pax_global_header00006660000000000000000000000064146441661730014526gustar00rootroot0000000000000052 comment=1c0d52ace3c237ca6276cafb5c73f699a75c1d40 optee_os-4.3.0/000077500000000000000000000000001464416617300133475ustar00rootroot00000000000000optee_os-4.3.0/.checkpatch.conf000066400000000000000000000004041464416617300163670ustar00rootroot00000000000000--codespell --no-tree --quiet --strict --max-line-length=80 --ignore=CAMELCASE --ignore=CONCATENATED_STRING --ignore=FILE_PATH_CHANGES --ignore=GERRIT_CHANGE_ID --ignore=NOT_UNIFIED_DIFF --ignore=PREFER_KERNEL_TYPES --ignore=USLEEP_RANGE --kconfig-prefix=CFG_ optee_os-4.3.0/.clang-format000066400000000000000000000103231464416617300157210ustar00rootroot00000000000000# SPDX-License-Identifier: GPL-2.0 # # clang-format configuration file. Intended for clang-format >= 11. # # This is not perfect, but should help in most cases. # Please note that the maintainers have the last word if there's # disagrement with this tool. # # For more information, see: # https://clang.llvm.org/docs/ClangFormat.html # https://clang.llvm.org/docs/ClangFormatStyleOptions.html # --- AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: false BinPackArguments: true BinPackParameters: true BraceWrapping: AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: true AfterNamespace: true AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Custom BreakBeforeInheritanceComma: false BreakBeforeTernaryOperators: false BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: false ColumnLimit: 80 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 Cpp11BracedListStyle: false DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: false # Taken from: # find lib core -name "*.h" -path '*/include/*' -print0 | xargs -0 grep -E -h \ # '^#define[[:blank:]]*[^[:blank:]]*(FOREACH|for_each)[^[:blank:]]' | \ # sed \ # -e "s,^#define[ \t]*\([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ # -e "s,^#define[ \t]*\([^[:space:]]*FOREACH[^[:space:]]*\)(.*$, - '\1'," | \ # LC_ALL=C sort -u ForEachMacros: - 'CIRCLEQ_FOREACH' - 'CIRCLEQ_FOREACH_REVERSE' - 'LIST_FOREACH' - 'LIST_FOREACH_SAFE' - 'SCATTERED_ARRAY_FOREACH' - 'SIMPLEQ_FOREACH' - 'SLIST_FOREACH' - 'SLIST_FOREACH_SAFE' - 'STAILQ_FOREACH' - 'STAILQ_FOREACH_SAFE' - 'TAILQ_FOREACH' - 'TAILQ_FOREACH_REVERSE' - 'TAILQ_FOREACH_REVERSE_SAFE' - 'TAILQ_FOREACH_SAFE' - 'fdt_for_each_property_offset' - 'fdt_for_each_subnode' - 'for_each_dt_driver' - 'for_each_early_ta' - 'for_each_fip_sp' - 'for_each_secure_partition' IncludeBlocks: Preserve IncludeCategories: - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false IndentGotoLabels: false IndentPPDirectives: None IndentWidth: 8 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 8 ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true # Taken from git's rules PenaltyBreakAssignment: 10 PenaltyBreakBeforeFirstCallParameter: 30 PenaltyBreakComment: 10 PenaltyBreakFirstLessLess: 0 PenaltyBreakString: 10 PenaltyExcessCharacter: 100 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Right ReflowComments: false SortIncludes: false SortUsingDeclarations: false SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatementsExceptForEachMacros SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: false SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp03 TabWidth: 8 UseTab: Always ... optee_os-4.3.0/CHANGELOG.md000066400000000000000000003001271464416617300151630ustar00rootroot00000000000000# OP-TEE - version 4.3.0 (2024-07-12) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_3_0], [commits][OP_TEE_optee_os_commits_4_3_0] and [pull requests][OP_TEE_optee_os_pr_4_3_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_3_0], [commits][OP_TEE_optee_client_commits_4_3_0] and [pull requests][OP_TEE_optee_client_pr_4_3_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_3_0], [commits][OP_TEE_optee_test_commits_4_3_0] and [pull requests][OP_TEE_optee_test_pr_4_3_0] - OP-TEE/build: [release page][OP_TEE_build_release_4_3_0], [commits][OP_TEE_build_commits_4_3_0] and [pull requests][OP_TEE_build_pr_4_3_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_3_0], [commits][linaro_swg_optee_examples_commits_4_3_0] and [pull requests][linaro_swg_optee_examples_pr_4_3_0] [OP_TEE_optee_os_release_4_3_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.3.0 [OP_TEE_optee_os_commits_4_3_0]: https://github.com/OP-TEE/optee_os/compare/4.2.0...4.3.0 [OP_TEE_optee_os_pr_4_3_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12 [OP_TEE_optee_client_release_4_3_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.3.0 [OP_TEE_optee_client_commits_4_3_0]: https://github.com/OP-TEE/optee_client/compare/4.2.0...4.3.0 [OP_TEE_optee_client_pr_4_3_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12 [OP_TEE_optee_test_release_4_3_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.3.0 [OP_TEE_optee_test_commits_4_3_0]: https://github.com/OP-TEE/optee_test/compare/4.2.0...4.3.0 [OP_TEE_optee_test_pr_4_3_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12 [OP_TEE_build_release_4_3_0]: https://github.com/OP-TEE/build/releases/tag/4.3.0 [OP_TEE_build_commits_4_3_0]: https://github.com/OP-TEE/build/compare/4.2.0...4.3.0 [OP_TEE_build_pr_4_3_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12 [linaro_swg_optee_examples_release_4_3_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.3.0 [linaro_swg_optee_examples_commits_4_3_0]: https://github.com/linaro-swg/optee_examples/compare/4.2.0...4.3.0 [linaro_swg_optee_examples_pr_4_3_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12 # OP-TEE - version 4.2.0 (2024-04-12) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_2_0], [commits][OP_TEE_optee_os_commits_4_2_0] and [pull requests][OP_TEE_optee_os_pr_4_2_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_2_0], [commits][OP_TEE_optee_client_commits_4_2_0] and [pull requests][OP_TEE_optee_client_pr_4_2_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_2_0], [commits][OP_TEE_optee_test_commits_4_2_0] and [pull requests][OP_TEE_optee_test_pr_4_2_0] - OP-TEE/build: [release page][OP_TEE_build_release_4_2_0], [commits][OP_TEE_build_commits_4_2_0] and [pull requests][OP_TEE_build_pr_4_2_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_2_0], [commits][linaro_swg_optee_examples_commits_4_2_0] and [pull requests][linaro_swg_optee_examples_pr_4_2_0] [OP_TEE_optee_os_release_4_2_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.2.0 [OP_TEE_optee_os_commits_4_2_0]: https://github.com/OP-TEE/optee_os/compare/4.1.0...4.2.0 [OP_TEE_optee_os_pr_4_2_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 [OP_TEE_optee_client_release_4_2_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.2.0 [OP_TEE_optee_client_commits_4_2_0]: https://github.com/OP-TEE/optee_client/compare/4.1.0...4.2.0 [OP_TEE_optee_client_pr_4_2_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 [OP_TEE_optee_test_release_4_2_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.2.0 [OP_TEE_optee_test_commits_4_2_0]: https://github.com/OP-TEE/optee_test/compare/4.1.0...4.2.0 [OP_TEE_optee_test_pr_4_2_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 [OP_TEE_build_release_4_2_0]: https://github.com/OP-TEE/build/releases/tag/4.2.0 [OP_TEE_build_commits_4_2_0]: https://github.com/OP-TEE/build/compare/4.1.0...4.2.0 [OP_TEE_build_pr_4_2_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 [linaro_swg_optee_examples_release_4_2_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.2.0 [linaro_swg_optee_examples_commits_4_2_0]: https://github.com/linaro-swg/optee_examples/compare/4.1.0...4.2.0 [linaro_swg_optee_examples_pr_4_2_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12 # OP-TEE - version 4.1.0 (2024-01-19) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_1], [commits][OP_TEE_optee_os_commits_4_1] and [pull requests][OP_TEE_optee_os_pr_4_1] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_1], [commits][OP_TEE_optee_client_commits_4_1] and [pull requests][OP_TEE_optee_client_pr_4_1] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_1], [commits][OP_TEE_optee_test_commits_4_1] and [pull requests][OP_TEE_optee_test_pr_4_1] - OP-TEE/build: [release page][OP_TEE_build_release_4_1], [commits][OP_TEE_build_commits_4_1] and [pull requests][OP_TEE_build_pr_4_1] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_1], [commits][linaro_swg_optee_examples_commits_4_1] and [pull requests][linaro_swg_optee_examples_pr_4_1] [OP_TEE_optee_os_release_4_1]: https://github.com/OP-TEE/optee_os/releases/tag/4.1.0 [OP_TEE_optee_os_commits_4_1]: https://github.com/OP-TEE/optee_os/compare/4.0.0...4.1.0 [OP_TEE_optee_os_pr_4_1]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 [OP_TEE_optee_client_release_4_1]: https://github.com/OP-TEE/optee_client/releases/tag/4.1.0 [OP_TEE_optee_client_commits_4_1]: https://github.com/OP-TEE/optee_client/compare/4.0.0...4.1.0 [OP_TEE_optee_client_pr_4_1]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 [OP_TEE_optee_test_release_4_1]: https://github.com/OP-TEE/optee_test/releases/tag/4.1.0 [OP_TEE_optee_test_commits_4_1]: https://github.com/OP-TEE/optee_test/compare/4.0.0...4.1.0 [OP_TEE_optee_test_pr_4_1]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 [OP_TEE_build_release_4_1]: https://github.com/OP-TEE/build/releases/tag/4.1.0 [OP_TEE_build_commits_4_1]: https://github.com/OP-TEE/build/compare/4.0.0...4.1.0 [OP_TEE_build_pr_4_1]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 [linaro_swg_optee_examples_release_4_1]: https://github.com/linaro-swg/optee_examples/releases/tag/4.1.0 [linaro_swg_optee_examples_commits_4_1]: https://github.com/linaro-swg/optee_examples/compare/4.0.0...4.1.0 [linaro_swg_optee_examples_pr_4_1]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-10-20..2024-01-19 # OP-TEE - version 4.0.0 (2023-10-20) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_0], [commits][OP_TEE_optee_os_commits_4_0] and [pull requests][OP_TEE_optee_os_pr_4_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_0], [commits][OP_TEE_optee_client_commits_4_0] and [pull requests][OP_TEE_optee_client_pr_4_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_0], [commits][OP_TEE_optee_test_commits_4_0] and [pull requests][OP_TEE_optee_test_pr_4_0] - OP-TEE/build: [release page][OP_TEE_build_release_4_0], [commits][OP_TEE_build_commits_4_0] and [pull requests][OP_TEE_build_pr_4_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_0], [commits][linaro_swg_optee_examples_commits_4_0] and [pull requests][linaro_swg_optee_examples_pr_4_0] [OP_TEE_optee_os_release_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.0.0 [OP_TEE_optee_os_commits_4_0]: https://github.com/OP-TEE/optee_os/compare/3.22.0...4.0.0 [OP_TEE_optee_os_pr_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [OP_TEE_optee_client_release_4_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.0.0 [OP_TEE_optee_client_commits_4_0]: https://github.com/OP-TEE/optee_client/compare/3.22.0...4.0.0 [OP_TEE_optee_client_pr_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [OP_TEE_optee_test_release_4_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.0.0 [OP_TEE_optee_test_commits_4_0]: https://github.com/OP-TEE/optee_test/compare/3.22.0...4.0.0 [OP_TEE_optee_test_pr_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [OP_TEE_build_release_4_0]: https://github.com/OP-TEE/build/releases/tag/4.0.0 [OP_TEE_build_commits_4_0]: https://github.com/OP-TEE/build/compare/3.22.0...4.0.0 [OP_TEE_build_pr_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 [linaro_swg_optee_examples_release_4_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.0.0 [linaro_swg_optee_examples_commits_4_0]: https://github.com/linaro-swg/optee_examples/compare/3.22.0...4.0.0 [linaro_swg_optee_examples_pr_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-07-07..2023-10-20 # OP-TEE - version 3.22.0 (2023-07-07) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_22], [commits][OP_TEE_optee_os_commits_3_22] and [pull requests][OP_TEE_optee_os_pr_3_22] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_22], [commits][OP_TEE_optee_client_commits_3_22] and [pull requests][OP_TEE_optee_client_pr_3_22] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_22], [commits][OP_TEE_optee_test_commits_3_22] and [pull requests][OP_TEE_optee_test_pr_3_22] - OP-TEE/build: [release page][OP_TEE_build_release_3_22], [commits][OP_TEE_build_commits_3_22] and [pull requests][OP_TEE_build_pr_3_22] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_22], [commits][linaro_swg_optee_examples_commits_3_22] and [pull requests][linaro_swg_optee_examples_pr_3_22] [OP_TEE_optee_os_release_3_22]: https://github.com/OP-TEE/optee_os/releases/tag/3.22.0 [OP_TEE_optee_os_commits_3_22]: https://github.com/OP-TEE/optee_os/compare/3.21.0...3.22.0 [OP_TEE_optee_os_pr_3_22]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 [OP_TEE_optee_client_release_3_22]: https://github.com/OP-TEE/optee_client/releases/tag/3.22.0 [OP_TEE_optee_client_commits_3_22]: https://github.com/OP-TEE/optee_client/compare/3.21.0...3.22.0 [OP_TEE_optee_client_pr_3_22]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 [OP_TEE_optee_test_release_3_22]: https://github.com/OP-TEE/optee_test/releases/tag/3.22.0 [OP_TEE_optee_test_commits_3_22]: https://github.com/OP-TEE/optee_test/compare/3.21.0...3.22.0 [OP_TEE_optee_test_pr_3_22]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 [OP_TEE_build_release_3_22]: https://github.com/OP-TEE/build/releases/tag/3.22.0 [OP_TEE_build_commits_3_22]: https://github.com/OP-TEE/build/compare/3.21.0...3.22.0 [OP_TEE_build_pr_3_22]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 [linaro_swg_optee_examples_release_3_22]: https://github.com/linaro-swg/optee_examples/releases/tag/3.22.0 [linaro_swg_optee_examples_commits_3_22]: https://github.com/linaro-swg/optee_examples/compare/3.21.0...3.22.0 [linaro_swg_optee_examples_pr_3_22]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-04-14..2023-07-07 # OP-TEE - version 3.21.0 (2023-04-14) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_21], [commits][OP_TEE_optee_os_commits_3_21] and [pull requests][OP_TEE_optee_os_pr_3_21] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_21], [commits][OP_TEE_optee_client_commits_3_21] and [pull requests][OP_TEE_optee_client_pr_3_21] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_21], [commits][OP_TEE_optee_test_commits_3_21] and [pull requests][OP_TEE_optee_test_pr_3_21] - OP-TEE/build: [release page][OP_TEE_build_release_3_21], [commits][OP_TEE_build_commits_3_21] and [pull requests][OP_TEE_build_pr_3_21] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_21], [commits][linaro_swg_optee_examples_commits_3_21] and [pull requests][linaro_swg_optee_examples_pr_3_21] [OP_TEE_optee_os_release_3_21]: https://github.com/OP-TEE/optee_os/releases/tag/3.21.0 [OP_TEE_optee_os_commits_3_21]: https://github.com/OP-TEE/optee_os/compare/3.20.0...3.21.0 [OP_TEE_optee_os_pr_3_21]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 [OP_TEE_optee_client_release_3_21]: https://github.com/OP-TEE/optee_client/releases/tag/3.21.0 [OP_TEE_optee_client_commits_3_21]: https://github.com/OP-TEE/optee_client/compare/3.20.0...3.21.0 [OP_TEE_optee_client_pr_3_21]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 [OP_TEE_optee_test_release_3_21]: https://github.com/OP-TEE/optee_test/releases/tag/3.21.0 [OP_TEE_optee_test_commits_3_21]: https://github.com/OP-TEE/optee_test/compare/3.20.0...3.21.0 [OP_TEE_optee_test_pr_3_21]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 [OP_TEE_build_release_3_21]: https://github.com/OP-TEE/build/releases/tag/3.21.0 [OP_TEE_build_commits_3_21]: https://github.com/OP-TEE/build/compare/3.20.0...3.21.0 [OP_TEE_build_pr_3_21]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 [linaro_swg_optee_examples_release_3_21]: https://github.com/linaro-swg/optee_examples/releases/tag/3.21.0 [linaro_swg_optee_examples_commits_3_21]: https://github.com/linaro-swg/optee_examples/compare/3.20.0...3.21.0 [linaro_swg_optee_examples_pr_3_21]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2023-01-20..2023-04-14 # OP-TEE - version 3.20.0 (2023-01-20) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_20], [commits][OP_TEE_optee_os_commits_3_20] and [pull requests][OP_TEE_optee_os_pr_3_20] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_20], [commits][OP_TEE_optee_client_commits_3_20] and [pull requests][OP_TEE_optee_client_pr_3_20] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_20], [commits][OP_TEE_optee_test_commits_3_20] and [pull requests][OP_TEE_optee_test_pr_3_20] - OP-TEE/build: [release page][OP_TEE_build_release_3_20], [commits][OP_TEE_build_commits_3_20] and [pull requests][OP_TEE_build_pr_3_20] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_20], [commits][linaro_swg_optee_examples_commits_3_20] and [pull requests][linaro_swg_optee_examples_pr_3_20] [OP_TEE_optee_os_release_3_20]: https://github.com/OP-TEE/optee_os/releases/tag/3.20.0 [OP_TEE_optee_os_commits_3_20]: https://github.com/OP-TEE/optee_os/compare/3.19.0...3.20.0 [OP_TEE_optee_os_pr_3_20]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 [OP_TEE_optee_client_release_3_20]: https://github.com/OP-TEE/optee_client/releases/tag/3.20.0 [OP_TEE_optee_client_commits_3_20]: https://github.com/OP-TEE/optee_client/compare/3.19.0...3.20.0 [OP_TEE_optee_client_pr_3_20]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 [OP_TEE_optee_test_release_3_20]: https://github.com/OP-TEE/optee_test/releases/tag/3.20.0 [OP_TEE_optee_test_commits_3_20]: https://github.com/OP-TEE/optee_test/compare/3.19.0...3.20.0 [OP_TEE_optee_test_pr_3_20]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 [OP_TEE_build_release_3_20]: https://github.com/OP-TEE/build/releases/tag/3.20.0 [OP_TEE_build_commits_3_20]: https://github.com/OP-TEE/build/compare/3.19.0...3.20.0 [OP_TEE_build_pr_3_20]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 [linaro_swg_optee_examples_release_3_20]: https://github.com/linaro-swg/optee_examples/releases/tag/3.20.0 [linaro_swg_optee_examples_commits_3_20]: https://github.com/linaro-swg/optee_examples/compare/3.19.0...3.20.0 [linaro_swg_optee_examples_pr_3_20]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-10-14..2023-01-20 # OP-TEE - version 3.19.0 (2022-10-14) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_19], [commits][OP_TEE_optee_os_commits_3_19] and [ pull requests][OP_TEE_optee_os_pr_3_19] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_19], [commits][OP_TEE_optee_client_commits_3_19] and [pull requests][OP_TEE_optee_client_pr_3_19] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_19], [commits][OP_TEE_optee_test_commits_3_19] and [pull requests][OP_TEE_optee_test_pr_3_19] - OP-TEE/build: [release page][OP_TEE_build_release_3_19], [commits][OP_TEE_build_commits_3_19] and [pull requests][OP_TEE_build_pr_3_19] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_19], [commits][linaro_swg_optee_examples_commits_3_19] and [pull requests][linaro_swg_optee_examples_pr_3_19] [OP_TEE_optee_os_release_3_19]: https://github.com/OP-TEE/optee_os/releases/tag/3.19.0 [OP_TEE_optee_os_commits_3_19]: https://github.com/OP-TEE/optee_os/compare/3.18.0...3.19.0 [OP_TEE_optee_os_pr_3_19]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 [OP_TEE_optee_client_release_3_19]: https://github.com/OP-TEE/optee_client/releases/tag/3.19.0 [OP_TEE_optee_client_commits_3_19]: https://github.com/OP-TEE/optee_client/compare/3.18.0...3.19.0 [OP_TEE_optee_client_pr_3_19]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 [OP_TEE_optee_test_release_3_19]: https://github.com/OP-TEE/optee_test/releases/tag/3.19.0 [OP_TEE_optee_test_commits_3_19]: https://github.com/OP-TEE/optee_test/compare/3.18.0...3.19.0 [OP_TEE_optee_test_pr_3_19]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 [OP_TEE_build_release_3_19]: https://github.com/OP-TEE/build/releases/tag/3.19.0 [OP_TEE_build_commits_3_19]: https://github.com/OP-TEE/build/compare/3.18.0...3.19.0 [OP_TEE_build_pr_3_19]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 [linaro_swg_optee_examples_release_3_19]: https://github.com/linaro-swg/optee_examples/releases/tag/3.19.0 [linaro_swg_optee_examples_commits_3_19]: https://github.com/linaro-swg/optee_examples/compare/3.18.0...3.19.0 [linaro_swg_optee_examples_pr_3_19]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-07-15..2022-10-14 # OP-TEE - version 3.18.0 (2022-07-15) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_18_0], [commits][OP_TEE_optee_os_commits_3_18_0] and [pull requests][OP_TEE_optee_os_pr_3_18_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_18_0], [commits][OP_TEE_optee_client_commits_3_18_0] and [pull requests][OP_TEE_optee_client_pr_3_18_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_18_0], [commits][OP_TEE_optee_test_commits_3_18_0] and [pull requests][OP_TEE_optee_test_pr_3_18_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_18_0], [commits][OP_TEE_build_commits_3_18_0] and [pull requests][OP_TEE_build_pr_3_18_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_18_0], [commits][linaro_swg_optee_examples_commits_3_18_0] and [pull requests][linaro_swg_optee_examples_pr_3_18_0] [OP_TEE_optee_os_release_3_18_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.18.0 [OP_TEE_optee_os_commits_3_18_0]: https://github.com/OP-TEE/optee_os/compare/3.17.0...3.18.0 [OP_TEE_optee_os_pr_3_18_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 [OP_TEE_optee_client_release_3_18_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.18.0 [OP_TEE_optee_client_commits_3_18_0]: https://github.com/OP-TEE/optee_client/compare/3.17.0...3.18.0 [OP_TEE_optee_client_pr_3_18_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 [OP_TEE_optee_test_release_3_18_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.18.0 [OP_TEE_optee_test_commits_3_18_0]: https://github.com/OP-TEE/optee_test/compare/3.17.0...3.18.0 [OP_TEE_optee_test_pr_3_18_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 [OP_TEE_build_release_3_18_0]: https://github.com/OP-TEE/build/releases/tag/3.18.0 [OP_TEE_build_commits_3_18_0]: https://github.com/OP-TEE/build/compare/3.17.0...3.18.0 [OP_TEE_build_pr_3_18_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 [linaro_swg_optee_examples_release_3_18_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.18.0 [linaro_swg_optee_examples_commits_3_18_0]: https://github.com/linaro-swg/optee_examples/compare/3.17.0...3.18.0 [linaro_swg_optee_examples_pr_3_18_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-04-15..2022-07-15 # OP-TEE - version 3.17.0 (2022-04-15) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_17_0], [commits][OP_TEE_optee_os_commits_3_17_0] and [pull requests][OP_TEE_optee_os_pr_3_17_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_17_0], [commits][OP_TEE_optee_client_commits_3_17_0] and [pull requests][OP_TEE_optee_client_pr_3_17_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_17_0], [commits][OP_TEE_optee_test_commits_3_17_0] and [pull requests][OP_TEE_optee_test_pr_3_17_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_17_0], [commits][OP_TEE_build_commits_3_17_0] and [pull requests][OP_TEE_build_pr_3_17_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_17_0], [commits][linaro_swg_optee_examples_commits_3_17_0] and [pull requests][linaro_swg_optee_examples_pr_3_17_0] [OP_TEE_optee_os_release_3_17_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.17.0 [OP_TEE_optee_os_commits_3_17_0]: https://github.com/OP-TEE/optee_os/compare/3.16.0...3.17.0 [OP_TEE_optee_os_pr_3_17_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-28..2022-04-15 [OP_TEE_optee_client_release_3_17_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.17.0 [OP_TEE_optee_client_commits_3_17_0]: https://github.com/OP-TEE/optee_client/compare/3.16.0...3.17.0 [OP_TEE_optee_client_pr_3_17_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-01-28..2022-04-15 [OP_TEE_optee_test_release_3_17_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.17.0 [OP_TEE_optee_test_commits_3_17_0]: https://github.com/OP-TEE/optee_test/compare/3.16.0...3.17.0 [OP_TEE_optee_test_pr_3_17_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-01-28..2022-04-15 [OP_TEE_build_release_3_17_0]: https://github.com/OP-TEE/build/releases/tag/3.17.0 [OP_TEE_build_commits_3_17_0]: https://github.com/OP-TEE/build/compare/3.16.0...3.17.0 [OP_TEE_build_pr_3_17_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-28..2022-04-15 [linaro_swg_optee_examples_release_3_17_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.17.0 [linaro_swg_optee_examples_commits_3_17_0]: https://github.com/linaro-swg/optee_examples/compare/3.16.0...3.17.0 [linaro_swg_optee_examples_pr_3_17_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2022-01-28..2022-04-15 # OP-TEE - version 3.16.0 (2022-01-28) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_16_0], [commits][OP_TEE_optee_os_commits_3_16_0] and [pull requests][OP_TEE_optee_os_pr_3_16_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_16_0], [commits][OP_TEE_optee_client_commits_3_16_0] and [pull requests][OP_TEE_optee_client_pr_3_16_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_16_0], [commits][OP_TEE_optee_test_commits_3_16_0] and [pull requests][OP_TEE_optee_test_pr_3_16_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_16_0], [commits][OP_TEE_build_commits_3_16_0] and [pull requests][OP_TEE_build_pr_3_16_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_16_0], [commits][linaro_swg_optee_examples_commits_3_16_0] and [pull requests][linaro_swg_optee_examples_pr_3_16_0] [OP_TEE_optee_os_release_3_16_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.16.0 [OP_TEE_optee_os_commits_3_16_0]: https://github.com/OP-TEE/optee_os/compare/3.15.0...3.16.0 [OP_TEE_optee_os_pr_3_16_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 [OP_TEE_optee_client_release_3_16_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.16.0 [OP_TEE_optee_client_commits_3_16_0]: https://github.com/OP-TEE/optee_client/compare/3.15.0...3.16.0 [OP_TEE_optee_client_pr_3_16_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 [OP_TEE_optee_test_release_3_16_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.16.0 [OP_TEE_optee_test_commits_3_16_0]: https://github.com/OP-TEE/optee_test/compare/3.15.0...3.16.0 [OP_TEE_optee_test_pr_3_16_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 [OP_TEE_build_release_3_16_0]: https://github.com/OP-TEE/build/releases/tag/3.16.0 [OP_TEE_build_commits_3_16_0]: https://github.com/OP-TEE/build/compare/3.15.0...3.16.0 [OP_TEE_build_pr_3_16_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 [linaro_swg_optee_examples_release_3_16_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.16.0 [linaro_swg_optee_examples_commits_3_16_0]: https://github.com/linaro-swg/optee_examples/compare/3.15.0...3.16.0 [linaro_swg_optee_examples_pr_3_16_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-10-18..2022-01-28 # OP-TEE - version 3.15.0 (2021-10-18) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_15_0], [commits][OP_TEE_optee_os_commits_3_15_0] and [pull requests][OP_TEE_optee_os_pr_3_15_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_15_0], [commits][OP_TEE_optee_client_commits_3_15_0] and [pull requests][OP_TEE_optee_client_pr_3_15_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_15_0], [commits][OP_TEE_optee_test_commits_3_15_0] and [pull requests][OP_TEE_optee_test_pr_3_15_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_15_0], [commits][OP_TEE_build_commits_3_15_0] and [pull requests][OP_TEE_build_pr_3_15_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_15_0], [commits][linaro_swg_optee_examples_commits_3_15_0] and [pull requests][linaro_swg_optee_examples_pr_3_15_0] [OP_TEE_optee_os_release_3_15_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.15.0 [OP_TEE_optee_os_commits_3_15_0]: https://github.com/OP-TEE/optee_os/compare/3.14.0...3.15.0 [OP_TEE_optee_os_pr_3_15_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 [OP_TEE_optee_client_release_3_15_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.15.0 [OP_TEE_optee_client_commits_3_15_0]: https://github.com/OP-TEE/optee_client/compare/3.14.0...3.15.0 [OP_TEE_optee_client_pr_3_15_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 [OP_TEE_optee_test_release_3_15_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.15.0 [OP_TEE_optee_test_commits_3_15_0]: https://github.com/OP-TEE/optee_test/compare/3.14.0...3.15.0 [OP_TEE_optee_test_pr_3_15_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 [OP_TEE_build_release_3_15_0]: https://github.com/OP-TEE/build/releases/tag/3.15.0 [OP_TEE_build_commits_3_15_0]: https://github.com/OP-TEE/build/compare/3.14.0...3.15.0 [OP_TEE_build_pr_3_15_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 [linaro_swg_optee_examples_release_3_15_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.15.0 [linaro_swg_optee_examples_commits_3_15_0]: https://github.com/linaro-swg/optee_examples/compare/3.14.0...3.15.0 [linaro_swg_optee_examples_pr_3_15_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-07-16..2021-10-18 # OP-TEE - version 3.14.0 (target date: 2021-07-16) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_14_0], [commits][OP_TEE_optee_os_commits_3_14_0] and [pull requests][OP_TEE_optee_os_pr_3_14_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_14_0], [commits][OP_TEE_optee_client_commits_3_14_0] and [pull requests][OP_TEE_optee_client_pr_3_14_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_14_0], [commits][OP_TEE_optee_test_commits_3_14_0] and [pull requests][OP_TEE_optee_test_pr_3_14_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_14_0], [commits][OP_TEE_build_commits_3_14_0] and [pull requests][OP_TEE_build_pr_3_14_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_14_0], [commits][linaro_swg_optee_examples_commits_3_14_0] and [pull requests][linaro_swg_optee_examples_pr_3_14_0] [OP_TEE_optee_os_release_3_14_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.14.0 [OP_TEE_optee_os_commits_3_14_0]: https://github.com/OP-TEE/optee_os/compare/3.13.0...3.14.0 [OP_TEE_optee_os_pr_3_14_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 [OP_TEE_optee_client_release_3_14_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.14.0 [OP_TEE_optee_client_commits_3_14_0]: https://github.com/OP-TEE/optee_client/compare/3.13.0...3.14.0 [OP_TEE_optee_client_pr_3_14_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01-..2021-07-16 [OP_TEE_optee_test_release_3_14_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.14.0 [OP_TEE_optee_test_commits_3_14_0]: https://github.com/OP-TEE/optee_test/compare/3.13.0...3.14.0 [OP_TEE_optee_test_pr_3_14_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 [OP_TEE_build_release_3_14_0]: https://github.com/OP-TEE/build/releases/tag/3.14.0 [OP_TEE_build_commits_3_14_0]: https://github.com/OP-TEE/build/compare/3.13.0...3.14.0 [OP_TEE_build_pr_3_14_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 [linaro_swg_optee_examples_release_3_14_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.14.0 [linaro_swg_optee_examples_commits_3_14_0]: https://github.com/linaro-swg/optee_examples/compare/3.13.0...3.14.0 [linaro_swg_optee_examples_pr_3_14_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-05-01..2021-07-16 # OP-TEE - version 3.13.0 (2021-04-30) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_13_0], [commits][OP_TEE_optee_os_commits_3_13_0] and [pull requests][OP_TEE_optee_os_pr_3_13_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_13_0], [commits][OP_TEE_optee_client_commits_3_13_0] and [pull requests][OP_TEE_optee_client_pr_3_13_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_13_0], [commits][OP_TEE_optee_test_commits_3_13_0] and [pull requests][OP_TEE_optee_test_pr_3_13_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_13_0], [commits][OP_TEE_build_commits_3_13_0] and [pull requests][OP_TEE_build_pr_3_13_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_13_0], [commits][linaro_swg_optee_examples_commits_3_13_0] and [pull requests][linaro_swg_optee_examples_pr_3_13_0] [OP_TEE_optee_os_release_3_13_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.13.0 [OP_TEE_optee_os_commits_3_13_0]: https://github.com/OP-TEE/optee_os/compare/3.12.0...3.13.0 [OP_TEE_optee_os_pr_3_13_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 [OP_TEE_optee_client_release_3_13_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.13.0 [OP_TEE_optee_client_commits_3_13_0]: https://github.com/OP-TEE/optee_client/compare/3.12.0...3.13.0 [OP_TEE_optee_client_pr_3_13_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 [OP_TEE_optee_test_release_3_13_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.13.0 [OP_TEE_optee_test_commits_3_13_0]: https://github.com/OP-TEE/optee_test/compare/3.12.0...3.13.0 [OP_TEE_optee_test_pr_3_13_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 [OP_TEE_build_release_3_13_0]: https://github.com/OP-TEE/build/releases/tag/3.13.0 [OP_TEE_build_commits_3_13_0]: https://github.com/OP-TEE/build/compare/3.12.0...3.13.0 [OP_TEE_build_pr_3_13_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 [linaro_swg_optee_examples_release_3_13_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.13.0 [linaro_swg_optee_examples_commits_3_13_0]: https://github.com/linaro-swg/optee_examples/compare/3.12.0...3.13.0 [linaro_swg_optee_examples_pr_3_13_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2021-01-20..2021-04-30 # OP-TEE - version 3.12.0 (2021-01-20) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_12_0], [commits][OP_TEE_optee_os_commits_3_12_0] and [pull requests][OP_TEE_optee_os_pr_3_12_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_12_0], [commits][OP_TEE_optee_client_commits_3_12_0] and [pull requests][OP_TEE_optee_client_pr_3_12_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_12_0], [commits][OP_TEE_optee_test_commits_3_12_0] and [pull requests][OP_TEE_optee_test_pr_3_12_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_12_0], [commits][OP_TEE_build_commits_3_12_0] and [pull requests][OP_TEE_build_pr_3_12_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_12_0], [commits][linaro_swg_optee_examples_commits_3_12_0] and [pull requests][linaro_swg_optee_examples_pr_3_12_0] [OP_TEE_optee_os_release_3_12_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.12.0 [OP_TEE_optee_os_commits_3_12_0]: https://github.com/OP-TEE/optee_os/compare/3.11.0...3.12.0 [OP_TEE_optee_os_pr_3_12_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 [OP_TEE_optee_client_release_3_12_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.12.0 [OP_TEE_optee_client_commits_3_12_0]: https://github.com/OP-TEE/optee_client/compare/3.11.0...3.12.0 [OP_TEE_optee_client_pr_3_12_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 [OP_TEE_optee_test_release_3_12_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.12.0 [OP_TEE_optee_test_commits_3_12_0]: https://github.com/OP-TEE/optee_test/compare/3.11.0...3.12.0 [OP_TEE_optee_test_pr_3_12_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 [OP_TEE_build_release_3_12_0]: https://github.com/OP-TEE/build/releases/tag/3.12.0 [OP_TEE_build_commits_3_12_0]: https://github.com/OP-TEE/build/compare/3.11.0...3.12.0 [OP_TEE_build_pr_3_12_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 [linaro_swg_optee_examples_release_3_12_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.12.0 [linaro_swg_optee_examples_commits_3_12_0]: https://github.com/linaro-swg/optee_examples/compare/3.11.0...3.12.0 [linaro_swg_optee_examples_pr_3_12_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-10-16..2021-01-20 # OP-TEE - version 3.11.0 (2020-10-16) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_11_0], [commits][OP_TEE_optee_os_commits_3_11_0] and [pull requests][OP_TEE_optee_os_pr_3_11_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_11_0], [commits][OP_TEE_optee_client_commits_3_11_0] and [pull requests][OP_TEE_optee_client_pr_3_11_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_11_0], [commits][OP_TEE_optee_test_commits_3_11_0] and [pull requests][OP_TEE_optee_test_pr_3_11_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_11_0], [commits][OP_TEE_build_commits_3_11_0] and [pull requests][OP_TEE_build_pr_3_11_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_11_0], [commits][linaro_swg_optee_examples_commits_3_11_0] and [pull requests][linaro_swg_optee_examples_pr_3_11_0] [OP_TEE_optee_os_release_3_11_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.11.0 [OP_TEE_optee_os_commits_3_11_0]: https://github.com/OP-TEE/optee_os/compare/3.10.0...3.11.0 [OP_TEE_optee_os_pr_3_11_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 [OP_TEE_optee_client_release_3_11_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.11.0 [OP_TEE_optee_client_commits_3_11_0]: https://github.com/OP-TEE/optee_client/compare/3.10.0...3.11.0 [OP_TEE_optee_client_pr_3_11_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 [OP_TEE_optee_test_release_3_11_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.11.0 [OP_TEE_optee_test_commits_3_11_0]: https://github.com/OP-TEE/optee_test/compare/3.10.0...3.11.0 [OP_TEE_optee_test_pr_3_11_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 [OP_TEE_build_release_3_11_0]: https://github.com/OP-TEE/build/releases/tag/3.11.0 [OP_TEE_build_commits_3_11_0]: https://github.com/OP-TEE/build/compare/3.10.0...3.11.0 [OP_TEE_build_pr_3_11_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 [linaro_swg_optee_examples_release_3_11_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.11.0 [linaro_swg_optee_examples_commits_3_11_0]: https://github.com/linaro-swg/optee_examples/compare/3.10.0...3.11.0 [linaro_swg_optee_examples_pr_3_11_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-08-21..2020-10-16 # OP-TEE - version 3.10.0 (2020-08-21) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_10_0], [commits][OP_TEE_optee_os_commits_3_10_0] and [pull requests][OP_TEE_optee_os_pr_3_10_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_10_0], [commits][OP_TEE_optee_client_commits_3_10_0] and [pull requests][OP_TEE_optee_client_pr_3_10_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_10_0], [commits][OP_TEE_optee_test_commits_3_10_0] and [pull requests][OP_TEE_optee_test_pr_3_10_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_10_0], [commits][OP_TEE_build_commits_3_10_0] and [pull requests][OP_TEE_build_pr_3_10_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_10_0], [commits][linaro_swg_optee_examples_commits_3_10_0] and [pull requests][linaro_swg_optee_examples_pr_3_10_0] [OP_TEE_optee_os_release_3_10_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.10.0 [OP_TEE_optee_os_commits_3_10_0]: https://github.com/OP-TEE/optee_os/compare/3.9.0...3.10.0 [OP_TEE_optee_os_pr_3_10_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 [OP_TEE_optee_client_release_3_10_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.10.0 [OP_TEE_optee_client_commits_3_10_0]: https://github.com/OP-TEE/optee_client/compare/3.9.0...3.10.0 [OP_TEE_optee_client_pr_3_10_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 [OP_TEE_optee_test_release_3_10_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.10.0 [OP_TEE_optee_test_commits_3_10_0]: https://github.com/OP-TEE/optee_test/compare/3.9.0...3.10.0 [OP_TEE_optee_test_pr_3_10_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 [OP_TEE_build_release_3_10_0]: https://github.com/OP-TEE/build/releases/tag/3.10.0 [OP_TEE_build_commits_3_10_0]: https://github.com/OP-TEE/build/compare/3.9.0...3.10.0 [OP_TEE_build_pr_3_10_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 [linaro_swg_optee_examples_release_3_10_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.10.0 [linaro_swg_optee_examples_commits_3_10_0]: https://github.com/linaro-swg/optee_examples/compare/3.9.0...3.10.0 [linaro_swg_optee_examples_pr_3_10_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-04-22..2020-08-21 # OP-TEE - version 3.9.0 (2020-04-22) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_9_0], [commits][OP_TEE_optee_os_commits_3_9_0] and [pull requests][OP_TEE_optee_os_pr_3_9_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_9_0], [commits][OP_TEE_optee_client_commits_3_9_0] and [pull requests][OP_TEE_optee_client_pr_3_9_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_9_0], [commits][OP_TEE_optee_test_commits_3_9_0] and [pull requests][OP_TEE_optee_test_pr_3_9_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_9_0], [commits][OP_TEE_build_commits_3_9_0] and [pull requests][OP_TEE_build_pr_3_9_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_9_0], [commits][linaro_swg_optee_examples_commits_3_9_0] and [pull requests][linaro_swg_optee_examples_pr_3_9_0] [OP_TEE_optee_os_release_3_9_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.9.0 [OP_TEE_optee_os_commits_3_9_0]: https://github.com/OP-TEE/optee_os/compare/3.8.0...3.9.0 [OP_TEE_optee_os_pr_3_9_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 [OP_TEE_optee_client_release_3_9_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.9.0 [OP_TEE_optee_client_commits_3_9_0]: https://github.com/OP-TEE/optee_client/compare/3.8.0...3.9.0 [OP_TEE_optee_client_pr_3_9_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 [OP_TEE_optee_test_release_3_9_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.9.0 [OP_TEE_optee_test_commits_3_9_0]: https://github.com/OP-TEE/optee_test/compare/3.8.0...3.9.0 [OP_TEE_optee_test_pr_3_9_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 [OP_TEE_build_release_3_9_0]: https://github.com/OP-TEE/build/releases/tag/3.9.0 [OP_TEE_build_commits_3_9_0]: https://github.com/OP-TEE/build/compare/3.8.0...3.9.0 [OP_TEE_build_pr_3_9_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 [linaro_swg_optee_examples_release_3_9_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.9.0 [linaro_swg_optee_examples_commits_3_9_0]: https://github.com/linaro-swg/optee_examples/compare/3.8.0...3.9.0 [linaro_swg_optee_examples_pr_3_9_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-05-22 # OP-TEE - version 3.8.0 (2020-01-24) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_8_0], [commits][OP_TEE_optee_os_commits_3_8_0] and [pull requests][OP_TEE_optee_os_pr_3_8_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_8_0], [commits][OP_TEE_optee_client_commits_3_8_0] and [pull requests][OP_TEE_optee_client_pr_3_8_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_8_0], [commits][OP_TEE_optee_test_commits_3_8_0] and [pull requests][OP_TEE_optee_test_pr_3_8_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_8_0], [commits][OP_TEE_build_commits_3_8_0] and [pull requests][OP_TEE_build_pr_3_8_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_8_0], [commits][linaro_swg_optee_examples_commits_3_8_0] and [pull requests][linaro_swg_optee_examples_pr_3_8_0] [OP_TEE_optee_os_release_3_8_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.8.0 [OP_TEE_optee_os_commits_3_8_0]: https://github.com/OP-TEE/optee_os/compare/3.7.0...3.8.0 [OP_TEE_optee_os_pr_3_8_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2020-01-24..2020-01-24 [OP_TEE_optee_client_release_3_8_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.8.0 [OP_TEE_optee_client_commits_3_8_0]: https://github.com/OP-TEE/optee_client/compare/3.7.0...3.8.0 [OP_TEE_optee_client_pr_3_8_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 [OP_TEE_optee_test_release_3_8_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.8.0 [OP_TEE_optee_test_commits_3_8_0]: https://github.com/OP-TEE/optee_test/compare/3.7.0...3.8.0 [OP_TEE_optee_test_pr_3_8_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 [OP_TEE_build_release_3_8_0]: https://github.com/OP-TEE/build/releases/tag/3.8.0 [OP_TEE_build_commits_3_8_0]: https://github.com/OP-TEE/build/compare/3.7.0...3.8.0 [OP_TEE_build_pr_3_8_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 [linaro_swg_optee_examples_release_3_8_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.8.0 [linaro_swg_optee_examples_commits_3_8_0]: https://github.com/linaro-swg/optee_examples/compare/3.7.0...3.8.0 [linaro_swg_optee_examples_pr_3_8_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2020-01-24 # OP-TEE - version 3.7.0 (2019-10-18) - Links to the release pages, commits and pull requests merged into this release for: - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_3_7_0], [commits][OP_TEE_optee_os_commits_3_7_0] and [pull requests][OP_TEE_optee_os_pr_3_7_0] - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_3_7_0], [commits][OP_TEE_optee_client_commits_3_7_0] and [pull requests][OP_TEE_optee_client_pr_3_7_0] - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_3_7_0], [commits][OP_TEE_optee_test_commits_3_7_0] and [pull requests][OP_TEE_optee_test_pr_3_7_0] - OP-TEE/build: [release page][OP_TEE_build_release_3_7_0], [commits][OP_TEE_build_commits_3_7_0] and [pull requests][OP_TEE_build_pr_3_7_0] - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_3_7_0], [commits][linaro_swg_optee_examples_commits_3_7_0] and [pull requests][linaro_swg_optee_examples_pr_3_7_0] [OP_TEE_optee_os_release_3_7_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.7.0 [OP_TEE_optee_os_commits_3_7_0]: https://github.com/OP-TEE/optee_os/compare/3.6.0...3.7.0 [OP_TEE_optee_os_pr_3_7_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 [OP_TEE_optee_client_release_3_7_0]: https://github.com/OP-TEE/optee_client/releases/tag/3.7.0 [OP_TEE_optee_client_commits_3_7_0]: https://github.com/OP-TEE/optee_client/compare/3.6.0...3.7.0 [OP_TEE_optee_client_pr_3_7_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 [OP_TEE_optee_test_release_3_7_0]: https://github.com/OP-TEE/optee_test/releases/tag/3.7.0 [OP_TEE_optee_test_commits_3_7_0]: https://github.com/OP-TEE/optee_test/compare/3.6.0...3.7.0 [OP_TEE_optee_test_pr_3_7_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 [OP_TEE_build_release_3_7_0]: https://github.com/OP-TEE/build/releases/tag/3.7.0 [OP_TEE_build_commits_3_7_0]: https://github.com/OP-TEE/build/compare/3.6.0...3.7.0 [OP_TEE_build_pr_3_7_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 [linaro_swg_optee_examples_release_3_7_0]: https://github.com/linaro-swg/optee_examples/releases/tag/3.7.0 [linaro_swg_optee_examples_commits_3_7_0]: https://github.com/linaro-swg/optee_examples/compare/3.6.0...3.7.0 [linaro_swg_optee_examples_pr_3_7_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-07-05..2019-10-18 # OP-TEE - version 3.6.0 (2019-07-05) - Link to the GitHub [release page][github_release_3_6_0]. - Links to the [commits][github_commits_3_6_0] and [pull requests][github_pr_3_6_0] merged into this release. [github_release_3_6_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.6.0 [github_commits_3_6_0]: https://github.com/OP-TEE/optee_os/compare/3.5.0...3.6.0 [github_pr_3_6_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-04-26..2019-07-05 # OP-TEE - version 3.5.0 (2019-04-26) - Link to the GitHub [release page][github_release_3_5_0]. - Links to the [commits][github_commits_3_5_0] and [pull requests][github_pr_3_5_0] merged into this release. [github_release_3_5_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.5.0 [github_commits_3_5_0]: https://github.com/OP-TEE/optee_os/compare/3.4.0...3.5.0 [github_pr_3_5_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2019-01-26..2019-04-26 # OP-TEE - version 3.4.0 (2019-01-25) - Link to the GitHub [release page][github_release_3_4_0]. - Links to the [commits][github_commits_3_4_0] and [pull requests][github_pr_3_4_0] merged into this release. [github_release_3_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.4.0 [github_commits_3_4_0]: https://github.com/OP-TEE/optee_os/compare/3.3.0...3.4.0 [github_pr_3_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-10-12..2019-01-25 # OP-TEE - version 3.3.0 (2018-10-12) - Link to the GitHub [release page][github_release_3_3_0]. - Links to the [commits][github_commits_3_3_0] and [pull requests][github_pr_3_3_0] merged into this release. [github_release_3_3_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.3.0 [github_commits_3_3_0]: https://github.com/OP-TEE/optee_os/compare/3.2.0...3.3.0 [github_pr_3_3_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-07-04..2018-10-12 # OP-TEE - version 3.2.0 (2018-07-04) - Link to the GitHub [release page][github_release_3_2_0]. - Links to the [commits][github_commits_3_2_0] and [pull requests][github_pr_3_2_0] merged into this release. ## Known issues * HiKey960: assertion in bget create_free_block() \[memalign() self-test\] ([#2414]) * D02: assertion '!have_spinlock()' ([#2437]) [github_commits_3_2_0]: https://github.com/OP-TEE/optee_os/compare/3.1.0...3.2.0 [github_pr_3_2_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-04-13..2018-07-04 [github_release_3_2_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.2.0 [#2414]: https://github.com/OP-TEE/optee_os/issues/2414 [#2437]: https://github.com/OP-TEE/optee_os/issues/2437 # OP-TEE - version 3.1.0 (2018-04-13) - Link to the GitHub [release page][github_release_3_1_0]. - Links to the [commits][github_commits_3_1_0] and [pull requests][github_pr_3_1_0] merged into this release. [github_commits_3_1_0]: https://github.com/OP-TEE/optee_os/compare/3.0.0...3.1.0 [github_pr_3_1_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2018-01-26..2018-04-13 [github_release_3_1_0]: https://github.com/OP-TEE/optee_os/releases/tag/3.1.0 # OP-TEE - version 3.0.0 (2018-01-26) [Link][github_commits_3_0_0] to a list of all commits between this release and the previous one (2.6.0). About backwards compatibility: Trusted Applications built with OP-TEE 2.5.0 or earlier will not run properly with a *debug* build of this release due to commit [0e1c6e8e][commit_0e1c6e8e] ("Dump call stack on TA panic"). Non-debug builds are not affected. ## New features * New supported platforms: Armada 3700 ([#1946]), Poplar ([#1999]), 64-bit support for FSL ls1012ardb ([#1941]), i.MX6SX Sabreauto ([#1974]). * arm32: sm: init CNTVOFF ([#2052]) * Debug/info/error traces: make output more compact ([#2011]) * tzc380: implement new functions ([#1994]) * Secure Data Path: add pseudo-TA to convert VA to PA (#1993]) * Pager: use NEON AES GCM implementation ([#1959]) * Crypto: add optimized AES GCM implementation using NEON ([#1949]) * Add support for using secure storage for TA anti-rollback ([#1928]) * Crypto: replace struct crypto_ops with function interface ([#1923], [#1931]) * aosp_optee.mk: define OPTEE_BIN ([#1922]) * Add build option to allow concurrent execution of single-instance TAs ([#1915]) * Pager: support for address sanitizer ([#1856]) * Pager: make memory between CFG_TEE_RAM_START and TEE load address usable by pager ([#1826]) ## Bug fixes * Fix crash in tee_mmu_final() on TA loading error ([#2092]) * LibTomCrypt: fix issue causing invalid output when using AES CTR with hardware acceleration (CFG_CRYPTO_WITH_CE) ([#2086]) * pl310: fix cache sync ([#2035]) * tzc380: do not write reserved bits ([#1994]) * Fix potential double free in ta_open() ([#1970]) * libfdt: fix undefined behaviour in fdt_offset_ptr() ([#1969]) * imx_wdog: fix register access ([#1966]) * Secure storage: fix potential memory leak after early return ([#1961]) * LibTomCrypt: fix double free in dsa_import() ([#1963]) * RPMB: fix TA independance issue in secure storage ([#1921]) * RPMB: return TEE_ERROR_ACCESS_CONFLICT instead of panicking when a TA attempts to create an existing persistent object without the overwrite flag ([#1919]) * PSCI: pass non-secure context to psci_system_suspend() ([#1916]) * Fix "Argument list too long" during "make clean" ([#1897]) ## Security fixes * Mitigations and hardening against the Spectre and Meltdown vulnerabilities (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754). ## Known issues * Secure storage (REE FS): storage size not updated after TEE_TruncateObjectData() ([#2094]) * Possible deadlock with CFG_WITH_PAGER=y when loading a TA and not enough page tables are available in pgt_cache ([#2080]) ## Tested on The release was tested successfully on the platforms listed below. * d02 * hikey * hikey-hikey960 * imx-mx6ulevk * imx-mx7dsabresd * marvell-armada7k8k * marvell-armada3700 * mediatek-mt8173 * rcar-salvator_m3 * rockchip-rk322x * rpi3 * sam * ti * vexpress-juno * vexpress-qemu_armv8a * vexpress-qemu_virt [commit_0e1c6e8e]: https://github.com/OP-TEE/optee_os/commit/0e1c6e8e [github_commits_3_0_0]: https://github.com/OP-TEE/optee_os/compare/2.6.0...3.0.0 [#2092]: https://github.com/OP-TEE/optee_os/pull/2092 [#2086]: https://github.com/OP-TEE/optee_os/pull/2086 [#2094]: https://github.com/OP-TEE/optee_os/issues/2094 [#2080]: https://github.com/OP-TEE/optee_os/issues/2080 [#2052]: https://github.com/OP-TEE/optee_os/pull/2052 [#2035]: https://github.com/OP-TEE/optee_os/pull/2035 [#2011]: https://github.com/OP-TEE/optee_os/pull/2011 [#1999]: https://github.com/OP-TEE/optee_os/pull/1999 [#1994]: https://github.com/OP-TEE/optee_os/pull/1994 [#1993]: https://github.com/OP-TEE/optee_os/pull/1993 [#1974]: https://github.com/OP-TEE/optee_os/pull/1974 [#1970]: https://github.com/OP-TEE/optee_os/pull/1970 [#1969]: https://github.com/OP-TEE/optee_os/pull/1969 [#1966]: https://github.com/OP-TEE/optee_os/pull/1966 [#1963]: https://github.com/OP-TEE/optee_os/pull/1963 [#1961]: https://github.com/OP-TEE/optee_os/pull/1961 [#1959]: https://github.com/OP-TEE/optee_os/pull/1959 [#1949]: https://github.com/OP-TEE/optee_os/pull/1949 [#1946]: https://github.com/OP-TEE/optee_os/pull/1946 [#1941]: https://github.com/OP-TEE/optee_os/pull/1941 [#1931]: https://github.com/OP-TEE/optee_os/pull/1931 [#1928]: https://github.com/OP-TEE/optee_os/pull/1928 [#1923]: https://github.com/OP-TEE/optee_os/pull/1923 [#1922]: https://github.com/OP-TEE/optee_os/pull/1922 [#1921]: https://github.com/OP-TEE/optee_os/pull/1921 [#1919]: https://github.com/OP-TEE/optee_os/pull/1919 [#1916]: https://github.com/OP-TEE/optee_os/pull/1916 [#1915]: https://github.com/OP-TEE/optee_os/pull/1915 [#1897]: https://github.com/OP-TEE/optee_os/pull/1897 [#1856]: https://github.com/OP-TEE/optee_os/pull/1856 [#1826]: https://github.com/OP-TEE/optee_os/pull/1826 # OP-TEE - version 2.6.0 [Link][github_commits_2_6_0] to a list of all commits between this release and the previous one (2.5.0). ## New features * New supported platforms: Atmel SAMA5 ([#1714]), HiSilicon HiKey960 ([#1684]), Rockchip RK322X ([#1666]), NXP LS1043A-RDB/LS1046A-RDB ([#1787]), Marvell Armada 70x0/80x0 ([#1807]). * Dynamic shared memory (non-contiguous, non-secure memory can be mapped into Trusted Applications VA space) ([#1631]) * Dump TA call stack on panic ([#1858]) * i.MX: PSCI reset ([#1849]) * plat-ti: AM43xx: suspend/resume support ([#1822]) * QEMU SMP support ([#1820]) * plat-ti: AM43xx: disable TRNG ([#1816]) * plat-ti: enable Secure Data Path by default ([#1815]) * Improve symbolize.py ([#1778], [#1767], [#1766]) * Early TAs (TAs linked in tee.bin) ([#1733]) * Suspend/resume framework for arm32 and imx7d support ([#1729]) * RK322X PSCI version, features and suspend support ([#1720]) * arm32: handle aborts in system mode ([#1703]) * i.MX: add SNVS SRTC support ([#1700]) * GCC7 support ([#1693]) * Improve detection of programming errors in locking code ([#1671], [#1670]) * Support TEE RAM size larger than page directory size ([#1669]) ## Removed features * Remove TUI code ([#1842]) ## Bug fixes * Add missing synchronization barrier in core_mmu_map_pages() ([#1827]) * Secure storage: REE FS: fix bug in error path ([#1801]) * ASAN bug fixes ([#1799]) * Fix race in core_mmu_user_mapping_is_active() ([#1785]) * libutee: printf() and puts() fixes, add putchar() ([#1759], [#1754]) * arm32: GICv3: fix FIQ masking in IRQ/ABT/SVC/UND handlers ([#1748]) * arm32: preserve r12 in native_intr_handler() ([#1682]) * arm64: fix print_kernel_stack() ([#1664]) * benchmark: fix core data-abort ([#1658]) ## Security fixes or enhancements * crypto: fix software PRNG weaknesses ([OP-TEE-2017-0001][OP-TEE-2017-0001]) ([#1843]) ## Tested on The release was tested successfully on the platforms listed below. If a platform is not listed, it means the release was not tested on this platform. * d02 * hikey * hikey-hikey960 * imx-mx6ulevk * imx-mx7dsabresd * ls-ls1021a??? (single core) * ls-ls1043ardb * ls-ls1046ardb * mediatek-mt8173 * rcar * rockchip-rk322x * rpi3 * sam * stm-b2260 * stm-cannes * ti-??? * vexpress-fvp * vexpress-juno * vexpress-qemu_armv8a * vexpress-qemu_virt [github_commits_2_6_0]: https://github.com/OP-TEE/optee_os/compare/2.5.0...2.6.0 [#1858]: https://github.com/OP-TEE/optee_os/issues/1858 [#1849]: https://github.com/OP-TEE/optee_os/issues/1849 [#1843]: https://github.com/OP-TEE/optee_os/issues/1843 [#1842]: https://github.com/OP-TEE/optee_os/issues/1842 [#1827]: https://github.com/OP-TEE/optee_os/issues/1827 [#1822]: https://github.com/OP-TEE/optee_os/issues/1822 [#1820]: https://github.com/OP-TEE/optee_os/issues/1820 [#1816]: https://github.com/OP-TEE/optee_os/issues/1816 [#1815]: https://github.com/OP-TEE/optee_os/issues/1815 [#1807]: https://github.com/OP-TEE/optee_os/issues/1807 [#1801]: https://github.com/OP-TEE/optee_os/issues/1801 [#1799]: https://github.com/OP-TEE/optee_os/issues/1799 [#1787]: https://github.com/OP-TEE/optee_os/issues/1787 [#1785]: https://github.com/OP-TEE/optee_os/issues/1785 [#1778]: https://github.com/OP-TEE/optee_os/issues/1778 [#1767]: https://github.com/OP-TEE/optee_os/issues/1767 [#1766]: https://github.com/OP-TEE/optee_os/issues/1766 [#1759]: https://github.com/OP-TEE/optee_os/issues/1759 [#1754]: https://github.com/OP-TEE/optee_os/issues/1754 [#1748]: https://github.com/OP-TEE/optee_os/issues/1748 [#1733]: https://github.com/OP-TEE/optee_os/issues/1733 [#1729]: https://github.com/OP-TEE/optee_os/issues/1729 [#1720]: https://github.com/OP-TEE/optee_os/issues/1720 [#1714]: https://github.com/OP-TEE/optee_os/issues/1714 [#1703]: https://github.com/OP-TEE/optee_os/issues/1703 [#1700]: https://github.com/OP-TEE/optee_os/issues/1700 [#1693]: https://github.com/OP-TEE/optee_os/issues/1693 [#1684]: https://github.com/OP-TEE/optee_os/issues/1684 [#1682]: https://github.com/OP-TEE/optee_os/issues/1682 [#1671]: https://github.com/OP-TEE/optee_os/issues/1671 [#1670]: https://github.com/OP-TEE/optee_os/issues/1670 [#1669]: https://github.com/OP-TEE/optee_os/issues/1669 [#1666]: https://github.com/OP-TEE/optee_os/issues/1666 [#1664]: https://github.com/OP-TEE/optee_os/issues/1664 [#1658]: https://github.com/OP-TEE/optee_os/issues/1658 [#1631]: https://github.com/OP-TEE/optee_os/issues/1631 [OP-TEE-2017-0001]: https://www.op-tee.org/security-advisories/ # OP-TEE - version 2.5.0 [Link][github_commits_2_5_0] to a list of all commits between this release and the previous one (2.4.0). ## New features * New supported platform: i.MX7D ([#1639]) * Secure storage: anti-rollback protection for REE FS using RPMB FS ([#1630]) * Assign non-secure DDR configuration from DT if CFG_DT=y ([#1623]) * Add new image format: split image into three separate binaries suitable for upcoming ARM Trusted Firmware ([#1589]). * Make alignment check configurable ([#1586]) * drivers: add TZC380 driver ([#1578]) * plat-imx: PSCI CPU off ([#1577]) * 64-bit paging on QEMU v8 and HiKey ([#1575], [#1592]) * Benchmark framework ([#1365]) * Dump call stack of user TAs on abort ([#1552]) * plat-hikey: enable Secure Data Path ([#1440]) * Add interface to load and decrypt/authenticate user TAs ([#1513]) * plat-ti: add secure paging support ([#1493]) * plat-ti: add OTP hardware key support ([#1492]) * Support ARM GICv3 ([#1465]) ## Removed features * stm-orly2 is not supported anymore ([#1650]) * Remove secure storage based on SQL FS (`CFG_SQL_FS=y`) ([#1490]) * Remove support for mapping user TAs with 1 MiB or 2 MiB granularity (`CFG_SMALL_PAGE_USER_TA=n`) ([#1559]). TAs are always mapped using small pages. ## Bug fixes * Reduce size of non-pageable code ([#1621]) * Ignore `TA_FLAG_MULTI_SESSION` and `TA_FLAG_INSTANCE_KEEP_ALIVE` when `TA_FLAG_SINGLE_INSTANCE` is not set ([#1574]) * libutee: remove buffering for AES GCM (PR#1573) and AES CTR ([#1580]) * Fix ROUNDUP()/ROUNDDOWN() macros ([#1519]) * Do not touch other bits in GICD_CTLR ([#1508]) * Fix build issue with `DEBUG=y` and `CFG_TEE_CORE_LOG_LEVEL=0` ([#1502]) * crypto: do not restrict hash size when algorithm is ECDSA ([#1497]) ## Security fixes or enhancements - crypto: fix RSA key leakage after fault injection attack ([OP-TEE-2016-0003][OP-TEE-2016-0003]) ([#1610]) * crypto: fix RSA key leakage after side channel attack ([OP-TEE-2016-0002][OP-TEE-2016-0002]) ([#1610]) * Make pager aliased pages not always writable ([#1551]) * Support for no-exec RO and RW data ([#1459], [#1550]) ## New issues * armv7: some platform-specific code (`plat_cpu_reset_early()`) overwrites SCTLR bits configured by generic code. This affects alignment checks (`SCTLR.A`) and write-implies-no-exec (`SCTLR.WXN`, `SCTLR.UWXN`), which can therefore not be configured via the compile-time `CFG_` variables. * armv7: plat-imx: Cortex-A9 cores should enable branch prediction (`SCLTR.Z`) for improved performance. * [#1656] qemu_armv8a: init hangs when secure data path and pager are both enabled. ## Tested on In the list below, _standard_ means that the `xtest` program passed with its default configuration, while _extended_ means it was run successfully with the additional GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. If a platform is not listed, it means the release was not tested on this platform. * d02: extended * hikey: extended * imx-mx6ulevk: standard * imx-mx6ullevk: standard * imx-mx7dsabresd: standard * ls-ls1021atwr: standard * mediatek-mt8173: standard * rcar-h3: standard * rpi3: standard * stm-b2260: extended * stm-cannes: extended * ti-am43xx: standard * ti-am57xx: standard * ti-dra7xx: standard * vexpress-fvp: standard * vexpress-juno: standard * vexpress-qemu_armv8a: standard * vexpress-qemu_virt: standard [github_commits_2_5_0]: https://github.com/OP-TEE/optee_os/compare/2.4.0...2.5.0-rc1 [#1656]: https://github.com/OP-TEE/optee_os/issues/1656 [#1650]: https://github.com/OP-TEE/optee_os/pull/1650 [#1639]: https://github.com/OP-TEE/optee_os/pull/1639 [#1630]: https://github.com/OP-TEE/optee_os/pull/1630 [#1623]: https://github.com/OP-TEE/optee_os/pull/1623 [#1621]: https://github.com/OP-TEE/optee_os/pull/1621 [#1610]: https://github.com/OP-TEE/optee_os/pull/1610 [#1592]: https://github.com/OP-TEE/optee_os/pull/1592 [#1589]: https://github.com/OP-TEE/optee_os/pull/1589 [#1586]: https://github.com/OP-TEE/optee_os/pull/1586 [#1580]: https://github.com/OP-TEE/optee_os/pull/1580 [#1578]: https://github.com/OP-TEE/optee_os/pull/1578 [#1577]: https://github.com/OP-TEE/optee_os/pull/1577 [#1574]: https://github.com/OP-TEE/optee_os/pull/1574 [#1559]: https://github.com/OP-TEE/optee_os/pull/1559 [#1551]: https://github.com/OP-TEE/optee_os/pull/1551 [#1550]: https://github.com/OP-TEE/optee_os/pull/1550 [#1519]: https://github.com/OP-TEE/optee_os/pull/1519 [#1502]: https://github.com/OP-TEE/optee_os/pull/1502 [#1365]: https://github.com/OP-TEE/optee_os/pull/1365 [#1552]: https://github.com/OP-TEE/optee_os/pull/1552 [#1513]: https://github.com/OP-TEE/optee_os/pull/1513 [#1508]: https://github.com/OP-TEE/optee_os/pull/1508 [#1493]: https://github.com/OP-TEE/optee_os/pull/1493 [#1497]: https://github.com/OP-TEE/optee_os/pull/1497 [#1492]: https://github.com/OP-TEE/optee_os/pull/1492 [#1490]: https://github.com/OP-TEE/optee_os/pull/1490 [#1465]: https://github.com/OP-TEE/optee_os/pull/1465 [#1459]: https://github.com/OP-TEE/optee_os/pull/1459 [#1440]: https://github.com/OP-TEE/optee_os/pull/1440 [OP-TEE-2016-0003]: https://www.op-tee.org/security-advisories/ [OP-TEE-2016-0002]: https://www.op-tee.org/security-advisories/ # OP-TEE - version 2.4.0 [Link][github_commits_2_4_0] to a list of all commits between this release and the previous one (2.3.0). Please note: this release is API-compatible with the previous one, but the Secure Storage internal format for the REE and SQL FS is not compatible due to commits [a238b74][commit_a238b74] ("core: REE FS: use the new hash tree interface") and [44e900e][commit_44e900e] ("core: SQL FS: use the new hash tree interface"). ## New features * Add porting guidelines * Add support for Secure Data Path which allows Client and Trusted Applications to share references to secure memory * New supported platform: Texas Instruments AM57xx (`PLATFORM=ti-am57xx`) * ARMv7-A: add support for platform services in secure monitor and add these services for the DRA7xx platform * SPI framework and PL022 driver cleanup and improvements * Use CNTPCT (when available) to add entropy to the software PRNG * Add GlobalPlatform Socket API for UDP and TCP (IPv4 and IPv6) * DRA7: add TRNG driver, enable GICv2 driver * Support load address larger than 4G * libutee: preserve error code when calling TEE_Panic() for easier troubleshooting * Support TA profiling with gprof (-pg compiler switch) * Optimize the ELF loader for TAs when pager is enabled * Update documentation * Add paged secure shared memory that can be transferred between TAs as needed * Introduce MOBJ abstraction * i.MX6: add PSCI "on" function * arm32: introduce PSCI framework ## Bug fixes * Secure storage: improve integrity checking of the REE and SQL filesystems by adding a hash tree on the internal data structures. Any external modification is detected, except full rollback. Fixes [#1188][issue1188]. * The linux driver will set the 'privileged' flag (TEE_GEN_CAP_PRIVILEGED) on the device intended for use by tee-supplicant. Fixes [#1199][issue1199]. * RPMB: don't try to program the RPMB key by default * Fix "make clean" error cases * Fix issue when resetting persistent storage enumerator [#1332][issue1332] * Fix TA panic when doing AES CTS with specific buffer sizes [#1203][issue1203]. ## Known issues * On RPi3 xtest sometimes stall (rcu_sched self-detected stall on CPU) [#1353][issue1353] * For multi-core PSCI support is to be added for ls1021atwr in OP-TEE. * USB keyboard cannot be used to stop the u-boot timeout ([build issue131]). * Travis service (build.git) seems unstable from time to time. ## Tested on In the list below, _standard_ means that the `xtest` program passed with its default configuration, while _extended_ means it was run successfully with the additional GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. If a platform is not listed, it means the release was not tested on this platform. * d02: extended * hikey: extended * imx-mx6ulevk: standard * ls-ls1021atwr: standard (single core) * mediatek-mt8173: standard * rcar-h3: standard * rpi3: standard * stm-b2260: extended * ti-dra7xx: standard * vexpress-fvp: standard * vexpress-juno: standard * vexpress-qemu_armv8a: standard * vexpress-qemu_virt: standard * zynqmp-zc1751_dc1: standard * zynqmp-zc1751_dc2: standard * zynqmp-zcu102: standard [github_commits_2_4_0]: https://github.com/OP-TEE/optee_os/compare/2.3.0...2.4.0 [issue1332]: https://github.com/OP-TEE/optee_os/issues/1332 [issue1353]: https://github.com/OP-TEE/optee_os/issues/1353 [build issue131]: https://github.com/OP-TEE/build/issues/131 [commit_a238b74]: https://github.com/OP-TEE/optee_os/commit/a238b744b1b3 [commit_44e900e]: https://github.com/OP-TEE/optee_os/commit/44e900eabfc1 # OP-TEE - version 2.3.0 [Link][github_commits_2_3_0] to a list of all commits between this release and the previous one (2.2.0). Please note: this release is API-compatible with the previous one, but the Secure Storage internal format for the REE FS is not compatible due to commit [361fb3e][commit_361fb3e] ("core: REE FS: use a single file per object"). [commit_361fb3e]: https://github.com/OP-TEE/optee_os/commit/361fb3e ## New features * New supported platform: Xilinx Zynq 7000 ZC702 (`PLATFORM=zynq7k-zc702`) * Add debug assertions to spinlocks and mutexes * Add more CP15 register access macros for Cortex-A9 * ARMv7-A: redesign secure monitor to make it easier to register services * ARMv7-A: cleanup boot arguments * libutee: extend `TEE_CheckMemoryAccessRights()` with `TEE_MEMORY_ACCESS_SECURE` and `TEE_MEMORY_ACCESS_NONSECURE` * plat-hikey: enable SPI by default and add sample test code * Consider `CFLAGS_ta_arm64` and `CFLAGS_ta_arm32` when building TAs * Secure storage refactoring - Simplify interface with tee-supplicant. Minimize round trips with normal world, especially by adding a cache for FS RPC payload data. - REE FS: use a single file per object, remove block cache. * Print call stack in panic() ## Bug fixes * Fix UUID encoding when communicating with normal world (use big endian mode instead of native endianness). Related to this, the string format for UUIDs has changed in tee-supplicant, so that TA file names now follow the format defined in RFC4122 (a missing hyphen was added). The old format is still supported, but deprecated, and will likely be removed with the next major release. * Drop write permission to non-writable ELF segments after TA loading is complete. * mm: fix confusing memory mapping debug traces * plat-ti: fix issues with MMU mapping * crypto: fix clearing of big numbers * build: allow spaces and double quotes in CFG_ variables * mm: use paddr_t to support both 32- and 64-bit architectures properly. Resolves 32-bit truncation error when pool is at top of 32 bit address space on 64-bit architecture. * plat-stm: support pager. Fix pager on ARMv7-A SMP boards. * Fix debug output of Trusted Applications (remove "ERROR: TEE-CORE:" prefix) * Do not consider TA memref parameters as TA private memory * crypto: fix `cipher_final()` which would not call `cbc_done()` for CBC_MAC algorithms * fix for 16-way PL310 * arm32: fix call stack unwinding (`print_stack()`) * arm32: fix spinlock assembly code * plat-stm, plat-imx: fix SCR initalization * Fix user L1 MMU entries calculation (non-LPAE), allowing TTBCR.N values other than 7. * mtk-mt8173: fix panic caused by incorrect size of SHMEM * plat-stm: fix RNG driver (non-flat mapping) ## Known issues * New issues open on GitHub * [#1203][issue1203] AES-CTS mode will fail when inlen=0x100, in_incr=0x80 * [#1199][issue1199] Both tee and teepriv reported GlobalPlatform compliant * [#1188][issue1188] Secure storage (SQL FS and REE FS): blocks not tied to current meta header * [#1172][issue1172] paddr_t should be larger than 32 bits when CFG_WITH_LPAE is enabled ## Tested on In the list below, _standard_ means that the `xtest` program passed with its default configuration, while _extended_ means it was run successfully with the additional GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. If a platform is not listed, it means the release was not tested on this platform. * d02: extended * hikey: extended * imx-mx6ulevk: standard * ls-ls1021atwr: standard * mediatek-mt8173: standard * rcar-h3: standard * rpi3: standard * stm-b2260: extended * stm-cannes: extended * ti-dra7xx: standard * vexpress-fvp: standard * vexpress-juno: standard * vexpress-qemu_armv8a: standard * vexpress-qemu_virt: extended * zynqmp-zcu102: standard [github_commits_2_3_0]: https://github.com/OP-TEE/optee_os/compare/2.2.0...2.3.0 [issue1172]: https://github.com/OP-TEE/optee_os/issues/1172 [issue1188]: https://github.com/OP-TEE/optee_os/issues/1188 [issue1199]: https://github.com/OP-TEE/optee_os/issues/1199 [issue1203]: https://github.com/OP-TEE/optee_os/issues/1203 # OP-TEE - version 2.2.0 [Link][github_commits_2_2_0] to a list of all commits between this release and the previous one (2.1.0). Please note: this release is API-compatible with the previous one, but the Secure Storage internal format is not compatible due to commit [fde4a75][commit_fde4a75] ("storage: encrypt the FEK with a TA-specific key"). [commit_fde4a75]: https://github.com/OP-TEE/optee_os/commit/fde4a75 ## New features * New supported platforms: * Freescale i.MX6 Quad SABRE Lite & SD * HiSilicon D02 * Raspberry Pi3 * Renesas RCAR H3 * STMicroelectronics b2260 - h410 * Pager: Support paging of read/write pages by encrypting them with AES-GCM. Support paging of user TAs. Add global setting for TZSRAM size (CFG_CORE_TZSRAM_EMUL_SIZE), defaults to 300K. * Support for more than 8 CPU cores * Added SPI framework and PL022 driver * GPIO: framework supports multiple instances, PL061 driver now has get/set interrupt and mode control functions * Secure storage: Encrypt the File Encryption Key with a TA-specific key for better TA isolation. Add build-time and run-time support for multiple storage backends. Add SQLite backend. * Trusted User Interface: some code is introduced to support the implementation of TUI. This includes: a generic framebuffer driver, display and serial abstractions, and drivers for PL111 (LCD) / PL050 (KMI) / TZC400 and PS2 mouse. * AES acceleration using ARMv8-A Cryptographic Extensions instructions is now supported in AArch32 mode * Add support for GCC flags: -fsanitize=undefined and -fsanitize=kernel-address * Use a global setting for core heap size (CFG_CORE_HEAP_SIZE), 64K by default. * Add macros to unwind and print the call stack of TEE core * Libtomcrypt: sync with the latest `develop` branch. * The Trusted Application SDK (ta_dev_kit.mk) can produce libraries (.a) * Rework assertions and TEE core panics and properly honor NDEBUG ## Bug fixes * Fix incorrect algorithm passed to cipher.final() * scripts: support Python 2.x and 3.x * Secure storage: Add proper locking to support concurrent access. Fix sign extension bug with offset parameter of syscall storage_obj_seek which could cause errors in Aarch32 mode. Fix reading beyond end of file. * Aarch64: mask all maskable exceptions before doing a normal return from call. * Device Tree: add no-map property to OP-TEE node in reserved-memory. * LibTomcrypt: fix CVE-2016-6129 ## Known issues * New issues open on GitHub * [#1093][issue1093] rcar-h3: xtest 6010 hangs * [#1092][issue1092] rcar-h3: xtest 4010 fails * [#1081][issue1081] Bad mapping of TA secure memref parameters * [#1071][issue1071] __data_end may not correctly represent text start position when using CFG_WITH_PAGER * [#1069][issue1069] armv7/Aarch32: crash in stack unwind (DPRINT_STACK()) ## Tested on In the list below, _standard_ means that the `xtest` program passed with its default configuration, while _extended_ means it was run successfully with the additional GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. If a platform is not listed, it means the release was not tested on this platform. * d02: extended * hikey: extended * imx-mx6qsabrelite: standard * imx-mx6qsabresd: standard * rcar-h3: standard, pass except issues [#1092][issue1092] and [#1093][issue1093] * rpi3: standard * stm-b2260: standard * stm-cannes: standard * ti-dra7xx: standard * vexpress-fvp: standard * vexpress-juno: standard * vexpress-qemu_armv8a: standard * vexpress-qemu_virt: extended * zynqmp-zcu102: standard [github_commits_2_2_0]: https://github.com/OP-TEE/optee_os/compare/2.1.0...2.2.0 [issue1081]: https://github.com/OP-TEE/optee_os/issues/1081 [issue1071]: https://github.com/OP-TEE/optee_os/issues/1071 [issue1069]: https://github.com/OP-TEE/optee_os/issues/1069 [issue1092]: https://github.com/OP-TEE/optee_os/issues/1092 [issue1093]: https://github.com/OP-TEE/optee_os/issues/1093 # OP-TEE - version 2.1.0 ## New features * New supported platforms: * Xilinx Zynq UltraScale+ MPSOC * Spreadtrum SC9860 * GCC5 support * Non Linear Mapping support: In OP-TEE kernel mode, the physical to virtual addresses was linear until this release, meaning the virtual addresses were equal to the physical addresses. This is no more the case in this release. * Font rendering routines have been introduced in order to ease an implementation of Trusted UI. * File Storage: Possibility to use the normal world filesystem and the RPMB implementations simultaneously. * AOSP: There is a [local manifest][aosp_local_manifest] to build OP-TEE into an AOSP build, running on HiKey. Please refer to the README in that repo for instructions. * OpenEmbedded: In addition to the makefile-based build described in the optee_os README, there is an [OpenEmbedded-based build][oe_build] that supports Qemu (32-bit), FVP (64-bit), and HiKey (64-bit). Please refer to the README in that repo for instructions. * [Link][github_commits_2_1_0] to a list of all commits between this and previous release. ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The [optee_test][optee_test] project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. | * ARM Juno Board (vexpress-juno), standard. * Foundation Models (vexpress-fvp), standard tests + extended tests, using FVP ARM V8 Foundation Platformr0p0 (platform build 10.0.37) * FSL i.MX6 UltraLite EVK (imx), standard. * FSL ls1021a (ls-ls1021atwr), standard tests. * HiKey (hikey), standard + extended tests. * QEMU (vexpress-qemu), standard + extended tests. * Xilinx Zynq UltraScale+ MPSOC, standard tests Note that the following platform has not been tested: * MTK8173-EVB (mediatek-mt8173) ## Known issues * Issue(s) open on GitHub * [#868][pr868]: python-wand font generation sometimes times out * [#863][pr863]: "double free or corruption" error when building optee_os * [#858][pr858]: UUIDs in binary format have wrong endinanness * [#857][pr857]: Formatting of UUIDs is incorrect * [#847][pr847]: optee_os panic(TEE-CORE: Assertion) * [#838][pr838]: TUI font rendering is _very_ slow * [#814][pr814]: Persistent objects : save informations after close * [#665][pr665]: xtest 1013 stalled on HiKey when log levels are 4 and optee_os is on its own UART * [#506][pr506]: tee-supplicant panic & ta panic [github_commits_2_1_0]: https://github.com/OP-TEE/optee_os/compare/2.0.0...2.1.0 [pr868]: https://github.com/OP-TEE/optee_os/issues/868 [pr863]: https://github.com/OP-TEE/optee_os/issues/863 [pr858]: https://github.com/OP-TEE/optee_os/issues/858 [pr857]: https://github.com/OP-TEE/optee_os/issues/857 [pr847]: https://github.com/OP-TEE/optee_os/issues/847 [pr838]: https://github.com/OP-TEE/optee_os/issues/838 [pr814]: https://github.com/OP-TEE/optee_os/issues/814 [pr665]: https://github.com/OP-TEE/optee_os/issues/665 [aosp_local_manifest]: https://github.com/linaro-swg/optee_android_manifest [oe_build]: https://github.com/linaro-swg/oe-optee # OP-TEE - version 2.0.0 ## New features * Generic driver: A new generic TEE driver is in the process of being [upstreamed][gendrv_v9]. In this release, [OP-TEE/optee_linuxdriver][optee_linuxdriver] is no more used. Instead, linux v4.5 is being patched using the proposed Generic TEE Driver, as it can be found in [https://github.com/linaro-swg/linux/tree/optee][linux_optee] * RPMB support: Secure Storage can now use Replay Protected Memory Block (RPMB) partition of an eMMC device. Check the [full documentation][rpmb_doc] * Hard-float ABI is now available. * [Link][github_commits_2_0_0] to a list of all commits between this and previous release. ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The [optee_test][optee_test] project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. | * ARM Juno Board (vexpress-juno), standard. * Foundation Models (vexpress-fvp), standard tests + extended tests, using FVP ARM V8 Foundation Platformr0p0 (platform build 9.5.40) * FSL ls1021a (ls-ls1021atwr), standard. * HiKey (hikey), standard. * MTK8173-EVB (mediatek-mt8173), standard. * QEMU (vexpress-qemu), standard + extended tests. * STM Cannes (stm-cannes), standard + extended tests. ## Known issues * Issue(s) open on GitHub * [#40][prld40] BUG_ON() when re-using RPC buffer to tee-supplicant * [#506][pr506]: tee-supplicant panic & ta panic [github_commits_2_0_0]: https://github.com/OP-TEE/optee_os/compare/1.1.0...2.0.0 [rpmb_doc]: https://github.com/OP-TEE/optee_os/blob/master/documentation/secure_storage_rpmb.md [optee_linuxdriver]: https://github.com/OP-TEE/optee_linuxdriver [gendrv_v9]: https://lkml.org/lkml/2016/4/1/205 [linux_optee]: https://github.com/linaro-swg/linux/tree/optee # OP-TEE - version 1.1.0 ## New features * Softfloat library: floating point support is now available in 32bits TA. * Support running 64-bits TA: on ARMv8-A platform, TA can be compiled in AArch32 and/or in AArch64 in case the core is compiled in AArch64. An example can be found in HiKey configuration file. Using the following excerpt code, the user TA libraries are compiled in both AArch32 and AArch64, and can be found in `out/arm-plat-hikey/export-ta_arm32` and `out/arm-plat-hikey/export-ta_arm64` ``` ta-targets = ta_arm32 ta-targets += ta_arm64 ``` * Concurrent TA support: multiple TA can run in parallel on several cores. * New tests added in xtest test suite: concurrent TA (xtest 1013), floating point tests (xtest 1006 and os_test TA) and corruption file storage (xtest 20000) * [Link][github_commits_1_1_0] to a list of all commits between this and previous release. ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The [optee_test][optee_test] project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. | | Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | * Foundation Models (vexpress-fvp), standard tests + extended tests, using FVP ARM V8 Foundation Platformr0p0 (platform build 9.5.40) * HiKey (hikey), standard + extended tests. * MT8173 (mediatek), standard tests. * QEMU (vexpress-qemu), standard + extended tests. * STM Cannes (stm-cannes), standard + extended tests. ## Known issues * Secure Storage is implemented, but note that anti-rollback protection is not implemented yet. * Issue(s) open on GitHub * [#40][prld40] BUG_ON() when re-using RPC buffer to tee-supplicant * [#296][pr296]: Connecting RPMB to the storage APIs. * [#493][pr493]: setup_juno_optee: unable to find pre-built binaries * [#506][pr506]: tee-supplicant panic & ta panic [prld40]: https://github.com/OP-TEE/optee_linuxdriver/issues/40 [pr506]: https://github.com/OP-TEE/optee_os/issues/506 [github_commits_1_1_0]: https://github.com/OP-TEE/optee_os/compare/1.0.1...1.1.0 # OP-TEE - version 1.0.0 OP-TEE is now maintained by Linaro. Contributors do not need to sign a CLA anymore, but must follow the rules of the [DCO][DCO] (Developer Certificate of Origin) instead. ## New features * Add hardware support for Texas Instruments DRA7xx, ARMv7 (plat-ti) * GlobalPlatform™ TEE Internal Core API Specification v1.1, including ECC algorithms. * Secure Storage: Files stored by the REE are now encrypted. Operations are made atomic in order to prevent inconsistencies in case of errors during the storage operations. [Slides][LCStorage] describing the Secure Storage have been presented at the Linaro Connect SFO15. * Change of format of the Trusted Applications: they follow a [signed ELF format][elf] * Rework thread [synchronization][synchro] in optee_os. * Use of ARMv8 native cryptographic support. * [OP-TEE/optee_test][optee_test] test suite is released. * Introduce [OP-TEE/manifest][manifest] and [OP-TEE/build][build] to setup and build QEMU, FVP, HiKey and Mediatek platforms. Setup scripts that used to be in optee_os have been removed, except for Juno board. * [Link][github_commits_1_0_0] to a list of all commits between this and previous release. ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The [optee_test][optee_test] project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. | | Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | * ARM Juno Board (vexpress-juno), standard + extended tests. * Foundation Models (vexpress-fvp), standard tests. * HiKey (hikey), standard + extended tests. * MT8173 (mediatek), standard tests. * QEMU (vexpress-qemu), standard + extended tests. * STM Cannes (stm-cannes), standard + extended tests. ## Known issues * Secure Storage is implemented, but note that anti-rollback protection is not implemented yet. * Issue(s) open on GitHub * [#210][pr210]: libteec.so 32-bit does not communicate well with 64-bit kernel module * [#296][pr296]: Connecting RPMB to the storage APIs. * [#493][pr493]: setup_juno_optee: unable to find pre-built binaries * [#494][pr494]: HiKey: xtest 7671 fails (1.0.0-rc2) [pr210]: https://github.com/OP-TEE/optee_os/issues/210 [pr296]: https://github.com/OP-TEE/optee_os/issues/296 [pr493]: https://github.com/OP-TEE/optee_os/issues/493 [pr494]: https://github.com/OP-TEE/optee_os/issues/494 [github_commits_1_0_0]: https://github.com/OP-TEE/optee_os/compare/0.3.0...1.0.0 [DCO]: https://github.com/OP-TEE/optee_os/blob/master/Notice.md#contributions [LCStorage]: http://www.slideshare.net/linaroorg/sfo15503-secure-storage-in-optee [synchro]: https://github.com/OP-TEE/optee_os/blob/master/documentation/optee_design.md#4-thread-handling [elf]: https://github.com/OP-TEE/optee_os/blob/master/documentation/optee_design.md#format [optee_test]: https://github.com/OP-TEE/optee_test [manifest]: https://github.com/OP-TEE/manifest [build]: https://github.com/OP-TEE/build # OP-TEE - version 0.3.0 ## New features * Add hardware support for * Mediatek MT8173 Board, ARMv8-A (plat-mediatek) * Hisilicon HiKey Board, ARMv8-A (plat-hikey) * AArch64 build of optee_os is now possible through the configuration `CFG_ARM64_core=y` * Secure Storage: Data can be encrypted prior to their storage in the non-secure. Build is configured using `CFG_ENC_FS=y` * A generic boot scheme can be used. Boot configuration is commonalized. This helps new board support. It is applied on plat-hikey, plat-vexpress, plat-mediatek, plat-stm and plat-vexpress. ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The optee_test project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. | | Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | * ARM Juno Board (vexpress-juno), standard tests. * Foundation Models (vexpress-fvp), standard tests. * HiKey (hikey), standard tests. * MT8173 (mediatek), standard tests. * QEMU (vexpress-qemu), standard + extended tests. * STM Cannes (stm-cannes), standard + extended tests. ------------------------------------------- # OP-TEE - version 0.2.0 ## New features ### Linux Driver Refactoring Linux Driver has been refactored. It is now split in two parts: * optee.ko, the generic Linux driver. It contains all functionality common to all backends. * optee_armtz.ko, a specific backend dedicated to the TrustZone optee. It depends on optee.ko. Loading the TrustZone optee linux driver module is now performed using modprobe optee_armtz Thanks to the dependency between the generic and the backend modules, optee.ko is then automatically loaded. ### Misc new features * support PL310 lock down at TEE boot * add 64bits support (division / print) ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The optee_test project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.1.0.4. | | Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | * ARM Juno Board (vexpress-juno), standard tests + extended tests. * Foundation Models (vexpress-fvp), standard + extended tests. * QEMU (vexpress-qemu), standard + extended tests. * STM Cannes (stm-cannes), standard + extended tests. ## Issues resolved since last release * Fix user TA trace issue, in order each TA is able to select its own trace level ------------------------------------------- # OP-TEE - version 0.1.0 ## New features Below is a summary of the most important features added, but at the end you will find a link that present you all commits between the current and previous release tag. * GlobalPlatform Client API v1.0 support. * GlobalPlatform Internal API v1.0 support. * GlobalPlatform Secure Elements v1.0 support. * Add hardware support for * Allwinner A80, ARMv7-A. * ARM Juno Board, ARMv8-A. * Foundation Models, ARMv8-A. * Fast Models, ARMv8-A. * QEMU, ARMv7-A. * STM Cannes, ARMv7-A. * STM Orly2, ARMv7-A. * Add LibTomCrypt as the default software cryptographic library. * Add cryptographic abstraction layer in on secure side to ease the use of other cryptographic software libraries or adding support for hardware acceleration. * Extended cryptographic API with support for HKDF, Concat KDF and PBKDF2. * SHA-1 and SHA-256 ARMv8-A crypto extension implementation. * Enabled paging support in OP-TEE OS. * Add support for xtest (both standard and extended) in QEMU and FVP setup scripts. * Add documentation for the OS design, cryptographic abstraction layer, secure elements design, the build system, GitHub usage, key derivation extensions, ARM-Trusted Firmware usage within OP-TEE and GlobalPlatform usage within OP-TEE. * Integrate support for Travis CI. * [Link][github_commits_0_1_0] to a list of all commits between this and previous release. ## Tested on Definitions: | Type | Meaning | | ---- | ------- | | Standard tests | The optee_test project. | | Extended tests | optee_test with tests from the GlobalPlatform™ TEE Initial Configuration Test Suite v1.0.0. | | Hello world test | Plain hello world Trusted Application such as [this][hello_world]. | * Allwinner A80 (plat-sunxi), hello world test. * ARM Juno Board (vexpress-juno), standard tests. * Foundation Models (plat-vexpress-fvp), standard + extended tests * QEMU (plat-vexpress-qemu), standard + extended tests (and Secure Elements tested separately). * STM Cannes (plat-stm-cannes), standard + extended tests. ## Issues resolved since last release N/A since this is the first release tag on OP-TEE. ## Known issues * Storage is implemented, but not "Secure storage", meaning that a client needs to do encrypt files on their own before storing the files. * Issue(s) open on GitHub * [#95][pr95]: An error about building the test code of libtomcrypt. * [#149][pr149]: when testing optee os with arm trusted firmware (I utilized optee os tee.bin as bl32 image) on juno platform, I got an error. * [#161][pr161]: tee_svc_cryp.c lacks accessibility checks on user-supplied TEE_Attributes. [hello_world]: https://github.com/jenswi-linaro/lcu14_optee_hello_world [github_commits_0_1_0]: https://github.com/OP-TEE/optee_os/compare/b01047730e77127c23a36591643eeb8bb0487d68...999e4a6c0f64d3177fd3d0db234107b6fb860884 [pr95]: https://github.com/OP-TEE/optee_os/issues/95 [pr149]: https://github.com/OP-TEE/optee_os/issues/149 [pr161]: https://github.com/OP-TEE/optee_os/issues/161 * Global Platform Device Internal Core API v1.1 * [#230][pr230]: Persistent object corruption support (TEE_ERROR_CORRUPT_OBJECT/_2) * [#230][pr230]: Persistent object access support (TEE_ERROR_STORAGE_NOT_AVAILABLE/_2) optee_os-4.3.0/LICENSE000066400000000000000000000026011464416617300143530ustar00rootroot00000000000000Unless it has its own copyright/license embedded in its body, each file is subject to the following license terms: Copyright (c) 2015, Linaro Limited All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. optee_os-4.3.0/MAINTAINERS000066400000000000000000000226621464416617300150540ustar00rootroot00000000000000 Maintainers in the OP-TEE project Linaro as such maintains OP-TEE, but for individual devices which might not be available to Linaro and/or in public in general we have assigned sub-maintainers for these platforms. Please keep this list in alphabetical order, and refer to the Linux kernel's MAINTAINER file for the description of section entries [1]. Note that OP-TEE development mainly occurs on GitHub [2] so this file should be used a bit differently compared to the Linux MAINTAINERS file: 1. GitHub accounts may be given in square brackets, starting with an @ sign. For example, [@jbech-linaro]. 2. Patches should generally be submitted as GitHub pull requests (more details in documentation/github.md). Therefore, please do NOT send patches to the e-mail addresses below. Maintainers normally are subscribed to GitHub notifications, so they should see your pull requests. If you need to 'ping' some maintainer, just mention his/her GitHub account in a comment in the pull request. 2. Bug reports and questions should be posted to the GitHub project as well (use the "Issues" tab). 3. The last entry ("THE REST") lists the overall maintainers (M:) and the members of the Linaro Security Working Group who provide reviews on a regular basis (R:). [1] https://www.kernel.org/doc/linux/MAINTAINERS [2] https://github.com/OP-TEE/optee_os ---------- AOSP build R: Tadd Kao [@taddk] S: Maintained F: mk/aosp_optee.mk ARM Foundation FVP R: Jens Wiklander [@jenswi-linaro] S: Maintained F: core/arch/arm/plat-vexpress/ ARM Juno R: Jens Wiklander [@jenswi-linaro] S: Maintained F: core/arch/arm/plat-vexpress/ ARM Corstone1000 R: Emekcan.Aras@arm.com [@ememarar] S: Maintained F: core/arch/arm/plat-corstone1000/ AllWinner sun8i H2+ R: Ying-Chun Liu (PaulLiu) [@grandpaul] S: Maintained F: core/arch/arm/plat-sunxi/ AllWinner sun50i A64 R: Amit Singh Tomar [@Amit-Radur] S: Maintained F: core/arch/arm/plat-sunxi/ AmLogic AXG (A113D) R: Carlo Caione [@carlocaione] S: Maintained F: core/arch/arm/plat-amlogic/ Atmel ATSAMA5D2-XULT R: Akshay Bhat [@nodeax] S: Maintained F: core/arch/arm/plat-sam/ Broadcom ns3 L: Broadcom S: Orphan F: core/arch/arm/plat-bcm/ Core Drivers I2C R: Jorge Ramirez [@ldts] S: Maintained F: core/drivers/imx_i2c.c Core Drivers RNGB R: Jorge Ramirez [@ldts] S: Maintained F: core/drivers/imx_rngb.c Core Drivers SE050 R: Jorge Ramirez [@ldts] S: Maintained F: core/drivers/crypto/se050 Core Drivers Versal ACAP R: Jorge Ramirez [@ldts] S: Maintained F: core/drivers/crypto/versal/authenc.c F: core/drivers/crypto/versal/ecc.c F: core/drivers/crypto/versal/ipi.c F: core/drivers/crypto/versal/rsa.c F: core/drivers/versal_gpio.c F: core/drivers/versal_huk.c F: core/drivers/versal_mbox.c F: core/drivers/versal_nvm.c F: core/drivers/versal_pm.c F: core/drivers/versal_puf.c F: core/drivers/versal_sha3_384.c F: core/drivers/versal_trng.c Core Drivers ZYNQMP R: Jorge Ramirez [@ldts] S: Maintained F: core/drivers/zynqmp_csu_aes.c F: core/drivers/zynqmp_csu_puf.c F: core/drivers/zynqmp_csudma.c F: core/drivers/zynqmp_huk.c F: core/drivers/zynqmp_pm.c Function Graph Tracer (ftrace) support R: Sumit Garg [@b49020] S: Maintained F: ldelf/ftrace.c F: lib/libutils/ext/ftrace/ HiSilicon D02 S: Orphan F: core/arch/arm/plat-d02/ HiSilicon D06 R: Xiaoxu Zeng [@xiaoxuZeng] S: Maintained F: core/arch/arm/plat-d06/ HiSilicon HiKey (Kirin 620), HiKey960 (Kirin 960) R: Jerome Forissier [@jforissier] S: Maintained F: core/arch/arm/plat-hikey/ HiSilicon Poplar (Hi3798C V200) R: Igor Opaniuk [@igoropaniuk] S: Maintained F: core/arch/arm/plat-poplar/ Hisilicon Hi3519AV100 family R: Jerome Forissier [@jforissier] S: Maintained F: core/arch/arm/plat-hisilicon Marvell Armada 70x0, Armada 80x0, Armada 3700, OcteonTX2 CN96XX, OcteonTX2 CFN95XX, OcteonTX2 CN98XX, CN10K R: Tao Lu [@taovcu] S: Maintained F: core/arch/arm/plat-marvell/ MediaTek MT8173 EVB S: Orphan F: core/arch/arm/plat-mediatek/ NXP LS1043A-RDB, LS1046A-RDB, LS1012A-RDB, LS1028A-RDB, LS1088A-RDB, LS2088A-RDB, LX2160A-RDB, LX2160A-QDS R: Pankaj Gupta [@pangupta] R: Sahil Malhotra [@sahilnxp] S: Maintained F: core/arch/arm/plat-ls/ Core Drivers I2C R: Sahil Malhotra [@sahilnxp] S: Maintained F: core/drivers/ls_i2c.c LS Core Drivers GPIO R: Sahil Malhotra [@sahilnxp] S: Maintained F: core/drivers/ls_gpio.c LS Core Drivers DSPI R: Sahil Malhotra [@sahilnxp] S: Maintained F: core/drivers/ls_dspi.c NXP (Freescale) i.MX family R: Peng Fan [@MrVan] R: Silvano Di Ninno [@sdininno] R: Sahil Malhotra [@sahilnxp] S: Maintained F: core/arch/arm/plat-imx/ F: core/arch/arm/plat-imx/registers F: core/drivers/crypto/caam/ F: core/drivers/imx/ F: core/drivers/imx_csu.c F: core/drivers/imx_ele.c F: core/drivers/imx_lpuart.c F: core/drivers/imx_ocotp.c F: core/drivers/imx_sc_api.c F: core/drivers/imx_scu.c F: core/drivers/imx_snvs.c F: core/drivers/imx_uart.c F: core/drivers/imx_wdog.c Clock driver framework R: Clement Leger [@clementleger] S: Maintained F: core/drivers/clk/ Crypto driver interface R: Cedric Neveux [@cneveux] R: Silvano Di Ninno [@sdininno] R: Sahil Malhotra [@sahilnxp] S: Maintained F: core/drivers/crypto/ NXP (Freescale) i.MX7 WaRP7 R: Peng Fan [@MrVan] R: Bryan O'Donoghue [@bryanodonoghue] S: Maintained F: core/arch/arm/plat-imx/conf.mk PKCS#11 TA R: Etienne Carriere [@etienne-lms] R: Ruchika Gupta [@ruchi393] R: Vesa Jääskeläinen [@vesajaaskelainen] S: Maintained F: ta/pkcs11 QEMU (32 and 64 bits) R: Jens Wiklander [@jenswi-linaro] S: Maintained F: core/arch/arm/plat-vexpress/ Raspberry Pi3 R: Joakim Bech [@jbech-linaro] S: Maintained F: core/arch/arm/plat-rpi3/ Renesas RCAR R: Volodymyr Babchuk [@lorc] S: Maintained F: core/arch/arm/plat-rcar/ Renesas RZ/G2 R: Lad Prabhakar [@prabhakarlad] R: Biju Das [@bijucdas] S: Maintained F: core/arch/arm/plat-rzg/ Renesas RZ/N1 R: Sumit Garg [@b49020] S: Maintained F: core/arch/arm/plat-rzn1/ Rockchip RK322X R: Rockchip S: Maintained F: core/arch/arm/plat-rockchip/ Socionext DeveloperBox (Synquacer SC2A11) R: Sumit Garg [@b49020] S: Maintained F: core/arch/arm/plat-synquacer/ Socionext UniPhier R: Kunihiko Hayashi R: [@96boards-akebi96/optee] S: Maintained F: core/arch/arm/plat-uniphier/ Spreadtrum SC9860 S: Orphan F: core/arch/arm/plat-sprd/ STMicroelectronics b2260-h410, b2120-h310/h410 R: Etienne Carriere [@etienne-lms] S: Maintained F: core/arch/arm/plat-stm/ STMicroelectronics drivers R: Etienne Carriere [@etienne-lms] R: Gatien Chevallier [@GseoC] S: Maintained F: core/drivers/stm32_* STMicroelectronics stm32mp1 R: Etienne Carriere [@etienne-lms] S: Maintained F: core/arch/arm/plat-stm32mp1/ F: core/drivers/stm32mp15_huk.c F: core/drivers/stpmic1.c STMicroelectronics stm32mp2 R: Etienne Carriere [@etienne-lms] R: Gatien Chevallier [@GseoC] S: Maintained F: core/arch/arm/plat-stm32mp2/* Texas Instruments AM43xx, AM57xx, DRA7xx, AM65x, J721E, J784S4, AM64x, AM62x R: Andrew Davis [@glneo] S: Maintained F: core/arch/arm/plat-ti/ F: core/arch/arm/plat-k3/ Xilinx Zynq 7000 ZC702 Board R: Yan Yan R: Feng Yu S: Maintained F: core/arch/arm/plat-zynq7k/ Xilinx Zynq UltraScale+ MPSOC R: Ricardo Salveti [@ricardosalveti] S: Maintained F: core/arch/arm/plat-zynqmp/ Xilinx Versal ACAP R: Jorge Ramirez-Ortiz [@ldts] S: Maintained F: core/arch/arm/plat-versal/ Virtualization support R: Volodymyr Babchuk [@lorc] S: Maintained F: core/arch/arm/kernel/virtualization.c Aspeed AST2600, AST2700 R: Chia-Wei Wang [@ChiaweiW] R: Neal Liu [@Neal-liu] S: Maintained F: core/arch/arm/plat-aspeed/ RISC-V R: Marouene Boubakri [@maroueneboubakri] S: Maintained F: core/arch/riscv/ F: lib/libutee/arch/riscv/ F: lib/libutils/ext/arch/riscv/ F: lib/libutils/isoc/arch/riscv/ F: ta/arch/riscv/ THE REST M: Joakim Bech [@jbech-linaro] M: Jens Wiklander [@jenswi-linaro] M: Jerome Forissier [@jforissier] R: Etienne Carriere [@etienne-lms] L: op-tee@lists.trustedfirmware.org S: Maintained F: * F: */ optee_os-4.3.0/Makefile000066400000000000000000000071401464416617300150110ustar00rootroot00000000000000SHELL = bash # It can happen that a makefile calls us, which contains an 'export' directive # or the '.EXPORT_ALL_VARIABLES:' special target. In this case, all the make # variables are added to the environment for each line of the recipes, so that # any sub-makefile can use them. # We have observed this can cause issues such as 'Argument list too long' # errors as the shell runs out of memory. # Since this Makefile won't call any sub-makefiles, and since the commands do # not expect to implicitely obtain any make variable from the environment, we # can safely cancel this export mechanism. Unfortunately, it can't be done # globally, only by name. Let's unexport MAKEFILE_LIST which is by far the # biggest one due to our way of tracking dependencies and compile flags # (we include many *.cmd and *.d files). unexport MAKEFILE_LIST # Automatically delete corrupt targets (file updated but recipe exits with a # nonzero status). Useful since a few recipes use shell redirection. .DELETE_ON_ERROR: include mk/macros.mk include mk/checkconf.mk .PHONY: all all: .PHONY: mem_usage mem_usage: # log and load eventual tee config file # path is absolute or relative to current source root directory. ifdef CFG_OPTEE_CONFIG $(info Loading OPTEE configuration file $(CFG_OPTEE_CONFIG)) include $(CFG_OPTEE_CONFIG) endif # If $(PLATFORM) is defined and contains a hyphen, parse it as # $(PLATFORM)-$(PLATFORM_FLAVOR) for convenience ifneq (,$(findstring -,$(PLATFORM))) ops := $(join PLATFORM PLATFORM_FLAVOR,$(addprefix =,$(subst -, ,$(PLATFORM)))) $(foreach op,$(ops),$(eval override $(op))) endif # Make these default for now ARCH ?= arm PLATFORM ?= vexpress # Default value for PLATFORM_FLAVOR is set in plat-$(PLATFORM)/conf.mk ifeq ($O,) O := out out-dir := $(O)/$(ARCH)-plat-$(PLATFORM) else out-dir := $(O) endif arch_$(ARCH) := y ifneq ($V,1) q := @ cmd-echo := true cmd-echo-silent := echo else q := cmd-echo := echo cmd-echo-silent := true endif ifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4 ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),) cmd-echo-silent := true endif else # make-3.8x ifneq ($(findstring s, $(MAKEFLAGS)),) cmd-echo-silent := true endif endif SCRIPTS_DIR := scripts include core/core.mk # Platform/arch config is supposed to assign the targets ta-targets ?= invalid $(call force,default-user-ta-target,$(firstword $(ta-targets))) ifeq ($(CFG_WITH_USER_TA),y) include ldelf/ldelf.mk define build-ta-target ta-target := $(1) include ta/ta.mk endef $(foreach t, $(ta-targets), $(eval $(call build-ta-target, $(t)))) # Build user TAs included in this git ifeq ($(CFG_BUILD_IN_TREE_TA),y) define build-user-ta ta-mk-file := $(1) include ta/mk/build-user-ta.mk endef $(foreach t, $(sort $(wildcard ta/*/user_ta.mk)), $(eval $(call build-user-ta,$(t)))) endif endif include mk/cleandirs.mk .PHONY: clean clean: @$(cmd-echo-silent) ' CLEAN $(out-dir)' $(call do-rm-f, $(cleanfiles)) ${q}dirs="$(call cleandirs-for-rmdir)"; if [ "$$dirs" ]; then $(RMDIR) $$dirs; fi @if [ "$(out-dir)" != "$(O)" ]; then $(cmd-echo-silent) ' CLEAN $(O)'; fi ${q}if [ -d "$(O)" ]; then $(RMDIR) $(O); fi ${q}rm -f compile_commands.json .PHONY: cscope cscope: @echo ' CSCOPE .' ${q}rm -f cscope.* ${q}find $(PWD) -name "*.[chSs]" | grep -v export-ta_ | \ grep -v -F _init.ld.S | grep -v -F _unpaged.ld.S > cscope.files ${q}cscope -b -q -k .PHONY: checkpatch checkpatch-staging checkpatch-working checkpatch: checkpatch-staging checkpatch-working checkpatch-working: ${q}./scripts/checkpatch.sh checkpatch-staging: ${q}./scripts/checkpatch.sh --cached optee_os-4.3.0/README.md000066400000000000000000000003211464416617300146220ustar00rootroot00000000000000# OP-TEE Trusted OS This git contains source code for the secure side implementation of OP-TEE project. All official OP-TEE documentation has moved to http://optee.readthedocs.io. // OP-TEE core maintainers optee_os-4.3.0/core/000077500000000000000000000000001464416617300142775ustar00rootroot00000000000000optee_os-4.3.0/core/arch/000077500000000000000000000000001464416617300152145ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/000077500000000000000000000000001464416617300157735ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/arm.mk000066400000000000000000000401771464416617300171140ustar00rootroot00000000000000# Setup compiler for the core module ifeq ($(CFG_ARM64_core),y) arch-bits-core := 64 else arch-bits-core := 32 endif CROSS_COMPILE_core := $(CROSS_COMPILE$(arch-bits-core)) COMPILER_core := $(COMPILER) include mk/$(COMPILER_core).mk # Defines the cc-option macro using the compiler set for the core module include mk/cc-option.mk # Size of emulated TrustZone protected SRAM, 448 kB. # Only applicable when paging is enabled. CFG_CORE_TZSRAM_EMUL_SIZE ?= 458752 ifneq ($(CFG_LPAE_ADDR_SPACE_SIZE),) $(warning Error: CFG_LPAE_ADDR_SPACE_SIZE is not supported any longer) $(error Error: Please use CFG_LPAE_ADDR_SPACE_BITS instead) endif CFG_LPAE_ADDR_SPACE_BITS ?= 32 CFG_MMAP_REGIONS ?= 13 CFG_RESERVED_VASPACE_SIZE ?= (1024 * 1024 * 10) ifeq ($(CFG_ARM64_core),y) ifeq ($(CFG_ARM32_core),y) $(error CFG_ARM64_core and CFG_ARM32_core cannot be both 'y') endif CFG_KERN_LINKER_FORMAT ?= elf64-littleaarch64 CFG_KERN_LINKER_ARCH ?= aarch64 # TCR_EL1.IPS needs to be initialized according to the largest physical # address that we need to map. # Physical address size # 32 bits, 4GB. # 36 bits, 64GB. # (etc.) CFG_CORE_ARM64_PA_BITS ?= 32 $(call force,CFG_WITH_LPAE,y) else $(call force,CFG_ARM32_core,y) CFG_KERN_LINKER_FORMAT ?= elf32-littlearm CFG_KERN_LINKER_ARCH ?= arm endif ifeq ($(CFG_TA_FLOAT_SUPPORT),y) # Use hard-float for floating point support in user TAs instead of # soft-float CFG_WITH_VFP ?= y ifeq ($(CFG_ARM64_core),y) # AArch64 has no fallback to soft-float $(call force,CFG_WITH_VFP,y) endif ifeq ($(CFG_WITH_VFP),y) arm64-platform-hard-float-enabled := y ifneq ($(CFG_TA_ARM32_NO_HARD_FLOAT_SUPPORT),y) arm32-platform-hard-float-enabled := y endif endif endif # Adds protection against CVE-2017-5715 also know as Spectre # (https://spectreattack.com) # See also https://developer.arm.com/-/media/Files/pdf/Cache_Speculation_Side-channels.pdf # Variant 2 CFG_CORE_WORKAROUND_SPECTRE_BP ?= y # Same as CFG_CORE_WORKAROUND_SPECTRE_BP but targeting exceptions from # secure EL0 instead of non-secure world, including mitigation for # CVE-2022-23960. CFG_CORE_WORKAROUND_SPECTRE_BP_SEC ?= $(CFG_CORE_WORKAROUND_SPECTRE_BP) # Adds protection against a tool like Cachegrab # (https://github.com/nccgroup/cachegrab), which uses non-secure interrupts # to prime and later analyze the L1D, L1I and BTB caches to gain # information from secure world execution. CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME ?= y ifeq ($(CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME),y) $(call force,CFG_CORE_WORKAROUND_SPECTRE_BP,y,Required by CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME) endif # Adds workarounds against if ARM core is configured with Non-maskable FIQ # (NMFI) support. This is indicated by SCTLR.NMFI being true. NMFI cannot be # disabled by software and as it affects atomic context end result will be # prohibiting FIQ signal usage in OP-TEE and applying some tweaks to make sure # FIQ is enabled in critical places. CFG_CORE_WORKAROUND_ARM_NMFI ?= n CFG_CORE_RWDATA_NOEXEC ?= y CFG_CORE_RODATA_NOEXEC ?= n ifeq ($(CFG_CORE_RODATA_NOEXEC),y) $(call force,CFG_CORE_RWDATA_NOEXEC,y) endif # 'y' to set the Alignment Check Enable bit in SCTLR/SCTLR_EL1, 'n' to clear it CFG_SCTLR_ALIGNMENT_CHECK ?= n ifeq ($(CFG_CORE_LARGE_PHYS_ADDR),y) $(call force,CFG_WITH_LPAE,y) endif # SPMC configuration "S-EL1 SPMC" where SPM Core is implemented at S-EL1, # that is, OP-TEE. ifeq ($(CFG_CORE_SEL1_SPMC),y) $(call force,CFG_CORE_FFA,y) $(call force,CFG_CORE_SEL2_SPMC,n) $(call force,CFG_CORE_EL3_SPMC,n) endif # SPMC configuration "S-EL2 SPMC" where SPM Core is implemented at S-EL2, # that is, the hypervisor sandboxing OP-TEE ifeq ($(CFG_CORE_SEL2_SPMC),y) $(call force,CFG_CORE_FFA,y) $(call force,CFG_CORE_SEL1_SPMC,n) $(call force,CFG_CORE_EL3_SPMC,n) CFG_CORE_HAFNIUM_INTC ?= y # Enable support in OP-TEE to relocate itself to allow it to run from a # physical address that differs from the link address CFG_CORE_PHYS_RELOCATABLE ?= y endif # SPMC configuration "EL3 SPMC" where SPM Core is implemented at EL3, that # is, in TF-A ifeq ($(CFG_CORE_EL3_SPMC),y) $(call force,CFG_CORE_FFA,y) $(call force,CFG_CORE_SEL2_SPMC,n) $(call force,CFG_CORE_SEL1_SPMC,n) endif ifeq ($(CFG_CORE_FFA),y) ifneq ($(CFG_DT),y) $(error CFG_CORE_FFA depends on CFG_DT) endif ifneq ($(CFG_ARM64_core),y) $(error CFG_CORE_FFA depends on CFG_ARM64_core) endif endif ifeq ($(CFG_CORE_PHYS_RELOCATABLE)-$(CFG_WITH_PAGER),y-y) $(error CFG_CORE_PHYS_RELOCATABLE and CFG_WITH_PAGER are not compatible) endif ifeq ($(CFG_CORE_PHYS_RELOCATABLE),y) ifneq ($(CFG_CORE_SEL2_SPMC),y) $(error CFG_CORE_PHYS_RELOCATABLE depends on CFG_CORE_SEL2_SPMC) endif endif ifeq ($(CFG_CORE_FFA)-$(CFG_WITH_PAGER),y-y) $(error CFG_CORE_FFA and CFG_WITH_PAGER are not compatible) endif ifeq ($(CFG_GIC),y) ifeq ($(CFG_ARM_GICV3),y) $(call force,CFG_CORE_IRQ_IS_NATIVE_INTR,y) else $(call force,CFG_CORE_IRQ_IS_NATIVE_INTR,n) endif endif CFG_CORE_HAFNIUM_INTC ?= n ifeq ($(CFG_CORE_HAFNIUM_INTC),y) $(call force,CFG_CORE_IRQ_IS_NATIVE_INTR,y) endif # Selects if IRQ is used to signal native interrupt # if CFG_CORE_IRQ_IS_NATIVE_INTR == y: # IRQ signals a native interrupt pending # FIQ signals a foreign non-secure interrupt or a managed exit pending # else: (vice versa) # IRQ signals a foreign non-secure interrupt or a managed exit pending # FIQ signals a native interrupt pending CFG_CORE_IRQ_IS_NATIVE_INTR ?= n # Unmaps all kernel mode code except the code needed to take exceptions # from user space and restore kernel mode mapping again. This gives more # strict control over what is accessible while in user mode. # Addresses CVE-2017-5715 (aka Meltdown) known to affect Arm Cortex-A75 CFG_CORE_UNMAP_CORE_AT_EL0 ?= y # Initialize PMCR.DP to 1 to prohibit cycle counting in secure state, and # save/restore PMCR during world switch. CFG_SM_NO_CYCLE_COUNTING ?= y # CFG_CORE_ASYNC_NOTIF_GIC_INTID is defined by the platform to some free # interrupt. Setting it to a non-zero number enables support for using an # Arm-GIC to notify normal world. This config variable should use a value # larger or equal to 24 to make it of the type SPI or PPI (secure PPI # only). # Note that asynchronous notifactions must be enabled with # CFG_CORE_ASYNC_NOTIF=y for this variable to be used. CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 0 ifeq ($(CFG_ARM32_core),y) # Configration directive related to ARMv7 optee boot arguments. # CFG_PAGEABLE_ADDR: if defined, forces pageable data physical address. # CFG_NS_ENTRY_ADDR: if defined, forces NS World physical entry address. # CFG_DT_ADDR: if defined, forces Device Tree data physical address. endif # CFG_MAX_CACHE_LINE_SHIFT is used to define platform specific maximum cache # line size in address lines. This must cover all inner and outer cache levels. # When data is aligned with this and cache operations are performed then those # only affect correct data. # # Default value (6 lines or 64 bytes) should cover most architectures, override # this in platform config if different. CFG_MAX_CACHE_LINE_SHIFT ?= 6 core-platform-cppflags += -I$(arch-dir)/include core-platform-subdirs += \ $(addprefix $(arch-dir)/, kernel crypto mm tee) $(platform-dir) ifneq ($(CFG_WITH_ARM_TRUSTED_FW),y) core-platform-subdirs += $(arch-dir)/sm endif arm64-platform-cppflags += -DARM64=1 -D__LP64__=1 arm32-platform-cppflags += -DARM32=1 -D__ILP32__=1 platform-cflags-generic ?= -ffunction-sections -fdata-sections -pipe platform-aflags-generic ?= -pipe arm32-platform-aflags += -marm arm32-platform-cflags-no-hard-float ?= -mfloat-abi=soft arm32-platform-cflags-hard-float ?= -mfloat-abi=hard -funsafe-math-optimizations arm32-platform-cflags-generic-thumb ?= -mthumb \ -fno-short-enums -fno-common -mno-unaligned-access arm32-platform-cflags-generic-arm ?= -marm -fno-omit-frame-pointer -mapcs \ -fno-short-enums -fno-common -mno-unaligned-access arm32-platform-aflags-no-hard-float ?= arm64-platform-cflags-no-hard-float ?= -mgeneral-regs-only arm64-platform-cflags-hard-float ?= arm64-platform-cflags-generic := -mstrict-align $(call cc-option,-mno-outline-atomics,) ifeq ($(CFG_MEMTAG),y) arm64-platform-cflags += -march=armv8.5-a+memtag arm64-platform-aflags += -march=armv8.5-a+memtag endif platform-cflags-optimization ?= -O$(CFG_CC_OPT_LEVEL) ifeq ($(CFG_DEBUG_INFO),y) platform-cflags-debug-info ?= -g3 platform-aflags-debug-info ?= -g endif core-platform-cflags += $(platform-cflags-optimization) core-platform-cflags += $(platform-cflags-generic) core-platform-cflags += $(platform-cflags-debug-info) core-platform-aflags += $(platform-aflags-generic) core-platform-aflags += $(platform-aflags-debug-info) ifeq ($(call cfg-one-enabled, CFG_CORE_ASLR CFG_CORE_PHYS_RELOCATABLE),y) core-platform-cflags += -fpie endif ifeq ($(CFG_CORE_PAUTH),y) bp-core-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf) endif ifeq ($(CFG_CORE_BTI),y) bp-core-opt := $(call cc-option,-mbranch-protection=bti) endif ifeq (y-y,$(CFG_CORE_PAUTH)-$(CFG_CORE_BTI)) bp-core-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf+bti) endif ifeq (y,$(filter $(CFG_CORE_BTI) $(CFG_CORE_PAUTH),y)) ifeq (,$(bp-core-opt)) $(error -mbranch-protection not supported) endif core-platform-cflags += $(bp-core-opt) endif ifeq ($(CFG_ARM64_core),y) core-platform-cppflags += $(arm64-platform-cppflags) core-platform-cflags += $(arm64-platform-cflags) core-platform-cflags += $(arm64-platform-cflags-generic) core-platform-cflags += $(arm64-platform-cflags-no-hard-float) core-platform-aflags += $(arm64-platform-aflags) else core-platform-cppflags += $(arm32-platform-cppflags) core-platform-cflags += $(arm32-platform-cflags) core-platform-cflags += $(arm32-platform-cflags-no-hard-float) ifeq ($(CFG_UNWIND),y) core-platform-cflags += -funwind-tables endif ifeq ($(CFG_SYSCALL_FTRACE),y) core-platform-cflags += $(arm32-platform-cflags-generic-arm) else core-platform-cflags += $(arm32-platform-cflags-generic-thumb) endif core-platform-aflags += $(core_arm32-platform-aflags) core-platform-aflags += $(arm32-platform-aflags) endif # Provide default supported-ta-targets if not set by the platform config ifeq (,$(supported-ta-targets)) supported-ta-targets = ta_arm32 ifeq ($(CFG_ARM64_core),y) supported-ta-targets += ta_arm64 endif endif ta-targets := $(if $(CFG_USER_TA_TARGETS),$(filter $(supported-ta-targets),$(CFG_USER_TA_TARGETS)),$(supported-ta-targets)) unsup-targets := $(filter-out $(ta-targets),$(CFG_USER_TA_TARGETS)) ifneq (,$(unsup-targets)) $(error CFG_USER_TA_TARGETS contains unsupported value(s): $(unsup-targets). Valid values: $(supported-ta-targets)) endif ifneq ($(filter ta_arm32,$(ta-targets)),) # Variables for ta-target/sm "ta_arm32" CFG_ARM32_ta_arm32 := y arch-bits-ta_arm32 := 32 ta_arm32-platform-cppflags += $(arm32-platform-cppflags) ta_arm32-platform-cflags += $(arm32-platform-cflags) ta_arm32-platform-cflags += $(platform-cflags-optimization) ta_arm32-platform-cflags += $(platform-cflags-debug-info) ta_arm32-platform-cflags += -fpic # Thumb mode doesn't support function graph tracing due to missing # frame pointer support required to trace function call chain. So # rather compile in ARM mode if function tracing is enabled. ifeq ($(CFG_FTRACE_SUPPORT),y) ta_arm32-platform-cflags += $(arm32-platform-cflags-generic-arm) else ta_arm32-platform-cflags += $(arm32-platform-cflags-generic-thumb) endif ifeq ($(arm32-platform-hard-float-enabled),y) ta_arm32-platform-cflags += $(arm32-platform-cflags-hard-float) else ta_arm32-platform-cflags += $(arm32-platform-cflags-no-hard-float) endif ifeq ($(CFG_UNWIND),y) ta_arm32-platform-cflags += -funwind-tables endif ta_arm32-platform-aflags += $(platform-aflags-generic) ta_arm32-platform-aflags += $(platform-aflags-debug-info) ta_arm32-platform-aflags += $(arm32-platform-aflags) ta_arm32-platform-cxxflags += -fpic ta_arm32-platform-cxxflags += $(arm32-platform-cxxflags) ta_arm32-platform-cxxflags += $(platform-cflags-optimization) ta_arm32-platform-cxxflags += $(platform-cflags-debug-info) ifeq ($(arm32-platform-hard-float-enabled),y) ta_arm32-platform-cxxflags += $(arm32-platform-cflags-hard-float) else ta_arm32-platform-cxxflags += $(arm32-platform-cflags-no-hard-float) endif ta-mk-file-export-vars-ta_arm32 += CFG_ARM32_ta_arm32 ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-cppflags ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-cflags ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-aflags ta-mk-file-export-vars-ta_arm32 += ta_arm32-platform-cxxflags ta-mk-file-export-add-ta_arm32 += CROSS_COMPILE ?= arm-linux-gnueabihf-_nl_ ta-mk-file-export-add-ta_arm32 += CROSS_COMPILE32 ?= $$(CROSS_COMPILE)_nl_ ta-mk-file-export-add-ta_arm32 += CROSS_COMPILE_ta_arm32 ?= $$(CROSS_COMPILE32)_nl_ ta-mk-file-export-add-ta_arm32 += COMPILER ?= gcc_nl_ ta-mk-file-export-add-ta_arm32 += COMPILER_ta_arm32 ?= $$(COMPILER)_nl_ ta-mk-file-export-add-ta_arm32 += PYTHON3 ?= python3_nl_ endif ifneq ($(filter ta_arm64,$(ta-targets)),) # Variables for ta-target/sm "ta_arm64" CFG_ARM64_ta_arm64 := y arch-bits-ta_arm64 := 64 ta_arm64-platform-cppflags += $(arm64-platform-cppflags) ta_arm64-platform-cflags += $(arm64-platform-cflags) ta_arm64-platform-cflags += $(platform-cflags-optimization) ta_arm64-platform-cflags += $(platform-cflags-debug-info) ta_arm64-platform-cflags += -fpic ta_arm64-platform-cflags += $(arm64-platform-cflags-generic) ifeq ($(arm64-platform-hard-float-enabled),y) ta_arm64-platform-cflags += $(arm64-platform-cflags-hard-float) else ta_arm64-platform-cflags += $(arm64-platform-cflags-no-hard-float) endif ta_arm64-platform-aflags += $(platform-aflags-generic) ta_arm64-platform-aflags += $(platform-aflags-debug-info) ta_arm64-platform-aflags += $(arm64-platform-aflags) ta_arm64-platform-cxxflags += -fpic ta_arm64-platform-cxxflags += $(platform-cflags-optimization) ta_arm64-platform-cxxflags += $(platform-cflags-debug-info) ifeq ($(CFG_TA_PAUTH),y) bp-ta-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf) endif ifeq ($(CFG_TA_BTI),y) bp-ta-opt := $(call cc-option,-mbranch-protection=bti) endif ifeq (y-y,$(CFG_TA_PAUTH)-$(CFG_TA_BTI)) bp-ta-opt := $(call cc-option,-mbranch-protection=pac-ret+leaf+bti) endif ifeq (y,$(filter $(CFG_TA_BTI) $(CFG_TA_PAUTH),y)) ifeq (,$(bp-ta-opt)) $(error -mbranch-protection not supported) endif ta_arm64-platform-cflags += $(bp-ta-opt) endif ta-mk-file-export-vars-ta_arm64 += CFG_ARM64_ta_arm64 ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-cppflags ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-cflags ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-aflags ta-mk-file-export-vars-ta_arm64 += ta_arm64-platform-cxxflags ta-mk-file-export-add-ta_arm64 += CROSS_COMPILE64 ?= $$(CROSS_COMPILE)_nl_ ta-mk-file-export-add-ta_arm64 += CROSS_COMPILE_ta_arm64 ?= $$(CROSS_COMPILE64)_nl_ ta-mk-file-export-add-ta_arm64 += COMPILER ?= gcc_nl_ ta-mk-file-export-add-ta_arm64 += COMPILER_ta_arm64 ?= $$(COMPILER)_nl_ ta-mk-file-export-add-ta_arm64 += PYTHON3 ?= python3_nl_ endif # Set cross compiler prefix for each TA target $(foreach sm, $(ta-targets), $(eval CROSS_COMPILE_$(sm) ?= $(CROSS_COMPILE$(arch-bits-$(sm))))) arm32-sysreg-txt = core/arch/arm/kernel/arm32_sysreg.txt arm32-sysregs-$(arm32-sysreg-txt)-h := arm32_sysreg.h arm32-sysregs-$(arm32-sysreg-txt)-s := arm32_sysreg.S arm32-sysregs += $(arm32-sysreg-txt) ifeq ($(CFG_ARM_GICV3),y) arm32-gicv3-sysreg-txt = core/arch/arm/kernel/arm32_gicv3_sysreg.txt arm32-sysregs-$(arm32-gicv3-sysreg-txt)-h := arm32_gicv3_sysreg.h arm32-sysregs-$(arm32-gicv3-sysreg-txt)-s := arm32_gicv3_sysreg.S arm32-sysregs += $(arm32-gicv3-sysreg-txt) endif arm32-sysregs-out := $(out-dir)/$(sm)/include/generated define process-arm32-sysreg FORCE-GENSRC$(sm): $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-h) cleanfiles := $$(cleanfiles) $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-h) $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-h): $(1) scripts/arm32_sysreg.py @$(cmd-echo-silent) ' GEN $$@' $(q)mkdir -p $$(dir $$@) $(q)scripts/arm32_sysreg.py --guard __$$(arm32-sysregs-$(1)-h) \ < $$< > $$@ FORCE-GENSRC$(sm): $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-s) cleanfiles := $$(cleanfiles) $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-s) $$(arm32-sysregs-out)/$$(arm32-sysregs-$(1)-s): $(1) scripts/arm32_sysreg.py @$(cmd-echo-silent) ' GEN $$@' $(q)mkdir -p $$(dir $$@) $(q)scripts/arm32_sysreg.py --s_file < $$< > $$@ endef #process-arm32-sysreg $(foreach sr, $(arm32-sysregs), $(eval $(call process-arm32-sysreg,$(sr)))) optee_os-4.3.0/core/arch/arm/cpu/000077500000000000000000000000001464416617300165625ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/cpu/cortex-a15.mk000066400000000000000000000006601464416617300210050ustar00rootroot00000000000000$(call force,CFG_ARM32_core,y) $(call force,CFG_ARM64_core,n) $(call force,CFG_HWSUPP_MEM_PERM_WXN,y) $(call force,CFG_HWSUPP_MEM_PERM_PXN,y) arm32-platform-cpuarch := cortex-a15 arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) # Program flow prediction may need manual enablement CFG_ENABLE_SCTLR_Z ?= y optee_os-4.3.0/core/arch/arm/cpu/cortex-a5.mk000066400000000000000000000006561464416617300207310ustar00rootroot00000000000000$(call force,CFG_ARM32_core,y) $(call force,CFG_ARM64_core,n) $(call force,CFG_WITH_LPAE,n) $(call force,CFG_HWSUPP_MEM_PERM_WXN,n) $(call force,CFG_HWSUPP_MEM_PERM_PXN,n) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,n) arm32-platform-cpuarch := cortex-a5 arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) optee_os-4.3.0/core/arch/arm/cpu/cortex-a7.mk000066400000000000000000000006051464416617300207250ustar00rootroot00000000000000$(call force,CFG_ARM32_core,y) $(call force,CFG_ARM64_core,n) $(call force,CFG_HWSUPP_MEM_PERM_WXN,y) $(call force,CFG_HWSUPP_MEM_PERM_PXN,y) $(call force,CFG_ENABLE_SCTLR_Z,n) arm32-platform-cpuarch := cortex-a7 arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) optee_os-4.3.0/core/arch/arm/cpu/cortex-a9.mk000066400000000000000000000007731464416617300207350ustar00rootroot00000000000000$(call force,CFG_ARM32_core,y) $(call force,CFG_ARM64_core,n) $(call force,CFG_WITH_LPAE,n) $(call force,CFG_HWSUPP_MEM_PERM_WXN,n) $(call force,CFG_HWSUPP_MEM_PERM_PXN,n) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,n) arm32-platform-cpuarch := cortex-a9 arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) # Program flow prediction may need manual enablement CFG_ENABLE_SCTLR_Z ?= y optee_os-4.3.0/core/arch/arm/cpu/cortex-armv8-0.mk000066400000000000000000000007031464416617300216070ustar00rootroot00000000000000$(call force,CFG_HWSUPP_MEM_PERM_WXN,y) $(call force,CFG_HWSUPP_MEM_PERM_PXN,y) $(call force,CFG_ENABLE_SCTLR_RR,n) $(call force,CFG_ENABLE_SCTLR_Z,n) # cortex-a53 and cortex-a57 complies on arm32 architectures arm32-platform-cpuarch := cortex-a53 arm32-platform-cflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-aflags += -mcpu=$(arm32-platform-cpuarch) arm32-platform-cxxflags += -mcpu=$(arm32-platform-cpuarch) platform-flavor-armv8 := 1 optee_os-4.3.0/core/arch/arm/crypto/000077500000000000000000000000001464416617300173135ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/crypto/aes-gcm-ce.c000066400000000000000000000142041464416617300213610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include "aes_armv8a_ce.h" static void get_be_block(void *dst, const void *src) { uint64_t *d = dst; d[1] = get_be64(src); d[0] = get_be64((const uint8_t *)src + 8); } static void put_be_block(void *dst, const void *src) { const uint64_t *s = src; put_be64(dst, s[1]); put_be64((uint8_t *)dst + 8, s[0]); } static void ghash_reflect(uint64_t h[2], const uint64_t k[2]) { uint64_t b = get_be64(k); uint64_t a = get_be64(k + 1); h[0] = (a << 1) | (b >> 63); h[1] = (b << 1) | (a >> 63); if (b >> 63) h[1] ^= 0xc200000000000000UL; } void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key) { uint64_t k[2] = { 0 }; uint64_t h[2] = { 0 }; crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), enc_key->rounds, state->ctr, k); ghash_reflect(state->ghash_key.h, k); internal_aes_gcm_gfmul(k, k, h); ghash_reflect(state->ghash_key.h2, h); internal_aes_gcm_gfmul(k, h, h); ghash_reflect(state->ghash_key.h3, h); internal_aes_gcm_gfmul(k, h, h); ghash_reflect(state->ghash_key.h4, h); } static void pmull_ghash_update(int num_blocks, uint64_t dg[2], const uint8_t *src, const struct internal_ghash_key *ghash_key, const uint8_t *head) { #ifdef CFG_HWSUPP_PMULT_64 pmull_ghash_update_p64(num_blocks, dg, src, ghash_key, head); #else pmull_ghash_update_p8(num_blocks, dg, src, ghash_key, head); #endif } void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, const void *head, const void *data, size_t num_blocks) { uint32_t vfp_state; uint64_t dg[2]; get_be_block(dg, state->hash_state); vfp_state = thread_kernel_enable_vfp(); pmull_ghash_update(num_blocks, dg, data, &state->ghash_key, head); thread_kernel_disable_vfp(vfp_state); put_be_block(state->hash_state, dg); } static void encrypt_pl(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, uint64_t dg[2], const uint8_t *src, size_t num_blocks, uint8_t *dst) { void *buf_cryp = state->buf_cryp; while (num_blocks) { ce_aes_xor_block(buf_cryp, buf_cryp, src); pmull_ghash_update(1, dg, buf_cryp, &state->ghash_key, NULL); memcpy(dst, buf_cryp, TEE_AES_BLOCK_SIZE); ce_aes_ecb_encrypt(buf_cryp, (const uint8_t *)state->ctr, (const uint8_t *)ek->data, ek->rounds, 1, 1); internal_aes_gcm_inc_ctr(state); src += TEE_AES_BLOCK_SIZE; dst += TEE_AES_BLOCK_SIZE; num_blocks--; } } static void decrypt_pl(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, uint64_t dg[2], const uint8_t *src, size_t num_blocks, uint8_t *dst) { while (num_blocks) { ce_aes_ctr_encrypt(dst, src, (const uint8_t *)ek->data, ek->rounds, 1, (uint8_t *)state->ctr, 1); pmull_ghash_update(1, dg, src, &state->ghash_key, NULL); src += TEE_AES_BLOCK_SIZE; dst += TEE_AES_BLOCK_SIZE; num_blocks--; } } #ifdef ARM64 static void update_payload_2block(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, uint64_t dg[2], TEE_OperationMode mode, const void *src, size_t num_blocks, void *dst) { assert(num_blocks && !(num_blocks % 2)); if (mode == TEE_MODE_ENCRYPT) { uint8_t ks[sizeof(state->buf_cryp) * 2] = { 0 }; /* * ks holds the encrypted counters of the next two blocks. * pmull_gcm_encrypt() uses this to encrypt the first two * blocks. When pmull_gcm_encrypt() returns is ks updated * with the encrypted counters of the next two blocks. As * we're only keeping one of these blocks we throw away * block number two consequently decreases the counter by * one. */ memcpy(ks, state->buf_cryp, sizeof(state->buf_cryp)); pmull_gcm_load_round_keys(ek->data, ek->rounds); pmull_gcm_encrypt_block(ks + sizeof(state->buf_cryp), (uint8_t *)state->ctr, ek->rounds); internal_aes_gcm_inc_ctr(state); pmull_gcm_encrypt(num_blocks, dg, dst, src, &state->ghash_key, state->ctr, NULL, ek->rounds, ks); memcpy(state->buf_cryp, ks, TEE_AES_BLOCK_SIZE); internal_aes_gcm_dec_ctr(state); } else { pmull_gcm_decrypt(num_blocks, dg, dst, src, &state->ghash_key, state->ctr, ek->data, ek->rounds); } } /* Overriding the __weak function */ void internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, TEE_OperationMode mode, const void *src, size_t num_blocks, void *dst) { size_t nb = ROUNDDOWN(num_blocks, 2); uint32_t vfp_state = 0; uint64_t dg[2] = { 0 }; get_be_block(dg, state->hash_state); vfp_state = thread_kernel_enable_vfp(); /* * pmull_gcm_encrypt() and pmull_gcm_decrypt() can only handle * blocks in multiples of two. */ if (nb) update_payload_2block(state, ek, dg, mode, src, nb, dst); if (nb != num_blocks) { /* There's a final block */ const void *s = (const uint8_t *)src + nb * TEE_AES_BLOCK_SIZE; void *d = (uint8_t *)dst + nb * TEE_AES_BLOCK_SIZE; if (mode == TEE_MODE_ENCRYPT) encrypt_pl(state, ek, dg, s, 1, d); else decrypt_pl(state, ek, dg, s, 1, d); } thread_kernel_disable_vfp(vfp_state); put_be_block(state->hash_state, dg); } #endif /*ARM64*/ #ifdef ARM32 /* Overriding the __weak function */ void internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, TEE_OperationMode mode, const void *src, size_t num_blocks, void *dst) { uint64_t dg[2] = { 0 }; uint32_t vfp_state = 0; assert(!state->buf_pos && num_blocks); get_be_block(dg, state->hash_state); vfp_state = thread_kernel_enable_vfp(); if (mode == TEE_MODE_ENCRYPT) encrypt_pl(state, ek, dg, src, num_blocks, dst); else decrypt_pl(state, ek, dg, src, num_blocks, dst); thread_kernel_disable_vfp(vfp_state); put_be_block(state->hash_state, dg); } #endif optee_os-4.3.0/core/arch/arm/crypto/aes_armv8a_ce.c000066400000000000000000000161351464416617300221620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, 2020 Linaro Limited * Copyright (C) 2013 Linaro Ltd * Copyright (c) 2001-2007, Tom St Denis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* * AES cipher for ARMv8 with Crypto Extensions */ #include #include #include #include #include #include #include "aes_armv8a_ce.h" struct aes_block { uint8_t b[TEE_AES_BLOCK_SIZE]; }; static uint32_t ror32(uint32_t val, unsigned int shift) { return (val >> shift) | (val << (32 - shift)); } static void expand_enc_key(uint32_t *enc_key, size_t key_len) { /* The AES key schedule round constants */ static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, }; unsigned int kwords = key_len / sizeof(uint32_t); unsigned int i = 0; for (i = 0; i < sizeof(rcon); i++) { uint32_t *rki = enc_key + i * kwords; uint32_t *rko = rki + kwords; rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; if (key_len == 24) { if (i >= 7) break; rko[4] = rko[3] ^ rki[4]; rko[5] = rko[4] ^ rki[5]; } else if (key_len == 32) { if (i >= 6) break; rko[4] = ce_aes_sub(rko[3]) ^ rki[4]; rko[5] = rko[4] ^ rki[5]; rko[6] = rko[5] ^ rki[6]; rko[7] = rko[6] ^ rki[7]; } } } static void make_dec_key(unsigned int round_count, const struct aes_block *key_enc, struct aes_block *key_dec) { unsigned int i = 0; unsigned int j = round_count; /* * Generate the decryption keys for the Equivalent Inverse Cipher. * This involves reversing the order of the round keys, and applying * the Inverse Mix Columns transformation on all but the first and * the last ones. */ j = round_count; key_dec[0] = key_enc[j]; for (i = 1, j--; j > 0; i++, j--) ce_aes_invert(key_dec + i, key_enc + j); key_dec[i] = key_enc[0]; } TEE_Result crypto_accel_aes_expand_keys(const void *key, size_t key_len, void *enc_key, void *dec_key, size_t expanded_key_len, unsigned int *round_count) { unsigned int num_rounds = 0; uint32_t vfp_state = 0; if (!key || !enc_key) return TEE_ERROR_BAD_PARAMETERS; if (key_len != 16 && key_len != 24 && key_len != 32) return TEE_ERROR_BAD_PARAMETERS; if (!IS_ALIGNED_WITH_TYPE(enc_key, struct aes_block) || !IS_ALIGNED_WITH_TYPE(dec_key, struct aes_block)) return TEE_ERROR_BAD_PARAMETERS; num_rounds = 10 + ((key_len / 8) - 2) * 2; if (expanded_key_len < (num_rounds + 1) * sizeof(struct aes_block)) return TEE_ERROR_BAD_PARAMETERS; *round_count = num_rounds; memset(enc_key, 0, expanded_key_len); memcpy(enc_key, key, key_len); vfp_state = thread_kernel_enable_vfp(); expand_enc_key(enc_key, key_len); if (dec_key) make_dec_key(num_rounds, enc_key, dec_key); thread_kernel_disable_vfp(vfp_state); return TEE_SUCCESS; } void crypto_accel_aes_ecb_enc(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count) { uint32_t vfp_state = 0; assert(out && in && key); vfp_state = thread_kernel_enable_vfp(); ce_aes_ecb_encrypt(out, in, key, round_count, block_count, 1); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_aes_ecb_dec(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count) { uint32_t vfp_state = 0; assert(out && in && key); vfp_state = thread_kernel_enable_vfp(); ce_aes_ecb_decrypt(out, in, key, round_count, block_count, 1); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_aes_cbc_enc(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && iv); vfp_state = thread_kernel_enable_vfp(); ce_aes_cbc_encrypt(out, in, key, round_count, block_count, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_aes_cbc_dec(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && iv); vfp_state = thread_kernel_enable_vfp(); ce_aes_cbc_decrypt(out, in, key, round_count, block_count, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_aes_ctr_be_enc(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && iv); vfp_state = thread_kernel_enable_vfp(); ce_aes_ctr_encrypt(out, in, key, round_count, block_count, iv, 1); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_aes_xts_enc(void *out, const void *in, const void *key1, unsigned int round_count, unsigned int block_count, const void *key2, void *tweak) { uint32_t vfp_state = 0; assert(out && in && key1 && key2 && tweak); vfp_state = thread_kernel_enable_vfp(); ce_aes_xts_encrypt(out, in, key1, round_count, block_count, key2, tweak); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_aes_xts_dec(void *out, const void *in, const void *key1, unsigned int round_count, unsigned int block_count, const void *key2, void *tweak) { uint32_t vfp_state = 0; assert(out && in && key1 && key2 && tweak); vfp_state = thread_kernel_enable_vfp(); ce_aes_xts_decrypt(out, in, key1, round_count, block_count, key2, tweak); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/aes_armv8a_ce.h000066400000000000000000000024221464416617300221610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020 Linaro Limited */ #ifndef __AES_ARMV8_CE_H #define __AES_ARMV8_CE_H #include /* Prototypes for assembly functions */ uint32_t ce_aes_sub(uint32_t in); void ce_aes_invert(void *dst, const void *src); void ce_aes_ecb_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], int rounds, int blocks, int first); void ce_aes_ecb_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], int rounds, int blocks, int first); void ce_aes_cbc_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], int rounds, int blocks, uint8_t iv[]); void ce_aes_cbc_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], int rounds, int blocks, uint8_t iv[]); void ce_aes_ctr_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], int rounds, int blocks, uint8_t ctr[], int first); void ce_aes_xts_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], int rounds, int blocks, uint8_t const rk2[], uint8_t iv[]); void ce_aes_xts_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], int rounds, int blocks, uint8_t const rk2[], uint8_t iv[]); void ce_aes_xor_block(uint8_t out[], uint8_t const op1[], uint8_t const op2[]); #endif /*__AES_ARMV8_CE_H*/ optee_os-4.3.0/core/arch/arm/crypto/aes_modes_armv8a_ce_a32.S000066400000000000000000000257351464416617300240040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, 2020 Linaro Limited * Copyright (C) 2015 Linaro Ltd * * aes-ce-core.S - AES in CBC/CTR/XTS mode using ARMv8 Crypto Extensions */ #include .fpu crypto-neon-fp-armv8 .macro enc_round, state, key aese.8 \state, \key aesmc.8 \state, \state .endm .macro dec_round, state, key aesd.8 \state, \key aesimc.8 \state, \state .endm .macro enc_dround, key1, key2 enc_round q0, \key1 enc_round q0, \key2 .endm .macro dec_dround, key1, key2 dec_round q0, \key1 dec_round q0, \key2 .endm .macro enc_fround, key1, key2, key3 enc_round q0, \key1 aese.8 q0, \key2 veor q0, q0, \key3 .endm .macro dec_fround, key1, key2, key3 dec_round q0, \key1 aesd.8 q0, \key2 veor q0, q0, \key3 .endm .macro enc_dround_3x, key1, key2 enc_round q0, \key1 enc_round q1, \key1 enc_round q2, \key1 enc_round q0, \key2 enc_round q1, \key2 enc_round q2, \key2 .endm .macro dec_dround_3x, key1, key2 dec_round q0, \key1 dec_round q1, \key1 dec_round q2, \key1 dec_round q0, \key2 dec_round q1, \key2 dec_round q2, \key2 .endm .macro enc_fround_3x, key1, key2, key3 enc_round q0, \key1 enc_round q1, \key1 enc_round q2, \key1 aese.8 q0, \key2 aese.8 q1, \key2 aese.8 q2, \key2 veor q0, q0, \key3 veor q1, q1, \key3 veor q2, q2, \key3 .endm .macro dec_fround_3x, key1, key2, key3 dec_round q0, \key1 dec_round q1, \key1 dec_round q2, \key1 aesd.8 q0, \key2 aesd.8 q1, \key2 aesd.8 q2, \key2 veor q0, q0, \key3 veor q1, q1, \key3 veor q2, q2, \key3 .endm .macro do_block, dround, fround cmp r3, #12 @ which key size? vld1.8 {q10-q11}, [ip]! \dround q8, q9 vld1.8 {q12-q13}, [ip]! \dround q10, q11 vld1.8 {q10-q11}, [ip]! \dround q12, q13 vld1.8 {q12-q13}, [ip]! \dround q10, q11 blo 0f @ AES-128: 10 rounds vld1.8 {q10-q11}, [ip]! \dround q12, q13 beq 1f @ AES-192: 12 rounds vld1.8 {q12-q13}, [ip] \dround q10, q11 0: \fround q12, q13, q14 bx lr 1: \fround q10, q11, q14 bx lr .endm /* * Internal, non-AAPCS compliant functions that implement the core * AES transforms. These should preserve all registers except q0 - * q2 and ip. * Arguments: * q0 : first in/output block * q1 : second in/output block (_3x version only) * q2 : third in/output block (_3x version only) * q8 : first round key * q9 : secound round key * q14 : final round key * r2 : address of round key array * r3 : number of rounds */ .section .text.ce_aes_helpers .align 6 aes_encrypt: add ip, r2, #32 @ 3rd round key .Laes_encrypt_tweak: do_block enc_dround, enc_fround .align 6 aes_decrypt: add ip, r2, #32 @ 3rd round key do_block dec_dround, dec_fround .align 6 aes_encrypt_3x: add ip, r2, #32 @ 3rd round key do_block enc_dround_3x, enc_fround_3x .align 6 aes_decrypt_3x: add ip, r2, #32 @ 3rd round key do_block dec_dround_3x, dec_fround_3x .macro prepare_key, rk, rounds add ip, \rk, \rounds, lsl #4 vld1.8 {q8-q9}, [\rk] @ load first 2 round keys vld1.8 {q14}, [ip] @ load last round key .endm /* * void ce_aes_ecb_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * int first) */ FUNC ce_aes_ecb_encrypt , : push {r4, lr} ldr r4, [sp, #8] prepare_key r2, r3 .Lecbencloop3x: subs r4, r4, #3 bmi .Lecbenc1x vld1.8 {q0-q1}, [r1]! vld1.8 {q2}, [r1]! bl aes_encrypt_3x vst1.8 {q0-q1}, [r0]! vst1.8 {q2}, [r0]! b .Lecbencloop3x .Lecbenc1x: adds r4, r4, #3 beq .Lecbencout .Lecbencloop: vld1.8 {q0}, [r1]! bl aes_encrypt vst1.8 {q0}, [r0]! subs r4, r4, #1 bne .Lecbencloop .Lecbencout: pop {r4, pc} END_FUNC ce_aes_ecb_encrypt /* * void ce_aes_ecb_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * int first) */ FUNC ce_aes_ecb_decrypt , : push {r4, lr} ldr r4, [sp, #8] prepare_key r2, r3 .Lecbdecloop3x: subs r4, r4, #3 bmi .Lecbdec1x vld1.8 {q0-q1}, [r1]! vld1.8 {q2}, [r1]! bl aes_decrypt_3x vst1.8 {q0-q1}, [r0]! vst1.8 {q2}, [r0]! b .Lecbdecloop3x .Lecbdec1x: adds r4, r4, #3 beq .Lecbdecout .Lecbdecloop: vld1.8 {q0}, [r1]! bl aes_decrypt vst1.8 {q0}, [r0]! subs r4, r4, #1 bne .Lecbdecloop .Lecbdecout: pop {r4, pc} END_FUNC ce_aes_ecb_decrypt /* * void ce_aes_cbc_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * uint8_t iv[]) */ FUNC ce_aes_cbc_encrypt , : push {r4-r6, lr} ldrd r4, r5, [sp, #16] vld1.8 {q0}, [r5] prepare_key r2, r3 .Lcbcencloop: vld1.8 {q1}, [r1]! @ get next pt block veor q0, q0, q1 @ ..and xor with iv bl aes_encrypt vst1.8 {q0}, [r0]! subs r4, r4, #1 bne .Lcbcencloop vst1.8 {q0}, [r5] pop {r4-r6, pc} END_FUNC ce_aes_cbc_encrypt /* * void ce_aes_cbc_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * uint8_t iv[]) */ FUNC ce_aes_cbc_decrypt , : push {r4-r6, lr} ldrd r4, r5, [sp, #16] vld1.8 {q6}, [r5] @ keep iv in q6 prepare_key r2, r3 .Lcbcdecloop3x: subs r4, r4, #3 bmi .Lcbcdec1x vld1.8 {q0-q1}, [r1]! vld1.8 {q2}, [r1]! vmov q3, q0 vmov q4, q1 vmov q5, q2 bl aes_decrypt_3x veor q0, q0, q6 veor q1, q1, q3 veor q2, q2, q4 vmov q6, q5 vst1.8 {q0-q1}, [r0]! vst1.8 {q2}, [r0]! b .Lcbcdecloop3x .Lcbcdec1x: adds r4, r4, #3 beq .Lcbcdecout vmov q15, q14 @ preserve last round key .Lcbcdecloop: vld1.8 {q0}, [r1]! @ get next ct block veor q14, q15, q6 @ combine prev ct with last key vmov q6, q0 bl aes_decrypt vst1.8 {q0}, [r0]! subs r4, r4, #1 bne .Lcbcdecloop .Lcbcdecout: vst1.8 {q6}, [r5] @ keep iv in q6 pop {r4-r6, pc} END_FUNC ce_aes_cbc_decrypt /* * void ce_aes_ctr_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * uint8_t ctr[], int first) */ FUNC ce_aes_ctr_encrypt , : push {r4-r6, lr} ldrd r4, r5, [sp, #16] vld1.8 {q6}, [r5] @ load ctr prepare_key r2, r3 vmov r6, s27 @ keep swabbed ctr in r6 rev r6, r6 cmn r6, r4 @ 32 bit overflow? bcs .Lctrloop .Lctrloop3x: subs r4, r4, #3 bmi .Lctr1x add r6, r6, #1 vmov q0, q6 vmov q1, q6 rev ip, r6 add r6, r6, #1 vmov q2, q6 vmov s7, ip rev ip, r6 add r6, r6, #1 vmov s11, ip vld1.8 {q3-q4}, [r1]! vld1.8 {q5}, [r1]! bl aes_encrypt_3x veor q0, q0, q3 veor q1, q1, q4 veor q2, q2, q5 rev ip, r6 vst1.8 {q0-q1}, [r0]! vst1.8 {q2}, [r0]! vmov s27, ip b .Lctrloop3x .Lctr1x: adds r4, r4, #3 beq .Lctrout .Lctrloop: vmov q0, q6 bl aes_encrypt subs r4, r4, #1 bmi .Lctrtailblock @ blocks < 0 means tail block vld1.8 {q3}, [r1]! veor q3, q0, q3 vst1.8 {q3}, [r0]! adds r6, r6, #1 @ increment BE ctr rev ip, r6 vmov s27, ip bcs .Lctrcarry teq r4, #0 bne .Lctrloop .Lctrout: vst1.8 {q6}, [r5] pop {r4-r6, pc} .Lctrtailblock: vst1.8 {q0}, [r0, :64] @ return just the key stream pop {r4-r6, pc} .Lctrcarry: .irp sreg, s26, s25, s24 vmov ip, \sreg @ load next word of ctr rev ip, ip @ ... to handle the carry adds ip, ip, #1 rev ip, ip vmov \sreg, ip bcc 0f .endr 0: teq r4, #0 beq .Lctrout b .Lctrloop END_FUNC ce_aes_ctr_encrypt /* * void ce_aes_xts_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], int rounds, int blocks, * uint8_t const rk2[], uint8_t iv[]) * void ce_aes_xts_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], int rounds, int blocks, * uint8_t const rk2[], uint8_t iv[]); */ .macro next_tweak, out, in, const, tmp vshr.s64 \tmp, \in, #63 vand \tmp, \tmp, \const vadd.u64 \out, \in, \in vext.8 \tmp, \tmp, \tmp, #8 veor \out, \out, \tmp .endm LOCAL_FUNC ce_aes_xts_init , : vldr d14, .Lxts_mul_x vldr d15, .Lxts_mul_x + 8 ldr r4, [sp, #16] @ load args ldr r5, [sp, #24] vld1.8 {q0}, [r5] @ load iv @ Encrypt the IV in q0 with the second AES key. This should only @ be done at the start of a block. ldr r6, [sp, #20] @ load AES key 2 prepare_key r6, r3 add ip, r6, #32 @ 3rd round key of key 2 b .Laes_encrypt_tweak @ tail call .align 3 .Lxts_mul_x: .quad 1, 0x87 END_FUNC ce_aes_xts_init FUNC ce_aes_xts_encrypt , : push {r4-r6, lr} bl ce_aes_xts_init @ run shared prologue prepare_key r2, r3 vmov q3, q0 teq r6, #0 @ start of a block? bne .Lxtsenc3x .Lxtsencloop3x: next_tweak q3, q3, q7, q6 .Lxtsenc3x: subs r4, r4, #3 bmi .Lxtsenc1x vld1.8 {q0-q1}, [r1]! @ get 3 pt blocks vld1.8 {q2}, [r1]! next_tweak q4, q3, q7, q6 veor q0, q0, q3 next_tweak q5, q4, q7, q6 veor q1, q1, q4 veor q2, q2, q5 bl aes_encrypt_3x veor q0, q0, q3 veor q1, q1, q4 veor q2, q2, q5 vst1.8 {q0-q1}, [r0]! @ write 3 ct blocks vst1.8 {q2}, [r0]! vmov q3, q5 teq r4, #0 beq .Lxtsencout b .Lxtsencloop3x .Lxtsenc1x: adds r4, r4, #3 beq .Lxtsencout .Lxtsencloop: vld1.8 {q0}, [r1]! veor q0, q0, q3 bl aes_encrypt veor q0, q0, q3 vst1.8 {q0}, [r0]! subs r4, r4, #1 beq .Lxtsencout next_tweak q3, q3, q7, q6 b .Lxtsencloop .Lxtsencout: next_tweak q3, q3, q7, q6 vst1.8 {q3}, [r5] pop {r4-r6, pc} END_FUNC ce_aes_xts_encrypt FUNC ce_aes_xts_decrypt , : push {r4-r6, lr} bl ce_aes_xts_init @ run shared prologue prepare_key r2, r3 vmov q3, q0 teq r6, #0 @ start of a block? bne .Lxtsdec3x .Lxtsdecloop3x: next_tweak q3, q3, q7, q6 .Lxtsdec3x: subs r4, r4, #3 bmi .Lxtsdec1x vld1.8 {q0-q1}, [r1]! @ get 3 ct blocks vld1.8 {q2}, [r1]! next_tweak q4, q3, q7, q6 veor q0, q0, q3 next_tweak q5, q4, q7, q6 veor q1, q1, q4 veor q2, q2, q5 bl aes_decrypt_3x veor q0, q0, q3 veor q1, q1, q4 veor q2, q2, q5 vst1.8 {q0-q1}, [r0]! @ write 3 pt blocks vst1.8 {q2}, [r0]! vmov q3, q5 teq r4, #0 beq .Lxtsdecout b .Lxtsdecloop3x .Lxtsdec1x: adds r4, r4, #3 beq .Lxtsdecout .Lxtsdecloop: vld1.8 {q0}, [r1]! veor q0, q0, q3 add ip, r2, #32 @ 3rd round key bl aes_decrypt veor q0, q0, q3 vst1.8 {q0}, [r0]! subs r4, r4, #1 beq .Lxtsdecout next_tweak q3, q3, q7, q6 b .Lxtsdecloop .Lxtsdecout: next_tweak q3, q3, q7, q6 vst1.8 {q3}, [r5] pop {r4-r6, pc} END_FUNC ce_aes_xts_decrypt /* * u32 ce_aes_sub(u32 input) - use the aese instruction to perform the * AES sbox substitution on each byte in * 'input' */ FUNC ce_aes_sub , : vdup.32 q1, r0 veor q0, q0, q0 aese.8 q0, q1 vmov r0, s0 bx lr END_FUNC ce_aes_sub /* * void ce_aes_invert(void *dst, const void *src) * * perform the Inverse MixColumns operation on round key in */ FUNC ce_aes_invert , : vld1.8 {q0}, [r1] aesimc.8 q0, q0 vst1.8 {q0}, [r0] bx lr END_FUNC ce_aes_invert /* * void ce_aes_xor_block(uint8_t out[], uint8_t const op1[], * uint8_t const op2[]); */ FUNC ce_aes_xor_block , : vld1.8 {q0}, [r1] vld1.8 {q1}, [r2] veor q0, q0, q1 vst1.8 {q0}, [r0] bx lr END_FUNC ce_aes_xor_block optee_os-4.3.0/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S000066400000000000000000000401521464416617300237770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, 2020 Linaro Limited * Copyright (C) 2013 Linaro Ltd * * - AES cipher for ARMv8 with Crypto Extensions * - Chaining mode wrappers for AES */ #include .arch armv8-a+crypto /* Preload all round keys */ .macro load_round_keys, rounds, rk cmp \rounds, #12 blo 2222f /* 128 bits */ beq 1111f /* 192 bits */ ld1 {v17.16b-v18.16b}, [\rk], #32 1111: ld1 {v19.16b-v20.16b}, [\rk], #32 2222: ld1 {v21.16b-v24.16b}, [\rk], #64 ld1 {v25.16b-v28.16b}, [\rk], #64 ld1 {v29.16b-v31.16b}, [\rk] .endm /* Prepare for encryption with key in rk[] */ .macro enc_prepare, rounds, rk, ignore load_round_keys \rounds, \rk .endm /* Prepare for encryption (again) but with new key in rk[] */ .macro enc_switch_key, rounds, rk, ignore load_round_keys \rounds, \rk .endm /* Prepare for decryption with key in rk[] */ .macro dec_prepare, rounds, rk, ignore load_round_keys \rounds, \rk .endm .macro do_enc_Nx, de, mc, k, i0, i1, i2, i3 aes\de \i0\().16b, \k\().16b aes\mc \i0\().16b, \i0\().16b .ifnb \i1 aes\de \i1\().16b, \k\().16b aes\mc \i1\().16b, \i1\().16b .ifnb \i3 aes\de \i2\().16b, \k\().16b aes\mc \i2\().16b, \i2\().16b aes\de \i3\().16b, \k\().16b aes\mc \i3\().16b, \i3\().16b .endif .endif .endm /* Up to 4 interleaved encryption rounds with the same round key */ .macro round_Nx, enc, k, i0, i1, i2, i3 .ifc \enc, e do_enc_Nx e, mc, \k, \i0, \i1, \i2, \i3 .else do_enc_Nx d, imc, \k, \i0, \i1, \i2, \i3 .endif .endm /* Up to 4 interleaved final rounds */ .macro fin_round_Nx, de, k, k2, i0, i1, i2, i3 aes\de \i0\().16b, \k\().16b .ifnb \i1 aes\de \i1\().16b, \k\().16b .ifnb \i3 aes\de \i2\().16b, \k\().16b aes\de \i3\().16b, \k\().16b .endif .endif eor \i0\().16b, \i0\().16b, \k2\().16b .ifnb \i1 eor \i1\().16b, \i1\().16b, \k2\().16b .ifnb \i3 eor \i2\().16b, \i2\().16b, \k2\().16b eor \i3\().16b, \i3\().16b, \k2\().16b .endif .endif .endm /* Up to 4 interleaved blocks */ .macro do_block_Nx, enc, rounds, i0, i1, i2, i3 cmp \rounds, #12 blo 2222f /* 128 bits */ beq 1111f /* 192 bits */ round_Nx \enc, v17, \i0, \i1, \i2, \i3 round_Nx \enc, v18, \i0, \i1, \i2, \i3 1111: round_Nx \enc, v19, \i0, \i1, \i2, \i3 round_Nx \enc, v20, \i0, \i1, \i2, \i3 2222: .irp key, v21, v22, v23, v24, v25, v26, v27, v28, v29 round_Nx \enc, \key, \i0, \i1, \i2, \i3 .endr fin_round_Nx \enc, v30, v31, \i0, \i1, \i2, \i3 .endm .macro encrypt_block, in, rounds, t0, t1, t2 do_block_Nx e, \rounds, \in .endm .macro encrypt_block2x, i0, i1, rounds, t0, t1, t2 do_block_Nx e, \rounds, \i0, \i1 .endm .macro encrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2 do_block_Nx e, \rounds, \i0, \i1, \i2, \i3 .endm .macro decrypt_block, in, rounds, t0, t1, t2 do_block_Nx d, \rounds, \in .endm .macro decrypt_block2x, i0, i1, rounds, t0, t1, t2 do_block_Nx d, \rounds, \i0, \i1 .endm .macro decrypt_block4x, i0, i1, i2, i3, rounds, t0, t1, t2 do_block_Nx d, \rounds, \i0, \i1, \i2, \i3 .endm /* * There are several ways to instantiate this code: * - no interleave, all inline * - 2-way interleave, 2x calls out of line (-DINTERLEAVE=2) * - 2-way interleave, all inline (-DINTERLEAVE=2 -DINTERLEAVE_INLINE) * - 4-way interleave, 4x calls out of line (-DINTERLEAVE=4) * - 4-way interleave, all inline (-DINTERLEAVE=4 -DINTERLEAVE_INLINE) * * Macros imported by this code: * - enc_prepare - setup NEON registers for encryption * - dec_prepare - setup NEON registers for decryption * - enc_switch_key - change to new key after having prepared for encryption * - encrypt_block - encrypt a single block * - decrypt block - decrypt a single block * - encrypt_block2x - encrypt 2 blocks in parallel (if INTERLEAVE == 2) * - decrypt_block2x - decrypt 2 blocks in parallel (if INTERLEAVE == 2) * - encrypt_block4x - encrypt 4 blocks in parallel (if INTERLEAVE == 4) * - decrypt_block4x - decrypt 4 blocks in parallel (if INTERLEAVE == 4) */ #if defined(INTERLEAVE) && !defined(INTERLEAVE_INLINE) #define FRAME_PUSH stp x29, x30, [sp,#-16]! ; mov x29, sp #define FRAME_POP ldp x29, x30, [sp],#16 #if INTERLEAVE == 2 LOCAL_FUNC aes_encrypt_block2x , : encrypt_block2x v0, v1, w3, x2, x6, w7 ret END_FUNC aes_encrypt_block2x LOCAL_FUNC aes_decrypt_block2x , : decrypt_block2x v0, v1, w3, x2, x6, w7 ret END_FUNC aes_decrypt_block2x #elif INTERLEAVE == 4 LOCAL_FUNC aes_encrypt_block4x , : encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 ret END_FUNC aes_encrypt_block4x LOCAL_FUNC aes_decrypt_block4x , : decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 ret END_FUNC aes_decrypt_block4x #else #error INTERLEAVE should equal 2 or 4 #endif .macro do_encrypt_block2x bl aes_encrypt_block2x .endm .macro do_decrypt_block2x bl aes_decrypt_block2x .endm .macro do_encrypt_block4x bl aes_encrypt_block4x .endm .macro do_decrypt_block4x bl aes_decrypt_block4x .endm #else #define FRAME_PUSH #define FRAME_POP .macro do_encrypt_block2x encrypt_block2x v0, v1, w3, x2, x6, w7 .endm .macro do_decrypt_block2x decrypt_block2x v0, v1, w3, x2, x6, w7 .endm .macro do_encrypt_block4x encrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 .endm .macro do_decrypt_block4x decrypt_block4x v0, v1, v2, v3, w3, x2, x6, w7 .endm #endif /* * uint32_t ce_aes_sub(uint32_t in) - use the aese instruction to * perform the AES sbox substitution on each byte in 'input' */ FUNC ce_aes_sub , : dup v1.4s, w0 movi v0.16b, #0 aese v0.16b, v1.16b umov w0, v0.s[0] ret END_FUNC ce_aes_sub /* * void ce_aes_invert(void *dst, const void *src); */ FUNC ce_aes_invert , : ld1 {v0.16b}, [x1] aesimc v1.16b, v0.16b st1 {v1.16b}, [x0] ret END_FUNC ce_aes_invert /* * ce_aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], * int rounds, int blocks, int first) */ FUNC ce_aes_ecb_encrypt , : FRAME_PUSH cbz w5, .LecbencloopNx enc_prepare w3, x2, x5 .LecbencloopNx: #if INTERLEAVE >= 2 subs w4, w4, #INTERLEAVE bmi .Lecbenc1x #if INTERLEAVE == 2 ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */ do_encrypt_block2x st1 {v0.16b-v1.16b}, [x0], #32 #else ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ do_encrypt_block4x st1 {v0.16b-v3.16b}, [x0], #64 #endif b .LecbencloopNx .Lecbenc1x: adds w4, w4, #INTERLEAVE beq .Lecbencout #endif .Lecbencloop: ld1 {v0.16b}, [x1], #16 /* get next pt block */ encrypt_block v0, w3, x2, x5, w6 st1 {v0.16b}, [x0], #16 subs w4, w4, #1 bne .Lecbencloop .Lecbencout: FRAME_POP ret END_FUNC ce_aes_ecb_encrypt /* * ce_aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], * int rounds, int blocks, int first) */ FUNC ce_aes_ecb_decrypt , : FRAME_PUSH cbz w5, .LecbdecloopNx dec_prepare w3, x2, x5 .LecbdecloopNx: #if INTERLEAVE >= 2 subs w4, w4, #INTERLEAVE bmi .Lecbdec1x #if INTERLEAVE == 2 ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ do_decrypt_block2x st1 {v0.16b-v1.16b}, [x0], #32 #else ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ do_decrypt_block4x st1 {v0.16b-v3.16b}, [x0], #64 #endif b .LecbdecloopNx .Lecbdec1x: adds w4, w4, #INTERLEAVE beq .Lecbdecout #endif .Lecbdecloop: ld1 {v0.16b}, [x1], #16 /* get next ct block */ decrypt_block v0, w3, x2, x5, w6 st1 {v0.16b}, [x0], #16 subs w4, w4, #1 bne .Lecbdecloop .Lecbdecout: FRAME_POP ret END_FUNC ce_aes_ecb_decrypt /* * void ce_aes_cbc_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * uint8_t iv[]) */ FUNC ce_aes_cbc_encrypt , : ld1 {v4.16b}, [x5] /* get iv */ enc_prepare w3, x2, x6 .Lcbcencloop4x: subs w4, w4, #4 bmi .Lcbcenc1x ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ eor v0.16b, v0.16b, v4.16b /* ..and xor with iv */ encrypt_block v0, w3, x2, x6, w7 eor v1.16b, v1.16b, v0.16b encrypt_block v1, w3, x2, x6, w7 eor v2.16b, v2.16b, v1.16b encrypt_block v2, w3, x2, x6, w7 eor v3.16b, v3.16b, v2.16b encrypt_block v3, w3, x2, x6, w7 st1 {v0.16b-v3.16b}, [x0], #64 mov v4.16b, v3.16b b .Lcbcencloop4x .Lcbcenc1x: adds w4, w4, #4 beq .Lcbcencout .Lcbcencloop: ld1 {v0.16b}, [x1], #16 /* get next pt block */ eor v4.16b, v4.16b, v0.16b /* ..and xor with iv */ encrypt_block v4, w3, x2, x6, w7 st1 {v4.16b}, [x0], #16 subs w4, w4, #1 bne .Lcbcencloop .Lcbcencout: st1 {v4.16b}, [x5] /* return iv */ ret END_FUNC ce_aes_cbc_encrypt /* * void ce_aes_cbc_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * uint8_t iv[]) */ FUNC ce_aes_cbc_decrypt , : stp x29, x30, [sp, #-16]! mov x29, sp ld1 {v7.16b}, [x5] /* get iv */ dec_prepare w3, x2, x6 .LcbcdecloopNx: subs w4, w4, #4 bmi .Lcbcdec1x ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ mov v4.16b, v0.16b mov v5.16b, v1.16b mov v6.16b, v2.16b bl aes_decrypt_block4x sub x1, x1, #16 eor v0.16b, v0.16b, v7.16b eor v1.16b, v1.16b, v4.16b ld1 {v7.16b}, [x1], #16 /* reload 1 ct block */ eor v2.16b, v2.16b, v5.16b eor v3.16b, v3.16b, v6.16b st1 {v0.16b-v3.16b}, [x0], #64 b .LcbcdecloopNx .Lcbcdec1x: adds w4, w4, #4 beq .Lcbcdecout .Lcbcdecloop: ld1 {v1.16b}, [x1], #16 /* get next ct block */ mov v0.16b, v1.16b /* ...and copy to v0 */ decrypt_block v0, w3, x2, x6, w7 eor v0.16b, v0.16b, v7.16b /* xor with iv => pt */ mov v7.16b, v1.16b /* ct is next iv */ st1 {v0.16b}, [x0], #16 subs w4, w4, #1 bne .Lcbcdecloop .Lcbcdecout: st1 {v7.16b}, [x5] /* return iv */ ldp x29, x30, [sp], #16 ret END_FUNC ce_aes_cbc_decrypt /* * void ce_aes_ctr_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], int rounds, int blocks, * uint8_t ctr[], int first) */ FUNC ce_aes_ctr_encrypt , : stp x29, x30, [sp, #-16]! mov x29, sp enc_prepare w3, x2, x6 ld1 {v4.16b}, [x5] umov x6, v4.d[1] /* keep swabbed ctr in reg */ rev x6, x6 cmn w6, w4 /* 32 bit overflow? */ bcs .Lctrloop .LctrloopNx: subs w4, w4, #4 bmi .Lctr1x add w7, w6, #1 mov v0.16b, v4.16b add w8, w6, #2 mov v1.16b, v4.16b add w9, w6, #3 mov v2.16b, v4.16b rev w7, w7 mov v3.16b, v4.16b rev w8, w8 mov v1.s[3], w7 rev w9, w9 mov v2.s[3], w8 mov v3.s[3], w9 ld1 {v5.16b-v7.16b}, [x1], #48 /* get 3 input blocks */ bl aes_encrypt_block4x eor v0.16b, v5.16b, v0.16b ld1 {v5.16b}, [x1], #16 /* get 1 input block */ eor v1.16b, v6.16b, v1.16b eor v2.16b, v7.16b, v2.16b eor v3.16b, v5.16b, v3.16b st1 {v0.16b-v3.16b}, [x0], #64 add x6, x6, #4 rev x7, x6 ins v4.d[1], x7 cbz w4, .Lctrout b .LctrloopNx .Lctr1x: adds w4, w4, #4 beq .Lctrout .Lctrloop: mov v0.16b, v4.16b encrypt_block v0, w3, x2, x8, w7 adds x6, x6, #1 /* increment BE ctr */ rev x7, x6 ins v4.d[1], x7 bcs .Lctrcarry /* overflow? */ .Lctrcarrydone: subs w4, w4, #1 bmi .Lctrtailblock /* blocks <0 means tail block */ ld1 {v3.16b}, [x1], #16 eor v3.16b, v0.16b, v3.16b st1 {v3.16b}, [x0], #16 bne .Lctrloop .Lctrout: st1 {v4.16b}, [x5] /* return next CTR value */ ldp x29, x30, [sp], #16 ret .Lctrtailblock: st1 {v0.16b}, [x0] ldp x29, x30, [sp], #16 ret .Lctrcarry: umov x7, v4.d[0] /* load upper word of ctr */ rev x7, x7 /* ... to handle the carry */ add x7, x7, #1 rev x7, x7 ins v4.d[0], x7 b .Lctrcarrydone END_FUNC ce_aes_ctr_encrypt .macro next_tweak, out, in, const, tmp sshr \tmp\().2d, \in\().2d, #63 and \tmp\().16b, \tmp\().16b, \const\().16b add \out\().2d, \in\().2d, \in\().2d ext \tmp\().16b, \tmp\().16b, \tmp\().16b, #8 eor \out\().16b, \out\().16b, \tmp\().16b .endm /* * void ce_aes_xts_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], int rounds, int blocks, * uint8_t const rk2[], uint8_t iv[]) */ FUNC ce_aes_xts_encrypt , : FRAME_PUSH ld1 {v4.16b}, [x6] enc_prepare w3, x5, x6 encrypt_block v4, w3, x5, x6, w7 /* first tweak */ enc_switch_key w3, x2, x6 ldr q7, .Lxts_mul_x b .LxtsencNx .LxtsencloopNx: next_tweak v4, v4, v7, v8 .LxtsencNx: #if INTERLEAVE >= 2 subs w4, w4, #INTERLEAVE bmi .Lxtsenc1x #if INTERLEAVE == 2 ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 pt blocks */ next_tweak v5, v4, v7, v8 eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b do_encrypt_block2x eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b st1 {v0.16b-v1.16b}, [x0], #32 cbz w4, .LxtsencoutNx next_tweak v4, v5, v7, v8 b .LxtsencNx .LxtsencoutNx: mov v4.16b, v5.16b b .Lxtsencout #else ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 pt blocks */ next_tweak v5, v4, v7, v8 eor v0.16b, v0.16b, v4.16b next_tweak v6, v5, v7, v8 eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b next_tweak v7, v6, v7, v8 eor v3.16b, v3.16b, v7.16b do_encrypt_block4x eor v3.16b, v3.16b, v7.16b eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b st1 {v0.16b-v3.16b}, [x0], #64 mov v4.16b, v7.16b ldr q7, .Lxts_mul_x cbz w4, .Lxtsencout b .LxtsencloopNx #endif .Lxtsenc1x: adds w4, w4, #INTERLEAVE beq .Lxtsencout #endif .Lxtsencloop: ld1 {v1.16b}, [x1], #16 eor v0.16b, v1.16b, v4.16b encrypt_block v0, w3, x2, x6, w7 eor v0.16b, v0.16b, v4.16b st1 {v0.16b}, [x0], #16 subs w4, w4, #1 beq .Lxtsencout next_tweak v4, v4, v7, v8 b .Lxtsencloop .Lxtsencout: next_tweak v4, v4, v7, v8 st1 {v4.16b}, [x6], #16 FRAME_POP ret .align 4 .Lxts_mul_x: .word 1, 0, 0x87, 0 END_FUNC ce_aes_xts_encrypt /* * void ce_aes_xts_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], int rounds, int blocks, * uint8_t const rk2[], uint8_t iv[]) */ FUNC ce_aes_xts_decrypt , : FRAME_PUSH ld1 {v4.16b}, [x6] enc_prepare w3, x5, x6 encrypt_block v4, w3, x5, x6, w7 /* first tweak */ dec_prepare w3, x2, x6 ldr q7, .Lxts_mul_x b .LxtsdecNx .LxtsdecloopNx: next_tweak v4, v4, v7, v8 .LxtsdecNx: #if INTERLEAVE >= 2 subs w4, w4, #INTERLEAVE bmi .Lxtsdec1x #if INTERLEAVE == 2 ld1 {v0.16b-v1.16b}, [x1], #32 /* get 2 ct blocks */ next_tweak v5, v4, v7, v8 eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b do_decrypt_block2x eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b st1 {v0.16b-v1.16b}, [x0], #32 cbz w4, .LxtsdecoutNx next_tweak v4, v5, v7, v8 b .LxtsdecNx .LxtsdecoutNx: mov v4.16b, v5.16b b .Lxtsdecout #else ld1 {v0.16b-v3.16b}, [x1], #64 /* get 4 ct blocks */ next_tweak v5, v4, v7, v8 eor v0.16b, v0.16b, v4.16b next_tweak v6, v5, v7, v8 eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b next_tweak v7, v6, v7, v8 eor v3.16b, v3.16b, v7.16b do_decrypt_block4x eor v3.16b, v3.16b, v7.16b eor v0.16b, v0.16b, v4.16b eor v1.16b, v1.16b, v5.16b eor v2.16b, v2.16b, v6.16b st1 {v0.16b-v3.16b}, [x0], #64 mov v4.16b, v7.16b ldr q7, .Lxts_mul_x cbz w4, .Lxtsdecout b .LxtsdecloopNx #endif .Lxtsdec1x: adds w4, w4, #INTERLEAVE beq .Lxtsdecout #endif .Lxtsdecloop: ld1 {v1.16b}, [x1], #16 eor v0.16b, v1.16b, v4.16b decrypt_block v0, w3, x2, x6, w7 eor v0.16b, v0.16b, v4.16b st1 {v0.16b}, [x0], #16 subs w4, w4, #1 beq .Lxtsdecout next_tweak v4, v4, v7, v8 b .Lxtsdecloop .Lxtsdecout: FRAME_POP next_tweak v4, v4, v7, v8 st1 {v4.16b}, [x6], #16 ret END_FUNC ce_aes_xts_decrypt /* * void ce_aes_xor_block(uint8_t out[], uint8_t const op1[], * uint8_t const op2[]); */ FUNC ce_aes_xor_block , : ld1 {v0.16b}, [x1] ld1 {v1.16b}, [x2] eor v0.16b, v0.16b, v1.16b st1 {v0.16b}, [x0] ret END_FUNC ce_aes_xor_block BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/ghash-ce-core_a32.S000066400000000000000000000117411464416617300225150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Accelerated GHASH implementation with ARMv8 PMULL instructions. * * Copyright (C) 2014 - 2017 Linaro Ltd. */ #include #include #define CPU_LE(x...) x SHASH .req q0 T1 .req q1 XL .req q2 XM .req q3 XH .req q4 IN1 .req q4 SHASH_L .req d0 SHASH_H .req d1 T1_L .req d2 T1_H .req d3 XL_L .req d4 XL_H .req d5 XM_L .req d6 XM_H .req d7 XH_L .req d8 t0l .req d10 t0h .req d11 t1l .req d12 t1h .req d13 t2l .req d14 t2h .req d15 t3l .req d16 t3h .req d17 t4l .req d18 t4h .req d19 t0q .req q5 t1q .req q6 t2q .req q7 t3q .req q8 t4q .req q9 T2 .req q9 s1l .req d20 s1h .req d21 s2l .req d22 s2h .req d23 s3l .req d24 s3h .req d25 s4l .req d26 s4h .req d27 MASK .req d28 SHASH2_p8 .req d28 k16 .req d29 k32 .req d30 k48 .req d31 SHASH2_p64 .req d31 .text .fpu crypto-neon-fp-armv8 .macro __pmull_p64, rd, rn, rm, b1, b2, b3, b4 vmull.p64 \rd, \rn, \rm .endm /* * This implementation of 64x64 -> 128 bit polynomial multiplication * using vmull.p8 instructions (8x8 -> 16) is taken from the paper * "Fast Software Polynomial Multiplication on ARM Processors Using * the NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and * Ricardo Dahab (https://hal.inria.fr/hal-01506572) * * It has been slightly tweaked for in-order performance, and to allow * 'rq' to overlap with 'ad' or 'bd'. */ .macro __pmull_p8, rq, ad, bd, b1=t4l, b2=t3l, b3=t4l, b4=t3l vext.8 t0l, \ad, \ad, #1 @ A1 .ifc \b1, t4l vext.8 t4l, \bd, \bd, #1 @ B1 .endif vmull.p8 t0q, t0l, \bd @ F = A1*B vext.8 t1l, \ad, \ad, #2 @ A2 vmull.p8 t4q, \ad, \b1 @ E = A*B1 .ifc \b2, t3l vext.8 t3l, \bd, \bd, #2 @ B2 .endif vmull.p8 t1q, t1l, \bd @ H = A2*B vext.8 t2l, \ad, \ad, #3 @ A3 vmull.p8 t3q, \ad, \b2 @ G = A*B2 veor t0q, t0q, t4q @ L = E + F .ifc \b3, t4l vext.8 t4l, \bd, \bd, #3 @ B3 .endif vmull.p8 t2q, t2l, \bd @ J = A3*B veor t0l, t0l, t0h @ t0 = (L) (P0 + P1) << 8 veor t1q, t1q, t3q @ M = G + H .ifc \b4, t3l vext.8 t3l, \bd, \bd, #4 @ B4 .endif vmull.p8 t4q, \ad, \b3 @ I = A*B3 veor t1l, t1l, t1h @ t1 = (M) (P2 + P3) << 16 vmull.p8 t3q, \ad, \b4 @ K = A*B4 vand t0h, t0h, k48 vand t1h, t1h, k32 veor t2q, t2q, t4q @ N = I + J veor t0l, t0l, t0h veor t1l, t1l, t1h veor t2l, t2l, t2h @ t2 = (N) (P4 + P5) << 24 vand t2h, t2h, k16 veor t3l, t3l, t3h @ t3 = (K) (P6 + P7) << 32 vmov.i64 t3h, #0 vext.8 t0q, t0q, t0q, #15 veor t2l, t2l, t2h vext.8 t1q, t1q, t1q, #14 vmull.p8 \rq, \ad, \bd @ D = A*B vext.8 t2q, t2q, t2q, #13 vext.8 t3q, t3q, t3q, #12 veor t0q, t0q, t1q veor t2q, t2q, t3q veor \rq, \rq, t0q veor \rq, \rq, t2q .endm // // PMULL (64x64->128) based reduction for CPUs that can do // it in a single instruction. // .macro __pmull_reduce_p64 vmull.p64 T1, XL_L, MASK veor XH_L, XH_L, XM_H vext.8 T1, T1, T1, #8 veor XL_H, XL_H, XM_L veor T1, T1, XL vmull.p64 XL, T1_H, MASK .endm // // Alternative reduction for CPUs that lack support for the // 64x64->128 PMULL instruction // .macro __pmull_reduce_p8 veor XL_H, XL_H, XM_L veor XH_L, XH_L, XM_H vshl.i64 T1, XL, #57 vshl.i64 T2, XL, #62 veor T1, T1, T2 vshl.i64 T2, XL, #63 veor T1, T1, T2 veor XL_H, XL_H, T1_L veor XH_L, XH_L, T1_H vshr.u64 T1, XL, #1 veor XH, XH, XL veor XL, XL, T1 vshr.u64 T1, T1, #6 vshr.u64 XL, XL, #1 .endm .macro ghash_update, pn vld1.64 {XL}, [r1] /* do the head block first, if supplied */ ldr ip, [sp] teq ip, #0 beq 0f vld1.8 {T1}, [ip] teq r0, #0 b 1f 0: vld1.8 {T1}, [r2]! subs r0, r0, #1 1: /* multiply XL by SHASH in GF(2^128) */ #ifndef CONFIG_CPU_BIG_ENDIAN vrev64.8 T1, T1 #endif vext.8 IN1, T1, T1, #8 veor T1_L, T1_L, XL_H veor XL, XL, IN1 __pmull_\pn XH, XL_H, SHASH_H, s1h, s2h, s3h, s4h @ a1 * b1 veor T1, T1, XL __pmull_\pn XL, XL_L, SHASH_L, s1l, s2l, s3l, s4l @ a0 * b0 __pmull_\pn XM, T1_L, SHASH2_\pn @ (a1+a0)(b1+b0) veor T1, XL, XH veor XM, XM, T1 __pmull_reduce_\pn veor T1, T1, XH veor XL, XL, T1 bne 0b vst1.64 {XL}, [r1] bx lr .endm /* * void pmull_ghash_update(int blocks, u64 dg[], const char *src, * struct ghash_key const *k, const char *head) */ FUNC pmull_ghash_update_p64 , : vld1.64 {SHASH}, [r3] veor SHASH2_p64, SHASH_L, SHASH_H vmov.i8 MASK, #0xe1 vshl.u64 MASK, MASK, #57 ghash_update p64 END_FUNC pmull_ghash_update_p64 FUNC pmull_ghash_update_p8 , : vld1.64 {SHASH}, [r3] veor SHASH2_p8, SHASH_L, SHASH_H vext.8 s1l, SHASH_L, SHASH_L, #1 vext.8 s2l, SHASH_L, SHASH_L, #2 vext.8 s3l, SHASH_L, SHASH_L, #3 vext.8 s4l, SHASH_L, SHASH_L, #4 vext.8 s1h, SHASH_H, SHASH_H, #1 vext.8 s2h, SHASH_H, SHASH_H, #2 vext.8 s3h, SHASH_H, SHASH_H, #3 vext.8 s4h, SHASH_H, SHASH_H, #4 vmov.i64 k16, #0xffff vmov.i64 k32, #0xffffffff vmov.i64 k48, #0xffffffffffff ghash_update p8 END_FUNC pmull_ghash_update_p8 optee_os-4.3.0/core/arch/arm/crypto/ghash-ce-core_a64.S000066400000000000000000000336611464416617300225270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, 2024 Linaro Limited * Copyright (C) 2014 - 2017 Linaro Ltd. * * Accelerated GHASH implementation with ARMv8 PMULL instructions. */ #include #include #define CPU_LE(x...) x /* * Only increase the lowest quarter, that is, 32-bits of the counter. If * it wraps it must not propagate into the upper bits. */ #define INC_QUART_CTR 1 SHASH .req v0 SHASH2 .req v1 T1 .req v2 T2 .req v3 MASK .req v4 XL .req v5 XM .req v6 XH .req v7 IN1 .req v7 k00_16 .req v8 k32_48 .req v9 t3 .req v10 t4 .req v11 t5 .req v12 t6 .req v13 t7 .req v14 t8 .req v15 t9 .req v16 perm1 .req v17 perm2 .req v18 perm3 .req v19 sh1 .req v20 sh2 .req v21 sh3 .req v22 sh4 .req v23 ss1 .req v24 ss2 .req v25 ss3 .req v26 ss4 .req v27 XL2 .req v8 XM2 .req v9 XH2 .req v10 XL3 .req v11 XM3 .req v12 XH3 .req v13 TT3 .req v14 TT4 .req v15 HH .req v16 HH3 .req v17 HH4 .req v18 HH34 .req v19 .arch armv8-a+crypto .macro __pmull_p64, rd, rn, rm pmull \rd\().1q, \rn\().1d, \rm\().1d .endm .macro __pmull2_p64, rd, rn, rm pmull2 \rd\().1q, \rn\().2d, \rm\().2d .endm .macro __pmull_p8, rq, ad, bd ext t3.8b, \ad\().8b, \ad\().8b, #1 // A1 ext t5.8b, \ad\().8b, \ad\().8b, #2 // A2 ext t7.8b, \ad\().8b, \ad\().8b, #3 // A3 __pmull_p8_\bd \rq, \ad .endm .macro __pmull2_p8, rq, ad, bd tbl t3.16b, {\ad\().16b}, perm1.16b // A1 tbl t5.16b, {\ad\().16b}, perm2.16b // A2 tbl t7.16b, {\ad\().16b}, perm3.16b // A3 __pmull2_p8_\bd \rq, \ad .endm .macro __pmull_p8_SHASH, rq, ad __pmull_p8_tail \rq, \ad\().8b, SHASH.8b, 8b,, sh1, sh2, sh3, sh4 .endm .macro __pmull_p8_SHASH2, rq, ad __pmull_p8_tail \rq, \ad\().8b, SHASH2.8b, 8b,, ss1, ss2, ss3, ss4 .endm .macro __pmull2_p8_SHASH, rq, ad __pmull_p8_tail \rq, \ad\().16b, SHASH.16b, 16b, 2, sh1, sh2, sh3, sh4 .endm .macro __pmull_p8_tail, rq, ad, bd, nb, t, b1, b2, b3, b4 pmull\t t3.8h, t3.\nb, \bd // F = A1*B pmull\t t4.8h, \ad, \b1\().\nb // E = A*B1 pmull\t t5.8h, t5.\nb, \bd // H = A2*B pmull\t t6.8h, \ad, \b2\().\nb // G = A*B2 pmull\t t7.8h, t7.\nb, \bd // J = A3*B pmull\t t8.8h, \ad, \b3\().\nb // I = A*B3 pmull\t t9.8h, \ad, \b4\().\nb // K = A*B4 pmull\t \rq\().8h, \ad, \bd // D = A*B eor t3.16b, t3.16b, t4.16b // L = E + F eor t5.16b, t5.16b, t6.16b // M = G + H eor t7.16b, t7.16b, t8.16b // N = I + J uzp1 t4.2d, t3.2d, t5.2d uzp2 t3.2d, t3.2d, t5.2d uzp1 t6.2d, t7.2d, t9.2d uzp2 t7.2d, t7.2d, t9.2d // t3 = (L) (P0 + P1) << 8 // t5 = (M) (P2 + P3) << 16 eor t4.16b, t4.16b, t3.16b and t3.16b, t3.16b, k32_48.16b // t7 = (N) (P4 + P5) << 24 // t9 = (K) (P6 + P7) << 32 eor t6.16b, t6.16b, t7.16b and t7.16b, t7.16b, k00_16.16b eor t4.16b, t4.16b, t3.16b eor t6.16b, t6.16b, t7.16b zip2 t5.2d, t4.2d, t3.2d zip1 t3.2d, t4.2d, t3.2d zip2 t9.2d, t6.2d, t7.2d zip1 t7.2d, t6.2d, t7.2d ext t3.16b, t3.16b, t3.16b, #15 ext t5.16b, t5.16b, t5.16b, #14 ext t7.16b, t7.16b, t7.16b, #13 ext t9.16b, t9.16b, t9.16b, #12 eor t3.16b, t3.16b, t5.16b eor t7.16b, t7.16b, t9.16b eor \rq\().16b, \rq\().16b, t3.16b eor \rq\().16b, \rq\().16b, t7.16b .endm .macro __pmull_pre_p64 add x8, x3, #16 ld1 {HH.2d-HH4.2d}, [x8] trn1 SHASH2.2d, SHASH.2d, HH.2d trn2 T1.2d, SHASH.2d, HH.2d eor SHASH2.16b, SHASH2.16b, T1.16b trn1 HH34.2d, HH3.2d, HH4.2d trn2 T1.2d, HH3.2d, HH4.2d eor HH34.16b, HH34.16b, T1.16b movi MASK.16b, #0xe1 shl MASK.2d, MASK.2d, #57 .endm .macro __pmull_pre_p8 ext SHASH2.16b, SHASH.16b, SHASH.16b, #8 eor SHASH2.16b, SHASH2.16b, SHASH.16b // k00_16 := 0x0000000000000000_000000000000ffff // k32_48 := 0x00000000ffffffff_0000ffffffffffff movi k32_48.2d, #0xffffffff mov k32_48.h[2], k32_48.h[0] ushr k00_16.2d, k32_48.2d, #32 // prepare the permutation vectors mov_imm x5, 0x080f0e0d0c0b0a09 movi T1.8b, #8 dup perm1.2d, x5 eor perm1.16b, perm1.16b, T1.16b ushr perm2.2d, perm1.2d, #8 ushr perm3.2d, perm1.2d, #16 ushr T1.2d, perm1.2d, #24 sli perm2.2d, perm1.2d, #56 sli perm3.2d, perm1.2d, #48 sli T1.2d, perm1.2d, #40 // precompute loop invariants tbl sh1.16b, {SHASH.16b}, perm1.16b tbl sh2.16b, {SHASH.16b}, perm2.16b tbl sh3.16b, {SHASH.16b}, perm3.16b tbl sh4.16b, {SHASH.16b}, T1.16b ext ss1.8b, SHASH2.8b, SHASH2.8b, #1 ext ss2.8b, SHASH2.8b, SHASH2.8b, #2 ext ss3.8b, SHASH2.8b, SHASH2.8b, #3 ext ss4.8b, SHASH2.8b, SHASH2.8b, #4 .endm // // PMULL (64x64->128) based reduction for CPUs that can do // it in a single instruction. // .macro __pmull_reduce_p64 pmull T2.1q, XL.1d, MASK.1d eor XM.16b, XM.16b, T1.16b mov XH.d[0], XM.d[1] mov XM.d[1], XL.d[0] eor XL.16b, XM.16b, T2.16b ext T2.16b, XL.16b, XL.16b, #8 pmull XL.1q, XL.1d, MASK.1d .endm // // Alternative reduction for CPUs that lack support for the // 64x64->128 PMULL instruction // .macro __pmull_reduce_p8 eor XM.16b, XM.16b, T1.16b mov XL.d[1], XM.d[0] mov XH.d[0], XM.d[1] shl T1.2d, XL.2d, #57 shl T2.2d, XL.2d, #62 eor T2.16b, T2.16b, T1.16b shl T1.2d, XL.2d, #63 eor T2.16b, T2.16b, T1.16b ext T1.16b, XL.16b, XH.16b, #8 eor T2.16b, T2.16b, T1.16b mov XL.d[1], T2.d[0] mov XH.d[0], T2.d[1] ushr T2.2d, XL.2d, #1 eor XH.16b, XH.16b, XL.16b eor XL.16b, XL.16b, T2.16b ushr T2.2d, T2.2d, #6 ushr XL.2d, XL.2d, #1 .endm .macro __pmull_ghash, pn ld1 {SHASH.2d}, [x3] ld1 {XL.2d}, [x1] __pmull_pre_\pn /* do the head block first, if supplied */ cbz x4, 0f ld1 {T1.16b}, [x4] mov x4, xzr b 3f 0: .ifc \pn, p64 tbnz w0, #0, 2f // skip until #blocks is a tbnz w0, #1, 2f // round multiple of 4 1: ld1 {XM3.16b-TT4.16b}, [x2], #64 sub w0, w0, #4 rev64 T1.16b, XM3.16b rev64 T2.16b, XH3.16b rev64 TT4.16b, TT4.16b rev64 TT3.16b, TT3.16b ext IN1.16b, TT4.16b, TT4.16b, #8 ext XL3.16b, TT3.16b, TT3.16b, #8 eor TT4.16b, TT4.16b, IN1.16b pmull2 XH2.1q, SHASH.2d, IN1.2d // a1 * b1 pmull XL2.1q, SHASH.1d, IN1.1d // a0 * b0 pmull XM2.1q, SHASH2.1d, TT4.1d // (a1 + a0)(b1 + b0) eor TT3.16b, TT3.16b, XL3.16b pmull2 XH3.1q, HH.2d, XL3.2d // a1 * b1 pmull XL3.1q, HH.1d, XL3.1d // a0 * b0 pmull2 XM3.1q, SHASH2.2d, TT3.2d // (a1 + a0)(b1 + b0) ext IN1.16b, T2.16b, T2.16b, #8 eor XL2.16b, XL2.16b, XL3.16b eor XH2.16b, XH2.16b, XH3.16b eor XM2.16b, XM2.16b, XM3.16b eor T2.16b, T2.16b, IN1.16b pmull2 XH3.1q, HH3.2d, IN1.2d // a1 * b1 pmull XL3.1q, HH3.1d, IN1.1d // a0 * b0 pmull XM3.1q, HH34.1d, T2.1d // (a1 + a0)(b1 + b0) eor XL2.16b, XL2.16b, XL3.16b eor XH2.16b, XH2.16b, XH3.16b eor XM2.16b, XM2.16b, XM3.16b ext IN1.16b, T1.16b, T1.16b, #8 ext TT3.16b, XL.16b, XL.16b, #8 eor XL.16b, XL.16b, IN1.16b eor T1.16b, T1.16b, TT3.16b pmull2 XH.1q, HH4.2d, XL.2d // a1 * b1 eor T1.16b, T1.16b, XL.16b pmull XL.1q, HH4.1d, XL.1d // a0 * b0 pmull2 XM.1q, HH34.2d, T1.2d // (a1 + a0)(b1 + b0) eor XL.16b, XL.16b, XL2.16b eor XH.16b, XH.16b, XH2.16b eor XM.16b, XM.16b, XM2.16b eor T2.16b, XL.16b, XH.16b ext T1.16b, XL.16b, XH.16b, #8 eor XM.16b, XM.16b, T2.16b __pmull_reduce_p64 eor T2.16b, T2.16b, XH.16b eor XL.16b, XL.16b, T2.16b cbz w0, 5f b 1b .endif 2: ld1 {T1.16b}, [x2], #16 sub w0, w0, #1 3: /* multiply XL by SHASH in GF(2^128) */ CPU_LE( rev64 T1.16b, T1.16b ) ext T2.16b, XL.16b, XL.16b, #8 ext IN1.16b, T1.16b, T1.16b, #8 eor T1.16b, T1.16b, T2.16b eor XL.16b, XL.16b, IN1.16b __pmull2_\pn XH, XL, SHASH // a1 * b1 eor T1.16b, T1.16b, XL.16b __pmull_\pn XL, XL, SHASH // a0 * b0 __pmull_\pn XM, T1, SHASH2 // (a1 + a0)(b1 + b0) 4: eor T2.16b, XL.16b, XH.16b ext T1.16b, XL.16b, XH.16b, #8 eor XM.16b, XM.16b, T2.16b __pmull_reduce_\pn eor T2.16b, T2.16b, XH.16b eor XL.16b, XL.16b, T2.16b cbnz w0, 0b 5: st1 {XL.2d}, [x1] ret .endm /* * void pmull_ghash_update_p64(int blocks, uint64_t dg[2], const uint8_t *src, * const struct internal_ghash_key *ghash_key, * const uint8_t *head); */ FUNC pmull_ghash_update_p64 , : __pmull_ghash p64 END_FUNC pmull_ghash_update_p64 /* * void pmull_ghash_update_p8(int blocks, uint64_t dg[2], const uint8_t *src, * const struct internal_ghash_key *ghash_key, * const uint8_t *head); */ FUNC pmull_ghash_update_p8 , : __pmull_ghash p8 END_FUNC pmull_ghash_update_p8 KS0 .req v12 KS1 .req v13 INP0 .req v14 INP1 .req v15 .macro load_round_keys, rounds, rk cmp \rounds, #12 blo 2222f /* 128 bits */ beq 1111f /* 192 bits */ ld1 {v17.4s-v18.4s}, [\rk], #32 1111: ld1 {v19.4s-v20.4s}, [\rk], #32 2222: ld1 {v21.4s-v24.4s}, [\rk], #64 ld1 {v25.4s-v28.4s}, [\rk], #64 ld1 {v29.4s-v31.4s}, [\rk] .endm .macro enc_round, state, key aese \state\().16b, \key\().16b aesmc \state\().16b, \state\().16b .endm .macro enc_block, state, rounds cmp \rounds, #12 b.lo 2222f /* 128 bits */ b.eq 1111f /* 192 bits */ enc_round \state, v17 enc_round \state, v18 1111: enc_round \state, v19 enc_round \state, v20 2222: .irp key, v21, v22, v23, v24, v25, v26, v27, v28, v29 enc_round \state, \key .endr aese \state\().16b, v30.16b eor \state\().16b, \state\().16b, v31.16b .endm .macro pmull_gcm_do_crypt, enc ld1 {SHASH.2d}, [x4], #16 ld1 {HH.2d}, [x4] ld1 {XL.2d}, [x1] #if INC_QUART_CTR ldr x8, [x5, #8] // load lower counter #else ldp x9, x8, [x5] // load counter #endif movi MASK.16b, #0xe1 trn1 SHASH2.2d, SHASH.2d, HH.2d trn2 T1.2d, SHASH.2d, HH.2d CPU_LE( rev x8, x8 ) #if !INC_QUART_CTR CPU_LE( rev x9, x9 ) #endif shl MASK.2d, MASK.2d, #57 eor SHASH2.16b, SHASH2.16b, T1.16b .if \enc == 1 ldr x10, [sp] ld1 {KS0.16b-KS1.16b}, [x10] .endif cbnz x6, 4f 0: ld1 {INP0.16b-INP1.16b}, [x3], #32 #if INC_QUART_CTR lsr x12, x8, #32 // Save the upper 32 bits rev x9, x8 add w11, w8, #1 add w8, w8, #2 add x11, x11, x12, lsl #32 // Restore the upper 32 bits add x8, x8, x12, lsl #32 #endif .if \enc == 1 eor INP0.16b, INP0.16b, KS0.16b // encrypt input eor INP1.16b, INP1.16b, KS1.16b .endif sub w0, w0, #2 #if INC_QUART_CTR ld1 {KS0.8b}, [x5] // load upper counter rev x11, x11 mov KS1.8b, KS0.8b ins KS0.d[1], x9 // set lower counter ins KS1.d[1], x11 #else ins KS0.d[1], x8 ins KS0.d[0], x9 rev64 KS0.16b, KS0.16b add x8, x8, #1 cbnz x8, 10f add x9, x9, #1 10: ins KS1.d[1], x8 ins KS1.d[0], x9 rev64 KS1.16b, KS1.16b add x8, x8, #1 cbnz x8, 11f add x9, x9, #1 11: #endif rev64 T1.16b, INP1.16b cmp w7, #12 b.ge 2f // AES-192/256? 1: enc_round KS0, v21 ext IN1.16b, T1.16b, T1.16b, #8 enc_round KS1, v21 pmull2 XH2.1q, SHASH.2d, IN1.2d // a1 * b1 enc_round KS0, v22 eor T1.16b, T1.16b, IN1.16b enc_round KS1, v22 pmull XL2.1q, SHASH.1d, IN1.1d // a0 * b0 enc_round KS0, v23 pmull XM2.1q, SHASH2.1d, T1.1d // (a1 + a0)(b1 + b0) enc_round KS1, v23 rev64 T1.16b, INP0.16b ext T2.16b, XL.16b, XL.16b, #8 enc_round KS0, v24 ext IN1.16b, T1.16b, T1.16b, #8 eor T1.16b, T1.16b, T2.16b enc_round KS1, v24 eor XL.16b, XL.16b, IN1.16b enc_round KS0, v25 eor T1.16b, T1.16b, XL.16b enc_round KS1, v25 pmull2 XH.1q, HH.2d, XL.2d // a1 * b1 enc_round KS0, v26 pmull XL.1q, HH.1d, XL.1d // a0 * b0 enc_round KS1, v26 pmull2 XM.1q, SHASH2.2d, T1.2d // (a1 + a0)(b1 + b0) enc_round KS0, v27 eor XL.16b, XL.16b, XL2.16b eor XH.16b, XH.16b, XH2.16b enc_round KS1, v27 eor XM.16b, XM.16b, XM2.16b ext T1.16b, XL.16b, XH.16b, #8 enc_round KS0, v28 eor T2.16b, XL.16b, XH.16b eor XM.16b, XM.16b, T1.16b enc_round KS1, v28 eor XM.16b, XM.16b, T2.16b enc_round KS0, v29 pmull T2.1q, XL.1d, MASK.1d enc_round KS1, v29 mov XH.d[0], XM.d[1] mov XM.d[1], XL.d[0] aese KS0.16b, v30.16b eor XL.16b, XM.16b, T2.16b aese KS1.16b, v30.16b ext T2.16b, XL.16b, XL.16b, #8 eor KS0.16b, KS0.16b, v31.16b pmull XL.1q, XL.1d, MASK.1d eor T2.16b, T2.16b, XH.16b eor KS1.16b, KS1.16b, v31.16b eor XL.16b, XL.16b, T2.16b .if \enc == 0 eor INP0.16b, INP0.16b, KS0.16b eor INP1.16b, INP1.16b, KS1.16b .endif st1 {INP0.16b-INP1.16b}, [x2], #32 cbnz w0, 0b CPU_LE( rev x8, x8 ) #if !INC_QUART_CTR CPU_LE( rev x9, x9 ) #endif st1 {XL.2d}, [x1] #if INC_QUART_CTR str x8, [x5, #8] // store lower counter #else stp x9, x8, [x5] // store counter #endif .if \enc == 1 st1 {KS0.16b-KS1.16b}, [x10] .endif ret 2: b.eq 3f // AES-192? enc_round KS0, v17 enc_round KS1, v17 enc_round KS0, v18 enc_round KS1, v18 3: enc_round KS0, v19 enc_round KS1, v19 enc_round KS0, v20 enc_round KS1, v20 b 1b 4: load_round_keys w7, x6 b 0b .endm /* * void pmull_gcm_encrypt(int blocks, uint64_t dg[2], uint8_t dst[], * const uint8_t src[], * const struct internal_ghash_key *ghash_key, * uint64_t ctr[], const uint64_t rk[], int rounds, * uint8_t ks[]); */ FUNC pmull_gcm_encrypt , : pmull_gcm_do_crypt 1 END_FUNC pmull_gcm_encrypt /* * void pmull_gcm_decrypt(int blocks, uint64_t dg[2], uint8_t dst[], * const uint8_t src[], * const struct internal_ghash_key *ghash_key, * uint64_t ctr[], const uint64_t rk[], int rounds); */ FUNC pmull_gcm_decrypt , : pmull_gcm_do_crypt 0 END_FUNC pmull_gcm_decrypt /* * void pmull_gcm_encrypt_block(uint8_t dst[], const uint8_t src[], int rounds) */ FUNC pmull_gcm_encrypt_block , : ld1 {v0.16b}, [x1] enc_block v0, w2 st1 {v0.16b}, [x0] ret END_FUNC pmull_gcm_encrypt_block /* * void pmull_gcm_load_round_keys(const uint64_t rk[30], int rounds) */ FUNC pmull_gcm_load_round_keys , : load_round_keys w1, x0 ret END_FUNC pmull_gcm_load_round_keys /* * uint32_t pmull_gcm_aes_sub(uint32_t input) * * use the aese instruction to perform the AES sbox substitution * on each byte in 'input' */ FUNC pmull_gcm_aes_sub , : dup v1.4s, w0 movi v0.16b, #0 aese v0.16b, v1.16b umov w0, v0.s[0] ret END_FUNC pmull_gcm_aes_sub BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sha1_armv8a_ce.c000066400000000000000000000010271464416617300222400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited */ #include #include /* Prototype for assembly function */ void sha1_ce_transform(uint32_t state[5], const void *src, unsigned int block_count); void crypto_accel_sha1_compress(uint32_t state[5], const void *src, unsigned int block_count) { uint32_t vfp_state = 0; vfp_state = thread_kernel_enable_vfp(); sha1_ce_transform(state, src, block_count); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/sha1_armv8a_ce_a32.S000066400000000000000000000043751464416617300226760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2020, Linaro Limited */ /* SHA-1 secure hash using ARMv8 Crypto Extensions */ #include .fpu crypto-neon-fp-armv8 k0 .req q0 k1 .req q1 k2 .req q2 k3 .req q3 ta0 .req q4 ta1 .req q5 tb0 .req q5 tb1 .req q4 dga .req q6 dgb .req q7 dgbs .req s28 dg0 .req q12 dg1a0 .req q13 dg1a1 .req q14 dg1b0 .req q14 dg1b1 .req q13 .macro add_only, op, ev, rc, s0, dg1 .ifnb \s0 vadd.u32 tb\ev, q\s0, \rc .endif sha1h.32 dg1b\ev, dg0 .ifb \dg1 sha1\op\().32 dg0, dg1a\ev, ta\ev .else sha1\op\().32 dg0, \dg1, ta\ev .endif .endm .macro add_update, op, ev, rc, s0, s1, s2, s3, dg1 sha1su0.32 q\s0, q\s1, q\s2 add_only \op, \ev, \rc, \s1, \dg1 sha1su1.32 q\s0, q\s3 .endm FUNC sha1_ce_transform , : /* load round constants */ adr r3, .Lsha1_rcon vld1.32 {k0-k1}, [r3]! vld1.32 {k2-k3}, [r3] /* load state */ vld1.32 {dga}, [r0] vldr dgbs, [r0, #16] 0: /* load input */ vld1.8 {q8-q9}, [r1]! vrev32.8 q8, q8 vrev32.8 q9, q9 vld1.8 {q10-q11}, [r1]! vrev32.8 q10, q10 vrev32.8 q11, q11 subs r2, r2, #1 vadd.u32 ta0, q8, k0 vmov dg0, dga add_update c, 0, k0, 8, 9, 10, 11, dgb add_update c, 1, k0, 9, 10, 11, 8 add_update c, 0, k0, 10, 11, 8, 9 add_update c, 1, k0, 11, 8, 9, 10 add_update c, 0, k1, 8, 9, 10, 11 add_update p, 1, k1, 9, 10, 11, 8 add_update p, 0, k1, 10, 11, 8, 9 add_update p, 1, k1, 11, 8, 9, 10 add_update p, 0, k1, 8, 9, 10, 11 add_update p, 1, k2, 9, 10, 11, 8 add_update m, 0, k2, 10, 11, 8, 9 add_update m, 1, k2, 11, 8, 9, 10 add_update m, 0, k2, 8, 9, 10, 11 add_update m, 1, k2, 9, 10, 11, 8 add_update m, 0, k3, 10, 11, 8, 9 add_update p, 1, k3, 11, 8, 9, 10 add_only p, 0, k3, 9 add_only p, 1, k3, 10 add_only p, 0, k3, 11 add_only p, 1 /* update state */ vadd.u32 dga, dga, dg0 vadd.u32 dgb, dgb, dg1a0 bne 0b /* store new state */ vst1.32 {dga}, [r0] vstr dgbs, [r0, #16] bx lr .align 4 .Lsha1_rcon: .word 0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999 .word 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1 .word 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc .word 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6 END_FUNC sha1_ce_transform optee_os-4.3.0/core/arch/arm/crypto/sha1_armv8a_ce_a64.S000066400000000000000000000050561464416617300227000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2020, Linaro Limited * Copyright (C) 2014 Linaro Ltd */ /* SHA-1 secure hash using ARMv8 Crypto Extensions */ #include .arch armv8-a+crypto k0 .req v0 k1 .req v1 k2 .req v2 k3 .req v3 t0 .req v4 t1 .req v5 dga .req q6 dgav .req v6 dgb .req s7 dgbv .req v7 dg0q .req q12 dg0s .req s12 dg0v .req v12 dg1s .req s13 dg1v .req v13 dg2s .req s14 .macro add_only, op, ev, rc, s0, dg1 .ifc \ev, ev add t1.4s, v\s0\().4s, \rc\().4s sha1h dg2s, dg0s .ifnb \dg1 sha1\op dg0q, \dg1, t0.4s .else sha1\op dg0q, dg1s, t0.4s .endif .else .ifnb \s0 add t0.4s, v\s0\().4s, \rc\().4s .endif sha1h dg1s, dg0s sha1\op dg0q, dg2s, t1.4s .endif .endm .macro add_update, op, ev, rc, s0, s1, s2, s3, dg1 sha1su0 v\s0\().4s, v\s1\().4s, v\s2\().4s add_only \op, \ev, \rc, \s1, \dg1 sha1su1 v\s0\().4s, v\s3\().4s .endm /* * void sha1_ce_transform(u32 state[5], u8 const *src, int blocks) */ FUNC sha1_ce_transform , : /* load round constants */ adr x6, .Lsha1_rcon ld1r {k0.4s}, [x6], #4 ld1r {k1.4s}, [x6], #4 ld1r {k2.4s}, [x6], #4 ld1r {k3.4s}, [x6] /* load state */ ld1 {dgav.4s}, [x0] ldr dgb, [x0, #16] /* load input */ 0: ld1 {v8.16b-v11.16b}, [x1], #64 sub w2, w2, #1 rev32 v8.16b, v8.16b rev32 v9.16b, v9.16b rev32 v10.16b, v10.16b rev32 v11.16b, v11.16b 1: add t0.4s, v8.4s, k0.4s mov dg0v.16b, dgav.16b add_update c, ev, k0, 8, 9, 10, 11, dgb add_update c, od, k0, 9, 10, 11, 8 add_update c, ev, k0, 10, 11, 8, 9 add_update c, od, k0, 11, 8, 9, 10 add_update c, ev, k1, 8, 9, 10, 11 add_update p, od, k1, 9, 10, 11, 8 add_update p, ev, k1, 10, 11, 8, 9 add_update p, od, k1, 11, 8, 9, 10 add_update p, ev, k1, 8, 9, 10, 11 add_update p, od, k2, 9, 10, 11, 8 add_update m, ev, k2, 10, 11, 8, 9 add_update m, od, k2, 11, 8, 9, 10 add_update m, ev, k2, 8, 9, 10, 11 add_update m, od, k2, 9, 10, 11, 8 add_update m, ev, k3, 10, 11, 8, 9 add_update p, od, k3, 11, 8, 9, 10 add_only p, ev, k3, 9 add_only p, od, k3, 10 add_only p, ev, k3, 11 add_only p, od /* update state */ add dgbv.2s, dgbv.2s, dg1v.2s add dgav.4s, dgav.4s, dg0v.4s cbnz w2, 0b /* store new state */ 3: st1 {dgav.4s}, [x0] str dgb, [x0, #16] ret /* The SHA1 round constants */ .align 4 .Lsha1_rcon: .word 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 END_FUNC sha1_ce_transform BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sha256_armv8a_ce.c000066400000000000000000000010321464416617300224100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited */ #include #include /* Prototype for assembly function */ void sha256_ce_transform(uint32_t state[8], const void *src, unsigned int block_count); void crypto_accel_sha256_compress(uint32_t state[8], const void *src, unsigned int block_count) { uint32_t vfp_state = 0; vfp_state = thread_kernel_enable_vfp(); sha256_ce_transform(state, src, block_count); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/sha256_armv8a_ce_a32.S000066400000000000000000000046761464416617300230560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2020, Linaro Limited */ /* SHA-256 secure hash using ARMv8 Crypto Extensions */ #include .fpu crypto-neon-fp-armv8 k0 .req q7 k1 .req q8 ta0 .req q9 ta1 .req q10 tb0 .req q10 tb1 .req q9 dga .req q11 dgb .req q12 dg0 .req q13 dg1 .req q14 dg2 .req q15 .macro add_only, ev, s0 vmov dg2, dg0 .ifnb \s0 vld1.32 {k\ev}, [r3]! .endif sha256h.32 dg0, dg1, tb\ev sha256h2.32 dg1, dg2, tb\ev .ifnb \s0 vadd.u32 ta\ev, q\s0, k\ev .endif .endm .macro add_update, ev, s0, s1, s2, s3 sha256su0.32 q\s0, q\s1 add_only \ev, \s1 sha256su1.32 q\s0, q\s2, q\s3 .endm FUNC sha256_ce_transform , : /* load state */ vld1.8 {dga-dgb}, [r0] /* load input */ 0: vld1.8 {q0-q1}, [r1]! vrev32.8 q0, q0 vrev32.8 q1, q1 vld1.8 {q2-q3}, [r1]! vrev32.8 q2, q2 vrev32.8 q3, q3 subs r2, r2, #1 /* load round constants */ adr r3, .Lsha256_rcon vld1.32 {k0}, [r3]! vadd.u32 ta0, q0, k0 vmov dg0, dga vmov dg1, dgb add_update 1, 0, 1, 2, 3 add_update 0, 1, 2, 3, 0 add_update 1, 2, 3, 0, 1 add_update 0, 3, 0, 1, 2 add_update 1, 0, 1, 2, 3 add_update 0, 1, 2, 3, 0 add_update 1, 2, 3, 0, 1 add_update 0, 3, 0, 1, 2 add_update 1, 0, 1, 2, 3 add_update 0, 1, 2, 3, 0 add_update 1, 2, 3, 0, 1 add_update 0, 3, 0, 1, 2 add_only 1, 1 add_only 0, 2 add_only 1, 3 add_only 0 /* update state */ vadd.u32 dga, dga, dg0 vadd.u32 dgb, dgb, dg1 bne 0b /* store new state */ vst1.8 {dga-dgb}, [r0] bx lr .align 6 .Lsha256_rcon: .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 END_FUNC sha256_ce_transform optee_os-4.3.0/core/arch/arm/crypto/sha256_armv8a_ce_a64.S000066400000000000000000000063771464416617300230630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2020, Linaro Limited * Copyright (C) 2014 Linaro Ltd */ /* Core SHA-224/SHA-256 transform using v8 Crypto Extensions */ #include .arch armv8-a+crypto dga .req q20 dgav .req v20 dgb .req q21 dgbv .req v21 t0 .req v22 t1 .req v23 dg0q .req q24 dg0v .req v24 dg1q .req q25 dg1v .req v25 dg2q .req q26 dg2v .req v26 .macro add_only, ev, rc, s0 mov dg2v.16b, dg0v.16b .ifeq \ev add t1.4s, v\s0\().4s, \rc\().4s sha256h dg0q, dg1q, t0.4s sha256h2 dg1q, dg2q, t0.4s .else .ifnb \s0 add t0.4s, v\s0\().4s, \rc\().4s .endif sha256h dg0q, dg1q, t1.4s sha256h2 dg1q, dg2q, t1.4s .endif .endm .macro add_update, ev, rc, s0, s1, s2, s3 sha256su0 v\s0\().4s, v\s1\().4s add_only \ev, \rc, \s1 sha256su1 v\s0\().4s, v\s2\().4s, v\s3\().4s .endm /* * void sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src, * int blocks) */ FUNC sha256_ce_transform , : /* load round constants */ adr x8, .Lsha2_rcon ld1 { v0.4s- v3.4s}, [x8], #64 ld1 { v4.4s- v7.4s}, [x8], #64 ld1 { v8.4s-v11.4s}, [x8], #64 ld1 {v12.4s-v15.4s}, [x8] /* load state */ mov x9, x0 ld1 {dgav.4s}, [x9], #16 ld1 {dgbv.4s}, [x9] /* load input */ 0: ld1 {v16.16b-v19.16b}, [x1], #64 sub w2, w2, #1 rev32 v16.16b, v16.16b rev32 v17.16b, v17.16b rev32 v18.16b, v18.16b rev32 v19.16b, v19.16b 1: add t0.4s, v16.4s, v0.4s mov dg0v.16b, dgav.16b mov dg1v.16b, dgbv.16b add_update 0, v1, 16, 17, 18, 19 add_update 1, v2, 17, 18, 19, 16 add_update 0, v3, 18, 19, 16, 17 add_update 1, v4, 19, 16, 17, 18 add_update 0, v5, 16, 17, 18, 19 add_update 1, v6, 17, 18, 19, 16 add_update 0, v7, 18, 19, 16, 17 add_update 1, v8, 19, 16, 17, 18 add_update 0, v9, 16, 17, 18, 19 add_update 1, v10, 17, 18, 19, 16 add_update 0, v11, 18, 19, 16, 17 add_update 1, v12, 19, 16, 17, 18 add_only 0, v13, 17 add_only 1, v14, 18 add_only 0, v15, 19 add_only 1 /* update state */ add dgav.4s, dgav.4s, dg0v.4s add dgbv.4s, dgbv.4s, dg1v.4s /* handled all input blocks? */ cbnz w2, 0b /* store new state */ 3: mov x9, x0 st1 {dgav.16b}, [x9], #16 st1 {dgbv.16b}, [x9] ret /* * The SHA-256 round constants */ .align 4 .Lsha2_rcon: .word 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 .word 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 .word 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 .word 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 .word 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc .word 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da .word 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 .word 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 .word 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 .word 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 .word 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 .word 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 .word 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 .word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 .word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 .word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 END_FUNC sha256_ce_transform BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sha3_armv8a_ce.c000066400000000000000000000012001464416617300222330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Linaro Limited */ #include #include /* Prototype for assembly function */ int sha3_ce_transform(uint64_t state[25], const void *src, unsigned int block_count, unsigned int digest_size); void crypto_accel_sha3_compress(uint64_t state[25], const void *src, unsigned int block_count, unsigned int digest_size) { uint32_t vfp_state = 0; int res = 0; vfp_state = thread_kernel_enable_vfp(); res = sha3_ce_transform(state, src, block_count, digest_size); thread_kernel_disable_vfp(vfp_state); assert(!res); } optee_os-4.3.0/core/arch/arm/crypto/sha3_armv8a_ce_a64.S000066400000000000000000000147671464416617300227130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2018 Linaro Ltd * Copyright (c) 2023 Linaro Limited */ /* Core SHA-3 transform using v8 Crypto Extensions */ #include #include .irp b,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,\ 21,22,23,24,25,26,27,28,29,30,31 .set .Lv\b\().2d, \b .set .Lv\b\().16b, \b .endr /* * ARMv8.2 Crypto Extensions instructions */ .macro eor3, rd, rn, rm, ra .inst 0xce000000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | \ (.L\rm << 16) .endm .macro rax1, rd, rn, rm .inst 0xce608c00 | .L\rd | (.L\rn << 5) | (.L\rm << 16) .endm .macro bcax, rd, rn, rm, ra .inst 0xce200000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | \ (.L\rm << 16) .endm .macro xar, rd, rn, rm, imm6 .inst 0xce800000 | .L\rd | (.L\rn << 5) | ((\imm6) << 10) | \ (.L\rm << 16) .endm /* * int sha3_ce_transform(u64 *st, const u8 *data, int blocks, * int dg_size) */ .text FUNC sha3_ce_transform , : /* load state */ add x8, x0, #32 ld1 { v0.1d- v3.1d}, [x0] ld1 { v4.1d- v7.1d}, [x8], #32 ld1 { v8.1d-v11.1d}, [x8], #32 ld1 {v12.1d-v15.1d}, [x8], #32 ld1 {v16.1d-v19.1d}, [x8], #32 ld1 {v20.1d-v23.1d}, [x8], #32 ld1 {v24.1d}, [x8] 0: sub w2, w2, #1 mov w8, #24 adr_l x9, .Lsha3_rcon /* load input */ ld1 {v25.8b-v28.8b}, [x1], #32 ld1 {v29.8b-v31.8b}, [x1], #24 eor v0.8b, v0.8b, v25.8b eor v1.8b, v1.8b, v26.8b eor v2.8b, v2.8b, v27.8b eor v3.8b, v3.8b, v28.8b eor v4.8b, v4.8b, v29.8b eor v5.8b, v5.8b, v30.8b eor v6.8b, v6.8b, v31.8b /* Bit 6 set? -> SHA3-512 */ tbnz x3, #6, 3f /* SHA3-384, SHA3-256, SHA3-224 or SHA3-128 */ ld1 {v25.8b-v28.8b}, [x1], #32 ld1 {v29.8b-v30.8b}, [x1], #16 eor v7.8b, v7.8b, v25.8b eor v8.8b, v8.8b, v26.8b eor v9.8b, v9.8b, v27.8b eor v10.8b, v10.8b, v28.8b eor v11.8b, v11.8b, v29.8b eor v12.8b, v12.8b, v30.8b /* bit 4 set? -> SHA3-384, SHA3-224 or SHA3-128 */ tbnz x3, #4, 1f /* SHA3-256: digest size 32 bytes, block size 136 bytes */ ld1 {v25.8b-v28.8b}, [x1], #32 eor v13.8b, v13.8b, v25.8b eor v14.8b, v14.8b, v26.8b eor v15.8b, v15.8b, v27.8b eor v16.8b, v16.8b, v28.8b b 4f /* bit 5 set? -> SHA-384 */ 1: tbnz x3, #5, 4f /* SHA3-224 or SHA3-128 */ ld1 {v25.8b-v28.8b}, [x1], #32 eor v13.8b, v13.8b, v25.8b eor v14.8b, v14.8b, v26.8b eor v15.8b, v15.8b, v27.8b eor v16.8b, v16.8b, v28.8b /* bit 2 set? -> SHA-224 */ tbnz x3, #2, 2f /* SHA3-128: digest size 16 bytes, block size 168 bytes */ ld1 {v25.8b-v28.8b}, [x1], #32 eor v17.8b, v17.8b, v25.8b eor v18.8b, v18.8b, v26.8b eor v19.8b, v19.8b, v27.8b eor v20.8b, v20.8b, v28.8b b 4f /* SHA3-224: digest size 28 bytes, block size 144 bytes */ 2: ld1 {v29.8b}, [x1], #8 eor v17.8b, v17.8b, v29.8b b 4f /* SHA3-512: digest size 64 bytes , block size 72 bytes */ 3: ld1 {v25.8b-v26.8b}, [x1], #16 eor v7.8b, v7.8b, v25.8b eor v8.8b, v8.8b, v26.8b 4: sub w8, w8, #1 eor3 v29.16b, v4.16b, v9.16b, v14.16b eor3 v26.16b, v1.16b, v6.16b, v11.16b eor3 v28.16b, v3.16b, v8.16b, v13.16b eor3 v25.16b, v0.16b, v5.16b, v10.16b eor3 v27.16b, v2.16b, v7.16b, v12.16b eor3 v29.16b, v29.16b, v19.16b, v24.16b eor3 v26.16b, v26.16b, v16.16b, v21.16b eor3 v28.16b, v28.16b, v18.16b, v23.16b eor3 v25.16b, v25.16b, v15.16b, v20.16b eor3 v27.16b, v27.16b, v17.16b, v22.16b rax1 v30.2d, v29.2d, v26.2d // bc[0] rax1 v26.2d, v26.2d, v28.2d // bc[2] rax1 v28.2d, v28.2d, v25.2d // bc[4] rax1 v25.2d, v25.2d, v27.2d // bc[1] rax1 v27.2d, v27.2d, v29.2d // bc[3] eor v0.16b, v0.16b, v30.16b xar v29.2d, v1.2d, v25.2d, (64 - 1) xar v1.2d, v6.2d, v25.2d, (64 - 44) xar v6.2d, v9.2d, v28.2d, (64 - 20) xar v9.2d, v22.2d, v26.2d, (64 - 61) xar v22.2d, v14.2d, v28.2d, (64 - 39) xar v14.2d, v20.2d, v30.2d, (64 - 18) xar v31.2d, v2.2d, v26.2d, (64 - 62) xar v2.2d, v12.2d, v26.2d, (64 - 43) xar v12.2d, v13.2d, v27.2d, (64 - 25) xar v13.2d, v19.2d, v28.2d, (64 - 8) xar v19.2d, v23.2d, v27.2d, (64 - 56) xar v23.2d, v15.2d, v30.2d, (64 - 41) xar v15.2d, v4.2d, v28.2d, (64 - 27) xar v28.2d, v24.2d, v28.2d, (64 - 14) xar v24.2d, v21.2d, v25.2d, (64 - 2) xar v8.2d, v8.2d, v27.2d, (64 - 55) xar v4.2d, v16.2d, v25.2d, (64 - 45) xar v16.2d, v5.2d, v30.2d, (64 - 36) xar v5.2d, v3.2d, v27.2d, (64 - 28) xar v27.2d, v18.2d, v27.2d, (64 - 21) xar v3.2d, v17.2d, v26.2d, (64 - 15) xar v25.2d, v11.2d, v25.2d, (64 - 10) xar v26.2d, v7.2d, v26.2d, (64 - 6) xar v30.2d, v10.2d, v30.2d, (64 - 3) bcax v20.16b, v31.16b, v22.16b, v8.16b bcax v21.16b, v8.16b, v23.16b, v22.16b bcax v22.16b, v22.16b, v24.16b, v23.16b bcax v23.16b, v23.16b, v31.16b, v24.16b bcax v24.16b, v24.16b, v8.16b, v31.16b ld1r {v31.2d}, [x9], #8 bcax v17.16b, v25.16b, v19.16b, v3.16b bcax v18.16b, v3.16b, v15.16b, v19.16b bcax v19.16b, v19.16b, v16.16b, v15.16b bcax v15.16b, v15.16b, v25.16b, v16.16b bcax v16.16b, v16.16b, v3.16b, v25.16b bcax v10.16b, v29.16b, v12.16b, v26.16b bcax v11.16b, v26.16b, v13.16b, v12.16b bcax v12.16b, v12.16b, v14.16b, v13.16b bcax v13.16b, v13.16b, v29.16b, v14.16b bcax v14.16b, v14.16b, v26.16b, v29.16b bcax v7.16b, v30.16b, v9.16b, v4.16b bcax v8.16b, v4.16b, v5.16b, v9.16b bcax v9.16b, v9.16b, v6.16b, v5.16b bcax v5.16b, v5.16b, v30.16b, v6.16b bcax v6.16b, v6.16b, v4.16b, v30.16b bcax v3.16b, v27.16b, v0.16b, v28.16b bcax v4.16b, v28.16b, v1.16b, v0.16b bcax v0.16b, v0.16b, v2.16b, v1.16b bcax v1.16b, v1.16b, v27.16b, v2.16b bcax v2.16b, v2.16b, v28.16b, v27.16b eor v0.16b, v0.16b, v31.16b cbnz w8, 4b cbnz w2, 0b /* save state */ st1 { v0.1d- v3.1d}, [x0], #32 st1 { v4.1d- v7.1d}, [x0], #32 st1 { v8.1d-v11.1d}, [x0], #32 st1 {v12.1d-v15.1d}, [x0], #32 st1 {v16.1d-v19.1d}, [x0], #32 st1 {v20.1d-v23.1d}, [x0], #32 st1 {v24.1d}, [x0] mov w0, w2 ret END_FUNC sha3_ce_transform .section ".rodata", "a" .align 8 LOCAL_DATA .Lsha3_rcon , : .quad 0x0000000000000001, 0x0000000000008082, 0x800000000000808a .quad 0x8000000080008000, 0x000000000000808b, 0x0000000080000001 .quad 0x8000000080008081, 0x8000000000008009, 0x000000000000008a .quad 0x0000000000000088, 0x0000000080008009, 0x000000008000000a .quad 0x000000008000808b, 0x800000000000008b, 0x8000000000008089 .quad 0x8000000000008003, 0x8000000000008002, 0x8000000000000080 .quad 0x000000000000800a, 0x800000008000000a, 0x8000000080008081 .quad 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sha512_armv8a_ce.c000066400000000000000000000010321464416617300224030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include /* Prototype for assembly function */ void sha512_ce_transform(uint64_t state[8], const void *src, unsigned int block_count); void crypto_accel_sha512_compress(uint64_t state[8], const void *src, unsigned int block_count) { uint32_t vfp_state = 0; vfp_state = thread_kernel_enable_vfp(); sha512_ce_transform(state, src, block_count); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/sha512_armv8a_ce_a64.S000066400000000000000000000144611464416617300230470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Linaro Limited * Copyright (C) 2018 Linaro Ltd */ /* Core SHA-384/SHA-512 transform using v8 Crypto Extensions */ #include #include .irp b,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 .set .Lq\b, \b .set .Lv\b\().2d, \b .endr .macro sha512h, rd, rn, rm .inst 0xce608000 | .L\rd | (.L\rn << 5) | (.L\rm << 16) .endm .macro sha512h2, rd, rn, rm .inst 0xce608400 | .L\rd | (.L\rn << 5) | (.L\rm << 16) .endm .macro sha512su0, rd, rn .inst 0xcec08000 | .L\rd | (.L\rn << 5) .endm .macro sha512su1, rd, rn, rm .inst 0xce608800 | .L\rd | (.L\rn << 5) | (.L\rm << 16) .endm /* * The SHA-512 round constants */ .section ".rodata", "a" .align 4 LOCAL_DATA .Lsha512_rcon , : .quad 0x428a2f98d728ae22, 0x7137449123ef65cd .quad 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc .quad 0x3956c25bf348b538, 0x59f111f1b605d019 .quad 0x923f82a4af194f9b, 0xab1c5ed5da6d8118 .quad 0xd807aa98a3030242, 0x12835b0145706fbe .quad 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2 .quad 0x72be5d74f27b896f, 0x80deb1fe3b1696b1 .quad 0x9bdc06a725c71235, 0xc19bf174cf692694 .quad 0xe49b69c19ef14ad2, 0xefbe4786384f25e3 .quad 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65 .quad 0x2de92c6f592b0275, 0x4a7484aa6ea6e483 .quad 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5 .quad 0x983e5152ee66dfab, 0xa831c66d2db43210 .quad 0xb00327c898fb213f, 0xbf597fc7beef0ee4 .quad 0xc6e00bf33da88fc2, 0xd5a79147930aa725 .quad 0x06ca6351e003826f, 0x142929670a0e6e70 .quad 0x27b70a8546d22ffc, 0x2e1b21385c26c926 .quad 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df .quad 0x650a73548baf63de, 0x766a0abb3c77b2a8 .quad 0x81c2c92e47edaee6, 0x92722c851482353b .quad 0xa2bfe8a14cf10364, 0xa81a664bbc423001 .quad 0xc24b8b70d0f89791, 0xc76c51a30654be30 .quad 0xd192e819d6ef5218, 0xd69906245565a910 .quad 0xf40e35855771202a, 0x106aa07032bbd1b8 .quad 0x19a4c116b8d2d0c8, 0x1e376c085141ab53 .quad 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8 .quad 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb .quad 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3 .quad 0x748f82ee5defb2fc, 0x78a5636f43172f60 .quad 0x84c87814a1f0ab72, 0x8cc702081a6439ec .quad 0x90befffa23631e28, 0xa4506cebde82bde9 .quad 0xbef9a3f7b2c67915, 0xc67178f2e372532b .quad 0xca273eceea26619c, 0xd186b8c721c0c207 .quad 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178 .quad 0x06f067aa72176fba, 0x0a637dc5a2c898a6 .quad 0x113f9804bef90dae, 0x1b710b35131c471b .quad 0x28db77f523047d84, 0x32caab7b40c72493 .quad 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c .quad 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a .quad 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 END_DATA .Lsha512_rcon .macro dround, i0, i1, i2, i3, i4, rc0, rc1, in0, in1, in2, in3, in4 .ifnb \rc1 ld1 {v\rc1\().2d}, [x4], #16 .endif add v5.2d, v\rc0\().2d, v\in0\().2d ext v6.16b, v\i2\().16b, v\i3\().16b, #8 ext v5.16b, v5.16b, v5.16b, #8 ext v7.16b, v\i1\().16b, v\i2\().16b, #8 add v\i3\().2d, v\i3\().2d, v5.2d .ifnb \in1 ext v5.16b, v\in3\().16b, v\in4\().16b, #8 sha512su0 v\in0\().2d, v\in1\().2d .endif sha512h q\i3, q6, v7.2d .ifnb \in1 sha512su1 v\in0\().2d, v\in2\().2d, v5.2d .endif add v\i4\().2d, v\i1\().2d, v\i3\().2d sha512h2 q\i3, q\i1, v\i0\().2d .endm /* * void sha512_ce_transform(struct sha512_state *sst, u8 const *src, * int blocks) */ FUNC sha512_ce_transform , : /* load state */ ld1 {v8.2d-v11.2d}, [x0] /* load first 4 round constants */ adr_l x3, .Lsha512_rcon ld1 {v20.2d-v23.2d}, [x3], #64 /* load input */ 0: ld1 {v12.2d-v15.2d}, [x1], #64 ld1 {v16.2d-v19.2d}, [x1], #64 sub w2, w2, #1 rev64 v12.16b, v12.16b rev64 v13.16b, v13.16b rev64 v14.16b, v14.16b rev64 v15.16b, v15.16b rev64 v16.16b, v16.16b rev64 v17.16b, v17.16b rev64 v18.16b, v18.16b rev64 v19.16b, v19.16b mov x4, x3 // rc pointer mov v0.16b, v8.16b mov v1.16b, v9.16b mov v2.16b, v10.16b mov v3.16b, v11.16b // v0 ab cd -- ef gh ab // v1 cd -- ef gh ab cd // v2 ef gh ab cd -- ef // v3 gh ab cd -- ef gh // v4 -- ef gh ab cd -- dround 0, 1, 2, 3, 4, 20, 24, 12, 13, 19, 16, 17 dround 3, 0, 4, 2, 1, 21, 25, 13, 14, 12, 17, 18 dround 2, 3, 1, 4, 0, 22, 26, 14, 15, 13, 18, 19 dround 4, 2, 0, 1, 3, 23, 27, 15, 16, 14, 19, 12 dround 1, 4, 3, 0, 2, 24, 28, 16, 17, 15, 12, 13 dround 0, 1, 2, 3, 4, 25, 29, 17, 18, 16, 13, 14 dround 3, 0, 4, 2, 1, 26, 30, 18, 19, 17, 14, 15 dround 2, 3, 1, 4, 0, 27, 31, 19, 12, 18, 15, 16 dround 4, 2, 0, 1, 3, 28, 24, 12, 13, 19, 16, 17 dround 1, 4, 3, 0, 2, 29, 25, 13, 14, 12, 17, 18 dround 0, 1, 2, 3, 4, 30, 26, 14, 15, 13, 18, 19 dround 3, 0, 4, 2, 1, 31, 27, 15, 16, 14, 19, 12 dround 2, 3, 1, 4, 0, 24, 28, 16, 17, 15, 12, 13 dround 4, 2, 0, 1, 3, 25, 29, 17, 18, 16, 13, 14 dround 1, 4, 3, 0, 2, 26, 30, 18, 19, 17, 14, 15 dround 0, 1, 2, 3, 4, 27, 31, 19, 12, 18, 15, 16 dround 3, 0, 4, 2, 1, 28, 24, 12, 13, 19, 16, 17 dround 2, 3, 1, 4, 0, 29, 25, 13, 14, 12, 17, 18 dround 4, 2, 0, 1, 3, 30, 26, 14, 15, 13, 18, 19 dround 1, 4, 3, 0, 2, 31, 27, 15, 16, 14, 19, 12 dround 0, 1, 2, 3, 4, 24, 28, 16, 17, 15, 12, 13 dround 3, 0, 4, 2, 1, 25, 29, 17, 18, 16, 13, 14 dround 2, 3, 1, 4, 0, 26, 30, 18, 19, 17, 14, 15 dround 4, 2, 0, 1, 3, 27, 31, 19, 12, 18, 15, 16 dround 1, 4, 3, 0, 2, 28, 24, 12, 13, 19, 16, 17 dround 0, 1, 2, 3, 4, 29, 25, 13, 14, 12, 17, 18 dround 3, 0, 4, 2, 1, 30, 26, 14, 15, 13, 18, 19 dround 2, 3, 1, 4, 0, 31, 27, 15, 16, 14, 19, 12 dround 4, 2, 0, 1, 3, 24, 28, 16, 17, 15, 12, 13 dround 1, 4, 3, 0, 2, 25, 29, 17, 18, 16, 13, 14 dround 0, 1, 2, 3, 4, 26, 30, 18, 19, 17, 14, 15 dround 3, 0, 4, 2, 1, 27, 31, 19, 12, 18, 15, 16 dround 2, 3, 1, 4, 0, 28, 24, 12 dround 4, 2, 0, 1, 3, 29, 25, 13 dround 1, 4, 3, 0, 2, 30, 26, 14 dround 0, 1, 2, 3, 4, 31, 27, 15 dround 3, 0, 4, 2, 1, 24, , 16 dround 2, 3, 1, 4, 0, 25, , 17 dround 4, 2, 0, 1, 3, 26, , 18 dround 1, 4, 3, 0, 2, 27, , 19 /* update state */ add v8.2d, v8.2d, v0.2d add v9.2d, v9.2d, v1.2d add v10.2d, v10.2d, v2.2d add v11.2d, v11.2d, v3.2d /* handled all input blocks? */ cbnz w2, 0b /* store new state */ 3: st1 {v8.2d-v11.2d}, [x0] mov w0, w2 ret END_FUNC sha512_ce_transform BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sm3_armv8a_ce.c000066400000000000000000000010311464416617300221010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022 Linaro Limited */ #include #include /* Prototype for assembly function */ void sm3_ce_transform(uint32_t state[8], const void *src, unsigned int block_count); void crypto_accel_sm3_compress(uint32_t state[8], const void *src, unsigned int block_count) { uint32_t vfp_state = 0; vfp_state = thread_kernel_enable_vfp(); sm3_ce_transform(state, src, block_count); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/sm3_armv8a_ce_a64.S000066400000000000000000000064051464416617300225450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022 Linaro Limited * Copyright (C) 2018 Linaro Ltd */ /* Core SM3 secure hash using ARMv8.2 Crypto Extensions */ #include #include .irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 .set .Lv\b\().4s, \b .endr .macro sm3partw1, rd, rn, rm .inst 0xce60c000 | .L\rd | (.L\rn << 5) | (.L\rm << 16) .endm .macro sm3partw2, rd, rn, rm .inst 0xce60c400 | .L\rd | (.L\rn << 5) | (.L\rm << 16) .endm .macro sm3ss1, rd, rn, rm, ra .inst 0xce400000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | (.L\rm << 16) .endm .macro sm3tt1a, rd, rn, rm, imm2 .inst 0xce408000 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) .endm .macro sm3tt1b, rd, rn, rm, imm2 .inst 0xce408400 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) .endm .macro sm3tt2a, rd, rn, rm, imm2 .inst 0xce408800 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) .endm .macro sm3tt2b, rd, rn, rm, imm2 .inst 0xce408c00 | .L\rd | (.L\rn << 5) | ((\imm2) << 12) | (.L\rm << 16) .endm .macro round, ab, s0, t0, t1, i sm3ss1 v5.4s, v8.4s, \t0\().4s, v9.4s shl \t1\().4s, \t0\().4s, #1 sri \t1\().4s, \t0\().4s, #31 sm3tt1\ab v8.4s, v5.4s, v10.4s, \i sm3tt2\ab v9.4s, v5.4s, \s0\().4s, \i .endm .macro qround, ab, s0, s1, s2, s3, s4 .ifnb \s4 ext \s4\().16b, \s1\().16b, \s2\().16b, #12 ext v6.16b, \s0\().16b, \s1\().16b, #12 ext v7.16b, \s2\().16b, \s3\().16b, #8 sm3partw1 \s4\().4s, \s0\().4s, \s3\().4s .endif eor v10.16b, \s0\().16b, \s1\().16b round \ab, \s0, v11, v12, 0 round \ab, \s0, v12, v11, 1 round \ab, \s0, v11, v12, 2 round \ab, \s0, v12, v11, 3 .ifnb \s4 sm3partw2 \s4\().4s, v7.4s, v6.4s .endif .endm /* * void sm3_ce_transform(struct sm3_state *sst, u8 const *src, * int blocks) */ FUNC sm3_ce_transform , : /* load state */ ld1 {v8.4s-v9.4s}, [x0] rev64 v8.4s, v8.4s rev64 v9.4s, v9.4s ext v8.16b, v8.16b, v8.16b, #8 ext v9.16b, v9.16b, v9.16b, #8 adr_l x8, .Lt ldp s13, s14, [x8] /* load input */ 0: ld1 {v0.16b-v3.16b}, [x1], #64 sub w2, w2, #1 mov v15.16b, v8.16b mov v16.16b, v9.16b rev32 v0.16b, v0.16b rev32 v1.16b, v1.16b rev32 v2.16b, v2.16b rev32 v3.16b, v3.16b ext v11.16b, v13.16b, v13.16b, #4 qround a, v0, v1, v2, v3, v4 qround a, v1, v2, v3, v4, v0 qround a, v2, v3, v4, v0, v1 qround a, v3, v4, v0, v1, v2 ext v11.16b, v14.16b, v14.16b, #4 qround b, v4, v0, v1, v2, v3 qround b, v0, v1, v2, v3, v4 qround b, v1, v2, v3, v4, v0 qround b, v2, v3, v4, v0, v1 qround b, v3, v4, v0, v1, v2 qround b, v4, v0, v1, v2, v3 qround b, v0, v1, v2, v3, v4 qround b, v1, v2, v3, v4, v0 qround b, v2, v3, v4, v0, v1 qround b, v3, v4 qround b, v4, v0 qround b, v0, v1 eor v8.16b, v8.16b, v15.16b eor v9.16b, v9.16b, v16.16b /* handled all input blocks? */ cbnz w2, 0b /* save state */ rev64 v8.4s, v8.4s rev64 v9.4s, v9.4s ext v8.16b, v8.16b, v8.16b, #8 ext v9.16b, v9.16b, v9.16b, #8 st1 {v8.4s-v9.4s}, [x0] ret END_FUNC sm3_ce_transform .section ".rodata", "a" .align 3 LOCAL_DATA .Lt , : .word 0x79cc4519, 0x9d8a7a87 END_DATA .Lt BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sm4_armv8a_aese_a64.S000066400000000000000000000642511464416617300230770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. * Copyright (C) 2022, Alibaba Group. * Copyright (C) 2022 Tianjia Zhang * * SM4 optimization for ARMv8 by NEON and AES HW instruction, which is an * optional Cryptographic Extension for ARMv8-A. * * The NEON implementation refers to Linux kernel (sm4-neon-core.S contributed * by Tianjia Zhang ). * * The AES trick refers to sm4ni (https://github.com/mjosaarinen/sm4ni). The * constants used in load_sbox_matrix are from this blog (https://www.cnblogs. * com/kentle/p/15826075.html). We've done some further optimizations so the * constants don't look the same. */ #include .arch armv8-a+crypto #define m0 w9 #define m1 w10 #define m2 w11 #define m3 w12 #define tw0l x7 #define tw0h x8 #define tw1l x9 #define tw1h x10 #define tw2l x11 #define tw2h x12 #define tw3l x13 #define tw3h x14 #define tw4l x15 #define tw4h x16 #define tw5l x17 #define tw5h x18 #define tw6l x19 #define tw6h x20 #define tw7l x21 #define tw7h x22 #define tmpw0 w23 #define tmpx0 x23 #define tmpw1 w24 #define tmpx1 x24 #define tmpw2 w25 /* round keys: v0-v7 */ #define RK0 v0 #define RK1 v1 #define RK2 v2 #define RK3 v3 #define RK4 v4 #define RK5 v5 #define RK6 v6 #define RK7 v7 /* plain blocks: v8-v15 */ #define BLK0 v8 #define BLK1 v9 #define BLK2 v10 #define BLK3 v11 #define BLK4 v12 #define BLK5 v13 #define BLK6 v14 #define BLK7 v15 #define TMP0 v16 #define TMP1 v17 #define TMP2 v18 #define TMP3 v19 #define TMP4 v20 #define TMP5 v21 #define TMP6 v22 #define TMP7 v23 #define TMP8 v24 #define IV v25 #define ANDMASKV v26 #define ANDMASKQ q26 #define ATALMaskV v27 #define ATALMaskQ q27 #define ATAHMaskV v28 #define ATAHMaskQ q28 #define TALMaskV v29 #define TALMaskQ q29 #define TAHMaskV v30 #define TAHMaskQ q30 #define MASKV v31 #define MASKQ q31 .macro frame_push stp x15, x16, [sp, #-0x10]! stp x17, x18, [sp, #-0x10]! stp x19, x20, [sp, #-0x10]! stp x21, x22, [sp, #-0x10]! stp x23, x24, [sp, #-0x10]! stp x25, x26, [sp, #-0x10]! stp x27, x28, [sp, #-0x10]! stp x29, x30, [sp, #-0x10]! stp d8, d9, [sp, #-0x10]! stp d10, d11, [sp, #-0x10]! stp d12, d13, [sp, #-0x10]! stp d14, d15, [sp, #-0x10]! .endm .macro frame_pop ldp d14, d15, [sp], #0x10 ldp d12, d13, [sp], #0x10 ldp d10, d11, [sp], #0x10 ldp d8, d9, [sp], #0x10 ldp x29, x30, [sp], #0x10 ldp x27, x28, [sp], #0x10 ldp x25, x26, [sp], #0x10 ldp x23, x24, [sp], #0x10 ldp x21, x22, [sp], #0x10 ldp x19, x20, [sp], #0x10 ldp x17, x18, [sp], #0x10 ldp x15, x16, [sp], #0x10 .endm .macro load_sbox_matrix ldr MASKQ, .Lsbox_magic ldr TAHMaskQ, .Lsbox_magic+16 ldr TALMaskQ, .Lsbox_magic+32 ldr ATAHMaskQ, .Lsbox_magic+48 ldr ATALMaskQ, .Lsbox_magic+64 ldr ANDMASKQ, .Lsbox_magic+80 .endm .macro multi_matrix, x, high, low, tmp ushr \tmp\().16b, \x\().16b, 4 and \x\().16b, \x\().16b, ANDMASKV.16b tbl \x\().16b, {\low\().16b}, \x\().16b tbl \tmp\().16b, {\high\().16b}, \tmp\().16b eor \x\().16b, \x\().16b, \tmp\().16b .endm .macro sbox, des, src, tmp1, tmp2 tbl \des\().16b, {\src\().16b}, MASKV.16b multi_matrix \des, TAHMaskV, TALMaskV, \tmp2 eor \tmp1\().16b, \tmp1\().16b, \tmp1\().16b aese \des\().16b, \tmp1\().16b multi_matrix \des, ATAHMaskV, ATALMaskV, \tmp2 .endm .macro sbox_double, des0, src0, des1, src1, tmp1, tmp2 tbl \des0\().16b, {\src0\().16b}, MASKV.16b tbl \des1\().16b, {\src1\().16b}, MASKV.16b multi_matrix \des0, TAHMaskV, TALMaskV, \tmp2 multi_matrix \des1, TAHMaskV, TALMaskV, \tmp2 eor \tmp1\().16b, \tmp1\().16b, \tmp1\().16b aese \des0\().16b, \tmp1\().16b multi_matrix \des0, ATAHMaskV, ATALMaskV, \tmp2 aese \des1\().16b, \tmp1\().16b multi_matrix \des1, ATAHMaskV, ATALMaskV, \tmp2 .endm .macro round, c0, c1, c2, c3, k mov tmpw0, \k eor tmpw1, \c1, \c2 eor tmpw0, \c3, tmpw0 eor tmpw2, tmpw1, tmpw0 mov TMP0.s[0], tmpw2 /* nonlinear transformation */ sbox TMP1, TMP0, TMP2, TMP3 /* linear transformation */ mov tmpw2, TMP1.s[0] ror tmpw0, tmpw2, #(32-10) eor tmpw0, tmpw0, tmpw2, ror #(32-2) ror tmpw1, tmpw2, #(32-24) eor tmpw1, tmpw1, tmpw2, ror #(32-18) eor tmpw0, tmpw0, tmpw1 eor tmpw2, tmpw0, tmpw2 eor \c0, \c0, tmpw2 .endm .macro round4_enc, k round m0, m1, m2, m3, \k\().s[0] round m1, m2, m3, m0, \k\().s[1] round m2, m3, m0, m1, \k\().s[2] round m3, m0, m1, m2, \k\().s[3] .endm .macro round4_dec, k round m0, m1, m2, m3, \k\().s[3] round m1, m2, m3, m0, \k\().s[2] round m2, m3, m0, m1, \k\().s[1] round m3, m0, m1, m2, \k\().s[0] .endm .macro encrypt_block_no_rev, in mov m0, \in\().s[0] mov m1, \in\().s[1] mov m2, \in\().s[2] mov m3, \in\().s[3] round4_enc RK0 round4_enc RK1 round4_enc RK2 round4_enc RK3 round4_enc RK4 round4_enc RK5 round4_enc RK6 round4_enc RK7 mov \in\().s[0], m3 mov \in\().s[1], m2 mov \in\().s[2], m1 mov \in\().s[3], m0 .endm .macro encrypt_block, in rev32 \in\().16b, \in\().16b encrypt_block_no_rev \in rev32 \in\().16b, \in\().16b .endm .macro decrypt_block_no_rev, in mov m0, \in\().s[0] mov m1, \in\().s[1] mov m2, \in\().s[2] mov m3, \in\().s[3] round4_dec RK7 round4_dec RK6 round4_dec RK5 round4_dec RK4 round4_dec RK3 round4_dec RK2 round4_dec RK1 round4_dec RK0 mov \in\().s[0], m3 mov \in\().s[1], m2 mov \in\().s[2], m1 mov \in\().s[3], m0 .endm .macro decrypt_block, in rev32 \in\().16b, \in\().16b decrypt_block_no_rev \in rev32 \in\().16b, \in\().16b .endm LOCAL_FUNC sm4_encrypt_block1x , : encrypt_block BLK0 ret END_FUNC sm4_encrypt_block1x LOCAL_FUNC sm4_decrypt_block1x , : decrypt_block BLK0 ret END_FUNC sm4_decrypt_block1x .macro transpose_4x4, s0, s1, s2, s3 zip1 TMP0.4s, \s0\().4s, \s1\().4s zip1 TMP1.4s, \s2\().4s, \s3\().4s zip2 TMP2.4s, \s0\().4s, \s1\().4s zip2 TMP3.4s, \s2\().4s, \s3\().4s zip1 \s0\().2d, TMP0.2d, TMP1.2d zip2 \s1\().2d, TMP0.2d, TMP1.2d zip1 \s2\().2d, TMP2.2d, TMP3.2d zip2 \s3\().2d, TMP2.2d, TMP3.2d .endm .macro rotate_clockwise_90, s0, s1, s2, s3 zip1 TMP0.4s, \s1\().4s, \s0\().4s zip2 TMP1.4s, \s1\().4s, \s0\().4s zip1 TMP2.4s, \s3\().4s, \s2\().4s zip2 TMP3.4s, \s3\().4s, \s2\().4s zip1 \s0\().2d, TMP2.2d, TMP0.2d zip2 \s1\().2d, TMP2.2d, TMP0.2d zip1 \s2\().2d, TMP3.2d, TMP1.2d zip2 \s3\().2d, TMP3.2d, TMP1.2d .endm .macro round_4x, s0, s1, s2, s3, k dup TMP8.4s, \k eor TMP1.16b, \s2\().16b, \s3\().16b eor TMP8.16b, TMP8.16b, \s1\().16b eor TMP8.16b, TMP8.16b, TMP1.16b /* nonlinear transformation */ sbox TMP0, TMP8, TMP2, TMP3 /* linear transformation */ shl TMP1.4s, TMP0.4s, #2 shl TMP2.4s, TMP0.4s, #10 shl TMP3.4s, TMP0.4s, #18 shl TMP4.4s, TMP0.4s, #24 sri TMP1.4s, TMP0.4s, #(32-2) sri TMP2.4s, TMP0.4s, #(32-10) sri TMP3.4s, TMP0.4s, #(32-18) sri TMP4.4s, TMP0.4s, #(32-24) eor TMP0.16b, TMP0.16b, TMP1.16b eor TMP2.16b, TMP2.16b, TMP3.16b eor TMP4.16b, TMP4.16b, \s0\().16b eor TMP0.16b, TMP0.16b, TMP2.16b eor \s0\().16b, TMP0.16b, TMP4.16b .endm .macro round4_4x, k round_4x BLK0, BLK1, BLK2, BLK3, \k\().s[0] round_4x BLK1, BLK2, BLK3, BLK0, \k\().s[1] round_4x BLK2, BLK3, BLK0, BLK1, \k\().s[2] round_4x BLK3, BLK0, BLK1, BLK2, \k\().s[3] .endm LOCAL_FUNC sm4_encrypt_block4x , : rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b transpose_4x4 BLK0, BLK1, BLK2, BLK3 round4_4x RK0 round4_4x RK1 round4_4x RK2 round4_4x RK3 round4_4x RK4 round4_4x RK5 round4_4x RK6 round4_4x RK7 rotate_clockwise_90 BLK0, BLK1, BLK2, BLK3 rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b ret END_FUNC sm4_encrypt_block4x .macro round_8x, s0, s1, s2, s3, t0, t1, t2, t3, k dup TMP8.4s, \k eor TMP0.16b, \s2\().16b, \s3\().16b mov TMP7.16b, TMP8.16b eor TMP1.16b, \t2\().16b, \t3\().16b eor TMP8.16b, TMP8.16b, \s1\().16b eor TMP7.16b, TMP7.16b, \t1\().16b eor TMP8.16b, TMP8.16b, TMP0.16b eor TMP7.16b, TMP7.16b, TMP1.16b /* nonlinear transformation */ sbox_double TMP0, TMP8, TMP1, TMP7, TMP2, TMP3 /* linear transformation */ shl TMP6.4s, TMP0.4s, #2 shl TMP8.4s, TMP1.4s, #2 shl TMP2.4s, TMP0.4s, #10 shl TMP5.4s, TMP1.4s, #10 shl TMP3.4s, TMP0.4s, #18 shl TMP4.4s, TMP0.4s, #24 sri TMP6.4s, TMP0.4s, #(32-2) sri TMP2.4s, TMP0.4s, #(32-10) sri TMP3.4s, TMP0.4s, #(32-18) sri TMP4.4s, TMP0.4s, #(32-24) eor TMP0.16b, TMP0.16b, TMP6.16b eor TMP2.16b, TMP2.16b, TMP3.16b shl TMP6.4s, TMP1.4s, #18 shl TMP7.4s, TMP1.4s, #24 sri TMP8.4s, TMP1.4s, #(32-2) sri TMP5.4s, TMP1.4s, #(32-10) sri TMP6.4s, TMP1.4s, #(32-18) sri TMP7.4s, TMP1.4s, #(32-24) eor TMP4.16b, TMP4.16b, \s0\().16b eor TMP1.16b, TMP1.16b, TMP8.16b eor \s0\().16b, TMP0.16b, TMP2.16b eor \s0\().16b, \s0\().16b, TMP4.16b eor TMP5.16b, TMP5.16b, TMP6.16b eor TMP7.16b, TMP7.16b, \t0\().16b eor TMP1.16b, TMP1.16b, TMP5.16b eor \t0\().16b, TMP1.16b, TMP7.16b .endm .macro round4_8x, k round_8x BLK0, BLK1, BLK2, BLK3, BLK4, BLK5, BLK6, BLK7, \k\().s[0] round_8x BLK1, BLK2, BLK3, BLK0, BLK5, BLK6, BLK7, BLK4, \k\().s[1] round_8x BLK2, BLK3, BLK0, BLK1, BLK6, BLK7, BLK4, BLK5, \k\().s[2] round_8x BLK3, BLK0, BLK1, BLK2, BLK7, BLK4, BLK5, BLK6, \k\().s[3] .endm LOCAL_FUNC sm4_encrypt_block8x , : rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b rev32 BLK4.16b, BLK4.16b rev32 BLK5.16b, BLK5.16b rev32 BLK6.16b, BLK6.16b rev32 BLK7.16b, BLK7.16b transpose_4x4 BLK0, BLK1, BLK2, BLK3 transpose_4x4 BLK4, BLK5, BLK6, BLK7 round4_8x RK0 round4_8x RK1 round4_8x RK2 round4_8x RK3 round4_8x RK4 round4_8x RK5 round4_8x RK6 round4_8x RK7 rotate_clockwise_90 BLK0, BLK1, BLK2, BLK3 rotate_clockwise_90 BLK4, BLK5, BLK6, BLK7 rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b rev32 BLK4.16b, BLK4.16b rev32 BLK5.16b, BLK5.16b rev32 BLK6.16b, BLK6.16b rev32 BLK7.16b, BLK7.16b ret END_FUNC sm4_encrypt_block8x .macro inc_le128, vctr, low, high mov \vctr\().d[1], \high mov \vctr\().d[0], \low adds \high, \high, #1 adc \low, \low, xzr rev64 \vctr\().16b, \vctr\().16b .endm .macro mov_reg_to_vec, desv, src0, src1 mov \desv\().d[0], \src0 mov \desv\().d[1], \src1 .endm .macro next_tweak, des0, des1, src0, src1 mov tmpw2, 0x87 extr tmpx0, \src1, \src1, #32 extr \des1, \src1, \src0, #63 and tmpw1, tmpw2, tmpw0, asr#31 eor \des0, tmpx1, \src0, lsl#1 .endm .macro next_tweak_vec, desv, srcv mov tw0l, \srcv\().d[0] mov tw0h, \srcv\().d[1] next_tweak tw1l, tw1h, tw0l, tw0h mov \desv\().d[0], tw1l mov \desv\().d[1], tw1h .endm LOCAL_DATA .Lck , : .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269 .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9 .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249 .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9 .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229 .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299 .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209 .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 END_DATA .Lck LOCAL_DATA .Lfk , : .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc END_DATA .Lfk LOCAL_DATA .Lshuffles , : .long 0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x03020100 END_DATA .Lshuffles LOCAL_DATA .Lsbox_magic , : .dword 0x0b0e0104070a0d00, 0x0306090c0f020508 .dword 0x62185a2042387a00, 0x22581a6002783a40 .dword 0x15df62a89e54e923, 0xc10bb67c4a803df7 .dword 0xb9aa6b78c1d21300, 0x1407c6d56c7fbead .dword 0x6404462679195b3b, 0xe383c1a1fe9edcbc .dword 0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f END_DATA .Lsbox_magic .macro sm4_setkey ld1 {v5.4s}, [x1] load_sbox_matrix rev32 v5.16b, v5.16b adr x5, .Lfk ld1 {v6.4s}, [x5] eor v5.16b, v5.16b, v6.16b mov x6, #32 adr x5, .Lck 1: mov w7, v5.s[1] ldr w8, [x5], #4 eor w8, w8, w7 mov w7, v5.s[2] eor w8, w8, w7 mov w7, v5.s[3] eor w8, w8, w7 /* optimize sbox using AESE instruction */ mov TMP0.s[0], w8 sbox TMP1, TMP0, TMP2, TMP3 mov w7, TMP1.s[0] /* linear transformation */ eor w8, w7, w7, ror #19 eor w8, w8, w7, ror #9 mov w7, v5.s[0] eor w8, w8, w7 mov v5.s[0], w8 ext v5.16b, v5.16b, v5.16b, 4 subs x6, x6, #1 .endm /* * void neon_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); * x0: round key * x1: user key */ FUNC neon_sm4_setkey_enc , : sm4_setkey str w8, [x0], #4 b.ne 1b ret END_FUNC neon_sm4_setkey_enc /* * void neon_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); * x0: round key * x1: user key */ FUNC neon_sm4_setkey_dec , : add x0, x0, 124 sm4_setkey str w8, [x0], #-4 b.ne 1b ret END_FUNC neon_sm4_setkey_dec /* * void neon_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len); * x0: output * x1: input * x2: round key * w3: length */ FUNC neon_sm4_ecb_encrypt , : frame_push load_sbox_matrix ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 .Lecbloop8x: cmp w3, 8 b.lt .Lecb4x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 bl sm4_encrypt_block8x st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w3, w3, #8 b.gt .Lecbloop8x .Lecb4x: cmp w3, 1 b.lt .Lecbout cmp w3, 2 b.lt .Lecb1x cmp w3, 3 b.lt .Lecb2x cmp w3, 4 b.lt .Lecb3x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 bl sm4_encrypt_block4x st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w3, w3, #4 b .Lecb4x .Lecb3x: ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 bl sm4_encrypt_block4x st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w3, w3, #3 b.le .Lecbout .Lecb2x: ld1 {BLK0.16b, BLK1.16b}, [x1], #32 bl sm4_encrypt_block4x st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w3, w3, #2 b.le .Lecbout .Lecb1x: ld1 {BLK0.16b}, [x1], #16 bl sm4_encrypt_block1x st1 {BLK0.16b}, [x0], #16 .Lecbout: frame_pop ret END_FUNC neon_sm4_ecb_encrypt /* * void neon_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len, * uint8_t iv[]); * x0: output * x1: input * x2: round key * w3: length * x4: iv */ FUNC neon_sm4_cbc_encrypt , : frame_push load_sbox_matrix ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 ld1 {IV.16b}, [x4] .Lcbcencloop4x: cmp w3, 4 b.lt .Lcbcenc1x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 eor BLK0.16b, BLK0.16b, IV.16b rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b encrypt_block_no_rev BLK0 eor BLK1.16b, BLK1.16b, BLK0.16b encrypt_block_no_rev BLK1 rev32 BLK0.16b, BLK0.16b eor BLK2.16b, BLK2.16b, BLK1.16b encrypt_block_no_rev BLK2 rev32 BLK1.16b, BLK1.16b eor BLK3.16b, BLK3.16b, BLK2.16b encrypt_block_no_rev BLK3 rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b mov IV.16b, BLK3.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 subs w3, w3, #4 b .Lcbcencloop4x .Lcbcenc1x: cmp w3, 1 b.lt .Lcbcencout .Lcbcencloop: ld1 {BLK0.16b}, [x1], #16 eor BLK0.16b, BLK0.16b, IV.16b bl sm4_encrypt_block1x mov IV.16b, BLK0.16b st1 {BLK0.16b}, [x0], #16 subs w3, w3, #1 bne .Lcbcencloop .Lcbcencout: st1 {IV.16b}, [x4] frame_pop ret END_FUNC neon_sm4_cbc_encrypt /* * void neon_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len, * uint8_t iv[]); * x0: output * x1: input * x2: round key * w3: length * x4: iv */ FUNC neon_sm4_cbc_decrypt , : frame_push load_sbox_matrix ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 ld1 {IV.16b}, [x4] .Lcbcdecloop8x: cmp w3, 8 b.lt .Lcbcdec4x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 bl sm4_encrypt_block8x sub x5, x1, #128 eor BLK0.16b, BLK0.16b, IV.16b ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 eor BLK1.16b, BLK1.16b, TMP0.16b eor BLK2.16b, BLK2.16b, TMP1.16b eor BLK3.16b, BLK3.16b, TMP2.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x5], #64 eor BLK4.16b, BLK4.16b, TMP3.16b eor BLK5.16b, BLK5.16b, TMP4.16b mov IV.16b, TMP7.16b eor BLK6.16b, BLK6.16b, TMP5.16b eor BLK7.16b, BLK7.16b, TMP6.16b st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w3, w3, #8 b.gt .Lcbcdecloop8x .Lcbcdec4x: cmp w3, 1 b.lt .Lcbcdecout cmp w3, 2 b.lt .Lcbcdec1x cmp w3, 3 b.lt .Lcbcdec2x cmp w3, 4 b.lt .Lcbcdec3x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 bl sm4_encrypt_block4x sub x5, x1, 64 ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 eor BLK0.16b, BLK0.16b, IV.16b eor BLK1.16b, BLK1.16b, TMP0.16b eor BLK2.16b, BLK2.16b, TMP1.16b eor BLK3.16b, BLK3.16b, TMP2.16b mov IV.16b, TMP3.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w3, w3, #4 b .Lcbcdec4x .Lcbcdec3x: ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 bl sm4_encrypt_block4x sub x5, x1, 48 ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x5], #48 eor BLK0.16b, BLK0.16b, IV.16b eor BLK1.16b, BLK1.16b, TMP0.16b eor BLK2.16b, BLK2.16b, TMP1.16b mov IV.16b, TMP2.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w3, w3, #3 b.le .Lcbcdecout .Lcbcdec2x: ld1 {BLK0.16b, BLK1.16b}, [x1], #32 bl sm4_encrypt_block4x sub x5, x1, 32 ld1 {TMP0.16b, TMP1.16b}, [x5], #32 eor BLK0.16b, BLK0.16b, IV.16b eor BLK1.16b, BLK1.16b, TMP0.16b mov IV.16b, TMP1.16b st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w3, w3, #2 b.le .Lcbcdecout .Lcbcdec1x: ld1 {BLK0.16b}, [x1], #16 bl sm4_encrypt_block1x sub x5, x1, 16 ld1 {TMP0.16b}, [x5], #16 eor BLK0.16b, BLK0.16b, IV.16b mov IV.16b, TMP0.16b st1 {BLK0.16b}, [x0], #16 .Lcbcdecout: st1 {IV.16b}, [x4] frame_pop ret END_FUNC neon_sm4_cbc_decrypt /* * void neon_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len, * uint8_t iv[]); * x0: output * x1: input * x2: round key * w3: length * x4: iv */ FUNC neon_sm4_ctr_encrypt , : frame_push load_sbox_matrix ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 ldp x7, x8, [x4] rev x7, x7 rev x8, x8 .Lctrloop8x: cmp w3, 8 b.lt .Lctr4x /* construct CTRs */ inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 inc_le128 BLK2, x7, x8 inc_le128 BLK3, x7, x8 inc_le128 BLK4, x7, x8 inc_le128 BLK5, x7, x8 inc_le128 BLK6, x7, x8 inc_le128 BLK7, x7, x8 bl sm4_encrypt_block8x ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x1], #64 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b eor BLK4.16b, BLK4.16b, TMP4.16b eor BLK5.16b, BLK5.16b, TMP5.16b eor BLK6.16b, BLK6.16b, TMP6.16b eor BLK7.16b, BLK7.16b, TMP7.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w3, w3, #8 b.gt .Lctrloop8x .Lctr4x: cmp w3, 1 b.lt .Lctrout cmp w3, 2 b.lt .Lctr1x cmp w3, 3 b.lt .Lctr2x cmp w3, 4 b.lt .Lctr3x inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 inc_le128 BLK2, x7, x8 inc_le128 BLK3, x7, x8 bl sm4_encrypt_block4x ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w3, w3, #4 b .Lctr4x .Lctr3x: inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 inc_le128 BLK2, x7, x8 bl sm4_encrypt_block4x ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x1], #48 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w3, w3, #3 b.le .Lctrout .Lctr2x: inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 bl sm4_encrypt_block4x ld1 {TMP0.16b, TMP1.16b}, [x1], #32 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w3, w3, #2 b.le .Lctrout .Lctr1x: inc_le128 BLK0, x7, x8 bl sm4_encrypt_block1x ld1 {TMP0.16b}, [x1], #16 eor BLK0.16b, BLK0.16b, TMP0.16b st1 {BLK0.16b}, [x0], #16 .Lctrout: rev x7, x7 rev x8, x8 stp x7, x8, [x4] frame_pop ret END_FUNC neon_sm4_ctr_encrypt /* * x0: output * x1: input * x2: round key1 * x3: round key2 * w4: blocks * x26: enc/dec */ LOCAL_FUNC xts_do_cipher , : stp x29, x30, [sp, #-16]! mov x29, sp load_sbox_matrix ld1 {IV.16b}, [x5] /* load round key2 for first tweak */ ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 encrypt_block IV /* load round key1 for block cipher */ ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 /* w6: remain */ and w6, w4, #0x0F /* w4: blocks */ lsr w4, w4, 4 /* blocks == 0: ret */ cmp w4, #1 b.lt .Lxtsout cmp w6, 0 b.eq .Lxtsblks subs w4, w4, #1 b.eq .Lxtstail .Lxtsblks: mov tw0l, IV.d[0] mov tw0h, IV.d[1] next_tweak tw1l, tw1h, tw0l, tw0h next_tweak tw2l, tw2h, tw1l, tw1h next_tweak tw3l, tw3h, tw2l, tw2h next_tweak tw4l, tw4h, tw3l, tw3h next_tweak tw5l, tw5h, tw4l, tw4h next_tweak tw6l, tw6h, tw5l, tw5h next_tweak tw7l, tw7h, tw6l, tw6h .Lxtsloop8x: cmp w4, 8 b.lt .Lxts4x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 mov_reg_to_vec TMP0, tw0l, tw0h mov_reg_to_vec TMP1, tw1l, tw1h mov_reg_to_vec TMP2, tw2l, tw2h mov_reg_to_vec TMP3, tw3l, tw3h eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 mov_reg_to_vec TMP4, tw4l, tw4h mov_reg_to_vec TMP5, tw5l, tw5h mov_reg_to_vec TMP6, tw6l, tw6h mov_reg_to_vec IV, tw7l, tw7h eor BLK4.16b, BLK4.16b, TMP4.16b eor BLK5.16b, BLK5.16b, TMP5.16b eor BLK6.16b, BLK6.16b, TMP6.16b eor BLK7.16b, BLK7.16b, IV.16b bl sm4_encrypt_block8x mov_reg_to_vec TMP0, tw0l, tw0h next_tweak tw0l, tw0h, tw7l, tw7h mov_reg_to_vec TMP1, tw1l, tw1h next_tweak tw1l, tw1h, tw0l, tw0h mov_reg_to_vec TMP2, tw2l, tw2h next_tweak tw2l, tw2h, tw1l, tw1h mov_reg_to_vec TMP3, tw3l, tw3h next_tweak tw3l, tw3h, tw2l, tw2h mov_reg_to_vec TMP4, tw4l, tw4h next_tweak tw4l, tw4h, tw3l, tw3h mov_reg_to_vec TMP5, tw5l, tw5h next_tweak tw5l, tw5h, tw4l, tw4h mov_reg_to_vec TMP6, tw6l, tw6h next_tweak tw6l, tw6h, tw5l, tw5h mov_reg_to_vec IV, tw7l, tw7h next_tweak tw7l, tw7h, tw6l, tw6h eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b eor BLK4.16b, BLK4.16b, TMP4.16b eor BLK5.16b, BLK5.16b, TMP5.16b eor BLK6.16b, BLK6.16b, TMP6.16b eor BLK7.16b, BLK7.16b, IV.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w4, w4, #8 b.gt .Lxtsloop8x .Lxts4x: cmp w4, 1 b.lt .Lxtsblksout cmp w4, 2 b.lt .Lxts1x cmp w4, 3 b.lt .Lxts2x cmp w4, 4 b.lt .Lxts3x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 mov_reg_to_vec BLK4, tw0l, tw0h mov_reg_to_vec BLK5, tw1l, tw1h mov_reg_to_vec BLK6, tw2l, tw2h mov_reg_to_vec IV, tw3l, tw3h eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, BLK6.16b eor BLK3.16b, BLK3.16b, IV.16b bl sm4_encrypt_block4x eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, BLK6.16b eor BLK3.16b, BLK3.16b, IV.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w4, w4, #4 mov tw0l, tw4l mov tw0h, tw4h mov tw1l, tw5l mov tw1h, tw5h mov tw2l, tw6l mov tw2h, tw6h b .Lxts4x .Lxts3x: ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 mov_reg_to_vec BLK4, tw0l, tw0h mov_reg_to_vec BLK5, tw1l, tw1h mov_reg_to_vec IV, tw2l, tw2h eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, IV.16b bl sm4_encrypt_block4x eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, IV.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w4, w4, #3 b.le .Lxtsblksout .Lxts2x: ld1 {BLK0.16b, BLK1.16b}, [x1], #32 mov_reg_to_vec BLK4, tw0l, tw0h mov_reg_to_vec IV, tw1l, tw1h eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, IV.16b bl sm4_encrypt_block4x eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, IV.16b st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w4, w4, #2 b.le .Lxtsblksout .Lxts1x: ld1 {BLK0.16b}, [x1], #16 mov_reg_to_vec IV, tw0l, tw0h eor BLK0.16b, BLK0.16b, IV.16b bl sm4_encrypt_block1x eor BLK0.16b, BLK0.16b, IV.16b st1 {BLK0.16b}, [x0], #16 .Lxtsblksout: cmp w6, 0 /* if encrypt some blocks with a partial block */ next_tweak_vec IV, IV b.eq .Lxtsout .Lxtstail: next_tweak_vec TMP7, IV cmp x26, 1 b.eq 1f /* The last two tweaks IV, TMP7 need to be swapped for decryption */ mov TMP8.16b, IV.16b mov IV.16b, TMP7.16b mov TMP7.16b, TMP8.16b 1: ld1 {BLK0.16b}, [x1], #16 eor BLK0.16b, BLK0.16b, IV.16b bl sm4_encrypt_block1x eor BLK0.16b, BLK0.16b, IV.16b st1 {BLK0.16b}, [x0], #16 sub x7, x0, 16 10: subs x6, x6, 1 ldrb tmpw0, [x7, x6] strb tmpw0, [x0, x6] ldrb tmpw0, [x1, x6] strb tmpw0, [x7, x6] b.gt 10b ld1 {BLK0.16b}, [x7] eor BLK0.16b, BLK0.16b, TMP7.16b bl sm4_encrypt_block1x eor BLK0.16b, BLK0.16b, TMP7.16b st1 {BLK0.16b}, [x7] .Lxtsout: /* load round key2 for last tweak */ sub x3, x3, #128 ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 /* decrypt last tweak for next update */ decrypt_block IV st1 {IV.16b}, [x5] ldp x29, x30, [sp], #16 ret END_FUNC xts_do_cipher /* * void neon_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], uint8_t const rk2[], * size_t len, uint8_t iv[]) * x0: output * x1: input * x2: round key1 * x3: round key2 * w4: len * x5: iv */ FUNC neon_sm4_xts_encrypt , : frame_push mov x26, 1 bl xts_do_cipher frame_pop ret END_FUNC neon_sm4_xts_encrypt /* * void neon_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], uint8_t const rk2[], * size_t len, uint8_t iv[]) * x0: output * x1: input * x2: round key1 * x3: round key2 * w4: len * x5: iv */ FUNC neon_sm4_xts_decrypt , : frame_push mov x26, 0 bl xts_do_cipher frame_pop ret END_FUNC neon_sm4_xts_decrypt optee_os-4.3.0/core/arch/arm/crypto/sm4_armv8a_ce.c000066400000000000000000000052261464416617300221140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. * * SM4 optimization for ARMv8 by SM4 HW instruction, which is an optional * Cryptographic Extension for ARMv8.2-A. */ #include #include #include "sm4_armv8a_ce.h" void crypto_accel_sm4_setkey_enc(uint32_t sk[32], const uint8_t key[16]) { uint32_t vfp_state = 0; assert(sk && key); vfp_state = thread_kernel_enable_vfp(); ce_sm4_setkey_enc(sk, key); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_setkey_dec(uint32_t sk[32], const uint8_t key[16]) { uint32_t vfp_state = 0; assert(sk && key); vfp_state = thread_kernel_enable_vfp(); ce_sm4_setkey_dec(sk, key); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_ecb_enc(void *out, const void *in, const void *key, unsigned int len) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); ce_sm4_ecb_encrypt(out, in, key, len); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_cbc_enc(void *out, const void *in, const void *key, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); ce_sm4_cbc_encrypt(out, in, key, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_cbc_dec(void *out, const void *in, const void *key, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); ce_sm4_cbc_decrypt(out, in, key, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_ctr_enc(void *out, const void *in, const void *key, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); ce_sm4_ctr_encrypt(out, in, key, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_xts_enc(void *out, const void *in, const void *key1, const void *key2, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key1 && key2 && (len >= 16)); vfp_state = thread_kernel_enable_vfp(); ce_sm4_xts_encrypt(out, in, key1, key2, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_xts_dec(void *out, const void *in, const void *key1, const void *key2, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key1 && key2 && (len >= 16)); vfp_state = thread_kernel_enable_vfp(); ce_sm4_xts_decrypt(out, in, key1, key2, len, iv); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/sm4_armv8a_ce.h000066400000000000000000000021001464416617300221050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. */ #ifndef __SM4_ARMV8_CE_H #define __SM4_ARMV8_CE_H #include /* Prototypes for assembly functions */ void ce_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); void ce_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); void ce_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len); void ce_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len, uint8_t iv[]); void ce_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len, uint8_t iv[]); void ce_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len, uint8_t iv[]); void ce_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], uint8_t const rk2[], size_t len, uint8_t iv[]); void ce_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], uint8_t const rk2[], size_t len, uint8_t iv[]); #endif /*__SM4_ARMV8_CE_H*/ optee_os-4.3.0/core/arch/arm/crypto/sm4_armv8a_ce_a64.S000066400000000000000000000572301464416617300225500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. * Copyright (C) 2022, Alibaba Group. * Copyright (C) 2022 Tianjia Zhang * * SM4 optimization for ARMv8 by SM4 HW instruction, which is an optional * Cryptographic Extension for ARMv8.2-A. * * The CE implementation refers to Linux kernel (sm4-ce-core.S contributed * by Tianjia Zhang ). */ #include .arch armv8.2-a+crypto+sm4 #define tw0l x7 #define tw0h x8 #define tw1l x9 #define tw1h x10 #define tw2l x11 #define tw2h x12 #define tw3l x13 #define tw3h x14 #define tw4l x15 #define tw4h x16 #define tw5l x17 #define tw5h x18 #define tw6l x19 #define tw6h x20 #define tw7l x21 #define tw7h x22 #define tmpw0 w23 #define tmpx0 x23 #define tmpw1 w24 #define tmpx1 x24 #define tmpw2 w25 /* round keys: v0-v7 */ #define RK0 v0 #define RK1 v1 #define RK2 v2 #define RK3 v3 #define RK4 v4 #define RK5 v5 #define RK6 v6 #define RK7 v7 /* plain blocks: v8-v15 */ #define BLK0 v8 #define BLK1 v9 #define BLK2 v10 #define BLK3 v11 #define BLK4 v12 #define BLK5 v13 #define BLK6 v14 #define BLK7 v15 #define TMP0 v16 #define TMP1 v17 #define TMP2 v18 #define TMP3 v19 #define TMP4 v20 #define TMP5 v21 #define TMP6 v22 #define TMP7 v23 #define TMP8 v24 #define IV v25 .macro frame_push stp x15, x16, [sp, #-0x10]! stp x17, x18, [sp, #-0x10]! stp x19, x20, [sp, #-0x10]! stp x21, x22, [sp, #-0x10]! stp x23, x24, [sp, #-0x10]! stp x25, x26, [sp, #-0x10]! stp x27, x28, [sp, #-0x10]! stp x29, x30, [sp, #-0x10]! stp d8, d9, [sp, #-0x10]! stp d10, d11, [sp, #-0x10]! stp d12, d13, [sp, #-0x10]! stp d14, d15, [sp, #-0x10]! .endm .macro frame_pop ldp d14, d15, [sp], #0x10 ldp d12, d13, [sp], #0x10 ldp d10, d11, [sp], #0x10 ldp d8, d9, [sp], #0x10 ldp x29, x30, [sp], #0x10 ldp x27, x28, [sp], #0x10 ldp x25, x26, [sp], #0x10 ldp x23, x24, [sp], #0x10 ldp x21, x22, [sp], #0x10 ldp x19, x20, [sp], #0x10 ldp x17, x18, [sp], #0x10 ldp x15, x16, [sp], #0x10 .endm .macro encrypt_block_no_rev, in sm4e \in\().4s, RK0.4s sm4e \in\().4s, RK1.4s sm4e \in\().4s, RK2.4s sm4e \in\().4s, RK3.4s sm4e \in\().4s, RK4.4s sm4e \in\().4s, RK5.4s sm4e \in\().4s, RK6.4s sm4e \in\().4s, RK7.4s rev64 \in\().4s, \in\().4s ext \in\().16b, \in\().16b, \in\().16b, #8 .endm .macro encrypt_block, in rev32 \in\().16b, \in\().16b sm4e \in\().4s, RK0.4s sm4e \in\().4s, RK1.4s sm4e \in\().4s, RK2.4s sm4e \in\().4s, RK3.4s sm4e \in\().4s, RK4.4s sm4e \in\().4s, RK5.4s sm4e \in\().4s, RK6.4s sm4e \in\().4s, RK7.4s rev64 \in\().16b, \in\().16b ext \in\().16b, \in\().16b, \in\().16b, #8 .endm .macro decrypt_block, in rev32 \in\().16b, \in\().16b rev64 RK7.4s, RK7.4s; rev64 RK6.4s, RK6.4s; rev64 RK5.4s, RK5.4s; rev64 RK4.4s, RK4.4s; ext RK7.16b, RK7.16b, RK7.16b, #8; ext RK6.16b, RK6.16b, RK6.16b, #8; ext RK5.16b, RK5.16b, RK5.16b, #8; ext RK4.16b, RK4.16b, RK4.16b, #8; sm4e \in\().4s, RK7.4s sm4e \in\().4s, RK6.4s sm4e \in\().4s, RK5.4s sm4e \in\().4s, RK4.4s rev64 RK3.4s, RK3.4s; rev64 RK2.4s, RK2.4s; rev64 RK1.4s, RK1.4s; rev64 RK0.4s, RK0.4s; ext RK3.16b, RK3.16b, RK3.16b, #8; ext RK2.16b, RK2.16b, RK2.16b, #8; ext RK1.16b, RK1.16b, RK1.16b, #8; ext RK0.16b, RK0.16b, RK0.16b, #8; sm4e \in\().4s, RK3.4s sm4e \in\().4s, RK2.4s sm4e \in\().4s, RK1.4s sm4e \in\().4s, RK0.4s rev64 \in\().16b, \in\().16b ext \in\().16b, \in\().16b, \in\().16b, #8 .endm LOCAL_FUNC sm4_encrypt_block1x , : encrypt_block BLK0 ret END_FUNC sm4_encrypt_block1x LOCAL_FUNC sm4_decrypt_block1x , : decrypt_block BLK0 ret END_FUNC sm4_decrypt_block1x LOCAL_FUNC sm4_encrypt_block4x , : rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b sm4e BLK0.4s, RK0.4s sm4e BLK1.4s, RK0.4s sm4e BLK2.4s, RK0.4s sm4e BLK3.4s, RK0.4s sm4e BLK0.4s, RK1.4s sm4e BLK1.4s, RK1.4s sm4e BLK2.4s, RK1.4s sm4e BLK3.4s, RK1.4s sm4e BLK0.4s, RK2.4s sm4e BLK1.4s, RK2.4s sm4e BLK2.4s, RK2.4s sm4e BLK3.4s, RK2.4s sm4e BLK0.4s, RK3.4s sm4e BLK1.4s, RK3.4s sm4e BLK2.4s, RK3.4s sm4e BLK3.4s, RK3.4s sm4e BLK0.4s, RK4.4s sm4e BLK1.4s, RK4.4s sm4e BLK2.4s, RK4.4s sm4e BLK3.4s, RK4.4s sm4e BLK0.4s, RK5.4s sm4e BLK1.4s, RK5.4s sm4e BLK2.4s, RK5.4s sm4e BLK3.4s, RK5.4s sm4e BLK0.4s, RK6.4s sm4e BLK1.4s, RK6.4s sm4e BLK2.4s, RK6.4s sm4e BLK3.4s, RK6.4s sm4e BLK0.4s, RK7.4s sm4e BLK1.4s, RK7.4s sm4e BLK2.4s, RK7.4s sm4e BLK3.4s, RK7.4s rev64 BLK0.16b, BLK0.16b rev64 BLK1.16b, BLK1.16b rev64 BLK2.16b, BLK2.16b rev64 BLK3.16b, BLK3.16b ext BLK0.16b, BLK0.16b, BLK0.16b, #8 ext BLK1.16b, BLK1.16b, BLK1.16b, #8 ext BLK2.16b, BLK2.16b, BLK2.16b, #8 ext BLK3.16b, BLK3.16b, BLK3.16b, #8 ret END_FUNC sm4_encrypt_block4x LOCAL_FUNC sm4_encrypt_block8x , : rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b rev32 BLK4.16b, BLK4.16b rev32 BLK5.16b, BLK5.16b rev32 BLK6.16b, BLK6.16b rev32 BLK7.16b, BLK7.16b sm4e BLK0.4s, RK0.4s sm4e BLK1.4s, RK0.4s sm4e BLK2.4s, RK0.4s sm4e BLK3.4s, RK0.4s sm4e BLK4.4s, RK0.4s sm4e BLK5.4s, RK0.4s sm4e BLK6.4s, RK0.4s sm4e BLK7.4s, RK0.4s sm4e BLK0.4s, RK1.4s sm4e BLK1.4s, RK1.4s sm4e BLK2.4s, RK1.4s sm4e BLK3.4s, RK1.4s sm4e BLK4.4s, RK1.4s sm4e BLK5.4s, RK1.4s sm4e BLK6.4s, RK1.4s sm4e BLK7.4s, RK1.4s sm4e BLK0.4s, RK2.4s sm4e BLK1.4s, RK2.4s sm4e BLK2.4s, RK2.4s sm4e BLK3.4s, RK2.4s sm4e BLK4.4s, RK2.4s sm4e BLK5.4s, RK2.4s sm4e BLK6.4s, RK2.4s sm4e BLK7.4s, RK2.4s sm4e BLK0.4s, RK3.4s sm4e BLK1.4s, RK3.4s sm4e BLK2.4s, RK3.4s sm4e BLK3.4s, RK3.4s sm4e BLK4.4s, RK3.4s sm4e BLK5.4s, RK3.4s sm4e BLK6.4s, RK3.4s sm4e BLK7.4s, RK3.4s sm4e BLK0.4s, RK4.4s sm4e BLK1.4s, RK4.4s sm4e BLK2.4s, RK4.4s sm4e BLK3.4s, RK4.4s sm4e BLK4.4s, RK4.4s sm4e BLK5.4s, RK4.4s sm4e BLK6.4s, RK4.4s sm4e BLK7.4s, RK4.4s sm4e BLK0.4s, RK5.4s sm4e BLK1.4s, RK5.4s sm4e BLK2.4s, RK5.4s sm4e BLK3.4s, RK5.4s sm4e BLK4.4s, RK5.4s sm4e BLK5.4s, RK5.4s sm4e BLK6.4s, RK5.4s sm4e BLK7.4s, RK5.4s sm4e BLK0.4s, RK6.4s sm4e BLK1.4s, RK6.4s sm4e BLK2.4s, RK6.4s sm4e BLK3.4s, RK6.4s sm4e BLK4.4s, RK6.4s sm4e BLK5.4s, RK6.4s sm4e BLK6.4s, RK6.4s sm4e BLK7.4s, RK6.4s sm4e BLK0.4s, RK7.4s sm4e BLK1.4s, RK7.4s sm4e BLK2.4s, RK7.4s sm4e BLK3.4s, RK7.4s sm4e BLK4.4s, RK7.4s sm4e BLK5.4s, RK7.4s sm4e BLK6.4s, RK7.4s sm4e BLK7.4s, RK7.4s rev64 BLK0.16b, BLK0.16b rev64 BLK1.16b, BLK1.16b rev64 BLK2.16b, BLK2.16b rev64 BLK3.16b, BLK3.16b rev64 BLK4.16b, BLK4.16b rev64 BLK5.16b, BLK5.16b rev64 BLK6.16b, BLK6.16b rev64 BLK7.16b, BLK7.16b ext BLK0.16b, BLK0.16b, BLK0.16b, #8 ext BLK1.16b, BLK1.16b, BLK1.16b, #8 ext BLK2.16b, BLK2.16b, BLK2.16b, #8 ext BLK3.16b, BLK3.16b, BLK3.16b, #8 ext BLK4.16b, BLK4.16b, BLK4.16b, #8 ext BLK5.16b, BLK5.16b, BLK5.16b, #8 ext BLK6.16b, BLK6.16b, BLK6.16b, #8 ext BLK7.16b, BLK7.16b, BLK7.16b, #8 ret END_FUNC sm4_encrypt_block8x .macro inc_le128, vctr, low, high mov \vctr\().d[1], \high mov \vctr\().d[0], \low adds \high, \high, #1 adc \low, \low, xzr rev64 \vctr\().16b, \vctr\().16b .endm .macro mov_reg_to_vec, desv, src0, src1 mov \desv\().d[0], \src0 mov \desv\().d[1], \src1 .endm .macro next_tweak, des0, des1, src0, src1 mov tmpw2, 0x87 extr tmpx0, \src1, \src1, #32 extr \des1, \src1, \src0, #63 and tmpw1, tmpw2, tmpw0, asr#31 eor \des0, tmpx1, \src0, lsl#1 .endm .macro next_tweak_vec, desv, srcv mov tw0l, \srcv\().d[0] mov tw0h, \srcv\().d[1] next_tweak tw1l, tw1h, tw0l, tw0h mov \desv\().d[0], tw1l mov \desv\().d[1], tw1h .endm LOCAL_DATA .Lck , : .long 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269 .long 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9 .long 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249 .long 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9 .long 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229 .long 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299 .long 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209 .long 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279 END_DATA .Lck LOCAL_DATA .Lfk , : .long 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc END_DATA .Lfk /* * void ce_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); * x0: round key * x1: user key */ FUNC ce_sm4_setkey_enc , : ld1 {RK0.4s}, [x1] adr x2, .Lfk ld1 {TMP8.4s}, [x2] adr x2, .Lck ld1 {TMP0.4s, TMP1.4s, TMP2.4s, TMP3.4s}, [x2], 64 rev32 RK0.16b, RK0.16b ld1 {TMP4.4s, TMP5.4s, TMP6.4s, TMP7.4s}, [x2] eor RK0.16b, RK0.16b, TMP8.16b sm4ekey RK0.4s, RK0.4s, TMP0.4s sm4ekey RK1.4s, RK0.4s, TMP1.4s sm4ekey RK2.4s, RK1.4s, TMP2.4s sm4ekey RK3.4s, RK2.4s, TMP3.4s sm4ekey RK4.4s, RK3.4s, TMP4.4s st1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x0], 64 sm4ekey RK5.4s, RK4.4s, TMP5.4s sm4ekey RK6.4s, RK5.4s, TMP6.4s sm4ekey RK7.4s, RK6.4s, TMP7.4s st1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x0] ret END_FUNC ce_sm4_setkey_enc /* * void ce_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); * x0: round key * x1: user key */ FUNC ce_sm4_setkey_dec , : ld1 {RK7.4s}, [x1] adr x2, .Lfk ld1 {TMP8.4s}, [x2] adr x2, .Lck ld1 {TMP0.4s, TMP1.4s, TMP2.4s, TMP3.4s}, [x2], 64 rev32 RK7.16b, RK7.16b ld1 {TMP4.4s, TMP5.4s, TMP6.4s, TMP7.4s}, [x2] eor RK7.16b, RK7.16b, TMP8.16b; sm4ekey RK7.4s, RK7.4s, TMP0.4s sm4ekey RK6.4s, RK7.4s, TMP1.4s sm4ekey RK5.4s, RK6.4s, TMP2.4s rev64 RK7.4s, RK7.4s rev64 RK6.4s, RK6.4s ext RK7.16b, RK7.16b, RK7.16b, #8 ext RK6.16b, RK6.16b, RK6.16b, #8 sm4ekey RK4.4s, RK5.4s, TMP3.4s sm4ekey RK3.4s, RK4.4s, TMP4.4s rev64 RK5.4s, RK5.4s rev64 RK4.4s, RK4.4s ext RK5.16b, RK5.16b, RK5.16b, #8 ext RK4.16b, RK4.16b, RK4.16b, #8 sm4ekey RK2.4s, RK3.4s, TMP5.4s sm4ekey RK1.4s, RK2.4s, TMP6.4s rev64 RK3.4s, RK3.4s rev64 RK2.4s, RK2.4s ext RK3.16b, RK3.16b, RK3.16b, #8 ext RK2.16b, RK2.16b, RK2.16b, #8 sm4ekey RK0.4s, RK1.4s, TMP7.4s rev64 RK1.4s, RK1.4s rev64 RK0.4s, RK0.4s ext RK1.16b, RK1.16b, RK1.16b, #8 ext RK0.16b, RK0.16b, RK0.16b, #8 st1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x0], 64 st1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x0] ret END_FUNC ce_sm4_setkey_dec /* * void ce_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len); * x0: output * x1: input * x2: round key * w3: length */ FUNC ce_sm4_ecb_encrypt , : frame_push ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 .Lecbloop8x: cmp w3, 8 b.lt .Lecb4x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 bl sm4_encrypt_block8x st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w3, w3, #8 b.gt .Lecbloop8x .Lecb4x: cmp w3, 1 b.lt .Lecbout cmp w3, 2 b.lt .Lecb1x cmp w3, 3 b.lt .Lecb2x cmp w3, 4 b.lt .Lecb3x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 bl sm4_encrypt_block4x st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w3, w3, #4 b .Lecb4x .Lecb3x: ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 bl sm4_encrypt_block4x st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w3, w3, #3 b.le .Lecbout .Lecb2x: ld1 {BLK0.16b, BLK1.16b}, [x1], #32 bl sm4_encrypt_block4x st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w3, w3, #2 b.le .Lecbout .Lecb1x: ld1 {BLK0.16b}, [x1], #16 bl sm4_encrypt_block1x st1 {BLK0.16b}, [x0], #16 .Lecbout: frame_pop ret END_FUNC ce_sm4_ecb_encrypt /* * void ce_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len, * uint8_t iv[]); * x0: output * x1: input * x2: round key * w3: length * x4: iv */ FUNC ce_sm4_cbc_encrypt , : frame_push ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 ld1 {IV.16b}, [x4] .Lcbcencloop4x: cmp w3, 4 b.lt .Lcbcenc1x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 eor BLK0.16b, BLK0.16b, IV.16b rev32 BLK0.16b, BLK0.16b rev32 BLK1.16b, BLK1.16b rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b encrypt_block_no_rev BLK0 eor BLK1.16b, BLK1.16b, BLK0.16b encrypt_block_no_rev BLK1 rev32 BLK0.16b, BLK0.16b eor BLK2.16b, BLK2.16b, BLK1.16b encrypt_block_no_rev BLK2 rev32 BLK1.16b, BLK1.16b eor BLK3.16b, BLK3.16b, BLK2.16b encrypt_block_no_rev BLK3 rev32 BLK2.16b, BLK2.16b rev32 BLK3.16b, BLK3.16b mov IV.16b, BLK3.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 subs w3, w3, #4 b .Lcbcencloop4x .Lcbcenc1x: cmp w3, 1 b.lt .Lcbcencout .Lcbcencloop: ld1 {BLK0.16b}, [x1], #16 eor BLK0.16b, BLK0.16b, IV.16b bl sm4_encrypt_block1x mov IV.16b, BLK0.16b st1 {BLK0.16b}, [x0], #16 subs w3, w3, #1 bne .Lcbcencloop .Lcbcencout: st1 {IV.16b}, [x4] frame_pop ret END_FUNC ce_sm4_cbc_encrypt /* * void ce_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len, * uint8_t iv[]); * x0: output * x1: input * x2: round key * w3: length * x4: iv */ FUNC ce_sm4_cbc_decrypt , : frame_push ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 ld1 {IV.16b}, [x4] .Lcbcdecloop8x: cmp w3, 8 b.lt .Lcbcdec4x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 bl sm4_encrypt_block8x sub x5, x1, #128 eor BLK0.16b, BLK0.16b, IV.16b ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 eor BLK1.16b, BLK1.16b, TMP0.16b eor BLK2.16b, BLK2.16b, TMP1.16b eor BLK3.16b, BLK3.16b, TMP2.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x5], #64 eor BLK4.16b, BLK4.16b, TMP3.16b eor BLK5.16b, BLK5.16b, TMP4.16b mov IV.16b, TMP7.16b eor BLK6.16b, BLK6.16b, TMP5.16b eor BLK7.16b, BLK7.16b, TMP6.16b st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w3, w3, #8 b.gt .Lcbcdecloop8x .Lcbcdec4x: cmp w3, 1 b.lt .Lcbcdecout cmp w3, 2 b.lt .Lcbcdec1x cmp w3, 3 b.lt .Lcbcdec2x cmp w3, 4 b.lt .Lcbcdec3x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 bl sm4_encrypt_block4x sub x5, x1, 64 ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x5], #64 eor BLK0.16b, BLK0.16b, IV.16b eor BLK1.16b, BLK1.16b, TMP0.16b eor BLK2.16b, BLK2.16b, TMP1.16b eor BLK3.16b, BLK3.16b, TMP2.16b mov IV.16b, TMP3.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w3, w3, #4 b .Lcbcdec4x .Lcbcdec3x: ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 bl sm4_encrypt_block4x sub x5, x1, 48 ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x5], #48 eor BLK0.16b, BLK0.16b, IV.16b eor BLK1.16b, BLK1.16b, TMP0.16b eor BLK2.16b, BLK2.16b, TMP1.16b mov IV.16b, TMP2.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w3, w3, #3 b.le .Lcbcdecout .Lcbcdec2x: ld1 {BLK0.16b, BLK1.16b}, [x1], #32 bl sm4_encrypt_block4x sub x5, x1, 32 ld1 {TMP0.16b, TMP1.16b}, [x5], #32 eor BLK0.16b, BLK0.16b, IV.16b eor BLK1.16b, BLK1.16b, TMP0.16b mov IV.16b, TMP1.16b st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w3, w3, #2 b.le .Lcbcdecout .Lcbcdec1x: ld1 {BLK0.16b}, [x1], #16 bl sm4_encrypt_block1x sub x5, x1, 16 ld1 {TMP0.16b}, [x5], #16 eor BLK0.16b, BLK0.16b, IV.16b mov IV.16b, TMP0.16b st1 {BLK0.16b}, [x0], #16 .Lcbcdecout: st1 {IV.16b}, [x4] frame_pop ret END_FUNC ce_sm4_cbc_decrypt /* * void ce_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk[], size_t len, * uint8_t iv[]); * x0: output * x1: input * x2: round key * w3: length * x4: iv */ FUNC ce_sm4_ctr_encrypt , : frame_push ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 lsr w3, w3, 4 ldp x7, x8, [x4] rev x7, x7 rev x8, x8 .Lctrloop8x: cmp w3, 8 b.lt .Lctr4x /* construct CTRs */ inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 inc_le128 BLK2, x7, x8 inc_le128 BLK3, x7, x8 inc_le128 BLK4, x7, x8 inc_le128 BLK5, x7, x8 inc_le128 BLK6, x7, x8 inc_le128 BLK7, x7, x8 bl sm4_encrypt_block8x ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 ld1 {TMP4.16b, TMP5.16b, TMP6.16b, TMP7.16b}, [x1], #64 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b eor BLK4.16b, BLK4.16b, TMP4.16b eor BLK5.16b, BLK5.16b, TMP5.16b eor BLK6.16b, BLK6.16b, TMP6.16b eor BLK7.16b, BLK7.16b, TMP7.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w3, w3, #8 b.gt .Lctrloop8x .Lctr4x: cmp w3, 1 b.lt .Lctrout cmp w3, 2 b.lt .Lctr1x cmp w3, 3 b.lt .Lctr2x cmp w3, 4 b.lt .Lctr3x inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 inc_le128 BLK2, x7, x8 inc_le128 BLK3, x7, x8 bl sm4_encrypt_block4x ld1 {TMP0.16b, TMP1.16b, TMP2.16b, TMP3.16b}, [x1], #64 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w3, w3, #4 b .Lctr4x .Lctr3x: inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 inc_le128 BLK2, x7, x8 bl sm4_encrypt_block4x ld1 {TMP0.16b, TMP1.16b, TMP2.16b}, [x1], #48 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w3, w3, #3 b.le .Lctrout .Lctr2x: inc_le128 BLK0, x7, x8 inc_le128 BLK1, x7, x8 bl sm4_encrypt_block4x ld1 {TMP0.16b, TMP1.16b}, [x1], #32 eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w3, w3, #2 b.le .Lctrout .Lctr1x: inc_le128 BLK0, x7, x8 bl sm4_encrypt_block1x ld1 {TMP0.16b}, [x1], #16 eor BLK0.16b, BLK0.16b, TMP0.16b st1 {BLK0.16b}, [x0], #16 .Lctrout: rev x7, x7 rev x8, x8 stp x7, x8, [x4] frame_pop ret END_FUNC ce_sm4_ctr_encrypt /* * x0: output * x1: input * x2: round key1 * x3: round key2 * w4: blocks * x26: enc/dec */ LOCAL_FUNC xts_do_cipher , : stp x29, x30, [sp, #-16]! mov x29, sp ld1 {IV.16b}, [x5] /* load round key2 for first tweak */ ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 encrypt_block IV /* load round key1 for block cipher */ ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x2], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x2], #64 /* w6: remain */ and w6, w4, #0x0F /* w4: blocks */ lsr w4, w4, 4 /* blocks == 0: ret */ cmp w4, #1 b.lt .Lxtsout cmp w6, 0 b.eq .Lxtsblks subs w4, w4, #1 b.eq .Lxtstail .Lxtsblks: mov tw0l, IV.d[0] mov tw0h, IV.d[1] next_tweak tw1l, tw1h, tw0l, tw0h next_tweak tw2l, tw2h, tw1l, tw1h next_tweak tw3l, tw3h, tw2l, tw2h next_tweak tw4l, tw4h, tw3l, tw3h next_tweak tw5l, tw5h, tw4l, tw4h next_tweak tw6l, tw6h, tw5l, tw5h next_tweak tw7l, tw7h, tw6l, tw6h .Lxtsloop8x: cmp w4, 8 b.lt .Lxts4x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 mov_reg_to_vec TMP0, tw0l, tw0h mov_reg_to_vec TMP1, tw1l, tw1h mov_reg_to_vec TMP2, tw2l, tw2h mov_reg_to_vec TMP3, tw3l, tw3h eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b ld1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x1], #64 mov_reg_to_vec TMP4, tw4l, tw4h mov_reg_to_vec TMP5, tw5l, tw5h mov_reg_to_vec TMP6, tw6l, tw6h mov_reg_to_vec IV, tw7l, tw7h eor BLK4.16b, BLK4.16b, TMP4.16b eor BLK5.16b, BLK5.16b, TMP5.16b eor BLK6.16b, BLK6.16b, TMP6.16b eor BLK7.16b, BLK7.16b, IV.16b bl sm4_encrypt_block8x mov_reg_to_vec TMP0, tw0l, tw0h next_tweak tw0l, tw0h, tw7l, tw7h mov_reg_to_vec TMP1, tw1l, tw1h next_tweak tw1l, tw1h, tw0l, tw0h mov_reg_to_vec TMP2, tw2l, tw2h next_tweak tw2l, tw2h, tw1l, tw1h mov_reg_to_vec TMP3, tw3l, tw3h next_tweak tw3l, tw3h, tw2l, tw2h mov_reg_to_vec TMP4, tw4l, tw4h next_tweak tw4l, tw4h, tw3l, tw3h mov_reg_to_vec TMP5, tw5l, tw5h next_tweak tw5l, tw5h, tw4l, tw4h mov_reg_to_vec TMP6, tw6l, tw6h next_tweak tw6l, tw6h, tw5l, tw5h mov_reg_to_vec IV, tw7l, tw7h next_tweak tw7l, tw7h, tw6l, tw6h eor BLK0.16b, BLK0.16b, TMP0.16b eor BLK1.16b, BLK1.16b, TMP1.16b eor BLK2.16b, BLK2.16b, TMP2.16b eor BLK3.16b, BLK3.16b, TMP3.16b eor BLK4.16b, BLK4.16b, TMP4.16b eor BLK5.16b, BLK5.16b, TMP5.16b eor BLK6.16b, BLK6.16b, TMP6.16b eor BLK7.16b, BLK7.16b, IV.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 st1 {BLK4.16b, BLK5.16b, BLK6.16b, BLK7.16b}, [x0], #64 subs w4, w4, #8 b.gt .Lxtsloop8x .Lxts4x: cmp w4, 1 b.lt .Lxtsblksout cmp w4, 2 b.lt .Lxts1x cmp w4, 3 b.lt .Lxts2x cmp w4, 4 b.lt .Lxts3x ld1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x1], #64 mov_reg_to_vec BLK4, tw0l, tw0h mov_reg_to_vec BLK5, tw1l, tw1h mov_reg_to_vec BLK6, tw2l, tw2h mov_reg_to_vec IV, tw3l, tw3h eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, BLK6.16b eor BLK3.16b, BLK3.16b, IV.16b bl sm4_encrypt_block4x eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, BLK6.16b eor BLK3.16b, BLK3.16b, IV.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b, BLK3.16b}, [x0], #64 sub w4, w4, #4 mov tw0l, tw4l mov tw0h, tw4h mov tw1l, tw5l mov tw1h, tw5h mov tw2l, tw6l mov tw2h, tw6h b .Lxts4x .Lxts3x: ld1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x1], #48 mov_reg_to_vec BLK4, tw0l, tw0h mov_reg_to_vec BLK5, tw1l, tw1h mov_reg_to_vec IV, tw2l, tw2h eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, IV.16b bl sm4_encrypt_block4x eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, BLK5.16b eor BLK2.16b, BLK2.16b, IV.16b st1 {BLK0.16b, BLK1.16b, BLK2.16b}, [x0], #48 subs w4, w4, #3 b.le .Lxtsblksout .Lxts2x: ld1 {BLK0.16b, BLK1.16b}, [x1], #32 mov_reg_to_vec BLK4, tw0l, tw0h mov_reg_to_vec IV, tw1l, tw1h eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, IV.16b bl sm4_encrypt_block4x eor BLK0.16b, BLK0.16b, BLK4.16b eor BLK1.16b, BLK1.16b, IV.16b st1 {BLK0.16b, BLK1.16b}, [x0], #32 subs w4, w4, #2 b.le .Lxtsblksout .Lxts1x: ld1 {BLK0.16b}, [x1], #16 mov_reg_to_vec IV, tw0l, tw0h eor BLK0.16b, BLK0.16b, IV.16b bl sm4_encrypt_block1x eor BLK0.16b, BLK0.16b, IV.16b st1 {BLK0.16b}, [x0], #16 .Lxtsblksout: cmp w6, 0 /* if encrypt some blocks with a partial block */ next_tweak_vec IV, IV b.eq .Lxtsout .Lxtstail: next_tweak_vec TMP7, IV cmp x26, 1 b.eq 1f /* The last two tweaks IV, TMP7 need to be swapped for decryption */ mov TMP8.16b, IV.16b mov IV.16b, TMP7.16b mov TMP7.16b, TMP8.16b 1: ld1 {BLK0.16b}, [x1], #16 eor BLK0.16b, BLK0.16b, IV.16b bl sm4_encrypt_block1x eor BLK0.16b, BLK0.16b, IV.16b st1 {BLK0.16b}, [x0], #16 sub x7, x0, 16 10: subs x6, x6, 1 ldrb tmpw0, [x7, x6] strb tmpw0, [x0, x6] ldrb tmpw0, [x1, x6] strb tmpw0, [x7, x6] b.gt 10b ld1 {BLK0.16b}, [x7] eor BLK0.16b, BLK0.16b, TMP7.16b bl sm4_encrypt_block1x eor BLK0.16b, BLK0.16b, TMP7.16b st1 {BLK0.16b}, [x7] .Lxtsout: /* load round key2 for last tweak */ sub x3, x3, #128 ld1 {RK0.4s, RK1.4s, RK2.4s, RK3.4s}, [x3], #64 ld1 {RK4.4s, RK5.4s, RK6.4s, RK7.4s}, [x3], #64 /* decrypt last tweak for next update */ decrypt_block IV st1 {IV.16b}, [x5] ldp x29, x30, [sp], #16 ret END_FUNC xts_do_cipher /* * void ce_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], uint8_t const rk2[], * size_t len, uint8_t iv[]) * x0: output * x1: input * x2: round key1 * x3: round key2 * w4: len * x5: iv */ FUNC ce_sm4_xts_encrypt , : frame_push mov x26, 1 bl xts_do_cipher frame_pop ret END_FUNC ce_sm4_xts_encrypt /* * void ce_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], * uint8_t const rk1[], uint8_t const rk2[], * size_t len, uint8_t iv[]) * x0: output * x1: input * x2: round key1 * x3: round key2 * w4: len * x5: iv */ FUNC ce_sm4_xts_decrypt , : frame_push mov x26, 0 bl xts_do_cipher frame_pop ret END_FUNC ce_sm4_xts_decrypt BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/crypto/sm4_armv8a_neon.c000066400000000000000000000052571464416617300224700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. * * SM4 optimization for ARMv8 by NEON and AES HW instruction, which is an * optional Cryptographic Extension for ARMv8-A. */ #include #include #include "sm4_armv8a_neon.h" void crypto_accel_sm4_setkey_enc(uint32_t sk[32], const uint8_t key[16]) { uint32_t vfp_state = 0; assert(sk && key); vfp_state = thread_kernel_enable_vfp(); neon_sm4_setkey_enc(sk, key); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_setkey_dec(uint32_t sk[32], const uint8_t key[16]) { uint32_t vfp_state = 0; assert(sk && key); vfp_state = thread_kernel_enable_vfp(); neon_sm4_setkey_dec(sk, key); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_ecb_enc(void *out, const void *in, const void *key, unsigned int len) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); neon_sm4_ecb_encrypt(out, in, key, len); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_cbc_enc(void *out, const void *in, const void *key, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); neon_sm4_cbc_encrypt(out, in, key, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_cbc_dec(void *out, const void *in, const void *key, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); neon_sm4_cbc_decrypt(out, in, key, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_ctr_enc(void *out, const void *in, const void *key, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key && !(len % 16)); vfp_state = thread_kernel_enable_vfp(); neon_sm4_ctr_encrypt(out, in, key, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_xts_enc(void *out, const void *in, const void *key1, const void *key2, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key1 && key2 && (len >= 16)); vfp_state = thread_kernel_enable_vfp(); neon_sm4_xts_encrypt(out, in, key1, key2, len, iv); thread_kernel_disable_vfp(vfp_state); } void crypto_accel_sm4_xts_dec(void *out, const void *in, const void *key1, const void *key2, unsigned int len, void *iv) { uint32_t vfp_state = 0; assert(out && in && key1 && key2 && (len >= 16)); vfp_state = thread_kernel_enable_vfp(); neon_sm4_xts_decrypt(out, in, key1, key2, len, iv); thread_kernel_disable_vfp(vfp_state); } optee_os-4.3.0/core/arch/arm/crypto/sm4_armv8a_neon.h000066400000000000000000000021511464416617300224630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. */ #ifndef __SM4_ARMV8_NEON_H #define __SM4_ARMV8_NEON_H #include /* Prototypes for assembly functions */ void neon_sm4_setkey_enc(uint32_t sk[32], uint8_t const key[16]); void neon_sm4_setkey_dec(uint32_t sk[32], uint8_t const key[16]); void neon_sm4_ecb_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len); void neon_sm4_cbc_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len, uint8_t iv[]); void neon_sm4_cbc_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len, uint8_t iv[]); void neon_sm4_ctr_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk[], size_t len, uint8_t iv[]); void neon_sm4_xts_encrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], uint8_t const rk2[], size_t len, uint8_t iv[]); void neon_sm4_xts_decrypt(uint8_t out[], uint8_t const in[], uint8_t const rk1[], uint8_t const rk2[], size_t len, uint8_t iv[]); #endif /*__SM4_ARMV8_NEON_H*/ optee_os-4.3.0/core/arch/arm/crypto/sub.mk000066400000000000000000000024531464416617300204410ustar00rootroot00000000000000ifeq ($(CFG_CRYPTO_WITH_CE),y) srcs-$(CFG_ARM64_core) += ghash-ce-core_a64.S srcs-$(CFG_ARM32_core) += ghash-ce-core_a32.S srcs-y += aes-gcm-ce.c endif ifeq ($(CFG_CRYPTO_AES_ARM_CE),y) srcs-y += aes_armv8a_ce.c srcs-$(CFG_ARM64_core) += aes_modes_armv8a_ce_a64.S aflags-aes_modes_armv8a_ce_a64.S-y += -DINTERLEAVE=4 srcs-$(CFG_ARM32_core) += aes_modes_armv8a_ce_a32.S endif ifeq ($(CFG_CRYPTO_SHA1_ARM_CE),y) srcs-y += sha1_armv8a_ce.c srcs-$(CFG_ARM64_core) += sha1_armv8a_ce_a64.S srcs-$(CFG_ARM32_core) += sha1_armv8a_ce_a32.S endif ifeq ($(CFG_CRYPTO_SHA256_ARM_CE),y) srcs-y += sha256_armv8a_ce.c srcs-$(CFG_ARM64_core) += sha256_armv8a_ce_a64.S srcs-$(CFG_ARM32_core) += sha256_armv8a_ce_a32.S endif ifeq ($(CFG_CRYPTO_SHA512_ARM_CE),y) srcs-y += sha512_armv8a_ce.c srcs-$(CFG_ARM64_core) += sha512_armv8a_ce_a64.S endif ifeq ($(CFG_CRYPTO_SHA3_ARM_CE),y) srcs-y += sha3_armv8a_ce.c srcs-$(CFG_ARM64_core) += sha3_armv8a_ce_a64.S endif ifeq ($(CFG_CRYPTO_SM3_ARM_CE),y) srcs-y += sm3_armv8a_ce.c srcs-$(CFG_ARM64_core) += sm3_armv8a_ce_a64.S endif ifeq ($(CFG_CRYPTO_SM4_ARM_CE),y) srcs-$(CFG_ARM64_core) += sm4_armv8a_ce.c srcs-$(CFG_ARM64_core) += sm4_armv8a_ce_a64.S else ifeq ($(CFG_CRYPTO_SM4_ARM_AESE),y) srcs-$(CFG_ARM64_core) += sm4_armv8a_neon.c srcs-$(CFG_ARM64_core) += sm4_armv8a_aese_a64.S endif optee_os-4.3.0/core/arch/arm/dts/000077500000000000000000000000001464416617300165655ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/dts/at91-sama5d27_som1.dtsi000066400000000000000000000061531464416617300225150ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * at91-sama5d27_som1.dtsi - Device Tree file for SAMA5D27 SoM1 board * * Copyright (c) 2017, Microchip Technology Inc. * 2017 Cristian Birsan * 2017 Claudiu Beznea */ #include "sama5d2.dtsi" #include "sama5d2-pinfunc.h" / { model = "Atmel SAMA5D27 SoM1"; compatible = "atmel,sama5d27-som1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; aliases { i2c0 = &i2c0; }; clocks { slow_xtal { clock-frequency = <32768>; }; main_xtal { clock-frequency = <24000000>; }; }; ahb { sdmmc0: sdio-host@a0000000 { microchip,sdcal-inverted; }; apb { qspi1: spi@f0024000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_qspi1_default>; flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <80000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; m25p,fast-read; at91bootstrap@0 { label = "at91bootstrap"; reg = <0x00000000 0x00040000>; }; bootloader@40000 { label = "bootloader"; reg = <0x00040000 0x000c0000>; }; bootloaderenvred@100000 { label = "bootloader env redundant"; reg = <0x00100000 0x00040000>; }; bootloaderenv@140000 { label = "bootloader env"; reg = <0x00140000 0x00040000>; }; dtb@180000 { label = "device tree"; reg = <0x00180000 0x00080000>; }; kernel@200000 { label = "kernel"; reg = <0x00200000 0x00600000>; }; }; }; macb0: ethernet@f8008000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb0_default>; phy-mode = "rmii"; ethernet-phy@7 { reg = <0x7>; interrupt-parent = <&pioA>; interrupts = ; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb0_phy_irq>; }; }; i2c0: i2c@f8028000 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c0_default>; status = "okay"; at24@50 { compatible = "atmel,24c02"; reg = <0x50>; pagesize = <8>; }; }; pinctrl@fc039000 { pinctrl_i2c0_default: i2c0_default { pinmux = , ; bias-disable; }; pinctrl_qspi1_default: qspi1_default { sck_cs { pinmux = , ; bias-disable; }; data { pinmux = , , , ; bias-pull-up; }; }; pinctrl_macb0_default: macb0_default { pinmux = , , , , , , , , , ; bias-disable; }; pinctrl_macb0_phy_irq: macb0_phy_irq { pinmux = ; bias-disable; }; }; }; }; }; optee_os-4.3.0/core/arch/arm/dts/at91-sama5d27_som1_ek.dts000066400000000000000000000270521464416617300230240ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * at91-sama5d27_som1_ek.dts - Device Tree file for SAMA5D27-SOM1-EK board * * Copyright (c) 2017, Microchip Technology Inc. * 2016 Nicolas Ferre * 2017 Cristian Birsan * 2017 Claudiu Beznea */ /dts-v1/; #include "at91-sama5d27_som1.dtsi" #include #include / { model = "Atmel SAMA5D27 SOM1 EK"; compatible = "atmel,sama5d27-som1-ek", "atmel,sama5d27-som1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; aliases { serial0 = &uart1; /* DBGU */ serial1 = &uart4; /* mikro BUS 1 */ serial2 = &uart2; /* mikro BUS 2 */ i2c1 = &i2c1; i2c2 = &i2c3; }; chosen { stdout-path = "serial0:115200n8"; }; ahb { usb0: gadget@300000 { atmel,vbus-gpio = <&pioA PIN_PD20 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usba_vbus>; status = "okay"; }; usb1: ohci@400000 { num-ports = <3>; atmel,vbus-gpio = <0 /* &pioA PIN_PD20 GPIO_ACTIVE_HIGH */ &pioA PIN_PA27 GPIO_ACTIVE_HIGH 0 >; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb_default>; status = "okay"; }; usb2: ehci@500000 { status = "okay"; }; sdmmc0: sdio-host@a0000000 { bus-width = <8>; mmc-ddr-3_3v; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc0_default>; status = "okay"; }; sdmmc1: sdio-host@b0000000 { bus-width = <4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc1_default>; status = "okay"; }; apb { isc: isc@f0008000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_isc_base &pinctrl_isc_data_8bit &pinctrl_isc_data_9_10 &pinctrl_isc_data_11_12>; status = "okay"; }; qspi1: spi@f0024000 { status = "okay"; }; spi0: spi@f8000000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi0_default>; status = "okay"; }; macb0: ethernet@f8008000 { status = "okay"; }; tcb0: timer@f800c000 { timer0: timer@0 { compatible = "atmel,tcb-timer"; reg = <0>; }; timer1: timer@1 { compatible = "atmel,tcb-timer"; reg = <1>; }; }; uart1: serial@f8020000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1_default>; atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; uart2: serial@f8024000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus2_uart>; atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; pwm0: pwm@f802c000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus1_pwm &pinctrl_mikrobus2_pwm>; status = "disabled"; /* Conflict with leds. */ }; flx1: flexcom@f8038000 { atmel,flexcom-mode = ; status = "okay"; i2c3: i2c@600 { dmas = <0>, <0>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus_i2c>; status = "okay"; }; }; shdwc@f8048010 { debounce-delay-us = <976>; atmel,wakeup-rtc-timer; input@0 { reg = <0>; }; }; uart3: serial@fc008000 { atmel,use-dma-rx; atmel,use-dma-tx; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart3_default>; status = "disabled"; /* Conflict with isc. */ }; uart4: serial@fc00c000 { atmel,use-dma-rx; atmel,use-dma-tx; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus1_uart>; status = "okay"; }; flx3: flexcom@fc014000 { atmel,flexcom-mode = ; status = "disabled"; uart8: serial@200 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx3_default>; status = "disabled"; /* Conflict with isc. */ }; spi5: spi@400 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx3_default>; status = "disabled"; /* Conflict with isc. */ }; }; flx4: flexcom@fc018000 { atmel,flexcom-mode = ; status = "okay"; uart9: serial@200 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx4_default>; status = "disabled"; /* Conflict with spi6 and i2c6. */ }; spi6: spi@400 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus_spi &pinctrl_mikrobus1_spi_cs &pinctrl_mikrobus2_spi_cs>; status = "okay"; /* Conflict with uart5 and i2c6. */ }; i2c6: i2c@600 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx4_default>; status = "disabled"; /* Conflict with uart5 and spi6. */ }; }; i2c1: i2c@fc028000 { dmas = <0>, <0>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1_default>; status = "okay"; }; adc: adc@fc030000 { vddana-supply = <&vddana>; vref-supply = <&advref>; status = "disabled"; }; pinctrl@fc039000 { pinctrl_can1_default: can1_default { pinmux = , ; bias-disable; }; pinctrl_flx3_default: flx3_default { pinmux = , , , , ; bias-disable; }; pinctrl_i2c1_default: i2c1_default { pinmux = , ; bias-disable; }; pinctrl_isc_base: isc_base { pinmux = , , , ; bias-disable; }; pinctrl_isc_data_8bit: isc_data_8bit { pinmux = , , , , , , , ; bias-disable; }; pinctrl_isc_data_9_10: isc_data_9_10 { pinmux = , ; bias-disable; }; pinctrl_isc_data_11_12: isc_data_11_12 { pinmux = , ; bias-disable; }; pinctrl_key_gpio_default: key_gpio_default { pinmux = ; bias-pull-up; }; pinctrl_led_gpio_default: led_gpio_default { pinmux = , , ; bias-pull-up; }; pinctrl_sdmmc0_default: sdmmc0_default { cmd_data { pinmux = , , , , , , , , ; bias-disable; }; ck_cd_vddsel { pinmux = , , ; bias-disable; }; }; pinctrl_sdmmc1_default: sdmmc1_default { cmd_data { pinmux = , , , , ; bias-disable; }; conf-ck_cd { pinmux = , ; bias-disable; }; }; pinctrl_spi0_default: spi0_default { pinmux = , , , ; bias-disable; }; pinctrl_uart1_default: uart1_default { pinmux = , ; bias-disable; }; pinctrl_uart3_default: uart3_default { pinmux = , ; bias-disable; }; pinctrl_usb_default: usb_default { pinmux = , ; bias-disable; }; pinctrl_usba_vbus: usba_vbus { pinmux = ; bias-disable; }; pinctrl_mikrobus1_an: mikrobus1_an { pinmux = ; bias-disable; }; pinctrl_mikrobus2_an: mikrobus2_an { pinmux = ; bias-disable; }; pinctrl_mikrobus1_rst: mikrobus1_rst { pinmux = ; bias-disable; }; pinctrl_mikrobus2_rst: mikrobus2_rst { pinmux = ; bias-disable; }; pinctrl_mikrobus1_spi_cs: mikrobus1_spi_cs { pinmux = ; bias-disable; }; pinctrl_mikrobus2_spi_cs: mikrobus2_spi_cs { pinmux = ; bias-disable; }; pinctrl_mikrobus_spi: mikrobus_spi { pinmux = , , ; bias-disable; }; pinctrl_mikrobus1_pwm: mikrobus1_pwm { pinmux = ; bias-disable; }; pinctrl_mikrobus2_pwm: mikrobus2_pwm { pinmux = ; bias-disable; }; pinctrl_mikrobus1_int: mikrobus1_int { pinmux = ; bias-disable; }; pinctrl_mikrobus2_int: mikrobus2_int { pinmux = ; bias-disable; }; pinctrl_mikrobus1_uart: mikrobus1_uart { pinmux = , ; bias-disable; }; pinctrl_mikrobus2_uart: mikrobus2_uart { pinmux = , ; bias-disable; }; pinctrl_mikrobus_i2c: mikrobus1_i2c { pinmux = , ; bias-disable; }; pinctrl_flx4_default: flx4_uart_default { pinmux = , , , , ; bias-disable; }; }; can1: can@fc050000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can1_default>; status = "okay"; }; }; }; gpio_keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_key_gpio_default>; pb4 { label = "USER"; gpios = <&pioA PIN_PA29 GPIO_ACTIVE_LOW>; /* linux,code = ; BSD license issue */ wakeup-source; }; }; leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_led_gpio_default>; status = "okay"; /* Conflict with pwm0. */ red { label = "red"; gpios = <&pioA PIN_PA10 GPIO_ACTIVE_HIGH>; }; green { label = "green"; gpios = <&pioA PIN_PB1 GPIO_ACTIVE_HIGH>; }; blue { label = "blue"; gpios = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; }; vddin_3v3: fixed-regulator-vddin_3v3 { compatible = "regulator-fixed"; regulator-name = "VDDIN_3V3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; status = "okay"; }; vddana: fixed-regulator-vddana { compatible = "regulator-fixed"; regulator-name = "VDDANA"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; vin-supply = <&vddin_3v3>; status = "okay"; }; advref: fixed-regulator-advref { compatible = "regulator-fixed"; regulator-name = "advref"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-boot-on; vin-supply = <&vddana>; status = "okay"; }; }; optee_os-4.3.0/core/arch/arm/dts/at91-sama5d27_wlsom1.dtsi000066400000000000000000000147401464416617300230610ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * at91-sama5d27_wlsom1.dtsi - Device Tree file for SAMA5D27 WLSOM1 * * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries * * Author: Nicolas Ferre * Author: Eugen Hristev */ #include "sama5d2.dtsi" #include "sama5d2-pinfunc.h" #include #include / { model = "Microchip SAMA5D27 WLSOM1"; compatible = "microchip,sama5d27-wlsom1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; aliases { i2c0 = &i2c0; }; clocks { slow_xtal { clock-frequency = <32768>; }; main_xtal { clock-frequency = <24000000>; }; }; }; &flx1 { atmel,flexcom-mode = ; uart6: serial@200 { pinctrl-0 = <&pinctrl_flx1_default>; pinctrl-names = "default"; }; }; &i2c0 { pinctrl-0 = <&pinctrl_i2c0_default>; pinctrl-1 = <&pinctrl_i2c0_gpio>; pinctrl-names = "default", "gpio"; sda-gpios = <&pioA PIN_PD21 GPIO_ACTIVE_HIGH>; scl-gpios = <&pioA PIN_PD22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; }; &i2c1 { dmas = <0>, <0>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1_default>; pinctrl-1 = <&pinctrl_i2c1_gpio>; sda-gpios = <&pioA PIN_PD19 GPIO_ACTIVE_HIGH>; scl-gpios = <&pioA PIN_PD20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "disable"; secure-status = "okay"; mcp16502@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; status = "okay"; lpm-gpios = <&pioBU 0 GPIO_ACTIVE_LOW>; regulators { vdd_3v3: VDD_IO { regulator-name = "VDD_IO"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3700000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-mode = <4>; }; regulator-state-mem { regulator-off-in-suspend; regulator-mode = <4>; }; }; vddio_ddr: VDD_DDR { regulator-name = "VDD_DDR"; regulator-min-microvolt = <600000>; regulator-max-microvolt = <1850000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-microvolt = <1200000>; regulator-changeable-in-suspend; regulator-mode = <4>; }; regulator-state-mem { regulator-on-in-suspend; regulator-suspend-microvolt = <1200000>; regulator-changeable-in-suspend; regulator-mode = <4>; }; }; vdd_core: VDD_CORE { regulator-name = "VDD_CORE"; regulator-min-microvolt = <600000>; regulator-max-microvolt = <1850000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-mode = <4>; }; regulator-state-mem { regulator-off-in-suspend; regulator-mode = <4>; }; }; vdd_ddr: VDD_OTHER { regulator-name = "VDD_OTHER"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-microvolt = <1800000>; regulator-changeable-in-suspend; regulator-mode = <4>; }; regulator-state-mem { regulator-on-in-suspend; regulator-suspend-microvolt = <1800000>; regulator-changeable-in-suspend; regulator-mode = <4>; }; }; LDO1 { regulator-name = "LDO1"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3700000>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; }; regulator-state-mem { regulator-off-in-suspend; }; }; LDO2 { regulator-name = "LDO2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3700000>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; }; regulator-state-mem { regulator-off-in-suspend; }; }; }; }; }; &macb0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb0_default>; phy-mode = "rmii"; ethernet-phy@0 { reg = <0x0>; interrupt-parent = <&pioA>; interrupts = ; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb0_phy_irq>; }; }; &pmc { atmel,osc-bypass; }; &qspi1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_qspi1_default>; status = "disabled"; qspi1_flash: spi_flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <80000000>; spi-rx-bus-width = <4>; spi-tx-bus-width = <4>; m25p,fast-read; status = "disabled"; at91bootstrap@0 { label = "at91bootstrap"; reg = <0x0 0x40000>; }; bootloader@40000 { label = "bootloader"; reg = <0x40000 0xc0000>; }; bootloaderenvred@100000 { label = "bootloader env redundant"; reg = <0x100000 0x40000>; }; bootloaderenv@140000 { label = "bootloader env"; reg = <0x140000 0x40000>; }; dtb@180000 { label = "device tree"; reg = <0x180000 0x80000>; }; kernel@200000 { label = "kernel"; reg = <0x200000 0x600000>; }; }; }; &pioA { pinctrl_flx1_default: flx1_usart_default { pinmux = , , , ; bias-disable; }; pinctrl_i2c0_default: i2c0_default { pinmux = , ; bias-disable; }; pinctrl_i2c0_gpio: i2c0_gpio { pinmux = , ; bias-disable; }; pinctrl_i2c1_default: i2c1_default { pinmux = , ; bias-disable; }; pinctrl_i2c1_gpio: i2c1_gpio { pinmux = , ; bias-disable; }; pinctrl_macb0_default: macb0_default { pinmux = , , , , , , , , , ; bias-disable; }; pinctrl_macb0_phy_irq: macb0_phy_irq { pinmux = ; bias-disable; }; pinctrl_qspi1_default: qspi1_default { pinmux = , , , , , ; bias-pull-up; }; }; optee_os-4.3.0/core/arch/arm/dts/at91-sama5d27_wlsom1_ek.dts000066400000000000000000000107521464416617300233660ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * at91-sama5d27_wlsom1_ek.dts - Device Tree file for SAMA5D27 WLSOM1 EK * * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries * * Author: Nicolas Ferre */ /dts-v1/; #include "at91-sama5d27_wlsom1.dtsi" / { model = "Microchip SAMA5D27 WLSOM1 EK"; compatible = "microchip,sama5d27-wlsom1-ek", "microchip,sama5d27-wlsom1", "atmel,sama5d27", "atmel,sama5d2", "atmel,sama5"; aliases { serial0 = &uart0; /* DBGU */ serial1 = &uart6; /* BT */ serial2 = &uart5; /* mikro BUS 2 */ serial3 = &uart3; /* mikro BUS 1 */ i2c1 = &i2c1; }; chosen { stdout-path = "serial0:115200n8"; }; leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_led_gpio_default>; status = "okay"; red { label = "red"; gpios = <&pioA PIN_PA6 GPIO_ACTIVE_HIGH>; }; green { label = "green"; gpios = <&pioA PIN_PA7 GPIO_ACTIVE_HIGH>; }; blue { label = "blue"; gpios = <&pioA PIN_PA8 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; }; }; &adc { vddana-supply = <&vdd_3v3>; vref-supply = <&vdd_3v3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_adc_default>; status = "okay"; }; &flx0 { atmel,flexcom-mode = ; status = "okay"; uart5: serial@200 { pinctrl-0 = <&pinctrl_flx0_default>; pinctrl-names = "default"; atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; }; &flx1 { status = "okay"; uart6: serial@200 { atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; }; &macb0 { status = "okay"; }; &pioA { /* * There is no real pinmux for ADC, if the pin * is not requested by another peripheral then * the muxing is done when channel is enabled. * Requesting pins for ADC is GPIO is * encouraged to prevent conflicts and to * disable bias in order to be in the same * state when the pin is not muxed to the adc. */ pinctrl_adc_default: adc_default { pinmux = , ; bias-disable; }; pinctrl_flx0_default: flx0_usart_default { pinmux = , ; bias-disable; }; pinctrl_key_gpio_default: key_gpio_default { pinmux = ; bias-pull-up; }; pinctrl_led_gpio_default: led_gpio_default { pinmux = , , ; bias-pull-down; }; pinctrl_sdmmc0_default: sdmmc0_default { cmd_data { pinmux = , , , , ; bias-disable; }; ck_cd_vddsel { pinmux = , , , ; bias-disable; }; }; pinctrl_uart0_default: uart0_default { pinmux = , ; bias-disable; }; pinctrl_uart3_default: uart3_default { pinmux = , ; bias-disable; }; pinctrl_pwm0_default: pwm0_default { pinmux = , ; bias-disable; }; pinctrl_usb_default: usb_default { pinmux = ; bias-disable; }; pinctrl_usba_vbus: usba_vbus { pinmux = ; bias-disable; }; }; &pwm0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm0_default>; status = "okay"; }; &qspi1 { status = "okay"; qspi1_flash: spi_flash@0 { status = "okay"; }; }; &sdmmc0 { bus-width = <4>; mmc-ddr-3_3v; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc0_default>; status = "okay"; }; &shutdown_controller { atmel,shdwc-debouncer = <976>; atmel,wakeup-rtc-timer; input@0 { reg = <0>; }; }; &tcb0 { timer0: timer@0 { compatible = "atmel,tcb-timer"; reg = <0>; }; timer1: timer@1 { compatible = "atmel,tcb-timer"; reg = <1>; }; }; &uart0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart0_default>; atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; &uart3 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart3_default>; atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; &usb0 { atmel,vbus-gpio = <&pioA PIN_PA16 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usba_vbus>; status = "okay"; }; &usb1 { num-ports = <3>; atmel,vbus-gpio = <0 &pioA PIN_PA10 GPIO_ACTIVE_HIGH 0 >; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb_default>; status = "okay"; }; &usb2 { phy_type = "hsic"; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/at91-sama5d2_xplained.dts000066400000000000000000000433461464416617300232070ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * at91-sama5d2_xplained.dts - Device Tree file for SAMA5D2 Xplained board * * Copyright (C) 2015 Atmel, * 2015 Nicolas Ferre */ /dts-v1/; #include "sama5d2.dtsi" #include "sama5d2-pinfunc.h" #include #include #include / { model = "Atmel SAMA5D2 Xplained"; compatible = "atmel,sama5d2-xplained", "atmel,sama5d2", "atmel,sama5"; aliases { serial0 = &uart1; /* DBGU */ i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; /* XPRO EXT2 */ }; chosen { stdout-path = "serial0:115200n8"; }; clocks { slow_xtal { clock-frequency = <32768>; }; main_xtal { clock-frequency = <12000000>; }; }; ahb { usb0: gadget@300000 { atmel,vbus-gpio = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usba_vbus>; status = "okay"; }; usb1: ohci@400000 { num-ports = <3>; atmel,vbus-gpio = <0 /* &pioA PIN_PB9 GPIO_ACTIVE_HIGH */ &pioA PIN_PB10 GPIO_ACTIVE_HIGH 0 >; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usb_default>; status = "okay"; }; usb2: ehci@500000 { status = "okay"; }; sdmmc0: sdio-host@a0000000 { bus-width = <8>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc0_default>; non-removable; mmc-ddr-1_8v; status = "okay"; }; sdmmc1: sdio-host@b0000000 { bus-width = <4>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc1_default>; status = "okay"; /* conflict with qspi0 */ vqmmc-supply = <&vdd_3v3_reg>; vmmc-supply = <&vdd_3v3_reg>; }; apb { qspi0: spi@f0020000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_qspi0_default>; status = "disabled"; /* conflict with sdmmc1 */ flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <80000000>; spi-tx-bus-width = <4>; spi-rx-bus-width = <4>; m25p,fast-read; at91bootstrap@0 { label = "at91bootstrap"; reg = <0x00000000 0x00040000>; }; bootloader@40000 { label = "bootloader"; reg = <0x00040000 0x000c0000>; }; bootloaderenvred@100000 { label = "bootloader env redundant"; reg = <0x00100000 0x00040000>; }; bootloaderenv@140000 { label = "bootloader env"; reg = <0x00140000 0x00040000>; }; dtb@180000 { label = "device tree"; reg = <0x00180000 0x00080000>; }; kernel@200000 { label = "kernel"; reg = <0x00200000 0x00600000>; }; misc@800000 { label = "misc"; reg = <0x00800000 0x00000000>; }; }; }; spi0: spi@f8000000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spi0_default>; status = "okay"; m25p80@0 { compatible = "atmel,at25df321a"; reg = <0>; spi-max-frequency = <50000000>; }; }; macb0: ethernet@f8008000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_macb0_default &pinctrl_macb0_phy_irq>; phy-mode = "rmii"; status = "okay"; ethernet-phy@1 { reg = <0x1>; interrupt-parent = <&pioA>; interrupts = ; }; }; tcb0: timer@f800c000 { timer0: timer@0 { compatible = "atmel,tcb-timer"; reg = <0>; }; timer1: timer@1 { compatible = "atmel,tcb-timer"; reg = <1>; }; }; uart1: serial@f8020000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart1_default>; atmel,use-dma-rx; atmel,use-dma-tx; status = "okay"; }; i2c0: i2c@f8028000 { dmas = <0>, <0>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c0_default>; pinctrl-1 = <&pinctrl_i2c0_gpio>; sda-gpios = <&pioA PIN_PD21 GPIO_ACTIVE_HIGH>; scl-gpios = <&pioA PIN_PD22 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-sda-hold-time-ns = <350>; status = "okay"; pmic@5b { compatible = "active-semi,act8945a"; reg = <0x5b>; active-semi,vsel-high; status = "okay"; regulators { vdd_1v35_reg: REG_DCDC1 { regulator-name = "VDD_1V35"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-on-in-suspend; regulator-suspend-min-microvolt=<1400000>; regulator-suspend-max-microvolt=<1400000>; regulator-changeable-in-suspend; regulator-mode=; }; }; vdd_1v2_reg: REG_DCDC2 { regulator-name = "VDD_1V2"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1300000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; vdd_3v3_reg: REG_DCDC3 { regulator-name = "VDD_3V3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; vdd_fuse_reg: REG_LDO1 { regulator-name = "VDD_FUSE"; regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2500000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; vdd_3v3_lp_reg: REG_LDO2 { regulator-name = "VDD_3V3_LP"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; vdd_led_reg: REG_LDO3 { regulator-name = "VDD_LED"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; vdd_sdhc_1v8_reg: REG_LDO4 { regulator-name = "VDD_SDHC_1V8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-allowed-modes = , ; regulator-initial-mode = ; regulator-always-on; regulator-state-mem { regulator-off-in-suspend; }; }; }; charger { compatible = "active-semi,act8945a-charger"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>; interrupt-parent = <&pioA>; interrupts = ; active-semi,chglev-gpios = <&pioA PIN_PA12 GPIO_ACTIVE_HIGH>; active-semi,lbo-gpios = <&pioA PIN_PC8 GPIO_ACTIVE_LOW>; active-semi,input-voltage-threshold-microvolt = <6600>; active-semi,precondition-timeout = <40>; active-semi,total-timeout = <3>; status = "okay"; }; }; }; pwm0: pwm@f802c000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm0_pwm2_default>; status = "disabled"; /* conflict with leds */ }; flx0: flexcom@f8034000 { atmel,flexcom-mode = ; status = "disabled"; /* conflict with ISC_D2 & ISC_D3 data pins */ uart5: serial@200 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx0_default>; status = "okay"; }; i2c2: i2c@600 { dmas = <0>, <0>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_flx0_default>; pinctrl-1 = <&pinctrl_i2c2_gpio>; sda-gpios = <&pioA PIN_PB28 GPIO_ACTIVE_HIGH>; scl-gpios = <&pioA PIN_PB29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-sda-hold-time-ns = <350>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; status = "disabled"; /* conflict with ISC_D2 & ISC_D3 data pins */ }; }; shdwc@f8048010 { debounce-delay-us = <976>; atmel,wakeup-rtc-timer; input@0 { reg = <0>; }; }; i2s0: i2s@f8050000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2s0_default>; status = "disabled"; /* conflict with can0 */ }; can0: can@f8054000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can0_default>; status = "okay"; }; uart3: serial@fc008000 { atmel,use-dma-rx; atmel,use-dma-tx; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart3_default>; status = "okay"; }; flx4: flexcom@fc018000 { atmel,flexcom-mode = ; status = "okay"; i2c6: i2c@600 { dmas = <0>, <0>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_flx4_default>; pinctrl-1 = <&pinctrl_flx4_gpio>; sda-gpios = <&pioA PIN_PD12 GPIO_ACTIVE_HIGH>; scl-gpios = <&pioA PIN_PD13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; status = "okay"; }; }; i2c1: i2c@fc028000 { dmas = <0>, <0>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1_default>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; pinctrl-1 = <&pinctrl_i2c1_gpio>; sda-gpios = <&pioA PIN_PD4 GPIO_ACTIVE_HIGH>; scl-gpios = <&pioA PIN_PD5 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; at24@54 { compatible = "atmel,24c02"; reg = <0x54>; pagesize = <16>; }; }; adc: adc@fc030000 { vddana-supply = <&vdd_3v3_lp_reg>; vref-supply = <&vdd_3v3_lp_reg>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_adc_default &pinctrl_adtrg_default>; status = "okay"; }; pinctrl@fc039000 { /* * There is no real pinmux for ADC, if the pin * is not requested by another peripheral then * the muxing is done when channel is enabled. * Requesting pins for ADC is GPIO is * encouraged to prevent conflicts and to * disable bias in order to be in the same * state when the pin is not muxed to the adc. */ pinctrl_adc_default: adc_default { pinmux = ; bias-disable; }; pinctrl_can0_default: can0_default { pinmux = , ; bias-disable; }; pinctrl_can1_default: can1_default { pinmux = , ; bias-disable; }; /* * The ADTRG pin can work on any edge type. * In here it's being pulled up, so need to * connect it to ground to get an edge e.g. * Trigger can be configured on falling, rise * or any edge, and the pull-up can be changed * to pull-down or left floating according to * needs. */ pinctrl_adtrg_default: adtrg_default { pinmux = ; bias-pull-up; }; pinctrl_charger_chglev: charger_chglev { pinmux = ; bias-disable; }; pinctrl_charger_irq: charger_irq { pinmux = ; bias-disable; }; pinctrl_charger_lbo: charger_lbo { pinmux = ; bias-pull-up; }; pinctrl_classd_default_pfets: classd_default_pfets { pinmux = , ; bias-pull-up; }; pinctrl_classd_default_nfets: classd_default_nfets { pinmux = , ; bias-pull-down; }; pinctrl_flx0_default: flx0_default { pinmux = , ; bias-disable; }; pinctrl_flx4_default: flx4_default { pinmux = , ; bias-disable; }; pinctrl_flx4_gpio: flx4_gpio { pinmux = , ; bias-disable; }; pinctrl_i2c0_default: i2c0_default { pinmux = , ; bias-disable; }; pinctrl_i2c0_gpio: i2c0_gpio { pinmux = , ; bias-disable; }; pinctrl_i2c1_default: i2c1_default { pinmux = , ; bias-disable; }; pinctrl_i2c1_gpio: i2c1_gpio { pinmux = , ; bias-disable; }; pinctrl_i2c2_gpio: i2c2_gpio { pinmux = , ; bias-disable; }; pinctrl_i2s0_default: i2s0_default { pinmux = , , , , ; bias-disable; }; pinctrl_i2s1_default: i2s1_default { pinmux = , , , , ; bias-disable; }; pinctrl_key_gpio_default: key_gpio_default { pinmux = ; bias-pull-up; }; pinctrl_led_gpio_default: led_gpio_default { pinmux = , , ; bias-pull-up; }; pinctrl_macb0_default: macb0_default { pinmux = , , , , , , , , , ; bias-disable; }; pinctrl_macb0_phy_irq: macb0_phy_irq { pinmux = ; bias-disable; }; pinctrl_qspi0_default: qspi0_default { sck_cs { pinmux = , ; bias-disable; }; data { pinmux = , , , ; bias-pull-up; }; }; pinctrl_sdmmc0_default: sdmmc0_default { cmd_data { pinmux = , , , , , , , , ; bias-disable; }; ck_cd_rstn_vddsel { pinmux = , , , ; bias-disable; }; }; pinctrl_sdmmc1_default: sdmmc1_default { cmd_data { pinmux = , , , , ; bias-disable; }; conf-ck_cd { pinmux = , ; bias-disable; }; }; pinctrl_spi0_default: spi0_default { pinmux = , , , ; bias-disable; }; pinctrl_uart1_default: uart1_default { pinmux = , ; bias-disable; }; pinctrl_uart3_default: uart3_default { pinmux = , ; bias-disable; }; pinctrl_usb_default: usb_default { pinmux = ; bias-disable; }; pinctrl_usba_vbus: usba_vbus { pinmux = ; bias-disable; }; pinctrl_pwm0_pwm2_default: pwm0_pwm2_default { pinmux = , ; bias-pull-up; }; }; classd: classd@fc048000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_classd_default_pfets &pinctrl_classd_default_nfets>; atmel,pwm-type = "diff"; atmel,non-overlap-time = <10>; status = "okay"; }; i2s1: i2s@fc04c000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2s1_default>; status = "disabled"; /* conflict with spi0, sdmmc1 */ }; can1: can@fc050000 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can1_default>; status = "okay"; }; }; }; gpio_keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_key_gpio_default>; bp1 { label = "PB_USER"; gpios = <&pioA PIN_PB9 GPIO_ACTIVE_LOW>; /* linux,code = ; BSD license issue */ wakeup-source; }; }; leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_led_gpio_default>; status = "okay"; /* conflict with pwm0 */ red { label = "red"; gpios = <&pioA PIN_PB6 GPIO_ACTIVE_LOW>; }; green { label = "green"; gpios = <&pioA PIN_PB5 GPIO_ACTIVE_LOW>; }; blue { label = "blue"; gpios = <&pioA PIN_PB0 GPIO_ACTIVE_LOW>; linux,default-trigger = "heartbeat"; }; }; }; optee_os-4.3.0/core/arch/arm/dts/at91-sama7g54_ek.dts000066400000000000000000000446171464416617300221000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * at91-sama7g54_ek.dts - Device Tree file for SAMA7G54-EK board * * Copyright (c) 2017, Microchip Technology Inc. * 2016 Nicolas Ferre * 2017 Cristian Birsan * 2017 Claudiu Beznea */ /dts-v1/; #include "sama7g5-pinfunc.h" #include "sama7g5.dtsi" #include / { model = "Microchip SAMA7G5-EK"; compatible = "microchip,sama7g5ek", "microchip,sama7g5", "microchip,sama7"; aliases { serial0 = &uart3; serial1 = &uart4; serial2 = &uart7; serial3 = &uart0; i2c0 = &i2c1; i2c1 = &i2c8; i2c2 = &i2c9; }; clocks { slow_xtal { clock-frequency = <32768>; }; main_xtal { clock-frequency = <24000000>; }; }; leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_led_gpio_default>; status = "okay"; /* Conflict with pwm. */ red_led { label = "red"; gpios = <&pioA PIN_PB8 GPIO_ACTIVE_HIGH>; }; green_led { label = "green"; gpios = <&pioA PIN_PA13 GPIO_ACTIVE_HIGH>; }; blue_led { label = "blue"; gpios = <&pioA PIN_PD20 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; }; /* 512 M */ memory@60000000 { device_type = "memory"; reg = <0x60000000 0x20000000>; }; sound: sound { #address-cells = <1>; #size-cells = <0>; assigned-clocks = <&pmc PMC_TYPE_CORE PMC_AUDIOPMCPLL>; assigned-clock-rates = <196608000>; compatible = "microchip,asrc-card"; microchip,model = "mchp-asrc-card @ sama7g5 EK"; status = "disabled"; microchip,audio-asrc = <&asrc 0>, <&asrc 1>, <&asrc 2>, <&asrc 3>; microchip,dai-link@0 { reg = <0>; microchip,convert-channels = <2>; microchip,convert-rate = <48000>; cpu { sound-dai = <&spdiftx>; }; codec { sound-dai = <&spdif_out>; }; }; microchip,dai-link@1 { reg = <1>; microchip,convert-channels = <2>; microchip,convert-rate = <48000>; cpu { sound-dai = <&spdifrx>; }; codec { sound-dai = <&spdif_in>; }; }; }; spdif_in: spdif-in { #sound-dai-cells = <0>; compatible = "linux,spdif-dir"; }; spdif_out: spdif-out { #sound-dai-cells = <0>; compatible = "linux,spdif-dit"; }; }; &asrc { status = "okay"; }; &adc { vddana-supply = <&vddout25>; vref-supply = <&vddout25>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus1_an_default &pinctrl_mikrobus2_an_default>; status = "disabled"; }; &can0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can0_default>; status = "okay"; }; &can1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_can1_default>; status = "okay"; }; &cpu0 { cpu-supply = <&vddcpu>; }; &qspi0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_qspi>; status = "okay"; flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <133000000>; spi-tx-bus-width = <8>; spi-rx-bus-width = <8>; m25p,fast-read; at91bootstrap@0 { label = "ospi: at91bootstrap"; reg = <0x0 0x40000>; }; bootloader@40000 { label = "ospi: bootloader"; reg = <0x40000 0xc0000>; }; bootloaderenvred@100000 { label = "ospi: bootloader env redundant"; reg = <0x100000 0x40000>; }; bootloaderenv@140000 { label = "ospi: bootloader env"; reg = <0x140000 0x40000>; }; dtb@180000 { label = "ospi: device tree"; reg = <0x180000 0x80000>; }; kernel@200000 { label = "ospi: kernel"; reg = <0x200000 0x600000>; }; rootfs@800000 { label = "ospi: rootfs"; reg = <0x800000 0x7800000>; }; }; }; &dma0 { status = "okay"; }; &dma1 { status = "okay"; }; &dma2 { status = "okay"; }; &flx0 { atmel,flexcom-mode = ; status = "disabled"; uart0: serial@200 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx0_default>; status = "disabled"; }; }; &flx1 { atmel,flexcom-mode = ; status = "okay"; i2c1: i2c@600 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1_default>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; status = "disable"; secure-status = "okay"; pac1934@10 { compatible = "microchip,pac1934"; reg = <0x10>; #address-cells = <1>; #size-cells = <0>; status = "okay"; channel@1 { reg = <0x1>; shunt-resistor-micro-ohms = <10000>; label = "VDD3V3"; }; channel@2 { reg = <0x2>; shunt-resistor-micro-ohms = <10000>; label = "VDDIODDR"; }; channel@3 { reg = <0x3>; shunt-resistor-micro-ohms = <10000>; label = "VDDCORE"; }; channel@4 { reg = <0x4>; shunt-resistor-micro-ohms = <10000>; label = "VDDCPU"; }; }; mcp16502@5b { compatible = "microchip,mcp16502"; reg = <0x5b>; status = "okay"; regulators { vdd_3v3: VDD_IO { regulator-name = "VDD_IO"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-microvolt = <3300000>; regulator-mode = <4>; }; regulator-state-mem { regulator-off-in-suspend; regulator-mode = <4>; }; }; vddioddr: VDD_DDR { regulator-name = "VDD_DDR"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-microvolt = <1350000>; regulator-mode = <4>; }; regulator-state-mem { regulator-on-in-suspend; regulator-suspend-microvolt = <1350000>; regulator-mode = <4>; }; }; vddcore: VDD_CORE { regulator-name = "VDD_CORE"; regulator-min-microvolt = <1150000>; regulator-max-microvolt = <1150000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-voltage = <1150000>; regulator-mode = <4>; }; regulator-state-mem { regulator-off-in-suspend; regulator-mode = <4>; }; }; vddcpu: VDD_OTHER { regulator-name = "VDD_OTHER"; regulator-min-microvolt = <1050000>; regulator-max-microvolt = <1250000>; regulator-initial-mode = <2>; regulator-allowed-modes = <2>, <4>; regulator-ramp-delay = <3125>; regulator-always-on; regulator-state-standby { regulator-on-in-suspend; regulator-suspend-voltage = <1050000>; regulator-mode = <4>; }; regulator-state-mem { regulator-off-in-suspend; regulator-mode = <4>; }; }; vldo1: LDO1 { regulator-name = "LDO1"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-state-standby { regulator-suspend-voltage = <1800000>; regulator-on-in-suspend; }; regulator-state-mem { regulator-off-in-suspend; }; }; vldo2: LDO2 { regulator-name = "LDO2"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <3700000>; regulator-state-standby { regulator-suspend-voltage = <1800000>; regulator-on-in-suspend; }; regulator-state-mem { regulator-off-in-suspend; }; }; }; }; }; }; &flx3 { atmel,flexcom-mode = ; status = "okay"; uart3: serial@200 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx3_default>; status = "okay"; }; }; &flx4 { atmel,flexcom-mode = ; status = "okay"; uart4: serial@200 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx4_default>; status = "okay"; }; }; &flx7 { atmel,flexcom-mode = ; status = "okay"; uart7: serial@200 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_flx7_default>; status = "okay"; }; }; &flx8 { atmel,flexcom-mode = ; status = "okay"; i2c8: i2c@600 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c8_default>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; status = "okay"; eeprom0: eeprom0@52 { compatible = "atmel,24mac02e4"; #address-cells = <1>; #size-cells = <0>; reg = <0x52>; pagesize = <16>; size = <256>; status = "okay"; eeprom0_eui48: eui48@fa { reg = <0xfa 0x6>; }; }; eeprom1: eeprom1@53 { compatible = "atmel,24mac02e4"; #address-cells = <1>; #size-cells = <0>; reg = <0x53>; pagesize = <16>; size = <256>; status = "okay"; eeprom1_eui48: eui48@fa { reg = <0xfa 0x6>; }; }; }; }; &flx9 { atmel,flexcom-mode = ; status = "okay"; i2c9: i2c@600 { dmas = <0>, <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c9_default>; i2c-analog-filter; i2c-digital-filter; i2c-digital-filter-width-ns = <35>; status = "okay"; }; }; &flx11 { atmel,flexcom-mode = ; status = "okay"; spi11: spi@400 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus1_spi &pinctrl_mikrobus1_spi_cs>; status = "okay"; }; }; &gmac0 { #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gmac0_default &pinctrl_gmac0_mdio_default &pinctrl_gmac0_txck_default &pinctrl_gmac0_phy_irq>; phy-mode = "rgmii-id"; status = "okay"; nvmem-cells = <&eeprom0_eui48>; nvmem-cell-names = "mac-address"; ethernet-phy@7 { reg = <0x7>; interrupt-parent = <&pioA>; interrupts = ; }; }; &gmac1 { #address-cells = <1>; #size-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gmac1_default &pinctrl_gmac1_mdio_default &pinctrl_gmac1_phy_irq>; phy-mode = "rmii"; status = "disabled"; /* Conflict with pdmc0. */ nvmem-cells = <&eeprom1_eui48>; nvmem-cell-names = "mac-address"; ethernet-phy@0 { reg = <0x0>; interrupt-parent = <&pioA>; interrupts = ; }; }; &i2s0 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2s0_default>; }; &pdmc0 { #sound-dai-cells = <0>; status = "disabled"; /* Conflict with gmac1. */ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pdmc0_default>; }; &pioA { pinctrl_can0_default: can0_default { pinmux = , ; bias-disable; }; pinctrl_can1_default: can1_default { pinmux = , ; bias-disable; }; pinctrl_flx0_default: flx0_default { pinmux = , , , ; bias-disable; }; pinctrl_flx3_default: flx3_default { pinmux = , ; bias-pull-up; }; pinctrl_flx4_default: flx4_default { pinmux = , ; bias-disable; }; pinctrl_flx7_default: flx7_default { pinmux = , ; bias-disable; }; pinctrl_gmac0_default: gmac0_default { pinmux = , , , , , , , , , , , ; slew-rate = <0>; bias-disable; }; pinctrl_gmac0_mdio_default: gmac0_mdio_default { pinmux = , ; bias-disable; }; pinctrl_gmac0_txck_default: gmac0_txck_default { pinmux = ; slew-rate = <0>; bias-pull-up; }; pinctrl_gmac0_phy_irq: gmac0_phy_irq { pinmux = ; bias-disable; }; pinctrl_gmac1_default: gmac1_default { pinmux = , , , , , , , ; slew-rate = <0>; bias-disable; }; pinctrl_gmac1_mdio_default: gmac1_mdio_default { pinmux = , ; bias-disable; }; pinctrl_gmac1_phy_irq: gmac1_phy_irq { pinmux = ; bias-disable; }; pinctrl_i2c1_default: i2c1_default { pinmux = , ; bias-disable; }; pinctrl_i2c8_default: i2c8_default { pinmux = , ; bias-disable; }; pinctrl_i2c9_default: i2c9_default { pinmux = , ; bias-disable; }; pinctrl_i2s0_default: i2s0_default { pinmux = , , , , ; bias-disable; }; pinctrl_key_gpio_default: key_gpio_default { pinmux = ; bias-pull-up; }; pinctrl_led_gpio_default: led_gpio_default { pinmux = , , ; bias-pull-up; }; pinctrl_mikrobus1_an_default: mikrobus1_an_default { pinmux = ; bias-disable; }; pinctrl_mikrobus2_an_default: mikrobus2_an_default { pinmux = ; bias-disable; }; pinctrl_mikrobus1_pwm2_default: mikrobus1_pwm2_default { pinmux = ; bias-disable; }; pinctrl_mikrobus2_pwm3_default: mikrobus2_pwm3_default { pinmux = ; bias-disable; }; pinctrl_mikrobus1_spi_cs: mikrobus1_spi_cs { pinmux = ; bias-disable; }; pinctrl_mikrobus1_spi: mikrobus1_spi { pinmux = , , ; bias-disable; }; pinctrl_pdmc0_default: pdmc0_default { pinmux = , , ; bias_disable; }; pinctrl_qspi: qspi { pinmux = , , , , , , , , , , , , ; bias-disable; slew-rate = <0>; }; pinctrl_sdmmc0_default: sdmmc0_default { cmd_data { pinmux = , , , , , , , , ; slew-rate = <0>; bias-pull-up; }; ck_cd_rstn_vddsel { pinmux = , , ; slew-rate = <0>; bias-pull-up; }; }; pinctrl_sdmmc1_default: sdmmc1_default { cmd_data { pinmux = , , , , ; slew-rate = <0>; bias-pull-up; }; ck_cd_rstn_vddsel { pinmux = , , , ; slew-rate = <0>; bias-pull-up; }; }; pinctrl_sdmmc2_default: sdmmc2_default { cmd_data { pinmux = , , , , ; slew-rate = <0>; bias-pull-up; }; ck { pinmux = ; slew-rate = <0>; bias-pull-up; }; }; pinctrl_spdifrx_default: spdifrx_default { pinmux = ; bias-disable; }; pinctrl_spdiftx_default: spdiftx_default { pinmux = ; bias-disable; }; pinctrl_usba_vbus_det: usba_vbus_det { pinmux = ; bias-disable; }; pinctrl_usbb_vbus_det: usbb_vbus_det { pinmux = ; bias-disable; }; pinctrl_usba_vbus_en: usba_vbus_en { pinmux = ; bias-disable; }; pinctrl_usbb_vbus_en: usbb_vbus_en { pinmux = ; bias-disable; }; pinctrl_usbc_vbus_en: usbc_vbus_en { pinmux = ; bias-disable; }; }; &pwm { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mikrobus1_pwm2_default &pinctrl_mikrobus2_pwm3_default>; status = "disabled"; /* Conflict with leds. */ }; &rtt { atmel,rtt-rtc-time-reg = <&gpbr 0x0>; }; &sdmmc0 { bus-width = <8>; non-removable; vmmc-supply = <&vdd_3v3>; vqmmc-supply = <&vldo1>; mmc-ddr-1_8v; cap-mmc-highspeed; cap-mmc-hw-reset; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc0_default>; status = "okay"; }; &sdmmc1 { bus-width = <4>; vmmc-supply = <&vdd_3v3>; vqmmc-supply = <&vdd_3v3>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc1_default>; status = "okay"; }; &sdmmc2 { bus-width = <4>; no-1-8-v; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdmmc2_default>; }; &shdwc { debounce-delay-us = <976>; microchip,lpm-connection = <&gmac1 &main_xtal>; input@0 { reg = <0>; }; }; &spdifrx { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spdifrx_default>; status = "okay"; }; &spdiftx { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_spdiftx_default>; status = "okay"; }; &tcb0 { timer0: timer@0 { compatible = "atmel,tcb-timer"; reg = <0>; }; timer1: timer@1 { compatible = "atmel,tcb-timer"; reg = <1>; }; }; &usb0 { atmel,vbus-gpio = <&pioA PIN_PD11 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usba_vbus_det>; phys = <&usb_phy0>; phy-names = "usb"; status = "okay"; }; &usb1 { atmel,vbus-gpio = <&pioA PIN_PC12 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usbb_vbus_det>; phys = <&usb_phy1>; phy-names = "usb"; status = "disabled"; }; &usb2 { num-ports = <3>; atmel,vbus-gpio = <0 &pioA PIN_PC11 GPIO_ACTIVE_HIGH &pioA PIN_PC6 GPIO_ACTIVE_HIGH >; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_usbb_vbus_en &pinctrl_usbc_vbus_en>; phys = <&usb_phy1>, <&usb_phy2>; phy-names = "usb", "usb"; status = "okay"; }; &usb3 { status = "okay"; }; &usb_phy0 { status = "okay"; }; &usb_phy1 { status = "okay"; }; &usb_phy2 { status = "okay"; }; &vddout25 { vin-supply = <&vdd_3v3>; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/dt_driver_test.dtsi000066400000000000000000000023631464416617300224770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include / { /* * Device dt-test-consumer consumes resource, it is expected * to defer its probe until resources are ready. */ dt-test-consumer { compatible = "linaro,dt-test-consumer"; clocks = <&dt_test_provider 3>, <&dt_test_provider 7>; clock-names = "clk0", "clk1"; resets = <&dt_test_provider 35>, <&dt_test_provider 5>; reset-names = "rst0", "rst1"; test-gpios = <&dt_test_provider 1 GPIO_ACTIVE_LOW>, <&dt_test_provider 2 GPIO_PULL_UP>; }; /* * Resource device are discovered from subnode added to probe * list by related drivers (here all simple-bus). */ dt-test-bus-b0 { compatible = "simple-bus"; dt-test-bus-b1 { compatible = "simple-bus"; dt-test-bus-b2 { compatible = "simple-bus"; dt-test-bus-b3 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <0>; dt_test_provider: dt-test-provider@0 { compatible = "linaro,dt-test-provider"; reg = <0>; #clock-cells = <1>; #reset-cells = <1>; #gpio-cells = <2>; }; }; }; }; }; dt-test-crypt-consumer { compatible = "linaro,dt-test-crypt-consumer"; }; }; optee_os-4.3.0/core/arch/arm/dts/embedded_dtb_test.dts000066400000000000000000000003201464416617300227150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ /dts-v1/; #include "dt_driver_test.dtsi" / { model = "Embedded device tree for OP-TEE/Qemu platform test purpose"; }; optee_os-4.3.0/core/arch/arm/dts/fsl-lx2160a-qds.dts000066400000000000000000000116121464416617300217460ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR MIT) // // Device Tree file for LX2160AQDS // // Copyright 2018-2020 NXP /dts-v1/; #include "fsl-lx2160a.dtsi" / { model = "NXP Layerscape LX2160AQDS"; compatible = "fsl,lx2160a-qds", "fsl,lx2160a"; aliases { crypto = &crypto; serial0 = &uart0; }; chosen { stdout-path = "serial0:115200n8"; }; sb_3v3: regulator-sb3v3 { compatible = "regulator-fixed"; regulator-name = "MC34717-3.3VSB"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; mdio-mux-1 { compatible = "mdio-mux-multiplexer"; mux-controls = <&mux 0>; mdio-parent-bus = <&emdio1>; #address-cells=<1>; #size-cells = <0>; mdio@0 { /* On-board PHY #1 RGMI1*/ reg = <0x00>; #address-cells = <1>; #size-cells = <0>; }; mdio@8 { /* On-board PHY #2 RGMI2*/ reg = <0x8>; #address-cells = <1>; #size-cells = <0>; }; mdio@18 { /* Slot #1 */ reg = <0x18>; #address-cells = <1>; #size-cells = <0>; }; mdio@19 { /* Slot #2 */ reg = <0x19>; #address-cells = <1>; #size-cells = <0>; }; mdio@1a { /* Slot #3 */ reg = <0x1a>; #address-cells = <1>; #size-cells = <0>; }; mdio@1b { /* Slot #4 */ reg = <0x1b>; #address-cells = <1>; #size-cells = <0>; }; mdio@1c { /* Slot #5 */ reg = <0x1c>; #address-cells = <1>; #size-cells = <0>; }; mdio@1d { /* Slot #6 */ reg = <0x1d>; #address-cells = <1>; #size-cells = <0>; }; mdio@1e { /* Slot #7 */ reg = <0x1e>; #address-cells = <1>; #size-cells = <0>; }; mdio@1f { /* Slot #8 */ reg = <0x1f>; #address-cells = <1>; #size-cells = <0>; }; }; mdio-mux-2 { compatible = "mdio-mux-multiplexer"; mux-controls = <&mux 1>; mdio-parent-bus = <&emdio2>; #address-cells=<1>; #size-cells = <0>; mdio@0 { /* Slot #1 (secondary EMI) */ reg = <0x00>; #address-cells = <1>; #size-cells = <0>; }; mdio@1 { /* Slot #2 (secondary EMI) */ reg = <0x01>; #address-cells = <1>; #size-cells = <0>; }; mdio@2 { /* Slot #3 (secondary EMI) */ reg = <0x02>; #address-cells = <1>; #size-cells = <0>; }; mdio@3 { /* Slot #4 (secondary EMI) */ reg = <0x03>; #address-cells = <1>; #size-cells = <0>; }; mdio@4 { /* Slot #5 (secondary EMI) */ reg = <0x04>; #address-cells = <1>; #size-cells = <0>; }; mdio@5 { /* Slot #6 (secondary EMI) */ reg = <0x05>; #address-cells = <1>; #size-cells = <0>; }; mdio@6 { /* Slot #7 (secondary EMI) */ reg = <0x06>; #address-cells = <1>; #size-cells = <0>; }; mdio@7 { /* Slot #8 (secondary EMI) */ reg = <0x07>; #address-cells = <1>; #size-cells = <0>; }; }; }; &can0 { status = "okay"; }; &can1 { status = "okay"; }; &crypto { status = "okay"; }; &dspi0 { status = "okay"; dflash0: flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <1000000>; }; }; &dspi1 { status = "okay"; dflash1: flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <1000000>; }; }; &dspi2 { status = "okay"; dflash2: flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <1000000>; }; }; &emdio1 { status = "okay"; }; &emdio2 { status = "okay"; }; &esdhc0 { status = "okay"; }; &esdhc1 { status = "okay"; }; &i2c0 { status = "okay"; fpga@66 { compatible = "fsl,lx2160aqds-fpga", "fsl,fpga-qixis-i2c", "simple-mfd"; reg = <0x66>; mux: mux-controller { compatible = "reg-mux"; #mux-control-cells = <1>; mux-reg-masks = <0x54 0xf8>, /* 0: reg 0x54, bits 7:3 */ <0x54 0x07>; /* 1: reg 0x54, bit 2:0 */ }; }; i2c-mux@77 { compatible = "nxp,pca9547"; reg = <0x77>; #address-cells = <1>; #size-cells = <0>; i2c@2 { #address-cells = <1>; #size-cells = <0>; reg = <0x2>; power-monitor@40 { compatible = "ti,ina220"; reg = <0x40>; shunt-resistor = <500>; }; power-monitor@41 { compatible = "ti,ina220"; reg = <0x41>; shunt-resistor = <1000>; }; }; i2c@3 { #address-cells = <1>; #size-cells = <0>; reg = <0x3>; temperature-sensor@4c { compatible = "nxp,sa56004"; reg = <0x4c>; vcc-supply = <&sb_3v3>; }; temperature-sensor@4d { compatible = "nxp,sa56004"; reg = <0x4d>; vcc-supply = <&sb_3v3>; }; rtc@51 { compatible = "nxp,pcf2129"; reg = <0x51>; }; }; }; }; &sata0 { status = "okay"; }; &sata1 { status = "okay"; }; &sata2 { status = "okay"; }; &sata3 { status = "okay"; }; &uart0 { status = "okay"; }; &uart1 { status = "okay"; }; &usb0 { status = "okay"; }; &usb1 { status = "okay"; }; &sata0 { status = "okay"; }; &sata1 { status = "okay"; }; &sata2 { status = "okay"; }; &sata3 { status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/fsl-lx2160a-rdb.dts000066400000000000000000000043411464416617300217270ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR MIT) // // Device Tree file for LX2160ARDB // // Copyright 2018 NXP /dts-v1/; #include "fsl-lx2160a.dtsi" / { model = "NXP Layerscape LX2160ARDB"; compatible = "fsl,lx2160a-rdb", "fsl,lx2160a"; aliases { crypto = &crypto; serial0 = &uart0; }; chosen { stdout-path = "serial0:115200n8"; }; sb_3v3: regulator-sb3v3 { compatible = "regulator-fixed"; regulator-name = "MC34717-3.3VSB"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-boot-on; regulator-always-on; }; }; &crypto { status = "okay"; }; &esdhc0 { sd-uhs-sdr104; sd-uhs-sdr50; sd-uhs-sdr25; sd-uhs-sdr12; status = "okay"; }; &esdhc1 { mmc-hs200-1_8v; mmc-hs400-1_8v; bus-width = <8>; status = "okay"; }; &fspi { status = "okay"; mt35xu512aba0: flash@0 { #address-cells = <1>; #size-cells = <1>; compatible = "spansion,m25p80"; m25p,fast-read; spi-max-frequency = <50000000>; reg = <0>; spi-rx-bus-width = <8>; spi-tx-bus-width = <8>; }; mt35xu512aba1: flash@1 { #address-cells = <1>; #size-cells = <1>; compatible = "spansion,m25p80"; m25p,fast-read; spi-max-frequency = <50000000>; reg = <1>; spi-rx-bus-width = <8>; spi-tx-bus-width = <8>; }; }; &i2c0 { status = "okay"; i2c-mux@77 { compatible = "nxp,pca9547"; reg = <0x77>; #address-cells = <1>; #size-cells = <0>; i2c@2 { #address-cells = <1>; #size-cells = <0>; reg = <0x2>; power-monitor@40 { compatible = "ti,ina220"; reg = <0x40>; shunt-resistor = <1000>; }; }; i2c@3 { #address-cells = <1>; #size-cells = <0>; reg = <0x3>; temperature-sensor@4c { compatible = "nxp,sa56004"; reg = <0x4c>; vcc-supply = <&sb_3v3>; }; temperature-sensor@4d { compatible = "nxp,sa56004"; reg = <0x4d>; vcc-supply = <&sb_3v3>; }; }; }; }; &i2c4 { status = "okay"; rtc@51 { compatible = "nxp,pcf2129"; reg = <0x51>; // IRQ10_B interrupts = <0 150 0x4>; }; }; &sata0 { status = "okay"; }; &sata1 { status = "okay"; }; &sata2 { status = "okay"; }; &sata3 { status = "okay"; }; &uart0 { status = "okay"; }; &uart1 { status = "okay"; }; &usb0 { status = "okay"; }; &usb1 { status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/fsl-lx2160a.dtsi000066400000000000000000001131101464416617300213260ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR MIT) // // Device Tree Include file for Layerscape-LX2160A family SoC. // // Copyright 2018-2020 NXP #include #include /memreserve/ 0x80000000 0x00010000; / { compatible = "fsl,lx2160a"; interrupt-parent = <&gic>; #address-cells = <2>; #size-cells = <2>; aliases { rtc1 = &ftm_alarm0; }; cpus { #address-cells = <1>; #size-cells = <0>; // 8 clusters having 2 Cortex-A72 cores each cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x0>; clocks = <&clockgen 1 0>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster0_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu1: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x1>; clocks = <&clockgen 1 0>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster0_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu100: cpu@100 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x100>; clocks = <&clockgen 1 1>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster1_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu101: cpu@101 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x101>; clocks = <&clockgen 1 1>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster1_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu200: cpu@200 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x200>; clocks = <&clockgen 1 2>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster2_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu201: cpu@201 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x201>; clocks = <&clockgen 1 2>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster2_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu300: cpu@300 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x300>; clocks = <&clockgen 1 3>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster3_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu301: cpu@301 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x301>; clocks = <&clockgen 1 3>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster3_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu400: cpu@400 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x400>; clocks = <&clockgen 1 4>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster4_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu401: cpu@401 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x401>; clocks = <&clockgen 1 4>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster4_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu500: cpu@500 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x500>; clocks = <&clockgen 1 5>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster5_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu501: cpu@501 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x501>; clocks = <&clockgen 1 5>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster5_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu600: cpu@600 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x600>; clocks = <&clockgen 1 6>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster6_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu601: cpu@601 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x601>; clocks = <&clockgen 1 6>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster6_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu700: cpu@700 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x700>; clocks = <&clockgen 1 7>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster7_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cpu701: cpu@701 { device_type = "cpu"; compatible = "arm,cortex-a72"; enable-method = "psci"; reg = <0x701>; clocks = <&clockgen 1 7>; d-cache-size = <0x8000>; d-cache-line-size = <64>; d-cache-sets = <128>; i-cache-size = <0xC000>; i-cache-line-size = <64>; i-cache-sets = <192>; next-level-cache = <&cluster7_l2>; cpu-idle-states = <&cpu_pw15>; #cooling-cells = <2>; }; cluster0_l2: l2-cache0 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster1_l2: l2-cache1 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster2_l2: l2-cache2 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster3_l2: l2-cache3 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster4_l2: l2-cache4 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster5_l2: l2-cache5 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster6_l2: l2-cache6 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cluster7_l2: l2-cache7 { compatible = "cache"; cache-size = <0x100000>; cache-line-size = <64>; cache-sets = <1024>; cache-level = <2>; }; cpu_pw15: cpu-pw15 { compatible = "arm,idle-state"; idle-state-name = "PW15"; arm,psci-suspend-param = <0x0>; entry-latency-us = <2000>; exit-latency-us = <2000>; min-residency-us = <6000>; }; }; gic: interrupt-controller@6000000 { compatible = "arm,gic-v3"; reg = <0x0 0x06000000 0 0x10000>, // GIC Dist <0x0 0x06200000 0 0x200000>, // GICR (RD_base + // SGI_base) <0x0 0x0c0c0000 0 0x2000>, // GICC <0x0 0x0c0d0000 0 0x1000>, // GICH <0x0 0x0c0e0000 0 0x20000>; // GICV #interrupt-cells = <3>; #address-cells = <2>; #size-cells = <2>; ranges; interrupt-controller; interrupts = ; its: gic-its@6020000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x6020000 0 0x20000>; }; }; timer { compatible = "arm,armv8-timer"; interrupts = , , , ; }; pmu { compatible = "arm,cortex-a72-pmu"; interrupts = ; }; psci { compatible = "arm,psci-0.2"; method = "smc"; }; memory@80000000 { // DRAM space - 1, size : 2 GB DRAM device_type = "memory"; reg = <0x00000000 0x80000000 0 0x80000000>; }; memory@2080000000 { // DRAM space - 1, size : 126 GB DRAM device_type = "memory"; reg = <0x00000020 0x80000000 0x0000001F 0x80000000>; }; ddr1: memory-controller@1080000 { compatible = "fsl,qoriq-memory-controller"; reg = <0x0 0x1080000 0x0 0x1000>; interrupts = ; little-endian; }; ddr2: memory-controller@1090000 { compatible = "fsl,qoriq-memory-controller"; reg = <0x0 0x1090000 0x0 0x1000>; interrupts = ; little-endian; }; // One clock unit-sysclk node which bootloader require during DT fix-up sysclk: sysclk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <100000000>; // fixed up by bootloader clock-output-names = "sysclk"; }; thermal-zones { core_thermal1: core-thermal1 { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&tmu 0>; trips { core_cluster_alert: core-cluster-alert { temperature = <85000>; hysteresis = <2000>; type = "passive"; }; core_cluster_crit: core-cluster-crit { temperature = <95000>; hysteresis = <2000>; type = "critical"; }; }; }; }; soc { compatible = "simple-bus"; #address-cells = <2>; #size-cells = <2>; ranges; dma-ranges = <0x0 0x0 0x0 0x0 0x10000 0x00000000>; crypto: crypto@8000000 { compatible = "fsl,sec-v5.0", "fsl,sec-v4.0"; fsl,sec-era = <10>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x00 0x8000000 0x100000>; reg = <0x00 0x8000000 0x0 0x100000>; interrupts = ; dma-coherent; status = "disabled"; sec_jr0: jr@10000 { compatible = "fsl,sec-v5.0-job-ring", "fsl,sec-v4.0-job-ring"; reg = <0x10000 0x10000>; interrupts = ; status = "okay"; secure-status = "disabled"; /* NS-only */ }; sec_jr1: jr@20000 { compatible = "fsl,sec-v5.0-job-ring", "fsl,sec-v4.0-job-ring"; reg = <0x20000 0x10000>; interrupts = ; status = "okay"; secure-status = "disabled"; /* NS-only */ }; sec_jr2: jr@30000 { compatible = "fsl,sec-v5.0-job-ring", "fsl,sec-v4.0-job-ring"; reg = <0x30000 0x10000>; interrupts = ; status = "disabled"; secure-status = "okay"; /* S-only */ }; sec_jr3: jr@40000 { compatible = "fsl,sec-v5.0-job-ring", "fsl,sec-v4.0-job-ring"; reg = <0x40000 0x10000>; interrupts = ; status = "okay"; secure-status = "disabled"; /* workaround for ATF */ }; }; clockgen: clock-controller@1300000 { compatible = "fsl,lx2160a-clockgen"; reg = <0 0x1300000 0 0xa0000>; #clock-cells = <2>; clocks = <&sysclk>; }; dcfg: syscon@1e00000 { compatible = "fsl,lx2160a-dcfg", "syscon"; reg = <0x0 0x1e00000 0x0 0x10000>; little-endian; }; sfp: sfp@1e80000 { compatible = "fsl,lx2160a-sfp"; reg = <0x0 0x1e80000 0x0 0x1000>; }; sec_mon: sec-mon@1e90000 { compatible = "fsl,lx2160a-sec-mon"; reg = <0x0 0x1e90000 0x0 0x1000>; status = "disabled"; secure-status = "okay"; }; /* WRIOP0: 0x8b8_0000, E-MDIO1: 0x1_6000 */ emdio1: mdio@8b96000 { compatible = "fsl,fman-memac-mdio"; reg = <0x0 0x8b96000 0x0 0x1000>; interrupts = ; #address-cells = <1>; #size-cells = <0>; little-endian; /* force the driver in LE mode */ status = "disabled"; }; /* WRIOP0: 0x8b8_0000, E-MDIO2: 0x1_7000 */ emdio2: mdio@8b97000 { compatible = "fsl,fman-memac-mdio"; reg = <0x0 0x8b97000 0x0 0x1000>; interrupts = ; #address-cells = <1>; #size-cells = <0>; little-endian; /* force the driver in LE mode */ status = "disabled"; }; i2c0: i2c@2000000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2000000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; scl-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>; status = "disabled"; }; i2c1: i2c@2010000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2010000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; status = "disabled"; }; i2c2: i2c@2020000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2020000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; status = "disabled"; }; i2c3: i2c@2030000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2030000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; status = "disabled"; }; i2c4: i2c@2040000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2040000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; scl-gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>; status = "disabled"; }; i2c5: i2c@2050000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2050000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; status = "disabled"; }; i2c6: i2c@2060000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2060000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; status = "disabled"; }; i2c7: i2c@2070000 { compatible = "fsl,vf610-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2070000 0x0 0x10000>; interrupts = ; clock-names = "i2c"; clocks = <&clockgen 4 15>; status = "disabled"; }; fspi: spi@20c0000 { compatible = "nxp,lx2160a-fspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x20c0000 0x0 0x10000>, <0x0 0x20000000 0x0 0x10000000>; reg-names = "fspi_base", "fspi_mmap"; interrupts = ; clocks = <&clockgen 4 3>, <&clockgen 4 3>; clock-names = "fspi_en", "fspi"; status = "disabled"; }; dspi0: spi@2100000 { compatible = "fsl,lx2160a-dspi", "fsl,ls2085a-dspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2100000 0x0 0x10000>; interrupts = ; clocks = <&clockgen 4 7>; clock-names = "dspi"; spi-num-chipselects = <5>; bus-num = <0>; status = "disabled"; }; dspi1: spi@2110000 { compatible = "fsl,lx2160a-dspi", "fsl,ls2085a-dspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2110000 0x0 0x10000>; interrupts = ; clocks = <&clockgen 4 7>; clock-names = "dspi"; spi-num-chipselects = <5>; bus-num = <1>; status = "disabled"; }; dspi2: spi@2120000 { compatible = "fsl,lx2160a-dspi", "fsl,ls2085a-dspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x2120000 0x0 0x10000>; interrupts = ; clocks = <&clockgen 4 7>; clock-names = "dspi"; spi-num-chipselects = <5>; bus-num = <2>; status = "disabled"; }; esdhc0: esdhc@2140000 { compatible = "fsl,esdhc"; reg = <0x0 0x2140000 0x0 0x10000>; interrupts = <0 28 0x4>; /* Level high type */ clocks = <&clockgen 4 1>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; little-endian; bus-width = <4>; status = "disabled"; }; esdhc1: esdhc@2150000 { compatible = "fsl,esdhc"; reg = <0x0 0x2150000 0x0 0x10000>; interrupts = <0 63 0x4>; /* Level high type */ clocks = <&clockgen 4 1>; voltage-ranges = <1800 1800 3300 3300>; sdhci,auto-cmd12; broken-cd; little-endian; bus-width = <4>; status = "disabled"; }; can0: can@2180000 { compatible = "fsl,lx2160ar1-flexcan"; reg = <0x0 0x2180000 0x0 0x10000>; interrupts = ; clocks = <&sysclk>, <&clockgen 4 7>; clock-names = "ipg", "per"; status = "disabled"; }; can1: can@2190000 { compatible = "fsl,lx2160ar1-flexcan"; reg = <0x0 0x2190000 0x0 0x10000>; interrupts = ; clocks = <&sysclk>, <&clockgen 4 7>; clock-names = "ipg", "per"; status = "disabled"; }; tmu: tmu@1f80000 { compatible = "fsl,qoriq-tmu"; reg = <0x0 0x1f80000 0x0 0x10000>; interrupts = <0 23 0x4>; fsl,tmu-range = <0x800000E6 0x8001017D>; fsl,tmu-calibration = /* Calibration data group 1 */ <0x00000000 0x00000035 /* Calibration data group 2 */ 0x00010001 0x00000154>; little-endian; #thermal-sensor-cells = <1>; }; uart0: serial@21c0000 { compatible = "arm,sbsa-uart","arm,pl011"; reg = <0x0 0x21c0000 0x0 0x1000>; interrupts = ; current-speed = <115200>; status = "disabled"; }; uart1: serial@21d0000 { compatible = "arm,sbsa-uart","arm,pl011"; reg = <0x0 0x21d0000 0x0 0x1000>; interrupts = ; current-speed = <115200>; status = "disabled"; }; uart2: serial@21e0000 { compatible = "arm,sbsa-uart","arm,pl011"; reg = <0x0 0x21e0000 0x0 0x1000>; interrupts = ; current-speed = <115200>; status = "disabled"; }; uart3: serial@21f0000 { compatible = "arm,sbsa-uart","arm,pl011"; reg = <0x0 0x21f0000 0x0 0x1000>; interrupts = ; current-speed = <115200>; status = "disabled"; }; gpio0: gpio@2300000 { compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2300000 0x0 0x10000>; interrupts = ; gpio-controller; little-endian; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; gpio1: gpio@2310000 { compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2310000 0x0 0x10000>; interrupts = ; gpio-controller; little-endian; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; gpio2: gpio@2320000 { compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2320000 0x0 0x10000>; interrupts = ; gpio-controller; little-endian; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; gpio3: gpio@2330000 { compatible = "fsl,qoriq-gpio"; reg = <0x0 0x2330000 0x0 0x10000>; interrupts = ; gpio-controller; little-endian; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; }; watchdog@23a0000 { compatible = "arm,sbsa-gwdt"; reg = <0x0 0x23a0000 0 0x1000>, <0x0 0x2390000 0 0x1000>; interrupts = ; timeout-sec = <30>; }; rcpm: rcpm@1e34040 { compatible = "fsl,lx2160a-rcpm", "fsl,qoriq-rcpm-2.1+"; reg = <0x0 0x1e34040 0x0 0x1c>; #fsl,rcpm-wakeup-cells = <7>; little-endian; }; ftm_alarm0: timer@2800000 { compatible = "fsl,lx2160a-ftm-alarm"; reg = <0x0 0x2800000 0x0 0x10000>; fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0 0x0>; interrupts = <0 44 4>; }; usb0: usb@3100000 { compatible = "fsl,lx2160a-dwc3", "snps,dwc3"; reg = <0x0 0x3100000 0x0 0x10000>; interrupts = ; dr_mode = "host"; snps,quirk-frame-length-adjustment = <0x20>; usb3-lpm-capable; snps,dis-u1u2-when-u3-quirk; snps,dis_rxdet_inp3_quirk; snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; snps,host-vbus-glitches; dma-coherent; status = "disabled"; }; usb1: usb@3110000 { compatible = "fsl,lx2160a-dwc3", "snps,dwc3"; reg = <0x0 0x3110000 0x0 0x10000>; interrupts = ; dr_mode = "host"; snps,quirk-frame-length-adjustment = <0x20>; usb3-lpm-capable; snps,dis-u1u2-when-u3-quirk; snps,dis_rxdet_inp3_quirk; snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>; snps,host-vbus-glitches; status = "disabled"; }; sata0: sata@3200000 { compatible = "fsl,lx2160a-ahci"; reg = <0x0 0x3200000 0x0 0x10000>, <0x7 0x100520 0x0 0x4>; reg-names = "ahci", "sata-ecc"; interrupts = ; clocks = <&clockgen 4 3>; dma-coherent; status = "disabled"; }; sata1: sata@3210000 { compatible = "fsl,lx2160a-ahci"; reg = <0x0 0x3210000 0x0 0x10000>, <0x7 0x100520 0x0 0x4>; reg-names = "ahci", "sata-ecc"; interrupts = ; clocks = <&clockgen 4 3>; dma-coherent; status = "disabled"; }; sata2: sata@3220000 { compatible = "fsl,lx2160a-ahci"; reg = <0x0 0x3220000 0x0 0x10000>, <0x7 0x100520 0x0 0x4>; reg-names = "ahci", "sata-ecc"; interrupts = ; clocks = <&clockgen 4 3>; dma-coherent; status = "disabled"; }; sata3: sata@3230000 { compatible = "fsl,lx2160a-ahci"; reg = <0x0 0x3230000 0x0 0x10000>, <0x7 0x100520 0x0 0x4>; reg-names = "ahci", "sata-ecc"; interrupts = ; clocks = <&clockgen 4 3>; dma-coherent; status = "disabled"; }; pcie@3400000 { compatible = "fsl,lx2160a-pcie"; reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ 0x80 0x00000000 0x0 0x00001000>; /* configuration space */ reg-names = "csr_axi_slave", "config_axi_slave"; interrupts = , /* AER interrupt */ , /* PME interrupt */ ; /* controller interrupt */ interrupt-names = "aer", "pme", "intr"; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; dma-coherent; apio-wins = <8>; ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ msi-parent = <&its>; iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pcie_ep@3400000 { compatible = "fsl,lx2160a-pcie-ep"; reg = <0x00 0x03400000 0x0 0x00100000 0x80 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; num-ob-windows = <256>; status = "disabled"; }; pcie@3500000 { compatible = "fsl,lx2160a-pcie"; reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */ 0x88 0x00000000 0x0 0x00001000>; /* configuration space */ reg-names = "csr_axi_slave", "config_axi_slave"; interrupts = , /* AER interrupt */ , /* PME interrupt */ ; /* controller interrupt */ interrupt-names = "aer", "pme", "intr"; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; dma-coherent; apio-wins = <8>; ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ msi-parent = <&its>; iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pcie_ep@3500000 { compatible = "fsl,lx2160a-pcie-ep"; reg = <0x00 0x03500000 0x0 0x00100000 0x88 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; num-ob-windows = <256>; status = "disabled"; }; pcie@3600000 { compatible = "fsl,lx2160a-pcie"; reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */ 0x90 0x00000000 0x0 0x00001000>; /* configuration space */ reg-names = "csr_axi_slave", "config_axi_slave"; interrupts = , /* AER interrupt */ , /* PME interrupt */ ; /* controller interrupt */ interrupt-names = "aer", "pme", "intr"; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; dma-coherent; apio-wins = <8>; ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ msi-parent = <&its>; iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 2 &gic 0 0 GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pcie_ep@3600000 { compatible = "fsl,lx2160a-pcie-ep"; reg = <0x00 0x03600000 0x0 0x00100000 0x90 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; num-ob-windows = <256>; max-functions = <2>; status = "disabled"; }; pcie@3700000 { compatible = "fsl,lx2160a-pcie"; reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */ 0x98 0x00000000 0x0 0x00001000>; /* configuration space */ reg-names = "csr_axi_slave", "config_axi_slave"; interrupts = , /* AER interrupt */ , /* PME interrupt */ ; /* controller interrupt */ interrupt-names = "aer", "pme", "intr"; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; dma-coherent; apio-wins = <8>; ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ msi-parent = <&its>; iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 2 &gic 0 0 GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pcie_ep@3700000 { compatible = "fsl,lx2160a-pcie-ep"; reg = <0x00 0x03700000 0x0 0x00100000 0x98 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; num-ob-windows = <256>; status = "disabled"; }; pcie@3800000 { compatible = "fsl,lx2160a-pcie"; reg = <0x00 0x03800000 0x0 0x00100000 /* controller registers */ 0xa0 0x00000000 0x0 0x00001000>; /* configuration space */ reg-names = "csr_axi_slave", "config_axi_slave"; interrupts = , /* AER interrupt */ , /* PME interrupt */ ; /* controller interrupt */ interrupt-names = "aer", "pme", "intr"; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; dma-coherent; apio-wins = <8>; ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ msi-parent = <&its>; iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 2 &gic 0 0 GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pcie_ep@3800000 { compatible = "fsl,lx2160a-pcie-ep"; reg = <0x00 0x03800000 0x0 0x00100000 0xa0 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; num-ob-windows = <256>; max-functions = <2>; status = "disabled"; }; pcie@3900000 { compatible = "fsl,lx2160a-pcie"; reg = <0x00 0x03900000 0x0 0x00100000 /* controller registers */ 0xa8 0x00000000 0x0 0x00001000>; /* configuration space */ reg-names = "csr_axi_slave", "config_axi_slave"; interrupts = , /* AER interrupt */ , /* PME interrupt */ ; /* controller interrupt */ interrupt-names = "aer", "pme", "intr"; #address-cells = <3>; #size-cells = <2>; device_type = "pci"; dma-coherent; apio-wins = <8>; ppio-wins = <8>; bus-range = <0x0 0xff>; ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ msi-parent = <&its>; iommu-map = <0 &smmu 0 1>; /* This is fixed-up by u-boot */ #interrupt-cells = <1>; interrupt-map-mask = <0 0 0 7>; interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 2 &gic 0 0 GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 3 &gic 0 0 GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>, <0000 0 0 4 &gic 0 0 GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; pcie_ep@3900000 { compatible = "fsl,lx2160a-pcie-ep"; reg = <0x00 0x03900000 0x0 0x00100000 0xa8 0x00000000 0x8 0x00000000>; reg-names = "regs", "addr_space"; num-ob-windows = <256>; status = "disabled"; }; smmu: iommu@5000000 { compatible = "arm,mmu-500"; reg = <0 0x5000000 0 0x800000>; #iommu-cells = <1>; #global-interrupts = <14>; // global secure fault interrupts = , // combined secure , // global non-secure fault , // combined non-secure , // performance counter interrupts 0-9 , , , , , , , , , , // per context interrupt, 64 interrupts , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ; dma-coherent; }; console@8340020 { compatible = "fsl,dpaa2-console"; reg = <0x00000000 0x08340020 0 0x2>; }; ptp-timer@8b95000 { compatible = "fsl,dpaa2-ptp"; reg = <0x0 0x8b95000 0x0 0x100>; clocks = <&clockgen 4 1>; little-endian; fsl,extts-fifo; }; fsl_mc: fsl-mc@80c000000 { compatible = "fsl,qoriq-mc"; reg = <0x00000008 0x0c000000 0 0x40>, <0x00000000 0x08340000 0 0x40000>; msi-parent = <&its>; /* iommu-map property is fixed up by u-boot */ iommu-map = <0 &smmu 0 0>; dma-coherent; #address-cells = <3>; #size-cells = <1>; /* * Region type 0x0 - MC portals * Region type 0x1 - QBMAN portals */ ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000 0x1 0x0 0x0 0x8 0x18000000 0x8000000>; /* * Define the maximum number of MACs present on the SoC. */ dpmacs { #address-cells = <1>; #size-cells = <0>; dpmac1: dpmac@1 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x1>; }; dpmac2: dpmac@2 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x2>; }; dpmac3: dpmac@3 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x3>; }; dpmac4: dpmac@4 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x4>; }; dpmac5: dpmac@5 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x5>; }; dpmac6: dpmac@6 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x6>; }; dpmac7: dpmac@7 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x7>; }; dpmac8: dpmac@8 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x8>; }; dpmac9: dpmac@9 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x9>; }; dpmac10: dpmac@a { compatible = "fsl,qoriq-mc-dpmac"; reg = <0xa>; }; dpmac11: dpmac@b { compatible = "fsl,qoriq-mc-dpmac"; reg = <0xb>; }; dpmac12: dpmac@c { compatible = "fsl,qoriq-mc-dpmac"; reg = <0xc>; }; dpmac13: dpmac@d { compatible = "fsl,qoriq-mc-dpmac"; reg = <0xd>; }; dpmac14: dpmac@e { compatible = "fsl,qoriq-mc-dpmac"; reg = <0xe>; }; dpmac15: dpmac@f { compatible = "fsl,qoriq-mc-dpmac"; reg = <0xf>; }; dpmac16: dpmac@10 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x10>; }; dpmac17: dpmac@11 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x11>; }; dpmac18: dpmac@12 { compatible = "fsl,qoriq-mc-dpmac"; reg = <0x12>; }; }; }; }; firmware { optee { compatible = "linaro,optee-tz"; method = "smc"; }; }; }; optee_os-4.3.0/core/arch/arm/dts/hikey.dts000066400000000000000000000005041464416617300204110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ /dts-v1/; / { #address-cells = <1>; #size-cells = <0>; reserved-memory { #address-cells = <1>; #size-cells = <1>; sdp@3e800000 { compatible = "linaro,secure-heap"; no-map; reg = <0x3E800000 0x00400000>; }; }; }; optee_os-4.3.0/core/arch/arm/dts/sama5d2-pinfunc.h000066400000000000000000001234461464416617300216440ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) 2021 Microchip */ #define PINMUX_PIN(no, func, ioset) \ (((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20)) #define PIN_PA0 0 #define PIN_PA0__GPIO PINMUX_PIN(PIN_PA0, 0, 0) #define PIN_PA0__SDMMC0_CK PINMUX_PIN(PIN_PA0, 1, 1) #define PIN_PA0__QSPI0_SCK PINMUX_PIN(PIN_PA0, 2, 1) #define PIN_PA0__D0 PINMUX_PIN(PIN_PA0, 6, 2) #define PIN_PA1 1 #define PIN_PA1__GPIO PINMUX_PIN(PIN_PA1, 0, 0) #define PIN_PA1__SDMMC0_CMD PINMUX_PIN(PIN_PA1, 1, 1) #define PIN_PA1__QSPI0_CS PINMUX_PIN(PIN_PA1, 2, 1) #define PIN_PA1__D1 PINMUX_PIN(PIN_PA1, 6, 2) #define PIN_PA2 2 #define PIN_PA2__GPIO PINMUX_PIN(PIN_PA2, 0, 0) #define PIN_PA2__SDMMC0_DAT0 PINMUX_PIN(PIN_PA2, 1, 1) #define PIN_PA2__QSPI0_IO0 PINMUX_PIN(PIN_PA2, 2, 1) #define PIN_PA2__D2 PINMUX_PIN(PIN_PA2, 6, 2) #define PIN_PA3 3 #define PIN_PA3__GPIO PINMUX_PIN(PIN_PA3, 0, 0) #define PIN_PA3__SDMMC0_DAT1 PINMUX_PIN(PIN_PA3, 1, 1) #define PIN_PA3__QSPI0_IO1 PINMUX_PIN(PIN_PA3, 2, 1) #define PIN_PA3__D3 PINMUX_PIN(PIN_PA3, 6, 2) #define PIN_PA4 4 #define PIN_PA4__GPIO PINMUX_PIN(PIN_PA4, 0, 0) #define PIN_PA4__SDMMC0_DAT2 PINMUX_PIN(PIN_PA4, 1, 1) #define PIN_PA4__QSPI0_IO2 PINMUX_PIN(PIN_PA4, 2, 1) #define PIN_PA4__D4 PINMUX_PIN(PIN_PA4, 6, 2) #define PIN_PA5 5 #define PIN_PA5__GPIO PINMUX_PIN(PIN_PA5, 0, 0) #define PIN_PA5__SDMMC0_DAT3 PINMUX_PIN(PIN_PA5, 1, 1) #define PIN_PA5__QSPI0_IO3 PINMUX_PIN(PIN_PA5, 2, 1) #define PIN_PA5__D5 PINMUX_PIN(PIN_PA5, 6, 2) #define PIN_PA6 6 #define PIN_PA6__GPIO PINMUX_PIN(PIN_PA6, 0, 0) #define PIN_PA6__SDMMC0_DAT4 PINMUX_PIN(PIN_PA6, 1, 1) #define PIN_PA6__QSPI1_SCK PINMUX_PIN(PIN_PA6, 2, 1) #define PIN_PA6__TIOA5 PINMUX_PIN(PIN_PA6, 4, 1) #define PIN_PA6__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA6, 5, 1) #define PIN_PA6__D6 PINMUX_PIN(PIN_PA6, 6, 2) #define PIN_PA7 7 #define PIN_PA7__GPIO PINMUX_PIN(PIN_PA7, 0, 0) #define PIN_PA7__SDMMC0_DAT5 PINMUX_PIN(PIN_PA7, 1, 1) #define PIN_PA7__QSPI1_IO0 PINMUX_PIN(PIN_PA7, 2, 1) #define PIN_PA7__TIOB5 PINMUX_PIN(PIN_PA7, 4, 1) #define PIN_PA7__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA7, 5, 1) #define PIN_PA7__D7 PINMUX_PIN(PIN_PA7, 6, 2) #define PIN_PA8 8 #define PIN_PA8__GPIO PINMUX_PIN(PIN_PA8, 0, 0) #define PIN_PA8__SDMMC0_DAT6 PINMUX_PIN(PIN_PA8, 1, 1) #define PIN_PA8__QSPI1_IO1 PINMUX_PIN(PIN_PA8, 2, 1) #define PIN_PA8__TCLK5 PINMUX_PIN(PIN_PA8, 4, 1) #define PIN_PA8__FLEXCOM2_IO2 PINMUX_PIN(PIN_PA8, 5, 1) #define PIN_PA8__NWE_NANDWE PINMUX_PIN(PIN_PA8, 6, 2) #define PIN_PA9 9 #define PIN_PA9__GPIO PINMUX_PIN(PIN_PA9, 0, 0) #define PIN_PA9__SDMMC0_DAT7 PINMUX_PIN(PIN_PA9, 1, 1) #define PIN_PA9__QSPI1_IO2 PINMUX_PIN(PIN_PA9, 2, 1) #define PIN_PA9__TIOA4 PINMUX_PIN(PIN_PA9, 4, 1) #define PIN_PA9__FLEXCOM2_IO3 PINMUX_PIN(PIN_PA9, 5, 1) #define PIN_PA9__NCS3 PINMUX_PIN(PIN_PA9, 6, 2) #define PIN_PA10 10 #define PIN_PA10__GPIO PINMUX_PIN(PIN_PA10, 0, 0) #define PIN_PA10__SDMMC0_RSTN PINMUX_PIN(PIN_PA10, 1, 1) #define PIN_PA10__QSPI1_IO3 PINMUX_PIN(PIN_PA10, 2, 1) #define PIN_PA10__TIOB4 PINMUX_PIN(PIN_PA10, 4, 1) #define PIN_PA10__FLEXCOM2_IO4 PINMUX_PIN(PIN_PA10, 5, 1) #define PIN_PA10__A21_NANDALE PINMUX_PIN(PIN_PA10, 6, 2) #define PIN_PA11 11 #define PIN_PA11__GPIO PINMUX_PIN(PIN_PA11, 0, 0) #define PIN_PA11__SDMMC0_VDDSEL PINMUX_PIN(PIN_PA11, 1, 1) #define PIN_PA11__QSPI1_CS PINMUX_PIN(PIN_PA11, 2, 1) #define PIN_PA11__TCLK4 PINMUX_PIN(PIN_PA11, 4, 1) #define PIN_PA11__A22_NANDCLE PINMUX_PIN(PIN_PA11, 6, 2) #define PIN_PA12 12 #define PIN_PA12__GPIO PINMUX_PIN(PIN_PA12, 0, 0) #define PIN_PA12__SDMMC0_WP PINMUX_PIN(PIN_PA12, 1, 1) #define PIN_PA12__IRQ PINMUX_PIN(PIN_PA12, 2, 1) #define PIN_PA12__NRD_NANDOE PINMUX_PIN(PIN_PA12, 6, 2) #define PIN_PA13 13 #define PIN_PA13__GPIO PINMUX_PIN(PIN_PA13, 0, 0) #define PIN_PA13__SDMMC0_CD PINMUX_PIN(PIN_PA13, 1, 1) #define PIN_PA13__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA13, 5, 1) #define PIN_PA13__D8 PINMUX_PIN(PIN_PA13, 6, 2) #define PIN_PA14 14 #define PIN_PA14__GPIO PINMUX_PIN(PIN_PA14, 0, 0) #define PIN_PA14__SPI0_SPCK PINMUX_PIN(PIN_PA14, 1, 1) #define PIN_PA14__TK1 PINMUX_PIN(PIN_PA14, 2, 1) #define PIN_PA14__QSPI0_SCK PINMUX_PIN(PIN_PA14, 3, 2) #define PIN_PA14__I2SC1_MCK PINMUX_PIN(PIN_PA14, 4, 2) #define PIN_PA14__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA14, 5, 1) #define PIN_PA14__D9 PINMUX_PIN(PIN_PA14, 6, 2) #define PIN_PA15 15 #define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0) #define PIN_PA15__SPI0_MOSI PINMUX_PIN(PIN_PA15, 1, 1) #define PIN_PA15__TF1 PINMUX_PIN(PIN_PA15, 2, 1) #define PIN_PA15__QSPI0_CS PINMUX_PIN(PIN_PA15, 3, 2) #define PIN_PA15__I2SC1_CK PINMUX_PIN(PIN_PA15, 4, 2) #define PIN_PA15__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA15, 5, 1) #define PIN_PA15__D10 PINMUX_PIN(PIN_PA15, 6, 2) #define PIN_PA16 16 #define PIN_PA16__GPIO PINMUX_PIN(PIN_PA16, 0, 0) #define PIN_PA16__SPI0_MISO PINMUX_PIN(PIN_PA16, 1, 1) #define PIN_PA16__TD1 PINMUX_PIN(PIN_PA16, 2, 1) #define PIN_PA16__QSPI0_IO0 PINMUX_PIN(PIN_PA16, 3, 2) #define PIN_PA16__I2SC1_WS PINMUX_PIN(PIN_PA16, 4, 2) #define PIN_PA16__FLEXCOM3_IO3 PINMUX_PIN(PIN_PA16, 5, 1) #define PIN_PA16__D11 PINMUX_PIN(PIN_PA16, 6, 2) #define PIN_PA17 17 #define PIN_PA17__GPIO PINMUX_PIN(PIN_PA17, 0, 0) #define PIN_PA17__SPI0_NPCS0 PINMUX_PIN(PIN_PA17, 1, 1) #define PIN_PA17__RD1 PINMUX_PIN(PIN_PA17, 2, 1) #define PIN_PA17__QSPI0_IO1 PINMUX_PIN(PIN_PA17, 3, 2) #define PIN_PA17__I2SC1_DI0 PINMUX_PIN(PIN_PA17, 4, 2) #define PIN_PA17__FLEXCOM3_IO4 PINMUX_PIN(PIN_PA17, 5, 1) #define PIN_PA17__D12 PINMUX_PIN(PIN_PA17, 6, 2) #define PIN_PA18 18 #define PIN_PA18__GPIO PINMUX_PIN(PIN_PA18, 0, 0) #define PIN_PA18__SPI0_NPCS1 PINMUX_PIN(PIN_PA18, 1, 1) #define PIN_PA18__RK1 PINMUX_PIN(PIN_PA18, 2, 1) #define PIN_PA18__QSPI0_IO2 PINMUX_PIN(PIN_PA18, 3, 2) #define PIN_PA18__I2SC1_DO0 PINMUX_PIN(PIN_PA18, 4, 2) #define PIN_PA18__SDMMC1_DAT0 PINMUX_PIN(PIN_PA18, 5, 1) #define PIN_PA18__D13 PINMUX_PIN(PIN_PA18, 6, 2) #define PIN_PA19 19 #define PIN_PA19__GPIO PINMUX_PIN(PIN_PA19, 0, 0) #define PIN_PA19__SPI0_NPCS2 PINMUX_PIN(PIN_PA19, 1, 1) #define PIN_PA19__RF1 PINMUX_PIN(PIN_PA19, 2, 1) #define PIN_PA19__QSPI0_IO3 PINMUX_PIN(PIN_PA19, 3, 2) #define PIN_PA19__TIOA0 PINMUX_PIN(PIN_PA19, 4, 1) #define PIN_PA19__SDMMC1_DAT1 PINMUX_PIN(PIN_PA19, 5, 1) #define PIN_PA19__D14 PINMUX_PIN(PIN_PA19, 6, 2) #define PIN_PA20 20 #define PIN_PA20__GPIO PINMUX_PIN(PIN_PA20, 0, 0) #define PIN_PA20__SPI0_NPCS3 PINMUX_PIN(PIN_PA20, 1, 1) #define PIN_PA20__TIOB0 PINMUX_PIN(PIN_PA20, 4, 1) #define PIN_PA20__SDMMC1_DAT2 PINMUX_PIN(PIN_PA20, 5, 1) #define PIN_PA20__D15 PINMUX_PIN(PIN_PA20, 6, 2) #define PIN_PA21 21 #define PIN_PA21__GPIO PINMUX_PIN(PIN_PA21, 0, 0) #define PIN_PA21__IRQ PINMUX_PIN(PIN_PA21, 1, 2) #define PIN_PA21__PCK2 PINMUX_PIN(PIN_PA21, 2, 3) #define PIN_PA21__TCLK0 PINMUX_PIN(PIN_PA21, 4, 1) #define PIN_PA21__SDMMC1_DAT3 PINMUX_PIN(PIN_PA21, 5, 1) #define PIN_PA21__NANDRDY PINMUX_PIN(PIN_PA21, 6, 2) #define PIN_PA22 22 #define PIN_PA22__GPIO PINMUX_PIN(PIN_PA22, 0, 0) #define PIN_PA22__FLEXCOM1_IO2 PINMUX_PIN(PIN_PA22, 1, 1) #define PIN_PA22__D0 PINMUX_PIN(PIN_PA22, 2, 1) #define PIN_PA22__TCK PINMUX_PIN(PIN_PA22, 3, 4) #define PIN_PA22__SPI1_SPCK PINMUX_PIN(PIN_PA22, 4, 2) #define PIN_PA22__SDMMC1_CK PINMUX_PIN(PIN_PA22, 5, 1) #define PIN_PA22__QSPI0_SCK PINMUX_PIN(PIN_PA22, 6, 3) #define PIN_PA23 23 #define PIN_PA23__GPIO PINMUX_PIN(PIN_PA23, 0, 0) #define PIN_PA23__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA23, 1, 1) #define PIN_PA23__D1 PINMUX_PIN(PIN_PA23, 2, 1) #define PIN_PA23__TDI PINMUX_PIN(PIN_PA23, 3, 4) #define PIN_PA23__SPI1_MOSI PINMUX_PIN(PIN_PA23, 4, 2) #define PIN_PA23__QSPI0_CS PINMUX_PIN(PIN_PA23, 6, 3) #define PIN_PA24 24 #define PIN_PA24__GPIO PINMUX_PIN(PIN_PA24, 0, 0) #define PIN_PA24__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA24, 1, 1) #define PIN_PA24__D2 PINMUX_PIN(PIN_PA24, 2, 1) #define PIN_PA24__TDO PINMUX_PIN(PIN_PA24, 3, 4) #define PIN_PA24__SPI1_MISO PINMUX_PIN(PIN_PA24, 4, 2) #define PIN_PA24__QSPI0_IO0 PINMUX_PIN(PIN_PA24, 6, 3) #define PIN_PA25 25 #define PIN_PA25__GPIO PINMUX_PIN(PIN_PA25, 0, 0) #define PIN_PA25__FLEXCOM1_IO3 PINMUX_PIN(PIN_PA25, 1, 1) #define PIN_PA25__D3 PINMUX_PIN(PIN_PA25, 2, 1) #define PIN_PA25__TMS PINMUX_PIN(PIN_PA25, 3, 4) #define PIN_PA25__SPI1_NPCS0 PINMUX_PIN(PIN_PA25, 4, 2) #define PIN_PA25__QSPI0_IO1 PINMUX_PIN(PIN_PA25, 6, 3) #define PIN_PA26 26 #define PIN_PA26__GPIO PINMUX_PIN(PIN_PA26, 0, 0) #define PIN_PA26__FLEXCOM1_IO4 PINMUX_PIN(PIN_PA26, 1, 1) #define PIN_PA26__D4 PINMUX_PIN(PIN_PA26, 2, 1) #define PIN_PA26__NTRST PINMUX_PIN(PIN_PA26, 3, 4) #define PIN_PA26__SPI1_NPCS1 PINMUX_PIN(PIN_PA26, 4, 2) #define PIN_PA26__QSPI0_IO2 PINMUX_PIN(PIN_PA26, 6, 3) #define PIN_PA27 27 #define PIN_PA27__GPIO PINMUX_PIN(PIN_PA27, 0, 0) #define PIN_PA27__TIOA1 PINMUX_PIN(PIN_PA27, 1, 2) #define PIN_PA27__D5 PINMUX_PIN(PIN_PA27, 2, 1) #define PIN_PA27__SPI0_NPCS2 PINMUX_PIN(PIN_PA27, 3, 2) #define PIN_PA27__SPI1_NPCS2 PINMUX_PIN(PIN_PA27, 4, 2) #define PIN_PA27__SDMMC1_RSTN PINMUX_PIN(PIN_PA27, 5, 1) #define PIN_PA27__QSPI0_IO3 PINMUX_PIN(PIN_PA27, 6, 3) #define PIN_PA28 28 #define PIN_PA28__GPIO PINMUX_PIN(PIN_PA28, 0, 0) #define PIN_PA28__TIOB1 PINMUX_PIN(PIN_PA28, 1, 2) #define PIN_PA28__D6 PINMUX_PIN(PIN_PA28, 2, 1) #define PIN_PA28__SPI0_NPCS3 PINMUX_PIN(PIN_PA28, 3, 2) #define PIN_PA28__SPI1_NPCS3 PINMUX_PIN(PIN_PA28, 4, 2) #define PIN_PA28__SDMMC1_CMD PINMUX_PIN(PIN_PA28, 5, 1) #define PIN_PA28__CLASSD_L0 PINMUX_PIN(PIN_PA28, 6, 1) #define PIN_PA29 29 #define PIN_PA29__GPIO PINMUX_PIN(PIN_PA29, 0, 0) #define PIN_PA29__TCLK1 PINMUX_PIN(PIN_PA29, 1, 2) #define PIN_PA29__D7 PINMUX_PIN(PIN_PA29, 2, 1) #define PIN_PA29__SPI0_NPCS1 PINMUX_PIN(PIN_PA29, 3, 2) #define PIN_PA29__SDMMC1_WP PINMUX_PIN(PIN_PA29, 5, 1) #define PIN_PA29__CLASSD_L1 PINMUX_PIN(PIN_PA29, 6, 1) #define PIN_PA30 30 #define PIN_PA30__GPIO PINMUX_PIN(PIN_PA30, 0, 0) #define PIN_PA30__NWE_NANDWE PINMUX_PIN(PIN_PA30, 2, 1) #define PIN_PA30__SPI0_NPCS0 PINMUX_PIN(PIN_PA30, 3, 2) #define PIN_PA30__PWMH0 PINMUX_PIN(PIN_PA30, 4, 1) #define PIN_PA30__SDMMC1_CD PINMUX_PIN(PIN_PA30, 5, 1) #define PIN_PA30__CLASSD_L2 PINMUX_PIN(PIN_PA30, 6, 1) #define PIN_PA31 31 #define PIN_PA31__GPIO PINMUX_PIN(PIN_PA31, 0, 0) #define PIN_PA31__NCS3 PINMUX_PIN(PIN_PA31, 2, 1) #define PIN_PA31__SPI0_MISO PINMUX_PIN(PIN_PA31, 3, 2) #define PIN_PA31__PWML0 PINMUX_PIN(PIN_PA31, 4, 1) #define PIN_PA31__CLASSD_L3 PINMUX_PIN(PIN_PA31, 6, 1) #define PIN_PB0 32 #define PIN_PB0__GPIO PINMUX_PIN(PIN_PB0, 0, 0) #define PIN_PB0__A21_NANDALE PINMUX_PIN(PIN_PB0, 2, 1) #define PIN_PB0__SPI0_MOSI PINMUX_PIN(PIN_PB0, 3, 2) #define PIN_PB0__PWMH1 PINMUX_PIN(PIN_PB0, 4, 1) #define PIN_PB1 33 #define PIN_PB1__GPIO PINMUX_PIN(PIN_PB1, 0, 0) #define PIN_PB1__A22_NANDCLE PINMUX_PIN(PIN_PB1, 2, 1) #define PIN_PB1__SPI0_SPCK PINMUX_PIN(PIN_PB1, 3, 2) #define PIN_PB1__PWML1 PINMUX_PIN(PIN_PB1, 4, 1) #define PIN_PB1__CLASSD_R0 PINMUX_PIN(PIN_PB1, 6, 1) #define PIN_PB2 34 #define PIN_PB2__GPIO PINMUX_PIN(PIN_PB2, 0, 0) #define PIN_PB2__NRD_NANDOE PINMUX_PIN(PIN_PB2, 2, 1) #define PIN_PB2__PWMFI0 PINMUX_PIN(PIN_PB2, 4, 1) #define PIN_PB2__CLASSD_R1 PINMUX_PIN(PIN_PB2, 6, 1) #define PIN_PB3 35 #define PIN_PB3__GPIO PINMUX_PIN(PIN_PB3, 0, 0) #define PIN_PB3__URXD4 PINMUX_PIN(PIN_PB3, 1, 1) #define PIN_PB3__D8 PINMUX_PIN(PIN_PB3, 2, 1) #define PIN_PB3__IRQ PINMUX_PIN(PIN_PB3, 3, 3) #define PIN_PB3__PWMEXTRG0 PINMUX_PIN(PIN_PB3, 4, 1) #define PIN_PB3__CLASSD_R2 PINMUX_PIN(PIN_PB3, 6, 1) #define PIN_PB4 36 #define PIN_PB4__GPIO PINMUX_PIN(PIN_PB4, 0, 0) #define PIN_PB4__UTXD4 PINMUX_PIN(PIN_PB4, 1, 1) #define PIN_PB4__D9 PINMUX_PIN(PIN_PB4, 2, 1) #define PIN_PB4__FIQ PINMUX_PIN(PIN_PB4, 3, 4) #define PIN_PB4__CLASSD_R3 PINMUX_PIN(PIN_PB4, 6, 1) #define PIN_PB5 37 #define PIN_PB5__GPIO PINMUX_PIN(PIN_PB5, 0, 0) #define PIN_PB5__TCLK2 PINMUX_PIN(PIN_PB5, 1, 1) #define PIN_PB5__D10 PINMUX_PIN(PIN_PB5, 2, 1) #define PIN_PB5__PWMH2 PINMUX_PIN(PIN_PB5, 3, 1) #define PIN_PB5__QSPI1_SCK PINMUX_PIN(PIN_PB5, 4, 2) #define PIN_PB5__GTSUCOMP PINMUX_PIN(PIN_PB5, 6, 3) #define PIN_PB6 38 #define PIN_PB6__GPIO PINMUX_PIN(PIN_PB6, 0, 0) #define PIN_PB6__TIOA2 PINMUX_PIN(PIN_PB6, 1, 1) #define PIN_PB6__D11 PINMUX_PIN(PIN_PB6, 2, 1) #define PIN_PB6__PWML2 PINMUX_PIN(PIN_PB6, 3, 1) #define PIN_PB6__QSPI1_CS PINMUX_PIN(PIN_PB6, 4, 2) #define PIN_PB6__GTXER PINMUX_PIN(PIN_PB6, 6, 3) #define PIN_PB7 39 #define PIN_PB7__GPIO PINMUX_PIN(PIN_PB7, 0, 0) #define PIN_PB7__TIOB2 PINMUX_PIN(PIN_PB7, 1, 1) #define PIN_PB7__D12 PINMUX_PIN(PIN_PB7, 2, 1) #define PIN_PB7__PWMH3 PINMUX_PIN(PIN_PB7, 3, 1) #define PIN_PB7__QSPI1_IO0 PINMUX_PIN(PIN_PB7, 4, 2) #define PIN_PB7__GRXCK PINMUX_PIN(PIN_PB7, 6, 3) #define PIN_PB8 40 #define PIN_PB8__GPIO PINMUX_PIN(PIN_PB8, 0, 0) #define PIN_PB8__TCLK3 PINMUX_PIN(PIN_PB8, 1, 1) #define PIN_PB8__D13 PINMUX_PIN(PIN_PB8, 2, 1) #define PIN_PB8__PWML3 PINMUX_PIN(PIN_PB8, 3, 1) #define PIN_PB8__QSPI1_IO1 PINMUX_PIN(PIN_PB8, 4, 2) #define PIN_PB8__GCRS PINMUX_PIN(PIN_PB8, 6, 3) #define PIN_PB9 41 #define PIN_PB9__GPIO PINMUX_PIN(PIN_PB9, 0, 0) #define PIN_PB9__TIOA3 PINMUX_PIN(PIN_PB9, 1, 1) #define PIN_PB9__D14 PINMUX_PIN(PIN_PB9, 2, 1) #define PIN_PB9__PWMFI1 PINMUX_PIN(PIN_PB9, 3, 1) #define PIN_PB9__QSPI1_IO2 PINMUX_PIN(PIN_PB9, 4, 2) #define PIN_PB9__GCOL PINMUX_PIN(PIN_PB9, 6, 3) #define PIN_PB10 42 #define PIN_PB10__GPIO PINMUX_PIN(PIN_PB10, 0, 0) #define PIN_PB10__TIOB3 PINMUX_PIN(PIN_PB10, 1, 1) #define PIN_PB10__D15 PINMUX_PIN(PIN_PB10, 2, 1) #define PIN_PB10__PWMEXTRG1 PINMUX_PIN(PIN_PB10, 3, 1) #define PIN_PB10__QSPI1_IO3 PINMUX_PIN(PIN_PB10, 4, 2) #define PIN_PB10__GRX2 PINMUX_PIN(PIN_PB10, 6, 3) #define PIN_PB11 43 #define PIN_PB11__GPIO PINMUX_PIN(PIN_PB11, 0, 0) #define PIN_PB11__LCDDAT0 PINMUX_PIN(PIN_PB11, 1, 1) #define PIN_PB11__A0_NBS0 PINMUX_PIN(PIN_PB11, 2, 1) #define PIN_PB11__URXD3 PINMUX_PIN(PIN_PB11, 3, 3) #define PIN_PB11__PDMIC_DAT PINMUX_PIN(PIN_PB11, 4, 2) #define PIN_PB11__GRX3 PINMUX_PIN(PIN_PB11, 6, 3) #define PIN_PB12 44 #define PIN_PB12__GPIO PINMUX_PIN(PIN_PB12, 0, 0) #define PIN_PB12__LCDDAT1 PINMUX_PIN(PIN_PB12, 1, 1) #define PIN_PB12__A1 PINMUX_PIN(PIN_PB12, 2, 1) #define PIN_PB12__UTXD3 PINMUX_PIN(PIN_PB12, 3, 3) #define PIN_PB12__PDMIC_CLK PINMUX_PIN(PIN_PB12, 4, 2) #define PIN_PB12__GTX2 PINMUX_PIN(PIN_PB12, 6, 3) #define PIN_PB13 45 #define PIN_PB13__GPIO PINMUX_PIN(PIN_PB13, 0, 0) #define PIN_PB13__LCDDAT2 PINMUX_PIN(PIN_PB13, 1, 1) #define PIN_PB13__A2 PINMUX_PIN(PIN_PB13, 2, 1) #define PIN_PB13__PCK1 PINMUX_PIN(PIN_PB13, 3, 3) #define PIN_PB13__GTX3 PINMUX_PIN(PIN_PB13, 6, 3) #define PIN_PB14 46 #define PIN_PB14__GPIO PINMUX_PIN(PIN_PB14, 0, 0) #define PIN_PB14__LCDDAT3 PINMUX_PIN(PIN_PB14, 1, 1) #define PIN_PB14__A3 PINMUX_PIN(PIN_PB14, 2, 1) #define PIN_PB14__TK1 PINMUX_PIN(PIN_PB14, 3, 2) #define PIN_PB14__I2SC1_MCK PINMUX_PIN(PIN_PB14, 4, 1) #define PIN_PB14__QSPI1_SCK PINMUX_PIN(PIN_PB14, 5, 3) #define PIN_PB14__GTXCK PINMUX_PIN(PIN_PB14, 6, 3) #define PIN_PB15 47 #define PIN_PB15__GPIO PINMUX_PIN(PIN_PB15, 0, 0) #define PIN_PB15__LCDDAT4 PINMUX_PIN(PIN_PB15, 1, 1) #define PIN_PB15__A4 PINMUX_PIN(PIN_PB15, 2, 1) #define PIN_PB15__TF1 PINMUX_PIN(PIN_PB15, 3, 2) #define PIN_PB15__I2SC1_CK PINMUX_PIN(PIN_PB15, 4, 1) #define PIN_PB15__QSPI1_CS PINMUX_PIN(PIN_PB15, 5, 3) #define PIN_PB15__GTXEN PINMUX_PIN(PIN_PB15, 6, 3) #define PIN_PB16 48 #define PIN_PB16__GPIO PINMUX_PIN(PIN_PB16, 0, 0) #define PIN_PB16__LCDDAT5 PINMUX_PIN(PIN_PB16, 1, 1) #define PIN_PB16__A5 PINMUX_PIN(PIN_PB16, 2, 1) #define PIN_PB16__TD1 PINMUX_PIN(PIN_PB16, 3, 2) #define PIN_PB16__I2SC1_WS PINMUX_PIN(PIN_PB16, 4, 1) #define PIN_PB16__QSPI1_IO0 PINMUX_PIN(PIN_PB16, 5, 3) #define PIN_PB16__GRXDV PINMUX_PIN(PIN_PB16, 6, 3) #define PIN_PB17 49 #define PIN_PB17__GPIO PINMUX_PIN(PIN_PB17, 0, 0) #define PIN_PB17__LCDDAT6 PINMUX_PIN(PIN_PB17, 1, 1) #define PIN_PB17__A6 PINMUX_PIN(PIN_PB17, 2, 1) #define PIN_PB17__RD1 PINMUX_PIN(PIN_PB17, 3, 2) #define PIN_PB17__I2SC1_DI0 PINMUX_PIN(PIN_PB17, 4, 1) #define PIN_PB17__QSPI1_IO1 PINMUX_PIN(PIN_PB17, 5, 3) #define PIN_PB17__GRXER PINMUX_PIN(PIN_PB17, 6, 3) #define PIN_PB18 50 #define PIN_PB18__GPIO PINMUX_PIN(PIN_PB18, 0, 0) #define PIN_PB18__LCDDAT7 PINMUX_PIN(PIN_PB18, 1, 1) #define PIN_PB18__A7 PINMUX_PIN(PIN_PB18, 2, 1) #define PIN_PB18__RK1 PINMUX_PIN(PIN_PB18, 3, 2) #define PIN_PB18__I2SC1_DO0 PINMUX_PIN(PIN_PB18, 4, 1) #define PIN_PB18__QSPI1_IO2 PINMUX_PIN(PIN_PB18, 5, 3) #define PIN_PB18__GRX0 PINMUX_PIN(PIN_PB18, 6, 3) #define PIN_PB19 51 #define PIN_PB19__GPIO PINMUX_PIN(PIN_PB19, 0, 0) #define PIN_PB19__LCDDAT8 PINMUX_PIN(PIN_PB19, 1, 1) #define PIN_PB19__A8 PINMUX_PIN(PIN_PB19, 2, 1) #define PIN_PB19__RF1 PINMUX_PIN(PIN_PB19, 3, 2) #define PIN_PB19__TIOA3 PINMUX_PIN(PIN_PB19, 4, 2) #define PIN_PB19__QSPI1_IO3 PINMUX_PIN(PIN_PB19, 5, 3) #define PIN_PB19__GRX1 PINMUX_PIN(PIN_PB19, 6, 3) #define PIN_PB20 52 #define PIN_PB20__GPIO PINMUX_PIN(PIN_PB20, 0, 0) #define PIN_PB20__LCDDAT9 PINMUX_PIN(PIN_PB20, 1, 1) #define PIN_PB20__A9 PINMUX_PIN(PIN_PB20, 2, 1) #define PIN_PB20__TK0 PINMUX_PIN(PIN_PB20, 3, 1) #define PIN_PB20__TIOB3 PINMUX_PIN(PIN_PB20, 4, 2) #define PIN_PB20__PCK1 PINMUX_PIN(PIN_PB20, 5, 4) #define PIN_PB20__GTX0 PINMUX_PIN(PIN_PB20, 6, 3) #define PIN_PB21 53 #define PIN_PB21__GPIO PINMUX_PIN(PIN_PB21, 0, 0) #define PIN_PB21__LCDDAT10 PINMUX_PIN(PIN_PB21, 1, 1) #define PIN_PB21__A10 PINMUX_PIN(PIN_PB21, 2, 1) #define PIN_PB21__TF0 PINMUX_PIN(PIN_PB21, 3, 1) #define PIN_PB21__TCLK3 PINMUX_PIN(PIN_PB21, 4, 2) #define PIN_PB21__FLEXCOM3_IO2 PINMUX_PIN(PIN_PB21, 5, 3) #define PIN_PB21__GTX1 PINMUX_PIN(PIN_PB21, 6, 3) #define PIN_PB22 54 #define PIN_PB22__GPIO PINMUX_PIN(PIN_PB22, 0, 0) #define PIN_PB22__LCDDAT11 PINMUX_PIN(PIN_PB22, 1, 1) #define PIN_PB22__A11 PINMUX_PIN(PIN_PB22, 2, 1) #define PIN_PB22__TD0 PINMUX_PIN(PIN_PB22, 3, 1) #define PIN_PB22__TIOA2 PINMUX_PIN(PIN_PB22, 4, 2) #define PIN_PB22__FLEXCOM3_IO1 PINMUX_PIN(PIN_PB22, 5, 3) #define PIN_PB22__GMDC PINMUX_PIN(PIN_PB22, 6, 3) #define PIN_PB23 55 #define PIN_PB23__GPIO PINMUX_PIN(PIN_PB23, 0, 0) #define PIN_PB23__LCDDAT12 PINMUX_PIN(PIN_PB23, 1, 1) #define PIN_PB23__A12 PINMUX_PIN(PIN_PB23, 2, 1) #define PIN_PB23__RD0 PINMUX_PIN(PIN_PB23, 3, 1) #define PIN_PB23__TIOB2 PINMUX_PIN(PIN_PB23, 4, 2) #define PIN_PB23__FLEXCOM3_IO0 PINMUX_PIN(PIN_PB23, 5, 3) #define PIN_PB23__GMDIO PINMUX_PIN(PIN_PB23, 6, 3) #define PIN_PB24 56 #define PIN_PB24__GPIO PINMUX_PIN(PIN_PB24, 0, 0) #define PIN_PB24__LCDDAT13 PINMUX_PIN(PIN_PB24, 1, 1) #define PIN_PB24__A13 PINMUX_PIN(PIN_PB24, 2, 1) #define PIN_PB24__RK0 PINMUX_PIN(PIN_PB24, 3, 1) #define PIN_PB24__TCLK2 PINMUX_PIN(PIN_PB24, 4, 2) #define PIN_PB24__FLEXCOM3_IO3 PINMUX_PIN(PIN_PB24, 5, 3) #define PIN_PB24__ISC_D10 PINMUX_PIN(PIN_PB24, 6, 3) #define PIN_PB25 57 #define PIN_PB25__GPIO PINMUX_PIN(PIN_PB25, 0, 0) #define PIN_PB25__LCDDAT14 PINMUX_PIN(PIN_PB25, 1, 1) #define PIN_PB25__A14 PINMUX_PIN(PIN_PB25, 2, 1) #define PIN_PB25__RF0 PINMUX_PIN(PIN_PB25, 3, 1) #define PIN_PB25__FLEXCOM3_IO4 PINMUX_PIN(PIN_PB25, 5, 3) #define PIN_PB25__ISC_D11 PINMUX_PIN(PIN_PB25, 6, 3) #define PIN_PB26 58 #define PIN_PB26__GPIO PINMUX_PIN(PIN_PB26, 0, 0) #define PIN_PB26__LCDDAT15 PINMUX_PIN(PIN_PB26, 1, 1) #define PIN_PB26__A15 PINMUX_PIN(PIN_PB26, 2, 1) #define PIN_PB26__URXD0 PINMUX_PIN(PIN_PB26, 3, 1) #define PIN_PB26__PDMIC_DAT PINMUX_PIN(PIN_PB26, 4, 1) #define PIN_PB26__ISC_D0 PINMUX_PIN(PIN_PB26, 6, 3) #define PIN_PB27 59 #define PIN_PB27__GPIO PINMUX_PIN(PIN_PB27, 0, 0) #define PIN_PB27__LCDDAT16 PINMUX_PIN(PIN_PB27, 1, 1) #define PIN_PB27__A16 PINMUX_PIN(PIN_PB27, 2, 1) #define PIN_PB27__UTXD0 PINMUX_PIN(PIN_PB27, 3, 1) #define PIN_PB27__PDMIC_CLK PINMUX_PIN(PIN_PB27, 4, 1) #define PIN_PB27__ISC_D1 PINMUX_PIN(PIN_PB27, 6, 3) #define PIN_PB28 60 #define PIN_PB28__GPIO PINMUX_PIN(PIN_PB28, 0, 0) #define PIN_PB28__LCDDAT17 PINMUX_PIN(PIN_PB28, 1, 1) #define PIN_PB28__A17 PINMUX_PIN(PIN_PB28, 2, 1) #define PIN_PB28__FLEXCOM0_IO0 PINMUX_PIN(PIN_PB28, 3, 1) #define PIN_PB28__TIOA5 PINMUX_PIN(PIN_PB28, 4, 2) #define PIN_PB28__ISC_D2 PINMUX_PIN(PIN_PB28, 6, 3) #define PIN_PB29 61 #define PIN_PB29__GPIO PINMUX_PIN(PIN_PB29, 0, 0) #define PIN_PB29__LCDDAT18 PINMUX_PIN(PIN_PB29, 1, 1) #define PIN_PB29__A18 PINMUX_PIN(PIN_PB29, 2, 1) #define PIN_PB29__FLEXCOM0_IO1 PINMUX_PIN(PIN_PB29, 3, 1) #define PIN_PB29__TIOB5 PINMUX_PIN(PIN_PB29, 4, 2) #define PIN_PB29__ISC_D3 PINMUX_PIN(PIN_PB29, 7, 3) #define PIN_PB30 62 #define PIN_PB30__GPIO PINMUX_PIN(PIN_PB30, 0, 0) #define PIN_PB30__LCDDAT19 PINMUX_PIN(PIN_PB30, 1, 1) #define PIN_PB30__A19 PINMUX_PIN(PIN_PB30, 2, 1) #define PIN_PB30__FLEXCOM0_IO2 PINMUX_PIN(PIN_PB30, 3, 1) #define PIN_PB30__TCLK5 PINMUX_PIN(PIN_PB30, 4, 2) #define PIN_PB30__ISC_D4 PINMUX_PIN(PIN_PB30, 6, 3) #define PIN_PB31 63 #define PIN_PB31__GPIO PINMUX_PIN(PIN_PB31, 0, 0) #define PIN_PB31__LCDDAT20 PINMUX_PIN(PIN_PB31, 1, 1) #define PIN_PB31__A20 PINMUX_PIN(PIN_PB31, 2, 1) #define PIN_PB31__FLEXCOM0_IO3 PINMUX_PIN(PIN_PB31, 3, 1) #define PIN_PB31__TWD0 PINMUX_PIN(PIN_PB31, 4, 1) #define PIN_PB31__ISC_D5 PINMUX_PIN(PIN_PB31, 6, 3) #define PIN_PC0 64 #define PIN_PC0__GPIO PINMUX_PIN(PIN_PC0, 0, 0) #define PIN_PC0__LCDDAT21 PINMUX_PIN(PIN_PC0, 1, 1) #define PIN_PC0__A23 PINMUX_PIN(PIN_PC0, 2, 1) #define PIN_PC0__FLEXCOM0_IO4 PINMUX_PIN(PIN_PC0, 3, 1) #define PIN_PC0__TWCK0 PINMUX_PIN(PIN_PC0, 4, 1) #define PIN_PC0__ISC_D6 PINMUX_PIN(PIN_PC0, 6, 3) #define PIN_PC1 65 #define PIN_PC1__GPIO PINMUX_PIN(PIN_PC1, 0, 0) #define PIN_PC1__LCDDAT22 PINMUX_PIN(PIN_PC1, 1, 1) #define PIN_PC1__A24 PINMUX_PIN(PIN_PC1, 2, 1) #define PIN_PC1__CANTX0 PINMUX_PIN(PIN_PC1, 3, 1) #define PIN_PC1__SPI1_SPCK PINMUX_PIN(PIN_PC1, 4, 1) #define PIN_PC1__I2SC0_CK PINMUX_PIN(PIN_PC1, 5, 1) #define PIN_PC1__ISC_D7 PINMUX_PIN(PIN_PC1, 6, 3) #define PIN_PC2 66 #define PIN_PC2__GPIO PINMUX_PIN(PIN_PC2, 0, 0) #define PIN_PC2__LCDDAT23 PINMUX_PIN(PIN_PC2, 1, 1) #define PIN_PC2__A25 PINMUX_PIN(PIN_PC2, 2, 1) #define PIN_PC2__CANRX0 PINMUX_PIN(PIN_PC2, 3, 1) #define PIN_PC2__SPI1_MOSI PINMUX_PIN(PIN_PC2, 4, 1) #define PIN_PC2__I2SC0_MCK PINMUX_PIN(PIN_PC2, 5, 1) #define PIN_PC2__ISC_D8 PINMUX_PIN(PIN_PC2, 6, 3) #define PIN_PC3 67 #define PIN_PC3__GPIO PINMUX_PIN(PIN_PC3, 0, 0) #define PIN_PC3__LCDPWM PINMUX_PIN(PIN_PC3, 1, 1) #define PIN_PC3__NWAIT PINMUX_PIN(PIN_PC3, 2, 1) #define PIN_PC3__TIOA1 PINMUX_PIN(PIN_PC3, 3, 1) #define PIN_PC3__SPI1_MISO PINMUX_PIN(PIN_PC3, 4, 1) #define PIN_PC3__I2SC0_WS PINMUX_PIN(PIN_PC3, 5, 1) #define PIN_PC3__ISC_D9 PINMUX_PIN(PIN_PC3, 6, 3) #define PIN_PC4 68 #define PIN_PC4__GPIO PINMUX_PIN(PIN_PC4, 0, 0) #define PIN_PC4__LCDDISP PINMUX_PIN(PIN_PC4, 1, 1) #define PIN_PC4__NWR1_NBS1 PINMUX_PIN(PIN_PC4, 2, 1) #define PIN_PC4__TIOB1 PINMUX_PIN(PIN_PC4, 3, 1) #define PIN_PC4__SPI1_NPCS0 PINMUX_PIN(PIN_PC4, 4, 1) #define PIN_PC4__I2SC0_DI0 PINMUX_PIN(PIN_PC4, 5, 1) #define PIN_PC4__ISC_PCK PINMUX_PIN(PIN_PC4, 6, 3) #define PIN_PC5 69 #define PIN_PC5__GPIO PINMUX_PIN(PIN_PC5, 0, 0) #define PIN_PC5__LCDVSYNC PINMUX_PIN(PIN_PC5, 1, 1) #define PIN_PC5__NCS0 PINMUX_PIN(PIN_PC5, 2, 1) #define PIN_PC5__TCLK1 PINMUX_PIN(PIN_PC5, 3, 1) #define PIN_PC5__SPI1_NPCS1 PINMUX_PIN(PIN_PC5, 4, 1) #define PIN_PC5__I2SC0_DO0 PINMUX_PIN(PIN_PC5, 5, 1) #define PIN_PC5__ISC_VSYNC PINMUX_PIN(PIN_PC5, 6, 3) #define PIN_PC6 70 #define PIN_PC6__GPIO PINMUX_PIN(PIN_PC6, 0, 0) #define PIN_PC6__LCDHSYNC PINMUX_PIN(PIN_PC6, 1, 1) #define PIN_PC6__NCS1 PINMUX_PIN(PIN_PC6, 2, 1) #define PIN_PC6__TWD1 PINMUX_PIN(PIN_PC6, 3, 1) #define PIN_PC6__SPI1_NPCS2 PINMUX_PIN(PIN_PC6, 4, 1) #define PIN_PC6__ISC_HSYNC PINMUX_PIN(PIN_PC6, 6, 3) #define PIN_PC7 71 #define PIN_PC7__GPIO PINMUX_PIN(PIN_PC7, 0, 0) #define PIN_PC7__LCDPCK PINMUX_PIN(PIN_PC7, 1, 1) #define PIN_PC7__NCS2 PINMUX_PIN(PIN_PC7, 2, 1) #define PIN_PC7__TWCK1 PINMUX_PIN(PIN_PC7, 3, 1) #define PIN_PC7__SPI1_NPCS3 PINMUX_PIN(PIN_PC7, 4, 1) #define PIN_PC7__URXD1 PINMUX_PIN(PIN_PC7, 5, 2) #define PIN_PC7__ISC_MCK PINMUX_PIN(PIN_PC7, 6, 3) #define PIN_PC8 72 #define PIN_PC8__GPIO PINMUX_PIN(PIN_PC8, 0, 0) #define PIN_PC8__LCDDEN PINMUX_PIN(PIN_PC8, 1, 1) #define PIN_PC8__NANDRDY PINMUX_PIN(PIN_PC8, 2, 1) #define PIN_PC8__FIQ PINMUX_PIN(PIN_PC8, 3, 1) #define PIN_PC8__PCK0 PINMUX_PIN(PIN_PC8, 4, 3) #define PIN_PC8__UTXD1 PINMUX_PIN(PIN_PC8, 5, 2) #define PIN_PC8__ISC_FIELD PINMUX_PIN(PIN_PC8, 6, 3) #define PIN_PC9 73 #define PIN_PC9__GPIO PINMUX_PIN(PIN_PC9, 0, 0) #define PIN_PC9__FIQ PINMUX_PIN(PIN_PC9, 1, 3) #define PIN_PC9__GTSUCOMP PINMUX_PIN(PIN_PC9, 2, 1) #define PIN_PC9__ISC_D0 PINMUX_PIN(PIN_PC9, 3, 1) #define PIN_PC9__TIOA4 PINMUX_PIN(PIN_PC9, 4, 2) #define PIN_PC10 74 #define PIN_PC10__GPIO PINMUX_PIN(PIN_PC10, 0, 0) #define PIN_PC10__LCDDAT2 PINMUX_PIN(PIN_PC10, 1, 2) #define PIN_PC10__GTXCK PINMUX_PIN(PIN_PC10, 2, 1) #define PIN_PC10__ISC_D1 PINMUX_PIN(PIN_PC10, 3, 1) #define PIN_PC10__TIOB4 PINMUX_PIN(PIN_PC10, 4, 2) #define PIN_PC10__CANTX0 PINMUX_PIN(PIN_PC10, 5, 2) #define PIN_PC11 75 #define PIN_PC11__GPIO PINMUX_PIN(PIN_PC11, 0, 0) #define PIN_PC11__LCDDAT3 PINMUX_PIN(PIN_PC11, 1, 2) #define PIN_PC11__GTXEN PINMUX_PIN(PIN_PC11, 2, 1) #define PIN_PC11__ISC_D2 PINMUX_PIN(PIN_PC11, 3, 1) #define PIN_PC11__TCLK4 PINMUX_PIN(PIN_PC11, 4, 2) #define PIN_PC11__CANRX0 PINMUX_PIN(PIN_PC11, 5, 2) #define PIN_PC11__A0_NBS0 PINMUX_PIN(PIN_PC11, 6, 2) #define PIN_PC12 76 #define PIN_PC12__GPIO PINMUX_PIN(PIN_PC12, 0, 0) #define PIN_PC12__LCDDAT4 PINMUX_PIN(PIN_PC12, 1, 2) #define PIN_PC12__GRXDV PINMUX_PIN(PIN_PC12, 2, 1) #define PIN_PC12__ISC_D3 PINMUX_PIN(PIN_PC12, 3, 1) #define PIN_PC12__URXD3 PINMUX_PIN(PIN_PC12, 4, 1) #define PIN_PC12__TK0 PINMUX_PIN(PIN_PC12, 5, 2) #define PIN_PC12__A1 PINMUX_PIN(PIN_PC12, 6, 2) #define PIN_PC13 77 #define PIN_PC13__GPIO PINMUX_PIN(PIN_PC13, 0, 0) #define PIN_PC13__LCDDAT5 PINMUX_PIN(PIN_PC13, 1, 2) #define PIN_PC13__GRXER PINMUX_PIN(PIN_PC13, 2, 1) #define PIN_PC13__ISC_D4 PINMUX_PIN(PIN_PC13, 3, 1) #define PIN_PC13__UTXD3 PINMUX_PIN(PIN_PC13, 4, 1) #define PIN_PC13__TF0 PINMUX_PIN(PIN_PC13, 5, 2) #define PIN_PC13__A2 PINMUX_PIN(PIN_PC13, 6, 2) #define PIN_PC14 78 #define PIN_PC14__GPIO PINMUX_PIN(PIN_PC14, 0, 0) #define PIN_PC14__LCDDAT6 PINMUX_PIN(PIN_PC14, 1, 2) #define PIN_PC14__GRX0 PINMUX_PIN(PIN_PC14, 2, 1) #define PIN_PC14__ISC_D5 PINMUX_PIN(PIN_PC14, 3, 1) #define PIN_PC14__TD0 PINMUX_PIN(PIN_PC14, 5, 2) #define PIN_PC14__A3 PINMUX_PIN(PIN_PC14, 6, 2) #define PIN_PC15 79 #define PIN_PC15__GPIO PINMUX_PIN(PIN_PC15, 0, 0) #define PIN_PC15__LCDDAT7 PINMUX_PIN(PIN_PC15, 1, 2) #define PIN_PC15__GRX1 PINMUX_PIN(PIN_PC15, 2, 1) #define PIN_PC15__ISC_D6 PINMUX_PIN(PIN_PC15, 3, 1) #define PIN_PC15__RD0 PINMUX_PIN(PIN_PC15, 5, 2) #define PIN_PC15__A4 PINMUX_PIN(PIN_PC15, 6, 2) #define PIN_PC16 80 #define PIN_PC16__GPIO PINMUX_PIN(PIN_PC16, 0, 0) #define PIN_PC16__LCDDAT10 PINMUX_PIN(PIN_PC16, 1, 2) #define PIN_PC16__GTX0 PINMUX_PIN(PIN_PC16, 2, 1) #define PIN_PC16__ISC_D7 PINMUX_PIN(PIN_PC16, 3, 1) #define PIN_PC16__RK0 PINMUX_PIN(PIN_PC16, 5, 2) #define PIN_PC16__A5 PINMUX_PIN(PIN_PC16, 6, 2) #define PIN_PC17 81 #define PIN_PC17__GPIO PINMUX_PIN(PIN_PC17, 0, 0) #define PIN_PC17__LCDDAT11 PINMUX_PIN(PIN_PC17, 1, 2) #define PIN_PC17__GTX1 PINMUX_PIN(PIN_PC17, 2, 1) #define PIN_PC17__ISC_D8 PINMUX_PIN(PIN_PC17, 3, 1) #define PIN_PC17__RF0 PINMUX_PIN(PIN_PC17, 5, 2) #define PIN_PC17__A6 PINMUX_PIN(PIN_PC17, 6, 2) #define PIN_PC18 82 #define PIN_PC18__GPIO PINMUX_PIN(PIN_PC18, 0, 0) #define PIN_PC18__LCDDAT12 PINMUX_PIN(PIN_PC18, 1, 2) #define PIN_PC18__GMDC PINMUX_PIN(PIN_PC18, 2, 1) #define PIN_PC18__ISC_D9 PINMUX_PIN(PIN_PC18, 3, 1) #define PIN_PC18__FLEXCOM3_IO2 PINMUX_PIN(PIN_PC18, 5, 2) #define PIN_PC18__A7 PINMUX_PIN(PIN_PC18, 6, 2) #define PIN_PC19 83 #define PIN_PC19__GPIO PINMUX_PIN(PIN_PC19, 0, 0) #define PIN_PC19__LCDDAT13 PINMUX_PIN(PIN_PC19, 1, 2) #define PIN_PC19__GMDIO PINMUX_PIN(PIN_PC19, 2, 1) #define PIN_PC19__ISC_D10 PINMUX_PIN(PIN_PC19, 3, 1) #define PIN_PC19__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC19, 5, 2) #define PIN_PC19__A8 PINMUX_PIN(PIN_PC19, 6, 2) #define PIN_PC20 84 #define PIN_PC20__GPIO PINMUX_PIN(PIN_PC20, 0, 0) #define PIN_PC20__LCDDAT14 PINMUX_PIN(PIN_PC20, 1, 2) #define PIN_PC20__GRXCK PINMUX_PIN(PIN_PC20, 2, 1) #define PIN_PC20__ISC_D11 PINMUX_PIN(PIN_PC20, 3, 1) #define PIN_PC20__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC20, 5, 2) #define PIN_PC20__A9 PINMUX_PIN(PIN_PC20, 6, 2) #define PIN_PC21 85 #define PIN_PC21__GPIO PINMUX_PIN(PIN_PC21, 0, 0) #define PIN_PC21__LCDDAT15 PINMUX_PIN(PIN_PC21, 1, 2) #define PIN_PC21__GTXER PINMUX_PIN(PIN_PC21, 2, 1) #define PIN_PC21__ISC_PCK PINMUX_PIN(PIN_PC21, 3, 1) #define PIN_PC21__FLEXCOM3_IO3 PINMUX_PIN(PIN_PC21, 5, 2) #define PIN_PC21__A10 PINMUX_PIN(PIN_PC21, 6, 2) #define PIN_PC22 86 #define PIN_PC22__GPIO PINMUX_PIN(PIN_PC22, 0, 0) #define PIN_PC22__LCDDAT18 PINMUX_PIN(PIN_PC22, 1, 2) #define PIN_PC22__GCRS PINMUX_PIN(PIN_PC22, 2, 1) #define PIN_PC22__ISC_VSYNC PINMUX_PIN(PIN_PC22, 3, 1) #define PIN_PC22__FLEXCOM3_IO4 PINMUX_PIN(PIN_PC22, 5, 2) #define PIN_PC22__A11 PINMUX_PIN(PIN_PC22, 6, 2) #define PIN_PC23 87 #define PIN_PC23__GPIO PINMUX_PIN(PIN_PC23, 0, 0) #define PIN_PC23__LCDDAT19 PINMUX_PIN(PIN_PC23, 1, 2) #define PIN_PC23__GCOL PINMUX_PIN(PIN_PC23, 2, 1) #define PIN_PC23__ISC_HSYNC PINMUX_PIN(PIN_PC23, 3, 1) #define PIN_PC23__A12 PINMUX_PIN(PIN_PC23, 6, 2) #define PIN_PC24 88 #define PIN_PC24__GPIO PINMUX_PIN(PIN_PC24, 0, 0) #define PIN_PC24__LCDDAT20 PINMUX_PIN(PIN_PC24, 1, 2) #define PIN_PC24__GRX2 PINMUX_PIN(PIN_PC24, 2, 1) #define PIN_PC24__ISC_MCK PINMUX_PIN(PIN_PC24, 3, 1) #define PIN_PC24__A13 PINMUX_PIN(PIN_PC24, 6, 2) #define PIN_PC25 89 #define PIN_PC25__GPIO PINMUX_PIN(PIN_PC25, 0, 0) #define PIN_PC25__LCDDAT21 PINMUX_PIN(PIN_PC25, 1, 2) #define PIN_PC25__GRX3 PINMUX_PIN(PIN_PC25, 2, 1) #define PIN_PC25__ISC_FIELD PINMUX_PIN(PIN_PC25, 3, 1) #define PIN_PC25__A14 PINMUX_PIN(PIN_PC25, 6, 2) #define PIN_PC26 90 #define PIN_PC26__GPIO PINMUX_PIN(PIN_PC26, 0, 0) #define PIN_PC26__LCDDAT22 PINMUX_PIN(PIN_PC26, 1, 2) #define PIN_PC26__GTX2 PINMUX_PIN(PIN_PC26, 2, 1) #define PIN_PC26__CANTX1 PINMUX_PIN(PIN_PC26, 4, 1) #define PIN_PC26__A15 PINMUX_PIN(PIN_PC26, 6, 2) #define PIN_PC27 91 #define PIN_PC27__GPIO PINMUX_PIN(PIN_PC27, 0, 0) #define PIN_PC27__LCDDAT23 PINMUX_PIN(PIN_PC27, 1, 2) #define PIN_PC27__GTX3 PINMUX_PIN(PIN_PC27, 2, 1) #define PIN_PC27__PCK1 PINMUX_PIN(PIN_PC27, 3, 2) #define PIN_PC27__CANRX1 PINMUX_PIN(PIN_PC27, 4, 1) #define PIN_PC27__TWD0 PINMUX_PIN(PIN_PC27, 5, 2) #define PIN_PC27__A16 PINMUX_PIN(PIN_PC27, 6, 2) #define PIN_PC28 92 #define PIN_PC28__GPIO PINMUX_PIN(PIN_PC28, 0, 0) #define PIN_PC28__LCDPWM PINMUX_PIN(PIN_PC28, 1, 2) #define PIN_PC28__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC28, 2, 1) #define PIN_PC28__PCK2 PINMUX_PIN(PIN_PC28, 3, 2) #define PIN_PC28__TWCK0 PINMUX_PIN(PIN_PC28, 5, 2) #define PIN_PC28__A17 PINMUX_PIN(PIN_PC28, 6, 2) #define PIN_PC29 93 #define PIN_PC29__GPIO PINMUX_PIN(PIN_PC29, 0, 0) #define PIN_PC29__LCDDISP PINMUX_PIN(PIN_PC29, 1, 2) #define PIN_PC29__FLEXCOM4_IO1 PINMUX_PIN(PIN_PC29, 2, 1) #define PIN_PC29__A18 PINMUX_PIN(PIN_PC29, 6, 2) #define PIN_PC30 94 #define PIN_PC30__GPIO PINMUX_PIN(PIN_PC30, 0, 0) #define PIN_PC30__LCDVSYNC PINMUX_PIN(PIN_PC30, 1, 2) #define PIN_PC30__FLEXCOM4_IO2 PINMUX_PIN(PIN_PC30, 2, 1) #define PIN_PC30__A19 PINMUX_PIN(PIN_PC30, 6, 2) #define PIN_PC31 95 #define PIN_PC31__GPIO PINMUX_PIN(PIN_PC31, 0, 0) #define PIN_PC31__LCDHSYNC PINMUX_PIN(PIN_PC31, 1, 2) #define PIN_PC31__FLEXCOM4_IO3 PINMUX_PIN(PIN_PC31, 2, 1) #define PIN_PC31__URXD3 PINMUX_PIN(PIN_PC31, 3, 2) #define PIN_PC31__A20 PINMUX_PIN(PIN_PC31, 6, 2) #define PIN_PD0 96 #define PIN_PD0__GPIO PINMUX_PIN(PIN_PD0, 0, 0) #define PIN_PD0__LCDPCK PINMUX_PIN(PIN_PD0, 1, 2) #define PIN_PD0__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD0, 2, 1) #define PIN_PD0__UTXD3 PINMUX_PIN(PIN_PD0, 3, 2) #define PIN_PD0__GTSUCOMP PINMUX_PIN(PIN_PD0, 4, 2) #define PIN_PD0__A23 PINMUX_PIN(PIN_PD0, 6, 2) #define PIN_PD1 97 #define PIN_PD1__GPIO PINMUX_PIN(PIN_PD1, 0, 0) #define PIN_PD1__LCDDEN PINMUX_PIN(PIN_PD1, 1, 2) #define PIN_PD1__GRXCK PINMUX_PIN(PIN_PD1, 4, 2) #define PIN_PD1__A24 PINMUX_PIN(PIN_PD1, 6, 2) #define PIN_PD2 98 #define PIN_PD2__GPIO PINMUX_PIN(PIN_PD2, 0, 0) #define PIN_PD2__URXD1 PINMUX_PIN(PIN_PD2, 1, 1) #define PIN_PD2__GTXER PINMUX_PIN(PIN_PD2, 4, 2) #define PIN_PD2__ISC_MCK PINMUX_PIN(PIN_PD2, 5, 2) #define PIN_PD2__A25 PINMUX_PIN(PIN_PD2, 6, 2) #define PIN_PD3 99 #define PIN_PD3__GPIO PINMUX_PIN(PIN_PD3, 0, 0) #define PIN_PD3__UTXD1 PINMUX_PIN(PIN_PD3, 1, 1) #define PIN_PD3__FIQ PINMUX_PIN(PIN_PD3, 2, 2) #define PIN_PD3__GCRS PINMUX_PIN(PIN_PD3, 4, 2) #define PIN_PD3__ISC_D11 PINMUX_PIN(PIN_PD3, 5, 2) #define PIN_PD3__NWAIT PINMUX_PIN(PIN_PD3, 6, 2) #define PIN_PD4 100 #define PIN_PD4__GPIO PINMUX_PIN(PIN_PD4, 0, 0) #define PIN_PD4__TWD1 PINMUX_PIN(PIN_PD4, 1, 2) #define PIN_PD4__URXD2 PINMUX_PIN(PIN_PD4, 2, 1) #define PIN_PD4__GCOL PINMUX_PIN(PIN_PD4, 4, 2) #define PIN_PD4__ISC_D10 PINMUX_PIN(PIN_PD4, 5, 2) #define PIN_PD4__NCS0 PINMUX_PIN(PIN_PD4, 6, 2) #define PIN_PD5 101 #define PIN_PD5__GPIO PINMUX_PIN(PIN_PD5, 0, 0) #define PIN_PD5__TWCK1 PINMUX_PIN(PIN_PD5, 1, 2) #define PIN_PD5__UTXD2 PINMUX_PIN(PIN_PD5, 2, 1) #define PIN_PD5__GRX2 PINMUX_PIN(PIN_PD5, 4, 2) #define PIN_PD5__ISC_D9 PINMUX_PIN(PIN_PD5, 5, 2) #define PIN_PD5__NCS1 PINMUX_PIN(PIN_PD5, 6, 2) #define PIN_PD6 102 #define PIN_PD6__GPIO PINMUX_PIN(PIN_PD6, 0, 0) #define PIN_PD6__TCK PINMUX_PIN(PIN_PD6, 1, 2) #define PIN_PD6__PCK1 PINMUX_PIN(PIN_PD6, 2, 1) #define PIN_PD6__GRX3 PINMUX_PIN(PIN_PD6, 4, 2) #define PIN_PD6__ISC_D8 PINMUX_PIN(PIN_PD6, 5, 2) #define PIN_PD6__NCS2 PINMUX_PIN(PIN_PD6, 6, 2) #define PIN_PD7 103 #define PIN_PD7__GPIO PINMUX_PIN(PIN_PD7, 0, 0) #define PIN_PD7__TDI PINMUX_PIN(PIN_PD7, 1, 2) #define PIN_PD7__UTMI_RXVAL PINMUX_PIN(PIN_PD7, 3, 1) #define PIN_PD7__GTX2 PINMUX_PIN(PIN_PD7, 4, 2) #define PIN_PD7__ISC_D0 PINMUX_PIN(PIN_PD7, 5, 2) #define PIN_PD7__NWR1_NBS1 PINMUX_PIN(PIN_PD7, 6, 2) #define PIN_PD8 104 #define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0) #define PIN_PD8__TDO PINMUX_PIN(PIN_PD8, 1, 2) #define PIN_PD8__UTMI_RXERR PINMUX_PIN(PIN_PD8, 3, 1) #define PIN_PD8__GTX3 PINMUX_PIN(PIN_PD8, 4, 2) #define PIN_PD8__ISC_D1 PINMUX_PIN(PIN_PD8, 5, 2) #define PIN_PD8__NANDRDY PINMUX_PIN(PIN_PD8, 6, 2) #define PIN_PD9 105 #define PIN_PD9__GPIO PINMUX_PIN(PIN_PD9, 0, 0) #define PIN_PD9__TMS PINMUX_PIN(PIN_PD9, 1, 2) #define PIN_PD9__UTMI_RXACT PINMUX_PIN(PIN_PD9, 3, 1) #define PIN_PD9__GTXCK PINMUX_PIN(PIN_PD9, 4, 2) #define PIN_PD9__ISC_D2 PINMUX_PIN(PIN_PD9, 5, 2) #define PIN_PD10 106 #define PIN_PD10__GPIO PINMUX_PIN(PIN_PD10, 0, 0) #define PIN_PD10__NTRST PINMUX_PIN(PIN_PD10, 1, 2) #define PIN_PD10__UTMI_HDIS PINMUX_PIN(PIN_PD10, 3, 1) #define PIN_PD10__GTXEN PINMUX_PIN(PIN_PD10, 4, 2) #define PIN_PD10__ISC_D3 PINMUX_PIN(PIN_PD10, 5, 2) #define PIN_PD11 107 #define PIN_PD11__GPIO PINMUX_PIN(PIN_PD11, 0, 0) #define PIN_PD11__TIOA1 PINMUX_PIN(PIN_PD11, 1, 3) #define PIN_PD11__PCK2 PINMUX_PIN(PIN_PD11, 2, 2) #define PIN_PD11__UTMI_LS0 PINMUX_PIN(PIN_PD11, 3, 1) #define PIN_PD11__GRXDV PINMUX_PIN(PIN_PD11, 4, 2) #define PIN_PD11__ISC_D4 PINMUX_PIN(PIN_PD11, 5, 2) #define PIN_PD11__ISC_MCK PINMUX_PIN(PIN_PD11, 7, 4) #define PIN_PD12 108 #define PIN_PD12__GPIO PINMUX_PIN(PIN_PD12, 0, 0) #define PIN_PD12__TIOB1 PINMUX_PIN(PIN_PD12, 1, 3) #define PIN_PD12__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD12, 2, 2) #define PIN_PD12__UTMI_LS1 PINMUX_PIN(PIN_PD12, 3, 1) #define PIN_PD12__GRXER PINMUX_PIN(PIN_PD12, 4, 2) #define PIN_PD12__ISC_D5 PINMUX_PIN(PIN_PD12, 5, 2) #define PIN_PD12__ISC_D4 PINMUX_PIN(PIN_PD12, 6, 4) #define PIN_PD13 109 #define PIN_PD13__GPIO PINMUX_PIN(PIN_PD13, 0, 0) #define PIN_PD13__TCLK1 PINMUX_PIN(PIN_PD13, 1, 3) #define PIN_PD13__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD13, 2, 2) #define PIN_PD13__UTMI_CDRPCSEL0 PINMUX_PIN(PIN_PD13, 3, 1) #define PIN_PD13__GRX0 PINMUX_PIN(PIN_PD13, 4, 2) #define PIN_PD13__ISC_D6 PINMUX_PIN(PIN_PD13, 5, 2) #define PIN_PD13__ISC_D5 PINMUX_PIN(PIN_PD13, 6, 4) #define PIN_PD14 110 #define PIN_PD14__GPIO PINMUX_PIN(PIN_PD14, 0, 0) #define PIN_PD14__TCK PINMUX_PIN(PIN_PD14, 1, 1) #define PIN_PD14__FLEXCOM4_IO2 PINMUX_PIN(PIN_PD14, 2, 2) #define PIN_PD14__UTMI_CDRPCSEL1 PINMUX_PIN(PIN_PD14, 3, 1) #define PIN_PD14__GRX1 PINMUX_PIN(PIN_PD14, 4, 2) #define PIN_PD14__ISC_D7 PINMUX_PIN(PIN_PD14, 5, 2) #define PIN_PD14__ISC_D6 PINMUX_PIN(PIN_PD14, 6, 4) #define PIN_PD15 111 #define PIN_PD15__GPIO PINMUX_PIN(PIN_PD15, 0, 0) #define PIN_PD15__TDI PINMUX_PIN(PIN_PD15, 1, 1) #define PIN_PD15__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD15, 2, 2) #define PIN_PD15__UTMI_CDRCPDIVEN PINMUX_PIN(PIN_PD15, 3, 1) #define PIN_PD15__GTX0 PINMUX_PIN(PIN_PD15, 4, 2) #define PIN_PD15__ISC_PCK PINMUX_PIN(PIN_PD15, 5, 2) #define PIN_PD15__ISC_D7 PINMUX_PIN(PIN_PD15, 6, 4) #define PIN_PD16 112 #define PIN_PD16__GPIO PINMUX_PIN(PIN_PD16, 0, 0) #define PIN_PD16__TDO PINMUX_PIN(PIN_PD16, 1, 1) #define PIN_PD16__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD16, 2, 2) #define PIN_PD16__UTMI_CDRBISTEN PINMUX_PIN(PIN_PD16, 3, 1) #define PIN_PD16__GTX1 PINMUX_PIN(PIN_PD16, 4, 2) #define PIN_PD16__ISC_VSYNC PINMUX_PIN(PIN_PD16, 5, 2) #define PIN_PD16__ISC_D8 PINMUX_PIN(PIN_PD16, 6, 4) #define PIN_PD17 113 #define PIN_PD17__GPIO PINMUX_PIN(PIN_PD17, 0, 0) #define PIN_PD17__TMS PINMUX_PIN(PIN_PD17, 1, 1) #define PIN_PD17__UTMI_CDRCPSELDIV PINMUX_PIN(PIN_PD17, 3, 1) #define PIN_PD17__GMDC PINMUX_PIN(PIN_PD17, 4, 2) #define PIN_PD17__ISC_HSYNC PINMUX_PIN(PIN_PD17, 5, 2) #define PIN_PD17__ISC_D9 PINMUX_PIN(PIN_PD17, 6, 4) #define PIN_PD18 114 #define PIN_PD18__GPIO PINMUX_PIN(PIN_PD18, 0, 0) #define PIN_PD18__NTRST PINMUX_PIN(PIN_PD18, 1, 1) #define PIN_PD18__GMDIO PINMUX_PIN(PIN_PD18, 4, 2) #define PIN_PD18__ISC_FIELD PINMUX_PIN(PIN_PD18, 5, 2) #define PIN_PD18__ISC_D10 PINMUX_PIN(PIN_PD18, 6, 4) #define PIN_PD19 115 #define PIN_PD19__GPIO PINMUX_PIN(PIN_PD19, 0, 0) #define PIN_PD19__PCK0 PINMUX_PIN(PIN_PD19, 1, 1) #define PIN_PD19__TWD1 PINMUX_PIN(PIN_PD19, 2, 3) #define PIN_PD19__URXD2 PINMUX_PIN(PIN_PD19, 3, 3) #define PIN_PD19__I2SC0_CK PINMUX_PIN(PIN_PD19, 5, 2) #define PIN_PD19__ISC_D11 PINMUX_PIN(PIN_PD19, 6, 4) #define PIN_PD20 116 #define PIN_PD20__GPIO PINMUX_PIN(PIN_PD20, 0, 0) #define PIN_PD20__TIOA2 PINMUX_PIN(PIN_PD20, 1, 3) #define PIN_PD20__TWCK1 PINMUX_PIN(PIN_PD20, 2, 3) #define PIN_PD20__UTXD2 PINMUX_PIN(PIN_PD20, 3, 3) #define PIN_PD20__I2SC0_MCK PINMUX_PIN(PIN_PD20, 5, 2) #define PIN_PD20__ISC_PCK PINMUX_PIN(PIN_PD20, 6, 4) #define PIN_PD21 117 #define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0) #define PIN_PD21__TIOB2 PINMUX_PIN(PIN_PD21, 1, 3) #define PIN_PD21__TWD0 PINMUX_PIN(PIN_PD21, 2, 4) #define PIN_PD21__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD21, 3, 3) #define PIN_PD21__I2SC0_WS PINMUX_PIN(PIN_PD21, 5, 2) #define PIN_PD21__ISC_VSYNC PINMUX_PIN(PIN_PD21, 6, 4) #define PIN_PD22 118 #define PIN_PD22__GPIO PINMUX_PIN(PIN_PD22, 0, 0) #define PIN_PD22__TCLK2 PINMUX_PIN(PIN_PD22, 1, 3) #define PIN_PD22__TWCK0 PINMUX_PIN(PIN_PD22, 2, 4) #define PIN_PD22__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD22, 3, 3) #define PIN_PD22__I2SC0_DI0 PINMUX_PIN(PIN_PD22, 5, 2) #define PIN_PD22__ISC_HSYNC PINMUX_PIN(PIN_PD22, 6, 4) #define PIN_PD23 119 #define PIN_PD23__GPIO PINMUX_PIN(PIN_PD23, 0, 0) #define PIN_PD23__URXD2 PINMUX_PIN(PIN_PD23, 1, 2) #define PIN_PD23__FLEXCOM4_IO2 PINMUX_PIN(PIN_PD23, 3, 3) #define PIN_PD23__I2SC0_DO0 PINMUX_PIN(PIN_PD23, 5, 2) #define PIN_PD23__ISC_FIELD PINMUX_PIN(PIN_PD23, 6, 4) #define PIN_PD24 120 #define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) #define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD24, 1, 2) #define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD24, 3, 3) #define PIN_PD25 121 #define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) #define PIN_PD25__SPI1_SPCK PINMUX_PIN(PIN_PD25, 1, 3) #define PIN_PD25__FLEXCOM4_IO4 PINMUX_PIN(PIN_PD25, 3, 3) #define PIN_PD26 122 #define PIN_PD26__GPIO PINMUX_PIN(PIN_PD26, 0, 0) #define PIN_PD26__SPI1_MOSI PINMUX_PIN(PIN_PD26, 1, 3) #define PIN_PD26__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD26, 3, 2) #define PIN_PD27 123 #define PIN_PD27__GPIO PINMUX_PIN(PIN_PD27, 0, 0) #define PIN_PD27__SPI1_MISO PINMUX_PIN(PIN_PD27, 1, 3) #define PIN_PD27__TCK PINMUX_PIN(PIN_PD27, 2, 3) #define PIN_PD27__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD27, 3, 2) #define PIN_PD28 124 #define PIN_PD28__GPIO PINMUX_PIN(PIN_PD28, 0, 0) #define PIN_PD28__SPI1_NPCS0 PINMUX_PIN(PIN_PD28, 1, 3) #define PIN_PD28__TCI PINMUX_PIN(PIN_PD28, 2, 3) #define PIN_PD28__FLEXCOM2_IO2 PINMUX_PIN(PIN_PD28, 3, 2) #define PIN_PD29 125 #define PIN_PD29__GPIO PINMUX_PIN(PIN_PD29, 0, 0) #define PIN_PD29__SPI1_NPCS1 PINMUX_PIN(PIN_PD29, 1, 3) #define PIN_PD29__TDO PINMUX_PIN(PIN_PD29, 2, 3) #define PIN_PD29__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD29, 3, 2) #define PIN_PD29__TIOA3 PINMUX_PIN(PIN_PD29, 4, 3) #define PIN_PD29__TWD0 PINMUX_PIN(PIN_PD29, 5, 3) #define PIN_PD30 126 #define PIN_PD30__GPIO PINMUX_PIN(PIN_PD30, 0, 0) #define PIN_PD30__SPI1_NPCS2 PINMUX_PIN(PIN_PD30, 1, 3) #define PIN_PD30__TMS PINMUX_PIN(PIN_PD30, 2, 3) #define PIN_PD30__FLEXCOM2_IO4 PINMUX_PIN(PIN_PD30, 3, 2) #define PIN_PD30__TIOB3 PINMUX_PIN(PIN_PD30, 4, 3) #define PIN_PD30__TWCK0 PINMUX_PIN(PIN_PD30, 5, 3) #define PIN_PD31 127 #define PIN_PD31__GPIO PINMUX_PIN(PIN_PD31, 0, 0) #define PIN_PD31__ADTRG PINMUX_PIN(PIN_PD31, 1, 1) #define PIN_PD31__NTRST PINMUX_PIN(PIN_PD31, 2, 3) #define PIN_PD31__IRQ PINMUX_PIN(PIN_PD31, 3, 4) #define PIN_PD31__TCLK3 PINMUX_PIN(PIN_PD31, 4, 3) #define PIN_PD31__PCK0 PINMUX_PIN(PIN_PD31, 5, 2) optee_os-4.3.0/core/arch/arm/dts/sama5d2.dtsi000066400000000000000000001035641464416617300207170ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * sama5d2.dtsi - Device Tree Include file for SAMA5D2 family SoC * * Copyright (C) 2015 Atmel, * 2015 Ludovic Desroches */ #include #include #include #include / { #address-cells = <1>; #size-cells = <1>; model = "Atmel SAMA5D2 family SoC"; compatible = "atmel,sama5d2"; interrupt-parent = <&aic>; aliases { serial0 = &uart1; serial1 = &uart3; }; cpus { #address-cells = <1>; #size-cells = <0>; cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a5"; reg = <0>; next-level-cache = <&L2>; clocks = <&pmc PMC_TYPE_CORE PMC_MCK_PRES>; clock-names = "cpu"; }; }; pmu { compatible = "arm,cortex-a5-pmu"; interrupts = <2 IRQ_TYPE_LEVEL_HIGH 0>; }; etb@740000 { compatible = "arm,coresight-etb10", "arm,primecell"; reg = <0x740000 0x1000>; clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; clock-names = "apb_pclk"; in-ports { port { etb_in: endpoint { remote-endpoint = <&etm_out>; }; }; }; }; etm@73c000 { compatible = "arm,coresight-etm3x", "arm,primecell"; reg = <0x73c000 0x1000>; clocks = <&pmc PMC_TYPE_CORE PMC_MCK>; clock-names = "apb_pclk"; out-ports { port { etm_out: endpoint { remote-endpoint = <&etb_in>; }; }; }; }; memory@20000000 { device_type = "memory"; reg = <0x20000000 0x20000000>; }; clocks { slow_xtal: slow_xtal { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; }; main_xtal: main_xtal { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <0>; }; }; ns_sram: sram@200000 { compatible = "atmel,sama5d2-sram", "mmio-sram"; reg = <0x00200000 0x20000>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x00200000 0x20000>; status = "disabled"; secure-status = "okay"; }; ahb { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; nfc_sram: sram@100000 { compatible = "mmio-sram"; no-memory-wc; reg = <0x00100000 0x2400>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x00100000 0x2400>; }; usb0: gadget@300000 { compatible = "atmel,sama5d3-udc"; reg = <0x00300000 0x100000 0xfc02c000 0x400>; interrupts = <42 IRQ_TYPE_LEVEL_HIGH 2>; clocks = <&pmc PMC_TYPE_PERIPHERAL 42>, <&pmc PMC_TYPE_CORE PMC_UTMI>; clock-names = "pclk", "hclk"; assigned-clocks = <&pmc PMC_TYPE_CORE PMC_USBCK>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <48000000>; status = "disabled"; }; usb1: ohci@400000 { compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00400000 0x100000>; interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; clocks = <&pmc PMC_TYPE_PERIPHERAL 41>, <&pmc PMC_TYPE_PERIPHERAL 41>, <&pmc PMC_TYPE_SYSTEM 6>; clock-names = "ohci_clk", "hclk", "uhpck"; assigned-clocks = <&pmc PMC_TYPE_CORE PMC_USBCK>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <48000000>; status = "disabled"; }; usb2: ehci@500000 { compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; reg = <0x00500000 0x100000>; interrupts = <41 IRQ_TYPE_LEVEL_HIGH 2>; clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>, <&pmc PMC_TYPE_PERIPHERAL 41>; clock-names = "usb_clk", "ehci_clk"; assigned-clocks = <&pmc PMC_TYPE_CORE PMC_USBCK>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <48000000>; status = "disabled"; }; L2: cache-controller@a00000 { compatible = "arm,pl310-cache"; reg = <0x00a00000 0x1000>; interrupts = <63 IRQ_TYPE_LEVEL_HIGH 4>; cache-unified; cache-level = <2>; }; ebi: ebi@10000000 { compatible = "atmel,sama5d3-ebi"; #address-cells = <2>; #size-cells = <1>; atmel,smc = <&hsmc>; reg = <0x10000000 0x10000000 0x60000000 0x30000000>; ranges = <0x0 0x0 0x10000000 0x10000000 0x1 0x0 0x60000000 0x10000000 0x2 0x0 0x70000000 0x10000000 0x3 0x0 0x80000000 0x10000000>; clocks = <&pmc PMC_TYPE_CORE PMC_MCK2>; status = "disabled"; nand_controller: nand-controller { compatible = "atmel,sama5d3-nand-controller"; atmel,nfc-sram = <&nfc_sram>; atmel,nfc-io = <&nfc_io>; ecc-engine = <&pmecc>; #address-cells = <2>; #size-cells = <1>; ranges; status = "disabled"; }; }; sdmmc0: sdio-host@a0000000 { compatible = "atmel,sama5d2-sdhci"; reg = <0xa0000000 0x300>; interrupts = <31 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 31>, <&pmc PMC_TYPE_GCK 31>, <&pmc PMC_TYPE_CORE PMC_MAIN>; clock-names = "hclock", "multclk", "baseclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 31>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <480000000>; status = "disabled"; }; sdmmc1: sdio-host@b0000000 { compatible = "atmel,sama5d2-sdhci"; reg = <0xb0000000 0x300>; interrupts = <32 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 32>, <&pmc PMC_TYPE_GCK 32>, <&pmc PMC_TYPE_CORE PMC_MAIN>; clock-names = "hclock", "multclk", "baseclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 32>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <480000000>; status = "disabled"; }; nfc_io: nfc-io@c0000000 { compatible = "atmel,sama5d3-nfc-io", "syscon"; reg = <0xc0000000 0x8000000>; }; apb { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; hlcdc: hlcdc@f0000000 { compatible = "atmel,sama5d2-hlcdc"; reg = <0xf0000000 0x2000>; interrupts = <45 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 45>, <&pmc PMC_TYPE_SYSTEM 3>, <&clk32k>; clock-names = "periph_clk","sys_clk", "slow_clk"; status = "disabled"; hlcdc-display-controller { compatible = "atmel,hlcdc-display-controller"; #address-cells = <1>; #size-cells = <0>; port@0 { #address-cells = <1>; #size-cells = <0>; reg = <0>; }; }; hlcdc_pwm: hlcdc-pwm { compatible = "atmel,hlcdc-pwm"; #pwm-cells = <3>; }; }; isc: isc@f0008000 { compatible = "atmel,sama5d2-isc"; reg = <0xf0008000 0x4000>; interrupts = <46 IRQ_TYPE_LEVEL_HIGH 5>; clocks = <&pmc PMC_TYPE_PERIPHERAL 46>, <&pmc PMC_TYPE_SYSTEM 18>, <&pmc PMC_TYPE_GCK 46>; clock-names = "hclock", "iscck", "gck"; #clock-cells = <0>; clock-output-names = "isc-mck"; status = "disabled"; }; ramc0: ramc@f000c000 { compatible = "atmel,sama5d3-ddramc"; reg = <0xf000c000 0x200>; clocks = <&pmc PMC_TYPE_SYSTEM 2>, <&pmc PMC_TYPE_PERIPHERAL 13>; clock-names = "ddrck", "mpddr"; }; dma0: dma-controller@f0010000 { compatible = "atmel,sama5d4-dma"; reg = <0xf0010000 0x1000>; interrupts = <6 IRQ_TYPE_LEVEL_HIGH 0>; #dma-cells = <1>; clocks = <&pmc PMC_TYPE_PERIPHERAL 6>; clock-names = "dma_clk"; }; /* Place dma1 here despite its address */ dma1: dma-controller@f0004000 { compatible = "atmel,sama5d4-dma"; reg = <0xf0004000 0x1000>; interrupts = <7 IRQ_TYPE_LEVEL_HIGH 0>; #dma-cells = <1>; clocks = <&pmc PMC_TYPE_PERIPHERAL 7>; clock-names = "dma_clk"; }; pmc: pmc@f0014000 { compatible = "atmel,sama5d2-pmc", "syscon"; reg = <0xf0014000 0x160>; interrupts = <74 IRQ_TYPE_LEVEL_HIGH 7>; #clock-cells = <2>; clocks = <&clk32k>, <&main_xtal>; clock-names = "slow_clk", "main_xtal"; status = "disabled"; secure-status = "okay"; }; qspi0: spi@f0020000 { compatible = "atmel,sama5d2-qspi"; reg = <0xf0020000 0x100>, <0xd0000000 0x08000000>; reg-names = "qspi_base", "qspi_mmap"; interrupts = <52 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 52>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; qspi1: spi@f0024000 { compatible = "atmel,sama5d2-qspi"; reg = <0xf0024000 0x100>, <0xd8000000 0x08000000>; reg-names = "qspi_base", "qspi_mmap"; interrupts = <53 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 53>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; sha@f0028000 { compatible = "atmel,at91sam9g46-sha"; reg = <0xf0028000 0x100>; interrupts = <12 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(30))>; dma-names = "tx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 12>; clock-names = "sha_clk"; status = "okay"; }; aes@f002c000 { compatible = "atmel,at91sam9g46-aes"; reg = <0xf002c000 0x100>; interrupts = <9 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(26))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(27))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 9>; clock-names = "aes_clk"; status = "okay"; }; spi0: spi@f8000000 { compatible = "atmel,at91rm9200-spi"; reg = <0xf8000000 0x100>; interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(6))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(7))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 33>; clock-names = "spi_clk"; atmel,fifo-size = <16>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; ssc0: ssc@f8004000 { compatible = "atmel,at91sam9g45-ssc"; reg = <0xf8004000 0x4000>; interrupts = <43 IRQ_TYPE_LEVEL_HIGH 4>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(21))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(22))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 43>; clock-names = "pclk"; status = "disabled"; }; macb0: ethernet@f8008000 { compatible = "atmel,sama5d2-gem"; reg = <0xf8008000 0x1000>; interrupts = <5 IRQ_TYPE_LEVEL_HIGH 3 /* Queue 0 */ 66 IRQ_TYPE_LEVEL_HIGH 3 /* Queue 1 */ 67 IRQ_TYPE_LEVEL_HIGH 3>; /* Queue 2 */ #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 5>, <&pmc PMC_TYPE_PERIPHERAL 5>; clock-names = "hclk", "pclk"; status = "disabled"; }; tcb0: timer@f800c000 { compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; #address-cells = <1>; #size-cells = <0>; reg = <0xf800c000 0x100>; interrupts = <35 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 35>, <&pmc PMC_TYPE_GCK 35>, <&clk32k>; clock-names = "t0_clk", "gclk", "slow_clk"; }; tcb1: timer@f8010000 { compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; #address-cells = <1>; #size-cells = <0>; reg = <0xf8010000 0x100>; interrupts = <36 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 36>, <&pmc PMC_TYPE_GCK 36>, <&clk32k>; clock-names = "t0_clk", "gclk", "slow_clk"; status = "disabled"; secure-status = "okay"; }; hsmc: hsmc@f8014000 { compatible = "atmel,sama5d2-smc", "syscon", "simple-mfd"; reg = <0xf8014000 0x1000>; interrupts = <17 IRQ_TYPE_LEVEL_HIGH 6>; clocks = <&pmc PMC_TYPE_PERIPHERAL 17>; #address-cells = <1>; #size-cells = <1>; ranges; pmecc: ecc-engine@f8014070 { compatible = "atmel,sama5d2-pmecc"; reg = <0xf8014070 0x490>, <0xf8014500 0x100>; }; }; pdmic: pdmic@f8018000 { compatible = "atmel,sama5d2-pdmic"; reg = <0xf8018000 0x124>; interrupts = <48 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(50))>; dma-names = "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 48>, <&pmc PMC_TYPE_GCK 48>; clock-names = "pclk", "gclk"; status = "disabled"; }; uart0: serial@f801c000 { compatible = "atmel,at91sam9260-usart"; reg = <0xf801c000 0x100>; interrupts = <24 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(35))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(36))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 24>; clock-names = "usart"; status = "disabled"; }; uart1: serial@f8020000 { compatible = "atmel,at91sam9260-usart"; reg = <0xf8020000 0x100>; interrupts = <25 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(37))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(38))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 25>; clock-names = "usart"; status = "disabled"; }; uart2: serial@f8024000 { compatible = "atmel,at91sam9260-usart"; reg = <0xf8024000 0x100>; interrupts = <26 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(39))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(40))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 26>; clock-names = "usart"; status = "disabled"; }; i2c0: i2c@f8028000 { compatible = "atmel,sama5d2-i2c"; reg = <0xf8028000 0x100>; interrupts = <29 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(0))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(1))>; dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 29>; atmel,fifo-size = <16>; status = "disabled"; }; pwm0: pwm@f802c000 { compatible = "atmel,sama5d2-pwm"; reg = <0xf802c000 0x4000>; interrupts = <38 IRQ_TYPE_LEVEL_HIGH 7>; #pwm-cells = <3>; clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; status = "disabled"; }; sfr: sfr@f8030000 { compatible = "atmel,sama5d2-sfr", "syscon"; reg = <0xf8030000 0x98>; status = "disabled"; secure-status = "okay"; }; flx0: flexcom@f8034000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xf8034000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xf8034000 0x800>; status = "disabled"; uart5: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; clock-names = "usart"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(11))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(12))>; dma-names = "tx", "rx"; atmel,fifo-size = <32>; status = "disabled"; }; spi2: spi@400 { compatible = "atmel,at91rm9200-spi"; reg = <0x400 0x200>; interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; clock-names = "spi_clk"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(11))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(12))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; i2c2: i2c@600 { compatible = "atmel,sama5d2-i2c"; reg = <0x600 0x200>; interrupts = <19 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(11))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(12))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; }; flx1: flexcom@f8038000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xf8038000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xf8038000 0x800>; status = "disabled"; uart6: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; clock-names = "usart"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(13))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(14))>; dma-names = "tx", "rx"; atmel,fifo-size = <32>; status = "disabled"; }; spi3: spi@400 { compatible = "atmel,at91rm9200-spi"; reg = <0x400 0x200>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; clock-names = "spi_clk"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(13))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(14))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; i2c3: i2c@600 { compatible = "atmel,sama5d2-i2c"; reg = <0x600 0x200>; interrupts = <20 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 20>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(13))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(14))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; }; securam: sram@f8044000 { compatible = "atmel,sama5d2-securam", "mmio-sram"; reg = <0xf8044000 0x1420>; clocks = <&pmc PMC_TYPE_PERIPHERAL 51>; #address-cells = <1>; #size-cells = <1>; no-memory-wc; ranges = <0 0xf8044000 0x1420>; status = "disabled"; secure-status = "okay"; }; reset_controller: rstc@f8048000 { compatible = "atmel,sama5d3-rstc"; reg = <0xf8048000 0x10>; clocks = <&clk32k>; status = "disabled"; secure-status = "okay"; }; shutdown_controller: shdwc@f8048010 { compatible = "atmel,sama5d2-shdwc"; reg = <0xf8048010 0x10>; clocks = <&clk32k>; #address-cells = <1>; #size-cells = <0>; atmel,wakeup-rtc-timer; status = "disabled"; secure-status = "okay"; }; pit: timer@f8048030 { compatible = "atmel,at91sam9260-pit"; reg = <0xf8048030 0x10>; interrupts = <3 IRQ_TYPE_LEVEL_HIGH 5>; clocks = <&pmc PMC_TYPE_CORE PMC_MCK2>; }; watchdog: watchdog@f8048040 { compatible = "atmel,sama5d4-wdt"; reg = <0xf8048040 0x10>; interrupts = <4 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&clk32k>; status = "disabled"; secure-status = "okay"; }; clk32k: sckc@f8048050 { compatible = "atmel,sama5d4-sckc"; reg = <0xf8048050 0x4>; clocks = <&slow_xtal>; #clock-cells = <0>; status = "disabled"; secure-status = "okay"; }; rtc: rtc@f80480b0 { compatible = "atmel,sama5d2-rtc"; reg = <0xf80480b0 0x30>; interrupts = <74 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&clk32k>; status = "disabled"; secure-status = "okay"; }; sfc: sfc@f804c000 { compatible = "atmel,sama5d2-sfc"; reg = <0xf804c000 0x64>; read-only; status = "disabled"; secure-status = "okay"; #address-cells = <1>; #size-cells = <1>; sfc_kr: cell@0 { reg = <0x0 0x4>; bits = <0 7>; }; sfc_dr0: cell@20 { reg = <0x20 0x4>; }; }; die_id: die_id { compatible = "optee,nvmem-die-id"; nvmem-cells = <&sfc_kr>; nvmem-cell-names = "die_id"; }; huk: huk { compatible = "optee,nvmem-huk"; nvmem-cells = <&sfc_dr0>; nvmem-cell-names = "hw_unique_key"; }; i2s0: i2s@f8050000 { compatible = "atmel,sama5d2-i2s"; reg = <0xf8050000 0x100>; interrupts = <54 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(31))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(32))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 54>, <&pmc PMC_TYPE_GCK 54>; clock-names = "pclk", "gclk"; assigned-clocks = <&pmc PMC_TYPE_CORE PMC_I2S0_MUX>; assigned-clock-parents = <&pmc PMC_TYPE_GCK 54>; status = "disabled"; }; can0: can@f8054000 { compatible = "bosch,m_can"; reg = <0xf8054000 0x4000>, <0x210000 0x1c00>; reg-names = "m_can", "message_ram"; interrupts = <56 IRQ_TYPE_LEVEL_HIGH 7>, <64 IRQ_TYPE_LEVEL_HIGH 7>; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 56>, <&pmc PMC_TYPE_GCK 56>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 56>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>; status = "disabled"; }; spi1: spi@fc000000 { compatible = "atmel,at91rm9200-spi"; reg = <0xfc000000 0x100>; interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(8))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(9))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 34>; clock-names = "spi_clk"; atmel,fifo-size = <16>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; uart3: serial@fc008000 { compatible = "atmel,at91sam9260-usart"; reg = <0xfc008000 0x100>; interrupts = <27 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma1 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(41))>, <&dma1 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(42))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 27>; clock-names = "usart"; status = "disabled"; }; uart4: serial@fc00c000 { compatible = "atmel,at91sam9260-usart"; reg = <0xfc00c000 0x100>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(43))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(44))>; dma-names = "tx", "rx"; interrupts = <28 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 28>; clock-names = "usart"; status = "disabled"; }; flx2: flexcom@fc010000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xfc010000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xfc010000 0x800>; status = "disabled"; uart7: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; clock-names = "usart"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(15))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(16))>; dma-names = "tx", "rx"; atmel,fifo-size = <32>; status = "disabled"; }; spi4: spi@400 { compatible = "atmel,at91rm9200-spi"; reg = <0x400 0x200>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; clock-names = "spi_clk"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(15))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(16))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; i2c4: i2c@600 { compatible = "atmel,sama5d2-i2c"; reg = <0x600 0x200>; interrupts = <21 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(15))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(16))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; }; flx3: flexcom@fc014000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xfc014000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xfc014000 0x800>; status = "disabled"; uart8: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; clock-names = "usart"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(17))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(18))>; dma-names = "tx", "rx"; atmel,fifo-size = <32>; status = "disabled"; }; spi5: spi@400 { compatible = "atmel,at91rm9200-spi"; reg = <0x400 0x200>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; clock-names = "spi_clk"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(17))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(18))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; i2c5: i2c@600 { compatible = "atmel,sama5d2-i2c"; reg = <0x600 0x200>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(17))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(18))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; }; flx4: flexcom@fc018000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xfc018000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xfc018000 0x800>; status = "disabled"; uart9: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; clock-names = "usart"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(19))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(20))>; dma-names = "tx", "rx"; atmel,fifo-size = <32>; status = "disabled"; }; spi6: spi@400 { compatible = "atmel,at91rm9200-spi"; reg = <0x400 0x200>; interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; clock-names = "spi_clk"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(19))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(20))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; i2c6: i2c@600 { compatible = "atmel,sama5d2-i2c"; reg = <0x600 0x200>; interrupts = <23 IRQ_TYPE_LEVEL_HIGH 7>; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(19))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(20))>; dma-names = "tx", "rx"; atmel,fifo-size = <16>; status = "disabled"; }; }; trng@fc01c000 { compatible = "atmel,at91sam9g45-trng"; reg = <0xfc01c000 0x100>; interrupts = <47 IRQ_TYPE_LEVEL_HIGH 0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; status = "disabled"; secure-status = "okay"; }; aic: interrupt-controller@fc020000 { #interrupt-cells = <3>; compatible = "atmel,sama5d2-aic"; interrupt-controller; reg = <0xfc020000 0x200>; atmel,external-irqs = <49>; }; saic: interrupt-controller@f803c000 { #interrupt-cells = <3>; compatible = "atmel,sama5d2-saic"; interrupt-controller; reg = <0xf803c000 0x200>; atmel,external-irqs = <49>; status = "disabled"; secure-status = "okay"; }; i2c1: i2c@fc028000 { compatible = "atmel,sama5d2-i2c"; reg = <0xfc028000 0x100>; interrupts = <30 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(2))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(3))>; dma-names = "tx", "rx"; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 30>; atmel,fifo-size = <16>; status = "disabled"; }; adc: adc@fc030000 { compatible = "atmel,sama5d2-adc"; reg = <0xfc030000 0x100>; interrupts = <40 IRQ_TYPE_LEVEL_HIGH 7>; clocks = <&pmc PMC_TYPE_PERIPHERAL 40>; clock-names = "adc_clk"; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(25))>; dma-names = "rx"; atmel,min-sample-rate-hz = <200000>; atmel,max-sample-rate-hz = <20000000>; atmel,startup-time-ms = <4>; atmel,trigger-edge-type = ; #io-channel-cells = <1>; status = "disabled"; }; resistive_touch: resistive-touch { compatible = "resistive-adc-touch"; io-channels = <&adc AT91_SAMA5D2_ADC_X_CHANNEL>, <&adc AT91_SAMA5D2_ADC_Y_CHANNEL>, <&adc AT91_SAMA5D2_ADC_P_CHANNEL>; io-channel-names = "x", "y", "pressure"; touchscreen-min-pressure = <50000>; status = "disabled"; }; pioA: pinctrl@fc039000 { compatible = "atmel,sama5d2-pinctrl"; reg = <0xfc039000 0x600>; interrupts = <18 IRQ_TYPE_LEVEL_HIGH 7>, <68 IRQ_TYPE_LEVEL_HIGH 7>, <69 IRQ_TYPE_LEVEL_HIGH 7>, <70 IRQ_TYPE_LEVEL_HIGH 7>; interrupt-controller; #interrupt-cells = <2>; gpio-controller; #gpio-cells = <2>; clocks = <&pmc PMC_TYPE_PERIPHERAL 18>; status = "disabled"; secure-status = "okay"; }; pioBU: secumod@fc040000 { compatible = "atmel,sama5d2-secumod", "syscon"; reg = <0xfc040000 0x100>; gpio-controller; #gpio-cells = <2>; status = "disabled"; secure-status = "okay"; }; tdes@fc044000 { compatible = "atmel,at91sam9g46-tdes"; reg = <0xfc044000 0x100>; interrupts = <11 IRQ_TYPE_LEVEL_HIGH 0>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(28))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(29))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; clock-names = "tdes_clk"; status = "okay"; }; classd: classd@fc048000 { compatible = "atmel,sama5d2-classd"; reg = <0xfc048000 0x100>; interrupts = <59 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(47))>; dma-names = "tx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 59>, <&pmc PMC_TYPE_GCK 59>; clock-names = "pclk", "gclk"; status = "disabled"; }; i2s1: i2s@fc04c000 { compatible = "atmel,sama5d2-i2s"; reg = <0xfc04c000 0x100>; interrupts = <55 IRQ_TYPE_LEVEL_HIGH 7>; dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(33))>, <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | AT91_XDMAC_DT_PERID(34))>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 55>, <&pmc PMC_TYPE_GCK 55>; clock-names = "pclk", "gclk"; assigned-clocks = <&pmc PMC_TYPE_CORE PMC_I2S1_MUX>; assigned-parrents = <&pmc PMC_TYPE_GCK 55>; status = "disabled"; }; can1: can@fc050000 { compatible = "bosch,m_can"; reg = <0xfc050000 0x4000>, <0x210000 0x3800>; reg-names = "m_can", "message_ram"; interrupts = <57 IRQ_TYPE_LEVEL_HIGH 7>, <65 IRQ_TYPE_LEVEL_HIGH 7>; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 57>, <&pmc PMC_TYPE_GCK 57>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 57>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x1c00 0 0 64 0 0 32 32>; status = "disabled"; }; sfrbu: sfr@fc05c000 { compatible = "atmel,sama5d2-sfrbu", "syscon"; reg = <0xfc05c000 0x20>; }; chipid@fc069000 { compatible = "atmel,sama5d2-chipid"; reg = <0xfc069000 0x8>; }; }; }; }; optee_os-4.3.0/core/arch/arm/dts/sama7g5-pinfunc.h000066400000000000000000001313351464416617300216500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries */ #define PINMUX_PIN(no, func, ioset) \ (((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20)) #define PIN_PA0 0 #define PIN_PA0__GPIO PINMUX_PIN(PIN_PA0, 0, 0) #define PIN_PA0__SDMMC0_CK PINMUX_PIN(PIN_PA0, 1, 1) #define PIN_PA0__FLEXCOM0_IO0 PINMUX_PIN(PIN_PA0, 2, 1) #define PIN_PA0__CANTX3 PINMUX_PIN(PIN_PA0, 3, 1) #define PIN_PA0__PWML0 PINMUX_PIN(PIN_PA0, 5, 2) #define PIN_PA1 1 #define PIN_PA1__GPIO PINMUX_PIN(PIN_PA1, 0, 0) #define PIN_PA1__SDMMC0_CMD PINMUX_PIN(PIN_PA1, 1, 1) #define PIN_PA1__FLEXCOM0_IO1 PINMUX_PIN(PIN_PA1, 2, 1) #define PIN_PA1__CANRX3 PINMUX_PIN(PIN_PA1, 3, 1) #define PIN_PA1__D14 PINMUX_PIN(PIN_PA1, 4, 1) #define PIN_PA1__PWMH0 PINMUX_PIN(PIN_PA1, 5, 3) #define PIN_PA2 2 #define PIN_PA2__GPIO PINMUX_PIN(PIN_PA2, 0, 0) #define PIN_PA2__SDMMC0_RSTN PINMUX_PIN(PIN_PA2, 1, 1) #define PIN_PA2__FLEXCOM0_IO2 PINMUX_PIN(PIN_PA2, 2, 1) #define PIN_PA2__PDMC1_CLK PINMUX_PIN(PIN_PA2, 3, 1) #define PIN_PA2__D15 PINMUX_PIN(PIN_PA2, 4, 1) #define PIN_PA2__PWMH1 PINMUX_PIN(PIN_PA2, 5, 3) #define PIN_PA2__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA2, 6, 3) #define PIN_PA3 3 #define PIN_PA3__GPIO PINMUX_PIN(PIN_PA3, 0, 0) #define PIN_PA3__SDMMC0_DAT0 PINMUX_PIN(PIN_PA3, 1, 1) #define PIN_PA3__FLEXCOM0_IO3 PINMUX_PIN(PIN_PA3, 2, 1) #define PIN_PA3__PDMC1_DS0 PINMUX_PIN(PIN_PA3, 3, 1) #define PIN_PA3__NWR1_NBS1 PINMUX_PIN(PIN_PA3, 4, 1) #define PIN_PA3__PWML3 PINMUX_PIN(PIN_PA3, 5, 3) #define PIN_PA3__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA3, 6, 3) #define PIN_PA4 4 #define PIN_PA4__GPIO PINMUX_PIN(PIN_PA4, 0, 0) #define PIN_PA4__SDMMC0_DAT1 PINMUX_PIN(PIN_PA4, 1, 1) #define PIN_PA4__FLEXCOM0_IO4 PINMUX_PIN(PIN_PA4, 2, 1) #define PIN_PA4__PDMC1_DS1 PINMUX_PIN(PIN_PA4, 3, 1) #define PIN_PA4__NCS2 PINMUX_PIN(PIN_PA4, 4, 1) #define PIN_PA4__PWMH3 PINMUX_PIN(PIN_PA4, 5, 3) #define PIN_PA4__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA4, 6, 3) #define PIN_PA5 5 #define PIN_PA5__GPIO PINMUX_PIN(PIN_PA5, 0, 0) #define PIN_PA5__SDMMC0_DAT2 PINMUX_PIN(PIN_PA5, 1, 1) #define PIN_PA5__FLEXCOM1_IO0 PINMUX_PIN(PIN_PA5, 2, 1) #define PIN_PA5__CANTX2 PINMUX_PIN(PIN_PA5, 3, 1) #define PIN_PA5__A23 PINMUX_PIN(PIN_PA5, 4, 1) #define PIN_PA5__PWMEXTRG0 PINMUX_PIN(PIN_PA5, 5, 3) #define PIN_PA5__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA5, 6, 3) #define PIN_PA6 6 #define PIN_PA6__GPIO PINMUX_PIN(PIN_PA6, 0, 0) #define PIN_PA6__SDMMC0_DAT3 PINMUX_PIN(PIN_PA6, 1, 1) #define PIN_PA6__FLEXCOM1_IO1 PINMUX_PIN(PIN_PA6, 2, 1) #define PIN_PA6__CANRX2 PINMUX_PIN(PIN_PA6, 3, 1) #define PIN_PA6__A24 PINMUX_PIN(PIN_PA6, 4, 1) #define PIN_PA6__PWMEXTRG1 PINMUX_PIN(PIN_PA6, 5, 3) #define PIN_PA6__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA6, 6, 3) #define PIN_PA7 7 #define PIN_PA7__GPIO PINMUX_PIN(PIN_PA7, 0, 0) #define PIN_PA7__SDMMC0_DAT4 PINMUX_PIN(PIN_PA7, 1, 1) #define PIN_PA7__FLEXCOM2_IO0 PINMUX_PIN(PIN_PA7, 2, 1) #define PIN_PA7__CANTX1 PINMUX_PIN(PIN_PA7, 3, 1) #define PIN_PA7__NWAIT PINMUX_PIN(PIN_PA7, 4, 1) #define PIN_PA7__PWMFI0 PINMUX_PIN(PIN_PA7, 5, 3) #define PIN_PA7__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA7, 6, 3) #define PIN_PA8 8 #define PIN_PA8__GPIO PINMUX_PIN(PIN_PA8, 0, 0) #define PIN_PA8__SDMMC0_DAT5 PINMUX_PIN(PIN_PA8, 1, 1) #define PIN_PA8__FLEXCOM2_IO1 PINMUX_PIN(PIN_PA8, 2, 1) #define PIN_PA8__CANRX1 PINMUX_PIN(PIN_PA8, 3, 1) #define PIN_PA8__NCS0 PINMUX_PIN(PIN_PA8, 4, 1) #define PIN_PA8__PWMIF1 PINMUX_PIN(PIN_PA8, 5, 3) #define PIN_PA8__FLEXCOM4_IO0 PINMUX_PIN(PIN_PA8, 6, 3) #define PIN_PA9 9 #define PIN_PA9__GPIO PINMUX_PIN(PIN_PA9, 0, 0) #define PIN_PA9__SDMMC0_DAT6 PINMUX_PIN(PIN_PA9, 1, 1) #define PIN_PA9__FLEXCOM2_IO2 PINMUX_PIN(PIN_PA9, 2, 1) #define PIN_PA9__CANTX0 PINMUX_PIN(PIN_PA9, 3, 1) #define PIN_PA9__SMCK PINMUX_PIN(PIN_PA9, 4, 1) #define PIN_PA9__SPDIF_RX PINMUX_PIN(PIN_PA9, 5, 1) #define PIN_PA9__FLEXCOM4_IO1 PINMUX_PIN(PIN_PA9, 6, 3) #define PIN_PA10 10 #define PIN_PA10__GPIO PINMUX_PIN(PIN_PA10, 0, 0) #define PIN_PA10__SDMMC0_DAT7 PINMUX_PIN(PIN_PA10, 1, 1) #define PIN_PA10__FLEXCOM2_IO3 PINMUX_PIN(PIN_PA10, 2, 1) #define PIN_PA10__CANRX0 PINMUX_PIN(PIN_PA10, 3, 1) #define PIN_PA10__NCS1 PINMUX_PIN(PIN_PA10, 4, 1) #define PIN_PA10__SPDIF_TX PINMUX_PIN(PIN_PA10, 5, 1) #define PIN_PA10__FLEXCOM5_IO0 PINMUX_PIN(PIN_PA10, 6, 3) #define PIN_PA11 11 #define PIN_PA11__GPIO PINMUX_PIN(PIN_PA11, 0, 0) #define PIN_PA11__SDMMC0_DS PINMUX_PIN(PIN_PA11, 1, 1) #define PIN_PA11__FLEXCOM2_IO4 PINMUX_PIN(PIN_PA11, 2, 1) #define PIN_PA11__A0_NBS0 PINMUX_PIN(PIN_PA11, 4, 1) #define PIN_PA11__TIOA0 PINMUX_PIN(PIN_PA11, 5, 1) #define PIN_PA11__FLEXCOM5_IO1 PINMUX_PIN(PIN_PA11, 6, 3) #define PIN_PA12 12 #define PIN_PA12__GPIO PINMUX_PIN(PIN_PA12, 0, 0) #define PIN_PA12__SDMMC0_WP PINMUX_PIN(PIN_PA12, 1, 1) #define PIN_PA12__FLEXCOM1_IO3 PINMUX_PIN(PIN_PA12, 2, 1) #define PIN_PA12__FLEXCOM3_IO5 PINMUX_PIN(PIN_PA12, 4, 1) #define PIN_PA12__PWML2 PINMUX_PIN(PIN_PA12, 5, 3) #define PIN_PA12__FLEXCOM6_IO0 PINMUX_PIN(PIN_PA12, 6, 3) #define PIN_PA13 13 #define PIN_PA13__GPIO PINMUX_PIN(PIN_PA13, 0, 0) #define PIN_PA13__SDMMC0_1V8SEL PINMUX_PIN(PIN_PA13, 1, 1) #define PIN_PA13__FLEXCOM1_IO2 PINMUX_PIN(PIN_PA13, 2, 1) #define PIN_PA13__FLEXCOM3_IO6 PINMUX_PIN(PIN_PA13, 4, 1) #define PIN_PA13__PWMH2 PINMUX_PIN(PIN_PA13, 5, 3) #define PIN_PA13__FLEXCOM6_IO1 PINMUX_PIN(PIN_PA13, 6, 3) #define PIN_PA14 14 #define PIN_PA14__GPIO PINMUX_PIN(PIN_PA14, 0, 0) #define PIN_PA14__SDMMC0_CD PINMUX_PIN(PIN_PA14, 1, 1) #define PIN_PA14__FLEXCOM1_IO4 PINMUX_PIN(PIN_PA14, 2, 1) #define PIN_PA14__A25 PINMUX_PIN(PIN_PA14, 4, 1) #define PIN_PA14__PWML1 PINMUX_PIN(PIN_PA14, 5, 3) #define PIN_PA15 15 #define PIN_PA15__GPIO PINMUX_PIN(PIN_PA15, 0, 0) #define PIN_PA15__G0_TXEN PINMUX_PIN(PIN_PA15, 1, 1) #define PIN_PA15__FLEXCOM3_IO0 PINMUX_PIN(PIN_PA15, 2, 1) #define PIN_PA15__ISC_MCK PINMUX_PIN(PIN_PA15, 3, 1) #define PIN_PA15__A1 PINMUX_PIN(PIN_PA15, 4, 1) #define PIN_PA15__TIOB0 PINMUX_PIN(PIN_PA15, 5, 1) #define PIN_PA16 16 #define PIN_PA16__GPIO PINMUX_PIN(PIN_PA16, 0, 0) #define PIN_PA16__G0_TX0 PINMUX_PIN(PIN_PA16, 1, 1) #define PIN_PA16__FLEXCOM3_IO1 PINMUX_PIN(PIN_PA16, 2, 1) #define PIN_PA16__ISC_D0 PINMUX_PIN(PIN_PA16, 3, 1) #define PIN_PA16__A2 PINMUX_PIN(PIN_PA16, 4, 1) #define PIN_PA16__TCLK0 PINMUX_PIN(PIN_PA16, 5, 1) #define PIN_PA17 17 #define PIN_PA17__GPIO PINMUX_PIN(PIN_PA17, 0, 0) #define PIN_PA17__G0_TX1 PINMUX_PIN(PIN_PA17, 1, 1) #define PIN_PA17__FLEXCOM3_IO2 PINMUX_PIN(PIN_PA17, 2, 1) #define PIN_PA17__ISC_D1 PINMUX_PIN(PIN_PA17, 3, 1) #define PIN_PA17__A3 PINMUX_PIN(PIN_PA17, 4, 1) #define PIN_PA17__TIOA1 PINMUX_PIN(PIN_PA17, 5, 1) #define PIN_PA18 18 #define PIN_PA18__GPIO PINMUX_PIN(PIN_PA18, 0, 0) #define PIN_PA18__G0_RXDV PINMUX_PIN(PIN_PA18, 1, 1) #define PIN_PA18__FLEXCOM3_IO3 PINMUX_PIN(PIN_PA18, 2, 1) #define PIN_PA18__ISC_D2 PINMUX_PIN(PIN_PA18, 3, 1) #define PIN_PA18__A4 PINMUX_PIN(PIN_PA18, 4, 1) #define PIN_PA18__TIOB1 PINMUX_PIN(PIN_PA18, 5, 1) #define PIN_PA19 19 #define PIN_PA19__GPIO PINMUX_PIN(PIN_PA19, 0, 0) #define PIN_PA19__G0_RX0 PINMUX_PIN(PIN_PA19, 1, 1) #define PIN_PA19__FLEXCOM3_IO4 PINMUX_PIN(PIN_PA19, 2, 1) #define PIN_PA19__ISC_D3 PINMUX_PIN(PIN_PA19, 3, 1) #define PIN_PA19__A5 PINMUX_PIN(PIN_PA19, 4, 1) #define PIN_PA19__TCLK1 PINMUX_PIN(PIN_PA19, 5, 1) #define PIN_PA20 20 #define PIN_PA20__GPIO PINMUX_PIN(PIN_PA20, 0, 0) #define PIN_PA20__G0_RX1 PINMUX_PIN(PIN_PA20, 1, 1) #define PIN_PA20__FLEXCOM4_IO0 PINMUX_PIN(PIN_PA20, 2, 1) #define PIN_PA20__ISC_D4 PINMUX_PIN(PIN_PA20, 3, 1) #define PIN_PA20__A6 PINMUX_PIN(PIN_PA20, 4, 1) #define PIN_PA20__TIOA2 PINMUX_PIN(PIN_PA20, 5, 1) #define PIN_PA21 21 #define PIN_PA21__GPIO PINMUX_PIN(PIN_PA21, 0, 0) #define PIN_PA21__G0_RXER PINMUX_PIN(PIN_PA21, 1, 1) #define PIN_PA21__FLEXCOM4_IO1 PINMUX_PIN(PIN_PA21, 2, 1) #define PIN_PA21__ISC_D5 PINMUX_PIN(PIN_PA21, 3, 1) #define PIN_PA21__A7 PINMUX_PIN(PIN_PA21, 4, 1) #define PIN_PA21__TIOB2 PINMUX_PIN(PIN_PA21, 5, 1) #define PIN_PA22 22 #define PIN_PA22__GPIO PINMUX_PIN(PIN_PA22, 0, 0) #define PIN_PA22__G0_MDC PINMUX_PIN(PIN_PA22, 1, 1) #define PIN_PA22__FLEXCOM4_IO2 PINMUX_PIN(PIN_PA22, 2, 1) #define PIN_PA22__ISC_D6 PINMUX_PIN(PIN_PA22, 3, 1) #define PIN_PA22__A8 PINMUX_PIN(PIN_PA22, 4, 1) #define PIN_PA22__TCLK2 PINMUX_PIN(PIN_PA22, 5, 1) #define PIN_PA23 23 #define PIN_PA23__GPIO PINMUX_PIN(PIN_PA23, 0, 0) #define PIN_PA23__G0_MDIO PINMUX_PIN(PIN_PA23, 1, 1) #define PIN_PA23__FLEXCOM4_IO3 PINMUX_PIN(PIN_PA23, 2, 1) #define PIN_PA23__ISC_D7 PINMUX_PIN(PIN_PA23, 3, 1) #define PIN_PA23__A9 PINMUX_PIN(PIN_PA23, 4, 1) #define PIN_PA24 24 #define PIN_PA24__GPIO PINMUX_PIN(PIN_PA24, 0, 0) #define PIN_PA24__G0_TXCK PINMUX_PIN(PIN_PA24, 1, 1) #define PIN_PA24__FLEXCOM4_IO4 PINMUX_PIN(PIN_PA24, 2, 1) #define PIN_PA24__ISC_HSYNC PINMUX_PIN(PIN_PA24, 3, 1) #define PIN_PA24__A10 PINMUX_PIN(PIN_PA24, 4, 1) #define PIN_PA24__FLEXCOM0_IO5 PINMUX_PIN(PIN_PA24, 5, 1) #define PIN_PA25 25 #define PIN_PA25__GPIO PINMUX_PIN(PIN_PA25, 0, 0) #define PIN_PA25__G0_125CK PINMUX_PIN(PIN_PA25, 1, 1) #define PIN_PA25__FLEXCOM5_IO4 PINMUX_PIN(PIN_PA25, 2, 1) #define PIN_PA25__ISC_VSYNC PINMUX_PIN(PIN_PA25, 3, 1) #define PIN_PA25__A11 PINMUX_PIN(PIN_PA25, 4, 1) #define PIN_PA25__FLEXCOM0_IO6 PINMUX_PIN(PIN_PA25, 5, 1) #define PIN_PA25__FLEXCOM7_IO0 PINMUX_PIN(PIN_PA25, 6, 3) #define PIN_PA26 26 #define PIN_PA26__GPIO PINMUX_PIN(PIN_PA26, 0, 0) #define PIN_PA26__G0_TX2 PINMUX_PIN(PIN_PA26, 1, 1) #define PIN_PA26__FLEXCOM5_IO2 PINMUX_PIN(PIN_PA26, 2, 1) #define PIN_PA26__ISC_FIELD PINMUX_PIN(PIN_PA26, 3, 1) #define PIN_PA26__A12 PINMUX_PIN(PIN_PA26, 4, 1) #define PIN_PA26__TF0 PINMUX_PIN(PIN_PA26, 5, 1) #define PIN_PA26__FLEXCOM7_IO1 PINMUX_PIN(PIN_PA26, 6, 3) #define PIN_PA27 27 #define PIN_PA27__GPIO PINMUX_PIN(PIN_PA27, 0, 0) #define PIN_PA27__G0_TX3 PINMUX_PIN(PIN_PA27, 1, 1) #define PIN_PA27__FLEXCOM5_IO3 PINMUX_PIN(PIN_PA27, 2, 1) #define PIN_PA27__ISC_PCK PINMUX_PIN(PIN_PA27, 3, 1) #define PIN_PA27__A13 PINMUX_PIN(PIN_PA27, 4, 1) #define PIN_PA27__TK0 PINMUX_PIN(PIN_PA27, 5, 1) #define PIN_PA27__FLEXCOM8_IO0 PINMUX_PIN(PIN_PA27, 6, 3) #define PIN_PA28 28 #define PIN_PA28__GPIO PINMUX_PIN(PIN_PA28, 0, 0) #define PIN_PA28__G0_RX2 PINMUX_PIN(PIN_PA28, 1, 1) #define PIN_PA28__FLEXCOM5_IO0 PINMUX_PIN(PIN_PA28, 2, 1) #define PIN_PA28__ISC_D8 PINMUX_PIN(PIN_PA28, 3, 1) #define PIN_PA28__A14 PINMUX_PIN(PIN_PA28, 4, 1) #define PIN_PA28__RD0 PINMUX_PIN(PIN_PA28, 5, 1) #define PIN_PA28__FLEXCOM8_IO1 PINMUX_PIN(PIN_PA28, 6, 3) #define PIN_PA29 29 #define PIN_PA29__GPIO PINMUX_PIN(PIN_PA29, 0, 0) #define PIN_PA29__G0_RX3 PINMUX_PIN(PIN_PA29, 1, 1) #define PIN_PA29__FLEXCOM5_IO1 PINMUX_PIN(PIN_PA29, 2, 1) #define PIN_PA29__ISC_D9 PINMUX_PIN(PIN_PA29, 3, 1) #define PIN_PA29__A15 PINMUX_PIN(PIN_PA29, 4, 1) #define PIN_PA29__RF0 PINMUX_PIN(PIN_PA29, 5, 1) #define PIN_PA29__FLEXCOM9_IO0 PINMUX_PIN(PIN_PA29, 6, 3) #define PIN_PA30 30 #define PIN_PA30__GPIO PINMUX_PIN(PIN_PA30, 0, 0) #define PIN_PA30__G0_RXCK PINMUX_PIN(PIN_PA30, 1, 1) #define PIN_PA30__FLEXCOM6_IO4 PINMUX_PIN(PIN_PA30, 2, 1) #define PIN_PA30__ISC_D10 PINMUX_PIN(PIN_PA30, 3, 1) #define PIN_PA30__A16 PINMUX_PIN(PIN_PA30, 4, 1) #define PIN_PA30__RK0 PINMUX_PIN(PIN_PA30, 5, 1) #define PIN_PA30__FLEXCOM9_IO1 PINMUX_PIN(PIN_PA30, 6, 3) #define PIN_PA31 31 #define PIN_PA31__GPIO PINMUX_PIN(PIN_PA31, 0, 0) #define PIN_PA31__G0_TXER PINMUX_PIN(PIN_PA31, 1, 1) #define PIN_PA31__FLEXCOM6_IO2 PINMUX_PIN(PIN_PA31, 2, 1) #define PIN_PA31__ISC_D11 PINMUX_PIN(PIN_PA31, 3, 1) #define PIN_PA31__A17 PINMUX_PIN(PIN_PA31, 4, 1) #define PIN_PA31__TD0 PINMUX_PIN(PIN_PA31, 5, 1) #define PIN_PA31__FLEXCOM10_IO0 PINMUX_PIN(PIN_PA31, 6, 3) #define PIN_PB0 32 #define PIN_PB0__GPIO PINMUX_PIN(PIN_PB0, 0, 0) #define PIN_PB0__G0_COL PINMUX_PIN(PIN_PB0, 1, 1) #define PIN_PB0__FLEXCOM6_IO3 PINMUX_PIN(PIN_PB0, 2, 2) #define PIN_PB0__EXT_IRQ0 PINMUX_PIN(PIN_PB0, 3, 1) #define PIN_PB0__A18 PINMUX_PIN(PIN_PB0, 4, 1) #define PIN_PB0__SPDIF_RX PINMUX_PIN(PIN_PB0, 5, 2) #define PIN_PB0__FLEXCOM10_IO1 PINMUX_PIN(PIN_PB0, 6, 3) #define PIN_PB1 33 #define PIN_PB1__GPIO PINMUX_PIN(PIN_PB1, 0, 0) #define PIN_PB1__G0_CRS PINMUX_PIN(PIN_PB1, 1, 1) #define PIN_PB1__FLEXCOM6_IO1 PINMUX_PIN(PIN_PB1, 2, 2) #define PIN_PB1__EXT_IRQ1 PINMUX_PIN(PIN_PB1, 3, 1) #define PIN_PB1__A19 PINMUX_PIN(PIN_PB1, 4, 1) #define PIN_PB1__SPDIF_TX PINMUX_PIN(PIN_PB1, 5, 2) #define PIN_PB1__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB1, 6, 3) #define PIN_PB2 34 #define PIN_PB2__GPIO PINMUX_PIN(PIN_PB2, 0, 0) #define PIN_PB2__G0_TSUCOMP PINMUX_PIN(PIN_PB2, 1, 1) #define PIN_PB2__FLEXCOM6_IO0 PINMUX_PIN(PIN_PB2, 2, 1) #define PIN_PB2__ADTRG PINMUX_PIN(PIN_PB2, 3, 1) #define PIN_PB2__A20 PINMUX_PIN(PIN_PB2, 4, 1) #define PIN_PB2__FLEXCOM11_IO1 PINMUX_PIN(PIN_PB2, 6, 3) #define PIN_PB3 35 #define PIN_PB3__GPIO PINMUX_PIN(PIN_PB3, 0, 0) #define PIN_PB3__RF1 PINMUX_PIN(PIN_PB3, 1, 1) #define PIN_PB3__FLEXCOM11_IO0 PINMUX_PIN(PIN_PB3, 2, 1) #define PIN_PB3__PCK2 PINMUX_PIN(PIN_PB3, 3, 2) #define PIN_PB3__D8 PINMUX_PIN(PIN_PB3, 4, 1) #define PIN_PB4 36 #define PIN_PB4__GPIO PINMUX_PIN(PIN_PB4, 0, 0) #define PIN_PB4__TF1 PINMUX_PIN(PIN_PB4, 1, 1) #define PIN_PB4__FLEXCOM11_IO1 PINMUX_PIN(PIN_PB4, 2, 1) #define PIN_PB4__PCK3 PINMUX_PIN(PIN_PB4, 3, 2) #define PIN_PB4__D9 PINMUX_PIN(PIN_PB4, 4, 1) #define PIN_PB5 37 #define PIN_PB5__GPIO PINMUX_PIN(PIN_PB5, 0, 0) #define PIN_PB5__TK1 PINMUX_PIN(PIN_PB5, 1, 1) #define PIN_PB5__FLEXCOM11_IO2 PINMUX_PIN(PIN_PB5, 2, 1) #define PIN_PB5__PCK4 PINMUX_PIN(PIN_PB5, 3, 2) #define PIN_PB5__D10 PINMUX_PIN(PIN_PB5, 4, 1) #define PIN_PB6 38 #define PIN_PB6__GPIO PINMUX_PIN(PIN_PB6, 0, 0) #define PIN_PB6__RK1 PINMUX_PIN(PIN_PB6, 1, 1) #define PIN_PB6__FLEXCOM11_IO3 PINMUX_PIN(PIN_PB6, 2, 1) #define PIN_PB6__PCK5 PINMUX_PIN(PIN_PB6, 3, 2) #define PIN_PB6__D11 PINMUX_PIN(PIN_PB6, 4, 1) #define PIN_PB7 39 #define PIN_PB7__GPIO PINMUX_PIN(PIN_PB7, 0, 0) #define PIN_PB7__TD1 PINMUX_PIN(PIN_PB7, 1, 1) #define PIN_PB7__FLEXCOM11_IO4 PINMUX_PIN(PIN_PB7, 2, 1) #define PIN_PB7__FLEXCOM3_IO5 PINMUX_PIN(PIN_PB7, 3, 2) #define PIN_PB7__D12 PINMUX_PIN(PIN_PB7, 4, 1) #define PIN_PB8 40 #define PIN_PB8__GPIO PINMUX_PIN(PIN_PB8, 0, 0) #define PIN_PB8__RD1 PINMUX_PIN(PIN_PB8, 1, 1) #define PIN_PB8__FLEXCOM8_IO0 PINMUX_PIN(PIN_PB8, 2, 1) #define PIN_PB8__FLEXCOM3_IO6 PINMUX_PIN(PIN_PB8, 3, 2) #define PIN_PB8__D13 PINMUX_PIN(PIN_PB8, 4, 1) #define PIN_PB9 41 #define PIN_PB9__GPIO PINMUX_PIN(PIN_PB9, 0, 0) #define PIN_PB9__QSPI0_IO3 PINMUX_PIN(PIN_PB9, 1, 1) #define PIN_PB9__FLEXCOM8_IO1 PINMUX_PIN(PIN_PB9, 2, 1) #define PIN_PB9__PDMC0_CLK PINMUX_PIN(PIN_PB9, 3, 1) #define PIN_PB9__NCS3_NANDCS PINMUX_PIN(PIN_PB9, 4, 1) #define PIN_PB9__PWML0 PINMUX_PIN(PIN_PB9, 5, 2) #define PIN_PB10 42 #define PIN_PB10__GPIO PINMUX_PIN(PIN_PB10, 0, 0) #define PIN_PB10__QSPI0_IO2 PINMUX_PIN(PIN_PB10, 1, 1) #define PIN_PB10__FLEXCOM8_IO2 PINMUX_PIN(PIN_PB10, 2, 1) #define PIN_PB10__PDMC0_DS0 PINMUX_PIN(PIN_PB10, 3, 1) #define PIN_PB10__NWE_NWR0_NANDWE PINMUX_PIN(PIN_PB10, 4, 1) #define PIN_PB10__PWMH0 PINMUX_PIN(PIN_PB10, 5, 2) #define PIN_PB11 43 #define PIN_PB11__GPIO PINMUX_PIN(PIN_PB11, 0, 0) #define PIN_PB11__QSPI0_IO1 PINMUX_PIN(PIN_PB11, 1, 1) #define PIN_PB11__FLEXCOM8_IO3 PINMUX_PIN(PIN_PB11, 2, 1) #define PIN_PB11__PDMC0_DS1 PINMUX_PIN(PIN_PB11, 3, 1) #define PIN_PB11__NRD_NANDOE PINMUX_PIN(PIN_PB11, 4, 1) #define PIN_PB11__PWML1 PINMUX_PIN(PIN_PB11, 5, 2) #define PIN_PB12 44 #define PIN_PB12__GPIO PINMUX_PIN(PIN_PB12, 0, 0) #define PIN_PB12__QSPI0_IO0 PINMUX_PIN(PIN_PB12, 1, 1) #define PIN_PB12__FLEXCOM8_IO4 PINMUX_PIN(PIN_PB12, 2, 1) #define PIN_PB12__FLEXCOM6_IO5 PINMUX_PIN(PIN_PB12, 3, 1) #define PIN_PB12__A21_NANDALE PINMUX_PIN(PIN_PB12, 4, 1) #define PIN_PB12__PWMH1 PINMUX_PIN(PIN_PB12, 5, 2) #define PIN_PB13 45 #define PIN_PB13__GPIO PINMUX_PIN(PIN_PB13, 0, 0) #define PIN_PB13__QSPI0_CS PINMUX_PIN(PIN_PB13, 1, 1) #define PIN_PB13__FLEXCOM9_IO0 PINMUX_PIN(PIN_PB13, 2, 1) #define PIN_PB13__FLEXCOM6_IO6 PINMUX_PIN(PIN_PB13, 3, 1) #define PIN_PB13__A22_NANDCLE PINMUX_PIN(PIN_PB13, 4, 1) #define PIN_PB13__PWML2 PINMUX_PIN(PIN_PB13, 5, 2) #define PIN_PB14 46 #define PIN_PB14__GPIO PINMUX_PIN(PIN_PB14, 0, 0) #define PIN_PB14__QSPI0_SCK PINMUX_PIN(PIN_PB14, 1, 1) #define PIN_PB14__FLEXCOM9_IO1 PINMUX_PIN(PIN_PB14, 2, 1) #define PIN_PB14__D0 PINMUX_PIN(PIN_PB14, 4, 1) #define PIN_PB14__PWMH2 PINMUX_PIN(PIN_PB14, 5, 2) #define PIN_PB15 47 #define PIN_PB15__GPIO PINMUX_PIN(PIN_PB15, 0, 0) #define PIN_PB15__QSPI0_SCKN PINMUX_PIN(PIN_PB15, 1, 1) #define PIN_PB15__FLEXCOM9_IO2 PINMUX_PIN(PIN_PB15, 2, 1) #define PIN_PB15__D1 PINMUX_PIN(PIN_PB15, 4, 1) #define PIN_PB15__PWML3 PINMUX_PIN(PIN_PB15, 5, 2) #define PIN_PB16 48 #define PIN_PB16__GPIO PINMUX_PIN(PIN_PB16, 0, 0) #define PIN_PB16__QSPI0_IO4 PINMUX_PIN(PIN_PB16, 1, 1) #define PIN_PB16__FLEXCOM9_IO3 PINMUX_PIN(PIN_PB16, 2, 1) #define PIN_PB16__PCK0 PINMUX_PIN(PIN_PB16, 3, 1) #define PIN_PB16__D2 PINMUX_PIN(PIN_PB16, 4, 1) #define PIN_PB16__PWMH3 PINMUX_PIN(PIN_PB16, 5, 2) #define PIN_PB16__EXT_IRQ0 PINMUX_PIN(PIN_PB16, 6, 2) #define PIN_PB17 49 #define PIN_PB17__GPIO PINMUX_PIN(PIN_PB17, 0, 0) #define PIN_PB17__QSPI0_IO5 PINMUX_PIN(PIN_PB17, 1, 1) #define PIN_PB17__FLEXCOM9_IO4 PINMUX_PIN(PIN_PB17, 2, 1) #define PIN_PB17__PCK1 PINMUX_PIN(PIN_PB17, 3, 1) #define PIN_PB17__D3 PINMUX_PIN(PIN_PB17, 4, 1) #define PIN_PB17__PWMEXTRG0 PINMUX_PIN(PIN_PB17, 5, 2) #define PIN_PB17__EXT_IRQ1 PINMUX_PIN(PIN_PB17, 6, 2) #define PIN_PB18 50 #define PIN_PB18__GPIO PINMUX_PIN(PIN_PB18, 0, 0) #define PIN_PB18__QSPI0_IO6 PINMUX_PIN(PIN_PB18, 1, 1) #define PIN_PB18__FLEXCOM10_IO0 PINMUX_PIN(PIN_PB18, 2, 1) #define PIN_PB18__PCK2 PINMUX_PIN(PIN_PB18, 3, 1) #define PIN_PB18__D4 PINMUX_PIN(PIN_PB18, 4, 1) #define PIN_PB18__PWMEXTRG1 PINMUX_PIN(PIN_PB18, 5, 2) #define PIN_PB19 51 #define PIN_PB19__GPIO PINMUX_PIN(PIN_PB19, 0, 0) #define PIN_PB19__QSPI0_IO7 PINMUX_PIN(PIN_PB19, 1, 1) #define PIN_PB19__FLEXCOM10_IO1 PINMUX_PIN(PIN_PB19, 2, 1) #define PIN_PB19__PCK3 PINMUX_PIN(PIN_PB19, 3, 1) #define PIN_PB19__D5 PINMUX_PIN(PIN_PB19, 4, 1) #define PIN_PB19__PWMFI0 PINMUX_PIN(PIN_PB19, 5, 2) #define PIN_PB20 52 #define PIN_PB20__GPIO PINMUX_PIN(PIN_PB20, 0, 0) #define PIN_PB20__QSPI0_DQS PINMUX_PIN(PIN_PB20, 1, 1) #define PIN_PB20__FLEXCOM10_IO2 PINMUX_PIN(PIN_PB20, 2, 1) #define PIN_PB20__D6 PINMUX_PIN(PIN_PB20, 4, 1) #define PIN_PB20__PWMFI1 PINMUX_PIN(PIN_PB20, 5, 2) #define PIN_PB21 53 #define PIN_PB21__GPIO PINMUX_PIN(PIN_PB21, 0, 0) #define PIN_PB21__QSPI0_INT PINMUX_PIN(PIN_PB21, 1, 1) #define PIN_PB21__FLEXCOM10_IO3 PINMUX_PIN(PIN_PB21, 2, 1) #define PIN_PB21__FLEXCOM9_IO5 PINMUX_PIN(PIN_PB21, 3, 1) #define PIN_PB21__D7 PINMUX_PIN(PIN_PB21, 4, 1) #define PIN_PB22 54 #define PIN_PB22__GPIO PINMUX_PIN(PIN_PB22, 0, 0) #define PIN_PB22__QSPI1_IO3 PINMUX_PIN(PIN_PB22, 1, 1) #define PIN_PB22__FLEXCOM10_IO4 PINMUX_PIN(PIN_PB22, 2, 1) #define PIN_PB22__FLEXCOM9_IO6 PINMUX_PIN(PIN_PB22, 3, 1) #define PIN_PB22__NANDRDY PINMUX_PIN(PIN_PB22, 4, 1) #define PIN_PB23 55 #define PIN_PB23__GPIO PINMUX_PIN(PIN_PB23, 0, 0) #define PIN_PB23__QSPI1_IO2 PINMUX_PIN(PIN_PB23, 1, 1) #define PIN_PB23__FLEXCOM7_IO0 PINMUX_PIN(PIN_PB23, 2, 1) #define PIN_PB23__I2SMCC0_CK PINMUX_PIN(PIN_PB23, 3, 1) #define PIN_PB23__PCK4 PINMUX_PIN(PIN_PB23, 6, 1) #define PIN_PB24 56 #define PIN_PB24__GPIO PINMUX_PIN(PIN_PB24, 0, 0) #define PIN_PB24__QSPI1_IO1 PINMUX_PIN(PIN_PB24, 1, 1) #define PIN_PB24__FLEXCOM7_IO1 PINMUX_PIN(PIN_PB24, 2, 1) #define PIN_PB24__I2SMCC0_WS PINMUX_PIN(PIN_PB24, 3, 1) #define PIN_PB24__PCK5 PINMUX_PIN(PIN_PB24, 6, 1) #define PIN_PB25 57 #define PIN_PB25__GPIO PINMUX_PIN(PIN_PB25, 0, 0) #define PIN_PB25__QSPI1_IO0 PINMUX_PIN(PIN_PB25, 1, 1) #define PIN_PB25__FLEXCOM7_IO2 PINMUX_PIN(PIN_PB25, 2, 1) #define PIN_PB25__I2SMCC0_DOUT1 PINMUX_PIN(PIN_PB25, 3, 1) #define PIN_PB25__PCK6 PINMUX_PIN(PIN_PB25, 6, 1) #define PIN_PB26 58 #define PIN_PB26__GPIO PINMUX_PIN(PIN_PB26, 0, 0) #define PIN_PB26__QSPI1_CS PINMUX_PIN(PIN_PB26, 1, 1) #define PIN_PB26__FLEXCOM7_IO3 PINMUX_PIN(PIN_PB26, 2, 1) #define PIN_PB26__I2SMCC0_DOUT0 PINMUX_PIN(PIN_PB26, 3, 1) #define PIN_PB26__PWMEXTRG0 PINMUX_PIN(PIN_PB26, 5, 1) #define PIN_PB26__PCK7 PINMUX_PIN(PIN_PB26, 6, 1) #define PIN_PB27 59 #define PIN_PB27__GPIO PINMUX_PIN(PIN_PB27, 0, 0) #define PIN_PB27__QSPI1_SCK PINMUX_PIN(PIN_PB27, 1, 1) #define PIN_PB27__FLEXCOM7_IO4 PINMUX_PIN(PIN_PB27, 2, 1) #define PIN_PB27__I2SMCC0_MCK PINMUX_PIN(PIN_PB27, 3, 1) #define PIN_PB27__PWMEXTRG1 PINMUX_PIN(PIN_PB27, 5, 1) #define PIN_PB28 60 #define PIN_PB28__GPIO PINMUX_PIN(PIN_PB28, 0, 0) #define PIN_PB28__SDMMC1_RSTN PINMUX_PIN(PIN_PB28, 1, 1) #define PIN_PB28__ADTRG PINMUX_PIN(PIN_PB28, 2, 2) #define PIN_PB28__PWMFI0 PINMUX_PIN(PIN_PB28, 5, 1) #define PIN_PB28__FLEXCOM7_IO0 PINMUX_PIN(PIN_PB28, 6, 4) #define PIN_PB29 61 #define PIN_PB29__GPIO PINMUX_PIN(PIN_PB29, 0, 0) #define PIN_PB29__SDMMC1_CMD PINMUX_PIN(PIN_PB29, 1, 1) #define PIN_PB29__FLEXCOM3_IO2 PINMUX_PIN(PIN_PB29, 2, 2) #define PIN_PB29__FLEXCOM0_IO5 PINMUX_PIN(PIN_PB29, 3, 2) #define PIN_PB29__TIOA3 PINMUX_PIN(PIN_PB29, 4, 2) #define PIN_PB29__PWMFI1 PINMUX_PIN(PIN_PB29, 5, 1) #define PIN_PB29__FLEXCOM7_IO1 PINMUX_PIN(PIN_PB29, 6, 4) #define PIN_PB30 62 #define PIN_PB30__GPIO PINMUX_PIN(PIN_PB30, 0, 0) #define PIN_PB30__SDMMC1_CK PINMUX_PIN(PIN_PB30, 1, 1) #define PIN_PB30__FLEXCOM3_IO3 PINMUX_PIN(PIN_PB30, 2, 2) #define PIN_PB30__FLEXCOM0_IO6 PINMUX_PIN(PIN_PB30, 3, 2) #define PIN_PB30__TIOB3 PINMUX_PIN(PIN_PB30, 4, 1) #define PIN_PB30__PWMH0 PINMUX_PIN(PIN_PB30, 5, 1) #define PIN_PB30__FLEXCOM8_IO0 PINMUX_PIN(PIN_PB30, 6, 4) #define PIN_PB31 63 #define PIN_PB31__GPIO PINMUX_PIN(PIN_PB31, 0, 0) #define PIN_PB31__SDMMC1_DAT0 PINMUX_PIN(PIN_PB31, 1, 1) #define PIN_PB31__FLEXCOM3_IO4 PINMUX_PIN(PIN_PB31, 2, 2) #define PIN_PB31__FLEXCOM9_IO5 PINMUX_PIN(PIN_PB31, 3, 2) #define PIN_PB31__TCLK3 PINMUX_PIN(PIN_PB31, 4, 1) #define PIN_PB31__PWML0 PINMUX_PIN(PIN_PB31, 5, 1) #define PIN_PB31__FLEXCOM8_IO1 PINMUX_PIN(PIN_PB31, 6, 4) #define PIN_PC0 64 #define PIN_PC0__GPIO PINMUX_PIN(PIN_PC0, 0, 0) #define PIN_PC0__SDMMC1_DAT1 PINMUX_PIN(PIN_PC0, 1, 1) #define PIN_PC0__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC0, 2, 2) #define PIN_PC0__TIOA4 PINMUX_PIN(PIN_PC0, 4, 1) #define PIN_PC0__PWML1 PINMUX_PIN(PIN_PC0, 5, 1) #define PIN_PC0__FLEXCOM9_IO0 PINMUX_PIN(PIN_PC0, 6, 4) #define PIN_PC1 65 #define PIN_PC1__GPIO PINMUX_PIN(PIN_PC1, 0, 0) #define PIN_PC1__SDMMC1_DAT2 PINMUX_PIN(PIN_PC1, 1, 1) #define PIN_PC1__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC1, 2, 2) #define PIN_PC1__TIOB4 PINMUX_PIN(PIN_PC1, 4, 1) #define PIN_PC1__PWMH1 PINMUX_PIN(PIN_PC1, 5, 1) #define PIN_PC1__FLEXCOM9_IO1 PINMUX_PIN(PIN_PC1, 6, 4) #define PIN_PC2 66 #define PIN_PC2__GPIO PINMUX_PIN(PIN_PC2, 0, 0) #define PIN_PC2__SDMMC1_DAT3 PINMUX_PIN(PIN_PC2, 1, 1) #define PIN_PC2__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC2, 2, 2) #define PIN_PC2__TCLK4 PINMUX_PIN(PIN_PC2, 4, 1) #define PIN_PC2__PWML2 PINMUX_PIN(PIN_PC2, 5, 1) #define PIN_PC2__FLEXCOM10_IO0 PINMUX_PIN(PIN_PC2, 6, 4) #define PIN_PC3 67 #define PIN_PC3__GPIO PINMUX_PIN(PIN_PC3, 0, 0) #define PIN_PC3__SDMMC1_WP PINMUX_PIN(PIN_PC3, 1, 1) #define PIN_PC3__FLEXCOM4_IO1 PINMUX_PIN(PIN_PC3, 2, 2) #define PIN_PC3__TIOA5 PINMUX_PIN(PIN_PC3, 4, 1) #define PIN_PC3__PWMH2 PINMUX_PIN(PIN_PC3, 5, 1) #define PIN_PC3__FLEXCOM10_IO1 PINMUX_PIN(PIN_PC3, 6, 4) #define PIN_PC4 68 #define PIN_PC4__GPIO PINMUX_PIN(PIN_PC4, 0, 0) #define PIN_PC4__SDMMC1_CD PINMUX_PIN(PIN_PC4, 1, 1) #define PIN_PC4__FLEXCOM4_IO2 PINMUX_PIN(PIN_PC4, 2, 2) #define PIN_PC4__FLEXCOM9_IO6 PINMUX_PIN(PIN_PC4, 3, 2) #define PIN_PC4__TIOB5 PINMUX_PIN(PIN_PC4, 4, 1) #define PIN_PC4__PWML3 PINMUX_PIN(PIN_PC4, 5, 1) #define PIN_PC4__FLEXCOM11_IO0 PINMUX_PIN(PIN_PC4, 6, 4) #define PIN_PC5 69 #define PIN_PC5__GPIO PINMUX_PIN(PIN_PC5, 0, 0) #define PIN_PC5__SDMMC1_1V8SEL PINMUX_PIN(PIN_PC5, 1, 1) #define PIN_PC5__FLEXCOM4_IO3 PINMUX_PIN(PIN_PC5, 2, 2) #define PIN_PC5__FLEXCOM6_IO5 PINMUX_PIN(PIN_PC5, 3, 2) #define PIN_PC5__TCLK5 PINMUX_PIN(PIN_PC5, 4, 1) #define PIN_PC5__PWMH3 PINMUX_PIN(PIN_PC5, 5, 1) #define PIN_PC5__FLEXCOM11_IO1 PINMUX_PIN(PIN_PC5, 6, 4) #define PIN_PC6 70 #define PIN_PC6__GPIO PINMUX_PIN(PIN_PC6, 0, 0) #define PIN_PC6__FLEXCOM4_IO4 PINMUX_PIN(PIN_PC6, 2, 2) #define PIN_PC6__FLEXCOM6_IO6 PINMUX_PIN(PIN_PC6, 3, 2) #define PIN_PC7 71 #define PIN_PC7__GPIO PINMUX_PIN(PIN_PC7, 0, 0) #define PIN_PC7__I2SMCC0_DIN0 PINMUX_PIN(PIN_PC7, 1, 1) #define PIN_PC7__FLEXCOM7_IO0 PINMUX_PIN(PIN_PC7, 2, 2) #define PIN_PC8 72 #define PIN_PC8__GPIO PINMUX_PIN(PIN_PC8, 0, 0) #define PIN_PC8__I2SMCC0_DIN1 PINMUX_PIN(PIN_PC8, 1, 1) #define PIN_PC8__FLEXCOM7_IO1 PINMUX_PIN(PIN_PC8, 2, 2) #define PIN_PC9 73 #define PIN_PC9__GPIO PINMUX_PIN(PIN_PC9, 0, 0) #define PIN_PC9__I2SMCC0_DOUT3 PINMUX_PIN(PIN_PC9, 1, 1) #define PIN_PC9__FLEXCOM7_IO2 PINMUX_PIN(PIN_PC9, 2, 2) #define PIN_PC9__FLEXCOM1_IO0 PINMUX_PIN(PIN_PC9, 6, 4) #define PIN_PC10 74 #define PIN_PC10__GPIO PINMUX_PIN(PIN_PC10, 0, 0) #define PIN_PC10__I2SMCC0_DOUT2 PINMUX_PIN(PIN_PC10, 1, 1) #define PIN_PC10__FLEXCOM7_IO3 PINMUX_PIN(PIN_PC10, 2, 2) #define PIN_PC10__FLEXCOM1_IO1 PINMUX_PIN(PIN_PC10, 6, 4) #define PIN_PC11 75 #define PIN_PC11__GPIO PINMUX_PIN(PIN_PC11, 0, 0) #define PIN_PC11__I2SMCC1_CK PINMUX_PIN(PIN_PC11, 1, 1) #define PIN_PC11__FLEXCOM7_IO4 PINMUX_PIN(PIN_PC11, 2, 2) #define PIN_PC11__FLEXCOM2_IO0 PINMUX_PIN(PIN_PC11, 6, 4) #define PIN_PC12 76 #define PIN_PC12__GPIO PINMUX_PIN(PIN_PC12, 0, 0) #define PIN_PC12__I2SMCC1_WS PINMUX_PIN(PIN_PC12, 1, 1) #define PIN_PC12__FLEXCOM8_IO2 PINMUX_PIN(PIN_PC12, 2, 2) #define PIN_PC12__FLEXCOM2_IO1 PINMUX_PIN(PIN_PC12, 6, 4) #define PIN_PC13 77 #define PIN_PC13__GPIO PINMUX_PIN(PIN_PC13, 0, 0) #define PIN_PC13__I2SMCC1_MCK PINMUX_PIN(PIN_PC13, 1, 1) #define PIN_PC13__FLEXCOM8_IO1 PINMUX_PIN(PIN_PC13, 2, 2) #define PIN_PC13__FLEXCOM3_IO0 PINMUX_PIN(PIN_PC13, 6, 4) #define PIN_PC14 78 #define PIN_PC14__GPIO PINMUX_PIN(PIN_PC14, 0, 0) #define PIN_PC14__I2SMCC1_DOUT0 PINMUX_PIN(PIN_PC14, 1, 1) #define PIN_PC14__FLEXCOM8_IO0 PINMUX_PIN(PIN_PC14, 2, 2) #define PIN_PC14__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC14, 6, 4) #define PIN_PC15 79 #define PIN_PC15__GPIO PINMUX_PIN(PIN_PC15, 0, 0) #define PIN_PC15__I2SMCC1_DOUT1 PINMUX_PIN(PIN_PC15, 1, 1) #define PIN_PC15__FLEXCOM8_IO3 PINMUX_PIN(PIN_PC15, 2, 2) #define PIN_PC15__FLEXCOM4_IO0 PINMUX_PIN(PIN_PC15, 6, 4) #define PIN_PC16 80 #define PIN_PC16__GPIO PINMUX_PIN(PIN_PC16, 0, 0) #define PIN_PC16__I2SMCC1_DOUT2 PINMUX_PIN(PIN_PC16, 1, 1) #define PIN_PC16__FLEXCOM8_IO4 PINMUX_PIN(PIN_PC16, 2, 2) #define PIN_PC16__FLEXCOM3_IO1 PINMUX_PIN(PIN_PC16, 6, 4) #define PIN_PC17 81 #define PIN_PC17__GPIO PINMUX_PIN(PIN_PC17, 0, 0) #define PIN_PC17__I2SMCC1_DOUT3 PINMUX_PIN(PIN_PC17, 1, 1) #define PIN_PC17__EXT_IRQ0 PINMUX_PIN(PIN_PC17, 2, 3) #define PIN_PC17__FLEXCOM5_IO0 PINMUX_PIN(PIN_PC17, 6, 4) #define PIN_PC18 82 #define PIN_PC18__GPIO PINMUX_PIN(PIN_PC18, 0, 0) #define PIN_PC18__I2SMCC1_DIN0 PINMUX_PIN(PIN_PC18, 1, 1) #define PIN_PC18__FLEXCOM9_IO0 PINMUX_PIN(PIN_PC18, 2, 2) #define PIN_PC18__FLEXCOM5_IO1 PINMUX_PIN(PIN_PC18, 6, 4) #define PIN_PC19 83 #define PIN_PC19__GPIO PINMUX_PIN(PIN_PC19, 0, 0) #define PIN_PC19__I2SMCC1_DIN1 PINMUX_PIN(PIN_PC19, 1, 1) #define PIN_PC19__FLEXCOM9_IO1 PINMUX_PIN(PIN_PC19, 2, 2) #define PIN_PC19__FLEXCOM6_IO0 PINMUX_PIN(PIN_PC19, 6, 4) #define PIN_PC20 84 #define PIN_PC20__GPIO PINMUX_PIN(PIN_PC20, 0, 0) #define PIN_PC20__I2SMCC1_DIN2 PINMUX_PIN(PIN_PC20, 1, 1) #define PIN_PC20__FLEXCOM9_IO4 PINMUX_PIN(PIN_PC20, 2, 2) #define PIN_PC20__FLEXCOM6_IO1 PINMUX_PIN(PIN_PC20, 6, 4) #define PIN_PC21 85 #define PIN_PC21__GPIO PINMUX_PIN(PIN_PC21, 0, 0) #define PIN_PC21__I2SMCC1_DIN3 PINMUX_PIN(PIN_PC21, 1, 1) #define PIN_PC21__FLEXCOM9_IO2 PINMUX_PIN(PIN_PC21, 2, 2) #define PIN_PC21__D3 PINMUX_PIN(PIN_PC21, 4, 2) #define PIN_PC21__FLEXCOM6_IO0 PINMUX_PIN(PIN_PC21, 6, 5) #define PIN_PC22 86 #define PIN_PC22__GPIO PINMUX_PIN(PIN_PC22, 0, 0) #define PIN_PC22__I2SMCC0_DIN2 PINMUX_PIN(PIN_PC22, 1, 1) #define PIN_PC22__FLEXCOM9_IO3 PINMUX_PIN(PIN_PC22, 2, 2) #define PIN_PC22__D4 PINMUX_PIN(PIN_PC22, 4, 2) #define PIN_PC22__FLEXCOM6_IO1 PINMUX_PIN(PIN_PC22, 6, 5) #define PIN_PC23 87 #define PIN_PC23__GPIO PINMUX_PIN(PIN_PC23, 0, 0) #define PIN_PC23__I2SMCC0_DIN3 PINMUX_PIN(PIN_PC23, 1, 1) #define PIN_PC23__FLEXCOM0_IO5 PINMUX_PIN(PIN_PC23, 2, 3) #define PIN_PC23__D5 PINMUX_PIN(PIN_PC23, 4, 2) #define PIN_PC23__FLEXCOM7_IO0 PINMUX_PIN(PIN_PC23, 6, 5) #define PIN_PC24 88 #define PIN_PC24__GPIO PINMUX_PIN(PIN_PC24, 0, 0) #define PIN_PC24__FLEXCOM0_IO6 PINMUX_PIN(PIN_PC24, 2, 3) #define PIN_PC24__EXT_IRQ1 PINMUX_PIN(PIN_PC24, 3, 3) #define PIN_PC24__D6 PINMUX_PIN(PIN_PC24, 4, 2) #define PIN_PC24__FLEXCOM7_IO1 PINMUX_PIN(PIN_PC24, 6, 5) #define PIN_PC25 89 #define PIN_PC25__GPIO PINMUX_PIN(PIN_PC25, 0, 0) #define PIN_PC25__NTRST PINMUX_PIN(PIN_PC25, 1, 1) #define PIN_PC26 90 #define PIN_PC26__GPIO PINMUX_PIN(PIN_PC26, 0, 0) #define PIN_PC26__TCK_SWCLK PINMUX_PIN(PIN_PC26, 1, 1) #define PIN_PC27 91 #define PIN_PC27__GPIO PINMUX_PIN(PIN_PC27, 0, 0) #define PIN_PC27__TMS_SWDIO PINMUX_PIN(PIN_PC27, 1, 1) #define PIN_PC28 92 #define PIN_PC28__GPIO PINMUX_PIN(PIN_PC28, 0, 0) #define PIN_PC28__TDI PINMUX_PIN(PIN_PC28, 1, 1) #define PIN_PC29 93 #define PIN_PC29__GPIO PINMUX_PIN(PIN_PC29, 0, 0) #define PIN_PC29__TDO PINMUX_PIN(PIN_PC29, 1, 1) #define PIN_PC30 94 #define PIN_PC30__GPIO PINMUX_PIN(PIN_PC30, 0, 0) #define PIN_PC30__FLEXCOM10_IO0 PINMUX_PIN(PIN_PC30, 2, 2) #define PIN_PC31 95 #define PIN_PC31__GPIO PINMUX_PIN(PIN_PC31, 0, 0) #define PIN_PC31__FLEXCOM10_IO1 PINMUX_PIN(PIN_PC31, 2, 2) #define PIN_PD0 96 #define PIN_PD0__GPIO PINMUX_PIN(PIN_PD0, 0, 0) #define PIN_PD0__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD0, 2, 2) #define PIN_PD1 97 #define PIN_PD1__GPIO PINMUX_PIN(PIN_PD1, 0, 0) #define PIN_PD1__FLEXCOM11_IO1 PINMUX_PIN(PIN_PD1, 2, 2) #define PIN_PD2 98 #define PIN_PD2__GPIO PINMUX_PIN(PIN_PD2, 0, 0) #define PIN_PD2__SDMMC2_RSTN PINMUX_PIN(PIN_PD2, 1, 1) #define PIN_PD2__PCK0 PINMUX_PIN(PIN_PD2, 2, 2) #define PIN_PD2__CANTX4 PINMUX_PIN(PIN_PD2, 3, 1) #define PIN_PD2__D7 PINMUX_PIN(PIN_PD2, 4, 2) #define PIN_PD2__TIOA0 PINMUX_PIN(PIN_PD2, 5, 2) #define PIN_PD2__FLEXCOM8_IO0 PINMUX_PIN(PIN_PD2, 6, 5) #define PIN_PD3 99 #define PIN_PD3__GPIO PINMUX_PIN(PIN_PD3, 0, 0) #define PIN_PD3__SDMMC2_CMD PINMUX_PIN(PIN_PD3, 1, 1) #define PIN_PD3__FLEXCOM0_IO0 PINMUX_PIN(PIN_PD3, 2, 2) #define PIN_PD3__CANRX4 PINMUX_PIN(PIN_PD3, 3, 1) #define PIN_PD3__NANDRDY PINMUX_PIN(PIN_PD3, 4, 2) #define PIN_PD3__TIOB0 PINMUX_PIN(PIN_PD3, 5, 2) #define PIN_PD3__FLEXCOM8_IO1 PINMUX_PIN(PIN_PD3, 6, 5) #define PIN_PD4 100 #define PIN_PD4__GPIO PINMUX_PIN(PIN_PD4, 0, 0) #define PIN_PD4__SDMMC2_CK PINMUX_PIN(PIN_PD4, 1, 1) #define PIN_PD4__FLEXCOM0_IO1 PINMUX_PIN(PIN_PD4, 2, 2) #define PIN_PD4__CANTX5 PINMUX_PIN(PIN_PD4, 3, 1) #define PIN_PD4__NCS3_NANDCS PINMUX_PIN(PIN_PD4, 4, 2) #define PIN_PD4__TCLK0 PINMUX_PIN(PIN_PD4, 5, 2) #define PIN_PD4__FLEXCOM9_IO0 PINMUX_PIN(PIN_PD4, 6, 5) #define PIN_PD5 101 #define PIN_PD5__GPIO PINMUX_PIN(PIN_PD5, 0, 0) #define PIN_PD5__SDMMC2_DAT0 PINMUX_PIN(PIN_PD5, 1, 1) #define PIN_PD5__FLEXCOM0_IO2 PINMUX_PIN(PIN_PD5, 2, 2) #define PIN_PD5__CANRX5 PINMUX_PIN(PIN_PD5, 3, 1) #define PIN_PD5__NWE_NWR0_NANDWE PINMUX_PIN(PIN_PD5, 4, 2) #define PIN_PD5__TIOA1 PINMUX_PIN(PIN_PD5, 5, 2) #define PIN_PD5__FLEXCOM9_IO1 PINMUX_PIN(PIN_PD5, 6, 5) #define PIN_PD6 102 #define PIN_PD6__GPIO PINMUX_PIN(PIN_PD6, 0, 0) #define PIN_PD6__SDMMC2_DAT1 PINMUX_PIN(PIN_PD6, 1, 1) #define PIN_PD6__FLEXCOM0_IO3 PINMUX_PIN(PIN_PD6, 2, 2) #define PIN_PD6__SPDIF_RX PINMUX_PIN(PIN_PD6, 3, 3) #define PIN_PD6__NRD_NANDOE PINMUX_PIN(PIN_PD6, 4, 2) #define PIN_PD6__TIOB1 PINMUX_PIN(PIN_PD6, 5, 2) #define PIN_PD6__FLEXCOM10_IO0 PINMUX_PIN(PIN_PD6, 6, 5) #define PIN_PD7 103 #define PIN_PD7__GPIO PINMUX_PIN(PIN_PD7, 0, 0) #define PIN_PD7__SDMMC2_DAT2 PINMUX_PIN(PIN_PD7, 1, 1) #define PIN_PD7__FLEXCOM0_IO4 PINMUX_PIN(PIN_PD7, 2, 2) #define PIN_PD7__SPDIF_TX PINMUX_PIN(PIN_PD7, 2, 2) #define PIN_PD7__A21_NANDALE PINMUX_PIN(PIN_PD7, 4, 2) #define PIN_PD7__TCLK1 PINMUX_PIN(PIN_PD7, 5, 2) #define PIN_PD7__FLEXCOM10_IO1 PINMUX_PIN(PIN_PD7, 6, 5) #define PIN_PD8 104 #define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0) #define PIN_PD8__SDMMC2_DAT3 PINMUX_PIN(PIN_PD8, 1, 1) #define PIN_PD8__I2SMCC0_DIN0 PINMUX_PIN(PIN_PD8, 3, 1) #define PIN_PD8__A11_NANDCLE PINMUX_PIN(PIN_PD8, 4, 2) #define PIN_PD8__TIOA2 PINMUX_PIN(PIN_PD8, 5, 2) #define PIN_PD8__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD8, 6, 5) #define PIN_PD9 105 #define PIN_PD9__GPIO PINMUX_PIN(PIN_PD9, 0, 0) #define PIN_PD9__SDMMC2_WP PINMUX_PIN(PIN_PD9, 1, 1) #define PIN_PD9__I2SMCC0_DIN1 PINMUX_PIN(PIN_PD9, 3, 2) #define PIN_PD9__D0 PINMUX_PIN(PIN_PD9, 4, 2) #define PIN_PD9__TIOB2 PINMUX_PIN(PIN_PD9, 5, 2) #define PIN_PD9__FLEXCOM11_IO1 PINMUX_PIN(PIN_PD9, 6, 5) #define PIN_PD10 106 #define PIN_PD10__GPIO PINMUX_PIN(PIN_PD10, 0, 0) #define PIN_PD10__SDMMC2_CD PINMUX_PIN(PIN_PD10, 1, 1) #define PIN_PD10__PCK6 PINMUX_PIN(PIN_PD10, 2, 2) #define PIN_PD10__I2SMCC0_DIN2 PINMUX_PIN(PIN_PD10, 3, 2) #define PIN_PD10__D1 PINMUX_PIN(PIN_PD10, 4, 2) #define PIN_PD10__TCLK2 PINMUX_PIN(PIN_PD10, 5, 2) #define PIN_PD10__FLEXCOM0_IO0 PINMUX_PIN(PIN_PD10, 6, 3) #define PIN_PD11 107 #define PIN_PD11__GPIO PINMUX_PIN(PIN_PD11, 0, 0) #define PIN_PD11__SDMMC2_1V8SEL PINMUX_PIN(PIN_PD11, 1, 1) #define PIN_PD11__PCK7 PINMUX_PIN(PIN_PD11, 2, 2) #define PIN_PD11__I2SMCC0_DIN3 PINMUX_PIN(PIN_PD11, 3, 2) #define PIN_PD11__D2 PINMUX_PIN(PIN_PD11, 4, 2) #define PIN_PD11__TIOA3 PINMUX_PIN(PIN_PD11, 5, 2) #define PIN_PD11__FLEXCOM0_IO1 PINMUX_PIN(PIN_PD11, 6, 3) #define PIN_PD12 108 #define PIN_PD12__GPIO PINMUX_PIN(PIN_PD12, 0, 0) #define PIN_PD12__PCK1 PINMUX_PIN(PIN_PD12, 1, 2) #define PIN_PD12__FLEXCOM1_IO0 PINMUX_PIN(PIN_PD12, 2, 2) #define PIN_PD12__CANTX0 PINMUX_PIN(PIN_PD12, 4, 2) #define PIN_PD12__TIOB3 PINMUX_PIN(PIN_PD12, 5, 2) #define PIN_PD13 109 #define PIN_PD13__GPIO PINMUX_PIN(PIN_PD13, 0, 0) #define PIN_PD13__I2SMCC0_CK PINMUX_PIN(PIN_PD13, 1, 2) #define PIN_PD13__FLEXCOM1_IO1 PINMUX_PIN(PIN_PD13, 2, 2) #define PIN_PD13__PWML0 PINMUX_PIN(PIN_PD13, 3, 4) #define PIN_PD13__CANRX0 PINMUX_PIN(PIN_PD13, 4, 2) #define PIN_PD13__TCLK3 PINMUX_PIN(PIN_PD13, 5, 2) #define PIN_PD14 110 #define PIN_PD14__GPIO PINMUX_PIN(PIN_PD14, 0, 0) #define PIN_PD14__I2SMCC0_MCK PINMUX_PIN(PIN_PD14, 1, 2) #define PIN_PD14__FLEXCOM1_IO2 PINMUX_PIN(PIN_PD14, 2, 2) #define PIN_PD14__PWMH0 PINMUX_PIN(PIN_PD14, 3, 4) #define PIN_PD14__CANTX1 PINMUX_PIN(PIN_PD14, 4, 2) #define PIN_PD14__TIOA4 PINMUX_PIN(PIN_PD14, 5, 2) #define PIN_PD14__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD14, 6, 5) #define PIN_PD15 111 #define PIN_PD15__GPIO PINMUX_PIN(PIN_PD15, 0, 0) #define PIN_PD15__I2SMCC0_WS PINMUX_PIN(PIN_PD15, 1, 2) #define PIN_PD15__FLEXCOM1_IO3 PINMUX_PIN(PIN_PD15, 2, 2) #define PIN_PD15__PWML1 PINMUX_PIN(PIN_PD15, 3, 4) #define PIN_PD15__CANRX1 PINMUX_PIN(PIN_PD15, 4, 2) #define PIN_PD15__TIOB4 PINMUX_PIN(PIN_PD15, 5, 2) #define PIN_PD15__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD15, 6, 5) #define PIN_PD16 112 #define PIN_PD16__GPIO PINMUX_PIN(PIN_PD16, 0, 0) #define PIN_PD16__I2SMCC0_DOUT0 PINMUX_PIN(PIN_PD16, 1, 2) #define PIN_PD16__FLEXCOM1_IO4 PINMUX_PIN(PIN_PD16, 2, 2) #define PIN_PD16__PWMH1 PINMUX_PIN(PIN_PD16, 3, 4) #define PIN_PD16__CANTX2 PINMUX_PIN(PIN_PD16, 4, 2) #define PIN_PD16__TCLK4 PINMUX_PIN(PIN_PD16, 5, 2) #define PIN_PD16__FLEXCOM3_IO0 PINMUX_PIN(PIN_PD16, 6, 5) #define PIN_PD17 113 #define PIN_PD17__GPIO PINMUX_PIN(PIN_PD17, 0, 0) #define PIN_PD17__I2SMCC0_DOUT1 PINMUX_PIN(PIN_PD17, 1, 2) #define PIN_PD17__FLEXCOM2_IO0 PINMUX_PIN(PIN_PD17, 2, 2) #define PIN_PD17__PWML2 PINMUX_PIN(PIN_PD17, 3, 4) #define PIN_PD17__CANRX2 PINMUX_PIN(PIN_PD17, 4, 2) #define PIN_PD17__TIOA5 PINMUX_PIN(PIN_PD17, 5, 2) #define PIN_PD17__FLEXCOM3_IO1 PINMUX_PIN(PIN_PD17, 6, 5) #define PIN_PD18 114 #define PIN_PD18__GPIO PINMUX_PIN(PIN_PD18, 0, 0) #define PIN_PD18__I2SMCC0_DOUT2 PINMUX_PIN(PIN_PD18, 1, 2) #define PIN_PD18__FLEXCOM2_IO1 PINMUX_PIN(PIN_PD18, 2, 2) #define PIN_PD18__PWMH2 PINMUX_PIN(PIN_PD18, 3, 4) #define PIN_PD18__CANTX3 PINMUX_PIN(PIN_PD18, 4, 2) #define PIN_PD18__TIOB5 PINMUX_PIN(PIN_PD18, 5, 2) #define PIN_PD18__FLEXCOM4_IO0 PINMUX_PIN(PIN_PD18, 6, 5) #define PIN_PD19 115 #define PIN_PD19__GPIO PINMUX_PIN(PIN_PD19, 0, 0) #define PIN_PD19__I2SMCC0_DOUT3 PINMUX_PIN(PIN_PD19, 1, 2) #define PIN_PD19__FLEXCOM2_IO2 PINMUX_PIN(PIN_PD19, 2, 2) #define PIN_PD19__PWML3 PINMUX_PIN(PIN_PD19, 3, 4) #define PIN_PD19__CANRX3 PINMUX_PIN(PIN_PD19, 4, 2) #define PIN_PD19__TCLK5 PINMUX_PIN(PIN_PD19, 5, 2) #define PIN_PD19__FLEXCOM4_IO1 PINMUX_PIN(PIN_PD19, 6, 5) #define PIN_PD20 116 #define PIN_PD20__GPIO PINMUX_PIN(PIN_PD20, 0, 0) #define PIN_PD20__PCK0 PINMUX_PIN(PIN_PD20, 1, 3) #define PIN_PD20__FLEXCOM2_IO3 PINMUX_PIN(PIN_PD20, 2, 2) #define PIN_PD20__PWMH3 PINMUX_PIN(PIN_PD20, 3, 4) #define PIN_PD20__CANTX4 PINMUX_PIN(PIN_PD20, 4, 2) #define PIN_PD20__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD20, 6, 5) #define PIN_PD21 117 #define PIN_PD21__GPIO PINMUX_PIN(PIN_PD21, 0, 0) #define PIN_PD21__PCK1 PINMUX_PIN(PIN_PD21, 1, 3) #define PIN_PD21__FLEXCOM2_IO4 PINMUX_PIN(PIN_PD21, 2, 2) #define PIN_PD21__CANRX4 PINMUX_PIN(PIN_PD21, 4, 2) #define PIN_PD21__FLEXCOM5_IO1 PINMUX_PIN(PIN_PD21, 6, 5) #define PIN_PD21__G1_TXEN PINMUX_PIN(PIN_PD21, 7, 1) #define PIN_PD22 118 #define PIN_PD22__GPIO PINMUX_PIN(PIN_PD22, 0, 0) #define PIN_PD22__PDMC0_CLK PINMUX_PIN(PIN_PD22, 1, 2) #define PIN_PD22__PWMEXTRG0 PINMUX_PIN(PIN_PD22, 3, 4) #define PIN_PD22__RD1 PINMUX_PIN(PIN_PD22, 4, 2) #define PIN_PD22__CANTX5 PINMUX_PIN(PIN_PD22, 6, 2) #define PIN_PD22__G1_TX0 PINMUX_PIN(PIN_PD22, 7, 1) #define PIN_PD23 119 #define PIN_PD23__GPIO PINMUX_PIN(PIN_PD23, 0, 0) #define PIN_PD23__PDMC0_DS0 PINMUX_PIN(PIN_PD23, 1, 2) #define PIN_PD23__PWMEXTRG1 PINMUX_PIN(PIN_PD23, 3, 4) #define PIN_PD23__RF1 PINMUX_PIN(PIN_PD23, 4, 2) #define PIN_PD23__ISC_MCK PINMUX_PIN(PIN_PD23, 5, 2) #define PIN_PD23__CANRX5 PINMUX_PIN(PIN_PD23, 6, 2) #define PIN_PD23__G1_TX1 PINMUX_PIN(PIN_PD23, 7, 1) #define PIN_PD24 120 #define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0) #define PIN_PD24__PDMC0_DS1 PINMUX_PIN(PIN_PD24, 1, 2) #define PIN_PD24__PWMFI0 PINMUX_PIN(PIN_PD24, 3, 4) #define PIN_PD24__RK1 PINMUX_PIN(PIN_PD24, 4, 2) #define PIN_PD24__ISC_D0 PINMUX_PIN(PIN_PD24, 5, 2) #define PIN_PD24__G1_RXDV PINMUX_PIN(PIN_PD24, 7, 1) #define PIN_PD25 121 #define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0) #define PIN_PD25__PDMC1_CLK PINMUX_PIN(PIN_PD25, 1, 2) #define PIN_PD25__FLEXCOM5_IO0 PINMUX_PIN(PIN_PD25, 2, 2) #define PIN_PD25__PWMFI1 PINMUX_PIN(PIN_PD25, 3, 4) #define PIN_PD25__TD1 PINMUX_PIN(PIN_PD25, 4, 2) #define PIN_PD25__ISC_D1 PINMUX_PIN(PIN_PD25, 5, 2) #define PIN_PD25__G1_RX0 PINMUX_PIN(PIN_PD25, 7, 1) #define PIN_PD26 122 #define PIN_PD26__GPIO PINMUX_PIN(PIN_PD26, 0, 0) #define PIN_PD26__PDMC1_DS0 PINMUX_PIN(PIN_PD26, 1, 2) #define PIN_PD26__FLEXCOM5_IO1 PINMUX_PIN(PIN_PD26, 2, 2) #define PIN_PD26__ADTRG PINMUX_PIN(PIN_PD26, 3, 3) #define PIN_PD26__TF1 PINMUX_PIN(PIN_PD26, 4, 2) #define PIN_PD26__ISC_D2 PINMUX_PIN(PIN_PD26, 5, 2) #define PIN_PD26__G1_RX1 PINMUX_PIN(PIN_PD26, 7, 1) #define PIN_PD27 123 #define PIN_PD27__GPIO PINMUX_PIN(PIN_PD27, 0, 0) #define PIN_PD27__PDMC1_DS1 PINMUX_PIN(PIN_PD27, 1, 2) #define PIN_PD27__FLEXCOM5_IO2 PINMUX_PIN(PIN_PD27, 2, 2) #define PIN_PD27__TIOA0 PINMUX_PIN(PIN_PD27, 3, 3) #define PIN_PD27__TK1 PINMUX_PIN(PIN_PD27, 4, 2) #define PIN_PD27__ISC_D3 PINMUX_PIN(PIN_PD27, 5, 2) #define PIN_PD27__G1_RXER PINMUX_PIN(PIN_PD27, 7, 1) #define PIN_PD28 124 #define PIN_PD28__GPIO PINMUX_PIN(PIN_PD28, 0, 0) #define PIN_PD28__RD0 PINMUX_PIN(PIN_PD28, 1, 2) #define PIN_PD28__FLEXCOM5_IO3 PINMUX_PIN(PIN_PD28, 2, 2) #define PIN_PD28__TIOB0 PINMUX_PIN(PIN_PD28, 3, 3) #define PIN_PD28__I2SMCC1_CK PINMUX_PIN(PIN_PD28, 4, 2) #define PIN_PD28__ISC_D4 PINMUX_PIN(PIN_PD28, 5, 2) #define PIN_PD28__PWML3 PINMUX_PIN(PIN_PD28, 6, 5) #define PIN_PD28__G1_MDC PINMUX_PIN(PIN_PD28, 7, 1) #define PIN_PD29 125 #define PIN_PD29__GPIO PINMUX_PIN(PIN_PD29, 0, 0) #define PIN_PD29__RF0 PINMUX_PIN(PIN_PD29, 1, 2) #define PIN_PD29__FLEXCOM5_IO4 PINMUX_PIN(PIN_PD29, 2, 2) #define PIN_PD29__TCLK0 PINMUX_PIN(PIN_PD29, 3, 3) #define PIN_PD29__I2SMCC1_WS PINMUX_PIN(PIN_PD29, 4, 2) #define PIN_PD29__ISC_D5 PINMUX_PIN(PIN_PD29, 5, 2) #define PIN_PD29__PWMH3 PINMUX_PIN(PIN_PD29, 6, 5) #define PIN_PD29__G1_MDIO PINMUX_PIN(PIN_PD29, 7, 1) #define PIN_PD30 126 #define PIN_PD30__GPIO PINMUX_PIN(PIN_PD30, 0, 0) #define PIN_PD30__RK0 PINMUX_PIN(PIN_PD30, 1, 2) #define PIN_PD30__FLEXCOM6_IO0 PINMUX_PIN(PIN_PD30, 2, 2) #define PIN_PD30__TIOA1 PINMUX_PIN(PIN_PD30, 3, 3) #define PIN_PD30__I2SMCC1_MCK PINMUX_PIN(PIN_PD30, 4, 2) #define PIN_PD30__ISC_D6 PINMUX_PIN(PIN_PD30, 5, 2) #define PIN_PD30__PWMEXTRG0 PINMUX_PIN(PIN_PD30, 6, 5) #define PIN_PD30__G1_TXCK PINMUX_PIN(PIN_PD30, 7, 1) #define PIN_PD31 127 #define PIN_PD31__GPIO PINMUX_PIN(PIN_PD31, 0, 0) #define PIN_PD31__TD0 PINMUX_PIN(PIN_PD31, 1, 2) #define PIN_PD31__FLEXCOM6_IO1 PINMUX_PIN(PIN_PD31, 2, 2) #define PIN_PD31__TIOB1 PINMUX_PIN(PIN_PD31, 3, 3) #define PIN_PD31__I2SMCC1_DOUT0 PINMUX_PIN(PIN_PD31, 4, 2) #define PIN_PD31__ISC_D7 PINMUX_PIN(PIN_PD31, 5, 2) #define PIN_PD31__PWM_EXTRG1 PINMUX_PIN(PIN_PD31, 6, 5) #define PIN_PD31__G1_TX2 PINMUX_PIN(PIN_PD31, 7, 1) #define PIN_PE0 128 #define PIN_PE0__GPIO PINMUX_PIN(PIN_PE0, 0, 0) #define PIN_PE0__TF0 PINMUX_PIN(PIN_PE0, 1, 2) #define PIN_PE0__FLEXCOM6_IO2 PINMUX_PIN(PIN_PE0, 2, 2) #define PIN_PE0__TCLK1 PINMUX_PIN(PIN_PE0, 3, 3) #define PIN_PE0__I2SMCC1_DOUT1 PINMUX_PIN(PIN_PE0, 4, 2) #define PIN_PE0__ISC_HSYNC PINMUX_PIN(PIN_PE0, 5, 2) #define PIN_PE0__PWMFI0 PINMUX_PIN(PIN_PE0, 6, 5) #define PIN_PE0__G1_TX3 PINMUX_PIN(PIN_PE0, 7, 1) #define PIN_PE1 129 #define PIN_PE1__GPIO PINMUX_PIN(PIN_PE1, 0, 0) #define PIN_PE1__TK0 PINMUX_PIN(PIN_PE1, 1, 2) #define PIN_PE1__FLEXCOM6_IO3 PINMUX_PIN(PIN_PE1, 2, 2) #define PIN_PE1__TIOA2 PINMUX_PIN(PIN_PE1, 3, 3) #define PIN_PE1__I2SMCC1_DOUT2 PINMUX_PIN(PIN_PE1, 4, 2) #define PIN_PE1__ISC_VSYNC PINMUX_PIN(PIN_PE1, 5, 2) #define PIN_PE1__PWMFI1 PINMUX_PIN(PIN_PE1, 6, 5) #define PIN_PE1__G1_RX2 PINMUX_PIN(PIN_PE1, 7, 1) #define PIN_PE2 130 #define PIN_PE2__GPIO PINMUX_PIN(PIN_PE2, 0, 0) #define PIN_PE2__PWML0 PINMUX_PIN(PIN_PE2, 1, 5) #define PIN_PE2__FLEXCOM6_IO4 PINMUX_PIN(PIN_PE2, 2, 2) #define PIN_PE2__TIOB2 PINMUX_PIN(PIN_PE2, 3, 3) #define PIN_PE2__I2SMCC1_DOUT3 PINMUX_PIN(PIN_PE2, 4, 2) #define PIN_PE2__ISC_FIELD PINMUX_PIN(PIN_PE2, 5, 2) #define PIN_PE2__G1_RX3 PINMUX_PIN(PIN_PE2, 7, 1) #define PIN_PE3 131 #define PIN_PE3__GPIO PINMUX_PIN(PIN_PE3, 0, 0) #define PIN_PE3__PWMH0 PINMUX_PIN(PIN_PE3, 1, 5) #define PIN_PE3__FLEXCOM0_IO0 PINMUX_PIN(PIN_PE3, 2, 4) #define PIN_PE3__TCLK2 PINMUX_PIN(PIN_PE3, 3, 3) #define PIN_PE3__I2SMCC1_DIN0 PINMUX_PIN(PIN_PE3, 4, 2) #define PIN_PE3__ISC_PCK PINMUX_PIN(PIN_PE3, 5, 2) #define PIN_PE3__G1_RXCK PINMUX_PIN(PIN_PE3, 7, 1) #define PIN_PE4 132 #define PIN_PE4__GPIO PINMUX_PIN(PIN_PE4, 0, 0) #define PIN_PE4__PWML1 PINMUX_PIN(PIN_PE4, 1, 5) #define PIN_PE4__FLEXCOM0_IO1 PINMUX_PIN(PIN_PE4, 2, 4) #define PIN_PE4__TIOA3 PINMUX_PIN(PIN_PE4, 3, 3) #define PIN_PE4__I2SMCC1_DIN1 PINMUX_PIN(PIN_PE4, 4, 2) #define PIN_PE4__ISC_D8 PINMUX_PIN(PIN_PE4, 5, 2) #define PIN_PE4__G1_TXER PINMUX_PIN(PIN_PE4, 7, 1) #define PIN_PE5 133 #define PIN_PE5__GPIO PINMUX_PIN(PIN_PE5, 0, 0) #define PIN_PE5__PWMH1 PINMUX_PIN(PIN_PE5, 1, 5) #define PIN_PE5__FLEXCOM0_IO2 PINMUX_PIN(PIN_PE5, 2, 4) #define PIN_PE5__TIOB3 PINMUX_PIN(PIN_PE5, 3, 3) #define PIN_PE5__I2SMCC1_DIN2 PINMUX_PIN(PIN_PE5, 4, 2) #define PIN_PE5__ISC_D9 PINMUX_PIN(PIN_PE5, 5, 2) #define PIN_PE5__G1_COL PINMUX_PIN(PIN_PE5, 7, 1) #define PIN_PE6 134 #define PIN_PE6__GPIO PINMUX_PIN(PIN_PE6, 0, 0) #define PIN_PE6__PWML2 PINMUX_PIN(PIN_PE6, 1, 5) #define PIN_PE6__FLEXCOM0_IO3 PINMUX_PIN(PIN_PE6, 2, 4) #define PIN_PE6__TCLK3 PINMUX_PIN(PIN_PE6, 3, 3) #define PIN_PE6__I2SMCC1_DIN3 PINMUX_PIN(PIN_PE6, 4, 2) #define PIN_PE6__ISC_D10 PINMUX_PIN(PIN_PE6, 5, 2) #define PIN_PE6__G1_CRS PINMUX_PIN(PIN_PE6, 7, 1) #define PIN_PE7 135 #define PIN_PE7__GPIO PINMUX_PIN(PIN_PE7, 0, 0) #define PIN_PE7__PWMH2 PINMUX_PIN(PIN_PE7, 1, 5) #define PIN_PE7__FLEXCOM0_IO4 PINMUX_PIN(PIN_PE7, 2, 4) #define PIN_PE7__TIOA4 PINMUX_PIN(PIN_PE7, 3, 3) #define PIN_PE7__ISC_D11 PINMUX_PIN(PIN_PE7, 5, 2) #define PIN_PE7__G1_TSUCOMP PINMUX_PIN(PIN_PE7, 7, 1) optee_os-4.3.0/core/arch/arm/dts/sama7g5.dtsi000066400000000000000000001040251464416617300207200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * sama7g5.dtsi - Device Tree Include file for SAMA7G5 family SoC * * Copyright (C) 2020 Microchip Technology, Inc. and its subsidiaries * * Author: Eugen Hristev * Author: Claudiu Beznea */ #include #include #include #include #include #include / { model = "Microchip SAMA7G5 family SoC"; compatible = "microchip,sama7g5"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&gic>; cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x0>; clocks = <&pmc PMC_TYPE_CORE PMC_CPUPLL>; clock-names = "cpu"; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; /* min followed by max */ }; }; cpu_opp_table: opp-table { compatible = "operating-points-v2"; opp-90000000 { opp-hz = /bits/ 64 <90000000>; opp-microvolt = <1050000 1050000 1225000>; clock-latency-ns = <320000>; }; opp-250000000 { opp-hz = /bits/ 64 <250000000>; opp-microvolt = <1050000 1050000 1225000>; clock-latency-ns = <320000>; }; opp-600000000 { opp-hz = /bits/ 64 <600000000>; opp-microvolt = <1050000 1050000 1225000>; clock-latency-ns = <320000>; opp-suspend; }; opp-800000000 { opp-hz = /bits/ 64 <800000000>; opp-microvolt = <1150000 1125000 1225000>; clock-latency-ns = <320000>; }; opp-1000000002 { opp-hz = /bits/ 64 <1000000002>; opp-microvolt = <1250000 1225000 1300000>; clock-latency-ns = <320000>; }; }; thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive = <1000>; polling-delay = <5000>; thermal-sensors = <&thermal_sensor>; trips { cpu_normal: cpu-alert0 { temperature = <90000>; hysteresis = <0>; type = "passive"; }; cpu_hot: cpu-alert1 { temperature = <95000>; hysteresis = <0>; type = "passive"; }; cpu_critical: cpu-critical { temperature = <100000>; hysteresis = <0>; type = "critical"; }; }; cooling-maps { map0 { trip = <&cpu_normal>; }; map1 { trip = <&cpu_hot>; }; }; }; }; clocks { slow_xtal: slow_xtal { compatible = "fixed-clock"; #clock-cells = <0>; }; main_xtal: main_xtal { compatible = "fixed-clock"; #clock-cells = <0>; }; usb_clk: usb_clk { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <48000000>; }; }; utmi_clk: utmi-clk { compatible = "microchip,sama7g5-utmi-clk"; sfr-phandle = <&sfr>; #clock-cells = <1>; clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>; clock-names = "utmi_clk"; reset-names = "usb0_reset", "usb1_reset", "usb2_reset"; status = "disabled"; }; utmi { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <0>; usb_phy0: phy@0 { compatible = "microchip,sama7g5-usb-phy"; sfr-phandle = <&sfr>; reg = <0>; clock-names = "utmi_clk"; status = "disabled"; #phy-cells = <0>; }; usb_phy1: phy@1 { compatible = "microchip,sama7g5-usb-phy"; sfr-phandle = <&sfr>; reg = <1>; clock-names = "utmi_clk"; status = "disabled"; #phy-cells = <0>; }; usb_phy2: phy@2 { compatible = "microchip,sama7g5-usb-phy"; sfr-phandle = <&sfr>; reg = <2>; clock-names = "utmi_clk"; status = "disabled"; #phy-cells = <0>; }; }; vddout25: fixed-regulator-vddout25 { compatible = "regulator-fixed"; regulator-name = "VDDOUT25"; regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2500000>; regulator-boot-on; status = "disabled"; }; ns_sram: sram@100000 { compatible = "atmel,sama5d2-sram", "mmio-sram"; #address-cells = <1>; #size-cells = <1>; reg = <0x100000 0x3400>; ranges; status = "disabled"; secure-status = "okay"; }; thermal_sensor: thermal-sensor { compatible = "generic-adc-thermal"; #thermal-sensor-cells = <0>; io-channel-names = "sensor-channel"; status = "disabled"; }; soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; usb0: gadget@200000 { #address-cells = <1>; #size-cells = <0>; compatible = "microchip,sama7g5-udc"; reg = <0x00200000 0x100000 0xe0814000 0x400>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 104>, <&usb_clk>; clock-names = "pclk", "hclk"; status = "disabled"; }; usb1: gadget@300000 { #address-cells = <1>; #size-cells = <0>; compatible = "microchip,sama7g5-udc"; reg = <0x00300000 0x100000 0xe0818000 0x400>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 105>, <&usb_clk>; clock-names = "pclk", "hclk"; status = "disabled"; }; usb2: ohci@400000 { compatible = "microchip,sama7g5-ohci", "usb-ohci"; reg = <0x00400000 0x100000>; interrupts = ; clock-names = "ohci_clk", "hclk", "uhpck"; status = "disabled"; }; usb3: ehci@500000 { compatible = "atmel,at91sam9g45-ehci", "usb-ehci"; reg = <0x00500000 0x100000>; interrupts = ; clocks = <&usb_clk>, <&pmc PMC_TYPE_PERIPHERAL 106>; clock-names = "usb_clk", "ehci_clk"; status = "disabled"; }; nfc_sram: sram@600000 { compatible = "mmio-sram"; no-memory-wc; reg = <0x00600000 0x2400>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x00600000 0x2400>; }; nfc_io: nfc-io@10000000 { compatible = "atmel,sama5d3-nfc-io", "syscon"; reg = <0x10000000 0x8000000>; }; ebi: ebi@40000000 { compatible = "atmel,sama5d3-ebi"; #address-cells = <2>; #size-cells = <1>; atmel,smc = <&hsmc>; reg = <0x40000000 0x20000000>; ranges = <0x0 0x0 0x40000000 0x8000000 0x1 0x0 0x48000000 0x8000000 0x2 0x0 0x50000000 0x8000000 0x3 0x0 0x58000000 0x8000000>; clocks = <&pmc PMC_TYPE_CORE PMC_MCK1>; status = "disabled"; nand_controller: nand-controller { compatible = "atmel,sama5d3-nand-controller"; atmel,nfc-sram = <&nfc_sram>; atmel,nfc-io = <&nfc_io>; ecc-engine = <&pmecc>; #address-cells = <2>; #size-cells = <1>; ranges; status = "disabled"; }; }; securam: sram@e0000000 { compatible = "microchip,sama7g5-securam", "atmel,sama5d2-securam", "mmio-sram"; reg = <0xe0000000 0x4000>; clocks = <&pmc PMC_TYPE_PERIPHERAL 18>; #address-cells = <1>; #size-cells = <1>; ranges = <0 0xe0000000 0x4000>; no-memory-wc; status = "disabled"; secure-status = "okay"; }; secumod: secumod@e0004000 { compatible = "microchip,sama7g5-secumod", "atmel,sama5d2-secumod", "syscon"; reg = <0xe0004000 0x4000>; gpio-controller; #gpio-cells = <2>; status = "disabled"; secure-status = "okay"; }; sfrbu: sfr@e0008000 { compatible = "microchip,sama7g5-sfrbu", "atmel,sama5d2-sfrbu", "syscon"; reg = <0xe0008000 0x20>; }; pioA: pinctrl@e0014000 { compatible = "microchip,sama7g5-pinctrl"; reg = <0xe0014000 0x800>; interrupts = , , , , ; interrupt-controller; #interrupt-cells = <2>; gpio-controller; #gpio-cells = <2>; clocks = <&pmc PMC_TYPE_PERIPHERAL 11>; status = "disabled"; secure-status = "okay"; }; pmc: pmc@e0018000 { compatible = "microchip,sama7g5-pmc", "syscon"; reg = <0xe0018000 0x200>; interrupts = ; #clock-cells = <2>; clocks = <&clk32k 1>, <&clk32k 0>, <&main_xtal>; clock-names = "td_slck", "md_slck", "main_xtal"; status = "disabled"; secure-status = "okay"; }; reset_controller: reset-controller@e001d000 { compatible = "microchip,sama7g5-rstc"; reg = <0xe001d000 0xc>, <0xe001d0e4 0x4>; #reset-cells = <1>; clocks = <&clk32k 0>; status = "disabled"; secure-status = "okay"; }; shdwc: shdwc@e001d010 { compatible = "microchip,sama7g5-shdwc", "syscon"; reg = <0xe001d010 0x10>; clocks = <&clk32k 0>; #address-cells = <1>; #size-cells = <0>; atmel,wakeup-rtc-timer; atmel,wakeup-rtt-timer; status = "disabled"; secure-status = "okay"; }; rtt: rtc@e001d020 { compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt"; reg = <0xe001d020 0x30>; interrupts = ; clocks = <&clk32k 0>; }; clk32k: clock-controller@e001d050 { compatible = "microchip,sama7g5-sckc", "microchip,sam9x60-sckc"; reg = <0xe001d050 0x4>; clocks = <&slow_xtal>; #clock-cells = <1>; status = "disabled"; secure-status = "okay"; }; gpbr: gpbr@e001d060 { compatible = "microchip,sama7g5-gpbr", "syscon"; reg = <0xe001d060 0x48>; }; rtc: rtc@e001d0a8 { compatible = "microchip,sama7g5-rtc", "microchip,sam9x60-rtc"; reg = <0xe001d0a8 0x30>; interrupts = ; clocks = <&clk32k 1>; status = "disabled"; secure-status = "okay"; }; ps_wdt: watchdog@e001d180 { compatible = "microchip,sama7g5-wdt"; reg = <0xe001d180 0x24>; interrupts = ; clocks = <&clk32k 0>; status = "disabled"; secure-status = "okay"; }; chipid@e0020000 { compatible = "microchip,sama7g5-chipid"; reg = <0xe0020000 0x8>; }; tcb1: timer@e0800000 { compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; #address-cells = <1>; #size-cells = <0>; reg = <0xe0800000 0x100>; interrupts = , , ; clocks = <&pmc PMC_TYPE_PERIPHERAL 91>, <&pmc PMC_TYPE_PERIPHERAL 92>, <&pmc PMC_TYPE_PERIPHERAL 93>, <&clk32k 1>; clock-names = "t0_clk", "t1_clk", "t2_clk", "slow_clk"; status = "disabled"; secure-status = "okay"; }; hsmc: hsmc@e0808000 { compatible = "atmel,sama5d2-smc", "syscon", "simple-mfd"; reg = <0xe0808000 0x1000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 21>; #address-cells = <1>; #size-cells = <1>; ranges; pmecc: ecc-engine@e0808070 { compatible = "atmel,sama5d2-pmecc"; reg = <0xe0808070 0x490>, <0xe0808500 0x200>; }; }; qspi0: spi@e080c000 { compatible = "microchip,sama7g5-ospi"; reg = <0xe080c000 0x400>, <0x20000000 0x10000000>; reg-names = "qspi_base", "qspi_mmap"; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(41)>, <&dma0 AT91_XDMAC_DT_PERID(40)>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 78>, <&pmc PMC_TYPE_GCK 78>; clock-names = "pclk", "gclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 78>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <133000000>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; qspi1: spi@e0810000 { compatible = "microchip,sama7g5-qspi"; reg = <0xe0810000 0x400>, <0x30000000 0x10000000>; reg-names = "qspi_base", "qspi_mmap"; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(43)>, <&dma0 AT91_XDMAC_DT_PERID(42)>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 79>, <&pmc PMC_TYPE_GCK 79>; clock-names = "pclk", "gclk"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; can0: can@e0828000 { compatible = "bosch,m_can"; reg = <0xe0828000 0x100>, <0x100000 0x7800>; reg-names = "m_can", "message_ram"; interrupts = ; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 61>, <&pmc PMC_TYPE_GCK 61>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 61>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x3400 0 0 64 0 0 32 32>; status = "disabled"; }; can1: can@e082c000 { compatible = "bosch,m_can"; reg = <0xe082c000 0x100>, <0x100000 0xbc00>; reg-names = "m_can", "message_ram"; interrupts = ; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 62>, <&pmc PMC_TYPE_GCK 62>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 62>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x7800 0 0 64 0 0 32 32>; status = "disabled"; }; can2: can@e0830000 { compatible = "bosch,m_can"; reg = <0xe0830000 0x100>, <0x100000 0x10000>; reg-names = "m_can", "message_ram"; interrupts = ; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 63>, <&pmc PMC_TYPE_GCK 63>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 63>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0xbc00 0 0 64 0 0 32 32>; status = "disabled"; }; can3: can@e0834000 { compatible = "bosch,m_can"; reg = <0xe0834000 0x100>, <0x110000 0x4400>; reg-names = "m_can", "message_ram"; interrupts = ; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 64>, <&pmc PMC_TYPE_GCK 64>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 64>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>; status = "disabled"; }; can4: can@e0838000 { compatible = "bosch,m_can"; reg = <0xe0838000 0x100>, <0x110000 0x8800>; reg-names = "m_can", "message_ram"; interrupts = ; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 65>, <&pmc PMC_TYPE_GCK 65>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 65>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x4400 0 0 64 0 0 32 32>; status = "disabled"; }; can5: can@e083c000 { compatible = "bosch,m_can"; reg = <0xe083c000 0x100>, <0x110000 0xcc00>; reg-names = "m_can", "message_ram"; interrupts = ; interrupt-names = "int0", "int1"; clocks = <&pmc PMC_TYPE_PERIPHERAL 66>, <&pmc PMC_TYPE_GCK 66>; clock-names = "hclk", "cclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 66>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clock-rates = <40000000>; bosch,mram-cfg = <0x8800 0 0 64 0 0 32 32>; status = "disabled"; }; adc: adc@e1000000 { compatible = "microchip,sama7g5-adc"; reg = <0xe1000000 0x200>; interrupts = ; clocks = <&pmc PMC_TYPE_GCK 26>; assigned-clocks = <&pmc PMC_TYPE_GCK 26>; assigned-clock-rates = <100000000>; clock-names = "adc_clk"; dmas = <&dma0 AT91_XDMAC_DT_PERID(0)>; dma-names = "rx"; atmel,min-sample-rate-hz = <200000>; atmel,max-sample-rate-hz = <20000000>; atmel,startup-time-ms = <4>; #io-channel-cells = <1>; nvmem-cells = <&temperature_calib>; nvmem-cell-names = "temperature_calib"; status = "disabled"; }; sdmmc0: mmc@e1204000 { compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci"; reg = <0xe1204000 0x4000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 80>, <&pmc PMC_TYPE_GCK 80>; clock-names = "hclock", "multclk"; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clocks = <&pmc PMC_TYPE_GCK 80>; assigned-clock-rates = <200000000>; microchip,sdcal-inverted; status = "disabled"; }; sdmmc1: mmc@e1208000 { compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci"; reg = <0xe1208000 0x4000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 81>, <&pmc PMC_TYPE_GCK 81>; clock-names = "hclock", "multclk"; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clocks = <&pmc PMC_TYPE_GCK 81>; assigned-clock-rates = <200000000>; microchip,sdcal-inverted; status = "disabled"; }; sdmmc2: mmc@e120c000 { compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci"; reg = <0xe120c000 0x4000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 82>, <&pmc PMC_TYPE_GCK 82>; clock-names = "hclock", "multclk"; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>; assigned-clocks = <&pmc PMC_TYPE_GCK 82>; assigned-clock-rates = <200000000>; microchip,sdcal-inverted; status = "disabled"; }; csi2host: csi2host@e1400000 { compatible = "snps,dw-csi"; #address-cells = <1>; #size-cells = <0>; reg = <0xe1400000 0x7FF>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 33>, <&pmc PMC_TYPE_GCK 33>; clock-names = "perclk", "phyclk"; assigned-clocks = <&pmc PMC_TYPE_GCK 33>; assigned-clock-rates = <26600000>; snps,output-type = <1>; phys = <&csi_dphy>; status = "disabled"; port@1 { reg = <1>; csi2host_in: endpoint { }; }; port@2 { reg = <2>; csi2host_out: endpoint { }; }; }; csi_dphy: dphy@e1400040 { compatible = "snps,dw-dphy-rx"; #phy-cells = <0>; bus-width = <8>; snps,dphy-frequency = <900000>; snps,phy_type = <0>; reg = <0xe1400040 0x20>; status = "disabled"; }; csi2dc: csi2dc@e1404000 { compatible = "microchip,sama7g5-csi2dc"; reg = <0xe1404000 0x500>; clocks = <&pmc PMC_TYPE_PERIPHERAL 34>, <&xisc>; clock-names = "pclk", "scck"; assigned-clocks = <&xisc>; assigned-clock-rates = <266000000>; status = "disabled"; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; csi2dc_in: endpoint { }; }; port@1 { reg = <1>; csi2dc_out: endpoint { bus-width = <14>; hsync-active = <1>; vsync-active = <1>; remote-endpoint = <&xisc_in>; }; }; }; }; xisc: xisc@e1408000 { compatible = "microchip,sama7g5-isc"; reg = <0xe1408000 0x2000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 56>; clock-names = "hclock"; #clock-cells = <0>; clock-output-names = "isc-mck"; status = "disabled"; port { xisc_in: endpoint { bus-type = <5>; /* Parallel */ bus-width = <14>; hsync-active = <1>; vsync-active = <1>; remote-endpoint = <&csi2dc_out>; }; }; }; pwm: pwm@e1604000 { compatible = "microchip,sama7g5-pwm", "atmel,sama5d2-pwm"; reg = <0xe1604000 0x4000>; interrupts = ; #pwm-cells = <3>; clocks = <&pmc PMC_TYPE_PERIPHERAL 77>; status = "disabled"; }; pdmc0: sound@e1608000 { compatible = "microchip,sama7g5-pdmc"; reg = <0xe1608000 0x1000>; interrupts = ; #sound-dai-cells = <0>; dmas = <&dma0 AT91_XDMAC_DT_PERID(37)>; dma-names = "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 68>, <&pmc PMC_TYPE_GCK 68>; clock-names = "pclk", "gclk"; sound-name-prefix = "PDMC0"; status = "disabled"; }; pdmc1: sound@e160c000 { compatible = "microchip,sama7g5-pdmc"; reg = <0xe160c000 0x1000>; interrupts = ; #sound-dai-cells = <0>; dmas = <&dma0 AT91_XDMAC_DT_PERID(38)>; dma-names = "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 69>, <&pmc PMC_TYPE_GCK 69>; clock-names = "pclk", "gclk"; sound-name-prefix = "PDMC1"; status = "disabled"; }; asrc: sound@e1610000 { compatible = "microchip,sama7g5-asrc"; reg = <0xe1610000 0x1000>; interrupts = ; #sound-dai-cells = <1>; dmas = <&dma0 AT91_XDMAC_DT_PERID(55)>, <&dma0 AT91_XDMAC_DT_PERID(56)>, <&dma0 AT91_XDMAC_DT_PERID(57)>, <&dma0 AT91_XDMAC_DT_PERID(58)>, <&dma0 AT91_XDMAC_DT_PERID(59)>, <&dma0 AT91_XDMAC_DT_PERID(60)>, <&dma0 AT91_XDMAC_DT_PERID(61)>, <&dma0 AT91_XDMAC_DT_PERID(62)>; dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3"; clocks = <&pmc PMC_TYPE_PERIPHERAL 30>, <&pmc PMC_TYPE_GCK 30>; clock-names = "pclk", "gclk"; microchip,triggers = <&i2s0>, <&i2s1>, <&pdmc0>, <&pdmc1>, <&ssc0>, <&ssc1>, <&spdiftx>, <&spdifrx>; microchip,trigger-indexes = <1>, <2>, <3>, <4>, <5>, <8>, <9>, <10>; assigned-clocks = <&pmc PMC_TYPE_GCK 30>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_AUDIOPMCPLL>; status = "disabled"; }; spdifrx: spdifrx@e1614000 { #sound-dai-cells = <0>; compatible = "microchip,sama7g5-spdifrx"; reg = <0xe1614000 0x4000>; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(49)>; dma-names = "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 84>, <&pmc PMC_TYPE_GCK 84>; clock-names = "pclk", "gclk"; status = "disabled"; sound-name-prefix = "SPDIFRX0"; }; spdiftx: spdiftx@e1618000 { #sound-dai-cells = <0>; compatible = "microchip,sama7g5-spdiftx"; reg = <0xe1618000 0x4000>; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(50)>; dma-names = "tx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 85>, <&pmc PMC_TYPE_GCK 85>; clock-names = "pclk", "gclk"; sound-name-prefix = "SPDIFTX0"; }; i2s0: i2s@e161c000 { compatible = "microchip,sama7g5-i2smcc"; #sound-dai-cells = <0>; reg = <0xe161c000 0x4000>; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(34)>, <&dma0 AT91_XDMAC_DT_PERID(33)>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 57>, <&pmc PMC_TYPE_GCK 57>; clock-names = "pclk", "gclk"; sound-name-prefix = "I2SMCC0"; status = "disabled"; }; i2s1: i2s@e1620000 { compatible = "microchip,sama7g5-i2smcc"; #sound-dai-cells = <0>; reg = <0xe1620000 0x4000>; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(36)>, <&dma0 AT91_XDMAC_DT_PERID(35)>; dma-names = "tx", "rx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 58>, <&pmc PMC_TYPE_GCK 58>; clock-names = "pclk", "gclk"; sound-name-prefix = "I2SMCC1"; status = "disabled"; }; sfr: sfr@e1624000 { compatible = "microchip,sama7g5-sfr", "syscon"; reg = <0xe1624000 0x4000>; }; eic: interrupt-controller@e1628000 { compatible = "microchip,sama7g5-eic"; reg = <0xe1628000 0xec>; interrupt-parent = <&gic>; interrupt-controller; #interrupt-cells = <2>; interrupts = , ; clocks = <&pmc PMC_TYPE_PERIPHERAL 37>; clock-names = "pclk"; status = "disabled"; }; pit64b0: timer@e1800000 { compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b"; reg = <0xe1800000 0x4000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 70>, <&pmc PMC_TYPE_GCK 70>; clock-names = "pclk", "gclk"; }; pit64b1: timer@e1804000 { compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b"; reg = <0xe1804000 0x4000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 71>, <&pmc PMC_TYPE_GCK 71>; clock-names = "pclk", "gclk"; }; ssc0: sound@e180c000 { compatible = "atmel,at91sam9g45-ssc"; reg = <0xe180c000 0x1000>; #sound-dai-cells = <0>; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(44)>, <&dma0 AT91_XDMAC_DT_PERID(45)>; dma-names = "rx", "tx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 86>; clock-names = "pclk"; sound-name-prefix = "SSC0"; status = "disabled"; }; aes: crypto@e1810000 { compatible = "atmel,at91sam9g46-aes"; reg = <0xe1810000 0x100>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 27>; clock-names = "aes_clk"; dmas = <&dma0 AT91_XDMAC_DT_PERID(1)>, <&dma0 AT91_XDMAC_DT_PERID(2)>; dma-names = "tx", "rx"; status = "okay"; }; sha: crypto@e1814000 { compatible = "atmel,at91sam9g46-sha"; reg = <0xe1814000 0x100>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 83>; clock-names = "sha_clk"; dmas = <&dma0 AT91_XDMAC_DT_PERID(48)>; dma-names = "tx"; status = "okay"; }; flx0: flexcom@e1818000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe1818000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe1818000 0x800>; status = "disabled"; uart0: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 38>; clock-names = "usart"; dmas = <&dma1 AT91_XDMAC_DT_PERID(6)>, <&dma1 AT91_XDMAC_DT_PERID(5)>; dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; status = "disabled"; }; }; flx1: flexcom@e181c000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe181c000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe181c000 0x800>; status = "disabled"; i2c1: i2c@600 { compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 39>; atmel,fifo-size = <32>; dmas = <&dma0 AT91_XDMAC_DT_PERID(8)>, <&dma0 AT91_XDMAC_DT_PERID(7)>; dma-names = "tx", "rx"; status = "disabled"; }; }; flx3: flexcom@e1824000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe1824000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 41>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe1824000 0x800>; status = "disabled"; uart3: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 41>; clock-names = "usart"; dmas = <&dma1 AT91_XDMAC_DT_PERID(12)>, <&dma1 AT91_XDMAC_DT_PERID(11)>; dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; status = "disabled"; }; }; ssc1: sound@e200c000 { compatible = "atmel,at91sam9g45-ssc"; reg = <0xe200c000 0x1000>; #sound-dai-cells = <0>; interrupts = ; dmas = <&dma0 AT91_XDMAC_DT_PERID(46)>, <&dma0 AT91_XDMAC_DT_PERID(47)>; dma-names = "rx", "tx"; clocks = <&pmc PMC_TYPE_PERIPHERAL 87>; clock-names = "pclk"; sound-name-prefix = "SSC1"; status = "disabled"; }; trng: rng@e2010000 { compatible = "microchip,sama7g5-trng", "atmel,at91sam9g45-trng"; reg = <0xe2010000 0x100>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 97>; status = "disabled"; secure-status = "okay"; }; tdes: crypto@e2014000 { compatible = "atmel,at91sam9g46-tdes"; reg = <0xe2014000 0x100>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 96>; clock-names = "tdes_clk"; dmas = <&dma0 AT91_XDMAC_DT_PERID(54)>, <&dma0 AT91_XDMAC_DT_PERID(53)>; dma-names = "tx", "rx"; status = "okay"; }; flx4: flexcom@e2018000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe2018000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 42>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe2018000 0x800>; status = "disabled"; uart4: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 42>; clock-names = "usart"; dmas = <&dma1 AT91_XDMAC_DT_PERID(14)>, <&dma1 AT91_XDMAC_DT_PERID(13)>; dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; atmel,fifo-size = <16>; status = "disabled"; }; }; flx7: flexcom@e2024000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe2024000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 45>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe2024000 0x800>; status = "disabled"; uart7: serial@200 { compatible = "atmel,at91sam9260-usart"; reg = <0x200 0x200>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 45>; clock-names = "usart"; dmas = <&dma1 AT91_XDMAC_DT_PERID(20)>, <&dma1 AT91_XDMAC_DT_PERID(19)>; dma-names = "tx", "rx"; atmel,use-dma-rx; atmel,use-dma-tx; atmel,fifo-size = <16>; status = "disabled"; }; }; gmac0: ethernet@e2800000 { compatible = "microchip,sama7g5-gem"; reg = <0xe2800000 0x1000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_GCK 51>, <&pmc PMC_TYPE_GCK 53>; clock-names = "pclk", "hclk", "tx_clk", "tsu_clk"; assigned-clocks = <&pmc PMC_TYPE_GCK 51>; assigned-clock-rates = <125000000>; assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_ETHPLL>; status = "disabled"; }; gmac1: ethernet@e2804000 { compatible = "microchip,sama7g5-emac"; reg = <0xe2804000 0x1000>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_GCK 54>; clock-names = "pclk", "hclk", "tsu_clk"; assigned-clocks = <&pmc PMC_TYPE_GCK 54>; assigned-clock-rates = <200000000>; status = "disabled"; }; dma0: dma-controller@e2808000 { compatible = "microchip,sama7g5-dma"; reg = <0xe2808000 0x1000>; interrupts = ; #dma-cells = <1>; clocks = <&pmc PMC_TYPE_PERIPHERAL 22>; clock-names = "dma_clk"; status = "disabled"; }; dma1: dma-controller@e280c000 { compatible = "microchip,sama7g5-dma"; reg = <0xe280c000 0x1000>; interrupts = ; #dma-cells = <1>; clocks = <&pmc PMC_TYPE_PERIPHERAL 23>; clock-names = "dma_clk"; status = "disabled"; }; /* Place dma2 here despite it's address */ dma2: dma-controller@e1200000 { compatible = "microchip,sama7g5-dma"; reg = <0xe1200000 0x1000>; interrupts = ; #dma-cells = <1>; clocks = <&pmc PMC_TYPE_PERIPHERAL 24>; clock-names = "dma_clk"; dma-requests = <0>; status = "disabled"; }; tcb0: timer@e2814000 { compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon"; #address-cells = <1>; #size-cells = <0>; reg = <0xe2814000 0x100>; interrupts = , , ; clocks = <&pmc PMC_TYPE_PERIPHERAL 88>, <&pmc PMC_TYPE_PERIPHERAL 89>, <&pmc PMC_TYPE_PERIPHERAL 90>, <&clk32k 1>; clock-names = "t0_clk", "t1_clk", "t2_clk", "slow_clk"; }; flx8: flexcom@e2818000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe2818000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 46>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe2818000 0x800>; status = "disabled"; i2c8: i2c@600 { compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 46>; atmel,fifo-size = <32>; dmas = <&dma0 AT91_XDMAC_DT_PERID(22)>, <&dma0 AT91_XDMAC_DT_PERID(21)>; dma-names = "tx", "rx"; status = "disabled"; }; }; flx9: flexcom@e281c000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe281c000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe281c000 0x800>; status = "disabled"; i2c9: i2c@600 { compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c"; reg = <0x600 0x200>; interrupts = ; #address-cells = <1>; #size-cells = <0>; clocks = <&pmc PMC_TYPE_PERIPHERAL 47>; atmel,fifo-size = <32>; dmas = <&dma0 AT91_XDMAC_DT_PERID(24)>, <&dma0 AT91_XDMAC_DT_PERID(23)>; dma-names = "tx", "rx"; status = "disabled"; }; }; flx11: flexcom@e2824000 { compatible = "atmel,sama5d2-flexcom"; reg = <0xe2824000 0x200>; clocks = <&pmc PMC_TYPE_PERIPHERAL 49>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe2824000 0x800>; status = "disabled"; spi11: spi@400 { compatible = "atmel,at91rm9200-spi"; reg = <0x400 0x200>; interrupts = ; clocks = <&pmc PMC_TYPE_PERIPHERAL 49>; clock-names = "spi_clk"; #address-cells = <1>; #size-cells = <0>; atmel,fifo-size = <32>; dmas = <&dma0 AT91_XDMAC_DT_PERID(28)>, <&dma0 AT91_XDMAC_DT_PERID(27)>; dma-names = "tx", "rx"; status = "disabled"; }; }; uddrc: uddrc@e3800000 { compatible = "microchip,sama7g5-uddrc"; reg = <0xe3800000 0x4000>; }; ddr3phy: ddr3phy@e3804000 { compatible = "microchip,sama7g5-ddr3phy"; reg = <0xe3804000 0x1000>; }; otpc: efuse@e8c00000 { compatible = "microchip,sama7g5-otpc", "syscon"; reg = <0xe8c00000 0x100>; #address-cells = <1>; #size-cells = <1>; temperature_calib: calib@1 { status = "disabled"; }; }; gic: interrupt-controller@e8c11000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; #address-cells = <0>; interrupt-controller; reg = <0xe8c11000 0x1000>, <0xe8c12000 0x2000>; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp13-pinctrl.dtsi000066400000000000000000000023001464416617300225670ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019-2022 - All Rights Reserved * Author: Alexandre Torgue */ #include &pinctrl { i2c4_pins_a: i2c4-0 { pins { pinmux = , /* I2C4_SCL */ ; /* I2C4_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; rcc_mco_pins_a: rcc-pins-0 { pins { pinmux = ; /* RCC_MCO_1 */ bias-disable; drive-push-pull; slew-rate = <1>; }; }; uart4_pins_a: uart4-0 { pins1 { pinmux = ; /* UART4_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART4_RX */ bias-disable; }; }; usart1_pins_a: usart1-0 { pins1 { pinmux = , /* USART1_TX */ ; /* USART1_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART1_RX */ ; /* USART1_CTS_NSS */ bias-pull-up; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp131.dtsi000066400000000000000000000345761464416617300212230ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include #include #include #include #include / { #address-cells = <1>; #size-cells = <1>; cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { compatible = "arm,cortex-a7"; device_type = "cpu"; reg = <0>; }; }; hse_monitor: hse-monitor { compatible = "st,freq-monitor"; counter = <&lptimer3 1 1 0 0>; status = "disabled"; }; intc: interrupt-controller@a0021000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; interrupt-controller; reg = <0xa0021000 0x1000>, <0xa0022000 0x2000>; }; psci { compatible = "arm,psci-1.0"; method = "smc"; }; clocks { clk_hse: clk-hse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <24000000>; }; clk_hsi: clk-hsi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <64000000>; }; clk_lse: clk-lse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32768>; }; clk_lsi: clk-lsi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32000>; }; clk_csi: clk-csi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <4000000>; }; clk_i2sin: clk-i2sin { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <19000000>; }; }; sdmmc1_io: sdmmc1_io { compatible = "st,stm32mp13-iod"; regulator-name = "sdmmc1_io"; regulator-always-on; }; sdmmc2_io: sdmmc2_io { compatible = "st,stm32mp13-iod"; regulator-name = "sdmmc2_io"; regulator-always-on; }; soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; ranges; usart3: serial@4000f000 { compatible = "st,stm32h7-uart"; reg = <0x4000f000 0x400>; interrupts = ; clocks = <&rcc USART3_K>; resets = <&rcc USART3_R>; status = "disabled"; }; uart4: serial@40010000 { compatible = "st,stm32h7-uart"; reg = <0x40010000 0x400>; interrupts = ; clocks = <&rcc UART4_K>; resets = <&rcc UART4_R>; status = "disabled"; }; uart5: serial@40011000 { compatible = "st,stm32h7-uart"; reg = <0x40011000 0x400>; interrupts = ; clocks = <&rcc UART5_K>; resets = <&rcc UART5_R>; status = "disabled"; }; uart7: serial@40018000 { compatible = "st,stm32h7-uart"; reg = <0x40018000 0x400>; interrupts = ; clocks = <&rcc UART7_K>; resets = <&rcc UART7_R>; status = "disabled"; }; uart8: serial@40019000 { compatible = "st,stm32h7-uart"; reg = <0x40019000 0x400>; interrupts = ; clocks = <&rcc UART8_K>; resets = <&rcc UART8_R>; status = "disabled"; }; usart6: serial@44003000 { compatible = "st,stm32h7-uart"; reg = <0x44003000 0x400>; interrupts = ; clocks = <&rcc USART6_K>; resets = <&rcc USART6_R>; status = "disabled"; }; rcc: rcc@50000000 { compatible = "st,stm32mp13-rcc", "syscon"; reg = <0x50000000 0x1000>; #address-cells = <1>; #size-cells = <0>; #clock-cells = <1>; #reset-cells = <1>; clocks = <&clk_hse>, <&clk_hsi>, <&clk_lse>, <&clk_lsi>, <&clk_csi>, <&clk_i2sin>; clock-names = "clk-hse", "clk-hsi", "clk-lse", "clk-lsi", "clk-csi", "clk-i2sin"; interrupts = ; secure-interrupts = ; secure-interrupt-names = "wakeup"; }; pwr_regulators: pwr@50001000 { compatible = "st,stm32mp1,pwr-reg"; reg = <0x50001000 0x10>; reg11: reg11 { regulator-name = "reg11"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; }; reg18: reg18 { regulator-name = "reg18"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; usb33: usb33 { regulator-name = "usb33"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; }; pwr_irq: pwr@50001010 { compatible = "st,stm32mp1,pwr-irq"; status = "disabled"; }; syscfg: syscon@50020000 { compatible = "st,stm32mp157-syscfg", "syscon"; reg = <0x50020000 0x400>; }; iwdg2: watchdog@5a002000 { compatible = "st,stm32mp1-iwdg"; reg = <0x5a002000 0x400>; interrupts = ; clocks = <&rcc IWDG2>, <&rcc CK_LSI>; clock-names = "pclk", "lsi"; status = "disabled"; }; rtc: rtc@5c004000 { compatible = "st,stm32mp13-rtc"; reg = <0x5c004000 0x400>; clocks = <&rcc RTCAPB>, <&rcc RTC>; clock-names = "pclk", "rtc_ck"; status = "disabled"; }; bsec: efuse@5c005000 { compatible = "st,stm32mp13-bsec"; reg = <0x5c005000 0x400>; #address-cells = <1>; #size-cells = <1>; cfg0_otp: cfg0_otp@0 { reg = <0x0 0x2>; }; part_number_otp: part_number_otp@4 { reg = <0x4 0x2>; bits = <0 12>; }; monotonic_otp: monotonic_otp@10 { reg = <0x10 0x4>; }; nand_otp: cfg9_otp@24 { reg = <0x24 0x4>; }; uid_otp: uid_otp@34 { reg = <0x34 0xc>; }; hw2_otp: hw2_otp@48 { reg = <0x48 0x4>; }; ts_cal1: calib@5c { reg = <0x5c 0x2>; }; ts_cal2: calib@5e { reg = <0x5e 0x2>; }; pkh_otp: pkh_otp@60 { reg = <0x60 0x20>; }; ethernet_mac1_address: mac1@e4 { reg = <0xe4 0xc>; st,non-secure-otp; }; oem_enc_key: oem_enc_key@170 { reg = <0x170 0x10>; }; }; tzc400: tzc@5c006000 { compatible = "st,stm32mp1-tzc"; reg = <0x5c006000 0x1000>; interrupts = ; st,mem-map = <0xc0000000 0x40000000>; clocks = <&rcc TZC>; }; tamp: tamp@5c00a000 { compatible = "st,stm32mp13-tamp"; reg = <0x5c00a000 0x400>; interrupts = ; clocks = <&rcc RTCAPB>; }; pinctrl: pin-controller@50002000 { #address-cells = <1>; #size-cells = <1>; compatible = "st,stm32mp135-pinctrl"; ranges = <0 0x50002000 0x8400>; pins-are-numbered; gpioa: gpio@50002000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOA>; reg = <0x0 0x400>; st,bank-name = "GPIOA"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@50003000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOB>; reg = <0x1000 0x400>; st,bank-name = "GPIOB"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@50004000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOC>; reg = <0x2000 0x400>; st,bank-name = "GPIOC"; ngpios = <16>; gpio-ranges = <&pinctrl 0 32 16>; }; gpiod: gpio@50005000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOD>; reg = <0x3000 0x400>; st,bank-name = "GPIOD"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@50006000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOE>; reg = <0x4000 0x400>; st,bank-name = "GPIOE"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@50007000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOF>; reg = <0x5000 0x400>; st,bank-name = "GPIOF"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>; }; gpiog: gpio@50008000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOG>; reg = <0x6000 0x400>; st,bank-name = "GPIOG"; ngpios = <16>; gpio-ranges = <&pinctrl 0 96 16>; }; gpioh: gpio@50009000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOH>; reg = <0x7000 0x400>; st,bank-name = "GPIOH"; ngpios = <15>; gpio-ranges = <&pinctrl 0 112 15>; }; gpioi: gpio@5000a000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; clocks = <&rcc GPIOI>; reg = <0x8000 0x400>; st,bank-name = "GPIOI"; ngpios = <8>; gpio-ranges = <&pinctrl 0 128 8>; }; }; etzpc: etzpc@5c007000 { compatible = "st,stm32-etzpc", "firewall-bus"; reg = <0x5C007000 0x400>; clocks = <&rcc TZPC>; #address-cells = <1>; #size-cells = <1>; adc_2: adc@48004000 { reg = <0x48004000 0x400>; compatible = "st,stm32mp13-adc-core"; interrupts = ; clocks = <&rcc ADC2>, <&rcc ADC2_K>; clock-names = "bus", "adc"; interrupt-controller; #interrupt-cells = <1>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; adc2: adc@0 { compatible = "st,stm32mp13-adc"; reg = <0x0>; #io-channel-cells = <1>; #address-cells = <1>; #size-cells = <0>; interrupt-parent = <&adc_2>; interrupts = <0>; status = "disabled"; channel@13 { reg = <13>; label = "vrefint"; }; channel@14 { reg = <14>; label = "vddcore"; }; channel@16 { reg = <16>; label = "vddcpu"; }; channel@17 { reg = <17>; label = "vddq_ddr"; }; }; }; usart1: serial@4c000000 { compatible = "st,stm32h7-uart"; reg = <0x4c000000 0x400>; interrupts = ; clocks = <&rcc USART1_K>; resets = <&rcc USART1_R>; status = "disabled"; }; usart2: serial@4c001000 { compatible = "st,stm32h7-uart"; reg = <0x4c001000 0x400>; interrupts = ; clocks = <&rcc USART2_K>; resets = <&rcc USART2_R>; status = "disabled"; }; i2c3: i2c@4c004000 { compatible = "st,stm32mp13-i2c"; reg = <0x4c004000 0x400>; clocks = <&rcc I2C3_K>; resets = <&rcc I2C3_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x4>; i2c-analog-filter; status = "disabled"; }; i2c4: i2c@4c005000 { compatible = "st,stm32mp13-i2c"; reg = <0x4c005000 0x400>; clocks = <&rcc I2C4_K>; resets = <&rcc I2C4_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x8>; i2c-analog-filter; status = "disabled"; }; i2c5: i2c@4c006000 { compatible = "st,stm32mp13-i2c"; reg = <0x4c006000 0x400>; clocks = <&rcc I2C5_K>; resets = <&rcc I2C5_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x10>; i2c-analog-filter; status = "disabled"; }; timers12: timer@4c007000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x4c007000 0x400>; interrupts = ; clocks = <&rcc TIM12_K>; clock-names = "int"; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers13: timer@4c008000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x4c008000 0x400>; clocks = <&rcc TIM13_K>; clock-names = "int"; status = "disabled"; }; timers14: timer@4c009000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x4c009000 0x400>; clocks = <&rcc TIM14_K>; clock-names = "int"; status = "disabled"; }; timers15: timer@4c00a000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x4c00a000 0x400>; interrupts = ; clocks = <&rcc TIM15_K>; clock-names = "int"; status = "disabled"; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers16: timer@4c00b000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x4c00b000 0x400>; clocks = <&rcc TIM16_K>; clock-names = "int"; status = "disabled"; }; timers17: timer@4c00c000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x4c00c000 0x400>; clocks = <&rcc TIM17_K>; clock-names = "int"; status = "disabled"; }; lptimer2: timer@50021000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-lptimer"; reg = <0x50021000 0x400>; interrupts = ; clocks = <&rcc LPTIM2_K>; clock-names = "mux"; status = "disabled"; }; lptimer3: timer@50022000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-lptimer"; reg = <0x50022000 0x400>; interrupts = ; clocks = <&rcc LPTIM3_K>; clock-names = "mux"; status = "disabled"; counter { compatible = "st,stm32-lptimer-counter"; status = "disabled"; }; }; vrefbuf: vrefbuf@50025000 { compatible = "st,stm32mp13-vrefbuf"; reg = <0x50025000 0x8>; regulator-name = "vrefbuf"; regulator-min-microvolt = <1650000>; regulator-max-microvolt = <2500000>; clocks = <&rcc VREF>; status = "disabled"; }; hash: hash@54003000 { compatible = "st,stm32mp13-hash"; reg = <0x54003000 0x400>; interrupts = ; clocks = <&rcc HASH1>; resets = <&rcc HASH1_R>; status = "disabled"; }; rng: rng@54004000 { compatible = "st,stm32mp13-rng"; reg = <0x54004000 0x400>; clocks = <&rcc RNG1_K>; resets = <&rcc RNG1_R>; status = "disabled"; }; iwdg1: watchdog@5c003000 { compatible = "st,stm32mp1-iwdg"; reg = <0x5C003000 0x400>; interrupts = ; clocks = <&rcc IWDG1>, <&rcc CK_LSI>; clock-names = "pclk", "lsi"; status = "disabled"; }; stgen: stgen@5c008000 { compatible = "st,stm32-stgen"; reg = <0x5C008000 0x1000>; }; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp133.dtsi000066400000000000000000000003611464416617300212060ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp131.dtsi" optee_os-4.3.0/core/arch/arm/dts/stm32mp135.dtsi000066400000000000000000000011341464416617300212070ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp133.dtsi" / { soc { etzpc: etzpc@5c007000 { ltdc: display-controller@5a001000 { compatible = "st,stm32-ltdc"; reg = <0x5a001000 0x400>; interrupts = , ; clocks = <&rcc LTDC_PX>; clock-names = "lcd"; resets = <&rcc LTDC_R>; status = "disabled"; }; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp135f-dk.dts000066400000000000000000000211441464416617300216030ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ /dts-v1/; #include #include #include #include #include "stm32mp135.dtsi" #include "stm32mp13xf.dtsi" #include "stm32mp13-pinctrl.dtsi" / { model = "STMicroelectronics STM32MP135F-DK Discovery Board"; compatible = "st,stm32mp135f-dk", "st,stm32mp135"; aliases { serial0 = &uart4; serial1 = &usart1; }; chosen { stdout-path = "serial0:115200n8"; }; memory@c0000000 { device_type = "memory"; reg = <0xc0000000 0x20000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; optee_framebuffer: optee-framebuffer@dd000000 { /* Secure framebuffer memory */ reg = <0xdd000000 0x1000000>; no-map; }; }; vin: vin { compatible = "regulator-fixed"; regulator-name = "vin"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; }; v3v3_ao: v3v3_ao { compatible = "regulator-fixed"; regulator-name = "v3v3_ao"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; }; &adc_2 { vdda-supply = <&vdd_adc>; vref-supply = <&vdd_adc>; status = "okay"; adc2: adc@0 { status = "okay"; channel@15 { reg = <15>; label = "vbat"; }; }; }; &bsec { board_id: board_id@f0 { reg = <0xf0 0x4>; st,non-secure-otp; }; }; &gpiob { st,protreg = ; }; &gpiod { st,protreg = ; }; &gpioe { st,protreg = ; }; &i2c4 { pinctrl-names = "default"; pinctrl-0 = <&i2c4_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; clock-frequency = <400000>; status = "okay"; pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; status = "okay"; st,wakeup-pin-number = <1>; st,notif-it-id = <0>; regulators { compatible = "st,stpmic1-regulators"; buck1-supply = <&vin>; buck2-supply = <&vin>; buck3-supply = <&vin>; buck4-supply = <&vin>; ldo1-supply = <&vin>; ldo4-supply = <&vin>; ldo5-supply = <&vin>; ldo6-supply = <&vin>; vref_ddr-supply = <&vin>; pwr_sw1-supply = <&bst_out>; pwr_sw2-supply = <&v3v3_ao>; vddcpu: buck1 { regulator-name = "vddcpu"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-over-current-protection; lp-stop { regulator-suspend-microvolt = <1250000>; }; lplv-stop { regulator-suspend-microvolt = <900000>; }; lplv-stop2 { regulator-off-in-suspend; }; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; vdd_ddr: buck2 { regulator-name = "vdd_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-over-current-protection; standby-ddr-off { regulator-off-in-suspend; }; }; vdd: buck3 { regulator-name = "vdd"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; st,mask-reset; regulator-over-current-protection; }; vddcore: buck4 { regulator-name = "vddcore"; regulator-min-microvolt = <1250000>; regulator-max-microvolt = <1250000>; regulator-always-on; regulator-over-current-protection; lplv-stop { regulator-suspend-microvolt = <900000>; }; lplv-stop2 { regulator-suspend-microvolt = <900000>; }; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; vdd_adc: ldo1 { regulator-name = "vdd_adc"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; unused1: ldo2 { regulator-name = "ldo2"; }; unused2: ldo3 { regulator-name = "ldo3"; }; vdd_usb: ldo4 { regulator-name = "vdd_usb"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; vdd_sd: ldo5 { regulator-name = "vdd_sd"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-boot-on; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; v1v8_periph: ldo6 { regulator-name = "v1v8_periph"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; vref_ddr: vref_ddr { regulator-name = "vref_ddr"; regulator-always-on; standby-ddr-sr { regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; }; }; bst_out: boost { regulator-name = "bst_out"; }; v3v3_sw: pwr_sw2 { regulator-name = "v3v3_sw"; regulator-active-discharge = <1>; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; }; }; }; &iwdg1 { timeout-sec = <32>; status = "okay"; }; &oem_enc_key { st,non-secure-otp-provisioning; }; &pwr_regulators { vdd-supply = <&vdd>; vdd_3v3_usbfs-supply = <&vdd_usb>; }; &rcc { compatible = "st,stm32mp13-rcc", "syscon"; st,clksrc = < CLK_MPU_PLL1P CLK_AXI_PLL2P CLK_MLAHBS_PLL3 CLK_RTC_LSE CLK_MCO1_HSE CLK_MCO2_DISABLED CLK_CKPER_HSE CLK_ETH1_PLL4P CLK_ETH2_PLL4P CLK_SDMMC1_PLL4P CLK_SDMMC2_PLL4P CLK_STGEN_HSE CLK_USBPHY_HSE CLK_I2C4_HSI CLK_I2C5_HSI CLK_USBO_USBPHY CLK_ADC2_CKPER CLK_I2C12_HSI CLK_UART1_HSI CLK_UART2_HSI CLK_UART35_HSI CLK_UART4_HSI CLK_UART6_HSI CLK_UART78_HSI CLK_SAES_AXI CLK_DCMIPP_PLL2Q CLK_LPTIM3_PCLK3 CLK_RNG1_PLL4R >; st,clkdiv = < DIV(DIV_MPU, 1) DIV(DIV_AXI, 0) DIV(DIV_MLAHB, 0) DIV(DIV_APB1, 1) DIV(DIV_APB2, 1) DIV(DIV_APB3, 1) DIV(DIV_APB4, 1) DIV(DIV_APB5, 2) DIV(DIV_APB6, 1) DIV(DIV_RTC, 0) DIV(DIV_MCO1, 0) DIV(DIV_MCO2, 0) >; st,pll_vco { pll1_vco_2000Mhz: pll1-vco-2000Mhz { src = ; divmn = <1 82>; frac = <0xAAA>; }; pll1_vco_1300Mhz: pll1-vco-1300Mhz { src = ; divmn = <2 80>; frac = <0x800>; }; pll2_vco_1066Mhz: pll2-vco-1066Mhz { src = ; divmn = <2 65>; frac = <0x1400>; }; pll3_vco_417Mhz: pll3-vco-417Mhz { src = ; divmn = <1 33>; frac = <0x1a04>; }; pll4_vco_600Mhz: pll4-vco-600Mhz { src = ; divmn = <1 49>; }; }; /* VCO = 1300.0 MHz => P = 650 (CPU) */ pll1: st,pll@0 { compatible = "st,stm32mp1-pll"; reg = <0>; st,pll = <&pll1_cfg1>; pll1_cfg1: pll1_cfg1 { st,pll_vco = <&pll1_vco_1300Mhz>; st,pll_div_pqr = <0 1 1>; }; pll1_cfg2: pll1_cfg2 { st,pll_vco = <&pll1_vco_2000Mhz>; st,pll_div_pqr = <0 1 1>; }; }; /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ pll2: st,pll@1 { compatible = "st,stm32mp1-pll"; reg = <1>; st,pll = <&pll2_cfg1>; pll2_cfg1: pll2_cfg1 { st,pll_vco = <&pll2_vco_1066Mhz>; st,pll_div_pqr = <1 1 0>; }; }; /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ pll3: st,pll@2 { compatible = "st,stm32mp1-pll"; reg = <2>; st,pll = <&pll3_cfg1>; pll3_cfg1: pll3_cfg1 { st,pll_vco = <&pll3_vco_417Mhz>; st,pll_div_pqr = <1 16 36>; }; }; /* VCO = 600.0 MHz => P = 50, Q = 10, R = 50 */ pll4: st,pll@3 { compatible = "st,stm32mp1-pll"; reg = <3>; st,pll = <&pll4_cfg1>; pll4_cfg1: pll4_cfg1 { st,pll_vco = <&pll4_vco_600Mhz>; st,pll_div_pqr = <11 59 11>; }; }; st,clk_opp { /* CK_MPU clock config for MP13 */ st,ck_mpu { cfg_1 { hz = <650000000>; st,clksrc = ; st,pll = <&pll1_cfg1>; }; cfg_2 { hz = <1000000000>; st,clksrc = ; st,pll = <&pll1_cfg2>; }; }; }; }; &rng { status = "okay"; clock-error-detect; }; &rtc { status = "okay"; }; &saes { status = "okay"; }; &sdmmc1_io { vddsd1-supply = <&vdd>; }; &sdmmc2_io { vddsd2-supply = <&vdd>; }; &uart4 { pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_a>; status = "okay"; }; &usart1 { pinctrl-names = "default"; pinctrl-0 = <&usart1_pins_a>; uart-has-rtscts; status = "disabled"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp13xc.dtsi000066400000000000000000000015471464416617300214650ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &etzpc { cryp: crypto@54002000 { compatible = "st,stm32mp1-cryp"; reg = <0x54002000 0x400>; interrupts = ; clocks = <&rcc CRYP1>; resets = <&rcc CRYP1_R>; status = "disabled"; }; saes: saes@54005000 { compatible = "st,stm32mp13-saes"; reg = <0x54005000 0x400>; interrupts = ; clocks = <&rcc SAES_K>; resets = <&rcc SAES_R>; status = "disabled"; }; pka: pka@54006000 { compatible = "st,stm32mp13-pka64"; reg = <0x54006000 0x2000>; interrupts = ; clocks = <&rcc PKA>; resets = <&rcc PKA_R>; status = "disabled"; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp13xf.dtsi000066400000000000000000000015471464416617300214700ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &etzpc { cryp: crypto@54002000 { compatible = "st,stm32mp1-cryp"; reg = <0x54002000 0x400>; interrupts = ; clocks = <&rcc CRYP1>; resets = <&rcc CRYP1_R>; status = "disabled"; }; saes: saes@54005000 { compatible = "st,stm32mp13-saes"; reg = <0x54005000 0x400>; interrupts = ; clocks = <&rcc SAES_K>; resets = <&rcc SAES_R>; status = "disabled"; }; pka: pka@54006000 { compatible = "st,stm32mp13-pka64"; reg = <0x54006000 0x2000>; interrupts = ; clocks = <&rcc PKA>; resets = <&rcc PKA_R>; status = "disabled"; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15-pinctrl.dtsi000066400000000000000000001773451464416617300226170ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ #include &pinctrl { adc1_in6_pins_a: adc1-in6-0 { pins { pinmux = ; }; }; adc12_ain_pins_a: adc12-ain-0 { pins { pinmux = , /* ADC1 in13 */ , /* ADC1 in6 */ , /* ADC2 in2 */ ; /* ADC2 in6 */ }; }; adc12_ain_pins_b: adc12-ain-1 { pins { pinmux = , /* ADC1 in6 */ ; /* ADC2 in2 */ }; }; adc12_usb_cc_pins_a: adc12-usb-cc-pins-0 { pins { pinmux = , /* ADC12 in18 */ ; /* ADC12 in19 */ }; }; cec_pins_a: cec-0 { pins { pinmux = ; bias-disable; drive-open-drain; slew-rate = <0>; }; }; cec_sleep_pins_a: cec-sleep-0 { pins { pinmux = ; /* HDMI_CEC */ }; }; cec_pins_b: cec-1 { pins { pinmux = ; bias-disable; drive-open-drain; slew-rate = <0>; }; }; cec_sleep_pins_b: cec-sleep-1 { pins { pinmux = ; /* HDMI_CEC */ }; }; dac_ch1_pins_a: dac-ch1-0 { pins { pinmux = ; }; }; dac_ch2_pins_a: dac-ch2-0 { pins { pinmux = ; }; }; dcmi_pins_a: dcmi-0 { pins { pinmux = ,/* DCMI_HSYNC */ ,/* DCMI_VSYNC */ ,/* DCMI_PIXCLK */ ,/* DCMI_D0 */ ,/* DCMI_D1 */ ,/* DCMI_D2 */ ,/* DCMI_D3 */ ,/* DCMI_D4 */ ,/* DCMI_D5 */ ,/* DCMI_D6 */ ,/* DCMI_D7 */ ,/* DCMI_D8 */ ,/* DCMI_D9 */ ,/* DCMI_D10 */ ;/* DCMI_D11 */ bias-disable; }; }; dcmi_sleep_pins_a: dcmi-sleep-0 { pins { pinmux = ,/* DCMI_HSYNC */ ,/* DCMI_VSYNC */ ,/* DCMI_PIXCLK */ ,/* DCMI_D0 */ ,/* DCMI_D1 */ ,/* DCMI_D2 */ ,/* DCMI_D3 */ ,/* DCMI_D4 */ ,/* DCMI_D5 */ ,/* DCMI_D6 */ ,/* DCMI_D7 */ ,/* DCMI_D8 */ ,/* DCMI_D9 */ ,/* DCMI_D10 */ ;/* DCMI_D11 */ }; }; dcmi_pins_b: dcmi-1 { pins { pinmux = ,/* DCMI_HSYNC */ ,/* DCMI_VSYNC */ ,/* DCMI_PIXCLK */ ,/* DCMI_D0 */ ,/* DCMI_D1 */ ,/* DCMI_D2 */ ,/* DCMI_D3 */ ,/* DCMI_D4 */ ,/* DCMI_D5 */ ,/* DCMI_D6 */ ;/* DCMI_D7 */ bias-disable; }; }; dcmi_sleep_pins_b: dcmi-sleep-1 { pins { pinmux = ,/* DCMI_HSYNC */ ,/* DCMI_VSYNC */ ,/* DCMI_PIXCLK */ ,/* DCMI_D0 */ ,/* DCMI_D1 */ ,/* DCMI_D2 */ ,/* DCMI_D3 */ ,/* DCMI_D4 */ ,/* DCMI_D5 */ ,/* DCMI_D6 */ ;/* DCMI_D7 */ }; }; ethernet0_rgmii_pins_a: rgmii-0 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ , /* ETH_RGMII_GTX_CLK */ , /* ETH_RGMII_TXD0 */ , /* ETH_RGMII_TXD1 */ , /* ETH_RGMII_TXD2 */ , /* ETH_RGMII_TXD3 */ , /* ETH_RGMII_TX_CTL */ ; /* ETH_MDC */ bias-disable; drive-push-pull; slew-rate = <2>; }; pins2 { pinmux = ; /* ETH_MDIO */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = , /* ETH_RGMII_RXD0 */ , /* ETH_RGMII_RXD1 */ , /* ETH_RGMII_RXD2 */ , /* ETH_RGMII_RXD3 */ , /* ETH_RGMII_RX_CLK */ ; /* ETH_RGMII_RX_CTL */ bias-disable; }; }; ethernet0_rgmii_sleep_pins_a: rgmii-sleep-0 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ , /* ETH_RGMII_GTX_CLK */ , /* ETH_RGMII_TXD0 */ , /* ETH_RGMII_TXD1 */ , /* ETH_RGMII_TXD2 */ , /* ETH_RGMII_TXD3 */ , /* ETH_RGMII_TX_CTL */ , /* ETH_MDIO */ , /* ETH_MDC */ , /* ETH_RGMII_RXD0 */ , /* ETH_RGMII_RXD1 */ , /* ETH_RGMII_RXD2 */ , /* ETH_RGMII_RXD3 */ , /* ETH_RGMII_RX_CLK */ ; /* ETH_RGMII_RX_CTL */ }; }; ethernet0_rgmii_pins_b: rgmii-1 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ , /* ETH_RGMII_GTX_CLK */ , /* ETH_RGMII_TXD0 */ , /* ETH_RGMII_TXD1 */ , /* ETH_RGMII_TXD2 */ , /* ETH_RGMII_TXD3 */ , /* ETH_RGMII_TX_CTL */ ; /* ETH_MDC */ bias-disable; drive-push-pull; slew-rate = <2>; }; pins2 { pinmux = ; /* ETH_MDIO */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = , /* ETH_RGMII_RXD0 */ , /* ETH_RGMII_RXD1 */ , /* ETH_RGMII_RXD2 */ , /* ETH_RGMII_RXD3 */ , /* ETH_RGMII_RX_CLK */ ; /* ETH_RGMII_RX_CTL */ bias-disable; }; }; ethernet0_rgmii_sleep_pins_b: rgmii-sleep-1 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ , /* ETH_RGMII_GTX_CLK */ , /* ETH_RGMII_TXD0 */ , /* ETH_RGMII_TXD1 */ , /* ETH_RGMII_TXD2 */ , /* ETH_RGMII_TXD3 */ , /* ETH_RGMII_TX_CTL */ , /* ETH_MDC */ , /* ETH_MDIO */ , /* ETH_RGMII_RXD0 */ , /* ETH_RGMII_RXD1 */ , /* ETH_RGMII_RXD2 */ , /* ETH_RGMII_RXD3 */ , /* ETH_RGMII_RX_CLK */ ; /* ETH_RGMII_RX_CTL */ }; }; ethernet0_rgmii_pins_c: rgmii-2 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ , /* ETH_RGMII_GTX_CLK */ , /* ETH_RGMII_TXD0 */ , /* ETH_RGMII_TXD1 */ , /* ETH_RGMII_TXD2 */ , /* ETH_RGMII_TXD3 */ , /* ETH_RGMII_TX_CTL */ ; /* ETH_MDC */ bias-disable; drive-push-pull; slew-rate = <2>; }; pins2 { pinmux = ; /* ETH_MDIO */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = , /* ETH_RGMII_RXD0 */ , /* ETH_RGMII_RXD1 */ , /* ETH_RGMII_RXD2 */ , /* ETH_RGMII_RXD3 */ , /* ETH_RGMII_RX_CLK */ ; /* ETH_RGMII_RX_CTL */ bias-disable; }; }; ethernet0_rgmii_sleep_pins_c: rgmii-sleep-2 { pins1 { pinmux = , /* ETH_RGMII_CLK125 */ , /* ETH_RGMII_GTX_CLK */ , /* ETH_RGMII_TXD0 */ , /* ETH_RGMII_TXD1 */ , /* ETH_RGMII_TXD2 */ , /* ETH_RGMII_TXD3 */ , /* ETH_RGMII_TX_CTL */ , /* ETH_MDIO */ , /* ETH_MDC */ , /* ETH_RGMII_RXD0 */ , /* ETH_RGMII_RXD1 */ , /* ETH_RGMII_RXD2 */ , /* ETH_RGMII_RXD3 */ , /* ETH_RGMII_RX_CLK */ ; /* ETH_RGMII_RX_CTL */ }; }; ethernet0_rmii_pins_a: rmii-0 { pins1 { pinmux = , /* ETH1_RMII_TXD0 */ , /* ETH1_RMII_TXD1 */ , /* ETH1_RMII_TX_EN */ , /* ETH1_RMII_REF_CLK */ , /* ETH1_MDIO */ ; /* ETH1_MDC */ bias-disable; drive-push-pull; slew-rate = <2>; }; pins2 { pinmux = , /* ETH1_RMII_RXD0 */ , /* ETH1_RMII_RXD1 */ ; /* ETH1_RMII_CRS_DV */ bias-disable; }; }; ethernet0_rmii_sleep_pins_a: rmii-sleep-0 { pins1 { pinmux = , /* ETH1_RMII_TXD0 */ , /* ETH1_RMII_TXD1 */ , /* ETH1_RMII_TX_EN */ , /* ETH1_MDIO */ , /* ETH1_MDC */ , /* ETH1_RMII_RXD0 */ , /* ETH1_RMII_RXD1 */ , /* ETH1_RMII_REF_CLK */ ; /* ETH1_RMII_CRS_DV */ }; }; ethernet0_rmii_pins_b: rmii-1 { pins1 { pinmux = , /* ETH1_CLK */ , /* ETH1_MDC */ , /* ETH1_TXD0 */ ; /* ETH1_TXD1 */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* ETH1_MDIO */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = , /* ETH1_CRS_DV */ , /* ETH1_RXD0 */ ; /* ETH1_RXD1 */ bias-disable; }; pins4 { pinmux = ; /* ETH1_TX_EN */ }; }; ethernet0_rmii_sleep_pins_b: rmii-sleep-1 { pins1 { pinmux = , /* ETH1_MDIO */ , /* ETH1_CRS_DV */ , /* ETH1_CLK */ , /* ETH1_TX_EN */ , /* ETH1_MDC */ , /* ETH1_RXD0 */ , /* ETH1_RXD1 */ , /* ETH1_TXD0 */ ; /* ETH1_TXD1 */ }; }; ethernet0_rmii_pins_c: rmii-2 { pins1 { pinmux = , /* ETH1_RMII_TXD0 */ , /* ETH1_RMII_TXD1 */ , /* ETH1_RMII_TX_EN */ , /* ETH1_RMII_REF_CLK */ , /* ETH1_MDIO */ ; /* ETH1_MDC */ bias-disable; drive-push-pull; slew-rate = <2>; }; pins2 { pinmux = , /* ETH1_RMII_RXD0 */ , /* ETH1_RMII_RXD1 */ ; /* ETH1_RMII_CRS_DV */ bias-disable; }; }; ethernet0_rmii_sleep_pins_c: rmii-sleep-2 { pins1 { pinmux = , /* ETH1_RMII_TXD0 */ , /* ETH1_RMII_TXD1 */ , /* ETH1_RMII_TX_EN */ , /* ETH1_MDIO */ , /* ETH1_MDC */ , /* ETH1_RMII_RXD0 */ , /* ETH1_RMII_RXD1 */ , /* ETH1_RMII_REF_CLK */ ; /* ETH1_RMII_CRS_DV */ }; }; fmc_pins_a: fmc-0 { pins1 { pinmux = , /* FMC_NOE */ , /* FMC_NWE */ , /* FMC_A16_FMC_CLE */ , /* FMC_A17_FMC_ALE */ , /* FMC_D0 */ , /* FMC_D1 */ , /* FMC_D2 */ , /* FMC_D3 */ , /* FMC_D4 */ , /* FMC_D5 */ , /* FMC_D6 */ , /* FMC_D7 */ ; /* FMC_NE2_FMC_NCE */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* FMC_NWAIT */ bias-pull-up; }; }; fmc_sleep_pins_a: fmc-sleep-0 { pins { pinmux = , /* FMC_NOE */ , /* FMC_NWE */ , /* FMC_A16_FMC_CLE */ , /* FMC_A17_FMC_ALE */ , /* FMC_D0 */ , /* FMC_D1 */ , /* FMC_D2 */ , /* FMC_D3 */ , /* FMC_D4 */ , /* FMC_D5 */ , /* FMC_D6 */ , /* FMC_D7 */ , /* FMC_NWAIT */ ; /* FMC_NE2_FMC_NCE */ }; }; fmc_pins_b: fmc-1 { pins { pinmux = , /* FMC_NOE */ , /* FMC_NWE */ , /* FMC_NL */ , /* FMC_D0 */ , /* FMC_D1 */ , /* FMC_D2 */ , /* FMC_D3 */ , /* FMC_D4 */ , /* FMC_D5 */ , /* FMC_D6 */ , /* FMC_D7 */ , /* FMC_D8 */ , /* FMC_D9 */ , /* FMC_D10 */ , /* FMC_D11 */ , /* FMC_D12 */ , /* FMC_D13 */ , /* FMC_D14 */ , /* FMC_D15 */ , /* FMC_NE2_FMC_NCE */ ; /* FMC_NE4 */ bias-disable; drive-push-pull; slew-rate = <3>; }; }; fmc_sleep_pins_b: fmc-sleep-1 { pins { pinmux = , /* FMC_NOE */ , /* FMC_NWE */ , /* FMC_NL */ , /* FMC_D0 */ , /* FMC_D1 */ , /* FMC_D2 */ , /* FMC_D3 */ , /* FMC_D4 */ , /* FMC_D5 */ , /* FMC_D6 */ , /* FMC_D7 */ , /* FMC_D8 */ , /* FMC_D9 */ , /* FMC_D10 */ , /* FMC_D11 */ , /* FMC_D12 */ , /* FMC_D13 */ , /* FMC_D14 */ , /* FMC_D15 */ , /* FMC_NE2_FMC_NCE */ ; /* FMC_NE4 */ }; }; i2c1_pins_a: i2c1-0 { pins { pinmux = , /* I2C1_SCL */ ; /* I2C1_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c1_sleep_pins_a: i2c1-sleep-0 { pins { pinmux = , /* I2C1_SCL */ ; /* I2C1_SDA */ }; }; i2c1_pins_b: i2c1-1 { pins { pinmux = , /* I2C1_SCL */ ; /* I2C1_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c1_sleep_pins_b: i2c1-sleep-1 { pins { pinmux = , /* I2C1_SCL */ ; /* I2C1_SDA */ }; }; i2c2_pins_a: i2c2-0 { pins { pinmux = , /* I2C2_SCL */ ; /* I2C2_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c2_sleep_pins_a: i2c2-sleep-0 { pins { pinmux = , /* I2C2_SCL */ ; /* I2C2_SDA */ }; }; i2c2_pins_b1: i2c2-1 { pins { pinmux = ; /* I2C2_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c2_sleep_pins_b1: i2c2-sleep-1 { pins { pinmux = ; /* I2C2_SDA */ }; }; i2c2_pins_c: i2c2-2 { pins { pinmux = , /* I2C2_SCL */ ; /* I2C2_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c2_pins_sleep_c: i2c2-sleep-2 { pins { pinmux = , /* I2C2_SCL */ ; /* I2C2_SDA */ }; }; i2c5_pins_a: i2c5-0 { pins { pinmux = , /* I2C5_SCL */ ; /* I2C5_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c5_sleep_pins_a: i2c5-sleep-0 { pins { pinmux = , /* I2C5_SCL */ ; /* I2C5_SDA */ }; }; i2c5_pins_b: i2c5-1 { pins { pinmux = , /* I2C5_SCL */ ; /* I2C5_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c5_sleep_pins_b: i2c5-sleep-1 { pins { pinmux = , /* I2C5_SCL */ ; /* I2C5_SDA */ }; }; i2s2_pins_a: i2s2-0 { pins { pinmux = , /* I2S2_SDO */ , /* I2S2_WS */ ; /* I2S2_CK */ slew-rate = <1>; drive-push-pull; bias-disable; }; }; i2s2_sleep_pins_a: i2s2-sleep-0 { pins { pinmux = , /* I2S2_SDO */ , /* I2S2_WS */ ; /* I2S2_CK */ }; }; ltdc_pins_a: ltdc-0 { pins { pinmux = , /* LCD_CLK */ , /* LCD_HSYNC */ , /* LCD_VSYNC */ , /* LCD_DE */ , /* LCD_R0 */ , /* LCD_R1 */ , /* LCD_R2 */ , /* LCD_R3 */ , /* LCD_R4 */ , /* LCD_R5 */ , /* LCD_R6 */ , /* LCD_R7 */ , /* LCD_G0 */ , /* LCD_G1 */ , /* LCD_G2 */ , /* LCD_G3 */ , /* LCD_G4 */ , /* LCD_G5 */ , /* LCD_G6 */ , /* LCD_G7 */ , /* LCD_B0 */ , /* LCD_B1 */ , /* LCD_B2 */ , /* LCD_B3 */ , /* LCD_B4 */ , /* LCD_B5 */ , /* LCD_B6 */ ; /* LCD_B7 */ bias-disable; drive-push-pull; slew-rate = <1>; }; }; ltdc_sleep_pins_a: ltdc-sleep-0 { pins { pinmux = , /* LCD_CLK */ , /* LCD_HSYNC */ , /* LCD_VSYNC */ , /* LCD_DE */ , /* LCD_R0 */ , /* LCD_R1 */ , /* LCD_R2 */ , /* LCD_R3 */ , /* LCD_R4 */ , /* LCD_R5 */ , /* LCD_R6 */ , /* LCD_R7 */ , /* LCD_G0 */ , /* LCD_G1 */ , /* LCD_G2 */ , /* LCD_G3 */ , /* LCD_G4 */ , /* LCD_G5 */ , /* LCD_G6 */ , /* LCD_G7 */ , /* LCD_B0 */ , /* LCD_B1 */ , /* LCD_B2 */ , /* LCD_B3 */ , /* LCD_B4 */ , /* LCD_B5 */ , /* LCD_B6 */ ; /* LCD_B7 */ }; }; ltdc_pins_b: ltdc-1 { pins { pinmux = , /* LCD_CLK */ , /* LCD_HSYNC */ , /* LCD_VSYNC */ , /* LCD_DE */ , /* LCD_R0 */ , /* LCD_R1 */ , /* LCD_R2 */ , /* LCD_R3 */ , /* LCD_R4 */ , /* LCD_R5 */ , /* LCD_R6 */ , /* LCD_R7 */ , /* LCD_G0 */ , /* LCD_G1 */ , /* LCD_G2 */ , /* LCD_G3 */ , /* LCD_G4 */ , /* LCD_G5 */ , /* LCD_G6 */ , /* LCD_G7 */ , /* LCD_B0 */ , /* LCD_B1 */ , /* LCD_B2 */ , /* LCD_B3 */ , /* LCD_B4 */ , /* LCD_B5 */ , /* LCD_B6 */ ; /* LCD_B7 */ bias-disable; drive-push-pull; slew-rate = <1>; }; }; ltdc_sleep_pins_b: ltdc-sleep-1 { pins { pinmux = , /* LCD_CLK */ , /* LCD_HSYNC */ , /* LCD_VSYNC */ , /* LCD_DE */ , /* LCD_R0 */ , /* LCD_R1 */ , /* LCD_R2 */ , /* LCD_R3 */ , /* LCD_R4 */ , /* LCD_R5 */ , /* LCD_R6 */ , /* LCD_R7 */ , /* LCD_G0 */ , /* LCD_G1 */ , /* LCD_G2 */ , /* LCD_G3 */ , /* LCD_G4 */ , /* LCD_G5 */ , /* LCD_G6 */ , /* LCD_G7 */ , /* LCD_B0 */ , /* LCD_B1 */ , /* LCD_B2 */ , /* LCD_B3 */ , /* LCD_B4 */ , /* LCD_B5 */ , /* LCD_B6 */ ; /* LCD_B7 */ }; }; ltdc_pins_c: ltdc-2 { pins1 { pinmux = , /* LTDC_R6 */ , /* LTDC_B7 */ , /* LTDC_R5 */ , /* LTDC_G7 */ , /* LTDC_B2 */ , /* LTDC_B3 */ , /* LTDC_G3 */ , /* LTDC_B4 */ , /* LTDC_DE */ , /* LTDC_R7 */ , /* LTDC_G5 */ , /* LTDC_R2 */ , /* LTDC_R3 */ , /* LTDC_R4 */ , /* LTDC_G2 */ , /* LTDC_G4 */ , /* LTDC_G6 */ , /* LTDC_B5 */ , /* LTDC_B6 */ , /* LTDC_VSYNC */ ; /* LTDC_HSYNC */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* LTDC_CLK */ bias-disable; drive-push-pull; slew-rate = <1>; }; }; ltdc_sleep_pins_c: ltdc-sleep-2 { pins1 { pinmux = , /* LTDC_R6 */ , /* LTDC_B7 */ , /* LTDC_R5 */ , /* LTDC_G7 */ , /* LTDC_B2 */ , /* LTDC_B3 */ , /* LTDC_G3 */ , /* LTDC_B4 */ , /* LTDC_DE */ , /* LTDC_R7 */ , /* LTDC_G5 */ , /* LTDC_R2 */ , /* LTDC_R3 */ , /* LTDC_R4 */ , /* LTDC_G2 */ , /* LTDC_G4 */ , /* LTDC_G6 */ , /* LTDC_B5 */ , /* LTDC_B6 */ , /* LTDC_VSYNC */ , /* LTDC_HSYNC */ ; /* LTDC_CLK */ }; }; ltdc_pins_d: ltdc-3 { pins1 { pinmux = ; /* LCD_CLK */ bias-disable; drive-push-pull; slew-rate = <3>; }; pins2 { pinmux = , /* LCD_HSYNC */ , /* LCD_VSYNC */ , /* LCD_DE */ , /* LCD_R0 */ , /* LCD_R1 */ , /* LCD_R2 */ , /* LCD_R3 */ , /* LCD_R4 */ , /* LCD_R5 */ , /* LCD_R6 */ , /* LCD_R7 */ , /* LCD_G0 */ , /* LCD_G1 */ , /* LCD_G2 */ , /* LCD_G3 */ , /* LCD_G4 */ , /* LCD_G5 */ , /* LCD_G6 */ , /* LCD_G7 */ , /* LCD_B0 */ , /* LCD_B1 */ , /* LCD_B2 */ , /* LCD_B3 */ , /* LCD_B4 */ , /* LCD_B5 */ , /* LCD_B6 */ ; /* LCD_B7 */ bias-disable; drive-push-pull; slew-rate = <2>; }; }; ltdc_sleep_pins_d: ltdc-sleep-3 { pins { pinmux = , /* LCD_CLK */ , /* LCD_HSYNC */ , /* LCD_VSYNC */ , /* LCD_DE */ , /* LCD_R0 */ , /* LCD_R1 */ , /* LCD_R2 */ , /* LCD_R3 */ , /* LCD_R4 */ , /* LCD_R5 */ , /* LCD_R6 */ , /* LCD_R7 */ , /* LCD_G0 */ , /* LCD_G1 */ , /* LCD_G2 */ , /* LCD_G3 */ , /* LCD_G4 */ , /* LCD_G5 */ , /* LCD_G6 */ , /* LCD_G7 */ , /* LCD_B0 */ , /* LCD_B1 */ , /* LCD_B2 */ , /* LCD_B3 */ , /* LCD_B4 */ , /* LCD_B5 */ , /* LCD_B6 */ ; /* LCD_B7 */ }; }; mco2_pins_a: mco2-0 { pins { pinmux = ; /* MCO2 */ bias-disable; drive-push-pull; slew-rate = <2>; }; }; mco2_sleep_pins_a: mco2-sleep-0 { pins { pinmux = ; /* MCO2 */ }; }; m_can1_pins_a: m-can1-0 { pins1 { pinmux = ; /* CAN1_TX */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* CAN1_RX */ bias-disable; }; }; m_can1_sleep_pins_a: m_can1-sleep-0 { pins { pinmux = , /* CAN1_TX */ ; /* CAN1_RX */ }; }; m_can1_pins_b: m-can1-1 { pins1 { pinmux = ; /* CAN1_TX */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* CAN1_RX */ bias-disable; }; }; m_can1_sleep_pins_b: m_can1-sleep-1 { pins { pinmux = , /* CAN1_TX */ ; /* CAN1_RX */ }; }; m_can2_pins_a: m-can2-0 { pins1 { pinmux = ; /* CAN2_TX */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* CAN2_RX */ bias-disable; }; }; m_can2_sleep_pins_a: m_can2-sleep-0 { pins { pinmux = , /* CAN2_TX */ ; /* CAN2_RX */ }; }; pwm1_pins_a: pwm1-0 { pins { pinmux = , /* TIM1_CH1 */ , /* TIM1_CH2 */ ; /* TIM1_CH4 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm1_sleep_pins_a: pwm1-sleep-0 { pins { pinmux = , /* TIM1_CH1 */ , /* TIM1_CH2 */ ; /* TIM1_CH4 */ }; }; pwm1_pins_b: pwm1-1 { pins { pinmux = ; /* TIM1_CH1 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm1_sleep_pins_b: pwm1-sleep-1 { pins { pinmux = ; /* TIM1_CH1 */ }; }; pwm2_pins_a: pwm2-0 { pins { pinmux = ; /* TIM2_CH4 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm2_sleep_pins_a: pwm2-sleep-0 { pins { pinmux = ; /* TIM2_CH4 */ }; }; pwm3_pins_a: pwm3-0 { pins { pinmux = ; /* TIM3_CH2 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm3_sleep_pins_a: pwm3-sleep-0 { pins { pinmux = ; /* TIM3_CH2 */ }; }; pwm3_pins_b: pwm3-1 { pins { pinmux = ; /* TIM3_CH2 */ bias-disable; drive-push-pull; slew-rate = <0>; }; }; pwm3_sleep_pins_b: pwm3-sleep-1 { pins { pinmux = ; /* TIM3_CH2 */ }; }; pwm4_pins_a: pwm4-0 { pins { pinmux = , /* TIM4_CH3 */ ; /* TIM4_CH4 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm4_sleep_pins_a: pwm4-sleep-0 { pins { pinmux = , /* TIM4_CH3 */ ; /* TIM4_CH4 */ }; }; pwm4_pins_b: pwm4-1 { pins { pinmux = ; /* TIM4_CH2 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm4_sleep_pins_b: pwm4-sleep-1 { pins { pinmux = ; /* TIM4_CH2 */ }; }; pwm5_pins_a: pwm5-0 { pins { pinmux = ; /* TIM5_CH2 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm5_sleep_pins_a: pwm5-sleep-0 { pins { pinmux = ; /* TIM5_CH2 */ }; }; pwm5_pins_b: pwm5-1 { pins { pinmux = , /* TIM5_CH2 */ , /* TIM5_CH3 */ ; /* TIM5_CH4 */ bias-disable; drive-push-pull; slew-rate = <0>; }; }; pwm5_sleep_pins_b: pwm5-sleep-1 { pins { pinmux = , /* TIM5_CH2 */ , /* TIM5_CH3 */ ; /* TIM5_CH4 */ }; }; pwm8_pins_a: pwm8-0 { pins { pinmux = ; /* TIM8_CH4 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm8_sleep_pins_a: pwm8-sleep-0 { pins { pinmux = ; /* TIM8_CH4 */ }; }; pwm12_pins_a: pwm12-0 { pins { pinmux = ; /* TIM12_CH1 */ bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; pwm12_sleep_pins_a: pwm12-sleep-0 { pins { pinmux = ; /* TIM12_CH1 */ }; }; qspi_clk_pins_a: qspi-clk-0 { pins { pinmux = ; /* QSPI_CLK */ bias-disable; drive-push-pull; slew-rate = <3>; }; }; qspi_clk_sleep_pins_a: qspi-clk-sleep-0 { pins { pinmux = ; /* QSPI_CLK */ }; }; qspi_bk1_pins_a: qspi-bk1-0 { pins1 { pinmux = , /* QSPI_BK1_IO0 */ , /* QSPI_BK1_IO1 */ , /* QSPI_BK1_IO2 */ ; /* QSPI_BK1_IO3 */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* QSPI_BK1_NCS */ bias-pull-up; drive-push-pull; slew-rate = <1>; }; }; qspi_bk1_sleep_pins_a: qspi-bk1-sleep-0 { pins { pinmux = , /* QSPI_BK1_IO0 */ , /* QSPI_BK1_IO1 */ , /* QSPI_BK1_IO2 */ , /* QSPI_BK1_IO3 */ ; /* QSPI_BK1_NCS */ }; }; qspi_bk2_pins_a: qspi-bk2-0 { pins1 { pinmux = , /* QSPI_BK2_IO0 */ , /* QSPI_BK2_IO1 */ , /* QSPI_BK2_IO2 */ ; /* QSPI_BK2_IO3 */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* QSPI_BK2_NCS */ bias-pull-up; drive-push-pull; slew-rate = <1>; }; }; qspi_bk2_sleep_pins_a: qspi-bk2-sleep-0 { pins { pinmux = , /* QSPI_BK2_IO0 */ , /* QSPI_BK2_IO1 */ , /* QSPI_BK2_IO2 */ , /* QSPI_BK2_IO3 */ ; /* QSPI_BK2_NCS */ }; }; sai2a_pins_a: sai2a-0 { pins { pinmux = , /* SAI2_SCK_A */ , /* SAI2_SD_A */ , /* SAI2_FS_A */ ; /* SAI2_MCLK_A */ slew-rate = <0>; drive-push-pull; bias-disable; }; }; sai2a_sleep_pins_a: sai2a-sleep-0 { pins { pinmux = , /* SAI2_SCK_A */ , /* SAI2_SD_A */ , /* SAI2_FS_A */ ; /* SAI2_MCLK_A */ }; }; sai2a_pins_b: sai2a-1 { pins1 { pinmux = , /* SAI2_SD_A */ , /* SAI2_FS_A */ ; /* SAI2_SCK_A */ slew-rate = <0>; drive-push-pull; bias-disable; }; }; sai2a_sleep_pins_b: sai2a-sleep-1 { pins { pinmux = , /* SAI2_SD_A */ , /* SAI2_FS_A */ ; /* SAI2_SCK_A */ }; }; sai2a_pins_c: sai2a-2 { pins { pinmux = , /* SAI2_SCK_A */ , /* SAI2_SD_A */ ; /* SAI2_FS_A */ slew-rate = <0>; drive-push-pull; bias-disable; }; }; sai2a_sleep_pins_c: sai2a-sleep-2 { pins { pinmux = , /* SAI2_SCK_A */ , /* SAI2_SD_A */ ; /* SAI2_FS_A */ }; }; sai2b_pins_a: sai2b-0 { pins1 { pinmux = , /* SAI2_SCK_B */ , /* SAI2_FS_B */ ; /* SAI2_MCLK_B */ slew-rate = <0>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* SAI2_SD_B */ bias-disable; }; }; sai2b_sleep_pins_a: sai2b-sleep-0 { pins { pinmux = , /* SAI2_SD_B */ , /* SAI2_SCK_B */ , /* SAI2_FS_B */ ; /* SAI2_MCLK_B */ }; }; sai2b_pins_b: sai2b-1 { pins { pinmux = ; /* SAI2_SD_B */ bias-disable; }; }; sai2b_sleep_pins_b: sai2b-sleep-1 { pins { pinmux = ; /* SAI2_SD_B */ }; }; sai2b_pins_c: sai2b-2 { pins1 { pinmux = ; /* SAI2_SD_B */ bias-disable; }; }; sai2b_sleep_pins_c: sai2b-sleep-2 { pins { pinmux = ; /* SAI2_SD_B */ }; }; sai4a_pins_a: sai4a-0 { pins { pinmux = ; /* SAI4_SD_A */ slew-rate = <0>; drive-push-pull; bias-disable; }; }; sai4a_sleep_pins_a: sai4a-sleep-0 { pins { pinmux = ; /* SAI4_SD_A */ }; }; sdmmc1_b4_pins_a: sdmmc1-b4-0 { pins1 { pinmux = , /* SDMMC1_D0 */ , /* SDMMC1_D1 */ , /* SDMMC1_D2 */ , /* SDMMC1_D3 */ ; /* SDMMC1_CMD */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* SDMMC1_CK */ slew-rate = <2>; drive-push-pull; bias-disable; }; }; sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 { pins1 { pinmux = , /* SDMMC1_D0 */ , /* SDMMC1_D1 */ , /* SDMMC1_D2 */ ; /* SDMMC1_D3 */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* SDMMC1_CK */ slew-rate = <2>; drive-push-pull; bias-disable; }; pins3 { pinmux = ; /* SDMMC1_CMD */ slew-rate = <1>; drive-open-drain; bias-disable; }; }; sdmmc1_b4_init_pins_a: sdmmc1-b4-init-0 { pins1 { pinmux = , /* SDMMC1_D0 */ , /* SDMMC1_D1 */ , /* SDMMC1_D2 */ ; /* SDMMC1_D3 */ slew-rate = <1>; drive-push-pull; bias-disable; }; }; sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 { pins { pinmux = , /* SDMMC1_D0 */ , /* SDMMC1_D1 */ , /* SDMMC1_D2 */ , /* SDMMC1_D3 */ , /* SDMMC1_CK */ ; /* SDMMC1_CMD */ }; }; sdmmc1_dir_pins_a: sdmmc1-dir-0 { pins1 { pinmux = , /* SDMMC1_D0DIR */ , /* SDMMC1_D123DIR */ ; /* SDMMC1_CDIR */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2{ pinmux = ; /* SDMMC1_CKIN */ bias-pull-up; }; }; sdmmc1_dir_init_pins_a: sdmmc1-dir-init-0 { pins1 { pinmux = , /* SDMMC1_D0DIR */ , /* SDMMC1_D123DIR */ ; /* SDMMC1_CDIR */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; }; sdmmc1_dir_sleep_pins_a: sdmmc1-dir-sleep-0 { pins { pinmux = , /* SDMMC1_D0DIR */ , /* SDMMC1_D123DIR */ , /* SDMMC1_CDIR */ ; /* SDMMC1_CKIN */ }; }; sdmmc1_dir_pins_b: sdmmc1-dir-1 { pins1 { pinmux = , /* SDMMC1_D0DIR */ , /* SDMMC1_D123DIR */ ; /* SDMMC1_CDIR */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2{ pinmux = ; /* SDMMC1_CKIN */ bias-pull-up; }; }; sdmmc1_dir_sleep_pins_b: sdmmc1-dir-sleep-1 { pins { pinmux = , /* SDMMC1_D0DIR */ , /* SDMMC1_D123DIR */ , /* SDMMC1_CDIR */ ; /* SDMMC1_CKIN */ }; }; sdmmc2_b4_pins_a: sdmmc2-b4-0 { pins1 { pinmux = , /* SDMMC2_D0 */ , /* SDMMC2_D1 */ , /* SDMMC2_D2 */ , /* SDMMC2_D3 */ ; /* SDMMC2_CMD */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2 { pinmux = ; /* SDMMC2_CK */ slew-rate = <2>; drive-push-pull; bias-pull-up; }; }; sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 { pins1 { pinmux = , /* SDMMC2_D0 */ , /* SDMMC2_D1 */ , /* SDMMC2_D2 */ ; /* SDMMC2_D3 */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2 { pinmux = ; /* SDMMC2_CK */ slew-rate = <2>; drive-push-pull; bias-pull-up; }; pins3 { pinmux = ; /* SDMMC2_CMD */ slew-rate = <1>; drive-open-drain; bias-pull-up; }; }; sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 { pins { pinmux = , /* SDMMC2_D0 */ , /* SDMMC2_D1 */ , /* SDMMC2_D2 */ , /* SDMMC2_D3 */ , /* SDMMC2_CK */ ; /* SDMMC2_CMD */ }; }; sdmmc2_b4_pins_b: sdmmc2-b4-1 { pins1 { pinmux = , /* SDMMC2_D0 */ , /* SDMMC2_D1 */ , /* SDMMC2_D2 */ , /* SDMMC2_D3 */ ; /* SDMMC2_CMD */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* SDMMC2_CK */ slew-rate = <2>; drive-push-pull; bias-disable; }; }; sdmmc2_b4_od_pins_b: sdmmc2-b4-od-1 { pins1 { pinmux = , /* SDMMC2_D0 */ , /* SDMMC2_D1 */ , /* SDMMC2_D2 */ ; /* SDMMC2_D3 */ slew-rate = <1>; drive-push-pull; bias-disable; }; pins2 { pinmux = ; /* SDMMC2_CK */ slew-rate = <2>; drive-push-pull; bias-disable; }; pins3 { pinmux = ; /* SDMMC2_CMD */ slew-rate = <1>; drive-open-drain; bias-disable; }; }; sdmmc2_d47_pins_a: sdmmc2-d47-0 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; }; sdmmc2_d47_sleep_pins_a: sdmmc2-d47-sleep-0 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ }; }; sdmmc2_d47_pins_b: sdmmc2-d47-1 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ slew-rate = <1>; drive-push-pull; bias-disable; }; }; sdmmc2_d47_sleep_pins_b: sdmmc2-d47-sleep-1 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ }; }; sdmmc2_d47_pins_c: sdmmc2-d47-2 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; }; sdmmc2_d47_sleep_pins_c: sdmmc2-d47-sleep-2 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ }; }; sdmmc2_d47_pins_d: sdmmc2-d47-3 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ }; }; sdmmc2_d47_sleep_pins_d: sdmmc2-d47-sleep-3 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ }; }; sdmmc3_b4_pins_a: sdmmc3-b4-0 { pins1 { pinmux = , /* SDMMC3_D0 */ , /* SDMMC3_D1 */ , /* SDMMC3_D2 */ , /* SDMMC3_D3 */ ; /* SDMMC3_CMD */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2 { pinmux = ; /* SDMMC3_CK */ slew-rate = <2>; drive-push-pull; bias-pull-up; }; }; sdmmc3_b4_od_pins_a: sdmmc3-b4-od-0 { pins1 { pinmux = , /* SDMMC3_D0 */ , /* SDMMC3_D1 */ , /* SDMMC3_D2 */ ; /* SDMMC3_D3 */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2 { pinmux = ; /* SDMMC3_CK */ slew-rate = <2>; drive-push-pull; bias-pull-up; }; pins3 { pinmux = ; /* SDMMC2_CMD */ slew-rate = <1>; drive-open-drain; bias-pull-up; }; }; sdmmc3_b4_sleep_pins_a: sdmmc3-b4-sleep-0 { pins { pinmux = , /* SDMMC3_D0 */ , /* SDMMC3_D1 */ , /* SDMMC3_D2 */ , /* SDMMC3_D3 */ , /* SDMMC3_CK */ ; /* SDMMC3_CMD */ }; }; sdmmc3_b4_pins_b: sdmmc3-b4-1 { pins1 { pinmux = , /* SDMMC3_D0 */ , /* SDMMC3_D1 */ , /* SDMMC3_D2 */ , /* SDMMC3_D3 */ ; /* SDMMC3_CMD */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2 { pinmux = ; /* SDMMC3_CK */ slew-rate = <2>; drive-push-pull; bias-pull-up; }; }; sdmmc3_b4_od_pins_b: sdmmc3-b4-od-1 { pins1 { pinmux = , /* SDMMC3_D0 */ , /* SDMMC3_D1 */ , /* SDMMC3_D2 */ ; /* SDMMC3_D3 */ slew-rate = <1>; drive-push-pull; bias-pull-up; }; pins2 { pinmux = ; /* SDMMC3_CK */ slew-rate = <2>; drive-push-pull; bias-pull-up; }; pins3 { pinmux = ; /* SDMMC2_CMD */ slew-rate = <1>; drive-open-drain; bias-pull-up; }; }; sdmmc3_b4_sleep_pins_b: sdmmc3-b4-sleep-1 { pins { pinmux = , /* SDMMC3_D0 */ , /* SDMMC3_D1 */ , /* SDMMC3_D2 */ , /* SDMMC3_D3 */ , /* SDMMC3_CK */ ; /* SDMMC3_CMD */ }; }; spdifrx_pins_a: spdifrx-0 { pins { pinmux = ; /* SPDIF_IN1 */ bias-disable; }; }; spdifrx_sleep_pins_a: spdifrx-sleep-0 { pins { pinmux = ; /* SPDIF_IN1 */ }; }; spi2_pins_a: spi2-0 { pins1 { pinmux = , /* SPI1_SCK */ ; /* SPI1_MOSI */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* SPI1_MISO */ bias-disable; }; }; spi4_pins_a: spi4-0 { pins { pinmux = , /* SPI4_SCK */ ; /* SPI4_MOSI */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* SPI4_MISO */ bias-disable; }; }; stusb1600_pins_a: stusb1600-0 { pins { pinmux = ; bias-pull-up; }; }; uart4_pins_a: uart4-0 { pins1 { pinmux = ; /* UART4_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART4_RX */ bias-disable; }; }; uart4_idle_pins_a: uart4-idle-0 { pins1 { pinmux = ; /* UART4_TX */ }; pins2 { pinmux = ; /* UART4_RX */ bias-disable; }; }; uart4_sleep_pins_a: uart4-sleep-0 { pins { pinmux = , /* UART4_TX */ ; /* UART4_RX */ }; }; uart4_pins_b: uart4-1 { pins1 { pinmux = ; /* UART4_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART4_RX */ bias-disable; }; }; uart4_pins_c: uart4-2 { pins1 { pinmux = ; /* UART4_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART4_RX */ bias-disable; }; }; uart7_pins_a: uart7-0 { pins1 { pinmux = ; /* UART7_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* UART7_RX */ , /* UART7_CTS */ ; /* UART7_RTS */ bias-disable; }; }; uart7_pins_b: uart7-1 { pins1 { pinmux = ; /* UART7_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART7_RX */ bias-disable; }; }; uart7_pins_c: uart7-2 { pins1 { pinmux = ; /* UART7_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART7_RX */ bias-pull-up; }; }; uart7_idle_pins_c: uart7-idle-2 { pins1 { pinmux = ; /* UART7_TX */ }; pins2 { pinmux = ; /* UART7_RX */ bias-pull-up; }; }; uart7_sleep_pins_c: uart7-sleep-2 { pins { pinmux = , /* UART7_TX */ ; /* UART7_RX */ }; }; uart8_pins_a: uart8-0 { pins1 { pinmux = ; /* UART8_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* UART8_RX */ bias-disable; }; }; uart8_rtscts_pins_a: uart8rtscts-0 { pins { pinmux = , /* UART8_RTS */ ; /* UART8_CTS */ bias-disable; }; }; usart2_pins_a: usart2-0 { pins1 { pinmux = , /* USART2_TX */ ; /* USART2_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART2_RX */ ; /* USART2_CTS_NSS */ bias-disable; }; }; usart2_sleep_pins_a: usart2-sleep-0 { pins { pinmux = , /* USART2_TX */ , /* USART2_RTS */ , /* USART2_RX */ ; /* USART2_CTS_NSS */ }; }; usart2_pins_b: usart2-1 { pins1 { pinmux = , /* USART2_TX */ ; /* USART2_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART2_RX */ ; /* USART2_CTS_NSS */ bias-disable; }; }; usart2_sleep_pins_b: usart2-sleep-1 { pins { pinmux = , /* USART2_TX */ , /* USART2_RTS */ , /* USART2_RX */ ; /* USART2_CTS_NSS */ }; }; usart2_pins_c: usart2-2 { pins1 { pinmux = , /* USART2_TX */ ; /* USART2_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART2_RX */ ; /* USART2_CTS_NSS */ bias-disable; }; }; usart2_idle_pins_c: usart2-idle-2 { pins1 { pinmux = , /* USART2_TX */ ; /* USART2_CTS_NSS */ }; pins2 { pinmux = ; /* USART2_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = ; /* USART2_RX */ bias-disable; }; }; usart2_sleep_pins_c: usart2-sleep-2 { pins { pinmux = , /* USART2_TX */ , /* USART2_RTS */ , /* USART2_RX */ ; /* USART2_CTS_NSS */ }; }; usart3_pins_a: usart3-0 { pins1 { pinmux = ; /* USART3_TX */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = ; /* USART3_RX */ bias-disable; }; }; usart3_pins_b: usart3-1 { pins1 { pinmux = , /* USART3_TX */ ; /* USART3_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART3_RX */ ; /* USART3_CTS_NSS */ bias-pull-up; }; }; usart3_idle_pins_b: usart3-idle-1 { pins1 { pinmux = , /* USART3_TX */ ; /* USART3_CTS_NSS */ }; pins2 { pinmux = ; /* USART3_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = ; /* USART3_RX */ bias-pull-up; }; }; usart3_sleep_pins_b: usart3-sleep-1 { pins { pinmux = , /* USART3_TX */ , /* USART3_RTS */ , /* USART3_CTS_NSS */ ; /* USART3_RX */ }; }; usart3_pins_c: usart3-2 { pins1 { pinmux = , /* USART3_TX */ ; /* USART3_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART3_RX */ ; /* USART3_CTS_NSS */ bias-pull-up; }; }; usart3_idle_pins_c: usart3-idle-2 { pins1 { pinmux = , /* USART3_TX */ ; /* USART3_CTS_NSS */ }; pins2 { pinmux = ; /* USART3_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins3 { pinmux = ; /* USART3_RX */ bias-pull-up; }; }; usart3_sleep_pins_c: usart3-sleep-2 { pins { pinmux = , /* USART3_TX */ , /* USART3_RTS */ , /* USART3_CTS_NSS */ ; /* USART3_RX */ }; }; usart3_pins_d: usart3-3 { pins1 { pinmux = , /* USART3_TX */ ; /* USART3_RTS */ bias-disable; drive-push-pull; slew-rate = <0>; }; pins2 { pinmux = , /* USART3_RX */ ; /* USART3_CTS_NSS */ bias-disable; }; }; usart3_idle_pins_d: usart3-idle-3 { pins1 { pinmux = , /* USART3_TX */ , /* USART3_RTS */ ; /* USART3_CTS_NSS */ }; pins2 { pinmux = ; /* USART3_RX */ bias-disable; }; }; usart3_sleep_pins_d: usart3-sleep-3 { pins { pinmux = , /* USART3_TX */ , /* USART3_RTS */ , /* USART3_CTS_NSS */ ; /* USART3_RX */ }; }; usbotg_hs_pins_a: usbotg-hs-0 { pins { pinmux = ; /* OTG_ID */ }; }; usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { pins { pinmux = , /* OTG_FS_DM */ ; /* OTG_FS_DP */ }; }; }; &pinctrl_z { i2c2_pins_b2: i2c2-0 { pins { pinmux = ; /* I2C2_SCL */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c2_sleep_pins_b2: i2c2-sleep-0 { pins { pinmux = ; /* I2C2_SCL */ }; }; i2c4_pins_a: i2c4-0 { pins { pinmux = , /* I2C4_SCL */ ; /* I2C4_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c4_sleep_pins_a: i2c4-sleep-0 { pins { pinmux = , /* I2C4_SCL */ ; /* I2C4_SDA */ }; }; i2c6_pins_a: i2c6-0 { pins { pinmux = , /* I2C6_SCL */ ; /* I2C6_SDA */ bias-disable; drive-open-drain; slew-rate = <0>; }; }; i2c6_sleep_pins_a: i2c6-sleep-0 { pins { pinmux = , /* I2C6_SCL */ ; /* I2C6_SDA */ }; }; spi1_pins_a: spi1-0 { pins1 { pinmux = , /* SPI1_SCK */ ; /* SPI1_MOSI */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* SPI1_MISO */ bias-disable; }; }; spi1_pins_b: spi1-1 { pins1 { pinmux = , /* SPI1_SCK */ ; /* SPI1_MOSI */ bias-disable; drive-push-pull; slew-rate = <1>; }; pins2 { pinmux = ; /* SPI1_MISO */ bias-disable; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp151.dtsi000066400000000000000000001265401464416617300212160ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ #include #include #include / { #address-cells = <1>; #size-cells = <1>; cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { compatible = "arm,cortex-a7"; clock-frequency = <650000000>; device_type = "cpu"; reg = <0>; }; }; arm-pmu { compatible = "arm,cortex-a7-pmu"; interrupts = ; interrupt-affinity = <&cpu0>; interrupt-parent = <&intc>; }; psci { compatible = "arm,psci-1.0"; method = "smc"; }; intc: interrupt-controller@a0021000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; interrupt-controller; reg = <0xa0021000 0x1000>, <0xa0022000 0x2000>; }; timer { compatible = "arm,armv7-timer"; interrupts = , , , ; interrupt-parent = <&intc>; }; clocks { clk_hse: clk-hse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <24000000>; }; clk_hsi: clk-hsi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <64000000>; }; clk_lse: clk-lse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32768>; }; clk_lsi: clk-lsi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32000>; }; clk_csi: clk-csi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <4000000>; }; }; thermal-zones { cpu_thermal: cpu-thermal { polling-delay-passive = <0>; polling-delay = <0>; thermal-sensors = <&dts>; trips { cpu_alert1: cpu-alert1 { temperature = <85000>; hysteresis = <0>; type = "passive"; }; cpu-crit { temperature = <120000>; hysteresis = <0>; type = "critical"; }; }; cooling-maps { }; }; }; booster: regulator-booster { compatible = "st,stm32mp1-booster"; st,syscfg = <&syscfg>; status = "disabled"; }; soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; ranges; timers2: timer@40000000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40000000 0x400>; clocks = <&rcc TIM2_K>; clock-names = "int"; dmas = <&dmamux1 18 0x400 0x1>, <&dmamux1 19 0x400 0x1>, <&dmamux1 20 0x400 0x1>, <&dmamux1 21 0x400 0x1>, <&dmamux1 22 0x400 0x1>; dma-names = "ch1", "ch2", "ch3", "ch4", "up"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@1 { compatible = "st,stm32h7-timer-trigger"; reg = <1>; status = "disabled"; }; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers3: timer@40001000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40001000 0x400>; clocks = <&rcc TIM3_K>; clock-names = "int"; dmas = <&dmamux1 23 0x400 0x1>, <&dmamux1 24 0x400 0x1>, <&dmamux1 25 0x400 0x1>, <&dmamux1 26 0x400 0x1>, <&dmamux1 27 0x400 0x1>, <&dmamux1 28 0x400 0x1>; dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@2 { compatible = "st,stm32h7-timer-trigger"; reg = <2>; status = "disabled"; }; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers4: timer@40002000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40002000 0x400>; clocks = <&rcc TIM4_K>; clock-names = "int"; dmas = <&dmamux1 29 0x400 0x1>, <&dmamux1 30 0x400 0x1>, <&dmamux1 31 0x400 0x1>, <&dmamux1 32 0x400 0x1>; dma-names = "ch1", "ch2", "ch3", "ch4"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@3 { compatible = "st,stm32h7-timer-trigger"; reg = <3>; status = "disabled"; }; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers5: timer@40003000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40003000 0x400>; clocks = <&rcc TIM5_K>; clock-names = "int"; dmas = <&dmamux1 55 0x400 0x1>, <&dmamux1 56 0x400 0x1>, <&dmamux1 57 0x400 0x1>, <&dmamux1 58 0x400 0x1>, <&dmamux1 59 0x400 0x1>, <&dmamux1 60 0x400 0x1>; dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@4 { compatible = "st,stm32h7-timer-trigger"; reg = <4>; status = "disabled"; }; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers6: timer@40004000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40004000 0x400>; clocks = <&rcc TIM6_K>; clock-names = "int"; dmas = <&dmamux1 69 0x400 0x1>; dma-names = "up"; status = "disabled"; timer@5 { compatible = "st,stm32h7-timer-trigger"; reg = <5>; status = "disabled"; }; }; timers7: timer@40005000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40005000 0x400>; clocks = <&rcc TIM7_K>; clock-names = "int"; dmas = <&dmamux1 70 0x400 0x1>; dma-names = "up"; status = "disabled"; timer@6 { compatible = "st,stm32h7-timer-trigger"; reg = <6>; status = "disabled"; }; }; timers12: timer@40006000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40006000 0x400>; clocks = <&rcc TIM12_K>; clock-names = "int"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@11 { compatible = "st,stm32h7-timer-trigger"; reg = <11>; status = "disabled"; }; }; timers13: timer@40007000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40007000 0x400>; clocks = <&rcc TIM13_K>; clock-names = "int"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@12 { compatible = "st,stm32h7-timer-trigger"; reg = <12>; status = "disabled"; }; }; timers14: timer@40008000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x40008000 0x400>; clocks = <&rcc TIM14_K>; clock-names = "int"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@13 { compatible = "st,stm32h7-timer-trigger"; reg = <13>; status = "disabled"; }; }; lptimer1: timer@40009000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-lptimer"; reg = <0x40009000 0x400>; interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM1_K>; clock-names = "mux"; wakeup-source; status = "disabled"; pwm { compatible = "st,stm32-pwm-lp"; #pwm-cells = <3>; status = "disabled"; }; trigger@0 { compatible = "st,stm32-lptimer-trigger"; reg = <0>; status = "disabled"; }; counter { compatible = "st,stm32-lptimer-counter"; status = "disabled"; }; }; spi2: spi@4000b000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x4000b000 0x400>; interrupts = ; clocks = <&rcc SPI2_K>; resets = <&rcc SPI2_R>; dmas = <&dmamux1 39 0x400 0x05>, <&dmamux1 40 0x400 0x05>; dma-names = "rx", "tx"; status = "disabled"; }; i2s2: audio-controller@4000b000 { compatible = "st,stm32h7-i2s"; #sound-dai-cells = <0>; reg = <0x4000b000 0x400>; interrupts = ; dmas = <&dmamux1 39 0x400 0x01>, <&dmamux1 40 0x400 0x01>; dma-names = "rx", "tx"; status = "disabled"; }; spi3: spi@4000c000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x4000c000 0x400>; interrupts = ; clocks = <&rcc SPI3_K>; resets = <&rcc SPI3_R>; dmas = <&dmamux1 61 0x400 0x05>, <&dmamux1 62 0x400 0x05>; dma-names = "rx", "tx"; status = "disabled"; }; i2s3: audio-controller@4000c000 { compatible = "st,stm32h7-i2s"; #sound-dai-cells = <0>; reg = <0x4000c000 0x400>; interrupts = ; dmas = <&dmamux1 61 0x400 0x01>, <&dmamux1 62 0x400 0x01>; dma-names = "rx", "tx"; status = "disabled"; }; spdifrx: audio-controller@4000d000 { compatible = "st,stm32h7-spdifrx"; #sound-dai-cells = <0>; reg = <0x4000d000 0x400>; clocks = <&rcc SPDIF_K>; clock-names = "kclk"; interrupts = ; dmas = <&dmamux1 93 0x400 0x01>, <&dmamux1 94 0x400 0x01>; dma-names = "rx", "rx-ctrl"; status = "disabled"; }; usart2: serial@4000e000 { compatible = "st,stm32h7-uart"; reg = <0x4000e000 0x400>; interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART2_K>; wakeup-source; dmas = <&dmamux1 43 0x400 0x15>, <&dmamux1 44 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; usart3: serial@4000f000 { compatible = "st,stm32h7-uart"; reg = <0x4000f000 0x400>; interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART3_K>; wakeup-source; dmas = <&dmamux1 45 0x400 0x15>, <&dmamux1 46 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; uart4: serial@40010000 { compatible = "st,stm32h7-uart"; reg = <0x40010000 0x400>; interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART4_K>; wakeup-source; dmas = <&dmamux1 63 0x400 0x15>, <&dmamux1 64 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; uart5: serial@40011000 { compatible = "st,stm32h7-uart"; reg = <0x40011000 0x400>; interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART5_K>; wakeup-source; dmas = <&dmamux1 65 0x400 0x15>, <&dmamux1 66 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; i2c1: i2c@40012000 { compatible = "st,stm32mp15-i2c"; reg = <0x40012000 0x400>; interrupt-names = "event", "error"; interrupts = , ; clocks = <&rcc I2C1_K>; resets = <&rcc I2C1_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x1>; wakeup-source; i2c-analog-filter; status = "disabled"; }; i2c2: i2c@40013000 { compatible = "st,stm32mp15-i2c"; reg = <0x40013000 0x400>; interrupt-names = "event", "error"; interrupts = , ; clocks = <&rcc I2C2_K>; resets = <&rcc I2C2_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x2>; wakeup-source; i2c-analog-filter; status = "disabled"; }; i2c3: i2c@40014000 { compatible = "st,stm32mp15-i2c"; reg = <0x40014000 0x400>; interrupt-names = "event", "error"; interrupts = , ; clocks = <&rcc I2C3_K>; resets = <&rcc I2C3_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x4>; wakeup-source; i2c-analog-filter; status = "disabled"; }; i2c5: i2c@40015000 { compatible = "st,stm32mp15-i2c"; reg = <0x40015000 0x400>; interrupt-names = "event", "error"; interrupts = , ; clocks = <&rcc I2C5_K>; resets = <&rcc I2C5_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x10>; wakeup-source; i2c-analog-filter; status = "disabled"; }; cec: cec@40016000 { compatible = "st,stm32-cec"; reg = <0x40016000 0x400>; interrupts = ; clocks = <&rcc CEC_K>, <&rcc CEC>; clock-names = "cec", "hdmi-cec"; status = "disabled"; }; dac: dac@40017000 { compatible = "st,stm32h7-dac-core"; reg = <0x40017000 0x400>; clocks = <&rcc DAC12>; clock-names = "pclk"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; dac1: dac@1 { compatible = "st,stm32-dac"; #io-channel-cells = <1>; reg = <1>; status = "disabled"; }; dac2: dac@2 { compatible = "st,stm32-dac"; #io-channel-cells = <1>; reg = <2>; status = "disabled"; }; }; uart7: serial@40018000 { compatible = "st,stm32h7-uart"; reg = <0x40018000 0x400>; interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART7_K>; wakeup-source; dmas = <&dmamux1 79 0x400 0x15>, <&dmamux1 80 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; uart8: serial@40019000 { compatible = "st,stm32h7-uart"; reg = <0x40019000 0x400>; interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc UART8_K>; wakeup-source; dmas = <&dmamux1 81 0x400 0x15>, <&dmamux1 82 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; timers1: timer@44000000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x44000000 0x400>; clocks = <&rcc TIM1_K>; clock-names = "int"; dmas = <&dmamux1 11 0x400 0x1>, <&dmamux1 12 0x400 0x1>, <&dmamux1 13 0x400 0x1>, <&dmamux1 14 0x400 0x1>, <&dmamux1 15 0x400 0x1>, <&dmamux1 16 0x400 0x1>, <&dmamux1 17 0x400 0x1>; dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig", "com"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@0 { compatible = "st,stm32h7-timer-trigger"; reg = <0>; status = "disabled"; }; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; timers8: timer@44001000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x44001000 0x400>; clocks = <&rcc TIM8_K>; clock-names = "int"; dmas = <&dmamux1 47 0x400 0x1>, <&dmamux1 48 0x400 0x1>, <&dmamux1 49 0x400 0x1>, <&dmamux1 50 0x400 0x1>, <&dmamux1 51 0x400 0x1>, <&dmamux1 52 0x400 0x1>, <&dmamux1 53 0x400 0x1>; dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig", "com"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@7 { compatible = "st,stm32h7-timer-trigger"; reg = <7>; status = "disabled"; }; counter { compatible = "st,stm32-timer-counter"; status = "disabled"; }; }; usart6: serial@44003000 { compatible = "st,stm32h7-uart"; reg = <0x44003000 0x400>; interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART6_K>; wakeup-source; dmas = <&dmamux1 71 0x400 0x15>, <&dmamux1 72 0x400 0x11>; dma-names = "rx", "tx"; status = "disabled"; }; spi1: spi@44004000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x44004000 0x400>; interrupts = ; clocks = <&rcc SPI1_K>; resets = <&rcc SPI1_R>; dmas = <&dmamux1 37 0x400 0x05>, <&dmamux1 38 0x400 0x05>; dma-names = "rx", "tx"; status = "disabled"; }; i2s1: audio-controller@44004000 { compatible = "st,stm32h7-i2s"; #sound-dai-cells = <0>; reg = <0x44004000 0x400>; interrupts = ; dmas = <&dmamux1 37 0x400 0x01>, <&dmamux1 38 0x400 0x01>; dma-names = "rx", "tx"; status = "disabled"; }; spi4: spi@44005000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x44005000 0x400>; interrupts = ; clocks = <&rcc SPI4_K>; resets = <&rcc SPI4_R>; dmas = <&dmamux1 83 0x400 0x05>, <&dmamux1 84 0x400 0x05>; dma-names = "rx", "tx"; status = "disabled"; }; timers15: timer@44006000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x44006000 0x400>; clocks = <&rcc TIM15_K>; clock-names = "int"; dmas = <&dmamux1 105 0x400 0x1>, <&dmamux1 106 0x400 0x1>, <&dmamux1 107 0x400 0x1>, <&dmamux1 108 0x400 0x1>; dma-names = "ch1", "up", "trig", "com"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@14 { compatible = "st,stm32h7-timer-trigger"; reg = <14>; status = "disabled"; }; }; timers16: timer@44007000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x44007000 0x400>; clocks = <&rcc TIM16_K>; clock-names = "int"; dmas = <&dmamux1 109 0x400 0x1>, <&dmamux1 110 0x400 0x1>; dma-names = "ch1", "up"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@15 { compatible = "st,stm32h7-timer-trigger"; reg = <15>; status = "disabled"; }; }; timers17: timer@44008000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-timers"; reg = <0x44008000 0x400>; clocks = <&rcc TIM17_K>; clock-names = "int"; dmas = <&dmamux1 111 0x400 0x1>, <&dmamux1 112 0x400 0x1>; dma-names = "ch1", "up"; status = "disabled"; pwm { compatible = "st,stm32-pwm"; #pwm-cells = <3>; status = "disabled"; }; timer@16 { compatible = "st,stm32h7-timer-trigger"; reg = <16>; status = "disabled"; }; }; spi5: spi@44009000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x44009000 0x400>; interrupts = ; clocks = <&rcc SPI5_K>; resets = <&rcc SPI5_R>; dmas = <&dmamux1 85 0x400 0x05>, <&dmamux1 86 0x400 0x05>; dma-names = "rx", "tx"; status = "disabled"; }; sai1: sai@4400a000 { compatible = "st,stm32h7-sai"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x4400a000 0x400>; reg = <0x4400a000 0x4>, <0x4400a3f0 0x10>; interrupts = ; resets = <&rcc SAI1_R>; status = "disabled"; sai1a: audio-controller@4400a004 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-a"; reg = <0x4 0x20>; clocks = <&rcc SAI1_K>; clock-names = "sai_ck"; dmas = <&dmamux1 87 0x400 0x01>; status = "disabled"; }; sai1b: audio-controller@4400a024 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-b"; reg = <0x24 0x20>; clocks = <&rcc SAI1_K>; clock-names = "sai_ck"; dmas = <&dmamux1 88 0x400 0x01>; status = "disabled"; }; }; sai2: sai@4400b000 { compatible = "st,stm32h7-sai"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x4400b000 0x400>; reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>; interrupts = ; resets = <&rcc SAI2_R>; status = "disabled"; sai2a: audio-controller@4400b004 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-a"; reg = <0x4 0x20>; clocks = <&rcc SAI2_K>; clock-names = "sai_ck"; dmas = <&dmamux1 89 0x400 0x01>; status = "disabled"; }; sai2b: audio-controller@4400b024 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-b"; reg = <0x24 0x20>; clocks = <&rcc SAI2_K>; clock-names = "sai_ck"; dmas = <&dmamux1 90 0x400 0x01>; status = "disabled"; }; }; sai3: sai@4400c000 { compatible = "st,stm32h7-sai"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x4400c000 0x400>; reg = <0x4400c000 0x4>, <0x4400c3f0 0x10>; interrupts = ; resets = <&rcc SAI3_R>; status = "disabled"; sai3a: audio-controller@4400c004 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-a"; reg = <0x04 0x20>; clocks = <&rcc SAI3_K>; clock-names = "sai_ck"; dmas = <&dmamux1 113 0x400 0x01>; status = "disabled"; }; sai3b: audio-controller@4400c024 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-b"; reg = <0x24 0x20>; clocks = <&rcc SAI3_K>; clock-names = "sai_ck"; dmas = <&dmamux1 114 0x400 0x01>; status = "disabled"; }; }; dfsdm: dfsdm@4400d000 { compatible = "st,stm32mp1-dfsdm"; reg = <0x4400d000 0x800>; clocks = <&rcc DFSDM_K>; clock-names = "dfsdm"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; dfsdm0: filter@0 { compatible = "st,stm32-dfsdm-adc"; #io-channel-cells = <1>; reg = <0>; interrupts = ; dmas = <&dmamux1 101 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; dfsdm1: filter@1 { compatible = "st,stm32-dfsdm-adc"; #io-channel-cells = <1>; reg = <1>; interrupts = ; dmas = <&dmamux1 102 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; dfsdm2: filter@2 { compatible = "st,stm32-dfsdm-adc"; #io-channel-cells = <1>; reg = <2>; interrupts = ; dmas = <&dmamux1 103 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; dfsdm3: filter@3 { compatible = "st,stm32-dfsdm-adc"; #io-channel-cells = <1>; reg = <3>; interrupts = ; dmas = <&dmamux1 104 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; dfsdm4: filter@4 { compatible = "st,stm32-dfsdm-adc"; #io-channel-cells = <1>; reg = <4>; interrupts = ; dmas = <&dmamux1 91 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; dfsdm5: filter@5 { compatible = "st,stm32-dfsdm-adc"; #io-channel-cells = <1>; reg = <5>; interrupts = ; dmas = <&dmamux1 92 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; }; dma1: dma-controller@48000000 { compatible = "st,stm32-dma"; reg = <0x48000000 0x400>; interrupts = , , , , , , , ; clocks = <&rcc DMA1>; resets = <&rcc DMA1_R>; #dma-cells = <4>; st,mem2mem; dma-requests = <8>; }; dma2: dma-controller@48001000 { compatible = "st,stm32-dma"; reg = <0x48001000 0x400>; interrupts = , , , , , , , ; clocks = <&rcc DMA2>; resets = <&rcc DMA2_R>; #dma-cells = <4>; st,mem2mem; dma-requests = <8>; }; dmamux1: dma-router@48002000 { compatible = "st,stm32h7-dmamux"; reg = <0x48002000 0x40>; #dma-cells = <3>; dma-requests = <128>; dma-masters = <&dma1 &dma2>; dma-channels = <16>; clocks = <&rcc DMAMUX>; resets = <&rcc DMAMUX_R>; }; adc: adc@48003000 { compatible = "st,stm32mp1-adc-core"; reg = <0x48003000 0x400>; interrupts = , ; clocks = <&rcc ADC12>, <&rcc ADC12_K>; clock-names = "bus", "adc"; interrupt-controller; st,syscfg = <&syscfg>; #interrupt-cells = <1>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; adc1: adc@0 { compatible = "st,stm32mp1-adc"; #io-channel-cells = <1>; reg = <0x0>; interrupt-parent = <&adc>; interrupts = <0>; dmas = <&dmamux1 9 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; adc2: adc@100 { compatible = "st,stm32mp1-adc"; #io-channel-cells = <1>; reg = <0x100>; interrupt-parent = <&adc>; interrupts = <1>; dmas = <&dmamux1 10 0x400 0x01>; dma-names = "rx"; status = "disabled"; }; }; sdmmc3: mmc@48004000 { compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; arm,primecell-periphid = <0x00253180>; reg = <0x48004000 0x400>; interrupts = ; interrupt-names = "cmd_irq"; clocks = <&rcc SDMMC3_K>; clock-names = "apb_pclk"; resets = <&rcc SDMMC3_R>; cap-sd-highspeed; cap-mmc-highspeed; max-frequency = <120000000>; status = "disabled"; }; usbotg_hs: usb-otg@49000000 { compatible = "st,stm32mp15-hsotg", "snps,dwc2"; reg = <0x49000000 0x10000>; clocks = <&rcc USBO_K>; clock-names = "otg"; resets = <&rcc USBO_R>; reset-names = "dwc2"; interrupts = ; g-rx-fifo-size = <512>; g-np-tx-fifo-size = <32>; g-tx-fifo-size = <256 16 16 16 16 16 16 16>; dr_mode = "otg"; otg-rev = <0x200>; usb33d-supply = <&usb33>; status = "disabled"; }; ipcc: mailbox@4c001000 { compatible = "st,stm32mp1-ipcc"; #mbox-cells = <1>; reg = <0x4c001000 0x400>; st,proc-id = <0>; interrupts-extended = <&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>, <&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>, <&exti 61 1>; interrupt-names = "rx", "tx", "wakeup"; clocks = <&rcc IPCC>; wakeup-source; status = "disabled"; }; dcmi: dcmi@4c006000 { compatible = "st,stm32-dcmi"; reg = <0x4c006000 0x400>; interrupts = ; resets = <&rcc CAMITF_R>; clocks = <&rcc DCMI>; clock-names = "mclk"; dmas = <&dmamux1 75 0x400 0x01>; dma-names = "tx"; status = "disabled"; }; rcc: rcc@50000000 { compatible = "st,stm32mp1-rcc", "syscon"; reg = <0x50000000 0x1000>; #clock-cells = <1>; #reset-cells = <1>; }; pwr_regulators: pwr@50001000 { compatible = "st,stm32mp1,pwr-reg"; reg = <0x50001000 0x10>; reg11: reg11 { regulator-name = "reg11"; regulator-min-microvolt = <1100000>; regulator-max-microvolt = <1100000>; }; reg18: reg18 { regulator-name = "reg18"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; }; usb33: usb33 { regulator-name = "usb33"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; }; }; pwr_mcu: pwr_mcu@50001014 { compatible = "st,stm32mp151-pwr-mcu", "syscon"; reg = <0x50001014 0x4>; }; exti: interrupt-controller@5000d000 { compatible = "st,stm32mp1-exti", "syscon"; interrupt-controller; #interrupt-cells = <2>; reg = <0x5000d000 0x400>; }; syscfg: syscon@50020000 { compatible = "st,stm32mp157-syscfg", "syscon"; reg = <0x50020000 0x400>; clocks = <&rcc SYSCFG>; }; lptimer2: timer@50021000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-lptimer"; reg = <0x50021000 0x400>; interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM2_K>; clock-names = "mux"; wakeup-source; status = "disabled"; pwm { compatible = "st,stm32-pwm-lp"; #pwm-cells = <3>; status = "disabled"; }; trigger@1 { compatible = "st,stm32-lptimer-trigger"; reg = <1>; status = "disabled"; }; counter { compatible = "st,stm32-lptimer-counter"; status = "disabled"; }; }; lptimer3: timer@50022000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32-lptimer"; reg = <0x50022000 0x400>; interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM3_K>; clock-names = "mux"; wakeup-source; status = "disabled"; pwm { compatible = "st,stm32-pwm-lp"; #pwm-cells = <3>; status = "disabled"; }; trigger@2 { compatible = "st,stm32-lptimer-trigger"; reg = <2>; status = "disabled"; }; }; lptimer4: timer@50023000 { compatible = "st,stm32-lptimer"; reg = <0x50023000 0x400>; interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM4_K>; clock-names = "mux"; wakeup-source; status = "disabled"; pwm { compatible = "st,stm32-pwm-lp"; #pwm-cells = <3>; status = "disabled"; }; }; lptimer5: timer@50024000 { compatible = "st,stm32-lptimer"; reg = <0x50024000 0x400>; interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc LPTIM5_K>; clock-names = "mux"; wakeup-source; status = "disabled"; pwm { compatible = "st,stm32-pwm-lp"; #pwm-cells = <3>; status = "disabled"; }; }; vrefbuf: vrefbuf@50025000 { compatible = "st,stm32-vrefbuf"; reg = <0x50025000 0x8>; regulator-min-microvolt = <1500000>; regulator-max-microvolt = <2500000>; clocks = <&rcc VREF>; status = "disabled"; }; sai4: sai@50027000 { compatible = "st,stm32h7-sai"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0x50027000 0x400>; reg = <0x50027000 0x4>, <0x500273f0 0x10>; interrupts = ; resets = <&rcc SAI4_R>; status = "disabled"; sai4a: audio-controller@50027004 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-a"; reg = <0x04 0x20>; clocks = <&rcc SAI4_K>; clock-names = "sai_ck"; dmas = <&dmamux1 99 0x400 0x01>; status = "disabled"; }; sai4b: audio-controller@50027024 { #sound-dai-cells = <0>; compatible = "st,stm32-sai-sub-b"; reg = <0x24 0x20>; clocks = <&rcc SAI4_K>; clock-names = "sai_ck"; dmas = <&dmamux1 100 0x400 0x01>; status = "disabled"; }; }; dts: thermal@50028000 { compatible = "st,stm32-thermal"; reg = <0x50028000 0x100>; interrupts = ; clocks = <&rcc TMPSENS>; clock-names = "pclk"; #thermal-sensor-cells = <0>; status = "disabled"; }; hash1: hash@54002000 { compatible = "st,stm32f756-hash"; reg = <0x54002000 0x400>; interrupts = ; clocks = <&rcc HASH1>; resets = <&rcc HASH1_R>; dmas = <&mdma1 31 0x2 0x1000A02 0x0 0x0>; dma-names = "in"; dma-maxburst = <2>; status = "disabled"; }; rng1: rng@54003000 { compatible = "st,stm32-rng"; reg = <0x54003000 0x400>; clocks = <&rcc RNG1_K>; resets = <&rcc RNG1_R>; status = "disabled"; }; mdma1: dma-controller@58000000 { compatible = "st,stm32h7-mdma"; reg = <0x58000000 0x1000>; interrupts = ; clocks = <&rcc MDMA>; resets = <&rcc MDMA_R>; #dma-cells = <5>; dma-channels = <32>; dma-requests = <48>; }; fmc: memory-controller@58002000 { #address-cells = <2>; #size-cells = <1>; compatible = "st,stm32mp1-fmc2-ebi"; reg = <0x58002000 0x1000>; clocks = <&rcc FMC_K>; resets = <&rcc FMC_R>; status = "disabled"; ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ <4 0 0x80000000 0x10000000>; /* NAND */ nand-controller@4,0 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32mp1-fmc2-nfc"; reg = <4 0x00000000 0x1000>, <4 0x08010000 0x1000>, <4 0x08020000 0x1000>, <4 0x01000000 0x1000>, <4 0x09010000 0x1000>, <4 0x09020000 0x1000>; interrupts = ; dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>, <&mdma1 20 0x2 0x12000a08 0x0 0x0>, <&mdma1 21 0x2 0x12000a0a 0x0 0x0>; dma-names = "tx", "rx", "ecc"; status = "disabled"; }; }; qspi: spi@58003000 { compatible = "st,stm32f469-qspi"; reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; reg-names = "qspi", "qspi_mm"; interrupts = ; dmas = <&mdma1 22 0x2 0x10100002 0x0 0x0>, <&mdma1 22 0x2 0x10100008 0x0 0x0>; dma-names = "tx", "rx"; clocks = <&rcc QSPI_K>; resets = <&rcc QSPI_R>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; }; sdmmc1: mmc@58005000 { compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; arm,primecell-periphid = <0x00253180>; reg = <0x58005000 0x1000>; interrupts = ; interrupt-names = "cmd_irq"; clocks = <&rcc SDMMC1_K>; clock-names = "apb_pclk"; resets = <&rcc SDMMC1_R>; cap-sd-highspeed; cap-mmc-highspeed; max-frequency = <120000000>; status = "disabled"; }; sdmmc2: mmc@58007000 { compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; arm,primecell-periphid = <0x00253180>; reg = <0x58007000 0x1000>; interrupts = ; interrupt-names = "cmd_irq"; clocks = <&rcc SDMMC2_K>; clock-names = "apb_pclk"; resets = <&rcc SDMMC2_R>; cap-sd-highspeed; cap-mmc-highspeed; max-frequency = <120000000>; status = "disabled"; }; crc1: crc@58009000 { compatible = "st,stm32f7-crc"; reg = <0x58009000 0x400>; clocks = <&rcc CRC1>; status = "disabled"; }; ethernet0: ethernet@5800a000 { compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; reg = <0x5800a000 0x2000>; reg-names = "stmmaceth"; interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "macirq"; clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx", "eth-ck", "ptp_ref", "ethstp"; clocks = <&rcc ETHMAC>, <&rcc ETHTX>, <&rcc ETHRX>, <&rcc ETHCK_K>, <&rcc ETHPTP_K>, <&rcc ETHSTP>; st,syscon = <&syscfg 0x4>; snps,mixed-burst; snps,pbl = <2>; snps,en-tx-lpi-clockgating; snps,axi-config = <&stmmac_axi_config_0>; snps,tso; status = "disabled"; stmmac_axi_config_0: stmmac-axi-config { snps,wr_osr_lmt = <0x7>; snps,rd_osr_lmt = <0x7>; snps,blen = <0 0 0 0 16 8 4>; }; }; usbh_ohci: usb@5800c000 { compatible = "generic-ohci"; reg = <0x5800c000 0x1000>; clocks = <&usbphyc>, <&rcc USBH>; resets = <&rcc USBH_R>; interrupts = ; status = "disabled"; }; usbh_ehci: usb@5800d000 { compatible = "generic-ehci"; reg = <0x5800d000 0x1000>; clocks = <&usbphyc>, <&rcc USBH>; resets = <&rcc USBH_R>; interrupts = ; companion = <&usbh_ohci>; status = "disabled"; }; ltdc: display-controller@5a001000 { compatible = "st,stm32-ltdc"; reg = <0x5a001000 0x400>; interrupts = , ; clocks = <&rcc LTDC_PX>; clock-names = "lcd"; resets = <&rcc LTDC_R>; status = "disabled"; port { #address-cells = <1>; #size-cells = <0>; }; }; iwdg2: watchdog@5a002000 { compatible = "st,stm32mp1-iwdg"; reg = <0x5a002000 0x400>; interrupts = ; clocks = <&rcc IWDG2>, <&rcc CK_LSI>; clock-names = "pclk", "lsi"; status = "disabled"; }; usbphyc: usbphyc@5a006000 { #address-cells = <1>; #size-cells = <0>; #clock-cells = <0>; compatible = "st,stm32mp1-usbphyc"; reg = <0x5a006000 0x1000>; clocks = <&rcc USBPHY_K>; resets = <&rcc USBPHY_R>; vdda1v1-supply = <®11>; vdda1v8-supply = <®18>; status = "disabled"; usbphyc_port0: usb-phy@0 { #phy-cells = <0>; reg = <0>; }; usbphyc_port1: usb-phy@1 { #phy-cells = <1>; reg = <1>; }; }; usart1: serial@5c000000 { compatible = "st,stm32h7-uart"; reg = <0x5c000000 0x400>; interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>; clocks = <&rcc USART1_K>; wakeup-source; status = "disabled"; }; spi6: spi@5c001000 { #address-cells = <1>; #size-cells = <0>; compatible = "st,stm32h7-spi"; reg = <0x5c001000 0x400>; interrupts = ; clocks = <&rcc SPI6_K>; resets = <&rcc SPI6_R>; dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>, <&mdma1 35 0x0 0x40002 0x0 0x0>; dma-names = "rx", "tx"; status = "disabled"; }; i2c4: i2c@5c002000 { compatible = "st,stm32mp15-i2c"; reg = <0x5c002000 0x400>; interrupt-names = "event", "error"; interrupts = , ; clocks = <&rcc I2C4_K>; resets = <&rcc I2C4_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x8>; wakeup-source; i2c-analog-filter; status = "disabled"; }; iwdg1: watchdog@5c003000 { compatible = "st,stm32mp1-iwdg"; reg = <0x5C003000 0x400>; interrupts = ; clocks = <&rcc IWDG1>, <&rcc CK_LSI>; clock-names = "pclk", "lsi"; status = "disabled"; }; rtc: rtc@5c004000 { compatible = "st,stm32mp1-rtc"; reg = <0x5c004000 0x400>; clocks = <&rcc RTCAPB>, <&rcc RTC>; clock-names = "pclk", "rtc_ck"; interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; }; bsec: efuse@5c005000 { compatible = "st,stm32mp15-bsec"; reg = <0x5c005000 0x400>; #address-cells = <1>; #size-cells = <1>; cfg0_otp: cfg0_otp@0 { reg = <0x0 0x1>; }; part_number_otp: part_number_otp@4 { reg = <0x4 0x1>; }; monotonic_otp: monotonic_otp@10 { reg = <0x10 0x4>; }; nand_otp: nand_otp@24 { reg = <0x24 0x4>; }; uid_otp: uid_otp@34 { reg = <0x34 0xc>; }; package_otp: package_otp@40 { reg = <0x40 0x4>; }; hw2_otp: hw2_otp@48 { reg = <0x48 0x4>; }; ts_cal1: calib@5c { reg = <0x5c 0x2>; }; ts_cal2: calib@5e { reg = <0x5e 0x2>; }; pkh_otp: pkh_otp@60 { reg = <0x60 0x20>; }; ethernet_mac_address: mac@e4 { reg = <0xe4 0x8>; st,non-secure-otp; }; }; etzpc: etzpc@5c007000 { compatible = "st,stm32-etzpc"; reg = <0x5C007000 0x400>; clocks = <&rcc TZPC>; status = "disabled"; secure-status = "okay"; }; i2c6: i2c@5c009000 { compatible = "st,stm32mp15-i2c"; reg = <0x5c009000 0x400>; interrupt-names = "event", "error"; interrupts = , ; clocks = <&rcc I2C6_K>; resets = <&rcc I2C6_R>; #address-cells = <1>; #size-cells = <0>; st,syscfg-fmp = <&syscfg 0x4 0x20>; wakeup-source; i2c-analog-filter; status = "disabled"; }; tamp: tamp@5c00a000 { compatible = "st,stm32-tamp", "syscon", "simple-mfd"; reg = <0x5c00a000 0x400>; clocks = <&rcc RTCAPB>; }; /* * Break node order to solve dependency probe issue between * pinctrl and exti. */ pinctrl: pinctrl@50002000 { #address-cells = <1>; #size-cells = <1>; compatible = "st,stm32mp157-pinctrl"; ranges = <0 0x50002000 0xa400>; interrupt-parent = <&exti>; st,syscfg = <&exti 0x60 0xff>; pins-are-numbered; gpioa: gpio@50002000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x0 0x400>; clocks = <&rcc GPIOA>; st,bank-name = "GPIOA"; status = "disabled"; }; gpiob: gpio@50003000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x1000 0x400>; clocks = <&rcc GPIOB>; st,bank-name = "GPIOB"; status = "disabled"; }; gpioc: gpio@50004000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x2000 0x400>; clocks = <&rcc GPIOC>; st,bank-name = "GPIOC"; status = "disabled"; }; gpiod: gpio@50005000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x3000 0x400>; clocks = <&rcc GPIOD>; st,bank-name = "GPIOD"; status = "disabled"; }; gpioe: gpio@50006000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x4000 0x400>; clocks = <&rcc GPIOE>; st,bank-name = "GPIOE"; status = "disabled"; }; gpiof: gpio@50007000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x5000 0x400>; clocks = <&rcc GPIOF>; st,bank-name = "GPIOF"; status = "disabled"; }; gpiog: gpio@50008000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x6000 0x400>; clocks = <&rcc GPIOG>; st,bank-name = "GPIOG"; status = "disabled"; }; gpioh: gpio@50009000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x7000 0x400>; clocks = <&rcc GPIOH>; st,bank-name = "GPIOH"; status = "disabled"; }; gpioi: gpio@5000a000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x8000 0x400>; clocks = <&rcc GPIOI>; st,bank-name = "GPIOI"; status = "disabled"; }; gpioj: gpio@5000b000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x9000 0x400>; clocks = <&rcc GPIOJ>; st,bank-name = "GPIOJ"; status = "disabled"; }; gpiok: gpio@5000c000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0xa000 0x400>; clocks = <&rcc GPIOK>; st,bank-name = "GPIOK"; status = "disabled"; }; }; pinctrl_z: pinctrl@54004000 { #address-cells = <1>; #size-cells = <1>; compatible = "st,stm32mp157-z-pinctrl"; ranges = <0 0x54004000 0x400>; pins-are-numbered; interrupt-parent = <&exti>; st,syscfg = <&exti 0x60 0xff>; gpioz: gpio@54004000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0 0x400>; clocks = <&rcc GPIOZ>; st,bank-name = "GPIOZ"; st,bank-ioport = <11>; status = "disabled"; }; }; }; mlahb: ahb { compatible = "st,mlahb", "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges; dma-ranges = <0x00000000 0x38000000 0x10000>, <0x10000000 0x10000000 0x60000>, <0x30000000 0x30000000 0x60000>; m4_rproc: m4@10000000 { compatible = "st,stm32mp1-m4"; reg = <0x10000000 0x40000>, <0x30000000 0x40000>, <0x38000000 0x10000>; resets = <&rcc MCU_R>, <&rcc MCU_HOLD_BOOT_R>; reset-names = "mcu_rst", "hold_boot"; st,syscfg-tz = <&rcc 0x000 0x1>; st,syscfg-pdds = <&pwr_mcu 0x0 0x1>; st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>; st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>; status = "disabled"; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp153.dtsi000066400000000000000000000032201464416617300212050ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp151.dtsi" / { cpus { cpu1: cpu@1 { compatible = "arm,cortex-a7"; clock-frequency = <650000000>; device_type = "cpu"; reg = <1>; }; }; arm-pmu { interrupts = , ; interrupt-affinity = <&cpu0>, <&cpu1>; }; timer { interrupts = , , , ; }; soc { m_can1: can@4400e000 { compatible = "bosch,m_can"; reg = <0x4400e000 0x400>, <0x44011000 0x1400>; reg-names = "m_can", "message_ram"; interrupts = , ; interrupt-names = "int0", "int1"; clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; clock-names = "hclk", "cclk"; bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; status = "disabled"; }; m_can2: can@4400f000 { compatible = "bosch,m_can"; reg = <0x4400f000 0x400>, <0x44011000 0x2800>; reg-names = "m_can", "message_ram"; interrupts = , ; interrupt-names = "int0", "int1"; clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; clock-names = "hclk", "cclk"; bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; status = "disabled"; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157.dtsi000066400000000000000000000015271464416617300212210ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp153.dtsi" / { soc { gpu: gpu@59000000 { compatible = "vivante,gc"; reg = <0x59000000 0x800>; interrupts = ; clocks = <&rcc GPU>, <&rcc GPU_K>; clock-names = "bus" ,"core"; resets = <&rcc GPU_R>; }; dsi: dsi@5a000000 { compatible = "st,stm32-dsi"; reg = <0x5a000000 0x800>; clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>; clock-names = "pclk", "ref", "px_clk"; resets = <&rcc DSI_R>; reset-names = "apb"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; ports { #address-cells = <1>; #size-cells = <0>; }; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157a-dhcor-avenger96.dts000066400000000000000000000017271464416617300241140ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * Copyright (C) Linaro Ltd 2019 - All Rights Reserved * Author: Manivannan Sadhasivam * Copyright (C) 2020 Marek Vasut * * DHCOR STM32MP1 variant: * DHCR-STM32MP157A-C065-R102-V18-SPI-C-01LG * DHCOR PCB number: 586-100 or newer * Avenger96 PCB number: 588-200 or newer */ /dts-v1/; #include "stm32mp157.dtsi" #include "stm32mp15xc.dtsi" #include "stm32mp15xx-dhcor-som.dtsi" #include "stm32mp15xx-dhcor-avenger96.dtsi" / { model = "Arrow Electronics STM32MP157A Avenger96 board"; compatible = "arrow,stm32mp157a-avenger96", "dh,stm32mp157a-dhcor-som", "st,stm32mp157"; }; &m_can1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&m_can1_pins_b>; pinctrl-1 = <&m_can1_sleep_pins_b>; status = "disabled"; }; &m_can2 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&m_can2_pins_a>; pinctrl-1 = <&m_can2_sleep_pins_a>; status = "disabled"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts000066400000000000000000000005351464416617300226150ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 */ /dts-v1/; #include "stm32mp157a-dk1.dts" / { model = "STMicroelectronics STM32MP157A-DK1 SCMI Discovery Board"; compatible = "st,stm32mp157a-dk1-scmi", "st,stm32mp157"; }; &rcc { compatible = "st,stm32mp1-rcc-secure"; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157a-dk1.dts000066400000000000000000000013621464416617300216630ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ /dts-v1/; #include "stm32mp157.dtsi" #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxac-pinctrl.dtsi" #include "stm32mp15xx-dkx.dtsi" / { model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; aliases { ethernet0 = ðernet0; serial0 = &uart4; serial1 = &usart3; serial2 = &uart7; }; chosen { stdout-path = "serial0:115200n8"; }; }; &bsec { board_id: board_id@ec { reg = <0xec 0x4>; st,non-secure-otp; }; huk_otp: huk-otp@f0 { reg = <0xf0 0x10>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-dhcom-pdk2.dts000066400000000000000000000014301464416617300231320ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause /* * Copyright (C) 2019-2020 Marek Vasut * Copyright (C) 2022 DH electronics GmbH * * DHCOM STM32MP1 variant: * DHCM-STM32MP157C-C065-R102-F0819-SPI-E2-CAN2-SDR104-RTC-WBT-T-DSI-I-01D2 * DHCOM PCB number: 587-200 or newer * PDK2 PCB number: 516-400 or newer */ /dts-v1/; #include "stm32mp157.dtsi" #include "stm32mp15xc.dtsi" #include "stm32mp15xx-dhcom-som.dtsi" #include "stm32mp15xx-dhcom-pdk2.dtsi" / { model = "DH electronics STM32MP157C DHCOM Premium Developer Kit (2)"; compatible = "dh,stm32mp157c-dhcom-pdk2", "dh,stm32mp157c-dhcom-som", "st,stm32mp157"; }; &m_can1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&m_can1_pins_a>; pinctrl-1 = <&m_can1_sleep_pins_a>; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts000066400000000000000000000005351464416617300226200ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 */ /dts-v1/; #include "stm32mp157c-dk2.dts" / { model = "STMicroelectronics STM32MP157C-DK2 SCMI Discovery Board"; compatible = "st,stm32mp157c-dk2-scmi", "st,stm32mp157"; }; &rcc { compatible = "st,stm32mp1-rcc-secure"; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-dk2.dts000066400000000000000000000035011464416617300216630ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ /dts-v1/; #include "stm32mp157.dtsi" #include "stm32mp15xc.dtsi" #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxac-pinctrl.dtsi" #include "stm32mp15xx-dkx.dtsi" / { model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; aliases { ethernet0 = ðernet0; serial0 = &uart4; serial1 = &usart3; serial2 = &uart7; serial3 = &usart2; }; chosen { stdout-path = "serial0:115200n8"; }; }; &bsec { board_id: board_id@ec { reg = <0xec 0x4>; st,non-secure-otp; }; huk_otp: huk-otp@f0 { reg = <0xf0 0x10>; }; }; &dsi { status = "disabled"; phy-dsi-supply = <®18>; ports { port@0 { reg = <0>; dsi_in: endpoint { remote-endpoint = <<dc_ep1_out>; }; }; port@1 { reg = <1>; dsi_out: endpoint { remote-endpoint = <&panel_in>; }; }; }; panel@0 { compatible = "orisetech,otm8009a"; reg = <0>; reset-gpios = <&gpioe 4 GPIO_ACTIVE_LOW>; power-supply = <&v3v3>; status = "okay"; port { panel_in: endpoint { remote-endpoint = <&dsi_out>; }; }; }; }; &i2c1 { touchscreen@38 { compatible = "focaltech,ft6236"; reg = <0x38>; interrupts = <2 2>; interrupt-parent = <&gpiof>; interrupt-controller; touchscreen-size-x = <480>; touchscreen-size-y = <800>; status = "okay"; }; }; <dc { status = "disabled"; port { ltdc_ep1_out: endpoint@1 { reg = <1>; remote-endpoint = <&dsi_in>; }; }; }; &usart2 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&usart2_pins_c>; pinctrl-1 = <&usart2_sleep_pins_c>; pinctrl-2 = <&usart2_idle_pins_c>; status = "disabled"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts000066400000000000000000000007111464416617300226050ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 */ /dts-v1/; #include "stm32mp157c-ed1.dts" / { model = "STMicroelectronics STM32MP157C SCMI eval daughter"; compatible = "st,stm32mp157c-ed1-scmi", "st,stm32mp157"; }; &iwdg1 { timeout-sec = <32>; }; &iwdg2 { timeout-sec = <32>; status = "okay"; secure-status = "disabled"; }; &rcc { compatible = "st,stm32mp1-rcc-secure"; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-ed1.dts000066400000000000000000000211131464416617300216530ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ /dts-v1/; #include "stm32mp157.dtsi" #include "stm32mp15xc.dtsi" #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxaa-pinctrl.dtsi" #include #include / { model = "STMicroelectronics STM32MP157C eval daughter"; compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; chosen { stdout-path = "serial0:115200n8"; }; memory@c0000000 { device_type = "memory"; reg = <0xC0000000 0x40000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; mcuram2: mcuram2@10000000 { compatible = "shared-dma-pool"; reg = <0x10000000 0x40000>; no-map; }; vdev0vring0: vdev0vring0@10040000 { compatible = "shared-dma-pool"; reg = <0x10040000 0x1000>; no-map; }; vdev0vring1: vdev0vring1@10041000 { compatible = "shared-dma-pool"; reg = <0x10041000 0x1000>; no-map; }; vdev0buffer: vdev0buffer@10042000 { compatible = "shared-dma-pool"; reg = <0x10042000 0x4000>; no-map; }; ipc_shmem: ipc-shmem@1004f000 { compatible = "shared-dma-pool"; reg = <0x10048000 0x8000>; no-map; }; mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; no-map; }; retram: retram@38000000 { compatible = "shared-dma-pool"; reg = <0x38000000 0x10000>; no-map; }; gpu_reserved: gpu@e8000000 { reg = <0xe8000000 0x8000000>; no-map; }; }; aliases { serial0 = &uart4; }; sd_switch: regulator-sd_switch { compatible = "regulator-gpio"; regulator-name = "sd_switch"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <2900000>; regulator-type = "voltage"; regulator-always-on; gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; gpios-states = <0>; states = <1800000 0x1>, <2900000 0x0>; }; vin: vin { compatible = "regulator-fixed"; regulator-name = "vin"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; }; }; &adc { /* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */ pinctrl-0 = <&adc1_in6_pins_a>; pinctrl-names = "default"; vdd-supply = <&vdd>; vdda-supply = <&vdda>; vref-supply = <&vdda>; status = "disabled"; adc1: adc@0 { st,adc-channels = <0 1 6>; /* 16.5 ck_cycles sampling time */ st,min-sample-time-nsecs = <400>; status = "okay"; }; }; &bsec { board_id: board_id@ec { reg = <0xec 0x4>; st,non-secure-otp; }; huk_otp: huk-otp@f0 { reg = <0xf0 0x10>; }; }; &crc1 { status = "disabled"; }; &dac { pinctrl-names = "default"; pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; vref-supply = <&vdda>; status = "disabled"; dac1: dac@1 { status = "okay"; }; dac2: dac@2 { status = "okay"; }; }; &dts { status = "disabled"; }; &gpu { contiguous-area = <&gpu_reserved>; }; &hash1 { status = "disabled"; }; &i2c4 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c4_pins_a>; pinctrl-1 = <&i2c4_sleep_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; clock-frequency = <400000>; status = "okay"; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; regulators { compatible = "st,stpmic1-regulators"; buck1-supply = <&vin>; buck2-supply = <&vin>; buck3-supply = <&vin>; buck4-supply = <&vin>; ldo1-supply = <&v3v3>; ldo2-supply = <&v3v3>; ldo3-supply = <&vdd_ddr>; ldo4-supply = <&vin>; ldo5-supply = <&v3v3>; ldo6-supply = <&v3v3>; vref_ddr-supply = <&vin>; boost-supply = <&vin>; pwr_sw1-supply = <&bst_out>; pwr_sw2-supply = <&bst_out>; vddcore: buck1 { regulator-name = "vddcore"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd_ddr: buck2 { regulator-name = "vdd_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd: buck3 { regulator-name = "vdd"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; st,mask-reset; regulator-initial-mode = <0>; regulator-over-current-protection; }; v3v3: buck4 { regulator-name = "v3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-over-current-protection; regulator-initial-mode = <0>; }; vdda: ldo1 { regulator-name = "vdda"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; }; v2v8: ldo2 { regulator-name = "v2v8"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; interrupts = ; }; vtt_ddr: ldo3 { regulator-name = "vtt_ddr"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <750000>; regulator-always-on; regulator-over-current-protection; }; vdd_usb: ldo4 { regulator-name = "vdd_usb"; interrupts = ; regulator-always-on; }; vdd_sd: ldo5 { regulator-name = "vdd_sd"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; regulator-boot-on; }; v1v8: ldo6 { regulator-name = "v1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; interrupts = ; }; vref_ddr: vref_ddr { regulator-name = "vref_ddr"; regulator-always-on; }; bst_out: boost { regulator-name = "bst_out"; interrupts = ; }; vbus_otg: pwr_sw1 { regulator-name = "vbus_otg"; interrupts = ; }; vbus_sw: pwr_sw2 { regulator-name = "vbus_sw"; interrupts = ; regulator-active-discharge = <1>; }; }; onkey { compatible = "st,stpmic1-onkey"; interrupts = , ; interrupt-names = "onkey-falling", "onkey-rising"; power-off-time-sec = <10>; status = "disabled"; }; watchdog { compatible = "st,stpmic1-wdt"; status = "disabled"; }; }; }; &ipcc { status = "disabled"; }; &iwdg1 { timeout-sec = <32>; status = "okay"; }; &iwdg2 { timeout-sec = <32>; status = "disabled"; }; &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; mbox-names = "vq0", "vq1", "shutdown", "detach"; interrupt-parent = <&exti>; interrupts = <68 1>; status = "disabled"; }; &pwr_regulators { vdd-supply = <&vdd>; vdd_3v3_usbfs-supply = <&vdd_usb>; }; &rcc { compatible = "st,stm32mp1-rcc"; status = "okay"; }; &rng1 { status = "okay"; }; &rtc { status = "disabled"; }; &sdmmc1 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; disable-wp; st,sig-dir; st,neg-edge; st,use-ckin; bus-width = <4>; vmmc-supply = <&vdd_sd>; vqmmc-supply = <&sd_switch>; sd-uhs-sdr12; sd-uhs-sdr25; sd-uhs-sdr50; sd-uhs-ddr50; status = "disabled"; }; &sdmmc2 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; non-removable; no-sd; no-sdio; st,neg-edge; bus-width = <8>; vmmc-supply = <&v3v3>; vqmmc-supply = <&vdd>; mmc-ddr-3_3v; status = "disabled"; }; &timers6 { status = "disabled"; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; timer@5 { status = "okay"; }; }; &uart4 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&uart4_pins_a>; pinctrl-1 = <&uart4_sleep_pins_a>; pinctrl-2 = <&uart4_idle_pins_a>; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; &usbotg_hs { vbus-supply = <&vbus_otg>; }; &usbphyc_port0 { phy-supply = <&vdd_usb>; }; &usbphyc_port1 { phy-supply = <&vdd_usb>; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-ev1-scmi.dts000066400000000000000000000006001464416617300226240ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 */ /dts-v1/; #include "stm32mp157c-ev1.dts" / { model = "STMicroelectronics STM32MP157C SCMI eval daughter on eval mother"; compatible = "st,stm32mp157c-ev1-scmi", "st,stm32mp157c-ed1-scmi", "st,stm32mp157"; }; &rcc { compatible = "st,stm32mp1-rcc-secure"; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp157c-ev1.dts000066400000000000000000000173111464416617300217020ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ /dts-v1/; #include "stm32mp157c-ed1.dts" #include / { model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; chosen { stdout-path = "serial0:115200n8"; }; aliases { serial0 = &uart4; serial1 = &usart3; ethernet0 = ðernet0; }; clocks { clk_ext_camera: clk-ext-camera { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <24000000>; }; }; joystick { compatible = "gpio-keys"; pinctrl-0 = <&joystick_pins>; pinctrl-names = "default"; button-0 { label = "JoySel"; interrupt-parent = <&stmfx_pinctrl>; interrupts = <0 IRQ_TYPE_EDGE_RISING>; }; button-1 { label = "JoyDown"; interrupt-parent = <&stmfx_pinctrl>; interrupts = <1 IRQ_TYPE_EDGE_RISING>; }; button-2 { label = "JoyLeft"; interrupt-parent = <&stmfx_pinctrl>; interrupts = <2 IRQ_TYPE_EDGE_RISING>; }; button-3 { label = "JoyRight"; interrupt-parent = <&stmfx_pinctrl>; interrupts = <3 IRQ_TYPE_EDGE_RISING>; }; button-4 { label = "JoyUp"; interrupt-parent = <&stmfx_pinctrl>; interrupts = <4 IRQ_TYPE_EDGE_RISING>; }; }; panel_backlight: panel-backlight { compatible = "gpio-backlight"; gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; default-on; status = "okay"; }; }; &cec { pinctrl-names = "default"; pinctrl-0 = <&cec_pins_a>; status = "disabled"; }; &dcmi { status = "disabled"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&dcmi_pins_a>; pinctrl-1 = <&dcmi_sleep_pins_a>; port { dcmi_0: endpoint { remote-endpoint = <&ov5640_0>; bus-type = <5>; bus-width = <8>; hsync-active = <0>; vsync-active = <0>; pclk-sample = <1>; }; }; }; &dsi { phy-dsi-supply = <®18>; status = "disabled"; ports { port@0 { reg = <0>; dsi_in: endpoint { remote-endpoint = <<dc_ep0_out>; }; }; port@1 { reg = <1>; dsi_out: endpoint { remote-endpoint = <&dsi_panel_in>; }; }; }; panel-dsi@0 { compatible = "raydium,rm68200"; reg = <0>; reset-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; backlight = <&panel_backlight>; power-supply = <&v3v3>; status = "okay"; port { dsi_panel_in: endpoint { remote-endpoint = <&dsi_out>; }; }; }; }; ðernet0 { status = "disabled"; pinctrl-0 = <ðernet0_rgmii_pins_a>; pinctrl-1 = <ðernet0_rgmii_sleep_pins_a>; pinctrl-names = "default", "sleep"; phy-mode = "rgmii-id"; max-speed = <1000>; phy-handle = <&phy0>; mdio0 { #address-cells = <1>; #size-cells = <0>; compatible = "snps,dwmac-mdio"; phy0: ethernet-phy@0 { reg = <0>; }; }; }; &fmc { pinctrl-names = "default", "sleep"; pinctrl-0 = <&fmc_pins_a>; pinctrl-1 = <&fmc_sleep_pins_a>; status = "disabled"; nand-controller@4,0 { status = "okay"; nand@0 { reg = <0>; nand-on-flash-bbt; #address-cells = <1>; #size-cells = <1>; }; }; }; &i2c2 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c2_pins_a>; pinctrl-1 = <&i2c2_sleep_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "disabled"; ov5640: camera@3c { compatible = "ovti,ov5640"; reg = <0x3c>; clocks = <&clk_ext_camera>; clock-names = "xclk"; DOVDD-supply = <&v2v8>; powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; rotation = <180>; status = "okay"; port { ov5640_0: endpoint { remote-endpoint = <&dcmi_0>; bus-width = <8>; data-shift = <2>; /* lines 9:2 are used */ hsync-active = <0>; vsync-active = <0>; pclk-sample = <1>; }; }; }; stmfx: stmfx@42 { compatible = "st,stmfx-0300"; reg = <0x42>; interrupts = <8 IRQ_TYPE_EDGE_RISING>; interrupt-parent = <&gpioi>; vdd-supply = <&v3v3>; stmfx_pinctrl: pinctrl { compatible = "st,stmfx-0300-pinctrl"; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; gpio-ranges = <&stmfx_pinctrl 0 0 24>; joystick_pins: joystick-pins { pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; bias-pull-down; }; }; }; }; &i2c5 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c5_pins_a>; pinctrl-1 = <&i2c5_sleep_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "disabled"; }; <dc { status = "disabled"; port { ltdc_ep0_out: endpoint@0 { reg = <0>; remote-endpoint = <&dsi_in>; }; }; }; &m_can1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&m_can1_pins_a>; pinctrl-1 = <&m_can1_sleep_pins_a>; status = "disabled"; }; &qspi { pinctrl-names = "default", "sleep"; pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a &qspi_bk2_sleep_pins_a>; reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; #address-cells = <1>; #size-cells = <0>; status = "disabled"; flash0: flash@0 { compatible = "jedec,spi-nor"; reg = <0>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; #address-cells = <1>; #size-cells = <1>; }; flash1: flash@1 { compatible = "jedec,spi-nor"; reg = <1>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; #address-cells = <1>; #size-cells = <1>; }; }; &sdmmc3 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc3_b4_pins_a>; pinctrl-1 = <&sdmmc3_b4_od_pins_a>; pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; broken-cd; st,neg-edge; bus-width = <4>; vmmc-supply = <&v3v3>; status = "disabled"; }; &spi1 { pinctrl-names = "default"; pinctrl-0 = <&spi1_pins_a>; status = "disabled"; }; &timers2 { /* spare dmas for other usage (un-delete to enable pwm capture) */ /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm2_pins_a>; pinctrl-1 = <&pwm2_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@1 { status = "okay"; }; }; &timers8 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm8_pins_a>; pinctrl-1 = <&pwm8_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@7 { status = "okay"; }; }; &timers12 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm12_pins_a>; pinctrl-1 = <&pwm12_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@11 { status = "okay"; }; }; &usart3 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&usart3_pins_b>; pinctrl-1 = <&usart3_sleep_pins_b>; pinctrl-2 = <&usart3_idle_pins_b>; /* * HW flow control USART3_RTS is optional, and isn't default wired to * the connector. SB23 needs to be soldered in order to use it, and R77 * (ETH_CLK) should be removed. */ uart-has-rtscts; status = "disabled"; }; &usbh_ehci { phys = <&usbphyc_port0>; status = "disabled"; }; &usbotg_hs { pinctrl-0 = <&usbotg_hs_pins_a>; pinctrl-names = "default"; phys = <&usbphyc_port1 0>; phy-names = "usb2-phy"; status = "disabled"; }; &usbphyc { status = "disabled"; }; &usbphyc_port0 { st,tune-hs-dc-level = <2>; st,enable-fs-rftime-tuning; st,enable-hs-rftime-reduction; st,trim-hs-current = <15>; st,trim-hs-impedance = <1>; st,tune-squelch-level = <3>; st,tune-hs-rx-offset = <2>; st,no-lsfs-sc; }; &usbphyc_port1 { st,tune-hs-dc-level = <2>; st,enable-fs-rftime-tuning; st,enable-hs-rftime-reduction; st,trim-hs-current = <15>; st,trim-hs-impedance = <1>; st,tune-squelch-level = <3>; st,tune-hs-rx-offset = <2>; st,no-lsfs-sc; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xc.dtsi000066400000000000000000000006751464416617300214700ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ / { soc { cryp1: cryp@54001000 { compatible = "st,stm32mp1-cryp"; reg = <0x54001000 0x400>; interrupts = ; clocks = <&rcc CRYP1>; resets = <&rcc CRYP1_R>; status = "disabled"; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xx-dhcom-pdk2.dtsi000066400000000000000000000144131464416617300234360ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause /* * Copyright (C) 2019-2020 Marek Vasut * Copyright (C) 2022 DH electronics GmbH */ / { aliases { serial0 = &uart4; serial1 = &usart3; serial2 = &uart8; }; chosen { stdout-path = "serial0:115200n8"; }; clk_ext_audio_codec: clock-codec { compatible = "fixed-clock"; #clock-cells = <0>; clock-frequency = <24000000>; }; display_bl: display-bl { compatible = "pwm-backlight"; pwms = <&pwm2 3 500000 1>; brightness-levels = <0 16 22 30 40 55 75 102 138 188 255>; default-brightness-level = <8>; enable-gpios = <&gpioi 0 GPIO_ACTIVE_HIGH>; power-supply = <®_panel_bl>; status = "okay"; }; gpio-keys-polled { compatible = "gpio-keys-polled"; poll-interval = <20>; /* * The EXTi IRQ line 3 is shared with ethernet, * so mark this as polled GPIO key. */ button-0 { label = "TA1-GPIO-A"; gpios = <&gpiof 3 GPIO_ACTIVE_LOW>; }; /* * The EXTi IRQ line 6 is shared with touchscreen, * so mark this as polled GPIO key. */ button-1 { label = "TA2-GPIO-B"; gpios = <&gpiod 6 GPIO_ACTIVE_LOW>; }; /* * The EXTi IRQ line 0 is shared with PMIC, * so mark this as polled GPIO key. */ button-2 { label = "TA3-GPIO-C"; gpios = <&gpiog 0 GPIO_ACTIVE_LOW>; }; }; gpio-keys { compatible = "gpio-keys"; button-3 { label = "TA4-GPIO-D"; gpios = <&gpiod 12 GPIO_ACTIVE_LOW>; wakeup-source; }; }; led { compatible = "gpio-leds"; led-0 { label = "green:led5"; gpios = <&gpioc 6 GPIO_ACTIVE_HIGH>; default-state = "off"; status = "disabled"; }; led-1 { label = "green:led6"; gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; default-state = "off"; }; led-2 { label = "green:led7"; gpios = <&gpioi 2 GPIO_ACTIVE_HIGH>; default-state = "off"; }; led-3 { label = "green:led8"; gpios = <&gpioi 3 GPIO_ACTIVE_HIGH>; default-state = "off"; }; }; panel { compatible = "edt,etm0700g0edh6"; backlight = <&display_bl>; power-supply = <®_panel_bl>; port { lcd_panel_in: endpoint { remote-endpoint = <&lcd_display_out>; }; }; }; reg_panel_bl: regulator-panel-bl { compatible = "regulator-fixed"; regulator-name = "panel_backlight"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; vin-supply = <®_panel_supply>; }; reg_panel_supply: regulator-panel-supply { compatible = "regulator-fixed"; regulator-name = "panel_supply"; regulator-min-microvolt = <24000000>; regulator-max-microvolt = <24000000>; }; sound { compatible = "audio-graph-card"; routing = "MIC_IN", "Capture", "Capture", "Mic Bias", "Playback", "HP_OUT"; dais = <&sai2a_port &sai2b_port>; status = "okay"; }; }; &cec { pinctrl-names = "default"; pinctrl-0 = <&cec_pins_a>; status = "okay"; }; &i2c2 { /* Header X22 */ pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; }; &i2c5 { /* Header X21 */ pinctrl-names = "default"; pinctrl-0 = <&i2c5_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; sgtl5000: codec@a { compatible = "fsl,sgtl5000"; reg = <0x0a>; #sound-dai-cells = <0>; clocks = <&clk_ext_audio_codec>; VDDA-supply = <&v3v3>; VDDIO-supply = <&vdd>; sgtl5000_port: port { #address-cells = <1>; #size-cells = <0>; sgtl5000_tx_endpoint: endpoint@0 { reg = <0>; remote-endpoint = <&sai2a_endpoint>; frame-master = <&sgtl5000_tx_endpoint>; bitclock-master = <&sgtl5000_tx_endpoint>; }; sgtl5000_rx_endpoint: endpoint@1 { reg = <1>; remote-endpoint = <&sai2b_endpoint>; frame-master = <&sgtl5000_rx_endpoint>; bitclock-master = <&sgtl5000_rx_endpoint>; }; }; }; touchscreen@38 { compatible = "edt,edt-ft5406"; reg = <0x38>; interrupt-parent = <&gpioc>; interrupts = <6 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */ }; }; <dc { pinctrl-names = "default", "sleep"; pinctrl-0 = <<dc_pins_b>; pinctrl-1 = <<dc_sleep_pins_b>; status = "okay"; port { lcd_display_out: endpoint { remote-endpoint = <&lcd_panel_in>; }; }; }; &sai2 { clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; clock-names = "pclk", "x8k", "x11k"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&sai2a_pins_b &sai2b_pins_b>; pinctrl-1 = <&sai2a_sleep_pins_b &sai2b_sleep_pins_b>; status = "okay"; sai2a: audio-controller@4400b004 { #clock-cells = <0>; dma-names = "tx"; clocks = <&rcc SAI2_K>; clock-names = "sai_ck"; status = "okay"; sai2a_port: port { sai2a_endpoint: endpoint { remote-endpoint = <&sgtl5000_tx_endpoint>; format = "i2s"; mclk-fs = <512>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <16>; }; }; }; sai2b: audio-controller@4400b024 { dma-names = "rx"; st,sync = <&sai2a 2>; clocks = <&rcc SAI2_K>, <&sai2a>; clock-names = "sai_ck", "MCLK"; status = "okay"; sai2b_port: port { sai2b_endpoint: endpoint { remote-endpoint = <&sgtl5000_rx_endpoint>; format = "i2s"; mclk-fs = <512>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <16>; }; }; }; }; &timers2 { /* spare dmas for other usage (un-delete to enable pwm capture) */ /delete-property/dmas; /delete-property/dma-names; status = "okay"; pwm2: pwm { pinctrl-0 = <&pwm2_pins_a>; pinctrl-names = "default"; status = "okay"; }; timer@1 { status = "okay"; }; }; &usart3 { pinctrl-names = "default"; pinctrl-0 = <&usart3_pins_a>; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; &uart8 { pinctrl-names = "default"; pinctrl-0 = <&uart8_pins_a &uart8_rtscts_pins_a>; uart-has-rtscts; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; &usbh_ehci { phys = <&usbphyc_port0>; status = "okay"; }; &usbotg_hs { dr_mode = "otg"; pinctrl-0 = <&usbotg_hs_pins_a>; pinctrl-names = "default"; phy-names = "usb2-phy"; phys = <&usbphyc_port1 0>; vbus-supply = <&vbus_otg>; status = "okay"; }; &usbphyc { status = "okay"; }; &usbphyc_port0 { phy-supply = <&vdd_usb>; }; &usbphyc_port1 { phy-supply = <&vdd_usb>; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi000066400000000000000000000270341464416617300233770ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) 2019-2020 Marek Vasut * Copyright (C) 2022 DH electronics GmbH */ #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxaa-pinctrl.dtsi" #include #include / { aliases { ethernet0 = ðernet0; ethernet1 = &ksz8851; rtc0 = &hwrtc; rtc1 = &rtc; }; memory@c0000000 { device_type = "memory"; reg = <0xC0000000 0x40000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; mcuram2: mcuram2@10000000 { compatible = "shared-dma-pool"; reg = <0x10000000 0x40000>; no-map; }; vdev0vring0: vdev0vring0@10040000 { compatible = "shared-dma-pool"; reg = <0x10040000 0x1000>; no-map; }; vdev0vring1: vdev0vring1@10041000 { compatible = "shared-dma-pool"; reg = <0x10041000 0x1000>; no-map; }; vdev0buffer: vdev0buffer@10042000 { compatible = "shared-dma-pool"; reg = <0x10042000 0x4000>; no-map; }; mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; no-map; }; retram: retram@38000000 { compatible = "shared-dma-pool"; reg = <0x38000000 0x10000>; no-map; }; }; ethernet_vio: vioregulator { compatible = "regulator-fixed"; regulator-name = "vio"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; gpio = <&gpiog 3 GPIO_ACTIVE_LOW>; regulator-always-on; regulator-boot-on; vin-supply = <&vdd>; }; }; &adc { vdd-supply = <&vdd>; vdda-supply = <&vdda>; vref-supply = <&vdda>; status = "okay"; adc1: adc@0 { st,min-sample-time-nsecs = <5000>; st,adc-channels = <0>; status = "okay"; }; adc2: adc@100 { st,adc-channels = <1>; st,min-sample-time-nsecs = <5000>; status = "okay"; }; }; &crc1 { status = "okay"; }; &dac { pinctrl-names = "default"; pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>; vref-supply = <&vdda>; status = "okay"; dac1: dac@1 { status = "okay"; }; dac2: dac@2 { status = "okay"; }; }; &dts { status = "okay"; }; ðernet0 { status = "okay"; pinctrl-0 = <ðernet0_rmii_pins_c &mco2_pins_a>; pinctrl-1 = <ðernet0_rmii_sleep_pins_c &mco2_sleep_pins_a>; pinctrl-names = "default", "sleep"; phy-mode = "rmii"; max-speed = <100>; phy-handle = <&phy0>; mdio0 { #address-cells = <1>; #size-cells = <0>; compatible = "snps,dwmac-mdio"; phy0: ethernet-phy@1 { reg = <1>; /* LAN8710Ai */ compatible = "ethernet-phy-id0007.c0f0", "ethernet-phy-ieee802.3-c22"; clocks = <&rcc CK_MCO2>; reset-gpios = <&gpioh 3 GPIO_ACTIVE_LOW>; reset-assert-us = <500>; reset-deassert-us = <500>; smsc,disable-energy-detect; interrupt-parent = <&gpioi>; interrupts = <11 IRQ_TYPE_LEVEL_LOW>; }; }; }; &fmc { pinctrl-names = "default", "sleep"; pinctrl-0 = <&fmc_pins_b>; pinctrl-1 = <&fmc_sleep_pins_b>; status = "okay"; ksz8851: ethernet@1,0 { compatible = "micrel,ks8851-mll"; reg = <1 0x0 0x2>, <1 0x2 0x20000>; interrupt-parent = <&gpioc>; interrupts = <3 IRQ_TYPE_LEVEL_LOW>; bank-width = <2>; /* Timing values are in nS */ st,fmc2-ebi-cs-mux-enable; st,fmc2-ebi-cs-transaction-type = <4>; st,fmc2-ebi-cs-buswidth = <16>; st,fmc2-ebi-cs-address-setup-ns = <5>; st,fmc2-ebi-cs-address-hold-ns = <5>; st,fmc2-ebi-cs-bus-turnaround-ns = <5>; st,fmc2-ebi-cs-data-setup-ns = <45>; st,fmc2-ebi-cs-data-hold-ns = <1>; st,fmc2-ebi-cs-write-address-setup-ns = <5>; st,fmc2-ebi-cs-write-address-hold-ns = <5>; st,fmc2-ebi-cs-write-bus-turnaround-ns = <5>; st,fmc2-ebi-cs-write-data-setup-ns = <45>; st,fmc2-ebi-cs-write-data-hold-ns = <1>; }; }; &gpioa { gpio-line-names = "", "", "", "", "", "", "DHCOM-K", "", "", "", "", "", "", "", "", ""; }; &gpiob { gpio-line-names = "", "", "", "", "", "", "", "", "DHCOM-Q", "", "", "", "", "", "", ""; }; &gpioc { gpio-line-names = "", "", "", "", "", "", "DHCOM-E", "", "", "", "", "", "", "", "", ""; }; &gpiod { gpio-line-names = "", "", "", "", "", "", "DHCOM-B", "", "", "", "", "DHCOM-F", "DHCOM-D", "", "", ""; }; &gpioe { gpio-line-names = "", "", "", "", "", "", "DHCOM-P", "", "", "", "", "", "", "", "", ""; }; &gpiof { gpio-line-names = "", "", "", "DHCOM-A", "", "", "", "", "", "", "", "", "", "", "", ""; }; &gpiog { gpio-line-names = "DHCOM-C", "", "", "", "", "", "", "", "DHCOM-L", "", "", "", "", "", "", ""; }; &gpioh { gpio-line-names = "", "", "", "", "", "", "", "DHCOM-N", "DHCOM-J", "DHCOM-W", "DHCOM-V", "DHCOM-U", "DHCOM-T", "", "DHCOM-S", ""; }; &gpioi { gpio-line-names = "DHCOM-G", "DHCOM-O", "DHCOM-H", "DHCOM-I", "DHCOM-R", "DHCOM-M", "", "", "", "", "", "", "", "", "", ""; }; &i2c4 { pinctrl-names = "default"; pinctrl-0 = <&i2c4_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; hwrtc: rtc@32 { compatible = "microcrystal,rv8803"; reg = <0x32>; }; pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; regulators { compatible = "st,stpmic1-regulators"; ldo1-supply = <&v3v3>; ldo2-supply = <&v3v3>; ldo3-supply = <&vdd_ddr>; ldo5-supply = <&v3v3>; ldo6-supply = <&v3v3>; pwr_sw1-supply = <&bst_out>; pwr_sw2-supply = <&bst_out>; vddcore: buck1 { regulator-name = "vddcore"; regulator-min-microvolt = <800000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd_ddr: buck2 { regulator-name = "vdd_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd: buck3 { regulator-name = "vdd"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; st,mask-reset; regulator-initial-mode = <0>; regulator-over-current-protection; }; v3v3: buck4 { regulator-name = "v3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-over-current-protection; regulator-initial-mode = <0>; }; vdda: ldo1 { regulator-name = "vdda"; regulator-always-on; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; }; v2v8: ldo2 { regulator-name = "v2v8"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; interrupts = ; }; vtt_ddr: ldo3 { regulator-name = "vtt_ddr"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <750000>; regulator-always-on; regulator-over-current-protection; }; vdd_usb: ldo4 { regulator-name = "vdd_usb"; interrupts = ; }; vdd_sd: ldo5 { regulator-name = "vdd_sd"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; regulator-boot-on; }; v1v8: ldo6 { regulator-name = "v1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; interrupts = ; }; vref_ddr: vref_ddr { regulator-name = "vref_ddr"; regulator-always-on; }; bst_out: boost { regulator-name = "bst_out"; interrupts = ; }; vbus_otg: pwr_sw1 { regulator-name = "vbus_otg"; interrupts = ; }; vbus_sw: pwr_sw2 { regulator-name = "vbus_sw"; interrupts = ; regulator-active-discharge = <1>; }; }; onkey { compatible = "st,stpmic1-onkey"; interrupts = , ; interrupt-names = "onkey-falling", "onkey-rising"; power-off-time-sec = <10>; status = "okay"; }; watchdog { compatible = "st,stpmic1-wdt"; status = "disabled"; }; }; touchscreen@49 { compatible = "ti,tsc2004"; reg = <0x49>; vio-supply = <&v3v3>; interrupts-extended = <&gpioh 15 IRQ_TYPE_EDGE_FALLING>; }; eeprom@50 { compatible = "atmel,24c02"; reg = <0x50>; pagesize = <16>; }; }; &ipcc { status = "okay"; }; &iwdg2 { timeout-sec = <32>; status = "okay"; secure-status = "disabled"; }; &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; mbox-names = "vq0", "vq1", "shutdown"; interrupt-parent = <&exti>; interrupts = <68 1>; status = "okay"; }; &pwr_regulators { vdd-supply = <&vdd>; vdd_3v3_usbfs-supply = <&vdd_usb>; }; &qspi { pinctrl-names = "default", "sleep"; pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>; reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; #address-cells = <1>; #size-cells = <0>; status = "okay"; flash0: flash@0 { compatible = "jedec,spi-nor"; reg = <0>; spi-rx-bus-width = <4>; spi-max-frequency = <108000000>; #address-cells = <1>; #size-cells = <1>; }; }; &rcc { /* Connect MCO2 output to ETH_RX_CLK input via pad-pad connection */ /* clocks = <&rcc CK_MCO2>; Not supported in OP-TEE OS */ /* clock-names = "ETH_RX_CLK/ETH_REF_CLK"; Not supported */ /* * Set PLL4P output to 100 MHz to supply SDMMC with faster clock, * set MCO2 output to 50 MHz to supply ETHRX clock with PLL4P/2, * so that MCO2 behaves as a divider for the ETHRX clock here. */ /* assigned-clocks = <&rcc CK_MCO2>, <&rcc PLL4_P>; Not supported */ /* assigned-clock-parents = <&rcc PLL4_P>; Not supported */ /* assigned-clock-rates = <50000000>, <100000000>; Not supported */ status = "okay"; }; &rng1 { status = "okay"; }; &rtc { status = "okay"; }; &sdmmc1 { pinctrl-names = "default", "opendrain", "sleep", "init"; pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_a>; pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_a>; pinctrl-3 = <&sdmmc1_b4_init_pins_a &sdmmc1_dir_init_pins_a>; cd-gpios = <&gpiog 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; disable-wp; st,sig-dir; st,neg-edge; st,use-ckin; st,cmd-gpios = <&gpiod 2 0>; st,ck-gpios = <&gpioc 12 0>; st,ckin-gpios = <&gpioe 4 0>; bus-width = <4>; vmmc-supply = <&vdd_sd>; status = "okay"; }; &sdmmc1_b4_pins_a { /* * SD bus pull-up resistors: * - optional on SoMs with SD voltage translator * - mandatory on SoMs without SD voltage translator */ pins1 { bias-pull-up; }; pins2 { bias-pull-up; }; }; &sdmmc2 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>; pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>; non-removable; no-sd; no-sdio; st,neg-edge; bus-width = <8>; vmmc-supply = <&v3v3>; vqmmc-supply = <&v3v3>; mmc-ddr-3_3v; status = "okay"; }; &sdmmc3 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc3_b4_pins_a>; pinctrl-1 = <&sdmmc3_b4_od_pins_a>; pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; broken-cd; st,neg-edge; bus-width = <4>; vmmc-supply = <&v3v3>; vqmmc-supply = <&v3v3>; mmc-ddr-3_3v; status = "okay"; }; &uart4 { pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_a>; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi000066400000000000000000000206251464416617300244130ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * Copyright (C) Linaro Ltd 2019 - All Rights Reserved * Author: Manivannan Sadhasivam * Copyright (C) 2020 Marek Vasut */ /* Avenger96 uses DHCOR SoM configured for 1V8 IO operation */ #include "stm32mp15xx-dhcor-io1v8.dtsi" / { aliases { ethernet0 = ðernet0; mmc0 = &sdmmc1; serial0 = &uart4; serial1 = &uart7; serial2 = &usart2; spi0 = &qspi; }; /* XTal Q1 */ cec_clock: clk-cec-fixed { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <24000000>; }; chosen { stdout-path = "serial0:115200n8"; }; hdmi-out { compatible = "hdmi-connector"; type = "a"; port { hdmi_con: endpoint { remote-endpoint = <&adv7513_out>; }; }; }; led { compatible = "gpio-leds"; led1 { label = "green:user0"; gpios = <&gpioz 7 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; default-state = "off"; }; led2 { label = "green:user1"; gpios = <&gpiof 3 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc0"; default-state = "off"; }; led3 { label = "green:user2"; gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc1"; default-state = "off"; }; led4 { label = "green:user3"; gpios = <&gpiog 1 GPIO_ACTIVE_HIGH>; linux,default-trigger = "none"; default-state = "off"; panic-indicator; }; }; sd_switch: regulator-sd_switch { compatible = "regulator-gpio"; regulator-name = "sd_switch"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <2900000>; regulator-type = "voltage"; regulator-always-on; gpios = <&gpioi 5 GPIO_ACTIVE_HIGH>; gpios-states = <0>; states = <1800000 0x1>, <2900000 0x0>; }; sound { compatible = "audio-graph-card"; label = "STM32MP1-AV96-HDMI"; dais = <&sai2a_port>; status = "okay"; }; wlan_pwr: regulator-wlan { compatible = "regulator-fixed"; regulator-name = "wl-reg"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>; enable-active-high; }; }; &adc { pinctrl-names = "default"; pinctrl-0 = <&adc12_ain_pins_b>; vdd-supply = <&vdd>; vdda-supply = <&vdda>; vref-supply = <&vdda>; status = "okay"; adc1: adc@0 { st,adc-channels = <0 1 6>; st,min-sample-time-nsecs = <5000>; status = "okay"; }; adc2: adc@100 { st,adc-channels = <0 1 2>; st,min-sample-time-nsecs = <5000>; status = "okay"; }; }; ðernet0 { status = "okay"; pinctrl-0 = <ðernet0_rgmii_pins_c>; pinctrl-1 = <ðernet0_rgmii_sleep_pins_c>; pinctrl-names = "default", "sleep"; phy-mode = "rgmii"; max-speed = <1000>; phy-handle = <&phy0>; mdio0 { #address-cells = <1>; #size-cells = <0>; compatible = "snps,dwmac-mdio"; reset-gpios = <&gpioz 2 GPIO_ACTIVE_LOW>; reset-delay-us = <1000>; reset-post-delay-us = <1000>; phy0: ethernet-phy@7 { reg = <7>; rxc-skew-ps = <1500>; rxdv-skew-ps = <540>; rxd0-skew-ps = <420>; rxd1-skew-ps = <420>; rxd2-skew-ps = <420>; rxd3-skew-ps = <420>; txc-skew-ps = <1440>; txen-skew-ps = <540>; txd0-skew-ps = <420>; txd1-skew-ps = <420>; txd2-skew-ps = <420>; txd3-skew-ps = <420>; }; }; }; &gpioa { gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "AV96-K", "AV96-I", "", "AV96-A", ""; }; &gpiob { gpio-line-names = "", "", "", "", "", "AV96-J", "", "", "", "", "", "AV96-B", "", "AV96-L", "", ""; }; &gpioc { gpio-line-names = "", "", "", "AV96-C", "", "", "", "", "", "", "", "", "", "", "", ""; }; &gpiod { gpio-line-names = "", "", "", "", "", "", "", "", "AV96-D", "", "", "", "", "", "AV96-E", "AV96-F"; }; &gpiof { gpio-line-names = "", "", "", "", "", "", "", "", "", "", "", "", "AV96-G", "AV96-H", "", ""; }; &i2c1 { /* X6 I2C1 */ pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins_b>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; /delete-property/dmas; /delete-property/dma-names; }; &i2c2 { /* X6 I2C2 */ pinctrl-names = "default"; pinctrl-0 = <&i2c2_pins_c>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; /delete-property/dmas; /delete-property/dma-names; }; &i2c4 { hdmi-transmitter@3d { compatible = "adi,adv7513"; reg = <0x3d>, <0x4d>, <0x2d>, <0x5d>; reg-names = "main", "edid", "cec", "packet"; clocks = <&cec_clock>; clock-names = "cec"; avdd-supply = <&v3v3>; dvdd-supply = <&v3v3>; pvdd-supply = <&v3v3>; dvdd-3v-supply = <&v3v3>; bgvdd-supply = <&v3v3>; interrupts = <9 IRQ_TYPE_EDGE_FALLING>; interrupt-parent = <&gpiog>; status = "okay"; adi,input-depth = <8>; adi,input-colorspace = "rgb"; adi,input-clock = "1x"; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; adv7513_in: endpoint { remote-endpoint = <<dc_ep0_out>; }; }; port@1 { reg = <1>; adv7513_out: endpoint { remote-endpoint = <&hdmi_con>; }; }; port@2 { reg = <2>; adv7513_i2s0: endpoint { remote-endpoint = <&sai2a_endpoint>; }; }; }; }; }; <dc { pinctrl-names = "default", "sleep"; pinctrl-0 = <<dc_pins_d>; pinctrl-1 = <<dc_sleep_pins_d>; status = "okay"; port { #address-cells = <1>; #size-cells = <0>; ltdc_ep0_out: endpoint@0 { reg = <0>; remote-endpoint = <&adv7513_in>; }; }; }; &sai2 { clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; pinctrl-names = "default", "sleep"; pinctrl-0 = <&sai2a_pins_c>; pinctrl-1 = <&sai2a_sleep_pins_c>; clock-names = "pclk", "x8k", "x11k"; status = "okay"; sai2a: audio-controller@4400b004 { #clock-cells = <0>; dma-names = "tx"; clocks = <&rcc SAI2_K>; clock-names = "sai_ck"; status = "okay"; sai2a_port: port { sai2a_endpoint: endpoint { remote-endpoint = <&adv7513_i2s0>; format = "i2s"; mclk-fs = <256>; }; }; }; }; &sdmmc1 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_b>; pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_b>; pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_b>; cd-gpios = <&gpioi 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; disable-wp; st,sig-dir; st,neg-edge; st,use-ckin; bus-width = <4>; vmmc-supply = <&vdd_sd>; vqmmc-supply = <&sd_switch>; status = "okay"; }; &sdmmc2 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_c>; pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_c>; pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_c>; bus-width = <8>; mmc-ddr-1_8v; no-sd; no-sdio; non-removable; st,neg-edge; vmmc-supply = <&v3v3>; vqmmc-supply = <&vdd_io>; status = "okay"; }; &sdmmc3 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc3_b4_pins_b>; pinctrl-1 = <&sdmmc3_b4_od_pins_b>; pinctrl-2 = <&sdmmc3_b4_sleep_pins_b>; broken-cd; non-removable; st,neg-edge; bus-width = <4>; vmmc-supply = <&wlan_pwr>; status = "okay"; #address-cells = <1>; #size-cells = <0>; brcmf: bcrmf@1 { reg = <1>; compatible = "brcm,bcm4329-fmac"; }; }; &spi2 { pinctrl-names = "default"; pinctrl-0 = <&spi2_pins_a>; cs-gpios = <&gpioi 0 0>; status = "disabled"; /delete-property/dmas; /delete-property/dma-names; }; &uart4 { /* On Low speed expansion header */ label = "LS-UART1"; pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_b>; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; &uart7 { /* On Low speed expansion header */ label = "LS-UART0"; pinctrl-names = "default"; pinctrl-0 = <&uart7_pins_a>; uart-has-rtscts; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; /* Bluetooth */ &usart2 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&usart2_pins_a>; pinctrl-1 = <&usart2_sleep_pins_a>; st,hw-flow-ctrl; /delete-property/dmas; /delete-property/dma-names; status = "okay"; bluetooth { compatible = "brcm,bcm43438-bt"; max-speed = <3000000>; shutdown-gpios = <&gpioz 6 GPIO_ACTIVE_HIGH>; }; }; &usbh_ehci { phys = <&usbphyc_port0>; phy-names = "usb"; status = "okay"; }; &usbotg_hs { pinctrl-0 = <&usbotg_hs_pins_a>; pinctrl-names = "default"; phy-names = "usb2-phy"; phys = <&usbphyc_port1 0>; status = "okay"; vbus-supply = <&vbus_otg>; }; &usbphyc { status = "okay"; }; &usbphyc_port0 { phy-supply = <&vdd_usb>; }; &usbphyc_port1 { phy-supply = <&vdd_usb>; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xx-dhcor-io1v8.dtsi000066400000000000000000000010741464416617300235500ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * Copyright (C) Linaro Ltd 2019 - All Rights Reserved * Author: Manivannan Sadhasivam * Copyright (C) 2020 Marek Vasut */ / { /* Enpirion EP3A8LQI U2 on the DHCOR */ vdd_io: regulator-buck-io { compatible = "regulator-fixed"; regulator-name = "buck-io"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; regulator-boot-on; vin-supply = <&vdd>; }; }; &pwr_regulators { vdd-supply = <&vdd_io>; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi000066400000000000000000000132721464416617300234030ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * Copyright (C) Linaro Ltd 2019 - All Rights Reserved * Author: Manivannan Sadhasivam * Copyright (C) 2020 Marek Vasut * Copyright (C) 2022 DH electronics GmbH */ #include "stm32mp15-pinctrl.dtsi" #include "stm32mp15xxac-pinctrl.dtsi" #include #include / { aliases { spi0 = &qspi; }; memory@c0000000 { device_type = "memory"; reg = <0xc0000000 0x40000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; mcuram2: mcuram2@10000000 { compatible = "shared-dma-pool"; reg = <0x10000000 0x40000>; no-map; }; vdev0vring0: vdev0vring0@10040000 { compatible = "shared-dma-pool"; reg = <0x10040000 0x1000>; no-map; }; vdev0vring1: vdev0vring1@10041000 { compatible = "shared-dma-pool"; reg = <0x10041000 0x1000>; no-map; }; vdev0buffer: vdev0buffer@10042000 { compatible = "shared-dma-pool"; reg = <0x10042000 0x4000>; no-map; }; mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; no-map; }; retram: retram@38000000 { compatible = "shared-dma-pool"; reg = <0x38000000 0x10000>; no-map; }; }; }; &crc1 { status = "okay"; }; &dts { status = "okay"; }; &i2c4 { pinctrl-names = "default"; pinctrl-0 = <&i2c4_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; status = "okay"; /delete-property/dmas; /delete-property/dma-names; pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; regulators { compatible = "st,stpmic1-regulators"; ldo1-supply = <&v3v3>; ldo2-supply = <&v3v3>; ldo3-supply = <&vdd_ddr>; ldo5-supply = <&v3v3>; ldo6-supply = <&v3v3>; pwr_sw1-supply = <&bst_out>; pwr_sw2-supply = <&bst_out>; vddcore: buck1 { regulator-name = "vddcore"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd_ddr: buck2 { regulator-name = "vdd_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd: buck3 { regulator-name = "vdd"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; v3v3: buck4 { regulator-name = "v3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-over-current-protection; regulator-initial-mode = <0>; }; vdda: ldo1 { regulator-name = "vdda"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; }; v2v8: ldo2 { regulator-name = "v2v8"; regulator-min-microvolt = <2800000>; regulator-max-microvolt = <2800000>; interrupts = ; }; vtt_ddr: ldo3 { regulator-name = "vtt_ddr"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <750000>; regulator-always-on; regulator-over-current-protection; }; vdd_usb: ldo4 { regulator-name = "vdd_usb"; interrupts = ; }; vdd_sd: ldo5 { regulator-name = "vdd_sd"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; regulator-boot-on; }; v1v8: ldo6 { regulator-name = "v1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; interrupts = ; regulator-enable-ramp-delay = <300000>; }; vref_ddr: vref_ddr { regulator-name = "vref_ddr"; regulator-always-on; }; bst_out: boost { regulator-name = "bst_out"; interrupts = ; }; vbus_otg: pwr_sw1 { regulator-name = "vbus_otg"; interrupts = ; regulator-active-discharge = <1>; }; vbus_sw: pwr_sw2 { regulator-name = "vbus_sw"; interrupts = ; regulator-active-discharge = <1>; }; }; onkey { compatible = "st,stpmic1-onkey"; interrupts = , ; interrupt-names = "onkey-falling", "onkey-rising"; status = "okay"; }; watchdog { compatible = "st,stpmic1-wdt"; status = "disabled"; }; }; eeprom@53 { compatible = "atmel,24c02"; reg = <0x53>; pagesize = <16>; }; }; &ipcc { status = "okay"; }; &iwdg2 { timeout-sec = <32>; status = "okay"; secure-status = "disabled"; }; &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>; mbox-names = "vq0", "vq1", "shutdown"; interrupt-parent = <&exti>; interrupts = <68 1>; status = "okay"; }; &pwr_regulators { vdd-supply = <&vdd>; vdd_3v3_usbfs-supply = <&vdd_usb>; }; &qspi { pinctrl-names = "default", "sleep"; pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; pinctrl-1 = <&qspi_clk_sleep_pins_a &qspi_bk1_sleep_pins_a>; reg = <0x58003000 0x1000>, <0x70000000 0x200000>; #address-cells = <1>; #size-cells = <0>; status = "okay"; flash0: flash@0 { compatible = "jedec,spi-nor"; reg = <0>; spi-rx-bus-width = <4>; spi-max-frequency = <50000000>; #address-cells = <1>; #size-cells = <1>; }; }; &rcc { status = "okay"; }; &rng1 { status = "okay"; }; &rtc { status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xx-dkx.dtsi000066400000000000000000000361531464416617300223010ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include #include / { memory@c0000000 { device_type = "memory"; reg = <0xc0000000 0x20000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; mcuram2: mcuram2@10000000 { compatible = "shared-dma-pool"; reg = <0x10000000 0x40000>; no-map; }; vdev0vring0: vdev0vring0@10040000 { compatible = "shared-dma-pool"; reg = <0x10040000 0x1000>; no-map; }; vdev0vring1: vdev0vring1@10041000 { compatible = "shared-dma-pool"; reg = <0x10041000 0x1000>; no-map; }; vdev0buffer: vdev0buffer@10042000 { compatible = "shared-dma-pool"; reg = <0x10042000 0x4000>; no-map; }; ipc_shmem: ipc-shmem@1004f000 { compatible = "shared-dma-pool"; reg = <0x10048000 0x8000>; no-map; }; mcuram: mcuram@30000000 { compatible = "shared-dma-pool"; reg = <0x30000000 0x40000>; no-map; }; retram: retram@38000000 { compatible = "shared-dma-pool"; reg = <0x38000000 0x10000>; no-map; }; gpu_reserved: gpu@d4000000 { reg = <0xd4000000 0x4000000>; no-map; }; }; led { compatible = "gpio-leds"; led-blue { label = "heartbeat"; gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; default-state = "off"; status = "disabled"; }; }; sound { compatible = "audio-graph-card"; label = "STM32MP1-DK"; routing = "Playback" , "MCLK", "Capture" , "MCLK", "MICL" , "Mic Bias"; dais = <&sai2a_port &sai2b_port &i2s2_port>; status = "disabled"; }; vin: vin { compatible = "regulator-fixed"; regulator-name = "vin"; regulator-min-microvolt = <5000000>; regulator-max-microvolt = <5000000>; regulator-always-on; }; }; &adc { pinctrl-names = "default"; pinctrl-0 = <&adc12_ain_pins_a>, <&adc12_usb_cc_pins_a>; vdd-supply = <&vdd>; vdda-supply = <&vdd>; vref-supply = <&vrefbuf>; status = "disabled"; adc1: adc@0 { /* * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in18 & in19. * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C: * 5 * (56 + 47kOhms) * 5pF => 2.5us. * Use arbitrary margin here (e.g. 5us). */ st,min-sample-time-nsecs = <5000>; /* AIN connector, USB Type-C CC1 & CC2 */ st,adc-channels = <0 1 6 13 18 19>; status = "okay"; }; adc2: adc@100 { /* AIN connector, USB Type-C CC1 & CC2 */ st,adc-channels = <0 1 2 6 18 19>; st,min-sample-time-nsecs = <5000>; status = "okay"; }; }; &cec { pinctrl-names = "default", "sleep"; pinctrl-0 = <&cec_pins_b>; pinctrl-1 = <&cec_sleep_pins_b>; status = "disabled"; }; &crc1 { status = "disabled"; }; &dts { status = "disabled"; }; ðernet0 { status = "disabled"; pinctrl-0 = <ðernet0_rgmii_pins_a>; pinctrl-1 = <ðernet0_rgmii_sleep_pins_a>; pinctrl-names = "default", "sleep"; phy-mode = "rgmii-id"; max-speed = <1000>; phy-handle = <&phy0>; mdio0 { #address-cells = <1>; #size-cells = <0>; compatible = "snps,dwmac-mdio"; phy0: ethernet-phy@0 { reg = <0>; }; }; }; &gpu { contiguous-area = <&gpu_reserved>; }; &hash1 { status = "disabled"; }; &i2c1 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c1_pins_a>; pinctrl-1 = <&i2c1_sleep_pins_a>; i2c-scl-rising-time-ns = <100>; i2c-scl-falling-time-ns = <7>; status = "disabled"; /delete-property/dmas; /delete-property/dma-names; hdmi-transmitter@39 { compatible = "sil,sii9022"; reg = <0x39>; iovcc-supply = <&v3v3_hdmi>; cvcc12-supply = <&v1v2_hdmi>; reset-gpios = <&gpioa 10 GPIO_ACTIVE_LOW>; interrupts = <1 IRQ_TYPE_EDGE_FALLING>; interrupt-parent = <&gpiog>; #sound-dai-cells = <0>; status = "okay"; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; sii9022_in: endpoint { remote-endpoint = <<dc_ep0_out>; }; }; port@3 { reg = <3>; sii9022_tx_endpoint: endpoint { remote-endpoint = <&i2s2_endpoint>; }; }; }; }; cs42l51: cs42l51@4a { compatible = "cirrus,cs42l51"; reg = <0x4a>; #sound-dai-cells = <0>; VL-supply = <&v3v3>; VD-supply = <&v1v8_audio>; VA-supply = <&v1v8_audio>; VAHP-supply = <&v1v8_audio>; reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; clocks = <&sai2a>; clock-names = "MCLK"; status = "okay"; cs42l51_port: port { #address-cells = <1>; #size-cells = <0>; cs42l51_tx_endpoint: endpoint@0 { reg = <0>; remote-endpoint = <&sai2a_endpoint>; frame-master = <&cs42l51_tx_endpoint>; bitclock-master = <&cs42l51_tx_endpoint>; }; cs42l51_rx_endpoint: endpoint@1 { reg = <1>; remote-endpoint = <&sai2b_endpoint>; frame-master = <&cs42l51_rx_endpoint>; bitclock-master = <&cs42l51_rx_endpoint>; }; }; }; }; &i2c4 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c4_pins_a>; pinctrl-1 = <&i2c4_sleep_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; clock-frequency = <400000>; status = "okay"; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; stusb1600@28 { compatible = "st,stusb1600"; reg = <0x28>; interrupts = <11 IRQ_TYPE_LEVEL_LOW>; interrupt-parent = <&gpioi>; pinctrl-names = "default"; pinctrl-0 = <&stusb1600_pins_a>; status = "okay"; vdd-supply = <&vin>; connector { compatible = "usb-c-connector"; label = "USB-C"; power-role = "dual"; typec-power-opmode = "default"; port { con_usbotg_hs_ep: endpoint { remote-endpoint = <&usbotg_hs_ep>; }; }; }; }; pmic: stpmic@33 { compatible = "st,stpmic1"; reg = <0x33>; interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; status = "okay"; regulators { compatible = "st,stpmic1-regulators"; buck1-supply = <&vin>; buck2-supply = <&vin>; buck3-supply = <&vin>; buck4-supply = <&vin>; ldo1-supply = <&v3v3>; ldo2-supply = <&vin>; ldo3-supply = <&vdd_ddr>; ldo4-supply = <&vin>; ldo5-supply = <&vin>; ldo6-supply = <&v3v3>; vref_ddr-supply = <&vin>; boost-supply = <&vin>; pwr_sw1-supply = <&bst_out>; pwr_sw2-supply = <&bst_out>; vddcore: buck1 { regulator-name = "vddcore"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd_ddr: buck2 { regulator-name = "vdd_ddr"; regulator-min-microvolt = <1350000>; regulator-max-microvolt = <1350000>; regulator-always-on; regulator-initial-mode = <0>; regulator-over-current-protection; }; vdd: buck3 { regulator-name = "vdd"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; st,mask-reset; regulator-initial-mode = <0>; regulator-over-current-protection; }; v3v3: buck4 { regulator-name = "v3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; regulator-over-current-protection; regulator-initial-mode = <0>; }; v1v8_audio: ldo1 { regulator-name = "v1v8_audio"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; interrupts = ; }; v3v3_hdmi: ldo2 { regulator-name = "v3v3_hdmi"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; interrupts = ; }; vtt_ddr: ldo3 { regulator-name = "vtt_ddr"; regulator-min-microvolt = <500000>; regulator-max-microvolt = <750000>; regulator-always-on; regulator-over-current-protection; }; vdd_usb: ldo4 { regulator-name = "vdd_usb"; interrupts = ; regulator-always-on; }; vdda: ldo5 { regulator-name = "vdda"; regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; interrupts = ; regulator-boot-on; }; v1v2_hdmi: ldo6 { regulator-name = "v1v2_hdmi"; regulator-min-microvolt = <1200000>; regulator-max-microvolt = <1200000>; regulator-always-on; interrupts = ; }; vref_ddr: vref_ddr { regulator-name = "vref_ddr"; regulator-always-on; }; bst_out: boost { regulator-name = "bst_out"; interrupts = ; }; vbus_otg: pwr_sw1 { regulator-name = "vbus_otg"; interrupts = ; }; vbus_sw: pwr_sw2 { regulator-name = "vbus_sw"; interrupts = ; regulator-active-discharge = <1>; }; }; onkey { compatible = "st,stpmic1-onkey"; interrupts = , ; interrupt-names = "onkey-falling", "onkey-rising"; power-off-time-sec = <10>; status = "okay"; }; watchdog { compatible = "st,stpmic1-wdt"; status = "disabled"; }; }; }; &i2c5 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c5_pins_a>; pinctrl-1 = <&i2c5_sleep_pins_a>; i2c-scl-rising-time-ns = <185>; i2c-scl-falling-time-ns = <20>; clock-frequency = <400000>; /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; status = "disabled"; }; &i2s2 { clocks = <&rcc SPI2>, <&rcc SPI2_K>, <&rcc PLL3_Q>, <&rcc PLL3_R>; clock-names = "pclk", "i2sclk", "x8k", "x11k"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2s2_pins_a>; pinctrl-1 = <&i2s2_sleep_pins_a>; status = "disabled"; i2s2_port: port { i2s2_endpoint: endpoint { remote-endpoint = <&sii9022_tx_endpoint>; format = "i2s"; mclk-fs = <256>; }; }; }; &ipcc { status = "disabled"; }; &iwdg1 { timeout-sec = <32>; status = "okay"; }; &iwdg2 { timeout-sec = <32>; status = "disabled"; }; <dc { pinctrl-names = "default", "sleep"; pinctrl-0 = <<dc_pins_a>; pinctrl-1 = <<dc_sleep_pins_a>; status = "disabled"; port { ltdc_ep0_out: endpoint@0 { reg = <0>; remote-endpoint = <&sii9022_in>; }; }; }; &m4_rproc { memory-region = <&retram>, <&mcuram>, <&mcuram2>, <&vdev0vring0>, <&vdev0vring1>, <&vdev0buffer>, <&ipc_shmem>; mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>; mbox-names = "vq0", "vq1", "shutdown", "detach"; interrupt-parent = <&exti>; interrupts = <68 1>; status = "okay"; }; &pwr_regulators { vdd-supply = <&vdd>; vdd_3v3_usbfs-supply = <&vdd_usb>; }; &rcc { compatible = "st,stm32mp1-rcc"; status = "okay"; }; &rng1 { status = "okay"; }; &rtc { status = "okay"; }; &sai2 { clocks = <&rcc SAI2>, <&rcc PLL3_Q>, <&rcc PLL3_R>; clock-names = "pclk", "x8k", "x11k"; pinctrl-names = "default", "sleep"; pinctrl-0 = <&sai2a_pins_a>, <&sai2b_pins_b>; pinctrl-1 = <&sai2a_sleep_pins_a>, <&sai2b_sleep_pins_b>; status = "disabled"; sai2a: audio-controller@4400b004 { #clock-cells = <0>; dma-names = "tx"; clocks = <&rcc SAI2_K>; clock-names = "sai_ck"; status = "okay"; sai2a_port: port { sai2a_endpoint: endpoint { remote-endpoint = <&cs42l51_tx_endpoint>; format = "i2s"; mclk-fs = <256>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; }; }; }; sai2b: audio-controller@4400b024 { dma-names = "rx"; st,sync = <&sai2a 2>; clocks = <&rcc SAI2_K>, <&sai2a>; clock-names = "sai_ck", "MCLK"; status = "okay"; sai2b_port: port { sai2b_endpoint: endpoint { remote-endpoint = <&cs42l51_rx_endpoint>; format = "i2s"; mclk-fs = <256>; dai-tdm-slot-num = <2>; dai-tdm-slot-width = <32>; }; }; }; }; &sdmmc1 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc1_b4_pins_a>; pinctrl-1 = <&sdmmc1_b4_od_pins_a>; pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>; cd-gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; disable-wp; st,neg-edge; bus-width = <4>; vmmc-supply = <&v3v3>; status = "disabled"; }; &sdmmc3 { pinctrl-names = "default", "opendrain", "sleep"; pinctrl-0 = <&sdmmc3_b4_pins_a>; pinctrl-1 = <&sdmmc3_b4_od_pins_a>; pinctrl-2 = <&sdmmc3_b4_sleep_pins_a>; broken-cd; st,neg-edge; bus-width = <4>; vmmc-supply = <&v3v3>; status = "disabled"; }; &timers1 { /* spare dmas for other usage */ /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm1_pins_a>; pinctrl-1 = <&pwm1_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@0 { status = "okay"; }; }; &timers3 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm3_pins_a>; pinctrl-1 = <&pwm3_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@2 { status = "okay"; }; }; &timers4 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm4_pins_a &pwm4_pins_b>; pinctrl-1 = <&pwm4_sleep_pins_a &pwm4_sleep_pins_b>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@3 { status = "okay"; }; }; &timers5 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm5_pins_a>; pinctrl-1 = <&pwm5_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@4 { status = "okay"; }; }; &timers6 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; timer@5 { status = "okay"; }; }; &timers12 { /delete-property/dmas; /delete-property/dma-names; status = "disabled"; pwm { pinctrl-0 = <&pwm12_pins_a>; pinctrl-1 = <&pwm12_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; timer@11 { status = "okay"; }; }; &uart4 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&uart4_pins_a>; pinctrl-1 = <&uart4_sleep_pins_a>; pinctrl-2 = <&uart4_idle_pins_a>; /delete-property/dmas; /delete-property/dma-names; status = "okay"; }; &uart7 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&uart7_pins_c>; pinctrl-1 = <&uart7_sleep_pins_c>; pinctrl-2 = <&uart7_idle_pins_c>; /delete-property/dmas; /delete-property/dma-names; status = "disabled"; }; &usart3 { pinctrl-names = "default", "sleep", "idle"; pinctrl-0 = <&usart3_pins_c>; pinctrl-1 = <&usart3_sleep_pins_c>; pinctrl-2 = <&usart3_idle_pins_c>; uart-has-rtscts; status = "disabled"; }; &usbh_ehci { phys = <&usbphyc_port0>; status = "disabled"; }; &usbotg_hs { phys = <&usbphyc_port1 0>; phy-names = "usb2-phy"; usb-role-switch; status = "disabled"; port { usbotg_hs_ep: endpoint { remote-endpoint = <&con_usbotg_hs_ep>; }; }; }; &usbphyc { status = "disabled"; }; &usbphyc_port0 { phy-supply = <&vdd_usb>; st,tune-hs-dc-level = <2>; st,enable-fs-rftime-tuning; st,enable-hs-rftime-reduction; st,trim-hs-current = <15>; st,trim-hs-impedance = <1>; st,tune-squelch-level = <3>; st,tune-hs-rx-offset = <2>; st,no-lsfs-sc; }; &usbphyc_port1 { phy-supply = <&vdd_usb>; st,tune-hs-dc-level = <2>; st,enable-fs-rftime-tuning; st,enable-hs-rftime-reduction; st,trim-hs-current = <15>; st,trim-hs-impedance = <1>; st,tune-squelch-level = <3>; st,tune-hs-rx-offset = <2>; st,no-lsfs-sc; }; &vrefbuf { regulator-min-microvolt = <2500000>; regulator-max-microvolt = <2500000>; vdda-supply = <&vdd>; status = "okay"; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xxaa-pinctrl.dtsi000066400000000000000000000027511464416617300234650ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { st,package = ; gpioa: gpio@50002000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@50003000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@50004000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 32 16>; }; gpiod: gpio@50005000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@50006000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@50007000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>; }; gpiog: gpio@50008000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 96 16>; }; gpioh: gpio@50009000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 112 16>; }; gpioi: gpio@5000a000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 128 16>; }; gpioj: gpio@5000b000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 144 16>; }; gpiok: gpio@5000c000 { status = "okay"; ngpios = <8>; gpio-ranges = <&pinctrl 0 160 8>; }; }; &pinctrl_z { st,package = ; gpioz: gpio@54004000 { status = "okay"; ngpios = <8>; gpio-ranges = <&pinctrl_z 0 400 8>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xxab-pinctrl.dtsi000066400000000000000000000020371464416617300234630ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { st,package = ; gpioa: gpio@50002000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@50003000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@50004000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 32 16>; }; gpiod: gpio@50005000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@50006000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@50007000 { status = "okay"; ngpios = <6>; gpio-ranges = <&pinctrl 6 86 6>; }; gpiog: gpio@50008000 { status = "okay"; ngpios = <10>; gpio-ranges = <&pinctrl 6 102 10>; }; gpioh: gpio@50009000 { status = "okay"; ngpios = <2>; gpio-ranges = <&pinctrl 0 112 2>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xxac-pinctrl.dtsi000066400000000000000000000024371464416617300234700ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { st,package = ; gpioa: gpio@50002000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@50003000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@50004000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 32 16>; }; gpiod: gpio@50005000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@50006000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@50007000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>; }; gpiog: gpio@50008000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 96 16>; }; gpioh: gpio@50009000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 112 16>; }; gpioi: gpio@5000a000 { status = "okay"; ngpios = <12>; gpio-ranges = <&pinctrl 0 128 12>; }; }; &pinctrl_z { st,package = ; gpioz: gpio@54004000 { status = "okay"; ngpios = <8>; gpio-ranges = <&pinctrl_z 0 400 8>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp15xxad-pinctrl.dtsi000066400000000000000000000020371464416617300234650ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2019 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { st,package = ; gpioa: gpio@50002000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@50003000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@50004000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 32 16>; }; gpiod: gpio@50005000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@50006000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@50007000 { status = "okay"; ngpios = <6>; gpio-ranges = <&pinctrl 6 86 6>; }; gpiog: gpio@50008000 { status = "okay"; ngpios = <10>; gpio-ranges = <&pinctrl 6 102 10>; }; gpioh: gpio@50009000 { status = "okay"; ngpios = <2>; gpio-ranges = <&pinctrl 0 112 2>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp25-pinctrl.dtsi000066400000000000000000000004101464416617300225720ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include optee_os-4.3.0/core/arch/arm/dts/stm32mp251.dtsi000066400000000000000000000164211464416617300212130ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include #include #include / { #address-cells = <2>; #size-cells = <2>; cpus { #address-cells = <1>; #size-cells = <0>; cpu0: cpu@0 { compatible = "arm,cortex-a35"; device_type = "cpu"; reg = <0>; enable-method = "psci"; }; }; psci { compatible = "arm,psci-1.0"; method = "smc"; }; intc: interrupt-controller@4ac00000 { compatible = "arm,cortex-a7-gic"; #interrupt-cells = <3>; interrupt-controller; reg = <0x0 0x4ac10000 0x0 0x1000>, <0x0 0x4ac20000 0x0 0x2000>, <0x0 0x4ac40000 0x0 0x2000>, <0x0 0x4ac60000 0x0 0x2000>; #address-cells = <1>; }; clocks { clk_hse: clk-hse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <24000000>; }; clk_hsi: clk-hsi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <64000000>; }; clk_lse: clk-lse { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32768>; }; clk_lsi: clk-lsi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <32000>; }; clk_msi: clk-msi { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <4000000>; }; clk_i2sin: clk-i2sin { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <0>; }; clk_rcbsec: clk-rcbsec { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <64000000>; }; }; soc@0 { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; ranges = <0x0 0x0 0x0 0x80000000>; hpdma1: dma-controller@40400000 { compatible = "st,stm32-dma3"; reg = <0x40400000 0x1000>; #dma-cells = <4>; status = "disabled"; }; hpdma2: dma-controller@40410000 { compatible = "st,stm32-dma3"; reg = <0x40410000 0x1000>; #dma-cells = <4>; status = "disabled"; }; hpdma3: dma-controller@40420000 { compatible = "st,stm32-dma3"; reg = <0x40420000 0x1000>; #dma-cells = <4>; status = "disabled"; }; ipcc1: mailbox@40490000 { compatible = "st,stm32mp25-ipcc"; reg = <0x40490000 0x400>; status = "disabled"; }; rifsc: rifsc@42080000 { compatible = "st,stm32mp25-rifsc"; reg = <0x42080000 0x1000>; #address-cells = <1>; #size-cells = <1>; usart2: serial@400e0000 { reg = <0x400e0000 0x400>; status = "disabled"; }; }; rcc: rcc@44200000 { compatible = "st,stm32mp25-rcc", "syscon"; reg = <0x44200000 0x10000>; interrupts = ; #clock-cells = <1>; #reset-cells = <1>; clocks = <&clk_hse>, <&clk_hsi>, <&clk_lse>, <&clk_lsi>, <&clk_msi>, <&clk_i2sin>; clock-names = "clk-hse", "clk-hsi", "clk-lse", "clk-lsi", "clk-msi", "clk-i2sin"; hsi_calibration: hsi-calibration { compatible = "st,hsi-cal"; st,cal_hsi_dev = <31>; st,cal_hsi_ref = <1953>; status = "disabled"; }; msi_calibration: msi-calibration { compatible = "st,msi-cal"; status = "disabled"; }; }; pinctrl: pinctrl@44240000 { #address-cells = <1>; #size-cells = <1>; compatible = "st,stm32mp257-pinctrl"; ranges = <0 0x44240000 0xa0400>; pins-are-numbered; gpioa: gpio@44240000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x0 0x400>; clocks = <&rcc CK_BUS_GPIOA>; st,bank-name = "GPIOA"; status = "disabled"; }; gpiob: gpio@44250000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x10000 0x400>; clocks = <&rcc CK_BUS_GPIOB>; st,bank-name = "GPIOB"; status = "disabled"; }; gpioc: gpio@44260000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x20000 0x400>; clocks = <&rcc CK_BUS_GPIOC>; st,bank-name = "GPIOC"; status = "disabled"; }; gpiod: gpio@44270000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x30000 0x400>; clocks = <&rcc CK_BUS_GPIOD>; st,bank-name = "GPIOD"; status = "disabled"; }; gpioe: gpio@44280000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x40000 0x400>; clocks = <&rcc CK_BUS_GPIOE>; st,bank-name = "GPIOE"; status = "disabled"; }; gpiof: gpio@44290000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x50000 0x400>; clocks = <&rcc CK_BUS_GPIOF>; st,bank-name = "GPIOF"; status = "disabled"; }; gpiog: gpio@442a0000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x60000 0x400>; clocks = <&rcc CK_BUS_GPIOG>; st,bank-name = "GPIOG"; status = "disabled"; }; gpioh: gpio@442b0000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x70000 0x400>; clocks = <&rcc CK_BUS_GPIOH>; st,bank-name = "GPIOH"; status = "disabled"; }; gpioi: gpio@442c0000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x80000 0x400>; clocks = <&rcc CK_BUS_GPIOI>; st,bank-name = "GPIOI"; status = "disabled"; }; gpioj: gpio@442d0000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0x90000 0x400>; clocks = <&rcc CK_BUS_GPIOJ>; st,bank-name = "GPIOJ"; status = "disabled"; }; gpiok: gpio@442e0000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0xa0000 0x400>; clocks = <&rcc CK_BUS_GPIOK>; st,bank-name = "GPIOK"; status = "disabled"; }; }; pinctrl_z: pinctrl-z@46200000 { #address-cells = <1>; #size-cells = <1>; compatible = "st,stm32mp257-z-pinctrl"; ranges = <0 0x46200000 0x400>; pins-are-numbered; gpioz: gpio@46200000 { gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; reg = <0 0x400>; clocks = <&rcc CK_BUS_GPIOZ>; st,bank-name = "GPIOZ"; st,bank-ioport = <11>; status = "disabled"; }; }; hsem: hwspinlock@46240000 { compatible = "st,stm32mp25-hsem"; reg = <0x46240000 0x400>; interrupts = ; status = "disabled"; }; ipcc2: mailbox@46250000 { compatible = "st,stm32mp25-ipcc"; reg = <0x46250000 0x400>; status = "disabled"; }; fmc: memory-controller@48200000 { #address-cells = <2>; #size-cells = <1>; compatible = "st,stm32mp25-fmc2-ebi"; reg = <0x48200000 0x400>; status = "disabled"; ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ <4 0 0x80000000 0x10000000>; /* NAND */ }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp253.dtsi000066400000000000000000000005771464416617300212220ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp251.dtsi" / { cpus { cpu1: cpu@1 { compatible = "arm,cortex-a35"; device_type = "cpu"; reg = <1>; enable-method = "psci"; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp255.dtsi000066400000000000000000000003731464416617300212160ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp253.dtsi" / { }; optee_os-4.3.0/core/arch/arm/dts/stm32mp257.dtsi000066400000000000000000000003731464416617300212200ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ #include "stm32mp255.dtsi" / { }; optee_os-4.3.0/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi000066400000000000000000000120121464416617300243560ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2024 - All Rights Reserved */ &clk_hse { clock-frequency = <40000000>; }; &clk_hsi { clock-frequency = <64000000>; }; &clk_lse { clock-frequency = <32768>; }; &clk_lsi { clock-frequency = <32000>; }; &clk_msi { clock-frequency = <16000000>; }; &rcc { st,busclk = < DIV_CFG(DIV_LSMCU, 1) DIV_CFG(DIV_APB1, 0) DIV_CFG(DIV_APB2, 0) DIV_CFG(DIV_APB3, 0) DIV_CFG(DIV_APB4, 0) DIV_CFG(DIV_APBDBG, 0) >; st,flexgen = < FLEXGEN_CFG(0, XBAR_SRC_PLL4, 0, 2) FLEXGEN_CFG(1, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(2, XBAR_SRC_PLL4, 0, 1) FLEXGEN_CFG(3, XBAR_SRC_PLL4, 0, 2) FLEXGEN_CFG(4, XBAR_SRC_PLL4, 0, 3) FLEXGEN_CFG(5, XBAR_SRC_PLL4, 0, 2) FLEXGEN_CFG(6, XBAR_SRC_PLL4, 0, 1) FLEXGEN_CFG(7, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(8, XBAR_SRC_HSI_KER, 0, 0) FLEXGEN_CFG(9, XBAR_SRC_HSI_KER, 0, 0) FLEXGEN_CFG(10, XBAR_SRC_PLL7, 0, 16) FLEXGEN_CFG(11, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(12, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(13, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(14, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(15, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(16, XBAR_SRC_PLL4, 0, 23) FLEXGEN_CFG(17, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(18, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(19, XBAR_SRC_HSI_KER, 0, 3) FLEXGEN_CFG(20, XBAR_SRC_HSI_KER, 0, 0) FLEXGEN_CFG(21, XBAR_SRC_HSI_KER, 0, 0) FLEXGEN_CFG(22, XBAR_SRC_HSI_KER, 0, 0) FLEXGEN_CFG(23, XBAR_SRC_PLL7, 0, 16) FLEXGEN_CFG(24, XBAR_SRC_PLL7, 0, 16) FLEXGEN_CFG(25, XBAR_SRC_PLL7, 0, 16) FLEXGEN_CFG(26, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(27, XBAR_SRC_PLL8, 0, 3) FLEXGEN_CFG(28, XBAR_SRC_PLL8, 0, 21) FLEXGEN_CFG(29, XBAR_SRC_PLL5, 0, 1) FLEXGEN_CFG(30, XBAR_SRC_HSE_KER, 0, 1) FLEXGEN_CFG(31, XBAR_SRC_PLL5, 0, 19) FLEXGEN_CFG(32, XBAR_SRC_PLL5, 0, 19) FLEXGEN_CFG(33, XBAR_SRC_PLL4, 0, 23) FLEXGEN_CFG(34, XBAR_SRC_PLL4, 0, 59) FLEXGEN_CFG(35, XBAR_SRC_HSI_KER, 0, 3) FLEXGEN_CFG(36, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(37, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(38, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(39, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(40, XBAR_SRC_LSE, 0, 0) FLEXGEN_CFG(41, XBAR_SRC_PLL4, 0, 11) FLEXGEN_CFG(42, XBAR_SRC_PLL7, 0, 16) FLEXGEN_CFG(43, XBAR_SRC_PLL4, 0, 23) FLEXGEN_CFG(44, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(45, XBAR_SRC_PLL4, 0, 2) FLEXGEN_CFG(46, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(47, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(48, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(49, XBAR_SRC_PLL5, 0, 3) FLEXGEN_CFG(51, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(52, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(53, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(54, XBAR_SRC_PLL6, 0, 3) FLEXGEN_CFG(55, XBAR_SRC_PLL6, 0, 3) FLEXGEN_CFG(56, XBAR_SRC_PLL4, 0, 5) FLEXGEN_CFG(57, XBAR_SRC_HSE_KER, 0, 1) FLEXGEN_CFG(58, XBAR_SRC_HSE_KER, 0, 1) FLEXGEN_CFG(59, XBAR_SRC_PLL4, 0, 1) FLEXGEN_CFG(60, XBAR_SRC_PLL4, 0, 23) FLEXGEN_CFG(61, XBAR_SRC_PLL4, 0, 7) FLEXGEN_CFG(62, XBAR_SRC_PLL4, 0, 7) FLEXGEN_CFG(63, XBAR_SRC_PLL4, 0, 2) >; st,kerclk = < MUX_CFG(MUX_ADC12, MUX_ADC12_FLEX46) MUX_CFG(MUX_USB2PHY1, MUX_USB2PHY1_FLEX57) MUX_CFG(MUX_USB2PHY2, MUX_USB2PHY2_FLEX58) MUX_CFG(MUX_USB3PCIEPHY, MUX_USB3PCIEPHY_HSE) MUX_CFG(MUX_DSIPHY, MUX_DSIPHY_FLEX28) MUX_CFG(MUX_DSIBLANE, MUX_DSIBLANE_DSIPHY) MUX_CFG(MUX_LVDSPHY, MUX_LVDSPHY_FLEX32) MUX_CFG(MUX_DTS, MUX_DTS_HSE) MUX_CFG(MUX_RTC, MUX_RTC_LSE) MUX_CFG(MUX_D3PER, MUX_D3PER_LSE) MCO_CFG(MCO1, MUX_MCO1_FLEX61, MCO_OFF) MCO_CFG(MCO2, MUX_MCO2_FLEX62, MCO_OFF) >; pll1: st,pll-1 { st,pll = <&pll1_cfg_1200Mhz>; pll1_cfg_1200Mhz: pll1-cfg-1200Mhz { cfg = <30 1 1 1>; src = ; }; pll1_cfg_1500Mhz: pll1-cfg-1500Mhz { cfg = <75 2 1 1>; src = ; }; }; pll2: st,pll-2 { st,pll = <&pll2_cfg_600Mhz>; pll2_cfg_600Mhz: pll2-cfg-600Mhz { cfg = <30 1 1 2>; src = ; }; }; pll3: st,pll-3 { st,pll = <&pll3_cfg_800Mhz>; pll3_cfg_800Mhz: pll3-cfg-800Mhz { cfg = <20 1 1 1>; src = ; }; pll3_cfg_900Mhz: pll3-cfg-900Mhz { cfg = <45 2 1 1>; src = ; }; }; pll4: st,pll-4 { st,pll = <&pll4_cfg_1200Mhz>; pll4_cfg_1200Mhz: pll4-cfg-1200Mhz { cfg = <30 1 1 1>; src = ; }; }; pll5: st,pll-5 { st,pll = <&pll5_cfg_532Mhz>; pll5_cfg_532Mhz: pll5-cfg-532Mhz { cfg = <133 5 1 2>; src = ; }; }; pll6: st,pll-6 { st,pll = <&pll6_cfg_500Mhz>; pll6_cfg_500Mhz: pll6-cfg-500Mhz { cfg = <25 1 1 2>; src = ; }; }; pll7: st,pll-7 { st,pll = <&pll7_cfg_835_51172Mhz>; pll7_cfg_835_51172Mhz: pll7-cfg-835-51172Mhz { cfg = <167 4 1 2>; src = ; frac = < 0x1A3337 >; }; }; pll8: st,pll-8 { st,pll = <&pll8_cfg_594Mhz>; pll8_cfg_594Mhz: pll8-cfg-594Mhz { cfg = <297 5 1 4>; src = ; }; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi000066400000000000000000000337331464416617300244040ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2024 - All Rights Reserved */ &rifsc { st,protreg = < RIFPROT(STM32MP25_RIFSC_TIM1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM10_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM11_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM12_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM13_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM14_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM15_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM16_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM17_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_TIM20_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LPTIM1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LPTIM2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LPTIM3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LPTIM4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LPTIM5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPI8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SPDIFRX_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_USART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_USART2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_USART3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_UART4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_UART5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_USART6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_UART7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_UART8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_UART9_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LPUART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I2C7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_I2C8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SAI1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SAI2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SAI3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SAI4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_MDF1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ADF1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_FDCAN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_HDP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ADC12_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ADC3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ETH1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ETH2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ETHSW_DEIP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ETHSW_ACM_MSGBUF_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ETHSW_ACM_CFG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_USBH_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_USB3DR_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_COMBOPHY_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_PCIE_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_UCPD1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_STGEN_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_SDMMC1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SDMMC2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SDMMC3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_GPU_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LTDC_CMN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LTDC_L0L1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LTDC_L2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LTDC_ROT_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_DSI_CMN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_DSI_TRIG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_DSI_RDFIFO_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_LVDS_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_CSI_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_DCMIPP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_DCMI_PSSI_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_VDEC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_VENC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_RNG_ID, RIF_CID1_BF|RIF_CID2_BF, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_PKA_ID, RIF_CID1_BF|RIF_CID2_BF, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_SAES_ID, RIF_CID1_BF|RIF_CID2_BF, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_HASH_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_CRYP1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_CRYP2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_IWDG1_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_IWDG2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_IWDG3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_IWDG4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_IWDG5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_WWDG1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_WWDG2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_VREFBUF_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_DTS_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_RAMCFG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_CRC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_SERC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN) RIFPROT(STM32MP25_RIFSC_GICV2M_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I3C1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I3C2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I3C3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_I3C4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) RIFPROT(STM32MP25_RIFSC_ICACHE_DCACHE_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS) >; st,rimu = < RIMUPROT(RIMU_ID(0), RIF_CID1, RIF_NSEC, RIF_NPRIV, RIF_CIDSEL_M) RIMUPROT(RIMU_ID(1), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(2), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(3), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(4), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(5), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(6), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(7), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(8), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(9), RIF_CID1, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) RIMUPROT(RIMU_ID(10), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(11), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) RIMUPROT(RIMU_ID(12), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) RIMUPROT(RIMU_ID(13), RIF_CID4, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M) RIMUPROT(RIMU_ID(14), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) RIMUPROT(RIMU_ID(15), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P) >; st,glocked = ; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp257f-ev1.dts000066400000000000000000000016001464416617300217000ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ /dts-v1/; #include #include #include #include "stm32mp25-pinctrl.dtsi" #include "stm32mp257.dtsi" #include "stm32mp257f-ev1-ca35tdcid-rcc.dtsi" #include "stm32mp257f-ev1-ca35tdcid-rif.dtsi" #include "stm32mp25xf.dtsi" #include "stm32mp25xxai-pinctrl.dtsi" / { model = "STMicroelectronics STM32MP257F-EV1 Evaluation Board"; compatible = "st,stm32mp257f-ev1", "st,stm32mp257"; aliases { serial0 = &usart2; }; chosen { stdout-path = "serial0:115200n8"; }; memory@80000000 { device_type = "memory"; reg = <0x0 0x80000000 0x1 0x00000000>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp25xc.dtsi000066400000000000000000000003401464416617300214560ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ / { }; optee_os-4.3.0/core/arch/arm/dts/stm32mp25xf.dtsi000066400000000000000000000003401464416617300214610ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ / { }; optee_os-4.3.0/core/arch/arm/dts/stm32mp25xxai-pinctrl.dtsi000066400000000000000000000026561464416617300235020ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { gpioa: gpio@44240000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@44250000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@44260000 { status = "okay"; ngpios = <14>; gpio-ranges = <&pinctrl 0 32 14>; }; gpiod: gpio@44270000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@44280000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@44290000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>; }; gpiog: gpio@442a0000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 96 16>; }; gpioh: gpio@442b0000 { status = "okay"; ngpios = <12>; gpio-ranges = <&pinctrl 2 114 12>; }; gpioi: gpio@442c0000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 128 16>; }; gpioj: gpio@442d0000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 144 16>; }; gpiok: gpio@442e0000 { status = "okay"; ngpios = <8>; gpio-ranges = <&pinctrl 0 160 8>; }; }; &pinctrl_z { gpioz: gpio@46200000 { status = "okay"; ngpios = <10>; gpio-ranges = <&pinctrl_z 0 400 10>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp25xxak-pinctrl.dtsi000066400000000000000000000023441464416617300234760ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { gpioa: gpio@44240000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@44250000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@44260000 { status = "okay"; ngpios = <14>; gpio-ranges = <&pinctrl 0 32 14>; }; gpiod: gpio@44270000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@44280000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@44290000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>; }; gpiog: gpio@442a0000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 96 16>; }; gpioh: gpio@442b0000 { status = "okay"; ngpios = <12>; gpio-ranges = <&pinctrl 2 114 12>; }; gpioi: gpio@442c0000 { status = "okay"; ngpios = <12>; gpio-ranges = <&pinctrl 0 128 12>; }; }; &pinctrl_z { gpioz: gpio@46200000 { status = "okay"; ngpios = <10>; gpio-ranges = <&pinctrl_z 0 400 10>; }; }; optee_os-4.3.0/core/arch/arm/dts/stm32mp25xxal-pinctrl.dtsi000066400000000000000000000023441464416617300234770ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved * Author: Alexandre Torgue for STMicroelectronics. */ &pinctrl { gpioa: gpio@44240000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 0 16>; }; gpiob: gpio@44250000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 16 16>; }; gpioc: gpio@44260000 { status = "okay"; ngpios = <14>; gpio-ranges = <&pinctrl 0 32 14>; }; gpiod: gpio@44270000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 48 16>; }; gpioe: gpio@44280000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 64 16>; }; gpiof: gpio@44290000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 80 16>; }; gpiog: gpio@442a0000 { status = "okay"; ngpios = <16>; gpio-ranges = <&pinctrl 0 96 16>; }; gpioh: gpio@442b0000 { status = "okay"; ngpios = <12>; gpio-ranges = <&pinctrl 2 114 12>; }; gpioi: gpio@442c0000 { status = "okay"; ngpios = <12>; gpio-ranges = <&pinctrl 0 128 12>; }; }; &pinctrl_z { gpioz: gpio@46200000 { status = "okay"; ngpios = <10>; gpio-ranges = <&pinctrl_z 0 400 10>; }; }; optee_os-4.3.0/core/arch/arm/include/000077500000000000000000000000001464416617300174165ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/arm.h000066400000000000000000000154571464416617300203620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2019-2023, Arm Limited. All rights reserved. */ #ifndef __ARM_H #define __ARM_H #include #include #include /* MIDR definitions */ #define MIDR_PRIMARY_PART_NUM_SHIFT U(4) #define MIDR_PRIMARY_PART_NUM_WIDTH U(12) #define MIDR_PRIMARY_PART_NUM_MASK (BIT(MIDR_PRIMARY_PART_NUM_WIDTH) - 1) #define MIDR_IMPLEMENTER_SHIFT U(24) #define MIDR_IMPLEMENTER_WIDTH U(8) #define MIDR_IMPLEMENTER_MASK (BIT(MIDR_IMPLEMENTER_WIDTH) - 1) #define MIDR_IMPLEMENTER_ARM U(0x41) #define MIDR_VARIANT_SHIFT U(20) #define MIDR_VARIANT_WIDTH U(4) #define MIDR_VARIANT_MASK (BIT(MIDR_VARIANT_WIDTH) - 1) #define MIDR_REVISION_SHIFT U(0) #define MIDR_REVISION_WIDTH U(4) #define MIDR_REVISION_MASK (BIT(MIDR_REVISION_WIDTH) - 1) #define CORTEX_A5_PART_NUM U(0xC05) #define CORTEX_A7_PART_NUM U(0xC07) #define CORTEX_A8_PART_NUM U(0xC08) #define CORTEX_A9_PART_NUM U(0xC09) #define CORTEX_A15_PART_NUM U(0xC0F) #define CORTEX_A17_PART_NUM U(0xC0E) #define CORTEX_A57_PART_NUM U(0xD07) #define CORTEX_A72_PART_NUM U(0xD08) #define CORTEX_A73_PART_NUM U(0xD09) #define CORTEX_A75_PART_NUM U(0xD0A) #define CORTEX_A65_PART_NUM U(0xD06) #define CORTEX_A65AE_PART_NUM U(0xD43) #define CORTEX_A76_PART_NUM U(0xD0B) #define CORTEX_A76AE_PART_NUM U(0xD0E) #define CORTEX_A77_PART_NUM U(0xD0D) #define CORTEX_A78_PART_NUM U(0xD41) #define CORTEX_A78AE_PART_NUM U(0xD42) #define CORTEX_A78C_PART_NUM U(0xD4B) #define CORTEX_A710_PART_NUM U(0xD47) #define CORTEX_X1_PART_NUM U(0xD44) #define CORTEX_X2_PART_NUM U(0xD48) #define NEOVERSE_E1_PART_NUM U(0xD4A) #define NEOVERSE_N1_PART_NUM U(0xD0C) #define NEOVERSE_N2_PART_NUM U(0xD49) #define NEOVERSE_V1_PART_NUM U(0xD40) /* MPIDR definitions */ #define MPIDR_AFFINITY_BITS U(8) #define MPIDR_AFFLVL_MASK ULL(0xff) #define MPIDR_AFF0_SHIFT U(0) #define MPIDR_AFF0_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT) #define MPIDR_AFF1_SHIFT U(8) #define MPIDR_AFF1_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) #define MPIDR_AFF2_SHIFT U(16) #define MPIDR_AFF2_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) #define MPIDR_AFF3_SHIFT U(32) #define MPIDR_AFF3_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT) #define MPIDR_MT_SHIFT U(24) #define MPIDR_MT_MASK BIT(MPIDR_MT_SHIFT) #define MPIDR_CPU_MASK MPIDR_AFF0_MASK #define MPIDR_CLUSTER_SHIFT MPIDR_AFF1_SHIFT #define MPIDR_CLUSTER_MASK MPIDR_AFF1_MASK #define MPIDR_AARCH32_AFF_MASK (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | \ MPIDR_AFF2_MASK) /* ID_ISAR5 Cryptography Extension masks */ #define ID_ISAR5_AES GENMASK_32(7, 4) #define ID_ISAR5_SHA1 GENMASK_32(11, 8) #define ID_ISAR5_SHA2 GENMASK_32(15, 12) #define ID_ISAR5_CRC32 GENMASK_32(19, 16) /* CLIDR definitions */ #define CLIDR_LOUIS_SHIFT U(21) #define CLIDR_LOC_SHIFT U(24) #define CLIDR_FIELD_WIDTH U(3) /* CSSELR definitions */ #define CSSELR_LEVEL_SHIFT U(1) /* CTR definitions */ #define CTR_CWG_SHIFT U(24) #define CTR_CWG_MASK U(0xf) #define CTR_ERG_SHIFT U(20) #define CTR_ERG_MASK U(0xf) #define CTR_DMINLINE_SHIFT U(16) #define CTR_DMINLINE_WIDTH U(4) #define CTR_DMINLINE_MASK (BIT(4) - 1) #define CTR_L1IP_SHIFT U(14) #define CTR_L1IP_MASK U(0x3) #define CTR_IMINLINE_SHIFT U(0) #define CTR_IMINLINE_MASK U(0xf) #define CTR_WORD_SIZE U(4) #define ARM32_CPSR_MODE_MASK U(0x1f) #define ARM32_CPSR_MODE_USR U(0x10) #define ARM32_CPSR_MODE_FIQ U(0x11) #define ARM32_CPSR_MODE_IRQ U(0x12) #define ARM32_CPSR_MODE_SVC U(0x13) #define ARM32_CPSR_MODE_MON U(0x16) #define ARM32_CPSR_MODE_ABT U(0x17) #define ARM32_CPSR_MODE_UND U(0x1b) #define ARM32_CPSR_MODE_SYS U(0x1f) #define ARM32_CPSR_T BIT(5) #define ARM32_CPSR_F_SHIFT U(6) #define ARM32_CPSR_F BIT(6) #define ARM32_CPSR_I BIT(7) #define ARM32_CPSR_A BIT(8) #define ARM32_CPSR_E BIT(9) #define ARM32_CPSR_FIA (ARM32_CPSR_F | ARM32_CPSR_I | ARM32_CPSR_A) #define ARM32_CPSR_IT_MASK (ARM32_CPSR_IT_MASK1 | ARM32_CPSR_IT_MASK2) #define ARM32_CPSR_IT_MASK1 U(0x06000000) #define ARM32_CPSR_IT_MASK2 U(0x0000fc00) /* ARM Generic timer definitions */ #define CNTKCTL_PL0PCTEN BIT(0) /* physical counter el0 access enable */ #define CNTKCTL_PL0VCTEN BIT(1) /* virtual counter el0 access enable */ #ifdef ARM32 #include #endif #ifdef ARM64 #include #endif #ifndef __ASSEMBLER__ static inline __noprof uint64_t barrier_read_counter_timer(void) { isb(); #ifdef CFG_CORE_SEL2_SPMC return read_cntvct(); #else return read_cntpct(); #endif } static inline bool feat_bti_is_implemented(void) { #ifdef ARM32 return false; #else return ((read_id_aa64pfr1_el1() & ID_AA64PFR1_EL1_BT_MASK) == FEAT_BTI_IMPLEMENTED); #endif } static inline unsigned int feat_mte_implemented(void) { #ifdef ARM32 return 0; #else return (read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & ID_AA64PFR1_EL1_MTE_MASK; #endif } static inline unsigned int feat_pan_implemented(void) { #ifdef ARM32 return 0; #else return (read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) & ID_AA64MMFR1_EL1_PAN_MASK; #endif } static inline bool feat_crc32_implemented(void) { #ifdef ARM32 return read_id_isar5() & ID_ISAR5_CRC32; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_CRC32; #endif } static inline bool feat_aes_implemented(void) { #ifdef ARM32 return read_id_isar5() & ID_ISAR5_AES; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_AES; #endif } static inline bool feat_sha1_implemented(void) { #ifdef ARM32 return read_id_isar5() & ID_ISAR5_SHA1; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA1; #endif } static inline bool feat_sha256_implemented(void) { #ifdef ARM32 return read_id_isar5() & ID_ISAR5_SHA2; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA2; #endif } static inline bool feat_sha512_implemented(void) { #ifdef ARM32 return false; #else return ((read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA2) >> ID_AA64ISAR0_SHA2_SHIFT) == ID_AA64ISAR0_SHA2_FEAT_SHA512; #endif } static inline bool feat_sha3_implemented(void) { #ifdef ARM32 return false; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA3; #endif } static inline bool feat_sm3_implemented(void) { #ifdef ARM32 return false; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_SM3; #endif } static inline bool feat_sm4_implemented(void) { #ifdef ARM32 return false; #else return read_id_aa64isar0_el1() & ID_AA64ISAR0_SM4; #endif } static inline bool feat_pauth_is_implemented(void) { #ifdef ARM32 return false; #else uint64_t mask = SHIFT_U64(ID_AA64ISAR1_GPI_MASK, ID_AA64ISAR1_GPI_SHIFT) | SHIFT_U64(ID_AA64ISAR1_GPA_MASK, ID_AA64ISAR1_GPA_SHIFT) | SHIFT_U64(ID_AA64ISAR1_API_MASK, ID_AA64ISAR1_API_SHIFT) | SHIFT_U64(ID_AA64ISAR1_APA_MASK, ID_AA64ISAR1_APA_SHIFT); /* If any of the fields is not zero, PAuth is implemented by arch */ return (read_id_aa64isar1_el1() & mask) != 0U; #endif } #endif #endif /*__ARM_H*/ optee_os-4.3.0/core/arch/arm/include/arm32.h000066400000000000000000000146031464416617300205170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __ARM32_H #define __ARM32_H #include #include #include #include #define CPSR_MODE_MASK ARM32_CPSR_MODE_MASK #define CPSR_MODE_USR ARM32_CPSR_MODE_USR #define CPSR_MODE_FIQ ARM32_CPSR_MODE_FIQ #define CPSR_MODE_IRQ ARM32_CPSR_MODE_IRQ #define CPSR_MODE_SVC ARM32_CPSR_MODE_SVC #define CPSR_MODE_MON ARM32_CPSR_MODE_MON #define CPSR_MODE_ABT ARM32_CPSR_MODE_ABT #define CPSR_MODE_UND ARM32_CPSR_MODE_UND #define CPSR_MODE_SYS ARM32_CPSR_MODE_SYS #define CPSR_T ARM32_CPSR_T #define CPSR_F_SHIFT ARM32_CPSR_F_SHIFT #define CPSR_F ARM32_CPSR_F #define CPSR_I ARM32_CPSR_I #define CPSR_A ARM32_CPSR_A #define CPSR_FIA ARM32_CPSR_FIA #define CPSR_IT_MASK ARM32_CPSR_IT_MASK #define CPSR_IT_MASK1 ARM32_CPSR_IT_MASK1 #define CPSR_IT_MASK2 ARM32_CPSR_IT_MASK2 #define PMCR_DP BIT32(5) #define SCR_NS BIT32(0) #define SCR_IRQ BIT32(1) #define SCR_FIQ BIT32(2) #define SCR_EA BIT32(3) #define SCR_FW BIT32(4) #define SCR_AW BIT32(5) #define SCR_NET BIT32(6) #define SCR_SCD BIT32(7) #define SCR_HCE BIT32(8) #define SCR_SIF BIT32(9) #define SCTLR_M BIT32(0) #define SCTLR_A BIT32(1) #define SCTLR_C BIT32(2) #define SCTLR_CP15BEN BIT32(5) #define SCTLR_SW BIT32(10) #define SCTLR_Z BIT32(11) #define SCTLR_I BIT32(12) #define SCTLR_V BIT32(13) #define SCTLR_RR BIT32(14) #define SCTLR_HA BIT32(17) #define SCTLR_WXN BIT32(19) #define SCTLR_UWXN BIT32(20) #define SCTLR_FI BIT32(21) #define SCTLR_SPAN BIT32(23) #define SCTLR_VE BIT32(24) #define SCTLR_EE BIT32(25) #define SCTLR_NMFI BIT32(27) #define SCTLR_TRE BIT32(28) #define SCTLR_AFE BIT32(29) #define SCTLR_TE BIT32(30) /* Only valid for Cortex-A15 */ #define ACTLR_CA15_ENABLE_INVALIDATE_BTB BIT(0) /* Only valid for Cortex-A8 */ #define ACTLR_CA8_ENABLE_INVALIDATE_BTB BIT(6) /* Only valid for Cortex-A9 */ #define ACTLR_CA9_WFLZ BIT(3) #define ACTLR_SMP BIT32(6) #define NSACR_CP10 BIT32(10) #define NSACR_CP11 BIT32(11) #define NSACR_NSD32DIS BIT32(14) #define NSACR_NSASEDIS BIT32(15) #define NSACR_NS_L2ERR BIT32(17) #define NSACR_NS_SMP BIT32(18) #define CPACR_ASEDIS BIT32(31) #define CPACR_D32DIS BIT32(30) #define CPACR_CP(co_proc, access) SHIFT_U32((access), ((co_proc) * 2)) #define CPACR_CP_ACCESS_DENIED U(0x0) #define CPACR_CP_ACCESS_PL1_ONLY U(0x1) #define CPACR_CP_ACCESS_FULL U(0x3) #define DACR_DOMAIN(num, perm) SHIFT_U32((perm), ((num) * 2)) #define DACR_DOMAIN_PERM_NO_ACCESS U(0x0) #define DACR_DOMAIN_PERM_CLIENT U(0x1) #define DACR_DOMAIN_PERM_MANAGER U(0x3) #define PAR_F BIT32(0) #define PAR_SS BIT32(1) #define PAR_LPAE BIT32(11) #define PAR_PA_SHIFT U(12) #define PAR32_PA_MASK (BIT32(20) - 1) #define PAR64_PA_MASK (BIT64(28) - 1) /* * TTBCR has different register layout if LPAE is enabled or not. * TTBCR.EAE == 0 => LPAE is not enabled * TTBCR.EAE == 1 => LPAE is enabled */ #define TTBCR_EAE BIT32(31) /* When TTBCR.EAE == 0 */ #define TTBCR_PD0 BIT32(4) #define TTBCR_PD1 BIT32(5) /* When TTBCR.EAE == 1 */ #define TTBCR_T0SZ_SHIFT U(0) #define TTBCR_EPD0 BIT32(7) #define TTBCR_IRGN0_SHIFT U(8) #define TTBCR_ORGN0_SHIFT U(10) #define TTBCR_SH0_SHIFT U(12) #define TTBCR_T1SZ_SHIFT U(16) #define TTBCR_A1 BIT32(22) #define TTBCR_EPD1 BIT32(23) #define TTBCR_IRGN1_SHIFT U(24) #define TTBCR_ORGN1_SHIFT U(26) #define TTBCR_SH1_SHIFT U(28) /* Normal memory, Inner/Outer Non-cacheable */ #define TTBCR_XRGNX_NC U(0x0) /* Normal memory, Inner/Outer Write-Back Write-Allocate Cacheable */ #define TTBCR_XRGNX_WB U(0x1) /* Normal memory, Inner/Outer Write-Through Cacheable */ #define TTBCR_XRGNX_WT U(0x2) /* Normal memory, Inner/Outer Write-Back no Write-Allocate Cacheable */ #define TTBCR_XRGNX_WBWA U(0x3) /* Non-shareable */ #define TTBCR_SHX_NSH U(0x0) /* Outer Shareable */ #define TTBCR_SHX_OSH U(0x2) /* Inner Shareable */ #define TTBCR_SHX_ISH U(0x3) #define TTBR_ASID_MASK U(0xff) #define TTBR_ASID_SHIFT U(48) #define TLBI_MVA_SHIFT U(12) #define TLBI_ASID_MASK U(0xff) #define FSR_LPAE BIT32(9) #define FSR_WNR BIT32(11) /* Valid if FSR.LPAE is 1 */ #define FSR_STATUS_MASK (BIT32(6) - 1) /* Valid if FSR.LPAE is 0 */ #define FSR_FS_MASK (BIT32(10) | (BIT32(4) - 1)) /* ID_PFR1 bit fields */ #define IDPFR1_VIRT_SHIFT U(12) #define IDPFR1_VIRT_MASK SHIFT_U32(0xF, IDPFR1_VIRT_SHIFT) #define IDPFR1_GENTIMER_SHIFT U(16) #define IDPFR1_GENTIMER_MASK SHIFT_U32(0xF, IDPFR1_GENTIMER_SHIFT) #ifndef __ASSEMBLER__ #include #ifdef CFG_ARM_GICV3 #include #endif static inline __noprof void isb(void) { asm volatile ("isb" : : : "memory"); } static inline __noprof void dsb(void) { asm volatile ("dsb" : : : "memory"); } static inline __noprof void dsb_ish(void) { asm volatile ("dsb ish" : : : "memory"); } static inline __noprof void dsb_ishst(void) { asm volatile ("dsb ishst" : : : "memory"); } static inline __noprof void dmb(void) { asm volatile ("dmb" : : : "memory"); } static inline __noprof void sev(void) { asm volatile ("sev" : : : "memory"); } static inline __noprof void wfe(void) { asm volatile ("wfe" : : : "memory"); } static inline __noprof uint32_t read_cpsr(void) { uint32_t cpsr; asm volatile ("mrs %[cpsr], cpsr" : [cpsr] "=r" (cpsr) ); return cpsr; } static inline __noprof void write_cpsr(uint32_t cpsr) { asm volatile ("msr cpsr_fsxc, %[cpsr]" : : [cpsr] "r" (cpsr) ); } static inline __noprof uint32_t read_spsr(void) { uint32_t spsr; asm volatile ("mrs %[spsr], spsr" : [spsr] "=r" (spsr) ); return spsr; } static inline __noprof void wfi(void) { asm volatile("wfi" : : : "memory"); } static __always_inline __noprof uint32_t read_pc(void) { uint32_t val; asm volatile ("adr %0, ." : "=r" (val)); return val; } static __always_inline __noprof uint32_t read_sp(void) { uint32_t val; asm volatile ("mov %0, sp" : "=r" (val)); return val; } static __always_inline __noprof uint32_t read_lr(void) { uint32_t val; asm volatile ("mov %0, lr" : "=r" (val)); return val; } static __always_inline __noprof uint32_t read_fp(void) { uint32_t val; asm volatile ("mov %0, fp" : "=r" (val)); return val; } static __always_inline __noprof uint32_t read_r7(void) { uint32_t val; asm volatile ("mov %0, r7" : "=r" (val)); return val; } #endif /*__ASSEMBLER__*/ #endif /*__ARM32_H*/ optee_os-4.3.0/core/arch/arm/include/arm32_macros.S000066400000000000000000000007651464416617300220420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #ifdef CFG_ARM_GICV3 #include #endif .macro mov_imm reg, val .if ((\val) & 0xffff0000) == 0 movw \reg, #(\val) .else movw \reg, #((\val) & 0xffff) movt \reg, #((\val) >> 16) .endif .endm .macro panic_at_smc_return #if defined(CFG_TEE_CORE_DEBUG) bl __panic_at_smc_return #else b . #endif .endm optee_os-4.3.0/core/arch/arm/include/arm32_macros_cortex_a9.S000066400000000000000000000032511464416617300240100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Freescale Semiconductor, Inc. * All rights reserved. * * Peng Fan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ .macro write_pcr reg mcr p15, 0, \reg, c15, c0, 0 .endm .macro read_pcr reg mrc p15, 0, \reg, c15, c0, 0 .endm .macro write_diag reg mcr p15, 0, \reg, c15, c0, 1 .endm .macro read_diag reg mrc p15, 0, \reg, c15, c0, 1 .endm optee_os-4.3.0/core/arch/arm/include/arm64.h000066400000000000000000000370711464416617300205300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2023, Arm Limited */ #ifndef __ARM64_H #define __ARM64_H #include #include #include #include #define SCTLR_M BIT64(0) #define SCTLR_A BIT64(1) #define SCTLR_C BIT64(2) #define SCTLR_SA BIT64(3) #define SCTLR_I BIT64(12) #define SCTLR_ENDB BIT64(13) #define SCTLR_WXN BIT64(19) #define SCTLR_SPAN BIT64(23) #define SCTLR_ENDA BIT64(27) #define SCTLR_ENIB BIT64(30) #define SCTLR_ENIA BIT64(31) #define SCTLR_BT0 BIT64(35) #define SCTLR_BT1 BIT64(36) #define SCTLR_ITFSB BIT64(37) #define SCTLR_TCF_MASK SHIFT_U64(0x3, 40) #define SCTLR_TCF_NONE SHIFT_U64(0x0, 40) #define SCTLR_TCF_SYNC SHIFT_U64(0x1, 40) #define SCTLR_TCF_ASYNC SHIFT_U64(0x2, 40) #define SCTLR_TCF_ASYMM SHIFT_U64(0x3, 40) #define SCTLR_TCF0_MASK SHIFT_U64(0x3, 38) #define SCTLR_TCF0_NONE SHIFT_U64(0x0, 38) #define SCTLR_TCF0_SYNC SHIFT_U64(0x1, 38) #define SCTLR_TCF0_ASYNC SHIFT_U64(0x2, 38) #define SCTLR_TCF0_ASYMM SHIFT_U64(0x3, 38) #define SCTLR_ATA0 BIT64(42) #define SCTLR_ATA BIT64(43) #define TTBR_ASID_MASK U(0xff) #define TTBR_ASID_SHIFT U(48) #define CLIDR_LOUIS_SHIFT U(21) #define CLIDR_LOC_SHIFT U(24) #define CLIDR_FIELD_WIDTH U(3) #define CSSELR_LEVEL_SHIFT U(1) #define DAIFBIT_FIQ BIT32(0) #define DAIFBIT_IRQ BIT32(1) #define DAIFBIT_ABT BIT32(2) #define DAIFBIT_DBG BIT32(3) #define DAIFBIT_ALL (DAIFBIT_FIQ | DAIFBIT_IRQ | \ DAIFBIT_ABT | DAIFBIT_DBG) #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) #define DAIFBIT_NATIVE_INTR DAIFBIT_IRQ #define DAIFBIT_FOREIGN_INTR DAIFBIT_FIQ #else #define DAIFBIT_NATIVE_INTR DAIFBIT_FIQ #define DAIFBIT_FOREIGN_INTR DAIFBIT_IRQ #endif #define DAIF_F_SHIFT U(6) #define DAIF_F BIT32(6) #define DAIF_I BIT32(7) #define DAIF_A BIT32(8) #define DAIF_D BIT32(9) #define DAIF_AIF (DAIF_A | DAIF_I | DAIF_F) #define SPSR_MODE_RW_SHIFT U(4) #define SPSR_MODE_RW_MASK U(0x1) #define SPSR_MODE_RW_64 U(0x0) #define SPSR_MODE_RW_32 U(0x1) #define SPSR_64_MODE_SP_SHIFT U(0) #define SPSR_64_MODE_SP_MASK U(0x1) #define SPSR_64_MODE_SP_EL0 U(0x0) #define SPSR_64_MODE_SP_ELX U(0x1) #define SPSR_64_MODE_EL_SHIFT U(2) #define SPSR_64_MODE_EL_MASK U(0x3) #define SPSR_64_MODE_EL1 U(0x1) #define SPSR_64_MODE_EL0 U(0x0) #define SPSR_64_DAIF_SHIFT U(6) #define SPSR_64_DAIF_MASK U(0xf) #define SPSR_64_PAN BIT64(22) #define SPSR_32_AIF_SHIFT U(6) #define SPSR_32_AIF_MASK U(0x7) #define SPSR_32_E_SHIFT U(9) #define SPSR_32_E_MASK U(0x1) #define SPSR_32_E_LITTLE U(0x0) #define SPSR_32_E_BIG U(0x1) #define SPSR_32_T_SHIFT U(5) #define SPSR_32_T_MASK U(0x1) #define SPSR_32_T_ARM U(0x0) #define SPSR_32_T_THUMB U(0x1) #define SPSR_32_MODE_SHIFT U(0) #define SPSR_32_MODE_MASK U(0xf) #define SPSR_32_MODE_USR U(0x0) #define SPSR_64(el, sp, daif) \ (SPSR_MODE_RW_64 << SPSR_MODE_RW_SHIFT | \ ((el) & SPSR_64_MODE_EL_MASK) << SPSR_64_MODE_EL_SHIFT | \ ((sp) & SPSR_64_MODE_SP_MASK) << SPSR_64_MODE_SP_SHIFT | \ ((daif) & SPSR_64_DAIF_MASK) << SPSR_64_DAIF_SHIFT) #define SPSR_32(mode, isa, aif) \ (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT | \ SPSR_32_E_LITTLE << SPSR_32_E_SHIFT | \ ((mode) & SPSR_32_MODE_MASK) << SPSR_32_MODE_SHIFT | \ ((isa) & SPSR_32_T_MASK) << SPSR_32_T_SHIFT | \ ((aif) & SPSR_32_AIF_MASK) << SPSR_32_AIF_SHIFT) #define TCR_T0SZ_SHIFT U(0) #define TCR_EPD0 BIT64(7) #define TCR_IRGN0_SHIFT U(8) #define TCR_ORGN0_SHIFT U(10) #define TCR_SH0_SHIFT U(12) #define TCR_T1SZ_SHIFT U(16) #define TCR_A1 BIT64(22) #define TCR_EPD1 BIT64(23) #define TCR_IRGN1_SHIFT U(24) #define TCR_ORGN1_SHIFT U(26) #define TCR_SH1_SHIFT U(28) #define TCR_EL1_IPS_SHIFT U(32) #define TCR_EL1_IPS_MASK UINT64_C(0x7) #define TCR_TG1_4KB SHIFT_U64(2, 30) #define TCR_RES1 BIT64(31) #define TCR_TBI0 BIT64(37) #define TCR_TBI1 BIT64(38) #define TCR_TCMA0 BIT64(57) #define TCR_TCMA1 BIT64(58) /* Normal memory, Inner/Outer Non-cacheable */ #define TCR_XRGNX_NC U(0x0) /* Normal memory, Inner/Outer Write-Back Write-Allocate Cacheable */ #define TCR_XRGNX_WB U(0x1) /* Normal memory, Inner/Outer Write-Through Cacheable */ #define TCR_XRGNX_WT U(0x2) /* Normal memory, Inner/Outer Write-Back no Write-Allocate Cacheable */ #define TCR_XRGNX_WBWA U(0x3) /* Non-shareable */ #define TCR_SHX_NSH U(0x0) /* Outer Shareable */ #define TCR_SHX_OSH U(0x2) /* Inner Shareable */ #define TCR_SHX_ISH U(0x3) #define ESR_EC_SHIFT U(26) #define ESR_EC_MASK U(0x3f) #define ESR_EC_UNKNOWN U(0x00) #define ESR_EC_WFI U(0x01) #define ESR_EC_AARCH32_CP15_32 U(0x03) #define ESR_EC_AARCH32_CP15_64 U(0x04) #define ESR_EC_AARCH32_CP14_MR U(0x05) #define ESR_EC_AARCH32_CP14_LS U(0x06) #define ESR_EC_FP_ASIMD U(0x07) #define ESR_EC_AARCH32_CP10_ID U(0x08) #define ESR_EC_PAUTH U(0x09) #define ESR_EC_AARCH32_CP14_64 U(0x0c) #define ESR_EC_BTI U(0x0d) #define ESR_EC_ILLEGAL U(0x0e) #define ESR_EC_AARCH32_SVC U(0x11) #define ESR_EC_AARCH64_SVC U(0x15) #define ESR_EC_AARCH64_SYS U(0x18) #define ESR_EC_ERET U(0x1a) #define ESR_EC_FPAC U(0x1c) #define ESR_EC_IABT_EL0 U(0x20) #define ESR_EC_IABT_EL1 U(0x21) #define ESR_EC_PC_ALIGN U(0x22) #define ESR_EC_DABT_EL0 U(0x24) #define ESR_EC_DABT_EL1 U(0x25) #define ESR_EC_SP_ALIGN U(0x26) #define ESR_EC_AARCH32_FP U(0x28) #define ESR_EC_AARCH64_FP U(0x2c) #define ESR_EC_SERROR U(0x2f) #define ESR_EC_BREAKPT_EL0 U(0x30) #define ESR_EC_BREAKPT_EL1 U(0x31) #define ESR_EC_SOFTSTP_EL0 U(0x32) #define ESR_EC_SOFTSTP_EL1 U(0x33) #define ESR_EC_WATCHPT_EL0 U(0x34) #define ESR_EC_WATCHPT_EL1 U(0x35) #define ESR_EC_AARCH32_BKPT U(0x38) #define ESR_EC_AARCH64_BRK U(0x3c) /* Combined defines for DFSC and IFSC */ #define ESR_FSC_MASK U(0x3f) #define ESR_FSC_SIZE_L0 U(0x00) #define ESR_FSC_SIZE_L1 U(0x01) #define ESR_FSC_SIZE_L2 U(0x02) #define ESR_FSC_SIZE_L3 U(0x03) #define ESR_FSC_TRANS_L0 U(0x04) #define ESR_FSC_TRANS_L1 U(0x05) #define ESR_FSC_TRANS_L2 U(0x06) #define ESR_FSC_TRANS_L3 U(0x07) #define ESR_FSC_ACCF_L1 U(0x09) #define ESR_FSC_ACCF_L2 U(0x0a) #define ESR_FSC_ACCF_L3 U(0x0b) #define ESR_FSC_PERMF_L1 U(0x0d) #define ESR_FSC_PERMF_L2 U(0x0e) #define ESR_FSC_PERMF_L3 U(0x0f) #define ESR_FSC_TAG_CHECK U(0x11) #define ESR_FSC_ALIGN U(0x21) /* WnR for DABT and RES0 for IABT */ #define ESR_ABT_WNR BIT32(6) #define CPACR_EL1_FPEN_SHIFT U(20) #define CPACR_EL1_FPEN_MASK U(0x3) #define CPACR_EL1_FPEN_NONE U(0x0) #define CPACR_EL1_FPEN_EL1 U(0x1) #define CPACR_EL1_FPEN_EL0EL1 U(0x3) #define CPACR_EL1_FPEN(x) ((x) >> CPACR_EL1_FPEN_SHIFT \ & CPACR_EL1_FPEN_MASK) #define PAR_F BIT32(0) #define PAR_PA_SHIFT U(12) #define PAR_PA_MASK (BIT64(36) - 1) #define TLBI_VA_SHIFT U(12) #define TLBI_ASID_SHIFT U(48) #define TLBI_ASID_MASK U(0xff) #define ID_AA64PFR1_EL1_BT_MASK ULL(0xf) #define FEAT_BTI_IMPLEMENTED ULL(0x1) #define ID_AA64PFR1_EL1_MTE_MASK UL(0xf) #define ID_AA64PFR1_EL1_MTE_SHIFT U(8) #define FEAT_MTE_NOT_IMPLEMENTED U(0x0) #define FEAT_MTE_IMPLEMENTED U(0x1) #define FEAT_MTE2_IMPLEMENTED U(0x2) #define FEAT_MTE3_IMPLEMENTED U(0x3) #define ID_AA64MMFR0_EL1_PARANGE_MASK UL(0xf) #define ID_AA64MMFR1_EL1_PAN_MASK UL(0xf) #define ID_AA64MMFR1_EL1_PAN_SHIFT U(20) #define FEAT_PAN_NOT_IMPLEMENTED U(0x0) #define FEAT_PAN_IMPLEMENTED U(0x1) #define FEAT_PAN2_IMPLEMENTED U(0x2) #define FEAT_PAN3_IMPLEMENTED U(0x3) #define ID_AA64ISAR1_GPI_SHIFT U(28) #define ID_AA64ISAR1_GPI_MASK U(0xf) #define ID_AA64ISAR1_GPI_NI U(0x0) #define ID_AA64ISAR1_GPI_IMP_DEF U(0x1) #define ID_AA64ISAR1_GPA_SHIFT U(24) #define ID_AA64ISAR1_GPA_MASK U(0xf) #define ID_AA64ISAR1_GPA_NI U(0x0) #define ID_AA64ISAR1_GPA_ARCHITECTED U(0x1) #define ID_AA64ISAR1_API_SHIFT U(8) #define ID_AA64ISAR1_API_MASK U(0xf) #define ID_AA64ISAR1_API_NI U(0x0) #define ID_AA64ISAR1_API_IMP_DEF U(0x1) #define ID_AA64ISAR1_API_IMP_DEF_EPAC U(0x2) #define ID_AA64ISAR1_API_IMP_DEF_EPAC2 U(0x3) #define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC U(0x4) #define ID_AA64ISAR1_API_IMP_DEF_EPAC2_FPAC_CMB U(0x5) #define ID_AA64ISAR1_APA_SHIFT U(4) #define ID_AA64ISAR1_APA_MASK U(0xf) #define ID_AA64ISAR1_APA_NI U(0x0) #define ID_AA64ISAR1_APA_ARCHITECTED U(0x1) #define ID_AA64ISAR1_APA_ARCH_EPAC U(0x2) #define ID_AA64ISAR1_APA_ARCH_EPAC2 U(0x3) #define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC U(0x4) #define ID_AA64ISAR1_APA_ARCH_EPAC2_FPAC_CMB U(0x5) #define ID_MMFR3_EL1_PAN_SHIFT U(16) #define GCR_EL1_RRND BIT64(16) /* ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0 */ #define ID_AA64ISAR0_AES GENMASK_64(7, 4) #define ID_AA64ISAR0_SHA1 GENMASK_64(11, 8) #define ID_AA64ISAR0_SHA2 GENMASK_64(15, 12) #define ID_AA64ISAR0_CRC32 GENMASK_64(19, 16) #define ID_AA64ISAR0_ATOMIC GENMASK_64(23, 20) #define ID_AA64ISAR0_TME GENMASK_64(27, 24) #define ID_AA64ISAR0_RDM GENMASK_64(31, 28) #define ID_AA64ISAR0_SHA3 GENMASK_64(35, 32) #define ID_AA64ISAR0_SM3 GENMASK_64(39, 36) #define ID_AA64ISAR0_SM4 GENMASK_64(43, 40) #define ID_AA64ISAR0_SHA2_SHIFT U(12) #define ID_AA64ISAR0_SHA2_FEAT_SHA256 U(1) #define ID_AA64ISAR0_SHA2_FEAT_SHA512 U(2) #ifndef __ASSEMBLER__ static inline __noprof void isb(void) { asm volatile ("isb" : : : "memory"); } static inline __noprof void dsb(void) { asm volatile ("dsb sy" : : : "memory"); } static inline __noprof void dsb_ish(void) { asm volatile ("dsb ish" : : : "memory"); } static inline __noprof void dsb_ishst(void) { asm volatile ("dsb ishst" : : : "memory"); } static inline __noprof void dsb_osh(void) { asm volatile ("dsb osh" : : : "memory"); } static inline __noprof void sev(void) { asm volatile ("sev" : : : "memory"); } static inline __noprof void wfe(void) { asm volatile ("wfe" : : : "memory"); } static inline __noprof void wfi(void) { asm volatile ("wfi" : : : "memory"); } static inline __noprof void write_at_s1e1r(uint64_t va) { asm volatile ("at S1E1R, %0" : : "r" (va)); } static __always_inline __noprof uint64_t read_pc(void) { uint64_t val; asm volatile ("adr %0, ." : "=r" (val)); return val; } static __always_inline __noprof uint64_t read_fp(void) { uint64_t val; asm volatile ("mov %0, x29" : "=r" (val)); return val; } static inline __noprof uint64_t read_pmu_ccnt(void) { uint64_t val; asm volatile("mrs %0, PMCCNTR_EL0" : "=r"(val)); return val; } static inline __noprof void tlbi_vaae1is(uint64_t va) { asm volatile ("tlbi vaae1is, %0" : : "r" (va)); } static inline __noprof void tlbi_vale1is(uint64_t va) { asm volatile ("tlbi vale1is, %0" : : "r" (va)); } static inline void write_64bit_pair(uint64_t dst, uint64_t hi, uint64_t lo) { /* 128bits should be written to hardware at one time */ asm volatile ("stp %1, %0, [%2]" : : "r" (hi), "r" (lo), "r" (dst) : "memory"); } static inline void read_64bit_pair(uint64_t src, uint64_t *hi, uint64_t *lo) { uint64_t tmp0 = 0; uint64_t tmp1 = 0; /* 128bits should be read from hardware at one time */ asm volatile ("ldp %0, %1, [%2]\n" : "=&r"(tmp0), "=&r"(tmp1) : "r"(src) : "memory"); *lo = tmp0; *hi = tmp1; } /* * Templates for register read/write functions based on mrs/msr */ #define DEFINE_REG_READ_FUNC_(reg, type, asmreg) \ static inline __noprof type read_##reg(void) \ { \ uint64_t val64 = 0; \ \ asm volatile("mrs %0, " #asmreg : "=r" (val64)); \ return val64; \ } #define DEFINE_REG_WRITE_FUNC_(reg, type, asmreg) \ static inline __noprof void write_##reg(type val) \ { \ uint64_t val64 = val; \ \ asm volatile("msr " #asmreg ", %0" : : "r" (val64)); \ } #define DEFINE_U32_REG_READ_FUNC(reg) \ DEFINE_REG_READ_FUNC_(reg, uint32_t, reg) #define DEFINE_U32_REG_WRITE_FUNC(reg) \ DEFINE_REG_WRITE_FUNC_(reg, uint32_t, reg) #define DEFINE_U32_REG_READWRITE_FUNCS(reg) \ DEFINE_U32_REG_READ_FUNC(reg) \ DEFINE_U32_REG_WRITE_FUNC(reg) #define DEFINE_U64_REG_READ_FUNC(reg) \ DEFINE_REG_READ_FUNC_(reg, uint64_t, reg) #define DEFINE_U64_REG_WRITE_FUNC(reg) \ DEFINE_REG_WRITE_FUNC_(reg, uint64_t, reg) #define DEFINE_U64_REG_READWRITE_FUNCS(reg) \ DEFINE_U64_REG_READ_FUNC(reg) \ DEFINE_U64_REG_WRITE_FUNC(reg) /* * Define register access functions */ DEFINE_U32_REG_READWRITE_FUNCS(cpacr_el1) DEFINE_U32_REG_READWRITE_FUNCS(daif) #ifdef __clang__ DEFINE_REG_READ_FUNC_(fpcr, uint32_t, S3_3_c4_c4_0) DEFINE_REG_WRITE_FUNC_(fpcr, uint32_t, S3_3_c4_c4_0) DEFINE_REG_READ_FUNC_(fpsr, uint32_t, S3_3_c4_c4_1) DEFINE_REG_WRITE_FUNC_(fpsr, uint32_t, S3_3_c4_c4_1) #else DEFINE_U32_REG_READWRITE_FUNCS(fpcr) DEFINE_U32_REG_READWRITE_FUNCS(fpsr) #endif DEFINE_U32_REG_READ_FUNC(ctr_el0) #define read_ctr() read_ctr_el0() DEFINE_U32_REG_READ_FUNC(contextidr_el1) DEFINE_U64_REG_READ_FUNC(sctlr_el1) /* ARM Generic timer functions */ DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0) DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0) DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0) DEFINE_REG_READ_FUNC_(cntkctl, uint32_t, cntkctl_el1) DEFINE_REG_WRITE_FUNC_(cntkctl, uint32_t, cntkctl_el1) DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1) DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1) DEFINE_REG_READ_FUNC_(cntps_tval, uint32_t, cntps_tval_el1) DEFINE_REG_WRITE_FUNC_(cntps_tval, uint32_t, cntps_tval_el1) DEFINE_REG_READ_FUNC_(cntps_cval, uint64_t, cntps_cval_el1) DEFINE_REG_WRITE_FUNC_(cntps_cval, uint64_t, cntps_cval_el1) DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0) DEFINE_U64_REG_READWRITE_FUNCS(ttbr0_el1) DEFINE_U64_REG_READWRITE_FUNCS(ttbr1_el1) DEFINE_U64_REG_READWRITE_FUNCS(tcr_el1) DEFINE_U64_REG_READ_FUNC(esr_el1) DEFINE_U64_REG_READ_FUNC(far_el1) DEFINE_U64_REG_READ_FUNC(mpidr_el1) /* Alias for reading this register to avoid ifdefs in code */ #define read_mpidr() read_mpidr_el1() DEFINE_U64_REG_READ_FUNC(midr_el1) /* Alias for reading this register to avoid ifdefs in code */ #define read_midr() read_midr_el1() DEFINE_U64_REG_READ_FUNC(par_el1) DEFINE_U64_REG_WRITE_FUNC(mair_el1) DEFINE_U64_REG_READ_FUNC(id_aa64mmfr0_el1) DEFINE_U64_REG_READ_FUNC(id_aa64mmfr1_el1) DEFINE_U64_REG_READ_FUNC(id_aa64pfr1_el1) DEFINE_U64_REG_READ_FUNC(id_aa64isar0_el1) DEFINE_U64_REG_READ_FUNC(id_aa64isar1_el1) DEFINE_REG_READ_FUNC_(apiakeylo, uint64_t, S3_0_c2_c1_0) DEFINE_REG_READ_FUNC_(apiakeyhi, uint64_t, S3_0_c2_c1_1) DEFINE_REG_WRITE_FUNC_(apibkeylo, uint64_t, S3_0_c2_c1_2) DEFINE_REG_WRITE_FUNC_(apibkeyhi, uint64_t, S3_0_c2_c1_3) DEFINE_REG_READ_FUNC_(apdakeylo, uint64_t, S3_0_c2_c2_0) DEFINE_REG_READ_FUNC_(apdakeyhi, uint64_t, S3_0_c2_c2_1) DEFINE_REG_WRITE_FUNC_(apdbkeylo, uint64_t, S3_0_c2_c2_2) DEFINE_REG_WRITE_FUNC_(apdbkeyhi, uint64_t, S3_0_c2_c2_3) DEFINE_REG_WRITE_FUNC_(apgakeylo, uint64_t, S3_0_c2_c3_0) DEFINE_REG_WRITE_FUNC_(apgakeyhi, uint64_t, S3_0_c2_c3_1) /* Register read/write functions for GICC registers by using system interface */ DEFINE_REG_READ_FUNC_(icc_ctlr, uint32_t, S3_0_C12_C12_4) DEFINE_REG_WRITE_FUNC_(icc_ctlr, uint32_t, S3_0_C12_C12_4) DEFINE_REG_WRITE_FUNC_(icc_pmr, uint32_t, S3_0_C4_C6_0) DEFINE_REG_READ_FUNC_(icc_iar0, uint32_t, S3_0_c12_c8_0) DEFINE_REG_READ_FUNC_(icc_iar1, uint32_t, S3_0_c12_c12_0) DEFINE_REG_WRITE_FUNC_(icc_eoir0, uint32_t, S3_0_c12_c8_1) DEFINE_REG_WRITE_FUNC_(icc_eoir1, uint32_t, S3_0_c12_c12_1) DEFINE_REG_WRITE_FUNC_(icc_igrpen0, uint32_t, S3_0_C12_C12_6) DEFINE_REG_WRITE_FUNC_(icc_igrpen1, uint32_t, S3_0_C12_C12_7) DEFINE_REG_WRITE_FUNC_(icc_sgi1r, uint64_t, S3_0_C12_C11_5) DEFINE_REG_WRITE_FUNC_(icc_asgi1r, uint64_t, S3_0_C12_C11_6) DEFINE_REG_WRITE_FUNC_(pan, uint64_t, S3_0_c4_c2_3) DEFINE_REG_READ_FUNC_(pan, uint64_t, S3_0_c4_c2_3) static inline void write_pan_enable(void) { /* msr pan, #1 */ asm volatile("msr S0_0_c4_c1_4, xzr" ::: "memory" ); } static inline void write_pan_disable(void) { /* msr pan, #0 */ asm volatile("msr S0_0_c4_c0_4, xzr" ::: "memory" ); } #endif /*__ASSEMBLER__*/ #endif /*__ARM64_H*/ optee_os-4.3.0/core/arch/arm/include/arm64_macros.S000066400000000000000000000104331464416617300220400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ .altmacro /* * This helper macro concatenates instr_prefix, instr_suffix, to * create a ldp/stp instruction. It also selects register name x/w * based on reg_bytes. */ .macro __do_dregs instr_prefix, instr_suffix, reg_bytes, base_reg, \ base_offs, reg0, reg1 .if \reg_bytes == 8 \instr_prefix\instr_suffix \ x\reg0, x\reg1, [\base_reg, #\base_offs] .else \instr_prefix\instr_suffix \ w\reg0, w\reg1, [\base_reg, #\base_offs] .endif .endm /* * This helper macro concatenates instr_prefix, instr_suffix, to * create a ldr/str instruction. It also selects register name x/w * based on reg_bytes. */ .macro __do_reg instr_prefix, instr_suffix, reg_bytes, base_reg, \ base_offs, reg .if \reg_bytes == 8 \instr_prefix\instr_suffix \ x\reg, [\base_reg, #\base_offs] .else \instr_prefix\instr_suffix \ w\reg, [\base_reg, #\base_offs] .endif .endm /* * This helper macro uses recursion to create a loop which will * start with generating instructions for register pairs and if * it's an odd number of registers end with a single load/store. */ .macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \ from_regnum, to_regnum .if (\to_regnum - \from_regnum + 1) >= 2 __do_dregs \instr_prefix, p, \reg_bytes, \base_reg, \ \base_offs, \from_regnum, %(\from_regnum + 1) .else __do_reg \instr_prefix, r, \reg_bytes, \base_reg, \ \base_offs, \from_regnum .endif .if (\to_regnum - \from_regnum + 1) > 2 _do_regs \instr_prefix, \reg_bytes, \base_reg, \ %(\base_offs + 2 * \reg_bytes), \ %(\from_regnum + 2), \to_regnum .endif .endm /* * Stores registers x[from_regnum]..x[to_regnum] at * [base_reg, #base_offs] */ .macro store_xregs base_reg, base_offs, from_regnum, to_regnum _do_regs st 8 \base_reg, \base_offs, \from_regnum, \to_regnum .endm /* * Stores registers w[from_regnum]..w[to_regnum] at * [base_reg, #base_offs] */ .macro store_wregs base_reg, base_offs, from_regnum, to_regnum _do_regs st 4 \base_reg, \base_offs, \from_regnum, \to_regnum .endm /* * Loads registers x[from_regnum]..x[to_regnum] at * [base_reg, #base_offs] */ .macro load_xregs base_reg, base_offs, from_regnum, to_regnum _do_regs ld 8 \base_reg, \base_offs, \from_regnum, \to_regnum .endm /* * Loads registers w[from_regnum]..w[to_regnum] at * [base_reg, #base_offs] */ .macro load_wregs base_reg, base_offs, from_regnum, to_regnum _do_regs ld 4 \base_reg, \base_offs, \from_regnum, \to_regnum .endm /* Push register pair on stack */ .macro push, r1, r2 stp \r1, \r2, [sp, #-16]! .endm /* Pop register pair from stack */ .macro pop, r1, r2 ldp \r1, \r2, [sp], #16 .endm .macro mov_imm _reg, _val .if (((\_val) >> 31) == 0 || ((\_val) >> 31) == 0x1ffffffff) movz \_reg, :abs_g1_s:\_val .else .if (((\_val) >> 47) == 0 || ((\_val) >> 47) == 0x1ffff) movz \_reg, :abs_g2_s:\_val .else movz \_reg, :abs_g3:\_val movk \_reg, :abs_g2_nc:\_val .endif movk \_reg, :abs_g1_nc:\_val .endif movk \_reg, :abs_g0_nc:\_val .endm .macro add_imm _reg, _val .if ((\_val) > 0xfff) add \_reg, \_reg, ((\_val) >> 12), LSL #12 .endif .if (((\_val) & 0xfff) > 0) add \_reg, \_reg, ((\_val) & 0xfff) .endif .endm .macro sub_imm _reg, _val .if ((\_val) > 0xfff) sub \_reg, \_reg, ((\_val) >> 12), LSL #12 .endif .if (((\_val) & 0xfff) > 0) sub \_reg, \_reg, ((\_val) & 0xfff) .endif .endm /* * Load address of into , being in the range * +/- 4GB of the PC (note that 'adr reg, sym' is limited to +/- 1MB). */ .macro adr_l reg, sym adrp \reg, \sym add \reg, \reg, :lo12:\sym .endm .macro panic_at_smc_return #if defined(CFG_TEE_CORE_DEBUG) bl __panic_at_smc_return #else b . #endif .endm .macro read_apiakeylo reg mrs \reg, S3_0_c2_c1_0 .endm .macro read_apiakeyhi reg mrs \reg, S3_0_c2_c1_1 .endm .macro write_apiakeylo reg msr S3_0_c2_c1_0, \reg .endm .macro write_apiakeyhi reg msr S3_0_c2_c1_1, \reg .endm .macro write_pan reg /* msr pan, \reg */ msr S3_0_c4_c2_3, \reg .endm .macro write_pan_enable /* msr pan, #1 */ msr S0_0_c4_c1_4, xzr .endm .macro write_pan_disable /* msr pan, #0 */ msr S0_0_c4_c0_4, xzr .endm optee_os-4.3.0/core/arch/arm/include/crypto/000077500000000000000000000000001464416617300207365ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/crypto/ghash-ce-core.h000066400000000000000000000023601464416617300235150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef __CRYPTO_GHASH_CE_CORE_H #define __CRYPTO_GHASH_CE_CORE_H #include struct internal_ghash_key { uint64_t h[2]; uint64_t h2[2]; uint64_t h3[2]; uint64_t h4[2]; }; void pmull_ghash_update_p64(int blocks, uint64_t dg[2], const uint8_t *src, const struct internal_ghash_key *ghash_key, const uint8_t *head); void pmull_ghash_update_p8(int blocks, uint64_t dg[2], const uint8_t *src, const struct internal_ghash_key *ghash_key, const uint8_t *head); void pmull_gcm_load_round_keys(const uint64_t rk[30], int rounds); void pmull_gcm_encrypt(int blocks, uint64_t dg[2], uint8_t dst[], const uint8_t src[], const struct internal_ghash_key *ghash_key, uint64_t ctr[], const uint64_t rk[], int rounds, uint8_t ks[]); void pmull_gcm_decrypt(int blocks, uint64_t dg[2], uint8_t dst[], const uint8_t src[], const struct internal_ghash_key *ghash_key, uint64_t ctr[], const uint64_t rk[], int rounds); uint32_t pmull_gcm_aes_sub(uint32_t input); void pmull_gcm_encrypt_block(uint8_t dst[], const uint8_t src[], int rounds); #endif /*__CRYPTO_GHASH_CE_CORE_H*/ optee_os-4.3.0/core/arch/arm/include/ffa.h000066400000000000000000000267271464416617300203410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2020, Linaro Limited * Copyright (c) 2018-2024, Arm Limited. All rights reserved. */ #ifndef __FFA_H #define __FFA_H /* This is based on the FF-A 1.0 EAC specification */ #include #include #include /* Error codes */ #define FFA_OK 0 #define FFA_NOT_SUPPORTED -1 #define FFA_INVALID_PARAMETERS -2 #define FFA_NO_MEMORY -3 #define FFA_BUSY -4 #define FFA_INTERRUPTED -5 #define FFA_DENIED -6 #define FFA_RETRY -7 #define FFA_ABORTED -8 #define FFA_NO_DATA -9 /* FFA_VERSION helpers */ #define FFA_VERSION_MAJOR U(1) #define FFA_VERSION_MAJOR_SHIFT U(16) #define FFA_VERSION_MAJOR_MASK U(0x7FFF) #define FFA_VERSION_MINOR U(1) #define FFA_VERSION_MINOR_SHIFT U(0) #define FFA_VERSION_MINOR_MASK U(0xFFFF) #define MAKE_FFA_VERSION(major, minor) \ ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \ ((minor) & FFA_VERSION_MINOR_MASK)) #define FFA_VERSION_1_0 MAKE_FFA_VERSION(1, 0) #define FFA_VERSION_1_1 MAKE_FFA_VERSION(1, 1) /* Function IDs */ #define FFA_ERROR U(0x84000060) #define FFA_SUCCESS_32 U(0x84000061) #define FFA_SUCCESS_64 U(0xC4000061) #define FFA_INTERRUPT U(0x84000062) #define FFA_VERSION U(0x84000063) #define FFA_FEATURES U(0x84000064) #define FFA_RX_RELEASE U(0x84000065) #define FFA_RXTX_MAP_32 U(0x84000066) #define FFA_RXTX_MAP_64 U(0xC4000066) #define FFA_RXTX_UNMAP U(0x84000067) #define FFA_PARTITION_INFO_GET U(0x84000068) #define FFA_ID_GET U(0x84000069) #define FFA_SPM_ID_GET U(0x84000085) #define FFA_MSG_WAIT U(0x8400006B) #define FFA_MSG_YIELD U(0x8400006C) #define FFA_RUN U(0x8400006D) #define FFA_MSG_SEND2 U(0x84000086) #define FFA_MSG_SEND U(0x8400006E) #define FFA_MSG_SEND_DIRECT_REQ_32 U(0x8400006F) #define FFA_MSG_SEND_DIRECT_REQ_64 U(0xC400006F) #define FFA_MSG_SEND_DIRECT_RESP_32 U(0x84000070) #define FFA_MSG_SEND_DIRECT_RESP_64 U(0xC4000070) #define FFA_MSG_POLL U(0x8400006A) #define FFA_MEM_DONATE_32 U(0x84000071) #define FFA_MEM_DONATE_64 U(0xC4000071) #define FFA_MEM_LEND_32 U(0x84000072) #define FFA_MEM_LEND_64 U(0xC4000072) #define FFA_MEM_SHARE_32 U(0x84000073) #define FFA_MEM_SHARE_64 U(0xC4000073) #define FFA_MEM_RETRIEVE_REQ_32 U(0x84000074) #define FFA_MEM_RETRIEVE_REQ_64 U(0xC4000074) #define FFA_MEM_RETRIEVE_RESP U(0x84000075) #define FFA_MEM_RELINQUISH U(0x84000076) #define FFA_MEM_RECLAIM U(0x84000077) #define FFA_MEM_FRAG_RX U(0x8400007A) #define FFA_MEM_FRAG_TX U(0x8400007B) #define FFA_NORMAL_WORLD_RESUME U(0x8400007C) #define FFA_NOTIFICATION_BITMAP_CREATE U(0x8400007D) #define FFA_NOTIFICATION_BITMAP_DESTROY U(0x8400007E) #define FFA_NOTIFICATION_BIND U(0x8400007F) #define FFA_NOTIFICATION_UNBIND U(0x84000080) #define FFA_NOTIFICATION_SET U(0x84000081) #define FFA_NOTIFICATION_GET U(0x84000082) #define FFA_NOTIFICATION_INFO_GET_32 U(0x84000083) #define FFA_NOTIFICATION_INFO_GET_64 U(0xC4000083) #define FFA_SECONDARY_EP_REGISTER_64 U(0xC4000087) #define FFA_MEM_PERM_GET_32 U(0x84000088) #define FFA_MEM_PERM_GET_64 U(0xC4000088) #define FFA_MEM_PERM_SET_32 U(0x84000089) #define FFA_MEM_PERM_SET_64 U(0xC4000089) #define FFA_CONSOLE_LOG_32 U(0x8400008A) #define FFA_CONSOLE_LOG_64 U(0xC400008A) #define FFA_FEATURES_FUNC_ID_MASK BIT32(31) #define FFA_FEATURES_FEATURE_ID_MASK GENMASK_32(7, 0) /* Flags used in calls to FFA_NOTIFICATION_GET interface */ #define FFA_NOTIF_FLAG_BITMAP_SP BIT(0) #define FFA_NOTIF_FLAG_BITMAP_VM BIT(1) #define FFA_NOTIF_FLAG_BITMAP_SPM BIT(2) #define FFA_NOTIF_FLAG_BITMAP_HYP BIT(3) /* Flags used in calls to FFA_NOTIFICATION_INFO_GET interface */ #define FFA_NOTIF_INFO_GET_MORE_FLAG BIT(0) #define FFA_NOTIF_INFO_GET_ID_LIST_SHIFT 12 #define FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT 7 #define FFA_NOTIF_INFO_GET_ID_COUNT_MASK 0x1F /* Feature IDs used with FFA_FEATURES */ #define FFA_FEATURE_NOTIF_PEND_INTR U(0x1) #define FFA_FEATURE_SCHEDULE_RECV_INTR U(0x2) #define FFA_FEATURE_MANAGED_EXIT_INTR U(0x3) /* Special value for traffic targeted to the Hypervisor or SPM */ #define FFA_TARGET_INFO_MBZ U(0x0) #define FFA_MSG_FLAG_FRAMEWORK BIT(31) #define FFA_MSG_TYPE_MASK GENMASK_32(7, 0) #define FFA_MSG_PSCI U(0x0) #define FFA_MSG_SEND_VM_CREATED U(0x4) #define FFA_MSG_RESP_VM_CREATED U(0x5) #define FFA_MSG_SEND_VM_DESTROYED U(0x6) #define FFA_MSG_RESP_VM_DESTROYED U(0x7) #define FFA_MSG_VERSION_REQ U(0x8) #define FFA_MSG_VERSION_RESP U(0x9) /* * Flag used as parameter to FFA_PARTITION_INFO_GET to return partition * count only. */ #define FFA_PARTITION_INFO_GET_COUNT_FLAG BIT(0) /* Memory attributes: Normal memory, Write-Back cacheable, Inner shareable */ #define FFA_NORMAL_MEM_REG_ATTR U(0x2f) /* Memory access permissions: Read-write */ #define FFA_MEM_ACC_RW BIT(1) /* Memory access permissions: executable */ #define FFA_MEM_ACC_EXE BIT(3) /* Memory access permissions mask */ #define FFA_MEM_ACC_MASK 0xf /* Clear memory before mapping in receiver */ #define FFA_MEMORY_REGION_FLAG_CLEAR BIT(0) /* Relayer may time slice this operation */ #define FFA_MEMORY_REGION_FLAG_TIME_SLICE BIT(1) /* Clear memory after receiver relinquishes it */ #define FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH BIT(2) /* Share memory transaction */ #define FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE SHIFT_U32(1, 3) /* Relayer must choose the alignment boundary */ #define FFA_MEMORY_REGION_FLAG_ANY_ALIGNMENT 0 #define FFA_MEM_PERM_DATA_PERM GENMASK_32(1, 0) #define FFA_MEM_PERM_RW U(0x1) #define FFA_MEM_PERM_RO U(0x3) #define FFA_MEM_PERM_INSTRUCTION_PERM BIT(2) #define FFA_MEM_PERM_NX BIT(2) #define FFA_MEM_PERM_X U(0) #define FFA_MEM_PERM_RESERVED GENMASK_32(31, 3) /* Special value for MBZ parameters */ #define FFA_PARAM_MBZ U(0x0) /* * The W1 register in FFA_INTERRUPT and FFA_RUN interfaces contains the target * information. This value has two parts, the SP ID and vCPU ID. The SP ID * identifies the SP to resume and the vCPU ID identifies the vCPU or execution * context to resume (FF-A v1.1 section 4.8). */ #define FFA_TARGET_INFO_SET(sp_id, vcpu_id) (((sp_id) << 16) | (vcpu_id)) #define FFA_TARGET_INFO_GET_SP_ID(info) (((info) >> 16) & 0xffff) #define FFA_TARGET_INFO_GET_VCPU_ID(info) ((info) & 0xffff) /* * Flags used for the FFA_PARTITION_INFO_GET return message: * BIT(0): Supports receipt of direct requests * BIT(1): Can send direct requests * BIT(2): Can send and receive indirect messages * BIT(3): Supports receipt of notifications * BIT(4-5): Partition ID is a PE endpoint ID */ #define FFA_PART_PROP_DIRECT_REQ_RECV BIT(0) #define FFA_PART_PROP_DIRECT_REQ_SEND BIT(1) #define FFA_PART_PROP_INDIRECT_MSGS BIT(2) #define FFA_PART_PROP_RECV_NOTIF BIT(3) #define FFA_PART_PROP_IS_PE_ID SHIFT_U32(0, 4) #define FFA_PART_PROP_IS_SEPID_INDEP SHIFT_U32(1, 4) #define FFA_PART_PROP_IS_SEPID_DEP SHIFT_U32(2, 4) #define FFA_PART_PROP_IS_AUX_ID SHIFT_U32(3, 4) #define FFA_PART_PROP_NOTIF_CREATED BIT(6) #define FFA_PART_PROP_NOTIF_DESTROYED BIT(7) #define FFA_PART_PROP_AARCH64_STATE BIT(8) #define FFA_MEMORY_HANDLE_HYPERVISOR_BIT BIT64(63) #define FFA_MEMORY_HANDLE_SECURE_BIT BIT64(45) #define FFA_MEMORY_HANDLE_NON_SECURE_BIT BIT64(44) /* * Codes the OP-TEE partition/guest ID into a cookie in order to know which * partition to activate when reclaiming the shared memory. This field is 0 * unless CFG_NS_VIRTUALIZATION is enabled. */ #define FFA_MEMORY_HANDLE_PRTN_SHIFT 16 #define FFA_MEMORY_HANDLE_PRTN_MASK GENMASK_32(16, 0) #define FFA_BOOT_INFO_NAME_LEN U(16) /* Boot Info descriptors type */ #define FFA_BOOT_INFO_TYPE_IMDEF BIT(7) #define FFA_BOOT_INFO_TYPE_ID_MASK GENMASK_32(6, 0) #define FFA_BOOT_INFO_TYPE_ID_FDT U(0) #define FFA_BOOT_INFO_TYPE_ID_HOB U(1) /* Boot Info descriptors flags */ #define FFA_BOOT_INFO_FLAG_NAME_FORMAT_MASK GENMASK_32(1, 0) #define FFA_BOOT_INFO_FLAG_NAME_FORMAT_STRING U(0) #define FFA_BOOT_INFO_FLAG_NAME_FORMAT_UUID U(1) /** Bits [3:2] encode the format of the content field in ffa_boot_info_desc. */ #define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT U(2) #define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_MASK GENMASK_32(3, 2) #define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_VALUE U(1) #define FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR U(0) #define FFA_BOOT_INFO_SIGNATURE U(0xFFA) #define FFA_BOOT_INFO_VERSION U(0x10001) #define FFA_CONSOLE_LOG_CHAR_COUNT_MASK GENMASK_32(7, 0) #define FFA_CONSOLE_LOG_32_MAX_MSG_LEN U(24) #define FFA_CONSOLE_LOG_64_MAX_MSG_LEN U(48) /* Memory transaction type in FFA_MEM_RETRIEVE_RESP flags */ #define FFA_MEMORY_TRANSACTION_TYPE_MASK GENMASK_32(4, 3) #define FFA_MEMORY_TRANSACTION_TYPE_SHARE SHIFT_U32(1, 3) #define FFA_MEMORY_TRANSACTION_TYPE_LEND SHIFT_U32(2, 3) #define FFA_MEMORY_TRANSACTION_TYPE_DONATE SHIFT_U32(3, 3) #ifndef __ASSEMBLER__ /* Constituent memory region descriptor */ struct ffa_address_range { uint64_t address; uint32_t page_count; uint32_t reserved; }; /* Composite memory region descriptor */ struct ffa_mem_region { uint32_t total_page_count; uint32_t address_range_count; uint64_t reserved; struct ffa_address_range address_range_array[]; }; /* Memory access permissions descriptor */ struct ffa_mem_access_perm { uint16_t endpoint_id; uint8_t perm; uint8_t flags; }; /* Endpoint memory access descriptor */ struct ffa_mem_access { struct ffa_mem_access_perm access_perm; uint32_t region_offs; uint64_t reserved; }; /* Lend, donate or share memory transaction descriptor */ struct ffa_mem_transaction_1_0 { uint16_t sender_id; uint8_t mem_reg_attr; uint8_t reserved0; uint32_t flags; uint64_t global_handle; uint64_t tag; uint32_t reserved1; uint32_t mem_access_count; struct ffa_mem_access mem_access_array[]; }; struct ffa_mem_transaction_1_1 { uint16_t sender_id; uint16_t mem_reg_attr; uint32_t flags; uint64_t global_handle; uint64_t tag; uint32_t mem_access_size; uint32_t mem_access_count; uint32_t mem_access_offs; uint8_t reserved[12]; }; /* * The parts needed from struct ffa_mem_transaction_1_0 or struct * ffa_mem_transaction_1_1, used to provide an abstraction of difference in * data structures between version 1.0 and 1.1. This is just an internal * interface and can be changed without changing any ABI. */ struct ffa_mem_transaction_x { uint16_t sender_id; uint8_t mem_reg_attr; uint8_t flags; uint8_t mem_access_size; uint8_t mem_access_count; uint16_t mem_access_offs; uint64_t global_handle; uint64_t tag; }; #define FFA_UUID_SIZE 16 /* Partition information descriptor */ struct ffa_partition_info_x { uint16_t id; uint16_t execution_context; uint32_t partition_properties; /* * The uuid field is absent in FF-A 1.0, and an array of 16 * (FFA_UUID_SIZE) from FF-A 1.1 */ uint8_t uuid[]; }; /* Descriptor to relinquish a memory region (FFA_MEM_RELINQUISH) */ struct ffa_mem_relinquish { uint64_t handle; uint32_t flags; uint32_t endpoint_count; uint16_t endpoint_id_array[]; }; /* FF-A v1.0 boot information name-value pairs */ struct ffa_boot_info_nvp_1_0 { uint32_t name[4]; uint64_t value; uint64_t size; }; /* FF-A v1.0 boot information descriptor */ struct ffa_boot_info_1_0 { uint32_t magic; uint32_t count; struct ffa_boot_info_nvp_1_0 nvp[]; }; /* FF-A v1.1 boot information descriptor */ struct ffa_boot_info_1_1 { char name[FFA_BOOT_INFO_NAME_LEN]; uint8_t type; uint8_t reserved; uint16_t flags; uint32_t size; uint64_t contents; }; /* FF-A v1.1 boot information header */ struct ffa_boot_info_header_1_1 { uint32_t signature; uint32_t version; uint32_t blob_size; uint32_t desc_size; uint32_t desc_count; uint32_t desc_offset; uint64_t reserved; }; #endif /*__ASSEMBLER__*/ #endif /* __FFA_H */ optee_os-4.3.0/core/arch/arm/include/kernel/000077500000000000000000000000001464416617300206765ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/kernel/arch_scall.h000066400000000000000000000021161464416617300231420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2022, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef __KERNEL_ARCH_SCALL_H #define __KERNEL_ARCH_SCALL_H #include #include #include static inline void scall_get_max_args(struct thread_scall_regs *regs, size_t *scn, size_t *max_args) { #ifdef ARM32 *scn = regs->r7; *max_args = regs->r6; #endif #ifdef ARM64 if (((regs->spsr >> SPSR_MODE_RW_SHIFT) & SPSR_MODE_RW_MASK) == SPSR_MODE_RW_32) { *scn = regs->x7; *max_args = regs->x6; } else { *scn = regs->x8; *max_args = 0; } #endif } static inline void scall_set_retval(struct thread_scall_regs *regs, uint32_t ret_val) { #ifdef ARM32 regs->r0 = ret_val; #endif #ifdef ARM64 regs->x0 = ret_val; #endif } static inline void scall_set_sys_return_regs(struct thread_scall_regs *regs, bool panic, uint32_t panic_code) { #ifdef ARM32 regs->r1 = panic; regs->r2 = panic_code; #endif #ifdef ARM64 regs->x1 = panic; regs->x2 = panic_code; #endif } #endif /*__KERNEL_ARCH_SCALL_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/cache_helpers_arch.h000066400000000000000000000007621464416617300246360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __KERNEL_CACHE_HELPERS_ARCH_H #define __KERNEL_CACHE_HELPERS_ARCH_H #ifndef __ASSEMBLER__ #include #include #endif #ifndef __ASSEMBLER__ static inline unsigned int dcache_get_line_size(void) { uint32_t value = read_ctr(); return CTR_WORD_SIZE << ((value >> CTR_DMINLINE_SHIFT) & CTR_DMINLINE_MASK); } #endif /*!__ASSEMBLER__*/ #endif /*__KERNEL_CACHE_HELPERS_ARCH_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/delay_arch.h000066400000000000000000000034301464416617300231420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __KERNEL_DELAY_ARCH_H #define __KERNEL_DELAY_ARCH_H #ifdef CFG_CORE_HAS_GENERIC_TIMER #include #include static inline unsigned int delay_cnt_freq(void) { return read_cntfrq(); } static inline uint64_t delay_cnt_read(void) { return barrier_read_counter_timer(); } #endif /* CFG_CORE_HAS_GENERIC_TIMER */ #endif optee_os-4.3.0/core/arch/arm/include/kernel/misc_arch.h000066400000000000000000000006601464416617300230010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_MISC_ARCH_H #define __KERNEL_MISC_ARCH_H #include #include #include size_t get_core_pos_mpidr(uint32_t mpidr); uint32_t read_mode_sp(int cpu_mode); uint32_t read_mode_lr(int cpu_mode); void wait_cycles(unsigned long cycles); #endif /*__KERNEL_MISC_ARCH_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/secure_partition.h000066400000000000000000000046631464416617300244370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020-2023, Arm Limited. */ #ifndef __KERNEL_SECURE_PARTITION_H #define __KERNEL_SECURE_PARTITION_H #include #include #include #include #include #include #include #include #include #include TAILQ_HEAD(sp_sessions_head, sp_session); enum sp_status { sp_idle, sp_busy, sp_preempted, sp_dead }; struct sp_session { struct ffa_rxtx rxtx; enum sp_status state; uint16_t endpoint_id; uint16_t caller_id; uint32_t boot_order; struct ts_session ts_sess; unsigned int spinlock; const void *fdt; bool is_initialized; TEE_UUID ffa_uuid; uint32_t ns_int_mode; uint32_t ns_int_mode_inherited; TAILQ_ENTRY(sp_session) link; }; struct sp_ctx { struct thread_ctx_regs sp_regs; struct sp_session *open_session; struct user_mode_ctx uctx; struct ts_ctx ts_ctx; }; struct sp_image { struct embedded_ts image; const void *fdt; }; #ifdef CFG_SECURE_PARTITION bool is_sp_ctx(struct ts_ctx *ctx); #else static inline bool is_sp_ctx(struct ts_ctx *ctx __unused) { return false; } #endif static inline struct sp_session *__noprof to_sp_session(struct ts_session *sess) { assert(is_sp_ctx(sess->ctx)); return container_of(sess, struct sp_session, ts_sess); } static inline struct sp_ctx *to_sp_ctx(struct ts_ctx *ctx) { assert(is_sp_ctx(ctx)); return container_of(ctx, struct sp_ctx, ts_ctx); } struct sp_session *sp_get_session(uint32_t session_id); TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp); TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size, const TEE_UUID *ffa_uuid, size_t *elem_count, bool count_only); bool sp_has_exclusive_access(struct sp_mem_map_region *mem, struct user_mode_ctx *uctx); TEE_Result sp_map_shared(struct sp_session *s, struct sp_mem_receiver *receiver, struct sp_mem *mem, uint64_t *va); TEE_Result sp_unmap_ffa_regions(struct sp_session *s, struct sp_mem *smem); #define for_each_secure_partition(_sp) \ SCATTERED_ARRAY_FOREACH(_sp, sp_images, struct sp_image) struct fip_sp { struct sp_image sp_img; STAILQ_ENTRY(fip_sp) link; }; STAILQ_HEAD(fip_sp_head, fip_sp); extern struct fip_sp_head fip_sp_list; #define for_each_fip_sp(_sp) \ STAILQ_FOREACH(_sp, &fip_sp_list, link) #endif /* __KERNEL_SECURE_PARTITION_H */ optee_os-4.3.0/core/arch/arm/include/kernel/spmc_sp_handler.h000066400000000000000000000031631464416617300242130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Arm Limited. */ #ifndef __KERNEL_SPMC_SP_HANDLER_H #define __KERNEL_SPMC_SP_HANDLER_H #include #include #include #include #include #define FFA_DST(x) ((x) & UINT16_MAX) #define FFA_SRC(x) (((x) >> 16) & UINT16_MAX) void spmc_sp_thread_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); void spmc_sp_msg_handler(struct thread_smc_args *args, struct sp_session *caller_sp); bool ffa_mem_reclaim(struct thread_smc_args *args, struct sp_session *caller_sp); #ifdef CFG_SECURE_PARTITION void spmc_sp_start_thread(struct thread_smc_args *args); int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans, struct ffa_rxtx *rxtx, size_t blen, size_t flen, uint64_t *global_handle, struct sp_session *owner_sp); void spmc_sp_set_to_preempted(struct ts_session *ts_sess); int spmc_sp_resume_from_preempted(uint16_t endpoint_id); #else static inline void spmc_sp_start_thread(struct thread_smc_args *args __unused) { } static inline int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans __unused, struct ffa_rxtx *rxtx __unused, size_t blen __unused, size_t flen __unused, uint64_t *global_handle __unused, struct sp_session *owner_sp __unused) { return FFA_NOT_SUPPORTED; } static inline void spmc_sp_set_to_preempted(struct ts_session *ts_sess __unused) { } static inline int spmc_sp_resume_from_preempted(uint16_t endpoint_id __unused) { return FFA_NOT_SUPPORTED; } #endif #endif /* __KERNEL_SPMC_SP_HANDLER_H */ optee_os-4.3.0/core/arch/arm/include/kernel/stmm_sp.h000066400000000000000000000130101464416617300225240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2020, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #ifndef __KERNEL_STMM_SP_H #define __KERNEL_STMM_SP_H #include #include #include #include #include #include #include #define STMM_RET_SUCCESS 0 #define STMM_RET_NOT_SUPPORTED -1 #define STMM_RET_INVALID_PARAM -2 #define STMM_RET_DENIED -3 #define STMM_RET_NO_MEM -5 #define STMM_MEM_ATTR_ACCESS_MASK U(0x3) #define STMM_MEM_ATTR_ACCESS_NONE U(0) #define STMM_MEM_ATTR_ACCESS_RW U(1) #define STMM_MEM_ATTR_ACCESS_RO U(3) #define STMM_MEM_ATTR_EXEC_NEVER BIT(2) #define STMM_MEM_ATTR_EXEC U(0) #define STMM_MEM_ATTR_ALL (STMM_MEM_ATTR_ACCESS_RW | \ STMM_MEM_ATTR_ACCESS_RO | \ STMM_MEM_ATTR_EXEC_NEVER) /* * Used for EDK2 StMM communication. Since StMM can be launched on an arbitrary * address it uses these 2 syscalls to define the memory attributes for the * data and code segments after dispatching the binaries. * * FFA_SVC_MEMORY_ATTRIBUTES_SET_64/FFA_SVC_MEMORY_ATTRIBUTES_SET_32: * - x4: base address * - x5: number of pages * - x6: attributes of the remapping (described above) * * FFA_SVC_MEMORY_ATTRIBUTES_GET_32/FFA_SVC_MEMORY_ATTRIBUTES_GET_64: * - x4: base address, currently only a single page is requested. */ #define FFA_SVC_MEMORY_ATTRIBUTES_GET_64 UINT32_C(0xC4000064) #define FFA_SVC_MEMORY_ATTRIBUTES_SET_64 UINT32_C(0xC4000065) #define FFA_SVC_MEMORY_ATTRIBUTES_GET_32 UINT32_C(0x84000064) #define FFA_SVC_MEMORY_ATTRIBUTES_SET_32 UINT32_C(0x84000065) /* * We need to define the RPMB IDs formally, since the plan is * for them to be included in the FFA spec (for SP-to-SP future communication). * This is fine for now as it represents the internal contract between the * EDK2 RPMB driver and Secure Partition * * FFA_SVC_RPMB_WRITE/FFA_SVC_RPMB_WRITE_32: * - x4: virtual address of the buffer to write in the device * - x5: buffer byte length * - x6: byte offset in the device * FFA_SVC_RPMB_READ/FFA_SVC_RPMB_READ_32: * - x4: virtual address of the buffer were RPMB contents are copied * - x5: buffer byte length to read * - x6: byte offset in the device */ #define FFA_SVC_RPMB_READ UINT32_C(0xC4000066) #define FFA_SVC_RPMB_WRITE UINT32_C(0xC4000067) #define FFA_SVC_RPMB_READ_32 UINT32_C(0x84000066) #define FFA_SVC_RPMB_WRITE_32 UINT32_C(0x84000067) /* Param header types */ #define STMM_PARAM_EP UINT8_C(0x01) #define STMM_PARAM_IMAGE_BINARY UINT8_C(0x02) #define STMM_PARAM_BL31 UINT8_C(0x03) #define STMM_PARAM_BL_LOAD_INFO UINT8_C(0x04) #define STMM_PARAM_BL_PARAMS UINT8_C(0x05) #define STMM_PARAM_PSCI_LIB_ARGS UINT8_C(0x06) #define STMM_PARAM_SP_IMAGE_BOOT_INFO UINT8_C(0x07) /* Param header version */ #define STMM_PARAM_VERSION_1 UINT8_C(0x01) #define STMM_PARAM_VERSION_2 UINT8_C(0x02) /* * This structure provides information on format used to describe * secure partition invocation parameters. */ struct stmm_param_header { uint8_t type; /* type of the structure */ uint8_t version; /* version of this structure */ uint16_t size; /* size of this structure in bytes */ uint32_t attr; /* attributes: unused bits SBZ */ }; /* * Flags used by the stmm_mp_info structure to describe the * characteristics of a cpu. Only a single flag is defined at the moment to * indicate the primary cpu. */ #define MP_INFO_FLAG_PRIMARY_CPU UINT32_C(0x00000001) /* * This structure is used to provide information required to initialise a S-EL0 * partition. */ struct stmm_mp_info { uint64_t mpidr; uint32_t linear_id; uint32_t flags; }; struct stmm_boot_info { struct stmm_param_header h; uint64_t sp_mem_base; uint64_t sp_mem_limit; uint64_t sp_image_base; uint64_t sp_stack_base; uint64_t sp_heap_base; uint64_t sp_ns_comm_buf_base; uint64_t sp_shared_buf_base; uint64_t sp_image_size; uint64_t sp_pcpu_stack_size; uint64_t sp_heap_size; uint64_t sp_ns_comm_buf_size; uint64_t sp_shared_buf_size; uint32_t num_sp_mem_regions; uint32_t num_cpus; struct stmm_mp_info *mp_info; }; struct stmm_ctx { struct user_mode_ctx uctx; struct tee_ta_ctx ta_ctx; struct thread_ctx_regs regs; vaddr_t ns_comm_buf_addr; unsigned int ns_comm_buf_size; }; extern const struct ts_ops stmm_sp_ops; static inline bool is_stmm_ctx(struct ts_ctx *ctx __maybe_unused) { return IS_ENABLED(CFG_WITH_STMM_SP) && ctx && ctx->ops == &stmm_sp_ops; } static inline struct stmm_ctx *to_stmm_ctx(struct ts_ctx *ctx) { assert(is_stmm_ctx(ctx)); return container_of(ctx, struct stmm_ctx, ta_ctx.ts_ctx); } #ifdef CFG_WITH_STMM_SP /* * Setup session context for the StMM application * @uuid: TA UUID * @sess: Session for which to setup the StMM context * * This function must be called with tee_ta_mutex locked. */ TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *s); /* * Finalize session context initialization the StMM application * @sess: Session for which to finalize StMM context */ TEE_Result stmm_complete_session(struct tee_ta_session *s); #else static inline TEE_Result stmm_init_session(const TEE_UUID *uuid __unused, struct tee_ta_session *s __unused) { return TEE_ERROR_ITEM_NOT_FOUND; } static inline TEE_Result stmm_complete_session(struct tee_ta_session *s __unused) { return TEE_ERROR_GENERIC; } #endif #ifdef CFG_WITH_STMM_SP const TEE_UUID *stmm_get_uuid(void); #else static inline const TEE_UUID *stmm_get_uuid(void) { return NULL; } #endif #endif /*__KERNEL_STMM_SP_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/tee_l2cc_mutex.h000066400000000000000000000024571464416617300237610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TEE_L2CC_MUTEX_H #define __KERNEL_TEE_L2CC_MUTEX_H #include #include #include #include #if defined(CFG_PL310) TEE_Result tee_enable_l2cc_mutex(void); TEE_Result tee_disable_l2cc_mutex(void); TEE_Result tee_get_l2cc_mutex(paddr_t *mutex); TEE_Result tee_set_l2cc_mutex(paddr_t *mutex); void tee_l2cc_mutex_lock(void); void tee_l2cc_mutex_unlock(void); /* * Store the pa of a mutex used for l2cc * It is allocated from the boot */ void tee_l2cc_store_mutex_boot_pa(uint32_t pa); #else static TEE_Result tee_enable_l2cc_mutex(void); static TEE_Result tee_disable_l2cc_mutex(void); static TEE_Result tee_get_l2cc_mutex(paddr_t *mutex); static TEE_Result tee_set_l2cc_mutex(paddr_t *mutex); static inline TEE_Result tee_enable_l2cc_mutex(void) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result tee_disable_l2cc_mutex(void) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result tee_get_l2cc_mutex(paddr_t *mutex __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result tee_set_l2cc_mutex(paddr_t *mutex __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif #endif /* __KERNEL_TEE_L2CC_MUTEX_H */ optee_os-4.3.0/core/arch/arm/include/kernel/thread_arch.h000066400000000000000000000257171464416617300233270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2016-2022, Linaro Limited * Copyright (c) 2020-2021, Arm Limited */ #ifndef __KERNEL_THREAD_ARCH_H #define __KERNEL_THREAD_ARCH_H #ifndef __ASSEMBLER__ #include #include #include #include #endif #ifndef __ASSEMBLER__ #ifdef ARM64 /* * struct thread_core_local needs to have alignment suitable for a stack * pointer since SP_EL1 points to this */ #define THREAD_CORE_LOCAL_ALIGNED __aligned(16) #else #define THREAD_CORE_LOCAL_ALIGNED __aligned(8) #endif struct mobj; /* * Storage of keys used for pointer authentication. FEAT_PAuth supports a * number of keys of which only the APIA key is currently used, depending on * configuration. */ struct thread_pauth_keys { uint64_t apia_hi; uint64_t apia_lo; }; struct thread_core_local { #ifdef ARM32 uint32_t r[2]; paddr_t sm_pm_ctx_phys; #endif #ifdef ARM64 uint64_t x[4]; #endif #ifdef CFG_CORE_PAUTH struct thread_pauth_keys keys; #endif vaddr_t tmp_stack_va_end; long kcode_offset; short int curr_thread; uint32_t flags; vaddr_t abt_stack_va_end; #ifdef CFG_TEE_CORE_DEBUG unsigned int locked_count; /* Number of spinlocks held */ #endif #if defined(ARM64) && defined(CFG_CORE_FFA) /* Function ID to use for a direct response, 32-bit vs 64-bit */ uint32_t direct_resp_fid; #endif #if defined(ARM64) && defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) uint8_t bhb_loop_count; #endif #ifdef CFG_CORE_DEBUG_CHECK_STACKS bool stackcheck_recursion; #endif #ifdef CFG_FAULT_MITIGATION struct ftmn_func_arg *ftmn_arg; #endif } THREAD_CORE_LOCAL_ALIGNED; struct thread_vector_table { uint32_t std_smc_entry; uint32_t fast_smc_entry; uint32_t cpu_on_entry; uint32_t cpu_off_entry; uint32_t cpu_resume_entry; uint32_t cpu_suspend_entry; uint32_t fiq_entry; uint32_t system_off_entry; uint32_t system_reset_entry; }; extern struct thread_vector_table thread_vector_table; struct thread_user_vfp_state { struct vfp_state vfp; bool lazy_saved; bool saved; }; #ifdef ARM32 struct thread_smc_args { uint32_t a0; /* SMC function ID */ uint32_t a1; /* Parameter */ uint32_t a2; /* Parameter */ uint32_t a3; /* Thread ID when returning from RPC */ uint32_t a4; /* Not used */ uint32_t a5; /* Not used */ uint32_t a6; /* Not used */ uint32_t a7; /* Hypervisor Client ID */ }; #endif /*ARM32*/ #ifdef ARM64 struct thread_smc_args { uint64_t a0; /* SMC function ID */ uint64_t a1; /* Parameter */ uint64_t a2; /* Parameter */ uint64_t a3; /* Thread ID when returning from RPC */ uint64_t a4; /* Not used */ uint64_t a5; /* Not used */ uint64_t a6; /* Not used */ uint64_t a7; /* Hypervisor Client ID */ }; #endif /*ARM64*/ #ifdef ARM32 struct thread_abort_regs { uint32_t usr_sp; uint32_t usr_lr; uint32_t pad; uint32_t spsr; uint32_t elr; uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r4; uint32_t r5; uint32_t r6; uint32_t r7; uint32_t r8; uint32_t r9; uint32_t r10; uint32_t r11; uint32_t ip; }; #endif /*ARM32*/ #ifdef ARM64 struct thread_abort_regs { uint64_t x0; /* r0_usr */ uint64_t x1; /* r1_usr */ uint64_t x2; /* r2_usr */ uint64_t x3; /* r3_usr */ uint64_t x4; /* r4_usr */ uint64_t x5; /* r5_usr */ uint64_t x6; /* r6_usr */ uint64_t x7; /* r7_usr */ uint64_t x8; /* r8_usr */ uint64_t x9; /* r9_usr */ uint64_t x10; /* r10_usr */ uint64_t x11; /* r11_usr */ uint64_t x12; /* r12_usr */ uint64_t x13; /* r13/sp_usr */ uint64_t x14; /* r14/lr_usr */ uint64_t x15; uint64_t x16; uint64_t x17; uint64_t x18; uint64_t x19; uint64_t x20; uint64_t x21; uint64_t x22; uint64_t x23; uint64_t x24; uint64_t x25; uint64_t x26; uint64_t x27; uint64_t x28; uint64_t x29; uint64_t x30; uint64_t elr; uint64_t spsr; uint64_t sp_el0; #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) uint64_t apiakey_hi; uint64_t apiakey_lo; #endif }; #endif /*ARM64*/ #ifdef ARM32 struct thread_scall_regs { uint32_t spsr; uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r4; uint32_t r5; uint32_t r6; uint32_t r7; uint32_t lr; }; #endif /*ARM32*/ #ifdef ARM64 struct thread_scall_regs { uint64_t elr; uint64_t spsr; uint64_t x0; /* r0_usr */ uint64_t x1; /* r1_usr */ uint64_t x2; /* r2_usr */ uint64_t x3; /* r3_usr */ uint64_t x4; /* r4_usr */ uint64_t x5; /* r5_usr */ uint64_t x6; /* r6_usr */ uint64_t x7; /* r7_usr */ uint64_t x8; /* r8_usr */ uint64_t x9; /* r9_usr */ uint64_t x10; /* r10_usr */ uint64_t x11; /* r11_usr */ uint64_t x12; /* r12_usr */ uint64_t x13; /* r13/sp_usr */ uint64_t x14; /* r14/lr_usr */ uint64_t x30; uint64_t sp_el0; #ifdef CFG_SECURE_PARTITION uint64_t x15; uint64_t x16; uint64_t x17; uint64_t x18; uint64_t x19; uint64_t x20; uint64_t x21; uint64_t x22; uint64_t x23; uint64_t x24; uint64_t x25; uint64_t x26; uint64_t x27; uint64_t x28; uint64_t x29; #endif #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) uint64_t apiakey_hi; uint64_t apiakey_lo; #endif uint64_t pad; } __aligned(16); #endif /*ARM64*/ #ifdef ARM32 struct thread_ctx_regs { uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r4; uint32_t r5; uint32_t r6; uint32_t r7; uint32_t r8; uint32_t r9; uint32_t r10; uint32_t r11; uint32_t r12; uint32_t usr_sp; uint32_t usr_lr; uint32_t svc_spsr; uint32_t svc_sp; uint32_t svc_lr; uint32_t pc; uint32_t cpsr; }; #endif /*ARM32*/ #ifdef ARM64 struct thread_ctx_regs { uint64_t sp; uint64_t pc; uint64_t cpsr; uint64_t x[31]; uint64_t tpidr_el0; #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) uint64_t apiakey_hi; uint64_t apiakey_lo; #endif }; #endif /*ARM64*/ struct user_mode_ctx; #ifdef CFG_WITH_ARM_TRUSTED_FW /* * These five functions have a __weak default implementation which does * nothing. Platforms are expected to override them if needed. */ unsigned long thread_cpu_off_handler(unsigned long a0, unsigned long a1); unsigned long thread_cpu_suspend_handler(unsigned long a0, unsigned long a1); unsigned long thread_cpu_resume_handler(unsigned long a0, unsigned long a1); unsigned long thread_system_off_handler(unsigned long a0, unsigned long a1); unsigned long thread_system_reset_handler(unsigned long a0, unsigned long a1); #endif /*CFG_WITH_ARM_TRUSTED_FW*/ /* * Defines the bits for the exception mask used by the * thread_*_exceptions() functions below. * These definitions are compatible with both ARM32 and ARM64. */ #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) #define THREAD_EXCP_FOREIGN_INTR (ARM32_CPSR_F >> ARM32_CPSR_F_SHIFT) #define THREAD_EXCP_NATIVE_INTR (ARM32_CPSR_I >> ARM32_CPSR_F_SHIFT) #else #define THREAD_EXCP_FOREIGN_INTR (ARM32_CPSR_I >> ARM32_CPSR_F_SHIFT) #define THREAD_EXCP_NATIVE_INTR (ARM32_CPSR_F >> ARM32_CPSR_F_SHIFT) #endif #define THREAD_EXCP_ALL (THREAD_EXCP_FOREIGN_INTR \ | THREAD_EXCP_NATIVE_INTR \ | (ARM32_CPSR_A >> ARM32_CPSR_F_SHIFT)) #ifdef CFG_WITH_VFP /* * thread_kernel_enable_vfp() - Temporarily enables usage of VFP * * Foreign interrupts are masked while VFP is enabled. User space must not be * entered before thread_kernel_disable_vfp() has been called to disable VFP * and restore the foreign interrupt status. * * This function may only be called from an active thread context and may * not be called again before thread_kernel_disable_vfp() has been called. * * VFP state is saved as needed. * * Returns a state variable that should be passed to * thread_kernel_disable_vfp(). */ uint32_t thread_kernel_enable_vfp(void); /* * thread_kernel_disable_vfp() - Disables usage of VFP * @state: state variable returned by thread_kernel_enable_vfp() * * Disables usage of VFP and restores foreign interrupt status after a call to * thread_kernel_enable_vfp(). * * This function may only be called after a call to * thread_kernel_enable_vfp(). */ void thread_kernel_disable_vfp(uint32_t state); /* * thread_kernel_save_vfp() - Saves kernel vfp state if enabled */ void thread_kernel_save_vfp(void); /* * thread_kernel_save_vfp() - Restores kernel vfp state */ void thread_kernel_restore_vfp(void); /* * thread_user_enable_vfp() - Enables vfp for user mode usage * @uvfp: pointer to where to save the vfp state if needed */ void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp); #else /*CFG_WITH_VFP*/ static inline void thread_kernel_save_vfp(void) { } static inline void thread_kernel_restore_vfp(void) { } #endif /*CFG_WITH_VFP*/ /* * thread_user_save_vfp() - Saves the user vfp state if enabled */ #ifdef CFG_WITH_VFP void thread_user_save_vfp(void); #else static inline void thread_user_save_vfp(void) { } #endif /* * thread_user_clear_vfp() - Clears the vfp state * @uctx: pointer to user mode context containing the saved state to clear */ #ifdef CFG_WITH_VFP void thread_user_clear_vfp(struct user_mode_ctx *uctx); #else static inline void thread_user_clear_vfp(struct user_mode_ctx *uctx __unused) { } #endif #ifdef ARM64 /* * thread_get_saved_thread_sp() - Returns the saved sp of current thread * * When switching from the thread stack pointer the value is stored * separately in the current thread context. This function returns this * saved value. * * @returns stack pointer */ vaddr_t thread_get_saved_thread_sp(void); #endif /*ARM64*/ /* * Provides addresses and size of kernel code that must be mapped while in * user mode. */ #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 void thread_get_user_kcode(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz); #else static inline void thread_get_user_kcode(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz) { *mobj = NULL; *offset = 0; *va = 0; *sz = 0; } #endif /* * Provides addresses and size of kernel (rw) data that must be mapped * while in user mode. */ #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \ defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) void thread_get_user_kdata(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz); #else static inline void thread_get_user_kdata(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz) { *mobj = NULL; *offset = 0; *va = 0; *sz = 0; } #endif /* * Disables and empties the prealloc RPC cache one reference at a time. If * all threads are idle this function returns true and a cookie of one shm * object which was removed from the cache. When the cache is empty *cookie * is set to 0 and the cache is disabled else a valid cookie value. If one * thread isn't idle this function returns false. */ bool thread_disable_prealloc_rpc_cache(uint64_t *cookie); /* * Enabled the prealloc RPC cache. If all threads are idle the cache is * enabled and this function returns true. If one thread isn't idle this * function return false. */ bool thread_enable_prealloc_rpc_cache(void); unsigned long thread_hvc(unsigned long func_id, unsigned long a1, unsigned long a2, unsigned long a3); unsigned long thread_smc(unsigned long func_id, unsigned long a1, unsigned long a2, unsigned long a3); void thread_smccc(struct thread_smc_args *arg_res); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_THREAD_ARCH_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/thread_private_arch.h000066400000000000000000000157541464416617300250610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_THREAD_PRIVATE_ARCH_H #define __KERNEL_THREAD_PRIVATE_ARCH_H #ifndef __ASSEMBLER__ #include #include #include #ifdef CFG_WITH_ARM_TRUSTED_FW #define STACK_TMP_OFFS 0 #else #define STACK_TMP_OFFS SM_STACK_TMP_RESERVE_SIZE #endif #ifdef ARM32 #ifdef CFG_CORE_SANITIZE_KADDRESS #define STACK_TMP_SIZE (3072 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) #else #define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) #endif #define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) #if defined(CFG_CORE_SANITIZE_KADDRESS) || defined(__clang__) || \ !defined(CFG_CRYPTO_WITH_CE) #define STACK_ABT_SIZE 3072 #else #define STACK_ABT_SIZE 2048 #endif #endif /*ARM32*/ #ifdef ARM64 #if (defined(__clang__) && !defined(__OPTIMIZE_SIZE__)) || \ defined(CFG_CORE_SANITIZE_KADDRESS) #define STACK_TMP_SIZE (4096 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) #else #define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) #endif #if defined(CFG_CORE_SANITIZE_KADDRESS) #define STACK_THREAD_SIZE (10240 + CFG_STACK_THREAD_EXTRA) #else #define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) #endif #define STACK_ABT_SIZE 3072 #endif /*ARM64*/ #ifdef CFG_CORE_DEBUG_CHECK_STACKS /* * Extra space added to each stack in order to reliably detect and dump stack * overflows. Should cover the maximum expected overflow size caused by any C * function (say, 512 bytes; no function should have that much local variables), * plus the maximum stack space needed by __cyg_profile_func_exit(): about 1 KB, * a large part of which is used to print the call stack. Total: 1.5 KB. */ #define STACK_CHECK_EXTRA 1536 #else #define STACK_CHECK_EXTRA 0 #endif #ifdef ARM64 struct thread_user_mode_rec { uint64_t ctx_regs_ptr; uint64_t exit_status0_ptr; uint64_t exit_status1_ptr; uint64_t pad; uint64_t x[31 - 19]; /* x19..x30 */ }; #endif /*ARM64*/ #ifdef CFG_WITH_VFP struct thread_vfp_state { bool ns_saved; bool sec_saved; bool sec_lazy_saved; struct vfp_state ns; struct vfp_state sec; struct thread_user_vfp_state *uvfp; }; #endif /*CFG_WITH_VFP*/ #endif /*__ASSEMBLER__*/ #ifdef ARM64 #ifdef CFG_WITH_VFP #define THREAD_VFP_STATE_SIZE \ (16 + (16 * 32 + 16) * 2 + 16) #else #define THREAD_VFP_STATE_SIZE 0 #endif #endif /*ARM64*/ #ifndef __ASSEMBLER__ /* * During boot note the part of code and data that needs to be mapped while * in user mode. The provided address and size have to be page aligned. * Note that the code and data will be mapped at the lowest possible * addresses available for user space (see core_mmu_get_user_va_range()). */ extern long thread_user_kcode_offset; /* * Initializes VBAR for current CPU (called by thread_init_per_cpu() */ void thread_init_vbar(vaddr_t addr); void thread_excp_vect(void); void thread_excp_vect_wa_spectre_v2(void); void thread_excp_vect_wa_a15_spectre_v2(void); void thread_excp_vect_wa_spectre_bhb(void); void thread_excp_vect_end(void); /* * Assembly function as the first function in a thread. Handles a stdcall, * a0-a3 holds the parameters. Hands over to __thread_std_smc_entry() when * everything is set up and does some post processing once * __thread_std_smc_entry() returns. */ void thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); uint32_t __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); void thread_sp_alloc_and_run(struct thread_smc_args *args); /* * Resumes execution of currently active thread by restoring context and * jumping to the instruction where to continue execution. * * Arguments supplied by non-secure world will be copied into the saved * context of the current thread if THREAD_FLAGS_COPY_ARGS_ON_RETURN is set * in the flags field in the thread context. */ void thread_resume(struct thread_ctx_regs *regs); uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, uint32_t *exit_status0, uint32_t *exit_status1); /* * Private functions made available for thread_asm.S */ /* Returns the temp stack for current CPU */ void *thread_get_tmp_sp(void); /* * Marks the current thread as suspended. And updated the flags * for the thread context (see thread resume for use of flags). * Returns thread index of the thread that was suspended. */ int thread_state_suspend(uint32_t flags, uint32_t cpsr, vaddr_t pc); /* * Marks the current thread as free. */ void thread_state_free(void); /* Returns a pointer to the saved registers in current thread context. */ struct thread_ctx_regs *thread_get_ctx_regs(void); #ifdef ARM32 /* Sets sp for abort mode */ void thread_set_abt_sp(vaddr_t sp); /* Sets sp for undefined mode */ void thread_set_und_sp(vaddr_t sp); /* Sets sp for irq mode */ void thread_set_irq_sp(vaddr_t sp); /* Sets sp for fiq mode */ void thread_set_fiq_sp(vaddr_t sp); /* Read usr_sp banked CPU register */ uint32_t thread_get_usr_sp(void); uint32_t thread_get_usr_lr(void); void thread_set_usr_lr(uint32_t usr_lr); #endif /*ARM32*/ void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); /* * The thread_rpc() function suspends current thread and temporarily exits * to non-secure world. This function returns later when non-secure world * returns. * * The purpose of this function is to request services from non-secure * world. */ #define THREAD_RPC_NUM_ARGS 4 #ifdef ARM64 void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr); void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); #ifdef CFG_CORE_FFA struct thread_rpc_arg { union { struct { uint32_t w1; uint32_t w4; uint32_t w5; uint32_t w6; } call; struct { uint32_t w4; uint32_t w5; uint32_t w6; } ret; uint32_t pad[THREAD_RPC_NUM_ARGS]; }; }; static inline void thread_rpc(struct thread_rpc_arg *rpc_arg) { __thread_rpc(rpc_arg->pad); } #else static inline void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) { __thread_rpc(rv); } #endif #endif #ifdef ARM32 void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); #endif /* * Called from assembly only, vector_fast_smc_entry(). Handles a fast SMC * by dispatching it to the registered fast SMC handler. */ void thread_handle_fast_smc(struct thread_smc_args *args); /* * Called from assembly only, vector_std_smc_entry(). Handles a std SMC by * dispatching it to the registered std SMC handler. */ uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); /* Called from assembly only. Handles a SVC from user mode. */ void thread_scall_handler(struct thread_scall_regs *regs); void thread_spmc_register_secondary_ep(vaddr_t ep); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_THREAD_PRIVATE_ARCH_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/thread_spmc.h000066400000000000000000000047351464416617300233510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021-2024, Arm Limited. * Copyright (c) 2023, Linaro Limited */ #ifndef __KERNEL_THREAD_SPMC_H #define __KERNEL_THREAD_SPMC_H #include #include #include #include /* The FF-A ID of Secure World components should be between these limits */ #define FFA_SWD_ID_MIN 0x8000 #define FFA_SWD_ID_MAX UINT16_MAX /* * OP-TEE FF-A partition ID. This is valid both when * - the SPMC is implemented by OP-TEE and the core OP-TEE functionality runs * in a logical SP that resides at the same exception level as the SPMC, or, * - the SPMC is at a higher EL and OP-TEE is running as a standalone S-EL1 SP. */ extern uint16_t optee_endpoint_id; /* * FF-A ID of the SPMC. This is valid both when the SPMC is implemented in * OP-TEE or at a higher EL. */ extern uint16_t spmc_id; #if defined(CFG_CORE_SEL1_SPMC) /* FF-A ID of the SPMD. This is only valid when OP-TEE is the S-EL1 SPMC. */ extern uint16_t spmd_id; #endif #define SPMC_CORE_SEL1_MAX_SHM_COUNT 64 struct ffa_rxtx { void *rx; void *tx; unsigned int size; unsigned int spinlock; uint32_t ffa_vers; bool tx_is_mine; }; void spmc_handle_spm_id_get(struct thread_smc_args *args); void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *buf); void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *buf); void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *buf); uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx); void spmc_set_args(struct thread_smc_args *args, uint32_t fid, uint32_t src_dst, uint32_t w2, uint32_t w3, uint32_t w4, uint32_t w5); void spmc_handle_partition_info_get(struct thread_smc_args *args, struct ffa_rxtx *rxtx); TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, size_t idx, uint16_t endpoint_id, uint16_t execution_context, uint32_t part_props, const uint32_t uuid_words[4]); int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen, struct ffa_mem_transaction_x *trans); #if defined(CFG_CORE_SEL1_SPMC) void thread_spmc_set_async_notif_intid(int intid); #else static inline void __noreturn thread_spmc_set_async_notif_intid(int intid __unused) { panic(); } struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie); void thread_spmc_relinquish(uint64_t memory_region_handle); #endif #endif /* __KERNEL_THREAD_SPMC_H */ optee_os-4.3.0/core/arch/arm/include/kernel/tlb_helpers.h000066400000000000000000000021421464416617300233510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2017, Linaro Limited */ #ifndef __KERNEL_TLB_HELPERS_H #define __KERNEL_TLB_HELPERS_H #include #ifndef __ASSEMBLER__ #include void tlbi_all(void); void tlbi_asid(unsigned long asid); void tlbi_va_allasid(unsigned long addr); static inline void tlbi_va_allasid_nosync(vaddr_t va) { #ifdef ARM64 tlbi_vaae1is(va >> TLBI_VA_SHIFT); #else write_tlbimvaais(va); #endif } static inline void tlbi_va_asid_nosync(vaddr_t va, uint32_t asid) { uint32_t a = asid & TLBI_ASID_MASK; #ifdef ARM64 tlbi_vale1is((va >> TLBI_VA_SHIFT) | SHIFT_U64(a, TLBI_ASID_SHIFT)); tlbi_vale1is((va >> TLBI_VA_SHIFT) | SHIFT_U64(a | 1, TLBI_ASID_SHIFT)); #else write_tlbimvais((va & ~(BIT32(TLBI_MVA_SHIFT) - 1)) | a); write_tlbimvais((va & ~(BIT32(TLBI_MVA_SHIFT) - 1)) | a | 1); #endif } static inline void tlbi_va_asid(vaddr_t va, uint32_t asid) { dsb_ishst(); tlbi_va_asid_nosync(va, asid); dsb_ish(); isb(); } #endif /*!__ASSEMBLER__*/ #endif /* __KERNEL_TLB_HELPERS_H */ optee_os-4.3.0/core/arch/arm/include/kernel/tz_proc_def.h000066400000000000000000000052451464416617300233530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TZ_PROC_DEF_H #define __KERNEL_TZ_PROC_DEF_H #include /* * General constants */ /* * CP15 Multiprocessor Affinity register (MPIDR) */ #define CP15_CONFIG_CPU_ID_MASK U(0x00000003) #define CPU_ID0 U(0x00000000) #define CPU_ID1 U(0x00000001) /* * CP15 Secure configuration register */ #define CP15_CONFIG_NS_MASK U(0x00000001) #define CP15_CONFIG_IRQ_MASK U(0x00000002) #define CP15_CONFIG_FIQ_MASK U(0x00000004) #define CP15_CONFIG_EA_MASK U(0x00000008) #define CP15_CONFIG_FW_MASK U(0x00000010) #define CP15_CONFIG_AW_MASK U(0x00000020) #define CP15_CONFIG_nET_MASK U(0x00000040) /* * CP15 Control register */ #define CP15_CONTROL_M_MASK U(0x00000001) #define CP15_CONTROL_C_MASK U(0x00000004) #define CP15_CONTROL_Z_MASK U(0x00000800) #define CP15_CONTROL_I_MASK U(0x00001000) #define CP15_CONTROL_V_MASK U(0x00002000) #define CP15_CONTROL_HA_MASK U(0x00020000) #define CP15_CONTROL_EE_MASK U(0x02000000) #define CP15_CONTROL_NMFI_MASK U(0x08000000) #define CP15_CONTROL_TRE_MASK U(0x10000000) #define CP15_CONTROL_AFE_MASK U(0x20000000) #define CP15_CONTROL_TE_MASK U(0x40000000) /* * CP15 Auxiliary Control register */ #define CP15_CONTROL_SMP_MASK U(0x00000040) #define CP15_CONTROL_EXCL_MASK U(0x00000080) /* * CP15 Non secure access control register */ #define CP15_NSAC_TL_MASK U(0x10000) #define CP15_NSAC_CL_MASK U(0x20000) #define CP15_NSAC_CPN_MASK U(0x3FFF) /* * CP15 Cache register */ #define CP15_CACHE_ADDR_R_BIT U(12) #define CP15_CACHE_ADDR_L_BIT (U(32) - CP15_CACHE_ADDR_R_BIT) #define CP15_CACHE_RESULT_MASK U(0x00000001) /* * CP15 TCM register * * ITCM configuration (4kbytes, @0x20100000, enabled) * DTCM configuration (4kbytes, @0x20101000, enabled) */ #define CP15_TCM_ENABLE_MASK U(0x00000001) #define CP15_TCM_INSTR_TCM U(0x2010000C) #define CP15_TCM_DATA_TCM U(0x2010100C) /* * CP15 cache lockdown register * * ITCM configuration (4kbytes, @0x20100000, enabled) * DTCM configuration (4kbytes, @0x20101000, enabled) */ #define CP15_CACHE_LOCK_ALLWAYS_MASK U(0x0000000F) /* * CP15 cache cleaning constant definition */ /* start of line number field offset in way/index format */ #define LINE_FIELD_OFFSET U(5) /* Warning: this assumes a 256 lines/way cache (32kB cache) */ #define LINE_FIELD_OVERFLOW U(13) /* start of way number field offset in way/index format */ #define WAY_FIELD_OFFSET U(30) #endif /*__KERNEL_TZ_PROC_DEF_H*/ optee_os-4.3.0/core/arch/arm/include/kernel/tz_ssvce_def.h000066400000000000000000000065141464416617300235330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TZ_SSVCE_DEF_H #define __KERNEL_TZ_SSVCE_DEF_H #include #include /* * ARMv7 Secure Services library */ #define CPSR_OFFSET U(0x00) #define STACK_INT_USAGE U(0x04) /* * tee service IDs (TODO: align with the service ID list). * Set by NSec in R4 before SMC to request a TEE service. */ #define SSAPI_RET_FROM_INT_SERV U(4) #define SSAPI_RET_FROM_RPC_SERV U(5) /* * TEE monitor: status returned by the routine that checks the entry * reason (valid Service ID / secure context). */ #define SEC_INVALID_ENTRY U(0) #define SEC_PRE_INIT_ENTRY U(1) #define SEC_RET_FROM_INT_ENTRY U(2) #define SEC_RET_FROM_RPC_ENTRY U(3) #define SEC_NORMAL_ENTRY U(4) /* * teecore exit reason. * Set by Secure in R4 before SMC to request a switch to NSec. */ #define SEC_EXIT_NORMAL U(1) #define SEC_EXIT_START_EXT_CODE U(2) #define SEC_EXIT_INT U(3) #define SEC_EXIT_RPC_CALL U(4) #define SEC_EXIT_FIRST U(5) #define SEC_EXIT_DEEP_SLEEP U(6) /* misc */ #define SEC_UNDEF_STACK_OFFSET U(4) #define SEC_ABORT_STACK_OFFSET U(12) #define SEC_ENTRY_STATUS_NOK U(0) #define SEC_ENTRY_STATUS_OK U(1) /* * Outer cache iomem */ #define PL310_LINE_SIZE U(32) #define PL310_8_WAYS U(8) #define PL310_CACHE_ID 0x0 /* reg1 */ #define PL310_CTRL U(0x100) #define PL310_AUX_CTRL U(0x104) #define PL310_TAG_RAM_CTRL U(0x108) #define PL310_DATA_RAM_CTRL U(0x10C) /* reg7 */ #define PL310_SYNC U(0x730) #define PL310_INV_BY_WAY U(0x77C) #define PL310_CLEAN_BY_WAY U(0x7BC) #define PL310_FLUSH_BY_WAY U(0x7FC) #define PL310_INV_BY_PA U(0x770) #define PL310_CLEAN_BY_PA U(0x7B0) #define PL310_FLUSH_BY_PA U(0x7F0) #define PL310_FLUSH_BY_INDEXWAY U(0x7F8) /* reg9 */ #define PL310_DCACHE_LOCKDOWN_BASE U(0x900) #define PL310_ICACHE_LOCKDOWN_BASE U(0x904) /* reg12 */ #define PL310_ADDR_FILT_START U(0xC00) #define PL310_ADDR_FILT_END U(0xC04) /* reg15 */ #define PL310_DEBUG_CTRL U(0xF40) #define PL310_PREFETCH_CTRL U(0xF60) #define PL310_POWER_CTRL U(0xF80) #define PL310_CTRL_ENABLE_BIT BIT32(0) #define PL310_AUX_16WAY_BIT BIT32(16) #define PL310_CACHE_ID_PART_MASK GENMASK_32(9, 6) #define PL310_CACHE_ID_PART_L310 0xC0 #define PL310_CACHE_ID_RTL_MASK GENMASK_32(5, 0) #define PL310_CACHE_ID_RTL_R3P2 0x8 /* * SCU iomem */ #define SCU_CTRL U(0x00) #define SCU_CONFIG U(0x04) #define SCU_POWER U(0x08) #define SCU_INV_SEC U(0x0C) #define SCU_FILT_SA U(0x40) #define SCU_FILT_EA U(0x44) #define SCU_SAC U(0x50) #define SCU_NSAC U(0x54) #define SCU_SIZE U(0x58) #define SCU_ERRATA744369 U(0x30) #define SCU_ACCESS_CONTROL_CPU0 BIT32(0) #define SCU_ACCESS_CONTROL_CPU1 BIT32(1) #define SCU_ACCESS_CONTROL_CPU2 BIT32(2) #define SCU_ACCESS_CONTROL_CPU3 BIT32(3) #define SCU_NSAC_SCU_SHIFT U(0) #define SCU_NSAC_PTIMER_SHIFT U(4) #define SCU_NSAC_GTIMER_SHIFT U(8) /* * GIC iomem */ #define GIC_DIST_ISR0 U(0x080) #define GIC_DIST_ISR1 U(0x084) #define GIC_DIST_IPRIO U(0x400) /* * CPU iomem */ #define CORE_ICC_ICCPMR U(0x0004) #endif /* __KERNEL_TZ_SSVCE_DEF_H */ optee_os-4.3.0/core/arch/arm/include/kernel/tz_ssvce_pl310.h000066400000000000000000000014101464416617300236220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TZ_SSVCE_PL310_H #define __KERNEL_TZ_SSVCE_PL310_H #include #include #include vaddr_t pl310_base(void); vaddr_t pl310_nsbase(void); /* * End address is included in the range (last address in range) */ void arm_cl2_cleaninvbyway(vaddr_t pl310_base); void arm_cl2_invbyway(vaddr_t pl310_base); void arm_cl2_cleanbyway(vaddr_t pl310_base); void arm_cl2_cleanbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); void arm_cl2_invbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); void arm_cl2_cleaninvbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); #endif /* __KERNEL_TZ_SSVCE_PL310_H */ optee_os-4.3.0/core/arch/arm/include/kernel/user_access_arch.h000066400000000000000000000012471464416617300243470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, Amazon.com Inc. or its affiliates. All rights Reserved. */ #ifndef __KERNEL_USER_ACCESS_ARCH_H #define __KERNEL_USER_ACCESS_ARCH_H #include #ifdef CFG_PAN /* Enter a section where user mode access is temporarily enabled. */ static inline void enter_user_access(void) { write_pan_disable(); } /* Exit from the section where user mode access was temporarily enabled. */ static inline void exit_user_access(void) { write_pan_enable(); } #else static inline void enter_user_access(void) {} static inline void exit_user_access(void) {} #endif /* CFG_PAN */ #endif /* __KERNEL_USER_ACCESS_ARCH_H */ optee_os-4.3.0/core/arch/arm/include/kernel/vfp.h000066400000000000000000000041751464416617300216510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __KERNEL_VFP_H #define __KERNEL_VFP_H #include #include #ifdef ARM32 /* * Advanced SIMD/floating point state on ARMv7-A or ARMv8-A AArch32 has: * - 32 64-bit data registers * - FPSCR (32 bits) * - FPEXC (32 bits) */ #define VFP_NUM_REGS U(32) struct vfp_reg { uint64_t v; }; struct vfp_state { uint32_t fpexc; uint32_t fpscr; struct vfp_reg reg[VFP_NUM_REGS]; }; #endif #ifdef ARM64 /* * Advanced SIMD/floating point state on ARMv8-A AArch64 has: * - 32 128-bit data registers * - FPSR (32 bits) * - FPCR (32 bits) * - CPACR_EL1.FPEN (2 bits) */ #define VFP_NUM_REGS U(32) struct vfp_reg { uint8_t v[16]; } __aligned(16); struct vfp_state { struct vfp_reg reg[VFP_NUM_REGS]; uint32_t fpsr; uint32_t fpcr; uint32_t cpacr_el1; }; #endif #ifdef CFG_WITH_VFP /* vfp_is_enabled() - Returns true if VFP is enabled */ bool vfp_is_enabled(void); /* vfp_enable() - Enables vfp */ void vfp_enable(void); /* vfp_disable() - Disables vfp */ void vfp_disable(void); #else static inline bool vfp_is_enabled(void) { return false; } static inline void vfp_enable(void) { } static inline void vfp_disable(void) { } #endif /* * vfp_lazy_save_state_init() - Saves VFP enable status and disables VFP * @state: VFP state structure to initialize */ void vfp_lazy_save_state_init(struct vfp_state *state); /* * vfp_lazy_save_state_final() - Saves rest of VFP state * @state: VFP state to save to * @force_save: Forces saving of state regardless of previous state if true. * * If VFP was enabled when vfp_lazy_save_state_init() was called or * @force_save is true: save rest of state and disable VFP. Otherwise, do * nothing. */ void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save); /* * vfp_lazy_restore_state() - Lazy restore VFP state * @state: VFP state to restore * * Restores VFP enable status and also restores rest of VFP state if * vfp_lazy_save_state_final() was called on this state. */ void vfp_lazy_restore_state(struct vfp_state *state, bool full_state); #endif /*__KERNEL_VFP_H*/ optee_os-4.3.0/core/arch/arm/include/mm/000077500000000000000000000000001464416617300200275ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/mm/core_mmu_arch.h000066400000000000000000000127621464416617300230130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MM_CORE_MMU_ARCH_H #define __MM_CORE_MMU_ARCH_H #ifndef __ASSEMBLER__ #include #include #include #include #include #include #include #include #endif #include /* * Platforms can define TRUSTED_{S,D}RAM_* or TZ{S,D}RAM_*. We're helping * here with the transition to TRUSTED_{S,D}RAM_* by defining these if * missing based on the legacy defines. */ #ifdef TZSRAM_BASE #ifdef TRUSTED_SRAM_BASE #error TRUSTED_SRAM_BASE is already defined #endif #define TRUSTED_SRAM_BASE TZSRAM_BASE #define TRUSTED_SRAM_SIZE TZSRAM_SIZE #endif #ifdef TZDRAM_BASE #ifdef TRUSTED_DRAM_BASE #error TRUSTED_DRAM_BASE is already defined #endif #define TRUSTED_DRAM_BASE TZDRAM_BASE #define TRUSTED_DRAM_SIZE TZDRAM_SIZE #endif #define SMALL_PAGE_SHIFT U(12) #ifdef CFG_WITH_LPAE #define CORE_MMU_PGDIR_SHIFT U(21) #define CORE_MMU_PGDIR_LEVEL U(3) #else #define CORE_MMU_PGDIR_SHIFT U(20) #define CORE_MMU_PGDIR_LEVEL U(2) #endif #define CORE_MMU_USER_CODE_SHIFT SMALL_PAGE_SHIFT #define CORE_MMU_USER_PARAM_SHIFT SMALL_PAGE_SHIFT /* * Level of base table (i.e. first level of page table), * depending on address space */ #if !defined(CFG_WITH_LPAE) || (CFG_LPAE_ADDR_SPACE_BITS < 40) #define CORE_MMU_BASE_TABLE_SHIFT U(30) #define CORE_MMU_BASE_TABLE_LEVEL U(1) #elif (CFG_LPAE_ADDR_SPACE_BITS <= 48) #define CORE_MMU_BASE_TABLE_SHIFT U(39) #define CORE_MMU_BASE_TABLE_LEVEL U(0) #else /* (CFG_LPAE_ADDR_SPACE_BITS > 48) */ #error "CFG_WITH_LPAE with CFG_LPAE_ADDR_SPACE_BITS > 48 isn't supported!" #endif #ifdef CFG_WITH_LPAE /* * CORE_MMU_BASE_TABLE_OFFSET is used when switching to/from reduced kernel * mapping. The actual value depends on internals in core_mmu_lpae.c which * we rather not expose here. There's a compile time assertion to check * that these magic numbers are correct. */ #define CORE_MMU_BASE_TABLE_OFFSET \ (CFG_TEE_CORE_NB_CORE * \ BIT(CFG_LPAE_ADDR_SPACE_BITS - CORE_MMU_BASE_TABLE_SHIFT) * \ U(8)) #endif #ifndef __ASSEMBLER__ /* * Assembly code in enable_mmu() depends on the layout of this struct. */ struct core_mmu_config { #if defined(ARM64) uint64_t tcr_el1; uint64_t mair_el1; uint64_t ttbr0_el1_base; uint64_t ttbr0_core_offset; uint64_t map_offset; #elif defined(CFG_WITH_LPAE) uint32_t ttbcr; uint32_t mair0; uint32_t ttbr0_base; uint32_t ttbr0_core_offset; uint32_t map_offset; #else uint32_t prrr; uint32_t nmrr; uint32_t dacr; uint32_t ttbcr; uint32_t ttbr; uint32_t map_offset; #endif }; #ifdef CFG_WITH_LPAE /* * struct core_mmu_user_map - current user mapping register state * @user_map: physical address of user map translation table * @asid: ASID for the user map * * Note that this struct should be treated as an opaque struct since * the content depends on descriptor table format. */ struct core_mmu_user_map { uint64_t user_map; uint32_t asid; }; #else /* * struct core_mmu_user_map - current user mapping register state * @ttbr0: content of ttbr0 * @ctxid: content of contextidr * * Note that this struct should be treated as an opaque struct since * the content depends on descriptor table format. */ struct core_mmu_user_map { uint32_t ttbr0; uint32_t ctxid; }; #endif #ifdef CFG_WITH_LPAE bool core_mmu_user_va_range_is_defined(void); #else static inline bool __noprof core_mmu_user_va_range_is_defined(void) { return true; } #endif /* Cache maintenance operation type */ enum cache_op { DCACHE_CLEAN, DCACHE_AREA_CLEAN, DCACHE_INVALIDATE, DCACHE_AREA_INVALIDATE, ICACHE_INVALIDATE, ICACHE_AREA_INVALIDATE, DCACHE_CLEAN_INV, DCACHE_AREA_CLEAN_INV, }; /* L1/L2 cache maintenance */ TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len); #ifdef CFG_PL310 TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len); #else static inline TEE_Result cache_op_outer(enum cache_op op __unused, paddr_t pa __unused, size_t len __unused) { /* Nothing to do about L2 Cache Maintenance when no PL310 */ return TEE_SUCCESS; } #endif /* Do section mapping, not support on LPAE */ void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb); #if defined(ARM64) unsigned int core_mmu_arm64_get_pa_width(void); #endif static inline bool core_mmu_check_max_pa(paddr_t pa __maybe_unused) { #if defined(ARM64) return pa <= (BIT64(core_mmu_arm64_get_pa_width()) - 1); #elif defined(CFG_CORE_LARGE_PHYS_ADDR) return pa <= (BIT64(40) - 1); #else COMPILE_TIME_ASSERT(sizeof(paddr_t) == sizeof(uint32_t)); return true; #endif } /* * Special barrier to make sure all the changes to translation tables are * visible before returning. */ static inline void core_mmu_table_write_barrier(void) { dsb_ishst(); } static inline bool core_mmu_entry_have_security_bit(uint32_t attr) { return !(attr & TEE_MATTR_TABLE) || !IS_ENABLED(CFG_WITH_LPAE); } static inline unsigned int core_mmu_get_va_width(void) { if (IS_ENABLED(ARM64)) { COMPILE_TIME_ASSERT(CFG_LPAE_ADDR_SPACE_BITS >= 32); COMPILE_TIME_ASSERT(CFG_LPAE_ADDR_SPACE_BITS <= 48); return CFG_LPAE_ADDR_SPACE_BITS; } return 32; } static inline bool core_mmu_level_in_range(unsigned int level) { #if CORE_MMU_BASE_TABLE_LEVEL == 0 return level <= CORE_MMU_PGDIR_LEVEL; #else return level >= CORE_MMU_BASE_TABLE_LEVEL && level <= CORE_MMU_PGDIR_LEVEL; #endif } #endif /*__ASSEMBLER__*/ #endif /* __MM_CORE_MMU_ARCH_H */ optee_os-4.3.0/core/arch/arm/include/mm/generic_ram_layout.h000066400000000000000000000151131464416617300240510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __MM_GENERIC_RAM_LAYOUT_H #define __MM_GENERIC_RAM_LAYOUT_H #include /* * Generic RAM layout configuration directives * * Mandatory directives: * CFG_TZDRAM_START * CFG_TZDRAM_SIZE * CFG_SHMEM_START * CFG_SHMEM_SIZE * * Optional directives: * CFG_TEE_LOAD_ADDR If defined sets TEE_LOAD_ADDR. If not, TEE_LOAD_ADDR * is set by the platform or defaults to TEE_RAM_START. * CFG_TEE_RAM_VA_SIZE Some platforms may have specific needs * * Optional directives when pager is enabled: * CFG_TZSRAM_START If no set, emulated at CFG_TZDRAM_START * CFG_TZSRAM_SIZE Default to CFG_CORE_TZSRAM_EMUL_SIZE * * Optional directive when CFG_SECURE_DATA_PATH is enabled: * CFG_TEE_SDP_MEM_SIZE If CFG_TEE_SDP_MEM_BASE is not defined, SDP test * memory byte size can be set by CFG_TEE_SDP_MEM_SIZE. * * This header file produces the following generic macros upon the mandatory * and optional configuration directives listed above: * * TEE_RAM_START TEE core RAM physical base address * TEE_RAM_VA_SIZE TEE core virtual memory address range size * TEE_RAM_PH_SIZE TEE core physical RAM byte size * TA_RAM_START TA contexts/pagestore RAM physical base address * TA_RAM_SIZE TA contexts/pagestore RAM byte size * TEE_SHMEM_START Non-secure static shared memory physical base address * TEE_SHMEM_SIZE Non-secure static shared memory byte size * * TZDRAM_BASE Main/external secure RAM base address * TZDRAM_SIZE Main/external secure RAM byte size * TZSRAM_BASE On-chip secure RAM base address, required by pager. * TZSRAM_SIZE On-chip secure RAM byte size, required by pager. * * TEE_LOAD_ADDR Only defined here if CFG_TEE_LOAD_ADDR is defined. * Otherwise we expect the platform_config.h to define it * unless which LEE_LOAD_ADDR defaults to TEE_RAM_START. * * TEE_RAM_VA_SIZE Set to CFG_TEE_RAM_VA_SIZE or defaults to * CORE_MMU_PGDIR_SIZE. * * TEE_SDP_TEST_MEM_BASE Define if a SDP memory pool is required and none set. * Always defined in the inner top (high addresses) * of CFG_TZDRAM_START/_SIZE. * TEE_SDP_TEST_MEM_SIZE Set to CFG_TEE_SDP_MEM_SIZE or a default size. * * ---------------------------------------------------------------------------- * TEE RAM layout without CFG_WITH_PAGER *_ * +----------------------------------+ <-- CFG_TZDRAM_START * | TEE core secure RAM (TEE_RAM) | * +----------------------------------+ * | Trusted Application RAM (TA_RAM) | * +----------------------------------+ * | SDP test memory (optional) | * +----------------------------------+ <-- CFG_TZDRAM_START + CFG_TZDRAM_SIZE * * +----------------------------------+ <-- CFG_SHMEM_START * | Non-secure static SHM | * +----------------------------------+ <-- CFG_SHMEM_START + CFG_SHMEM_SIZE * * ---------------------------------------------------------------------------- * TEE RAM layout with CFG_WITH_PAGER=y and undefined CFG_TZSRAM_START/_SIZE * * +----------------------------------+ <-- CFG_TZDRAM_START * | TEE core secure RAM (TEE_RAM) | | | CFG_CORE_TZSRAM_EMUL_SIZE * +----------------------------------+ --|-' * | reserved (for kasan) | | TEE_RAM_VA_SIZE * +----------------------------------+ --' * | TA RAM / Pagestore (TA_RAM) | * +----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE * +----------------------------------+ <-- * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE * +----------------------------------+ <-+ CFG_TZDRAM_START + CFG_TZDRAM_SIZE * * +----------------------------------+ <-- CFG_SHMEM_START * | Non-secure static SHM | | * +----------------------------------+ v CFG_SHMEM_SIZE * * ---------------------------------------------------------------------------- * TEE RAM layout with CFG_WITH_PAGER=y and define CFG_TZSRAM_START/_SIZE * * +----------------------------------+ <-- CFG_TZSRAM_START * | TEE core secure RAM (TEE_RAM) | | CFG_TZSRAM_SIZE * +----------------------------------+ --' * * +----------------------------------+ <- CFG_TZDRAM_START * | TA RAM / Pagestore (TA_RAM) | * |----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE * |----------------------------------+ <-- * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE * +----------------------------------+ <-+ CFG_TZDRAM_START + CFG_TZDRAM_SIZE * * +----------------------------------+ <-- CFG_SHMEM_START * | Non-secure static SHM | | * +----------------------------------+ v CFG_SHMEM_SIZE */ #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else /* Platform specific platform_config.h may set TEE_LOAD_ADDR */ #endif #ifdef CFG_TEE_RAM_VA_SIZE #define TEE_RAM_VA_SIZE CFG_TEE_RAM_VA_SIZE #else #define TEE_RAM_VA_SIZE CORE_MMU_PGDIR_SIZE #endif #ifdef CFG_SHMEM_SIZE #define TEE_SHMEM_SIZE CFG_SHMEM_SIZE #endif #ifdef CFG_SHMEM_START #define TEE_SHMEM_START CFG_SHMEM_START #ifndef CFG_SHMEM_SIZE #error CFG_SHMEM_START mandates CFG_SHMEM_SIZE #endif #endif #if defined(CFG_WITH_PAGER) && defined(CFG_TZSRAM_START) #define TZSRAM_BASE CFG_TZSRAM_START #define TZSRAM_SIZE CFG_TZSRAM_SIZE #endif #ifdef CFG_TZDRAM_START #if !defined(CFG_WITH_PAGER) || defined(CFG_TZSRAM_START) #define TZDRAM_BASE CFG_TZDRAM_START #define TZDRAM_SIZE CFG_TZDRAM_SIZE #else #define TZSRAM_BASE CFG_TZDRAM_START #define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE #define TZDRAM_BASE ROUNDUP(TZSRAM_BASE + TZSRAM_SIZE, \ TEE_RAM_VA_SIZE) #define TZDRAM_SIZE (CFG_TZDRAM_START + (CFG_TZDRAM_SIZE - \ TZDRAM_BASE)) #endif #ifdef CFG_WITH_PAGER #define TEE_RAM_START TZSRAM_BASE #define TEE_RAM_PH_SIZE TZSRAM_SIZE #else #define TEE_RAM_START TZDRAM_BASE #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE #endif /*CFG_WITH_PAGER*/ #endif /*CFG_TZDRAM_START*/ /* * Secure data path test memory pool * - If SDP is disabled, no SDP test memory needed. * - If SDP is enabled, if CFG_TEE_SDP_MEM_BASE, SDP test pool is not needed. * - If SDP is enabled and CFG_TEE_SDP_MEM_BASE not defined, a SDP test pool * is defined at the end of the secure RAM. CFG_TEE_SDP_MEM_SIZE can set * its size otherwise it defaults to 4MB. */ #if !defined(CFG_SECURE_DATA_PATH) || defined(CFG_TEE_SDP_MEM_BASE) #define TEE_SDP_TEST_MEM_SIZE 0 #else #ifdef CFG_TEE_SDP_MEM_SIZE #define TEE_SDP_TEST_MEM_SIZE CFG_TEE_SDP_MEM_SIZE #else #define TEE_SDP_TEST_MEM_SIZE SIZE_4M #endif #define TEE_SDP_TEST_MEM_BASE (CFG_TZDRAM_START + (CFG_TZDRAM_SIZE - \ TEE_SDP_TEST_MEM_SIZE)) #endif #endif /*__MM_GENERIC_RAM_LAYOUT_H*/ optee_os-4.3.0/core/arch/arm/include/optee_ffa.h000066400000000000000000000140741464416617300215250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2021, Linaro Limited */ /* * This file is exported by OP-TEE and is kept in sync between secure world * and normal world drivers. We're using ARM FF-A 1.0 specification. */ #ifndef __OPTEE_FFA_H #define __OPTEE_FFA_H #include /* * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal * messages. * * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP * are using the AArch32 SMC calling convention with register usage as * defined in FF-A specification: * w0: Function ID (0x8400006F or 0x84000070) * w1: Source/Destination IDs * w2: Reserved (MBZ) * w3-w7: Implementation defined, free to be used below */ #define OPTEE_FFA_VERSION_MAJOR UINT32_C(1) #define OPTEE_FFA_VERSION_MINOR UINT32_C(0) #define OPTEE_FFA_BLOCKING_CALL(id) UINT32_C(id) #define OPTEE_FFA_YIELDING_CALL_BIT U(31) #define OPTEE_FFA_YIELDING_CALL(id) (UINT32_C(id) | \ BIT32(OPTEE_FFA_YIELDING_CALL_BIT)) /* * Returns the API version implemented, currently follows the FF-A version. * Call register usage: * w3: Service ID, OPTEE_FFA_GET_API_VERSION * w4-w7: Not used (MBZ) * * Return register usage: * w3: OPTEE_FFA_VERSION_MAJOR * w4: OPTEE_FFA_VERSION_MINOR * w5-w7: Not used (MBZ) */ #define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0) /* * Returns the revision of OP-TEE. * * Used by non-secure world to figure out which version of the Trusted OS * is installed. Note that the returned revision is the revision of the * Trusted OS, not of the API. * * Call register usage: * w3: Service ID, OPTEE_FFA_GET_OS_VERSION * w4-w7: Unused (MBZ) * * Return register usage: * w3: CFG_OPTEE_REVISION_MAJOR * w4: CFG_OPTEE_REVISION_MINOR * w5: TEE_IMPL_GIT_SHA1 (or zero if not supported) */ #define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1) /* * Exchange capabilities between normal world and secure world. * * Currently there are no defined capabilities. When features are added new * capabilities may be added. * * Call register usage: * w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES * w4-w7: Not used (MBZ) * * Return register usage: * w3: Error code, 0 on success * w4: Bit[7:0]: Number of parameters needed for RPC to be supplied * as the second MSG arg struct for * OPTEE_FFA_YIELDING_CALL_WITH_ARG. * Bit[31:8]: Reserved (MBZ) * w5: Bitfield of OP-TEE capabilities OPTEE_FFA_SEC_CAP_* * w6: The maximum secure world notification number * w7: Not used (MBZ) */ /* * Secure world supports using an offset into the argument shared memory * object, see also OPTEE_FFA_YIELDING_CALL_WITH_ARG */ #define OPTEE_FFA_SEC_CAP_ARG_OFFSET BIT(0) /* OP-TEE supports asynchronous notification via FF-A */ #define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF BIT(1) #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2) /* * Unregister shared memory * * Call register usage: * w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM * w4: Shared memory handle, lower bits * w5: Shared memory handle, higher bits * w6-w7: Not used (MBZ) * * Return register usage: * w3: Error code, 0 on success * w4-w7: Not used (MBZ) */ #define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3) /* * Inform OP-TEE that normal world is able to receive asynchronous * notifications. * * Call register usage: * w3: Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF * w4: Notification value to request bottom half processing, should be * less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE * w5-w7: Not used (MBZ) * * Return register usage: * w3: Error code, 0 on success * w4-w7: Not used (MBZ) */ #define OPTEE_FFA_ENABLE_ASYNC_NOTIF OPTEE_FFA_BLOCKING_CALL(5) #define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE 64 /* * Call with struct optee_msg_arg as argument in the supplied shared memory * with a zero internal offset and normal cached memory attributes. * Register usage: * w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG * w4: Lower 32 bits of a 64-bit Shared memory handle * w5: Upper 32 bits of a 64-bit Shared memory handle * w6: Offset into shared memory pointing to a struct optee_msg_arg * right after the parameters of this struct (at offset * OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg * for RPC, this struct has reserved space for the number of RPC * parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES. * MBZ unless the bit OPTEE_FFA_SEC_CAP_ARG_OFFSET is received with * OPTEE_FFA_EXCHANGE_CAPABILITIES. * w7: Not used (MBZ) * Resume from RPC. Register usage: * w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME * w4-w6: Not used (MBZ) * w7: Resume info * * Normal return (yielding call is completed). Register usage: * w3: Error code, 0 on success * w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE * w5-w7: Not used (MBZ) * * RPC interrupt return (RPC from secure world). Register usage: * w3: Error code == 0 * w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE * w5-w6: Not used (MBZ) * w7: Resume info * * Possible error codes in register w3: * 0: Success * FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START * OPTEE_FFA_YIELDING_CALL_RESUME * * Possible error codes for OPTEE_FFA_YIELDING_CALL_START, * FFA_BUSY: Number of OP-TEE OS threads exceeded, * try again later * FFA_DENIED: RPC shared memory object not found * FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory * * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME * FFA_INVALID_PARAMETER: Bad resume info */ #define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0) #define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1) #define OPTEE_FFA_YIELDING_CALL_RETURN_DONE U(0) #define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD U(1) #define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT U(2) #endif /*__OPTEE_FFA_H*/ optee_os-4.3.0/core/arch/arm/include/pta_stmm.h000066400000000000000000000011021464416617300214050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2020, Linaro Limited */ #ifndef __PTA_STMM_H #define __PTA_STMM_H /* * Interface to the pseudo TA, which provides a communication channel with * the Standalone MM SP (StMM) running at S-EL0. */ #define PTA_STMM_UUID { 0xed32d533, 0x99e6, 0x4209, {\ 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } } /* * Pass a buffer to Standalone MM SP * * [in/out] memref[0]: EFI Communication buffer * [out] value[1].a: EFI return code */ #define PTA_STMM_CMD_COMMUNICATE 0 #endif /* __PTA_STMM_H */ optee_os-4.3.0/core/arch/arm/include/scmi/000077500000000000000000000000001464416617300203515ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/scmi/scmi_server.h000066400000000000000000000036321464416617300230470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2022, Linaro Limited */ #ifndef __SCMI_SCMI_SERVER_H #define __SCMI_SCMI_SERVER_H #include #include #ifdef CFG_SCMI_SCPFW /* * Request processing of an incoming event in the SCMI server for a target * MHU/SMT mailbox. * * @channel_id: SCMI channel handler */ TEE_Result scmi_server_smt_process_thread(unsigned int channel_id); /* * Request processing of an incoming event in the SCMI server for a target * MHU/MSG mailbox. * * @id: SCMI channel handler * @in_buf: Input message MSG buffer * @in_size: Input message MSG buffer size * @out_buf: Output message MSG buffer * @out_size: Reference to output message MSG buffer size */ TEE_Result scmi_server_msg_process_thread(unsigned int channel_id, void *in_buf, size_t in_size, void *out_buf, size_t *out_size); /* * Get SCP-firmware channel device ID from the client channel ID. * * @channel_id: SCMI channel handler * @handle: Output SCP-firmware device ID for the target SCMI mailbox */ TEE_Result scmi_server_get_channel(unsigned int channel_id, int *handle); /* Get number of channels supported by the SCMI platform/server */ int scmi_server_get_channels_count(void); #else /* CFG_SCMI_SCPFW */ static inline TEE_Result scmi_server_smt_process_thread(unsigned int channel_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result scmi_server_msg_process_thread(unsigned int channel_id __unused, void *in_buf __unused, size_t in_size __unused, void *out_buf __unused, size_t *out_size __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result scmi_server_get_channel(unsigned int id __unused, int *handle __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline int scmi_server_get_channels_count(void) { return 0; } #endif /* CFG_SCMI_SCPFW */ #endif /* __SCMI_SCMI_SERVER_H */ optee_os-4.3.0/core/arch/arm/include/sm/000077500000000000000000000000001464416617300200355ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/sm/optee_smc.h000066400000000000000000000566531464416617300222030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2021, Linaro Limited */ #ifndef __SM_OPTEE_SMC_H #define __SM_OPTEE_SMC_H #include /* * This file is exported by OP-TEE and is in kept in sync between secure * world and normal world kernel driver. We're following ARM SMC Calling * Convention as specified in * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html * * This file depends on optee_msg.h being included to expand the SMC id * macros below. */ #define OPTEE_SMC_32 U(0) #define OPTEE_SMC_64 U(0x40000000) #define OPTEE_SMC_FAST_CALL U(0x80000000) #define OPTEE_SMC_STD_CALL U(0) #define OPTEE_SMC_OWNER_MASK U(0x3F) #define OPTEE_SMC_OWNER_SHIFT U(24) #define OPTEE_SMC_FUNC_MASK U(0xFFFF) #define OPTEE_SMC_IS_FAST_CALL(smc_val) ((smc_val) & OPTEE_SMC_FAST_CALL) #define OPTEE_SMC_IS_64(smc_val) ((smc_val) & OPTEE_SMC_64) #define OPTEE_SMC_FUNC_NUM(smc_val) ((smc_val) & OPTEE_SMC_FUNC_MASK) #define OPTEE_SMC_OWNER_NUM(smc_val) \ (((smc_val) >> OPTEE_SMC_OWNER_SHIFT) & OPTEE_SMC_OWNER_MASK) #define OPTEE_SMC_CALL_VAL(type, calling_convention, owner, func_num) \ ((type) | (calling_convention) | \ (((owner) & OPTEE_SMC_OWNER_MASK) << \ OPTEE_SMC_OWNER_SHIFT) |\ ((func_num) & OPTEE_SMC_FUNC_MASK)) #define OPTEE_SMC_STD_CALL_VAL(func_num) \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_STD_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS, (func_num)) #define OPTEE_SMC_FAST_CALL_VAL(func_num) \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS, (func_num)) #define OPTEE_SMC_OWNER_ARCH U(0) #define OPTEE_SMC_OWNER_CPU U(1) #define OPTEE_SMC_OWNER_SIP U(2) #define OPTEE_SMC_OWNER_OEM U(3) #define OPTEE_SMC_OWNER_STANDARD U(4) #define OPTEE_SMC_OWNER_TRUSTED_APP U(48) #define OPTEE_SMC_OWNER_TRUSTED_OS U(50) #define OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED U(62) #define OPTEE_SMC_OWNER_TRUSTED_OS_API U(63) /* * Function specified by SMC Calling convention. */ #define OPTEE_SMC_FUNCID_CALLS_COUNT U(0xFF00) #define OPTEE_SMC_CALLS_COUNT \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS_API, \ OPTEE_SMC_FUNCID_CALLS_COUNT) /* * Normal cached memory (write-back), shareable for SMP systems and not * shareable for UP systems. */ #define OPTEE_SMC_SHM_CACHED U(1) /* * a0..a7 is used as register names in the descriptions below, on arm32 * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's * 32-bit registers. */ /* * Function specified by SMC Calling convention * * Return the following UID if using API specified in this file * without further extensions: * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. * see also OPTEE_MSG_UID_* in optee_msg.h */ #define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID #define OPTEE_SMC_CALLS_UID \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS_API, \ OPTEE_SMC_FUNCID_CALLS_UID) /* * Function specified by SMC Calling convention * * Returns 2.0 if using API specified in this file without further extensions. * see also OPTEE_MSG_REVISION_* in optee_msg.h */ #define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION #define OPTEE_SMC_CALLS_REVISION \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS_API, \ OPTEE_SMC_FUNCID_CALLS_REVISION) /* * Get UUID of Trusted OS. * * Used by non-secure world to figure out which Trusted OS is installed. * Note that returned UUID is the UUID of the Trusted OS, not of the API. * * Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID * described above. */ #define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID #define OPTEE_SMC_CALL_GET_OS_UUID \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID) /* * Get revision of Trusted OS. * * Used by non-secure world to figure out which version of the Trusted OS * is installed. Note that the returned revision is the revision of the * Trusted OS, not of the API. * * Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION * described above. May optionally return a 32-bit build identifier in a2, * with zero meaning unspecified. */ #define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION #define OPTEE_SMC_CALL_GET_OS_REVISION \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION) /* * Call with struct optee_msg_arg as argument * * When called with OPTEE_SMC_CALL_WITH_RPC_ARG or * OPTEE_SMC_CALL_WITH_REGD_ARG in a0 there is one RPC struct optee_msg_arg * following after the first struct optee_msg_arg. The RPC struct * optee_msg_arg has reserved space for the number of RPC parameters as * returned by OPTEE_SMC_EXCHANGE_CAPABILITIES. * * When calling these functions normal world has a few responsibilities: * 1. It must be able to handle eventual RPCs * 2. Non-secure interrupts should not be masked * 3. If asynchronous notifications has been negotiated successfully, then * the interrupt for asynchronous notifications should be unmasked * during this call. * * Call register usage, OPTEE_SMC_CALL_WITH_ARG and * OPTEE_SMC_CALL_WITH_RPC_ARG: * a0 SMC Function ID, OPTEE_SMC_CALL_WITH_ARG or OPTEE_SMC_CALL_WITH_RPC_ARG * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a3 Cache settings, not used if physical pointer is in a predefined shared * memory area else per OPTEE_SMC_SHM_* * a4-6 Not used * a7 Hypervisor Client ID register * * Call register usage, OPTEE_SMC_CALL_WITH_REGD_ARG: * a0 SMC Function ID, OPTEE_SMC_CALL_WITH_REGD_ARG * a1 Upper 32 bits of a 64-bit shared memory cookie * a2 Lower 32 bits of a 64-bit shared memory cookie * a3 Offset of the struct optee_msg_arg in the shared memory with the * supplied cookie * a4-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 Return value, OPTEE_SMC_RETURN_* * a1-3 Not used * a4-7 Preserved * * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage: * a0 Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT * a1-3 Preserved * a4-7 Preserved * * RPC return register usage: * a0 Return value, OPTEE_SMC_RETURN_IS_RPC(val) * a1-2 RPC parameters * a3-7 Resume information, must be preserved * * Possible return values: * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this * function. * OPTEE_SMC_RETURN_OK Call completed, result updated in * the previously supplied struct * optee_msg_arg. * OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded, * try again later. * OPTEE_SMC_RETURN_EBADADDR Bad physical pointer to struct * optee_msg_arg. * OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg * OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal * world. */ #define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG #define OPTEE_SMC_CALL_WITH_ARG \ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG) #define OPTEE_SMC_CALL_WITH_RPC_ARG \ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_RPC_ARG) #define OPTEE_SMC_CALL_WITH_REGD_ARG \ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG) /* * Get Shared Memory Config * * Returns the Secure/Non-secure shared memory config. * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG * a1-6 Not used * a7 Hypervisor Client ID register * * Have config return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 Physical address of start of SHM * a2 Size of of SHM * a3 Cache settings of memory, as defined by the * OPTEE_SMC_SHM_* values above * a4-7 Preserved * * Not available register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL * a1-3 Not used * a4-7 Preserved */ #define OPTEE_SMC_FUNCID_GET_SHM_CONFIG 7 #define OPTEE_SMC_GET_SHM_CONFIG \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG) /* * Configures L2CC mutex * * Disables, enables usage of L2CC mutex. Returns or sets physical address * of L2CC mutex. * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_L2CC_MUTEX * a1 OPTEE_SMC_L2CC_MUTEX_GET_ADDR Get physical address of mutex * OPTEE_SMC_L2CC_MUTEX_SET_ADDR Set physical address of mutex * OPTEE_SMC_L2CC_MUTEX_ENABLE Enable usage of mutex * OPTEE_SMC_L2CC_MUTEX_DISABLE Disable usage of mutex * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, upper 32bit of a 64bit * physical address of mutex * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, lower 32bit of a 64bit * physical address of mutex * a3-6 Not used * a7 Hypervisor Client ID register * * Have config return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 Preserved * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, upper 32bit of a 64bit * physical address of mutex * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, lower 32bit of a 64bit * physical address of mutex * a3-7 Preserved * * Error return register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL Physical address not available * OPTEE_SMC_RETURN_EBADADDR Bad supplied physical address * OPTEE_SMC_RETURN_EBADCMD Unsupported value in a1 * a1-7 Preserved */ #define OPTEE_SMC_L2CC_MUTEX_GET_ADDR U(0) #define OPTEE_SMC_L2CC_MUTEX_SET_ADDR U(1) #define OPTEE_SMC_L2CC_MUTEX_ENABLE U(2) #define OPTEE_SMC_L2CC_MUTEX_DISABLE U(3) #define OPTEE_SMC_FUNCID_L2CC_MUTEX U(8) #define OPTEE_SMC_L2CC_MUTEX \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_L2CC_MUTEX) /* * Exchanges capabilities between normal world and secure world * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES * a1 bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_* * a2-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* * a2 The maximum secure world notification number * a3 Bit[7:0]: Number of parameters needed for RPC to be supplied * as the second MSG arg struct for * OPTEE_SMC_CALL_WITH_ARG * Bit[31:8]: Reserved (MBZ) * a3-7 Preserved * * Error return register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world * a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_* * a2-7 Preserved */ /* Normal world works as a uniprocessor system */ #define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR BIT(0) /* Secure world has reserved shared memory for normal world to use */ #define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0) /* Secure world can communicate via previously unregistered shared memory */ #define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1) /* * Secure world supports commands "register/unregister shared memory", * secure world accepts command buffers located in any parts of non-secure RAM */ #define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2) /* Secure world is built with virtualization support */ #define OPTEE_SMC_SEC_CAP_VIRTUALIZATION BIT(3) /* Secure world supports Shared Memory with a NULL reference */ #define OPTEE_SMC_SEC_CAP_MEMREF_NULL BIT(4) /* Secure world supports asynchronous notification of normal world */ #define OPTEE_SMC_SEC_CAP_ASYNC_NOTIF BIT(5) /* Secure world supports pre-allocating RPC arg struct */ #define OPTEE_SMC_SEC_CAP_RPC_ARG BIT(6) #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES U(9) #define OPTEE_SMC_EXCHANGE_CAPABILITIES \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES) /* * Disable and empties cache of shared memory objects * * Secure world can cache frequently used shared memory objects, for * example objects used as RPC arguments. When secure world is idle this * function returns one shared memory reference to free. To disable the * cache and free all cached objects this function has to be called until * it returns OPTEE_SMC_RETURN_ENOTAVAIL. * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 Upper 32 bits of a 64-bit Shared memory cookie * a2 Lower 32 bits of a 64-bit Shared memory cookie * a3-7 Preserved * * Cache empty return register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL * a1-7 Preserved * * Not idle return register usage: * a0 OPTEE_SMC_RETURN_EBUSY * a1-7 Preserved */ #define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE U(10) #define OPTEE_SMC_DISABLE_SHM_CACHE \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE) /* * Enable cache of shared memory objects * * Secure world can cache frequently used shared memory objects, for * example objects used as RPC arguments. When secure world is idle this * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned. * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1-7 Preserved * * Not idle return register usage: * a0 OPTEE_SMC_RETURN_EBUSY * a1-7 Preserved */ #define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE U(11) #define OPTEE_SMC_ENABLE_SHM_CACHE \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE) /* * Release of secondary cores * * OP-TEE in secure world is in charge of the release process of secondary * cores. The Rich OS issue the this request to ask OP-TEE to boot up the * secondary cores, go through the OP-TEE per-core initialization, and then * switch to the Non-seCure world with the Rich OS provided entry address. * The secondary cores enter Non-Secure world in SVC mode, with Thumb, FIQ, * IRQ and Abort bits disabled. * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_BOOT_SECONDARY * a1 Index of secondary core to boot * a2 Upper 32 bits of a 64-bit Non-Secure world entry physical address * a3 Lower 32 bits of a 64-bit Non-Secure world entry physical address * a4-7 Not used * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1-7 Preserved * * Error return: * a0 OPTEE_SMC_RETURN_EBADCMD Core index out of range * a1-7 Preserved * * Not idle return register usage: * a0 OPTEE_SMC_RETURN_EBUSY * a1-7 Preserved */ #define OPTEE_SMC_FUNCID_BOOT_SECONDARY U(12) #define OPTEE_SMC_BOOT_SECONDARY \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_BOOT_SECONDARY) /* * Inform OP-TEE about a new virtual machine * * Hypervisor issues this call during virtual machine (guest) creation. * OP-TEE records client id of new virtual machine and prepares * to receive requests from it. This call is available only if OP-TEE * was built with virtualization support. * * Call requests usage: * a0 SMC Function ID, OPTEE_SMC_VM_CREATED * a1 Hypervisor Client ID of newly created virtual machine * a2-6 Not used * a7 Hypervisor Client ID register. Must be 0, because only hypervisor * can issue this call * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1-7 Preserved * * Error return: * a0 OPTEE_SMC_RETURN_ENOTAVAIL OP-TEE have no resources for * another VM * a1-7 Preserved * */ #define OPTEE_SMC_FUNCID_VM_CREATED U(13) #define OPTEE_SMC_VM_CREATED \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_VM_CREATED) /* * Inform OP-TEE about shutdown of a virtual machine * * Hypervisor issues this call during virtual machine (guest) destruction. * OP-TEE will clean up all resources associated with this VM. This call is * available only if OP-TEE was built with virtualization support. * * Call requests usage: * a0 SMC Function ID, OPTEE_SMC_VM_DESTROYED * a1 Hypervisor Client ID of virtual machine being shut down * a2-6 Not used * a7 Hypervisor Client ID register. Must be 0, because only hypervisor * can issue this call * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1-7 Preserved * */ #define OPTEE_SMC_FUNCID_VM_DESTROYED U(14) #define OPTEE_SMC_VM_DESTROYED \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_VM_DESTROYED) /* * Query OP-TEE about number of supported threads * * Normal World OS or Hypervisor issues this call to find out how many * threads OP-TEE supports. That is how many standard calls can be issued * in parallel before OP-TEE will return OPTEE_SMC_RETURN_ETHREAD_LIMIT. * * Call requests usage: * a0 SMC Function ID, OPTEE_SMC_GET_THREAD_COUNT * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 Number of threads * a2-7 Preserved * * Error return: * a0 OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Requested call is not implemented * a1-7 Preserved */ #define OPTEE_SMC_FUNCID_GET_THREAD_COUNT U(15) #define OPTEE_SMC_GET_THREAD_COUNT \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_THREAD_COUNT) /* * Inform OP-TEE that normal world is able to receive asynchronous * notifications. * * Call requests usage: * a0 SMC Function ID, OPTEE_SMC_ENABLE_ASYNC_NOTIF * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1-7 Preserved * * Not supported return register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL * a1-7 Preserved */ #define OPTEE_SMC_FUNCID_ENABLE_ASYNC_NOTIF 16 #define OPTEE_SMC_ENABLE_ASYNC_NOTIF \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_ASYNC_NOTIF) /* * Retrieve a value of notifications pending since the last call of this * function. * * OP-TEE keeps a record of all posted values. When an interrupt is * received which indicates that there are posted values this function * should be called until all pended values have been retrieved. When a * value is retrieved, it's cleared from the record in secure world. * * It is expected that this function is called from an interrupt handler * in normal world. * * Call requests usage: * a0 SMC Function ID, OPTEE_SMC_GET_ASYNC_NOTIF_VALUE * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 value * a2 Bit[0]: OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID if the value in a1 is * valid, else 0 if no values were pending * a2 Bit[1]: OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING if another value is * pending, else 0. * Bit[31:2]: MBZ * a3-7 Preserved * * Not supported return register usage: * a0 OPTEE_SMC_RETURN_ENOTAVAIL * a1-7 Preserved */ #define OPTEE_SMC_ASYNC_NOTIF_VALID BIT(0) #define OPTEE_SMC_ASYNC_NOTIF_PENDING BIT(1) /* * Notification that OP-TEE expects a yielding call to do some bottom half * work in a driver. */ #define OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF 0 #define OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE 17 #define OPTEE_SMC_GET_ASYNC_NOTIF_VALUE \ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_ASYNC_NOTIF_VALUE) /* See OPTEE_SMC_CALL_WITH_RPC_ARG above */ #define OPTEE_SMC_FUNCID_CALL_WITH_RPC_ARG U(18) /* See OPTEE_SMC_CALL_WITH_REGD_ARG above */ #define OPTEE_SMC_FUNCID_CALL_WITH_REGD_ARG U(19) /* * Resume from RPC (for example after processing a foreign interrupt) * * Call register usage: * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC * a1-3 Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned * OPTEE_SMC_RETURN_RPC in a0 * * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above. * * Possible return values * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this * function. * OPTEE_SMC_RETURN_OK Original call completed, result * updated in the previously supplied. * struct optee_msg_arg * OPTEE_SMC_RETURN_RPC Call suspended by RPC call to normal * world. * OPTEE_SMC_RETURN_ERESUME Resume failed, the opaque resume * information was corrupt. */ #define OPTEE_SMC_FUNCID_RETURN_FROM_RPC U(3) #define OPTEE_SMC_CALL_RETURN_FROM_RPC \ OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC) #define OPTEE_SMC_RETURN_RPC_PREFIX_MASK U(0xFFFF0000) #define OPTEE_SMC_RETURN_RPC_PREFIX U(0xFFFF0000) #define OPTEE_SMC_RETURN_RPC_FUNC_MASK U(0x0000FFFF) #define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \ ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK) #define OPTEE_SMC_RPC_VAL(func) ((func) | OPTEE_SMC_RETURN_RPC_PREFIX) /* * Allocate memory for RPC parameter passing. The memory is used to hold a * struct optee_msg_arg. * * "Call" register usage: * a0 This value, OPTEE_SMC_RETURN_RPC_ALLOC * a1 Size in bytes of required argument memory * a2 Not used * a3 Resume information, must be preserved * a4-5 Not used * a6-7 Resume information, must be preserved * * "Return" register usage: * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. * a1 Upper 32 bits of 64-bit physical pointer to allocated * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't * be allocated. * a2 Lower 32 bits of 64-bit physical pointer to allocated * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't * be allocated * a3 Preserved * a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing * the memory or doing an RPC * a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing * the memory or doing an RPC * a6-7 Preserved */ #define OPTEE_SMC_RPC_FUNC_ALLOC U(0) #define OPTEE_SMC_RETURN_RPC_ALLOC \ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC) /* * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC * * "Call" register usage: * a0 This value, OPTEE_SMC_RETURN_RPC_FREE * a1 Upper 32 bits of 64-bit shared memory cookie belonging to this * argument memory * a2 Lower 32 bits of 64-bit shared memory cookie belonging to this * argument memory * a3-7 Resume information, must be preserved * * "Return" register usage: * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. * a1-2 Not used * a3-7 Preserved */ #define OPTEE_SMC_RPC_FUNC_FREE U(2) #define OPTEE_SMC_RETURN_RPC_FREE \ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE) /* * Deliver a foreign interrupt in normal world. * * "Call" register usage: * a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR * a1-7 Resume information, must be preserved * * "Return" register usage: * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. * a1-7 Preserved */ #define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR U(4) #define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR) /* * Do an RPC request. The supplied struct optee_msg_arg tells which * request to do and the parameters for the request. The following fields * are used (the rest are unused): * - cmd the Request ID * - ret return value of the request, filled in by normal world * - num_params number of parameters for the request * - params the parameters * - param_attrs attributes of the parameters * * "Call" register usage: * a0 OPTEE_SMC_RETURN_RPC_CMD * a1 Upper 32 bits of a 64-bit Shared memory cookie holding a * struct optee_msg_arg, must be preserved, only the data should * be updated * a2 Lower 32 bits of a 64-bit Shared memory cookie holding a * struct optee_msg_arg, must be preserved, only the data should * be updated * a3-7 Resume information, must be preserved * * "Return" register usage: * a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC. * a1-2 Not used * a3-7 Preserved */ #define OPTEE_SMC_RPC_FUNC_CMD U(5) #define OPTEE_SMC_RETURN_RPC_CMD \ OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD) /* Returned in a0 */ #define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION U(0xFFFFFFFF) /* Returned in a0 only from Trusted OS functions */ #define OPTEE_SMC_RETURN_OK U(0x0) #define OPTEE_SMC_RETURN_ETHREAD_LIMIT U(0x1) #define OPTEE_SMC_RETURN_EBUSY U(0x2) #define OPTEE_SMC_RETURN_ERESUME U(0x3) #define OPTEE_SMC_RETURN_EBADADDR U(0x4) #define OPTEE_SMC_RETURN_EBADCMD U(0x5) #define OPTEE_SMC_RETURN_ENOMEM U(0x6) #define OPTEE_SMC_RETURN_ENOTAVAIL U(0x7) #define OPTEE_SMC_RETURN_IS_RPC(ret) \ (((ret) != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION) && \ ((((ret) & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) == \ OPTEE_SMC_RETURN_RPC_PREFIX))) #endif /* __SM_OPTEE_SMC_H */ optee_os-4.3.0/core/arch/arm/include/sm/pm.h000066400000000000000000000036711464416617300206310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __SM_PM_H #define __SM_PM_H #include #include struct sm_pm_ctx { uint32_t sp; paddr_t cpu_resume_addr; uint32_t suspend_regs[16]; }; /* suspend/resume core functions */ void sm_pm_cpu_suspend_save(struct sm_pm_ctx *ptr, uint32_t sp); void sm_pm_cpu_do_suspend(uint32_t *ptr); void sm_pm_cpu_do_resume(void); /* * Exported to platform suspend, arg will be passed to fn as r0 * Return value: 0 - cpu resumed from suspended state. * -1 - cpu not suspended. */ int sm_pm_cpu_suspend(uint32_t arg, int (*fn)(uint32_t)); #endif optee_os-4.3.0/core/arch/arm/include/sm/psci.h000066400000000000000000000063071464416617300211520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2023, Linaro Limited */ #ifndef __SM_PSCI_H #define __SM_PSCI_H #include #include #include #define PSCI_VERSION_0_2 U(0x00000002) #define PSCI_VERSION_1_0 U(0x00010000) #define PSCI_VERSION_1_1 U(0x00010001) #define PSCI_VERSION U(0x84000000) #define PSCI_CPU_SUSPEND U(0x84000001) #define PSCI_CPU_OFF U(0x84000002) #define PSCI_CPU_ON U(0x84000003) #define PSCI_CPU_ON_SMC64 (PSCI_CPU_ON | U(0x40000000)) #define PSCI_AFFINITY_INFO U(0x84000004) #define PSCI_MIGRATE U(0x84000005) #define PSCI_MIGRATE_INFO_TYPE U(0x84000006) #define PSCI_MIGRATE_INFO_UP_CPU U(0x84000007) #define PSCI_SYSTEM_OFF U(0x84000008) #define PSCI_SYSTEM_RESET U(0x84000009) #define PSCI_PSCI_FEATURES U(0x8400000a) #define PSCI_CPU_FREEZE U(0x8400000b) #define PSCI_CPU_DEFAULT_SUSPEND U(0x8400000c) #define PSCI_NODE_HW_STATE U(0x8400000d) #define PSCI_SYSTEM_SUSPEND U(0x8400000e) #define PSCI_PSCI_SET_SUSPEND_MODE U(0x8400000f) #define PSCI_FN_STAT_RESIDENCY U(0x84000010) #define PSCI_FN_STAT_COUNT U(0x84000011) #define PSCI_SYSTEM_RESET2 U(0x84000012) #define PSCI_MEM_PROTECT U(0x84000013) #define PSCI_MEM_PROTECT_CHECK_RANGE U(0x84000014) #define PSCI_NUM_CALLS U(21) #define PSCI_AFFINITY_LEVEL_ON U(0) #define PSCI_AFFINITY_LEVEL_OFF U(1) #define PSCI_AFFINITY_LEVEL_ON_PENDING U(2) #define PSCI_POWER_STATE_ID_MASK U(0xffff) #define PSCI_POWER_STATE_ID_SHIFT U(0) #define PSCI_POWER_STATE_TYPE_SHIFT U(16) #define PSCI_POWER_STATE_TYPE_MASK BIT32(PSCI_POWER_STATE_TYPE_SHIFT) #define PSCI_POWER_STATE_AFFL_SHIFT U(24) #define PSCI_POWER_STATE_AFFL_MASK SHIFT_U32(0x3, \ PSCI_POWER_STATE_AFFL_SHIFT) #define PSCI_POWER_STATE_TYPE_STANDBY U(0) #define PSCI_POWER_STATE_TYPE_POWER_DOWN U(1) #define PSCI_RET_SUCCESS (0) #define PSCI_RET_NOT_SUPPORTED (-1) #define PSCI_RET_INVALID_PARAMETERS (-2) #define PSCI_RET_DENIED (-3) #define PSCI_RET_ALREADY_ON (-4) #define PSCI_RET_ON_PENDING (-5) #define PSCI_RET_INTERNAL_FAILURE (-6) #define PSCI_RET_NOT_PRESENT (-7) #define PSCI_RET_DISABLED (-8) #define PSCI_RET_INVALID_ADDRESS (-9) uint32_t psci_version(void); int psci_cpu_suspend(uint32_t power_state, uintptr_t entry, uint32_t context_id, struct sm_nsec_ctx *nsec); int psci_cpu_off(void); int psci_cpu_on(uint32_t cpu_id, uint32_t entry, uint32_t context_id); int psci_affinity_info(uint32_t affinity, uint32_t lowest_affnity_level); int psci_migrate(uint32_t cpu_id); int psci_migrate_info_type(void); int psci_migrate_info_up_cpu(void); void psci_system_off(void); void psci_system_reset(void); int psci_features(uint32_t psci_fid); int psci_system_reset2(uint32_t reset_type, uint32_t cookie); int psci_mem_protect(uint32_t enable); int psci_mem_chk_range(paddr_t base, size_t length); int psci_node_hw_state(uint32_t cpu_id, uint32_t power_level); int psci_system_suspend(uintptr_t entry, uint32_t context_id, struct sm_nsec_ctx *nsec); int psci_stat_residency(uint32_t cpu_id, uint32_t power_state); int psci_stat_count(uint32_t cpu_id, uint32_t power_state); void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec); void psci_armv7_cpu_off(void); #endif /* __SM_PSCI_H */ optee_os-4.3.0/core/arch/arm/include/sm/sm.h000066400000000000000000000057451464416617300206400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __SM_SM_H #define __SM_SM_H #ifndef __ASSEMBLER__ #include #include struct sm_unbanked_regs { uint32_t usr_sp; uint32_t usr_lr; uint32_t irq_spsr; uint32_t irq_sp; uint32_t irq_lr; uint32_t fiq_spsr; uint32_t fiq_sp; uint32_t fiq_lr; /* * Note that fiq_r{8-12} are not saved here. Instead thread_fiq_handler * preserves r{8-12}. */ uint32_t svc_spsr; uint32_t svc_sp; uint32_t svc_lr; uint32_t abt_spsr; uint32_t abt_sp; uint32_t abt_lr; uint32_t und_spsr; uint32_t und_sp; uint32_t und_lr; #ifdef CFG_SM_NO_CYCLE_COUNTING uint32_t pmcr; #endif #ifdef CFG_FTRACE_SUPPORT uint32_t cntkctl; uint32_t pad; #endif }; struct sm_nsec_ctx { struct sm_unbanked_regs ub_regs; uint32_t r8; uint32_t r9; uint32_t r10; uint32_t r11; uint32_t r12; uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r4; uint32_t r5; uint32_t r6; uint32_t r7; /* return state */ uint32_t mon_lr; uint32_t mon_spsr; }; struct sm_sec_ctx { struct sm_unbanked_regs ub_regs; uint32_t r0; uint32_t r1; uint32_t r2; uint32_t r3; uint32_t r4; uint32_t r5; uint32_t r6; uint32_t r7; /* return state */ uint32_t mon_lr; uint32_t mon_spsr; }; struct sm_ctx { #ifndef CFG_SM_NO_CYCLE_COUNTING uint32_t pad; #endif struct sm_sec_ctx sec; #ifdef CFG_SM_NO_CYCLE_COUNTING uint32_t pad; #endif struct sm_nsec_ctx nsec; }; /* * The secure monitor reserves space at top of stack_tmp to hold struct * sm_ctx. */ #define SM_STACK_TMP_RESERVE_SIZE sizeof(struct sm_ctx) /* Returns storage location of non-secure context for current CPU */ struct sm_nsec_ctx *sm_get_nsec_ctx(void); /* Returns stack pointer to use in monitor mode for current CPU */ void *sm_get_sp(void); /* * Initializes secure monitor, must be called by each CPU */ void sm_init(vaddr_t stack_pointer); enum sm_handler_ret { SM_HANDLER_SMC_HANDLED = 0, SM_HANDLER_PENDING_SMC, }; /* * Returns whether SMC was handled from platform handler in secure monitor * or if it shall reach OP-TEE core . */ enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx); void sm_save_unbanked_regs(struct sm_unbanked_regs *regs); void sm_restore_unbanked_regs(struct sm_unbanked_regs *regs); /* * These function return to secure monitor by SMC instead of a normal * function return. */ void vector_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); void vector_fast_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); void vector_fiq_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); #endif /*!__ASSEMBLER__*/ /* 32 bit return value for sm_from_nsec() */ #define SM_EXIT_TO_NON_SECURE 0 #define SM_EXIT_TO_SECURE 1 #endif /*__SM_SM_H*/ optee_os-4.3.0/core/arch/arm/include/sm/std_smc.h000066400000000000000000000024411464416617300216430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2023, Linaro Limited */ #ifndef __SM_STD_SMC_H__ #define __SM_STD_SMC_H__ #include /* SMC function IDs for Standard Service queries */ #define ARM_STD_SVC_CALL_COUNT 0x8400ff00 #define ARM_STD_SVC_UID 0x8400ff01 /* 0x8400ff02 is reserved */ #define ARM_STD_SVC_VERSION 0x8400ff03 #define ARM_SMCCC_VERSION 0x80000000 #define ARM_SMCCC_ARCH_FEATURES 0x80000001 #define ARM_SMCCC_ARCH_SOC_ID 0x80000002 #define ARM_SMCCC_ARCH_WORKAROUND_1 0x80008000 #define ARM_SMCCC_ARCH_WORKAROUND_2 0x80007fff #define ARM_SMCCC_RET_SUCCESS 0 #define ARM_SMCCC_RET_NOT_SUPPORTED 0xffffffff #define ARM_SMCCC_RET_NOT_REQUIRED 0xfffffffe #define ARM_SMCCC_RET_INVALID_PARAMETER 0xfffffffd #define SMCCC_V_1_0 0x10000 #define SMCCC_V_1_1 0x10001 #define SMCCC_V_1_2 0x10002 /* ARM Standard Service Calls version numbers */ #define STD_SVC_VERSION_MAJOR 0x0 #define STD_SVC_VERSION_MINOR 0x1 /* The macros below are used to identify PSCI calls from the SMC function ID */ #define PSCI_FID_MASK 0xffe0u #define PSCI_FID_VALUE 0u #define is_psci_fid(_fid) \ (((_fid) & PSCI_FID_MASK) == PSCI_FID_VALUE) void smc_std_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec); #endif optee_os-4.3.0/core/arch/arm/include/sm/teesmc_opteed.h000066400000000000000000000071211464416617300230270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __SM_TEESMC_OPTEED_H #define __SM_TEESMC_OPTEED_H /* * This file specify SMC function IDs used when returning from TEE to the * secure monitor. * * All SMC Function IDs indicates SMC32 Calling Convention but will carry * full 64 bit values in the argument registers if invoked from Aarch64 * mode. This violates the SMC Calling Convention, but since this * convention only coveres API towards Normwal World it's something that * only concerns the OP-TEE Dispatcher in ARM Trusted Firmware and OP-TEE * OS at Secure EL1. */ /* * Issued when returning from initial entry. * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ENTRY_DONE * r1/x1 Pointer to entry vector */ #define TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 #define TEESMC_OPTEED_RETURN_ENTRY_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE) /* * Issued when returning from "cpu_on" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ON_DONE * r1/x1 0 on success and anything else to indicate error condition */ #define TEESMC_OPTEED_FUNCID_RETURN_ON_DONE 1 #define TEESMC_OPTEED_RETURN_ON_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ON_DONE) /* * Issued when returning from "cpu_off" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_OFF_DONE * r1/x1 0 on success and anything else to indicate error condition */ #define TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE 2 #define TEESMC_OPTEED_RETURN_OFF_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE) /* * Issued when returning from "cpu_suspend" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SUSPEND_DONE * r1/x1 0 on success and anything else to indicate error condition */ #define TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 #define TEESMC_OPTEED_RETURN_SUSPEND_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE) /* * Issued when returning from "cpu_resume" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_RESUME_DONE * r1/x1 0 on success and anything else to indicate error condition */ #define TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE 4 #define TEESMC_OPTEED_RETURN_RESUME_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE) /* * Issued when returning from "std_smc" or "fast_smc" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_CALL_DONE * r1-4/x1-4 Return value 0-3 which will passed to normal world in * r0-3/x0-3 */ #define TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE 5 #define TEESMC_OPTEED_RETURN_CALL_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE) /* * Issued when returning from "fiq" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_FIQ_DONE */ #define TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE 6 #define TEESMC_OPTEED_RETURN_FIQ_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE) /* * Issued when returning from "system_off" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE */ #define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 #define TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) /* * Issued when returning from "system_reset" vector * * Register usage: * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE */ #define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 #define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \ TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) #endif /*__SM_TEESMC_OPTEED_H*/ optee_os-4.3.0/core/arch/arm/include/sm/teesmc_opteed_macros.h000066400000000000000000000005361464416617300243760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __SM_TEESMC_OPTEED_MACROS_H #define __SM_TEESMC_OPTEED_MACROS_H #define TEESMC_OPTEED_RV(func_num) \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_TRUSTED_OS_OPTEED, (func_num)) #endif /*__SM_TEESMC_OPTEED_MACROS_H*/ optee_os-4.3.0/core/arch/arm/include/sm/watchdog_smc.h000066400000000000000000000045671464416617300226640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) STMicroelectronics 2023 */ #ifndef __SM_WATCHDOG_SMC_H #define __SM_WATCHDOG_SMC_H /* * This file describes the secure watchdog management service. * It exposes the SMC supported commands. * We're following ARM SMC Calling Convention as specified in * https://developer.arm.com/documentation/den0028. */ /* * Overall global call for watchdog interface * Call requests usage: * a0 [in] SMC Function ID, CFG_WDT_SM_HANDLER_ID * [out] PSCI error code return * a1 [in] Watchdog command (one of SMCWD_*) * [out] Depends on watchdog command (input a1) * a2 [in/out] Depends on watchdog command (input a1) * a3-6 [in/out] Not used * a7 [in/out] Hypervisor Client ID register */ /* Watchdog supported commands */ #define SMCWD_INIT 0 #define SMCWD_SET_TIMEOUT 1 #define SMCWD_ENABLE 2 #define SMCWD_PET 3 #define SMCWD_GET_TIMELEFT 4 /* * Command SMCWD_INIT : Watchdog initialization * [in] a1 Set to SMCWD_INIT * [out] a1 The minimal timeout value in seconds supported * a2 The maximum timeout value in seconds supported * Return codes: * PSCI_RET_SUCCESS - Command success * PSCI_RET_INTERNAL_FAILURE - Initialization failure * * Command SMCWD_SET_TIMEOUT : Watchdog set timeout * [in] a1 Set to SMCWD_SET_TIMEOUT * a2 The timeout value in seconds to set * Return codes: * PSCI_RET_SUCCESS - Command success * PSCI_RET_INVALID_PARAMETERS - Incorrect input param * * Command SMCWD_ENABLE : Watchdog enable * [in] a1 Set to SMCWD_ENABLE * a2 Set to 0 to stop the watchdog, 1 to enable it * Return codes: * PSCI_RET_SUCCESS - Command success * PSCI_RET_INVALID_PARAMETERS - Incorrect input param * * Command SMCWD_PET : Ping the watchdog for refresh * [in] a1 Set to SMCWD_PET * Return codes: * PSCI_RET_SUCCESS - Command success * PSCI_RET_DISABLED - The watchdog is not enabled * * Command SMCWD_GET_TIMELEFT : Get time left * [in] a1 Set to SMCWD_GET_TIMELEFT * [out] a1 The timeout value in seconds before watchdog expires * Return codes: * PSCI_RET_SUCCESS - Command success * PSCI_RET_DISABLED - The watchdog is not enabled * PSCI_RET_NOT_SUPPORTED - Function not supported * * Other commands * [in] a1 Other values * Return codes: * PSCI_RET_NOT_SUPPORTED - Function not supported * * a3-6 Not used * a7 Hypervisor Client ID register */ #endif /* __SM_WATCHDOG_SMC_H */ optee_os-4.3.0/core/arch/arm/include/smccc.h000066400000000000000000000015421464416617300206610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __SMCCC_H #define __SMCCC_H /* * Describes features of SMC Calling Convention from v1.1 * See also https://developer.arm.com/-/media/developer/pdf/ARM_DEN_0070A_Firmware_interfaces_for_mitigating_CVE-2017-5715.pdf */ /* * Retrieve the implemented version of the SMC Calling Convention * Mandatory from SMCCC v1.1 * Optional in SMCCC v1.0 */ #define SMCCC_VERSION 0x80000000 /* * Determine the availability and capability of Arm Architecture Service * functions. * Mandatory from SMCCC v1.1 * Optional for SMCCC v1.0 */ #define SMCCC_ARCH_FEATURES 0x80000001 /* * Execute the mitigation for CVE-2017-5715 on the calling PE * Optional from SMCCC v1.1 * Not supported in SMCCC v1.0 */ #define SMCCC_ARCH_WORKAROUND_1 0x80008000 #endif /*__SMCCC_H*/ optee_os-4.3.0/core/arch/arm/include/tee/000077500000000000000000000000001464416617300201735ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/include/tee/entry_fast.h000066400000000000000000000021621464416617300225230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_ENTRY_FAST_H #define __TEE_ENTRY_FAST_H #include /* These functions are overridable by the specific target */ void tee_entry_get_api_call_count(struct thread_smc_args *args); void tee_entry_get_api_uuid(struct thread_smc_args *args); void tee_entry_get_api_revision(struct thread_smc_args *args); void tee_entry_get_os_uuid(struct thread_smc_args *args); void tee_entry_get_os_revision(struct thread_smc_args *args); /* * Returns the number of calls recognized by tee_entry(). Used by the * specific target to calculate the total number of supported calls when * overriding tee_entry_get_api_call_count(). */ size_t tee_entry_generic_get_api_call_count(void); /* * Fast call entry, __weak, overridable. If overridden should call * __tee_entry_fast() at the end in order to handle the standard functions. */ void tee_entry_fast(struct thread_smc_args *args); void __tee_entry_fast(struct thread_smc_args *args); #endif /* __TEE_ENTRY_FAST_H */ optee_os-4.3.0/core/arch/arm/kernel/000077500000000000000000000000001464416617300172535ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/kernel/abort.c000066400000000000000000000361701464416617300205350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include enum fault_type { FAULT_TYPE_USER_MODE_PANIC, FAULT_TYPE_USER_MODE_VFP, FAULT_TYPE_PAGEABLE, FAULT_TYPE_IGNORE, }; #ifdef CFG_UNWIND #ifdef ARM32 /* * Kernel or user mode unwind (32-bit execution state). */ static void __print_stack_unwind(struct abort_info *ai) { struct unwind_state_arm32 state = { }; uint32_t mode = ai->regs->spsr & CPSR_MODE_MASK; uint32_t sp = 0; uint32_t lr = 0; assert(!abort_is_user_exception(ai)); if (mode == CPSR_MODE_SYS) { sp = ai->regs->usr_sp; lr = ai->regs->usr_lr; } else { sp = read_mode_sp(mode); lr = read_mode_lr(mode); } memset(&state, 0, sizeof(state)); state.registers[0] = ai->regs->r0; state.registers[1] = ai->regs->r1; state.registers[2] = ai->regs->r2; state.registers[3] = ai->regs->r3; state.registers[4] = ai->regs->r4; state.registers[5] = ai->regs->r5; state.registers[6] = ai->regs->r6; state.registers[7] = ai->regs->r7; state.registers[8] = ai->regs->r8; state.registers[9] = ai->regs->r9; state.registers[10] = ai->regs->r10; state.registers[11] = ai->regs->r11; state.registers[13] = sp; state.registers[14] = lr; state.registers[15] = ai->pc; print_stack_arm32(&state, thread_stack_start(), thread_stack_size()); } #endif /* ARM32 */ #ifdef ARM64 /* Kernel mode unwind (64-bit execution state) */ static void __print_stack_unwind(struct abort_info *ai) { struct unwind_state_arm64 state = { .pc = ai->regs->elr, .fp = ai->regs->x29, }; print_stack_arm64(&state, thread_stack_start(), thread_stack_size()); } #endif /*ARM64*/ #else /* CFG_UNWIND */ static void __print_stack_unwind(struct abort_info *ai __unused) { } #endif /* CFG_UNWIND */ static __maybe_unused const char *abort_type_to_str(uint32_t abort_type) { if (abort_type == ABORT_TYPE_DATA) return "data"; if (abort_type == ABORT_TYPE_PREFETCH) return "prefetch"; return "undef"; } static __maybe_unused const char *fault_to_str(uint32_t abort_type, uint32_t fault_descr) { /* fault_descr is only valid for data or prefetch abort */ if (abort_type != ABORT_TYPE_DATA && abort_type != ABORT_TYPE_PREFETCH) return ""; switch (core_mmu_get_fault_type(fault_descr)) { case CORE_MMU_FAULT_ALIGNMENT: return " (alignment fault)"; case CORE_MMU_FAULT_TRANSLATION: return " (translation fault)"; case CORE_MMU_FAULT_READ_PERMISSION: return " (read permission fault)"; case CORE_MMU_FAULT_WRITE_PERMISSION: return " (write permission fault)"; case CORE_MMU_FAULT_TAG_CHECK: return " (tag check fault)"; default: return ""; } } static __maybe_unused void __print_abort_info(struct abort_info *ai __maybe_unused, const char *ctx __maybe_unused) { __maybe_unused size_t core_pos = 0; #ifdef ARM32 uint32_t mode = ai->regs->spsr & CPSR_MODE_MASK; __maybe_unused uint32_t sp = 0; __maybe_unused uint32_t lr = 0; if (mode == CPSR_MODE_USR || mode == CPSR_MODE_SYS) { sp = ai->regs->usr_sp; lr = ai->regs->usr_lr; core_pos = thread_get_tsd()->abort_core; } else { sp = read_mode_sp(mode); lr = read_mode_lr(mode); core_pos = get_core_pos(); } #endif /*ARM32*/ #ifdef ARM64 if (abort_is_user_exception(ai)) core_pos = thread_get_tsd()->abort_core; else core_pos = get_core_pos(); #endif /*ARM64*/ EMSG_RAW(""); if (IS_ENABLED(CFG_MEMTAG)) EMSG_RAW("%s %s-abort at address 0x%" PRIxVA " [tagged 0x%" PRIxVA "]%s", ctx, abort_type_to_str(ai->abort_type), memtag_strip_tag_vaddr((void *)ai->va), ai->va, fault_to_str(ai->abort_type, ai->fault_descr)); else EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "%s", ctx, abort_type_to_str(ai->abort_type), ai->va, fault_to_str(ai->abort_type, ai->fault_descr)); #ifdef ARM32 EMSG_RAW(" fsr 0x%08x ttbr0 0x%08x ttbr1 0x%08x cidr 0x%X", ai->fault_descr, read_ttbr0(), read_ttbr1(), read_contextidr()); EMSG_RAW(" cpu #%zu cpsr 0x%08x", core_pos, ai->regs->spsr); EMSG_RAW(" r0 0x%08x r4 0x%08x r8 0x%08x r12 0x%08x", ai->regs->r0, ai->regs->r4, ai->regs->r8, ai->regs->ip); EMSG_RAW(" r1 0x%08x r5 0x%08x r9 0x%08x sp 0x%08x", ai->regs->r1, ai->regs->r5, ai->regs->r9, sp); EMSG_RAW(" r2 0x%08x r6 0x%08x r10 0x%08x lr 0x%08x", ai->regs->r2, ai->regs->r6, ai->regs->r10, lr); EMSG_RAW(" r3 0x%08x r7 0x%08x r11 0x%08x pc 0x%08x", ai->regs->r3, ai->regs->r7, ai->regs->r11, ai->pc); #endif /*ARM32*/ #ifdef ARM64 EMSG_RAW(" esr 0x%08x ttbr0 0x%08" PRIx64 " ttbr1 0x%08" PRIx64 " cidr 0x%X", ai->fault_descr, read_ttbr0_el1(), read_ttbr1_el1(), read_contextidr_el1()); EMSG_RAW(" cpu #%zu cpsr 0x%08x", core_pos, (uint32_t)ai->regs->spsr); EMSG_RAW(" x0 %016" PRIx64 " x1 %016" PRIx64, ai->regs->x0, ai->regs->x1); EMSG_RAW(" x2 %016" PRIx64 " x3 %016" PRIx64, ai->regs->x2, ai->regs->x3); EMSG_RAW(" x4 %016" PRIx64 " x5 %016" PRIx64, ai->regs->x4, ai->regs->x5); EMSG_RAW(" x6 %016" PRIx64 " x7 %016" PRIx64, ai->regs->x6, ai->regs->x7); EMSG_RAW(" x8 %016" PRIx64 " x9 %016" PRIx64, ai->regs->x8, ai->regs->x9); EMSG_RAW(" x10 %016" PRIx64 " x11 %016" PRIx64, ai->regs->x10, ai->regs->x11); EMSG_RAW(" x12 %016" PRIx64 " x13 %016" PRIx64, ai->regs->x12, ai->regs->x13); EMSG_RAW(" x14 %016" PRIx64 " x15 %016" PRIx64, ai->regs->x14, ai->regs->x15); EMSG_RAW(" x16 %016" PRIx64 " x17 %016" PRIx64, ai->regs->x16, ai->regs->x17); EMSG_RAW(" x18 %016" PRIx64 " x19 %016" PRIx64, ai->regs->x18, ai->regs->x19); EMSG_RAW(" x20 %016" PRIx64 " x21 %016" PRIx64, ai->regs->x20, ai->regs->x21); EMSG_RAW(" x22 %016" PRIx64 " x23 %016" PRIx64, ai->regs->x22, ai->regs->x23); EMSG_RAW(" x24 %016" PRIx64 " x25 %016" PRIx64, ai->regs->x24, ai->regs->x25); EMSG_RAW(" x26 %016" PRIx64 " x27 %016" PRIx64, ai->regs->x26, ai->regs->x27); EMSG_RAW(" x28 %016" PRIx64 " x29 %016" PRIx64, ai->regs->x28, ai->regs->x29); EMSG_RAW(" x30 %016" PRIx64 " elr %016" PRIx64, ai->regs->x30, ai->regs->elr); EMSG_RAW(" sp_el0 %016" PRIx64, ai->regs->sp_el0); #endif /*ARM64*/ } /* * Print abort info and (optionally) stack dump to the console * @ai kernel-mode abort info. * @stack_dump true to show a stack trace */ static void __abort_print(struct abort_info *ai, bool stack_dump) { assert(!abort_is_user_exception(ai)); __print_abort_info(ai, "Core"); if (stack_dump) { trace_printf_helper_raw(TRACE_ERROR, true, "TEE load address @ %#"PRIxVA, VCORE_START_VA); __print_stack_unwind(ai); } } void abort_print(struct abort_info *ai) { __abort_print(ai, false); } void abort_print_error(struct abort_info *ai) { __abort_print(ai, true); } /* This function must be called from a normal thread */ void abort_print_current_ts(void) { struct thread_specific_data *tsd = thread_get_tsd(); struct abort_info ai = { }; struct ts_session *s = ts_get_current_session(); ai.abort_type = tsd->abort_type; ai.fault_descr = tsd->abort_descr; ai.va = tsd->abort_va; ai.pc = tsd->abort_regs.elr; ai.regs = &tsd->abort_regs; if (ai.abort_type != ABORT_TYPE_USER_MODE_PANIC) __print_abort_info(&ai, "User mode"); s->ctx->ops->dump_state(s->ctx); #if defined(CFG_FTRACE_SUPPORT) if (s->ctx->ops->dump_ftrace) { s->fbuf = NULL; s->ctx->ops->dump_ftrace(s->ctx); } #endif } static void save_abort_info_in_tsd(struct abort_info *ai) { struct thread_specific_data *tsd = thread_get_tsd(); tsd->abort_type = ai->abort_type; tsd->abort_descr = ai->fault_descr; tsd->abort_va = ai->va; tsd->abort_regs = *ai->regs; tsd->abort_core = get_core_pos(); } #ifdef ARM32 static void set_abort_info(uint32_t abort_type, struct thread_abort_regs *regs, struct abort_info *ai) { switch (abort_type) { case ABORT_TYPE_DATA: ai->fault_descr = read_dfsr(); ai->va = read_dfar(); break; case ABORT_TYPE_PREFETCH: ai->fault_descr = read_ifsr(); ai->va = read_ifar(); break; default: ai->fault_descr = 0; ai->va = regs->elr; break; } ai->abort_type = abort_type; ai->pc = regs->elr; ai->regs = regs; } #endif /*ARM32*/ #ifdef ARM64 static void set_abort_info(uint32_t abort_type __unused, struct thread_abort_regs *regs, struct abort_info *ai) { ai->fault_descr = read_esr_el1(); switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { case ESR_EC_IABT_EL0: case ESR_EC_IABT_EL1: ai->abort_type = ABORT_TYPE_PREFETCH; ai->va = read_far_el1(); break; case ESR_EC_DABT_EL0: case ESR_EC_DABT_EL1: case ESR_EC_SP_ALIGN: ai->abort_type = ABORT_TYPE_DATA; ai->va = read_far_el1(); break; default: ai->abort_type = ABORT_TYPE_UNDEF; ai->va = regs->elr; } ai->pc = regs->elr; ai->regs = regs; } #endif /*ARM64*/ #ifdef ARM32 static void handle_user_mode_panic(struct abort_info *ai) { /* * It was a user exception, stop user execution and return * to TEE Core. */ ai->regs->r0 = TEE_ERROR_TARGET_DEAD; ai->regs->r1 = true; ai->regs->r2 = 0xdeadbeef; ai->regs->elr = (uint32_t)thread_unwind_user_mode; ai->regs->spsr &= CPSR_FIA; ai->regs->spsr &= ~CPSR_MODE_MASK; ai->regs->spsr |= CPSR_MODE_SVC; /* Select Thumb or ARM mode */ if (ai->regs->elr & 1) ai->regs->spsr |= CPSR_T; else ai->regs->spsr &= ~CPSR_T; } #endif /*ARM32*/ #ifdef ARM64 static void handle_user_mode_panic(struct abort_info *ai) { struct thread_ctx *tc __maybe_unused = NULL; uint32_t daif = 0; uint32_t pan_bit = 0; /* * It was a user exception, stop user execution and return * to TEE Core. */ ai->regs->x0 = TEE_ERROR_TARGET_DEAD; ai->regs->x1 = true; ai->regs->x2 = 0xdeadbeef; ai->regs->elr = (vaddr_t)thread_unwind_user_mode; ai->regs->sp_el0 = thread_get_saved_thread_sp(); #if defined(CFG_CORE_PAUTH) /* * We're going to return to the privileged core thread, update the * APIA key to match the key used by the thread. */ tc = threads + thread_get_id(); ai->regs->apiakey_hi = tc->keys.apia_hi; ai->regs->apiakey_lo = tc->keys.apia_lo; #endif if (IS_ENABLED(CFG_PAN) && feat_pan_implemented() && read_pan()) pan_bit = SPSR_64_PAN; daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK; /* XXX what about DAIF_D? */ ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif) | pan_bit; } #endif /*ARM64*/ #ifdef CFG_WITH_VFP static void handle_user_mode_vfp(void) { struct ts_session *s = ts_get_current_session(); thread_user_enable_vfp(&to_user_mode_ctx(s->ctx)->vfp); } #endif /*CFG_WITH_VFP*/ #ifdef CFG_WITH_USER_TA #ifdef ARM32 /* Returns true if the exception originated from user mode */ bool abort_is_user_exception(struct abort_info *ai) { return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR; } #endif /*ARM32*/ #ifdef ARM64 /* Returns true if the exception originated from user mode */ bool abort_is_user_exception(struct abort_info *ai) { uint32_t spsr = ai->regs->spsr; if (spsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT)) return true; if (((spsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) == SPSR_64_MODE_EL0) return true; return false; } #endif /*ARM64*/ #else /*CFG_WITH_USER_TA*/ bool abort_is_user_exception(struct abort_info *ai __unused) { return false; } #endif /*CFG_WITH_USER_TA*/ #if defined(CFG_WITH_VFP) && defined(CFG_WITH_USER_TA) #ifdef ARM32 static bool is_vfp_fault(struct abort_info *ai) { if ((ai->abort_type != ABORT_TYPE_UNDEF) || vfp_is_enabled()) return false; /* * Not entirely accurate, but if it's a truly undefined instruction * we'll end up in this function again, except this time * vfp_is_enabled() so we'll return false. */ return true; } #endif /*ARM32*/ #ifdef ARM64 static bool is_vfp_fault(struct abort_info *ai) { switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { case ESR_EC_FP_ASIMD: case ESR_EC_AARCH32_FP: case ESR_EC_AARCH64_FP: return true; default: return false; } } #endif /*ARM64*/ #else /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ static bool is_vfp_fault(struct abort_info *ai __unused) { return false; } #endif /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ bool abort_is_write_fault(struct abort_info *ai) { #ifdef ARM32 unsigned int write_not_read = 11; #endif #ifdef ARM64 unsigned int write_not_read = 6; #endif return ai->abort_type == ABORT_TYPE_DATA && (ai->fault_descr & BIT(write_not_read)); } static enum fault_type get_fault_type(struct abort_info *ai) { if (abort_is_user_exception(ai)) { if (is_vfp_fault(ai)) return FAULT_TYPE_USER_MODE_VFP; #ifndef CFG_WITH_PAGER return FAULT_TYPE_USER_MODE_PANIC; #endif } if (thread_is_from_abort_mode()) { abort_print_error(ai); panic("[abort] abort in abort handler (trap CPU)"); } if (ai->abort_type == ABORT_TYPE_UNDEF) { if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] undefined abort (trap CPU)"); } switch (core_mmu_get_fault_type(ai->fault_descr)) { case CORE_MMU_FAULT_ALIGNMENT: if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] alignement fault! (trap CPU)"); break; case CORE_MMU_FAULT_ACCESS_BIT: if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] access bit fault! (trap CPU)"); break; case CORE_MMU_FAULT_DEBUG_EVENT: if (!abort_is_user_exception(ai)) abort_print(ai); DMSG("[abort] Ignoring debug event!"); return FAULT_TYPE_IGNORE; case CORE_MMU_FAULT_TRANSLATION: case CORE_MMU_FAULT_WRITE_PERMISSION: case CORE_MMU_FAULT_READ_PERMISSION: return FAULT_TYPE_PAGEABLE; case CORE_MMU_FAULT_ASYNC_EXTERNAL: if (!abort_is_user_exception(ai)) abort_print(ai); DMSG("[abort] Ignoring async external abort!"); return FAULT_TYPE_IGNORE; case CORE_MMU_FAULT_TAG_CHECK: if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] Tag check fault! (trap CPU)"); break; case CORE_MMU_FAULT_OTHER: default: if (!abort_is_user_exception(ai)) abort_print(ai); DMSG("[abort] Unhandled fault!"); return FAULT_TYPE_IGNORE; } } void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs) { struct abort_info ai; bool handled; set_abort_info(abort_type, regs, &ai); switch (get_fault_type(&ai)) { case FAULT_TYPE_IGNORE: break; case FAULT_TYPE_USER_MODE_PANIC: DMSG("[abort] abort in User mode (TA will panic)"); save_abort_info_in_tsd(&ai); vfp_disable(); handle_user_mode_panic(&ai); break; #ifdef CFG_WITH_VFP case FAULT_TYPE_USER_MODE_VFP: handle_user_mode_vfp(); break; #endif case FAULT_TYPE_PAGEABLE: default: if (thread_get_id_may_fail() < 0) { abort_print_error(&ai); panic("abort outside thread context"); } thread_kernel_save_vfp(); handled = tee_pager_handle_fault(&ai); thread_kernel_restore_vfp(); if (!handled) { if (!abort_is_user_exception(&ai)) { abort_print_error(&ai); panic("unhandled pageable abort"); } DMSG("[abort] abort in User mode (TA will panic)"); save_abort_info_in_tsd(&ai); vfp_disable(); handle_user_mode_panic(&ai); } break; } } optee_os-4.3.0/core/arch/arm/kernel/arch_scall.c000066400000000000000000000073231464416617300215170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2022, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #include #include #define TA32_CONTEXT_MAX_SIZE (14 * sizeof(uint32_t)) #define TA64_CONTEXT_MAX_SIZE (2 * sizeof(uint64_t)) #ifdef CFG_UNWIND #ifdef ARM32 /* Get register values pushed onto the stack by _utee_panic() */ static void save_panic_regs_a32_ta(struct thread_specific_data *tsd, uint32_t *pushed) { tsd->abort_regs = (struct thread_abort_regs){ .elr = pushed[0], .r0 = pushed[1], .r1 = pushed[2], .r2 = pushed[3], .r3 = pushed[4], .r4 = pushed[5], .r5 = pushed[6], .r6 = pushed[7], .r7 = pushed[8], .r8 = pushed[9], .r9 = pushed[10], .r10 = pushed[11], .r11 = pushed[12], .usr_sp = (uint32_t)pushed, .usr_lr = pushed[13], .spsr = read_spsr(), }; } void scall_save_panic_stack(struct thread_scall_regs *regs) { struct thread_specific_data *tsd = thread_get_tsd(); struct ts_session *s = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; tsd->abort_descr = 0; tsd->abort_va = 0; if (vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE, (uaddr_t)regs->r1, TA32_CONTEXT_MAX_SIZE)) { TAMSG_RAW(""); TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, (uaddr_t)regs->r1); return; } save_panic_regs_a32_ta(tsd, (uint32_t *)regs->r1); } #endif /*ARM32*/ #ifdef ARM64 /* Get register values pushed onto the stack by _utee_panic() (32-bit TA) */ static void save_panic_regs_a32_ta(struct thread_specific_data *tsd, uint32_t *pushed) { tsd->abort_regs = (struct thread_abort_regs){ .elr = pushed[0], .x0 = pushed[1], .x1 = pushed[2], .x2 = pushed[3], .x3 = pushed[4], .x4 = pushed[5], .x5 = pushed[6], .x6 = pushed[7], .x7 = pushed[8], .x8 = pushed[9], .x9 = pushed[10], .x10 = pushed[11], .x11 = pushed[12], .x13 = (uint64_t)pushed, .x14 = pushed[13], .spsr = (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT), }; } /* Get register values pushed onto the stack by _utee_panic() (64-bit TA) */ static void save_panic_regs_a64_ta(struct thread_specific_data *tsd, uint64_t *pushed) { TEE_Result res = TEE_SUCCESS; uint64_t x29 = 0; uint64_t elr = 0; res = GET_USER_SCALAR(x29, &pushed[0]); if (res) x29 = 0; res = GET_USER_SCALAR(elr, &pushed[1]); if (res) elr = 0; tsd->abort_regs = (struct thread_abort_regs){ .x29 = x29, .elr = elr, .spsr = (SPSR_64_MODE_EL0 << SPSR_64_MODE_EL_SHIFT), }; } void scall_save_panic_stack(struct thread_scall_regs *regs) { struct thread_specific_data *tsd = thread_get_tsd(); struct ts_session *s = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); if (vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE, (uaddr_t)regs->x1, utc->uctx.is_32bit ? TA32_CONTEXT_MAX_SIZE : TA64_CONTEXT_MAX_SIZE)) { TAMSG_RAW(""); TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, (uaddr_t)regs->x1); return; } tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; tsd->abort_descr = 0; tsd->abort_va = 0; if (utc->uctx.is_32bit) save_panic_regs_a32_ta(tsd, (uint32_t *)regs->x1); else save_panic_regs_a64_ta(tsd, (uint64_t *)regs->x1); } #endif /*ARM64*/ #else /* CFG_UNWIND */ void scall_save_panic_stack(struct thread_scall_regs *regs __unused) { struct thread_specific_data *tsd = thread_get_tsd(); tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; } #endif /* CFG_UNWIND */ optee_os-4.3.0/core/arch/arm/kernel/arch_scall_a32.S000066400000000000000000000057441464416617300221510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include "tee_syscall_numbers.h" #include "trace_levels.h" #include #include #include #include #include /* * uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); * * Called from scall_handle_user_ta() */ FUNC scall_do_call , : UNWIND( .cantunwind) push {r5-r9, lr} mov r7, sp mov r8, r0 mov r9, r1 ldr r5, [r8, #THREAD_SCALL_REG_R5] ldr r6, [r8, #THREAD_SCALL_REG_R6] /* * Copy eventual arguments passed on the user stack. * * r5 holds the address of the first word * r6 holds the number of words * * scall_handle_user_ta() who calls this function has already checked * that we don't copy too much data. */ cmp r6, #0 beq .Lno_args sub sp, sp, r6, lsl #2 bic sp, sp, #7 /* make sure it's a multiple of 8 */ mov r0, sp mov r1, r5 mov r2, r6, lsl #2 ldr lr, =copy_from_user blx lr /* If copy failed return the error */ cmp r0, #0 bne .Lret .Lno_args: /* Load arguments to function */ add lr, r8, #THREAD_SCALL_REG_R0 ldm lr, {r0-r3} blx r9 .Lret: mov sp, r7 pop {r5-r9, pc} END_FUNC scall_do_call /* * syscall_sys_return() and syscall_panic() are two special cases for syscalls * in the way that they do not return to the TA, instead execution is resumed * as if __thread_enter_user_mode() had returned to thread_enter_user_mode(). * * In order to do this the functions need a way to get hold of a pointer to * the struct thread_scall_regs provided by storing relevant registers on the * stack in thread_scall_handler() and later load them into registers again * when thread_scall_handler() is returning. * * scall_do_call() is supplied the pointer to struct thread_scall_regs in * r0. This pointer can later be retrieved from r8. */ /* * User space sees this function as: * void syscall_sys_return(uint32_t ret) __noreturn; * * But internally the function depends on being called from * scall_do_call() with pointer to the struct thread_scall_regs saved by * thread_scall_handler() in r8. * * The argument ret is already in r0 so we don't touch that and let it * propagate as return value of the called scall_sys_return_helper(). */ FUNC syscall_sys_return , : mov r1, #0 /* panic = false */ mov r2, #0 /* panic_code = 0 */ mov r3, r8 /* pointer to struct thread_scall_regs */ b scall_sys_return_helper END_FUNC syscall_sys_return /* * User space sees this function as: * void syscall_panic(uint32_t code) __noreturn; * * But internally the function depends on being called from * scall_do_call() with pointer to the struct thread_scall_regs saved by * thread_scall_handler() in r8. */ FUNC syscall_panic , : mov r1, #1 /* panic = true */ mov r2, r0 /* panic_code = 0 */ mov r3, r8 /* pointer to struct thread_scall_regs */ ldr r0, =TEE_ERROR_TARGET_DEAD b scall_sys_return_helper END_FUNC syscall_panic optee_os-4.3.0/core/arch/arm/kernel/arch_scall_a64.S000066400000000000000000000116341464416617300221510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #include "tee_syscall_numbers.h" #include "trace_levels.h" #include #include #include #include #include #include #if 0 struct sc_rec { uint64_t x0; uint64_t x1; uint64_t x19; uint64_t x30; } #endif #define SC_REC_X0 (8 * 0) #define SC_REC_X1 (8 * 1) #define SC_REC_X19 (8 * 2) #define SC_REC_X30 (8 * 3) #define SC_REC_SIZE (SC_REC_X30 + 8) /* * uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); * * Called from scall_handle_user_ta() */ FUNC scall_do_call , : sub sp, sp, #SC_REC_SIZE stp x0, x1, [sp, #SC_REC_X0] stp x19, x30, [sp, #SC_REC_X19] mov x19, sp ldr x2, [x0, #THREAD_SCALL_REG_SPSR] tst x2, #(SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT) b.eq .Lcall_a64 ldp x5, x6, [x0, #THREAD_SCALL_REG_X5] cmp x6, #0 b.eq .Lno_args_a32 /* * Calculate required space on stack to copy Aarch32 arguments * and to transform them into Aarch64 arguments. * x6 = nargs_on_stack * n64 = (nargs_on_stack - 4) * 8 * n32 = nargs_on_stack * 4 * sp -= ROUNDUP(MAX(n32, n64), 16) * */ /* n64 = (nargs_on_stack - 4) * 8 */ sub x1, x6, #0x4 lsl x1, x1, #3 /* n32 = nargs_on_stack * 4 */ lsl x0, x6, #2 /* sp -= ROUNDUP(MAX(n32, n64), 16) */ cmp x1, x0 csel x0, x1, x0, ge add x0, x0, #0xf and x0, x0, #0xfffffffffffffff0 sub sp, sp, x0 /* * Find location on stack where to copy the Aarch32 arguments * and do the copy. * copy_from_user(sp, x5, nargs_on_stack * 4) */ mov x0, sp mov x1, x5 add x2, xzr, x6, lsl #2 bl copy_from_user /* If copy failed return the error */ cmp x0, #0 bne .Lret /* * Load arguments into w4..w7, we're loading junk into unused * registers, but it's quicker than trying to figure out how * many registers to load into. */ /* x0 = nargs_on_stack */ ldr x0, [x19, #SC_REC_X0] ldr x0, [x0, #THREAD_SCALL_REG_X6] load_wregs sp, 0, 4, 7 /* * Convert remaining Aarch32 parameters passed on stack as Aarch64 * parameters on stack. * * nargs_on_stack is initialized in x0 above * n64 = (nargs_on_stack - 4) * 8 * if n64 < 0 goro .Lno_args * x0 = x2 = x19 - n64 * x1 points to next argument * while (x2 != x19) { * w3 = *x1 * x1 += 4 * *x2 = x3 * x2 += 8 * } * sp = x0 */ /* n64 = (nargs_on_stack - 4) * 8 */ subs x2, x0, #0x4 b.le .Lno_args_a32 lsl x2, x2, #3 mov x0, x2 .Lcpy_to_stack: ldr w3, [x1], #4 str x3, [x2], #8 cmp x2, x19 b.ne .Lcpy_to_stack mov sp, x0 .Lno_args_a32: /* Load the first 4 arguments to function */ ldr x9, [x19, #SC_REC_X0] load_xregs x9, THREAD_SCALL_REG_X0, 0, 3 mov w0, w0 mov w1, w1 mov w2, w2 mov w3, w3 /* Call the syscall function */ ldr x16, [x19, #SC_REC_X1] blr x16 b .Lret .Lcall_a64: /* Load the first 8 arguments to function */ ldr x9, [x19, #SC_REC_X0] load_xregs x9, THREAD_SCALL_REG_X0, 0, 8 /* Call the syscall function */ ldr x16, [x19, #SC_REC_X1] blr x16 .Lret: mov sp, x19 ldp x19, x30, [sp, #SC_REC_X19] add sp, sp, #SC_REC_SIZE ret END_FUNC scall_do_call /* * syscall_sys_return() and syscall_panic() are two special cases for syscalls * in the way that they do not return to the TA, instead execution is resumed * as if __thread_enter_user_mode() had returned to thread_enter_user_mode(). * * In order to do this the functions need a way to get hold of a pointer to * the struct thread_scall_regs provided by storing relevant registers on the * stack in el0_svc() and later load them into registers again when el0_svc() * is returning. * * scall_do_call() is supplied the pointer to struct thread_scall_regs in * x0. This pointer can later be retrieved by chasing x19. */ /* * User space sees this function as: * void syscall_sys_return(uint32_t ret) __noreturn; * * But internally the function depends on being called from * scall_do_call() to be able to chase x19 in order to get hold of a * pointer to struct thread_scall_regs. * * The argument ret is already in x0 so we don't touch that and let it * propagate as return value of the called scall_sys_return_helper(). */ FUNC syscall_sys_return , : mov x1, #0 /* panic = false */ mov x2, #0 /* panic_code = 0 */ ldr x3, [x19, #SC_REC_X0] /* pointer to struct thread_scall_regs */ b scall_sys_return_helper END_FUNC syscall_sys_return /* * User space sees this function as: * void syscall_panic(uint32_t code) __noreturn; * * But internally the function depends on being called from * scall_do_call() to be able to chase x19 in order to get hold of a * pointer to struct thread_scall_regs. */ FUNC syscall_panic , : mov x1, #1 /* panic = true */ mov x2, x0 /* code */ ldr w0, =TEE_ERROR_TARGET_DEAD ldr x3, [x19, #SC_REC_X0] /* pointer to struct thread_scall_regs */ b scall_sys_return_helper END_FUNC syscall_panic BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/arm32_gicv3_sysreg.txt000066400000000000000000000022571464416617300234350ustar00rootroot00000000000000# Format of file # # lines beginning with '@' will be printed as additional comments @ Based on register description in @ ARM Generic Interrupt Controller @ Architecture Specification @ GIC architecture version 3.0 and version 4.0 @ Table 8-7 Mapping of MCR and MRC to physical and virtual CPU interface registers, AArch32 state ICC_AP0R0 c12 0 c8 4 RW ICC_AP0R1 c12 0 c8 5 RW ICC_AP0R2 c12 0 c8 6 RW ICC_AP0R3 c12 0 c8 7 RW ICC_AP1R0 c12 0 c9 0 RW ICC_AP1R1 c12 0 c9 1 RW ICC_AP1R2 c12 0 c9 2 RW ICC_AP1R3 c12 0 c9 3 RW ICC_ASGI1R - 1 c12 - WO ICC_BPR0 c12 0 c8 3 RW ICC_BPR1 c12 0 c12 3 RW ICC_CTLR c12 0 c12 4 RW ICC_DIR c12 0 c11 1 WO ICC_EOIR0 c12 0 c8 1 WO ICC_EOIR1 c12 0 c12 1 WO ICC_HPPIR0 c12 0 c8 2 RO ICC_HPPIR1 c12 0 c12 2 RO ICC_HSRE c12 4 c9 5 RW ICC_IAR0 c12 0 c8 0 RO ICC_IAR1 c12 0 c12 0 RO ICC_IGRPEN0 c12 0 c12 6 RW ICC_IGRPEN1 c12 0 c12 7 RW ICC_MCTLR c12 6 c12 4 RW ICC_MGRPEN1 c12 6 c12 7 RW ICC_MSRE c12 6 c12 5 RW ICC_PMR c4 0 c6 0 RW ICC_RPR c12 0 c11 3 RO ICC_SGI0R - 2 c12 - WO ICC_SGI1R - 0 c12 - WO ICC_SRE c12 0 c12 5 RW optee_os-4.3.0/core/arch/arm/kernel/arm32_sysreg.txt000066400000000000000000000171271464416617300223440ustar00rootroot00000000000000# Format of file # # lines beginning with '@' will be printed as additional comments @ Based on register description in @ ARM Architecture Reference Manual @ ARMv7-A and ARMv7-R edition @ Issue C.c @ @ B3.18.1 Identification registers, functional group AIDR c0 1 c0 7 RO IMPLEMENTATION DEFINED Auxiliary ID Register CCSIDR c0 1 c0 0 RO Cache Size ID Registers CLIDR c0 1 c0 1 RO Cache Level ID Register CSSELR c0 2 c0 0 RW Cache Size Selection Register CTR c0 0 c0 1 RO Cache Type Register ID_AFR0 c0 0 c1 3 RO Auxiliary Feature Register 0 ID_DFR0 c0 0 c1 2 RO Debug Feature Register 0 ID_ISAR0 c0 0 c2 0 RO Instruction Set Attribute Register 0 ID_ISAR1 c0 0 c2 1 RO Instruction Set Attribute Register 1 ID_ISAR2 c0 0 c2 2 RO Instruction Set Attribute Register 2 ID_ISAR3 c0 0 c2 3 RO Instruction Set Attribute Register 3 ID_ISAR4 c0 0 c2 4 RO Instruction Set Attribute Register 4 ID_ISAR5 c0 0 c2 5 RO Instruction Set Attribute Register 5 ID_MMFR0 c0 0 c1 4 RO Memory Model Feature Register 0 ID_MMFR1 c0 0 c1 5 RO Memory Model Feature Register 1 ID_MMFR2 c0 0 c1 6 RO Memory Model Feature Register 2 ID_MMFR3 c0 0 c1 7 RO Memory Model Feature Register 3 ID_PFR0 c0 0 c1 0 RO Processor Feature Register 0 ID_PFR1 c0 0 c1 1 RO Processor Feature Register 1 MIDR c0 0 c0 0 RO Main ID Register MPIDR c0 0 c0 5 RO Multiprocessor Affinity Register REVIDR c0 0 c0 6 RO Revision ID Register TCMTR c0 0 c0 2 RO TCM Type Register TLBTR c0 0 c0 3 RO TLB Type Register @ B3.18.2 Virtual memory control registers, functional group AMAIR0 c10 0 c3 0 RW Auxiliary Memory Attribute Indirection Register 0 AMAIR1 c10 0 c3 1 RW Auxiliary Memory Attribute Indirection Register 1 CONTEXTIDR c13 0 c0 1 RW Context ID Register DACR c3 0 c0 0 RW Domain Access Control Register MAIR0 c10 0 c2 0 RW Memory Attribute Indirection Register 0 MAIR1 c10 0 c2 1 RW Memory Attribute Indirection Register 1 NMRR c10 0 c2 1 RW Normal Memory Remap Register PRRR c10 0 c2 0 RW Primary Region Remap Register SCTLR c1 0 c0 0 RW System Control Register TTBCR c2 0 c0 2 RW Translation Table Base Control Register TTBR0 c2 0 c0 0 RW Translation Table Base Register 0 TTBR0_64bit - 0 c2 - RW Translation Table Base Register 0 TTBR1 c2 0 c0 1 RW Translation Table Base Register 1 TTBR1_64bit - 1 c2 - RW Translation Table Base Register 1 @ B3.18.3 PL1 Fault handling registers, functional group ADFSR c5 0 c1 0 RW Auxiliary Data Fault Status Register AIFSR c5 0 c1 1 RW Auxiliary Instruction Fault Status Register DFAR c6 0 c0 0 RW Data Fault Address Register DFSR c5 0 c0 0 RW Data Fault Status Register IFAR c6 0 c0 2 RW Instruction Fault Address Register IFSR c5 0 c0 1 RW Instruction Fault Status Register @ B3.18.4 Other system control registers, functional group ACTLR c1 0 c0 1 RW IMPLEMENTATION DEFINED Auxiliary Control Register CPACR c1 0 c0 2 RW Coprocessor Access Control Register FCSEIDR c13 0 c0 0 RW FCSE Process ID Register @ B3.18.6 Cache maintenance operations, functional group, VMSA BPIALL c7 0 c5 6 WOD Branch predictor invalidate all BPIALLIS c7 0 c1 6 WOD Branch predictor invalidate all IS BPIMVA c7 0 c5 7 WO Branch predictor invalidate by MVA DCCIMVAC c7 0 c14 1 WO Data cache clean and invalidate by MVA PoC DCCISW c7 0 c14 2 WO Data cache clean and invalidate by set/way DCCMVAC c7 0 c10 1 WO Data cache clean by MVA PoC DCCMVAU c7 0 c11 1 WO Data cache clean by MVA PoU DCCSW c7 0 c10 2 WO Data cache clean by set/way DCIMVAC c7 0 c6 1 WO Data cache invalidate by MVA PoC DCISW c7 0 c6 2 WO Data cache invalidate by set/way ICIALLU c7 0 c5 0 WOD Instruction cache invalidate all PoU ICIALLUIS c7 0 c1 0 WOD Instruction cache invalidate all PoU, IS ICIMVAU c7 0 c5 1 WO Instruction cache invalidate by MVA PoU @ B3.18.7 TLB maintenance operations, functional group TLBIALL c8 0 c7 0 WOD Invalidate entire unified TLB TLBIALLIS c8 0 c3 0 WOD Invalidate entire unified TLB IS TLBIASID c8 0 c7 2 WO Invalidate unified TLB by ASID TLBIASIDIS c8 0 c3 2 WO Invalidate unified TLB by ASID IS TLBIMVAA c8 0 c7 3 WO Invalidate unified TLB by MVA, all ASID TLBIMVAAIS c8 0 c3 3 WO Invalidate unified TLB by MVA, all ASID IS TLBIMVA c8 0 c7 1 WO Invalidate unified TLB by MVA TLBIMVAIS c8 0 c3 1 WO Invalidate unified TLB by MVA IS @ B3.18.8 Address translation operations, functional group ATS12NSOPR c7 0 c8 4 WO Stages 1 and 2 Non-secure only PL1 read ATS12NSOPW c7 0 c8 5 WO Stages 1 and 2 Non-secure only PL1 write ATS12NSOUR c7 0 c8 6 WO Stages 1 and 2 Non-secure only unprivileged read ATS12NSOUW c7 0 c8 7 WO Stages 1 and 2 Non-secure only unprivileged write ATS1CPR c7 0 c8 0 WO Stage 1 Current state PL1 read ATS1CPW c7 0 c8 1 WO Stage 1 Current state PL1 write ATS1CUR c7 0 c8 2 WO Stage 1 Current state unprivileged read ATS1CUW c7 0 c8 3 WO Stage 1 Current state unprivileged write ATS1HR c7 4 c8 0 WO Stage 1 Hyp mode read ATS1HW c7 4 c8 1 WO Stage 1 Hyp mode write PAR32 c7 0 c4 0 RW Physical Address Register PAR64 - 0 c7 - RW Physical Address Register @ B3.18.9 Miscellaneous operations, functional group TPIDRPRW c13 0 c0 4 RW PL1 only Thread ID Register TPIDRURO c13 0 c0 3 RW PL0 User Read-Only Thread ID Register TPIDRURW c13 0 c0 2 RW PL0 User Read/Write Thread ID Register @ B3.18.11 Security Extensions registers, functional group ISR c12 0 c1 0 RO Interrupt Status Register MVBAR c12 0 c0 1 RW Monitor Vector Base Address Register NSACR c1 0 c1 2 RW Non-Secure Access Control Register SCR c1 0 c1 0 RW Secure Configuration Register SDER c1 0 c1 1 RW Secure Debug Enable Register VBAR c12 0 c0 0 RW Vector Base Address Register @ B8.2 Generic Timer registers summary CNTFRQ c14 0 c0 0 RW Counter Frequency register CNTPCT - 0 c14 - RO Physical Count register CNTKCTL c14 0 c1 0 RW Timer PL1 Control register CNTP_TVAL c14 0 c2 0 RW PL1 Physical TimerValue register CNTP_CTL c14 0 c2 1 RW PL1 Physical Timer Control register CNTV_TVAL c14 0 c3 0 RW Virtual TimerValue register CNTV_CTL c14 0 c3 1 RW Virtual Timer Control register CNTVCT - 1 c14 - RO Virtual Count register CNTP_CVAL - 2 c14 - RW PL1 Physical Timer CompareValue register CNTV_CVAL - 3 c14 - RW Virtual Timer CompareValue register CNTVOFF - 4 c14 - RW Virtual Offset register @ Table C12-7 Performance Monitors register summary PMCR c9 0 c12 0 RW Performance Monitors Control Register PMCNTENSET c9 0 c12 1 RW Performance Monitors Count Enable Set register PMCNTENCLR c9 0 c12 2 RW Performance Monitors Count Enable Clear register PMOVSR c9 0 c12 3 RW Performance Monitors Overflow Flag Status Register PMSWINC c9 0 c12 4 WO Performance Monitors Software Increment register PMSELR c9 0 c12 5 RW Performance Monitors Event Counter Selection Register PMCEID0 c9 0 c12 6 RO Performance Monitors Common Event Identification reg 0 PMCEID1 c9 0 c12 7 RO Performance Monitors Common Event Identification reg 1 PMCCNTR c9 0 c13 0 RW Performance Monitors Cycle Count Register PMXEVTYPER c9 0 c13 1 RW Performance Monitors Event Type Select Register PMXEVCNTR c9 0 c13 2 RW Performance Monitors Event Count Register PMUSERENR c9 0 c14 0 RW Performance Monitors User Enable Register PMINTENSET c9 0 c14 1 RW Performance Monitors Interrupt Enable Set register PMINTENCLR c9 0 c14 2 RW Performance Monitors Interrupt Enable Clear register PMOVSSET c9 0 c14 3 RW Performance Monitors Overflow Flag Status Set register optee_os-4.3.0/core/arch/arm/kernel/asm-defines.c000066400000000000000000000152161464416617300216170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2022, Linaro Limited */ #include #include #include #include #include #include #include #include DEFINES { #ifdef ARM32 DEFINE(SM_NSEC_CTX_R0, offsetof(struct sm_nsec_ctx, r0)); DEFINE(SM_NSEC_CTX_R8, offsetof(struct sm_nsec_ctx, r8)); DEFINE(SM_SEC_CTX_R0, offsetof(struct sm_sec_ctx, r0)); DEFINE(SM_SEC_CTX_MON_LR, offsetof(struct sm_sec_ctx, mon_lr)); DEFINE(SM_CTX_SEC_SIZE, sizeof(struct sm_sec_ctx)); DEFINE(SM_CTX_SIZE, sizeof(struct sm_ctx)); DEFINE(SM_CTX_NSEC, offsetof(struct sm_ctx, nsec)); DEFINE(SM_CTX_SEC, offsetof(struct sm_ctx, sec)); DEFINE(THREAD_SCALL_REG_R0, offsetof(struct thread_scall_regs, r0)); DEFINE(THREAD_SCALL_REG_R5, offsetof(struct thread_scall_regs, r5)); DEFINE(THREAD_SCALL_REG_R6, offsetof(struct thread_scall_regs, r6)); /* struct thread_ctx */ DEFINE(THREAD_CTX_STACK_VA_END, offsetof(struct thread_ctx, stack_va_end)); /* struct thread_ctx_regs */ DEFINE(THREAD_CTX_REGS_USR_SP, offsetof(struct thread_ctx_regs, usr_sp)); DEFINE(THREAD_CTX_REGS_PC, offsetof(struct thread_ctx_regs, pc)); DEFINE(THREAD_CTX_REGS_CPSR, offsetof(struct thread_ctx_regs, cpsr)); /* struct thread_core_local */ DEFINE(THREAD_CORE_LOCAL_R0, offsetof(struct thread_core_local, r[0])); DEFINE(THREAD_CORE_LOCAL_SM_PM_CTX_PHYS, offsetof(struct thread_core_local, sm_pm_ctx_phys)); DEFINE(THREAD_CORE_LOCAL_SIZE, sizeof(struct thread_core_local)); DEFINE(SM_PM_CTX_SIZE, sizeof(struct sm_pm_ctx)); #endif /*ARM32*/ #ifdef ARM64 DEFINE(THREAD_SMC_ARGS_X0, offsetof(struct thread_smc_args, a0)); DEFINE(THREAD_SMC_ARGS_SIZE, sizeof(struct thread_smc_args)); DEFINE(THREAD_SCALL_REG_X0, offsetof(struct thread_scall_regs, x0)); DEFINE(THREAD_SCALL_REG_X2, offsetof(struct thread_scall_regs, x2)); DEFINE(THREAD_SCALL_REG_X5, offsetof(struct thread_scall_regs, x5)); DEFINE(THREAD_SCALL_REG_X6, offsetof(struct thread_scall_regs, x6)); DEFINE(THREAD_SCALL_REG_X30, offsetof(struct thread_scall_regs, x30)); DEFINE(THREAD_SCALL_REG_ELR, offsetof(struct thread_scall_regs, elr)); DEFINE(THREAD_SCALL_REG_SPSR, offsetof(struct thread_scall_regs, spsr)); DEFINE(THREAD_SCALL_REG_SP_EL0, offsetof(struct thread_scall_regs, sp_el0)); #ifdef CFG_TA_PAUTH DEFINE(THREAD_SCALL_REG_APIAKEY_HI, offsetof(struct thread_scall_regs, apiakey_hi)); #endif DEFINE(THREAD_SCALL_REG_SIZE, sizeof(struct thread_scall_regs)); /* struct thread_abort_regs */ DEFINE(THREAD_ABT_REG_X0, offsetof(struct thread_abort_regs, x0)); DEFINE(THREAD_ABT_REG_X2, offsetof(struct thread_abort_regs, x2)); DEFINE(THREAD_ABT_REG_X30, offsetof(struct thread_abort_regs, x30)); DEFINE(THREAD_ABT_REG_SPSR, offsetof(struct thread_abort_regs, spsr)); DEFINE(THREAD_ABT_REGS_SIZE, sizeof(struct thread_abort_regs)); #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) DEFINE(THREAD_ABT_REGS_APIAKEY_HI, offsetof(struct thread_abort_regs, apiakey_hi)); #endif /* struct thread_ctx */ DEFINE(THREAD_CTX_KERN_SP, offsetof(struct thread_ctx, kern_sp)); DEFINE(THREAD_CTX_STACK_VA_END, offsetof(struct thread_ctx, stack_va_end)); #if defined(CFG_CORE_PAUTH) DEFINE(THREAD_CTX_KEYS, offsetof(struct thread_ctx, keys)); #endif /* struct thread_ctx_regs */ DEFINE(THREAD_CTX_REGS_SP, offsetof(struct thread_ctx_regs, sp)); DEFINE(THREAD_CTX_REGS_X0, offsetof(struct thread_ctx_regs, x[0])); DEFINE(THREAD_CTX_REGS_X1, offsetof(struct thread_ctx_regs, x[1])); DEFINE(THREAD_CTX_REGS_X2, offsetof(struct thread_ctx_regs, x[2])); DEFINE(THREAD_CTX_REGS_X4, offsetof(struct thread_ctx_regs, x[4])); DEFINE(THREAD_CTX_REGS_X19, offsetof(struct thread_ctx_regs, x[19])); DEFINE(THREAD_CTX_REGS_TPIDR_EL0, offsetof(struct thread_ctx_regs, tpidr_el0)); #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) DEFINE(THREAD_CTX_REGS_APIAKEY_HI, offsetof(struct thread_ctx_regs, apiakey_hi)); #endif /* struct thread_user_mode_rec */ DEFINE(THREAD_USER_MODE_REC_CTX_REGS_PTR, offsetof(struct thread_user_mode_rec, ctx_regs_ptr)); DEFINE(THREAD_USER_MODE_REC_EXIT_STATUS0_PTR, offsetof(struct thread_user_mode_rec, exit_status0_ptr)); DEFINE(THREAD_USER_MODE_REC_X19, offsetof(struct thread_user_mode_rec, x[0])); DEFINE(THREAD_USER_MODE_REC_SIZE, sizeof(struct thread_user_mode_rec)); /* struct thread_core_local */ DEFINE(THREAD_CORE_LOCAL_X0, offsetof(struct thread_core_local, x[0])); DEFINE(THREAD_CORE_LOCAL_X2, offsetof(struct thread_core_local, x[2])); DEFINE(THREAD_CORE_LOCAL_KCODE_OFFSET, offsetof(struct thread_core_local, kcode_offset)); #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC DEFINE(THREAD_CORE_LOCAL_BHB_LOOP_COUNT, offsetof(struct thread_core_local, bhb_loop_count)); #endif #if defined(CFG_CORE_PAUTH) DEFINE(THREAD_CORE_LOCAL_KEYS, offsetof(struct thread_core_local, keys)); #endif #endif /*ARM64*/ /* struct thread_ctx */ DEFINE(THREAD_CTX_SIZE, sizeof(struct thread_ctx)); #ifdef CFG_CORE_FFA DEFINE(THREAD_CTX_TSD_RPC_TARGET_INFO, offsetof(struct thread_ctx, tsd.rpc_target_info)) DEFINE(THREAD_CTX_FLAGS, offsetof(struct thread_ctx, flags)) #endif /* struct thread_core_local */ DEFINE(THREAD_CORE_LOCAL_TMP_STACK_VA_END, offsetof(struct thread_core_local, tmp_stack_va_end)); DEFINE(THREAD_CORE_LOCAL_CURR_THREAD, offsetof(struct thread_core_local, curr_thread)); DEFINE(THREAD_CORE_LOCAL_FLAGS, offsetof(struct thread_core_local, flags)); DEFINE(THREAD_CORE_LOCAL_ABT_STACK_VA_END, offsetof(struct thread_core_local, abt_stack_va_end)); #if defined(ARM64) && defined(CFG_CORE_FFA) DEFINE(THREAD_CORE_LOCAL_DIRECT_RESP_FID, offsetof(struct thread_core_local, direct_resp_fid)); #endif DEFINE(STACK_TMP_GUARD, STACK_CANARY_SIZE / 2 + STACK_TMP_OFFS); /* struct core_mmu_config */ DEFINE(CORE_MMU_CONFIG_SIZE, sizeof(struct core_mmu_config)); DEFINE(CORE_MMU_CONFIG_MAP_OFFSET, offsetof(struct core_mmu_config, map_offset)); /* struct boot_embdata */ DEFINE(BOOT_EMBDATA_HASHES_OFFSET, offsetof(struct boot_embdata, hashes_offset)); DEFINE(BOOT_EMBDATA_HASHES_LEN, offsetof(struct boot_embdata, hashes_len)); DEFINE(BOOT_EMBDATA_RELOC_OFFSET, offsetof(struct boot_embdata, reloc_offset)); DEFINE(BOOT_EMBDATA_RELOC_LEN, offsetof(struct boot_embdata, reloc_len)); #ifdef CORE_MMU_BASE_TABLE_OFFSET /* * This define is too complex to be used as an argument for the * macros add_imm and sub_imm so evaluate it here. */ DEFINE(__CORE_MMU_BASE_TABLE_OFFSET, CORE_MMU_BASE_TABLE_OFFSET); #endif } optee_os-4.3.0/core/arch/arm/kernel/boot.c000066400000000000000000001147011464416617300203660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2023, Linaro Limited * Copyright (c) 2023, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(CFG_WITH_ARM_TRUSTED_FW) #include #endif #if defined(CFG_WITH_VFP) #include #endif /* * In this file we're using unsigned long to represent physical pointers as * they are received in a single register when OP-TEE is initially entered. * This limits 32-bit systems to only use make use of the lower 32 bits * of a physical address for initial parameters. * * 64-bit systems on the other hand can use full 64-bit physical pointers. */ #define PADDR_INVALID ULONG_MAX #if defined(CFG_BOOT_SECONDARY_REQUEST) struct ns_entry_context { uintptr_t entry_point; uintptr_t context_id; }; struct ns_entry_context ns_entry_contexts[CFG_TEE_CORE_NB_CORE]; static uint32_t spin_table[CFG_TEE_CORE_NB_CORE]; #endif #ifdef CFG_BOOT_SYNC_CPU /* * Array used when booting, to synchronize cpu. * When 0, the cpu has not started. * When 1, it has started */ uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE]; DECLARE_KEEP_PAGER(sem_cpu_sync); #endif static unsigned long boot_arg_fdt __nex_bss; static unsigned long boot_arg_nsec_entry __nex_bss; static unsigned long boot_arg_pageable_part __nex_bss; static unsigned long boot_arg_transfer_list __nex_bss; static struct transfer_list_header *mapped_tl __nex_bss; #ifdef CFG_SECONDARY_INIT_CNTFRQ static uint32_t cntfrq; #endif /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void plat_primary_init_early(void) { } DECLARE_KEEP_PAGER(plat_primary_init_early); /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void boot_primary_init_intc(void) { } /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void boot_secondary_init_intc(void) { } /* May be overridden in plat-$(PLATFORM)/main.c */ __weak unsigned long plat_get_aslr_seed(void) { DMSG("Warning: no ASLR seed"); return 0; } #if defined(_CFG_CORE_STACK_PROTECTOR) || defined(CFG_WITH_STACK_CANARIES) /* Generate random stack canary value on boot up */ __weak void plat_get_random_stack_canaries(void *buf, size_t ncan, size_t size) { TEE_Result ret = TEE_ERROR_GENERIC; size_t i = 0; assert(buf && ncan && size); /* * With virtualization the RNG is not initialized in Nexus core. * Need to override with platform specific implementation. */ if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { IMSG("WARNING: Using fixed value for stack canary"); memset(buf, 0xab, ncan * size); goto out; } ret = crypto_rng_read(buf, ncan * size); if (ret != TEE_SUCCESS) panic("Failed to generate random stack canary"); out: /* Leave null byte in canary to prevent string base exploit */ for (i = 0; i < ncan; i++) *((uint8_t *)buf + size * i) = 0; } #endif /* _CFG_CORE_STACK_PROTECTOR || CFG_WITH_STACK_CANARIES */ /* * This function is called as a guard after each smc call which is not * supposed to return. */ void __panic_at_smc_return(void) { panic(); } #if defined(CFG_WITH_ARM_TRUSTED_FW) void init_sec_mon(unsigned long nsec_entry __maybe_unused) { assert(nsec_entry == PADDR_INVALID); /* Do nothing as we don't have a secure monitor */ } #else /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void init_sec_mon(unsigned long nsec_entry) { struct sm_nsec_ctx *nsec_ctx; assert(nsec_entry != PADDR_INVALID); /* Initialize secure monitor */ nsec_ctx = sm_get_nsec_ctx(); nsec_ctx->mon_lr = nsec_entry; nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; if (nsec_entry & 1) nsec_ctx->mon_spsr |= CPSR_T; } #endif #if defined(CFG_WITH_ARM_TRUSTED_FW) static void init_vfp_nsec(void) { } #else static void init_vfp_nsec(void) { /* Normal world can use CP10 and CP11 (SIMD/VFP) */ write_nsacr(read_nsacr() | NSACR_CP10 | NSACR_CP11); } #endif static void check_crypto_extensions(void) { bool ce_supported = true; if (!feat_aes_implemented() && IS_ENABLED(CFG_CRYPTO_AES_ARM_CE)) { EMSG("AES instructions are not supported"); ce_supported = false; } if (!feat_sha1_implemented() && IS_ENABLED(CFG_CRYPTO_SHA1_ARM_CE)) { EMSG("SHA1 instructions are not supported"); ce_supported = false; } if (!feat_sha256_implemented() && IS_ENABLED(CFG_CRYPTO_SHA256_ARM_CE)) { EMSG("SHA256 instructions are not supported"); ce_supported = false; } /* Check aarch64 specific instructions */ if (IS_ENABLED(CFG_ARM64_core)) { if (!feat_sha512_implemented() && IS_ENABLED(CFG_CRYPTO_SHA512_ARM_CE)) { EMSG("SHA512 instructions are not supported"); ce_supported = false; } if (!feat_sha3_implemented() && IS_ENABLED(CFG_CRYPTO_SHA3_ARM_CE)) { EMSG("SHA3 instructions are not supported"); ce_supported = false; } if (!feat_sm3_implemented() && IS_ENABLED(CFG_CRYPTO_SM3_ARM_CE)) { EMSG("SM3 instructions are not supported"); ce_supported = false; } if (!feat_sm4_implemented() && IS_ENABLED(CFG_CRYPTO_SM4_ARM_CE)) { EMSG("SM4 instructions are not supported"); ce_supported = false; } } if (!ce_supported) panic("HW doesn't support CE instructions"); } #if defined(CFG_WITH_VFP) #ifdef ARM32 static void init_vfp_sec(void) { uint32_t cpacr = read_cpacr(); /* * Enable Advanced SIMD functionality. * Enable use of D16-D31 of the Floating-point Extension register * file. */ cpacr &= ~(CPACR_ASEDIS | CPACR_D32DIS); /* * Enable usage of CP10 and CP11 (SIMD/VFP) (both kernel and user * mode. */ cpacr |= CPACR_CP(10, CPACR_CP_ACCESS_FULL); cpacr |= CPACR_CP(11, CPACR_CP_ACCESS_FULL); write_cpacr(cpacr); } #endif /* ARM32 */ #ifdef ARM64 static void init_vfp_sec(void) { /* Not using VFP until thread_kernel_enable_vfp() */ vfp_disable(); } #endif /* ARM64 */ #else /* CFG_WITH_VFP */ static void init_vfp_sec(void) { /* Not using VFP */ } #endif #ifdef CFG_SECONDARY_INIT_CNTFRQ static void primary_save_cntfrq(void) { assert(cntfrq == 0); /* * CNTFRQ should be initialized on the primary CPU by a * previous boot stage */ cntfrq = read_cntfrq(); } static void secondary_init_cntfrq(void) { assert(cntfrq != 0); write_cntfrq(cntfrq); } #else /* CFG_SECONDARY_INIT_CNTFRQ */ static void primary_save_cntfrq(void) { } static void secondary_init_cntfrq(void) { } #endif #ifdef CFG_CORE_SANITIZE_KADDRESS static void init_run_constructors(void) { const vaddr_t *ctor; for (ctor = &__ctor_list; ctor < &__ctor_end; ctor++) ((void (*)(void))(*ctor))(); } static void init_asan(void) { /* * CFG_ASAN_SHADOW_OFFSET is also supplied as * -fasan-shadow-offset=$(CFG_ASAN_SHADOW_OFFSET) to the compiler. * Since all the needed values to calculate the value of * CFG_ASAN_SHADOW_OFFSET isn't available in to make we need to * calculate it in advance and hard code it into the platform * conf.mk. Here where we have all the needed values we double * check that the compiler is supplied the correct value. */ #define __ASAN_SHADOW_START \ ROUNDUP(TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8, 8) assert(__ASAN_SHADOW_START == (vaddr_t)&__asan_shadow_start); #define __CFG_ASAN_SHADOW_OFFSET \ (__ASAN_SHADOW_START - (TEE_RAM_START / 8)) COMPILE_TIME_ASSERT(CFG_ASAN_SHADOW_OFFSET == __CFG_ASAN_SHADOW_OFFSET); #undef __ASAN_SHADOW_START #undef __CFG_ASAN_SHADOW_OFFSET /* * Assign area covered by the shadow area, everything from start up * to the beginning of the shadow area. */ asan_set_shadowed((void *)TEE_LOAD_ADDR, &__asan_shadow_start); /* * Add access to areas that aren't opened automatically by a * constructor. */ asan_tag_access(&__ctor_list, &__ctor_end); asan_tag_access(__rodata_start, __rodata_end); #ifdef CFG_WITH_PAGER asan_tag_access(__pageable_start, __pageable_end); #endif /*CFG_WITH_PAGER*/ asan_tag_access(__nozi_start, __nozi_end); #ifdef ARM32 asan_tag_access(__exidx_start, __exidx_end); asan_tag_access(__extab_start, __extab_end); #endif init_run_constructors(); /* Everything is tagged correctly, let's start address sanitizing. */ asan_start(); } #else /*CFG_CORE_SANITIZE_KADDRESS*/ static void init_asan(void) { } #endif /*CFG_CORE_SANITIZE_KADDRESS*/ #if defined(CFG_MEMTAG) /* Called from entry_a64.S only when MEMTAG is configured */ void boot_init_memtag(void) { memtag_init_ops(feat_mte_implemented()); } /* Called from entry_a64.S only when MEMTAG is configured */ void boot_clear_memtag(void) { enum teecore_memtypes mtypes[] = { MEM_AREA_TEE_RAM, MEM_AREA_TEE_RAM_RW, MEM_AREA_NEX_RAM_RO, MEM_AREA_NEX_RAM_RW, MEM_AREA_TEE_ASAN, MEM_AREA_TA_RAM }; vaddr_t s = 0; vaddr_t e = 0; size_t n = 0; for (n = 0; n < ARRAY_SIZE(mtypes); n++) { core_mmu_get_mem_by_type(mtypes[n], &s, &e); if (e > s) { DMSG("Clearing tags for VA %#"PRIxVA"..%#"PRIxVA, s, e - 1); memtag_set_tags((void *)s, e - s, 0); } } } #endif #ifdef CFG_WITH_PAGER #ifdef CFG_CORE_SANITIZE_KADDRESS static void carve_out_asan_mem(tee_mm_pool_t *pool) { const size_t s = pool->hi - pool->lo; tee_mm_entry_t *mm; paddr_t apa = ASAN_MAP_PA; size_t asz = ASAN_MAP_SZ; if (core_is_buffer_outside(apa, asz, pool->lo, s)) return; /* Reserve the shadow area */ if (!core_is_buffer_inside(apa, asz, pool->lo, s)) { if (apa < pool->lo) { /* * ASAN buffer is overlapping with the beginning of * the pool. */ asz -= pool->lo - apa; apa = pool->lo; } else { /* * ASAN buffer is overlapping with the end of the * pool. */ asz = pool->hi - apa; } } mm = tee_mm_alloc2(pool, apa, asz); assert(mm); } #else static void carve_out_asan_mem(tee_mm_pool_t *pool __unused) { } #endif static void print_pager_pool_size(void) { struct tee_pager_stats __maybe_unused stats; tee_pager_get_stats(&stats); IMSG("Pager pool size: %zukB", stats.npages_all * SMALL_PAGE_SIZE / 1024); } static void init_virt_pool(tee_mm_pool_t *virt_pool) { const vaddr_t begin = VCORE_START_VA; size_t size = TEE_RAM_VA_SIZE; #ifdef CFG_CORE_SANITIZE_KADDRESS /* Carve out asan memory, flat maped after core memory */ if (begin + size > ASAN_SHADOW_PA) size = ASAN_MAP_PA - begin; #endif if (!tee_mm_init(virt_pool, begin, size, SMALL_PAGE_SHIFT, TEE_MM_POOL_NO_FLAGS)) panic("core_virt_mem_pool init failed"); } /* * With CFG_CORE_ASLR=y the init part is relocated very early during boot. * The init part is also paged just as the rest of the normal paged code, with * the difference that it's preloaded during boot. When the backing store * is configured the entire paged binary is copied in place and then also * the init part. Since the init part has been relocated (references to * addresses updated to compensate for the new load address) this has to be * undone for the hashes of those pages to match with the original binary. * * If CFG_CORE_ASLR=n, nothing needs to be done as the code/ro pages are * unchanged. */ static void undo_init_relocation(uint8_t *paged_store __maybe_unused) { #ifdef CFG_CORE_ASLR unsigned long *ptr = NULL; const uint32_t *reloc = NULL; const uint32_t *reloc_end = NULL; unsigned long offs = boot_mmu_config.map_offset; const struct boot_embdata *embdata = (const void *)__init_end; vaddr_t addr_end = (vaddr_t)__init_end - offs - TEE_LOAD_ADDR; vaddr_t addr_start = (vaddr_t)__init_start - offs - TEE_LOAD_ADDR; reloc = (const void *)((vaddr_t)embdata + embdata->reloc_offset); reloc_end = reloc + embdata->reloc_len / sizeof(*reloc); for (; reloc < reloc_end; reloc++) { if (*reloc < addr_start) continue; if (*reloc >= addr_end) break; ptr = (void *)(paged_store + *reloc - addr_start); *ptr -= offs; } #endif } static struct fobj *ro_paged_alloc(tee_mm_entry_t *mm, void *hashes, void *store) { const unsigned int num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE; #ifdef CFG_CORE_ASLR unsigned int reloc_offs = (vaddr_t)__pageable_start - VCORE_START_VA; const struct boot_embdata *embdata = (const void *)__init_end; const void *reloc = __init_end + embdata->reloc_offset; return fobj_ro_reloc_paged_alloc(num_pages, hashes, reloc_offs, reloc, embdata->reloc_len, store); #else return fobj_ro_paged_alloc(num_pages, hashes, store); #endif } static void init_runtime(unsigned long pageable_part) { size_t n; size_t init_size = (size_t)(__init_end - __init_start); size_t pageable_start = (size_t)__pageable_start; size_t pageable_end = (size_t)__pageable_end; size_t pageable_size = pageable_end - pageable_start; vaddr_t tzsram_end = TZSRAM_BASE + TZSRAM_SIZE - TEE_LOAD_ADDR + VCORE_START_VA; size_t hash_size = (pageable_size / SMALL_PAGE_SIZE) * TEE_SHA256_HASH_SIZE; const struct boot_embdata *embdata = (const void *)__init_end; const void *tmp_hashes = NULL; tee_mm_entry_t *mm = NULL; struct fobj *fobj = NULL; uint8_t *paged_store = NULL; uint8_t *hashes = NULL; assert(pageable_size % SMALL_PAGE_SIZE == 0); assert(embdata->total_len >= embdata->hashes_offset + embdata->hashes_len); assert(hash_size == embdata->hashes_len); tmp_hashes = __init_end + embdata->hashes_offset; init_asan(); /* Add heap2 first as heap1 may be too small as initial bget pool */ malloc_add_pool(__heap2_start, __heap2_end - __heap2_start); malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); /* * This needs to be initialized early to support address lookup * in MEM_AREA_TEE_RAM */ tee_pager_early_init(); hashes = malloc(hash_size); IMSG_RAW("\n"); IMSG("Pager is enabled. Hashes: %zu bytes", hash_size); assert(hashes); asan_memcpy_unchecked(hashes, tmp_hashes, hash_size); /* * Need tee_mm_sec_ddr initialized to be able to allocate secure * DDR below. */ core_mmu_init_ta_ram(); carve_out_asan_mem(&tee_mm_sec_ddr); mm = tee_mm_alloc(&tee_mm_sec_ddr, pageable_size); assert(mm); paged_store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM, pageable_size); /* * Load pageable part in the dedicated allocated area: * - Move pageable non-init part into pageable area. Note bootloader * may have loaded it anywhere in TA RAM hence use memmove(). * - Copy pageable init part from current location into pageable area. */ memmove(paged_store + init_size, phys_to_virt(pageable_part, core_mmu_get_type_by_pa(pageable_part), __pageable_part_end - __pageable_part_start), __pageable_part_end - __pageable_part_start); asan_memcpy_unchecked(paged_store, __init_start, init_size); /* * Undo eventual relocation for the init part so the hash checks * can pass. */ undo_init_relocation(paged_store); /* Check that hashes of what's in pageable area is OK */ DMSG("Checking hashes of pageable area"); for (n = 0; (n * SMALL_PAGE_SIZE) < pageable_size; n++) { const uint8_t *hash = hashes + n * TEE_SHA256_HASH_SIZE; const uint8_t *page = paged_store + n * SMALL_PAGE_SIZE; TEE_Result res; DMSG("hash pg_idx %zu hash %p page %p", n, hash, page); res = hash_sha256_check(hash, page, SMALL_PAGE_SIZE); if (res != TEE_SUCCESS) { EMSG("Hash failed for page %zu at %p: res 0x%x", n, (void *)page, res); panic(); } } /* * Assert prepaged init sections are page aligned so that nothing * trails uninited at the end of the premapped init area. */ assert(!(init_size & SMALL_PAGE_MASK)); /* * Initialize the virtual memory pool used for main_mmu_l2_ttb which * is supplied to tee_pager_init() below. */ init_virt_pool(&core_virt_mem_pool); /* * Assign alias area for pager end of the small page block the rest * of the binary is loaded into. We're taking more than needed, but * we're guaranteed to not need more than the physical amount of * TZSRAM. */ mm = tee_mm_alloc2(&core_virt_mem_pool, (vaddr_t)core_virt_mem_pool.lo + core_virt_mem_pool.size - TZSRAM_SIZE, TZSRAM_SIZE); assert(mm); tee_pager_set_alias_area(mm); /* * Claim virtual memory which isn't paged. * Linear memory (flat map core memory) ends there. */ mm = tee_mm_alloc2(&core_virt_mem_pool, VCORE_UNPG_RX_PA, (vaddr_t)(__pageable_start - VCORE_UNPG_RX_PA)); assert(mm); /* * Allocate virtual memory for the pageable area and let the pager * take charge of all the pages already assigned to that memory. */ mm = tee_mm_alloc2(&core_virt_mem_pool, (vaddr_t)__pageable_start, pageable_size); assert(mm); fobj = ro_paged_alloc(mm, hashes, paged_store); assert(fobj); tee_pager_add_core_region(tee_mm_get_smem(mm), PAGED_REGION_TYPE_RO, fobj); fobj_put(fobj); tee_pager_add_pages(pageable_start, init_size / SMALL_PAGE_SIZE, false); tee_pager_add_pages(pageable_start + init_size, (pageable_size - init_size) / SMALL_PAGE_SIZE, true); if (pageable_end < tzsram_end) tee_pager_add_pages(pageable_end, (tzsram_end - pageable_end) / SMALL_PAGE_SIZE, true); /* * There may be physical pages in TZSRAM before the core load address. * These pages can be added to the physical pages pool of the pager. * This setup may happen when a the secure bootloader runs in TZRAM * and its memory can be reused by OP-TEE once boot stages complete. */ tee_pager_add_pages(core_virt_mem_pool.lo, (VCORE_UNPG_RX_PA - core_virt_mem_pool.lo) / SMALL_PAGE_SIZE, true); print_pager_pool_size(); } #else static void init_runtime(unsigned long pageable_part __unused) { init_asan(); /* * By default whole OP-TEE uses malloc, so we need to initialize * it early. But, when virtualization is enabled, malloc is used * only by TEE runtime, so malloc should be initialized later, for * every virtual partition separately. Core code uses nex_malloc * instead. */ #ifdef CFG_NS_VIRTUALIZATION nex_malloc_add_pool(__nex_heap_start, __nex_heap_end - __nex_heap_start); #else malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); #endif IMSG_RAW("\n"); } #endif #if defined(CFG_DT) static int add_optee_dt_node(struct dt_descriptor *dt) { int offs; int ret; if (fdt_path_offset(dt->blob, "/firmware/optee") >= 0) { DMSG("OP-TEE Device Tree node already exists!"); return 0; } offs = fdt_path_offset(dt->blob, "/firmware"); if (offs < 0) { offs = add_dt_path_subnode(dt, "/", "firmware"); if (offs < 0) return -1; } offs = fdt_add_subnode(dt->blob, offs, "optee"); if (offs < 0) return -1; ret = fdt_setprop_string(dt->blob, offs, "compatible", "linaro,optee-tz"); if (ret < 0) return -1; ret = fdt_setprop_string(dt->blob, offs, "method", "smc"); if (ret < 0) return -1; if (CFG_CORE_ASYNC_NOTIF_GIC_INTID) { /* * The format of the interrupt property is defined by the * binding of the interrupt domain root. In this case it's * one Arm GIC v1, v2 or v3 so we must be compatible with * these. * * An SPI type of interrupt is indicated with a 0 in the * first cell. A PPI type is indicated with value 1. * * The interrupt number goes in the second cell where * SPIs ranges from 0 to 987 and PPI ranges from 0 to 15. * * Flags are passed in the third cells. */ uint32_t itr_trigger = 0; uint32_t itr_type = 0; uint32_t itr_id = 0; uint32_t val[3] = { }; /* PPI are visible only in current CPU cluster */ static_assert(IS_ENABLED(CFG_CORE_FFA) || !CFG_CORE_ASYNC_NOTIF_GIC_INTID || (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_SPI_BASE) || ((CFG_TEE_CORE_NB_CORE <= 8) && (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_PPI_BASE))); if (CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_SPI_BASE) { itr_type = GIC_SPI; itr_id = CFG_CORE_ASYNC_NOTIF_GIC_INTID - GIC_SPI_BASE; itr_trigger = IRQ_TYPE_EDGE_RISING; } else { itr_type = GIC_PPI; itr_id = CFG_CORE_ASYNC_NOTIF_GIC_INTID - GIC_PPI_BASE; itr_trigger = IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(CFG_TEE_CORE_NB_CORE); } val[0] = TEE_U32_TO_BIG_ENDIAN(itr_type); val[1] = TEE_U32_TO_BIG_ENDIAN(itr_id); val[2] = TEE_U32_TO_BIG_ENDIAN(itr_trigger); ret = fdt_setprop(dt->blob, offs, "interrupts", val, sizeof(val)); if (ret < 0) return -1; } return 0; } #ifdef CFG_PSCI_ARM32 static int append_psci_compatible(void *fdt, int offs, const char *str) { return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1); } static int dt_add_psci_node(struct dt_descriptor *dt) { int offs; if (fdt_path_offset(dt->blob, "/psci") >= 0) { DMSG("PSCI Device Tree node already exists!"); return 0; } offs = add_dt_path_subnode(dt, "/", "psci"); if (offs < 0) return -1; if (append_psci_compatible(dt->blob, offs, "arm,psci-1.0")) return -1; if (append_psci_compatible(dt->blob, offs, "arm,psci-0.2")) return -1; if (append_psci_compatible(dt->blob, offs, "arm,psci")) return -1; if (fdt_setprop_string(dt->blob, offs, "method", "smc")) return -1; if (fdt_setprop_u32(dt->blob, offs, "cpu_suspend", PSCI_CPU_SUSPEND)) return -1; if (fdt_setprop_u32(dt->blob, offs, "cpu_off", PSCI_CPU_OFF)) return -1; if (fdt_setprop_u32(dt->blob, offs, "cpu_on", PSCI_CPU_ON)) return -1; if (fdt_setprop_u32(dt->blob, offs, "sys_poweroff", PSCI_SYSTEM_OFF)) return -1; if (fdt_setprop_u32(dt->blob, offs, "sys_reset", PSCI_SYSTEM_RESET)) return -1; return 0; } static int check_node_compat_prefix(struct dt_descriptor *dt, int offs, const char *prefix) { const size_t prefix_len = strlen(prefix); size_t l; int plen; const char *prop; prop = fdt_getprop(dt->blob, offs, "compatible", &plen); if (!prop) return -1; while (plen > 0) { if (memcmp(prop, prefix, prefix_len) == 0) return 0; /* match */ l = strlen(prop) + 1; prop += l; plen -= l; } return -1; } static int dt_add_psci_cpu_enable_methods(struct dt_descriptor *dt) { int offs = 0; while (1) { offs = fdt_next_node(dt->blob, offs, NULL); if (offs < 0) break; if (fdt_getprop(dt->blob, offs, "enable-method", NULL)) continue; /* already set */ if (check_node_compat_prefix(dt, offs, "arm,cortex-a")) continue; /* no compatible */ if (fdt_setprop_string(dt->blob, offs, "enable-method", "psci")) return -1; /* Need to restart scanning as offsets may have changed */ offs = 0; } return 0; } static int config_psci(struct dt_descriptor *dt) { if (dt_add_psci_node(dt)) return -1; return dt_add_psci_cpu_enable_methods(dt); } #else static int config_psci(struct dt_descriptor *dt __unused) { return 0; } #endif /*CFG_PSCI_ARM32*/ static int mark_tzdram_as_reserved(struct dt_descriptor *dt) { return add_res_mem_dt_node(dt, "optee_core", CFG_TZDRAM_START, CFG_TZDRAM_SIZE); } static void update_external_dt(void) { struct dt_descriptor *dt = get_external_dt_desc(); if (!dt || !dt->blob) return; if (!IS_ENABLED(CFG_CORE_FFA) && add_optee_dt_node(dt)) panic("Failed to add OP-TEE Device Tree node"); if (config_psci(dt)) panic("Failed to config PSCI"); #ifdef CFG_CORE_RESERVED_SHM if (mark_static_shm_as_reserved(dt)) panic("Failed to config non-secure memory"); #endif if (mark_tzdram_as_reserved(dt)) panic("Failed to config secure memory"); } #else /*CFG_DT*/ static void update_external_dt(void) { } #endif /*!CFG_DT*/ #ifdef CFG_NS_VIRTUALIZATION static TEE_Result virt_init_heap(void) { /* We need to initialize pool for every virtual guest partition */ malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); return TEE_SUCCESS; } preinit_early(virt_init_heap); #endif void init_tee_runtime(void) { #ifndef CFG_WITH_PAGER /* Pager initializes TA RAM early */ core_mmu_init_ta_ram(); #endif /* * With virtualization we call this function when creating the * OP-TEE partition instead. */ if (!IS_ENABLED(CFG_NS_VIRTUALIZATION)) call_preinitcalls(); call_initcalls(); /* * These two functions uses crypto_rng_read() to initialize the * pauth keys. Once call_initcalls() returns we're guaranteed that * crypto_rng_read() is ready to be used. */ thread_init_core_local_pauth_keys(); thread_init_thread_pauth_keys(); /* * Reinitialize canaries around the stacks with crypto_rng_read(). * * TODO: Updating canaries when CFG_NS_VIRTUALIZATION is enabled will * require synchronization between thread_check_canaries() and * thread_update_canaries(). */ if (!IS_ENABLED(CFG_NS_VIRTUALIZATION)) thread_update_canaries(); } static void init_primary(unsigned long pageable_part, unsigned long nsec_entry) { thread_init_core_local_stacks(); /* * Mask asynchronous exceptions before switch to the thread vector * as the thread handler requires those to be masked while * executing with the temporary stack. The thread subsystem also * asserts that the foreign interrupts are blocked when using most of * its functions. */ thread_set_exceptions(THREAD_EXCP_ALL); primary_save_cntfrq(); init_vfp_sec(); if (IS_ENABLED(CFG_CRYPTO_WITH_CE)) check_crypto_extensions(); /* * Pager: init_runtime() calls thread_kernel_enable_vfp() so we must * set a current thread right now to avoid a chicken-and-egg problem * (thread_init_boot_thread() sets the current thread but needs * things set by init_runtime()). */ thread_get_core_local()->curr_thread = 0; init_runtime(pageable_part); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { /* * Virtualization: We can't initialize threads right now because * threads belong to "tee" part and will be initialized * separately per each new virtual guest. So, we'll clear * "curr_thread" and call it done. */ thread_get_core_local()->curr_thread = -1; } else { thread_init_boot_thread(); } thread_init_primary(); thread_init_per_cpu(); init_sec_mon(nsec_entry); } static bool cpu_nmfi_enabled(void) { #if defined(ARM32) return read_sctlr() & SCTLR_NMFI; #else /* Note: ARM64 does not feature non-maskable FIQ support. */ return false; #endif } /* * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ void __weak boot_init_primary_late(unsigned long fdt __unused, unsigned long manifest __unused) { size_t fdt_size = CFG_DTB_MAX_SIZE; if (IS_ENABLED(CFG_TRANSFER_LIST) && mapped_tl) { struct transfer_list_entry *tl_e = NULL; tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); if (tl_e) fdt_size = tl_e->data_size; } init_external_dt(boot_arg_fdt, fdt_size); reinit_manifest_dt(); #ifdef CFG_CORE_SEL1_SPMC tpm_map_log_area(get_manifest_dt()); #else tpm_map_log_area(get_external_dt()); #endif discover_nsec_memory(); update_external_dt(); configure_console_from_dt(); IMSG("OP-TEE version: %s", core_v_str); if (IS_ENABLED(CFG_INSECURE)) { IMSG("WARNING: This OP-TEE configuration might be insecure!"); IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); } IMSG("Primary CPU initializing"); #ifdef CFG_CORE_ASLR DMSG("Executing at offset %#lx with virtual load address %#"PRIxVA, (unsigned long)boot_mmu_config.map_offset, VCORE_START_VA); #endif if (IS_ENABLED(CFG_MEMTAG)) DMSG("Memory tagging %s", memtag_is_enabled() ? "enabled" : "disabled"); /* Check if platform needs NMFI workaround */ if (cpu_nmfi_enabled()) { if (!IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) IMSG("WARNING: This ARM core has NMFI enabled, please apply workaround!"); } else { if (IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) IMSG("WARNING: This ARM core does not have NMFI enabled, no need for workaround"); } boot_primary_init_intc(); init_vfp_nsec(); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { IMSG("Initializing virtualization support"); core_mmu_init_virtualization(); } else { init_tee_runtime(); } call_finalcalls(); IMSG("Primary CPU switching to normal world boot"); } static void init_secondary_helper(unsigned long nsec_entry) { IMSG("Secondary CPU %zu initializing", get_core_pos()); /* * Mask asynchronous exceptions before switch to the thread vector * as the thread handler requires those to be masked while * executing with the temporary stack. The thread subsystem also * asserts that the foreign interrupts are blocked when using most of * its functions. */ thread_set_exceptions(THREAD_EXCP_ALL); secondary_init_cntfrq(); thread_init_per_cpu(); init_sec_mon(nsec_entry); boot_secondary_init_intc(); init_vfp_sec(); init_vfp_nsec(); IMSG("Secondary CPU %zu switching to normal world boot", get_core_pos()); } /* * Note: this function is weak just to make it possible to exclude it from * the unpaged area so that it lies in the init area. */ void __weak boot_init_primary_early(void) { unsigned long pageable_part = 0; unsigned long e = PADDR_INVALID; struct transfer_list_entry *tl_e = NULL; if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) e = boot_arg_nsec_entry; if (IS_ENABLED(CFG_TRANSFER_LIST) && boot_arg_transfer_list) { /* map and save the TL */ mapped_tl = transfer_list_map(boot_arg_transfer_list); if (!mapped_tl) panic("Failed to map transfer list"); transfer_list_dump(mapped_tl); tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); if (tl_e) { /* * Expand the data size of the DTB entry to the maximum * allocable mapped memory to reserve sufficient space * for inserting new nodes, avoid potentially corrupting * next entries. */ uint32_t dtb_max_sz = mapped_tl->max_size - mapped_tl->size + tl_e->data_size; if (!transfer_list_set_data_size(mapped_tl, tl_e, dtb_max_sz)) { EMSG("Failed to extend DTB size to %#"PRIx32, dtb_max_sz); panic(); } } tl_e = transfer_list_find(mapped_tl, TL_TAG_OPTEE_PAGABLE_PART); } if (IS_ENABLED(CFG_WITH_PAGER)) { if (IS_ENABLED(CFG_TRANSFER_LIST) && tl_e) pageable_part = get_le64(transfer_list_entry_data(tl_e)); else pageable_part = boot_arg_pageable_part; } init_primary(pageable_part, e); } static void boot_save_transfer_list(unsigned long zero_reg, unsigned long transfer_list, unsigned long fdt) { struct transfer_list_header *tl = (void *)transfer_list; struct transfer_list_entry *tl_e = NULL; if (zero_reg != 0) panic("Incorrect transfer list register convention"); if (!IS_ALIGNED_WITH_TYPE(transfer_list, struct transfer_list_header) || !IS_ALIGNED(transfer_list, TL_ALIGNMENT_FROM_ORDER(tl->alignment))) panic("Transfer list base address is not aligned"); if (transfer_list_check_header(tl) == TL_OPS_NONE) panic("Invalid transfer list"); tl_e = transfer_list_find(tl, TL_TAG_FDT); if (fdt != (unsigned long)transfer_list_entry_data(tl_e)) panic("DT does not match to the DT entry of the TL"); boot_arg_transfer_list = transfer_list; } #if defined(CFG_WITH_ARM_TRUSTED_FW) unsigned long boot_cpu_on_handler(unsigned long a0 __maybe_unused, unsigned long a1 __unused) { init_secondary_helper(PADDR_INVALID); return 0; } #else void boot_init_secondary(unsigned long nsec_entry) { init_secondary_helper(nsec_entry); } #endif #if defined(CFG_BOOT_SECONDARY_REQUEST) void boot_set_core_ns_entry(size_t core_idx, uintptr_t entry, uintptr_t context_id) { ns_entry_contexts[core_idx].entry_point = entry; ns_entry_contexts[core_idx].context_id = context_id; dsb_ishst(); } int boot_core_release(size_t core_idx, paddr_t entry) { if (!core_idx || core_idx >= CFG_TEE_CORE_NB_CORE) return -1; ns_entry_contexts[core_idx].entry_point = entry; dmb(); spin_table[core_idx] = 1; dsb(); sev(); return 0; } /* * spin until secondary boot request, then returns with * the secondary core entry address. */ struct ns_entry_context *boot_core_hpen(void) { #ifdef CFG_PSCI_ARM32 return &ns_entry_contexts[get_core_pos()]; #else do { wfe(); } while (!spin_table[get_core_pos()]); dmb(); return &ns_entry_contexts[get_core_pos()]; #endif } #endif #if defined(CFG_CORE_ASLR) #if defined(CFG_DT) unsigned long __weak get_aslr_seed(void) { void *fdt = NULL; int rc = 0; const uint64_t *seed = NULL; int offs = 0; int len = 0; if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) fdt = (void *)boot_arg_fdt; if (!fdt) { DMSG("No fdt"); goto err; } rc = fdt_check_header(fdt); if (rc) { DMSG("Bad fdt: %d", rc); goto err; } offs = fdt_path_offset(fdt, "/secure-chosen"); if (offs < 0) { DMSG("Cannot find /secure-chosen"); goto err; } seed = fdt_getprop(fdt, offs, "kaslr-seed", &len); if (!seed || len != sizeof(*seed)) { DMSG("Cannot find valid kaslr-seed"); goto err; } return fdt64_to_cpu(fdt64_ld(seed)); err: /* Try platform implementation */ return plat_get_aslr_seed(); } #else /*!CFG_DT*/ unsigned long __weak get_aslr_seed(void) { /* Try platform implementation */ return plat_get_aslr_seed(); } #endif /*!CFG_DT*/ #endif /*CFG_CORE_ASLR*/ static void *get_fdt_from_boot_info(struct ffa_boot_info_header_1_1 *hdr) { struct ffa_boot_info_1_1 *desc = NULL; uint8_t content_fmt = 0; uint8_t name_fmt = 0; void *fdt = NULL; int ret = 0; if (hdr->signature != FFA_BOOT_INFO_SIGNATURE) { EMSG("Bad boot info signature %#"PRIx32, hdr->signature); panic(); } if (hdr->version != FFA_BOOT_INFO_VERSION) { EMSG("Bad boot info version %#"PRIx32, hdr->version); panic(); } if (hdr->desc_count != 1) { EMSG("Bad boot info descriptor count %#"PRIx32, hdr->desc_count); panic(); } desc = (void *)((vaddr_t)hdr + hdr->desc_offset); name_fmt = desc->flags & FFA_BOOT_INFO_FLAG_NAME_FORMAT_MASK; if (name_fmt == FFA_BOOT_INFO_FLAG_NAME_FORMAT_STRING) DMSG("Boot info descriptor name \"%16s\"", desc->name); else if (name_fmt == FFA_BOOT_INFO_FLAG_NAME_FORMAT_UUID) DMSG("Boot info descriptor UUID %pUl", (void *)desc->name); else DMSG("Boot info descriptor: unknown name format %"PRIu8, name_fmt); content_fmt = (desc->flags & FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_MASK) >> FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT; if (content_fmt != FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR) { EMSG("Bad boot info content format %"PRIu8", expected %u (address)", content_fmt, FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR); panic(); } fdt = (void *)(vaddr_t)desc->contents; ret = fdt_check_full(fdt, desc->size); if (ret < 0) { EMSG("Invalid Device Tree at %p: error %d", fdt, ret); panic(); } return fdt; } static void get_sec_mem_from_manifest(void *fdt, paddr_t *base, size_t *size) { int ret = 0; uint64_t num = 0; ret = fdt_node_check_compatible(fdt, 0, "arm,ffa-manifest-1.0"); if (ret < 0) { EMSG("Invalid FF-A manifest at %p: error %d", fdt, ret); panic(); } ret = dt_getprop_as_number(fdt, 0, "load-address", &num); if (ret < 0) { EMSG("Can't read \"load-address\" from FF-A manifest at %p: error %d", fdt, ret); panic(); } *base = num; /* "mem-size" is currently an undocumented extension to the spec. */ ret = dt_getprop_as_number(fdt, 0, "mem-size", &num); if (ret < 0) { EMSG("Can't read \"mem-size\" from FF-A manifest at %p: error %d", fdt, ret); panic(); } *size = num; } void __weak boot_save_args(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4 __maybe_unused) { /* * Register use: * * Scenario A: Default arguments * a0 - CFG_CORE_FFA=y && CFG_CORE_SEL2_SPMC=n: * if non-NULL holds the TOS FW config [1] address * - CFG_CORE_FFA=y && (CFG_CORE_SEL2_SPMC=y || CFG_CORE_EL3_SPMC=y): * address of FF-A Boot Information Blob * - CFG_CORE_FFA=n: * if non-NULL holds the pagable part address * a1 - CFG_WITH_ARM_TRUSTED_FW=n (Armv7): * Armv7 standard bootarg #1 (kept track of in entry_a32.S) * a2 - CFG_CORE_SEL2_SPMC=n: * if non-NULL holds the system DTB address * - CFG_WITH_ARM_TRUSTED_FW=n (Armv7): * Armv7 standard bootarg #2 (system DTB address, kept track * of in entry_a32.S) * a3 - Not used * a4 - CFG_WITH_ARM_TRUSTED_FW=n: * Non-secure entry address * * [1] A TF-A concept: TOS_FW_CONFIG - Trusted OS Firmware * configuration file. Used by Trusted OS (BL32), that is, OP-TEE * here. This is also called Manifest DT, related to the Manifest DT * passed in the FF-A Boot Information Blob, but with a different * compatible string. * Scenario B: FW Handoff via Transfer List * Note: FF-A and non-secure entry are not yet supported with * Transfer List * a0 - DTB address or 0 (AArch64) * - must be 0 (AArch32) * a1 - TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK * a2 - must be 0 (AArch64) * - DTB address or 0 (AArch32) * a3 - Transfer list base address * a4 - Not used */ if (IS_ENABLED(CFG_TRANSFER_LIST) && a1 == (TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK)) { if (IS_ENABLED(CFG_ARM64_core)) { boot_save_transfer_list(a2, a3, a0); boot_arg_fdt = a0; } else { boot_save_transfer_list(a0, a3, a2); boot_arg_fdt = a2; } return; } if (!IS_ENABLED(CFG_CORE_SEL2_SPMC)) { #if defined(CFG_DT_ADDR) boot_arg_fdt = CFG_DT_ADDR; #else boot_arg_fdt = a2; #endif } if (IS_ENABLED(CFG_CORE_FFA)) { if (IS_ENABLED(CFG_CORE_SEL2_SPMC) || IS_ENABLED(CFG_CORE_EL3_SPMC)) init_manifest_dt(get_fdt_from_boot_info((void *)a0)); else init_manifest_dt((void *)a0); if (IS_ENABLED(CFG_CORE_SEL2_SPMC) && IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) { paddr_t base = 0; size_t size = 0; get_sec_mem_from_manifest(get_manifest_dt(), &base, &size); core_mmu_set_secure_memory(base, size); } } else { if (IS_ENABLED(CFG_WITH_PAGER)) { #if defined(CFG_PAGEABLE_ADDR) boot_arg_pageable_part = CFG_PAGEABLE_ADDR; #else boot_arg_pageable_part = a0; #endif } if (!IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) { #if defined(CFG_NS_ENTRY_ADDR) boot_arg_nsec_entry = CFG_NS_ENTRY_ADDR; #else boot_arg_nsec_entry = a4; #endif } } } #if defined(CFG_TRANSFER_LIST) static TEE_Result release_transfer_list(void) { struct dt_descriptor *dt = get_external_dt_desc(); if (!mapped_tl) return TEE_SUCCESS; if (dt) { int ret = 0; struct transfer_list_entry *tl_e = NULL; /* * Pack the DTB and update the transfer list before un-mapping */ ret = fdt_pack(dt->blob); if (ret < 0) { EMSG("Failed to pack Device Tree at 0x%" PRIxPA ": error %d", virt_to_phys(dt->blob), ret); panic(); } tl_e = transfer_list_find(mapped_tl, TL_TAG_FDT); assert(dt->blob == transfer_list_entry_data(tl_e)); transfer_list_set_data_size(mapped_tl, tl_e, fdt_totalsize(dt->blob)); dt->blob = NULL; } transfer_list_unmap_sync(mapped_tl); mapped_tl = NULL; return TEE_SUCCESS; } boot_final(release_transfer_list); #endif optee_os-4.3.0/core/arch/arm/kernel/cache_helpers_a32.S000066400000000000000000000173221464416617300226360ustar00rootroot00000000000000/* * Copyright (c) 2017, Linaro Limited. All rights reserved. * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include /* * Cache line size helpers */ .macro dcache_line_size reg, tmp read_ctr \tmp ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH mov \reg, #CTR_WORD_SIZE lsl \reg, \reg, \tmp .endm .macro icache_line_size reg, tmp read_ctr \tmp and \tmp, \tmp, #CTR_IMINLINE_MASK mov \reg, #CTR_WORD_SIZE lsl \reg, \reg, \tmp .endm /* * This macro can be used for implementing various data cache operations `op` */ .macro do_dcache_maintenance_by_mva reg dcache_line_size r2, r3 add r1, r0, r1 sub r3, r2, #1 bic r0, r0, r3 loop_\reg: write_\reg r0 add r0, r0, r2 cmp r0, r1 blo loop_\reg dsb sy bx lr .endm /* ------------------------------------------ * Clean+Invalidate from base address till * size. 'r0' = addr, 'r1' = size * ------------------------------------------ */ FUNC dcache_cleaninv_range , : do_dcache_maintenance_by_mva dccimvac END_FUNC dcache_cleaninv_range /* ------------------------------------------ * Clean from base address till size. * 'r0' = addr, 'r1' = size * ------------------------------------------ */ FUNC dcache_clean_range , : do_dcache_maintenance_by_mva dccmvac END_FUNC dcache_clean_range /* ------------------------------------------ * Invalidate from base address till * size. 'r0' = addr, 'r1' = size * ------------------------------------------ */ FUNC dcache_inv_range , : do_dcache_maintenance_by_mva dcimvac END_FUNC dcache_inv_range /* ------------------------------------------ * Clean from base address till size to point of unification * 'r0' = addr, 'r1' = size * ------------------------------------------ */ FUNC dcache_clean_range_pou , : do_dcache_maintenance_by_mva dccmvau END_FUNC dcache_clean_range_pou /* ---------------------------------------------------------------- * Data cache operations by set/way to the level specified * * The main function, do_dcsw_op requires: * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, * DCACHE_OP_CLEAN), as defined in cache_helpers.h * r1: The cache level to begin operation from * r2: clidr_el1 * r3: The last cache level to operate on * and will carry out the operation on each data cache from level 0 * to the level in r3 in sequence * * The dcsw_op macro sets up the r2 and r3 parameters based on * clidr_el1 cache information before invoking the main function * ---------------------------------------------------------------- */ .macro dcsw_op shift, fw, ls read_clidr r2 ubfx r3, r2, \shift, \fw lsl r3, r3, \ls mov r1, #0 b do_dcsw_op .endm LOCAL_FUNC do_dcsw_op , : push {r4-r12,lr} adr r11, dcsw_loop_table // compute cache op based on the operation type add r6, r11, r0, lsl #3 // cache op is 2x32-bit instructions loop1: add r10, r1, r1, LSR #1 // Work out 3x current cache level mov r12, r2, LSR r10 // extract cache type bits from clidr and r12, r12, #7 // mask the bits for current cache only cmp r12, #2 // see what cache we have at this level blo level_done // no cache or only instruction cache at this level write_csselr r1 // select current cache level in csselr isb // isb to sych the new cssr&csidr read_ccsidr r12 // read the new ccsidr and r10, r12, #7 // extract the length of the cache lines add r10, r10, #4 // add 4 (r10 = line length offset) ubfx r4, r12, #3, #10 // r4 = maximum way number (right aligned) clz r5, r4 // r5 = the bit position of the way size increment mov r9, r4 // r9 working copy of the aligned max way number loop2: ubfx r7, r12, #13, #15 // r7 = max set number (right aligned) loop3: orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 orr r0, r0, r7, LSL r10 // factor in the set number blx r6 subs r7, r7, #1 // decrement the set number bhs loop3 subs r9, r9, #1 // decrement the way number bhs loop2 level_done: add r1, r1, #2 // increment the cache number cmp r3, r1 dsb sy // ensure completion of previous cache maintenance instruction bhi loop1 mov r6, #0 write_csselr r6 //select cache level 0 in csselr dsb sy isb pop {r4-r12,pc} dcsw_loop_table: write_dcisw r0 bx lr write_dccisw r0 bx lr write_dccsw r0 bx lr END_FUNC do_dcsw_op /* --------------------------------------------------------------- * Data cache operations by set/way till PoU. * * The function requires : * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, * DCACHE_OP_CLEAN), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_louis , : dcsw_op #CLIDR_LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT END_FUNC dcache_op_louis /* --------------------------------------------------------------- * Data cache operations by set/way till PoC. * * The function requires : * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, * DCACHE_OP_CLEAN), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_all , : dcsw_op #CLIDR_LOC_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT END_FUNC dcache_op_all /* --------------------------------------------------------------- * Helper macro for data cache operations by set/way for the * level specified * --------------------------------------------------------------- */ .macro dcsw_op_level level read_clidr r2 mov r3, \level sub r1, r3, #2 b do_dcsw_op .endm /* --------------------------------------------------------------- * Data cache operations by set/way for level 1 cache * * The main function, do_dcsw_op requires: * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, * DCACHE_OP_CLEAN), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_level1 , : dcsw_op_level #(1 << CSSELR_LEVEL_SHIFT) END_FUNC dcache_op_level1 /* --------------------------------------------------------------- * Data cache operations by set/way for level 2 cache * * The main function, do_dcsw_op requires: * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, * DCACHE_OP_CLEAN), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_level2 , : dcsw_op_level #(2 << CSSELR_LEVEL_SHIFT) END_FUNC dcache_op_level2 /* --------------------------------------------------------------- * Data cache operations by set/way for level 3 cache * * The main function, do_dcsw_op requires: * r0: The operation type (DCACHE_OP_INV, DCACHE_OP_CLEAN_INV, * DCACHE_OP_CLEAN), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_level3 , : dcsw_op_level #(3 << CSSELR_LEVEL_SHIFT) END_FUNC dcache_op_level3 FUNC icache_inv_all , : /* Invalidate Entire Instruction Cache (and branch predictors) */ write_icialluis dsb ishst /* ensure that maintenance operations are seen */ isb /* by the instructions rigth after the isb */ bx lr END_FUNC icache_inv_all /* ------------------------------------------ * Invalidate from base address till * size. 'r0' = addr, 'r1' = size * ------------------------------------------ */ FUNC icache_inv_range , : icache_line_size r2, r3 add r1, r0, r1 sub r3, r2, #1 bic r0, r0, r3 loop_ic_inv: write_icimvau r0 add r0, r0, r2 cmp r0, r1 blo loop_ic_inv /* Invalidate entire branch predictor array inner shareable */ write_bpiallis dsb ishst isb bx lr END_FUNC icache_inv_range optee_os-4.3.0/core/arch/arm/kernel/cache_helpers_a64.S000066400000000000000000000153261464416617300226450ustar00rootroot00000000000000/* * Copyright (c) 2017, Linaro Limited. All rights reserved. * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include .macro dcache_line_size reg, tmp mrs \tmp, ctr_el0 ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH mov \reg, #CTR_WORD_SIZE lsl \reg, \reg, \tmp .endm .macro icache_line_size reg, tmp mrs \tmp, ctr_el0 and \tmp, \tmp, #CTR_IMINLINE_MASK mov \reg, #CTR_WORD_SIZE lsl \reg, \reg, \tmp .endm /* * This macro can be used for implementing various data cache operations `op` */ .macro do_dcache_maintenance_by_va op dcache_line_size x2, x3 add x1, x0, x1 sub x3, x2, #1 bic x0, x0, x3 loop_\op: dc \op, x0 add x0, x0, x2 cmp x0, x1 b.lo loop_\op dsb sy ret .endm /* ------------------------------------------ * Clean+Invalidate from base address till * size. 'x0' = addr, 'x1' = size * ------------------------------------------ */ FUNC dcache_cleaninv_range , : do_dcache_maintenance_by_va civac END_FUNC dcache_cleaninv_range /* ------------------------------------------ * Clean from base address till size. * 'x0' = addr, 'x1' = size * ------------------------------------------ */ FUNC dcache_clean_range , : do_dcache_maintenance_by_va cvac END_FUNC dcache_clean_range /* ------------------------------------------ * Invalidate from base address till * size. 'x0' = addr, 'x1' = size * ------------------------------------------ */ FUNC dcache_inv_range , : do_dcache_maintenance_by_va ivac END_FUNC dcache_inv_range /* ------------------------------------------ * Clean from base address till size to point of unification * 'x0' = addr, 'x1' = size * ------------------------------------------ */ FUNC dcache_clean_range_pou , : do_dcache_maintenance_by_va cvau END_FUNC dcache_clean_range_pou /* --------------------------------------------------------------- * Data cache operations by set/way to the level specified * * The main function, do_dcsw_op requires: * x0: The operation type (0-2), as defined in cache_helpers.h * x3: The last cache level to operate on * x9: clidr_el1 * x10: The cache level to begin operation from * and will carry out the operation on each data cache from level 0 * to the level in x3 in sequence * * The dcsw_op macro sets up the x3 and x9 parameters based on * clidr_el1 cache information before invoking the main function * --------------------------------------------------------------- */ .macro dcsw_op shift, fw, ls mrs x9, clidr_el1 ubfx x3, x9, \shift, \fw lsl x3, x3, \ls mov x10, xzr b do_dcsw_op .endm LOCAL_FUNC do_dcsw_op , : cbz x3, exit adr x14, dcsw_loop_table // compute inner loop address add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions BTI( add x14, x14, x0, lsl #2) // inner loop is + "bti j" instruction mov x0, x9 mov w8, #1 loop1: add x2, x10, x10, lsr #1 // work out 3x current cache level lsr x1, x0, x2 // extract cache type bits from clidr and x1, x1, #7 // mask the bits for current cache only cmp x1, #2 // see what cache we have at this level b.lo level_done // nothing to do if no cache or icache msr csselr_el1, x10 // select current cache level in csselr isb // isb to sych the new cssr&csidr mrs x1, ccsidr_el1 // read the new ccsidr and x2, x1, #7 // extract the length of the cache lines add x2, x2, #4 // add 4 (line length offset) ubfx x4, x1, #3, #10 // maximum way number clz w5, w4 // bit position of way size increment lsl w9, w4, w5 // w9 = aligned max way number lsl w16, w8, w5 // w16 = way number loop decrement orr w9, w10, w9 // w9 = combine way and cache number ubfx w6, w1, #13, #15 // w6 = max set number lsl w17, w8, w2 // w17 = set number loop decrement dsb sy // barrier before we start this level br x14 // jump to DC operation specific loop .macro dcsw_loop _op BTI( bti j) loop2_\_op: lsl w7, w6, w2 // w7 = aligned max set number loop3_\_op: orr w11, w9, w7 // combine cache, way and set number dc \_op, x11 subs w7, w7, w17 // decrement set number b.hs loop3_\_op subs x9, x9, x16 // decrement way number b.hs loop2_\_op b level_done .endm level_done: add x10, x10, #2 // increment cache number cmp x3, x10 b.hi loop1 msr csselr_el1, xzr // select cache level 0 in csselr dsb sy // barrier to complete final cache operation isb exit: ret dcsw_loop_table: dcsw_loop isw dcsw_loop cisw dcsw_loop csw END_FUNC do_dcsw_op FUNC dcache_op_louis , : dcsw_op #CLIDR_LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT END_FUNC dcache_op_louis FUNC dcache_op_all , : dcsw_op #CLIDR_LOC_SHIFT, #CLIDR_FIELD_WIDTH, #CSSELR_LEVEL_SHIFT END_FUNC dcache_op_all /* --------------------------------------------------------------- * Helper macro for data cache operations by set/way for the * level specified * --------------------------------------------------------------- */ .macro dcsw_op_level level mrs x9, clidr_el1 mov x3, \level sub x10, x3, #2 b do_dcsw_op .endm /* --------------------------------------------------------------- * Data cache operations by set/way for level 1 cache * * The main function, do_dcsw_op requires: * x0: The operation type (0-2), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_level1 , : dcsw_op_level #(1 << CSSELR_LEVEL_SHIFT) END_FUNC dcache_op_level1 /* --------------------------------------------------------------- * Data cache operations by set/way for level 2 cache * * The main function, do_dcsw_op requires: * x0: The operation type (0-2), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_level2 , : dcsw_op_level #(2 << CSSELR_LEVEL_SHIFT) END_FUNC dcache_op_level2 /* --------------------------------------------------------------- * Data cache operations by set/way for level 3 cache * * The main function, do_dcsw_op requires: * x0: The operation type (0-2), as defined in cache_helpers.h * --------------------------------------------------------------- */ FUNC dcache_op_level3 , : dcsw_op_level #(3 << CSSELR_LEVEL_SHIFT) END_FUNC dcache_op_level3 FUNC icache_inv_all , : /* Invalidate Entire Instruction Cache */ ic ialluis dsb ish /* ensure that maintenance operations are seen */ isb /* by the instructions rigth after the isb */ ret END_FUNC icache_inv_all FUNC icache_inv_range , : icache_line_size x2, x3 add x1, x0, x1 sub x3, x2, #1 bic x0, x0, x3 loop_ic_inv: ic ivau, x0 add x0, x0, x2 cmp x0, x1 b.lo loop_ic_inv dsb ish ret END_FUNC icache_inv_range BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/entry_a32.S000066400000000000000000000455571464416617300212250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited * Copyright (c) 2021-2023, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include .arch_extension sec .section .data .balign 4 #ifdef CFG_BOOT_SYNC_CPU .equ SEM_CPU_READY, 1 #endif #ifdef CFG_PL310 .section .rodata.init panic_boot_file: .asciz __FILE__ /* * void assert_flat_mapped_range(uint32_t vaddr, uint32_t line) */ LOCAL_FUNC __assert_flat_mapped_range , : UNWIND( .cantunwind) push { r4-r6, lr } mov r4, r0 mov r5, r1 bl cpu_mmu_enabled cmp r0, #0 beq 1f mov r0, r4 bl virt_to_phys cmp r0, r4 beq 1f /* * this must be compliant with the panic generic routine: * __do_panic(__FILE__, __LINE__, __func__, str) */ ldr r0, =panic_boot_file mov r1, r5 mov r2, #0 mov r3, #0 bl __do_panic b . /* should NOT return */ 1: pop { r4-r6, pc } END_FUNC __assert_flat_mapped_range /* panic if mmu is enable and vaddr != paddr (scratch lr) */ .macro assert_flat_mapped_range va, line ldr r0, \va ldr r1, =\line bl __assert_flat_mapped_range .endm #endif /* CFG_PL310 */ WEAK_FUNC plat_cpu_reset_early , : bx lr END_FUNC plat_cpu_reset_early DECLARE_KEEP_PAGER plat_cpu_reset_early .section .identity_map, "ax" .align 5 LOCAL_FUNC reset_vect_table , : , .identity_map b . b . /* Undef */ b . /* Syscall */ b . /* Prefetch abort */ b . /* Data abort */ b . /* Reserved */ b . /* IRQ */ b . /* FIQ */ END_FUNC reset_vect_table .macro cpu_is_ready #ifdef CFG_BOOT_SYNC_CPU bl __get_core_pos lsl r0, r0, #2 ldr r1,=sem_cpu_sync ldr r2, =SEM_CPU_READY str r2, [r1, r0] dsb sev #endif .endm .macro wait_primary #ifdef CFG_BOOT_SYNC_CPU ldr r0, =sem_cpu_sync mov r2, #SEM_CPU_READY sev 1: ldr r1, [r0] cmp r1, r2 wfene bne 1b #endif .endm .macro wait_secondary #ifdef CFG_BOOT_SYNC_CPU ldr r0, =sem_cpu_sync mov r3, #CFG_TEE_CORE_NB_CORE mov r2, #SEM_CPU_READY sev 1: subs r3, r3, #1 beq 3f add r0, r0, #4 2: ldr r1, [r0] cmp r1, r2 wfene bne 2b b 1b 3: #endif .endm /* * set_sctlr : Setup some core configuration in CP15 SCTLR * * Setup required by current implementation of the OP-TEE core: * - Disable data and instruction cache. * - MMU is expected off and exceptions trapped in ARM mode. * - Enable or disable alignment checks upon platform configuration. * - Optionally enable write-implies-execute-never. * - Optionally enable round robin strategy for cache replacement. * * Clobbers r0. */ .macro set_sctlr read_sctlr r0 bic r0, r0, #(SCTLR_M | SCTLR_C) bic r0, r0, #SCTLR_I bic r0, r0, #SCTLR_TE orr r0, r0, #SCTLR_SPAN #if defined(CFG_SCTLR_ALIGNMENT_CHECK) orr r0, r0, #SCTLR_A #else bic r0, r0, #SCTLR_A #endif #if defined(CFG_HWSUPP_MEM_PERM_WXN) && defined(CFG_CORE_RWDATA_NOEXEC) orr r0, r0, #(SCTLR_WXN | SCTLR_UWXN) #endif #if defined(CFG_ENABLE_SCTLR_RR) orr r0, r0, #SCTLR_RR #endif write_sctlr r0 .endm .macro maybe_init_spectre_workaround #if !defined(CFG_WITH_ARM_TRUSTED_FW) && \ (defined(CFG_CORE_WORKAROUND_SPECTRE_BP) || \ defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC)) read_midr r0 ubfx r1, r0, #MIDR_IMPLEMENTER_SHIFT, #MIDR_IMPLEMENTER_WIDTH cmp r1, #MIDR_IMPLEMENTER_ARM bne 1f ubfx r1, r0, #MIDR_PRIMARY_PART_NUM_SHIFT, \ #MIDR_PRIMARY_PART_NUM_WIDTH movw r2, #CORTEX_A8_PART_NUM cmp r1, r2 moveq r2, #ACTLR_CA8_ENABLE_INVALIDATE_BTB beq 2f movw r2, #CORTEX_A15_PART_NUM cmp r1, r2 moveq r2, #ACTLR_CA15_ENABLE_INVALIDATE_BTB bne 1f /* Skip it for all other CPUs */ 2: read_actlr r0 orr r0, r0, r2 write_actlr r0 isb 1: #endif .endm FUNC _start , : UNWIND( .cantunwind) /* * Temporary copy of boot argument registers, will be passed to * boot_save_args() further down. */ mov r4, r0 mov r5, r1 mov r6, r2 mov r7, r3 mov r8, lr /* * 32bit entry is expected to execute Supervisor mode, * some bootloader may enter in Supervisor or Monitor */ cps #CPSR_MODE_SVC /* Early ARM secure MP specific configuration */ bl plat_cpu_reset_early maybe_init_spectre_workaround set_sctlr isb ldr r0, =reset_vect_table write_vbar r0 #if defined(CFG_WITH_ARM_TRUSTED_FW) b reset_primary #else bl __get_core_pos cmp r0, #0 beq reset_primary b reset_secondary #endif END_FUNC _start DECLARE_KEEP_INIT _start /* * Setup sp to point to the top of the tmp stack for the current CPU: * sp is assigned: * stack_tmp + (cpu_id + 1) * stack_tmp_stride - STACK_TMP_GUARD */ .macro set_sp bl __get_core_pos cmp r0, #CFG_TEE_CORE_NB_CORE /* Unsupported CPU, park it before it breaks something */ bge unhandled_cpu add r0, r0, #1 /* r2 = stack_tmp - STACK_TMP_GUARD */ adr r3, stack_tmp_rel ldr r2, [r3] add r2, r2, r3 /* * stack_tmp_stride and stack_tmp_stride_rel are the * equivalent of: * extern const u32 stack_tmp_stride; * u32 stack_tmp_stride_rel = (u32)&stack_tmp_stride - * (u32)&stack_tmp_stride_rel * * To load the value of stack_tmp_stride we do the equivalent * of: * *(u32 *)(stack_tmp_stride + (u32)&stack_tmp_stride_rel) */ adr r3, stack_tmp_stride_rel ldr r1, [r3] ldr r1, [r1, r3] /* * r0 is core pos + 1 * r1 is value of stack_tmp_stride * r2 is value of stack_tmp + guard */ mul r1, r0, r1 add sp, r1, r2 .endm /* * Cache maintenance during entry: handle outer cache. * End address is exclusive: first byte not to be changed. * Note however arm_clX_inv/cleanbyva operate on full cache lines. * * Use ANSI #define to trap source file line number for PL310 assertion */ .macro __inval_cache_vrange vbase, vend, line #if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL) assert_flat_mapped_range (\vbase), (\line) bl pl310_base ldr r1, \vbase ldr r2, \vend bl arm_cl2_invbypa #endif ldr r0, \vbase ldr r1, \vend sub r1, r1, r0 bl dcache_inv_range .endm .macro __flush_cache_vrange vbase, vend, line #if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL) assert_flat_mapped_range (\vbase), (\line) ldr r0, \vbase ldr r1, \vend sub r1, r1, r0 bl dcache_clean_range bl pl310_base ldr r1, \vbase ldr r2, \vend bl arm_cl2_cleaninvbypa #endif ldr r0, \vbase ldr r1, \vend sub r1, r1, r0 bl dcache_cleaninv_range .endm #define inval_cache_vrange(vbase, vend) \ __inval_cache_vrange vbase, vend, __LINE__ #define flush_cache_vrange(vbase, vend) \ __flush_cache_vrange vbase, vend, __LINE__ #ifdef CFG_BOOT_SYNC_CPU #define flush_cpu_semaphores \ flush_cache_vrange(sem_cpu_sync_start, sem_cpu_sync_end) #else #define flush_cpu_semaphores #endif LOCAL_FUNC reset_primary , : , .identity_map UNWIND( .cantunwind) /* preserve r4-r8: bootargs */ #ifdef CFG_WITH_PAGER /* * Move init code into correct location and move hashes to a * temporary safe location until the heap is initialized. * * The binary is built as: * [Pager code, rodata and data] : In correct location * [Init code and rodata] : Should be copied to __init_start * [struct boot_embdata + data] : Should be saved before * initializing pager, first uint32_t tells the length of the data */ ldr r0, =__init_start /* dst */ ldr r1, =__data_end /* src */ ldr r2, =__init_end sub r2, r2, r0 /* init len */ ldr r12, [r1, r2] /* length of hashes etc */ add r2, r2, r12 /* length of init and hashes etc */ /* Copy backwards (as memmove) in case we're overlapping */ add r0, r0, r2 /* __init_start + len */ add r1, r1, r2 /* __data_end + len */ str r0, cached_mem_end ldr r2, =__init_start copy_init: ldmdb r1!, {r3, r9-r12} stmdb r0!, {r3, r9-r12} cmp r0, r2 bgt copy_init #else /* * The binary is built as: * [Core, rodata and data] : In correct location * [struct boot_embdata + data] : Should be moved to __end, first * uint32_t tells the length of the struct + data */ ldr r0, =__end /* dst */ ldr r1, =__data_end /* src */ ldr r2, [r1] /* struct boot_embdata::total_len */ /* Copy backwards (as memmove) in case we're overlapping */ add r0, r0, r2 add r1, r1, r2 str r0, cached_mem_end ldr r2, =__end copy_init: ldmdb r1!, {r3, r9-r12} stmdb r0!, {r3, r9-r12} cmp r0, r2 bgt copy_init #endif /* * Clear .bss, this code obviously depends on the linker keeping * start/end of .bss at least 8 byte aligned. */ ldr r0, =__bss_start ldr r1, =__bss_end mov r2, #0 mov r3, #0 clear_bss: stmia r0!, {r2, r3} cmp r0, r1 bls clear_bss #ifdef CFG_NS_VIRTUALIZATION /* * Clear .nex_bss, this code obviously depends on the linker keeping * start/end of .bss at least 8 byte aligned. */ ldr r0, =__nex_bss_start ldr r1, =__nex_bss_end mov r2, #0 mov r3, #0 clear_nex_bss: stmia r0!, {r2, r3} cmp r0, r1 bls clear_nex_bss #endif #ifdef CFG_CORE_SANITIZE_KADDRESS /* First initialize the entire shadow area with no access */ ldr r0, =__asan_shadow_start /* start */ ldr r1, =__asan_shadow_end /* limit */ mov r2, #ASAN_DATA_RED_ZONE shadow_no_access: str r2, [r0], #4 cmp r0, r1 bls shadow_no_access /* Mark the entire stack area as OK */ ldr r2, =CFG_ASAN_SHADOW_OFFSET ldr r0, =__nozi_stack_start /* start */ lsr r0, r0, #ASAN_BLOCK_SHIFT add r0, r0, r2 ldr r1, =__nozi_stack_end /* limit */ lsr r1, r1, #ASAN_BLOCK_SHIFT add r1, r1, r2 mov r2, #0 shadow_stack_access_ok: strb r2, [r0], #1 cmp r0, r1 bls shadow_stack_access_ok #endif set_sp bl thread_init_thread_core_local /* complete ARM secure MP common configuration */ bl plat_primary_init_early /* Enable Console */ bl console_init mov r0, r8 mov r1, #0 push {r0, r1} mov r0, r4 mov r1, r5 mov r2, r6 mov r3, r7 bl boot_save_args add sp, sp, #(2 * 4) #ifdef CFG_PL310 bl pl310_base bl arm_cl2_config #endif /* * Invalidate dcache for all memory used during initialization to * avoid nasty surprices when the cache is turned on. We must not * invalidate memory not used by OP-TEE since we may invalidate * entries used by for instance ARM Trusted Firmware. */ inval_cache_vrange(cached_mem_start, cached_mem_end) #if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL) /* Enable PL310 if not yet enabled */ bl pl310_base bl arm_cl2_enable #endif #ifdef CFG_CORE_ASLR bl get_aslr_seed #else mov r0, #0 #endif ldr r1, =boot_mmu_config bl core_init_mmu_map #ifdef CFG_CORE_ASLR /* * Process relocation information for updating with the virtual map * offset. We're doing this now before MMU is enabled as some of * the memory will become write protected. */ ldr r0, =boot_mmu_config ldr r0, [r0, #CORE_MMU_CONFIG_MAP_OFFSET] /* * Update cached_mem_end address with load offset since it was * calculated before relocation. */ ldr r2, cached_mem_end add r2, r2, r0 str r2, cached_mem_end bl relocate #endif bl __get_core_pos bl enable_mmu #ifdef CFG_CORE_ASLR /* * Reinitialize console, since register_serial_console() has * previously registered a PA and with ASLR the VA is different * from the PA. */ bl console_init #endif #ifdef CFG_NS_VIRTUALIZATION /* * Initialize partition tables for each partition to * default_partition which has been relocated now to a different VA */ bl core_mmu_set_default_prtn_tbl #endif bl boot_init_primary_early #ifndef CFG_NS_VIRTUALIZATION mov r9, sp ldr r0, =threads ldr r0, [r0, #THREAD_CTX_STACK_VA_END] mov sp, r0 bl thread_get_core_local mov r8, r0 mov r0, #0 str r0, [r8, #THREAD_CORE_LOCAL_FLAGS] #endif bl boot_init_primary_late #ifndef CFG_NS_VIRTUALIZATION mov r0, #THREAD_CLF_TMP str r0, [r8, #THREAD_CORE_LOCAL_FLAGS] mov sp, r9 #endif #ifdef _CFG_CORE_STACK_PROTECTOR /* Update stack canary value */ sub sp, sp, #0x8 mov r0, sp mov r1, #1 mov r2, #0x4 bl plat_get_random_stack_canaries ldr r0, [sp] ldr r1, =__stack_chk_guard str r0, [r1] add sp, sp, #0x8 #endif /* * In case we've touched memory that secondary CPUs will use before * they have turned on their D-cache, clean and invalidate the * D-cache before exiting to normal world. */ flush_cache_vrange(cached_mem_start, cached_mem_end) /* release secondary boot cores and sync with them */ cpu_is_ready flush_cpu_semaphores wait_secondary #ifdef CFG_PL310_LOCKED #ifdef CFG_PL310_SIP_PROTOCOL #error "CFG_PL310_LOCKED must not be defined when CFG_PL310_SIP_PROTOCOL=y" #endif /* lock/invalidate all lines: pl310 behaves as if disable */ bl pl310_base bl arm_cl2_lockallways bl pl310_base bl arm_cl2_cleaninvbyway #endif /* * Clear current thread id now to allow the thread to be reused on * next entry. Matches the thread_init_boot_thread() in * boot.c. */ #ifndef CFG_NS_VIRTUALIZATION bl thread_clr_boot_thread #endif #ifdef CFG_CORE_FFA ldr r0, =cpu_on_handler /* * Compensate for the virtual map offset since cpu_on_handler() is * called with MMU off. */ ldr r1, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET sub r0, r0, r1 bl thread_spmc_register_secondary_ep b thread_ffa_msg_wait #else /* CFG_CORE_FFA */ #if defined(CFG_WITH_ARM_TRUSTED_FW) ldr r0, =boot_mmu_config ldr r0, [r0, #CORE_MMU_CONFIG_MAP_OFFSET] ldr r1, =thread_vector_table /* Pass the vector address returned from main_init */ sub r1, r1, r0 #else /* Relay standard bootarg #1 and #2 to non-secure entry */ mov r4, #0 mov r3, r6 /* std bootarg #2 for register R2 */ mov r2, r5 /* std bootarg #1 for register R1 */ mov r1, #0 #endif /* CFG_WITH_ARM_TRUSTED_FW */ mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE smc #0 /* SMC should not return */ panic_at_smc_return #endif /* CFG_CORE_FFA */ END_FUNC reset_primary #ifdef CFG_BOOT_SYNC_CPU LOCAL_DATA sem_cpu_sync_start , : .word sem_cpu_sync END_DATA sem_cpu_sync_start LOCAL_DATA sem_cpu_sync_end , : .word sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2) END_DATA sem_cpu_sync_end #endif LOCAL_DATA cached_mem_start , : .word __text_start END_DATA cached_mem_start LOCAL_DATA cached_mem_end , : .skip 4 END_DATA cached_mem_end LOCAL_FUNC unhandled_cpu , : wfi b unhandled_cpu END_FUNC unhandled_cpu #ifdef CFG_CORE_ASLR LOCAL_FUNC relocate , : push {r4-r5} /* r0 holds load offset */ #ifdef CFG_WITH_PAGER ldr r12, =__init_end #else ldr r12, =__end #endif ldr r2, [r12, #BOOT_EMBDATA_RELOC_OFFSET] ldr r3, [r12, #BOOT_EMBDATA_RELOC_LEN] mov_imm r1, TEE_LOAD_ADDR add r2, r2, r12 /* start of relocations */ add r3, r3, r2 /* end of relocations */ /* * Relocations are not formatted as Rel32, instead they are in a * compressed format created by get_reloc_bin() in * scripts/gen_tee_bin.py * * All the R_ARM_RELATIVE relocations are translated into a list of * 32-bit offsets from TEE_LOAD_ADDR. At each address a 32-bit * value pointed out which increased with the load offset. */ #ifdef CFG_WITH_PAGER /* * With pager enabled we can only relocate the pager and init * parts, the rest has to be done when a page is populated. */ sub r12, r12, r1 #endif b 2f /* Loop over the relocation addresses and process all entries */ 1: ldr r4, [r2], #4 #ifdef CFG_WITH_PAGER /* Skip too large addresses */ cmp r4, r12 bge 2f #endif ldr r5, [r4, r1] add r5, r5, r0 str r5, [r4, r1] 2: cmp r2, r3 bne 1b pop {r4-r5} bx lr END_FUNC relocate #endif /* * void enable_mmu(unsigned long core_pos); * * This function depends on being mapped with in the identity map where * physical address and virtual address is the same. After MMU has been * enabled the instruction pointer will be updated to execute as the new * offset instead. Stack pointers and the return address are updated. */ LOCAL_FUNC enable_mmu , : , .identity_map /* r0 = core pos */ adr r1, boot_mmu_config #ifdef CFG_WITH_LPAE ldm r1!, {r2, r3} /* * r2 = ttbcr * r3 = mair0 */ write_ttbcr r2 write_mair0 r3 ldm r1!, {r2, r3} /* * r2 = ttbr0_base * r3 = ttbr0_core_offset */ /* * ttbr0_el1 = ttbr0_base + ttbr0_core_offset * core_pos */ mla r12, r0, r3, r2 mov r0, #0 write_ttbr0_64bit r12, r0 write_ttbr1_64bit r0, r0 #else ldm r1!, {r2, r3} /* * r2 = prrr * r3 = nmrr */ write_prrr r2 write_nmrr r3 ldm r1!, {r2, r3} /* * r2 = dacr * r3 = ttbcr */ write_dacr r2 write_ttbcr r3 ldm r1!, {r2} /* r2 = ttbr */ write_ttbr0 r2 write_ttbr1 r2 mov r2, #0 write_contextidr r2 #endif ldm r1!, {r2} /* r2 = load_offset (always 0 if CFG_CORE_ASLR=n) */ isb /* Invalidate TLB */ write_tlbiall /* * Make sure translation table writes have drained into memory and * the TLB invalidation is complete. */ dsb sy isb read_sctlr r0 orr r0, r0, #SCTLR_M #ifndef CFG_WITH_LPAE /* Enable Access flag (simplified access permissions) and TEX remap */ orr r0, r0, #(SCTLR_AFE | SCTLR_TRE) #endif write_sctlr r0 isb /* Update vbar */ read_vbar r1 add r1, r1, r2 write_vbar r1 isb /* Invalidate instruction cache and branch predictor */ write_iciallu write_bpiall isb read_sctlr r0 /* Enable I and D cache */ orr r0, r0, #SCTLR_I orr r0, r0, #SCTLR_C #if defined(CFG_ENABLE_SCTLR_Z) /* * This is only needed on ARMv7 architecture and hence conditionned * by configuration directive CFG_ENABLE_SCTLR_Z. For recent * architectures, the program flow prediction is automatically * enabled upon MMU enablement. */ orr r0, r0, #SCTLR_Z #endif write_sctlr r0 isb /* Adjust stack pointer and return address */ add sp, sp, r2 add lr, lr, r2 bx lr END_FUNC enable_mmu LOCAL_DATA stack_tmp_rel , : .word stack_tmp - stack_tmp_rel - STACK_TMP_GUARD END_DATA stack_tmp_rel LOCAL_DATA stack_tmp_stride_rel , : .word stack_tmp_stride - stack_tmp_stride_rel END_DATA stack_tmp_stride_rel DATA boot_mmu_config , : /* struct core_mmu_config */ .skip CORE_MMU_CONFIG_SIZE END_DATA boot_mmu_config #if defined(CFG_WITH_ARM_TRUSTED_FW) FUNC cpu_on_handler , : , .identity_map UNWIND( .cantunwind) mov r4, r0 mov r5, r1 mov r6, lr set_sctlr isb adr r0, reset_vect_table write_vbar r0 mov r4, lr bl __get_core_pos bl enable_mmu set_sp mov r0, r4 mov r1, r5 bl boot_cpu_on_handler #ifdef CFG_CORE_FFA b thread_ffa_msg_wait #else bx r6 #endif END_FUNC cpu_on_handler DECLARE_KEEP_PAGER cpu_on_handler #else /* defined(CFG_WITH_ARM_TRUSTED_FW) */ LOCAL_FUNC reset_secondary , : , .identity_map UNWIND( .cantunwind) adr r0, reset_vect_table write_vbar r0 wait_primary set_sp #if defined (CFG_BOOT_SECONDARY_REQUEST) /* if L1 is not invalidated before, do it here */ mov r0, #DCACHE_OP_INV bl dcache_op_level1 #endif bl __get_core_pos bl enable_mmu cpu_is_ready #if defined (CFG_BOOT_SECONDARY_REQUEST) /* * boot_core_hpen() return value (r0) is address of * ns entry context structure */ bl boot_core_hpen ldm r0, {r0, r6} #else mov r0, r8 /* ns-entry address */ mov r6, #0 #endif bl boot_init_secondary mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE mov r1, r6 mov r2, #0 mov r3, #0 mov r4, #0 smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC reset_secondary DECLARE_KEEP_PAGER reset_secondary #endif /* defined(CFG_WITH_ARM_TRUSTED_FW) */ optee_os-4.3.0/core/arch/arm/kernel/entry_a64.S000066400000000000000000000371101464416617300212140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2022, Linaro Limited * Copyright (c) 2021-2023, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include /* * Setup SP_EL0 and SPEL1, SP will be set to SP_EL0. * SP_EL0 is assigned: * stack_tmp + (cpu_id + 1) * stack_tmp_stride - STACK_TMP_GUARD * SP_EL1 is assigned thread_core_local[cpu_id] */ .macro set_sp bl __get_core_pos cmp x0, #CFG_TEE_CORE_NB_CORE /* Unsupported CPU, park it before it breaks something */ bge unhandled_cpu add x0, x0, #1 adr_l x1, stack_tmp_stride ldr w1, [x1] mul x1, x0, x1 /* x0 = stack_tmp - STACK_TMP_GUARD */ adr_l x2, stack_tmp_rel ldr w0, [x2] add x0, x0, x2 msr spsel, #0 add sp, x1, x0 bl thread_get_core_local msr spsel, #1 mov sp, x0 msr spsel, #0 .endm .macro read_feat_mte reg mrs \reg, id_aa64pfr1_el1 ubfx \reg, \reg, #ID_AA64PFR1_EL1_MTE_SHIFT, #4 .endm .macro read_feat_pan reg mrs \reg, id_mmfr3_el1 ubfx \reg, \reg, #ID_MMFR3_EL1_PAN_SHIFT, #4 .endm .macro set_sctlr_el1 mrs x0, sctlr_el1 orr x0, x0, #SCTLR_I orr x0, x0, #SCTLR_SA orr x0, x0, #SCTLR_SPAN #if defined(CFG_CORE_RWDATA_NOEXEC) orr x0, x0, #SCTLR_WXN #endif #if defined(CFG_SCTLR_ALIGNMENT_CHECK) orr x0, x0, #SCTLR_A #else bic x0, x0, #SCTLR_A #endif #ifdef CFG_MEMTAG read_feat_mte x1 cmp w1, #1 b.ls 111f orr x0, x0, #(SCTLR_ATA | SCTLR_ATA0) bic x0, x0, #SCTLR_TCF_MASK bic x0, x0, #SCTLR_TCF0_MASK 111: #endif #if defined(CFG_TA_PAUTH) && defined(CFG_TA_BTI) orr x0, x0, #SCTLR_BT0 #endif #if defined(CFG_CORE_PAUTH) && defined(CFG_CORE_BTI) orr x0, x0, #SCTLR_BT1 #endif msr sctlr_el1, x0 .endm .macro init_memtag_per_cpu read_feat_mte x0 cmp w0, #1 b.ls 11f #ifdef CFG_TEE_CORE_DEBUG /* * This together with GCR_EL1.RRND = 0 will make the tags * acquired with the irg instruction deterministic. */ mov_imm x0, 0xcafe00 msr rgsr_el1, x0 /* Avoid tag = 0x0 and 0xf */ mov x0, #0 #else /* * Still avoid tag = 0x0 and 0xf as we use that tag for * everything which isn't explicitly tagged. Setting * GCR_EL1.RRND = 1 to allow an implementation specific * method of generating the tags. */ mov x0, #GCR_EL1_RRND #endif orr x0, x0, #1 orr x0, x0, #(1 << 15) msr gcr_el1, x0 /* * Enable the tag checks on the current CPU. * * Depends on boot_init_memtag() having cleared tags for * TEE core memory. Well, not really, addresses with the * tag value 0b0000 will use unchecked access due to * TCR_TCMA0. */ mrs x0, tcr_el1 orr x0, x0, #TCR_TBI0 orr x0, x0, #TCR_TCMA0 msr tcr_el1, x0 mrs x0, sctlr_el1 orr x0, x0, #SCTLR_TCF_SYNC orr x0, x0, #SCTLR_TCF0_SYNC msr sctlr_el1, x0 isb 11: .endm .macro init_pauth_per_cpu msr spsel, #1 ldp x0, x1, [sp, #THREAD_CORE_LOCAL_KEYS] msr spsel, #0 write_apiakeyhi x0 write_apiakeylo x1 mrs x0, sctlr_el1 orr x0, x0, #SCTLR_ENIA msr sctlr_el1, x0 isb .endm .macro init_pan read_feat_pan x0 cmp x0, #0 b.eq 1f mrs x0, sctlr_el1 bic x0, x0, #SCTLR_SPAN msr sctlr_el1, x0 write_pan_enable 1: .endm FUNC _start , : /* * Temporary copy of boot argument registers, will be passed to * boot_save_args() further down. */ mov x19, x0 mov x20, x1 mov x21, x2 mov x22, x3 adr x0, reset_vect_table msr vbar_el1, x0 isb #ifdef CFG_PAN init_pan #endif set_sctlr_el1 isb #ifdef CFG_WITH_PAGER /* * Move init code into correct location and move hashes to a * temporary safe location until the heap is initialized. * * The binary is built as: * [Pager code, rodata and data] : In correct location * [Init code and rodata] : Should be copied to __init_start * [struct boot_embdata + data] : Should be saved before * initializing pager, first uint32_t tells the length of the data */ adr x0, __init_start /* dst */ adr x1, __data_end /* src */ adr x2, __init_end sub x2, x2, x0 /* init len */ ldr w4, [x1, x2] /* length of hashes etc */ add x2, x2, x4 /* length of init and hashes etc */ /* Copy backwards (as memmove) in case we're overlapping */ add x0, x0, x2 /* __init_start + len */ add x1, x1, x2 /* __data_end + len */ adr x3, cached_mem_end str x0, [x3] adr x2, __init_start copy_init: ldp x3, x4, [x1, #-16]! stp x3, x4, [x0, #-16]! cmp x0, x2 b.gt copy_init #else /* * The binary is built as: * [Core, rodata and data] : In correct location * [struct boot_embdata + data] : Should be moved to __end, first * uint32_t tells the length of the struct + data */ adr_l x0, __end /* dst */ adr_l x1, __data_end /* src */ ldr w2, [x1] /* struct boot_embdata::total_len */ /* Copy backwards (as memmove) in case we're overlapping */ add x0, x0, x2 add x1, x1, x2 adr x3, cached_mem_end str x0, [x3] adr_l x2, __end copy_init: ldp x3, x4, [x1, #-16]! stp x3, x4, [x0, #-16]! cmp x0, x2 b.gt copy_init #endif /* * Clear .bss, this code obviously depends on the linker keeping * start/end of .bss at least 8 byte aligned. */ adr_l x0, __bss_start adr_l x1, __bss_end clear_bss: str xzr, [x0], #8 cmp x0, x1 b.lt clear_bss #ifdef CFG_NS_VIRTUALIZATION /* * Clear .nex_bss, this code obviously depends on the linker keeping * start/end of .bss at least 8 byte aligned. */ adr_l x0, __nex_bss_start adr_l x1, __nex_bss_end clear_nex_bss: str xzr, [x0], #8 cmp x0, x1 b.lt clear_nex_bss #endif #if defined(CFG_CORE_PHYS_RELOCATABLE) /* * Save the base physical address, it will not change after this * point. */ adr_l x2, core_mmu_tee_load_pa adr x1, _start /* Load address */ str x1, [x2] mov_imm x0, TEE_LOAD_ADDR /* Compiled load address */ sub x0, x1, x0 /* Relocatation offset */ cbz x0, 1f bl relocate 1: #endif /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */ set_sp bl thread_init_thread_core_local /* Enable aborts now that we can receive exceptions */ msr daifclr, #DAIFBIT_ABT /* * Invalidate dcache for all memory used during initialization to * avoid nasty surprices when the cache is turned on. We must not * invalidate memory not used by OP-TEE since we may invalidate * entries used by for instance ARM Trusted Firmware. */ adr_l x0, __text_start ldr x1, cached_mem_end sub x1, x1, x0 bl dcache_cleaninv_range /* Enable Console */ bl console_init mov x0, x19 mov x1, x20 mov x2, x21 mov x3, x22 mov x4, xzr bl boot_save_args #ifdef CFG_MEMTAG /* * If FEAT_MTE2 is available, initializes the memtag callbacks. * Tags for OP-TEE core memory are then cleared to make it safe to * enable MEMTAG below. */ bl boot_init_memtag #endif #ifdef CFG_CORE_ASLR bl get_aslr_seed #else mov x0, #0 #endif adr x1, boot_mmu_config bl core_init_mmu_map #ifdef CFG_CORE_ASLR /* * Process relocation information again updating for the virtual * map offset. We're doing this now before MMU is enabled as some * of the memory will become write protected. */ ldr x0, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET cbz x0, 1f /* * Update cached_mem_end address with load offset since it was * calculated before relocation. */ adr x5, cached_mem_end ldr x6, [x5] add x6, x6, x0 str x6, [x5] adr x1, _start /* Load address */ bl relocate 1: #endif bl __get_core_pos bl enable_mmu #ifdef CFG_CORE_ASLR /* * Reinitialize console, since register_serial_console() has * previously registered a PA and with ASLR the VA is different * from the PA. */ bl console_init #endif #ifdef CFG_MEMTAG bl boot_clear_memtag #endif #ifdef CFG_NS_VIRTUALIZATION /* * Initialize partition tables for each partition to * default_partition which has been relocated now to a different VA */ bl core_mmu_set_default_prtn_tbl #endif bl boot_init_primary_early #ifdef CFG_MEMTAG init_memtag_per_cpu #endif #ifndef CFG_NS_VIRTUALIZATION mov x23, sp adr_l x0, threads ldr x0, [x0, #THREAD_CTX_STACK_VA_END] mov sp, x0 bl thread_get_core_local mov x24, x0 str wzr, [x24, #THREAD_CORE_LOCAL_FLAGS] #endif bl boot_init_primary_late #ifdef CFG_CORE_PAUTH init_pauth_per_cpu #endif #ifndef CFG_NS_VIRTUALIZATION mov x0, #THREAD_CLF_TMP str w0, [x24, #THREAD_CORE_LOCAL_FLAGS] mov sp, x23 #endif #ifdef _CFG_CORE_STACK_PROTECTOR /* Update stack canary value */ sub sp, sp, #0x10 mov x0, sp mov x1, #1 mov x2, #0x8 bl plat_get_random_stack_canaries ldr x0, [sp] adr_l x5, __stack_chk_guard str x0, [x5] add sp, sp, #0x10 #endif /* * In case we've touched memory that secondary CPUs will use before * they have turned on their D-cache, clean and invalidate the * D-cache before exiting to normal world. */ adr_l x0, __text_start ldr x1, cached_mem_end sub x1, x1, x0 bl dcache_cleaninv_range /* * Clear current thread id now to allow the thread to be reused on * next entry. Matches the thread_init_boot_thread in * boot.c. */ #ifndef CFG_NS_VIRTUALIZATION bl thread_clr_boot_thread #endif #ifdef CFG_CORE_FFA adr x0, cpu_on_handler /* * Compensate for the virtual map offset since cpu_on_handler() is * called with MMU off. */ ldr x1, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET sub x0, x0, x1 bl thread_spmc_register_secondary_ep b thread_ffa_msg_wait #else /* * Pass the vector address returned from main_init Compensate for * the virtual map offset since cpu_on_handler() is called with MMU * off. */ ldr x0, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET adr x1, thread_vector_table sub x1, x1, x0 mov x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE smc #0 /* SMC should not return */ panic_at_smc_return #endif END_FUNC _start DECLARE_KEEP_INIT _start .section .identity_map.data .balign 8 LOCAL_DATA cached_mem_end , : .skip 8 END_DATA cached_mem_end #if defined(CFG_CORE_ASLR) || defined(CFG_CORE_PHYS_RELOCATABLE) LOCAL_FUNC relocate , : /* * x0 holds relocate offset * x1 holds load address */ #ifdef CFG_WITH_PAGER adr_l x6, __init_end #else adr_l x6, __end #endif ldp w2, w3, [x6, #BOOT_EMBDATA_RELOC_OFFSET] add x2, x2, x6 /* start of relocations */ add x3, x3, x2 /* end of relocations */ /* * Relocations are not formatted as Rela64, instead they are in a * compressed format created by get_reloc_bin() in * scripts/gen_tee_bin.py * * All the R_AARCH64_RELATIVE relocations are translated into a * list of 32-bit offsets from TEE_LOAD_ADDR. At each address a * 64-bit value pointed out which increased with the load offset. */ #ifdef CFG_WITH_PAGER /* * With pager enabled we can only relocate the pager and init * parts, the rest has to be done when a page is populated. */ sub x6, x6, x1 #endif b 2f /* Loop over the relocation addresses and process all entries */ 1: ldr w4, [x2], #4 #ifdef CFG_WITH_PAGER /* Skip too large addresses */ cmp x4, x6 b.ge 2f #endif add x4, x4, x1 ldr x5, [x4] add x5, x5, x0 str x5, [x4] 2: cmp x2, x3 b.ne 1b ret END_FUNC relocate #endif /* * void enable_mmu(unsigned long core_pos); * * This function depends on being mapped with in the identity map where * physical address and virtual address is the same. After MMU has been * enabled the instruction pointer will be updated to execute as the new * offset instead. Stack pointers and the return address are updated. */ LOCAL_FUNC enable_mmu , : , .identity_map adr x1, boot_mmu_config load_xregs x1, 0, 2, 6 /* * x0 = core_pos * x2 = tcr_el1 * x3 = mair_el1 * x4 = ttbr0_el1_base * x5 = ttbr0_core_offset * x6 = load_offset */ msr tcr_el1, x2 msr mair_el1, x3 /* * ttbr0_el1 = ttbr0_el1_base + ttbr0_core_offset * core_pos */ madd x1, x5, x0, x4 msr ttbr0_el1, x1 msr ttbr1_el1, xzr isb /* Invalidate TLB */ tlbi vmalle1 /* * Make sure translation table writes have drained into memory and * the TLB invalidation is complete. */ dsb sy isb /* Enable the MMU */ mrs x1, sctlr_el1 orr x1, x1, #SCTLR_M msr sctlr_el1, x1 isb /* Update vbar */ mrs x1, vbar_el1 add x1, x1, x6 msr vbar_el1, x1 isb /* Invalidate instruction cache and branch predictor */ ic iallu isb /* Enable I and D cache */ mrs x1, sctlr_el1 orr x1, x1, #SCTLR_I orr x1, x1, #SCTLR_C msr sctlr_el1, x1 isb /* Adjust stack pointers and return address */ msr spsel, #1 add sp, sp, x6 msr spsel, #0 add sp, sp, x6 add x30, x30, x6 ret END_FUNC enable_mmu .section .identity_map.data .balign 8 DATA boot_mmu_config , : /* struct core_mmu_config */ .skip CORE_MMU_CONFIG_SIZE END_DATA boot_mmu_config FUNC cpu_on_handler , : mov x19, x0 mov x20, x1 mov x21, x30 adr x0, reset_vect_table msr vbar_el1, x0 isb set_sctlr_el1 isb #ifdef CFG_PAN init_pan #endif /* Enable aborts now that we can receive exceptions */ msr daifclr, #DAIFBIT_ABT bl __get_core_pos bl enable_mmu /* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */ set_sp #ifdef CFG_MEMTAG init_memtag_per_cpu #endif #ifdef CFG_CORE_PAUTH init_pauth_per_cpu #endif mov x0, x19 mov x1, x20 #ifdef CFG_CORE_FFA bl boot_cpu_on_handler b thread_ffa_msg_wait #else mov x30, x21 b boot_cpu_on_handler #endif END_FUNC cpu_on_handler DECLARE_KEEP_PAGER cpu_on_handler LOCAL_FUNC unhandled_cpu , : wfi b unhandled_cpu END_FUNC unhandled_cpu LOCAL_DATA stack_tmp_rel , : .word stack_tmp - stack_tmp_rel - STACK_TMP_GUARD END_DATA stack_tmp_rel /* * This macro verifies that the a given vector doesn't exceed the * architectural limit of 32 instructions. This is meant to be placed * immedately after the last instruction in the vector. It takes the * vector entry as the parameter */ .macro check_vector_size since .if (. - \since) > (32 * 4) .error "Vector exceeds 32 instructions" .endif .endm .section .identity_map, "ax", %progbits .align 11 LOCAL_FUNC reset_vect_table , :, .identity_map, , nobti /* ----------------------------------------------------- * Current EL with SP0 : 0x0 - 0x180 * ----------------------------------------------------- */ SynchronousExceptionSP0: b SynchronousExceptionSP0 check_vector_size SynchronousExceptionSP0 .align 7 IrqSP0: b IrqSP0 check_vector_size IrqSP0 .align 7 FiqSP0: b FiqSP0 check_vector_size FiqSP0 .align 7 SErrorSP0: b SErrorSP0 check_vector_size SErrorSP0 /* ----------------------------------------------------- * Current EL with SPx: 0x200 - 0x380 * ----------------------------------------------------- */ .align 7 SynchronousExceptionSPx: b SynchronousExceptionSPx check_vector_size SynchronousExceptionSPx .align 7 IrqSPx: b IrqSPx check_vector_size IrqSPx .align 7 FiqSPx: b FiqSPx check_vector_size FiqSPx .align 7 SErrorSPx: b SErrorSPx check_vector_size SErrorSPx /* ----------------------------------------------------- * Lower EL using AArch64 : 0x400 - 0x580 * ----------------------------------------------------- */ .align 7 SynchronousExceptionA64: b SynchronousExceptionA64 check_vector_size SynchronousExceptionA64 .align 7 IrqA64: b IrqA64 check_vector_size IrqA64 .align 7 FiqA64: b FiqA64 check_vector_size FiqA64 .align 7 SErrorA64: b SErrorA64 check_vector_size SErrorA64 /* ----------------------------------------------------- * Lower EL using AArch32 : 0x0 - 0x180 * ----------------------------------------------------- */ .align 7 SynchronousExceptionA32: b SynchronousExceptionA32 check_vector_size SynchronousExceptionA32 .align 7 IrqA32: b IrqA32 check_vector_size IrqA32 .align 7 FiqA32: b FiqA32 check_vector_size FiqA32 .align 7 SErrorA32: b SErrorA32 check_vector_size SErrorA32 END_FUNC reset_vect_table BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/generic_timer.c000066400000000000000000000030041464416617300222300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, Linaro Limited */ #include #include #include static void timer_disable(const struct callout_timer_desc *desc __unused) { write_cntps_ctl(0); } static void timer_set_next(const struct callout_timer_desc *desc __unused, uint64_t ctrval) { write_cntps_cval(ctrval); write_cntps_ctl(1); } static uint64_t timer_ms_to_ticks(const struct callout_timer_desc *desc __unused, uint32_t timeout_ms) { uint64_t freq = read_cntfrq(); return (freq * timeout_ms) / 1000; } static uint64_t timer_now(const struct callout_timer_desc *desc __unused) { return barrier_read_counter_timer(); } static struct itr_handler timer_itr __nex_bss; static const struct callout_timer_desc timer_desc __relrodata_unpaged("timer_desc") = { .disable_timeout = timer_disable, .set_next_timeout = timer_set_next, .ms_to_ticks = timer_ms_to_ticks, .get_now = timer_now, .is_per_cpu = true, }; DECLARE_KEEP_PAGER(timer_desc); static enum itr_return timer_itr_cb(struct itr_handler *h __unused) { callout_service_cb(); return ITRR_HANDLED; } DECLARE_KEEP_PAGER(timer_itr_cb); void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number) { timer_itr = (struct itr_handler){ .it = itr_number, .flags = ITRF_TRIGGER_LEVEL, .handler = timer_itr_cb, }; if (interrupt_add_handler_with_chip(itr_chip, &timer_itr)) panic(); interrupt_enable(timer_itr.chip, timer_itr.it); callout_service_init(&timer_desc); } optee_os-4.3.0/core/arch/arm/kernel/idle.c000066400000000000000000000002671464416617300203410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Huawei Technology Co., Ltd */ #include #include void cpu_idle(void) { dsb(); wfi(); } optee_os-4.3.0/core/arch/arm/kernel/kern.ld.S000066400000000000000000000333301464416617300207360ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND MIT) */ /* * Copyright (c) 2014, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2008-2010 Travis Geiselbrecht * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include /* * Note: * Clang 11 (ld.lld) generates non-relocatable reference when using ROUNDDOWN() * from , which does not work with ASLR. */ #define LD_ROUNDDOWN(x, y) ((x) - ((x) % (y))) OUTPUT_FORMAT(CFG_KERN_LINKER_FORMAT) OUTPUT_ARCH(CFG_KERN_LINKER_ARCH) ENTRY(_start) SECTIONS { . = TEE_LOAD_ADDR; ASSERT(!(TEE_LOAD_ADDR & (SMALL_PAGE_SIZE - 1)), "text start should be page aligned") __text_start = .; /* * Memory between TEE_LOAD_ADDR and page aligned rounded down * value will be mapped with unpaged "text" section attributes: * likely to be read-only/executable. */ __flatmap_unpg_rx_start = LD_ROUNDDOWN(__text_start, SMALL_PAGE_SIZE); .text : { KEEP(*(.text._start)) __identity_map_init_start = .; __text_data_start = .; *(.identity_map.data) __text_data_end = .; *(.identity_map .identity_map.* \ /* * The one below is needed because it's a weak * symbol that may be overridden by platform * specific code. */ .text.get_core_pos_mpidr) __identity_map_init_end = .; KEEP(*(.text.init .text.plat_cpu_reset_early \ .text.reset .text.reset_primary .text.unhandled_cpu \ .text.__assert_flat_mapped_range)) #ifdef CFG_WITH_PAGER *(.text) /* Include list of sections needed for paging */ #include #else *(.text .text.*) #endif *(.sram.text.glue_7* .gnu.linkonce.t.*) . = ALIGN(8); } __text_end = .; #ifdef CFG_CORE_RODATA_NOEXEC . = ALIGN(SMALL_PAGE_SIZE); #endif __flatmap_unpg_rx_size = . - __flatmap_unpg_rx_start; __flatmap_unpg_ro_start = .; .rodata : ALIGN(8) { __rodata_start = .; *(.gnu.linkonce.r.*) #ifdef CFG_WITH_PAGER *(.rodata .rodata.__unpaged .rodata.__unpaged.*) #include #else *(.rodata .rodata.*) #ifndef CFG_CORE_ASLR . = ALIGN(8); KEEP(*(SORT(.scattered_array*))); #endif #endif . = ALIGN(8); __rodata_end = .; } #if defined(CFG_CORE_ASLR) .data.rel.ro : { #if !defined(CFG_WITH_PAGER) . = ALIGN(8); KEEP(*(SORT(.scattered_array*))); #endif *(.data.rel.ro.__unpaged .data.rel.ro.__unpaged.*) } #endif .got : { *(.got.plt) *(.got) } .note.gnu.property : { *(.note.gnu.property) } .plt : { *(.plt) } .ctors : ALIGN(8) { __ctor_list = .; KEEP(*(.ctors .ctors.* .init_array .init_array.*)) __ctor_end = .; } .dtors : ALIGN(8) { __dtor_list = .; KEEP(*(.dtors .dtors.* .fini_array .fini_array.*)) __dtor_end = .; } /* .ARM.exidx is sorted, so has to go in its own output section. */ .ARM.exidx : { __exidx_start = .; *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = .; } .ARM.extab : { __extab_start = .; *(.ARM.extab*) __extab_end = .; } /* Start page aligned read-write memory */ #ifdef CFG_CORE_RWDATA_NOEXEC . = ALIGN(SMALL_PAGE_SIZE); #endif __flatmap_unpg_ro_size = . - __flatmap_unpg_ro_start; #ifdef CFG_NS_VIRTUALIZATION __flatmap_nex_rw_start = . ; .nex_data : ALIGN(8) { *(.nex_data .nex_data.*) } .nex_bss : ALIGN(8) { __nex_bss_start = .; *(.nex_bss .nex_bss.*) __nex_bss_end = .; } /* * We want to keep all nexus memory in one place, because * it should be always mapped and it is easier to map one * memory region than two. * Next section are NOLOAD ones, but they are followed * by sections with data. Thus, this NOLOAD section will * be included in the resulting binary, filled with zeroes */ .nex_stack (NOLOAD) : { __nozi_stack_start = .; KEEP(*(.nozi_stack.stack_tmp .nozi_stack.stack_abt)) . = ALIGN(8); __nozi_stack_end = .; } .nex_heap (NOLOAD) : { __nex_heap_start = .; . += CFG_CORE_NEX_HEAP_SIZE; . = ALIGN(16 * 1024); __nex_heap_end = .; } .nex_nozi (NOLOAD) : { ASSERT(!(ABSOLUTE(.) & (16 * 1024 - 1)), "align nozi to 16kB"); KEEP(*(.nozi.mmu.base_table .nozi.mmu.l2)) } . = ALIGN(SMALL_PAGE_SIZE); __flatmap_nex_rw_size = . - __flatmap_nex_rw_start; __flatmap_nex_rw_end = .; #endif __flatmap_unpg_rw_start = .; .data : ALIGN(8) { /* writable data */ __data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */ __data_start = .; *(.data .data.* .gnu.linkonce.d.*) . = ALIGN(8); } /* unintialized data */ .bss : { __data_end = .; __bss_start = .; *(.bss .bss.*) *(.gnu.linkonce.b.*) *(COMMON) . = ALIGN(8); __bss_end = .; } .heap1 (NOLOAD) : { /* * We're keeping track of the padding added before the * .nozi section so we can do something useful with * this otherwise wasted memory. */ __heap1_start = .; #ifndef CFG_WITH_PAGER . += CFG_CORE_HEAP_SIZE; #endif #ifdef CFG_WITH_LPAE . = ALIGN(4 * 1024); #else . = ALIGN(16 * 1024); #endif __heap1_end = .; } /* * Uninitialized data that shouldn't be zero initialized at * runtime. * * L1 mmu table requires 16 KiB alignment */ .nozi (NOLOAD) : { __nozi_start = .; KEEP(*(.nozi .nozi.*)) . = ALIGN(16); __nozi_end = .; /* * If virtualization is enabled, abt and tmp stacks will placed * at above .nex_stack section and thread stacks will go there */ __nozi_stack_start = .; KEEP(*(.nozi_stack .nozi_stack.*)) . = ALIGN(8); __nozi_stack_end = .; } #ifdef CFG_WITH_PAGER .heap2 (NOLOAD) : { __heap2_start = .; /* * Reserve additional memory for heap, the total should be * at least CFG_CORE_HEAP_SIZE, but count what has already * been reserved in .heap1 */ . += CFG_CORE_HEAP_SIZE - (__heap1_end - __heap1_start); . = ALIGN(SMALL_PAGE_SIZE); __heap2_end = .; } /* Start page aligned read-only memory */ __flatmap_unpg_rw_size = . - __flatmap_unpg_rw_start; __init_start = .; __flatmap_init_rx_start = .; ASSERT(!(__flatmap_init_rx_start & (SMALL_PAGE_SIZE - 1)), "read-write memory is not paged aligned") .text_init : { __text_init_start = .; /* * Include list of sections needed for boot initialization, this list * overlaps with unpaged.ld.S but since unpaged.ld.S is first all those * sections will go into the unpaged area. */ #include KEEP(*(.text.startup.*)); /* Make sure constructor functions are available during init */ KEEP(*(.text._GLOBAL__sub_*)); . = ALIGN(8); __text_init_end = .; } #ifdef CFG_CORE_RODATA_NOEXEC . = ALIGN(SMALL_PAGE_SIZE); #endif __flatmap_init_rx_size = . - __flatmap_init_rx_start; __flatmap_init_ro_start = .; .rodata_init : { __rodata_init_start = .; #include #ifndef CFG_CORE_ASLR . = ALIGN(8); KEEP(*(SORT(.scattered_array*))); #endif __rodata_init_end = .; } #ifdef CFG_CORE_ASLR .data.rel.ro_init : ALIGN(8) { KEEP(*(SORT(.scattered_array*))); } #endif . = ALIGN(8); __ro_and_relro_data_init_end = .; __init_end = ALIGN(__ro_and_relro_data_init_end, SMALL_PAGE_SIZE); __get_tee_init_end = __init_end; __init_size = __init_end - __init_start; /* vcore flat map stops here. No need to page align, rodata follows. */ __flatmap_init_ro_size = __init_end - __flatmap_init_ro_start; .rodata_pageable : ALIGN(8) { __rodata_pageable_start = .; *(.rodata*) __rodata_pageable_end = .; } #ifdef CFG_CORE_RODATA_NOEXEC . = ALIGN(SMALL_PAGE_SIZE); #endif .text_pageable : ALIGN(8) { __text_pageable_start = .; *(.text*) . = ALIGN(SMALL_PAGE_SIZE); __text_pageable_end = .; } __pageable_part_end = .; __pageable_part_start = __init_end; __pageable_start = __init_start; __pageable_end = __pageable_part_end; ASSERT(TEE_LOAD_ADDR >= TEE_RAM_START, "Load address before start of physical memory") ASSERT(TEE_LOAD_ADDR < (TEE_RAM_START + TEE_RAM_PH_SIZE), "Load address after end of physical memory") ASSERT((TEE_RAM_START + TEE_RAM_PH_SIZE - __init_end) > SMALL_PAGE_SIZE, "Too few free pages to initialize paging") #endif /*CFG_WITH_PAGER*/ #ifdef CFG_CORE_SANITIZE_KADDRESS . = TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8; . = ALIGN(8); .asan_shadow : { __asan_shadow_start = .; . += TEE_RAM_VA_SIZE / 9; __asan_shadow_end = .; __asan_shadow_size = __asan_shadow_end - __asan_shadow_start; } #endif /*CFG_CORE_SANITIZE_KADDRESS*/ __end = .; #ifndef CFG_WITH_PAGER __init_size = __data_end - TEE_LOAD_ADDR; #endif /* * Guard against moving the location counter backwards in the assignment * below. */ ASSERT(. <= (TEE_RAM_START + TEE_RAM_VA_SIZE), "TEE_RAM_VA_SIZE is too small") . = TEE_RAM_START + TEE_RAM_VA_SIZE; _end_of_ram = .; #ifndef CFG_WITH_PAGER __flatmap_unpg_rw_size = _end_of_ram - __flatmap_unpg_rw_start; __get_tee_init_end = .; #endif /* * These regions will not become a normal part of the dumped * binary, instead some are interpreted by the dump script and * converted into suitable format for OP-TEE itself to use. */ .dynamic : { *(.dynamic) } .hash : { *(.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel : { *(.rel.*) } .rela : { *(.rela.*) } #if !defined(CFG_CORE_ASLR) && !defined(CFG_CORE_PHYS_RELOCATABLE) ASSERT(SIZEOF(.rel) == 0, "Relocation entries not expected") ASSERT(SIZEOF(.rela) == 0, "Relocation entries not expected") #endif /DISCARD/ : { /* Strip unnecessary stuff */ *(.comment .note .eh_frame .interp) /* Strip meta variables */ *(__keep_meta_vars*) } } /* Unpaged read-only memories */ __vcore_unpg_rx_start = __flatmap_unpg_rx_start; __vcore_unpg_ro_start = __flatmap_unpg_ro_start; #ifdef CFG_CORE_RODATA_NOEXEC __vcore_unpg_rx_size = __flatmap_unpg_rx_size; __vcore_unpg_ro_size = __flatmap_unpg_ro_size; #else __vcore_unpg_rx_size = __flatmap_unpg_rx_size + __flatmap_unpg_ro_size; __vcore_unpg_ro_size = 0; #endif __vcore_unpg_rx_end = __vcore_unpg_rx_start + __vcore_unpg_rx_size; __vcore_unpg_ro_end = __vcore_unpg_ro_start + __vcore_unpg_ro_size; /* Unpaged read-write memory */ __vcore_unpg_rw_start = __flatmap_unpg_rw_start; __vcore_unpg_rw_size = __flatmap_unpg_rw_size; __vcore_unpg_rw_end = __vcore_unpg_rw_start + __vcore_unpg_rw_size; #ifdef CFG_NS_VIRTUALIZATION /* Nexus read-write memory */ __vcore_nex_rw_start = __flatmap_nex_rw_start; __vcore_nex_rw_size = __flatmap_nex_rw_size; __vcore_nex_rw_end = __vcore_nex_rw_start + __vcore_nex_rw_size; #endif #ifdef CFG_WITH_PAGER /* * Core init mapping shall cover up to end of the physical RAM. * This is required since the hash table is appended to the * binary data after the firmware build sequence. */ #define __FLATMAP_PAGER_TRAILING_SPACE \ (TEE_RAM_START + TEE_RAM_PH_SIZE - \ (__flatmap_init_ro_start + __flatmap_init_ro_size)) /* Paged/init read-only memories */ __vcore_init_rx_start = __flatmap_init_rx_start; __vcore_init_ro_start = __flatmap_init_ro_start; #ifdef CFG_CORE_RODATA_NOEXEC __vcore_init_rx_size = __flatmap_init_rx_size; __vcore_init_ro_size = __flatmap_init_ro_size + __FLATMAP_PAGER_TRAILING_SPACE; #else __vcore_init_rx_size = __flatmap_init_rx_size + __flatmap_init_ro_size + __FLATMAP_PAGER_TRAILING_SPACE; __vcore_init_ro_size = 0; #endif /* CFG_CORE_RODATA_NOEXEC */ __vcore_init_rx_end = __vcore_init_rx_start + __vcore_init_rx_size; __vcore_init_ro_end = __vcore_init_ro_start + __vcore_init_ro_size; #endif /* CFG_WITH_PAGER */ #ifdef CFG_CORE_SANITIZE_KADDRESS __asan_map_start = (__asan_shadow_start / SMALL_PAGE_SIZE) * SMALL_PAGE_SIZE; __asan_map_end = ((__asan_shadow_end - 1) / SMALL_PAGE_SIZE) * SMALL_PAGE_SIZE + SMALL_PAGE_SIZE; __asan_map_size = __asan_map_end - __asan_map_start; #endif /*CFG_CORE_SANITIZE_KADDRESS*/ optee_os-4.3.0/core/arch/arm/kernel/link.mk000066400000000000000000000232761464416617300205530ustar00rootroot00000000000000link-out-dir = $(out-dir)/core link-script-dummy = $(arch-dir)/kernel/link_dummy.ld link-script = $(if $(wildcard $(platform-dir)/kern.ld.S), \ $(platform-dir)/kern.ld.S, \ $(arch-dir)/kernel/kern.ld.S) link-script-pp = $(link-out-dir)/kern.ld link-script-dep = $(link-out-dir)/.kern.ld.d AWK = awk link-ldflags-common += $(call ld-option,--no-warn-rwx-segments) ifeq ($(CFG_ARM32_core),y) link-ldflags-common += $(call ld-option,--no-warn-execstack) endif link-ldflags = $(LDFLAGS) ifeq ($(call cfg-one-enabled, CFG_CORE_ASLR CFG_CORE_PHYS_RELOCATABLE),y) link-ldflags += -pie -Bsymbolic -z norelro $(ldflag-apply-dynamic-relocs) ifeq ($(CFG_ARM64_core),y) link-ldflags += -z text else # Suppression of relocations in read-only segments has not been done yet link-ldflags += -z notext endif endif ifeq ($(CFG_CORE_BTI),y) # force-bti tells the linker to warn if some object files lack the .note.gnu.property # section with the BTI flag, and to turn on the BTI flag in the output anyway. The # resulting executable would likely fail at runtime so we use this flag along # with the --fatal-warnings below to check and prevent this situation (with useful # diagnostics). link-ldflags += $(call ld-option,-z force-bti) --fatal-warnings endif link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)/tee.map link-ldflags += --sort-section=alignment link-ldflags += --fatal-warnings link-ldflags += --gc-sections link-ldflags += $(link-ldflags-common) link-ldadd = $(LDADD) link-ldadd += $(ldflags-external) link-ldadd += $(libdeps) link-objs := $(filter-out \ $(out-dir)/$(platform-dir)/link_dummies_paged.o \ $(out-dir)/$(platform-dir)/link_dummies_init.o \ $(out-dir)/$(arch-dir)/kernel/link_dummies_paged.o \ $(out-dir)/$(arch-dir)/kernel/link_dummies_init.o, \ $(objs)) link-objs-init := $(filter-out \ $(out-dir)/$(platform-dir)/link_dummies_init.o \ $(out-dir)/$(arch-dir)/kernel/link_dummies_init.o, \ $(objs)) ldargs-tee.elf := $(link-ldflags) $(link-objs) $(link-out-dir)/version.o \ $(link-ldadd) $(libgcccore) link-script-cppflags := \ $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ $(nostdinccore) $(CPPFLAGS) \ $(addprefix -I,$(incdirscore) $(link-out-dir)) \ $(cppflagscore)) ldargs-all_objs := -T $(link-script-dummy) --no-check-sections \ $(link-ldflags-common) \ $(link-objs) $(link-ldadd) $(libgcccore) cleanfiles += $(link-out-dir)/all_objs.o $(link-out-dir)/all_objs.o: $(objs) $(libdeps) $(MAKEFILE_LIST) @$(cmd-echo-silent) ' LD $@' $(q)$(LDcore) $(ldargs-all_objs) -o $@ cleanfiles += $(link-out-dir)/unpaged_entries.txt $(link-out-dir)/unpaged_entries.txt: $(link-out-dir)/all_objs.o @$(cmd-echo-silent) ' GEN $@' $(q)$(NMcore) $< | \ $(AWK) '/ ____keep_pager/ { printf "-u%s ", $$3 }' > $@ unpaged-ldargs := -T $(link-script-dummy) --no-check-sections --gc-sections \ $(link-ldflags-common) unpaged-ldadd := $(objs) $(link-ldadd) $(libgcccore) cleanfiles += $(link-out-dir)/unpaged.o $(link-out-dir)/unpaged.o: $(link-out-dir)/unpaged_entries.txt @$(cmd-echo-silent) ' LD $@' $(q)$(LDcore) $(unpaged-ldargs) \ `cat $(link-out-dir)/unpaged_entries.txt` \ $(unpaged-ldadd) -o $@ cleanfiles += $(link-out-dir)/text_unpaged.ld.S $(link-out-dir)/text_unpaged.ld.S: $(link-out-dir)/unpaged.o @$(cmd-echo-silent) ' GEN $@' $(q)$(READELFcore) -S -W $< | \ $(PYTHON3) ./scripts/gen_ld_sects.py .text. > $@ cleanfiles += $(link-out-dir)/rodata_unpaged.ld.S $(link-out-dir)/rodata_unpaged.ld.S: $(link-out-dir)/unpaged.o @$(cmd-echo-silent) ' GEN $@' $(q)$(READELFcore) -S -W $< | \ $(PYTHON3) ./scripts/gen_ld_sects.py .rodata. > $@ cleanfiles += $(link-out-dir)/init_entries.txt $(link-out-dir)/init_entries.txt: $(link-out-dir)/all_objs.o @$(cmd-echo-silent) ' GEN $@' $(q)$(NMcore) $< | \ $(AWK) '/ ____keep_init/ { printf "-u%s ", $$3 }' > $@ init-ldargs := -T $(link-script-dummy) --no-check-sections --gc-sections \ $(link-ldflags-common) init-ldadd := $(link-objs-init) $(link-out-dir)/version.o $(link-ldadd) \ $(libgcccore) cleanfiles += $(link-out-dir)/init.o $(link-out-dir)/init.o: $(link-out-dir)/init_entries.txt $(call gen-version-o) @$(cmd-echo-silent) ' LD $@' $(q)$(LDcore) $(init-ldargs) \ `cat $(link-out-dir)/init_entries.txt` \ $(init-ldadd) -o $@ cleanfiles += $(link-out-dir)/text_init.ld.S $(link-out-dir)/text_init.ld.S: $(link-out-dir)/init.o @$(cmd-echo-silent) ' GEN $@' $(q)$(READELFcore) -S -W $< | \ $(PYTHON3) ./scripts/gen_ld_sects.py .text. > $@ cleanfiles += $(link-out-dir)/rodata_init.ld.S $(link-out-dir)/rodata_init.ld.S: $(link-out-dir)/init.o @$(cmd-echo-silent) ' GEN $@' $(q)$(READELFcore) -S -W $< | $(PYTHON3) ./scripts/gen_ld_sects.py .rodata. > $@ -include $(link-script-dep) link-script-extra-deps += $(link-out-dir)/text_unpaged.ld.S link-script-extra-deps += $(link-out-dir)/rodata_unpaged.ld.S link-script-extra-deps += $(link-out-dir)/text_init.ld.S link-script-extra-deps += $(link-out-dir)/rodata_init.ld.S link-script-extra-deps += $(conf-file) cleanfiles += $(link-script-pp) $(link-script-dep) $(link-script-pp): $(link-script) $(link-script-extra-deps) @$(cmd-echo-silent) ' CPP $@' @mkdir -p $(dir $@) $(q)$(CPPcore) -P -MT $@ -MD -MF $(link-script-dep) \ $(link-script-cppflags) $< -o $@ define update-buildcount @$(cmd-echo-silent) ' UPD $(1)' $(q)if [ ! -f $(1) ]; then \ mkdir -p $(dir $(1)); \ echo 1 >$(1); \ else \ expr 0`cat $(1)` + 1 >$(1); \ fi endef # filter-out to workaround objdump warning version-o-cflags = $(filter-out -g3,$(core-platform-cflags) \ $(platform-cflags) $(cflagscore)) # SOURCE_DATE_EPOCH defined for reproducible builds ifneq ($(SOURCE_DATE_EPOCH),) date-opts = -d @$(SOURCE_DATE_EPOCH) endif DATE_STR = `LC_ALL=C date -u $(date-opts)` BUILD_COUNT_STR = `cat $(link-out-dir)/.buildcount` CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'` define gen-version-o $(call update-buildcount,$(link-out-dir)/.buildcount) @$(cmd-echo-silent) ' GEN $(link-out-dir)/version.o' $(q)echo -e "const char core_v_str[] =" \ "\"$(TEE_IMPL_VERSION) \"" \ "\"($(CORE_CC_VERSION)) \"" \ "\"#$(BUILD_COUNT_STR) \"" \ "\"$(DATE_STR) \"" \ "\"$(CFG_KERN_LINKER_ARCH)\";\n" \ | $(CCcore) $(version-o-cflags) \ -xc - -c -o $(link-out-dir)/version.o endef $(link-out-dir)/version.o: $(call gen-version-o) -include $(link-out-dir)/.tee.elf.cmd define check-link-objs $(if $(strip $(filter-out $(link-objs), $(old-link-objs)) $(filter-out $(old-link-objs), $(link-objs))), FORCE_LINK := FORCE) endef $(eval $(call check-link-objs)) all: $(link-out-dir)/tee.elf cleanfiles += $(link-out-dir)/tee.elf $(link-out-dir)/tee.map cleanfiles += $(link-out-dir)/version.o cleanfiles += $(link-out-dir)/.buildcount cleanfiles += $(link-out-dir)/.tee.elf.cmd $(link-out-dir)/tee.elf: $(link-objs) $(libdeps) $(link-script-pp) $(FORCE_LINK) @echo "old-link-objs := $(link-objs)" >$(link-out-dir)/.tee.elf.cmd @$(cmd-echo-silent) ' LD $@' $(q)$(LDcore) $(ldargs-tee.elf) -o $@ all: $(link-out-dir)/tee.dmp cleanfiles += $(link-out-dir)/tee.dmp $(link-out-dir)/tee.dmp: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' OBJDUMP $@' $(q)$(OBJDUMPcore) -l -x -d $< > $@ cleanfiles += $(link-out-dir)/tee-pager.bin $(link-out-dir)/tee-pager.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py @echo Warning: $@ is deprecated @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_pager_bin $@ cleanfiles += $(link-out-dir)/tee-pageable.bin $(link-out-dir)/tee-pageable.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py @echo Warning: $@ is deprecated @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_pageable_bin $@ all: $(link-out-dir)/tee.bin cleanfiles += $(link-out-dir)/tee.bin $(link-out-dir)/tee.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_tee_bin $@ all: $(link-out-dir)/tee-header_v2.bin cleanfiles += $(link-out-dir)/tee-header_v2.bin $(link-out-dir)/tee-header_v2.bin: $(link-out-dir)/tee.elf \ scripts/gen_tee_bin.py @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_header_v2 $@ all: $(link-out-dir)/tee-pager_v2.bin cleanfiles += $(link-out-dir)/tee-pager_v2.bin $(link-out-dir)/tee-pager_v2.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_pager_v2 $@ all: $(link-out-dir)/tee-pageable_v2.bin cleanfiles += $(link-out-dir)/tee-pageable_v2.bin $(link-out-dir)/tee-pageable_v2.bin: $(link-out-dir)/tee.elf \ scripts/gen_tee_bin.py @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) scripts/gen_tee_bin.py --input $< --out_pageable_v2 $@ all: $(link-out-dir)/tee.symb_sizes cleanfiles += $(link-out-dir)/tee.symb_sizes $(link-out-dir)/tee.symb_sizes: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' GEN $@' $(q)$(NMcore) --print-size --reverse-sort --size-sort $< > $@ cleanfiles += $(link-out-dir)/tee.mem_usage ifneq ($(filter mem_usage,$(MAKECMDGOALS)),) mem_usage: $(link-out-dir)/tee.mem_usage $(link-out-dir)/tee.mem_usage: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) ./scripts/mem_usage.py $< > $@ endif all: $(link-out-dir)/tee-raw.bin cleanfiles += $(link-out-dir)/tee-raw.bin $(link-out-dir)/tee-raw.bin: $(link-out-dir)/tee.elf scripts/gen_tee_bin.py @$(cmd-echo-silent) ' GEN $@' $(q)scripts/gen_tee_bin.py --input $< --out_tee_raw_bin $@ cleanfiles += $(link-out-dir)/tee.srec $(link-out-dir)/tee.srec: $(link-out-dir)/tee-raw.bin @$(cmd-echo-silent) ' SREC $@' $(q)$(OBJCOPYcore) -I binary -O srec $(SRECFLAGS) $< $@ optee_os-4.3.0/core/arch/arm/kernel/link_dummies_init.c000066400000000000000000000012731464416617300231250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited */ #include #include #include void __section(".text.dummy.boot_save_boot_info") boot_save_args(unsigned long a0 __unused, unsigned long a1 __unused, unsigned long a2 __unused, unsigned long a3 __unused, unsigned long a4 __unused) { } unsigned long __section(".text.dummy.get_aslr_seed") get_aslr_seed(void) { return 0; } void __section(".text.dummy.core_init_mmu_map") core_init_mmu_map(unsigned long seed __unused, struct core_mmu_config *cfg __unused) { } void __section(".text.dummy.boot_init_primary_early") boot_init_primary_early(void) { } optee_os-4.3.0/core/arch/arm/kernel/link_dummies_paged.c000066400000000000000000000032371464416617300232440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2021, Linaro Limited * Copyright (c) 2023, Arm Limited */ #include #include #include #include #include #include #include #include #include #include void __section(".text.dummy.call_preinitcalls") call_preinitcalls(void) { } void __section(".text.dummy.call_initcalls") call_initcalls(void) { } void __section(".text.dummy.call_finalcalls") call_finalcalls(void) { } void __section(".text.dummy.boot_init_primary_late") boot_init_primary_late(unsigned long fdt __unused, unsigned long manifest __unused) { } uint32_t __section(".text.dummy.__thread_std_smc_entry") __thread_std_smc_entry(uint32_t a0 __unused, uint32_t a1 __unused, uint32_t a2 __unused, uint32_t a3 __unused, uint32_t a4 __unused, uint32_t a5 __unused) { return 0; } const struct mobj_ops mobj_reg_shm_ops __rodata_dummy; const struct mobj_ops mobj_phys_ops __rodata_dummy; const struct mobj_ops mobj_virt_ops __rodata_dummy; const struct mobj_ops mobj_shm_ops __rodata_dummy; const struct mobj_ops mobj_with_fobj_ops __rodata_dummy; const struct fobj_ops ops_rwp_paged_iv __rodata_dummy; const struct fobj_ops ops_rwp_unpaged_iv __rodata_dummy; const struct fobj_ops ops_ro_paged __rodata_dummy; const struct fobj_ops ops_ro_reloc_paged __rodata_dummy; const struct fobj_ops ops_locked_paged __rodata_dummy; const struct fobj_ops ops_sec_mem __rodata_dummy; const struct ts_ops user_ta_ops __rodata_dummy; const struct ts_ops stmm_sp_ops __rodata_dummy; optee_os-4.3.0/core/arch/arm/kernel/link_dummy.ld000066400000000000000000000044011464416617300217430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ SECTIONS { /* * This seems to make the ARMv7 linker happy with regards to glue_7 * sections etc. */ ..dummy : { } } __asan_map_end = .; __asan_map_size = .; __asan_map_start = .; __asan_shadow_end = .; __asan_shadow_size = .; __asan_shadow_start = .; __bss_end = .; __bss_start = .; __ctor_end = .; __ctor_list = .; __data_end = .; __data_start = .; __end = .; __end_phys_ddr_overall_section = .; __end_phys_mem_map_section = .; __end_phys_nsec_ddr_section = .; __end_phys_sdp_mem_section = .; __exidx_end = .; __exidx_start = .; __extab_end = .; __extab_start = .; __heap1_end = .; __heap1_start = .; __heap2_end = .; __heap2_start = .; __identity_map_init_end = .; __identity_map_init_start = .; __initcall_end = .; __initcall_start = .; __init_end = .; __init_size = .; __init_start = .; __nex_bss_end = .; __nex_bss_start = .; __nex_heap_end = .; __nex_heap_start = .; __nozi_end = .; __nozi_stack_end = .; __nozi_stack_start = .; __nozi_start = .; __pageable_end = .; __pageable_part_end = .; __pageable_part_start = .; __pageable_start = .; __rela_end = .; __rela_start = .; __rel_end = .; __rel_start = .; __ro_and_relro_data_init_end = .; __rodata_early_ta_end = .; __rodata_early_ta_start = .; __rodata_end = .; __rodata_init_end = .; __rodata_init_start = .; __rodata_pageable_end = .; __rodata_pageable_start = .; __rodata_start = .; __start_phys_ddr_overall_section = .; __start_phys_nsec_ddr_section = .; __text_init_end = .; __text_init_start = .; __text_pageable_end = .; __text_pageable_start = .; __text_start = .; __text_data_start = .; __text_data_end = .; __text_end = .; __tmp_hashes_end = .; __tmp_hashes_size = .; __tmp_hashes_start = .; __vcore_init_ro_end = .; __vcore_init_ro_size = .; __vcore_init_ro_start = .; __vcore_init_rx_end = .; __vcore_init_rx_size = .; __vcore_init_rx_start = .; __vcore_nex_rw_end = .; __vcore_nex_rw_size = .; __vcore_nex_rw_start = .; __vcore_unpg_ro_end = .; __vcore_unpg_ro_size = .; __vcore_unpg_ro_start = .; __vcore_unpg_rw_end = .; __vcore_unpg_rw_size = .; __vcore_unpg_rw_start = .; __vcore_unpg_rx_end = .; __vcore_unpg_rx_size = .; __vcore_unpg_rx_start = .; PROVIDE(core_v_str = 0); PROVIDE(tee_entry_std = 0); PROVIDE(init_teecore = 0); optee_os-4.3.0/core/arch/arm/kernel/misc_a32.S000066400000000000000000000055531464416617300210070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2019, Arm Limited. All rights reserved. */ #include #include #include #include /* size_t __get_core_pos(void); */ FUNC __get_core_pos , : , .identity_map read_mpidr r0 b get_core_pos_mpidr END_FUNC __get_core_pos /* size_t get_core_pos_mpidr(uint32_t mpidr); */ /* Let platforms override this if needed */ WEAK_FUNC get_core_pos_mpidr , : mov r3, r0 /* * Shift MPIDR value if it's not already shifted. * Using logical shift ensures AFF0 to be filled with zeroes. * This part is necessary even if CFG_CORE_THREAD_SHIFT is 0 because * MT bit can be set on single threaded systems where all the AFF0 * values are zeroes. */ tst r0, #MPIDR_MT_MASK lsleq r3, r0, #MPIDR_AFFINITY_BITS /* * At this point the MPIDR layout is always shifted so it looks * as follows AFF2 -> cluster, AFF1 -> core, AFF0 -> thread */ #if CFG_CORE_THREAD_SHIFT == 0 /* Calculate CorePos = (ClusterId * (cores/cluster)) + CoreId */ ubfx r0, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ubfx r1, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS add r0, r0, r1, LSL #(CFG_CORE_CLUSTER_SHIFT) #else /* * Calculate CorePos = * ((ClusterId * (cores/cluster)) + CoreId) * (threads/core) + ThreadId */ ubfx r0, r3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS ubfx r1, r3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ubfx r2, r3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS add r1, r1, r2, LSL #(CFG_CORE_CLUSTER_SHIFT) add r0, r0, r1, LSL #(CFG_CORE_THREAD_SHIFT) #endif bx lr END_FUNC get_core_pos_mpidr /* * uint32_t temp_set_mode(int cpu_mode) * returns cpsr to be set */ LOCAL_FUNC temp_set_mode , : mov r1, r0 cmp r1, #CPSR_MODE_USR /* update mode: usr -> sys */ moveq r1, #CPSR_MODE_SYS cpsid aif /* disable interrupts */ mrs r0, cpsr /* get cpsr with disabled its*/ bic r0, #CPSR_MODE_MASK /* clear mode */ orr r0, r1 /* set expected mode */ bx lr END_FUNC temp_set_mode /* uint32_t read_mode_sp(int cpu_mode) */ FUNC read_mode_sp , : push {r4, lr} UNWIND( .save {r4, lr}) mrs r4, cpsr /* save cpsr */ bl temp_set_mode msr cpsr, r0 /* set the new mode */ mov r0, sp /* get the function result */ msr cpsr, r4 /* back to the old mode */ pop {r4, pc} END_FUNC read_mode_sp /* uint32_t read_mode_lr(int cpu_mode) */ FUNC read_mode_lr , : push {r4, lr} UNWIND( .save {r4, lr}) mrs r4, cpsr /* save cpsr */ bl temp_set_mode msr cpsr, r0 /* set the new mode */ mov r0, lr /* get the function result */ msr cpsr, r4 /* back to the old mode */ pop {r4, pc} END_FUNC read_mode_lr /* void wait_cycles(unsigned long cycles) */ FUNC wait_cycles , : /* Divide by 4 since each loop will take 4 cycles to complete */ lsrs r0, r0, #2 bxeq lr loop: subs r0, r0, #1 nop bne loop bx lr END_FUNC wait_cycles optee_os-4.3.0/core/arch/arm/kernel/misc_a64.S000066400000000000000000000032551464416617300210110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2019, Arm Limited. All rights reserved. */ #include #include #include /* size_t __get_core_pos(void); */ FUNC __get_core_pos , : , .identity_map mrs x0, mpidr_el1 b get_core_pos_mpidr END_FUNC __get_core_pos /* size_t get_core_pos_mpidr(uint32_t mpidr); */ /* Let platforms override this if needed */ WEAK_FUNC get_core_pos_mpidr , : /* * Shift MPIDR value if it's not already shifted. * Using logical shift ensures AFF0 to be filled with zeroes. * This part is necessary even if CFG_CORE_THREAD_SHIFT is 0 because * MT bit can be set on single threaded systems where all the AFF0 * values are zeroes. */ tst x0, #MPIDR_MT_MASK lsl x3, x0, #MPIDR_AFFINITY_BITS csel x3, x3, x0, eq /* * At this point the MPIDR layout is always shifted so it looks * as follows AFF2 -> cluster, AFF1 -> core, AFF0 -> thread */ #if CFG_CORE_THREAD_SHIFT == 0 /* Calculate CorePos = (ClusterId * (cores/cluster)) + CoreId */ ubfx x0, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ubfx x1, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS add x0, x0, x1, LSL #(CFG_CORE_CLUSTER_SHIFT) #else /* * Calculate CorePos = * ((ClusterId * (cores/cluster)) + CoreId) * (threads/core) + ThreadId */ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS add x1, x1, x2, LSL #(CFG_CORE_CLUSTER_SHIFT) add x0, x0, x1, LSL #(CFG_CORE_THREAD_SHIFT) #endif ret END_FUNC get_core_pos_mpidr BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/rpc_io_i2c.c000066400000000000000000000031741464416617300214340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020 Foundries Ltd */ #include #include #include #include /* * @brief: I2C master transfer request to an I2C slave device. * It is the responsibility of the caller to validate the number of bytes * processed by the REE. * * @param req: the secure world I2C master request * @param len: the number of bytes processed by REE * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error. */ TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *req, size_t *len) { struct thread_param p[4] = { }; TEE_Result res = TEE_SUCCESS; struct mobj *mobj = NULL; uint8_t *va = NULL; assert(req); if (!len) return TEE_ERROR_BAD_PARAMETERS; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_I2C, THREAD_SHM_TYPE_KERNEL_PRIVATE, req->buffer_len, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; if (req->mode == RPC_I2C_MODE_WRITE) memcpy(va, req->buffer, req->buffer_len); p[0] = THREAD_PARAM_VALUE(IN, req->mode, req->bus, req->chip); p[1] = THREAD_PARAM_VALUE(IN, req->flags, 0, 0); p[2] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, req->buffer_len); p[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); res = thread_rpc_cmd(OPTEE_RPC_CMD_I2C_TRANSFER, ARRAY_SIZE(p), p); if (res != TEE_SUCCESS) return res; /* * Reporting more bytes than supplied or requested from the I2C chip is * an REE error */ if (p[3].u.value.a > req->buffer_len) return TEE_ERROR_EXCESS_DATA; *len = p[3].u.value.a; if (req->mode == RPC_I2C_MODE_READ) memcpy(req->buffer, va, *len); return TEE_SUCCESS; } optee_os-4.3.0/core/arch/arm/kernel/secure_partition.c000066400000000000000000001376051464416617300230120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020-2024, Arm Limited. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BOUNCE_BUFFER_SIZE 4096 #define SP_MANIFEST_ATTR_READ BIT(0) #define SP_MANIFEST_ATTR_WRITE BIT(1) #define SP_MANIFEST_ATTR_EXEC BIT(2) #define SP_MANIFEST_ATTR_NSEC BIT(3) #define SP_MANIFEST_ATTR_RO (SP_MANIFEST_ATTR_READ) #define SP_MANIFEST_ATTR_RW (SP_MANIFEST_ATTR_READ | \ SP_MANIFEST_ATTR_WRITE) #define SP_MANIFEST_ATTR_RX (SP_MANIFEST_ATTR_READ | \ SP_MANIFEST_ATTR_EXEC) #define SP_MANIFEST_ATTR_RWX (SP_MANIFEST_ATTR_READ | \ SP_MANIFEST_ATTR_WRITE | \ SP_MANIFEST_ATTR_EXEC) #define SP_MANIFEST_FLAG_NOBITS BIT(0) #define SP_MANIFEST_NS_INT_QUEUED (0x0) #define SP_MANIFEST_NS_INT_MANAGED_EXIT (0x1) #define SP_MANIFEST_NS_INT_SIGNALED (0x2) #define SP_PKG_HEADER_MAGIC (0x474b5053) #define SP_PKG_HEADER_VERSION_V1 (0x1) #define SP_PKG_HEADER_VERSION_V2 (0x2) struct sp_pkg_header { uint32_t magic; uint32_t version; uint32_t pm_offset; uint32_t pm_size; uint32_t img_offset; uint32_t img_size; }; struct fip_sp_head fip_sp_list = STAILQ_HEAD_INITIALIZER(fip_sp_list); static const struct ts_ops sp_ops; /* List that holds all of the loaded SP's */ static struct sp_sessions_head open_sp_sessions = TAILQ_HEAD_INITIALIZER(open_sp_sessions); static const struct embedded_ts *find_secure_partition(const TEE_UUID *uuid) { const struct sp_image *sp = NULL; const struct fip_sp *fip_sp = NULL; for_each_secure_partition(sp) { if (!memcmp(&sp->image.uuid, uuid, sizeof(*uuid))) return &sp->image; } for_each_fip_sp(fip_sp) { if (!memcmp(&fip_sp->sp_img.image.uuid, uuid, sizeof(*uuid))) return &fip_sp->sp_img.image; } return NULL; } bool is_sp_ctx(struct ts_ctx *ctx) { return ctx && (ctx->ops == &sp_ops); } static void set_sp_ctx_ops(struct ts_ctx *ctx) { ctx->ops = &sp_ops; } struct sp_session *sp_get_session(uint32_t session_id) { struct sp_session *s = NULL; TAILQ_FOREACH(s, &open_sp_sessions, link) { if (s->endpoint_id == session_id) return s; } return NULL; } TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size, const TEE_UUID *ffa_uuid, size_t *elem_count, bool count_only) { TEE_Result res = TEE_SUCCESS; uint32_t part_props = FFA_PART_PROP_DIRECT_REQ_RECV | FFA_PART_PROP_DIRECT_REQ_SEND; struct sp_session *s = NULL; TAILQ_FOREACH(s, &open_sp_sessions, link) { if (ffa_uuid && memcmp(&s->ffa_uuid, ffa_uuid, sizeof(*ffa_uuid))) continue; if (s->state == sp_dead) continue; if (!count_only && !res) { uint32_t uuid_words[4] = { 0 }; tee_uuid_to_octets((uint8_t *)uuid_words, &s->ffa_uuid); res = spmc_fill_partition_entry(ffa_vers, buf, buf_size, *elem_count, s->endpoint_id, 1, part_props, uuid_words); } *elem_count += 1; } return res; } bool sp_has_exclusive_access(struct sp_mem_map_region *mem, struct user_mode_ctx *uctx) { /* * Check that we have access to the region if it is supposed to be * mapped to the current context. */ if (uctx) { struct vm_region *region = NULL; /* Make sure that each mobj belongs to the SP */ TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { if (region->mobj == mem->mobj) break; } if (!region) return false; } /* Check that it is not shared with another SP */ return !sp_mem_is_shared(mem); } static bool endpoint_id_is_valid(uint32_t id) { /* * These IDs are assigned at the SPMC init so already have valid values * by the time this function gets first called */ return id != spmd_id && id != spmc_id && id != optee_endpoint_id && id >= FFA_SWD_ID_MIN && id <= FFA_SWD_ID_MAX; } static TEE_Result new_session_id(uint16_t *endpoint_id) { uint32_t id = 0; /* Find the first available endpoint id */ for (id = FFA_SWD_ID_MIN; id <= FFA_SWD_ID_MAX; id++) { if (endpoint_id_is_valid(id) && !sp_get_session(id)) { *endpoint_id = id; return TEE_SUCCESS; } } return TEE_ERROR_BAD_FORMAT; } static TEE_Result sp_create_ctx(const TEE_UUID *bin_uuid, struct sp_session *s) { TEE_Result res = TEE_SUCCESS; struct sp_ctx *spc = NULL; /* Register context */ spc = calloc(1, sizeof(struct sp_ctx)); if (!spc) return TEE_ERROR_OUT_OF_MEMORY; spc->open_session = s; s->ts_sess.ctx = &spc->ts_ctx; spc->ts_ctx.uuid = *bin_uuid; res = vm_info_init(&spc->uctx, &spc->ts_ctx); if (res) goto err; set_sp_ctx_ops(&spc->ts_ctx); return TEE_SUCCESS; err: free(spc); return res; } /* * Insert a new sp_session to the sessions list, so that it is ordered * by boot_order. */ static void insert_session_ordered(struct sp_sessions_head *open_sessions, struct sp_session *session) { struct sp_session *s = NULL; if (!open_sessions || !session) return; TAILQ_FOREACH(s, &open_sp_sessions, link) { if (s->boot_order > session->boot_order) break; } if (!s) TAILQ_INSERT_TAIL(open_sessions, session, link); else TAILQ_INSERT_BEFORE(s, session, link); } static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions, const TEE_UUID *bin_uuid, const uint32_t boot_order, struct sp_session **sess) { TEE_Result res = TEE_SUCCESS; struct sp_session *s = calloc(1, sizeof(struct sp_session)); if (!s) return TEE_ERROR_OUT_OF_MEMORY; s->boot_order = boot_order; res = new_session_id(&s->endpoint_id); if (res) goto err; DMSG("Loading Secure Partition %pUl", (void *)bin_uuid); res = sp_create_ctx(bin_uuid, s); if (res) goto err; insert_session_ordered(open_sessions, s); *sess = s; return TEE_SUCCESS; err: free(s); return res; } static TEE_Result sp_init_set_registers(struct sp_ctx *ctx) { struct thread_ctx_regs *sp_regs = &ctx->sp_regs; memset(sp_regs, 0, sizeof(*sp_regs)); sp_regs->sp = ctx->uctx.stack_ptr; sp_regs->pc = ctx->uctx.entry_func; return TEE_SUCCESS; } TEE_Result sp_map_shared(struct sp_session *s, struct sp_mem_receiver *receiver, struct sp_mem *smem, uint64_t *va) { TEE_Result res = TEE_SUCCESS; struct sp_ctx *ctx = NULL; uint32_t perm = TEE_MATTR_UR; struct sp_mem_map_region *reg = NULL; ctx = to_sp_ctx(s->ts_sess.ctx); /* Get the permission */ if (receiver->perm.perm & FFA_MEM_ACC_EXE) perm |= TEE_MATTR_UX; if (receiver->perm.perm & FFA_MEM_ACC_RW) { if (receiver->perm.perm & FFA_MEM_ACC_EXE) return TEE_ERROR_ACCESS_CONFLICT; perm |= TEE_MATTR_UW; } /* * Currently we don't support passing a va. We can't guarantee that the * full region will be mapped in a contiguous region. A smem->region can * have multiple mobj for one share. Currently there doesn't seem to be * an option to guarantee that these will be mapped in a contiguous va * space. */ if (*va) return TEE_ERROR_NOT_SUPPORTED; SLIST_FOREACH(reg, &smem->regions, link) { res = vm_map(&ctx->uctx, va, reg->page_count * SMALL_PAGE_SIZE, perm, 0, reg->mobj, reg->page_offset); if (res != TEE_SUCCESS) { EMSG("Failed to map memory region %#"PRIx32, res); return res; } } return TEE_SUCCESS; } TEE_Result sp_unmap_ffa_regions(struct sp_session *s, struct sp_mem *smem) { TEE_Result res = TEE_SUCCESS; vaddr_t vaddr = 0; size_t len = 0; struct sp_ctx *ctx = to_sp_ctx(s->ts_sess.ctx); struct sp_mem_map_region *reg = NULL; SLIST_FOREACH(reg, &smem->regions, link) { vaddr = (vaddr_t)sp_mem_get_va(&ctx->uctx, reg->page_offset, reg->mobj); len = reg->page_count * SMALL_PAGE_SIZE; res = vm_unmap(&ctx->uctx, vaddr, len); if (res != TEE_SUCCESS) return res; } return TEE_SUCCESS; } static TEE_Result sp_dt_get_u64(const void *fdt, int node, const char *property, uint64_t *value) { const fdt64_t *p = NULL; int len = 0; p = fdt_getprop(fdt, node, property, &len); if (!p) return TEE_ERROR_ITEM_NOT_FOUND; if (len != sizeof(*p)) return TEE_ERROR_BAD_FORMAT; *value = fdt64_ld(p); return TEE_SUCCESS; } static TEE_Result sp_dt_get_u32(const void *fdt, int node, const char *property, uint32_t *value) { const fdt32_t *p = NULL; int len = 0; p = fdt_getprop(fdt, node, property, &len); if (!p) return TEE_ERROR_ITEM_NOT_FOUND; if (len != sizeof(*p)) return TEE_ERROR_BAD_FORMAT; *value = fdt32_to_cpu(*p); return TEE_SUCCESS; } static TEE_Result sp_dt_get_u16(const void *fdt, int node, const char *property, uint16_t *value) { const fdt16_t *p = NULL; int len = 0; p = fdt_getprop(fdt, node, property, &len); if (!p) return TEE_ERROR_ITEM_NOT_FOUND; if (len != sizeof(*p)) return TEE_ERROR_BAD_FORMAT; *value = fdt16_to_cpu(*p); return TEE_SUCCESS; } static TEE_Result sp_dt_get_uuid(const void *fdt, int node, const char *property, TEE_UUID *uuid) { uint32_t uuid_array[4] = { 0 }; const fdt32_t *p = NULL; int len = 0; int i = 0; p = fdt_getprop(fdt, node, property, &len); if (!p) return TEE_ERROR_ITEM_NOT_FOUND; if (len != sizeof(TEE_UUID)) return TEE_ERROR_BAD_FORMAT; for (i = 0; i < 4; i++) uuid_array[i] = fdt32_to_cpu(p[i]); tee_uuid_from_octets(uuid, (uint8_t *)uuid_array); return TEE_SUCCESS; } static TEE_Result sp_is_elf_format(const void *fdt, int sp_node, bool *is_elf_format) { TEE_Result res = TEE_SUCCESS; uint32_t elf_format = 0; res = sp_dt_get_u32(fdt, sp_node, "elf-format", &elf_format); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) return res; *is_elf_format = (elf_format != 0); return TEE_SUCCESS; } static TEE_Result sp_binary_open(const TEE_UUID *uuid, const struct ts_store_ops **ops, struct ts_store_handle **handle) { TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; SCATTERED_ARRAY_FOREACH(*ops, sp_stores, struct ts_store_ops) { res = (*ops)->open(uuid, handle); if (res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) break; } return res; } static TEE_Result load_binary_sp(struct ts_session *s, struct user_mode_ctx *uctx) { size_t bin_size = 0, bin_size_rounded = 0, bin_page_count = 0; size_t bb_size = ROUNDUP(BOUNCE_BUFFER_SIZE, SMALL_PAGE_SIZE); size_t bb_num_pages = bb_size / SMALL_PAGE_SIZE; const struct ts_store_ops *store_ops = NULL; struct ts_store_handle *handle = NULL; TEE_Result res = TEE_SUCCESS; tee_mm_entry_t *mm = NULL; struct fobj *fobj = NULL; struct mobj *mobj = NULL; uaddr_t base_addr = 0; uint32_t vm_flags = 0; unsigned int idx = 0; vaddr_t va = 0; if (!s || !uctx) return TEE_ERROR_BAD_PARAMETERS; DMSG("Loading raw binary format SP %pUl", &uctx->ts_ctx->uuid); /* Initialize the bounce buffer */ fobj = fobj_sec_mem_alloc(bb_num_pages); mobj = mobj_with_fobj_alloc(fobj, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(fobj); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map(uctx, &va, bb_size, TEE_MATTR_PRW, 0, mobj, 0); mobj_put(mobj); if (res) return res; uctx->bbuf = (uint8_t *)va; uctx->bbuf_size = BOUNCE_BUFFER_SIZE; vm_set_ctx(uctx->ts_ctx); /* Find TS store and open SP binary */ res = sp_binary_open(&uctx->ts_ctx->uuid, &store_ops, &handle); if (res != TEE_SUCCESS) { EMSG("Failed to open SP binary"); return res; } /* Query binary size and calculate page count */ res = store_ops->get_size(handle, &bin_size); if (res != TEE_SUCCESS) goto err; if (ROUNDUP_OVERFLOW(bin_size, SMALL_PAGE_SIZE, &bin_size_rounded)) { res = TEE_ERROR_OVERFLOW; goto err; } bin_page_count = bin_size_rounded / SMALL_PAGE_SIZE; /* Allocate memory */ mm = tee_mm_alloc(&tee_mm_sec_ddr, bin_size_rounded); if (!mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } base_addr = tee_mm_get_smem(mm); /* Create mobj */ mobj = sp_mem_new_mobj(bin_page_count, TEE_MATTR_MEM_TYPE_CACHED, true); if (!mobj) { res = TEE_ERROR_OUT_OF_MEMORY; goto err_free_tee_mm; } res = sp_mem_add_pages(mobj, &idx, base_addr, bin_page_count); if (res) goto err_free_mobj; /* Map memory area for the SP binary */ va = 0; res = vm_map(uctx, &va, bin_size_rounded, TEE_MATTR_URWX, vm_flags, mobj, 0); if (res) goto err_free_mobj; /* Read SP binary into the previously mapped memory area */ res = store_ops->read(handle, NULL, (void *)va, bin_size); if (res) goto err_unmap; /* Set memory protection to allow execution */ res = vm_set_prot(uctx, va, bin_size_rounded, TEE_MATTR_UX); if (res) goto err_unmap; mobj_put(mobj); store_ops->close(handle); /* The entry point must be at the beginning of the SP binary. */ uctx->entry_func = va; uctx->load_addr = va; uctx->is_32bit = false; s->handle_scall = s->ctx->ops->handle_scall; return TEE_SUCCESS; err_unmap: vm_unmap(uctx, va, bin_size_rounded); err_free_mobj: mobj_put(mobj); err_free_tee_mm: tee_mm_free(mm); err: store_ops->close(handle); return res; } static TEE_Result sp_open_session(struct sp_session **sess, struct sp_sessions_head *open_sessions, const TEE_UUID *ffa_uuid, const TEE_UUID *bin_uuid, const uint32_t boot_order, const void *fdt) { TEE_Result res = TEE_SUCCESS; struct sp_session *s = NULL; struct sp_ctx *ctx = NULL; bool is_elf_format = false; if (!find_secure_partition(bin_uuid)) return TEE_ERROR_ITEM_NOT_FOUND; res = sp_create_session(open_sessions, bin_uuid, boot_order, &s); if (res != TEE_SUCCESS) { DMSG("sp_create_session failed %#"PRIx32, res); return res; } ctx = to_sp_ctx(s->ts_sess.ctx); assert(ctx); if (!ctx) return TEE_ERROR_TARGET_DEAD; *sess = s; ts_push_current_session(&s->ts_sess); res = sp_is_elf_format(fdt, 0, &is_elf_format); if (res == TEE_SUCCESS) { if (is_elf_format) { /* Load the SP using ldelf. */ ldelf_load_ldelf(&ctx->uctx); res = ldelf_init_with_ldelf(&s->ts_sess, &ctx->uctx); } else { /* Raw binary format SP */ res = load_binary_sp(&s->ts_sess, &ctx->uctx); } } else { EMSG("Failed to detect SP format"); } if (res != TEE_SUCCESS) { EMSG("Failed loading SP %#"PRIx32, res); ts_pop_current_session(); return TEE_ERROR_TARGET_DEAD; } /* * Make the SP ready for its first run. * Set state to busy to prevent other endpoints from sending messages to * the SP before its boot phase is done. */ s->state = sp_busy; s->caller_id = 0; sp_init_set_registers(ctx); memcpy(&s->ffa_uuid, ffa_uuid, sizeof(*ffa_uuid)); ts_pop_current_session(); return TEE_SUCCESS; } static TEE_Result fdt_get_uuid(const void * const fdt, TEE_UUID *uuid) { const struct fdt_property *description = NULL; int description_name_len = 0; if (fdt_node_check_compatible(fdt, 0, "arm,ffa-manifest-1.0")) { EMSG("Failed loading SP, manifest not found"); return TEE_ERROR_BAD_PARAMETERS; } description = fdt_get_property(fdt, 0, "description", &description_name_len); if (description) DMSG("Loading SP: %s", description->data); if (sp_dt_get_uuid(fdt, 0, "uuid", uuid)) { EMSG("Missing or invalid UUID in SP manifest"); return TEE_ERROR_BAD_FORMAT; } return TEE_SUCCESS; } static TEE_Result copy_and_map_fdt(struct sp_ctx *ctx, const void * const fdt, void **fdt_copy, size_t *mapped_size) { size_t total_size = ROUNDUP(fdt_totalsize(fdt), SMALL_PAGE_SIZE); size_t num_pages = total_size / SMALL_PAGE_SIZE; uint32_t perm = TEE_MATTR_UR | TEE_MATTR_PRW; TEE_Result res = TEE_SUCCESS; struct mobj *m = NULL; struct fobj *f = NULL; vaddr_t va = 0; f = fobj_sec_mem_alloc(num_pages); m = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(f); if (!m) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map(&ctx->uctx, &va, total_size, perm, 0, m, 0); mobj_put(m); if (res) return res; if (fdt_open_into(fdt, (void *)va, total_size)) return TEE_ERROR_GENERIC; *fdt_copy = (void *)va; *mapped_size = total_size; return res; } static void fill_boot_info_1_0(vaddr_t buf, const void *fdt) { struct ffa_boot_info_1_0 *info = (struct ffa_boot_info_1_0 *)buf; static const char fdt_name[16] = "TYPE_DT\0\0\0\0\0\0\0\0"; memcpy(&info->magic, "FF-A", 4); info->count = 1; COMPILE_TIME_ASSERT(sizeof(info->nvp[0].name) == sizeof(fdt_name)); memcpy(info->nvp[0].name, fdt_name, sizeof(fdt_name)); info->nvp[0].value = (uintptr_t)fdt; info->nvp[0].size = fdt_totalsize(fdt); } static void fill_boot_info_1_1(vaddr_t buf, const void *fdt) { size_t desc_offs = ROUNDUP(sizeof(struct ffa_boot_info_header_1_1), 8); struct ffa_boot_info_header_1_1 *header = (struct ffa_boot_info_header_1_1 *)buf; struct ffa_boot_info_1_1 *desc = (struct ffa_boot_info_1_1 *)(buf + desc_offs); header->signature = FFA_BOOT_INFO_SIGNATURE; header->version = FFA_BOOT_INFO_VERSION; header->blob_size = desc_offs + sizeof(struct ffa_boot_info_1_1); header->desc_size = sizeof(struct ffa_boot_info_1_1); header->desc_count = 1; header->desc_offset = desc_offs; memset(&desc[0].name, 0, sizeof(desc[0].name)); /* Type: Standard boot info (bit[7] == 0), FDT type */ desc[0].type = FFA_BOOT_INFO_TYPE_ID_FDT; /* Flags: Contents field contains an address */ desc[0].flags = FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_ADDR << FFA_BOOT_INFO_FLAG_CONTENT_FORMAT_SHIFT; desc[0].size = fdt_totalsize(fdt); desc[0].contents = (uintptr_t)fdt; } static TEE_Result create_and_map_boot_info(struct sp_ctx *ctx, const void *fdt, struct thread_smc_args *args, vaddr_t *va, size_t *mapped_size, uint32_t sp_ffa_version) { size_t total_size = ROUNDUP(CFG_SP_INIT_INFO_MAX_SIZE, SMALL_PAGE_SIZE); size_t num_pages = total_size / SMALL_PAGE_SIZE; uint32_t perm = TEE_MATTR_UR | TEE_MATTR_PRW; TEE_Result res = TEE_SUCCESS; struct fobj *f = NULL; struct mobj *m = NULL; uint32_t info_reg = 0; f = fobj_sec_mem_alloc(num_pages); m = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(f); if (!m) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map(&ctx->uctx, va, total_size, perm, 0, m, 0); mobj_put(m); if (res) return res; *mapped_size = total_size; switch (sp_ffa_version) { case MAKE_FFA_VERSION(1, 0): fill_boot_info_1_0(*va, fdt); break; case MAKE_FFA_VERSION(1, 1): fill_boot_info_1_1(*va, fdt); break; default: EMSG("Unknown FF-A version: %#"PRIx32, sp_ffa_version); return TEE_ERROR_NOT_SUPPORTED; } res = sp_dt_get_u32(fdt, 0, "gp-register-num", &info_reg); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) { /* If the property is not present, set default to x0 */ info_reg = 0; } else { return TEE_ERROR_BAD_FORMAT; } } switch (info_reg) { case 0: args->a0 = *va; break; case 1: args->a1 = *va; break; case 2: args->a2 = *va; break; case 3: args->a3 = *va; break; default: EMSG("Invalid register selected for passing boot info"); return TEE_ERROR_BAD_FORMAT; } return TEE_SUCCESS; } static TEE_Result handle_fdt_load_relative_mem_regions(struct sp_ctx *ctx, const void *fdt) { int node = 0; int subnode = 0; tee_mm_entry_t *mm = NULL; TEE_Result res = TEE_SUCCESS; /* * Memory regions are optional in the SP manifest, it's not an error if * we don't find any. */ node = fdt_node_offset_by_compatible(fdt, 0, "arm,ffa-manifest-memory-regions"); if (node < 0) return TEE_SUCCESS; fdt_for_each_subnode(subnode, fdt, node) { uint64_t load_rel_offset = 0; uint32_t attributes = 0; uint64_t base_addr = 0; uint32_t pages_cnt = 0; uint32_t flags = 0; uint32_t perm = 0; size_t size = 0; vaddr_t va = 0; mm = NULL; /* Load address relative offset of a memory region */ if (!sp_dt_get_u64(fdt, subnode, "load-address-relative-offset", &load_rel_offset)) { va = ctx->uctx.load_addr + load_rel_offset; } else { /* Skip non load address relative memory regions */ continue; } if (!sp_dt_get_u64(fdt, subnode, "base-address", &base_addr)) { EMSG("Both base-address and load-address-relative-offset fields are set"); return TEE_ERROR_BAD_FORMAT; } /* Size of memory region as count of 4K pages */ if (sp_dt_get_u32(fdt, subnode, "pages-count", &pages_cnt)) { EMSG("Mandatory field is missing: pages-count"); return TEE_ERROR_BAD_FORMAT; } if (MUL_OVERFLOW(pages_cnt, SMALL_PAGE_SIZE, &size)) return TEE_ERROR_OVERFLOW; /* Memory region attributes */ if (sp_dt_get_u32(fdt, subnode, "attributes", &attributes)) { EMSG("Mandatory field is missing: attributes"); return TEE_ERROR_BAD_FORMAT; } /* Check instruction and data access permissions */ switch (attributes & SP_MANIFEST_ATTR_RWX) { case SP_MANIFEST_ATTR_RO: perm = TEE_MATTR_UR; break; case SP_MANIFEST_ATTR_RW: perm = TEE_MATTR_URW; break; case SP_MANIFEST_ATTR_RX: perm = TEE_MATTR_URX; break; default: EMSG("Invalid memory access permissions"); return TEE_ERROR_BAD_FORMAT; } res = sp_dt_get_u32(fdt, subnode, "load-flags", &flags); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) { EMSG("Optional field with invalid value: flags"); return TEE_ERROR_BAD_FORMAT; } /* Load relative regions must be secure */ if (attributes & SP_MANIFEST_ATTR_NSEC) { EMSG("Invalid memory security attribute"); return TEE_ERROR_BAD_FORMAT; } if (flags & SP_MANIFEST_FLAG_NOBITS) { /* * NOBITS flag is set, which means that loaded binary * doesn't contain this area, so it's need to be * allocated. */ struct mobj *m = NULL; unsigned int idx = 0; mm = tee_mm_alloc(&tee_mm_sec_ddr, size); if (!mm) return TEE_ERROR_OUT_OF_MEMORY; base_addr = tee_mm_get_smem(mm); m = sp_mem_new_mobj(pages_cnt, TEE_MATTR_MEM_TYPE_CACHED, true); if (!m) { res = TEE_ERROR_OUT_OF_MEMORY; goto err_mm_free; } res = sp_mem_add_pages(m, &idx, base_addr, pages_cnt); if (res) { mobj_put(m); goto err_mm_free; } res = vm_map(&ctx->uctx, &va, size, perm, 0, m, 0); mobj_put(m); if (res) goto err_mm_free; } else { /* * If NOBITS is not present the memory area is already * mapped and only need to set the correct permissions. */ res = vm_set_prot(&ctx->uctx, va, size, perm); if (res) return res; } } return TEE_SUCCESS; err_mm_free: tee_mm_free(mm); return res; } static TEE_Result handle_fdt_dev_regions(struct sp_ctx *ctx, void *fdt) { int node = 0; int subnode = 0; TEE_Result res = TEE_SUCCESS; const char *dt_device_match_table = { "arm,ffa-manifest-device-regions", }; /* * Device regions are optional in the SP manifest, it's not an error if * we don't find any */ node = fdt_node_offset_by_compatible(fdt, 0, dt_device_match_table); if (node < 0) return TEE_SUCCESS; fdt_for_each_subnode(subnode, fdt, node) { uint64_t base_addr = 0; uint32_t pages_cnt = 0; uint32_t attributes = 0; struct mobj *m = NULL; bool is_secure = true; uint32_t perm = 0; vaddr_t va = 0; unsigned int idx = 0; /* * Physical base address of a device MMIO region. * Currently only physically contiguous region is supported. */ if (sp_dt_get_u64(fdt, subnode, "base-address", &base_addr)) { EMSG("Mandatory field is missing: base-address"); return TEE_ERROR_BAD_FORMAT; } /* Total size of MMIO region as count of 4K pages */ if (sp_dt_get_u32(fdt, subnode, "pages-count", &pages_cnt)) { EMSG("Mandatory field is missing: pages-count"); return TEE_ERROR_BAD_FORMAT; } /* Data access, instruction access and security attributes */ if (sp_dt_get_u32(fdt, subnode, "attributes", &attributes)) { EMSG("Mandatory field is missing: attributes"); return TEE_ERROR_BAD_FORMAT; } /* Check instruction and data access permissions */ switch (attributes & SP_MANIFEST_ATTR_RWX) { case SP_MANIFEST_ATTR_RO: perm = TEE_MATTR_UR; break; case SP_MANIFEST_ATTR_RW: perm = TEE_MATTR_URW; break; default: EMSG("Invalid memory access permissions"); return TEE_ERROR_BAD_FORMAT; } /* * The SP is a secure endpoint, security attribute can be * secure or non-secure */ if (attributes & SP_MANIFEST_ATTR_NSEC) is_secure = false; /* Memory attributes must be Device-nGnRnE */ m = sp_mem_new_mobj(pages_cnt, TEE_MATTR_MEM_TYPE_STRONGLY_O, is_secure); if (!m) return TEE_ERROR_OUT_OF_MEMORY; res = sp_mem_add_pages(m, &idx, (paddr_t)base_addr, pages_cnt); if (res) { mobj_put(m); return res; } res = vm_map(&ctx->uctx, &va, pages_cnt * SMALL_PAGE_SIZE, perm, 0, m, 0); mobj_put(m); if (res) return res; /* * Overwrite the device region's PA in the fdt with the VA. This * fdt will be passed to the SP. */ res = fdt_setprop_u64(fdt, subnode, "base-address", va); /* * Unmap the region if the overwrite failed since the SP won't * be able to access it without knowing the VA. */ if (res) { vm_unmap(&ctx->uctx, va, pages_cnt * SMALL_PAGE_SIZE); return res; } } return TEE_SUCCESS; } static TEE_Result swap_sp_endpoints(uint32_t endpoint_id, uint32_t new_endpoint_id) { struct sp_session *session = sp_get_session(endpoint_id); uint32_t manifest_endpoint_id = 0; /* * We don't know in which order the SPs are loaded. The endpoint ID * defined in the manifest could already be generated by * new_session_id() and used by another SP. If this is the case, we swap * the ID's of the two SPs. We also have to make sure that the ID's are * not defined twice in the manifest. */ /* The endpoint ID was not assigned yet */ if (!session) return TEE_SUCCESS; /* * Read the manifest file from the SP who originally had the endpoint. * We can safely swap the endpoint ID's if the manifest file doesn't * have an endpoint ID defined. */ if (!sp_dt_get_u32(session->fdt, 0, "id", &manifest_endpoint_id)) { assert(manifest_endpoint_id == endpoint_id); EMSG("SP: Found duplicated endpoint ID %#"PRIx32, endpoint_id); return TEE_ERROR_ACCESS_CONFLICT; } session->endpoint_id = new_endpoint_id; return TEE_SUCCESS; } static TEE_Result read_manifest_endpoint_id(struct sp_session *s) { uint32_t endpoint_id = 0; /* * The endpoint ID can be optionally defined in the manifest file. We * have to map the ID inside the manifest to the SP if it's defined. * If not, the endpoint ID generated inside new_session_id() will be * used. */ if (!sp_dt_get_u32(s->fdt, 0, "id", &endpoint_id)) { TEE_Result res = TEE_ERROR_GENERIC; if (!endpoint_id_is_valid(endpoint_id)) { EMSG("Invalid endpoint ID 0x%"PRIx32, endpoint_id); return TEE_ERROR_BAD_FORMAT; } res = swap_sp_endpoints(endpoint_id, s->endpoint_id); if (res) return res; DMSG("SP: endpoint ID (0x%"PRIx32") found in manifest", endpoint_id); /* Assign the endpoint ID to the current SP */ s->endpoint_id = endpoint_id; } return TEE_SUCCESS; } static TEE_Result handle_fdt_mem_regions(struct sp_ctx *ctx, void *fdt) { int node = 0; int subnode = 0; tee_mm_entry_t *mm = NULL; TEE_Result res = TEE_SUCCESS; /* * Memory regions are optional in the SP manifest, it's not an error if * we don't find any. */ node = fdt_node_offset_by_compatible(fdt, 0, "arm,ffa-manifest-memory-regions"); if (node < 0) return TEE_SUCCESS; fdt_for_each_subnode(subnode, fdt, node) { uint64_t load_rel_offset = 0; bool alloc_needed = false; uint32_t attributes = 0; uint64_t base_addr = 0; uint32_t pages_cnt = 0; bool is_secure = true; struct mobj *m = NULL; unsigned int idx = 0; uint32_t perm = 0; size_t size = 0; vaddr_t va = 0; mm = NULL; /* Load address relative offset of a memory region */ if (!sp_dt_get_u64(fdt, subnode, "load-address-relative-offset", &load_rel_offset)) { /* * At this point the memory region is already mapped by * handle_fdt_load_relative_mem_regions. * Only need to set the base-address in the manifest and * then skip the rest of the mapping process. */ va = ctx->uctx.load_addr + load_rel_offset; res = fdt_setprop_u64(fdt, subnode, "base-address", va); if (res) return res; continue; } /* * Base address of a memory region. * If not present, we have to allocate the specified memory. * If present, this field could specify a PA or VA. Currently * only a PA is supported. */ if (sp_dt_get_u64(fdt, subnode, "base-address", &base_addr)) alloc_needed = true; /* Size of memory region as count of 4K pages */ if (sp_dt_get_u32(fdt, subnode, "pages-count", &pages_cnt)) { EMSG("Mandatory field is missing: pages-count"); return TEE_ERROR_BAD_FORMAT; } if (MUL_OVERFLOW(pages_cnt, SMALL_PAGE_SIZE, &size)) return TEE_ERROR_OVERFLOW; /* * Memory region attributes: * - Instruction/data access permissions * - Cacheability/shareability attributes * - Security attributes * * Cacheability/shareability attributes can be ignored for now. * OP-TEE only supports a single type for normal cached memory * and currently there is no use case that would require to * change this. */ if (sp_dt_get_u32(fdt, subnode, "attributes", &attributes)) { EMSG("Mandatory field is missing: attributes"); return TEE_ERROR_BAD_FORMAT; } /* Check instruction and data access permissions */ switch (attributes & SP_MANIFEST_ATTR_RWX) { case SP_MANIFEST_ATTR_RO: perm = TEE_MATTR_UR; break; case SP_MANIFEST_ATTR_RW: perm = TEE_MATTR_URW; break; case SP_MANIFEST_ATTR_RX: perm = TEE_MATTR_URX; break; default: EMSG("Invalid memory access permissions"); return TEE_ERROR_BAD_FORMAT; } /* * The SP is a secure endpoint, security attribute can be * secure or non-secure. * The SPMC cannot allocate non-secure memory, i.e. if the base * address is missing this attribute must be secure. */ if (attributes & SP_MANIFEST_ATTR_NSEC) { if (alloc_needed) { EMSG("Invalid memory security attribute"); return TEE_ERROR_BAD_FORMAT; } is_secure = false; } if (alloc_needed) { /* Base address is missing, we have to allocate */ mm = tee_mm_alloc(&tee_mm_sec_ddr, size); if (!mm) return TEE_ERROR_OUT_OF_MEMORY; base_addr = tee_mm_get_smem(mm); } m = sp_mem_new_mobj(pages_cnt, TEE_MATTR_MEM_TYPE_CACHED, is_secure); if (!m) { res = TEE_ERROR_OUT_OF_MEMORY; goto err_mm_free; } res = sp_mem_add_pages(m, &idx, base_addr, pages_cnt); if (res) { mobj_put(m); goto err_mm_free; } res = vm_map(&ctx->uctx, &va, size, perm, 0, m, 0); mobj_put(m); if (res) goto err_mm_free; /* * Overwrite the memory region's base address in the fdt with * the VA. This fdt will be passed to the SP. * If the base-address field was not present in the original * fdt, this function will create it. This doesn't cause issues * since the necessary extra space has been allocated when * opening the fdt. */ res = fdt_setprop_u64(fdt, subnode, "base-address", va); /* * Unmap the region if the overwrite failed since the SP won't * be able to access it without knowing the VA. */ if (res) { vm_unmap(&ctx->uctx, va, size); goto err_mm_free; } } return TEE_SUCCESS; err_mm_free: tee_mm_free(mm); return res; } static TEE_Result handle_tpm_event_log(struct sp_ctx *ctx, void *fdt) { uint32_t perm = TEE_MATTR_URW | TEE_MATTR_PRW; uint32_t dummy_size __maybe_unused = 0; TEE_Result res = TEE_SUCCESS; size_t page_count = 0; struct fobj *f = NULL; struct mobj *m = NULL; vaddr_t log_addr = 0; size_t log_size = 0; int node = 0; node = fdt_node_offset_by_compatible(fdt, 0, "arm,tpm_event_log"); if (node < 0) return TEE_SUCCESS; /* Checking the existence and size of the event log properties */ if (sp_dt_get_u64(fdt, node, "tpm_event_log_addr", &log_addr)) { EMSG("tpm_event_log_addr not found or has invalid size"); return TEE_ERROR_BAD_FORMAT; } if (sp_dt_get_u32(fdt, node, "tpm_event_log_size", &dummy_size)) { EMSG("tpm_event_log_size not found or has invalid size"); return TEE_ERROR_BAD_FORMAT; } /* Validating event log */ res = tpm_get_event_log_size(&log_size); if (res) return res; if (!log_size) { EMSG("Empty TPM event log was provided"); return TEE_ERROR_ITEM_NOT_FOUND; } /* Allocating memory area for the event log to share with the SP */ page_count = ROUNDUP_DIV(log_size, SMALL_PAGE_SIZE); f = fobj_sec_mem_alloc(page_count); m = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(f); if (!m) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map(&ctx->uctx, &log_addr, log_size, perm, 0, m, 0); mobj_put(m); if (res) return res; /* Copy event log */ res = tpm_get_event_log((void *)log_addr, &log_size); if (res) goto err_unmap; /* Setting event log details in the manifest */ res = fdt_setprop_u64(fdt, node, "tpm_event_log_addr", log_addr); if (res) goto err_unmap; res = fdt_setprop_u32(fdt, node, "tpm_event_log_size", log_size); if (res) goto err_unmap; return TEE_SUCCESS; err_unmap: vm_unmap(&ctx->uctx, log_addr, log_size); return res; } /* * Note: this function is called only on the primary CPU. It assumes that the * features present on the primary CPU are available on all of the secondary * CPUs as well. */ static TEE_Result handle_hw_features(void *fdt) { uint32_t val __maybe_unused = 0; TEE_Result res = TEE_SUCCESS; int node = 0; /* * HW feature descriptions are optional in the SP manifest, it's not an * error if we don't find any. */ node = fdt_node_offset_by_compatible(fdt, 0, "arm,hw-features"); if (node < 0) return TEE_SUCCESS; /* Modify the crc32 property only if it's already present */ if (!sp_dt_get_u32(fdt, node, "crc32", &val)) { res = fdt_setprop_u32(fdt, node, "crc32", feat_crc32_implemented()); if (res) return res; } return TEE_SUCCESS; } static TEE_Result read_ns_interrupts_action(const void *fdt, struct sp_session *s) { TEE_Result res = TEE_ERROR_BAD_PARAMETERS; res = sp_dt_get_u32(fdt, 0, "ns-interrupts-action", &s->ns_int_mode); if (res) { EMSG("Mandatory property is missing: ns-interrupts-action"); return res; } switch (s->ns_int_mode) { case SP_MANIFEST_NS_INT_QUEUED: case SP_MANIFEST_NS_INT_SIGNALED: /* OK */ break; case SP_MANIFEST_NS_INT_MANAGED_EXIT: EMSG("Managed exit is not implemented"); return TEE_ERROR_NOT_IMPLEMENTED; default: EMSG("Invalid ns-interrupts-action value: %"PRIu32, s->ns_int_mode); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result read_ffa_version(const void *fdt, struct sp_session *s) { TEE_Result res = TEE_ERROR_BAD_PARAMETERS; uint32_t ffa_version = 0; res = sp_dt_get_u32(fdt, 0, "ffa-version", &ffa_version); if (res) { EMSG("Mandatory property is missing: ffa-version"); return res; } if (ffa_version != FFA_VERSION_1_0 && ffa_version != FFA_VERSION_1_1) { EMSG("Invalid FF-A version value: 0x%08"PRIx32, ffa_version); return TEE_ERROR_BAD_PARAMETERS; } s->rxtx.ffa_vers = ffa_version; return TEE_SUCCESS; } static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt) { TEE_Result res = TEE_SUCCESS; struct sp_session *sess = NULL; TEE_UUID ffa_uuid = {}; uint16_t boot_order = 0; uint32_t boot_order_arg = 0; res = fdt_get_uuid(fdt, &ffa_uuid); if (res) return res; res = sp_dt_get_u16(fdt, 0, "boot-order", &boot_order); if (res == TEE_SUCCESS) { boot_order_arg = boot_order; } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { boot_order_arg = UINT32_MAX; } else { EMSG("Failed reading boot-order property err:%#"PRIx32, res); return res; } res = sp_open_session(&sess, &open_sp_sessions, &ffa_uuid, bin_uuid, boot_order_arg, fdt); if (res) return res; sess->fdt = fdt; res = read_manifest_endpoint_id(sess); if (res) return res; DMSG("endpoint is 0x%"PRIx16, sess->endpoint_id); res = read_ns_interrupts_action(fdt, sess); if (res) return res; res = read_ffa_version(fdt, sess); if (res) return res; return TEE_SUCCESS; } static TEE_Result sp_first_run(struct sp_session *sess) { TEE_Result res = TEE_SUCCESS; struct thread_smc_args args = { }; struct sp_ctx *ctx = NULL; vaddr_t boot_info_va = 0; size_t boot_info_size = 0; void *fdt_copy = NULL; size_t fdt_size = 0; ctx = to_sp_ctx(sess->ts_sess.ctx); ts_push_current_session(&sess->ts_sess); sess->is_initialized = false; /* * Load relative memory regions must be handled before doing any other * mapping to prevent conflicts in the VA space. */ res = handle_fdt_load_relative_mem_regions(ctx, sess->fdt); if (res) { ts_pop_current_session(); return res; } res = copy_and_map_fdt(ctx, sess->fdt, &fdt_copy, &fdt_size); if (res) goto out; res = handle_fdt_dev_regions(ctx, fdt_copy); if (res) goto out; res = handle_fdt_mem_regions(ctx, fdt_copy); if (res) goto out; if (IS_ENABLED(CFG_CORE_TPM_EVENT_LOG)) { res = handle_tpm_event_log(ctx, fdt_copy); if (res) goto out; } res = handle_hw_features(fdt_copy); if (res) goto out; res = create_and_map_boot_info(ctx, fdt_copy, &args, &boot_info_va, &boot_info_size, sess->rxtx.ffa_vers); if (res) goto out; ts_pop_current_session(); res = sp_enter(&args, sess); if (res) { ts_push_current_session(&sess->ts_sess); goto out; } spmc_sp_msg_handler(&args, sess); ts_push_current_session(&sess->ts_sess); sess->is_initialized = true; out: /* Free the boot info page from the SP memory */ vm_unmap(&ctx->uctx, boot_info_va, boot_info_size); vm_unmap(&ctx->uctx, (vaddr_t)fdt_copy, fdt_size); ts_pop_current_session(); return res; } TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp) { TEE_Result res = TEE_SUCCESS; struct sp_ctx *ctx = to_sp_ctx(sp->ts_sess.ctx); ctx->sp_regs.x[0] = args->a0; ctx->sp_regs.x[1] = args->a1; ctx->sp_regs.x[2] = args->a2; ctx->sp_regs.x[3] = args->a3; ctx->sp_regs.x[4] = args->a4; ctx->sp_regs.x[5] = args->a5; ctx->sp_regs.x[6] = args->a6; ctx->sp_regs.x[7] = args->a7; res = sp->ts_sess.ctx->ops->enter_invoke_cmd(&sp->ts_sess, 0); args->a0 = ctx->sp_regs.x[0]; args->a1 = ctx->sp_regs.x[1]; args->a2 = ctx->sp_regs.x[2]; args->a3 = ctx->sp_regs.x[3]; args->a4 = ctx->sp_regs.x[4]; args->a5 = ctx->sp_regs.x[5]; args->a6 = ctx->sp_regs.x[6]; args->a7 = ctx->sp_regs.x[7]; return res; } /* * According to FF-A v1.1 section 8.3.1.4 if a caller requires less permissive * active on NS interrupt than the callee, the callee must inherit the caller's * configuration. * Each SP's own NS action setting is stored in ns_int_mode. The effective * action will be MIN([self action], [caller's action]) which is stored in the * ns_int_mode_inherited field. */ static void sp_cpsr_configure_foreign_interrupts(struct sp_session *s, struct ts_session *caller, uint64_t *cpsr) { if (caller) { struct sp_session *caller_sp = to_sp_session(caller); s->ns_int_mode_inherited = MIN(caller_sp->ns_int_mode_inherited, s->ns_int_mode); } else { s->ns_int_mode_inherited = s->ns_int_mode; } if (s->ns_int_mode_inherited == SP_MANIFEST_NS_INT_QUEUED) *cpsr |= SHIFT_U32(THREAD_EXCP_FOREIGN_INTR, ARM32_CPSR_F_SHIFT); else *cpsr &= ~SHIFT_U32(THREAD_EXCP_FOREIGN_INTR, ARM32_CPSR_F_SHIFT); } static TEE_Result sp_enter_invoke_cmd(struct ts_session *s, uint32_t cmd __unused) { struct sp_ctx *ctx = to_sp_ctx(s->ctx); TEE_Result res = TEE_SUCCESS; uint32_t exceptions = 0; struct sp_session *sp_s = to_sp_session(s); struct ts_session *sess = NULL; struct thread_ctx_regs *sp_regs = NULL; uint32_t thread_id = THREAD_ID_INVALID; struct ts_session *caller = NULL; uint32_t rpc_target_info = 0; uint32_t panicked = false; uint32_t panic_code = 0; sp_regs = &ctx->sp_regs; ts_push_current_session(s); exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); /* Enable/disable foreign interrupts in CPSR/SPSR */ caller = ts_get_calling_session(); sp_cpsr_configure_foreign_interrupts(sp_s, caller, &sp_regs->cpsr); /* * Store endpoint ID and thread ID in rpc_target_info. This will be used * as w1 in FFA_INTERRUPT in case of a foreign interrupt. */ rpc_target_info = thread_get_tsd()->rpc_target_info; thread_id = thread_get_id(); assert(thread_id <= UINT16_MAX); thread_get_tsd()->rpc_target_info = FFA_TARGET_INFO_SET(sp_s->endpoint_id, thread_id); __thread_enter_user_mode(sp_regs, &panicked, &panic_code); /* Restore rpc_target_info */ thread_get_tsd()->rpc_target_info = rpc_target_info; thread_unmask_exceptions(exceptions); thread_user_clear_vfp(&ctx->uctx); if (panicked) { DMSG("SP panicked with code %#"PRIx32, panic_code); abort_print_current_ts(); sess = ts_pop_current_session(); cpu_spin_lock(&sp_s->spinlock); sp_s->state = sp_dead; cpu_spin_unlock(&sp_s->spinlock); return TEE_ERROR_TARGET_DEAD; } sess = ts_pop_current_session(); assert(sess == s); return res; } /* We currently don't support 32 bits */ #ifdef ARM64 static void sp_svc_store_registers(struct thread_scall_regs *regs, struct thread_ctx_regs *sp_regs) { COMPILE_TIME_ASSERT(sizeof(sp_regs->x[0]) == sizeof(regs->x0)); memcpy(sp_regs->x, ®s->x0, 31 * sizeof(regs->x0)); sp_regs->pc = regs->elr; sp_regs->sp = regs->sp_el0; } #endif static bool sp_handle_scall(struct thread_scall_regs *regs) { struct ts_session *ts = ts_get_current_session(); struct sp_ctx *uctx = to_sp_ctx(ts->ctx); struct sp_session *s = uctx->open_session; assert(s); sp_svc_store_registers(regs, &uctx->sp_regs); regs->x0 = 0; regs->x1 = 0; /* panic */ regs->x2 = 0; /* panic code */ /* * All the registers of the SP are saved in the SP session by the SVC * handler. * We always return to S-El1 after handling the SVC. We will continue * in sp_enter_invoke_cmd() (return from __thread_enter_user_mode). * The sp_enter() function copies the FF-A parameters (a0-a7) from the * saved registers to the thread_smc_args. The thread_smc_args object is * afterward used by the spmc_sp_msg_handler() to handle the * FF-A message send by the SP. */ return false; } static void sp_dump_state(struct ts_ctx *ctx) { struct sp_ctx *utc = to_sp_ctx(ctx); if (utc->uctx.dump_entry_func) { TEE_Result res = ldelf_dump_state(&utc->uctx); if (!res || res == TEE_ERROR_TARGET_DEAD) return; } user_mode_ctx_print_mappings(&utc->uctx); } static const struct ts_ops sp_ops = { .enter_invoke_cmd = sp_enter_invoke_cmd, .handle_scall = sp_handle_scall, .dump_state = sp_dump_state, }; static TEE_Result process_sp_pkg(uint64_t sp_pkg_pa, TEE_UUID *sp_uuid) { enum teecore_memtypes mtype = MEM_AREA_TA_RAM; struct sp_pkg_header *sp_pkg_hdr = NULL; struct fip_sp *sp = NULL; uint64_t sp_fdt_end = 0; size_t sp_pkg_size = 0; vaddr_t sp_pkg_va = 0; /* Process the first page which contains the SP package header */ sp_pkg_va = (vaddr_t)phys_to_virt(sp_pkg_pa, mtype, SMALL_PAGE_SIZE); if (!sp_pkg_va) { EMSG("Cannot find mapping for PA %#" PRIxPA, sp_pkg_pa); return TEE_ERROR_GENERIC; } sp_pkg_hdr = (struct sp_pkg_header *)sp_pkg_va; if (sp_pkg_hdr->magic != SP_PKG_HEADER_MAGIC) { EMSG("Invalid SP package magic"); return TEE_ERROR_BAD_FORMAT; } if (sp_pkg_hdr->version != SP_PKG_HEADER_VERSION_V1 && sp_pkg_hdr->version != SP_PKG_HEADER_VERSION_V2) { EMSG("Invalid SP header version"); return TEE_ERROR_BAD_FORMAT; } if (ADD_OVERFLOW(sp_pkg_hdr->img_offset, sp_pkg_hdr->img_size, &sp_pkg_size)) { EMSG("Invalid SP package size"); return TEE_ERROR_BAD_FORMAT; } if (ADD_OVERFLOW(sp_pkg_hdr->pm_offset, sp_pkg_hdr->pm_size, &sp_fdt_end) || sp_fdt_end > sp_pkg_hdr->img_offset) { EMSG("Invalid SP manifest size"); return TEE_ERROR_BAD_FORMAT; } /* Process the whole SP package now that the size is known */ sp_pkg_va = (vaddr_t)phys_to_virt(sp_pkg_pa, mtype, sp_pkg_size); if (!sp_pkg_va) { EMSG("Cannot find mapping for PA %#" PRIxPA, sp_pkg_pa); return TEE_ERROR_GENERIC; } sp_pkg_hdr = (struct sp_pkg_header *)sp_pkg_va; sp = calloc(1, sizeof(struct fip_sp)); if (!sp) return TEE_ERROR_OUT_OF_MEMORY; memcpy(&sp->sp_img.image.uuid, sp_uuid, sizeof(*sp_uuid)); sp->sp_img.image.ts = (uint8_t *)(sp_pkg_va + sp_pkg_hdr->img_offset); sp->sp_img.image.size = sp_pkg_hdr->img_size; sp->sp_img.image.flags = 0; sp->sp_img.fdt = (uint8_t *)(sp_pkg_va + sp_pkg_hdr->pm_offset); STAILQ_INSERT_TAIL(&fip_sp_list, sp, link); return TEE_SUCCESS; } static TEE_Result fip_sp_init_all(void) { TEE_Result res = TEE_SUCCESS; uint64_t sp_pkg_addr = 0; const void *fdt = NULL; TEE_UUID sp_uuid = { }; int sp_pkgs_node = 0; int subnode = 0; int root = 0; fdt = get_manifest_dt(); if (!fdt) { EMSG("No SPMC manifest found"); return TEE_ERROR_GENERIC; } root = fdt_path_offset(fdt, "/"); if (root < 0) return TEE_ERROR_BAD_FORMAT; if (fdt_node_check_compatible(fdt, root, "arm,ffa-core-manifest-1.0")) return TEE_ERROR_BAD_FORMAT; /* SP packages are optional, it's not an error if we don't find any */ sp_pkgs_node = fdt_node_offset_by_compatible(fdt, root, "arm,sp_pkg"); if (sp_pkgs_node < 0) return TEE_SUCCESS; fdt_for_each_subnode(subnode, fdt, sp_pkgs_node) { res = sp_dt_get_u64(fdt, subnode, "load-address", &sp_pkg_addr); if (res) { EMSG("Invalid FIP SP load address"); return res; } res = sp_dt_get_uuid(fdt, subnode, "uuid", &sp_uuid); if (res) { EMSG("Invalid FIP SP uuid"); return res; } res = process_sp_pkg(sp_pkg_addr, &sp_uuid); if (res) { EMSG("Invalid FIP SP package"); return res; } } return TEE_SUCCESS; } static void fip_sp_deinit_all(void) { while (!STAILQ_EMPTY(&fip_sp_list)) { struct fip_sp *sp = STAILQ_FIRST(&fip_sp_list); STAILQ_REMOVE_HEAD(&fip_sp_list, link); free(sp); } } static TEE_Result sp_init_all(void) { TEE_Result res = TEE_SUCCESS; const struct sp_image *sp = NULL; const struct fip_sp *fip_sp = NULL; char __maybe_unused msg[60] = { '\0', }; struct sp_session *s = NULL; struct sp_session *prev_sp = NULL; for_each_secure_partition(sp) { if (sp->image.uncompressed_size) snprintf(msg, sizeof(msg), " (compressed, uncompressed %u)", sp->image.uncompressed_size); else msg[0] = '\0'; DMSG("SP %pUl size %u%s", (void *)&sp->image.uuid, sp->image.size, msg); res = sp_init_uuid(&sp->image.uuid, sp->fdt); if (res != TEE_SUCCESS) { EMSG("Failed initializing SP(%pUl) err:%#"PRIx32, &sp->image.uuid, res); if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) panic(); } } res = fip_sp_init_all(); if (res) panic("Failed initializing FIP SPs"); for_each_fip_sp(fip_sp) { sp = &fip_sp->sp_img; DMSG("SP %pUl size %u", (void *)&sp->image.uuid, sp->image.size); res = sp_init_uuid(&sp->image.uuid, sp->fdt); if (res != TEE_SUCCESS) { EMSG("Failed initializing SP(%pUl) err:%#"PRIx32, &sp->image.uuid, res); if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) panic(); } } /* * At this point all FIP SPs are loaded by ldelf or by the raw binary SP * loader, so the original images (loaded by BL2) are not needed anymore */ fip_sp_deinit_all(); /* * Now that all SPs are loaded, check through the boot order values, * and warn in case there is a non-unique value. */ TAILQ_FOREACH(s, &open_sp_sessions, link) { /* User specified boot-order values are uint16 */ if (s->boot_order > UINT16_MAX) break; if (prev_sp && prev_sp->boot_order == s->boot_order) IMSG("WARNING: duplicated boot-order (%pUl vs %pUl)", &prev_sp->ts_sess.ctx->uuid, &s->ts_sess.ctx->uuid); prev_sp = s; } /* Continue the initialization and run the SP */ TAILQ_FOREACH(s, &open_sp_sessions, link) { DMSG("Starting SP: 0x%"PRIx16, s->endpoint_id); res = sp_first_run(s); if (res != TEE_SUCCESS) { EMSG("Failed starting SP(0x%"PRIx16") err:%#"PRIx32, s->endpoint_id, res); if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) panic(); } } return TEE_SUCCESS; } boot_final(sp_init_all); static TEE_Result secure_partition_open(const TEE_UUID *uuid, struct ts_store_handle **h) { return emb_ts_open(uuid, h, find_secure_partition); } REGISTER_SP_STORE(2) = { .description = "SP store", .open = secure_partition_open, .get_size = emb_ts_get_size, .get_tag = emb_ts_get_tag, .read = emb_ts_read, .close = emb_ts_close, }; optee_os-4.3.0/core/arch/arm/kernel/semihosting_a64.S000066400000000000000000000005671464416617300224120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024 Linaro, Ltd. */ #include /* * uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg) * * Refer to "Semihosting for Aarch32 and Aarch64": * https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst */ FUNC __do_semihosting , : hlt #0xf000 ret END_FUNC __do_semihosting optee_os-4.3.0/core/arch/arm/kernel/spin_lock_a32.S000066400000000000000000000046221464416617300220310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2014, STMicroelectronics International N.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* void __cpu_spin_lock(unsigned int *lock) */ FUNC __cpu_spin_lock , : mov r2, #SPINLOCK_LOCK 1: ldrex r1, [r0] cmp r1, #SPINLOCK_UNLOCK wfene strexeq r1, r2, [r0] cmpeq r1, #0 bne 1b dmb bx lr END_FUNC __cpu_spin_lock /* int __cpu_spin_trylock(unsigned int *lock) - return 0 on success */ FUNC __cpu_spin_trylock , : mov r2, #SPINLOCK_LOCK mov r1, r0 1: ldrex r0, [r1] cmp r0, #0 bne 1f strex r0, r2, [r1] cmp r0, #0 bne 1b dmb bx lr 1: clrex dmb bx lr END_FUNC __cpu_spin_trylock /* void __cpu_spin_unlock(unsigned int *lock) */ FUNC __cpu_spin_unlock , : dmb mov r1, #SPINLOCK_UNLOCK str r1, [r0] dsb sev bx lr END_FUNC __cpu_spin_unlock optee_os-4.3.0/core/arch/arm/kernel/spin_lock_a64.S000066400000000000000000000072251464416617300220400ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ /* * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* void __cpu_spin_lock(unsigned int *lock); */ FUNC __cpu_spin_lock , : mov w2, #SPINLOCK_LOCK sevl l1: wfe l2: ldaxr w1, [x0] cbnz w1, l1 stxr w1, w2, [x0] cbnz w1, l2 ret END_FUNC __cpu_spin_lock /* unsigned int __cpu_spin_trylock(unsigned int *lock); */ FUNC __cpu_spin_trylock , : mov x1, x0 mov w2, #SPINLOCK_LOCK .loop: ldaxr w0, [x1] cbnz w0, .cpu_spin_trylock_out stxr w0, w2, [x1] cbnz w0, .loop .cpu_spin_trylock_out: ret END_FUNC __cpu_spin_trylock /* void __cpu_spin_unlock(unsigned int *lock); */ FUNC __cpu_spin_unlock , : stlr wzr, [x0] ret END_FUNC __cpu_spin_unlock BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/spmc_sp_handler.c000066400000000000000000001015021464416617300225570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2024, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include static unsigned int mem_ref_lock = SPINLOCK_UNLOCK; void spmc_sp_start_thread(struct thread_smc_args *args) { thread_sp_alloc_and_run(args); } static void ffa_set_error(struct thread_smc_args *args, uint32_t error) { args->a0 = FFA_ERROR; args->a1 = FFA_PARAM_MBZ; args->a2 = error; args->a3 = FFA_PARAM_MBZ; args->a4 = FFA_PARAM_MBZ; args->a5 = FFA_PARAM_MBZ; args->a6 = FFA_PARAM_MBZ; args->a7 = FFA_PARAM_MBZ; } static void ffa_success(struct thread_smc_args *args) { args->a0 = FFA_SUCCESS_32; } static TEE_Result ffa_get_dst(struct thread_smc_args *args, struct sp_session *caller, struct sp_session **dst) { struct sp_session *s = NULL; if (args->a2 != FFA_PARAM_MBZ) return FFA_INVALID_PARAMETERS; s = sp_get_session(FFA_DST(args->a1)); /* Message came from the NW */ if (!caller) { if (!s) { EMSG("Neither destination nor source is a SP"); return FFA_INVALID_PARAMETERS; } } else { /* Check if the source matches the endpoint we came from */ if (FFA_SRC(args->a1) != caller->endpoint_id) { EMSG("Source address doesn't match the endpoint id"); return FFA_INVALID_PARAMETERS; } } *dst = s; return FFA_OK; } static struct sp_mem_receiver *find_sp_mem_receiver(struct sp_session *s, struct sp_mem *smem) { struct sp_mem_receiver *receiver = NULL; /* * FF-A Spec 8.10.2: * Each Handle identifies a single unique composite memory region * description that is, there is a 1:1 mapping between the two. * * Each memory share has an unique handle. We can only have each SP * once as a receiver in the memory share. For each receiver of a * memory share, we have one sp_mem_access_descr object. * This means that there can only be one SP linked to a specific * struct sp_mem_access_descr. */ SLIST_FOREACH(receiver, &smem->receivers, link) { if (receiver->perm.endpoint_id == s->endpoint_id) break; } return receiver; } static int add_mem_region_to_sp(struct ffa_mem_access *mem_acc, struct sp_mem *smem) { struct ffa_mem_access_perm *access_perm = &mem_acc->access_perm; struct sp_session *s = NULL; struct sp_mem_receiver *receiver = NULL; uint8_t perm = READ_ONCE(access_perm->perm); uint16_t endpoint_id = READ_ONCE(access_perm->endpoint_id); s = sp_get_session(endpoint_id); /* Only add memory shares of loaded SPs */ if (!s) return FFA_DENIED; /* Only allow each endpoint once */ if (find_sp_mem_receiver(s, smem)) return FFA_DENIED; if (perm & ~FFA_MEM_ACC_MASK) return FFA_DENIED; receiver = calloc(1, sizeof(struct sp_mem_receiver)); if (!receiver) return FFA_NO_MEMORY; receiver->smem = smem; receiver->perm.endpoint_id = endpoint_id; receiver->perm.perm = perm; receiver->perm.flags = READ_ONCE(access_perm->flags); SLIST_INSERT_HEAD(&smem->receivers, receiver, link); return FFA_OK; } static void spmc_sp_handle_mem_share(struct thread_smc_args *args, struct ffa_rxtx *rxtx, struct sp_session *owner_sp) { struct ffa_mem_transaction_x mem_trans = { }; uint32_t tot_len = args->a1; uint32_t frag_len = args->a2; uint64_t global_handle = 0; int res = FFA_OK; cpu_spin_lock(&rxtx->spinlock); /* Descriptor fragments or custom buffers aren't supported yet. */ if (frag_len != tot_len || args->a3 || args->a4) res = FFA_NOT_SUPPORTED; else if (frag_len > rxtx->size) res = FFA_INVALID_PARAMETERS; else res = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx, frag_len, &mem_trans); if (!res) res = spmc_sp_add_share(&mem_trans, rxtx, tot_len, frag_len, &global_handle, owner_sp); if (!res) { args->a3 = high32_from_64(global_handle); args->a2 = low32_from_64(global_handle); args->a1 = FFA_PARAM_MBZ; args->a0 = FFA_SUCCESS_32; } else { ffa_set_error(args, res); } cpu_spin_unlock(&rxtx->spinlock); } static int spmc_sp_add_sp_region(struct sp_mem *smem, struct ffa_address_range *mem_reg, struct sp_session *owner_sp, uint8_t highest_permission) { struct sp_ctx *sp_ctx = NULL; uint64_t va = READ_ONCE(mem_reg->address); int res = FFA_OK; uint64_t region_len = READ_ONCE(mem_reg->page_count) * SMALL_PAGE_SIZE; struct mobj *mobj = NULL; sp_ctx = to_sp_ctx(owner_sp->ts_sess.ctx); /* * The memory region we try to share might not be linked to just one * mobj. Create a new region for each mobj. */ while (region_len) { size_t len = region_len; struct sp_mem_map_region *region = NULL; uint16_t prot = 0; size_t offs = 0; /* * There is already a mobj for each address that is in the SPs * address range. */ mobj = vm_get_mobj(&sp_ctx->uctx, va, &len, &prot, &offs); if (!mobj) return FFA_DENIED; /* * If we share memory from a SP, check if we are not sharing * with a higher permission than the memory was originally * mapped. */ if ((highest_permission & FFA_MEM_ACC_RW) && !(prot & TEE_MATTR_UW)) { res = FFA_DENIED; goto err; } if ((highest_permission & FFA_MEM_ACC_EXE) && !(prot & TEE_MATTR_UX)) { res = FFA_DENIED; goto err; } region = calloc(1, sizeof(*region)); region->mobj = mobj; region->page_offset = offs; region->page_count = len / SMALL_PAGE_SIZE; if (!sp_has_exclusive_access(region, &sp_ctx->uctx)) { free(region); res = FFA_DENIED; goto err; } va += len; region_len -= len; SLIST_INSERT_HEAD(&smem->regions, region, link); } return FFA_OK; err: mobj_put(mobj); return res; } static int spmc_sp_add_nw_region(struct sp_mem *smem, struct ffa_mem_region *mem_reg) { uint64_t page_count = READ_ONCE(mem_reg->total_page_count); struct sp_mem_map_region *region = NULL; struct mobj *m = sp_mem_new_mobj(page_count, TEE_MATTR_MEM_TYPE_CACHED, false); unsigned int i = 0; unsigned int idx = 0; int res = FFA_OK; uint64_t address_count = READ_ONCE(mem_reg->address_range_count); if (!m) return FFA_NO_MEMORY; for (i = 0; i < address_count; i++) { struct ffa_address_range *addr_range = NULL; addr_range = &mem_reg->address_range_array[i]; if (sp_mem_add_pages(m, &idx, READ_ONCE(addr_range->address), READ_ONCE(addr_range->page_count))) { res = FFA_DENIED; goto clean_up; } } region = calloc(1, sizeof(*region)); if (!region) { res = FFA_NO_MEMORY; goto clean_up; } region->mobj = m; region->page_count = page_count; if (!sp_has_exclusive_access(region, NULL)) { free(region); res = FFA_DENIED; goto clean_up; } SLIST_INSERT_HEAD(&smem->regions, region, link); return FFA_OK; clean_up: mobj_put(m); return res; } int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans, struct ffa_rxtx *rxtx, size_t blen, size_t flen, uint64_t *global_handle, struct sp_session *owner_sp) { int res = FFA_INVALID_PARAMETERS; unsigned int num_mem_accs = 0; unsigned int i = 0; struct ffa_mem_access *mem_acc = NULL; size_t needed_size = 0; size_t addr_range_offs = 0; struct ffa_mem_region *mem_reg = NULL; uint8_t highest_permission = 0; struct sp_mem *smem = NULL; uint16_t sender_id = mem_trans->sender_id; size_t addr_range_cnt = 0; struct ffa_address_range *addr_range = NULL; size_t total_page_count = 0; size_t page_count_sum = 0; if (blen != flen) { DMSG("Fragmented memory share is not supported for SPs"); return FFA_NOT_SUPPORTED; } smem = sp_mem_new(); if (!smem) return FFA_NO_MEMORY; if ((owner_sp && owner_sp->endpoint_id != sender_id) || (!owner_sp && sp_get_session(sender_id))) { res = FFA_DENIED; goto cleanup; } num_mem_accs = mem_trans->mem_access_count; mem_acc = (void *)((vaddr_t)rxtx->rx + mem_trans->mem_access_offs); if (!num_mem_accs) { res = FFA_INVALID_PARAMETERS; goto cleanup; } /* Store the ffa_mem_transaction */ smem->sender_id = sender_id; smem->mem_reg_attr = mem_trans->mem_reg_attr; smem->flags = mem_trans->flags; smem->tag = mem_trans->tag; if (MUL_OVERFLOW(num_mem_accs, sizeof(*mem_acc), &needed_size) || ADD_OVERFLOW(needed_size, mem_trans->mem_access_offs, &needed_size) || needed_size > blen) { res = FFA_INVALID_PARAMETERS; goto cleanup; } for (i = 0; i < num_mem_accs; i++) highest_permission |= READ_ONCE(mem_acc[i].access_perm.perm); /* Check if the memory region array fits into the buffer */ addr_range_offs = READ_ONCE(mem_acc[0].region_offs); if (ADD_OVERFLOW(addr_range_offs, sizeof(*mem_reg), &needed_size) || needed_size > blen) { res = FFA_INVALID_PARAMETERS; goto cleanup; } mem_reg = (void *)((char *)rxtx->rx + addr_range_offs); addr_range_cnt = READ_ONCE(mem_reg->address_range_count); total_page_count = READ_ONCE(mem_reg->total_page_count); /* Memory transaction without address ranges or pages is invalid */ if (!addr_range_cnt || !total_page_count) { res = FFA_INVALID_PARAMETERS; goto cleanup; } /* Check if the region descriptors fit into the buffer */ if (MUL_OVERFLOW(addr_range_cnt, sizeof(*addr_range), &needed_size) || ADD_OVERFLOW(needed_size, addr_range_offs, &needed_size) || needed_size > blen) { res = FFA_INVALID_PARAMETERS; goto cleanup; } page_count_sum = 0; for (i = 0; i < addr_range_cnt; i++) { addr_range = &mem_reg->address_range_array[i]; /* Memory region without pages is invalid */ if (!addr_range->page_count) { res = FFA_INVALID_PARAMETERS; goto cleanup; } /* Sum the page count of each region */ if (ADD_OVERFLOW(page_count_sum, addr_range->page_count, &page_count_sum)) { res = FFA_INVALID_PARAMETERS; goto cleanup; } } /* Validate total page count */ if (total_page_count != page_count_sum) { res = FFA_INVALID_PARAMETERS; goto cleanup; } /* Iterate over all the addresses */ if (owner_sp) { for (i = 0; i < addr_range_cnt; i++) { addr_range = &mem_reg->address_range_array[i]; res = spmc_sp_add_sp_region(smem, addr_range, owner_sp, highest_permission); if (res) goto cleanup; } } else { res = spmc_sp_add_nw_region(smem, mem_reg); if (res) goto cleanup; } /* Add the memory address to the SP */ for (i = 0; i < num_mem_accs; i++) { res = add_mem_region_to_sp(&mem_acc[i], smem); if (res) goto cleanup; } *global_handle = smem->global_handle; sp_mem_add(smem); return FFA_OK; cleanup: sp_mem_remove(smem); return res; } void spmc_sp_set_to_preempted(struct ts_session *ts_sess) { if (ts_sess && is_sp_ctx(ts_sess->ctx)) { struct sp_session *sp_sess = to_sp_session(ts_sess); assert(sp_sess->state == sp_busy); sp_sess->state = sp_preempted; } } int spmc_sp_resume_from_preempted(uint16_t endpoint_id) { struct sp_session *sp_sess = sp_get_session(endpoint_id); if (!sp_sess) return FFA_INVALID_PARAMETERS; if (sp_sess->state != sp_preempted) return FFA_DENIED; sp_sess->state = sp_busy; return FFA_OK; } static bool check_rxtx(struct ffa_rxtx *rxtx) { return rxtx && rxtx->rx && rxtx->tx && rxtx->size > 0; } static TEE_Result check_retrieve_request(struct sp_mem_receiver *receiver, uint32_t ffa_vers, struct ffa_mem_transaction_x *mem_trans, void *rx, struct sp_mem *smem, int64_t tx_len) { struct ffa_mem_access *retr_access = NULL; uint8_t share_perm = receiver->perm.perm; uint32_t retr_perm = 0; uint32_t retr_flags = mem_trans->flags; uint64_t retr_tag = mem_trans->tag; struct sp_mem_map_region *reg = NULL; /* * The request came from the endpoint. It should only have one * ffa_mem_access element */ if (mem_trans->mem_access_count != 1) return TEE_ERROR_BAD_PARAMETERS; retr_access = (void *)((vaddr_t)rx + mem_trans->mem_access_offs); retr_perm = READ_ONCE(retr_access->access_perm.perm); /* Check if tag is correct */ if (receiver->smem->tag != retr_tag) { EMSG("Incorrect tag %#"PRIx64" %#"PRIx64, receiver->smem->tag, retr_tag); return TEE_ERROR_BAD_PARAMETERS; } /* Check permissions and flags */ if ((retr_perm & FFA_MEM_ACC_RW) && !(share_perm & FFA_MEM_ACC_RW)) { DMSG("Incorrect memshare permission set"); return TEE_ERROR_BAD_PARAMETERS; } if ((retr_perm & FFA_MEM_ACC_EXE) && !(share_perm & FFA_MEM_ACC_EXE)) { DMSG("Incorrect memshare permission set"); return TEE_ERROR_BAD_PARAMETERS; } if (retr_flags & FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH) { DMSG("CLEAR_RELINQUISH is not allowed for FFA_SHARE"); return TEE_ERROR_BAD_PARAMETERS; } /* * Check if there is enough space in the tx buffer to send the respons. */ if (ffa_vers <= FFA_VERSION_1_0) tx_len -= sizeof(struct ffa_mem_transaction_1_0); else tx_len -= sizeof(struct ffa_mem_transaction_1_1); tx_len -= sizeof(struct ffa_mem_access) + sizeof(struct ffa_mem_region); if (tx_len < 0) return FFA_NO_MEMORY; SLIST_FOREACH(reg, &smem->regions, link) { tx_len -= sizeof(struct ffa_address_range); if (tx_len < 0) return FFA_NO_MEMORY; } return TEE_SUCCESS; } static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer, struct sp_mem_receiver *receiver, struct sp_mem *smem, struct sp_session *s) { size_t off = 0; struct ffa_mem_region *dst_region = NULL; struct ffa_address_range *addr_dst = NULL; struct sp_mem_map_region *reg = NULL; struct ffa_mem_access *mem_acc = NULL; /* * we respond with a ffa_mem_retrieve_resp which defines the * following data in the rx buffer of the sp. * struct mem_transaction_descr * struct mem_access_descr (always 1 element) * struct mem_region_descr */ if (ffa_vers <= FFA_VERSION_1_0) { struct ffa_mem_transaction_1_0 *d_ds = dst_buffer; memset(d_ds, 0, sizeof(*d_ds)); off = sizeof(*d_ds); mem_acc = d_ds->mem_access_array; /* copy the mem_transaction_descr */ d_ds->sender_id = receiver->smem->sender_id; d_ds->mem_reg_attr = receiver->smem->mem_reg_attr; d_ds->flags = FFA_MEMORY_TRANSACTION_TYPE_SHARE; d_ds->tag = receiver->smem->tag; d_ds->mem_access_count = 1; } else { struct ffa_mem_transaction_1_1 *d_ds = dst_buffer; memset(d_ds, 0, sizeof(*d_ds)); off = sizeof(*d_ds); mem_acc = (void *)(d_ds + 1); d_ds->sender_id = receiver->smem->sender_id; d_ds->mem_reg_attr = receiver->smem->mem_reg_attr; d_ds->flags = FFA_MEMORY_TRANSACTION_TYPE_SHARE; d_ds->tag = receiver->smem->tag; d_ds->mem_access_size = sizeof(*mem_acc); d_ds->mem_access_count = 1; d_ds->mem_access_offs = off; } off += sizeof(struct ffa_mem_access); dst_region = (struct ffa_mem_region *)(mem_acc + 1); /* Copy the mem_accsess_descr */ mem_acc[0].region_offs = off; memcpy(&mem_acc[0].access_perm, &receiver->perm, sizeof(struct ffa_mem_access_perm)); /* Copy the mem_region_descr */ memset(dst_region, 0, sizeof(*dst_region)); dst_region->address_range_count = 0; dst_region->total_page_count = 0; addr_dst = dst_region->address_range_array; SLIST_FOREACH(reg, &smem->regions, link) { uint32_t offset = reg->page_offset; struct sp_ctx *ctx = to_sp_ctx(s->ts_sess.ctx); addr_dst->address = (uint64_t)sp_mem_get_va(&ctx->uctx, offset, reg->mobj); addr_dst->page_count = reg->page_count; dst_region->address_range_count++; dst_region->total_page_count += addr_dst->page_count; } } static void ffa_mem_retrieve(struct thread_smc_args *args, struct sp_session *caller_sp, struct ffa_rxtx *rxtx) { struct ffa_mem_transaction_x mem_trans = { }; uint32_t tot_len = args->a1; uint32_t frag_len = args->a2; int ret = FFA_OK; size_t tx_len = 0; struct ffa_mem_access *mem_acc = NULL; struct ffa_mem_region *mem_region = NULL; uint64_t va = 0; struct sp_mem *smem = NULL; struct sp_mem_receiver *receiver = NULL; uint32_t exceptions = 0; uint32_t address_offset = 0; size_t needed_size = 0; if (!check_rxtx(rxtx) || !rxtx->tx_is_mine) { ret = FFA_DENIED; goto err; } /* Descriptor fragments aren't supported yet. */ if (frag_len != tot_len) { ret = FFA_NOT_SUPPORTED; goto err; } if (frag_len > rxtx->size) { ret = FFA_INVALID_PARAMETERS; goto err; } tx_len = rxtx->size; ret = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx, frag_len, &mem_trans); if (ret) goto err; smem = sp_mem_get(mem_trans.global_handle); if (!smem) { DMSG("Incorrect handle"); ret = FFA_DENIED; goto err; } receiver = sp_mem_get_receiver(caller_sp->endpoint_id, smem); mem_acc = (void *)((vaddr_t)rxtx->rx + mem_trans.mem_access_offs); address_offset = READ_ONCE(mem_acc[0].region_offs); if (ADD_OVERFLOW(address_offset, sizeof(struct ffa_mem_region), &needed_size) || needed_size > tx_len) { ret = FFA_INVALID_PARAMETERS; goto err; } if (check_retrieve_request(receiver, rxtx->ffa_vers, &mem_trans, rxtx->rx, smem, tx_len) != TEE_SUCCESS) { ret = FFA_INVALID_PARAMETERS; goto err; } exceptions = cpu_spin_lock_xsave(&mem_ref_lock); if (receiver->ref_count == UINT8_MAX) { ret = FFA_DENIED; cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); goto err; } receiver->ref_count++; /* We only need to map the region the first time we request it. */ if (receiver->ref_count == 1) { TEE_Result ret_map = TEE_SUCCESS; cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); /* * Try to map the memory linked to the handle in * sp_mem_access_descr. */ mem_region = (struct ffa_mem_region *)((vaddr_t)rxtx->rx + address_offset); va = READ_ONCE(mem_region->address_range_array[0].address); ret_map = sp_map_shared(caller_sp, receiver, smem, &va); if (ret_map) { EMSG("Could not map memory region: %#"PRIx32, ret_map); exceptions = cpu_spin_lock_xsave(&mem_ref_lock); receiver->ref_count--; cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); ret = FFA_DENIED; goto err; } } else { cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); } create_retrieve_response(rxtx->ffa_vers, rxtx->tx, receiver, smem, caller_sp); args->a0 = FFA_MEM_RETRIEVE_RESP; args->a1 = tx_len; args->a2 = tx_len; rxtx->tx_is_mine = false; return; err: ffa_set_error(args, ret); } static void ffa_mem_relinquish(struct thread_smc_args *args, struct sp_session *caller_sp, struct ffa_rxtx *rxtx) { struct sp_mem *smem = NULL; struct ffa_mem_relinquish *mem = rxtx->rx; struct sp_mem_receiver *receiver = NULL; int err = FFA_NOT_SUPPORTED; uint32_t exceptions = 0; if (!check_rxtx(rxtx)) { ffa_set_error(args, FFA_DENIED); return; } exceptions = cpu_spin_lock_xsave(&rxtx->spinlock); smem = sp_mem_get(READ_ONCE(mem->handle)); if (!smem) { DMSG("Incorrect handle"); err = FFA_DENIED; goto err_unlock_rxtwx; } if (READ_ONCE(mem->endpoint_count) != 1) { DMSG("Incorrect endpoint count"); err = FFA_INVALID_PARAMETERS; goto err_unlock_rxtwx; } if (READ_ONCE(mem->endpoint_id_array[0]) != caller_sp->endpoint_id) { DMSG("Incorrect endpoint id"); err = FFA_DENIED; goto err_unlock_rxtwx; } cpu_spin_unlock_xrestore(&rxtx->spinlock, exceptions); receiver = sp_mem_get_receiver(caller_sp->endpoint_id, smem); exceptions = cpu_spin_lock_xsave(&mem_ref_lock); if (!receiver->ref_count) { DMSG("To many relinquish requests"); err = FFA_DENIED; goto err_unlock_memref; } receiver->ref_count--; if (!receiver->ref_count) { cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); if (sp_unmap_ffa_regions(caller_sp, smem) != TEE_SUCCESS) { DMSG("Failed to unmap region"); ffa_set_error(args, FFA_DENIED); return; } } else { cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); } ffa_success(args); return; err_unlock_rxtwx: cpu_spin_unlock_xrestore(&rxtx->spinlock, exceptions); ffa_set_error(args, err); return; err_unlock_memref: cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); ffa_set_error(args, err); } static void zero_mem_region(struct sp_mem *smem, struct sp_session *s) { void *addr = NULL; struct sp_ctx *ctx = to_sp_ctx(s->ts_sess.ctx); struct sp_mem_map_region *reg = NULL; ts_push_current_session(&s->ts_sess); SLIST_FOREACH(reg, &smem->regions, link) { size_t sz = reg->page_count * SMALL_PAGE_SIZE; addr = sp_mem_get_va(&ctx->uctx, reg->page_offset, reg->mobj); assert(addr); memset(addr, 0, sz); } ts_pop_current_session(); } /* * ffa_mem_reclaim returns false if it couldn't process the reclaim message. * This happens when the memory regions was shared with the OP-TEE endpoint. * After this thread_spmc calls handle_mem_reclaim() to make sure that the * region is reclaimed from the OP-TEE endpoint. */ bool ffa_mem_reclaim(struct thread_smc_args *args, struct sp_session *caller_sp) { uint64_t handle = reg_pair_to_64(args->a2, args->a1); uint32_t flags = args->a3; struct sp_mem *smem = NULL; struct sp_mem_receiver *receiver = NULL; uint32_t exceptions = 0; smem = sp_mem_get(handle); if (!smem) return false; /* * If the caller is an SP, make sure that it is the owner of the share. * If the call comes from NWd this is ensured by the hypervisor. */ if (caller_sp && caller_sp->endpoint_id != smem->sender_id) { ffa_set_error(args, FFA_INVALID_PARAMETERS); return true; } exceptions = cpu_spin_lock_xsave(&mem_ref_lock); /* Make sure that all shares where relinquished */ SLIST_FOREACH(receiver, &smem->receivers, link) { if (receiver->ref_count != 0) { ffa_set_error(args, FFA_DENIED); cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); return true; } } if (flags & FFA_MEMORY_REGION_FLAG_CLEAR) { if (caller_sp) { zero_mem_region(smem, caller_sp); } else { /* * Currently we don't support zeroing Normal World * memory. To do this we would have to map the memory * again, zero it and unmap it. */ ffa_set_error(args, FFA_DENIED); cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); return true; } } sp_mem_remove(smem); cpu_spin_unlock_xrestore(&mem_ref_lock, exceptions); ffa_success(args); return true; } static struct sp_session * ffa_handle_sp_direct_req(struct thread_smc_args *args, struct sp_session *caller_sp) { struct sp_session *dst = NULL; TEE_Result res = FFA_OK; if (args->a2 != FFA_PARAM_MBZ) { ffa_set_error(args, FFA_INVALID_PARAMETERS); return caller_sp; } res = ffa_get_dst(args, caller_sp, &dst); if (res) { /* Tried to send message to an incorrect endpoint */ ffa_set_error(args, res); return caller_sp; } if (!dst) { EMSG("Request to normal world not supported"); ffa_set_error(args, FFA_NOT_SUPPORTED); return caller_sp; } if (dst == caller_sp) { EMSG("Cannot send message to own ID"); ffa_set_error(args, FFA_INVALID_PARAMETERS); return caller_sp; } cpu_spin_lock(&dst->spinlock); if (dst->state != sp_idle) { DMSG("SP is busy"); ffa_set_error(args, FFA_BUSY); cpu_spin_unlock(&dst->spinlock); return caller_sp; } dst->state = sp_busy; cpu_spin_unlock(&dst->spinlock); /* * Store the calling endpoint id. This will make it possible to check * if the response is sent back to the correct endpoint. */ dst->caller_id = FFA_SRC(args->a1); /* Forward the message to the destination SP */ res = sp_enter(args, dst); if (res) { /* The SP Panicked */ ffa_set_error(args, FFA_ABORTED); /* Return error to calling SP */ return caller_sp; } return dst; } static struct sp_session * ffa_handle_sp_direct_resp(struct thread_smc_args *args, struct sp_session *caller_sp) { struct sp_session *dst = NULL; TEE_Result res = FFA_OK; if (!caller_sp) { EMSG("Response from normal world not supported"); ffa_set_error(args, FFA_NOT_SUPPORTED); return NULL; } res = ffa_get_dst(args, caller_sp, &dst); if (res) { /* Tried to send response to an incorrect endpoint */ ffa_set_error(args, res); return caller_sp; } if (dst && dst->state != sp_busy) { EMSG("SP is not waiting for a request"); ffa_set_error(args, FFA_INVALID_PARAMETERS); return caller_sp; } if (caller_sp->caller_id != FFA_DST(args->a1)) { EMSG("FFA_MSG_SEND_DIRECT_RESP to incorrect SP"); ffa_set_error(args, FFA_INVALID_PARAMETERS); return caller_sp; } caller_sp->caller_id = 0; cpu_spin_lock(&caller_sp->spinlock); caller_sp->state = sp_idle; cpu_spin_unlock(&caller_sp->spinlock); if (!dst) { /* Send message back to the NW */ return NULL; } /* Forward the message to the destination SP */ res = sp_enter(args, dst); if (res) { /* The SP Panicked */ ffa_set_error(args, FFA_ABORTED); /* Return error to calling SP */ return caller_sp; } return dst; } static struct sp_session * ffa_handle_sp_error(struct thread_smc_args *args, struct sp_session *caller_sp) { /* If caller_sp == NULL send message to Normal World */ if (caller_sp && sp_enter(args, caller_sp)) { /* * We can not return the error. Unwind the call chain with one * link. Set the state of the SP to dead. */ caller_sp->state = sp_dead; /* Create error. */ ffa_set_error(args, FFA_ABORTED); return sp_get_session(caller_sp->caller_id); } return caller_sp; } static void handle_features(struct thread_smc_args *args) { uint32_t ret_fid = 0; uint32_t ret_w2 = FFA_PARAM_MBZ; switch (args->a1) { #ifdef ARM64 case FFA_RXTX_MAP_64: #endif case FFA_RXTX_MAP_32: ret_fid = FFA_SUCCESS_32; ret_w2 = 0; /* 4kB Minimum buffer size and alignment boundary */ break; case FFA_ERROR: case FFA_VERSION: case FFA_SUCCESS_32: #ifdef ARM64 case FFA_SUCCESS_64: #endif default: ret_fid = FFA_ERROR; ret_w2 = FFA_NOT_SUPPORTED; break; } spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_w2, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static void handle_mem_perm_get(struct thread_smc_args *args, struct sp_session *sp_s) { struct sp_ctx *sp_ctx = NULL; TEE_Result res = TEE_ERROR_BAD_PARAMETERS; uint16_t attrs = 0; uint32_t ret_fid = FFA_ERROR; uint32_t ret_val = FFA_INVALID_PARAMETERS; /* * The FFA_MEM_PERM_GET interface is only allowed during initialization */ if (sp_s->is_initialized) { ret_val = FFA_DENIED; goto out; } sp_ctx = to_sp_ctx(sp_s->ts_sess.ctx); if (!sp_ctx) goto out; /* Query memory attributes */ ts_push_current_session(&sp_s->ts_sess); res = vm_get_prot(&sp_ctx->uctx, args->a1, SMALL_PAGE_SIZE, &attrs); ts_pop_current_session(); if (res) goto out; /* Build response value */ ret_fid = FFA_SUCCESS_32; ret_val = 0; if ((attrs & TEE_MATTR_URW) == TEE_MATTR_URW) ret_val |= FFA_MEM_PERM_RW; else if (attrs & TEE_MATTR_UR) ret_val |= FFA_MEM_PERM_RO; if ((attrs & TEE_MATTR_UX) == 0) ret_val |= FFA_MEM_PERM_NX; out: spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_val, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static void handle_mem_perm_set(struct thread_smc_args *args, struct sp_session *sp_s) { struct sp_ctx *sp_ctx = NULL; TEE_Result res = TEE_ERROR_BAD_PARAMETERS; size_t region_size = 0; uint32_t data_perm = 0; uint32_t instruction_perm = 0; uint16_t attrs = 0; uint32_t ret_fid = FFA_ERROR; uint32_t ret_val = FFA_INVALID_PARAMETERS; /* * The FFA_MEM_PERM_GET interface is only allowed during initialization */ if (sp_s->is_initialized) { ret_val = FFA_DENIED; goto out; } sp_ctx = to_sp_ctx(sp_s->ts_sess.ctx); if (!sp_ctx) goto out; if (MUL_OVERFLOW(args->a2, SMALL_PAGE_SIZE, ®ion_size)) goto out; if (args->a3 & FFA_MEM_PERM_RESERVED) { /* Non-zero reserved bits */ goto out; } data_perm = args->a3 & FFA_MEM_PERM_DATA_PERM; instruction_perm = args->a3 & FFA_MEM_PERM_INSTRUCTION_PERM; /* RWX access right configuration is not permitted */ if (data_perm == FFA_MEM_PERM_RW && instruction_perm == FFA_MEM_PERM_X) goto out; switch (data_perm) { case FFA_MEM_PERM_RO: attrs = TEE_MATTR_UR; break; case FFA_MEM_PERM_RW: attrs = TEE_MATTR_URW; break; default: /* Invalid permission value */ goto out; } if (instruction_perm == FFA_MEM_PERM_X) attrs |= TEE_MATTR_UX; /* Set access rights */ ts_push_current_session(&sp_s->ts_sess); res = vm_set_prot(&sp_ctx->uctx, args->a1, region_size, attrs); ts_pop_current_session(); if (res != TEE_SUCCESS) goto out; ret_fid = FFA_SUCCESS_32; ret_val = FFA_PARAM_MBZ; out: spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_val, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static void spmc_handle_version(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { spmc_set_args(args, spmc_exchange_version(args->a1, rxtx), FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static void handle_console_log(struct thread_smc_args *args) { uint32_t ret_fid = FFA_ERROR; uint32_t ret_val = FFA_INVALID_PARAMETERS; size_t char_count = args->a1 & FFA_CONSOLE_LOG_CHAR_COUNT_MASK; const void *reg_list[] = { &args->a2, &args->a3, &args->a4, &args->a5, &args->a6, &args->a7 }; char buffer[FFA_CONSOLE_LOG_64_MAX_MSG_LEN + 1] = { 0 }; size_t max_length = 0; size_t reg_size = 0; size_t n = 0; if (args->a0 == FFA_CONSOLE_LOG_64) { max_length = FFA_CONSOLE_LOG_64_MAX_MSG_LEN; reg_size = sizeof(uint64_t); } else { max_length = FFA_CONSOLE_LOG_32_MAX_MSG_LEN; reg_size = sizeof(uint32_t); } if (char_count < 1 || char_count > max_length) goto out; for (n = 0; n < char_count; n += reg_size) memcpy(buffer + n, reg_list[n / reg_size], MIN(char_count - n, reg_size)); buffer[char_count] = '\0'; trace_ext_puts(buffer); ret_fid = FFA_SUCCESS_32; ret_val = FFA_PARAM_MBZ; out: spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_val, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } /* * FF-A messages handler for SP. Every messages for or from a SP is handled * here. This is the entry of the sp_spmc kernel thread. The caller_sp is set * to NULL when it is the Normal World. */ void spmc_sp_msg_handler(struct thread_smc_args *args, struct sp_session *caller_sp) { thread_check_canaries(); do { switch (args->a0) { #ifdef ARM64 case FFA_MSG_SEND_DIRECT_REQ_64: #endif case FFA_MSG_SEND_DIRECT_REQ_32: caller_sp = ffa_handle_sp_direct_req(args, caller_sp); break; #ifdef ARM64 case FFA_MSG_SEND_DIRECT_RESP_64: #endif case FFA_MSG_SEND_DIRECT_RESP_32: caller_sp = ffa_handle_sp_direct_resp(args, caller_sp); break; case FFA_ERROR: caller_sp = ffa_handle_sp_error(args, caller_sp); break; case FFA_MSG_WAIT: /* FFA_WAIT gives control back to NW */ cpu_spin_lock(&caller_sp->spinlock); caller_sp->state = sp_idle; cpu_spin_unlock(&caller_sp->spinlock); caller_sp = NULL; break; #ifdef ARM64 case FFA_RXTX_MAP_64: #endif case FFA_RXTX_MAP_32: ts_push_current_session(&caller_sp->ts_sess); spmc_handle_rxtx_map(args, &caller_sp->rxtx); ts_pop_current_session(); sp_enter(args, caller_sp); break; case FFA_RXTX_UNMAP: ts_push_current_session(&caller_sp->ts_sess); spmc_handle_rxtx_unmap(args, &caller_sp->rxtx); ts_pop_current_session(); sp_enter(args, caller_sp); break; case FFA_RX_RELEASE: ts_push_current_session(&caller_sp->ts_sess); spmc_handle_rx_release(args, &caller_sp->rxtx); ts_pop_current_session(); sp_enter(args, caller_sp); break; case FFA_ID_GET: args->a0 = FFA_SUCCESS_32; args->a2 = caller_sp->endpoint_id; sp_enter(args, caller_sp); break; case FFA_VERSION: spmc_handle_version(args, &caller_sp->rxtx); sp_enter(args, caller_sp); break; case FFA_FEATURES: handle_features(args); sp_enter(args, caller_sp); break; case FFA_SPM_ID_GET: spmc_handle_spm_id_get(args); sp_enter(args, caller_sp); break; case FFA_PARTITION_INFO_GET: ts_push_current_session(&caller_sp->ts_sess); spmc_handle_partition_info_get(args, &caller_sp->rxtx); ts_pop_current_session(); sp_enter(args, caller_sp); break; #ifdef ARM64 case FFA_MEM_SHARE_64: #endif case FFA_MEM_SHARE_32: ts_push_current_session(&caller_sp->ts_sess); spmc_sp_handle_mem_share(args, &caller_sp->rxtx, caller_sp); ts_pop_current_session(); sp_enter(args, caller_sp); break; #ifdef ARM64 case FFA_MEM_RETRIEVE_REQ_64: #endif case FFA_MEM_RETRIEVE_REQ_32: ts_push_current_session(&caller_sp->ts_sess); ffa_mem_retrieve(args, caller_sp, &caller_sp->rxtx); ts_pop_current_session(); sp_enter(args, caller_sp); break; case FFA_MEM_RELINQUISH: ts_push_current_session(&caller_sp->ts_sess); ffa_mem_relinquish(args, caller_sp, &caller_sp->rxtx); ts_pop_current_session(); sp_enter(args, caller_sp); break; case FFA_MEM_RECLAIM: ffa_mem_reclaim(args, caller_sp); sp_enter(args, caller_sp); break; #ifdef ARM64 case FFA_MEM_PERM_GET_64: #endif case FFA_MEM_PERM_GET_32: handle_mem_perm_get(args, caller_sp); sp_enter(args, caller_sp); break; #ifdef ARM64 case FFA_MEM_PERM_SET_64: #endif case FFA_MEM_PERM_SET_32: handle_mem_perm_set(args, caller_sp); sp_enter(args, caller_sp); break; #ifdef ARM64 case FFA_CONSOLE_LOG_64: #endif case FFA_CONSOLE_LOG_32: handle_console_log(args); sp_enter(args, caller_sp); break; default: EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0); ffa_set_error(args, FFA_INVALID_PARAMETERS); sp_enter(args, caller_sp); } } while (caller_sp); } optee_os-4.3.0/core/arch/arm/kernel/stmm_sp.c000066400000000000000000000547501464416617300211140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ARM64 #define SVC_REGS_A0(_regs) ((_regs)->x0) #define SVC_REGS_A1(_regs) ((_regs)->x1) #define SVC_REGS_A2(_regs) ((_regs)->x2) #define SVC_REGS_A3(_regs) ((_regs)->x3) #define SVC_REGS_A4(_regs) ((_regs)->x4) #define SVC_REGS_A5(_regs) ((_regs)->x5) #define SVC_REGS_A6(_regs) ((_regs)->x6) #define SVC_REGS_A7(_regs) ((_regs)->x7) #define __FFA_SVC_RPMB_READ FFA_SVC_RPMB_READ #define __FFA_SVC_RPMB_WRITE FFA_SVC_RPMB_WRITE #define __FFA_SVC_MEMORY_ATTRIBUTES_GET FFA_SVC_MEMORY_ATTRIBUTES_GET_64 #define __FFA_SVC_MEMORY_ATTRIBUTES_SET FFA_SVC_MEMORY_ATTRIBUTES_SET_64 #define __FFA_MSG_SEND_DIRECT_RESP FFA_MSG_SEND_DIRECT_RESP_64 #define __FFA_MSG_SEND_DIRECT_REQ FFA_MSG_SEND_DIRECT_REQ_64 #endif #ifdef ARM32 #define SVC_REGS_A0(_regs) ((_regs)->r0) #define SVC_REGS_A1(_regs) ((_regs)->r1) #define SVC_REGS_A2(_regs) ((_regs)->r2) #define SVC_REGS_A3(_regs) ((_regs)->r3) #define SVC_REGS_A4(_regs) ((_regs)->r4) #define SVC_REGS_A5(_regs) ((_regs)->r5) #define SVC_REGS_A6(_regs) ((_regs)->r6) #define SVC_REGS_A7(_regs) ((_regs)->r7) #define __FFA_SVC_RPMB_READ FFA_SVC_RPMB_READ_32 #define __FFA_SVC_RPMB_WRITE FFA_SVC_RPMB_WRITE_32 #define __FFA_SVC_MEMORY_ATTRIBUTES_GET FFA_SVC_MEMORY_ATTRIBUTES_GET_32 #define __FFA_SVC_MEMORY_ATTRIBUTES_SET FFA_SVC_MEMORY_ATTRIBUTES_SET_32 #define __FFA_MSG_SEND_DIRECT_RESP FFA_MSG_SEND_DIRECT_RESP_32 #define __FFA_MSG_SEND_DIRECT_REQ FFA_MSG_SEND_DIRECT_REQ_32 #endif static const TEE_UUID stmm_uuid = PTA_STMM_UUID; /* * Once a complete FFA spec is added, these will become discoverable. * Until then these are considered part of the internal ABI between * OP-TEE and StMM. */ static const uint16_t stmm_id = 1U; static const uint16_t stmm_pta_id = 2U; static const uint16_t mem_mgr_id = 3U; static const uint16_t ffa_storage_id = 4U; static const unsigned int stmm_stack_size = 4 * SMALL_PAGE_SIZE; static const unsigned int stmm_heap_size = 398 * SMALL_PAGE_SIZE; static const unsigned int stmm_sec_buf_size = 4 * SMALL_PAGE_SIZE; static const unsigned int stmm_ns_comm_buf_size = 4 * SMALL_PAGE_SIZE; extern unsigned char stmm_image[]; extern const unsigned int stmm_image_size; extern const unsigned int stmm_image_uncompressed_size; const TEE_UUID *stmm_get_uuid(void) { return &stmm_uuid; } static struct stmm_ctx *stmm_alloc_ctx(const TEE_UUID *uuid) { TEE_Result res = TEE_SUCCESS; struct stmm_ctx *spc = NULL; spc = calloc(1, sizeof(*spc)); if (!spc) return NULL; spc->ta_ctx.ts_ctx.ops = &stmm_sp_ops; spc->ta_ctx.ts_ctx.uuid = *uuid; spc->ta_ctx.flags = TA_FLAG_SINGLE_INSTANCE | TA_FLAG_INSTANCE_KEEP_ALIVE; res = vm_info_init(&spc->uctx, &spc->ta_ctx.ts_ctx); if (res) { free(spc); return NULL; } spc->ta_ctx.ref_count = 1; condvar_init(&spc->ta_ctx.busy_cv); return spc; } static TEE_Result stmm_enter_user_mode(struct stmm_ctx *spc) { uint32_t exceptions = 0; uint32_t panic_code = 0; uint32_t panicked = 0; uint64_t cntkctl = 0; exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); cntkctl = read_cntkctl(); write_cntkctl(cntkctl | CNTKCTL_PL0PCTEN); #ifdef ARM32 /* Handle usr_lr in place of __thread_enter_user_mode() */ thread_set_usr_lr(spc->regs.usr_lr); #endif __thread_enter_user_mode(&spc->regs, &panicked, &panic_code); #ifdef ARM32 spc->regs.usr_lr = thread_get_usr_lr(); #endif write_cntkctl(cntkctl); thread_unmask_exceptions(exceptions); thread_user_clear_vfp(&spc->uctx); if (panicked) { abort_print_current_ts(); DMSG("stmm panicked with code %#"PRIx32, panic_code); return TEE_ERROR_TARGET_DEAD; } return TEE_SUCCESS; } #ifdef ARM64 static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0, unsigned long a1, unsigned long sp, unsigned long pc) { spc->regs.x[0] = a0; spc->regs.x[1] = a1; spc->regs.sp = sp; spc->regs.pc = pc; } #endif #ifdef ARM32 static uint32_t __maybe_unused get_spsr(void) { uint32_t s = 0; s = read_cpsr(); s &= ~(CPSR_MODE_MASK | CPSR_T | ARM32_CPSR_IT_MASK); s |= CPSR_MODE_USR; return s; } static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0, unsigned long a1, unsigned long sp, unsigned long pc) { spc->regs.r0 = a0; spc->regs.r1 = a1; spc->regs.usr_sp = sp; spc->regs.cpsr = get_spsr(); spc->regs.pc = pc; } #endif static TEE_Result alloc_and_map_sp_fobj(struct stmm_ctx *spc, size_t sz, uint32_t prot, vaddr_t *va) { size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; struct fobj *fobj = fobj_ta_mem_alloc(num_pgs); TEE_Result res = TEE_SUCCESS; struct mobj *mobj = NULL; mobj = mobj_with_fobj_alloc(fobj, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(fobj); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map(&spc->uctx, va, num_pgs * SMALL_PAGE_SIZE, prot, 0, mobj, 0); if (res) mobj_put(mobj); return TEE_SUCCESS; } static void *zalloc(void *opaque __unused, unsigned int items, unsigned int size) { return mempool_alloc(mempool_default, items * size); } static void zfree(void *opaque __unused, void *address) { mempool_free(mempool_default, address); } static void uncompress_image(void *dst, size_t dst_size, void *src, size_t src_size) { z_stream strm = { .next_in = src, .avail_in = src_size, .next_out = dst, .avail_out = dst_size, .zalloc = zalloc, .zfree = zfree, }; if (inflateInit(&strm) != Z_OK) panic("inflateInit"); if (inflate(&strm, Z_SYNC_FLUSH) != Z_STREAM_END) panic("inflate"); if (inflateEnd(&strm) != Z_OK) panic("inflateEnd"); } static TEE_Result load_stmm(struct stmm_ctx *spc) { struct stmm_boot_info *boot_info = NULL; struct stmm_mp_info *mp_info = NULL; TEE_Result res = TEE_SUCCESS; vaddr_t sp_addr = 0; vaddr_t image_addr = 0; vaddr_t heap_addr = 0; vaddr_t stack_addr = 0; vaddr_t sec_buf_addr = 0; vaddr_t comm_buf_addr = 0; unsigned int sp_size = 0; unsigned int uncompressed_size_roundup = 0; uncompressed_size_roundup = ROUNDUP(stmm_image_uncompressed_size, SMALL_PAGE_SIZE); sp_size = uncompressed_size_roundup + stmm_stack_size + stmm_heap_size + stmm_sec_buf_size; res = alloc_and_map_sp_fobj(spc, sp_size, TEE_MATTR_PRW, &sp_addr); if (res) return res; res = alloc_and_map_sp_fobj(spc, stmm_ns_comm_buf_size, TEE_MATTR_URW | TEE_MATTR_PRW, &comm_buf_addr); /* * We don't need to free the previous instance here, they'll all be * handled during the destruction call (stmm_ctx_destroy()) */ if (res) return res; image_addr = sp_addr; heap_addr = image_addr + uncompressed_size_roundup; stack_addr = heap_addr + stmm_heap_size; sec_buf_addr = stack_addr + stmm_stack_size; vm_set_ctx(&spc->ta_ctx.ts_ctx); uncompress_image((void *)image_addr, stmm_image_uncompressed_size, stmm_image, stmm_image_size); res = vm_set_prot(&spc->uctx, image_addr, uncompressed_size_roundup, TEE_MATTR_URX | TEE_MATTR_PR); if (res) return res; res = vm_set_prot(&spc->uctx, heap_addr, stmm_heap_size, TEE_MATTR_URW | TEE_MATTR_PRW); if (res) return res; res = vm_set_prot(&spc->uctx, stack_addr, stmm_stack_size, TEE_MATTR_URW | TEE_MATTR_PRW); if (res) return res; res = vm_set_prot(&spc->uctx, sec_buf_addr, stmm_sec_buf_size, TEE_MATTR_URW | TEE_MATTR_PRW); if (res) return res; DMSG("stmm load address %#"PRIxVA, image_addr); boot_info = (struct stmm_boot_info *)sec_buf_addr; mp_info = (struct stmm_mp_info *)(boot_info + 1); *boot_info = (struct stmm_boot_info){ .h.type = STMM_PARAM_SP_IMAGE_BOOT_INFO, .h.version = STMM_PARAM_VERSION_1, .h.size = sizeof(struct stmm_boot_info), .h.attr = 0, .sp_mem_base = sp_addr, .sp_mem_limit = sp_addr + sp_size, .sp_image_base = image_addr, .sp_stack_base = stack_addr, .sp_heap_base = heap_addr, .sp_ns_comm_buf_base = comm_buf_addr, .sp_shared_buf_base = sec_buf_addr, .sp_image_size = stmm_image_size, .sp_pcpu_stack_size = stmm_stack_size, .sp_heap_size = stmm_heap_size, .sp_ns_comm_buf_size = stmm_ns_comm_buf_size, .sp_shared_buf_size = stmm_sec_buf_size, .num_sp_mem_regions = 6, .num_cpus = 1, .mp_info = mp_info, }; mp_info->mpidr = read_mpidr(); mp_info->linear_id = 0; mp_info->flags = MP_INFO_FLAG_PRIMARY_CPU; spc->ns_comm_buf_addr = comm_buf_addr; spc->ns_comm_buf_size = stmm_ns_comm_buf_size; init_stmm_regs(spc, sec_buf_addr, (vaddr_t)(mp_info + 1) - sec_buf_addr, stack_addr + stmm_stack_size, image_addr); return stmm_enter_user_mode(spc); } TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess) { struct stmm_ctx *spc = NULL; /* Caller is expected to hold tee_ta_mutex for safe changes in @sess */ assert(mutex_is_locked(&tee_ta_mutex)); if (memcmp(uuid, &stmm_uuid, sizeof(*uuid))) return TEE_ERROR_ITEM_NOT_FOUND; spc = stmm_alloc_ctx(uuid); if (!spc) return TEE_ERROR_OUT_OF_MEMORY; spc->ta_ctx.is_initializing = true; sess->ts_sess.ctx = &spc->ta_ctx.ts_ctx; sess->ts_sess.handle_scall = sess->ts_sess.ctx->ops->handle_scall; return TEE_SUCCESS; } TEE_Result stmm_complete_session(struct tee_ta_session *sess) { struct stmm_ctx *spc = to_stmm_ctx(sess->ts_sess.ctx); TEE_Result res = TEE_SUCCESS; ts_push_current_session(&sess->ts_sess); res = load_stmm(spc); ts_pop_current_session(); vm_set_ctx(NULL); if (res) { sess->ts_sess.ctx = NULL; spc->ta_ctx.ts_ctx.ops->destroy(&spc->ta_ctx.ts_ctx); return res; } mutex_lock(&tee_ta_mutex); spc->ta_ctx.is_initializing = false; TAILQ_INSERT_TAIL(&tee_ctxes, &spc->ta_ctx, link); mutex_unlock(&tee_ta_mutex); return TEE_SUCCESS; } static TEE_Result stmm_enter_open_session(struct ts_session *s) { struct stmm_ctx *spc = to_stmm_ctx(s->ctx); struct tee_ta_session *ta_sess = to_ta_session(s); const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (ta_sess->param->types != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (spc->ta_ctx.is_initializing) { /* StMM is initialized in stmm_init_session() */ ta_sess->err_origin = TEE_ORIGIN_TEE; return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static TEE_Result stmm_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) { struct stmm_ctx *spc = to_stmm_ctx(s->ctx); struct tee_ta_session *ta_sess = to_ta_session(s); TEE_Result res = TEE_SUCCESS; TEE_Result __maybe_unused tmp_res = TEE_SUCCESS; unsigned int ns_buf_size = 0; struct param_mem *mem = NULL; void *va = NULL; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (cmd != PTA_STMM_CMD_COMMUNICATE) return TEE_ERROR_BAD_PARAMETERS; if (ta_sess->param->types != exp_pt) return TEE_ERROR_BAD_PARAMETERS; mem = &ta_sess->param->u[0].mem; ns_buf_size = mem->size; if (ns_buf_size > spc->ns_comm_buf_size) { mem->size = spc->ns_comm_buf_size; return TEE_ERROR_EXCESS_DATA; } res = mobj_inc_map(mem->mobj); if (res) return res; va = mobj_get_va(mem->mobj, mem->offs, mem->size); if (!va) { EMSG("Can't get a valid VA for NS buffer"); res = TEE_ERROR_BAD_PARAMETERS; goto out_va; } #ifdef ARM64 spc->regs.x[0] = __FFA_MSG_SEND_DIRECT_REQ; spc->regs.x[1] = (stmm_pta_id << 16) | stmm_id; spc->regs.x[2] = FFA_PARAM_MBZ; spc->regs.x[3] = spc->ns_comm_buf_addr; spc->regs.x[4] = ns_buf_size; spc->regs.x[5] = 0; spc->regs.x[6] = 0; spc->regs.x[7] = 0; #endif #ifdef ARM32 spc->regs.r0 = __FFA_MSG_SEND_DIRECT_REQ; spc->regs.r1 = (stmm_pta_id << 16) | stmm_id; spc->regs.r2 = FFA_PARAM_MBZ; spc->regs.r3 = spc->ns_comm_buf_addr; spc->regs.r4 = ns_buf_size; spc->regs.r5 = 0; spc->regs.r6 = 0; spc->regs.r7 = 0; #endif ts_push_current_session(s); memcpy((void *)spc->ns_comm_buf_addr, va, ns_buf_size); res = stmm_enter_user_mode(spc); if (res) goto out_session; /* * Copy the SPM response from secure partition back to the non-secure * buffer of the client that called us. */ #ifdef ARM64 ta_sess->param->u[1].val.a = spc->regs.x[4]; #endif #ifdef ARM32 ta_sess->param->u[1].val.a = spc->regs.r4; #endif memcpy(va, (void *)spc->ns_comm_buf_addr, ns_buf_size); out_session: ts_pop_current_session(); out_va: tmp_res = mobj_dec_map(mem->mobj); assert(!tmp_res); return res; } static void stmm_enter_close_session(struct ts_session *s __unused) { } static void stmm_dump_state(struct ts_ctx *ctx) { user_mode_ctx_print_mappings(to_user_mode_ctx(ctx)); } DECLARE_KEEP_PAGER(stmm_dump_state); static uint32_t stmm_get_instance_id(struct ts_ctx *ctx) { return to_stmm_ctx(ctx)->uctx.vm_info.asid; } static void stmm_ctx_destroy(struct ts_ctx *ctx) { struct stmm_ctx *spc = to_stmm_ctx(ctx); vm_info_final(&spc->uctx); free(spc); } static uint32_t sp_svc_get_mem_attr(vaddr_t va) { TEE_Result res = TEE_ERROR_BAD_PARAMETERS; struct ts_session *sess = NULL; struct stmm_ctx *spc = NULL; uint16_t attrs = 0; uint16_t perm = 0; if (!va) goto err; sess = ts_get_current_session(); spc = to_stmm_ctx(sess->ctx); res = vm_get_prot(&spc->uctx, va, SMALL_PAGE_SIZE, &attrs); if (res) goto err; if (attrs & TEE_MATTR_UR) perm |= STMM_MEM_ATTR_ACCESS_RO; else if (attrs & TEE_MATTR_UW) perm |= STMM_MEM_ATTR_ACCESS_RW; if (attrs & TEE_MATTR_UX) perm |= STMM_MEM_ATTR_EXEC; return perm; err: return STMM_RET_DENIED; } static int sp_svc_set_mem_attr(vaddr_t va, unsigned int nr_pages, uint32_t perm) { TEE_Result res = TEE_ERROR_BAD_PARAMETERS; struct ts_session *sess = NULL; struct stmm_ctx *spc = NULL; size_t sz = 0; uint32_t prot = 0; if (!va || !nr_pages || MUL_OVERFLOW(nr_pages, SMALL_PAGE_SIZE, &sz)) return STMM_RET_INVALID_PARAM; if (perm & ~STMM_MEM_ATTR_ALL) return STMM_RET_INVALID_PARAM; sess = ts_get_current_session(); spc = to_stmm_ctx(sess->ctx); if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RO) prot |= TEE_MATTR_UR; else if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RW) prot |= TEE_MATTR_URW; if ((perm & STMM_MEM_ATTR_EXEC_NEVER) == STMM_MEM_ATTR_EXEC) prot |= TEE_MATTR_UX; res = vm_set_prot(&spc->uctx, va, sz, prot); if (res) return STMM_RET_DENIED; return STMM_RET_SUCCESS; } #ifdef ARM64 static void save_sp_ctx(struct stmm_ctx *spc, struct thread_scall_regs *regs) { size_t n = 0; /* Save the return values from StMM */ for (n = 0; n <= 7; n++) spc->regs.x[n] = *(®s->x0 + n); spc->regs.sp = regs->sp_el0; spc->regs.pc = regs->elr; spc->regs.cpsr = regs->spsr; } #endif #ifdef ARM32 static void save_sp_ctx(struct stmm_ctx *spc, struct thread_scall_regs *regs) { spc->regs.r0 = regs->r0; spc->regs.r1 = regs->r1; spc->regs.r2 = regs->r2; spc->regs.r3 = regs->r3; spc->regs.r4 = regs->r4; spc->regs.r5 = regs->r5; spc->regs.r6 = regs->r6; spc->regs.r7 = regs->r7; spc->regs.pc = regs->lr; spc->regs.cpsr = regs->spsr; spc->regs.usr_sp = thread_get_usr_sp(); } #endif static void return_from_sp_helper(bool panic, uint32_t panic_code, struct thread_scall_regs *regs) { struct ts_session *sess = ts_get_current_session(); struct stmm_ctx *spc = to_stmm_ctx(sess->ctx); if (panic) spc->ta_ctx.panicked = true; else save_sp_ctx(spc, regs); SVC_REGS_A0(regs) = 0; SVC_REGS_A1(regs) = panic; SVC_REGS_A2(regs) = panic_code; } static void service_compose_direct_resp(struct thread_scall_regs *regs, uint32_t ret_val) { uint16_t src_id = 0; uint16_t dst_id = 0; /* extract from request */ src_id = (SVC_REGS_A1(regs) >> 16) & UINT16_MAX; dst_id = SVC_REGS_A1(regs) & UINT16_MAX; /* compose message */ SVC_REGS_A0(regs) = __FFA_MSG_SEND_DIRECT_RESP; /* swap endpoint ids */ SVC_REGS_A1(regs) = SHIFT_U32(dst_id, 16) | src_id; SVC_REGS_A2(regs) = FFA_PARAM_MBZ; SVC_REGS_A3(regs) = ret_val; SVC_REGS_A4(regs) = 0; SVC_REGS_A5(regs) = 0; SVC_REGS_A6(regs) = 0; SVC_REGS_A7(regs) = 0; } /* * Combined read from secure partition, this will open, read and * close the file object. */ static TEE_Result sec_storage_obj_read(unsigned long storage_id, char *obj_id, unsigned long obj_id_len, void *data, unsigned long len, unsigned long offset, unsigned long flags) { const struct tee_file_operations *fops = NULL; TEE_Result res = TEE_ERROR_BAD_STATE; struct ts_session *sess = NULL; struct tee_file_handle *fh = NULL; struct tee_pobj *po = NULL; size_t file_size = 0; size_t read_len = 0; fops = tee_svc_storage_file_ops(storage_id); if (!fops) return TEE_ERROR_ITEM_NOT_FOUND; if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; sess = ts_get_current_session(); res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, &po); if (res != TEE_SUCCESS) return res; res = po->fops->open(po, &file_size, &fh); if (res != TEE_SUCCESS) goto out; read_len = len; res = po->fops->read(fh, offset, NULL, data, &read_len); if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); po->fops->remove(po); } else if (res == TEE_SUCCESS && len != read_len) { res = TEE_ERROR_CORRUPT_OBJECT; } po->fops->close(&fh); out: tee_pobj_release(po); return res; } /* * Combined write from secure partition, this will create/open, write and * close the file object. */ static TEE_Result sec_storage_obj_write(unsigned long storage_id, char *obj_id, unsigned long obj_id_len, void *data, unsigned long len, unsigned long offset, unsigned long flags) { const struct tee_file_operations *fops = NULL; struct ts_session *sess = NULL; struct tee_file_handle *fh = NULL; TEE_Result res = TEE_SUCCESS; struct tee_pobj *po = NULL; fops = tee_svc_storage_file_ops(storage_id); if (!fops) return TEE_ERROR_ITEM_NOT_FOUND; if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; sess = ts_get_current_session(); res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, &po); if (res != TEE_SUCCESS) return res; res = po->fops->open(po, NULL, &fh); if (res == TEE_ERROR_ITEM_NOT_FOUND) res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, NULL, 0, &fh); if (res == TEE_SUCCESS) { res = po->fops->write(fh, offset, NULL, data, len); po->fops->close(&fh); } tee_pobj_release(po); return res; } static void stmm_handle_mem_mgr_service(struct thread_scall_regs *regs) { uint32_t action = SVC_REGS_A3(regs); uintptr_t va = SVC_REGS_A4(regs); uint32_t nr_pages = SVC_REGS_A5(regs); uint32_t perm = SVC_REGS_A6(regs); switch (action) { case __FFA_SVC_MEMORY_ATTRIBUTES_GET: service_compose_direct_resp(regs, sp_svc_get_mem_attr(va)); break; case __FFA_SVC_MEMORY_ATTRIBUTES_SET: service_compose_direct_resp(regs, sp_svc_set_mem_attr(va, nr_pages, perm)); break; default: EMSG("Undefined service id %#"PRIx32, action); service_compose_direct_resp(regs, STMM_RET_INVALID_PARAM); break; } } static uint32_t tee2stmm_ret_val(TEE_Result res) { switch (res) { case TEE_SUCCESS: return STMM_RET_SUCCESS; case TEE_ERROR_NOT_SUPPORTED: return STMM_RET_NOT_SUPPORTED; case TEE_ERROR_ACCESS_DENIED: return STMM_RET_DENIED; case TEE_ERROR_OUT_OF_MEMORY: return STMM_RET_NO_MEM; case TEE_ERROR_BAD_PARAMETERS: default: return STMM_RET_INVALID_PARAM; } } #define FILENAME "EFI_VARS" static void stmm_handle_storage_service(struct thread_scall_regs *regs) { uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_SHARE_READ | TEE_DATA_FLAG_SHARE_WRITE; uint32_t action = SVC_REGS_A3(regs); void *va = (void *)SVC_REGS_A4(regs); unsigned long len = SVC_REGS_A5(regs); unsigned long offset = SVC_REGS_A6(regs); char obj_id[] = FILENAME; size_t obj_id_len = strlen(obj_id); TEE_Result res = TEE_SUCCESS; uint32_t stmm_rc = STMM_RET_INVALID_PARAM; switch (action) { case __FFA_SVC_RPMB_READ: DMSG("RPMB read"); res = sec_storage_obj_read(TEE_STORAGE_PRIVATE_RPMB, obj_id, obj_id_len, va, len, offset, flags); stmm_rc = tee2stmm_ret_val(res); break; case __FFA_SVC_RPMB_WRITE: DMSG("RPMB write"); res = sec_storage_obj_write(TEE_STORAGE_PRIVATE_RPMB, obj_id, obj_id_len, va, len, offset, flags); stmm_rc = tee2stmm_ret_val(res); break; default: EMSG("Undefined service id %#"PRIx32, action); break; } service_compose_direct_resp(regs, stmm_rc); } static void spm_eret_error(int32_t error_code, struct thread_scall_regs *regs) { SVC_REGS_A0(regs) = FFA_ERROR; SVC_REGS_A1(regs) = FFA_PARAM_MBZ; SVC_REGS_A2(regs) = error_code; SVC_REGS_A3(regs) = FFA_PARAM_MBZ; SVC_REGS_A4(regs) = FFA_PARAM_MBZ; SVC_REGS_A5(regs) = FFA_PARAM_MBZ; SVC_REGS_A6(regs) = FFA_PARAM_MBZ; SVC_REGS_A7(regs) = FFA_PARAM_MBZ; } static void spm_handle_direct_req(struct thread_scall_regs *regs) { uint16_t dst_id = SVC_REGS_A1(regs) & UINT16_MAX; if (dst_id == mem_mgr_id) { stmm_handle_mem_mgr_service(regs); } else if (dst_id == ffa_storage_id) { stmm_handle_storage_service(regs); } else { EMSG("Undefined endpoint id %#"PRIx16, dst_id); spm_eret_error(STMM_RET_INVALID_PARAM, regs); } } /* Return true if returning to SP, false if returning to caller */ static bool spm_handle_scall(struct thread_scall_regs *regs) { #ifdef ARM64 uint64_t *a0 = ®s->x0; #endif #ifdef ARM32 uint32_t *a0 = ®s->r0; #endif switch (*a0) { case FFA_VERSION: DMSG("Received FFA version"); *a0 = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); return true; case __FFA_MSG_SEND_DIRECT_RESP: DMSG("Received FFA direct response"); return_from_sp_helper(false, 0, regs); return false; case __FFA_MSG_SEND_DIRECT_REQ: DMSG("Received FFA direct request"); spm_handle_direct_req(regs); return true; default: EMSG("Undefined syscall %#"PRIx32, (uint32_t)*a0); return_from_sp_helper(true /*panic*/, 0xabcd, regs); return false; } } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct ts_ops stmm_sp_ops __weak __relrodata_unpaged("stmm_sp_ops") = { .enter_open_session = stmm_enter_open_session, .enter_invoke_cmd = stmm_enter_invoke_cmd, .enter_close_session = stmm_enter_close_session, .dump_state = stmm_dump_state, .destroy = stmm_ctx_destroy, .get_instance_id = stmm_get_instance_id, .handle_scall = spm_handle_scall, }; optee_os-4.3.0/core/arch/arm/kernel/sub.mk000066400000000000000000000054321464416617300204010ustar00rootroot00000000000000srcs-y += rpc_io_i2c.c srcs-y += idle.c srcs-$(CFG_SECURE_TIME_SOURCE_CNTPCT) += tee_time_arm_cntpct.c ifeq ($(CFG_CALLOUT),y) srcs-$(CFG_ARM64_core) += generic_timer.c endif srcs-$(CFG_ARM64_core) += timer_a64.c srcs-$(CFG_ARM32_core) += spin_lock_a32.S srcs-$(CFG_ARM64_core) += spin_lock_a64.S srcs-$(CFG_ARM32_core) += tlb_helpers_a32.S srcs-$(CFG_ARM64_core) += tlb_helpers_a64.S srcs-$(CFG_ARM64_core) += cache_helpers_a64.S srcs-$(CFG_ARM32_core) += cache_helpers_a32.S srcs-$(CFG_PL310) += tz_ssvce_pl310_a32.S srcs-$(CFG_PL310) += tee_l2cc_mutex.c srcs-$(CFG_ARM32_core) += thread_a32.S srcs-$(CFG_ARM64_core) += thread_a64.S srcs-y += thread.c ifeq ($(CFG_WITH_USER_TA),y) srcs-y += arch_scall.c srcs-$(CFG_ARM32_core) += arch_scall_a32.S srcs-$(CFG_ARM64_core) += arch_scall_a64.S endif ifeq ($(CFG_CORE_FFA),y) srcs-y += thread_spmc.c cppflags-thread_spmc.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) srcs-$(CFG_ARM64_core) += thread_spmc_a64.S else srcs-y += thread_optee_smc.c srcs-$(CFG_ARM32_core) += thread_optee_smc_a32.S srcs-$(CFG_ARM64_core) += thread_optee_smc_a64.S endif srcs-y += abort.c srcs-$(CFG_WITH_VFP) += vfp.c ifeq ($(CFG_WITH_VFP),y) srcs-$(CFG_ARM32_core) += vfp_a32.S srcs-$(CFG_ARM64_core) += vfp_a64.S endif srcs-$(CFG_ARM32_core) += misc_a32.S srcs-$(CFG_ARM64_core) += misc_a64.S srcs-$(CFG_WITH_STMM_SP) += stmm_sp.c srcs-$(CFG_SECURE_PARTITION) += secure_partition.c srcs-$(CFG_SECURE_PARTITION) += spmc_sp_handler.c srcs-y += boot.c srcs-$(CFG_ARM32_core) += entry_a32.S srcs-$(CFG_ARM64_core) += entry_a64.S ifeq ($(CFG_UNWIND),y) srcs-$(CFG_ARM32_core) += unwind_arm32.c srcs-$(CFG_ARM64_core) += unwind_arm64.c endif srcs-$(CFG_NS_VIRTUALIZATION) += virtualization.c ifeq ($(CFG_SEMIHOSTING),y) srcs-$(CFG_ARM64_core) += semihosting_a64.S endif srcs-y += link_dummies_paged.c srcs-y += link_dummies_init.c asm-defines-y += asm-defines.c # Reflect the following dependencies: # asm-defines.c includes # includes # includes # and (optional) asm-defines-asm-defines.c-deps += $(out-dir)/core/include/generated/arm32_sysreg.h ifeq ($(CFG_ARM_GICV3),y) asm-defines-asm-defines.c-deps += $(out-dir)/core/include/generated/arm32_gicv3_sysreg.h endif ifeq ($(CFG_SYSCALL_FTRACE),y) # We would not like to profile thread.c file as it provide common APIs # that are needed for ftrace framework to trace syscalls. So profiling # this file could create an incorrect cyclic behaviour. cflags-remove-thread.c-y += -pg # Tracing abort dump files corrupts the stack trace. So exclude them # from profiling. cflags-remove-abort.c-y += -pg ifeq ($(CFG_UNWIND),y) cflags-remove-unwind_arm32.c-y += -pg cflags-remove-unwind_arm64.c-$(CFG_ARM64_core) += -pg endif endif optee_os-4.3.0/core/arch/arm/kernel/tee_l2cc_mutex.c000066400000000000000000000057651464416617300223360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include /* * l2cc_mutex_va holds teecore virtual address of TZ L2CC mutex or NULL. * * l2cc_mutex_pa holds TZ L2CC mutex physical address. It is relevant only * if 'l2cc_mutex_va' hold a non-NULL address. */ #define MUTEX_SZ sizeof(uint32_t) static uint32_t *l2cc_mutex_va; static uint32_t l2cc_mutex_pa; static uint32_t l2cc_mutex_boot_pa; static unsigned int *l2cc_mutex; void tee_l2cc_store_mutex_boot_pa(uint32_t pa) { l2cc_mutex_boot_pa = pa; } /* * Allocate public RAM to get a L2CC mutex to shared with NSec. * Return 0 on success. */ static int l2cc_mutex_alloc(void) { void *va; if (l2cc_mutex_va != NULL) return -1; l2cc_mutex_pa = l2cc_mutex_boot_pa; va = phys_to_virt(l2cc_mutex_pa, MEM_AREA_NSEC_SHM, MUTEX_SZ); if (!va) return -1; *(uint32_t *)va = 0; l2cc_mutex_va = va; return 0; } static void l2cc_mutex_set(void *mutex) { l2cc_mutex = (unsigned int *)mutex; } /* * tee_xxx_l2cc_mutex(): Handle L2 mutex configuration requests from NSec * * Policy: * - if NSec did not register a L2 mutex, default allocate it in public RAM. * - if NSec disables L2 mutex, disable the current mutex and unregister it. * * Enable L2CC: NSec allows teecore to run safe outer maintance * with shared mutex. * Disable L2CC: NSec will run outer maintenance with locking * shared mutex. teecore cannot run outer maintenance. * Set L2CC: NSec proposes a Shared Memory locaiotn for the outer * maintenance shared mutex. * Get L2CC: NSec requests the outer maintenance shared mutex * location. If NSec has successufully registered one, * return its location, otherwise, allocated one in NSec * and provided NSec the physical location. */ TEE_Result tee_enable_l2cc_mutex(void) { int ret; if (!l2cc_mutex_va) { ret = l2cc_mutex_alloc(); if (ret) return TEE_ERROR_GENERIC; } l2cc_mutex_set(l2cc_mutex_va); return TEE_SUCCESS; } TEE_Result tee_disable_l2cc_mutex(void) { l2cc_mutex_va = NULL; l2cc_mutex_set(NULL); return TEE_SUCCESS; } TEE_Result tee_get_l2cc_mutex(paddr_t *mutex) { int ret; if (!l2cc_mutex_va) { ret = l2cc_mutex_alloc(); if (ret) return TEE_ERROR_GENERIC; } *mutex = l2cc_mutex_pa; return TEE_SUCCESS; } TEE_Result tee_set_l2cc_mutex(paddr_t *mutex) { uint32_t addr; void *va; if (l2cc_mutex_va != NULL) return TEE_ERROR_BAD_PARAMETERS; addr = *mutex; va = phys_to_virt(addr, MEM_AREA_NSEC_SHM, MUTEX_SZ); if (!va) return TEE_ERROR_BAD_PARAMETERS; l2cc_mutex_pa = addr; l2cc_mutex_va = va; return TEE_SUCCESS; } void tee_l2cc_mutex_lock(void) { if (l2cc_mutex) cpu_spin_lock(l2cc_mutex); } void tee_l2cc_mutex_unlock(void) { if (l2cc_mutex) cpu_spin_unlock(l2cc_mutex); } optee_os-4.3.0/core/arch/arm/kernel/tee_time_arm_cntpct.c000066400000000000000000000031311464416617300234220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, 2015 Linaro Limited */ #include #include #include #include #include #include #include #include #include TEE_Result tee_time_get_sys_time(TEE_Time *time) { uint64_t cntpct = barrier_read_counter_timer(); uint32_t cntfrq = read_cntfrq(); time->seconds = cntpct / cntfrq; time->millis = (cntpct % cntfrq) / (cntfrq / TEE_TIME_MILLIS_BASE); return TEE_SUCCESS; } uint32_t tee_time_get_sys_time_protection_level(void) { return 1000; } /* * We collect jitter using cntpct in 32- or 64-bit mode that is typically * clocked at around 1MHz. * * The first time we are called, we add low 16 bits of the counter as entropy. * * Subsequently, accumulate 2 low bits each time by: * * - rotating the accumumlator by 2 bits * - XORing it in 2-bit chunks with the whole CNTPCT contents * * and adding one byte of entropy when we reach 8 rotated bits. */ void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum) { uint64_t tsc = barrier_read_counter_timer(); int bytes = 0, n; static uint8_t first, bits; static uint16_t acc; if (!first) { acc = tsc; bytes = 2; first = 1; } else { acc = (acc << 2) | ((acc >> 6) & 3); for (n = 0; n < 64; n += 2) acc ^= (tsc >> n) & 3; bits += 2; if (bits >= 8) { bits = 0; bytes = 1; } } if (bytes) { FMSG("0x%02X", (int)acc & ((1 << (bytes * 8)) - 1)); crypto_rng_add_event(sid, pnum, (uint8_t *)&acc, bytes); } } optee_os-4.3.0/core/arch/arm/kernel/thread.c000066400000000000000000000735721464416617300207040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2022, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020-2021, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 static vaddr_t thread_user_kcode_va __nex_bss; long thread_user_kcode_offset __nex_bss; static size_t thread_user_kcode_size __nex_bss; #endif #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \ defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) long thread_user_kdata_sp_offset __nex_bss; static uint8_t thread_user_kdata_page[ ROUNDUP(sizeof(struct thread_core_local) * CFG_TEE_CORE_NB_CORE, SMALL_PAGE_SIZE)] __aligned(SMALL_PAGE_SIZE) #ifndef CFG_NS_VIRTUALIZATION __section(".nozi.kdata_page"); #else __section(".nex_nozi.kdata_page"); #endif #endif #ifdef ARM32 uint32_t __nostackcheck thread_get_exceptions(void) { uint32_t cpsr = read_cpsr(); return (cpsr >> CPSR_F_SHIFT) & THREAD_EXCP_ALL; } void __nostackcheck thread_set_exceptions(uint32_t exceptions) { uint32_t cpsr = read_cpsr(); /* Foreign interrupts must not be unmasked while holding a spinlock */ if (!(exceptions & THREAD_EXCP_FOREIGN_INTR)) assert_have_no_spinlock(); cpsr &= ~(THREAD_EXCP_ALL << CPSR_F_SHIFT); cpsr |= ((exceptions & THREAD_EXCP_ALL) << CPSR_F_SHIFT); barrier(); write_cpsr(cpsr); barrier(); } #endif /*ARM32*/ #ifdef ARM64 uint32_t __nostackcheck thread_get_exceptions(void) { uint32_t daif = read_daif(); return (daif >> DAIF_F_SHIFT) & THREAD_EXCP_ALL; } void __nostackcheck thread_set_exceptions(uint32_t exceptions) { uint32_t daif = read_daif(); /* Foreign interrupts must not be unmasked while holding a spinlock */ if (!(exceptions & THREAD_EXCP_FOREIGN_INTR)) assert_have_no_spinlock(); daif &= ~(THREAD_EXCP_ALL << DAIF_F_SHIFT); daif |= ((exceptions & THREAD_EXCP_ALL) << DAIF_F_SHIFT); barrier(); write_daif(daif); barrier(); } #endif /*ARM64*/ uint32_t __nostackcheck thread_mask_exceptions(uint32_t exceptions) { uint32_t state = thread_get_exceptions(); thread_set_exceptions(state | (exceptions & THREAD_EXCP_ALL)); return state; } void __nostackcheck thread_unmask_exceptions(uint32_t state) { thread_set_exceptions(state & THREAD_EXCP_ALL); } static void thread_lazy_save_ns_vfp(void) { #ifdef CFG_WITH_VFP struct thread_ctx *thr = threads + thread_get_id(); thr->vfp_state.ns_saved = false; vfp_lazy_save_state_init(&thr->vfp_state.ns); #endif /*CFG_WITH_VFP*/ } static void thread_lazy_restore_ns_vfp(void) { #ifdef CFG_WITH_VFP struct thread_ctx *thr = threads + thread_get_id(); struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; assert(!thr->vfp_state.sec_lazy_saved && !thr->vfp_state.sec_saved); if (tuv && tuv->lazy_saved && !tuv->saved) { vfp_lazy_save_state_final(&tuv->vfp, false /*!force_save*/); tuv->saved = true; } vfp_lazy_restore_state(&thr->vfp_state.ns, thr->vfp_state.ns_saved); thr->vfp_state.ns_saved = false; #endif /*CFG_WITH_VFP*/ } #ifdef ARM32 static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7, void *pc) { thread->regs.pc = (uint32_t)pc; /* * Stdcalls starts in SVC mode with masked foreign interrupts, masked * Asynchronous abort and unmasked native interrupts. */ thread->regs.cpsr = read_cpsr() & ARM32_CPSR_E; thread->regs.cpsr |= CPSR_MODE_SVC | CPSR_A | (THREAD_EXCP_FOREIGN_INTR << ARM32_CPSR_F_SHIFT); /* Enable thumb mode if it's a thumb instruction */ if (thread->regs.pc & 1) thread->regs.cpsr |= CPSR_T; /* Reinitialize stack pointer */ thread->regs.svc_sp = thread->stack_va_end; /* * Copy arguments into context. This will make the * arguments appear in r0-r7 when thread is started. */ thread->regs.r0 = a0; thread->regs.r1 = a1; thread->regs.r2 = a2; thread->regs.r3 = a3; thread->regs.r4 = a4; thread->regs.r5 = a5; thread->regs.r6 = a6; thread->regs.r7 = a7; } #endif /*ARM32*/ #ifdef ARM64 static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7, void *pc) { thread->regs.pc = (uint64_t)pc; /* * Stdcalls starts in SVC mode with masked foreign interrupts, masked * Asynchronous abort and unmasked native interrupts. */ thread->regs.cpsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, THREAD_EXCP_FOREIGN_INTR | DAIFBIT_ABT); /* Reinitialize stack pointer */ thread->regs.sp = thread->stack_va_end; /* * Copy arguments into context. This will make the * arguments appear in x0-x7 when thread is started. */ thread->regs.x[0] = a0; thread->regs.x[1] = a1; thread->regs.x[2] = a2; thread->regs.x[3] = a3; thread->regs.x[4] = a4; thread->regs.x[5] = a5; thread->regs.x[6] = a6; thread->regs.x[7] = a7; /* Set up frame pointer as per the Aarch64 AAPCS */ thread->regs.x[29] = 0; } #endif /*ARM64*/ static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7, void *pc, uint32_t flags) { struct thread_core_local *l = thread_get_core_local(); bool found_thread = false; size_t n = 0; assert(l->curr_thread == THREAD_ID_INVALID); thread_lock_global(); for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].state == THREAD_STATE_FREE) { threads[n].state = THREAD_STATE_ACTIVE; found_thread = true; break; } } thread_unlock_global(); if (!found_thread) return; l->curr_thread = n; threads[n].flags = flags; init_regs(threads + n, a0, a1, a2, a3, a4, a5, a6, a7, pc); #ifdef CFG_CORE_PAUTH /* * Copy the APIA key into the registers to be restored with * thread_resume(). */ threads[n].regs.apiakey_hi = threads[n].keys.apia_hi; threads[n].regs.apiakey_lo = threads[n].keys.apia_lo; #endif thread_lazy_save_ns_vfp(); l->flags &= ~THREAD_CLF_TMP; thread_resume(&threads[n].regs); /*NOTREACHED*/ panic(); } void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { __thread_alloc_and_run(a0, a1, a2, a3, a4, a5, 0, 0, thread_std_smc_entry, 0); } #ifdef CFG_SECURE_PARTITION void thread_sp_alloc_and_run(struct thread_smc_args *args __maybe_unused) { __thread_alloc_and_run(args->a0, args->a1, args->a2, args->a3, args->a4, args->a5, args->a6, args->a7, spmc_sp_thread_entry, THREAD_FLAGS_FFA_ONLY); } #endif #ifdef ARM32 static void copy_a0_to_a3(struct thread_ctx_regs *regs, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) { /* * Update returned values from RPC, values will appear in * r0-r3 when thread is resumed. */ regs->r0 = a0; regs->r1 = a1; regs->r2 = a2; regs->r3 = a3; } #endif /*ARM32*/ #ifdef ARM64 static void copy_a0_to_a3(struct thread_ctx_regs *regs, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) { /* * Update returned values from RPC, values will appear in * x0-x3 when thread is resumed. */ regs->x[0] = a0; regs->x[1] = a1; regs->x[2] = a2; regs->x[3] = a3; } #endif /*ARM64*/ #ifdef ARM32 static bool is_from_user(uint32_t cpsr) { return (cpsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR; } #endif #ifdef ARM64 static bool is_from_user(uint32_t cpsr) { if (cpsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT)) return true; if (((cpsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) == SPSR_64_MODE_EL0) return true; return false; } #endif #ifdef CFG_SYSCALL_FTRACE static void __noprof ftrace_suspend(void) { struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); if (s && s->fbuf) s->fbuf->syscall_trace_suspended = true; } static void __noprof ftrace_resume(void) { struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); if (s && s->fbuf) s->fbuf->syscall_trace_suspended = false; } #else static void __noprof ftrace_suspend(void) { } static void __noprof ftrace_resume(void) { } #endif static bool is_user_mode(struct thread_ctx_regs *regs) { return is_from_user((uint32_t)regs->cpsr); } void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) { size_t n = thread_id; struct thread_core_local *l = thread_get_core_local(); bool found_thread = false; assert(l->curr_thread == THREAD_ID_INVALID); thread_lock_global(); if (n < CFG_NUM_THREADS && threads[n].state == THREAD_STATE_SUSPENDED) { threads[n].state = THREAD_STATE_ACTIVE; found_thread = true; } thread_unlock_global(); if (!found_thread) return; l->curr_thread = n; if (threads[n].have_user_map) { core_mmu_set_user_map(&threads[n].user_map); if (threads[n].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) tee_ta_ftrace_update_times_resume(); } if (is_user_mode(&threads[n].regs)) tee_ta_update_session_utime_resume(); /* * Return from RPC to request service of a foreign interrupt must not * get parameters from non-secure world. */ if (threads[n].flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN) { copy_a0_to_a3(&threads[n].regs, a0, a1, a2, a3); threads[n].flags &= ~THREAD_FLAGS_COPY_ARGS_ON_RETURN; } thread_lazy_save_ns_vfp(); if (threads[n].have_user_map) ftrace_resume(); l->flags &= ~THREAD_CLF_TMP; thread_resume(&threads[n].regs); /*NOTREACHED*/ panic(); } #ifdef ARM64 static uint64_t spsr_from_pstate(void) { uint64_t spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, 0); spsr |= read_daif(); if (IS_ENABLED(CFG_PAN) && feat_pan_implemented() && read_pan()) spsr |= SPSR_64_PAN; return spsr; } void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) { thread_rpc_spsr(rv, spsr_from_pstate()); } vaddr_t thread_get_saved_thread_sp(void) { struct thread_core_local *l = thread_get_core_local(); int ct = l->curr_thread; assert(ct != THREAD_ID_INVALID); return threads[ct].kern_sp; } #endif /*ARM64*/ #ifdef ARM32 bool thread_is_in_normal_mode(void) { return (read_cpsr() & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_SVC; } #endif void thread_state_free(void) { struct thread_core_local *l = thread_get_core_local(); int ct = l->curr_thread; assert(ct != THREAD_ID_INVALID); thread_lazy_restore_ns_vfp(); tee_pager_release_phys( (void *)(threads[ct].stack_va_end - STACK_THREAD_SIZE), STACK_THREAD_SIZE); thread_lock_global(); assert(threads[ct].state == THREAD_STATE_ACTIVE); threads[ct].state = THREAD_STATE_FREE; threads[ct].flags = 0; l->curr_thread = THREAD_ID_INVALID; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); thread_unlock_global(); } #ifdef CFG_WITH_PAGER static void release_unused_kernel_stack(struct thread_ctx *thr, uint32_t cpsr __maybe_unused) { #ifdef ARM64 /* * If we're from user mode then thr->regs.sp is the saved user * stack pointer and thr->kern_sp holds the last kernel stack * pointer. But if we're from kernel mode then thr->kern_sp isn't * up to date so we need to read from thr->regs.sp instead. */ vaddr_t sp = is_from_user(cpsr) ? thr->kern_sp : thr->regs.sp; #else vaddr_t sp = thr->regs.svc_sp; #endif vaddr_t base = thr->stack_va_end - STACK_THREAD_SIZE; size_t len = sp - base; tee_pager_release_phys((void *)base, len); } #else static void release_unused_kernel_stack(struct thread_ctx *thr __unused, uint32_t cpsr __unused) { } #endif int thread_state_suspend(uint32_t flags, uint32_t cpsr, vaddr_t pc) { struct thread_core_local *l = thread_get_core_local(); int ct = l->curr_thread; assert(ct != THREAD_ID_INVALID); if (core_mmu_user_mapping_is_active()) ftrace_suspend(); thread_check_canaries(); release_unused_kernel_stack(threads + ct, cpsr); if (is_from_user(cpsr)) { thread_user_save_vfp(); tee_ta_update_session_utime_suspend(); tee_ta_gprof_sample_pc(pc); } thread_lazy_restore_ns_vfp(); thread_lock_global(); assert(threads[ct].state == THREAD_STATE_ACTIVE); threads[ct].flags |= flags; threads[ct].regs.cpsr = cpsr; threads[ct].regs.pc = pc; threads[ct].state = THREAD_STATE_SUSPENDED; threads[ct].have_user_map = core_mmu_user_mapping_is_active(); if (threads[ct].have_user_map) { if (threads[ct].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) tee_ta_ftrace_update_times_suspend(); core_mmu_get_user_map(&threads[ct].user_map); core_mmu_set_user_map(NULL); } if (IS_ENABLED(CFG_SECURE_PARTITION)) { struct ts_session *ts_sess = TAILQ_FIRST(&threads[ct].tsd.sess_stack); spmc_sp_set_to_preempted(ts_sess); } l->curr_thread = THREAD_ID_INVALID; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); thread_unlock_global(); return ct; } bool thread_init_stack(uint32_t thread_id, vaddr_t sp) { if (thread_id >= CFG_NUM_THREADS) return false; threads[thread_id].stack_va_end = sp; return true; } static void __maybe_unused set_core_local_kcode_offset(struct thread_core_local *cls, long offset) { size_t n = 0; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) cls[n].kcode_offset = offset; } static void init_user_kcode(void) { #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 vaddr_t v = (vaddr_t)thread_excp_vect; vaddr_t ve = (vaddr_t)thread_excp_vect_end; thread_user_kcode_va = ROUNDDOWN(v, CORE_MMU_USER_CODE_SIZE); ve = ROUNDUP(ve, CORE_MMU_USER_CODE_SIZE); thread_user_kcode_size = ve - thread_user_kcode_va; core_mmu_get_user_va_range(&v, NULL); thread_user_kcode_offset = thread_user_kcode_va - v; set_core_local_kcode_offset(thread_core_local, thread_user_kcode_offset); #if defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) set_core_local_kcode_offset((void *)thread_user_kdata_page, thread_user_kcode_offset); /* * When transitioning to EL0 subtract SP with this much to point to * this special kdata page instead. SP is restored by add this much * while transitioning back to EL1. */ v += thread_user_kcode_size; thread_user_kdata_sp_offset = (vaddr_t)thread_core_local - v; #endif #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ } void thread_init_primary(void) { /* Initialize canaries around the stacks */ thread_init_canaries(); init_user_kcode(); } static uint32_t __maybe_unused get_midr_implementer(uint32_t midr) { return (midr >> MIDR_IMPLEMENTER_SHIFT) & MIDR_IMPLEMENTER_MASK; } static uint32_t __maybe_unused get_midr_primary_part(uint32_t midr) { return (midr >> MIDR_PRIMARY_PART_NUM_SHIFT) & MIDR_PRIMARY_PART_NUM_MASK; } static uint32_t __maybe_unused get_midr_variant(uint32_t midr) { return (midr >> MIDR_VARIANT_SHIFT) & MIDR_VARIANT_MASK; } static uint32_t __maybe_unused get_midr_revision(uint32_t midr) { return (midr >> MIDR_REVISION_SHIFT) & MIDR_REVISION_MASK; } #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC #ifdef ARM64 static bool probe_workaround_available(uint32_t wa_id) { int32_t r; r = thread_smc(SMCCC_VERSION, 0, 0, 0); if (r < 0) return false; if (r < 0x10001) /* compare with version 1.1 */ return false; /* Version >= 1.1, so SMCCC_ARCH_FEATURES is available */ r = thread_smc(SMCCC_ARCH_FEATURES, wa_id, 0, 0); return r >= 0; } static vaddr_t __maybe_unused select_vector_wa_spectre_v2(void) { if (probe_workaround_available(SMCCC_ARCH_WORKAROUND_1)) { DMSG("SMCCC_ARCH_WORKAROUND_1 (%#08" PRIx32 ") available", SMCCC_ARCH_WORKAROUND_1); DMSG("SMC Workaround for CVE-2017-5715 used"); return (vaddr_t)thread_excp_vect_wa_spectre_v2; } DMSG("SMCCC_ARCH_WORKAROUND_1 (%#08" PRIx32 ") unavailable", SMCCC_ARCH_WORKAROUND_1); DMSG("SMC Workaround for CVE-2017-5715 not needed (if ARM-TF is up to date)"); return (vaddr_t)thread_excp_vect; } #else static vaddr_t __maybe_unused select_vector_wa_spectre_v2(void) { return (vaddr_t)thread_excp_vect_wa_spectre_v2; } #endif #endif #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC static vaddr_t select_vector_wa_spectre_bhb(uint8_t loop_count __maybe_unused) { /* * Spectre-BHB has only been analyzed for AArch64 so far. For * AArch32 fall back to the Spectre-V2 workaround which is likely * to work even if perhaps a bit more expensive than a more * optimized workaround. */ #ifdef ARM64 #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 struct thread_core_local *cl = (void *)thread_user_kdata_page; cl[get_core_pos()].bhb_loop_count = loop_count; #endif thread_get_core_local()->bhb_loop_count = loop_count; DMSG("Spectre-BHB CVE-2022-23960 workaround enabled with \"K\" = %u", loop_count); return (vaddr_t)thread_excp_vect_wa_spectre_bhb; #else return select_vector_wa_spectre_v2(); #endif } #endif static vaddr_t get_excp_vect(void) { #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC uint32_t midr = read_midr(); uint8_t vers = 0; if (get_midr_implementer(midr) != MIDR_IMPLEMENTER_ARM) return (vaddr_t)thread_excp_vect; /* * Variant rx, Revision py, for instance * Variant 2 Revision 0 = r2p0 = 0x20 */ vers = (get_midr_variant(midr) << 4) | get_midr_revision(midr); /* * Spectre-V2 (CVE-2017-5715) software workarounds covers what's * needed for Spectre-BHB (CVE-2022-23960) too. The workaround for * Spectre-V2 is more expensive than the one for Spectre-BHB so if * possible select the workaround for Spectre-BHB. */ switch (get_midr_primary_part(midr)) { #ifdef ARM32 /* Spectre-V2 */ case CORTEX_A8_PART_NUM: case CORTEX_A9_PART_NUM: case CORTEX_A17_PART_NUM: #endif /* Spectre-V2 */ case CORTEX_A57_PART_NUM: case CORTEX_A73_PART_NUM: case CORTEX_A75_PART_NUM: return select_vector_wa_spectre_v2(); #ifdef ARM32 /* Spectre-V2 */ case CORTEX_A15_PART_NUM: return (vaddr_t)thread_excp_vect_wa_a15_spectre_v2; #endif /* * Spectre-V2 for vers < r1p0 * Spectre-BHB for vers >= r1p0 */ case CORTEX_A72_PART_NUM: if (vers < 0x10) return select_vector_wa_spectre_v2(); return select_vector_wa_spectre_bhb(8); /* * Doing the more safe but expensive Spectre-V2 workaround for CPUs * still being researched on the best mitigation sequence. */ case CORTEX_A65_PART_NUM: case CORTEX_A65AE_PART_NUM: case NEOVERSE_E1_PART_NUM: return select_vector_wa_spectre_v2(); /* Spectre-BHB */ case CORTEX_A76_PART_NUM: case CORTEX_A76AE_PART_NUM: case CORTEX_A77_PART_NUM: return select_vector_wa_spectre_bhb(24); case CORTEX_A78_PART_NUM: case CORTEX_A78AE_PART_NUM: case CORTEX_A78C_PART_NUM: case CORTEX_A710_PART_NUM: case CORTEX_X1_PART_NUM: case CORTEX_X2_PART_NUM: return select_vector_wa_spectre_bhb(32); case NEOVERSE_N1_PART_NUM: return select_vector_wa_spectre_bhb(24); case NEOVERSE_N2_PART_NUM: case NEOVERSE_V1_PART_NUM: return select_vector_wa_spectre_bhb(32); default: return (vaddr_t)thread_excp_vect; } #endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ return (vaddr_t)thread_excp_vect; } void thread_init_per_cpu(void) { #ifdef ARM32 struct thread_core_local *l = thread_get_core_local(); #if !defined(CFG_WITH_ARM_TRUSTED_FW) /* Initialize secure monitor */ sm_init(l->tmp_stack_va_end + STACK_TMP_OFFS); #endif thread_set_irq_sp(l->tmp_stack_va_end); thread_set_fiq_sp(l->tmp_stack_va_end); thread_set_abt_sp((vaddr_t)l); thread_set_und_sp((vaddr_t)l); #endif thread_init_vbar(get_excp_vect()); #ifdef CFG_FTRACE_SUPPORT /* * Enable accesses to frequency register and physical counter * register in EL0/PL0 required for timestamping during * function tracing. */ write_cntkctl(read_cntkctl() | CNTKCTL_PL0PCTEN); #endif } #ifdef CFG_WITH_VFP uint32_t thread_kernel_enable_vfp(void) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); struct thread_ctx *thr = threads + thread_get_id(); struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; assert(!vfp_is_enabled()); if (!thr->vfp_state.ns_saved) { vfp_lazy_save_state_final(&thr->vfp_state.ns, true /*force_save*/); thr->vfp_state.ns_saved = true; } else if (thr->vfp_state.sec_lazy_saved && !thr->vfp_state.sec_saved) { /* * This happens when we're handling an abort while the * thread was using the VFP state. */ vfp_lazy_save_state_final(&thr->vfp_state.sec, false /*!force_save*/); thr->vfp_state.sec_saved = true; } else if (tuv && tuv->lazy_saved && !tuv->saved) { /* * This can happen either during syscall or abort * processing (while processing a syscall). */ vfp_lazy_save_state_final(&tuv->vfp, false /*!force_save*/); tuv->saved = true; } vfp_enable(); return exceptions; } void thread_kernel_disable_vfp(uint32_t state) { uint32_t exceptions; assert(vfp_is_enabled()); vfp_disable(); exceptions = thread_get_exceptions(); assert(exceptions & THREAD_EXCP_FOREIGN_INTR); exceptions &= ~THREAD_EXCP_FOREIGN_INTR; exceptions |= state & THREAD_EXCP_FOREIGN_INTR; thread_set_exceptions(exceptions); } void thread_kernel_save_vfp(void) { struct thread_ctx *thr = threads + thread_get_id(); assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); if (vfp_is_enabled()) { vfp_lazy_save_state_init(&thr->vfp_state.sec); thr->vfp_state.sec_lazy_saved = true; } } void thread_kernel_restore_vfp(void) { struct thread_ctx *thr = threads + thread_get_id(); assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); assert(!vfp_is_enabled()); if (thr->vfp_state.sec_lazy_saved) { vfp_lazy_restore_state(&thr->vfp_state.sec, thr->vfp_state.sec_saved); thr->vfp_state.sec_saved = false; thr->vfp_state.sec_lazy_saved = false; } } void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp) { struct thread_ctx *thr = threads + thread_get_id(); struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); assert(!vfp_is_enabled()); if (!thr->vfp_state.ns_saved) { vfp_lazy_save_state_final(&thr->vfp_state.ns, true /*force_save*/); thr->vfp_state.ns_saved = true; } else if (tuv && uvfp != tuv) { if (tuv->lazy_saved && !tuv->saved) { vfp_lazy_save_state_final(&tuv->vfp, false /*!force_save*/); tuv->saved = true; } } if (uvfp->lazy_saved) vfp_lazy_restore_state(&uvfp->vfp, uvfp->saved); uvfp->lazy_saved = false; uvfp->saved = false; thr->vfp_state.uvfp = uvfp; vfp_enable(); } void thread_user_save_vfp(void) { struct thread_ctx *thr = threads + thread_get_id(); struct thread_user_vfp_state *tuv = thr->vfp_state.uvfp; assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); if (!vfp_is_enabled()) return; assert(tuv && !tuv->lazy_saved && !tuv->saved); vfp_lazy_save_state_init(&tuv->vfp); tuv->lazy_saved = true; } void thread_user_clear_vfp(struct user_mode_ctx *uctx) { struct thread_user_vfp_state *uvfp = &uctx->vfp; struct thread_ctx *thr = threads + thread_get_id(); if (uvfp == thr->vfp_state.uvfp) thr->vfp_state.uvfp = NULL; uvfp->lazy_saved = false; uvfp->saved = false; } #endif /*CFG_WITH_VFP*/ #ifdef ARM32 static bool get_spsr(bool is_32bit, unsigned long entry_func, uint32_t *spsr) { uint32_t s; if (!is_32bit) return false; s = read_cpsr(); s &= ~(CPSR_MODE_MASK | CPSR_T | CPSR_IT_MASK1 | CPSR_IT_MASK2); s |= CPSR_MODE_USR; if (entry_func & 1) s |= CPSR_T; *spsr = s; return true; } #endif #ifdef ARM64 static bool get_spsr(bool is_32bit, unsigned long entry_func, uint32_t *spsr) { uint32_t s; if (is_32bit) { s = read_daif() & (SPSR_32_AIF_MASK << SPSR_32_AIF_SHIFT); s |= SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT; s |= (entry_func & SPSR_32_T_MASK) << SPSR_32_T_SHIFT; } else { s = read_daif() & (SPSR_64_DAIF_MASK << SPSR_64_DAIF_SHIFT); } *spsr = s; return true; } #endif static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, uint32_t spsr, struct thread_pauth_keys *keys __maybe_unused) { /* * First clear all registers to avoid leaking information from * other TAs or even the Core itself. */ *regs = (struct thread_ctx_regs){ }; #ifdef ARM32 regs->r0 = a0; regs->r1 = a1; regs->r2 = a2; regs->r3 = a3; regs->usr_sp = user_sp; regs->pc = entry_func; regs->cpsr = spsr; #endif #ifdef ARM64 regs->x[0] = a0; regs->x[1] = a1; regs->x[2] = a2; regs->x[3] = a3; regs->sp = user_sp; regs->pc = entry_func; regs->cpsr = spsr; regs->x[13] = user_sp; /* Used when running TA in Aarch32 */ regs->sp = user_sp; /* Used when running TA in Aarch64 */ #ifdef CFG_TA_PAUTH assert(keys); regs->apiakey_hi = keys->apia_hi; regs->apiakey_lo = keys->apia_lo; #endif /* Set frame pointer (user stack can't be unwound past this point) */ regs->x[29] = 0; #endif } static struct thread_pauth_keys *thread_get_pauth_keys(void) { #if defined(CFG_TA_PAUTH) struct ts_session *s = ts_get_current_session(); /* Only user TA's support the PAUTH keys */ struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); return &utc->uctx.keys; #else return NULL; #endif } uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, bool is_32bit, uint32_t *exit_status0, uint32_t *exit_status1) { uint32_t spsr = 0; uint32_t exceptions = 0; uint32_t rc = 0; struct thread_ctx_regs *regs = NULL; struct thread_pauth_keys *keys = NULL; tee_ta_update_session_utime_resume(); keys = thread_get_pauth_keys(); /* Derive SPSR from current CPSR/PSTATE readout. */ if (!get_spsr(is_32bit, entry_func, &spsr)) { *exit_status0 = 1; /* panic */ *exit_status1 = 0xbadbadba; return 0; } exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); /* * We're using the per thread location of saved context registers * for temporary storage. Now that exceptions are masked they will * not be used for any thing else until they are eventually * unmasked when user mode has been entered. */ regs = thread_get_ctx_regs(); set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, spsr, keys); rc = __thread_enter_user_mode(regs, exit_status0, exit_status1); thread_unmask_exceptions(exceptions); return rc; } #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 void thread_get_user_kcode(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz) { core_mmu_get_user_va_range(va, NULL); *mobj = mobj_tee_ram_rx; *sz = thread_user_kcode_size; *offset = thread_user_kcode_va - (vaddr_t)mobj_get_va(*mobj, 0, *sz); } #endif #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) && \ defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) && defined(ARM64) void thread_get_user_kdata(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz) { vaddr_t v; core_mmu_get_user_va_range(&v, NULL); *va = v + thread_user_kcode_size; *mobj = mobj_tee_ram_rw; *sz = sizeof(thread_user_kdata_page); *offset = (vaddr_t)thread_user_kdata_page - (vaddr_t)mobj_get_va(*mobj, 0, *sz); } #endif static void setup_unwind_user_mode(struct thread_scall_regs *regs) { #ifdef ARM32 regs->lr = (uintptr_t)thread_unwind_user_mode; regs->spsr = read_cpsr(); #endif #ifdef ARM64 regs->elr = (uintptr_t)thread_unwind_user_mode; regs->spsr = spsr_from_pstate(); /* * Regs is the value of stack pointer before calling the SVC * handler. By the addition matches for the reserved space at the * beginning of el0_sync_svc(). This prepares the stack when * returning to thread_unwind_user_mode instead of a normal * exception return. */ regs->sp_el0 = (uint64_t)(regs + 1); #endif } static void gprof_set_status(struct ts_session *s __maybe_unused, enum ts_gprof_status status __maybe_unused) { #ifdef CFG_TA_GPROF_SUPPORT if (s->ctx->ops->gprof_set_status) s->ctx->ops->gprof_set_status(status); #endif } /* * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ void __weak thread_scall_handler(struct thread_scall_regs *regs) { struct ts_session *sess = NULL; uint32_t state = 0; /* Enable native interrupts */ state = thread_get_exceptions(); thread_unmask_exceptions(state & ~THREAD_EXCP_NATIVE_INTR); thread_user_save_vfp(); sess = ts_get_current_session(); /* * User mode service has just entered kernel mode, suspend gprof * collection until we're about to switch back again. */ gprof_set_status(sess, TS_GPROF_SUSPEND); /* Restore foreign interrupts which are disabled on exception entry */ thread_restore_foreign_intr(); assert(sess && sess->handle_scall); if (sess->handle_scall(regs)) { /* We're about to switch back to user mode */ gprof_set_status(sess, TS_GPROF_RESUME); } else { /* We're returning from __thread_enter_user_mode() */ setup_unwind_user_mode(regs); } } #ifdef CFG_WITH_ARM_TRUSTED_FW /* * These five functions are __weak to allow platforms to override them if * needed. */ unsigned long __weak thread_cpu_off_handler(unsigned long a0 __unused, unsigned long a1 __unused) { return 0; } DECLARE_KEEP_PAGER(thread_cpu_off_handler); unsigned long __weak thread_cpu_suspend_handler(unsigned long a0 __unused, unsigned long a1 __unused) { return 0; } DECLARE_KEEP_PAGER(thread_cpu_suspend_handler); unsigned long __weak thread_cpu_resume_handler(unsigned long a0 __unused, unsigned long a1 __unused) { return 0; } DECLARE_KEEP_PAGER(thread_cpu_resume_handler); unsigned long __weak thread_system_off_handler(unsigned long a0 __unused, unsigned long a1 __unused) { return 0; } DECLARE_KEEP_PAGER(thread_system_off_handler); unsigned long __weak thread_system_reset_handler(unsigned long a0 __unused, unsigned long a1 __unused) { return 0; } DECLARE_KEEP_PAGER(thread_system_reset_handler); #endif /*CFG_WITH_ARM_TRUSTED_FW*/ #ifdef CFG_CORE_WORKAROUND_ARM_NMFI void __noreturn interrupt_main_handler(void) { /* * Note: overrides the default implementation of this function so that * if there would be another handler defined there would be duplicate * symbol error during linking. */ panic("Secure interrupt received but it is not supported"); } #endif optee_os-4.3.0/core/arch/arm/kernel/thread_a32.S000066400000000000000000000555751464416617300213340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2020, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include .syntax unified .arch_extension sec .macro cmp_spsr_user_mode reg:req /* * We're only testing the lower 4 bits as bit 5 (0x10) * always is set. */ tst \reg, #0x0f .endm FUNC thread_set_abt_sp , : UNWIND( .cantunwind) mrs r1, cpsr cps #CPSR_MODE_ABT mov sp, r0 msr cpsr, r1 bx lr END_FUNC thread_set_abt_sp FUNC thread_set_und_sp , : UNWIND( .cantunwind) mrs r1, cpsr cps #CPSR_MODE_UND mov sp, r0 msr cpsr, r1 bx lr END_FUNC thread_set_und_sp FUNC thread_set_irq_sp , : UNWIND( .cantunwind) mrs r1, cpsr cps #CPSR_MODE_IRQ mov sp, r0 msr cpsr, r1 bx lr END_FUNC thread_set_irq_sp FUNC thread_set_fiq_sp , : UNWIND( .cantunwind) mrs r1, cpsr cps #CPSR_MODE_FIQ mov sp, r0 msr cpsr, r1 bx lr END_FUNC thread_set_fiq_sp FUNC thread_get_usr_sp , : mrs r1, cpsr cpsid aif cps #CPSR_MODE_SYS mov r0, sp msr cpsr, r1 bx lr END_FUNC thread_get_usr_sp FUNC thread_get_usr_lr , : mrs r1, cpsr cpsid aif cps #CPSR_MODE_SYS mov r0, lr msr cpsr, r1 bx lr END_FUNC thread_get_usr_lr FUNC thread_set_usr_lr , : mrs r1, cpsr cpsid aif cps #CPSR_MODE_SYS mov lr, r0 msr cpsr, r1 bx lr END_FUNC thread_set_usr_lr /* void thread_resume(struct thread_ctx_regs *regs) */ FUNC thread_resume , : UNWIND( .cantunwind) add r12, r0, #(13 * 4) /* Restore registers r0-r12 later */ cps #CPSR_MODE_SYS ldr sp, [r12], #4 ldr lr, [r12], #4 cps #CPSR_MODE_SVC ldr r1, [r12], #4 ldr sp, [r12], #4 ldr lr, [r12], #4 msr spsr_fsxc, r1 ldm r12, {r1, r2} /* * Switching to some other mode than SVC as we need to set spsr in * order to return into the old state properly and it may be SVC * mode we're returning to. */ cps #CPSR_MODE_ABT cmp_spsr_user_mode r2 mov lr, r1 msr spsr_fsxc, r2 ldm r0, {r0-r12} movsne pc, lr b eret_to_user_mode END_FUNC thread_resume /* * Disables IRQ and FIQ and saves state of thread in fiq mode which has * the banked r8-r12 registers, returns original CPSR. */ LOCAL_FUNC thread_save_state_fiq , : UNWIND( .cantunwind) mov r9, lr /* * Uses stack for temporary storage, while storing needed * context in the thread context struct. */ mrs r8, cpsr cpsid aif /* Disable Async abort, IRQ and FIQ */ push {r4-r7} push {r0-r3} mrs r6, cpsr /* Save current CPSR */ bl thread_get_ctx_regs pop {r1-r4} /* r0-r3 pushed above */ stm r0!, {r1-r4} pop {r1-r4} /* r4-r7 pushed above */ stm r0!, {r1-r4} cps #CPSR_MODE_SYS stm r0!, {r8-r12} str sp, [r0], #4 str lr, [r0], #4 cps #CPSR_MODE_SVC mrs r1, spsr str r1, [r0], #4 str sp, [r0], #4 str lr, [r0], #4 /* back to fiq mode */ orr r6, r6, #ARM32_CPSR_FIA /* Disable Async abort, IRQ and FIQ */ msr cpsr, r6 /* Restore mode */ mov r0, r8 /* Return original CPSR */ bx r9 END_FUNC thread_save_state_fiq /* * Disables IRQ and FIQ and saves state of thread, returns original * CPSR. */ FUNC thread_save_state , : UNWIND( .cantunwind) push {r12, lr} /* * Uses stack for temporary storage, while storing needed * context in the thread context struct. */ mrs r12, cpsr cpsid aif /* Disable Async abort, IRQ and FIQ */ push {r4-r7} push {r0-r3} mov r5, r12 /* Save CPSR in a preserved register */ mrs r6, cpsr /* Save current CPSR */ bl thread_get_ctx_regs pop {r1-r4} /* r0-r3 pushed above */ stm r0!, {r1-r4} pop {r1-r4} /* r4-r7 pushed above */ stm r0!, {r1-r4} stm r0!, {r8-r11} pop {r12, lr} stm r0!, {r12} cps #CPSR_MODE_SYS str sp, [r0], #4 str lr, [r0], #4 cps #CPSR_MODE_SVC mrs r1, spsr str r1, [r0], #4 str sp, [r0], #4 str lr, [r0], #4 orr r6, r6, #ARM32_CPSR_FIA /* Disable Async abort, IRQ and FIQ */ msr cpsr, r6 /* Restore mode */ mov r0, r5 /* Return original CPSR */ bx lr END_FUNC thread_save_state #ifdef CFG_CORE_SEL2_SPMC /* * unsigned long thread_hvc(unsigned long func_id, unsigned long a1, * unsigned long a2, unsigned long a3) */ FUNC thread_hvc , : push {r4-r7} UNWIND( .save {r4-r7}) hvc #0 pop {r4-r7} bx lr END_FUNC thread_hvc #endif /*CFG_CORE_SEL2_SPMC*/ /* * unsigned long thread_smc(unsigned long func_id, unsigned long a1, * unsigned long a2, unsigned long a3) */ FUNC thread_smc , : push {r4-r7} UNWIND( .save {r4-r7}) smc #0 pop {r4-r7} bx lr END_FUNC thread_smc /* void thread_smccc(struct thread_smc_args *arg_res) */ FUNC thread_smccc , : push {r4-r7} push {r0, lr} ldm r0, {r0-r7} #ifdef CFG_CORE_SEL2_SPMC hvc #0 #else smc #0 #endif pop {r12, lr} stm r12, {r0-r7} pop {r4-r7} bx lr END_FUNC thread_smccc FUNC thread_init_vbar , : /* Set vector (VBAR) */ write_vbar r0 bx lr END_FUNC thread_init_vbar DECLARE_KEEP_PAGER thread_init_vbar /* * Below are low level routines handling entry and return from user mode. * * thread_enter_user_mode() saves all that registers user mode can change * so kernel mode can restore needed registers when resuming execution * after the call to thread_enter_user_mode() has returned. * thread_enter_user_mode() doesn't return directly since it enters user * mode instead, it's thread_unwind_user_mode() that does the * returning by restoring the registers saved by thread_enter_user_mode(). * * There's three ways for thread_enter_user_mode() to return to caller, * user TA calls _utee_return, user TA calls _utee_panic or through an abort. * * Calls to _utee_return or _utee_panic are handled as: * __thread_svc_handler() -> thread_scall_handler() -> scall_do_call() which * calls syscall_return() or syscall_panic(). * * These function calls returns normally except thread_scall_handler() which * which is an exception handling routine so it reads return address and * SPSR to restore from the stack. syscall_return() and syscall_panic() * changes return address and SPSR used by thread_scall_handler() to instead of * returning into user mode as with other syscalls it returns into * thread_unwind_user_mode() in kernel mode instead. When * thread_scall_handler() returns the stack pointer at the point where * thread_enter_user_mode() left it so this is where * thread_unwind_user_mode() can operate. * * Aborts are handled in a similar way but by thread_abort_handler() * instead, when the pager sees that it's an abort from user mode that * can't be handled it updates SPSR and return address used by * thread_abort_handler() to return into thread_unwind_user_mode() * instead. */ /* * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, * uint32_t *exit_status0, * uint32_t *exit_status1); * * This function depends on being called with exceptions masked. */ FUNC __thread_enter_user_mode , : UNWIND( .cantunwind) /* * Save all registers to allow syscall_return() to resume execution * as if this function would have returned. This is also used in * syscall_panic(). * * If stack usage of this function is changed * thread_unwind_user_mode() has to be updated. */ push {r4-r12,lr} /* * Save old user sp and set new user sp. */ cps #CPSR_MODE_SYS mov r4, sp ldr sp, [r0, #THREAD_CTX_REGS_USR_SP] cps #CPSR_MODE_SVC push {r1, r2, r4, r5} /* Prepare user mode entry via eret_to_user_mode */ ldr lr, [r0, #THREAD_CTX_REGS_PC] ldr r4, [r0, #THREAD_CTX_REGS_CPSR] msr spsr_fsxc, r4 ldm r0, {r0-r12} b eret_to_user_mode END_FUNC __thread_enter_user_mode /* * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, * uint32_t exit_status1); * See description in thread.h */ FUNC thread_unwind_user_mode , : UNWIND( .cantunwind) /* Match push {r1, r2, r4, r5} in thread_enter_user_mode() */ pop {r4-r7} str r1, [r4] str r2, [r5] /* Restore old user sp */ cps #CPSR_MODE_SYS mov sp, r6 cps #CPSR_MODE_SVC /* Match push {r4-r12,lr} in thread_enter_user_mode() */ pop {r4-r12,pc} END_FUNC thread_unwind_user_mode .macro maybe_restore_mapping /* * This macro is a bit hard to read due to all the ifdefs, * we're testing for two different configs which makes four * different combinations. * * - With LPAE, and then some extra code if with * CFG_CORE_UNMAP_CORE_AT_EL0 * - Without LPAE, and then some extra code if with * CFG_CORE_UNMAP_CORE_AT_EL0 */ /* * At this point we can't rely on any memory being writable * yet, so we're using TPIDRPRW to store r0, and if with * LPAE TPIDRURO to store r1 too. */ write_tpidrprw r0 #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) write_tpidruro r1 #endif #ifdef CFG_WITH_LPAE read_ttbr0_64bit r0, r1 tst r1, #BIT(TTBR_ASID_SHIFT - 32) beq 11f #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 /* * Update the mapping to use the full kernel mode mapping. * Since the translation table could reside above 4GB we'll * have to use 64-bit arithmetics. */ subs r0, r0, #CORE_MMU_BASE_TABLE_OFFSET sbc r1, r1, #0 #endif bic r1, r1, #BIT(TTBR_ASID_SHIFT - 32) write_ttbr0_64bit r0, r1 isb #else /*!CFG_WITH_LPAE*/ read_contextidr r0 tst r0, #1 beq 11f /* Update the mapping to use the full kernel mode mapping. */ bic r0, r0, #1 write_contextidr r0 isb #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 read_ttbcr r0 bic r0, r0, #TTBCR_PD1 write_ttbcr r0 isb #endif #endif /*!CFG_WITH_LPAE*/ #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 ldr r0, =thread_user_kcode_offset ldr r0, [r0] read_vbar r1 add r1, r1, r0 write_vbar r1 isb 11: /* * The PC is adjusted unconditionally to guard against the * case there was an FIQ just before we did the "cpsid aif". */ ldr r0, =22f bx r0 22: #else 11: #endif read_tpidrprw r0 #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) read_tpidruro r1 #endif .endm /* The handler of native interrupt. */ .macro native_intr_handler mode:req cpsid aif maybe_restore_mapping /* * FIQ and IRQ have a +4 offset for lr compared to preferred return * address */ sub lr, lr, #4 /* * We're always saving {r0-r3}. In IRQ mode we're saving r12 also. * In FIQ mode we're saving the banked fiq registers {r8-r12} FIQ * because the secure monitor doesn't save those. The treatment of * the banked fiq registers is somewhat analogous to the lazy save * of VFP registers. */ .ifc \mode\(),fiq push {r0-r3, r8-r12, lr} .else push {r0-r3, r12, lr} .endif bl thread_check_canaries bl interrupt_main_handler mrs r0, spsr cmp_spsr_user_mode r0 .ifc \mode\(),fiq pop {r0-r3, r8-r12, lr} .else pop {r0-r3, r12, lr} .endif movsne pc, lr b eret_to_user_mode .endm /* The handler of foreign interrupt. */ .macro foreign_intr_handler mode:req cpsid aif maybe_restore_mapping sub lr, lr, #4 push {r12} .ifc \mode\(),fiq /* * If a foreign (non-secure) interrupt is received as a FIQ we need * to check that we're in a saveable state or if we need to mask * the interrupt to be handled later. * * The window when this is needed is quite narrow, it's between * entering the exception vector and until the "cpsid" instruction * of the handler has been executed. * * Currently we can save the state properly if the FIQ is received * while in user or svc (kernel) mode. * * If we're returning to abort, undef or irq mode we're returning * with the mapping restored. This is OK since before the handler * we're returning to eventually returns to user mode the reduced * mapping will be restored. */ mrs r12, spsr and r12, r12, #ARM32_CPSR_MODE_MASK cmp r12, #ARM32_CPSR_MODE_USR cmpne r12, #ARM32_CPSR_MODE_SVC beq 1f mrs r12, spsr orr r12, r12, #ARM32_CPSR_F msr spsr_fsxc, r12 pop {r12} movs pc, lr 1: .endif push {lr} .ifc \mode\(),fiq bl thread_save_state_fiq .else bl thread_save_state .endif #ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME /* * Prevent leaking information about which entries has been used in * cache. We're relying on the secure monitor/dispatcher to take * care of the BTB. */ mov r0, #DCACHE_OP_CLEAN_INV bl dcache_op_louis write_iciallu #endif /* * Use SP_abt to update core local flags. * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_TMP; */ cps #CPSR_MODE_ABT ldr r1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsl r1, r1, #THREAD_CLF_SAVED_SHIFT orr r1, r1, #THREAD_CLF_TMP str r1, [sp, #THREAD_CORE_LOCAL_FLAGS] .ifc \mode\(),fiq cps #CPSR_MODE_FIQ .else cps #CPSR_MODE_IRQ .endif mov r0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR mrs r1, spsr pop {r2} pop {r12} blx thread_state_suspend /* * Switch to SVC mode and copy current stack pointer as it already * is the tmp stack. */ mov r1, sp cps #CPSR_MODE_SVC mov sp, r1 /* Passing thread index in r0 */ b thread_foreign_intr_exit .endm FUNC thread_excp_vect , :, align=32 UNWIND( .cantunwind) b . /* Reset */ b __thread_und_handler /* Undefined instruction */ b __thread_svc_handler /* System call */ b __thread_pabort_handler /* Prefetch abort */ b __thread_dabort_handler /* Data abort */ b . /* Reserved */ b __thread_irq_handler /* IRQ */ b __thread_fiq_handler /* FIQ */ #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC .macro vector_prologue_spectre /* * This depends on SP being 8 byte aligned, that is, the * lowest three bits in SP are zero. * * To avoid unexpected speculation we need to invalidate * the branch predictor before we do the first branch. It * doesn't matter if it's a conditional or an unconditional * branch speculation can still occur. * * The idea is to form a specific bit pattern in the lowest * three bits of SP depending on which entry in the vector * we enter via. This is done by adding 1 to SP in each * entry but the last. */ add sp, sp, #1 /* 7:111 Reset */ add sp, sp, #1 /* 6:110 Undefined instruction */ add sp, sp, #1 /* 5:101 Secure monitor call */ add sp, sp, #1 /* 4:100 Prefetch abort */ add sp, sp, #1 /* 3:011 Data abort */ add sp, sp, #1 /* 2:010 Reserved */ add sp, sp, #1 /* 1:001 IRQ */ cpsid aif /* 0:000 FIQ */ .endm .balign 32 .global thread_excp_vect_wa_a15_spectre_v2 thread_excp_vect_wa_a15_spectre_v2: vector_prologue_spectre write_tpidrprw r0 mrs r0, spsr cmp_spsr_user_mode r0 bne 1f /* * Invalidate the branch predictor for the current processor. * For Cortex-A8 ACTLR[6] has to be set to 1 for BPIALL to be * effective. * Note that the BPIALL instruction is not effective in * invalidating the branch predictor on Cortex-A15. For that CPU, * set ACTLR[0] to 1 during early processor initialisation, and * invalidate the branch predictor by performing an ICIALLU * instruction. See also: * https://github.com/ARM-software/arm-trusted-firmware/wiki/Arm-Trusted-Firmware-Security-Advisory-TFV-6#variant-2-cve-2017-5715 */ write_iciallu isb b 1f .balign 32 .global thread_excp_vect_wa_spectre_v2 thread_excp_vect_wa_spectre_v2: vector_prologue_spectre write_tpidrprw r0 mrs r0, spsr cmp_spsr_user_mode r0 bne 1f /* Invalidate the branch predictor for the current processor. */ write_bpiall isb 1: and r0, sp, #(BIT(0) | BIT(1) | BIT(2)) bic sp, sp, #(BIT(0) | BIT(1) | BIT(2)) add pc, pc, r0, LSL #3 nop read_tpidrprw r0 b __thread_fiq_handler /* FIQ */ read_tpidrprw r0 b __thread_irq_handler /* IRQ */ read_tpidrprw r0 b . /* Reserved */ read_tpidrprw r0 b __thread_dabort_handler /* Data abort */ read_tpidrprw r0 b __thread_pabort_handler /* Prefetch abort */ read_tpidrprw r0 b __thread_svc_handler /* System call */ read_tpidrprw r0 b __thread_und_handler /* Undefined instruction */ read_tpidrprw r0 b . /* Reset */ #endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ __thread_und_handler: cpsid aif maybe_restore_mapping strd r0, r1, [sp, #THREAD_CORE_LOCAL_R0] mrs r1, spsr tst r1, #CPSR_T subne lr, lr, #2 subeq lr, lr, #4 mov r0, #ABORT_TYPE_UNDEF b __thread_abort_common __thread_dabort_handler: cpsid aif maybe_restore_mapping strd r0, r1, [sp, #THREAD_CORE_LOCAL_R0] sub lr, lr, #8 mov r0, #ABORT_TYPE_DATA b __thread_abort_common __thread_pabort_handler: cpsid aif maybe_restore_mapping strd r0, r1, [sp, #THREAD_CORE_LOCAL_R0] sub lr, lr, #4 mov r0, #ABORT_TYPE_PREFETCH __thread_abort_common: /* * At this label: * cpsr is in mode undef or abort * sp is still pointing to struct thread_core_local belonging to * this core. * {r0, r1} are saved in struct thread_core_local pointed to by sp * {r2-r11, ip} are untouched. * r0 holds the first argument for abort_handler() */ /* * Update core local flags. * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT; */ ldr r1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsl r1, r1, #THREAD_CLF_SAVED_SHIFT orr r1, r1, #THREAD_CLF_ABORT /* * Select stack and update flags accordingly * * Normal case: * If the abort stack is unused select that. * * Fatal error handling: * If we're already using the abort stack as noted by bit * (THREAD_CLF_SAVED_SHIFT + THREAD_CLF_ABORT_SHIFT) in the flags * field we're selecting the temporary stack instead to be able to * make a stack trace of the abort in abort mode. * * r1 is initialized as a temporary stack pointer until we've * switched to system mode. */ tst r1, #(THREAD_CLF_ABORT << THREAD_CLF_SAVED_SHIFT) orrne r1, r1, #THREAD_CLF_TMP /* flags |= THREAD_CLF_TMP; */ str r1, [sp, #THREAD_CORE_LOCAL_FLAGS] ldrne r1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] ldreq r1, [sp, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] /* * Store registers on stack fitting struct thread_abort_regs * start from the end of the struct * {r2-r11, ip} * Load content of previously saved {r0-r1} and stores * it up to the pad field. * After this is only {usr_sp, usr_lr} missing in the struct */ stmdb r1!, {r2-r11, ip} /* Push on the selected stack */ ldrd r2, r3, [sp, #THREAD_CORE_LOCAL_R0] /* Push the original {r0-r1} on the selected stack */ stmdb r1!, {r2-r3} mrs r3, spsr /* Push {pad, spsr, elr} on the selected stack */ stmdb r1!, {r2, r3, lr} cps #CPSR_MODE_SYS str lr, [r1, #-4]! str sp, [r1, #-4]! mov sp, r1 bl abort_handler mov ip, sp ldr sp, [ip], #4 ldr lr, [ip], #4 /* * Even if we entered via CPSR_MODE_UND, we are returning via * CPSR_MODE_ABT. It doesn't matter as lr and spsr are assigned * here. */ cps #CPSR_MODE_ABT ldm ip!, {r0, r1, lr} /* r0 is pad */ msr spsr_fsxc, r1 /* Update core local flags */ ldr r0, [sp, #THREAD_CORE_LOCAL_FLAGS] lsr r0, r0, #THREAD_CLF_SAVED_SHIFT str r0, [sp, #THREAD_CORE_LOCAL_FLAGS] cmp_spsr_user_mode r1 ldm ip, {r0-r11, ip} movsne pc, lr b eret_to_user_mode /* end thread_abort_common */ __thread_svc_handler: cpsid aif maybe_restore_mapping push {r0-r7, lr} mrs r0, spsr push {r0} mov r0, sp bl thread_scall_handler cpsid aif /* In case something was unmasked */ pop {r0} msr spsr_fsxc, r0 cmp_spsr_user_mode r0 pop {r0-r7, lr} movsne pc, lr b eret_to_user_mode /* end thread_svc_handler */ __thread_fiq_handler: #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) foreign_intr_handler fiq #else native_intr_handler fiq #endif /* end thread_fiq_handler */ __thread_irq_handler: #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) native_intr_handler irq #else foreign_intr_handler irq #endif /* end thread_irq_handler */ /* * Returns to user mode. * Expects to be jumped to with lr pointing to the user space * address to jump to and spsr holding the desired cpsr. Async * abort, irq and fiq should be masked. */ eret_to_user_mode: write_tpidrprw r0 #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) write_tpidruro r1 #endif #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 ldr r0, =thread_user_kcode_offset ldr r0, [r0] read_vbar r1 sub r1, r1, r0 write_vbar r1 isb /* Jump into the reduced mapping before the full mapping is removed */ ldr r1, =1f sub r1, r1, r0 bx r1 1: #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ #ifdef CFG_WITH_LPAE read_ttbr0_64bit r0, r1 #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 add r0, r0, #CORE_MMU_BASE_TABLE_OFFSET #endif /* switch to user ASID */ orr r1, r1, #BIT(TTBR_ASID_SHIFT - 32) write_ttbr0_64bit r0, r1 isb #else /*!CFG_WITH_LPAE*/ #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 read_ttbcr r0 orr r0, r0, #TTBCR_PD1 write_ttbcr r0 isb #endif read_contextidr r0 orr r0, r0, #BIT(0) write_contextidr r0 isb #endif /*!CFG_WITH_LPAE*/ read_tpidrprw r0 #if defined(CFG_CORE_UNMAP_CORE_AT_EL0) || defined(CFG_WITH_LPAE) read_tpidruro r1 #endif movs pc, lr /* * void icache_inv_user_range(void *addr, size_t size); * * This function has to execute with the user space ASID active, * this means executing with reduced mapping and the code needs * to be located here together with the vector. */ .global icache_inv_user_range .type icache_inv_user_range , %function icache_inv_user_range: push {r4-r7} /* Mask all exceptions */ mrs r4, cpsr /* This register must be preserved */ cpsid aif #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 ldr r2, =thread_user_kcode_offset ldr r2, [r2] read_vbar r5 /* This register must be preserved */ sub r3, r5, r2 write_vbar r3 isb /* Jump into the reduced mapping before the full mapping is removed */ ldr r3, =1f sub r3, r3, r2 bx r3 1: #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ #ifdef CFG_WITH_LPAE read_ttbr0_64bit r6, r7 /* These registers must be preseved */ /* switch to user ASID */ orr r3, r7, #BIT(TTBR_ASID_SHIFT - 32) #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 add r2, r6, #CORE_MMU_BASE_TABLE_OFFSET write_ttbr0_64bit r2, r3 #else write_ttbr0_64bit r6, r3 #endif isb #else /*!CFG_WITH_LPAE*/ #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 read_ttbcr r6 /* This register must be preserved */ orr r2, r6, #TTBCR_PD1 write_ttbcr r2 isb #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ read_contextidr r7 /* This register must be preserved */ orr r2, r7, #BIT(0) write_contextidr r2 isb #endif /*!CFG_WITH_LPAE*/ /* * Do the actual icache invalidation */ /* Calculate minimum icache line size, result in r2 */ read_ctr r3 and r3, r3, #CTR_IMINLINE_MASK mov r2, #CTR_WORD_SIZE lsl r2, r2, r3 add r1, r0, r1 sub r3, r2, #1 bic r0, r0, r3 1: write_icimvau r0 add r0, r0, r2 cmp r0, r1 blo 1b /* Invalidate entire branch predictor array inner shareable */ write_bpiallis dsb ishst isb #ifdef CFG_WITH_LPAE write_ttbr0_64bit r6, r7 isb #else /*!CFG_WITH_LPAE*/ write_contextidr r7 isb #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 write_ttbcr r6 isb #endif #endif /*!CFG_WITH_LPAE*/ #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 write_vbar r5 isb /* * The PC is adjusted unconditionally to guard against the * case there was an FIQ just before we did the "cpsid aif". */ ldr r0, =1f bx r0 1: #endif msr cpsr_fsxc, r4 /* Restore exceptions */ pop {r4-r7} bx lr /* End of icache_inv_user_range() */ /* * Make sure that literals are placed before the * thread_excp_vect_end label. */ .pool .global thread_excp_vect_end thread_excp_vect_end: END_FUNC thread_excp_vect optee_os-4.3.0/core/arch/arm/kernel/thread_a64.S000066400000000000000000000763611464416617300213350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include .macro get_thread_ctx core_local, res, tmp0, tmp1 ldrh w\tmp0, [\core_local, \ #THREAD_CORE_LOCAL_CURR_THREAD] adr_l x\res, threads mov x\tmp1, #THREAD_CTX_SIZE madd x\res, x\tmp0, x\tmp1, x\res .endm .macro return_from_exception eret /* Guard against speculation past ERET */ dsb nsh isb .endm .macro b_if_spsr_is_el0 reg, label tbnz \reg, #(SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT), \label tst \reg, #(SPSR_64_MODE_EL_MASK << SPSR_64_MODE_EL_SHIFT) b.eq \label .endm .macro pauth_el0_to_el1 reg /* * If pauth is only enabled in one of core or TA (xor) we * need to update sctlr. */ #if (defined(CFG_TA_PAUTH) && !defined(CFG_CORE_PAUTH)) || \ (!defined(CFG_TA_PAUTH) && defined(CFG_CORE_PAUTH)) mrs \reg, sctlr_el1 /* Flip the SCTLR_ENIA bit */ eor \reg, \reg, #SCTLR_ENIA msr sctlr_el1, \reg #endif .endm .macro pauth_el1_to_el0 reg /* * If pauth is only enabled in one of core or TA (xor) we * need to update sctlr. */ #if (defined(CFG_TA_PAUTH) && !defined(CFG_CORE_PAUTH)) || \ (!defined(CFG_TA_PAUTH) && defined(CFG_CORE_PAUTH)) mrs \reg, sctlr_el1 /* Flip the SCTLR_ENIA bit */ eor \reg, \reg, #SCTLR_ENIA msr sctlr_el1, \reg #endif .endm /* void thread_resume(struct thread_ctx_regs *regs) */ FUNC thread_resume , : load_xregs x0, THREAD_CTX_REGS_SP, 1, 3 load_xregs x0, THREAD_CTX_REGS_X4, 4, 30 mov sp, x1 msr elr_el1, x2 msr spsr_el1, x3 ldr x1, [x0, THREAD_CTX_REGS_TPIDR_EL0] msr tpidr_el0, x1 #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) load_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 write_apiakeyhi x1 write_apiakeylo x2 #endif b_if_spsr_is_el0 w3, 1f #if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) /* SCTLR or the APIA key has changed */ isb #endif load_xregs x0, THREAD_CTX_REGS_X1, 1, 3 ldr x0, [x0, THREAD_CTX_REGS_X0] return_from_exception 1: load_xregs x0, THREAD_CTX_REGS_X1, 1, 3 ldr x0, [x0, THREAD_CTX_REGS_X0] msr spsel, #1 store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 b eret_to_el0 END_FUNC thread_resume #ifdef CFG_CORE_SEL2_SPMC FUNC thread_hvc , : hvc #0 ret END_FUNC thread_hvc #endif FUNC thread_smc , : smc #0 ret END_FUNC thread_smc /* void thread_smccc(struct thread_smc_args *arg_res) */ FUNC thread_smccc , : push x0, xzr mov x8, x0 load_xregs x8, 0, 0, 7 #ifdef CFG_CORE_SEL2_SPMC hvc #0 #else smc #0 #endif pop x8, xzr store_xregs x8, 0, 0, 7 ret END_FUNC thread_smccc FUNC thread_init_vbar , : msr vbar_el1, x0 ret END_FUNC thread_init_vbar DECLARE_KEEP_PAGER thread_init_vbar /* * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, * uint32_t *exit_status0, * uint32_t *exit_status1); * * This function depends on being called with exceptions masked. */ FUNC __thread_enter_user_mode , : /* * Create the and fill in the struct thread_user_mode_rec */ sub sp, sp, #THREAD_USER_MODE_REC_SIZE store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 0, 2 store_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30 /* * Save kern sp in x19 * Switch to SP_EL1 */ mov x19, sp msr spsel, #1 /* * Save the kernel stack pointer in the thread context */ /* get pointer to current thread context */ get_thread_ctx sp, 21, 20, 22 /* * Save kernel stack pointer to ensure that el0_svc() uses * correct stack pointer */ str x19, [x21, #THREAD_CTX_KERN_SP] /* * Initialize SPSR, ELR_EL1, and SP_EL0 to enter user mode */ load_xregs x0, THREAD_CTX_REGS_SP, 1, 3 msr sp_el0, x1 msr elr_el1, x2 msr spsr_el1, x3 #ifdef CFG_TA_PAUTH /* Load APIAKEY */ load_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 write_apiakeyhi x1 write_apiakeylo x2 #endif /* * Save the values for x0 and x1 in struct thread_core_local to be * restored later just before the eret. */ load_xregs x0, THREAD_CTX_REGS_X0, 1, 2 store_xregs sp, THREAD_CORE_LOCAL_X0, 1, 2 /* Load the rest of the general purpose registers */ load_xregs x0, THREAD_CTX_REGS_X2, 2, 30 /* Jump into user mode */ b eret_to_el0 END_FUNC __thread_enter_user_mode DECLARE_KEEP_PAGER __thread_enter_user_mode /* * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, * uint32_t exit_status1); * See description in thread.h */ FUNC thread_unwind_user_mode , : /* Store the exit status */ load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, 3, 5 str w1, [x4] str w2, [x5] /* Save x19..x30 */ store_xregs x3, THREAD_CTX_REGS_X19, 19, 30 /* Restore x19..x30 */ load_xregs sp, THREAD_USER_MODE_REC_X19, 19, 30 add sp, sp, #THREAD_USER_MODE_REC_SIZE /* Return from the call of thread_enter_user_mode() */ ret END_FUNC thread_unwind_user_mode /* * This macro verifies that the a given vector doesn't exceed the * architectural limit of 32 instructions. This is meant to be placed * immedately after the last instruction in the vector. It takes the * vector entry as the parameter */ .macro check_vector_size since .if (. - \since) > (32 * 4) .error "Vector exceeds 32 instructions" .endif .endm .macro restore_mapping #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 /* Temporarily save x0, x1 */ msr tpidr_el1, x0 msr tpidrro_el0, x1 /* Update the mapping to use the full kernel mapping */ mrs x0, ttbr0_el1 sub_imm x0, __CORE_MMU_BASE_TABLE_OFFSET /* switch to kernel mode ASID */ bic x0, x0, #BIT(TTBR_ASID_SHIFT) msr ttbr0_el1, x0 isb /* Jump into the full mapping and continue execution */ adr x0, 1f ldr x1, [sp, #THREAD_CORE_LOCAL_KCODE_OFFSET] add x0, x0, x1 br x0 1: BTI( bti j) /* Point to the vector into the full mapping */ adr_l x0, thread_user_kcode_offset ldr x0, [x0] mrs x1, vbar_el1 add x1, x1, x0 msr vbar_el1, x1 isb #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC /* * Update the SP with thread_user_kdata_sp_offset as * described in init_user_kcode(). */ adr_l x0, thread_user_kdata_sp_offset ldr x0, [x0] add sp, sp, x0 #endif /* Restore x0, x1 */ mrs x0, tpidr_el1 mrs x1, tpidrro_el0 store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 #else store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 mrs x0, ttbr0_el1 /* switch to kernel mode ASID */ bic x0, x0, #BIT(TTBR_ASID_SHIFT) msr ttbr0_el1, x0 isb #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ .endm #define INV_INSN 0 FUNC thread_excp_vect , : , default, 2048, nobti /* ----------------------------------------------------- * EL1 with SP0 : 0x0 - 0x180 * ----------------------------------------------------- */ .balign 128, INV_INSN el1_sync_sp0: store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 b el1_sync_abort check_vector_size el1_sync_sp0 .balign 128, INV_INSN el1_irq_sp0: store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 b elx_irq check_vector_size el1_irq_sp0 .balign 128, INV_INSN el1_fiq_sp0: store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 b elx_fiq check_vector_size el1_fiq_sp0 .balign 128, INV_INSN el1_serror_sp0: b el1_serror_sp0 check_vector_size el1_serror_sp0 /* ----------------------------------------------------- * Current EL with SP1: 0x200 - 0x380 * ----------------------------------------------------- */ .balign 128, INV_INSN el1_sync_sp1: b el1_sync_sp1 check_vector_size el1_sync_sp1 .balign 128, INV_INSN el1_irq_sp1: b el1_irq_sp1 check_vector_size el1_irq_sp1 .balign 128, INV_INSN el1_fiq_sp1: b el1_fiq_sp1 check_vector_size el1_fiq_sp1 .balign 128, INV_INSN el1_serror_sp1: b el1_serror_sp1 check_vector_size el1_serror_sp1 /* ----------------------------------------------------- * Lower EL using AArch64 : 0x400 - 0x580 * ----------------------------------------------------- */ .balign 128, INV_INSN el0_sync_a64: restore_mapping /* PAuth will be disabled later else check_vector_size will fail */ b el0_sync_a64_finish check_vector_size el0_sync_a64 .balign 128, INV_INSN el0_irq_a64: restore_mapping pauth_el0_to_el1 x1 b elx_irq check_vector_size el0_irq_a64 .balign 128, INV_INSN el0_fiq_a64: restore_mapping pauth_el0_to_el1 x1 b elx_fiq check_vector_size el0_fiq_a64 .balign 128, INV_INSN el0_serror_a64: b el0_serror_a64 check_vector_size el0_serror_a64 /* ----------------------------------------------------- * Lower EL using AArch32 : 0x0 - 0x180 * ----------------------------------------------------- */ .balign 128, INV_INSN el0_sync_a32: restore_mapping b el0_sync_a32_finish check_vector_size el0_sync_a32 .balign 128, INV_INSN el0_irq_a32: restore_mapping b elx_irq check_vector_size el0_irq_a32 .balign 128, INV_INSN el0_fiq_a32: restore_mapping b elx_fiq check_vector_size el0_fiq_a32 .balign 128, INV_INSN el0_serror_a32: b el0_serror_a32 check_vector_size el0_serror_a32 #if defined(CFG_CORE_WORKAROUND_SPECTRE_BP_SEC) .macro invalidate_branch_predictor store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 mov_imm x0, SMCCC_ARCH_WORKAROUND_1 smc #0 load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 .endm .balign 2048, INV_INSN .global thread_excp_vect_wa_spectre_v2 thread_excp_vect_wa_spectre_v2: /* ----------------------------------------------------- * EL1 with SP0 : 0x0 - 0x180 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_v2_el1_sync_sp0: b el1_sync_sp0 check_vector_size wa_spectre_v2_el1_sync_sp0 .balign 128, INV_INSN wa_spectre_v2_el1_irq_sp0: b el1_irq_sp0 check_vector_size wa_spectre_v2_el1_irq_sp0 .balign 128, INV_INSN wa_spectre_v2_el1_fiq_sp0: b el1_fiq_sp0 check_vector_size wa_spectre_v2_el1_fiq_sp0 .balign 128, INV_INSN wa_spectre_v2_el1_serror_sp0: b el1_serror_sp0 check_vector_size wa_spectre_v2_el1_serror_sp0 /* ----------------------------------------------------- * Current EL with SP1: 0x200 - 0x380 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_v2_el1_sync_sp1: b wa_spectre_v2_el1_sync_sp1 check_vector_size wa_spectre_v2_el1_sync_sp1 .balign 128, INV_INSN wa_spectre_v2_el1_irq_sp1: b wa_spectre_v2_el1_irq_sp1 check_vector_size wa_spectre_v2_el1_irq_sp1 .balign 128, INV_INSN wa_spectre_v2_el1_fiq_sp1: b wa_spectre_v2_el1_fiq_sp1 check_vector_size wa_spectre_v2_el1_fiq_sp1 .balign 128, INV_INSN wa_spectre_v2_el1_serror_sp1: b wa_spectre_v2_el1_serror_sp1 check_vector_size wa_spectre_v2_el1_serror_sp1 /* ----------------------------------------------------- * Lower EL using AArch64 : 0x400 - 0x580 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_v2_el0_sync_a64: invalidate_branch_predictor b el0_sync_a64 check_vector_size wa_spectre_v2_el0_sync_a64 .balign 128, INV_INSN wa_spectre_v2_el0_irq_a64: invalidate_branch_predictor b el0_irq_a64 check_vector_size wa_spectre_v2_el0_irq_a64 .balign 128, INV_INSN wa_spectre_v2_el0_fiq_a64: invalidate_branch_predictor b el0_fiq_a64 check_vector_size wa_spectre_v2_el0_fiq_a64 .balign 128, INV_INSN wa_spectre_v2_el0_serror_a64: b wa_spectre_v2_el0_serror_a64 check_vector_size wa_spectre_v2_el0_serror_a64 /* ----------------------------------------------------- * Lower EL using AArch32 : 0x0 - 0x180 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_v2_el0_sync_a32: invalidate_branch_predictor b el0_sync_a32 check_vector_size wa_spectre_v2_el0_sync_a32 .balign 128, INV_INSN wa_spectre_v2_el0_irq_a32: invalidate_branch_predictor b el0_irq_a32 check_vector_size wa_spectre_v2_el0_irq_a32 .balign 128, INV_INSN wa_spectre_v2_el0_fiq_a32: invalidate_branch_predictor b el0_fiq_a32 check_vector_size wa_spectre_v2_el0_fiq_a32 .balign 128, INV_INSN wa_spectre_v2_el0_serror_a32: b wa_spectre_v2_el0_serror_a32 check_vector_size wa_spectre_v2_el0_serror_a32 .macro discard_branch_history str x0, [sp, #THREAD_CORE_LOCAL_X0] ldrb w0, [sp, #THREAD_CORE_LOCAL_BHB_LOOP_COUNT] 1: b 2f 2: subs w0, w0, #1 bne 1b dsb sy isb ldr x0, [sp, #THREAD_CORE_LOCAL_X0] .endm .balign 2048, INV_INSN .global thread_excp_vect_wa_spectre_bhb thread_excp_vect_wa_spectre_bhb: /* ----------------------------------------------------- * EL1 with SP0 : 0x0 - 0x180 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_bhb_el1_sync_sp0: b el1_sync_sp0 check_vector_size wa_spectre_bhb_el1_sync_sp0 .balign 128, INV_INSN wa_spectre_bhb_el1_irq_sp0: b el1_irq_sp0 check_vector_size wa_spectre_bhb_el1_irq_sp0 .balign 128, INV_INSN wa_spectre_bhb_el1_fiq_sp0: b el1_fiq_sp0 check_vector_size wa_spectre_bhb_el1_fiq_sp0 .balign 128, INV_INSN wa_spectre_bhb_el1_serror_sp0: b el1_serror_sp0 check_vector_size wa_spectre_bhb_el1_serror_sp0 /* ----------------------------------------------------- * Current EL with SP1: 0x200 - 0x380 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_bhb_el1_sync_sp1: b wa_spectre_bhb_el1_sync_sp1 check_vector_size wa_spectre_bhb_el1_sync_sp1 .balign 128, INV_INSN wa_spectre_bhb_el1_irq_sp1: b wa_spectre_bhb_el1_irq_sp1 check_vector_size wa_spectre_bhb_el1_irq_sp1 .balign 128, INV_INSN wa_spectre_bhb_el1_fiq_sp1: b wa_spectre_bhb_el1_fiq_sp1 check_vector_size wa_spectre_bhb_el1_fiq_sp1 .balign 128, INV_INSN wa_spectre_bhb_el1_serror_sp1: b wa_spectre_bhb_el1_serror_sp1 check_vector_size wa_spectre_bhb_el1_serror_sp1 /* ----------------------------------------------------- * Lower EL using AArch64 : 0x400 - 0x580 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_bhb_el0_sync_a64: discard_branch_history b el0_sync_a64 check_vector_size wa_spectre_bhb_el0_sync_a64 .balign 128, INV_INSN wa_spectre_bhb_el0_irq_a64: discard_branch_history b el0_irq_a64 check_vector_size wa_spectre_bhb_el0_irq_a64 .balign 128, INV_INSN wa_spectre_bhb_el0_fiq_a64: discard_branch_history b el0_fiq_a64 check_vector_size wa_spectre_bhb_el0_fiq_a64 .balign 128, INV_INSN wa_spectre_bhb_el0_serror_a64: b wa_spectre_bhb_el0_serror_a64 check_vector_size wa_spectre_bhb_el0_serror_a64 /* ----------------------------------------------------- * Lower EL using AArch32 : 0x0 - 0x180 * ----------------------------------------------------- */ .balign 128, INV_INSN wa_spectre_bhb_el0_sync_a32: discard_branch_history b el0_sync_a32 check_vector_size wa_spectre_bhb_el0_sync_a32 .balign 128, INV_INSN wa_spectre_bhb_el0_irq_a32: discard_branch_history b el0_irq_a32 check_vector_size wa_spectre_bhb_el0_irq_a32 .balign 128, INV_INSN wa_spectre_bhb_el0_fiq_a32: discard_branch_history b el0_fiq_a32 check_vector_size wa_spectre_bhb_el0_fiq_a32 .balign 128, INV_INSN wa_spectre_bhb_el0_serror_a32: b wa_spectre_bhb_el0_serror_a32 check_vector_size wa_spectre_bhb_el0_serror_a32 #endif /*CFG_CORE_WORKAROUND_SPECTRE_BP_SEC*/ /* * We're keeping this code in the same section as the vector to make sure * that it's always available. */ eret_to_el0: pauth_el1_to_el0 x1 #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 /* Point to the vector into the reduced mapping */ adr_l x0, thread_user_kcode_offset ldr x0, [x0] mrs x1, vbar_el1 sub x1, x1, x0 msr vbar_el1, x1 isb #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC /* Store the SP offset in tpidr_el1 to be used below to update SP */ adr_l x1, thread_user_kdata_sp_offset ldr x1, [x1] msr tpidr_el1, x1 #endif /* Jump into the reduced mapping and continue execution */ adr_l x1, 1f sub x1, x1, x0 br x1 1: BTI( bti j) load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 msr tpidrro_el0, x0 /* Update the mapping to exclude the full kernel mapping */ mrs x0, ttbr0_el1 add_imm x0, __CORE_MMU_BASE_TABLE_OFFSET orr x0, x0, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ msr ttbr0_el1, x0 isb #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP_SEC /* * Update the SP with thread_user_kdata_sp_offset as described in * init_user_kcode(). */ mrs x0, tpidr_el1 sub sp, sp, x0 #endif mrs x0, tpidrro_el0 #else mrs x0, ttbr0_el1 orr x0, x0, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ msr ttbr0_el1, x0 isb load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ return_from_exception el0_sync_a64_finish: mrs x2, esr_el1 mrs x3, sp_el0 lsr x2, x2, #ESR_EC_SHIFT cmp x2, #ESR_EC_AARCH64_SVC b.eq el0_svc b el0_sync_abort el0_sync_a32_finish: mrs x2, esr_el1 mrs x3, sp_el0 lsr x2, x2, #ESR_EC_SHIFT cmp x2, #ESR_EC_AARCH32_SVC b.eq el0_svc b el0_sync_abort /* * void icache_inv_user_range(void *addr, size_t size); * * This function has to execute with the user space ASID active, * this means executing with reduced mapping and the code needs * to be located here together with the vector. */ .global icache_inv_user_range .type icache_inv_user_range , %function icache_inv_user_range: /* Mask all exceptions */ mrs x6, daif /* this register must be preserved */ msr daifset, #DAIFBIT_ALL #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 /* Point to the vector into the reduced mapping */ adr_l x7, thread_user_kcode_offset ldr x7, [x7] /* this register must be preserved */ mrs x4, vbar_el1 /* this register must be preserved */ sub x3, x4, x7 msr vbar_el1, x3 isb /* Jump into the reduced mapping and continue execution */ adr x3, 1f sub x3, x3, x7 br x3 1: BTI( bti j) /* Update the mapping to exclude the full kernel mapping */ mrs x5, ttbr0_el1 /* this register must be preserved */ orr x2, x5, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ add_imm x2, __CORE_MMU_BASE_TABLE_OFFSET msr ttbr0_el1, x2 isb #else mrs x5, ttbr0_el1 /* this register must be preserved */ orr x2, x5, #BIT(TTBR_ASID_SHIFT) /* switch to user mode ASID */ msr ttbr0_el1, x2 isb #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ /* * Do the actual icache invalidation */ /* Calculate minimum icache line size, result in x2 */ mrs x3, ctr_el0 and x3, x3, #CTR_IMINLINE_MASK mov x2, #CTR_WORD_SIZE lsl x2, x2, x3 add x1, x0, x1 sub x3, x2, #1 bic x0, x0, x3 1: ic ivau, x0 add x0, x0, x2 cmp x0, x1 b.lo 1b dsb ish #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 /* Update the mapping to use the full kernel mapping and ASID */ msr ttbr0_el1, x5 isb /* Jump into the full mapping and continue execution */ adr x0, 1f add x0, x0, x7 br x0 1: BTI( bti j) /* Point to the vector into the full mapping */ msr vbar_el1, x4 isb #else /* switch to kernel mode ASID */ msr ttbr0_el1, x5 isb #endif /*CFG_CORE_UNMAP_CORE_AT_EL0*/ msr daif, x6 /* restore exceptions */ ret /* End of icache_inv_user_range() */ /* * Make sure that literals are placed before the * thread_excp_vect_end label. */ .pool .global thread_excp_vect_end thread_excp_vect_end: END_FUNC thread_excp_vect LOCAL_FUNC el0_svc , : pauth_el0_to_el1 x1 /* get pointer to current thread context in x0 */ get_thread_ctx sp, 0, 1, 2 mrs x1, tpidr_el0 str x1, [x0, #THREAD_CTX_REGS_TPIDR_EL0] /* load saved kernel sp */ ldr x3, [x0, #THREAD_CTX_KERN_SP] /* Keep pointer to initial recod in x1 */ mov x1, sp /* Switch to SP_EL0 and restore kernel sp */ msr spsel, #0 mov x2, sp /* Save SP_EL0 */ mov sp, x3 /* Make room for struct thread_scall_regs */ sub sp, sp, #THREAD_SCALL_REG_SIZE stp x30, x2, [sp, #THREAD_SCALL_REG_X30] #ifdef CFG_TA_PAUTH /* Save APIAKEY */ read_apiakeyhi x2 read_apiakeylo x3 stp x2, x3, [sp, #THREAD_SCALL_REG_APIAKEY_HI] #endif #ifdef CFG_CORE_PAUTH ldp x2, x3, [x0, #THREAD_CTX_KEYS] write_apiakeyhi x2 write_apiakeylo x3 #endif #if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) /* SCTLR or the APIA key has changed */ isb #endif /* Restore x0-x3 */ ldp x2, x3, [x1, #THREAD_CORE_LOCAL_X2] ldp x0, x1, [x1, #THREAD_CORE_LOCAL_X0] /* Prepare the argument for the handler */ store_xregs sp, THREAD_SCALL_REG_X0, 0, 14 mrs x0, elr_el1 mrs x1, spsr_el1 store_xregs sp, THREAD_SCALL_REG_ELR, 0, 1 mov x0, sp /* * Unmask native interrupts, Serror, and debug exceptions since we have * nothing left in sp_el1. Note that the SVC handler is excepted to * re-enable foreign interrupts by itself. */ #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) msr daifclr, #(DAIFBIT_IRQ | DAIFBIT_ABT | DAIFBIT_DBG) #else msr daifclr, #(DAIFBIT_FIQ | DAIFBIT_ABT | DAIFBIT_DBG) #endif /* Call the handler */ bl thread_scall_handler /* Mask all maskable exceptions since we're switching back to sp_el1 */ msr daifset, #DAIFBIT_ALL /* * Save kernel sp we'll had at the beginning of this function. * This is when this TA has called another TA because * __thread_enter_user_mode() also saves the stack pointer in this * field. */ msr spsel, #1 get_thread_ctx sp, 0, 1, 2 msr spsel, #0 add x1, sp, #THREAD_SCALL_REG_SIZE str x1, [x0, #THREAD_CTX_KERN_SP] /* Restore registers to the required state and return*/ ldr x1, [x0, #THREAD_CTX_REGS_TPIDR_EL0] msr tpidr_el0, x1 load_xregs sp, THREAD_SCALL_REG_ELR, 0, 1 msr elr_el1, x0 msr spsr_el1, x1 load_xregs sp, THREAD_SCALL_REG_X2, 2, 14 mov x30, sp ldr x0, [x30, #THREAD_SCALL_REG_SP_EL0] mov sp, x0 b_if_spsr_is_el0 w1, 1f ldp x0, x1, [x30, THREAD_SCALL_REG_X0] ldr x30, [x30, #THREAD_SCALL_REG_X30] return_from_exception 1: #ifdef CFG_TA_PAUTH /* Restore APIAKEY */ load_xregs x30, THREAD_SCALL_REG_APIAKEY_HI, 0, 1 write_apiakeyhi x0 write_apiakeylo x1 #endif ldp x0, x1, [x30, THREAD_SCALL_REG_X0] ldr x30, [x30, #THREAD_SCALL_REG_X30] msr spsel, #1 store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 b eret_to_el0 END_FUNC el0_svc LOCAL_FUNC el1_sync_abort , : mov x0, sp msr spsel, #0 mov x3, sp /* Save original sp */ /* * Update core local flags. * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT; */ ldr w1, [x0, #THREAD_CORE_LOCAL_FLAGS] lsl w1, w1, #THREAD_CLF_SAVED_SHIFT orr w1, w1, #THREAD_CLF_ABORT tbnz w1, #(THREAD_CLF_SAVED_SHIFT + THREAD_CLF_ABORT_SHIFT), \ .Lsel_tmp_sp /* Select abort stack */ ldr x2, [x0, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] b .Lset_sp .Lsel_tmp_sp: /* We have an abort while using the abort stack, select tmp stack */ ldr x2, [x0, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] orr w1, w1, #THREAD_CLF_TMP /* flags |= THREAD_CLF_TMP; */ .Lset_sp: mov sp, x2 str w1, [x0, #THREAD_CORE_LOCAL_FLAGS] /* * Save state on stack */ sub sp, sp, #THREAD_ABT_REGS_SIZE mrs x2, spsr_el1 /* Store spsr, sp_el0 */ stp x2, x3, [sp, #THREAD_ABT_REG_SPSR] /* Store original x0, x1 */ ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X0] stp x2, x3, [sp, #THREAD_ABT_REG_X0] /* Store original x2, x3 and x4 to x29 */ ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X2] store_xregs sp, THREAD_ABT_REG_X2, 2, 29 /* Store x30, elr_el1 */ mrs x1, elr_el1 stp x30, x1, [sp, #THREAD_ABT_REG_X30] #if defined(CFG_CORE_PAUTH) read_apiakeyhi x2 read_apiakeylo x3 stp x2, x3, [sp, #THREAD_ABT_REGS_APIAKEY_HI] ldp x2, x3, [x0, #THREAD_CORE_LOCAL_KEYS] write_apiakeyhi x2 write_apiakeylo x3 isb #endif /* * Call handler */ mov x0, #0 mov x1, sp bl abort_handler /* * Restore state from stack */ /* Load x30, elr_el1 */ ldp x30, x0, [sp, #THREAD_ABT_REG_X30] msr elr_el1, x0 /* Load x0 to x29 */ load_xregs sp, THREAD_ABT_REG_X0, 0, 29 /* Switch to SP_EL1 */ msr spsel, #1 /* Save x0 to x3 in CORE_LOCAL */ store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 /* Restore spsr_el1 and sp_el0 */ mrs x3, sp_el0 ldp x0, x1, [x3, #THREAD_ABT_REG_SPSR] msr spsr_el1, x0 msr sp_el0, x1 /* Update core local flags */ ldr w0, [sp, #THREAD_CORE_LOCAL_FLAGS] lsr w0, w0, #THREAD_CLF_SAVED_SHIFT str w0, [sp, #THREAD_CORE_LOCAL_FLAGS] #if defined(CFG_CORE_PAUTH) ldp x0, x1, [x3, #THREAD_ABT_REGS_APIAKEY_HI] write_apiakeyhi x0 write_apiakeylo x1 isb #endif /* Restore x0 to x3 */ load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 /* Return from exception */ return_from_exception END_FUNC el1_sync_abort /* sp_el0 in x3 */ LOCAL_FUNC el0_sync_abort , : pauth_el0_to_el1 x1 /* * Update core local flags */ ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsl w1, w1, #THREAD_CLF_SAVED_SHIFT orr w1, w1, #THREAD_CLF_ABORT str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] /* * Save state on stack */ /* load abt_stack_va_end */ ldr x1, [sp, #THREAD_CORE_LOCAL_ABT_STACK_VA_END] /* Keep pointer to initial record in x0 */ mov x0, sp /* Switch to SP_EL0 */ msr spsel, #0 mov sp, x1 sub sp, sp, #THREAD_ABT_REGS_SIZE mrs x2, spsr_el1 /* Store spsr, sp_el0 */ stp x2, x3, [sp, #THREAD_ABT_REG_SPSR] /* Store original x0, x1 */ ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X0] stp x2, x3, [sp, #THREAD_ABT_REG_X0] /* Store original x2, x3 and x4 to x29 */ ldp x2, x3, [x0, #THREAD_CORE_LOCAL_X2] store_xregs sp, THREAD_ABT_REG_X2, 2, 29 /* Store x30, elr_el1 */ mrs x1, elr_el1 stp x30, x1, [sp, #THREAD_ABT_REG_X30] #if defined(CFG_TA_PAUTH) read_apiakeyhi x2 read_apiakeylo x3 stp x2, x3, [sp, #THREAD_ABT_REGS_APIAKEY_HI] #endif #if defined(CFG_CORE_PAUTH) ldp x2, x3, [x0, #THREAD_CORE_LOCAL_KEYS] write_apiakeyhi x2 write_apiakeylo x3 #endif #if defined(CFG_CORE_PAUTH) || defined(CFG_TA_PAUTH) /* SCTLR or the APIA key has changed */ isb #endif /* * Call handler */ mov x0, #0 mov x1, sp bl abort_handler /* * Restore state from stack */ /* Load x30, elr_el1 */ ldp x30, x0, [sp, #THREAD_ABT_REG_X30] msr elr_el1, x0 /* Load x0 to x29 */ load_xregs sp, THREAD_ABT_REG_X0, 0, 29 /* Switch to SP_EL1 */ msr spsel, #1 /* Save x0 to x3 in EL1_REC */ store_xregs sp, THREAD_CORE_LOCAL_X0, 0, 3 /* Restore spsr_el1 and sp_el0 */ mrs x3, sp_el0 ldp x0, x1, [x3, #THREAD_ABT_REG_SPSR] msr spsr_el1, x0 msr sp_el0, x1 /* Update core local flags */ ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsr w1, w1, #THREAD_CLF_SAVED_SHIFT str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) ldp x1, x2, [x3, #THREAD_ABT_REGS_APIAKEY_HI] write_apiakeyhi x1 write_apiakeylo x2 #endif /* Restore x2 to x3 */ load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3 b_if_spsr_is_el0 w0, 1f #if defined(CFG_CORE_PAUTH) /* the APIA key has changed */ isb #endif /* Restore x0 to x1 */ load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 /* Return from exception */ return_from_exception 1: b eret_to_el0 END_FUNC el0_sync_abort /* The handler of foreign interrupt. */ .macro foreign_intr_handler mode:req /* * Update core local flags */ ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsl w1, w1, #THREAD_CLF_SAVED_SHIFT orr w1, w1, #THREAD_CLF_TMP .ifc \mode\(),fiq orr w1, w1, #THREAD_CLF_FIQ .else orr w1, w1, #THREAD_CLF_IRQ .endif str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] /* get pointer to current thread context in x0 */ get_thread_ctx sp, 0, 1, 2 /* Keep original SP_EL0 */ mrs x2, sp_el0 /* Store original sp_el0 */ str x2, [x0, #THREAD_CTX_REGS_SP] /* Store tpidr_el0 */ mrs x2, tpidr_el0 str x2, [x0, #THREAD_CTX_REGS_TPIDR_EL0] /* Store x4..x30 */ store_xregs x0, THREAD_CTX_REGS_X4, 4, 30 /* Load original x0..x3 into x10..x13 */ load_xregs sp, THREAD_CORE_LOCAL_X0, 10, 13 /* Save original x0..x3 */ store_xregs x0, THREAD_CTX_REGS_X0, 10, 13 #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) /* Save APIAKEY */ read_apiakeyhi x1 read_apiakeylo x2 store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 #endif #if defined(CFG_CORE_PAUTH) ldp x1, x2, [sp, #THREAD_CORE_LOCAL_KEYS] write_apiakeyhi x1 write_apiakeylo x2 isb #endif /* load tmp_stack_va_end */ ldr x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] /* Switch to SP_EL0 */ msr spsel, #0 mov sp, x1 #ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME /* * Prevent leaking information about which entries has been used in * cache. We're relying on the dispatcher in TF-A to take care of * the BTB. */ mov x0, #DCACHE_OP_CLEAN_INV bl dcache_op_louis ic iallu #endif /* * Mark current thread as suspended */ mov w0, #THREAD_FLAGS_EXIT_ON_FOREIGN_INTR mrs x1, spsr_el1 mrs x2, elr_el1 bl thread_state_suspend /* Update core local flags */ /* Switch to SP_EL1 */ msr spsel, #1 ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsr w1, w1, #THREAD_CLF_SAVED_SHIFT orr w1, w1, #THREAD_CLF_TMP str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] msr spsel, #0 /* * Note that we're exiting with SP_EL0 selected since the entry * functions expects to have SP_EL0 selected with the tmp stack * set. */ /* Passing thread index in w0 */ b thread_foreign_intr_exit .endm /* * This struct is never used from C it's only here to visualize the * layout. * * struct elx_nintr_rec { * uint64_t x[19 - 4]; x4..x18 * uint64_t lr; * uint64_t sp_el0; * #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) * uint64_t apiakey_hi; * uint64_t apiakey_lo; * #endif * }; */ #define ELX_NINTR_REC_X(x) (8 * ((x) - 4)) #define ELX_NINTR_REC_LR (8 + ELX_NINTR_REC_X(19)) #define ELX_NINTR_REC_SP_EL0 (8 + ELX_NINTR_REC_LR) #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) #define ELX_NINTR_REG_APIAKEY_HI (8 + ELX_NINTR_REC_SP_EL0) #define ELX_NINTR_REG_APIAKEY_LO (8 + ELX_NINTR_REG_APIAKEY_HI) #define ELX_NINTR_REC_SIZE (8 + ELX_NINTR_REG_APIAKEY_LO) #else #define ELX_NINTR_REC_SIZE (8 + ELX_NINTR_REC_SP_EL0) #endif /* The handler of native interrupt. */ .macro native_intr_handler mode:req /* * Update core local flags */ ldr w1, [sp, #THREAD_CORE_LOCAL_FLAGS] lsl w1, w1, #THREAD_CLF_SAVED_SHIFT .ifc \mode\(),fiq orr w1, w1, #THREAD_CLF_FIQ .else orr w1, w1, #THREAD_CLF_IRQ .endif orr w1, w1, #THREAD_CLF_TMP str w1, [sp, #THREAD_CORE_LOCAL_FLAGS] /* * Save registers on the temp stack that can be corrupted by a call * to a C function. * * Note that we're temporarily using x1 to access the temp stack * until we're ready to switch to sp_el0 and update sp. */ /* load tmp_stack_va_end */ ldr x1, [sp, #THREAD_CORE_LOCAL_TMP_STACK_VA_END] /* Make room for struct elx_nintr_rec */ sub x1, x1, #ELX_NINTR_REC_SIZE /* Store lr and original sp_el0 */ mrs x2, sp_el0 stp x30, x2, [x1, #ELX_NINTR_REC_LR] /* Store x4..x18 */ store_xregs x1, ELX_NINTR_REC_X(4), 4, 18 #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) read_apiakeyhi x2 read_apiakeylo x3 stp x2, x3, [x1, #ELX_NINTR_REG_APIAKEY_HI] #if defined(CFG_CORE_PAUTH) ldp x2, x3, [sp, #THREAD_CORE_LOCAL_KEYS] write_apiakeyhi x2 write_apiakeylo x3 #endif /* SCTLR or the APIA key has changed */ isb #endif /* Switch to SP_EL0 */ msr spsel, #0 mov sp, x1 bl thread_check_canaries bl interrupt_main_handler /* * Restore registers */ #if defined(CFG_TA_PAUTH) || defined(CFG_CORE_PAUTH) ldp x0, x1, [sp, #ELX_NINTR_REG_APIAKEY_HI] write_apiakeyhi x0 write_apiakeylo x1 #endif /* Restore x4..x18 */ load_xregs sp, ELX_NINTR_REC_X(4), 4, 18 /* Load lr and original sp_el0 */ ldp x30, x2, [sp, #ELX_NINTR_REC_LR] /* Restore SP_El0 */ mov sp, x2 /* Switch back to SP_EL1 */ msr spsel, #1 /* Update core local flags */ ldr w0, [sp, #THREAD_CORE_LOCAL_FLAGS] lsr w0, w0, #THREAD_CLF_SAVED_SHIFT str w0, [sp, #THREAD_CORE_LOCAL_FLAGS] mrs x0, spsr_el1 /* Restore x2..x3 */ load_xregs sp, THREAD_CORE_LOCAL_X2, 2, 3 b_if_spsr_is_el0 w0, 1f #if defined(CFG_CORE_PAUTH) /* APIA key has changed */ isb #endif /* Restore x0..x1 */ load_xregs sp, THREAD_CORE_LOCAL_X0, 0, 1 /* Return from exception */ return_from_exception 1: b eret_to_el0 .endm LOCAL_FUNC elx_irq , : #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) native_intr_handler irq #else foreign_intr_handler irq #endif END_FUNC elx_irq LOCAL_FUNC elx_fiq , : #if defined(CFG_CORE_IRQ_IS_NATIVE_INTR) foreign_intr_handler fiq #else native_intr_handler fiq #endif END_FUNC elx_fiq BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/thread_optee_smc.c000066400000000000000000000425221464416617300227310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2021, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static bool thread_prealloc_rpc_cache; static unsigned int thread_rpc_pnum; static_assert(NOTIF_VALUE_DO_BOTTOM_HALF == OPTEE_SMC_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF); void thread_handle_fast_smc(struct thread_smc_args *args) { thread_check_canaries(); if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(args->a7) && args->a7 != HYP_CLNT_ID) { args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; goto out; } tee_entry_fast(args); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); out: /* Fast handlers must not unmask any exceptions */ assert(thread_get_exceptions() == THREAD_EXCP_ALL); } uint32_t thread_handle_std_smc(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6 __unused, uint32_t a7 __maybe_unused) { uint32_t rv = OPTEE_SMC_RETURN_OK; thread_check_canaries(); if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(a7)) return OPTEE_SMC_RETURN_ENOTAVAIL; /* * thread_resume_from_rpc() and thread_alloc_and_run() only return * on error. Successful return is done via thread_exit() or * thread_rpc(). */ if (a0 == OPTEE_SMC_CALL_RETURN_FROM_RPC) { thread_resume_from_rpc(a3, a1, a2, a4, a5); rv = OPTEE_SMC_RETURN_ERESUME; } else { thread_alloc_and_run(a0, a1, a2, a3, 0, 0); rv = OPTEE_SMC_RETURN_ETHREAD_LIMIT; } if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); return rv; } /** * Free physical memory previously allocated with thread_rpc_alloc_arg() * * @cookie: cookie received when allocating the buffer */ static void thread_rpc_free_arg(uint64_t cookie) { if (cookie) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_FREE }; reg_pair_from_64(cookie, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); } } static uint32_t get_msg_arg(struct mobj *mobj, size_t offset, size_t *num_params, struct optee_msg_arg **arg, struct optee_msg_arg **rpc_arg) { void *p = NULL; size_t sz = 0; if (!mobj) return OPTEE_SMC_RETURN_EBADADDR; p = mobj_get_va(mobj, offset, sizeof(struct optee_msg_arg)); if (!p || !IS_ALIGNED_WITH_TYPE(p, struct optee_msg_arg)) return OPTEE_SMC_RETURN_EBADADDR; *arg = p; *num_params = READ_ONCE((*arg)->num_params); if (*num_params > OPTEE_MSG_MAX_NUM_PARAMS) return OPTEE_SMC_RETURN_EBADADDR; sz = OPTEE_MSG_GET_ARG_SIZE(*num_params); if (!mobj_get_va(mobj, offset, sz)) return OPTEE_SMC_RETURN_EBADADDR; if (rpc_arg) { size_t rpc_sz = 0; rpc_sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); p = mobj_get_va(mobj, offset + sz, rpc_sz); if (!p) return OPTEE_SMC_RETURN_EBADADDR; *rpc_arg = p; } return OPTEE_SMC_RETURN_OK; } static void clear_prealloc_rpc_cache(struct thread_ctx *thr) { thread_rpc_free_arg(mobj_get_cookie(thr->rpc_mobj)); mobj_put(thr->rpc_mobj); thr->rpc_arg = NULL; thr->rpc_mobj = NULL; } static uint32_t call_entry_std(struct optee_msg_arg *arg, size_t num_params, struct optee_msg_arg *rpc_arg) { struct thread_ctx *thr = threads + thread_get_id(); uint32_t rv = 0; if (rpc_arg) { /* * In case the prealloc RPC arg cache is enabled, clear the * cached object for this thread. * * Normally it doesn't make sense to have the prealloc RPC * arg cache enabled together with a supplied RPC arg * struct. But if it is we must use the supplied struct and * at the same time make sure to not break anything. */ if (IS_ENABLED(CFG_PREALLOC_RPC_CACHE) && thread_prealloc_rpc_cache) clear_prealloc_rpc_cache(thr); thr->rpc_arg = rpc_arg; } if (tee_entry_std(arg, num_params)) rv = OPTEE_SMC_RETURN_EBADCMD; else rv = OPTEE_SMC_RETURN_OK; thread_rpc_shm_cache_clear(&thr->shm_cache); if (rpc_arg) thr->rpc_arg = NULL; if (rv == OPTEE_SMC_RETURN_OK && !(IS_ENABLED(CFG_PREALLOC_RPC_CACHE) && thread_prealloc_rpc_cache)) clear_prealloc_rpc_cache(thr); return rv; } static uint32_t std_entry_with_parg(paddr_t parg, bool with_rpc_arg) { size_t sz = sizeof(struct optee_msg_arg); struct optee_msg_arg *rpc_arg = NULL; struct optee_msg_arg *arg = NULL; struct mobj *mobj = NULL; size_t num_params = 0; uint32_t rv = 0; /* Check if this region is in static shared space */ if (core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sz)) { if (!IS_ALIGNED_WITH_TYPE(parg, struct optee_msg_arg)) goto bad_addr; arg = phys_to_virt(parg, MEM_AREA_NSEC_SHM, sizeof(struct optee_msg_arg)); if (!arg) goto bad_addr; num_params = READ_ONCE(arg->num_params); if (num_params > OPTEE_MSG_MAX_NUM_PARAMS) return OPTEE_SMC_RETURN_EBADADDR; sz = OPTEE_MSG_GET_ARG_SIZE(num_params); if (with_rpc_arg) { rpc_arg = (void *)((uint8_t *)arg + sz); sz += OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); } if (!core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sz)) goto bad_addr; return call_entry_std(arg, num_params, rpc_arg); } else { if (parg & SMALL_PAGE_MASK) goto bad_addr; /* * mobj_mapped_shm_alloc checks if parg resides in nonsec * ddr. */ mobj = mobj_mapped_shm_alloc(&parg, 1, 0, 0); if (!mobj) goto bad_addr; if (with_rpc_arg) rv = get_msg_arg(mobj, 0, &num_params, &arg, &rpc_arg); else rv = get_msg_arg(mobj, 0, &num_params, &arg, NULL); if (!rv) rv = call_entry_std(arg, num_params, rpc_arg); mobj_put(mobj); return rv; } bad_addr: EMSG("Bad arg address 0x%"PRIxPA, parg); return OPTEE_SMC_RETURN_EBADADDR; } static uint32_t std_entry_with_regd_arg(uint64_t cookie, size_t offset) { struct optee_msg_arg *rpc_arg = NULL; struct optee_msg_arg *arg = NULL; size_t num_params = 0; struct mobj *mobj = NULL; uint32_t rv = 0; mobj = mobj_reg_shm_get_by_cookie(cookie); if (!mobj) { EMSG("Bad arg cookie 0x%"PRIx64, cookie); return OPTEE_SMC_RETURN_EBADADDR; } if (mobj_inc_map(mobj)) { rv = OPTEE_SMC_RETURN_ENOMEM; goto out; } rv = get_msg_arg(mobj, offset, &num_params, &arg, &rpc_arg); if (!rv) rv = call_entry_std(arg, num_params, rpc_arg); mobj_dec_map(mobj); out: mobj_put(mobj); return rv; } static uint32_t std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3 __unused) { const bool with_rpc_arg = true; switch (a0) { case OPTEE_SMC_CALL_WITH_ARG: return std_entry_with_parg(reg_pair_to_64(a1, a2), !with_rpc_arg); case OPTEE_SMC_CALL_WITH_RPC_ARG: return std_entry_with_parg(reg_pair_to_64(a1, a2), with_rpc_arg); case OPTEE_SMC_CALL_WITH_REGD_ARG: return std_entry_with_regd_arg(reg_pair_to_64(a1, a2), a3); default: EMSG("Unknown SMC 0x%"PRIx32, a0); return OPTEE_SMC_RETURN_EBADCMD; } } /* * Helper routine for the assembly function thread_std_smc_entry() * * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4 __unused, uint32_t a5 __unused) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_on_stdcall(); return std_smc_entry(a0, a1, a2, a3); } bool thread_disable_prealloc_rpc_cache(uint64_t *cookie) { bool rv = false; size_t n = 0; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); thread_lock_global(); for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].state != THREAD_STATE_FREE) { rv = false; goto out; } } rv = true; if (IS_ENABLED(CFG_PREALLOC_RPC_CACHE)) { for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].rpc_arg) { *cookie = mobj_get_cookie(threads[n].rpc_mobj); mobj_put(threads[n].rpc_mobj); threads[n].rpc_arg = NULL; threads[n].rpc_mobj = NULL; goto out; } } } *cookie = 0; thread_prealloc_rpc_cache = false; out: thread_unlock_global(); thread_unmask_exceptions(exceptions); return rv; } bool thread_enable_prealloc_rpc_cache(void) { bool rv = false; size_t n = 0; uint32_t exceptions = 0; if (!IS_ENABLED(CFG_PREALLOC_RPC_CACHE)) return true; exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); thread_lock_global(); for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].state != THREAD_STATE_FREE) { rv = false; goto out; } } rv = true; thread_prealloc_rpc_cache = true; out: thread_unlock_global(); thread_unmask_exceptions(exceptions); return rv; } static struct mobj *rpc_shm_mobj_alloc(paddr_t pa, size_t sz, uint64_t cookie) { /* Check if this region is in static shared space */ if (core_pbuf_is(CORE_MEM_NSEC_SHM, pa, sz)) return mobj_shm_alloc(pa, sz, cookie); if (IS_ENABLED(CFG_CORE_DYN_SHM) && !(pa & SMALL_PAGE_MASK) && sz <= SMALL_PAGE_SIZE) return mobj_mapped_shm_alloc(&pa, 1, 0, cookie); return NULL; } /** * Allocates data for struct optee_msg_arg. * * @size: size in bytes of struct optee_msg_arg * * @returns mobj that describes allocated buffer or NULL on error */ static struct mobj *thread_rpc_alloc_arg(size_t size) { paddr_t pa; uint64_t co; uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_ALLOC, size }; struct mobj *mobj = NULL; thread_rpc(rpc_args); /* Registers 1 and 2 passed from normal world */ pa = reg_pair_to_64(rpc_args[0], rpc_args[1]); /* Registers 4 and 5 passed from normal world */ co = reg_pair_to_64(rpc_args[2], rpc_args[3]); if (!IS_ALIGNED_WITH_TYPE(pa, struct optee_msg_arg)) goto err; mobj = rpc_shm_mobj_alloc(pa, size, co); if (!mobj) goto err; return mobj; err: thread_rpc_free_arg(co); mobj_put(mobj); return NULL; } static bool set_rmem(struct optee_msg_param *param, struct thread_param *tpm) { param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; param->u.rmem.offs = tpm->u.memref.offs; param->u.rmem.size = tpm->u.memref.size; if (tpm->u.memref.mobj) { param->u.rmem.shm_ref = mobj_get_cookie(tpm->u.memref.mobj); if (!param->u.rmem.shm_ref) return false; } else { param->u.rmem.shm_ref = 0; } return true; } static bool set_tmem(struct optee_msg_param *param, struct thread_param *tpm) { paddr_t pa = 0; uint64_t shm_ref = 0; struct mobj *mobj = tpm->u.memref.mobj; param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; if (mobj) { shm_ref = mobj_get_cookie(mobj); if (!shm_ref) return false; if (mobj_get_pa(mobj, tpm->u.memref.offs, 0, &pa)) return false; } param->u.tmem.size = tpm->u.memref.size; param->u.tmem.buf_ptr = pa; param->u.tmem.shm_ref = shm_ref; return true; } static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params, struct thread_param *params, void **arg_ret, uint64_t *carg_ret) { struct thread_ctx *thr = threads + thread_get_id(); struct optee_msg_arg *arg = thr->rpc_arg; size_t sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); if (num_params > THREAD_RPC_MAX_NUM_PARAMS) return TEE_ERROR_BAD_PARAMETERS; if (!arg) { struct mobj *mobj = thread_rpc_alloc_arg(sz); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; arg = mobj_get_va(mobj, 0, sz); if (!arg) { thread_rpc_free_arg(mobj_get_cookie(mobj)); return TEE_ERROR_OUT_OF_MEMORY; } thr->rpc_arg = arg; thr->rpc_mobj = mobj; } memset(arg, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); arg->cmd = cmd; arg->num_params = num_params; arg->ret = TEE_ERROR_GENERIC; /* in case value isn't updated */ for (size_t n = 0; n < num_params; n++) { switch (params[n].attr) { case THREAD_PARAM_ATTR_NONE: arg->params[n].attr = OPTEE_MSG_ATTR_TYPE_NONE; break; case THREAD_PARAM_ATTR_VALUE_IN: case THREAD_PARAM_ATTR_VALUE_OUT: case THREAD_PARAM_ATTR_VALUE_INOUT: arg->params[n].attr = params[n].attr - THREAD_PARAM_ATTR_VALUE_IN + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; arg->params[n].u.value.a = params[n].u.value.a; arg->params[n].u.value.b = params[n].u.value.b; arg->params[n].u.value.c = params[n].u.value.c; break; case THREAD_PARAM_ATTR_MEMREF_IN: case THREAD_PARAM_ATTR_MEMREF_OUT: case THREAD_PARAM_ATTR_MEMREF_INOUT: if (!params[n].u.memref.mobj || mobj_matches(params[n].u.memref.mobj, CORE_MEM_NSEC_SHM)) { if (!set_tmem(arg->params + n, params + n)) return TEE_ERROR_BAD_PARAMETERS; } else if (mobj_matches(params[n].u.memref.mobj, CORE_MEM_REG_SHM)) { if (!set_rmem(arg->params + n, params + n)) return TEE_ERROR_BAD_PARAMETERS; } else { return TEE_ERROR_BAD_PARAMETERS; } break; default: return TEE_ERROR_BAD_PARAMETERS; } } *arg_ret = arg; *carg_ret = mobj_get_cookie(thr->rpc_mobj); return TEE_SUCCESS; } static uint32_t get_rpc_arg_res(struct optee_msg_arg *arg, size_t num_params, struct thread_param *params) { for (size_t n = 0; n < num_params; n++) { switch (params[n].attr) { case THREAD_PARAM_ATTR_VALUE_OUT: case THREAD_PARAM_ATTR_VALUE_INOUT: params[n].u.value.a = arg->params[n].u.value.a; params[n].u.value.b = arg->params[n].u.value.b; params[n].u.value.c = arg->params[n].u.value.c; break; case THREAD_PARAM_ATTR_MEMREF_OUT: case THREAD_PARAM_ATTR_MEMREF_INOUT: /* * rmem.size and tmem.size is the same type and * location. */ params[n].u.memref.size = arg->params[n].u.rmem.size; break; default: break; } } return arg->ret; } uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, struct thread_param *params) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_CMD }; void *arg = NULL; uint64_t carg = 0; uint32_t ret = 0; /* The source CRYPTO_RNG_SRC_JITTER_RPC is safe to use here */ plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_RPC, &thread_rpc_pnum); ret = get_rpc_arg(cmd, num_params, params, &arg, &carg); if (ret) return ret; reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); return get_rpc_arg_res(arg, num_params, params); } /** * Free physical memory previously allocated with thread_rpc_alloc() * * @cookie: cookie received when allocating the buffer * @bt: must be the same as supplied when allocating * @mobj: mobj that describes allocated buffer * * This function also frees corresponding mobj. */ static void thread_rpc_free(unsigned int bt, uint64_t cookie, struct mobj *mobj) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_CMD }; void *arg = NULL; uint64_t carg = 0; struct thread_param param = THREAD_PARAM_VALUE(IN, bt, cookie, 0); uint32_t ret = get_rpc_arg(OPTEE_RPC_CMD_SHM_FREE, 1, ¶m, &arg, &carg); mobj_put(mobj); if (!ret) { reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); } } static struct mobj *get_rpc_alloc_res(struct optee_msg_arg *arg, unsigned int bt, size_t size) { struct mobj *mobj = NULL; uint64_t cookie = 0; size_t sz = 0; paddr_t p = 0; if (arg->ret || arg->num_params != 1) goto err; if (arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT && arg->params[0].attr != (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG)) goto err; p = arg->params[0].u.tmem.buf_ptr; sz = READ_ONCE(arg->params[0].u.tmem.size); cookie = arg->params[0].u.tmem.shm_ref; if (sz < size) goto err; if (arg->params[0].attr == OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT) mobj = rpc_shm_mobj_alloc(p, sz, cookie); else mobj = msg_param_mobj_from_noncontig(p, sz, cookie, true); if (!mobj) { thread_rpc_free(bt, cookie, mobj); goto err; } assert(mobj_is_nonsec(mobj)); return mobj; err: EMSG("RPC allocation failed. Non-secure world result: ret=%#" PRIx32" ret_origin=%#"PRIx32, arg->ret, arg->ret_origin); return NULL; } /** * Allocates shared memory buffer via RPC * * @size: size in bytes of shared memory buffer * @align: required alignment of buffer * @bt: buffer type OPTEE_RPC_SHM_TYPE_* * * Returns a pointer to MOBJ for the memory on success, or NULL on failure. */ static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_SMC_RETURN_RPC_CMD }; void *arg = NULL; uint64_t carg = 0; struct thread_param param = THREAD_PARAM_VALUE(IN, bt, size, align); uint32_t ret = get_rpc_arg(OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m, &arg, &carg); if (ret) return NULL; reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); return get_rpc_alloc_res(arg, bt, size); } struct mobj *thread_rpc_alloc_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_APPL); } struct mobj *thread_rpc_alloc_kernel_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); } void thread_rpc_free_kernel_payload(struct mobj *mobj) { if (mobj) thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); } void thread_rpc_free_payload(struct mobj *mobj) { if (mobj) thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), mobj); } struct mobj *thread_rpc_alloc_global_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_GLOBAL); } void thread_rpc_free_global_payload(struct mobj *mobj) { thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj), mobj); } optee_os-4.3.0/core/arch/arm/kernel/thread_optee_smc_a32.S000066400000000000000000000152711464416617300233570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include .arch_extension sec /* * If ASLR is configured the identity mapped code may be mapped at two * locations, the identity location where virtual and physical address is * the same and at the runtime selected location to which OP-TEE has been * relocated. Code executing at a location different compared to the * runtime selected location works OK as long as it doesn't do relative * addressing outside the identity mapped range. To allow relative * addressing this macro jumps to the runtime selected location. * * Note that the identity mapped range and the runtime selected range can * only differ if ASLR is configured. */ .macro readjust_pc #ifdef CFG_CORE_ASLR ldr r12, =1111f bx r12 1111: #endif .endm FUNC vector_std_smc_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc push {r4-r7} bl thread_handle_std_smc add sp, sp, #(4 * 4) /* * Normally thread_handle_std_smc() should return via * thread_exit(), thread_rpc(), but if thread_handle_std_smc() * hasn't switched stack (error detected) it will do a normal "C" * return. */ mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_std_smc_entry FUNC vector_fast_smc_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc push {r0-r7} mov r0, sp bl thread_handle_fast_smc pop {r1-r8} ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_fast_smc_entry FUNC vector_fiq_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc /* Secure Monitor received a FIQ and passed control to us. */ bl thread_check_canaries bl interrupt_main_handler ldr r0, =TEESMC_OPTEED_RETURN_FIQ_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_fiq_entry #if defined(CFG_WITH_ARM_TRUSTED_FW) LOCAL_FUNC vector_cpu_on_entry , : , .identity_map UNWIND( .cantunwind) bl cpu_on_handler /* When cpu_on_handler() returns mmu is enabled */ mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_ON_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_on_entry LOCAL_FUNC vector_cpu_off_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc bl thread_cpu_off_handler mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_OFF_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_off_entry LOCAL_FUNC vector_cpu_suspend_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc bl thread_cpu_suspend_handler mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_SUSPEND_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_suspend_entry LOCAL_FUNC vector_cpu_resume_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc bl thread_cpu_resume_handler mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_RESUME_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_resume_entry LOCAL_FUNC vector_system_off_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc bl thread_system_off_handler mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_system_off_entry LOCAL_FUNC vector_system_reset_entry , : , .identity_map UNWIND( .cantunwind) readjust_pc bl thread_system_reset_handler mov r1, r0 ldr r0, =TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_system_reset_entry /* * Vector table supplied to ARM Trusted Firmware (ARM-TF) at * initialization. Also used when compiled with the internal monitor, but * the cpu_*_entry and system_*_entry are not used then. * * Note that ARM-TF depends on the layout of this vector table, any change * in layout has to be synced with ARM-TF. */ FUNC thread_vector_table , : , .identity_map UNWIND( .cantunwind) b vector_std_smc_entry b vector_fast_smc_entry b vector_cpu_on_entry b vector_cpu_off_entry b vector_cpu_resume_entry b vector_cpu_suspend_entry b vector_fiq_entry b vector_system_off_entry b vector_system_reset_entry END_FUNC thread_vector_table DECLARE_KEEP_PAGER thread_vector_table #endif /*if defined(CFG_WITH_ARM_TRUSTED_FW)*/ FUNC thread_std_smc_entry , : UNWIND( .cantunwind) push {r4, r5} /* Pass these following the arm32 calling convention */ bl __thread_std_smc_entry add sp, sp, #8 /* There's nothing return, just restore the sp */ mov r4, r0 /* Save return value for later */ /* Disable interrupts before switching to temporary stack */ cpsid aif bl thread_get_tmp_sp mov sp, r0 bl thread_state_free ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE mov r1, r4 mov r2, #0 mov r3, #0 mov r4, #0 smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC thread_std_smc_entry /* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */ FUNC thread_rpc , : push {r0, lr} UNWIND( .save {r0, lr}) bl thread_save_state mov r4, r0 /* Save original CPSR */ /* * Switch to temporary stack and SVC mode. Save CPSR to resume into. */ bl thread_get_tmp_sp ldr r5, [sp] /* Get pointer to rv[] */ cps #CPSR_MODE_SVC /* Change to SVC mode */ mov sp, r0 /* Switch to tmp stack */ mov r0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN mov r1, r4 /* CPSR to restore */ ldr r2, =.thread_rpc_return bl thread_state_suspend mov r4, r0 /* Supply thread index */ ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE ldm r5, {r1-r3} /* Load rv[] into r0-r2 */ smc #0 /* SMC should not return */ panic_at_smc_return .thread_rpc_return: /* * At this point has the stack pointer been restored to the value * it had when thread_save_state() was called above. * * Jumps here from thread_resume above when RPC has returned. The * IRQ and FIQ bits are restored to what they where when this * function was originally entered. */ pop {r12, lr} /* Get pointer to rv[] */ stm r12, {r0-r3} /* Store r0-r3 into rv[] */ bx lr END_FUNC thread_rpc DECLARE_KEEP_PAGER thread_rpc /* * void thread_foreign_intr_exit(uint32_t thread_index) * * This function is jumped to at the end of macro foreign_intr_handler(). * The current thread as indicated by @thread_index has just been * suspended. The job here is just to inform normal world the thread id to * resume when returning. */ FUNC thread_foreign_intr_exit , : mov r4, r0 ldr r0, =TEESMC_OPTEED_RETURN_CALL_DONE ldr r1, =OPTEE_SMC_RETURN_RPC_FOREIGN_INTR mov r2, #0 mov r3, #0 smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC thread_foreign_intr_exit optee_os-4.3.0/core/arch/arm/kernel/thread_optee_smc_a64.S000066400000000000000000000154141464416617300233630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include /* * If ASLR is configured the identity mapped code may be mapped at two * locations, the identity location where virtual and physical address is * the same and at the runtime selected location to which OP-TEE has been * relocated. Code executing at a location different compared to the * runtime selected location works OK as long as it doesn't do relative * addressing outside the identity mapped range. To allow relative * addressing this macro jumps to the runtime selected location. * * Note that the identity mapped range and the runtime selected range can * only differ if ASLR is configured. */ .macro readjust_pc #ifdef CFG_CORE_ASLR adr x16, 1111f ldr x17, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET add x16, x16, x17 br x16 1111: BTI( bti j) #endif .endm LOCAL_FUNC vector_std_smc_entry , : , .identity_map readjust_pc bl thread_handle_std_smc /* * Normally thread_handle_std_smc() should return via * thread_exit(), thread_rpc(), but if thread_handle_std_smc() * hasn't switched stack (error detected) it will do a normal "C" * return. */ mov w1, w0 ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_std_smc_entry LOCAL_FUNC vector_fast_smc_entry , : , .identity_map readjust_pc sub sp, sp, #THREAD_SMC_ARGS_SIZE store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 mov x0, sp bl thread_handle_fast_smc load_xregs sp, THREAD_SMC_ARGS_X0, 1, 8 add sp, sp, #THREAD_SMC_ARGS_SIZE ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_fast_smc_entry LOCAL_FUNC vector_fiq_entry , : , .identity_map readjust_pc /* Secure Monitor received a FIQ and passed control to us. */ bl thread_check_canaries bl interrupt_main_handler ldr x0, =TEESMC_OPTEED_RETURN_FIQ_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_fiq_entry LOCAL_FUNC vector_cpu_on_entry , : , .identity_map bl cpu_on_handler mov x1, x0 ldr x0, =TEESMC_OPTEED_RETURN_ON_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_on_entry LOCAL_FUNC vector_cpu_off_entry , : , .identity_map readjust_pc bl thread_cpu_off_handler mov x1, x0 ldr x0, =TEESMC_OPTEED_RETURN_OFF_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_off_entry LOCAL_FUNC vector_cpu_suspend_entry , : , .identity_map readjust_pc bl thread_cpu_suspend_handler mov x1, x0 ldr x0, =TEESMC_OPTEED_RETURN_SUSPEND_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_suspend_entry LOCAL_FUNC vector_cpu_resume_entry , : , .identity_map readjust_pc bl thread_cpu_resume_handler mov x1, x0 ldr x0, =TEESMC_OPTEED_RETURN_RESUME_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_cpu_resume_entry LOCAL_FUNC vector_system_off_entry , : , .identity_map readjust_pc bl thread_system_off_handler mov x1, x0 ldr x0, =TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_system_off_entry LOCAL_FUNC vector_system_reset_entry , : , .identity_map readjust_pc bl thread_system_reset_handler mov x1, x0 ldr x0, =TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC vector_system_reset_entry /* * Vector table supplied to ARM Trusted Firmware (ARM-TF) at * initialization. * * Note that ARM-TF depends on the layout of this vector table, any change * in layout has to be synced with ARM-TF. */ FUNC thread_vector_table , : , .identity_map, , nobti b vector_std_smc_entry b vector_fast_smc_entry b vector_cpu_on_entry b vector_cpu_off_entry b vector_cpu_resume_entry b vector_cpu_suspend_entry b vector_fiq_entry b vector_system_off_entry b vector_system_reset_entry END_FUNC thread_vector_table DECLARE_KEEP_PAGER thread_vector_table FUNC thread_std_smc_entry , : bl __thread_std_smc_entry mov w20, w0 /* Save return value for later */ /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL bl thread_get_tmp_sp mov sp, x0 bl thread_state_free ldr x0, =TEESMC_OPTEED_RETURN_CALL_DONE mov w1, w20 mov x2, #0 mov x3, #0 mov x4, #0 smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC thread_std_smc_entry /* void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr) */ FUNC thread_rpc_spsr , : /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL push x0, xzr push x1, x30 bl thread_get_ctx_regs ldr x30, [sp, #8] store_xregs x0, THREAD_CTX_REGS_X19, 19, 30 mov x19, x0 #if defined(CFG_CORE_PAUTH) /* Save APIAKEY */ read_apiakeyhi x1 read_apiakeylo x2 store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 #endif bl thread_get_tmp_sp pop x1, xzr /* Match "push x1, x30" above */ mov x2, sp str x2, [x19, #THREAD_CTX_REGS_SP] ldr x20, [sp] /* Get pointer to rv[] */ mov sp, x0 /* Switch to tmp stack */ /* * We need to read rv[] early, because thread_state_suspend * can invoke virt_unset_guest() which will unmap pages, * where rv[] resides */ load_wregs x20, 0, 21, 23 /* Load rv[] into w20-w22 */ adr x2, .thread_rpc_return mov w0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN bl thread_state_suspend mov x4, x0 /* Supply thread index */ ldr w0, =TEESMC_OPTEED_RETURN_CALL_DONE mov x1, x21 mov x2, x22 mov x3, x23 smc #0 /* SMC should not return */ panic_at_smc_return .thread_rpc_return: /* * At this point has the stack pointer been restored to the value * stored in THREAD_CTX above. * * Jumps here from thread_resume above when RPC has returned. The * IRQ and FIQ bits are restored to what they where when this * function was originally entered. */ pop x16, xzr /* Get pointer to rv[] */ store_wregs x16, 0, 0, 3 /* Store w0-w3 into rv[] */ ret END_FUNC thread_rpc_spsr DECLARE_KEEP_PAGER thread_rpc_spsr /* * void thread_foreign_intr_exit(uint32_t thread_index) * * This function is jumped to at the end of macro foreign_intr_handler(). * The current thread as indicated by @thread_index has just been * suspended. The job here is just to inform normal world the thread id to * resume when returning. */ FUNC thread_foreign_intr_exit , : mov w4, w0 ldr w0, =TEESMC_OPTEED_RETURN_CALL_DONE ldr w1, =OPTEE_SMC_RETURN_RPC_FOREIGN_INTR mov w2, #0 mov w3, #0 smc #0 /* SMC should not return */ panic_at_smc_return END_FUNC thread_foreign_intr_exit BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/thread_spmc.c000066400000000000000000002023321464416617300217120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020-2023, Linaro Limited. * Copyright (c) 2019-2024, Arm Limited. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CFG_CORE_SEL1_SPMC) struct mem_share_state { struct mobj_ffa *mf; unsigned int page_count; unsigned int region_count; unsigned int current_page_idx; }; struct mem_frag_state { struct mem_share_state share; tee_mm_entry_t *mm; unsigned int frag_offset; SLIST_ENTRY(mem_frag_state) link; }; #endif struct notif_vm_bitmap { bool initialized; int do_bottom_half_value; uint64_t pending; uint64_t bound; }; static unsigned int spmc_notif_lock __nex_data = SPINLOCK_UNLOCK; static bool spmc_notif_is_ready __nex_bss; static int notif_intid __nex_data __maybe_unused = -1; /* Id used to look up the guest specific struct notif_vm_bitmap */ static unsigned int notif_vm_bitmap_id __nex_bss; /* Notification state when ns-virtualization isn't enabled */ static struct notif_vm_bitmap default_notif_vm_bitmap; /* Initialized in spmc_init() below */ uint16_t optee_endpoint_id __nex_bss; uint16_t spmc_id __nex_bss; #ifdef CFG_CORE_SEL1_SPMC uint16_t spmd_id __nex_bss; static const uint32_t my_part_props = FFA_PART_PROP_DIRECT_REQ_RECV | FFA_PART_PROP_DIRECT_REQ_SEND | #ifdef CFG_NS_VIRTUALIZATION FFA_PART_PROP_NOTIF_CREATED | FFA_PART_PROP_NOTIF_DESTROYED | #endif #ifdef ARM64 FFA_PART_PROP_AARCH64_STATE | #endif FFA_PART_PROP_IS_PE_ID; static uint32_t my_uuid_words[] = { /* * - if the SPMC is in S-EL2 this UUID describes OP-TEE as a S-EL1 * SP, or * - if the SPMC is in S-EL1 then this UUID is for OP-TEE as a * logical partition, residing in the same exception level as the * SPMC * UUID 486178e0-e7f8-11e3-bc5e-0002a5d5c51b */ 0xe0786148, 0xe311f8e7, 0x02005ebc, 0x1bc5d5a5, }; /* * If struct ffa_rxtx::size is 0 RX/TX buffers are not mapped or initialized. * * struct ffa_rxtx::spin_lock protects the variables below from concurrent * access this includes the use of content of struct ffa_rxtx::rx and * @frag_state_head. * * struct ffa_rxtx::tx_buf_is_mine is true when we may write to struct * ffa_rxtx::tx and false when it is owned by normal world. * * Note that we can't prevent normal world from updating the content of * these buffers so we must always be careful when reading. while we hold * the lock. */ static struct ffa_rxtx my_rxtx __nex_bss; static bool is_nw_buf(struct ffa_rxtx *rxtx) { return rxtx == &my_rxtx; } static SLIST_HEAD(mem_frag_state_head, mem_frag_state) frag_state_head = SLIST_HEAD_INITIALIZER(&frag_state_head); #else static uint8_t __rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE); static uint8_t __tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE); static struct ffa_rxtx my_rxtx = { .rx = __rx_buf, .tx = __tx_buf, .size = sizeof(__rx_buf), }; #endif static uint32_t swap_src_dst(uint32_t src_dst) { return (src_dst >> 16) | (src_dst << 16); } static uint16_t get_sender_id(uint32_t src_dst) { return src_dst >> 16; } void spmc_set_args(struct thread_smc_args *args, uint32_t fid, uint32_t src_dst, uint32_t w2, uint32_t w3, uint32_t w4, uint32_t w5) { *args = (struct thread_smc_args){ .a0 = fid, .a1 = src_dst, .a2 = w2, .a3 = w3, .a4 = w4, .a5 = w5, }; } static void set_simple_ret_val(struct thread_smc_args *args, int ffa_ret) { if (ffa_ret) spmc_set_args(args, FFA_ERROR, 0, ffa_ret, 0, 0, 0); else spmc_set_args(args, FFA_SUCCESS_32, 0, 0, 0, 0, 0); } uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx) { /* * No locking, if the caller does concurrent calls to this it's * only making a mess for itself. We must be able to renegotiate * the FF-A version in order to support differing versions between * the loader and the driver. */ if (vers < FFA_VERSION_1_1) rxtx->ffa_vers = FFA_VERSION_1_0; else rxtx->ffa_vers = FFA_VERSION_1_1; return rxtx->ffa_vers; } static bool is_ffa_success(uint32_t fid) { #ifdef ARM64 if (fid == FFA_SUCCESS_64) return true; #endif return fid == FFA_SUCCESS_32; } static int32_t get_ffa_ret_code(const struct thread_smc_args *args) { if (is_ffa_success(args->a0)) return FFA_OK; if (args->a0 == FFA_ERROR && args->a2) return args->a2; return FFA_NOT_SUPPORTED; } static int ffa_simple_call(uint32_t fid, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4) { struct thread_smc_args args = { .a0 = fid, .a1 = a1, .a2 = a2, .a3 = a3, .a4 = a4, }; thread_smccc(&args); return get_ffa_ret_code(&args); } static int __maybe_unused ffa_features(uint32_t id) { return ffa_simple_call(FFA_FEATURES, id, 0, 0, 0); } static int __maybe_unused ffa_set_notification(uint16_t dst, uint16_t src, uint32_t flags, uint64_t bitmap) { return ffa_simple_call(FFA_NOTIFICATION_SET, SHIFT_U32(src, 16) | dst, flags, low32_from_64(bitmap), high32_from_64(bitmap)); } #if defined(CFG_CORE_SEL1_SPMC) static void handle_features(struct thread_smc_args *args) { uint32_t ret_fid = FFA_ERROR; uint32_t ret_w2 = FFA_NOT_SUPPORTED; switch (args->a1) { case FFA_FEATURE_SCHEDULE_RECV_INTR: if (spmc_notif_is_ready) { ret_fid = FFA_SUCCESS_32; ret_w2 = notif_intid; } break; #ifdef ARM64 case FFA_RXTX_MAP_64: #endif case FFA_RXTX_MAP_32: ret_fid = FFA_SUCCESS_32; ret_w2 = 0; /* 4kB Minimum buffer size and alignment boundary */ break; #ifdef ARM64 case FFA_MEM_SHARE_64: #endif case FFA_MEM_SHARE_32: ret_fid = FFA_SUCCESS_32; /* * Partition manager supports transmission of a memory * transaction descriptor in a buffer dynamically allocated * by the endpoint. */ ret_w2 = BIT(0); break; case FFA_ERROR: case FFA_VERSION: case FFA_SUCCESS_32: #ifdef ARM64 case FFA_SUCCESS_64: #endif case FFA_FEATURES: case FFA_SPM_ID_GET: case FFA_MEM_FRAG_TX: case FFA_MEM_RECLAIM: case FFA_MSG_SEND_DIRECT_REQ_64: case FFA_MSG_SEND_DIRECT_REQ_32: case FFA_INTERRUPT: case FFA_PARTITION_INFO_GET: case FFA_RXTX_UNMAP: case FFA_RX_RELEASE: case FFA_FEATURE_MANAGED_EXIT_INTR: case FFA_NOTIFICATION_BITMAP_CREATE: case FFA_NOTIFICATION_BITMAP_DESTROY: case FFA_NOTIFICATION_BIND: case FFA_NOTIFICATION_UNBIND: case FFA_NOTIFICATION_SET: case FFA_NOTIFICATION_GET: case FFA_NOTIFICATION_INFO_GET_32: #ifdef ARM64 case FFA_NOTIFICATION_INFO_GET_64: #endif ret_fid = FFA_SUCCESS_32; ret_w2 = FFA_PARAM_MBZ; break; default: break; } spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, ret_w2, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static int map_buf(paddr_t pa, unsigned int sz, void **va_ret) { tee_mm_entry_t *mm = NULL; if (!core_pbuf_is(CORE_MEM_NON_SEC, pa, sz)) return FFA_INVALID_PARAMETERS; mm = tee_mm_alloc(&core_virt_shm_pool, sz); if (!mm) return FFA_NO_MEMORY; if (core_mmu_map_contiguous_pages(tee_mm_get_smem(mm), pa, sz / SMALL_PAGE_SIZE, MEM_AREA_NSEC_SHM)) { tee_mm_free(mm); return FFA_INVALID_PARAMETERS; } *va_ret = (void *)tee_mm_get_smem(mm); return 0; } void spmc_handle_spm_id_get(struct thread_smc_args *args) { spmc_set_args(args, FFA_SUCCESS_32, FFA_PARAM_MBZ, spmc_id, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static void unmap_buf(void *va, size_t sz) { tee_mm_entry_t *mm = tee_mm_find(&core_virt_shm_pool, (vaddr_t)va); assert(mm); core_mmu_unmap_pages(tee_mm_get_smem(mm), sz / SMALL_PAGE_SIZE); tee_mm_free(mm); } void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { int rc = 0; unsigned int sz = 0; paddr_t rx_pa = 0; paddr_t tx_pa = 0; void *rx = NULL; void *tx = NULL; cpu_spin_lock(&rxtx->spinlock); if (args->a3 & GENMASK_64(63, 6)) { rc = FFA_INVALID_PARAMETERS; goto out; } sz = args->a3 * SMALL_PAGE_SIZE; if (!sz) { rc = FFA_INVALID_PARAMETERS; goto out; } /* TX/RX are swapped compared to the caller */ tx_pa = args->a2; rx_pa = args->a1; if (rxtx->size) { rc = FFA_DENIED; goto out; } /* * If the buffer comes from a SP the address is virtual and already * mapped. */ if (is_nw_buf(rxtx)) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { enum teecore_memtypes mt = MEM_AREA_NEX_NSEC_SHM; bool tx_alloced = false; /* * With virtualization we establish this mapping in * the nexus mapping which then is replicated to * each partition. * * This means that this mapping must be done before * any partition is created and then must not be * changed. */ /* * core_mmu_add_mapping() may reuse previous * mappings. First check if there's any mappings to * reuse so we know how to clean up in case of * failure. */ tx = phys_to_virt(tx_pa, mt, sz); rx = phys_to_virt(rx_pa, mt, sz); if (!tx) { tx = core_mmu_add_mapping(mt, tx_pa, sz); if (!tx) { rc = FFA_NO_MEMORY; goto out; } tx_alloced = true; } if (!rx) rx = core_mmu_add_mapping(mt, rx_pa, sz); if (!rx) { if (tx_alloced && tx) core_mmu_remove_mapping(mt, tx, sz); rc = FFA_NO_MEMORY; goto out; } } else { rc = map_buf(tx_pa, sz, &tx); if (rc) goto out; rc = map_buf(rx_pa, sz, &rx); if (rc) { unmap_buf(tx, sz); goto out; } } rxtx->tx = tx; rxtx->rx = rx; } else { if ((tx_pa & SMALL_PAGE_MASK) || (rx_pa & SMALL_PAGE_MASK)) { rc = FFA_INVALID_PARAMETERS; goto out; } if (!virt_to_phys((void *)tx_pa) || !virt_to_phys((void *)rx_pa)) { rc = FFA_INVALID_PARAMETERS; goto out; } rxtx->tx = (void *)tx_pa; rxtx->rx = (void *)rx_pa; } rxtx->size = sz; rxtx->tx_is_mine = true; DMSG("Mapped tx %#"PRIxPA" size %#x @ %p", tx_pa, sz, tx); DMSG("Mapped rx %#"PRIxPA" size %#x @ %p", rx_pa, sz, rx); out: cpu_spin_unlock(&rxtx->spinlock); set_simple_ret_val(args, rc); } void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { int rc = FFA_INVALID_PARAMETERS; cpu_spin_lock(&rxtx->spinlock); if (!rxtx->size) goto out; /* * We don't unmap the SP memory as the SP might still use it. * We avoid to make changes to nexus mappings at this stage since * there currently isn't a way to replicate those changes to all * partitions. */ if (is_nw_buf(rxtx) && !IS_ENABLED(CFG_NS_VIRTUALIZATION)) { unmap_buf(rxtx->rx, rxtx->size); unmap_buf(rxtx->tx, rxtx->size); } rxtx->size = 0; rxtx->rx = NULL; rxtx->tx = NULL; rc = 0; out: cpu_spin_unlock(&rxtx->spinlock); set_simple_ret_val(args, rc); } void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { int rc = 0; cpu_spin_lock(&rxtx->spinlock); /* The senders RX is our TX */ if (!rxtx->size || rxtx->tx_is_mine) { rc = FFA_DENIED; } else { rc = 0; rxtx->tx_is_mine = true; } cpu_spin_unlock(&rxtx->spinlock); set_simple_ret_val(args, rc); } static bool is_nil_uuid(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3) { return !w0 && !w1 && !w2 && !w3; } static bool is_my_uuid(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3) { /* * This depends on which UUID we have been assigned. * TODO add a generic mechanism to obtain our UUID. * * The test below is for the hard coded UUID * 486178e0-e7f8-11e3-bc5e-0002a5d5c51b */ return w0 == my_uuid_words[0] && w1 == my_uuid_words[1] && w2 == my_uuid_words[2] && w3 == my_uuid_words[3]; } TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen, size_t idx, uint16_t endpoint_id, uint16_t execution_context, uint32_t part_props, const uint32_t uuid_words[4]) { struct ffa_partition_info_x *fpi = NULL; size_t fpi_size = sizeof(*fpi); if (ffa_vers >= FFA_VERSION_1_1) fpi_size += FFA_UUID_SIZE; if ((idx + 1) * fpi_size > blen) return TEE_ERROR_OUT_OF_MEMORY; fpi = (void *)((vaddr_t)buf + idx * fpi_size); fpi->id = endpoint_id; /* Number of execution contexts implemented by this partition */ fpi->execution_context = execution_context; fpi->partition_properties = part_props; if (ffa_vers >= FFA_VERSION_1_1) { if (uuid_words) memcpy(fpi->uuid, uuid_words, FFA_UUID_SIZE); else memset(fpi->uuid, 0, FFA_UUID_SIZE); } return TEE_SUCCESS; } static int handle_partition_info_get_all(size_t *elem_count, struct ffa_rxtx *rxtx, bool count_only) { if (!count_only) { /* Add OP-TEE SP */ if (spmc_fill_partition_entry(rxtx->ffa_vers, rxtx->tx, rxtx->size, 0, optee_endpoint_id, CFG_TEE_CORE_NB_CORE, my_part_props, my_uuid_words)) return FFA_NO_MEMORY; } *elem_count = 1; if (IS_ENABLED(CFG_SECURE_PARTITION)) { if (sp_partition_info_get(rxtx->ffa_vers, rxtx->tx, rxtx->size, NULL, elem_count, count_only)) return FFA_NO_MEMORY; } return FFA_OK; } void spmc_handle_partition_info_get(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { TEE_Result res = TEE_SUCCESS; uint32_t ret_fid = FFA_ERROR; uint32_t fpi_size = 0; uint32_t rc = 0; bool count_only = args->a5 & FFA_PARTITION_INFO_GET_COUNT_FLAG; if (!count_only) { cpu_spin_lock(&rxtx->spinlock); if (!rxtx->size || !rxtx->tx_is_mine) { rc = FFA_BUSY; goto out; } } if (is_nil_uuid(args->a1, args->a2, args->a3, args->a4)) { size_t elem_count = 0; ret_fid = handle_partition_info_get_all(&elem_count, rxtx, count_only); if (ret_fid) { rc = ret_fid; ret_fid = FFA_ERROR; } else { ret_fid = FFA_SUCCESS_32; rc = elem_count; } goto out; } if (is_my_uuid(args->a1, args->a2, args->a3, args->a4)) { if (!count_only) { res = spmc_fill_partition_entry(rxtx->ffa_vers, rxtx->tx, rxtx->size, 0, optee_endpoint_id, CFG_TEE_CORE_NB_CORE, my_part_props, my_uuid_words); if (res) { ret_fid = FFA_ERROR; rc = FFA_INVALID_PARAMETERS; goto out; } } rc = 1; } else if (IS_ENABLED(CFG_SECURE_PARTITION)) { uint32_t uuid_array[4] = { 0 }; TEE_UUID uuid = { }; size_t count = 0; uuid_array[0] = args->a1; uuid_array[1] = args->a2; uuid_array[2] = args->a3; uuid_array[3] = args->a4; tee_uuid_from_octets(&uuid, (uint8_t *)uuid_array); res = sp_partition_info_get(rxtx->ffa_vers, rxtx->tx, rxtx->size, &uuid, &count, count_only); if (res != TEE_SUCCESS) { ret_fid = FFA_ERROR; rc = FFA_INVALID_PARAMETERS; goto out; } rc = count; } else { ret_fid = FFA_ERROR; rc = FFA_INVALID_PARAMETERS; goto out; } ret_fid = FFA_SUCCESS_32; out: if (ret_fid == FFA_SUCCESS_32 && !count_only && rxtx->ffa_vers >= FFA_VERSION_1_1) fpi_size = sizeof(struct ffa_partition_info_x) + FFA_UUID_SIZE; spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, fpi_size, FFA_PARAM_MBZ, FFA_PARAM_MBZ); if (!count_only) { rxtx->tx_is_mine = false; cpu_spin_unlock(&rxtx->spinlock); } } static void spmc_handle_run(struct thread_smc_args *args) { uint16_t endpoint = FFA_TARGET_INFO_GET_SP_ID(args->a1); uint16_t thread_id = FFA_TARGET_INFO_GET_VCPU_ID(args->a1); uint32_t rc = FFA_OK; if (endpoint != optee_endpoint_id) { /* * The endpoint should be an SP, try to resume the SP from * preempted into busy state. */ rc = spmc_sp_resume_from_preempted(endpoint); if (rc) goto out; } thread_resume_from_rpc(thread_id, 0, 0, 0, 0); /* thread_resume_from_rpc return only of the thread_id is invalid */ rc = FFA_INVALID_PARAMETERS; out: set_simple_ret_val(args, rc); } #endif /*CFG_CORE_SEL1_SPMC*/ static struct notif_vm_bitmap *get_notif_vm_bitmap(struct guest_partition *prtn, uint16_t vm_id) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { if (!prtn) return NULL; assert(vm_id == virt_get_guest_id(prtn)); return virt_get_guest_spec_data(prtn, notif_vm_bitmap_id); } if (vm_id) return NULL; return &default_notif_vm_bitmap; } static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value, uint16_t vm_id) { struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint32_t old_itr_status = 0; uint32_t res = 0; if (!spmc_notif_is_ready) { /* * This should never happen, not if normal world respects the * exchanged capabilities. */ EMSG("Asynchronous notifications are not ready"); return TEE_ERROR_NOT_IMPLEMENTED; } if (bottom_half_value >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE) { EMSG("Invalid bottom half value %"PRIu32, bottom_half_value); return TEE_ERROR_BAD_PARAMETERS; } prtn = virt_get_guest(vm_id); nvb = get_notif_vm_bitmap(prtn, vm_id); if (!nvb) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); nvb->do_bottom_half_value = bottom_half_value; cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); notif_deliver_atomic_event(NOTIF_EVENT_STARTED, vm_id); res = TEE_SUCCESS; out: virt_put_guest(prtn); return res; } static void handle_yielding_call(struct thread_smc_args *args, uint32_t direct_resp_fid) { TEE_Result res = 0; thread_check_canaries(); #ifdef ARM64 /* Saving this for an eventual RPC */ thread_get_core_local()->direct_resp_fid = direct_resp_fid; #endif if (args->a3 == OPTEE_FFA_YIELDING_CALL_RESUME) { /* Note connection to struct thread_rpc_arg::ret */ thread_resume_from_rpc(args->a7, args->a4, args->a5, args->a6, 0); res = TEE_ERROR_BAD_PARAMETERS; } else { thread_alloc_and_run(args->a1, args->a3, args->a4, args->a5, args->a6, args->a7); res = TEE_ERROR_BUSY; } spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, res, 0, 0); } static uint32_t handle_unregister_shm(uint32_t a4, uint32_t a5) { uint64_t cookie = reg_pair_to_64(a5, a4); uint32_t res = 0; res = mobj_ffa_unregister_by_cookie(cookie); switch (res) { case TEE_SUCCESS: case TEE_ERROR_ITEM_NOT_FOUND: return 0; case TEE_ERROR_BUSY: EMSG("res %#"PRIx32, res); return FFA_BUSY; default: EMSG("res %#"PRIx32, res); return FFA_INVALID_PARAMETERS; } } static void handle_blocking_call(struct thread_smc_args *args, uint32_t direct_resp_fid) { uint32_t sec_caps = 0; switch (args->a3) { case OPTEE_FFA_GET_API_VERSION: spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, OPTEE_FFA_VERSION_MAJOR, OPTEE_FFA_VERSION_MINOR, 0); break; case OPTEE_FFA_GET_OS_VERSION: spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, CFG_OPTEE_REVISION_MAJOR, CFG_OPTEE_REVISION_MINOR, TEE_IMPL_GIT_SHA1 >> 32); break; case OPTEE_FFA_EXCHANGE_CAPABILITIES: sec_caps = OPTEE_FFA_SEC_CAP_ARG_OFFSET; if (spmc_notif_is_ready) sec_caps |= OPTEE_FFA_SEC_CAP_ASYNC_NOTIF; spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, 0, THREAD_RPC_MAX_NUM_PARAMS, sec_caps); break; case OPTEE_FFA_UNREGISTER_SHM: spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, handle_unregister_shm(args->a4, args->a5), 0, 0); break; case OPTEE_FFA_ENABLE_ASYNC_NOTIF: spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, spmc_enable_async_notif(args->a4, FFA_SRC(args->a1)), 0, 0); break; default: EMSG("Unhandled blocking service ID %#"PRIx32, (uint32_t)args->a3); spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, TEE_ERROR_BAD_PARAMETERS, 0, 0); } } static void handle_framework_direct_request(struct thread_smc_args *args, struct ffa_rxtx *rxtx, uint32_t direct_resp_fid) { uint32_t w0 = FFA_ERROR; uint32_t w1 = FFA_PARAM_MBZ; uint32_t w2 = FFA_NOT_SUPPORTED; uint32_t w3 = FFA_PARAM_MBZ; switch (args->a2 & FFA_MSG_TYPE_MASK) { case FFA_MSG_SEND_VM_CREATED: if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { uint16_t guest_id = args->a5; TEE_Result res = virt_guest_created(guest_id); w0 = direct_resp_fid; w1 = swap_src_dst(args->a1); w2 = FFA_MSG_FLAG_FRAMEWORK | FFA_MSG_RESP_VM_CREATED; if (res == TEE_SUCCESS) w3 = FFA_OK; else if (res == TEE_ERROR_OUT_OF_MEMORY) w3 = FFA_DENIED; else w3 = FFA_INVALID_PARAMETERS; } break; case FFA_MSG_SEND_VM_DESTROYED: if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { uint16_t guest_id = args->a5; TEE_Result res = virt_guest_destroyed(guest_id); w0 = direct_resp_fid; w1 = swap_src_dst(args->a1); w2 = FFA_MSG_FLAG_FRAMEWORK | FFA_MSG_RESP_VM_DESTROYED; if (res == TEE_SUCCESS) w3 = FFA_OK; else w3 = FFA_INVALID_PARAMETERS; } break; case FFA_MSG_VERSION_REQ: w0 = direct_resp_fid; w1 = swap_src_dst(args->a1); w2 = FFA_MSG_FLAG_FRAMEWORK | FFA_MSG_VERSION_RESP; w3 = spmc_exchange_version(args->a3, rxtx); break; default: break; } spmc_set_args(args, w0, w1, w2, w3, FFA_PARAM_MBZ, FFA_PARAM_MBZ); } static void handle_direct_request(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { uint32_t direct_resp_fid = 0; if (IS_ENABLED(CFG_SECURE_PARTITION) && FFA_DST(args->a1) != spmc_id && FFA_DST(args->a1) != optee_endpoint_id) { spmc_sp_start_thread(args); return; } if (OPTEE_SMC_IS_64(args->a0)) direct_resp_fid = FFA_MSG_SEND_DIRECT_RESP_64; else direct_resp_fid = FFA_MSG_SEND_DIRECT_RESP_32; if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) { handle_framework_direct_request(args, rxtx, direct_resp_fid); return; } if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(get_sender_id(args->a1))) { spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0, TEE_ERROR_ITEM_NOT_FOUND, 0, 0); return; } if (args->a3 & BIT32(OPTEE_FFA_YIELDING_CALL_BIT)) handle_yielding_call(args, direct_resp_fid); else handle_blocking_call(args, direct_resp_fid); /* * Note that handle_yielding_call() typically only returns if a * thread cannot be allocated or found. virt_unset_guest() is also * called from thread_state_suspend() and thread_state_free(). */ if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); } int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen, struct ffa_mem_transaction_x *trans) { uint16_t mem_reg_attr = 0; uint32_t flags = 0; uint32_t count = 0; uint32_t offs = 0; uint32_t size = 0; size_t n = 0; if (!IS_ALIGNED_WITH_TYPE(buf, uint64_t)) return FFA_INVALID_PARAMETERS; if (ffa_vers >= FFA_VERSION_1_1) { struct ffa_mem_transaction_1_1 *descr = NULL; if (blen < sizeof(*descr)) return FFA_INVALID_PARAMETERS; descr = buf; trans->sender_id = READ_ONCE(descr->sender_id); mem_reg_attr = READ_ONCE(descr->mem_reg_attr); flags = READ_ONCE(descr->flags); trans->global_handle = READ_ONCE(descr->global_handle); trans->tag = READ_ONCE(descr->tag); count = READ_ONCE(descr->mem_access_count); size = READ_ONCE(descr->mem_access_size); offs = READ_ONCE(descr->mem_access_offs); } else { struct ffa_mem_transaction_1_0 *descr = NULL; if (blen < sizeof(*descr)) return FFA_INVALID_PARAMETERS; descr = buf; trans->sender_id = READ_ONCE(descr->sender_id); mem_reg_attr = READ_ONCE(descr->mem_reg_attr); flags = READ_ONCE(descr->flags); trans->global_handle = READ_ONCE(descr->global_handle); trans->tag = READ_ONCE(descr->tag); count = READ_ONCE(descr->mem_access_count); size = sizeof(struct ffa_mem_access); offs = offsetof(struct ffa_mem_transaction_1_0, mem_access_array); } if (mem_reg_attr > UINT8_MAX || flags > UINT8_MAX || size > UINT8_MAX || count > UINT8_MAX || offs > UINT16_MAX) return FFA_INVALID_PARAMETERS; /* Check that the endpoint memory access descriptor array fits */ if (MUL_OVERFLOW(size, count, &n) || ADD_OVERFLOW(offs, n, &n) || n > blen) return FFA_INVALID_PARAMETERS; trans->mem_reg_attr = mem_reg_attr; trans->flags = flags; trans->mem_access_size = size; trans->mem_access_count = count; trans->mem_access_offs = offs; return 0; } #if defined(CFG_CORE_SEL1_SPMC) static int get_acc_perms(vaddr_t mem_acc_base, unsigned int mem_access_size, unsigned int mem_access_count, uint8_t *acc_perms, unsigned int *region_offs) { struct ffa_mem_access_perm *descr = NULL; struct ffa_mem_access *mem_acc = NULL; unsigned int n = 0; for (n = 0; n < mem_access_count; n++) { mem_acc = (void *)(mem_acc_base + mem_access_size * n); descr = &mem_acc->access_perm; if (READ_ONCE(descr->endpoint_id) == optee_endpoint_id) { *acc_perms = READ_ONCE(descr->perm); *region_offs = READ_ONCE(mem_acc[n].region_offs); return 0; } } return FFA_INVALID_PARAMETERS; } static int mem_share_init(struct ffa_mem_transaction_x *mem_trans, void *buf, size_t blen, unsigned int *page_count, unsigned int *region_count, size_t *addr_range_offs) { const uint16_t exp_mem_reg_attr = FFA_NORMAL_MEM_REG_ATTR; const uint8_t exp_mem_acc_perm = FFA_MEM_ACC_RW; struct ffa_mem_region *region_descr = NULL; unsigned int region_descr_offs = 0; uint8_t mem_acc_perm = 0; size_t n = 0; if (mem_trans->mem_reg_attr != exp_mem_reg_attr) return FFA_INVALID_PARAMETERS; /* Check that the access permissions matches what's expected */ if (get_acc_perms((vaddr_t)buf + mem_trans->mem_access_offs, mem_trans->mem_access_size, mem_trans->mem_access_count, &mem_acc_perm, ®ion_descr_offs) || mem_acc_perm != exp_mem_acc_perm) return FFA_INVALID_PARAMETERS; /* Check that the Composite memory region descriptor fits */ if (ADD_OVERFLOW(region_descr_offs, sizeof(*region_descr), &n) || n > blen) return FFA_INVALID_PARAMETERS; if (!IS_ALIGNED_WITH_TYPE((vaddr_t)buf + region_descr_offs, struct ffa_mem_region)) return FFA_INVALID_PARAMETERS; region_descr = (struct ffa_mem_region *)((vaddr_t)buf + region_descr_offs); *page_count = READ_ONCE(region_descr->total_page_count); *region_count = READ_ONCE(region_descr->address_range_count); *addr_range_offs = n; return 0; } static int add_mem_share_helper(struct mem_share_state *s, void *buf, size_t flen) { unsigned int region_count = flen / sizeof(struct ffa_address_range); struct ffa_address_range *arange = NULL; unsigned int n = 0; if (region_count > s->region_count) region_count = s->region_count; if (!IS_ALIGNED_WITH_TYPE(buf, struct ffa_address_range)) return FFA_INVALID_PARAMETERS; arange = buf; for (n = 0; n < region_count; n++) { unsigned int page_count = READ_ONCE(arange[n].page_count); uint64_t addr = READ_ONCE(arange[n].address); if (mobj_ffa_add_pages_at(s->mf, &s->current_page_idx, addr, page_count)) return FFA_INVALID_PARAMETERS; } s->region_count -= region_count; if (s->region_count) return region_count * sizeof(*arange); if (s->current_page_idx != s->page_count) return FFA_INVALID_PARAMETERS; return 0; } static int add_mem_share_frag(struct mem_frag_state *s, void *buf, size_t flen) { int rc = 0; rc = add_mem_share_helper(&s->share, buf, flen); if (rc >= 0) { if (!ADD_OVERFLOW(s->frag_offset, rc, &s->frag_offset)) { /* We're not at the end of the descriptor yet */ if (s->share.region_count) return s->frag_offset; /* We're done */ rc = 0; } else { rc = FFA_INVALID_PARAMETERS; } } SLIST_REMOVE(&frag_state_head, s, mem_frag_state, link); if (rc < 0) mobj_ffa_sel1_spmc_delete(s->share.mf); else mobj_ffa_push_to_inactive(s->share.mf); free(s); return rc; } static bool is_sp_share(struct ffa_mem_transaction_x *mem_trans, void *buf) { struct ffa_mem_access_perm *perm = NULL; struct ffa_mem_access *mem_acc = NULL; if (!IS_ENABLED(CFG_SECURE_PARTITION)) return false; if (mem_trans->mem_access_count < 1) return false; mem_acc = (void *)((vaddr_t)buf + mem_trans->mem_access_offs); perm = &mem_acc->access_perm; /* * perm->endpoint_id is read here only to check if the endpoint is * OP-TEE. We do read it later on again, but there are some additional * checks there to make sure that the data is correct. */ return READ_ONCE(perm->endpoint_id) != optee_endpoint_id; } static int add_mem_share(struct ffa_mem_transaction_x *mem_trans, tee_mm_entry_t *mm, void *buf, size_t blen, size_t flen, uint64_t *global_handle) { int rc = 0; struct mem_share_state share = { }; size_t addr_range_offs = 0; uint64_t cookie = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; size_t n = 0; rc = mem_share_init(mem_trans, buf, flen, &share.page_count, &share.region_count, &addr_range_offs); if (rc) return rc; if (!share.page_count || !share.region_count) return FFA_INVALID_PARAMETERS; if (MUL_OVERFLOW(share.region_count, sizeof(struct ffa_address_range), &n) || ADD_OVERFLOW(n, addr_range_offs, &n) || n > blen) return FFA_INVALID_PARAMETERS; if (mem_trans->global_handle) cookie = mem_trans->global_handle; share.mf = mobj_ffa_sel1_spmc_new(cookie, share.page_count); if (!share.mf) return FFA_NO_MEMORY; if (flen != blen) { struct mem_frag_state *s = calloc(1, sizeof(*s)); if (!s) { rc = FFA_NO_MEMORY; goto err; } s->share = share; s->mm = mm; s->frag_offset = addr_range_offs; SLIST_INSERT_HEAD(&frag_state_head, s, link); rc = add_mem_share_frag(s, (char *)buf + addr_range_offs, flen - addr_range_offs); if (rc >= 0) *global_handle = mobj_ffa_get_cookie(share.mf); return rc; } rc = add_mem_share_helper(&share, (char *)buf + addr_range_offs, flen - addr_range_offs); if (rc) { /* * Number of consumed bytes may be returned instead of 0 for * done. */ rc = FFA_INVALID_PARAMETERS; goto err; } *global_handle = mobj_ffa_push_to_inactive(share.mf); return 0; err: mobj_ffa_sel1_spmc_delete(share.mf); return rc; } static int handle_mem_share_tmem(paddr_t pbuf, size_t blen, size_t flen, unsigned int page_count, uint64_t *global_handle, struct ffa_rxtx *rxtx) { struct ffa_mem_transaction_x mem_trans = { }; int rc = 0; size_t len = 0; void *buf = NULL; tee_mm_entry_t *mm = NULL; vaddr_t offs = pbuf & SMALL_PAGE_MASK; if (MUL_OVERFLOW(page_count, SMALL_PAGE_SIZE, &len)) return FFA_INVALID_PARAMETERS; if (!core_pbuf_is(CORE_MEM_NON_SEC, pbuf, len)) return FFA_INVALID_PARAMETERS; /* * Check that the length reported in flen is covered by len even * if the offset is taken into account. */ if (len < flen || len - offs < flen) return FFA_INVALID_PARAMETERS; mm = tee_mm_alloc(&core_virt_shm_pool, len); if (!mm) return FFA_NO_MEMORY; if (core_mmu_map_contiguous_pages(tee_mm_get_smem(mm), pbuf, page_count, MEM_AREA_NSEC_SHM)) { rc = FFA_INVALID_PARAMETERS; goto out; } buf = (void *)(tee_mm_get_smem(mm) + offs); cpu_spin_lock(&rxtx->spinlock); rc = spmc_read_mem_transaction(rxtx->ffa_vers, buf, flen, &mem_trans); if (rc) goto unlock; if (is_sp_share(&mem_trans, buf)) { rc = spmc_sp_add_share(&mem_trans, buf, blen, flen, global_handle, NULL); goto unlock; } if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(mem_trans.sender_id)) { rc = FFA_DENIED; goto unlock; } rc = add_mem_share(&mem_trans, mm, buf, blen, flen, global_handle); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); unlock: cpu_spin_unlock(&rxtx->spinlock); if (rc > 0) return rc; core_mmu_unmap_pages(tee_mm_get_smem(mm), page_count); out: tee_mm_free(mm); return rc; } static int handle_mem_share_rxbuf(size_t blen, size_t flen, uint64_t *global_handle, struct ffa_rxtx *rxtx) { struct ffa_mem_transaction_x mem_trans = { }; int rc = FFA_DENIED; cpu_spin_lock(&rxtx->spinlock); if (!rxtx->rx || flen > rxtx->size) goto out; rc = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx, flen, &mem_trans); if (rc) goto out; if (is_sp_share(&mem_trans, rxtx->rx)) { rc = spmc_sp_add_share(&mem_trans, rxtx, blen, flen, global_handle, NULL); goto out; } if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(mem_trans.sender_id)) goto out; rc = add_mem_share(&mem_trans, NULL, rxtx->rx, blen, flen, global_handle); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); out: cpu_spin_unlock(&rxtx->spinlock); return rc; } static void handle_mem_share(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { uint32_t tot_len = args->a1; uint32_t frag_len = args->a2; uint64_t addr = args->a3; uint32_t page_count = args->a4; uint32_t ret_w1 = 0; uint32_t ret_w2 = FFA_INVALID_PARAMETERS; uint32_t ret_w3 = 0; uint32_t ret_fid = FFA_ERROR; uint64_t global_handle = 0; int rc = 0; /* Check that the MBZs are indeed 0 */ if (args->a5 || args->a6 || args->a7) goto out; /* Check that fragment length doesn't exceed total length */ if (frag_len > tot_len) goto out; /* Check for 32-bit calling convention */ if (args->a0 == FFA_MEM_SHARE_32) addr &= UINT32_MAX; if (!addr) { /* * The memory transaction descriptor is passed via our rx * buffer. */ if (page_count) goto out; rc = handle_mem_share_rxbuf(tot_len, frag_len, &global_handle, rxtx); } else { rc = handle_mem_share_tmem(addr, tot_len, frag_len, page_count, &global_handle, rxtx); } if (rc < 0) { ret_w2 = rc; } else if (rc > 0) { ret_fid = FFA_MEM_FRAG_RX; ret_w3 = rc; reg_pair_from_64(global_handle, &ret_w2, &ret_w1); } else { ret_fid = FFA_SUCCESS_32; reg_pair_from_64(global_handle, &ret_w3, &ret_w2); } out: spmc_set_args(args, ret_fid, ret_w1, ret_w2, ret_w3, 0, 0); } static struct mem_frag_state *get_frag_state(uint64_t global_handle) { struct mem_frag_state *s = NULL; SLIST_FOREACH(s, &frag_state_head, link) if (mobj_ffa_get_cookie(s->share.mf) == global_handle) return s; return NULL; } static void handle_mem_frag_tx(struct thread_smc_args *args, struct ffa_rxtx *rxtx) { uint64_t global_handle = reg_pair_to_64(args->a2, args->a1); size_t flen = args->a3; uint32_t endpoint_id = args->a4; struct mem_frag_state *s = NULL; tee_mm_entry_t *mm = NULL; unsigned int page_count = 0; void *buf = NULL; uint32_t ret_w1 = 0; uint32_t ret_w2 = 0; uint32_t ret_w3 = 0; uint32_t ret_fid = 0; int rc = 0; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { uint16_t guest_id = endpoint_id >> 16; if (!guest_id || virt_set_guest(guest_id)) { rc = FFA_INVALID_PARAMETERS; goto out_set_rc; } } /* * Currently we're only doing this for fragmented FFA_MEM_SHARE_* * requests. */ cpu_spin_lock(&rxtx->spinlock); s = get_frag_state(global_handle); if (!s) { rc = FFA_INVALID_PARAMETERS; goto out; } mm = s->mm; if (mm) { if (flen > tee_mm_get_bytes(mm)) { rc = FFA_INVALID_PARAMETERS; goto out; } page_count = s->share.page_count; buf = (void *)tee_mm_get_smem(mm); } else { if (flen > rxtx->size) { rc = FFA_INVALID_PARAMETERS; goto out; } buf = rxtx->rx; } rc = add_mem_share_frag(s, buf, flen); out: if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); cpu_spin_unlock(&rxtx->spinlock); if (rc <= 0 && mm) { core_mmu_unmap_pages(tee_mm_get_smem(mm), page_count); tee_mm_free(mm); } out_set_rc: if (rc < 0) { ret_fid = FFA_ERROR; ret_w2 = rc; } else if (rc > 0) { ret_fid = FFA_MEM_FRAG_RX; ret_w3 = rc; reg_pair_from_64(global_handle, &ret_w2, &ret_w1); } else { ret_fid = FFA_SUCCESS_32; reg_pair_from_64(global_handle, &ret_w3, &ret_w2); } spmc_set_args(args, ret_fid, ret_w1, ret_w2, ret_w3, 0, 0); } static void handle_mem_reclaim(struct thread_smc_args *args) { int rc = FFA_INVALID_PARAMETERS; uint64_t cookie = 0; if (args->a3 || args->a4 || args->a5 || args->a6 || args->a7) goto out; cookie = reg_pair_to_64(args->a2, args->a1); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { uint16_t guest_id = 0; if (cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT) { guest_id = virt_find_guest_by_cookie(cookie); } else { guest_id = (cookie >> FFA_MEMORY_HANDLE_PRTN_SHIFT) & FFA_MEMORY_HANDLE_PRTN_MASK; } if (!guest_id) goto out; if (virt_set_guest(guest_id)) { if (!virt_reclaim_cookie_from_destroyed_guest(guest_id, cookie)) rc = FFA_OK; goto out; } } switch (mobj_ffa_sel1_spmc_reclaim(cookie)) { case TEE_SUCCESS: rc = FFA_OK; break; case TEE_ERROR_ITEM_NOT_FOUND: DMSG("cookie %#"PRIx64" not found", cookie); rc = FFA_INVALID_PARAMETERS; break; default: DMSG("cookie %#"PRIx64" busy", cookie); rc = FFA_DENIED; break; } if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); out: set_simple_ret_val(args, rc); } static void handle_notification_bitmap_create(struct thread_smc_args *args) { uint32_t ret_val = FFA_INVALID_PARAMETERS; uint32_t ret_fid = FFA_ERROR; uint32_t old_itr_status = 0; if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 && !args->a5 && !args->a6 && !args->a7) { struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint16_t vm_id = args->a1; prtn = virt_get_guest(vm_id); nvb = get_notif_vm_bitmap(prtn, vm_id); if (!nvb) { ret_val = FFA_INVALID_PARAMETERS; goto out_virt_put; } old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); if (nvb->initialized) { ret_val = FFA_DENIED; goto out_unlock; } nvb->initialized = true; nvb->do_bottom_half_value = -1; ret_val = FFA_OK; ret_fid = FFA_SUCCESS_32; out_unlock: cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); out_virt_put: virt_put_guest(prtn); } spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); } static void handle_notification_bitmap_destroy(struct thread_smc_args *args) { uint32_t ret_val = FFA_INVALID_PARAMETERS; uint32_t ret_fid = FFA_ERROR; uint32_t old_itr_status = 0; if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 && !args->a5 && !args->a6 && !args->a7) { struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint16_t vm_id = args->a1; prtn = virt_get_guest(vm_id); nvb = get_notif_vm_bitmap(prtn, vm_id); if (!nvb) { ret_val = FFA_INVALID_PARAMETERS; goto out_virt_put; } old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); if (nvb->pending || nvb->bound) { ret_val = FFA_DENIED; goto out_unlock; } memset(nvb, 0, sizeof(*nvb)); ret_val = FFA_OK; ret_fid = FFA_SUCCESS_32; out_unlock: cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); out_virt_put: virt_put_guest(prtn); } spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); } static void handle_notification_bind(struct thread_smc_args *args) { uint32_t ret_val = FFA_INVALID_PARAMETERS; struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint32_t ret_fid = FFA_ERROR; uint32_t old_itr_status = 0; uint64_t bitmap = 0; uint16_t vm_id = 0; if (args->a5 || args->a6 || args->a7) goto out; if (args->a2) { /* We only deal with global notifications */ ret_val = FFA_DENIED; goto out; } /* The destination of the eventual notification */ vm_id = FFA_DST(args->a1); bitmap = reg_pair_to_64(args->a4, args->a3); prtn = virt_get_guest(vm_id); nvb = get_notif_vm_bitmap(prtn, vm_id); if (!nvb) { ret_val = FFA_INVALID_PARAMETERS; goto out_virt_put; } old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); if ((bitmap & nvb->bound)) { ret_val = FFA_DENIED; } else { nvb->bound |= bitmap; ret_val = FFA_OK; ret_fid = FFA_SUCCESS_32; } cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); out_virt_put: virt_put_guest(prtn); out: spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); } static void handle_notification_unbind(struct thread_smc_args *args) { uint32_t ret_val = FFA_INVALID_PARAMETERS; struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint32_t ret_fid = FFA_ERROR; uint32_t old_itr_status = 0; uint64_t bitmap = 0; uint16_t vm_id = 0; if (args->a2 || args->a5 || args->a6 || args->a7) goto out; /* The destination of the eventual notification */ vm_id = FFA_DST(args->a1); bitmap = reg_pair_to_64(args->a4, args->a3); prtn = virt_get_guest(vm_id); nvb = get_notif_vm_bitmap(prtn, vm_id); if (!nvb) { ret_val = FFA_INVALID_PARAMETERS; goto out_virt_put; } old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); if (bitmap & nvb->pending) { ret_val = FFA_DENIED; } else { nvb->bound &= ~bitmap; ret_val = FFA_OK; ret_fid = FFA_SUCCESS_32; } cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); out_virt_put: virt_put_guest(prtn); out: spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0); } static void handle_notification_get(struct thread_smc_args *args) { uint32_t w2 = FFA_INVALID_PARAMETERS; struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint32_t ret_fid = FFA_ERROR; uint32_t old_itr_status = 0; uint16_t vm_id = 0; uint32_t w3 = 0; if (args->a5 || args->a6 || args->a7) goto out; if (!(args->a2 & 0x1)) { ret_fid = FFA_SUCCESS_32; w2 = 0; goto out; } vm_id = FFA_DST(args->a1); prtn = virt_get_guest(vm_id); nvb = get_notif_vm_bitmap(prtn, vm_id); if (!nvb) goto out_virt_put; old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); reg_pair_from_64(nvb->pending, &w3, &w2); nvb->pending = 0; ret_fid = FFA_SUCCESS_32; cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); out_virt_put: virt_put_guest(prtn); out: spmc_set_args(args, ret_fid, 0, w2, w3, 0, 0); } struct notif_info_get_state { struct thread_smc_args *args; unsigned int ids_per_reg; unsigned int ids_count; unsigned int id_pos; unsigned int count; unsigned int max_list_count; unsigned int list_count; }; static unsigned long get_smc_arg(struct thread_smc_args *args, unsigned int idx) { switch (idx) { case 0: return args->a0; case 1: return args->a1; case 2: return args->a2; case 3: return args->a3; case 4: return args->a4; case 5: return args->a5; case 6: return args->a6; case 7: return args->a7; default: assert(0); return 0; } } static void set_smc_arg(struct thread_smc_args *args, unsigned int idx, unsigned long val) { switch (idx) { case 0: args->a0 = val; break; case 1: args->a1 = val; break; case 2: args->a2 = val; break; case 3: args->a3 = val; break; case 4: args->a4 = val; break; case 5: args->a5 = val; break; case 6: args->a6 = val; break; case 7: args->a7 = val; break; default: assert(0); } } static bool add_id_in_regs(struct notif_info_get_state *state, uint16_t id) { unsigned int reg_idx = state->id_pos / state->ids_per_reg + 3; unsigned int reg_shift = (state->id_pos % state->ids_per_reg) * 16; unsigned long v; if (reg_idx > 7) return false; v = get_smc_arg(state->args, reg_idx); v &= ~(0xffffUL << reg_shift); v |= (unsigned long)id << reg_shift; set_smc_arg(state->args, reg_idx, v); state->id_pos++; state->count++; return true; } static bool add_id_count(struct notif_info_get_state *state) { assert(state->list_count < state->max_list_count && state->count >= 1 && state->count <= 4); state->ids_count |= (state->count - 1) << (state->list_count * 2 + 12); state->list_count++; state->count = 0; return state->list_count < state->max_list_count; } static bool add_nvb_to_state(struct notif_info_get_state *state, uint16_t guest_id, struct notif_vm_bitmap *nvb) { if (!nvb->pending) return true; /* * Add only the guest_id, meaning a global notification for this * guest. * * If notifications for one or more specific vCPUs we'd add those * before calling add_id_count(), but that's not supported. */ return add_id_in_regs(state, guest_id) && add_id_count(state); } static void handle_notification_info_get(struct thread_smc_args *args) { struct notif_info_get_state state = { .args = args }; uint32_t ffa_res = FFA_INVALID_PARAMETERS; struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint32_t more_pending_flag = 0; uint32_t itr_state = 0; uint16_t guest_id = 0; if (args->a1 || args->a2 || args->a3 || args->a4 || args->a5 || args->a6 || args->a7) goto err; if (OPTEE_SMC_IS_64(args->a0)) { spmc_set_args(args, FFA_SUCCESS_64, 0, 0, 0, 0, 0); state.ids_per_reg = 4; state.max_list_count = 31; } else { spmc_set_args(args, FFA_SUCCESS_32, 0, 0, 0, 0, 0); state.ids_per_reg = 2; state.max_list_count = 15; } while (true) { /* * With NS-Virtualization we need to go through all * partitions to collect the notification bitmaps, without * we just check the only notification bitmap we have. */ if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { prtn = virt_next_guest(prtn); if (!prtn) break; guest_id = virt_get_guest_id(prtn); } nvb = get_notif_vm_bitmap(prtn, guest_id); itr_state = cpu_spin_lock_xsave(&spmc_notif_lock); if (!add_nvb_to_state(&state, guest_id, nvb)) more_pending_flag = BIT(0); cpu_spin_unlock_xrestore(&spmc_notif_lock, itr_state); if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || more_pending_flag) break; } virt_put_guest(prtn); if (!state.id_pos) { ffa_res = FFA_NO_DATA; goto err; } args->a2 = (state.list_count << FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT) | (state.ids_count << FFA_NOTIF_INFO_GET_ID_LIST_SHIFT) | more_pending_flag; return; err: spmc_set_args(args, FFA_ERROR, 0, ffa_res, 0, 0, 0); } void thread_spmc_set_async_notif_intid(int intid) { assert(interrupt_can_raise_sgi(interrupt_get_main_chip())); notif_intid = intid; spmc_notif_is_ready = true; DMSG("Asynchronous notifications are ready"); } void notif_send_async(uint32_t value, uint16_t guest_id) { struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; uint32_t old_itr_status = 0; prtn = virt_get_guest(guest_id); nvb = get_notif_vm_bitmap(prtn, guest_id); if (nvb) { old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock); assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready && nvb->do_bottom_half_value >= 0 && notif_intid >= 0); nvb->pending |= BIT64(nvb->do_bottom_half_value); interrupt_raise_sgi(interrupt_get_main_chip(), notif_intid, ITR_CPU_MASK_TO_THIS_CPU); cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status); } virt_put_guest(prtn); } #else void notif_send_async(uint32_t value, uint16_t guest_id) { struct guest_partition *prtn = NULL; struct notif_vm_bitmap *nvb = NULL; /* global notification, delay notification interrupt */ uint32_t flags = BIT32(1); int res = 0; prtn = virt_get_guest(guest_id); nvb = get_notif_vm_bitmap(prtn, guest_id); if (nvb) { assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready && nvb->do_bottom_half_value >= 0); res = ffa_set_notification(guest_id, optee_endpoint_id, flags, BIT64(nvb->do_bottom_half_value)); if (res) { EMSG("notification set failed with error %d", res); panic(); } } virt_put_guest(prtn); } #endif /* Only called from assembly */ void thread_spmc_msg_recv(struct thread_smc_args *args); void thread_spmc_msg_recv(struct thread_smc_args *args) { assert((thread_get_exceptions() & THREAD_EXCP_ALL) == THREAD_EXCP_ALL); switch (args->a0) { #if defined(CFG_CORE_SEL1_SPMC) case FFA_FEATURES: handle_features(args); break; case FFA_SPM_ID_GET: spmc_handle_spm_id_get(args); break; #ifdef ARM64 case FFA_RXTX_MAP_64: #endif case FFA_RXTX_MAP_32: spmc_handle_rxtx_map(args, &my_rxtx); break; case FFA_RXTX_UNMAP: spmc_handle_rxtx_unmap(args, &my_rxtx); break; case FFA_RX_RELEASE: spmc_handle_rx_release(args, &my_rxtx); break; case FFA_PARTITION_INFO_GET: spmc_handle_partition_info_get(args, &my_rxtx); break; case FFA_RUN: spmc_handle_run(args); break; #endif /*CFG_CORE_SEL1_SPMC*/ case FFA_INTERRUPT: if (IS_ENABLED(CFG_CORE_SEL1_SPMC)) spmc_set_args(args, FFA_NORMAL_WORLD_RESUME, 0, 0, 0, 0, 0); else spmc_set_args(args, FFA_MSG_WAIT, 0, 0, 0, 0, 0); break; #ifdef ARM64 case FFA_MSG_SEND_DIRECT_REQ_64: #endif case FFA_MSG_SEND_DIRECT_REQ_32: handle_direct_request(args, &my_rxtx); break; #if defined(CFG_CORE_SEL1_SPMC) #ifdef ARM64 case FFA_MEM_SHARE_64: #endif case FFA_MEM_SHARE_32: handle_mem_share(args, &my_rxtx); break; case FFA_MEM_RECLAIM: if (!IS_ENABLED(CFG_SECURE_PARTITION) || !ffa_mem_reclaim(args, NULL)) handle_mem_reclaim(args); break; case FFA_MEM_FRAG_TX: handle_mem_frag_tx(args, &my_rxtx); break; case FFA_NOTIFICATION_BITMAP_CREATE: handle_notification_bitmap_create(args); break; case FFA_NOTIFICATION_BITMAP_DESTROY: handle_notification_bitmap_destroy(args); break; case FFA_NOTIFICATION_BIND: handle_notification_bind(args); break; case FFA_NOTIFICATION_UNBIND: handle_notification_unbind(args); break; case FFA_NOTIFICATION_GET: handle_notification_get(args); break; #ifdef ARM64 case FFA_NOTIFICATION_INFO_GET_64: #endif case FFA_NOTIFICATION_INFO_GET_32: handle_notification_info_get(args); break; #endif /*CFG_CORE_SEL1_SPMC*/ case FFA_ERROR: EMSG("Cannot handle FFA_ERROR(%d)", (int)args->a2); if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) { /* * The SPMC will return an FFA_ERROR back so better * panic() now than flooding the log. */ panic("FFA_ERROR from SPMC is fatal"); } spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); break; default: EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0); set_simple_ret_val(args, FFA_NOT_SUPPORTED); } } static TEE_Result yielding_call_with_arg(uint64_t cookie, uint32_t offset) { size_t sz_rpc = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); struct thread_ctx *thr = threads + thread_get_id(); TEE_Result res = TEE_ERROR_BAD_PARAMETERS; struct optee_msg_arg *arg = NULL; struct mobj *mobj = NULL; uint32_t num_params = 0; size_t sz = 0; mobj = mobj_ffa_get_by_cookie(cookie, 0); if (!mobj) { EMSG("Can't find cookie %#"PRIx64, cookie); return TEE_ERROR_BAD_PARAMETERS; } res = mobj_inc_map(mobj); if (res) goto out_put_mobj; res = TEE_ERROR_BAD_PARAMETERS; arg = mobj_get_va(mobj, offset, sizeof(*arg)); if (!arg) goto out_dec_map; num_params = READ_ONCE(arg->num_params); if (num_params > OPTEE_MSG_MAX_NUM_PARAMS) goto out_dec_map; sz = OPTEE_MSG_GET_ARG_SIZE(num_params); thr->rpc_arg = mobj_get_va(mobj, offset + sz, sz_rpc); if (!thr->rpc_arg) goto out_dec_map; virt_on_stdcall(); res = tee_entry_std(arg, num_params); thread_rpc_shm_cache_clear(&thr->shm_cache); thr->rpc_arg = NULL; out_dec_map: mobj_dec_map(mobj); out_put_mobj: mobj_put(mobj); return res; } /* * Helper routine for the assembly function thread_std_smc_entry() * * Note: this function is weak just to make link_dummies_paged.c happy. */ uint32_t __weak __thread_std_smc_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5 __unused) { /* * Arguments are supplied from handle_yielding_call() as: * a0 <- w1 * a1 <- w3 * a2 <- w4 * a3 <- w5 * a4 <- w6 * a5 <- w7 */ thread_get_tsd()->rpc_target_info = swap_src_dst(a0); if (a1 == OPTEE_FFA_YIELDING_CALL_WITH_ARG) return yielding_call_with_arg(reg_pair_to_64(a3, a2), a4); return FFA_DENIED; } static bool set_fmem(struct optee_msg_param *param, struct thread_param *tpm) { uint64_t offs = tpm->u.memref.offs; param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; param->u.fmem.offs_low = offs; param->u.fmem.offs_high = offs >> 32; if (param->u.fmem.offs_high != offs >> 32) return false; param->u.fmem.size = tpm->u.memref.size; if (tpm->u.memref.mobj) { uint64_t cookie = mobj_get_cookie(tpm->u.memref.mobj); /* If a mobj is passed it better be one with a valid cookie. */ if (cookie == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) return false; param->u.fmem.global_id = cookie; } else { param->u.fmem.global_id = OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; } return true; } static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params, struct thread_param *params, struct optee_msg_arg **arg_ret) { size_t sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); struct thread_ctx *thr = threads + thread_get_id(); struct optee_msg_arg *arg = thr->rpc_arg; if (num_params > THREAD_RPC_MAX_NUM_PARAMS) return TEE_ERROR_BAD_PARAMETERS; if (!arg) { EMSG("rpc_arg not set"); return TEE_ERROR_GENERIC; } memset(arg, 0, sz); arg->cmd = cmd; arg->num_params = num_params; arg->ret = TEE_ERROR_GENERIC; /* in case value isn't updated */ for (size_t n = 0; n < num_params; n++) { switch (params[n].attr) { case THREAD_PARAM_ATTR_NONE: arg->params[n].attr = OPTEE_MSG_ATTR_TYPE_NONE; break; case THREAD_PARAM_ATTR_VALUE_IN: case THREAD_PARAM_ATTR_VALUE_OUT: case THREAD_PARAM_ATTR_VALUE_INOUT: arg->params[n].attr = params[n].attr - THREAD_PARAM_ATTR_VALUE_IN + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; arg->params[n].u.value.a = params[n].u.value.a; arg->params[n].u.value.b = params[n].u.value.b; arg->params[n].u.value.c = params[n].u.value.c; break; case THREAD_PARAM_ATTR_MEMREF_IN: case THREAD_PARAM_ATTR_MEMREF_OUT: case THREAD_PARAM_ATTR_MEMREF_INOUT: if (!set_fmem(arg->params + n, params + n)) return TEE_ERROR_BAD_PARAMETERS; break; default: return TEE_ERROR_BAD_PARAMETERS; } } if (arg_ret) *arg_ret = arg; return TEE_SUCCESS; } static uint32_t get_rpc_arg_res(struct optee_msg_arg *arg, size_t num_params, struct thread_param *params) { for (size_t n = 0; n < num_params; n++) { switch (params[n].attr) { case THREAD_PARAM_ATTR_VALUE_OUT: case THREAD_PARAM_ATTR_VALUE_INOUT: params[n].u.value.a = arg->params[n].u.value.a; params[n].u.value.b = arg->params[n].u.value.b; params[n].u.value.c = arg->params[n].u.value.c; break; case THREAD_PARAM_ATTR_MEMREF_OUT: case THREAD_PARAM_ATTR_MEMREF_INOUT: params[n].u.memref.size = arg->params[n].u.fmem.size; break; default: break; } } return arg->ret; } uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, struct thread_param *params) { struct thread_rpc_arg rpc_arg = { .call = { .w1 = thread_get_tsd()->rpc_target_info, .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD, }, }; struct optee_msg_arg *arg = NULL; uint32_t ret = 0; ret = get_rpc_arg(cmd, num_params, params, &arg); if (ret) return ret; thread_rpc(&rpc_arg); return get_rpc_arg_res(arg, num_params, params); } static void thread_rpc_free(unsigned int bt, uint64_t cookie, struct mobj *mobj) { struct thread_rpc_arg rpc_arg = { .call = { .w1 = thread_get_tsd()->rpc_target_info, .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD, }, }; struct thread_param param = THREAD_PARAM_VALUE(IN, bt, cookie, 0); uint32_t res2 = 0; uint32_t res = 0; DMSG("freeing cookie %#"PRIx64, cookie); res = get_rpc_arg(OPTEE_RPC_CMD_SHM_FREE, 1, ¶m, NULL); mobj_put(mobj); res2 = mobj_ffa_unregister_by_cookie(cookie); if (res2) DMSG("mobj_ffa_unregister_by_cookie(%#"PRIx64"): %#"PRIx32, cookie, res2); if (!res) thread_rpc(&rpc_arg); } static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt) { struct thread_rpc_arg rpc_arg = { .call = { .w1 = thread_get_tsd()->rpc_target_info, .w4 = OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD, }, }; struct thread_param param = THREAD_PARAM_VALUE(IN, bt, size, align); struct optee_msg_arg *arg = NULL; unsigned int internal_offset = 0; struct mobj *mobj = NULL; uint64_t cookie = 0; if (get_rpc_arg(OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m, &arg)) return NULL; thread_rpc(&rpc_arg); if (arg->num_params != 1 || arg->params->attr != OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT) return NULL; internal_offset = READ_ONCE(arg->params->u.fmem.internal_offs); cookie = READ_ONCE(arg->params->u.fmem.global_id); mobj = mobj_ffa_get_by_cookie(cookie, internal_offset); if (!mobj) { DMSG("mobj_ffa_get_by_cookie(%#"PRIx64", %#x): failed", cookie, internal_offset); return NULL; } assert(mobj_is_nonsec(mobj)); if (mobj->size < size) { DMSG("Mobj %#"PRIx64": wrong size", cookie); mobj_put(mobj); return NULL; } if (mobj_inc_map(mobj)) { DMSG("mobj_inc_map(%#"PRIx64"): failed", cookie); mobj_put(mobj); return NULL; } return mobj; } struct mobj *thread_rpc_alloc_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_APPL); } struct mobj *thread_rpc_alloc_kernel_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); } void thread_rpc_free_kernel_payload(struct mobj *mobj) { if (mobj) thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); } void thread_rpc_free_payload(struct mobj *mobj) { if (mobj) thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), mobj); } struct mobj *thread_rpc_alloc_global_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_GLOBAL); } void thread_rpc_free_global_payload(struct mobj *mobj) { if (mobj) thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj), mobj); } void thread_spmc_register_secondary_ep(vaddr_t ep) { unsigned long ret = 0; /* Let the SPM know the entry point for secondary CPUs */ ret = thread_smc(FFA_SECONDARY_EP_REGISTER_64, ep, 0, 0); if (ret != FFA_SUCCESS_32 && ret != FFA_SUCCESS_64) EMSG("FFA_SECONDARY_EP_REGISTER_64 ret %#lx", ret); } static uint16_t ffa_id_get(void) { /* * Ask the SPM component running at a higher EL to return our FF-A ID. * This can either be the SPMC ID (if the SPMC is enabled in OP-TEE) or * the partition ID (if not). */ struct thread_smc_args args = { .a0 = FFA_ID_GET, }; thread_smccc(&args); if (!is_ffa_success(args.a0)) { if (args.a0 == FFA_ERROR) EMSG("Get id failed with error %ld", args.a2); else EMSG("Get id failed"); panic(); } return args.a2; } static uint16_t ffa_spm_id_get(void) { /* * Ask the SPM component running at a higher EL to return its ID. * If OP-TEE implements the S-EL1 SPMC, this will get the SPMD ID. * If not, the ID of the SPMC will be returned. */ struct thread_smc_args args = { .a0 = FFA_SPM_ID_GET, }; thread_smccc(&args); if (!is_ffa_success(args.a0)) { if (args.a0 == FFA_ERROR) EMSG("Get spm id failed with error %ld", args.a2); else EMSG("Get spm id failed"); panic(); } return args.a2; } #if defined(CFG_CORE_SEL1_SPMC) static TEE_Result spmc_init(void) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_add_guest_spec_data(¬if_vm_bitmap_id, sizeof(struct notif_vm_bitmap), NULL)) panic("virt_add_guest_spec_data"); spmd_id = ffa_spm_id_get(); DMSG("SPMD ID %#"PRIx16, spmd_id); spmc_id = ffa_id_get(); DMSG("SPMC ID %#"PRIx16, spmc_id); optee_endpoint_id = FFA_SWD_ID_MIN; while (optee_endpoint_id == spmd_id || optee_endpoint_id == spmc_id) optee_endpoint_id++; DMSG("OP-TEE endpoint ID %#"PRIx16, optee_endpoint_id); /* * If SPMD think we are version 1.0 it will report version 1.0 to * normal world regardless of what version we query the SPM with. * However, if SPMD think we are version 1.1 it will forward * queries from normal world to let us negotiate version. So by * setting version 1.0 here we should be compatible. * * Note that disagreement on negotiated version means that we'll * have communication problems with normal world. */ my_rxtx.ffa_vers = FFA_VERSION_1_0; return TEE_SUCCESS; } #else /* !defined(CFG_CORE_SEL1_SPMC) */ static void spmc_rxtx_map(struct ffa_rxtx *rxtx) { struct thread_smc_args args = { #ifdef ARM64 .a0 = FFA_RXTX_MAP_64, #else .a0 = FFA_RXTX_MAP_32, #endif .a1 = virt_to_phys(rxtx->tx), .a2 = virt_to_phys(rxtx->rx), .a3 = 1, }; thread_smccc(&args); if (!is_ffa_success(args.a0)) { if (args.a0 == FFA_ERROR) EMSG("rxtx map failed with error %ld", args.a2); else EMSG("rxtx map failed"); panic(); } } static uint32_t get_ffa_version(uint32_t my_version) { struct thread_smc_args args = { .a0 = FFA_VERSION, .a1 = my_version, }; thread_smccc(&args); if (args.a0 & BIT(31)) { EMSG("FF-A version failed with error %ld", args.a0); panic(); } return args.a0; } static void *spmc_retrieve_req(uint64_t cookie, struct ffa_mem_transaction_x *trans) { struct ffa_mem_access *acc_descr_array = NULL; struct ffa_mem_access_perm *perm_descr = NULL; struct thread_smc_args args = { .a0 = FFA_MEM_RETRIEVE_REQ_32, .a3 = 0, /* Address, Using TX -> MBZ */ .a4 = 0, /* Using TX -> MBZ */ }; size_t size = 0; int rc = 0; if (my_rxtx.ffa_vers == FFA_VERSION_1_0) { struct ffa_mem_transaction_1_0 *trans_descr = my_rxtx.tx; size = sizeof(*trans_descr) + 1 * sizeof(struct ffa_mem_access); memset(trans_descr, 0, size); trans_descr->sender_id = thread_get_tsd()->rpc_target_info; trans_descr->mem_reg_attr = FFA_NORMAL_MEM_REG_ATTR; trans_descr->global_handle = cookie; trans_descr->flags = FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE | FFA_MEMORY_REGION_FLAG_ANY_ALIGNMENT; trans_descr->mem_access_count = 1; acc_descr_array = trans_descr->mem_access_array; } else { struct ffa_mem_transaction_1_1 *trans_descr = my_rxtx.tx; size = sizeof(*trans_descr) + 1 * sizeof(struct ffa_mem_access); memset(trans_descr, 0, size); trans_descr->sender_id = thread_get_tsd()->rpc_target_info; trans_descr->mem_reg_attr = FFA_NORMAL_MEM_REG_ATTR; trans_descr->global_handle = cookie; trans_descr->flags = FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE | FFA_MEMORY_REGION_FLAG_ANY_ALIGNMENT; trans_descr->mem_access_count = 1; trans_descr->mem_access_offs = sizeof(*trans_descr); trans_descr->mem_access_size = sizeof(struct ffa_mem_access); acc_descr_array = (void *)((vaddr_t)my_rxtx.tx + sizeof(*trans_descr)); } acc_descr_array->region_offs = 0; acc_descr_array->reserved = 0; perm_descr = &acc_descr_array->access_perm; perm_descr->endpoint_id = optee_endpoint_id; perm_descr->perm = FFA_MEM_ACC_RW; perm_descr->flags = 0; args.a1 = size; /* Total Length */ args.a2 = size; /* Frag Length == Total length */ thread_smccc(&args); if (args.a0 != FFA_MEM_RETRIEVE_RESP) { if (args.a0 == FFA_ERROR) EMSG("Failed to fetch cookie %#"PRIx64" error code %d", cookie, (int)args.a2); else EMSG("Failed to fetch cookie %#"PRIx64" a0 %#"PRIx64, cookie, args.a0); return NULL; } rc = spmc_read_mem_transaction(my_rxtx.ffa_vers, my_rxtx.rx, my_rxtx.size, trans); if (rc) { EMSG("Memory transaction failure for cookie %#"PRIx64" rc %d", cookie, rc); return NULL; } return my_rxtx.rx; } void thread_spmc_relinquish(uint64_t cookie) { struct ffa_mem_relinquish *relinquish_desc = my_rxtx.tx; struct thread_smc_args args = { .a0 = FFA_MEM_RELINQUISH, }; memset(relinquish_desc, 0, sizeof(*relinquish_desc)); relinquish_desc->handle = cookie; relinquish_desc->flags = 0; relinquish_desc->endpoint_count = 1; relinquish_desc->endpoint_id_array[0] = optee_endpoint_id; thread_smccc(&args); if (!is_ffa_success(args.a0)) EMSG("Failed to relinquish cookie %#"PRIx64, cookie); } static int set_pages(struct ffa_address_range *regions, unsigned int num_regions, unsigned int num_pages, struct mobj_ffa *mf) { unsigned int n = 0; unsigned int idx = 0; for (n = 0; n < num_regions; n++) { unsigned int page_count = READ_ONCE(regions[n].page_count); uint64_t addr = READ_ONCE(regions[n].address); if (mobj_ffa_add_pages_at(mf, &idx, addr, page_count)) return FFA_INVALID_PARAMETERS; } if (idx != num_pages) return FFA_INVALID_PARAMETERS; return 0; } struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie) { struct mobj_ffa *ret = NULL; struct ffa_mem_transaction_x retrieve_desc = { }; struct ffa_mem_access *descr_array = NULL; struct ffa_mem_region *descr = NULL; struct mobj_ffa *mf = NULL; unsigned int num_pages = 0; unsigned int offs = 0; void *buf = NULL; struct thread_smc_args ffa_rx_release_args = { .a0 = FFA_RX_RELEASE }; /* * OP-TEE is only supporting a single mem_region while the * specification allows for more than one. */ buf = spmc_retrieve_req(cookie, &retrieve_desc); if (!buf) { EMSG("Failed to retrieve cookie from rx buffer %#"PRIx64, cookie); return NULL; } descr_array = (void *)((vaddr_t)buf + retrieve_desc.mem_access_offs); offs = READ_ONCE(descr_array->region_offs); descr = (struct ffa_mem_region *)((vaddr_t)buf + offs); num_pages = READ_ONCE(descr->total_page_count); mf = mobj_ffa_spmc_new(cookie, num_pages); if (!mf) goto out; if (set_pages(descr->address_range_array, READ_ONCE(descr->address_range_count), num_pages, mf)) { mobj_ffa_spmc_delete(mf); goto out; } ret = mf; out: /* Release RX buffer after the mem retrieve request. */ thread_smccc(&ffa_rx_release_args); return ret; } static TEE_Result spmc_init(void) { unsigned int major = 0; unsigned int minor __maybe_unused = 0; uint32_t my_vers = 0; uint32_t vers = 0; my_vers = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); vers = get_ffa_version(my_vers); major = (vers >> FFA_VERSION_MAJOR_SHIFT) & FFA_VERSION_MAJOR_MASK; minor = (vers >> FFA_VERSION_MINOR_SHIFT) & FFA_VERSION_MINOR_MASK; DMSG("SPMC reported version %u.%u", major, minor); if (major != FFA_VERSION_MAJOR) { EMSG("Incompatible major version %u, expected %u", major, FFA_VERSION_MAJOR); panic(); } if (vers < my_vers) my_vers = vers; DMSG("Using version %u.%u", (my_vers >> FFA_VERSION_MAJOR_SHIFT) & FFA_VERSION_MAJOR_MASK, (my_vers >> FFA_VERSION_MINOR_SHIFT) & FFA_VERSION_MINOR_MASK); my_rxtx.ffa_vers = my_vers; spmc_rxtx_map(&my_rxtx); spmc_id = ffa_spm_id_get(); DMSG("SPMC ID %#"PRIx16, spmc_id); optee_endpoint_id = ffa_id_get(); DMSG("OP-TEE endpoint ID %#"PRIx16, optee_endpoint_id); if (!ffa_features(FFA_NOTIFICATION_SET)) { spmc_notif_is_ready = true; DMSG("Asynchronous notifications are ready"); } return TEE_SUCCESS; } #endif /* !defined(CFG_CORE_SEL1_SPMC) */ nex_service_init(spmc_init); optee_os-4.3.0/core/arch/arm/kernel/thread_spmc_a64.S000066400000000000000000000150751464416617300223520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Linaro Limited * Copyright (c) 2019-2021, Arm Limited */ #include #include #include #include #include #include #include #include #ifdef CFG_SECURE_PARTITION LOCAL_FUNC thread_ffa_interrupt , : mov_imm x0, FFA_INTERRUPT /* FID */ /* X1: Endpoint/vCPU IDs is set by caller */ mov x2, #FFA_PARAM_MBZ /* Param MBZ */ mov x3, #FFA_PARAM_MBZ /* Param MBZ */ mov x4, #FFA_PARAM_MBZ /* Param MBZ */ mov x5, #FFA_PARAM_MBZ /* Param MBZ */ mov x6, #FFA_PARAM_MBZ /* Param MBZ */ mov x7, #FFA_PARAM_MBZ /* Param MBZ */ b .ffa_msg_loop END_FUNC thread_ffa_interrupt #endif /* CFG_SECURE_PARTITION */ FUNC thread_ffa_msg_wait , : mov_imm x0, FFA_MSG_WAIT /* FID */ mov x1, #FFA_TARGET_INFO_MBZ /* Target info MBZ */ mov x2, #FFA_PARAM_MBZ /* Param MBZ */ mov x3, #FFA_PARAM_MBZ /* Param MBZ */ mov x4, #FFA_PARAM_MBZ /* Param MBZ */ mov x5, #FFA_PARAM_MBZ /* Param MBZ */ mov x6, #FFA_PARAM_MBZ /* Param MBZ */ mov x7, #FFA_PARAM_MBZ /* Param MBZ */ b .ffa_msg_loop END_FUNC thread_ffa_msg_wait /* Caller provides x1, x3-x7 params */ LOCAL_FUNC ffa_msg_send_direct_resp , : msr spsel, #1 ldr w0, [sp, #THREAD_CORE_LOCAL_DIRECT_RESP_FID] msr spsel, #0 mov x2, #FFA_PARAM_MBZ /* RES MBZ */ .ffa_msg_loop: /* * Native interrupts unmasked while invoking SMC with caller * provided parameters. */ msr daifclr, #DAIFBIT_NATIVE_INTR smc #0 msr daifset, #DAIFBIT_NATIVE_INTR /* Store the parameters as struct thread_smc_args on stack */ sub sp, sp, #THREAD_SMC_ARGS_SIZE store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 mov x0, sp /* parse and handle message */ bl thread_spmc_msg_recv /* Load struct thread_smc_args into registers */ load_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 add sp, sp, #THREAD_SMC_ARGS_SIZE b .ffa_msg_loop END_FUNC ffa_msg_send_direct_resp FUNC thread_std_smc_entry , : ror w19, w0, #16 /* Save target info with src and dst swapped */ bl __thread_std_smc_entry mov w20, w0 /* Save return value */ /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL bl thread_get_tmp_sp mov sp, x0 bl thread_state_free mov w1, w19 /* Target info */ mov w3, w20 /* Return value */ mov x4, #FFA_PARAM_MBZ /* Unused parameter */ mov x5, #FFA_PARAM_MBZ /* Unused parameter */ mov x6, #FFA_PARAM_MBZ /* Unused parameter */ mov x7, #FFA_PARAM_MBZ /* Unused parameter */ b ffa_msg_send_direct_resp END_FUNC thread_std_smc_entry #ifdef CFG_SECURE_PARTITION /* void spmc_sp_thread_entry(args) */ FUNC spmc_sp_thread_entry , : /* Store the parameters as struct thread_smc_args on stack */ sub sp, sp, #THREAD_SMC_ARGS_SIZE store_xregs sp, THREAD_SMC_ARGS_X0, 0, 7 mov x0, sp mov x1, #0 /* Pass NULL pointer for caller_sp, coming from NW */ bl spmc_sp_msg_handler load_xregs sp, THREAD_SMC_ARGS_X0, 20, 27 /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL bl thread_get_tmp_sp mov sp, x0 bl thread_state_free /* Restore the FF-A arguments before the SMC instruction. */ mov w0, w20 mov w1, w21 mov w2, w22 mov w3, w23 mov w4, w24 mov w5, w25 mov w6, w26 mov w7, w27 b .ffa_msg_loop END_FUNC spmc_sp_thread_entry #endif /* void thread_rpc_spsr(uint32_t rv[THREAD_RPC_NUM_ARGS], uint64_t spsr) */ FUNC thread_rpc_spsr , : /* Mask all maskable exceptions before switching to temporary stack */ msr daifset, #DAIFBIT_ALL push x0, xzr push x1, x30 bl thread_get_ctx_regs ldr x30, [sp, #8] store_xregs x0, THREAD_CTX_REGS_X19, 19, 30 mov x19, x0 #if defined(CFG_CORE_PAUTH) /* Save APIAKEY */ read_apiakeyhi x1 read_apiakeylo x2 store_xregs x0, THREAD_CTX_REGS_APIAKEY_HI, 1, 2 #endif bl thread_get_tmp_sp pop x1, xzr /* Match "push x1, x30" above */ mov x2, sp str x2, [x19, #THREAD_CTX_REGS_SP] ldr x20, [sp] /* Get pointer to rpc_arg[] */ mov sp, x0 /* Switch to tmp stack */ /* * We need to read rpc_arg[] early, because thread_state_suspend * can invoke virt_unset_guest() which will unmap pages, * where rpc_arg[] resides */ load_wregs x20, 0, 21, 24 /* Load rpc_arg[] into w21-w24 */ adr x2, .thread_rpc_return mov w0, #THREAD_FLAGS_COPY_ARGS_ON_RETURN bl thread_state_suspend mov w1, w21 mov w3, #0 /* Error code = 0 */ mov w4, w22 mov w5, w23 mov w6, w24 mov w7, w0 /* Supply thread index */ b ffa_msg_send_direct_resp .thread_rpc_return: /* * At this point has the stack pointer been restored to the value * stored in THREAD_CTX above. * * Jumps here from thread_resume above when RPC has returned. The * IRQ and FIQ bits are restored to what they where when this * function was originally entered. w0-w3 holds the values supplied * to thread_resume_from_rpc() in a0-a3. */ pop x16, xzr /* Get pointer to rv[] */ store_wregs x16, 0, 0, 3 /* Store w0-w3 into rv[] */ ret END_FUNC thread_rpc_spsr /* * void thread_foreign_intr_exit(uint32_t thread_index) * * This function is jumped to at the end of macro foreign_intr_handler(). * The current thread as indicated by @thread_index has just been * suspended. The job here is just to inform normal world the thread id to * resume when returning. * If the active FF-A endpoint is OP-TEE (or a TA) then an this function send an * OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT message to the normal world via the * FFA_MSG_SEND_DIRECT_RESP interface. This is handled by the OP-TEE * driver in Linux so it can schedule task to the thread. * If the active endpoint is an SP the function sends an FFA_INTERRUPT. This is * handled by the FF-A driver and after taking care of the NWd interrupts it * returns via an FFA_RUN call. * The active endpoint is determined by checking the THREAD_FLAGS_FFA_ONLY flag * in threads[w0].flags. This is only set for the thread which handles SPs. */ FUNC thread_foreign_intr_exit , : /* load threads[w0].tsd.rpc_target_info into w1 */ mov x1, #THREAD_CTX_SIZE adr_l x2, threads madd x2, x1, x0, x2 ldr w1, [x2, #THREAD_CTX_TSD_RPC_TARGET_INFO] #ifdef CFG_SECURE_PARTITION /* load threads[w0].flags into w2 */ ldr w2, [x2, #THREAD_CTX_FLAGS] and w2, w2, #THREAD_FLAGS_FFA_ONLY cbnz w2, thread_ffa_interrupt #endif /* CFG_SECURE_PARTITION */ mov w3, #FFA_PARAM_MBZ mov w4, #OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT mov x5, #FFA_PARAM_MBZ mov w6, #FFA_PARAM_MBZ mov w7, w0 b ffa_msg_send_direct_resp END_FUNC thread_foreign_intr_exit BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/timer_a64.c000066400000000000000000000024601464416617300212130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include #include #include static unsigned int timer_lock = SPINLOCK_UNLOCK; static bool timer_running; void generic_timer_start(uint32_t time_ms) { uint32_t exceptions = cpu_spin_lock_xsave(&timer_lock); uint32_t timer_ticks = 0; if (timer_running == true) goto exit; /* The timer will fire time_ms from now */ timer_ticks = ((uint64_t)read_cntfrq() * time_ms) / 1000; write_cntps_tval(timer_ticks); /* Enable the secure physical timer */ write_cntps_ctl(1); timer_running = true; exit: cpu_spin_unlock_xrestore(&timer_lock, exceptions); } void generic_timer_stop(void) { uint32_t exceptions = cpu_spin_lock_xsave(&timer_lock); /* Disable the timer */ write_cntps_ctl(0); timer_running = false; cpu_spin_unlock_xrestore(&timer_lock, exceptions); } void generic_timer_handler(uint32_t time_ms) { uint32_t timer_ticks = 0; /* Ensure that the timer did assert the interrupt */ assert((read_cntps_ctl() >> 2)); /* Disable the timer */ write_cntps_ctl(0); /* Reconfigure timer to fire time_ms from now */ timer_ticks = ((uint64_t)read_cntfrq() * time_ms) / 1000; write_cntps_tval(timer_ticks); /* Enable the secure physical timer */ write_cntps_ctl(1); } optee_os-4.3.0/core/arch/arm/kernel/tlb_helpers_a32.S000066400000000000000000000021771464416617300223560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2017, Linaro Limited */ #include #include /* void tlbi_all(void); */ FUNC tlbi_all , : dsb ishst /* Sync with table update */ write_tlbiallis /* Invalidate TLBs */ dsb ish /* Sync with tlb invalidation completion */ isb /* Sync execution on tlb update */ bx lr END_FUNC tlbi_all /* void tlbi_va_allasid(vaddr_t va); */ FUNC tlbi_va_allasid , : dsb ishst /* Sync with table update */ write_tlbimvaais r0 /* Inval TLB by MVA all ASID Inner Sharable */ dsb ish /* Sync with tlb invalidation completion */ isb /* Sync execution on tlb update */ bx lr END_FUNC tlbi_va_allasid /* void tlbi_asid(unsigned long asid); */ FUNC tlbi_asid , : dsb ishst /* Sync with table update */ write_tlbiasidis r0 /* Inval unified TLB by ASID Inner Sharable */ orr r0, r0, #1 /* Select the kernel ASID */ write_tlbiasidis r0 /* Inval unified TLB by ASID Inner Sharable */ dsb ish /* Sync with tlb invalidation completion */ isb /* Sync execution on tlb update */ bx lr END_FUNC tlbi_asid optee_os-4.3.0/core/arch/arm/kernel/tlb_helpers_a64.S000066400000000000000000000023431464416617300223560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2017, Linaro Limited */ #include #include #include /* void tlbi_all(void); */ FUNC tlbi_all , : dsb ishst /* Sync with table update */ tlbi vmalle1is /* All tlb in inner shareable */ dsb ish /* Sync with tlb invalidation completion */ isb /* Sync execution on tlb update */ ret END_FUNC tlbi_all /* void tlbi_va_allasid(vaddr_t va); */ FUNC tlbi_va_allasid , : lsr x0, x0, #TLBI_VA_SHIFT dsb ishst /* Sync with table update */ tlbi vaae1is, x0 /* Invalidate tlb by va in inner shareable */ dsb ish /* Sync with tlb invalidation completion */ isb /* Sync execution on tlb update */ ret END_FUNC tlbi_va_allasid /* void tlbi_asid(unsigned int asid); */ FUNC tlbi_asid , : lsl x0, x0, #TLBI_ASID_SHIFT dsb ishst /* Sync with table update */ tlbi aside1is, x0 /* Invalidate tlb by asid in inner shareable */ orr x0, x0, #BIT(TLBI_ASID_SHIFT) /* Select the kernel ASID */ tlbi aside1is, x0 /* Invalidate tlb by asid in inner shareable */ dsb ish /* Sync with tlb invalidation completion */ isb /* Sync execution on tlb update */ ret END_FUNC tlbi_asid BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/tz_ssvce_pl310_a32.S000066400000000000000000000117621464416617300226320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #define PL310_LOCKDOWN_NBREGS 8 #define PL310_LOCKDOWN_SZREG 4 #define PL310_8WAYS_MASK 0x00FF #define PL310_16WAYS_UPPERMASK 0xFF00 /* * void arm_cl2_lockallways(vaddr_t base) * * lock all L2 caches ways for data and instruction */ FUNC arm_cl2_lockallways , : add r1, r0, #PL310_DCACHE_LOCKDOWN_BASE ldr r2, [r0, #PL310_AUX_CTRL] tst r2, #PL310_AUX_16WAY_BIT mov r2, #PL310_8WAYS_MASK orrne r2, #PL310_16WAYS_UPPERMASK mov r0, #PL310_LOCKDOWN_NBREGS 1: /* lock Dcache and Icache */ str r2, [r1], #PL310_LOCKDOWN_SZREG str r2, [r1], #PL310_LOCKDOWN_SZREG subs r0, r0, #1 bne 1b mov pc, lr END_FUNC arm_cl2_lockallways /* * Set sync operation mask according to ways associativity. * Preserve r0 = pl310 iomem base address */ .macro syncbyway_set_mask reg ldr \reg, [r0, #PL310_AUX_CTRL] tst \reg, #PL310_AUX_16WAY_BIT mov \reg, #PL310_8WAYS_MASK orrne \reg, \reg, #PL310_16WAYS_UPPERMASK .endm /* * void arm_cl2_cleaninvbyway(vaddr_t base) * clean & invalidate the whole L2 cache. */ FUNC arm_cl2_cleaninvbyway , : syncbyway_set_mask r1 str r1, [r0, #PL310_FLUSH_BY_WAY] /* Wait for all cache ways to be cleaned and invalidated */ loop_cli_way_done: ldr r2, [r0, #PL310_FLUSH_BY_WAY] and r2, r2, r1 cmp r2, #0 bne loop_cli_way_done /* Cache Sync */ /* * Wait for writing cache sync * To PL310, Cache sync is atomic opertion, no need to check * the status. For PL220, this check is needed. Keeping the loop * for PL310 is no harm for PL310. */ loop_cli_sync: ldr r1, [r0, #PL310_SYNC] cmp r1, #0 bne loop_cli_sync mov r1, #0 str r1, [r0, #PL310_SYNC] loop_cli_sync_done: ldr r1, [r0, #PL310_SYNC] cmp r1, #0 bne loop_cli_sync_done mov pc, lr END_FUNC arm_cl2_cleaninvbyway /* void arm_cl2_invbyway(vaddr_t base) */ FUNC arm_cl2_invbyway , : syncbyway_set_mask r1 str r1, [r0, #PL310_INV_BY_WAY] loop_inv_way_done: ldr r2, [r0, #PL310_INV_BY_WAY] and r2, r2, r1 cmp r2, #0 bne loop_inv_way_done loop_inv_way_sync: ldr r1, [r0, #PL310_SYNC] cmp r1, #0 bne loop_inv_way_sync mov r1, #0 str r1, [r0, #PL310_SYNC] loop_inv_way_sync_done: ldr r1, [r0, #PL310_SYNC] cmp r1, #0 bne loop_inv_way_sync_done mov pc, lr END_FUNC arm_cl2_invbyway /* void arm_cl2_cleanbyway(vaddr_t base) */ FUNC arm_cl2_cleanbyway , : syncbyway_set_mask r1 str r1, [r0, #PL310_CLEAN_BY_WAY] loop_cl_way_done: ldr r2, [r0, #PL310_CLEAN_BY_WAY] and r2, r2, r1 cmp r2, #0 bne loop_cl_way_done loop_cl_way_sync: ldr r1, [r0, #PL310_SYNC] cmp r1, #0 bne loop_cl_way_sync mov r1, #0 str r1, [r0, #PL310_SYNC] loop_cl_way_sync_done: ldr r1, [r0, #PL310_SYNC] cmp r1, #0 bne loop_cl_way_sync_done mov pc, lr END_FUNC arm_cl2_cleanbyway /* * void _arm_cl2_xxxbypa(vaddr_t pl310_base, paddr_t start, paddr_t end, * int pl310value); * pl310value is one of PL310_CLEAN_BY_PA, PL310_INV_BY_PA or PL310_FLUSH_BY_PA */ LOCAL_FUNC _arm_cl2_xxxbypa , : /* Align start address on PL310 line size */ and r1, #(~(PL310_LINE_SIZE - 1)) #ifdef SCU_BASE /* * ARM ERRATA #764369 * Undocummented SCU Diagnostic Control Register */ /* * NOTE: * We're assuming that if mmu is enabled PL310_BASE and SCU_BASE * still have the same relative offsets from each other. */ sub r0, r0, #(PL310_BASE - SCU_BASE) mov r12, #1 str r12, [r0, #SCU_ERRATA744369] dsb add r0, r0, #(PL310_BASE - SCU_BASE) #endif loop_cl2_xxxbypa: str r1, [r0, r3] loop_xxx_pa_done: ldr r12, [r0, r3] and r12, r12, r1 cmp r12, #0 bne loop_xxx_pa_done add r1, r1, #PL310_LINE_SIZE cmp r2, r1 bpl loop_cl2_xxxbypa loop_xxx_pa_sync: ldr r12, [r0, #PL310_SYNC] cmp r12, #0 bne loop_xxx_pa_sync mov r12, #0 str r12, [r0, #PL310_SYNC] loop_xxx_pa_sync_done: ldr r12, [r0, #PL310_SYNC] cmp r12, #0 bne loop_xxx_pa_sync_done mov pc, lr END_FUNC _arm_cl2_xxxbypa /* * void _arm_cl2_cleanbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); * clean L2 cache by physical address range. */ FUNC arm_cl2_cleanbypa , : mov r3, #PL310_CLEAN_BY_PA b _arm_cl2_xxxbypa END_FUNC arm_cl2_cleanbypa /* * void arm_cl2_invbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); * invalidate L2 cache by physical address range. */ FUNC arm_cl2_invbypa , : mov r3, #PL310_INV_BY_PA b _arm_cl2_xxxbypa END_FUNC arm_cl2_invbypa /* * void arm_cl2_cleaninvbypa(vaddr_t pl310_base, paddr_t start, paddr_t end); * clean and invalidate L2 cache by physical address range. */ FUNC arm_cl2_cleaninvbypa , : mov r3, #PL310_FLUSH_BY_PA b _arm_cl2_xxxbypa END_FUNC arm_cl2_cleaninvbypa /* * __weak vaddr_t pl310_nsbase(void); * return the non-secure PL310 base address * * Weak implementation to preserve the previous behavior where only the * secure PL310 base address was returned. Up to the platform to map * and return non-secure PL310 base address. */ WEAK_FUNC pl310_nsbase , : b pl310_base END_FUNC pl310_nsbase optee_os-4.3.0/core/arch/arm/kernel/unwind_arm32.c000066400000000000000000000076761464416617300217470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2015 Linaro Limited * Copyright 2013-2014 Andrew Turner. * Copyright 2013-2014 Ian Lepore. * Copyright 2013-2014 Rui Paulo. * Copyright 2013 Eitan Adler. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include "unwind_private.h" /* The register names */ #define FP 11 #define SP 13 #define LR 14 #define PC 15 bool find_exidx(vaddr_t addr __unused, vaddr_t *idx_start, vaddr_t *idx_end) { *idx_start = (vaddr_t)__exidx_start; *idx_end = (vaddr_t)__exidx_end; return true; } vaddr_t *unw_get_kernel_stack(void) { size_t n = 0; size_t size = 0; size_t exidx_sz = 0; vaddr_t *tmp = NULL; vaddr_t *addr = NULL; struct unwind_state_arm32 state = { }; vaddr_t stack = thread_stack_start(); size_t stack_size = thread_stack_size(); if (SUB_OVERFLOW((vaddr_t)__exidx_end, (vaddr_t)__exidx_start, &exidx_sz)) return NULL; /* r7: Thumb-style frame pointer */ state.registers[7] = read_r7(); /* r11: ARM-style frame pointer */ state.registers[FP] = read_fp(); state.registers[SP] = read_sp(); state.registers[LR] = read_lr(); /* * Add 4 to make sure that we have an address well inside this function. * This is needed because we're subtracting 2 from PC when calling * find_index() above. See a comment there for more details. */ state.registers[PC] = (uint32_t)unw_get_kernel_stack + 4; while (unwind_stack_arm32(&state, stack, stack_size)) { tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); if (!tmp) goto err; addr = tmp; addr[n] = state.registers[PC]; n++; } if (addr) { tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); if (!tmp) goto err; addr = tmp; addr[n] = 0; } return addr; err: EMSG("Out of memory"); return NULL; } #if (TRACE_LEVEL > 0) void print_kernel_stack(void) { struct unwind_state_arm32 state = { }; vaddr_t stack_start = 0; vaddr_t stack_end = 0; /* r7: Thumb-style frame pointer */ state.registers[7] = read_r7(); /* r11: ARM-style frame pointer */ state.registers[FP] = read_fp(); state.registers[SP] = read_sp(); state.registers[LR] = read_lr(); /* * Add 4 to make sure that we have an address well inside this function. * This is needed because we're subtracting 2 from PC when calling * find_index() above. See a comment there for more details. */ state.registers[PC] = (uint32_t)print_kernel_stack + 4; trace_printf_helper_raw(TRACE_ERROR, true, "TEE load address @ %#"PRIxVA, VCORE_START_VA); get_stack_hard_limits(&stack_start, &stack_end); print_stack_arm32(&state, stack_start, stack_end - stack_start); } #endif optee_os-4.3.0/core/arch/arm/kernel/unwind_arm64.c000066400000000000000000000056221464416617300217410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /*- * Copyright (c) 2015 Linaro Limited * Copyright (c) 2015 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under * the sponsorship of the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include "unwind_private.h" #if defined(CFG_CORE_PAUTH) void pauth_strip_pac(uint64_t *lr) { const uint64_t va_mask = GENMASK_64(CFG_LPAE_ADDR_SPACE_BITS - 1, 0); *lr = *lr & va_mask; } #endif vaddr_t *unw_get_kernel_stack(void) { size_t n = 0; size_t size = 0; vaddr_t *tmp = NULL; vaddr_t *addr = NULL; uaddr_t stack = thread_stack_start(); size_t stack_size = thread_stack_size(); struct unwind_state_arm64 state = { .pc = read_pc(), .fp = read_fp() }; while (unwind_stack_arm64(&state, stack, stack_size)) { tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); if (!tmp) goto err; addr = tmp; addr[n] = state.pc; n++; } if (addr) { tmp = unw_grow(addr, &size, (n + 1) * sizeof(vaddr_t)); if (!tmp) goto err; addr = tmp; addr[n] = 0; } return addr; err: EMSG("Out of memory"); free(addr); return NULL; } #if defined(CFG_UNWIND) && (TRACE_LEVEL > 0) void print_kernel_stack(void) { struct unwind_state_arm64 state = { }; vaddr_t stack_start = 0; vaddr_t stack_end = 0; state.pc = read_pc(); state.fp = read_fp(); trace_printf_helper_raw(TRACE_ERROR, true, "TEE load address @ %#"PRIxVA, VCORE_START_VA); get_stack_hard_limits(&stack_start, &stack_end); print_stack_arm64(&state, stack_start, stack_end - stack_start); } #endif optee_os-4.3.0/core/arch/arm/kernel/unwind_private.h000066400000000000000000000007061464416617300224650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #include #include #include static inline void *unw_grow(void *p, size_t *cur_size, size_t new_size) { size_t rounded_size = 0; void *tmp = NULL; if (*cur_size >= new_size) return p; rounded_size = ROUNDUP(new_size, 16 * sizeof(vaddr_t)); tmp = realloc(p, rounded_size); if (tmp) *cur_size = rounded_size; return tmp; } optee_os-4.3.0/core/arch/arm/kernel/vfp.c000066400000000000000000000051071464416617300202150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include "vfp_private.h" #ifdef ARM32 bool vfp_is_enabled(void) { return !!(vfp_read_fpexc() & FPEXC_EN); } void vfp_enable(void) { vfp_write_fpexc(vfp_read_fpexc() | FPEXC_EN); } void vfp_disable(void) { vfp_write_fpexc(vfp_read_fpexc() & ~FPEXC_EN); } void vfp_lazy_save_state_init(struct vfp_state *state) { uint32_t fpexc = vfp_read_fpexc(); state->fpexc = fpexc; vfp_write_fpexc(fpexc & ~FPEXC_EN); } void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save) { if ((state->fpexc & FPEXC_EN) || force_save) { uint32_t fpexc = vfp_read_fpexc(); assert(!(fpexc & FPEXC_EN)); vfp_write_fpexc(fpexc | FPEXC_EN); state->fpscr = vfp_read_fpscr(); vfp_save_extension_regs(state->reg); vfp_write_fpexc(fpexc); } } void vfp_lazy_restore_state(struct vfp_state *state, bool full_state) { if (full_state) { /* * Only restore VFP registers if they have been touched as they * otherwise are intact. */ /* FPEXC is restored to what's in state->fpexc below */ vfp_write_fpexc(vfp_read_fpexc() | FPEXC_EN); vfp_write_fpscr(state->fpscr); vfp_restore_extension_regs(state->reg); } vfp_write_fpexc(state->fpexc); } #endif /* ARM32 */ #ifdef ARM64 bool vfp_is_enabled(void) { return (CPACR_EL1_FPEN(read_cpacr_el1()) & CPACR_EL1_FPEN_EL0EL1); } void vfp_enable(void) { uint32_t val = read_cpacr_el1(); val |= (CPACR_EL1_FPEN_EL0EL1 << CPACR_EL1_FPEN_SHIFT); write_cpacr_el1(val); isb(); } void vfp_disable(void) { uint32_t val = read_cpacr_el1(); val &= ~(CPACR_EL1_FPEN_MASK << CPACR_EL1_FPEN_SHIFT); write_cpacr_el1(val); isb(); } void vfp_lazy_save_state_init(struct vfp_state *state) { state->cpacr_el1 = read_cpacr_el1(); vfp_disable(); } void vfp_lazy_save_state_final(struct vfp_state *state, bool force_save) { if ((CPACR_EL1_FPEN(state->cpacr_el1) & CPACR_EL1_FPEN_EL0EL1) || force_save) { assert(!vfp_is_enabled()); vfp_enable(); state->fpcr = read_fpcr(); state->fpsr = read_fpsr(); vfp_save_extension_regs(state->reg); vfp_disable(); } } void vfp_lazy_restore_state(struct vfp_state *state, bool full_state) { if (full_state) { /* * Only restore VFP registers if they have been touched as they * otherwise are intact. */ /* CPACR_EL1 is restored to what's in state->cpacr_el1 below */ vfp_enable(); write_fpcr(state->fpcr); write_fpsr(state->fpsr); vfp_restore_extension_regs(state->reg); } write_cpacr_el1(state->cpacr_el1); isb(); } #endif /* ARM64 */ optee_os-4.3.0/core/arch/arm/kernel/vfp_a32.S000066400000000000000000000020701464416617300206360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2016, Linaro Limited */ #include #include #include .fpu neon /* void vfp_save_extension_regs(uint64_t regs[VFP_NUM_REGS]); */ FUNC vfp_save_extension_regs , : vstm r0!, {d0-d15} read_cpacr r1 tst r1, #CPACR_D32DIS bxne lr vstm r0, {d16-d31} bx lr END_FUNC vfp_save_extension_regs /* void vfp_restore_extension_regs(uint64_t regs[VFP_NUM_REGS]); */ FUNC vfp_restore_extension_regs , : vldm r0!, {d0-d15} read_cpacr r1 tst r1, #CPACR_D32DIS bxne lr vldm r0, {d16-d31} bx lr END_FUNC vfp_restore_extension_regs /* void vfp_write_fpexc(uint32_t fpexc) */ FUNC vfp_write_fpexc , : vmsr fpexc, r0 bx lr END_FUNC vfp_write_fpexc /* uint32_t vfp_read_fpexc(void) */ FUNC vfp_read_fpexc , : vmrs r0, fpexc bx lr END_FUNC vfp_read_fpexc /* void vfp_write_fpscr(uint32_t fpscr) */ FUNC vfp_write_fpscr , : vmsr fpscr, r0 bx lr END_FUNC vfp_write_fpscr /* uint32_t vfp_read_fpscr(void) */ FUNC vfp_read_fpscr , : vmrs r0, fpscr bx lr END_FUNC vfp_read_fpscr optee_os-4.3.0/core/arch/arm/kernel/vfp_a64.S000066400000000000000000000025741464416617300206540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #include /* void vfp_save_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); */ FUNC vfp_save_extension_regs , : stp q0, q1, [x0, #16 * 0] stp q2, q3, [x0, #16 * 2] stp q4, q5, [x0, #16 * 4] stp q6, q7, [x0, #16 * 6] stp q8, q9, [x0, #16 * 8] stp q10, q11, [x0, #16 * 10] stp q12, q13, [x0, #16 * 12] stp q14, q15, [x0, #16 * 14] stp q16, q17, [x0, #16 * 16] stp q18, q19, [x0, #16 * 18] stp q20, q21, [x0, #16 * 20] stp q22, q23, [x0, #16 * 22] stp q24, q25, [x0, #16 * 24] stp q26, q27, [x0, #16 * 26] stp q28, q29, [x0, #16 * 28] stp q30, q31, [x0, #16 * 30] ret END_FUNC vfp_save_extension_regs /* void vfp_restore_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); */ FUNC vfp_restore_extension_regs , : ldp q0, q1, [x0, #16 * 0] ldp q2, q3, [x0, #16 * 2] ldp q4, q5, [x0, #16 * 4] ldp q6, q7, [x0, #16 * 6] ldp q8, q9, [x0, #16 * 8] ldp q10, q11, [x0, #16 * 10] ldp q12, q13, [x0, #16 * 12] ldp q14, q15, [x0, #16 * 14] ldp q16, q17, [x0, #16 * 16] ldp q18, q19, [x0, #16 * 18] ldp q20, q21, [x0, #16 * 20] ldp q22, q23, [x0, #16 * 22] ldp q24, q25, [x0, #16 * 24] ldp q26, q27, [x0, #16 * 26] ldp q28, q29, [x0, #16 * 28] ldp q30, q31, [x0, #16 * 30] ret END_FUNC vfp_restore_extension_regs BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/core/arch/arm/kernel/vfp_private.h000066400000000000000000000013331464416617300217510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef VFP_PRIVATE #define VFP_PRIVATE #include void vfp_save_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); void vfp_restore_extension_regs(struct vfp_reg regs[VFP_NUM_REGS]); void vfp_clear_extension_regs(void); #ifdef ARM32 #define FPEXC_EN (1 << 30) /* * These functions can't be implemented in inline assembly when compiling * for thumb mode, to make it easy always implement then in ARM assembly as * ordinary functions. */ void vfp_write_fpexc(uint32_t fpexc); uint32_t vfp_read_fpexc(void); void vfp_write_fpscr(uint32_t fpscr); uint32_t vfp_read_fpscr(void); #endif /* ARM32 */ #endif /*VFP_PRIVATE*/ optee_os-4.3.0/core/arch/arm/kernel/virtualization.c000066400000000000000000000453121464416617300225100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, EPAM Systems. All rights reserved. * Copyright (c) 2023-2024, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LIST_HEAD(prtn_list_head, guest_partition); static unsigned int prtn_list_lock __nex_data = SPINLOCK_UNLOCK; static struct prtn_list_head prtn_list __nex_data = LIST_HEAD_INITIALIZER(prtn_list); static struct prtn_list_head prtn_destroy_list __nex_data = LIST_HEAD_INITIALIZER(prtn_destroy_list); /* Free pages used for guest partitions */ tee_mm_pool_t virt_mapper_pool __nex_bss; /* Memory used by OP-TEE core */ struct tee_mmap_region *kmemory_map __nex_bss; struct guest_spec_data { size_t size; void (*destroy)(void *data); }; static bool add_disabled __nex_bss; static unsigned gsd_count __nex_bss; static struct guest_spec_data *gsd_array __nex_bss; struct guest_partition { LIST_ENTRY(guest_partition) link; struct mmu_partition *mmu_prtn; struct tee_mmap_region *memory_map; struct mutex mutex; void *tables_va; tee_mm_entry_t *tee_ram; tee_mm_entry_t *ta_ram; tee_mm_entry_t *tables; bool runtime_initialized; bool got_guest_destroyed; bool shutting_down; uint16_t id; struct refcount refc; #ifdef CFG_CORE_SEL1_SPMC uint64_t cookies[SPMC_CORE_SEL1_MAX_SHM_COUNT]; uint8_t cookie_count; bitstr_t bit_decl(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT); #endif void **data_array; }; struct guest_partition *current_partition[CFG_TEE_CORE_NB_CORE] __nex_bss; static struct guest_partition *get_current_prtn(void) { struct guest_partition *ret; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); ret = current_partition[get_core_pos()]; thread_unmask_exceptions(exceptions); return ret; } uint16_t virt_get_current_guest_id(void) { struct guest_partition *prtn = get_current_prtn(); if (!prtn) return 0; return prtn->id; } static void set_current_prtn(struct guest_partition *prtn) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); current_partition[get_core_pos()] = prtn; thread_unmask_exceptions(exceptions); } static size_t get_ta_ram_size(void) { size_t ta_size = 0; core_mmu_get_ta_range(NULL, &ta_size); return ROUNDDOWN(ta_size / CFG_VIRT_GUEST_COUNT - VCORE_UNPG_RW_SZ - core_mmu_get_total_pages_size(), SMALL_PAGE_SIZE); } static struct tee_mmap_region *prepare_memory_map(paddr_t tee_data, paddr_t ta_ram) { int i, entries; vaddr_t max_va = 0; struct tee_mmap_region *map; /* * This function assumes that at time of operation, * kmemory_map (aka static_memory_map from core_mmu.c) * will not be altered. This is true, because all * changes to static_memory_map are done during * OP-TEE initialization, while this function will * called when hypervisor creates a guest. */ /* Count number of entries in nexus memory map */ for (map = kmemory_map, entries = 1; map->type != MEM_AREA_END; map++, entries++) ; /* Allocate entries for virtual guest map */ map = nex_calloc(entries + 1, sizeof(struct tee_mmap_region)); if (!map) return NULL; memcpy(map, kmemory_map, sizeof(*map) * entries); /* Map TEE .data and .bss sections */ for (i = 0; i < entries; i++) { if (map[i].va == (vaddr_t)(VCORE_UNPG_RW_PA)) { map[i].type = MEM_AREA_TEE_RAM_RW; map[i].attr = core_mmu_type_to_attr(map[i].type); map[i].pa = tee_data; } if (map[i].va + map[i].size > max_va) max_va = map[i].va + map[i].size; } /* Map TA_RAM */ assert(map[entries - 1].type == MEM_AREA_END); map[entries] = map[entries - 1]; map[entries - 1].region_size = SMALL_PAGE_SIZE; map[entries - 1].va = ROUNDUP(max_va, map[entries - 1].region_size); map[entries - 1].va += (ta_ram - map[entries - 1].va) & CORE_MMU_PGDIR_MASK; map[entries - 1].pa = ta_ram; map[entries - 1].size = get_ta_ram_size(); map[entries - 1].type = MEM_AREA_TA_RAM; map[entries - 1].attr = core_mmu_type_to_attr(map[entries - 1].type); DMSG("New map (%08lx):", (vaddr_t)(VCORE_UNPG_RW_PA)); for (i = 0; i < entries; i++) DMSG("T: %-16s rsz: %08x, pa: %08lx, va: %08lx, sz: %08lx attr: %x", teecore_memtype_name(map[i].type), map[i].region_size, map[i].pa, map[i].va, map[i].size, map[i].attr); return map; } void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base, paddr_size_t secmem0_size, paddr_t secmem1_base, paddr_size_t secmem1_size) { struct tee_mmap_region *map = NULL; paddr_size_t size = secmem0_size; paddr_t base = secmem0_base; if (secmem1_size) { assert(secmem0_base + secmem0_size <= secmem1_base); size = secmem1_base + secmem1_size - base; } /* Init page pool that covers all secure RAM */ if (!tee_mm_init(&virt_mapper_pool, base, size, SMALL_PAGE_SHIFT, TEE_MM_POOL_NEX_MALLOC)) panic("Can't create pool with free pages"); DMSG("Created virtual mapper pool from %"PRIxPA" to %"PRIxPA, base, base + size); if (secmem1_size) { /* Carve out an eventual gap between secmem0 and secmem1 */ base = secmem0_base + secmem0_size; size = secmem1_base - base; if (size) { DMSG("Carving out gap between secmem0 and secmem1 (0x%"PRIxPA":0x%"PRIxPASZ")", base, size); if (!tee_mm_alloc2(&virt_mapper_pool, base, size)) panic("Can't carve out secmem gap"); } } /* Carve out areas that are used by OP-TEE core */ for (map = memory_map; map->type != MEM_AREA_END; map++) { switch (map->type) { case MEM_AREA_TEE_RAM_RX: case MEM_AREA_TEE_RAM_RO: case MEM_AREA_NEX_RAM_RO: case MEM_AREA_NEX_RAM_RW: DMSG("Carving out area of type %d (0x%08lx-0x%08lx)", map->type, map->pa, map->pa + map->size); if (!tee_mm_alloc2(&virt_mapper_pool, map->pa, map->size)) panic("Can't carve out used area"); break; default: continue; } } kmemory_map = memory_map; } static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn) { TEE_Result res = TEE_SUCCESS; paddr_t original_data_pa = 0; prtn->tee_ram = tee_mm_alloc(&virt_mapper_pool, VCORE_UNPG_RW_SZ); if (!prtn->tee_ram) { EMSG("Can't allocate memory for TEE runtime context"); res = TEE_ERROR_OUT_OF_MEMORY; goto err; } DMSG("TEE RAM: %08" PRIxPA, tee_mm_get_smem(prtn->tee_ram)); prtn->ta_ram = tee_mm_alloc(&virt_mapper_pool, get_ta_ram_size()); if (!prtn->ta_ram) { EMSG("Can't allocate memory for TA data"); res = TEE_ERROR_OUT_OF_MEMORY; goto err; } DMSG("TA RAM: %08" PRIxPA, tee_mm_get_smem(prtn->ta_ram)); prtn->tables = tee_mm_alloc(&virt_mapper_pool, core_mmu_get_total_pages_size()); if (!prtn->tables) { EMSG("Can't allocate memory for page tables"); res = TEE_ERROR_OUT_OF_MEMORY; goto err; } prtn->tables_va = phys_to_virt(tee_mm_get_smem(prtn->tables), MEM_AREA_SEC_RAM_OVERALL, core_mmu_get_total_pages_size()); assert(prtn->tables_va); prtn->mmu_prtn = core_alloc_mmu_prtn(prtn->tables_va); if (!prtn->mmu_prtn) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } prtn->memory_map = prepare_memory_map(tee_mm_get_smem(prtn->tee_ram), tee_mm_get_smem(prtn->ta_ram)); if (!prtn->memory_map) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } core_init_mmu_prtn(prtn->mmu_prtn, prtn->memory_map); original_data_pa = virt_to_phys(__data_start); /* Switch to guest's mappings */ core_mmu_set_prtn(prtn->mmu_prtn); /* clear .bss */ memset((void *)(VCORE_UNPG_RW_PA), 0, VCORE_UNPG_RW_SZ); /* copy .data section from R/O original */ memcpy(__data_start, phys_to_virt(original_data_pa, MEM_AREA_SEC_RAM_OVERALL, __data_end - __data_start), __data_end - __data_start); return TEE_SUCCESS; err: if (prtn->tee_ram) tee_mm_free(prtn->tee_ram); if (prtn->ta_ram) tee_mm_free(prtn->ta_ram); if (prtn->tables) tee_mm_free(prtn->tables); nex_free(prtn->mmu_prtn); nex_free(prtn->memory_map); return res; } static void destroy_gsd(struct guest_partition *prtn, bool free_only) { size_t n = 0; for (n = 0; n < gsd_count; n++) { if (!free_only && prtn->data_array[n] && gsd_array[n].destroy) gsd_array[n].destroy(prtn->data_array[n]); nex_free(prtn->data_array[n]); } nex_free(prtn->data_array); prtn->data_array = NULL; } static TEE_Result alloc_gsd(struct guest_partition *prtn) { unsigned int n = 0; if (!gsd_count) return TEE_SUCCESS; prtn->data_array = nex_calloc(gsd_count, sizeof(void *)); if (!prtn->data_array) return TEE_ERROR_OUT_OF_MEMORY; for (n = 0; n < gsd_count; n++) { prtn->data_array[n] = nex_calloc(1, gsd_array[n].size); if (!prtn->data_array[n]) { destroy_gsd(prtn, true /*free_only*/); return TEE_ERROR_OUT_OF_MEMORY; } } return TEE_SUCCESS; } TEE_Result virt_guest_created(uint16_t guest_id) { struct guest_partition *prtn = NULL; TEE_Result res = TEE_SUCCESS; uint32_t exceptions = 0; prtn = nex_calloc(1, sizeof(*prtn)); if (!prtn) return TEE_ERROR_OUT_OF_MEMORY; res = alloc_gsd(prtn); if (res) goto err_free_prtn; prtn->id = guest_id; mutex_init(&prtn->mutex); refcount_set(&prtn->refc, 1); res = configure_guest_prtn_mem(prtn); if (res) goto err_free_gsd; set_current_prtn(prtn); /* Initialize threads */ thread_init_threads(); /* Do the preinitcalls */ call_preinitcalls(); exceptions = cpu_spin_lock_xsave(&prtn_list_lock); LIST_INSERT_HEAD(&prtn_list, prtn, link); cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); IMSG("Added guest %d", guest_id); set_current_prtn(NULL); core_mmu_set_default_prtn(); return TEE_SUCCESS; err_free_gsd: destroy_gsd(prtn, true /*free_only*/); err_free_prtn: nex_free(prtn); return res; } static bool prtn_have_remaining_resources(struct guest_partition *prtn __maybe_unused) { #ifdef CFG_CORE_SEL1_SPMC int i = 0; if (prtn->cookie_count) return true; bit_ffs(prtn->shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i); return i >= 0; #else return false; #endif } static void get_prtn(struct guest_partition *prtn) { if (!refcount_inc(&prtn->refc)) panic(); } uint16_t virt_get_guest_id(struct guest_partition *prtn) { if (!prtn) return 0; return prtn->id; } static struct guest_partition *find_guest_by_id_unlocked(uint16_t guest_id) { struct guest_partition *prtn = NULL; LIST_FOREACH(prtn, &prtn_list, link) if (!prtn->shutting_down && prtn->id == guest_id) return prtn; return NULL; } struct guest_partition *virt_next_guest(struct guest_partition *prtn) { struct guest_partition *ret = NULL; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&prtn_list_lock); if (prtn) ret = LIST_NEXT(prtn, link); else ret = LIST_FIRST(&prtn_list); while (ret && ret->shutting_down) ret = LIST_NEXT(prtn, link); if (ret) get_prtn(ret); cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); virt_put_guest(prtn); return ret; } struct guest_partition *virt_get_current_guest(void) { struct guest_partition *prtn = get_current_prtn(); if (prtn) get_prtn(prtn); return prtn; } struct guest_partition *virt_get_guest(uint16_t guest_id) { struct guest_partition *prtn = NULL; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&prtn_list_lock); prtn = find_guest_by_id_unlocked(guest_id); if (prtn) get_prtn(prtn); cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); return prtn; } void virt_put_guest(struct guest_partition *prtn) { if (prtn && refcount_dec(&prtn->refc)) { uint32_t exceptions = 0; bool do_free = true; assert(prtn->shutting_down); exceptions = cpu_spin_lock_xsave(&prtn_list_lock); LIST_REMOVE(prtn, link); if (prtn_have_remaining_resources(prtn)) { LIST_INSERT_HEAD(&prtn_destroy_list, prtn, link); /* * Delay the nex_free() until * virt_reclaim_cookie_from_destroyed_guest() * is done with this partition. */ do_free = false; } cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); destroy_gsd(prtn, false /*!free_only*/); tee_mm_free(prtn->tee_ram); prtn->tee_ram = NULL; tee_mm_free(prtn->ta_ram); prtn->ta_ram = NULL; tee_mm_free(prtn->tables); prtn->tables = NULL; core_free_mmu_prtn(prtn->mmu_prtn); prtn->mmu_prtn = NULL; nex_free(prtn->memory_map); prtn->memory_map = NULL; if (do_free) nex_free(prtn); } } TEE_Result virt_guest_destroyed(uint16_t guest_id) { struct guest_partition *prtn = NULL; uint32_t exceptions = 0; IMSG("Removing guest %"PRId16, guest_id); exceptions = cpu_spin_lock_xsave(&prtn_list_lock); prtn = find_guest_by_id_unlocked(guest_id); if (prtn && !prtn->got_guest_destroyed) prtn->got_guest_destroyed = true; else prtn = NULL; cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); if (prtn) { notif_deliver_atomic_event(NOTIF_EVENT_SHUTDOWN, prtn->id); exceptions = cpu_spin_lock_xsave(&prtn_list_lock); prtn->shutting_down = true; cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); virt_put_guest(prtn); } else { EMSG("Client with id %d is not found", guest_id); } return TEE_SUCCESS; } TEE_Result virt_set_guest(uint16_t guest_id) { struct guest_partition *prtn = get_current_prtn(); /* This can be true only if we return from IRQ RPC */ if (prtn && prtn->id == guest_id) return TEE_SUCCESS; if (prtn) panic("Virtual guest partition is already set"); prtn = virt_get_guest(guest_id); if (!prtn) return TEE_ERROR_ITEM_NOT_FOUND; set_current_prtn(prtn); core_mmu_set_prtn(prtn->mmu_prtn); return TEE_SUCCESS; } void virt_unset_guest(void) { struct guest_partition *prtn = get_current_prtn(); if (!prtn) return; set_current_prtn(NULL); core_mmu_set_default_prtn(); virt_put_guest(prtn); } void virt_on_stdcall(void) { struct guest_partition *prtn = get_current_prtn(); /* Initialize runtime on first std call */ if (!prtn->runtime_initialized) { mutex_lock(&prtn->mutex); if (!prtn->runtime_initialized) { init_tee_runtime(); prtn->runtime_initialized = true; } mutex_unlock(&prtn->mutex); } } struct tee_mmap_region *virt_get_memory_map(void) { struct guest_partition *prtn; prtn = get_current_prtn(); if (!prtn) return NULL; return prtn->memory_map; } void virt_get_ta_ram(vaddr_t *start, vaddr_t *end) { struct guest_partition *prtn = get_current_prtn(); *start = (vaddr_t)phys_to_virt(tee_mm_get_smem(prtn->ta_ram), MEM_AREA_TA_RAM, tee_mm_get_bytes(prtn->ta_ram)); *end = *start + tee_mm_get_bytes(prtn->ta_ram); } #ifdef CFG_CORE_SEL1_SPMC static int find_cookie(struct guest_partition *prtn, uint64_t cookie) { int i = 0; for (i = 0; i < prtn->cookie_count; i++) if (prtn->cookies[i] == cookie) return i; return -1; } static struct guest_partition *find_prtn_cookie(uint64_t cookie, int *idx) { struct guest_partition *prtn = NULL; int i = 0; LIST_FOREACH(prtn, &prtn_list, link) { i = find_cookie(prtn, cookie); if (i >= 0) { if (idx) *idx = i; return prtn; } } return NULL; } TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie) { TEE_Result res = TEE_ERROR_ACCESS_DENIED; struct guest_partition *prtn = NULL; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&prtn_list_lock); if (find_prtn_cookie(cookie, NULL)) goto out; prtn = current_partition[get_core_pos()]; if (prtn->cookie_count < ARRAY_SIZE(prtn->cookies)) { prtn->cookies[prtn->cookie_count] = cookie; prtn->cookie_count++; res = TEE_SUCCESS; } out: cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); return res; } void virt_remove_cookie(uint64_t cookie) { struct guest_partition *prtn = NULL; uint32_t exceptions = 0; int i = 0; exceptions = cpu_spin_lock_xsave(&prtn_list_lock); prtn = find_prtn_cookie(cookie, &i); if (prtn) { memmove(prtn->cookies + i, prtn->cookies + i + 1, sizeof(uint64_t) * (prtn->cookie_count - i - 1)); prtn->cookie_count--; } cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); } uint16_t virt_find_guest_by_cookie(uint64_t cookie) { struct guest_partition *prtn = NULL; uint32_t exceptions = 0; uint16_t ret = 0; exceptions = cpu_spin_lock_xsave(&prtn_list_lock); prtn = find_prtn_cookie(cookie, NULL); if (prtn) ret = prtn->id; cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); return ret; } bitstr_t *virt_get_shm_bits(void) { return get_current_prtn()->shm_bits; } static TEE_Result reclaim_cookie(struct guest_partition *prtn, uint64_t cookie) { if (cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT) { size_t n = 0; for (n = 0; n < prtn->cookie_count; n++) { if (prtn->cookies[n] == cookie) { memmove(prtn->cookies + n, prtn->cookies + n + 1, sizeof(uint64_t) * (prtn->cookie_count - n - 1)); prtn->cookie_count--; return TEE_SUCCESS; } } } else { uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT | SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK, FFA_MEMORY_HANDLE_PRTN_SHIFT); int64_t i = cookie & ~mask; if (i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT && bit_test(prtn->shm_bits, i)) { bit_clear(prtn->shm_bits, i); return TEE_SUCCESS; } } return TEE_ERROR_ITEM_NOT_FOUND; } TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, uint64_t cookie) { struct guest_partition *prtn = NULL; TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&prtn_list_lock); LIST_FOREACH(prtn, &prtn_destroy_list, link) { if (prtn->id == guest_id) { res = reclaim_cookie(prtn, cookie); if (prtn_have_remaining_resources(prtn)) prtn = NULL; else LIST_REMOVE(prtn, link); break; } } cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions); nex_free(prtn); return res; } #endif /*CFG_CORE_SEL1_SPMC*/ TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size, void (*data_destroy)(void *data)) { void *p = NULL; /* * This function only executes successfully in a single threaded * environment before exiting to the normal world the first time. * If add_disabled is true, it means we're not in this environment * any longer. */ if (add_disabled) return TEE_ERROR_BAD_PARAMETERS; p = nex_realloc(gsd_array, sizeof(*gsd_array) * (gsd_count + 1)); if (!p) return TEE_ERROR_OUT_OF_MEMORY; gsd_array = p; gsd_array[gsd_count] = (struct guest_spec_data){ .size = data_size, .destroy = data_destroy, }; *data_id = gsd_count + 1; gsd_count++; return TEE_SUCCESS; } void *virt_get_guest_spec_data(struct guest_partition *prtn, unsigned int data_id) { assert(data_id); if (!data_id || !prtn || data_id > gsd_count) return NULL; return prtn->data_array[data_id - 1]; } static TEE_Result virt_disable_add(void) { add_disabled = true; return TEE_SUCCESS; } nex_release_init_resource(virt_disable_add); optee_os-4.3.0/core/arch/arm/mm/000077500000000000000000000000001464416617300164045ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/mm/core_mmu.c000066400000000000000000000127361464416617300203670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Two ASIDs per context, one for kernel mode and one for user mode. ASID 0 * and 1 are reserved and not used. This means a maximum of 126 loaded user * mode contexts. This value can be increased but not beyond the maximum * ASID, which is architecture dependent (max 255 for ARMv7-A and ARMv8-A * Aarch32). This constant defines number of ASID pairs. */ #define MMU_NUM_ASID_PAIRS 64 static bitstr_t bit_decl(g_asid, MMU_NUM_ASID_PAIRS) __nex_bss; static unsigned int g_asid_spinlock __nex_bss = SPINLOCK_UNLOCK; void tlbi_va_range(vaddr_t va, size_t len, size_t granule) { assert(granule == CORE_MMU_PGDIR_SIZE || granule == SMALL_PAGE_SIZE); assert(!(va & (granule - 1)) && !(len & (granule - 1))); dsb_ishst(); while (len) { tlbi_va_allasid_nosync(va); len -= granule; va += granule; } dsb_ish(); isb(); } void tlbi_va_range_asid(vaddr_t va, size_t len, size_t granule, uint32_t asid) { assert(granule == CORE_MMU_PGDIR_SIZE || granule == SMALL_PAGE_SIZE); assert(!(va & (granule - 1)) && !(len & (granule - 1))); dsb_ishst(); while (len) { tlbi_va_asid_nosync(va, asid); len -= granule; va += granule; } dsb_ish(); isb(); } TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len) { switch (op) { case DCACHE_CLEAN: dcache_op_all(DCACHE_OP_CLEAN); break; case DCACHE_AREA_CLEAN: dcache_clean_range(va, len); break; case DCACHE_INVALIDATE: dcache_op_all(DCACHE_OP_INV); break; case DCACHE_AREA_INVALIDATE: dcache_inv_range(va, len); break; case ICACHE_INVALIDATE: icache_inv_all(); break; case ICACHE_AREA_INVALIDATE: icache_inv_range(va, len); break; case DCACHE_CLEAN_INV: dcache_op_all(DCACHE_OP_CLEAN_INV); break; case DCACHE_AREA_CLEAN_INV: dcache_cleaninv_range(va, len); break; default: return TEE_ERROR_NOT_IMPLEMENTED; } return TEE_SUCCESS; } #ifdef CFG_PL310 TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len) { TEE_Result ret = TEE_SUCCESS; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); vaddr_t pl310_base_pa_op = 0; /* * According the ARM PL310 documentation, if the operation is specific * to the PA, the behavior is presented in the following manner: * - Secure access: The data in the cache is only affected by the * operation if it is secure. * - Non-secure access: The data in the cache is only affected by the * operation if it is non-secure. * * https://developer.arm.com/documentation/ddi0246/a/programmer-s-model/register-descriptions/register-7--cache-maintenance-operations * * Depending on the buffer location, use the secure or non-secure PL310 * base address to do physical address based cache operation on the * buffer. */ if (tee_pbuf_is_sec(pa, len)) pl310_base_pa_op = pl310_base(); else pl310_base_pa_op = pl310_nsbase(); tee_l2cc_mutex_lock(); switch (op) { case DCACHE_INVALIDATE: arm_cl2_invbyway(pl310_base()); break; case DCACHE_AREA_INVALIDATE: if (len) arm_cl2_invbypa(pl310_base_pa_op, pa, pa + len - 1); break; case DCACHE_CLEAN: arm_cl2_cleanbyway(pl310_base()); break; case DCACHE_AREA_CLEAN: if (len) arm_cl2_cleanbypa(pl310_base_pa_op, pa, pa + len - 1); break; case DCACHE_CLEAN_INV: arm_cl2_cleaninvbyway(pl310_base()); break; case DCACHE_AREA_CLEAN_INV: if (len) arm_cl2_cleaninvbypa(pl310_base_pa_op, pa, pa + len - 1); break; default: ret = TEE_ERROR_NOT_IMPLEMENTED; } tee_l2cc_mutex_unlock(); thread_unmask_exceptions(exceptions); return ret; } #endif /*CFG_PL310*/ unsigned int asid_alloc(void) { uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); unsigned int r; int i; bit_ffc(g_asid, MMU_NUM_ASID_PAIRS, &i); if (i == -1) { r = 0; } else { bit_set(g_asid, i); r = (i + 1) * 2; } cpu_spin_unlock_xrestore(&g_asid_spinlock, exceptions); return r; } void asid_free(unsigned int asid) { uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); /* Only even ASIDs are supposed to be allocated */ assert(!(asid & 1)); if (asid) { int i = (asid - 1) / 2; assert(i < MMU_NUM_ASID_PAIRS && bit_test(g_asid, i)); bit_clear(g_asid, i); } cpu_spin_unlock_xrestore(&g_asid_spinlock, exceptions); } bool arch_va2pa_helper(void *va, paddr_t *pa) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); paddr_t par = 0; paddr_t par_pa_mask = 0; bool ret = false; #ifdef ARM32 write_ats1cpr((vaddr_t)va); isb(); #ifdef CFG_WITH_LPAE par = read_par64(); par_pa_mask = PAR64_PA_MASK; #else par = read_par32(); par_pa_mask = PAR32_PA_MASK; #endif #endif /*ARM32*/ #ifdef ARM64 write_at_s1e1r((vaddr_t)va); isb(); par = read_par_el1(); par_pa_mask = PAR_PA_MASK; #endif if (par & PAR_F) goto out; *pa = (par & (par_pa_mask << PAR_PA_SHIFT)) | ((vaddr_t)va & (BIT64(PAR_PA_SHIFT) - 1)); ret = true; out: thread_unmask_exceptions(exceptions); return ret; } bool cpu_mmu_enabled(void) { uint32_t sctlr; #ifdef ARM32 sctlr = read_sctlr(); #else sctlr = read_sctlr_el1(); #endif return sctlr & SCTLR_M ? true : false; } optee_os-4.3.0/core/arch/arm/mm/core_mmu_lpae.c000066400000000000000000001077471464416617300213770ustar00rootroot00000000000000// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) /* * Copyright (c) 2015-2016, 2022 Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2014, 2022, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef DEBUG_XLAT_TABLE #define DEBUG_XLAT_TABLE 0 #endif #if DEBUG_XLAT_TABLE #define debug_print(...) DMSG_RAW(__VA_ARGS__) #else #define debug_print(...) ((void)0) #endif /* * Miscellaneous MMU related constants */ #define INVALID_DESC 0x0 #define BLOCK_DESC 0x1 #define L3_BLOCK_DESC 0x3 #define TABLE_DESC 0x3 #define DESC_ENTRY_TYPE_MASK 0x3 #define XN (1ull << 2) #define PXN (1ull << 1) #define CONT_HINT (1ull << 0) #define UPPER_ATTRS(x) (((x) & 0x7) << 52) #define GP BIT64(50) /* Guarded Page, Aarch64 FEAT_BTI */ #define NON_GLOBAL (1ull << 9) #define ACCESS_FLAG (1ull << 8) #define NSH (0x0 << 6) #define OSH (0x2 << 6) #define ISH (0x3 << 6) #define AP_RO (0x1 << 5) #define AP_RW (0x0 << 5) #define AP_UNPRIV (0x1 << 4) #define NS (0x1 << 3) #define LOWER_ATTRS_SHIFT 2 #define LOWER_ATTRS(x) (((x) & 0xfff) << LOWER_ATTRS_SHIFT) #define ATTR_DEVICE_nGnRE_INDEX 0x0 #define ATTR_IWBWA_OWBWA_NTR_INDEX 0x1 #define ATTR_DEVICE_nGnRnE_INDEX 0x2 #define ATTR_TAGGED_NORMAL_MEM_INDEX 0x3 #define ATTR_INDEX_MASK 0x7 #define ATTR_DEVICE_nGnRnE (0x0) #define ATTR_DEVICE_nGnRE (0x4) #define ATTR_IWBWA_OWBWA_NTR (0xff) /* Same as ATTR_IWBWA_OWBWA_NTR but with memory tagging. */ #define ATTR_TAGGED_NORMAL_MEM (0xf0) #define MAIR_ATTR_SET(attr, index) (((uint64_t)attr) << ((index) << 3)) #define OUTPUT_ADDRESS_MASK (0x0000FFFFFFFFF000ULL) /* (internal) physical address size bits in EL3/EL1 */ #define TCR_PS_BITS_4GB (0x0) #define TCR_PS_BITS_64GB (0x1) #define TCR_PS_BITS_1TB (0x2) #define TCR_PS_BITS_4TB (0x3) #define TCR_PS_BITS_16TB (0x4) #define TCR_PS_BITS_256TB (0x5) #define TCR_PS_BITS_4PB (0x6) #define UNSET_DESC ((uint64_t)-1) #define FOUR_KB_SHIFT 12 #define PAGE_SIZE_SHIFT FOUR_KB_SHIFT #define PAGE_SIZE (1 << PAGE_SIZE_SHIFT) #define PAGE_SIZE_MASK (PAGE_SIZE - 1) #define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == 0) #define XLAT_ENTRY_SIZE_SHIFT 3 /* Each MMU table entry is 8 bytes (1 << 3) */ #define XLAT_ENTRY_SIZE (1 << XLAT_ENTRY_SIZE_SHIFT) #define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT #define XLAT_TABLE_SIZE (1 << XLAT_TABLE_SIZE_SHIFT) #define XLAT_TABLE_LEVEL_MAX U(3) /* Values for number of entries in each MMU translation table */ #define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT) #define XLAT_TABLE_ENTRIES (1 << XLAT_TABLE_ENTRIES_SHIFT) #define XLAT_TABLE_ENTRIES_MASK (XLAT_TABLE_ENTRIES - 1) /* Values to convert a memory address to an index into a translation table */ #define L3_XLAT_ADDRESS_SHIFT PAGE_SIZE_SHIFT #define L2_XLAT_ADDRESS_SHIFT (L3_XLAT_ADDRESS_SHIFT + \ XLAT_TABLE_ENTRIES_SHIFT) #define L1_XLAT_ADDRESS_SHIFT (L2_XLAT_ADDRESS_SHIFT + \ XLAT_TABLE_ENTRIES_SHIFT) #define L0_XLAT_ADDRESS_SHIFT (L1_XLAT_ADDRESS_SHIFT + \ XLAT_TABLE_ENTRIES_SHIFT) #define XLAT_ADDR_SHIFT(level) (PAGE_SIZE_SHIFT + \ ((XLAT_TABLE_LEVEL_MAX - (level)) * \ XLAT_TABLE_ENTRIES_SHIFT)) #define XLAT_BLOCK_SIZE(level) (UL(1) << XLAT_ADDR_SHIFT(level)) /* Base table */ #define BASE_XLAT_ADDRESS_SHIFT XLAT_ADDR_SHIFT(CORE_MMU_BASE_TABLE_LEVEL) #define BASE_XLAT_BLOCK_SIZE XLAT_BLOCK_SIZE(CORE_MMU_BASE_TABLE_LEVEL) #define NUM_BASE_LEVEL_ENTRIES \ BIT(CFG_LPAE_ADDR_SPACE_BITS - BASE_XLAT_ADDRESS_SHIFT) /* * MMU L1 table, one for each core * * With CFG_CORE_UNMAP_CORE_AT_EL0, each core has one table to be used * while in kernel mode and one to be used while in user mode. */ #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 #define NUM_BASE_TABLES 2 #else #define NUM_BASE_TABLES 1 #endif #ifndef MAX_XLAT_TABLES #ifdef CFG_NS_VIRTUALIZATION # define XLAT_TABLE_VIRTUALIZATION_EXTRA 3 #else # define XLAT_TABLE_VIRTUALIZATION_EXTRA 0 #endif #ifdef CFG_CORE_ASLR # define XLAT_TABLE_ASLR_EXTRA 3 #else # define XLAT_TABLE_ASLR_EXTRA 0 #endif #if (CORE_MMU_BASE_TABLE_LEVEL == 0) # define XLAT_TABLE_TEE_EXTRA 8 # define XLAT_TABLE_USER_EXTRA (NUM_BASE_TABLES * CFG_TEE_CORE_NB_CORE) #else # define XLAT_TABLE_TEE_EXTRA 5 # define XLAT_TABLE_USER_EXTRA 0 #endif #define MAX_XLAT_TABLES (XLAT_TABLE_TEE_EXTRA + \ XLAT_TABLE_VIRTUALIZATION_EXTRA + \ XLAT_TABLE_ASLR_EXTRA + \ XLAT_TABLE_USER_EXTRA) #endif /*!MAX_XLAT_TABLES*/ #if (CORE_MMU_BASE_TABLE_LEVEL == 0) #if (MAX_XLAT_TABLES <= UINT8_MAX) typedef uint8_t l1_idx_t; #elif (MAX_XLAT_TABLES <= UINT16_MAX) typedef uint16_t l1_idx_t; #else #error MAX_XLAT_TABLES is suspiciously large, please check #endif #endif typedef uint64_t base_xlat_tbls_t[CFG_TEE_CORE_NB_CORE][NUM_BASE_LEVEL_ENTRIES]; typedef uint64_t xlat_tbl_t[XLAT_TABLE_ENTRIES]; static base_xlat_tbls_t base_xlation_table[NUM_BASE_TABLES] __aligned(NUM_BASE_LEVEL_ENTRIES * XLAT_ENTRY_SIZE) __section(".nozi.mmu.base_table"); static xlat_tbl_t xlat_tables[MAX_XLAT_TABLES] __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2"); #define XLAT_TABLES_SIZE (sizeof(xlat_tbl_t) * MAX_XLAT_TABLES) /* MMU L2 table for TAs, one for each thread */ static xlat_tbl_t xlat_tables_ul1[CFG_NUM_THREADS] __aligned(XLAT_TABLE_SIZE) __section(".nozi.mmu.l2"); /* * TAs page table entry inside a level 1 page table. * * TAs mapping is expected to start from level 2. * * If base level is 1 then this is the index of a level 1 entry, * that will point directly into TA mapping table. * * If base level is 0 then entry 0 in base table is always used, and then * we fallback to "base level == 1" like scenario. */ static int user_va_idx __nex_data = -1; struct mmu_partition { base_xlat_tbls_t *base_tables; xlat_tbl_t *xlat_tables; xlat_tbl_t *l2_ta_tables; unsigned int xlat_tables_used; unsigned int asid; #if (CORE_MMU_BASE_TABLE_LEVEL == 0) /* * Indexes of the L1 table from 'xlat_tables' * that points to the user mappings. */ l1_idx_t user_l1_table_idx[NUM_BASE_TABLES][CFG_TEE_CORE_NB_CORE]; #endif }; static struct mmu_partition default_partition __nex_data = { .base_tables = base_xlation_table, .xlat_tables = xlat_tables, .l2_ta_tables = xlat_tables_ul1, .xlat_tables_used = 0, .asid = 0 }; #ifdef CFG_NS_VIRTUALIZATION static struct mmu_partition *current_prtn[CFG_TEE_CORE_NB_CORE] __nex_bss; #endif static struct mmu_partition *get_prtn(void) { #ifdef CFG_NS_VIRTUALIZATION struct mmu_partition *ret; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); ret = current_prtn[get_core_pos()]; thread_unmask_exceptions(exceptions); return ret; #else return &default_partition; #endif } static uint32_t desc_to_mattr(unsigned level, uint64_t desc) { uint32_t a; if (!(desc & 1)) return 0; if (level == XLAT_TABLE_LEVEL_MAX) { if ((desc & DESC_ENTRY_TYPE_MASK) != L3_BLOCK_DESC) return 0; } else { if ((desc & DESC_ENTRY_TYPE_MASK) == TABLE_DESC) return TEE_MATTR_TABLE; } a = TEE_MATTR_VALID_BLOCK; if (desc & LOWER_ATTRS(ACCESS_FLAG)) a |= TEE_MATTR_PRX | TEE_MATTR_URX; if (!(desc & LOWER_ATTRS(AP_RO))) a |= TEE_MATTR_PW | TEE_MATTR_UW; if (!(desc & LOWER_ATTRS(AP_UNPRIV))) a &= ~TEE_MATTR_URWX; if (desc & UPPER_ATTRS(XN)) a &= ~(TEE_MATTR_PX | TEE_MATTR_UX); if (desc & UPPER_ATTRS(PXN)) a &= ~TEE_MATTR_PX; COMPILE_TIME_ASSERT(ATTR_DEVICE_nGnRnE_INDEX == TEE_MATTR_MEM_TYPE_STRONGLY_O); COMPILE_TIME_ASSERT(ATTR_DEVICE_nGnRE_INDEX == TEE_MATTR_MEM_TYPE_DEV); COMPILE_TIME_ASSERT(ATTR_IWBWA_OWBWA_NTR_INDEX == TEE_MATTR_MEM_TYPE_CACHED); COMPILE_TIME_ASSERT(ATTR_TAGGED_NORMAL_MEM_INDEX == TEE_MATTR_MEM_TYPE_TAGGED); a |= ((desc & LOWER_ATTRS(ATTR_INDEX_MASK)) >> LOWER_ATTRS_SHIFT) << TEE_MATTR_MEM_TYPE_SHIFT; if (!(desc & LOWER_ATTRS(NON_GLOBAL))) a |= TEE_MATTR_GLOBAL; if (!(desc & LOWER_ATTRS(NS))) a |= TEE_MATTR_SECURE; if (desc & GP) a |= TEE_MATTR_GUARDED; return a; } static uint64_t mattr_to_desc(unsigned level, uint32_t attr) { uint64_t desc; uint32_t a = attr; if (a & TEE_MATTR_TABLE) return TABLE_DESC; if (!(a & TEE_MATTR_VALID_BLOCK)) return 0; if (a & (TEE_MATTR_PX | TEE_MATTR_PW)) a |= TEE_MATTR_PR; if (a & (TEE_MATTR_UX | TEE_MATTR_UW)) a |= TEE_MATTR_UR; if (a & TEE_MATTR_UR) a |= TEE_MATTR_PR; if (a & TEE_MATTR_UW) a |= TEE_MATTR_PW; if (IS_ENABLED(CFG_CORE_BTI) && (a & TEE_MATTR_PX)) a |= TEE_MATTR_GUARDED; if (level == XLAT_TABLE_LEVEL_MAX) desc = L3_BLOCK_DESC; else desc = BLOCK_DESC; if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX))) desc |= UPPER_ATTRS(XN); if (!(a & TEE_MATTR_PX)) desc |= UPPER_ATTRS(PXN); if (a & TEE_MATTR_UR) desc |= LOWER_ATTRS(AP_UNPRIV); if (!(a & TEE_MATTR_PW)) desc |= LOWER_ATTRS(AP_RO); if (feat_bti_is_implemented() && (a & TEE_MATTR_GUARDED)) desc |= GP; /* Keep in sync with core_mmu.c:core_mmu_mattr_is_ok */ switch ((a >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK) { case TEE_MATTR_MEM_TYPE_STRONGLY_O: desc |= LOWER_ATTRS(ATTR_DEVICE_nGnRnE_INDEX | OSH); break; case TEE_MATTR_MEM_TYPE_DEV: desc |= LOWER_ATTRS(ATTR_DEVICE_nGnRE_INDEX | OSH); break; case TEE_MATTR_MEM_TYPE_CACHED: desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); break; case TEE_MATTR_MEM_TYPE_TAGGED: desc |= LOWER_ATTRS(ATTR_TAGGED_NORMAL_MEM_INDEX | ISH); break; default: /* * "Can't happen" the attribute is supposed to be checked * with core_mmu_mattr_is_ok() before. */ panic(); } if (a & (TEE_MATTR_UR | TEE_MATTR_PR)) desc |= LOWER_ATTRS(ACCESS_FLAG); if (!(a & TEE_MATTR_GLOBAL)) desc |= LOWER_ATTRS(NON_GLOBAL); desc |= a & TEE_MATTR_SECURE ? 0 : LOWER_ATTRS(NS); return desc; } #ifdef CFG_NS_VIRTUALIZATION size_t core_mmu_get_total_pages_size(void) { return ROUNDUP(sizeof(base_xlation_table), SMALL_PAGE_SIZE) + sizeof(xlat_tables) + sizeof(xlat_tables_ul1); } struct mmu_partition *core_alloc_mmu_prtn(void *tables) { struct mmu_partition *prtn; uint8_t *tbl = tables; unsigned int asid = asid_alloc(); assert(((vaddr_t)tbl) % SMALL_PAGE_SIZE == 0); if (!asid) return NULL; prtn = nex_malloc(sizeof(*prtn)); if (!prtn) { asid_free(asid); return NULL; } prtn->base_tables = (void *)tbl; COMPILE_TIME_ASSERT(sizeof(base_xlation_table) <= SMALL_PAGE_SIZE); memset(prtn->base_tables, 0, SMALL_PAGE_SIZE); tbl += ROUNDUP(sizeof(base_xlation_table), SMALL_PAGE_SIZE); prtn->xlat_tables = (void *)tbl; memset(prtn->xlat_tables, 0, XLAT_TABLES_SIZE); tbl += XLAT_TABLES_SIZE; assert(((vaddr_t)tbl) % SMALL_PAGE_SIZE == 0); prtn->l2_ta_tables = (void *)tbl; prtn->xlat_tables_used = 0; prtn->asid = asid; return prtn; } void core_free_mmu_prtn(struct mmu_partition *prtn) { asid_free(prtn->asid); nex_free(prtn); } void core_mmu_set_prtn(struct mmu_partition *prtn) { uint64_t ttbr; /* * We are changing mappings for current CPU, * so make sure that we will not be rescheduled */ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); current_prtn[get_core_pos()] = prtn; ttbr = virt_to_phys(prtn->base_tables[0][get_core_pos()]); write_ttbr0_el1(ttbr | ((paddr_t)prtn->asid << TTBR_ASID_SHIFT)); isb(); tlbi_all(); } void core_mmu_set_default_prtn(void) { core_mmu_set_prtn(&default_partition); } void core_mmu_set_default_prtn_tbl(void) { size_t n = 0; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) current_prtn[n] = &default_partition; } #endif static uint64_t *core_mmu_xlat_table_alloc(struct mmu_partition *prtn) { uint64_t *new_table = NULL; if (prtn->xlat_tables_used >= MAX_XLAT_TABLES) { EMSG("%u xlat tables exhausted", MAX_XLAT_TABLES); return NULL; } new_table = prtn->xlat_tables[prtn->xlat_tables_used++]; DMSG("xlat tables used %u / %u", prtn->xlat_tables_used, MAX_XLAT_TABLES); return new_table; } /* * Given an entry that points to a table returns the virtual address * of the pointed table. NULL otherwise. */ static void *core_mmu_xlat_table_entry_pa2va(struct mmu_partition *prtn, unsigned int level, uint64_t entry) { paddr_t pa = 0; void *va = NULL; if ((entry & DESC_ENTRY_TYPE_MASK) != TABLE_DESC || level >= XLAT_TABLE_LEVEL_MAX) return NULL; pa = entry & OUTPUT_ADDRESS_MASK; if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || prtn == &default_partition) va = phys_to_virt(pa, MEM_AREA_TEE_RAM_RW_DATA, XLAT_TABLE_SIZE); else va = phys_to_virt(pa, MEM_AREA_SEC_RAM_OVERALL, XLAT_TABLE_SIZE); return va; } /* * For a table entry that points to a table - allocate and copy to * a new pointed table. This is done for the requested entry, * without going deeper into the pointed table entries. * * A success is returned for non-table entries, as nothing to do there. */ __maybe_unused static bool core_mmu_entry_copy(struct core_mmu_table_info *tbl_info, unsigned int idx) { uint64_t *orig_table = NULL; uint64_t *new_table = NULL; uint64_t *entry = NULL; struct mmu_partition *prtn = NULL; #ifdef CFG_NS_VIRTUALIZATION prtn = tbl_info->prtn; #else prtn = &default_partition; #endif assert(prtn); if (idx >= tbl_info->num_entries) return false; entry = (uint64_t *)tbl_info->table + idx; /* Nothing to do for non-table entries */ if ((*entry & DESC_ENTRY_TYPE_MASK) != TABLE_DESC || tbl_info->level >= XLAT_TABLE_LEVEL_MAX) return true; new_table = core_mmu_xlat_table_alloc(prtn); if (!new_table) return false; orig_table = core_mmu_xlat_table_entry_pa2va(prtn, tbl_info->level, *entry); if (!orig_table) return false; /* Copy original table content to new table */ memcpy(new_table, orig_table, XLAT_TABLE_ENTRIES * XLAT_ENTRY_SIZE); /* Point to the new table */ *entry = virt_to_phys(new_table) | (*entry & ~OUTPUT_ADDRESS_MASK); return true; } static void core_init_mmu_prtn_tee(struct mmu_partition *prtn, struct tee_mmap_region *mm) { size_t n; assert(prtn && mm); for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) { debug_print(" %010" PRIxVA " %010" PRIxPA " %10zx %x", mm[n].va, mm[n].pa, mm[n].size, mm[n].attr); if (!IS_PAGE_ALIGNED(mm[n].pa) || !IS_PAGE_ALIGNED(mm[n].size)) panic("unaligned region"); } /* Clear table before use */ memset(prtn->base_tables, 0, sizeof(base_xlation_table)); for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) if (!core_mmu_is_dynamic_vaspace(mm + n)) core_mmu_map_region(prtn, mm + n); /* * Primary mapping table is ready at index `get_core_pos()` * whose value may not be ZERO. Take this index as copy source. */ for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { if (n == get_core_pos()) continue; memcpy(prtn->base_tables[0][n], prtn->base_tables[0][get_core_pos()], XLAT_ENTRY_SIZE * NUM_BASE_LEVEL_ENTRIES); } } /* * In order to support 32-bit TAs we will have to find * a user VA base in the region [1GB, 4GB[. * Due to OP-TEE design limitation, TAs page table should be an entry * inside a level 1 page table. * * Available options are only these: * - base level 0 entry 0 - [0GB, 512GB[ * - level 1 entry 0 - [0GB, 1GB[ * - level 1 entry 1 - [1GB, 2GB[ <---- * - level 1 entry 2 - [2GB, 3GB[ <---- * - level 1 entry 3 - [3GB, 4GB[ <---- * - level 1 entry 4 - [4GB, 5GB[ * - ... * - ... * * - base level 1 entry 0 - [0GB, 1GB[ * - base level 1 entry 1 - [1GB, 2GB[ <---- * - base level 1 entry 2 - [2GB, 3GB[ <---- * - base level 1 entry 3 - [3GB, 4GB[ <---- * - base level 1 entry 4 - [4GB, 5GB[ * - ... */ static void set_user_va_idx(struct mmu_partition *prtn) { uint64_t *tbl = NULL; unsigned int n = 0; assert(prtn); tbl = prtn->base_tables[0][get_core_pos()]; /* * If base level is 0, then we must use its entry 0. */ if (CORE_MMU_BASE_TABLE_LEVEL == 0) { /* * If base level 0 entry 0 is not used then * it's clear that we can use level 1 entry 1 inside it. * (will be allocated later). */ if ((tbl[0] & DESC_ENTRY_TYPE_MASK) == INVALID_DESC) { user_va_idx = 1; return; } assert((tbl[0] & DESC_ENTRY_TYPE_MASK) == TABLE_DESC); tbl = core_mmu_xlat_table_entry_pa2va(prtn, 0, tbl[0]); assert(tbl); } /* * Search level 1 table (i.e. 1GB mapping per entry) for * an empty entry in the range [1GB, 4GB[. */ for (n = 1; n < 4; n++) { if ((tbl[n] & DESC_ENTRY_TYPE_MASK) == INVALID_DESC) { user_va_idx = n; break; } } assert(user_va_idx != -1); } /* * Setup an entry inside a core level 1 page table for TAs memory mapping * * If base table level is 1 - user_va_idx is already the index, * so nothing to do. * If base table level is 0 - we might need to allocate entry 0 of base table, * as TAs page table is an entry inside a level 1 * page table. */ static void core_init_mmu_prtn_ta_core(struct mmu_partition *prtn __maybe_unused, unsigned int base_idx __maybe_unused, unsigned int core __maybe_unused) { #if (CORE_MMU_BASE_TABLE_LEVEL == 0) struct core_mmu_table_info tbl_info = { }; uint64_t *tbl = NULL; uintptr_t idx = 0; assert(user_va_idx != -1); COMPILE_TIME_ASSERT(MAX_XLAT_TABLES < (1 << (8 * sizeof(prtn->user_l1_table_idx[0][0])))); tbl = prtn->base_tables[base_idx][core]; /* * If base level is 0, then user_va_idx refers to * level 1 page table that's in base level 0 entry 0. */ core_mmu_set_info_table(&tbl_info, 0, 0, tbl); #ifdef CFG_NS_VIRTUALIZATION tbl_info.prtn = prtn; #endif /* * If this isn't the core that created the initial tables * mappings, then the level 1 table must be copied, * as it will hold pointer to the user mapping table * that changes per core. */ if (core != get_core_pos()) { if (!core_mmu_entry_copy(&tbl_info, 0)) panic(); } if (!core_mmu_entry_to_finer_grained(&tbl_info, 0, true)) panic(); /* * Now base level table should be ready with a table descriptor */ assert((tbl[0] & DESC_ENTRY_TYPE_MASK) == TABLE_DESC); tbl = core_mmu_xlat_table_entry_pa2va(prtn, 0, tbl[0]); assert(tbl); idx = ((uintptr_t)&tbl[user_va_idx] - (uintptr_t)prtn->xlat_tables) / sizeof(xlat_tbl_t); assert(idx < prtn->xlat_tables_used); prtn->user_l1_table_idx[base_idx][core] = idx; #endif } static void core_init_mmu_prtn_ta(struct mmu_partition *prtn) { unsigned int base_idx = 0; unsigned int core = 0; assert(user_va_idx != -1); for (base_idx = 0; base_idx < NUM_BASE_TABLES; base_idx++) for (core = 0; core < CFG_TEE_CORE_NB_CORE; core++) core_init_mmu_prtn_ta_core(prtn, base_idx, core); } void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm) { core_init_mmu_prtn_tee(prtn, mm); core_init_mmu_prtn_ta(prtn); } void core_init_mmu(struct tee_mmap_region *mm) { uint64_t max_va = 0; size_t n; COMPILE_TIME_ASSERT(CORE_MMU_BASE_TABLE_SHIFT == XLAT_ADDR_SHIFT(CORE_MMU_BASE_TABLE_LEVEL)); #ifdef CFG_CORE_UNMAP_CORE_AT_EL0 COMPILE_TIME_ASSERT(CORE_MMU_BASE_TABLE_OFFSET == sizeof(base_xlation_table) / 2); #endif COMPILE_TIME_ASSERT(XLAT_TABLES_SIZE == sizeof(xlat_tables)); /* Initialize default pagetables */ core_init_mmu_prtn_tee(&default_partition, mm); for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) { vaddr_t va_end = mm[n].va + mm[n].size - 1; if (va_end > max_va) max_va = va_end; } set_user_va_idx(&default_partition); core_init_mmu_prtn_ta(&default_partition); COMPILE_TIME_ASSERT(CFG_LPAE_ADDR_SPACE_BITS > L1_XLAT_ADDRESS_SHIFT); assert(max_va < BIT64(CFG_LPAE_ADDR_SPACE_BITS)); } #ifdef CFG_WITH_PAGER /* Prefer to consume only 1 base xlat table for the whole mapping */ bool core_mmu_prefer_tee_ram_at_top(paddr_t paddr) { size_t base_level_size = BASE_XLAT_BLOCK_SIZE; paddr_t base_level_mask = base_level_size - 1; return (paddr & base_level_mask) > (base_level_size / 2); } #endif #ifdef ARM32 void core_init_mmu_regs(struct core_mmu_config *cfg) { uint32_t ttbcr = 0; uint32_t mair = 0; cfg->ttbr0_base = virt_to_phys(base_xlation_table[0][0]); cfg->ttbr0_core_offset = sizeof(base_xlation_table[0][0]); mair = MAIR_ATTR_SET(ATTR_DEVICE_nGnRE, ATTR_DEVICE_nGnRE_INDEX); mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); mair |= MAIR_ATTR_SET(ATTR_DEVICE_nGnRnE, ATTR_DEVICE_nGnRnE_INDEX); /* * Tagged memory isn't supported in 32-bit mode, map tagged memory * as normal memory instead. */ mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_TAGGED_NORMAL_MEM_INDEX); cfg->mair0 = mair; ttbcr = TTBCR_EAE; ttbcr |= TTBCR_XRGNX_WBWA << TTBCR_IRGN0_SHIFT; ttbcr |= TTBCR_XRGNX_WBWA << TTBCR_ORGN0_SHIFT; ttbcr |= TTBCR_SHX_ISH << TTBCR_SH0_SHIFT; ttbcr |= TTBCR_EPD1; /* Disable the use of TTBR1 */ /* TTBCR.A1 = 0 => ASID is stored in TTBR0 */ cfg->ttbcr = ttbcr; } #endif /*ARM32*/ #ifdef ARM64 static unsigned int get_hard_coded_pa_size_bits(void) { /* * Intermediate Physical Address Size. * 0b000 32 bits, 4GB. * 0b001 36 bits, 64GB. * 0b010 40 bits, 1TB. * 0b011 42 bits, 4TB. * 0b100 44 bits, 16TB. * 0b101 48 bits, 256TB. * 0b110 52 bits, 4PB */ static_assert(CFG_CORE_ARM64_PA_BITS >= 32); static_assert(CFG_CORE_ARM64_PA_BITS <= 52); if (CFG_CORE_ARM64_PA_BITS <= 32) return TCR_PS_BITS_4GB; if (CFG_CORE_ARM64_PA_BITS <= 36) return TCR_PS_BITS_64GB; if (CFG_CORE_ARM64_PA_BITS <= 40) return TCR_PS_BITS_1TB; if (CFG_CORE_ARM64_PA_BITS <= 42) return TCR_PS_BITS_4TB; if (CFG_CORE_ARM64_PA_BITS <= 44) return TCR_PS_BITS_16TB; if (CFG_CORE_ARM64_PA_BITS <= 48) return TCR_PS_BITS_256TB; /* CFG_CORE_ARM64_PA_BITS <= 48 */ return TCR_PS_BITS_4PB; } static unsigned int get_physical_addr_size_bits(void) { const unsigned int size_bits = read_id_aa64mmfr0_el1() & ID_AA64MMFR0_EL1_PARANGE_MASK; unsigned int b = 0; if (IS_ENABLED(CFG_AUTO_MAX_PA_BITS)) return size_bits; b = get_hard_coded_pa_size_bits(); assert(b <= size_bits); return b; } unsigned int core_mmu_arm64_get_pa_width(void) { const uint8_t map[] = { 32, 36, 40, 42, 44, 48, 52, }; unsigned int size_bits = get_physical_addr_size_bits(); size_bits = MIN(size_bits, ARRAY_SIZE(map) - 1); return map[size_bits]; } void core_init_mmu_regs(struct core_mmu_config *cfg) { uint64_t ips = get_physical_addr_size_bits(); uint64_t mair = 0; uint64_t tcr = 0; cfg->ttbr0_el1_base = virt_to_phys(base_xlation_table[0][0]); cfg->ttbr0_core_offset = sizeof(base_xlation_table[0][0]); mair = MAIR_ATTR_SET(ATTR_DEVICE_nGnRE, ATTR_DEVICE_nGnRE_INDEX); mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); mair |= MAIR_ATTR_SET(ATTR_DEVICE_nGnRnE, ATTR_DEVICE_nGnRnE_INDEX); /* * If MEMTAG isn't enabled, map tagged memory as normal memory * instead. */ if (memtag_is_enabled()) mair |= MAIR_ATTR_SET(ATTR_TAGGED_NORMAL_MEM, ATTR_TAGGED_NORMAL_MEM_INDEX); else mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_TAGGED_NORMAL_MEM_INDEX); cfg->mair_el1 = mair; tcr = TCR_RES1; tcr |= TCR_XRGNX_WBWA << TCR_IRGN0_SHIFT; tcr |= TCR_XRGNX_WBWA << TCR_ORGN0_SHIFT; tcr |= TCR_SHX_ISH << TCR_SH0_SHIFT; tcr |= ips << TCR_EL1_IPS_SHIFT; tcr |= 64 - CFG_LPAE_ADDR_SPACE_BITS; /* Disable the use of TTBR1 */ tcr |= TCR_EPD1; /* * TCR.A1 = 0 => ASID is stored in TTBR0 * TCR.AS = 0 => Same ASID size as in Aarch32/ARMv7 */ cfg->tcr_el1 = tcr; } #endif /*ARM64*/ void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, unsigned level, vaddr_t va_base, void *table) { tbl_info->level = level; tbl_info->next_level = level + 1; tbl_info->table = table; tbl_info->va_base = va_base; tbl_info->shift = XLAT_ADDR_SHIFT(level); #if (CORE_MMU_BASE_TABLE_LEVEL > 0) assert(level >= CORE_MMU_BASE_TABLE_LEVEL); #endif assert(level <= XLAT_TABLE_LEVEL_MAX); if (level == CORE_MMU_BASE_TABLE_LEVEL) tbl_info->num_entries = NUM_BASE_LEVEL_ENTRIES; else tbl_info->num_entries = XLAT_TABLE_ENTRIES; } void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info) { vaddr_t va_range_base; void *tbl = get_prtn()->l2_ta_tables[thread_get_id()]; core_mmu_get_user_va_range(&va_range_base, NULL); core_mmu_set_info_table(pgd_info, 2, va_range_base, tbl); } void core_mmu_create_user_map(struct user_mode_ctx *uctx, struct core_mmu_user_map *map) { struct core_mmu_table_info dir_info; COMPILE_TIME_ASSERT(sizeof(uint64_t) * XLAT_TABLE_ENTRIES == PGT_SIZE); core_mmu_get_user_pgdir(&dir_info); memset(dir_info.table, 0, PGT_SIZE); core_mmu_populate_user_map(&dir_info, uctx); map->user_map = virt_to_phys(dir_info.table) | TABLE_DESC; map->asid = uctx->vm_info.asid; } bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, unsigned max_level, struct core_mmu_table_info *tbl_info) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); unsigned int num_entries = NUM_BASE_LEVEL_ENTRIES; unsigned int level = CORE_MMU_BASE_TABLE_LEVEL; vaddr_t va_base = 0; bool ret = false; uint64_t *tbl; if (!prtn) prtn = get_prtn(); tbl = prtn->base_tables[0][get_core_pos()]; while (true) { unsigned int level_size_shift = XLAT_ADDR_SHIFT(level); unsigned int n = (va - va_base) >> level_size_shift; if (n >= num_entries) goto out; if (level == max_level || level == XLAT_TABLE_LEVEL_MAX || (tbl[n] & TABLE_DESC) != TABLE_DESC) { /* * We've either reached max_level, a block * mapping entry or an "invalid" mapping entry. */ /* * Base level is the CPU specific translation table. * It doesn't make sense to return anything based * on that unless foreign interrupts already are * masked. */ if (level == CORE_MMU_BASE_TABLE_LEVEL && !(exceptions & THREAD_EXCP_FOREIGN_INTR)) goto out; tbl_info->table = tbl; tbl_info->va_base = va_base; tbl_info->level = level; tbl_info->next_level = level + 1; tbl_info->shift = level_size_shift; tbl_info->num_entries = num_entries; #ifdef CFG_NS_VIRTUALIZATION tbl_info->prtn = prtn; #endif ret = true; goto out; } tbl = core_mmu_xlat_table_entry_pa2va(prtn, level, tbl[n]); if (!tbl) goto out; va_base += (vaddr_t)n << level_size_shift; level++; num_entries = XLAT_TABLE_ENTRIES; } out: thread_unmask_exceptions(exceptions); return ret; } bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, unsigned int idx, bool secure __unused) { uint64_t *new_table; uint64_t *entry; int i; paddr_t pa; uint64_t attr; paddr_t block_size_on_next_lvl = XLAT_BLOCK_SIZE(tbl_info->level + 1); struct mmu_partition *prtn; #ifdef CFG_NS_VIRTUALIZATION prtn = tbl_info->prtn; #else prtn = &default_partition; #endif assert(prtn); if (tbl_info->level >= XLAT_TABLE_LEVEL_MAX || idx >= tbl_info->num_entries) return false; entry = (uint64_t *)tbl_info->table + idx; if ((*entry & DESC_ENTRY_TYPE_MASK) == TABLE_DESC) return true; new_table = core_mmu_xlat_table_alloc(prtn); if (!new_table) return false; if (*entry) { pa = *entry & OUTPUT_ADDRESS_MASK; attr = *entry & ~(OUTPUT_ADDRESS_MASK | DESC_ENTRY_TYPE_MASK); for (i = 0; i < XLAT_TABLE_ENTRIES; i++) { new_table[i] = pa | attr | BLOCK_DESC; pa += block_size_on_next_lvl; } } else { memset(new_table, 0, XLAT_TABLE_ENTRIES * XLAT_ENTRY_SIZE); } *entry = virt_to_phys(new_table) | TABLE_DESC; return true; } void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, paddr_t pa, uint32_t attr) { uint64_t *tbl = table; uint64_t desc = mattr_to_desc(level, attr); tbl[idx] = desc | pa; } void core_mmu_get_entry_primitive(const void *table, size_t level, size_t idx, paddr_t *pa, uint32_t *attr) { const uint64_t *tbl = table; if (pa) *pa = tbl[idx] & GENMASK_64(47, 12); if (attr) *attr = desc_to_mattr(level, tbl[idx]); } bool core_mmu_user_va_range_is_defined(void) { return user_va_idx != -1; } void core_mmu_get_user_va_range(vaddr_t *base, size_t *size) { assert(user_va_idx != -1); if (base) *base = (vaddr_t)user_va_idx << L1_XLAT_ADDRESS_SHIFT; if (size) *size = BIT64(L1_XLAT_ADDRESS_SHIFT); } static uint64_t *core_mmu_get_user_mapping_entry(struct mmu_partition *prtn, unsigned int base_idx) { #if (CORE_MMU_BASE_TABLE_LEVEL == 0) l1_idx_t idx = 0; uint64_t *tbl = NULL; #endif assert(user_va_idx != -1); #if (CORE_MMU_BASE_TABLE_LEVEL == 0) idx = prtn->user_l1_table_idx[base_idx][get_core_pos()]; tbl = prtn->xlat_tables[idx]; return &tbl[user_va_idx]; #else return &prtn->base_tables[base_idx][get_core_pos()][user_va_idx]; #endif } bool core_mmu_user_mapping_is_active(void) { bool ret = false; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); uint64_t *entry = NULL; entry = core_mmu_get_user_mapping_entry(get_prtn(), 0); ret = (*entry != 0); thread_unmask_exceptions(exceptions); return ret; } #ifdef ARM32 void core_mmu_get_user_map(struct core_mmu_user_map *map) { struct mmu_partition *prtn = get_prtn(); uint64_t *entry = NULL; entry = core_mmu_get_user_mapping_entry(prtn, 0); map->user_map = *entry; if (map->user_map) { map->asid = (read_ttbr0_64bit() >> TTBR_ASID_SHIFT) & TTBR_ASID_MASK; } else { map->asid = 0; } } void core_mmu_set_user_map(struct core_mmu_user_map *map) { uint64_t ttbr = 0; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); struct mmu_partition *prtn = get_prtn(); uint64_t *entries[NUM_BASE_TABLES] = { }; unsigned int i = 0; ttbr = read_ttbr0_64bit(); /* Clear ASID */ ttbr &= ~((uint64_t)TTBR_ASID_MASK << TTBR_ASID_SHIFT); write_ttbr0_64bit(ttbr); isb(); for (i = 0; i < NUM_BASE_TABLES; i++) entries[i] = core_mmu_get_user_mapping_entry(prtn, i); /* Set the new map */ if (map && map->user_map) { for (i = 0; i < NUM_BASE_TABLES; i++) *entries[i] = map->user_map; dsb(); /* Make sure the write above is visible */ ttbr |= ((uint64_t)map->asid << TTBR_ASID_SHIFT); write_ttbr0_64bit(ttbr); isb(); } else { for (i = 0; i < NUM_BASE_TABLES; i++) *entries[i] = INVALID_DESC; dsb(); /* Make sure the write above is visible */ } tlbi_all(); icache_inv_all(); thread_unmask_exceptions(exceptions); } enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr) { assert(fault_descr & FSR_LPAE); switch (fault_descr & FSR_STATUS_MASK) { case 0x21: /* b100001 Alignment fault */ return CORE_MMU_FAULT_ALIGNMENT; case 0x11: /* b010001 Asynchronous extern abort (DFSR only) */ return CORE_MMU_FAULT_ASYNC_EXTERNAL; case 0x12: /* b100010 Debug event */ return CORE_MMU_FAULT_DEBUG_EVENT; default: break; } switch ((fault_descr & FSR_STATUS_MASK) >> 2) { case 0x1: /* b0001LL Translation fault */ return CORE_MMU_FAULT_TRANSLATION; case 0x2: /* b0010LL Access flag fault */ case 0x3: /* b0011LL Permission fault */ if (fault_descr & FSR_WNR) return CORE_MMU_FAULT_WRITE_PERMISSION; else return CORE_MMU_FAULT_READ_PERMISSION; default: return CORE_MMU_FAULT_OTHER; } } #endif /*ARM32*/ #ifdef ARM64 void core_mmu_get_user_map(struct core_mmu_user_map *map) { struct mmu_partition *prtn = get_prtn(); uint64_t *entry = NULL; entry = core_mmu_get_user_mapping_entry(prtn, 0); map->user_map = *entry; if (map->user_map) { map->asid = (read_ttbr0_el1() >> TTBR_ASID_SHIFT) & TTBR_ASID_MASK; } else { map->asid = 0; } } void core_mmu_set_user_map(struct core_mmu_user_map *map) { uint64_t ttbr = 0; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); struct mmu_partition *prtn = get_prtn(); uint64_t *entries[NUM_BASE_TABLES] = { }; unsigned int i = 0; ttbr = read_ttbr0_el1(); /* Clear ASID */ ttbr &= ~((uint64_t)TTBR_ASID_MASK << TTBR_ASID_SHIFT); write_ttbr0_el1(ttbr); isb(); for (i = 0; i < NUM_BASE_TABLES; i++) entries[i] = core_mmu_get_user_mapping_entry(prtn, i); /* Set the new map */ if (map && map->user_map) { for (i = 0; i < NUM_BASE_TABLES; i++) *entries[i] = map->user_map; dsb(); /* Make sure the write above is visible */ ttbr |= ((uint64_t)map->asid << TTBR_ASID_SHIFT); write_ttbr0_el1(ttbr); isb(); } else { for (i = 0; i < NUM_BASE_TABLES; i++) *entries[i] = INVALID_DESC; dsb(); /* Make sure the write above is visible */ } tlbi_all(); icache_inv_all(); thread_unmask_exceptions(exceptions); } enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr) { switch ((fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) { case ESR_EC_SP_ALIGN: case ESR_EC_PC_ALIGN: return CORE_MMU_FAULT_ALIGNMENT; case ESR_EC_IABT_EL0: case ESR_EC_DABT_EL0: case ESR_EC_IABT_EL1: case ESR_EC_DABT_EL1: switch (fault_descr & ESR_FSC_MASK) { case ESR_FSC_SIZE_L0: case ESR_FSC_SIZE_L1: case ESR_FSC_SIZE_L2: case ESR_FSC_SIZE_L3: case ESR_FSC_TRANS_L0: case ESR_FSC_TRANS_L1: case ESR_FSC_TRANS_L2: case ESR_FSC_TRANS_L3: return CORE_MMU_FAULT_TRANSLATION; case ESR_FSC_ACCF_L1: case ESR_FSC_ACCF_L2: case ESR_FSC_ACCF_L3: case ESR_FSC_PERMF_L1: case ESR_FSC_PERMF_L2: case ESR_FSC_PERMF_L3: if (fault_descr & ESR_ABT_WNR) return CORE_MMU_FAULT_WRITE_PERMISSION; else return CORE_MMU_FAULT_READ_PERMISSION; case ESR_FSC_ALIGN: return CORE_MMU_FAULT_ALIGNMENT; case ESR_FSC_TAG_CHECK: return CORE_MMU_FAULT_TAG_CHECK; default: return CORE_MMU_FAULT_OTHER; } default: return CORE_MMU_FAULT_OTHER; } } #endif /*ARM64*/ optee_os-4.3.0/core/arch/arm/mm/core_mmu_v7.c000066400000000000000000000510041464416617300207720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_WITH_LPAE #error This file is not to be used with LPAE #endif #ifdef CFG_NS_VIRTUALIZATION #error Currently V7 MMU code does not support virtualization #endif #ifndef DEBUG_XLAT_TABLE #define DEBUG_XLAT_TABLE 0 #endif #if DEBUG_XLAT_TABLE #define debug_print(...) DMSG_RAW(__VA_ARGS__) #else #define debug_print(...) ((void)0) #endif /* * MMU related values */ /* Sharable */ #define TEE_MMU_TTB_S (1 << 1) /* Not Outer Sharable */ #define TEE_MMU_TTB_NOS (1 << 5) /* Normal memory, Inner Non-cacheable */ #define TEE_MMU_TTB_IRGN_NC 0 /* Normal memory, Inner Write-Back Write-Allocate Cacheable */ #define TEE_MMU_TTB_IRGN_WBWA (1 << 6) /* Normal memory, Inner Write-Through Cacheable */ #define TEE_MMU_TTB_IRGN_WT 1 /* Normal memory, Inner Write-Back no Write-Allocate Cacheable */ #define TEE_MMU_TTB_IRGN_WB (1 | (1 << 6)) /* Normal memory, Outer Write-Back Write-Allocate Cacheable */ #define TEE_MMU_TTB_RNG_WBWA (1 << 3) /* Normal memory, Outer Write-Back no Write-Allocate Cacheable */ #define TEE_MMU_TTB_RNG_WB (3 << 3) #ifndef CFG_NO_SMP #define TEE_MMU_DEFAULT_ATTRS \ (TEE_MMU_TTB_S | TEE_MMU_TTB_NOS | \ TEE_MMU_TTB_IRGN_WBWA | TEE_MMU_TTB_RNG_WBWA) #else #define TEE_MMU_DEFAULT_ATTRS (TEE_MMU_TTB_IRGN_WB | TEE_MMU_TTB_RNG_WB) #endif #define INVALID_DESC 0x0 #define SECTION_SHIFT 20 #define SECTION_MASK 0x000fffff #define SECTION_SIZE 0x00100000 /* armv7 memory mapping attributes: section mapping */ #define SECTION_SECURE (0 << 19) #define SECTION_NOTSECURE (1 << 19) #define SECTION_SHARED (1 << 16) #define SECTION_NOTGLOBAL (1 << 17) #define SECTION_ACCESS_FLAG (1 << 10) #define SECTION_UNPRIV (1 << 11) #define SECTION_RO (1 << 15) #define SECTION_TEXCB(texcb) ((((texcb) >> 2) << 12) | \ ((((texcb) >> 1) & 0x1) << 3) | \ (((texcb) & 0x1) << 2)) #define SECTION_DEVICE SECTION_TEXCB(ATTR_DEVICE_INDEX) #define SECTION_NORMAL SECTION_TEXCB(ATTR_DEVICE_INDEX) #define SECTION_NORMAL_CACHED SECTION_TEXCB(ATTR_NORMAL_CACHED_INDEX) #define SECTION_STRONG_O SECTION_TEXCB(ATTR_STRONG_O_INDEX) #define SECTION_TAGGED_CACHED SECTION_TEXCB(ATTR_TAGGED_CACHED_INDEX) #define SECTION_XN (1 << 4) #define SECTION_PXN (1 << 0) #define SECTION_SECTION (2 << 0) #define SECTION_PT_NOTSECURE (1 << 3) #define SECTION_PT_PT (1 << 0) #define SECTION_PT_ATTR_MASK ~((1 << 10) - 1) #define SMALL_PAGE_SMALL_PAGE (1 << 1) #define SMALL_PAGE_SHARED (1 << 10) #define SMALL_PAGE_NOTGLOBAL (1 << 11) #define SMALL_PAGE_TEXCB(texcb) ((((texcb) >> 2) << 6) | \ ((((texcb) >> 1) & 0x1) << 3) | \ (((texcb) & 0x1) << 2)) #define SMALL_PAGE_DEVICE SMALL_PAGE_TEXCB(ATTR_DEVICE_INDEX) #define SMALL_PAGE_NORMAL SMALL_PAGE_TEXCB(ATTR_DEVICE_INDEX) #define SMALL_PAGE_NORMAL_CACHED \ SMALL_PAGE_TEXCB(ATTR_NORMAL_CACHED_INDEX) #define SMALL_PAGE_STRONG_O SMALL_PAGE_TEXCB(ATTR_STRONG_O_INDEX) #define SMALL_PAGE_TAGGED_CACHED \ SMALL_PAGE_TEXCB(ATTR_TAGGED_CACHED_INDEX) #define SMALL_PAGE_ACCESS_FLAG (1 << 4) #define SMALL_PAGE_UNPRIV (1 << 5) #define SMALL_PAGE_RO (1 << 9) #define SMALL_PAGE_XN (1 << 0) /* The TEX, C and B bits concatenated */ #define ATTR_DEVICE_INDEX 0x0 #define ATTR_NORMAL_CACHED_INDEX 0x1 #define ATTR_STRONG_O_INDEX 0x2 /* Compat with TEE_MATTR_MEM_TYPE_TAGGED */ #define ATTR_TAGGED_CACHED_INDEX 0x3 #define PRRR_IDX(idx, tr, nos) (((tr) << (2 * (idx))) | \ ((uint32_t)(nos) << ((idx) + 24))) #define NMRR_IDX(idx, ir, or) (((ir) << (2 * (idx))) | \ ((uint32_t)(or) << (2 * (idx) + 16))) #define PRRR_DS0 (1 << 16) #define PRRR_DS1 (1 << 17) #define PRRR_NS0 (1 << 18) #define PRRR_NS1 (1 << 19) #define ATTR_DEVICE_PRRR PRRR_IDX(ATTR_DEVICE_INDEX, 1, 0) #define ATTR_DEVICE_NMRR NMRR_IDX(ATTR_DEVICE_INDEX, 0, 0) #define ATTR_STRONGLY_O_PRRR PRRR_IDX(ATTR_STRONG_O_INDEX, 0, 0) #define ATTR_STRONGLY_O_NMRR NMRR_IDX(ATTR_STRONG_O_INDEX, 0, 0) #ifndef CFG_NO_SMP #define ATTR_NORMAL_CACHED_PRRR PRRR_IDX(ATTR_NORMAL_CACHED_INDEX, 2, 1) #define ATTR_NORMAL_CACHED_NMRR NMRR_IDX(ATTR_NORMAL_CACHED_INDEX, 1, 1) #define ATTR_TAGGED_CACHED_PRRR PRRR_IDX(ATTR_TAGGED_CACHED_INDEX, 2, 1) #define ATTR_TAGGED_CACHED_NMRR NMRR_IDX(ATTR_TAGGED_CACHED_INDEX, 1, 1) #else #define ATTR_NORMAL_CACHED_PRRR PRRR_IDX(ATTR_NORMAL_CACHED_INDEX, 2, 0) #define ATTR_NORMAL_CACHED_NMRR NMRR_IDX(ATTR_NORMAL_CACHED_INDEX, 3, 3) #define ATTR_TAGGED_CACHED_PRRR PRRR_IDX(ATTR_TAGGED_CACHED_INDEX, 2, 0) #define ATTR_TAGGED_CACHED_NMRR NMRR_IDX(ATTR_TAGGED_CACHED_INDEX, 3, 3) #endif #define NUM_L1_ENTRIES 4096 #define NUM_L2_ENTRIES 256 #define L1_TBL_SIZE (NUM_L1_ENTRIES * 4) #define L2_TBL_SIZE (NUM_L2_ENTRIES * 4) #define L1_ALIGNMENT L1_TBL_SIZE #define L2_ALIGNMENT L2_TBL_SIZE /* Defined to the smallest possible secondary L1 MMU table */ #define TTBCR_N_VALUE 7 /* Number of sections in ttbr0 when user mapping activated */ #define NUM_UL1_ENTRIES (1 << (12 - TTBCR_N_VALUE)) #define UL1_ALIGNMENT (NUM_UL1_ENTRIES * 4) /* TTB attributes */ /* TTB0 of TTBR0 (depends on TTBCR_N_VALUE) */ #define TTB_UL1_MASK (~(UL1_ALIGNMENT - 1)) /* TTB1 of TTBR1 */ #define TTB_L1_MASK (~(L1_ALIGNMENT - 1)) #ifndef MAX_XLAT_TABLES #ifdef CFG_CORE_ASLR # define XLAT_TABLE_ASLR_EXTRA 2 #else # define XLAT_TABLE_ASLR_EXTRA 0 #endif #define MAX_XLAT_TABLES (4 + XLAT_TABLE_ASLR_EXTRA) #endif /*!MAX_XLAT_TABLES*/ enum desc_type { DESC_TYPE_PAGE_TABLE, DESC_TYPE_SECTION, DESC_TYPE_SUPER_SECTION, DESC_TYPE_LARGE_PAGE, DESC_TYPE_SMALL_PAGE, DESC_TYPE_INVALID, }; typedef uint32_t l1_xlat_tbl_t[NUM_L1_ENTRIES]; typedef uint32_t l2_xlat_tbl_t[NUM_L2_ENTRIES]; typedef uint32_t ul1_xlat_tbl_t[NUM_UL1_ENTRIES]; static l1_xlat_tbl_t main_mmu_l1_ttb __aligned(L1_ALIGNMENT) __section(".nozi.mmu.l1"); /* L2 MMU tables */ static l2_xlat_tbl_t main_mmu_l2_ttb[MAX_XLAT_TABLES] __aligned(L2_ALIGNMENT) __section(".nozi.mmu.l2"); /* MMU L1 table for TAs, one for each thread */ static ul1_xlat_tbl_t main_mmu_ul1_ttb[CFG_NUM_THREADS] __aligned(UL1_ALIGNMENT) __section(".nozi.mmu.ul1"); struct mmu_partition { l1_xlat_tbl_t *l1_table; l2_xlat_tbl_t *l2_tables; ul1_xlat_tbl_t *ul1_tables; uint32_t tables_used; }; static struct mmu_partition default_partition = { .l1_table = &main_mmu_l1_ttb, .l2_tables = main_mmu_l2_ttb, .ul1_tables = main_mmu_ul1_ttb, .tables_used = 0, }; #ifdef CFG_NS_VIRTUALIZATION static struct mmu_partition *current_prtn[CFG_TEE_CORE_NB_CORE]; void core_mmu_set_default_prtn_tbl(void) { size_t n = 0; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) current_prtn[n] = &default_partition; } #endif static struct mmu_partition *get_prtn(void) { #ifdef CFG_NS_VIRTUALIZATION return current_prtn[get_core_pos()]; #else return &default_partition; #endif } static vaddr_t core_mmu_get_main_ttb_va(struct mmu_partition *prtn) { return (vaddr_t)prtn->l1_table; } static paddr_t core_mmu_get_main_ttb_pa(struct mmu_partition *prtn) { paddr_t pa = virt_to_phys((void *)core_mmu_get_main_ttb_va(prtn)); if (pa & ~TTB_L1_MASK) panic("invalid core l1 table"); return pa; } static vaddr_t core_mmu_get_ul1_ttb_va(struct mmu_partition *prtn) { return (vaddr_t)prtn->ul1_tables[thread_get_id()]; } static paddr_t core_mmu_get_ul1_ttb_pa(struct mmu_partition *prtn) { paddr_t pa = virt_to_phys((void *)core_mmu_get_ul1_ttb_va(prtn)); if (pa & ~TTB_UL1_MASK) panic("invalid user l1 table"); return pa; } static void *core_mmu_alloc_l2(struct mmu_partition *prtn, size_t size) { uint32_t to_alloc = ROUNDUP(size, NUM_L2_ENTRIES * SMALL_PAGE_SIZE) / (NUM_L2_ENTRIES * SMALL_PAGE_SIZE); DMSG("L2 table used: %d/%d", prtn->tables_used + to_alloc, MAX_XLAT_TABLES); if (prtn->tables_used + to_alloc > MAX_XLAT_TABLES) return NULL; memset(prtn->l2_tables[prtn->tables_used], 0, sizeof(l2_xlat_tbl_t) * to_alloc); prtn->tables_used += to_alloc; return prtn->l2_tables[prtn->tables_used - to_alloc]; } static enum desc_type get_desc_type(unsigned level, uint32_t desc) { assert(level >= 1 && level <= 2); if (level == 1) { if ((desc & 0x3) == 0x1) return DESC_TYPE_PAGE_TABLE; if ((desc & 0x2) == 0x2) { if (desc & (1 << 18)) return DESC_TYPE_SUPER_SECTION; return DESC_TYPE_SECTION; } } else { if ((desc & 0x3) == 0x1) return DESC_TYPE_LARGE_PAGE; if ((desc & 0x2) == 0x2) return DESC_TYPE_SMALL_PAGE; } return DESC_TYPE_INVALID; } static uint32_t texcb_to_mattr(uint32_t texcb) { COMPILE_TIME_ASSERT(ATTR_DEVICE_INDEX == TEE_MATTR_MEM_TYPE_DEV); COMPILE_TIME_ASSERT(ATTR_NORMAL_CACHED_INDEX == TEE_MATTR_MEM_TYPE_CACHED); COMPILE_TIME_ASSERT(ATTR_STRONG_O_INDEX == TEE_MATTR_MEM_TYPE_STRONGLY_O); COMPILE_TIME_ASSERT(ATTR_TAGGED_CACHED_INDEX == TEE_MATTR_MEM_TYPE_TAGGED); return texcb << TEE_MATTR_MEM_TYPE_SHIFT; } static uint32_t mattr_to_texcb(uint32_t attr) { /* Keep in sync with core_mmu.c:core_mmu_mattr_is_ok */ return (attr >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK; } static uint32_t desc_to_mattr(unsigned level, uint32_t desc) { uint32_t a; switch (get_desc_type(level, desc)) { case DESC_TYPE_PAGE_TABLE: a = TEE_MATTR_TABLE; if (!(desc & SECTION_PT_NOTSECURE)) a |= TEE_MATTR_SECURE; break; case DESC_TYPE_SECTION: a = TEE_MATTR_VALID_BLOCK; if (desc & SECTION_ACCESS_FLAG) a |= TEE_MATTR_PRX | TEE_MATTR_URX; if (!(desc & SECTION_RO)) a |= TEE_MATTR_PW | TEE_MATTR_UW; if (desc & SECTION_XN) a &= ~(TEE_MATTR_PX | TEE_MATTR_UX); if (desc & SECTION_PXN) a &= ~TEE_MATTR_PX; a |= texcb_to_mattr(((desc >> 12) & 0x7) | ((desc >> 2) & 0x3)); if (!(desc & SECTION_NOTGLOBAL)) a |= TEE_MATTR_GLOBAL; if (!(desc & SECTION_NOTSECURE)) a |= TEE_MATTR_SECURE; break; case DESC_TYPE_SMALL_PAGE: a = TEE_MATTR_VALID_BLOCK; if (desc & SMALL_PAGE_ACCESS_FLAG) a |= TEE_MATTR_PRX | TEE_MATTR_URX; if (!(desc & SMALL_PAGE_RO)) a |= TEE_MATTR_PW | TEE_MATTR_UW; if (desc & SMALL_PAGE_XN) a &= ~(TEE_MATTR_PX | TEE_MATTR_UX); a |= texcb_to_mattr(((desc >> 6) & 0x7) | ((desc >> 2) & 0x3)); if (!(desc & SMALL_PAGE_NOTGLOBAL)) a |= TEE_MATTR_GLOBAL; break; default: return 0; } return a; } static uint32_t mattr_to_desc(unsigned level, uint32_t attr) { uint32_t desc; uint32_t a = attr; unsigned texcb; if (level == 1 && (a & TEE_MATTR_TABLE)) { desc = SECTION_PT_PT; if (!(a & TEE_MATTR_SECURE)) desc |= SECTION_PT_NOTSECURE; return desc; } if (!(a & TEE_MATTR_VALID_BLOCK)) return INVALID_DESC; if (a & (TEE_MATTR_PX | TEE_MATTR_PW)) a |= TEE_MATTR_PR; if (a & (TEE_MATTR_UX | TEE_MATTR_UW)) a |= TEE_MATTR_UR; if (a & TEE_MATTR_UR) a |= TEE_MATTR_PR; if (a & TEE_MATTR_UW) a |= TEE_MATTR_PW; texcb = mattr_to_texcb(a); if (level == 1) { /* Section */ #ifndef CFG_NO_SMP desc = SECTION_SECTION | SECTION_SHARED; #else desc = SECTION_SECTION; #endif if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX))) desc |= SECTION_XN; #ifdef CFG_HWSUPP_MEM_PERM_PXN if (!(a & TEE_MATTR_PX)) desc |= SECTION_PXN; #endif if (a & TEE_MATTR_UR) desc |= SECTION_UNPRIV; if (!(a & TEE_MATTR_PW)) desc |= SECTION_RO; if (a & (TEE_MATTR_UR | TEE_MATTR_PR)) desc |= SECTION_ACCESS_FLAG; if (!(a & TEE_MATTR_GLOBAL)) desc |= SECTION_NOTGLOBAL; if (!(a & TEE_MATTR_SECURE)) desc |= SECTION_NOTSECURE; desc |= SECTION_TEXCB(texcb); } else { #ifndef CFG_NO_SMP desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED; #else desc = SMALL_PAGE_SMALL_PAGE; #endif if (!(a & (TEE_MATTR_PX | TEE_MATTR_UX))) desc |= SMALL_PAGE_XN; if (a & TEE_MATTR_UR) desc |= SMALL_PAGE_UNPRIV; if (!(a & TEE_MATTR_PW)) desc |= SMALL_PAGE_RO; if (a & (TEE_MATTR_UR | TEE_MATTR_PR)) desc |= SMALL_PAGE_ACCESS_FLAG; if (!(a & TEE_MATTR_GLOBAL)) desc |= SMALL_PAGE_NOTGLOBAL; desc |= SMALL_PAGE_TEXCB(texcb); } return desc; } void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, unsigned level, vaddr_t va_base, void *table) { tbl_info->level = level; tbl_info->next_level = level + 1; tbl_info->table = table; tbl_info->va_base = va_base; assert(level <= 2); if (level == 1) { tbl_info->shift = SECTION_SHIFT; tbl_info->num_entries = NUM_L1_ENTRIES; } else { tbl_info->shift = SMALL_PAGE_SHIFT; tbl_info->num_entries = NUM_L2_ENTRIES; } } void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info) { void *tbl = (void *)core_mmu_get_ul1_ttb_va(get_prtn()); core_mmu_set_info_table(pgd_info, 1, 0, tbl); pgd_info->num_entries = NUM_UL1_ENTRIES; } void core_mmu_create_user_map(struct user_mode_ctx *uctx, struct core_mmu_user_map *map) { struct core_mmu_table_info dir_info = { }; COMPILE_TIME_ASSERT(L2_TBL_SIZE == PGT_SIZE); core_mmu_get_user_pgdir(&dir_info); memset(dir_info.table, 0, dir_info.num_entries * sizeof(uint32_t)); core_mmu_populate_user_map(&dir_info, uctx); map->ttbr0 = core_mmu_get_ul1_ttb_pa(get_prtn()) | TEE_MMU_DEFAULT_ATTRS; map->ctxid = uctx->vm_info.asid; } bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, unsigned max_level, struct core_mmu_table_info *tbl_info) { uint32_t *tbl; unsigned n = va >> SECTION_SHIFT; if (!prtn) prtn = get_prtn(); tbl = (uint32_t *)core_mmu_get_main_ttb_va(prtn); if (max_level == 1 || (tbl[n] & 0x3) != 0x1) { core_mmu_set_info_table(tbl_info, 1, 0, tbl); } else { paddr_t ntbl = tbl[n] & ~((1 << 10) - 1); void *l2tbl = phys_to_virt(ntbl, MEM_AREA_TEE_RAM_RW_DATA, L2_TBL_SIZE); if (!l2tbl) return false; core_mmu_set_info_table(tbl_info, 2, n << SECTION_SHIFT, l2tbl); } return true; } void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, paddr_t pa, uint32_t attr) { uint32_t *tbl = table; uint32_t desc = mattr_to_desc(level, attr); tbl[idx] = desc | pa; } static paddr_t desc_to_pa(unsigned level, uint32_t desc) { unsigned shift_mask; switch (get_desc_type(level, desc)) { case DESC_TYPE_PAGE_TABLE: shift_mask = 10; break; case DESC_TYPE_SECTION: shift_mask = 20; break; case DESC_TYPE_SUPER_SECTION: shift_mask = 24; /* We're ignoring bits 32 and above. */ break; case DESC_TYPE_LARGE_PAGE: shift_mask = 16; break; case DESC_TYPE_SMALL_PAGE: shift_mask = 12; break; default: /* Invalid section */ shift_mask = 4; } return desc & ~((1 << shift_mask) - 1); } bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, unsigned int idx, bool secure) { uint32_t *new_table; uint32_t *entry; uint32_t new_table_desc; uint32_t attr; uint32_t desc; paddr_t pa; int i; if (tbl_info->level != 1) return false; if (idx >= NUM_L1_ENTRIES) return false; entry = (uint32_t *)tbl_info->table + idx; attr = desc_to_mattr(1, *entry); if (*entry && get_desc_type(1, *entry) == DESC_TYPE_PAGE_TABLE) { /* * If there is page table already, * check the secure attribute fits */ return secure == (bool)(attr & TEE_MATTR_SECURE); } /* If there is something mapped, check the secure access flag */ if (attr && secure != (bool)(attr & TEE_MATTR_SECURE)) return false; new_table = core_mmu_alloc_l2(get_prtn(), NUM_L2_ENTRIES * SMALL_PAGE_SIZE); if (!new_table) return false; new_table_desc = SECTION_PT_PT | virt_to_phys(new_table); if (!secure) new_table_desc |= SECTION_PT_NOTSECURE; if (*entry) { pa = desc_to_pa(1, *entry); desc = mattr_to_desc(2, attr); for (i = 0; i < NUM_L2_ENTRIES; i++, pa += SMALL_PAGE_SIZE) new_table[i] = desc | pa; } /* Update descriptor at current level */ *entry = new_table_desc; return true; } void core_mmu_get_entry_primitive(const void *table, size_t level, size_t idx, paddr_t *pa, uint32_t *attr) { const uint32_t *tbl = table; if (pa) *pa = desc_to_pa(level, tbl[idx]); if (attr) *attr = desc_to_mattr(level, tbl[idx]); } void core_mmu_get_user_va_range(vaddr_t *base, size_t *size) { if (base) { /* Leaving the first entry unmapped to make NULL unmapped */ *base = 1 << SECTION_SHIFT; } if (size) *size = (NUM_UL1_ENTRIES - 1) << SECTION_SHIFT; } void core_mmu_get_user_map(struct core_mmu_user_map *map) { map->ttbr0 = read_ttbr0(); map->ctxid = read_contextidr(); } void core_mmu_set_user_map(struct core_mmu_user_map *map) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); /* * Update the reserved Context ID and TTBR0 */ dsb(); /* ARM erratum 754322 */ write_contextidr(0); isb(); if (map) { write_ttbr0(map->ttbr0); isb(); write_contextidr(map->ctxid); isb(); } else { write_ttbr0(read_ttbr1()); isb(); } tlbi_all(); icache_inv_all(); /* Restore interrupts */ thread_unmask_exceptions(exceptions); } bool core_mmu_user_mapping_is_active(void) { bool ret; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); ret = read_ttbr0() != read_ttbr1(); thread_unmask_exceptions(exceptions); return ret; } static void print_mmap_area(const struct tee_mmap_region *mm __maybe_unused, const char *str __maybe_unused) { if (!(mm->attr & TEE_MATTR_VALID_BLOCK)) debug_print("%s [%08" PRIxVA " %08" PRIxVA "] not mapped", str, mm->va, mm->va + mm->size); else debug_print("%s [%08" PRIxVA " %08" PRIxVA "] %s-%s-%s-%s", str, mm->va, mm->va + mm->size, mattr_is_cached(mm->attr) ? "MEM" : "DEV", mm->attr & TEE_MATTR_PW ? "RW" : "RO", mm->attr & TEE_MATTR_PX ? "X" : "XN", mm->attr & TEE_MATTR_SECURE ? "S" : "NS"); } void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb) { uint32_t attr = mattr_to_desc(1, mm->attr); size_t idx = mm->va >> SECTION_SHIFT; paddr_t pa = 0; size_t n; if (core_mmap_is_end_of_table(mm)) return; print_mmap_area(mm, "section map"); attr = mattr_to_desc(1, mm->attr); if (attr != INVALID_DESC) pa = mm->pa; n = ROUNDUP(mm->size, SECTION_SIZE) >> SECTION_SHIFT; while (n--) { assert(!attr || !ttb[idx] || ttb[idx] == (pa | attr)); ttb[idx] = pa | attr; idx++; pa += SECTION_SIZE; } } void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm) { void *ttb1 = (void *)core_mmu_get_main_ttb_va(prtn); size_t n; /* reset L1 table */ memset(ttb1, 0, L1_TBL_SIZE); for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) if (!core_mmu_is_dynamic_vaspace(mm + n)) core_mmu_map_region(prtn, mm + n); } void core_init_mmu(struct tee_mmap_region *mm) { /* Initialize default pagetables */ core_init_mmu_prtn(&default_partition, mm); } void core_init_mmu_regs(struct core_mmu_config *cfg) { cfg->ttbr = core_mmu_get_main_ttb_pa(&default_partition) | TEE_MMU_DEFAULT_ATTRS; cfg->prrr = ATTR_DEVICE_PRRR | ATTR_NORMAL_CACHED_PRRR | ATTR_STRONGLY_O_PRRR | ATTR_TAGGED_CACHED_PRRR; cfg->nmrr = ATTR_DEVICE_NMRR | ATTR_NORMAL_CACHED_NMRR | ATTR_STRONGLY_O_NMRR | ATTR_TAGGED_CACHED_NMRR; cfg->prrr |= PRRR_NS1 | PRRR_DS1; /* * Program Domain access control register with two domains: * domain 0: teecore * domain 1: TA */ cfg->dacr = DACR_DOMAIN(0, DACR_DOMAIN_PERM_CLIENT) | DACR_DOMAIN(1, DACR_DOMAIN_PERM_CLIENT); /* * Enable lookups using TTBR0 and TTBR1 with the split of addresses * defined by TEE_MMU_TTBCR_N_VALUE. */ cfg->ttbcr = TTBCR_N_VALUE; } enum core_mmu_fault core_mmu_get_fault_type(uint32_t fsr) { assert(!(fsr & FSR_LPAE)); switch (fsr & FSR_FS_MASK) { case 0x1: /* DFSR[10,3:0] 0b00001 Alignment fault (DFSR only) */ return CORE_MMU_FAULT_ALIGNMENT; case 0x2: /* DFSR[10,3:0] 0b00010 Debug event */ return CORE_MMU_FAULT_DEBUG_EVENT; case 0x4: /* DFSR[10,3:0] b00100 Fault on instr cache maintenance */ case 0x5: /* DFSR[10,3:0] b00101 Translation fault first level */ case 0x7: /* DFSR[10,3:0] b00111 Translation fault second level */ return CORE_MMU_FAULT_TRANSLATION; case 0xd: /* DFSR[10,3:0] b01101 Permission fault first level */ case 0xf: /* DFSR[10,3:0] b01111 Permission fault second level */ if (fsr & FSR_WNR) return CORE_MMU_FAULT_WRITE_PERMISSION; else return CORE_MMU_FAULT_READ_PERMISSION; case 0x3: /* DFSR[10,3:0] b00011 access bit fault on section */ case 0x6: /* DFSR[10,3:0] b00110 access bit fault on page */ return CORE_MMU_FAULT_ACCESS_BIT; case (1 << 10) | 0x6: /* DFSR[10,3:0] 0b10110 Async external abort (DFSR only) */ return CORE_MMU_FAULT_ASYNC_EXTERNAL; default: return CORE_MMU_FAULT_OTHER; } } optee_os-4.3.0/core/arch/arm/mm/mobj_ffa.c000066400000000000000000000460711464416617300203230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include /* * Life cycle of struct mobj_ffa * * SPMC at S-EL1 (CFG_CORE_SEL1_SPMC=y) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * During FFA_MEM_SHARE allocated in mobj_ffa_sel1_spmc_new() and finally * added to the inactive list at the end of add_mem_share() once * successfully filled in. * registered_by_cookie = false * mobj.refs.val = 0 * inactive_refs = 0 * * During FFA_MEM_RECLAIM reclaimed/freed using * mobj_ffa_sel1_spmc_reclaim(). This will always succeed if the normal * world is only calling this when all other threads are done with the * shared memory object. However, there are some conditions that must be * met to make sure that this is the case: * mobj not in the active list, else -> return TEE_ERROR_BUSY * mobj not in inactive list, else -> return TEE_ERROR_ITEM_NOT_FOUND * mobj inactive_refs is 0, else -> return TEE_ERROR_BUSY * * mobj is activated using mobj_ffa_get_by_cookie() which unless the mobj * is active already: * - move the mobj into the active list * - if not registered_by_cookie -> * set registered_by_cookie and increase inactive_refs * - set mobj.refc.val to 1 * - increase inactive_refs * * A previously activated mobj is made ready for reclaim using * mobj_ffa_unregister_by_cookie() which only succeeds if the mobj is in * the inactive list and registered_by_cookie is set and then: * - clears registered_by_cookie * - decreases inactive_refs * * Each successful call to mobj_ffa_get_by_cookie() must be matched by a * call to mobj_put(). If the mobj.refc.val reaches 0 it's * - moved to the inactive list * - inactive_refs is decreased * * SPMC at S-EL2/EL3 (CFG_CORE_SEL1_SPMC=n) * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * mobj is activated/allocated using mobj_ffa_get_by_cookie() which if * already active only is * - increasing mobj.refc.val and inactive_refs * if found in inactive list is * - setting mobj.refc.val to 1 * - increasing inactive_refs * - moved into active list * if not found is created using thread_spmc_populate_mobj_from_rx() and * then: * - setting mobj.refc.val to 1 * - increasing inactive_refs * - moved into active list * * A previously activated mobj is relinquished using * mobj_ffa_unregister_by_cookie() which only succeeds if the mobj is in * the inactive list and inactive_refs is 1 */ struct mobj_ffa { struct mobj mobj; SLIST_ENTRY(mobj_ffa) link; uint64_t cookie; tee_mm_entry_t *mm; struct refcount mapcount; unsigned int inactive_refs; uint16_t page_offset; #ifdef CFG_CORE_SEL1_SPMC bool registered_by_cookie; #endif paddr_t pages[]; }; SLIST_HEAD(mobj_ffa_head, mobj_ffa); #ifdef CFG_CORE_SEL1_SPMC #ifdef CFG_NS_VIRTUALIZATION static bitstr_t *get_shm_bits(void) { return virt_get_shm_bits(); } #else static bitstr_t bit_decl(__shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT); static bitstr_t *get_shm_bits(void) { return __shm_bits; } #endif #endif static struct mobj_ffa_head shm_head = SLIST_HEAD_INITIALIZER(shm_head); static struct mobj_ffa_head shm_inactive_head = SLIST_HEAD_INITIALIZER(shm_inactive_head); static unsigned int shm_lock = SPINLOCK_UNLOCK; static const struct mobj_ops mobj_ffa_ops; static struct mobj_ffa *to_mobj_ffa(struct mobj *mobj) { assert(mobj->ops == &mobj_ffa_ops); return container_of(mobj, struct mobj_ffa, mobj); } static size_t shm_size(size_t num_pages) { size_t s = 0; if (MUL_OVERFLOW(sizeof(paddr_t), num_pages, &s)) return 0; if (ADD_OVERFLOW(sizeof(struct mobj_ffa), s, &s)) return 0; return s; } static struct mobj_ffa *ffa_new(unsigned int num_pages) { struct mobj_ffa *mf = NULL; size_t s = 0; if (!num_pages) return NULL; s = shm_size(num_pages); if (!s) return NULL; mf = calloc(1, s); if (!mf) return NULL; mf->mobj.ops = &mobj_ffa_ops; mf->mobj.size = num_pages * SMALL_PAGE_SIZE; mf->mobj.phys_granule = SMALL_PAGE_SIZE; refcount_set(&mf->mobj.refc, 0); mf->inactive_refs = 0; return mf; } #ifdef CFG_CORE_SEL1_SPMC struct mobj_ffa *mobj_ffa_sel1_spmc_new(uint64_t cookie, unsigned int num_pages) { struct mobj_ffa *mf = NULL; bitstr_t *shm_bits = NULL; uint32_t exceptions = 0; int i = 0; if (cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) { if (!(cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT)) return NULL; if (virt_add_cookie_to_current_guest(cookie)) return NULL; } mf = ffa_new(num_pages); if (!mf) { if (cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) virt_remove_cookie(cookie); return NULL; } if (cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID) { mf->cookie = cookie; return mf; } shm_bits = get_shm_bits(); exceptions = cpu_spin_lock_xsave(&shm_lock); bit_ffc(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i); if (i != -1) { bit_set(shm_bits, i); mf->cookie = i; mf->cookie |= FFA_MEMORY_HANDLE_NON_SECURE_BIT; /* * Encode the partition ID into the handle so we know which * partition to switch to when reclaiming a handle. */ mf->cookie |= SHIFT_U64(virt_get_current_guest_id(), FFA_MEMORY_HANDLE_PRTN_SHIFT); } cpu_spin_unlock_xrestore(&shm_lock, exceptions); if (i == -1) { free(mf); return NULL; } return mf; } #endif /*CFG_CORE_SEL1_SPMC*/ static size_t get_page_count(struct mobj_ffa *mf) { return ROUNDUP(mf->mobj.size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; } static bool cmp_cookie(struct mobj_ffa *mf, uint64_t cookie) { return mf->cookie == cookie; } static bool cmp_ptr(struct mobj_ffa *mf, uint64_t ptr) { return mf == (void *)(vaddr_t)ptr; } static struct mobj_ffa *pop_from_list(struct mobj_ffa_head *head, bool (*cmp_func)(struct mobj_ffa *mf, uint64_t val), uint64_t val) { struct mobj_ffa *mf = SLIST_FIRST(head); struct mobj_ffa *p = NULL; if (!mf) return NULL; if (cmp_func(mf, val)) { SLIST_REMOVE_HEAD(head, link); return mf; } while (true) { p = SLIST_NEXT(mf, link); if (!p) return NULL; if (cmp_func(p, val)) { SLIST_REMOVE_AFTER(mf, link); return p; } mf = p; } } static struct mobj_ffa *find_in_list(struct mobj_ffa_head *head, bool (*cmp_func)(struct mobj_ffa *mf, uint64_t val), uint64_t val) { struct mobj_ffa *mf = NULL; SLIST_FOREACH(mf, head, link) if (cmp_func(mf, val)) return mf; return NULL; } #if defined(CFG_CORE_SEL1_SPMC) void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf) { if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || !(mf->cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT)) { uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT; bitstr_t *shm_bits = get_shm_bits(); uint32_t exceptions = 0; int64_t i = 0; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) mask |= SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK, FFA_MEMORY_HANDLE_PRTN_SHIFT); i = mf->cookie & ~mask; assert(i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT); exceptions = cpu_spin_lock_xsave(&shm_lock); assert(bit_test(shm_bits, i)); bit_clear(shm_bits, i); cpu_spin_unlock_xrestore(&shm_lock, exceptions); } assert(!mf->mm); free(mf); } #else /* !defined(CFG_CORE_SEL1_SPMC) */ struct mobj_ffa *mobj_ffa_spmc_new(uint64_t cookie, unsigned int num_pages) { struct mobj_ffa *mf = NULL; assert(cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID); mf = ffa_new(num_pages); if (mf) mf->cookie = cookie; return mf; } void mobj_ffa_spmc_delete(struct mobj_ffa *mf) { free(mf); } #endif /* !defined(CFG_CORE_SEL1_SPMC) */ TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mf, unsigned int *idx, paddr_t pa, unsigned int num_pages) { unsigned int n = 0; size_t tot_page_count = get_page_count(mf); if (ADD_OVERFLOW(*idx, num_pages, &n) || n > tot_page_count) return TEE_ERROR_BAD_PARAMETERS; if (!IS_ENABLED(CFG_CORE_SEL2_SPMC) && !core_pbuf_is(CORE_MEM_NON_SEC, pa, num_pages * SMALL_PAGE_SIZE)) return TEE_ERROR_BAD_PARAMETERS; for (n = 0; n < num_pages; n++) mf->pages[n + *idx] = pa + n * SMALL_PAGE_SIZE; (*idx) += n; return TEE_SUCCESS; } uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mf) { return mf->cookie; } uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mf) { uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&shm_lock); assert(!find_in_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf)); assert(!find_in_list(&shm_inactive_head, cmp_cookie, mf->cookie)); assert(!find_in_list(&shm_head, cmp_cookie, mf->cookie)); SLIST_INSERT_HEAD(&shm_inactive_head, mf, link); cpu_spin_unlock_xrestore(&shm_lock, exceptions); return mf->cookie; } static void unmap_helper(struct mobj_ffa *mf) { if (mf->mm) { core_mmu_unmap_pages(tee_mm_get_smem(mf->mm), get_page_count(mf)); tee_mm_free(mf->mm); mf->mm = NULL; } } #ifdef CFG_CORE_SEL1_SPMC TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie) { TEE_Result res = TEE_SUCCESS; struct mobj_ffa *mf = NULL; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&shm_lock); mf = find_in_list(&shm_head, cmp_cookie, cookie); /* * If the mobj is found here it's still active and cannot be * reclaimed. */ if (mf) { DMSG("cookie %#"PRIx64" busy refc %u", cookie, refcount_val(&mf->mobj.refc)); res = TEE_ERROR_BUSY; goto out; } mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie); if (!mf) { res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } /* * If the mobj has been registered via mobj_ffa_get_by_cookie() * but not unregistered yet with mobj_ffa_unregister_by_cookie(). */ if (mf->inactive_refs) { DMSG("cookie %#"PRIx64" busy inactive_refs %u", cookie, mf->inactive_refs); res = TEE_ERROR_BUSY; goto out; } if (!pop_from_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf)) panic(); res = TEE_SUCCESS; out: cpu_spin_unlock_xrestore(&shm_lock, exceptions); if (!res) { mobj_ffa_sel1_spmc_delete(mf); virt_remove_cookie(cookie); } return res; } #endif /*CFG_CORE_SEL1_SPMC*/ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie) { TEE_Result res = TEE_SUCCESS; struct mobj_ffa *mf = NULL; uint32_t exceptions = 0; assert(cookie != OPTEE_MSG_FMEM_INVALID_GLOBAL_ID); exceptions = cpu_spin_lock_xsave(&shm_lock); mf = find_in_list(&shm_head, cmp_cookie, cookie); /* * If the mobj is found here it's still active and cannot be * unregistered. */ if (mf) { EMSG("cookie %#"PRIx64" busy refc %u:%u", cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); res = TEE_ERROR_BUSY; goto out; } mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie); /* * If the mobj isn't found or if it already has been unregistered. */ if (!mf) { EMSG("cookie %#"PRIx64" not found", cookie); res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } #if defined(CFG_CORE_SEL1_SPMC) if (!mf->registered_by_cookie) { /* * This is expected behaviour if the normal world has * registered the memory but OP-TEE has not yet used the * corresponding cookie with mobj_ffa_get_by_cookie(). It * can be non-trivial for the normal world to predict if * the cookie really has been used or not. So even if we * return it as an error it will be ignored by * handle_unregister_shm(). */ EMSG("cookie %#"PRIx64" not registered refs %u:%u", cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } assert(mf->inactive_refs); mf->inactive_refs--; mf->registered_by_cookie = false; #else if (mf->inactive_refs) { EMSG("cookie %#"PRIx64" busy refc %u:%u", cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); res = TEE_ERROR_BUSY; goto out; } mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie); mobj_ffa_spmc_delete(mf); thread_spmc_relinquish(cookie); #endif res = TEE_SUCCESS; out: cpu_spin_unlock_xrestore(&shm_lock, exceptions); return res; } struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs) { struct mobj_ffa *mf = NULL; uint32_t exceptions = 0; if (internal_offs >= SMALL_PAGE_SIZE) return NULL; exceptions = cpu_spin_lock_xsave(&shm_lock); mf = find_in_list(&shm_head, cmp_cookie, cookie); if (mf) { if (mf->page_offset == internal_offs) { if (!refcount_inc(&mf->mobj.refc)) { /* * If refcount is 0 some other thread has * called mobj_put() on this reached 0 and * before ffa_inactivate() got the lock we * found it. Let's reinitialize it. */ refcount_set(&mf->mobj.refc, 1); mf->inactive_refs++; } DMSG("cookie %#"PRIx64" active: refc %u:%u", cookie, refcount_val(&mf->mobj.refc), mf->inactive_refs); } else { EMSG("cookie %#"PRIx64" mismatching internal_offs got %#"PRIx16" expected %#x", cookie, mf->page_offset, internal_offs); mf = NULL; } } else { mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie); #if !defined(CFG_CORE_SEL1_SPMC) /* Try to retrieve it from the SPM at S-EL2 */ if (mf) { DMSG("cookie %#"PRIx64" resurrecting", cookie); } else { DMSG("Populating mobj from rx buffer, cookie %#"PRIx64, cookie); mf = thread_spmc_populate_mobj_from_rx(cookie); } #endif if (mf) { #if defined(CFG_CORE_SEL1_SPMC) if (!mf->registered_by_cookie) { mf->inactive_refs++; mf->registered_by_cookie = true; } #endif assert(refcount_val(&mf->mobj.refc) == 0); refcount_set(&mf->mobj.refc, 1); refcount_set(&mf->mapcount, 0); mf->inactive_refs++; /* * mf->page_offset is offset into the first page. * This offset is assigned from the internal_offs * parameter to this function. * * While a mobj_ffa is active (ref_count > 0) this * will not change, but when being pushed to the * inactive list it can be changed again. * * So below we're backing out the old * mf->page_offset and then assigning a new from * internal_offset. */ mf->mobj.size += mf->page_offset; assert(!(mf->mobj.size & SMALL_PAGE_MASK)); mf->mobj.size -= internal_offs; mf->page_offset = internal_offs; SLIST_INSERT_HEAD(&shm_head, mf, link); } } cpu_spin_unlock_xrestore(&shm_lock, exceptions); if (!mf) { EMSG("Failed to get cookie %#"PRIx64" internal_offs %#x", cookie, internal_offs); return NULL; } return &mf->mobj; } static TEE_Result ffa_get_pa(struct mobj *mobj, size_t offset, size_t granule, paddr_t *pa) { struct mobj_ffa *mf = to_mobj_ffa(mobj); size_t full_offset = 0; paddr_t p = 0; if (!pa) return TEE_ERROR_GENERIC; if (offset >= mobj->size) return TEE_ERROR_GENERIC; full_offset = offset + mf->page_offset; switch (granule) { case 0: p = mf->pages[full_offset / SMALL_PAGE_SIZE] + (full_offset & SMALL_PAGE_MASK); break; case SMALL_PAGE_SIZE: p = mf->pages[full_offset / SMALL_PAGE_SIZE]; break; default: return TEE_ERROR_GENERIC; } *pa = p; return TEE_SUCCESS; } static size_t ffa_get_phys_offs(struct mobj *mobj, size_t granule __maybe_unused) { assert(granule >= mobj->phys_granule); return to_mobj_ffa(mobj)->page_offset; } static void *ffa_get_va(struct mobj *mobj, size_t offset, size_t len) { struct mobj_ffa *mf = to_mobj_ffa(mobj); if (!mf->mm || !mobj_check_offset_and_len(mobj, offset, len)) return NULL; return (void *)(tee_mm_get_smem(mf->mm) + offset + mf->page_offset); } static void ffa_inactivate(struct mobj *mobj) { struct mobj_ffa *mf = to_mobj_ffa(mobj); uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&shm_lock); /* * If refcount isn't 0 some other thread has found this mobj in * shm_head after the mobj_put() that put us here and before we got * the lock. */ if (refcount_val(&mobj->refc)) { DMSG("cookie %#"PRIx64" was resurrected", mf->cookie); goto out; } /* * pop_from_list() can fail to find the mobj if we had just * decreased the refcount to 0 in mobj_put() and was going to * acquire the shm_lock but another thread found this mobj and * reinitialized the refcount to 1. Then before we got cpu time the * other thread called mobj_put() and deactivated the mobj again. * * However, we still have the inactive count that guarantees * that the mobj can't be freed until it reaches 0. * At this point the mobj is in the inactive list. */ if (pop_from_list(&shm_head, cmp_ptr, (vaddr_t)mf)) { unmap_helper(mf); SLIST_INSERT_HEAD(&shm_inactive_head, mf, link); } out: if (!mf->inactive_refs) panic(); mf->inactive_refs--; cpu_spin_unlock_xrestore(&shm_lock, exceptions); } static TEE_Result ffa_get_mem_type(struct mobj *mobj __unused, uint32_t *mt) { if (!mt) return TEE_ERROR_GENERIC; *mt = TEE_MATTR_MEM_TYPE_CACHED; return TEE_SUCCESS; } static bool ffa_matches(struct mobj *mobj __maybe_unused, enum buf_is_attr attr) { assert(mobj->ops == &mobj_ffa_ops); return attr == CORE_MEM_NON_SEC || attr == CORE_MEM_REG_SHM; } static uint64_t ffa_get_cookie(struct mobj *mobj) { return to_mobj_ffa(mobj)->cookie; } static TEE_Result ffa_inc_map(struct mobj *mobj) { TEE_Result res = TEE_SUCCESS; struct mobj_ffa *mf = to_mobj_ffa(mobj); uint32_t exceptions = 0; size_t sz = 0; while (true) { if (refcount_inc(&mf->mapcount)) return TEE_SUCCESS; exceptions = cpu_spin_lock_xsave(&shm_lock); if (!refcount_val(&mf->mapcount)) break; /* continue to reinitialize */ /* * If another thread beat us to initialize mapcount, * restart to make sure we still increase it. */ cpu_spin_unlock_xrestore(&shm_lock, exceptions); } /* * If we have beated another thread calling ffa_dec_map() * to get the lock we need only to reinitialize mapcount to 1. */ if (!mf->mm) { sz = ROUNDUP(mobj->size + mf->page_offset, SMALL_PAGE_SIZE); mf->mm = tee_mm_alloc(&core_virt_shm_pool, sz); if (!mf->mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = core_mmu_map_pages(tee_mm_get_smem(mf->mm), mf->pages, sz / SMALL_PAGE_SIZE, MEM_AREA_NSEC_SHM); if (res) { tee_mm_free(mf->mm); mf->mm = NULL; goto out; } } refcount_set(&mf->mapcount, 1); out: cpu_spin_unlock_xrestore(&shm_lock, exceptions); return res; } static TEE_Result ffa_dec_map(struct mobj *mobj) { struct mobj_ffa *mf = to_mobj_ffa(mobj); uint32_t exceptions = 0; if (!refcount_dec(&mf->mapcount)) return TEE_SUCCESS; exceptions = cpu_spin_lock_xsave(&shm_lock); if (!refcount_val(&mf->mapcount)) unmap_helper(mf); cpu_spin_unlock_xrestore(&shm_lock, exceptions); return TEE_SUCCESS; } static TEE_Result mapped_shm_init(void) { vaddr_t pool_start = 0; vaddr_t pool_end = 0; core_mmu_get_mem_by_type(MEM_AREA_SHM_VASPACE, &pool_start, &pool_end); if (!pool_start || !pool_end) panic("Can't find region for shmem pool"); if (!tee_mm_init(&core_virt_shm_pool, pool_start, pool_end - pool_start, SMALL_PAGE_SHIFT, TEE_MM_POOL_NO_FLAGS)) panic("Could not create shmem pool"); DMSG("Shared memory address range: %#"PRIxVA", %#"PRIxVA, pool_start, pool_end); return TEE_SUCCESS; } static const struct mobj_ops mobj_ffa_ops = { .get_pa = ffa_get_pa, .get_phys_offs = ffa_get_phys_offs, .get_va = ffa_get_va, .get_mem_type = ffa_get_mem_type, .matches = ffa_matches, .free = ffa_inactivate, .get_cookie = ffa_get_cookie, .inc_map = ffa_inc_map, .dec_map = ffa_dec_map, }; preinit(mapped_shm_init); optee_os-4.3.0/core/arch/arm/mm/sp_mem.c000066400000000000000000000163321464416617300200350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2022, Arm Limited. All rights reserved. */ #include #include #include #include #include #include #define NUM_SHARES 64 static bitstr_t bit_decl(share_bits, NUM_SHARES); static unsigned int sp_mem_lock = SPINLOCK_UNLOCK; /* mem_shares stores all active FF-A shares. */ SLIST_HEAD(sp_mem_head, sp_mem); static struct sp_mem_head mem_shares = SLIST_HEAD_INITIALIZER(sp_mem_head); static const struct mobj_ops mobj_sp_ops; struct mobj_sp { struct mobj mobj; uint32_t mem_type; bool is_secure; paddr_t pages[]; }; static struct mobj_sp *to_mobj_sp(struct mobj *mobj) { assert(mobj->ops == &mobj_sp_ops); return container_of(mobj, struct mobj_sp, mobj); } static size_t mobj_sp_size(size_t num_pages) { size_t s = 0; if (MUL_OVERFLOW(sizeof(paddr_t), num_pages, &s)) return 0; if (ADD_OVERFLOW(sizeof(struct mobj_sp), s, &s)) return 0; return s; } struct mobj *sp_mem_new_mobj(uint64_t pages, uint32_t mem_type, bool is_secure) { struct mobj_sp *m = NULL; size_t s = 0; s = mobj_sp_size(pages); if (!s) return NULL; m = calloc(1, s); if (!m) return NULL; m->mobj.ops = &mobj_sp_ops; m->mobj.size = pages * SMALL_PAGE_SIZE; m->mobj.phys_granule = SMALL_PAGE_SIZE; m->mem_type = mem_type; m->is_secure = is_secure; refcount_set(&m->mobj.refc, 1); return &m->mobj; } static size_t get_page_count(struct mobj_sp *ms) { return ROUNDUP(ms->mobj.size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; } /* Add some physical pages to the mobj object. */ int sp_mem_add_pages(struct mobj *mobj, unsigned int *idx, paddr_t pa, unsigned int num_pages) { struct mobj_sp *ms = to_mobj_sp(mobj); unsigned int n = 0; size_t tot_page_count = get_page_count(ms); if (ADD_OVERFLOW(*idx, num_pages, &n) || n > tot_page_count) return TEE_ERROR_BAD_PARAMETERS; /* Don't check for device memory */ if (ms->mem_type == TEE_MATTR_MEM_TYPE_CACHED) { if (ms->is_secure) { if (!tee_pbuf_is_sec(pa, num_pages * SMALL_PAGE_SIZE)) return TEE_ERROR_BAD_PARAMETERS; } else { if (!tee_pbuf_is_non_sec(pa, num_pages * SMALL_PAGE_SIZE)) return TEE_ERROR_BAD_PARAMETERS; } } for (n = 0; n < num_pages; n++) ms->pages[n + *idx] = pa + n * SMALL_PAGE_SIZE; *idx += n; return TEE_SUCCESS; } static TEE_Result get_mem_type(struct mobj *mobj, uint32_t *mt) { struct mobj_sp *m = to_mobj_sp(mobj); *mt = m->mem_type; return TEE_SUCCESS; } static bool mobj_sp_matches(struct mobj *mobj, enum buf_is_attr attr) { struct mobj_sp *m = to_mobj_sp(mobj); if (m->is_secure) return attr == CORE_MEM_SEC; else return attr == CORE_MEM_NON_SEC || attr == CORE_MEM_REG_SHM; } static TEE_Result get_pa(struct mobj *mobj, size_t offset, size_t granule, paddr_t *pa) { struct mobj_sp *ms = to_mobj_sp(mobj); paddr_t p = 0; if (!pa) return TEE_ERROR_GENERIC; if (offset >= mobj->size) return TEE_ERROR_GENERIC; switch (granule) { case 0: p = ms->pages[offset / SMALL_PAGE_SIZE] + (offset & SMALL_PAGE_MASK); break; case SMALL_PAGE_SIZE: p = ms->pages[offset / SMALL_PAGE_SIZE]; break; default: return TEE_ERROR_GENERIC; } *pa = p; return TEE_SUCCESS; } DECLARE_KEEP_PAGER(get_pa); static size_t get_phys_offs(struct mobj *mobj __maybe_unused, size_t granule __maybe_unused) { return 0; } static void inactivate(struct mobj *mobj) { struct mobj_sp *ms = to_mobj_sp(mobj); uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&sp_mem_lock); /* * If refcount isn't 0 some other thread has found this mobj in * shm_head after the mobj_put() that put us here and before we got * the lock. */ if (!refcount_val(&mobj->refc)) free(ms); cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); } static const struct mobj_ops mobj_sp_ops = { .get_pa = get_pa, .get_phys_offs = get_phys_offs, .get_mem_type = get_mem_type, .matches = mobj_sp_matches, .free = inactivate, }; struct sp_mem_receiver *sp_mem_get_receiver(uint32_t s_id, struct sp_mem *smem) { struct sp_mem_receiver *r = NULL; SLIST_FOREACH(r, &smem->receivers, link) { if (r->perm.endpoint_id == s_id) return r; } return NULL; } struct sp_mem *sp_mem_get(uint64_t handle) { struct sp_mem *smem = NULL; uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); SLIST_FOREACH(smem, &mem_shares, link) { if (smem->global_handle == handle) break; } cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); return smem; } void *sp_mem_get_va(const struct user_mode_ctx *uctx, size_t offset, struct mobj *mobj) { struct vm_region *region = NULL; TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { if (region->mobj == mobj && region->offset == offset) return (void *)region->va; } return NULL; } struct sp_mem *sp_mem_new(void) { struct sp_mem *smem = NULL; uint32_t exceptions = 0; int i = 0; smem = calloc(1, sizeof(*smem)); if (!smem) return NULL; exceptions = cpu_spin_lock_xsave(&sp_mem_lock); bit_ffc(share_bits, NUM_SHARES, &i); if (i == -1) { cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); free(smem); return NULL; } bit_set(share_bits, i); /* * OP-TEE SHAREs use bit 44 use bit 45 instead. */ smem->global_handle = i | FFA_MEMORY_HANDLE_SECURE_BIT; SLIST_INIT(&smem->regions); SLIST_INIT(&smem->receivers); cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); return smem; } void sp_mem_add(struct sp_mem *smem) { uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); SLIST_INSERT_HEAD(&mem_shares, smem, link); cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); } bool sp_mem_is_shared(struct sp_mem_map_region *new_reg) { struct sp_mem *smem = NULL; uint32_t exceptions = cpu_spin_lock_xsave(&sp_mem_lock); uint64_t new_reg_end = new_reg->page_offset + (new_reg->page_count * SMALL_PAGE_SIZE); SLIST_FOREACH(smem, &mem_shares, link) { struct sp_mem_map_region *reg = NULL; SLIST_FOREACH(reg, &smem->regions, link) { if (new_reg->mobj == reg->mobj) { uint64_t reg_end = 0; reg_end = reg->page_offset + (reg->page_count * SMALL_PAGE_SIZE); if (new_reg->page_offset < reg_end && new_reg_end > reg->page_offset) { cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); return true; } } } } cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); return false; } void sp_mem_remove(struct sp_mem *smem) { uint32_t exceptions = 0; int i = 0; struct sp_mem *tsmem = NULL; if (!smem) return; /* Remove all receivers */ while (!SLIST_EMPTY(&smem->receivers)) { struct sp_mem_receiver *receiver = NULL; receiver = SLIST_FIRST(&smem->receivers); SLIST_REMOVE_HEAD(&smem->receivers, link); free(receiver); } /* Remove all regions */ while (!SLIST_EMPTY(&smem->regions)) { struct sp_mem_map_region *region = SLIST_FIRST(&smem->regions); mobj_put(region->mobj); SLIST_REMOVE_HEAD(&smem->regions, link); free(region); } exceptions = cpu_spin_lock_xsave(&sp_mem_lock); i = smem->global_handle & ~FFA_MEMORY_HANDLE_SECURE_BIT; assert(i < NUM_SHARES); bit_clear(share_bits, i); SLIST_FOREACH(tsmem, &mem_shares, link) { if (tsmem == smem) { SLIST_REMOVE(&mem_shares, smem, sp_mem, link); break; } } cpu_spin_unlock_xrestore(&sp_mem_lock, exceptions); free(smem); } optee_os-4.3.0/core/arch/arm/mm/sub.mk000066400000000000000000000011611464416617300175250ustar00rootroot00000000000000srcs-y += core_mmu.c srcs-$(CFG_WITH_PAGER) += tee_pager.c ifeq ($(CFG_WITH_LPAE),y) srcs-y += core_mmu_lpae.c else srcs-y += core_mmu_v7.c endif srcs-$(CFG_CORE_FFA) += mobj_ffa.c srcs-$(CFG_SECURE_PARTITION) += sp_mem.c ifeq ($(CFG_SYSCALL_FTRACE),y) # We would not like to profile MMU APIs as these are used to switch TA # context which may cause undesired behaviour as ftrace requires TA context # to be active. Moreover profiling code uses some of MMU APIs to check # if TA context is active or not. ifeq ($(CFG_WITH_LPAE),y) cflags-remove-core_mmu_lpae.c-y += -pg else cflags-remove-core_mmu_v7.c-y += -pg endif endif optee_os-4.3.0/core/arch/arm/mm/tee_pager.c000066400000000000000000001464051464416617300205150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2021, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct vm_paged_region_head core_vm_regions = TAILQ_HEAD_INITIALIZER(core_vm_regions); #define INVALID_PGIDX UINT_MAX #define PMEM_FLAG_DIRTY BIT(0) #define PMEM_FLAG_HIDDEN BIT(1) /* * struct tee_pager_pmem - Represents a physical page used for paging. * * @flags flags defined by PMEM_FLAG_* above * @fobj_pgidx index of the page in the @fobj * @fobj File object of which a page is made visible. * @va_alias Virtual address where the physical page always is aliased. * Used during remapping of the page when the content need to * be updated before it's available at the new location. */ struct tee_pager_pmem { unsigned int flags; unsigned int fobj_pgidx; struct fobj *fobj; void *va_alias; TAILQ_ENTRY(tee_pager_pmem) link; }; struct tblidx { struct pgt *pgt; unsigned int idx; }; /* The list of physical pages. The first page in the list is the oldest */ TAILQ_HEAD(tee_pager_pmem_head, tee_pager_pmem); static struct tee_pager_pmem_head tee_pager_pmem_head = TAILQ_HEAD_INITIALIZER(tee_pager_pmem_head); static struct tee_pager_pmem_head tee_pager_lock_pmem_head = TAILQ_HEAD_INITIALIZER(tee_pager_lock_pmem_head); /* number of pages hidden */ #define TEE_PAGER_NHIDE (tee_pager_npages / 3) /* Number of registered physical pages, used hiding pages. */ static size_t tee_pager_npages; /* This area covers the IVs for all fobjs with paged IVs */ static struct vm_paged_region *pager_iv_region; /* Used by make_iv_available(), see make_iv_available() for details. */ static struct tee_pager_pmem *pager_spare_pmem; #ifdef CFG_WITH_STATS static struct tee_pager_stats pager_stats; static inline void incr_ro_hits(void) { pager_stats.ro_hits++; } static inline void incr_rw_hits(void) { pager_stats.rw_hits++; } static inline void incr_hidden_hits(void) { pager_stats.hidden_hits++; } static inline void incr_zi_released(void) { pager_stats.zi_released++; } static inline void incr_npages_all(void) { pager_stats.npages_all++; } static inline void set_npages(void) { pager_stats.npages = tee_pager_npages; } void tee_pager_get_stats(struct tee_pager_stats *stats) { *stats = pager_stats; pager_stats.hidden_hits = 0; pager_stats.ro_hits = 0; pager_stats.rw_hits = 0; pager_stats.zi_released = 0; } #else /* CFG_WITH_STATS */ static inline void incr_ro_hits(void) { } static inline void incr_rw_hits(void) { } static inline void incr_hidden_hits(void) { } static inline void incr_zi_released(void) { } static inline void incr_npages_all(void) { } static inline void set_npages(void) { } void tee_pager_get_stats(struct tee_pager_stats *stats) { memset(stats, 0, sizeof(struct tee_pager_stats)); } #endif /* CFG_WITH_STATS */ #define TBL_NUM_ENTRIES (CORE_MMU_PGDIR_SIZE / SMALL_PAGE_SIZE) #define TBL_LEVEL CORE_MMU_PGDIR_LEVEL #define TBL_SHIFT SMALL_PAGE_SHIFT #define EFFECTIVE_VA_SIZE \ (ROUNDUP(VCORE_START_VA + TEE_RAM_VA_SIZE, CORE_MMU_PGDIR_SIZE) - \ ROUNDDOWN(VCORE_START_VA, CORE_MMU_PGDIR_SIZE)) static struct pager_table { struct pgt pgt; struct core_mmu_table_info tbl_info; } *pager_tables; static unsigned int num_pager_tables; static unsigned pager_spinlock = SPINLOCK_UNLOCK; /* Defines the range of the alias area */ static tee_mm_entry_t *pager_alias_area; /* * Physical pages are added in a stack like fashion to the alias area, * @pager_alias_next_free gives the address of next free entry if * @pager_alias_next_free is != 0 */ static uintptr_t pager_alias_next_free; #ifdef CFG_TEE_CORE_DEBUG #define pager_lock(ai) pager_lock_dldetect(__func__, __LINE__, ai) static uint32_t pager_lock_dldetect(const char *func, const int line, struct abort_info *ai) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); unsigned int retries = 0; unsigned int reminder = 0; while (!cpu_spin_trylock(&pager_spinlock)) { retries++; if (!retries) { /* wrapped, time to report */ trace_printf(func, line, TRACE_ERROR, true, "possible spinlock deadlock reminder %u", reminder); if (reminder < UINT_MAX) reminder++; if (ai) abort_print(ai); } } return exceptions; } #else static uint32_t pager_lock(struct abort_info __unused *ai) { return cpu_spin_lock_xsave(&pager_spinlock); } #endif static uint32_t pager_lock_check_stack(size_t stack_size) { if (stack_size) { int8_t buf[stack_size]; size_t n; /* * Make sure to touch all pages of the stack that we expect * to use with this lock held. We need to take eventual * page faults before the lock is taken or we'll deadlock * the pager. The pages that are populated in this way will * eventually be released at certain save transitions of * the thread. */ for (n = 0; n < stack_size; n += SMALL_PAGE_SIZE) io_write8((vaddr_t)buf + n, 1); io_write8((vaddr_t)buf + stack_size - 1, 1); } return pager_lock(NULL); } static void pager_unlock(uint32_t exceptions) { cpu_spin_unlock_xrestore(&pager_spinlock, exceptions); } void *tee_pager_phys_to_virt(paddr_t pa, size_t len) { struct core_mmu_table_info ti; unsigned idx; uint32_t a; paddr_t p; vaddr_t v; size_t n; if (pa & SMALL_PAGE_MASK || len > SMALL_PAGE_SIZE) return NULL; /* * Most addresses are mapped lineary, try that first if possible. */ if (!tee_pager_get_table_info(pa, &ti)) return NULL; /* impossible pa */ idx = core_mmu_va2idx(&ti, pa); core_mmu_get_entry(&ti, idx, &p, &a); if ((a & TEE_MATTR_VALID_BLOCK) && p == pa) return (void *)core_mmu_idx2va(&ti, idx); n = 0; idx = core_mmu_va2idx(&pager_tables[n].tbl_info, TEE_RAM_START); while (true) { while (idx < TBL_NUM_ENTRIES) { v = core_mmu_idx2va(&pager_tables[n].tbl_info, idx); if (v >= (TEE_RAM_START + TEE_RAM_VA_SIZE)) return NULL; core_mmu_get_entry(&pager_tables[n].tbl_info, idx, &p, &a); if ((a & TEE_MATTR_VALID_BLOCK) && p == pa) return (void *)v; idx++; } n++; if (n >= num_pager_tables) return NULL; idx = 0; } return NULL; } static bool pmem_is_hidden(struct tee_pager_pmem *pmem) { return pmem->flags & PMEM_FLAG_HIDDEN; } static bool pmem_is_dirty(struct tee_pager_pmem *pmem) { return pmem->flags & PMEM_FLAG_DIRTY; } static bool pmem_is_covered_by_region(struct tee_pager_pmem *pmem, struct vm_paged_region *reg) { if (pmem->fobj != reg->fobj) return false; if (pmem->fobj_pgidx < reg->fobj_pgoffs) return false; if ((pmem->fobj_pgidx - reg->fobj_pgoffs) >= (reg->size >> SMALL_PAGE_SHIFT)) return false; return true; } static size_t get_pgt_count(vaddr_t base, size_t size) { assert(size); return (base + size - 1) / CORE_MMU_PGDIR_SIZE + 1 - base / CORE_MMU_PGDIR_SIZE; } static bool region_have_pgt(struct vm_paged_region *reg, struct pgt *pgt) { size_t n = 0; for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) if (reg->pgt_array[n] == pgt) return true; return false; } static struct tblidx pmem_get_region_tblidx(struct tee_pager_pmem *pmem, struct vm_paged_region *reg) { size_t tbloffs = (reg->base & CORE_MMU_PGDIR_MASK) >> SMALL_PAGE_SHIFT; size_t idx = pmem->fobj_pgidx - reg->fobj_pgoffs + tbloffs; assert(pmem->fobj && pmem->fobj_pgidx != INVALID_PGIDX); assert(idx / TBL_NUM_ENTRIES < get_pgt_count(reg->base, reg->size)); return (struct tblidx){ .idx = idx % TBL_NUM_ENTRIES, .pgt = reg->pgt_array[idx / TBL_NUM_ENTRIES], }; } static struct pager_table *find_pager_table_may_fail(vaddr_t va) { size_t n; const vaddr_t mask = CORE_MMU_PGDIR_MASK; if (!pager_tables) return NULL; n = ((va & ~mask) - pager_tables[0].tbl_info.va_base) >> CORE_MMU_PGDIR_SHIFT; if (n >= num_pager_tables) return NULL; assert(va >= pager_tables[n].tbl_info.va_base && va <= (pager_tables[n].tbl_info.va_base | mask)); return pager_tables + n; } static struct pager_table *find_pager_table(vaddr_t va) { struct pager_table *pt = find_pager_table_may_fail(va); assert(pt); return pt; } bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti) { struct pager_table *pt = find_pager_table_may_fail(va); if (!pt) return false; *ti = pt->tbl_info; return true; } static struct core_mmu_table_info *find_table_info(vaddr_t va) { return &find_pager_table(va)->tbl_info; } static struct pgt *find_core_pgt(vaddr_t va) { return &find_pager_table(va)->pgt; } void tee_pager_set_alias_area(tee_mm_entry_t *mm) { struct pager_table *pt; unsigned idx; vaddr_t smem = tee_mm_get_smem(mm); size_t nbytes = tee_mm_get_bytes(mm); vaddr_t v; uint32_t a = 0; DMSG("0x%" PRIxVA " - 0x%" PRIxVA, smem, smem + nbytes); assert(!pager_alias_area); pager_alias_area = mm; pager_alias_next_free = smem; /* Clear all mapping in the alias area */ pt = find_pager_table(smem); idx = core_mmu_va2idx(&pt->tbl_info, smem); while (pt <= (pager_tables + num_pager_tables - 1)) { while (idx < TBL_NUM_ENTRIES) { v = core_mmu_idx2va(&pt->tbl_info, idx); if (v >= (smem + nbytes)) goto out; core_mmu_get_entry(&pt->tbl_info, idx, NULL, &a); core_mmu_set_entry(&pt->tbl_info, idx, 0, 0); if (a & TEE_MATTR_VALID_BLOCK) pgt_dec_used_entries(&pt->pgt); idx++; } pt++; idx = 0; } out: tlbi_va_range(smem, nbytes, SMALL_PAGE_SIZE); } static size_t tbl_usage_count(struct core_mmu_table_info *ti) { size_t n; uint32_t a = 0; size_t usage = 0; for (n = 0; n < ti->num_entries; n++) { core_mmu_get_entry(ti, n, NULL, &a); if (a & TEE_MATTR_VALID_BLOCK) usage++; } return usage; } static void tblidx_get_entry(struct tblidx tblidx, paddr_t *pa, uint32_t *attr) { assert(tblidx.pgt && tblidx.idx < TBL_NUM_ENTRIES); core_mmu_get_entry_primitive(tblidx.pgt->tbl, TBL_LEVEL, tblidx.idx, pa, attr); } static void tblidx_set_entry(struct tblidx tblidx, paddr_t pa, uint32_t attr) { assert(tblidx.pgt && tblidx.idx < TBL_NUM_ENTRIES); core_mmu_set_entry_primitive(tblidx.pgt->tbl, TBL_LEVEL, tblidx.idx, pa, attr); } static struct tblidx region_va2tblidx(struct vm_paged_region *reg, vaddr_t va) { paddr_t mask = CORE_MMU_PGDIR_MASK; size_t n = 0; assert(va >= reg->base && va < (reg->base + reg->size)); n = (va - (reg->base & ~mask)) / CORE_MMU_PGDIR_SIZE; return (struct tblidx){ .idx = (va & mask) / SMALL_PAGE_SIZE, .pgt = reg->pgt_array[n], }; } static vaddr_t tblidx2va(struct tblidx tblidx) { return tblidx.pgt->vabase + (tblidx.idx << SMALL_PAGE_SHIFT); } static void tblidx_tlbi_entry(struct tblidx tblidx) { vaddr_t va = tblidx2va(tblidx); #if defined(CFG_PAGED_USER_TA) if (tblidx.pgt->ctx) { uint32_t asid = to_user_mode_ctx(tblidx.pgt->ctx)->vm_info.asid; tlbi_va_asid(va, asid); return; } #endif tlbi_va_allasid(va); } static void pmem_assign_fobj_page(struct tee_pager_pmem *pmem, struct vm_paged_region *reg, vaddr_t va) { struct tee_pager_pmem *p = NULL; unsigned int fobj_pgidx = 0; assert(!pmem->fobj && pmem->fobj_pgidx == INVALID_PGIDX); assert(va >= reg->base && va < (reg->base + reg->size)); fobj_pgidx = (va - reg->base) / SMALL_PAGE_SIZE + reg->fobj_pgoffs; TAILQ_FOREACH(p, &tee_pager_pmem_head, link) assert(p->fobj != reg->fobj || p->fobj_pgidx != fobj_pgidx); pmem->fobj = reg->fobj; pmem->fobj_pgidx = fobj_pgidx; } static void pmem_clear(struct tee_pager_pmem *pmem) { pmem->fobj = NULL; pmem->fobj_pgidx = INVALID_PGIDX; pmem->flags = 0; } static void pmem_unmap(struct tee_pager_pmem *pmem, struct pgt *only_this_pgt) { struct vm_paged_region *reg = NULL; struct tblidx tblidx = { }; uint32_t a = 0; TAILQ_FOREACH(reg, &pmem->fobj->regions, fobj_link) { /* * If only_this_pgt points to a pgt then the pgt of this * region has to match or we'll skip over it. */ if (only_this_pgt && !region_have_pgt(reg, only_this_pgt)) continue; if (!pmem_is_covered_by_region(pmem, reg)) continue; tblidx = pmem_get_region_tblidx(pmem, reg); if (!tblidx.pgt) continue; tblidx_get_entry(tblidx, NULL, &a); if (a & TEE_MATTR_VALID_BLOCK) { tblidx_set_entry(tblidx, 0, 0); pgt_dec_used_entries(tblidx.pgt); tblidx_tlbi_entry(tblidx); } } } void tee_pager_early_init(void) { size_t n = 0; num_pager_tables = EFFECTIVE_VA_SIZE / CORE_MMU_PGDIR_SIZE; pager_tables = calloc(num_pager_tables, sizeof(*pager_tables)); if (!pager_tables) panic("Cannot allocate pager_tables"); /* * Note that this depends on add_pager_vaspace() adding vaspace * after end of memory. */ for (n = 0; n < num_pager_tables; n++) { if (!core_mmu_find_table(NULL, VCORE_START_VA + n * CORE_MMU_PGDIR_SIZE, UINT_MAX, &pager_tables[n].tbl_info)) panic("can't find mmu tables"); if (pager_tables[n].tbl_info.shift != TBL_SHIFT) panic("Unsupported page size in translation table"); assert(pager_tables[n].tbl_info.num_entries == TBL_NUM_ENTRIES); assert(pager_tables[n].tbl_info.level == TBL_LEVEL); pager_tables[n].pgt.tbl = pager_tables[n].tbl_info.table; pager_tables[n].pgt.vabase = pager_tables[n].tbl_info.va_base; pgt_set_used_entries(&pager_tables[n].pgt, tbl_usage_count(&pager_tables[n].tbl_info)); } } static void *pager_add_alias_page(paddr_t pa) { unsigned idx; struct core_mmu_table_info *ti; /* Alias pages mapped without write permission: runtime will care */ uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_SECURE | TEE_MATTR_PR | (TEE_MATTR_MEM_TYPE_CACHED << TEE_MATTR_MEM_TYPE_SHIFT); DMSG("0x%" PRIxPA, pa); ti = find_table_info(pager_alias_next_free); idx = core_mmu_va2idx(ti, pager_alias_next_free); core_mmu_set_entry(ti, idx, pa, attr); pgt_inc_used_entries(find_core_pgt(pager_alias_next_free)); pager_alias_next_free += SMALL_PAGE_SIZE; if (pager_alias_next_free >= (tee_mm_get_smem(pager_alias_area) + tee_mm_get_bytes(pager_alias_area))) pager_alias_next_free = 0; return (void *)core_mmu_idx2va(ti, idx); } static void region_insert(struct vm_paged_region_head *regions, struct vm_paged_region *reg, struct vm_paged_region *r_prev) { uint32_t exceptions = pager_lock_check_stack(8); if (r_prev) TAILQ_INSERT_AFTER(regions, r_prev, reg, link); else TAILQ_INSERT_HEAD(regions, reg, link); TAILQ_INSERT_TAIL(®->fobj->regions, reg, fobj_link); pager_unlock(exceptions); } DECLARE_KEEP_PAGER(region_insert); static struct vm_paged_region *alloc_region(vaddr_t base, size_t size) { struct vm_paged_region *reg = NULL; if ((base & SMALL_PAGE_MASK) || !size) { EMSG("invalid pager region [%" PRIxVA " +0x%zx]", base, size); panic(); } reg = calloc(1, sizeof(*reg)); if (!reg) return NULL; reg->pgt_array = calloc(get_pgt_count(base, size), sizeof(struct pgt *)); if (!reg->pgt_array) { free(reg); return NULL; } reg->base = base; reg->size = size; return reg; } void tee_pager_add_core_region(vaddr_t base, enum vm_paged_region_type type, struct fobj *fobj) { struct vm_paged_region *reg = NULL; size_t n = 0; assert(fobj); DMSG("0x%" PRIxPTR " - 0x%" PRIxPTR " : type %d", base, base + fobj->num_pages * SMALL_PAGE_SIZE, type); reg = alloc_region(base, fobj->num_pages * SMALL_PAGE_SIZE); if (!reg) panic("alloc_region"); reg->fobj = fobj_get(fobj); reg->fobj_pgoffs = 0; reg->type = type; switch (type) { case PAGED_REGION_TYPE_RO: reg->flags = TEE_MATTR_PRX; break; case PAGED_REGION_TYPE_RW: case PAGED_REGION_TYPE_LOCK: reg->flags = TEE_MATTR_PRW; break; default: panic(); } for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) reg->pgt_array[n] = find_core_pgt(base + n * CORE_MMU_PGDIR_SIZE); region_insert(&core_vm_regions, reg, NULL); } static struct vm_paged_region *find_region(struct vm_paged_region_head *regions, vaddr_t va) { struct vm_paged_region *reg; if (!regions) return NULL; TAILQ_FOREACH(reg, regions, link) { if (core_is_buffer_inside(va, 1, reg->base, reg->size)) return reg; } return NULL; } #ifdef CFG_PAGED_USER_TA static struct vm_paged_region *find_uta_region(vaddr_t va) { struct ts_ctx *ctx = thread_get_tsd()->ctx; if (!is_user_mode_ctx(ctx)) return NULL; return find_region(to_user_mode_ctx(ctx)->regions, va); } #else static struct vm_paged_region *find_uta_region(vaddr_t va __unused) { return NULL; } #endif /*CFG_PAGED_USER_TA*/ static uint32_t get_region_mattr(uint32_t reg_flags) { uint32_t attr = TEE_MATTR_VALID_BLOCK | TEE_MATTR_SECURE | TEE_MATTR_MEM_TYPE_CACHED << TEE_MATTR_MEM_TYPE_SHIFT | (reg_flags & (TEE_MATTR_PRWX | TEE_MATTR_URWX)); return attr; } static paddr_t get_pmem_pa(struct tee_pager_pmem *pmem) { struct core_mmu_table_info *ti; paddr_t pa; unsigned idx; ti = find_table_info((vaddr_t)pmem->va_alias); idx = core_mmu_va2idx(ti, (vaddr_t)pmem->va_alias); core_mmu_get_entry(ti, idx, &pa, NULL); return pa; } #ifdef CFG_PAGED_USER_TA static void unlink_region(struct vm_paged_region_head *regions, struct vm_paged_region *reg) { uint32_t exceptions = pager_lock_check_stack(64); TAILQ_REMOVE(regions, reg, link); TAILQ_REMOVE(®->fobj->regions, reg, fobj_link); pager_unlock(exceptions); } DECLARE_KEEP_PAGER(unlink_region); static void free_region(struct vm_paged_region *reg) { fobj_put(reg->fobj); free(reg->pgt_array); free(reg); } static TEE_Result pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, struct fobj *fobj, uint32_t prot) { struct vm_paged_region *r_prev = NULL; struct vm_paged_region *reg = NULL; vaddr_t b = base; size_t fobj_pgoffs = 0; size_t s = fobj->num_pages * SMALL_PAGE_SIZE; if (!uctx->regions) { uctx->regions = malloc(sizeof(*uctx->regions)); if (!uctx->regions) return TEE_ERROR_OUT_OF_MEMORY; TAILQ_INIT(uctx->regions); } reg = TAILQ_FIRST(uctx->regions); while (reg) { if (core_is_buffer_intersect(b, s, reg->base, reg->size)) return TEE_ERROR_BAD_PARAMETERS; if (b < reg->base) break; r_prev = reg; reg = TAILQ_NEXT(reg, link); } reg = alloc_region(b, s); if (!reg) return TEE_ERROR_OUT_OF_MEMORY; /* Table info will be set when the context is activated. */ reg->fobj = fobj_get(fobj); reg->fobj_pgoffs = fobj_pgoffs; reg->type = PAGED_REGION_TYPE_RW; reg->flags = prot; region_insert(uctx->regions, reg, r_prev); return TEE_SUCCESS; } static void map_pgts(struct vm_paged_region *reg) { struct core_mmu_table_info dir_info = { NULL }; size_t n = 0; core_mmu_get_user_pgdir(&dir_info); for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) { struct pgt *pgt = reg->pgt_array[n]; uint32_t attr = 0; paddr_t pa = 0; size_t idx = 0; idx = core_mmu_va2idx(&dir_info, pgt->vabase); core_mmu_get_entry(&dir_info, idx, &pa, &attr); /* * Check if the page table already is used, if it is, it's * already registered. */ if (pgt->num_used_entries) { assert(attr & TEE_MATTR_TABLE); assert(pa == virt_to_phys(pgt->tbl)); continue; } attr = TEE_MATTR_SECURE | TEE_MATTR_TABLE; pa = virt_to_phys(pgt->tbl); assert(pa); /* * Note that the update of the table entry is guaranteed to * be atomic. */ core_mmu_set_entry(&dir_info, idx, pa, attr); } } TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, struct fobj *fobj, uint32_t prot) { TEE_Result res = TEE_SUCCESS; struct thread_specific_data *tsd = thread_get_tsd(); struct vm_paged_region *reg = NULL; res = pager_add_um_region(uctx, base, fobj, prot); if (res) return res; if (uctx->ts_ctx == tsd->ctx) { /* * We're chaning the currently active utc. Assign page * tables to the new regions and make sure that the page * tables are registered in the upper table. */ tee_pager_assign_um_tables(uctx); TAILQ_FOREACH(reg, uctx->regions, link) map_pgts(reg); } return TEE_SUCCESS; } static void split_region(struct vm_paged_region *reg, struct vm_paged_region *r2, vaddr_t va) { uint32_t exceptions = pager_lock_check_stack(64); size_t diff = va - reg->base; size_t r2_pgt_count = 0; size_t reg_pgt_count = 0; size_t n0 = 0; size_t n = 0; assert(r2->base == va); assert(r2->size == reg->size - diff); r2->fobj = fobj_get(reg->fobj); r2->fobj_pgoffs = reg->fobj_pgoffs + diff / SMALL_PAGE_SIZE; r2->type = reg->type; r2->flags = reg->flags; r2_pgt_count = get_pgt_count(r2->base, r2->size); reg_pgt_count = get_pgt_count(reg->base, reg->size); n0 = reg_pgt_count - r2_pgt_count; for (n = n0; n < reg_pgt_count; n++) r2->pgt_array[n - n0] = reg->pgt_array[n]; reg->size = diff; TAILQ_INSERT_BEFORE(reg, r2, link); TAILQ_INSERT_AFTER(®->fobj->regions, reg, r2, fobj_link); pager_unlock(exceptions); } DECLARE_KEEP_PAGER(split_region); TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx, vaddr_t va) { struct vm_paged_region *reg = NULL; struct vm_paged_region *r2 = NULL; if (va & SMALL_PAGE_MASK) return TEE_ERROR_BAD_PARAMETERS; TAILQ_FOREACH(reg, uctx->regions, link) { if (va == reg->base || va == reg->base + reg->size) return TEE_SUCCESS; if (va > reg->base && va < reg->base + reg->size) { size_t diff = va - reg->base; r2 = alloc_region(va, reg->size - diff); if (!r2) return TEE_ERROR_OUT_OF_MEMORY; split_region(reg, r2, va); return TEE_SUCCESS; } } return TEE_SUCCESS; } static struct pgt ** merge_region_with_next(struct vm_paged_region_head *regions, struct vm_paged_region *reg, struct vm_paged_region *r_next, struct pgt **pgt_array) { uint32_t exceptions = pager_lock_check_stack(64); struct pgt **old_pgt_array = reg->pgt_array; reg->pgt_array = pgt_array; TAILQ_REMOVE(regions, r_next, link); TAILQ_REMOVE(&r_next->fobj->regions, r_next, fobj_link); pager_unlock(exceptions); return old_pgt_array; } DECLARE_KEEP_PAGER(merge_region_with_next); static struct pgt **alloc_merged_pgt_array(struct vm_paged_region *a, struct vm_paged_region *a_next) { size_t a_next_pgt_count = get_pgt_count(a_next->base, a_next->size); size_t a_pgt_count = get_pgt_count(a->base, a->size); size_t pgt_count = get_pgt_count(a->base, a->size + a_next->size); struct pgt **pgt_array = NULL; bool have_shared_pgt = false; have_shared_pgt = ((a->base + a->size) & ~CORE_MMU_PGDIR_MASK) == (a_next->base & ~CORE_MMU_PGDIR_MASK); if (have_shared_pgt) assert(pgt_count == a_pgt_count + a_next_pgt_count - 1); else assert(pgt_count == a_pgt_count + a_next_pgt_count); /* In case there's a shared pgt they must match */ if (have_shared_pgt && a->pgt_array[a_pgt_count - 1] != a_next->pgt_array[0]) return NULL; pgt_array = calloc(pgt_count, sizeof(struct pgt *)); if (!pgt_array) return NULL; /* * Copy and merge the two pgt_arrays, note the special case * where a pgt is shared. */ memcpy(pgt_array, a->pgt_array, a_pgt_count * sizeof(struct pgt *)); if (have_shared_pgt) memcpy(pgt_array + a_pgt_count, a_next->pgt_array + 1, (a_next_pgt_count - 1) * sizeof(struct pgt *)); else memcpy(pgt_array + a_pgt_count, a_next->pgt_array, a_next_pgt_count * sizeof(struct pgt *)); return pgt_array; } void tee_pager_merge_um_region(struct user_mode_ctx *uctx, vaddr_t va, size_t len) { struct vm_paged_region *r_next = NULL; struct vm_paged_region *reg = NULL; struct pgt **pgt_array = NULL; vaddr_t end_va = 0; if ((va | len) & SMALL_PAGE_MASK) return; if (ADD_OVERFLOW(va, len, &end_va)) return; for (reg = TAILQ_FIRST(uctx->regions);; reg = r_next) { r_next = TAILQ_NEXT(reg, link); if (!r_next) return; /* Try merging with the area just before va */ if (reg->base + reg->size < va) continue; /* * If reg->base is well past our range we're done. * Note that if it's just the page after our range we'll * try to merge. */ if (reg->base > end_va) return; if (reg->base + reg->size != r_next->base) continue; if (reg->fobj != r_next->fobj || reg->type != r_next->type || reg->flags != r_next->flags) continue; if (reg->fobj_pgoffs + reg->size / SMALL_PAGE_SIZE != r_next->fobj_pgoffs) continue; pgt_array = alloc_merged_pgt_array(reg, r_next); if (!pgt_array) continue; /* * merge_region_with_next() returns the old pgt array which * was replaced in reg. We don't want to call free() * directly from merge_region_with_next() that would pull * free() and its dependencies into the unpaged area. */ free(merge_region_with_next(uctx->regions, reg, r_next, pgt_array)); free_region(r_next); r_next = reg; } } static void rem_region(struct vm_paged_region_head *regions, struct vm_paged_region *reg) { struct tee_pager_pmem *pmem; size_t last_pgoffs = reg->fobj_pgoffs + (reg->size >> SMALL_PAGE_SHIFT) - 1; uint32_t exceptions; struct tblidx tblidx = { }; uint32_t a = 0; exceptions = pager_lock_check_stack(64); TAILQ_REMOVE(regions, reg, link); TAILQ_REMOVE(®->fobj->regions, reg, fobj_link); TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { if (pmem->fobj != reg->fobj || pmem->fobj_pgidx < reg->fobj_pgoffs || pmem->fobj_pgidx > last_pgoffs) continue; tblidx = pmem_get_region_tblidx(pmem, reg); tblidx_get_entry(tblidx, NULL, &a); if (!(a & TEE_MATTR_VALID_BLOCK)) continue; tblidx_set_entry(tblidx, 0, 0); tblidx_tlbi_entry(tblidx); pgt_dec_used_entries(tblidx.pgt); } pager_unlock(exceptions); } DECLARE_KEEP_PAGER(rem_region); void tee_pager_rem_um_region(struct user_mode_ctx *uctx, vaddr_t base, size_t size) { struct vm_paged_region *reg; struct vm_paged_region *r_next; size_t s = ROUNDUP(size, SMALL_PAGE_SIZE); TAILQ_FOREACH_SAFE(reg, uctx->regions, link, r_next) { if (core_is_buffer_inside(reg->base, reg->size, base, s)) { rem_region(uctx->regions, reg); free_region(reg); } } tlbi_asid(uctx->vm_info.asid); } void tee_pager_rem_um_regions(struct user_mode_ctx *uctx) { struct vm_paged_region *reg = NULL; if (!uctx->regions) return; while (true) { reg = TAILQ_FIRST(uctx->regions); if (!reg) break; unlink_region(uctx->regions, reg); free_region(reg); } free(uctx->regions); } static bool __maybe_unused same_context(struct tee_pager_pmem *pmem) { struct vm_paged_region *reg = TAILQ_FIRST(&pmem->fobj->regions); void *ctx = reg->pgt_array[0]->ctx; do { reg = TAILQ_NEXT(reg, fobj_link); if (!reg) return true; } while (reg->pgt_array[0]->ctx == ctx); return false; } bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx, vaddr_t base, size_t size, uint32_t flags) { bool ret = false; vaddr_t b = base; size_t s = size; size_t s2 = 0; struct vm_paged_region *reg = find_region(uctx->regions, b); uint32_t exceptions = 0; struct tee_pager_pmem *pmem = NULL; uint32_t a = 0; uint32_t f = 0; uint32_t mattr = 0; uint32_t f2 = 0; struct tblidx tblidx = { }; f = (flags & TEE_MATTR_URWX) | TEE_MATTR_UR | TEE_MATTR_PR; if (f & TEE_MATTR_UW) f |= TEE_MATTR_PW; mattr = get_region_mattr(f); exceptions = pager_lock_check_stack(SMALL_PAGE_SIZE); while (s) { if (!reg) { ret = false; goto out; } s2 = MIN(reg->size, s); b += s2; s -= s2; if (reg->flags == f) goto next_region; TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { if (!pmem_is_covered_by_region(pmem, reg)) continue; tblidx = pmem_get_region_tblidx(pmem, reg); tblidx_get_entry(tblidx, NULL, &a); if (a == f) continue; tblidx_set_entry(tblidx, 0, 0); tblidx_tlbi_entry(tblidx); pmem->flags &= ~PMEM_FLAG_HIDDEN; if (pmem_is_dirty(pmem)) f2 = mattr; else f2 = mattr & ~(TEE_MATTR_UW | TEE_MATTR_PW); tblidx_set_entry(tblidx, get_pmem_pa(pmem), f2); if (!(a & TEE_MATTR_VALID_BLOCK)) pgt_inc_used_entries(tblidx.pgt); /* * Make sure the table update is visible before * continuing. */ dsb_ishst(); /* * Here's a problem if this page already is shared. * We need do icache invalidate for each context * in which it is shared. In practice this will * never happen. */ if (flags & TEE_MATTR_UX) { void *va = (void *)tblidx2va(tblidx); /* Assert that the pmem isn't shared. */ assert(same_context(pmem)); dcache_clean_range_pou(va, SMALL_PAGE_SIZE); icache_inv_user_range(va, SMALL_PAGE_SIZE); } } reg->flags = f; next_region: reg = TAILQ_NEXT(reg, link); } ret = true; out: pager_unlock(exceptions); return ret; } DECLARE_KEEP_PAGER(tee_pager_set_um_region_attr); #endif /*CFG_PAGED_USER_TA*/ void tee_pager_invalidate_fobj(struct fobj *fobj) { struct tee_pager_pmem *pmem; uint32_t exceptions; exceptions = pager_lock_check_stack(64); TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) if (pmem->fobj == fobj) pmem_clear(pmem); pager_unlock(exceptions); } DECLARE_KEEP_PAGER(tee_pager_invalidate_fobj); static struct tee_pager_pmem *pmem_find(struct vm_paged_region *reg, vaddr_t va) { struct tee_pager_pmem *pmem = NULL; size_t fobj_pgidx = 0; assert(va >= reg->base && va < (reg->base + reg->size)); fobj_pgidx = (va - reg->base) / SMALL_PAGE_SIZE + reg->fobj_pgoffs; TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) if (pmem->fobj == reg->fobj && pmem->fobj_pgidx == fobj_pgidx) return pmem; return NULL; } static bool tee_pager_unhide_page(struct vm_paged_region *reg, vaddr_t page_va) { struct tblidx tblidx = region_va2tblidx(reg, page_va); struct tee_pager_pmem *pmem = pmem_find(reg, page_va); uint32_t a = get_region_mattr(reg->flags); uint32_t attr = 0; paddr_t pa = 0; if (!pmem) return false; tblidx_get_entry(tblidx, NULL, &attr); if (attr & TEE_MATTR_VALID_BLOCK) return false; /* * The page is hidden, or not not mapped yet. Unhide the page and * move it to the tail. * * Since the page isn't mapped there doesn't exist a valid TLB entry * for this address, so no TLB invalidation is required after setting * the new entry. A DSB is needed though, to make the write visible. * * For user executable pages it's more complicated. Those pages can * be shared between multiple TA mappings and thus populated by * another TA. The reference manual states that: * * "instruction cache maintenance is required only after writing * new data to a physical address that holds an instruction." * * So for hidden pages we would not need to invalidate i-cache, but * for newly populated pages we do. Since we don't know which we * have to assume the worst and always invalidate the i-cache. We * don't need to clean the d-cache though, since that has already * been done earlier. * * Additional bookkeeping to tell if the i-cache invalidation is * needed or not is left as a future optimization. */ /* If it's not a dirty block, then it should be read only. */ if (!pmem_is_dirty(pmem)) a &= ~(TEE_MATTR_PW | TEE_MATTR_UW); pa = get_pmem_pa(pmem); pmem->flags &= ~PMEM_FLAG_HIDDEN; if (reg->flags & TEE_MATTR_UX) { void *va = (void *)tblidx2va(tblidx); /* Set a temporary read-only mapping */ assert(!(a & (TEE_MATTR_UW | TEE_MATTR_PW))); tblidx_set_entry(tblidx, pa, a & ~TEE_MATTR_UX); dsb_ishst(); icache_inv_user_range(va, SMALL_PAGE_SIZE); /* Set the final mapping */ tblidx_set_entry(tblidx, pa, a); tblidx_tlbi_entry(tblidx); } else { tblidx_set_entry(tblidx, pa, a); dsb_ishst(); } pgt_inc_used_entries(tblidx.pgt); TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); incr_hidden_hits(); return true; } static void tee_pager_hide_pages(void) { struct tee_pager_pmem *pmem = NULL; size_t n = 0; TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { if (n >= TEE_PAGER_NHIDE) break; n++; /* we cannot hide pages when pmem->fobj is not defined. */ if (!pmem->fobj) continue; if (pmem_is_hidden(pmem)) continue; pmem->flags |= PMEM_FLAG_HIDDEN; pmem_unmap(pmem, NULL); } } static unsigned int __maybe_unused num_regions_with_pmem(struct tee_pager_pmem *pmem) { struct vm_paged_region *reg = NULL; unsigned int num_matches = 0; TAILQ_FOREACH(reg, &pmem->fobj->regions, fobj_link) if (pmem_is_covered_by_region(pmem, reg)) num_matches++; return num_matches; } /* * Find mapped pmem, hide and move to pageble pmem. * Return false if page was not mapped, and true if page was mapped. */ static bool tee_pager_release_one_phys(struct vm_paged_region *reg, vaddr_t page_va) { struct tee_pager_pmem *pmem = NULL; struct tblidx tblidx = { }; size_t fobj_pgidx = 0; assert(page_va >= reg->base && page_va < (reg->base + reg->size)); fobj_pgidx = (page_va - reg->base) / SMALL_PAGE_SIZE + reg->fobj_pgoffs; TAILQ_FOREACH(pmem, &tee_pager_lock_pmem_head, link) { if (pmem->fobj != reg->fobj || pmem->fobj_pgidx != fobj_pgidx) continue; /* * Locked pages may not be shared. We're asserting that the * number of regions using this pmem is one and only one as * we're about to unmap it. */ assert(num_regions_with_pmem(pmem) == 1); tblidx = pmem_get_region_tblidx(pmem, reg); tblidx_set_entry(tblidx, 0, 0); pgt_dec_used_entries(tblidx.pgt); TAILQ_REMOVE(&tee_pager_lock_pmem_head, pmem, link); pmem_clear(pmem); tee_pager_npages++; set_npages(); TAILQ_INSERT_HEAD(&tee_pager_pmem_head, pmem, link); incr_zi_released(); return true; } return false; } static void pager_deploy_page(struct tee_pager_pmem *pmem, struct vm_paged_region *reg, vaddr_t page_va, bool clean_user_cache, bool writable) { struct tblidx tblidx = region_va2tblidx(reg, page_va); uint32_t attr = get_region_mattr(reg->flags); struct core_mmu_table_info *ti = NULL; uint8_t *va_alias = pmem->va_alias; paddr_t pa = get_pmem_pa(pmem); unsigned int idx_alias = 0; uint32_t attr_alias = 0; paddr_t pa_alias = 0; /* Ensure we are allowed to write to aliased virtual page */ ti = find_table_info((vaddr_t)va_alias); idx_alias = core_mmu_va2idx(ti, (vaddr_t)va_alias); core_mmu_get_entry(ti, idx_alias, &pa_alias, &attr_alias); if (!(attr_alias & TEE_MATTR_PW)) { attr_alias |= TEE_MATTR_PW; core_mmu_set_entry(ti, idx_alias, pa_alias, attr_alias); tlbi_va_allasid((vaddr_t)va_alias); } asan_tag_access(va_alias, va_alias + SMALL_PAGE_SIZE); if (fobj_load_page(pmem->fobj, pmem->fobj_pgidx, va_alias)) { EMSG("PH 0x%" PRIxVA " failed", page_va); panic(); } switch (reg->type) { case PAGED_REGION_TYPE_RO: TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); incr_ro_hits(); /* Forbid write to aliases for read-only (maybe exec) pages */ attr_alias &= ~TEE_MATTR_PW; core_mmu_set_entry(ti, idx_alias, pa_alias, attr_alias); tlbi_va_allasid((vaddr_t)va_alias); break; case PAGED_REGION_TYPE_RW: TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); if (writable && (attr & (TEE_MATTR_PW | TEE_MATTR_UW))) pmem->flags |= PMEM_FLAG_DIRTY; incr_rw_hits(); break; case PAGED_REGION_TYPE_LOCK: /* Move page to lock list */ if (tee_pager_npages <= 0) panic("Running out of pages"); tee_pager_npages--; set_npages(); TAILQ_INSERT_TAIL(&tee_pager_lock_pmem_head, pmem, link); break; default: panic(); } asan_tag_no_access(va_alias, va_alias + SMALL_PAGE_SIZE); if (!writable) attr &= ~(TEE_MATTR_PW | TEE_MATTR_UW); /* * We've updated the page using the aliased mapping and * some cache maintenance is now needed if it's an * executable page. * * Since the d-cache is a Physically-indexed, * physically-tagged (PIPT) cache we can clean either the * aliased address or the real virtual address. In this * case we choose the real virtual address. * * The i-cache can also be PIPT, but may be something else * too like VIPT. The current code requires the caches to * implement the IVIPT extension, that is: * "instruction cache maintenance is required only after * writing new data to a physical address that holds an * instruction." * * To portably invalidate the icache the page has to * be mapped at the final virtual address but not * executable. */ if (reg->flags & (TEE_MATTR_PX | TEE_MATTR_UX)) { uint32_t mask = TEE_MATTR_PX | TEE_MATTR_UX | TEE_MATTR_PW | TEE_MATTR_UW; void *va = (void *)page_va; /* Set a temporary read-only mapping */ tblidx_set_entry(tblidx, pa, attr & ~mask); tblidx_tlbi_entry(tblidx); dcache_clean_range_pou(va, SMALL_PAGE_SIZE); if (clean_user_cache) icache_inv_user_range(va, SMALL_PAGE_SIZE); else icache_inv_range(va, SMALL_PAGE_SIZE); /* Set the final mapping */ tblidx_set_entry(tblidx, pa, attr); tblidx_tlbi_entry(tblidx); } else { tblidx_set_entry(tblidx, pa, attr); /* * No need to flush TLB for this entry, it was * invalid. We should use a barrier though, to make * sure that the change is visible. */ dsb_ishst(); } pgt_inc_used_entries(tblidx.pgt); FMSG("Mapped 0x%" PRIxVA " -> 0x%" PRIxPA, page_va, pa); } static void make_dirty_page(struct tee_pager_pmem *pmem, struct vm_paged_region *reg, struct tblidx tblidx, paddr_t pa) { assert(reg->flags & (TEE_MATTR_UW | TEE_MATTR_PW)); assert(!(pmem->flags & PMEM_FLAG_DIRTY)); FMSG("Dirty %#"PRIxVA, tblidx2va(tblidx)); pmem->flags |= PMEM_FLAG_DIRTY; tblidx_set_entry(tblidx, pa, get_region_mattr(reg->flags)); tblidx_tlbi_entry(tblidx); } /* * This function takes a reference to a page (@fobj + fobj_pgidx) and makes * the corresponding IV available. * * In case the page needs to be saved the IV must be writable, consequently * is the page holding the IV made dirty. If the page instead only is to * be verified it's enough that the page holding the IV is readonly and * thus doesn't have to be made dirty too. * * This function depends on pager_spare_pmem pointing to a free pmem when * entered. In case the page holding the needed IV isn't mapped this spare * pmem is used to map the page. If this function has used pager_spare_pmem * and assigned it to NULL it must be reassigned with a new free pmem * before this function can be called again. */ static void make_iv_available(struct fobj *fobj, unsigned int fobj_pgidx, bool writable) { struct vm_paged_region *reg = pager_iv_region; struct tee_pager_pmem *pmem = NULL; struct tblidx tblidx = { }; vaddr_t page_va = 0; uint32_t attr = 0; paddr_t pa = 0; page_va = fobj_get_iv_vaddr(fobj, fobj_pgidx) & ~SMALL_PAGE_MASK; if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) || !page_va) { assert(!page_va); return; } assert(reg && reg->type == PAGED_REGION_TYPE_RW); assert(pager_spare_pmem); assert(core_is_buffer_inside(page_va, 1, reg->base, reg->size)); tblidx = region_va2tblidx(reg, page_va); /* * We don't care if tee_pager_unhide_page() succeeds or not, we're * still checking the attributes afterwards. */ tee_pager_unhide_page(reg, page_va); tblidx_get_entry(tblidx, &pa, &attr); if (!(attr & TEE_MATTR_VALID_BLOCK)) { /* * We're using the spare pmem to map the IV corresponding * to another page. */ pmem = pager_spare_pmem; pager_spare_pmem = NULL; pmem_assign_fobj_page(pmem, reg, page_va); if (writable) pmem->flags |= PMEM_FLAG_DIRTY; pager_deploy_page(pmem, reg, page_va, false /*!clean_user_cache*/, writable); } else if (writable && !(attr & TEE_MATTR_PW)) { pmem = pmem_find(reg, page_va); /* Note that pa is valid since TEE_MATTR_VALID_BLOCK is set */ make_dirty_page(pmem, reg, tblidx, pa); } } static void pager_get_page(struct vm_paged_region *reg, struct abort_info *ai, bool clean_user_cache) { vaddr_t page_va = ai->va & ~SMALL_PAGE_MASK; struct tblidx tblidx = region_va2tblidx(reg, page_va); struct tee_pager_pmem *pmem = NULL; bool writable = false; uint32_t attr = 0; /* * Get a pmem to load code and data into, also make sure * the corresponding IV page is available. */ while (true) { pmem = TAILQ_FIRST(&tee_pager_pmem_head); if (!pmem) { EMSG("No pmem entries"); abort_print(ai); panic(); } if (pmem->fobj) { pmem_unmap(pmem, NULL); if (pmem_is_dirty(pmem)) { uint8_t *va = pmem->va_alias; make_iv_available(pmem->fobj, pmem->fobj_pgidx, true /*writable*/); asan_tag_access(va, va + SMALL_PAGE_SIZE); if (fobj_save_page(pmem->fobj, pmem->fobj_pgidx, pmem->va_alias)) panic("fobj_save_page"); asan_tag_no_access(va, va + SMALL_PAGE_SIZE); pmem_clear(pmem); /* * If the spare pmem was used by * make_iv_available() we need to replace * it with the just freed pmem. * * See make_iv_available() for details. */ if (IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) && !pager_spare_pmem) { TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); pager_spare_pmem = pmem; pmem = NULL; } /* * Check if the needed virtual page was * made available as a side effect of the * call to make_iv_available() above. If so * we're done. */ tblidx_get_entry(tblidx, NULL, &attr); if (attr & TEE_MATTR_VALID_BLOCK) return; /* * The freed pmem was used to replace the * consumed pager_spare_pmem above. Restart * to find another pmem. */ if (!pmem) continue; } } TAILQ_REMOVE(&tee_pager_pmem_head, pmem, link); pmem_clear(pmem); pmem_assign_fobj_page(pmem, reg, page_va); make_iv_available(pmem->fobj, pmem->fobj_pgidx, false /*!writable*/); if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) || pager_spare_pmem) break; /* * The spare pmem was used by make_iv_available(). We need * to replace it with the just freed pmem. And get another * pmem. * * See make_iv_available() for details. */ pmem_clear(pmem); pager_spare_pmem = pmem; } /* * PAGED_REGION_TYPE_LOCK are always writable while PAGED_REGION_TYPE_RO * are never writable. * * Pages from PAGED_REGION_TYPE_RW starts read-only to be * able to tell when they are updated and should be tagged * as dirty. */ if (reg->type == PAGED_REGION_TYPE_LOCK || (reg->type == PAGED_REGION_TYPE_RW && abort_is_write_fault(ai))) writable = true; else writable = false; pager_deploy_page(pmem, reg, page_va, clean_user_cache, writable); } static bool pager_update_permissions(struct vm_paged_region *reg, struct abort_info *ai, bool *handled) { struct tblidx tblidx = region_va2tblidx(reg, ai->va); struct tee_pager_pmem *pmem = NULL; uint32_t attr = 0; paddr_t pa = 0; *handled = false; tblidx_get_entry(tblidx, &pa, &attr); /* Not mapped */ if (!(attr & TEE_MATTR_VALID_BLOCK)) return false; /* Not readable, should not happen */ if (abort_is_user_exception(ai)) { if (!(attr & TEE_MATTR_UR)) return true; } else { if (!(attr & TEE_MATTR_PR)) { abort_print_error(ai); panic(); } } switch (core_mmu_get_fault_type(ai->fault_descr)) { case CORE_MMU_FAULT_TRANSLATION: case CORE_MMU_FAULT_READ_PERMISSION: if (ai->abort_type == ABORT_TYPE_PREFETCH) { /* Check attempting to execute from an NOX page */ if (abort_is_user_exception(ai)) { if (!(attr & TEE_MATTR_UX)) return true; } else { if (!(attr & TEE_MATTR_PX)) { abort_print_error(ai); panic(); } } } /* Since the page is mapped now it's OK */ break; case CORE_MMU_FAULT_WRITE_PERMISSION: /* Check attempting to write to an RO page */ pmem = pmem_find(reg, ai->va); if (!pmem) panic(); if (abort_is_user_exception(ai)) { if (!(reg->flags & TEE_MATTR_UW)) return true; if (!(attr & TEE_MATTR_UW)) make_dirty_page(pmem, reg, tblidx, pa); } else { if (!(reg->flags & TEE_MATTR_PW)) { abort_print_error(ai); panic(); } if (!(attr & TEE_MATTR_PW)) make_dirty_page(pmem, reg, tblidx, pa); } /* Since permissions has been updated now it's OK */ break; default: /* Some fault we can't deal with */ if (abort_is_user_exception(ai)) return true; abort_print_error(ai); panic(); } *handled = true; return true; } #ifdef CFG_TEE_CORE_DEBUG static void stat_handle_fault(void) { static size_t num_faults; static size_t min_npages = SIZE_MAX; static size_t total_min_npages = SIZE_MAX; num_faults++; if ((num_faults % 1024) == 0 || tee_pager_npages < total_min_npages) { DMSG("nfaults %zu npages %zu (min %zu)", num_faults, tee_pager_npages, min_npages); min_npages = tee_pager_npages; /* reset */ } if (tee_pager_npages < min_npages) min_npages = tee_pager_npages; if (tee_pager_npages < total_min_npages) total_min_npages = tee_pager_npages; } #else static void stat_handle_fault(void) { } #endif bool tee_pager_handle_fault(struct abort_info *ai) { struct vm_paged_region *reg; vaddr_t page_va = ai->va & ~SMALL_PAGE_MASK; uint32_t exceptions; bool ret; bool clean_user_cache = false; #ifdef TEE_PAGER_DEBUG_PRINT if (!abort_is_user_exception(ai)) abort_print(ai); #endif /* * We're updating pages that can affect several active CPUs at a * time below. We end up here because a thread tries to access some * memory that isn't available. We have to be careful when making * that memory available as other threads may succeed in accessing * that address the moment after we've made it available. * * That means that we can't just map the memory and populate the * page, instead we use the aliased mapping to populate the page * and once everything is ready we map it. */ exceptions = pager_lock(ai); stat_handle_fault(); /* check if the access is valid */ if (abort_is_user_exception(ai)) { reg = find_uta_region(ai->va); clean_user_cache = true; } else { reg = find_region(&core_vm_regions, ai->va); if (!reg) { reg = find_uta_region(ai->va); clean_user_cache = true; } } if (!reg || !reg->pgt_array[0]) { ret = false; goto out; } if (tee_pager_unhide_page(reg, page_va)) goto out_success; /* * The page wasn't hidden, but some other core may have * updated the table entry before we got here or we need * to make a read-only page read-write (dirty). */ if (pager_update_permissions(reg, ai, &ret)) { /* * Nothing more to do with the abort. The problem * could already have been dealt with from another * core or if ret is false the TA will be paniced. */ goto out; } pager_get_page(reg, ai, clean_user_cache); out_success: tee_pager_hide_pages(); ret = true; out: pager_unlock(exceptions); return ret; } void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap) { size_t n = 0; DMSG("0x%" PRIxVA " - 0x%" PRIxVA " : %d", vaddr, vaddr + npages * SMALL_PAGE_SIZE, (int)unmap); /* setup memory */ for (n = 0; n < npages; n++) { struct core_mmu_table_info *ti = NULL; struct tee_pager_pmem *pmem = NULL; vaddr_t va = vaddr + n * SMALL_PAGE_SIZE; struct tblidx tblidx = { }; unsigned int pgidx = 0; paddr_t pa = 0; uint32_t attr = 0; ti = find_table_info(va); pgidx = core_mmu_va2idx(ti, va); /* * Note that we can only support adding pages in the * valid range of this table info, currently not a problem. */ core_mmu_get_entry(ti, pgidx, &pa, &attr); /* Ignore unmapped pages/blocks */ if (!(attr & TEE_MATTR_VALID_BLOCK)) continue; pmem = calloc(1, sizeof(struct tee_pager_pmem)); if (!pmem) panic("out of mem"); pmem_clear(pmem); pmem->va_alias = pager_add_alias_page(pa); if (unmap) { core_mmu_set_entry(ti, pgidx, 0, 0); pgt_dec_used_entries(find_core_pgt(va)); } else { struct vm_paged_region *reg = NULL; /* * The page is still mapped, let's assign the region * and update the protection bits accordingly. */ reg = find_region(&core_vm_regions, va); assert(reg); pmem_assign_fobj_page(pmem, reg, va); tblidx = pmem_get_region_tblidx(pmem, reg); assert(tblidx.pgt == find_core_pgt(va)); assert(pa == get_pmem_pa(pmem)); tblidx_set_entry(tblidx, pa, get_region_mattr(reg->flags)); } if (unmap && IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV) && !pager_spare_pmem) { pager_spare_pmem = pmem; } else { tee_pager_npages++; incr_npages_all(); set_npages(); TAILQ_INSERT_TAIL(&tee_pager_pmem_head, pmem, link); } } /* * As this is done at inits, invalidate all TLBs once instead of * targeting only the modified entries. */ tlbi_all(); } #ifdef CFG_PAGED_USER_TA static struct pgt *find_pgt(struct pgt *pgt, vaddr_t va) { struct pgt *p = pgt; while (p && (va & ~CORE_MMU_PGDIR_MASK) != p->vabase) p = SLIST_NEXT(p, link); return p; } void tee_pager_assign_um_tables(struct user_mode_ctx *uctx) { struct vm_paged_region *reg = NULL; struct pgt *pgt = NULL; size_t n = 0; if (!uctx->regions) return; pgt = SLIST_FIRST(&uctx->pgt_cache); TAILQ_FOREACH(reg, uctx->regions, link) { for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) { vaddr_t va = reg->base + CORE_MMU_PGDIR_SIZE * n; struct pgt *p __maybe_unused = find_pgt(pgt, va); if (!reg->pgt_array[n]) reg->pgt_array[n] = p; else assert(reg->pgt_array[n] == p); } } } void tee_pager_pgt_save_and_release_entries(struct pgt *pgt) { struct tee_pager_pmem *pmem = NULL; struct vm_paged_region *reg = NULL; struct vm_paged_region_head *regions = NULL; uint32_t exceptions = pager_lock_check_stack(SMALL_PAGE_SIZE); size_t n = 0; if (!pgt->num_used_entries) goto out; TAILQ_FOREACH(pmem, &tee_pager_pmem_head, link) { if (pmem->fobj) pmem_unmap(pmem, pgt); } assert(!pgt->num_used_entries); out: regions = to_user_mode_ctx(pgt->ctx)->regions; if (regions) { TAILQ_FOREACH(reg, regions, link) { for (n = 0; n < get_pgt_count(reg->base, reg->size); n++) { if (reg->pgt_array[n] == pgt) { reg->pgt_array[n] = NULL; break; } } } } pager_unlock(exceptions); } DECLARE_KEEP_PAGER(tee_pager_pgt_save_and_release_entries); #endif /*CFG_PAGED_USER_TA*/ void tee_pager_release_phys(void *addr, size_t size) { bool unmaped = false; vaddr_t va = (vaddr_t)addr; vaddr_t begin = ROUNDUP(va, SMALL_PAGE_SIZE); vaddr_t end = ROUNDDOWN(va + size, SMALL_PAGE_SIZE); struct vm_paged_region *reg; uint32_t exceptions; if (end <= begin) return; exceptions = pager_lock_check_stack(128); for (va = begin; va < end; va += SMALL_PAGE_SIZE) { reg = find_region(&core_vm_regions, va); if (!reg) panic(); unmaped |= tee_pager_release_one_phys(reg, va); } if (unmaped) tlbi_va_range(begin, end - begin, SMALL_PAGE_SIZE); pager_unlock(exceptions); } DECLARE_KEEP_PAGER(tee_pager_release_phys); void *tee_pager_alloc(size_t size) { tee_mm_entry_t *mm = NULL; uint8_t *smem = NULL; size_t num_pages = 0; struct fobj *fobj = NULL; if (!size) return NULL; mm = tee_mm_alloc(&core_virt_mem_pool, ROUNDUP(size, SMALL_PAGE_SIZE)); if (!mm) return NULL; smem = (uint8_t *)tee_mm_get_smem(mm); num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE; fobj = fobj_locked_paged_alloc(num_pages); if (!fobj) { tee_mm_free(mm); return NULL; } tee_pager_add_core_region((vaddr_t)smem, PAGED_REGION_TYPE_LOCK, fobj); fobj_put(fobj); asan_tag_access(smem, smem + num_pages * SMALL_PAGE_SIZE); return smem; } vaddr_t tee_pager_init_iv_region(struct fobj *fobj) { tee_mm_entry_t *mm = NULL; uint8_t *smem = NULL; assert(!pager_iv_region); mm = tee_mm_alloc(&core_virt_mem_pool, fobj->num_pages * SMALL_PAGE_SIZE); if (!mm) panic(); smem = (uint8_t *)tee_mm_get_smem(mm); tee_pager_add_core_region((vaddr_t)smem, PAGED_REGION_TYPE_RW, fobj); fobj_put(fobj); asan_tag_access(smem, smem + fobj->num_pages * SMALL_PAGE_SIZE); pager_iv_region = find_region(&core_vm_regions, (vaddr_t)smem); assert(pager_iv_region && pager_iv_region->fobj == fobj); return (vaddr_t)smem; } optee_os-4.3.0/core/arch/arm/plat-amlogic/000077500000000000000000000000001464416617300203445ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-amlogic/conf.mk000066400000000000000000000006321464416617300216230ustar00rootroot00000000000000PLATFORM_FLAVOR ?= axg include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) CFG_TZDRAM_START ?= 0x05300000 CFG_TZDRAM_SIZE ?= 0x00c00000 CFG_SHMEM_START ?= 0x05000000 CFG_SHMEM_SIZE ?= 0x00100000 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_AMLOGIC_UART,y) $(call force,CFG_WITH_PAGER,n) $(call force,CFG_ARM64_core,y) optee_os-4.3.0/core/arch/arm/plat-amlogic/link.mk000066400000000000000000000010651464416617300216340ustar00rootroot00000000000000include core/arch/arm/kernel/link.mk # Create BL32 image from the native binary images define aml_bin2img_cmd @$(cmd-echo-silent) ' GEN $@' $(q)./core/arch/arm/plat-amlogic/scripts/aml_bin2img.py endef ifneq (,$(filter $(PLATFORM_FLAVOR),axg)) all: $(link-out-dir)/bl32.img cleanfiles += $(link-out-dir)/bl32.img $(link-out-dir)/bl32.img: $(link-out-dir)/tee-pager_v2.bin $(aml_bin2img_cmd) --source $< --dest $@ --entry 0x5300000 \ --res_mem_start 0x5300000 --res_mem_size 0x1000000 \ --sec_mem_start 0x5300000 --sec_mem_size 0xc00000 endif optee_os-4.3.0/core/arch/arm/plat-amlogic/main.c000066400000000000000000000007721464416617300214420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020 Carlo Caione */ #include #include #include #include #include static struct amlogic_uart_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); void plat_console_init(void) { amlogic_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-amlogic/platform_config.h000066400000000000000000000006611464416617300236710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020 Carlo Caione */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #define GIC_BASE 0xFFC01000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define CONSOLE_UART_BASE 0xFF803000 #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-amlogic/scripts/000077500000000000000000000000001464416617300220335ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-amlogic/scripts/aml_bin2img.py000077500000000000000000000063251464416617300245760ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2020 Carlo Caione # # Derived from plat-stm32mp1/scripts/stm32image.py # import argparse import struct import mmap header_size = 0x200 ext_magic_number = 0x12348765 version = 0x00002710 def get_size(file): file.seek(0, 2) # End of the file size = file.tell() return size def aml_set_header(dest_fd, entry, res_mem_start, res_mem_size, sec_mem_start, sec_mem_size): dest_fd.seek(0, 0) dest_fd.write(struct.pack(' 0: mmsrc = mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ) dest_fd.write(mmsrc[:sizesrc]) mmsrc.close() src_fd.close() aml_set_header(dest_fd, entry, res_mem_start, res_mem_size, sec_mem_start, sec_mem_size) dest_fd.close() def auto_int(x): return int(x, 0) def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--source', required=True, help='Source file') parser.add_argument('--dest', required=True, help='Destination file') parser.add_argument('--entry', required=True, type=auto_int, help='Entry point') parser.add_argument('--res_mem_start', required=True, type=auto_int, help='Reserved memory start') parser.add_argument('--res_mem_size', required=True, type=auto_int, help='Reserved memory size') parser.add_argument('--sec_mem_start', required=True, type=auto_int, help='Secure memory start') parser.add_argument('--sec_mem_size', required=True, type=auto_int, help='Secure memory size') return parser.parse_args() def main(): args = get_args() source_file = args.source destination_file = args.dest entry_point = args.entry res_mem_start = args.res_mem_start res_mem_size = args.res_mem_size sec_mem_start = args.sec_mem_start sec_mem_size = args.sec_mem_size aml_create_header_file(source_file, destination_file, entry_point, res_mem_start, res_mem_size, sec_mem_start, sec_mem_size) if __name__ == "__main__": main() optee_os-4.3.0/core/arch/arm/plat-amlogic/sub.mk000066400000000000000000000000471464416617300214670ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-aspeed/000077500000000000000000000000001464416617300201725ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-aspeed/conf.mk000066400000000000000000000022601464416617300214500ustar00rootroot00000000000000PLATFORM_FLAVOR ?= ast2600 ifeq ($(PLATFORM_FLAVOR),ast2600) include core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_8250_UART,y) $(call force,CFG_ARM32_core,y) $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_GIC,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE) CFG_DRAM_BASE ?= 0x80000000 CFG_DRAM_SIZE ?= 0x40000000 CFG_TZDRAM_START ?= 0xb0000000 CFG_TZDRAM_SIZE ?= 0x1000000 CFG_CORE_RESERVED_SHM ?= n arm32-platform-cflags += -mfpu=vfpv3-d16 else ifeq ($(PLATFORM_FLAVOR),ast2700) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_8250_UART,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE) CFG_DRAM_BASE ?= 0x400000000 CFG_DRAM_SIZE ?= 0x40000000 CFG_TZDRAM_START ?= 0x430080000 CFG_TZDRAM_SIZE ?= 0x1000000 CFG_CORE_RESERVED_SHM ?= n supported-ta-targets = ta_arm64 else $(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") endif optee_os-4.3.0/core/arch/arm/plat-aspeed/core_pos_a32.S000066400000000000000000000004771464416617300226040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Aspeed Technology Inc. */ #include #include #include FUNC get_core_pos_mpidr , : /* * need this to correct core0 - 0xf00, core1 - 0xf01, ... */ and r0, r0, #MPIDR_CPU_MASK bx lr END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-aspeed/platform_ast2600.c000066400000000000000000000051371464416617300233470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Aspeed Technology Inc. */ #include #include #include #include #include #include #include #include #include enum TZM_PERM { TZM_PERM_VGA_CURSOR_RD, TZM_PERM_VGA_CRT_RD, TZM_PERM_SOC_DISPLAY_RD, TZM_PERM_PCIE_BUS1_RW, TZM_PERM_VIDEO_HIGH_WR, TZM_PERM_CPU_RW, TZM_PERM_SLI_RW, TZM_PERM_PCIE_BUS2_RW, TZM_PERM_USB20_HUB_EHCI1_DMA_RW, TZM_PERM_USB20_DEV_EHCI2_DMA_RW, TZM_PERM_USB11_UCHI_HOST_RW, TZM_PERM_AHB_RW, TZM_PERM_CM3_DATA_RW, TZM_PERM_CM3_INSN_RW, TZM_PERM_MAC0_DMA_RW, TZM_PERM_MAC1_DMA_RW, TZM_PERM_SDIO_DMA_RW, TZM_PERM_PILOT_RW, TZM_PERM_XDMA1_RW, TZM_PERM_MCTP1_RW, TZM_PERM_VIDEO_FLAG_RW, TZM_PERM_VIDEO_LOW_WR, TZM_PERM_2D_DATA_RW, TZM_PERM_ENCRYPT_RW, TZM_PERM_MCTP2_RW, TZM_PERM_XDMA2_RW, TZM_PERM_ECC_RSA_RW, }; register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SMALL_PAGE_SIZE); register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE + GICD_OFFSET, GIC_DIST_REG_SIZE); register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE + GICC_OFFSET, GIC_CPU_REG_SIZE); register_phys_mem(MEM_AREA_IO_SEC, AHBC_BASE, SMALL_PAGE_SIZE); register_phys_mem(MEM_AREA_IO_NSEC, SCU_BASE, SMALL_PAGE_SIZE); #define AHBC_REG_WR_PROT 0x204 #define AHBC_TZP_ACCESS1 0x280 #define AHBC_TZP_HACE BIT(20) #define AHBC_TZM_ST(i) (0x300 + ((i) * 0x10)) #define AHBC_TZM_ED(i) (0x304 + ((i) * 0x10)) #define AHBC_TZM_PERM(i) (0x308 + ((i) * 0x10)) register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); static struct serial8250_uart_data console_data; void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } void plat_primary_init_early(void) { vaddr_t ahbc_virt = 0; uint32_t tzm_perm = 0; ahbc_virt = core_mmu_get_va(AHBC_BASE, MEM_AREA_IO_SEC, SMALL_PAGE_SIZE); if (!ahbc_virt) panic(); tzm_perm = BIT(TZM_PERM_CPU_RW); if (IS_ENABLED(CFG_ASPEED_CRYPTO_DRIVER)) { tzm_perm |= BIT(TZM_PERM_ENCRYPT_RW); io_write32(ahbc_virt + AHBC_TZP_ACCESS1, AHBC_TZP_HACE); } io_write32(ahbc_virt + AHBC_TZM_PERM(0), tzm_perm); io_write32(ahbc_virt + AHBC_TZM_ED(0), CFG_TZDRAM_START + CFG_TZDRAM_SIZE - 1); io_write32(ahbc_virt + AHBC_TZM_ST(0), CFG_TZDRAM_START | BIT(0)); io_write32(ahbc_virt + AHBC_REG_WR_PROT, BIT(16)); } optee_os-4.3.0/core/arch/arm/plat-aspeed/platform_ast2700.c000066400000000000000000000015641464416617300233500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Aspeed Technology Inc. */ #include #include #include #include #include #include #include register_phys_mem(MEM_AREA_IO_SEC, UART_BASE, SMALL_PAGE_SIZE); register_phys_mem(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); register_phys_mem(MEM_AREA_IO_SEC, GICR_BASE, GICR_SIZE); register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); static struct serial8250_uart_data console_data; void boot_primary_init_intc(void) { gic_init_v3(0, GICD_BASE, GICR_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-aspeed/platform_config.h000066400000000000000000000017171464416617300235220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Aspeed Technology Inc. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #if defined(PLATFORM_FLAVOR_ast2600) #define GIC_BASE 0x40460000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define AHBC_BASE 0x1e600000 #define SCU_BASE 0x1e6e2000 #define UART5_BASE 0x1e784000 #define CONSOLE_UART_BASE UART5_BASE #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 1846153 #elif defined(PLATFORM_FLAVOR_ast2700) #define GICD_BASE 0x12200000 #define GICR_BASE 0x12280000 #define GICR_SIZE 0x100000 #define UART_BASE 0x14c33000 #define UART12_BASE (UART_BASE + 0xb00) #define CONSOLE_UART_BASE UART12_BASE #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 1846153 #else #error "Unknown platform flavor" #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-aspeed/sub.mk000066400000000000000000000002211464416617300213070ustar00rootroot00000000000000global-incdirs-y += . srcs-$(PLATFORM_FLAVOR_ast2600) += platform_ast2600.c core_pos_a32.S srcs-$(PLATFORM_FLAVOR_ast2700) += platform_ast2700.c optee_os-4.3.0/core/arch/arm/plat-bcm/000077500000000000000000000000001464416617300174725ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-bcm/bcm_elog.c000066400000000000000000000026711464416617300214130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include static struct bcm_elog global_elog; void bcm_elog_putchar(char ch) { struct bcm_elog *elog = &global_elog; uint32_t offset = 0, len = 0; vaddr_t base = 0; base = io_pa_or_va(&elog->base, elog->max_size); offset = io_read32(base + BCM_ELOG_OFF_OFFSET); len = io_read32(base + BCM_ELOG_LEN_OFFSET); io_write8(base + offset, ch); offset++; /* Log buffer is now full and need to wrap around */ if (offset >= elog->max_size) offset = BCM_ELOG_HEADER_LEN; /* Only increment length when log buffer is not full */ if (len < elog->max_size - BCM_ELOG_HEADER_LEN) len++; io_write32(base + BCM_ELOG_OFF_OFFSET, offset); io_write32(base + BCM_ELOG_LEN_OFFSET, len); } void bcm_elog_init(uintptr_t pa_base, uint32_t size) { struct bcm_elog *elog = &global_elog; uint32_t val = 0; vaddr_t base = 0; elog->base.pa = pa_base; elog->max_size = size; base = io_pa_or_va(&elog->base, BCM_ELOG_HEADER_LEN); /* * If a valid signature is found, it means logging is already * initialized. In this case, we should not re-initialize the entry * header in the designated memory */ val = io_read32(base + BCM_ELOG_SIG_OFFSET); if (val != BCM_ELOG_SIG_VAL) { io_write32(base + BCM_ELOG_SIG_OFFSET, BCM_ELOG_SIG_VAL); io_write32(base + BCM_ELOG_OFF_OFFSET, BCM_ELOG_HEADER_LEN); io_write32(base + BCM_ELOG_LEN_OFFSET, 0); } } optee_os-4.3.0/core/arch/arm/plat-bcm/bcm_elog.h000066400000000000000000000014201464416617300214070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef BCM_ELOG_H #define BCM_ELOG_H #include /* Error logging signature offset and value */ #define BCM_ELOG_SIG_OFFSET 0x0000 #define BCM_ELOG_SIG_VAL 0x75767971 /* Current logging offset that points to where new logs should be added */ #define BCM_ELOG_OFF_OFFSET 0x0004 /* Current logging length (excluding header) */ #define BCM_ELOG_LEN_OFFSET 0x0008 #define BCM_ELOG_HEADER_LEN 12 /* * @base: base address of memory where log is saved * @max_size: max size of memory reserved for logging */ struct bcm_elog { struct io_pa_va base; uint32_t max_size; }; void bcm_elog_init(uintptr_t pa_base, uint32_t size); void bcm_elog_putchar(char ch); #endif /* BCM_ELOG_H */ optee_os-4.3.0/core/arch/arm/plat-bcm/conf.mk000066400000000000000000000021251464416617300207500ustar00rootroot00000000000000PLATFORM_FLAVOR ?= ns3 include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_8250_UART,y) $(call force,CFG_TEE_CORE_DEBUG,n) $(call force,CFG_GIC,y) $(call force,CFG_WITH_LPAE,y) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_CORE_CLUSTER_SHIFT,1) $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_CORE_ARM64_PA_BITS,48) CFG_TZDRAM_START ?= 0x8e000000 CFG_TZDRAM_SIZE ?= 0x01000000 # 16MB CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) - $(CFG_SHMEM_SIZE)) CFG_SHMEM_SIZE ?= 0x01000000 # 16MB CFG_TEE_RAM_VA_SIZE := 0x400000 # 4MB $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) ifeq ($(PLATFORM_FLAVOR),ns3) $(call force,CFG_PL022,y) $(call force,CFG_SP805_WDT,y) $(call force,CFG_BCM_HWRNG,y) $(call force,CFG_BCM_SOTP,y) $(call force,CFG_BCM_GPIO,y) CFG_BNXT_FW ?= y CFG_BCM_ELOG_DUMP ?= y endif CFG_BCM_ELOG_AP_UART_LOG_BASE ?= 0x8f110000 CFG_BCM_ELOG_AP_UART_LOG_SIZE ?= 0x10000 CFG_BCM_ELOG_BASE ?= 0x8f120000 CFG_BCM_ELOG_SIZE ?= 0x100000 ifeq ($(DEBUG),1) platform-cflags += -gdwarf-2 platform-aflags += -gdwarf-2 endif CFG_WITH_STACK_CANARIES ?= n optee_os-4.3.0/core/arch/arm/plat-bcm/crc32.c000066400000000000000000000067561464416617300205700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include static const uint32_t crc32tbl[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; static uint32_t ucrc32(const char ch, uint32_t crc) { return crc32tbl[(crc ^ ch) & 0xff] ^ (crc >> 8); } uint32_t crc32i(uint32_t crc, const char *buf, size_t len) { size_t l = 0; for (l = 0; l < len; l++) crc = ucrc32(buf[l], crc); return ~crc; } optee_os-4.3.0/core/arch/arm/plat-bcm/crc32.h000066400000000000000000000004371464416617300205630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef CRC32_H #define CRC32_H #include #include #define CRC32_INIT_VAL (~0) #define CRC32 crc32i uint32_t crc32i(uint32_t crc, const char *buf, size_t len); #endif /* CRC32_H */ optee_os-4.3.0/core/arch/arm/plat-bcm/main.c000066400000000000000000000041171464416617300205650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include #include #include #include struct serial8250_uart_data console_data; #ifdef BCM_DEVICE0_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE0_BASE, BCM_DEVICE0_SIZE); #endif #ifdef BCM_DEVICE1_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE1_BASE, BCM_DEVICE1_SIZE); #endif #ifdef BCM_DEVICE2_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE2_BASE, BCM_DEVICE2_SIZE); #endif #ifdef BCM_DEVICE3_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE3_BASE, BCM_DEVICE3_SIZE); #endif #ifdef BCM_DEVICE4_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, BCM_DEVICE4_BASE, BCM_DEVICE4_SIZE); #endif #ifdef BCM_DEVICE5_BASE register_phys_mem_pgdir(MEM_AREA_IO_NSEC, BCM_DEVICE5_BASE, BCM_DEVICE5_SIZE); #endif #ifdef BCM_DRAM0_NS_BASE register_dynamic_shm(BCM_DRAM0_NS_BASE, BCM_DRAM0_NS_SIZE); #endif #ifdef BCM_DRAM1_NS_BASE register_dynamic_shm(BCM_DRAM1_NS_BASE, BCM_DRAM1_NS_SIZE); #endif #ifdef BCM_DRAM2_NS_BASE register_dynamic_shm(BCM_DRAM2_NS_BASE, BCM_DRAM2_NS_SIZE); #endif #ifdef BCM_DRAM0_SEC_BASE register_phys_mem(MEM_AREA_RAM_SEC, BCM_DRAM0_SEC_BASE, BCM_DRAM0_SEC_SIZE); #endif #ifdef CFG_BCM_ELOG_AP_UART_LOG_BASE register_phys_mem(MEM_AREA_IO_NSEC, CFG_BCM_ELOG_AP_UART_LOG_BASE, CFG_BCM_ELOG_AP_UART_LOG_SIZE); #endif #ifdef CFG_BCM_ELOG_BASE register_phys_mem(MEM_AREA_RAM_NSEC, CFG_BCM_ELOG_BASE, CFG_BCM_ELOG_SIZE); #endif void plat_trace_ext_puts(const char *str) { const char *p; for (p = str; *p; p++) bcm_elog_putchar(*p); } void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); bcm_elog_init(CFG_BCM_ELOG_AP_UART_LOG_BASE, CFG_BCM_ELOG_AP_UART_LOG_SIZE); } void boot_primary_init_intc(void) { gic_init(0, GICD_BASE); } optee_os-4.3.0/core/arch/arm/plat-bcm/platform_config.h000066400000000000000000000035571464416617300230260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #define STACK_ALIGNMENT 64 #define CONSOLE_UART_CLK_IN_HZ 25000000 #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_BASE 0x68a10000 #define GICD_BASE 0x63c00000 #define SMBUS0_BASE 0x689b0000 #define SMBUS0_END (SMBUS0_BASE + 0xB0) #define SECURE_GPIO_BASE0 0x68b00000 #define ASIU_GPIO_INTR 190 #define GPIO_NUM_START0 0 #define NUM_GPIOS0 151 #define CHIP_SECURE_GPIO_CONTROL0_BASE 0x68b60000 #define SPI_0_BASE 0x68a80000 #define SPI_0_END (SPI_0_BASE + 0x1000) #define SPI_0_CLK_HZ 175000000 #define SPI_0_CS_MUX_PAD 0x68a40490 #define HWRNG_BASE 0x68b20000 #define HWRNG_END (HWRNG_BASE + 0x28) #define SOTP_BASE 0x68b50000 /* NO ECC bits are present from ROW_0 to ROW_20, i.e Section 0 to Section 3 */ #define SOTP_NO_ECC_ROWS 20 /* Secure Watch Dog */ #define SEC_WDT_BASE 0x68B30000 #define SEC_WDT_END (SEC_WDT_BASE + 0x1000) #define SEC_WDT_CLK_HZ 12500000 #define SEC_WDT_INTR 192 #define BNXT_BASE 0x60800000 #define QSPI_MEM_BASE 0x70000000 /* device memory ranges */ #define BCM_DEVICE0_BASE GICD_BASE #define BCM_DEVICE0_SIZE CORE_MMU_PGDIR_SIZE #define BCM_DEVICE1_BASE SMBUS0_BASE #define BCM_DEVICE1_SIZE CORE_MMU_PGDIR_SIZE #define BCM_DEVICE4_BASE BNXT_BASE #define BCM_DEVICE4_SIZE 0x800000 #define BCM_DEVICE5_BASE QSPI_MEM_BASE #define BCM_DEVICE5_SIZE 0x800000 /* NS DDR ranges */ #define BCM_DRAM0_NS_BASE 0x80000000 #define BCM_DRAM0_NS_SIZE 0xae00000 #define BCM_DRAM1_NS_BASE 0x90000000 #define BCM_DRAM1_NS_SIZE 0x70000000 #define BCM_DRAM2_NS_BASE 0x880100000 #define BCM_DRAM2_NS_SIZE 0x17ff00000 /* Secure DDR ranges */ #define BCM_DRAM0_SEC_BASE 0x8ae00000 #define BCM_DRAM0_SEC_SIZE 0x2200000 #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-bcm/sub.mk000066400000000000000000000001161464416617300206120ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += crc32.c srcs-y += bcm_elog.c optee_os-4.3.0/core/arch/arm/plat-corstone1000/000077500000000000000000000000001464416617300210665ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-corstone1000/conf.mk000066400000000000000000000021741464416617300223500ustar00rootroot00000000000000PLATFORM_FLAVOR ?= mps3 # ARM debugger needs this platform-cflags-debug-info = -gdwarf-2 platform-aflags-debug-info = -gdwarf-2 $(call force,CFG_HWSUPP_MEM_PERM_WXN,y) $(call force,CFG_HWSUPP_MEM_PERM_PXN,y) $(call force,CFG_ENABLE_SCTLR_RR,n) $(call force,CFG_ENABLE_SCTLR_Z,n) $(call force,CFG_WITH_LPAE,y) $(call force,CFG_PSCI_ARM64,y) $(call force,CFG_DT,y) $(call force,CFG_EXTERNAL_DTB_OVERLAY,y) $(call force,CFG_CORE_SEL1_SPMC,y) $(call force,CFG_CORE_FFA,y) $(call force,CFG_SECURE_PARTITION,y) $(call force,CFG_GIC,y) $(call force,CFG_PL011,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_ARM64_core,y) arm64-platform-cpuarch := cortex-a35 arm64-platform-cflags += -mcpu=$(arm64-platform-cpuarch) arm64-platform-aflags += -mcpu=$(arm64-platform-cpuarch) CFG_WITH_STATS ?= y CFG_WITH_ARM_TRUSTED_FW ?= y CFG_TEE_CORE_NB_CORE ?= 1 CFG_TZDRAM_START ?= 0x02002000 # TEE_RAM (OPTEE kernel + DATA) + TA_RAM = 3MB CFG_TZDRAM_SIZE ?= 0x300000 CFG_SHMEM_START ?= 0x86000000 CFG_SHMEM_SIZE ?= 0x00200000 CFG_DDR_SIZE ?= 0x7f000000 CFG_DT_ADDR ?= 0x82100000 CFG_DTB_MAX_SIZE ?= 0x100000 CFG_CORE_HEAP_SIZE ?= 131072 optee_os-4.3.0/core/arch/arm/plat-corstone1000/main.c000066400000000000000000000015751464416617300221660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Arm Limited */ #include #include #include #include #include #include #include #include static struct pl011_data console_data __nex_bss; register_ddr(DRAM0_BASE, DRAM0_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); void boot_primary_init_intc(void) { gic_init(GICC_BASE, GICD_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-corstone1000/platform_config.h000066400000000000000000000014571464416617300244170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Arm Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #define GIC_BASE 0x1c000000 #define UART0_BASE 0x1a510000 #define UART1_BASE 0x1a520000 #define CONSOLE_UART_BASE UART1_BASE #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE CFG_DDR_SIZE #define GICD_OFFSET 0x10000 #define GICC_OFFSET 0x2F000 #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) #define UART_BAUDRATE 115200 #define CONSOLE_BAUDRATE UART_BAUDRATE #define SYS_COUNTER_FREQ_IN_TICKS UL(50000000) /* 50MHz */ #define CONSOLE_UART_CLK_IN_HZ UL(50000000) /* 50MHz*/ #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-corstone1000/sub.mk000066400000000000000000000000471464416617300222110ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-d02/000077500000000000000000000000001464416617300173165ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-d02/conf.mk000066400000000000000000000014651464416617300206020ustar00rootroot00000000000000include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,16) CFG_NUM_THREADS ?= 16 CFG_CRYPTO_WITH_CE ?= y CFG_WITH_SOFTWARE_PRNG ?= n # Overrides default in mk/config.mk with 96 kB CFG_CORE_HEAP_SIZE ?= 98304 $(call force,CFG_HI16XX_UART,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) $(call force,CFG_HI16XX_RNG,y) endif $(call force,CFG_WITH_LPAE,y) ifeq ($(CFG_ARM64_core),y) CFG_CORE_TZSRAM_EMUL_SIZE ?= 655360 else CFG_CORE_TZSRAM_EMUL_SIZE ?= 524288 endif # 20MB-384kB of secure RAM ifeq ($(CFG_WITH_PAGER),y) CFG_TEE_RAM_VA_SIZE ?= 0x00400000 else CFG_TEE_RAM_VA_SIZE ?= 0x00200000 endif CFG_TZDRAM_START ?= 0x50400000 CFG_TZDRAM_SIZE ?= 0x013a00000 CFG_SHMEM_START ?= 0x50000000 CFG_SHMEM_SIZE ?= 0x00400000 optee_os-4.3.0/core/arch/arm/plat-d02/main.c000066400000000000000000000011101464416617300203770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include #include #include #include static struct hi16xx_uart_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, HI16XX_UART_REG_SIZE); void plat_console_init(void) { hi16xx_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-d02/platform_config.h000066400000000000000000000046041464416617300226440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* UART */ #define PERI_SUB_CTRL_ADDR 0x80000000 #define CONSOLE_UART_BASE (PERI_SUB_CTRL_ADDR + 0x00300000) #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 200000000 /* ALG sub-controller */ #define ALG_SC_BASE 0xD0000000 #define ALG_SC_REG_SIZE 0xF010 /* RNG */ #define RNG_BASE 0xD1010000 #define RNG_REG_SIZE 0x18 /* * HiSilicon D02 memory map * * Note: the physical address ranges below correspond to DRAM which is * non-secure by default. Therefore, the terms TZDRAM and TZSRAM may not * reflect the reality and only indicate areas that "would normally be" * secure DRAM and secure SRAM in a more complete implementation. * The memory map was defined like this for lack of better documentation. * It is good enough for development/testing purposes. * * CFG_WITH_PAGER=n * * 0x7FC0_0000 - * Linux/other | DRAM1 * 0x5180_0000 - * TA RAM: 16 MiB | * 0x5080_0000 | TZDRAM * TEE RAM: 4 MiB (TEE_RAM_VA_SIZE) | * 0x5040_0000 [TZDRAM_BASE, TEE_LOAD_ADDR] - * Shared memory: 4 MiB | SHMEM * 0x5000_0000 - * Linux/other | DRAM0 * 0x0000_0000 [DRAM0_BASE] - * * CFG_WITH_PAGER=y * * 0x7FC0_0000 - * Linux/other | DRAM1 * 0x5180_0000 - * TA RAM: 20096 KiB (TZDRAM_SIZE) | TZDRAM * 0x5046_0000 - * TEE RAM: 384 KiB (TZSRAM_SIZE) | TZSRAM * 0x5040_0000 [TZSRAM_BASE, TEE_LOAD_ADDR] - * Shared memory: 4 MiB | SHMEM * 0x5000_0000 - * Linux/other | DRAM0 * 0x0000_0000 [DRAM0_BASE] - */ #define DRAM0_BASE 0x00000000 #define DRAM0_SIZE 0x50000000 #define DRAM1_BASE 0x51800000 #define DRAM1_SIZE 0x2E400000 #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-d02/sub.mk000066400000000000000000000000471464416617300204410ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-d06/000077500000000000000000000000001464416617300173225ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-d06/conf.mk000066400000000000000000000014101464416617300205740ustar00rootroot00000000000000include core/arch/arm/cpu/cortex-armv8-0.mk CFG_TEE_CORE_NB_CORE ?= 128 CFG_NUM_THREADS ?= 96 CFG_CRYPTO_WITH_CE ?= y CFG_WITH_PAGER ?= n CFG_WITH_SOFTWARE_PRNG ?= n CFG_WITH_STATS ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_HISILICON_CRYPTO_DRIVER ?= y $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_WITH_LPAE,y) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_LPAE_ADDR_SPACE_BITS,48) $(call force,CFG_LPC_UART,y) CFG_TEE_CORE_LOG_LEVEL ?= 4 CFG_CORE_HEAP_SIZE ?= 0x008000000 CFG_CORE_ARM64_PA_BITS ?= 40 CFG_TEE_RAM_VA_SIZE ?= 0x009000000 CFG_TZDRAM_START ?= 0x20C0000000 CFG_TZDRAM_SIZE ?= 0x32000000 CFG_SHMEM_START ?= 0x50000000 CFG_SHMEM_SIZE ?= 0x04000000 optee_os-4.3.0/core/arch/arm/plat-d06/core_pos_a64.S000066400000000000000000000016711464416617300217360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2019, Arm Limited. All rights reserved. * Copyright (c) 2020, Marek Vasut * Copyright (c) 2022, Huawei Technologies Co., Ltd */ #include #include #include /* * bit8~bit10: core index * bit16~bit18: ccl index * bit20~bit22: sccl index * 96 cores: index = sccl * 24 + ccl * 4 + core * 128 cores: index = sccl * 32 + ccl * 4 + core (now used) */ FUNC get_core_pos_mpidr , : lsr x1, x0, 8 and x2, x1, 0x7 lsr x1, x0, 16 and x3, x1, 0x7 lsr x1, x0, 20 and x4, x1, 0x7 mov x5, x4 #if (CFG_TEE_CORE_NB_CORE == 96) lsl x5, x5, 1 add x5, x5, x4 lsl x5, x5, 1 #elif (CFG_TEE_CORE_NB_CORE == 128) lsl x5, x5, 3 #else static_assert(0); #endif add x5, x5, x3 lsl x5, x5, 2 add x5, x5, x2 mov x0, x5 ret END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-d06/main.c000066400000000000000000000007731464416617300204210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2022, Huawei Technologies Co., Ltd */ #include #include #include static struct lpc_uart_data console_data __nex_bss; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, LPC_BASE, LPC_SIZE); void plat_console_init(void) { lpc_uart_init(&console_data, LPC_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-d06/platform_config.h000066400000000000000000000010221464416617300226370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2022, Huawei Technologies Co., Ltd */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* UART */ #define UART_BASE 0x2f8 #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 200 /* HISI_TRNG */ #define HISI_TRNG_BASE 0x2010C0000 #define HISI_TRNG_SIZE 0x100 #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-d06/sub.mk000066400000000000000000000001001464416617300204330ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += core_pos_a64.S optee_os-4.3.0/core/arch/arm/plat-hikey/000077500000000000000000000000001464416617300200425ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-hikey/conf.mk000066400000000000000000000026151464416617300213240ustar00rootroot00000000000000PLATFORM_FLAVOR ?= hikey include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_PL011,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) CFG_NUM_THREADS ?= 8 CFG_CRYPTO_WITH_CE ?= y ifeq ($(PLATFORM_FLAVOR),hikey) CFG_CORE_HEAP_SIZE ?= 73728 CFG_PL061 ?= y CFG_PL022 ?= y CFG_SPI ?= y ifeq ($(CFG_SPI_TEST),y) $(call force,CFG_SPI,y) endif ifeq ($(CFG_SPI),y) $(call force,CFG_PL061,y) $(call force,CFG_PL022,y) endif ifeq ($(CFG_PL061),y) core-platform-cppflags += -DPLAT_PL061_MAX_GPIOS=160 endif endif CFG_CACHE_API ?= y CFG_SECURE_DATA_PATH ?= n CFG_TEE_SDP_MEM_BASE ?= 0x3E800000 CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 ifeq ($(PLATFORM_FLAVOR),hikey) CFG_CONSOLE_UART ?= 3 CFG_DRAM_SIZE_GB ?= 2 endif ifeq ($(PLATFORM_FLAVOR),hikey960) CFG_CONSOLE_UART ?= 6 CFG_DRAM_SIZE_GB ?= 3 CFG_CORE_BGET_BESTFIT ?= y ifeq ($(CFG_ARM32_core),y) CFG_ASAN_SHADOW_OFFSET ?= 0x372E38E0 endif # Hikey960 4G/6G versions have physical addresses above 4G range ifneq (,$(filter 4 6,$(CFG_DRAM_SIZE_GB))) $(call force,CFG_CORE_ARM64_PA_BITS,36) endif endif CFG_TZDRAM_START ?= 0x3F000000 CFG_TZDRAM_SIZE ?= 0x01000000 CFG_SHMEM_START ?= 0x3EE00000 CFG_SHMEM_SIZE ?= 0x00200000 CFG_TEE_RAM_VA_SIZE ?= 0x00200000 CFG_DRAM1_BASE ?= 0x40000000 CFG_IN_TREE_EARLY_TAS += avb/023f8f1a-292a-432b-8fc4-de8471358067 CFG_EMBED_DTB_SOURCE_FILE ?= hikey.dts optee_os-4.3.0/core/arch/arm/plat-hikey/hikey_peripherals.h000066400000000000000000000061071464416617300237260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2016, Linaro Ltd and Contributors. All rights reserved. * Copyright (c) 2016, Hisilicon Ltd and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __HIKEY_PERIPHERALS_H__ #define __HIKEY_PERIPHERALS_H__ #include #define PMUSSI_BASE 0xF8000000 #define PERI_BASE 0xF7030000 #define PMX0_BASE 0xF7010000 #define PMX1_BASE 0xF7010800 #define GPIO6_BASE 0xF7022000 #define SPI_BASE 0xF7106000 #define PMUSSI_REG_SIZE 0x1000 #define PERI_BASE_REG_SIZE 0x2000 #define PMX0_REG_SIZE 0x27c #define PMX1_REG_SIZE 0x28c /* register offsets */ #define PMUSSI_LDO21_REG_ADJ SHIFT_U32(0x86, 2) #define PMUSSI_ENA_LDO17_22 SHIFT_U32(0x2F, 2) #define PERI_SC_PERIPH_RSTDIS3 0x334 #define PERI_SC_PERIPH_RSTSTAT3 0x338 #define PERI_SC_PERIPH_CLKEN3 0x230 #define PERI_SC_PERIPH_CLKSTAT3 0x238 #define PMX0_IOMG104 0x1a0 #define PMX0_IOMG105 0x1a4 #define PMX0_IOMG106 0x1a8 #define PMX0_IOMG107 0x1ac #define PMX1_IOCG104 0x1b0 #define PMX1_IOCG105 0x1b4 #define PMX1_IOCG106 0x1b8 #define PMX1_IOCG107 0x1bc /* end register offsets */ #define PMUSSI_LDO21_REG_VL_MASK 0x7 #define PMUSSI_LDO21_REG_VL_1V8 0x3 #define PMUSSI_ENA_LDO21 BIT(4) #define PERI_RST3_SSP BIT(9) #define PERI_CLK3_SSP BIT(9) #define PINMUX_GPIO 0 #define PINMUX_SPI 1 #define PINCFG_NOPULL 0 #define PINCFG_PULLUP 1 #define PINCFG_PULLDN 2 #define GPIO6_2 50 #define SPI_CLK_HZ 150000000 /* 150mhz */ #define SPI_500_KHZ 500000 #define SPI_10_KHZ 10000 #ifdef CFG_SPI void spi_init(void); #ifdef CFG_SPI_TEST void spi_test(void); #endif /* CFG_SPI_TEST */ #endif /* CFG_SPI */ #endif /* __HIKEY_PERIPHERALS_H__ */ optee_os-4.3.0/core/arch/arm/plat-hikey/main.c000066400000000000000000000107541464416617300211410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #ifdef CFG_SPI #include #include #endif #if defined(PLATFORM_FLAVOR_hikey) #include #endif #include #include #include #include #include #include #include static struct pl011_data console_data __nex_bss; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE); #if defined(PLATFORM_FLAVOR_hikey) register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMUSSI_BASE, PMUSSI_REG_SIZE); #endif #if defined(CFG_SPI) && defined(PLATFORM_FLAVOR_hikey) register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PERI_BASE, PERI_BASE_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMX0_BASE, PMX0_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMX1_BASE, PMX1_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, GPIO6_BASE, PL061_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, SPI_BASE, PL022_REG_SIZE); #endif register_ddr(DRAM0_BASE, DRAM0_SIZE_NSEC); #ifdef DRAM1_SIZE_NSEC register_ddr(DRAM1_BASE, DRAM1_SIZE_NSEC); #endif #ifdef DRAM2_SIZE_NSEC register_ddr(DRAM2_BASE, DRAM2_SIZE_NSEC); #endif void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } #if defined(PLATFORM_FLAVOR_hikey) #ifdef CFG_SPI void spi_init(void) { uint32_t shifted_val, read_val; vaddr_t peri_base = core_mmu_get_va(PERI_BASE, MEM_AREA_IO_NSEC, PERI_BASE_REG_SIZE); vaddr_t pmx0_base = core_mmu_get_va(PMX0_BASE, MEM_AREA_IO_NSEC, PMX0_REG_SIZE); vaddr_t pmx1_base = core_mmu_get_va(PMX1_BASE, MEM_AREA_IO_NSEC, PMX1_REG_SIZE); DMSG("take SPI0 out of reset"); shifted_val = PERI_RST3_SSP; /* * no need to read PERI_SC_PERIPH_RSTDIS3 first * as all the bits are processed and cleared after writing */ io_write32(peri_base + PERI_SC_PERIPH_RSTDIS3, shifted_val); DMSG("PERI_SC_PERIPH_RSTDIS3: 0x%x", io_read32(peri_base + PERI_SC_PERIPH_RSTDIS3)); /* * wait until the requested device is out of reset * and ready to be used */ do { read_val = io_read32(peri_base + PERI_SC_PERIPH_RSTSTAT3); } while (read_val & shifted_val); DMSG("PERI_SC_PERIPH_RSTSTAT3: 0x%x", read_val); DMSG("enable SPI clock"); /* * no need to read PERI_SC_PERIPH_CLKEN3 first * as all the bits are processed and cleared after writing */ shifted_val = PERI_CLK3_SSP; io_write32(peri_base + PERI_SC_PERIPH_CLKEN3, shifted_val); DMSG("PERI_SC_PERIPH_CLKEN3: 0x%x", io_read32(peri_base + PERI_SC_PERIPH_CLKEN3)); DMSG("PERI_SC_PERIPH_CLKSTAT3: 0x%x", io_read32(peri_base + PERI_SC_PERIPH_CLKSTAT3)); /* * GPIO6_2 can be configured as PINMUX_GPIO, but as PINMUX_SPI, HW IP * will control the chip select pin so we don't have to manually do it. * The only concern is that the IP will pulse it between each packet, * which might not work with certain clients. There seems to be no * option to configure it to stay enabled for the total duration of the * transfer. * ref: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0194h/CJACFAFG.html */ DMSG("configure gpio6 pins 0-3 as SPI"); io_write32(pmx0_base + PMX0_IOMG104, PINMUX_SPI); io_write32(pmx0_base + PMX0_IOMG105, PINMUX_SPI); io_write32(pmx0_base + PMX0_IOMG106, PINMUX_SPI); io_write32(pmx0_base + PMX0_IOMG107, PINMUX_SPI); DMSG("configure gpio6 pins 0-3 as nopull"); io_write32(pmx1_base + PMX1_IOCG104, PINCFG_NOPULL); io_write32(pmx1_base + PMX1_IOCG105, PINCFG_NOPULL); io_write32(pmx1_base + PMX1_IOCG106, PINCFG_NOPULL); io_write32(pmx1_base + PMX1_IOCG107, PINCFG_NOPULL); #ifdef CFG_SPI_TEST spi_test(); #endif } #endif static TEE_Result peripherals_init(void) { vaddr_t pmussi_base = core_mmu_get_va(PMUSSI_BASE, MEM_AREA_IO_NSEC, PMUSSI_REG_SIZE); DMSG("enable LD021_1V8 source (pin 35) on LS connector"); /* * Mezzanine cards usually use this to source level shifters for * UART, GPIO, SPI, I2C, etc so if not enabled, connected * peripherals will not work either (during bootloader stage) * until linux is booted. */ io_mask8(pmussi_base + PMUSSI_LDO21_REG_ADJ, PMUSSI_LDO21_REG_VL_1V8, PMUSSI_LDO21_REG_VL_MASK); io_write8(pmussi_base + PMUSSI_ENA_LDO17_22, PMUSSI_ENA_LDO21); #ifdef CFG_SPI spi_init(); #endif return TEE_SUCCESS; } driver_init(peripherals_init); #endif /* PLATFORM_FLAVOR_hikey */ optee_os-4.3.0/core/arch/arm/plat-hikey/platform_config.h000066400000000000000000000117521464416617300233720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* PL011 UART */ #if defined(PLATFORM_FLAVOR_hikey) #define PL011_UART0_BASE 0xF8015000 #define PL011_UART2_BASE 0xF7112000 #define PL011_UART3_BASE 0xF7113000 #if (CFG_CONSOLE_UART == 3) #define CONSOLE_UART_BASE PL011_UART3_BASE #elif (CFG_CONSOLE_UART == 2) #define CONSOLE_UART_BASE PL011_UART2_BASE #elif (CFG_CONSOLE_UART == 0) #define CONSOLE_UART_BASE PL011_UART0_BASE #else #error Unknown console UART #endif #elif defined(PLATFORM_FLAVOR_hikey960) #define PL011_UART5_BASE 0xFDF05000 #define PL011_UART6_BASE 0xFFF32000 #if (CFG_CONSOLE_UART == 6) #define CONSOLE_UART_BASE PL011_UART6_BASE #elif (CFG_CONSOLE_UART == 5) #define CONSOLE_UART_BASE PL011_UART5_BASE #else #error Unknown console UART #endif #else /* PLATFORM_FLAVOR_hikey */ #error Unknown HiKey PLATFORM_FLAVOR #endif /* PLATFORM_FLAVOR_hikey */ #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 19200000 /* * HiKey and HiKey960 memory map * * Refer to the default configuration from conf.mk for description below. * * TZDRAM is secured (firewalled) by the DDR controller, see ARM-TF, but note * that security of this type of memory is weak for two reasons: * 1. It is prone to physical tampering since DRAM is external to the SoC * 2. It is still somewhat prone to software attacks because the memory * protection may be reverted by the non-secure kernel with a piece of * code similar to the one that sets the protection in ARM-TF (we're * missing a "lockdown" step which would prevent any change to the DDRC * configuration until the next SoC reset). * TZSRAM is emulated in the TZDRAM area, because the on-chip SRAM of the * HiKey SoC is too small to run OP-TEE (72K total with 64K available, see * "SRAM Memory Region Layout" in ARM-TF plat/hikey/include/hisi_sram_map.h), * while the SRAM of the HiKey960 SoC is not available to the public at the * moment. * * CFG_WITH_PAGER=n * * 0x4000_0000 - * TA RAM: 14 MiB | * 0x3F20_0000 | TZDRAM * TEE RAM: 2 MiB (TEE_RAM_VA_SIZE) | * 0x3F00_0000 [TZDRAM_BASE, BL32_LOAD_ADDR] - * Shared memory: 2 MiB | * 0x3EE0_0000 | DRAM0 * Reserved by UEFI for OP-TEE, unused | * 0x3EC0_0000 - * Secure Data Path buffers: 4 MiB | DRAM0 (secure) * 0x3E80_0000 [CFG_TEE_SDP_MEM_BASE] - * Reserved by UEFI for OP-TEE, unused | * 0x3E00_0000 | DRAM0 * Available to Linux | * 0x0000_0000 [DRAM0_BASE] - * * CFG_WITH_PAGER=y * * 0x4000_0000 - * TA RAM: 14 MiB | TZDRAM * 0x3F20_0000 - * Unused * 0x3F03_2000 - * TEE RAM: 200 KiB | TZSRAM * 0x3F00_0000 [TZSRAM_BASE, BL32_LOAD_ADDR] - * Shared memory: 2 MiB | * 0x3EE0_0000 | DRAM0 * Reserved by UEFI for OP-TEE, unused | * 0x3EC0_0000 - * Secure Data Path buffers: 4 MiB | DRAM0 (secure) * 0x3E80_0000 [CFG_TEE_SDP_MEM_BASE] - * Reserved by UEFI for OP-TEE, unused | * 0x3E00_0000 | DRAM0 * Available to Linux | * 0x0000_0000 [DRAM0_BASE] - */ #define DRAM0_BASE 0x00000000 /* DRAM0 exists below TZDRAM */ #define DRAM0_SIZE (CFG_TZDRAM_START - DRAM0_BASE) #define DRAM0_SIZE_NSEC 0x3E000000 #define DRAM1_BASE CFG_DRAM1_BASE #if defined(PLATFORM_FLAVOR_hikey) #if (CFG_DRAM_SIZE_GB == 2) #define DRAM1_SIZE_NSEC 0x40000000 #elif (CFG_DRAM_SIZE_GB == 1) /* do nothing */ #else #error Unknown DRAM size #endif #elif defined(PLATFORM_FLAVOR_hikey960) /* * Physical address ranges for HiKey960 RAM: * 3G board: 0~3G * 4G board: 0~3G 3~3.5G 8~8.5G * 6G board: 0~3G 4~7G */ #if (CFG_DRAM_SIZE_GB == 3) #define DRAM1_SIZE_NSEC 0x80000000 #elif (CFG_DRAM_SIZE_GB == 4) #define DRAM1_SIZE_NSEC (0xE0000000 - DRAM1_BASE) #define DRAM2_BASE 0x200000000 #define DRAM2_SIZE_NSEC 0x20000000 #elif (CFG_DRAM_SIZE_GB == 6) #define DRAM1_SIZE_NSEC 0x80000000 #define DRAM2_BASE 0x100000000 #define DRAM2_SIZE_NSEC 0xC0000000 #else #error Unknown DRAM size #endif #if (CFG_DRAM_SIZE_GB >= 4 && defined(CFG_ARM32_core) && \ defined(CFG_CORE_DYN_SHM) && !defined(CFG_LARGE_PHYS_ADDR)) #error 32-bit TEE with CFG_CORE_DYN_SHM and without CFG_LARGE_PHYS_ADDR \ cannot support boards with 4G RAM or more #endif #else /* PLATFORM_FLAVOR_hikey */ #error Unknown HiKey PLATFORM_FLAVOR #endif /* PLATFORM_FLAVOR_hikey */ #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-hikey/spi_test.c000066400000000000000000000153521464416617300220460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #include #include #include #define PL022_STAT 0x00C #define PL022_STAT_BSY SHIFT_U32(1, 4) static void spi_cs_callback(enum gpio_level value) { static bool inited; static struct pl061_data pd; vaddr_t gpio6_base = core_mmu_get_va(GPIO6_BASE, MEM_AREA_IO_NSEC, PL061_REG_SIZE); vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, PL022_REG_SIZE); if (!inited) { pl061_init(&pd); pl061_register(gpio6_base, 6); pl061_set_mode_control(GPIO6_2, PL061_MC_SW); pd.chip.ops->set_interrupt(NULL, GPIO6_2, GPIO_INTERRUPT_DISABLE); pd.chip.ops->set_direction(NULL, GPIO6_2, GPIO_DIR_OUT); inited = true; } if (io_read8(spi_base + PL022_STAT) & PL022_STAT_BSY) DMSG("pl022 busy - do NOT set CS!"); while (io_read8(spi_base + PL022_STAT) & PL022_STAT_BSY) ; DMSG("pl022 done - set CS!"); pd.chip.ops->set_value(NULL, GPIO6_2, value); } static void spi_set_cs_mux(uint32_t val) { uint32_t data; vaddr_t pmx0_base = core_mmu_get_va(PMX0_BASE, MEM_AREA_IO_NSEC, PMX0_REG_SIZE); if (val == PINMUX_SPI) { DMSG("Configure gpio6 pin2 as SPI"); io_write32(pmx0_base + PMX0_IOMG106, PINMUX_SPI); } else { DMSG("Configure gpio6 pin2 as GPIO"); io_write32(pmx0_base + PMX0_IOMG106, PINMUX_GPIO); } data = io_read32(pmx0_base + PMX0_IOMG106); if (data) DMSG("gpio6 pin2 is SPI"); else DMSG("gpio6 pin2 is GPIO"); } static void spi_test_with_manual_cs_control(void) { struct pl022_data pd; vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, PL022_REG_SIZE); uint8_t tx[3] = {0x01, 0x80, 0x00}; uint8_t rx[3] = {0}; size_t i, j, len = 3; enum spi_result res; spi_set_cs_mux(PINMUX_GPIO); DMSG("Set CS callback"); pd.cs_control = PL022_CS_CTRL_MANUAL; DMSG("spi_base: 0x%" PRIxVA, spi_base); DMSG("Configure SPI"); pd.base = spi_base; pd.clk_hz = SPI_CLK_HZ; pd.speed_hz = SPI_10_KHZ; pd.mode = SPI_MODE0; pd.data_size_bits = 8; pd.loopback = true; pl022_init(&pd); pd.chip.ops->configure(&pd.chip); pd.chip.ops->start(&pd.chip); /* * Pulse CS only once for the whole transmission. * This is the scheme used by the pl022 driver. */ spi_cs_callback(GPIO_LEVEL_HIGH); tee_time_busy_wait(2); spi_cs_callback(GPIO_LEVEL_LOW); for (j = 0; j < 10; j++) { DMSG("SPI test loop: %zu", j); res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); if (res) { EMSG("SPI transceive error %d", res); break; } for (i = 0; i < len; i++) DMSG("rx[%zu] = 0x%x", i, rx[i]); tee_time_busy_wait(20); } spi_cs_callback(GPIO_LEVEL_HIGH); /* Pulse CS once per transfer */ spi_cs_callback(GPIO_LEVEL_HIGH); tee_time_busy_wait(2); for (j = 10; j < 20; j++) { DMSG("SPI test loop: %zu", j); spi_cs_callback(GPIO_LEVEL_LOW); res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); if (res) { EMSG("SPI transceive error %d", res); break; } for (i = 0; i < len; i++) DMSG("rx[%zu] = 0x%x", i, rx[i]); tee_time_busy_wait(20); spi_cs_callback(GPIO_LEVEL_HIGH); } /* Pulse CS once per word/byte */ spi_set_cs_mux(PINMUX_SPI); tee_time_busy_wait(2); for (j = 20; j < 30; j++) { DMSG("SPI test loop: %zu", j); res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); if (res) { EMSG("SPI transceive error %d", res); break; } for (i = 0; i < len; i++) DMSG("rx[%zu] = 0x%x", i, rx[i]); tee_time_busy_wait(20); } pd.chip.ops->end(&pd.chip); } static void spi_test_with_registered_cs_cb(void) { struct pl022_data pd; vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, PL022_REG_SIZE); uint8_t tx[3] = {0x01, 0x80, 0x00}; uint8_t rx[3] = {0}; size_t i, j, len = 3; enum spi_result res; spi_set_cs_mux(PINMUX_GPIO); DMSG("Set CS callback"); pd.cs_data.cs_cb = spi_cs_callback; pd.cs_control = PL022_CS_CTRL_CB; DMSG("spi_base: 0x%" PRIxVA, spi_base); DMSG("Configure SPI"); pd.base = spi_base; pd.clk_hz = SPI_CLK_HZ; pd.speed_hz = SPI_10_KHZ; pd.mode = SPI_MODE0; pd.data_size_bits = 8; pd.loopback = true; pl022_init(&pd); pd.chip.ops->configure(&pd.chip); pd.chip.ops->start(&pd.chip); for (j = 0; j < 20; j++) { DMSG("SPI test loop: %zu", j); res = pd.chip.ops->txrx8(&pd.chip, tx, rx, len); if (res) { EMSG("SPI transceive error %d", res); break; } for (i = 0; i < len; i++) DMSG("rx[%zu] = 0x%x", i, rx[i]); tee_time_busy_wait(20); } pd.chip.ops->end(&pd.chip); } static void spi_test_with_builtin_cs_control(void) { struct pl061_data pd061; struct pl022_data pd022; vaddr_t gpio6_base = core_mmu_get_va(GPIO6_BASE, MEM_AREA_IO_NSEC, PL061_REG_SIZE); vaddr_t spi_base = core_mmu_get_va(SPI_BASE, MEM_AREA_IO_NSEC, PL022_REG_SIZE); uint8_t tx[3] = {0x01, 0x80, 0x00}; uint8_t rx[3] = {0}; size_t i, j, len = 3; enum spi_result res; spi_set_cs_mux(PINMUX_GPIO); DMSG("gpio6_base: 0x%" PRIxVA, gpio6_base); DMSG("Configure GPIO"); pl061_init(&pd061); pl061_register(gpio6_base, 6); DMSG("Enable software mode control for chip select"); pl061_set_mode_control(GPIO6_2, PL061_MC_SW); pd022.cs_data.gpio_data.chip = &pd061.chip; pd022.cs_data.gpio_data.pin_num = GPIO6_2; pd022.cs_control = PL022_CS_CTRL_AUTO_GPIO; DMSG("spi_base: 0x%" PRIxVA, spi_base); DMSG("Configure SPI"); pd022.base = spi_base; pd022.clk_hz = SPI_CLK_HZ; pd022.speed_hz = SPI_10_KHZ; pd022.mode = SPI_MODE0; pd022.data_size_bits = 8; pd022.loopback = true; pl022_init(&pd022); pd022.chip.ops->configure(&pd022.chip); pd022.chip.ops->start(&pd022.chip); for (j = 0; j < 20; j++) { DMSG("SPI test loop: %zu", j); res = pd022.chip.ops->txrx8(&pd022.chip, tx, rx, len); if (res) { EMSG("SPI transceive error %d", res); break; } for (i = 0; i < len; i++) DMSG("rx[%zu] = 0x%x", i, rx[i]); tee_time_busy_wait(20); } pd022.chip.ops->end(&pd022.chip); } /* * spi_init() MUST be run before calling this function! * * spi_test runs some loopback tests, so the SPI module will just receive * what is transmitted, i.e. 0x01, 0x80, 0x00. * * In non-loopback mode, the transmitted value will elicit a readback of * the measured value from the ADC chip on the Linksprite 96Boards * Mezzanine card [1], which can be connected to either a sliding * rheostat [2] or photoresistor [3]. * * [1] http://linksprite.com/wiki/index.php5?title=Linker_Mezzanine_card_for_96board * [2] http://learn.linksprite.com/96-board/sliding-rheostat * [3] http://learn.linksprite.com/96-board/photoresistor */ void spi_test(void) { spi_test_with_builtin_cs_control(); spi_test_with_registered_cs_cb(); spi_test_with_manual_cs_control(); } optee_os-4.3.0/core/arch/arm/plat-hikey/sub.mk000066400000000000000000000001601464416617300211610ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c ifeq ($(PLATFORM_FLAVOR),hikey) srcs-$(CFG_SPI_TEST) += spi_test.c endif optee_os-4.3.0/core/arch/arm/plat-hisilicon/000077500000000000000000000000001464416617300207125ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-hisilicon/conf.mk000066400000000000000000000034151464416617300221730ustar00rootroot00000000000000PLATFORM_FLAVOR ?= hi3519av100_demo hi3519av100-flavorlist = hi3519av100_demo hi3519av100_tst ifneq (,$(filter $(PLATFORM_FLAVOR),$(hi3519av100-flavorlist))) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_HI3519AV100,y) $(call force,CFG_TEE_CORE_NB_CORE,2) # Hi3519av100 has got two clusters, one core per cluster $(call force,CFG_CORE_CLUSTER_SHIFT,0) $(call force,CFG_PL011,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_ARM32_core,y) $(call force,CFG_PSCI_ARM32,y) CFG_BOOT_SECONDARY_REQUEST ?= y CFG_NUM_THREADS ?= 4 CFG_CRYPTO_WITH_CE ?= y CFG_NS_ENTRY_ADDR ?= 0x22008000 CFG_CORE_HEAP_SIZE ?= 131072 # # Hi3519av100 memory map # # This is a general memory map for demo board, and for your own board, # you have to define your own memory map. # # 0x4000_0000 [DRAM_LIMIT] # other (media memory zone/uboot and other) # # 0x3360_0000 - # TA RAM: 12 MiB | TZDRAM # 0x32a0_0000 - # # CFG_WITH_PAGER=n - # TEE RAM: 4 MiB (TEE_RAM_VA_SIZE) | TZDRAM # 0x3260_0000 [TZDRAM_BASE, TEE_LOAD_ADDR] - # # CFG_WITH_PAGER=y # Unused # 0x32607_0000 - # TEE RAM: 448 KiB (TZSRAM_SIZE) | TZSRAM # 0x3260_0000 [TZDRAM_BASE, TZSRAM_BASE, TEE_LOAD_ADDR] # OP-TEE Future Use: 2 MiB # 0x3240_0000 # Shared memory: 4 MB # 0x3200_0000 # Linux memory: 256MB # 0x2200_0000 # DSP reserved memory: 32MB # 0x2000_0000 [DRAM_BASE] # CFG_TZDRAM_START ?= 0x32600000 CFG_TZDRAM_SIZE ?= 0x01000000 CFG_TEE_RAM_VA_SIZE ?= 0x00400000 CFG_SHMEM_START ?= 0x32000000 CFG_SHMEM_SIZE ?= 0x00400000 else $(error Error: Not supported PLATFORM_FLAVOR or NULL PLATFORM_FLAVOR) endif optee_os-4.3.0/core/arch/arm/plat-hisilicon/hi3519av100.h000066400000000000000000000011431464416617300225540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. */ #ifndef __HI3519AV100_H__ #define __HI3519AV100_H__ #include /* PL011 */ #define PL011_UART0_BASE 0x04540000 #define PL011_BAUDRATE 115200 #define PL011_UART0_CLK_IN_HZ 24000000 /* BootSRAM */ #define BOOTSRAM_BASE 0x04200000 #define BOOTSRAM_SIZE 0x1000 /* CPU Reset Control */ #define CPU_CRG_BASE 0x04510000 #define CPU_CRG_SIZE 0x1000 /* Sysctrl Register */ #define SYS_CTRL_BASE 0x04520000 #define SYS_CTRL_SIZE 0x1000 #endif /* __HI3519AV100_H__ */ optee_os-4.3.0/core/arch/arm/plat-hisilicon/hi3519av100_plat_init.S000066400000000000000000000033201464416617300245710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. */ /* * Entry points for the Hi3519AV100 a53 aarch32 mode init. * It is assumed no stack is available when these routines are called. * It is assumed each routine is called with return address in LR * and with ARM registers R0, R1, R2, R3 being scratched. */ #include #include #include #include #define CCI_BASE 0x04528000 #define CPUECTLR_A53_SMPEN BIT(6) #define ACTRL_CPUECTLR BIT(1) #define HACTRL_CPUECTLR BIT(1) .section .text .balign 4 .code 32 /* * Hi3519AV100 a53 aarch32 configuration early configuration * * Use scratch registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* * Write the CPU Extended Control Register * Set the SMPEN bit, this Cortex-A53 core's register */ mrrc p15, 1, r0, r1, c15 orr r0, r0, #CPUECTLR_A53_SMPEN mcrr p15, 1, r0, r1, c15 /* * Enable Non-Secure EL1 write access to CPUECTLR */ mrs r1, cpsr cps #CPSR_MODE_MON read_scr r0 orr r0, r0, #SCR_NS /* Set NS bit in SCR */ write_scr r0 isb /* Write HACTLR register */ mrc p15, 4, r2, c1, c0, 1 orr r2, r2, #HACTRL_CPUECTLR mcr p15, 4, r2, c1, c0, 1 bic r0, r0, #SCR_NS /* Clr NS bit in SCR */ write_scr r0 isb /* Write ACTLR register */ mrc p15, 0, r2, c1, c0, 1 orr r2, r2, #ACTRL_CPUECTLR mcr p15, 0, r2, c1, c0, 1 msr cpsr, r1 /* * Enable cci for secondary core */ mov r3, lr bl __get_core_pos mov lr, r3 cmp r0, #0 beq out ldr r0, =CCI_BASE ldr r1, [r0] orr r1, r1, #BIT(9) /* bit 9 set to 1 */ str r1, [r0] out: bx lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-hisilicon/main.c000066400000000000000000000015461464416617300220100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. */ #include #include #include #include #include #include #include #include static struct pl011_data console_data; register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE); #ifdef BOOTSRAM_BASE register_phys_mem(MEM_AREA_IO_SEC, BOOTSRAM_BASE, BOOTSRAM_SIZE); #endif #ifdef CPU_CRG_BASE register_phys_mem(MEM_AREA_IO_SEC, CPU_CRG_BASE, CPU_CRG_SIZE); #endif #ifdef SYS_CTRL_BASE register_phys_mem(MEM_AREA_IO_SEC, SYS_CTRL_BASE, SYS_CTRL_SIZE); #endif void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-hisilicon/platform_config.h000066400000000000000000000007051464416617300242360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* PL011 UART */ #define CONSOLE_UART_BASE PL011_UART0_BASE #define CONSOLE_BAUDRATE PL011_BAUDRATE #define CONSOLE_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-hisilicon/psci.c000066400000000000000000000041541464416617300220200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, HiSilicon Technologies Co., Ltd. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define REG_CPU_SUSSYS_RESET 0xcc #define REG_CPU_START_COMMAND 0x0 #define REG_CPU_START_ADDR 0x4 #define REG_SYSCTRL_RESET 0x4 #define RELEASE_CORE_MASK (BIT32(25) | BIT32(1)) int psci_features(uint32_t psci_fid) { switch (psci_fid) { case ARM_SMCCC_VERSION: case PSCI_PSCI_FEATURES: case PSCI_VERSION: case PSCI_SYSTEM_RESET: #ifdef CFG_BOOT_SECONDARY_REQUEST case PSCI_CPU_ON: #endif return PSCI_RET_SUCCESS; default: return PSCI_RET_NOT_SUPPORTED; } } uint32_t psci_version(void) { return PSCI_VERSION_1_0; } void psci_system_reset(void) { vaddr_t sysctrl = core_mmu_get_va(SYS_CTRL_BASE, MEM_AREA_IO_SEC, SYS_CTRL_SIZE); if (!sysctrl) { EMSG("no sysctrl mapping, hang here"); panic(); } io_write32(sysctrl + REG_SYSCTRL_RESET, 0xdeadbeef); } #ifdef CFG_BOOT_SECONDARY_REQUEST int psci_cpu_on(uint32_t core_idx, uint32_t entry, uint32_t context_id) { uint32_t val = 0; size_t pos = get_core_pos_mpidr(core_idx); vaddr_t bootsram = core_mmu_get_va(BOOTSRAM_BASE, MEM_AREA_IO_SEC, BOOTSRAM_SIZE); vaddr_t crg = core_mmu_get_va(CPU_CRG_BASE, MEM_AREA_IO_SEC, CPU_CRG_SIZE); if (!bootsram || !crg) { EMSG("No bootsram or crg mapping"); return PSCI_RET_INVALID_PARAMETERS; } if ((pos == 0) || (pos >= CFG_TEE_CORE_NB_CORE)) return PSCI_RET_INVALID_PARAMETERS; /* set secondary core's NS entry addresses */ boot_set_core_ns_entry(pos, entry, context_id); val = virt_to_phys((void *)TEE_LOAD_ADDR); io_write32(bootsram + REG_CPU_START_ADDR, val); io_write32(bootsram + REG_CPU_START_COMMAND, 0xe51ff004); /* release secondary core */ io_clrbits32(crg + REG_CPU_SUSSYS_RESET, RELEASE_CORE_MASK); return PSCI_RET_SUCCESS; } #endif optee_os-4.3.0/core/arch/arm/plat-hisilicon/sub.mk000066400000000000000000000001731464416617300220350ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-$(CFG_HI3519AV100) += hi3519av100_plat_init.S srcs-$(CFG_PSCI_ARM32) += psci.c optee_os-4.3.0/core/arch/arm/plat-imx/000077500000000000000000000000001464416617300175265ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-imx/a7_plat_init.S000066400000000000000000000025661464416617300222350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Peng Fan */ /* * Entry points for the A7 init. * It is assume no stack is available when these routines are called. * It is assume each routine is called with return address in LR * and with ARM registers R0, R1, R2, R3 being scratchable. */ #include #include #include #include #include .section .text .balign 4 .code 32 /* * Cortex A7 configuration early configuration * * Use scratables registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* * DDI: Disable dual issue [bit28=0] * DDVM: Disable Distributed Virtual Memory transactions [bit15=0] * L1PCTL: L1 Data prefetch control [bit14:13=2b11] * L1RADIS: L1 Data Cache read-allocate mode disable [bit12=0] * L2RADIS: L2 Data Cache read-allocate mode disable [bit11=0] * DODMBS: Disable optimized data memory barrier behavior [bit10=0] * SMP: Enables coherent requests to the processor [bit6=0] */ mov_imm r0, 0x00006040 write_actlr r0 mov_imm r0, 0x00040C00 write_nsacr r0 bx lr END_FUNC plat_cpu_reset_early FUNC get_core_pos_mpidr , : /* Drop ClusterId. There is no SoCs with more than 4 A7 Cores. */ and r0, r0, #MPIDR_CPU_MASK bx lr END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-imx/a9_plat_init.S000066400000000000000000000110521464416617300222250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * Copyright 2019 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Entry points for the A9 inits, A9 revision specific or not. * It is assume no stack is available when these routines are called. * It is assume each routine is called with return address in LR * and with ARM registers R0, R1, R2, R3 being scratchable. */ #include #include #include #include #include #include .section .text .balign 4 .code 32 /* * Cortex A9 early configuration * * Use registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* * Under very rare timing circumstances, transition into streaming * mode might create a data corruption * Configurations affected * This erratum affects configurations with either: * - One processor if the ACP is present * - Two or more processors * This erratum can be worked round by setting bit[22] of the * undocumented Diagnostic Control Register to 1. This * register is encoded as CP15 c15 0 c0 1. * The bit can be written in Secure state only, with the following * Read/Modify/Write code sequence: * MRC p15,0,rt,c15,c0,1 * ORR rt,rt,#0x00400000 * MCR p15,0,rt,c15,c0,1 * When this bit is set, the processor is unable to switch into * Read-Allocate (streaming) mode, which means this erratum cannot * occur. Setting this bit could possibly result in a visible drop * in performance for routines that perform intensive memory * accesses, such as memset() or memcpy(). However, the workaround * is not expected to create any significant performance degradation * in most standard applications. */ #if defined(CFG_MX6QP) || defined(CFG_MX6Q) || defined(CFG_MX6D) || \ defined(CFG_MX6DL) read_diag r0 orr r0, r0, #1 << 22 write_diag r0 #endif /* * Disallow NSec to mask FIQ [bit4: FW=0] * Allow NSec to manage Imprecise Abort [bit5: AW=1] * Imprecise Abort trapped to Abort Mode [bit3: EA=0] * In Sec world, FIQ trapped to FIQ Mode [bit2: FIQ=0] * IRQ always trapped to IRQ Mode [bit1: IRQ=0] * Secure World [bit0: NS=0] */ mov r0, #SCR_AW write_scr r0 /* * Mandated HW config loaded * * SCTLR = 0x00004000 * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) * * ACTRL = 0x000000[46(i.MX6SLL),47] * - core always in full SMP (FW bit0=[0(i.MX6SLL),1], SMP bit6=1) * - L2 write full line of zero disabled (bit3=0) * (keep WFLZ low. Will be set once outer L2 is ready) * - L1 Prefetch enable (bit2=1) * - L2 Prefetch hint enable (bit1=1) * * NSACR = 0x00020C00 * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) * - Nsec can lockdown TLB (TL bit17=1) * - NSec cannot access PLE (PLE bit16=0) * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) * * PCR * - no change latency, enable clk gating */ mov_imm r0, 0x00004000 write_sctlr r0 #ifdef CFG_MX6SLL mov_imm r0, 0x00000046 #else mov_imm r0, 0x00000047 #endif write_actlr r0 mov_imm r0, 0x00020C00 write_nsacr r0 read_pcr r0 orr r0, r0, #0x1 write_pcr r0 mov pc, lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-imx/conf.mk000066400000000000000000000321741464416617300210130ustar00rootroot00000000000000PLATFORM_FLAVOR ?= mx6ulevk # Get SoC associated with the PLATFORM_FLAVOR mx6ul-flavorlist = \ mx6ulevk \ mx6ul9x9evk \ mx6ulccimx6ulsbcpro \ mx6ulccbv2 \ mx6ull-flavorlist = \ mx6ullevk \ mx6ulzevk \ mx6q-flavorlist = \ mx6qsabrelite \ mx6qsabreauto \ mx6qsabresd \ mx6qhmbedge \ mx6qapalis \ mx6qp-flavorlist = \ mx6qpsabreauto \ mx6qpsabresd \ mx6sl-flavorlist = \ mx6slevk mx6sll-flavorlist = \ mx6sllevk mx6sx-flavorlist = \ mx6sxsabreauto \ mx6sxsabresd \ mx6sxudooneofull \ mx6d-flavorlist = \ mx6dhmbedge \ mx6dapalis \ mx6dl-flavorlist = \ mx6dlsabreauto \ mx6dlsabresd \ mx6dlhmbedge \ mx6s-flavorlist = \ mx6shmbedge \ mx6solosabresd \ mx6solosabreauto \ mx7d-flavorlist = \ mx7dsabresd \ mx7dpico_mbl \ mx7dclsom \ mx7s-flavorlist = \ mx7swarp7 \ mx7swarp7_mbl \ mx7ulp-flavorlist = \ mx7ulpevk mx8mq-flavorlist = \ mx8mqevk mx8mm-flavorlist = \ mx8mmevk \ mx8mm_cl_iot_gate mx8mn-flavorlist = \ mx8mnevk mx8mp-flavorlist = \ mx8mpevk \ mx8mp_rsb3720_6g mx8qm-flavorlist = \ mx8qmmek \ mx8qx-flavorlist = \ mx8qxpmek \ mx8dxmek \ mx8dxl-flavorlist = \ mx8dxlevk \ mx8ulp-flavorlist = \ mx8ulpevk \ mx93-flavorlist = \ mx93evk \ ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ul-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6UL,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_TZC380,y) include core/arch/arm/cpu/cortex-a7.mk else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ull-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6ULL,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_TZC380,y) $(call force,CFG_IMX_CAAM,n) $(call force,CFG_NXP_CAAM,n) $(call force,CFG_IMX_DCP,y) include core/arch/arm/cpu/cortex-a7.mk else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6q-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6Q,y) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_TZC380,y) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6qp-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6QP,y) $(call force,CFG_TEE_CORE_NB_CORE,4) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6d-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6D,y) $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_TZC380,y) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6dl-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6DL,y) $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_TZC380,y) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6s-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6S,y) $(call force,CFG_TEE_CORE_NB_CORE,1) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6sl-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6SL,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_IMX_CAAM,n) $(call force,CFG_NXP_CAAM,n) $(call force,CFG_IMX_DCP,y) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6sll-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6SLL,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_IMX_CAAM,n) $(call force,CFG_NXP_CAAM,n) $(call force,CFG_IMX_DCP,y) $(call force,CFG_NO_SMP,y) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6sx-flavorlist))) $(call force,CFG_MX6,y) $(call force,CFG_MX6SX,y) $(call force,CFG_TEE_CORE_NB_CORE,1) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7s-flavorlist))) $(call force,CFG_MX7,y) $(call force,CFG_TEE_CORE_NB_CORE,1) include core/arch/arm/cpu/cortex-a7.mk else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7d-flavorlist))) $(call force,CFG_MX7,y) $(call force,CFG_TEE_CORE_NB_CORE,2) include core/arch/arm/cpu/cortex-a7.mk else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7ulp-flavorlist))) $(call force,CFG_MX7ULP,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_TZC380,n) $(call force,CFG_IMX_CSU,n) include core/arch/arm/cpu/cortex-a7.mk else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mq-flavorlist))) $(call force,CFG_MX8MQ,y) $(call force,CFG_MX8M,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_TZC380,y) CFG_DRAM_BASE ?= 0x40000000 CFG_TEE_CORE_NB_CORE ?= 4 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mm-flavorlist))) $(call force,CFG_MX8MM,y) $(call force,CFG_MX8M,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_TZC380,y) CFG_DRAM_BASE ?= 0x40000000 CFG_TEE_CORE_NB_CORE ?= 4 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mn-flavorlist))) $(call force,CFG_MX8MN,y) $(call force,CFG_MX8M,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_TZC380,y) CFG_DRAM_BASE ?= 0x40000000 CFG_TEE_CORE_NB_CORE ?= 4 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mp-flavorlist))) $(call force,CFG_MX8MP,y) $(call force,CFG_MX8M,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_TZC380,y) CFG_DRAM_BASE ?= 0x40000000 CFG_TEE_CORE_NB_CORE ?= 4 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qm-flavorlist))) $(call force,CFG_MX8QM,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_IMX_SNVS,n) CFG_IMX_LPUART ?= y CFG_DRAM_BASE ?= 0x80000000 CFG_TEE_CORE_NB_CORE ?= 6 $(call force,CFG_IMX_OCOTP,n) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qx-flavorlist))) $(call force,CFG_MX8QX,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_IMX_SNVS,n) CFG_IMX_LPUART ?= y CFG_DRAM_BASE ?= 0x80000000 CFG_TEE_CORE_NB_CORE ?= 4 $(call force,CFG_IMX_OCOTP,n) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8dxl-flavorlist))) $(call force,CFG_MX8DXL,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_IMX_SNVS,n) CFG_IMX_LPUART ?= y CFG_DRAM_BASE ?= 0x80000000 $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_IMX_OCOTP,n) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist))) $(call force,CFG_MX8ULP,y) $(call force,CFG_ARM64_core,y) CFG_IMX_LPUART ?= y CFG_DRAM_BASE ?= 0x80000000 CFG_TEE_CORE_NB_CORE ?= 2 $(call force,CFG_NXP_SNVS,n) $(call force,CFG_IMX_OCOTP,n) CFG_IMX_MU ?= y CFG_IMX_ELE ?= n else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx93-flavorlist))) $(call force,CFG_MX93,y) $(call force,CFG_ARM64_core,y) CFG_IMX_LPUART ?= y CFG_DRAM_BASE ?= 0x80000000 CFG_TEE_CORE_NB_CORE ?= 2 $(call force,CFG_NXP_SNVS,n) $(call force,CFG_IMX_OCOTP,n) $(call force,CFG_TZC380,n) $(call force,CFG_CRYPTO_DRIVER,n) $(call force,CFG_NXP_CAAM,n) CFG_IMX_MU ?= y CFG_IMX_ELE ?= n else $(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dsabresd)) CFG_DDR_SIZE ?= 0x40000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 CFG_IMX_WDOG_EXT_RESET ?= y endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dclsom)) CFG_DDR_SIZE ?= 0x40000000 CFG_UART_BASE ?= UART1_BASE CFG_IMX_WDOG_EXT_RESET ?= y endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dpico_mbl)) CFG_DDR_SIZE ?= 0x20000000 CFG_NS_ENTRY_ADDR ?= 0x87800000 CFG_DT_ADDR ?= 0x83100000 CFG_UART_BASE ?= UART5_BASE CFG_BOOT_SECONDARY_REQUEST ?= n CFG_EXTERNAL_DTB_OVERLAY ?= y CFG_IMX_WDOG_EXT_RESET ?= y endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx7swarp7)) CFG_DDR_SIZE ?= 0x20000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 CFG_BOOT_SECONDARY_REQUEST ?= n endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx7swarp7_mbl)) CFG_DDR_SIZE ?= 0x20000000 CFG_NS_ENTRY_ADDR ?= 0x87800000 CFG_DT_ADDR ?= 0x83100000 CFG_BOOT_SECONDARY_REQUEST ?= n CFG_EXTERNAL_DTB_OVERLAY = y CFG_IMX_WDOG_EXT_RESET = y endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx7ulpevk)) CFG_DDR_SIZE ?= 0x40000000 CFG_NS_ENTRY_ADDR ?= 0x60800000 CFG_UART_BASE ?= UART4_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qpsabresd mx6qsabresd mx6dlsabresd \ mx6dlsabrelite mx6dhmbedge mx6dlhmbedge mx6solosabresd \ mx6dapalis mx6qapalis)) CFG_DDR_SIZE ?= 0x40000000 CFG_NS_ENTRY_ADDR ?= 0x12000000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qpsabreauto mx6qsabreauto \ mx6dlsabreauto mx6solosabreauto)) CFG_DDR_SIZE ?= 0x80000000 CFG_NS_ENTRY_ADDR ?= 0x12000000 CFG_UART_BASE ?= UART4_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qhmbedge)) CFG_DDR_SIZE ?= 0x80000000 CFG_UART_BASE ?= UART1_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6shmbedge)) CFG_DDR_SIZE ?= 0x40000000 CFG_NS_ENTRY_ADDR ?= 0x12000000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6qsabrelite mx6dlsabrelite)) CFG_DDR_SIZE ?= 0x40000000 CFG_NS_ENTRY_ADDR ?= 0x12000000 CFG_UART_BASE ?= UART2_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6slevk)) CFG_NS_ENTRY_ADDR ?= 0x80800000 CFG_DDR_SIZE ?= 0x40000000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6sllevk)) CFG_NS_ENTRY_ADDR ?= 0x80800000 CFG_DDR_SIZE ?= 0x80000000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6sxsabreauto)) CFG_DDR_SIZE ?= 0x80000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6sxsabresd)) CFG_DDR_SIZE ?= 0x40000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 endif ifeq ($(PLATFORM_FLAVOR), mx6sxudooneofull) CFG_DDR_SIZE ?= 0x40000000 CFG_UART_BASE ?= UART1_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ulevk mx6ullevk mx6ulzevk)) CFG_DDR_SIZE ?= 0x20000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ulccimx6ulsbcpro)) CFG_DDR_SIZE ?= 0x10000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 CFG_UART_BASE ?= UART5_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ul9x9evk)) CFG_DDR_SIZE ?= 0x10000000 CFG_NS_ENTRY_ADDR ?= 0x80800000 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx6ulccbv2)) CFG_DDR_SIZE ?= 0x10000000 CFG_UART_BASE ?= UART7_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mqevk)) CFG_DDR_SIZE ?= 0xc0000000 CFG_UART_BASE ?= UART1_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mmevk)) CFG_DDR_SIZE ?= 0x80000000 CFG_UART_BASE ?= UART2_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mm_cl_iot_gate)) CFG_DDR_SIZE ?= 0x40000000 CFG_UART_BASE ?= UART3_BASE CFG_NSEC_DDR_1_BASE ?= 0x80000000UL CFG_NSEC_DDR_1_SIZE ?= 0x40000000UL endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mnevk)) CFG_DDR_SIZE ?= 0x80000000 CFG_UART_BASE ?= UART2_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mpevk)) CFG_DDR_SIZE ?= UL(0x180000000) CFG_UART_BASE ?= UART2_BASE $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mp_rsb3720_6g)) CFG_DDR_SIZE ?= UL(0x180000000) CFG_UART_BASE ?= UART3_BASE CFG_TZDRAM_START ?= 0x56000000 $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8qxpmek mx8qmmek)) CFG_DDR_SIZE ?= 0x80000000 CFG_UART_BASE ?= UART0_BASE CFG_NSEC_DDR_1_BASE ?= 0x880000000UL CFG_NSEC_DDR_1_SIZE ?= 0x380000000UL CFG_CORE_ARM64_PA_BITS ?= 40 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxmek)) CFG_DDR_SIZE ?= 0x40000000 CFG_UART_BASE ?= UART0_BASE $(call force,CFG_MX8DX,y) endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8dxlevk)) CFG_DDR_SIZE ?= 0x40000000 CFG_UART_BASE ?= UART0_BASE CFG_NSEC_DDR_1_BASE ?= 0x800000000UL CFG_NSEC_DDR_1_SIZE ?= 0x400000000UL CFG_CORE_ARM64_PA_BITS ?= 40 endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx8ulpevk)) CFG_DDR_SIZE ?= 0x80000000 CFG_UART_BASE ?= UART5_BASE endif ifneq (,$(filter $(PLATFORM_FLAVOR),mx93evk)) CFG_DDR_SIZE ?= 0x80000000 CFG_UART_BASE ?= UART1_BASE endif # i.MX6 Solo/SL/SoloX/DualLite/Dual/Quad specific config ifeq ($(filter y, $(CFG_MX6QP) $(CFG_MX6Q) $(CFG_MX6D) $(CFG_MX6DL) $(CFG_MX6S) \ $(CFG_MX6SL) $(CFG_MX6SLL) $(CFG_MX6SX)), y) include core/arch/arm/cpu/cortex-a9.mk $(call force,CFG_PL310,y) CFG_PL310_LOCKED ?= y CFG_ENABLE_SCTLR_RR ?= y CFG_IMX_SCU ?= y endif ifeq ($(filter y, $(CFG_MX6QP) $(CFG_MX6Q) $(CFG_MX6D) $(CFG_MX6DL) $(CFG_MX6S)), y) CFG_DRAM_BASE ?= 0x10000000 endif ifneq (,$(filter y, $(CFG_MX6UL) $(CFG_MX6ULL) $(CFG_MX6SL) $(CFG_MX6SLL) \ $(CFG_MX6SX))) CFG_DRAM_BASE ?= 0x80000000 endif ifeq ($(filter y, $(CFG_MX7)), y) CFG_INIT_CNTVOFF ?= y CFG_DRAM_BASE ?= 0x80000000 endif ifeq ($(filter y, $(CFG_MX7ULP)), y) CFG_INIT_CNTVOFF ?= y CFG_DRAM_BASE ?= UL(0x60000000) $(call force,CFG_IMX_LPUART,y) $(call force,CFG_BOOT_SECONDARY_REQUEST,n) endif ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP))) $(call force,CFG_GIC,y) CFG_BOOT_SECONDARY_REQUEST ?= y CFG_DT ?= y CFG_DTB_MAX_SIZE ?= 0x20000 CFG_PAGEABLE_ADDR ?= 0 CFG_PSCI_ARM32 ?= y CFG_SECURE_TIME_SOURCE_REE ?= y CFG_UART_BASE ?= UART1_BASE endif ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX8M))) $(call force,CFG_IMX_UART,y) CFG_IMX_SNVS ?= y endif ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7))) CFG_IMX_CSU ?= y endif ifeq ($(filter y, $(CFG_PSCI_ARM32)), y) CFG_HWSUPP_MEM_PERM_WXN = n CFG_IMX_WDOG ?= y endif ifeq ($(CFG_ARM64_core),y) # arm-v8 platforms include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) CFG_CRYPTO_WITH_CE ?= y supported-ta-targets = ta_arm64 endif CFG_TZDRAM_SIZE ?= 0x01e00000 CFG_SHMEM_SIZE ?= 0x00200000 CFG_TZDRAM_START ?= ($(CFG_DRAM_BASE) - $(CFG_TZDRAM_SIZE) - $(CFG_SHMEM_SIZE) + $(CFG_DDR_SIZE)) CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) # Enable embedded tests by default CFG_ENABLE_EMBEDDED_TESTS ?= y # Set default heap size for imx platforms to 128k CFG_CORE_HEAP_SIZE ?= 131072 CFG_CRYPTO_SIZE_OPTIMIZATION ?= n CFG_MMAP_REGIONS ?= 24 # SE05X and OCOTP both implement tee_otp_get_die_id() ifeq ($(CFG_NXP_SE05X),y) $(call force,CFG_IMX_OCOTP,n) endif CFG_IMX_OCOTP ?= y CFG_IMX_DIGPROG ?= y CFG_PKCS11_TA ?= y # Almost all platforms include CAAM HW Modules, except the # ones forced to be disabled CFG_NXP_CAAM ?= n ifeq ($(CFG_NXP_CAAM),y) ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX) $(CFG_MX8DXL)), y) CFG_IMX_SC ?= y CFG_IMX_MU ?= y endif else ifneq (,$(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP))) CFG_IMX_CAAM ?= y endif endif optee_os-4.3.0/core/arch/arm/plat-imx/config/000077500000000000000000000000001464416617300207735ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-imx/config/imx6qdlsolo.h000066400000000000000000000075321464416617300234340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * Copyright 2017-2019 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef CONFIG_IMX6QDLSOLO_H #define CONFIG_IMX6QDLSOLO_H /* * PL310 TAG RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_TAG_RAM_CTRL_INIT #define PL310_TAG_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 DATA RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_DATA_RAM_CTRL_INIT #define PL310_DATA_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 Auxiliary Control Register */ #ifndef PL310_AUX_CTRL_INIT #if defined(CFG_MX6QP) || defined(CFG_MX6Q) || defined(CFG_MX6D) /* * Early BRESP enabled (bit30=1) * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=1) * Force write allocated (default) (bit24:23=00) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * 64kb way size (bit19:17=3b011) * 16-way associativity (bit16=1) * Store buffer device limitation disabled (bit11=0) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) enabled (bit0=1) */ #define PL310_AUX_CTRL_INIT 0x7E470001 #else /* * Early BRESP enabled (bit30=0) * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=0) * Force write allocated (default) (bit24:23=00) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * 32kb way size (bit19:17=3b010) * 8-way associativity (bit16=0) * Store buffer device limitation enabled (bit11=1) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) disabled (bit0=0) */ #define PL310_AUX_CTRL_INIT 0x3C440800 #endif #endif /* * PL310 Prefetch Control Register * * Double linefill enabled (bit30=1) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop disabled (bit24=0) * Incr double linefill disable (bit23=0) * Prefetch offset = 0xF (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x7000000F /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 #endif optee_os-4.3.0/core/arch/arm/plat-imx/config/imx6sl.h000066400000000000000000000034001464416617300223630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef _CONFIG_IMX6SL_H #define _CONFIG_IMX6SL_H /* * PL310 TAG RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_TAG_RAM_CTRL_INIT #define PL310_TAG_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 DATA RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_DATA_RAM_CTRL_INIT #define PL310_DATA_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 Auxiliary Control Register * * Early BRESP enabled (bit30=1) * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=1) * Force write allocated (default) (bit24:23=00) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * 16kb way size (bit19:17=3b001) * 16-way associativity (bit16=1) * Store buffer device limitation enabled (bit11=0) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) enabled (bit0=1) */ #ifndef PL310_AUX_CTRL_INIT #define PL310_AUX_CTRL_INIT 0x7E430001 #endif /* * PL310 Prefetch Control Register * * Double linefill enabled (bit30=1) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop disabled (bit24=0) * Incr double linefill disable (bit23=0) * Prefetch offset = 0xF (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x7000000F /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 #endif optee_os-4.3.0/core/arch/arm/plat-imx/config/imx6sll.h000066400000000000000000000034021464416617300225410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef _CONFIG_IMX6SLL_H #define _CONFIG_IMX6SLL_H /* * PL310 TAG RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_TAG_RAM_CTRL_INIT #define PL310_TAG_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 DATA RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_DATA_RAM_CTRL_INIT #define PL310_DATA_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 Auxiliary Control Register * * Early BRESP enabled (bit30=1) * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=1) * Force write allocated (default) (bit24:23=00) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * 16kb way size (bit19:17=3b001) * 16-way associativity (bit16=1) * Store buffer device limitation enabled (bit11=0) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) enabled (bit0=1) */ #ifndef PL310_AUX_CTRL_INIT #define PL310_AUX_CTRL_INIT 0x7E430001 #endif /* * PL310 Prefetch Control Register * * Double linefill enabled (bit30=1) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop disabled (bit24=0) * Incr double linefill disable (bit23=0) * Prefetch offset = 0xF (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x7000000F /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 #endif optee_os-4.3.0/core/arch/arm/plat-imx/config/imx6sx.h000066400000000000000000000034441464416617300224070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Peng Fan */ #ifndef __CONFIG_IMX6SX_H #define __CONFIG_IMX6SX_H /* * PL310 TAG RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_TAG_RAM_CTRL_INIT #define PL310_TAG_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 DATA RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:3 - 4 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_DATA_RAM_CTRL_INIT #define PL310_DATA_RAM_CTRL_INIT 0x00000132 #endif /* * PL310 Auxiliary Control Register * * Early BRESP enabled (bit30=1) * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=1) * Force write allocated (default) (bit24:23=00) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * 16kb way size (bit19:17=3b001) * 16-way associativity (bit16=1) * Store buffer device limitation enabled (bit11=0) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) enabled (bit0=1) */ #ifndef PL310_AUX_CTRL_INIT #define PL310_AUX_CTRL_INIT 0x7E430001 #endif /* * PL310 Prefetch Control Register * * Double linefill enabled (bit30=1) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop disabled (bit24=0) * Incr double linefill disable (bit23=0) * Prefetch offset = 0xF (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x7000000F /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 #endif optee_os-4.3.0/core/arch/arm/plat-imx/imx-common.c000066400000000000000000000073551464416617300217670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * Copyright 2017-2019, 2021 NXP * * Peng Fan */ #include #include #include #include #include #include #include #define SOC_TYPE(reg) (((reg) & (0x00FF0000)) >> 16) #define SOC_REV_MAJOR(reg) (((reg) & (0x0000FF00)) >> 8) #define SOC_REV_MINOR(reg) ((reg) & (0x0000000F)) #define SOC_REV_MINOR_MX7(reg) ((reg) & (0x000000FF)) static uint32_t imx_digprog; #ifdef ANATOP_BASE uint32_t imx_get_digprog(void) { vaddr_t addr = 0; if (imx_digprog) return imx_digprog; addr = core_mmu_get_va(ANATOP_BASE, MEM_AREA_IO_SEC, 0x1000); if (!addr) return 0; imx_digprog = io_read32(addr + DIGPROG_OFFSET); #ifdef CFG_MX8MQ /* * On the i.MX8MQ, the minor revision number must be updated to make * the difference between B0 chip and the newer chips. */ addr = core_mmu_get_va(OCOTP_BASE, MEM_AREA_IO_SEC, OCOTP_SIZE); if (!addr) return 0; if (io_read32(addr + OCOTP_SW_INFO_B1) == OCOTP_SW_MAGIC_B1) imx_digprog |= BIT32(0); #endif /* CFG_MX8MQ */ return imx_digprog; } #else /* ANATOP_BASE */ uint32_t imx_get_digprog(void) { if (imx_digprog) return imx_digprog; if (IS_ENABLED(CFG_MX7ULP)) imx_digprog = SOC_MX7ULP << 16; else if (IS_ENABLED(CFG_MX8QX)) imx_digprog = SOC_MX8QX << 16; else if (IS_ENABLED(CFG_MX8QM)) imx_digprog = SOC_MX8QM << 16; else if (IS_ENABLED(CFG_MX8DXL)) imx_digprog = SOC_MX8DXL << 16; else if (IS_ENABLED(CFG_MX8ULP)) imx_digprog = SOC_MX8ULP << 16; else if (IS_ENABLED(CFG_MX93)) imx_digprog = SOC_MX93 << 16; return imx_digprog; } #endif /* ANATOP_BASE */ uint32_t imx_soc_rev_major(void) { if (imx_digprog == 0) imx_get_digprog(); return SOC_REV_MAJOR(imx_digprog); } uint32_t imx_soc_rev_minor(void) { if (imx_digprog == 0) imx_get_digprog(); if (IS_ENABLED(CFG_MX7)) return SOC_REV_MINOR_MX7(imx_digprog); else return SOC_REV_MINOR(imx_digprog); } uint32_t imx_soc_type(void) { if (imx_digprog == 0) imx_get_digprog(); return SOC_TYPE(imx_digprog); } bool soc_is_imx6sl(void) { return imx_soc_type() == SOC_MX6SL; } bool soc_is_imx6sll(void) { return imx_soc_type() == SOC_MX6SLL; } bool soc_is_imx6sx(void) { return imx_soc_type() == SOC_MX6SX; } bool soc_is_imx6ul(void) { return imx_soc_type() == SOC_MX6UL; } bool soc_is_imx6ull(void) { return imx_soc_type() == SOC_MX6ULL; } bool soc_is_imx6sdl(void) { return imx_soc_type() == SOC_MX6DL; } bool soc_is_imx6dq(void) { return (imx_soc_type() == SOC_MX6Q) && (imx_soc_rev_major() == 0); } bool soc_is_imx6dqp(void) { return (imx_soc_type() == SOC_MX6Q) && (imx_soc_rev_major() == 1); } bool soc_is_imx6(void) { uint32_t soc = imx_soc_type(); return (soc == SOC_MX6SLL) || (soc == SOC_MX6SL) || (soc == SOC_MX6D) || (soc == SOC_MX6SX) || (soc == SOC_MX6UL) || (soc == SOC_MX6ULL) || (soc == SOC_MX6DL) || (soc == SOC_MX6Q); } bool soc_is_imx7ds(void) { return imx_soc_type() == SOC_MX7D; } bool soc_is_imx7ulp(void) { return imx_soc_type() == SOC_MX7ULP; } bool soc_is_imx8mq(void) { return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x40; } bool soc_is_imx8mm(void) { return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x41; } bool soc_is_imx8mn(void) { return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x42; } bool soc_is_imx8mp(void) { return imx_soc_type() == SOC_MX8M && imx_soc_rev_major() == 0x43; } bool soc_is_imx8m(void) { return soc_is_imx8mq() || soc_is_imx8mm() || soc_is_imx8mn() || soc_is_imx8mp(); } bool soc_is_imx8mq_b0_layer(void) { if (soc_is_imx8mq() && imx_soc_rev_minor() == 0x0) return true; else return false; } optee_os-4.3.0/core/arch/arm/plat-imx/imx-regs.h000066400000000000000000000040461464416617300214360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * Copyright 2019, 2023 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLAT_IMX_IMX_REGS_H #define PLAT_IMX_IMX_REGS_H #ifdef CFG_MX6 #include #elif defined(CFG_MX7) #include #elif defined(CFG_MX7ULP) #include #elif defined(CFG_MX8MQ) || defined(CFG_MX8MM) || defined(CFG_MX8MN) || \ defined(CFG_MX8MP) #include #elif defined(CFG_MX8QX) || defined(CFG_MX8QM) || defined(CFG_MX8DXL) #include #elif defined(CFG_MX8ULP) #include #elif defined(CFG_MX93) #include #else #error "CFG_MX* not defined" #endif #endif optee_os-4.3.0/core/arch/arm/plat-imx/imx.h000066400000000000000000000022701464416617300204750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Peng Fan */ #ifndef PLAT_IMX_IMX_H #define PLAT_IMX_IMX_H #include #include #define SOC_MX6SL 0x60 #define SOC_MX6DL 0x61 #define SOC_MX6SX 0x62 #define SOC_MX6Q 0x63 #define SOC_MX6UL 0x64 #define SOC_MX6ULL 0x65 #define SOC_MX6SLL 0x67 #define SOC_MX6D 0x6A #define SOC_MX7D 0x72 #define SOC_MX7ULP 0xE1 #define SOC_MX8QX 0xE2 #define SOC_MX8QM 0xE3 #define SOC_MX8DXL 0xE4 #define SOC_MX8M 0x82 #define SOC_MX8ULP 0x83 #define SOC_MX93 0xC1 #ifndef __ASSEMBLER__ bool soc_is_imx6(void); bool soc_is_imx6sx(void); bool soc_is_imx6sl(void); bool soc_is_imx6sll(void); bool soc_is_imx6ul(void); bool soc_is_imx6ull(void); bool soc_is_imx6sdl(void); bool soc_is_imx6dq(void); bool soc_is_imx6dqp(void); bool soc_is_imx7ds(void); bool soc_is_imx7ulp(void); bool soc_is_imx8m(void); bool soc_is_imx8mq(void); bool soc_is_imx8mm(void); bool soc_is_imx8mn(void); bool soc_is_imx8mp(void); bool soc_is_imx8mq_b0_layer(void); uint32_t imx_soc_type(void); uint32_t imx_soc_rev_major(void); uint32_t imx_soc_rev_minor(void); uint32_t imx_get_digprog(void); #endif /* __ASSEMBLER__ */ #endif optee_os-4.3.0/core/arch/arm/plat-imx/imx_pl310.c000066400000000000000000000064221464416617300214120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * * Peng Fan */ #include #include #include #include #include #include #include #include #include #include #include "imx_pl310.h" #define PL310_AUX_CTRL_FLZW BIT(0) #define PL310_DEBUG_CTRL_DISABLE_WRITEBACK BIT(1) #define PL310_DEBUG_CTRL_DISABLE_LINEFILL BIT(0) #define PL310_PREFETCH_DOUBLE_LINEFILL BIT(30) register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); void arm_cl2_config(vaddr_t pl310_base) { uint32_t val = 0; uint32_t id = 0; /* Disable PL310 */ io_write32(pl310_base + PL310_CTRL, 0); io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); /* * The L2 cache controller(PL310) version on the i.MX6D/Q * is r3p1-50rel0 * The L2 cache controller(PL310) version on the * i.MX6DL/SOLO/SL/SX/DQP is r3p2. * * According to ARM PL310 errata: 752271 * ID: 752271: Double linefill feature can cause data corruption * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 * Workaround: The only workaround to this erratum is to disable the * double linefill feature. This is the default behavior. */ val = PL310_PREFETCH_CTRL_INIT; id = io_read32(pl310_base + PL310_CACHE_ID); if (((id & PL310_CACHE_ID_PART_MASK) == PL310_CACHE_ID_PART_L310) && ((id & PL310_CACHE_ID_RTL_MASK) < PL310_CACHE_ID_RTL_R3P2)) val &= ~PL310_PREFETCH_DOUBLE_LINEFILL; io_write32(pl310_base + PL310_PREFETCH_CTRL, val); io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); /* invalidate all cache ways */ arm_cl2_invbyway(pl310_base); } void arm_cl2_enable(vaddr_t pl310_base) { uint32_t val __maybe_unused; /* Enable PL310 ctrl -> only set lsb bit */ io_write32(pl310_base + PL310_CTRL, 1); #ifndef CFG_PL310_SIP_PROTOCOL /* if L2 FLZW enable, enable in L1 */ val = io_read32(pl310_base + PL310_AUX_CTRL); if (val & PL310_AUX_CTRL_FLZW) write_actlr(read_actlr() | ACTLR_CA9_WFLZ); #endif } vaddr_t pl310_base(void) { return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1); } vaddr_t pl310_nsbase(void) { return core_mmu_get_va(PL310_BASE, MEM_AREA_IO_NSEC, 1); } #ifdef CFG_PL310_SIP_PROTOCOL uint32_t pl310_enable(void) { vaddr_t base = pl310_base(); arm_cl2_config(base); arm_cl2_enable(base); return OPTEE_SMC_RETURN_OK; } uint32_t pl310_disable(void) { EMSG("not implemented"); return OPTEE_SMC_RETURN_ENOTAVAIL; } uint32_t pl310_enable_writeback(void) { vaddr_t base = pl310_base(); io_write32(base + PL310_DEBUG_CTRL, 0); return OPTEE_SMC_RETURN_OK; } uint32_t pl310_disable_writeback(void) { vaddr_t base = pl310_base(); uint32_t val = PL310_DEBUG_CTRL_DISABLE_WRITEBACK | PL310_DEBUG_CTRL_DISABLE_LINEFILL; io_write32(base + PL310_DEBUG_CTRL, val); return OPTEE_SMC_RETURN_OK; } uint32_t pl310_enable_wflz(void) { write_actlr(read_actlr() | ACTLR_CA9_WFLZ); return OPTEE_SMC_RETURN_OK; } #endif optee_os-4.3.0/core/arch/arm/plat-imx/imx_pl310.h000066400000000000000000000005541464416617300214170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) Microsoft Corporation. All rights reserved. */ #ifndef __IMX_PL310_H__ #define __IMX_PL310_H__ uint32_t pl310_enable(void); uint32_t pl310_disable(void); uint32_t pl310_enable_writeback(void); uint32_t pl310_disable_writeback(void); uint32_t pl310_enable_wflz(void); #endif /* __IMX_PL310_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/link.mk000066400000000000000000000005101464416617300210100ustar00rootroot00000000000000include core/arch/arm/kernel/link.mk .PHONY: uTee uTee: $(link-out-dir)/uTee cleanfiles += $(link-out-dir)/uTee $(link-out-dir)/uTee: $(link-out-dir)/tee-raw.bin @$(cmd-echo-silent) ' MKIMAGE $@' $(q)ADDR=`printf 0x%x $$(($(subst UL,,$(CFG_TZDRAM_START))))`; \ mkimage -A arm -O linux -C none -a $$ADDR -e $$ADDR -d $< $@ optee_os-4.3.0/core/arch/arm/plat-imx/main.c000066400000000000000000000072771464416617300206330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * Copyright 2019, 2023 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include static struct imx_uart_data console_data __nex_bss; #ifdef CONSOLE_UART_BASE register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); #endif #ifdef GIC_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); #endif #ifdef ANATOP_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, ANATOP_BASE, CORE_MMU_PGDIR_SIZE); #endif #ifdef GICD_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, 0x10000); #endif #ifdef AIPS0_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS0_BASE, ROUNDUP(AIPS0_SIZE, CORE_MMU_PGDIR_SIZE)); #endif #ifdef AIPS1_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS1_BASE, ROUNDUP(AIPS1_SIZE, CORE_MMU_PGDIR_SIZE)); #endif #ifdef AIPS2_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS2_BASE, ROUNDUP(AIPS2_SIZE, CORE_MMU_PGDIR_SIZE)); #endif #ifdef AIPS3_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, AIPS3_BASE, ROUNDUP(AIPS3_SIZE, CORE_MMU_PGDIR_SIZE)); #endif #ifdef IRAM_BASE register_phys_mem(MEM_AREA_TEE_COHERENT, ROUNDDOWN(IRAM_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); #endif #ifdef M4_AIPS_BASE register_phys_mem(MEM_AREA_IO_SEC, M4_AIPS_BASE, M4_AIPS_SIZE); #endif #ifdef IRAM_S_BASE register_phys_mem(MEM_AREA_TEE_COHERENT, ROUNDDOWN(IRAM_S_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); #endif #if defined(CFG_PL310) register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(PL310_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); #endif #ifdef CFG_DRAM_BASE register_ddr(CFG_DRAM_BASE, CFG_DDR_SIZE); #endif #ifdef CFG_NSEC_DDR_1_BASE register_ddr(CFG_NSEC_DDR_1_BASE, CFG_NSEC_DDR_1_SIZE); #endif void plat_console_init(void) { #ifdef CONSOLE_UART_BASE imx_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); #endif } void boot_primary_init_intc(void) { #ifdef GICD_BASE gic_init(0, GICD_BASE); #else gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); #endif } #if CFG_TEE_CORE_NB_CORE > 1 void boot_secondary_init_intc(void) { gic_init_per_cpu(); } #endif optee_os-4.3.0/core/arch/arm/plat-imx/platform_config.h000066400000000000000000000042141464416617300230510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * Copyright 2019 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #include #include #ifndef CFG_DDR_SIZE #error "CFG_DDR_SIZE not defined" #endif #define STACK_ALIGNMENT 64 #define CONSOLE_UART_BASE (CFG_UART_BASE) /* For i.MX6 Quad SABRE Lite and Smart Device board */ #if defined(CFG_MX6QP) || defined(CFG_MX6Q) || defined(CFG_MX6D) || \ defined(CFG_MX6DL) || defined(CFG_MX6S) #include #elif defined(CFG_MX6SX) #include /* For i.MX 6SL */ #elif defined(CFG_MX6SL) #include /* For i.MX 6SLL */ #elif defined(CFG_MX6SLL) #include #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-imx/registers/000077500000000000000000000000001464416617300215355ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx6-crm.h000066400000000000000000001042341464416617300233540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef __IMX6_CRM_H__ #define __IMX6_CRM_H__ #define CCM_CCR 0x0000 #define CCM_CCDR 0x0004 #define CCM_CSR 0x0008 #define CCM_CCSR 0x000C #define CCM_CACRR 0x0010 #define CCM_CBCDR 0x0014 #define CCM_CBCMR 0x0018 #define CCM_CSCMR1 0x001C #define CCM_CSCMR2 0x0020 #define CCM_CSCDR1 0x0024 #define CCM_CS1CDR 0x0028 #define CCM_CS2CDR 0x002C #define CCM_CDCDR 0x0030 #define CCM_CHSCCDR 0x0034 #define CCM_CSCDR2 0x0038 #define CCM_CSCDR3 0x003C #define CCM_CSCDR4 0x0040 #define CCM_CWDR 0x0044 #define CCM_CDHIPR 0x0048 #define CCM_CDCR 0x004C #define CCM_CTOR 0x0050 #define CCM_CLPCR 0x0054 #define CCM_CISR 0x0058 #define CCM_CIMR 0x005C #define CCM_CCOSR 0x0060 #define CCM_CGPR 0x0064 #define CCM_CCGR0 0x0068 #define CCM_CCGR1 0x006C #define CCM_CCGR2 0x0070 #define CCM_CCGR3 0x0074 #define CCM_CCGR4 0x0078 #define CCM_CCGR5 0x007C #define CCM_CCGR6 0x0080 #define CCM_CCGR7 0x0084 #define CCM_CMEOR 0x0088 #define CCM_ANALOG_PLL_SYS 0x4000 #define CCM_ANALOG_PLL_SYS_SET 0x4004 #define CCM_ANALOG_PLL_SYS_CLR 0x4008 #define CCM_ANALOG_PLL_SYS_TOG 0x400C #define CCM_ANALOG_USB1_PLL_480_CTRL 0x4010 #define CCM_ANALOG_USB1_PLL_480_CTRL_SET 0x4014 #define CCM_ANALOG_USB1_PLL_480_CTRL_CLR 0x4018 #define CCM_ANALOG_USB1_PLL_480_CTRL_TOG 0x401C #define CCM_ANALOG_PLL_528 0x4030 #define CCM_ANALOG_PLL_528_SET 0x4034 #define CCM_ANALOG_PLL_528_CLR 0x4038 #define CCM_ANALOG_PLL_528_TOG 0x403C #define CCM_ANALOG_PLL_528_SS 0x4040 #define CCM_ANALOG_PLL_528_NUM 0x4050 #define CCM_ANALOG_PLL_528_DENOM 0x4060 #define CCM_ANALOG_PLL_AUDIO 0x4070 #define CCM_ANALOG_PLL_AUDIO_SET 0x4074 #define CCM_ANALOG_PLL_AUDIO_CLR 0x4078 #define CCM_ANALOG_PLL_AUDIO_TOG 0x407C #define CCM_ANALOG_PLL_AUDIO_NUM 0x4080 #define CCM_ANALOG_PLL_AUDIO_DENOM 0x4090 #define CCM_ANALOG_PLL_VIDEO 0x40A0 #define CCM_ANALOG_PLL_VIDEO_SET 0x40A4 #define CCM_ANALOG_PLL_VIDEO_CLR 0x40A8 #define CCM_ANALOG_PLL_VIDEO_TOG 0x40AC #define CCM_ANALOG_PLL_VIDEO_NUM 0x40B0 #define CCM_ANALOG_PLL_VEDIO_DENON 0x40C0 #define CCM_ANALOG_PLL_ENET 0x40E0 #define CCM_ANALOG_PLL_ENET_SET 0x40E4 #define CCM_ANALOG_PLL_ENET_CLR 0x40E8 #define CCM_ANALOG_PLL_ENET_TOG 0x40EC #define CCM_ANALOG_PFD_480 0x40F0 #define CCM_ANALOG_PFD_480_SET 0x40F4 #define CCM_ANALOG_PFD_480_CLR 0x40F8 #define CCM_ANALOG_PFD_480_TOG 0x40FC #define CCM_ANALOG_PFD_528 0x4100 #define CCM_ANALOG_PFD_528_SET 0x4104 #define CCM_ANALOG_PFD_528_CLR 0x4108 #define CCM_ANALOG_PFD_528_TOG 0x410C /* Define the bits in register CCR */ #define BS_CCM_CCR_RBC_EN 27 #define BM_CCM_CCR_RBC_EN BIT32(BS_CCM_CCR_RBC_EN) #define BS_CCM_CCR_REG_BYPASS_COUNT 21 #define BM_CCM_CCR_REG_BYPASS_COUNT \ SHIFT_U32(0x3F, BS_CCM_CCR_REG_BYPASS_COUNT) #define BS_CCM_CCR_WB_COUNT 16 #define BM_CCM_CCR_WB_COUNT SHIFT_U32(0x7, BS_CCM_CCR_WB_COUNT) #define BS_CCM_CCR_OSCNT 0 #define BM_CCM_CCR_OSCNT SHIFT_U32(0xFF, BS_CCM_CCR_OSCNT) #define CCM_CCR_COSC_EN SHIFT_U32((1 << 12), BS_CCM_CCR_OSCNT) /* Define the bits in register CCDR */ #define BS_CCM_CCDR_MMDC_CH1_HS_MASK 16 #define BM_CCM_CCDR_MMDC_CH1_HS_MASK BIT32(BS_CCM_CCDR_MMDC_CH1_HS_MASK) #define BS_CCM_CCDR_MMDC_CH0_HS_MASK 17 #define BM_CCM_CCDR_MMDC_CH0_HS_MASK BIT32(BS_CCM_CCDR_MMDC_CH0_HS_MASK) /* Define the bits in register CSR */ #define BS_CCM_CSR_COSC_READY 5 #define BM_CCM_CSR_COSC_READY BIT32(BS_CCM_CSR_COSC_READY) #define BS_CCM_CSR_REF_EN_B 0 #define BM_CCM_CSR_REF_EN_B BIT32(BS_CCM_CSR_REF_EN_B) /* Define the bits in register CCSR */ #define BS_CCM_CCSR_PDF_540M_AUTO_DIS 15 #define BM_CCM_CCSR_PDF_540M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_540M_AUTO_DIS) #define BS_CCM_CCSR_PDF_720M_AUTO_DIS 14 #define BM_CCM_CCSR_PDF_720M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_720M_AUTO_DIS) #define BS_CCM_CCSR_PDF_454M_AUTO_DIS 13 #define BM_CCM_CCSR_PDF_454M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_454M_AUTO_DIS) #define BS_CCM_CCSR_PDF_508M_AUTO_DIS 12 #define BM_CCM_CCSR_PDF_508M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_508M_AUTO_DIS) #define BS_CCM_CCSR_PDF_594M_AUTO_DIS 11 #define BM_CCM_CCSR_PDF_594M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_594M_AUTO_DIS) #define BS_CCM_CCSR_PDF_352M_AUTO_DIS 10 #define BM_CCM_CCSR_PDF_352M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_352M_AUTO_DIS) #define BS_CCM_CCSR_PDF_400M_AUTO_DIS 9 #define BM_CCM_CCSR_PDF_400M_AUTO_DIS BIT32(BS_CCM_CCSR_PDF_400M_AUTO_DIS) #define BS_CCM_CCSR_STEP_SEL 8 #define BM_CCM_CCSR_STEP_SEL BIT32(BS_CCM_CCSR_STEP_SEL) #define BS_CCM_CCSR_PLL1_SW_CLK_SEL 2 #define BM_CCM_CCSR_PLL1_SW_CLK_SEL BIT32(BS_CCM_CCSR_PLL1_SW_CLK_SEL) #define BS_CCM_CCSR_PLL2_SW_CLK_SEL 1 #define BM_CCM_CCSR_PLL2_SW_CLK_SEL BIT32(BS_CCM_CCSR_PLL2_SW_CLK_SEL) #define BS_CCM_CCSR_PLL3_SW_CLK_SEL 0 #define BM_CCM_CCSR_PLL3_SW_CLK_SEL BIT32(BS_CCM_CCSR_PLL3_SW_CLK_SEL) /* Define the bits in register CACRR */ #define BS_CCM_CACRR_ARM_PODF 0 #define BM_CCM_CACRR_ARM_PODF SHIFT_U32(0x7, BS_CCM_CACRR_ARM_PODF) /* Define the bits in register CBCDR */ #define BS_CCM_CBCDR_PERIPH_CLK2_PODF 27 #define BM_CCM_CBCDR_PERIPH_CLK2_PODF \ SHIFT_U32(0x7, BS_CCM_CBCDR_PERIPH_CLK2_PODF) #define BS_CCM_CBCDR_PERIPH2_CLK2_SEL 26 #define BM_CCM_CBCDR_PERIPH2_CLK2_SEL BIT32(BS_CCM_CBCDR_PERIPH2_CLK2_SEL) #define BS_CCM_CBCDR_PERIPH_CLK_SEL 25 #define BM_CCM_CBCDR_PERIPH_CLK_SEL BIT32(BS_CCM_CBCDR_PERIPH_CLK_SEL) #define BS_CCM_CBCDR_MMDC_CH0_PODF 19 #define BM_CCM_CBCDR_MMDC_CH0_PODF \ SHIFT_U32(0x7, BS_CCM_CBCDR_MMDC_CH0_PODF) #define BS_CCM_CBCDR_AXI_PODF 16 #define BM_CCM_CBCDR_AXI_PODF SHIFT_U32(0x7, BS_CCM_CBCDR_AXI_PODF) #define BS_CCM_CBCDR_AHB_PODF 10 #define BM_CCM_CBCDR_AHB_PODF SHIFT_U32(0x7, BS_CCM_CBCDR_AHB_PODF) #define BS_CCM_CBCDR_IPG_PODF 8 #define BM_CCM_CBCDR_IPG_PODF SHIFT_U32(0x3, BS_CCM_CBCDR_IPG_PODF) #define BS_CCM_CBCDR_AXI_ALT_SEL 7 #define BM_CCM_CBCDR_AXI_ALT_SEL BIT32(BS_CCM_CBCDR_AXI_ALT_SEL) #define BS_CCM_CBCDR_AXI_SEL 6 #define BM_CCM_CBCDR_AXI_SEL BIT32(BS_CCM_CBCDR_AXI_SEL) #define BS_CCM_CBCDR_MMDC_CH1_PODF 3 #define BM_CCM_CBCDR_MMDC_CH1_PODF \ SHIFT_U32(0x7, BS_CCM_CBCDR_MMDC_CH1_PODF) #define BS_CCM_CBCDR_PERIPH2_CLK2_PODF 0 #define BM_CCM_CBCDR_PERIPH2_CLK2_PODF \ SHIFT_U32(0x7, BS_CCM_CBCDR_PERIPH2_CLK2_PODF) /* Define the bits in register CBCMR */ #define BS_CCM_CBCMR_GPU3D_SHADER_PODF 29 #define BM_CCM_CBCMR_GPU3D_SHADER_PODF \ SHIFT_U32(0x7, BS_CCM_CBCMR_GPU3D_SHADER_PODF) #define BS_CCM_CBCMR_GPU3D_CORE_PODF 26 #define BM_CCM_CBCMR_GPU3D_CORE_PODF \ SHIFT_U32(0x7, BS_CCM_CBCMR_GPU3D_CORE_PODF) #define BS_CCM_CBCMR_GPU2D_CORE_PODF 23 #define BM_CCM_CBCMR_GPU2D_CORE_PODF \ SHIFT_U32(0x7, BS_CCM_CBCMR_GPU2D_CORE_PODF) #define BS_CCM_CBCMR_PRE_PERIPH2_CLK_SEL 21 #define BM_CCM_CBCMR_PRE_PERIPH2_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_PRE_PERIPH2_CLK_SEL) #define BS_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL 20 #define BM_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL \ BIT32(BS_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL) #define BS_CCM_CBCMR_PRE_PERIPH_CLK_SEL 18 #define BM_CCM_CBCMR_PRE_PERIPH_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_PRE_PERIPH_CLK_SEL) #define BS_CCM_CBCMR_GPU2D_CLK_SEL 16 #define BM_CCM_CBCMR_GPU2D_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_GPU2D_CLK_SEL) #define BS_CCM_CBCMR_VPU_AXI_CLK_SEL 14 #define BM_CCM_CBCMR_VPU_AXI_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_VPU_AXI_CLK_SEL) #define BS_CCM_CBCMR_PERIPH_CLK2_SEL 12 #define BM_CCM_CBCMR_PERIPH_CLK2_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_PERIPH_CLK2_SEL) #define BS_CCM_CBCMR_VDOAXI_CLK_SEL 11 #define BM_CCM_CBCMR_VDOAXI_CLK_SEL BIT32(BS_CCM_CBCMR_VDOAXI_CLK_SEL) #define BS_CCM_CBCMR_PCIE_AXI_CLK_SEL 10 #define BM_CCM_CBCMR_PCIE_AXI_CLK_SEL BIT32(BS_CCM_CBCMR_PCIE_AXI_CLK_SE) #define BS_CCM_CBCMR_GPU3D_SHADER_CLK_SEL 8 #define BM_CCM_CBCMR_GPU3D_SHADER_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_GPU3D_SHADER_CLK_SEL) #define BS_CCM_CBCMR_GPU3D_CORE_CLK_SEL 4 #define BM_CCM_CBCMR_GPU3D_CORE_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CBCMR_GPU3D_CORE_CLK_SEL) #define BS_CCM_CBCMR_GPU3D_AXI_CLK_SEL 1 #define BM_CCM_CBCMR_GPU3D_AXI_CLK_SEL \ BIT32(BS_CCM_CBCMR_GPU3D_AXI_CLK_SEL) #define BS_CCM_CBCMR_GPU2D_AXI_CLK_SEL 0 #define BM_CCM_CBCMR_GPU2D_AXI_CLK_SEL \ BIT32(BS_CCM_CBCMR_GPU2D_AXI_CLK_SELx0) /* Define the bits in register CSCMR1 */ #define BS_CCM_CSCMR1_ACLK_EMI_SLOW 29 #define BM_CCM_CSCMR1_ACLK_EMI_SLOW \ SHIFT_U32(0x3, BS_CCM_CSCMR1_ACLK_EMI_SLOW) #define BS_CCM_CSCMR1_ACLK_EMI 27 #define BM_CCM_CSCMR1_ACLK_EMI SHIFT_U32(0x3, BS_CCM_CSCMR1_ACLK_EMI) #define BS_CCM_CSCMR1_ACLK_EMI_SLOW_PODF 23 #define BM_CCM_CSCMR1_ACLK_EMI_SLOW_PODF \ SHIFT_U32(0x7, BS_CCM_CSCMR1_ACLK_EMI_SLOW_PODF) #define BS_CCM_CSCMR1_ACLK_EMI_PODF 20 #define BM_CCM_CSCMR1_ACLK_EMI_PODF \ SHIFT_U32(0x7, BS_CCM_CSCMR1_ACLK_EMI_PODF) #define BS_CCM_CSCMR1_USDHC4_CLK_SEL 19 #define BM_CCM_CSCMR1_USDHC4_CLK_SEL \ BIT32(BS_CCM_CSCMR1_USDHC4_CLK_SEL) #define BS_CCM_CSCMR1_USDHC3_CLK_SEL 18 #define BM_CCM_CSCMR1_USDHC3_CLK_SEL \ BIT32(BS_CCM_CSCMR1_USDHC3_CLK_SEL) #define BS_CCM_CSCMR1_USDHC2_CLK_SEL 17 #define BM_CCM_CSCMR1_USDHC2_CLK_SEL \ BIT32(BS_CCM_CSCMR1_USDHC2_CLK_SEL) #define BS_CCM_CSCMR1_USDHC1_CLK_SEL 16 #define BM_CCM_CSCMR1_USDHC1_CLK_SEL \ BIT32(BS_CCM_CSCMR1_USDHC1_CLK_SEL) #define BS_CCM_CSCMR1_SSI3_CLK_SEL 14 #define BM_CCM_CSCMR1_SSI3_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CSCMR1_SSI3_CLK_SEL) #define BS_CCM_CSCMR1_SSI2_CLK_SEL 12 #define BM_CCM_CSCMR1_SSI2_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CSCMR1_SSI2_CLK_SEL) #define BS_CCM_CSCMR1_SSI1_CLK_SEL 10 #define BM_CCM_CSCMR1_SSI1_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CSCMR1_SSI1_CLK_SEL) #define BS_CCM_CSCMR1_PERCLK_PODF 0 #define BM_CCM_CSCMR1_PERCLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CSCMR1_PERCLK_PODF) /* Define the bits in register CSCMR2 */ #define BS_CCM_CSCMR2_ESAI_PRE_SEL 19 #define BM_CCM_CSCMR2_ESAI_PRE_SEL \ SHIFT_U32(0x3, BS_CCM_CSCMR2_ESAI_PRE_SEL) #define BS_CCM_CSCMR2_LDB_DI1_IPU_DIV 11 #define BM_CCM_CSCMR2_LDB_DI1_IPU_DIV BIT32(BS_CCM_CSCMR2_LDB_DI1_IPU_DIV) #define BS_CCM_CSCMR2_LDB_DI0_IPU_DIV 10 #define BM_CCM_CSCMR2_LDB_DI0_IPU_DIV BIT32(BS_CCM_CSCMR2_LDB_DI1_IPU_DIV) #define BS_CCM_CSCMR2_CAN_CLK_SEL 2 #define BM_CCM_CSCMR2_CAN_CLK_SEL \ SHIFT_U32(0x3F, BS_CCM_CSCMR2_CAN_CLK_SEL) /* Define the bits in register CSCDR1 */ #define BS_CCM_CSCDR1_VPU_AXI_PODF 25 #define BM_CCM_CSCDR1_VPU_AXI_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR1_VPU_AXI_PODF) #define BS_CCM_CSCDR1_USDHC4_PODF 22 #define BM_CCM_CSCDR1_USDHC4_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC4_PODF) #define BS_CCM_CSCDR1_USDHC3_PODF 19 #define BM_CCM_CSCDR1_USDHC3_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC3_PODF) #define BS_CCM_CSCDR1_USDHC2_PODF 16 #define BM_CCM_CSCDR1_USDHC2_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC2_PODF) #define BS_CCM_CSCDR1_USDHC1_PODF 11 #define BM_CCM_CSCDR1_USDHC1_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR1_USDHC1_PODF) #define BS_CCM_CSCDR1_USBOH3_CLK_PRED 8 #define BM_CCM_CSCDR1_USBOH3_CLK_PRED \ SHIFT_U32(0x7, BS_CCM_CSCDR1_USBOH3_CLK_PRED) #define BS_CCM_CSCDR1_USBOH3_CLK_PODF 6 #define BM_CCM_CSCDR1_USBOH3_CLK_PODF \ SHIFT_U32(0x3, BS_CCM_CSCDR1_USBOH3_CLK_PODF) #ifdef CONFIG_MX6SL #define BS_CCM_CSCDR1_UART_CLK_SEL 6 #define BM_CCM_CSCDR1_UART_CLK_SEL BIT32(BS_CCM_CSCDR1_UART_CLK_SEL) #define BS_CCM_CSCDR1_UART_CLK_PODF 0 #define BM_CCM_CSCDR1_UART_CLK_PODF SHIFT_U32(0x1F, BS_CCM_CSCDR1_UA) #else #define BS_CCM_CSCDR1_UART_CLK_PODF 0 #define BM_CCM_CSCDR1_UART_CLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CSCDR1_UART_CLK_PODF) #endif /* Define the bits in register CS1CDR */ #define BS_CCM_CS1CDR_ESAI_CLK_PODF 25 #define BM_CCM_CS1CDR_ESAI_CLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CS1CDR_ESAI_CLK_PODF) #define BS_CCM_CS1CDR_SSI3_CLK_PODF 16 #define BM_CCM_CS1CDR_SSI3_CLK_PODF SHIFT_U32(0x3F, BS_CCM_CS1CDR_SSI3) #define BS_CCM_CS1CDR_ESAI_CLK_PRED 9 #define BM_CCM_CS1CDR_ESAI_CLK_PRED \ SHIFT_U32(0x3, BS_CCM_CS1CDR_ESAI_CLK_PRED) #define BS_CCM_CS1CDR_SSI1_CLK_PRED 6 #define BM_CCM_CS1CDR_SSI1_CLK_PRED \ SHIFT_U32(0x7, BS_CCM_CS1CDR_SSI1_CLK_PRED) #define BS_CCM_CS1CDR_SSI1_CLK_PODF 0 #define BM_CCM_CS1CDR_SSI1_CLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CS1CDR_SSI1_CLK_PODF) /* Define the bits in register CS2CDR */ #define BS_CCM_CS2CDR_ENFC_CLK_PODF 21 #define BM_CCM_CS2CDR_ENFC_CLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CS2CDR_ENFC_CLK_PODF) #define CCM_CS2CDR_ENFC_CLK_PODF(v) \ (SHIFT_U32(v, BS_CCM_CS2CDR_ENFC_CLK_PODF) & \ BM_CCM_CS2CDR_ENFC_CLK_PODF) #define BS_CCM_CS2CDR_ENFC_CLK_PRED 18 #define BM_CCM_CS2CDR_ENFC_CLK_PRED \ SHIFT_U32(0x7, BS_CCM_CS2CDR_ENFC_CLK_PRED) #define CCM_CS2CDR_ENFC_CLK_PRED(v) \ (SHIFT_U32(v, BS_CCM_CS2CDR_ENFC_CLK_PRED) & \ BM_CCM_CS2CDR_ENFC_CLK_PRED) #define BS_CCM_CS2CDR_ENFC_CLK_SEL 16 #define BM_CCM_CS2CDR_ENFC_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CS2CDR_ENFC_CLK_SEL_OFFSET) #define CCM_CS2CDR_ENFC_CLK_SEL(v) \ (SHIFT_U32(v, BS_CCM_CS2CDR_ENFC_CLK_SEL) & \ BM_CCM_CS2CDR_ENFC_CLK_SEL) #define BS_CCM_CS2CDR_LDB_DI1_CLK_SEL 12 #define BM_CCM_CS2CDR_LDB_DI1_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CS2CDR_LDB_DI1_CLK_SEL) #define BS_CCM_CS2CDR_LDB_DI0_CLK_SEL 9 #define BM_CCM_CS2CDR_LDB_DI0_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CS2CDR_LDB_DI0_CLK_SEL) #define BS_CCM_CS2CDR_SSI2_CLK_PRED 6 #define BM_CCM_CS2CDR_SSI2_CLK_PRED \ SHIFT_U32(0x7, BS_CCM_CS2CDR_SSI2_CLK_PRED) #define BS_CCM_CS2CDR_SSI2_CLK_PODF 0 #define BM_CCM_CS2CDR_SSI2_CLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CS2CDR_SSI2_CLK_PODF) /* Define the bits in register CDCDR */ #define BS_CCM_CDCDR_HSI_TX_PODF 29 #define BM_CCM_CDCDR_HSI_TX_PODF \ SHIFT_U32(0x7, BS_CCM_CDCDR_HSI_TX_PODF) #define BS_CCM_CDCDR_SPDIF0_CLK_PRED 25 #define BM_CCM_CDCDR_SPDIF0_CLK_PRED \ SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF0_CLK_PRED) #define BS_CCM_CDCDR_HSI_TX_CLK_SEL 28 #define BM_CCM_CDCDR_HSI_TX_CLK_SEL \ BIT32(BS_CCM_CDCDR_HSI_TX_CLK_SEL) #define BS_CCM_CDCDR_SPDIF0_CLK_PODF 19 #define BM_CCM_CDCDR_SPDIF0_CLK_PODF \ SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF0_CLK_PODF) #define BS_CCM_CDCDR_SPDIF0_CLK_SEL 20 #define BM_CCM_CDCDR_SPDIF0_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CDCDR_SPDIF0_CLK_SEL) #define BS_CCM_CDCDR_SPDIF1_CLK_PRED 12 #define BM_CCM_CDCDR_SPDIF1_CLK_PRED \ SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF1_CLK_PRED) #define BS_CCM_CDCDR_SPDIF1_CLK_PODF 9 #define BM_CCM_CDCDR_SPDIF1_CLK_PODF \ SHIFT_U32(0x7, BS_CCM_CDCDR_SPDIF1_CLK_PODF) #define BS_CCM_CDCDR_SPDIF1_CLK_SEL 7 #define BM_CCM_CDCDR_SPDIF1_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CDCDR_SPDIF1_CLK_SEL) /* Define the bits in register CHSCCDR */ #define BS_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL 15 #define BM_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI1_PRE_CLK_SEL) #define BS_CCM_CHSCCDR_IPU1_DI1_PODF 12 #define BM_CCM_CHSCCDR_IPU1_DI1_PODF \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI1_PODF) #define BS_CCM_CHSCCDR_IPU1_DI1_CLK_SEL 9 #define BM_CCM_CHSCCDR_IPU1_DI1_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI1_CLK_SEL) #define BS_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL 6 #define BM_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI0_PRE_CLK_SEL) #define BS_CCM_CHSCCDR_IPU1_DI0_PODF 3 #define BM_CCM_CHSCCDR_IPU1_DI0_PODF \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI0_PODF) #define BS_CCM_CHSCCDR_IPU1_DI0_CLK_SEL 0 #define BM_CCM_CHSCCDR_IPU1_DI0_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU1_DI0_CLK_SEL) #define CHSCCDR_CLK_SEL_LDB_DI0 3 #define CHSCCDR_PODF_DIVIDE_BY_3 2 #define CHSCCDR_IPU_PRE_CLK_540M_PFD 5 /* Define the bits in register CSCDR2 */ #define BS_CCM_CSCDR2_ECSPI_CLK_PODF 19 #define BM_CCM_CSCDR2_ECSPI_CLK_PODF \ SHIFT_U32(0x3F, BS_CCM_CSCDR2_ECSPI_CLK_PODF) #define BS_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL 15 #define BM_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL) #define BS_CCM_CHSCCDR_IPU2_DI1_PODF 12 #define BM_CCM_CHSCCDR_IPU2_DI1_PODF \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI1_PODF) #define BS_CCM_CHSCCDR_IPU2_DI1_CLK_SEL 9 #define BM_CCM_CHSCCDR_IPU2_DI1_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI1_CLK_SEL) #define BS_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL 6 #define BM_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI0_PRE_CLK_SEL) #define BS_CCM_CHSCCDR_IPU2_DI0_PODF 3 #define BM_CCM_CHSCCDR_IPU2_DI0_PODF \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI0_PODF) #define BS_CCM_CHSCCDR_IPU2_DI0_CLK_SEL 0 #define BM_CCM_CHSCCDR_IPU2_DI0_CLK_SEL \ SHIFT_U32(0x7, BS_CCM_CHSCCDR_IPU2_DI0_CLK_SEL) /* Define the bits in register CSCDR3 */ #define BS_CCM_CSCDR3_IPU2_HSP_PODF 16 #define BM_CCM_CSCDR3_IPU2_HSP_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR3_IPU2_HSP_PODF) #define BS_CCM_CSCDR3_IPU2_HSP_CLK_SEL 14 #define BM_CCM_CSCDR3_IPU2_HSP_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CSCDR3_IPU2_HSP_CLK_SEL) #define BS_CCM_CSCDR3_IPU1_HSP_PODF 11 #define BM_CCM_CSCDR3_IPU1_HSP_PODF \ SHIFT_U32(0x7, BS_CCM_CSCDR3_IPU1_HSP_PODF) #define BS_CCM_CSCDR3_IPU1_HSP_CLK_SEL 9 #define BM_CCM_CSCDR3_IPU1_HSP_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CSCDR3_IPU1_HSP_CLK_SEL) /* Define the bits in register CDHIPR */ #define BS_CCM_CDHIPR_ARM_PODF_BUSY 16 #define BM_CCM_CDHIPR_ARM_PODF_BUSY \ BIT32(BS_CCM_CDHIPR_ARM_PODF_BUSY) #define BS_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY 5 #define BM_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY \ BIT32(BS_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY) #define BS_CCM_CDHIPR_MMDC_CH0_PODF_BUSY 4 #define BM_CCM_CDHIPR_MMDC_CH0_PODF_BUSY \ BIT32(BS_CCM_CDHIPR_MMDC_CH0_PODF_BUSY) #define BS_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY 3 #define BM_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY \ BIT32(BS_CCM_CDHIPR_PERIPH2_CLK_SEL_BUSY) #define BS_CCM_CDHIPR_MMDC_CH1_PODF_BUSY 2 #define BM_CCM_CDHIPR_MMDC_CH1_PODF_BUSY \ BIT32(BS_CCM_CDHIPR_MMDC_CH1_PODF_BUSY) #define BS_CCM_CDHIPR_AHB_PODF_BUSY 1 #define BM_CCM_CDHIPR_AHB_PODF_BUSY \ BIT32(BS_CCM_CDHIPR_AHB_PODF_BUSY) #define BS_CCM_CDHIPR_AXI_PODF_BUSY 0 #define BM_CCM_CDHIPR_AXI_PODF_BUSY \ BIT32(BS_CCM_CDHIPR_AXI_PODF_BUSY) /* Define the bits in register CLPCR */ #define BS_CCM_CLPCR_MASK_L2CC_IDLE 27 #define BM_CCM_CLPCR_MASK_L2CC_IDLE \ BIT32(BS_CCM_CLPCR_MASK_L2CC_IDLE) #define BS_CCM_CLPCR_MASK_SCU_IDLE 26 #define BM_CCM_CLPCR_MASK_SCU_IDLE \ BIT32(BS_CCM_CLPCR_MASK_SCU_IDLE) #define BS_CCM_CLPCR_MASK_CORE3_WFI 25 #define BM_CCM_CLPCR_MASK_CORE3_WFI \ BIT32(BS_CCM_CLPCR_MASK_CORE3_WFI) #define BS_CCM_CLPCR_MASK_CORE2_WFI 24 #define BM_CCM_CLPCR_MASK_CORE2_WFI \ BIT32(BS_CCM_CLPCR_MASK_CORE2_WFI) #define BS_CCM_CLPCR_MASK_CORE1_WFI 23 #define BM_CCM_CLPCR_MASK_CORE1_WFI \ BIT32(BS_CCM_CLPCR_MASK_CORE1_WFI) #define BS_CCM_CLPCR_MASK_CORE0_WFI 22 #define BM_CCM_CLPCR_MASK_CORE0_WFI \ BIT32(BS_CCM_CLPCR_MASK_CORE0_WFI) #define BS_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS 21 #define BM_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS \ BIT32(BS_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS) #define BS_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS 19 #define BM_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS \ BIT32(BS_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS) #define BS_CCM_CLPCR_WB_CORE_AT_LPM 17 #define BM_CCM_CLPCR_WB_CORE_AT_LPM \ BIT32(BS_CCM_CLPCR_WB_CORE_AT_LPM) #define BS_CCM_CLPCR_WB_PER_AT_LPM 16 #define BM_CCM_CLPCR_WB_PER_AT_LPM \ BIT32(BS_CCM_CLPCR_WB_PER_AT_LPM) #define BS_CCM_CLPCR_COSC_PWRDOWN 11 #define BM_CCM_CLPCR_COSC_PWRDOWN \ BIT32(BS_CCM_CLPCR_COSC_PWRDOWN) #define BS_CCM_CLPCR_STBY_COUNT 9 #define BM_CCM_CLPCR_STBY_COUNT \ SHIFT_U32(0x3, BS_CCM_CLPCR_STBY_COUNT) #define BS_CCM_CLPCR_VSTBY 8 #define BM_CCM_CLPCR_VSTBY \ BIT32(BS_CCM_CLPCR_VSTBY) #define BS_CCM_CLPCR_DIS_REF_OSC 7 #define BM_CCM_CLPCR_DIS_REF_OSC \ BIT32(BS_CCM_CLPCR_DIS_REF_OSC) #define BS_CCM_CLPCR_SBYOS 6 #define BM_CCM_CLPCR_SBYOS \ BIT32(BS_CCM_CLPCR_SBYOS) #define BS_CCM_CLPCR_ARM_CLK_DIS_ON_LPM 5 #define BM_CCM_CLPCR_ARM_CLK_DIS_ON_LPM \ BIT32(BS_CCM_CLPCR_ARM_CLK_DIS_ON_LPM) #define BS_CCM_CLPCR_LPSR_CLK_SEL 3 #define BM_CCM_CLPCR_LPSR_CLK_SEL \ SHIFT_U32(0x3, BS_CCM_CLPCR_LPSR_CLK_SEL) #define BS_CCM_CLPCR_BYPASS_PMIC_VFUNC_RDY 2 #define BM_CCM_CLPCR_BYPASS_PMIC_VFUNC_RDY \ BIT32(BS_CCM_CLPCR_BYPASS_PMIC_VFUNC_RDY) #define BS_CCM_CLPCR_LPM 0 #define BM_CCM_CLPCR_LPM \ SHIFT_U32(0x3, BS_CCM_CLPCR_LPM) /* Define the bits in register CISR */ #define BS_CCM_CISR_ARM_PODF_LOADED 26 #define BM_CCM_CISR_ARM_PODF_LOADED \ BIT32(BS_CCM_CISR_ARM_PODF_LOADED) #define BS_CCM_CISR_MMDC_CH0_PODF_LOADED 23 #define BM_CCM_CISR_MMDC_CH0_PODF_LOADED \ BIT32(BS_CCM_CISR_MMDC_CH0_PODF_LOADED) #define BS_CCM_CISR_PERIPH_CLK_SEL_LOADED 22 #define BM_CCM_CISR_PERIPH_CLK_SEL_LOADED \ BIT32(BS_CCM_CISR_PERIPH_CLK_SEL_LOADED) #define BS_CCM_CISR_MMDC_CH1_PODF_LOADED 21 #define BM_CCM_CISR_MMDC_CH1_PODF_LOADED \ BIT32(BS_CCM_CISR_MMDC_CH1_PODF_LOADED) #define BS_CCM_CISR_AHB_PODF_LOADED 20 #define BM_CCM_CISR_AHB_PODF_LOADED \ BIT32(BS_CCM_CISR_AHB_PODF_LOADED) #define BS_CCM_CISR_PERIPH2_CLK_SEL_LOADED 19 #define BM_CCM_CISR_PERIPH2_CLK_SEL_LOADED \ BIT32(BS_CCM_CISR_PERIPH2_CLK_SEL_LOADED) #define BS_CCM_CISR_AXI_PODF_LOADED 17 #define BM_CCM_CISR_AXI_PODF_LOADED \ BIT32(BS_CCM_CISR_AXI_PODF_LOADED) #define BS_CCM_CISR_COSC_READY 6 #define BM_CCM_CISR_COSC_READY \ BIT32(BS_CCM_CISR_COSC_READY) #define BS_CCM_CISR_LRF_PLL 0 #define BM_CCM_CISR_LRF_PLL \ BIT32(BS_CCM_CISR_LRF_PLL) /* Define the bits in register CIMR */ #define BS_CCM_CIMR_MASK_ARM_PODF_LOADED 26 #define BM_CCM_CIMR_MASK_ARM_PODF_LOADED \ BIT32(BS_CCM_CIMR_MASK_ARM_PODF_LOADED) #define BS_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED 23 #define BM_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED \ BIT32(BS_CCM_CIMR_MASK_MMDC_CH0_PODF_LOADED) #define BS_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED 22 #define BM_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED \ BIT32(BS_CCM_CIMR_MASK_PERIPH_CLK_SEL_LOADED) #define BS_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED 21 #define BM_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED \ BIT32(BS_CCM_CIMR_MASK_MMDC_CH1_PODF_LOADED) #define BS_CCM_CIMR_MASK_AHB_PODF_LOADED 20 #define BM_CCM_CIMR_MASK_AHB_PODF_LOADED \ BIT32(BS_CCM_CIMR_MASK_AHB_PODF_LOADED) #define BS_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED 19 #define BM_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED \ BIT32(BS_CCM_CIMR_MASK_PERIPH2_CLK_SEL_LOADED) #define BS_CCM_CIMR_MASK_AXI_PODF_LOADED 17 #define BM_CCM_CIMR_MASK_AXI_PODF_LOADED \ BIT32(BS_CCM_CIMR_MASK_AXI_PODF_LOADED) #define BS_CCM_CIMR_MASK_COSC_READY 6 #define BM_CCM_CIMR_MASK_COSC_READY \ BIT32(BS_CCM_CIMR_MASK_COSC_READY) #define BS_CCM_CIMR_MASK_LRF_PLL 0 #define BM_CCM_CIMR_MASK_LRF_PLL \ BIT32(BS_CCM_CIMR_MASK_LRF_PLL) /* Define the bits in register CCOSR */ #define BS_CCM_CCOSR_CKO2_EN 24 #define BM_CCM_CCOSR_CKO2_EN \ BIT32(BS_CCM_CCOSR_CKO2_EN) #define BS_CCM_CCOSR_CKO2_DIV 21 #define BM_CCM_CCOSR_CKO2_DIV \ SHIFT_U32(0x7, BS_CCM_CCOSR_CKO2_DIV) #define BS_CCM_CCOSR_CKO2_SEL 16 #define BM_CCM_CCOSR_CKO2_SEL \ SHIFT_U32(0x1F, BS_CCM_CCOSR_CKO2_SEL) #define BS_CCM_CCOSR_CLK_OUT_SEL 8 #define BM_CCM_CCOSR_CLK_OUT_SEL_CKO2 \ BIT32(BS_CCM_CCOSR_CLK_OUT_SEL) #define BS_CCM_CCOSR_CKOL_EN 7 #define BM_CCM_CCOSR_CKOL_EN \ BIT32(BS_CCM_CCOSR_CKOL_EN) #define BS_CCM_CCOSR_CKOL_DIV 4 #define BM_CCM_CCOSR_CKOL_DIV \ SHIFT_U32(0x7, BS_CCM_CCOSR_CKOL_DIV) #define BS_CCM_CCOSR_CKOL_SEL 0 #define BM_CCM_CCOSR_CKOL_SEL \ SHIFT_U32(0xF, BS_CCM_CCOSR_CKOL_SEL) /* Define the bits in registers CGPR */ #define BS_CCM_CGPR_INT_MEM_CLK_LPM 17 #define BM_CCM_CGPR_INT_MEM_CLK_LPM \ BIT32(BS_CCM_CGPR_INT_MEM_CLK_LPM) #define BS_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE 4 #define BM_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE \ BIT32(BS_CCM_CGPR_EFUSE_PROG_SUPPLY_GATE) #define BS_CCM_CGPR_MMDC_EXT_CLK_DIS 2 #define BM_CCM_CGPR_MMDC_EXT_CLK_DIS \ BIT32(BS_CCM_CGPR_MMDC_EXT_CLK_DIS) #define BS_CCM_CGPR_PMIC_DELAY_SCALER 0 #define BM_CCM_CGPR_PMIC_DELAY_SCALER \ BIT32(BS_CCM_CGPR_PMIC_DELAY_SCALER) /* Define the bits in registers CCGRx */ #define BS_CCM_CCGR0_AIPS_TZ1 0 #define BM_CCM_CCGR0_AIPS_TZ1 \ SHIFT_U32(3, BS_CCM_CCGR0_AIPS_TZ1) #define BS_CCM_CCGR0_AIPS_TZ2 2 #define BM_CCM_CCGR0_AIPS_TZ2 \ SHIFT_U32(3, BS_CCM_CCGR0_AIPS_TZ2) #define BS_CCM_CCGR0_APBHDMA 4 #define BM_CCM_CCGR0_APBHDMA \ SHIFT_U32(3, BS_CCM_CCGR0_APBHDMA) #define BS_CCM_CCGR0_ASRC 6 #define BM_CCM_CCGR0_ASRC \ SHIFT_U32(3, BS_CCM_CCGR0_ASRC) #define BS_CCM_CCGR0_CAAM_SECURE_MEM 8 #define BM_CCM_CCGR0_CAAM_SECURE_MEM \ SHIFT_U32(3, BS_CCM_CCGR0_CAAM_SECURE_MEM) #define BS_CCM_CCGR0_CAAM_WRAPPER_ACLK 10 #define BM_CCM_CCGR0_CAAM_WRAPPER_ACLK \ SHIFT_U32(3, BS_CCM_CCGR0_CAAM_WRAPPER_ACLK) #define BS_CCM_CCGR0_CAAM_WRAPPER_IPG 12 #define BM_CCM_CCGR0_CAAM_WRAPPER_IPG \ SHIFT_U32(3, BS_CCM_CCGR0_CAAM_WRAPPER_IPG) #define BS_CCM_CCGR0_CAN1 14 #define BM_CCM_CCGR0_CAN1 SHIFT_U32(3, BS_CCM_CCGR0_CAN1) #define BS_CCM_CCGR0_CAN1_SERIAL 16 #define BM_CCM_CCGR0_CAN1_SERIAL \ SHIFT_U32(3, BS_CCM_CCGR0_CAN1_SERIAL) #define BS_CCM_CCGR0_CAN2 18 #define BM_CCM_CCGR0_CAN2 SHIFT_U32(3, BS_CCM_CCGR0_CAN2) #define BS_CCM_CCGR0_CAN2_SERIAL 20 #define BM_CCM_CCGR0_CAN2_SERIAL \ SHIFT_U32(3, BS_CCM_CCGR0_CAN2_SERIAL) #define BS_CCM_CCGR0_CHEETAH_DBG_CLK 22 #define BM_CCM_CCGR0_CHEETAH_DBG_CLK \ SHIFT_U32(3, BS_CCM_CCGR0_CHEETAH_DBG_CLK) #define BS_CCM_CCGR0_DCIC1 24 #define BM_CCM_CCGR0_DCIC1 SHIFT_U32(3, BS_CCM_CCGR0_DCIC1) #define BS_CCM_CCGR0_DCIC2 26 #define BM_CCM_CCGR0_DCIC2 SHIFT_U32(3, BS_CCM_CCGR0_DCIC2) #define BS_CCM_CCGR0_DTCP 28 #define BM_CCM_CCGR0_DTCP SHIFT_U32(3, BS_CCM_CCGR0_DTCP) #define BS_CCM_CCGR1_ECSPI1S 0 #define BM_CCM_CCGR1_ECSPI1S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI1S) #define BS_CCM_CCGR1_ECSPI2S 2 #define BM_CCM_CCGR1_ECSPI2S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI2S) #define BS_CCM_CCGR1_ECSPI3S 4 #define BM_CCM_CCGR1_ECSPI3S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI3S) #define BS_CCM_CCGR1_ECSPI4S 6 #define BM_CCM_CCGR1_ECSPI4S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI4S) #define BS_CCM_CCGR1_ECSPI5S 8 #define BM_CCM_CCGR1_ECSPI5S SHIFT_U32(3, BS_CCM_CCGR1_ECSPI5S) #define BS_CCM_CCGR1_ENET_CLK_ENABLE 10 #define BM_CCM_CCGR1_ENET_CLK_ENABLE \ (3 << BS_CCM_CCGR1_ENET_CLK_ENABLE) #define BS_CCM_CCGR1_EPIT1S 12 #define BM_CCM_CCGR1_EPIT1S SHIFT_U32(3, BS_CCM_CCGR1_EPIT1S) #define BS_CCM_CCGR1_EPIT2S 14 #define BM_CCM_CCGR1_EPIT2S SHIFT_U32(3, BS_CCM_CCGR1_EPIT2S) #define BS_CCM_CCGR1_ESAIS 16 #define BM_CCM_CCGR1_ESAIS SHIFT_U32(3, BS_CCM_CCGR1_ESAIS) #define BS_CCM_CCGR1_GPT_BUS 20 #define BM_CCM_CCGR1_GPT_BUS SHIFT_U32(3, BS_CCM_CCGR1_GPT_BUS) #define BS_CCM_CCGR1_GPT_SERIAL 22 #define BM_CCM_CCGR1_GPT_SERIAL SHIFT_U32(3, BS_CCM_CCGR1_GPT_SERIAL) #define BS_CCM_CCGR1_GPU2D 24 #define BM_CCM_CCGR1_GPU2D SHIFT_U32(3, BS_CCM_CCGR1_GPU2D) #define BS_CCM_CCGR1_GPU3D 26 #define BM_CCM_CCGR1_GPU3D SHIFT_U32(3, BS_CCM_CCGR1_GPU3D) #define BS_CCM_CCGR2_HDMI_TX_IAHBCLK 0 #define BM_CCM_CCGR2_HDMI_TX_IAHBCLK \ SHIFT_U32(3, BS_CCM_CCGR2_HDMI_TX_IAHBCLK) #define BS_CCM_CCGR2_HDMI_TX_ISFRCLK 4 #define BM_CCM_CCGR2_HDMI_TX_ISFRCLK \ SHIFT_U32(3, BS_CCM_CCGR2_HDMI_TX_ISFRCLK) #define BS_CCM_CCGR2_I2C1_SERIAL 6 #define BM_CCM_CCGR2_I2C1_SERIAL SHIFT_U32(3, BS_CCM_CCGR2_I2C1_SERIAL) #define BS_CCM_CCGR2_I2C2_SERIAL 8 #define BM_CCM_CCGR2_I2C2_SERIAL SHIFT_U32(3, BS_CCM_CCGR2_I2C2_SERIAL) #define BS_CCM_CCGR2_I2C3_SERIAL 10 #define BM_CCM_CCGR2_I2C3_SERIAL SHIFT_U32(3, BS_CCM_CCGR2_I2C3_SERIAL) #define BS_CCM_CCGR2_OCOTP_CTRL 12 #define BM_CCM_CCGR2_OCOTP_CTRL SHIFT_U32(3, BS_CCM_CCGR2_OCOTP_CTRL) #define BS_CCM_CCGR2_IOMUX_IPT_CLK_IO 14 #define BM_CCM_CCGR2_IOMUX_IPT_CLK_IO \ SHIFT_U32(3, BS_CCM_CCGR2_IOMUX_IPT_CLK_IO) #define BS_CCM_CCGR2_IPMUX1 16 #define BM_CCM_CCGR2_IPMUX1 SHIFT_U32(3, BS_CCM_CCGR2_IPMUX1) #define BS_CCM_CCGR2_IPMUX2 18 #define BM_CCM_CCGR2_IPMUX2 SHIFT_U32(3, BS_CCM_CCGR2_IPMUX2) #define BS_CCM_CCGR2_IPMUX3 20 #define BM_CCM_CCGR2_IPMUX3 SHIFT_U32(3, BS_CCM_CCGR2_IPMUX3) #define BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS 22 #define BM_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS \ SHIFT_U32(3, BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC1_IPGS) #define BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG 24 #define BM_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG \ SHIFT_U32(3, BS_CCM_CCGR2_IPSYNC_IP2APB_TZASC2_IPG) #define BS_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK 26 #define BM_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK \ SHIFT_U32(3, BS_CCM_CCGR2_IPSYNC_VDOA_IPG_MASTER_CLK) #define BS_CCM_CCGR3_IPU1_IPU 0 #define BM_CCM_CCGR3_IPU1_IPU SHIFT_U32(3, BS_CCM_CCGR3_IPU1_IPU) #define BS_CCM_CCGR3_IPU1_IPU_DI0 2 #define BM_CCM_CCGR3_IPU1_IPU_DI0 SHIFT_U32(3, BS_CCM_CCGR3_IPU1_IPU_DI0) #define BS_CCM_CCGR3_IPU1_IPU_DI1 4 #define BM_CCM_CCGR3_IPU1_IPU_DI1 SHIFT_U32(3, BS_CCM_CCGR3_IPU1_IPU_DI1) #define BS_CCM_CCGR3_IPU2_IPU 6 #define BM_CCM_CCGR3_IPU2_IPU SHIFT_U32(3, BS_CCM_CCGR3_IPU2_IPU) #define BS_CCM_CCGR3_IPU2_IPU_DI0 8 #define BM_CCM_CCGR3_IPU2_IPU_DI0 SHIFT_U32(3, BS_CCM_CCGR3_IPU2_IPU_DI0) #define BS_CCM_CCGR3_IPU2_IPU_DI1 10 #define BM_CCM_CCGR3_IPU2_IPU_DI1 SHIFT_U32(3, BS_CCM_CCGR3_IPU2_IPU_DI1) #define BS_CCM_CCGR3_LDB_DI0 12 #define BM_CCM_CCGR3_LDB_DI0 SHIFT_U32(3, BS_CCM_CCGR3_LDB_DI0) #define BS_CCM_CCGR3_LDB_DI1 14 #define BM_CCM_CCGR3_LDB_DI1 SHIFT_U32(3, BS_CCM_CCGR3_LDB_DI1) #define BS_CCM_CCGR3_MIPI_CORE_CFG 16 #define BM_CCM_CCGR3_MIPI_CORE_CFG \ SHIFT_U32(3, BS_CCM_CCGR3_MIPI_CORE_CFG) #define BS_CCM_CCGR3_MLB 18 #define BM_CCM_CCGR3_MLB SHIFT_U32(3, BS_CCM_CCGR3_MLB) #define BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0 20 #define BM_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0 \ SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P0) #define BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1 22 #define BM_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1 \ SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_ACLK_FAST_CORE_P1) #define BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0 24 #define BM_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0 \ SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P0) #define BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1 26 #define BM_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1 \ SHIFT_U32(3, BS_CCM_CCGR3_MMDC_CORE_IPG_CLK_P1) #define BS_CCM_CCGR3_OCRAM 28 #define BM_CCM_CCGR3_OCRAM SHIFT_U32(3, BS_CCM_CCGR3_OCRAM) #define BS_CCM_CCGR3_OPENVGAXICLK 30 #define BM_CCM_CCGR3_OPENVGAXICLK \ SHIFT_U32(3, BS_CCM_CCGR3_OPENVGAXICLK) #define BS_CCM_CCGR4_PCIE 0 #define BM_CCM_CCGR4_PCIE SHIFT_U32(3, BS_CCM_CCGR4_PCIE) #define BS_CCM_CCGR4_PL301_MX6QFAST1_S133 8 #define BM_CCM_CCGR4_PL301_MX6QFAST1_S133 \ SHIFT_U32(3, BS_CCM_CCGR4_PL301_MX6QFAST1_S133) #define BS_CCM_CCGR4_PL301_MX6QPER1_BCH 12 #define BM_CCM_CCGR4_PL301_MX6QPER1_BCH \ SHIFT_U32(3, BS_CCM_CCGR4_PL301_MX6QPER1_BCH) #define BS_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE 14 #define BM_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE \ SHIFT_U32(3, BS_CCM_CCGR4_PL301_MX6QPER2_MAINCLK_ENABLE) #define BS_CCM_CCGR4_PWM1 16 #define BM_CCM_CCGR4_PWM1 \ SHIFT_U32(3, BS_CCM_CCGR4_PWM1) #define BS_CCM_CCGR4_PWM2 18 #define BM_CCM_CCGR4_PWM2 \ SHIFT_U32(3, BS_CCM_CCGR4_PWM2) #define BS_CCM_CCGR4_PWM3 20 #define BM_CCM_CCGR4_PWM3 \ SHIFT_U32(3, BS_CCM_CCGR4_PWM3) #define BS_CCM_CCGR4_PWM4 22 #define BM_CCM_CCGR4_PWM4 \ SHIFT_U32(3, BS_CCM_CCGR4_PWM4) #define BS_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB 24 #define BM_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB \ SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_BCH_INPUT_APB) #define BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH 26 #define BM_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH \ SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_BCH) #define BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO 28 #define BM_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO \ SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO) #define BS_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB 30 #define BM_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB \ SHIFT_U32(3, BS_CCM_CCGR4_RAWNAND_U_GPMI_INPUT_APB) #define BS_CCM_CCGR5_ROM 0 #define BM_CCM_CCGR5_ROM SHIFT_U32(3, BS_CCM_CCGR5_ROM) #define BS_CCM_CCGR5_SATA 4 #define BM_CCM_CCGR5_SATA SHIFT_U32(3, BS_CCM_CCGR5_SATA) #define BS_CCM_CCGR5_SDMA 6 #define BM_CCM_CCGR5_SDMA SHIFT_U32(3, BS_CCM_CCGR5_SDMA) #define BS_CCM_CCGR5_SPBA 12 #define BM_CCM_CCGR5_SPBA SHIFT_U32(3, BS_CCM_CCGR5_SPBA) #define BS_CCM_CCGR5_SPDIF 14 #define BM_CCM_CCGR5_SPDIF SHIFT_U32(3, BS_CCM_CCGR5_SPDIF) #define BS_CCM_CCGR5_SSI1 18 #define BM_CCM_CCGR5_SSI1 SHIFT_U32(3, BS_CCM_CCGR5_SSI1) #define BS_CCM_CCGR5_SSI2 20 #define BM_CCM_CCGR5_SSI2 SHIFT_U32(3, BS_CCM_CCGR5_SSI2) #define BS_CCM_CCGR5_SSI3 22 #define BM_CCM_CCGR5_SSI3 SHIFT_U32(3, BS_CCM_CCGR5_SSI3) #define BS_CCM_CCGR5_UART 24 #define BM_CCM_CCGR5_UART SHIFT_U32(3, BS_CCM_CCGR5_UART) #define BS_CCM_CCGR5_UART_SERIAL 26 #define BM_CCM_CCGR5_UART_SERIAL SHIFT_U32(3, BS_CCM_CCGR5_UART_SERIAL) #define BS_CCM_CCGR6_USBOH3 0 #define BM_CCM_CCGR6_USBOH3 SHIFT_U32(3, BS_CCM_CCGR6_USBOH3) #define BS_CCM_CCGR6_USDHC1 2 #define BM_CCM_CCGR6_USDHC1 SHIFT_U32(3, BS_CCM_CCGR6_USDHC1) #define BS_CCM_CCGR6_USDHC2 4 #define BM_CCM_CCGR6_USDHC2 SHIFT_U32(3, BS_CCM_CCGR6_USDHC2) #define BS_CCM_CCGR6_USDHC3 6 #define BM_CCM_CCGR6_USDHC3 SHIFT_U32(3, BS_CCM_CCGR6_USDHC3) #define BS_CCM_CCGR6_USDHC4 8 #define BM_CCM_CCGR6_USDHC4 SHIFT_U32(3, BS_CCM_CCGR6_USDHC4) #define BS_CCM_CCGR6_EMI_SLOW 10 #define BM_CCM_CCGR6_EMI_SLOW SHIFT_U32(3, BS_CCM_CCGR6_EMI_SLOW) #define BS_CCM_CCGR6_VDOAXICLK 12 #define BM_CCM_CCGR6_VDOAXICLK SHIFT_U32(3, BS_CCM_CCGR6_VDOAXICLK) #define BS_CCM_CCGR6_I2C4_SERIAL 24 #define BM_CCM_CCGR6_I2C4_SERIAL SHIFT_U32(3, BS_CCM_CCGR6_I2C4_SERIAL) /* * Define Analog Macros and common bits */ #define BS_CCM_ANALOG_PLL_LOCK 31 #define BM_CCM_ANALOG_PLL_LOCK \ BIT32(BS_CCM_ANALOG_PLL_LOCK) #define BS_CCM_ANALOG_PLL_BYPASS 16 #define BM_CCM_ANALOG_PLL_BYPASS \ BIT32(BS_CCM_ANALOG_PLL_BYPASS) #define BS_CCM_ANALOG_PLL_BYPASS_CLK_SRC 14 #define BM_CCM_ANALOG_PLL_BYPASS_CLK_SRC \ SHIFT_U32(0x3, BS_CCM_ANALOG_PLL_BYPASS_CLK_SRC) #define CCM_ANALOG_PLL_BYPASS_CLK_SRC(clk) \ (SHIFT_U32(clk, BS_CCM_ANALOG_PLL_BYPASS_CLK_SRC) & \ BM_CCM_ANALOG_PLL_BYPASS_CLK_SRC) #define CCM_ANALOG_PLL_BYPASS_CLK_SRC_CLK24M 0x0 #define CCM_ANALOG_PLL_BYPASS_CLK_SRC_CLK1 0x1 #define CCM_ANALOG_PLL_BYPASS_CLK_SRC_CLK2 0x2 #define CCM_ANALOG_PLL_BYPASS_CLK_SRC_XOR 0x3 #define BS_CCM_ANALOG_PLL_ENABLE 13 #define BM_CCM_ANALOG_PLL_ENABLE BIT32(BS_CCM_ANALOG_PLL_ENABLE) #define BS_CCM_ANALOG_PLL_POWERDOWN 12 #define BM_CCM_ANALOG_PLL_POWERDOWN BIT32(BS_CCM_ANALOG_PLL_POWERDOWN) #define BS_CCM_ANALOG_PLL_DIV_SELECT 0 /* * Specific Analog bits definition */ #define BS_CCM_ANALOG_PLL_ARM_PLL_SEL 19 #define BM_CCM_ANALOG_PLL_ARM_PLL_SEL BIT32(BS_CCM_ANALOG_PLL_ARM_PLL_SEL) #define BS_CCM_ANALOG_PLL_ARM_LVDS_24MHZ_SEL 18 #define BM_CCM_ANALOG_PLL_ARM_LVDS_24MHZ_SEL \ BIT32(BS_CCM_ANALOG_PLL_ARM_LVDS_24MHZ_SEL) #define BS_CCM_ANALOG_PLL_ARM_LVDS_SEL 17 #define BM_CCM_ANALOG_PLL_ARM_LVDS_SEL \ BIT32(BS_CCM_ANALOG_PLL_ARM_LVDS_SEL) #define BM_CCM_ANALOG_PLL_ARM_DIV_SELECT \ SHIFT_U32(0x7F, BS_CCM_ANALOG_PLL_DIV_SELECT) #endif /* __IMX6_CRM_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx6-dcp.h000066400000000000000000000067351464416617300233500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 NXP */ #ifndef __IMX6_DCP_H__ #define __IMX6_DCP_H__ /* DCP base address */ #ifdef CFG_MX6ULL #define DCP_BASE 0x2280000 #endif #if defined(CFG_MX6SL) || defined(CFG_MX6SLL) #define DCP_BASE 0x20FC000 #endif /* DCP registers address offset */ #define DCP_CTRL 0x00 #define DCP_CTRL_SET 0x04 #define DCP_CTRL_CLR 0x08 #define DCP_STAT 0x10 #define DCP_STAT_CLR 0x18 #define DCP_CHANNELCTRL 0x20 #define DCP_CAPABILITY0 0x30 #define DCP_CAPABILITY1 0x40 #define DCP_CONTEXT 0x50 #define DCP_KEY 0x60 #define DCP_KEYDATA 0x70 #define DCP_PACKET0 0x80 #define DCP_PACKET1 0x90 #define DCP_PACKET2 0xA0 #define DCP_PACKET3 0xB0 #define DCP_PACKET4 0xC0 #define DCP_PACKET5 0xD0 #define DCP_PACKET6 0xE0 #define DCP_CH_N_CMDPTR(n) (0x100 + (n) * 0x40) #define DCP_CH_N_SEMA(n) (0x110 + (n) * 0x40) #define DCP_CH_N_STAT(n) (0x120 + (n) * 0x40) #define DCP_CHOCMDPTR 0x100 #define DCP_CH0SEMA 0x110 #define DCP_CH0STAT 0x120 #define DCP_CH1CMDPTR 0x140 #define DCP_CH2CMDPTR 0x180 #define DCP_CH3CMDPTR 0x1C0 /* DCP CHANNELCTRL register configuration */ #define DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK GENMASK_32(7, 0) #define DCP_STAT_CLEAR GENMASK_32(31, 0) #define DCP_CH_STAT_ERROR_MASK GENMASK_32(23, 0) /* DCP CTRL register configuration */ #define DCP_CTRL_SFTRST BIT32(31) #define DCP_CTRL_CLKGATE BIT32(30) #define DCP_CTRL_GATHER_RESIDUAL_WRITES BIT32(23) #define DCP_CTRL_ENABLE_CONTEXT_CACHING BIT32(22) #define DCP_CTRL_ENABLE_CONTEXT_SWITCHING BIT32(21) #define DCP_CTRL_CH3_INTERRUPT_ENABLE BIT32(3) #define DCP_CTRL_CH2_INTERRUPT_ENABLE BIT32(2) #define DCP_CTRL_CH1_INTERRUPT_ENABLE BIT32(1) #define DCP_CTRL_CH0_INTERRUPT_ENABLE BIT32(0) /* DCP CAPABILITY0 register configuration */ #define DCP_CAPABILITY0_DISABLE_UNIQUE_KEY BIT32(29) /* Work Packet control0 configuration */ #define DCP_CONTROL0_OUTPUT_WORDSWAP BIT32(23) #define DCP_CONTROL0_OUTPUT_BYTESWAP BIT32(22) #define DCP_CONTROL0_INPUT_WORDSWAP BIT32(21) #define DCP_CONTROL0_INPUT_BYTESWAP BIT32(20) #define DCP_CONTROL0_KEY_WORDSWAP BIT32(19) #define DCP_CONTROL0_KEY_BYTESWA BIT32(18) #define DCP_CONTROL0_TEST_SEMA_IRQ BIT32(17) #define DCP_CONTROL0_CONSTANT_FILL BIT32(16) #define DCP_CONTROL0_HASH_OUTPUT BIT32(15) #define DCP_CONTROL0_HASH_CHECK BIT32(14) #define DCP_CONTROL0_HASH_TERM BIT32(13) #define DCP_CONTROL0_HASH_INIT BIT32(12) #define DCP_CONTROL0_PAYLOAD_KEY BIT32(11) #define DCP_CONTROL0_OTP_KEY BIT32(10) #define DCP_CONTROL0_CIPHER_INIT BIT32(9) #define DCP_CONTROL0_CIPHER_ENCRYPT BIT32(8) #define DCP_CONTROL0_ENABLE_BLIT BIT32(7) #define DCP_CONTROL0_ENABLE_HASH BIT32(6) #define DCP_CONTROL0_ENABLE_CIPHER BIT32(5) #define DCP_CONTROL0_ENABLE_MEMCOPY BIT32(4) #define DCP_CONTROL0_CHAIN_CONTINUOUS BIT32(3) #define DCP_CONTROL0_CHAIN BIT32(2) #define DCP_CONTROL0_DECR_SEMAPHORE BIT32(1) #define DCP_CONTROL0_INTERRUPT_ENABLE BIT32(0) /* Work Packet control1 configuration */ #define DCP_CONTROL1_HASH_SELECT_SHA256 SHIFT_U32(2, 16) #define DCP_CONTROL1_HASH_SELECT_CRC32 BIT32(16) #define DCP_CONTROL1_HASH_SELECT_SHA1 SHIFT_U32(0, 16) #define DCP_CONTROL1_CIPHER_MODE_CBC BIT32(4) #define DCP_CONTROL1_CIPHER_MODE_ECB SHIFT_U32(0, 4) #define DCP_CONTROL1_CIPHER_SELECT_AES128 0 #define DCP_CONTROL1_KEY_SELECT_OTP_CRYPTO SHIFT_U32(0xfe, 8) #endif /* __IMX6_DCP_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx6.h000066400000000000000000000125171464416617300225770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * Copyright 2017-2020 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __IMX6_H__ #define __IMX6_H__ #include #include #define UART1_BASE 0x2020000 #define IOMUXC_BASE 0x020E0000 #define IOMUXC_SIZE 0x4000 #define IOMUXC_GPR_BASE 0x020E4000 #define SRC_BASE 0x020D8000 #define SRC_SIZE 0x4000 #define CCM_BASE 0x020C4000 #define CCM_SIZE 0x4000 #define ANATOP_BASE 0x020C8000 #define ANATOP_SIZE 0x1000 #define SNVS_BASE 0x020CC000 #define SNVS_SIZE 0x4000 #define GPC_BASE 0x020DC000 #define GPC_SIZE 0x4000 #define WDOG_BASE 0x020BC000 #define CSU_BASE 0x021C0000 #define SEMA4_BASE 0x02290000 #define SEMA4_SIZE 0x4000 #define MMDC_P0_BASE 0x021B0000 #define MMDC_P0_SIZE 0x4000 #define MMDC_P1_BASE 0x021B4000 #define MMDC_P1_SIZE 0x4000 #define TZASC_BASE 0x21D0000 #define TZASC_SIZE 0x4000 #define TZASC2_BASE 0x21D4000 #define UART2_BASE 0x021E8000 #define UART3_BASE 0x021EC000 #define UART4_BASE 0x021F0000 #define UART5_BASE 0x021F4000 #define AIPS1_BASE 0x02000000 #define AIPS1_SIZE 0x100000 #define AIPS2_BASE 0x02100000 #define AIPS2_SIZE 0x100000 #define AIPS3_BASE 0x02200000 #define AIPS3_SIZE 0x100000 #if defined(CFG_MX6ULL) #define RNGB_BASE 0x02284000 #elif defined(CFG_MX6SL) || defined(CFG_MX6SLL) #define RNGB_BASE 0x021b4000 #endif #define SCU_BASE 0x00A00000 #define PL310_BASE 0x00A02000 #define IRAM_BASE 0x00900000 #define OCOTP_BASE 0x021BC000 #define OCOTP_SIZE 0x4000 #define GIC_BASE 0x00A00000 #define GICD_OFFSET 0x1000 #if defined(CFG_MX6UL) || defined(CFG_MX6ULL) #define GICC_OFFSET 0x2000 #define UART6_BASE 0x021FC000 #define UART7_BASE 0x02018000 /* No CAAM on i.MX6ULL */ #define CAAM_BASE 0x02140000 #else #define GICC_OFFSET 0x100 #define CAAM_BASE 0x02100000 #endif #define CAAM_SIZE 0x40000 #define GIC_CPU_BASE (GIC_BASE + GICC_OFFSET) #define GIC_DIST_BASE (GIC_BASE + GICD_OFFSET) /* Central Security Unit register values */ #define CSU_CSL_START 0x0 #define CSU_CSL_END 0xA0 #define CSU_ACCESS_ALL 0x00FF00FF #define CSU_SETTING_LOCK 0x01000100 #define CSU_SA 0x218 /* Used in suspend/resume and low power idle */ #define MX6Q_SRC_GPR1 0x20 #define MX6Q_SRC_GPR2 0x24 #define MX6Q_MMDC_MISC 0x18 #define MX6Q_MMDC_MAPSR 0x404 #define MX6Q_MMDC_MPDGCTRL0 0x83c #define MX6Q_GPC_IMR1 0x08 #define MX6Q_GPC_IMR2 0x0c #define MX6Q_GPC_IMR3 0x10 #define MX6Q_GPC_IMR4 0x14 #define MX6Q_CCM_CCR 0x0 #define MX6Q_ANATOP_CORE 0x140 #define IOMUXC_GPR9_OFFSET 0x24 #define IOMUXC_GPR10_OFFSET 0x28 #define IOMUXC_GPR10_OCRAM_TZ_ADDR_OFFSET 5 #define IOMUXC_GPR10_OCRAM_TZ_ADDR_MASK GENMASK_32(10, 5) #define IOMUXC_GPR10_OCRAM_TZ_EN_OFFSET 4 #define IOMUXC_GPR10_OCRAM_TZ_EN_MASK GENMASK_32(4, 4) #define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_OFFSET 20 #define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_MASK GENMASK_32(20, 20) #define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_OFFSET 21 #define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_MASK GENMASK_32(26, 21) #define IOMUXC_GPR10_OCRAM_TZ_ADDR_OFFSET_6UL 11 #define IOMUXC_GPR10_OCRAM_TZ_ADDR_MASK_6UL GENMASK_32(15, 11) #define IOMUXC_GPR10_OCRAM_TZ_EN_OFFSET_6UL 10 #define IOMUXC_GPR10_OCRAM_TZ_EN_MASK_6UL GENMASK_32(10, 10) #define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_OFFSET_6UL 26 #define IOMUXC_GPR10_OCRAM_TZ_EN_LOCK_MASK_6UL GENMASK_32(26, 26) #define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_OFFSET_6UL (27) #define IOMUXC_GPR10_OCRAM_TZ_ADDR_LOCK_MASK_6UL GENMASK_32(31, 27) #ifdef CFG_MX6SL #define DIGPROG_OFFSET 0x280 #else #define DIGPROG_OFFSET 0x260 #endif #if defined(CFG_MX6ULL) #define I2C1_BASE 0x021a0000 #define I2C2_BASE 0x021a4000 #define I2C3_BASE 0x021a8000 #define I2C4_BASE 0x021f8000 #define IOMUXC_I2C1_SCL_CFG_OFF 0x340 #define IOMUXC_I2C1_SDA_CFG_OFF 0x344 #define IOMUXC_I2C1_SCL_MUX_OFF 0xb4 #define IOMUXC_I2C1_SDA_MUX_OFF 0xb8 #define IOMUXC_I2C1_SCL_INP_OFF 0x5a4 #define IOMUXC_I2C1_SDA_INP_OFF 0x5a8 #endif #endif /* __IMX6_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx7-crm.h000066400000000000000000000070621464416617300233560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef __IMX7_CRM_H__ #define __IMX7_CRM_H__ /* * GPRx Registers */ #define CCM_GPR0 0x0 #define CCM_GPRx_OFFSET 0x10 #define CCM_GPRx(idx) (((idx) * CCM_GRPx_OFFSET) + CCM_GPR0) #define CCM_GPRx_SET(idx) (CCM_GPRx(idx) + 0x4) #define CCM_GPRx_CLR(idx) (CCM_GPRx(idx) + 0x8) #define CCM_GPRx_TOG(idx) (CCM_GPRx(idx) + 0xC) /* * PLL_CTRLx Registers (PLL Control) */ #define CCM_PLL_CTRL0 0x800 #define CCM_PLL_CTRLx_OFFSET 0x10 #define CCM_PLL_CTRLx(idx) (((idx) * CCM_PLL_CTRLx_OFFSET) + CCM_PLL_CTRL0) #define CCM_PLL_CTRLx_SET(idx) (CCM_PLL_CTRLx(idx) + 0x4) #define CCM_PLL_CTRLx_CLR(idx) (CCM_PLL_CTRLx(idx) + 0x8) #define CCM_PLL_CTRLx_TOG(idx) (CCM_PLL_CTRLx(idx) + 0xC) /* * CCGRx Registers (Clock Gating) */ #define CCM_CCGR0 0x4000 #define CCM_CCGRx_OFFSET 0x10 #define CCM_CCGRx(idx) (((idx) * CCM_CCGRx_OFFSET) + CCM_CCGR0) #define CCM_CCGRx_SET(idx) (CCM_CCGRx(idx) + 0x4) #define CCM_CCGRx_CLR(idx) (CCM_CCGRx(idx) + 0x8) #define CCM_CCGRx_TOG(idx) (CCM_CCGRx(idx) + 0xC) #define BS_CCM_CCGRx_SETTING(idx) ((idx) * 4) #define BM_CCM_CCGRx_SETTING(idx) \ SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_DISABLE(idx) \ SHIFT_U32(0, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_RUN(idx) \ BIT32(BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_RUN_WAIT(idx) \ SHIFT_U32(0x2, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_ALWAYS_ON(idx) \ SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) /* * TARGET_ROOTx Registers (Target) */ #define CCM_TARGET_ROOT0 0x8000 #define CCM_TARGET_ROOTx_OFFSET 0x80 #define CCM_TARGET_ROOTx(idx) \ (((idx) * CCM_TARGET_ROOTx_OFFSET) + CCM_TARGET_ROOT0) #define CCM_TARGET_ROOTx_SET(idx) (CCM_TARGET_ROOTx(idx) + 0x4) #define CCM_TARGET_ROOTx_CLR(idx) (CCM_TARGET_ROOTx(idx) + 0x8) #define CCM_TARGET_ROOTx_TOG(idx) (CCM_TARGET_ROOTx(idx) + 0xC) /* * MISC_ROOTx Registers (Miscellaneous) */ #define CCM_MISC_ROOT0 0x8010 #define CCM_MISC_ROOTx_OFFSET 0x80 #define CCM_MISC_ROOTx(idx) \ (((idx) * CCM_MISC_ROOTx_OFFSET) + CCM_MISC_ROOT0) #define CCM_MISC_ROOTx_SET(idx) (CCM_MISC_ROOTx(idx) + 0x4) #define CCM_MISC_ROOTx_CLR(idx) (CCM_MISC_ROOTx(idx) + 0x8) #define CCM_MISC_ROOTx_TOG(idx) (CCM_MISC_ROOTx(idx) + 0xC) /* * POST_ROOTx Registers (Post Divider) */ #define CCM_POST_ROOT0 0x8020 #define CCM_POST_ROOTx_OFFSET 0x80 #define CCM_POST_ROOTx(idx) \ (((idx) * CCM_POST_ROOTx_OFFSET) + CCM_POST_ROOT0) #define CCM_POST_ROOTx_SET(idx) (CCM_POST_ROOTx(idx) + 0x4) #define CCM_POST_ROOTx_CLR(idx) (CCM_POST_ROOTx(idx) + 0x8) #define CCM_POST_ROOTx_TOG(idx) (CCM_POST_ROOTx(idx) + 0xC) /* * PRE_ROOTx Registers (Pre Divider) */ #define CCM_PRE_ROOT0 0x8030 #define CCM_PRE_ROOTx_OFFSET 0x80 #define CCM_PRE_ROOTx(idx) \ (((idx) * CCM_PRE_ROOTx_OFFSET) + CCM_PRE_ROOT0) #define CCM_PRE_ROOTx_SET(idx) (CCM_PRE_ROOTx(idx) + 0x4) #define CCM_PRE_ROOTx_CLR(idx) (CCM_PRE_ROOTx(idx) + 0x8) #define CCM_PRE_ROOTx_TOG(idx) (CCM_PRE_ROOTx(idx) + 0xC) /* * ACCESS_CTRL_ROOTx Registers (Access Control) */ #define CCM_ACCESS_CTRL_ROOT0 0x8030 #define CCM_ACCESS_CTRL_ROOTx_OFFSET 0x80 #define CCM_ACCESS_CTRL_ROOTx(idx) \ (((idx) * CCM_ACCESS_CTRL_ROOTx_OFFSET) + CCM_ACCESS_CTRL_ROOT0) #define CCM_ACCESS_CTRL_ROOTx_SET(idx) (CCM_ACCESS_CTRL_ROOTx(idx) + 0x4) #define CCM_ACCESS_CTRL_ROOTx_CLR(idx) (CCM_ACCESS_CTRL_ROOTx(idx) + 0x8) #define CCM_ACCESS_CTRL_ROOTx_TOG(idx) (CCM_ACCESS_CTRL_ROOTx(idx) + 0xC) /* * Clock Domain ID */ #define CCM_CLOCK_DOMAIN_OCOTP 35 #define CCM_CLOCK_DOMAIN_CAAM 36 #endif /* __IMX7_CRM_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx7.h000066400000000000000000000041321464416617300225720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef __IMX7_H__ #define __IMX7_H__ #include #define GIC_BASE 0x31000000 #define GIC_SIZE 0x8000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define CAAM_BASE 0x30900000 #define CAAM_SIZE 0x40000 #define UART1_BASE 0x30860000 #define UART2_BASE 0x30890000 #define UART3_BASE 0x30880000 #define UART4_BASE 0x30A60000 #define UART5_BASE 0x30A70000 #define AIPS1_BASE 0x30000000 #define AIPS1_SIZE 0x400000 #define AIPS2_BASE 0x30400000 #define AIPS2_SIZE 0x400000 #define AIPS3_BASE 0x30800000 #define AIPS3_SIZE 0x400000 #define WDOG_BASE 0x30280000 #define LPSR_BASE 0x30270000 #define IOMUXC_BASE 0x30330000 #define IOMUXC_SIZE 0x4000 #define IOMUXC_GPR_BASE 0x30340000 #define OCOTP_BASE 0x30350000 #define OCOTP_SIZE 0x10000 #define ANATOP_BASE 0x30360000 #define SNVS_BASE 0x30370000 #define SNVS_SIZE 0x10000 #define CCM_BASE 0x30380000 #define CCM_SIZE 0x10000 #define SRC_BASE 0x30390000 #define SRC_SIZE 0x4000 #define GPC_BASE 0x303A0000 #define GPC_SIZE 0x4000 #define CSU_BASE 0x303E0000 #define TZASC_BASE 0x30780000 #define TZASC_SIZE 0x10000 #define DDRC_PHY_BASE 0x30790000 #define MMDC_P0_BASE 0x307A0000 #define DDRC_BASE 0x307A0000 #define IRAM_BASE 0x00900000 #define IRAM_S_BASE 0x00180000 #define CSU_CSL_START 0x0 #define CSU_CSL_END 0x100 #define CSU_ACCESS_ALL 0x00FF00FF #define CSU_SETTING_LOCK 0x01000100 #define CSU_SA 0x218 #define TRUSTZONE_OCRAM_START 0x180000 #define IOMUXC_GPR9_OFFSET 0x24 #define IOMUXC_GPR9_TZASC1_MUX_CONTROL_OFFSET 0 #define IOMUXC_GPR11_OFFSET 0x2C #define IOMUXC_GPR11_OCRAM_S_TZ_ADDR_OFFSET 11 #define IOMUXC_GPR11_OCRAM_S_TZ_ADDR_MASK GENMASK_32(13, 11) #define IOMUXC_GPR11_OCRAM_S_TZ_EN_OFFSET 10 #define IOMUXC_GPR11_OCRAM_S_TZ_EN_MASK GENMASK_32(10, 10) #define IOMUXC_GPR11_OCRAM_S_TZ_EN_LOCK_OFFSET 26 #define IOMUXC_GPR11_OCRAM_S_TZ_EN_LOCK_MASK GENMASK_32(26, 26) #define IOMUXC_GPR11_OCRAM_S_TZ_ADDR_LOCK_OFFSET GENMASK_32(29, 27) #define DIGPROG_OFFSET 0x800 #endif /* __IMX7_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx7ulp-crm.h000066400000000000000000000005011464416617300240660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef __IMX7ULP_CRM_H__ #define __IMX7ULP_CRM_H__ #include #define PCC_CGC_BIT_SHIFT 30 #define PCC_ENABLE_CLOCK BIT32(PCC_CGC_BIT_SHIFT) #define PCC_DISABLE_CLOCK BIT32(0) #define PCC_CAAM 0x90 #endif /* __IMX7ULP_CRM_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx7ulp.h000066400000000000000000000027551464416617300233240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef __IMX7ULP_H__ #define __IMX7ULP_H__ #include #define GIC_BASE 0x40020000 #define GIC_SIZE 0x8000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define AIPS0_BASE 0x40000000 #define AIPS0_SIZE 0x800000 #define AIPS1_BASE 0x40800000 #define AIPS1_SIZE 0x800000 #define M4_AIPS_BASE 0x41000000 #define M4_AIPS_SIZE 0x100000 #define M4_AIPS0_BASE 0x41000000 #define M4_AIPS0_SIZE 0x80000 #define M4_AIPS1_BASE 0x41080000 #define M4_AIPS1_SIZE 0x80000 #define GPIOC_BASE 0x400f0000 #define GPIOD_BASE 0x400f0040 #define GPIOE_BASE 0x400f0080 #define GPIOF_BASE 0x400f00c0 #define TPM5_BASE 0x40260000 #define WDOG_BASE 0x403d0000 #define WDOG_SIZE 0x10 #define SCG1_BASE 0x403e0000 #define PCC2_BASE 0x403f0000 #define PMC1_BASE 0x40400000 #define SMC1_BASE 0x40410000 #define MMDC_BASE 0x40ab0000 #define IOMUXC1_BASE 0x40ac0000 #define MMDC_IO_BASE 0x40ad0000 #define PCC3_BASE 0x40b30000 #define OCOTP_BASE 0x410A6000 #define OCOTP_SIZE 0x4000 #define PMC0_BASE 0x410a1000 #define SIM_BASE 0x410a3000 #define OCOTP_BASE 0x410A6000 #define OCOTP_SIZE 0x4000 #define CAAM_BASE 0x40240000 #define CAAM_SIZE 0x10000 #define UART4_BASE 0x402d0000 #define UART5_BASE 0x402e0000 #define UART6_BASE 0x40a60000 #define UART7_BASE 0x40a70000 #define IRAM_BASE 0x1FFFC000 #define IRAM_SIZE 0x4000 #define LP_OCRAM_START IRAM_BASE #endif /* __IMX7ULP_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx8m-crm.h000066400000000000000000000021301464416617300235230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 Foundries Ltd */ #ifndef __IMX8M_CRM_H #define __IMX8M_CRM_H /* CCGRx Registers (Clock Gating) */ #define CCM_CCGR0 0x4000 #define CCM_CCGRx_OFFSET 0x10 #define CCM_CCGRx(idx) (((idx) * CCM_CCGRx_OFFSET) + CCM_CCGR0) #define CCM_CCGRx_SET(idx) (CCM_CCGRx(idx) + 0x4) #define CCM_CCGRx_CLR(idx) (CCM_CCGRx(idx) + 0x8) #define CCM_CCGRx_TOG(idx) (CCM_CCGRx(idx) + 0xC) #define BS_CCM_CCGRx_SETTING(idx) ((idx) * 4) #define BM_CCM_CCGRx_SETTING(idx) \ SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_DISABLE(idx) \ SHIFT_U32(0, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_RUN(idx) \ BIT32(BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_RUN_WAIT(idx) \ SHIFT_U32(0x2, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCGRx_ALWAYS_ON(idx) \ SHIFT_U32(0x3, BS_CCM_CCGRx_SETTING(idx)) #define CCM_CCRG_I2C1 23 #define CCM_CCRG_I2C2 24 #define CCM_CCRG_I2C3 25 #define CCM_CCRG_I2C4 26 #define CCM_CCRG_OCOTP 34 #if defined(CFG_MX8MP) #define CCM_CCRG_I2C5 51 #define CCM_CCRG_I2C6 52 #endif #endif /* __IMX8M_CRM_H */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx8m.h000066400000000000000000000032361464416617300227540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP */ #ifndef __IMX8M_H__ #define __IMX8M_H__ #include #define GICD_BASE 0x38800000 #define GICR_BASE 0x38880000 #define UART1_BASE 0x30860000 #define UART2_BASE 0x30890000 #define UART3_BASE 0x30880000 #define UART4_BASE 0x30A60000 #define TZASC_BASE 0x32F80000 #define TZASC_SIZE 0x10000 #define CAAM_BASE 0x30900000 #define CAAM_SIZE 0x40000 #define CCM_BASE 0x30380000 #define CCM_SIZE 0x10000 #define ANATOP_BASE 0x30360000 #define IOMUXC_BASE 0x30330000 #define OCOTP_BASE 0x30350000 #define OCOTP_SIZE 0x10000 #define SNVS_BASE 0x30370000 #define SNVS_SIZE 0x10000 #define SECMEM_BASE 0x00100000 #define SECMEM_SIZE 0x8000 #ifdef CFG_MX8MQ #define DIGPROG_OFFSET 0x06c #define OCOTP_SW_INFO_B1 0x40 #define OCOTP_SW_MAGIC_B1 0xFF0055AA #endif #if defined(CFG_MX8MM) || defined(CFG_MX8MN) || defined(CFG_MX8MP) #define DIGPROG_OFFSET 0x800 #endif #if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MN) #define I2C1_BASE 0x30a20000 #define I2C2_BASE 0x30a30000 #define I2C3_BASE 0x30a40000 #define I2C4_BASE 0x30a50000 #define IOMUXC_I2C1_SCL_CFG_OFF 0x47C #define IOMUXC_I2C1_SDA_CFG_OFF 0x480 #define IOMUXC_I2C1_SCL_MUX_OFF 0x214 #define IOMUXC_I2C1_SDA_MUX_OFF 0x218 #endif #if defined(CFG_MX8MP) #define I2C1_BASE 0x30a20000 #define I2C2_BASE 0x30a30000 #define I2C3_BASE 0x30a40000 #define I2C4_BASE 0x30a50000 #define I2C5_BASE 0x30ad0000 #define I2C6_BASE 0x30ae0000 #define IOMUXC_I2C1_SCL_CFG_OFF 0x460 #define IOMUXC_I2C1_SDA_CFG_OFF 0x464 #define IOMUXC_I2C1_SCL_MUX_OFF 0x200 #define IOMUXC_I2C1_SDA_MUX_OFF 0x204 #endif #endif /* __IMX8M_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx8q.h000066400000000000000000000007441464416617300227610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP */ #ifndef __IMX8Q_H__ #define __IMX8Q_H__ #define GICD_BASE 0x51a00000 #define GICR_BASE 0x51b00000 #define UART0_BASE 0x5a060000 #define UART1_BASE 0x5a070000 #define UART2_BASE 0x5a080000 #define UART3_BASE 0x5a090000 #define UART4_BASE 0x5a0a0000 #define CAAM_BASE 0x31400000 #define CAAM_SIZE 0x40000 #define SC_IPC_BASE_SECURE 0x5d1b0000 #define SC_IPC_SIZE 0x10000 #endif /* __IMX8Q_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx8ulp-crm.h000066400000000000000000000004311464416617300240710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP */ #ifndef __IMX8ULP_CRM_H__ #define __IMX8ULP_CRM_H__ #include #define PCC_CGC_BIT_SHIFT 30 #define PCC_ENABLE_CLOCK BIT32(PCC_CGC_BIT_SHIFT) #define PCC_CAAM 0xB8 #endif /* __IMX8ULP_CRM_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx8ulp.h000066400000000000000000000011311464416617300233100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP */ #ifndef __IMX8ULP_H__ #define __IMX8ULP_H__ #include #define GICD_BASE 0x2d400000 #define GICR_BASE 0x2d440000 #define UART4_BASE 0x29390000 #define UART5_BASE 0x293a0000 #define CAAM_BASE 0x292e0000 #define CAAM_SIZE 0x10000 #define PCC3_BASE 0x292d0000 #define PCC3_SIZE 0x1000 #define AIPS3_BASE 0x29000000 #define AIPS3_SIZE 0x400000 #define SECMEM_BASE 0x00100000 #define SECMEM_SIZE 0x80000 #define MU_BASE 0x27020000 #define MU_SIZE 0x10000 #endif /* __IMX8ULP_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/registers/imx93.h000066400000000000000000000004361464416617300226620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __IMX93_H__ #define __IMX93_H__ #define GICD_BASE 0x48000000 #define GICR_BASE 0x48040000 #define UART1_BASE 0x44380000 #define MU_BASE 0x47520000 #define MU_SIZE 0x10000 #endif /* __IMX93_H__ */ optee_os-4.3.0/core/arch/arm/plat-imx/sm_platform_handler.c000066400000000000000000000027221464416617300237150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) Microsoft Corporation. All rights reserved. */ #include #include #include #include #include "imx_pl310.h" #define IMX_SIP_PL310_ENABLE 1 #define IMX_SIP_PL310_DISABLE 2 #define IMX_SIP_PL310_ENABLE_WRITEBACK 3 #define IMX_SIP_PL310_DISABLE_WRITEBACK 4 #define IMX_SIP_PL310_ENABLE_WFLZ 5 static enum sm_handler_ret imx_sip_handler(struct thread_smc_args *smc_args) { uint16_t sip_func = OPTEE_SMC_FUNC_NUM(smc_args->a0); switch (sip_func) { #ifdef CFG_PL310_SIP_PROTOCOL case IMX_SIP_PL310_ENABLE: smc_args->a0 = pl310_enable(); break; case IMX_SIP_PL310_DISABLE: smc_args->a0 = pl310_disable(); break; case IMX_SIP_PL310_ENABLE_WRITEBACK: smc_args->a0 = pl310_enable_writeback(); break; case IMX_SIP_PL310_DISABLE_WRITEBACK: smc_args->a0 = pl310_disable_writeback(); break; case IMX_SIP_PL310_ENABLE_WFLZ: smc_args->a0 = pl310_enable_wflz(); break; #endif default: EMSG("Invalid SIP function code: 0x%x", sip_func); smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; break; } return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) { uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); switch (smc_owner) { case OPTEE_SMC_OWNER_SIP: return imx_sip_handler((struct thread_smc_args *)nsec_r0); default: return SM_HANDLER_PENDING_SMC; } } optee_os-4.3.0/core/arch/arm/plat-imx/sub.mk000066400000000000000000000010061464416617300206450ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c imx-common.c srcs-$(CFG_PL310) += imx_pl310.c ifeq ($(CFG_PSCI_ARM32),y) $(call force,CFG_PM_ARM32,y) CFG_IMX_PM ?= y endif ifneq (,$(filter y, $(CFG_MX6Q) $(CFG_MX6QP) $(CFG_MX6D) $(CFG_MX6DL) \ $(CFG_MX6S) $(CFG_MX6SL) $(CFG_MX6SLL) $(CFG_MX6SX))) srcs-y += a9_plat_init.S srcs-$(CFG_SM_PLATFORM_HANDLER) += sm_platform_handler.c endif ifneq (,$(filter y, $(CFG_MX7) $(CFG_MX7ULP) $(CFG_MX6UL) $(CFG_MX6ULL))) srcs-y += a7_plat_init.S endif srcs-$(CFG_TZC380) += tzc380.c optee_os-4.3.0/core/arch/arm/plat-imx/tzc380.c000066400000000000000000000045021464416617300207260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Pengutronix * All rights reserved. * Copyright 2023 NXP * * Rouven Czerwinski */ #include #include #include #include #include #include #include #include /* * TZASC2_BASE is asserted non null when used. * This is needed to compile the code for i.MX6UL/L * and i.MX8MQ. */ #ifndef TZASC2_BASE #define TZASC2_BASE 0 #else register_phys_mem(MEM_AREA_IO_SEC, TZASC2_BASE, TZASC_SIZE); #endif register_phys_mem(MEM_AREA_IO_SEC, TZASC_BASE, TZASC_SIZE); static int imx_tzc_auto_configure(vaddr_t addr, vaddr_t rsize, uint32_t attr, uint8_t region) { vaddr_t addr_imx = 0; /* * On 8mscale platforms, the TZASC controller for the DRAM protection, * has the memory regions starting at address 0x0 instead of the DRAM * base address (0x40000000) */ if (IS_ENABLED(CFG_MX8M)) addr_imx = addr - CFG_DRAM_BASE; else addr_imx = addr; return tzc_auto_configure(addr_imx, rsize, attr, region); } static TEE_Result imx_configure_tzasc(void) { vaddr_t addr[2] = {0}; int end = 1; int i = 0; addr[0] = core_mmu_get_va(TZASC_BASE, MEM_AREA_IO_SEC, 1); if (IS_ENABLED(CFG_MX6Q) || IS_ENABLED(CFG_MX6D) || IS_ENABLED(CFG_MX6DL)) { assert(TZASC2_BASE != 0); addr[1] = core_mmu_get_va(TZASC2_BASE, MEM_AREA_IO_SEC, 1); end = 2; } for (i = 0; i < end; i++) { uint8_t region = 1; tzc_init(addr[i]); region = imx_tzc_auto_configure(CFG_DRAM_BASE, CFG_DDR_SIZE, TZC_ATTR_SP_NS_RW, region); region = imx_tzc_auto_configure(CFG_TZDRAM_START, CFG_TZDRAM_SIZE, TZC_ATTR_SP_S_RW, region); region = imx_tzc_auto_configure(CFG_SHMEM_START, CFG_SHMEM_SIZE, TZC_ATTR_SP_ALL, region); if (tzc_regions_lockdown() != TEE_SUCCESS) panic("Region lockdown failed!"); tzc_dump_state(); } return TEE_SUCCESS; } static TEE_Result pm_enter_resume(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *pm_handle __unused) { if (op == PM_OP_RESUME) return imx_configure_tzasc(); return TEE_SUCCESS; } static TEE_Result tzasc_init(void) { register_pm_driver_cb(pm_enter_resume, NULL, "imx-tzasc"); return imx_configure_tzasc(); } driver_init(tzasc_init); optee_os-4.3.0/core/arch/arm/plat-k3/000077500000000000000000000000001464416617300172465ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-k3/conf.mk000066400000000000000000000017441464416617300205320ustar00rootroot00000000000000CFG_WITH_STATS ?= y CFG_CRYPTO_WITH_CE ?= y CFG_CONSOLE_UART ?= 0 CFG_TZDRAM_START ?= 0x9e800000 CFG_TZDRAM_SIZE ?= 0x01400000 # 20MB CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00400000 # 4MB $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_8250_UART,y) $(call force,CFG_HWSUPP_MEM_PERM_PXN,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_GIC,y) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_K3_OTP_KEYWRITING,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) ifneq (,$(filter ${PLATFORM_FLAVOR},am65x)) $(call force,CFG_CORE_CLUSTER_SHIFT,1) endif ifneq (,$(filter ${PLATFORM_FLAVOR},am65x j721e j784s4 am64x am62x)) CFG_WITH_SOFTWARE_PRNG ?= n else $(call force,CFG_WITH_SOFTWARE_PRNG,y) endif ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) $(call force,CFG_SA2UL,y) CFG_HWRNG_QUALITY ?= 1024 CFG_HWRNG_PTA ?= y endif include core/arch/arm/cpu/cortex-armv8-0.mk optee_os-4.3.0/core/arch/arm/plat-k3/drivers/000077500000000000000000000000001464416617300207245ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-k3/drivers/sa2ul.c000066400000000000000000000106431464416617300221220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Texas Instruments K3 SA2UL Driver * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Andrew Davis */ #include #include #include #include #include #include #include #include #include #include #include #include "sa2ul.h" #define SA2UL_ES 0x0008 #define SA2UL_ES_TRNG BIT(3) #define SA2UL_EEC 0x1000 #define SA2UL_EEC_TRNG BIT(3) #define FW_ENABLE_REGION 0x0a #define FW_BACKGROUND_REGION BIT(8) #define FW_BIG_ARM_PRIVID 0x01 #define FW_TIFS_PRIVID 0xca #define FW_WILDCARD_PRIVID 0xc3 #define FW_SECURE_ONLY GENMASK_32(7, 0) #define FW_NON_SECURE GENMASK_32(15, 0) register_phys_mem_pgdir(MEM_AREA_IO_SEC, SA2UL_BASE, SA2UL_REG_SIZE); static TEE_Result sa2ul_init(void) { vaddr_t sa2ul = (vaddr_t)phys_to_virt(SA2UL_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); uint16_t fwl_id = SA2UL_TI_SCI_FW_ID; uint16_t sa2ul_region = SA2UL_TI_SCI_FW_RGN_ID; uint16_t rng_region = RNG_TI_SCI_FW_RGN_ID; uint8_t owner_index = OPTEE_HOST_ID; uint8_t owner_privid = 0; uint16_t owner_permission_bits = 0; uint32_t control = 0; uint32_t permissions[FWL_MAX_PRIVID_SLOTS] = { }; uint32_t num_perm = 0; uint64_t start_address = 0; uint64_t end_address = 0; uint32_t val = 0; TEE_Result result = TEE_SUCCESS; int ret = 0; if (SA2UL_TI_SCI_DEV_ID != -1) { /* Power on the SA2UL device */ ret = ti_sci_device_get(SA2UL_TI_SCI_DEV_ID); if (ret) { EMSG("Failed to get SA2UL device"); return TEE_ERROR_GENERIC; } } IMSG("Activated SA2UL device"); /* Try to claim the SA2UL firewall for ourselves */ ret = ti_sci_change_fwl_owner(fwl_id, sa2ul_region, owner_index, &owner_privid, &owner_permission_bits); if (ret) { /* * This is not fatal, it just means we are on an HS device * where the DMSC already owns the SA2UL. On GP we need * to do additional setup for access permissions below. */ DMSG("Could not change SA2UL firewall owner"); } else { IMSG("Fixing SA2UL firewall owner for GP device"); /* Get current SA2UL firewall configuration */ ret = ti_sci_get_fwl_region(fwl_id, sa2ul_region, 1, &control, permissions, &start_address, &end_address); if (ret) { EMSG("Could not get firewall region information"); return TEE_ERROR_GENERIC; } /* Modify SA2UL firewall to allow all others access*/ control = FW_BACKGROUND_REGION | FW_ENABLE_REGION; permissions[0] = (FW_WILDCARD_PRIVID << 16) | FW_NON_SECURE; ret = ti_sci_set_fwl_region(fwl_id, sa2ul_region, 1, control, permissions, 0x0, UINT32_MAX); if (ret) { EMSG("Could not set firewall region information"); return TEE_ERROR_GENERIC; } } /* Claim the TRNG firewall for ourselves */ ret = ti_sci_change_fwl_owner(fwl_id, rng_region, owner_index, &owner_privid, &owner_permission_bits); if (ret) { EMSG("Could not change TRNG firewall owner"); return TEE_ERROR_GENERIC; } /* Get current TRNG firewall configuration */ ret = ti_sci_get_fwl_region(fwl_id, rng_region, 1, &control, permissions, &start_address, &end_address); if (ret) { EMSG("Could not get firewall region information"); return TEE_ERROR_GENERIC; } /* Modify TRNG firewall to block all others access */ control = FW_ENABLE_REGION; start_address = RNG_BASE; end_address = RNG_BASE + RNG_REG_SIZE - 1; permissions[num_perm++] = (FW_BIG_ARM_PRIVID << 16) | FW_SECURE_ONLY; #if defined(PLATFORM_FLAVOR_am62x) permissions[num_perm++] = (FW_TIFS_PRIVID << 16) | FW_NON_SECURE; #endif ret = ti_sci_set_fwl_region(fwl_id, rng_region, num_perm, control, permissions, start_address, end_address); if (ret) { EMSG("Could not set firewall region information"); return TEE_ERROR_GENERIC; } IMSG("Enabled firewalls for SA2UL TRNG device"); /* Enable RNG engine in SA2UL if not already enabled */ val = io_read32(sa2ul + SA2UL_ES); if (!(val & SA2UL_ES_TRNG)) { IMSG("Enabling SA2UL TRNG engine"); io_setbits32(sa2ul + SA2UL_EEC, SA2UL_EEC_TRNG); } /* Initialize the RNG Module */ result = sa2ul_rng_init(); if (result != TEE_SUCCESS) return result; IMSG("SA2UL Drivers initialized"); return TEE_SUCCESS; } driver_init(sa2ul_init); optee_os-4.3.0/core/arch/arm/plat-k3/drivers/sa2ul.h000066400000000000000000000005261464416617300221260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Texas Instruments K3 SA2UL Driver * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Andrew Davis */ #ifndef __DRIVERS_SA2UL_H #define __DRIVERS_SA2UL_H #include TEE_Result sa2ul_rng_init(void); #endif /* __DRIVERS_SA2UL_H */ optee_os-4.3.0/core/arch/arm/plat-k3/drivers/sa2ul_rng.c000066400000000000000000000107221464416617300227660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Texas Instruments K3 SA2UL RNG Driver * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Andrew Davis */ #include #include #include #include #include #include #include #include #include #include #include "sa2ul.h" #define RNG_OUTPUT_0 0x00 #define RNG_OUTPUT_1 0x04 #define RNG_OUTPUT_2 0x08 #define RNG_OUTPUT_3 0x0C #define RNG_STATUS 0x10 #define RNG_READY BIT(0) #define SHUTDOWN_OFLO BIT(1) #define RNG_INTACK 0x10 #define RNG_CONTROL 0x14 #define ENABLE_TRNG BIT(10) #define RNG_CONFIG 0x18 #define RNG_ALARMCNT 0x1C #define RNG_FROENABLE 0x20 #define RNG_FRODETUNE 0x24 #define RNG_ALARMMASK 0x28 #define RNG_ALARMSTOP 0x2C #define RNG_OPTIONS 0x78 #define RNG_EIP_REV 0x7C #define RNG_CONTROL_STARTUP_CYCLES_SHIFT 16 #define RNG_CONTROL_STARTUP_CYCLES_MASK GENMASK_32(31, 16) #define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT 16 #define RNG_CONFIG_MAX_REFIL_CYCLES_MASK GENMASK_32(31, 16) #define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT 0 #define RNG_CONFIG_MIN_REFIL_CYCLES_MASK GENMASK_32(7, 0) #define RNG_ALARMCNT_ALARM_TH_SHIFT 0 #define RNG_ALARMCNT_ALARM_TH_MASK GENMASK_32(7, 0) #define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT 16 #define RNG_ALARMCNT_SHUTDOWN_TH_MASK GENMASK_32(20, 16) #define RNG_CONTROL_STARTUP_CYCLES 0xff #define RNG_CONFIG_MIN_REFIL_CYCLES 0x5 #define RNG_CONFIG_MAX_REFIL_CYCLES 0x22 #define RNG_ALARM_THRESHOLD 0xff #define RNG_SHUTDOWN_THRESHOLD 0x4 #define RNG_FRO_MASK GENMASK_32(23, 0) register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); static struct mutex fifo_lock = MUTEX_INITIALIZER; static vaddr_t rng; static bool sa2ul_rng_is_enabled(void) { return io_read32(rng + RNG_CONTROL) & ENABLE_TRNG; } static void sa2ul_rng_init_seq(void) { uint32_t val = 0; /* Ensure initial latency */ val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; io_write32(rng + RNG_CONFIG, val); /* Configure the desired FROs */ io_write32(rng + RNG_FRODETUNE, 0x0); /* Enable all FROs */ io_write32(rng + RNG_FROENABLE, 0xffffff); io_write32(rng + RNG_CONTROL, ENABLE_TRNG); } static void sa2ul_rng_read128(uint32_t *word0, uint32_t *word1, uint32_t *word2, uint32_t *word3) { if (!sa2ul_rng_is_enabled()) sa2ul_rng_init_seq(); /* Is the result ready (available)? */ while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) { /* Is the shutdown threshold reached? */ if (io_read32(rng + RNG_STATUS) & SHUTDOWN_OFLO) { uint32_t alarm = io_read32(rng + RNG_ALARMSTOP); uint32_t tune = io_read32(rng + RNG_FRODETUNE); /* Clear the alarm events */ io_write32(rng + RNG_ALARMMASK, 0x0); io_write32(rng + RNG_ALARMSTOP, 0x0); /* De-tune offending FROs */ io_write32(rng + RNG_FRODETUNE, tune ^ alarm); /* Re-enable the shut down FROs */ io_write32(rng + RNG_FROENABLE, RNG_FRO_MASK); /* Clear the shutdown overflow event */ io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO); DMSG("Fixed FRO shutdown"); } } /* Read random value */ *word0 = io_read32(rng + RNG_OUTPUT_0); *word1 = io_read32(rng + RNG_OUTPUT_1); *word2 = io_read32(rng + RNG_OUTPUT_2); *word3 = io_read32(rng + RNG_OUTPUT_3); /* Acknowledge read complete */ io_write32(rng + RNG_INTACK, RNG_READY); } TEE_Result hw_get_random_bytes(void *buf, size_t len) { static union { uint32_t val[4]; uint8_t byte[16]; } fifo; static size_t fifo_pos; uint8_t *buffer = buf; size_t buffer_pos = 0; while (buffer_pos < len) { mutex_lock(&fifo_lock); /* Refill our FIFO */ if (fifo_pos == 0) sa2ul_rng_read128(&fifo.val[0], &fifo.val[1], &fifo.val[2], &fifo.val[3]); buffer[buffer_pos++] = fifo.byte[fifo_pos++]; fifo_pos %= 16; mutex_unlock(&fifo_lock); } return TEE_SUCCESS; } TEE_Result sa2ul_rng_init(void) { rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); sa2ul_rng_init_seq(); IMSG("SA2UL TRNG initialized"); return TEE_SUCCESS; } optee_os-4.3.0/core/arch/arm/plat-k3/drivers/sec_proxy.c000066400000000000000000000175011464416617300231070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Texas Instruments K3 Secure Proxy Driver * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Manorit Chawdhry */ #include #include #include #include #include #include #include #include #include #include "sec_proxy.h" /* SEC PROXY RT THREAD STATUS */ #define RT_THREAD_STATUS_REG 0x0 #define RT_THREAD_STATUS_ERROR_MASK BIT(31) #define RT_THREAD_STATUS_CUR_CNT_MASK GENMASK_32(7, 0) /* SEC PROXY SCFG THREAD CTRL */ #define SCFG_THREAD_CTRL_REG 0x1000 #define SCFG_THREAD_CTRL_DIR_SHIFT 31 #define SCFG_THREAD_CTRL_DIR_MASK BIT(31) /* SECURE PROXY GENERIC HELPERS */ enum threads { SEC_PROXY_TX_THREAD, SEC_PROXY_RX_THREAD, SEC_PROXY_MAX_THREADS }; #define SEC_PROXY_THREAD(base, x) ((base) + (0x1000 * (x))) #define SEC_PROXY_DATA_START_OFFS 0x4 #define SEC_PROXY_DATA_END_OFFS 0x3c #define THREAD_DIR_TX (0) #define THREAD_DIR_RX (1) /** * struct k3_sec_proxy_thread - Description of a Secure Proxy Thread * @id: Thread ID * @data: Thread Data path region for target * @scfg: Secure Config Region for Thread * @rt: RealTime Region for Thread */ struct k3_sec_proxy_thread { const char *name; vaddr_t data; vaddr_t scfg; vaddr_t rt; } spts[SEC_PROXY_MAX_THREADS]; /** * k3_sec_proxy_verify_thread() - Verify thread status before * sending/receiving data * @dir: Direction of the thread */ static TEE_Result k3_sec_proxy_verify_thread(uint32_t dir) { struct k3_sec_proxy_thread *spt = &spts[dir]; uint64_t timeout = 0; uint32_t val = 0; unsigned int retry = 2; FMSG("Check for thread corruption"); val = io_read32(spt->rt + RT_THREAD_STATUS_REG); /* Check for any errors already available */ while ((val & RT_THREAD_STATUS_ERROR_MASK) && retry--) { if (!retry) { EMSG("Thread %s is corrupted, cannot send data.", spt->name); return TEE_ERROR_BAD_STATE; } /* Write Bit 0 to this location */ IMSG("Resetting proxy thread %s", spt->name); val ^= RT_THREAD_STATUS_ERROR_MASK; io_write32(spt->rt + RT_THREAD_STATUS_REG, val); } FMSG("Check for thread direction"); /* Make sure thread is configured for right direction */ if ((io_read32(spt->scfg + SCFG_THREAD_CTRL_REG) & SCFG_THREAD_CTRL_DIR_MASK) >> SCFG_THREAD_CTRL_DIR_SHIFT != dir) { if (dir == SEC_PROXY_TX_THREAD) EMSG("Trying to receive data on tx Thread %s", spt->name); else EMSG("Trying to send data on rx Thread %s", spt->name); return TEE_ERROR_COMMUNICATION; } FMSG("Check for thread queue"); /* Check the message queue before sending/receiving data */ timeout = timeout_init_us(SEC_PROXY_TIMEOUT_US); while (!(io_read32(spt->rt + RT_THREAD_STATUS_REG) & RT_THREAD_STATUS_CUR_CNT_MASK)) { DMSG("Waiting for thread %s to %s", spt->name, (dir == THREAD_DIR_TX) ? "empty" : "fill"); if (timeout_elapsed(timeout)) { EMSG("Queue is busy"); return TEE_ERROR_BUSY; } } FMSG("Success"); return TEE_SUCCESS; } /** * k3_sec_proxy_send() - Send data over a Secure Proxy thread * @msg: Pointer to k3_sec_proxy_msg */ TEE_Result k3_sec_proxy_send(const struct k3_sec_proxy_msg *msg) { struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_TX_THREAD]; int num_words = 0; int trail_bytes = 0; int i = 0; uintptr_t data_reg = 0; uint32_t data_word = 0; TEE_Result ret = TEE_SUCCESS; FMSG("Verifying the thread"); ret = k3_sec_proxy_verify_thread(THREAD_DIR_TX); if (ret) { EMSG("Thread %s verification failed. ret = %d", spt->name, ret); return ret; } /* Check the message size. */ if (msg->len > SEC_PROXY_MAX_MSG_SIZE) { EMSG("Thread %s message length %zu > max msg size %d", spt->name, msg->len, SEC_PROXY_MAX_MSG_SIZE); return TEE_ERROR_BAD_STATE; } /* Send the message */ data_reg = spt->data + SEC_PROXY_DATA_START_OFFS; num_words = msg->len / sizeof(uint32_t); for (i = 0; i < num_words; i++) { memcpy(&data_word, &msg->buf[i * 4], sizeof(uint32_t)); io_write32(data_reg, data_word); data_reg += sizeof(uint32_t); } trail_bytes = msg->len % sizeof(uint32_t); if (trail_bytes) { uint32_t data_trail = 0; i = msg->len - trail_bytes; while (trail_bytes--) { data_trail <<= 8; data_trail |= msg->buf[i++]; } io_write32(data_reg, data_trail); data_reg += sizeof(uint32_t); } /* * 'data_reg' indicates next register to write. If we did not already * write on tx complete reg(last reg), we must do so for transmit */ if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS)) io_write32(spt->data + SEC_PROXY_DATA_END_OFFS, 0); return TEE_SUCCESS; } /** * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread * @msg: Pointer to k3_sec_proxy_msg */ TEE_Result k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg) { struct k3_sec_proxy_thread *spt = &spts[SEC_PROXY_RX_THREAD]; int num_words = 0; int i = 0; int trail_bytes = 0; uint32_t data_trail = 0; uint32_t data_word = 0; uintptr_t data_reg = 0; TEE_Result ret = TEE_SUCCESS; FMSG("Verifying thread"); ret = k3_sec_proxy_verify_thread(THREAD_DIR_RX); if (ret) { EMSG("Thread %s verification failed. ret = %d", spt->name, ret); return ret; } /* Receive the message */ data_reg = spt->data + SEC_PROXY_DATA_START_OFFS; num_words = msg->len / sizeof(uint32_t); for (i = 0; i < num_words; i++) { data_word = io_read32(data_reg); memcpy(&msg->buf[i * 4], &data_word, sizeof(uint32_t)); data_reg += sizeof(uint32_t); } trail_bytes = msg->len % sizeof(uint32_t); if (trail_bytes) { data_trail = io_read32(data_reg); data_reg += sizeof(uint32_t); i = msg->len - trail_bytes; while (trail_bytes--) { msg->buf[i++] = data_trail & 0xff; data_trail >>= 8; } } /* * 'data_reg' indicates next register to read. If we did not already * read on rx complete reg(last reg), we must do so for receive */ if (data_reg <= (spt->data + SEC_PROXY_DATA_END_OFFS)) io_read32(spt->data + SEC_PROXY_DATA_END_OFFS); return TEE_SUCCESS; } /** * k3_sec_proxy_init() - Initialize the secure proxy threads */ TEE_Result k3_sec_proxy_init(void) { struct k3_sec_proxy_thread *thread; int rx_thread = SEC_PROXY_RESPONSE_THREAD; int tx_thread = SEC_PROXY_REQUEST_THREAD; uint32_t target_data = 0; uint32_t cfg_scfg = 0; uint32_t cfg_rt = 0; DMSG("tx_thread: %d, rx_thread: %d", tx_thread, rx_thread); /* TX_THREAD */ target_data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, tx_thread); cfg_scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, tx_thread); cfg_rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, tx_thread); thread = &spts[SEC_PROXY_TX_THREAD]; thread->name = "SEC_PROXY_LOW_PRIORITY_THREAD"; thread->data = core_mmu_get_va(target_data, MEM_AREA_IO_SEC, SEC_PROXY_DATA_SIZE); if (!thread->data) return TEE_ERROR_OUT_OF_MEMORY; thread->scfg = core_mmu_get_va(cfg_scfg, MEM_AREA_IO_SEC, SEC_PROXY_SCFG_SIZE); if (!thread->scfg) return TEE_ERROR_OUT_OF_MEMORY; thread->rt = core_mmu_get_va(cfg_rt, MEM_AREA_IO_SEC, SEC_PROXY_RT_SIZE); if (!thread->rt) return TEE_ERROR_OUT_OF_MEMORY; /* RX_THREAD */ target_data = SEC_PROXY_THREAD(SEC_PROXY_DATA_BASE, rx_thread); cfg_scfg = SEC_PROXY_THREAD(SEC_PROXY_SCFG_BASE, rx_thread); cfg_rt = SEC_PROXY_THREAD(SEC_PROXY_RT_BASE, rx_thread); thread = &spts[SEC_PROXY_RX_THREAD]; thread->name = "SEC_PROXY_RESPONSE_THREAD"; thread->data = core_mmu_get_va(target_data, MEM_AREA_IO_SEC, SEC_PROXY_DATA_SIZE); if (!thread->data) return TEE_ERROR_OUT_OF_MEMORY; thread->scfg = core_mmu_get_va(cfg_scfg, MEM_AREA_IO_SEC, SEC_PROXY_SCFG_SIZE); if (!thread->scfg) return TEE_ERROR_OUT_OF_MEMORY; thread->rt = core_mmu_get_va(cfg_rt, MEM_AREA_IO_SEC, SEC_PROXY_RT_SIZE); if (!thread->rt) return TEE_ERROR_OUT_OF_MEMORY; return TEE_SUCCESS; } optee_os-4.3.0/core/arch/arm/plat-k3/drivers/sec_proxy.h000066400000000000000000000021101464416617300231020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Texas Instruments K3 Secure Proxy Driver * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Manorit Chawdhry */ #ifndef SEC_PROXY_H #define SEC_PROXY_H #include #include #include #define SEC_PROXY_MAX_MSG_SIZE 60 /** * struct k3_sec_proxy_msg - Secure proxy message structure * @len: Length of data in the Buffer * @buf: Buffer pointer * * This is the structure for data used in k3_sec_proxy_{send,recv}() */ struct k3_sec_proxy_msg { size_t len; uint8_t *buf; }; /** * k3_sec_proxy_send() - Send data over a Secure Proxy thread * @msg: Pointer to k3_sec_proxy_msg */ TEE_Result k3_sec_proxy_send(const struct k3_sec_proxy_msg *msg); /** * k3_sec_proxy_recv() - Receive data from a Secure Proxy thread * @msg: Pointer to k3_sec_proxy_msg */ TEE_Result k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg); /** * k3_sec_proxy_init() - Initialize the secure proxy threads */ TEE_Result k3_sec_proxy_init(void); #endif /* __SEC_PROXY_H */ optee_os-4.3.0/core/arch/arm/plat-k3/drivers/sub.mk000066400000000000000000000001471464416617300220500ustar00rootroot00000000000000srcs-y += sec_proxy.c srcs-y += ti_sci.c srcs-$(CFG_SA2UL) += sa2ul.c srcs-$(CFG_SA2UL) += sa2ul_rng.c optee_os-4.3.0/core/arch/arm/plat-k3/drivers/ti_sci.c000066400000000000000000000270161464416617300223500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Texas Instruments System Control Interface Driver * Based on TF-A implementation * * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Manorit Chawdhry */ #include #include #include #include #include #include #include #include "sec_proxy.h" #include "ti_sci.h" #include "ti_sci_protocol.h" static uint8_t message_sequence; /** * struct ti_sci_xfer - Structure representing a message flow * @tx_message: Transmit message * @rx_message: Receive message */ struct ti_sci_xfer { struct k3_sec_proxy_msg tx_message; struct k3_sec_proxy_msg rx_message; }; /** * ti_sci_setup_xfer() - Setup message transfer * * @msg_type: Message type * @msg_flags: Flag to set for the message * @tx_buf: Buffer to be sent to mailbox channel * @tx_message_size: transmit message size * @rx_buf: Buffer to be received from mailbox channel * @rx_message_size: receive message size * @xfer: Transfer message * * Helper function which is used by various command functions that are * exposed to clients of this driver for allocating a message traffic event. * * Return: 0 if all goes well, else appropriate error message */ static int ti_sci_setup_xfer(uint16_t msg_type, uint32_t msg_flags, void *tx_buf, size_t tx_message_size, void *rx_buf, size_t rx_message_size, struct ti_sci_xfer *xfer) { struct ti_sci_msg_hdr *hdr = NULL; /* Ensure we have sane transfer sizes */ if (rx_message_size > SEC_PROXY_MAX_MSG_SIZE || tx_message_size > SEC_PROXY_MAX_MSG_SIZE || rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr)) { EMSG("Message transfer size not sane"); return TEE_ERROR_SHORT_BUFFER; } hdr = (struct ti_sci_msg_hdr *)tx_buf; hdr->seq = ++message_sequence; hdr->type = msg_type; hdr->host = OPTEE_HOST_ID; hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED; xfer->tx_message.buf = tx_buf; xfer->tx_message.len = tx_message_size; xfer->rx_message.buf = rx_buf; xfer->rx_message.len = rx_message_size; return 0; } /** * ti_sci_get_response() - Receive response from mailbox channel * * @xfer: Transfer to initiate and wait for response * * Return: 0 if all goes well, else appropriate error message */ static inline int ti_sci_get_response(struct ti_sci_xfer *xfer) { struct k3_sec_proxy_msg *msg = &xfer->rx_message; struct ti_sci_msg_hdr *hdr = NULL; unsigned int retry = 5; int ret = 0; for (; retry > 0; retry--) { /* Receive the response */ ret = k3_sec_proxy_recv(msg); if (ret) { EMSG("Message receive failed (%d)", ret); return ret; } /* msg is updated by Secure Proxy driver */ hdr = (struct ti_sci_msg_hdr *)msg->buf; /* Sanity check for message response */ if (hdr->seq == message_sequence) break; IMSG("Message with sequence ID %u is not expected", hdr->seq); } if (!retry) { EMSG("Timed out waiting for message"); return TEE_ERROR_BUSY; } if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) { DMSG("Message not acknowledged"); return TEE_ERROR_ACCESS_DENIED; } return 0; } /** * ti_sci_do_xfer() - Do one transfer * * @xfer: Transfer to initiate and wait for response * * Return: 0 if all goes well, else appropriate error message */ static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer) { struct k3_sec_proxy_msg *msg = &xfer->tx_message; int ret = 0; /* Send the message */ ret = k3_sec_proxy_send(msg); if (ret) { EMSG("Message sending failed (%d)", ret); return ret; } /* Get the response */ ret = ti_sci_get_response(xfer); if (ret) { if ((TEE_Result)ret != TEE_ERROR_ACCESS_DENIED) EMSG("Failed to get response (%d)", ret); return ret; } return 0; } int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info) { struct ti_sci_msg_req_version req = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_VERSION, 0x0, &req, sizeof(req), rev_info, sizeof(*rev_info), &xfer); if (ret) return ret; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; return 0; } static int ti_sci_device_set_state(uint32_t id, uint32_t flags, uint8_t state) { struct ti_sci_msg_req_set_device_state req = { }; struct ti_sci_msg_resp_set_device_state resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_SET_DEVICE_STATE, flags, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.id = id; req.state = state; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; return 0; } int ti_sci_device_get(uint32_t id) { return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_ON); } int ti_sci_device_put(uint32_t id) { return ti_sci_device_set_state(id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); } int ti_sci_set_fwl_region(uint16_t fwl_id, uint16_t region, uint32_t n_permission_regs, uint32_t control, const uint32_t permissions[FWL_MAX_PRIVID_SLOTS], uint64_t start_address, uint64_t end_address) { struct ti_sci_msg_req_fwl_set_firewall_region req = { }; struct ti_sci_msg_resp_fwl_set_firewall_region resp = { }; struct ti_sci_xfer xfer = { }; unsigned int i = 0; int ret = 0; assert(n_permission_regs <= FWL_MAX_PRIVID_SLOTS); ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_SET, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.fwl_id = fwl_id; req.region = region; req.n_permission_regs = n_permission_regs; req.control = control; for (i = 0; i < n_permission_regs; i++) req.permissions[i] = permissions[i]; req.start_address = start_address; req.end_address = end_address; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; return 0; } int ti_sci_get_fwl_region(uint16_t fwl_id, uint16_t region, uint32_t n_permission_regs, uint32_t *control, uint32_t permissions[FWL_MAX_PRIVID_SLOTS], uint64_t *start_address, uint64_t *end_address) { struct ti_sci_msg_req_fwl_get_firewall_region req = { }; struct ti_sci_msg_resp_fwl_get_firewall_region resp = { }; struct ti_sci_xfer xfer = { }; unsigned int i = 0; int ret = 0; assert(n_permission_regs <= FWL_MAX_PRIVID_SLOTS); ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_GET, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.fwl_id = fwl_id; req.region = region; req.n_permission_regs = n_permission_regs; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; *control = resp.control; for (i = 0; i < n_permission_regs; i++) permissions[i] = resp.permissions[i]; *start_address = resp.start_address; *end_address = resp.end_address; return 0; } int ti_sci_change_fwl_owner(uint16_t fwl_id, uint16_t region, uint8_t owner_index, uint8_t *owner_privid, uint16_t *owner_permission_bits) { struct ti_sci_msg_req_fwl_change_owner_info req = { }; struct ti_sci_msg_resp_fwl_change_owner_info resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_FWL_CHANGE_OWNER, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.fwl_id = fwl_id; req.region = region; req.owner_index = owner_index; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; *owner_privid = resp.owner_privid; *owner_permission_bits = resp.owner_permission_bits; return 0; } int ti_sci_get_dkek(uint8_t sa2ul_instance, const char *context, const char *label, uint8_t dkek[SA2UL_DKEK_KEY_LEN]) { struct ti_sci_msg_req_sa2ul_get_dkek req = { }; struct ti_sci_msg_resp_sa2ul_get_dkek resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_SA2UL_GET_DKEK, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.sa2ul_instance = sa2ul_instance; req.kdf_label_len = strlen(label); req.kdf_context_len = strlen(context); if (req.kdf_label_len + req.kdf_context_len > KDF_LABEL_AND_CONTEXT_LEN_MAX) { EMSG("Context and Label too long"); return TEE_ERROR_BAD_PARAMETERS; } memcpy(req.kdf_label_and_context, label, strlen(label)); memcpy(req.kdf_label_and_context + strlen(label), context, strlen(context)); ret = ti_sci_do_xfer(&xfer); if (ret) return ret; memcpy(dkek, resp.dkek, sizeof(resp.dkek)); memzero_explicit(&resp, sizeof(resp)); return 0; } int ti_sci_read_otp_mmr(uint8_t mmr_idx, uint32_t *val) { struct ti_sci_msg_req_read_otp_mmr req = { }; struct ti_sci_msg_resp_read_otp_mmr resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_OTP_MMR, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) goto exit; req.mmr_idx = mmr_idx; ret = ti_sci_do_xfer(&xfer); if (ret) goto exit; *val = resp.mmr_val; exit: memzero_explicit(&resp, sizeof(resp)); return ret; } int ti_sci_write_otp_row(uint8_t row_idx, uint32_t row_val, uint32_t row_mask) { struct ti_sci_msg_req_write_otp_row req = { }; struct ti_sci_msg_resp_write_otp_row resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_WRITE_OTP_ROW, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) goto exit; req.row_idx = row_idx; req.row_val = row_val; req.row_mask = row_mask; ret = ti_sci_do_xfer(&xfer); if (ret) goto exit; DMSG("resp.row_val: 0x%08x", resp.row_val); if (resp.row_val != (req.row_val & req.row_mask)) { EMSG("Value not written correctly"); DMSG("req.row_val : 0x%08"PRIx32, req.row_val); DMSG("req.row_mask: 0x%08"PRIx32, req.row_mask); ret = TEE_ERROR_BAD_STATE; } exit: memzero_explicit(&resp, sizeof(resp)); memzero_explicit(&req, sizeof(req)); return ret; } int ti_sci_lock_otp_row(uint8_t row_idx, uint8_t hw_write_lock, uint8_t hw_read_lock, uint8_t row_soft_lock) { struct ti_sci_msg_req_lock_otp_row req = { }; struct ti_sci_msg_resp_lock_otp_row resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_LOCK_OTP_ROW, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.row_idx = row_idx; req.hw_write_lock = hw_write_lock; req.hw_read_lock = hw_read_lock; req.row_soft_lock = row_soft_lock; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; return 0; } int ti_sci_get_swrev(uint32_t *swrev) { struct ti_sci_msq_req_get_swrev req = { }; struct ti_sci_msq_resp_get_swrev resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_SWREV, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; req.identifier = OTP_REV_ID_SEC_BRDCFG; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; *swrev = resp.swrev; memzero_explicit(&resp, sizeof(resp)); return 0; } int ti_sci_get_keycnt_keyrev(uint32_t *key_cnt, uint32_t *key_rev) { struct ti_sci_msq_req_get_keycnt_keyrev req = { }; struct ti_sci_msq_resp_get_keycnt_keyrev resp = { }; struct ti_sci_xfer xfer = { }; int ret = 0; ret = ti_sci_setup_xfer(TI_SCI_MSG_READ_KEYCNT_KEYREV, 0, &req, sizeof(req), &resp, sizeof(resp), &xfer); if (ret) return ret; ret = ti_sci_do_xfer(&xfer); if (ret) return ret; *key_cnt = resp.keycnt; *key_rev = resp.keyrev; memzero_explicit(&resp, sizeof(resp)); return 0; } int ti_sci_init(void) { struct ti_sci_msg_resp_version rev_info = { }; int ret = 0; ret = ti_sci_get_revision(&rev_info); if (ret) { EMSG("Unable to communicate with control firmware (%d)", ret); return ret; } IMSG("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')", rev_info.abi_major, rev_info.abi_minor, rev_info.firmware_revision, rev_info.firmware_description); return 0; } optee_os-4.3.0/core/arch/arm/plat-k3/drivers/ti_sci.h000066400000000000000000000164411464416617300223550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/ * Manorit Chawdhry */ #ifndef TI_SCI_H #define TI_SCI_H #include #include #include #include "ti_sci_protocol.h" /** * ti_sci_get_revision() - Get the revision of the SCI entity * * Updates the SCI information in the internal data structure. * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info); /** * Device control operations * * - ti_sci_device_get - Get access to device managed by TISCI * - ti_sci_device_put - Release access to device managed by TISCI * * NOTE: for all these functions, the following are generic in nature: * @id: Device Identifier * * Returns 0 for successful request, else returns corresponding error message. * * Request for the device - NOTE: the client MUST maintain integrity of * usage count by balancing get_device with put_device. No refcounting is * managed by driver for that purpose. */ int ti_sci_device_get(uint32_t id); int ti_sci_device_put(uint32_t id); /** * ti_sci_set_fwl_region() - Request for configuring a firewall region * * @fwl_id: Firewall ID in question. fwl_id is defined in the TRM. * @region: Region or channel number to set config info. This field * is unused in case of a simple firewall and must be * initialized to zero. In case of a region based * firewall, this field indicates the region in question * (index starting from 0). In case of a channel based * firewall, this field indicates the channel in question * (index starting from 0). * @n_permission_regs: Number of permission registers to set * @control: Contents of the firewall CONTROL register to set * @permissions: Contents of the firewall PERMISSION register to set * @start_address: Contents of the firewall START_ADDRESS register to set * @end_address: Contents of the firewall END_ADDRESS register to set * * Return: 0 if all went well, else returns appropriate error value. */ int ti_sci_set_fwl_region(uint16_t fwl_id, uint16_t region, uint32_t n_permission_regs, uint32_t control, const uint32_t permissions[FWL_MAX_PRIVID_SLOTS], uint64_t start_address, uint64_t end_address); /** * ti_sci_cmd_get_fwl_region() - Request for getting a firewall region * * @fwl_id: Firewall ID in question. fwl_id is defined in the TRM. * @region: Region or channel number to set config info. This field * is unused in case of a simple firewall and must be * initialized to zero. In case of a region based * firewall, this field indicates the region in question * (index starting from 0). In case of a channel based * firewall, this field indicates the channel in question * (index starting from 0). * @n_permission_regs: Region or channel number to set config info * @control: Contents of the firewall CONTROL register * @permissions: Contents of the firewall PERMISSION register * @start_address: Contents of the firewall START_ADDRESS register * @end_address: Contents of the firewall END_ADDRESS register * * Return: 0 if all went well, else returns appropriate error value. */ int ti_sci_get_fwl_region(uint16_t fwl_id, uint16_t region, uint32_t n_permission_regs, uint32_t *control, uint32_t permissions[FWL_MAX_PRIVID_SLOTS], uint64_t *start_address, uint64_t *end_address); /** * ti_sci_change_fwl_owner() - Request for changing a firewall owner * * @fwl_id: Firewall ID in question. fwl_id is defined in the TRM. * @region: Region or channel number to set config info. This field * is unused in case of a simple firewall and must be * initialized to zero. In case of a region based * firewall, this field indicates the region in question * (index starting from 0). In case of a channel based * firewall, this field indicates the channel in question * (index starting from 0). * @owner_index: New owner index to transfer ownership to * @owner_privid: New owner priv-ID returned by DMSC. This field is * currently initialized to zero by DMSC. * @owner_permission_bits: New owner permission bits returned by DMSC. This * field is currently initialized to zero by DMSC. * * Return: 0 if all went well, else returns appropriate error value. */ int ti_sci_change_fwl_owner(uint16_t fwl_id, uint16_t region, uint8_t owner_index, uint8_t *owner_privid, uint16_t *owner_permission_bits); /** * ti_sci_get_dkek() - Get the DKEK * @sa2ul_instance: SA2UL instance to get key * @context: Context string input to KDF * @label: Label string input to KDF * @dkek: Returns with DKEK populated * * Updates the DKEK the internal data structure. * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_get_dkek(uint8_t sa2ul_instance, const char *context, const char *label, uint8_t dkek[SA2UL_DKEK_KEY_LEN]); /** * ti_sci_read_otp_mmr() - Get the Extended OTP * @mmr_idx: 32-bit MMR index * @val: Value of the 32-bit MMR * * Reads the extended OTP bits from efuse * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_read_otp_mmr(uint8_t mmr_idx, uint32_t *val); /** * ti_sci_write_otp_row() - Write the extended OTP row * @row_idx: Index of the OTP row. Zero indexing * @row_val: Value to be written * @row_mask: Mask bits for row_val to be written * * Writes a Row in the extended OTP field * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_write_otp_row(uint8_t row_idx, uint32_t row_val, uint32_t row_mask); /** * ti_sci_lock_otp_row - Locking the Extended OTP row * @row_idx: Index of the OTP row. Zero indexing * @hw_write_lock: Hardware write lock * @hw_read_lock: Hardware read lock * @row_soft_lock: Software write lock * * Lockes a Row in the extended OTP field to prevent read/writes * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_lock_otp_row(uint8_t row_idx, uint8_t hw_write_lock, uint8_t hw_read_lock, uint8_t row_soft_lock); /** * ti_sci_get_swrev - Read Software Revision * @swrev: Software Revision * * Reads the software revision. The System Firmware currently supports reading * only the software revision from the Secure Board Configuration. * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_get_swrev(uint32_t *swrev); /** * ti_sci_get_keycnt_keyrev - Read Key Count and Key Revision values * @key_cnt: Key Count * @key_rev: Key Revision * * Reads the Key Count and Key Revision in OTP * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_get_keycnt_keyrev(uint32_t *key_cnt, uint32_t *key_rev); /** * ti_sci_init() - Basic initialization * * Return: 0 if all goes well, else appropriate error message */ int ti_sci_init(void); #endif optee_os-4.3.0/core/arch/arm/plat-k3/drivers/ti_sci_protocol.h000066400000000000000000000327041464416617300242760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2016-2022 Texas Instruments Incorporated - https://www.ti.com/ * Lokesh Vutla * Manorit Chawdhry */ #ifndef TI_SCI_PROTOCOL_H #define TI_SCI_PROTOCOL_H #include #include #include /* Generic Messages */ #define TI_SCI_MSG_VERSION 0x0002 /* Device requests */ #define TI_SCI_MSG_SET_DEVICE_STATE 0x0200 /* Security Management Messages */ #define TI_SCI_MSG_FWL_SET 0x9000 #define TI_SCI_MSG_FWL_GET 0x9001 #define TI_SCI_MSG_FWL_CHANGE_OWNER 0x9002 #define TI_SCI_MSG_SA2UL_GET_DKEK 0x9029 #define TI_SCI_MSG_READ_OTP_MMR 0x9022 #define TI_SCI_MSG_WRITE_OTP_ROW 0x9023 #define TI_SCI_MSG_LOCK_OTP_ROW 0x9024 /* OTP Revision Read/Write Message Description */ #define TI_SCI_MSG_WRITE_SWREV 0x9032 #define TI_SCI_MSG_READ_SWREV 0x9033 #define TI_SCI_MSG_READ_KEYCNT_KEYREV 0x9034 #define TI_SCI_MSG_WRITE_KEYREV 0x9035 /** * struct ti_sci_secure_msg_hdr - Secure Message Header for All messages * and responses * * @checksum: Integrity check for HS devices * @reserved: Reserved for future uses */ struct ti_sci_secure_msg_hdr { uint16_t checksum; uint16_t reserved; } __packed; /** * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses * @type: Type of messages: One of TI_SCI_MSG* values * @host: Host of the message * @seq: Message identifier indicating a transfer sequence * @flags: Flag for the message */ struct ti_sci_msg_hdr { struct ti_sci_secure_msg_hdr sec_hdr; uint16_t type; uint8_t host; uint8_t seq; #define TI_SCI_MSG_FLAG(val) BIT(val) #define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 #define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0) #define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1) #define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0 #define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1) /* Additional Flags */ uint32_t flags; } __packed; /** * struct ti_sci_msg_version_req - Request for firmware version information * @hdr: Generic header * * Request for TI_SCI_MSG_VERSION */ struct ti_sci_msg_req_version { struct ti_sci_msg_hdr hdr; } __packed; /** * struct ti_sci_msg_resp_version - Response for firmware version information * @hdr: Generic header * @firmware_description: String describing the firmware * @firmware_revision: Firmware revision * @abi_major: Major version of the ABI that firmware supports * @abi_minor: Minor version of the ABI that firmware supports * @sub_version: Sub-version number of the firmware * @patch_version: Patch-version number of the firmware. * * In general, ABI version changes follow the rule that minor version increments * are backward compatible. Major revision changes in ABI may not be * backward compatible. * * Response to request TI_SCI_MSG_VERSION */ struct ti_sci_msg_resp_version { struct ti_sci_msg_hdr hdr; #define FIRMWARE_DESCRIPTION_LENGTH 32 char firmware_description[FIRMWARE_DESCRIPTION_LENGTH]; uint16_t firmware_revision; uint8_t abi_major; uint8_t abi_minor; uint8_t sub_version; uint8_t patch_version; } __packed; /** * struct ti_sci_msg_req_set_device_state - Set the desired state of the device * @hdr: Generic header * @id: Indicates which device to modify * @reserved: Reserved space in message, must be 0 for backward compatibility * @state: The desired state of the device. * * Certain flags can also be set to alter the device state: * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. * The meaning of this flag will vary slightly from device to device and from * SoC to SoC but it generally allows the device to wake the SoC out of deep * suspend states. * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. * If another host already has this device set to STATE_RETENTION or STATE_ON, * the message will fail. Once successful, other hosts attempting to set * STATE_RETENTION or STATE_ON will fail. * * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic * ACK/NACK message. */ struct ti_sci_msg_req_set_device_state { /* Additional hdr->flags options */ #define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8) #define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9) #define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10) struct ti_sci_msg_hdr hdr; uint32_t id; uint32_t reserved; #define MSG_DEVICE_SW_STATE_AUTO_OFF 0 #define MSG_DEVICE_SW_STATE_RETENTION 1 #define MSG_DEVICE_SW_STATE_ON 2 uint8_t state; } __packed; /** * struct ti_sci_msg_resp_set_device_state - Response for set device state * @hdr: Generic header * * Response to request TI_SCI_MSG_SET_DEVICE_STATE */ struct ti_sci_msg_resp_set_device_state { struct ti_sci_msg_hdr hdr; } __packed; #define FWL_MAX_PRIVID_SLOTS 3U /** * struct ti_sci_msg_req_fwl_set_firewall_region - Set firewall permissions * @hdr: Generic Header * @fwl_id: Firewall ID * @region: Region or channel number to set config info. * This field is unused in case of a simple firewall and * must be initialized to zero. In case of a region based * firewall, this field indicates the region (index * starting from 0). In case of a channel based firewall, * this field indicates the channel (index starting * from 0). * @n_permission_regs: Number of permission registers to set * @control: Contents of the firewall CONTROL register to set * @permissions: Contents of the firewall PERMISSION register to set * @start_address: Contents of the firewall START_ADDRESS register to set * @end_address: Contents of the firewall END_ADDRESS register to set */ struct ti_sci_msg_req_fwl_set_firewall_region { struct ti_sci_msg_hdr hdr; uint16_t fwl_id; uint16_t region; uint32_t n_permission_regs; uint32_t control; uint32_t permissions[FWL_MAX_PRIVID_SLOTS]; uint64_t start_address; uint64_t end_address; } __packed; struct ti_sci_msg_resp_fwl_set_firewall_region { struct ti_sci_msg_hdr hdr; } __packed; /** * struct ti_sci_msg_req_fwl_get_firewall_region - Retrieve firewall permissions * @hdr: Generic Header * @fwl_id: Firewall ID in question * @region: Region or channel number to set config info. * This field is unused in case of a simple firewall and * must be initialized to zero. In case of a region based * firewall, this field indicates the region (index * starting from 0). In case of a channel based firewall, * this field indicates the channel (index starting * from 0). * @n_permission_regs: Number of permission registers to retrieve */ struct ti_sci_msg_req_fwl_get_firewall_region { struct ti_sci_msg_hdr hdr; uint16_t fwl_id; uint16_t region; uint32_t n_permission_regs; } __packed; /** * struct ti_sci_msg_resp_fwl_get_firewall_region - Response for retrieving the * firewall permissions * * @hdr: Generic Header * * @fwl_id: Firewall ID in question * @region: Region or channel number to set config info. * This field is unused in case of a simple firewall and * must be initialized to zero. In case of a region based * firewall, this field indicates the region (index * starting from 0). In case of a channel based firewall, * this field indicates the channel (index starting * from 0). * @n_permission_regs: Number of permission registers retrieved * @control: Contents of the firewall CONTROL register * @permissions: Contents of the firewall PERMISSION registers * @start_address: Contents of the firewall START_ADDRESS register * @end_address: Contents of the firewall END_ADDRESS register */ struct ti_sci_msg_resp_fwl_get_firewall_region { struct ti_sci_msg_hdr hdr; uint16_t fwl_id; uint16_t region; uint32_t n_permission_regs; uint32_t control; uint32_t permissions[FWL_MAX_PRIVID_SLOTS]; uint64_t start_address; uint64_t end_address; } __packed; /** * struct ti_sci_msg_req_fwl_change_owner_info - Request change firewall owner * * @hdr: Generic Header * * @fwl_id: Firewall ID in question * @region: Region or channel number if applicable * @owner_index: New owner index to transfer ownership to */ struct ti_sci_msg_req_fwl_change_owner_info { struct ti_sci_msg_hdr hdr; uint16_t fwl_id; uint16_t region; uint8_t owner_index; } __packed; /** * struct ti_sci_msg_resp_fwl_change_owner_info - Response for change * firewall owner * * @hdr: Generic Header * * @fwl_id: Firewall ID specified in request * @region: Region or channel number specified in request * @owner_index: Owner index specified in request * @owner_privid: New owner priv-ID returned by DMSC. * @owner_permission_bits: New owner permission bits returned by DMSC. */ struct ti_sci_msg_resp_fwl_change_owner_info { struct ti_sci_msg_hdr hdr; uint16_t fwl_id; uint16_t region; uint8_t owner_index; uint8_t owner_privid; uint16_t owner_permission_bits; } __packed; /** * struct ti_sci_msg_sa2ul_get_dkek_req - Request for DKEK value * @hdr: Generic header * @sa2ul_instance: SA2UL instance number - set to 0 * @kdf_label_len: Length of "Label" input to KDF * @kdf_context_len: Length of "Context" input to KDF * @kdf_label_and_context: "Label" and "Context" bytes * * Request for TI_SCI_MSG_SA2UL_GET_DKEK */ struct ti_sci_msg_req_sa2ul_get_dkek { struct ti_sci_msg_hdr hdr; uint8_t sa2ul_instance; uint8_t kdf_label_len; uint8_t kdf_context_len; #define KDF_LABEL_AND_CONTEXT_LEN_MAX 41 uint8_t kdf_label_and_context[KDF_LABEL_AND_CONTEXT_LEN_MAX]; } __packed; /** * struct ti_sci_msg_sa2ul_get_dkek_req - Response for DKEK value * @hdr: Generic header * @dkek: Array containing Derived KEK * * Response to request TI_SCI_MSG_SA2UL_GET_DKEK */ struct ti_sci_msg_resp_sa2ul_get_dkek { struct ti_sci_msg_hdr hdr; #define SA2UL_DKEK_KEY_LEN 32 uint8_t dkek[SA2UL_DKEK_KEY_LEN]; } __packed; /** * struct ti_sci_msg_resp_read_otp_mmr - Request for reading extended OTP * @hdr: Generic header * @mmr_idx: Index of 32 bit MMR * * Request for TI_SCI_MSG_READ_OTP_MMR */ struct ti_sci_msg_req_read_otp_mmr { struct ti_sci_msg_hdr hdr; uint8_t mmr_idx; } __packed; /** * struct ti_sci_msg_resp_read_otp_mmr - Response for reading extended OTP * @hdr: Generic header * @mmr_val: Value written in the OTP * * Response to request TI_SCI_MSG_READ_OTP_MMR */ struct ti_sci_msg_resp_read_otp_mmr { struct ti_sci_msg_hdr hdr; uint32_t mmr_val; } __packed; /** * struct ti_sci_msg_req_write_otp_row - Request for writing Extended OTP * @hdr: Generic header * @row_idx: Index of the OTP row. Zero indexing * @row_val: Value to be written * @row_mask: Mask bits for row_val to be written * * Request for TI_SCI_MSG_WRITE_OTP_ROW */ struct ti_sci_msg_req_write_otp_row { struct ti_sci_msg_hdr hdr; uint8_t row_idx; uint32_t row_val; uint32_t row_mask; } __packed; /** * struct ti_sci_msg_resp_write_otp_row - Response for writing Extended OTP * @hdr: Generic header * @row_val: Value that is written * * Response to request TI_SCI_MSG_WRITE_OTP_ROW */ struct ti_sci_msg_resp_write_otp_row { struct ti_sci_msg_hdr hdr; uint32_t row_val; } __packed; /** * struct ti_sci_msg_req_lock_otp_row - Request for Lock OTP row * @hdr: Generic header * @row_idx: Index of the OTP row. Zero indexing * @hw_write_lock: 0x5A indicates row will be write protected * @hw_read_lock: 0x5A indicates row will be read protected * @row_soft_lock: Software write lock * * Request for TI_SCI_MSG_LOCK_OTP_ROW */ struct ti_sci_msg_req_lock_otp_row { struct ti_sci_msg_hdr hdr; uint8_t row_idx; uint8_t hw_write_lock; uint8_t hw_read_lock; uint8_t row_soft_lock; } __packed; /** * struct ti_sci_msg_resp_lock_otp_row - Response for Lock OTP row * @hdr: Generic header * * Response to request TI_SCI_MSG_LOCK_OTP_ROW */ struct ti_sci_msg_resp_lock_otp_row { struct ti_sci_msg_hdr hdr; } __packed; /** * \brief OTP Revision Identifiers */ enum tisci_otp_revision_identifier { /** Software Revision SBL */ OTP_REV_ID_SBL = 0, /** Software Revision SYSFW */ OTP_REV_ID_SYSFW = 1, /** Software Revision Secure Board Configuration */ OTP_REV_ID_SEC_BRDCFG = 2, }; /** * struct ti_sci_msq_req_get_swrev - Request for reading the Software Revision * in OTP * @hdr: Generic header * @identifier: One of the entries from enum tisci_otp_revision_identifier * (Current support only for OTP_REV_ID_SEC_BRDCFG) * * Request for TI_SCI_MSG_READ_SWREV */ struct ti_sci_msq_req_get_swrev { struct ti_sci_msg_hdr hdr; uint8_t identifier; } __packed; /** * struct ti_sci_msq_req_get_swrev - Response for reading the Software Revision * in OTP * @hdr: Generic header * @swrev: Decoded Sofrware Revision value from efuses * * Response for TI_SCI_MSG_READ_SWREV */ struct ti_sci_msq_resp_get_swrev { struct ti_sci_msg_hdr hdr; uint32_t swrev; } __packed; /** * struct ti_sci_msq_req_get_keycnt_keyrev - Request for reading the Key Count * and Key Revision in OTP * @hdr: Generic header * * Request for TI_SCI_MSG_READ_KEYCNT_KEYREV */ struct ti_sci_msq_req_get_keycnt_keyrev { struct ti_sci_msg_hdr hdr; } __packed; /** * struct ti_sci_msq_req_get_swrev - Response for reading the Key Count and Key * Revision in OTP * @hdr: Generic header * @keycnt: Key Count integer value * @keyrev: Key Revision integer value * * Response for TI_SCI_MSG_READ_SWREV */ struct ti_sci_msq_resp_get_keycnt_keyrev { struct ti_sci_msg_hdr hdr; uint32_t keycnt; uint32_t keyrev; } __packed; #endif optee_os-4.3.0/core/arch/arm/plat-k3/main.c000066400000000000000000000050061464416617300203370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ * Andrew F. Davis */ #include #include #include #include #include #include #include #include #include #include #include #include #include static struct serial8250_uart_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GICC_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GICD_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_DATA_BASE, SEC_PROXY_DATA_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_SCFG_BASE, SEC_PROXY_SCFG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SEC_PROXY_RT_BASE, SEC_PROXY_RT_SIZE); register_ddr(DRAM0_BASE, DRAM0_SIZE); register_ddr(DRAM1_BASE, DRAM1_SIZE); void boot_primary_init_intc(void) { gic_init(GICC_BASE, GICD_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } static TEE_Result init_ti_sci(void) { TEE_Result ret = TEE_SUCCESS; ret = k3_sec_proxy_init(); if (ret != TEE_SUCCESS) return ret; ret = ti_sci_init(); if (ret) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } service_init(init_ti_sci); static TEE_Result secure_boot_information(void) { uint32_t keycnt = 0; uint32_t keyrev = 0; uint32_t swrev = 0; if (!ti_sci_get_swrev(&swrev)) IMSG("Secure Board Configuration Software: Rev %"PRIu32, swrev); if (!ti_sci_get_keycnt_keyrev(&keycnt, &keyrev)) IMSG("Secure Boot Keys: Count %"PRIu32 ", Rev %"PRIu32, keycnt, keyrev); return TEE_SUCCESS; } service_init_late(secure_boot_information); TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { uint8_t dkek[SA2UL_DKEK_KEY_LEN] = { }; int ret = 0; assert(SA2UL_DKEK_KEY_LEN >= HW_UNIQUE_KEY_LENGTH); ret = ti_sci_get_dkek(0, "OP-TEE", "DKEK", dkek); if (ret) { EMSG("Could not get HUK"); return TEE_ERROR_SECURITY; } memcpy(&hwkey->data[0], dkek, sizeof(hwkey->data)); memzero_explicit(&dkek, sizeof(dkek)); IMSG("HUK Initialized"); return TEE_SUCCESS; } optee_os-4.3.0/core/arch/arm/plat-k3/platform_config.h000066400000000000000000000062021464416617300225700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ * Andrew F. Davis */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #define UART0_BASE 0x02800000 #define CONSOLE_UART_BASE (UART0_BASE + CFG_CONSOLE_UART * 0x10000) #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 48000000 #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE 0x80000000 #define DRAM1_BASE 0x880000000 #define DRAM1_SIZE 0x780000000 #define SCU_BASE 0x01800000 #if defined(PLATFORM_FLAVOR_j721e) || defined(PLATFORM_FLAVOR_j784s4) #define GICC_OFFSET 0x100000 #define GICC_SIZE 0x100000 #define GICD_OFFSET 0x0 #define GICD_SIZE 0x10000 #else #define GICC_OFFSET 0x80000 #define GICC_SIZE 0x90000 #define GICD_OFFSET 0x0 #define GICD_SIZE 0x10000 #endif #if defined(PLATFORM_FLAVOR_am65x) || defined(PLATFORM_FLAVOR_j721e) || \ defined(PLATFORM_FLAVOR_j784s4) #define SEC_PROXY_DATA_BASE 0x32c00000 #define SEC_PROXY_DATA_SIZE 0x100000 #define SEC_PROXY_SCFG_BASE 0x32800000 #define SEC_PROXY_SCFG_SIZE 0x100000 #define SEC_PROXY_RT_BASE 0x32400000 #define SEC_PROXY_RT_SIZE 0x100000 #define SEC_PROXY_RESPONSE_THREAD 6 #define SEC_PROXY_REQUEST_THREAD 7 #else #define SEC_PROXY_DATA_BASE 0x4d000000 #define SEC_PROXY_DATA_SIZE 0x80000 #define SEC_PROXY_SCFG_BASE 0x4a400000 #define SEC_PROXY_SCFG_SIZE 0x80000 #define SEC_PROXY_RT_BASE 0x4a600000 #define SEC_PROXY_RT_SIZE 0x80000 #define SEC_PROXY_RESPONSE_THREAD 10 #define SEC_PROXY_REQUEST_THREAD 11 #endif #define OPTEE_HOST_ID 11 #define SEC_PROXY_TIMEOUT_US 1000000 #define GICC_BASE (SCU_BASE + GICC_OFFSET) #define GICD_BASE (SCU_BASE + GICD_OFFSET) /* SA2UL */ #if defined(PLATFORM_FLAVOR_am65x) #define SA2UL_BASE 0x04e00000 #define SA2UL_TI_SCI_DEV_ID 136 #define SA2UL_TI_SCI_FW_ID 2112 #define SA2UL_TI_SCI_FW_RGN_ID 0 #elif defined(PLATFORM_FLAVOR_j721e) #define SA2UL_BASE 0x40900000 #define SA2UL_TI_SCI_DEV_ID 265 #define SA2UL_TI_SCI_FW_ID 1196 #define SA2UL_TI_SCI_FW_RGN_ID 0 #elif defined(PLATFORM_FLAVOR_j784s4) #define SA2UL_BASE 0x40900000 #define SA2UL_TI_SCI_DEV_ID -1 #define SA2UL_TI_SCI_FW_ID 1196 #define SA2UL_TI_SCI_FW_RGN_ID 0 #elif defined(PLATFORM_FLAVOR_am64x) #define SA2UL_BASE 0x40900000 #define SA2UL_TI_SCI_DEV_ID 133 #define SA2UL_TI_SCI_FW_ID 35 #define SA2UL_TI_SCI_FW_RGN_ID 0 #elif defined(PLATFORM_FLAVOR_am62x) #define SA2UL_BASE 0x40900000 #define SA2UL_TI_SCI_DEV_ID -1 #define SA2UL_TI_SCI_FW_ID 66 #define SA2UL_TI_SCI_FW_RGN_ID 1 #endif #define SA2UL_REG_SIZE 0x1000 /* RNG */ #define RNG_BASE (SA2UL_BASE + 0x10000) #define RNG_REG_SIZE 0x1000 #if defined(PLATFORM_FLAVOR_am62x) #define RNG_TI_SCI_FW_RGN_ID 2 #else #define RNG_TI_SCI_FW_RGN_ID 3 #endif /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-k3/sub.mk000066400000000000000000000000741464416617300203710ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c subdirs-y += drivers optee_os-4.3.0/core/arch/arm/plat-ls/000077500000000000000000000000001464416617300173475ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-ls/conf.mk000066400000000000000000000100511464416617300206220ustar00rootroot00000000000000PLATFORM_FLAVOR ?= ls1012ardb $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_GIC,y) $(call force,CFG_16550_UART,y) $(call force,CFG_LS,y) $(call force,CFG_DRAM0_BASE,0x80000000) $(call force,CFG_TEE_OS_DRAM0_SIZE,0x4000000) CFG_ENABLE_EMBEDDED_TESTS ?= y CFG_PKCS11_TA ?= y CFG_CORE_HEAP_SIZE ?= 131072 ifeq ($(PLATFORM_FLAVOR),ls1012ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_DRAM0_SIZE,0x40000000) $(call force,CFG_CORE_CLUSTER_SHIFT,2) CFG_NUM_THREADS ?= 2 CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),ls1043ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,2) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),ls1046ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,2) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),ls1088ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,2) $(call force,CFG_ARM_GICV3,y) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),ls2088ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,1) $(call force,CFG_ARM_GICV3,y) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),lx2160aqds) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,16) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_DRAM1_BASE,0x2080000000) $(call force,CFG_DRAM1_SIZE,0x1F80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,1) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_PL011,y) $(call force,CFG_CORE_ARM64_PA_BITS,40) $(call force,CFG_EMBED_DTB,y) $(call force,CFG_EMBED_DTB_SOURCE_FILE,fsl-lx2160a-qds.dts) CFG_LS_I2C ?= y CFG_LS_GPIO ?= y CFG_LS_DSPI ?= y CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),lx2160ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,16) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_DRAM1_BASE,0x2080000000) $(call force,CFG_DRAM1_SIZE,0x1F80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,1) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_PL011,y) $(call force,CFG_CORE_ARM64_PA_BITS,40) $(call force,CFG_EMBED_DTB,y) $(call force,CFG_EMBED_DTB_SOURCE_FILE,fsl-lx2160a-rdb.dts) CFG_LS_I2C ?= y CFG_LS_GPIO ?= y CFG_LS_DSPI ?= y CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),ls1028ardb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_DRAM0_SIZE,0x80000000) $(call force,CFG_CORE_CLUSTER_SHIFT,1) $(call force,CFG_ARM_GICV3,y) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(platform-flavor-armv8),1) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) CFG_TZDRAM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - CFG_TEE_OS_DRAM0_SIZE) CFG_TZDRAM_SIZE ?= ( CFG_TEE_OS_DRAM0_SIZE - CFG_SHMEM_SIZE) #CFG_SHMEM_START (Non-Secure shared memory) needs to be 2MB aligned boundary for TZASC 380 configuration. CFG_SHMEM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - CFG_SHMEM_SIZE) $(call force,CFG_ARM64_core,y) CFG_USER_TA_TARGETS ?= ta_arm64 else #In ARMv7 platform CFG_SHMEM_SIZE is different to that of ARMv8 platforms. CFG_TZDRAM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - CFG_TEE_OS_DRAM0_SIZE) CFG_TZDRAM_SIZE ?= ( CFG_TEE_OS_DRAM0_SIZE - (2*CFG_SHMEM_SIZE)) #CFG_SHMEM_START (Non-Secure shared memory) needs to be 2MB aligned boundary for TZASC 380 configuration. CFG_SHMEM_START ?= ((CFG_DRAM0_BASE + CFG_DRAM0_SIZE) - (2*CFG_SHMEM_SIZE)) endif #Keeping Number of TEE thread equal to number of cores on the SoC CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE) ifneq ($(CFG_ARM64_core),y) $(call force,CFG_SECONDARY_INIT_CNTFRQ,y) endif CFG_CRYPTO_SIZE_OPTIMIZATION ?= n # NXP CAAM support is not enabled by default and can be enabled # on the command line CFG_NXP_CAAM ?= n optee_os-4.3.0/core/arch/arm/plat-ls/main.c000066400000000000000000000140151464416617300204400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018 NXP * Copyright (C) 2015 Freescale Semiconductor, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #ifdef CFG_PL011 #include #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_PL011 static struct pl011_data console_data; #else static struct ns16550_data console_data; #endif register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); #if !defined(PLATFORM_FLAVOR_lx2160aqds) && !defined(PLATFORM_FLAVOR_lx2160ardb) register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); #endif #if defined(PLATFORM_FLAVOR_lx2160ardb) || defined(PLATFORM_FLAVOR_lx2160aqds) register_ddr(CFG_DRAM0_BASE, (CFG_TZDRAM_START - CFG_DRAM0_BASE)); #ifdef CFG_DRAM1_BASE register_ddr(CFG_DRAM1_BASE, CFG_DRAM1_SIZE); #endif #endif #ifdef DCFG_BASE register_phys_mem_pgdir(MEM_AREA_IO_NSEC, DCFG_BASE, CORE_MMU_PGDIR_SIZE); #endif #ifdef CFG_ARM32_core void plat_primary_init_early(void) { vaddr_t addr; #if defined(CFG_BOOT_SECONDARY_REQUEST) /* set secondary entry address */ io_write32(DCFG_BASE + DCFG_SCRATCHRW1, __compiler_bswap32(TEE_LOAD_ADDR)); /* release secondary cores */ io_write32(DCFG_BASE + DCFG_CCSR_BRR /* cpu1 */, __compiler_bswap32(0x1 << 1)); dsb(); sev(); #endif /* configure CSU */ /* first grant all peripherals */ for (addr = CSU_BASE + CSU_CSL_START; addr != CSU_BASE + CSU_CSL_END; addr += 4) io_write32(addr, __compiler_bswap32(CSU_ACCESS_ALL)); /* restrict key preipherals from NS */ io_write32(CSU_BASE + CSU_CSL30, __compiler_bswap32(CSU_ACCESS_SEC_ONLY)); io_write32(CSU_BASE + CSU_CSL37, __compiler_bswap32(CSU_ACCESS_SEC_ONLY)); /* lock the settings */ for (addr = CSU_BASE + CSU_CSL_START; addr != CSU_BASE + CSU_CSL_END; addr += 4) io_setbits32(addr, __compiler_bswap32(CSU_SETTING_LOCK)); } #endif void plat_console_init(void) { #ifdef CFG_PL011 /* * Everything for uart driver initialization is done in bootloader. * So not reinitializing console. */ pl011_init(&console_data, CONSOLE_UART_BASE, 0, 0); #else ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U8, 0); #endif register_serial_console(&console_data.chip); } #if defined(PLATFORM_FLAVOR_lx2160aqds) || defined(PLATFORM_FLAVOR_lx2160ardb) static TEE_Result get_gic_base_addr_from_dt(paddr_t *gic_addr) { paddr_t paddr = 0; size_t size = 0; void *fdt = get_embedded_dt(); int gic_offset = 0; gic_offset = fdt_path_offset(fdt, "/soc/interrupt-controller@6000000"); if (gic_offset < 0) gic_offset = fdt_path_offset(fdt, "/interrupt-controller@6000000"); if (gic_offset > 0) { paddr = fdt_reg_base_address(fdt, gic_offset); if (paddr == DT_INFO_INVALID_REG) { EMSG("GIC: Unable to get base addr from DT"); return TEE_ERROR_ITEM_NOT_FOUND; } size = fdt_reg_size(fdt, gic_offset); if (size == DT_INFO_INVALID_REG_SIZE) { EMSG("GIC: Unable to get size of base addr from DT"); return TEE_ERROR_ITEM_NOT_FOUND; } } else { EMSG("Unable to get gic offset node"); return TEE_ERROR_ITEM_NOT_FOUND; } /* make entry in page table */ if (!core_mmu_add_mapping(MEM_AREA_IO_SEC, paddr, size)) { EMSG("GIC controller base MMU PA mapping failure"); return TEE_ERROR_GENERIC; } *gic_addr = paddr; return TEE_SUCCESS; } #endif #define SVR_MINOR_MASK 0xF static void get_gic_offset(uint32_t *offsetc, uint32_t *offsetd) { #ifdef PLATFORM_FLAVOR_ls1043ardb vaddr_t addr = 0; uint32_t rev = 0; addr = (vaddr_t)phys_to_virt(DCFG_BASE + DCFG_SVR_OFFSET, MEM_AREA_IO_NSEC, 1); if (!addr) { EMSG("Failed to get virtual address for SVR register"); panic(); } rev = get_be32((void *)addr); if ((rev & SVR_MINOR_MASK) == 1) { *offsetc = GICC_OFFSET_REV1_1; *offsetd = GICD_OFFSET_REV1_1; } else { *offsetc = GICC_OFFSET_REV1; *offsetd = GICD_OFFSET_REV1; } #else *offsetc = GICC_OFFSET; *offsetd = GICD_OFFSET; #endif } void boot_primary_init_intc(void) { paddr_t gic_base = 0; uint32_t gicc_offset = 0; uint32_t gicd_offset = 0; #if defined(PLATFORM_FLAVOR_lx2160aqds) || defined(PLATFORM_FLAVOR_lx2160ardb) if (get_gic_base_addr_from_dt(&gic_base)) EMSG("Failed to get GIC base addr from DT"); #else gic_base = GIC_BASE; #endif get_gic_offset(&gicc_offset, &gicd_offset); gic_init(gic_base + gicc_offset, gic_base + gicd_offset); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } optee_os-4.3.0/core/arch/arm/plat-ls/plat_init.S000066400000000000000000000054041464416617300214610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Wind River Systems. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Entry points for the A9 inits, A9 revision specific or not. * It is assume no stack is available when these routines are called. * It is assume each routine is called with return address in LR * and with ARM registers R0, R1, R2, R3 being scratchable. */ #include #include #include #include .section .text .balign 4 .code 32 /* * platform early configuration * * Use scratables registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* * Disallow NSec to mask FIQ [bit4: FW=0] * Allow NSec to manage Imprecise Abort [bit5: AW=1] * Imprecise Abort trapped to Abort Mode [bit3: EA=0] * In Sec world, FIQ trapped to FIQ Mode [bit2: FIQ=0] * IRQ always trapped to IRQ Mode [bit1: IRQ=0] * Secure World [bit0: NS=0] */ mov r0, #SCR_AW write_scr r0 /* write Secure Configuration Register */ /* * Mandated HW config loaded * * SCTLR = 0x00000000 * * ACTRL = 0x00000040 * - core NOT booted in full SMP (FW bit0=0) * * NSACR = 0x00000C00 * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) */ mov_imm r0, 0x00000000 write_sctlr r0 mov_imm r0, 0x00000040 write_actlr r0 mov_imm r0, 0x00000C00 write_nsacr r0 mov pc, lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-ls/platform_config.h000066400000000000000000000074031464416617300226750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * All rights reserved. * Copyright 2021 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #define STACK_ALIGNMENT 64 /* console uart define */ #define CONSOLE_UART_BASE UART0_BASE /* Platform specific defines */ #if defined(PLATFORM_FLAVOR_ls1012ardb) /* DUART 1 */ #define UART0_BASE 0x021C0500 #define GIC_BASE 0x01400000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define CAAM_BASE 0x01700000 #define CAAM_SIZE 0x100000 #endif #if defined(PLATFORM_FLAVOR_ls1043ardb) #define UART0_BASE 0x021C0500 #define GIC_BASE 0x01400000 #define GICC_OFFSET_REV1 0x2000 #define GICD_OFFSET_REV1 0x1000 #define GICC_OFFSET_REV1_1 0x20000 #define GICD_OFFSET_REV1_1 0x10000 #define CAAM_BASE 0x01700000 #define CAAM_SIZE 0x100000 #define DCFG_BASE 0x01EE0000 #define DCFG_SVR_OFFSET 0xA4 #endif #if defined(PLATFORM_FLAVOR_ls1046ardb) /* DUART 1 */ #define UART0_BASE 0x021C0500 #define GIC_BASE 0x01400000 #define GICC_OFFSET 0x20000 #define GICD_OFFSET 0x10000 #define CAAM_BASE 0x01700000 #define CAAM_SIZE 0x100000 #endif #if defined(PLATFORM_FLAVOR_ls1088ardb) /* DUART 1 */ #define UART0_BASE 0x021C0500 #define GIC_BASE 0x06000000 #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x0 #define CAAM_BASE 0x08000000 #define CAAM_SIZE 0x100000 #endif #if defined(PLATFORM_FLAVOR_ls2088ardb) /* DUART 1 */ #define UART0_BASE 0x021C0600 #define GIC_BASE 0x06000000 #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x0 #define CAAM_BASE 0x08000000 #define CAAM_SIZE 0x100000 #endif #if defined(PLATFORM_FLAVOR_ls1028ardb) /* DUART 1 */ #define UART0_BASE 0x021C0500 #define GIC_BASE 0x06000000 #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x0 #define CAAM_BASE 0x08000000 #define CAAM_SIZE 0x100000 #endif #if defined(PLATFORM_FLAVOR_lx2160ardb) /* DUART 1 */ #define UART0_BASE 0x021C0000 #define GIC_BASE 0x06000000 #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x0 #define CAAM_BASE 0x08000000 #define CAAM_SIZE 0x100000 #endif #if defined(PLATFORM_FLAVOR_lx2160aqds) /* DUART 1 */ #define UART0_BASE 0x021C0000 #define GIC_BASE 0x06000000 #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x0 #define CAAM_BASE 0x08000000 #define CAAM_SIZE 0x100000 #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-ls/sub.mk000066400000000000000000000001151464416617300204660ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-$(CFG_ARM32_core) += plat_init.S optee_os-4.3.0/core/arch/arm/plat-marvell/000077500000000000000000000000001464416617300203735ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-marvell/armada3700/000077500000000000000000000000001464416617300221325ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-marvell/armada3700/hal_sec_perf.c000066400000000000000000000152621464416617300247160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Marvell International Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #define PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC, 1)) #define MCU_BASE 0xD0000000 #define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044) #define TRUSTZONE_LOCK BIT(31) #define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3)) #define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3)) #define RW_PERM 0x0 #define RO_PERM 0x1 #define WO_PERM 0x2 #define ABORT_PERM 0x3 #define MAX_RANGE_NUM 16 #define INVALID_SIZE_CODE 0xff #ifdef TEE_RES_CFG_16M #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M) #elif defined(TEE_RES_CFG_24M) #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M) #elif defined(TEE_RES_CFG_8M) #define RSVD_SEC_MEM SIZE_8M #else #error "no reserved secure memory defined." #endif #define RA_ADDR TZDRAM_BASE #define RA_SIZE TZDRAM_SIZE #define RA_PERM ABORT_PERM #define TZ_IS_VALID(data) ((data) & (0x1)) #define TZ_SET_VALID(data) ((data) |= (0x1)) #define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1)) #define TZ_SET_PERM(data, val) \ do { \ (data) &= (~(0x3 << 1)); \ (data) |= (((val) & 0x3) << 1); \ } while (0) #define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3)) #define TZ_SET_RZ_EN(data, val) \ do { \ (data) &= (~(0x1 << 3)); \ (data) |= (((val) & 0x1) << 3); \ } while (0) #define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 8)) >> 8)) #define TZ_SET_AREA_LEN_CODE(data, val) \ do { \ (data) &= (~(0x1F << 8)); \ (data) |= (((val) & 0x1F) << 8); \ } while (0) #define TZ_GET_START_ADDR_L(data, ret) \ ((ret) = (((data) & 0xFFF00000))) #define TZ_SET_START_ADDR_L(data, val) \ do { \ (data) &= (~0xFFF00000); \ (data) |= (((val) & 0xFFF00000)); \ } while (0) #define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4)) #define TZ_SET_UR_PERM(data, val) \ do { \ (data) &= (~(0x3 << 4)); \ (data) |= (((val) & 0x3) << 4); \ } while (0) #define TZ_GET_UR_RZ_EN(data, val) \ ((ret) = (((data) & (0x1 << 6)) >> 6)) #define TZ_SET_UR_RZ_EN(data, val) \ do { \ (data) &= (~(0x1 << 6)); \ (data) |= (((val) & 0x1) << 6); \ } while (0) /* armada3700 mini region size is 1M */ #define RANGE_SIZE_TO_CODE(size, code, i) \ do { \ (code) = INVALID_SIZE_CODE; \ for ((i) = 0; (i) <= 0x1d; (i)++) { \ if (((uint32_t)0x1 << (i)) == ((size) >> 20)) { \ (code) = (i); \ break; \ } \ } \ } while (0) #define TZ_LOCK_MC(x) \ do { \ (x) = io_read32(MCU_MC_CONTROL_0_REG); \ (x) |= (TRUSTZONE_LOCK); \ io_write32(MCU_MC_CONTROL_0_REG, (x)); \ } while (0) register_phys_mem_pgdir(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_PGDIR_SIZE); static int32_t _find_valid_range(void) { uint32_t i; uint32_t tmp; for (i = 0; i < MAX_RANGE_NUM; i++) { tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); if (!TZ_IS_VALID(tmp)) return i; } return -1; } static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm) { uint32_t data; uint32_t sizecode; int32_t valid_range; uint32_t i; if (!IS_ALIGNED(addr, SIZE_1M)) { EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!", addr); return -1; } if (!IS_ALIGNED(size, SIZE_1M)) { EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!", size); return -1; } RANGE_SIZE_TO_CODE(size, sizecode, i); if (sizecode == INVALID_SIZE_CODE) { EMSG("not valid region size(2^n)! size:0x%" PRIx32, size); return -1; } valid_range = _find_valid_range(); if (valid_range == -1) { EMSG("ERR: can't find valid range!"); return -1; } data = io_read32(MCU_TZ_RANGE_LOW_REG(valid_range)); TZ_SET_VALID(data); TZ_SET_PERM(data, perm); TZ_SET_AREA_LEN_CODE(data, sizecode); TZ_SET_START_ADDR_L(data, addr); if (!valid_range) { /* Set Undefine Range RW */ TZ_SET_UR_PERM(data, RW_PERM); TZ_SET_UR_RZ_EN(data, 0); } io_write32(MCU_TZ_RANGE_LOW_REG(valid_range), data); return 0; } static void _dump_range(void) { uint32_t i; uint32_t tmp; uint32_t __maybe_unused sizecode_read; uint32_t __maybe_unused sizem; uint32_t __maybe_unused addr_read; uint32_t __maybe_unused perm_read; for (i = 0; i < MAX_RANGE_NUM; i++) { tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); if (TZ_IS_VALID(tmp)) { TZ_GET_PERM(tmp, perm_read); TZ_GET_AREA_LEN_CODE(tmp, sizecode_read); TZ_GET_START_ADDR_L(tmp, addr_read); DMSG("Range Num%" PRIu32 ": Reg 0x%" PRIx64 " = 0x%" PRIx32, i, MCU_TZ_RANGE_LOW_REG(i), tmp); DMSG("AddrL: 0x%08" PRIx32, addr_read); DMSG("Size: %" PRIu32 "M", (0x1 << sizecode_read)); DMSG("Perm: %" PRIu32, perm_read); } } } static void _set_range(uint32_t addr, uint32_t size, uint32_t perm) { uint32_t rgn_addr = addr; uint32_t rgn_size = size; /* minimum region size is 1M and must be times of 1M */ uint32_t p = 0x100000; while (1) { if ((p * 2) > rgn_size) { set_range(rgn_addr, p, perm); rgn_addr += p; rgn_size -= p; if (rgn_size == 0) break; p = 0x100000; } else p <<= 1; } } static TEE_Result init_sec_perf(void) { uint32_t tmp; /* Set Secure Memory Region */ DMSG("sec-rgn size: ra = 0x%" PRIx32 ", size = 0x%" PRIx64, RA_ADDR, RA_SIZE); _set_range(RA_ADDR, RA_SIZE, RA_PERM); /* Close TZ register modification */ TZ_LOCK_MC(tmp); _dump_range(); return TEE_SUCCESS; } service_init(init_sec_perf); optee_os-4.3.0/core/arch/arm/plat-marvell/armada7k8k/000077500000000000000000000000001464416617300223255ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c000066400000000000000000000170301464416617300251040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Marvell International Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #define PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC, 1)) #define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044) #define TRUSTZONE_LOCK BIT(31) #define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3)) #define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3)) #define RW_PERM 0x0 #define RO_PERM 0x1 #define WO_PERM 0x2 #define ABORT_PERM 0x3 #define MAX_RANGE_NUM 16 #define INVALID_SIZE_CODE 0xff #ifdef TEE_RES_CFG_16M #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M) #elif defined(TEE_RES_CFG_24M) #define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M) #elif defined(TEE_RES_CFG_8M) #define RSVD_SEC_MEM SIZE_8M #else #error "no reserved secure memory defined." #endif #define RA_ADDR TZDRAM_BASE #define RA_SIZE TZDRAM_SIZE #define RA_PERM ABORT_PERM #define TZ_IS_VALID(data) ((data) & (0x1)) #define TZ_SET_VALID(data) ((data) |= (0x1)) #define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1)) #define TZ_SET_PERM(data, val) \ do { \ (data) &= (~(0x3 << 1)); \ (data) |= (((val) & 0x3) << 1); \ } while (0) #define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3)) #define TZ_SET_RZ_EN(data, val) \ do { \ (data) &= (~(0x1 << 3)); \ (data) |= (((val) & 0x1) << 3); \ } while (0) #define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 7)) >> 7)) #define TZ_SET_AREA_LEN_CODE(data, val) \ do { \ (data) &= (~(0x1F << 7)); \ (data) |= (((val) & 0x1F) << 7); \ } while (0) #define TZ_GET_START_ADDR_L(data, ret) \ ((ret) = (((data) & 0xFFFFF000))) #define TZ_SET_START_ADDR_L(data, val) \ do { \ (data) &= (~0xFFFFF000); \ (data) |= (((val) & 0xFFFFF000)); \ } while (0) #define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4)) #define TZ_SET_UR_PERM(data, val) \ do { \ (data) &= (~(0x3 << 4)); \ (data) |= (((val) & 0x3) << 4); \ } while (0) #define TZ_GET_UR_RZ_EN(data, val) \ ((ret) = (((data) & (0x1 << 6)) >> 6)) #define TZ_SET_UR_RZ_EN(data, val) \ do { \ (data) &= (~(0x1 << 6)); \ (data) |= (((val) & 0x1) << 6); \ } while (0) /* armada mini region size is 1M */ #define RANGE_SIZE_TO_CODE(size, code, i) \ do { \ (code) = INVALID_SIZE_CODE; \ for ((i) = 8; (i) <= 0x1f; (i)++) { \ if (((uint32_t)0x1 << (i)) == ((size) >> 12)) { \ (code) = (i); \ break; \ } \ } \ } while (0) #define RANGE_CODE_TO_SIZE_K(code, sizek) ((sizek) = ((4) << (code))) #define TZ_LOCK_MC(x) \ do { \ (x) = io_read32(MCU_MC_CONTROL_0_REG); \ (x) |= (TRUSTZONE_LOCK); \ io_write32(MCU_MC_CONTROL_0_REG, (x)); \ } while (0) register_phys_mem_pgdir(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, MC_SCR_REGISTER, CORE_MMU_PGDIR_SIZE); static int32_t _find_valid_range(void) { uint32_t i; uint32_t tmp; for (i = 0; i < MAX_RANGE_NUM; i++) { tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); if (!TZ_IS_VALID(tmp)) return i; } return -1; } static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm) { uint32_t data; uint32_t sizecode; int32_t valid_range; uint32_t i; if (!IS_ALIGNED(addr, SIZE_1M)) { EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!", addr); return -1; } if (!IS_ALIGNED(size, SIZE_1M)) { EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!", size); return -1; } if (!IS_ALIGNED(addr, size)) { EMSG("region size(0x%" PRIx32 ") not align with addr(0x%" PRIx32 ")", size, addr); return -1; } RANGE_SIZE_TO_CODE(size, sizecode, i); if (sizecode == INVALID_SIZE_CODE) { EMSG("not valid region size(2^n)! size:0x%" PRIx32, size); return -1; } valid_range = _find_valid_range(); if (valid_range == -1) { EMSG("ERR: can't find valid range!"); return -1; } data = io_read32(MCU_TZ_RANGE_LOW_REG(valid_range)); TZ_SET_VALID(data); TZ_SET_PERM(data, perm); TZ_SET_AREA_LEN_CODE(data, sizecode); TZ_SET_START_ADDR_L(data, addr); if (!valid_range) { /* Set Undefine Range RW */ TZ_SET_UR_PERM(data, RW_PERM); TZ_SET_UR_RZ_EN(data, 0); } io_write32(MCU_TZ_RANGE_LOW_REG(valid_range), data); return 0; } static void _dump_range(void) { uint32_t i; uint32_t tmp; uint32_t sizek; uint32_t sizecode_read; uint32_t __maybe_unused sizem; uint32_t __maybe_unused addr_read; uint32_t __maybe_unused perm_read; for (i = 0; i < MAX_RANGE_NUM; i++) { tmp = io_read32(MCU_TZ_RANGE_LOW_REG(i)); if (TZ_IS_VALID(tmp)) { TZ_GET_PERM(tmp, perm_read); TZ_GET_AREA_LEN_CODE(tmp, sizecode_read); TZ_GET_START_ADDR_L(tmp, addr_read); DMSG("Range Num%" PRIu32 ": Reg 0x%" PRIx64 " = 0x%" PRIx32, i, MCU_TZ_RANGE_LOW_REG(i), tmp); DMSG("AddrL: 0x%08" PRIx32, addr_read); RANGE_CODE_TO_SIZE_K(sizecode_read, sizek); sizem = sizek >> 10; DMSG("Size: %" PRIu32 "K, %" PRIu32 "M", sizek, sizem); DMSG("Perm: %" PRIu32, perm_read); } } } static uint32_t _find_granule(uint32_t addr, uint32_t size) { /* max supported granule for armada is 8TB * but 2GB is far enough here */ uint32_t max_granule = SIZE_2G; while (max_granule >= SIZE_4K) { /* min granule is 4kB */ if (max_granule <= size && IS_ALIGNED(addr, max_granule)) return max_granule; max_granule >>= 1; } return 0; /* cannot find a valid granule */ } static void _set_range(uint32_t addr, uint32_t size, uint32_t perm) { uint32_t rgn_addr = addr; uint32_t rgn_size = size; uint32_t p; while (rgn_size) { p = _find_granule(rgn_addr, rgn_size); if (!p) panic("cannot find a suitable granule!"); if (set_range(rgn_addr, p, perm)) panic("set_range failed!"); rgn_addr += p; rgn_size -= p; } } static TEE_Result init_sec_perf(void) { uint32_t tmp; /* MC_SCR config: deny NS access to MC registers */ tmp = io_read32(PHY_2_VIR(MC_SCR_REGISTER)); tmp |= 0x1; io_write32(PHY_2_VIR(MC_SCR_REGISTER), tmp); /* Set Secure Memory Region */ DMSG("sec-rgn size: ra = 0x%08" PRIx32 ", size = 0x%" PRIx32, RA_ADDR, RA_SIZE); _set_range(RA_ADDR, RA_SIZE, RA_PERM); /* Close TZ register modification */ TZ_LOCK_MC(tmp); _dump_range(); return TEE_SUCCESS; } service_init(init_sec_perf); optee_os-4.3.0/core/arch/arm/plat-marvell/cn10k/000077500000000000000000000000001464416617300213075ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-marvell/cn10k/core_pos.S000066400000000000000000000005221464416617300232430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023 Marvell. */ #include #include #include FUNC get_core_pos_mpidr , : /* No clusters, core position is affinity2 of MPIDR_EL1 */ mov_imm x1, MPIDR_AFFLVL_MASK and x0, x1, x0, LSR #MPIDR_AFF2_SHIFT ret END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-marvell/conf.mk000066400000000000000000000127111464416617300216530ustar00rootroot00000000000000PLATFORM_FLAVOR ?= armada7k8k ifeq ($(PLATFORM_FLAVOR),armada7k8k) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_TZDRAM_START,0x04400000) $(call force,CFG_TZDRAM_SIZE,0x00C00000) $(call force,CFG_SHMEM_START,0x05000000) $(call force,CFG_SHMEM_SIZE,0x00400000) $(call force,CFG_TEE_RAM_VA_SIZE,0x00400000) # If Secure Data Path is enabled, uses the TZDRAM last 4MByte $(call force,CFG_TEE_SDP_MEM_SIZE,0x00400000) platform-debugger-arm := 1 $(call force,CFG_8250_UART,y) endif ifeq ($(PLATFORM_FLAVOR),armada3700) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_TZDRAM_START,0x04400000) $(call force,CFG_TZDRAM_SIZE,0x00C00000) $(call force,CFG_SHMEM_START,0x05000000) $(call force,CFG_SHMEM_SIZE,0x00400000) $(call force,CFG_TEE_RAM_VA_SIZE,0x00400000) # If Secure Data Path is enabled, uses the TZDRAM last 4MByte $(call force,CFG_TEE_SDP_MEM_SIZE,0x00400000) platform-debugger-arm := 1 $(call force,CFG_MVEBU_UART,y) $(call force,CFG_ARM_GICV3,y) endif ifeq ($(PLATFORM_FLAVOR),otx2t96) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,24) $(call force,CFG_CLUSTERS_PER_NODE,4) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x01000000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_HW_UNQ_KEY_SUPPORT ?= y CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(PLATFORM_FLAVOR),otx2f95) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,6) $(call force,CFG_CLUSTERS_PER_NODE,1) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x01000000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_HW_UNQ_KEY_SUPPORT ?= y CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(PLATFORM_FLAVOR),otx2t98) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,36) $(call force,CFG_CLUSTERS_PER_NODE,6) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x01000000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) #$(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_HW_UNQ_KEY_SUPPORT ?= y CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(PLATFORM_FLAVOR),cn10ka) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,24) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x03400000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(PLATFORM_FLAVOR),cn10kb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x03400000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(PLATFORM_FLAVOR),cnf10ka) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,18) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x03400000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(PLATFORM_FLAVOR),cnf10kb) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,12) $(call force,CFG_TZDRAM_START,0x00001000) $(call force,CFG_TZDRAM_SIZE,0x000a00000) $(call force,CFG_SHMEM_START,0x03400000) $(call force,CFG_SHMEM_SIZE,0x00800000) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,48) $(call force,CFG_LPAE_ADDR_SPACE_BITS,36) $(call force,CFG_PL011,y) $(call force,CFG_ARM_GICV3,y) CFG_USER_TA_TARGETS ?= ta_arm64 CFG_NUM_THREADS ?= CFG_TEE_CORE_NB_CORE CFG_CORE_HEAP_SIZE ?= 131072 endif ifeq ($(platform-debugger-arm),1) # ARM debugger needs this platform-cflags-debug-info = -gdwarf-2 platform-aflags-debug-info = -gdwarf-2 endif $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_ARM64_core,y) $(call force,CFG_GIC,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_CORE_CLUSTER_SHIFT,1) CFG_WITH_STATS ?= y optee_os-4.3.0/core/arch/arm/plat-marvell/main.c000066400000000000000000000072551464416617300214740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Marvell International Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #if defined(PLATFORM_FLAVOR_armada7k8k) #include #elif defined(PLATFORM_FLAVOR_armada3700) #include #endif #ifdef CFG_PL011 #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(PLATFORM_FLAVOR_armada7k8k) static struct serial8250_uart_data console_data; #elif defined(PLATFORM_FLAVOR_armada3700) static struct mvebu_uart_data console_data; #elif CFG_PL011 static struct pl011_data console_data; #endif register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); #ifdef CFG_HW_UNQ_KEY_SUPPORT register_phys_mem(MEM_AREA_IO_SEC, PLAT_MARVELL_FUSF_FUSE_BASE, SMALL_PAGE_SIZE); #endif #ifdef GIC_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, CORE_MMU_PGDIR_SIZE); #ifdef GICC_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, CORE_MMU_PGDIR_SIZE); #endif void boot_primary_init_intc(void) { paddr_t gicd_base = 0; paddr_t gicc_base = 0; #ifdef GICC_BASE gicc_base = GIC_BASE + GICC_OFFSET; #endif gicd_base = GIC_BASE + GICD_OFFSET; gic_init(gicc_base, gicd_base); } #endif void plat_console_init(void) { #if defined(PLATFORM_FLAVOR_armada7k8k) serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); #elif defined(PLATFORM_FLAVOR_armada3700) mvebu_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); #elif CFG_PL011 pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); #endif register_serial_console(&console_data.chip); } #ifdef CFG_HW_UNQ_KEY_SUPPORT TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { void *huk = phys_to_virt(PLAT_MARVELL_FUSF_FUSE_BASE + PLAT_MARVELL_FUSF_HUK_OFFSET, MEM_AREA_IO_SEC, sizeof(hwkey->data)); if (!huk) { EMSG("\nH/W Unique key is not fetched from the platform."); return TEE_ERROR_SECURITY; } memcpy(&hwkey->data[0], huk, sizeof(hwkey->data)); return TEE_SUCCESS; } #endif optee_os-4.3.0/core/arch/arm/plat-marvell/otx2/000077500000000000000000000000001464416617300212675ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-marvell/otx2/core_pos.S000066400000000000000000000005621464416617300232270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Marvell International Ltd. */ #include #include FUNC get_core_pos_mpidr , : ubfx x1, x0, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS mov x2, #CFG_CLUSTERS_PER_NODE mul x1, x1, x2 ubfx x2, x0, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS add x0, x1, x2 ret END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-marvell/platform_config.h000066400000000000000000000114001464416617300237110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017 Marvell International Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #ifdef ARM64 #ifdef CFG_WITH_PAGER #error "Pager not supported yet" #endif #else #error "32 bit mode not supported yet" #endif /*ARM64*/ #if defined(PLATFORM_FLAVOR_armada7k8k) /* * armada7k8k specifics. */ #define TEE_RES_CFG_8M #define MVEBU_REGS_BASE 0xF0000000 /* GICv2 */ #define MVEBU_GICD_BASE 0x210000 #define MVEBU_GICC_BASE 0x220000 #define GIC_DIST_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE) #define GIC_CPU_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE) #define GIC_BASE GIC_DIST_BASE /* UART */ #define PLAT_MARVELL_BOOT_UART_BASE (MVEBU_REGS_BASE + 0x512000) #define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 200000000 #define MARVELL_CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE #define GICC_OFFSET 0x10000 #define GICD_OFFSET 0x0 #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) /* MCU */ #define MCU_BASE 0xF0020000 #define MCU_REG_SIZE SIZE_4K #define MC_SCR_REGISTER 0xF06F0204 #define MC_SCR_REG_SIZE SIZE_4K #elif defined(PLATFORM_FLAVOR_armada3700) /* * armada3700 specifics. */ #define TEE_RES_CFG_8M #define MVEBU_REGS_BASE 0xD0000000 /* GICv3 */ #define MVEBU_GICD_BASE 0x1D00000 #define MVEBU_GICR_BASE 0x1D40000 #define MVEBU_GICC_BASE 0x1D80000 #define GIC_DIST_BASE (MVEBU_REGS_BASE + MVEBU_GICD_BASE) #define GIC_RDIS_BASE (MVEBU_REGS_BASE + MVEBU_GICR_BASE) #define GIC_CPU_BASE (MVEBU_REGS_BASE + MVEBU_GICC_BASE) #define GIC_BASE GIC_DIST_BASE #define GICC_OFFSET (0x80000) #define GICR_OFFSET (0x40000) #define GICD_OFFSET (0x0) #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) /* UART */ #define PLAT_MARVELL_BOOT_UART_BASE (MVEBU_REGS_BASE + 0x12000) #define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 25804800 #define MARVELL_CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE #elif defined(PLATFORM_FLAVOR_otx2t96) || defined(PLATFORM_FLAVOR_otx2f95) || \ defined(PLATFORM_FLAVOR_otx2t98) /* * OcteonTX2(otx2) specifics. */ /* GICv3 */ #define GIC_BASE 0x801000000000ll #define GICD_OFFSET (0x0) #define GICD_BASE (GIC_BASE + GICD_OFFSET) /* UART */ #define PLAT_MARVELL_BOOT_UART_BASE 0x87E028000000ll #define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 16666656 #define MARVELL_CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE /* eFUSE */ #define PLAT_MARVELL_FUSF_FUSE_BASE 0x87E004000000ll #define PLAT_MARVELL_FUSF_HUK_OFFSET (0x90) #elif defined(PLATFORM_FLAVOR_cn10ka) || defined(PLATFORM_FLAVOR_cn10kb) || \ defined(PLATFORM_FLAVOR_cnf10ka) || defined(PLATFORM_FLAVOR_cnf10kb) /* * cn10k specifics. */ /* GICv3 */ #define GIC_BASE 0x801000000000ll #define GICD_OFFSET 0x0 #define GICD_BASE (GIC_BASE + GICD_OFFSET) /* UART */ #define PLAT_MARVELL_BOOT_UART_BASE 0x87E028000000ll #define PLAT_MARVELL_BOOT_UART_CLK_IN_HZ 16666656 #define MARVELL_CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_BASE PLAT_MARVELL_BOOT_UART_BASE #else #error "Unknown platform flavor" #endif #define UART_BAUDRATE MARVELL_CONSOLE_BAUDRATE #define CONSOLE_BAUDRATE UART_BAUDRATE #define CONSOLE_UART_CLK_IN_HZ PLAT_MARVELL_BOOT_UART_CLK_IN_HZ #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-marvell/sub.mk000066400000000000000000000006121464416617300215140ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c ifneq (,$(filter $(PLATFORM_FLAVOR),otx2t96 otx2f95 otx2t98)) srcs-$(CFG_ARM64_core) += otx2/core_pos.S endif ifneq (,$(filter $(PLATFORM_FLAVOR),cn10ka cn10kb cnf10ka cnf10kb)) srcs-$(CFG_ARM64_core) += cn10k/core_pos.S endif srcs-$(PLATFORM_FLAVOR_armada7k8k) += armada7k8k/hal_sec_perf.c srcs-$(PLATFORM_FLAVOR_armada3700) += armada3700/hal_sec_perf.c optee_os-4.3.0/core/arch/arm/plat-mediatek/000077500000000000000000000000001464416617300205145ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-mediatek/conf.mk000066400000000000000000000052671464416617300220040ustar00rootroot00000000000000PLATFORM_FLAVOR ?= mt8173 CFG_ARM64_core ?= y include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_8250_UART,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) # default DRAM base address CFG_DRAM_BASE ?= 0x40000000 # default DRAM size 1 GiB CFG_DRAM_SIZE ?= 0x40000000 # When need to create a virtual memory pool for mapping other # physical address, enable the config to increase MAX_XLAT_TABLES. CFG_MTK_RESERVED_VA ?= n ifeq ($(PLATFORM_FLAVOR),mt8173) # 2**1 = 2 cores per cluster $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_CORE_CLUSTER_SHIFT,1) CFG_TZDRAM_START ?= 0xbe000000 CFG_TZDRAM_SIZE ?= 0x01e00000 CFG_SHMEM_START ?= 0xbfe00000 CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),mt8175) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_CORE_CLUSTER_SHIFT,2) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) CFG_TZDRAM_START ?= 0x43200000 CFG_TZDRAM_SIZE ?= 0x00a00000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),mt8516) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_CORE_CLUSTER_SHIFT,2) CFG_TZDRAM_START ?= 0x4fd00000 CFG_TZDRAM_SIZE ?= 0x00300000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),mt8183) $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_CORE_CLUSTER_SHIFT,2) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) CFG_TZDRAM_START ?= 0x4fd00000 CFG_TZDRAM_SIZE ?= 0x00300000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),mt8195) $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_CORE_CLUSTER_SHIFT,2) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) CFG_TZDRAM_START ?= 0x43200000 CFG_TZDRAM_SIZE ?= 0x00a00000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),mt8188) $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_CORE_CLUSTER_SHIFT,2) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) CFG_TZDRAM_START ?= 0x43200000 CFG_TZDRAM_SIZE ?= 0x00a00000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),mt7988) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_CORE_CLUSTER_SHIFT,1) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_GIC,y) $(call force,CFG_WITH_SOFTWARE_PRNG,y) CFG_TZDRAM_START ?= 0x43041000 CFG_TZDRAM_SIZE ?= 0x04ff000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= 0x00200000 endif optee_os-4.3.0/core/arch/arm/plat-mediatek/main.c000066400000000000000000000020411464416617300216010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include #include #include #include #include #if (CFG_TEE_CORE_LOG_LEVEL != 0) register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); #endif static struct serial8250_uart_data console_data; register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE); #ifdef CFG_GIC register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE + GICC_OFFSET, CORE_MMU_PGDIR_SIZE); void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } #endif void plat_console_init(void) { if (CFG_TEE_CORE_LOG_LEVEL != 0) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } } optee_os-4.3.0/core/arch/arm/plat-mediatek/platform_config.h000066400000000000000000000056221464416617300240430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #ifdef ARM64 #ifdef CFG_WITH_PAGER #error "Pager not supported for ARM64" #endif #endif /*ARM64*/ #if defined(PLATFORM_FLAVOR_mt8173) #define GIC_BASE 0x10220000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define UART0_BASE 0x11002000 #define UART1_BASE 0x11003000 #define UART2_BASE 0x11004000 #define UART3_BASE 0x11005000 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 921600 #define CONSOLE_UART_CLK_IN_HZ 26000000 #define DRAM0_BASE 0x40000000 #define DRAM0_SIZE 0x80000000 #elif defined(PLATFORM_FLAVOR_mt8175) #define GIC_BASE 0x0C000000 #define GICC_OFFSET 0x400000 #define GICD_OFFSET 0x0 #define UART0_BASE 0x11002000 #define UART1_BASE 0x11103000 #define UART2_BASE 0x11104000 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 921600 #define CONSOLE_UART_CLK_IN_HZ 26000000 #elif defined(PLATFORM_FLAVOR_mt8516) #define GIC_BASE 0x10310000 #define GICC_OFFSET 0x10000 #define GICD_OFFSET 0x00000 #define UART0_BASE 0x11005000 #define UART1_BASE 0x11106000 #define UART2_BASE 0x11107000 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 921600 #define CONSOLE_UART_CLK_IN_HZ 26000000 #elif defined(PLATFORM_FLAVOR_mt8183) #define GIC_BASE 0x0C000000 #define GICC_OFFSET 0x400000 #define GICD_OFFSET 0x0 #define UART0_BASE 0x11002000 #define UART1_BASE 0x11103000 #define UART2_BASE 0x11104000 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 921600 #define CONSOLE_UART_CLK_IN_HZ 26000000 #elif defined(PLATFORM_FLAVOR_mt8195) #define GIC_BASE 0x0C000000 #define GICC_OFFSET 0x400000 #define GICD_OFFSET 0x0 #define UART0_BASE 0x11001100 #define UART1_BASE 0x11101200 #define UART2_BASE 0x11101300 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 921600 #define CONSOLE_UART_CLK_IN_HZ 26000000 #elif defined(PLATFORM_FLAVOR_mt8188) #define GIC_BASE 0x0C000000 #define GICC_OFFSET 0x400000 #define GICD_OFFSET 0x0 #define UART0_BASE 0x11001100 #define UART1_BASE 0x11101200 #define UART2_BASE 0x11101300 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 26000000 #elif defined(PLATFORM_FLAVOR_mt7988) #define GIC_BASE 0x0C000000 #define GICC_OFFSET 0x400000 #define GICD_OFFSET 0x000000 #define UART0_BASE 0x11000000 #define UART1_BASE 0x11000100 #define UART2_BASE 0x11000200 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 40000000 #else #error "Unknown platform flavor" #endif #ifdef CFG_MTK_RESERVED_VA #define MAX_XLAT_TABLES (30 + (CFG_RESERVED_VASPACE_SIZE) / \ (CORE_MMU_PGDIR_SIZE) + 1) #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-mediatek/sub.mk000066400000000000000000000000471464416617300216370ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-nuvoton/000077500000000000000000000000001464416617300204415ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-nuvoton/conf.mk000066400000000000000000000022631464416617300217220ustar00rootroot00000000000000PLATFORM_FLAVOR ?= npcm845x ifeq ($(PLATFORM_FLAVOR),npcm845x) include core/arch/arm/cpu/cortex-armv8-0.mk CFG_ARM64_core ?= y endif #npcm845x CFG_USER_TA_TARGETS ?= ta_arm64 $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_GIC,y) $(call force,CFG_ARM_GICV2,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_16550_UART,y) # Not used now for current platform $(call force,CFG_EXTERNAL_DT,n) CFG_WITH_STATS ?= y # To enable version printing with color in main CFG_NPCM_DEBUG ?= n ifeq ($(PLATFORM_FLAVOR),npcm845x) CFG_TEE_CORE_NB_CORE ?= 4 # [3000.0000 031f.ffff] is reserved to early boot CFG_TZDRAM_START ?= 0x02100000 CFG_TZDRAM_SIZE ?= 0x03f00000 # SHM chosen arbitrary, in a way that it does not interfere # with initial location of linux kernel, dtb and initrd. CFG_SHMEM_START ?= 0x06000000 CFG_SHMEM_SIZE ?= 0x00200000 # When Secure Data Path is enable, last MByte of TZDRAM is SDP test memory. CFG_TEE_SDP_MEM_BASE ?= 0x05F00000 CFG_TEE_SDP_MEM_SIZE ?= 0x00100000 $(call force,CFG_DT,y) CFG_DTB_MAX_SIZE ?= 0x100000 $(call force,CFG_WITH_PAGER,n,Pager is not supported for NPCM845x) else $(error Unsupported platform flavor "$(PLATFORM_FLAVOR)") endif #npcm845x optee_os-4.3.0/core/arch/arm/plat-nuvoton/main.c000066400000000000000000000051711464416617300215350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2023, Linaro Limited * Copyright (c) 2014-2023, STMicroelectronics International N.V. * Copyright (C) 2022-2023 Nuvoton Ltd. */ #include #include #include #include #include #include #include #include #include #include #define COLOR_NORMAL "\x1B[0m" #define COLOR_RED "\x1B[31m" #define COLOR_GREEN "\x1B[32m" #define COLOR_YELLOW "\x1B[33m" #define COLOR_BLUE "\x1B[34m" #define COLOR_MAGENTA "\x1B[35m" #define COLOR_CYAN "\x1B[36m" #define COLOR_WHITE "\x1B[37m" #define NPCM_MEASURE_BASE 0xF0848000 #define NPCM_MEASURE_UUID 0xC50 #define NPCM_MEASURE_SIZE 5 static struct ns16550_data console_data __nex_bss; static struct { uint8_t data[HW_UNIQUE_KEY_LENGTH]; bool ready; } npcm_hwkey; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, UART_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_DIST_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_RAM_NSEC, NPCM_MEASURE_BASE, SMALL_PAGE_SIZE); register_ddr(DRAM0_BASE, DRAM0_SIZE); static void print_version(void) { IMSG(COLOR_MAGENTA); IMSG(">================================================"); IMSG("OP-TEE OS Version %s", core_v_str); IMSG(">================================================"); IMSG(COLOR_NORMAL); } void boot_primary_init_intc(void) { if (IS_ENABLED(CFG_NPCM_DEBUG)) print_version(); gic_init(GICC_BASE, GICD_BASE); } void plat_console_init(void) { ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2); register_serial_console(&console_data.chip); } TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { void *vaddr = NULL; TEE_Result res = TEE_SUCCESS; uint32_t bin[HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t)] = {}; uint8_t *bin_val = (uint8_t *)(&bin[0]); if (npcm_hwkey.ready) goto out; vaddr = phys_to_virt(NPCM_MEASURE_BASE + NPCM_MEASURE_UUID, MEM_AREA_RAM_NSEC, NPCM_MEASURE_SIZE); if (!vaddr) { EMSG("Not enough memory mapped"); return TEE_ERROR_SECURITY; } res = tee_hash_createdigest(TEE_ALG_SHA256, (uint8_t *)vaddr, NPCM_MEASURE_SIZE, bin_val, HW_UNIQUE_KEY_LENGTH); if (res != TEE_SUCCESS) { EMSG("Can't create a digest for HUK"); return TEE_ERROR_SECURITY; } memcpy(&npcm_hwkey.data[0], bin, HW_UNIQUE_KEY_LENGTH); npcm_hwkey.ready = true; IMSG("HUK Initialized"); out: memcpy(hwkey->data, npcm_hwkey.data, HW_UNIQUE_KEY_LENGTH); return res; } optee_os-4.3.0/core/arch/arm/plat-nuvoton/platform_config.h000066400000000000000000000013761464416617300237720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2023, Linaro Limited * Copyright (C) 2022-2023 Nuvoton Ltd. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #define DRAM0_BASE 0x00000000 #define DRAM0_SIZE 0x40000000 /* 1G DDR */ #define GIC_BASE 0xDFFF8000 #define UART0_BASE 0xf0000000 #define UART_REG_SIZE 0x100 #define CONSOLE_UART_BASE UART0_BASE #define GICD_OFFSET 0x1000 #define GICC_OFFSET 0x2000 #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-nuvoton/sub.mk000066400000000000000000000000471464416617300215640ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-poplar/000077500000000000000000000000001464416617300202265ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-poplar/conf.mk000066400000000000000000000011541464416617300215050ustar00rootroot00000000000000include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_PL011,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) ifeq ($(CFG_ARM64_core),y) CFG_CORE_TZSRAM_EMUL_SIZE ?= 655360 else CFG_CORE_TZSRAM_EMUL_SIZE ?= 524288 endif CFG_NUM_THREADS ?= 4 CFG_CRYPTO_WITH_CE ?= y # Overrides default in mk/config.mk with 96 kB CFG_CORE_HEAP_SIZE ?= 98304 CFG_PL061 ?= y ifeq ($(CFG_PL061),y) core-platform-cppflags += -DPLAT_PL061_MAX_GPIOS=104 endif CFG_TEE_SDP_MEM_BASE ?= 0x02800000 CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 CFG_DRAM_SIZE_GB ?= 2 optee_os-4.3.0/core/arch/arm/plat-poplar/hi3798cv200.h000066400000000000000000000004531464416617300221070ustar00rootroot00000000000000/* * Copyright (c) 2017, Linaro Limited * SPDX-License-Identifier: BSD-2-Clause */ #ifndef __HI3798cv200_H__ #define __HI3798cv200_H__ /* PL011 */ #define PL011_UART0_BASE (0xF8B00000) #define PL011_BAUDRATE (115200) #define PL011_UART0_CLK_IN_HZ (75000000) #endif /* __HI3798cv200_H__ */ optee_os-4.3.0/core/arch/arm/plat-poplar/main.c000066400000000000000000000012731464416617300213210ustar00rootroot00000000000000/* * Copyright (c) 2017, Linaro Limited * SPDX-License-Identifier: BSD-2-Clause */ #include #include #ifdef CFG_PL061 #include #endif #include #include #include #include #include static struct pl011_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE); /* for dynamic shared memory */ register_dynamic_shm(DRAM0_BASE_NSEC, DRAM0_SIZE_NSEC); void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-poplar/platform_config.h000066400000000000000000000101161464416617300235470ustar00rootroot00000000000000/* * Copyright (c) 2017, Linaro Limited * SPDX-License-Identifier: BSD-2-Clause */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* PL011 UART */ #define CONSOLE_UART_BASE PL011_UART0_BASE #define CONSOLE_BAUDRATE PL011_BAUDRATE #define CONSOLE_UART_CLK_IN_HZ PL011_UART0_CLK_IN_HZ /* * Poplar memory map * * Note: the physical address ranges below correspond to DRAM which is * non-secure by default. Therefore, the terms TZDRAM and TZSRAM may not * reflect the reality and only indicate areas that "would normally be" * secure DRAM and secure SRAM in a more complete implementation. * The memory map was defined like this for lack of better documentation. * It is good enough for development/testing purposes. * * 0xFF00_0000 [DRAM2_LIMIT] * other (devmem) * 0xF000_0000 [DRAM2_BASE] * * 0x8000_0000 (0x4000_0000 for 1GB board) [DRAM0_LIMIT] * u-boot + ree memory: 1144 MiB (144 MiB for 1GB board) * 0x3700_0000 CONFIG_SYS_TEXT_BASE (u-boot) * PLAT_POPLAR_NS_IMAGE_OFFSET (arm-tf) * ramdisk: 76 MiB * 0x3240_0000 * fdt: 2 MiB * 0x3220_0000 * pxe file or script addr: 2 MiB * 0x3200_0000 * kernel/android: 32 MiB * 0x3000_0000 * ree memory: 696 MiB * 0x0480_0000 CONFIG_SYS_LOAD_ADDR (defined in u-boot) * other: 6 MiB * 0x0420_0000 CONFIG_SYS_INIT_SP_ADDR (defined in u-boot) * 0x0408_0000 KERNEL_TEXT_OFFSET (defined in u-boot) * unused: 512 KiB * 0x0400_0000 * * 0x0400_0000 - * TA RAM: 14 MiB | TZDRAM * 0x0320_0000 - * * CFG_WITH_PAGER=n - * TEE RAM: 2 MiB (TEE_RAM_VA_SIZE) | TZDRAM * 0x0300_0000 [TZDRAM_BASE, TEE_LOAD_ADDR] - * * CFG_WITH_PAGER=y * Unused * 0x030A_0000 - * TEE RAM: 640 KiB (TZSRAM_SIZE) | TZSRAM * 0x0300_0000 [TZSRAM_BASE, TEE_LOAD_ADDR] - * * 0x0300_0000 [TZDRAM_BASE, TZSRAM_BASE, TEE_LOAD_ADDR] * OP-TEE Future Use: 4 MiB * 0x02C0_0000 * * 0x02C0_0000 * Secure Data Path buffers: 4 MiB * 0x0280_0000 [CFG_TEE_SDP_MEM_BASE] * Shared memory: 4 MiB * 0x0240_0000 * OP-TEE Future Use: 2 MiB * 0x0220_0000 * * 0x0220_0000 * unused: 64 KiB * 0x021F_0000 l-loader limit (len/size set by poplar-l-loader.git) * unused (cannot be used) * 0x0210_0000 l-loader limit (max bootrom can accept) * fip.bin load zone: 768 KiB * 0x0204_0000 * bl31: 80 KiB * 0x0202_A000 * bl2: 48 KiB * 0x0201_E000 * bl1: 64 KiB * 0x0200_E000 * l-loader text: 52 KiB * 0x0200_1000 * unused * 0x0200_0000 * TA virtual memory space * 0x0000_0000 [DRAM0_BASE] */ #define DRAM0_BASE 0x00000000 #if (CFG_DRAM_SIZE_GB == 2) #define DRAM0_SIZE 0x80000000 #elif (CFG_DRAM_SIZE_GB == 1) #define DRAM0_SIZE 0x40000000 #else #error Unsupported DRAM size #endif #define DRAM0_BASE_NSEC 0x04080000 #define DRAM0_SIZE_NSEC (DRAM0_SIZE - DRAM0_BASE_NSEC) #define DRAM2_BASE 0xF0000000 #define DRAM2_SIZE 0x0F000000 #ifdef CFG_WITH_PAGER #define TZSRAM_BASE 0x03000000 #define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE #define TZDRAM_BASE 0x03200000 #define TZDRAM_SIZE (14 * 1024 * 1024) #define TEE_RAM_START TZSRAM_BASE #define TEE_RAM_PH_SIZE TZSRAM_SIZE #define TA_RAM_START ROUNDUP(TZDRAM_BASE, CORE_MMU_PGDIR_SIZE) #define TA_RAM_SIZE ROUNDDOWN(TZDRAM_SIZE, CORE_MMU_PGDIR_SIZE) #else /* CFG_WITH_PAGER */ #define TZDRAM_BASE 0x03000000 #define TZDRAM_SIZE (16 * 1024 * 1024) #define TEE_RAM_START TZDRAM_BASE #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE #define TA_RAM_START ROUNDUP((TZDRAM_BASE + TEE_RAM_VA_SIZE), \ CORE_MMU_PGDIR_SIZE) #define TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - TEE_RAM_VA_SIZE),\ CORE_MMU_PGDIR_SIZE) #endif /* CFG_WITH_PAGER */ #define TEE_SHMEM_START 0x02400000 #define TEE_SHMEM_SIZE (4 * 1024 * 1024) #define TEE_RAM_VA_SIZE (2 * 1024 * 1024) #define TEE_LOAD_ADDR 0x03000000 /* BL32_BASE */ #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-poplar/sub.mk000066400000000000000000000000471464416617300213510ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-rcar/000077500000000000000000000000001464416617300176605ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-rcar/conf.mk000066400000000000000000000021401464416617300211330ustar00rootroot00000000000000PLATFORM_FLAVOR ?= generic_dt include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_SCIF,y) $(call force,CFG_GIC,y) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_ARM64_core,y) $(call force,CFG_WITH_LPAE,y) ifeq ($(PLATFORM_FLAVOR), spider_s4) $(call force,CFG_RCAR_GEN4, y) else $(call force,CFG_RCAR_GEN3, y) endif CFG_TZDRAM_START ?= 0x44100000 CFG_TZDRAM_SIZE ?= 0x03D00000 CFG_TEE_RAM_VA_SIZE ?= 0x100000 supported-ta-targets = ta_arm64 ifeq ($(CFG_RCAR_GEN3), y) CFG_DT ?= y ifeq ($(CFG_RCAR_GEN3_HWRNG), y) $(warning "Warning: Use of HWRNG can cause crashes on some Renesas SoCs") CFG_WITH_SOFTWARE_PRNG ?= n CFG_HWRNG_QUALITY ?= 1024 CFG_HWRNG_PTA ?= y $(call force,CFG_RCAR_ROMAPI, y) endif endif ifeq ($(CFG_RCAR_GEN4), y) # 1xx - for SCIFxx # 2xx - for HSCIFxx CFG_TZDRAM_SIZE = 0x2200000 CFG_RCAR_UART ?= 200 $(call force,CFG_RCAR_ROMAPI, n) $(call force,CFG_CORE_CLUSTER_SHIFT, 1) $(call force,CFG_ARM_GICV3, y) endif optee_os-4.3.0/core/arch/arm/plat-rcar/core_pos_a64.S000066400000000000000000000043051464416617300222710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2019, Arm Limited. All rights reserved. * Copyright (c) 2020, Marek Vasut */ #include #include #include #include #include "rcar.h" FUNC get_core_pos_mpidr , : /* * Shift MPIDR value if it's not already shifted. * Using logical shift ensures AFF0 to be filled with zeroes. * This part is necessary even if CFG_CORE_THREAD_SHIFT is 0 because * MT bit can be set on single threaded systems where all the AFF0 * values are zeroes. */ tst x0, #MPIDR_MT_MASK lsl x3, x0, #MPIDR_AFFINITY_BITS csel x3, x3, x0, eq /* * At this point the MPIDR layout is always shifted so it looks * as follows AFF2 -> cluster, AFF1 -> core, AFF0 -> thread */ /* Calculate CorePos = (ClusterId * (cores/cluster)) + CoreId */ ubfx x0, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ubfx x1, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS /* * R-Car M3W/M3W+ have 6 cores, but internally cluster 0 has two * cores (0, 1) and cluster 1 has four cores (4, 5, 6, 7). Other * R-Car SoCs either have two full clusters (4xCA57 + 4xCA53) or * they have one cluster. * * The code below normalizes the M3W/M3W+ core enumeration such * that cluster 0 returns core IDs {0, 1} and cluster 1 returns * core IDs {2, 3, 4, 5}. This is achieved by calculating the * core ID as CorePos = CoreId + (ClusterId << (IsM3W ? 1 : 0)) */ adr_l x2, rcar_prr_value ldr w3, [x2] cmp w3, wzr bne 1f /* Load PRR PRODUCT into x3 */ mov x2, #PRR_BASE ldr w3, [x2, #PRR_OFFSET] /* * Cache the PRR register value. PRR value does not change at runtime. * This function is first called with MMU disabled, so it is possible * to read the PRR register via its physical address, but once MMU is * enabled, this is no longer possible as the virtual address is not * available here, so in that case, use the cached value of the PRR. */ adr_l x2, rcar_prr_value str w3, [x2] 1: mov w2, #PRR_PRODUCT_M3W and w3, w3, #PRR_PRODUCT_MASK cmp w2, w3 beq 2f /* if (!IsM3W) { x1 <<= 2; } else { x1 <<= 1} */ lsl x1, x1, #1 2: lsl x1, x1, #1 add x0, x0, x1 ret END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-rcar/hw_rng.c000066400000000000000000000026211464416617300213110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* Copyright (c) 2021, EPAM Systems. All rights reserved. */ #include #include #include #include #include #include #include "romapi.h" #define SCRATCH_BUF_SZ 4096 static uint8_t scratch_buf[SCRATCH_BUF_SZ] __nex_bss __aligned(RCAR_CACHE_LINE_SZ); static unsigned int spin_lock __nex_data = SPINLOCK_UNLOCK; /* * It is inefficient to call ROM_GetRndVector() every time we want 8 bits of * random data, so we will cache the unused values for latter use. */ static uint8_t rng_cache[PLAT_RND_VECTOR_SZ] __nex_bss __aligned(RCAR_CACHE_LINE_SZ); static uint8_t rng_cache_pos __nex_data; TEE_Result hw_get_random_bytes(void *buf, size_t len) { uint32_t exceptions; uint8_t *buffer = buf; size_t buffer_pos = 0; uint8_t ret_val = 0; assert(rng_cache_pos < PLAT_RND_VECTOR_SZ); while (buffer_pos < len) { exceptions = cpu_spin_lock_xsave(&spin_lock); /* Refill our FIFO */ if (rng_cache_pos == 0) { uint32_t ret = plat_rom_getrndvector(rng_cache, scratch_buf, sizeof(scratch_buf)); if (ret != 0) panic("ROM_GetRndVector() returned error!"); } buffer[buffer_pos++] = rng_cache[rng_cache_pos++]; if (rng_cache_pos == PLAT_RND_VECTOR_SZ) rng_cache_pos = 0; cpu_spin_unlock_xrestore(&spin_lock, exceptions); } return ret_val; } optee_os-4.3.0/core/arch/arm/plat-rcar/link.mk000066400000000000000000000002021464416617300211400ustar00rootroot00000000000000include core/arch/arm/kernel/link.mk SRECFLAGS ?= --srec-forceS3 --adjust-vma=$(CFG_TZDRAM_START) all: $(link-out-dir)/tee.srec optee_os-4.3.0/core/arch/arm/plat-rcar/main.c000066400000000000000000000061511464416617300207530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, GlobalLogic * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, SCIF_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); #ifdef PRR_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, PRR_BASE, SMALL_PAGE_SIZE); #endif /* Legacy platforms */ #if defined(PLATFORM_FLAVOR_salvator_h3) || \ defined(PLATFORM_FLAVOR_salvator_h3_4x2g) || \ defined(PLATFORM_FLAVOR_salvator_m3) || \ defined(PLATFORM_FLAVOR_salvator_m3_2x4g) || \ defined(PLATFORM_FLAVOR_spider_s4) register_ddr(NSEC_DDR_0_BASE, NSEC_DDR_0_SIZE); register_ddr(NSEC_DDR_1_BASE, NSEC_DDR_1_SIZE); #ifdef NSEC_DDR_2_BASE register_ddr(NSEC_DDR_2_BASE, NSEC_DDR_2_SIZE); #endif #ifdef NSEC_DDR_3_BASE register_ddr(NSEC_DDR_3_BASE, NSEC_DDR_3_SIZE); #endif #endif static struct scif_uart_data console_data __nex_bss; #ifdef PRR_BASE uint32_t rcar_prr_value __nex_bss; #endif void plat_console_init(void) { scif_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); } #ifdef CFG_RCAR_ROMAPI /* Should only seed from a hardware random number generator */ static_assert(!IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)); unsigned long plat_get_aslr_seed(void) { unsigned long seed = 0; /* On RCAR we can get hw random bytes on early boot stages */ if (crypto_rng_read(&seed, sizeof(seed))) panic(); return seed; } #endif void boot_primary_init_intc(void) { gic_init(GICC_BASE, GICD_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } optee_os-4.3.0/core/arch/arm/plat-rcar/platform_config.h000066400000000000000000000071211464416617300232030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, GlobalLogic * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #define RCAR_CACHE_LINE_SZ 64 /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT RCAR_CACHE_LINE_SZ #if defined(CFG_RCAR_GEN3) #define GIC_BASE 0xF1000000 #define GICC_BASE 0xF1020000 #define GICD_BASE 0xF1010000 #define CONSOLE_UART_BASE 0xE6E88000 #define PRR_BASE 0xFFF00000 #elif defined(CFG_RCAR_GEN4) #define GICC_BASE 0xF1060000 #define GICD_BASE 0xF1000000 #if CFG_RCAR_UART == 103 /* SCIF3 */ #define CONSOLE_UART_BASE 0xE6C50000 #elif CFG_RCAR_UART == 200 /* HSCIF0 */ #define CONSOLE_UART_BASE 0xE6540000 #endif #endif /* CFG_RCAR_GENx */ #if defined(PLATFORM_FLAVOR_salvator_h3) #define NSEC_DDR_0_BASE 0x47E00000 #define NSEC_DDR_0_SIZE 0x38200000 #define NSEC_DDR_1_BASE 0x500000000U #define NSEC_DDR_1_SIZE 0x40000000 #define NSEC_DDR_2_BASE 0x600000000U #define NSEC_DDR_2_SIZE 0x40000000 #define NSEC_DDR_3_BASE 0x700000000U #define NSEC_DDR_3_SIZE 0x40000000 #elif defined(PLATFORM_FLAVOR_salvator_h3_4x2g) #define NSEC_DDR_0_BASE 0x47E00000 #define NSEC_DDR_0_SIZE 0x78200000 #define NSEC_DDR_1_BASE 0x500000000U #define NSEC_DDR_1_SIZE 0x80000000 #define NSEC_DDR_2_BASE 0x600000000U #define NSEC_DDR_2_SIZE 0x80000000 #define NSEC_DDR_3_BASE 0x700000000U #define NSEC_DDR_3_SIZE 0x80000000 #elif defined(PLATFORM_FLAVOR_salvator_m3) #define NSEC_DDR_0_BASE 0x47E00000 #define NSEC_DDR_0_SIZE 0x78200000 #define NSEC_DDR_1_BASE 0x600000000U #define NSEC_DDR_1_SIZE 0x80000000 #elif defined(PLATFORM_FLAVOR_salvator_m3_2x4g) #define NSEC_DDR_0_BASE 0x47E00000 #define NSEC_DDR_0_SIZE 0x78200000 #define NSEC_DDR_1_BASE 0x480000000U #define NSEC_DDR_1_SIZE 0x80000000 #define NSEC_DDR_2_BASE 0x600000000U #define NSEC_DDR_2_SIZE 0x100000000U #elif defined(PLATFORM_FLAVOR_spider_s4) #define NSEC_DDR_0_BASE 0x48000000 #define NSEC_DDR_0_SIZE 0x78000000 #define NSEC_DDR_1_BASE 0x480000000U #define NSEC_DDR_1_SIZE 0x80000000U #else /* Generic DT-based platform */ #endif /* Full GlobalPlatform test suite requires TEE_SHMEM_SIZE to be at least 2MB */ #define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) #define TEE_SHMEM_SIZE 0x100000 #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-rcar/rcar.h000066400000000000000000000010511464416617300207550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2021, EPAM Systems. All rights reserved. */ #ifndef PLAT_RCAR_RCAR_H #define PLAT_RCAR_RCAR_H #define PRR_OFFSET 0x44 #define PRR_PRODUCT_H3 0x4F00 #define PRR_PRODUCT_M3W 0x5200 #define PRR_PRODUCT_MASK 0xFF00 #define PRR_CUT_MASK 0xFF #define PRR_CUT_10 0x00 /* Ver 1.0 */ #define PRR_CUT_11 0x01 /* Ver 1.1 */ #define PRR_CUT_20 0x10 /* Ver 2.0 */ #define PRR_CUT_30 0x20 /* Ver.3.0 */ #ifndef __ASSEMBLER__ extern uint32_t rcar_prr_value; #endif #endif /* PLAT_RCAR_RCAR_H */ optee_os-4.3.0/core/arch/arm/plat-rcar/romapi.c000066400000000000000000000104461464416617300213200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, EPAM Systems */ #include #include #include #include #include "rcar.h" #include "romapi.h" static int get_api_table_index(void) { /* * Depending on SoC type and version, there are 4 possible addresses * for each ROMAPI function */ static int index __nex_data = -1; if (index != -1) return index; switch (rcar_prr_value & PRR_PRODUCT_MASK) { case PRR_PRODUCT_H3: switch (rcar_prr_value & PRR_CUT_MASK) { case PRR_CUT_10: /* H3 ES1.0 */ case PRR_CUT_11: /* H3 ES1.1 */ index = 0; break; case PRR_CUT_20: /* H3 ES2.0 */ index = 1; break; default: /* Newer H3 versions use unified table */ index = 3; break; } break; case PRR_PRODUCT_M3W: switch (rcar_prr_value & PRR_CUT_MASK) { case PRR_CUT_10: /* M3 ES1.0 */ index = 2; break; default: /* Newer M3 versions use unified table */ index = 3; break; } break; default: /* All other SoCs use unified table */ index = 3; break; } return index; } /* implemented in romapi_call.S */ extern uint32_t __plat_romapi_wrapper(paddr_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3); static uint32_t __plat_romapi_direct(paddr_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3) { uint32_t (*fptr)(uint64_t arg1, uint64_t arg2, uint64_t arg3) = NULL; assert(!cpu_mmu_enabled()); fptr = (typeof(fptr))func; return fptr(arg1, arg2, arg3); } static uint32_t plat_call_romapi(paddr_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3) { uint32_t (*fptr)(paddr_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3) = NULL; /* * If MMU is enabled, we need to use trampoline function that will * disable MMU and switch stack pointer to physical address. On other * hand, if MMU is disabled, we can call the ROM function directly. */ if (cpu_mmu_enabled()) /* * With ASLR enabled __plat_romapi_wrapper() function will be * mapped at two addresses: at random address (with the rest of * OP-TEE) and at identity address. We need to map it at * identity address and call it at identity address because this * function turns off MMU to perform ROM API call. But * __plat_romapi_wrapper *symbol* will be relocated by ASLR * code. To get identity address of the function we need to use * virt_to_phys(). */ fptr = (void *)virt_to_phys(__plat_romapi_wrapper); else /* * With MMU disabled we can call ROM code directly. */ fptr = __plat_romapi_direct; return fptr(func, arg1, arg2, arg3); } static paddr_t va2pa(void *ptr) { if (cpu_mmu_enabled()) return virt_to_phys(ptr); else return (paddr_t)ptr; } static const paddr_t romapi_getrndvector[] = { 0xEB10DFC4, /* H3 1.0/1.1, needs confirmation */ 0xEB117134, /* H3 2.0 */ 0xEB11055C, /* M3 1.0/1.05, needs confirmation */ 0xEB100188, /* H3 3.0, M3 1.1+, M3N, E3, D3, V3M 2.0 */ }; uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ], uint8_t *scratch, uint32_t scratch_sz) { uint32_t ret = -1; int try = 0; paddr_t func_addr = romapi_getrndvector[get_api_table_index()]; paddr_t rndbuff_pa = va2pa(rndbuff); paddr_t scratch_pa = va2pa(scratch); assert(scratch_sz >= 4096); assert(rndbuff_pa % RCAR_CACHE_LINE_SZ == 0); assert(scratch_pa % RCAR_CACHE_LINE_SZ == 0); while (try++ < 3) { ret = plat_call_romapi(func_addr, rndbuff_pa, scratch_pa, scratch_sz); if (ret == 0) break; IMSG("ROM_GetRndVector() returned "PRIx32, ret); } /* * ROM code is called with MMU turned off, so any accesses to rndbuff * are not affected by data cache. This can lead to two problems: * * 1. Any prior writes can be cached but may not reach memory. So staled * values can be flushed to memory later and overwrite new data written * by ROM code. This includes stack as well. * * 2. ROM code will write new data to the buffer, but we may see old, * cached values. * * ROM code wrapper will issue dcache_op_all(DCACHE_OP_CLEAN). This will * ensure that all writes reached memory. After the call we need to * invalidate the cache to see new data. * * We are not accessing scratch area, so no need to do cache maintenance * for that buffer. */ cache_op_inner(DCACHE_AREA_INVALIDATE, rndbuff, PLAT_RND_VECTOR_SZ); return ret; } optee_os-4.3.0/core/arch/arm/plat-rcar/romapi.h000066400000000000000000000011751464416617300213240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, EPAM Systems */ #ifndef __ROMAPI_H #define __ROMAPI_H #include /* * Mask ROM provides number of facilities, including function that returns 32 * byte random vector. */ #define PLAT_RND_VECTOR_SZ 32 /* * Call to this function must be protected by a spinlock, because ROM code * accesses hardware. This function requires at least 4kb scratch buffer to * work. All parameters should be aligned to 8 bytes. */ uint32_t plat_rom_getrndvector(uint8_t rndbuff[PLAT_RND_VECTOR_SZ], uint8_t *scratch, uint32_t scratch_sz); #endif optee_os-4.3.0/core/arch/arm/plat-rcar/romapi_call.S000066400000000000000000000040651464416617300222730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, EPAM Systems */ #include #include #include #include #include /* uint32_t __plat_romapi_wrapper(paddr_t func, uint64_t arg1, uint64_t arg2, * uint64_t arg3) * Call MaskROM function func(arg1, arg2, arg3). * We need to disable MMU before calling any MaskROM API functions */ FUNC __plat_romapi_wrapper , : , .identity_map push fp, lr push x19, x20 push x21, x22 push x23, x24 mov x19, x0 mov x20, x1 mov x21, x2 mov x22, x3 /* Get PA of stack pointer */ mov x0, sp #ifdef CFG_CORE_ASLR /* * We are running at identity location, so we can't use bl there, * because assembler will generate relative address to virt_to_phys(), * which is not identity mapped. */ adr_l x9, virt_to_phys ldr x10, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET add x9, x9, x10 blr x9 #else bl virt_to_phys #endif mov x23, x0 /* We about to disable MMU. Make sure that all writes reached memory */ mov x0, #DCACHE_OP_CLEAN #ifdef CFG_CORE_ASLR /* See the comment above */ adr_l x9, dcache_op_all ldr x10, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET add x9, x9, x10 blr x9 #else bl dcache_op_all #endif /* Disable MMU */ mrs x9, sctlr_el1 bic x9, x9, #SCTLR_M bic x9, x9, #SCTLR_C msr sctlr_el1, x9 isb /* Invalidate instruction cache and branch predictor */ ic ialluis dsb ish /* ensure that maintenance operations are seen */ isb /* Save old SP to x24 and switch to a new stack */ mov x24, sp mov sp, x23 /* call the function */ mov x0, x20 /* x20: uint64_t arg1 */ mov x1, x21 /* x21: uint64_t arg2 */ mov x2, x22 /* x22: uint64_t arg3 */ blr x19 /* x19: paddr_t func */ /* restore sp */ mov sp, x24 /* Enable MMU */ mrs x9, sctlr_el1 orr x9, x9, #SCTLR_M orr x9, x9, #SCTLR_C msr sctlr_el1, x9 isb /* Invalidate instruction cache and branch predictor */ ic iallu isb pop x23, x24 pop x21, x22 pop x19, x20 pop fp, lr ret END_FUNC __plat_romapi_wrapper optee_os-4.3.0/core/arch/arm/plat-rcar/sub.mk000066400000000000000000000003001464416617300207730ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-${CFG_RCAR_GEN3} += core_pos_a64.S srcs-${CFG_RCAR_ROMAPI} += romapi.c srcs-${CFG_RCAR_ROMAPI} += romapi_call.S srcs-${CFG_RCAR_ROMAPI} += hw_rng.c optee_os-4.3.0/core/arch/arm/plat-rockchip/000077500000000000000000000000001464416617300205335ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-rockchip/common.h000066400000000000000000000015561464416617300222030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. */ #ifndef PLAT_ROCKCHIP_COMMON_H #define PLAT_ROCKCHIP_COMMON_H /* For SMP cpu bootup, they are common for rockchip platforms */ #define LOCK_TAG 0xDEADBEAF #define LOCK_ADDR_OFFSET 4 #define BOOT_ADDR_OFFSET 8 /* * Some register has write-mask bits, it means if you want to set the bits, * you need set the write-mask bits at the same time, the write-mask bits is * in high 16-bits. The following macro definition helps you access register * efficiently. */ #define REG_MSK_SHIFT 16 #define WMSK_BIT(nr) BIT((nr) + REG_MSK_SHIFT) #define BIT_WITH_WMSK(nr) (BIT(nr) | WMSK_BIT(nr)) #define BITS_WMSK(msk, shift) SHIFT_U32(msk, (shift) + REG_MSK_SHIFT) #define BITS_WITH_WMASK(bits, msk, shift) \ (SHIFT_U32(bits, shift) | BITS_WMSK(msk, shift)) #endif optee_os-4.3.0/core/arch/arm/plat-rockchip/conf.mk000066400000000000000000000030141464416617300220070ustar00rootroot00000000000000PLATFORM_FLAVOR ?= rk322x $(call force,CFG_GIC,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_8250_UART,y) CFG_DT ?= y CFG_WITH_STATS ?= y CFG_NUM_THREADS ?= 4 ifeq ($(PLATFORM_FLAVOR),rk322x) include ./core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_PSCI_ARM32,y) $(call force,CFG_BOOT_SECONDARY_REQUEST,y) CFG_TZDRAM_START ?= 0x68400000 CFG_TZDRAM_SIZE ?= 0x00200000 CFG_SHMEM_START ?= 0x68600000 CFG_SHMEM_SIZE ?= 0x00100000 CFG_EARLY_CONSOLE ?= y CFG_EARLY_CONSOLE_BASE ?= UART2_BASE CFG_EARLY_CONSOLE_SIZE ?= UART2_SIZE CFG_EARLY_CONSOLE_BAUDRATE ?= 1500000 CFG_EARLY_CONSOLE_CLK_IN_HZ ?= 24000000 endif ifeq ($(PLATFORM_FLAVOR),rk3399) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,6) $(call force,CFG_ARM_GICV3,y) CFG_CRYPTO_WITH_CE ?= y CFG_TZDRAM_START ?= 0x30000000 CFG_TZDRAM_SIZE ?= 0x02000000 CFG_SHMEM_START ?= 0x32000000 CFG_SHMEM_SIZE ?= 0x00400000 CFG_EARLY_CONSOLE ?= y CFG_EARLY_CONSOLE_BASE ?= UART2_BASE CFG_EARLY_CONSOLE_SIZE ?= UART2_SIZE CFG_EARLY_CONSOLE_BAUDRATE ?= 1500000 CFG_EARLY_CONSOLE_CLK_IN_HZ ?= 24000000 endif ifeq ($(PLATFORM_FLAVOR),px30) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) CFG_TZDRAM_START ?= 0x30000000 CFG_TZDRAM_SIZE ?= 0x02000000 CFG_SHMEM_START ?= 0x32000000 CFG_SHMEM_SIZE ?= 0x00400000 CFG_EARLY_CONSOLE ?= n endif ifeq ($(platform-flavor-armv8),1) $(call force,CFG_ARM64_core,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) ta-targets = ta_arm64 endif optee_os-4.3.0/core/arch/arm/plat-rockchip/core_pos_a32.S000066400000000000000000000006161464416617300231400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #include #include #include FUNC get_core_pos_mpidr , : /* * Because mpidr is designed mistake in hardware, ie. core0 is 0xf00, * core1 is 0xf01..., so we need implement the function to correct this. */ and r0, r0, #MPIDR_CPU_MASK bx lr END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-rockchip/cru.h000066400000000000000000000027051464416617300215010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. */ #ifndef PLAT_ROCKCHIP_CRU_H #define PLAT_ROCKCHIP_CRU_H #include #include #if defined(PLATFORM_FLAVOR_rk322x) enum plls_id { APLL_ID, DPLL_ID, CPLL_ID, GPLL_ID, PLL_END, }; #define CRU_SOFTRST_CON(i) (0x110 + ((i) * 4)) #define CRU_MODE_CON 0x040 #define CRU_GLBRST_CFG_BASE 0x140 #define CRU_FSTRST_VAL_BASE 0x1f0 #define CRU_SNDRST_VAL_BASE 0x1f4 #define CRU_FSTRST_VAL 0xfdb9 #define CRU_SNDRST_VAL 0xeca8 #define PLLS_SLOW_MODE 0x11030000 #define CORE_SOFT_RESET(core) SHIFT_U32(0x100010, (core)) #define CORE_SOFT_RELEASE(core) SHIFT_U32(0x100000, (core)) #define CORE_HELD_IN_RESET(core) SHIFT_U32(0x000010, (core)) #define NONBOOT_CORES_SOFT_RESET 0x00e000e0 #define CRU_CLKGATE_CON_CNT 16 #define CRU_CLKSEL_CON(i) (0x044 + ((i) * 4)) #define CRU_CLKGATE_CON(i) (0x0d0 + ((i) * 4)) #define CRU_PLL_CON0(pll) ((pll) * 0x0c + 0x0) #define CRU_PLL_CON1(pll) ((pll) * 0x0c + 0x4) #define CRU_PLL_CON2(pll) ((pll) * 0x0c + 0x8) #define PLL_LOCK BIT(10) #define PLL_POWER_UP BITS_WITH_WMASK(0, 1, 13) #define PLL_POWER_DOWN BITS_WITH_WMASK(1, 1, 13) #define PLL_MODE_BIT(pll) ((pll) * 4) #define PLL_MODE_MSK(pll) BIT(PLL_MODE_BIT(pll)) #define PLL_SLOW_MODE(pll) BITS_WITH_WMASK(0, 1, PLL_MODE_BIT(pll)) #define PLL_NORM_MODE(pll) BITS_WITH_WMASK(1, 1, PLL_MODE_BIT(pll)) #endif #endif optee_os-4.3.0/core/arch/arm/plat-rockchip/grf.h000066400000000000000000000006571464416617300214720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. */ #ifndef PLAT_ROCKCHIP_GRF_H #define PLAT_ROCKCHIP_GRF_H #if defined(PLATFORM_FLAVOR_rk322x) #define GRF_CPU_STATUS1 0x524 #define CORE_WFE_MASK(core) SHIFT_U32(0x02, (core)) #define CORE_WFI_MASK(core) SHIFT_U32(0x20, (core)) #define CORE_WFE_I_MASK(core) (CORE_WFI_MASK(core) | CORE_WFE_MASK(core)) #endif #endif optee_os-4.3.0/core/arch/arm/plat-rockchip/main.c000066400000000000000000000024211464416617300216220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #include #include #include #include #include #include #include #include #include #if defined(CFG_EARLY_CONSOLE) static struct serial8250_uart_data early_console_data; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CFG_EARLY_CONSOLE_BASE, CFG_EARLY_CONSOLE_SIZE); #endif register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); void boot_primary_init_intc(void) { gic_init(GICC_BASE, GICD_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } void plat_console_init(void) { #if defined(CFG_EARLY_CONSOLE) /* * Console devices can vary a lot between devices and * OP-TEE will switch to the DT-based real console later, * based on DT-devices and the systems chosen node. * So early console is only needed for early debugging. */ serial8250_uart_init(&early_console_data, CFG_EARLY_CONSOLE_BASE, CFG_EARLY_CONSOLE_CLK_IN_HZ, CFG_EARLY_CONSOLE_BAUDRATE); register_serial_console(&early_console_data.chip); #endif } optee_os-4.3.0/core/arch/arm/plat-rockchip/plat_init.S000066400000000000000000000005051464416617300226420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. */ #include #include #include FUNC plat_cpu_reset_early , : /* Enable SMP bit */ read_actlr r0 orr r0, r0, #ACTLR_SMP write_actlr r0 bx lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-rockchip/platform.c000066400000000000000000000020041464416617300225170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. */ #include #include #include #include #include #include int __weak platform_secure_init(void) { return 0; } int __weak platform_secure_ddr_region(int rgn __maybe_unused, paddr_t st __maybe_unused, size_t sz __maybe_unused) { MSG("Not protecting region %d: 0x%lx-0x%lx", rgn, st, st + sz); return 0; } static TEE_Result platform_init(void) { int ret = 0; platform_secure_init(); /* * Rockchip SoCs can protect multiple memory regions (mostly 8). * Region 0 is assigned for Trusted-Firmware memory, so use * regions 1 for OP-TEE memory, which leaves on all known SoCs * at least 6 more regions available for other purposes. */ ret = platform_secure_ddr_region(1, CFG_TZDRAM_START, CFG_TZDRAM_SIZE); if (ret < 0) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } service_init(platform_init); optee_os-4.3.0/core/arch/arm/plat-rockchip/platform.h000066400000000000000000000004431464416617300225310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #ifndef PLAT_ROCKCHIP_PLATFORM_H #define PLAT_ROCKCHIP_PLATFORM_H int platform_secure_init(void); int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz); #endif optee_os-4.3.0/core/arch/arm/plat-rockchip/platform_config.h000066400000000000000000000041771464416617300240660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #define SIZE_K(n) ((n) * 1024) #define SIZE_M(n) ((n) * 1024 * 1024) #if defined(PLATFORM_FLAVOR_rk322x) #define GIC_BASE 0x32010000 #define GIC_SIZE SIZE_K(64) #define GICD_BASE (GIC_BASE + 0x1000) #define GICC_BASE (GIC_BASE + 0x2000) #define SGRF_BASE 0x10140000 #define SGRF_SIZE SIZE_K(64) #define DDRSGRF_BASE 0x10150000 #define DDRSGRF_SIZE SIZE_K(64) #define GRF_BASE 0x11000000 #define GRF_SIZE SIZE_K(64) #define UART2_BASE 0x11030000 #define UART2_SIZE SIZE_K(64) #define CRU_BASE 0x110e0000 #define CRU_SIZE SIZE_K(64) /* Internal SRAM */ #define ISRAM_BASE 0x10080000 #define ISRAM_SIZE SIZE_K(8) #elif defined(PLATFORM_FLAVOR_rk3399) #define MMIO_BASE 0xF8000000 #define GIC_BASE (MMIO_BASE + 0x06E00000) #define GIC_SIZE SIZE_M(2) #define GICC_BASE (MMIO_BASE + 0x07F00000) #define GICD_BASE GIC_BASE #define GICR_BASE (GIC_BASE + SIZE_M(1)) #define UART0_BASE (MMIO_BASE + 0x07180000) #define UART0_SIZE SIZE_K(64) #define UART1_BASE (MMIO_BASE + 0x07190000) #define UART1_SIZE SIZE_K(64) #define UART2_BASE (MMIO_BASE + 0x071A0000) #define UART2_SIZE SIZE_K(64) #define UART3_BASE (MMIO_BASE + 0x071B0000) #define UART3_SIZE SIZE_K(64) #define SGRF_BASE (MMIO_BASE + 0x07330000) #define SGRF_SIZE SIZE_K(64) #elif defined(PLATFORM_FLAVOR_px30) #define GIC_BASE 0xff130000 #define GIC_SIZE SIZE_K(64) #define GICD_BASE (GIC_BASE + 0x1000) #define GICC_BASE (GIC_BASE + 0x2000) #define UART1_BASE 0xff158000 #define UART1_SIZE SIZE_K(64) #define UART2_BASE 0xff160000 #define UART2_SIZE SIZE_K(64) #define UART5_BASE 0xff178000 #define UART5_SIZE SIZE_K(64) #define FIREWALL_DDR_BASE 0xff534000 #define FIREWALL_DDR_SIZE SIZE_K(16) #else #error "Unknown platform flavor" #endif #ifdef CFG_WITH_LPAE #define MAX_XLAT_TABLES 5 #endif #endif optee_os-4.3.0/core/arch/arm/plat-rockchip/platform_px30.c000066400000000000000000000024261464416617300234010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #include #include #include #include #include #include #define FIREWALL_DDR_FW_DDR_RGN(i) ((i) * 0x4) #define FIREWALL_DDR_FW_DDR_MST(i) (0x20 + (i) * 0x4) #define FIREWALL_DDR_FW_DDR_CON_REG 0x40 #define FIREWALL_DDR_FW_DDR_RGN_NUM 8 #define FIREWALL_DDR_FW_DDR_MST_NUM 6 #define RG_MAP_SECURE(top, base) ((((top) - 1) << 16) | (base)) register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE); int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) { vaddr_t fw_base = (vaddr_t)phys_to_virt_io(FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE); paddr_t ed = st + sz; uint32_t st_mb = st / SIZE_M(1); uint32_t ed_mb = ed / SIZE_M(1); if (!fw_base) panic(); assert(rgn <= 7); assert(st < ed); /* Check aligned 1MB */ assert(st % SIZE_M(1) == 0); assert(ed % SIZE_M(1) == 0); DMSG("protecting region %d: 0x%lx-0x%lx", rgn, st, ed); /* Map top and base */ io_write32(fw_base + FIREWALL_DDR_FW_DDR_RGN(rgn), RG_MAP_SECURE(ed_mb, st_mb)); /* Enable secure setting */ io_setbits32(fw_base + FIREWALL_DDR_FW_DDR_CON_REG, BIT(rgn)); return 0; } optee_os-4.3.0/core/arch/arm/plat-rockchip/platform_rk322x.c000066400000000000000000000021541464416617300236400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, SGRF_BASE, SGRF_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, DDRSGRF_BASE, DDRSGRF_SIZE); #define SGRF_SOC_CON(n) ((n) * 4) #define DDR_SGRF_DDR_CON(n) ((n) * 4) #define DDR_RGN0_NS BIT32(30) #define SLAVE_ALL_NS GENMASK_32(31, 16) int platform_secure_init(void) { vaddr_t sgrf_base = (vaddr_t)phys_to_virt_io(SGRF_BASE, SGRF_SIZE); vaddr_t ddrsgrf_base = (vaddr_t)phys_to_virt_io(DDRSGRF_BASE, DDRSGRF_SIZE); /* Set rgn0 non-secure */ io_write32(ddrsgrf_base + DDR_SGRF_DDR_CON(0), DDR_RGN0_NS); /* Initialize all slave non-secure */ io_write32(sgrf_base + SGRF_SOC_CON(7), SLAVE_ALL_NS); io_write32(sgrf_base + SGRF_SOC_CON(8), SLAVE_ALL_NS); io_write32(sgrf_base + SGRF_SOC_CON(9), SLAVE_ALL_NS); io_write32(sgrf_base + SGRF_SOC_CON(10), SLAVE_ALL_NS); return 0; } optee_os-4.3.0/core/arch/arm/plat-rockchip/platform_rk3399.c000066400000000000000000000023221464416617300235460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH */ #include #include #include #include #include #include #define SGRF_DDRRGN_CON0_16(n) ((n) * 4) #define SGRF_DDR_RGN_0_16_WMSK GENMASK_32(11, 0) register_phys_mem_pgdir(MEM_AREA_IO_SEC, SGRF_BASE, SGRF_SIZE); int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) { vaddr_t sgrf_base = (vaddr_t)phys_to_virt_io(SGRF_BASE, SGRF_SIZE); paddr_t ed = st + sz; uint32_t st_mb = st / SIZE_M(1); uint32_t ed_mb = ed / SIZE_M(1); if (!sgrf_base) panic(); assert(rgn <= 7); assert(st < ed); /* Check aligned 1MB */ assert(st % SIZE_M(1) == 0); assert(ed % SIZE_M(1) == 0); DMSG("protecting region %d: 0x%lx-0x%lx", rgn, st, ed); /* Set ddr region addr start */ io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(rgn), BITS_WITH_WMASK(st_mb, SGRF_DDR_RGN_0_16_WMSK, 0)); /* Set ddr region addr end */ io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(rgn + 8), BITS_WITH_WMASK((ed_mb - 1), SGRF_DDR_RGN_0_16_WMSK, 0)); io_write32(sgrf_base + SGRF_DDRRGN_CON0_16(16), BIT_WITH_WMSK(rgn)); return 0; } optee_os-4.3.0/core/arch/arm/plat-rockchip/psci_rk322x.c000066400000000000000000000217131464416617300227540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct dram_data { uint32_t cru_mode_con; uint32_t cru_clksel0; uint32_t cru_clksel1; uint32_t cru_clksel10; uint32_t cru_clksel21; uint32_t cru_clkgate[CRU_CLKGATE_CON_CNT]; }; static struct dram_data dram_d; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CRU_BASE, CRU_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GRF_BASE, GRF_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, ISRAM_BASE, ISRAM_SIZE); static const uint32_t clks_gating_table[CRU_CLKGATE_CON_CNT] = { /* gate: 0-3 */ 0xefb8, 0x0ff7, 0xfff4, 0x887f, /* gate: 4-7 */ 0x0030, 0x00f8, 0x07e0, 0xc000, /* gate: 8-11 */ 0xff84, 0xb047, 0x1ca0, 0x57ff, /* gate: 12-15 */ 0x0000, 0x00ff, 0x1cc0, 0x000f, }; static void clks_disable(void) { uint32_t i; vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); for (i = 0; i < CRU_CLKGATE_CON_CNT; i++) { dram_d.cru_clkgate[i] = io_read32(va_base + CRU_CLKGATE_CON(i)); io_write32(va_base + CRU_CLKGATE_CON(i), BITS_WITH_WMASK(clks_gating_table[i], 0xffff, 0)); } } static void clks_restore(void) { uint32_t i; vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); for (i = 0; i < CRU_CLKGATE_CON_CNT; i++) io_write32(va_base + CRU_CLKGATE_CON(i), BITS_WITH_WMASK(dram_d.cru_clkgate[i], 0xffff, 0)); } static void pll_power_down(uint32_t pll) { vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); io_write32(va_base + CRU_MODE_CON, PLL_SLOW_MODE(pll)); io_write32(va_base + CRU_PLL_CON1(pll), PLL_POWER_DOWN); } static void pll_power_up(uint32_t pll) { vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); io_write32(va_base + CRU_PLL_CON1(pll), PLL_POWER_UP); } static void pll_wait_lock(uint32_t pll) { uint32_t loop = 0; vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); while (!(io_read32(va_base + CRU_PLL_CON1(pll)) & PLL_LOCK) && (loop < 500)) { udelay(2); loop++; } if (!(io_read32(va_base + CRU_PLL_CON1(pll)) & PLL_LOCK)) { EMSG("PLL can't lock, index = %" PRIu32, pll); panic(); } } /* * Select clock from external 24MHz OSC(slow mode) and power down plls, * then set frequency division of relevant bus to 24MHz. */ static void plls_power_down(void) { vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); dram_d.cru_clksel0 = io_read32(va_base + CRU_CLKSEL_CON(0)); dram_d.cru_clksel1 = io_read32(va_base + CRU_CLKSEL_CON(1)); dram_d.cru_clksel10 = io_read32(va_base + CRU_CLKSEL_CON(10)); dram_d.cru_clksel21 = io_read32(va_base + CRU_CLKSEL_CON(21)); dram_d.cru_mode_con = io_read32(va_base + CRU_MODE_CON); pll_power_down(GPLL_ID); pll_power_down(CPLL_ID); pll_power_down(APLL_ID); /* core */ io_write32(va_base + CRU_CLKSEL_CON(0), BITS_WITH_WMASK(0, 0x1f, 0)); io_write32(va_base + CRU_CLKSEL_CON(1), BITS_WITH_WMASK(0, 0xf, 0) | BITS_WITH_WMASK(0, 0x7, 4)); /* peri aclk, hclk, pclk */ io_write32(va_base + CRU_CLKSEL_CON(10), BITS_WITH_WMASK(0, 0x1f, 0) | BITS_WITH_WMASK(0, 0x3, 8) | BITS_WITH_WMASK(0, 0x7, 12)); /* pdbus */ io_write32(va_base + CRU_CLKSEL_CON(0), BITS_WITH_WMASK(0, 0x1f, 8)); io_write32(va_base + CRU_CLKSEL_CON(1), BITS_WITH_WMASK(0, 0x3, 8) | BITS_WITH_WMASK(0, 0x7, 12)); /* hdmi cec 32k */ io_write32(va_base + CRU_CLKSEL_CON(21), BITS_WITH_WMASK(732, 0x3fff, 0) | BITS_WITH_WMASK(2, 0x3, 14)); } static void plls_restore(void) { vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); /* power up plls */ pll_power_up(APLL_ID); pll_power_up(GPLL_ID); pll_power_up(CPLL_ID); udelay(200); /* wait lock*/ pll_wait_lock(APLL_ID); pll_wait_lock(GPLL_ID); pll_wait_lock(CPLL_ID); /* hdmi cec 32k */ io_write32(va_base + CRU_CLKSEL_CON(21), dram_d.cru_clksel21 | BITS_WMSK(0x3fff, 0) | BITS_WMSK(0x3, 14)); /* pdbus */ io_write32(va_base + CRU_CLKSEL_CON(0), dram_d.cru_clksel0 | BITS_WMSK(0x1f, 8)); io_write32(va_base + CRU_CLKSEL_CON(1), dram_d.cru_clksel1 | BITS_WMSK(0x3, 8) | BITS_WMSK(0x7, 12)); /* peri aclk, hclk, pclk */ io_write32(va_base + CRU_CLKSEL_CON(10), dram_d.cru_clksel10 | BITS_WMSK(0x1f, 0) | BITS_WMSK(0x3, 8) | BITS_WMSK(0x7, 12)); /* core */ io_write32(va_base + CRU_CLKSEL_CON(0), dram_d.cru_clksel0 | BITS_WMSK(0x1f, 0)); io_write32(va_base + CRU_CLKSEL_CON(1), dram_d.cru_clksel1 | BITS_WMSK(0xf, 0) | BITS_WMSK(0x7, 4)); /* resume plls mode */ io_write32(va_base + CRU_MODE_CON, dram_d.cru_mode_con | BITS_WMSK(0x1, PLL_MODE_BIT(APLL_ID))); io_write32(va_base + CRU_MODE_CON, dram_d.cru_mode_con | BITS_WMSK(0x1, PLL_MODE_BIT(CPLL_ID))); io_write32(va_base + CRU_MODE_CON, dram_d.cru_mode_con | BITS_WMSK(0x1, PLL_MODE_BIT(GPLL_ID))); } static bool wait_core_wfe_i(uint32_t core) { uint32_t wfei_mask, loop = 0; vaddr_t va_base = (vaddr_t)phys_to_virt_io(GRF_BASE, GRF_SIZE); wfei_mask = CORE_WFE_I_MASK(core); while (!(io_read32(va_base + GRF_CPU_STATUS1) & wfei_mask) && loop < 500) { udelay(2); loop++; } return io_read32(va_base + GRF_CPU_STATUS1) & wfei_mask; } static bool core_held_in_reset(uint32_t core) { uint32_t val; vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); val = io_read32(va_base + CRU_SOFTRST_CON(0)); return val & CORE_HELD_IN_RESET(core); } uint32_t psci_version(void) { return PSCI_VERSION_1_0; } int psci_features(uint32_t psci_fid) { switch (psci_fid) { case PSCI_PSCI_FEATURES: case PSCI_VERSION: case PSCI_CPU_ON: case PSCI_CPU_OFF: case PSCI_SYSTEM_SUSPEND: case PSCI_SYSTEM_RESET: return PSCI_RET_SUCCESS; default: return PSCI_RET_NOT_SUPPORTED; } } int psci_cpu_on(uint32_t core_idx, uint32_t entry, uint32_t context_id) { bool wfei; vaddr_t cru_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); vaddr_t isram_base = (vaddr_t)phys_to_virt_io(ISRAM_BASE, ISRAM_SIZE); core_idx &= MPIDR_CPU_MASK; if ((core_idx == 0) || (core_idx >= CFG_TEE_CORE_NB_CORE)) return PSCI_RET_INVALID_PARAMETERS; DMSG("core_id: %" PRIu32, core_idx); /* set secondary cores' NS entry addresses */ boot_set_core_ns_entry(core_idx, entry, context_id); /* wait */ if (!core_held_in_reset(core_idx)) { wfei = wait_core_wfe_i(core_idx); if (!wfei) { EMSG("Can't wait cpu%" PRIu32 " wfei before softrst", core_idx); return PSCI_RET_DENIED; } } /* soft reset core */ io_write32(cru_base + CRU_SOFTRST_CON(0), CORE_SOFT_RESET(core_idx)); dsb(); udelay(2); /* soft release core */ io_write32(cru_base + CRU_SOFTRST_CON(0), CORE_SOFT_RELEASE(core_idx)); dsb(); /* wait */ wfei = wait_core_wfe_i(core_idx); if (!wfei) { EMSG("Can't wait cpu%" PRIu32 " wfei after softrst", core_idx); return PSCI_RET_DENIED; } /* set secondary secure entry address and lock tag */ io_write32(isram_base + BOOT_ADDR_OFFSET, TEE_LOAD_ADDR); io_write32(isram_base + LOCK_ADDR_OFFSET, LOCK_TAG); dsb(); sev(); dsb(); return PSCI_RET_SUCCESS; } int psci_cpu_off(void) { uint32_t core = get_core_pos(); if ((core == 0) || (core >= CFG_TEE_CORE_NB_CORE)) return PSCI_RET_INVALID_PARAMETERS; DMSG("core_id: %" PRIu32, core); psci_armv7_cpu_off(); thread_mask_exceptions(THREAD_EXCP_ALL); while (1) wfi(); return PSCI_RET_INTERNAL_FAILURE; } int psci_affinity_info(uint32_t affinity, uint32_t lowest_affnity_level __unused) { uint32_t core_idx = affinity & MPIDR_CPU_MASK; uint32_t wfi_mask = CORE_WFI_MASK(core_idx); vaddr_t va_base = (vaddr_t)phys_to_virt_io(GRF_BASE, GRF_SIZE); DMSG("core_id: %" PRIu32 " STATUS: %" PRIx32 " MASK: %" PRIx32, core_idx, io_read32(va_base + GRF_CPU_STATUS1), wfi_mask); return (io_read32(va_base + GRF_CPU_STATUS1) & wfi_mask) ? PSCI_AFFINITY_LEVEL_OFF : PSCI_AFFINITY_LEVEL_ON; } void psci_system_reset(void) { vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); /* PLLs enter slow mode */ io_write32(va_base + CRU_MODE_CON, PLLS_SLOW_MODE); dsb(); /* Global second reset */ io_write32(va_base + CRU_SNDRST_VAL_BASE, CRU_SNDRST_VAL); dsb(); } int psci_system_suspend(uintptr_t entry __unused, uint32_t context_id __unused, struct sm_nsec_ctx *nsec __unused) { DMSG("system suspend"); clks_disable(); plls_power_down(); cache_op_inner(DCACHE_CLEAN_INV, NULL, 0); wfi(); plls_restore(); clks_restore(); return PSCI_RET_SUCCESS; } /* When SMP bootup, we release cores one by one */ static TEE_Result reset_nonboot_cores(void) { vaddr_t va_base = (vaddr_t)phys_to_virt_io(CRU_BASE, CRU_SIZE); io_write32(va_base + CRU_SOFTRST_CON(0), NONBOOT_CORES_SOFT_RESET); return TEE_SUCCESS; } service_init_late(reset_nonboot_cores); optee_os-4.3.0/core/arch/arm/plat-rockchip/sub.mk000066400000000000000000000005231464416617300216550ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += platform.c srcs-$(PLATFORM_FLAVOR_px30) += platform_px30.c srcs-$(PLATFORM_FLAVOR_rk322x) += platform_rk322x.c srcs-$(PLATFORM_FLAVOR_rk3399) += platform_rk3399.c ifeq ($(PLATFORM_FLAVOR),rk322x) srcs-y += plat_init.S srcs-y += core_pos_a32.S srcs-$(CFG_PSCI_ARM32) += psci_rk322x.c endif optee_os-4.3.0/core/arch/arm/plat-rpi3/000077500000000000000000000000001464416617300176065ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-rpi3/conf.mk000066400000000000000000000014311464416617300210630ustar00rootroot00000000000000include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) CFG_SHMEM_START ?= 0x08000000 CFG_SHMEM_SIZE ?= 0x00400000 CFG_TZDRAM_START ?= 0x10100000 CFG_TZDRAM_SIZE ?= 0x00F00000 CFG_TEE_RAM_VA_SIZE ?= 0x00700000 $(call force,CFG_8250_UART,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) CFG_NUM_THREADS ?= 4 CFG_CRYPTO_WITH_CE ?= n CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_WITH_STACK_CANARIES ?= y CFG_WITH_STATS ?= y arm32-platform-cflags += -Wno-error=cast-align arm64-platform-cflags += -Wno-error=cast-align $(call force,CFG_CRYPTO_SHA256_ARM32_CE,n) $(call force,CFG_CRYPTO_SHA256_ARM64_CE,n) $(call force,CFG_CRYPTO_SHA1_ARM32_CE,n) $(call force,CFG_CRYPTO_SHA1_ARM64_CE,n) $(call force,CFG_CRYPTO_AES_ARM64_CE,n) optee_os-4.3.0/core/arch/arm/plat-rpi3/main.c000066400000000000000000000036401464416617300207010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); static struct serial8250_uart_data console_data; void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-rpi3/platform_config.h000066400000000000000000000047071464416617300231400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Sequitur Labs Inc. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #ifdef ARM64 #ifdef CFG_WITH_PAGER #error "Pager not supported for ARM64" #endif #endif /* ARM64 */ /* 16550 UART */ #define CONSOLE_UART_BASE 0x3f215040 /* UART0 */ #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 19200000 /* * RPi memory map * * No secure memory on RPi... * * * Available to Linux * 0x0a00_0000 * TA RAM: 16 MiB | * 0x0842_0000 | TZDRAM * TEE RAM: 4 MiB (TEE_RAM_VA_SIZE) | * 0x0840_0000 [ARM Trusted Firmware ] - * 0x0840_0000 [TZDRAM_BASE, BL32_LOAD_ADDR] - * Shared memory: 4 MiB | * 0x0800_0000 | DRAM0 * Available to Linux | * 0x0000_0000 [DRAM0_BASE] - * */ #define DRAM0_BASE 0x00000000 #define DRAM0_SIZE 0x40000000 #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-rpi3/sub.mk000066400000000000000000000000471464416617300207310ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-rzg/000077500000000000000000000000001464416617300175335ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-rzg/conf.mk000066400000000000000000000024651464416617300210200ustar00rootroot00000000000000PLATFORM_FLAVOR ?= hihope_rzg2m include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_SCIF,y) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) # Disable core ASLR for two reasons: # 1. There is no source for ALSR seed, as RZ/G2 platform # does not provide DTB to OP-TEE. Also, there is no # publicly available documentation on integrated # hardware RNG, so we can't use it either. # 2. OP-TEE crashes during boot with enabled CFG_CORE_ASLR. $(call force,CFG_CORE_ASLR,n) ifeq ($(PLATFORM_FLAVOR),ek874) $(call force,CFG_TEE_CORE_NB_CORE,2) endif ifeq ($(PLATFORM_FLAVOR),hihope_rzg2m) $(call force,CFG_TEE_CORE_NB_CORE,6) # RZ/G2M have 6 cores for 2 clusters, but the number isn't contiguous. # One cluster has ids 0, 1, other has ids 3, 4, 5, 6. # CFG_CORE_CLUSTER_SHIFT will process to make the right numbering. $(call force,CFG_CORE_CLUSTER_SHIFT,1) endif ifeq ($(PLATFORM_FLAVOR),hihope_rzg2n) $(call force,CFG_TEE_CORE_NB_CORE,2) endif ifeq ($(PLATFORM_FLAVOR),hihope_rzg2h) $(call force,CFG_TEE_CORE_NB_CORE,8) endif CFG_TZDRAM_START ?= 0x44100000 CFG_TZDRAM_SIZE ?= 0x03D00000 CFG_TEE_RAM_VA_SIZE ?= 0x100000 ifeq ($(CFG_ARM64_core),y) supported-ta-targets = ta_arm64 endif CFG_DT ?= y optee_os-4.3.0/core/arch/arm/plat-rzg/link.mk000066400000000000000000000001041464416617300210140ustar00rootroot00000000000000include core/arch/arm/kernel/link.mk all: $(link-out-dir)/tee.srec optee_os-4.3.0/core/arch/arm/plat-rzg/main.c000066400000000000000000000017751464416617300206350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, GlobalLogic * Copyright (c) 2019-2020, Renesas Electronics Corporation */ #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, SCIF_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_DIST_REG_SIZE); register_dynamic_shm(NSEC_DDR_0_BASE, NSEC_DDR_0_SIZE); #ifdef NSEC_DDR_1_BASE register_dynamic_shm(NSEC_DDR_1_BASE, NSEC_DDR_1_SIZE); #endif #ifdef NSEC_DDR_2_BASE register_dynamic_shm(NSEC_DDR_2_BASE, NSEC_DDR_2_SIZE); #endif #ifdef NSEC_DDR_3_BASE register_dynamic_shm(NSEC_DDR_3_BASE, NSEC_DDR_3_SIZE); #endif static struct scif_uart_data console_data __nex_bss; void plat_console_init(void) { scif_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-rzg/platform_config.h000066400000000000000000000024131464416617300230550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, GlobalLogic * Copyright (c) 2020, Renesas Electronics Corporation */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #define GIC_BASE 0xF1000000 #define GICC_BASE 0xF1020000 #define GICD_BASE 0xF1010000 #define CONSOLE_UART_BASE 0xE6E88000 #if defined(PLATFORM_FLAVOR_ek874) #define NSEC_DDR_0_BASE 0x47E00000U #define NSEC_DDR_0_SIZE 0x78200000 #elif defined(PLATFORM_FLAVOR_hihope_rzg2h) #define NSEC_DDR_0_BASE 0x47E00000U #define NSEC_DDR_0_SIZE 0x78200000 #define NSEC_DDR_1_BASE 0x500000000U #define NSEC_DDR_1_SIZE 0x80000000 #elif defined(PLATFORM_FLAVOR_hihope_rzg2m) #define NSEC_DDR_0_BASE 0x47E00000U #define NSEC_DDR_0_SIZE 0x78200000 #define NSEC_DDR_1_BASE 0x600000000U #define NSEC_DDR_1_SIZE 0x80000000 #elif defined(PLATFORM_FLAVOR_hihope_rzg2n) #define NSEC_DDR_0_BASE 0x47E00000U #define NSEC_DDR_0_SIZE 0x78200000 #define NSEC_DDR_1_BASE 0x480000000U #define NSEC_DDR_1_SIZE 0x80000000 #else #error "Unknown platform flavor" #endif #define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) #define TEE_SHMEM_SIZE 0x100000 #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-rzg/sub.mk000066400000000000000000000000471464416617300206560ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-rzn1/000077500000000000000000000000001464416617300176235ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-rzn1/a7_plat_init.S000066400000000000000000000033201464416617300223170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Wind River Systems. * Copyright (c) 2020, Linaro Limited */ /* * Entry points for the A7 init. * * Assumptions: * - No stack is available when these routines are called. * - Each routine is called with return address in LR and * with ARM registers R0, R1, R2, R3 being scratchable. */ #include #include #include #include .section .text .balign 4 .code 32 FUNC plat_cpu_reset_early , : /* * SCR = 0x00000020 * - FW: Disallow NSec to mask FIQ [bit4=0] * - AW: Allow NSec to manage Imprecise Abort [bit5=1] * - EA: Imprecise Abort trapped to Abort Mode [bit3=0] * - FIQ: In Sec world, FIQ trapped to FIQ Mode [bit2=0] * - IRQ: IRQ always trapped to IRQ Mode [bit1=0] * - NS: Secure World [bit0=0] */ mov r0, #SCR_AW write_scr r0 mov_imm r0, 0x00000000 write_sctlr r0 /* * ACTRL = 0x00006040 * - DDI: Disable dual issue [bit28=0] * - DDVM: Disable Distributed Virtual Memory transactions [bit15=0] * - L1PCTL: L1 Data prefetch control [bit14:13=2b11] * - L1RADIS: L1 Data Cache read-allocate mode disable [bit12=0] * - L2RADIS: L2 Data Cache read-allocate mode disable [bit11=0] * - DODMBS: Disable optimized data memory barrier behavior [bit10=0] * - SMP: Enables coherent requests to the processor [bit6=0] */ mov_imm r0, 0x00006040 write_actlr r0 /* * NSACR = 0x00000C00 * - NS_SMP: Non-secure mode cannot change ACTRL.SMP (bit18=0) * - NSASEDIS/NSD32DIS/CP10/CP11: Non-secure mode can use SIMD/VFP * (bit15:14=2b00, bit11:10=2b11) */ mov_imm r0, 0x00000C00 write_nsacr r0 mov pc, lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-rzn1/conf.mk000066400000000000000000000013061464416617300211010ustar00rootroot00000000000000PLATFORM_FLAVOR ?= rzn1 include core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_ARM32_core,y) $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_BOOT_SECONDARY_REQUEST,y) $(call force,CFG_SECONDARY_INIT_CNTFRQ,y) $(call force,CFG_PSCI_ARM32,y) $(call force,CFG_16550_UART,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_PAGER,n) $(call force,CFG_GIC,y) $(call force,CFG_SM_PLATFORM_HANDLER,y) $(call force,CFG_TA_FLOAT_SUPPORT,n) ta-targets = ta_arm32 CFG_TZDRAM_START ?= 0x88000000 CFG_TZDRAM_SIZE ?= 0x00A00000 CFG_SHMEM_START ?= 0x87C00000 CFG_SHMEM_SIZE ?= 0x00400000 CFG_TEE_RAM_VA_SIZE ?= 0x00200000 CFG_NUM_THREADS ?= 4 CFG_NS_ENTRY_ADDR ?= 0x87A00000 CFG_BOOT_CM3 ?= y optee_os-4.3.0/core/arch/arm/plat-rzn1/main.c000066400000000000000000000055071464416617300207220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Schneider Electric * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #define SYSCTRL_PWRCTRL_CM3 (SYSCTRL_BASE + 0x174) #define SYSCTRL_PWRSTAT_CM3 (SYSCTRL_BASE + 0x178) #define SYSCTRL_PWRCTRL_CM3_CLKEN_A BIT(0) #define SYSCTRL_PWRCTRL_CM3_RSTN_A BIT(1) #define SYSCTRL_PWRCTRL_CM3_MIREQ_A BIT(2) #define SYSCTRL_PWRSTAT_CM3_MIRACK_A BIT(0) /* Timeout waiting for Master Idle Request Acknowledge */ #define IDLE_ACK_TIMEOUT_US 1000 static struct ns16550_data console_data; register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem(MEM_AREA_IO_SEC, PERIPH_REG_BASE, CORE_MMU_PGDIR_SIZE); register_ddr(DRAM_BASE, DRAM_SIZE); void plat_console_init(void) { ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2); register_serial_console(&console_data.chip); } void boot_primary_init_intc(void) { gic_init(GICC_BASE, GICD_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } static TEE_Result rzn1_tz_init(void) { vaddr_t tza_init_reg = 0; vaddr_t tza_targ_reg = 0; tza_init_reg = core_mmu_get_va(FW_STATIC_TZA_INIT, MEM_AREA_IO_SEC, sizeof(uint32_t)); tza_targ_reg = core_mmu_get_va(FW_STATIC_TZA_TARG, MEM_AREA_IO_SEC, sizeof(uint32_t)); /* TZ initiator ports */ io_write32(tza_init_reg, TZ_INIT_CSA_SEC | TZ_INIT_YS_SEC | TZ_INIT_YC_SEC | TZ_INIT_YD_SEC); /* TZ target ports */ io_write32(tza_targ_reg, TZ_TARG_PC_SEC | TZ_TARG_QB_SEC | TZ_TARG_QA_SEC | TZ_TARG_UB_SEC | TZ_TARG_UA_SEC); return TEE_SUCCESS; } service_init(rzn1_tz_init); #ifdef CFG_BOOT_CM3 static TEE_Result rzn1_cm3_start(void) { vaddr_t cm3_pwrctrl_reg = 0; vaddr_t cm3_pwrstat_reg = 0; uint64_t timeout_ack = timeout_init_us(IDLE_ACK_TIMEOUT_US); cm3_pwrctrl_reg = core_mmu_get_va(SYSCTRL_PWRCTRL_CM3, MEM_AREA_IO_SEC, sizeof(uint32_t)); cm3_pwrstat_reg = core_mmu_get_va(SYSCTRL_PWRSTAT_CM3, MEM_AREA_IO_SEC, sizeof(uint32_t)); /* Master Idle Request to the interconnect for CM3 */ io_clrbits32(cm3_pwrctrl_reg, SYSCTRL_PWRCTRL_CM3_MIREQ_A); /* Wait for Master Idle Request Acknowledge for CM3 */ while (!timeout_elapsed(timeout_ack)) if (!(io_read32(cm3_pwrstat_reg) & SYSCTRL_PWRSTAT_CM3_MIRACK_A)) break; if (io_read32(cm3_pwrstat_reg) & SYSCTRL_PWRSTAT_CM3_MIRACK_A) panic(); /* Clock Enable for CM3_HCLK & Active low Reset to CM3 */ io_setbits32(cm3_pwrctrl_reg, SYSCTRL_PWRCTRL_CM3_CLKEN_A); io_setbits32(cm3_pwrctrl_reg, SYSCTRL_PWRCTRL_CM3_RSTN_A); return TEE_SUCCESS; } service_init(rzn1_cm3_start); #endif optee_os-4.3.0/core/arch/arm/plat-rzn1/platform_config.h000066400000000000000000000013141464416617300231440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Schneider Electric * Copyright (c) 2020, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* DRAM */ #define DRAM_BASE 0x80000000 #define DRAM_SIZE 0x40000000 /* 1GB, and support 256MB */ /* GIC */ #define GIC_BASE 0x44100000 #define GICD_OFFSET 0x1000 #define GICC_OFFSET 0x2000 #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) /* Peripheral memory map */ #define PERIPH_REG_BASE 0x40000000 /* System Control */ #define SYSCTRL_BASE 0x4000C000 /* UART */ #define CONSOLE_UART_BASE 0x40060000 #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-rzn1/psci.c000066400000000000000000000036051464416617300207310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Schneider Electric * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include #include #include #define SYSCTRL_REG_RSTEN (SYSCTRL_BASE + 0x120) #define SYSCTRL_REG_RSTCTRL (SYSCTRL_BASE + 0x198) #define SYSCTRL_BOOTADDR_REG (SYSCTRL_BASE + 0x204) #define SYSCTRL_REG_RSTEN_MRESET_EN BIT(0) #define SYSCTRL_REG_RSTEN_SWRST_EN BIT(6) #define SYSCTRL_REG_RSTCTRL_SWRST_REQ BIT(6) int psci_features(uint32_t psci_fid) { switch (psci_fid) { case PSCI_PSCI_FEATURES: case PSCI_VERSION: case PSCI_CPU_ON: case PSCI_CPU_OFF: case PSCI_SYSTEM_RESET: return PSCI_RET_SUCCESS; default: return PSCI_RET_NOT_SUPPORTED; } } uint32_t psci_version(void) { return PSCI_VERSION_1_0; } int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) { vaddr_t sctl_va = core_mmu_get_va(SYSCTRL_BOOTADDR_REG, MEM_AREA_IO_SEC, sizeof(uint32_t)); if (core_id == 0 || core_id >= CFG_TEE_CORE_NB_CORE) return PSCI_RET_INVALID_PARAMETERS; DMSG("core_id: %" PRIu32, core_id); boot_set_core_ns_entry(core_id, entry, context_id); io_write32(sctl_va, TEE_LOAD_ADDR); dsb(); sev(); return PSCI_RET_SUCCESS; } int __noreturn psci_cpu_off(void) { DMSG("core_id: %" PRIu32, get_core_pos()); psci_armv7_cpu_off(); thread_mask_exceptions(THREAD_EXCP_ALL); while (1) wfi(); } void psci_system_reset(void) { /* Enable software reset */ io_setbits32(core_mmu_get_va(SYSCTRL_REG_RSTEN, MEM_AREA_IO_SEC, sizeof(uint32_t)), SYSCTRL_REG_RSTEN_SWRST_EN | SYSCTRL_REG_RSTEN_MRESET_EN); /* Trigger software reset */ io_setbits32(core_mmu_get_va(SYSCTRL_REG_RSTCTRL, MEM_AREA_IO_SEC, sizeof(uint32_t)), SYSCTRL_REG_RSTCTRL_SWRST_REQ); dsb(); } optee_os-4.3.0/core/arch/arm/plat-rzn1/rzn1_regauth.h000066400000000000000000000014411464416617300224050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Schneider Electric * Copyright (c) 2020, Linaro Limited */ #ifndef RZN1_REGAUTH_H #define RZN1_REGAUTH_H struct regauth_t { uint32_t paddr; uint32_t size; uint32_t rmask; uint32_t wmask; }; static const struct regauth_t regauth[] = { /* OTP */ { 0x40007000U, 0x4U, 0x0U, 0x0U }, /* OTPWCTRL */ /* System Controller */ { 0x4000C064U, 0x4U, 0xFFFFFFFFU, 0xFFFFFFE0U }, /* PWRCTRL_DDRC */ { 0x4000C204U, 0x4U, 0x0U, 0x0U }, /* BOOTADDR */ /* DDR CTRL */ { 0x4000D16CU, 0x3FCU, 0x0U, 0x0U }, /* DDR_CTL 91-346 */ { 0x4000E000U, 0x4U, 0xFFFFFFFFU, 0xFFFFFFFEU }, /* UNCCTRL */ { 0x4000E004U, 0x4U, 0xFFFFFFFFU, 0xFFFFFFFEU }, /* DLLCTRL */ }; #endif /* RZN1_REGAUTH_H */ optee_os-4.3.0/core/arch/arm/plat-rzn1/rzn1_tz.h000066400000000000000000000025431464416617300214070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Schneider Electric * Copyright (c) 2020, Linaro Limited */ #ifndef RZN1_TZ_H #define RZN1_TZ_H #include /* TZ config registers */ #define FW_STATIC_TZA_INIT 0x4000C0D0 #define FW_STATIC_TZA_TARG 0x4000C0D4 /* TZ initiatior ports */ #define TZ_INIT_CSB_SEC BIT(7) /* CoreSight AHB */ #define TZ_INIT_CSA_SEC BIT(6) /* CoreSight AXI */ #define TZ_INIT_YS_SEC BIT(5) /* Cortex-M3 System Bus interface */ #define TZ_INIT_YC_SEC BIT(4) /* Cortex-M3 ICode interface */ #define TZ_INIT_YD_SEC BIT(3) /* Cortex-M3 DCode interface */ #define TZ_INIT_Z_SEC BIT(2) /* Packet Engine */ #define TZ_INIT_I_SEC BIT(1) /* Peripheral Group */ #define TZ_INIT_F_SEC BIT(0) /* Peripheral Group */ /* TZ target ports */ #define TZ_TARG_W_SEC BIT(14) /* RTC */ #define TZ_TARG_PC_SEC BIT(9) /* DDR2/3 Controller */ #define TZ_TARG_RA_SEC BIT(8) /* CoreSight */ #define TZ_TARG_QB_SEC BIT(7) /* System Control */ #define TZ_TARG_QA_SEC BIT(6) /* PG0 */ #define TZ_TARG_NB_SEC BIT(5) /* Packet Engine */ #define TZ_TARG_NA_SEC BIT(4) /* Public Key Processor */ #define TZ_TARG_K_SEC BIT(3) /* Peripheral Group */ #define TZ_TARG_J_SEC BIT(2) /* Peripheral Group */ #define TZ_TARG_UB_SEC BIT(1) /* 2MB SRAM */ #define TZ_TARG_UA_SEC BIT(0) /* 2MB SRAM */ #endif /* RZN1_TZ_H */ optee_os-4.3.0/core/arch/arm/plat-rzn1/sm_platform_handler.c000066400000000000000000000043421464416617300240120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include #include "rzn1_regauth.h" #define RZN1_OEM_CONSOLE_PUTC 0x01 #define RZN1_OEM_SYSREG_AUTH 0x10 static const struct regauth_t regauth_pass = {.rmask = ~0U, .wmask = ~0U}; static const struct regauth_t *get_regauth(unsigned long paddr) { unsigned int idx = 0; unsigned int len = ARRAY_SIZE(regauth); while (idx < len) { if (core_is_buffer_inside(paddr, sizeof(uint32_t), regauth[idx].paddr, regauth[idx].size)) return ®auth[idx]; idx++; } return NULL; } static uint32_t oem_sysreg(uint32_t addr, uint32_t mask, uint32_t *pvalue) { vaddr_t reg = 0; const struct regauth_t *auth = get_regauth(addr); /* Allow operations on registers not in the list */ if (!auth) auth = ®auth_pass; reg = core_mmu_get_va(addr, MEM_AREA_IO_SEC, sizeof(uint32_t)); if (mask) { /* Write operation */ mask &= auth->wmask; if (!reg || !mask) DMSG("Blocking write of 0x%"PRIx32" to register 0x%" PRIx32" (0x%"PRIxVA")", *pvalue, addr, reg); else if (mask == ~0UL) io_write32(reg, *pvalue); else io_mask32(reg, *pvalue, mask); } else { /* Read operation */ if (!reg || !auth->rmask) DMSG("Blocking read of register 0x%"PRIx32" (0x%" PRIxVA")", addr, reg); else *pvalue = io_read32(reg) & auth->rmask; } return 0; } static enum sm_handler_ret oem_service(struct sm_ctx *ctx __unused, struct thread_smc_args *args) { switch (OPTEE_SMC_FUNC_NUM(args->a0)) { case RZN1_OEM_SYSREG_AUTH: args->a0 = oem_sysreg(args->a1, args->a2, &args->a3); args->a1 = args->a3; break; case RZN1_OEM_CONSOLE_PUTC: console_putc(args->a1); break; default: return SM_HANDLER_PENDING_SMC; } return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) { struct thread_smc_args *args = (void *)&ctx->nsec.r0; if (!OPTEE_SMC_IS_FAST_CALL(args->a0)) return SM_HANDLER_PENDING_SMC; switch (OPTEE_SMC_OWNER_NUM(args->a0)) { case OPTEE_SMC_OWNER_OEM: return oem_service(ctx, args); default: return SM_HANDLER_PENDING_SMC; } } optee_os-4.3.0/core/arch/arm/plat-rzn1/sub.mk000066400000000000000000000001611464416617300207430ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += psci.c srcs-y += sm_platform_handler.c srcs-y += a7_plat_init.S optee_os-4.3.0/core/arch/arm/plat-sam/000077500000000000000000000000001464416617300175115ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-sam/conf.mk000066400000000000000000000065211464416617300207730ustar00rootroot00000000000000PLATFORM_FLAVOR ?= sama5d27_som1_ek flavor_dts_file-sama5d2xult = at91-sama5d2_xplained.dts flavor_dts_file-sama5d2_xplained = at91-sama5d2_xplained.dts flavor_dts_file-sama5d27_som1_ek = at91-sama5d27_som1_ek.dts flavor_dts_file-sama5d27_wlsom1_ek = at91-sama5d27_wlsom1_ek.dts flavor_dts_file-sama7g54_ek = at91-sama7g54_ek.dts ifeq ($(PLATFORM_FLAVOR),sama5d2xult) $(warning "sama5d2xult is deprecated, please use sama5d2_xplained") endif ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) $(error Invalid platform flavor $(PLATFORM_FLAVOR)) endif CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR)) ifeq ($(PLATFORM_FLAVOR),sama7g54_ek) include core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_SAMA7G5,y) $(call force,CFG_GIC,y) $(call force,CFG_TZC400,y) else include core/arch/arm/cpu/cortex-a5.mk $(call force,CFG_SAMA5D2,y) $(call force,CFG_ATMEL_SAIC,y) $(call force,CFG_PL310,y) endif $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_ATMEL_UART,y) $(call force,CFG_ATMEL_TCB,y) $(call force,CFG_NO_SMP,y) $(call force,CFG_AT91_MATRIX,y) $(call force,CFG_DRIVERS_CLK,y) $(call force,CFG_DRIVERS_CLK_DT,y) $(call force,CFG_DRIVERS_CLK_FIXED,y) $(call force,CFG_DRIVERS_SAM_CLK,y) $(call force,CFG_PSCI_ARM32,y) $(call force,CFG_SM_PLATFORM_HANDLER,y) $(call force,CFG_CORE_HAS_GENERIC_TIMER,n) # These values are forced because of matrix configuration for secure area. # When modifying these, always update matrix settings in # matrix_configure_slave_h64mx(). ifeq ($(CFG_SAMA7G5),y) $(call force,CFG_TZDRAM_START,0x60000000) endif ifeq ($(CFG_SAMA5D2),y) $(call force,CFG_TZDRAM_START,0x20000000) endif $(call force,CFG_TZDRAM_SIZE,0x800000) # This value is forced because these feature aren't used by SAM platforms. $(call force,CFG_EXTERNAL_DT,n) $(call force,CFG_CORE_DYN_SHM,n) CFG_MMAP_REGIONS ?= 24 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + 0x1000000) CFG_SHMEM_SIZE ?= 0x400000 CFG_SCMI_SHMEM_START ?= ($(CFG_TZDRAM_START) + 0x1400000) CFG_SCMI_SHMEM_SIZE ?= 0x1000 CFG_TEE_RAM_VA_SIZE ?= 0x100000 # Device tree related configuration CFG_DT_ADDR ?= ($(CFG_TZDRAM_START) + 0x1500000) CFG_GENERATE_DTB_OVERLAY ?= y CFG_WITH_SOFTWARE_PRNG ?= n CFG_ATMEL_TRNG ?= y ifeq ($(CFG_ATMEL_TRNG),y) CFG_HWRNG_PTA ?= y $(call force,CFG_HWRNG_QUALITY,1024) endif CFG_ATMEL_RSTC ?= y CFG_ATMEL_SHDWC ?= y CFG_ATMEL_PM ?= y ifeq ($(CFG_ATMEL_PM),y) # Suspend mode to be used on PSCI suspend call # 0 = STANDBY # 1 = ULP0 # 2 = ULP0 Fast # 3 = ULP1 # 4 = BACKUP CFG_ATMEL_PM_SUSPEND_MODE ?= 0 $(call force,CFG_ATMEL_SHDWC,y) $(call force,CFG_PM_ARM32,y) endif CFG_WDT ?= y CFG_WDT_SM_HANDLER ?= y ifeq ($(CFG_WDT_SM_HANDLER),y) CFG_WDT_SM_HANDLER_ID := 0x2000500 endif CFG_ATMEL_WDT ?= y CFG_DRIVERS_RTC ?= y CFG_RTC_PTA ?= y CFG_ATMEL_RTC ?= y CFG_ATMEL_PIOBU ?= y ifeq ($(PLATFORM_FLAVOR),sama5d27_wlsom1_ek) CFG_DRIVERS_GPIO ?= y CFG_DRIVERS_I2C ?= y CFG_ATMEL_I2C ?= y CFG_DRIVERS_PINCTRL ?= y CFG_ATMEL_PIO ?= y endif # SCMI related configuration CFG_SCMI_PTA ?= y CFG_SCMI_MSG_DRIVERS ?= y ifeq ($(CFG_SCMI_MSG_DRIVERS),y) $(call force,CFG_SCMI_MSG_SMT,y) $(call force,CFG_SCMI_MSG_CLOCK,y) $(call force,CFG_SCMI_MSG_USE_CLK,y) $(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y) endif CFG_DRIVERS_NVMEM ?= y ifeq ($(CFG_SAMA7G5),y) CFG_ATMEL_SFC ?= n CFG_NVMEM_DIE_ID ?= n CFG_NVMEM_HUK ?= n else CFG_ATMEL_SFC ?= y CFG_NVMEM_DIE_ID ?= y CFG_NVMEM_HUK ?= y endif optee_os-4.3.0/core/arch/arm/plat-sam/freq.c000066400000000000000000000015701464416617300206150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip */ #include #include #include #include #include #include #include #include #include static unsigned long freq; static TEE_Result get_freq_from_dt(void) { int node; struct clk *clk; const void *fdt = get_embedded_dt(); if (!fdt) panic(); if (IS_ENABLED(CFG_SAMA7G5)) node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a7"); else node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a5"); if (!node) panic(); if (clk_dt_get_by_name(fdt, node, "cpu", &clk)) panic(); freq = clk_get_rate(clk); return at91_clk_register_cpu_opp(fdt, node, clk); } early_init_late(get_freq_from_dt); unsigned long plat_get_freq(void) { assert(freq); return freq; } optee_os-4.3.0/core/arch/arm/plat-sam/matrix.c000066400000000000000000000160361464416617300211670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-Source-Code /* * Copyright (c) 2013, Atmel Corporation * Copyright (c) 2017, Timesys Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define WORLD_NON_SECURE 0 #define WORLD_SECURE 1 static void matrix_write(unsigned int base, unsigned int offset, const unsigned int value) { io_write32(offset + base, value); } static unsigned int matrix_read(int base, unsigned int offset) { return io_read32(offset + base); } vaddr_t matrix_base(unsigned int matrix) { unsigned int i = 0; struct matrix *pmatrix = NULL; do { pmatrix = matrix_get(i++); if (!pmatrix) panic("Invalid matrix"); } while (pmatrix->matrix != matrix); return io_pa_or_va_secure(&pmatrix->p, CORE_MMU_PGDIR_SIZE); } void matrix_write_protect_enable(unsigned int matrix_base) { matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE); } void matrix_write_protect_disable(unsigned int matrix_base) { matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD); } void matrix_configure_slave_security(unsigned int matrix_base, unsigned int slave, unsigned int srtop_setting, unsigned int srsplit_setting, unsigned int ssr_setting) { matrix_write(matrix_base, MATRIX_SSR(slave), ssr_setting); matrix_write(matrix_base, MATRIX_SRTSR(slave), srtop_setting); matrix_write(matrix_base, MATRIX_SASSR(slave), srsplit_setting); } static const struct peri_security *get_peri_security(unsigned int peri_id) { unsigned int i = 0; struct peri_security *p = NULL; do { p = peri_security_get(i++); if (p && peri_id == p->peri_id) break; } while (p); return p; } static int matrix_set_periph_world(unsigned int matrix, unsigned int peri_id, unsigned int world) { unsigned int spselr = 0; unsigned int idx = peri_id / 32; unsigned int bit = 0x01 << (peri_id % 32); unsigned int base = matrix_base(matrix); if (idx > 3) return -1; spselr = matrix_read(base, MATRIX_SPSELR(idx)); if (world == WORLD_SECURE) spselr &= ~bit; else spselr |= bit; matrix_write(base, MATRIX_SPSELR(idx), spselr); return 0; } TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id) { unsigned int i = 0; paddr_t pbase = 0; struct peri_security *p = NULL; pbase = fdt_reg_base_address(fdt, node); if (pbase == DT_INFO_INVALID_REG) return TEE_ERROR_BAD_PARAMETERS; do { p = peri_security_get(i++); if (p && p->addr == pbase) { *id = p->peri_id; return TEE_SUCCESS; } } while (p); return TEE_ERROR_ITEM_NOT_FOUND; } int matrix_configure_periph_secure(unsigned int peri_id) { const struct peri_security *psec = NULL; psec = get_peri_security(peri_id); if (!psec) return -1; return matrix_set_periph_world(psec->matrix, peri_id, WORLD_SECURE); } int matrix_configure_periph_non_secure(unsigned int *peri_id_array, unsigned int size) { unsigned int i = 0; unsigned int *peri_id_p = peri_id_array; unsigned int matrix = 0; unsigned int peri_id = 0; const struct peri_security *peripheral_sec = NULL; int ret = 0; if (!peri_id_array || !size) return -1; for (i = 0; i < size; i++) { peripheral_sec = get_peri_security(*peri_id_p); if (!peripheral_sec) return -1; if (peripheral_sec->security_type != SECURITY_TYPE_PS) return -1; matrix = peripheral_sec->matrix; peri_id = *peri_id_p; ret = matrix_set_periph_world(matrix, peri_id, WORLD_NON_SECURE); if (ret) return -1; peri_id_p++; } return 0; } #ifdef CFG_PM_ARM32 static void matrix_save_regs(vaddr_t base, struct matrix_state *state) { int idx = 0; for (idx = 0; idx < MATRIX_SPSELR_COUNT; idx++) state->spselr[idx] = matrix_read(base, MATRIX_SPSELR(idx)); for (idx = 0; idx < MATRIX_SLAVE_COUNT; idx++) { state->ssr[idx] = matrix_read(base, MATRIX_SSR(idx)); state->srtsr[idx] = matrix_read(base, MATRIX_SRTSR(idx)); state->sassr[idx] = matrix_read(base, MATRIX_SASSR(idx)); } state->meier = matrix_read(base, MATRIX_MEIER); state->meimr = matrix_read(base, MATRIX_MEIMR); } static void matrix_suspend(void) { unsigned int i = 0; struct matrix *pmatrix = NULL; for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++)) matrix_save_regs(matrix_base(pmatrix->matrix), &pmatrix->state); } static void matrix_restore_regs(vaddr_t base, struct matrix_state *state) { int idx = 0; matrix_write_protect_disable(base); for (idx = 0; idx < MATRIX_SPSELR_COUNT; idx++) matrix_write(base, MATRIX_SPSELR(idx), state->spselr[idx]); for (idx = 0; idx < MATRIX_SLAVE_COUNT; idx++) { matrix_write(base, MATRIX_SSR(idx), state->ssr[idx]); matrix_write(base, MATRIX_SRTSR(idx), state->srtsr[idx]); matrix_write(base, MATRIX_SASSR(idx), state->sassr[idx]); } matrix_write(base, MATRIX_MEIER, state->meier); matrix_write(base, MATRIX_MEIMR, state->meimr); } static void matrix_resume(void) { unsigned int i = 0; struct matrix *pmatrix = NULL; for (pmatrix = matrix_get(i++); pmatrix; pmatrix = matrix_get(i++)) matrix_restore_regs(matrix_base(pmatrix->matrix), &pmatrix->state); } static TEE_Result matrix_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl __unused) { switch (op) { case PM_OP_RESUME: matrix_resume(); break; case PM_OP_SUSPEND: matrix_suspend(); break; default: panic("Invalid PM operation"); } return TEE_SUCCESS; } static TEE_Result matrix_pm_init(void) { /* * We can't call matrix_register_pm in matrix_init since allocator is * not ready yet so we just call it later in this driver init callback. */ register_pm_driver_cb(matrix_pm, NULL, "sam-matrix"); return TEE_SUCCESS; } driver_init(matrix_pm_init); #endif optee_os-4.3.0/core/arch/arm/plat-sam/matrix.h000066400000000000000000000056251464416617300211760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-Source-Code */ /* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2013, Atmel Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MATRIX_H #define MATRIX_H #include #include #include #define SECURITY_TYPE_AS 1 #define SECURITY_TYPE_NS 2 #define SECURITY_TYPE_PS 3 #define MATRIX_SPSELR_COUNT 3 #define MATRIX_SLAVE_COUNT 15 #ifdef CFG_PM_ARM32 struct matrix_state { uint32_t spselr[MATRIX_SPSELR_COUNT]; uint32_t ssr[MATRIX_SLAVE_COUNT]; uint32_t srtsr[MATRIX_SLAVE_COUNT]; uint32_t sassr[MATRIX_SLAVE_COUNT]; uint32_t meier; uint32_t meimr; }; #endif struct matrix { unsigned int matrix; struct io_pa_va p; #ifdef CFG_PM_ARM32 struct matrix_state state; #endif }; struct peri_security { unsigned int peri_id; unsigned int matrix; unsigned int security_type; paddr_t addr; }; struct peri_security *peri_security_get(unsigned int idx); struct matrix *matrix_get(unsigned int idx); vaddr_t matrix_base(unsigned int matrix); void matrix_write_protect_enable(unsigned int matrix_base); void matrix_write_protect_disable(unsigned int matrix_base); void matrix_configure_slave_security(unsigned int matrix_base, unsigned int slave, unsigned int srtop_setting, unsigned int srsplit_setting, unsigned int ssr_setting); int matrix_configure_periph_non_secure(unsigned int *peri_id_array, unsigned int size); int matrix_configure_periph_secure(unsigned int peri_id); TEE_Result matrix_dt_get_id(const void *fdt, int node, unsigned int *id); #endif /* #ifndef MATRIX_H */ optee_os-4.3.0/core/arch/arm/plat-sam/nsec-service/000077500000000000000000000000001464416617300220775ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c000066400000000000000000000023611464416617300262650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #include static enum sm_handler_ret sam_sip_handler(struct thread_smc_args *args) { switch (OPTEE_SMC_FUNC_NUM(args->a0)) { case SAMA5_SMC_SIP_SFR_SET_USB_SUSPEND: atmel_sfr_set_usb_suspend(args->a1); args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; break; case SAMA5_SMC_SIP_SET_SUSPEND_MODE: return at91_pm_set_suspend_mode(args); case SAMA5_SMC_SIP_GET_SUSPEND_MODE: return at91_pm_get_suspend_mode(args); case SAMA5_SMC_SIP_SCMI_CALL_ID: scmi_smt_fastcall_smc_entry(0); args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; break; default: return SM_HANDLER_PENDING_SMC; } return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) { uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); switch (smc_owner) { case OPTEE_SMC_OWNER_SIP: return sam_sip_handler((struct thread_smc_args *)nsec_r0); default: return SM_HANDLER_PENDING_SMC; } } optee_os-4.3.0/core/arch/arm/plat-sam/nsec-service/smc_ids.h000066400000000000000000000007471464416617300237010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Microchip */ #ifndef SMC_IDS_H #define SMC_IDS_H #include #include #define SAMA5_SMC_SIP_SCMI_CALL_ID 0x200 #define SAMA5_SMC_SIP_SFR_SET_USB_SUSPEND 0x300 #define SAMA5_SMC_SIP_SET_SUSPEND_MODE 0x400 #define SAMA5_SMC_SIP_GET_SUSPEND_MODE 0x401 /* SAMA5 SMC return codes */ #define SAMA5_SMC_SIP_RETURN_SUCCESS 0x0 #define SAMA5_SMC_SIP_RETURN_EINVAL 0x1 #endif /* SMC_IDS_H */ optee_os-4.3.0/core/arch/arm/plat-sam/nsec-service/sub.mk000066400000000000000000000000671464416617300232240ustar00rootroot00000000000000global-incdirs-y += . srcs-y += sm_platform_handler.c optee_os-4.3.0/core/arch/arm/plat-sam/platform_config.h000066400000000000000000000071621464416617300230410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017 Timesys Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #if defined(PLATFORM_FLAVOR_sama7g54_ek) #include #else #include #endif #define STACK_ALIGNMENT 64 #ifdef CFG_WITH_PAGER #error "Pager not supported for platform sama5d2" #endif #ifdef CFG_WITH_LPAE #error "LPAE not supported" #endif #if defined(PLATFORM_FLAVOR_sama7g54_ek) #define CONSOLE_UART_BASE (FLEXCOM3_BASE_ADDRESS + 0x200) #define SFR_BASE SFR_BASE_ADDRESS #define AT91C_BASE_TC0 TC0_BASE_ADDRESS #define AT91C_ID_TC0 ID_TC0_CHANNEL0 #define AT91C_ID_TC1 ID_TC1_CHANNEL0 #define AT91C_ID_SYS ID_RSTC #define AT91C_ID_PIOA ID_PIOA #define AT91C_ID_PIOB ID_PIOB #define AT91C_ID_PIOC ID_PIOC #define AT91C_ID_PIOD ID_PIOD #define AT91C_ID_WDT ID_DWDT_SW #define AT91C_ID_TRNG ID_TRNG #define AT91C_ID_SECUMOD ID_SECUMOD #define AT91C_ID_SFR ID_SFR #define AT91C_ID_SFRBU ID_SFRBU #else #if defined(PLATFORM_FLAVOR_sama5d27_wlsom1_ek) #define CONSOLE_UART_BASE AT91C_BASE_UART0 #else #define CONSOLE_UART_BASE AT91C_BASE_UART1 #endif #define PL310_BASE (AT91C_BASE_L2CC) #define SFR_BASE (AT91C_BASE_SFR) #endif /* * PL310 Auxiliary Control Register * * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockdown cache lines (bit26=1) * Round robin replacement policy (bit25=1) * Force write allocated (default) * Treats shared accesses (bit22=0, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * Platform flavor specific way config: * - 16kb way size (bit19:17=3b001) * Store buffer device limitation disabled (bit11=0) * Cacheable accesses have high prio (bit10=0) */ #define PL310_AUX_CTRL_INIT 0x3E020000 /* * PL310 Prefetch Control Register * * Double linefill enabled (bit30=1) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop enabled (bit24=1) * Incr double linefill enable (bit23=1) * Prefetch offset = 1 (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x71800001 /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-sam/platform_sama5d2.c000066400000000000000000000455631464416617300230320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Timesys Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MATRIX_AXIMX 1 #define MATRIX_H64MX 2 #define MATRIX_H32MX 3 static struct matrix matrixes[] = { { .matrix = MATRIX_H64MX, .p = { .pa = AT91C_BASE_MATRIX64 } }, { .matrix = MATRIX_H32MX, .p = { .pa = AT91C_BASE_MATRIX32, } } }; static struct peri_security peri_security_array[] = { { .peri_id = AT91C_ID_PMC, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_PMC, }, { .peri_id = AT91C_ID_ARM, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_PIT, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_PITC, }, { .peri_id = AT91C_ID_WDT, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_WDT, }, { .peri_id = AT91C_ID_GMAC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_GMAC, }, { .peri_id = AT91C_ID_XDMAC0, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_XDMAC0, }, { .peri_id = AT91C_ID_XDMAC1, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_XDMAC1, }, { .peri_id = AT91C_ID_ICM, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_ICM, }, { .peri_id = AT91C_ID_AES, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_AES, }, { .peri_id = AT91C_ID_AESB, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_AESB, }, { .peri_id = AT91C_ID_TDES, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_TDES, }, { .peri_id = AT91C_ID_SHA, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SHA, }, { .peri_id = AT91C_ID_MPDDRC, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_MPDDRC, }, { .peri_id = AT91C_ID_MATRIX1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_MATRIX32, }, { .peri_id = AT91C_ID_MATRIX0, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_MATRIX64, }, { .peri_id = AT91C_ID_SECUMOD, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_SECUMOD, }, { .peri_id = AT91C_ID_HSMC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_HSMC, }, { .peri_id = AT91C_ID_PIOA, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_PIOA, }, { .peri_id = AT91C_ID_FLEXCOM0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_FLEXCOM0, }, { .peri_id = AT91C_ID_FLEXCOM1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_FLEXCOM1, }, { .peri_id = AT91C_ID_FLEXCOM2, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_FLEXCOM2, }, { .peri_id = AT91C_ID_FLEXCOM3, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_FLEXCOM3, }, { .peri_id = AT91C_ID_FLEXCOM4, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_FLEXCOM4, }, { .peri_id = AT91C_ID_UART0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_UART0, }, { .peri_id = AT91C_ID_UART1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_UART1, }, { .peri_id = AT91C_ID_UART2, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_UART2, }, { .peri_id = AT91C_ID_UART3, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_UART3, }, { .peri_id = AT91C_ID_UART4, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_UART4, }, { .peri_id = AT91C_ID_TWI0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_TWI0, }, { .peri_id = AT91C_ID_TWI1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_TWI1, }, { .peri_id = AT91C_ID_SDMMC0, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SDHC0, }, { .peri_id = AT91C_ID_SDMMC1, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SDHC1, }, { .peri_id = AT91C_ID_SPI0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SPI0, }, { .peri_id = AT91C_ID_SPI1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SPI1, }, { .peri_id = AT91C_ID_TC0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_TC0, }, { .peri_id = AT91C_ID_TC1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_TC1, }, { .peri_id = AT91C_ID_PWM, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_PWMC, }, { .peri_id = AT91C_ID_ADC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_ADC, }, { .peri_id = AT91C_ID_UHPHS, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_UDPHS, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_UDPHS, }, { .peri_id = AT91C_ID_SSC0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SSC0, }, { .peri_id = AT91C_ID_SSC1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SSC1, }, { .peri_id = AT91C_ID_LCDC, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_LCDC, }, { .peri_id = AT91C_ID_ISI, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_HXISI, }, { .peri_id = AT91C_ID_TRNG, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_TRNG, }, { .peri_id = AT91C_ID_PDMIC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_PDMIC, }, { .peri_id = AT91C_ID_IRQ, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_NS, }, { .peri_id = AT91C_ID_SFC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SFC, }, { .peri_id = AT91C_ID_SECURAM, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_SECURAM, }, { .peri_id = AT91C_ID_QSPI0, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_QSPI0, }, { .peri_id = AT91C_ID_QSPI1, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_QSPI1, }, { .peri_id = AT91C_ID_I2SC0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_I2SC0, }, { .peri_id = AT91C_ID_I2SC1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_I2SC1, }, { .peri_id = AT91C_ID_CAN0_INT0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_CAN1_INT0, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_CLASSD, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_CLASSD, }, { .peri_id = AT91C_ID_SFR, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SFR, }, { .peri_id = AT91C_ID_SAIC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_SAIC, }, { .peri_id = AT91C_ID_AIC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_NS, .addr = AT91C_BASE_AIC, }, { .peri_id = AT91C_ID_L2CC, .matrix = MATRIX_H64MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_L2CC, }, { .peri_id = AT91C_ID_CAN0_INT1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_CAN1_INT1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_GMAC_Q1, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_GMAC_Q2, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_PIOB, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_PIOB, }, { .peri_id = AT91C_ID_PIOC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_PIOC, }, { .peri_id = AT91C_ID_PIOD, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_AS, .addr = AT91C_BASE_PIOD, }, { .peri_id = AT91C_ID_SDMMC0_TIMER, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_SDMMC1_TIMER, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, }, { .peri_id = AT91C_ID_SYS, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SYSC, }, { .peri_id = AT91C_ID_ACC, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_ACC, }, { .peri_id = AT91C_ID_RXLP, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_RXLP, }, { .peri_id = AT91C_ID_SFRBU, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_SFRBU, }, { .peri_id = AT91C_ID_CHIPID, .matrix = MATRIX_H32MX, .security_type = SECURITY_TYPE_PS, .addr = AT91C_BASE_CHIPID, }, }; static struct atmel_uart_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); void plat_console_init(void) { atmel_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); } register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX32, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, AT91C_BASE_MATRIX64, CORE_MMU_PGDIR_SIZE); struct peri_security *peri_security_get(unsigned int idx) { struct peri_security *p = NULL; if (idx < ARRAY_SIZE(peri_security_array)) p = &peri_security_array[idx]; return p; } struct matrix *matrix_get(unsigned int idx) { struct matrix *pmatrix = NULL; if (idx < ARRAY_SIZE(matrixes)) pmatrix = &matrixes[idx]; return pmatrix; } static void matrix_configure_slave_h64mx(void) { unsigned int ddr_port; unsigned int ssr_setting; unsigned int sasplit_setting; unsigned int srtop_setting; /* * 0: Bridge from H64MX to AXIMX * (Internal ROM, Crypto Library, PKCC RAM): Always Secured */ /* 1: H64MX Peripheral Bridge: SDMMC0, SDMMC1 Non-Secure */ srtop_setting = MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_128M) | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_128M); sasplit_setting = MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M) | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_128M); ssr_setting = (MATRIX_LANSECH_NS(1) | MATRIX_LANSECH_NS(2) | MATRIX_RDNSECH_NS(1) | MATRIX_RDNSECH_NS(2) | MATRIX_WRNSECH_NS(1) | MATRIX_WRNSECH_NS(2)); matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_PERI_BRIDGE, srtop_setting, sasplit_setting, ssr_setting); /* * Matrix DDR configuration is hardcoded here and is difficult to * generate at runtime. Since this configuration expect the secure * DRAM to be at start of RAM and 8M of size, enforce it here. */ COMPILE_TIME_ASSERT(CFG_TZDRAM_START == AT91C_BASE_DDRCS); COMPILE_TIME_ASSERT(CFG_TZDRAM_SIZE == 0x800000); /* 2 ~ 9 DDR2 Port1 ~ 7: Non-Secure, except op-tee tee/ta memory */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); sasplit_setting = (MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8M) | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M) | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_128M) | MATRIX_SASPLIT(3, MATRIX_SASPLIT_VALUE_128M)); ssr_setting = (MATRIX_LANSECH_S(0) | MATRIX_LANSECH_NS(1) | MATRIX_LANSECH_NS(2) | MATRIX_LANSECH_NS(3) | MATRIX_RDNSECH_S(0) | MATRIX_RDNSECH_NS(1) | MATRIX_RDNSECH_NS(2) | MATRIX_RDNSECH_NS(3) | MATRIX_WRNSECH_S(0) | MATRIX_WRNSECH_NS(1) | MATRIX_WRNSECH_NS(2) | MATRIX_WRNSECH_NS(3)); /* DDR port 0 not used from NWd */ for (ddr_port = 1; ddr_port < 8; ddr_port++) { matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_DDR2_PORT_0 + ddr_port, srtop_setting, sasplit_setting, ssr_setting); } /* * 10: Internal SRAM 128K: * - First 64K are reserved for suspend code in Secure World * - Last 64K are for Non-Secure world (used by CAN) */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SRTOP_VALUE_64K); ssr_setting = (MATRIX_LANSECH_S(0) | MATRIX_RDNSECH_S(0) | MATRIX_WRNSECH_S(0)); matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_INTERNAL_SRAM, srtop_setting, sasplit_setting, ssr_setting); /* 11: Internal SRAM 128K (Cache L2): Default */ /* 12: QSPI0: Normal world */ /* 13: QSPI1: Normal world */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M); ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_NS(0) | MATRIX_WRNSECH_NS(0); matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_QSPI0, srtop_setting, sasplit_setting, ssr_setting); matrix_configure_slave_security(matrix_base(MATRIX_H64MX), H64MX_SLAVE_QSPI1, srtop_setting, sasplit_setting, ssr_setting); /* 14: AESB: Default */ } static void matrix_configure_slave_h32mx(void) { unsigned int ssr_setting; unsigned int sasplit_setting; unsigned int srtop_setting; /* 0: Bridge from H32MX to H64MX: Not Secured */ /* 1: H32MX Peripheral Bridge 0: Not Secured */ /* 2: H32MX Peripheral Bridge 1: Not Secured */ /* * 3: External Bus Interface * EBI CS0 Memory(256M) ----> Slave Region 0, 1 * EBI CS1 Memory(256M) ----> Slave Region 2, 3 * EBI CS2 Memory(256M) ----> Slave Region 4, 5 * EBI CS3 Memory(128M) ----> Slave Region 6 * NFC Command Registers(128M) -->Slave Region 7 * NANDFlash(EBI CS3) --> Slave Region 6: Non-Secure */ srtop_setting = MATRIX_SRTOP(6, MATRIX_SRTOP_VALUE_128M); srtop_setting |= MATRIX_SRTOP(7, MATRIX_SRTOP_VALUE_128M); sasplit_setting = MATRIX_SASPLIT(6, MATRIX_SASPLIT_VALUE_128M); sasplit_setting |= MATRIX_SASPLIT(7, MATRIX_SASPLIT_VALUE_128M); ssr_setting = (MATRIX_LANSECH_NS(6) | MATRIX_RDNSECH_NS(6) | MATRIX_WRNSECH_NS(6)); ssr_setting |= (MATRIX_LANSECH_NS(7) | MATRIX_RDNSECH_NS(7) | MATRIX_WRNSECH_NS(7)); matrix_configure_slave_security(matrix_base(MATRIX_H32MX), H32MX_EXTERNAL_EBI, srtop_setting, sasplit_setting, ssr_setting); /* 4: NFC SRAM (4K): Non-Secure */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_8K); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8K); ssr_setting = (MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_NS(0) | MATRIX_WRNSECH_NS(0)); matrix_configure_slave_security(matrix_base(MATRIX_H32MX), H32MX_NFC_SRAM, srtop_setting, sasplit_setting, ssr_setting); /* 5: * USB Device High Speed Dual Port RAM (DPR): 1M * USB Host OHCI registers: 1M * USB Host EHCI registers: 1M */ srtop_setting = (MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) | MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_1M)); sasplit_setting = (MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_1M)); ssr_setting = (MATRIX_LANSECH_NS(0) | MATRIX_LANSECH_NS(1) | MATRIX_LANSECH_NS(2) | MATRIX_RDNSECH_NS(0) | MATRIX_RDNSECH_NS(1) | MATRIX_RDNSECH_NS(2) | MATRIX_WRNSECH_NS(0) | MATRIX_WRNSECH_NS(1) | MATRIX_WRNSECH_NS(2)); matrix_configure_slave_security(matrix_base(MATRIX_H32MX), H32MX_USB, srtop_setting, sasplit_setting, ssr_setting); } static unsigned int security_ps_peri_id[] = { AT91C_ID_PMC, AT91C_ID_ARM, AT91C_ID_PIT, AT91C_ID_WDT, AT91C_ID_GMAC, AT91C_ID_XDMAC0, AT91C_ID_XDMAC1, AT91C_ID_ICM, AT91C_ID_AES, AT91C_ID_AESB, AT91C_ID_TDES, AT91C_ID_SHA, AT91C_ID_MPDDRC, AT91C_ID_HSMC, AT91C_ID_FLEXCOM0, AT91C_ID_FLEXCOM1, AT91C_ID_FLEXCOM2, AT91C_ID_FLEXCOM3, AT91C_ID_FLEXCOM4, AT91C_ID_UART0, AT91C_ID_UART1, AT91C_ID_UART2, AT91C_ID_UART3, AT91C_ID_UART4, AT91C_ID_TWI0, AT91C_ID_TWI1, AT91C_ID_SDMMC0, AT91C_ID_SDMMC1, AT91C_ID_SPI0, AT91C_ID_SPI1, AT91C_ID_TC0, AT91C_ID_TC1, AT91C_ID_PWM, AT91C_ID_ADC, AT91C_ID_UHPHS, AT91C_ID_UDPHS, AT91C_ID_SSC0, AT91C_ID_SSC1, AT91C_ID_LCDC, AT91C_ID_ISI, AT91C_ID_TRNG, AT91C_ID_PDMIC, AT91C_ID_SFC, AT91C_ID_QSPI0, AT91C_ID_QSPI1, AT91C_ID_I2SC0, AT91C_ID_I2SC1, AT91C_ID_CAN0_INT0, AT91C_ID_CAN1_INT0, AT91C_ID_CLASSD, AT91C_ID_SFR, AT91C_ID_L2CC, AT91C_ID_CAN0_INT1, AT91C_ID_CAN1_INT1, AT91C_ID_GMAC_Q1, AT91C_ID_GMAC_Q2, AT91C_ID_SDMMC0_TIMER, AT91C_ID_SDMMC1_TIMER, AT91C_ID_SYS, AT91C_ID_ACC, AT91C_ID_RXLP, AT91C_ID_SFRBU, AT91C_ID_CHIPID, }; static int matrix_init(void) { matrix_write_protect_disable(matrix_base(MATRIX_H64MX)); matrix_write_protect_disable(matrix_base(MATRIX_H32MX)); matrix_configure_slave_h64mx(); matrix_configure_slave_h32mx(); return matrix_configure_periph_non_secure(security_ps_peri_id, ARRAY_SIZE(security_ps_peri_id)); } void plat_primary_init_early(void) { matrix_init(); } void boot_primary_init_intc(void) { if (atmel_saic_setup()) panic("Failed to init interrupts\n"); } optee_os-4.3.0/core/arch/arm/plat-sam/platform_sama7g5.c000066400000000000000000000500231464416617300230250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2024 Microchip Technology Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #define MATRIX_SAMA7G54 0 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, MATRIX_BASE_ADDRESS, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC_BASE_ADDRESS, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZPM_BASE_ADDRESS, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_INTERFACE_BASE, GICC_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_DISTRIBUTOR_BASE, GICD_SIZE); static struct matrix matrixes[] = { { .matrix = MATRIX_SAMA7G54, .p = { .pa = MATRIX_BASE_ADDRESS, }, }, }; static struct peri_security peri_security_array[] = { { .peri_id = ID_DWDT_SW, .security_type = SECURITY_TYPE_AS, .addr = DWDT_BASE_ADDRESS, }, { .peri_id = ID_DWDT_NSW, .security_type = SECURITY_TYPE_NS, .addr = DWDT_BASE_ADDRESS, }, { .peri_id = ID_DWDT_NSW_ALARM, .security_type = SECURITY_TYPE_AS, .addr = DWDT_BASE_ADDRESS, }, { .peri_id = ID_SCKC, .security_type = SECURITY_TYPE_AS, .addr = SCKC_BASE_ADDRESS, }, { .peri_id = ID_SHDWC, .security_type = SECURITY_TYPE_AS, .addr = SHDWC_BASE_ADDRESS, }, { .peri_id = ID_RSTC, .security_type = SECURITY_TYPE_AS, .addr = RSTC_BASE_ADDRESS, }, { .peri_id = ID_RTC, .security_type = SECURITY_TYPE_AS, .addr = RTC_BASE_ADDRESS, }, { .peri_id = ID_RTT, .security_type = SECURITY_TYPE_AS, .addr = RTT_BASE_ADDRESS, }, { .peri_id = ID_CHIPID, .security_type = SECURITY_TYPE_PS, .addr = CHIPID_BASE_ADDRESS, }, { .peri_id = ID_PMC, .security_type = SECURITY_TYPE_AS, .addr = PMC_BASE_ADDRESS, }, { .peri_id = ID_PIOA, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS, }, { .peri_id = ID_PIOB, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0x40, }, { .peri_id = ID_PIOC, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0x80, }, { .peri_id = ID_PIOD, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0xC0, }, { .peri_id = ID_PIOE, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0x100, }, { .peri_id = ID_SECUMOD, .security_type = SECURITY_TYPE_AS, .addr = SECUMOD_BASE_ADDRESS, }, { .peri_id = ID_SECURAM, .security_type = SECURITY_TYPE_AS, .addr = 0xE0000000, }, { .peri_id = ID_SFR, .security_type = SECURITY_TYPE_PS, .addr = SFR_BASE_ADDRESS, }, { .peri_id = ID_SFRBU, .security_type = SECURITY_TYPE_AS, .addr = SFRBU_BASE_ADDRESS, }, { .peri_id = ID_HSMC, .security_type = SECURITY_TYPE_PS, .addr = HSMC_BASE_ADDRESS, }, { .peri_id = ID_XDMAC0, .security_type = SECURITY_TYPE_PS, .addr = XDMAC0_BASE_ADDRESS, }, { .peri_id = ID_XDMAC1, .security_type = SECURITY_TYPE_PS, .addr = XDMAC1_BASE_ADDRESS, }, { .peri_id = ID_XDMAC2, .security_type = SECURITY_TYPE_PS, .addr = XDMAC2_BASE_ADDRESS, }, { .peri_id = ID_ACC, .security_type = SECURITY_TYPE_PS, .addr = ACC_BASE_ADDRESS, }, { .peri_id = ID_ADC, .security_type = SECURITY_TYPE_PS, .addr = ADC_BASE_ADDRESS, }, { .peri_id = ID_AES, .security_type = SECURITY_TYPE_PS, .addr = AES_BASE_ADDRESS, }, { .peri_id = ID_TZAESBASC, .security_type = SECURITY_TYPE_AS, .addr = TZAESBASC_BASE_ADDRESS, }, { .peri_id = ID_ASRC, .security_type = SECURITY_TYPE_PS, .addr = ASRC_BASE_ADDRESS, }, { .peri_id = ID_CPKCC, .security_type = SECURITY_TYPE_PS, .addr = CPKCC_BASE_ADDRESS, }, { .peri_id = ID_CSI, .security_type = SECURITY_TYPE_PS, .addr = CSI_BASE_ADDRESS, }, { .peri_id = ID_CSI2DC, .security_type = SECURITY_TYPE_PS, .addr = CSI2DC_BASE_ADDRESS, }, { .peri_id = ID_DDRPUBL, .security_type = SECURITY_TYPE_PS, .addr = DDRPUBL_BASE_ADDRESS, }, { .peri_id = ID_DDRUMCTL, .security_type = SECURITY_TYPE_PS, .addr = DDRUMCTL_BASE_ADDRESS, }, { .peri_id = ID_EIC, .security_type = SECURITY_TYPE_PS, .addr = EIC_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM0, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM0_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM1, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM1_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM2, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM2_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM3, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM3_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM4, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM4_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM5, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM5_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM6, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM6_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM7, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM7_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM8, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM8_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM9, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM9_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM10, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM10_BASE_ADDRESS, }, { .peri_id = ID_FLEXCOM11, .security_type = SECURITY_TYPE_PS, .addr = FLEXCOM11_BASE_ADDRESS, }, { .peri_id = ID_GMAC0, .security_type = SECURITY_TYPE_PS, .addr = GMAC0_BASE_ADDRESS, }, { .peri_id = ID_GMAC1, .security_type = SECURITY_TYPE_PS, .addr = GMAC1_BASE_ADDRESS, }, { .peri_id = ID_GMAC0_TSU, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_GMAC1_TSU, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_ICM, .security_type = SECURITY_TYPE_AS, .addr = ICM_BASE_ADDRESS, }, { .peri_id = ID_ISC, .security_type = SECURITY_TYPE_PS, .addr = ISC_BASE_ADDRESS, }, { .peri_id = ID_I2SMCC0, .security_type = SECURITY_TYPE_PS, .addr = I2SMCC0_BASE_ADDRESS, }, { .peri_id = ID_I2SMCC1, .security_type = SECURITY_TYPE_PS, .addr = I2SMCC1_BASE_ADDRESS, }, { .peri_id = ID_MATRIX, .security_type = SECURITY_TYPE_AS, .addr = MATRIX_BASE_ADDRESS, }, { .peri_id = ID_MCAN0, .security_type = SECURITY_TYPE_PS, .addr = MCAN0_BASE_ADDRESS, }, { .peri_id = ID_MCAN1, .security_type = SECURITY_TYPE_PS, .addr = MCAN1_BASE_ADDRESS, }, { .peri_id = ID_MCAN2, .security_type = SECURITY_TYPE_PS, .addr = MCAN2_BASE_ADDRESS, }, { .peri_id = ID_MCAN3, .security_type = SECURITY_TYPE_PS, .addr = MCAN3_BASE_ADDRESS, }, { .peri_id = ID_MCAN4, .security_type = SECURITY_TYPE_PS, .addr = MCAN4_BASE_ADDRESS, }, { .peri_id = ID_MCAN5, .security_type = SECURITY_TYPE_PS, .addr = MCAN5_BASE_ADDRESS, }, { .peri_id = ID_OTPC, .security_type = SECURITY_TYPE_PS, .addr = OTPC_BASE_ADDRESS, }, { .peri_id = ID_PDMC0, .security_type = SECURITY_TYPE_PS, .addr = PDMC0_BASE_ADDRESS, }, { .peri_id = ID_PDMC1, .security_type = SECURITY_TYPE_PS, .addr = PDMC1_BASE_ADDRESS, }, { .peri_id = ID_PIT64B0, .security_type = SECURITY_TYPE_PS, .addr = PIT64B0_BASE_ADDRESS, }, { .peri_id = ID_PIT64B1, .security_type = SECURITY_TYPE_PS, .addr = PIT64B1_BASE_ADDRESS, }, { .peri_id = ID_PIT64B2, .security_type = SECURITY_TYPE_PS, .addr = PIT64B2_BASE_ADDRESS, }, { .peri_id = ID_PIT64B3, .security_type = SECURITY_TYPE_PS, .addr = PIT64B3_BASE_ADDRESS, }, { .peri_id = ID_PIT64B4, .security_type = SECURITY_TYPE_PS, .addr = PIT64B4_BASE_ADDRESS, }, { .peri_id = ID_PIT64B5, .security_type = SECURITY_TYPE_PS, .addr = PIT64B5_BASE_ADDRESS, }, { .peri_id = ID_PWM, .security_type = SECURITY_TYPE_PS, .addr = PWM_BASE_ADDRESS, }, { .peri_id = ID_QSPI0, .security_type = SECURITY_TYPE_PS, .addr = QSPI0_BASE_ADDRESS, }, { .peri_id = ID_QSPI1, .security_type = SECURITY_TYPE_PS, .addr = QSPI1_BASE_ADDRESS, }, { .peri_id = ID_SDMMC0, .security_type = SECURITY_TYPE_PS, .addr = SDMMC0_BASE_ADDRESS, }, { .peri_id = ID_SDMMC1, .security_type = SECURITY_TYPE_PS, .addr = SDMMC1_BASE_ADDRESS, }, { .peri_id = ID_SDMMC2, .security_type = SECURITY_TYPE_PS, .addr = SDMMC2_BASE_ADDRESS, }, { .peri_id = ID_SHA, .security_type = SECURITY_TYPE_PS, .addr = SHA_BASE_ADDRESS, }, { .peri_id = ID_SPDIFRX, .security_type = SECURITY_TYPE_PS, .addr = SPDIFRX_BASE_ADDRESS, }, { .peri_id = ID_SPDIFTX, .security_type = SECURITY_TYPE_PS, .addr = SPDIFTX_BASE_ADDRESS, }, { .peri_id = ID_SSC0, .security_type = SECURITY_TYPE_PS, .addr = SSC0_BASE_ADDRESS, }, { .peri_id = ID_SSC1, .security_type = SECURITY_TYPE_PS, .addr = SSC1_BASE_ADDRESS, }, { .peri_id = ID_TC0_CHANNEL0, .security_type = SECURITY_TYPE_PS, .addr = TC0_BASE_ADDRESS, }, { .peri_id = ID_TC0_CHANNEL1, .security_type = SECURITY_TYPE_PS, .addr = TC0_BASE_ADDRESS + 0x40, }, { .peri_id = ID_TC0_CHANNEL2, .security_type = SECURITY_TYPE_PS, .addr = TC0_BASE_ADDRESS + 0x80, }, { .peri_id = ID_TC1_CHANNEL0, .security_type = SECURITY_TYPE_PS, .addr = TC1_BASE_ADDRESS, }, { .peri_id = ID_TC1_CHANNEL1, .security_type = SECURITY_TYPE_PS, .addr = TC1_BASE_ADDRESS + 0x40, }, { .peri_id = ID_TC1_CHANNEL2, .security_type = SECURITY_TYPE_PS, .addr = TC1_BASE_ADDRESS + 0x80, }, { .peri_id = ID_TCPCA, .security_type = SECURITY_TYPE_PS, .addr = TCPCA_BASE_ADDRESS, }, { .peri_id = ID_TCPCB, .security_type = SECURITY_TYPE_PS, .addr = TCPCB_BASE_ADDRESS, }, { .peri_id = ID_TDES, .security_type = SECURITY_TYPE_PS, .addr = TDES_BASE_ADDRESS, }, { .peri_id = ID_TRNG, .security_type = SECURITY_TYPE_PS, .addr = TRNG_BASE_ADDRESS, }, { .peri_id = ID_TZAESB_NS, .security_type = SECURITY_TYPE_PS, .addr = TZAESBNS_BASE_ADDRESS, }, { .peri_id = ID_TZAESB_NS_SINT, .security_type = SECURITY_TYPE_AS, .addr = TZAESBNS_BASE_ADDRESS,}, { .peri_id = ID_TZAESB_S, .security_type = SECURITY_TYPE_PS, .addr = TZAESBS_BASE_ADDRESS, }, { .peri_id = ID_TZAESB_S_SINT, .security_type = SECURITY_TYPE_AS, .addr = TZAESBS_BASE_ADDRESS, }, { .peri_id = ID_TZC, .security_type = SECURITY_TYPE_AS, .addr = TZC_BASE_ADDRESS, }, { .peri_id = ID_TZPM, .security_type = SECURITY_TYPE_PS, .addr = TZPM_BASE_ADDRESS, }, { .peri_id = ID_UDPHSA, .security_type = SECURITY_TYPE_PS, .addr = UDPHSA_BASE_ADDRESS, }, { .peri_id = ID_UDPHSB, .security_type = SECURITY_TYPE_PS, .addr = UDPHSB_BASE_ADDRESS, }, { .peri_id = ID_UHPHS, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_XDMAC0_SINT, .security_type = SECURITY_TYPE_PS, .addr = XDMAC0_BASE_ADDRESS, }, { .peri_id = ID_XDMAC1_SINT, .security_type = SECURITY_TYPE_PS, .addr = XDMAC1_BASE_ADDRESS, }, { .peri_id = ID_XDMAC2_SINT, .security_type = SECURITY_TYPE_PS, .addr = XDMAC2_BASE_ADDRESS, }, { .peri_id = ID_AES_SINT, .security_type = SECURITY_TYPE_PS, .addr = AES_BASE_ADDRESS, }, { .peri_id = ID_GMAC0_Q1, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_GMAC0_Q2, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_GMAC0_Q3, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_GMAC0_Q4, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_GMAC0_Q5, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_GMAC1_Q1, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_ICM_SINT, .security_type = SECURITY_TYPE_AS, .addr = ICM_BASE_ADDRESS, }, { .peri_id = ID_MCAN0_INT1, .security_type = SECURITY_TYPE_PS, .addr = MCAN0_BASE_ADDRESS, }, { .peri_id = ID_MCAN1_INT1, .security_type = SECURITY_TYPE_PS, .addr = MCAN1_BASE_ADDRESS, }, { .peri_id = ID_MCAN2_INT1, .security_type = SECURITY_TYPE_PS, .addr = MCAN2_BASE_ADDRESS, }, { .peri_id = ID_MCAN3_INT1, .security_type = SECURITY_TYPE_PS, .addr = MCAN3_BASE_ADDRESS, }, { .peri_id = ID_MCAN4_INT1, .security_type = SECURITY_TYPE_PS, .addr = MCAN4_BASE_ADDRESS, }, { .peri_id = ID_MCAN5_INT1, .security_type = SECURITY_TYPE_PS, .addr = MCAN5_BASE_ADDRESS, }, { .peri_id = ID_PIOA_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS, }, { .peri_id = ID_PIOB_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0x40, }, { .peri_id = ID_PIOC_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0x80, }, { .peri_id = ID_PIOD_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0xC0, }, { .peri_id = ID_PIOE_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIO_BASE_ADDRESS + 0x100, }, { .peri_id = ID_PIT64B0_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIT64B0_BASE_ADDRESS, }, { .peri_id = ID_PIT64B1_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIT64B1_BASE_ADDRESS, }, { .peri_id = ID_PIT64B2_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIT64B2_BASE_ADDRESS, }, { .peri_id = ID_PIT64B3_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIT64B3_BASE_ADDRESS, }, { .peri_id = ID_PIT64B4_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIT64B4_BASE_ADDRESS, }, { .peri_id = ID_PIT64B5_SINT, .security_type = SECURITY_TYPE_PS, .addr = PIT64B5_BASE_ADDRESS, }, { .peri_id = ID_SDMMC0_TIMER, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_SDMMC1_TIMER, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_SDMMC2_TIMER, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_SHA_SINT, .security_type = SECURITY_TYPE_PS, .addr = SHA_BASE_ADDRESS, }, { .peri_id = ID_TC0_SINT0, .security_type = SECURITY_TYPE_PS, .addr = TC0_BASE_ADDRESS, }, { .peri_id = ID_TC0_SINT1, .security_type = SECURITY_TYPE_PS, .addr = TC0_BASE_ADDRESS, }, { .peri_id = ID_TC0_SINT2, .security_type = SECURITY_TYPE_PS, .addr = TC0_BASE_ADDRESS, }, { .peri_id = ID_TC1_SINT0, .security_type = SECURITY_TYPE_PS, .addr = TC1_BASE_ADDRESS, }, { .peri_id = ID_TC1_SINT1, .security_type = SECURITY_TYPE_PS, .addr = TC1_BASE_ADDRESS, }, { .peri_id = ID_TC1_SINT2, .security_type = SECURITY_TYPE_PS, .addr = TC1_BASE_ADDRESS, }, { .peri_id = ID_TDES_SINT, .security_type = SECURITY_TYPE_PS, .addr = TDES_BASE_ADDRESS, }, { .peri_id = ID_TRNG_SINT, .security_type = SECURITY_TYPE_PS, .addr = TRNG_BASE_ADDRESS, }, { .peri_id = ID_EXT_IRQ0, .security_type = SECURITY_TYPE_PS, }, { .peri_id = ID_EXT_IRQ1, .security_type = SECURITY_TYPE_PS, }, }; static struct atmel_uart_data console_data; void plat_console_init(void) { atmel_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); } struct peri_security *peri_security_get(unsigned int idx) { struct peri_security *p = NULL; if (idx < ARRAY_SIZE(peri_security_array)) p = &peri_security_array[idx]; return p; } struct matrix *matrix_get(unsigned int idx) { struct matrix *p = NULL; if (idx < ARRAY_SIZE(matrixes)) p = &matrixes[idx]; return p; } static void matrix_configure_slave(void) { unsigned int sasplit_setting = 0; unsigned int srtop_setting = 0; unsigned int ssr_setting = 0; unsigned int base = 0; static_assert(CFG_TZDRAM_START == DDR_CS_ADDR); static_assert(CFG_TZDRAM_SIZE == 0x800000); base = matrix_base(MATRIX_SAMA7G54); /* 0: QSPI0: Normal world */ /* 1: QSPI1: Normal world */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M) | MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_128M); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M) | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M); ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_LANSECH_NS(1) | MATRIX_RDNSECH_NS(0) | MATRIX_RDNSECH_NS(1) | MATRIX_WRNSECH_NS(0) | MATRIX_WRNSECH_NS(1); matrix_configure_slave_security(base, 0, srtop_setting, sasplit_setting, ssr_setting); matrix_configure_slave_security(base, 1, srtop_setting, sasplit_setting, ssr_setting); /* 2: TZAESB: Default */ /* 3: UDDRC_P1: Non-Secure, except op-tee tee/ta memory */ /* * Matrix DDR configuration is hardcoded here and is difficult to * generate at runtime. Since this configuration expect the secure * DRAM to be at start of RAM and 8M of size, enforce it here. */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8M); ssr_setting = MATRIX_LANSECH_S(0) | MATRIX_RDNSECH_S(0) | MATRIX_WRNSECH_S(0); matrix_configure_slave_security(base, 3, srtop_setting, sasplit_setting, ssr_setting); /* 4: APB6: Default */ /* * 5: SRAM_P0 * 6: SRAM_P1 */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_64K); ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_RDNSECH_S(0) | MATRIX_WRNSECH_S(0); matrix_configure_slave_security(base, 5, srtop_setting, sasplit_setting, ssr_setting); matrix_configure_slave_security(base, 6, srtop_setting, sasplit_setting, ssr_setting); /* * 7: SMC * EBI_CS0 ----> Slave Region 0 * EBI_CS1 ----> Slave Region 1 * EBI_CS2 ----> Slave Region 2 * EBI_CS3 ----> Slave Region 3 * NFC_CMD ----> Slave Region 4 : Non-Secure */ srtop_setting = MATRIX_SRTOP(4, MATRIX_SRTOP_VALUE_128M); sasplit_setting = MATRIX_SASPLIT(4, MATRIX_SASPLIT_VALUE_128M); ssr_setting = MATRIX_LANSECH_NS(4) | MATRIX_RDNSECH_NS(4) | MATRIX_WRNSECH_NS(4); matrix_configure_slave_security(base, 7, srtop_setting, sasplit_setting, ssr_setting); /* * 8: NFC_RAM * Slave area below SASSPLIT boundary is configured as Not Secured */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_8K); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8K); ssr_setting = MATRIX_LANSECH_NS(0); matrix_configure_slave_security(base, 8, srtop_setting, sasplit_setting, ssr_setting); /* * 9: USB_RAM * Slave area below SASSPLIT boundary is configured as Not Secured */ srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) | MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) | MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_4K) | MATRIX_SRTOP(3, MATRIX_SRTOP_VALUE_4K); sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) | MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) | MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_4K) | MATRIX_SASPLIT(3, MATRIX_SASPLIT_VALUE_4K); ssr_setting = MATRIX_LANSECH_NS(0) | MATRIX_LANSECH_NS(1) | MATRIX_LANSECH_NS(2) | MATRIX_LANSECH_NS(3); matrix_configure_slave_security(base, 9, srtop_setting, sasplit_setting, ssr_setting); } static void matrix_init(void) { matrix_write_protect_disable(matrix_base(MATRIX_SAMA7G54)); matrix_configure_slave(); } static void tzc400_init(void) { struct tzc_region_config cfg = { }; unsigned int tzc_idx = 0; vaddr_t addr = 0; for (tzc_idx = 0; tzc_idx <= 1; tzc_idx++) { addr = TZC_BASE_ADDRESS + 0x1000 * tzc_idx; tzc_init(addr); if (tzc_idx) cfg.filters = BIT(0); else cfg.filters = GENMASK_32(3, 0); cfg.sec_attr = TZC_REGION_S_RDWR; cfg.base = 0x00000000; cfg.top = 0xffffffff; cfg.ns_device_access = BIT(16) | BIT(0); tzc_configure_region(0, &cfg); cfg.base = CFG_TZDRAM_START; cfg.top = cfg.base + CFG_TZDRAM_SIZE - 1; cfg.ns_device_access = 0; tzc_configure_region(1, &cfg); cfg.base += CFG_TZDRAM_SIZE; cfg.top = cfg.base - CFG_TZDRAM_SIZE + DDR_CS_SIZE - 1; cfg.ns_device_access = BIT(16) | BIT(0); tzc_configure_region(2, &cfg); } } static void tzpm_init(void) { struct peri_security *p = peri_security_array; unsigned int i = 0; vaddr_t addr = TZPM_BASE_ADDRESS; /* TZPM_PIDx register write is possible. */ io_write32(addr + 0x04, 0x12AC4B5D); for (i = 0; i < ARRAY_SIZE(peri_security_array); i++, p++) if (p->peri_id < 128 && p->security_type == SECURITY_TYPE_PS) io_setbits32(addr + 8 + 4 * (p->peri_id / 32), BIT(p->peri_id % 32)); } void plat_primary_init_early(void) { assert(!cpu_mmu_enabled()); matrix_init(); tzc400_init(); tzpm_init(); } void boot_primary_init_intc(void) { gic_init(GIC_INTERFACE_BASE, GIC_DISTRIBUTOR_BASE); } optee_os-4.3.0/core/arch/arm/plat-sam/pm/000077500000000000000000000000001464416617300201255ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-sam/pm/psci.c000066400000000000000000000036301464416617300212310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include int psci_system_suspend(uintptr_t entry, uint32_t context_id __unused, struct sm_nsec_ctx *nsec) { if (!atmel_pm_suspend_available()) return PSCI_RET_NOT_SUPPORTED; if (atmel_pm_suspend(entry, nsec)) return PSCI_RET_INTERNAL_FAILURE; return PSCI_RET_SUCCESS; } int psci_cpu_suspend(uint32_t power_state, uintptr_t entry __unused, uint32_t context_id __unused, struct sm_nsec_ctx *nsec __unused) { uint32_t type = 0; if (atmel_pm_suspend_available()) return PSCI_RET_NOT_SUPPORTED; type = (power_state & PSCI_POWER_STATE_TYPE_MASK) >> PSCI_POWER_STATE_TYPE_SHIFT; if (type != PSCI_POWER_STATE_TYPE_STANDBY) { DMSG("Power state %x not supported", type); return PSCI_RET_INVALID_PARAMETERS; } atmel_pm_cpu_idle(); return PSCI_RET_SUCCESS; } void __noreturn psci_system_off(void) { if (!atmel_shdwc_available()) panic(); atmel_shdwc_shutdown(); } void __noreturn psci_system_reset(void) { if (!atmel_rstc_available()) panic(); atmel_rstc_reset(); } int psci_features(uint32_t psci_fid) { switch (psci_fid) { case ARM_SMCCC_VERSION: case PSCI_PSCI_FEATURES: case PSCI_VERSION: return PSCI_RET_SUCCESS; case PSCI_SYSTEM_RESET: if (atmel_rstc_available()) return PSCI_RET_SUCCESS; return PSCI_RET_NOT_SUPPORTED; case PSCI_SYSTEM_OFF: if (atmel_shdwc_available()) return PSCI_RET_SUCCESS; return PSCI_RET_NOT_SUPPORTED; case PSCI_CPU_SUSPEND: case PSCI_SYSTEM_SUSPEND: if (atmel_pm_suspend_available()) return PSCI_RET_SUCCESS; return PSCI_RET_NOT_SUPPORTED; default: return PSCI_RET_NOT_SUPPORTED; } } uint32_t psci_version(void) { return PSCI_VERSION_1_0; } optee_os-4.3.0/core/arch/arm/plat-sam/pm/sub.mk000066400000000000000000000000411464416617300212420ustar00rootroot00000000000000srcs-$(CFG_PSCI_ARM32) += psci.c optee_os-4.3.0/core/arch/arm/plat-sam/sam_pl310.c000066400000000000000000000045541464416617300213640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Timesys Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); vaddr_t pl310_base(void) { static void *va; if (cpu_mmu_enabled()) { if (!va) va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, 1); return (vaddr_t)va; } return PL310_BASE; } void arm_cl2_config(vaddr_t pl310_base) { io_write32(pl310_base + PL310_CTRL, 0); io_write32(sam_sfr_base() + AT91_SFR_L2CC_HRAMC, 0x1); io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); io_write32(pl310_base + PL310_PREFETCH_CTRL, PL310_PREFETCH_CTRL_INIT); io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); /* invalidate all cache ways */ arm_cl2_invbyway(pl310_base); } void arm_cl2_enable(vaddr_t pl310_base) { /* Enable PL310 ctrl -> only set lsb bit */ io_write32(pl310_base + PL310_CTRL, 1); } optee_os-4.3.0/core/arch/arm/plat-sam/sam_sfr.c000066400000000000000000000025071464416617300213130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Timesys Corporation. * Copyright (C) 2021 Microchip * All rights reserved. */ #include #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, SFR_BASE, CORE_MMU_PGDIR_SIZE); vaddr_t sam_sfr_base(void) { static void *va; if (!cpu_mmu_enabled()) return SFR_BASE; if (!va) va = phys_to_virt(SFR_BASE, MEM_AREA_IO_SEC, 1); return (vaddr_t)va; } void atmel_sfr_set_usb_suspend(bool set) { if (set) io_setbits32(sam_sfr_base() + AT91_SFR_OHCIICR, AT91_OHCIICR_USB_SUSPEND); else io_clrbits32(sam_sfr_base() + AT91_SFR_OHCIICR, AT91_OHCIICR_USB_SUSPEND); } static TEE_Result atmel_sfr_probe(const void *fdt, int node, const void *compat_data __unused) { if (fdt_get_status(fdt, node) == DT_STATUS_OK_SEC) matrix_configure_periph_secure(AT91C_ID_SFR); return TEE_SUCCESS; } static const struct dt_device_match atmel_sfr_match_table[] = { { .compatible = "atmel,sama5d2-sfr" }, { } }; DEFINE_DT_DRIVER(atmel_sfr_dt_driver) = { .name = "atmel_sfr", .type = DT_DRIVER_NOTYPE, .match_table = atmel_sfr_match_table, .probe = atmel_sfr_probe, }; optee_os-4.3.0/core/arch/arm/plat-sam/sam_sfr.h000066400000000000000000000016311464416617300213150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Bootlin */ #ifndef SAM_SFR_H #define SAM_SFR_H #include #include /* OHCI INT Configuration Register */ #define AT91_SFR_OHCIICR 0x10 /* UTMI Clock Trimming Register */ #define AT91_SFR_UTMICKTRIM 0x30 /* Serial number 0 Register */ #define AT91_SFR_SN0 0x4c /* Serial number 1 Register */ #define AT91_SFR_SN1 0x50 /* AIC Interrupt Redirection Register */ #define AT91_SFR_AICREDIR 0x54 /* L2 cache RAM used as an internal SRAM */ #define AT91_SFR_L2CC_HRAMC 0x58 /* I2SC Register */ #define AT91_SFR_I2SCLKSEL 0x90 /* Field definitions */ #define AT91_UTMICKTRIM_FREQ GENMASK_32(1, 0) #define AT91_OHCIICR_USB_SUSPEND GENMASK_32(10, 8) #define AT91_SFR_AICREDIR_XOR_KEY 0xb6d81c4d #define AT91_SFR_AICREDIR_KEY_MASK GENMASK_32(31, 1) vaddr_t sam_sfr_base(void); void atmel_sfr_set_usb_suspend(bool set); #endif optee_os-4.3.0/core/arch/arm/plat-sam/sama5d2.h000066400000000000000000000256101464416617300211220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-Source-Code */ /* * Copyright (c) 2015, Atmel Corporation * Copyright (c) 2017, Timesys Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SAMA5D2_H #define SAMA5D2_H /* * Peripheral identifiers/interrupts. */ #define AT91C_ID_FIQ 0 /* FIQ Interrupt ID */ #define AT91C_ID_PMC 1 /* Power Management Controller */ #define AT91C_ID_ARM 2 /* Performance Monitor Unit */ #define AT91C_ID_PIT 3 /* Periodic Interval Timer Interrupt */ #define AT91C_ID_WDT 4 /* Watchdog Timer Interrupt */ #define AT91C_ID_GMAC 5 /* Ethernet MAC */ #define AT91C_ID_XDMAC0 6 /* DMA Controller 0 */ #define AT91C_ID_XDMAC1 7 /* DMA Controller 1 */ #define AT91C_ID_ICM 8 /* Integrity Check Monitor */ #define AT91C_ID_AES 9 /* Advanced Encryption Standard */ #define AT91C_ID_AESB 10 /* AES bridge */ #define AT91C_ID_TDES 11 /* Triple Data Encryption Standard */ #define AT91C_ID_SHA 12 /* SHA Signature */ #define AT91C_ID_MPDDRC 13 /* MPDDR Controller */ #define AT91C_ID_MATRIX1 14 /* H32MX, 32-bit AHB Matrix */ #define AT91C_ID_MATRIX0 15 /* H64MX, 64-bit AHB Matrix */ #define AT91C_ID_SECUMOD 16 /* Secure Module */ #define AT91C_ID_HSMC 17 /* Multi-bit ECC interrupt */ #define AT91C_ID_PIOA 18 /* Parallel I/O Controller A */ #define AT91C_ID_FLEXCOM0 19 /* FLEXCOM0 */ #define AT91C_ID_FLEXCOM1 20 /* FLEXCOM1 */ #define AT91C_ID_FLEXCOM2 21 /* FLEXCOM2 */ #define AT91C_ID_FLEXCOM3 22 /* FLEXCOM3 */ #define AT91C_ID_FLEXCOM4 23 /* FLEXCOM4 */ #define AT91C_ID_UART0 24 /* UART0 */ #define AT91C_ID_UART1 25 /* UART1 */ #define AT91C_ID_UART2 26 /* UART2 */ #define AT91C_ID_UART3 27 /* UART3 */ #define AT91C_ID_UART4 28 /* UART4 */ #define AT91C_ID_TWI0 29 /* Two-wire Interface 0 */ #define AT91C_ID_TWI1 30 /* Two-wire Interface 1 */ #define AT91C_ID_SDMMC0 31 /* SDMMC Controller 0 */ #define AT91C_ID_SDMMC1 32 /* SDMMC Controller 1 */ #define AT91C_ID_SPI0 33 /* Serial Peripheral Interface 0 */ #define AT91C_ID_SPI1 34 /* Serial Peripheral Interface 1 */ #define AT91C_ID_TC0 35 /* Timer Counter 0 (ch.0,1,2) */ #define AT91C_ID_TC1 36 /* Timer Counter 1 (ch.3,4,5) */ /* 37 */ #define AT91C_ID_PWM 38 /* PWM Controller0 (ch. 0,1,2,3) */ /* 39 */ #define AT91C_ID_ADC 40 /* Touch Screen ADC Controller */ #define AT91C_ID_UHPHS 41 /* USB Host High Speed */ #define AT91C_ID_UDPHS 42 /* USB Device High Speed */ #define AT91C_ID_SSC0 43 /* Serial Synchronous Controller 0 */ #define AT91C_ID_SSC1 44 /* Serial Synchronous Controller 1 */ #define AT91C_ID_LCDC 45 /* LCD Controller */ #define AT91C_ID_ISI 46 /* Image Sensor Interface */ #define AT91C_ID_TRNG 47 /* True Random Number Generator */ #define AT91C_ID_PDMIC 48 /* PDM Interface Controller */ #define AT91C_ID_IRQ 49 /* IRQ Interrupt ID */ #define AT91C_ID_SFC 50 /* Fuse Controller */ #define AT91C_ID_SECURAM 51 /* Secure RAM */ #define AT91C_ID_QSPI0 52 /* QSPI0 */ #define AT91C_ID_QSPI1 53 /* QSPI1 */ #define AT91C_ID_I2SC0 54 /* Inter-IC Sound Controller 0 */ #define AT91C_ID_I2SC1 55 /* Inter-IC Sound Controller 1 */ #define AT91C_ID_CAN0_INT0 56 /* MCAN 0 Interrupt0 */ #define AT91C_ID_CAN1_INT0 57 /* MCAN 1 Interrupt0 */ #define AT91C_ID_PTC 58 /* Peripheral Touch Controller */ #define AT91C_ID_CLASSD 59 /* Audio Class D Amplifier */ #define AT91C_ID_SFR 60 /* Special Function Register */ #define AT91C_ID_SAIC 61 /* Secured AIC */ #define AT91C_ID_AIC 62 /* Advanced Interrupt Controller */ #define AT91C_ID_L2CC 63 /* L2 Cache Controller */ #define AT91C_ID_CAN0_INT1 64 /* MCAN 0 Interrupt1 */ #define AT91C_ID_CAN1_INT1 65 /* MCAN 1 Interrupt1 */ #define AT91C_ID_GMAC_Q1 66 /* GMAC Queue 1 Interrupt */ #define AT91C_ID_GMAC_Q2 67 /* GMAC Queue 2 Interrupt */ #define AT91C_ID_PIOB 68 /* Parallel I/O Controller B */ #define AT91C_ID_PIOC 69 /* Parallel I/O Controller C */ #define AT91C_ID_PIOD 70 /* Parallel I/O Controller D */ #define AT91C_ID_SDMMC0_TIMER 71 /* SDMMC0 Timer */ #define AT91C_ID_SDMMC1_TIMER 72 /* SDMMC1 Timer */ /* 73 */ #define AT91C_ID_SYS 74 /* System Controller Interrupt */ #define AT91C_ID_ACC 75 /* Analog Comparator */ #define AT91C_ID_RXLP 76 /* UART Low-Power */ #define AT91C_ID_SFRBU 77 /* Special Function Register BackUp */ #define AT91C_ID_CHIPID 78 /* Chip ID */ #define AT91C_ID_COUNTS (AT91C_ID_CHIPID + 1) /* * User Peripherals physical base addresses. */ #define AT91C_BASE_LCDC 0xf0000000 #define AT91C_BASE_XDMAC1 0xf0004000 #define AT91C_BASE_HXISI 0xf0008000 #define AT91C_BASE_MPDDRC 0xf000c000 #define AT91C_BASE_XDMAC0 0xf0010000 #define AT91C_BASE_PMC 0xf0014000 #define AT91C_BASE_MATRIX64 0xf0018000 /* MATRIX0 */ #define AT91C_BASE_AESB 0xf001c000 #define AT91C_BASE_QSPI0 0xf0020000 #define AT91C_BASE_QSPI1 0xf0024000 #define AT91C_BASE_SHA 0xf0028000 #define AT91C_BASE_AES 0xf002c000 #define AT91C_BASE_SPI0 0xf8000000 #define AT91C_BASE_SSC0 0xf8004000 #define AT91C_BASE_GMAC 0xf8008000 #define AT91C_BASE_TC0 0xf800c000 #define AT91C_BASE_TC1 0xf8010000 #define AT91C_BASE_HSMC 0xf8014000 #define AT91C_BASE_PDMIC 0xf8018000 #define AT91C_BASE_UART0 0xf801c000 #define AT91C_BASE_UART1 0xf8020000 #define AT91C_BASE_UART2 0xf8024000 #define AT91C_BASE_TWI0 0xf8028000 #define AT91C_BASE_PWMC 0xf802c000 #define AT91C_BASE_SFR 0xf8030000 #define AT91C_BASE_FLEXCOM0 0xf8034000 #define AT91C_BASE_FLEXCOM1 0xf8038000 #define AT91C_BASE_SAIC 0xf803c000 #define AT91C_BASE_ICM 0xf8040000 #define AT91C_BASE_SECURAM 0xf8044000 #define AT91C_BASE_SYSC 0xf8048000 #define AT91C_BASE_ACC 0xf804a000 #define AT91C_BASE_RXLP 0xf8049000 #define AT91C_BASE_SFC 0xf804c000 #define AT91C_BASE_I2SC0 0xf8050000 #define AT91C_BASE_CAN0 0xf8054000 #define AT91C_BASE_SPI1 0xfc000000 #define AT91C_BASE_SSC1 0xfc004000 #define AT91C_BASE_UART3 0xfc008000 #define AT91C_BASE_UART4 0xfc00c000 #define AT91C_BASE_FLEXCOM2 0xfc010000 #define AT91C_BASE_FLEXCOM3 0xfc014000 #define AT91C_BASE_FLEXCOM4 0xfc018000 #define AT91C_BASE_TRNG 0xfc01c000 #define AT91C_BASE_AIC 0xfc020000 #define AT91C_BASE_TWI1 0xfc028000 #define AT91C_BASE_UDPHS 0xfc02c000 #define AT91C_BASE_ADC 0xfc030000 #define AT91C_BASE_PIOA 0xfc038000 #define AT91C_BASE_MATRIX32 0xfc03c000 /* MATRIX1 */ #define AT91C_BASE_SECUMOD 0xfc040000 #define AT91C_BASE_TDES 0xfc044000 #define AT91C_BASE_CLASSD 0xfc048000 #define AT91C_BASE_I2SC1 0xfc04c000 #define AT91C_BASE_CAN1 0xfc050000 #define AT91C_BASE_SFRBU 0xfc05c000 #define AT91C_BASE_CHIPID 0xfc069000 /* * Address Memory Space */ #define AT91C_BASE_INTERNAL_MEM 0x00000000 #define AT91C_BASE_CS0 0x10000000 #define AT91C_BASE_DDRCS 0x20000000 #define AT91C_BASE_DDRCS_AES 0x40000000 #define AT91C_BASE_CS1 0x60000000 #define AT91C_BASE_CS2 0x70000000 #define AT91C_BASE_CS3 0x80000000 #define AT91C_BASE_QSPI0_AES_MEM 0x90000000 #define AT91C_BASE_QSPI1_AES_MEM 0x98000000 #define AT91C_BASE_SDHC0 0xa0000000 #define AT91C_BASE_SDHC1 0xb0000000 #define AT91C_BASE_NFC_CMD_REG 0xc0000000 #define AT91C_BASE_QSPI0_MEM 0xd0000000 #define AT91C_BASE_QSPI1_MEM 0xd8000000 #define AT91C_BASE_PERIPH 0xf0000000 /* * Internal Memories */ #define AT91C_BASE_ROM 0x00000000 /* ROM */ #define AT91C_BASE_ECC_ROM 0x00060000 /* ECC ROM */ #define AT91C_BASE_NFC_SRAM 0x00100000 /* NFC SRAM */ #define AT91C_BASE_SRAM0 0x00200000 /* SRAM0 */ #define AT91C_BASE_SRAM1 0x00220000 /* SRAM1 */ #define AT91C_BASE_UDPHS_SRAM 0x00300000 /* UDPHS RAM */ #define AT91C_BASE_UHP_OHCI 0x00400000 /* UHP OHCI */ #define AT91C_BASE_UHP_EHCI 0x00500000 /* UHP EHCI */ #define AT91C_BASE_AXI_MATRIX 0x00600000 /* AXI Maxtrix */ #define AT91C_BASE_DAP 0x00700000 /* DAP */ #define AT91C_BASE_PTC 0x00800000 /* PTC */ #define AT91C_BASE_L2CC 0x00A00000 /* L2CC */ /* * Other misc defines */ #define AT91C_BASE_PMECC (AT91C_BASE_HSMC + 0x70) #define AT91C_BASE_PMERRLOC (AT91C_BASE_HSMC + 0x500) #define AT91_PMECC (AT91C_BASE_PMECC - AT91C_BASE_SYS) #define AT91_PMERRLOC (AT91C_BASE_PMERRLOC - AT91C_BASE_SYS) #define AT91C_BASE_PIOB (AT91C_BASE_PIOA + 0x40) #define AT91C_BASE_PIOC (AT91C_BASE_PIOB + 0x40) #define AT91C_BASE_PIOD (AT91C_BASE_PIOC + 0x40) /* SYSC spawns */ #define AT91C_BASE_RSTC AT91C_BASE_SYSC #define AT91C_BASE_SHDC (AT91C_BASE_SYSC + 0x10) #define AT91C_BASE_PITC (AT91C_BASE_SYSC + 0x30) #define AT91C_BASE_WDT (AT91C_BASE_SYSC + 0x40) #define AT91C_BASE_SCKCR (AT91C_BASE_SYSC + 0x50) #define AT91C_BASE_RTCC (AT91C_BASE_SYSC + 0xb0) #define ATMEL_BASE_SMC (AT91C_BASE_HSMC + 0x700) #define AT91C_NUM_PIO 4 #define AT91C_NUM_TWI 2 /* AICREDIR Unlock Key */ #define AICREDIR_KEY 0xB6D81C4D /* * Matrix Slaves ID */ /* MATRIX0(H64MX) Matrix Slaves */ /* Bridge from H64MX to AXIMX (Internal ROM, Cryto Library, PKCC RAM) */ #define H64MX_SLAVE_BRIDGE_TO_AXIMX 0 #define H64MX_SLAVE_PERI_BRIDGE 1 /* H64MX Peripheral Bridge */ #define H64MX_SLAVE_DDR2_PORT_0 2 /* DDR2 Port0-AESOTF */ #define H64MX_SLAVE_DDR2_PORT_1 3 /* DDR2 Port1 */ #define H64MX_SLAVE_DDR2_PORT_2 4 /* DDR2 Port2 */ #define H64MX_SLAVE_DDR2_PORT_3 5 /* DDR2 Port3 */ #define H64MX_SLAVE_DDR2_PORT_4 6 /* DDR2 Port4 */ #define H64MX_SLAVE_DDR2_PORT_5 7 /* DDR2 Port5 */ #define H64MX_SLAVE_DDR2_PORT_6 8 /* DDR2 Port6 */ #define H64MX_SLAVE_DDR2_PORT_7 9 /* DDR2 Port7 */ #define H64MX_SLAVE_INTERNAL_SRAM 10 /* Internal SRAM 128K */ #define H64MX_SLAVE_CACHE_L2 11 /* Internal SRAM 128K (L2) */ #define H64MX_SLAVE_QSPI0 12 /* QSPI0 */ #define H64MX_SLAVE_QSPI1 13 /* QSPI1 */ #define H64MX_SLAVE_AESB 14 /* AESB */ /* MATRIX1(H32MX) Matrix Slaves */ #define H32MX_BRIDGE_TO_H64MX 0 /* Bridge from H32MX to H64MX */ #define H32MX_PERI_BRIDGE_0 1 /* H32MX Peripheral Bridge 0 */ #define H32MX_PERI_BRIDGE_1 2 /* H32MX Peripheral Bridge 1 */ #define H32MX_EXTERNAL_EBI 3 /* External Bus Interface */ #define H32MX_NFC_CMD_REG 3 /* NFC command Register */ #define H32MX_NFC_SRAM 4 /* NFC SRAM */ #define H32MX_USB 5 #endif /* #ifndef SAMA5D2_H */ optee_os-4.3.0/core/arch/arm/plat-sam/sama7g5.h000066400000000000000000000453001464416617300211300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Header file for ATSAMA7G54 * * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries. */ #ifndef _SAMA7G54_H_ #define _SAMA7G54_H_ /* * SAMA7G54 definitions * This file defines all structures and symbols for SAMA7G54: * - registers and bitfields * - peripheral base address * - peripheral ID * - PIO definitions */ #define GIC_DISTRIBUTOR_BASE 0xE8C11000 /* Base for GIC distributor interface */ #define GIC_INTERFACE_BASE 0xE8C12000 /* Base address for GIC CPU interface */ #define GICC_SIZE 0x1000 #define GICD_SIZE 0x1000 /* ************************************************************************** */ /* PERIPHERAL ID DEFINITIONS FOR SAMA7G54 */ /* ************************************************************************** */ #define ID_DWDT_SW 0 /* Dual Watchdog Timer, Secure World (DWDT_SW) */ #define ID_DWDT_NSW 1 /* DWDT Non Secure World, interrupt (DWDT_NSW) */ #define ID_DWDT_NSW_ALARM 2 /* DWDT Non Secure World Alarm, interrupt */ #define ID_SCKC 4 /* Slow Clock Controller (SCKC) */ #define ID_SHDWC 5 /* SHutDoWn Controller (SHDWC) */ #define ID_RSTC 6 /* Reset Controller (RSTC) */ #define ID_RTC 7 /* Real-Time Clock (RTC) */ #define ID_RTT 8 /* Real-Time Timer (RTT) */ #define ID_CHIPID 9 /* Chip Identifier (CHIPID) */ #define ID_PMC 10 /* Power Management Controller (PMC) */ #define ID_PIOA 11 /* For PIO 0 to 31 (PIOA) */ #define ID_PIOB 12 /* For PIO 32 to 63, interrupt (PIOB) */ #define ID_PIOC 13 /* For PIO 64 to 95, interrupt (PIOC) */ #define ID_PIOD 14 /* For PIO 96 to 127, interrupt (PIOD) */ #define ID_PIOE 15 /* For PIO 128 to 136, interrupt (PIOE) */ #define ID_SECUMOD 17 /* Security Module (SECUMOD) */ #define ID_SECURAM 18 /* Secret RAM (SECURAM) */ #define ID_SFR 19 /* Special Function Register (SFR) */ #define ID_SFRBU 20 /* Special Function Register in BackUp zone */ #define ID_HSMC 21 /* Static Memory Controller - NAND (HSMC) */ #define ID_XDMAC0 22 /* DMA 0, mem to periph, 32 Channels (XDMAC0) */ #define ID_XDMAC1 23 /* DMA 1, mem to periph, 32 Channels (XDMAC1) */ #define ID_XDMAC2 24 /* DMA 2, mem to mem, 4 Channels (XDMAC2) */ #define ID_ACC 25 /* Analog Comparator Controller (ACC) */ #define ID_ADC 26 /* Analog-to-Digital Converter (ADC) */ #define ID_AES 27 /* Advanced Encryption Standard (AES) */ #define ID_TZAESBASC 28 /* TZ AES Bridge - Address Space Controlller */ #define ID_ASRC 30 /* Asynchronous Sample Rate Converter (ASRC) */ #define ID_CPKCC 32 /* Classic Public Key Cryptography Controller */ #define ID_CSI 33 /* CSI 2 between ISC and MIPI PHY (CSI) */ #define ID_CSI2DC 34 /* CSI to Demultiplexer Controller (CSI2DC) */ #define ID_DDRPUBL 35 /* DDR SDRAM PHY Utility Block "Lite" aka PUBL */ #define ID_DDRUMCTL 36 /* Universal DDR-SDRAM Memory Controller */ #define ID_EIC 37 /* External Interrupt Controller (EIC) */ #define ID_FLEXCOM0 38 /* Flexcom 0 (FLEXCOM0) */ #define ID_FLEXCOM1 39 /* Flexcom 1 (FLEXCOM1) */ #define ID_FLEXCOM2 40 /* Flexcom 2 (FLEXCOM2) */ #define ID_FLEXCOM3 41 /* Flexcom 3 (FLEXCOM3) */ #define ID_FLEXCOM4 42 /* Flexcom 4 (FLEXCOM4) */ #define ID_FLEXCOM5 43 /* Flexcom 5 (FLEXCOM5) */ #define ID_FLEXCOM6 44 /* Flexcom 6 (FLEXCOM6) */ #define ID_FLEXCOM7 45 /* Flexcom 7 (FLEXCOM7) */ #define ID_FLEXCOM8 46 /* Flexcom 8 (FLEXCOM8) */ #define ID_FLEXCOM9 47 /* Flexcom 9 (FLEXCOM9) */ #define ID_FLEXCOM10 48 /* Flexcom 10 (FLEXCOM10) */ #define ID_FLEXCOM11 49 /* Flexcom 11 (FLEXCOM11) */ #define ID_GMAC0 51 /* Gigabit Ethernet MAC (GMAC0) */ #define ID_GMAC1 52 /* Ethernet MAC (GMAC1) */ #define ID_GMAC0_TSU 53 /* GMAC - TSU Generic Clock - No Interrupt */ #define ID_GMAC1_TSU 54 /* EMAC - TSU Generic Clock - No Interrupt */ #define ID_ICM 55 /* Integrity Check Monitor (ICM) */ #define ID_ISC 56 /* Camera Interface (ISC) */ #define ID_I2SMCC0 57 /* Inter-IC Sound Controller 0 (I2SMCC0) */ #define ID_I2SMCC1 58 /* Inter-IC Sound Controller 1 (I2SMCC1) */ #define ID_MATRIX 60 /* HSS AHB Matrix (MATRIX) */ #define ID_MCAN0 61 /* Master CAN 0 (MCAN0) */ #define ID_MCAN1 62 /* Master CAN 1 (MCAN1) */ #define ID_MCAN2 63 /* Master CAN 2 (MCAN2) */ #define ID_MCAN3 64 /* Master CAN 3 (MCAN3) */ #define ID_MCAN4 65 /* Master CAN 4 (MCAN4) */ #define ID_MCAN5 66 /* Master CAN 5 (MCAN5) */ #define ID_OTPC 67 /* One Time Programmable memory Controller */ #define ID_PDMC0 68 /* Pulse Density Modulation Controller 0 */ #define ID_PDMC1 69 /* Pulse Density Modulation Controller 1 */ #define ID_PIT64B0 70 /* 64-bit Periodic Interval Timer 0 (PIT64B0) */ #define ID_PIT64B1 71 /* 64-bit Periodic Interval Timer 1 (PIT64B1) */ #define ID_PIT64B2 72 /* 64-bit Periodic Interval Timer 2 (PIT64B2) */ #define ID_PIT64B3 73 /* 64-bit Periodic Interval Timer 3 (PIT64B3) */ #define ID_PIT64B4 74 /* 64-bit Periodic Interval Timer 4 (PIT64B4) */ #define ID_PIT64B5 75 /* 64-bit Periodic Interval Timer 5 (PIT64B5) */ #define ID_PWM 77 /* Pulse Width Modulation (PWM) */ #define ID_QSPI0 78 /* Quad IO Serial Peripheral Interface 0 */ #define ID_QSPI1 79 /* Quad IO Serial Peripheral Interface 1 */ #define ID_SDMMC0 80 /* Ultra HS SD Host controller 0 (eMMC 5.1) */ #define ID_SDMMC1 81 /* Ultra HS SD Host controller 1 (eMMC 4.51) */ #define ID_SDMMC2 82 /* Ultra HS SD Host controller 2 (eMMC 4.51) */ #define ID_SHA 83 /* Secure Hash Algorithm (SHA) */ #define ID_SPDIFRX 84 /* Sony Philips Digital Interface RX (SPDIFRX) */ #define ID_SPDIFTX 85 /* Sony Philips Digital Interface TX (SPDIFTX) */ #define ID_SSC0 86 /* Synchronous Serial Interface 0 (SSC0) */ #define ID_SSC1 87 /* Synchronous Serial Interface 1 (SSC1) */ #define ID_TC0_CHANNEL0 88 /* 32-bit Timer Counter 0 Channel 0 */ #define ID_TC0_CHANNEL1 89 /* 32-bit Timer Counter 0 Channel 1 interrupt */ #define ID_TC0_CHANNEL2 90 /* 32-bit Timer Counter 0 Channel 2 interrupt */ #define ID_TC1_CHANNEL0 91 /* 32-bit Timer Counter 1 Channel 0 */ #define ID_TC1_CHANNEL1 92 /* 32-bit Timer Counter 1 Channel 1 interrupt */ #define ID_TC1_CHANNEL2 93 /* 32-bit Timer Counter 1 Channel 2 interrupt */ #define ID_TCPCA 94 /* USB Type-C Port Controller A (TCPCA) */ #define ID_TCPCB 95 /* USB Type-C Port Controller B (TCPCB) */ #define ID_TDES 96 /* Triple Data Encryption System (TDES) */ #define ID_TRNG 97 /* True Random Number Generator (TRNG) */ #define ID_TZAESB_NS 98 /* TZAESB Non-Secure (Clocks & Interrupt) */ #define ID_TZAESB_NS_SINT 99 /* TZAESB Non-Secure (Interrupt only) */ #define ID_TZAESB_S 100 /* TZAESB Secure */ #define ID_TZAESB_S_SINT 101 /* TZAESB Secure (Interrupt only) */ #define ID_TZC 102 /* TrustZone Address Space Controller (TZC400) */ #define ID_TZPM 103 /* TrustZone Peripheral Manager (TZPM) */ #define ID_UDPHSA 104 /* USB Device High Speed A (UDPHSA) */ #define ID_UDPHSB 105 /* USB Device High Speed B (UDPHSB) */ #define ID_UHPHS 106 /* USB Host Controller High Speed (UHPHS) */ #define ID_XDMAC0_SINT 112 /* DMA 0, mem to periph, 32 CH, Secure INT */ #define ID_XDMAC1_SINT 113 /* DMA 1, mem to periph, 32 CH, Secure INT */ #define ID_XDMAC2_SINT 114 /* DMA 2, mem to mem, 4 Channels, Secure INT */ #define ID_AES_SINT 115 /* Advanced Encryption Standard, Secure INT */ #define ID_GMAC0_Q1 116 /* GMAC0 Queue 1 */ #define ID_GMAC0_Q2 117 /* GMAC0 Queue 2 */ #define ID_GMAC0_Q3 118 /* GMAC0 Queue 3 */ #define ID_GMAC0_Q4 119 /* GMAC0 Queue 4 */ #define ID_GMAC0_Q5 120 /* GMAC0 Queue 5 */ #define ID_GMAC1_Q1 121 /* GMAC1 Queue 1 */ #define ID_ICM_SINT 122 /* Integrity Check Monitor, Secure INTerrupt */ #define ID_MCAN0_INT1 123 /* MCAN0 interrupt1 (MCAN0_INT1) */ #define ID_MCAN1_INT1 124 /* MCAN1 interrupt1 (MCAN1_INT1) */ #define ID_MCAN2_INT1 125 /* MCAN2 interrupt1 (MCAN2_INT1) */ #define ID_MCAN3_INT1 126 /* MCAN3 interrupt1 (MCAN3_INT1) */ #define ID_MCAN4_INT1 127 /* MCAN4 interrupt1 (MCAN4_INT1) */ #define ID_MCAN5_INT1 128 /* MCAN5 interrupt1 (MCAN5_INT1) */ #define ID_PIOA_SINT 129 /* For PIO 0 to 31, Secure INTerrupt */ #define ID_PIOB_SINT 130 /* For PIO 32 to 63, Secure INTerrupt */ #define ID_PIOC_SINT 131 /* For PIO 64 to 95, Secure INTerrupt */ #define ID_PIOD_SINT 132 /* For PIO 96 to 127, Secure INTerrupt */ #define ID_PIOE_SINT 133 /* For PIO 128 to 136, Secure INTerrupt */ #define ID_PIT64B0_SINT 135 /* 64-bit PIT 0, Secure INTerrupt */ #define ID_PIT64B1_SINT 136 /* 64-bit PIT 1, Secure INTerrupt */ #define ID_PIT64B2_SINT 137 /* 64-bit PIT 2, Secure INTerrupt */ #define ID_PIT64B3_SINT 138 /* 64-bit PIT 3, Secure INTerrupt */ #define ID_PIT64B4_SINT 139 /* 64-bit PIT 4, Secure INTerrupt */ #define ID_PIT64B5_SINT 140 /* 64-bit PIT 5, Secure INTerrupt */ #define ID_SDMMC0_TIMER 141 /* SD Host controller 0 (eMMC 5.1) Timer int */ #define ID_SDMMC1_TIMER 142 /* SD Host controller 1 (eMMC 4.51) Timer int */ #define ID_SDMMC2_TIMER 143 /* SD Host controller 2 (eMMC 4.51) Timer int */ #define ID_SHA_SINT 144 /* Secure Hash Algorithm, Secure INTerrupt */ #define ID_TC0_SINT0 145 /* 32-bit TC 0 Channel 0, Secure INTerrupt */ #define ID_TC0_SINT1 146 /* 32-bit TC 0 Channel 1, Secure INTerrupt */ #define ID_TC0_SINT2 147 /* 32-bit TC 0 Channel 2 (TC0_SINT2) */ #define ID_TC1_SINT0 148 /* 32-bit TC 1 Channel 0, Secure INTerrupt */ #define ID_TC1_SINT1 149 /* 32-bit TC 1 Channel 1, Secure INTerrupt */ #define ID_TC1_SINT2 150 /* 32-bit TC 1 Channel 2, Secure INTerrupt */ #define ID_TDES_SINT 151 /* Triple Data Encryption System, Secure INT */ #define ID_TRNG_SINT 152 /* True Random Number Generator, Secure INT */ #define ID_EXT_IRQ0 153 /* External Interrupt ID0 (FIQ) (EXT_IRQ0) */ #define ID_EXT_IRQ1 154 /* External Interrupt ID1 (IRQ) (EXT_IRQ1) */ #define ID_PERIPH_MAX 154 /* Number of peripheral IDs */ /* ************************************************************************** */ /* BASE ADDRESS DEFINITIONS FOR SAMA7G54 */ /* ************************************************************************** */ #define ACC_BASE_ADDRESS 0xe1600000 #define ADC_BASE_ADDRESS 0xe1000000 #define AES_BASE_ADDRESS 0xe1810000 #define ASRC_BASE_ADDRESS 0xe1610000 #define BSC_BASE_ADDRESS 0xe001d054 #define CHIPID_BASE_ADDRESS 0xe0020000 #define CSI_BASE_ADDRESS 0xe1400000 #define CPKCC_BASE_ADDRESS 0xe000c000 #define CSI2DC_BASE_ADDRESS 0xe1404000 #define DDRPUBL_BASE_ADDRESS 0xe3804000 #define DWDT_BASE_ADDRESS 0xe001c000 #define EIC_BASE_ADDRESS 0xe1628000 #define FLEXCOM0_BASE_ADDRESS 0xe1818000 #define FLEXCOM1_BASE_ADDRESS 0xe181c000 #define FLEXCOM2_BASE_ADDRESS 0xe1820000 #define FLEXCOM3_BASE_ADDRESS 0xe1824000 #define FLEXCOM4_BASE_ADDRESS 0xe2018000 #define FLEXCOM5_BASE_ADDRESS 0xe201c000 #define FLEXCOM6_BASE_ADDRESS 0xe2020000 #define FLEXCOM7_BASE_ADDRESS 0xe2024000 #define FLEXCOM8_BASE_ADDRESS 0xe2818000 #define FLEXCOM9_BASE_ADDRESS 0xe281c000 #define FLEXCOM10_BASE_ADDRESS 0xe2820000 #define FLEXCOM11_BASE_ADDRESS 0xe2824000 #define GMAC0_BASE_ADDRESS 0xe2800000 #define GMAC1_BASE_ADDRESS 0xe2804000 #define GPBR_BASE_ADDRESS 0xe001d060 #define I2SMCC0_BASE_ADDRESS 0xe161c000 #define I2SMCC1_BASE_ADDRESS 0xe1620000 #define ICM_BASE_ADDRESS 0xe081c000 #define ISC_BASE_ADDRESS 0xe1408000 #define MATRIX_BASE_ADDRESS 0xe0804000 #define MCAN0_BASE_ADDRESS 0xe0828000 #define MCAN1_BASE_ADDRESS 0xe082c000 #define MCAN2_BASE_ADDRESS 0xe0830000 #define MCAN3_BASE_ADDRESS 0xe0834000 #define MCAN4_BASE_ADDRESS 0xe0838000 #define MCAN5_BASE_ADDRESS 0xe083c000 #define NICGPV_BASE_ADDRESS 0xe8b00000 #define OTPC_BASE_ADDRESS 0xe8c00000 #define PDMC0_BASE_ADDRESS 0xe1608000 #define PDMC1_BASE_ADDRESS 0xe160c000 #define PIO_BASE_ADDRESS 0xe0014000 #define PIT64B0_BASE_ADDRESS 0xe1800000 #define PIT64B1_BASE_ADDRESS 0xe1804000 #define PIT64B2_BASE_ADDRESS 0xe1808000 #define PIT64B3_BASE_ADDRESS 0xe2004000 #define PIT64B4_BASE_ADDRESS 0xe2008000 #define PIT64B5_BASE_ADDRESS 0xe2810000 #define PMC_BASE_ADDRESS 0xe0018000 #define PWM_BASE_ADDRESS 0xe1604000 #define QSPI0_BASE_ADDRESS 0xe080c000 #define QSPI1_BASE_ADDRESS 0xe0810000 #define RSTC_BASE_ADDRESS 0xe001d000 #define RTC_BASE_ADDRESS 0xe001d0a8 #define RTT_BASE_ADDRESS 0xe001d020 #define SCKC_BASE_ADDRESS 0xe001d050 #define SDMMC0_BASE_ADDRESS 0xe1204000 #define SDMMC1_BASE_ADDRESS 0xe1208000 #define SDMMC2_BASE_ADDRESS 0xe120c000 #define SECUMOD_BASE_ADDRESS 0xe0004000 #define SFR_BASE_ADDRESS 0xe1624000 #define SFRBU_BASE_ADDRESS 0xe0008000 #define SHA_BASE_ADDRESS 0xe1814000 #define SHDWC_BASE_ADDRESS 0xe001d010 #define HSMC_BASE_ADDRESS 0xe0808000 #define SPDIFRX_BASE_ADDRESS 0xe1614000 #define SPDIFTX_BASE_ADDRESS 0xe1618000 #define SSC0_BASE_ADDRESS 0xe180c000 #define SSC1_BASE_ADDRESS 0xe200c000 #define SYSCWP_BASE_ADDRESS 0xe001d0dc #define TC0_BASE_ADDRESS 0xe2814000 #define TC1_BASE_ADDRESS 0xe0800000 #define TCPCA_BASE_ADDRESS 0xe0840000 #define TCPCB_BASE_ADDRESS 0xe0844000 #define TDES_BASE_ADDRESS 0xe2014000 #define TRNG_BASE_ADDRESS 0xe2010000 #define TZAESBNS_BASE_ADDRESS 0xe0820000 #define TZAESBS_BASE_ADDRESS 0xe0824000 #define TZAESBASC_BASE_ADDRESS 0xe2000000 #define TZC_BASE_ADDRESS 0xe3000000 #define TZPM_BASE_ADDRESS 0xe0010000 #define DDRUMCTL_BASE_ADDRESS 0xe3800000 #define UDPHSA_BASE_ADDRESS 0xe0814000 #define UDPHSB_BASE_ADDRESS 0xe0818000 #define UHPHS_OHCI_BASE_ADDRESS 0x00400000 #define UHPHS_EHCI_BASE_ADDRESS 0x00500000 #define XDMAC0_BASE_ADDRESS 0xe2808000 #define XDMAC1_BASE_ADDRESS 0xe280c000 #define XDMAC2_BASE_ADDRESS 0xe1200000 /* ************************************************************************** */ /* MEMORY MAPPING DEFINITIONS FOR SAMA7G54 */ /* ************************************************************************** */ #define IROM_SIZE 0x00014000 #define ECC_ROM_SIZE 0x00018000 #define CPKCC_ROM_SIZE 0x00010000 #define CPKCC_RAM_SIZE 0x00001000 #define IRAM_SIZE 0x00020000 #define UDPHS_RAMA_SIZE 0x00100000 #define UDPHS_RAMB_SIZE 0x00100000 #define UHPHS_OHCI_SIZE 0x00001000 #define UHPHS_EHCI_SIZE 0x00100000 #define NFC_RAM_SIZE 0x00003000 #define NFC_SIZE 0x08000000 #define QSPIMEM0_SIZE 0x10000000 #define QSPIMEM1_SIZE 0x10000000 #define EBI_CS0_SIZE 0x08000000 #define EBI_CS1_SIZE 0x08000000 #define EBI_CS2_SIZE 0x08000000 #define EBI_CS3_SIZE 0x08000000 #define DDR_CS_SIZE 0x80000000 #define SECURAM_SIZE 0x00004000 #define SDMMC0_SIZE 0x00004000 #define SDMMC1_SIZE 0x00004000 #define SDMMC2_SIZE 0x00004000 #define APB_DBG_S_SIZE 0x00060000 #define APB_DBG_SIZE 0x00001000 #define NICGPV_SIZE 0x00100000 #define OTPC_SIZE 0x00001000 #define CSI2DC_META_SIZE 0x00002000 #define ARM_PERIPH_SIZE 0x00008000 #define PERIPHERALS_SIZE 0x10000000 #define IROM_ADDR 0x00000000 #define ECC_ROM_ADDR 0x00020000 #define CPKCC_ROM_ADDR 0x00040000 #define CPKCC_RAM_ADDR 0x00051000 #define IRAM_ADDR 0x00100000 #define UDPHS_RAMA_ADDR 0x00200000 #define UDPHS_RAMB_ADDR 0x00300000 #define UHPHS_OHCI_ADDR 0x00400000 #define UHPHS_EHCI_ADDR 0x00500000 #define NFC_RAM_ADDR 0x00600000 #define NFC_ADDR 0x10000000 #define QSPIMEM0_ADDR 0x20000000 #define QSPIMEM1_ADDR 0x30000000 #define EBI_CS0_ADDR 0x40000000 #define EBI_CS1_ADDR 0x48000000 #define EBI_CS2_ADDR 0x50000000 #define EBI_CS3_ADDR 0x58000000 #define DDR_CS_ADDR 0x60000000 #define SECURAM_ADDR 0xe0000000 #define SDMMC0_ADDR 0xe1204000 #define SDMMC1_ADDR 0xe1208000 #define SDMMC2_ADDR 0xe120c000 #define APB_DBG_S_ADDR 0xe8800000 #define APB_DBG_ADDR 0xe8900000 #define NICGPV_ADDR 0xe8b00000 #define OTPC_ADDR 0xe8c00000 #define CSI2DC_META_ADDR 0xe8c02000 #define ARM_PERIPH_ADDR 0xe8c10000 #define PERIPHERALS_ADDR 0xe0000000 /* ************************************************************************** */ /* DEVICE SIGNATURES FOR SAMA7G54 */ /* ************************************************************************** */ #define CHIP_JTAGID 0X05B4203F #define CHIP_CIDR 0X80162110 #define CHIP_EXID 0X00000000 #endif /* _SAMA7G54_H_ */ optee_os-4.3.0/core/arch/arm/plat-sam/scmi_server.c000066400000000000000000000525021464416617300222020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, STMicroelectronics * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include static_assert(SMT_BUF_SLOT_SIZE <= CFG_SCMI_SHMEM_SIZE); register_phys_mem(MEM_AREA_IO_NSEC, CFG_SCMI_SHMEM_START, CFG_SCMI_SHMEM_SIZE); struct channel_resources { struct scmi_msg_channel *channel; }; static const struct channel_resources scmi_channel[] = { [0] = { .channel = &(struct scmi_msg_channel){ .shm_addr = { .pa = CFG_SCMI_SHMEM_START }, .shm_size = SMT_BUF_SLOT_SIZE, }, }, }; static const struct channel_resources *find_resource(unsigned int channel_id) { assert(channel_id < ARRAY_SIZE(scmi_channel)); return scmi_channel + channel_id; } struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id) { const size_t max_id = ARRAY_SIZE(scmi_channel); unsigned int confined_id = confine_array_index(channel_id, max_id); if (channel_id >= max_id) return NULL; return find_resource(confined_id)->channel; } static const char vendor[] = "Microchip"; static const char sub_vendor[] = ""; const char *plat_scmi_vendor_name(void) { return vendor; } const char *plat_scmi_sub_vendor_name(void) { return sub_vendor; } /* Currently supporting only SCMI Base protocol */ static const uint8_t plat_protocol_list[] = { SCMI_PROTOCOL_ID_CLOCK, 0 /* Null termination */ }; size_t plat_scmi_protocol_count(void) { return ARRAY_SIZE(plat_protocol_list) - 1; } const uint8_t *plat_scmi_protocol_list(unsigned int channel_id __unused) { return plat_protocol_list; } struct sam_pmc_clk { unsigned int scmi_id; unsigned int pmc_type; unsigned int pmc_id; }; #ifdef CFG_SAMA7G5 static const struct sam_pmc_clk pmc_clks[] = { { .scmi_id = AT91_SCMI_CLK_CORE_MCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MCK }, { .scmi_id = AT91_SCMI_CLK_CORE_UTMI, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_UTMI }, { .scmi_id = AT91_SCMI_CLK_CORE_CPUPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_CPUPLL }, { .scmi_id = AT91_SCMI_CLK_CORE_MAIN, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MAIN }, { .scmi_id = AT91_SCMI_CLK_CORE_SYSPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_SYSPLL }, { .scmi_id = AT91_SCMI_CLK_CORE_AUDIOPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_AUDIOPMCPLL }, { .scmi_id = AT91_SCMI_CLK_CORE_MCK_PRES, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MCK_PRES }, { .scmi_id = AT91_SCMI_CLK_CORE_DDRPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_DDRPLL }, { .scmi_id = AT91_SCMI_CLK_CORE_IMGPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_IMGPLL }, { .scmi_id = AT91_SCMI_CLK_CORE_ETHPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_ETHPLL }, { .scmi_id = AT91_SCMI_CLK_UTMI1, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_UTMI1 }, { .scmi_id = AT91_SCMI_CLK_UTMI2, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_UTMI2 }, { .scmi_id = AT91_SCMI_CLK_UTMI3, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_UTMI3 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK0, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 8 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK1, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 9 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK2, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 10 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK3, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 11 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK4, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 12 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK5, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 13 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK6, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 14 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK7, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 15 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_ASRC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_ASRC }, { .scmi_id = AT91_SCMI_CLK_GCK_ASRC_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_ASRC }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CSI_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_CSI }, { .scmi_id = AT91_SCMI_CLK_GCK_CSI_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_CSI }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CSI2DC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_CSI2DC }, { .scmi_id = AT91_SCMI_CLK_PERIPH_MACB0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_GMAC0 }, { .scmi_id = AT91_SCMI_CLK_GCK_MACB0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_GMAC0 }, { .scmi_id = AT91_SCMI_CLK_GCK_MACB0_TSU, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_GMAC0_TSU }, { .scmi_id = AT91_SCMI_CLK_PERIPH_MACB1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_GMAC1 }, { .scmi_id = AT91_SCMI_CLK_GCK_MACB1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_GMAC1 }, { .scmi_id = AT91_SCMI_CLK_GCK_MACB1_TSU, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_GMAC1_TSU }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TDES_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_TDES }, { .scmi_id = AT91_SCMI_CLK_PERIPH_HSMC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_HSMC }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PIOA_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_PIOA }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX2_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM2 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX3_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM3 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX4_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM4 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX5_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM5 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX6_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM6 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX7_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM7 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX8_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM8 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX9_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM9 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX10_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM10 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX11_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_FLEXCOM11 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TCB0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_TC0_CHANNEL0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TCB1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_TC1_CHANNEL0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PWM_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_PWM }, { .scmi_id = AT91_SCMI_CLK_GCK_ADC_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_ADC }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UHPHS_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_UHPHS }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UDPHSA_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_UDPHSA }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UDPHSB_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_UDPHSB }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SSC0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SSC0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SSC1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SSC1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TRNG_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_TRNG }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PDMC0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_PDMC0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PDMC1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_PDMC1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SECURAM_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SECURAM }, { .scmi_id = AT91_SCMI_CLK_PERIPH_I2S0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_I2SMCC0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_I2S1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_I2SMCC1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_MCAN0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_MCAN1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN2_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_MCAN2 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN3_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_MCAN3 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN4_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_MCAN4 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN5_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_MCAN5 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_DMA0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_XDMAC0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_DMA1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_XDMAC1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_DMA2_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_XDMAC2 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SPDIFRX_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SPDIFRX }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SPDIFTX_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SPDIFTX }, { .scmi_id = AT91_SCMI_CLK_GCK_SPDIFRX_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_SPDIFRX }, { .scmi_id = AT91_SCMI_CLK_GCK_SPDIFTX_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_SPDIFTX }, { .scmi_id = AT91_SCMI_CLK_PERIPH_AES_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_AES }, { .scmi_id = AT91_SCMI_CLK_PERIPH_AESB_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_TZAESBASC }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SHA_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SHA }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SDMMC0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SDMMC1 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC2_HCLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_SDMMC2 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_ISC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_ISC }, { .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_QSPI0 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = ID_QSPI1 }, { .scmi_id = AT91_SCMI_CLK_GCK_QSPI0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_QSPI0 }, { .scmi_id = AT91_SCMI_CLK_GCK_QSPI1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_QSPI1 }, { .scmi_id = AT91_SCMI_CLK_GCK_SDMMC0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_SDMMC0 }, { .scmi_id = AT91_SCMI_CLK_GCK_SDMMC1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_SDMMC1 }, { .scmi_id = AT91_SCMI_CLK_GCK_SDMMC2_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_SDMMC2 }, { .scmi_id = AT91_SCMI_CLK_GCK_TCB0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_TC0_CHANNEL0 }, { .scmi_id = AT91_SCMI_CLK_GCK_TCB1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_TC1_CHANNEL0 }, { .scmi_id = AT91_SCMI_CLK_GCK_I2S0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_I2SMCC0 }, { .scmi_id = AT91_SCMI_CLK_GCK_I2S1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_I2SMCC1 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_MCAN0 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_MCAN1 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN2_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_MCAN2 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN3_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_MCAN3 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN4_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_MCAN4 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN5_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = ID_MCAN5 }, }; #else static const struct sam_pmc_clk pmc_clks[] = { { .scmi_id = AT91_SCMI_CLK_CORE_MCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MCK }, { .scmi_id = AT91_SCMI_CLK_CORE_UTMI, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_UTMI }, { .scmi_id = AT91_SCMI_CLK_CORE_MAIN, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MAIN }, { .scmi_id = AT91_SCMI_CLK_CORE_MCK2, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MCK2 }, { .scmi_id = AT91_SCMI_CLK_CORE_I2S0_MUX, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_I2S0_MUX }, { .scmi_id = AT91_SCMI_CLK_CORE_I2S1_MUX, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_I2S1_MUX }, { .scmi_id = AT91_SCMI_CLK_CORE_PLLACK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_PLLACK }, { .scmi_id = AT91_SCMI_CLK_CORE_AUDIOPLLCK, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_AUDIOPLLCK }, { .scmi_id = AT91_SCMI_CLK_CORE_MCK_PRES, .pmc_type = PMC_TYPE_CORE, .pmc_id = PMC_MCK_PRES }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_DDRCK, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 2 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_LCDCK, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 3 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_UHPCK, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 6 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_UDPCK, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 7 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK0, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 8 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK1, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 9 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_PCK2, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 10 }, { .scmi_id = AT91_SCMI_CLK_SYSTEM_ISCCK, .pmc_type = PMC_TYPE_SYSTEM, .pmc_id = 18 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_MACB0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 5 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TDES_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 11 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_MATRIX1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 14 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_HSMC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 17 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PIOA_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 18 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 19 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 20 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX2_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 21 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX3_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 22 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_FLX4_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 23 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UART0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 24 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UART1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 25 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UART2_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 26 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UART3_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 27 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UART4_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 28 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TWI0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 29 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TWI1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 30 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SPI0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 33 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SPI1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 34 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TCB0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 35 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TCB1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 36 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PWM_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 38 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_ADC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 40 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UHPHS_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 41 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_UDPHS_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 42 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SSC0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 43 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SSC1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 44 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_TRNG_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 47 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PDMIC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 48 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SECURAM_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 51 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_I2S0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 54 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_I2S1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 55 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 56 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CAN1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 57 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_PTC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 58 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_CLASSD_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 59 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_DMA0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 6 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_DMA1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 7 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_AES_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 9 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_AESB_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 10 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SHA_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 12 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_MPDDR_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 13 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_MATRIX0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 15 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 31 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 32 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_LCDC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 45 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_ISC_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 46 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI0_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 52 }, { .scmi_id = AT91_SCMI_CLK_PERIPH_QSPI1_CLK, .pmc_type = PMC_TYPE_PERIPHERAL, .pmc_id = 53 }, { .scmi_id = AT91_SCMI_CLK_GCK_SDMMC0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 31 }, { .scmi_id = AT91_SCMI_CLK_GCK_SDMMC1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 32 }, { .scmi_id = AT91_SCMI_CLK_GCK_TCB0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 35 }, { .scmi_id = AT91_SCMI_CLK_GCK_TCB1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 36 }, { .scmi_id = AT91_SCMI_CLK_GCK_PWM_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 38 }, { .scmi_id = AT91_SCMI_CLK_GCK_ISC_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 46 }, { .scmi_id = AT91_SCMI_CLK_GCK_PDMIC_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 48 }, { .scmi_id = AT91_SCMI_CLK_GCK_I2S0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 54 }, { .scmi_id = AT91_SCMI_CLK_GCK_I2S1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 55 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN0_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 56 }, { .scmi_id = AT91_SCMI_CLK_GCK_CAN1_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 57 }, { .scmi_id = AT91_SCMI_CLK_GCK_CLASSD_GCLK, .pmc_type = PMC_TYPE_GCK, .pmc_id = 59 }, { .scmi_id = AT91_SCMI_CLK_PROG_PROG0, .pmc_type = PMC_TYPE_PROGRAMMABLE, .pmc_id = 0 }, { .scmi_id = AT91_SCMI_CLK_PROG_PROG1, .pmc_type = PMC_TYPE_PROGRAMMABLE, .pmc_id = 1 }, { .scmi_id = AT91_SCMI_CLK_PROG_PROG2, .pmc_type = PMC_TYPE_PROGRAMMABLE, .pmc_id = 2 }, }; #endif static TEE_Result sam_init_scmi_clk(void) { unsigned int i = 0; struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; const struct sam_pmc_clk *pmc_clk = NULL; for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) { pmc_clk = &pmc_clks[i]; res = at91_pmc_clk_get(pmc_clk->pmc_type, pmc_clk->pmc_id, &clk); if (res) { EMSG("Failed to get PMC clock type %u, id %u", pmc_clk->pmc_type, pmc_clk->pmc_id); return res; } res = scmi_clk_add(clk, 0, pmc_clk->scmi_id); if (res) { EMSG("Failed to add PMC SCMI clock id %u", pmc_clk->scmi_id); return res; } } clk = at91_sckc_clk_get(); if (!clk) return TEE_ERROR_GENERIC; res = scmi_clk_add(clk, 0, AT91_SCMI_CLK_SCKC_SLOWCK_32K); if (res) { EMSG("Failed to add slow clock to SCMI clocks"); return res; } clk = at91_cpu_opp_clk_get(); if (clk) { res = scmi_clk_add(clk, 0, AT91_SCMI_CLK_CPU_OPP); if (res) { EMSG("Failed to add CPU OPP clock to SCMI clocks"); return res; } } return TEE_SUCCESS; } /* * Initialize platform SCMI resources */ static TEE_Result sam_init_scmi_server(void) { size_t i = 0; for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) { const struct channel_resources *res = scmi_channel + i; struct scmi_msg_channel *chan = res->channel; /* Enforce non-secure shm mapped as device memory */ chan->shm_addr.va = (vaddr_t)phys_to_virt(chan->shm_addr.pa, MEM_AREA_IO_NSEC, 1); assert(chan->shm_addr.va); scmi_smt_init_agent_channel(chan); } return sam_init_scmi_clk(); } driver_init_late(sam_init_scmi_server); optee_os-4.3.0/core/arch/arm/plat-sam/sub.mk000066400000000000000000000004431464416617300206340ustar00rootroot00000000000000global-incdirs-y += . srcs-y += freq.c sam_sfr.c srcs-$(CFG_SAMA5D2) += platform_sama5d2.c srcs-$(CFG_SAMA7G5) += platform_sama7g5.c srcs-$(CFG_AT91_MATRIX) += matrix.c srcs-$(CFG_PL310) += sam_pl310.c srcs-$(CFG_SCMI_MSG_DRIVERS) += scmi_server.c subdirs-y += pm subdirs-y += nsec-service optee_os-4.3.0/core/arch/arm/plat-sam/tz_matrix.h000066400000000000000000000114261464416617300217070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-Source-Code */ /* * Copyright (c) 2013, Atmel Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TZ_MATRIX_H #define TZ_MATRIX_H #define MATRIX_MCFG(n) (0x0000 + (n) * 4) /* Master Configuration Register */ #define MATRIX_SCFG(n) (0x0040 + (n) * 4) /* Slave Configuration Register */ #define MATRIX_PRAS(n) (0x0080 + (n) * 8) /* Priority Register A for Slave */ #define MATRIX_PRBS(n) (0x0084 + (n) * 8) /* Priority Register B for Slave */ #define MATRIX_MRCR 0x0100 /* Master Remap Control Register */ #define MATRIX_MEIER 0x0150 /* Master Error Interrupt Enable Register */ #define MATRIX_MEIDR 0x0154 /* Master Error Interrupt Disable Register */ #define MATRIX_MEIMR 0x0158 /* Master Error Interrupt Mask Register */ #define MATRIX_MESR 0x015c /* Master Error Status Register */ /* Master n Error Address Register */ #define MATRIX_MEAR(n) (0x0160 + (n) * 4) #define MATRIX_WPMR 0x01E4 /* Write Protect Mode Register */ #define MATRIX_WPSR 0x01E8 /* Write Protect Status Register */ /* Security Slave n Register */ #define MATRIX_SSR(n) (0x0200 + (n) * 4) /* Security Area Split Slave n Register */ #define MATRIX_SASSR(n) (0x0240 + (n) * 4) /* Security Region Top Slave n Register */ #define MATRIX_SRTSR(n) (0x0280 + (n) * 4) /* Security Peripheral Select n Register */ #define MATRIX_SPSELR(n) (0x02c0 + (n) * 4) /**************************************************************************/ /* Write Protect Mode Register (MATRIX_WPMR) */ #define MATRIX_WPMR_WPEN (1 << 0) /* Write Protect Enable */ #define MATRIX_WPMR_WPEN_DISABLE (0 << 0) #define MATRIX_WPMR_WPEN_ENABLE (1 << 0) #define MATRIX_WPMR_WPKEY (PASSWD << 8) /* Write Protect KEY */ #define MATRIX_WPMR_WPKEY_PASSWD (0x4D4154 << 8) /* Security Slave Registers (MATRIX_SSRx) */ #define MATRIX_LANSECH(n, bit) ((bit) << n) #define MATRIX_LANSECH_S(n) (0x00 << n) #define MATRIX_LANSECH_NS(n) (0x01 << n) #define MATRIX_RDNSECH(n, bit) ((bit) << (n + 8)) #define MATRIX_RDNSECH_S(n) (0x00 << (n + 8)) #define MATRIX_RDNSECH_NS(n) (0x01 << (n + 8)) #define MATRIX_WRNSECH(n, bit) ((bit) << (n + 16)) #define MATRIX_WRNSECH_S(n) (0x00 << (n + 16)) #define MATRIX_WRNSECH_NS(n) (0x01 << (n + 16)) /* Security Areas Split Slave Registers (MATRIX_SASSRx) */ #define MATRIX_SASPLIT(n, value) ((value) << (4 * n)) #define MATRIX_SASPLIT_VALUE_4K 0x00 #define MATRIX_SASPLIT_VALUE_8K 0x01 #define MATRIX_SASPLIT_VALUE_16K 0x02 #define MATRIX_SASPLIT_VALUE_32K 0x03 #define MATRIX_SASPLIT_VALUE_64K 0x04 #define MATRIX_SASPLIT_VALUE_128K 0x05 #define MATRIX_SASPLIT_VALUE_256K 0x06 #define MATRIX_SASPLIT_VALUE_512K 0x07 #define MATRIX_SASPLIT_VALUE_1M 0x08 #define MATRIX_SASPLIT_VALUE_2M 0x09 #define MATRIX_SASPLIT_VALUE_4M 0x0a #define MATRIX_SASPLIT_VALUE_8M 0x0b #define MATRIX_SASPLIT_VALUE_16M 0x0c #define MATRIX_SASPLIT_VALUE_32M 0x0d #define MATRIX_SASPLIT_VALUE_64M 0x0e #define MATRIX_SASPLIT_VALUE_128M 0x0f /* Security Region Top Slave Registers (MATRIX_SRTSRx) */ #define MATRIX_SRTOP(n, value) ((value) << (4 * n)) #define MATRIX_SRTOP_VALUE_4K 0x00 #define MATRIX_SRTOP_VALUE_8K 0x01 #define MATRIX_SRTOP_VALUE_16K 0x02 #define MATRIX_SRTOP_VALUE_32K 0x03 #define MATRIX_SRTOP_VALUE_64K 0x04 #define MATRIX_SRTOP_VALUE_128K 0x05 #define MATRIX_SRTOP_VALUE_256K 0x06 #define MATRIX_SRTOP_VALUE_512K 0x07 #define MATRIX_SRTOP_VALUE_1M 0x08 #define MATRIX_SRTOP_VALUE_2M 0x09 #define MATRIX_SRTOP_VALUE_4M 0x0a #define MATRIX_SRTOP_VALUE_8M 0x0b #define MATRIX_SRTOP_VALUE_16M 0x0c #define MATRIX_SRTOP_VALUE_32M 0x0d #define MATRIX_SRTOP_VALUE_64M 0x0e #define MATRIX_SRTOP_VALUE_128M 0x0f #endif /* #ifndef TZ_MATRIX_H */ optee_os-4.3.0/core/arch/arm/plat-sprd/000077500000000000000000000000001464416617300177015ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-sprd/conf.mk000066400000000000000000000005071464416617300211610ustar00rootroot00000000000000PLATFORM_FLAVOR ?= sc9860 include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,8) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_GIC,y) $(call force,CFG_SPRD_UART,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) # Overrides default in mk/config.mk with 128 kB CFG_CORE_HEAP_SIZE ?= 131072 optee_os-4.3.0/core/arch/arm/plat-sprd/console.c000066400000000000000000000034421464416617300215120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Spreadtrum Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include static struct sprd_uart_data console_data; void plat_console_init(void) { sprd_uart_init(&console_data, CONSOLE_UART_BASE); register_serial_console(&console_data.chip); } void console_putc(int ch) { struct serial_chip *cons = &console_data.chip; cons->ops->putc(cons, ch & 0xff); } optee_os-4.3.0/core/arch/arm/plat-sprd/main.c000066400000000000000000000037661464416617300210050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Spreadtrum Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_NSEC, ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(GIC_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } optee_os-4.3.0/core/arch/arm/plat-sprd/platform_config.h000066400000000000000000000053651464416617300232340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Spreadtrum Communications Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #ifdef ARM64 #ifdef CFG_WITH_PAGER #error "Pager not supported for ARM64" #endif #endif /*ARM64*/ #if defined(PLATFORM_FLAVOR_sc9860) #define GIC_BASE 0x12000000 #define UART0_BASE 0x70000000 #define UART1_BASE 0x70100000 #define UART2_BASE 0x70200000 #define UART3_BASE 0x70300000 #define CONSOLE_UART_BASE UART1_BASE #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE 0x20000000 #define TZDRAM_BASE 0x8f600000 #define TZDRAM_SIZE (0x02000000 - TEE_SHMEM_SIZE) #define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) #define TEE_SHMEM_SIZE 0x200000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #else #error "Unknown platform flavor" #endif #define TEE_RAM_VA_SIZE (1024 * 1024) #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else #define TEE_LOAD_ADDR TEE_RAM_START #endif /* * +------------------+ * | | TEE_RAM | * + TZDRAM +---------+ * | | TA_RAM | * +--------+---------+ */ #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE #define TEE_RAM_START TZDRAM_BASE #define TA_RAM_START ROUNDUP((TZDRAM_BASE + TEE_RAM_VA_SIZE), \ CORE_MMU_PGDIR_SIZE) #define TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - TEE_RAM_VA_SIZE), \ CORE_MMU_PGDIR_SIZE) #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-sprd/sub.mk000066400000000000000000000000731464416617300210230ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += console.c optee_os-4.3.0/core/arch/arm/plat-stm/000077500000000000000000000000001464416617300175345ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm/conf.mk000066400000000000000000000025001464416617300210070ustar00rootroot00000000000000PLATFORM_FLAVOR ?= b2260 include core/arch/arm/cpu/cortex-a9.mk $(call force,CFG_ARM32_core,y) $(call force,CFG_SECURE_TIME_SOURCE_REE,y) $(call force,CFG_PL310,y) $(call force,CFG_CACHE_API,y) $(call force,CFG_WITH_LPAE,n) $(call force,CFG_GIC,y) CFG_WITH_PAGER ?= n CFG_BOOT_SYNC_CPU ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_WITH_STATS ?= y CFG_WITH_SOFTWARE_PRNG ?= n CFG_STIH_UART ?= y CFG_ENABLE_SCTLR_RR ?= y ifeq ($(PLATFORM_FLAVOR),b2260) $(call force,CFG_TEE_CORE_NB_CORE,2) CFG_DDR_START ?= 0x40000000 CFG_DDR_SIZE ?= 0x40000000 CFG_STM_RSV_DRAM_STARTBYTES ?= 0 CFG_CORE_TZSRAM_EMUL_START ?= 0x7fe00000 CFG_DDR_TEETZ_RESERVED_START ?= 0x7e000000 CFG_DDR_TEETZ_RESERVED_SIZE ?= 0x01e00000 CFG_PL310_LOCKED ?= y else $(call force,CFG_TEE_CORE_NB_CORE,2) CFG_DDR_START ?= 0x40000000 CFG_DDR_SIZE ?= 0x80000000 CFG_STM_RSV_DRAM_STARTBYTES ?= 0x02000000 CFG_CORE_TZSRAM_EMUL_START ?= 0x94a00000 CFG_DDR_TEETZ_RESERVED_START ?= 0x93a00000 CFG_DDR_TEETZ_RESERVED_SIZE ?= 0x01000000 CFG_PL310_LOCKED ?= n endif CFG_SHMEM_SIZE ?= 0x00200000 CFG_TZDRAM_START ?= ($(CFG_DDR_TEETZ_RESERVED_START)) CFG_TZDRAM_SIZE ?= ($(CFG_DDR_TEETZ_RESERVED_SIZE) - $(CFG_SHMEM_SIZE)) CFG_TZSRAM_START ?= ($(CFG_CORE_TZSRAM_EMUL_START)) CFG_TZSRAM_SIZE ?= ($(CFG_CORE_TZSRAM_EMUL_SIZE)) CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) optee_os-4.3.0/core/arch/arm/plat-stm/main.c000066400000000000000000000063571464416617300206370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2016, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, CPU_IOMEM_BASE, CPU_IOMEM_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, UART_CONSOLE_BASE, STIH_ASC_REG_SIZE); #ifdef DRAM0_BASE register_ddr(DRAM0_BASE, DRAM0_SIZE); #endif #ifdef DRAM1_BASE register_ddr(DRAM1_BASE, DRAM1_SIZE); #endif static struct stih_asc_pd console_data; #if defined(PLATFORM_FLAVOR_b2260) static bool ns_resources_ready(void) { return true; } #else /* some nonsecure resource might not be ready (uart) */ static int boot_is_completed; static bool ns_resources_ready(void) { return !!boot_is_completed; } /* Overriding the default __weak tee_entry_std() */ TEE_Result tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) { boot_is_completed = 1; return __tee_entry_std(arg, num_params); } #endif void plat_console_init(void) { stih_asc_init(&console_data, UART_CONSOLE_BASE); } void console_putc(int ch) { if (ns_resources_ready()) { struct serial_chip *cons = &console_data.chip; if (ch == '\n') cons->ops->putc(cons, '\r'); cons->ops->putc(cons, ch); } } void console_flush(void) { if (ns_resources_ready()) { struct serial_chip *cons = &console_data.chip; if (cons->ops->flush) cons->ops->flush(cons); } } vaddr_t pl310_base(void) { static void *va; if (cpu_mmu_enabled()) { if (!va) va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, 1); return (vaddr_t)va; } return PL310_BASE; } void arm_cl2_config(vaddr_t pl310) { /* pl310 off */ io_write32(pl310 + PL310_CTRL, 0); /* config PL310 */ io_write32(pl310 + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); io_write32(pl310 + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); io_write32(pl310 + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); io_write32(pl310 + PL310_PREFETCH_CTRL, PL310_PREFETCH_CTRL_INIT); io_write32(pl310 + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); /* invalidate all pl310 cache ways */ arm_cl2_invbyway(pl310); } void plat_primary_init_early(void) { int i; assert(!cpu_mmu_enabled()); io_write32(SCU_BASE + SCU_SAC, SCU_SAC_INIT); io_write32(SCU_BASE + SCU_NSAC, SCU_NSAC_INIT); io_write32(SCU_BASE + SCU_FILT_EA, CPU_PORT_FILT_END); io_write32(SCU_BASE + SCU_FILT_SA, CPU_PORT_FILT_START); io_write32(SCU_BASE + SCU_CTRL, SCU_CTRL_INIT); io_write32(pl310_base() + PL310_ADDR_FILT_END, CPU_PORT_FILT_END); io_write32(pl310_base() + PL310_ADDR_FILT_START, CPU_PORT_FILT_START | PL310_CTRL_ENABLE_BIT); /* TODO: gic_init scan fails, pre-init all SPIs are nonsecure */ for (i = 0; i < (31 * 4); i += 4) io_write32(GIC_DIST_BASE + GIC_DIST_ISR1 + i, 0xFFFFFFFF); } void boot_primary_init_intc(void) { gic_init(GIC_CPU_BASE, GIC_DIST_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } optee_os-4.3.0/core/arch/arm/plat-stm/platform_config.h000066400000000000000000000135111464416617300230570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2016, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #include /* Below are platform/SoC settings specific to stm platform flavors */ #if defined(PLATFORM_FLAVOR_b2260) #define CPU_IOMEM_BASE 0x08760000 #define CPU_IOMEM_SIZE 0x000a0000 #define CPU_PORT_FILT_START 0x40000000 #define CPU_PORT_FILT_END 0xC0000000 #define STXHXXX_LPM_PERIPH_BASE 0x09700000 #define RNG_BASE 0x08A89000 #define RNG_SIZE 0x00001000 #define ASC_NUM 21 #define UART_CONSOLE_BASE ST_ASC21_REGS_BASE #elif defined(PLATFORM_FLAVOR_cannes) #define CPU_IOMEM_BASE 0x08760000 #define CPU_IOMEM_SIZE 0x000a0000 #define CPU_PORT_FILT_START 0x40000000 #define CPU_PORT_FILT_END 0xC0000000 #define STXHXXX_LPM_PERIPH_BASE 0x09400000 #define RNG_BASE 0x08A89000 #define RNG_SIZE 0x00001000 #define ASC_NUM 20 #define UART_CONSOLE_BASE ST_ASC20_REGS_BASE #else /* defined(PLATFORM_FLAVOR_xxx) */ #error "Unknown platform flavor" #endif /* defined(PLATFORM_FLAVOR_xxx) */ #define PL310_BASE (CPU_IOMEM_BASE + 0x2000) #define GIC_DIST_BASE (CPU_IOMEM_BASE + 0x1000) #define SCU_BASE (CPU_IOMEM_BASE + 0x0000) #define GIC_CPU_BASE (CPU_IOMEM_BASE + 0x0100) #define ST_ASC20_REGS_BASE (STXHXXX_LPM_PERIPH_BASE + 0x00130000) #define ST_ASC21_REGS_BASE (STXHXXX_LPM_PERIPH_BASE + 0x00131000) /* Below are settings common to stm platform flavors */ /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 32 /* * CP15 Secure ConTroL Register (SCTLR * * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) */ #define CPU_SCTLR_INIT 0x00004000 /* * CP15 Auxiliary ConTroL Register (ACTRL) * * - core always in full SMP (FW bit0=1, SMP bit6=1) * - L2 write full line of zero disabled (bit3=0) * (keep WFLZ low. Will be set once outer L2 is ready) */ #define CPU_ACTLR_INIT 0x00000041 /* * CP15 NonSecure Access Control Register (NSACR) * * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) * - Nsec can lockdown TLB (TL bit17=1) * - NSec cannot access PLE (PLE bit16=0) * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) */ #define CPU_NSACR_INIT 0x00020C00 /* * CP15 Power Control Register (PCR) * * - no change latency, enable clk gating */ #define CPU_PCR_INIT 0x00000001 /* * SCU Secure Access Control / NonSecure Access Control * * SAC: Both secure CPU access SCU (bit[3:0]). * NSAC: Both nonsec cpu access SCU (bit[3:0]), private timers (bit[7:4]) * and global timers (bit[11:8]). */ #if !defined(SCU_SAC_INIT) || !defined(SCU_NSAC_INIT) #define SCU_CPUS_MASK (SHIFT_U32(1, CFG_TEE_CORE_NB_CORE) - 1) #define SCU_SAC_INIT SCU_CPUS_MASK #define SCU_NSAC_INIT (SHIFT_U32(SCU_CPUS_MASK, SCU_NSAC_SCU_SHIFT) | \ SHIFT_U32(SCU_CPUS_MASK, SCU_NSAC_PTIMER_SHIFT) | \ SHIFT_U32(SCU_CPUS_MASK, SCU_NSAC_GTIMER_SHIFT)) #endif /* * PL310 TAG RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:1 - 2 cycle of read accesses latency * bit[2:0]:1 - 2 cycle of setup latency */ #ifndef PL310_TAG_RAM_CTRL_INIT #define PL310_TAG_RAM_CTRL_INIT 0x00000111 #endif /* * PL310 DATA RAM Control Register * * bit[10:8]:2 - 3 cycle of write accesses latency * bit[6:4]:2 - 3 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_DATA_RAM_CTRL_INIT #define PL310_DATA_RAM_CTRL_INIT 0x00000222 #endif /* * PL310 Auxiliary Control Register * * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=0) * Force write allocated (default) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * Platform fmavor specific way config: * - way size (bit19:17) * - way associciativity (bit16) * Store buffer device limitation enabled (bit11=1) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) disabled (bit0=0) */ #ifndef PL310_AUX_CTRL_INIT #define PL310_AUX_CTRL_INIT 0x3C480800 #endif /* * PL310 Prefetch Control Register * * Double linefill disabled (bit30=0) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop enabled (bit24=1) * Incr double linefill disable (bit23=0) * Prefetch offset = 7 (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x31000007 /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 /* * SCU Control Register : CTRL = 0x00000065 * - ic stanby enable=1 * - scu standby enable=1 * - scu enable=1 */ #define SCU_CTRL_INIT 0x00000065 /* * Register non-secure DDR chunks for dynamic shared memory: these are * DDR ranges that do not include OP-TEE secure memory. * Some Stm platforms may reserve beginning of the DDR for non REE memory. */ #ifdef CFG_DDR_START /* Carvout out secure RAM range (emulated SRAM is expected near DRAM) */ #if defined(CFG_WITH_PAGER) && defined(TZSRAM_BASE) #if TZSRAM_BASE >= CFG_DDR_START #define STM_SECDDR_BASE MIN_UNSAFE(TZSRAM_BASE, TZDRAM_BASE) #define STM_SECDDR_END MAX_UNSAFE(TZSRAM_BASE + TZSRAM_SIZE, \ TZDRAM_BASE + TZDRAM_SIZE) #endif /*TZSRAM_BASE >= CFG_DDR_START*/ #endif /*CFG_WITH_PAGER && TZSRAM_BASE*/ #ifndef STM_SECDDR_BASE #define STM_SECDDR_BASE TZDRAM_BASE #define STM_SECDDR_END (TZDRAM_BASE + TZDRAM_SIZE) #endif #define STM_SECDDR_SIZE (STM_SECDDR_END - STM_SECDDR_BASE) /* Register the DDR chunks that do not intersect the secure DDR single area */ #define DRAM0_BASE (CFG_DDR_START + CFG_STM_RSV_DRAM_STARTBYTES) #define DRAM0_SIZE (STM_SECDDR_BASE - DRAM0_BASE) #if (STM_SECDDR_END < 0x80000000ULL) #define DRAM1_BASE STM_SECDDR_END #define DRAM1_SIZE ((CFG_DDR_START - DRAM1_BASE) + CFG_DDR_SIZE) #endif #endif /*CFG_DDR_START*/ #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-stm/rng_support.c000066400000000000000000000063101464416617300222620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2016, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include "rng_support.h" /* Address of the register to read in the RNG IP */ #define RNG_VAL_OFFSET 0x24 #define RNG_STATUS_OFFSET 0x20 #define RNG_STATUS_ERR0 BIT32(0) #define RNG_STATUS_ERR1 BIT32(1) #define RNG_STATUS_FULL BIT32(5) static vaddr_t rng_base(void) { static void *va; if (cpu_mmu_enabled()) { if (!va) va = phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_SIZE); return (vaddr_t)va; } return RNG_BASE; } static inline int hwrng_waithost_fifo_full(void) { uint32_t status; do { status = io_read32(rng_base() + RNG_STATUS_OFFSET); } while (!(status & RNG_STATUS_FULL)); if (status & (RNG_STATUS_ERR0 | RNG_STATUS_ERR1)) return 1; return 0; } TEE_Result hw_get_random_bytes(void *buf, size_t len) { /* * Only the HW RNG IP is used to generate the value through the * HOST interface. * * @see the document rng_fspec_revG_120720.pdf for details * * - HOST FIFO size = 8x8b (64b) * - LSB (16b) of the RNG_VAL register allows to read 16b * - bit5 of the RNG_STATUS register allows to known if the HOST * FIFO is full or not. * - bit1,0 of the RNG_STATUS register allows to known if the * data are valid. * * Main principle: * For performance reason, a local SW fifo is used to store the * content of the HOST FIFO (max size = 8bytes). When a random * value is expected, this SW fifo is used to return a stored value. * When the local SW fifo is empty, it is filled with the HOST FIFO * according the following sequence: * * - wait HOST FIFO full * o Indicates that max 8-bytes (64b) are available * o This is mandatory to guarantee that a valid data is * available. No STATUS bit to indicate that the HOST FIFO * is empty is provided. * - check STATUS bits * - update the local SW fifo with the HOST FIFO * * This avoid to wait at each iteration that a valid random value is * available. _LOCAL_FIFO_SIZE indicates the size of the local SW fifo. * */ #define _LOCAL_FIFO_SIZE 8 /* min 2, 4, 6, max 8 */ static uint8_t lfifo[_LOCAL_FIFO_SIZE]; /* local fifo */ static int pos; static int nbcall; /* debug purpose - 0 is the initial value*/ volatile uint32_t tmpval[_LOCAL_FIFO_SIZE/2]; int i; uint8_t *buffer = buf; size_t buffer_pos = 0; nbcall++; while (buffer_pos < len) { /* Refill our FIFO */ if (pos == 0) { if (hwrng_waithost_fifo_full()) return TEE_ERROR_GENERIC; /* * Read the FIFO according to the number of * expected elements */ for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++) tmpval[i] = io_read32(rng_base() + RNG_VAL_OFFSET) & 0xFFFF; /* Update the local SW fifo for next request */ pos = 0; for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++) { lfifo[pos] = tmpval[i] & 0xFF; pos++; lfifo[pos] = (tmpval[i] >> 8) & 0xFF; pos++; } pos = 0; } buffer[buffer_pos++] = lfifo[pos++]; if (pos == _LOCAL_FIFO_SIZE) pos = 0; } return TEE_SUCCESS; } optee_os-4.3.0/core/arch/arm/plat-stm/sub.mk000066400000000000000000000001261464416617300206550ustar00rootroot00000000000000global-incdirs-y += . srcs-y += rng_support.c srcs-y += tz_a9init.S srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-stm/tz_a9init.S000066400000000000000000000027131464416617300215750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2016, STMicroelectronics International N.V. */ #include #include #include #include #include #include .section .text .balign 4 .code 32 /* * void arm_cl2_enable(vaddr_t pl310_base) - Memory Cache Level2 Enable Function * * If PL310 supports FZLW, enable also FZL in A9 core * * Use scratables registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. * TODO: to be moved to PL310 code (tz_svce_pl310.S ?) */ FUNC arm_cl2_enable , : /* Enable PL310 ctrl -> only set lsb bit */ mov r1, #0x1 str r1, [r0, #PL310_CTRL] /* if L2 FLZW enable, enable in L1 */ ldr r1, [r0, #PL310_AUX_CTRL] tst r1, #(1 << 0) /* test AUX_CTRL[FLZ] */ read_actlr r0 orrne r0, r0, #(1 << 3) /* enable ACTLR[FLZW] */ write_actlr r0 mov pc, lr END_FUNC arm_cl2_enable /* * Cortex A9 configuration early configuration * * Use scratables registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* CPSR.A can be modified in any security state. */ mov_imm r0, SCR_AW write_scr r0 mov_imm r0, CPU_SCTLR_INIT write_sctlr r0 mov_imm r0, CPU_ACTLR_INIT write_actlr r0 mov_imm r0, CPU_NSACR_INIT write_nsacr r0 mov_imm r0, CPU_PCR_INIT write_pcr r0 mov pc, lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-stm32mp1/000077500000000000000000000000001464416617300203175ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp1/boot_api.h000066400000000000000000000007741464416617300222740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (C) 2017-2018, STMicroelectronics */ #ifndef __BOOT_API_H__ #define __BOOT_API_H__ /* * Backup registers mapping */ /* Backup register #4: magic to request core1 boot up */ #define BCKR_CORE1_MAGIC_NUMBER 4 /* Value for BCKR_CORE1_MAGIC_NUMBER entry */ #define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xca7face1 /* Backup register #5: physical address of core1 entry at boot up */ #define BCKR_CORE1_BRANCH_ADDRESS 5 #endif /* __BOOT_API_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/conf.mk000066400000000000000000000320721464416617300216010ustar00rootroot00000000000000# 1GB and 512MB DDR targets do not locate secure DDR at the same place. flavor_dts_file-157A_DHCOR_AVENGER96 = stm32mp157a-dhcor-avenger96.dts flavor_dts_file-157A_DK1 = stm32mp157a-dk1.dts flavor_dts_file-157C_DHCOM_PDK2 = stm32mp157c-dhcom-pdk2.dts flavor_dts_file-157C_DK2 = stm32mp157c-dk2.dts flavor_dts_file-157C_ED1 = stm32mp157c-ed1.dts flavor_dts_file-157C_EV1 = stm32mp157c-ev1.dts flavor_dts_file-157A_DK1_SCMI = stm32mp157a-dk1-scmi.dts flavor_dts_file-157C_DK2_SCMI = stm32mp157c-dk2-scmi.dts flavor_dts_file-157C_ED1_SCMI = stm32mp157c-ed1-scmi.dts flavor_dts_file-157C_EV1_SCMI = stm32mp157c-ev1-scmi.dts flavor_dts_file-135F_DK = stm32mp135f-dk.dts flavorlist-cryp-512M = $(flavor_dts_file-157C_DK2) \ $(flavor_dts_file-157C_DK2_SCMI) \ $(flavor_dts_file-135F_DK) flavorlist-no_cryp-512M = $(flavor_dts_file-157A_DK1) \ $(flavor_dts_file-157A_DK1_SCMI) flavorlist-cryp-1G = $(flavor_dts_file-157C_DHCOM_PDK2) \ $(flavor_dts_file-157C_ED1) \ $(flavor_dts_file-157C_EV1) \ $(flavor_dts_file-157C_ED1_SCMI) \ $(flavor_dts_file-157C_EV1_SCMI) flavorlist-no_cryp-1G = $(flavor_dts_file-157A_DHCOR_AVENGER96) flavorlist-no_cryp = $(flavorlist-no_cryp-512M) \ $(flavorlist-no_cryp-1G) flavorlist-512M = $(flavorlist-cryp-512M) \ $(flavorlist-no_cryp-512M) flavorlist-1G = $(flavorlist-cryp-1G) \ $(flavorlist-no_cryp-1G) flavorlist-MP15-HUK-DT = $(flavor_dts_file-157A_DK1) \ $(flavor_dts_file-157C_DK2) \ $(flavor_dts_file-157C_ED1) \ $(flavor_dts_file-157C_EV1) \ $(flavor_dts_file-157A_DK1_SCMI) \ $(flavor_dts_file-157C_DK2_SCMI) \ $(flavor_dts_file-157C_ED1_SCMI) \ $(flavor_dts_file-157C_EV1_SCMI) flavorlist-MP15 = $(flavor_dts_file-157A_DHCOR_AVENGER96) \ $(flavor_dts_file-157A_DK1) \ $(flavor_dts_file-157C_DHCOM_PDK2) \ $(flavor_dts_file-157C_DK2) \ $(flavor_dts_file-157C_ED1) \ $(flavor_dts_file-157C_EV1) \ $(flavor_dts_file-157A_DK1_SCMI) \ $(flavor_dts_file-157C_DK2_SCMI) \ $(flavor_dts_file-157C_ED1_SCMI) \ $(flavor_dts_file-157C_EV1_SCMI) flavorlist-MP13 = $(flavor_dts_file-135F_DK) ifneq ($(PLATFORM_FLAVOR),) ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) $(error Invalid platform flavor $(PLATFORM_FLAVOR)) endif CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR)) endif CFG_EMBED_DTB_SOURCE_FILE ?= stm32mp157c-dk2.dts ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-no_cryp)),) $(call force,CFG_STM32_CRYP,n) $(call force,CFG_STM32_SAES,n) endif ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-no_rng)),) $(call force,CFG_HWRNG_PTA,n) $(call force,CFG_WITH_SOFTWARE_PRNG,y) endif ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP15-HUK-DT)),) CFG_STM32MP15_HUK ?= y CFG_STM32_HUK_FROM_DT ?= y endif ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP13)),) $(call force,CFG_STM32MP13,y) endif ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP15)),) $(call force,CFG_STM32MP15,y) endif # CFG_STM32MP1x switches are exclusive. # - CFG_STM32MP15 is enabled for STM32MP15x-* targets (default) # - CFG_STM32MP13 is enabled for STM32MP13x-* targets ifeq ($(CFG_STM32MP13),y) $(call force,CFG_STM32MP15,n) else $(call force,CFG_STM32MP15,y) $(call force,CFG_STM32MP13,n) endif ifeq ($(call cfg-one-enabled,CFG_STM32MP15 CFG_STM32MP13),n) $(error One of CFG_STM32MP15 CFG_STM32MP13 must be enabled) endif ifeq ($(call cfg-all-enabled,CFG_STM32MP15 CFG_STM32MP13),y) $(error Only one of CFG_STM32MP15 CFG_STM32MP13 must be enabled) endif include core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_DRIVERS_CLK,y) $(call force,CFG_DRIVERS_CLK_DT,y) $(call force,CFG_DRIVERS_GPIO,y) $(call force,CFG_DRIVERS_PINCTRL,y) $(call force,CFG_DRIVERS_REGULATOR,y) $(call force,CFG_GIC,y) $(call force,CFG_INIT_CNTVOFF,y) $(call force,CFG_PSCI_ARM32,y) $(call force,CFG_REGULATOR_FIXED,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_SM_PLATFORM_HANDLER,y) $(call force,CFG_STM32_SHARED_IO,y) ifeq ($(CFG_STM32MP13),y) $(call force,CFG_BOOT_SECONDARY_REQUEST,n) $(call force,CFG_CORE_ASYNC_NOTIF,y) $(call force,CFG_CORE_ASYNC_NOTIF_GIC_INTID,31) $(call force,CFG_CORE_RESERVED_SHM,n) $(call force,CFG_DRIVERS_CLK_FIXED,y) $(call force,CFG_SECONDARY_INIT_CNTFRQ,n) $(call force,CFG_STM32_GPIO,y) $(call force,CFG_STM32_VREFBUF,y) $(call force,CFG_STM32MP_CLK_CORE,y) $(call force,CFG_STM32MP1_SHARED_RESOURCES,n) $(call force,CFG_STM32MP1_RSTCTRL,y) $(call force,CFG_STM32MP13_CLK,y) $(call force,CFG_STM32MP13_REGULATOR_IOD,y) $(call force,CFG_TEE_CORE_NB_CORE,1) $(call force,CFG_WITH_NSEC_GPIOS,n) CFG_EXTERNAL_DT ?= n CFG_STM32MP_OPP_COUNT ?= 2 CFG_WITH_PAGER ?= n endif # CFG_STM32MP13 ifeq ($(CFG_STM32MP15),y) $(call force,CFG_BOOT_SECONDARY_REQUEST,y) $(call force,CFG_DRIVERS_CLK_FIXED,n) $(call force,CFG_HALT_CORES_ON_PANIC_SGI,15) $(call force,CFG_SECONDARY_INIT_CNTFRQ,y) $(call force,CFG_STM32MP1_SHARED_RESOURCES,y) $(call force,CFG_STM32_SAES,n) $(call force,CFG_STM32MP1_RSTCTRL,y) $(call force,CFG_STM32MP15_CLK,y) CFG_CORE_RESERVED_SHM ?= n CFG_HALT_CORES_ON_PANIC ?= y CFG_EXTERNAL_DT ?= y CFG_STM32_BSEC_SIP ?= y CFG_TEE_CORE_NB_CORE ?= 2 CFG_WITH_PAGER ?= y CFG_WITH_SOFTWARE_PRNG ?= y endif # CFG_STM32MP15 ifeq ($(CFG_WITH_PAGER),y) CFG_WITH_LPAE ?= n endif CFG_WITH_LPAE ?= y CFG_MMAP_REGIONS ?= 23 CFG_DTB_MAX_SIZE ?= (256 * 1024) CFG_CORE_ASLR ?= n CFG_STM32MP_REMOTEPROC ?= n CFG_DRIVERS_REMOTEPROC ?= $(CFG_STM32MP_REMOTEPROC) CFG_REMOTEPROC_PTA ?= $(CFG_STM32MP_REMOTEPROC) ifeq ($(CFG_REMOTEPROC_PTA),y) # Remoteproc early TA for coprocessor firmware management in boot stages CFG_IN_TREE_EARLY_TAS += remoteproc/80a4c275-0a47-4905-8285-1486a9771a08 # Embed public part of this key in OP-TEE OS RPROC_SIGN_KEY ?= keys/default.pem endif ifneq ($(CFG_WITH_LPAE),y) # Without LPAE, default TEE virtual address range is 1MB, we need at least 2MB. CFG_TEE_RAM_VA_SIZE ?= 0x00200000 endif ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-512M)),) CFG_TZDRAM_START ?= 0xde000000 CFG_DRAM_SIZE ?= 0x20000000 endif CFG_DRAM_BASE ?= 0xc0000000 CFG_DRAM_SIZE ?= 0x40000000 # CFG_STM32MP1_SCMI_SHM_BASE and CFG_STM32MP1_SCMI_SHM_SIZE define the # device memory mapped SRAM used for SCMI message transfers. # When CFG_STM32MP1_SCMI_SHM_BASE is set to 0, the platform uses OP-TEE # native shared memory for SCMI communication instead of SRAM. # # When CFG_STM32MP1_SCMI_SHM_SYSRAM is enabled, OP-TEE uses the # last 4KB page of SYSRAM as SCMI shared memory. The switch is default # disabled. CFG_STM32MP1_SCMI_SHM_SYSRAM ?= n ifeq ($(CFG_STM32MP1_SCMI_SHM_SYSRAM),y) $(call force,CFG_STM32MP1_SCMI_SHM_BASE,0x2ffff000) else CFG_STM32MP1_SCMI_SHM_BASE ?= 0 endif $(call force,CFG_STM32MP1_SCMI_SHM_SIZE,0x1000) ifeq ($(CFG_STM32MP15),y) CFG_TZDRAM_START ?= 0xfe000000 ifeq ($(CFG_CORE_RESERVED_SHM),y) CFG_TZDRAM_SIZE ?= 0x01e00000 else CFG_TZDRAM_SIZE ?= 0x02000000 endif CFG_TZSRAM_START ?= 0x2ffc0000 CFG_TZSRAM_SIZE ?= 0x0003f000 ifeq ($(CFG_CORE_RESERVED_SHM),y) CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE)) CFG_SHMEM_SIZE ?= ($(CFG_DRAM_BASE) + $(CFG_DRAM_SIZE) - $(CFG_SHMEM_START)) endif else CFG_TZDRAM_SIZE ?= 0x02000000 CFG_TZDRAM_START ?= ($(CFG_DRAM_BASE) + $(CFG_DRAM_SIZE) - $(CFG_TZDRAM_SIZE)) endif #CFG_STM32MP15 CFG_STM32_BSEC ?= y CFG_STM32_CRYP ?= y CFG_STM32_ETZPC ?= y CFG_STM32_GPIO ?= y CFG_STM32_I2C ?= y CFG_STM32_IWDG ?= y CFG_STM32_RNG ?= y CFG_STM32_RSTCTRL ?= y CFG_STM32_SAES ?= y CFG_STM32_TAMP ?= y CFG_STM32_UART ?= y CFG_STPMIC1 ?= y CFG_TZC400 ?= y CFG_DRIVERS_I2C ?= $(CFG_STM32_I2C) CFG_REGULATOR_GPIO ?= $(CFG_STM32_GPIO) CFG_WITH_SOFTWARE_PRNG ?= n ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) $(call force,CFG_STM32_RNG,y,Required by HW RNG when CFG_WITH_SOFTWARE_PRNG=n) endif ifeq ($(CFG_STPMIC1),y) $(call force,CFG_STM32_I2C,y) $(call force,CFG_STM32_GPIO,y) endif # If any crypto driver is enabled, enable the crypto-framework layer ifeq ($(call cfg-one-enabled, CFG_STM32_CRYP CFG_STM32_SAES),y) $(call force,CFG_STM32_CRYPTO_DRIVER,y) endif CFG_DRIVERS_RSTCTRL ?= $(CFG_STM32_RSTCTRL) $(eval $(call cfg-depends-all,CFG_STM32_RSTCTRL,CFG_DRIVERS_RSTCTRL)) CFG_WDT ?= $(CFG_STM32_IWDG) CFG_WDT_SM_HANDLER ?= $(CFG_WDT) CFG_WDT_SM_HANDLER_ID ?= 0xbc000000 # Platform specific configuration CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION ?= y # Default enable scmi-msg server if SCP-firmware SCMI server is disabled ifneq ($(CFG_SCMI_SCPFW),y) CFG_SCMI_MSG_DRIVERS ?= y endif # SiP/OEM service for non-secure world CFG_STM32_BSEC_SIP ?= n CFG_STM32MP1_SCMI_SIP ?= n ifeq ($(CFG_STM32MP1_SCMI_SIP),y) $(call force,CFG_SCMI_MSG_DRIVERS,y,Mandated by CFG_STM32MP1_SCMI_SIP) $(call force,CFG_SCMI_MSG_SMT,y,Mandated by CFG_STM32MP1_SCMI_SIP) $(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y,Mandated by CFG_STM32MP1_SCMI_SIP) endif # Enable BSEC PTA for fuses access management CFG_STM32_BSEC_PTA ?= y ifeq ($(CFG_STM32_BSEC_PTA),y) $(call force,CFG_STM32_BSEC,y,Mandated by CFG_BSEC_PTA) endif # Default enable SCMI PTA support CFG_SCMI_PTA ?= y ifeq ($(CFG_SCMI_PTA),y) ifneq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_MSG_DRIVERS,y,Mandated by CFG_SCMI_PTA) CFG_SCMI_MSG_SMT_THREAD_ENTRY ?= y CFG_SCMI_MSG_SHM_MSG ?= y CFG_SCMI_MSG_SMT ?= y endif # !CFG_SCMI_SCPFW endif # CFG_SCMI_PTA CFG_SCMI_SCPFW ?= n ifeq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_SCPFW_PRODUCT,stm32mp1) endif CFG_SCMI_MSG_DRIVERS ?= n ifeq ($(CFG_SCMI_MSG_DRIVERS),y) $(call force,CFG_SCMI_MSG_CLOCK,y) $(call force,CFG_SCMI_MSG_RESET_DOMAIN,y) CFG_SCMI_MSG_SHM_MSG ?= y CFG_SCMI_MSG_SMT ?= y CFG_SCMI_MSG_SMT_THREAD_ENTRY ?= y $(call force,CFG_SCMI_MSG_VOLTAGE_DOMAIN,y) endif ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) CFG_HWRNG_PTA ?= y endif ifeq ($(CFG_HWRNG_PTA),y) $(call force,CFG_STM32_RNG,y,Mandated by CFG_HWRNG_PTA) $(call force,CFG_WITH_SOFTWARE_PRNG,n,Mandated by CFG_HWRNG_PTA) $(call force,CFG_HWRNG_QUALITY,1024) endif # Provision enough threads to pass xtest ifneq (,$(filter y,$(CFG_SCMI_PTA) $(CFG_STM32MP1_SCMI_SIP))) ifeq ($(CFG_WITH_PAGER),y) CFG_NUM_THREADS ?= 3 else CFG_NUM_THREADS ?= 10 endif endif # Default enable some test facitilites CFG_ENABLE_EMBEDDED_TESTS ?= y CFG_WITH_STATS ?= y # Default enable software fallback on crypto drivers CFG_STM32_SAES_SW_FALLBACK ?= y # Enable OTP update with BSEC driver CFG_STM32_BSEC_WRITE ?= y # Default disable some support for pager memory size constraint ifeq ($(CFG_WITH_PAGER),y) CFG_TEE_CORE_DEBUG ?= n CFG_UNWIND ?= n CFG_LOCKDEP ?= n CFG_TA_BGET_TEST ?= n endif # Non-secure UART and GPIO/pinctrl for the output console CFG_WITH_NSEC_GPIOS ?= y CFG_WITH_NSEC_UARTS ?= y # UART instance used for early console (0 disables early console) CFG_STM32_EARLY_CONSOLE_UART ?= 4 # CFG_STM32MP15_HUK enables use of a HUK read from BSEC fuses. # Disable the HUK by default as it requires a product specific configuration. # # Configuration must provide OTP indices where HUK is loaded. # When CFG_STM32_HUK_FROM_DT is enabled, HUK OTP location is found in the DT. # When CFG_STM32_HUK_FROM_DT is disabled, configuration sets each HUK location. # Either with CFG_STM32MP15_HUK_OTP_BASE, in which case the 4 words are used, # Or with CFG_STM32MP15_HUK_BSEC_KEY_0/1/2/3 each locating one BSEC word. # # Configuration must provide the HUK generation scheme. The following switches # are exclusive and at least one must be eable when CFG_STM32MP15_HUK is enable. # CFG_STM32MP15_HUK_BSEC_KEY makes platform HUK to be the raw fuses content. # CFG_STM32MP15_HUK_BSEC_DERIVE_UID makes platform HUK to be the HUK fuses # content derived with the device UID fuses content. See derivation scheme # in stm32mp15_huk.c implementation. CFG_STM32MP15_HUK ?= n CFG_STM32_HUK_FROM_DT ?= n ifeq ($(CFG_STM32MP15_HUK),y) ifneq ($(CFG_STM32_HUK_FROM_DT),y) ifneq (,$(CFG_STM32MP15_HUK_OTP_BASE)) $(call force,CFG_STM32MP15_HUK_BSEC_KEY_0,CFG_STM32MP15_HUK_OTP_BASE) $(call force,CFG_STM32MP15_HUK_BSEC_KEY_1,(CFG_STM32MP15_HUK_OTP_BASE + 1)) $(call force,CFG_STM32MP15_HUK_BSEC_KEY_2,(CFG_STM32MP15_HUK_OTP_BASE + 2)) $(call force,CFG_STM32MP15_HUK_BSEC_KEY_3,(CFG_STM32MP15_HUK_OTP_BASE + 3)) endif ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_0)) $(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_0) endif ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_1)) $(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_1) endif ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_2)) $(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_2) endif ifeq (,$(CFG_STM32MP15_HUK_BSEC_KEY_3)) $(error Missing configuration switch CFG_STM32MP15_HUK_BSEC_KEY_3) endif endif # CFG_STM32_HUK_FROM_DT CFG_STM32MP15_HUK_BSEC_KEY ?= y CFG_STM32MP15_HUK_BSEC_DERIVE_UID ?= n ifneq (y,$(call cfg-one-enabled,CFG_STM32MP15_HUK_BSEC_KEY CFG_STM32MP15_HUK_BSEC_DERIVE_UID)) $(error CFG_STM32MP15_HUK mandates one of CFG_STM32MP15_HUK_BSEC_KEY CFG_STM32MP15_HUK_BSEC_DERIVE_UID) else ifeq ($(CFG_STM32MP15_HUK_BSEC_KEY)-$(CFG_STM32MP15_HUK_BSEC_DERIVE_UID),y-y) $(error CFG_STM32MP15_HUK_BSEC_KEY and CFG_STM32MP15_HUK_BSEC_DERIVE_UID are exclusive) endif endif # CFG_STM32MP15_HUK CFG_TEE_CORE_DEBUG ?= y CFG_STM32_DEBUG_ACCESS ?= $(CFG_TEE_CORE_DEBUG) # Sanity on choice config switches ifeq ($(call cfg-all-enabled,CFG_STM32MP15 CFG_STM32MP13),y) $(error CFG_STM32MP13_CLK and CFG_STM32MP15_CLK are exclusive) endif optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/000077500000000000000000000000001464416617300217755ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h000066400000000000000000000117361464416617300247510ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) 2018-2019, STMicroelectronics */ #ifndef __STM32MP1_ETZPC_H #define __STM32MP1_ETZPC_H /* Define DECPROT IDs for stm32mp1 familly */ #ifdef CFG_STM32MP15 #define STM32MP1_ETZPC_STGENC_ID 0 #define STM32MP1_ETZPC_BKPSRAM_ID 1 #define STM32MP1_ETZPC_IWDG1_ID 2 #define STM32MP1_ETZPC_USART1_ID 3 #define STM32MP1_ETZPC_SPI6_ID 4 #define STM32MP1_ETZPC_I2C4_ID 5 #define STM32MP1_ETZPC_GPIOZ_ID 6 #define STM32MP1_ETZPC_RNG1_ID 7 #define STM32MP1_ETZPC_HASH1_ID 8 #define STM32MP1_ETZPC_CRYP1_ID 9 #define STM32MP1_ETZPC_DDRCTRL_ID 10 #define STM32MP1_ETZPC_DDRPHYC_ID 11 #define STM32MP1_ETZPC_I2C6_ID 12 /* 13-15 Reserved */ #define STM32MP1_ETZPC_TIM2_ID 16 #define STM32MP1_ETZPC_TIM3_ID 17 #define STM32MP1_ETZPC_TIM4_ID 18 #define STM32MP1_ETZPC_TIM5_ID 19 #define STM32MP1_ETZPC_TIM6_ID 20 #define STM32MP1_ETZPC_TIM7_ID 21 #define STM32MP1_ETZPC_TIM12_ID 22 #define STM32MP1_ETZPC_TIM13_ID 23 #define STM32MP1_ETZPC_TIM14_ID 24 #define STM32MP1_ETZPC_LPTIM1_ID 25 #define STM32MP1_ETZPC_WWDG1_ID 26 #define STM32MP1_ETZPC_SPI2_ID 27 #define STM32MP1_ETZPC_SPI3_ID 28 #define STM32MP1_ETZPC_SPDIFRX_ID 29 #define STM32MP1_ETZPC_USART2_ID 30 #define STM32MP1_ETZPC_USART3_ID 31 #define STM32MP1_ETZPC_UART4_ID 32 #define STM32MP1_ETZPC_UART5_ID 33 #define STM32MP1_ETZPC_I2C1_ID 34 #define STM32MP1_ETZPC_I2C2_ID 35 #define STM32MP1_ETZPC_I2C3_ID 36 #define STM32MP1_ETZPC_I2C5_ID 37 #define STM32MP1_ETZPC_CEC_ID 38 #define STM32MP1_ETZPC_DAC_ID 39 #define STM32MP1_ETZPC_UART7_ID 40 #define STM32MP1_ETZPC_UART8_ID 41 /* 42-43 Reserved */ #define STM32MP1_ETZPC_MDIOS_ID 44 /* 45-47 Reserved */ #define STM32MP1_ETZPC_TIM1_ID 48 #define STM32MP1_ETZPC_TIM8_ID 49 /* 50 Reserved */ #define STM32MP1_ETZPC_USART6_ID 51 #define STM32MP1_ETZPC_SPI1_ID 52 #define STM32MP1_ETZPC_SPI4_ID 53 #define STM32MP1_ETZPC_TIM15_ID 54 #define STM32MP1_ETZPC_TIM16_ID 55 #define STM32MP1_ETZPC_TIM17_ID 56 #define STM32MP1_ETZPC_SPI5_ID 57 #define STM32MP1_ETZPC_SAI1_ID 58 #define STM32MP1_ETZPC_SAI2_ID 59 #define STM32MP1_ETZPC_SAI3_ID 60 #define STM32MP1_ETZPC_DFSDM_ID 61 #define STM32MP1_ETZPC_TT_FDCAN_ID 62 /* 63 Reserved */ #define STM32MP1_ETZPC_LPTIM2_ID 64 #define STM32MP1_ETZPC_LPTIM3_ID 65 #define STM32MP1_ETZPC_LPTIM4_ID 66 #define STM32MP1_ETZPC_LPTIM5_ID 67 #define STM32MP1_ETZPC_SAI4_ID 68 #define STM32MP1_ETZPC_VREFBUF_ID 69 #define STM32MP1_ETZPC_DCMI_ID 70 #define STM32MP1_ETZPC_CRC2_ID 71 #define STM32MP1_ETZPC_ADC_ID 72 #define STM32MP1_ETZPC_HASH2_ID 73 #define STM32MP1_ETZPC_RNG2_ID 74 #define STM32MP1_ETZPC_CRYP2_ID 75 /* 76-79 Reserved */ #define STM32MP1_ETZPC_SRAM1_ID 80 #define STM32MP1_ETZPC_SRAM2_ID 81 #define STM32MP1_ETZPC_SRAM3_ID 82 #define STM32MP1_ETZPC_SRAM4_ID 83 #define STM32MP1_ETZPC_RETRAM_ID 84 #define STM32MP1_ETZPC_OTG_ID 85 #define STM32MP1_ETZPC_SDMMC3_ID 86 #define STM32MP1_ETZPC_DLYBSD3_ID 87 #define STM32MP1_ETZPC_DMA1_ID 88 #define STM32MP1_ETZPC_DMA2_ID 89 #define STM32MP1_ETZPC_DMAMUX_ID 90 #define STM32MP1_ETZPC_FMC_ID 91 #define STM32MP1_ETZPC_QSPI_ID 92 #define STM32MP1_ETZPC_DLYBQ_ID 93 #define STM32MP1_ETZPC_ETH_ID 94 /* 95 Reserved */ #define STM32MP1_ETZPC_MAX_ID 96 #endif /* CFG_STM32MP15 */ #ifdef CFG_STM32MP13 #define STM32MP1_ETZPC_VREFBUF_ID 0 #define STM32MP1_ETZPC_LPTIM2_ID 1 #define STM32MP1_ETZPC_LPTIM3_ID 2 #define STM32MP1_ETZPC_LTDC_ID 3 #define STM32MP1_ETZPC_DCMIPP_ID 4 #define STM32MP1_ETZPC_USBPHYCTRL_ID 5 #define STM32MP1_ETZPC_DDRCTRLPHY_ID 6 /* 7-11 Reserved */ #define STM32MP1_ETZPC_IWDG1_ID 12 #define STM32MP1_ETZPC_STGENC_ID 13 /* 14-15 Reserved */ #define STM32MP1_ETZPC_USART1_ID 16 #define STM32MP1_ETZPC_USART2_ID 17 #define STM32MP1_ETZPC_SPI4_ID 18 #define STM32MP1_ETZPC_SPI5_ID 19 #define STM32MP1_ETZPC_I2C3_ID 20 #define STM32MP1_ETZPC_I2C4_ID 21 #define STM32MP1_ETZPC_I2C5_ID 22 #define STM32MP1_ETZPC_TIM12_ID 23 #define STM32MP1_ETZPC_TIM13_ID 24 #define STM32MP1_ETZPC_TIM14_ID 25 #define STM32MP1_ETZPC_TIM15_ID 26 #define STM32MP1_ETZPC_TIM16_ID 27 #define STM32MP1_ETZPC_TIM17_ID 28 /* 29-31 Reserved */ #define STM32MP1_ETZPC_ADC1_ID 32 #define STM32MP1_ETZPC_ADC2_ID 33 #define STM32MP1_ETZPC_OTG_ID 34 /* 35-36 Reserved */ #define STM32MP1_ETZPC_TSC_ID 37 /* 38-39 Reserved */ #define STM32MP1_ETZPC_RNG_ID 40 #define STM32MP1_ETZPC_HASH_ID 41 #define STM32MP1_ETZPC_CRYP_ID 42 #define STM32MP1_ETZPC_SAES_ID 43 #define STM32MP1_ETZPC_PKA_ID 44 #define STM32MP1_ETZPC_BKPSRAM_ID 45 /* 46-47 Reserved */ #define STM32MP1_ETZPC_ETH1_ID 48 #define STM32MP1_ETZPC_ETH2_ID 49 #define STM32MP1_ETZPC_SDMMC1_ID 50 #define STM32MP1_ETZPC_SDMMC2_ID 51 /* 52 Reserved */ #define STM32MP1_ETZPC_MCE_ID 53 #define STM32MP1_ETZPC_FMC_ID 54 #define STM32MP1_ETZPC_QSPI_ID 55 /* 56-59 Reserved */ #define STM32MP1_ETZPC_SRAM1_ID 60 #define STM32MP1_ETZPC_SRAM2_ID 61 #define STM32MP1_ETZPC_SRAM3_ID 62 /* 63 Reserved */ #define STM32MP1_ETZPC_MAX_ID 64 #endif /* CFG_STM32MP13 */ #endif /*__STM32MP1_ETZPC_H*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c000066400000000000000000000455251464416617300245520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2017-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MODE_STANDBY 8 #define PMIC_I2C_TRIALS 1 #define PMIC_I2C_TIMEOUT_BUSY_MS 5 #define PMIC_REGU_SUPPLY_NAME_LEN 12 #define PMIC_REGU_COUNT 14 enum { PMIC_REGU_FLAG_MASK_RESET = 0, PMIC_REGU_FLAG_COUNT }; static_assert(IS_ENABLED(CFG_DRIVERS_REGULATOR)); static_assert(PMIC_REGU_FLAG_COUNT <= UINT_MAX); /* * struct pmic_regulator_data - Platform specific data * @flags: Flags for platform property to apply * @regu_name: Regulator name ID in stpmic1 driver * @voltages_desc: Supported levels description * @voltages_level: Pointer to supported levels or NULL if not yet allocated */ struct pmic_regulator_data { unsigned int flags; char *regu_name; struct regulator_voltages_desc voltages_desc; int *voltages_level; }; /* Expect a single PMIC instance */ static struct i2c_handle_s *i2c_handle; static uint32_t pmic_i2c_addr; static int pmic_status = -1; /* CPU voltage supplier if found */ static char cpu_supply_name[PMIC_REGU_SUPPLY_NAME_LEN]; bool stm32mp_with_pmic(void) { return pmic_status > 0; } static void init_pmic_state(const void *fdt, int pmic_node) { pmic_status = fdt_get_status(fdt, pmic_node); } static bool dt_pmic_is_secure(void) { return stm32mp_with_pmic() && i2c_handle->dt_status == DT_STATUS_OK_SEC; } static void priv_dt_properties(const void *fdt, int regu_node, struct pmic_regulator_data *priv) { const char *name = fdt_get_name(fdt, regu_node, NULL); assert(name); priv->regu_name = strdup(name); if (!priv->regu_name) panic(); if (fdt_getprop(fdt, regu_node, "st,mask-reset", NULL)) priv->flags |= PMIC_REGU_FLAG_MASK_RESET; } /* * @flags: Operations expected when entering a low power sequence * @voltage: Target voltage to apply during low power sequences */ struct regu_lp_config { uint8_t flags; struct stpmic1_lp_cfg cfg; }; #define REGU_LP_FLAG_LOAD_PWRCTRL BIT(0) #define REGU_LP_FLAG_ON_IN_SUSPEND BIT(1) #define REGU_LP_FLAG_OFF_IN_SUSPEND BIT(2) #define REGU_LP_FLAG_SET_VOLTAGE BIT(3) #define REGU_LP_FLAG_MODE_STANDBY BIT(4) /* * struct regu_lp_state - Low power configuration for regulators * @name: low power state identifier string name * @cfg_count: number of regulator configuration instance in @cfg * @cfg: regulator configurations for low power state @name */ struct regu_lp_state { const char *name; size_t cfg_count; struct regu_lp_config *cfg; }; enum regu_lp_state_id { REGU_LP_STATE_DISK = 0, REGU_LP_STATE_STANDBY, REGU_LP_STATE_MEM, REGU_LP_STATE_MEM_LOWVOLTAGE, REGU_LP_STATE_COUNT }; static struct regu_lp_state regu_lp_state[REGU_LP_STATE_COUNT] = { [REGU_LP_STATE_DISK] = { .name = "standby-ddr-off", }, [REGU_LP_STATE_STANDBY] = { .name = "standby-ddr-sr", }, [REGU_LP_STATE_MEM] = { .name = "lp-stop", }, [REGU_LP_STATE_MEM_LOWVOLTAGE] = { .name = "lplv-stop", }, }; static unsigned int regu_lp_state2idx(const char *name) { unsigned int i = 0; for (i = 0; i < ARRAY_SIZE(regu_lp_state); i++) if (!strcmp(name, regu_lp_state[i].name)) return i; panic(); } static void dt_get_regu_low_power_config(const void *fdt, const char *regu_name, int regu_node, const char *lp_state) { unsigned int state_idx = regu_lp_state2idx(lp_state); struct regu_lp_state *state = regu_lp_state + state_idx; const fdt32_t *cuint = NULL; int regu_state_node = 0; struct regu_lp_config *regu_cfg = NULL; state->cfg_count++; state->cfg = realloc(state->cfg, state->cfg_count * sizeof(*state->cfg)); if (!state->cfg) panic(); regu_cfg = &state->cfg[state->cfg_count - 1]; memset(regu_cfg, 0, sizeof(*regu_cfg)); if (stpmic1_regu_has_lp_cfg(regu_name)) { if (stpmic1_lp_cfg(regu_name, ®u_cfg->cfg)) { DMSG("Cannot setup low power for regu %s", regu_name); panic(); } /* * Always copy active configuration (Control register) * to PWRCTRL Control register, even if regu_state_node * does not exist. */ regu_cfg->flags |= REGU_LP_FLAG_LOAD_PWRCTRL; } /* Parse regulator stte node if any */ regu_state_node = fdt_subnode_offset(fdt, regu_node, lp_state); if (regu_state_node <= 0) return; if (fdt_getprop(fdt, regu_state_node, "regulator-on-in-suspend", NULL)) regu_cfg->flags |= REGU_LP_FLAG_ON_IN_SUSPEND; if (fdt_getprop(fdt, regu_state_node, "regulator-off-in-suspend", NULL)) regu_cfg->flags |= REGU_LP_FLAG_OFF_IN_SUSPEND; cuint = fdt_getprop(fdt, regu_state_node, "regulator-suspend-microvolt", NULL); if (cuint) { uint32_t mv = fdt32_to_cpu(*cuint) / 1000U; if (stpmic1_lp_voltage_cfg(regu_name, mv, ®u_cfg->cfg)) { DMSG("Cannot set voltage for %s", regu_name); panic(); } regu_cfg->flags |= REGU_LP_FLAG_SET_VOLTAGE; } cuint = fdt_getprop(fdt, regu_state_node, "regulator-mode", NULL); if (cuint && fdt32_to_cpu(*cuint) == MODE_STANDBY) regu_cfg->flags |= REGU_LP_FLAG_MODE_STANDBY; } /* * int stm32mp_pmic_set_lp_config(char *lp_state) * * Load the low power configuration stored in regu_lp_state[]. */ void stm32mp_pmic_apply_lp_config(const char *lp_state) { unsigned int state_idx = regu_lp_state2idx(lp_state); struct regu_lp_state *state = ®u_lp_state[state_idx]; size_t i = 0; if (stpmic1_powerctrl_on()) panic(); for (i = 0; i < state->cfg_count; i++) { struct stpmic1_lp_cfg *cfg = &state->cfg[i].cfg; if ((state->cfg[i].flags & REGU_LP_FLAG_LOAD_PWRCTRL) && stpmic1_lp_load_unpg(cfg)) panic(); if ((state->cfg[i].flags & REGU_LP_FLAG_ON_IN_SUSPEND) && stpmic1_lp_on_off_unpg(cfg, 1)) panic(); if ((state->cfg[i].flags & REGU_LP_FLAG_OFF_IN_SUSPEND) && stpmic1_lp_on_off_unpg(cfg, 0)) panic(); if ((state->cfg[i].flags & REGU_LP_FLAG_SET_VOLTAGE) && stpmic1_lp_voltage_unpg(cfg)) panic(); if ((state->cfg[i].flags & REGU_LP_FLAG_MODE_STANDBY) && stpmic1_lp_mode_unpg(cfg, 1)) panic(); } } /* Return a libfdt compliant status value */ static int save_cpu_supply_name(void) { void *fdt = NULL; int node = 0; const fdt32_t *cuint = NULL; const char *name = NULL; fdt = get_embedded_dt(); if (!fdt) panic(); node = fdt_path_offset(fdt, "/cpus/cpu@0"); if (node < 0) return -FDT_ERR_NOTFOUND; cuint = fdt_getprop(fdt, node, "cpu-supply", NULL); if (!cuint) return -FDT_ERR_NOTFOUND; node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); if (node < 0) return -FDT_ERR_NOTFOUND; name = fdt_get_name(fdt, node, NULL); assert(strnlen(name, sizeof(cpu_supply_name)) < sizeof(cpu_supply_name)); strncpy(cpu_supply_name, name, sizeof(cpu_supply_name)); return 0; } const char *stm32mp_pmic_get_cpu_supply_name(void) { return cpu_supply_name; } /* Preallocate not that much regu references */ static char *nsec_access_regu_name[PMIC_REGU_COUNT]; bool stm32mp_nsec_can_access_pmic_regu(const char *name) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(nsec_access_regu_name); n++) if (nsec_access_regu_name[n] && !strcmp(nsec_access_regu_name[n], name)) return true; return false; } static void register_nsec_regu(const char *name_ref) { size_t n = 0; assert(!stm32mp_nsec_can_access_pmic_regu(name_ref)); for (n = 0; n < ARRAY_SIZE(nsec_access_regu_name); n++) { if (!nsec_access_regu_name[n]) { nsec_access_regu_name[n] = strdup(name_ref); if (!nsec_access_regu_name[n]) panic(); break; } } assert(stm32mp_nsec_can_access_pmic_regu(name_ref)); } static TEE_Result pmic_set_state(struct regulator *regulator, bool enable) { struct pmic_regulator_data *priv = regulator->priv; int ret = 0; stm32mp_get_pmic(); if (enable) ret = stpmic1_regulator_enable(priv->regu_name); else ret = stpmic1_regulator_disable(priv->regu_name); stm32mp_put_pmic(); if (ret) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result pmic_get_state(struct regulator *regulator, bool *enabled) { struct pmic_regulator_data *priv = regulator->priv; stm32mp_get_pmic(); *enabled = stpmic1_is_regulator_enabled(priv->regu_name); stm32mp_put_pmic(); return TEE_SUCCESS; } static TEE_Result pmic_get_voltage(struct regulator *regulator, int *level_uv) { struct pmic_regulator_data *priv = regulator->priv; int rc = 0; stm32mp_get_pmic(); rc = stpmic1_regulator_voltage_get(priv->regu_name); stm32mp_put_pmic(); if (rc < 0) return TEE_ERROR_GENERIC; *level_uv = rc * 1000; return TEE_SUCCESS; } static TEE_Result pmic_set_voltage(struct regulator *regulator, int level_uv) { struct pmic_regulator_data *priv = regulator->priv; unsigned int level_mv = level_uv / 1000; int rc = 0; if (level_mv > UINT16_MAX) return TEE_ERROR_BAD_PARAMETERS; stm32mp_get_pmic(); rc = stpmic1_regulator_voltage_set(priv->regu_name, level_mv); stm32mp_put_pmic(); if (rc) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static int cmp_int_value(const void *a, const void *b) { const int *ia = a; const int *ib = b; return CMP_TRILEAN(*ia, *ib); } static size_t refine_levels_array(size_t count, int *levels_uv, int min_uv, int max_uv) { size_t n = 0; size_t m = 0; /* We need to sort the array has STPMIC1 driver does not */ qsort(levels_uv, count, sizeof(*levels_uv), cmp_int_value); /* Remove duplicates and return optimized count */ for (n = 1; n < count; n++) { if (levels_uv[m] != levels_uv[n]) { if (m + 1 != n) levels_uv[m + 1] = levels_uv[n]; m++; } } count = m + 1; for (n = count; n; n--) if (levels_uv[n - 1] <= max_uv) break; count = n; for (n = 0; n < count; n++) if (levels_uv[n] >= min_uv) break; count -= n; memmove(levels_uv, levels_uv + n, count * sizeof(*levels_uv)); return count; } static TEE_Result pmic_list_voltages(struct regulator *regulator, struct regulator_voltages_desc **out_desc, const int **out_levels) { struct pmic_regulator_data *priv = regulator->priv; if (!priv->voltages_level) { const uint16_t *level_ref = NULL; size_t level_count = 0; int *levels2 = NULL; int *levels = NULL; size_t n = 0; /* * Allocate and build a consised and ordered voltage list * based on the voltage list provided by stpmic1 driver. */ stpmic1_regulator_levels_mv(priv->regu_name, &level_ref, &level_count); levels = calloc(level_count, sizeof(*levels)); if (!levels) return TEE_ERROR_OUT_OF_MEMORY; for (n = 0; n < level_count; n++) levels[n] = level_ref[n] * 1000; level_count = refine_levels_array(level_count, levels, regulator->min_uv, regulator->max_uv); /* Shrink levels array to not waste heap memory */ levels2 = realloc(levels, sizeof(*levels) * level_count); if (!levels2) { free(levels); return TEE_ERROR_OUT_OF_MEMORY; } priv->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; priv->voltages_desc.num_levels = level_count; priv->voltages_level = levels2; } *out_desc = &priv->voltages_desc; *out_levels = priv->voltages_level; return TEE_SUCCESS; } static TEE_Result pmic_regu_init(struct regulator *regulator, const void *fdt __unused, int node __unused) { struct pmic_regulator_data *priv = regulator->priv; struct stpmic1_bo_cfg cfg = { }; if (!priv->flags) return TEE_SUCCESS; stm32mp_get_pmic(); if (priv->flags & PMIC_REGU_FLAG_MASK_RESET) { if (stpmic1_bo_mask_reset_cfg(priv->regu_name, &cfg) || stpmic1_bo_mask_reset_unpg(&cfg)) { EMSG("Mask reset failed for %s", priv->regu_name); return TEE_ERROR_GENERIC; } } if (regulator->flags & REGULATOR_PULL_DOWN) { if (stpmic1_bo_pull_down_cfg(priv->regu_name, &cfg) || stpmic1_bo_pull_down_unpg(&cfg)) { EMSG("Pull down failed for %s", priv->regu_name); return TEE_ERROR_GENERIC; } } stm32mp_put_pmic(); return TEE_SUCCESS; } static const struct regulator_ops pmic_regu_ops = { .set_state = pmic_set_state, .get_state = pmic_get_state, .set_voltage = pmic_set_voltage, .get_voltage = pmic_get_voltage, .supported_voltages = pmic_list_voltages, .supplied_init = pmic_regu_init, }; DECLARE_KEEP_PAGER(pmic_regu_ops); static const struct regulator_ops pmic_sw_ops = { .set_state = pmic_set_state, .get_state = pmic_get_state, .supplied_init = pmic_regu_init, }; DECLARE_KEEP_PAGER(pmic_sw_ops); /* * STPMIC1 regulator names, used in the DT as regulator node name and * provider node -supply property, */ static const char * const pmic_regu_name_ids[] = { "buck1", "buck2", "buck3", "buck4", "ldo1", "ldo2", "ldo3", "ldo4", "ldo5", "ldo6", "vref_ddr", "boost", "pwr_sw1", "pwr_sw2" }; /* Preallocated regulator instances */ static struct regulator pmic_regulators[ARRAY_SIZE(pmic_regu_name_ids)]; static struct pmic_regulator_data pmic_regu_cfg[ARRAY_SIZE(pmic_regu_name_ids)]; static TEE_Result release_voltage_lists(void) { size_t n = 0; /* Voltage list will be rebuilt at runtime if needed at least once */ for (n = 0; n < ARRAY_SIZE(pmic_regulators); n++) { struct pmic_regulator_data *priv = pmic_regulators[n].priv; if (priv && priv->voltages_level) free(priv->voltages_level); } return TEE_SUCCESS; } release_init_resource(release_voltage_lists); struct regulator *stm32mp_pmic_get_regulator(const char *name) { size_t i = 0; if (!name) return NULL; for (i = 0; i < ARRAY_SIZE(pmic_regu_name_ids); i++) if (!strcmp(pmic_regu_name_ids[i], name) && pmic_regulators[i].ops) return pmic_regulators + i; return NULL; } static TEE_Result register_pmic_regulator(const void *fdt, const char *regu_name, int regu_node, int regulators_node) { TEE_Result res = TEE_ERROR_GENERIC; struct regu_dt_desc desc = { }; size_t i = 0; for (i = 0; i < ARRAY_SIZE(pmic_regu_name_ids); i++) if (!strcmp(pmic_regu_name_ids[i], regu_name)) break; if (i >= ARRAY_SIZE(pmic_regu_name_ids)) { EMSG("Unknown regulator name %s", regu_name); panic(); } desc = (struct regu_dt_desc){ .name = pmic_regu_name_ids[i], .supply_name = pmic_regu_name_ids[i], .regulator = pmic_regulators + i, .priv = pmic_regu_cfg + i, }; priv_dt_properties(fdt, regu_node, pmic_regu_cfg + i); /* * pwr_sw1 and pwr_sw2 are regulator switches hence have no * set_voltage.get_voltage handler. */ if (!strncmp(regu_name, "pwr_sw", 6)) desc.ops = &pmic_sw_ops; else desc.ops = &pmic_regu_ops; res = regulator_dt_register(fdt, regu_node, regulators_node, &desc); if (res) EMSG("Failed to register %s, error: %#"PRIx32, regu_name, res); return res; } static void parse_regulator_fdt_nodes(const void *fdt, int pmic_node) { int regulators_node = 0; int regu_node = 0; regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); if (regulators_node < 0) panic(); fdt_for_each_subnode(regu_node, fdt, regulators_node) { int status = fdt_get_status(fdt, regu_node); const char *regu_name = NULL; size_t n = 0; assert(status >= 0); if (status == DT_STATUS_DISABLED) continue; regu_name = fdt_get_name(fdt, regu_node, NULL); assert(stpmic1_regulator_is_valid(regu_name)); if (status & DT_STATUS_OK_NSEC) register_nsec_regu(regu_name); for (n = 0; n < ARRAY_SIZE(regu_lp_state); n++) dt_get_regu_low_power_config(fdt, regu_name, regu_node, regu_lp_state[n].name); if (register_pmic_regulator(fdt, regu_name, regu_node, regulators_node)) panic(); } if (save_cpu_supply_name()) DMSG("No CPU supply provided"); } /* * PMIC and resource initialization */ static void initialize_pmic_i2c(const void *fdt, int pmic_node) { const fdt32_t *cuint = NULL; cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); if (!cuint) { EMSG("PMIC configuration failed on reg property"); panic(); } pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; if (pmic_i2c_addr > UINT16_MAX) { EMSG("PMIC configuration failed on i2c address translation"); panic(); } stm32mp_get_pmic(); if (!stm32_i2c_is_device_ready(i2c_handle, pmic_i2c_addr, PMIC_I2C_TRIALS, PMIC_I2C_TIMEOUT_BUSY_MS)) panic(); stpmic1_bind_i2c(i2c_handle, pmic_i2c_addr); stm32mp_put_pmic(); } /* * Automated suspend/resume at system suspend/resume is expected * only when the PMIC is secure. If it is non secure, only atomic * execution context can get/put the PMIC resources. */ static TEE_Result pmic_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *pm_handle __unused) { if (op == PM_OP_SUSPEND) stm32_i2c_suspend(i2c_handle); else stm32_i2c_resume(i2c_handle); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(pmic_pm); /* stm32mp_get/put_pmic allows secure atomic sequences to use non secure PMIC */ void stm32mp_get_pmic(void) { stm32_i2c_resume(i2c_handle); } void stm32mp_put_pmic(void) { stm32_i2c_suspend(i2c_handle); } static void register_non_secure_pmic(void) { /* Allow this function to be called when STPMIC1 not used */ if (!i2c_handle->base.pa) return; stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl); if (i2c_handle->pinctrl_sleep) stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl_sleep); stm32mp_register_non_secure_periph_iomem(i2c_handle->base.pa); } static void register_secure_pmic(void) { stm32mp_register_secure_pinctrl(i2c_handle->pinctrl); if (i2c_handle->pinctrl_sleep) stm32mp_register_secure_pinctrl(i2c_handle->pinctrl_sleep); stm32mp_register_secure_periph_iomem(i2c_handle->base.pa); register_pm_driver_cb(pmic_pm, NULL, "stm32mp1-pmic"); } static TEE_Result initialize_pmic(const void *fdt, int pmic_node) { unsigned long pmic_version = 0; init_pmic_state(fdt, pmic_node); initialize_pmic_i2c(fdt, pmic_node); stm32mp_get_pmic(); if (stpmic1_get_version(&pmic_version)) panic("Failed to access PMIC"); DMSG("PMIC version = 0x%02lx", pmic_version); stm32mp_put_pmic(); if (dt_pmic_is_secure()) register_secure_pmic(); else register_non_secure_pmic(); parse_regulator_fdt_nodes(fdt, pmic_node); return TEE_SUCCESS; } static TEE_Result stm32_pmic_probe(const void *fdt, int node, const void *compat_data __unused) { struct stm32_i2c_dev *stm32_i2c_dev = NULL; struct i2c_dev *i2c_dev = NULL; TEE_Result res = TEE_SUCCESS; res = i2c_dt_get_dev(fdt, node, &i2c_dev); if (res) return res; stm32_i2c_dev = container_of(i2c_dev, struct stm32_i2c_dev, i2c_dev); i2c_handle = stm32_i2c_dev->handle; res = initialize_pmic(fdt, node); if (res) { DMSG("Unexpectedly failed to get I2C bus: %#"PRIx32, res); panic(); } return TEE_SUCCESS; } static const struct dt_device_match stm32_pmic_match_table[] = { { .compatible = "st,stpmic1" }, { } }; DEFINE_DT_DRIVER(stm32_pmic_dt_driver) = { .name = "st,stpmic1", .match_table = stm32_pmic_match_table, .probe = stm32_pmic_probe, }; optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.h000066400000000000000000000020231464416617300245410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2017-2020, STMicroelectronics */ #ifndef __STM32MP1_PMIC_H__ #define __STM32MP1_PMIC_H__ #include #ifdef CFG_STPMIC1 void stm32mp_pmic_apply_boot_on_config(void); void stm32mp_pmic_apply_lp_config(const char *lp_state); void stm32mp_get_pmic(void); void stm32mp_put_pmic(void); const char *stm32mp_pmic_get_cpu_supply_name(void); /* Get the PMIC regulator related to @name or NULL if not found */ struct regulator *stm32mp_pmic_get_regulator(const char *name); #else static inline void stm32mp_pmic_apply_boot_on_config(void) { } static inline void stm32mp_pmic_apply_lp_config(const char *lp_state __unused) { } static inline void stm32mp_get_pmic(void) { panic(); } static inline void stm32mp_put_pmic(void) { panic(); } static inline const char *stm32mp_pmic_get_cpu_supply_name(void) { return NULL; } static inline struct regulator * stm32mp_pmic_get_regulator(const char *name __unused) { return NULL; } #endif #endif /*__STM32MP1_PMIC_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.c000066400000000000000000000161421464416617300244230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2018-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PWR_CR3_USB33_EN BIT(24) #define PWR_CR3_USB33_RDY BIT(26) #define PWR_CR3_REG18_EN BIT(28) #define PWR_CR3_REG18_RDY BIT(29) #define PWR_CR3_REG11_EN BIT(30) #define PWR_CR3_REG11_RDY BIT(31) #define TIMEOUT_US_10MS U(10000) #define VOLTAGE_2V7_THREDSHOLD_UV 2700000 struct pwr_regu_desc { unsigned int level_mv; uint32_t cr3_enable_mask; uint32_t cr3_ready_mask; }; static const struct pwr_regu_desc pwr_regulators[PWR_REGU_COUNT] = { [PWR_REG11] = { .level_mv = 1100, .cr3_enable_mask = PWR_CR3_REG11_EN, .cr3_ready_mask = PWR_CR3_REG11_RDY, }, [PWR_REG18] = { .level_mv = 1800, .cr3_enable_mask = PWR_CR3_REG18_EN, .cr3_ready_mask = PWR_CR3_REG18_RDY, }, [PWR_USB33] = { .level_mv = 3300, .cr3_enable_mask = PWR_CR3_USB33_EN, .cr3_ready_mask = PWR_CR3_USB33_RDY, }, }; vaddr_t stm32_pwr_base(void) { static struct io_pa_va base = { .pa = PWR_BASE }; return io_pa_or_va_secure(&base, 1); } unsigned int stm32mp1_pwr_regulator_mv(enum pwr_regulator id) { assert(id < PWR_REGU_COUNT); return pwr_regulators[id].level_mv; } void stm32mp1_pwr_regulator_set_state(enum pwr_regulator id, bool enable) { uintptr_t cr3 = stm32_pwr_base() + PWR_CR3_OFF; uint32_t enable_mask = pwr_regulators[id].cr3_enable_mask; assert(id < PWR_REGU_COUNT); if (enable) { uint32_t ready_mask = pwr_regulators[id].cr3_ready_mask; uint64_t to = 0; io_setbits32(cr3, enable_mask); to = timeout_init_us(10 * 1000); while (!timeout_elapsed(to)) if (io_read32(cr3) & ready_mask) break; if (!(io_read32(cr3) & ready_mask)) panic(); } else { io_clrbits32(cr3, enable_mask); } } bool stm32mp1_pwr_regulator_is_enabled(enum pwr_regulator id) { assert(id < PWR_REGU_COUNT); return io_read32(stm32_pwr_base() + PWR_CR3_OFF) & pwr_regulators[id].cr3_enable_mask; } static TEE_Result stm32mp1_pwr_regu_set_state(struct regulator *regu, bool enable) { const struct pwr_regu_desc *desc = regu->priv; uintptr_t cr3 = stm32_pwr_base() + PWR_CR3_OFF; assert(desc); if (enable) { uint32_t value = 0; io_setbits32_stm32shregs(cr3, desc->cr3_enable_mask); if (IO_READ32_POLL_TIMEOUT(cr3, value, value & desc->cr3_ready_mask, 0, TIMEOUT_US_10MS)) return TEE_ERROR_GENERIC; } else { io_clrbits32_stm32shregs(cr3, desc->cr3_enable_mask); } return TEE_SUCCESS; } static TEE_Result stm32mp1_pwr_regu_read_state(struct regulator *regu, bool *enabled) { const struct pwr_regu_desc *desc = regu->priv; assert(desc); *enabled = io_read32(stm32_pwr_base() + PWR_CR3_OFF) & desc->cr3_enable_mask; return TEE_SUCCESS; } static TEE_Result stm32mp1_pwr_regu_read_voltage(struct regulator *regu, int *level_uv) { const struct pwr_regu_desc *desc = regu->priv; assert(desc); *level_uv = (int)desc->level_mv * 1000; return TEE_SUCCESS; } static const struct regulator_ops stm32mp1_pwr_regu_ops = { .set_state = stm32mp1_pwr_regu_set_state, .get_state = stm32mp1_pwr_regu_read_state, .get_voltage = stm32mp1_pwr_regu_read_voltage, }; /* Preallocated regulator devices */ static struct regulator pwr_regu_device[PWR_REGU_COUNT]; #define DEFINE_REG(_id, _name, _supply) { \ .ops = &stm32mp1_pwr_regu_ops, \ .name = _name, \ .supply_name = _supply, \ .priv = (void *)(pwr_regulators + (_id)), \ .regulator = pwr_regu_device + (_id), \ } static const struct regu_dt_desc stm32mp1_pwr_regu_dt_desc[] = { [PWR_REG11] = DEFINE_REG(PWR_REG11, "reg11", "vdd"), [PWR_REG18] = DEFINE_REG(PWR_REG18, "reg18", "vdd"), [PWR_USB33] = DEFINE_REG(PWR_USB33, "usb33", "vdd_3v3_usbfs"), }; DECLARE_KEEP_PAGER(stm32mp1_pwr_regu_dt_desc); struct regulator *stm32mp1_pwr_get_regulator(enum pwr_regulator id) { if (id < ARRAY_SIZE(pwr_regu_device)) return pwr_regu_device + id; return NULL; } static TEE_Result vdd_hslv_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *pm_hdl __unused) { if (op == PM_OP_RESUME) stm32mp_enable_fixed_vdd_hslv(); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(vdd_hslv_pm); static TEE_Result set_fixed_vdd_hslv_mode(struct regulator *vdd_supply) { TEE_Result res = TEE_ERROR_GENERIC; bool product_below_2v5 = false; uint32_t otp_value = 0; uint32_t otp_id = 0; /* * High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. * It could be disabled for low frequencies or if AFMUX is selected * but the function is not used, typically for TRACE. * If high speed low voltage pad mode is enabled, platform will * over consume. * * WARNING: * Enabling High Speed mode while Vdd > 2.7V * with the OTP product_below_2v5 (OTP 18, BIT 13) * erroneously set to 1 can damage the SoC. */ res = stm32_bsec_find_otp_in_nvmem_layout("hw2_otp", &otp_id, NULL, NULL); if (res) panic(); res = stm32_bsec_read_otp(&otp_value, otp_id); if (res) panic(); if (otp_value & HW2_OTP_PRODUCT_BELOW_2V5) product_below_2v5 = true; if (regulator_get_voltage(vdd_supply) < VOLTAGE_2V7_THREDSHOLD_UV) { if (!product_below_2v5) { DMSG("Vdd domains HSLV protected by HW"); } else { stm32mp_enable_fixed_vdd_hslv(); register_pm_driver_cb(vdd_hslv_pm, NULL, "stm32mp1-pwr-hslv"); } } else if (product_below_2v5) { panic("Vdd too high for related IO domains"); } return TEE_SUCCESS; } static TEE_Result stm32mp1_pwr_regu_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; const struct regu_dt_desc *dt_desc = stm32mp1_pwr_regu_dt_desc; struct regulator *vdd_supply = NULL; int subnode = 0; /* Setup High Speed Low Voltage mode for fixed VDD domain */ res = regulator_dt_get_supply(fdt, node, "vdd", &vdd_supply); if (res) return res; res = set_fixed_vdd_hslv_mode(vdd_supply); if (res) return res; /* Register PWR regulators */ fdt_for_each_subnode(subnode, fdt, node) { const char *node_name = fdt_get_name(fdt, subnode, NULL); unsigned int n = 0; for (n = 0; n < ARRAY_SIZE(stm32mp1_pwr_regu_dt_desc); n++) if (!strcmp(dt_desc[n].name, node_name)) break; if (n >= ARRAY_SIZE(stm32mp1_pwr_regu_dt_desc)) { EMSG("Invalid PWR regulator node %s", node_name); panic(); } res = regulator_dt_register(fdt, subnode, node, dt_desc + n); if (res) { EMSG("Can't register %s: %#"PRIx32, node_name, res); panic(); } } return TEE_SUCCESS; } static const struct dt_device_match stm32mp1_pwr_regu_match_table[] = { { .compatible = "st,stm32mp1,pwr-reg" }, { } }; DEFINE_DT_DRIVER(stm32mp1_pwr_regu_dt_driver) = { .name = "stm32mp1-pwr-regu", .match_table = stm32mp1_pwr_regu_match_table, .probe = stm32mp1_pwr_regu_probe, }; optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pwr.h000066400000000000000000000022031464416617300244210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2018-2023, STMicroelectronics */ #ifndef __STM32MP1_PWR_H #define __STM32MP1_PWR_H #include #include #include #define PWR_CR1_OFF 0x00 #define PWR_CR2_OFF 0x08 #define PWR_CR3_OFF 0x0c #define PWR_MPUCR_OFF 0x10 #define PWR_WKUPCR_OFF 0x20 #define PWR_MPUWKUPENR_OFF 0x28 /* CR3 register bitfield for STM32MP13 variants */ #define PWR_CR3_VDDSD1EN BIT(13) #define PWR_CR3_VDDSD1RDY BIT(14) #define PWR_CR3_VDDSD2EN BIT(15) #define PWR_CR3_VDDSD2RDY BIT(16) #define PWR_CR3_VDDSD1VALID BIT(22) #define PWR_CR3_VDDSD2VALID BIT(23) #define PWR_OFFSET_MASK 0x3fUL enum pwr_regulator { PWR_REG11 = 0, PWR_REG18, PWR_USB33, PWR_REGU_COUNT }; vaddr_t stm32_pwr_base(void); unsigned int stm32mp1_pwr_regulator_mv(enum pwr_regulator id); void stm32mp1_pwr_regulator_set_state(enum pwr_regulator id, bool enable); bool stm32mp1_pwr_regulator_is_enabled(enum pwr_regulator id); /* Returns the registered regulator related to @id or NULL */ struct regulator *stm32mp1_pwr_get_regulator(enum pwr_regulator id); #endif /*__STM32MP1_PWR_H*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.c000066400000000000000000000116471464416617300251160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include /* * SYSCFG register offsets (base relative) */ #define SYSCFG_IOCTRLSETR U(0x18) #define SYSCFG_CMPCR U(0x20) #define SYSCFG_CMPENSETR U(0x24) #define SYSCFG_CMPSD1CR U(0x30) #define SYSCFG_CMPSD2CR U(0x40) #define SYSCFG_HSLVEN0R U(0x50) #define SYSCFG_IOSIZE U(0x400) /* * SYSCFG_IOCTRLSETR Register for STM32MP15 variants */ #define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) #define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) #define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) #define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) #define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) /* * SYSCFG_CMPCR Register */ #define SYSCFG_CMPCR_SW_CTRL BIT(1) #define SYSCFG_CMPCR_READY BIT(8) #define SYSCFG_CMPCR_RANSRC GENMASK_32(19, 16) #define SYSCFG_CMPCR_RANSRC_SHIFT U(16) #define SYSCFG_CMPCR_RAPSRC GENMASK_32(23, 20) #define SYSCFG_CMPCR_ANSRC_SHIFT U(24) #define SYSCFG_CMPCR_READY_TIMEOUT_US U(1000) #define CMPENSETR_OFFSET U(0x4) #define CMPENCLRR_OFFSET U(0x8) /* * SYSCFG_CMPENSETR Register */ #define SYSCFG_CMPENSETR_MPU_EN BIT(0) /* * HSLV definitions */ #define SYSCFG_HSLV_MASK GENMASK_32(15, 0) #define SYSCFG_HSLV_KEY U(0x1018) static vaddr_t get_syscfg_base(void) { static struct io_pa_va base = { .pa = SYSCFG_BASE }; return io_pa_or_va(&base, SYSCFG_IOSIZE); } static void enable_io_compensation(int cmpcr_offset) { vaddr_t cmpcr_va = get_syscfg_base() + cmpcr_offset; uint32_t value = 0; if (io_read32(cmpcr_va) & SYSCFG_CMPCR_READY) return; io_setbits32(cmpcr_va + CMPENSETR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); if (IO_READ32_POLL_TIMEOUT(cmpcr_va, value, value & SYSCFG_CMPCR_READY, 0, SYSCFG_CMPCR_READY_TIMEOUT_US)) { /* Allow an almost silent failure here */ EMSG("IO compensation cell not ready"); } io_clrbits32(cmpcr_va, SYSCFG_CMPCR_SW_CTRL); DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_va)); } static __maybe_unused void disable_io_compensation(int cmpcr_offset) { vaddr_t cmpcr_base = get_syscfg_base() + cmpcr_offset; uint32_t value_cmpcr = 0; uint32_t apsrc_ansrc = 0; uint32_t value_cmpcr2 = 0; value_cmpcr = io_read32(cmpcr_base); value_cmpcr2 = io_read32(cmpcr_base + CMPENSETR_OFFSET); if (!(value_cmpcr & SYSCFG_CMPCR_READY && value_cmpcr2 & SYSCFG_CMPENSETR_MPU_EN)) return; /* Copy APSRC (resp. ANSRC) in RAPSRC (resp. RANSRC) */ apsrc_ansrc = value_cmpcr >> SYSCFG_CMPCR_ANSRC_SHIFT; value_cmpcr &= ~(SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); value_cmpcr |= SHIFT_U32(apsrc_ansrc, SYSCFG_CMPCR_RANSRC_SHIFT); io_write32(cmpcr_base, value_cmpcr | SYSCFG_CMPCR_SW_CTRL); io_setbits32(cmpcr_base + CMPENCLRR_OFFSET, SYSCFG_CMPENSETR_MPU_EN); DMSG("SYSCFG.cmpcr = %#"PRIx32, io_read32(cmpcr_base)); } static TEE_Result stm32mp1_iocomp(void) { if (clk_enable(stm32mp_rcc_clock_id_to_clk(CK_CSI)) || clk_enable(stm32mp_rcc_clock_id_to_clk(SYSCFG))) panic(); enable_io_compensation(SYSCFG_CMPCR); return TEE_SUCCESS; } driver_init(stm32mp1_iocomp); #ifdef CFG_STM32MP13 void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable) { int cmpcr_offset = 0; switch (id) { case SYSCFG_IO_COMP_IDX_SD1: cmpcr_offset = SYSCFG_CMPSD1CR; break; case SYSCFG_IO_COMP_IDX_SD2: cmpcr_offset = SYSCFG_CMPSD2CR; break; default: panic(); } if (enable) enable_io_compensation(cmpcr_offset); else disable_io_compensation(cmpcr_offset); } void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable) { size_t hslvenxr_offset = 0; uint32_t hlvs_value = 0; assert(id < SYSCFG_HSLV_COUNT); if (enable) hlvs_value = SYSCFG_HSLV_KEY; /* IDs are indices of SYSCFG_HSLVENxR registers */ hslvenxr_offset = SYSCFG_HSLVEN0R + id * sizeof(uint32_t); io_write32(get_syscfg_base() + hslvenxr_offset, hlvs_value); /* Value read shall be 1 on enable and 0 on disable */ hlvs_value = io_read32(get_syscfg_base() + hslvenxr_offset) & SYSCFG_HSLV_MASK; if (enable != hlvs_value) panic(); } void stm32mp_enable_fixed_vdd_hslv(void) { enum stm32mp13_hslv_id id = SYSCFG_HSLV_COUNT; for (id = SYSCFG_HSLV_IDX_TPIU; id < SYSCFG_HSLV_COUNT; id++) { /* SDMMCs domains may not be supplied by VDD */ if (id == SYSCFG_HSLV_IDX_SDMMC1 || id == SYSCFG_HSLV_IDX_SDMMC2) continue; stm32mp_set_hslv_state(id, true); } } #endif /* CFG_STM32MP13 */ #ifdef CFG_STM32MP15 void stm32mp_enable_fixed_vdd_hslv(void) { io_write32(get_syscfg_base() + SYSCFG_IOCTRLSETR, SYSCFG_IOCTRLSETR_HSLVEN_TRACE | SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | SYSCFG_IOCTRLSETR_HSLVEN_ETH | SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | SYSCFG_IOCTRLSETR_HSLVEN_SPI); } #endif optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_syscfg.h000066400000000000000000000025601464416617300251150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, STMicroelectronics */ #ifndef __DRIVERS_STM32MP1_SYSCFG_H #define __DRIVERS_STM32MP1_SYSCFG_H /* High Speed Low Voltage domains IDs for STM32MP13 variants */ enum stm32mp13_hslv_id { SYSCFG_HSLV_IDX_TPIU = 0, SYSCFG_HSLV_IDX_QSPI, SYSCFG_HSLV_IDX_ETH1, SYSCFG_HSLV_IDX_ETH2, SYSCFG_HSLV_IDX_SDMMC1, SYSCFG_HSLV_IDX_SDMMC2, SYSCFG_HSLV_IDX_SPI1, SYSCFG_HSLV_IDX_SPI2, SYSCFG_HSLV_IDX_SPI3, SYSCFG_HSLV_IDX_SPI4, SYSCFG_HSLV_IDX_SPI5, SYSCFG_HSLV_IDX_LTDC, SYSCFG_HSLV_COUNT }; /* IO compensation domains IDs for STM32MP13 variants */ enum stm32mp13_vddsd_comp_id { SYSCFG_IO_COMP_IDX_SD1, SYSCFG_IO_COMP_IDX_SD2, SYSCFG_IO_COMP_COUNT }; #ifdef CFG_STM32MP13 /* * Enable or disable IO compensation for a VDDSD IO domains * @id: VDDSD domain ID * @enable: True to enable IO compensation, false to disable */ void stm32mp_set_vddsd_comp_state(enum stm32mp13_vddsd_comp_id id, bool enable); /* * Enable or disable High Speed Low Voltage mode of an IO domain * @index: HSLV IO domain ID * @enable: True to enable IO compensation, false to disable */ void stm32mp_set_hslv_state(enum stm32mp13_hslv_id id, bool enable); #endif /*CFG_STM32MP13*/ /* Enable High Speed Low Voltage mode for domains fixed supplied VDD */ void stm32mp_enable_fixed_vdd_hslv(void); #endif /*__DRIVERS_STM32MP1_SYSCFG_H*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/drivers/sub.mk000066400000000000000000000001361464416617300231170ustar00rootroot00000000000000srcs-$(CFG_STPMIC1) += stm32mp1_pmic.c srcs-y += stm32mp1_pwr.c srcs-y += stm32mp1_syscfg.c optee_os-4.3.0/core/arch/arm/plat-stm32mp1/link.mk000066400000000000000000000016121464416617300216050ustar00rootroot00000000000000include core/arch/arm/kernel/link.mk # Create stm32 formatted images from the native binary images define stm32image_cmd @$(cmd-echo-silent) ' GEN $@' $(q)./core/arch/arm/plat-stm32mp1/scripts/stm32image.py \ --load 0 --entry 0 endef all: $(link-out-dir)/tee-header_v2.stm32 cleanfiles += $(link-out-dir)/tee-header_v2.stm32 $(link-out-dir)/tee-header_v2.stm32: $(link-out-dir)/tee-header_v2.bin $(stm32image_cmd) --source $< --dest $@ --bintype 0x20 all: $(link-out-dir)/tee-pager_v2.stm32 cleanfiles += $(link-out-dir)/tee-pager_v2.stm32 $(link-out-dir)/tee-pager_v2.stm32: $(link-out-dir)/tee-pager_v2.bin $(stm32image_cmd) --source $< --dest $@ --bintype 0x21 all: $(link-out-dir)/tee-pageable_v2.stm32 cleanfiles += $(link-out-dir)/tee-pageable_v2.stm32 $(link-out-dir)/tee-pageable_v2.stm32: $(link-out-dir)/tee-pageable_v2.bin $(stm32image_cmd) --source $< --dest $@ --bintype 0x22 optee_os-4.3.0/core/arch/arm/plat-stm32mp1/link_dummies_paged.c000066400000000000000000000003241464416617300243020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #include const struct clk_ops stm32mp1_clk_ops __rodata_dummy; optee_os-4.3.0/core/arch/arm/plat-stm32mp1/main.c000066400000000000000000000437211464416617300214160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2022, STMicroelectronics * Copyright (c) 2016-2018, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB2_BASE, APB2_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB3_BASE, APB3_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB4_BASE, APB4_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB5_BASE, APB5_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, AHB4_BASE, AHB4_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, AHB5_BASE, AHB5_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB5_BASE, APB5_SIZE); #ifdef CFG_STM32MP13 register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB6_BASE, APB6_SIZE); #endif register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); register_ddr(DDR_BASE, CFG_DRAM_SIZE); #define _ID2STR(id) (#id) #define ID2STR(id) _ID2STR(id) static TEE_Result platform_banner(void) { IMSG("Platform stm32mp1: flavor %s - DT %s", ID2STR(PLATFORM_FLAVOR), ID2STR(CFG_EMBED_DTB_SOURCE_FILE)); return TEE_SUCCESS; } service_init(platform_banner); /* * Console * * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for * trace console. Value 0 disables the early console. * * We cannot use the generic serial_console support since probing * the console requires the platform clock driver to be already * up and ready which is done only once service_init are completed. */ static struct stm32_uart_pdata console_data; void plat_console_init(void) { /* Early console initialization before MMU setup */ struct uart { paddr_t pa; bool secure; } uarts[] = { [0] = { .pa = 0 }, [1] = { .pa = USART1_BASE, .secure = true, }, [2] = { .pa = USART2_BASE, .secure = false, }, [3] = { .pa = USART3_BASE, .secure = false, }, [4] = { .pa = UART4_BASE, .secure = false, }, [5] = { .pa = UART5_BASE, .secure = false, }, [6] = { .pa = USART6_BASE, .secure = false, }, [7] = { .pa = UART7_BASE, .secure = false, }, [8] = { .pa = UART8_BASE, .secure = false, }, }; COMPILE_TIME_ASSERT(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART); if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa) return; /* No clock yet bound to the UART console */ console_data.clock = NULL; console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure; stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa); register_serial_console(&console_data.chip); IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART); } static TEE_Result init_console_from_dt(void) { struct stm32_uart_pdata *pd = NULL; void *fdt = NULL; int node = 0; TEE_Result res = TEE_ERROR_GENERIC; fdt = get_embedded_dt(); res = get_console_node_from_dt(fdt, &node, NULL, NULL); if (res == TEE_ERROR_ITEM_NOT_FOUND) { fdt = get_external_dt(); res = get_console_node_from_dt(fdt, &node, NULL, NULL); if (res == TEE_ERROR_ITEM_NOT_FOUND) return TEE_SUCCESS; if (res != TEE_SUCCESS) return res; } pd = stm32_uart_init_from_dt_node(fdt, node); if (!pd) { IMSG("DTB disables console"); register_serial_console(NULL); return TEE_SUCCESS; } /* Replace early console with the new one */ console_flush(); console_data = *pd; register_serial_console(&console_data.chip); IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-"); free(pd); return TEE_SUCCESS; } /* Probe console from DT once clock inits (service init level) are completed */ service_init_late(init_console_from_dt); /* * GIC init, used also for primary/secondary boot core wake completion */ void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); stm32mp_register_online_cpu(); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); stm32mp_register_online_cpu(); } #ifdef CFG_STM32MP13 #ifdef CFG_STM32_ETZPC /* Configure ETZPC cell and lock it when resource is secure */ static void config_lock_decprot(uint32_t decprot_id, enum etzpc_decprot_attributes decprot_attr) { etzpc_configure_decprot(decprot_id, decprot_attr); if (decprot_attr == ETZPC_DECPROT_S_RW) etzpc_lock_decprot(decprot_id); } static TEE_Result set_etzpc_secure_configuration(void) { config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_DDRCTRLPHY_ID, ETZPC_DECPROT_NS_R_S_W); /* Configure ETZPC with peripheral registering */ config_lock_decprot(STM32MP1_ETZPC_ADC1_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_ADC2_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_CRYP_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_DCMIPP_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_ETH1_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_ETH2_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_FMC_ID, ETZPC_DECPROT_NS_RW); /* HASH is secure */ config_lock_decprot(STM32MP1_ETZPC_HASH_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_I2C3_ID, ETZPC_DECPROT_NS_RW); /* I2C4 is secure */ config_lock_decprot(STM32MP1_ETZPC_I2C4_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_I2C5_ID, ETZPC_DECPROT_NS_RW); /* IWDG1 is secure */ config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_LPTIM2_ID, ETZPC_DECPROT_NS_RW); /* LPTIM3 is secure */ config_lock_decprot(STM32MP1_ETZPC_LPTIM3_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_LTDC_ID, ETZPC_DECPROT_NS_RW); /* MCE is secure */ config_lock_decprot(STM32MP1_ETZPC_MCE_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_OTG_ID, ETZPC_DECPROT_NS_RW); /* PKA is secure */ config_lock_decprot(STM32MP1_ETZPC_PKA_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_QSPI_ID, ETZPC_DECPROT_NS_RW); /* RNG is secure */ config_lock_decprot(STM32MP1_ETZPC_RNG_ID, ETZPC_DECPROT_S_RW); /* SAES is secure */ config_lock_decprot(STM32MP1_ETZPC_SAES_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_SDMMC1_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_SDMMC2_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_SPI4_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_SPI5_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_SRAM1_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_SRAM2_ID, ETZPC_DECPROT_NS_RW); /* SRAM3 is secure */ config_lock_decprot(STM32MP1_ETZPC_SRAM3_ID, ETZPC_DECPROT_S_RW); /* STGENC is secure */ config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); /* TIM12 is secure */ config_lock_decprot(STM32MP1_ETZPC_TIM12_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_TIM13_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_TIM14_ID, ETZPC_DECPROT_NS_RW); /* TIM15 is secure */ config_lock_decprot(STM32MP1_ETZPC_TIM15_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_TIM16_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_TIM17_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_USART1_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_USART2_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_USBPHYCTRL_ID, ETZPC_DECPROT_NS_RW); config_lock_decprot(STM32MP1_ETZPC_VREFBUF_ID, ETZPC_DECPROT_NS_RW); return TEE_SUCCESS; } driver_init_late(set_etzpc_secure_configuration); #endif /* CFG_STM32_ETZPC */ #endif /* CFG_STM32MP13 */ #ifdef CFG_STM32MP15 /* * This concerns OP-TEE pager for STM32MP1 to use secure internal * RAMs to execute. TZSRAM refers the TZSRAM_BASE/TZSRAM_SIZE * used in boot.c to locate secure unpaged memory. * * STM32MP15 variants embed 640kB of contiguous securable SRAMs * * +--------------+ <-- SYSRAM_BASE * | | lower part can be assigned to secure world * | SYSRAM 256kB | 4kB granule boundary * | | upper part can be assigned to secure world * +--------------+ <-- SRAM1_BASE (= SYSRAM_BASE + SYSRAM_SIZE) | | full range assigned to non-secure world or * | SRAM1 128kB | to secure world, or to- Cortex-M4 exclusive access * +--------------+ <-- SRAM2_BASE (= SRAM1_BASE + SRAM1_SIZE) | | full range assigned to non-secure world or * | SRAM2 128kB | to secure world, or to- Cortex-M4 exclusive access * +--------------+ <-- SRAM3_BASE (= SRAM2_BASE + SRAM2_SIZE) | | full range assigned to non-secure world or * | SRAM3 64kB | to secure world, or to- Cortex-M4 exclusive access * +--------------+ <-- SRAM4_BASE (= SRAM3_BASE + SRAM3_SIZE) | | full range assigned to non-secure world or * | SRAM4 64kB | to secure world, or to- Cortex-M4 exclusive access * +--------------+ <-- SRAM4_BASE + SRAM4_SIZE * * If SRAMx memories are not used for the companion Cortex-M4 * processor, OP-TEE can use this memory. * * SYSRAM configuration for secure/non-secure boundaries requires the * secure SYSRAM memory to start at the SYSRAM physical base address and grow * from there while the non-secure SYSRAM range lies at SYSRAM end addresses * with a 4KB page granule. * * SRAM1, SRAM2, SRAM3 and SRAM4 are independently assigned to secure world, * to non-secure world or possibly to Cortex-M4 exclusive access. Each * assignment covers the full related SRAMx memory range. * * Using non-secure SYSRAM or one of the SRAMx for SCMI message communication * can be done using CFG_STM32MP1_SCMI_SHM_BASE/CFG_STM32MP1_SCMI_SHM_SIZE. * This imposes related memory area is assigned to non-secure world. * Using secure internal memories (SYSRAM and/or some SRAMx) with STM32MP15 * shall meet this constraints known the TZSRAM physical memory range shall * be contiguous. */ #define SYSRAM_END (SYSRAM_BASE + SYSRAM_SIZE) #define SYSRAM_SEC_END (SYSRAM_BASE + SYSRAM_SEC_SIZE) #define SRAMS_END (SRAM4_BASE + SRAM4_SIZE) #define SRAMS_START SRAM1_BASE #define TZSRAM_END (CFG_TZSRAM_START + CFG_TZSRAM_SIZE) #define SCMI_SHM_IS_IN_SRAMX ((CFG_STM32MP1_SCMI_SHM_BASE >= SRAM1_BASE) && \ (CFG_STM32MP1_SCMI_SHM_BASE + \ CFG_STM32MP1_SCMI_SHM_SIZE) <= SRAMS_END) #define TZSRAM_FITS_IN_SYSRAM_SEC ((CFG_TZSRAM_START >= SYSRAM_BASE) && \ (TZSRAM_END <= SYSRAM_SEC_END)) #define TZSRAM_FITS_IN_SYSRAM_AND_SRAMS ((CFG_TZSRAM_START >= SYSRAM_BASE) && \ (CFG_TZSRAM_START < SYSRAM_END) && \ (TZSRAM_END > SYSRAM_END) && \ (TZSRAM_END <= SRAMS_END) && \ (SYSRAM_SIZE == SYSRAM_SEC_SIZE)) #define TZSRAM_FITS_IN_SRAMS ((CFG_TZSRAM_START >= SRAMS_START) && \ (CFG_TZSRAM_START < SRAMS_END) && \ (TZSRAM_END <= SRAMS_END)) #define TZSRAM_IS_IN_DRAM (CFG_TZSRAM_START >= CFG_DRAM_BASE) #ifdef CFG_WITH_PAGER /* * At build time, we enforce that, when pager is used, * either TZSRAM fully fits inside SYSRAM secure address range, * or TZSRAM fully fits inside the full SYSRAM and spread inside SRAMx orderly, * or TZSRAM fully fits some inside SRAMs address range, * or TZSRAM is in DDR for debug and test purpose. */ static_assert(TZSRAM_FITS_IN_SYSRAM_SEC || TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS || TZSRAM_IS_IN_DRAM); #endif #if TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS || \ SCMI_SHM_IS_IN_SRAMX /* At run time we enforce that SRAM1 to SRAM4 are properly assigned if used */ static TEE_Result init_stm32mp15_secure_srams(void) { if (IS_ENABLED(CFG_WITH_PAGER)) { if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, SRAM1_BASE, SRAM1_SIZE)) stm32mp_register_secure_periph_iomem(SRAM1_BASE); if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, SRAM2_BASE, SRAM2_SIZE)) stm32mp_register_secure_periph_iomem(SRAM2_BASE); if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, SRAM3_BASE, SRAM3_SIZE)) stm32mp_register_secure_periph_iomem(SRAM3_BASE); if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE, SRAM4_BASE, SRAM4_SIZE)) stm32mp_register_secure_periph_iomem(SRAM4_BASE); } if (SCMI_SHM_IS_IN_SRAMX) { if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, CFG_STM32MP1_SCMI_SHM_SIZE, SRAM1_BASE, SRAM1_SIZE)) stm32mp_register_non_secure_periph_iomem(SRAM1_BASE); if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, CFG_STM32MP1_SCMI_SHM_SIZE, SRAM2_BASE, SRAM2_SIZE)) stm32mp_register_non_secure_periph_iomem(SRAM2_BASE); if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, CFG_STM32MP1_SCMI_SHM_SIZE, SRAM3_BASE, SRAM3_SIZE)) stm32mp_register_non_secure_periph_iomem(SRAM3_BASE); if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE, CFG_STM32MP1_SCMI_SHM_SIZE, SRAM4_BASE, SRAM4_SIZE)) stm32mp_register_non_secure_periph_iomem(SRAM4_BASE); } return TEE_SUCCESS; } service_init_late(init_stm32mp15_secure_srams); #endif /* TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS */ #endif /* CFG_STM32MP15 && CFG_TZSRAM_START */ static TEE_Result init_stm32mp1_drivers(void) { /* Secure internal memories for the platform, once ETZPC is ready */ etzpc_configure_tzma(0, ETZPC_TZMA_ALL_SECURE); etzpc_lock_tzma(0); etzpc_configure_tzma(1, SYSRAM_SEC_SIZE >> SMALL_PAGE_SHIFT); etzpc_lock_tzma(1); if (SYSRAM_SIZE > SYSRAM_SEC_SIZE) { size_t nsec_size = SYSRAM_SIZE - SYSRAM_SEC_SIZE; paddr_t nsec_start = SYSRAM_BASE + SYSRAM_SEC_SIZE; uint8_t *va = phys_to_virt(nsec_start, MEM_AREA_IO_NSEC, nsec_size); IMSG("Non-secure SYSRAM [%p %p]", va, va + nsec_size - 1); /* Clear content from the non-secure part */ memset(va, 0, nsec_size); } return TEE_SUCCESS; } service_init_late(init_stm32mp1_drivers); static TEE_Result init_late_stm32mp1_drivers(void) { TEE_Result res = TEE_ERROR_GENERIC; /* Set access permission to TAM backup registers */ if (IS_ENABLED(CFG_STM32_TAMP)) { struct stm32_bkpregs_conf conf = { .nb_zone1_regs = TAMP_BKP_REGISTER_ZONE1_COUNT, .nb_zone2_regs = TAMP_BKP_REGISTER_ZONE2_COUNT, }; res = stm32_tamp_set_secure_bkpregs(&conf); if (res == TEE_ERROR_DEFER_DRIVER_INIT) { /* TAMP driver was not probed if disabled in the DT */ res = TEE_SUCCESS; } if (res) panic(); } return TEE_SUCCESS; } driver_init_late(init_late_stm32mp1_drivers); vaddr_t stm32_rcc_base(void) { static struct io_pa_va base = { .pa = RCC_BASE }; return io_pa_or_va_secure(&base, 1); } vaddr_t get_gicd_base(void) { struct io_pa_va base = { .pa = GIC_BASE + GICD_OFFSET }; return io_pa_or_va_secure(&base, 1); } void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg) { cfg->base = BSEC_BASE; cfg->upper_start = STM32MP1_UPPER_OTP_START; cfg->max_id = STM32MP1_OTP_MAX_ID; } bool __weak stm32mp_with_pmic(void) { return false; } uint32_t may_spin_lock(unsigned int *lock) { if (!lock || !cpu_mmu_enabled()) return 0; return cpu_spin_lock_xsave(lock); } void may_spin_unlock(unsigned int *lock, uint32_t exceptions) { if (!lock || !cpu_mmu_enabled()) return; cpu_spin_unlock_xrestore(lock, exceptions); } static vaddr_t stm32_tamp_base(void) { static struct io_pa_va base = { .pa = TAMP_BASE }; return io_pa_or_va_secure(&base, 1); } static vaddr_t bkpreg_base(void) { return stm32_tamp_base() + TAMP_BKP_REGISTER_OFF; } vaddr_t stm32mp_bkpreg(unsigned int idx) { return bkpreg_base() + (idx * sizeof(uint32_t)); } static bool __maybe_unused bank_is_valid(unsigned int bank) { if (IS_ENABLED(CFG_STM32MP15)) return bank == GPIO_BANK_Z || bank <= GPIO_BANK_K; if (IS_ENABLED(CFG_STM32MP13)) return bank <= GPIO_BANK_I; panic(); } #ifdef CFG_STM32_IWDG TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase, struct stm32_iwdg_otp_data *otp_data) { unsigned int idx = 0; uint32_t otp_id = 0; size_t bit_len = 0; uint8_t bit_offset = 0; uint32_t otp_value = 0; switch (pbase) { case IWDG1_BASE: idx = 0; break; case IWDG2_BASE: idx = 1; break; default: panic(); } if (stm32_bsec_find_otp_in_nvmem_layout("hw2_otp", &otp_id, &bit_offset, &bit_len) || bit_len != 32 || bit_offset != 0) panic(); if (stm32_bsec_read_otp(&otp_value, otp_id)) panic(); otp_data->hw_enabled = otp_value & BIT(idx + HW2_OTP_IWDG_HW_ENABLE_SHIFT); otp_data->disable_on_stop = otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STOP_SHIFT); otp_data->disable_on_standby = otp_value & BIT(idx + HW2_OTP_IWDG_FZ_STANDBY_SHIFT); return TEE_SUCCESS; } #endif /*CFG_STM32_IWDG*/ #ifdef CFG_STM32_DEBUG_ACCESS static TEE_Result init_debug(void) { TEE_Result res = TEE_SUCCESS; uint32_t conf = stm32_bsec_read_debug_conf(); struct clk *dbg_clk = stm32mp_rcc_clock_id_to_clk(CK_DBG); uint32_t state = 0; res = stm32_bsec_get_state(&state); if (res) return res; if (state != BSEC_STATE_SEC_CLOSED && conf) { if (IS_ENABLED(CFG_INSECURE)) IMSG("WARNING: All debug accesses are allowed"); res = stm32_bsec_write_debug_conf(conf | BSEC_DEBUG_ALL); if (res) return res; /* * Enable DBG clock as used to access coprocessor * debug registers */ clk_enable(dbg_clk); } return TEE_SUCCESS; } early_init_late(init_debug); #endif /* CFG_STM32_DEBUG_ACCESS */ /* Some generic resources need to be unpaged */ DECLARE_KEEP_PAGER(pinctrl_apply_state); optee_os-4.3.0/core/arch/arm/plat-stm32mp1/nsec-service/000077500000000000000000000000001464416617300227055ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.c000066400000000000000000000033311464416617300246400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2016-2020, STMicroelectronics */ #include #include #include #include #include "bsec_svc.h" #include "stm32mp1_smc.h" void bsec_main(struct thread_smc_args *args) { TEE_Result result = TEE_ERROR_GENERIC; uint32_t cmd = args->a1; uint32_t otp_id = args->a2; uint32_t in_value = args->a3; uint32_t *out_value = &args->a1; uint32_t tmp = 0; if (!stm32_bsec_nsec_can_access_otp(otp_id)) { args->a0 = STM32_SIP_SVC_INVALID_PARAMS; return; } switch (cmd) { case STM32_SIP_SVC_BSEC_READ_SHADOW: FMSG("read shadow @%#"PRIx32, otp_id); result = stm32_bsec_read_otp(out_value, otp_id); break; case STM32_SIP_SVC_BSEC_PROG_OTP: FMSG("program @%#"PRIx32, otp_id); result = stm32_bsec_program_otp(in_value, otp_id); break; case STM32_SIP_SVC_BSEC_WRITE_SHADOW: FMSG("write shadow @%#"PRIx32, otp_id); result = stm32_bsec_write_otp(in_value, otp_id); break; case STM32_SIP_SVC_BSEC_READ_OTP: FMSG("read @%#"PRIx32, otp_id); result = stm32_bsec_read_otp(&tmp, otp_id); if (!result) result = stm32_bsec_shadow_register(otp_id); if (!result) result = stm32_bsec_read_otp(out_value, otp_id); if (!result) result = stm32_bsec_write_otp(tmp, otp_id); break; case STM32_SIP_SVC_BSEC_WRLOCK_OTP: FMSG("permanent write lock @%#"PRIx32, otp_id); result = stm32_bsec_permanent_lock_otp(otp_id); break; default: DMSG("Invalid command %#"PRIx32, cmd); result = TEE_ERROR_BAD_PARAMETERS; break; } if (!result) args->a0 = STM32_SIP_SVC_OK; else if (result == TEE_ERROR_BAD_PARAMETERS) args->a0 = STM32_SIP_SVC_INVALID_PARAMS; else args->a0 = STM32_SIP_SVC_FAILED; } optee_os-4.3.0/core/arch/arm/plat-stm32mp1/nsec-service/bsec_svc.h000066400000000000000000000007211464416617300246450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2016-2020, STMicroelectronics */ #ifndef __STM32MP1_BSEC_SVC_H__ #define __STM32MP1_BSEC_SVC_H__ #include #include #include #ifdef CFG_STM32_BSEC_SIP void bsec_main(struct thread_smc_args *args); #else static inline void bsec_main(struct thread_smc_args *args) { args->a0 = STM32_SIP_SVC_UNKNOWN_FUNCTION; } #endif #endif /*__STM32MP1_BSEC_SVC_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h000066400000000000000000000061071464416617300253120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2016-2022, STMicroelectronics * Copyright (c) 2018, Linaro Limited */ #ifndef __STM32MP1_SMC_H__ #define __STM32MP1_SMC_H__ #include /* * SIP Functions */ #define STM32_SIP_SVC_VERSION_MAJOR 0x0 #define STM32_SIP_SVC_VERSION_MINOR 0x1 #define STM32_SIP_SVC_FUNCTION_COUNT 0x3 /* STM32 SIP service generic return codes */ #define STM32_SIP_SVC_OK 0x0 #define STM32_SIP_SVC_UNKNOWN_FUNCTION OPTEE_SMC_RETURN_UNKNOWN_FUNCTION #define STM32_SIP_SVC_FAILED 0xfffffffeU #define STM32_SIP_SVC_INVALID_PARAMS 0xfffffffdU /* * SMC function IDs for STM32 Service queries * STM32 SMC services use the space between 0x82000000 and 0x8200FFFF * like this is defined in SMC calling Convention by ARM * for SiP (Silicon Partner) * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html */ /* * SIP function STM32_SIP_FUNC_CALL_COUNT * * Argument a0: (input) SMCC ID * (output) Count of defined function IDs */ #define STM32_SIP_SVC_FUNC_CALL_COUNT 0xff00 /* * Return the following UID if using API specified in this file without * further extensions: * 50aa78a7-9bf4-4a14-8a5e-264d5994c214. * * Represented in 4 32-bit words in STM32_SIP_UID_0, STM32_SIP_UID_1, * STM32_SIP_UID_2, STM32_SIP_UID_3. */ #define STM32_SIP_SVC_UID_0 0x50aa78a7 #define STM32_SIP_SVC_UID_1 0x9bf44a14 #define STM32_SIP_SVC_UID_2 0x8a5e264d #define STM32_SIP_SVC_UID_3 0x5994c214 /* * SIP function STM32_SIP_SVC_FUNC_UID * * Argument a0: (input) SMCC ID * (output) Lowest 32bit of the stm32mp1 SIP service UUID * Argument a1: (output) Next 32bit of the stm32mp1 SIP service UUID * Argument a2: (output) Next 32bit of the stm32mp1 SIP service UUID * Argument a3: (output) Last 32bit of the stm32mp1 SIP service UUID */ #define STM32_SIP_SVC_FUNC_UID 0xff01 /* * SIP function STM32_SIP_FUNC_VERSION * * Argument a0: (input) SMCC ID * (output) STM32 SIP service major * Argument a1: (output) STM32 SIP service minor */ #define STM32_SIP_SVC_FUNC_VERSION 0xff03 /* * SIP functions STM32_SIP_SVC_FUNC_BSEC - Deprecated * * Argument a0: (input) SMCCC function ID * (output) status return code * Argument a1: (input) Service ID (STM32_SIP_BSEC_xxx) * Argument a2: (input) OTP index * (output) OTP read value, if applicable * Argument a3: (input) OTP value if applicable */ #define STM32_SIP_SVC_FUNC_BSEC 0x1003 /* Service ID for function ID STM32_SIP_FUNC_BSEC */ #define STM32_SIP_SVC_BSEC_READ_SHADOW 0x1 #define STM32_SIP_SVC_BSEC_PROG_OTP 0x2 #define STM32_SIP_SVC_BSEC_WRITE_SHADOW 0x3 #define STM32_SIP_SVC_BSEC_READ_OTP 0x4 /* reserved for STM32_SIP_SVC_SMC_READ_ALL 0x5 */ /* reserved for STM32_SIP_SVC_SMC_WRITE_ALL 0x6 */ #define STM32_SIP_SVC_BSEC_WRLOCK_OTP 0x7 /* * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT0 * SIP function STM32_SIP_SVC_FUNC_SCMI_AGENT1 * * Process SCMI message pending in related SCMI shared memory buffer. * * Argument a0: (input) SMCC ID */ #define STM32_SIP_SVC_FUNC_SCMI_AGENT0 0x2000 #define STM32_SIP_SVC_FUNC_SCMI_AGENT1 0x2001 #endif /* __STM32MP1_SMC_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_svc_setup.c000066400000000000000000000033241464416617300265340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2017-2020, STMicroelectronics */ #include #include #include #include #include #include #include "bsec_svc.h" #include "stm32mp1_smc.h" static enum sm_handler_ret sip_service(struct sm_ctx *ctx __unused, struct thread_smc_args *args) { switch (OPTEE_SMC_FUNC_NUM(args->a0)) { case STM32_SIP_SVC_FUNC_CALL_COUNT: args->a0 = STM32_SIP_SVC_FUNCTION_COUNT; break; case STM32_SIP_SVC_FUNC_VERSION: args->a0 = STM32_SIP_SVC_VERSION_MAJOR; args->a1 = STM32_SIP_SVC_VERSION_MINOR; break; case STM32_SIP_SVC_FUNC_UID: args->a0 = STM32_SIP_SVC_UID_0; args->a1 = STM32_SIP_SVC_UID_1; args->a2 = STM32_SIP_SVC_UID_2; args->a3 = STM32_SIP_SVC_UID_3; break; case STM32_SIP_SVC_FUNC_SCMI_AGENT0: if (IS_ENABLED(CFG_STM32MP1_SCMI_SIP)) { scmi_smt_fastcall_smc_entry(0); args->a0 = STM32_SIP_SVC_OK; } else { args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; } break; case STM32_SIP_SVC_FUNC_SCMI_AGENT1: if (IS_ENABLED(CFG_STM32MP1_SCMI_SIP)) { scmi_smt_fastcall_smc_entry(1); args->a0 = STM32_SIP_SVC_OK; } else { args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; } break; case STM32_SIP_SVC_FUNC_BSEC: bsec_main(args); break; default: return SM_HANDLER_PENDING_SMC; } return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) { struct thread_smc_args *args = (void *)&ctx->nsec.r0; if (!OPTEE_SMC_IS_FAST_CALL(args->a0)) return SM_HANDLER_PENDING_SMC; switch (OPTEE_SMC_OWNER_NUM(args->a0)) { case OPTEE_SMC_OWNER_SIP: return sip_service(ctx, args); default: return SM_HANDLER_PENDING_SMC; } } optee_os-4.3.0/core/arch/arm/plat-stm32mp1/nsec-service/sub.mk000066400000000000000000000001371464416617300240300ustar00rootroot00000000000000global-incdirs-y += . srcs-y += stm32mp1_svc_setup.c srcs-$(CFG_STM32_BSEC_SIP) += bsec_svc.c optee_os-4.3.0/core/arch/arm/plat-stm32mp1/plat_tzc400.c000066400000000000000000000063501464416617300225330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2020, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #ifdef CFG_STM32MP15 #define TZC_FILTERS_MASK GENMASK_32(1, 0) #endif #ifdef CFG_STM32MP13 #define TZC_FILTERS_MASK GENMASK_32(0, 0) #endif static enum itr_return tzc_it_handler(struct itr_handler *handler __unused) { EMSG("TZC permission failure"); tzc_fail_dump(); if (IS_ENABLED(CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION)) panic(); else tzc_int_clear(); return ITRR_HANDLED; } static struct itr_handler tzc_itr_handler = { .it = STM32MP1_IRQ_TZC, .handler = tzc_it_handler, }; DECLARE_KEEP_PAGER(tzc_itr_handler); static bool tzc_region_is_non_secure(unsigned int i, uint64_t pa, size_t size) { struct tzc_region_config region_cfg = { }; uint32_t ns_cpu_mask = TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID); uint32_t filters_mask = TZC_FILTERS_MASK; vaddr_t base = pa; if (tzc_get_region_config(i, ®ion_cfg)) panic(); return region_cfg.base == base && region_cfg.top == (base + size - 1) && region_cfg.sec_attr == TZC_REGION_S_NONE && (region_cfg.ns_device_access & ns_cpu_mask) == ns_cpu_mask && region_cfg.filters == filters_mask; } static bool tzc_region_is_secure(unsigned int i, vaddr_t base, size_t size) { struct tzc_region_config region_cfg = { }; uint32_t filters_mask = TZC_FILTERS_MASK; if (tzc_get_region_config(i, ®ion_cfg)) panic(); return region_cfg.base == base && region_cfg.top == (base + size - 1) && region_cfg.sec_attr == TZC_REGION_S_RDWR && region_cfg.ns_device_access == 0 && region_cfg.filters == filters_mask; } static TEE_Result init_stm32mp1_tzc(void) { TEE_Result res = TEE_ERROR_GENERIC; void *base = phys_to_virt(TZC_BASE, MEM_AREA_IO_SEC, 1); unsigned int region_index = 1; const uint64_t dram_start = DDR_BASE; const uint64_t dram_end = dram_start + CFG_DRAM_SIZE; const uint64_t tzdram_start = CFG_TZDRAM_START; const uint64_t tzdram_size = CFG_TZDRAM_SIZE; const uint64_t tzdram_end = tzdram_start + tzdram_size; assert(base); tzc_init((vaddr_t)base); tzc_dump_state(); /* * Early boot stage is in charge of configuring memory regions * OP-TEE hence here only check this complies with static Core * expectations. */ if (dram_start < tzdram_start) { if (!tzc_region_is_non_secure(region_index, dram_start, tzdram_start - dram_start)) panic("Unexpected TZC area on non-secure region"); region_index++; } if (!tzc_region_is_secure(region_index, tzdram_start, tzdram_size)) panic("Unexpected TZC configuration on secure region"); if (tzdram_end < dram_end) { region_index++; if (!tzc_region_is_non_secure(region_index, tzdram_end, dram_end - tzdram_end)) panic("Unexpected TZC area on non-secure region"); } res = interrupt_add_handler_with_chip(interrupt_get_main_chip(), &tzc_itr_handler); if (res) panic(); interrupt_enable(tzc_itr_handler.chip, tzc_itr_handler.it); tzc_set_action(TZC_ACTION_INT); return TEE_SUCCESS; } driver_init(init_stm32mp1_tzc); optee_os-4.3.0/core/arch/arm/plat-stm32mp1/platform_config.h000066400000000000000000000144121464416617300236430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2018, STMicroelectronics */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 32 /* Translation table */ #ifdef CFG_WITH_LPAE #define MAX_XLAT_TABLES 4 #else #define MAX_XLAT_TABLES 8 #endif /* SoC interface registers base address ranges */ #define APB1_BASE 0x40000000 #define APB1_SIZE 0x0001d000 #define APB2_BASE 0x44000000 #define APB2_SIZE 0x00014000 #define APB3_BASE 0x50020000 #define APB3_SIZE 0x0000b000 #define APB4_BASE 0x5a000000 #define APB4_SIZE 0x00008000 #define APB5_BASE 0x5c000000 #define APB5_SIZE 0x0000b000 #ifdef CFG_STM32MP13 #define APB6_BASE 0x4c000000 #define APB6_SIZE 0x0000d000 #endif #define AHB4_BASE 0x50000000 #define AHB4_SIZE 0x00020000 #ifdef CFG_STM32MP13 #define AHB5_BASE 0x54000000 #define AHB5_SIZE 0x00008000 #endif #ifdef CFG_STM32MP15 #define AHB5_BASE 0x54000000 #define AHB5_SIZE 0x00005000 #endif /* SoC interface registers base address */ #define BSEC_BASE 0x5c005000 #define ETZPC_BASE 0x5c007000 #define CRYP1_BASE 0x54001000 #define DDR_BASE 0xc0000000ul #define GIC_BASE 0xa0021000ul #define GPIOA_BASE 0x50002000 #define GPIOB_BASE 0x50003000 #define GPIOC_BASE 0x50004000 #define GPIOD_BASE 0x50005000 #define GPIOE_BASE 0x50006000 #define GPIOF_BASE 0x50007000 #define GPIOG_BASE 0x50008000 #define GPIOH_BASE 0x50009000 #define GPIOI_BASE 0x5000a000 #define GPIOJ_BASE 0x5000b000 #define GPIOK_BASE 0x5000c000 #define GPIOZ_BASE 0x54004000 #define HASH1_BASE 0x54002000 #define I2C4_BASE 0x5c002000 #define I2C5_BASE 0x40015000 #define I2C6_BASE 0x5c009000 #define IWDG1_BASE 0x5c003000 #define IWDG2_BASE 0x5a002000 #define PWR_BASE 0x50001000 #define RCC_BASE 0x50000000 #ifdef CFG_STM32MP13 #define RNG1_BASE 0x54004000 #endif #ifdef CFG_STM32MP15 #define RNG1_BASE 0x54003000 #endif #define RTC_BASE 0x5c004000 #define SPI6_BASE 0x5c001000 #ifdef CFG_STM32MP15 #define SRAM1_BASE 0x30000000 #define SRAM2_BASE 0x30020000 #define SRAM3_BASE 0x30040000 #define SRAM4_BASE 0x30050000 #endif #define SYSCFG_BASE 0x50020000 #ifdef CFG_STM32MP13 #define SYSRAM_BASE 0x2ffe0000 #endif #ifdef CFG_STM32MP15 #define SYSRAM_BASE 0x2ffc0000 #endif #define TAMP_BASE 0x5c00a000 #define TZC_BASE 0x5c006000 #ifdef CFG_STM32MP13 #define UART1_BASE 0x4c000000 #define UART2_BASE 0x4c001000 #endif #ifdef CFG_STM32MP15 #define UART1_BASE 0x5c000000 #define UART2_BASE 0x4000e000 #endif #define UART3_BASE 0x4000f000 #define UART4_BASE 0x40010000 #define UART5_BASE 0x40011000 #define UART6_BASE 0x44003000 #define UART7_BASE 0x40018000 #define UART8_BASE 0x40019000 /* Console configuration */ #define STM32MP1_DEBUG_USART_BASE UART4_BASE #define GIC_SPI_UART4 84 #define CONSOLE_UART_BASE STM32MP1_DEBUG_USART_BASE #define CONSOLE_UART_SIZE 1024 /* BSEC OTP resources */ #define STM32MP1_OTP_MAX_ID 0x5FU #define STM32MP1_UPPER_OTP_START 0x20U #define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) /* Bit map for BSEC word CFG0_OTP */ #ifdef CFG_STM32MP13 #define CFG0_OTP_CLOSED_DEVICE U(0x3F) #endif #ifdef CFG_STM32MP15 #define CFG0_OTP_CLOSED_DEVICE BIT(6) #endif /* Bit map for BSEC word HW2_OTP */ #define HW2_OTP_IWDG_HW_ENABLE_SHIFT U(3) #define HW2_OTP_IWDG_FZ_STOP_SHIFT U(5) #define HW2_OTP_IWDG_FZ_STANDBY_SHIFT U(7) #define HW2_OTP_PRODUCT_BELOW_2V5 BIT(13) /* GIC resources */ #define GIC_SIZE 0x2000 #define GICC_OFFSET 0x1000 #define GICD_OFFSET 0x0000 #define GIC_NON_SEC_SGI_0 0 #define GIC_SEC_SGI_0 8 #define GIC_SEC_SGI_1 9 #define TARGET_CPU0_GIC_MASK BIT(0) #define TARGET_CPU1_GIC_MASK BIT(1) #define TARGET_CPUS_GIC_MASK GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0) /* * GPIO banks: 11 non secure banks (A to K) and 1 secure bank (Z) * Bank register's base address is computed from the bank ID listed here. */ #define GPIOS_NSEC_COUNT 11 #define GPIOS_NSEC_BASE GPIOA_BASE #define GPIOS_NSEC_SIZE (GPIOS_NSEC_COUNT * SMALL_PAGE_SIZE) #define STM32MP1_GPIOZ_MAX_COUNT 1 #define STM32MP1_GPIOZ_PIN_MAX_COUNT 8 #define GPIO_BANK_OFFSET 0x1000U /* Bank IDs used in GPIO driver API */ #define GPIO_BANK_A 0U #define GPIO_BANK_B 1U #define GPIO_BANK_C 2U #define GPIO_BANK_D 3U #define GPIO_BANK_E 4U #define GPIO_BANK_F 5U #define GPIO_BANK_G 6U #define GPIO_BANK_H 7U #define GPIO_BANK_I 8U #define GPIO_BANK_J 9U #define GPIO_BANK_K 10U #define GPIO_BANK_Z 25U /* TAMP resources */ #define TAMP_BKP_REGISTER_OFF 0x100 #define TAMP_BKP_REGISTER_COUNT U(32) #define TAMP_BKP_REGISTER_ZONE1_COUNT U(10) #define TAMP_BKP_REGISTER_ZONE2_COUNT U(5) #define TAMP_BKP_REGISTER_ZONE3_COUNT U(17) #if (TAMP_BKP_REGISTER_ZONE1_COUNT + TAMP_BKP_REGISTER_ZONE2_COUNT + \ TAMP_BKP_REGISTER_ZONE3_COUNT != TAMP_BKP_REGISTER_COUNT) #error Inconsistent TAMP backup register zone definition #endif /* TZC resources */ #define STM32MP1_IRQ_TZC 36 #define STM32MP1_TZC_A7_ID 0 #define STM32MP1_TZC_M4_ID 1 #define STM32MP1_TZC_LCD_ID 3 #define STM32MP1_TZC_GPU_ID 4 #define STM32MP1_TZC_MDMA_ID 5 #define STM32MP1_TZC_DMA_ID 6 #define STM32MP1_TZC_USB_HOST_ID 7 #define STM32MP1_TZC_USB_OTG_ID 8 #define STM32MP1_TZC_SDMMC_ID 9 #define STM32MP1_TZC_ETH_ID 10 #define STM32MP1_TZC_DAP_ID 15 /* USART/UART resources */ #define USART1_BASE UART1_BASE #define USART2_BASE UART2_BASE #define USART3_BASE UART3_BASE #define USART6_BASE UART6_BASE /* SYSRAM layout */ #ifdef CFG_STM32MP13 #define SYSRAM_SIZE 0x20000 #else /* Assume CFG_STM32MP15 */ #define SYSRAM_SIZE 0x40000 #endif #define SYSRAM_NS_SIZE (SYSRAM_SIZE - SYSRAM_SEC_SIZE) /* Non-secure SYSRAM must be above (higher addresses) secure SYSRAM */ #define STM32MP1_SCMI_SHM_END (CFG_STM32MP1_SCMI_SHM_BASE + \ CFG_STM32MP1_SCMI_SHM_SIZE) #if (CFG_STM32MP1_SCMI_SHM_BASE && \ (CFG_STM32MP1_SCMI_SHM_BASE >= SYSRAM_BASE) && \ (STM32MP1_SCMI_SHM_END <= (SYSRAM_BASE + SYSRAM_SIZE))) #define SYSRAM_SEC_SIZE (CFG_STM32MP1_SCMI_SHM_BASE - SYSRAM_BASE) #else #define SYSRAM_SEC_SIZE SYSRAM_SIZE #endif #ifdef CFG_STM32MP15 #define SRAM1_SIZE 0x20000 #define SRAM2_SIZE 0x20000 #define SRAM3_SIZE 0x10000 #define SRAM4_SIZE 0x10000 #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/pm/000077500000000000000000000000001464416617300207335ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp1/pm/psci.c000066400000000000000000000137161464416617300220450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2022, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define CONSOLE_FLUSH_DELAY_MS 10 /* * SMP boot support and access to the mailbox */ enum core_state_id { CORE_OFF = 0, CORE_RET, CORE_AWAKE, CORE_ON, }; static enum core_state_id core_state[CFG_TEE_CORE_NB_CORE]; static unsigned int __maybe_unused state_lock = SPINLOCK_UNLOCK; static uint32_t __maybe_unused lock_state_access(void) { return may_spin_lock(&state_lock); } static void __maybe_unused unlock_state_access(uint32_t exceptions) { may_spin_unlock(&state_lock, exceptions); } int psci_affinity_info(uint32_t affinity, uint32_t lowest_affinity_level) { unsigned int pos = get_core_pos_mpidr(affinity); DMSG("core %zu, state %u", pos, core_state[pos]); if ((pos >= CFG_TEE_CORE_NB_CORE) || (lowest_affinity_level > PSCI_AFFINITY_LEVEL_ON)) { return PSCI_RET_INVALID_PARAMETERS; } switch (core_state[pos]) { case CORE_OFF: case CORE_RET: return PSCI_AFFINITY_LEVEL_OFF; case CORE_AWAKE: return PSCI_AFFINITY_LEVEL_ON_PENDING; case CORE_ON: return PSCI_AFFINITY_LEVEL_ON; default: panic(); } } #if CFG_TEE_CORE_NB_CORE == 1 /* * Function called when a CPU is booted through the OP-TEE. * All cores shall register when online. */ void stm32mp_register_online_cpu(void) { assert(core_state[0] == CORE_OFF); core_state[0] = CORE_ON; } #else static void __noreturn stm32_pm_cpu_power_down_wfi(void) { dcache_op_level1(DCACHE_OP_CLEAN); io_write32(stm32_rcc_base() + RCC_MP_GRSTCSETR, RCC_MP_GRSTCSETR_MPUP1RST); dsb(); isb(); wfi(); panic(); } void stm32mp_register_online_cpu(void) { size_t pos = get_core_pos(); uint32_t exceptions = lock_state_access(); if (pos == 0) { assert(core_state[pos] == CORE_OFF); } else { if (core_state[pos] != CORE_AWAKE) { core_state[pos] = CORE_OFF; unlock_state_access(exceptions); stm32_pm_cpu_power_down_wfi(); panic(); } clk_disable(stm32mp_rcc_clock_id_to_clk(RTCAPB)); } core_state[pos] = CORE_ON; unlock_state_access(exceptions); } #define GICD_SGIR 0xF00 static void raise_sgi0_as_secure(void) { dsb_ishst(); io_write32(get_gicd_base() + GICD_SGIR, GIC_NON_SEC_SGI_0 | SHIFT_U32(TARGET_CPU1_GIC_MASK, 16)); } static void release_secondary_early_hpen(size_t __unused pos) { struct itr_chip *itr_chip = interrupt_get_main_chip(); /* Need to send SIG#0 over Group0 after individual core 1 reset */ raise_sgi0_as_secure(); udelay(20); io_write32(stm32mp_bkpreg(BCKR_CORE1_BRANCH_ADDRESS), TEE_LOAD_ADDR); io_write32(stm32mp_bkpreg(BCKR_CORE1_MAGIC_NUMBER), BOOT_API_A7_CORE1_MAGIC_NUMBER); dsb_ishst(); interrupt_raise_sgi(itr_chip, GIC_SEC_SGI_0, TARGET_CPU1_GIC_MASK); } /* Override default psci_cpu_on() with platform specific sequence */ int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) { size_t pos = get_core_pos_mpidr(core_id); uint32_t exceptions = 0; int rc = 0; if (!pos || pos >= CFG_TEE_CORE_NB_CORE) return PSCI_RET_INVALID_PARAMETERS; DMSG("core %zu, ns_entry 0x%" PRIx32 ", state %u", pos, entry, core_state[pos]); exceptions = lock_state_access(); switch (core_state[pos]) { case CORE_ON: rc = PSCI_RET_ALREADY_ON; break; case CORE_AWAKE: rc = PSCI_RET_ON_PENDING; break; case CORE_RET: rc = PSCI_RET_DENIED; break; case CORE_OFF: core_state[pos] = CORE_AWAKE; rc = PSCI_RET_SUCCESS; break; default: panic(); } unlock_state_access(exceptions); if (rc == PSCI_RET_SUCCESS) { boot_set_core_ns_entry(pos, entry, context_id); release_secondary_early_hpen(pos); } return rc; } /* Override default psci_cpu_off() with platform specific sequence */ int psci_cpu_off(void) { unsigned int pos = get_core_pos(); uint32_t exceptions = 0; if (pos == 0) { EMSG("PSCI_CPU_OFF not supported for core #0"); return PSCI_RET_INTERNAL_FAILURE; } DMSG("core %u", pos); exceptions = lock_state_access(); assert(core_state[pos] == CORE_ON); core_state[pos] = CORE_OFF; unlock_state_access(exceptions); /* Enable BKPREG access for the disabled CPU */ if (clk_enable(stm32mp_rcc_clock_id_to_clk(RTCAPB))) panic(); thread_mask_exceptions(THREAD_EXCP_ALL); stm32_pm_cpu_power_down_wfi(); panic(); } #endif /* Override default psci_system_off() with platform specific sequence */ void __noreturn psci_system_off(void) { DMSG("core %u", get_core_pos()); if (TRACE_LEVEL >= TRACE_DEBUG) { console_flush(); mdelay(CONSOLE_FLUSH_DELAY_MS); } if (stm32mp_with_pmic()) { stm32mp_get_pmic(); stpmic1_switch_off(); udelay(100); } panic(); } /* Override default psci_system_reset() with platform specific sequence */ void __noreturn psci_system_reset(void) { rstctrl_assert(stm32mp_rcc_reset_id_to_rstctrl(MPSYST_R)); udelay(100); panic(); } /* Override default psci_cpu_on() with platform supported features */ int psci_features(uint32_t psci_fid) { switch (psci_fid) { case ARM_SMCCC_VERSION: case PSCI_PSCI_FEATURES: case PSCI_SYSTEM_RESET: case PSCI_VERSION: return PSCI_RET_SUCCESS; case PSCI_CPU_ON: case PSCI_CPU_OFF: if (CFG_TEE_CORE_NB_CORE > 1) return PSCI_RET_SUCCESS; return PSCI_RET_NOT_SUPPORTED; case PSCI_SYSTEM_OFF: if (stm32mp_with_pmic()) return PSCI_RET_SUCCESS; return PSCI_RET_NOT_SUPPORTED; default: return PSCI_RET_NOT_SUPPORTED; } } /* Override default psci_version() to enable PSCI_VERSION_1_0 API */ uint32_t psci_version(void) { return PSCI_VERSION_1_0; } optee_os-4.3.0/core/arch/arm/plat-stm32mp1/pm/sub.mk000066400000000000000000000000411464416617300220500ustar00rootroot00000000000000srcs-$(CFG_PSCI_ARM32) += psci.c optee_os-4.3.0/core/arch/arm/plat-stm32mp1/reset.S000066400000000000000000000006671464416617300215760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2018, STMicroelectronics */ #include #include #include .section .text .balign 4 .code 32 #define STM32MP1_NSACR_PRESERVE_MASK (0xfff << 20) FUNC plat_cpu_reset_early , : ldr r0, =SCR_SIF write_scr r0 read_nsacr r0 mov_imm r1, STM32MP1_NSACR_PRESERVE_MASK and r0, r0, r1 write_nsacr r0 isb bx lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-stm32mp1/scmi_server.c000066400000000000000000000571151464416617300230150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2022, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TIMEOUT_US_1MS 1000 #define SCMI_CLOCK_NAME_SIZE 16 #define SCMI_RD_NAME_SIZE 16 #define SCMI_VOLTD_NAME_SIZE 16 /* * struct stm32_scmi_clk - Data for the exposed clock * @clock_id: Clock identifier in RCC clock driver * @name: Clock string ID exposed to channel * @enabled: State of the SCMI clock */ struct stm32_scmi_clk { unsigned long clock_id; struct clk *clk; const char *name; bool enabled; }; /* * struct stm32_scmi_rd - Data for the exposed reset controller * @reset_id: Reset identifier in RCC reset driver * @name: Reset string ID exposed to channel * @rstctrl: Reset controller device */ struct stm32_scmi_rd { unsigned long reset_id; const char *name; struct rstctrl *rstctrl; }; enum voltd_device { VOLTD_PWR, VOLTD_PMIC, VOLTD_VREFBUF, VOLTD_IOD, }; /* * struct stm32_scmi_voltd - Data for the exposed voltage domains * @name: Power regulator string ID exposed to channel * @priv_name: Internal string ID for the PMIC regulators * @priv_id: Internal ID for the regulator aside PMIC ones * @priv_dev: Internal ID for the device implementing the regulator * @regulator: Regulator controller device * @state: State of the SCMI voltage domain (true: enable, false: disable) */ struct stm32_scmi_voltd { const char *name; const char *priv_name; unsigned int priv_id; enum voltd_device priv_dev; struct regulator *regulator; bool state; }; #if CFG_STM32MP1_SCMI_SHM_BASE register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE, CFG_STM32MP1_SCMI_SHM_SIZE); /* Locate all non-secure SMT message buffers in last page of SYSRAM */ #define SMT_BUFFER_BASE CFG_STM32MP1_SCMI_SHM_BASE #if (SMT_BUFFER_BASE + SMT_BUF_SLOT_SIZE > \ CFG_STM32MP1_SCMI_SHM_BASE + CFG_STM32MP1_SCMI_SHM_SIZE) #error "SCMI shared memory mismatch" #endif #endif /*CFG_STM32MP1_SCMI_SHM_BASE*/ #define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \ [(_scmi_id)] = { \ .clock_id = (_id), \ .name = (_name), \ .enabled = (_init_enabled), \ } #define RESET_CELL(_scmi_id, _id, _name) \ [(_scmi_id)] = { \ .reset_id = (_id), \ .name = (_name), \ } #define VOLTD_CELL(_scmi_id, _dev_id, _priv_id, _priv_name, _name) \ [(_scmi_id)] = { \ .priv_name = (_priv_name), \ .priv_id = (_priv_id), \ .priv_dev = (_dev_id), \ .name = (_name), \ } #define VOLTD_CELL_PWR(_scmi_id, _priv_id, _name) \ VOLTD_CELL((_scmi_id), VOLTD_PWR, (_priv_id), NULL, (_name)) #define VOLTD_CELL_IOD(_scmi_id, _priv_id, _name) \ VOLTD_CELL((_scmi_id), VOLTD_IOD, (_priv_id), NULL, (_name)) #define VOLTD_CELL_VREFBUF(_scmi_id, _name) \ VOLTD_CELL((_scmi_id), VOLTD_VREFBUF, 0, NULL, (_name)) #define VOLTD_CELL_PMIC(_scmi_id, _priv_name, _name) \ VOLTD_CELL((_scmi_id), VOLTD_PMIC, 0, (_priv_name), (_name)) #ifdef CFG_STM32MP13 static struct stm32_scmi_clk stm32_scmi_clock[] = { CLOCK_CELL(CK_SCMI_HSE, CK_HSE, "ck_hse", true), CLOCK_CELL(CK_SCMI_HSI, CK_HSI, "ck_hsi", true), CLOCK_CELL(CK_SCMI_CSI, CK_CSI, "ck_csi", true), CLOCK_CELL(CK_SCMI_LSE, CK_LSE, "ck_lse", true), CLOCK_CELL(CK_SCMI_LSI, CK_LSI, "ck_lsi", true), CLOCK_CELL(CK_SCMI_HSE_DIV2, CK_HSE_DIV2, "clk-hse-div2", true), CLOCK_CELL(CK_SCMI_PLL2_Q, PLL2_Q, "pll2_q", true), CLOCK_CELL(CK_SCMI_PLL2_R, PLL2_R, "pll2_r", true), CLOCK_CELL(CK_SCMI_PLL3_P, PLL3_P, "pll3_p", true), CLOCK_CELL(CK_SCMI_PLL3_Q, PLL3_Q, "pll3_q", true), CLOCK_CELL(CK_SCMI_PLL3_R, PLL3_R, "pll3_r", true), CLOCK_CELL(CK_SCMI_PLL4_P, PLL4_P, "pll4_p", true), CLOCK_CELL(CK_SCMI_PLL4_Q, PLL4_Q, "pll4_q", true), CLOCK_CELL(CK_SCMI_PLL4_R, PLL4_R, "pll4_r", true), CLOCK_CELL(CK_SCMI_MPU, CK_MPU, "ck_mpu", true), CLOCK_CELL(CK_SCMI_AXI, CK_AXI, "ck_axi", true), CLOCK_CELL(CK_SCMI_MLAHB, CK_MLAHB, "ck_mlahb", true), CLOCK_CELL(CK_SCMI_CKPER, CK_PER, "ck_per", true), CLOCK_CELL(CK_SCMI_PCLK1, PCLK1, "pclk1", true), CLOCK_CELL(CK_SCMI_PCLK2, PCLK2, "pclk2", true), CLOCK_CELL(CK_SCMI_PCLK3, PCLK3, "pclk3", true), CLOCK_CELL(CK_SCMI_PCLK4, PCLK4, "pclk4", true), CLOCK_CELL(CK_SCMI_PCLK5, PCLK5, "pclk5", true), CLOCK_CELL(CK_SCMI_PCLK6, PCLK6, "pclk6", true), CLOCK_CELL(CK_SCMI_CKTIMG1, CK_TIMG1, "timg1_ck", true), CLOCK_CELL(CK_SCMI_CKTIMG2, CK_TIMG2, "timg2_ck", true), CLOCK_CELL(CK_SCMI_CKTIMG3, CK_TIMG3, "timg3_ck", true), CLOCK_CELL(CK_SCMI_RTC, RTC, "ck_rtc", true), CLOCK_CELL(CK_SCMI_RTCAPB, RTCAPB, "rtcapb", true), CLOCK_CELL(CK_SCMI_BSEC, BSEC, "bsec", true), }; #endif #ifdef CFG_STM32MP15 static struct stm32_scmi_clk stm32_scmi_clock[] = { CLOCK_CELL(CK_SCMI_HSE, CK_HSE, "ck_hse", true), CLOCK_CELL(CK_SCMI_HSI, CK_HSI, "ck_hsi", true), CLOCK_CELL(CK_SCMI_CSI, CK_CSI, "ck_csi", true), CLOCK_CELL(CK_SCMI_LSE, CK_LSE, "ck_lse", true), CLOCK_CELL(CK_SCMI_LSI, CK_LSI, "ck_lsi", true), CLOCK_CELL(CK_SCMI_PLL2_Q, PLL2_Q, "pll2_q", true), CLOCK_CELL(CK_SCMI_PLL2_R, PLL2_R, "pll2_r", true), CLOCK_CELL(CK_SCMI_MPU, CK_MPU, "ck_mpu", true), CLOCK_CELL(CK_SCMI_AXI, CK_AXI, "ck_axi", true), CLOCK_CELL(CK_SCMI_BSEC, BSEC, "bsec", true), CLOCK_CELL(CK_SCMI_CRYP1, CRYP1, "cryp1", false), CLOCK_CELL(CK_SCMI_GPIOZ, GPIOZ, "gpioz", false), CLOCK_CELL(CK_SCMI_HASH1, HASH1, "hash1", false), CLOCK_CELL(CK_SCMI_I2C4, I2C4_K, "i2c4_k", false), CLOCK_CELL(CK_SCMI_I2C6, I2C6_K, "i2c6_k", false), CLOCK_CELL(CK_SCMI_IWDG1, IWDG1, "iwdg1", false), CLOCK_CELL(CK_SCMI_RNG1, RNG1_K, "rng1_k", true), CLOCK_CELL(CK_SCMI_RTC, RTC, "ck_rtc", true), CLOCK_CELL(CK_SCMI_RTCAPB, RTCAPB, "rtcapb", true), CLOCK_CELL(CK_SCMI_SPI6, SPI6_K, "spi6_k", false), CLOCK_CELL(CK_SCMI_USART1, USART1_K, "usart1_k", false), }; #endif #ifdef CFG_STM32MP13 static struct stm32_scmi_rd stm32_scmi_reset_domain[] = { RESET_CELL(RST_SCMI_LTDC, LTDC_R, "ltdc"), RESET_CELL(RST_SCMI_MDMA, MDMA_R, "mdma"), }; #endif #ifdef CFG_STM32MP15 static struct stm32_scmi_rd stm32_scmi_reset_domain[] = { RESET_CELL(RST_SCMI_SPI6, SPI6_R, "spi6"), RESET_CELL(RST_SCMI_I2C4, I2C4_R, "i2c4"), RESET_CELL(RST_SCMI_I2C6, I2C6_R, "i2c6"), RESET_CELL(RST_SCMI_USART1, USART1_R, "usart1"), RESET_CELL(RST_SCMI_STGEN, STGEN_R, "stgen"), RESET_CELL(RST_SCMI_GPIOZ, GPIOZ_R, "gpioz"), RESET_CELL(RST_SCMI_CRYP1, CRYP1_R, "cryp1"), RESET_CELL(RST_SCMI_HASH1, HASH1_R, "hash1"), RESET_CELL(RST_SCMI_RNG1, RNG1_R, "rng1"), RESET_CELL(RST_SCMI_MDMA, MDMA_R, "mdma"), RESET_CELL(RST_SCMI_MCU, MCU_R, "mcu"), RESET_CELL(RST_SCMI_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"), }; #endif #ifdef CFG_STM32MP13 struct stm32_scmi_voltd scmi_voltage_domain[] = { VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"), VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"), VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"), VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC1_IO, IOD_SDMMC1, "sdmmc1"), VOLTD_CELL_IOD(VOLTD_SCMI_SDMMC2_IO, IOD_SDMMC2, "sdmmc2"), VOLTD_CELL_VREFBUF(VOLTD_SCMI_VREFBUF, "vrefbuf"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "buck1"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "buck2"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "buck3"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "buck4"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "ldo1"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "ldo2"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "ldo3"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "ldo4"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "ldo5"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "ldo6"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "pwr_sw1"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "pwr_sw2"), }; #endif #ifdef CFG_STM32MP15 struct stm32_scmi_voltd scmi_voltage_domain[] = { VOLTD_CELL_PWR(VOLTD_SCMI_REG11, PWR_REG11, "reg11"), VOLTD_CELL_PWR(VOLTD_SCMI_REG18, PWR_REG18, "reg18"), VOLTD_CELL_PWR(VOLTD_SCMI_USB33, PWR_USB33, "usb33"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK1, "buck1", "vddcore"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK2, "buck2", "vdd_ddr"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK3, "buck3", "vdd"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BUCK4, "buck4", "v3v3"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO1, "ldo1", "v1v8_audio"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO2, "ldo2", "v3v3_hdmi"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO3, "ldo3", "vtt_ddr"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO4, "ldo4", "vdd_usb"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO5, "ldo5", "vdda"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_LDO6, "ldo6", "v1v2_hdmi"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_VREFDDR, "vref_ddr", "vref_ddr"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_BOOST, "boost", "bst_out"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW1, "pwr_sw1", "vbus_otg"), VOLTD_CELL_PMIC(VOLTD_SCMI_STPMIC1_PWR_SW2, "pwr_sw2", "vbus_sw"), }; #endif struct channel_resources { struct scmi_msg_channel *channel; struct stm32_scmi_clk *clock; size_t clock_count; struct stm32_scmi_rd *rd; size_t rd_count; struct stm32_scmi_voltd *voltd; size_t voltd_count; }; static const struct channel_resources scmi_channel[] = { [0] = { .channel = &(struct scmi_msg_channel){ #ifdef SMT_BUFFER_BASE .shm_addr = { .pa = SMT_BUFFER_BASE }, .shm_size = SMT_BUF_SLOT_SIZE, #endif }, .clock = stm32_scmi_clock, .clock_count = ARRAY_SIZE(stm32_scmi_clock), .rd = stm32_scmi_reset_domain, .rd_count = ARRAY_SIZE(stm32_scmi_reset_domain), .voltd = scmi_voltage_domain, .voltd_count = ARRAY_SIZE(scmi_voltage_domain), }, }; static const struct channel_resources *find_resource(unsigned int channel_id) { assert(channel_id < ARRAY_SIZE(scmi_channel)); return scmi_channel + channel_id; } struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id) { const size_t max_id = ARRAY_SIZE(scmi_channel); unsigned int confined_id = confine_array_index(channel_id, max_id); if (channel_id >= max_id) return NULL; return find_resource(confined_id)->channel; } static size_t __maybe_unused plat_scmi_protocol_count_paranoid(void) { unsigned int n = 0; unsigned int count = 0; const size_t channel_count = ARRAY_SIZE(scmi_channel); for (n = 0; n < channel_count; n++) if (scmi_channel[n].clock_count) break; if (n < channel_count) count++; for (n = 0; n < channel_count; n++) if (scmi_channel[n].rd_count) break; if (n < channel_count) count++; for (n = 0; n < channel_count; n++) if (scmi_channel[n].voltd_count) break; if (n < channel_count) count++; return count; } static const char vendor[] = "ST"; static const char sub_vendor[] = ""; const char *plat_scmi_vendor_name(void) { return vendor; } const char *plat_scmi_sub_vendor_name(void) { return sub_vendor; } /* Currently supporting Clocks and Reset Domains */ static const uint8_t plat_protocol_list[] = { SCMI_PROTOCOL_ID_CLOCK, SCMI_PROTOCOL_ID_RESET_DOMAIN, SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, 0 /* Null termination */ }; size_t plat_scmi_protocol_count(void) { const size_t count = ARRAY_SIZE(plat_protocol_list) - 1; assert(count == plat_scmi_protocol_count_paranoid()); return count; } const uint8_t *plat_scmi_protocol_list(unsigned int channel_id __unused) { assert(plat_scmi_protocol_count_paranoid() == (ARRAY_SIZE(plat_protocol_list) - 1)); return plat_protocol_list; } /* * Platform SCMI clocks */ static struct stm32_scmi_clk *find_clock(unsigned int channel_id, unsigned int scmi_id) { const struct channel_resources *resource = find_resource(channel_id); size_t n = 0; if (resource) { for (n = 0; n < resource->clock_count; n++) if (n == scmi_id) return &resource->clock[n]; } return NULL; } size_t plat_scmi_clock_count(unsigned int channel_id) { const struct channel_resources *resource = find_resource(channel_id); if (!resource) return 0; return resource->clock_count; } const char *plat_scmi_clock_get_name(unsigned int channel_id, unsigned int scmi_id) { struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id)) return NULL; return clock->name; } int32_t plat_scmi_clock_rates_array(unsigned int channel_id, unsigned int scmi_id, size_t start_index, unsigned long *array, size_t *nb_elts) { struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); if (!clock) return SCMI_NOT_FOUND; if (!stm32mp_nsec_can_access_clock(clock->clock_id)) return SCMI_DENIED; /* Exposed clocks are currently fixed rate clocks */ if (start_index) return SCMI_INVALID_PARAMETERS; if (!array) *nb_elts = 1; else if (*nb_elts == 1) *array = clk_get_rate(clock->clk); else return SCMI_GENERIC_ERROR; return SCMI_SUCCESS; } unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, unsigned int scmi_id) { struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id)) return 0; return clk_get_rate(clock->clk); } int32_t plat_scmi_clock_get_state(unsigned int channel_id, unsigned int scmi_id) { struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id)) return 0; return (int32_t)clock->enabled; } int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, bool enable_not_disable) { struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id); if (!clock) return SCMI_NOT_FOUND; if (!stm32mp_nsec_can_access_clock(clock->clock_id)) return SCMI_DENIED; if (enable_not_disable) { if (!clock->enabled) { FMSG("SCMI clock %u enable", scmi_id); clk_enable(clock->clk); clock->enabled = true; } } else { if (clock->enabled) { FMSG("SCMI clock %u disable", scmi_id); clk_disable(clock->clk); clock->enabled = false; } } return SCMI_SUCCESS; } /* * Platform SCMI reset domains */ static struct stm32_scmi_rd *find_rd(unsigned int channel_id, unsigned int scmi_id) { const struct channel_resources *resource = find_resource(channel_id); size_t n = 0; if (resource) { for (n = 0; n < resource->rd_count; n++) if (n == scmi_id) return &resource->rd[n]; } return NULL; } const char *plat_scmi_rd_get_name(unsigned int channel_id, unsigned int scmi_id) { const struct stm32_scmi_rd *rd = find_rd(channel_id, scmi_id); if (!rd) return NULL; return rd->name; } size_t plat_scmi_rd_count(unsigned int channel_id) { const struct channel_resources *resource = find_resource(channel_id); if (!resource) return 0; return resource->rd_count; } int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id, uint32_t state) { const struct stm32_scmi_rd *rd = find_rd(channel_id, scmi_id); if (!rd) return SCMI_NOT_FOUND; if (!rd->rstctrl || !stm32mp_nsec_can_access_reset(rd->reset_id)) return SCMI_DENIED; assert(rd->rstctrl); #ifdef CFG_STM32MP15 if (rd->reset_id == MCU_HOLD_BOOT_R) return SCMI_NOT_SUPPORTED; #endif /* Supports only reset with context loss */ if (state) return SCMI_NOT_SUPPORTED; FMSG("SCMI reset %u cycle", scmi_id); if (rstctrl_assert_to(rd->rstctrl, TIMEOUT_US_1MS)) return SCMI_HARDWARE_ERROR; if (rstctrl_deassert_to(rd->rstctrl, TIMEOUT_US_1MS)) return SCMI_HARDWARE_ERROR; return SCMI_SUCCESS; } int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, bool assert_not_deassert) { const struct stm32_scmi_rd *rd = find_rd(channel_id, scmi_id); TEE_Result res = TEE_ERROR_GENERIC; if (!rd) return SCMI_NOT_FOUND; if (!rd->rstctrl || !stm32mp_nsec_can_access_reset(rd->reset_id)) return SCMI_DENIED; assert(rd->rstctrl); if (assert_not_deassert) { FMSG("SCMI reset %u set", scmi_id); res = rstctrl_assert(rd->rstctrl); } else { FMSG("SCMI reset %u release", scmi_id); res = rstctrl_deassert(rd->rstctrl); } if (res) return SCMI_HARDWARE_ERROR; return SCMI_SUCCESS; } /* * Platform SCMI voltage domains */ static struct stm32_scmi_voltd *find_voltd(unsigned int channel_id, unsigned int scmi_id) { const struct channel_resources *resource = find_resource(channel_id); size_t n = 0; if (resource) { for (n = 0; n < resource->voltd_count; n++) if (n == scmi_id) return &resource->voltd[n]; } return NULL; } size_t plat_scmi_voltd_count(unsigned int channel_id) { const struct channel_resources *resource = find_resource(channel_id); if (!resource) return 0; return resource->voltd_count; } const char *plat_scmi_voltd_get_name(unsigned int channel_id, unsigned int scmi_id) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); /* Currently non-secure is allowed to access all PWR regulators */ if (!voltd) return NULL; return voltd->name; } int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, unsigned int scmi_id, size_t start_index, long *out_levels, size_t *nb_elts) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); if (!voltd) return SCMI_NOT_FOUND; if (voltd->regulator) { struct regulator_voltages_desc *desc = NULL; TEE_Result res = TEE_ERROR_GENERIC; const int *levels = NULL; size_t n = 0; res = regulator_supported_voltages(voltd->regulator, &desc, &levels); if (res == TEE_ERROR_NOT_SUPPORTED) return SCMI_NOT_SUPPORTED; if (res) return SCMI_GENERIC_ERROR; if (!desc || desc->type != VOLTAGE_TYPE_FULL_LIST) { /* * Triplet min/max/step description. Caller should use * plat_scmi_voltd_levels_by_step(). */ return SCMI_NOT_SUPPORTED; } if (start_index >= desc->num_levels) return SCMI_OUT_OF_RANGE; if (!*nb_elts) { *nb_elts = desc->num_levels - start_index; return SCMI_SUCCESS; } *nb_elts = MIN(*nb_elts, desc->num_levels - start_index); for (n = 0; n < *nb_elts; n++) out_levels[n] = levels[start_index + n]; return SCMI_SUCCESS; } return SCMI_DENIED; } int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, unsigned int scmi_id, long *min_max_step) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); if (!voltd) return SCMI_NOT_FOUND; if (voltd->regulator) { struct regulator_voltages_desc *desc = NULL; TEE_Result res = TEE_ERROR_GENERIC; const int *levels = NULL; res = regulator_supported_voltages(voltd->regulator, &desc, &levels); if (res == TEE_ERROR_NOT_SUPPORTED) return SCMI_NOT_SUPPORTED; if (res) return SCMI_GENERIC_ERROR; if (!desc || desc->type != VOLTAGE_TYPE_INCREMENT) { /* * Triplet min/max/step description. Caller should use * plat_scmi_voltd_levels_by_step(). */ return SCMI_NOT_SUPPORTED; } min_max_step[0] = levels[0]; min_max_step[1] = levels[1]; min_max_step[2] = levels[2]; return SCMI_SUCCESS; } return SCMI_NOT_SUPPORTED; } int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, long *level_uv) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); if (!voltd) return SCMI_INVALID_PARAMETERS; if (voltd->regulator) { *level_uv = regulator_get_voltage(voltd->regulator); return SCMI_SUCCESS; } return SCMI_DENIED; } int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, long level_uv) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); if (!voltd) return SCMI_NOT_FOUND; if (voltd->regulator) { TEE_Result res = TEE_ERROR_GENERIC; if (level_uv < INT_MIN || level_uv > INT_MAX) return SCMI_OUT_OF_RANGE; res = regulator_set_voltage(voltd->regulator, level_uv); if (res) return SCMI_GENERIC_ERROR; else return SCMI_SUCCESS; } return SCMI_DENIED; } int32_t plat_scmi_voltd_get_config(unsigned int channel_id, unsigned int scmi_id, uint32_t *config) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); if (!voltd) return SCMI_NOT_FOUND; if (voltd->regulator) { if (voltd->state) *config = SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON; else *config = SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF; return SCMI_SUCCESS; } return SCMI_DENIED; } int32_t plat_scmi_voltd_set_config(unsigned int channel_id, unsigned int scmi_id, uint32_t config) { struct stm32_scmi_voltd *voltd = find_voltd(channel_id, scmi_id); if (!voltd) return SCMI_NOT_FOUND; if (voltd->regulator) { switch (config) { case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON: if (!voltd->state) { if (regulator_enable(voltd->regulator)) return SCMI_GENERIC_ERROR; voltd->state = true; } break; case SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF: if (voltd->state) { if (regulator_disable(voltd->regulator)) return SCMI_GENERIC_ERROR; voltd->state = false; } break; default: return SCMI_INVALID_PARAMETERS; } return SCMI_SUCCESS; } return SCMI_DENIED; } static void get_voltd_regulator(struct stm32_scmi_voltd *voltd) { switch (voltd->priv_dev) { case VOLTD_PWR: voltd->regulator = stm32mp1_pwr_get_regulator(voltd->priv_id); break; case VOLTD_PMIC: voltd->regulator = stm32mp_pmic_get_regulator(voltd->priv_name); break; case VOLTD_VREFBUF: voltd->regulator = stm32_vrefbuf_regulator(); break; case VOLTD_IOD: voltd->regulator = stm32mp1_get_iod_regulator(voltd->priv_id); break; default: break; } if (voltd->regulator && voltd->regulator->flags & REGULATOR_BOOT_ON) regulator_enable(voltd->regulator); } /* * Initialize platform SCMI resources */ static TEE_Result stm32mp1_init_scmi_server(void) { size_t i = 0; size_t j = 0; for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) { const struct channel_resources *res = scmi_channel + i; struct scmi_msg_channel *chan = res->channel; if (chan->shm_addr.pa) { struct io_pa_va *addr = &chan->shm_addr; /* Enforce non-secure shm mapped as device memory */ addr->va = (vaddr_t)phys_to_virt(addr->pa, MEM_AREA_IO_NSEC, chan->shm_size); assert(addr->va); scmi_smt_init_agent_channel(chan); } for (j = 0; j < res->clock_count; j++) { struct stm32_scmi_clk *clk = &res->clock[j]; if (!clk->name || strlen(clk->name) >= SCMI_CLOCK_NAME_SIZE) panic("SCMI clock name invalid"); clk->clk = stm32mp_rcc_clock_id_to_clk(clk->clock_id); assert(clk->clk); /* Sync SCMI clocks with their targeted initial state */ if (clk->enabled && stm32mp_nsec_can_access_clock(clk->clock_id)) clk_enable(clk->clk); } for (j = 0; j < res->rd_count; j++) { struct stm32_scmi_rd *rd = &res->rd[j]; struct rstctrl *rstctrl = NULL; if (!rd->name || strlen(rd->name) >= SCMI_RD_NAME_SIZE) panic("SCMI reset domain name invalid"); if (stm32mp_nsec_can_access_clock(rd->reset_id)) continue; rstctrl = stm32mp_rcc_reset_id_to_rstctrl(rd->reset_id); assert(rstctrl); if (rstctrl_get_exclusive(rstctrl)) continue; rd->rstctrl = rstctrl; } for (j = 0; j < res->voltd_count; j++) { struct stm32_scmi_voltd *voltd = &res->voltd[j]; if (!voltd->name || strlen(voltd->name) >= SCMI_VOLTD_NAME_SIZE) panic("SCMI voltage domain name invalid"); get_voltd_regulator(voltd); } } return TEE_SUCCESS; } driver_init_late(stm32mp1_init_scmi_server); optee_os-4.3.0/core/arch/arm/plat-stm32mp1/scripts/000077500000000000000000000000001464416617300220065ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp1/scripts/stm32image.py000077500000000000000000000066471464416617300243530ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017-2018, STMicroelectronics # import argparse import struct import mmap header_size = 256 hdr_magic_number = 0x324D5453 # magic ='S' 'T' 'M' 0x32 hdr_header_ver_variant = 0 hdr_header_ver_minor = 0 hdr_header_ver_major = 1 hdr_version_number = 0 hdr_option_flags = 1 # bit0=1 no signature hdr_edcsa_algo = 1 def get_size(file): file.seek(0, 2) # End of the file size = file.tell() return size def stm32image_checksum(dest_fd, sizedest): csum = 0 if sizedest < header_size: return 0 dest_fd.seek(header_size, 0) length = sizedest - header_size while length > 0: csum += ord(dest_fd.read(1)) length -= 1 return csum def stm32image_set_header(dest_fd, load, entry, bintype): sizedest = get_size(dest_fd) checksum = stm32image_checksum(dest_fd, sizedest) dest_fd.seek(0, 0) # Magic number dest_fd.write(struct.pack(' 0: mmsrc = mmap.mmap(src_fd.fileno(), 0, access=mmap.ACCESS_READ) dest_fd.write(mmsrc[:sizesrc]) mmsrc.close() src_fd.close() stm32image_set_header(dest_fd, load, entry, bintype) dest_fd.close() def int_parse(str): return int(str, 0) def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--source', required=True, help='Source file') parser.add_argument('--dest', required=True, help='Destination file') parser.add_argument('--load', required=True, type=int_parse, help='Load address') parser.add_argument('--entry', required=True, type=int_parse, help='Entry point') parser.add_argument('--bintype', required=True, type=int_parse, help='Binary identification') return parser.parse_args() def main(): args = get_args() source_file = args.source destination_file = args.dest load_address = args.load entry_point = args.entry binary_type = args.bintype stm32image_create_header_file(source_file, destination_file, load_address, entry_point, binary_type) if __name__ == "__main__": main() optee_os-4.3.0/core/arch/arm/plat-stm32mp1/shared_resources.c000066400000000000000000000440751464416617300240350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2017-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Once one starts to get the resource registering state, one cannot register * new resources. This ensures resource state cannot change. */ static bool registering_locked; /* * Shared peripherals and resources registration * * Each resource assignation is stored in a table. The state defaults * to PERIPH_UNREGISTERED if the resource is not explicitly assigned. * * Resource driver that as not embedded (a.k.a their related CFG_xxx build * directive is disabled) are assigned to the non-secure world. * * Each IO of the GPIOZ IO can be secure or non-secure. * * It is the platform responsibility the ensure resource assignation * matches the access permission firewalls configuration. */ enum shres_state { SHRES_UNREGISTERED = 0, SHRES_SECURE, SHRES_NON_SECURE, }; /* Use a byte array to store each resource state */ static uint8_t shres_state[STM32MP1_SHRES_COUNT] = { #if !defined(CFG_STM32_IWDG) [STM32MP1_SHRES_IWDG1] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_UART) [STM32MP1_SHRES_USART1] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_SPI) [STM32MP1_SHRES_SPI6] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_I2C) [STM32MP1_SHRES_I2C4] = SHRES_NON_SECURE, [STM32MP1_SHRES_I2C6] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_GPIO) [STM32MP1_SHRES_GPIOZ(0)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(1)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(2)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(3)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(4)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(5)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(6)] = SHRES_NON_SECURE, [STM32MP1_SHRES_GPIOZ(7)] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_RNG) [STM32MP1_SHRES_RNG1] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_HASH) [STM32MP1_SHRES_HASH1] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_CRYP) [STM32MP1_SHRES_CRYP1] = SHRES_NON_SECURE, #endif #if !defined(CFG_STM32_RTC) [STM32MP1_SHRES_RTC] = SHRES_NON_SECURE, #endif }; static const char __maybe_unused *shres2str_id_tbl[STM32MP1_SHRES_COUNT] = { [STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0", [STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1", [STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2", [STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3", [STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4", [STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5", [STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6", [STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7", [STM32MP1_SHRES_IWDG1] = "IWDG1", [STM32MP1_SHRES_USART1] = "USART1", [STM32MP1_SHRES_SPI6] = "SPI6", [STM32MP1_SHRES_I2C4] = "I2C4", [STM32MP1_SHRES_RNG1] = "RNG1", [STM32MP1_SHRES_HASH1] = "HASH1", [STM32MP1_SHRES_CRYP1] = "CRYP1", [STM32MP1_SHRES_I2C6] = "I2C6", [STM32MP1_SHRES_RTC] = "RTC", [STM32MP1_SHRES_MCU] = "MCU", [STM32MP1_SHRES_PLL3] = "PLL3", [STM32MP1_SHRES_MDMA] = "MDMA", [STM32MP1_SHRES_SRAM1] = "SRAM1", [STM32MP1_SHRES_SRAM2] = "SRAM2", [STM32MP1_SHRES_SRAM3] = "SRAM3", [STM32MP1_SHRES_SRAM4] = "SRAM4", }; static __maybe_unused const char *shres2str_id(enum stm32mp_shres id) { return shres2str_id_tbl[id]; } static const char *shres2str_state_tbl[4] __maybe_unused = { [SHRES_UNREGISTERED] = "unregistered", [SHRES_NON_SECURE] = "non-secure", [SHRES_SECURE] = "secure", }; static __maybe_unused const char *shres2str_state(enum shres_state id) { return shres2str_state_tbl[id]; } /* GPIOZ bank pin count depends on SoC variants */ /* A light count routine for unpaged context to not depend on DTB support */ static int gpioz_nbpin = -1; static unsigned int get_gpioz_nbpin(void) { if (gpioz_nbpin < 0) panic(); return gpioz_nbpin; } void stm32mp_register_gpioz_pin_count(size_t count) { assert(gpioz_nbpin == -1); gpioz_nbpin = count; } static void register_periph(enum stm32mp_shres id, enum shres_state state) { assert(id < STM32MP1_SHRES_COUNT && (state == SHRES_SECURE || state == SHRES_NON_SECURE)); if (registering_locked) panic(); if (shres_state[id] != SHRES_UNREGISTERED && shres_state[id] != state) { DMSG("Cannot change %s from %s to %s", shres2str_id(id), shres2str_state(shres_state[id]), shres2str_state(state)); panic(); } if (shres_state[id] == SHRES_UNREGISTERED) DMSG("Register %s as %s", shres2str_id(id), shres2str_state(state)); switch (id) { case STM32MP1_SHRES_GPIOZ(0): case STM32MP1_SHRES_GPIOZ(1): case STM32MP1_SHRES_GPIOZ(2): case STM32MP1_SHRES_GPIOZ(3): case STM32MP1_SHRES_GPIOZ(4): case STM32MP1_SHRES_GPIOZ(5): case STM32MP1_SHRES_GPIOZ(6): case STM32MP1_SHRES_GPIOZ(7): if ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin()) { EMSG("Invalid GPIO %u >= %u", id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin()); panic(); } break; default: break; } shres_state[id] = state; /* Explore clock tree to lock secure clock dependencies */ if (state == SHRES_SECURE) { switch (id) { case STM32MP1_SHRES_GPIOZ(0): case STM32MP1_SHRES_GPIOZ(1): case STM32MP1_SHRES_GPIOZ(2): case STM32MP1_SHRES_GPIOZ(3): case STM32MP1_SHRES_GPIOZ(4): case STM32MP1_SHRES_GPIOZ(5): case STM32MP1_SHRES_GPIOZ(6): case STM32MP1_SHRES_GPIOZ(7): stm32mp_register_clock_parents_secure(GPIOZ); break; case STM32MP1_SHRES_IWDG1: stm32mp_register_clock_parents_secure(IWDG1); break; case STM32MP1_SHRES_USART1: stm32mp_register_clock_parents_secure(USART1_K); break; case STM32MP1_SHRES_SPI6: stm32mp_register_clock_parents_secure(SPI6_K); break; case STM32MP1_SHRES_I2C4: stm32mp_register_clock_parents_secure(I2C4_K); break; case STM32MP1_SHRES_RNG1: stm32mp_register_clock_parents_secure(RNG1_K); break; case STM32MP1_SHRES_HASH1: stm32mp_register_clock_parents_secure(HASH1); break; case STM32MP1_SHRES_CRYP1: stm32mp_register_clock_parents_secure(CRYP1); break; case STM32MP1_SHRES_I2C6: stm32mp_register_clock_parents_secure(I2C6_K); break; case STM32MP1_SHRES_RTC: stm32mp_register_clock_parents_secure(RTC); break; default: /* No expected resource dependency */ break; } } } /* Register resource by ID */ void stm32mp_register_secure_periph(enum stm32mp_shres id) { register_periph(id, SHRES_SECURE); } void stm32mp_register_non_secure_periph(enum stm32mp_shres id) { register_periph(id, SHRES_NON_SECURE); } /* Register resource by IO memory base address */ static void register_periph_iomem(vaddr_t base, enum shres_state state) { enum stm32mp_shres id = STM32MP1_SHRES_COUNT; switch (base) { case IWDG1_BASE: id = STM32MP1_SHRES_IWDG1; break; case USART1_BASE: id = STM32MP1_SHRES_USART1; break; case SPI6_BASE: id = STM32MP1_SHRES_SPI6; break; case I2C4_BASE: id = STM32MP1_SHRES_I2C4; break; case I2C6_BASE: id = STM32MP1_SHRES_I2C6; break; case RTC_BASE: id = STM32MP1_SHRES_RTC; break; case RNG1_BASE: id = STM32MP1_SHRES_RNG1; break; case CRYP1_BASE: id = STM32MP1_SHRES_CRYP1; break; case HASH1_BASE: id = STM32MP1_SHRES_HASH1; break; case SRAM1_BASE: id = STM32MP1_SHRES_SRAM1; break; case SRAM2_BASE: id = STM32MP1_SHRES_SRAM2; break; case SRAM3_BASE: id = STM32MP1_SHRES_SRAM3; break; case SRAM4_BASE: id = STM32MP1_SHRES_SRAM4; break; /* Always non-secure resource cases */ #ifdef CFG_WITH_NSEC_GPIOS case GPIOA_BASE: case GPIOB_BASE: case GPIOC_BASE: case GPIOD_BASE: case GPIOE_BASE: case GPIOF_BASE: case GPIOG_BASE: case GPIOH_BASE: case GPIOI_BASE: case GPIOJ_BASE: case GPIOK_BASE: fallthrough; #endif #ifdef CFG_WITH_NSEC_UARTS case USART2_BASE: case USART3_BASE: case UART4_BASE: case UART5_BASE: case USART6_BASE: case UART7_BASE: case UART8_BASE: fallthrough; #endif #ifdef CFG_WITH_NSEC_I2CS case I2C5_BASE: fallthrough; #endif case IWDG2_BASE: /* Allow drivers to register some non-secure resources */ DMSG("IO for non-secure resource 0x%lx", base); if (state != SHRES_NON_SECURE) panic(); return; default: panic(); break; } register_periph(id, state); } void stm32mp_register_secure_periph_iomem(vaddr_t base) { register_periph_iomem(base, SHRES_SECURE); } void stm32mp_register_non_secure_periph_iomem(vaddr_t base) { register_periph_iomem(base, SHRES_NON_SECURE); } /* Register GPIO resource */ void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin) { switch (bank) { case GPIO_BANK_Z: assert(pin < get_gpioz_nbpin()); register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE); break; default: EMSG("GPIO bank %u cannot be secured", bank); panic(); } } void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) { switch (bank) { case GPIO_BANK_Z: assert(pin < get_gpioz_nbpin()); register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE); break; default: break; } } void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl) { unsigned int *bank = NULL; unsigned int *pin = NULL; size_t count = 0; size_t n = 0; stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count); if (!count) return; bank = calloc(count, sizeof(*bank)); pin = calloc(count, sizeof(*pin)); if (!bank || !pin) panic(); stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count); for (n = 0; n < count; n++) stm32mp_register_secure_gpio(bank[n], pin[n]); free(bank); free(pin); } void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl) { unsigned int *bank = NULL; unsigned int *pin = NULL; size_t count = 0; size_t n = 0; stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count); if (!count) return; bank = calloc(count, sizeof(*bank)); pin = calloc(count, sizeof(*pin)); if (!bank || !pin) panic(); stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count); for (n = 0; n < count; n++) stm32mp_register_non_secure_gpio(bank[n], pin[n]); free(bank); free(pin); } static void lock_registering(void) { registering_locked = true; } bool stm32mp_periph_is_secure(enum stm32mp_shres id) { lock_registering(); return shres_state[id] == SHRES_SECURE; } bool stm32mp_gpio_bank_is_non_secure(unsigned int bank) { unsigned int not_secure = 0; unsigned int pin = 0; lock_registering(); if (bank != GPIO_BANK_Z) return true; for (pin = 0; pin < get_gpioz_nbpin(); pin++) if (!stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin))) not_secure++; return not_secure > 0 && not_secure == get_gpioz_nbpin(); } bool stm32mp_gpio_bank_is_secure(unsigned int bank) { unsigned int secure = 0; unsigned int pin = 0; lock_registering(); if (bank != GPIO_BANK_Z) return false; for (pin = 0; pin < get_gpioz_nbpin(); pin++) if (stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin))) secure++; return secure > 0 && secure == get_gpioz_nbpin(); } bool stm32mp_nsec_can_access_clock(unsigned long clock_id) { enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; /* Oscillators and PLLs are visible from non-secure world */ COMPILE_TIME_ASSERT(CK_HSE == 0 && (CK_HSE + 1) == CK_CSI && (CK_HSE + 2) == CK_LSI && (CK_HSE + 3) == CK_LSE && (CK_HSE + 4) == CK_HSI && (CK_HSE + 5) == CK_HSE_DIV2 && (PLL1_P + 1) == PLL1_Q && (PLL1_P + 2) == PLL1_R && (PLL1_P + 3) == PLL2_P && (PLL1_P + 4) == PLL2_Q && (PLL1_P + 5) == PLL2_R && (PLL1_P + 6) == PLL3_P && (PLL1_P + 7) == PLL3_Q && (PLL1_P + 8) == PLL3_R); if (clock_id <= CK_HSE_DIV2 || (clock_id >= PLL1_P && clock_id <= PLL3_R)) return true; switch (clock_id) { case RTCAPB: case CK_MPU: case CK_AXI: case BSEC: return true; case GPIOZ: return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z); case SPI6_K: shres_id = STM32MP1_SHRES_SPI6; break; case I2C4_K: shres_id = STM32MP1_SHRES_I2C4; break; case I2C6_K: shres_id = STM32MP1_SHRES_I2C6; break; case USART1_K: shres_id = STM32MP1_SHRES_USART1; break; case IWDG1: shres_id = STM32MP1_SHRES_IWDG1; break; case CRYP1: shres_id = STM32MP1_SHRES_CRYP1; break; case HASH1: shres_id = STM32MP1_SHRES_HASH1; break; case RNG1_K: shres_id = STM32MP1_SHRES_RNG1; break; case RTC: shres_id = STM32MP1_SHRES_RTC; break; case CK_MCU: shres_id = STM32MP1_SHRES_MCU; break; default: return false; } return !stm32mp_periph_is_secure(shres_id); } bool stm32mp_nsec_can_access_reset(unsigned int reset_id) { enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT; switch (reset_id) { case GPIOZ_R: return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z); case SPI6_R: shres_id = STM32MP1_SHRES_SPI6; break; case I2C4_R: shres_id = STM32MP1_SHRES_I2C4; break; case I2C6_R: shres_id = STM32MP1_SHRES_I2C6; break; case USART1_R: shres_id = STM32MP1_SHRES_USART1; break; case CRYP1_R: shres_id = STM32MP1_SHRES_CRYP1; break; case HASH1_R: shres_id = STM32MP1_SHRES_HASH1; break; case RNG1_R: shres_id = STM32MP1_SHRES_RNG1; break; case MDMA_R: shres_id = STM32MP1_SHRES_MDMA; break; case MCU_R: case MCU_HOLD_BOOT_R: shres_id = STM32MP1_SHRES_MCU; break; default: return false; } return !stm32mp_periph_is_secure(shres_id); } static bool mckprot_resource(enum stm32mp_shres id) { switch (id) { case STM32MP1_SHRES_MCU: case STM32MP1_SHRES_PLL3: return true; default: return false; } } #ifdef CFG_STM32_ETZPC static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id) { if (!stm32mp_periph_is_secure(id)) return ETZPC_DECPROT_NS_RW; if (mckprot_resource(id)) return ETZPC_DECPROT_MCU_ISOLATION; return ETZPC_DECPROT_S_RW; } /* Configure ETZPC cell and lock it when resource is secure */ static void config_lock_decprot(uint32_t decprot_id, enum etzpc_decprot_attributes decprot_attr) { etzpc_configure_decprot(decprot_id, decprot_attr); if (decprot_attr == ETZPC_DECPROT_S_RW) etzpc_lock_decprot(decprot_id); } static void set_etzpc_secure_configuration(void) { /* Some peripherals shall be secure */ config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); config_lock_decprot(STM32MP1_ETZPC_DDRCTRL_ID, ETZPC_DECPROT_NS_R_S_W); config_lock_decprot(STM32MP1_ETZPC_DDRPHYC_ID, ETZPC_DECPROT_NS_R_S_W); /* Configure ETZPC with peripheral registering */ config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID, shres2decprot_attr(STM32MP1_SHRES_IWDG1)); config_lock_decprot(STM32MP1_ETZPC_USART1_ID, shres2decprot_attr(STM32MP1_SHRES_USART1)); config_lock_decprot(STM32MP1_ETZPC_SPI6_ID, shres2decprot_attr(STM32MP1_SHRES_SPI6)); config_lock_decprot(STM32MP1_ETZPC_I2C4_ID, shres2decprot_attr(STM32MP1_SHRES_I2C4)); config_lock_decprot(STM32MP1_ETZPC_RNG1_ID, shres2decprot_attr(STM32MP1_SHRES_RNG1)); config_lock_decprot(STM32MP1_ETZPC_HASH1_ID, shres2decprot_attr(STM32MP1_SHRES_HASH1)); config_lock_decprot(STM32MP1_ETZPC_CRYP1_ID, shres2decprot_attr(STM32MP1_SHRES_CRYP1)); config_lock_decprot(STM32MP1_ETZPC_I2C6_ID, shres2decprot_attr(STM32MP1_SHRES_I2C6)); config_lock_decprot(STM32MP1_ETZPC_SRAM1_ID, shres2decprot_attr(STM32MP1_SHRES_SRAM1)); config_lock_decprot(STM32MP1_ETZPC_SRAM2_ID, shres2decprot_attr(STM32MP1_SHRES_SRAM2)); config_lock_decprot(STM32MP1_ETZPC_SRAM3_ID, shres2decprot_attr(STM32MP1_SHRES_SRAM3)); config_lock_decprot(STM32MP1_ETZPC_SRAM4_ID, shres2decprot_attr(STM32MP1_SHRES_SRAM4)); } #else static void set_etzpc_secure_configuration(void) { /* Nothing to do */ } #endif static void rcc_secure_configuration(void) { bool secure = stm32_rcc_is_secure(); bool mckprot = stm32_rcc_is_mckprot(); enum stm32mp_shres id = STM32MP1_SHRES_COUNT; bool need_secure = false; bool need_mckprot = false; uint32_t state = 0; if (stm32_bsec_get_state(&state)) panic(); if (state == BSEC_STATE_SEC_CLOSED && !secure) panic("Closed device mandates secure RCC"); for (id = 0; id < STM32MP1_SHRES_COUNT; id++) { if (shres_state[id] != SHRES_SECURE) continue; /* SRAMs have no constraints on RCC configuration */ if (id == STM32MP1_SHRES_SRAM1 || id == STM32MP1_SHRES_SRAM2 || id == STM32MP1_SHRES_SRAM3 || id == STM32MP1_SHRES_SRAM4) continue; need_secure = true; if (mckprot_resource(id)) need_mckprot = true; if (!secure || (need_mckprot && !mckprot)) EMSG("Error RCC TZEN=%u MCKPROT=%u and %s (%u) secure", secure, mckprot, shres2str_id(id), id); } if ((need_secure && !secure) || (need_mckprot && !mckprot)) { if (IS_ENABLED(CFG_INSECURE)) EMSG("WARNING: CFG_INSECURE allows insecure RCC configuration"); else panic(); } if (!need_mckprot && mckprot) { DMSG("Disable RCC MCKPROT"); stm32_rcc_set_mckprot(false); } } static void set_gpio_secure_configuration(void) { unsigned int pin = 0; for (pin = 0; pin < get_gpioz_nbpin(); pin++) { enum stm32mp_shres shres = STM32MP1_SHRES_GPIOZ(pin); bool secure = stm32mp_periph_is_secure(shres); stm32_gpio_set_secure_cfg(GPIO_BANK_Z, pin, secure); } } static TEE_Result gpioz_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl __unused) { if (op == PM_OP_RESUME) set_gpio_secure_configuration(); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(gpioz_pm); static TEE_Result stm32mp1_init_final_shres(void) { enum stm32mp_shres id = STM32MP1_SHRES_COUNT; lock_registering(); for (id = (enum stm32mp_shres)0; id < STM32MP1_SHRES_COUNT; id++) { uint8_t __maybe_unused *state = &shres_state[id]; DMSG("stm32mp %-8s (%2u): %-14s", shres2str_id(id), id, shres2str_state(*state)); } set_etzpc_secure_configuration(); if (IS_ENABLED(CFG_STM32_GPIO)) { set_gpio_secure_configuration(); register_pm_driver_cb(gpioz_pm, NULL, "stm32mp1-shared-resources"); } rcc_secure_configuration(); return TEE_SUCCESS; } /* Finalize shres after drivers initialization, hence driver_init_late() */ driver_init_late(stm32mp1_init_final_shres); optee_os-4.3.0/core/arch/arm/plat-stm32mp1/stm32_util.h000066400000000000000000000214061464416617300225000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2018-2022, STMicroelectronics */ #ifndef __STM32_UTIL_H__ #define __STM32_UTIL_H__ #include #include #include #include #include #include #include #include /* Backup registers and RAM utils */ vaddr_t stm32mp_bkpreg(unsigned int idx); /* Platform util for the RCC drivers */ vaddr_t stm32_rcc_base(void); /* Platform util for the GIC */ vaddr_t get_gicd_base(void); /* Platform util for PMIC support */ bool stm32mp_with_pmic(void); /* Power management service */ #ifdef CFG_PSCI_ARM32 void stm32mp_register_online_cpu(void); #else static inline void stm32mp_register_online_cpu(void) { } #endif /* * Generic spinlock function that bypass spinlock if MMU is disabled or * lock is NULL. */ uint32_t may_spin_lock(unsigned int *lock); void may_spin_unlock(unsigned int *lock, uint32_t exceptions); /* Helper from platform RCC clock driver */ struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id); #ifdef CFG_STM32MP1_SHARED_RESOURCES /* Return true if @clock_id is shared by secure and non-secure worlds */ bool stm32mp_nsec_can_access_clock(unsigned long clock_id); #else /* CFG_STM32MP1_SHARED_RESOURCES */ static inline bool stm32mp_nsec_can_access_clock(unsigned long clock_id __unused) { return true; } #endif /* CFG_STM32MP1_SHARED_RESOURCES */ extern const struct clk_ops stm32mp1_clk_ops; #if defined(CFG_STPMIC1) /* Return true if non-secure world can manipulate regulator @pmic_regu_name */ bool stm32mp_nsec_can_access_pmic_regu(const char *pmic_regu_name); #else static inline bool stm32mp_nsec_can_access_pmic_regu(const char *name __unused) { return false; } #endif #ifdef CFG_STM32MP1_SHARED_RESOURCES /* Return true if and only if @reset_id relates to a non-secure peripheral */ bool stm32mp_nsec_can_access_reset(unsigned int reset_id); #else /* CFG_STM32MP1_SHARED_RESOURCES */ static inline bool stm32mp_nsec_can_access_reset(unsigned int reset_id __unused) { return true; } #endif /* CFG_STM32MP1_SHARED_RESOURCES */ /* Return rstctrl instance related to RCC reset controller DT binding ID */ struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id); /* * Structure and API function for BSEC driver to get some platform data. * * @base: BSEC interface registers physical base address * @upper_start: Base ID for the BSEC upper words in the platform * @max_id: Max value for BSEC word ID for the platform */ struct stm32_bsec_static_cfg { paddr_t base; unsigned int upper_start; unsigned int max_id; }; void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg); /* * Shared reference counter: increments by 2 on secure increment * request, decrements by 2 on secure decrement request. Bit #0 * is set to 1 on non-secure increment request and reset to 0 on * non-secure decrement request. These counters initialize to * either 0, 1 or 2 upon their expect default state. * Counters saturate to UINT_MAX / 2. */ #define SHREFCNT_NONSECURE_FLAG 0x1ul #define SHREFCNT_SECURE_STEP 0x2ul #define SHREFCNT_MAX (UINT_MAX / 2) /* Return 1 if refcnt increments from 0, else return 0 */ static inline int incr_shrefcnt(unsigned int *refcnt, bool secure) { int rc = !*refcnt; if (secure) { if (*refcnt < SHREFCNT_MAX) { *refcnt += SHREFCNT_SECURE_STEP; assert(*refcnt < SHREFCNT_MAX); } } else { *refcnt |= SHREFCNT_NONSECURE_FLAG; } return rc; } /* Return 1 if refcnt decrements to 0, else return 0 */ static inline int decr_shrefcnt(unsigned int *refcnt, bool secure) { int rc = 0; if (secure) { if (*refcnt < SHREFCNT_MAX) { if (*refcnt < SHREFCNT_SECURE_STEP) panic(); *refcnt -= SHREFCNT_SECURE_STEP; rc = !*refcnt; } } else { rc = (*refcnt == SHREFCNT_NONSECURE_FLAG); *refcnt &= ~SHREFCNT_NONSECURE_FLAG; } return rc; } static inline int incr_refcnt(unsigned int *refcnt) { return incr_shrefcnt(refcnt, true); } static inline int decr_refcnt(unsigned int *refcnt) { return decr_shrefcnt(refcnt, true); } /* * Shared peripherals and resources registration * * Resources listed in enum stm32mp_shres assigned at run-time to the * non-secure world, to the secure world or shared by both worlds. * In the later case, there must exist a secure service in OP-TEE * for the non-secure world to access the resource. * * Resources may be a peripheral, a bus, a clock or a memory. * * Shared resources driver API functions allows drivers to register the * resource as secure, non-secure or shared and to get the resource * assignation state. */ #define STM32MP1_SHRES_GPIOZ(i) (STM32MP1_SHRES_GPIOZ_0 + i) enum stm32mp_shres { STM32MP1_SHRES_GPIOZ_0 = 0, STM32MP1_SHRES_GPIOZ_1, STM32MP1_SHRES_GPIOZ_2, STM32MP1_SHRES_GPIOZ_3, STM32MP1_SHRES_GPIOZ_4, STM32MP1_SHRES_GPIOZ_5, STM32MP1_SHRES_GPIOZ_6, STM32MP1_SHRES_GPIOZ_7, STM32MP1_SHRES_IWDG1, STM32MP1_SHRES_USART1, STM32MP1_SHRES_SPI6, STM32MP1_SHRES_I2C4, STM32MP1_SHRES_RNG1, STM32MP1_SHRES_HASH1, STM32MP1_SHRES_CRYP1, STM32MP1_SHRES_I2C6, STM32MP1_SHRES_RTC, STM32MP1_SHRES_MCU, STM32MP1_SHRES_PLL3, STM32MP1_SHRES_MDMA, STM32MP1_SHRES_SRAM1, STM32MP1_SHRES_SRAM2, STM32MP1_SHRES_SRAM3, STM32MP1_SHRES_SRAM4, STM32MP1_SHRES_COUNT }; #ifdef CFG_STM32MP1_SHARED_RESOURCES /* Register resource @id as a secure peripheral */ void stm32mp_register_secure_periph(enum stm32mp_shres id); /* Register resource @id as a non-secure peripheral */ void stm32mp_register_non_secure_periph(enum stm32mp_shres id); /* * Register resource identified by @base as a secure peripheral * @base: IOMEM physical base address of the resource */ void stm32mp_register_secure_periph_iomem(vaddr_t base); /* * Register resource identified by @base as a non-secure peripheral * @base: IOMEM physical base address of the resource */ void stm32mp_register_non_secure_periph_iomem(vaddr_t base); /* * Register GPIO resource as a secure peripheral * @bank: Bank of the target GPIO * @pin: Bit position of the target GPIO in the bank */ void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin); /* * Register GPIO resource as a non-secure peripheral * @bank: Bank of the target GPIO * @pin: Bit position of the target GPIO in the bank */ void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin); /* * Register pin resource of a pin control state as a secure peripheral * @bank: Bank of the target GPIO * @pin: Bit position of the target GPIO in the bank */ void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl); /* * Register pin resource of a pin control state as a non-secure peripheral * @bank: Bank of the target GPIO * @pin: Bit position of the target GPIO in the bank */ void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl); /* Return true if and only if resource @id is registered as secure */ bool stm32mp_periph_is_secure(enum stm32mp_shres id); /* Return true if and only if GPIO bank @bank is registered as secure */ bool stm32mp_gpio_bank_is_secure(unsigned int bank); /* Return true if and only if GPIO bank @bank is registered as non-secure */ bool stm32mp_gpio_bank_is_non_secure(unsigned int bank); /* Register parent clocks of @clock (ID used in clock DT bindings) as secure */ void stm32mp_register_clock_parents_secure(unsigned long clock_id); /* Register number of pins in the GPIOZ bank */ void stm32mp_register_gpioz_pin_count(size_t count); #else /* CFG_STM32MP1_SHARED_RESOURCES */ static inline void stm32mp_register_secure_periph(enum stm32mp_shres id __unused) { } static inline void stm32mp_register_non_secure_periph(enum stm32mp_shres id __unused) { } static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused) { } static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base __unused) { } static inline void stm32mp_register_secure_gpio(unsigned int bank __unused, unsigned int pin __unused) { } static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused, unsigned int pin __unused) { } static inline void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl __unused) { } static inline void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl __unused) { } static inline bool stm32mp_periph_is_secure(enum stm32mp_shres id __unused) { return true; } static inline bool stm32mp_gpio_bank_is_secure(unsigned int bank __unused) { return true; } static inline bool stm32mp_gpio_bank_is_non_secure(unsigned int bank __unused) { return false; } static inline void stm32mp_register_clock_parents_secure(unsigned long clock_id __unused) { } static inline void stm32mp_register_gpioz_pin_count(size_t count __unused) { } #endif /* CFG_STM32MP1_SHARED_RESOURCES */ #endif /*__STM32_UTIL_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp1/sub.mk000066400000000000000000000004671464416617300214500ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += reset.S srcs-$(CFG_SCMI_MSG_DRIVERS) += scmi_server.c srcs-$(CFG_STM32MP1_SHARED_RESOURCES) += shared_resources.c srcs-$(CFG_TZC400) += plat_tzc400.c srcs-$(CFG_WITH_PAGER) += link_dummies_paged.c subdirs-y += drivers subdirs-y += nsec-service subdirs-y += pm optee_os-4.3.0/core/arch/arm/plat-stm32mp2/000077500000000000000000000000001464416617300203205ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp2/conf.mk000066400000000000000000000045511464416617300216030ustar00rootroot00000000000000flavor_dts_file-257F_EV1 = stm32mp257f-ev1.dts flavorlist-MP25 = $(flavor_dts_file-257F_EV1) ifneq ($(PLATFORM_FLAVOR),) ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),) $(error Invalid platform flavor $(PLATFORM_FLAVOR)) endif CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR)) endif CFG_EMBED_DTB_SOURCE_FILE ?= stm32mp257f-ev1.dts ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP25)),) $(call force,CFG_STM32MP25,y) endif ifneq ($(CFG_STM32MP25),y) $(error STM32 Platform must be defined) endif include core/arch/arm/cpu/cortex-armv8-0.mk supported-ta-targets ?= ta_arm64 $(call force,CFG_ARM64_core,y) $(call force,CFG_DRIVERS_CLK,y) $(call force,CFG_DRIVERS_CLK_DT,y) $(call force,CFG_DRIVERS_GPIO,y) $(call force,CFG_DRIVERS_PINCTRL,y) $(call force,CFG_DT,y) $(call force,CFG_GIC,y) $(call force,CFG_HALT_CORES_ON_PANIC_SGI,15) $(call force,CFG_INIT_CNTVOFF,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_STM32_SHARED_IO,y) $(call force,CFG_STM32MP_CLK_CORE,y) $(call force,CFG_STM32MP25_CLK,y) $(call force,CFG_STM32MP25_RSTCTRL,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_WITH_LPAE,y) CFG_TZDRAM_START ?= 0x82000000 CFG_TZDRAM_SIZE ?= 0x02000000 # Support DDR ranges up to 8GBytes (address range: 0x80000000 + DDR size) CFG_CORE_LARGE_PHYS_ADDR ?= y CFG_CORE_ARM64_PA_BITS ?= 34 CFG_CORE_HEAP_SIZE ?= 262144 CFG_CORE_RESERVED_SHM ?= n CFG_DTB_MAX_SIZE ?= 262144 CFG_HALT_CORES_ON_PANIC ?= y CFG_MMAP_REGIONS ?= 30 CFG_NUM_THREADS ?= 5 CFG_TEE_CORE_NB_CORE ?= 2 CFG_STM32MP_OPP_COUNT ?= 3 CFG_STM32_FMC ?= y CFG_STM32_GPIO ?= y CFG_STM32_HPDMA ?= y CFG_STM32_HSEM ?= y CFG_STM32_IPCC ?= y CFG_STM32_RIF ?= y CFG_STM32_RIFSC ?= y CFG_STM32_RNG ?= y CFG_STM32_UART ?= y # Default enable some test facitilites CFG_ENABLE_EMBEDDED_TESTS ?= y CFG_WITH_STATS ?= y # Default disable ASLR CFG_CORE_ASLR ?= n # UART instance used for early console (0 disables early console) CFG_STM32_EARLY_CONSOLE_UART ?= 2 # Default disable external DT support CFG_EXTERNAL_DT ?= n # Default enable HWRNG PTA support CFG_HWRNG_PTA ?= y ifeq ($(CFG_HWRNG_PTA),y) $(call force,CFG_STM32_RNG,y,Required by CFG_HWRNG_PTA) $(call force,CFG_WITH_SOFTWARE_PRNG,n,Required by CFG_HWRNG_PTA) CFG_HWRNG_QUALITY ?= 1024 endif # Enable reset control ifeq ($(CFG_STM32MP25_RSTCTRL),y) $(call force,CFG_DRIVERS_RSTCTRL,y) $(call force,CFG_STM32_RSTCTRL,y) endif optee_os-4.3.0/core/arch/arm/plat-stm32mp2/drivers/000077500000000000000000000000001464416617300217765ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-stm32mp2/drivers/stm32mp25_syscfg.c000066400000000000000000000025521464416617300252000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #define SYSCON_OFFSET(id) ((id) & GENMASK_32(15, 0)) #define SYSCON_BANK(id) (((id) & GENMASK_32(31, 16)) >> 16) /* Safe Reset register definition */ #define SYSCFG_SAFERSTCR SYSCON_ID(SYSCON_SYSCFG, U(0x2018)) #define SYSCFG_SAFERSTCR_EN BIT(0) struct io_pa_va syscfg_base[SYSCON_NB_BANKS] = { { .pa = SYSCFG_BASE }, { .pa = A35SSC_BASE } }; static vaddr_t stm32mp_syscfg_base(uint32_t id) { uint32_t bank = SYSCON_BANK(id); assert(bank < SYSCON_NB_BANKS); return io_pa_or_va_secure(&syscfg_base[bank], 1); } void stm32mp_syscfg_write(uint32_t id, uint32_t value, uint32_t bitmsk) { vaddr_t syconf_base = stm32mp_syscfg_base(id); io_mask32_stm32shregs(syconf_base + SYSCON_OFFSET(id), value, bitmsk); } uint32_t stm32mp_syscfg_read(uint32_t id) { return io_read32(stm32mp_syscfg_base(id) + SYSCON_OFFSET(id)); } void stm32mp25_syscfg_set_safe_reset(bool status) { vaddr_t addr = stm32mp_syscfg_base(SYSCON_SYSCFG) + SYSCFG_SAFERSTCR; FMSG("Set safe reset to %d", status); if (status) io_setbits32(addr, SYSCFG_SAFERSTCR_EN); else io_clrbits32(addr, SYSCFG_SAFERSTCR_EN); } optee_os-4.3.0/core/arch/arm/plat-stm32mp2/drivers/sub.mk000066400000000000000000000000351464416617300231160ustar00rootroot00000000000000srcs-y += stm32mp25_syscfg.c optee_os-4.3.0/core/arch/arm/plat-stm32mp2/main.c000066400000000000000000000102551464416617300214130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_NSEC, APB1_BASE, APB1_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB1_BASE, APB1_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB2_BASE, APB2_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB3_BASE, APB3_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, APB4_BASE, APB4_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB2_BASE, AHB2_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB3_BASE, AHB3_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB4_BASE, AHB4_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, AHB5_BASE, AHB5_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAPB_BASE, SAPB_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SAHB_BASE, SAHB_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE); #define _ID2STR(id) (#id) #define ID2STR(id) _ID2STR(id) static TEE_Result platform_banner(void) { IMSG("Platform stm32mp2: flavor %s - DT %s", ID2STR(PLATFORM_FLAVOR), ID2STR(CFG_EMBED_DTB_SOURCE_FILE)); return TEE_SUCCESS; } service_init(platform_banner); /* * Console * * CFG_STM32_EARLY_CONSOLE_UART specifies the ID of the UART used for * trace console. Value 0 disables the early console. * * We cannot use the generic serial_console support since probing * the console requires the platform clock driver to be already * up and ready which is done only once service_init are completed. */ static struct stm32_uart_pdata console_data; void plat_console_init(void) { #ifdef CFG_STM32_UART /* Early console initialization before MMU setup */ struct uart { paddr_t pa; bool secure; } uarts[] = { [0] = { .pa = 0 }, [1] = { .pa = USART1_BASE, .secure = true, }, [2] = { .pa = USART2_BASE, .secure = false, }, [3] = { .pa = USART3_BASE, .secure = false, }, [4] = { .pa = UART4_BASE, .secure = false, }, [5] = { .pa = UART5_BASE, .secure = false, }, [6] = { .pa = USART6_BASE, .secure = false, }, [7] = { .pa = UART7_BASE, .secure = false, }, [8] = { .pa = UART8_BASE, .secure = false, }, [9] = { .pa = UART9_BASE, .secure = false, }, }; static_assert(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART); if (!uarts[CFG_STM32_EARLY_CONSOLE_UART].pa) return; /* No clock yet bound to the UART console */ console_data.clock = NULL; console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure; stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa); register_serial_console(&console_data.chip); IMSG("Early console on UART#%u", CFG_STM32_EARLY_CONSOLE_UART); #endif } #ifdef CFG_STM32_UART static TEE_Result init_console_from_dt(void) { struct stm32_uart_pdata *pd = NULL; void *fdt = NULL; int node = 0; TEE_Result res = TEE_ERROR_GENERIC; fdt = get_embedded_dt(); res = get_console_node_from_dt(fdt, &node, NULL, NULL); if (res == TEE_ERROR_ITEM_NOT_FOUND) { fdt = get_external_dt(); res = get_console_node_from_dt(fdt, &node, NULL, NULL); if (res == TEE_ERROR_ITEM_NOT_FOUND) return TEE_SUCCESS; if (res != TEE_SUCCESS) return res; } pd = stm32_uart_init_from_dt_node(fdt, node); if (!pd) { IMSG("DTB disables console"); register_serial_console(NULL); return TEE_SUCCESS; } /* Replace early console with the new one */ console_flush(); console_data = *pd; register_serial_console(&console_data.chip); IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-"); free(pd); return TEE_SUCCESS; } /* Probe console from DT once clock inits (service init level) are completed */ service_init_late(init_console_from_dt); #endif /*STM32_UART*/ vaddr_t stm32_rcc_base(void) { static struct io_pa_va base = { .pa = RCC_BASE }; return io_pa_or_va_secure(&base, 1); } void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } optee_os-4.3.0/core/arch/arm/plat-stm32mp2/platform_config.h000066400000000000000000000057751464416617300236600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, STMicroelectronics */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 32 /* SoC interface registers base address ranges */ #define APB1_BASE 0x40000000 #define APB1_SIZE 0x00200000 #define APB2_BASE 0x40200000 #define APB2_SIZE 0x00040000 #define AHB2_BASE 0x40400000 #define AHB2_SIZE 0x01c00000 #define AHB3_BASE 0x42000000 #define AHB3_SIZE 0x02000000 #define APB3_BASE 0x44000000 #define APB3_SIZE 0x001f0000 #define AHB4_BASE 0x44200000 #define AHB4_SIZE 0x01e00000 #define SAPB_BASE 0x46000000 #define SAPB_SIZE 0x00200000 #define SAHB_BASE 0x46200000 #define SAHB_SIZE 0x01e00000 #define APB4_BASE 0x48000000 #define APB4_SIZE 0x00200000 #define AHB5_BASE 0x48200000 #define AHB5_SIZE 0x01e00000 /* SoC interface registers base address */ #define UART2_BASE 0x400e0000 #define UART3_BASE 0x400f0000 #define UART4_BASE 0x40100000 #define UART5_BASE 0x40110000 #define I2C4_BASE 0x40150000 #define I2C6_BASE 0x40170000 #define UART6_BASE 0x40220000 #define UART9_BASE 0x402c0000 #define UART1_BASE 0x40330000 #define SPI6_BASE 0x40350000 #define UART7_BASE 0x40370000 #define UART8_BASE 0x40380000 #define OSPI1_BASE 0x40430000 #define OSPI2_BASE 0x40440000 #define HASH1_BASE 0x42010000 #define RNG1_BASE 0x42020000 #define CRYP1_BASE 0x42030000 #define SAES_BASE 0x42050000 #define PKA_BASE 0x42060000 #define RIFSC_BASE 0x42080000 #define RISAF5_BASE 0x420e0000 #define RISAB6_BASE 0x42140000 #define BSEC3_BASE 0x44000000 #define IWDG2_BASE 0x44002000 #define IWDG1_BASE 0x44010000 #define RCC_BASE 0x44200000 #define PWR_BASE 0x44210000 #define SYSCFG_BASE 0x44230000 #define GPIOA_BASE 0x44240000 #define GPIOB_BASE 0x44250000 #define GPIOC_BASE 0x44260000 #define GPIOD_BASE 0x44270000 #define GPIOE_BASE 0x44280000 #define GPIOF_BASE 0x44290000 #define GPIOG_BASE 0x442a0000 #define GPIOH_BASE 0x442b0000 #define GPIOI_BASE 0x442c0000 #define GPIOJ_BASE 0x442d0000 #define GPIOK_BASE 0x442e0000 #define RTC_BASE 0x46000000 #define TAMP_BASE 0x46010000 #define GPIOZ_BASE 0x46200000 #define STGEN_BASE 0x48080000 #define FMC_BASE 0x48200000 #define PCIE_BASE 0x48400000 #define A35SSC_BASE 0x48800000 #define GIC_BASE 0x4ac00000 #define DDR_BASE UL(0x80000000) #define SYSRAM_BASE 0x0e000000 #define SRAM1_BASE 0x0e040000 /* GIC resources */ #define GIC_SIZE 0x80000 #define GICC_OFFSET 0x20000 #define GICD_OFFSET 0x10000 /* Console configuration */ #define GIC_SPI_UART4 126 #define TARGET_CPU0_GIC_MASK BIT(0) #define TARGET_CPU1_GIC_MASK BIT(1) #define TARGET_CPUS_GIC_MASK GENMASK_32(CFG_TEE_CORE_NB_CORE - 1, 0) /* USART/UART resources */ #define USART1_BASE UART1_BASE #define USART2_BASE UART2_BASE #define USART3_BASE UART3_BASE #define USART6_BASE UART6_BASE #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp2/stm32_sysconf.h000066400000000000000000000056421464416617300232140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024, STMicroelectronics */ #ifndef __STM32_SYSCONF_H__ #define __STM32_SYSCONF_H__ #include #include #include /* syscon banks */ enum syscon_banks { SYSCON_SYSCFG, SYSCON_A35SSC, SYSCON_NB_BANKS }; #define SYSCON_ID(bank, offset) (((bank) << 16) | \ ((offset) & GENMASK_32(15, 0))) /* * A35SSC register offsets (base relative) */ #define A35SS_SSC_CHGCLKREQ SYSCON_ID(SYSCON_A35SSC, 0x0) #define A35SS_SSC_PLL_FREQ1 SYSCON_ID(SYSCON_A35SSC, 0x80) #define A35SS_SSC_PLL_FREQ2 SYSCON_ID(SYSCON_A35SSC, 0x90) #define A35SS_SSC_PLL_EN SYSCON_ID(SYSCON_A35SSC, 0xA0) #define A35SSC_M33CFG_ACCESS_CR SYSCON_ID(SYSCON_A35SSC, 0x2088) #define A35SSC_M33_TZEN_CR SYSCON_ID(SYSCON_A35SSC, 0x20A0) #define A35SSC_M33_INITSVTOR_CR SYSCON_ID(SYSCON_A35SSC, 0x20A4) #define A35SSC_M33_INITNSVTOR_CR SYSCON_ID(SYSCON_A35SSC, 0x20A8) /* * A35SSC M33CFG_ACCESS_CR register */ #define A35SSC_M33_TZEN_CR_M33CFG_SEC BIT(0) #define A35SSC_M33_TZEN_CR_M33CFG_PRIV BIT(1) /* * A35SSC M33_TZEN_CR register */ #define A35SSC_M33_TZEN_CR_CFG_SECEXT BIT(0) /* * A35SSC A35SS_SSC_CHGCLKREQ register */ #define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_EN BIT(0) #define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_MASK BIT(0) #define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK BIT(1) #define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_SHIFT U(1) /* * A35SSC A35SS_SSC_PLL_FREQ1 register */ #define A35SS_SSC_PLL_FREQ1_FBDIV_MASK GENMASK_32(11, 0) #define A35SS_SSC_PLL_FREQ1_FBDIV_SHIFT U(0) #define A35SS_SSC_PLL_FREQ1_REFDIV_MASK GENMASK_32(21, 16) #define A35SS_SSC_PLL_FREQ1_REFDIV_SHIFT U(16) #define A35SS_SSC_PLL_FREQ1_MASK (A35SS_SSC_PLL_FREQ1_REFDIV_MASK | \ A35SS_SSC_PLL_FREQ1_FBDIV_MASK) /* * A35SSC A35SS_SSC_PLL_FREQ2 register */ #define A35SS_SSC_PLL_FREQ2_POSTDIV1_MASK GENMASK_32(2, 0) #define A35SS_SSC_PLL_FREQ2_POSTDIV1_SHIFT U(0) #define A35SS_SSC_PLL_FREQ2_POSTDIV2_MASK GENMASK_32(5, 3) #define A35SS_SSC_PLL_FREQ2_POSTDIV2_SHIFT U(3) #define A35SS_SSC_PLL_FREQ2_MASK GENMASK_32(5, 0) /* * A35SSC A35SS_SSC_PLL_EN register */ #define A35SS_SSC_PLL_ENABLE_PD_EN BIT(0) #define A35SS_SSC_PLL_ENABLE_PD_MASK BIT(0) #define A35SS_SSC_PLL_ENABLE_LOCKP_MASK BIT(1) #define A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_EN BIT(2) #define A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_MASK BIT(2) /* * Write masked value is SYSCONF register * @id: SYSCONF register ID, processed with SYSCON_ID() macro * @value: Value to be written * @bitmsk: Bit mask applied to @value */ void stm32mp_syscfg_write(uint32_t id, uint32_t value, uint32_t bitmsk); /* * Read SYSCONF reagister * @id: SYSCONF register ID, processed with SYSCON_ID() macro */ uint32_t stm32mp_syscfg_read(uint32_t id); /* * Set safe reset state * @status: True to enable safe reset, false to disable safe reset */ void stm32mp25_syscfg_set_safe_reset(bool status); #endif /*__STM32_SYSCONF_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp2/stm32_util.h000066400000000000000000000012771464416617300225050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2023, STMicroelectronics */ #ifndef __STM32_UTIL_H__ #define __STM32_UTIL_H__ #include #include #include #include static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused) { } static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base __unused) { } static inline void stm32mp_register_gpioz_pin_count(size_t count __unused) { } #define may_spin_lock(lock) cpu_spin_lock_xsave(lock) #define may_spin_unlock(lock, exceptions) cpu_spin_unlock_xrestore(lock, \ exceptions) #endif /*__STM32_UTIL_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp2/stm32mp_pm.c000066400000000000000000000041501464416617300224650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023-2024, STMicroelectronics */ #include #include #include #include #include /** * @brief Handler for system off * * @param[in] a0 Unused * @param[in] a1 Unused * * @retval 0 if OK, other value else and TF-A will panic */ unsigned long thread_system_off_handler(unsigned long a0 __unused, unsigned long a1 __unused) { /* * configure targeted mode in PMIC for system OFF, * no need to save context */ uint32_t pm_hint = PM_HINT_CLOCK_STATE | ((PM_MAX_LEVEL << PM_HINT_PLATFORM_STATE_SHIFT) & PM_HINT_PLATFORM_STATE_MASK); return pm_change_state(PM_OP_SUSPEND, pm_hint); } static uint32_t get_pm_hint(unsigned long a0) { uint32_t pm_hint = 0U; /* a0 is the highest power level which was powered down. */ if (a0 < PM_D2_LPLV_LEVEL) pm_hint = PM_HINT_CLOCK_STATE; else pm_hint = PM_HINT_CONTEXT_STATE; pm_hint |= ((a0 << PM_HINT_PLATFORM_STATE_SHIFT) & PM_HINT_PLATFORM_STATE_MASK); return pm_hint; } /** * @brief Handler for cpu resume * * @param[in] a0 Max power level powered down * @param[in] a1 Unused * * @retval 0 if OK, other value else and TF-A will panic */ unsigned long thread_cpu_resume_handler(unsigned long a0, unsigned long a1 __unused) { TEE_Result retstatus = TEE_SUCCESS; retstatus = pm_change_state(PM_OP_RESUME, get_pm_hint(a0)); /* * Returned value to the TF-A. * If it is not 0, the system will panic */ if (retstatus == TEE_SUCCESS) return 0; else return 1; } /** * @brief Handler for cpu suspend * * @param[in] a0 Max power level to power down * @param[in] a1 Unused * * @retval 0 if OK, other value else and TF-A will panic */ unsigned long thread_cpu_suspend_handler(unsigned long a0, unsigned long a1 __unused) { TEE_Result retstatus = TEE_SUCCESS; retstatus = pm_change_state(PM_OP_SUSPEND, get_pm_hint(a0)); /* * Returned value to the TF-A. * If it is not 0, the system will panic */ if (retstatus == TEE_SUCCESS) return 0; else return 1; } optee_os-4.3.0/core/arch/arm/plat-stm32mp2/stm32mp_pm.h000066400000000000000000000023761464416617300225020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023-2024, STMicroelectronics */ #ifndef __STM32MP_PM_H__ #define __STM32MP_PM_H__ /* * The PSCI topology is defined in TF-A, with 5 power levels supported in * the first parameter a0="Max power level powered down" of TF-A SPD hooks * * power level (associated low power mode for a0) * 0: CPU1 core#0 or core#1 (Stop1 or LP-Stop1) * 1: D1 domain (LPLV-Stop1) * 2: LPLV D1 (Stop2 or LP-Stop2) * 3: D2 (LPLV-Stop1) * 4: LPLV D2 (Standby) * 5: MAX (PowerOff) * * these power level are only managed in power driver (PMIC), for pm function * use the 2 associated parameters: * - PM_HINT_CONTEXT_STATE : advertise driver to save all their context in DDR * (self refresh) for standby mode * - PM_HINT_CLOCK_STATE : advertise driver to interrupt operation when clock * are stalled for the other low power modes */ #define PM_CORE_LEVEL 0 #define PM_D1_LEVEL 1 #define PM_D1_LPLV_LEVEL 2 #define PM_D2_LEVEL 3 #define PM_D2_LPLV_LEVEL 4 #define PM_MAX_LEVEL 5 #endif /*__STM32MP_PM_H__*/ optee_os-4.3.0/core/arch/arm/plat-stm32mp2/sub.mk000066400000000000000000000001241464416617300214370ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += stm32mp_pm.c subdirs-y += drivers optee_os-4.3.0/core/arch/arm/plat-sunxi/000077500000000000000000000000001464416617300200775ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-sunxi/conf.mk000066400000000000000000000020621464416617300213550ustar00rootroot00000000000000PLATFORM_FLAVOR ?= bpi_zero $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_8250_UART,y) ifeq ($(PLATFORM_FLAVOR),bpi_zero) include core/arch/arm/cpu/cortex-a7.mk $(call force,CFG_SUN8I_H2_PLUS,y) $(call force,CFG_ARM32_core,y) $(call force,CFG_GIC,y) $(call force,CFG_WITH_LPAE,n) $(call force,CFG_WITH_PAGER,n) CFG_CRYPTO_SIZE_OPTIMIZATION ?= n CFG_NUM_THREADS ?= 4 CFG_TEE_CORE_NB_CORE ?= 4 CFG_BOOT_SECONDARY_REQUEST ?= y CFG_PSCI_ARM32 ?= y CFG_NS_ENTRY_ADDR ?= 0x42000000 CFG_DT ?= y CFG_INIT_CNTVOFF ?= y CFG_SECONDARY_INIT_CNTFRQ ?= y CFG_TZDRAM_START ?= 0x5c000000 CFG_TZDRAM_SIZE ?= 0x03e00000 CFG_SHMEM_START ?= 0x5fe00000 CFG_SHMEM_SIZE ?= 0x00200000 endif ifeq ($(PLATFORM_FLAVOR),sun50i_a64) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_ARM64_core,y) CFG_TZDRAM_START ?= 0x40000000 CFG_TZDRAM_SIZE ?= 0x2000000 CFG_SHMEM_START ?= 0x44000000 CFG_SHMEM_SIZE ?= 0x00400000 CFG_TEE_CORE_NB_CORE ?= 4 CFG_TZC380 ?= y endif ifeq ($(platform-flavor-armv8),1) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) endif CFG_WITH_STATS ?= y optee_os-4.3.0/core/arch/arm/plat-sunxi/main.c000066400000000000000000000125471464416617300212000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Allwinner Technology Co., Ltd. * Copyright (c) 2018, Linaro Limited * Copyright (c) 2018, Amit Singh Tomar * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef GIC_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); #endif #ifdef CONSOLE_UART_BASE register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SUNXI_UART_REG_SIZE); #endif #ifdef SUNXI_TZPC_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_TZPC_BASE, SUNXI_TZPC_REG_SIZE); #define REG_TZPC_SMTA_DECPORT0_STA_REG (0x0004) #define REG_TZPC_SMTA_DECPORT0_SET_REG (0x0008) #define REG_TZPC_SMTA_DECPORT0_CLR_REG (0x000C) #define REG_TZPC_SMTA_DECPORT1_STA_REG (0x0010) #define REG_TZPC_SMTA_DECPORT1_SET_REG (0x0014) #define REG_TZPC_SMTA_DECPORT1_CLR_REG (0x0018) #define REG_TZPC_SMTA_DECPORT2_STA_REG (0x001c) #define REG_TZPC_SMTA_DECPORT2_SET_REG (0x0020) #define REG_TZPC_SMTA_DECPORT2_CLR_REG (0x0024) #endif #ifdef SUNXI_CPUCFG_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_CPUCFG_BASE, SUNXI_CPUCFG_REG_SIZE); #endif #ifdef SUNXI_PRCM_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_PRCM_BASE, SUNXI_PRCM_REG_SIZE); #endif #ifdef CFG_TZC380 vaddr_t smc_base(void); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SUNXI_SMC_BASE, TZC400_REG_SIZE); #define SMC_MASTER_BYPASS 0x18 #define SMC_MASTER_BYPASS_EN_MASK 0x1 #endif #ifdef SUNXI_TZPC_BASE static void tzpc_init(void); #endif static struct serial8250_uart_data console_data; void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } #ifdef SUNXI_TZPC_BASE static void tzpc_init(void) { vaddr_t v = (vaddr_t)phys_to_virt(SUNXI_TZPC_BASE, MEM_AREA_IO_SEC, SUNXI_TZPC_REG_SIZE); DMSG("SMTA_DECPORT0=%x", io_read32(v + REG_TZPC_SMTA_DECPORT0_STA_REG)); DMSG("SMTA_DECPORT1=%x", io_read32(v + REG_TZPC_SMTA_DECPORT1_STA_REG)); DMSG("SMTA_DECPORT2=%x", io_read32(v + REG_TZPC_SMTA_DECPORT2_STA_REG)); /* Allow all peripherals for normal world */ io_write32(v + REG_TZPC_SMTA_DECPORT0_SET_REG, 0xbe); io_write32(v + REG_TZPC_SMTA_DECPORT1_SET_REG, 0xff); io_write32(v + REG_TZPC_SMTA_DECPORT2_SET_REG, 0x7f); DMSG("SMTA_DECPORT0=%x", io_read32(v + REG_TZPC_SMTA_DECPORT0_STA_REG)); DMSG("SMTA_DECPORT1=%x", io_read32(v + REG_TZPC_SMTA_DECPORT1_STA_REG)); DMSG("SMTA_DECPORT2=%x", io_read32(v + REG_TZPC_SMTA_DECPORT2_STA_REG)); } #else static inline void tzpc_init(void) { } #endif /* SUNXI_TZPC_BASE */ #ifndef CFG_WITH_ARM_TRUSTED_FW void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } #endif #ifdef ARM32 void plat_primary_init_early(void) { assert(!cpu_mmu_enabled()); tzpc_init(); } #endif /* * Allwinner's A64 has TZC380 like controller called SMC that can * be programmed to protect parts of DRAM from non-secure world. */ #ifdef CFG_TZC380 vaddr_t smc_base(void) { return (vaddr_t)phys_to_virt(SUNXI_SMC_BASE, MEM_AREA_IO_SEC, TZC400_REG_SIZE); } static TEE_Result smc_init(void) { vaddr_t base = smc_base(); if (!base) { EMSG("smc not mapped"); panic(); } tzc_init(base); tzc_configure_region(0, 0x0, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_1G) | TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_ALL); tzc_configure_region(1, 0x0, TZC_ATTR_REGION_SIZE(TZC_REGION_SIZE_32M) | TZC_ATTR_REGION_EN_MASK | TZC_ATTR_SP_S_RW); /* SoC specific bits */ io_clrbits32(base + SMC_MASTER_BYPASS, SMC_MASTER_BYPASS_EN_MASK); return TEE_SUCCESS; } driver_init(smc_init); #endif /* CFG_TZC380 */ optee_os-4.3.0/core/arch/arm/plat-sunxi/plat_init.S000066400000000000000000000034711464416617300222130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * Copyright (C) 2018, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include FUNC plat_cpu_reset_early , : /* NSACR configuration */ read_nsacr r0 orr r0, r0, #NSACR_CP10 orr r0, r0, #NSACR_CP11 orr r0, r0, #NSACR_NS_SMP write_nsacr r0 /* Enable SMP bit */ read_actlr r0 orr r0, r0, #ACTLR_SMP write_actlr r0 bx lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-sunxi/platform_config.h000066400000000000000000000045011464416617300234210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Allwinner Technology Co., Ltd. * Copyright (c) 2018, Linaro Limited * Copyright (c) 2018, Amit Singh Tomar /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* 16550 UART */ #define CONSOLE_UART_BASE 0x01c28000 /* UART0 */ #define CONSOLE_UART_CLK_IN_HZ 24000000 #define CONSOLE_BAUDRATE 115200 #define SUNXI_UART_REG_SIZE 0x400 #if defined(PLATFORM_FLAVOR_bpi_zero) #define GIC_BASE 0x01c80000 #define GICC_OFFSET 0x2000 #define GICD_OFFSET 0x1000 #define SUNXI_TZPC_BASE 0x01c23400 #define SUNXI_TZPC_REG_SIZE 0x400 #define SUNXI_CPUCFG_BASE 0x01f01c00 #define SUNXI_CPUCFG_REG_SIZE 0x400 #define SUNXI_PRCM_BASE 0x01f01400 #define SUNXI_PRCM_REG_SIZE 0x400 #define PRCM_CPU_SOFT_ENTRY_REG 0x164 #endif #if defined(PLATFORM_FLAVOR_sun50i_a64) #define SUNXI_SMC_BASE 0x01c1e000 #endif #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-sunxi/psci.c000066400000000000000000000116301464416617300212020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2013, ARM Ltd * Copyright (c) 2014, Allwinner Technology Co., Ltd. * Copyright (c) 2018, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define REG_CPUCFG_RES0 (0x0000) #define REG_CPUCFG_CPU_RST(cpu) (0x0040 + (cpu) * (0x0040)) #define REG_CPUCFG_GEN_CTRL (0x0184) #define REG_CPUCFG_PRIV0 (0x01a4) #define REG_CPUCFG_DBG_CTRL1 (0x01e4) #define REG_PRCM_CPU_PWROFF (0x0100) #define REG_PRCM_CPU_PWR_CLAMP(cpu) (0x0140 + (cpu) * (0x0004)) int psci_features(uint32_t psci_fid) { switch (psci_fid) { #ifdef CFG_BOOT_SECONDARY_REQUEST case PSCI_CPU_ON: return 0; #endif default: return PSCI_RET_NOT_SUPPORTED; } } #ifdef CFG_BOOT_SECONDARY_REQUEST int psci_cpu_on(uint32_t core_idx, uint32_t entry, uint32_t context_id) { vaddr_t base = (vaddr_t)phys_to_virt(SUNXI_PRCM_BASE, MEM_AREA_IO_SEC, SUNXI_PRCM_REG_SIZE); vaddr_t cpucfg = (vaddr_t)phys_to_virt(SUNXI_CPUCFG_BASE, MEM_AREA_IO_SEC, SUNXI_CPUCFG_REG_SIZE); uint32_t tmpff; uint32_t val; assert(base); assert(cpucfg); if ((core_idx == 0) || (core_idx >= CFG_TEE_CORE_NB_CORE)) return PSCI_RET_INVALID_PARAMETERS; /* set secondary cores' NS entry addresses */ boot_set_core_ns_entry(core_idx, entry, context_id); val = virt_to_phys((void *)TEE_LOAD_ADDR); /* set entry address */ DMSG("set entry address for CPU %d", core_idx); io_write32(cpucfg + REG_CPUCFG_PRIV0, val); /* assert reset on target CPU */ DMSG("assert reset on target CPU %d", core_idx); io_write32(cpucfg + REG_CPUCFG_CPU_RST(core_idx), 0); /* invalidate L1 cache */ DMSG("invalidate L1 cache for CPU %d", core_idx); io_clrbits32(cpucfg + REG_CPUCFG_GEN_CTRL, BIT32(core_idx)); /* lock CPU (Disable external debug access) */ DMSG("lock CPU %d", core_idx); io_clrbits32(cpucfg + REG_CPUCFG_DBG_CTRL1, BIT32(core_idx)); /* release clamp */ DMSG("release clamp for CPU %d", core_idx); tmpff = 0x1ff; do { tmpff >>= 1; io_write32(base + REG_PRCM_CPU_PWR_CLAMP(core_idx), tmpff); } while (tmpff); mdelay(10); /* clear power gating */ DMSG("clear power gating for CPU %d", core_idx); io_clrbits32(base + REG_PRCM_CPU_PWROFF, BIT32(core_idx)); udelay(1000); /* de-assert reset on target CPU */ DMSG("de-assert reset on target CPU %d", core_idx); io_write32(cpucfg + REG_CPUCFG_CPU_RST(core_idx), 0x03); /* unlock CPU (enable external debug access) */ DMSG("unlock CPU %d", core_idx); io_setbits32(cpucfg + REG_CPUCFG_DBG_CTRL1, BIT32(core_idx)); return PSCI_RET_SUCCESS; } int __noreturn psci_cpu_off(void) { uint32_t core_id; vaddr_t base = (vaddr_t)phys_to_virt(SUNXI_PRCM_BASE, MEM_AREA_IO_SEC, SUNXI_PRCM_REG_SIZE); vaddr_t cpucfg = (vaddr_t)phys_to_virt(SUNXI_CPUCFG_BASE, MEM_AREA_IO_SEC, SUNXI_CPUCFG_REG_SIZE); core_id = get_core_pos(); DMSG("core_id: %" PRIu32, core_id); #ifdef CFG_PSCI_ARM32 psci_armv7_cpu_off(); #endif /* CFG_PSCI_ARM32 */ assert(base); assert(cpucfg); /* set power gating */ DMSG("set power gating for cpu %d", core_id); io_setbits32(base + REG_PRCM_CPU_PWROFF, BIT32(core_id)); /* Activate power clamp */ DMSG("Activate power clamp for cpu %d", core_id); io_write32(base + REG_PRCM_CPU_PWR_CLAMP(core_id), 0xff); while (true) wfi(); } #endif optee_os-4.3.0/core/arch/arm/plat-sunxi/sub.mk000066400000000000000000000001561464416617300212230ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-$(CFG_ARM32_core) += plat_init.S srcs-$(CFG_ARM32_core) += psci.c optee_os-4.3.0/core/arch/arm/plat-synquacer/000077500000000000000000000000001464416617300207435ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-synquacer/conf.mk000066400000000000000000000010621464416617300222200ustar00rootroot00000000000000PLATFORM_FLAVOR ?= developerbox $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_GIC,y) $(call force,CFG_PL011,y) include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,24) CFG_NUM_THREADS ?= 8 CFG_TZDRAM_START ?= 0xfc000000 CFG_TZDRAM_SIZE ?= 0x03c00000 CFG_SHMEM_START ?= 0xffc00000 CFG_SHMEM_SIZE ?= 0x00400000 $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_ARM64_core,y) supported-ta-targets = ta_arm64 CFG_CRYPTO_SIZE_OPTIMIZATION ?= n $(call force,CFG_ARM_GICV3,y) $(call force,CFG_CORE_CLUSTER_SHIFT,1) optee_os-4.3.0/core/arch/arm/plat-synquacer/main.c000066400000000000000000000032521464416617300220350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "synquacer_rng_pta.h" static struct pl011_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, THERMAL_SENSOR_BASE, CORE_MMU_PGDIR_SIZE); void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } void boot_primary_init_intc(void) { gic_init(0, GIC_BASE + GICD_OFFSET); } static enum itr_return timer_itr_cb(struct itr_handler *h __unused) { /* Reset timer for next FIQ */ generic_timer_handler(TIMER_PERIOD_MS); /* Collect entropy on each timer FIQ */ rng_collect_entropy(); return ITRR_HANDLED; } static struct itr_handler timer_itr = { .it = IT_SEC_TIMER, .flags = ITRF_TRIGGER_LEVEL, .handler = timer_itr_cb, }; static TEE_Result init_timer_itr(void) { if (interrupt_add_handler_with_chip(interrupt_get_main_chip(), &timer_itr)) panic(); interrupt_enable(timer_itr.chip, timer_itr.it); /* Enable timer FIQ to fetch entropy required during boot */ generic_timer_start(TIMER_PERIOD_MS); return TEE_SUCCESS; } driver_init(init_timer_itr); optee_os-4.3.0/core/arch/arm/plat-synquacer/platform_config.h000066400000000000000000000013041464416617300242630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #define STACK_ALIGNMENT 64 #define GIC_BASE 0x30000000 #define GICD_OFFSET 0x0 /* console uart define */ #define UART0_BASE 0x2A400000 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_UART_CLK_IN_HZ 62500000 #define CONSOLE_BAUDRATE 115200 #define THERMAL_SENSOR_BASE 0x54190000 #define IT_SEC_TIMER 29 #define TIMER_PERIOD_MS 2 #define DRAM0_BASE 0x80000000 /* Platform specific defines */ #if defined(PLATFORM_FLAVOR_developerbox) #define DRAM0_SIZE 0x80000000 #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-synquacer/rng_pta.c000066400000000000000000000233631464416617300225500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018-2022, Linaro Limited */ /* * Developerbox doesn't provide a hardware based true random number * generator. So this pseudo TA provides a good source of entropy using * noise from 7 thermal sensors. Its suitable for entropy required * during boot, seeding kernel entropy pool, cryptographic use etc. * * Assumption * ========== * * We have assumed the entropy of the sensor is better than 8 bits per * 14 sensor readings. This entropy estimate is based on our simple * minimal entropy estimates done on 2.1G bytes of raw samples collected * from thermal sensors. * * We believe our estimate to be conservative and have designed to * health tests to trigger if a sensor does not achieve at least * 8 bits in 16 sensor reading (we use 16 rather than 14 to prevent * spurious failures on edge cases). * * Theory of operation * =================== * * This routine uses secure timer interrupt to sample raw thermal sensor * readings. As thermal sensor refresh rate is every 2ms, so interrupt * fires every 2ms. It implements continuous health test counting rising * and falling edges to report if sensors fail to provide entropy. * * It uses vetted conditioner as SHA512/256 (approved hash algorithm) * to condense entropy. As per NIST.SP.800-90B spec, to get full entropy * from vetted conditioner, we need to supply double of input entropy. * According to assumption above and requirement for vetted conditioner, * we need to supply 28 raw sensor readings to get 1 byte of full * entropy as output. So for 32 bytes of conditioner output, we need to * supply 896 bytes of raw sensor readings. * * Interfaces -> Input * ------------------- * * void rng_collect_entropy(void); * * Called as part of secure timer interrupt handler to sample raw * thermal sensor readings and add entropy to the pool. * * Interfaces -> Output * -------------------- * * TEE_Result rng_get_entropy(uint32_t types, * TEE_Param params[TEE_NUM_PARAMS]); * * Invoke command to expose an entropy interface to normal world. * * Testing * ======= * * Passes FIPS 140-2 rngtest. * * Limitations * =========== * * Output rate is limited to approx. 125 bytes per second. * * Our entropy estimation was not reached using any approved or * published estimation framework such as NIST.SP.800-90B and was tested * on a very small set of physical samples. Instead we have adopted what * we believe to be a conservative estimate and partnered it with a * fairly agressive health check. * * Generating the SHA512/256 hash takes 24uS and will be run by an * interrupt handler that pre-empts the normal world. */ #include #include #include #include #include #include #include #include #include #include "synquacer_rng_pta.h" #define PTA_NAME "rng.pta" #define THERMAL_SENSOR_BASE0 0x54190800 #define THERMAL_SENSOR_OFFSET 0x80 #define NUM_SENSORS 7 #define NUM_SLOTS ((NUM_SENSORS * 2) - 1) #define TEMP_DATA_REG_OFFSET 0x34 #define ENTROPY_POOL_SIZE 4096 #define SENSOR_DATA_SIZE 128 #define CONDITIONER_PAYLOAD (SENSOR_DATA_SIZE * NUM_SENSORS) /* * The health test monitors each sensor's least significant bit and counts * the number of rising and falling edges. It verifies that both counts * lie within interval of between 12.5% and 37.5% of the samples. * For true random data with 8 bits of entropy per byte, both counts would * be close to 25%. */ #define MAX_BIT_FLIP_EDGE_COUNT ((3 * SENSOR_DATA_SIZE) / 8) #define MIN_BIT_FLIP_EDGE_COUNT (SENSOR_DATA_SIZE / 8) static uint8_t entropy_pool[ENTROPY_POOL_SIZE] = {0}; static uint32_t entropy_size; static uint8_t sensors_data[NUM_SLOTS][SENSOR_DATA_SIZE] = {0}; static uint8_t sensors_data_slot_idx; static uint8_t sensors_data_idx; static uint32_t health_test_fail_cnt; static uint32_t health_test_cnt; static unsigned int entropy_lock = SPINLOCK_UNLOCK; static void pool_add_entropy(uint8_t *entropy, uint32_t size) { uint32_t copy_size = 0; if (entropy_size >= ENTROPY_POOL_SIZE) return; if ((ENTROPY_POOL_SIZE - entropy_size) >= size) copy_size = size; else copy_size = ENTROPY_POOL_SIZE - entropy_size; memcpy((entropy_pool + entropy_size), entropy, copy_size); entropy_size += copy_size; } static void pool_get_entropy(uint8_t *buf, uint32_t size) { uint32_t off = 0; if (size > entropy_size) return; off = entropy_size - size; memcpy(buf, &entropy_pool[off], size); entropy_size -= size; } static bool health_test(uint8_t sensor_id) { uint32_t falling_edge_count = 0; uint32_t rising_edge_count = 0; uint32_t lo_edge_count = 0; uint32_t hi_edge_count = 0; uint32_t i = 0; for (i = 0; i < (SENSOR_DATA_SIZE - 1); i++) { if ((sensors_data[sensor_id][i] ^ sensors_data[sensor_id][i + 1]) & 0x1) { falling_edge_count += (sensors_data[sensor_id][i] & 0x1); rising_edge_count += (sensors_data[sensor_id][i + 1] & 0x1); } } lo_edge_count = rising_edge_count < falling_edge_count ? rising_edge_count : falling_edge_count; hi_edge_count = rising_edge_count < falling_edge_count ? falling_edge_count : rising_edge_count; return (lo_edge_count >= MIN_BIT_FLIP_EDGE_COUNT) && (hi_edge_count <= MAX_BIT_FLIP_EDGE_COUNT); } static uint8_t pool_check_add_entropy(void) { uint32_t i = 0; uint8_t entropy_sha512_256[TEE_SHA256_HASH_SIZE]; uint8_t pool_status = 0; TEE_Result res = TEE_ERROR_GENERIC; for (i = 0; i < NUM_SENSORS; i++) { /* Check if particular sensor data passes health test */ if (health_test(sensors_data_slot_idx) == true) { sensors_data_slot_idx++; } else { health_test_fail_cnt++; memmove(sensors_data[sensors_data_slot_idx], sensors_data[sensors_data_slot_idx + 1], (SENSOR_DATA_SIZE * (NUM_SENSORS - i - 1))); } } health_test_cnt += NUM_SENSORS; /* Check if sensors_data have enough pass data for conditioning */ if (sensors_data_slot_idx >= NUM_SENSORS) { /* * Use vetted conditioner SHA512/256 as per * NIST.SP.800-90B to condition raw data from entropy * source. */ sensors_data_slot_idx -= NUM_SENSORS; res = hash_sha512_256_compute(entropy_sha512_256, sensors_data[sensors_data_slot_idx], CONDITIONER_PAYLOAD); if (res == TEE_SUCCESS) pool_add_entropy(entropy_sha512_256, TEE_SHA256_HASH_SIZE); } if (entropy_size >= ENTROPY_POOL_SIZE) pool_status = 1; return pool_status; } void rng_collect_entropy(void) { uint8_t i = 0; void *vaddr = 0; uint8_t pool_full = 0; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&entropy_lock); for (i = 0; i < NUM_SENSORS; i++) { vaddr = phys_to_virt_io(THERMAL_SENSOR_BASE0 + (THERMAL_SENSOR_OFFSET * i) + TEMP_DATA_REG_OFFSET, sizeof(uint32_t)); sensors_data[sensors_data_slot_idx + i][sensors_data_idx] = (uint8_t)io_read32((vaddr_t)vaddr); } sensors_data_idx++; if (sensors_data_idx >= SENSOR_DATA_SIZE) { pool_full = pool_check_add_entropy(); sensors_data_idx = 0; } if (pool_full) generic_timer_stop(); cpu_spin_unlock_xrestore(&entropy_lock, exceptions); } static TEE_Result rng_get_entropy(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t *e = NULL; uint32_t rq_size = 0; uint32_t pool_size = 0; uint32_t exceptions = 0; TEE_Result res = TEE_SUCCESS; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { EMSG("bad parameters types: 0x%" PRIx32, types); return TEE_ERROR_BAD_PARAMETERS; } rq_size = params[0].memref.size; if ((rq_size == 0) || (rq_size > ENTROPY_POOL_SIZE)) return TEE_ERROR_NOT_SUPPORTED; e = (uint8_t *)params[0].memref.buffer; if (!e) return TEE_ERROR_BAD_PARAMETERS; exceptions = cpu_spin_lock_xsave(&entropy_lock); /* * Report health test failure to normal world in case fail count * exceeds 1% of pass count. */ if (health_test_fail_cnt > ((health_test_cnt + 100) / 100)) { res = TEE_ERROR_HEALTH_TEST_FAIL; params[0].memref.size = 0; health_test_cnt = 0; health_test_fail_cnt = 0; goto exit; } pool_size = entropy_size; if (pool_size < rq_size) { params[0].memref.size = pool_size; pool_get_entropy(e, pool_size); } else { params[0].memref.size = rq_size; pool_get_entropy(e, rq_size); } exit: /* Enable timer FIQ to fetch entropy */ generic_timer_start(TIMER_PERIOD_MS); cpu_spin_unlock_xrestore(&entropy_lock, exceptions); return res; } static TEE_Result rng_get_info(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { EMSG("bad parameters types: 0x%" PRIx32, types); return TEE_ERROR_BAD_PARAMETERS; } /* Output RNG rate (per second) */ params[0].value.a = 125; /* * Quality/entropy per 1024 bit of output data. As we have used * a vetted conditioner as per NIST.SP.800-90B to provide full * entropy given our assumption of entropy estimate for raw sensor * data. */ params[0].value.b = 1024; return TEE_SUCCESS; } static TEE_Result invoke_command(void *pSessionContext __unused, uint32_t nCommandID, uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]) { FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME); switch (nCommandID) { case PTA_CMD_GET_ENTROPY: return rng_get_entropy(nParamTypes, pParams); case PTA_CMD_GET_RNG_INFO: return rng_get_info(nParamTypes, pParams); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_RNG_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_DEVICE_ENUM, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/arch/arm/plat-synquacer/sub.mk000066400000000000000000000000731464416617300220650ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += rng_pta.c optee_os-4.3.0/core/arch/arm/plat-synquacer/synquacer_rng_pta.h000066400000000000000000000003401464416617300246350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2018-2022, Linaro Limited */ #ifndef __SYNQUACER_RNG_PTA_H #define __SYNQUACER_RNG_PTA_H void rng_collect_entropy(void); #endif /* __SYNQUACER_RNG_PTA_H */ optee_os-4.3.0/core/arch/arm/plat-ti/000077500000000000000000000000001464416617300173455ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-ti/a9_plat_init.S000066400000000000000000000037121464416617300220500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ * Andrew Davis */ /* * Entry points for the A9 init. * It is assumed no stack is available when these routines are called. * It is assumed each routine is called with return address in LR * and with ARM registers R0, R1, R2, R3 being scratchable. */ #include #include #include #include #include .arch_extension sec .section .text .balign 4 .code 32 booted: .word 0 /* * Cortex A9 check for resume * * Use scratables registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* Check if we are resuming */ ldr r3, =booted ldr r2, [r3] cmp r2, #0 /* Cold boot, mark our boot flag and return to normal boot */ moveq r2, #1 streq r2, [r3] bxeq lr /* Otherwise we are resuming */ b resume_springboard END_FUNC plat_cpu_reset_early LOCAL_FUNC resume_springboard , : UNWIND( .cantunwind) /* Setup tmp stack */ bl __get_core_pos cmp r0, #CFG_TEE_CORE_NB_CORE /* Unsupported CPU, park it before it breaks something */ unhandled_cpu: wfige bge unhandled_cpu add r0, r0, #1 ldr r1, =stack_tmp_stride ldr r1, [r1] mul r1, r0, r1 ldr r0, =stack_tmp #if (STACK_TMP_GUARD != 0) mov_imm r2, STACK_TMP_GUARD sub r0, r0, r2 #endif add sp, r1, r0 /* Push our return on the stack as sm_pm_cpu_do_resume expects */ adr lr, after_resume push {r4 - r12, lr} /* Assumes suspend_regs is flat-mapped */ ldr r0, =suspend_regs bl sm_pm_cpu_do_resume after_resume: bl thread_init_per_cpu /* r5 contains the non-secure entry address (ARMv7 bootarg #0) */ mov r0, r5 bl init_sec_mon bl boot_primary_init_intc mov r0, #TEESMC_OPTEED_RETURN_ENTRY_DONE mov r1, #0 mov r2, #0 mov r3, #0 mov r4, #0 smc #0 b . /* SMC should not return */ END_FUNC resume_springboard optee_os-4.3.0/core/arch/arm/plat-ti/api_monitor_index_a15.h000066400000000000000000000025231464416617300236750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ * Andrew Davis */ #ifndef API_MONITOR_INDEX_H #define API_MONITOR_INDEX_H #define API_HAL_RET_VALUE_OK 0x00000000 #define API_HAL_RET_VALUE_SERVICE_UNKNWON 0xFFFFFFFF /* Base Index of APIs */ #define API_MONITOR_BASE_INDEX 0x00000100 /* HyperVisor Start */ #define API_MONITOR_HYP_STARTHYPERVISOR_INDEX (API_MONITOR_BASE_INDEX + 0x00000002) /* Caches cleaning */ #define API_MONITOR_CACHES_CLEAN_INDEX (API_MONITOR_BASE_INDEX + 0x00000003) /* Write the L2 Cache Controller Auxiliary Control */ #define API_MONITOR_L2ACTLR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000004) /* Set the Data and Tag RAM Latency */ #define API_MONITOR_L2CACHE_SETLATENCY_INDEX (API_MONITOR_BASE_INDEX + 0x00000005) /* L2 Cache Prefetch Control Register */ #define API_MONITOR_L2PFR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000006) /* Set Auxiliary Control Register */ #define API_MONITOR_ACTLR_SETREGISTER_INDEX (API_MONITOR_BASE_INDEX + 0x00000007) /* AMBA IF mode */ #define API_MONITOR_WUGEN_MPU_SETAMBAIF_INDEX (API_MONITOR_BASE_INDEX + 0x00000008) /* Timer CNTFRQ register set */ #define API_MONITOR_TIMER_SETCNTFRQ_INDEX (API_MONITOR_BASE_INDEX + 0x00000009) #endif /* API_MONITOR_INDEX_H */ optee_os-4.3.0/core/arch/arm/plat-ti/api_monitor_index_a9.h000066400000000000000000000026141464416617300236210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ * Andrew Davis */ #ifndef API_MONITOR_INDEX_H #define API_MONITOR_INDEX_H #define API_HAL_RET_VALUE_OK 0x00000000 #define API_HAL_RET_VALUE_SERVICE_UNKNWON 0xFFFFFFFF /* Base for power management related services */ #define SECURE_SVC_PM 0x70 /* Carry out late actions as part of suspend sequence */ #define SECURE_SVC_PM_LATE_SUSPEND (SECURE_SVC_PM + 1) /* Base Index of APIs */ #define API_MONITOR_BASE_INDEX 0x00000100 /* Set the Debug control register */ #define API_MONITOR_L2CACHE_SETDEBUG_INDEX (API_MONITOR_BASE_INDEX + 0x00000000) /* Clean and invalidate physical address range */ #define API_MONITOR_L2CACHE_CLEANINVBYPA_INDEX (API_MONITOR_BASE_INDEX + 0x00000001) /* Enables/Disables the PL310 Cache */ #define API_MONITOR_L2CACHE_SETCONTROL_INDEX (API_MONITOR_BASE_INDEX + 0x00000002) /* Set the Auxiliary Control Register */ #define API_MONITOR_L2CACHE_SETAUXILIARYCONTROL_INDEX (API_MONITOR_BASE_INDEX + 0x00000009) /* Set the Data and Tag RAM Latency */ #define API_MONITOR_L2CACHE_SETLATENCY_INDEX (API_MONITOR_BASE_INDEX + 0x00000012) /* Set the Pre-fetch Control Register */ #define API_MONITOR_L2CACHE_SETPREFETCHCONTROL_INDEX (API_MONITOR_BASE_INDEX + 0x00000013) #endif /* API_MONITOR_INDEX_H */ optee_os-4.3.0/core/arch/arm/plat-ti/conf.mk000066400000000000000000000017631464416617300206320ustar00rootroot00000000000000PLATFORM_FLAVOR ?= dra7xx CFG_WITH_STATS ?= y CFG_WITH_SOFTWARE_PRNG ?= n ifeq ($(PLATFORM_FLAVOR),dra7xx) include core/arch/arm/cpu/cortex-a15.mk $(call force,CFG_TEE_CORE_NB_CORE,2) CFG_OTP_SUPPORT ?= y $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) endif #dra7xx ifeq ($(PLATFORM_FLAVOR),am57xx) include core/arch/arm/cpu/cortex-a15.mk $(call force,CFG_TEE_CORE_NB_CORE,2) CFG_OTP_SUPPORT ?= y $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) endif #am57xx ifeq ($(PLATFORM_FLAVOR),am43xx) include core/arch/arm/cpu/cortex-a9.mk $(call force, CFG_TEE_CORE_NB_CORE,1) CFG_WITH_SOFTWARE_PRNG = y $(call force,CFG_NO_SMP,y) $(call force,CFG_PL310,y) $(call force,CFG_PL310_LOCKED,y) $(call force,CFG_PM_ARM32,y) $(call force,CFG_SECURE_TIME_SOURCE_REE,y) endif #am43xx $(call force,CFG_8250_UART,y) $(call force,CFG_ARM32_core,y) $(call force,CFG_SM_PLATFORM_HANDLER,y) $(call force,CFG_GIC,y) ifneq ($(CFG_WITH_SOFTWARE_PRNG),y) $(call force,CFG_DRA7_RNG,y) CFG_HWRNG_QUALITY ?= 1024 CFG_HWRNG_PTA ?= y endif optee_os-4.3.0/core/arch/arm/plat-ti/main.c000066400000000000000000000067101464416617300204410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PLAT_HW_UNIQUE_KEY_LENGTH 32 static struct serial8250_uart_data console_data; static uint8_t plat_huk[PLAT_HW_UNIQUE_KEY_LENGTH]; register_phys_mem(MEM_AREA_RAM_SEC, TZDRAM_BASE, TEE_RAM_VA_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SECRAM_BASE, SECRAM_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GICC_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GICD_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE); void boot_primary_init_intc(void) { gic_init(GICC_BASE, GICD_BASE); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } struct plat_nsec_ctx { uint32_t usr_sp; uint32_t usr_lr; uint32_t svc_sp; uint32_t svc_lr; uint32_t svc_spsr; uint32_t abt_sp; uint32_t abt_lr; uint32_t abt_spsr; uint32_t und_sp; uint32_t und_lr; uint32_t und_spsr; uint32_t irq_sp; uint32_t irq_lr; uint32_t irq_spsr; uint32_t fiq_sp; uint32_t fiq_lr; uint32_t fiq_spsr; uint32_t fiq_rx[5]; uint32_t mon_lr; uint32_t mon_spsr; }; struct plat_boot_args { struct plat_nsec_ctx nsec_ctx; uint8_t huk[PLAT_HW_UNIQUE_KEY_LENGTH]; }; void init_sec_mon(unsigned long nsec_entry) { struct plat_boot_args *plat_boot_args; struct sm_nsec_ctx *nsec_ctx; plat_boot_args = phys_to_virt(nsec_entry, MEM_AREA_IO_SEC, 1); if (!plat_boot_args) panic(); /* Invalidate cache to fetch data from external memory */ cache_op_inner(DCACHE_AREA_INVALIDATE, plat_boot_args, sizeof(*plat_boot_args)); /* Initialize secure monitor */ nsec_ctx = sm_get_nsec_ctx(); nsec_ctx->ub_regs.usr_sp = plat_boot_args->nsec_ctx.usr_sp; nsec_ctx->ub_regs.usr_lr = plat_boot_args->nsec_ctx.usr_lr; nsec_ctx->ub_regs.irq_spsr = plat_boot_args->nsec_ctx.irq_spsr; nsec_ctx->ub_regs.irq_sp = plat_boot_args->nsec_ctx.irq_sp; nsec_ctx->ub_regs.irq_lr = plat_boot_args->nsec_ctx.irq_lr; nsec_ctx->ub_regs.svc_spsr = plat_boot_args->nsec_ctx.svc_spsr; nsec_ctx->ub_regs.svc_sp = plat_boot_args->nsec_ctx.svc_sp; nsec_ctx->ub_regs.svc_lr = plat_boot_args->nsec_ctx.svc_lr; nsec_ctx->ub_regs.abt_spsr = plat_boot_args->nsec_ctx.abt_spsr; nsec_ctx->ub_regs.abt_sp = plat_boot_args->nsec_ctx.abt_sp; nsec_ctx->ub_regs.abt_lr = plat_boot_args->nsec_ctx.abt_lr; nsec_ctx->ub_regs.und_spsr = plat_boot_args->nsec_ctx.und_spsr; nsec_ctx->ub_regs.und_sp = plat_boot_args->nsec_ctx.und_sp; nsec_ctx->ub_regs.und_lr = plat_boot_args->nsec_ctx.und_lr; nsec_ctx->mon_lr = plat_boot_args->nsec_ctx.mon_lr; nsec_ctx->mon_spsr = plat_boot_args->nsec_ctx.mon_spsr; memcpy(plat_huk, plat_boot_args->huk, sizeof(plat_boot_args->huk)); } void plat_console_init(void) { serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } #if defined(CFG_OTP_SUPPORT) TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { memcpy(&hwkey->data[0], &plat_huk[0], sizeof(hwkey->data)); return TEE_SUCCESS; } #endif optee_os-4.3.0/core/arch/arm/plat-ti/platform_config.h000066400000000000000000000074231464416617300226750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE 0x80000000 #if defined(PLATFORM_FLAVOR_dra7xx) || defined(PLATFORM_FLAVOR_am57xx) /* Location of protected DDR on the DRA7xx platform */ #define TZDRAM_BASE 0xbdb00000 #define TZDRAM_SIZE 0x01c00000 #ifdef CFG_WITH_PAGER #define TZSRAM_BASE 0x40300000 #define TZSRAM_SIZE (256 * 1024) #endif /* CFG_WITH_PAGER */ #define UART1_BASE 0x4806A000 #define UART2_BASE 0x4806C000 #define UART3_BASE 0x48020000 #if defined(PLATFORM_FLAVOR_dra7xx) #define CONSOLE_UART_BASE UART1_BASE #elif defined(PLATFORM_FLAVOR_am57xx) #define CONSOLE_UART_BASE UART3_BASE #else #error "Unknown platform flavor" #endif #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 48000000 #define SCU_BASE 0x48210000 #define GICC_OFFSET 0x2000 #define GICC_SIZE 0x1000 #define GICD_OFFSET 0x1000 #define GICD_SIZE 0x1000 #define GICC_BASE (SCU_BASE + GICC_OFFSET) #define GICD_BASE (SCU_BASE + GICD_OFFSET) #define WUGEN_MPU_BASE 0x48281000 #define WUGEN_MPU_SIZE 0x1000 #define SECRAM_BASE 0x40200000 #define SECRAM_SIZE 0x00100000 /* RNG */ #define RNG_BASE 0x48090000 #elif defined(PLATFORM_FLAVOR_am43xx) /* Location of protected DDR on the AM43xx platform */ #define TZDRAM_BASE 0xbdb00000 #define TZDRAM_SIZE 0x01c00000 #define UART0_BASE 0x44E09000 #define UART1_BASE 0x48022000 #define UART2_BASE 0x48024000 #define UART3_BASE 0x481A6000 #define UART4_BASE 0x481A8000 #define UART5_BASE 0x481AA000 #define CONSOLE_UART_BASE UART0_BASE #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 48000000 #define SCU_BASE 0x48240000 #define GICD_OFFSET 0x1000 #define GICD_SIZE 0x1000 #define GICC_OFFSET 0x0100 #define GICC_SIZE 0x0100 #define PL310_OFFSET 0x2000 #define PL310_SIZE 0x1000 #define GICD_BASE (SCU_BASE + GICD_OFFSET) #define GICC_BASE (SCU_BASE + GICC_OFFSET) #define PL310_BASE (SCU_BASE + PL310_OFFSET) #define SECRAM_BASE 0x402F0000 #define SECRAM_SIZE 0x00100000 /* RNG */ #define RNG_BASE 0x48310000 #else #error "Unknown platform flavor" #endif /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #ifdef CFG_WITH_PAGER /* * Use TZSRAM for TEE, page out everything else to TZDRAM. * +--------+----------+ * | DRAM | SHMEM | * +--------+----------+ * | | TA_RAM | * | TZDRAM +----------+ * | | PAGE_RAM | * +--------+----------+ * | TZSRAM | TEE_RAM | * +--------+----------+ */ #define TEE_RAM_VA_SIZE (1 * 1024 * 1024) #define TEE_RAM_PH_SIZE TZSRAM_SIZE #define TEE_RAM_START TZSRAM_BASE #define TEE_LOAD_ADDR (TEE_RAM_START + 0x1000) #else /* CFG_WITH_PAGER */ /* * Assumes that either TZSRAM isn't large enough or TZSRAM doesn't exist, * everything is in TZDRAM. * +--------+---------+ * | DRAM | SHMEM | * +--------+---------+ * | | TA_RAM | * | TZDRAM +---------+ * | | TEE_RAM | * +--------+---------+ */ #define TEE_RAM_VA_SIZE (1 * 1024 * 1024) #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE #define TEE_RAM_START TZDRAM_BASE #define TEE_LOAD_ADDR TEE_RAM_START #endif /* CFG_WITH_PAGER */ #define TA_RAM_START ROUNDUP((TZDRAM_BASE + TEE_RAM_VA_SIZE), \ CORE_MMU_PGDIR_SIZE) #define TA_RAM_SIZE ROUNDDOWN((TZDRAM_SIZE - TEE_RAM_VA_SIZE), \ CORE_MMU_PGDIR_SIZE) /* Full GlobalPlatform test suite requires TEE_SHMEM_SIZE to be at least 2MB */ #define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) #define TEE_SHMEM_SIZE (4 * 1024 * 1024) #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-ti/sm_platform_handler_a15.c000066400000000000000000000035041464416617300242010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ * Andrew Davis */ #include #include #include #include #include #include #include #include #include "api_monitor_index_a15.h" #define WUGEN_MPU_AMBA_IF_MODE 0x80c register_phys_mem_pgdir(MEM_AREA_IO_SEC, WUGEN_MPU_BASE, WUGEN_MPU_SIZE); static vaddr_t wugen_mpu_base(void) { static void *va; if (cpu_mmu_enabled()) { if (!va) va = phys_to_virt(WUGEN_MPU_BASE, MEM_AREA_IO_SEC, WUGEN_MPU_SIZE); return (vaddr_t)va; } return WUGEN_MPU_BASE; } static void write_wugen_mpu_amba_if_mode(uint32_t val) { io_write32(wugen_mpu_base() + WUGEN_MPU_AMBA_IF_MODE, val); } static enum sm_handler_ret ti_sip_handler(struct thread_smc_args *smc_args) { uint16_t sip_func = OPTEE_SMC_FUNC_NUM(smc_args->a0); switch (sip_func) { case API_MONITOR_ACTLR_SETREGISTER_INDEX: write_actlr(smc_args->a1); isb(); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_TIMER_SETCNTFRQ_INDEX: write_cntfrq(smc_args->a1); isb(); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_WUGEN_MPU_SETAMBAIF_INDEX: write_wugen_mpu_amba_if_mode(smc_args->a1); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; default: EMSG("Invalid SIP function code: 0x%04"PRIx16, sip_func); smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; break; } return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) { uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); switch (smc_owner) { case OPTEE_SMC_OWNER_SIP: return ti_sip_handler((struct thread_smc_args *)nsec_r0); default: return SM_HANDLER_PENDING_SMC; } } optee_os-4.3.0/core/arch/arm/plat-ti/sm_platform_handler_a9.c000066400000000000000000000046561464416617300241350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ * Andrew Davis */ #include #include #include #include #include #include #include #include #include #include #include #include #include "api_monitor_index_a9.h" uint32_t suspend_regs[16]; static enum sm_handler_ret ti_sip_handler(struct thread_smc_args *smc_args) { uint16_t sip_func = OPTEE_SMC_FUNC_NUM(smc_args->a0); switch (sip_func) { case SECURE_SVC_PM_LATE_SUSPEND: sm_pm_cpu_do_suspend(suspend_regs); cache_op_inner(DCACHE_AREA_CLEAN, suspend_regs, sizeof(suspend_regs)); cache_op_outer(DCACHE_AREA_CLEAN, virt_to_phys(suspend_regs), sizeof(suspend_regs)); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_L2CACHE_SETDEBUG_INDEX: io_write32(pl310_base() + PL310_DEBUG_CTRL, smc_args->a1); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_L2CACHE_CLEANINVBYPA_INDEX: arm_cl2_cleaninvbypa(pl310_base(), smc_args->a1, smc_args->a1 + smc_args->a2); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_L2CACHE_SETCONTROL_INDEX: io_write32(pl310_base() + PL310_CTRL, smc_args->a1); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_L2CACHE_SETAUXILIARYCONTROL_INDEX: io_write32(pl310_base() + PL310_AUX_CTRL, smc_args->a1); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_L2CACHE_SETLATENCY_INDEX: io_write32(pl310_base() + PL310_TAG_RAM_CTRL, smc_args->a1); io_write32(pl310_base() + PL310_DATA_RAM_CTRL, smc_args->a2); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; case API_MONITOR_L2CACHE_SETPREFETCHCONTROL_INDEX: io_write32(pl310_base() + PL310_PREFETCH_CTRL, smc_args->a1); smc_args->a0 = OPTEE_SMC_RETURN_OK; break; default: EMSG("Invalid SIP function code: 0x%04"PRIx16, sip_func); smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD; break; } return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret sm_platform_handler(struct sm_ctx *ctx) { uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); uint16_t smc_owner = OPTEE_SMC_OWNER_NUM(*nsec_r0); switch (smc_owner) { case OPTEE_SMC_OWNER_SIP: return ti_sip_handler((struct thread_smc_args *)nsec_r0); default: return SM_HANDLER_PENDING_SMC; } } optee_os-4.3.0/core/arch/arm/plat-ti/sub.mk000066400000000000000000000004111464416617300204630ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-$(CFG_PL310) += ti_pl310.c srcs-$(PLATFORM_FLAVOR_dra7xx) += sm_platform_handler_a15.c srcs-$(PLATFORM_FLAVOR_am57xx) += sm_platform_handler_a15.c srcs-$(PLATFORM_FLAVOR_am43xx) += sm_platform_handler_a9.c a9_plat_init.S optee_os-4.3.0/core/arch/arm/plat-ti/ti_pl310.c000066400000000000000000000015261464416617300210500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ * Andrew Davis */ #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, PL310_SIZE); vaddr_t pl310_base(void) { static void *va; if (cpu_mmu_enabled()) { if (!va) va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, PL310_SIZE); return (vaddr_t)va; } return PL310_BASE; } /* ROM handles initial setup for us */ void arm_cl2_config(vaddr_t pl310_base) { (void)pl310_base; } /* We provide platform services that expect the cache to be disabled on boot */ void arm_cl2_enable(vaddr_t pl310_base) { (void)pl310_base; } optee_os-4.3.0/core/arch/arm/plat-totalcompute/000077500000000000000000000000001464416617300214515ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-totalcompute/conf.mk000066400000000000000000000021461464416617300227320ustar00rootroot00000000000000ifneq (,$(filter ${PLATFORM_FLAVOR},tc0 tc1 tc2)) include core/arch/arm/cpu/cortex-armv8-0.mk platform-debugger-arm := 1 endif $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_GENERIC_BOOT,y) ifeq ($(CFG_CORE_SEL2_SPMC),y) $(call force,CFG_GIC,n) $(call force,CFG_ARM_GICV3,n) else $(call force,CFG_GIC,y) $(call force,CFG_ARM_GICV3,y) endif $(call force,CFG_PL011,y) $(call force,CFG_PM_STUBS,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_ARM64_core,y) ifeq ($(platform-debugger-arm),1) # ARM debugger needs this platform-cflags-debug-info = -gdwarf-2 platform-aflags-debug-info = -gdwarf-2 endif $(call force,CFG_CORE_ARM64_PA_BITS,40) ifneq (,$(filter ${PLATFORM_FLAVOR},tc0 tc1 tc2)) CFG_TEE_CORE_NB_CORE = 8 ifeq ($(CFG_CORE_SEL1_SPMC),y) CFG_TZDRAM_START ?= 0xfd000000 CFG_TZDRAM_SIZE ?= 0x02000000 else ifeq ($(CFG_CORE_SEL2_SPMC),y) CFG_TZDRAM_START ?= 0xfd284000 # TZDRAM size 0x1980000 - 0x4000 manifest size CFG_TZDRAM_SIZE ?= 0x0197c000 else CFG_TZDRAM_START ?= 0xff000000 CFG_TZDRAM_SIZE ?= 0x01000000 endif CFG_SHMEM_START ?= 0xfce00000 CFG_SHMEM_SIZE ?= 0x00200000 endif optee_os-4.3.0/core/arch/arm/plat-totalcompute/fdts/000077500000000000000000000000001464416617300224115ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-totalcompute/fdts/optee_sp_manifest.dts000066400000000000000000000016101464416617300266270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2023, Arm Limited. All rights reserved. * * This file is a Partition Manifest (PM) for OP-TEE as a Secure Partition (SP) * */ /dts-v1/; / { compatible = "arm,ffa-manifest-1.0"; /* Properties */ description = "op-tee"; ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */ uuid = <0xe0786148 0xe311f8e7 0x02005ebc 0x1bc5d5a5>; id = <1>; execution-ctx-count = <8>; exception-level = <2>; /* S-EL1 */ execution-state = <0>; /* AARCH64 */ load-address = <0xfd280000>; entrypoint-offset = <0x4000>; xlat-granule = <0>; /* 4KiB */ boot-order = <0>; messaging-method = <0x3>; /* Direct request/response supported */ device-regions { compatible = "arm,ffa-manifest-device-regions"; ap_s_uart { base-address = <0x00000000 0x2A410000>; pages-count = <1>; attributes = <0x3>; /* read-write */ }; }; }; optee_os-4.3.0/core/arch/arm/plat-totalcompute/main.c000066400000000000000000000017131464416617300225430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Arm Limited. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include static struct pl011_data console_data __nex_bss; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); #ifndef CFG_CORE_SEL2_SPMC register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); #endif register_ddr(DRAM0_BASE, DRAM0_SIZE); register_ddr(DRAM1_BASE, DRAM1_SIZE); #ifndef CFG_CORE_SEL2_SPMC void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICC_OFFSET); } #endif void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_UART_BAUDRATE); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-totalcompute/platform_config.h000066400000000000000000000020611464416617300247720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021-2023, Arm Limited. All rights reserved. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #if (defined(PLATFORM_FLAVOR_tc0) || \ defined(PLATFORM_FLAVOR_tc1) || \ defined(PLATFORM_FLAVOR_tc2)) #ifndef CFG_CORE_SEL2_SPMC #define GIC_BASE 0x30000000 #define GICD_OFFSET 0x0 #define GICC_OFFSET 0x0 #endif #define UART0_BASE 0x2A410000 #define UART1_BASE 0x2A400000 #define CONSOLE_UART_BASE UART0_BASE #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE 0x7d000000 #define DRAM1_BASE 0x8080000000ULL #define DRAM1_SIZE 0x180000000ULL #define TZCDRAM_BASE 0xff000000 #define TZCDRAM_SIZE 0x01000000 #else #error "Unknown platform flavor" #endif #ifdef GIC_BASE #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) #endif #define CONSOLE_UART_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 7372800 #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-totalcompute/sub.mk000066400000000000000000000000471464416617300225740ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-uniphier/000077500000000000000000000000001464416617300205545ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-uniphier/conf.mk000066400000000000000000000021651464416617300220360ustar00rootroot00000000000000PLATFORM_FLAVOR ?= ld20 include core/arch/arm/cpu/cortex-armv8-0.mk ifeq ($(PLATFORM_FLAVOR),ld20) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_CORE_ARM64_PA_BITS,36) CFG_DRAM0_BASE ?= 0x80000000 CFG_DRAM0_SIZE ?= 0xc0000000 CFG_DRAM0_RSV_SIZE ?= 0x02000000 endif ifeq ($(PLATFORM_FLAVOR),ld11) $(call force,CFG_TEE_CORE_NB_CORE,2) CFG_DRAM0_BASE ?= 0x80000000 CFG_DRAM0_SIZE ?= 0x40000000 CFG_DRAM0_RSV_SIZE ?= 0x02000000 endif CFG_TZDRAM_START ?= (CFG_DRAM0_BASE + 0x01080000) CFG_TZDRAM_SIZE ?= 0x00E00000 CFG_SHMEM_START ?= (CFG_DRAM0_BASE + 0x00E00000) CFG_SHMEM_SIZE ?= 0x00200000 CFG_TEE_RAM_VA_SIZE ?= 0x00100000 # 32-bit flags core_arm32-platform-aflags += -mfpu=neon $(call force,CFG_HWSUPP_MEM_PERM_PXN,y) $(call force,CFG_GIC,y) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_8250_UART,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_CORE_CLUSTER_SHIFT,1) ta-targets = ta_arm32 ifeq ($(CFG_ARM64_core),y) ta-targets += ta_arm64 else $(call force,CFG_ARM32_core,y) endif CFG_NUM_THREADS ?= 4 CFG_CRYPTO_WITH_CE ?= y optee_os-4.3.0/core/arch/arm/plat-uniphier/kern.ld.S000066400000000000000000000001251464416617300222330ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND MIT) */ #include "../kernel/kern.ld.S" optee_os-4.3.0/core/arch/arm/plat-uniphier/main.c000066400000000000000000000022751464416617300216520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2017, Socionext Inc. */ #include #include #include #include #include #include #include #include #include register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(GIC_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); #ifdef DRAM0_BASE register_ddr(DRAM0_BASE, DRAM0_SIZE); #endif #ifdef DRAM1_BASE register_ddr(DRAM1_BASE, DRAM1_SIZE); #endif static struct serial8250_uart_data console_data; void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void plat_console_init(void) { /* Init UART */ serial8250_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); /* Register console */ register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/arm/plat-uniphier/platform_config.h000066400000000000000000000034401464416617300240770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2017, Socionext Inc. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 /* GIC */ #define GIC_BASE 0x5FE00000 #define GICD_OFFSET 0 #define GICC_OFFSET 0x80000 /* UART */ #define UART_CH 0 #define UART_BASE 0x54006800 #define CONSOLE_UART_BASE (UART_BASE + 0x100 * UART_CH) #define CONSOLE_BAUDRATE 115200 #define CONSOLE_UART_CLK_IN_HZ 58820000 /* * UniPhier memory map * * 0xXXXX_XXXX * Linux kernel and user space | DRAM#0-#x | Normal memory * 0x8200_0000 [DRAM0_BASE] - - * unused | | * 0x81E8_0000 | | * TA RAM: 13 MiB | TZDRAM | * 0x8118_0000 | | Secure memory * TEE RAM: 1 MiB (CFG_TEE_RAM_VA_SIZE) | | * 0x8108_0000 [CFG_TZDRAM_START] - | * BL31 runtime: 512 KiB | | * 0x8100_0000 | - * Shared memory: 2 MiB (CFG_SHMEM_SIZE) | | * 0x80E0_0000 [CFG_SHMEM_START] | DRAM#0 | Normal memory * reserved | | * 0x8008_0000 | | * BL2: 512 KiB | | * 0x8000_0000 [CFG_DRAM0_BASE] - - */ #define DRAM0_BASE (CFG_DRAM0_BASE + CFG_DRAM0_RSV_SIZE) #define DRAM0_SIZE (CFG_DRAM0_SIZE - CFG_DRAM0_RSV_SIZE) #define CFG_TEE_LOAD_ADDR CFG_TZDRAM_START #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-uniphier/sub.mk000066400000000000000000000000471464416617300216770ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-versal/000077500000000000000000000000001464416617300202255ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-versal/conf.mk000066400000000000000000000042021464416617300215010ustar00rootroot00000000000000PLATFORM_FLAVOR ?= generic include core/arch/arm/cpu/cortex-armv8-0.mk CFG_MMAP_REGIONS ?= 24 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_ARM_GICV3,y) $(call force,CFG_PL011,y) $(call force,CFG_GIC,y) # Disable core ASLR for two reasons: # 1. There is no source for ALSR seed, as TF-a does not provide a # DTB to OP-TEE. Hardware RNG is also not currently supported. # 2. Xilinx's bootgen can't find the OP-TEE entry point from the TEE.elf file # used to generate boot.bin. Enabling ASLR requires an update to TF-A. $(call force,CFG_CORE_ASLR,n) CFG_CRYPTO_WITH_CE ?= y CFG_CORE_DYN_SHM ?= y CFG_WITH_STATS ?= y CFG_ARM64_core ?= y CFG_TZDRAM_START ?= 0x60000000 CFG_TZDRAM_SIZE ?= 0x10000000 CFG_SHMEM_START ?= 0x70000000 CFG_SHMEM_SIZE ?= 0x10000000 ifeq ($(CFG_ARM64_core),y) $(call force,CFG_CORE_ARM64_PA_BITS,43) else $(call force,CFG_ARM32_core,y) endif # GPIO CFG_VERSAL_GPIO ?= y # Debug information CFG_VERSAL_TRACE_MBOX ?= n CFG_VERSAL_TRACE_PLM ?= n $(call force, CFG_VERSAL_MBOX,y) # MBOX configuration CFG_VERSAL_MBOX_IPI_ID ?= 3 $(call force, CFG_VERSAL_RNG_DRV,y) $(call force, CFG_WITH_SOFTWARE_PRNG,n) # TRNG configuration CFG_VERSAL_TRNG_SEED_LIFE ?= 3 CFG_VERSAL_TRNG_DF_MUL ?= 2 # eFuse and BBRAM driver $(call force, CFG_VERSAL_NVM,y) # Crypto driver CFG_VERSAL_CRYPTO_DRIVER ?= y ifeq ($(CFG_VERSAL_CRYPTO_DRIVER),y) # Disable Fault Mitigation: triggers false positives due to # the driver's software fallback operations - need further work CFG_FAULT_MITIGATION ?= n endif # SHA3-384 crypto engine CFG_VERSAL_SHA3_384 ?= y # PM driver CFG_VERSAL_PM ?= y # Physical Unclonable Function CFG_VERSAL_PUF ?= y # Enable Hardware Unique Key driver CFG_VERSAL_HUK ?= y # AES-GCM supported key sources for HUK: # 6 : eFUSE USR 0 # 7 : eFuse USR 1 # 11 : PUF KEK # 12 : AES User Key 0 (devel) CFG_VERSAL_HUK_KEY ?= 12 ifneq ($(CFG_VERSAL_HUK_KEY),$(filter 6 7 11 12,$(firstword $(CFG_VERSAL_HUK_KEY)))) $(error Invalid value: CFG_VERSAL_HUK_KEY=$(CFG_VERSAL_HUK_KEY)) endif CFG_CORE_HEAP_SIZE ?= 262144 optee_os-4.3.0/core/arch/arm/plat-versal/main.c000066400000000000000000000053161464416617300213220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VERSAL_AHWROT_SECURED 0xA5A5A5A5 #define VERSAL_SHWROT_SECURED 0x96969696 #define VERSAL_AHWROT_REG 0x14C #define VERSAL_SHWROT_REG 0x150 static struct pl011_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE); register_phys_mem(MEM_AREA_IO_SEC, PLM_RTCA, PLM_RTCA_LEN); register_ddr(DRAM0_BASE, DRAM0_SIZE); #if defined(DRAM1_BASE) register_ddr(DRAM1_BASE, DRAM1_SIZE); register_ddr(DRAM2_BASE, DRAM2_SIZE); #endif void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } static TEE_Result platform_banner(void) { vaddr_t plm_rtca = (vaddr_t)phys_to_virt(PLM_RTCA, MEM_AREA_IO_SEC, PLM_RTCA_LEN); const char __maybe_unused *ahwrot_str = "OFF"; const char __maybe_unused *shwrot_str = "OFF"; uint8_t version = 0; assert(plm_rtca); if (versal_soc_version(&version)) { EMSG("Failure to retrieve SoC version"); return TEE_ERROR_GENERIC; } IMSG("Platform Versal:\tSilicon Revision v%"PRIu8, version); if (io_read32(plm_rtca + VERSAL_AHWROT_REG) == VERSAL_AHWROT_SECURED) ahwrot_str = "ON"; if (io_read32(plm_rtca + VERSAL_SHWROT_REG) == VERSAL_SHWROT_SECURED) shwrot_str = "ON"; IMSG("Hardware Root of Trust: Asymmetric[%s], Symmetric[%s]", ahwrot_str, shwrot_str); return TEE_SUCCESS; } #if defined(CFG_RPMB_FS) bool plat_rpmb_key_is_ready(void) { vaddr_t plm_rtca = (vaddr_t)phys_to_virt(PLM_RTCA, MEM_AREA_IO_SEC, PLM_RTCA_LEN); assert(plm_rtca); if (io_read32(plm_rtca + VERSAL_AHWROT_REG) == VERSAL_AHWROT_SECURED) return true; if (io_read32(plm_rtca + VERSAL_SHWROT_REG) == VERSAL_SHWROT_SECURED) return true; return false; } #endif service_init(platform_banner); #if defined(CFG_VERSAL_FPGA_DDR_ADDR) static TEE_Result program_fpga(void) { return versal_write_fpga(CFG_VERSAL_FPGA_DDR_ADDR); } service_init(program_fpga); #endif optee_os-4.3.0/core/arch/arm/plat-versal/platform_config.h000066400000000000000000000025631464416617300235550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define CACHELINE_LEN 64 #define STACK_ALIGNMENT CACHELINE_LEN #if defined(PLATFORM_FLAVOR_generic) #define PLM_RTCA 0xF2014000 #define PLM_RTCA_LEN 0x1000 #define GIC_BASE 0xF9000000 #define UART0_BASE 0xFF000000 #define UART1_BASE 0xFF010000 #define IT_UART0 50 #define IT_UART1 51 #define UART0_CLK_IN_HZ 100000000 #define UART1_CLK_IN_HZ 100000000 #define CONSOLE_UART_BASE UART0_BASE #define IT_CONSOLE_UART IT_UART0 #define CONSOLE_UART_CLK_IN_HZ UART0_CLK_IN_HZ #define DRAM0_BASE 0 #define DRAM0_SIZE 0x80000000 #ifdef ARM64 /* DDR High area base is only available when compiling for 64 bits */ #define DRAM1_BASE 0x800000000 #define DRAM1_SIZE 0x180000000 #define DRAM2_BASE 0x50000000000 #define DRAM2_SIZE 0x200000000 #endif #define GICD_OFFSET 0 #define GICC_OFFSET 0x40000 #else #error "Unknown platform flavor" #endif #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else #define TEE_LOAD_ADDR TEE_RAM_START #endif #ifndef UART_BAUDRATE #define UART_BAUDRATE 115200 #endif #ifndef CONSOLE_BAUDRATE #define CONSOLE_BAUDRATE UART_BAUDRATE #endif #endif /* PLATFORM_CONFIG_H */ optee_os-4.3.0/core/arch/arm/plat-versal/sub.mk000066400000000000000000000000471464416617300213500ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/plat-vexpress/000077500000000000000000000000001464416617300206105ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-vexpress/conf.mk000066400000000000000000000115641464416617300220750ustar00rootroot00000000000000PLATFORM_FLAVOR ?= qemu_virt ifeq ($(PLATFORM_FLAVOR),qemu_virt) include core/arch/arm/cpu/cortex-a15.mk endif ifeq ($(PLATFORM_FLAVOR),fvp) include core/arch/arm/cpu/cortex-armv8-0.mk platform-debugger-arm := 1 endif ifeq ($(PLATFORM_FLAVOR),juno) include core/arch/arm/cpu/cortex-armv8-0.mk platform-debugger-arm := 1 # Workaround 808870: Unconditional VLDM instructions might cause an # alignment fault even though the address is aligned # Either hard float must be disabled for AArch32 or strict alignment checks # must be disabled ifeq ($(CFG_SCTLR_ALIGNMENT_CHECK),y) $(call force,CFG_TA_ARM32_NO_HARD_FLOAT_SUPPORT,y) else $(call force,CFG_SCTLR_ALIGNMENT_CHECK,n) endif endif #juno ifeq ($(PLATFORM_FLAVOR),qemu_armv8a) include core/arch/arm/cpu/cortex-armv8-0.mk CFG_ARM64_core ?= y supported-ta-targets ?= ta_arm64 ta_arm32 endif ifeq ($(platform-debugger-arm),1) # ARM debugger needs this platform-cflags-debug-info = -gdwarf-2 platform-aflags-debug-info = -gdwarf-2 endif ifeq ($(platform-flavor-armv8),1) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) endif $(call force,CFG_PL011,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) ifeq ($(CFG_CORE_TPM_EVENT_LOG),y) # NOTE: Below values for the TPM event log are implementation # dependent and used mostly for debugging purposes. # Care must be taken to properly configure them if used. CFG_TPM_LOG_BASE_ADDR ?= 0x402c951 CFG_TPM_MAX_LOG_SIZE ?= 0x200 endif ifneq ($(CFG_ARM64_core),y) $(call force,CFG_ARM32_core,y) endif CFG_WITH_STATS ?= y CFG_ENABLE_EMBEDDED_TESTS ?= y ifeq ($(CFG_CORE_SEL2_SPMC),y) $(call force,CFG_CORE_RESERVED_SHM,n) CFG_GIC ?= n else $(call force,CFG_GIC,y) endif ifeq ($(PLATFORM_FLAVOR),fvp) CFG_HALT_CORES_ON_PANIC ?= y CFG_TEE_CORE_NB_CORE ?= 8 ifeq ($(CFG_CORE_SEL2_SPMC),y) CFG_TZDRAM_START ?= 0x06281000 CFG_TZDRAM_SIZE ?= 0x01D80000 else CFG_TZDRAM_START ?= 0x06000000 CFG_TZDRAM_SIZE ?= 0x02000000 endif CFG_SHMEM_START ?= 0x83000000 CFG_SHMEM_SIZE ?= 0x00200000 # DRAM1 is defined above 4G $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) CFG_AUTO_MAX_PA_BITS ?= y ifeq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_SCPFW_PRODUCT,fvp) endif ifeq ($(CFG_CORE_SEL1_SPMC),y) CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 9 endif endif ifeq ($(PLATFORM_FLAVOR),juno) CFG_HALT_CORES_ON_PANIC ?= y CFG_TEE_CORE_NB_CORE ?= 6 CFG_TZDRAM_START ?= 0xff000000 CFG_TZDRAM_SIZE ?= 0x00ff8000 CFG_SHMEM_START ?= 0xfee00000 CFG_SHMEM_SIZE ?= 0x00200000 # DRAM1 is defined above 4G $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_CORE_ARM64_PA_BITS,36) CFG_CRYPTO_WITH_CE ?= y CFG_ARM_SMCCC_TRNG ?= y CFG_WITH_SOFTWARE_PRNG ?= n endif ifeq ($(PLATFORM_FLAVOR),qemu_virt) CFG_HALT_CORES_ON_PANIC ?= y CFG_TEE_CORE_NB_CORE ?= 4 # [0e00.0000 0e0f.ffff] is reserved to early boot CFG_TZDRAM_START ?= 0x0e100000 CFG_TZDRAM_SIZE ?= 0x00f00000 CFG_SHMEM_START ?= 0x7fe00000 CFG_SHMEM_SIZE ?= 0x00200000 # When Secure Data Path is enable, last MByte of TZDRAM is SDP test memory. CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 # Set VA space to 2MB for Kasan offset to match LPAE and 32bit MMU configs CFG_TEE_RAM_VA_SIZE ?= 0x00200000 ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) # CFG_ASAN_SHADOW_OFFSET is calculated as: # (&__asan_shadow_start - (TEE_RAM_VA_START / 8) # This is unfortunately currently not possible to do in make so we have to # calculate it offline, there's some asserts in # core/arch/arm/kernel/generic_boot.c to check that we got it right CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0 endif $(call force,CFG_BOOT_SECONDARY_REQUEST,y) $(call force,CFG_PSCI_ARM32,y) $(call force,CFG_DT,y) CFG_DTB_MAX_SIZE ?= 0x100000 CFG_CORE_ASYNC_NOTIF ?= y CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219 endif ifeq ($(PLATFORM_FLAVOR),qemu_armv8a) CFG_CORE_HEAP_SIZE ?= 131072 CFG_HALT_CORES_ON_PANIC ?= y CFG_TEE_CORE_NB_CORE ?= 4 CFG_AUTO_MAX_PA_BITS ?= y ifneq ($(CFG_CORE_SEL2_SPMC),y) # [0e00.0000 0e0f.ffff] is reserved to early boot CFG_TZDRAM_START ?= 0x0e100000 CFG_TZDRAM_SIZE ?= 0x00f00000 # SHM chosen arbitrary, in a way that it does not interfere # with initial location of linux kernel, dtb and initrd. CFG_SHMEM_START ?= 0x42000000 CFG_SHMEM_SIZE ?= 0x00200000 # When Secure Data Path is enable, last MByte of TZDRAM is SDP test memory. CFG_TEE_SDP_MEM_SIZE ?= 0x00400000 ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) # See comment above CFG_ASAN_SHADOW_OFFSET ?= 0xc6a71c0 endif endif $(call force,CFG_DT,y) CFG_DTB_MAX_SIZE ?= 0x100000 ifeq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_SCPFW_PRODUCT,fvp) endif CFG_CORE_ASYNC_NOTIF ?= y ifeq ($(CFG_CORE_SEL1_SPMC),y) CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 8 else ifneq ($(CFG_CORE_SEL2_SPMC),y) CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219 endif endif #PLATFORM_FLAVOR==qemu_armv8a ifneq (,$(filter $(PLATFORM_FLAVOR),qemu_virt qemu_armv8a)) CFG_DT_DRIVER_EMBEDDED_TEST ?= y ifeq ($(CFG_DT_DRIVER_EMBEDDED_TEST),y) $(call force,CFG_EMBED_DTB_SOURCE_FILE,embedded_dtb_test.dts,Mandated for DT tests) endif endif CFG_PKCS11_TA ?= y optee_os-4.3.0/core/arch/arm/plat-vexpress/juno_core_pos_a32.S000066400000000000000000000007471464416617300242550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include /* For Juno number the two A57s as 4 to 5 and A53s as 0 to 3 */ FUNC get_core_pos_mpidr , : /* Calculate CorePos = ((ClusterId ^ 1) * 4) + CoreId */ and r1, r0, #MPIDR_CPU_MASK and r0, r0, #MPIDR_CLUSTER_MASK eor r0, r0, #(1 << MPIDR_CLUSTER_SHIFT) add r0, r1, r0, LSR #6 bx lr END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-vexpress/juno_core_pos_a64.S000066400000000000000000000006631464416617300242570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #include #include /* For Juno number the two A57s as 4 to 5 and A53s as 0 to 3 */ FUNC get_core_pos_mpidr , : /* Calculate CorePos = ((ClusterId ^ 1) * 4) + CoreId */ and x1, x0, #MPIDR_CPU_MASK and x0, x0, #MPIDR_CLUSTER_MASK eor x0, x0, #(1 << MPIDR_CLUSTER_SHIFT) add x0, x1, x0, LSR #6 ret END_FUNC get_core_pos_mpidr optee_os-4.3.0/core/arch/arm/plat-vexpress/main.c000066400000000000000000000176061464416617300217120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2023, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct pl011_data console_data __nex_bss; static uint16_t console_notif_vm_id __nex_bss; static uint16_t console_notif_backup_vm_id __nex_bss; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE); #if defined(PLATFORM_FLAVOR_fvp) register_phys_mem(MEM_AREA_RAM_SEC, TZCDRAM_BASE, TZCDRAM_SIZE); #endif #if defined(PLATFORM_FLAVOR_qemu_virt) register_phys_mem_pgdir(MEM_AREA_IO_SEC, SECRAM_BASE, SECRAM_COHERENT_SIZE); #endif #ifdef DRAM0_BASE register_ddr(DRAM0_BASE, DRAM0_SIZE); #endif #ifdef DRAM1_BASE register_ddr(DRAM1_BASE, DRAM1_SIZE); #endif #ifdef CFG_GIC register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE); #ifdef GIC_REDIST_BASE register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_REDIST_BASE, GIC_REDIST_SIZE); #endif void boot_primary_init_intc(void) { #ifdef GIC_REDIST_BASE gic_init_v3(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET, GIC_REDIST_BASE); #else gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); #endif if (IS_ENABLED(CFG_CORE_SEL1_SPMC) && IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { size_t it = CFG_CORE_ASYNC_NOTIF_GIC_INTID; if (it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX) gic_init_donate_sgi_to_ns(it); thread_spmc_set_async_notif_intid(it); } } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } #endif /*CFG_GIC*/ #ifdef CFG_CORE_HAFNIUM_INTC void boot_primary_init_intc(void) { hfic_init(); } #endif void plat_console_init(void) { pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } #if (defined(CFG_GIC) || defined(CFG_CORE_HAFNIUM_INTC)) && \ defined(IT_CONSOLE_UART) && \ !(defined(CFG_WITH_ARM_TRUSTED_FW) && defined(CFG_ARM_GICV2)) && \ !defined(CFG_SEMIHOSTING_CONSOLE) && \ !defined(CFG_FFA_CONSOLE) /* * This cannot be enabled with TF-A and GICv3 because TF-A then need to * assign the interrupt number of the UART to OP-TEE (S-EL1). Currently * there's no way of TF-A to know which interrupts that OP-TEE will serve. * If TF-A doesn't assign the interrupt we're enabling below to OP-TEE it * will hang in EL3 since the interrupt will just be delivered again and * again. */ static void read_console(void) { struct serial_chip *cons = &console_data.chip; if (!cons->ops->getchar || !cons->ops->have_rx_data) return; while (cons->ops->have_rx_data(cons)) { int ch __maybe_unused = cons->ops->getchar(cons); DMSG("got 0x%x", ch); } } static uint16_t get_console_notif_vm_id(void) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) return console_notif_vm_id; return 0; } static enum itr_return console_itr_cb(struct itr_handler *hdl __unused) { if (notif_async_is_started(get_console_notif_vm_id())) { /* * Asynchronous notifications are enabled, lets read from * uart in the bottom half instead. */ console_data.chip.ops->rx_intr_disable(&console_data.chip); notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF, get_console_notif_vm_id()); } else { read_console(); } return ITRR_HANDLED; } static struct itr_handler console_itr __nex_data = { .it = IT_CONSOLE_UART, .flags = ITRF_TRIGGER_LEVEL, .handler = console_itr_cb, }; DECLARE_KEEP_PAGER(console_itr); static void atomic_console_notif(struct notif_driver *ndrv __unused, enum notif_event ev, uint16_t vm_id) { switch (ev) { case NOTIF_EVENT_STARTED: DMSG("Asynchronous notifications started, event %d (vm %#"PRIx16")", (int)ev, vm_id); break; case NOTIF_EVENT_SHUTDOWN: DMSG("Shutting down partition, event %d (vm %#"PRIx16")", (int)ev, vm_id); if (vm_id == console_notif_backup_vm_id) console_notif_backup_vm_id = 0; if (vm_id == console_notif_vm_id) console_notif_vm_id = console_notif_backup_vm_id; break; default: EMSG("Unknown event %d", (int)ev); } } DECLARE_KEEP_PAGER(atomic_console_notif); static void yielding_console_notif(struct notif_driver *ndrv __unused, enum notif_event ev) { switch (ev) { case NOTIF_EVENT_DO_BOTTOM_HALF: if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && console_notif_vm_id != virt_get_current_guest_id()) break; read_console(); console_data.chip.ops->rx_intr_enable(&console_data.chip); break; case NOTIF_EVENT_STOPPED: DMSG("Asynchronous notifications stopped"); console_data.chip.ops->rx_intr_enable(&console_data.chip); break; default: EMSG("Unknown event %d", (int)ev); } } static unsigned int console_notif_lock __nex_bss __maybe_unused; static struct notif_driver console_notif __nex_data = { .atomic_cb = atomic_console_notif, .yielding_cb = yielding_console_notif, }; static TEE_Result init_console_itr(void) { TEE_Result res = TEE_ERROR_GENERIC; bool have_itr_ctrl = console_data.chip.ops->rx_intr_enable && console_data.chip.ops->rx_intr_disable; res = interrupt_add_handler_with_chip(interrupt_get_main_chip(), &console_itr); if (res) return res; interrupt_enable(console_itr.chip, console_itr.it); if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF) && have_itr_ctrl) notif_register_driver(&console_notif); return TEE_SUCCESS; } nex_driver_init(init_console_itr); #ifdef CFG_NS_VIRTUALIZATION static TEE_Result claim_console(void) { uint32_t state = cpu_spin_lock_xsave(&console_notif_lock); console_notif_vm_id = virt_get_current_guest_id(); if (!console_notif_backup_vm_id) console_notif_backup_vm_id = console_notif_vm_id; cpu_spin_unlock_xrestore(&console_notif_lock, state); return TEE_SUCCESS; } driver_init(claim_console); #endif #endif #ifdef CFG_TZC400 register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC400_BASE, TZC400_REG_SIZE); static TEE_Result init_tzc400(void) { void *va; DMSG("Initializing TZC400"); va = phys_to_virt(TZC400_BASE, MEM_AREA_IO_SEC, TZC400_REG_SIZE); if (!va) { EMSG("TZC400 not mapped"); panic(); } tzc_init((vaddr_t)va); tzc_dump_state(); return TEE_SUCCESS; } service_init(init_tzc400); #endif /*CFG_TZC400*/ #if defined(PLATFORM_FLAVOR_qemu_virt) static void release_secondary_early_hpen(size_t pos) { struct mailbox { uint64_t ep; uint64_t hpen[]; } *mailbox; if (cpu_mmu_enabled()) mailbox = phys_to_virt(SECRAM_BASE, MEM_AREA_IO_SEC, SECRAM_COHERENT_SIZE); else mailbox = (void *)SECRAM_BASE; if (!mailbox) panic(); mailbox->ep = TEE_LOAD_ADDR; dsb_ishst(); mailbox->hpen[pos] = 1; dsb_ishst(); sev(); } int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id) { size_t pos = get_core_pos_mpidr(core_id); static bool core_is_released[CFG_TEE_CORE_NB_CORE]; if (!pos || pos >= CFG_TEE_CORE_NB_CORE) return PSCI_RET_INVALID_PARAMETERS; DMSG("core pos: %zu: ns_entry %#" PRIx32, pos, entry); if (core_is_released[pos]) { EMSG("core %zu already released", pos); return PSCI_RET_DENIED; } core_is_released[pos] = true; boot_set_core_ns_entry(pos, entry, context_id); release_secondary_early_hpen(pos); return PSCI_RET_SUCCESS; } #endif /*PLATFORM_FLAVOR_qemu_virt*/ #if defined(CFG_CALLOUT) && defined(IT_SEC_PHY_TIMER) && \ !defined(CFG_CORE_SEL2_SPMC) static TEE_Result init_callout_service(void) { timer_init_callout_service(interrupt_get_main_chip(), IT_SEC_PHY_TIMER); return TEE_SUCCESS; } nex_early_init(init_callout_service); #endif optee_os-4.3.0/core/arch/arm/plat-vexpress/platform_config.h000066400000000000000000000061661464416617300241430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #include /* Make stacks aligned to data cache line length */ #define STACK_ALIGNMENT 64 #if defined(PLATFORM_FLAVOR_fvp) #define GIC_BASE 0x2c000000 #define UART0_BASE 0x1c090000 #define UART1_BASE 0x1c0a0000 #define UART2_BASE 0x1c0b0000 #define UART3_BASE 0x1c0c0000 #define TZC400_BASE 0x2a4a0000 #define IT_UART1 38 #define CONSOLE_UART_BASE UART1_BASE #define IT_CONSOLE_UART IT_UART1 #elif defined(PLATFORM_FLAVOR_juno) #define GIC_BASE 0x2c010000 /* FPGA UART0 */ #define UART0_BASE 0x1c090000 /* FPGA UART1 */ #define UART1_BASE 0x1c0a0000 /* SoC UART0 */ #define UART2_BASE 0x7ff80000 /* SoC UART1 */ #define UART3_BASE 0x7ff70000 #define UART0_CLK_IN_HZ 24000000 #define UART1_CLK_IN_HZ 24000000 #define UART2_CLK_IN_HZ 7273800 #define UART3_CLK_IN_HZ 7273800 #define IT_UART3 116 #define CONSOLE_UART_BASE UART3_BASE #define IT_CONSOLE_UART IT_UART3 #define CONSOLE_UART_CLK_IN_HZ UART3_CLK_IN_HZ #elif defined(PLATFORM_FLAVOR_qemu_virt) #define GIC_BASE 0x08000000 #define UART0_BASE 0x09000000 #define UART1_BASE 0x09040000 #define PCSC_BASE 0x09100000 #define IT_UART1 40 #define IT_PCSC 37 #define CONSOLE_UART_BASE UART1_BASE #define IT_CONSOLE_UART IT_UART1 #elif defined(PLATFORM_FLAVOR_qemu_armv8a) #define GIC_BASE 0x08000000 #define UART0_BASE 0x09000000 #define UART1_BASE 0x09040000 #define IT_UART1 40 #define IT_SEC_PHY_TIMER 29 #define CONSOLE_UART_BASE UART1_BASE #define IT_CONSOLE_UART IT_UART1 #else #error "Unknown platform flavor" #endif #if defined(PLATFORM_FLAVOR_fvp) /* * FVP specifics. */ #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE 0x7f000000 #define DRAM1_BASE 0x880000000UL #define DRAM1_SIZE 0x180000000UL #define TZCDRAM_BASE 0xff000000 #define TZCDRAM_SIZE 0x01000000 #define GICC_OFFSET 0x0 #define GICD_OFFSET 0x3000000 #ifdef CFG_ARM_GICV3 #define GIC_REDIST_BASE 0x2F100000 #define GIC_REDIST_SIZE 0x00100000 #endif #elif defined(PLATFORM_FLAVOR_juno) /* * Juno specifics. */ #define DRAM0_BASE 0x80000000 #define DRAM0_SIZE 0x7F000000 #define DRAM1_BASE 0x880000000UL #define DRAM1_SIZE 0x180000000UL #define GICC_OFFSET 0x1f000 #define GICD_OFFSET 0 #elif defined(PLATFORM_FLAVOR_qemu_virt) /* * QEMU virt specifics. */ #define SECRAM_BASE 0x0e000000 #define SECRAM_COHERENT_SIZE 4096 #define GICD_OFFSET 0 #define GICC_OFFSET 0x10000 #elif defined(PLATFORM_FLAVOR_qemu_armv8a) #define GICD_OFFSET 0 #define GICC_OFFSET 0x10000 #ifdef CFG_ARM_GICV3 #define GIC_REDIST_BASE 0x080A0000 #define GIC_REDIST_SIZE 0x00F60000 #endif #else #error "Unknown platform flavor" #endif #define GICD_BASE (GIC_BASE + GICD_OFFSET) #define GICC_BASE (GIC_BASE + GICC_OFFSET) #ifndef UART_BAUDRATE #define UART_BAUDRATE 115200 #endif #ifndef CONSOLE_BAUDRATE #define CONSOLE_BAUDRATE UART_BAUDRATE #endif /* For virtual platforms where there isn't a clock */ #ifndef CONSOLE_UART_CLK_IN_HZ #define CONSOLE_UART_CLK_IN_HZ 1 #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-vexpress/sub.mk000066400000000000000000000003251464416617300217320ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c ifeq ($(PLATFORM_FLAVOR_juno),y) srcs-$(CFG_ARM32_core) += juno_core_pos_a32.S srcs-$(CFG_ARM64_core) += juno_core_pos_a64.S endif srcs-$(CFG_WITH_USER_TA) += vendor_props.c optee_os-4.3.0/core/arch/arm/plat-vexpress/vendor_props.c000066400000000000000000000037551464416617300235060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2020, Linaro Limited. */ #include #include #include #include #include #include #include /* * The data to hash is 48 bytes made up of: * - 16 bytes: the UUID of the calling TA. * - 32 bytes: the hardware device ID * The resulting endorsement seed is 32 bytes. * * The output buffer is the "binary" struct defined in * the "prop_value" union and therefore comprises: * - 4 bytes: the size of the binary value data (32) * - 32 bytes: the binary value data (endorsement seed) * * Note that this code assumes an endorsement seed * size == device ID size for convenience. */ static TEE_Result get_prop_endorsement(struct ts_session *sess, void *buf, size_t *blen) { TEE_Result res; uint32_t ta_endorsement_seed_size = 32; uint8_t data[sizeof(TEE_UUID) + ta_endorsement_seed_size]; uint32_t bin[1 + ta_endorsement_seed_size / sizeof(uint32_t)]; uint32_t *bin_len = (uint32_t *)bin; uint8_t *bin_val = (uint8_t *)(&bin[1]); if (*blen < sizeof(bin)) { *blen = sizeof(bin); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(bin); memcpy(data, &sess->ctx->uuid, sizeof(TEE_UUID)); if (tee_otp_get_die_id(&data[sizeof(TEE_UUID)], ta_endorsement_seed_size)) return TEE_ERROR_BAD_STATE; res = tee_hash_createdigest(TEE_ALG_SHA256, data, sizeof(data), bin_val, ta_endorsement_seed_size); if (res != TEE_SUCCESS) return TEE_ERROR_BAD_STATE; *bin_len = ta_endorsement_seed_size; return copy_to_user(buf, bin, sizeof(bin)); } static const struct tee_props vendor_propset_array_tee[] = { { .name = "com.microsoft.ta.endorsementSeed", .prop_type = USER_TA_PROP_TYPE_BINARY_BLOCK, .get_prop_func = get_prop_endorsement }, }; const struct tee_vendor_props vendor_props_tee = { .props = vendor_propset_array_tee, .len = ARRAY_SIZE(vendor_propset_array_tee), }; optee_os-4.3.0/core/arch/arm/plat-zynq7k/000077500000000000000000000000001464416617300201745ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-zynq7k/conf.mk000066400000000000000000000012641464416617300214550ustar00rootroot00000000000000PLATFORM_FLAVOR ?= zc702 include core/arch/arm/cpu/cortex-a9.mk $(call force,CFG_TEE_CORE_NB_CORE,2) $(call force,CFG_ARM32_core,y) $(call force,CFG_GIC,y) $(call force,CFG_CDNS_UART,y) $(call force,CFG_WITH_SOFTWARE_PRNG,y) $(call force,CFG_PL310,y) $(call force,CFG_PL310_LOCKED,y) $(call force,CFG_SECURE_TIME_SOURCE_REE,y) # Xilinx Zynq-7000's Cortex-A9 core has been configured with Non-maskable FIQ # (NMFI) support. This means that FIQ interrupts cannot be used in system # designs as atomic contexts cannot mask FIQ out. $(call force,CFG_CORE_WORKAROUND_ARM_NMFI,y) CFG_BOOT_SYNC_CPU ?= y CFG_BOOT_SECONDARY_REQUEST ?= y CFG_CRYPTO_SIZE_OPTIMIZATION ?= n CFG_ENABLE_SCTLR_RR ?= y optee_os-4.3.0/core/arch/arm/plat-zynq7k/main.c000066400000000000000000000140661464416617300212730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * All rights reserved. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct cdns_uart_data console_data; register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, SLCR_BASE, CORE_MMU_PGDIR_SIZE); void plat_primary_init_early(void) { /* primary core */ #if defined(CFG_BOOT_SECONDARY_REQUEST) /* set secondary entry address and release core */ io_write32(SECONDARY_ENTRY_DROP, TEE_LOAD_ADDR); dsb(); sev(); #endif /* SCU config */ io_write32(SCU_BASE + SCU_INV_SEC, SCU_INV_CTRL_INIT); io_write32(SCU_BASE + SCU_SAC, SCU_SAC_CTRL_INIT); io_write32(SCU_BASE + SCU_NSAC, SCU_NSAC_CTRL_INIT); /* SCU enable */ io_setbits32(SCU_BASE + SCU_CTRL, 0x1); /* NS Access control */ io_write32(SECURITY2_SDIO0, ACCESS_BITS_ALL); io_write32(SECURITY3_SDIO1, ACCESS_BITS_ALL); io_write32(SECURITY4_QSPI, ACCESS_BITS_ALL); io_write32(SECURITY6_APB_SLAVES, ACCESS_BITS_ALL); io_write32(SLCR_UNLOCK, SLCR_UNLOCK_MAGIC); io_write32(SLCR_TZ_DDR_RAM, ACCESS_BITS_ALL); io_write32(SLCR_TZ_DMA_NS, ACCESS_BITS_ALL); io_write32(SLCR_TZ_DMA_IRQ_NS, ACCESS_BITS_ALL); io_write32(SLCR_TZ_DMA_PERIPH_NS, ACCESS_BITS_ALL); io_write32(SLCR_TZ_GEM, ACCESS_BITS_ALL); io_write32(SLCR_TZ_SDIO, ACCESS_BITS_ALL); io_write32(SLCR_TZ_USB, ACCESS_BITS_ALL); io_write32(SLCR_LOCK, SLCR_LOCK_MAGIC); } void plat_console_init(void) { cdns_uart_init(&console_data, CONSOLE_UART_BASE, 0, 0); register_serial_console(&console_data.chip); } vaddr_t pl310_base(void) { static void *va; if (cpu_mmu_enabled()) { if (!va) va = phys_to_virt(PL310_BASE, MEM_AREA_IO_SEC, 1); return (vaddr_t)va; } return PL310_BASE; } void arm_cl2_config(vaddr_t pl310_base) { /* Disable PL310 */ io_write32(pl310_base + PL310_CTRL, 0); /* * Xilinx AR#54190 recommends setting L2C RAM in SLCR * to 0x00020202 for proper cache operations. */ io_write32(SLCR_L2C_RAM, SLCR_L2C_RAM_VALUE); io_write32(pl310_base + PL310_TAG_RAM_CTRL, PL310_TAG_RAM_CTRL_INIT); io_write32(pl310_base + PL310_DATA_RAM_CTRL, PL310_DATA_RAM_CTRL_INIT); io_write32(pl310_base + PL310_AUX_CTRL, PL310_AUX_CTRL_INIT); io_write32(pl310_base + PL310_PREFETCH_CTRL, PL310_PREFETCH_CTRL_INIT); io_write32(pl310_base + PL310_POWER_CTRL, PL310_POWER_CTRL_INIT); /* invalidate all cache ways */ arm_cl2_invbyway(pl310_base); } void arm_cl2_enable(vaddr_t pl310_base) { uint32_t val; /* Enable PL310 ctrl -> only set lsb bit */ io_write32(pl310_base + PL310_CTRL, 1); /* if L2 FLZW enable, enable in L1 */ val = io_read32(pl310_base + PL310_AUX_CTRL); if (val & 1) write_actlr(read_actlr() | (1 << 3)); } void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void boot_secondary_init_intc(void) { gic_init_per_cpu(); } static vaddr_t slcr_access_range[] = { 0x004, 0x008, /* lock, unlock */ 0x100, 0x1FF, /* PLL */ 0x200, 0x2FF, /* Reset */ 0xA00, 0xAFF /* L2C */ }; static uint32_t write_slcr(uint32_t addr, uint32_t val) { uint32_t i; for (i = 0; i < ARRAY_SIZE(slcr_access_range); i += 2) { if (addr >= slcr_access_range[i] && addr <= slcr_access_range[i+1]) { static vaddr_t va; if (!va) va = (vaddr_t)phys_to_virt(SLCR_BASE, MEM_AREA_IO_SEC, addr + sizeof(uint32_t)); io_write32(va + addr, val); return OPTEE_SMC_RETURN_OK; } } return OPTEE_SMC_RETURN_EBADADDR; } static uint32_t read_slcr(uint32_t addr, uint32_t *val) { uint32_t i; for (i = 0; i < ARRAY_SIZE(slcr_access_range); i += 2) { if (addr >= slcr_access_range[i] && addr <= slcr_access_range[i+1]) { static vaddr_t va; if (!va) va = (vaddr_t)phys_to_virt(SLCR_BASE, MEM_AREA_IO_SEC, addr + sizeof(uint32_t)); *val = io_read32(va + addr); return OPTEE_SMC_RETURN_OK; } } return OPTEE_SMC_RETURN_EBADADDR; } /* Overriding the default __weak tee_entry_fast() */ void tee_entry_fast(struct thread_smc_args *args) { switch (args->a0) { case ZYNQ7K_SMC_SLCR_WRITE: args->a0 = write_slcr(args->a1, args->a2); break; case ZYNQ7K_SMC_SLCR_READ: args->a0 = read_slcr(args->a1, &args->a2); break; default: __tee_entry_fast(args); break; } } optee_os-4.3.0/core/arch/arm/plat-zynq7k/plat_init.S000066400000000000000000000064661464416617300223170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * All rights reserved. * Copyright (c) 2016, Wind River Systems. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Entry points for the A9 inits, A9 revision specific or not. * It is assume no stack is available when these routines are called. * It is assume each routine is called with return address in LR * and with ARM registers R0, R1, R2, R3 being scratchable. */ #include #include #include #include #include #include #define ZYNQ_SLCR_L2C_RAM 0xF8000A1C .section .text .balign 4 .code 32 /* * Cortex A9 early configuration * * Use registers R0-R3. * No stack usage. * LR store return address. * Trap CPU in case of error. */ FUNC plat_cpu_reset_early , : /* * Disallow NSec to mask FIQ [bit4: FW=0] * Allow NSec to manage Imprecise Abort [bit5: AW=1] * Imprecise Abort trapped to Abort Mode [bit3: EA=0] * In Sec world, FIQ trapped to FIQ Mode [bit2: FIQ=0] * IRQ always trapped to IRQ Mode [bit1: IRQ=0] * Secure World [bit0: NS=0] */ mov r0, #SCR_AW write_scr r0 /* write Secure Configuration Register */ /* * Mandated HW config loaded * * SCTLR = 0x00004000 * - Round-Robin replac. for icache, btac, i/duTLB (bit14: RoundRobin) * * ACTRL = 0x00000041 * - core always in full SMP (FW bit0=1, SMP bit6=1) * - L2 write full line of zero disabled (bit3=0) * (keep WFLZ low. Will be set once outer L2 is ready) * * NSACR = 0x00020C00 * - NSec cannot change ACTRL.SMP (NS_SMP bit18=0) * - Nsec can lockdown TLB (TL bit17=1) * - NSec cannot access PLE (PLE bit16=0) * - NSec can use SIMD/VFP (CP10/CP11) (bit15:14=2b00, bit11:10=2b11) * * PCR = 0x00000001 * - no change latency, enable clk gating */ mov_imm r0, 0x00004000 write_sctlr r0 mov_imm r0, 0x00000041 write_actlr r0 mov_imm r0, 0x00020C00 write_nsacr r0 mov_imm r0, 0x00000001 write_pcr r0 mov pc, lr END_FUNC plat_cpu_reset_early optee_os-4.3.0/core/arch/arm/plat-zynq7k/platform_config.h000066400000000000000000000163121464416617300235210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Wind River Systems. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #define STACK_ALIGNMENT 64 /* For Zynq7000 board */ #define SCU_BASE 0xF8F00000 #define PL310_BASE 0xF8F02000 #define GIC_BASE 0xF8F00000 #define GICC_OFFSET 0x100 #define GICD_OFFSET 0x1000 #define GIC_CPU_BASE (GIC_BASE + GICC_OFFSET) #define GIC_DIST_BASE (GIC_BASE + GICD_OFFSET) #define SLCR_BASE 0xF8000000 #define SLCR_LOCK 0xF8000004 #define SLCR_UNLOCK 0xF8000008 #define SLCR_TZ_DDR_RAM 0xF8000430 #define SLCR_TZ_DMA_NS 0xF8000440 #define SLCR_TZ_DMA_IRQ_NS 0xF8000444 #define SLCR_TZ_DMA_PERIPH_NS 0xF8000448 #define SLCR_TZ_GEM 0xF8000450 #define SLCR_TZ_SDIO 0xF8000454 #define SLCR_TZ_USB 0xF8000458 #define SLCR_L2C_RAM 0xF8000A1C #define SLCR_LOCK_MAGIC 0x0000767B #define SLCR_UNLOCK_MAGIC 0x0000DF0D #define SECURITY2_SDIO0 0xE0200008 #define SECURITY3_SDIO1 0xE020000C #define SECURITY4_QSPI 0xE0200010 #define SECURITY6_APB_SLAVES 0xE0200018 #define UART0_BASE 0xE0000000 #define UART1_BASE 0xE0001000 #define CONSOLE_UART_BASE UART1_BASE #define TEE_RAM_VA_SIZE (1024 * 1024) /* * PL310 TAG RAM Control Register * * bit[10:8]:1 - 2 cycle of write accesses latency * bit[6:4]:1 - 2 cycle of read accesses latency * bit[2:0]:1 - 2 cycle of setup latency */ #ifndef PL310_TAG_RAM_CTRL_INIT #define PL310_TAG_RAM_CTRL_INIT 0x00000111 #endif /* * PL310 DATA RAM Control Register * * bit[10:8]:2 - 3 cycle of write accesses latency * bit[6:4]:2 - 3 cycle of read accesses latency * bit[2:0]:2 - 3 cycle of setup latency */ #ifndef PL310_DATA_RAM_CTRL_INIT #define PL310_DATA_RAM_CTRL_INIT 0x00000222 #endif /* * PL310 Auxiliary Control Register * * I/Dcache prefetch enabled (bit29:28=2b11) * NS can access interrupts (bit27=1) * NS can lockown cache lines (bit26=1) * Pseudo-random replacement policy (bit25=0) * Force write allocated (default) * Shared attribute internally ignored (bit22=1, bit13=0) * Parity disabled (bit21=0) * Event monitor disabled (bit20=0) * Platform fmavor specific way config: * - 64kb way size (bit19:17=3b011) * - 8-way associciativity (bit16=0) * Store buffer device limitation enabled (bit11=1) * Cacheable accesses have high prio (bit10=0) * Full Line Zero (FLZ) disabled (bit0=0) */ #ifndef PL310_AUX_CTRL_INIT #define PL310_AUX_CTRL_INIT 0x3C460800 #endif /* * PL310 Prefetch Control Register * * Double linefill disabled (bit30=0) * I/D prefetch enabled (bit29:28=2b11) * Prefetch drop enabled (bit24=1) * Incr double linefill disable (bit23=0) * Prefetch offset = 7 (bit4:0) */ #define PL310_PREFETCH_CTRL_INIT 0x31000007 /* * PL310 Power Register * * Dynamic clock gating enabled * Standby mode enabled */ #define PL310_POWER_CTRL_INIT 0x00000003 /* * SCU Invalidate Register * * Invalidate all registers */ #define SCU_INV_CTRL_INIT 0xFFFFFFFF /* * SCU Access Register * - both secure CPU access SCU */ #define SCU_SAC_CTRL_INIT 0x0000000F /* * SCU NonSecure Access Register * - both nonsec cpu access SCU, private and global timer */ #define SCU_NSAC_CTRL_INIT 0x00000FFF /* all bit enabled in access control register */ #define ACCESS_BITS_ALL 0xFFFFFFFF /* recommended value for setting the L2C_RAM register */ #define SLCR_L2C_RAM_VALUE 0x00020202 /* place in OCRAM to write secondary entry to */ #define SECONDARY_ENTRY_DROP 0xFFFFFFF0 /* define the memory areas */ #ifdef CFG_WITH_PAGER /* * TEE/TZ RAM layout: * * +---------------------------------------+ <- CFG_CORE_TZSRAM_EMUL_START * | TEE private highly | TEE_RAM | ^ * | secure memory | | | CFG_CORE_TZSRAM_EMUL_SIZE * +---------------------------------------+ v * * +---------------------------------------+ <- TZDRAM_BASE * | TEE private secure | TA_RAM | ^ + TZDRAM_SIZE * | external memory | | v * +---------------------------------------+ <- TEE_SHMEM_START * | Non secure | SHM | | * | shared memory | | | + TEE_SHMEM_SIZE * +---------------------------------------+ v * * TEE_RAM : default 256kByte * TA_RAM : all what is left in DDR TEE reserved area * PUB_RAM : default 2MByte */ /* emulated SRAM, 256K at start of secure DDR */ #define TZSRAM_BASE 0x3E000000 #define TZSRAM_SIZE CFG_CORE_TZSRAM_EMUL_SIZE /* Location of trusted dram */ #define TEE_RAM_START TZSRAM_BASE #define TEE_RAM_PH_SIZE TZSRAM_SIZE #define TZDRAM_BASE 0x3e100000 #define TZDRAM_SIZE 0x01e00000 #define TEE_SHMEM_START 0x3ff00000 #define TEE_SHMEM_SIZE 0x00100000 #define TA_RAM_START TZDRAM_BASE #define TA_RAM_SIZE TZDRAM_SIZE #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else #define TEE_LOAD_ADDR TEE_RAM_START #endif #else /* CFG_WITH_PAGER */ /* * TEE/TZ RAM layout: * * +---------------------------------------+ <- TZDRAM_BASE * | TEE private secure | TEE_RAM | ^ * | external memory +------------------+ | * | | TA_RAM | | * +---------------------------------------+ | TZDRAM_SIZE * | Non secure | SHM | | * | shared memory | | | * +---------------------------------------+ v * * TEE_RAM : 1MByte * PUB_RAM : 1MByte * TA_RAM : all what is left (at least 2MByte !) */ #define TZDRAM_BASE 0x3E000000 #define TZDRAM_SIZE (0x02000000 - TEE_SHMEM_SIZE) #define TEE_RAM_START TZDRAM_BASE #define TEE_RAM_PH_SIZE (1 * 1024 * 1024) #define TA_RAM_START (TZDRAM_BASE + TEE_RAM_PH_SIZE) #define TA_RAM_SIZE (TZDRAM_SIZE - TEE_RAM_PH_SIZE) #define TEE_SHMEM_START (TZDRAM_BASE + TZDRAM_SIZE) #define TEE_SHMEM_SIZE 0x00100000 #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else #define TEE_LOAD_ADDR TEE_RAM_START #endif #endif /* CFG_WITH_PAGER */ #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-zynq7k/platform_smc.h000066400000000000000000000052441464416617300230400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Wind River System * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_SMC_H #define PLATFORM_SMC_H #include /* * Read SLCR (System Level Control Register) * * Call register usage: * a0 SMC Function ID, ZYNQ7K_SMC_SLCR_READ * a1 Register offset * a2-7 Not used * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1 Value read back * a2-3 Not used * a4-7 Preserved * * OPTEE_SMC_RETURN_EBADCMD on Invalid input offset: * a0 OPTEE_SMC_RETURN_EBADCMD * a1 Undefined value * a2-3 Not used * a4-7 Preserved */ #define ZYNQ7K_SMC_FUNCID_SLCR_READ 0x100 #define ZYNQ7K_SMC_SLCR_READ \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_OEM, ZYNQ7K_SMC_FUNCID_SLCR_READ) /* * Write SLCR (System Level Control Register) * * Call register usage: * a0 SMC Function ID, ZYNQ7K_SMC_SLCR_READ * a1 Register offset * a2 Value to write * a3-7 Not used * * Normal return register usage: * a0 OPTEE_SMC_RETURN_OK * a1-3 Not used * a4-7 Preserved * * OPTEE_SMC_RETURN_EBADCMD on Invalid input offset: * a0 OPTEE_SMC_RETURN_EBADCMD * a1-3 Not used * a4-7 Preserved */ #define ZYNQ7K_SMC_FUNCID_SLCR_WRITE 0x101 #define ZYNQ7K_SMC_SLCR_WRITE \ OPTEE_SMC_CALL_VAL(OPTEE_SMC_32, OPTEE_SMC_FAST_CALL, \ OPTEE_SMC_OWNER_OEM, ZYNQ7K_SMC_FUNCID_SLCR_WRITE) #endif /* PLATFORM_SMC_H */ optee_os-4.3.0/core/arch/arm/plat-zynq7k/sub.mk000066400000000000000000000000751464416617300213200ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c srcs-y += plat_init.S optee_os-4.3.0/core/arch/arm/plat-zynqmp/000077500000000000000000000000001464416617300202675ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/plat-zynqmp/conf.mk000066400000000000000000000047461464416617300215600ustar00rootroot00000000000000PLATFORM_FLAVOR ?= zcu102 include core/arch/arm/cpu/cortex-armv8-0.mk $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_CDNS_UART,y) $(call force,CFG_GIC,y) $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y) $(call force,CFG_WITH_ARM_TRUSTED_FW,y) # Disable core ASLR for two reasons: # 1. There is no source for ALSR seed, as ATF does not provide a # DTB to OP-TEE. Hardware RNG is also not currently supported. # 2. OP-TEE does not boot with enabled CFG_CORE_ASLR. $(call force,CFG_CORE_ASLR,n) ifeq ($(CFG_ARM64_core),y) # ZynqMP supports up to 40 bits of physical addresses CFG_CORE_ARM64_PA_BITS ?= 40 else $(call force,CFG_ARM32_core,y) endif ifneq (,$(filter $(PLATFORM_FLAVOR),zcu102 zcu104 zcu106 zc1751_dc1 zc1751_dc2)) CFG_UART_BASE ?= UART0_BASE CFG_UART_IT ?= IT_UART0 CFG_UART_CLK_HZ ?= UART0_CLK_IN_HZ # ZCU102 features 4 GiB of DDR ifeq ($(CFG_ARM64_core),y) CFG_DDR_SIZE ?= 0x100000000 else # On 32 bit build limit to 2 GiB of RAM CFG_DDR_SIZE ?= 0x80000000 endif endif ifneq (,$(filter $(PLATFORM_FLAVOR),ultra96)) CFG_UART_BASE ?= UART1_BASE CFG_UART_IT ?= IT_UART1 CFG_UART_CLK_HZ ?= UART1_CLK_IN_HZ # Ultra96 features 2 GiB of DDR CFG_DDR_SIZE ?= 0x80000000 endif # By default use DT address as specified by Xilinx CFG_DT_ADDR ?= 0x100000 CFG_TZDRAM_START ?= 0x60000000 CFG_TZDRAM_SIZE ?= 0x10000000 CFG_SHMEM_START ?= 0x70000000 CFG_SHMEM_SIZE ?= 0x10000000 CFG_WITH_STATS ?= y CFG_CRYPTO_WITH_CE ?= y # Enable use of User AES eFuse as device key instead of PUF. # This is needed when images are encrypted with AES eFuse device key (AES_KEY). CFG_ZYNQMP_HUK_AES_EFUSE ?= n # Configures bitmask which user eFuses should be included in HUK generation. # Used when (part of) user eFuses are used for HUK seed (i.e. programmed with # good random values). # Bit 0 means eFuse USER_0, bit 1 for eFuse USER 1 and so on. CFG_ZYNQMP_HUK_USER_EFUSE_MASK ?= 0 CFG_ZYNQMP_PM ?= $(CFG_ARM64_core) ifeq ($(CFG_RPMB_FS),y) $(call force,CFG_ZYNQMP_HUK,y,Mandated by CFG_RPMB_FS) endif ifeq ($(CFG_ZYNQMP_HUK),y) $(call force,CFG_ZYNQMP_CSU_AES,y,Mandated by CFG_ZYNQMP_HUK) ifneq ($(CFG_ZYNQMP_HUK_AES_EFUSE),y) $(call force,CFG_ZYNQMP_CSU_PUF,y,Mandated by CFG_ZYNQMP_HUK) endif endif ifeq ($(CFG_ZYNQMP_CSU_AES),y) $(call force,CFG_ZYNQMP_CSUDMA,y,Mandated by CFG_ZYNQMP_CSU_AES) $(call force,CFG_DT,y,Mandated by CFG_ZYNQMP_CSU_AES) endif ifneq (,$(filter y, $(CFG_ZYNQMP_CSU_PUF) $(CFG_ZYNQMP_CSUDMA) $(CFG_ZYNQMP_CSU_AES))) $(call force,CFG_ZYNQMP_CSU,y,Mandated by CFG_ZYNQMP_CSU* clients) endif optee_os-4.3.0/core/arch/arm/plat-zynqmp/main.c000066400000000000000000000064561464416617300213720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Xilinx Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct cdns_uart_data console_data __nex_bss; register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(GIC_BASE, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, ROUNDDOWN(GIC_BASE + GICD_OFFSET, CORE_MMU_PGDIR_SIZE), CORE_MMU_PGDIR_SIZE); #if defined(CFG_ZYNQMP_CSU) register_phys_mem_pgdir(MEM_AREA_IO_SEC, CSU_BASE, CSU_SIZE); #endif #if CFG_DDR_SIZE > 0x80000000 #ifdef CFG_ARM32_core #error DDR size over 2 GiB is not supported in 32 bit ARM mode #endif register_ddr(DRAM0_BASE, 0x80000000); register_ddr(DRAM1_BASE, CFG_DDR_SIZE - 0x80000000); #else register_ddr(DRAM0_BASE, CFG_DDR_SIZE); #endif void boot_primary_init_intc(void) { gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET); } void plat_console_init(void) { cdns_uart_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE); register_serial_console(&console_data.chip); } #if defined(CFG_RPMB_FS) bool plat_rpmb_key_is_ready(void) { vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); struct tee_hw_unique_key hwkey = { }; uint32_t status = 0; if (tee_otp_get_hw_unique_key(&hwkey)) return false; /* * For security reasons, we don't allow writing the RPMB key using the * development HUK even though it is unique. */ status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); if (status & ZYNQMP_CSU_STATUS_AUTH) return true; return false; } #endif optee_os-4.3.0/core/arch/arm/plat-zynqmp/platform_config.h000066400000000000000000000060111464416617300236070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Xilinx Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* Make stacks aligned to data cache line length */ #define CACHELINE_LEN 64 #define STACK_ALIGNMENT CACHELINE_LEN #ifdef CFG_WITH_PAGER #error "Pager not supported for zynqmp" #endif /* DDR Low area base */ #define DRAM0_BASE 0 #ifdef ARM64 /* DDR High area base is only available when compiling for 64 bits */ #define DRAM1_BASE 0x800000000 #endif #ifdef CFG_CDNS_UART #define CONSOLE_UART_BASE (CFG_UART_BASE) #define IT_CONSOLE_UART (CFG_UART_IT) #define CONSOLE_UART_CLK_IN_HZ (CFG_UART_CLK_HZ) #endif #if defined(PLATFORM_FLAVOR_zc1751_dc1) || \ defined(PLATFORM_FLAVOR_zc1751_dc2) || \ defined(PLATFORM_FLAVOR_zcu102) || \ defined(PLATFORM_FLAVOR_zcu104) || \ defined(PLATFORM_FLAVOR_zcu106) || \ defined(PLATFORM_FLAVOR_ultra96) #define GIC_BASE 0xF9010000 #define UART0_BASE 0xFF000000 #define UART1_BASE 0xFF010000 #define IT_UART0 53 #define IT_UART1 54 #define UART0_CLK_IN_HZ 100000000 #define UART1_CLK_IN_HZ 100000000 #define GICD_OFFSET 0 #define GICC_OFFSET 0x10000 #else #error "Unknown platform flavor" #endif #define CSUDMA_BASE 0xFFC80000 #define CSUDMA_SIZE 0x1000 #define CSU_BASE 0xFFCA0000 #define CSU_SIZE 0x5038 #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else #define TEE_LOAD_ADDR TEE_RAM_START #endif #ifndef UART_BAUDRATE #define UART_BAUDRATE 115200 #endif #ifndef CONSOLE_BAUDRATE #define CONSOLE_BAUDRATE UART_BAUDRATE #endif /* For virtual platforms where there isn't a clock */ #ifndef CONSOLE_UART_CLK_IN_HZ #define CONSOLE_UART_CLK_IN_HZ 1 #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/arm/plat-zynqmp/sub.mk000066400000000000000000000000471464416617300214120ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/arm/sm/000077500000000000000000000000001464416617300164125ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/sm/pm.c000066400000000000000000000022431464416617300171730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017 NXP * * Peng Fan */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if CFG_TEE_CORE_NB_CORE > 4 #error "Max support 4 cores in one cluster now" #endif void sm_pm_cpu_suspend_save(struct sm_pm_ctx *ctx, uint32_t sp) { struct thread_core_local *p = thread_get_core_local(); p->sm_pm_ctx_phys = virt_to_phys((void *)ctx); /* The content will be passed to sm_pm_cpu_do_resume as register sp */ ctx->sp = sp; ctx->cpu_resume_addr = virt_to_phys((void *)(vaddr_t)sm_pm_cpu_do_resume); sm_pm_cpu_do_suspend(ctx->suspend_regs); dcache_op_level1(DCACHE_OP_CLEAN_INV); #ifdef CFG_PL310 arm_cl2_cleanbyway(core_mmu_get_va(PL310_BASE, MEM_AREA_IO_SEC, 1)); #endif } optee_os-4.3.0/core/arch/arm/sm/pm_a32.S000066400000000000000000000100031464416617300176110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017 NXP * * Peng Fan */ #include #include #include #include #include #include #include #include .section .text /* * int sm_pm_cpu_suspend(uint32_t arg, int (*fn)(uint32_t)) * @arg will be passed to fn as argument * return value: 0 - cpu resumed from suspended state. * -1 - cpu not suspended. */ FUNC sm_pm_cpu_suspend, : UNWIND( .cantunwind) push {r4 - r12, lr} mov r5, sp sub sp, sp, #SM_PM_CTX_SIZE push {r0, r1} mov r1, r5 add r0, sp, #8 blx sm_pm_cpu_suspend_save adr lr, aborted /* Jump to arch specific suspend */ pop {r0, pc} aborted: /* cpu not suspended */ add sp, sp, #SM_PM_CTX_SIZE /* Return -1 to the caller */ mov r0, #(-1) suspend_return: pop {r4 - r12, pc} END_FUNC sm_pm_cpu_suspend FUNC sm_pm_cpu_do_suspend, : UNWIND( .cantunwind) push {r4 - r11} read_midr r4 ubfx r5, r4, #4, #12 ldr r4, =CORTEX_A5_PART_NUM cmp r5, r4 beq a5_a7_suspend ldr r4, =CORTEX_A7_PART_NUM cmp r5, r4 beq a5_a7_suspend ldr r4, =CORTEX_A9_PART_NUM cmp r5, r4 beq a9_suspend /* cpu not supported */ b . /* A9 needs PCR/DIAG */ a9_suspend: read_pcr r4 read_diag r5 stmia r0!, {r4 - r5} a5_a7_suspend: read_fcseidr r4 read_tpidruro r5 stmia r0!, {r4 - r5} read_dacr r4 #ifdef CFG_WITH_LPAE #error "Not supported" #else read_ttbr0 r5 read_ttbr1 r6 read_ttbcr r7 #endif read_sctlr r8 read_actlr r9 read_cpacr r10 read_mvbar r11 stmia r0!, {r4 - r11} read_prrr r4 read_nmrr r5 read_vbar r6 read_nsacr r7 stmia r0, {r4 - r7} pop {r4 - r11} bx lr END_FUNC sm_pm_cpu_do_suspend FUNC sm_pm_cpu_resume, : UNWIND( .cantunwind) cpsid aif /* Call into the runtime address of __get_core_pos */ adr r0, _core_pos ldr r1, [r0] add r0, r0, r1 blx r0 /* * At this point, MMU is not enabled now. * 1. Get the runtime physical address of _suspend_sp * 2. Get the offset from _suspend_sp to &thread_core_local * 3. Get the runtime physical address of thread_core_local * Since moving towards non-linear mapping, * `ldr r0, =thread_core_local` is not used here. */ adr r4, _suspend_sp ldr r5, [r4] add r4, r4, r5 mov_imm r1, THREAD_CORE_LOCAL_SIZE mla r0, r0, r1, r4 ldr r0, [r0, #THREAD_CORE_LOCAL_SM_PM_CTX_PHYS] /* Need to use r0!, because sm_pm_cpu_do_resume needs it */ ldmia r0!, {sp, pc} END_FUNC sm_pm_cpu_resume /* * The following will be located in text section whose attribute is * marked as readonly, but we only need to read here * _suspend_sp stores the offset between thread_core_local to _suspend_sp. * _core_pos stores the offset between __get_core_pos to _core_pos. */ .align 2 .extern thread_core_local _suspend_sp: .long thread_core_local - . .extern __get_core_pos _core_pos: .long __get_core_pos - . /* * void sm_pm_cpu_do_resume(paddr suspend_regs) __noreturn; * Restore the registers stored when sm_pm_cpu_do_suspend * r0 points to the physical base address of the suspend_regs * field of struct sm_pm_ctx. */ FUNC sm_pm_cpu_do_resume, : UNWIND( .cantunwind) read_midr r4 ubfx r5, r4, #4, #12 ldr r4, =CORTEX_A5_PART_NUM cmp r5, r4 beq a5_a7_resume ldr r4, =CORTEX_A7_PART_NUM cmp r5, r4 beq a5_a7_resume /* * A9 needs PCR/DIAG */ ldmia r0!, {r4 - r5} write_pcr r4 write_diag r5 a5_a7_resume: /* v7 resume */ mov ip, #0 /* Invalidate icache to PoU */ write_iciallu /* set reserved context */ write_contextidr ip ldmia r0!, {r4 - r5} write_fcseidr r4 write_tpidruro r5 ldmia r0!, {r4 - r11} /* Invalidate entire TLB */ write_tlbiall write_dacr r4 #ifdef CFG_WITH_LPAE #error "Not supported -" #else write_ttbr0 r5 write_ttbr1 r6 write_ttbcr r7 #endif ldmia r0, {r4 - r7} write_prrr r4 write_nmrr r5 write_vbar r6 write_nsacr r7 write_actlr r9 write_cpacr r10 write_mvbar r11 write_bpiall isb dsb /* MMU will be enabled here */ write_sctlr r8 isb mov r0, #0 b suspend_return END_FUNC sm_pm_cpu_do_resume optee_os-4.3.0/core/arch/arm/sm/psci-helper.S000066400000000000000000000013361464416617300207540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017 NXP */ #include #include #include #include FUNC psci_disable_smp, : read_actlr r0 bic r0, r0, #ACTLR_SMP write_actlr r0 isb bx lr END_FUNC psci_disable_smp FUNC psci_enable_smp, : read_actlr r0 orr r0, r0, #ACTLR_SMP write_actlr r0 isb bx lr END_FUNC psci_enable_smp FUNC psci_armv7_cpu_off, : push {r12, lr} UNWIND( .save {r12, lr}) mov r0, #DCACHE_OP_CLEAN_INV bl dcache_op_all /* Disable Cache */ read_sctlr r0 bic r0, r0, #SCTLR_C write_sctlr r0 isb dsb mov r0, #DCACHE_OP_CLEAN_INV bl dcache_op_all clrex bl psci_disable_smp pop {r12, pc} END_FUNC psci_armv7_cpu_off optee_os-4.3.0/core/arch/arm/sm/psci.c000066400000000000000000000116641464416617300175240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * All rights reserved. * * Peng Fan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include __weak uint32_t psci_version(void) { return PSCI_VERSION_1_1; } __weak int psci_cpu_suspend(uint32_t power_state __unused, uintptr_t entry __unused, uint32_t context_id __unused, struct sm_nsec_ctx *nsec __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_cpu_off(void) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_cpu_on(uint32_t cpu_id __unused, uint32_t entry __unused, uint32_t context_id __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_affinity_info(uint32_t affinity __unused, uint32_t lowest_affnity_level __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_migrate(uint32_t cpu_id __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_migrate_info_type(void) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_migrate_info_up_cpu(void) { return PSCI_RET_NOT_SUPPORTED; } __weak void psci_system_off(void) { } __weak void psci_system_reset(void) { } __weak int psci_features(uint32_t psci_fid __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_mem_protect(uint32_t enable __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_mem_chk_range(paddr_t base __unused, size_t length __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_system_reset2(uint32_t reset_type __unused, uint32_t cookie __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_node_hw_state(uint32_t cpu_id __unused, uint32_t power_level __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_system_suspend(uintptr_t entry __unused, uint32_t context_id __unused, struct sm_nsec_ctx *nsec __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_stat_residency(uint32_t cpu_id __unused, uint32_t power_state __unused) { return PSCI_RET_NOT_SUPPORTED; } __weak int psci_stat_count(uint32_t cpu_id __unused, uint32_t power_state __unused) { return PSCI_RET_NOT_SUPPORTED; } void tee_psci_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec) { uint32_t smc_fid = args->a0; uint32_t a1 = args->a1; uint32_t a2 = args->a2; uint32_t a3 = args->a3; switch (smc_fid) { case PSCI_VERSION: args->a0 = psci_version(); break; case PSCI_CPU_SUSPEND: args->a0 = psci_cpu_suspend(a1, a2, a3, nsec); break; case PSCI_CPU_OFF: args->a0 = psci_cpu_off(); break; case PSCI_CPU_ON: args->a0 = psci_cpu_on(a1, a2, a3); break; case PSCI_AFFINITY_INFO: args->a0 = psci_affinity_info(a1, a2); break; case PSCI_MIGRATE: args->a0 = psci_migrate(a1); break; case PSCI_MIGRATE_INFO_TYPE: args->a0 = psci_migrate_info_type(); break; case PSCI_MIGRATE_INFO_UP_CPU: args->a0 = psci_migrate_info_up_cpu(); break; case PSCI_SYSTEM_OFF: psci_system_off(); while (1) ; break; case PSCI_SYSTEM_RESET: psci_system_reset(); while (1) ; break; case PSCI_PSCI_FEATURES: args->a0 = psci_features(a1); break; case PSCI_SYSTEM_RESET2: args->a0 = psci_system_reset2(a1, a2); break; case PSCI_MEM_PROTECT: args->a0 = psci_mem_protect(a1); break; case PSCI_MEM_PROTECT_CHECK_RANGE: args->a0 = psci_mem_chk_range(a1, a2); break; case PSCI_NODE_HW_STATE: args->a0 = psci_node_hw_state(a1, a2); break; case PSCI_SYSTEM_SUSPEND: args->a0 = psci_system_suspend(a1, a2, nsec); break; default: args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; break; } } optee_os-4.3.0/core/arch/arm/sm/sm.c000066400000000000000000000053031464416617300171760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2020, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include "sm_private.h" enum sm_handler_ret __weak sm_platform_handler(struct sm_ctx *ctx __unused) { return SM_HANDLER_PENDING_SMC; } static void smc_arch_handler(struct thread_smc_args *args) { uint32_t smc_fid = args->a0; uint32_t feature_fid = args->a1; switch (smc_fid) { case ARM_SMCCC_VERSION: args->a0 = SMCCC_V_1_1; break; case ARM_SMCCC_ARCH_FEATURES: switch (feature_fid) { case ARM_SMCCC_VERSION: case ARM_SMCCC_ARCH_SOC_ID: args->a0 = ARM_SMCCC_RET_SUCCESS; break; default: args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; break; } break; case ARM_SMCCC_ARCH_SOC_ID: args->a0 = ARM_SMCCC_RET_NOT_SUPPORTED; break; case ARM_SMCCC_ARCH_WORKAROUND_1: case ARM_SMCCC_ARCH_WORKAROUND_2: args->a0 = ARM_SMCCC_RET_NOT_REQUIRED; break; default: args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; break; } } uint32_t sm_from_nsec(struct sm_ctx *ctx) { uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); struct thread_smc_args *args = (struct thread_smc_args *)nsec_r0; /* * Check that struct sm_ctx has the different parts properly * aligned since the stack pointer will be updated to point at * different parts of this struct. */ COMPILE_TIME_ASSERT(!(offsetof(struct sm_ctx, sec.r0) % 8)); COMPILE_TIME_ASSERT(!(offsetof(struct sm_ctx, nsec.r0) % 8)); COMPILE_TIME_ASSERT(!(sizeof(struct sm_ctx) % 8)); if (wdt_sm_handler(args) == SM_HANDLER_SMC_HANDLED) return SM_EXIT_TO_NON_SECURE; if (IS_ENABLED(CFG_SM_PLATFORM_HANDLER) && sm_platform_handler(ctx) == SM_HANDLER_SMC_HANDLED) return SM_EXIT_TO_NON_SECURE; switch (OPTEE_SMC_OWNER_NUM(args->a0)) { case OPTEE_SMC_OWNER_STANDARD: if (IS_ENABLED(CFG_PSCI_ARM32)) { smc_std_handler(args, &ctx->nsec); return SM_EXIT_TO_NON_SECURE; } break; case OPTEE_SMC_OWNER_ARCH: smc_arch_handler(args); return SM_EXIT_TO_NON_SECURE; default: break; } sm_save_unbanked_regs(&ctx->nsec.ub_regs); sm_restore_unbanked_regs(&ctx->sec.ub_regs); memcpy(&ctx->sec.r0, args, sizeof(*args)); if (IS_ENABLED(CFG_CORE_WORKAROUND_ARM_NMFI)) { /* Make sure FIQ is masked when jumping to SMC entry. */ ctx->sec.mon_spsr |= CPSR_F; } if (OPTEE_SMC_IS_FAST_CALL(ctx->sec.r0)) ctx->sec.mon_lr = (uint32_t)vector_fast_smc_entry; else ctx->sec.mon_lr = (uint32_t)vector_std_smc_entry; return SM_EXIT_TO_SECURE; } optee_os-4.3.0/core/arch/arm/sm/sm_a32.S000066400000000000000000000246761464416617300176410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2020, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #define SM_CTX_SEC_END (SM_CTX_SEC + SM_CTX_SEC_SIZE) .macro save_regs mode cps \mode mrs r2, spsr str r2, [r0], #4 str sp, [r0], #4 str lr, [r0], #4 .endm FUNC sm_save_unbanked_regs , : UNWIND( .cantunwind) /* User mode registers has to be saved from system mode */ cps #CPSR_MODE_SYS str sp, [r0], #4 str lr, [r0], #4 save_regs #CPSR_MODE_IRQ save_regs #CPSR_MODE_FIQ save_regs #CPSR_MODE_SVC save_regs #CPSR_MODE_ABT save_regs #CPSR_MODE_UND #ifdef CFG_SM_NO_CYCLE_COUNTING read_pmcr r2 stm r0!, {r2} #endif #ifdef CFG_FTRACE_SUPPORT read_cntkctl r2 stm r0!, {r2} #endif cps #CPSR_MODE_MON bx lr END_FUNC sm_save_unbanked_regs .macro restore_regs mode cps \mode ldr r2, [r0], #4 ldr sp, [r0], #4 ldr lr, [r0], #4 msr spsr_fsxc, r2 .endm /* Restores the mode specific registers */ FUNC sm_restore_unbanked_regs , : UNWIND( .cantunwind) /* User mode registers has to be saved from system mode */ cps #CPSR_MODE_SYS ldr sp, [r0], #4 ldr lr, [r0], #4 restore_regs #CPSR_MODE_IRQ restore_regs #CPSR_MODE_FIQ restore_regs #CPSR_MODE_SVC restore_regs #CPSR_MODE_ABT restore_regs #CPSR_MODE_UND #ifdef CFG_SM_NO_CYCLE_COUNTING ldm r0!, {r2} write_pmcr r2 #endif #ifdef CFG_FTRACE_SUPPORT ldm r0!, {r2} write_cntkctl r2 #endif cps #CPSR_MODE_MON bx lr END_FUNC sm_restore_unbanked_regs /* * stack_tmp is used as stack, the top of the stack is reserved to hold * struct sm_ctx, everything below is for normal stack usage. As several * different CPU modes are using the same stack it's important that switch * of CPU mode isn't done until one mode is done. This means FIQ, IRQ and * Async abort has to be masked while using stack_tmp. */ LOCAL_FUNC sm_smc_entry , : UNWIND( .cantunwind) srsdb sp!, #CPSR_MODE_MON push {r0-r7} clrex /* Clear the exclusive monitor */ /* Find out if we're doing an secure or non-secure entry */ read_scr r1 tst r1, #SCR_NS bne .smc_from_nsec /* * As we're coming from secure world (NS bit cleared) the stack * pointer points to sm_ctx.sec.r0 at this stage. After the * instruction below the stack pointer points to sm_ctx. */ sub sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) /* Save secure context */ add r0, sp, #SM_CTX_SEC bl sm_save_unbanked_regs /* * On FIQ exit we're restoring the non-secure context unchanged, on * all other exits we're shifting r1-r4 from secure context into * r0-r3 in non-secure context. */ add r8, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) ldm r8, {r0-r4} mov_imm r9, TEESMC_OPTEED_RETURN_FIQ_DONE cmp r0, r9 addne r8, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) stmne r8, {r1-r4} /* Restore non-secure context */ add r0, sp, #SM_CTX_NSEC bl sm_restore_unbanked_regs .sm_ret_to_nsec: /* * Return to non-secure world */ add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) ldm r0, {r8-r12} #ifdef CFG_CORE_WORKAROUND_NSITR_CACHE_PRIME /* * Prevent leaking information about which code has been executed. * This is required to be used together with * CFG_CORE_WORKAROUND_SPECTRE_BP to protect Cortex A15 CPUs too. * * CFG_CORE_WORKAROUND_SPECTRE_BP also invalidates the branch * predictor on affected CPUs. In the cases where an alternative * vector has been installed the branch predictor is already * invalidated so invalidating here again would be redundant, but * testing for that is more trouble than it's worth. */ write_bpiall #endif /* Update SCR */ read_scr r0 orr r0, r0, #(SCR_NS | SCR_FIQ) /* Set NS and FIQ bit in SCR */ write_scr r0 /* * isb not needed since we're doing an exception return below * without dependency to the changes in SCR before that. */ add sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) b .sm_exit .smc_from_nsec: /* * As we're coming from non-secure world (NS bit set) the stack * pointer points to sm_ctx.nsec.r0 at this stage. After the * instruction below the stack pointer points to sm_ctx. */ sub sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) bic r1, r1, #(SCR_NS | SCR_FIQ) /* Clear NS and FIQ bit in SCR */ write_scr r1 isb add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) stm r0, {r8-r12} mov r0, sp bl sm_from_nsec cmp r0, #SM_EXIT_TO_NON_SECURE beq .sm_ret_to_nsec /* * Continue into secure world */ add sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) .sm_exit: pop {r0-r7} rfefd sp! END_FUNC sm_smc_entry /* * FIQ handling * * Saves CPU context in the same way as sm_smc_entry() above. The CPU * context will later be restored by sm_smc_entry() when handling a return * from FIQ. */ LOCAL_FUNC sm_fiq_entry , : UNWIND( .cantunwind) /* FIQ has a +4 offset for lr compared to preferred return address */ sub lr, lr, #4 /* sp points just past struct sm_sec_ctx */ srsdb sp!, #CPSR_MODE_MON push {r0-r7} clrex /* Clear the exclusive monitor */ /* * As we're coming from non-secure world the stack pointer points * to sm_ctx.nsec.r0 at this stage. After the instruction below the * stack pointer points to sm_ctx. */ sub sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) /* Update SCR */ read_scr r1 bic r1, r1, #(SCR_NS | SCR_FIQ) /* Clear NS and FIQ bit in SCR */ write_scr r1 isb /* Save non-secure context */ add r0, sp, #SM_CTX_NSEC bl sm_save_unbanked_regs add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) stm r0!, {r8-r12} /* Set FIQ entry */ ldr r0, =vector_fiq_entry str r0, [sp, #(SM_CTX_SEC + SM_SEC_CTX_MON_LR)] /* Restore secure context */ add r0, sp, #SM_CTX_SEC bl sm_restore_unbanked_regs add sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_MON_LR) rfefd sp! END_FUNC sm_fiq_entry LOCAL_FUNC sm_vect_table , :, align=32 UNWIND( .cantunwind) b . /* Reset */ b . /* Undefined instruction */ b sm_smc_entry /* Secure monitor call */ b . /* Prefetch abort */ b . /* Data abort */ b . /* Reserved */ b . /* IRQ */ b sm_fiq_entry /* FIQ */ END_FUNC sm_vect_table #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP .macro vector_prologue_spectre /* * This depends on SP being 8 byte aligned, that is, the * lowest three bits in SP are zero. * * The idea is to form a specific bit pattern in the lowest * three bits of SP depending on which entry in the vector * we enter via. This is done by adding 1 to SP in each * entry but the last. */ add sp, sp, #1 /* 7:111 Reset */ add sp, sp, #1 /* 6:110 Undefined instruction */ add sp, sp, #1 /* 5:101 Secure monitor call */ add sp, sp, #1 /* 4:100 Prefetch abort */ add sp, sp, #1 /* 3:011 Data abort */ add sp, sp, #1 /* 2:010 Reserved */ add sp, sp, #1 /* 1:001 IRQ */ nop /* 0:000 FIQ */ .endm LOCAL_FUNC sm_vect_table_a15 , :, align=32 UNWIND( .cantunwind) vector_prologue_spectre /* * Invalidate the branch predictor for the current processor. * For Cortex-A8 ACTLR[6] has to be set to 1 for BPIALL to be * effective. * Note that the BPIALL instruction is not effective in * invalidating the branch predictor on Cortex-A15. For that CPU, * set ACTLR[0] to 1 during early processor initialisation, and * invalidate the branch predictor by performing an ICIALLU * instruction. See also: * https://github.com/ARM-software/arm-trusted-firmware/wiki/Arm-Trusted-Firmware-Security-Advisory-TFV-6#variant-2-cve-2017-5715 */ write_iciallu isb b 1f END_FUNC sm_vect_table_a15 LOCAL_FUNC sm_vect_table_bpiall , :, align=32 UNWIND( .cantunwind) vector_prologue_spectre /* Invalidate the branch predictor for the current processor. */ write_bpiall isb 1: /* * Only two exception does normally occur, smc and fiq. With all * other exceptions it's good enough to just spinn, the lowest bits * still tells which exception we're stuck with when attaching a * debugger. */ /* Test for FIQ, all the lowest bits of SP are supposed to be 0 */ tst sp, #(BIT(0) | BIT(1) | BIT(2)) beq sm_fiq_entry /* Test for SMC, xor the lowest bits of SP to be 0 */ eor sp, sp, #(BIT(0) | BIT(2)) tst sp, #(BIT(0) | BIT(1) | BIT(2)) beq sm_smc_entry /* unhandled exception */ b . END_FUNC sm_vect_table_bpiall #endif /*!CFG_CORE_WORKAROUND_SPECTRE_BP*/ /* void sm_init(vaddr_t stack_pointer); */ FUNC sm_init , : /* Set monitor stack */ mrs r1, cpsr cps #CPSR_MODE_MON /* Point just beyond sm_ctx.sec */ sub sp, r0, #(SM_CTX_SIZE - SM_CTX_SEC_END) #ifdef CFG_INIT_CNTVOFF read_scr r0 orr r0, r0, #SCR_NS /* Set NS bit in SCR */ write_scr r0 isb /* * Accessing CNTVOFF: * If the implementation includes the Virtualization Extensions * this is a RW register, accessible from Hyp mode, and * from Monitor mode when SCR.NS is set to 1. * If the implementation includes the Security Extensions * but not the Virtualization Extensions, an MCRR or MRRC to * the CNTVOFF encoding is UNPREDICTABLE if executed in Monitor * mode, regardless of the value of SCR.NS. */ read_id_pfr1 r2 mov r3, r2 ands r3, r3, #IDPFR1_GENTIMER_MASK beq .no_gentimer ands r2, r2, #IDPFR1_VIRT_MASK beq .no_gentimer mov r2, #0 write_cntvoff r2, r2 .no_gentimer: bic r0, r0, #SCR_NS /* Clr NS bit in SCR */ write_scr r0 isb #endif #ifdef CFG_SM_NO_CYCLE_COUNTING read_pmcr r0 orr r0, #PMCR_DP write_pmcr r0 #endif msr cpsr, r1 #ifdef CFG_CORE_WORKAROUND_SPECTRE_BP /* * For unrecognized CPUs we fall back to the vector used for * unaffected CPUs. Cortex A-15 has special treatment compared to * the other affected Cortex CPUs. */ read_midr r1 ubfx r2, r1, #MIDR_IMPLEMENTER_SHIFT, #MIDR_IMPLEMENTER_WIDTH cmp r2, #MIDR_IMPLEMENTER_ARM bne 1f ubfx r2, r1, #MIDR_PRIMARY_PART_NUM_SHIFT, \ #MIDR_PRIMARY_PART_NUM_WIDTH movw r3, #CORTEX_A8_PART_NUM cmp r2, r3 movwne r3, #CORTEX_A9_PART_NUM cmpne r2, r3 movwne r3, #CORTEX_A17_PART_NUM cmpne r2, r3 ldreq r0, =sm_vect_table_bpiall beq 2f movw r3, #CORTEX_A15_PART_NUM cmp r2, r3 ldreq r0, =sm_vect_table_a15 beq 2f #endif /* Set monitor vector (MVBAR) */ 1: ldr r0, =sm_vect_table 2: write_mvbar r0 bx lr END_FUNC sm_init DECLARE_KEEP_PAGER sm_init /* struct sm_nsec_ctx *sm_get_nsec_ctx(void); */ FUNC sm_get_nsec_ctx , : mrs r1, cpsr cps #CPSR_MODE_MON /* * As we're in secure mode mon_sp points just beyond sm_ctx.sec, * which allows us to calculate the address of sm_ctx.nsec. */ add r0, sp, #(SM_CTX_NSEC - SM_CTX_SEC_END) msr cpsr, r1 bx lr END_FUNC sm_get_nsec_ctx optee_os-4.3.0/core/arch/arm/sm/sm_private.h000066400000000000000000000005221464416617300207330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef SM_PRIVATE_H #define SM_PRIVATE_H /* Returns one of SM_EXIT_TO_* exit monitor in secure or non-secure world */ uint32_t sm_from_nsec(struct sm_ctx *ctx); #endif /*SM_PRIVATE_H*/ optee_os-4.3.0/core/arch/arm/sm/std_smc.c000066400000000000000000000051211464416617300202110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * All rights reserved. * * Peng Fan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include static const TEE_UUID uuid = { 0x5f8b97df, 0x2d0d, 0x4ad2, {0x98, 0xd2, 0x74, 0xf4, 0x38, 0x27, 0x98, 0xbb}, }; void smc_std_handler(struct thread_smc_args *args, struct sm_nsec_ctx *nsec) { uint32_t smc_fid = args->a0; if (is_psci_fid(smc_fid)) { tee_psci_handler(args, nsec); return; } switch (smc_fid) { case ARM_STD_SVC_CALL_COUNT: /* PSCI is the only STD service implemented */ args->a0 = PSCI_NUM_CALLS; break; case ARM_STD_SVC_UID: args->a0 = uuid.timeLow; args->a1 = (uuid.timeHiAndVersion << 16) | uuid.timeMid; args->a2 = (uuid.clockSeqAndNode[3] << 24) | (uuid.clockSeqAndNode[2] << 16) | (uuid.clockSeqAndNode[1] << 8) | uuid.clockSeqAndNode[0]; args->a3 = (uuid.clockSeqAndNode[7] << 24) | (uuid.clockSeqAndNode[6] << 16) | (uuid.clockSeqAndNode[5] << 8) | uuid.clockSeqAndNode[4]; break; case ARM_STD_SVC_VERSION: args->a0 = STD_SVC_VERSION_MAJOR; args->a1 = STD_SVC_VERSION_MINOR; break; default: args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; break; } } optee_os-4.3.0/core/arch/arm/sm/sub.mk000066400000000000000000000002011464416617300175250ustar00rootroot00000000000000srcs-y += sm_a32.S srcs-y += sm.c srcs-$(CFG_PM_ARM32) += pm.c pm_a32.S srcs-$(CFG_PSCI_ARM32) += std_smc.c psci.c psci-helper.S optee_os-4.3.0/core/arch/arm/tee/000077500000000000000000000000001464416617300165505ustar00rootroot00000000000000optee_os-4.3.0/core/arch/arm/tee/cache.c000066400000000000000000000030661464416617300177640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015, Linaro Limited */ #include #include #include /* * tee_uta_cache_operation - dynamic cache clean/inval request from a TA. * It follows ARM recommendation: * https://developer.arm.com/documentation/ddi0246/c/Beicdhde * Note that this implementation assumes dsb operations are part of * cache_op_inner(), and outer cache sync are part of cache_op_outer(). */ TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len) { TEE_Result res; paddr_t pa; pa = virt_to_phys(va); if (!pa) return TEE_ERROR_ACCESS_DENIED; switch (op) { case TEE_CACHEFLUSH: #ifdef CFG_PL310 /* prevent initial L1 clean in case there is no outer L2 */ /* Clean L1, Flush L2, Flush L1 */ res = cache_op_inner(DCACHE_AREA_CLEAN, va, len); if (res != TEE_SUCCESS) return res; res = cache_op_outer(DCACHE_AREA_CLEAN_INV, pa, len); if (res != TEE_SUCCESS) return res; #endif return cache_op_inner(DCACHE_AREA_CLEAN_INV, va, len); case TEE_CACHECLEAN: /* Clean L1, Clean L2 */ res = cache_op_inner(DCACHE_AREA_CLEAN, va, len); if (res != TEE_SUCCESS) return res; return cache_op_outer(DCACHE_AREA_CLEAN, pa, len); case TEE_CACHEINVALIDATE: /* Inval L2, Inval L1 */ res = cache_op_outer(DCACHE_AREA_INVALIDATE, pa, len); if (res != TEE_SUCCESS) return res; return cache_op_inner(DCACHE_AREA_INVALIDATE, va, len); default: return TEE_ERROR_NOT_SUPPORTED; } } optee_os-4.3.0/core/arch/arm/tee/entry_fast.c000066400000000000000000000213041464416617300210720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2021, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #ifdef CFG_CORE_RESERVED_SHM static void tee_entry_get_shm_config(struct thread_smc_args *args) { args->a0 = OPTEE_SMC_RETURN_OK; args->a1 = default_nsec_shm_paddr; args->a2 = default_nsec_shm_size; /* Should this be TEESMC cache attributes instead? */ args->a3 = core_mmu_is_shm_cached(); } #endif static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args) { #ifdef ARM32 TEE_Result ret = TEE_ERROR_NOT_SUPPORTED; paddr_t pa = 0; switch (args->a1) { case OPTEE_SMC_L2CC_MUTEX_GET_ADDR: ret = tee_get_l2cc_mutex(&pa); reg_pair_from_64(pa, &args->a2, &args->a3); break; case OPTEE_SMC_L2CC_MUTEX_SET_ADDR: pa = reg_pair_to_64(args->a2, args->a3); ret = tee_set_l2cc_mutex(&pa); break; case OPTEE_SMC_L2CC_MUTEX_ENABLE: ret = tee_enable_l2cc_mutex(); break; case OPTEE_SMC_L2CC_MUTEX_DISABLE: ret = tee_disable_l2cc_mutex(); break; default: args->a0 = OPTEE_SMC_RETURN_EBADCMD; return; } if (ret == TEE_ERROR_NOT_SUPPORTED) args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; else if (ret) args->a0 = OPTEE_SMC_RETURN_EBADADDR; else args->a0 = OPTEE_SMC_RETURN_OK; #else args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; #endif } static void tee_entry_exchange_capabilities(struct thread_smc_args *args) { bool res_shm_en = IS_ENABLED(CFG_CORE_RESERVED_SHM); bool dyn_shm_en __maybe_unused = false; /* * Currently we ignore OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. * * The memory mapping of shared memory is defined as normal * shared memory for SMP systems and normal memory for UP * systems. Currently we map all memory as shared in secure * world. * * When translation tables are created with shared bit cleared for * uniprocessor systems we'll need to check * OPTEE_SMC_NSEC_CAP_UNIPROCESSOR. */ if (args->a1 & ~OPTEE_SMC_NSEC_CAP_UNIPROCESSOR) { /* Unknown capability. */ args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; return; } args->a0 = OPTEE_SMC_RETURN_OK; args->a1 = 0; if (res_shm_en) args->a1 |= OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM; IMSG("Reserved shared memory is %sabled", res_shm_en ? "en" : "dis"); #if defined(CFG_CORE_DYN_SHM) dyn_shm_en = core_mmu_nsec_ddr_is_defined(); if (dyn_shm_en) args->a1 |= OPTEE_SMC_SEC_CAP_DYNAMIC_SHM; #endif IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis"); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) args->a1 |= OPTEE_SMC_SEC_CAP_VIRTUALIZATION; IMSG("Normal World virtualization support is %sabled", IS_ENABLED(CFG_NS_VIRTUALIZATION) ? "en" : "dis"); args->a1 |= OPTEE_SMC_SEC_CAP_MEMREF_NULL; if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { args->a1 |= OPTEE_SMC_SEC_CAP_ASYNC_NOTIF; args->a2 = NOTIF_VALUE_MAX; } IMSG("Asynchronous notifications are %sabled", IS_ENABLED(CFG_CORE_ASYNC_NOTIF) ? "en" : "dis"); args->a1 |= OPTEE_SMC_SEC_CAP_RPC_ARG; args->a3 = THREAD_RPC_MAX_NUM_PARAMS; } static void tee_entry_disable_shm_cache(struct thread_smc_args *args) { uint64_t cookie; if (!thread_disable_prealloc_rpc_cache(&cookie)) { args->a0 = OPTEE_SMC_RETURN_EBUSY; return; } if (!cookie) { args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; return; } args->a0 = OPTEE_SMC_RETURN_OK; args->a1 = cookie >> 32; args->a2 = cookie; } static void tee_entry_enable_shm_cache(struct thread_smc_args *args) { if (thread_enable_prealloc_rpc_cache()) args->a0 = OPTEE_SMC_RETURN_OK; else args->a0 = OPTEE_SMC_RETURN_EBUSY; } static void tee_entry_boot_secondary(struct thread_smc_args *args) { #if defined(CFG_BOOT_SECONDARY_REQUEST) if (!boot_core_release(args->a1, (paddr_t)(args->a3))) args->a0 = OPTEE_SMC_RETURN_OK; else args->a0 = OPTEE_SMC_RETURN_EBADCMD; #else args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; #endif } static void tee_entry_get_thread_count(struct thread_smc_args *args) { args->a0 = OPTEE_SMC_RETURN_OK; args->a1 = CFG_NUM_THREADS; } #if defined(CFG_NS_VIRTUALIZATION) static void tee_entry_vm_created(struct thread_smc_args *args) { uint16_t guest_id = args->a1; /* Only hypervisor can issue this request */ if (args->a7 != HYP_CLNT_ID) { args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; return; } if (virt_guest_created(guest_id)) args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; else args->a0 = OPTEE_SMC_RETURN_OK; } static void tee_entry_vm_destroyed(struct thread_smc_args *args) { uint16_t guest_id = args->a1; /* Only hypervisor can issue this request */ if (args->a7 != HYP_CLNT_ID) { args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; return; } if (virt_guest_destroyed(guest_id)) args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL; else args->a0 = OPTEE_SMC_RETURN_OK; } #endif /* Note: this function is weak to let platforms add special handling */ void __weak tee_entry_fast(struct thread_smc_args *args) { __tee_entry_fast(args); } static void get_async_notif_value(struct thread_smc_args *args) { bool value_valid = false; bool value_pending = false; args->a0 = OPTEE_SMC_RETURN_OK; args->a1 = notif_get_value(&value_valid, &value_pending); args->a2 = 0; if (value_valid) args->a2 |= OPTEE_SMC_ASYNC_NOTIF_VALID; if (value_pending) args->a2 |= OPTEE_SMC_ASYNC_NOTIF_PENDING; } static void tee_entry_watchdog(struct thread_smc_args *args) { #if defined(CFG_WDT_SM_HANDLER) __wdt_sm_handler(args); #else args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; #endif } /* * If tee_entry_fast() is overridden, it's still supposed to call this * function. */ void __tee_entry_fast(struct thread_smc_args *args) { switch (args->a0) { /* Generic functions */ case OPTEE_SMC_CALLS_COUNT: tee_entry_get_api_call_count(args); break; case OPTEE_SMC_CALLS_UID: tee_entry_get_api_uuid(args); break; case OPTEE_SMC_CALLS_REVISION: tee_entry_get_api_revision(args); break; case OPTEE_SMC_CALL_GET_OS_UUID: tee_entry_get_os_uuid(args); break; case OPTEE_SMC_CALL_GET_OS_REVISION: tee_entry_get_os_revision(args); break; /* OP-TEE specific SMC functions */ #ifdef CFG_CORE_RESERVED_SHM case OPTEE_SMC_GET_SHM_CONFIG: tee_entry_get_shm_config(args); break; #endif case OPTEE_SMC_L2CC_MUTEX: tee_entry_fastcall_l2cc_mutex(args); break; case OPTEE_SMC_EXCHANGE_CAPABILITIES: tee_entry_exchange_capabilities(args); break; case OPTEE_SMC_DISABLE_SHM_CACHE: tee_entry_disable_shm_cache(args); break; case OPTEE_SMC_ENABLE_SHM_CACHE: tee_entry_enable_shm_cache(args); break; case OPTEE_SMC_BOOT_SECONDARY: tee_entry_boot_secondary(args); break; case OPTEE_SMC_GET_THREAD_COUNT: tee_entry_get_thread_count(args); break; #if defined(CFG_NS_VIRTUALIZATION) case OPTEE_SMC_VM_CREATED: tee_entry_vm_created(args); break; case OPTEE_SMC_VM_DESTROYED: tee_entry_vm_destroyed(args); break; #endif case OPTEE_SMC_ENABLE_ASYNC_NOTIF: if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { notif_deliver_atomic_event(NOTIF_EVENT_STARTED, 0); args->a0 = OPTEE_SMC_RETURN_OK; } else { args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; } break; case OPTEE_SMC_GET_ASYNC_NOTIF_VALUE: if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) get_async_notif_value(args); else args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; break; /* Watchdog entry if handler ID is defined in TOS range */ case CFG_WDT_SM_HANDLER_ID: tee_entry_watchdog(args); break; default: args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION; break; } } size_t tee_entry_generic_get_api_call_count(void) { /* * All the different calls handled in this file. If the specific * target has additional calls it will call this function and * add the number of calls the target has added. */ size_t ret = 12; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) ret += 2; return ret; } void __weak tee_entry_get_api_call_count(struct thread_smc_args *args) { args->a0 = tee_entry_generic_get_api_call_count(); } void __weak tee_entry_get_api_uuid(struct thread_smc_args *args) { args->a0 = OPTEE_MSG_UID_0; args->a1 = OPTEE_MSG_UID_1; args->a2 = OPTEE_MSG_UID_2; args->a3 = OPTEE_MSG_UID_3; } void __weak tee_entry_get_api_revision(struct thread_smc_args *args) { args->a0 = OPTEE_MSG_REVISION_MAJOR; args->a1 = OPTEE_MSG_REVISION_MINOR; } void __weak tee_entry_get_os_uuid(struct thread_smc_args *args) { args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0; args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1; args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2; args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3; } void __weak tee_entry_get_os_revision(struct thread_smc_args *args) { args->a0 = CFG_OPTEE_REVISION_MAJOR; args->a1 = CFG_OPTEE_REVISION_MINOR; args->a2 = TEE_IMPL_GIT_SHA1; } optee_os-4.3.0/core/arch/arm/tee/sub.mk000066400000000000000000000003251464416617300176720ustar00rootroot00000000000000ifeq ($(CFG_WITH_USER_TA),y) srcs-$(CFG_CACHE_API) += svc_cache.c endif ifneq ($(CFG_CORE_FFA),y) srcs-y += entry_fast.c cppflags-entry_fast.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) endif srcs-y += cache.c optee_os-4.3.0/core/arch/arm/tee/svc_cache.c000066400000000000000000000020111464416617300206240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015, Linaro Limited */ #include #include #include #include TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op) { struct ts_session *s = ts_get_current_session(); struct user_ta_ctx *utc = NULL; TEE_Result res = TEE_SUCCESS; if ((to_ta_ctx(s->ctx)->flags & TA_FLAG_CACHE_MAINTENANCE) == 0) return TEE_ERROR_NOT_SUPPORTED; utc = to_user_ta_ctx(s->ctx); /* * TAs are allowed to operate cache maintenance on TA memref parameters * only, not on the TA private memory. */ if (vm_buf_intersects_um_private(&utc->uctx, va, len)) return TEE_ERROR_ACCESS_DENIED; res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)va, len); if (res != TEE_SUCCESS) return TEE_ERROR_ACCESS_DENIED; return cache_operation(op, va, len); } optee_os-4.3.0/core/arch/riscv/000077500000000000000000000000001464416617300163425ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/include/000077500000000000000000000000001464416617300177655ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/include/encoding.h000066400000000000000000005460051464416617300217360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* Copyright (c) 2022 RISC-V International */ /* * This file is auto-generated by running 'make' in * https://github.com/riscv/riscv-opcodes (86edbf4) */ #ifndef RISCV_CSR_ENCODING_H #define RISCV_CSR_ENCODING_H #define MSTATUS_UIE 0x00000001 #define MSTATUS_SIE 0x00000002 #define MSTATUS_HIE 0x00000004 #define MSTATUS_MIE 0x00000008 #define MSTATUS_UPIE 0x00000010 #define MSTATUS_SPIE 0x00000020 #define MSTATUS_UBE 0x00000040 #define MSTATUS_MPIE 0x00000080 #define MSTATUS_SPP 0x00000100 #define MSTATUS_VS 0x00000600 #define MSTATUS_MPP 0x00001800 #define MSTATUS_FS 0x00006000 #define MSTATUS_XS 0x00018000 #define MSTATUS_MPRV 0x00020000 #define MSTATUS_SUM 0x00040000 #define MSTATUS_MXR 0x00080000 #define MSTATUS_TVM 0x00100000 #define MSTATUS_TW 0x00200000 #define MSTATUS_TSR 0x00400000 #define MSTATUS32_SD 0x80000000 #define MSTATUS_UXL 0x0000000300000000 #define MSTATUS_SXL 0x0000000C00000000 #define MSTATUS_SBE 0x0000001000000000 #define MSTATUS_MBE 0x0000002000000000 #define MSTATUS_GVA 0x0000004000000000 #define MSTATUS_MPV 0x0000008000000000 #define MSTATUS64_SD 0x8000000000000000 #define MSTATUSH_SBE 0x00000010 #define MSTATUSH_MBE 0x00000020 #define MSTATUSH_GVA 0x00000040 #define MSTATUSH_MPV 0x00000080 #define SSTATUS_UIE 0x00000001 #define SSTATUS_SIE 0x00000002 #define SSTATUS_UPIE 0x00000010 #define SSTATUS_SPIE 0x00000020 #define SSTATUS_UBE 0x00000040 #define SSTATUS_SPP 0x00000100 #define SSTATUS_VS 0x00000600 #define SSTATUS_FS 0x00006000 #define SSTATUS_XS 0x00018000 #define SSTATUS_SUM 0x00040000 #define SSTATUS_MXR 0x00080000 #define SSTATUS32_SD 0x80000000 #define SSTATUS_UXL 0x0000000300000000 #define SSTATUS64_SD 0x8000000000000000 #define HSTATUS_VSXL 0x300000000 #define HSTATUS_VTSR 0x00400000 #define HSTATUS_VTW 0x00200000 #define HSTATUS_VTVM 0x00100000 #define HSTATUS_VGEIN 0x0003f000 #define HSTATUS_HU 0x00000200 #define HSTATUS_SPVP 0x00000100 #define HSTATUS_SPV 0x00000080 #define HSTATUS_GVA 0x00000040 #define HSTATUS_VSBE 0x00000020 #define USTATUS_UIE 0x00000001 #define USTATUS_UPIE 0x00000010 #define DCSR_XDEBUGVER (3U<<30) #define DCSR_NDRESET (1<<29) #define DCSR_FULLRESET (1<<28) #define DCSR_EBREAKM (1<<15) #define DCSR_EBREAKH (1<<14) #define DCSR_EBREAKS (1<<13) #define DCSR_EBREAKU (1<<12) #define DCSR_STOPCYCLE (1<<10) #define DCSR_STOPTIME (1<<9) #define DCSR_CAUSE (7<<6) #define DCSR_DEBUGINT (1<<5) #define DCSR_HALT (1<<3) #define DCSR_STEP (1<<2) #define DCSR_PRV (3<<0) #define DCSR_CAUSE_NONE 0 #define DCSR_CAUSE_SWBP 1 #define DCSR_CAUSE_HWBP 2 #define DCSR_CAUSE_DEBUGINT 3 #define DCSR_CAUSE_STEP 4 #define DCSR_CAUSE_HALT 5 #define DCSR_CAUSE_GROUP 6 #define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) #define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) #define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) #define MCONTROL_SELECT (1<<19) #define MCONTROL_TIMING (1<<18) #define MCONTROL_ACTION (0x3f<<12) #define MCONTROL_CHAIN (1<<11) #define MCONTROL_MATCH (0xf<<7) #define MCONTROL_M (1<<6) #define MCONTROL_H (1<<5) #define MCONTROL_S (1<<4) #define MCONTROL_U (1<<3) #define MCONTROL_EXECUTE (1<<2) #define MCONTROL_STORE (1<<1) #define MCONTROL_LOAD (1<<0) #define MCONTROL_TYPE_NONE 0 #define MCONTROL_TYPE_MATCH 2 #define MCONTROL_ACTION_DEBUG_EXCEPTION 0 #define MCONTROL_ACTION_DEBUG_MODE 1 #define MCONTROL_ACTION_TRACE_START 2 #define MCONTROL_ACTION_TRACE_STOP 3 #define MCONTROL_ACTION_TRACE_EMIT 4 #define MCONTROL_MATCH_EQUAL 0 #define MCONTROL_MATCH_NAPOT 1 #define MCONTROL_MATCH_GE 2 #define MCONTROL_MATCH_LT 3 #define MCONTROL_MATCH_MASK_LOW 4 #define MCONTROL_MATCH_MASK_HIGH 5 #define MIP_USIP (1 << IRQ_U_SOFT) #define MIP_SSIP (1 << IRQ_S_SOFT) #define MIP_VSSIP (1 << IRQ_VS_SOFT) #define MIP_MSIP (1 << IRQ_M_SOFT) #define MIP_UTIP (1 << IRQ_U_TIMER) #define MIP_STIP (1 << IRQ_S_TIMER) #define MIP_VSTIP (1 << IRQ_VS_TIMER) #define MIP_MTIP (1 << IRQ_M_TIMER) #define MIP_UEIP (1 << IRQ_U_EXT) #define MIP_SEIP (1 << IRQ_S_EXT) #define MIP_VSEIP (1 << IRQ_VS_EXT) #define MIP_MEIP (1 << IRQ_M_EXT) #define MIP_SGEIP (1 << IRQ_S_GEXT) #define MIP_LCOFIP (1 << IRQ_LCOF) #define MIP_S_MASK (MIP_SSIP | MIP_STIP | MIP_SEIP) #define MIP_VS_MASK (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP) #define MIP_HS_MASK (MIP_VS_MASK | MIP_SGEIP) #define MIDELEG_FORCED_MASK MIP_HS_MASK #define SIP_SSIP MIP_SSIP #define SIP_STIP MIP_STIP #define MENVCFG_FIOM 0x00000001 #define MENVCFG_CBIE 0x00000030 #define MENVCFG_CBCFE 0x00000040 #define MENVCFG_CBZE 0x00000080 #define MENVCFG_PBMTE 0x4000000000000000 #define MENVCFG_STCE 0x8000000000000000 #define MENVCFGH_PBMTE 0x40000000 #define MENVCFGH_STCE 0x80000000 #define MSTATEEN0_CS 0x00000001 #define MSTATEEN0_FCSR 0x00000002 #define MSTATEEN0_HCONTEXT 0x0200000000000000 #define MSTATEEN0_HENVCFG 0x4000000000000000 #define MSTATEEN_HSTATEEN 0x8000000000000000 #define MSTATEEN0H_HCONTEXT 0x02000000 #define MSTATEEN0H_HENVCFG 0x40000000 #define MSTATEENH_HSTATEEN 0x80000000 #define MHPMEVENT_VUINH 0x0400000000000000 #define MHPMEVENT_VSINH 0x0800000000000000 #define MHPMEVENT_UINH 0x1000000000000000 #define MHPMEVENT_SINH 0x2000000000000000 #define MHPMEVENT_MINH 0x4000000000000000 #define MHPMEVENT_OF 0x8000000000000000 #define MHPMEVENTH_VUINH 0x04000000 #define MHPMEVENTH_VSINH 0x08000000 #define MHPMEVENTH_UINH 0x10000000 #define MHPMEVENTH_SINH 0x20000000 #define MHPMEVENTH_MINH 0x40000000 #define MHPMEVENTH_OF 0x80000000 #define HENVCFG_FIOM 0x00000001 #define HENVCFG_CBIE 0x00000030 #define HENVCFG_CBCFE 0x00000040 #define HENVCFG_CBZE 0x00000080 #define HENVCFG_PBMTE 0x4000000000000000 #define HENVCFG_STCE 0x8000000000000000 #define HENVCFGH_PBMTE 0x40000000 #define HENVCFGH_STCE 0x80000000 #define HSTATEEN0_CS 0x00000001 #define HSTATEEN0_FCSR 0x00000002 #define HSTATEEN0_SCONTEXT 0x0200000000000000 #define HSTATEEN0_SENVCFG 0x4000000000000000 #define HSTATEEN_SSTATEEN 0x8000000000000000 #define HSTATEEN0H_SCONTEXT 0x02000000 #define HSTATEEN0H_SENVCFG 0x40000000 #define HSTATEENH_SSTATEEN 0x80000000 #define SENVCFG_FIOM 0x00000001 #define SENVCFG_CBIE 0x00000030 #define SENVCFG_CBCFE 0x00000040 #define SENVCFG_CBZE 0x00000080 #define SSTATEEN0_CS 0x00000001 #define SSTATEEN0_FCSR 0x00000002 #define MSECCFG_MML 0x00000001 #define MSECCFG_MMWP 0x00000002 #define MSECCFG_RLB 0x00000004 #define MSECCFG_USEED 0x00000100 #define MSECCFG_SSEED 0x00000200 #define PRV_U 0 #define PRV_S 1 #define PRV_M 3 #define PRV_HS (PRV_S + 1) #define SATP32_MODE 0x80000000 #define SATP32_ASID 0x7FC00000 #define SATP32_PPN 0x003FFFFF #define SATP64_MODE 0xF000000000000000 #define SATP64_ASID 0x0FFFF00000000000 #define SATP64_PPN 0x00000FFFFFFFFFFF #define SATP_MODE_OFF 0 #define SATP_MODE_SV32 1 #define SATP_MODE_SV39 8 #define SATP_MODE_SV48 9 #define SATP_MODE_SV57 10 #define SATP_MODE_SV64 11 #define HGATP32_MODE 0x80000000 #define HGATP32_VMID 0x1FC00000 #define HGATP32_PPN 0x003FFFFF #define HGATP64_MODE 0xF000000000000000 #define HGATP64_VMID 0x03FFF00000000000 #define HGATP64_PPN 0x00000FFFFFFFFFFF #define HGATP_MODE_OFF 0 #define HGATP_MODE_SV32X4 1 #define HGATP_MODE_SV39X4 8 #define HGATP_MODE_SV48X4 9 #define HGATP_MODE_SV57X4 10 #define PMP_R 0x01 #define PMP_W 0x02 #define PMP_X 0x04 #define PMP_A 0x18 #define PMP_L 0x80 #define PMP_SHIFT 2 #define PMP_TOR 0x08 #define PMP_NA4 0x10 #define PMP_NAPOT 0x18 #define IRQ_U_SOFT 0 #define IRQ_S_SOFT 1 #define IRQ_VS_SOFT 2 #define IRQ_M_SOFT 3 #define IRQ_U_TIMER 4 #define IRQ_S_TIMER 5 #define IRQ_VS_TIMER 6 #define IRQ_M_TIMER 7 #define IRQ_U_EXT 8 #define IRQ_S_EXT 9 #define IRQ_VS_EXT 10 #define IRQ_M_EXT 11 #define IRQ_S_GEXT 12 #define IRQ_COP 12 #define IRQ_LCOF 13 /* page table entry (PTE) fields */ #define PTE_V 0x001 /* Valid */ #define PTE_R 0x002 /* Read */ #define PTE_W 0x004 /* Write */ #define PTE_X 0x008 /* Execute */ #define PTE_U 0x010 /* User */ #define PTE_G 0x020 /* Global */ #define PTE_A 0x040 /* Accessed */ #define PTE_D 0x080 /* Dirty */ #define PTE_SOFT 0x300 /* Reserved for Software */ #define PTE_RSVD 0x1FC0000000000000 /* Reserved for future standard use */ #define PTE_PBMT 0x6000000000000000 /* Svpbmt: Page-based memory types */ #define PTE_N 0x8000000000000000 /* Svnapot: NAPOT translation contiguity */ #define PTE_ATTR 0xFFC0000000000000 /* All attributes and reserved bits */ #define PTE_PPN_SHIFT 10 #define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) #ifdef __riscv #if __riscv_xlen == 64 # define MSTATUS_SD MSTATUS64_SD # define SSTATUS_SD SSTATUS64_SD # define RISCV_PGLEVEL_BITS 9 # define SATP_MODE SATP64_MODE #else # define MSTATUS_SD MSTATUS32_SD # define SSTATUS_SD SSTATUS32_SD # define RISCV_PGLEVEL_BITS 10 # define SATP_MODE SATP32_MODE #endif #define RISCV_PGSHIFT 12 #define RISCV_PGSIZE (1 << RISCV_PGSHIFT) #endif #endif /* Automatically generated by parse_opcodes. */ #ifndef RISCV_ENCODING_H #define RISCV_ENCODING_H #define MATCH_ADD 0x33 #define MASK_ADD 0xfe00707f #define MATCH_ADD16 0x40000077 #define MASK_ADD16 0xfe00707f #define MATCH_ADD32 0x40002077 #define MASK_ADD32 0xfe00707f #define MATCH_ADD64 0xc0001077 #define MASK_ADD64 0xfe00707f #define MATCH_ADD8 0x48000077 #define MASK_ADD8 0xfe00707f #define MATCH_ADD_UW 0x800003b #define MASK_ADD_UW 0xfe00707f #define MATCH_ADDD 0x7b #define MASK_ADDD 0xfe00707f #define MATCH_ADDI 0x13 #define MASK_ADDI 0x707f #define MATCH_ADDID 0x5b #define MASK_ADDID 0x707f #define MATCH_ADDIW 0x1b #define MASK_ADDIW 0x707f #define MATCH_ADDW 0x3b #define MASK_ADDW 0xfe00707f #define MATCH_AES32DSI 0x2a000033 #define MASK_AES32DSI 0x3e00707f #define MATCH_AES32DSMI 0x2e000033 #define MASK_AES32DSMI 0x3e00707f #define MATCH_AES32ESI 0x22000033 #define MASK_AES32ESI 0x3e00707f #define MATCH_AES32ESMI 0x26000033 #define MASK_AES32ESMI 0x3e00707f #define MATCH_AES64DS 0x3a000033 #define MASK_AES64DS 0xfe00707f #define MATCH_AES64DSM 0x3e000033 #define MASK_AES64DSM 0xfe00707f #define MATCH_AES64ES 0x32000033 #define MASK_AES64ES 0xfe00707f #define MATCH_AES64ESM 0x36000033 #define MASK_AES64ESM 0xfe00707f #define MATCH_AES64IM 0x30001013 #define MASK_AES64IM 0xfff0707f #define MATCH_AES64KS1I 0x31001013 #define MASK_AES64KS1I 0xff00707f #define MATCH_AES64KS2 0x7e000033 #define MASK_AES64KS2 0xfe00707f #define MATCH_AMOADD_D 0x302f #define MASK_AMOADD_D 0xf800707f #define MATCH_AMOADD_W 0x202f #define MASK_AMOADD_W 0xf800707f #define MATCH_AMOAND_D 0x6000302f #define MASK_AMOAND_D 0xf800707f #define MATCH_AMOAND_W 0x6000202f #define MASK_AMOAND_W 0xf800707f #define MATCH_AMOMAX_D 0xa000302f #define MASK_AMOMAX_D 0xf800707f #define MATCH_AMOMAX_W 0xa000202f #define MASK_AMOMAX_W 0xf800707f #define MATCH_AMOMAXU_D 0xe000302f #define MASK_AMOMAXU_D 0xf800707f #define MATCH_AMOMAXU_W 0xe000202f #define MASK_AMOMAXU_W 0xf800707f #define MATCH_AMOMIN_D 0x8000302f #define MASK_AMOMIN_D 0xf800707f #define MATCH_AMOMIN_W 0x8000202f #define MASK_AMOMIN_W 0xf800707f #define MATCH_AMOMINU_D 0xc000302f #define MASK_AMOMINU_D 0xf800707f #define MATCH_AMOMINU_W 0xc000202f #define MASK_AMOMINU_W 0xf800707f #define MATCH_AMOOR_D 0x4000302f #define MASK_AMOOR_D 0xf800707f #define MATCH_AMOOR_W 0x4000202f #define MASK_AMOOR_W 0xf800707f #define MATCH_AMOSWAP_D 0x800302f #define MASK_AMOSWAP_D 0xf800707f #define MATCH_AMOSWAP_W 0x800202f #define MASK_AMOSWAP_W 0xf800707f #define MATCH_AMOXOR_D 0x2000302f #define MASK_AMOXOR_D 0xf800707f #define MATCH_AMOXOR_W 0x2000202f #define MASK_AMOXOR_W 0xf800707f #define MATCH_AND 0x7033 #define MASK_AND 0xfe00707f #define MATCH_ANDI 0x7013 #define MASK_ANDI 0x707f #define MATCH_ANDN 0x40007033 #define MASK_ANDN 0xfe00707f #define MATCH_AUIPC 0x17 #define MASK_AUIPC 0x7f #define MATCH_AVE 0xe0000077 #define MASK_AVE 0xfe00707f #define MATCH_BCLR 0x48001033 #define MASK_BCLR 0xfe00707f #define MATCH_BCLRI 0x48001013 #define MASK_BCLRI 0xfc00707f #define MATCH_BCOMPRESS 0x8006033 #define MASK_BCOMPRESS 0xfe00707f #define MATCH_BCOMPRESSW 0x800603b #define MASK_BCOMPRESSW 0xfe00707f #define MATCH_BDECOMPRESS 0x48006033 #define MASK_BDECOMPRESS 0xfe00707f #define MATCH_BDECOMPRESSW 0x4800603b #define MASK_BDECOMPRESSW 0xfe00707f #define MATCH_BEQ 0x63 #define MASK_BEQ 0x707f #define MATCH_BEXT 0x48005033 #define MASK_BEXT 0xfe00707f #define MATCH_BEXTI 0x48005013 #define MASK_BEXTI 0xfc00707f #define MATCH_BFP 0x48007033 #define MASK_BFP 0xfe00707f #define MATCH_BFPW 0x4800703b #define MASK_BFPW 0xfe00707f #define MATCH_BGE 0x5063 #define MASK_BGE 0x707f #define MATCH_BGEU 0x7063 #define MASK_BGEU 0x707f #define MATCH_BINV 0x68001033 #define MASK_BINV 0xfe00707f #define MATCH_BINVI 0x68001013 #define MASK_BINVI 0xfc00707f #define MATCH_BITREV 0xe6000077 #define MASK_BITREV 0xfe00707f #define MATCH_BITREVI 0xe8000077 #define MASK_BITREVI 0xfc00707f #define MATCH_BLT 0x4063 #define MASK_BLT 0x707f #define MATCH_BLTU 0x6063 #define MASK_BLTU 0x707f #define MATCH_BMATFLIP 0x60301013 #define MASK_BMATFLIP 0xfff0707f #define MATCH_BMATOR 0x8003033 #define MASK_BMATOR 0xfe00707f #define MATCH_BMATXOR 0x48003033 #define MASK_BMATXOR 0xfe00707f #define MATCH_BNE 0x1063 #define MASK_BNE 0x707f #define MATCH_BPICK 0x3077 #define MASK_BPICK 0x600707f #define MATCH_BSET 0x28001033 #define MASK_BSET 0xfe00707f #define MATCH_BSETI 0x28001013 #define MASK_BSETI 0xfc00707f #define MATCH_C_ADD 0x9002 #define MASK_C_ADD 0xf003 #define MATCH_C_ADDI 0x1 #define MASK_C_ADDI 0xe003 #define MATCH_C_ADDI16SP 0x6101 #define MASK_C_ADDI16SP 0xef83 #define MATCH_C_ADDI4SPN 0x0 #define MASK_C_ADDI4SPN 0xe003 #define MATCH_C_ADDIW 0x2001 #define MASK_C_ADDIW 0xe003 #define MATCH_C_ADDW 0x9c21 #define MASK_C_ADDW 0xfc63 #define MATCH_C_AND 0x8c61 #define MASK_C_AND 0xfc63 #define MATCH_C_ANDI 0x8801 #define MASK_C_ANDI 0xec03 #define MATCH_C_BEQZ 0xc001 #define MASK_C_BEQZ 0xe003 #define MATCH_C_BNEZ 0xe001 #define MASK_C_BNEZ 0xe003 #define MATCH_C_EBREAK 0x9002 #define MASK_C_EBREAK 0xffff #define MATCH_C_FLD 0x2000 #define MASK_C_FLD 0xe003 #define MATCH_C_FLDSP 0x2002 #define MASK_C_FLDSP 0xe003 #define MATCH_C_FLW 0x6000 #define MASK_C_FLW 0xe003 #define MATCH_C_FLWSP 0x6002 #define MASK_C_FLWSP 0xe003 #define MATCH_C_FSD 0xa000 #define MASK_C_FSD 0xe003 #define MATCH_C_FSDSP 0xa002 #define MASK_C_FSDSP 0xe003 #define MATCH_C_FSW 0xe000 #define MASK_C_FSW 0xe003 #define MATCH_C_FSWSP 0xe002 #define MASK_C_FSWSP 0xe003 #define MATCH_C_J 0xa001 #define MASK_C_J 0xe003 #define MATCH_C_JAL 0x2001 #define MASK_C_JAL 0xe003 #define MATCH_C_JALR 0x9002 #define MASK_C_JALR 0xf07f #define MATCH_C_JR 0x8002 #define MASK_C_JR 0xf07f #define MATCH_C_LD 0x6000 #define MASK_C_LD 0xe003 #define MATCH_C_LDSP 0x6002 #define MASK_C_LDSP 0xe003 #define MATCH_C_LI 0x4001 #define MASK_C_LI 0xe003 #define MATCH_C_LQ 0x2000 #define MASK_C_LQ 0xe003 #define MATCH_C_LQSP 0x2002 #define MASK_C_LQSP 0xe003 #define MATCH_C_LUI 0x6001 #define MASK_C_LUI 0xe003 #define MATCH_C_LW 0x4000 #define MASK_C_LW 0xe003 #define MATCH_C_LWSP 0x4002 #define MASK_C_LWSP 0xe003 #define MATCH_C_MV 0x8002 #define MASK_C_MV 0xf003 #define MATCH_C_NOP 0x1 #define MASK_C_NOP 0xef83 #define MATCH_C_OR 0x8c41 #define MASK_C_OR 0xfc63 #define MATCH_C_SD 0xe000 #define MASK_C_SD 0xe003 #define MATCH_C_SDSP 0xe002 #define MASK_C_SDSP 0xe003 #define MATCH_C_SLLI 0x2 #define MASK_C_SLLI 0xe003 #define MATCH_C_SQ 0xa000 #define MASK_C_SQ 0xe003 #define MATCH_C_SQSP 0xa002 #define MASK_C_SQSP 0xe003 #define MATCH_C_SRAI 0x8401 #define MASK_C_SRAI 0xec03 #define MATCH_C_SRLI 0x8001 #define MASK_C_SRLI 0xec03 #define MATCH_C_SUB 0x8c01 #define MASK_C_SUB 0xfc63 #define MATCH_C_SUBW 0x9c01 #define MASK_C_SUBW 0xfc63 #define MATCH_C_SW 0xc000 #define MASK_C_SW 0xe003 #define MATCH_C_SWSP 0xc002 #define MASK_C_SWSP 0xe003 #define MATCH_C_XOR 0x8c21 #define MASK_C_XOR 0xfc63 #define MATCH_CBO_CLEAN 0x10200f #define MASK_CBO_CLEAN 0xfff07fff #define MATCH_CBO_FLUSH 0x20200f #define MASK_CBO_FLUSH 0xfff07fff #define MATCH_CBO_INVAL 0x200f #define MASK_CBO_INVAL 0xfff07fff #define MATCH_CBO_ZERO 0x40200f #define MASK_CBO_ZERO 0xfff07fff #define MATCH_CLMUL 0xa001033 #define MASK_CLMUL 0xfe00707f #define MATCH_CLMULH 0xa003033 #define MASK_CLMULH 0xfe00707f #define MATCH_CLMULR 0xa002033 #define MASK_CLMULR 0xfe00707f #define MATCH_CLO16 0xaeb00077 #define MASK_CLO16 0xfff0707f #define MATCH_CLO32 0xafb00077 #define MASK_CLO32 0xfff0707f #define MATCH_CLO8 0xae300077 #define MASK_CLO8 0xfff0707f #define MATCH_CLRS16 0xae800077 #define MASK_CLRS16 0xfff0707f #define MATCH_CLRS32 0xaf800077 #define MASK_CLRS32 0xfff0707f #define MATCH_CLRS8 0xae000077 #define MASK_CLRS8 0xfff0707f #define MATCH_CLZ 0x60001013 #define MASK_CLZ 0xfff0707f #define MATCH_CLZ16 0xae900077 #define MASK_CLZ16 0xfff0707f #define MATCH_CLZ32 0xaf900077 #define MASK_CLZ32 0xfff0707f #define MATCH_CLZ8 0xae100077 #define MASK_CLZ8 0xfff0707f #define MATCH_CLZW 0x6000101b #define MASK_CLZW 0xfff0707f #define MATCH_CMIX 0x6001033 #define MASK_CMIX 0x600707f #define MATCH_CMOV 0x6005033 #define MASK_CMOV 0x600707f #define MATCH_CMPEQ16 0x4c000077 #define MASK_CMPEQ16 0xfe00707f #define MATCH_CMPEQ8 0x4e000077 #define MASK_CMPEQ8 0xfe00707f #define MATCH_CPOP 0x60201013 #define MASK_CPOP 0xfff0707f #define MATCH_CPOPW 0x6020101b #define MASK_CPOPW 0xfff0707f #define MATCH_CRAS16 0x44000077 #define MASK_CRAS16 0xfe00707f #define MATCH_CRAS32 0x44002077 #define MASK_CRAS32 0xfe00707f #define MATCH_CRC32_B 0x61001013 #define MASK_CRC32_B 0xfff0707f #define MATCH_CRC32_D 0x61301013 #define MASK_CRC32_D 0xfff0707f #define MATCH_CRC32_H 0x61101013 #define MASK_CRC32_H 0xfff0707f #define MATCH_CRC32_W 0x61201013 #define MASK_CRC32_W 0xfff0707f #define MATCH_CRC32C_B 0x61801013 #define MASK_CRC32C_B 0xfff0707f #define MATCH_CRC32C_D 0x61b01013 #define MASK_CRC32C_D 0xfff0707f #define MATCH_CRC32C_H 0x61901013 #define MASK_CRC32C_H 0xfff0707f #define MATCH_CRC32C_W 0x61a01013 #define MASK_CRC32C_W 0xfff0707f #define MATCH_CRSA16 0x46000077 #define MASK_CRSA16 0xfe00707f #define MATCH_CRSA32 0x46002077 #define MASK_CRSA32 0xfe00707f #define MATCH_CSRRC 0x3073 #define MASK_CSRRC 0x707f #define MATCH_CSRRCI 0x7073 #define MASK_CSRRCI 0x707f #define MATCH_CSRRS 0x2073 #define MASK_CSRRS 0x707f #define MATCH_CSRRSI 0x6073 #define MASK_CSRRSI 0x707f #define MATCH_CSRRW 0x1073 #define MASK_CSRRW 0x707f #define MATCH_CSRRWI 0x5073 #define MASK_CSRRWI 0x707f #define MATCH_CTZ 0x60101013 #define MASK_CTZ 0xfff0707f #define MATCH_CTZW 0x6010101b #define MASK_CTZW 0xfff0707f #define MATCH_DIV 0x2004033 #define MASK_DIV 0xfe00707f #define MATCH_DIVU 0x2005033 #define MASK_DIVU 0xfe00707f #define MATCH_DIVUW 0x200503b #define MASK_DIVUW 0xfe00707f #define MATCH_DIVW 0x200403b #define MASK_DIVW 0xfe00707f #define MATCH_DRET 0x7b200073 #define MASK_DRET 0xffffffff #define MATCH_EBREAK 0x100073 #define MASK_EBREAK 0xffffffff #define MATCH_ECALL 0x73 #define MASK_ECALL 0xffffffff #define MATCH_FADD_D 0x2000053 #define MASK_FADD_D 0xfe00007f #define MATCH_FADD_H 0x4000053 #define MASK_FADD_H 0xfe00007f #define MATCH_FADD_Q 0x6000053 #define MASK_FADD_Q 0xfe00007f #define MATCH_FADD_S 0x53 #define MASK_FADD_S 0xfe00007f #define MATCH_FCLASS_D 0xe2001053 #define MASK_FCLASS_D 0xfff0707f #define MATCH_FCLASS_H 0xe4001053 #define MASK_FCLASS_H 0xfff0707f #define MATCH_FCLASS_Q 0xe6001053 #define MASK_FCLASS_Q 0xfff0707f #define MATCH_FCLASS_S 0xe0001053 #define MASK_FCLASS_S 0xfff0707f #define MATCH_FCVT_D_H 0x42200053 #define MASK_FCVT_D_H 0xfff0007f #define MATCH_FCVT_D_L 0xd2200053 #define MASK_FCVT_D_L 0xfff0007f #define MATCH_FCVT_D_LU 0xd2300053 #define MASK_FCVT_D_LU 0xfff0007f #define MATCH_FCVT_D_Q 0x42300053 #define MASK_FCVT_D_Q 0xfff0007f #define MATCH_FCVT_D_S 0x42000053 #define MASK_FCVT_D_S 0xfff0007f #define MATCH_FCVT_D_W 0xd2000053 #define MASK_FCVT_D_W 0xfff0007f #define MATCH_FCVT_D_WU 0xd2100053 #define MASK_FCVT_D_WU 0xfff0007f #define MATCH_FCVT_H_D 0x44100053 #define MASK_FCVT_H_D 0xfff0007f #define MATCH_FCVT_H_L 0xd4200053 #define MASK_FCVT_H_L 0xfff0007f #define MATCH_FCVT_H_LU 0xd4300053 #define MASK_FCVT_H_LU 0xfff0007f #define MATCH_FCVT_H_Q 0x44300053 #define MASK_FCVT_H_Q 0xfff0007f #define MATCH_FCVT_H_S 0x44000053 #define MASK_FCVT_H_S 0xfff0007f #define MATCH_FCVT_H_W 0xd4000053 #define MASK_FCVT_H_W 0xfff0007f #define MATCH_FCVT_H_WU 0xd4100053 #define MASK_FCVT_H_WU 0xfff0007f #define MATCH_FCVT_L_D 0xc2200053 #define MASK_FCVT_L_D 0xfff0007f #define MATCH_FCVT_L_H 0xc4200053 #define MASK_FCVT_L_H 0xfff0007f #define MATCH_FCVT_L_Q 0xc6200053 #define MASK_FCVT_L_Q 0xfff0007f #define MATCH_FCVT_L_S 0xc0200053 #define MASK_FCVT_L_S 0xfff0007f #define MATCH_FCVT_LU_D 0xc2300053 #define MASK_FCVT_LU_D 0xfff0007f #define MATCH_FCVT_LU_H 0xc4300053 #define MASK_FCVT_LU_H 0xfff0007f #define MATCH_FCVT_LU_Q 0xc6300053 #define MASK_FCVT_LU_Q 0xfff0007f #define MATCH_FCVT_LU_S 0xc0300053 #define MASK_FCVT_LU_S 0xfff0007f #define MATCH_FCVT_Q_D 0x46100053 #define MASK_FCVT_Q_D 0xfff0007f #define MATCH_FCVT_Q_H 0x46200053 #define MASK_FCVT_Q_H 0xfff0007f #define MATCH_FCVT_Q_L 0xd6200053 #define MASK_FCVT_Q_L 0xfff0007f #define MATCH_FCVT_Q_LU 0xd6300053 #define MASK_FCVT_Q_LU 0xfff0007f #define MATCH_FCVT_Q_S 0x46000053 #define MASK_FCVT_Q_S 0xfff0007f #define MATCH_FCVT_Q_W 0xd6000053 #define MASK_FCVT_Q_W 0xfff0007f #define MATCH_FCVT_Q_WU 0xd6100053 #define MASK_FCVT_Q_WU 0xfff0007f #define MATCH_FCVT_S_D 0x40100053 #define MASK_FCVT_S_D 0xfff0007f #define MATCH_FCVT_S_H 0x40200053 #define MASK_FCVT_S_H 0xfff0007f #define MATCH_FCVT_S_L 0xd0200053 #define MASK_FCVT_S_L 0xfff0007f #define MATCH_FCVT_S_LU 0xd0300053 #define MASK_FCVT_S_LU 0xfff0007f #define MATCH_FCVT_S_Q 0x40300053 #define MASK_FCVT_S_Q 0xfff0007f #define MATCH_FCVT_S_W 0xd0000053 #define MASK_FCVT_S_W 0xfff0007f #define MATCH_FCVT_S_WU 0xd0100053 #define MASK_FCVT_S_WU 0xfff0007f #define MATCH_FCVT_W_D 0xc2000053 #define MASK_FCVT_W_D 0xfff0007f #define MATCH_FCVT_W_H 0xc4000053 #define MASK_FCVT_W_H 0xfff0007f #define MATCH_FCVT_W_Q 0xc6000053 #define MASK_FCVT_W_Q 0xfff0007f #define MATCH_FCVT_W_S 0xc0000053 #define MASK_FCVT_W_S 0xfff0007f #define MATCH_FCVT_WU_D 0xc2100053 #define MASK_FCVT_WU_D 0xfff0007f #define MATCH_FCVT_WU_H 0xc4100053 #define MASK_FCVT_WU_H 0xfff0007f #define MATCH_FCVT_WU_Q 0xc6100053 #define MASK_FCVT_WU_Q 0xfff0007f #define MATCH_FCVT_WU_S 0xc0100053 #define MASK_FCVT_WU_S 0xfff0007f #define MATCH_FDIV_D 0x1a000053 #define MASK_FDIV_D 0xfe00007f #define MATCH_FDIV_H 0x1c000053 #define MASK_FDIV_H 0xfe00007f #define MATCH_FDIV_Q 0x1e000053 #define MASK_FDIV_Q 0xfe00007f #define MATCH_FDIV_S 0x18000053 #define MASK_FDIV_S 0xfe00007f #define MATCH_FENCE 0xf #define MASK_FENCE 0x707f #define MATCH_FENCE_I 0x100f #define MASK_FENCE_I 0x707f #define MATCH_FEQ_D 0xa2002053 #define MASK_FEQ_D 0xfe00707f #define MATCH_FEQ_H 0xa4002053 #define MASK_FEQ_H 0xfe00707f #define MATCH_FEQ_Q 0xa6002053 #define MASK_FEQ_Q 0xfe00707f #define MATCH_FEQ_S 0xa0002053 #define MASK_FEQ_S 0xfe00707f #define MATCH_FLD 0x3007 #define MASK_FLD 0x707f #define MATCH_FLE_D 0xa2000053 #define MASK_FLE_D 0xfe00707f #define MATCH_FLE_H 0xa4000053 #define MASK_FLE_H 0xfe00707f #define MATCH_FLE_Q 0xa6000053 #define MASK_FLE_Q 0xfe00707f #define MATCH_FLE_S 0xa0000053 #define MASK_FLE_S 0xfe00707f #define MATCH_FLH 0x1007 #define MASK_FLH 0x707f #define MATCH_FLQ 0x4007 #define MASK_FLQ 0x707f #define MATCH_FLT_D 0xa2001053 #define MASK_FLT_D 0xfe00707f #define MATCH_FLT_H 0xa4001053 #define MASK_FLT_H 0xfe00707f #define MATCH_FLT_Q 0xa6001053 #define MASK_FLT_Q 0xfe00707f #define MATCH_FLT_S 0xa0001053 #define MASK_FLT_S 0xfe00707f #define MATCH_FLW 0x2007 #define MASK_FLW 0x707f #define MATCH_FMADD_D 0x2000043 #define MASK_FMADD_D 0x600007f #define MATCH_FMADD_H 0x4000043 #define MASK_FMADD_H 0x600007f #define MATCH_FMADD_Q 0x6000043 #define MASK_FMADD_Q 0x600007f #define MATCH_FMADD_S 0x43 #define MASK_FMADD_S 0x600007f #define MATCH_FMAX_D 0x2a001053 #define MASK_FMAX_D 0xfe00707f #define MATCH_FMAX_H 0x2c001053 #define MASK_FMAX_H 0xfe00707f #define MATCH_FMAX_Q 0x2e001053 #define MASK_FMAX_Q 0xfe00707f #define MATCH_FMAX_S 0x28001053 #define MASK_FMAX_S 0xfe00707f #define MATCH_FMIN_D 0x2a000053 #define MASK_FMIN_D 0xfe00707f #define MATCH_FMIN_H 0x2c000053 #define MASK_FMIN_H 0xfe00707f #define MATCH_FMIN_Q 0x2e000053 #define MASK_FMIN_Q 0xfe00707f #define MATCH_FMIN_S 0x28000053 #define MASK_FMIN_S 0xfe00707f #define MATCH_FMSUB_D 0x2000047 #define MASK_FMSUB_D 0x600007f #define MATCH_FMSUB_H 0x4000047 #define MASK_FMSUB_H 0x600007f #define MATCH_FMSUB_Q 0x6000047 #define MASK_FMSUB_Q 0x600007f #define MATCH_FMSUB_S 0x47 #define MASK_FMSUB_S 0x600007f #define MATCH_FMUL_D 0x12000053 #define MASK_FMUL_D 0xfe00007f #define MATCH_FMUL_H 0x14000053 #define MASK_FMUL_H 0xfe00007f #define MATCH_FMUL_Q 0x16000053 #define MASK_FMUL_Q 0xfe00007f #define MATCH_FMUL_S 0x10000053 #define MASK_FMUL_S 0xfe00007f #define MATCH_FMV_D_X 0xf2000053 #define MASK_FMV_D_X 0xfff0707f #define MATCH_FMV_H_X 0xf4000053 #define MASK_FMV_H_X 0xfff0707f #define MATCH_FMV_W_X 0xf0000053 #define MASK_FMV_W_X 0xfff0707f #define MATCH_FMV_X_D 0xe2000053 #define MASK_FMV_X_D 0xfff0707f #define MATCH_FMV_X_H 0xe4000053 #define MASK_FMV_X_H 0xfff0707f #define MATCH_FMV_X_W 0xe0000053 #define MASK_FMV_X_W 0xfff0707f #define MATCH_FNMADD_D 0x200004f #define MASK_FNMADD_D 0x600007f #define MATCH_FNMADD_H 0x400004f #define MASK_FNMADD_H 0x600007f #define MATCH_FNMADD_Q 0x600004f #define MASK_FNMADD_Q 0x600007f #define MATCH_FNMADD_S 0x4f #define MASK_FNMADD_S 0x600007f #define MATCH_FNMSUB_D 0x200004b #define MASK_FNMSUB_D 0x600007f #define MATCH_FNMSUB_H 0x400004b #define MASK_FNMSUB_H 0x600007f #define MATCH_FNMSUB_Q 0x600004b #define MASK_FNMSUB_Q 0x600007f #define MATCH_FNMSUB_S 0x4b #define MASK_FNMSUB_S 0x600007f #define MATCH_FSD 0x3027 #define MASK_FSD 0x707f #define MATCH_FSGNJ_D 0x22000053 #define MASK_FSGNJ_D 0xfe00707f #define MATCH_FSGNJ_H 0x24000053 #define MASK_FSGNJ_H 0xfe00707f #define MATCH_FSGNJ_Q 0x26000053 #define MASK_FSGNJ_Q 0xfe00707f #define MATCH_FSGNJ_S 0x20000053 #define MASK_FSGNJ_S 0xfe00707f #define MATCH_FSGNJN_D 0x22001053 #define MASK_FSGNJN_D 0xfe00707f #define MATCH_FSGNJN_H 0x24001053 #define MASK_FSGNJN_H 0xfe00707f #define MATCH_FSGNJN_Q 0x26001053 #define MASK_FSGNJN_Q 0xfe00707f #define MATCH_FSGNJN_S 0x20001053 #define MASK_FSGNJN_S 0xfe00707f #define MATCH_FSGNJX_D 0x22002053 #define MASK_FSGNJX_D 0xfe00707f #define MATCH_FSGNJX_H 0x24002053 #define MASK_FSGNJX_H 0xfe00707f #define MATCH_FSGNJX_Q 0x26002053 #define MASK_FSGNJX_Q 0xfe00707f #define MATCH_FSGNJX_S 0x20002053 #define MASK_FSGNJX_S 0xfe00707f #define MATCH_FSH 0x1027 #define MASK_FSH 0x707f #define MATCH_FSL 0x4001033 #define MASK_FSL 0x600707f #define MATCH_FSLW 0x400103b #define MASK_FSLW 0x600707f #define MATCH_FSQ 0x4027 #define MASK_FSQ 0x707f #define MATCH_FSQRT_D 0x5a000053 #define MASK_FSQRT_D 0xfff0007f #define MATCH_FSQRT_H 0x5c000053 #define MASK_FSQRT_H 0xfff0007f #define MATCH_FSQRT_Q 0x5e000053 #define MASK_FSQRT_Q 0xfff0007f #define MATCH_FSQRT_S 0x58000053 #define MASK_FSQRT_S 0xfff0007f #define MATCH_FSR 0x4005033 #define MASK_FSR 0x600707f #define MATCH_FSRI 0x4005013 #define MASK_FSRI 0x400707f #define MATCH_FSRIW 0x400501b #define MASK_FSRIW 0x600707f #define MATCH_FSRW 0x400503b #define MASK_FSRW 0x600707f #define MATCH_FSUB_D 0xa000053 #define MASK_FSUB_D 0xfe00007f #define MATCH_FSUB_H 0xc000053 #define MASK_FSUB_H 0xfe00007f #define MATCH_FSUB_Q 0xe000053 #define MASK_FSUB_Q 0xfe00007f #define MATCH_FSUB_S 0x8000053 #define MASK_FSUB_S 0xfe00007f #define MATCH_FSW 0x2027 #define MASK_FSW 0x707f #define MATCH_GORC 0x28005033 #define MASK_GORC 0xfe00707f #define MATCH_GORCI 0x28005013 #define MASK_GORCI 0xfc00707f #define MATCH_GORCIW 0x2800501b #define MASK_GORCIW 0xfe00707f #define MATCH_GORCW 0x2800503b #define MASK_GORCW 0xfe00707f #define MATCH_GREV 0x68005033 #define MASK_GREV 0xfe00707f #define MATCH_GREVI 0x68005013 #define MASK_GREVI 0xfc00707f #define MATCH_GREVIW 0x6800501b #define MASK_GREVIW 0xfe00707f #define MATCH_GREVW 0x6800503b #define MASK_GREVW 0xfe00707f #define MATCH_HFENCE_GVMA 0x62000073 #define MASK_HFENCE_GVMA 0xfe007fff #define MATCH_HFENCE_VVMA 0x22000073 #define MASK_HFENCE_VVMA 0xfe007fff #define MATCH_HINVAL_GVMA 0x66000073 #define MASK_HINVAL_GVMA 0xfe007fff #define MATCH_HINVAL_VVMA 0x26000073 #define MASK_HINVAL_VVMA 0xfe007fff #define MATCH_HLV_B 0x60004073 #define MASK_HLV_B 0xfff0707f #define MATCH_HLV_BU 0x60104073 #define MASK_HLV_BU 0xfff0707f #define MATCH_HLV_D 0x6c004073 #define MASK_HLV_D 0xfff0707f #define MATCH_HLV_H 0x64004073 #define MASK_HLV_H 0xfff0707f #define MATCH_HLV_HU 0x64104073 #define MASK_HLV_HU 0xfff0707f #define MATCH_HLV_W 0x68004073 #define MASK_HLV_W 0xfff0707f #define MATCH_HLV_WU 0x68104073 #define MASK_HLV_WU 0xfff0707f #define MATCH_HLVX_HU 0x64304073 #define MASK_HLVX_HU 0xfff0707f #define MATCH_HLVX_WU 0x68304073 #define MASK_HLVX_WU 0xfff0707f #define MATCH_HSV_B 0x62004073 #define MASK_HSV_B 0xfe007fff #define MATCH_HSV_D 0x6e004073 #define MASK_HSV_D 0xfe007fff #define MATCH_HSV_H 0x66004073 #define MASK_HSV_H 0xfe007fff #define MATCH_HSV_W 0x6a004073 #define MASK_HSV_W 0xfe007fff #define MATCH_INSB 0xac000077 #define MASK_INSB 0xff80707f #define MATCH_JAL 0x6f #define MASK_JAL 0x7f #define MATCH_JALR 0x67 #define MASK_JALR 0x707f #define MATCH_KABS16 0xad100077 #define MASK_KABS16 0xfff0707f #define MATCH_KABS32 0xad200077 #define MASK_KABS32 0xfff0707f #define MATCH_KABS8 0xad000077 #define MASK_KABS8 0xfff0707f #define MATCH_KABSW 0xad400077 #define MASK_KABSW 0xfff0707f #define MATCH_KADD16 0x10000077 #define MASK_KADD16 0xfe00707f #define MATCH_KADD32 0x10002077 #define MASK_KADD32 0xfe00707f #define MATCH_KADD64 0x90001077 #define MASK_KADD64 0xfe00707f #define MATCH_KADD8 0x18000077 #define MASK_KADD8 0xfe00707f #define MATCH_KADDH 0x4001077 #define MASK_KADDH 0xfe00707f #define MATCH_KADDW 0x1077 #define MASK_KADDW 0xfe00707f #define MATCH_KCRAS16 0x14000077 #define MASK_KCRAS16 0xfe00707f #define MATCH_KCRAS32 0x14002077 #define MASK_KCRAS32 0xfe00707f #define MATCH_KCRSA16 0x16000077 #define MASK_KCRSA16 0xfe00707f #define MATCH_KCRSA32 0x16002077 #define MASK_KCRSA32 0xfe00707f #define MATCH_KDMABB 0xd2001077 #define MASK_KDMABB 0xfe00707f #define MATCH_KDMABB16 0xd8001077 #define MASK_KDMABB16 0xfe00707f #define MATCH_KDMABT 0xe2001077 #define MASK_KDMABT 0xfe00707f #define MATCH_KDMABT16 0xe8001077 #define MASK_KDMABT16 0xfe00707f #define MATCH_KDMATT 0xf2001077 #define MASK_KDMATT 0xfe00707f #define MATCH_KDMATT16 0xf8001077 #define MASK_KDMATT16 0xfe00707f #define MATCH_KDMBB 0xa001077 #define MASK_KDMBB 0xfe00707f #define MATCH_KDMBB16 0xda001077 #define MASK_KDMBB16 0xfe00707f #define MATCH_KDMBT 0x1a001077 #define MASK_KDMBT 0xfe00707f #define MATCH_KDMBT16 0xea001077 #define MASK_KDMBT16 0xfe00707f #define MATCH_KDMTT 0x2a001077 #define MASK_KDMTT 0xfe00707f #define MATCH_KDMTT16 0xfa001077 #define MASK_KDMTT16 0xfe00707f #define MATCH_KHM16 0x86000077 #define MASK_KHM16 0xfe00707f #define MATCH_KHM8 0x8e000077 #define MASK_KHM8 0xfe00707f #define MATCH_KHMBB 0xc001077 #define MASK_KHMBB 0xfe00707f #define MATCH_KHMBB16 0xdc001077 #define MASK_KHMBB16 0xfe00707f #define MATCH_KHMBT 0x1c001077 #define MASK_KHMBT 0xfe00707f #define MATCH_KHMBT16 0xec001077 #define MASK_KHMBT16 0xfe00707f #define MATCH_KHMTT 0x2c001077 #define MASK_KHMTT 0xfe00707f #define MATCH_KHMTT16 0xfc001077 #define MASK_KHMTT16 0xfe00707f #define MATCH_KHMX16 0x96000077 #define MASK_KHMX16 0xfe00707f #define MATCH_KHMX8 0x9e000077 #define MASK_KHMX8 0xfe00707f #define MATCH_KMABB 0x5a001077 #define MASK_KMABB 0xfe00707f #define MATCH_KMABB32 0x5a002077 #define MASK_KMABB32 0xfe00707f #define MATCH_KMABT 0x6a001077 #define MASK_KMABT 0xfe00707f #define MATCH_KMABT32 0x6a002077 #define MASK_KMABT32 0xfe00707f #define MATCH_KMADA 0x48001077 #define MASK_KMADA 0xfe00707f #define MATCH_KMADRS 0x6c001077 #define MASK_KMADRS 0xfe00707f #define MATCH_KMADRS32 0x6c002077 #define MASK_KMADRS32 0xfe00707f #define MATCH_KMADS 0x5c001077 #define MASK_KMADS 0xfe00707f #define MATCH_KMADS32 0x5c002077 #define MASK_KMADS32 0xfe00707f #define MATCH_KMAR64 0x94001077 #define MASK_KMAR64 0xfe00707f #define MATCH_KMATT 0x7a001077 #define MASK_KMATT 0xfe00707f #define MATCH_KMATT32 0x7a002077 #define MASK_KMATT32 0xfe00707f #define MATCH_KMAXDA 0x4a001077 #define MASK_KMAXDA 0xfe00707f #define MATCH_KMAXDA32 0x4a002077 #define MASK_KMAXDA32 0xfe00707f #define MATCH_KMAXDS 0x7c001077 #define MASK_KMAXDS 0xfe00707f #define MATCH_KMAXDS32 0x7c002077 #define MASK_KMAXDS32 0xfe00707f #define MATCH_KMDA 0x38001077 #define MASK_KMDA 0xfe00707f #define MATCH_KMDA32 0x38002077 #define MASK_KMDA32 0xfe00707f #define MATCH_KMMAC 0x60001077 #define MASK_KMMAC 0xfe00707f #define MATCH_KMMAC_U 0x70001077 #define MASK_KMMAC_U 0xfe00707f #define MATCH_KMMAWB 0x46001077 #define MASK_KMMAWB 0xfe00707f #define MATCH_KMMAWB2 0xce001077 #define MASK_KMMAWB2 0xfe00707f #define MATCH_KMMAWB2_U 0xde001077 #define MASK_KMMAWB2_U 0xfe00707f #define MATCH_KMMAWB_U 0x56001077 #define MASK_KMMAWB_U 0xfe00707f #define MATCH_KMMAWT 0x66001077 #define MASK_KMMAWT 0xfe00707f #define MATCH_KMMAWT2 0xee001077 #define MASK_KMMAWT2 0xfe00707f #define MATCH_KMMAWT2_U 0xfe001077 #define MASK_KMMAWT2_U 0xfe00707f #define MATCH_KMMAWT_U 0x76001077 #define MASK_KMMAWT_U 0xfe00707f #define MATCH_KMMSB 0x42001077 #define MASK_KMMSB 0xfe00707f #define MATCH_KMMSB_U 0x52001077 #define MASK_KMMSB_U 0xfe00707f #define MATCH_KMMWB2 0x8e001077 #define MASK_KMMWB2 0xfe00707f #define MATCH_KMMWB2_U 0x9e001077 #define MASK_KMMWB2_U 0xfe00707f #define MATCH_KMMWT2 0xae001077 #define MASK_KMMWT2 0xfe00707f #define MATCH_KMMWT2_U 0xbe001077 #define MASK_KMMWT2_U 0xfe00707f #define MATCH_KMSDA 0x4c001077 #define MASK_KMSDA 0xfe00707f #define MATCH_KMSDA32 0x4c002077 #define MASK_KMSDA32 0xfe00707f #define MATCH_KMSR64 0x96001077 #define MASK_KMSR64 0xfe00707f #define MATCH_KMSXDA 0x4e001077 #define MASK_KMSXDA 0xfe00707f #define MATCH_KMSXDA32 0x4e002077 #define MASK_KMSXDA32 0xfe00707f #define MATCH_KMXDA 0x3a001077 #define MASK_KMXDA 0xfe00707f #define MATCH_KMXDA32 0x3a002077 #define MASK_KMXDA32 0xfe00707f #define MATCH_KSLL16 0x64000077 #define MASK_KSLL16 0xfe00707f #define MATCH_KSLL32 0x64002077 #define MASK_KSLL32 0xfe00707f #define MATCH_KSLL8 0x6c000077 #define MASK_KSLL8 0xfe00707f #define MATCH_KSLLI16 0x75000077 #define MASK_KSLLI16 0xff00707f #define MATCH_KSLLI32 0x84002077 #define MASK_KSLLI32 0xfe00707f #define MATCH_KSLLI8 0x7c800077 #define MASK_KSLLI8 0xff80707f #define MATCH_KSLLIW 0x36001077 #define MASK_KSLLIW 0xfe00707f #define MATCH_KSLLW 0x26001077 #define MASK_KSLLW 0xfe00707f #define MATCH_KSLRA16 0x56000077 #define MASK_KSLRA16 0xfe00707f #define MATCH_KSLRA16_U 0x66000077 #define MASK_KSLRA16_U 0xfe00707f #define MATCH_KSLRA32 0x56002077 #define MASK_KSLRA32 0xfe00707f #define MATCH_KSLRA32_U 0x66002077 #define MASK_KSLRA32_U 0xfe00707f #define MATCH_KSLRA8 0x5e000077 #define MASK_KSLRA8 0xfe00707f #define MATCH_KSLRA8_U 0x6e000077 #define MASK_KSLRA8_U 0xfe00707f #define MATCH_KSLRAW 0x6e001077 #define MASK_KSLRAW 0xfe00707f #define MATCH_KSLRAW_U 0x7e001077 #define MASK_KSLRAW_U 0xfe00707f #define MATCH_KSTAS16 0xc4002077 #define MASK_KSTAS16 0xfe00707f #define MATCH_KSTAS32 0xc0002077 #define MASK_KSTAS32 0xfe00707f #define MATCH_KSTSA16 0xc6002077 #define MASK_KSTSA16 0xfe00707f #define MATCH_KSTSA32 0xc2002077 #define MASK_KSTSA32 0xfe00707f #define MATCH_KSUB16 0x12000077 #define MASK_KSUB16 0xfe00707f #define MATCH_KSUB32 0x12002077 #define MASK_KSUB32 0xfe00707f #define MATCH_KSUB64 0x92001077 #define MASK_KSUB64 0xfe00707f #define MATCH_KSUB8 0x1a000077 #define MASK_KSUB8 0xfe00707f #define MATCH_KSUBH 0x6001077 #define MASK_KSUBH 0xfe00707f #define MATCH_KSUBW 0x2001077 #define MASK_KSUBW 0xfe00707f #define MATCH_KWMMUL 0x62001077 #define MASK_KWMMUL 0xfe00707f #define MATCH_KWMMUL_U 0x72001077 #define MASK_KWMMUL_U 0xfe00707f #define MATCH_LB 0x3 #define MASK_LB 0x707f #define MATCH_LBU 0x4003 #define MASK_LBU 0x707f #define MATCH_LD 0x3003 #define MASK_LD 0x707f #define MATCH_LDU 0x7003 #define MASK_LDU 0x707f #define MATCH_LH 0x1003 #define MASK_LH 0x707f #define MATCH_LHU 0x5003 #define MASK_LHU 0x707f #define MATCH_LQ 0x300f #define MASK_LQ 0x707f #define MATCH_LR_D 0x1000302f #define MASK_LR_D 0xf9f0707f #define MATCH_LR_W 0x1000202f #define MASK_LR_W 0xf9f0707f #define MATCH_LUI 0x37 #define MASK_LUI 0x7f #define MATCH_LW 0x2003 #define MASK_LW 0x707f #define MATCH_LWU 0x6003 #define MASK_LWU 0x707f #define MATCH_MADDR32 0xc4001077 #define MASK_MADDR32 0xfe00707f #define MATCH_MAX 0xa006033 #define MASK_MAX 0xfe00707f #define MATCH_MAXU 0xa007033 #define MASK_MAXU 0xfe00707f #define MATCH_MAXW 0xf2000077 #define MASK_MAXW 0xfe00707f #define MATCH_MIN 0xa004033 #define MASK_MIN 0xfe00707f #define MATCH_MINU 0xa005033 #define MASK_MINU 0xfe00707f #define MATCH_MINW 0xf0000077 #define MASK_MINW 0xfe00707f #define MATCH_MRET 0x30200073 #define MASK_MRET 0xffffffff #define MATCH_MSUBR32 0xc6001077 #define MASK_MSUBR32 0xfe00707f #define MATCH_MUL 0x2000033 #define MASK_MUL 0xfe00707f #define MATCH_MULH 0x2001033 #define MASK_MULH 0xfe00707f #define MATCH_MULHSU 0x2002033 #define MASK_MULHSU 0xfe00707f #define MATCH_MULHU 0x2003033 #define MASK_MULHU 0xfe00707f #define MATCH_MULR64 0xf0001077 #define MASK_MULR64 0xfe00707f #define MATCH_MULSR64 0xe0001077 #define MASK_MULSR64 0xfe00707f #define MATCH_MULW 0x200003b #define MASK_MULW 0xfe00707f #define MATCH_OR 0x6033 #define MASK_OR 0xfe00707f #define MATCH_ORI 0x6013 #define MASK_ORI 0x707f #define MATCH_ORN 0x40006033 #define MASK_ORN 0xfe00707f #define MATCH_PACK 0x8004033 #define MASK_PACK 0xfe00707f #define MATCH_PACKH 0x8007033 #define MASK_PACKH 0xfe00707f #define MATCH_PACKU 0x48004033 #define MASK_PACKU 0xfe00707f #define MATCH_PACKUW 0x4800403b #define MASK_PACKUW 0xfe00707f #define MATCH_PACKW 0x800403b #define MASK_PACKW 0xfe00707f #define MATCH_PAUSE 0x100000f #define MASK_PAUSE 0xffffffff #define MATCH_PBSAD 0xfc000077 #define MASK_PBSAD 0xfe00707f #define MATCH_PBSADA 0xfe000077 #define MASK_PBSADA 0xfe00707f #define MATCH_PKBB16 0xe001077 #define MASK_PKBB16 0xfe00707f #define MATCH_PKBB32 0xe002077 #define MASK_PKBB32 0xfe00707f #define MATCH_PKBT16 0x1e001077 #define MASK_PKBT16 0xfe00707f #define MATCH_PKBT32 0x1e002077 #define MASK_PKBT32 0xfe00707f #define MATCH_PKTB16 0x3e001077 #define MASK_PKTB16 0xfe00707f #define MATCH_PKTB32 0x3e002077 #define MASK_PKTB32 0xfe00707f #define MATCH_PKTT16 0x2e001077 #define MASK_PKTT16 0xfe00707f #define MATCH_PKTT32 0x2e002077 #define MASK_PKTT32 0xfe00707f #define MATCH_PREFETCH_I 0x6013 #define MASK_PREFETCH_I 0x1f07fff #define MATCH_PREFETCH_R 0x106013 #define MASK_PREFETCH_R 0x1f07fff #define MATCH_PREFETCH_W 0x306013 #define MASK_PREFETCH_W 0x1f07fff #define MATCH_RADD16 0x77 #define MASK_RADD16 0xfe00707f #define MATCH_RADD32 0x2077 #define MASK_RADD32 0xfe00707f #define MATCH_RADD64 0x80001077 #define MASK_RADD64 0xfe00707f #define MATCH_RADD8 0x8000077 #define MASK_RADD8 0xfe00707f #define MATCH_RADDW 0x20001077 #define MASK_RADDW 0xfe00707f #define MATCH_RCRAS16 0x4000077 #define MASK_RCRAS16 0xfe00707f #define MATCH_RCRAS32 0x4002077 #define MASK_RCRAS32 0xfe00707f #define MATCH_RCRSA16 0x6000077 #define MASK_RCRSA16 0xfe00707f #define MATCH_RCRSA32 0x6002077 #define MASK_RCRSA32 0xfe00707f #define MATCH_REM 0x2006033 #define MASK_REM 0xfe00707f #define MATCH_REMU 0x2007033 #define MASK_REMU 0xfe00707f #define MATCH_REMUW 0x200703b #define MASK_REMUW 0xfe00707f #define MATCH_REMW 0x200603b #define MASK_REMW 0xfe00707f #define MATCH_ROL 0x60001033 #define MASK_ROL 0xfe00707f #define MATCH_ROLW 0x6000103b #define MASK_ROLW 0xfe00707f #define MATCH_ROR 0x60005033 #define MASK_ROR 0xfe00707f #define MATCH_RORI 0x60005013 #define MASK_RORI 0xfc00707f #define MATCH_RORIW 0x6000501b #define MASK_RORIW 0xfe00707f #define MATCH_RORW 0x6000503b #define MASK_RORW 0xfe00707f #define MATCH_RSTAS16 0xb4002077 #define MASK_RSTAS16 0xfe00707f #define MATCH_RSTAS32 0xb0002077 #define MASK_RSTAS32 0xfe00707f #define MATCH_RSTSA16 0xb6002077 #define MASK_RSTSA16 0xfe00707f #define MATCH_RSTSA32 0xb2002077 #define MASK_RSTSA32 0xfe00707f #define MATCH_RSUB16 0x2000077 #define MASK_RSUB16 0xfe00707f #define MATCH_RSUB32 0x2002077 #define MASK_RSUB32 0xfe00707f #define MATCH_RSUB64 0x82001077 #define MASK_RSUB64 0xfe00707f #define MATCH_RSUB8 0xa000077 #define MASK_RSUB8 0xfe00707f #define MATCH_RSUBW 0x22001077 #define MASK_RSUBW 0xfe00707f #define MATCH_SB 0x23 #define MASK_SB 0x707f #define MATCH_SC_D 0x1800302f #define MASK_SC_D 0xf800707f #define MATCH_SC_W 0x1800202f #define MASK_SC_W 0xf800707f #define MATCH_SCLIP16 0x84000077 #define MASK_SCLIP16 0xff00707f #define MATCH_SCLIP32 0xe4000077 #define MASK_SCLIP32 0xfe00707f #define MATCH_SCLIP8 0x8c000077 #define MASK_SCLIP8 0xff80707f #define MATCH_SCMPLE16 0x1c000077 #define MASK_SCMPLE16 0xfe00707f #define MATCH_SCMPLE8 0x1e000077 #define MASK_SCMPLE8 0xfe00707f #define MATCH_SCMPLT16 0xc000077 #define MASK_SCMPLT16 0xfe00707f #define MATCH_SCMPLT8 0xe000077 #define MASK_SCMPLT8 0xfe00707f #define MATCH_SD 0x3023 #define MASK_SD 0x707f #define MATCH_SEXT_B 0x60401013 #define MASK_SEXT_B 0xfff0707f #define MATCH_SEXT_H 0x60501013 #define MASK_SEXT_H 0xfff0707f #define MATCH_SFENCE_INVAL_IR 0x18100073 #define MASK_SFENCE_INVAL_IR 0xffffffff #define MATCH_SFENCE_VMA 0x12000073 #define MASK_SFENCE_VMA 0xfe007fff #define MATCH_SFENCE_W_INVAL 0x18000073 #define MASK_SFENCE_W_INVAL 0xffffffff #define MATCH_SH 0x1023 #define MASK_SH 0x707f #define MATCH_SH1ADD 0x20002033 #define MASK_SH1ADD 0xfe00707f #define MATCH_SH1ADD_UW 0x2000203b #define MASK_SH1ADD_UW 0xfe00707f #define MATCH_SH2ADD 0x20004033 #define MASK_SH2ADD 0xfe00707f #define MATCH_SH2ADD_UW 0x2000403b #define MASK_SH2ADD_UW 0xfe00707f #define MATCH_SH3ADD 0x20006033 #define MASK_SH3ADD 0xfe00707f #define MATCH_SH3ADD_UW 0x2000603b #define MASK_SH3ADD_UW 0xfe00707f #define MATCH_SHA256SIG0 0x10201013 #define MASK_SHA256SIG0 0xfff0707f #define MATCH_SHA256SIG1 0x10301013 #define MASK_SHA256SIG1 0xfff0707f #define MATCH_SHA256SUM0 0x10001013 #define MASK_SHA256SUM0 0xfff0707f #define MATCH_SHA256SUM1 0x10101013 #define MASK_SHA256SUM1 0xfff0707f #define MATCH_SHA512SIG0 0x10601013 #define MASK_SHA512SIG0 0xfff0707f #define MATCH_SHA512SIG0H 0x5c000033 #define MASK_SHA512SIG0H 0xfe00707f #define MATCH_SHA512SIG0L 0x54000033 #define MASK_SHA512SIG0L 0xfe00707f #define MATCH_SHA512SIG1 0x10701013 #define MASK_SHA512SIG1 0xfff0707f #define MATCH_SHA512SIG1H 0x5e000033 #define MASK_SHA512SIG1H 0xfe00707f #define MATCH_SHA512SIG1L 0x56000033 #define MASK_SHA512SIG1L 0xfe00707f #define MATCH_SHA512SUM0 0x10401013 #define MASK_SHA512SUM0 0xfff0707f #define MATCH_SHA512SUM0R 0x50000033 #define MASK_SHA512SUM0R 0xfe00707f #define MATCH_SHA512SUM1 0x10501013 #define MASK_SHA512SUM1 0xfff0707f #define MATCH_SHA512SUM1R 0x52000033 #define MASK_SHA512SUM1R 0xfe00707f #define MATCH_SHFL 0x8001033 #define MASK_SHFL 0xfe00707f #define MATCH_SHFLI 0x8001013 #define MASK_SHFLI 0xfe00707f #define MATCH_SHFLW 0x800103b #define MASK_SHFLW 0xfe00707f #define MATCH_SINVAL_VMA 0x16000073 #define MASK_SINVAL_VMA 0xfe007fff #define MATCH_SLL 0x1033 #define MASK_SLL 0xfe00707f #define MATCH_SLL16 0x54000077 #define MASK_SLL16 0xfe00707f #define MATCH_SLL32 0x54002077 #define MASK_SLL32 0xfe00707f #define MATCH_SLL8 0x5c000077 #define MASK_SLL8 0xfe00707f #define MATCH_SLLD 0x107b #define MASK_SLLD 0xfe00707f #define MATCH_SLLI 0x1013 #define MASK_SLLI 0xf800707f #define MATCH_SLLI16 0x74000077 #define MASK_SLLI16 0xff00707f #define MATCH_SLLI32 0x74002077 #define MASK_SLLI32 0xfe00707f #define MATCH_SLLI8 0x7c000077 #define MASK_SLLI8 0xff80707f #define MATCH_SLLI_UW 0x800101b #define MASK_SLLI_UW 0xfc00707f #define MATCH_SLLID 0x105b #define MASK_SLLID 0xfc00707f #define MATCH_SLLIW 0x101b #define MASK_SLLIW 0xfe00707f #define MATCH_SLLW 0x103b #define MASK_SLLW 0xfe00707f #define MATCH_SLO 0x20001033 #define MASK_SLO 0xfe00707f #define MATCH_SLOI 0x20001013 #define MASK_SLOI 0xfc00707f #define MATCH_SLOIW 0x2000101b #define MASK_SLOIW 0xfe00707f #define MATCH_SLOW 0x2000103b #define MASK_SLOW 0xfe00707f #define MATCH_SLT 0x2033 #define MASK_SLT 0xfe00707f #define MATCH_SLTI 0x2013 #define MASK_SLTI 0x707f #define MATCH_SLTIU 0x3013 #define MASK_SLTIU 0x707f #define MATCH_SLTU 0x3033 #define MASK_SLTU 0xfe00707f #define MATCH_SM3P0 0x10801013 #define MASK_SM3P0 0xfff0707f #define MATCH_SM3P1 0x10901013 #define MASK_SM3P1 0xfff0707f #define MATCH_SM4ED 0x30000033 #define MASK_SM4ED 0x3e00707f #define MATCH_SM4KS 0x34000033 #define MASK_SM4KS 0x3e00707f #define MATCH_SMAL 0x5e001077 #define MASK_SMAL 0xfe00707f #define MATCH_SMALBB 0x88001077 #define MASK_SMALBB 0xfe00707f #define MATCH_SMALBT 0x98001077 #define MASK_SMALBT 0xfe00707f #define MATCH_SMALDA 0x8c001077 #define MASK_SMALDA 0xfe00707f #define MATCH_SMALDRS 0x9a001077 #define MASK_SMALDRS 0xfe00707f #define MATCH_SMALDS 0x8a001077 #define MASK_SMALDS 0xfe00707f #define MATCH_SMALTT 0xa8001077 #define MASK_SMALTT 0xfe00707f #define MATCH_SMALXDA 0x9c001077 #define MASK_SMALXDA 0xfe00707f #define MATCH_SMALXDS 0xaa001077 #define MASK_SMALXDS 0xfe00707f #define MATCH_SMAQA 0xc8000077 #define MASK_SMAQA 0xfe00707f #define MATCH_SMAQA_SU 0xca000077 #define MASK_SMAQA_SU 0xfe00707f #define MATCH_SMAR64 0x84001077 #define MASK_SMAR64 0xfe00707f #define MATCH_SMAX16 0x82000077 #define MASK_SMAX16 0xfe00707f #define MATCH_SMAX32 0x92002077 #define MASK_SMAX32 0xfe00707f #define MATCH_SMAX8 0x8a000077 #define MASK_SMAX8 0xfe00707f #define MATCH_SMBB16 0x8001077 #define MASK_SMBB16 0xfe00707f #define MATCH_SMBT16 0x18001077 #define MASK_SMBT16 0xfe00707f #define MATCH_SMBT32 0x18002077 #define MASK_SMBT32 0xfe00707f #define MATCH_SMDRS 0x68001077 #define MASK_SMDRS 0xfe00707f #define MATCH_SMDRS32 0x68002077 #define MASK_SMDRS32 0xfe00707f #define MATCH_SMDS 0x58001077 #define MASK_SMDS 0xfe00707f #define MATCH_SMDS32 0x58002077 #define MASK_SMDS32 0xfe00707f #define MATCH_SMIN16 0x80000077 #define MASK_SMIN16 0xfe00707f #define MATCH_SMIN32 0x90002077 #define MASK_SMIN32 0xfe00707f #define MATCH_SMIN8 0x88000077 #define MASK_SMIN8 0xfe00707f #define MATCH_SMMUL 0x40001077 #define MASK_SMMUL 0xfe00707f #define MATCH_SMMUL_U 0x50001077 #define MASK_SMMUL_U 0xfe00707f #define MATCH_SMMWB 0x44001077 #define MASK_SMMWB 0xfe00707f #define MATCH_SMMWB_U 0x54001077 #define MASK_SMMWB_U 0xfe00707f #define MATCH_SMMWT 0x64001077 #define MASK_SMMWT 0xfe00707f #define MATCH_SMMWT_U 0x74001077 #define MASK_SMMWT_U 0xfe00707f #define MATCH_SMSLDA 0xac001077 #define MASK_SMSLDA 0xfe00707f #define MATCH_SMSLXDA 0xbc001077 #define MASK_SMSLXDA 0xfe00707f #define MATCH_SMSR64 0x86001077 #define MASK_SMSR64 0xfe00707f #define MATCH_SMTT16 0x28001077 #define MASK_SMTT16 0xfe00707f #define MATCH_SMTT32 0x28002077 #define MASK_SMTT32 0xfe00707f #define MATCH_SMUL16 0xa0000077 #define MASK_SMUL16 0xfe00707f #define MATCH_SMUL8 0xa8000077 #define MASK_SMUL8 0xfe00707f #define MATCH_SMULX16 0xa2000077 #define MASK_SMULX16 0xfe00707f #define MATCH_SMULX8 0xaa000077 #define MASK_SMULX8 0xfe00707f #define MATCH_SMXDS 0x78001077 #define MASK_SMXDS 0xfe00707f #define MATCH_SMXDS32 0x78002077 #define MASK_SMXDS32 0xfe00707f #define MATCH_SQ 0x4023 #define MASK_SQ 0x707f #define MATCH_SRA 0x40005033 #define MASK_SRA 0xfe00707f #define MATCH_SRA16 0x50000077 #define MASK_SRA16 0xfe00707f #define MATCH_SRA16_U 0x60000077 #define MASK_SRA16_U 0xfe00707f #define MATCH_SRA32 0x50002077 #define MASK_SRA32 0xfe00707f #define MATCH_SRA32_U 0x60002077 #define MASK_SRA32_U 0xfe00707f #define MATCH_SRA8 0x58000077 #define MASK_SRA8 0xfe00707f #define MATCH_SRA8_U 0x68000077 #define MASK_SRA8_U 0xfe00707f #define MATCH_SRA_U 0x24001077 #define MASK_SRA_U 0xfe00707f #define MATCH_SRAD 0x4000507b #define MASK_SRAD 0xfe00707f #define MATCH_SRAI 0x40005013 #define MASK_SRAI 0xf800707f #define MATCH_SRAI16 0x70000077 #define MASK_SRAI16 0xff00707f #define MATCH_SRAI16_U 0x71000077 #define MASK_SRAI16_U 0xff00707f #define MATCH_SRAI32 0x70002077 #define MASK_SRAI32 0xfe00707f #define MATCH_SRAI32_U 0x80002077 #define MASK_SRAI32_U 0xfe00707f #define MATCH_SRAI8 0x78000077 #define MASK_SRAI8 0xff80707f #define MATCH_SRAI8_U 0x78800077 #define MASK_SRAI8_U 0xff80707f #define MATCH_SRAI_U 0xd4001077 #define MASK_SRAI_U 0xfc00707f #define MATCH_SRAID 0x4000505b #define MASK_SRAID 0xfc00707f #define MATCH_SRAIW 0x4000501b #define MASK_SRAIW 0xfe00707f #define MATCH_SRAIW_U 0x34001077 #define MASK_SRAIW_U 0xfe00707f #define MATCH_SRAW 0x4000503b #define MASK_SRAW 0xfe00707f #define MATCH_SRET 0x10200073 #define MASK_SRET 0xffffffff #define MATCH_SRL 0x5033 #define MASK_SRL 0xfe00707f #define MATCH_SRL16 0x52000077 #define MASK_SRL16 0xfe00707f #define MATCH_SRL16_U 0x62000077 #define MASK_SRL16_U 0xfe00707f #define MATCH_SRL32 0x52002077 #define MASK_SRL32 0xfe00707f #define MATCH_SRL32_U 0x62002077 #define MASK_SRL32_U 0xfe00707f #define MATCH_SRL8 0x5a000077 #define MASK_SRL8 0xfe00707f #define MATCH_SRL8_U 0x6a000077 #define MASK_SRL8_U 0xfe00707f #define MATCH_SRLD 0x507b #define MASK_SRLD 0xfe00707f #define MATCH_SRLI 0x5013 #define MASK_SRLI 0xf800707f #define MATCH_SRLI16 0x72000077 #define MASK_SRLI16 0xff00707f #define MATCH_SRLI16_U 0x73000077 #define MASK_SRLI16_U 0xff00707f #define MATCH_SRLI32 0x72002077 #define MASK_SRLI32 0xfe00707f #define MATCH_SRLI32_U 0x82002077 #define MASK_SRLI32_U 0xfe00707f #define MATCH_SRLI8 0x7a000077 #define MASK_SRLI8 0xff80707f #define MATCH_SRLI8_U 0x7a800077 #define MASK_SRLI8_U 0xff80707f #define MATCH_SRLID 0x505b #define MASK_SRLID 0xfc00707f #define MATCH_SRLIW 0x501b #define MASK_SRLIW 0xfe00707f #define MATCH_SRLW 0x503b #define MASK_SRLW 0xfe00707f #define MATCH_SRO 0x20005033 #define MASK_SRO 0xfe00707f #define MATCH_SROI 0x20005013 #define MASK_SROI 0xfc00707f #define MATCH_SROIW 0x2000501b #define MASK_SROIW 0xfe00707f #define MATCH_SROW 0x2000503b #define MASK_SROW 0xfe00707f #define MATCH_STAS16 0xf4002077 #define MASK_STAS16 0xfe00707f #define MATCH_STAS32 0xf0002077 #define MASK_STAS32 0xfe00707f #define MATCH_STSA16 0xf6002077 #define MASK_STSA16 0xfe00707f #define MATCH_STSA32 0xf2002077 #define MASK_STSA32 0xfe00707f #define MATCH_SUB 0x40000033 #define MASK_SUB 0xfe00707f #define MATCH_SUB16 0x42000077 #define MASK_SUB16 0xfe00707f #define MATCH_SUB32 0x42002077 #define MASK_SUB32 0xfe00707f #define MATCH_SUB64 0xc2001077 #define MASK_SUB64 0xfe00707f #define MATCH_SUB8 0x4a000077 #define MASK_SUB8 0xfe00707f #define MATCH_SUBD 0x4000007b #define MASK_SUBD 0xfe00707f #define MATCH_SUBW 0x4000003b #define MASK_SUBW 0xfe00707f #define MATCH_SUNPKD810 0xac800077 #define MASK_SUNPKD810 0xfff0707f #define MATCH_SUNPKD820 0xac900077 #define MASK_SUNPKD820 0xfff0707f #define MATCH_SUNPKD830 0xaca00077 #define MASK_SUNPKD830 0xfff0707f #define MATCH_SUNPKD831 0xacb00077 #define MASK_SUNPKD831 0xfff0707f #define MATCH_SUNPKD832 0xad300077 #define MASK_SUNPKD832 0xfff0707f #define MATCH_SW 0x2023 #define MASK_SW 0x707f #define MATCH_SWAP8 0xad800077 #define MASK_SWAP8 0xfff0707f #define MATCH_UCLIP16 0x85000077 #define MASK_UCLIP16 0xff00707f #define MATCH_UCLIP32 0xf4000077 #define MASK_UCLIP32 0xfe00707f #define MATCH_UCLIP8 0x8d000077 #define MASK_UCLIP8 0xff80707f #define MATCH_UCMPLE16 0x3c000077 #define MASK_UCMPLE16 0xfe00707f #define MATCH_UCMPLE8 0x3e000077 #define MASK_UCMPLE8 0xfe00707f #define MATCH_UCMPLT16 0x2c000077 #define MASK_UCMPLT16 0xfe00707f #define MATCH_UCMPLT8 0x2e000077 #define MASK_UCMPLT8 0xfe00707f #define MATCH_UKADD16 0x30000077 #define MASK_UKADD16 0xfe00707f #define MATCH_UKADD32 0x30002077 #define MASK_UKADD32 0xfe00707f #define MATCH_UKADD64 0xb0001077 #define MASK_UKADD64 0xfe00707f #define MATCH_UKADD8 0x38000077 #define MASK_UKADD8 0xfe00707f #define MATCH_UKADDH 0x14001077 #define MASK_UKADDH 0xfe00707f #define MATCH_UKADDW 0x10001077 #define MASK_UKADDW 0xfe00707f #define MATCH_UKCRAS16 0x34000077 #define MASK_UKCRAS16 0xfe00707f #define MATCH_UKCRAS32 0x34002077 #define MASK_UKCRAS32 0xfe00707f #define MATCH_UKCRSA16 0x36000077 #define MASK_UKCRSA16 0xfe00707f #define MATCH_UKCRSA32 0x36002077 #define MASK_UKCRSA32 0xfe00707f #define MATCH_UKMAR64 0xb4001077 #define MASK_UKMAR64 0xfe00707f #define MATCH_UKMSR64 0xb6001077 #define MASK_UKMSR64 0xfe00707f #define MATCH_UKSTAS16 0xe4002077 #define MASK_UKSTAS16 0xfe00707f #define MATCH_UKSTAS32 0xe0002077 #define MASK_UKSTAS32 0xfe00707f #define MATCH_UKSTSA16 0xe6002077 #define MASK_UKSTSA16 0xfe00707f #define MATCH_UKSTSA32 0xe2002077 #define MASK_UKSTSA32 0xfe00707f #define MATCH_UKSUB16 0x32000077 #define MASK_UKSUB16 0xfe00707f #define MATCH_UKSUB32 0x32002077 #define MASK_UKSUB32 0xfe00707f #define MATCH_UKSUB64 0xb2001077 #define MASK_UKSUB64 0xfe00707f #define MATCH_UKSUB8 0x3a000077 #define MASK_UKSUB8 0xfe00707f #define MATCH_UKSUBH 0x16001077 #define MASK_UKSUBH 0xfe00707f #define MATCH_UKSUBW 0x12001077 #define MASK_UKSUBW 0xfe00707f #define MATCH_UMAQA 0xcc000077 #define MASK_UMAQA 0xfe00707f #define MATCH_UMAR64 0xa4001077 #define MASK_UMAR64 0xfe00707f #define MATCH_UMAX16 0x92000077 #define MASK_UMAX16 0xfe00707f #define MATCH_UMAX32 0xa2002077 #define MASK_UMAX32 0xfe00707f #define MATCH_UMAX8 0x9a000077 #define MASK_UMAX8 0xfe00707f #define MATCH_UMIN16 0x90000077 #define MASK_UMIN16 0xfe00707f #define MATCH_UMIN32 0xa0002077 #define MASK_UMIN32 0xfe00707f #define MATCH_UMIN8 0x98000077 #define MASK_UMIN8 0xfe00707f #define MATCH_UMSR64 0xa6001077 #define MASK_UMSR64 0xfe00707f #define MATCH_UMUL16 0xb0000077 #define MASK_UMUL16 0xfe00707f #define MATCH_UMUL8 0xb8000077 #define MASK_UMUL8 0xfe00707f #define MATCH_UMULX16 0xb2000077 #define MASK_UMULX16 0xfe00707f #define MATCH_UMULX8 0xba000077 #define MASK_UMULX8 0xfe00707f #define MATCH_UNSHFL 0x8005033 #define MASK_UNSHFL 0xfe00707f #define MATCH_UNSHFLI 0x8005013 #define MASK_UNSHFLI 0xfe00707f #define MATCH_UNSHFLW 0x800503b #define MASK_UNSHFLW 0xfe00707f #define MATCH_URADD16 0x20000077 #define MASK_URADD16 0xfe00707f #define MATCH_URADD32 0x20002077 #define MASK_URADD32 0xfe00707f #define MATCH_URADD64 0xa0001077 #define MASK_URADD64 0xfe00707f #define MATCH_URADD8 0x28000077 #define MASK_URADD8 0xfe00707f #define MATCH_URADDW 0x30001077 #define MASK_URADDW 0xfe00707f #define MATCH_URCRAS16 0x24000077 #define MASK_URCRAS16 0xfe00707f #define MATCH_URCRAS32 0x24002077 #define MASK_URCRAS32 0xfe00707f #define MATCH_URCRSA16 0x26000077 #define MASK_URCRSA16 0xfe00707f #define MATCH_URCRSA32 0x26002077 #define MASK_URCRSA32 0xfe00707f #define MATCH_URSTAS16 0xd4002077 #define MASK_URSTAS16 0xfe00707f #define MATCH_URSTAS32 0xd0002077 #define MASK_URSTAS32 0xfe00707f #define MATCH_URSTSA16 0xd6002077 #define MASK_URSTSA16 0xfe00707f #define MATCH_URSTSA32 0xd2002077 #define MASK_URSTSA32 0xfe00707f #define MATCH_URSUB16 0x22000077 #define MASK_URSUB16 0xfe00707f #define MATCH_URSUB32 0x22002077 #define MASK_URSUB32 0xfe00707f #define MATCH_URSUB64 0xa2001077 #define MASK_URSUB64 0xfe00707f #define MATCH_URSUB8 0x2a000077 #define MASK_URSUB8 0xfe00707f #define MATCH_URSUBW 0x32001077 #define MASK_URSUBW 0xfe00707f #define MATCH_VAADD_VV 0x24002057 #define MASK_VAADD_VV 0xfc00707f #define MATCH_VAADD_VX 0x24006057 #define MASK_VAADD_VX 0xfc00707f #define MATCH_VAADDU_VV 0x20002057 #define MASK_VAADDU_VV 0xfc00707f #define MATCH_VAADDU_VX 0x20006057 #define MASK_VAADDU_VX 0xfc00707f #define MATCH_VADC_VIM 0x40003057 #define MASK_VADC_VIM 0xfe00707f #define MATCH_VADC_VVM 0x40000057 #define MASK_VADC_VVM 0xfe00707f #define MATCH_VADC_VXM 0x40004057 #define MASK_VADC_VXM 0xfe00707f #define MATCH_VADD_VI 0x3057 #define MASK_VADD_VI 0xfc00707f #define MATCH_VADD_VV 0x57 #define MASK_VADD_VV 0xfc00707f #define MATCH_VADD_VX 0x4057 #define MASK_VADD_VX 0xfc00707f #define MATCH_VAMOADDEI16_V 0x502f #define MASK_VAMOADDEI16_V 0xf800707f #define MATCH_VAMOADDEI32_V 0x602f #define MASK_VAMOADDEI32_V 0xf800707f #define MATCH_VAMOADDEI64_V 0x702f #define MASK_VAMOADDEI64_V 0xf800707f #define MATCH_VAMOADDEI8_V 0x2f #define MASK_VAMOADDEI8_V 0xf800707f #define MATCH_VAMOANDEI16_V 0x6000502f #define MASK_VAMOANDEI16_V 0xf800707f #define MATCH_VAMOANDEI32_V 0x6000602f #define MASK_VAMOANDEI32_V 0xf800707f #define MATCH_VAMOANDEI64_V 0x6000702f #define MASK_VAMOANDEI64_V 0xf800707f #define MATCH_VAMOANDEI8_V 0x6000002f #define MASK_VAMOANDEI8_V 0xf800707f #define MATCH_VAMOMAXEI16_V 0xa000502f #define MASK_VAMOMAXEI16_V 0xf800707f #define MATCH_VAMOMAXEI32_V 0xa000602f #define MASK_VAMOMAXEI32_V 0xf800707f #define MATCH_VAMOMAXEI64_V 0xa000702f #define MASK_VAMOMAXEI64_V 0xf800707f #define MATCH_VAMOMAXEI8_V 0xa000002f #define MASK_VAMOMAXEI8_V 0xf800707f #define MATCH_VAMOMAXUEI16_V 0xe000502f #define MASK_VAMOMAXUEI16_V 0xf800707f #define MATCH_VAMOMAXUEI32_V 0xe000602f #define MASK_VAMOMAXUEI32_V 0xf800707f #define MATCH_VAMOMAXUEI64_V 0xe000702f #define MASK_VAMOMAXUEI64_V 0xf800707f #define MATCH_VAMOMAXUEI8_V 0xe000002f #define MASK_VAMOMAXUEI8_V 0xf800707f #define MATCH_VAMOMINEI16_V 0x8000502f #define MASK_VAMOMINEI16_V 0xf800707f #define MATCH_VAMOMINEI32_V 0x8000602f #define MASK_VAMOMINEI32_V 0xf800707f #define MATCH_VAMOMINEI64_V 0x8000702f #define MASK_VAMOMINEI64_V 0xf800707f #define MATCH_VAMOMINEI8_V 0x8000002f #define MASK_VAMOMINEI8_V 0xf800707f #define MATCH_VAMOMINUEI16_V 0xc000502f #define MASK_VAMOMINUEI16_V 0xf800707f #define MATCH_VAMOMINUEI32_V 0xc000602f #define MASK_VAMOMINUEI32_V 0xf800707f #define MATCH_VAMOMINUEI64_V 0xc000702f #define MASK_VAMOMINUEI64_V 0xf800707f #define MATCH_VAMOMINUEI8_V 0xc000002f #define MASK_VAMOMINUEI8_V 0xf800707f #define MATCH_VAMOOREI16_V 0x4000502f #define MASK_VAMOOREI16_V 0xf800707f #define MATCH_VAMOOREI32_V 0x4000602f #define MASK_VAMOOREI32_V 0xf800707f #define MATCH_VAMOOREI64_V 0x4000702f #define MASK_VAMOOREI64_V 0xf800707f #define MATCH_VAMOOREI8_V 0x4000002f #define MASK_VAMOOREI8_V 0xf800707f #define MATCH_VAMOSWAPEI16_V 0x800502f #define MASK_VAMOSWAPEI16_V 0xf800707f #define MATCH_VAMOSWAPEI32_V 0x800602f #define MASK_VAMOSWAPEI32_V 0xf800707f #define MATCH_VAMOSWAPEI64_V 0x800702f #define MASK_VAMOSWAPEI64_V 0xf800707f #define MATCH_VAMOSWAPEI8_V 0x800002f #define MASK_VAMOSWAPEI8_V 0xf800707f #define MATCH_VAMOXOREI16_V 0x2000502f #define MASK_VAMOXOREI16_V 0xf800707f #define MATCH_VAMOXOREI32_V 0x2000602f #define MASK_VAMOXOREI32_V 0xf800707f #define MATCH_VAMOXOREI64_V 0x2000702f #define MASK_VAMOXOREI64_V 0xf800707f #define MATCH_VAMOXOREI8_V 0x2000002f #define MASK_VAMOXOREI8_V 0xf800707f #define MATCH_VAND_VI 0x24003057 #define MASK_VAND_VI 0xfc00707f #define MATCH_VAND_VV 0x24000057 #define MASK_VAND_VV 0xfc00707f #define MATCH_VAND_VX 0x24004057 #define MASK_VAND_VX 0xfc00707f #define MATCH_VASUB_VV 0x2c002057 #define MASK_VASUB_VV 0xfc00707f #define MATCH_VASUB_VX 0x2c006057 #define MASK_VASUB_VX 0xfc00707f #define MATCH_VASUBU_VV 0x28002057 #define MASK_VASUBU_VV 0xfc00707f #define MATCH_VASUBU_VX 0x28006057 #define MASK_VASUBU_VX 0xfc00707f #define MATCH_VCOMPRESS_VM 0x5e002057 #define MASK_VCOMPRESS_VM 0xfe00707f #define MATCH_VCPOP_M 0x40082057 #define MASK_VCPOP_M 0xfc0ff07f #define MATCH_VDIV_VV 0x84002057 #define MASK_VDIV_VV 0xfc00707f #define MATCH_VDIV_VX 0x84006057 #define MASK_VDIV_VX 0xfc00707f #define MATCH_VDIVU_VV 0x80002057 #define MASK_VDIVU_VV 0xfc00707f #define MATCH_VDIVU_VX 0x80006057 #define MASK_VDIVU_VX 0xfc00707f #define MATCH_VFADD_VF 0x5057 #define MASK_VFADD_VF 0xfc00707f #define MATCH_VFADD_VV 0x1057 #define MASK_VFADD_VV 0xfc00707f #define MATCH_VFCLASS_V 0x4c081057 #define MASK_VFCLASS_V 0xfc0ff07f #define MATCH_VFCVT_F_X_V 0x48019057 #define MASK_VFCVT_F_X_V 0xfc0ff07f #define MATCH_VFCVT_F_XU_V 0x48011057 #define MASK_VFCVT_F_XU_V 0xfc0ff07f #define MATCH_VFCVT_RTZ_X_F_V 0x48039057 #define MASK_VFCVT_RTZ_X_F_V 0xfc0ff07f #define MATCH_VFCVT_RTZ_XU_F_V 0x48031057 #define MASK_VFCVT_RTZ_XU_F_V 0xfc0ff07f #define MATCH_VFCVT_X_F_V 0x48009057 #define MASK_VFCVT_X_F_V 0xfc0ff07f #define MATCH_VFCVT_XU_F_V 0x48001057 #define MASK_VFCVT_XU_F_V 0xfc0ff07f #define MATCH_VFDIV_VF 0x80005057 #define MASK_VFDIV_VF 0xfc00707f #define MATCH_VFDIV_VV 0x80001057 #define MASK_VFDIV_VV 0xfc00707f #define MATCH_VFIRST_M 0x4008a057 #define MASK_VFIRST_M 0xfc0ff07f #define MATCH_VFMACC_VF 0xb0005057 #define MASK_VFMACC_VF 0xfc00707f #define MATCH_VFMACC_VV 0xb0001057 #define MASK_VFMACC_VV 0xfc00707f #define MATCH_VFMADD_VF 0xa0005057 #define MASK_VFMADD_VF 0xfc00707f #define MATCH_VFMADD_VV 0xa0001057 #define MASK_VFMADD_VV 0xfc00707f #define MATCH_VFMAX_VF 0x18005057 #define MASK_VFMAX_VF 0xfc00707f #define MATCH_VFMAX_VV 0x18001057 #define MASK_VFMAX_VV 0xfc00707f #define MATCH_VFMERGE_VFM 0x5c005057 #define MASK_VFMERGE_VFM 0xfe00707f #define MATCH_VFMIN_VF 0x10005057 #define MASK_VFMIN_VF 0xfc00707f #define MATCH_VFMIN_VV 0x10001057 #define MASK_VFMIN_VV 0xfc00707f #define MATCH_VFMSAC_VF 0xb8005057 #define MASK_VFMSAC_VF 0xfc00707f #define MATCH_VFMSAC_VV 0xb8001057 #define MASK_VFMSAC_VV 0xfc00707f #define MATCH_VFMSUB_VF 0xa8005057 #define MASK_VFMSUB_VF 0xfc00707f #define MATCH_VFMSUB_VV 0xa8001057 #define MASK_VFMSUB_VV 0xfc00707f #define MATCH_VFMUL_VF 0x90005057 #define MASK_VFMUL_VF 0xfc00707f #define MATCH_VFMUL_VV 0x90001057 #define MASK_VFMUL_VV 0xfc00707f #define MATCH_VFMV_F_S 0x42001057 #define MASK_VFMV_F_S 0xfe0ff07f #define MATCH_VFMV_S_F 0x42005057 #define MASK_VFMV_S_F 0xfff0707f #define MATCH_VFMV_V_F 0x5e005057 #define MASK_VFMV_V_F 0xfff0707f #define MATCH_VFNCVT_F_F_W 0x480a1057 #define MASK_VFNCVT_F_F_W 0xfc0ff07f #define MATCH_VFNCVT_F_X_W 0x48099057 #define MASK_VFNCVT_F_X_W 0xfc0ff07f #define MATCH_VFNCVT_F_XU_W 0x48091057 #define MASK_VFNCVT_F_XU_W 0xfc0ff07f #define MATCH_VFNCVT_ROD_F_F_W 0x480a9057 #define MASK_VFNCVT_ROD_F_F_W 0xfc0ff07f #define MATCH_VFNCVT_RTZ_X_F_W 0x480b9057 #define MASK_VFNCVT_RTZ_X_F_W 0xfc0ff07f #define MATCH_VFNCVT_RTZ_XU_F_W 0x480b1057 #define MASK_VFNCVT_RTZ_XU_F_W 0xfc0ff07f #define MATCH_VFNCVT_X_F_W 0x48089057 #define MASK_VFNCVT_X_F_W 0xfc0ff07f #define MATCH_VFNCVT_XU_F_W 0x48081057 #define MASK_VFNCVT_XU_F_W 0xfc0ff07f #define MATCH_VFNMACC_VF 0xb4005057 #define MASK_VFNMACC_VF 0xfc00707f #define MATCH_VFNMACC_VV 0xb4001057 #define MASK_VFNMACC_VV 0xfc00707f #define MATCH_VFNMADD_VF 0xa4005057 #define MASK_VFNMADD_VF 0xfc00707f #define MATCH_VFNMADD_VV 0xa4001057 #define MASK_VFNMADD_VV 0xfc00707f #define MATCH_VFNMSAC_VF 0xbc005057 #define MASK_VFNMSAC_VF 0xfc00707f #define MATCH_VFNMSAC_VV 0xbc001057 #define MASK_VFNMSAC_VV 0xfc00707f #define MATCH_VFNMSUB_VF 0xac005057 #define MASK_VFNMSUB_VF 0xfc00707f #define MATCH_VFNMSUB_VV 0xac001057 #define MASK_VFNMSUB_VV 0xfc00707f #define MATCH_VFRDIV_VF 0x84005057 #define MASK_VFRDIV_VF 0xfc00707f #define MATCH_VFREC7_V 0x4c029057 #define MASK_VFREC7_V 0xfc0ff07f #define MATCH_VFREDMAX_VS 0x1c001057 #define MASK_VFREDMAX_VS 0xfc00707f #define MATCH_VFREDMIN_VS 0x14001057 #define MASK_VFREDMIN_VS 0xfc00707f #define MATCH_VFREDOSUM_VS 0xc001057 #define MASK_VFREDOSUM_VS 0xfc00707f #define MATCH_VFREDUSUM_VS 0x4001057 #define MASK_VFREDUSUM_VS 0xfc00707f #define MATCH_VFRSQRT7_V 0x4c021057 #define MASK_VFRSQRT7_V 0xfc0ff07f #define MATCH_VFRSUB_VF 0x9c005057 #define MASK_VFRSUB_VF 0xfc00707f #define MATCH_VFSGNJ_VF 0x20005057 #define MASK_VFSGNJ_VF 0xfc00707f #define MATCH_VFSGNJ_VV 0x20001057 #define MASK_VFSGNJ_VV 0xfc00707f #define MATCH_VFSGNJN_VF 0x24005057 #define MASK_VFSGNJN_VF 0xfc00707f #define MATCH_VFSGNJN_VV 0x24001057 #define MASK_VFSGNJN_VV 0xfc00707f #define MATCH_VFSGNJX_VF 0x28005057 #define MASK_VFSGNJX_VF 0xfc00707f #define MATCH_VFSGNJX_VV 0x28001057 #define MASK_VFSGNJX_VV 0xfc00707f #define MATCH_VFSLIDE1DOWN_VF 0x3c005057 #define MASK_VFSLIDE1DOWN_VF 0xfc00707f #define MATCH_VFSLIDE1UP_VF 0x38005057 #define MASK_VFSLIDE1UP_VF 0xfc00707f #define MATCH_VFSQRT_V 0x4c001057 #define MASK_VFSQRT_V 0xfc0ff07f #define MATCH_VFSUB_VF 0x8005057 #define MASK_VFSUB_VF 0xfc00707f #define MATCH_VFSUB_VV 0x8001057 #define MASK_VFSUB_VV 0xfc00707f #define MATCH_VFWADD_VF 0xc0005057 #define MASK_VFWADD_VF 0xfc00707f #define MATCH_VFWADD_VV 0xc0001057 #define MASK_VFWADD_VV 0xfc00707f #define MATCH_VFWADD_WF 0xd0005057 #define MASK_VFWADD_WF 0xfc00707f #define MATCH_VFWADD_WV 0xd0001057 #define MASK_VFWADD_WV 0xfc00707f #define MATCH_VFWCVT_F_F_V 0x48061057 #define MASK_VFWCVT_F_F_V 0xfc0ff07f #define MATCH_VFWCVT_F_X_V 0x48059057 #define MASK_VFWCVT_F_X_V 0xfc0ff07f #define MATCH_VFWCVT_F_XU_V 0x48051057 #define MASK_VFWCVT_F_XU_V 0xfc0ff07f #define MATCH_VFWCVT_RTZ_X_F_V 0x48079057 #define MASK_VFWCVT_RTZ_X_F_V 0xfc0ff07f #define MATCH_VFWCVT_RTZ_XU_F_V 0x48071057 #define MASK_VFWCVT_RTZ_XU_F_V 0xfc0ff07f #define MATCH_VFWCVT_X_F_V 0x48049057 #define MASK_VFWCVT_X_F_V 0xfc0ff07f #define MATCH_VFWCVT_XU_F_V 0x48041057 #define MASK_VFWCVT_XU_F_V 0xfc0ff07f #define MATCH_VFWMACC_VF 0xf0005057 #define MASK_VFWMACC_VF 0xfc00707f #define MATCH_VFWMACC_VV 0xf0001057 #define MASK_VFWMACC_VV 0xfc00707f #define MATCH_VFWMSAC_VF 0xf8005057 #define MASK_VFWMSAC_VF 0xfc00707f #define MATCH_VFWMSAC_VV 0xf8001057 #define MASK_VFWMSAC_VV 0xfc00707f #define MATCH_VFWMUL_VF 0xe0005057 #define MASK_VFWMUL_VF 0xfc00707f #define MATCH_VFWMUL_VV 0xe0001057 #define MASK_VFWMUL_VV 0xfc00707f #define MATCH_VFWNMACC_VF 0xf4005057 #define MASK_VFWNMACC_VF 0xfc00707f #define MATCH_VFWNMACC_VV 0xf4001057 #define MASK_VFWNMACC_VV 0xfc00707f #define MATCH_VFWNMSAC_VF 0xfc005057 #define MASK_VFWNMSAC_VF 0xfc00707f #define MATCH_VFWNMSAC_VV 0xfc001057 #define MASK_VFWNMSAC_VV 0xfc00707f #define MATCH_VFWREDOSUM_VS 0xcc001057 #define MASK_VFWREDOSUM_VS 0xfc00707f #define MATCH_VFWREDUSUM_VS 0xc4001057 #define MASK_VFWREDUSUM_VS 0xfc00707f #define MATCH_VFWSUB_VF 0xc8005057 #define MASK_VFWSUB_VF 0xfc00707f #define MATCH_VFWSUB_VV 0xc8001057 #define MASK_VFWSUB_VV 0xfc00707f #define MATCH_VFWSUB_WF 0xd8005057 #define MASK_VFWSUB_WF 0xfc00707f #define MATCH_VFWSUB_WV 0xd8001057 #define MASK_VFWSUB_WV 0xfc00707f #define MATCH_VID_V 0x5008a057 #define MASK_VID_V 0xfdfff07f #define MATCH_VIOTA_M 0x50082057 #define MASK_VIOTA_M 0xfc0ff07f #define MATCH_VL1RE16_V 0x2805007 #define MASK_VL1RE16_V 0xfff0707f #define MATCH_VL1RE32_V 0x2806007 #define MASK_VL1RE32_V 0xfff0707f #define MATCH_VL1RE64_V 0x2807007 #define MASK_VL1RE64_V 0xfff0707f #define MATCH_VL1RE8_V 0x2800007 #define MASK_VL1RE8_V 0xfff0707f #define MATCH_VL2RE16_V 0x22805007 #define MASK_VL2RE16_V 0xfff0707f #define MATCH_VL2RE32_V 0x22806007 #define MASK_VL2RE32_V 0xfff0707f #define MATCH_VL2RE64_V 0x22807007 #define MASK_VL2RE64_V 0xfff0707f #define MATCH_VL2RE8_V 0x22800007 #define MASK_VL2RE8_V 0xfff0707f #define MATCH_VL4RE16_V 0x62805007 #define MASK_VL4RE16_V 0xfff0707f #define MATCH_VL4RE32_V 0x62806007 #define MASK_VL4RE32_V 0xfff0707f #define MATCH_VL4RE64_V 0x62807007 #define MASK_VL4RE64_V 0xfff0707f #define MATCH_VL4RE8_V 0x62800007 #define MASK_VL4RE8_V 0xfff0707f #define MATCH_VL8RE16_V 0xe2805007 #define MASK_VL8RE16_V 0xfff0707f #define MATCH_VL8RE32_V 0xe2806007 #define MASK_VL8RE32_V 0xfff0707f #define MATCH_VL8RE64_V 0xe2807007 #define MASK_VL8RE64_V 0xfff0707f #define MATCH_VL8RE8_V 0xe2800007 #define MASK_VL8RE8_V 0xfff0707f #define MATCH_VLE1024_V 0x10007007 #define MASK_VLE1024_V 0x1df0707f #define MATCH_VLE1024FF_V 0x11007007 #define MASK_VLE1024FF_V 0x1df0707f #define MATCH_VLE128_V 0x10000007 #define MASK_VLE128_V 0x1df0707f #define MATCH_VLE128FF_V 0x11000007 #define MASK_VLE128FF_V 0x1df0707f #define MATCH_VLE16_V 0x5007 #define MASK_VLE16_V 0x1df0707f #define MATCH_VLE16FF_V 0x1005007 #define MASK_VLE16FF_V 0x1df0707f #define MATCH_VLE256_V 0x10005007 #define MASK_VLE256_V 0x1df0707f #define MATCH_VLE256FF_V 0x11005007 #define MASK_VLE256FF_V 0x1df0707f #define MATCH_VLE32_V 0x6007 #define MASK_VLE32_V 0x1df0707f #define MATCH_VLE32FF_V 0x1006007 #define MASK_VLE32FF_V 0x1df0707f #define MATCH_VLE512_V 0x10006007 #define MASK_VLE512_V 0x1df0707f #define MATCH_VLE512FF_V 0x11006007 #define MASK_VLE512FF_V 0x1df0707f #define MATCH_VLE64_V 0x7007 #define MASK_VLE64_V 0x1df0707f #define MATCH_VLE64FF_V 0x1007007 #define MASK_VLE64FF_V 0x1df0707f #define MATCH_VLE8_V 0x7 #define MASK_VLE8_V 0x1df0707f #define MATCH_VLE8FF_V 0x1000007 #define MASK_VLE8FF_V 0x1df0707f #define MATCH_VLM_V 0x2b00007 #define MASK_VLM_V 0xfff0707f #define MATCH_VLOXEI1024_V 0x1c007007 #define MASK_VLOXEI1024_V 0x1c00707f #define MATCH_VLOXEI128_V 0x1c000007 #define MASK_VLOXEI128_V 0x1c00707f #define MATCH_VLOXEI16_V 0xc005007 #define MASK_VLOXEI16_V 0x1c00707f #define MATCH_VLOXEI256_V 0x1c005007 #define MASK_VLOXEI256_V 0x1c00707f #define MATCH_VLOXEI32_V 0xc006007 #define MASK_VLOXEI32_V 0x1c00707f #define MATCH_VLOXEI512_V 0x1c006007 #define MASK_VLOXEI512_V 0x1c00707f #define MATCH_VLOXEI64_V 0xc007007 #define MASK_VLOXEI64_V 0x1c00707f #define MATCH_VLOXEI8_V 0xc000007 #define MASK_VLOXEI8_V 0x1c00707f #define MATCH_VLSE1024_V 0x18007007 #define MASK_VLSE1024_V 0x1c00707f #define MATCH_VLSE128_V 0x18000007 #define MASK_VLSE128_V 0x1c00707f #define MATCH_VLSE16_V 0x8005007 #define MASK_VLSE16_V 0x1c00707f #define MATCH_VLSE256_V 0x18005007 #define MASK_VLSE256_V 0x1c00707f #define MATCH_VLSE32_V 0x8006007 #define MASK_VLSE32_V 0x1c00707f #define MATCH_VLSE512_V 0x18006007 #define MASK_VLSE512_V 0x1c00707f #define MATCH_VLSE64_V 0x8007007 #define MASK_VLSE64_V 0x1c00707f #define MATCH_VLSE8_V 0x8000007 #define MASK_VLSE8_V 0x1c00707f #define MATCH_VLUXEI1024_V 0x14007007 #define MASK_VLUXEI1024_V 0x1c00707f #define MATCH_VLUXEI128_V 0x14000007 #define MASK_VLUXEI128_V 0x1c00707f #define MATCH_VLUXEI16_V 0x4005007 #define MASK_VLUXEI16_V 0x1c00707f #define MATCH_VLUXEI256_V 0x14005007 #define MASK_VLUXEI256_V 0x1c00707f #define MATCH_VLUXEI32_V 0x4006007 #define MASK_VLUXEI32_V 0x1c00707f #define MATCH_VLUXEI512_V 0x14006007 #define MASK_VLUXEI512_V 0x1c00707f #define MATCH_VLUXEI64_V 0x4007007 #define MASK_VLUXEI64_V 0x1c00707f #define MATCH_VLUXEI8_V 0x4000007 #define MASK_VLUXEI8_V 0x1c00707f #define MATCH_VMACC_VV 0xb4002057 #define MASK_VMACC_VV 0xfc00707f #define MATCH_VMACC_VX 0xb4006057 #define MASK_VMACC_VX 0xfc00707f #define MATCH_VMADC_VI 0x46003057 #define MASK_VMADC_VI 0xfe00707f #define MATCH_VMADC_VIM 0x44003057 #define MASK_VMADC_VIM 0xfe00707f #define MATCH_VMADC_VV 0x46000057 #define MASK_VMADC_VV 0xfe00707f #define MATCH_VMADC_VVM 0x44000057 #define MASK_VMADC_VVM 0xfe00707f #define MATCH_VMADC_VX 0x46004057 #define MASK_VMADC_VX 0xfe00707f #define MATCH_VMADC_VXM 0x44004057 #define MASK_VMADC_VXM 0xfe00707f #define MATCH_VMADD_VV 0xa4002057 #define MASK_VMADD_VV 0xfc00707f #define MATCH_VMADD_VX 0xa4006057 #define MASK_VMADD_VX 0xfc00707f #define MATCH_VMAND_MM 0x64002057 #define MASK_VMAND_MM 0xfc00707f #define MATCH_VMANDN_MM 0x60002057 #define MASK_VMANDN_MM 0xfc00707f #define MATCH_VMAX_VV 0x1c000057 #define MASK_VMAX_VV 0xfc00707f #define MATCH_VMAX_VX 0x1c004057 #define MASK_VMAX_VX 0xfc00707f #define MATCH_VMAXU_VV 0x18000057 #define MASK_VMAXU_VV 0xfc00707f #define MATCH_VMAXU_VX 0x18004057 #define MASK_VMAXU_VX 0xfc00707f #define MATCH_VMERGE_VIM 0x5c003057 #define MASK_VMERGE_VIM 0xfe00707f #define MATCH_VMERGE_VVM 0x5c000057 #define MASK_VMERGE_VVM 0xfe00707f #define MATCH_VMERGE_VXM 0x5c004057 #define MASK_VMERGE_VXM 0xfe00707f #define MATCH_VMFEQ_VF 0x60005057 #define MASK_VMFEQ_VF 0xfc00707f #define MATCH_VMFEQ_VV 0x60001057 #define MASK_VMFEQ_VV 0xfc00707f #define MATCH_VMFGE_VF 0x7c005057 #define MASK_VMFGE_VF 0xfc00707f #define MATCH_VMFGT_VF 0x74005057 #define MASK_VMFGT_VF 0xfc00707f #define MATCH_VMFLE_VF 0x64005057 #define MASK_VMFLE_VF 0xfc00707f #define MATCH_VMFLE_VV 0x64001057 #define MASK_VMFLE_VV 0xfc00707f #define MATCH_VMFLT_VF 0x6c005057 #define MASK_VMFLT_VF 0xfc00707f #define MATCH_VMFLT_VV 0x6c001057 #define MASK_VMFLT_VV 0xfc00707f #define MATCH_VMFNE_VF 0x70005057 #define MASK_VMFNE_VF 0xfc00707f #define MATCH_VMFNE_VV 0x70001057 #define MASK_VMFNE_VV 0xfc00707f #define MATCH_VMIN_VV 0x14000057 #define MASK_VMIN_VV 0xfc00707f #define MATCH_VMIN_VX 0x14004057 #define MASK_VMIN_VX 0xfc00707f #define MATCH_VMINU_VV 0x10000057 #define MASK_VMINU_VV 0xfc00707f #define MATCH_VMINU_VX 0x10004057 #define MASK_VMINU_VX 0xfc00707f #define MATCH_VMNAND_MM 0x74002057 #define MASK_VMNAND_MM 0xfc00707f #define MATCH_VMNOR_MM 0x78002057 #define MASK_VMNOR_MM 0xfc00707f #define MATCH_VMOR_MM 0x68002057 #define MASK_VMOR_MM 0xfc00707f #define MATCH_VMORN_MM 0x70002057 #define MASK_VMORN_MM 0xfc00707f #define MATCH_VMSBC_VV 0x4e000057 #define MASK_VMSBC_VV 0xfe00707f #define MATCH_VMSBC_VVM 0x4c000057 #define MASK_VMSBC_VVM 0xfe00707f #define MATCH_VMSBC_VX 0x4e004057 #define MASK_VMSBC_VX 0xfe00707f #define MATCH_VMSBC_VXM 0x4c004057 #define MASK_VMSBC_VXM 0xfe00707f #define MATCH_VMSBF_M 0x5000a057 #define MASK_VMSBF_M 0xfc0ff07f #define MATCH_VMSEQ_VI 0x60003057 #define MASK_VMSEQ_VI 0xfc00707f #define MATCH_VMSEQ_VV 0x60000057 #define MASK_VMSEQ_VV 0xfc00707f #define MATCH_VMSEQ_VX 0x60004057 #define MASK_VMSEQ_VX 0xfc00707f #define MATCH_VMSGT_VI 0x7c003057 #define MASK_VMSGT_VI 0xfc00707f #define MATCH_VMSGT_VX 0x7c004057 #define MASK_VMSGT_VX 0xfc00707f #define MATCH_VMSGTU_VI 0x78003057 #define MASK_VMSGTU_VI 0xfc00707f #define MATCH_VMSGTU_VX 0x78004057 #define MASK_VMSGTU_VX 0xfc00707f #define MATCH_VMSIF_M 0x5001a057 #define MASK_VMSIF_M 0xfc0ff07f #define MATCH_VMSLE_VI 0x74003057 #define MASK_VMSLE_VI 0xfc00707f #define MATCH_VMSLE_VV 0x74000057 #define MASK_VMSLE_VV 0xfc00707f #define MATCH_VMSLE_VX 0x74004057 #define MASK_VMSLE_VX 0xfc00707f #define MATCH_VMSLEU_VI 0x70003057 #define MASK_VMSLEU_VI 0xfc00707f #define MATCH_VMSLEU_VV 0x70000057 #define MASK_VMSLEU_VV 0xfc00707f #define MATCH_VMSLEU_VX 0x70004057 #define MASK_VMSLEU_VX 0xfc00707f #define MATCH_VMSLT_VV 0x6c000057 #define MASK_VMSLT_VV 0xfc00707f #define MATCH_VMSLT_VX 0x6c004057 #define MASK_VMSLT_VX 0xfc00707f #define MATCH_VMSLTU_VV 0x68000057 #define MASK_VMSLTU_VV 0xfc00707f #define MATCH_VMSLTU_VX 0x68004057 #define MASK_VMSLTU_VX 0xfc00707f #define MATCH_VMSNE_VI 0x64003057 #define MASK_VMSNE_VI 0xfc00707f #define MATCH_VMSNE_VV 0x64000057 #define MASK_VMSNE_VV 0xfc00707f #define MATCH_VMSNE_VX 0x64004057 #define MASK_VMSNE_VX 0xfc00707f #define MATCH_VMSOF_M 0x50012057 #define MASK_VMSOF_M 0xfc0ff07f #define MATCH_VMUL_VV 0x94002057 #define MASK_VMUL_VV 0xfc00707f #define MATCH_VMUL_VX 0x94006057 #define MASK_VMUL_VX 0xfc00707f #define MATCH_VMULH_VV 0x9c002057 #define MASK_VMULH_VV 0xfc00707f #define MATCH_VMULH_VX 0x9c006057 #define MASK_VMULH_VX 0xfc00707f #define MATCH_VMULHSU_VV 0x98002057 #define MASK_VMULHSU_VV 0xfc00707f #define MATCH_VMULHSU_VX 0x98006057 #define MASK_VMULHSU_VX 0xfc00707f #define MATCH_VMULHU_VV 0x90002057 #define MASK_VMULHU_VV 0xfc00707f #define MATCH_VMULHU_VX 0x90006057 #define MASK_VMULHU_VX 0xfc00707f #define MATCH_VMV1R_V 0x9e003057 #define MASK_VMV1R_V 0xfe0ff07f #define MATCH_VMV2R_V 0x9e00b057 #define MASK_VMV2R_V 0xfe0ff07f #define MATCH_VMV4R_V 0x9e01b057 #define MASK_VMV4R_V 0xfe0ff07f #define MATCH_VMV8R_V 0x9e03b057 #define MASK_VMV8R_V 0xfe0ff07f #define MATCH_VMV_S_X 0x42006057 #define MASK_VMV_S_X 0xfff0707f #define MATCH_VMV_V_I 0x5e003057 #define MASK_VMV_V_I 0xfff0707f #define MATCH_VMV_V_V 0x5e000057 #define MASK_VMV_V_V 0xfff0707f #define MATCH_VMV_V_X 0x5e004057 #define MASK_VMV_V_X 0xfff0707f #define MATCH_VMV_X_S 0x42002057 #define MASK_VMV_X_S 0xfe0ff07f #define MATCH_VMXNOR_MM 0x7c002057 #define MASK_VMXNOR_MM 0xfc00707f #define MATCH_VMXOR_MM 0x6c002057 #define MASK_VMXOR_MM 0xfc00707f #define MATCH_VNCLIP_WI 0xbc003057 #define MASK_VNCLIP_WI 0xfc00707f #define MATCH_VNCLIP_WV 0xbc000057 #define MASK_VNCLIP_WV 0xfc00707f #define MATCH_VNCLIP_WX 0xbc004057 #define MASK_VNCLIP_WX 0xfc00707f #define MATCH_VNCLIPU_WI 0xb8003057 #define MASK_VNCLIPU_WI 0xfc00707f #define MATCH_VNCLIPU_WV 0xb8000057 #define MASK_VNCLIPU_WV 0xfc00707f #define MATCH_VNCLIPU_WX 0xb8004057 #define MASK_VNCLIPU_WX 0xfc00707f #define MATCH_VNMSAC_VV 0xbc002057 #define MASK_VNMSAC_VV 0xfc00707f #define MATCH_VNMSAC_VX 0xbc006057 #define MASK_VNMSAC_VX 0xfc00707f #define MATCH_VNMSUB_VV 0xac002057 #define MASK_VNMSUB_VV 0xfc00707f #define MATCH_VNMSUB_VX 0xac006057 #define MASK_VNMSUB_VX 0xfc00707f #define MATCH_VNSRA_WI 0xb4003057 #define MASK_VNSRA_WI 0xfc00707f #define MATCH_VNSRA_WV 0xb4000057 #define MASK_VNSRA_WV 0xfc00707f #define MATCH_VNSRA_WX 0xb4004057 #define MASK_VNSRA_WX 0xfc00707f #define MATCH_VNSRL_WI 0xb0003057 #define MASK_VNSRL_WI 0xfc00707f #define MATCH_VNSRL_WV 0xb0000057 #define MASK_VNSRL_WV 0xfc00707f #define MATCH_VNSRL_WX 0xb0004057 #define MASK_VNSRL_WX 0xfc00707f #define MATCH_VOR_VI 0x28003057 #define MASK_VOR_VI 0xfc00707f #define MATCH_VOR_VV 0x28000057 #define MASK_VOR_VV 0xfc00707f #define MATCH_VOR_VX 0x28004057 #define MASK_VOR_VX 0xfc00707f #define MATCH_VREDAND_VS 0x4002057 #define MASK_VREDAND_VS 0xfc00707f #define MATCH_VREDMAX_VS 0x1c002057 #define MASK_VREDMAX_VS 0xfc00707f #define MATCH_VREDMAXU_VS 0x18002057 #define MASK_VREDMAXU_VS 0xfc00707f #define MATCH_VREDMIN_VS 0x14002057 #define MASK_VREDMIN_VS 0xfc00707f #define MATCH_VREDMINU_VS 0x10002057 #define MASK_VREDMINU_VS 0xfc00707f #define MATCH_VREDOR_VS 0x8002057 #define MASK_VREDOR_VS 0xfc00707f #define MATCH_VREDSUM_VS 0x2057 #define MASK_VREDSUM_VS 0xfc00707f #define MATCH_VREDXOR_VS 0xc002057 #define MASK_VREDXOR_VS 0xfc00707f #define MATCH_VREM_VV 0x8c002057 #define MASK_VREM_VV 0xfc00707f #define MATCH_VREM_VX 0x8c006057 #define MASK_VREM_VX 0xfc00707f #define MATCH_VREMU_VV 0x88002057 #define MASK_VREMU_VV 0xfc00707f #define MATCH_VREMU_VX 0x88006057 #define MASK_VREMU_VX 0xfc00707f #define MATCH_VRGATHER_VI 0x30003057 #define MASK_VRGATHER_VI 0xfc00707f #define MATCH_VRGATHER_VV 0x30000057 #define MASK_VRGATHER_VV 0xfc00707f #define MATCH_VRGATHER_VX 0x30004057 #define MASK_VRGATHER_VX 0xfc00707f #define MATCH_VRGATHEREI16_VV 0x38000057 #define MASK_VRGATHEREI16_VV 0xfc00707f #define MATCH_VRSUB_VI 0xc003057 #define MASK_VRSUB_VI 0xfc00707f #define MATCH_VRSUB_VX 0xc004057 #define MASK_VRSUB_VX 0xfc00707f #define MATCH_VS1R_V 0x2800027 #define MASK_VS1R_V 0xfff0707f #define MATCH_VS2R_V 0x22800027 #define MASK_VS2R_V 0xfff0707f #define MATCH_VS4R_V 0x62800027 #define MASK_VS4R_V 0xfff0707f #define MATCH_VS8R_V 0xe2800027 #define MASK_VS8R_V 0xfff0707f #define MATCH_VSADD_VI 0x84003057 #define MASK_VSADD_VI 0xfc00707f #define MATCH_VSADD_VV 0x84000057 #define MASK_VSADD_VV 0xfc00707f #define MATCH_VSADD_VX 0x84004057 #define MASK_VSADD_VX 0xfc00707f #define MATCH_VSADDU_VI 0x80003057 #define MASK_VSADDU_VI 0xfc00707f #define MATCH_VSADDU_VV 0x80000057 #define MASK_VSADDU_VV 0xfc00707f #define MATCH_VSADDU_VX 0x80004057 #define MASK_VSADDU_VX 0xfc00707f #define MATCH_VSBC_VVM 0x48000057 #define MASK_VSBC_VVM 0xfe00707f #define MATCH_VSBC_VXM 0x48004057 #define MASK_VSBC_VXM 0xfe00707f #define MATCH_VSE1024_V 0x10007027 #define MASK_VSE1024_V 0x1df0707f #define MATCH_VSE128_V 0x10000027 #define MASK_VSE128_V 0x1df0707f #define MATCH_VSE16_V 0x5027 #define MASK_VSE16_V 0x1df0707f #define MATCH_VSE256_V 0x10005027 #define MASK_VSE256_V 0x1df0707f #define MATCH_VSE32_V 0x6027 #define MASK_VSE32_V 0x1df0707f #define MATCH_VSE512_V 0x10006027 #define MASK_VSE512_V 0x1df0707f #define MATCH_VSE64_V 0x7027 #define MASK_VSE64_V 0x1df0707f #define MATCH_VSE8_V 0x27 #define MASK_VSE8_V 0x1df0707f #define MATCH_VSETIVLI 0xc0007057 #define MASK_VSETIVLI 0xc000707f #define MATCH_VSETVL 0x80007057 #define MASK_VSETVL 0xfe00707f #define MATCH_VSETVLI 0x7057 #define MASK_VSETVLI 0x8000707f #define MATCH_VSEXT_VF2 0x4803a057 #define MASK_VSEXT_VF2 0xfc0ff07f #define MATCH_VSEXT_VF4 0x4802a057 #define MASK_VSEXT_VF4 0xfc0ff07f #define MATCH_VSEXT_VF8 0x4801a057 #define MASK_VSEXT_VF8 0xfc0ff07f #define MATCH_VSLIDE1DOWN_VX 0x3c006057 #define MASK_VSLIDE1DOWN_VX 0xfc00707f #define MATCH_VSLIDE1UP_VX 0x38006057 #define MASK_VSLIDE1UP_VX 0xfc00707f #define MATCH_VSLIDEDOWN_VI 0x3c003057 #define MASK_VSLIDEDOWN_VI 0xfc00707f #define MATCH_VSLIDEDOWN_VX 0x3c004057 #define MASK_VSLIDEDOWN_VX 0xfc00707f #define MATCH_VSLIDEUP_VI 0x38003057 #define MASK_VSLIDEUP_VI 0xfc00707f #define MATCH_VSLIDEUP_VX 0x38004057 #define MASK_VSLIDEUP_VX 0xfc00707f #define MATCH_VSLL_VI 0x94003057 #define MASK_VSLL_VI 0xfc00707f #define MATCH_VSLL_VV 0x94000057 #define MASK_VSLL_VV 0xfc00707f #define MATCH_VSLL_VX 0x94004057 #define MASK_VSLL_VX 0xfc00707f #define MATCH_VSM_V 0x2b00027 #define MASK_VSM_V 0xfff0707f #define MATCH_VSMUL_VV 0x9c000057 #define MASK_VSMUL_VV 0xfc00707f #define MATCH_VSMUL_VX 0x9c004057 #define MASK_VSMUL_VX 0xfc00707f #define MATCH_VSOXEI1024_V 0x1c007027 #define MASK_VSOXEI1024_V 0x1c00707f #define MATCH_VSOXEI128_V 0x1c000027 #define MASK_VSOXEI128_V 0x1c00707f #define MATCH_VSOXEI16_V 0xc005027 #define MASK_VSOXEI16_V 0x1c00707f #define MATCH_VSOXEI256_V 0x1c005027 #define MASK_VSOXEI256_V 0x1c00707f #define MATCH_VSOXEI32_V 0xc006027 #define MASK_VSOXEI32_V 0x1c00707f #define MATCH_VSOXEI512_V 0x1c006027 #define MASK_VSOXEI512_V 0x1c00707f #define MATCH_VSOXEI64_V 0xc007027 #define MASK_VSOXEI64_V 0x1c00707f #define MATCH_VSOXEI8_V 0xc000027 #define MASK_VSOXEI8_V 0x1c00707f #define MATCH_VSRA_VI 0xa4003057 #define MASK_VSRA_VI 0xfc00707f #define MATCH_VSRA_VV 0xa4000057 #define MASK_VSRA_VV 0xfc00707f #define MATCH_VSRA_VX 0xa4004057 #define MASK_VSRA_VX 0xfc00707f #define MATCH_VSRL_VI 0xa0003057 #define MASK_VSRL_VI 0xfc00707f #define MATCH_VSRL_VV 0xa0000057 #define MASK_VSRL_VV 0xfc00707f #define MATCH_VSRL_VX 0xa0004057 #define MASK_VSRL_VX 0xfc00707f #define MATCH_VSSE1024_V 0x18007027 #define MASK_VSSE1024_V 0x1c00707f #define MATCH_VSSE128_V 0x18000027 #define MASK_VSSE128_V 0x1c00707f #define MATCH_VSSE16_V 0x8005027 #define MASK_VSSE16_V 0x1c00707f #define MATCH_VSSE256_V 0x18005027 #define MASK_VSSE256_V 0x1c00707f #define MATCH_VSSE32_V 0x8006027 #define MASK_VSSE32_V 0x1c00707f #define MATCH_VSSE512_V 0x18006027 #define MASK_VSSE512_V 0x1c00707f #define MATCH_VSSE64_V 0x8007027 #define MASK_VSSE64_V 0x1c00707f #define MATCH_VSSE8_V 0x8000027 #define MASK_VSSE8_V 0x1c00707f #define MATCH_VSSRA_VI 0xac003057 #define MASK_VSSRA_VI 0xfc00707f #define MATCH_VSSRA_VV 0xac000057 #define MASK_VSSRA_VV 0xfc00707f #define MATCH_VSSRA_VX 0xac004057 #define MASK_VSSRA_VX 0xfc00707f #define MATCH_VSSRL_VI 0xa8003057 #define MASK_VSSRL_VI 0xfc00707f #define MATCH_VSSRL_VV 0xa8000057 #define MASK_VSSRL_VV 0xfc00707f #define MATCH_VSSRL_VX 0xa8004057 #define MASK_VSSRL_VX 0xfc00707f #define MATCH_VSSUB_VV 0x8c000057 #define MASK_VSSUB_VV 0xfc00707f #define MATCH_VSSUB_VX 0x8c004057 #define MASK_VSSUB_VX 0xfc00707f #define MATCH_VSSUBU_VV 0x88000057 #define MASK_VSSUBU_VV 0xfc00707f #define MATCH_VSSUBU_VX 0x88004057 #define MASK_VSSUBU_VX 0xfc00707f #define MATCH_VSUB_VV 0x8000057 #define MASK_VSUB_VV 0xfc00707f #define MATCH_VSUB_VX 0x8004057 #define MASK_VSUB_VX 0xfc00707f #define MATCH_VSUXEI1024_V 0x14007027 #define MASK_VSUXEI1024_V 0x1c00707f #define MATCH_VSUXEI128_V 0x14000027 #define MASK_VSUXEI128_V 0x1c00707f #define MATCH_VSUXEI16_V 0x4005027 #define MASK_VSUXEI16_V 0x1c00707f #define MATCH_VSUXEI256_V 0x14005027 #define MASK_VSUXEI256_V 0x1c00707f #define MATCH_VSUXEI32_V 0x4006027 #define MASK_VSUXEI32_V 0x1c00707f #define MATCH_VSUXEI512_V 0x14006027 #define MASK_VSUXEI512_V 0x1c00707f #define MATCH_VSUXEI64_V 0x4007027 #define MASK_VSUXEI64_V 0x1c00707f #define MATCH_VSUXEI8_V 0x4000027 #define MASK_VSUXEI8_V 0x1c00707f #define MATCH_VWADD_VV 0xc4002057 #define MASK_VWADD_VV 0xfc00707f #define MATCH_VWADD_VX 0xc4006057 #define MASK_VWADD_VX 0xfc00707f #define MATCH_VWADD_WV 0xd4002057 #define MASK_VWADD_WV 0xfc00707f #define MATCH_VWADD_WX 0xd4006057 #define MASK_VWADD_WX 0xfc00707f #define MATCH_VWADDU_VV 0xc0002057 #define MASK_VWADDU_VV 0xfc00707f #define MATCH_VWADDU_VX 0xc0006057 #define MASK_VWADDU_VX 0xfc00707f #define MATCH_VWADDU_WV 0xd0002057 #define MASK_VWADDU_WV 0xfc00707f #define MATCH_VWADDU_WX 0xd0006057 #define MASK_VWADDU_WX 0xfc00707f #define MATCH_VWMACC_VV 0xf4002057 #define MASK_VWMACC_VV 0xfc00707f #define MATCH_VWMACC_VX 0xf4006057 #define MASK_VWMACC_VX 0xfc00707f #define MATCH_VWMACCSU_VV 0xfc002057 #define MASK_VWMACCSU_VV 0xfc00707f #define MATCH_VWMACCSU_VX 0xfc006057 #define MASK_VWMACCSU_VX 0xfc00707f #define MATCH_VWMACCU_VV 0xf0002057 #define MASK_VWMACCU_VV 0xfc00707f #define MATCH_VWMACCU_VX 0xf0006057 #define MASK_VWMACCU_VX 0xfc00707f #define MATCH_VWMACCUS_VX 0xf8006057 #define MASK_VWMACCUS_VX 0xfc00707f #define MATCH_VWMUL_VV 0xec002057 #define MASK_VWMUL_VV 0xfc00707f #define MATCH_VWMUL_VX 0xec006057 #define MASK_VWMUL_VX 0xfc00707f #define MATCH_VWMULSU_VV 0xe8002057 #define MASK_VWMULSU_VV 0xfc00707f #define MATCH_VWMULSU_VX 0xe8006057 #define MASK_VWMULSU_VX 0xfc00707f #define MATCH_VWMULU_VV 0xe0002057 #define MASK_VWMULU_VV 0xfc00707f #define MATCH_VWMULU_VX 0xe0006057 #define MASK_VWMULU_VX 0xfc00707f #define MATCH_VWREDSUM_VS 0xc4000057 #define MASK_VWREDSUM_VS 0xfc00707f #define MATCH_VWREDSUMU_VS 0xc0000057 #define MASK_VWREDSUMU_VS 0xfc00707f #define MATCH_VWSUB_VV 0xcc002057 #define MASK_VWSUB_VV 0xfc00707f #define MATCH_VWSUB_VX 0xcc006057 #define MASK_VWSUB_VX 0xfc00707f #define MATCH_VWSUB_WV 0xdc002057 #define MASK_VWSUB_WV 0xfc00707f #define MATCH_VWSUB_WX 0xdc006057 #define MASK_VWSUB_WX 0xfc00707f #define MATCH_VWSUBU_VV 0xc8002057 #define MASK_VWSUBU_VV 0xfc00707f #define MATCH_VWSUBU_VX 0xc8006057 #define MASK_VWSUBU_VX 0xfc00707f #define MATCH_VWSUBU_WV 0xd8002057 #define MASK_VWSUBU_WV 0xfc00707f #define MATCH_VWSUBU_WX 0xd8006057 #define MASK_VWSUBU_WX 0xfc00707f #define MATCH_VXOR_VI 0x2c003057 #define MASK_VXOR_VI 0xfc00707f #define MATCH_VXOR_VV 0x2c000057 #define MASK_VXOR_VV 0xfc00707f #define MATCH_VXOR_VX 0x2c004057 #define MASK_VXOR_VX 0xfc00707f #define MATCH_VZEXT_VF2 0x48032057 #define MASK_VZEXT_VF2 0xfc0ff07f #define MATCH_VZEXT_VF4 0x48022057 #define MASK_VZEXT_VF4 0xfc0ff07f #define MATCH_VZEXT_VF8 0x48012057 #define MASK_VZEXT_VF8 0xfc0ff07f #define MATCH_WEXT 0xce000077 #define MASK_WEXT 0xfe00707f #define MATCH_WEXTI 0xde000077 #define MASK_WEXTI 0xfe00707f #define MATCH_WFI 0x10500073 #define MASK_WFI 0xffffffff #define MATCH_WRS_NTO 0xd00073 #define MASK_WRS_NTO 0xffffffff #define MATCH_WRS_STO 0x1d00073 #define MASK_WRS_STO 0xffffffff #define MATCH_XNOR 0x40004033 #define MASK_XNOR 0xfe00707f #define MATCH_XOR 0x4033 #define MASK_XOR 0xfe00707f #define MATCH_XORI 0x4013 #define MASK_XORI 0x707f #define MATCH_XPERM16 0x28006033 #define MASK_XPERM16 0xfe00707f #define MATCH_XPERM32 0x28000033 #define MASK_XPERM32 0xfe00707f #define MATCH_XPERM4 0x28002033 #define MASK_XPERM4 0xfe00707f #define MATCH_XPERM8 0x28004033 #define MASK_XPERM8 0xfe00707f #define MATCH_ZUNPKD810 0xacc00077 #define MASK_ZUNPKD810 0xfff0707f #define MATCH_ZUNPKD820 0xacd00077 #define MASK_ZUNPKD820 0xfff0707f #define MATCH_ZUNPKD830 0xace00077 #define MASK_ZUNPKD830 0xfff0707f #define MATCH_ZUNPKD831 0xacf00077 #define MASK_ZUNPKD831 0xfff0707f #define MATCH_ZUNPKD832 0xad700077 #define MASK_ZUNPKD832 0xfff0707f #define CSR_FFLAGS 0x1 #define CSR_FRM 0x2 #define CSR_FCSR 0x3 #define CSR_VSTART 0x8 #define CSR_VXSAT 0x9 #define CSR_VXRM 0xa #define CSR_VCSR 0xf #define CSR_SEED 0x15 #define CSR_CYCLE 0xc00 #define CSR_TIME 0xc01 #define CSR_INSTRET 0xc02 #define CSR_HPMCOUNTER3 0xc03 #define CSR_HPMCOUNTER4 0xc04 #define CSR_HPMCOUNTER5 0xc05 #define CSR_HPMCOUNTER6 0xc06 #define CSR_HPMCOUNTER7 0xc07 #define CSR_HPMCOUNTER8 0xc08 #define CSR_HPMCOUNTER9 0xc09 #define CSR_HPMCOUNTER10 0xc0a #define CSR_HPMCOUNTER11 0xc0b #define CSR_HPMCOUNTER12 0xc0c #define CSR_HPMCOUNTER13 0xc0d #define CSR_HPMCOUNTER14 0xc0e #define CSR_HPMCOUNTER15 0xc0f #define CSR_HPMCOUNTER16 0xc10 #define CSR_HPMCOUNTER17 0xc11 #define CSR_HPMCOUNTER18 0xc12 #define CSR_HPMCOUNTER19 0xc13 #define CSR_HPMCOUNTER20 0xc14 #define CSR_HPMCOUNTER21 0xc15 #define CSR_HPMCOUNTER22 0xc16 #define CSR_HPMCOUNTER23 0xc17 #define CSR_HPMCOUNTER24 0xc18 #define CSR_HPMCOUNTER25 0xc19 #define CSR_HPMCOUNTER26 0xc1a #define CSR_HPMCOUNTER27 0xc1b #define CSR_HPMCOUNTER28 0xc1c #define CSR_HPMCOUNTER29 0xc1d #define CSR_HPMCOUNTER30 0xc1e #define CSR_HPMCOUNTER31 0xc1f #define CSR_VL 0xc20 #define CSR_VTYPE 0xc21 #define CSR_VLENB 0xc22 #define CSR_SSTATUS 0x100 #define CSR_SEDELEG 0x102 #define CSR_SIDELEG 0x103 #define CSR_SIE 0x104 #define CSR_STVEC 0x105 #define CSR_SCOUNTEREN 0x106 #define CSR_SENVCFG 0x10a #define CSR_SSTATEEN0 0x10c #define CSR_SSTATEEN1 0x10d #define CSR_SSTATEEN2 0x10e #define CSR_SSTATEEN3 0x10f #define CSR_SSCRATCH 0x140 #define CSR_SEPC 0x141 #define CSR_SCAUSE 0x142 #define CSR_STVAL 0x143 #define CSR_SIP 0x144 #define CSR_STIMECMP 0x14d #define CSR_SATP 0x180 #define CSR_SCONTEXT 0x5a8 #define CSR_VSSTATUS 0x200 #define CSR_VSIE 0x204 #define CSR_VSTVEC 0x205 #define CSR_VSSCRATCH 0x240 #define CSR_VSEPC 0x241 #define CSR_VSCAUSE 0x242 #define CSR_VSTVAL 0x243 #define CSR_VSIP 0x244 #define CSR_VSTIMECMP 0x24d #define CSR_VSATP 0x280 #define CSR_HSTATUS 0x600 #define CSR_HEDELEG 0x602 #define CSR_HIDELEG 0x603 #define CSR_HIE 0x604 #define CSR_HTIMEDELTA 0x605 #define CSR_HCOUNTEREN 0x606 #define CSR_HGEIE 0x607 #define CSR_HENVCFG 0x60a #define CSR_HSTATEEN0 0x60c #define CSR_HSTATEEN1 0x60d #define CSR_HSTATEEN2 0x60e #define CSR_HSTATEEN3 0x60f #define CSR_HTVAL 0x643 #define CSR_HIP 0x644 #define CSR_HVIP 0x645 #define CSR_HTINST 0x64a #define CSR_HGATP 0x680 #define CSR_HCONTEXT 0x6a8 #define CSR_HGEIP 0xe12 #define CSR_SCOUNTOVF 0xda0 #define CSR_UTVT 0x7 #define CSR_UNXTI 0x45 #define CSR_UINTSTATUS 0x46 #define CSR_USCRATCHCSW 0x48 #define CSR_USCRATCHCSWL 0x49 #define CSR_STVT 0x107 #define CSR_SNXTI 0x145 #define CSR_SINTSTATUS 0x146 #define CSR_SSCRATCHCSW 0x148 #define CSR_SSCRATCHCSWL 0x149 #define CSR_MTVT 0x307 #define CSR_MNXTI 0x345 #define CSR_MINTSTATUS 0x346 #define CSR_MSCRATCHCSW 0x348 #define CSR_MSCRATCHCSWL 0x349 #define CSR_MSTATUS 0x300 #define CSR_MISA 0x301 #define CSR_MEDELEG 0x302 #define CSR_MIDELEG 0x303 #define CSR_MIE 0x304 #define CSR_MTVEC 0x305 #define CSR_MCOUNTEREN 0x306 #define CSR_MENVCFG 0x30a #define CSR_MSTATEEN0 0x30c #define CSR_MSTATEEN1 0x30d #define CSR_MSTATEEN2 0x30e #define CSR_MSTATEEN3 0x30f #define CSR_MCOUNTINHIBIT 0x320 #define CSR_MSCRATCH 0x340 #define CSR_MEPC 0x341 #define CSR_MCAUSE 0x342 #define CSR_MTVAL 0x343 #define CSR_MIP 0x344 #define CSR_MTINST 0x34a #define CSR_MTVAL2 0x34b #define CSR_PMPCFG0 0x3a0 #define CSR_PMPCFG1 0x3a1 #define CSR_PMPCFG2 0x3a2 #define CSR_PMPCFG3 0x3a3 #define CSR_PMPCFG4 0x3a4 #define CSR_PMPCFG5 0x3a5 #define CSR_PMPCFG6 0x3a6 #define CSR_PMPCFG7 0x3a7 #define CSR_PMPCFG8 0x3a8 #define CSR_PMPCFG9 0x3a9 #define CSR_PMPCFG10 0x3aa #define CSR_PMPCFG11 0x3ab #define CSR_PMPCFG12 0x3ac #define CSR_PMPCFG13 0x3ad #define CSR_PMPCFG14 0x3ae #define CSR_PMPCFG15 0x3af #define CSR_PMPADDR0 0x3b0 #define CSR_PMPADDR1 0x3b1 #define CSR_PMPADDR2 0x3b2 #define CSR_PMPADDR3 0x3b3 #define CSR_PMPADDR4 0x3b4 #define CSR_PMPADDR5 0x3b5 #define CSR_PMPADDR6 0x3b6 #define CSR_PMPADDR7 0x3b7 #define CSR_PMPADDR8 0x3b8 #define CSR_PMPADDR9 0x3b9 #define CSR_PMPADDR10 0x3ba #define CSR_PMPADDR11 0x3bb #define CSR_PMPADDR12 0x3bc #define CSR_PMPADDR13 0x3bd #define CSR_PMPADDR14 0x3be #define CSR_PMPADDR15 0x3bf #define CSR_PMPADDR16 0x3c0 #define CSR_PMPADDR17 0x3c1 #define CSR_PMPADDR18 0x3c2 #define CSR_PMPADDR19 0x3c3 #define CSR_PMPADDR20 0x3c4 #define CSR_PMPADDR21 0x3c5 #define CSR_PMPADDR22 0x3c6 #define CSR_PMPADDR23 0x3c7 #define CSR_PMPADDR24 0x3c8 #define CSR_PMPADDR25 0x3c9 #define CSR_PMPADDR26 0x3ca #define CSR_PMPADDR27 0x3cb #define CSR_PMPADDR28 0x3cc #define CSR_PMPADDR29 0x3cd #define CSR_PMPADDR30 0x3ce #define CSR_PMPADDR31 0x3cf #define CSR_PMPADDR32 0x3d0 #define CSR_PMPADDR33 0x3d1 #define CSR_PMPADDR34 0x3d2 #define CSR_PMPADDR35 0x3d3 #define CSR_PMPADDR36 0x3d4 #define CSR_PMPADDR37 0x3d5 #define CSR_PMPADDR38 0x3d6 #define CSR_PMPADDR39 0x3d7 #define CSR_PMPADDR40 0x3d8 #define CSR_PMPADDR41 0x3d9 #define CSR_PMPADDR42 0x3da #define CSR_PMPADDR43 0x3db #define CSR_PMPADDR44 0x3dc #define CSR_PMPADDR45 0x3dd #define CSR_PMPADDR46 0x3de #define CSR_PMPADDR47 0x3df #define CSR_PMPADDR48 0x3e0 #define CSR_PMPADDR49 0x3e1 #define CSR_PMPADDR50 0x3e2 #define CSR_PMPADDR51 0x3e3 #define CSR_PMPADDR52 0x3e4 #define CSR_PMPADDR53 0x3e5 #define CSR_PMPADDR54 0x3e6 #define CSR_PMPADDR55 0x3e7 #define CSR_PMPADDR56 0x3e8 #define CSR_PMPADDR57 0x3e9 #define CSR_PMPADDR58 0x3ea #define CSR_PMPADDR59 0x3eb #define CSR_PMPADDR60 0x3ec #define CSR_PMPADDR61 0x3ed #define CSR_PMPADDR62 0x3ee #define CSR_PMPADDR63 0x3ef #define CSR_MSECCFG 0x747 #define CSR_TSELECT 0x7a0 #define CSR_TDATA1 0x7a1 #define CSR_TDATA2 0x7a2 #define CSR_TDATA3 0x7a3 #define CSR_TINFO 0x7a4 #define CSR_TCONTROL 0x7a5 #define CSR_MCONTEXT 0x7a8 #define CSR_MSCONTEXT 0x7aa #define CSR_DCSR 0x7b0 #define CSR_DPC 0x7b1 #define CSR_DSCRATCH0 0x7b2 #define CSR_DSCRATCH1 0x7b3 #define CSR_MCYCLE 0xb00 #define CSR_MINSTRET 0xb02 #define CSR_MHPMCOUNTER3 0xb03 #define CSR_MHPMCOUNTER4 0xb04 #define CSR_MHPMCOUNTER5 0xb05 #define CSR_MHPMCOUNTER6 0xb06 #define CSR_MHPMCOUNTER7 0xb07 #define CSR_MHPMCOUNTER8 0xb08 #define CSR_MHPMCOUNTER9 0xb09 #define CSR_MHPMCOUNTER10 0xb0a #define CSR_MHPMCOUNTER11 0xb0b #define CSR_MHPMCOUNTER12 0xb0c #define CSR_MHPMCOUNTER13 0xb0d #define CSR_MHPMCOUNTER14 0xb0e #define CSR_MHPMCOUNTER15 0xb0f #define CSR_MHPMCOUNTER16 0xb10 #define CSR_MHPMCOUNTER17 0xb11 #define CSR_MHPMCOUNTER18 0xb12 #define CSR_MHPMCOUNTER19 0xb13 #define CSR_MHPMCOUNTER20 0xb14 #define CSR_MHPMCOUNTER21 0xb15 #define CSR_MHPMCOUNTER22 0xb16 #define CSR_MHPMCOUNTER23 0xb17 #define CSR_MHPMCOUNTER24 0xb18 #define CSR_MHPMCOUNTER25 0xb19 #define CSR_MHPMCOUNTER26 0xb1a #define CSR_MHPMCOUNTER27 0xb1b #define CSR_MHPMCOUNTER28 0xb1c #define CSR_MHPMCOUNTER29 0xb1d #define CSR_MHPMCOUNTER30 0xb1e #define CSR_MHPMCOUNTER31 0xb1f #define CSR_MHPMEVENT3 0x323 #define CSR_MHPMEVENT4 0x324 #define CSR_MHPMEVENT5 0x325 #define CSR_MHPMEVENT6 0x326 #define CSR_MHPMEVENT7 0x327 #define CSR_MHPMEVENT8 0x328 #define CSR_MHPMEVENT9 0x329 #define CSR_MHPMEVENT10 0x32a #define CSR_MHPMEVENT11 0x32b #define CSR_MHPMEVENT12 0x32c #define CSR_MHPMEVENT13 0x32d #define CSR_MHPMEVENT14 0x32e #define CSR_MHPMEVENT15 0x32f #define CSR_MHPMEVENT16 0x330 #define CSR_MHPMEVENT17 0x331 #define CSR_MHPMEVENT18 0x332 #define CSR_MHPMEVENT19 0x333 #define CSR_MHPMEVENT20 0x334 #define CSR_MHPMEVENT21 0x335 #define CSR_MHPMEVENT22 0x336 #define CSR_MHPMEVENT23 0x337 #define CSR_MHPMEVENT24 0x338 #define CSR_MHPMEVENT25 0x339 #define CSR_MHPMEVENT26 0x33a #define CSR_MHPMEVENT27 0x33b #define CSR_MHPMEVENT28 0x33c #define CSR_MHPMEVENT29 0x33d #define CSR_MHPMEVENT30 0x33e #define CSR_MHPMEVENT31 0x33f #define CSR_MVENDORID 0xf11 #define CSR_MARCHID 0xf12 #define CSR_MIMPID 0xf13 #define CSR_MHARTID 0xf14 #define CSR_MCONFIGPTR 0xf15 #define CSR_STIMECMPH 0x15d #define CSR_VSTIMECMPH 0x25d #define CSR_HTIMEDELTAH 0x615 #define CSR_HENVCFGH 0x61a #define CSR_HSTATEEN0H 0x61c #define CSR_HSTATEEN1H 0x61d #define CSR_HSTATEEN2H 0x61e #define CSR_HSTATEEN3H 0x61f #define CSR_CYCLEH 0xc80 #define CSR_TIMEH 0xc81 #define CSR_INSTRETH 0xc82 #define CSR_HPMCOUNTER3H 0xc83 #define CSR_HPMCOUNTER4H 0xc84 #define CSR_HPMCOUNTER5H 0xc85 #define CSR_HPMCOUNTER6H 0xc86 #define CSR_HPMCOUNTER7H 0xc87 #define CSR_HPMCOUNTER8H 0xc88 #define CSR_HPMCOUNTER9H 0xc89 #define CSR_HPMCOUNTER10H 0xc8a #define CSR_HPMCOUNTER11H 0xc8b #define CSR_HPMCOUNTER12H 0xc8c #define CSR_HPMCOUNTER13H 0xc8d #define CSR_HPMCOUNTER14H 0xc8e #define CSR_HPMCOUNTER15H 0xc8f #define CSR_HPMCOUNTER16H 0xc90 #define CSR_HPMCOUNTER17H 0xc91 #define CSR_HPMCOUNTER18H 0xc92 #define CSR_HPMCOUNTER19H 0xc93 #define CSR_HPMCOUNTER20H 0xc94 #define CSR_HPMCOUNTER21H 0xc95 #define CSR_HPMCOUNTER22H 0xc96 #define CSR_HPMCOUNTER23H 0xc97 #define CSR_HPMCOUNTER24H 0xc98 #define CSR_HPMCOUNTER25H 0xc99 #define CSR_HPMCOUNTER26H 0xc9a #define CSR_HPMCOUNTER27H 0xc9b #define CSR_HPMCOUNTER28H 0xc9c #define CSR_HPMCOUNTER29H 0xc9d #define CSR_HPMCOUNTER30H 0xc9e #define CSR_HPMCOUNTER31H 0xc9f #define CSR_MSTATUSH 0x310 #define CSR_MENVCFGH 0x31a #define CSR_MSTATEEN0H 0x31c #define CSR_MSTATEEN1H 0x31d #define CSR_MSTATEEN2H 0x31e #define CSR_MSTATEEN3H 0x31f #define CSR_MHPMEVENT3H 0x723 #define CSR_MHPMEVENT4H 0x724 #define CSR_MHPMEVENT5H 0x725 #define CSR_MHPMEVENT6H 0x726 #define CSR_MHPMEVENT7H 0x727 #define CSR_MHPMEVENT8H 0x728 #define CSR_MHPMEVENT9H 0x729 #define CSR_MHPMEVENT10H 0x72a #define CSR_MHPMEVENT11H 0x72b #define CSR_MHPMEVENT12H 0x72c #define CSR_MHPMEVENT13H 0x72d #define CSR_MHPMEVENT14H 0x72e #define CSR_MHPMEVENT15H 0x72f #define CSR_MHPMEVENT16H 0x730 #define CSR_MHPMEVENT17H 0x731 #define CSR_MHPMEVENT18H 0x732 #define CSR_MHPMEVENT19H 0x733 #define CSR_MHPMEVENT20H 0x734 #define CSR_MHPMEVENT21H 0x735 #define CSR_MHPMEVENT22H 0x736 #define CSR_MHPMEVENT23H 0x737 #define CSR_MHPMEVENT24H 0x738 #define CSR_MHPMEVENT25H 0x739 #define CSR_MHPMEVENT26H 0x73a #define CSR_MHPMEVENT27H 0x73b #define CSR_MHPMEVENT28H 0x73c #define CSR_MHPMEVENT29H 0x73d #define CSR_MHPMEVENT30H 0x73e #define CSR_MHPMEVENT31H 0x73f #define CSR_MSECCFGH 0x757 #define CSR_MCYCLEH 0xb80 #define CSR_MINSTRETH 0xb82 #define CSR_MHPMCOUNTER3H 0xb83 #define CSR_MHPMCOUNTER4H 0xb84 #define CSR_MHPMCOUNTER5H 0xb85 #define CSR_MHPMCOUNTER6H 0xb86 #define CSR_MHPMCOUNTER7H 0xb87 #define CSR_MHPMCOUNTER8H 0xb88 #define CSR_MHPMCOUNTER9H 0xb89 #define CSR_MHPMCOUNTER10H 0xb8a #define CSR_MHPMCOUNTER11H 0xb8b #define CSR_MHPMCOUNTER12H 0xb8c #define CSR_MHPMCOUNTER13H 0xb8d #define CSR_MHPMCOUNTER14H 0xb8e #define CSR_MHPMCOUNTER15H 0xb8f #define CSR_MHPMCOUNTER16H 0xb90 #define CSR_MHPMCOUNTER17H 0xb91 #define CSR_MHPMCOUNTER18H 0xb92 #define CSR_MHPMCOUNTER19H 0xb93 #define CSR_MHPMCOUNTER20H 0xb94 #define CSR_MHPMCOUNTER21H 0xb95 #define CSR_MHPMCOUNTER22H 0xb96 #define CSR_MHPMCOUNTER23H 0xb97 #define CSR_MHPMCOUNTER24H 0xb98 #define CSR_MHPMCOUNTER25H 0xb99 #define CSR_MHPMCOUNTER26H 0xb9a #define CSR_MHPMCOUNTER27H 0xb9b #define CSR_MHPMCOUNTER28H 0xb9c #define CSR_MHPMCOUNTER29H 0xb9d #define CSR_MHPMCOUNTER30H 0xb9e #define CSR_MHPMCOUNTER31H 0xb9f #define CAUSE_MISALIGNED_FETCH 0x0 #define CAUSE_FETCH_ACCESS 0x1 #define CAUSE_ILLEGAL_INSTRUCTION 0x2 #define CAUSE_BREAKPOINT 0x3 #define CAUSE_MISALIGNED_LOAD 0x4 #define CAUSE_LOAD_ACCESS 0x5 #define CAUSE_MISALIGNED_STORE 0x6 #define CAUSE_STORE_ACCESS 0x7 #define CAUSE_USER_ECALL 0x8 #define CAUSE_SUPERVISOR_ECALL 0x9 #define CAUSE_VIRTUAL_SUPERVISOR_ECALL 0xa #define CAUSE_MACHINE_ECALL 0xb #define CAUSE_FETCH_PAGE_FAULT 0xc #define CAUSE_LOAD_PAGE_FAULT 0xd #define CAUSE_STORE_PAGE_FAULT 0xf #define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14 #define CAUSE_LOAD_GUEST_PAGE_FAULT 0x15 #define CAUSE_VIRTUAL_INSTRUCTION 0x16 #define CAUSE_STORE_GUEST_PAGE_FAULT 0x17 #define INSN_FIELD_RD 0xf80 #define INSN_FIELD_RT 0xf8000 #define INSN_FIELD_RS1 0xf8000 #define INSN_FIELD_RS2 0x1f00000 #define INSN_FIELD_RS3 0xf8000000 #define INSN_FIELD_AQRL 0x6000000 #define INSN_FIELD_AQ 0x4000000 #define INSN_FIELD_RL 0x2000000 #define INSN_FIELD_FM 0xf0000000 #define INSN_FIELD_PRED 0xf000000 #define INSN_FIELD_SUCC 0xf00000 #define INSN_FIELD_RM 0x7000 #define INSN_FIELD_FUNCT3 0x7000 #define INSN_FIELD_FUNCT2 0x6000000 #define INSN_FIELD_IMM20 0xfffff000 #define INSN_FIELD_JIMM20 0xfffff000 #define INSN_FIELD_IMM12 0xfff00000 #define INSN_FIELD_CSR 0xfff00000 #define INSN_FIELD_IMM12HI 0xfe000000 #define INSN_FIELD_BIMM12HI 0xfe000000 #define INSN_FIELD_IMM12LO 0xf80 #define INSN_FIELD_BIMM12LO 0xf80 #define INSN_FIELD_ZIMM 0xf8000 #define INSN_FIELD_SHAMT 0x7f00000 #define INSN_FIELD_SHAMTW 0x1f00000 #define INSN_FIELD_SHAMTW4 0xf00000 #define INSN_FIELD_SHAMTD 0x3f00000 #define INSN_FIELD_BS 0xc0000000 #define INSN_FIELD_RNUM 0xf00000 #define INSN_FIELD_RC 0x3e000000 #define INSN_FIELD_IMM2 0x300000 #define INSN_FIELD_IMM3 0x700000 #define INSN_FIELD_IMM4 0xf00000 #define INSN_FIELD_IMM5 0x1f00000 #define INSN_FIELD_IMM6 0x3f00000 #define INSN_FIELD_OPCODE 0x7f #define INSN_FIELD_FUNCT7 0xfe000000 #define INSN_FIELD_VD 0xf80 #define INSN_FIELD_VS3 0xf80 #define INSN_FIELD_VS1 0xf8000 #define INSN_FIELD_VS2 0x1f00000 #define INSN_FIELD_VM 0x2000000 #define INSN_FIELD_WD 0x4000000 #define INSN_FIELD_AMOOP 0xf8000000 #define INSN_FIELD_NF 0xe0000000 #define INSN_FIELD_SIMM5 0xf8000 #define INSN_FIELD_ZIMM10 0x3ff00000 #define INSN_FIELD_ZIMM11 0x7ff00000 #define INSN_FIELD_C_NZUIMM10 0x1fe0 #define INSN_FIELD_C_UIMM7LO 0x60 #define INSN_FIELD_C_UIMM7HI 0x1c00 #define INSN_FIELD_C_UIMM8LO 0x60 #define INSN_FIELD_C_UIMM8HI 0x1c00 #define INSN_FIELD_C_UIMM9LO 0x60 #define INSN_FIELD_C_UIMM9HI 0x1c00 #define INSN_FIELD_C_NZIMM6LO 0x7c #define INSN_FIELD_C_NZIMM6HI 0x1000 #define INSN_FIELD_C_IMM6LO 0x7c #define INSN_FIELD_C_IMM6HI 0x1000 #define INSN_FIELD_C_NZIMM10HI 0x1000 #define INSN_FIELD_C_NZIMM10LO 0x7c #define INSN_FIELD_C_NZIMM18HI 0x1000 #define INSN_FIELD_C_NZIMM18LO 0x7c #define INSN_FIELD_C_IMM12 0x1ffc #define INSN_FIELD_C_BIMM9LO 0x7c #define INSN_FIELD_C_BIMM9HI 0x1c00 #define INSN_FIELD_C_NZUIMM5 0x7c #define INSN_FIELD_C_NZUIMM6LO 0x7c #define INSN_FIELD_C_NZUIMM6HI 0x1000 #define INSN_FIELD_C_UIMM8SPLO 0x7c #define INSN_FIELD_C_UIMM8SPHI 0x1000 #define INSN_FIELD_C_UIMM8SP_S 0x1f80 #define INSN_FIELD_C_UIMM10SPLO 0x7c #define INSN_FIELD_C_UIMM10SPHI 0x1000 #define INSN_FIELD_C_UIMM9SPLO 0x7c #define INSN_FIELD_C_UIMM9SPHI 0x1000 #define INSN_FIELD_C_UIMM10SP_S 0x1f80 #define INSN_FIELD_C_UIMM9SP_S 0x1f80 #define INSN_FIELD_RS1_P 0x380 #define INSN_FIELD_RS2_P 0x1c #define INSN_FIELD_RD_P 0x1c #define INSN_FIELD_RD_RS1_N0 0xf80 #define INSN_FIELD_RD_RS1_P 0x380 #define INSN_FIELD_RD_RS1 0xf80 #define INSN_FIELD_RD_N2 0xf80 #define INSN_FIELD_RD_N0 0xf80 #define INSN_FIELD_RS1_N0 0xf80 #define INSN_FIELD_C_RS2_N0 0x7c #define INSN_FIELD_C_RS1_N0 0xf80 #define INSN_FIELD_C_RS2 0x7c #endif #ifdef DECLARE_INSN DECLARE_INSN(add, MATCH_ADD, MASK_ADD) DECLARE_INSN(add16, MATCH_ADD16, MASK_ADD16) DECLARE_INSN(add32, MATCH_ADD32, MASK_ADD32) DECLARE_INSN(add64, MATCH_ADD64, MASK_ADD64) DECLARE_INSN(add8, MATCH_ADD8, MASK_ADD8) DECLARE_INSN(add_uw, MATCH_ADD_UW, MASK_ADD_UW) DECLARE_INSN(addd, MATCH_ADDD, MASK_ADDD) DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) DECLARE_INSN(addid, MATCH_ADDID, MASK_ADDID) DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) DECLARE_INSN(aes32dsi, MATCH_AES32DSI, MASK_AES32DSI) DECLARE_INSN(aes32dsmi, MATCH_AES32DSMI, MASK_AES32DSMI) DECLARE_INSN(aes32esi, MATCH_AES32ESI, MASK_AES32ESI) DECLARE_INSN(aes32esmi, MATCH_AES32ESMI, MASK_AES32ESMI) DECLARE_INSN(aes64ds, MATCH_AES64DS, MASK_AES64DS) DECLARE_INSN(aes64dsm, MATCH_AES64DSM, MASK_AES64DSM) DECLARE_INSN(aes64es, MATCH_AES64ES, MASK_AES64ES) DECLARE_INSN(aes64esm, MATCH_AES64ESM, MASK_AES64ESM) DECLARE_INSN(aes64im, MATCH_AES64IM, MASK_AES64IM) DECLARE_INSN(aes64ks1i, MATCH_AES64KS1I, MASK_AES64KS1I) DECLARE_INSN(aes64ks2, MATCH_AES64KS2, MASK_AES64KS2) DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) DECLARE_INSN(and, MATCH_AND, MASK_AND) DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) DECLARE_INSN(andn, MATCH_ANDN, MASK_ANDN) DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) DECLARE_INSN(ave, MATCH_AVE, MASK_AVE) DECLARE_INSN(bclr, MATCH_BCLR, MASK_BCLR) DECLARE_INSN(bclri, MATCH_BCLRI, MASK_BCLRI) DECLARE_INSN(bcompress, MATCH_BCOMPRESS, MASK_BCOMPRESS) DECLARE_INSN(bcompressw, MATCH_BCOMPRESSW, MASK_BCOMPRESSW) DECLARE_INSN(bdecompress, MATCH_BDECOMPRESS, MASK_BDECOMPRESS) DECLARE_INSN(bdecompressw, MATCH_BDECOMPRESSW, MASK_BDECOMPRESSW) DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) DECLARE_INSN(bext, MATCH_BEXT, MASK_BEXT) DECLARE_INSN(bexti, MATCH_BEXTI, MASK_BEXTI) DECLARE_INSN(bfp, MATCH_BFP, MASK_BFP) DECLARE_INSN(bfpw, MATCH_BFPW, MASK_BFPW) DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) DECLARE_INSN(binv, MATCH_BINV, MASK_BINV) DECLARE_INSN(binvi, MATCH_BINVI, MASK_BINVI) DECLARE_INSN(bitrev, MATCH_BITREV, MASK_BITREV) DECLARE_INSN(bitrevi, MATCH_BITREVI, MASK_BITREVI) DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) DECLARE_INSN(bmatflip, MATCH_BMATFLIP, MASK_BMATFLIP) DECLARE_INSN(bmator, MATCH_BMATOR, MASK_BMATOR) DECLARE_INSN(bmatxor, MATCH_BMATXOR, MASK_BMATXOR) DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) DECLARE_INSN(bpick, MATCH_BPICK, MASK_BPICK) DECLARE_INSN(bset, MATCH_BSET, MASK_BSET) DECLARE_INSN(bseti, MATCH_BSETI, MASK_BSETI) DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) DECLARE_INSN(c_lq, MATCH_C_LQ, MASK_C_LQ) DECLARE_INSN(c_lqsp, MATCH_C_LQSP, MASK_C_LQSP) DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) DECLARE_INSN(c_sq, MATCH_C_SQ, MASK_C_SQ) DECLARE_INSN(c_sqsp, MATCH_C_SQSP, MASK_C_SQSP) DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) DECLARE_INSN(cbo_clean, MATCH_CBO_CLEAN, MASK_CBO_CLEAN) DECLARE_INSN(cbo_flush, MATCH_CBO_FLUSH, MASK_CBO_FLUSH) DECLARE_INSN(cbo_inval, MATCH_CBO_INVAL, MASK_CBO_INVAL) DECLARE_INSN(cbo_zero, MATCH_CBO_ZERO, MASK_CBO_ZERO) DECLARE_INSN(clmul, MATCH_CLMUL, MASK_CLMUL) DECLARE_INSN(clmulh, MATCH_CLMULH, MASK_CLMULH) DECLARE_INSN(clmulr, MATCH_CLMULR, MASK_CLMULR) DECLARE_INSN(clo16, MATCH_CLO16, MASK_CLO16) DECLARE_INSN(clo32, MATCH_CLO32, MASK_CLO32) DECLARE_INSN(clo8, MATCH_CLO8, MASK_CLO8) DECLARE_INSN(clrs16, MATCH_CLRS16, MASK_CLRS16) DECLARE_INSN(clrs32, MATCH_CLRS32, MASK_CLRS32) DECLARE_INSN(clrs8, MATCH_CLRS8, MASK_CLRS8) DECLARE_INSN(clz, MATCH_CLZ, MASK_CLZ) DECLARE_INSN(clz16, MATCH_CLZ16, MASK_CLZ16) DECLARE_INSN(clz32, MATCH_CLZ32, MASK_CLZ32) DECLARE_INSN(clz8, MATCH_CLZ8, MASK_CLZ8) DECLARE_INSN(clzw, MATCH_CLZW, MASK_CLZW) DECLARE_INSN(cmix, MATCH_CMIX, MASK_CMIX) DECLARE_INSN(cmov, MATCH_CMOV, MASK_CMOV) DECLARE_INSN(cmpeq16, MATCH_CMPEQ16, MASK_CMPEQ16) DECLARE_INSN(cmpeq8, MATCH_CMPEQ8, MASK_CMPEQ8) DECLARE_INSN(cpop, MATCH_CPOP, MASK_CPOP) DECLARE_INSN(cpopw, MATCH_CPOPW, MASK_CPOPW) DECLARE_INSN(cras16, MATCH_CRAS16, MASK_CRAS16) DECLARE_INSN(cras32, MATCH_CRAS32, MASK_CRAS32) DECLARE_INSN(crc32_b, MATCH_CRC32_B, MASK_CRC32_B) DECLARE_INSN(crc32_d, MATCH_CRC32_D, MASK_CRC32_D) DECLARE_INSN(crc32_h, MATCH_CRC32_H, MASK_CRC32_H) DECLARE_INSN(crc32_w, MATCH_CRC32_W, MASK_CRC32_W) DECLARE_INSN(crc32c_b, MATCH_CRC32C_B, MASK_CRC32C_B) DECLARE_INSN(crc32c_d, MATCH_CRC32C_D, MASK_CRC32C_D) DECLARE_INSN(crc32c_h, MATCH_CRC32C_H, MASK_CRC32C_H) DECLARE_INSN(crc32c_w, MATCH_CRC32C_W, MASK_CRC32C_W) DECLARE_INSN(crsa16, MATCH_CRSA16, MASK_CRSA16) DECLARE_INSN(crsa32, MATCH_CRSA32, MASK_CRSA32) DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) DECLARE_INSN(ctz, MATCH_CTZ, MASK_CTZ) DECLARE_INSN(ctzw, MATCH_CTZW, MASK_CTZW) DECLARE_INSN(div, MATCH_DIV, MASK_DIV) DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) DECLARE_INSN(fadd_h, MATCH_FADD_H, MASK_FADD_H) DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q) DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) DECLARE_INSN(fclass_h, MATCH_FCLASS_H, MASK_FCLASS_H) DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q) DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) DECLARE_INSN(fcvt_d_h, MATCH_FCVT_D_H, MASK_FCVT_D_H) DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q) DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) DECLARE_INSN(fcvt_h_d, MATCH_FCVT_H_D, MASK_FCVT_H_D) DECLARE_INSN(fcvt_h_l, MATCH_FCVT_H_L, MASK_FCVT_H_L) DECLARE_INSN(fcvt_h_lu, MATCH_FCVT_H_LU, MASK_FCVT_H_LU) DECLARE_INSN(fcvt_h_q, MATCH_FCVT_H_Q, MASK_FCVT_H_Q) DECLARE_INSN(fcvt_h_s, MATCH_FCVT_H_S, MASK_FCVT_H_S) DECLARE_INSN(fcvt_h_w, MATCH_FCVT_H_W, MASK_FCVT_H_W) DECLARE_INSN(fcvt_h_wu, MATCH_FCVT_H_WU, MASK_FCVT_H_WU) DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) DECLARE_INSN(fcvt_l_h, MATCH_FCVT_L_H, MASK_FCVT_L_H) DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q) DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) DECLARE_INSN(fcvt_lu_h, MATCH_FCVT_LU_H, MASK_FCVT_LU_H) DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q) DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D) DECLARE_INSN(fcvt_q_h, MATCH_FCVT_Q_H, MASK_FCVT_Q_H) DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L) DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU) DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S) DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W) DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU) DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) DECLARE_INSN(fcvt_s_h, MATCH_FCVT_S_H, MASK_FCVT_S_H) DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q) DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) DECLARE_INSN(fcvt_w_h, MATCH_FCVT_W_H, MASK_FCVT_W_H) DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q) DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) DECLARE_INSN(fcvt_wu_h, MATCH_FCVT_WU_H, MASK_FCVT_WU_H) DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q) DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) DECLARE_INSN(fdiv_h, MATCH_FDIV_H, MASK_FDIV_H) DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q) DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) DECLARE_INSN(feq_h, MATCH_FEQ_H, MASK_FEQ_H) DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q) DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) DECLARE_INSN(fle_h, MATCH_FLE_H, MASK_FLE_H) DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q) DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) DECLARE_INSN(flh, MATCH_FLH, MASK_FLH) DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ) DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) DECLARE_INSN(flt_h, MATCH_FLT_H, MASK_FLT_H) DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q) DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) DECLARE_INSN(fmadd_h, MATCH_FMADD_H, MASK_FMADD_H) DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q) DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) DECLARE_INSN(fmax_h, MATCH_FMAX_H, MASK_FMAX_H) DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q) DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) DECLARE_INSN(fmin_h, MATCH_FMIN_H, MASK_FMIN_H) DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q) DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) DECLARE_INSN(fmsub_h, MATCH_FMSUB_H, MASK_FMSUB_H) DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q) DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) DECLARE_INSN(fmul_h, MATCH_FMUL_H, MASK_FMUL_H) DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q) DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) DECLARE_INSN(fmv_h_x, MATCH_FMV_H_X, MASK_FMV_H_X) DECLARE_INSN(fmv_w_x, MATCH_FMV_W_X, MASK_FMV_W_X) DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) DECLARE_INSN(fmv_x_h, MATCH_FMV_X_H, MASK_FMV_X_H) DECLARE_INSN(fmv_x_w, MATCH_FMV_X_W, MASK_FMV_X_W) DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) DECLARE_INSN(fnmadd_h, MATCH_FNMADD_H, MASK_FNMADD_H) DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q) DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) DECLARE_INSN(fnmsub_h, MATCH_FNMSUB_H, MASK_FNMSUB_H) DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q) DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) DECLARE_INSN(fsgnj_h, MATCH_FSGNJ_H, MASK_FSGNJ_H) DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q) DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) DECLARE_INSN(fsgnjn_h, MATCH_FSGNJN_H, MASK_FSGNJN_H) DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q) DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) DECLARE_INSN(fsgnjx_h, MATCH_FSGNJX_H, MASK_FSGNJX_H) DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q) DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) DECLARE_INSN(fsh, MATCH_FSH, MASK_FSH) DECLARE_INSN(fsl, MATCH_FSL, MASK_FSL) DECLARE_INSN(fslw, MATCH_FSLW, MASK_FSLW) DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ) DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) DECLARE_INSN(fsqrt_h, MATCH_FSQRT_H, MASK_FSQRT_H) DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q) DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) DECLARE_INSN(fsr, MATCH_FSR, MASK_FSR) DECLARE_INSN(fsri, MATCH_FSRI, MASK_FSRI) DECLARE_INSN(fsriw, MATCH_FSRIW, MASK_FSRIW) DECLARE_INSN(fsrw, MATCH_FSRW, MASK_FSRW) DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) DECLARE_INSN(fsub_h, MATCH_FSUB_H, MASK_FSUB_H) DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q) DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) DECLARE_INSN(gorc, MATCH_GORC, MASK_GORC) DECLARE_INSN(gorci, MATCH_GORCI, MASK_GORCI) DECLARE_INSN(gorciw, MATCH_GORCIW, MASK_GORCIW) DECLARE_INSN(gorcw, MATCH_GORCW, MASK_GORCW) DECLARE_INSN(grev, MATCH_GREV, MASK_GREV) DECLARE_INSN(grevi, MATCH_GREVI, MASK_GREVI) DECLARE_INSN(greviw, MATCH_GREVIW, MASK_GREVIW) DECLARE_INSN(grevw, MATCH_GREVW, MASK_GREVW) DECLARE_INSN(hfence_gvma, MATCH_HFENCE_GVMA, MASK_HFENCE_GVMA) DECLARE_INSN(hfence_vvma, MATCH_HFENCE_VVMA, MASK_HFENCE_VVMA) DECLARE_INSN(hinval_gvma, MATCH_HINVAL_GVMA, MASK_HINVAL_GVMA) DECLARE_INSN(hinval_vvma, MATCH_HINVAL_VVMA, MASK_HINVAL_VVMA) DECLARE_INSN(hlv_b, MATCH_HLV_B, MASK_HLV_B) DECLARE_INSN(hlv_bu, MATCH_HLV_BU, MASK_HLV_BU) DECLARE_INSN(hlv_d, MATCH_HLV_D, MASK_HLV_D) DECLARE_INSN(hlv_h, MATCH_HLV_H, MASK_HLV_H) DECLARE_INSN(hlv_hu, MATCH_HLV_HU, MASK_HLV_HU) DECLARE_INSN(hlv_w, MATCH_HLV_W, MASK_HLV_W) DECLARE_INSN(hlv_wu, MATCH_HLV_WU, MASK_HLV_WU) DECLARE_INSN(hlvx_hu, MATCH_HLVX_HU, MASK_HLVX_HU) DECLARE_INSN(hlvx_wu, MATCH_HLVX_WU, MASK_HLVX_WU) DECLARE_INSN(hsv_b, MATCH_HSV_B, MASK_HSV_B) DECLARE_INSN(hsv_d, MATCH_HSV_D, MASK_HSV_D) DECLARE_INSN(hsv_h, MATCH_HSV_H, MASK_HSV_H) DECLARE_INSN(hsv_w, MATCH_HSV_W, MASK_HSV_W) DECLARE_INSN(insb, MATCH_INSB, MASK_INSB) DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) DECLARE_INSN(kabs16, MATCH_KABS16, MASK_KABS16) DECLARE_INSN(kabs32, MATCH_KABS32, MASK_KABS32) DECLARE_INSN(kabs8, MATCH_KABS8, MASK_KABS8) DECLARE_INSN(kabsw, MATCH_KABSW, MASK_KABSW) DECLARE_INSN(kadd16, MATCH_KADD16, MASK_KADD16) DECLARE_INSN(kadd32, MATCH_KADD32, MASK_KADD32) DECLARE_INSN(kadd64, MATCH_KADD64, MASK_KADD64) DECLARE_INSN(kadd8, MATCH_KADD8, MASK_KADD8) DECLARE_INSN(kaddh, MATCH_KADDH, MASK_KADDH) DECLARE_INSN(kaddw, MATCH_KADDW, MASK_KADDW) DECLARE_INSN(kcras16, MATCH_KCRAS16, MASK_KCRAS16) DECLARE_INSN(kcras32, MATCH_KCRAS32, MASK_KCRAS32) DECLARE_INSN(kcrsa16, MATCH_KCRSA16, MASK_KCRSA16) DECLARE_INSN(kcrsa32, MATCH_KCRSA32, MASK_KCRSA32) DECLARE_INSN(kdmabb, MATCH_KDMABB, MASK_KDMABB) DECLARE_INSN(kdmabb16, MATCH_KDMABB16, MASK_KDMABB16) DECLARE_INSN(kdmabt, MATCH_KDMABT, MASK_KDMABT) DECLARE_INSN(kdmabt16, MATCH_KDMABT16, MASK_KDMABT16) DECLARE_INSN(kdmatt, MATCH_KDMATT, MASK_KDMATT) DECLARE_INSN(kdmatt16, MATCH_KDMATT16, MASK_KDMATT16) DECLARE_INSN(kdmbb, MATCH_KDMBB, MASK_KDMBB) DECLARE_INSN(kdmbb16, MATCH_KDMBB16, MASK_KDMBB16) DECLARE_INSN(kdmbt, MATCH_KDMBT, MASK_KDMBT) DECLARE_INSN(kdmbt16, MATCH_KDMBT16, MASK_KDMBT16) DECLARE_INSN(kdmtt, MATCH_KDMTT, MASK_KDMTT) DECLARE_INSN(kdmtt16, MATCH_KDMTT16, MASK_KDMTT16) DECLARE_INSN(khm16, MATCH_KHM16, MASK_KHM16) DECLARE_INSN(khm8, MATCH_KHM8, MASK_KHM8) DECLARE_INSN(khmbb, MATCH_KHMBB, MASK_KHMBB) DECLARE_INSN(khmbb16, MATCH_KHMBB16, MASK_KHMBB16) DECLARE_INSN(khmbt, MATCH_KHMBT, MASK_KHMBT) DECLARE_INSN(khmbt16, MATCH_KHMBT16, MASK_KHMBT16) DECLARE_INSN(khmtt, MATCH_KHMTT, MASK_KHMTT) DECLARE_INSN(khmtt16, MATCH_KHMTT16, MASK_KHMTT16) DECLARE_INSN(khmx16, MATCH_KHMX16, MASK_KHMX16) DECLARE_INSN(khmx8, MATCH_KHMX8, MASK_KHMX8) DECLARE_INSN(kmabb, MATCH_KMABB, MASK_KMABB) DECLARE_INSN(kmabb32, MATCH_KMABB32, MASK_KMABB32) DECLARE_INSN(kmabt, MATCH_KMABT, MASK_KMABT) DECLARE_INSN(kmabt32, MATCH_KMABT32, MASK_KMABT32) DECLARE_INSN(kmada, MATCH_KMADA, MASK_KMADA) DECLARE_INSN(kmadrs, MATCH_KMADRS, MASK_KMADRS) DECLARE_INSN(kmadrs32, MATCH_KMADRS32, MASK_KMADRS32) DECLARE_INSN(kmads, MATCH_KMADS, MASK_KMADS) DECLARE_INSN(kmads32, MATCH_KMADS32, MASK_KMADS32) DECLARE_INSN(kmar64, MATCH_KMAR64, MASK_KMAR64) DECLARE_INSN(kmatt, MATCH_KMATT, MASK_KMATT) DECLARE_INSN(kmatt32, MATCH_KMATT32, MASK_KMATT32) DECLARE_INSN(kmaxda, MATCH_KMAXDA, MASK_KMAXDA) DECLARE_INSN(kmaxda32, MATCH_KMAXDA32, MASK_KMAXDA32) DECLARE_INSN(kmaxds, MATCH_KMAXDS, MASK_KMAXDS) DECLARE_INSN(kmaxds32, MATCH_KMAXDS32, MASK_KMAXDS32) DECLARE_INSN(kmda, MATCH_KMDA, MASK_KMDA) DECLARE_INSN(kmda32, MATCH_KMDA32, MASK_KMDA32) DECLARE_INSN(kmmac, MATCH_KMMAC, MASK_KMMAC) DECLARE_INSN(kmmac_u, MATCH_KMMAC_U, MASK_KMMAC_U) DECLARE_INSN(kmmawb, MATCH_KMMAWB, MASK_KMMAWB) DECLARE_INSN(kmmawb2, MATCH_KMMAWB2, MASK_KMMAWB2) DECLARE_INSN(kmmawb2_u, MATCH_KMMAWB2_U, MASK_KMMAWB2_U) DECLARE_INSN(kmmawb_u, MATCH_KMMAWB_U, MASK_KMMAWB_U) DECLARE_INSN(kmmawt, MATCH_KMMAWT, MASK_KMMAWT) DECLARE_INSN(kmmawt2, MATCH_KMMAWT2, MASK_KMMAWT2) DECLARE_INSN(kmmawt2_u, MATCH_KMMAWT2_U, MASK_KMMAWT2_U) DECLARE_INSN(kmmawt_u, MATCH_KMMAWT_U, MASK_KMMAWT_U) DECLARE_INSN(kmmsb, MATCH_KMMSB, MASK_KMMSB) DECLARE_INSN(kmmsb_u, MATCH_KMMSB_U, MASK_KMMSB_U) DECLARE_INSN(kmmwb2, MATCH_KMMWB2, MASK_KMMWB2) DECLARE_INSN(kmmwb2_u, MATCH_KMMWB2_U, MASK_KMMWB2_U) DECLARE_INSN(kmmwt2, MATCH_KMMWT2, MASK_KMMWT2) DECLARE_INSN(kmmwt2_u, MATCH_KMMWT2_U, MASK_KMMWT2_U) DECLARE_INSN(kmsda, MATCH_KMSDA, MASK_KMSDA) DECLARE_INSN(kmsda32, MATCH_KMSDA32, MASK_KMSDA32) DECLARE_INSN(kmsr64, MATCH_KMSR64, MASK_KMSR64) DECLARE_INSN(kmsxda, MATCH_KMSXDA, MASK_KMSXDA) DECLARE_INSN(kmsxda32, MATCH_KMSXDA32, MASK_KMSXDA32) DECLARE_INSN(kmxda, MATCH_KMXDA, MASK_KMXDA) DECLARE_INSN(kmxda32, MATCH_KMXDA32, MASK_KMXDA32) DECLARE_INSN(ksll16, MATCH_KSLL16, MASK_KSLL16) DECLARE_INSN(ksll32, MATCH_KSLL32, MASK_KSLL32) DECLARE_INSN(ksll8, MATCH_KSLL8, MASK_KSLL8) DECLARE_INSN(kslli16, MATCH_KSLLI16, MASK_KSLLI16) DECLARE_INSN(kslli32, MATCH_KSLLI32, MASK_KSLLI32) DECLARE_INSN(kslli8, MATCH_KSLLI8, MASK_KSLLI8) DECLARE_INSN(kslliw, MATCH_KSLLIW, MASK_KSLLIW) DECLARE_INSN(ksllw, MATCH_KSLLW, MASK_KSLLW) DECLARE_INSN(kslra16, MATCH_KSLRA16, MASK_KSLRA16) DECLARE_INSN(kslra16_u, MATCH_KSLRA16_U, MASK_KSLRA16_U) DECLARE_INSN(kslra32, MATCH_KSLRA32, MASK_KSLRA32) DECLARE_INSN(kslra32_u, MATCH_KSLRA32_U, MASK_KSLRA32_U) DECLARE_INSN(kslra8, MATCH_KSLRA8, MASK_KSLRA8) DECLARE_INSN(kslra8_u, MATCH_KSLRA8_U, MASK_KSLRA8_U) DECLARE_INSN(kslraw, MATCH_KSLRAW, MASK_KSLRAW) DECLARE_INSN(kslraw_u, MATCH_KSLRAW_U, MASK_KSLRAW_U) DECLARE_INSN(kstas16, MATCH_KSTAS16, MASK_KSTAS16) DECLARE_INSN(kstas32, MATCH_KSTAS32, MASK_KSTAS32) DECLARE_INSN(kstsa16, MATCH_KSTSA16, MASK_KSTSA16) DECLARE_INSN(kstsa32, MATCH_KSTSA32, MASK_KSTSA32) DECLARE_INSN(ksub16, MATCH_KSUB16, MASK_KSUB16) DECLARE_INSN(ksub32, MATCH_KSUB32, MASK_KSUB32) DECLARE_INSN(ksub64, MATCH_KSUB64, MASK_KSUB64) DECLARE_INSN(ksub8, MATCH_KSUB8, MASK_KSUB8) DECLARE_INSN(ksubh, MATCH_KSUBH, MASK_KSUBH) DECLARE_INSN(ksubw, MATCH_KSUBW, MASK_KSUBW) DECLARE_INSN(kwmmul, MATCH_KWMMUL, MASK_KWMMUL) DECLARE_INSN(kwmmul_u, MATCH_KWMMUL_U, MASK_KWMMUL_U) DECLARE_INSN(lb, MATCH_LB, MASK_LB) DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) DECLARE_INSN(ld, MATCH_LD, MASK_LD) DECLARE_INSN(ldu, MATCH_LDU, MASK_LDU) DECLARE_INSN(lh, MATCH_LH, MASK_LH) DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) DECLARE_INSN(lq, MATCH_LQ, MASK_LQ) DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) DECLARE_INSN(lw, MATCH_LW, MASK_LW) DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) DECLARE_INSN(maddr32, MATCH_MADDR32, MASK_MADDR32) DECLARE_INSN(max, MATCH_MAX, MASK_MAX) DECLARE_INSN(maxu, MATCH_MAXU, MASK_MAXU) DECLARE_INSN(maxw, MATCH_MAXW, MASK_MAXW) DECLARE_INSN(min, MATCH_MIN, MASK_MIN) DECLARE_INSN(minu, MATCH_MINU, MASK_MINU) DECLARE_INSN(minw, MATCH_MINW, MASK_MINW) DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) DECLARE_INSN(msubr32, MATCH_MSUBR32, MASK_MSUBR32) DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) DECLARE_INSN(mulr64, MATCH_MULR64, MASK_MULR64) DECLARE_INSN(mulsr64, MATCH_MULSR64, MASK_MULSR64) DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) DECLARE_INSN(or, MATCH_OR, MASK_OR) DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) DECLARE_INSN(orn, MATCH_ORN, MASK_ORN) DECLARE_INSN(pack, MATCH_PACK, MASK_PACK) DECLARE_INSN(packh, MATCH_PACKH, MASK_PACKH) DECLARE_INSN(packu, MATCH_PACKU, MASK_PACKU) DECLARE_INSN(packuw, MATCH_PACKUW, MASK_PACKUW) DECLARE_INSN(packw, MATCH_PACKW, MASK_PACKW) DECLARE_INSN(pause, MATCH_PAUSE, MASK_PAUSE) DECLARE_INSN(pbsad, MATCH_PBSAD, MASK_PBSAD) DECLARE_INSN(pbsada, MATCH_PBSADA, MASK_PBSADA) DECLARE_INSN(pkbb16, MATCH_PKBB16, MASK_PKBB16) DECLARE_INSN(pkbb32, MATCH_PKBB32, MASK_PKBB32) DECLARE_INSN(pkbt16, MATCH_PKBT16, MASK_PKBT16) DECLARE_INSN(pkbt32, MATCH_PKBT32, MASK_PKBT32) DECLARE_INSN(pktb16, MATCH_PKTB16, MASK_PKTB16) DECLARE_INSN(pktb32, MATCH_PKTB32, MASK_PKTB32) DECLARE_INSN(pktt16, MATCH_PKTT16, MASK_PKTT16) DECLARE_INSN(pktt32, MATCH_PKTT32, MASK_PKTT32) DECLARE_INSN(prefetch_i, MATCH_PREFETCH_I, MASK_PREFETCH_I) DECLARE_INSN(prefetch_r, MATCH_PREFETCH_R, MASK_PREFETCH_R) DECLARE_INSN(prefetch_w, MATCH_PREFETCH_W, MASK_PREFETCH_W) DECLARE_INSN(radd16, MATCH_RADD16, MASK_RADD16) DECLARE_INSN(radd32, MATCH_RADD32, MASK_RADD32) DECLARE_INSN(radd64, MATCH_RADD64, MASK_RADD64) DECLARE_INSN(radd8, MATCH_RADD8, MASK_RADD8) DECLARE_INSN(raddw, MATCH_RADDW, MASK_RADDW) DECLARE_INSN(rcras16, MATCH_RCRAS16, MASK_RCRAS16) DECLARE_INSN(rcras32, MATCH_RCRAS32, MASK_RCRAS32) DECLARE_INSN(rcrsa16, MATCH_RCRSA16, MASK_RCRSA16) DECLARE_INSN(rcrsa32, MATCH_RCRSA32, MASK_RCRSA32) DECLARE_INSN(rem, MATCH_REM, MASK_REM) DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) DECLARE_INSN(rol, MATCH_ROL, MASK_ROL) DECLARE_INSN(rolw, MATCH_ROLW, MASK_ROLW) DECLARE_INSN(ror, MATCH_ROR, MASK_ROR) DECLARE_INSN(rori, MATCH_RORI, MASK_RORI) DECLARE_INSN(roriw, MATCH_RORIW, MASK_RORIW) DECLARE_INSN(rorw, MATCH_RORW, MASK_RORW) DECLARE_INSN(rstas16, MATCH_RSTAS16, MASK_RSTAS16) DECLARE_INSN(rstas32, MATCH_RSTAS32, MASK_RSTAS32) DECLARE_INSN(rstsa16, MATCH_RSTSA16, MASK_RSTSA16) DECLARE_INSN(rstsa32, MATCH_RSTSA32, MASK_RSTSA32) DECLARE_INSN(rsub16, MATCH_RSUB16, MASK_RSUB16) DECLARE_INSN(rsub32, MATCH_RSUB32, MASK_RSUB32) DECLARE_INSN(rsub64, MATCH_RSUB64, MASK_RSUB64) DECLARE_INSN(rsub8, MATCH_RSUB8, MASK_RSUB8) DECLARE_INSN(rsubw, MATCH_RSUBW, MASK_RSUBW) DECLARE_INSN(sb, MATCH_SB, MASK_SB) DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) DECLARE_INSN(sclip16, MATCH_SCLIP16, MASK_SCLIP16) DECLARE_INSN(sclip32, MATCH_SCLIP32, MASK_SCLIP32) DECLARE_INSN(sclip8, MATCH_SCLIP8, MASK_SCLIP8) DECLARE_INSN(scmple16, MATCH_SCMPLE16, MASK_SCMPLE16) DECLARE_INSN(scmple8, MATCH_SCMPLE8, MASK_SCMPLE8) DECLARE_INSN(scmplt16, MATCH_SCMPLT16, MASK_SCMPLT16) DECLARE_INSN(scmplt8, MATCH_SCMPLT8, MASK_SCMPLT8) DECLARE_INSN(sd, MATCH_SD, MASK_SD) DECLARE_INSN(sext_b, MATCH_SEXT_B, MASK_SEXT_B) DECLARE_INSN(sext_h, MATCH_SEXT_H, MASK_SEXT_H) DECLARE_INSN(sfence_inval_ir, MATCH_SFENCE_INVAL_IR, MASK_SFENCE_INVAL_IR) DECLARE_INSN(sfence_vma, MATCH_SFENCE_VMA, MASK_SFENCE_VMA) DECLARE_INSN(sfence_w_inval, MATCH_SFENCE_W_INVAL, MASK_SFENCE_W_INVAL) DECLARE_INSN(sh, MATCH_SH, MASK_SH) DECLARE_INSN(sh1add, MATCH_SH1ADD, MASK_SH1ADD) DECLARE_INSN(sh1add_uw, MATCH_SH1ADD_UW, MASK_SH1ADD_UW) DECLARE_INSN(sh2add, MATCH_SH2ADD, MASK_SH2ADD) DECLARE_INSN(sh2add_uw, MATCH_SH2ADD_UW, MASK_SH2ADD_UW) DECLARE_INSN(sh3add, MATCH_SH3ADD, MASK_SH3ADD) DECLARE_INSN(sh3add_uw, MATCH_SH3ADD_UW, MASK_SH3ADD_UW) DECLARE_INSN(sha256sig0, MATCH_SHA256SIG0, MASK_SHA256SIG0) DECLARE_INSN(sha256sig1, MATCH_SHA256SIG1, MASK_SHA256SIG1) DECLARE_INSN(sha256sum0, MATCH_SHA256SUM0, MASK_SHA256SUM0) DECLARE_INSN(sha256sum1, MATCH_SHA256SUM1, MASK_SHA256SUM1) DECLARE_INSN(sha512sig0, MATCH_SHA512SIG0, MASK_SHA512SIG0) DECLARE_INSN(sha512sig0h, MATCH_SHA512SIG0H, MASK_SHA512SIG0H) DECLARE_INSN(sha512sig0l, MATCH_SHA512SIG0L, MASK_SHA512SIG0L) DECLARE_INSN(sha512sig1, MATCH_SHA512SIG1, MASK_SHA512SIG1) DECLARE_INSN(sha512sig1h, MATCH_SHA512SIG1H, MASK_SHA512SIG1H) DECLARE_INSN(sha512sig1l, MATCH_SHA512SIG1L, MASK_SHA512SIG1L) DECLARE_INSN(sha512sum0, MATCH_SHA512SUM0, MASK_SHA512SUM0) DECLARE_INSN(sha512sum0r, MATCH_SHA512SUM0R, MASK_SHA512SUM0R) DECLARE_INSN(sha512sum1, MATCH_SHA512SUM1, MASK_SHA512SUM1) DECLARE_INSN(sha512sum1r, MATCH_SHA512SUM1R, MASK_SHA512SUM1R) DECLARE_INSN(shfl, MATCH_SHFL, MASK_SHFL) DECLARE_INSN(shfli, MATCH_SHFLI, MASK_SHFLI) DECLARE_INSN(shflw, MATCH_SHFLW, MASK_SHFLW) DECLARE_INSN(sinval_vma, MATCH_SINVAL_VMA, MASK_SINVAL_VMA) DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) DECLARE_INSN(sll16, MATCH_SLL16, MASK_SLL16) DECLARE_INSN(sll32, MATCH_SLL32, MASK_SLL32) DECLARE_INSN(sll8, MATCH_SLL8, MASK_SLL8) DECLARE_INSN(slld, MATCH_SLLD, MASK_SLLD) DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) DECLARE_INSN(slli16, MATCH_SLLI16, MASK_SLLI16) DECLARE_INSN(slli32, MATCH_SLLI32, MASK_SLLI32) DECLARE_INSN(slli8, MATCH_SLLI8, MASK_SLLI8) DECLARE_INSN(slli_uw, MATCH_SLLI_UW, MASK_SLLI_UW) DECLARE_INSN(sllid, MATCH_SLLID, MASK_SLLID) DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) DECLARE_INSN(slo, MATCH_SLO, MASK_SLO) DECLARE_INSN(sloi, MATCH_SLOI, MASK_SLOI) DECLARE_INSN(sloiw, MATCH_SLOIW, MASK_SLOIW) DECLARE_INSN(slow, MATCH_SLOW, MASK_SLOW) DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) DECLARE_INSN(sm3p0, MATCH_SM3P0, MASK_SM3P0) DECLARE_INSN(sm3p1, MATCH_SM3P1, MASK_SM3P1) DECLARE_INSN(sm4ed, MATCH_SM4ED, MASK_SM4ED) DECLARE_INSN(sm4ks, MATCH_SM4KS, MASK_SM4KS) DECLARE_INSN(smal, MATCH_SMAL, MASK_SMAL) DECLARE_INSN(smalbb, MATCH_SMALBB, MASK_SMALBB) DECLARE_INSN(smalbt, MATCH_SMALBT, MASK_SMALBT) DECLARE_INSN(smalda, MATCH_SMALDA, MASK_SMALDA) DECLARE_INSN(smaldrs, MATCH_SMALDRS, MASK_SMALDRS) DECLARE_INSN(smalds, MATCH_SMALDS, MASK_SMALDS) DECLARE_INSN(smaltt, MATCH_SMALTT, MASK_SMALTT) DECLARE_INSN(smalxda, MATCH_SMALXDA, MASK_SMALXDA) DECLARE_INSN(smalxds, MATCH_SMALXDS, MASK_SMALXDS) DECLARE_INSN(smaqa, MATCH_SMAQA, MASK_SMAQA) DECLARE_INSN(smaqa_su, MATCH_SMAQA_SU, MASK_SMAQA_SU) DECLARE_INSN(smar64, MATCH_SMAR64, MASK_SMAR64) DECLARE_INSN(smax16, MATCH_SMAX16, MASK_SMAX16) DECLARE_INSN(smax32, MATCH_SMAX32, MASK_SMAX32) DECLARE_INSN(smax8, MATCH_SMAX8, MASK_SMAX8) DECLARE_INSN(smbb16, MATCH_SMBB16, MASK_SMBB16) DECLARE_INSN(smbt16, MATCH_SMBT16, MASK_SMBT16) DECLARE_INSN(smbt32, MATCH_SMBT32, MASK_SMBT32) DECLARE_INSN(smdrs, MATCH_SMDRS, MASK_SMDRS) DECLARE_INSN(smdrs32, MATCH_SMDRS32, MASK_SMDRS32) DECLARE_INSN(smds, MATCH_SMDS, MASK_SMDS) DECLARE_INSN(smds32, MATCH_SMDS32, MASK_SMDS32) DECLARE_INSN(smin16, MATCH_SMIN16, MASK_SMIN16) DECLARE_INSN(smin32, MATCH_SMIN32, MASK_SMIN32) DECLARE_INSN(smin8, MATCH_SMIN8, MASK_SMIN8) DECLARE_INSN(smmul, MATCH_SMMUL, MASK_SMMUL) DECLARE_INSN(smmul_u, MATCH_SMMUL_U, MASK_SMMUL_U) DECLARE_INSN(smmwb, MATCH_SMMWB, MASK_SMMWB) DECLARE_INSN(smmwb_u, MATCH_SMMWB_U, MASK_SMMWB_U) DECLARE_INSN(smmwt, MATCH_SMMWT, MASK_SMMWT) DECLARE_INSN(smmwt_u, MATCH_SMMWT_U, MASK_SMMWT_U) DECLARE_INSN(smslda, MATCH_SMSLDA, MASK_SMSLDA) DECLARE_INSN(smslxda, MATCH_SMSLXDA, MASK_SMSLXDA) DECLARE_INSN(smsr64, MATCH_SMSR64, MASK_SMSR64) DECLARE_INSN(smtt16, MATCH_SMTT16, MASK_SMTT16) DECLARE_INSN(smtt32, MATCH_SMTT32, MASK_SMTT32) DECLARE_INSN(smul16, MATCH_SMUL16, MASK_SMUL16) DECLARE_INSN(smul8, MATCH_SMUL8, MASK_SMUL8) DECLARE_INSN(smulx16, MATCH_SMULX16, MASK_SMULX16) DECLARE_INSN(smulx8, MATCH_SMULX8, MASK_SMULX8) DECLARE_INSN(smxds, MATCH_SMXDS, MASK_SMXDS) DECLARE_INSN(smxds32, MATCH_SMXDS32, MASK_SMXDS32) DECLARE_INSN(sq, MATCH_SQ, MASK_SQ) DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) DECLARE_INSN(sra16, MATCH_SRA16, MASK_SRA16) DECLARE_INSN(sra16_u, MATCH_SRA16_U, MASK_SRA16_U) DECLARE_INSN(sra32, MATCH_SRA32, MASK_SRA32) DECLARE_INSN(sra32_u, MATCH_SRA32_U, MASK_SRA32_U) DECLARE_INSN(sra8, MATCH_SRA8, MASK_SRA8) DECLARE_INSN(sra8_u, MATCH_SRA8_U, MASK_SRA8_U) DECLARE_INSN(sra_u, MATCH_SRA_U, MASK_SRA_U) DECLARE_INSN(srad, MATCH_SRAD, MASK_SRAD) DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) DECLARE_INSN(srai16, MATCH_SRAI16, MASK_SRAI16) DECLARE_INSN(srai16_u, MATCH_SRAI16_U, MASK_SRAI16_U) DECLARE_INSN(srai32, MATCH_SRAI32, MASK_SRAI32) DECLARE_INSN(srai32_u, MATCH_SRAI32_U, MASK_SRAI32_U) DECLARE_INSN(srai8, MATCH_SRAI8, MASK_SRAI8) DECLARE_INSN(srai8_u, MATCH_SRAI8_U, MASK_SRAI8_U) DECLARE_INSN(srai_u, MATCH_SRAI_U, MASK_SRAI_U) DECLARE_INSN(sraid, MATCH_SRAID, MASK_SRAID) DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) DECLARE_INSN(sraiw_u, MATCH_SRAIW_U, MASK_SRAIW_U) DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) DECLARE_INSN(srl16, MATCH_SRL16, MASK_SRL16) DECLARE_INSN(srl16_u, MATCH_SRL16_U, MASK_SRL16_U) DECLARE_INSN(srl32, MATCH_SRL32, MASK_SRL32) DECLARE_INSN(srl32_u, MATCH_SRL32_U, MASK_SRL32_U) DECLARE_INSN(srl8, MATCH_SRL8, MASK_SRL8) DECLARE_INSN(srl8_u, MATCH_SRL8_U, MASK_SRL8_U) DECLARE_INSN(srld, MATCH_SRLD, MASK_SRLD) DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) DECLARE_INSN(srli16, MATCH_SRLI16, MASK_SRLI16) DECLARE_INSN(srli16_u, MATCH_SRLI16_U, MASK_SRLI16_U) DECLARE_INSN(srli32, MATCH_SRLI32, MASK_SRLI32) DECLARE_INSN(srli32_u, MATCH_SRLI32_U, MASK_SRLI32_U) DECLARE_INSN(srli8, MATCH_SRLI8, MASK_SRLI8) DECLARE_INSN(srli8_u, MATCH_SRLI8_U, MASK_SRLI8_U) DECLARE_INSN(srlid, MATCH_SRLID, MASK_SRLID) DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) DECLARE_INSN(sro, MATCH_SRO, MASK_SRO) DECLARE_INSN(sroi, MATCH_SROI, MASK_SROI) DECLARE_INSN(sroiw, MATCH_SROIW, MASK_SROIW) DECLARE_INSN(srow, MATCH_SROW, MASK_SROW) DECLARE_INSN(stas16, MATCH_STAS16, MASK_STAS16) DECLARE_INSN(stas32, MATCH_STAS32, MASK_STAS32) DECLARE_INSN(stsa16, MATCH_STSA16, MASK_STSA16) DECLARE_INSN(stsa32, MATCH_STSA32, MASK_STSA32) DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) DECLARE_INSN(sub16, MATCH_SUB16, MASK_SUB16) DECLARE_INSN(sub32, MATCH_SUB32, MASK_SUB32) DECLARE_INSN(sub64, MATCH_SUB64, MASK_SUB64) DECLARE_INSN(sub8, MATCH_SUB8, MASK_SUB8) DECLARE_INSN(subd, MATCH_SUBD, MASK_SUBD) DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) DECLARE_INSN(sunpkd810, MATCH_SUNPKD810, MASK_SUNPKD810) DECLARE_INSN(sunpkd820, MATCH_SUNPKD820, MASK_SUNPKD820) DECLARE_INSN(sunpkd830, MATCH_SUNPKD830, MASK_SUNPKD830) DECLARE_INSN(sunpkd831, MATCH_SUNPKD831, MASK_SUNPKD831) DECLARE_INSN(sunpkd832, MATCH_SUNPKD832, MASK_SUNPKD832) DECLARE_INSN(sw, MATCH_SW, MASK_SW) DECLARE_INSN(swap8, MATCH_SWAP8, MASK_SWAP8) DECLARE_INSN(uclip16, MATCH_UCLIP16, MASK_UCLIP16) DECLARE_INSN(uclip32, MATCH_UCLIP32, MASK_UCLIP32) DECLARE_INSN(uclip8, MATCH_UCLIP8, MASK_UCLIP8) DECLARE_INSN(ucmple16, MATCH_UCMPLE16, MASK_UCMPLE16) DECLARE_INSN(ucmple8, MATCH_UCMPLE8, MASK_UCMPLE8) DECLARE_INSN(ucmplt16, MATCH_UCMPLT16, MASK_UCMPLT16) DECLARE_INSN(ucmplt8, MATCH_UCMPLT8, MASK_UCMPLT8) DECLARE_INSN(ukadd16, MATCH_UKADD16, MASK_UKADD16) DECLARE_INSN(ukadd32, MATCH_UKADD32, MASK_UKADD32) DECLARE_INSN(ukadd64, MATCH_UKADD64, MASK_UKADD64) DECLARE_INSN(ukadd8, MATCH_UKADD8, MASK_UKADD8) DECLARE_INSN(ukaddh, MATCH_UKADDH, MASK_UKADDH) DECLARE_INSN(ukaddw, MATCH_UKADDW, MASK_UKADDW) DECLARE_INSN(ukcras16, MATCH_UKCRAS16, MASK_UKCRAS16) DECLARE_INSN(ukcras32, MATCH_UKCRAS32, MASK_UKCRAS32) DECLARE_INSN(ukcrsa16, MATCH_UKCRSA16, MASK_UKCRSA16) DECLARE_INSN(ukcrsa32, MATCH_UKCRSA32, MASK_UKCRSA32) DECLARE_INSN(ukmar64, MATCH_UKMAR64, MASK_UKMAR64) DECLARE_INSN(ukmsr64, MATCH_UKMSR64, MASK_UKMSR64) DECLARE_INSN(ukstas16, MATCH_UKSTAS16, MASK_UKSTAS16) DECLARE_INSN(ukstas32, MATCH_UKSTAS32, MASK_UKSTAS32) DECLARE_INSN(ukstsa16, MATCH_UKSTSA16, MASK_UKSTSA16) DECLARE_INSN(ukstsa32, MATCH_UKSTSA32, MASK_UKSTSA32) DECLARE_INSN(uksub16, MATCH_UKSUB16, MASK_UKSUB16) DECLARE_INSN(uksub32, MATCH_UKSUB32, MASK_UKSUB32) DECLARE_INSN(uksub64, MATCH_UKSUB64, MASK_UKSUB64) DECLARE_INSN(uksub8, MATCH_UKSUB8, MASK_UKSUB8) DECLARE_INSN(uksubh, MATCH_UKSUBH, MASK_UKSUBH) DECLARE_INSN(uksubw, MATCH_UKSUBW, MASK_UKSUBW) DECLARE_INSN(umaqa, MATCH_UMAQA, MASK_UMAQA) DECLARE_INSN(umar64, MATCH_UMAR64, MASK_UMAR64) DECLARE_INSN(umax16, MATCH_UMAX16, MASK_UMAX16) DECLARE_INSN(umax32, MATCH_UMAX32, MASK_UMAX32) DECLARE_INSN(umax8, MATCH_UMAX8, MASK_UMAX8) DECLARE_INSN(umin16, MATCH_UMIN16, MASK_UMIN16) DECLARE_INSN(umin32, MATCH_UMIN32, MASK_UMIN32) DECLARE_INSN(umin8, MATCH_UMIN8, MASK_UMIN8) DECLARE_INSN(umsr64, MATCH_UMSR64, MASK_UMSR64) DECLARE_INSN(umul16, MATCH_UMUL16, MASK_UMUL16) DECLARE_INSN(umul8, MATCH_UMUL8, MASK_UMUL8) DECLARE_INSN(umulx16, MATCH_UMULX16, MASK_UMULX16) DECLARE_INSN(umulx8, MATCH_UMULX8, MASK_UMULX8) DECLARE_INSN(unshfl, MATCH_UNSHFL, MASK_UNSHFL) DECLARE_INSN(unshfli, MATCH_UNSHFLI, MASK_UNSHFLI) DECLARE_INSN(unshflw, MATCH_UNSHFLW, MASK_UNSHFLW) DECLARE_INSN(uradd16, MATCH_URADD16, MASK_URADD16) DECLARE_INSN(uradd32, MATCH_URADD32, MASK_URADD32) DECLARE_INSN(uradd64, MATCH_URADD64, MASK_URADD64) DECLARE_INSN(uradd8, MATCH_URADD8, MASK_URADD8) DECLARE_INSN(uraddw, MATCH_URADDW, MASK_URADDW) DECLARE_INSN(urcras16, MATCH_URCRAS16, MASK_URCRAS16) DECLARE_INSN(urcras32, MATCH_URCRAS32, MASK_URCRAS32) DECLARE_INSN(urcrsa16, MATCH_URCRSA16, MASK_URCRSA16) DECLARE_INSN(urcrsa32, MATCH_URCRSA32, MASK_URCRSA32) DECLARE_INSN(urstas16, MATCH_URSTAS16, MASK_URSTAS16) DECLARE_INSN(urstas32, MATCH_URSTAS32, MASK_URSTAS32) DECLARE_INSN(urstsa16, MATCH_URSTSA16, MASK_URSTSA16) DECLARE_INSN(urstsa32, MATCH_URSTSA32, MASK_URSTSA32) DECLARE_INSN(ursub16, MATCH_URSUB16, MASK_URSUB16) DECLARE_INSN(ursub32, MATCH_URSUB32, MASK_URSUB32) DECLARE_INSN(ursub64, MATCH_URSUB64, MASK_URSUB64) DECLARE_INSN(ursub8, MATCH_URSUB8, MASK_URSUB8) DECLARE_INSN(ursubw, MATCH_URSUBW, MASK_URSUBW) DECLARE_INSN(vaadd_vv, MATCH_VAADD_VV, MASK_VAADD_VV) DECLARE_INSN(vaadd_vx, MATCH_VAADD_VX, MASK_VAADD_VX) DECLARE_INSN(vaaddu_vv, MATCH_VAADDU_VV, MASK_VAADDU_VV) DECLARE_INSN(vaaddu_vx, MATCH_VAADDU_VX, MASK_VAADDU_VX) DECLARE_INSN(vadc_vim, MATCH_VADC_VIM, MASK_VADC_VIM) DECLARE_INSN(vadc_vvm, MATCH_VADC_VVM, MASK_VADC_VVM) DECLARE_INSN(vadc_vxm, MATCH_VADC_VXM, MASK_VADC_VXM) DECLARE_INSN(vadd_vi, MATCH_VADD_VI, MASK_VADD_VI) DECLARE_INSN(vadd_vv, MATCH_VADD_VV, MASK_VADD_VV) DECLARE_INSN(vadd_vx, MATCH_VADD_VX, MASK_VADD_VX) DECLARE_INSN(vamoaddei16_v, MATCH_VAMOADDEI16_V, MASK_VAMOADDEI16_V) DECLARE_INSN(vamoaddei32_v, MATCH_VAMOADDEI32_V, MASK_VAMOADDEI32_V) DECLARE_INSN(vamoaddei64_v, MATCH_VAMOADDEI64_V, MASK_VAMOADDEI64_V) DECLARE_INSN(vamoaddei8_v, MATCH_VAMOADDEI8_V, MASK_VAMOADDEI8_V) DECLARE_INSN(vamoandei16_v, MATCH_VAMOANDEI16_V, MASK_VAMOANDEI16_V) DECLARE_INSN(vamoandei32_v, MATCH_VAMOANDEI32_V, MASK_VAMOANDEI32_V) DECLARE_INSN(vamoandei64_v, MATCH_VAMOANDEI64_V, MASK_VAMOANDEI64_V) DECLARE_INSN(vamoandei8_v, MATCH_VAMOANDEI8_V, MASK_VAMOANDEI8_V) DECLARE_INSN(vamomaxei16_v, MATCH_VAMOMAXEI16_V, MASK_VAMOMAXEI16_V) DECLARE_INSN(vamomaxei32_v, MATCH_VAMOMAXEI32_V, MASK_VAMOMAXEI32_V) DECLARE_INSN(vamomaxei64_v, MATCH_VAMOMAXEI64_V, MASK_VAMOMAXEI64_V) DECLARE_INSN(vamomaxei8_v, MATCH_VAMOMAXEI8_V, MASK_VAMOMAXEI8_V) DECLARE_INSN(vamomaxuei16_v, MATCH_VAMOMAXUEI16_V, MASK_VAMOMAXUEI16_V) DECLARE_INSN(vamomaxuei32_v, MATCH_VAMOMAXUEI32_V, MASK_VAMOMAXUEI32_V) DECLARE_INSN(vamomaxuei64_v, MATCH_VAMOMAXUEI64_V, MASK_VAMOMAXUEI64_V) DECLARE_INSN(vamomaxuei8_v, MATCH_VAMOMAXUEI8_V, MASK_VAMOMAXUEI8_V) DECLARE_INSN(vamominei16_v, MATCH_VAMOMINEI16_V, MASK_VAMOMINEI16_V) DECLARE_INSN(vamominei32_v, MATCH_VAMOMINEI32_V, MASK_VAMOMINEI32_V) DECLARE_INSN(vamominei64_v, MATCH_VAMOMINEI64_V, MASK_VAMOMINEI64_V) DECLARE_INSN(vamominei8_v, MATCH_VAMOMINEI8_V, MASK_VAMOMINEI8_V) DECLARE_INSN(vamominuei16_v, MATCH_VAMOMINUEI16_V, MASK_VAMOMINUEI16_V) DECLARE_INSN(vamominuei32_v, MATCH_VAMOMINUEI32_V, MASK_VAMOMINUEI32_V) DECLARE_INSN(vamominuei64_v, MATCH_VAMOMINUEI64_V, MASK_VAMOMINUEI64_V) DECLARE_INSN(vamominuei8_v, MATCH_VAMOMINUEI8_V, MASK_VAMOMINUEI8_V) DECLARE_INSN(vamoorei16_v, MATCH_VAMOOREI16_V, MASK_VAMOOREI16_V) DECLARE_INSN(vamoorei32_v, MATCH_VAMOOREI32_V, MASK_VAMOOREI32_V) DECLARE_INSN(vamoorei64_v, MATCH_VAMOOREI64_V, MASK_VAMOOREI64_V) DECLARE_INSN(vamoorei8_v, MATCH_VAMOOREI8_V, MASK_VAMOOREI8_V) DECLARE_INSN(vamoswapei16_v, MATCH_VAMOSWAPEI16_V, MASK_VAMOSWAPEI16_V) DECLARE_INSN(vamoswapei32_v, MATCH_VAMOSWAPEI32_V, MASK_VAMOSWAPEI32_V) DECLARE_INSN(vamoswapei64_v, MATCH_VAMOSWAPEI64_V, MASK_VAMOSWAPEI64_V) DECLARE_INSN(vamoswapei8_v, MATCH_VAMOSWAPEI8_V, MASK_VAMOSWAPEI8_V) DECLARE_INSN(vamoxorei16_v, MATCH_VAMOXOREI16_V, MASK_VAMOXOREI16_V) DECLARE_INSN(vamoxorei32_v, MATCH_VAMOXOREI32_V, MASK_VAMOXOREI32_V) DECLARE_INSN(vamoxorei64_v, MATCH_VAMOXOREI64_V, MASK_VAMOXOREI64_V) DECLARE_INSN(vamoxorei8_v, MATCH_VAMOXOREI8_V, MASK_VAMOXOREI8_V) DECLARE_INSN(vand_vi, MATCH_VAND_VI, MASK_VAND_VI) DECLARE_INSN(vand_vv, MATCH_VAND_VV, MASK_VAND_VV) DECLARE_INSN(vand_vx, MATCH_VAND_VX, MASK_VAND_VX) DECLARE_INSN(vasub_vv, MATCH_VASUB_VV, MASK_VASUB_VV) DECLARE_INSN(vasub_vx, MATCH_VASUB_VX, MASK_VASUB_VX) DECLARE_INSN(vasubu_vv, MATCH_VASUBU_VV, MASK_VASUBU_VV) DECLARE_INSN(vasubu_vx, MATCH_VASUBU_VX, MASK_VASUBU_VX) DECLARE_INSN(vcompress_vm, MATCH_VCOMPRESS_VM, MASK_VCOMPRESS_VM) DECLARE_INSN(vcpop_m, MATCH_VCPOP_M, MASK_VCPOP_M) DECLARE_INSN(vdiv_vv, MATCH_VDIV_VV, MASK_VDIV_VV) DECLARE_INSN(vdiv_vx, MATCH_VDIV_VX, MASK_VDIV_VX) DECLARE_INSN(vdivu_vv, MATCH_VDIVU_VV, MASK_VDIVU_VV) DECLARE_INSN(vdivu_vx, MATCH_VDIVU_VX, MASK_VDIVU_VX) DECLARE_INSN(vfadd_vf, MATCH_VFADD_VF, MASK_VFADD_VF) DECLARE_INSN(vfadd_vv, MATCH_VFADD_VV, MASK_VFADD_VV) DECLARE_INSN(vfclass_v, MATCH_VFCLASS_V, MASK_VFCLASS_V) DECLARE_INSN(vfcvt_f_x_v, MATCH_VFCVT_F_X_V, MASK_VFCVT_F_X_V) DECLARE_INSN(vfcvt_f_xu_v, MATCH_VFCVT_F_XU_V, MASK_VFCVT_F_XU_V) DECLARE_INSN(vfcvt_rtz_x_f_v, MATCH_VFCVT_RTZ_X_F_V, MASK_VFCVT_RTZ_X_F_V) DECLARE_INSN(vfcvt_rtz_xu_f_v, MATCH_VFCVT_RTZ_XU_F_V, MASK_VFCVT_RTZ_XU_F_V) DECLARE_INSN(vfcvt_x_f_v, MATCH_VFCVT_X_F_V, MASK_VFCVT_X_F_V) DECLARE_INSN(vfcvt_xu_f_v, MATCH_VFCVT_XU_F_V, MASK_VFCVT_XU_F_V) DECLARE_INSN(vfdiv_vf, MATCH_VFDIV_VF, MASK_VFDIV_VF) DECLARE_INSN(vfdiv_vv, MATCH_VFDIV_VV, MASK_VFDIV_VV) DECLARE_INSN(vfirst_m, MATCH_VFIRST_M, MASK_VFIRST_M) DECLARE_INSN(vfmacc_vf, MATCH_VFMACC_VF, MASK_VFMACC_VF) DECLARE_INSN(vfmacc_vv, MATCH_VFMACC_VV, MASK_VFMACC_VV) DECLARE_INSN(vfmadd_vf, MATCH_VFMADD_VF, MASK_VFMADD_VF) DECLARE_INSN(vfmadd_vv, MATCH_VFMADD_VV, MASK_VFMADD_VV) DECLARE_INSN(vfmax_vf, MATCH_VFMAX_VF, MASK_VFMAX_VF) DECLARE_INSN(vfmax_vv, MATCH_VFMAX_VV, MASK_VFMAX_VV) DECLARE_INSN(vfmerge_vfm, MATCH_VFMERGE_VFM, MASK_VFMERGE_VFM) DECLARE_INSN(vfmin_vf, MATCH_VFMIN_VF, MASK_VFMIN_VF) DECLARE_INSN(vfmin_vv, MATCH_VFMIN_VV, MASK_VFMIN_VV) DECLARE_INSN(vfmsac_vf, MATCH_VFMSAC_VF, MASK_VFMSAC_VF) DECLARE_INSN(vfmsac_vv, MATCH_VFMSAC_VV, MASK_VFMSAC_VV) DECLARE_INSN(vfmsub_vf, MATCH_VFMSUB_VF, MASK_VFMSUB_VF) DECLARE_INSN(vfmsub_vv, MATCH_VFMSUB_VV, MASK_VFMSUB_VV) DECLARE_INSN(vfmul_vf, MATCH_VFMUL_VF, MASK_VFMUL_VF) DECLARE_INSN(vfmul_vv, MATCH_VFMUL_VV, MASK_VFMUL_VV) DECLARE_INSN(vfmv_f_s, MATCH_VFMV_F_S, MASK_VFMV_F_S) DECLARE_INSN(vfmv_s_f, MATCH_VFMV_S_F, MASK_VFMV_S_F) DECLARE_INSN(vfmv_v_f, MATCH_VFMV_V_F, MASK_VFMV_V_F) DECLARE_INSN(vfncvt_f_f_w, MATCH_VFNCVT_F_F_W, MASK_VFNCVT_F_F_W) DECLARE_INSN(vfncvt_f_x_w, MATCH_VFNCVT_F_X_W, MASK_VFNCVT_F_X_W) DECLARE_INSN(vfncvt_f_xu_w, MATCH_VFNCVT_F_XU_W, MASK_VFNCVT_F_XU_W) DECLARE_INSN(vfncvt_rod_f_f_w, MATCH_VFNCVT_ROD_F_F_W, MASK_VFNCVT_ROD_F_F_W) DECLARE_INSN(vfncvt_rtz_x_f_w, MATCH_VFNCVT_RTZ_X_F_W, MASK_VFNCVT_RTZ_X_F_W) DECLARE_INSN(vfncvt_rtz_xu_f_w, MATCH_VFNCVT_RTZ_XU_F_W, MASK_VFNCVT_RTZ_XU_F_W) DECLARE_INSN(vfncvt_x_f_w, MATCH_VFNCVT_X_F_W, MASK_VFNCVT_X_F_W) DECLARE_INSN(vfncvt_xu_f_w, MATCH_VFNCVT_XU_F_W, MASK_VFNCVT_XU_F_W) DECLARE_INSN(vfnmacc_vf, MATCH_VFNMACC_VF, MASK_VFNMACC_VF) DECLARE_INSN(vfnmacc_vv, MATCH_VFNMACC_VV, MASK_VFNMACC_VV) DECLARE_INSN(vfnmadd_vf, MATCH_VFNMADD_VF, MASK_VFNMADD_VF) DECLARE_INSN(vfnmadd_vv, MATCH_VFNMADD_VV, MASK_VFNMADD_VV) DECLARE_INSN(vfnmsac_vf, MATCH_VFNMSAC_VF, MASK_VFNMSAC_VF) DECLARE_INSN(vfnmsac_vv, MATCH_VFNMSAC_VV, MASK_VFNMSAC_VV) DECLARE_INSN(vfnmsub_vf, MATCH_VFNMSUB_VF, MASK_VFNMSUB_VF) DECLARE_INSN(vfnmsub_vv, MATCH_VFNMSUB_VV, MASK_VFNMSUB_VV) DECLARE_INSN(vfrdiv_vf, MATCH_VFRDIV_VF, MASK_VFRDIV_VF) DECLARE_INSN(vfrec7_v, MATCH_VFREC7_V, MASK_VFREC7_V) DECLARE_INSN(vfredmax_vs, MATCH_VFREDMAX_VS, MASK_VFREDMAX_VS) DECLARE_INSN(vfredmin_vs, MATCH_VFREDMIN_VS, MASK_VFREDMIN_VS) DECLARE_INSN(vfredosum_vs, MATCH_VFREDOSUM_VS, MASK_VFREDOSUM_VS) DECLARE_INSN(vfredusum_vs, MATCH_VFREDUSUM_VS, MASK_VFREDUSUM_VS) DECLARE_INSN(vfrsqrt7_v, MATCH_VFRSQRT7_V, MASK_VFRSQRT7_V) DECLARE_INSN(vfrsub_vf, MATCH_VFRSUB_VF, MASK_VFRSUB_VF) DECLARE_INSN(vfsgnj_vf, MATCH_VFSGNJ_VF, MASK_VFSGNJ_VF) DECLARE_INSN(vfsgnj_vv, MATCH_VFSGNJ_VV, MASK_VFSGNJ_VV) DECLARE_INSN(vfsgnjn_vf, MATCH_VFSGNJN_VF, MASK_VFSGNJN_VF) DECLARE_INSN(vfsgnjn_vv, MATCH_VFSGNJN_VV, MASK_VFSGNJN_VV) DECLARE_INSN(vfsgnjx_vf, MATCH_VFSGNJX_VF, MASK_VFSGNJX_VF) DECLARE_INSN(vfsgnjx_vv, MATCH_VFSGNJX_VV, MASK_VFSGNJX_VV) DECLARE_INSN(vfslide1down_vf, MATCH_VFSLIDE1DOWN_VF, MASK_VFSLIDE1DOWN_VF) DECLARE_INSN(vfslide1up_vf, MATCH_VFSLIDE1UP_VF, MASK_VFSLIDE1UP_VF) DECLARE_INSN(vfsqrt_v, MATCH_VFSQRT_V, MASK_VFSQRT_V) DECLARE_INSN(vfsub_vf, MATCH_VFSUB_VF, MASK_VFSUB_VF) DECLARE_INSN(vfsub_vv, MATCH_VFSUB_VV, MASK_VFSUB_VV) DECLARE_INSN(vfwadd_vf, MATCH_VFWADD_VF, MASK_VFWADD_VF) DECLARE_INSN(vfwadd_vv, MATCH_VFWADD_VV, MASK_VFWADD_VV) DECLARE_INSN(vfwadd_wf, MATCH_VFWADD_WF, MASK_VFWADD_WF) DECLARE_INSN(vfwadd_wv, MATCH_VFWADD_WV, MASK_VFWADD_WV) DECLARE_INSN(vfwcvt_f_f_v, MATCH_VFWCVT_F_F_V, MASK_VFWCVT_F_F_V) DECLARE_INSN(vfwcvt_f_x_v, MATCH_VFWCVT_F_X_V, MASK_VFWCVT_F_X_V) DECLARE_INSN(vfwcvt_f_xu_v, MATCH_VFWCVT_F_XU_V, MASK_VFWCVT_F_XU_V) DECLARE_INSN(vfwcvt_rtz_x_f_v, MATCH_VFWCVT_RTZ_X_F_V, MASK_VFWCVT_RTZ_X_F_V) DECLARE_INSN(vfwcvt_rtz_xu_f_v, MATCH_VFWCVT_RTZ_XU_F_V, MASK_VFWCVT_RTZ_XU_F_V) DECLARE_INSN(vfwcvt_x_f_v, MATCH_VFWCVT_X_F_V, MASK_VFWCVT_X_F_V) DECLARE_INSN(vfwcvt_xu_f_v, MATCH_VFWCVT_XU_F_V, MASK_VFWCVT_XU_F_V) DECLARE_INSN(vfwmacc_vf, MATCH_VFWMACC_VF, MASK_VFWMACC_VF) DECLARE_INSN(vfwmacc_vv, MATCH_VFWMACC_VV, MASK_VFWMACC_VV) DECLARE_INSN(vfwmsac_vf, MATCH_VFWMSAC_VF, MASK_VFWMSAC_VF) DECLARE_INSN(vfwmsac_vv, MATCH_VFWMSAC_VV, MASK_VFWMSAC_VV) DECLARE_INSN(vfwmul_vf, MATCH_VFWMUL_VF, MASK_VFWMUL_VF) DECLARE_INSN(vfwmul_vv, MATCH_VFWMUL_VV, MASK_VFWMUL_VV) DECLARE_INSN(vfwnmacc_vf, MATCH_VFWNMACC_VF, MASK_VFWNMACC_VF) DECLARE_INSN(vfwnmacc_vv, MATCH_VFWNMACC_VV, MASK_VFWNMACC_VV) DECLARE_INSN(vfwnmsac_vf, MATCH_VFWNMSAC_VF, MASK_VFWNMSAC_VF) DECLARE_INSN(vfwnmsac_vv, MATCH_VFWNMSAC_VV, MASK_VFWNMSAC_VV) DECLARE_INSN(vfwredosum_vs, MATCH_VFWREDOSUM_VS, MASK_VFWREDOSUM_VS) DECLARE_INSN(vfwredusum_vs, MATCH_VFWREDUSUM_VS, MASK_VFWREDUSUM_VS) DECLARE_INSN(vfwsub_vf, MATCH_VFWSUB_VF, MASK_VFWSUB_VF) DECLARE_INSN(vfwsub_vv, MATCH_VFWSUB_VV, MASK_VFWSUB_VV) DECLARE_INSN(vfwsub_wf, MATCH_VFWSUB_WF, MASK_VFWSUB_WF) DECLARE_INSN(vfwsub_wv, MATCH_VFWSUB_WV, MASK_VFWSUB_WV) DECLARE_INSN(vid_v, MATCH_VID_V, MASK_VID_V) DECLARE_INSN(viota_m, MATCH_VIOTA_M, MASK_VIOTA_M) DECLARE_INSN(vl1re16_v, MATCH_VL1RE16_V, MASK_VL1RE16_V) DECLARE_INSN(vl1re32_v, MATCH_VL1RE32_V, MASK_VL1RE32_V) DECLARE_INSN(vl1re64_v, MATCH_VL1RE64_V, MASK_VL1RE64_V) DECLARE_INSN(vl1re8_v, MATCH_VL1RE8_V, MASK_VL1RE8_V) DECLARE_INSN(vl2re16_v, MATCH_VL2RE16_V, MASK_VL2RE16_V) DECLARE_INSN(vl2re32_v, MATCH_VL2RE32_V, MASK_VL2RE32_V) DECLARE_INSN(vl2re64_v, MATCH_VL2RE64_V, MASK_VL2RE64_V) DECLARE_INSN(vl2re8_v, MATCH_VL2RE8_V, MASK_VL2RE8_V) DECLARE_INSN(vl4re16_v, MATCH_VL4RE16_V, MASK_VL4RE16_V) DECLARE_INSN(vl4re32_v, MATCH_VL4RE32_V, MASK_VL4RE32_V) DECLARE_INSN(vl4re64_v, MATCH_VL4RE64_V, MASK_VL4RE64_V) DECLARE_INSN(vl4re8_v, MATCH_VL4RE8_V, MASK_VL4RE8_V) DECLARE_INSN(vl8re16_v, MATCH_VL8RE16_V, MASK_VL8RE16_V) DECLARE_INSN(vl8re32_v, MATCH_VL8RE32_V, MASK_VL8RE32_V) DECLARE_INSN(vl8re64_v, MATCH_VL8RE64_V, MASK_VL8RE64_V) DECLARE_INSN(vl8re8_v, MATCH_VL8RE8_V, MASK_VL8RE8_V) DECLARE_INSN(vle1024_v, MATCH_VLE1024_V, MASK_VLE1024_V) DECLARE_INSN(vle1024ff_v, MATCH_VLE1024FF_V, MASK_VLE1024FF_V) DECLARE_INSN(vle128_v, MATCH_VLE128_V, MASK_VLE128_V) DECLARE_INSN(vle128ff_v, MATCH_VLE128FF_V, MASK_VLE128FF_V) DECLARE_INSN(vle16_v, MATCH_VLE16_V, MASK_VLE16_V) DECLARE_INSN(vle16ff_v, MATCH_VLE16FF_V, MASK_VLE16FF_V) DECLARE_INSN(vle256_v, MATCH_VLE256_V, MASK_VLE256_V) DECLARE_INSN(vle256ff_v, MATCH_VLE256FF_V, MASK_VLE256FF_V) DECLARE_INSN(vle32_v, MATCH_VLE32_V, MASK_VLE32_V) DECLARE_INSN(vle32ff_v, MATCH_VLE32FF_V, MASK_VLE32FF_V) DECLARE_INSN(vle512_v, MATCH_VLE512_V, MASK_VLE512_V) DECLARE_INSN(vle512ff_v, MATCH_VLE512FF_V, MASK_VLE512FF_V) DECLARE_INSN(vle64_v, MATCH_VLE64_V, MASK_VLE64_V) DECLARE_INSN(vle64ff_v, MATCH_VLE64FF_V, MASK_VLE64FF_V) DECLARE_INSN(vle8_v, MATCH_VLE8_V, MASK_VLE8_V) DECLARE_INSN(vle8ff_v, MATCH_VLE8FF_V, MASK_VLE8FF_V) DECLARE_INSN(vlm_v, MATCH_VLM_V, MASK_VLM_V) DECLARE_INSN(vloxei1024_v, MATCH_VLOXEI1024_V, MASK_VLOXEI1024_V) DECLARE_INSN(vloxei128_v, MATCH_VLOXEI128_V, MASK_VLOXEI128_V) DECLARE_INSN(vloxei16_v, MATCH_VLOXEI16_V, MASK_VLOXEI16_V) DECLARE_INSN(vloxei256_v, MATCH_VLOXEI256_V, MASK_VLOXEI256_V) DECLARE_INSN(vloxei32_v, MATCH_VLOXEI32_V, MASK_VLOXEI32_V) DECLARE_INSN(vloxei512_v, MATCH_VLOXEI512_V, MASK_VLOXEI512_V) DECLARE_INSN(vloxei64_v, MATCH_VLOXEI64_V, MASK_VLOXEI64_V) DECLARE_INSN(vloxei8_v, MATCH_VLOXEI8_V, MASK_VLOXEI8_V) DECLARE_INSN(vlse1024_v, MATCH_VLSE1024_V, MASK_VLSE1024_V) DECLARE_INSN(vlse128_v, MATCH_VLSE128_V, MASK_VLSE128_V) DECLARE_INSN(vlse16_v, MATCH_VLSE16_V, MASK_VLSE16_V) DECLARE_INSN(vlse256_v, MATCH_VLSE256_V, MASK_VLSE256_V) DECLARE_INSN(vlse32_v, MATCH_VLSE32_V, MASK_VLSE32_V) DECLARE_INSN(vlse512_v, MATCH_VLSE512_V, MASK_VLSE512_V) DECLARE_INSN(vlse64_v, MATCH_VLSE64_V, MASK_VLSE64_V) DECLARE_INSN(vlse8_v, MATCH_VLSE8_V, MASK_VLSE8_V) DECLARE_INSN(vluxei1024_v, MATCH_VLUXEI1024_V, MASK_VLUXEI1024_V) DECLARE_INSN(vluxei128_v, MATCH_VLUXEI128_V, MASK_VLUXEI128_V) DECLARE_INSN(vluxei16_v, MATCH_VLUXEI16_V, MASK_VLUXEI16_V) DECLARE_INSN(vluxei256_v, MATCH_VLUXEI256_V, MASK_VLUXEI256_V) DECLARE_INSN(vluxei32_v, MATCH_VLUXEI32_V, MASK_VLUXEI32_V) DECLARE_INSN(vluxei512_v, MATCH_VLUXEI512_V, MASK_VLUXEI512_V) DECLARE_INSN(vluxei64_v, MATCH_VLUXEI64_V, MASK_VLUXEI64_V) DECLARE_INSN(vluxei8_v, MATCH_VLUXEI8_V, MASK_VLUXEI8_V) DECLARE_INSN(vmacc_vv, MATCH_VMACC_VV, MASK_VMACC_VV) DECLARE_INSN(vmacc_vx, MATCH_VMACC_VX, MASK_VMACC_VX) DECLARE_INSN(vmadc_vi, MATCH_VMADC_VI, MASK_VMADC_VI) DECLARE_INSN(vmadc_vim, MATCH_VMADC_VIM, MASK_VMADC_VIM) DECLARE_INSN(vmadc_vv, MATCH_VMADC_VV, MASK_VMADC_VV) DECLARE_INSN(vmadc_vvm, MATCH_VMADC_VVM, MASK_VMADC_VVM) DECLARE_INSN(vmadc_vx, MATCH_VMADC_VX, MASK_VMADC_VX) DECLARE_INSN(vmadc_vxm, MATCH_VMADC_VXM, MASK_VMADC_VXM) DECLARE_INSN(vmadd_vv, MATCH_VMADD_VV, MASK_VMADD_VV) DECLARE_INSN(vmadd_vx, MATCH_VMADD_VX, MASK_VMADD_VX) DECLARE_INSN(vmand_mm, MATCH_VMAND_MM, MASK_VMAND_MM) DECLARE_INSN(vmandn_mm, MATCH_VMANDN_MM, MASK_VMANDN_MM) DECLARE_INSN(vmax_vv, MATCH_VMAX_VV, MASK_VMAX_VV) DECLARE_INSN(vmax_vx, MATCH_VMAX_VX, MASK_VMAX_VX) DECLARE_INSN(vmaxu_vv, MATCH_VMAXU_VV, MASK_VMAXU_VV) DECLARE_INSN(vmaxu_vx, MATCH_VMAXU_VX, MASK_VMAXU_VX) DECLARE_INSN(vmerge_vim, MATCH_VMERGE_VIM, MASK_VMERGE_VIM) DECLARE_INSN(vmerge_vvm, MATCH_VMERGE_VVM, MASK_VMERGE_VVM) DECLARE_INSN(vmerge_vxm, MATCH_VMERGE_VXM, MASK_VMERGE_VXM) DECLARE_INSN(vmfeq_vf, MATCH_VMFEQ_VF, MASK_VMFEQ_VF) DECLARE_INSN(vmfeq_vv, MATCH_VMFEQ_VV, MASK_VMFEQ_VV) DECLARE_INSN(vmfge_vf, MATCH_VMFGE_VF, MASK_VMFGE_VF) DECLARE_INSN(vmfgt_vf, MATCH_VMFGT_VF, MASK_VMFGT_VF) DECLARE_INSN(vmfle_vf, MATCH_VMFLE_VF, MASK_VMFLE_VF) DECLARE_INSN(vmfle_vv, MATCH_VMFLE_VV, MASK_VMFLE_VV) DECLARE_INSN(vmflt_vf, MATCH_VMFLT_VF, MASK_VMFLT_VF) DECLARE_INSN(vmflt_vv, MATCH_VMFLT_VV, MASK_VMFLT_VV) DECLARE_INSN(vmfne_vf, MATCH_VMFNE_VF, MASK_VMFNE_VF) DECLARE_INSN(vmfne_vv, MATCH_VMFNE_VV, MASK_VMFNE_VV) DECLARE_INSN(vmin_vv, MATCH_VMIN_VV, MASK_VMIN_VV) DECLARE_INSN(vmin_vx, MATCH_VMIN_VX, MASK_VMIN_VX) DECLARE_INSN(vminu_vv, MATCH_VMINU_VV, MASK_VMINU_VV) DECLARE_INSN(vminu_vx, MATCH_VMINU_VX, MASK_VMINU_VX) DECLARE_INSN(vmnand_mm, MATCH_VMNAND_MM, MASK_VMNAND_MM) DECLARE_INSN(vmnor_mm, MATCH_VMNOR_MM, MASK_VMNOR_MM) DECLARE_INSN(vmor_mm, MATCH_VMOR_MM, MASK_VMOR_MM) DECLARE_INSN(vmorn_mm, MATCH_VMORN_MM, MASK_VMORN_MM) DECLARE_INSN(vmsbc_vv, MATCH_VMSBC_VV, MASK_VMSBC_VV) DECLARE_INSN(vmsbc_vvm, MATCH_VMSBC_VVM, MASK_VMSBC_VVM) DECLARE_INSN(vmsbc_vx, MATCH_VMSBC_VX, MASK_VMSBC_VX) DECLARE_INSN(vmsbc_vxm, MATCH_VMSBC_VXM, MASK_VMSBC_VXM) DECLARE_INSN(vmsbf_m, MATCH_VMSBF_M, MASK_VMSBF_M) DECLARE_INSN(vmseq_vi, MATCH_VMSEQ_VI, MASK_VMSEQ_VI) DECLARE_INSN(vmseq_vv, MATCH_VMSEQ_VV, MASK_VMSEQ_VV) DECLARE_INSN(vmseq_vx, MATCH_VMSEQ_VX, MASK_VMSEQ_VX) DECLARE_INSN(vmsgt_vi, MATCH_VMSGT_VI, MASK_VMSGT_VI) DECLARE_INSN(vmsgt_vx, MATCH_VMSGT_VX, MASK_VMSGT_VX) DECLARE_INSN(vmsgtu_vi, MATCH_VMSGTU_VI, MASK_VMSGTU_VI) DECLARE_INSN(vmsgtu_vx, MATCH_VMSGTU_VX, MASK_VMSGTU_VX) DECLARE_INSN(vmsif_m, MATCH_VMSIF_M, MASK_VMSIF_M) DECLARE_INSN(vmsle_vi, MATCH_VMSLE_VI, MASK_VMSLE_VI) DECLARE_INSN(vmsle_vv, MATCH_VMSLE_VV, MASK_VMSLE_VV) DECLARE_INSN(vmsle_vx, MATCH_VMSLE_VX, MASK_VMSLE_VX) DECLARE_INSN(vmsleu_vi, MATCH_VMSLEU_VI, MASK_VMSLEU_VI) DECLARE_INSN(vmsleu_vv, MATCH_VMSLEU_VV, MASK_VMSLEU_VV) DECLARE_INSN(vmsleu_vx, MATCH_VMSLEU_VX, MASK_VMSLEU_VX) DECLARE_INSN(vmslt_vv, MATCH_VMSLT_VV, MASK_VMSLT_VV) DECLARE_INSN(vmslt_vx, MATCH_VMSLT_VX, MASK_VMSLT_VX) DECLARE_INSN(vmsltu_vv, MATCH_VMSLTU_VV, MASK_VMSLTU_VV) DECLARE_INSN(vmsltu_vx, MATCH_VMSLTU_VX, MASK_VMSLTU_VX) DECLARE_INSN(vmsne_vi, MATCH_VMSNE_VI, MASK_VMSNE_VI) DECLARE_INSN(vmsne_vv, MATCH_VMSNE_VV, MASK_VMSNE_VV) DECLARE_INSN(vmsne_vx, MATCH_VMSNE_VX, MASK_VMSNE_VX) DECLARE_INSN(vmsof_m, MATCH_VMSOF_M, MASK_VMSOF_M) DECLARE_INSN(vmul_vv, MATCH_VMUL_VV, MASK_VMUL_VV) DECLARE_INSN(vmul_vx, MATCH_VMUL_VX, MASK_VMUL_VX) DECLARE_INSN(vmulh_vv, MATCH_VMULH_VV, MASK_VMULH_VV) DECLARE_INSN(vmulh_vx, MATCH_VMULH_VX, MASK_VMULH_VX) DECLARE_INSN(vmulhsu_vv, MATCH_VMULHSU_VV, MASK_VMULHSU_VV) DECLARE_INSN(vmulhsu_vx, MATCH_VMULHSU_VX, MASK_VMULHSU_VX) DECLARE_INSN(vmulhu_vv, MATCH_VMULHU_VV, MASK_VMULHU_VV) DECLARE_INSN(vmulhu_vx, MATCH_VMULHU_VX, MASK_VMULHU_VX) DECLARE_INSN(vmv1r_v, MATCH_VMV1R_V, MASK_VMV1R_V) DECLARE_INSN(vmv2r_v, MATCH_VMV2R_V, MASK_VMV2R_V) DECLARE_INSN(vmv4r_v, MATCH_VMV4R_V, MASK_VMV4R_V) DECLARE_INSN(vmv8r_v, MATCH_VMV8R_V, MASK_VMV8R_V) DECLARE_INSN(vmv_s_x, MATCH_VMV_S_X, MASK_VMV_S_X) DECLARE_INSN(vmv_v_i, MATCH_VMV_V_I, MASK_VMV_V_I) DECLARE_INSN(vmv_v_v, MATCH_VMV_V_V, MASK_VMV_V_V) DECLARE_INSN(vmv_v_x, MATCH_VMV_V_X, MASK_VMV_V_X) DECLARE_INSN(vmv_x_s, MATCH_VMV_X_S, MASK_VMV_X_S) DECLARE_INSN(vmxnor_mm, MATCH_VMXNOR_MM, MASK_VMXNOR_MM) DECLARE_INSN(vmxor_mm, MATCH_VMXOR_MM, MASK_VMXOR_MM) DECLARE_INSN(vnclip_wi, MATCH_VNCLIP_WI, MASK_VNCLIP_WI) DECLARE_INSN(vnclip_wv, MATCH_VNCLIP_WV, MASK_VNCLIP_WV) DECLARE_INSN(vnclip_wx, MATCH_VNCLIP_WX, MASK_VNCLIP_WX) DECLARE_INSN(vnclipu_wi, MATCH_VNCLIPU_WI, MASK_VNCLIPU_WI) DECLARE_INSN(vnclipu_wv, MATCH_VNCLIPU_WV, MASK_VNCLIPU_WV) DECLARE_INSN(vnclipu_wx, MATCH_VNCLIPU_WX, MASK_VNCLIPU_WX) DECLARE_INSN(vnmsac_vv, MATCH_VNMSAC_VV, MASK_VNMSAC_VV) DECLARE_INSN(vnmsac_vx, MATCH_VNMSAC_VX, MASK_VNMSAC_VX) DECLARE_INSN(vnmsub_vv, MATCH_VNMSUB_VV, MASK_VNMSUB_VV) DECLARE_INSN(vnmsub_vx, MATCH_VNMSUB_VX, MASK_VNMSUB_VX) DECLARE_INSN(vnsra_wi, MATCH_VNSRA_WI, MASK_VNSRA_WI) DECLARE_INSN(vnsra_wv, MATCH_VNSRA_WV, MASK_VNSRA_WV) DECLARE_INSN(vnsra_wx, MATCH_VNSRA_WX, MASK_VNSRA_WX) DECLARE_INSN(vnsrl_wi, MATCH_VNSRL_WI, MASK_VNSRL_WI) DECLARE_INSN(vnsrl_wv, MATCH_VNSRL_WV, MASK_VNSRL_WV) DECLARE_INSN(vnsrl_wx, MATCH_VNSRL_WX, MASK_VNSRL_WX) DECLARE_INSN(vor_vi, MATCH_VOR_VI, MASK_VOR_VI) DECLARE_INSN(vor_vv, MATCH_VOR_VV, MASK_VOR_VV) DECLARE_INSN(vor_vx, MATCH_VOR_VX, MASK_VOR_VX) DECLARE_INSN(vredand_vs, MATCH_VREDAND_VS, MASK_VREDAND_VS) DECLARE_INSN(vredmax_vs, MATCH_VREDMAX_VS, MASK_VREDMAX_VS) DECLARE_INSN(vredmaxu_vs, MATCH_VREDMAXU_VS, MASK_VREDMAXU_VS) DECLARE_INSN(vredmin_vs, MATCH_VREDMIN_VS, MASK_VREDMIN_VS) DECLARE_INSN(vredminu_vs, MATCH_VREDMINU_VS, MASK_VREDMINU_VS) DECLARE_INSN(vredor_vs, MATCH_VREDOR_VS, MASK_VREDOR_VS) DECLARE_INSN(vredsum_vs, MATCH_VREDSUM_VS, MASK_VREDSUM_VS) DECLARE_INSN(vredxor_vs, MATCH_VREDXOR_VS, MASK_VREDXOR_VS) DECLARE_INSN(vrem_vv, MATCH_VREM_VV, MASK_VREM_VV) DECLARE_INSN(vrem_vx, MATCH_VREM_VX, MASK_VREM_VX) DECLARE_INSN(vremu_vv, MATCH_VREMU_VV, MASK_VREMU_VV) DECLARE_INSN(vremu_vx, MATCH_VREMU_VX, MASK_VREMU_VX) DECLARE_INSN(vrgather_vi, MATCH_VRGATHER_VI, MASK_VRGATHER_VI) DECLARE_INSN(vrgather_vv, MATCH_VRGATHER_VV, MASK_VRGATHER_VV) DECLARE_INSN(vrgather_vx, MATCH_VRGATHER_VX, MASK_VRGATHER_VX) DECLARE_INSN(vrgatherei16_vv, MATCH_VRGATHEREI16_VV, MASK_VRGATHEREI16_VV) DECLARE_INSN(vrsub_vi, MATCH_VRSUB_VI, MASK_VRSUB_VI) DECLARE_INSN(vrsub_vx, MATCH_VRSUB_VX, MASK_VRSUB_VX) DECLARE_INSN(vs1r_v, MATCH_VS1R_V, MASK_VS1R_V) DECLARE_INSN(vs2r_v, MATCH_VS2R_V, MASK_VS2R_V) DECLARE_INSN(vs4r_v, MATCH_VS4R_V, MASK_VS4R_V) DECLARE_INSN(vs8r_v, MATCH_VS8R_V, MASK_VS8R_V) DECLARE_INSN(vsadd_vi, MATCH_VSADD_VI, MASK_VSADD_VI) DECLARE_INSN(vsadd_vv, MATCH_VSADD_VV, MASK_VSADD_VV) DECLARE_INSN(vsadd_vx, MATCH_VSADD_VX, MASK_VSADD_VX) DECLARE_INSN(vsaddu_vi, MATCH_VSADDU_VI, MASK_VSADDU_VI) DECLARE_INSN(vsaddu_vv, MATCH_VSADDU_VV, MASK_VSADDU_VV) DECLARE_INSN(vsaddu_vx, MATCH_VSADDU_VX, MASK_VSADDU_VX) DECLARE_INSN(vsbc_vvm, MATCH_VSBC_VVM, MASK_VSBC_VVM) DECLARE_INSN(vsbc_vxm, MATCH_VSBC_VXM, MASK_VSBC_VXM) DECLARE_INSN(vse1024_v, MATCH_VSE1024_V, MASK_VSE1024_V) DECLARE_INSN(vse128_v, MATCH_VSE128_V, MASK_VSE128_V) DECLARE_INSN(vse16_v, MATCH_VSE16_V, MASK_VSE16_V) DECLARE_INSN(vse256_v, MATCH_VSE256_V, MASK_VSE256_V) DECLARE_INSN(vse32_v, MATCH_VSE32_V, MASK_VSE32_V) DECLARE_INSN(vse512_v, MATCH_VSE512_V, MASK_VSE512_V) DECLARE_INSN(vse64_v, MATCH_VSE64_V, MASK_VSE64_V) DECLARE_INSN(vse8_v, MATCH_VSE8_V, MASK_VSE8_V) DECLARE_INSN(vsetivli, MATCH_VSETIVLI, MASK_VSETIVLI) DECLARE_INSN(vsetvl, MATCH_VSETVL, MASK_VSETVL) DECLARE_INSN(vsetvli, MATCH_VSETVLI, MASK_VSETVLI) DECLARE_INSN(vsext_vf2, MATCH_VSEXT_VF2, MASK_VSEXT_VF2) DECLARE_INSN(vsext_vf4, MATCH_VSEXT_VF4, MASK_VSEXT_VF4) DECLARE_INSN(vsext_vf8, MATCH_VSEXT_VF8, MASK_VSEXT_VF8) DECLARE_INSN(vslide1down_vx, MATCH_VSLIDE1DOWN_VX, MASK_VSLIDE1DOWN_VX) DECLARE_INSN(vslide1up_vx, MATCH_VSLIDE1UP_VX, MASK_VSLIDE1UP_VX) DECLARE_INSN(vslidedown_vi, MATCH_VSLIDEDOWN_VI, MASK_VSLIDEDOWN_VI) DECLARE_INSN(vslidedown_vx, MATCH_VSLIDEDOWN_VX, MASK_VSLIDEDOWN_VX) DECLARE_INSN(vslideup_vi, MATCH_VSLIDEUP_VI, MASK_VSLIDEUP_VI) DECLARE_INSN(vslideup_vx, MATCH_VSLIDEUP_VX, MASK_VSLIDEUP_VX) DECLARE_INSN(vsll_vi, MATCH_VSLL_VI, MASK_VSLL_VI) DECLARE_INSN(vsll_vv, MATCH_VSLL_VV, MASK_VSLL_VV) DECLARE_INSN(vsll_vx, MATCH_VSLL_VX, MASK_VSLL_VX) DECLARE_INSN(vsm_v, MATCH_VSM_V, MASK_VSM_V) DECLARE_INSN(vsmul_vv, MATCH_VSMUL_VV, MASK_VSMUL_VV) DECLARE_INSN(vsmul_vx, MATCH_VSMUL_VX, MASK_VSMUL_VX) DECLARE_INSN(vsoxei1024_v, MATCH_VSOXEI1024_V, MASK_VSOXEI1024_V) DECLARE_INSN(vsoxei128_v, MATCH_VSOXEI128_V, MASK_VSOXEI128_V) DECLARE_INSN(vsoxei16_v, MATCH_VSOXEI16_V, MASK_VSOXEI16_V) DECLARE_INSN(vsoxei256_v, MATCH_VSOXEI256_V, MASK_VSOXEI256_V) DECLARE_INSN(vsoxei32_v, MATCH_VSOXEI32_V, MASK_VSOXEI32_V) DECLARE_INSN(vsoxei512_v, MATCH_VSOXEI512_V, MASK_VSOXEI512_V) DECLARE_INSN(vsoxei64_v, MATCH_VSOXEI64_V, MASK_VSOXEI64_V) DECLARE_INSN(vsoxei8_v, MATCH_VSOXEI8_V, MASK_VSOXEI8_V) DECLARE_INSN(vsra_vi, MATCH_VSRA_VI, MASK_VSRA_VI) DECLARE_INSN(vsra_vv, MATCH_VSRA_VV, MASK_VSRA_VV) DECLARE_INSN(vsra_vx, MATCH_VSRA_VX, MASK_VSRA_VX) DECLARE_INSN(vsrl_vi, MATCH_VSRL_VI, MASK_VSRL_VI) DECLARE_INSN(vsrl_vv, MATCH_VSRL_VV, MASK_VSRL_VV) DECLARE_INSN(vsrl_vx, MATCH_VSRL_VX, MASK_VSRL_VX) DECLARE_INSN(vsse1024_v, MATCH_VSSE1024_V, MASK_VSSE1024_V) DECLARE_INSN(vsse128_v, MATCH_VSSE128_V, MASK_VSSE128_V) DECLARE_INSN(vsse16_v, MATCH_VSSE16_V, MASK_VSSE16_V) DECLARE_INSN(vsse256_v, MATCH_VSSE256_V, MASK_VSSE256_V) DECLARE_INSN(vsse32_v, MATCH_VSSE32_V, MASK_VSSE32_V) DECLARE_INSN(vsse512_v, MATCH_VSSE512_V, MASK_VSSE512_V) DECLARE_INSN(vsse64_v, MATCH_VSSE64_V, MASK_VSSE64_V) DECLARE_INSN(vsse8_v, MATCH_VSSE8_V, MASK_VSSE8_V) DECLARE_INSN(vssra_vi, MATCH_VSSRA_VI, MASK_VSSRA_VI) DECLARE_INSN(vssra_vv, MATCH_VSSRA_VV, MASK_VSSRA_VV) DECLARE_INSN(vssra_vx, MATCH_VSSRA_VX, MASK_VSSRA_VX) DECLARE_INSN(vssrl_vi, MATCH_VSSRL_VI, MASK_VSSRL_VI) DECLARE_INSN(vssrl_vv, MATCH_VSSRL_VV, MASK_VSSRL_VV) DECLARE_INSN(vssrl_vx, MATCH_VSSRL_VX, MASK_VSSRL_VX) DECLARE_INSN(vssub_vv, MATCH_VSSUB_VV, MASK_VSSUB_VV) DECLARE_INSN(vssub_vx, MATCH_VSSUB_VX, MASK_VSSUB_VX) DECLARE_INSN(vssubu_vv, MATCH_VSSUBU_VV, MASK_VSSUBU_VV) DECLARE_INSN(vssubu_vx, MATCH_VSSUBU_VX, MASK_VSSUBU_VX) DECLARE_INSN(vsub_vv, MATCH_VSUB_VV, MASK_VSUB_VV) DECLARE_INSN(vsub_vx, MATCH_VSUB_VX, MASK_VSUB_VX) DECLARE_INSN(vsuxei1024_v, MATCH_VSUXEI1024_V, MASK_VSUXEI1024_V) DECLARE_INSN(vsuxei128_v, MATCH_VSUXEI128_V, MASK_VSUXEI128_V) DECLARE_INSN(vsuxei16_v, MATCH_VSUXEI16_V, MASK_VSUXEI16_V) DECLARE_INSN(vsuxei256_v, MATCH_VSUXEI256_V, MASK_VSUXEI256_V) DECLARE_INSN(vsuxei32_v, MATCH_VSUXEI32_V, MASK_VSUXEI32_V) DECLARE_INSN(vsuxei512_v, MATCH_VSUXEI512_V, MASK_VSUXEI512_V) DECLARE_INSN(vsuxei64_v, MATCH_VSUXEI64_V, MASK_VSUXEI64_V) DECLARE_INSN(vsuxei8_v, MATCH_VSUXEI8_V, MASK_VSUXEI8_V) DECLARE_INSN(vwadd_vv, MATCH_VWADD_VV, MASK_VWADD_VV) DECLARE_INSN(vwadd_vx, MATCH_VWADD_VX, MASK_VWADD_VX) DECLARE_INSN(vwadd_wv, MATCH_VWADD_WV, MASK_VWADD_WV) DECLARE_INSN(vwadd_wx, MATCH_VWADD_WX, MASK_VWADD_WX) DECLARE_INSN(vwaddu_vv, MATCH_VWADDU_VV, MASK_VWADDU_VV) DECLARE_INSN(vwaddu_vx, MATCH_VWADDU_VX, MASK_VWADDU_VX) DECLARE_INSN(vwaddu_wv, MATCH_VWADDU_WV, MASK_VWADDU_WV) DECLARE_INSN(vwaddu_wx, MATCH_VWADDU_WX, MASK_VWADDU_WX) DECLARE_INSN(vwmacc_vv, MATCH_VWMACC_VV, MASK_VWMACC_VV) DECLARE_INSN(vwmacc_vx, MATCH_VWMACC_VX, MASK_VWMACC_VX) DECLARE_INSN(vwmaccsu_vv, MATCH_VWMACCSU_VV, MASK_VWMACCSU_VV) DECLARE_INSN(vwmaccsu_vx, MATCH_VWMACCSU_VX, MASK_VWMACCSU_VX) DECLARE_INSN(vwmaccu_vv, MATCH_VWMACCU_VV, MASK_VWMACCU_VV) DECLARE_INSN(vwmaccu_vx, MATCH_VWMACCU_VX, MASK_VWMACCU_VX) DECLARE_INSN(vwmaccus_vx, MATCH_VWMACCUS_VX, MASK_VWMACCUS_VX) DECLARE_INSN(vwmul_vv, MATCH_VWMUL_VV, MASK_VWMUL_VV) DECLARE_INSN(vwmul_vx, MATCH_VWMUL_VX, MASK_VWMUL_VX) DECLARE_INSN(vwmulsu_vv, MATCH_VWMULSU_VV, MASK_VWMULSU_VV) DECLARE_INSN(vwmulsu_vx, MATCH_VWMULSU_VX, MASK_VWMULSU_VX) DECLARE_INSN(vwmulu_vv, MATCH_VWMULU_VV, MASK_VWMULU_VV) DECLARE_INSN(vwmulu_vx, MATCH_VWMULU_VX, MASK_VWMULU_VX) DECLARE_INSN(vwredsum_vs, MATCH_VWREDSUM_VS, MASK_VWREDSUM_VS) DECLARE_INSN(vwredsumu_vs, MATCH_VWREDSUMU_VS, MASK_VWREDSUMU_VS) DECLARE_INSN(vwsub_vv, MATCH_VWSUB_VV, MASK_VWSUB_VV) DECLARE_INSN(vwsub_vx, MATCH_VWSUB_VX, MASK_VWSUB_VX) DECLARE_INSN(vwsub_wv, MATCH_VWSUB_WV, MASK_VWSUB_WV) DECLARE_INSN(vwsub_wx, MATCH_VWSUB_WX, MASK_VWSUB_WX) DECLARE_INSN(vwsubu_vv, MATCH_VWSUBU_VV, MASK_VWSUBU_VV) DECLARE_INSN(vwsubu_vx, MATCH_VWSUBU_VX, MASK_VWSUBU_VX) DECLARE_INSN(vwsubu_wv, MATCH_VWSUBU_WV, MASK_VWSUBU_WV) DECLARE_INSN(vwsubu_wx, MATCH_VWSUBU_WX, MASK_VWSUBU_WX) DECLARE_INSN(vxor_vi, MATCH_VXOR_VI, MASK_VXOR_VI) DECLARE_INSN(vxor_vv, MATCH_VXOR_VV, MASK_VXOR_VV) DECLARE_INSN(vxor_vx, MATCH_VXOR_VX, MASK_VXOR_VX) DECLARE_INSN(vzext_vf2, MATCH_VZEXT_VF2, MASK_VZEXT_VF2) DECLARE_INSN(vzext_vf4, MATCH_VZEXT_VF4, MASK_VZEXT_VF4) DECLARE_INSN(vzext_vf8, MATCH_VZEXT_VF8, MASK_VZEXT_VF8) DECLARE_INSN(wext, MATCH_WEXT, MASK_WEXT) DECLARE_INSN(wexti, MATCH_WEXTI, MASK_WEXTI) DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) DECLARE_INSN(wrs_nto, MATCH_WRS_NTO, MASK_WRS_NTO) DECLARE_INSN(wrs_sto, MATCH_WRS_STO, MASK_WRS_STO) DECLARE_INSN(xnor, MATCH_XNOR, MASK_XNOR) DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) DECLARE_INSN(xperm16, MATCH_XPERM16, MASK_XPERM16) DECLARE_INSN(xperm32, MATCH_XPERM32, MASK_XPERM32) DECLARE_INSN(xperm4, MATCH_XPERM4, MASK_XPERM4) DECLARE_INSN(xperm8, MATCH_XPERM8, MASK_XPERM8) DECLARE_INSN(zunpkd810, MATCH_ZUNPKD810, MASK_ZUNPKD810) DECLARE_INSN(zunpkd820, MATCH_ZUNPKD820, MASK_ZUNPKD820) DECLARE_INSN(zunpkd830, MATCH_ZUNPKD830, MASK_ZUNPKD830) DECLARE_INSN(zunpkd831, MATCH_ZUNPKD831, MASK_ZUNPKD831) DECLARE_INSN(zunpkd832, MATCH_ZUNPKD832, MASK_ZUNPKD832) #endif #ifdef DECLARE_CSR DECLARE_CSR(fflags, CSR_FFLAGS) DECLARE_CSR(frm, CSR_FRM) DECLARE_CSR(fcsr, CSR_FCSR) DECLARE_CSR(vstart, CSR_VSTART) DECLARE_CSR(vxsat, CSR_VXSAT) DECLARE_CSR(vxrm, CSR_VXRM) DECLARE_CSR(vcsr, CSR_VCSR) DECLARE_CSR(seed, CSR_SEED) DECLARE_CSR(cycle, CSR_CYCLE) DECLARE_CSR(time, CSR_TIME) DECLARE_CSR(instret, CSR_INSTRET) DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3) DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4) DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5) DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6) DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7) DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8) DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9) DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10) DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11) DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12) DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13) DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14) DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15) DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16) DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17) DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18) DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19) DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20) DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21) DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22) DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23) DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24) DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25) DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26) DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27) DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28) DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29) DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30) DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31) DECLARE_CSR(vl, CSR_VL) DECLARE_CSR(vtype, CSR_VTYPE) DECLARE_CSR(vlenb, CSR_VLENB) DECLARE_CSR(sstatus, CSR_SSTATUS) DECLARE_CSR(sedeleg, CSR_SEDELEG) DECLARE_CSR(sideleg, CSR_SIDELEG) DECLARE_CSR(sie, CSR_SIE) DECLARE_CSR(stvec, CSR_STVEC) DECLARE_CSR(scounteren, CSR_SCOUNTEREN) DECLARE_CSR(senvcfg, CSR_SENVCFG) DECLARE_CSR(sstateen0, CSR_SSTATEEN0) DECLARE_CSR(sstateen1, CSR_SSTATEEN1) DECLARE_CSR(sstateen2, CSR_SSTATEEN2) DECLARE_CSR(sstateen3, CSR_SSTATEEN3) DECLARE_CSR(sscratch, CSR_SSCRATCH) DECLARE_CSR(sepc, CSR_SEPC) DECLARE_CSR(scause, CSR_SCAUSE) DECLARE_CSR(stval, CSR_STVAL) DECLARE_CSR(sip, CSR_SIP) DECLARE_CSR(stimecmp, CSR_STIMECMP) DECLARE_CSR(satp, CSR_SATP) DECLARE_CSR(scontext, CSR_SCONTEXT) DECLARE_CSR(vsstatus, CSR_VSSTATUS) DECLARE_CSR(vsie, CSR_VSIE) DECLARE_CSR(vstvec, CSR_VSTVEC) DECLARE_CSR(vsscratch, CSR_VSSCRATCH) DECLARE_CSR(vsepc, CSR_VSEPC) DECLARE_CSR(vscause, CSR_VSCAUSE) DECLARE_CSR(vstval, CSR_VSTVAL) DECLARE_CSR(vsip, CSR_VSIP) DECLARE_CSR(vstimecmp, CSR_VSTIMECMP) DECLARE_CSR(vsatp, CSR_VSATP) DECLARE_CSR(hstatus, CSR_HSTATUS) DECLARE_CSR(hedeleg, CSR_HEDELEG) DECLARE_CSR(hideleg, CSR_HIDELEG) DECLARE_CSR(hie, CSR_HIE) DECLARE_CSR(htimedelta, CSR_HTIMEDELTA) DECLARE_CSR(hcounteren, CSR_HCOUNTEREN) DECLARE_CSR(hgeie, CSR_HGEIE) DECLARE_CSR(henvcfg, CSR_HENVCFG) DECLARE_CSR(hstateen0, CSR_HSTATEEN0) DECLARE_CSR(hstateen1, CSR_HSTATEEN1) DECLARE_CSR(hstateen2, CSR_HSTATEEN2) DECLARE_CSR(hstateen3, CSR_HSTATEEN3) DECLARE_CSR(htval, CSR_HTVAL) DECLARE_CSR(hip, CSR_HIP) DECLARE_CSR(hvip, CSR_HVIP) DECLARE_CSR(htinst, CSR_HTINST) DECLARE_CSR(hgatp, CSR_HGATP) DECLARE_CSR(hcontext, CSR_HCONTEXT) DECLARE_CSR(hgeip, CSR_HGEIP) DECLARE_CSR(scountovf, CSR_SCOUNTOVF) DECLARE_CSR(utvt, CSR_UTVT) DECLARE_CSR(unxti, CSR_UNXTI) DECLARE_CSR(uintstatus, CSR_UINTSTATUS) DECLARE_CSR(uscratchcsw, CSR_USCRATCHCSW) DECLARE_CSR(uscratchcswl, CSR_USCRATCHCSWL) DECLARE_CSR(stvt, CSR_STVT) DECLARE_CSR(snxti, CSR_SNXTI) DECLARE_CSR(sintstatus, CSR_SINTSTATUS) DECLARE_CSR(sscratchcsw, CSR_SSCRATCHCSW) DECLARE_CSR(sscratchcswl, CSR_SSCRATCHCSWL) DECLARE_CSR(mtvt, CSR_MTVT) DECLARE_CSR(mnxti, CSR_MNXTI) DECLARE_CSR(mintstatus, CSR_MINTSTATUS) DECLARE_CSR(mscratchcsw, CSR_MSCRATCHCSW) DECLARE_CSR(mscratchcswl, CSR_MSCRATCHCSWL) DECLARE_CSR(mstatus, CSR_MSTATUS) DECLARE_CSR(misa, CSR_MISA) DECLARE_CSR(medeleg, CSR_MEDELEG) DECLARE_CSR(mideleg, CSR_MIDELEG) DECLARE_CSR(mie, CSR_MIE) DECLARE_CSR(mtvec, CSR_MTVEC) DECLARE_CSR(mcounteren, CSR_MCOUNTEREN) DECLARE_CSR(menvcfg, CSR_MENVCFG) DECLARE_CSR(mstateen0, CSR_MSTATEEN0) DECLARE_CSR(mstateen1, CSR_MSTATEEN1) DECLARE_CSR(mstateen2, CSR_MSTATEEN2) DECLARE_CSR(mstateen3, CSR_MSTATEEN3) DECLARE_CSR(mcountinhibit, CSR_MCOUNTINHIBIT) DECLARE_CSR(mscratch, CSR_MSCRATCH) DECLARE_CSR(mepc, CSR_MEPC) DECLARE_CSR(mcause, CSR_MCAUSE) DECLARE_CSR(mtval, CSR_MTVAL) DECLARE_CSR(mip, CSR_MIP) DECLARE_CSR(mtinst, CSR_MTINST) DECLARE_CSR(mtval2, CSR_MTVAL2) DECLARE_CSR(pmpcfg0, CSR_PMPCFG0) DECLARE_CSR(pmpcfg1, CSR_PMPCFG1) DECLARE_CSR(pmpcfg2, CSR_PMPCFG2) DECLARE_CSR(pmpcfg3, CSR_PMPCFG3) DECLARE_CSR(pmpcfg4, CSR_PMPCFG4) DECLARE_CSR(pmpcfg5, CSR_PMPCFG5) DECLARE_CSR(pmpcfg6, CSR_PMPCFG6) DECLARE_CSR(pmpcfg7, CSR_PMPCFG7) DECLARE_CSR(pmpcfg8, CSR_PMPCFG8) DECLARE_CSR(pmpcfg9, CSR_PMPCFG9) DECLARE_CSR(pmpcfg10, CSR_PMPCFG10) DECLARE_CSR(pmpcfg11, CSR_PMPCFG11) DECLARE_CSR(pmpcfg12, CSR_PMPCFG12) DECLARE_CSR(pmpcfg13, CSR_PMPCFG13) DECLARE_CSR(pmpcfg14, CSR_PMPCFG14) DECLARE_CSR(pmpcfg15, CSR_PMPCFG15) DECLARE_CSR(pmpaddr0, CSR_PMPADDR0) DECLARE_CSR(pmpaddr1, CSR_PMPADDR1) DECLARE_CSR(pmpaddr2, CSR_PMPADDR2) DECLARE_CSR(pmpaddr3, CSR_PMPADDR3) DECLARE_CSR(pmpaddr4, CSR_PMPADDR4) DECLARE_CSR(pmpaddr5, CSR_PMPADDR5) DECLARE_CSR(pmpaddr6, CSR_PMPADDR6) DECLARE_CSR(pmpaddr7, CSR_PMPADDR7) DECLARE_CSR(pmpaddr8, CSR_PMPADDR8) DECLARE_CSR(pmpaddr9, CSR_PMPADDR9) DECLARE_CSR(pmpaddr10, CSR_PMPADDR10) DECLARE_CSR(pmpaddr11, CSR_PMPADDR11) DECLARE_CSR(pmpaddr12, CSR_PMPADDR12) DECLARE_CSR(pmpaddr13, CSR_PMPADDR13) DECLARE_CSR(pmpaddr14, CSR_PMPADDR14) DECLARE_CSR(pmpaddr15, CSR_PMPADDR15) DECLARE_CSR(pmpaddr16, CSR_PMPADDR16) DECLARE_CSR(pmpaddr17, CSR_PMPADDR17) DECLARE_CSR(pmpaddr18, CSR_PMPADDR18) DECLARE_CSR(pmpaddr19, CSR_PMPADDR19) DECLARE_CSR(pmpaddr20, CSR_PMPADDR20) DECLARE_CSR(pmpaddr21, CSR_PMPADDR21) DECLARE_CSR(pmpaddr22, CSR_PMPADDR22) DECLARE_CSR(pmpaddr23, CSR_PMPADDR23) DECLARE_CSR(pmpaddr24, CSR_PMPADDR24) DECLARE_CSR(pmpaddr25, CSR_PMPADDR25) DECLARE_CSR(pmpaddr26, CSR_PMPADDR26) DECLARE_CSR(pmpaddr27, CSR_PMPADDR27) DECLARE_CSR(pmpaddr28, CSR_PMPADDR28) DECLARE_CSR(pmpaddr29, CSR_PMPADDR29) DECLARE_CSR(pmpaddr30, CSR_PMPADDR30) DECLARE_CSR(pmpaddr31, CSR_PMPADDR31) DECLARE_CSR(pmpaddr32, CSR_PMPADDR32) DECLARE_CSR(pmpaddr33, CSR_PMPADDR33) DECLARE_CSR(pmpaddr34, CSR_PMPADDR34) DECLARE_CSR(pmpaddr35, CSR_PMPADDR35) DECLARE_CSR(pmpaddr36, CSR_PMPADDR36) DECLARE_CSR(pmpaddr37, CSR_PMPADDR37) DECLARE_CSR(pmpaddr38, CSR_PMPADDR38) DECLARE_CSR(pmpaddr39, CSR_PMPADDR39) DECLARE_CSR(pmpaddr40, CSR_PMPADDR40) DECLARE_CSR(pmpaddr41, CSR_PMPADDR41) DECLARE_CSR(pmpaddr42, CSR_PMPADDR42) DECLARE_CSR(pmpaddr43, CSR_PMPADDR43) DECLARE_CSR(pmpaddr44, CSR_PMPADDR44) DECLARE_CSR(pmpaddr45, CSR_PMPADDR45) DECLARE_CSR(pmpaddr46, CSR_PMPADDR46) DECLARE_CSR(pmpaddr47, CSR_PMPADDR47) DECLARE_CSR(pmpaddr48, CSR_PMPADDR48) DECLARE_CSR(pmpaddr49, CSR_PMPADDR49) DECLARE_CSR(pmpaddr50, CSR_PMPADDR50) DECLARE_CSR(pmpaddr51, CSR_PMPADDR51) DECLARE_CSR(pmpaddr52, CSR_PMPADDR52) DECLARE_CSR(pmpaddr53, CSR_PMPADDR53) DECLARE_CSR(pmpaddr54, CSR_PMPADDR54) DECLARE_CSR(pmpaddr55, CSR_PMPADDR55) DECLARE_CSR(pmpaddr56, CSR_PMPADDR56) DECLARE_CSR(pmpaddr57, CSR_PMPADDR57) DECLARE_CSR(pmpaddr58, CSR_PMPADDR58) DECLARE_CSR(pmpaddr59, CSR_PMPADDR59) DECLARE_CSR(pmpaddr60, CSR_PMPADDR60) DECLARE_CSR(pmpaddr61, CSR_PMPADDR61) DECLARE_CSR(pmpaddr62, CSR_PMPADDR62) DECLARE_CSR(pmpaddr63, CSR_PMPADDR63) DECLARE_CSR(mseccfg, CSR_MSECCFG) DECLARE_CSR(tselect, CSR_TSELECT) DECLARE_CSR(tdata1, CSR_TDATA1) DECLARE_CSR(tdata2, CSR_TDATA2) DECLARE_CSR(tdata3, CSR_TDATA3) DECLARE_CSR(tinfo, CSR_TINFO) DECLARE_CSR(tcontrol, CSR_TCONTROL) DECLARE_CSR(mcontext, CSR_MCONTEXT) DECLARE_CSR(mscontext, CSR_MSCONTEXT) DECLARE_CSR(dcsr, CSR_DCSR) DECLARE_CSR(dpc, CSR_DPC) DECLARE_CSR(dscratch0, CSR_DSCRATCH0) DECLARE_CSR(dscratch1, CSR_DSCRATCH1) DECLARE_CSR(mcycle, CSR_MCYCLE) DECLARE_CSR(minstret, CSR_MINSTRET) DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3) DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4) DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5) DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6) DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7) DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8) DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9) DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10) DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11) DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12) DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13) DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14) DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15) DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16) DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17) DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18) DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19) DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20) DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21) DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22) DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23) DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24) DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25) DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26) DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27) DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28) DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29) DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30) DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31) DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3) DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4) DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5) DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6) DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7) DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8) DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9) DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10) DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11) DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12) DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13) DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14) DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15) DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16) DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17) DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18) DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19) DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20) DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21) DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22) DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23) DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24) DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25) DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26) DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27) DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28) DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29) DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30) DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31) DECLARE_CSR(mvendorid, CSR_MVENDORID) DECLARE_CSR(marchid, CSR_MARCHID) DECLARE_CSR(mimpid, CSR_MIMPID) DECLARE_CSR(mhartid, CSR_MHARTID) DECLARE_CSR(mconfigptr, CSR_MCONFIGPTR) DECLARE_CSR(stimecmph, CSR_STIMECMPH) DECLARE_CSR(vstimecmph, CSR_VSTIMECMPH) DECLARE_CSR(htimedeltah, CSR_HTIMEDELTAH) DECLARE_CSR(henvcfgh, CSR_HENVCFGH) DECLARE_CSR(hstateen0h, CSR_HSTATEEN0H) DECLARE_CSR(hstateen1h, CSR_HSTATEEN1H) DECLARE_CSR(hstateen2h, CSR_HSTATEEN2H) DECLARE_CSR(hstateen3h, CSR_HSTATEEN3H) DECLARE_CSR(cycleh, CSR_CYCLEH) DECLARE_CSR(timeh, CSR_TIMEH) DECLARE_CSR(instreth, CSR_INSTRETH) DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H) DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H) DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H) DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H) DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H) DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H) DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H) DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H) DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H) DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H) DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H) DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H) DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H) DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H) DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H) DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H) DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H) DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H) DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H) DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H) DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H) DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H) DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H) DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H) DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H) DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H) DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H) DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H) DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H) DECLARE_CSR(mstatush, CSR_MSTATUSH) DECLARE_CSR(menvcfgh, CSR_MENVCFGH) DECLARE_CSR(mstateen0h, CSR_MSTATEEN0H) DECLARE_CSR(mstateen1h, CSR_MSTATEEN1H) DECLARE_CSR(mstateen2h, CSR_MSTATEEN2H) DECLARE_CSR(mstateen3h, CSR_MSTATEEN3H) DECLARE_CSR(mhpmevent3h, CSR_MHPMEVENT3H) DECLARE_CSR(mhpmevent4h, CSR_MHPMEVENT4H) DECLARE_CSR(mhpmevent5h, CSR_MHPMEVENT5H) DECLARE_CSR(mhpmevent6h, CSR_MHPMEVENT6H) DECLARE_CSR(mhpmevent7h, CSR_MHPMEVENT7H) DECLARE_CSR(mhpmevent8h, CSR_MHPMEVENT8H) DECLARE_CSR(mhpmevent9h, CSR_MHPMEVENT9H) DECLARE_CSR(mhpmevent10h, CSR_MHPMEVENT10H) DECLARE_CSR(mhpmevent11h, CSR_MHPMEVENT11H) DECLARE_CSR(mhpmevent12h, CSR_MHPMEVENT12H) DECLARE_CSR(mhpmevent13h, CSR_MHPMEVENT13H) DECLARE_CSR(mhpmevent14h, CSR_MHPMEVENT14H) DECLARE_CSR(mhpmevent15h, CSR_MHPMEVENT15H) DECLARE_CSR(mhpmevent16h, CSR_MHPMEVENT16H) DECLARE_CSR(mhpmevent17h, CSR_MHPMEVENT17H) DECLARE_CSR(mhpmevent18h, CSR_MHPMEVENT18H) DECLARE_CSR(mhpmevent19h, CSR_MHPMEVENT19H) DECLARE_CSR(mhpmevent20h, CSR_MHPMEVENT20H) DECLARE_CSR(mhpmevent21h, CSR_MHPMEVENT21H) DECLARE_CSR(mhpmevent22h, CSR_MHPMEVENT22H) DECLARE_CSR(mhpmevent23h, CSR_MHPMEVENT23H) DECLARE_CSR(mhpmevent24h, CSR_MHPMEVENT24H) DECLARE_CSR(mhpmevent25h, CSR_MHPMEVENT25H) DECLARE_CSR(mhpmevent26h, CSR_MHPMEVENT26H) DECLARE_CSR(mhpmevent27h, CSR_MHPMEVENT27H) DECLARE_CSR(mhpmevent28h, CSR_MHPMEVENT28H) DECLARE_CSR(mhpmevent29h, CSR_MHPMEVENT29H) DECLARE_CSR(mhpmevent30h, CSR_MHPMEVENT30H) DECLARE_CSR(mhpmevent31h, CSR_MHPMEVENT31H) DECLARE_CSR(mseccfgh, CSR_MSECCFGH) DECLARE_CSR(mcycleh, CSR_MCYCLEH) DECLARE_CSR(minstreth, CSR_MINSTRETH) DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H) DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H) DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H) DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H) DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H) DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H) DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H) DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H) DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H) DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H) DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H) DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H) DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H) DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H) DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H) DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H) DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H) DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H) DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H) DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H) DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H) DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H) DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H) DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H) DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H) DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H) DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H) DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H) DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H) #endif #ifdef DECLARE_CAUSE DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) DECLARE_CAUSE("fetch access", CAUSE_FETCH_ACCESS) DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS) DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS) DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) DECLARE_CAUSE("virtual_supervisor_ecall", CAUSE_VIRTUAL_SUPERVISOR_ECALL) DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT) DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT) DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT) DECLARE_CAUSE("fetch guest page fault", CAUSE_FETCH_GUEST_PAGE_FAULT) DECLARE_CAUSE("load guest page fault", CAUSE_LOAD_GUEST_PAGE_FAULT) DECLARE_CAUSE("virtual instruction", CAUSE_VIRTUAL_INSTRUCTION) DECLARE_CAUSE("store guest page fault", CAUSE_STORE_GUEST_PAGE_FAULT) #endif optee_os-4.3.0/core/arch/riscv/include/kernel/000077500000000000000000000000001464416617300212455ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/include/kernel/arch_scall.h000066400000000000000000000012601464416617300235100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __KERNEL_ARCH_SCALL_H #define __KERNEL_ARCH_SCALL_H #include #include #include static inline void scall_get_max_args(struct thread_scall_regs *regs, size_t *scn, size_t *max_args) { *scn = regs->t0; *max_args = regs->t1; } static inline void scall_set_retval(struct thread_scall_regs *regs, uint32_t ret_val) { regs->a0 = ret_val; } static inline void scall_set_sys_return_regs(struct thread_scall_regs *regs, bool panic, uint32_t panic_code) { regs->a1 = panic; regs->a2 = panic_code; } #endif /*__KERNEL_ARCH_SCALL_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/cache_helpers_arch.h000066400000000000000000000003001464416617300251710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __KERNEL_CACHE_HELPERS_ARCH_H #define __KERNEL_CACHE_HELPERS_ARCH_H #endif /*__KERNEL_CACHE_HELPERS_ARCH_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/clint.h000066400000000000000000000025211464416617300225270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __KERNEL_CLINT_H #define __KERNEL_CLINT_H #include #include #include #include #ifdef CFG_RISCV_M_MODE /* Machine software-interrupt pending register for a specific hart */ #define CLINT_MSIP(hart) (CLINT_BASE + (4 * (hart))) /* Register for setting mtimecmp for a specific hart */ #define CLINT_MTIMECMP(hart)(CLINT_BASE + 0x4000 + (8 * (hart))) /* Number of cycles counted from the RTCCLK input */ #define CLINT_MTIME (CLINT_BASE + 0xbff8) static inline void clint_ipi_send(unsigned long hart) { assert(hart < CFG_TEE_CORE_NB_CORE); io_write32(CLINT_MSIP(hart), 1); } static inline void clint_ipi_clear(unsigned long hart) { assert(hart < CFG_TEE_CORE_NB_CORE); io_write32(CLINT_MSIP(hart), 0); } static inline void clint_set_mtimecmp(uint64_t timecmp) { /* Each hart has a separate source of timer interrupts */ io_write64(CLINT_MTIMECMP(get_core_pos()), timecmp); } static inline uint64_t clint_get_mtimecmp(void) { return io_read64(CLINT_MTIMECMP(get_core_pos())); } static inline uint64_t clint_get_mtime(void) { return io_read64(CLINT_MTIME); } static inline void clint_set_mtime(uint64_t mtime) { io_write64(CLINT_MTIME, mtime); } #endif /* CFG_RISCV_M_MODE */ #endif /* __KERNEL_CLINT_H */ optee_os-4.3.0/core/arch/riscv/include/kernel/delay_arch.h000066400000000000000000000005461464416617300235160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __KERNEL_DELAY_ARCH_H #define __KERNEL_DELAY_ARCH_H #include #include static inline unsigned int delay_cnt_freq(void) { return read_cntfrq(); } static inline uint64_t delay_cnt_read(void) { return read_time(); } #endif /*__KERNEL_DELAY_ARCH_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/misc_arch.h000066400000000000000000000002451464416617300233470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __KERNEL_MISC_ARCH_H #define __KERNEL_MISC_ARCH_H #endif /*__KERNEL_MISC_ARCH_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/secure_partition.h000066400000000000000000000012771464416617300250040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __KERNEL_SECURE_PARTITION_H #define __KERNEL_SECURE_PARTITION_H #include #include #include #include struct sp_ctx { struct user_mode_ctx uctx; struct ts_ctx ts_ctx; }; static inline bool is_sp_ctx(struct ts_ctx *ctx __unused) { return false; } static inline struct sp_session *__noprof to_sp_session(struct ts_session *sess __unused) { assert(is_sp_ctx(sess->ctx)); return NULL; } static inline struct sp_ctx *to_sp_ctx(struct ts_ctx *ctx __unused) { assert(is_sp_ctx(ctx)); return NULL; } #endif /* __KERNEL_SECURE_PARTITION_H */ optee_os-4.3.0/core/arch/riscv/include/kernel/stmm_sp.h000066400000000000000000000016141464416617300231020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __KERNEL_STMM_SP_H #define __KERNEL_STMM_SP_H #include #include #include #include #include struct stmm_ctx { struct user_mode_ctx uctx; struct tee_ta_ctx ta_ctx; }; static inline bool is_stmm_ctx(struct ts_ctx *ctx __unused) { return false; } static inline struct stmm_ctx *to_stmm_ctx(struct ts_ctx *ctx __unused) { assert(is_stmm_ctx(ctx)); return NULL; } static inline TEE_Result stmm_init_session(const TEE_UUID *uuid __unused, struct tee_ta_session *s __unused) { return TEE_ERROR_ITEM_NOT_FOUND; } static inline TEE_Result stmm_complete_session(struct tee_ta_session *s __unused) { return TEE_ERROR_GENERIC; } static inline const TEE_UUID *stmm_get_uuid(void) { return NULL; } #endif /*__KERNEL_STMM_SP_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/tee_l2cc_mutex.h000066400000000000000000000002651464416617300243230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __KERNEL_TEE_L2CC_MUTEX_H #define __KERNEL_TEE_L2CC_MUTEX_H #endif /* __KERNEL_TEE_L2CC_MUTEX_H */ optee_os-4.3.0/core/arch/riscv/include/kernel/thread_arch.h000066400000000000000000000111671464416617300236700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __KERNEL_THREAD_ARCH_H #define __KERNEL_THREAD_ARCH_H #ifndef __ASSEMBLER__ #include #include #include #endif #ifndef __ASSEMBLER__ #define THREAD_CORE_LOCAL_ALIGNED __aligned(16) struct thread_pauth_keys { }; struct thread_core_local { unsigned long x[4]; uint32_t hart_id; vaddr_t tmp_stack_va_end; short int curr_thread; uint32_t flags; vaddr_t abt_stack_va_end; #ifdef CFG_TEE_CORE_DEBUG unsigned int locked_count; /* Number of spinlocks held */ #endif #ifdef CFG_CORE_DEBUG_CHECK_STACKS bool stackcheck_recursion; #endif #ifdef CFG_FAULT_MITIGATION struct ftmn_func_arg *ftmn_arg; #endif } THREAD_CORE_LOCAL_ALIGNED; struct thread_user_vfp_state { }; struct thread_abi_args { unsigned long a0; /* ABI function ID */ unsigned long a1; /* Parameter */ unsigned long a2; /* Parameter */ unsigned long a3; /* Thread ID when returning from RPC */ unsigned long a4; /* Not used */ unsigned long a5; /* Not used */ unsigned long a6; /* Not used */ unsigned long a7; /* Hypervisor Client ID */ }; struct thread_abort_regs { unsigned long ra; unsigned long sp; unsigned long gp; unsigned long tp; unsigned long t0; unsigned long t1; unsigned long t2; unsigned long s0; unsigned long s1; unsigned long a0; unsigned long a1; unsigned long a2; unsigned long a3; unsigned long a4; unsigned long a5; unsigned long a6; unsigned long a7; unsigned long s2; unsigned long s3; unsigned long s4; unsigned long s5; unsigned long s6; unsigned long s7; unsigned long s8; unsigned long s9; unsigned long s10; unsigned long s11; unsigned long t3; unsigned long t4; unsigned long t5; unsigned long t6; unsigned long epc; unsigned long status; unsigned long ie; unsigned long cause; unsigned long tval; } __aligned(16); struct thread_scall_regs { unsigned long ra; unsigned long sp; unsigned long gp; unsigned long tp; unsigned long t0; unsigned long t1; unsigned long t2; unsigned long a0; unsigned long a1; unsigned long a2; unsigned long a3; unsigned long a4; unsigned long a5; unsigned long a6; unsigned long a7; unsigned long t3; unsigned long t4; unsigned long t5; unsigned long t6; unsigned long epc; unsigned long status; unsigned long ie; } __aligned(16); struct thread_ctx_regs { unsigned long ra; unsigned long sp; unsigned long gp; unsigned long tp; unsigned long t0; unsigned long t1; unsigned long t2; unsigned long s0; unsigned long s1; unsigned long a0; unsigned long a1; unsigned long a2; unsigned long a3; unsigned long a4; unsigned long a5; unsigned long a6; unsigned long a7; unsigned long s2; unsigned long s3; unsigned long s4; unsigned long s5; unsigned long s6; unsigned long s7; unsigned long s8; unsigned long s9; unsigned long s10; unsigned long s11; unsigned long t3; unsigned long t4; unsigned long t5; unsigned long t6; unsigned long epc; unsigned long status; unsigned long ie; }; struct user_mode_ctx; /* * These flags should vary according to the privilege mode selected * to run OP-TEE core on (M/HS/S). For now default to S-Mode. */ #define CSR_XIE_SIE BIT64(IRQ_XSOFT) #define CSR_XIE_TIE BIT64(IRQ_XTIMER) #define CSR_XIE_EIE BIT64(IRQ_XEXT) #define THREAD_EXCP_FOREIGN_INTR CSR_XIE_EIE #define THREAD_EXCP_NATIVE_INTR (CSR_XIE_SIE | CSR_XIE_TIE) #define THREAD_EXCP_ALL (THREAD_EXCP_FOREIGN_INTR |\ THREAD_EXCP_NATIVE_INTR) #ifdef CFG_WITH_VFP uint32_t thread_kernel_enable_vfp(void); void thread_kernel_disable_vfp(uint32_t state); void thread_kernel_save_vfp(void); void thread_kernel_restore_vfp(void); void thread_user_enable_vfp(struct thread_user_vfp_state *uvfp); #else /*CFG_WITH_VFP*/ static inline void thread_kernel_save_vfp(void) { } static inline void thread_kernel_restore_vfp(void) { } #endif /*CFG_WITH_VFP*/ #ifdef CFG_WITH_VFP void thread_user_save_vfp(void); #else static inline void thread_user_save_vfp(void) { } #endif #ifdef CFG_WITH_VFP void thread_user_clear_vfp(struct user_mode_ctx *uctx); #else static inline void thread_user_clear_vfp(struct user_mode_ctx *uctx __unused) { } #endif vaddr_t thread_get_saved_thread_sp(void); static inline void thread_get_user_kcode(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz) { *mobj = NULL; *offset = 0; *va = 0; *sz = 0; } static inline void thread_get_user_kdata(struct mobj **mobj, size_t *offset, vaddr_t *va, size_t *sz) { *mobj = NULL; *offset = 0; *va = 0; *sz = 0; } bool thread_disable_prealloc_rpc_cache(uint64_t *cookie); bool thread_enable_prealloc_rpc_cache(void); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_THREAD_ARCH_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/thread_private_arch.h000066400000000000000000000072721464416617300254240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __KERNEL_THREAD_PRIVATE_ARCH_H #define __KERNEL_THREAD_PRIVATE_ARCH_H #ifndef __ASSEMBLER__ #include #define STACK_TMP_OFFS 0 #if defined(__clang__) && !defined(__OPTIMIZE_SIZE__) #define STACK_TMP_SIZE (4096 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) #else #define STACK_TMP_SIZE (2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA) #endif #define STACK_THREAD_SIZE (8192 + CFG_STACK_THREAD_EXTRA) #if TRACE_LEVEL > 0 #define STACK_ABT_SIZE 3072 #else #define STACK_ABT_SIZE 1024 #endif #define STACK_CHECK_EXTRA 0 #define THREAD_RPC_NUM_ARGS 4 #define TRAP_MODE_KERNEL 0 #define TRAP_MODE_USER 1 struct thread_user_mode_rec { unsigned long ctx_regs_ptr; unsigned long exit_status0_ptr; unsigned long exit_status1_ptr; unsigned long pad; /* * x[] is used to save registers for user/kernel context-switching * 0-3: ra-tp * 4-6: s0-s1 * 6-15: s2-s11 */ unsigned long x[16]; }; extern long thread_user_kcode_offset; void thread_interrupt_handler(unsigned long cause, struct thread_ctx_regs *regs); /* * Initializes TVEC for current hart. Called by thread_init_per_cpu() */ void thread_init_tvec(void); void thread_trap_vect(void); void thread_trap_vect_end(void); void thread_return_to_udomain(unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); void __panic_at_abi_return(void); /* Helper function to prepare CSR status for exception return */ unsigned long xstatus_for_xret(uint8_t pie, uint8_t pp); /* * Assembly function as the first function in a thread. Handles a stdcall, * a0-a3 holds the parameters. Hands over to __thread_std_abi_entry() when * everything is set up and does some post processing once * __thread_std_abi_entry() returns. */ void thread_std_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); uint32_t __thread_std_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); /* * Called from assembly only, vector_fast_abi_entry(). Handles a fast ABI * by dispatching it to the registered fast ABI handler. */ void thread_handle_fast_abi(struct thread_abi_args *args); /* * Called from assembly only, vector_std_abi_entry(). Handles a std ABI by * dispatching it to the registered std ABI handler. */ uint32_t thread_handle_std_abi(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7); /* * Private functions made available for thread_rv.S */ int thread_state_suspend(uint32_t flags, unsigned long status, vaddr_t pc); void thread_resume(struct thread_ctx_regs *regs); uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, uint32_t *exit_status0, uint32_t *exit_status1); void *thread_get_tmp_sp(void); void thread_state_free(void); struct thread_ctx_regs *thread_get_ctx_regs(void); void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5); void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3); void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS], unsigned long status); void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]); static inline void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) { __thread_rpc(rv); } void thread_scall_handler(struct thread_scall_regs *regs); void thread_exit_user_mode(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long sp, unsigned long pc, unsigned long status); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_THREAD_PRIVATE_ARCH_H*/ optee_os-4.3.0/core/arch/riscv/include/kernel/tlb_helpers.h000066400000000000000000000005511464416617300237220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __KERNEL_TLB_HELPERS_H #define __KERNEL_TLB_HELPERS_H #ifndef __ASSEMBLER__ void tlbi_all(void); void tlbi_va_allasid(vaddr_t va); void tlbi_asid(unsigned long asid); void tlbi_va_asid(vaddr_t va, uint32_t asid); #endif /*!__ASSEMBLER__*/ #endif /* __KERNEL_TLB_HELPERS_H */ optee_os-4.3.0/core/arch/riscv/include/kernel/user_access_arch.h000066400000000000000000000014031464416617300247100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation * Copyright (c) 2023, Amazon.com Inc. or its affiliates. All rights Reserved. */ #ifndef __KERNEL_USER_ACCESS_ARCH_H #define __KERNEL_USER_ACCESS_ARCH_H #include #ifdef CFG_PAN /* Enter a section where user mode access is temporarily enabled. */ static inline void enter_user_access(void) { set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); } /* Exit from the section where user mode access was temporarily enabled. */ static inline void exit_user_access(void) { clear_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); } #else static inline void enter_user_access(void) {} static inline void exit_user_access(void) {} #endif /* CFG_PAN */ #endif /* __KERNEL_USER_ACCESS_ARCH_H */ optee_os-4.3.0/core/arch/riscv/include/mm/000077500000000000000000000000001464416617300203765ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/include/mm/core_mmu_arch.h000066400000000000000000000072711464416617300233610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __MM_CORE_MMU_ARCH_H #define __MM_CORE_MMU_ARCH_H #ifndef __ASSEMBLER__ #include #include #include #include #include #include #include #include #endif #include #ifdef TRUSTED_DRAM_BASE #error TRUSTED_DRAM_BASE is already defined #endif #define TRUSTED_DRAM_BASE TDDRAM_BASE #define TRUSTED_DRAM_SIZE TDDRAM_SIZE /* MMU defines */ #ifdef CFG_RISCV_MMU_MODE #define RISCV_MMU_MODE CFG_RISCV_MMU_MODE #else #ifdef RV64 #define RISCV_MMU_MODE U(39) #define RISCV_MMU_ASID_WIDTH 16 #else #define RISCV_MMU_MODE U(32) #define RISCV_MMU_ASID_WIDTH 9 #endif #endif #if RISCV_MMU_MODE == 48 /*Sv48*/ #define RISCV_SATP_MODE SATP_MODE_SV48 #define RISCV_SATP_MODE_SHIFT U(60) #define RISCV_SATP_ASID_SHIFT U(44) #define RISCV_SATP_ASID_SIZE U(16) #define RISCV_SATP_ASID_MASK 0x0FFFF #define RISCV_MMU_PA_WIDTH U(56) #define RISCV_MMU_VA_WIDTH U(48) #elif RISCV_MMU_MODE == 39 /*Sv39*/ #define RISCV_SATP_MODE SATP_MODE_SV39 #define RISCV_SATP_ASID_SHIFT U(44) #define RISCV_SATP_ASID_SIZE U(16) #define RISCV_SATP_ASID_MASK 0x0FFFF #define RISCV_MMU_PA_WIDTH U(56) #define RISCV_MMU_VA_WIDTH U(39) #define RISCV_SATP_MODE_SHIFT 60 #elif RISCV_MMU_MODE == 32 /*Sv32*/ #define RISCV_SATP_MODE SATP_MODE_SV32 #define RISCV_SATP_MODE_SHIFT U(31) #define RISCV_SATP_ASID_SHIFT U(22) #define RISCV_SATP_ASID_SIZE U(9) #define RISCV_SATP_ASID_MASK 0x01FF #define RISCV_MMU_PA_WIDTH U(32) #define RISCV_MMU_VA_WIDTH U(32) #else #error unknown or unsupported mmu mode #endif #define RISCV_PTES_PER_PT BIT(RISCV_PGLEVEL_BITS) #define RISCV_PGLEVELS ((RISCV_MMU_VA_WIDTH - RISCV_PGSHIFT) / \ RISCV_PGLEVEL_BITS) #define RISCV_MMU_VPN_MASK (BIT(RISCV_PGLEVEL_BITS) - 1) #define RISCV_MMU_MAX_PGTS 16 #define SMALL_PAGE_SHIFT U(12) /* * Level 0, shift = 12, 4 KiB pages * Level 1, shift = 21, 2 MiB pages (4 MiB pages in Sv32) * Level 2, shift = 30, 1 GiB pages * Level 3, shift = 39, 512 GiB pages * Level 4, shift = 48, 256 TiB pages */ #define CORE_MMU_SHIFT_OF_LEVEL(level) (RISCV_PGLEVEL_BITS * \ (level) + \ RISCV_PGSHIFT) #define CORE_MMU_USER_CODE_SHIFT SMALL_PAGE_SHIFT #define CORE_MMU_USER_PARAM_SHIFT SMALL_PAGE_SHIFT /* * In all MMU modes, the CORE_MMU_PGDIR_LEVEL is always 0: * Sv32: 4 KiB, 4 MiB * Sv39: 4 KiB, 2 MiB, 1 GiB * Sv48: 4 KiB, 2 MiB, 1 GiB, 512 GiB * Sv57: 4 KiB, 2 MiB, 1 GiB, 512 GiB, 256 TiB */ #define CORE_MMU_PGDIR_LEVEL U(0) #define CORE_MMU_PGDIR_SHIFT \ CORE_MMU_SHIFT_OF_LEVEL(CORE_MMU_PGDIR_LEVEL + 1) #define CORE_MMU_BASE_TABLE_LEVEL (RISCV_PGLEVELS - 1) #define CORE_MMU_BASE_TABLE_SHIFT \ CORE_MMU_SHIFT_OF_LEVEL(CORE_MMU_BASE_TABLE_LEVEL) #ifndef __ASSEMBLER__ struct core_mmu_config { unsigned long satp[CFG_TEE_CORE_NB_CORE]; uint32_t map_offset; }; struct core_mmu_user_map { unsigned long user_map; uint32_t asid; }; /* Cache maintenance operation type */ enum cache_op { DCACHE_CLEAN, DCACHE_AREA_CLEAN, DCACHE_INVALIDATE, DCACHE_AREA_INVALIDATE, ICACHE_INVALIDATE, ICACHE_AREA_INVALIDATE, DCACHE_CLEAN_INV, DCACHE_AREA_CLEAN_INV, }; static inline void core_mmu_table_write_barrier(void) { /* Invoke memory barrier */ mb(); } TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len); static inline bool core_mmu_check_max_pa(paddr_t pa) { return pa <= (BIT64(RISCV_MMU_PA_WIDTH) - 1); } static inline unsigned int core_mmu_get_va_width(void) { return RISCV_MMU_VA_WIDTH; } static inline bool core_mmu_level_in_range(unsigned int level) { return level <= CORE_MMU_BASE_TABLE_LEVEL; } #endif /*__ASSEMBLER__*/ #endif /* __MM_CORE_MMU_ARCH_H */ optee_os-4.3.0/core/arch/riscv/include/mm/generic_ram_layout.h000066400000000000000000000155431464416617300244270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited * Copyright 2022 NXP */ #ifndef __MM_GENERIC_RAM_LAYOUT_H #define __MM_GENERIC_RAM_LAYOUT_H #include /* * Generic RAM layout configuration directives * * Mandatory directives: * CFG_TDDRAM_START * CFG_TDDRAM_SIZE * CFG_SHMEM_START * CFG_SHMEM_SIZE * * Optional directives: * CFG_TEE_LOAD_ADDR If defined sets TEE_LOAD_ADDR. If not, TEE_LOAD_ADDR * is set by the platform or defaults to TEE_RAM_START. * CFG_TEE_RAM_VA_SIZE Some platforms may have specific needs * * Optional directives when pager is enabled: * CFG_TDSRAM_START If no set, emulated at CFG_TDDRAM_START * CFG_TDSRAM_SIZE Default to CFG_CORE_TDSRAM_EMUL_SIZE * * Optional directive when CFG_SECURE_DATA_PATH is enabled: * CFG_TEE_SDP_MEM_SIZE If CFG_TEE_SDP_MEM_BASE is not defined, SDP test * memory byte size can be set by CFG_TEE_SDP_MEM_SIZE. * * This header file produces the following generic macros upon the mandatory * and optional configuration directives listed above: * * TEE_RAM_START TEE core RAM physical base address * TEE_RAM_VA_SIZE TEE core virtual memory address range size * TEE_RAM_PH_SIZE TEE core physical RAM byte size * TA_RAM_START TA contexts/pagestore RAM physical base address * TA_RAM_SIZE TA contexts/pagestore RAM byte size * TEE_SHMEM_START Non-secure static shared memory physical base address * TEE_SHMEM_SIZE Non-secure static shared memory byte size * * TDDRAM_BASE Main/external secure RAM base address * TDDRAM_SIZE Main/external secure RAM byte size * TDSRAM_BASE On-chip secure RAM base address, required by pager. * TDSRAM_SIZE On-chip secure RAM byte size, required by pager. * * TEE_LOAD_ADDR Only defined here if CFG_TEE_LOAD_ADDR is defined. * Otherwise we expect the platform_config.h to define it * unless which LEE_LOAD_ADDR defaults to TEE_RAM_START. * * TEE_RAM_VA_SIZE Set to CFG_TEE_RAM_VA_SIZE or defaults to * CORE_MMU_PGDIR_SIZE. * * TEE_SDP_TEST_MEM_BASE Define if a SDP memory pool is required and none set. * Always defined in the inner top (high addresses) * of CFG_TDDRAM_START/_SIZE. * TEE_SDP_TEST_MEM_SIZE Set to CFG_TEE_SDP_MEM_SIZE or a default size. * * ---------------------------------------------------------------------------- * TEE RAM layout without CFG_WITH_PAGER *_ * +----------------------------------+ <-- CFG_TDDRAM_START * | TEE core secure RAM (TEE_RAM) | * +----------------------------------+ * | Trusted Application RAM (TA_RAM) | * +----------------------------------+ * | SDP test memory (optional) | * +----------------------------------+ <-- CFG_TDDRAM_START + CFG_TDDRAM_SIZE * * +----------------------------------+ <-- CFG_SHMEM_START * | Non-secure static SHM | * +----------------------------------+ <-- CFG_SHMEM_START + CFG_SHMEM_SIZE * * ---------------------------------------------------------------------------- * TEE RAM layout with CFG_WITH_PAGER=y and undefined CFG_TDSRAM_START/_SIZE * * +----------------------------------+ <-- CFG_TDDRAM_START * | TEE core secure RAM (TEE_RAM) | | | CFG_CORE_TDSRAM_EMUL_SIZE * +----------------------------------+ --|-' * | reserved (for kasan) | | TEE_RAM_VA_SIZE * +----------------------------------+ --' * | TA RAM / Pagestore (TA_RAM) | * +----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE * +----------------------------------+ <-- * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE * +----------------------------------+ <-+ CFG_TDDRAM_START + CFG_TDDRAM_SIZE * * +----------------------------------+ <-- CFG_SHMEM_START * | Non-secure static SHM | | * +----------------------------------+ v CFG_SHMEM_SIZE * * ---------------------------------------------------------------------------- * TEE RAM layout with CFG_WITH_PAGER=y and define CFG_TDSRAM_START/_SIZE * * +----------------------------------+ <-- CFG_TDSRAM_START * | TEE core secure RAM (TEE_RAM) | | CFG_TDSRAM_SIZE * +----------------------------------+ --' * * +----------------------------------+ <- CFG_TDDRAM_START * | TA RAM / Pagestore (TA_RAM) | * |----------------------------------+ <---- align with CORE_MMU_PGDIR_SIZE * |----------------------------------+ <-- * | SDP test memory (optional) | | CFG_TEE_SDP_MEM_SIZE * +----------------------------------+ <-+ CFG_TDDRAM_START + CFG_TDDRAM_SIZE * * +----------------------------------+ <-- CFG_SHMEM_START * | Non-secure static SHM | | * +----------------------------------+ v CFG_SHMEM_SIZE */ #ifdef CFG_TEE_LOAD_ADDR #define TEE_LOAD_ADDR CFG_TEE_LOAD_ADDR #else /* Platform specific platform_config.h may set TEE_LOAD_ADDR */ #endif #ifdef CFG_TEE_RAM_VA_SIZE #define TEE_RAM_VA_SIZE CFG_TEE_RAM_VA_SIZE #else #define TEE_RAM_VA_SIZE CORE_MMU_PGDIR_SIZE #endif #ifdef CFG_SHMEM_SIZE #define TEE_SHMEM_SIZE CFG_SHMEM_SIZE #endif #ifdef CFG_SHMEM_START #define TEE_SHMEM_START CFG_SHMEM_START #ifndef CFG_SHMEM_SIZE #error CFG_SHMEM_START mandates CFG_SHMEM_SIZE #endif #endif #if defined(CFG_TDSRAM_START) #define TDSRAM_BASE CFG_TDSRAM_START #define TDSRAM_SIZE CFG_TDSRAM_SIZE #endif #ifdef CFG_TDDRAM_START #if !defined(CFG_WITH_PAGER) || defined(CFG_TDSRAM_START) #define TDDRAM_BASE CFG_TDDRAM_START #define TDDRAM_SIZE CFG_TDDRAM_SIZE #else #define TDSRAM_BASE CFG_TDDRAM_START #define TDSRAM_SIZE CFG_CORE_TDSRAM_EMUL_SIZE #define TDDRAM_BASE ROUNDUP(TDSRAM_BASE + TDSRAM_SIZE, \ TEE_RAM_VA_SIZE) #define TDDRAM_SIZE (CFG_TDDRAM_START + (CFG_TDDRAM_SIZE - \ TDDRAM_BASE)) #endif #ifdef CFG_WITH_PAGER #define TEE_RAM_START TDSRAM_BASE #define TEE_RAM_PH_SIZE TDSRAM_SIZE #define TA_RAM_START ROUNDUP(TDDRAM_BASE, CORE_MMU_PGDIR_SIZE) #else #define TEE_RAM_START TDDRAM_BASE #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE #define TA_RAM_START ROUNDUP(TDDRAM_BASE + TEE_RAM_VA_SIZE, \ SMALL_PAGE_SIZE) #endif /*CFG_WITH_PAGER*/ #define TA_RAM_SIZE (ROUNDDOWN(TDDRAM_BASE + (TDDRAM_SIZE - \ TEE_SDP_TEST_MEM_SIZE), \ SMALL_PAGE_SIZE) - TA_RAM_START) #endif /*CFG_TDDRAM_START*/ /* * Secure data path test memory pool * - If SDP is disabled, no SDP test memory needed. * - If SDP is enabled, if CFG_TEE_SDP_MEM_BASE, SDP test pool is not needed. * - If SDP is enabled and CFG_TEE_SDP_MEM_BASE not defined, a SDP test pool * is defined at the end of the secure RAM. CFG_TEE_SDP_MEM_SIZE can set * its size otherwise it defaults to 4MB. */ #if !defined(CFG_SECURE_DATA_PATH) || defined(CFG_TEE_SDP_MEM_BASE) #define TEE_SDP_TEST_MEM_SIZE 0 #else #ifdef CFG_TEE_SDP_MEM_SIZE #define TEE_SDP_TEST_MEM_SIZE CFG_TEE_SDP_MEM_SIZE #else #define TEE_SDP_TEST_MEM_SIZE SIZE_4M #endif #define TEE_SDP_TEST_MEM_BASE (CFG_TDDRAM_START + (CFG_TDDRAM_SIZE - \ TEE_SDP_TEST_MEM_SIZE)) #endif #endif /*__MM_GENERIC_RAM_LAYOUT_H*/ optee_os-4.3.0/core/arch/riscv/include/riscv.h000066400000000000000000000201311464416617300212610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __RISCV_H #define __RISCV_H #include #include #include #include #include #include #define RISCV_XLEN_BITS (__riscv_xlen) #define RISCV_XLEN_BYTES (__riscv_xlen / 8) /* Bind registers to their ABI names */ #define REG_RA 1 #define REG_SP 2 #define REG_GP 3 #define REG_TP 4 #define REG_T0 5 #define REG_T2 7 #define REG_S0 8 #define REG_S1 9 #define REG_A0 10 #define REG_A1 11 #define REG_A2 12 #define REG_A3 13 #define REG_A5 15 #define REG_A7 17 #define REG_S2 18 #define REG_S11 27 #define REG_T3 28 #define REG_T6 31 #if defined(CFG_RISCV_M_MODE) #define CSR_MODE_OFFSET PRV_M #define XRET mret #elif defined(CFG_RISCV_S_MODE) #define CSR_MODE_OFFSET PRV_S #define XRET sret #endif #define CSR_MODE_BITS SHIFT_U64(CSR_MODE_OFFSET, 8) #define CSR_XSTATUS (CSR_MODE_BITS | 0x000) #define CSR_XIE (CSR_MODE_BITS | 0x004) #define CSR_XTVEC (CSR_MODE_BITS | 0x005) #define CSR_XSCRATCH (CSR_MODE_BITS | 0x040) #define CSR_XEPC (CSR_MODE_BITS | 0x041) #define CSR_XCAUSE (CSR_MODE_BITS | 0x042) #define CSR_XTVAL (CSR_MODE_BITS | 0x043) #define CSR_XIP (CSR_MODE_BITS | 0x044) #define IRQ_XSOFT (CSR_MODE_OFFSET + 0) #define IRQ_XTIMER (CSR_MODE_OFFSET + 4) #define IRQ_XEXT (CSR_MODE_OFFSET + 8) #define CSR_XIE_SIE BIT64(IRQ_XSOFT) #define CSR_XIE_TIE BIT64(IRQ_XTIMER) #define CSR_XIE_EIE BIT64(IRQ_XEXT) #define CSR_XSTATUS_IE BIT(CSR_MODE_OFFSET + 0) #define CSR_XSTATUS_PIE BIT(CSR_MODE_OFFSET + 4) #define CSR_XSTATUS_SPP BIT(8) #define CSR_XSTATUS_SUM BIT(18) #define CSR_XSTATUS_MXR BIT(19) #ifndef __ASSEMBLER__ #define read_csr(csr) \ ({ \ unsigned long __tmp; \ asm volatile ("csrr %0, %1" : "=r"(__tmp) : "i"(csr)); \ __tmp; \ }) #define write_csr(csr, val) \ ({ \ asm volatile ("csrw %0, %1" : : "i"(csr), "rK"(val)); \ }) #define swap_csr(csr, val) \ ({ \ unsigned long __tmp; \ asm volatile ("csrrw %0, %1, %2" \ : "=r"(__tmp) : "i"(csr), "rK"(val)); \ __tmp; \ }) #define set_csr(csr, bit) \ ({ \ unsigned long __tmp; \ asm volatile ("csrrs %0, %1, %2" \ : "=r"(__tmp) : "i"(csr), "rK"(bit)); \ __tmp; \ }) #define clear_csr(csr, bit) \ ({ \ unsigned long __tmp; \ asm volatile ("csrrc %0, %1, %2" \ : "=r"(__tmp) : "i"(csr), "rK"(bit)); \ __tmp; \ }) #define rdtime() read_csr(CSR_TIME) #define rdcycle() read_csr(CSR_CYCLE) #define rdinstret() read_csr(CSR_INSTRET) static inline __noprof void mb(void) { asm volatile ("fence" : : : "memory"); } static inline __noprof unsigned long read_gp(void) { unsigned long gp = 0; asm volatile("mv %0, gp" : "=&r"(gp)); return gp; } static inline __noprof unsigned long read_tp(void) { unsigned long tp = 0; asm volatile("mv %0, tp" : "=&r"(tp)); return tp; } static inline __noprof unsigned long read_fp(void) { unsigned long fp = 0; asm volatile ("mv %0, s0" : "=r" (fp)); return fp; } static inline __noprof unsigned long read_pc(void) { unsigned long pc = 0; asm volatile ("auipc %0, 0" : "=r" (pc)); return pc; } static inline __noprof void wfi(void) { asm volatile ("wfi"); } static inline __noprof void flush_tlb(void) { asm volatile("sfence.vma zero, zero"); } static inline __noprof void flush_tlb_entry(unsigned long va) { asm volatile ("sfence.vma %0" : : "r" (va) : "memory"); } /* supervisor address translation and protection */ static inline __noprof unsigned long read_satp(void) { unsigned long satp; asm volatile("csrr %0, satp" : "=r" (satp)); return satp; } static inline __noprof void write_satp(unsigned long satp) { asm volatile("csrw satp, %0" : : "r" (satp)); } /* machine trap-vector base-address register */ static inline __noprof unsigned long read_mtvec(void) { unsigned long mtvec; asm volatile("csrr %0, mtvec" : "=r" (mtvec)); return mtvec; } static inline __noprof void write_mtvec(unsigned long mtvec) { asm volatile("csrw mtvec, %0" : : "r" (mtvec)); } /* supervisor trap-vector base-address register */ static inline __noprof unsigned long read_stvec(void) { unsigned long stvec; asm volatile("csrr %0, stvec" : "=r" (stvec)); return stvec; } static inline __noprof void write_stvec(unsigned long stvec) { asm volatile("csrw stvec, %0" : : "r" (stvec)); } /* machine status register */ static inline __noprof unsigned long read_mstatus(void) { unsigned long mstatus; asm volatile("csrr %0, mstatus" : "=r" (mstatus)); return mstatus; } static inline __noprof void write_mstatus(unsigned long mstatus) { asm volatile("csrw mstatus, %0" : : "r" (mstatus)); } /* supervisor status register */ static inline __noprof unsigned long read_sstatus(void) { unsigned long sstatus; asm volatile("csrr %0, sstatus" : "=r" (sstatus)); return sstatus; } static inline __noprof void write_sstatus(unsigned long sstatus) { asm volatile("csrw sstatus, %0" : : "r" (sstatus)); } static inline __noprof void set_sstatus(unsigned long sstatus) { unsigned long x; asm volatile ("csrrs %0, sstatus, %1" : "=r"(x) : "rK"(sstatus)); } /* machine exception delegation */ static inline __noprof unsigned long read_medeleg(void) { unsigned long medeleg; asm volatile("csrr %0, medeleg" : "=r" (medeleg)); return medeleg; } static inline __noprof void write_medeleg(unsigned long medeleg) { asm volatile("csrw medeleg, %0" : : "r" (medeleg)); } /* machine interrupt delegation */ static inline __noprof unsigned long read_mideleg(void) { unsigned long mideleg; asm volatile("csrr %0, mideleg" : "=r" (mideleg)); return mideleg; } static inline __noprof void write_mideleg(unsigned long mideleg) { asm volatile("csrw mideleg, %0" : : "r" (mideleg)); } /* machine interrupt-enable register */ static inline __noprof unsigned long read_mie(void) { unsigned long mie; asm volatile("csrr %0, mie" : "=r" (mie)); return mie; } static inline __noprof void write_mie(unsigned long mie) { asm volatile("csrw mie, %0" : : "r" (mie)); } /* supervisor interrupt-enable register */ static inline __noprof unsigned long read_sie(void) { unsigned long sie; asm volatile("csrr %0, sie" : "=r" (sie)); return sie; } static inline __noprof void write_sie(unsigned long sie) { asm volatile("csrw sie, %0" : : "r" (sie)); } /* machine exception program counter */ static inline __noprof unsigned long read_mepc(void) { unsigned long mepc; asm volatile("csrr %0, mepc" : "=r" (mepc)); return mepc; } static inline __noprof void write_mepc(unsigned long mepc) { asm volatile("csrw mepc, %0" : : "r" (mepc)); } /* supervisor exception program counter */ static inline __noprof unsigned long read_sepc(void) { unsigned long sepc; asm volatile("csrr %0, sepc" : "=r" (sepc)); return sepc; } static inline __noprof void write_sepc(unsigned long sepc) { asm volatile("csrw sepc, %0" : : "r" (sepc)); } /* machine scratch register */ static inline __noprof unsigned long read_mscratch(void) { unsigned long mscratch; asm volatile("csrr %0, mscratch" : "=r" (mscratch)); return mscratch; } static inline __noprof void write_mscratch(unsigned long mscratch) { asm volatile("csrw mscratch, %0" : : "r" (mscratch)); } /* supervisor scratch register */ static inline __noprof unsigned long read_sscratch(void) { unsigned long sscratch; asm volatile("csrr %0, sscratch" : "=r" (sscratch)); return sscratch; } static inline __noprof void write_sscratch(unsigned long sscratch) { asm volatile("csrw sscratch, %0" : : "r" (sscratch)); } /* trap-return instructions */ static inline __noprof void mret(void) { asm volatile("mret"); } static inline __noprof void sret(void) { asm volatile("sret"); } static inline __noprof void uret(void) { asm volatile("uret"); } __noprof uint64_t read_time(void); static inline __noprof uint64_t barrier_read_counter_timer(void) { mb(); /* Get timer value after pending operations have completed */ return read_time(); } static inline __noprof uint32_t read_cntfrq(void) { return CFG_RISCV_MTIME_RATE; } __noprof bool riscv_detect_csr_seed(void); #endif /*__ASSEMBLER__*/ #endif /*__RISCV_H*/ optee_os-4.3.0/core/arch/riscv/include/riscv_macros.S000066400000000000000000000032761464416617300226130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP * Copyright (c) 2015, Linaro Limited */ .altmacro /* * This helper macro concatenates instr_prefix, instr_suffix, to * create a l(w,d)/s(w,d) instruction. */ .macro __do_reg instr_prefix, base_reg, base_offs, reg \instr_prefix x\reg, \base_offs(\base_reg) .endm /* * This helper macro uses recursion to create a loop with a single * load/store. */ .macro _do_regs instr_prefix, reg_bytes, base_reg, base_offs, \ from_regnum, to_regnum .if (\to_regnum - \from_regnum + 1) > 1 _do_regs \instr_prefix, \reg_bytes, \base_reg, \ %(\base_offs + 1 * \reg_bytes), \ %(\from_regnum + 1), \to_regnum .endif __do_reg \instr_prefix, \base_reg, \base_offs, \from_regnum .endm /* * Stores registers x[from_regnum]..x[to_regnum] at * [base_reg, #base_offs] */ .macro store_xregs base_reg, base_offs, from_regnum, to_regnum _do_regs STR, RISCV_XLEN_BYTES, \base_reg, \base_offs, \ \from_regnum, \to_regnum .endm /* * Loads registers x[from_regnum]..x[to_regnum] at * [base_reg, #base_offs] */ .macro load_xregs base_reg, base_offs, from_regnum, to_regnum _do_regs LDR, RISCV_XLEN_BYTES, \base_reg, \base_offs, \ \from_regnum, \to_regnum .endm /* * Multiplication macro for RISC-V harts without M extension. */ .macro mult, reg_op0, reg_op1, reg_res li \reg_res, 0 mv a0, \reg_op0 mv a1, \reg_op1 mv a2, a0 li a0, 0 1: andi a3, a1, 1 beqz a3, 2f add a0, a0, a2 2: srli a1, a1, 1 slli a2, a2, 1 bnez a1, 1b add \reg_res, \reg_res, a0 .endm .macro panic_at_abi_return #if defined(CFG_TEE_CORE_DEBUG) jal __panic_at_abi_return #else j . #endif .endm optee_os-4.3.0/core/arch/riscv/include/sbi.h000066400000000000000000000032501464416617300207130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __SBI_H #define __SBI_H #if defined(CFG_RISCV_SBI) /* SBI return error codes */ #define SBI_SUCCESS 0 #define SBI_ERR_FAILURE -1 #define SBI_ERR_NOT_SUPPORTED -2 #define SBI_ERR_INVALID_PARAM -3 #define SBI_ERR_DENIED -4 #define SBI_ERR_INVALID_ADDRESS -5 #define SBI_ERR_ALREADY_AVAILABLE -6 #define SBI_ERR_ALREADY_STARTED -7 #define SBI_ERR_ALREADY_STOPPED -8 /* SBI Extension IDs */ #define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x01 #define SBI_EXT_BASE 0x10 #define SBI_EXT_HSM 0x48534D #define SBI_EXT_DBCN 0x4442434E #define SBI_EXT_TEE 0x544545 #ifndef __ASSEMBLER__ /* SBI function IDs for Base extension */ enum sbi_ext_base_fid { SBI_EXT_BASE_GET_SPEC_VERSION = 0, SBI_EXT_BASE_GET_IMP_ID, SBI_EXT_BASE_GET_IMP_VERSION, SBI_EXT_BASE_PROBE_EXT, SBI_EXT_BASE_GET_MVENDORID, SBI_EXT_BASE_GET_MARCHID, SBI_EXT_BASE_GET_MIMPID, }; /* SBI function IDs for HSM extension */ enum sbi_ext_hsm_fid { SBI_EXT_HSM_HART_START = 0, SBI_EXT_HSM_HART_STOP, SBI_EXT_HSM_HART_GET_STATUS, SBI_EXT_HSM_HART_SUSPEND, }; /* SBI function IDs for Debug Console extension */ enum sbi_ext_dbcn_fid { SBI_EXT_DBCN_CONSOLE_WRITE = 0, SBI_EXT_DBCN_CONSOLE_READ = 1, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE = 2, }; #include #include #include #include #include #include int sbi_probe_extension(int extid); void sbi_console_putchar(int ch); int sbi_dbcn_write_byte(unsigned char ch); int sbi_hsm_hart_start(uint32_t hartid, paddr_t start_addr, unsigned long arg); #endif /*__ASSEMBLER__*/ #endif /*defined(CFG_RISCV_SBI)*/ #endif /*__SBI_H*/ optee_os-4.3.0/core/arch/riscv/include/sub.mk000066400000000000000000000000261464416617300211050ustar00rootroot00000000000000global-incdirs-y += . optee_os-4.3.0/core/arch/riscv/include/tee/000077500000000000000000000000001464416617300205425ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/include/tee/entry_fast.h000066400000000000000000000022101464416617300230640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP * Copyright (c) 2015, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_ENTRY_FAST_H #define __TEE_ENTRY_FAST_H #include /* These functions are overridable by the specific target */ void tee_entry_get_api_call_count(struct thread_abi_args *args); void tee_entry_get_api_uuid(struct thread_abi_args *args); void tee_entry_get_api_revision(struct thread_abi_args *args); void tee_entry_get_os_uuid(struct thread_abi_args *args); void tee_entry_get_os_revision(struct thread_abi_args *args); /* * Returns the number of calls recognized by tee_entry(). Used by the * specific target to calculate the total number of supported calls when * overriding tee_entry_get_api_call_count(). */ size_t tee_entry_generic_get_api_call_count(void); /* * Fast call entry, __weak, overridable. If overridden should call * __tee_entry_fast() at the end in order to handle the standard functions. */ void tee_entry_fast(struct thread_abi_args *args); void __tee_entry_fast(struct thread_abi_args *args); #endif /* __TEE_ENTRY_FAST_H */ optee_os-4.3.0/core/arch/riscv/include/tee/optee_abi.h000066400000000000000000000563511464416617300226540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP * Copyright (c) 2015-2021, Linaro Limited */ #ifndef __TEE_OPTEE_ABI_H #define __TEE_OPTEE_ABI_H #include /* * This file should be kept in sync between secure domain and non-secure * domain kernel driver. * This file depends on optee_msg.h being included to expand the ABI id * macros below. */ #define OPTEE_ABI_32 U(0) #define OPTEE_ABI_64 U(0x40000000) #define OPTEE_ABI_FAST_CALL U(0x80000000) #define OPTEE_ABI_STD_CALL U(0) #define OPTEE_ABI_OWNER_MASK U(0x3F) #define OPTEE_ABI_OWNER_SHIFT U(24) #define OPTEE_ABI_FUNC_MASK U(0xFFFF) #define OPTEE_ABI_IS_FAST_CALL(abi_val) ((abi_val) & OPTEE_ABI_FAST_CALL) #define OPTEE_ABI_IS_64(abi_val) ((abi_val) & OPTEE_ABI_64) #define OPTEE_ABI_FUNC_NUM(abi_val) ((abi_val) & OPTEE_ABI_FUNC_MASK) #define OPTEE_ABI_OWNER_NUM(abi_val) \ (((abi_val) >> OPTEE_ABI_OWNER_SHIFT) & OPTEE_ABI_OWNER_MASK) #define OPTEE_ABI_CALL_VAL(type, calling_convention, owner, func_num) \ ((type) | (calling_convention) | \ (((owner) & OPTEE_ABI_OWNER_MASK) << \ OPTEE_ABI_OWNER_SHIFT) |\ ((func_num) & OPTEE_ABI_FUNC_MASK)) #define OPTEE_ABI_STD_CALL_VAL(func_num) \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_STD_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS, (func_num)) #define OPTEE_ABI_FAST_CALL_VAL(func_num) \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS, (func_num)) #define OPTEE_ABI_OWNER_ARCH U(0) #define OPTEE_ABI_OWNER_CPU U(1) #define OPTEE_ABI_OWNER_SIP U(2) #define OPTEE_ABI_OWNER_OEM U(3) #define OPTEE_ABI_OWNER_STANDARD U(4) #define OPTEE_ABI_OWNER_TRUSTED_APP U(48) #define OPTEE_ABI_OWNER_TRUSTED_OS U(50) #define OPTEE_ABI_OWNER_TRUSTED_OS_OPTEED U(62) #define OPTEE_ABI_OWNER_TRUSTED_OS_API U(63) /* * Function specified by ABI Calling convention. */ #define OPTEE_ABI_FUNCID_CALLS_COUNT U(0xFF00) #define OPTEE_ABI_CALLS_COUNT \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS_API, \ OPTEE_ABI_FUNCID_CALLS_COUNT) /* * Normal cached memory (write-back), shareable for SMP systems and not * shareable for UP systems. */ #define OPTEE_ABI_SHM_CACHED U(1) /* * a0..a7 is used as register names in the descriptions below. */ /* * Function specified by ABI Calling convention * * Return the following UID if using API specified in this file * without further extensions: * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. * see also OPTEE_MSG_UID_* in optee_msg.h */ #define OPTEE_ABI_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID #define OPTEE_ABI_CALLS_UID \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS_API, \ OPTEE_ABI_FUNCID_CALLS_UID) /* * Function specified by ABI Calling convention * * Returns 2.0 if using API specified in this file without further extensions. * see also OPTEE_MSG_REVISION_* in optee_msg.h */ #define OPTEE_ABI_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION #define OPTEE_ABI_CALLS_REVISION \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS_API, \ OPTEE_ABI_FUNCID_CALLS_REVISION) /* * Get UUID of Trusted OS. * * Used by non-secure world to figure out which Trusted OS is installed. * Note that returned UUID is the UUID of the Trusted OS, not of the API. * * Returns UUID in a0-4 in the same way as OPTEE_ABI_CALLS_UID * described above. */ #define OPTEE_ABI_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID #define OPTEE_ABI_CALL_GET_OS_UUID \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_OS_UUID) /* * Get revision of Trusted OS. * * Used by non-secure world to figure out which version of the Trusted OS * is installed. Note that the returned revision is the revision of the * Trusted OS, not of the API. * * Returns revision in a0-1 in the same way as OPTEE_ABI_CALLS_REVISION * described above. May optionally return a 32-bit build identifier in a2, * with zero meaning unspecified. */ #define OPTEE_ABI_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION #define OPTEE_ABI_CALL_GET_OS_REVISION \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_OS_REVISION) /* * Call with struct optee_msg_arg as argument * * When called with OPTEE_ABI_CALL_WITH_RPC_ARG or * OPTEE_ABI_CALL_WITH_REGD_ARG in a0 there is one RPC struct optee_msg_arg * following after the first struct optee_msg_arg. The RPC struct * optee_msg_arg has reserved space for the number of RPC parameters as * returned by OPTEE_ABI_EXCHANGE_CAPABILITIES. * * When calling these functions normal world has a few responsibilities: * 1. It must be able to handle eventual RPCs * 2. Non-secure interrupts should not be masked * 3. If asynchronous notifications has been negotiated successfully, then * the interrupt for asynchronous notifications should be unmasked * during this call. * * Call register usage, OPTEE_ABI_CALL_WITH_ARG and * OPTEE_ABI_CALL_WITH_RPC_ARG: * a0 ABI Function ID, OPTEE_ABI_CALL_WITH_ARG or OPTEE_ABI_CALL_WITH_RPC_ARG * a1 Upper 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a2 Lower 32 bits of a 64-bit physical pointer to a struct optee_msg_arg * a3 Cache settings, not used if physical pointer is in a predefined shared * memory area else per OPTEE_ABI_SHM_* * a4-6 Not used * a7 Hypervisor Client ID register * * Call register usage, OPTEE_ABI_CALL_WITH_REGD_ARG: * a0 ABI Function ID, OPTEE_ABI_CALL_WITH_REGD_ARG * a1 Upper 32 bits of a 64-bit shared memory cookie * a2 Lower 32 bits of a 64-bit shared memory cookie * a3 Offset of the struct optee_msg_arg in the shared memory with the * supplied cookie * a4-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 Return value, OPTEE_ABI_RETURN_* * a1-3 Not used * a4-7 Preserved * * OPTEE_ABI_RETURN_ETHREAD_LIMIT return register usage: * a0 Return value, OPTEE_ABI_RETURN_ETHREAD_LIMIT * a1-3 Preserved * a4-7 Preserved * * RPC return register usage: * a0 Return value, OPTEE_ABI_RETURN_IS_RPC(val) * a1-2 RPC parameters * a3-7 Resume information, must be preserved * * Possible return values: * OPTEE_ABI_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this * function. * OPTEE_ABI_RETURN_OK Call completed, result updated in * the previously supplied struct * optee_msg_arg. * OPTEE_ABI_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded, * try again later. * OPTEE_ABI_RETURN_EBADADDR Bad physical pointer to struct * optee_msg_arg. * OPTEE_ABI_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg * OPTEE_ABI_RETURN_IS_RPC() Call suspended by RPC call to normal * world. */ #define OPTEE_ABI_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG #define OPTEE_ABI_CALL_WITH_ARG \ OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_CALL_WITH_ARG) #define OPTEE_ABI_CALL_WITH_RPC_ARG \ OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_CALL_WITH_RPC_ARG) #define OPTEE_ABI_CALL_WITH_REGD_ARG \ OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_CALL_WITH_REGD_ARG) /* * Get Shared Memory Config * * Returns the Secure/Non-secure shared memory config. * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_GET_SHM_CONFIG * a1-6 Not used * a7 Hypervisor Client ID register * * Have config return register usage: * a0 OPTEE_ABI_RETURN_OK * a1 Physical address of start of SHM * a2 Size of SHM * a3 Cache settings of memory, as defined by the * OPTEE_ABI_SHM_* values above * a4-7 Preserved * * Not available register usage: * a0 OPTEE_ABI_RETURN_ENOTAVAIL * a1-3 Not used * a4-7 Preserved */ #define OPTEE_ABI_FUNCID_GET_SHM_CONFIG 7 #define OPTEE_ABI_GET_SHM_CONFIG \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_SHM_CONFIG) /* * Configures L2CC mutex * * Disables, enables usage of L2CC mutex. Returns or sets physical address * of L2CC mutex. * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_L2CC_MUTEX * a1 OPTEE_ABI_L2CC_MUTEX_GET_ADDR Get physical address of mutex * OPTEE_ABI_L2CC_MUTEX_SET_ADDR Set physical address of mutex * OPTEE_ABI_L2CC_MUTEX_ENABLE Enable usage of mutex * OPTEE_ABI_L2CC_MUTEX_DISABLE Disable usage of mutex * a2 if a1 == OPTEE_ABI_L2CC_MUTEX_SET_ADDR, upper 32bit of a 64bit * physical address of mutex * a3 if a1 == OPTEE_ABI_L2CC_MUTEX_SET_ADDR, lower 32bit of a 64bit * physical address of mutex * a3-6 Not used * a7 Hypervisor Client ID register * * Have config return register usage: * a0 OPTEE_ABI_RETURN_OK * a1 Preserved * a2 if a1 == OPTEE_ABI_L2CC_MUTEX_GET_ADDR, upper 32bit of a 64bit * physical address of mutex * a3 if a1 == OPTEE_ABI_L2CC_MUTEX_GET_ADDR, lower 32bit of a 64bit * physical address of mutex * a3-7 Preserved * * Error return register usage: * a0 OPTEE_ABI_RETURN_ENOTAVAIL Physical address not available * OPTEE_ABI_RETURN_EBADADDR Bad supplied physical address * OPTEE_ABI_RETURN_EBADCMD Unsupported value in a1 * a1-7 Preserved */ #define OPTEE_ABI_L2CC_MUTEX_GET_ADDR U(0) #define OPTEE_ABI_L2CC_MUTEX_SET_ADDR U(1) #define OPTEE_ABI_L2CC_MUTEX_ENABLE U(2) #define OPTEE_ABI_L2CC_MUTEX_DISABLE U(3) #define OPTEE_ABI_FUNCID_L2CC_MUTEX U(8) #define OPTEE_ABI_L2CC_MUTEX \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_L2CC_MUTEX) /* * Exchanges capabilities between normal world and secure world * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_EXCHANGE_CAPABILITIES * a1 bitfield of normal world capabilities OPTEE_ABI_NSEC_CAP_* * a2-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1 bitfield of secure world capabilities OPTEE_ABI_SEC_CAP_* * a2 The maximum secure world notification number * a3 Bit[7:0]: Number of parameters needed for RPC to be supplied * as the second MSG arg struct for * OPTEE_ABI_CALL_WITH_ARG * Bit[31:8]: Reserved (MBZ) * a3-7 Preserved * * Error return register usage: * a0 OPTEE_ABI_RETURN_ENOTAVAIL, can't use the capabilities from normal world * a1 bitfield of secure world capabilities OPTEE_ABI_SEC_CAP_* * a2-7 Preserved */ /* Normal world works as a uniprocessor system */ #define OPTEE_ABI_NSEC_CAP_UNIPROCESSOR BIT(0) /* Secure world has reserved shared memory for normal world to use */ #define OPTEE_ABI_SEC_CAP_HAVE_RESERVED_SHM BIT(0) /* Secure world can communicate via previously unregistered shared memory */ #define OPTEE_ABI_SEC_CAP_UNREGISTERED_SHM BIT(1) /* * Secure world supports commands "register/unregister shared memory", * secure world accepts command buffers located in any parts of non-secure RAM */ #define OPTEE_ABI_SEC_CAP_DYNAMIC_SHM BIT(2) /* Secure world is built with virtualization support */ #define OPTEE_ABI_SEC_CAP_VIRTUALIZATION BIT(3) /* Secure world supports Shared Memory with a NULL reference */ #define OPTEE_ABI_SEC_CAP_MEMREF_NULL BIT(4) /* Secure world supports asynchronous notification of normal world */ #define OPTEE_ABI_SEC_CAP_ASYNC_NOTIF BIT(5) /* Secure world supports pre-allocating RPC arg struct */ #define OPTEE_ABI_SEC_CAP_RPC_ARG BIT(6) #define OPTEE_ABI_FUNCID_EXCHANGE_CAPABILITIES U(9) #define OPTEE_ABI_EXCHANGE_CAPABILITIES \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_EXCHANGE_CAPABILITIES) /* * Disable and empties cache of shared memory objects * * Secure world can cache frequently used shared memory objects, for * example objects used as RPC arguments. When secure world is idle this * function returns one shared memory reference to free. To disable the * cache and free all cached objects this function has to be called until * it returns OPTEE_ABI_RETURN_ENOTAVAIL. * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_DISABLE_SHM_CACHE * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1 Upper 32 bits of a 64-bit Shared memory cookie * a2 Lower 32 bits of a 64-bit Shared memory cookie * a3-7 Preserved * * Cache empty return register usage: * a0 OPTEE_ABI_RETURN_ENOTAVAIL * a1-7 Preserved * * Not idle return register usage: * a0 OPTEE_ABI_RETURN_EBUSY * a1-7 Preserved */ #define OPTEE_ABI_FUNCID_DISABLE_SHM_CACHE U(10) #define OPTEE_ABI_DISABLE_SHM_CACHE \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_DISABLE_SHM_CACHE) /* * Enable cache of shared memory objects * * Secure world can cache frequently used shared memory objects, for * example objects used as RPC arguments. When secure world is idle this * function returns OPTEE_ABI_RETURN_OK and the cache is enabled. If * secure world isn't idle OPTEE_ABI_RETURN_EBUSY is returned. * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_ENABLE_SHM_CACHE * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1-7 Preserved * * Not idle return register usage: * a0 OPTEE_ABI_RETURN_EBUSY * a1-7 Preserved */ #define OPTEE_ABI_FUNCID_ENABLE_SHM_CACHE U(11) #define OPTEE_ABI_ENABLE_SHM_CACHE \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_ENABLE_SHM_CACHE) /* * Release of secondary cores * * OP-TEE in secure world is in charge of the release process of secondary * cores. The Rich OS issue the this request to ask OP-TEE to boot up the * secondary cores, go through the OP-TEE per-core initialization, and then * switch to the Non-seCure world with the Rich OS provided entry address. * The secondary cores enter Non-Secure world in SVC mode, with Thumb, FIQ, * IRQ and Abort bits disabled. * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_BOOT_SECONDARY * a1 Index of secondary core to boot * a2 Upper 32 bits of a 64-bit Non-Secure world entry physical address * a3 Lower 32 bits of a 64-bit Non-Secure world entry physical address * a4-7 Not used * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1-7 Preserved * * Error return: * a0 OPTEE_ABI_RETURN_EBADCMD Core index out of range * a1-7 Preserved * * Not idle return register usage: * a0 OPTEE_ABI_RETURN_EBUSY * a1-7 Preserved */ #define OPTEE_ABI_FUNCID_BOOT_SECONDARY U(12) #define OPTEE_ABI_BOOT_SECONDARY \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_BOOT_SECONDARY) /* * Inform OP-TEE about a new virtual machine * * Hypervisor issues this call during virtual machine (guest) creation. * OP-TEE records client id of new virtual machine and prepares * to receive requests from it. This call is available only if OP-TEE * was built with virtualization support. * * Call requests usage: * a0 ABI Function ID, OPTEE_ABI_VM_CREATED * a1 Hypervisor Client ID of newly created virtual machine * a2-6 Not used * a7 Hypervisor Client ID register. Must be 0, because only hypervisor * can issue this call * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1-7 Preserved * * Error return: * a0 OPTEE_ABI_RETURN_ENOTAVAIL OP-TEE have no resources for * another VM * a1-7 Preserved * */ #define OPTEE_ABI_FUNCID_VM_CREATED U(13) #define OPTEE_ABI_VM_CREATED \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_VM_CREATED) /* * Inform OP-TEE about shutdown of a virtual machine * * Hypervisor issues this call during virtual machine (guest) destruction. * OP-TEE will clean up all resources associated with this VM. This call is * available only if OP-TEE was built with virtualization support. * * Call requests usage: * a0 ABI Function ID, OPTEE_ABI_VM_DESTROYED * a1 Hypervisor Client ID of virtual machine being shut down * a2-6 Not used * a7 Hypervisor Client ID register. Must be 0, because only hypervisor * can issue this call * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1-7 Preserved * */ #define OPTEE_ABI_FUNCID_VM_DESTROYED U(14) #define OPTEE_ABI_VM_DESTROYED \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_VM_DESTROYED) /* * Query OP-TEE about number of supported threads * * Normal World OS or Hypervisor issues this call to find out how many * threads OP-TEE supports. That is how many standard calls can be issued * in parallel before OP-TEE will return OPTEE_ABI_RETURN_ETHREAD_LIMIT. * * Call requests usage: * a0 ABI Function ID, OPTEE_ABI_GET_THREAD_COUNT * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1 Number of threads * a2-7 Preserved * * Error return: * a0 OPTEE_ABI_RETURN_UNKNOWN_FUNCTION Requested call is not implemented * a1-7 Preserved */ #define OPTEE_ABI_FUNCID_GET_THREAD_COUNT U(15) #define OPTEE_ABI_GET_THREAD_COUNT \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_THREAD_COUNT) /* * Inform OP-TEE that normal world is able to receive asynchronous * notifications. * * Call requests usage: * a0 ABI Function ID, OPTEE_ABI_ENABLE_ASYNC_NOTIF * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1-7 Preserved * * Not supported return register usage: * a0 OPTEE_ABI_RETURN_ENOTAVAIL * a1-7 Preserved */ #define OPTEE_ABI_FUNCID_ENABLE_ASYNC_NOTIF 16 #define OPTEE_ABI_ENABLE_ASYNC_NOTIF \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_ENABLE_ASYNC_NOTIF) /* * Retrieve a value of notifications pending since the last call of this * function. * * OP-TEE keeps a record of all posted values. When an interrupt is * received which indicates that there are posted values this function * should be called until all pended values have been retrieved. When a * value is retrieved, it's cleared from the record in secure world. * * It is expected that this function is called from an interrupt handler * in normal world. * * Call requests usage: * a0 ABI Function ID, OPTEE_ABI_GET_ASYNC_NOTIF_VALUE * a1-6 Not used * a7 Hypervisor Client ID register * * Normal return register usage: * a0 OPTEE_ABI_RETURN_OK * a1 value * a2 Bit[0]: OPTEE_ABI_ASYNC_NOTIF_VALUE_VALID if the value in a1 is * valid, else 0 if no values were pending * a2 Bit[1]: OPTEE_ABI_ASYNC_NOTIF_VALUE_PENDING if another value is * pending, else 0. * Bit[31:2]: MBZ * a3-7 Preserved * * Not supported return register usage: * a0 OPTEE_ABI_RETURN_ENOTAVAIL * a1-7 Preserved */ #define OPTEE_ABI_ASYNC_NOTIF_VALID BIT(0) #define OPTEE_ABI_ASYNC_NOTIF_PENDING BIT(1) /* * Notification that OP-TEE expects a yielding call to do some bottom half * work in a driver. */ #define OPTEE_ABI_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF 0 #define OPTEE_ABI_FUNCID_GET_ASYNC_NOTIF_VALUE 17 #define OPTEE_ABI_GET_ASYNC_NOTIF_VALUE \ OPTEE_ABI_FAST_CALL_VAL(OPTEE_ABI_FUNCID_GET_ASYNC_NOTIF_VALUE) /* See OPTEE_ABI_CALL_WITH_RPC_ARG above */ #define OPTEE_ABI_FUNCID_CALL_WITH_RPC_ARG U(18) /* See OPTEE_ABI_CALL_WITH_REGD_ARG above */ #define OPTEE_ABI_FUNCID_CALL_WITH_REGD_ARG U(19) /* * Resume from RPC (for example after processing a foreign interrupt) * * Call register usage: * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC * a1-3 Value of a1-3 when OPTEE_ABI_CALL_WITH_ARG returned * OPTEE_ABI_RETURN_RPC in a0 * * Return register usage is the same as for OPTEE_ABI_*CALL_WITH_ARG above. * * Possible return values * OPTEE_ABI_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this * function. * OPTEE_ABI_RETURN_OK Original call completed, result * updated in the previously supplied. * struct optee_msg_arg * OPTEE_ABI_RETURN_RPC Call suspended by RPC call to normal * world. * OPTEE_ABI_RETURN_ERESUME Resume failed, the opaque resume * information was corrupt. */ #define OPTEE_ABI_FUNCID_RETURN_FROM_RPC U(3) #define OPTEE_ABI_CALL_RETURN_FROM_RPC \ OPTEE_ABI_STD_CALL_VAL(OPTEE_ABI_FUNCID_RETURN_FROM_RPC) #define OPTEE_ABI_RETURN_RPC_PREFIX_MASK U(0xFFFF0000) #define OPTEE_ABI_RETURN_RPC_PREFIX U(0xFFFF0000) #define OPTEE_ABI_RETURN_RPC_FUNC_MASK U(0x0000FFFF) #define OPTEE_ABI_RETURN_GET_RPC_FUNC(ret) \ ((ret) & OPTEE_ABI_RETURN_RPC_FUNC_MASK) #define OPTEE_ABI_RPC_VAL(func) ((func) | OPTEE_ABI_RETURN_RPC_PREFIX) /* * Allocate memory for RPC parameter passing. The memory is used to hold a * struct optee_msg_arg. * * "Call" register usage: * a0 This value, OPTEE_ABI_RETURN_RPC_ALLOC * a1 Size in bytes of required argument memory * a2 Not used * a3 Resume information, must be preserved * a4-5 Not used * a6-7 Resume information, must be preserved * * "Return" register usage: * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. * a1 Upper 32 bits of 64-bit physical pointer to allocated * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't * be allocated. * a2 Lower 32 bits of 64-bit physical pointer to allocated * memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't * be allocated * a3 Preserved * a4 Upper 32 bits of 64-bit Shared memory cookie used when freeing * the memory or doing an RPC * a5 Lower 32 bits of 64-bit Shared memory cookie used when freeing * the memory or doing an RPC * a6-7 Preserved */ #define OPTEE_ABI_RPC_FUNC_ALLOC U(0) #define OPTEE_ABI_RETURN_RPC_ALLOC \ OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_ALLOC) /* * Free memory previously allocated by OPTEE_ABI_RETURN_RPC_ALLOC * * "Call" register usage: * a0 This value, OPTEE_ABI_RETURN_RPC_FREE * a1 Upper 32 bits of 64-bit shared memory cookie belonging to this * argument memory * a2 Lower 32 bits of 64-bit shared memory cookie belonging to this * argument memory * a3-7 Resume information, must be preserved * * "Return" register usage: * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. * a1-2 Not used * a3-7 Preserved */ #define OPTEE_ABI_RPC_FUNC_FREE U(2) #define OPTEE_ABI_RETURN_RPC_FREE \ OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_FREE) /* * Deliver a foreign interrupt in normal world. * * "Call" register usage: * a0 OPTEE_ABI_RETURN_RPC_FOREIGN_INTR * a1-7 Resume information, must be preserved * * "Return" register usage: * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. * a1-7 Preserved */ #define OPTEE_ABI_RPC_FUNC_FOREIGN_INTR U(4) #define OPTEE_ABI_RETURN_RPC_FOREIGN_INTR \ OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_FOREIGN_INTR) /* * Do an RPC request. The supplied struct optee_msg_arg tells which * request to do and the parameters for the request. The following fields * are used (the rest are unused): * - cmd the Request ID * - ret return value of the request, filled in by normal world * - num_params number of parameters for the request * - params the parameters * - param_attrs attributes of the parameters * * "Call" register usage: * a0 OPTEE_ABI_RETURN_RPC_CMD * a1 Upper 32 bits of a 64-bit Shared memory cookie holding a * struct optee_msg_arg, must be preserved, only the data should * be updated * a2 Lower 32 bits of a 64-bit Shared memory cookie holding a * struct optee_msg_arg, must be preserved, only the data should * be updated * a3-7 Resume information, must be preserved * * "Return" register usage: * a0 ABI Function ID, OPTEE_ABI_CALL_RETURN_FROM_RPC. * a1-2 Not used * a3-7 Preserved */ #define OPTEE_ABI_RPC_FUNC_CMD U(5) #define OPTEE_ABI_RETURN_RPC_CMD \ OPTEE_ABI_RPC_VAL(OPTEE_ABI_RPC_FUNC_CMD) /* Returned in a0 */ #define OPTEE_ABI_RETURN_UNKNOWN_FUNCTION U(0xFFFFFFFF) /* Returned in a0 only from Trusted OS functions */ #define OPTEE_ABI_RETURN_OK U(0x0) #define OPTEE_ABI_RETURN_ETHREAD_LIMIT U(0x1) #define OPTEE_ABI_RETURN_EBUSY U(0x2) #define OPTEE_ABI_RETURN_ERESUME U(0x3) #define OPTEE_ABI_RETURN_EBADADDR U(0x4) #define OPTEE_ABI_RETURN_EBADCMD U(0x5) #define OPTEE_ABI_RETURN_ENOMEM U(0x6) #define OPTEE_ABI_RETURN_ENOTAVAIL U(0x7) #define OPTEE_ABI_RETURN_IS_RPC(_ret) ({\ typeof(_ret) (ret) = (_ret); \ (((ret) != OPTEE_ABI_RETURN_UNKNOWN_FUNCTION) && \ ((((ret) & OPTEE_ABI_RETURN_RPC_PREFIX_MASK) == \ OPTEE_ABI_RETURN_RPC_PREFIX))); }) #endif /* __TEE_OPTEE_ABI_H */ optee_os-4.3.0/core/arch/riscv/include/tee/teeabi_opteed.h000066400000000000000000000063041464416617300235070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP * Copyright (c) 2014, Linaro Limited */ #ifndef __TEE_TEEABI_OPTEED_H #define __TEE_TEEABI_OPTEED_H /* * This file specify ABI function IDs used when returning from TEE to the * secure monitor if applicable. */ /* * Issued when returning from initial entry. * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_ENTRY_DONE * a1 Pointer to entry vector */ #define TEEABI_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 #define TEEABI_OPTEED_RETURN_ENTRY_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_ENTRY_DONE) /* * Issued when returning from "cpu_on" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_ON_DONE * a1 0 on success and anything else to indicate error condition */ #define TEEABI_OPTEED_FUNCID_RETURN_ON_DONE 1 #define TEEABI_OPTEED_RETURN_ON_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_ON_DONE) /* * Issued when returning from "cpu_off" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_OFF_DONE * a1 0 on success and anything else to indicate error condition */ #define TEEABI_OPTEED_FUNCID_RETURN_OFF_DONE 2 #define TEEABI_OPTEED_RETURN_OFF_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_OFF_DONE) /* * Issued when returning from "cpu_suspend" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_SUSPEND_DONE * a1 0 on success and anything else to indicate error condition */ #define TEEABI_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 #define TEEABI_OPTEED_RETURN_SUSPEND_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SUSPEND_DONE) /* * Issued when returning from "cpu_resume" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_RESUME_DONE * a1 0 on success and anything else to indicate error condition */ #define TEEABI_OPTEED_FUNCID_RETURN_RESUME_DONE 4 #define TEEABI_OPTEED_RETURN_RESUME_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_RESUME_DONE) /* * Issued when returning from "std_abi" or "fast_abi" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_CALL_DONE * a1-4 Return value 0-3 which will passed to non-secure domain in a0-3 */ #define TEEABI_OPTEED_FUNCID_RETURN_CALL_DONE 5 #define TEEABI_OPTEED_RETURN_CALL_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_CALL_DONE) /* * Issued when returning from "fiq" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_FIQ_DONE */ #define TEEABI_OPTEED_FUNCID_RETURN_FIQ_DONE 6 #define TEEABI_OPTEED_RETURN_FIQ_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_FIQ_DONE) /* * Issued when returning from "system_off" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_SYSTEM_OFF_DONE */ #define TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 #define TEEABI_OPTEED_RETURN_SYSTEM_OFF_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) /* * Issued when returning from "system_reset" vector * * Register usage: * a0 ABI Function ID, TEEABI_OPTEED_RETURN_SYSTEM_RESET_DONE */ #define TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 #define TEEABI_OPTEED_RETURN_SYSTEM_RESET_DONE \ TEEABI_OPTEED_RV(TEEABI_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) #endif /*__TEE_TEEABI_OPTEED_H*/ optee_os-4.3.0/core/arch/riscv/include/tee/teeabi_opteed_macros.h000066400000000000000000000005671464416617300250600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP * Copyright (c) 2014, Linaro Limited */ #ifndef __TEE_TEEABI_OPTEED_MACROS_H #define __TEE_TEEABI_OPTEED_MACROS_H #define TEEABI_OPTEED_RV(func_num) \ OPTEE_ABI_CALL_VAL(OPTEE_ABI_32, OPTEE_ABI_FAST_CALL, \ OPTEE_ABI_OWNER_TRUSTED_OS_OPTEED, (func_num)) #endif /*__TEE_TEEABI_OPTEED_MACROS_H*/ optee_os-4.3.0/core/arch/riscv/kernel/000077500000000000000000000000001464416617300176225ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/kernel/abort.c000066400000000000000000000236461464416617300211100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP * Copyright (c) 2015-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include enum fault_type { FAULT_TYPE_USER_MODE_PANIC, FAULT_TYPE_USER_MODE_VFP, FAULT_TYPE_PAGE_FAULT, FAULT_TYPE_IGNORE, }; #ifdef CFG_UNWIND /* Kernel mode unwind */ static void __print_stack_unwind(struct abort_info *ai) { struct unwind_state_riscv state = { .fp = ai->regs->s0, .pc = ai->regs->epc, }; print_stack_riscv(&state, thread_stack_start(), thread_stack_size()); } #else /* CFG_UNWIND */ static void __print_stack_unwind(struct abort_info *ai __unused) { } #endif /* CFG_UNWIND */ static __maybe_unused const char *abort_type_to_str(uint32_t abort_type) { if (abort_type == ABORT_TYPE_DATA) return "data"; if (abort_type == ABORT_TYPE_PREFETCH) return "prefetch"; return "undef"; } static __maybe_unused const char * fault_to_str(uint32_t abort_type, uint32_t fault_descr) { /* fault_descr is only valid for data or prefetch abort */ if (abort_type != ABORT_TYPE_DATA && abort_type != ABORT_TYPE_PREFETCH) return ""; switch (core_mmu_get_fault_type(fault_descr)) { case CORE_MMU_FAULT_ALIGNMENT: return " (alignment fault)"; case CORE_MMU_FAULT_TRANSLATION: return " (translation fault)"; case CORE_MMU_FAULT_READ_PERMISSION: return " (read permission fault)"; case CORE_MMU_FAULT_WRITE_PERMISSION: return " (write permission fault)"; case CORE_MMU_FAULT_TAG_CHECK: return " (tag check fault)"; default: return ""; } } static __maybe_unused void __print_abort_info(struct abort_info *ai __maybe_unused, const char *ctx __maybe_unused) { __maybe_unused size_t core_pos = 0; if (abort_is_user_exception(ai)) core_pos = thread_get_tsd()->abort_core; else core_pos = get_core_pos(); EMSG_RAW(""); EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "%s", ctx, abort_type_to_str(ai->abort_type), ai->va, fault_to_str(ai->abort_type, ai->fault_descr)); EMSG_RAW("cpu\t#%zu", core_pos); EMSG_RAW("cause\t%016" PRIxPTR " epc\t%016" PRIxPTR, ai->regs->cause, ai->regs->epc); EMSG_RAW("tval\t%016" PRIxPTR " status\t%016" PRIxPTR, ai->regs->tval, ai->regs->status); EMSG_RAW("ra\t%016" PRIxPTR " sp\t%016" PRIxPTR, ai->regs->ra, ai->regs->sp); EMSG_RAW("gp\t%016" PRIxPTR " tp\t%016" PRIxPTR, ai->regs->gp, ai->regs->tp); EMSG_RAW("t0\t%016" PRIxPTR " t1\t%016" PRIxPTR, ai->regs->t0, ai->regs->t1); EMSG_RAW("t2\t%016" PRIxPTR " s0\t%016" PRIxPTR, ai->regs->t2, ai->regs->s0); EMSG_RAW("s1\t%016" PRIxPTR " a0\t%016" PRIxPTR, ai->regs->s1, ai->regs->a0); EMSG_RAW("a1\t%016" PRIxPTR " a2\t%016" PRIxPTR, ai->regs->a1, ai->regs->a2); EMSG_RAW("a3\t%016" PRIxPTR " a4\t%016" PRIxPTR, ai->regs->a3, ai->regs->a4); EMSG_RAW("a5\t%016" PRIxPTR " a5\t%016" PRIxPTR, ai->regs->a5, ai->regs->a5); EMSG_RAW("a6\t%016" PRIxPTR " a7\t%016" PRIxPTR, ai->regs->a6, ai->regs->a7); EMSG_RAW("s2\t%016" PRIxPTR " s3\t%016" PRIxPTR, ai->regs->s2, ai->regs->s3); EMSG_RAW("s4\t%016" PRIxPTR " s5\t%016" PRIxPTR, ai->regs->s4, ai->regs->s5); EMSG_RAW("s6\t%016" PRIxPTR " s7\t%016" PRIxPTR, ai->regs->s6, ai->regs->s7); EMSG_RAW("s8\t%016" PRIxPTR " s9\t%016" PRIxPTR, ai->regs->s8, ai->regs->s9); EMSG_RAW("s10\t%016" PRIxPTR " s11\t%016" PRIxPTR, ai->regs->s10, ai->regs->s11); EMSG_RAW("t3\t%016" PRIxPTR " t4\t%016" PRIxPTR, ai->regs->t3, ai->regs->t4); EMSG_RAW("t5\t%016" PRIxPTR " t6\t%016" PRIxPTR, ai->regs->t5, ai->regs->t6); } /* * Print abort info and (optionally) stack dump to the console * @ai kernel-mode abort info. * @stack_dump true to show a stack trace */ static void __abort_print(struct abort_info *ai, bool stack_dump) { assert(!abort_is_user_exception(ai)); __print_abort_info(ai, "Core"); if (stack_dump) { trace_printf_helper_raw(TRACE_ERROR, true, "TEE load address @ %#"PRIxVA, VCORE_START_VA); __print_stack_unwind(ai); } } void abort_print(struct abort_info *ai) { __abort_print(ai, false); } void abort_print_error(struct abort_info *ai) { __abort_print(ai, true); } /* This function must be called from a normal thread */ void abort_print_current_ts(void) { struct thread_specific_data *tsd = thread_get_tsd(); struct abort_info ai = { }; struct ts_session *s = ts_get_current_session(); ai.abort_type = tsd->abort_type; ai.fault_descr = tsd->abort_descr; ai.va = tsd->abort_va; ai.pc = tsd->abort_regs.epc; ai.regs = &tsd->abort_regs; if (ai.abort_type != ABORT_TYPE_USER_MODE_PANIC) __print_abort_info(&ai, "User mode"); s->ctx->ops->dump_state(s->ctx); #if defined(CFG_FTRACE_SUPPORT) if (s->ctx->ops->dump_ftrace) { s->fbuf = NULL; s->ctx->ops->dump_ftrace(s->ctx); } #endif } static void save_abort_info_in_tsd(struct abort_info *ai) { struct thread_specific_data *tsd = thread_get_tsd(); tsd->abort_type = ai->abort_type; tsd->abort_descr = ai->fault_descr; tsd->abort_va = ai->va; tsd->abort_regs = *ai->regs; tsd->abort_core = get_core_pos(); } static void set_abort_info(uint32_t abort_type __unused, struct thread_abort_regs *regs, struct abort_info *ai) { ai->fault_descr = regs->cause; switch (ai->fault_descr) { case CAUSE_MISALIGNED_FETCH: case CAUSE_FETCH_ACCESS: case CAUSE_FETCH_PAGE_FAULT: case CAUSE_FETCH_GUEST_PAGE_FAULT: ai->abort_type = ABORT_TYPE_PREFETCH; break; case CAUSE_MISALIGNED_LOAD: case CAUSE_LOAD_ACCESS: case CAUSE_MISALIGNED_STORE: case CAUSE_STORE_ACCESS: case CAUSE_LOAD_PAGE_FAULT: case CAUSE_STORE_PAGE_FAULT: case CAUSE_LOAD_GUEST_PAGE_FAULT: case CAUSE_STORE_GUEST_PAGE_FAULT: ai->abort_type = ABORT_TYPE_DATA; break; default: ai->abort_type = ABORT_TYPE_UNDEF; } ai->va = regs->tval; ai->pc = regs->epc; ai->regs = regs; } static void handle_user_mode_panic(struct abort_info *ai) { /* * It was a user exception, stop user execution and return * to TEE Core. */ ai->regs->a0 = TEE_ERROR_TARGET_DEAD; ai->regs->a1 = true; ai->regs->a2 = 0xdeadbeef; ai->regs->ra = (vaddr_t)thread_unwind_user_mode; ai->regs->sp = thread_get_saved_thread_sp(); ai->regs->status = xstatus_for_xret(true, PRV_S); thread_exit_user_mode(ai->regs->a0, ai->regs->a1, ai->regs->a2, ai->regs->a3, ai->regs->sp, ai->regs->ra, ai->regs->status); } #ifdef CFG_WITH_VFP static void handle_user_mode_vfp(void) { struct ts_session *s = ts_get_current_session(); thread_user_enable_vfp(&to_user_mode_ctx(s->ctx)->vfp); } #endif /*CFG_WITH_VFP*/ #ifdef CFG_WITH_USER_TA /* Returns true if the exception originated from user mode */ bool abort_is_user_exception(struct abort_info *ai) { return (ai->regs->status & CSR_XSTATUS_SPP) == 0; } #else /*CFG_WITH_USER_TA*/ bool abort_is_user_exception(struct abort_info *ai __unused) { return false; } #endif /*CFG_WITH_USER_TA*/ #if defined(CFG_WITH_VFP) && defined(CFG_WITH_USER_TA) static bool is_vfp_fault(struct abort_info *ai) { /* Implement */ return false; } #else /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ static bool is_vfp_fault(struct abort_info *ai __unused) { return false; } #endif /*CFG_WITH_VFP && CFG_WITH_USER_TA*/ static enum fault_type get_fault_type(struct abort_info *ai) { if (abort_is_user_exception(ai)) { if (is_vfp_fault(ai)) return FAULT_TYPE_USER_MODE_VFP; return FAULT_TYPE_USER_MODE_PANIC; } if (thread_is_from_abort_mode()) { abort_print_error(ai); panic("[abort] abort in abort handler (trap CPU)"); } if (ai->abort_type == ABORT_TYPE_UNDEF) { if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] undefined abort (trap CPU)"); } switch (core_mmu_get_fault_type(ai->fault_descr)) { case CORE_MMU_FAULT_ALIGNMENT: if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] alignment fault! (trap CPU)"); break; case CORE_MMU_FAULT_ACCESS_BIT: if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] access bit fault! (trap CPU)"); break; case CORE_MMU_FAULT_DEBUG_EVENT: if (!abort_is_user_exception(ai)) abort_print(ai); DMSG("[abort] Ignoring debug event!"); return FAULT_TYPE_IGNORE; case CORE_MMU_FAULT_TRANSLATION: case CORE_MMU_FAULT_WRITE_PERMISSION: case CORE_MMU_FAULT_READ_PERMISSION: return FAULT_TYPE_PAGE_FAULT; case CORE_MMU_FAULT_ASYNC_EXTERNAL: if (!abort_is_user_exception(ai)) abort_print(ai); DMSG("[abort] Ignoring async external abort!"); return FAULT_TYPE_IGNORE; case CORE_MMU_FAULT_TAG_CHECK: if (abort_is_user_exception(ai)) return FAULT_TYPE_USER_MODE_PANIC; abort_print_error(ai); panic("[abort] Tag check fault! (trap CPU)"); break; case CORE_MMU_FAULT_OTHER: default: if (!abort_is_user_exception(ai)) abort_print(ai); DMSG("[abort] Unhandled fault!"); return FAULT_TYPE_IGNORE; } } void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs) { struct abort_info ai; set_abort_info(abort_type, regs, &ai); switch (get_fault_type(&ai)) { case FAULT_TYPE_IGNORE: break; case FAULT_TYPE_USER_MODE_PANIC: DMSG("[abort] abort in User mode (TA will panic)"); save_abort_info_in_tsd(&ai); #ifdef CFG_WITH_VFP vfp_disable(); #endif handle_user_mode_panic(&ai); break; #ifdef CFG_WITH_VFP case FAULT_TYPE_USER_MODE_VFP: handle_user_mode_vfp(); break; #endif case FAULT_TYPE_PAGE_FAULT: default: if (thread_get_id_may_fail() < 0) { abort_print_error(&ai); panic("abort outside thread context"); } if (!abort_is_user_exception(&ai)) { abort_print_error(&ai); panic("unhandled page fault abort"); } DMSG("[abort] abort in User mode (TA will panic)"); save_abort_info_in_tsd(&ai); #ifdef CFG_WITH_VFP vfp_disable(); #endif handle_user_mode_panic(&ai); break; } } optee_os-4.3.0/core/arch/riscv/kernel/arch_scall.c000066400000000000000000000040011464416617300220540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023 Andes Technology Corporation * Copyright 2022-2023 NXP * Copyright (c) 2014-2022, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #include #include #include #define TA_CONTEXT_MAX_SIZE (RISCV_XLEN_BYTES * 32) #ifdef CFG_UNWIND /* Get register values pushed onto the stack by _utee_panic() */ static void save_panic_regs_rv_ta(struct thread_specific_data *tsd, unsigned long *pushed) { TEE_Result res = TEE_SUCCESS; unsigned long s0 = 0; unsigned long epc = 0; #if defined(RV32) unsigned long *stack_s0 = &pushed[2]; unsigned long *stack_epc = &pushed[3]; #elif defined(RV64) unsigned long *stack_s0 = &pushed[0]; unsigned long *stack_epc = &pushed[1]; #endif res = GET_USER_SCALAR(s0, stack_s0); if (res) s0 = 0; res = GET_USER_SCALAR(epc, stack_epc); if (res) epc = 0; tsd->abort_regs = (struct thread_abort_regs){ .sp = (unsigned long)pushed, .s0 = s0, .epc = epc, }; } void scall_save_panic_stack(struct thread_scall_regs *regs) { struct thread_specific_data *tsd = thread_get_tsd(); struct ts_session *s = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx); if (vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE, (uaddr_t)regs->a1, TA_CONTEXT_MAX_SIZE)) { TAMSG_RAW(""); TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA, (uaddr_t)regs->a1); return; } tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; tsd->abort_descr = 0; tsd->abort_va = 0; save_panic_regs_rv_ta(tsd, (unsigned long *)regs->a1); } #else /* CFG_UNWIND */ void scall_save_panic_stack(struct thread_scall_regs *regs __unused) { struct thread_specific_data *tsd = thread_get_tsd(); tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC; } #endif /* CFG_UNWIND */ optee_os-4.3.0/core/arch/riscv/kernel/arch_scall_rv.S000066400000000000000000000024511464416617300225520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #include "tee_syscall_numbers.h" #include "trace_levels.h" #include #include #include #include #include #include /* * uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); * * Called from scall_handle_user_ta() */ FUNC scall_do_call , : addi sp, sp, -16 /* Save scall regs to t0 */ mv t0, a0 /* Save func to t1 */ mv t1, a1 /* Push return address to stack */ store_xregs sp, 0, 1 /* Load arguments to function */ load_xregs a0, THREAD_SCALL_REG_A0, 10, 17 /* Call the syscall function */ jalr t1 /* Pop return address from stack */ load_xregs sp, 0, 1 addi sp, sp, 16 ret END_FUNC scall_do_call /* * void syscall_sys_return(uint32_t ret); */ FUNC syscall_sys_return , : li a1, 0 /* panic = false */ li a2, 0 /* panic_code = 0 */ mv a3, t0 /* pointer to struct thread_scall_regs */ j scall_sys_return_helper END_FUNC syscall_sys_return /* * void syscall_panic(uint32_t code); */ FUNC syscall_panic , : li a1, 1 /* panic = true */ mv a2, a0 /* code */ li a0, TEE_ERROR_TARGET_DEAD mv a3, t0 /* pointer to struct thread_scall_regs */ j scall_sys_return_helper END_FUNC syscall_panic optee_os-4.3.0/core/arch/riscv/kernel/asm-defines.c000066400000000000000000000117421464416617300221660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include DEFINES { /* struct thread_ctx */ DEFINE(THREAD_CTX_KERN_SP, offsetof(struct thread_ctx, kern_sp)); DEFINE(THREAD_CTX_STACK_VA_END, offsetof(struct thread_ctx, stack_va_end)); DEFINE(THREAD_CTX_SIZE, sizeof(struct thread_ctx)); /* struct thread_core_local */ DEFINE(THREAD_CORE_LOCAL_SIZE, sizeof(struct thread_core_local)); DEFINE(THREAD_CORE_LOCAL_HART_ID, offsetof(struct thread_core_local, hart_id)); DEFINE(THREAD_CORE_LOCAL_TMP_STACK_VA_END, offsetof(struct thread_core_local, tmp_stack_va_end)); DEFINE(THREAD_CORE_LOCAL_CURR_THREAD, offsetof(struct thread_core_local, curr_thread)); DEFINE(THREAD_CORE_LOCAL_FLAGS, offsetof(struct thread_core_local, flags)); DEFINE(THREAD_CORE_LOCAL_ABT_STACK_VA_END, offsetof(struct thread_core_local, abt_stack_va_end)); DEFINE(THREAD_CORE_LOCAL_X0, offsetof(struct thread_core_local, x[0])); DEFINE(THREAD_CORE_LOCAL_X1, offsetof(struct thread_core_local, x[1])); DEFINE(STACK_TMP_GUARD, STACK_CANARY_SIZE / 2 + STACK_TMP_OFFS); /* struct thread_ctx_regs */ DEFINE(THREAD_CTX_REG_STATUS, offsetof(struct thread_ctx_regs, status)); DEFINE(THREAD_CTX_REG_EPC, offsetof(struct thread_ctx_regs, epc)); DEFINE(THREAD_CTX_REG_IE, offsetof(struct thread_ctx_regs, ie)); DEFINE(THREAD_CTX_REG_RA, offsetof(struct thread_ctx_regs, ra)); DEFINE(THREAD_CTX_REG_SP, offsetof(struct thread_ctx_regs, sp)); DEFINE(THREAD_CTX_REG_GP, offsetof(struct thread_ctx_regs, gp)); DEFINE(THREAD_CTX_REG_TP, offsetof(struct thread_ctx_regs, tp)); DEFINE(THREAD_CTX_REG_T0, offsetof(struct thread_ctx_regs, t0)); DEFINE(THREAD_CTX_REG_S0, offsetof(struct thread_ctx_regs, s0)); DEFINE(THREAD_CTX_REG_A0, offsetof(struct thread_ctx_regs, a0)); DEFINE(THREAD_CTX_REG_S2, offsetof(struct thread_ctx_regs, s2)); DEFINE(THREAD_CTX_REG_T3, offsetof(struct thread_ctx_regs, t3)); DEFINE(THREAD_CTX_REGS_SIZE, sizeof(struct thread_ctx_regs)); /* struct thread_user_mode_rec */ DEFINE(THREAD_USER_MODE_REC_CTX_REGS_PTR, offsetof(struct thread_user_mode_rec, ctx_regs_ptr)); DEFINE(THREAD_USER_MODE_REC_X1, offsetof(struct thread_user_mode_rec, x[0])); DEFINE(THREAD_USER_MODE_REC_X4, offsetof(struct thread_user_mode_rec, x[3])); DEFINE(THREAD_USER_MODE_REC_X8, offsetof(struct thread_user_mode_rec, x[4])); DEFINE(THREAD_USER_MODE_REC_X18, offsetof(struct thread_user_mode_rec, x[6])); DEFINE(THREAD_USER_MODE_REC_SIZE, sizeof(struct thread_user_mode_rec)); /* struct thread_abort_regs */ DEFINE(THREAD_ABT_REG_RA, offsetof(struct thread_abort_regs, ra)); DEFINE(THREAD_ABT_REG_SP, offsetof(struct thread_abort_regs, sp)); DEFINE(THREAD_ABT_REG_GP, offsetof(struct thread_abort_regs, gp)); DEFINE(THREAD_ABT_REG_TP, offsetof(struct thread_abort_regs, tp)); DEFINE(THREAD_ABT_REG_T0, offsetof(struct thread_abort_regs, t0)); DEFINE(THREAD_ABT_REG_S0, offsetof(struct thread_abort_regs, s0)); DEFINE(THREAD_ABT_REG_A0, offsetof(struct thread_abort_regs, a0)); DEFINE(THREAD_ABT_REG_S2, offsetof(struct thread_abort_regs, s2)); DEFINE(THREAD_ABT_REG_T3, offsetof(struct thread_abort_regs, t3)); DEFINE(THREAD_ABT_REG_EPC, offsetof(struct thread_abort_regs, epc)); DEFINE(THREAD_ABT_REG_STATUS, offsetof(struct thread_abort_regs, status)); DEFINE(THREAD_ABT_REG_IE, offsetof(struct thread_abort_regs, ie)); DEFINE(THREAD_ABT_REG_CAUSE, offsetof(struct thread_abort_regs, cause)); DEFINE(THREAD_ABT_REG_TVAL, offsetof(struct thread_abort_regs, tval)); DEFINE(THREAD_ABT_REGS_SIZE, sizeof(struct thread_abort_regs)); /* struct thread_scall_regs */ DEFINE(THREAD_SCALL_REG_RA, offsetof(struct thread_scall_regs, ra)); DEFINE(THREAD_SCALL_REG_SP, offsetof(struct thread_scall_regs, sp)); DEFINE(THREAD_SCALL_REG_GP, offsetof(struct thread_scall_regs, gp)); DEFINE(THREAD_SCALL_REG_TP, offsetof(struct thread_scall_regs, tp)); DEFINE(THREAD_SCALL_REG_T0, offsetof(struct thread_scall_regs, t0)); DEFINE(THREAD_SCALL_REG_A0, offsetof(struct thread_scall_regs, a0)); DEFINE(THREAD_SCALL_REG_T3, offsetof(struct thread_scall_regs, t3)); DEFINE(THREAD_SCALL_REG_EPC, offsetof(struct thread_scall_regs, epc)); DEFINE(THREAD_SCALL_REG_STATUS, offsetof(struct thread_scall_regs, status)); DEFINE(THREAD_SCALL_REG_IE, offsetof(struct thread_scall_regs, ie)); DEFINE(THREAD_SCALL_REGS_SIZE, sizeof(struct thread_scall_regs)); /* struct core_mmu_config */ DEFINE(CORE_MMU_CONFIG_SIZE, sizeof(struct core_mmu_config)); DEFINE(CORE_MMU_CONFIG_SATP, offsetof(struct core_mmu_config, satp[0])); DEFINE(CORE_MMU_CONFIG_SATP_SIZE, sizeof(unsigned long)); /* struct thread_abi_args */ DEFINE(THREAD_ABI_ARGS_A0, offsetof(struct thread_abi_args, a0)); DEFINE(THREAD_ABI_ARGS_SIZE, sizeof(struct thread_abi_args)); } optee_os-4.3.0/core/arch/riscv/kernel/boot.c000066400000000000000000000102651464416617300207350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023 Andes Technology Corporation * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PADDR_INVALID ULONG_MAX paddr_t start_addr; unsigned long boot_args[4]; uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE]; #if defined(CFG_DT) static int mark_tddram_as_reserved(struct dt_descriptor *dt) { return add_res_mem_dt_node(dt, "optee_core", CFG_TDDRAM_START, CFG_TDDRAM_SIZE); } static void update_external_dt(void) { struct dt_descriptor *dt = get_external_dt_desc(); if (!dt || !dt->blob) return; #ifdef CFG_CORE_RESERVED_SHM if (mark_static_shm_as_reserved(dt)) panic("Failed to config non-secure memory"); #endif if (mark_tddram_as_reserved(dt)) panic("Failed to config secure memory"); } #else /*CFG_DT*/ static void update_external_dt(void) { } #endif /*!CFG_DT*/ void init_sec_mon(unsigned long nsec_entry __maybe_unused) { assert(nsec_entry == PADDR_INVALID); /* Do nothing as we don't have a secure monitor */ } #ifdef CFG_RISCV_S_MODE static void start_secondary_cores(void) { size_t i = 0; size_t pos = get_core_pos(); for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++) if (i != pos && IS_ENABLED(CFG_RISCV_SBI) && sbi_hsm_hart_start(i, start_addr, i)) EMSG("Error starting secondary hart %zu", i); } #endif static void init_runtime(void) { malloc_add_pool(__heap1_start, __heap1_end - __heap1_start); IMSG_RAW("\n"); } void init_tee_runtime(void) { core_mmu_init_ta_ram(); call_preinitcalls(); call_initcalls(); } static void init_primary(unsigned long nsec_entry) { thread_init_core_local_stacks(); /* * Mask asynchronous exceptions before switch to the thread vector * as the thread handler requires those to be masked while * executing with the temporary stack. The thread subsystem also * asserts that the foreign interrupts are blocked when using most of * its functions. */ thread_set_exceptions(THREAD_EXCP_ALL); init_runtime(); thread_init_boot_thread(); thread_init_primary(); thread_init_per_cpu(); init_sec_mon(nsec_entry); } /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void plat_primary_init_early(void) { } /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void boot_primary_init_intc(void) { } /* May be overridden in plat-$(PLATFORM)/main.c */ __weak void boot_secondary_init_intc(void) { } void boot_init_primary_early(void) { unsigned long e = PADDR_INVALID; init_primary(e); } void boot_init_primary_late(unsigned long fdt, unsigned long tos_fw_config __unused) { init_external_dt(fdt, CFG_DTB_MAX_SIZE); discover_nsec_memory(); update_external_dt(); IMSG("OP-TEE version: %s", core_v_str); if (IS_ENABLED(CFG_INSECURE)) { IMSG("WARNING: This OP-TEE configuration might be insecure!"); IMSG("WARNING: Please check https://optee.readthedocs.io/en/latest/architecture/porting_guidelines.html"); } IMSG("Primary CPU initializing"); boot_primary_init_intc(); init_tee_runtime(); call_finalcalls(); IMSG("Primary CPU initialized"); #ifdef CFG_RISCV_S_MODE start_secondary_cores(); #endif } static void init_secondary_helper(unsigned long nsec_entry) { size_t pos = get_core_pos(); IMSG("Secondary CPU %zu initializing", pos); /* * Mask asynchronous exceptions before switch to the thread vector * as the thread handler requires those to be masked while * executing with the temporary stack. The thread subsystem also * asserts that the foreign interrupts are blocked when using most of * its functions. */ thread_set_exceptions(THREAD_EXCP_ALL); thread_init_per_cpu(); init_sec_mon(nsec_entry); boot_secondary_init_intc(); IMSG("Secondary CPU %zu initialized", pos); } void boot_init_secondary(unsigned long nsec_entry __unused) { init_secondary_helper(PADDR_INVALID); } optee_os-4.3.0/core/arch/riscv/kernel/cache_helpers_rv.S000066400000000000000000000030131464416617300232370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #include #include /* * On the below data cache management, we rely on FENCE instruction. * The FENCE instruction is used to order device I/O and memory accesses * as viewed by other RISC-V harts and external devices or coprocessors. * "fence" below is a pseudo-instruction of "fence iorw, iorw" which * performs Fence on all memory and I/O. */ /* void dcache_cleaninv_range(void *addr, size_t size); */ FUNC dcache_cleaninv_range , : fence ret END_FUNC dcache_cleaninv_range /* void dcache_clean_range(void *addr, size_t size); */ FUNC dcache_clean_range , : fence ret END_FUNC dcache_clean_range /* void dcache_inv_range(void *addr, size_t size); */ FUNC dcache_inv_range , : fence ret END_FUNC dcache_inv_range /* void dcache_op_all(unsigned long op_type); */ FUNC dcache_op_all , : fence ret END_FUNC dcache_op_all /* void icache_inv_all(void); */ FUNC icache_inv_all , : /* * FENCE.I instruction provides explicit synchronization * between writes to instruction memory and instruction * fetches on the same hart. This implies instruction cache * management operations as result of executing this instruction. */ fence.i ret END_FUNC icache_inv_all /* void icache_inv_range(void *addr, size_t size); */ FUNC icache_inv_range , : /* * RISC-V does not have an instruction to flush a range * of the I$, therefore, flush it entirely as invoking * icache_inv_all(). */ fence.i ret END_FUNC icache_inv_range optee_os-4.3.0/core/arch/riscv/kernel/csr_detect.S000066400000000000000000000034671464416617300220770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024 Andes Technology Corporation */ #include #include #define DETECT_OP_CSRR 0 #define DETECT_OP_CSRRW 1 .macro save_and_disable_xie reg csrrw \reg, CSR_XIE, zero .endm .macro restore_xie reg csrw CSR_XIE, \reg .endm .macro save_and_replace_xtvec reg, label la \reg, \label csrrw \reg, CSR_XTVEC, \reg .endm .macro restore_xtvec reg csrw CSR_XTVEC, \reg .endm /** * @brief A temporary trap handler to handle an exception during csr detection. * If csr read/write instruction leads to a trap, CPU will enter this * function and XRET with a0 = 0, which means the csr is not detected. * The caller must expect that a0 is used in this function. */ FUNC csr_detect_trap_vect , : csrr a0, CSR_XEPC addi a0, a0, 4 csrw CSR_XEPC, a0 mv a0, zero XRET END_FUNC csr_detect_trap_vect /* Detect CSR by csrr/csrrw instruction. a0=1 if detected, otherwise a0=0 */ .macro detect_csr csr, op, reg0, reg1, reg2 addi a0, a0, 1 save_and_disable_xie \reg0 save_and_replace_xtvec \reg1, csr_detect_trap_vect .if \op == DETECT_OP_CSRR csrr \reg2, \csr .elseif \op == DETECT_OP_CSRRW csrrw \reg2, \csr, zero .endif restore_xtvec \reg1 restore_xie \reg0 .endm .macro detect_csr_by_csrr csr, reg0, reg1, reg2 detect_csr \csr, DETECT_OP_CSRR, \reg0, \reg1, \reg2 .endm .macro detect_csr_by_csrrw csr, reg0, reg1, reg2 detect_csr \csr, DETECT_OP_CSRRW, \reg0, \reg1, \reg2 .endm /** * bool riscv_detect_csr_seed(void); * @brief A helper function to detect if CSR seed is accessible. The value of a0 * will be cleared by csr_detect_trap_vect() if exception occurs. * @retval 1 if CSR seed is detected, otherwise 0 */ FUNC riscv_detect_csr_seed , : detect_csr_by_csrrw seed, a1, a2, a3 ret END_FUNC riscv_detect_csr_seed optee_os-4.3.0/core/arch/riscv/kernel/entry.S000066400000000000000000000133771464416617300211220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include .section .data .balign 4 #ifdef CFG_BOOT_SYNC_CPU .equ SEM_CPU_READY, 1 #endif /* * Setup sp to point to the top of the tmp stack for the current CPU: * sp is assigned: * stack_tmp + (hartid + 1) * stack_tmp_stride - STACK_TMP_GUARD */ .macro set_sp /* Unsupported CPU, park it before it breaks something */ li t1, CFG_TEE_CORE_NB_CORE csrr t0, CSR_XSCRATCH bge t0, t1, unhandled_cpu addi t0, t0, 1 lw t1, stack_tmp_stride /* * t0 = (hartid + 1) * t1 = value of stack_tmp_stride * value of stack_tmp_rel = stack_tmp - stack_tmp_rel - STACK_TMP_GUARD * sp = stack_tmp + (hartid + 1) * stack_tmp_stride - STACK_TMP_GUARD * = stack_tmp_rel + (value of stack_tmp_rel) + (t0 * t1) */ mul t1, t0, t1 la t2, stack_tmp_rel lw t0, 0(t2) add t0, t0, t2 add sp, t1, t0 .endm .macro cpu_is_ready #ifdef CFG_BOOT_SYNC_CPU csrr t0, CSR_XSCRATCH la t1, sem_cpu_sync slli t0, t0, 2 add t1, t1, t0 li t2, SEM_CPU_READY sw t2, 0(t1) fence #endif .endm .macro set_tp csrr a0, CSR_XSCRATCH li a1, THREAD_CORE_LOCAL_SIZE la tp, thread_core_local mul a2, a1, a0 add tp, tp, a2 sw a0, THREAD_CORE_LOCAL_HART_ID(tp) .endm .macro set_satp /* * a0 = hartid * a1 = address of boot_mmu_config.satp[0] * a2 = size of CSR SATP * * This hart's SATP is of value (a1 + (a0 * a2)). */ csrr a0, CSR_XSCRATCH la a1, boot_mmu_config addi a1, a1, CORE_MMU_CONFIG_SATP li a2, CORE_MMU_CONFIG_SATP_SIZE mul a0, a0, a2 add a1, a1, a0 LDR a2, 0(a1) csrw CSR_SATP, a2 sfence.vma zero, zero .endm .macro wait_primary #ifdef CFG_BOOT_SYNC_CPU la t0, sem_cpu_sync li t2, SEM_CPU_READY 1: fence w, w lw t1, 0(t0) bne t1, t2, 1b #endif .endm .macro wait_secondary #ifdef CFG_BOOT_SYNC_CPU la t0, sem_cpu_sync li t1, CFG_TEE_CORE_NB_CORE li t2, SEM_CPU_READY 1: addi t1, t1, -1 beqz t1, 3f addi t0, t0, 4 2: fence lw t1, 0(t0) bne t1, t2, 2b j 1b 3: #endif .endm #ifdef CFG_BOOT_SYNC_CPU #define flush_cpu_semaphores \ la t0, sem_cpu_sync_start la t1, sem_cpu_sync_end fence #else #define flush_cpu_semaphores #endif .macro bootargs_entry /* * Save boot arguments */ la t0, boot_args /* Save boot hart */ STR a0, REGOFF(0)(t0) /* Save FDT address */ STR a1, REGOFF(1)(t0) .endm FUNC _start , : /* * Register usage: * a0 - if non-NULL holds the hart ID * a1 - if non-NULL holds the system DTB address * * CSR_XSCRATCH - saved a0 * s1 - saved a1 */ .option push .option norelax la gp, __global_pointer$ .option pop #ifdef CFG_RISCV_M_MODE csrr a0, CSR_MHARTID #endif csrw CSR_XSCRATCH, a0 #if defined(CFG_DT_ADDR) li s1, CFG_DT_ADDR #else mv s1, a1 /* Save device tree address into s1 */ #endif /* Only first hart who wins lottery runs the primary boot sequence. */ la a3, hart_lottery li a2, 1 amoadd.w a3, a2, (a3) bnez a3, reset_secondary jal reset_primary j . END_FUNC _start LOCAL_FUNC reset_primary , : , .identity_map UNWIND( .cantunwind) bootargs_entry /* * Zero bss */ lla t0, __bss_start lla t1, __bss_end beq t0, t1, 1f 0: STR zero, (t0) add t0, t0, RISCV_XLEN_BYTES bne t0, t1, 0b 1: #ifdef CFG_RISCV_S_MODE lla t0, _start lla t1, start_addr STR t0, (t1) #endif csrw CSR_SATP, zero set_sp set_tp jal thread_init_thread_core_local jal plat_primary_init_early jal console_init mv a0, x0 la a1, boot_mmu_config jal core_init_mmu_map set_satp jal boot_init_primary_early /* * Before entering boot_init_primary_late(), we do these two steps: * 1. Save current sp to s2, and set sp as threads[0].stack_va_end * 2. Clear the flag which indicates usage of the temporary stack in the * current hart's thread_core_local structure. */ mv s2, sp la a0, threads LDR a0, THREAD_CTX_STACK_VA_END(a0) mv sp, a0 jal thread_get_core_local mv s3, a0 sw zero, THREAD_CORE_LOCAL_FLAGS(s3) mv a0, s1 /* s1 contains saved device tree address */ mv a1, x0 /* unused */ jal boot_init_primary_late /* * After returning from boot_init_primary_late(), the flag and sp are * restored. */ li a0, THREAD_CLF_TMP sw a0, THREAD_CORE_LOCAL_FLAGS(s3) mv sp, s2 cpu_is_ready flush_cpu_semaphores wait_secondary jal thread_clr_boot_thread li a0, TEEABI_OPTEED_RETURN_ENTRY_DONE la a1, thread_vector_table j thread_return_to_udomain END_FUNC reset_primary LOCAL_FUNC reset_secondary , : , .identity_map UNWIND( .cantunwind) wait_primary csrw CSR_SATP, zero set_sp set_tp set_satp cpu_is_ready jal boot_init_secondary #ifdef CFG_RISCV_WITH_M_MODE_SM /* Return to untrusted domain */ li a0, TEEABI_OPTEED_RETURN_ON_DONE j thread_return_to_udomain #endif j . END_FUNC reset_secondary LOCAL_FUNC unhandled_cpu , : wfi j unhandled_cpu END_FUNC unhandled_cpu .section .identity_map.data .balign 8 LOCAL_DATA hart_lottery , : /* The hart who first increments this variable will be primary hart. */ .word 0 END_DATA hart_lottery #ifdef CFG_BOOT_SYNC_CPU LOCAL_DATA sem_cpu_sync_start , : .word sem_cpu_sync END_DATA sem_cpu_sync_start LOCAL_DATA sem_cpu_sync_end , : .word sem_cpu_sync + (CFG_TEE_CORE_NB_CORE << 2) END_DATA sem_cpu_sync_end #endif LOCAL_DATA stack_tmp_rel , : .word stack_tmp - stack_tmp_rel - STACK_TMP_GUARD END_DATA stack_tmp_rel LOCAL_DATA stack_tmp_stride_rel , : .word stack_tmp_stride - stack_tmp_stride_rel END_DATA stack_tmp_stride_rel .balign 8 LOCAL_DATA boot_mmu_config , : /* struct core_mmu_config */ .skip CORE_MMU_CONFIG_SIZE END_DATA boot_mmu_config optee_os-4.3.0/core/arch/riscv/kernel/idle.c000066400000000000000000000003401464416617300207000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include void cpu_idle(void) { /* ensure memory operations were complete */ mb(); /* stall the hart */ wfi(); } optee_os-4.3.0/core/arch/riscv/kernel/kern.ld.S000066400000000000000000000176141464416617300213140ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND MIT) */ /* * Copyright 2022-2023 NXP */ /* * Copyright (c) 2014, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2008-2010 Travis Geiselbrecht * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include /* * Note: * Clang 11 (ld.lld) generates non-relocatable reference when using ROUNDDOWN() * from , which does not work with ASLR. */ #define LD_ROUNDDOWN(x, y) ((x) - ((x) % (y))) OUTPUT_FORMAT(CFG_KERN_LINKER_FORMAT) OUTPUT_ARCH(CFG_KERN_LINKER_ARCH) ENTRY(_start) SECTIONS { . = TEE_LOAD_ADDR; /* Ensure text section is page aligned */ ASSERT(!(TEE_LOAD_ADDR & (SMALL_PAGE_SIZE - 1)), "text start should align to 4Kb") __text_start = .; /* * Memory between TEE_LOAD_ADDR and page aligned rounded down * value will be mapped with unpaged "text" section attributes: * likely to be read-only/executable. */ __flatmap_rx_start = LD_ROUNDDOWN(__text_start, SMALL_PAGE_SIZE); .text : { KEEP(*(.text._start)) __identity_map_init_start = .; __text_data_start = .; *(.identity_map.data) __text_data_end = .; *(.identity_map .identity_map.*) __identity_map_init_end = .; *(.text .text.*) *(.sram.text.glue_7* .gnu.linkonce.t.*) . = ALIGN(8); } __text_end = .; #ifdef CFG_CORE_RODATA_NOEXEC . = ALIGN(SMALL_PAGE_SIZE); #endif __flatmap_rx_size = . - __flatmap_rx_start; __flatmap_ro_start = .; .rodata : ALIGN(8) { __rodata_start = .; *(.gnu.linkonce.r.*) *(.rodata .rodata.*) #ifndef CFG_CORE_ASLR . = ALIGN(8); KEEP(*(SORT(.scattered_array*))); #endif . = ALIGN(8); __rodata_end = .; } .got : { *(.got.plt) *(.got) } .note.gnu.property : { *(.note.gnu.property) } .plt : { *(.plt) } .ctors : ALIGN(8) { __ctor_list = .; KEEP(*(.ctors .ctors.* .init_array .init_array.*)) __ctor_end = .; } .dtors : ALIGN(8) { __dtor_list = .; KEEP(*(.dtors .dtors.* .fini_array .fini_array.*)) __dtor_end = .; } /* Start page aligned read-write memory */ #ifdef CFG_CORE_RWDATA_NOEXEC . = ALIGN(SMALL_PAGE_SIZE); #endif __flatmap_ro_size = . - __flatmap_ro_start; __flatmap_rw_start = .; .data : ALIGN(8) { /* writable data */ __data_start_rom = .; /* in one segment binaries, the rom data address is on top of the ram data address */ __data_start = .; *(.data .data.* .gnu.linkonce.d.*) . = ALIGN(8); /* * To allow the linker relax accesses to global symbols, * those need to be within imm12 (signed 12-bit) offsets * from __global_pointer$. */ PROVIDE(__global_pointer$ = . + 0x800 ); *(.sdata .sdata.* .gnu.linkonce.s.*) } /* uninitialized data */ .bss : { __data_end = .; __bss_start = .; *(.sbss .sbss.*) *(.gnu.linkonce.sb.*) *(.bss .bss.*) *(.gnu.linkonce.b.*) *(COMMON) . = ALIGN(8); __bss_end = .; } .heap1 (NOLOAD) : { /* * We're keeping track of the padding added before the * .nozi section so we can do something useful with * this otherwise wasted memory. */ __heap1_start = .; . += CFG_CORE_HEAP_SIZE; . = ALIGN(4 * 1024); __heap1_end = .; } /* * Uninitialized data that shouldn't be zero initialized at * runtime. */ .nozi (NOLOAD) : { __nozi_start = .; KEEP(*(.nozi .nozi.*)) . = ALIGN(16); __nozi_end = .; __nozi_stack_start = .; KEEP(*(.nozi_stack .nozi_stack.*)) . = ALIGN(8); __nozi_stack_end = .; } #ifdef CFG_CORE_SANITIZE_KADDRESS . = TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8; . = ALIGN(8); .asan_shadow : { __asan_shadow_start = .; . += TEE_RAM_VA_SIZE / 9; __asan_shadow_end = .; __asan_shadow_size = __asan_shadow_end - __asan_shadow_start; } #endif /*CFG_CORE_SANITIZE_KADDRESS*/ __end = .; __init_size = __data_end - TEE_LOAD_ADDR; /* * Guard against moving the location counter backwards in the assignment * below. */ ASSERT(. <= (TEE_RAM_START + TEE_RAM_VA_SIZE), "TEE_RAM_VA_SIZE is too small") . = TEE_RAM_START + TEE_RAM_VA_SIZE; _end_of_ram = .; __flatmap_rw_size = _end_of_ram - __flatmap_rw_start; __get_tee_init_end = .; /* * These regions will not become a normal part of the dumped * binary, instead some are interpreted by the dump script and * converted into suitable format for OP-TEE itself to use. */ .dynamic : { *(.dynamic) } .hash : { *(.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel : { *(.rel.*) } .rela : { *(.rela.*) } #ifndef CFG_CORE_ASLR ASSERT(SIZEOF(.rel) == 0, "Relocation entries not expected") ASSERT(SIZEOF(.rela) == 0, "Relocation entries not expected") #endif /DISCARD/ : { /* Strip unnecessary stuff */ *(.comment .note .eh_frame .interp) /* Strip meta variables */ *(__keep_meta_vars*) } } /* Unpaged read-only memories */ __vcore_unpg_rx_start = __flatmap_rx_start; __vcore_unpg_ro_start = __flatmap_ro_start; #ifdef CFG_CORE_RODATA_NOEXEC __vcore_unpg_rx_size = __flatmap_rx_size; __vcore_unpg_ro_size = __flatmap_ro_size; #else __vcore_unpg_rx_size = __flatmap_rx_size + __flatmap_ro_size; __vcore_unpg_ro_size = 0; #endif __vcore_unpg_rx_end = __vcore_unpg_rx_start + __vcore_unpg_rx_size; __vcore_unpg_ro_end = __vcore_unpg_ro_start + __vcore_unpg_ro_size; /* Unpaged read-write memory */ __vcore_unpg_rw_start = __flatmap_rw_start; __vcore_unpg_rw_size = __flatmap_rw_size; __vcore_unpg_rw_end = __vcore_unpg_rw_start + __vcore_unpg_rw_size; #ifdef CFG_CORE_SANITIZE_KADDRESS __asan_map_start = (__asan_shadow_start / SMALL_PAGE_SIZE) * SMALL_PAGE_SIZE; __asan_map_end = ((__asan_shadow_end - 1) / SMALL_PAGE_SIZE) * SMALL_PAGE_SIZE + SMALL_PAGE_SIZE; __asan_map_size = __asan_map_end - __asan_map_start; #endif /*CFG_CORE_SANITIZE_KADDRESS*/ optee_os-4.3.0/core/arch/riscv/kernel/link.mk000066400000000000000000000111651464416617300211140ustar00rootroot00000000000000link-out-dir = $(out-dir)/core link-script = $(if $(wildcard $(platform-dir)/kern.ld.S), \ $(platform-dir)/kern.ld.S, \ $(arch-dir)/kernel/kern.ld.S) link-script-pp = $(link-out-dir)/kern.ld link-script-dep = $(link-out-dir)/.kern.ld.d link-ldflags-common += $(call ld-option,--no-warn-rwx-segments) link-ldflags = $(LDFLAGS) ifeq ($(CFG_CORE_ASLR),y) link-ldflags += -pie -Bsymbolic -z norelro $(ldflag-apply-dynamic-relocs) endif link-ldflags += -T $(link-script-pp) -Map=$(link-out-dir)/tee.map link-ldflags += --sort-section=alignment link-ldflags += --fatal-warnings link-ldflags += --gc-sections link-ldflags += $(link-ldflags-common) link-ldadd = $(LDADD) link-ldadd += $(ldflags-external) link-ldadd += $(libdeps) link-objs := $(objs) ldargs-tee.elf := $(link-ldflags) $(link-objs) $(link-out-dir)/version.o \ $(link-ldadd) $(libgcccore) link-script-cppflags := \ $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ $(nostdinccore) $(CPPFLAGS) \ $(addprefix -I,$(incdirscore) $(link-out-dir)) \ $(cppflagscore)) ldargs-all_objs := -T $(link-script) --no-check-sections \ $(link-ldflags-common) \ $(link-objs) $(link-ldadd) $(libgcccore) cleanfiles += $(link-out-dir)/all_objs.o $(link-out-dir)/all_objs.o: $(objs) $(libdeps) $(MAKEFILE_LIST) @$(cmd-echo-silent) ' LD $@' $(q)$(LDcore) $(ldargs-all_objs) -o $@ -include $(link-script-dep) link-script-extra-deps += $(conf-file) cleanfiles += $(link-script-pp) $(link-script-dep) $(link-script-pp): $(link-script) $(link-script-extra-deps) @$(cmd-echo-silent) ' CPP $@' @mkdir -p $(dir $@) $(q)$(CPPcore) -P -MT $@ -MD -MF $(link-script-dep) \ $(link-script-cppflags) $< -o $@ define update-buildcount @$(cmd-echo-silent) ' UPD $(1)' $(q)if [ ! -f $(1) ]; then \ mkdir -p $(dir $(1)); \ echo 1 >$(1); \ else \ expr 0`cat $(1)` + 1 >$(1); \ fi endef # filter-out to workaround objdump warning version-o-cflags = $(filter-out -g3,$(core-platform-cflags) \ $(platform-cflags) $(cflagscore)) # SOURCE_DATE_EPOCH defined for reproducible builds ifneq ($(SOURCE_DATE_EPOCH),) date-opts = -d @$(SOURCE_DATE_EPOCH) endif DATE_STR = `LC_ALL=C date -u $(date-opts)` BUILD_COUNT_STR = `cat $(link-out-dir)/.buildcount` CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'` define gen-version-o $(call update-buildcount,$(link-out-dir)/.buildcount) @$(cmd-echo-silent) ' GEN $(link-out-dir)/version.o' $(q)echo -e "const char core_v_str[] =" \ "\"$(TEE_IMPL_VERSION) \"" \ "\"($(CORE_CC_VERSION)) \"" \ "\"#$(BUILD_COUNT_STR) \"" \ "\"$(DATE_STR) \"" \ "\"$(CFG_KERN_LINKER_ARCH)\";\n" \ | $(CCcore) $(version-o-cflags) \ -xc - -c -o $(link-out-dir)/version.o endef $(link-out-dir)/version.o: $(call gen-version-o) -include $(link-out-dir)/.tee.elf.cmd define check-link-objs $(if $(strip $(filter-out $(link-objs), $(old-link-objs)) $(filter-out $(old-link-objs), $(link-objs))), FORCE_LINK := FORCE) endef #$(eval $(call check-link-objs)) all: $(link-out-dir)/tee.elf cleanfiles += $(link-out-dir)/tee.elf $(link-out-dir)/tee.map cleanfiles += $(link-out-dir)/version.o cleanfiles += $(link-out-dir)/.buildcount cleanfiles += $(link-out-dir)/.tee.elf.cmd $(link-out-dir)/tee.elf: $(link-objs) $(libdeps) $(link-script-pp) $(FORCE_LINK) $(call gen-version-o) @echo "old-link-objs := $(link-objs)" >$(link-out-dir)/.tee.elf.cmd @$(cmd-echo-silent) ' LD $@' $(q)$(LDcore) $(ldargs-tee.elf) -o $@ all: $(link-out-dir)/tee.dmp cleanfiles += $(link-out-dir)/tee.dmp $(link-out-dir)/tee.dmp: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' OBJDUMP $@' $(q)$(OBJDUMPcore) -l -x -d $< > $@ all: $(link-out-dir)/tee.bin cleanfiles += $(link-out-dir)/tee.bin $(link-out-dir)/tee.bin: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' GEN $@' $(q)$(OBJCOPYcore) -O binary $< $@ all: $(link-out-dir)/tee.symb_sizes cleanfiles += $(link-out-dir)/tee.symb_sizes $(link-out-dir)/tee.symb_sizes: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' GEN $@' $(q)$(NMcore) --print-size --reverse-sort --size-sort $< > $@ cleanfiles += $(link-out-dir)/tee.mem_usage ifneq ($(filter mem_usage,$(MAKECMDGOALS)),) mem_usage: $(link-out-dir)/tee.mem_usage $(link-out-dir)/tee.mem_usage: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' GEN $@' $(q)$(PYTHON3) ./scripts/mem_usage.py $< > $@ endif cleanfiles += $(link-out-dir)/tee-raw.bin $(link-out-dir)/tee-raw.bin: $(link-out-dir)/tee.elf @$(cmd-echo-silent) ' GEN $@' $(q)$(OBJCOPYcore) -O binary $< $@ cleanfiles += $(link-out-dir)/tee.srec $(link-out-dir)/tee.srec: $(link-out-dir)/tee-raw.bin @$(cmd-echo-silent) ' SREC $@' $(q)$(OBJCOPYcore) -I binary -O srec $(SRECFLAGS) $< $@ optee_os-4.3.0/core/arch/riscv/kernel/sbi.c000066400000000000000000000040771464416617300205530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include struct sbiret { long error; long value; }; #define _sbi_ecall(ext, fid, arg0, arg1, arg2, arg3, arg4, arg5, ...) ({ \ register unsigned long a0 asm("a0") = (unsigned long)arg0; \ register unsigned long a1 asm("a1") = (unsigned long)arg1; \ register unsigned long a2 asm("a2") = (unsigned long)arg2; \ register unsigned long a3 asm("a3") = (unsigned long)arg3; \ register unsigned long a4 asm("a4") = (unsigned long)arg4; \ register unsigned long a5 asm("a5") = (unsigned long)arg5; \ register unsigned long a6 asm("a6") = (unsigned long)fid; \ register unsigned long a7 asm("a7") = (unsigned long)ext; \ asm volatile ("ecall" \ : "+r" (a0), "+r" (a1) \ : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r"(a6), "r"(a7) \ : "memory"); \ (struct sbiret){ .error = a0, .value = a1 }; \ }) #define sbi_ecall(...) _sbi_ecall(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0) /** * sbi_probe_extension() - Check if an SBI extension ID is supported or not. * @extid: The extension ID to be probed. * * Return: 1 or an extension specific nonzero value if yes, 0 otherwise. */ int sbi_probe_extension(int extid) { struct sbiret ret = { }; ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid); if (!ret.error) return ret.value; return 0; } /** * sbi_console_putchar() - Writes given character to the console device. * @ch: The data to be written to the console. */ void sbi_console_putchar(int ch) { sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch); } /** * sbi_dbcn_write_byte() - Write byte to debug console * @ch: Byte to be written * * Return: SBI error code (SBI_SUCCESS = 0 on success) */ int sbi_dbcn_write_byte(unsigned char ch) { struct sbiret ret = { }; ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE, ch); return ret.error; } int sbi_hsm_hart_start(uint32_t hartid, paddr_t start_addr, unsigned long arg) { struct sbiret ret = { }; ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START, hartid, start_addr, arg); return ret.error; } optee_os-4.3.0/core/arch/riscv/kernel/sbi_console.c000066400000000000000000000017641464416617300222750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include #include #include #include #include #include #include #include #include struct sbi_console_data { struct serial_chip chip; }; static struct sbi_console_data console_data __nex_bss; static struct serial_ops sbi_console_ops __nex_bss; static void sbi_console_putc_legacy(struct serial_chip *chip __unused, int ch) { sbi_console_putchar(ch); } static void sbi_console_putc(struct serial_chip *chip __unused, int ch) { sbi_dbcn_write_byte(ch); } static void sbi_console_init(struct sbi_console_data *pd) { if (sbi_probe_extension(SBI_EXT_DBCN)) sbi_console_ops.putc = sbi_console_putc; else sbi_console_ops.putc = sbi_console_putc_legacy; pd->chip.ops = &sbi_console_ops; } void plat_console_init(void) { sbi_console_init(&console_data); register_serial_console(&console_data.chip); } optee_os-4.3.0/core/arch/riscv/kernel/semihosting_rv.S000066400000000000000000000007451464416617300230140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024 Andes Technology Corporation */ #include /* * uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg) * * Refer to RISC-V Semihosting Binary Interface: * https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc */ FUNC __do_semihosting , : , .identity_map .option push .option norvc slli x0, x0, 0x1f ebreak srai x0, x0, 0x7 .option pop ret END_FUNC __do_semihosting optee_os-4.3.0/core/arch/riscv/kernel/spinlock.S000066400000000000000000000014141464416617300215700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include #include /* void __cpu_spin_lock(unsigned int *lock) */ FUNC __cpu_spin_lock , : addi sp, sp, -(RISCV_XLEN_BYTES * 2) STR s0, 0(sp) STR ra, 8(sp) mv s0, a0 1: mv a0, s0 jal __cpu_spin_trylock addiw a0, a0, 0 bnez a0, 1b LDR ra, 8(sp) LDR s0, 0(sp) addi sp, sp, (RISCV_XLEN_BYTES * 2) ret END_FUNC __cpu_spin_lock /* void __cpu_spin_unlock(unsigned int *lock)*/ FUNC __cpu_spin_unlock , : fence rw, w amoswap.w x0, x0, 0(a0) ret END_FUNC __cpu_spin_unlock /* unsigned int __cpu_spin_trylock(unsigned int *lock) */ FUNC __cpu_spin_trylock , : li t0, SPINLOCK_LOCK amoswap.w a0, t0, 0(a0) fence r,rw ret END_FUNC __cpu_spin_trylock optee_os-4.3.0/core/arch/riscv/kernel/sub.mk000066400000000000000000000017471464416617300207550ustar00rootroot00000000000000srcs-y += spinlock.S srcs-y += cache_helpers_rv.S srcs-y += csr_detect.S srcs-y += idle.c srcs-$(CFG_RISCV_TIME_SOURCE_RDTIME) += tee_time_rdtime.c srcs-$(CFG_RISCV_SBI) += sbi.c srcs-$(CFG_RISCV_SBI_CONSOLE) += sbi_console.c srcs-y += boot.c srcs-y += entry.S srcs-y += abort.c srcs-y += thread_rv.S srcs-y += thread_arch.c srcs-y += arch_scall_rv.S srcs-y += arch_scall.c srcs-$(CFG_UNWIND) += unwind_rv.c srcs-$(CFG_SEMIHOSTING) += semihosting_rv.S srcs-y += thread_optee_abi.c srcs-y += thread_optee_abi_rv.S asm-defines-y += asm-defines.c ifeq ($(CFG_SYSCALL_FTRACE),y) # We would not like to profile thread.c file as it provide common APIs # that are needed for ftrace framework to trace syscalls. So profiling # this file could create an incorrect cyclic behaviour. cflags-remove-thread_arch.c-y += -pg # Tracing abort dump files corrupts the stack trace. So exclude them # from profiling. cflags-remove-abort.c-y += -pg ifeq ($(CFG_UNWIND),y) cflags-remove-unwind_rv.c-y += -pg endif endif optee_os-4.3.0/core/arch/riscv/kernel/tee_time_rdtime.c000066400000000000000000000016411464416617300231270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include __noprof uint64_t read_time(void) { uint64_t time = 0; uint32_t hi __maybe_unused = 0; uint32_t lo __maybe_unused = 0; #ifdef CFG_RISCV_M_MODE time = clint_get_mtime(); #endif /*CFG_RISCV_M_MODE*/ #ifdef CFG_RISCV_S_MODE #ifdef RV32 do { hi = read_csr(timeh); lo = read_csr(time); } while (hi != read_csr(timeh)); time = SHIFT_U64(hi, 32) | lo; #else /*RV64*/ time = rdtime(); #endif /*RV32*/ #endif /*CFG_RISCV_S_MODE*/ return time; } TEE_Result tee_time_get_sys_time(TEE_Time *time) { uint64_t tm = read_time(); uint64_t rate = read_cntfrq(); time->seconds = tm / rate; time->millis = (tm % rate) / (rate / TEE_TIME_MILLIS_BASE); return TEE_SUCCESS; } uint32_t tee_time_get_sys_time_protection_level(void) { return 1000; } optee_os-4.3.0/core/arch/riscv/kernel/thread_arch.c000066400000000000000000000313271464416617300222400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP * Copyright (c) 2016-2022, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020-2021, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * This function is called as a guard after each ABI call which is not * supposed to return. */ void __noreturn __panic_at_abi_return(void) { panic(); } /* This function returns current masked exception bits. */ uint32_t __nostackcheck thread_get_exceptions(void) { uint32_t xie = read_csr(CSR_XIE) & THREAD_EXCP_ALL; return xie ^ THREAD_EXCP_ALL; } void __nostackcheck thread_set_exceptions(uint32_t exceptions) { /* Foreign interrupts must not be unmasked while holding a spinlock */ if (!(exceptions & THREAD_EXCP_FOREIGN_INTR)) assert_have_no_spinlock(); /* * In ARM, the bits in DAIF register are used to mask the exceptions. * While in RISC-V, the bits in CSR XIE are used to enable(unmask) * corresponding interrupt sources. To not modify the function of * thread_set_exceptions(), we should "invert" the bits in "exceptions". * The corresponding bits in "exceptions" will be inverted so they will * be cleared when we write the final value into CSR XIE. So that we * can mask those exceptions. */ exceptions &= THREAD_EXCP_ALL; exceptions ^= THREAD_EXCP_ALL; barrier(); write_csr(CSR_XIE, exceptions); barrier(); } uint32_t __nostackcheck thread_mask_exceptions(uint32_t exceptions) { uint32_t state = thread_get_exceptions(); thread_set_exceptions(state | (exceptions & THREAD_EXCP_ALL)); return state; } void __nostackcheck thread_unmask_exceptions(uint32_t state) { thread_set_exceptions(state & THREAD_EXCP_ALL); } static void thread_lazy_save_ns_vfp(void) { static_assert(!IS_ENABLED(CFG_WITH_VFP)); } static void thread_lazy_restore_ns_vfp(void) { static_assert(!IS_ENABLED(CFG_WITH_VFP)); } static void setup_unwind_user_mode(struct thread_scall_regs *regs) { regs->ra = (uintptr_t)thread_unwind_user_mode; regs->status = xstatus_for_xret(true, PRV_S); regs->sp = thread_get_saved_thread_sp(); } static void thread_unhandled_trap(unsigned long cause __unused, struct thread_ctx_regs *regs __unused) { DMSG("Unhandled trap xepc:0x%016lx xcause:0x%016lx xtval:0x%016lx", read_csr(CSR_XEPC), read_csr(CSR_XCAUSE), read_csr(CSR_XTVAL)); panic(); } void thread_scall_handler(struct thread_scall_regs *regs) { struct ts_session *sess = NULL; uint32_t state = 0; /* Enable native interrupts */ state = thread_get_exceptions(); thread_unmask_exceptions(state & ~THREAD_EXCP_NATIVE_INTR); thread_user_save_vfp(); sess = ts_get_current_session(); /* Restore foreign interrupts which are disabled on exception entry */ thread_restore_foreign_intr(); assert(sess && sess->handle_scall); if (!sess->handle_scall(regs)) { setup_unwind_user_mode(regs); thread_exit_user_mode(regs->a0, regs->a1, regs->a2, regs->a3, regs->sp, regs->ra, regs->status); } } static void thread_irq_handler(void) { interrupt_main_handler(); } void thread_interrupt_handler(unsigned long cause, struct thread_ctx_regs *regs) { switch (cause & LONG_MAX) { case IRQ_XTIMER: clear_csr(CSR_XIE, CSR_XIE_TIE); break; case IRQ_XSOFT: thread_unhandled_trap(cause, regs); break; case IRQ_XEXT: thread_irq_handler(); break; default: thread_unhandled_trap(cause, regs); } } unsigned long xstatus_for_xret(uint8_t pie, uint8_t pp) { unsigned long xstatus = read_csr(CSR_XSTATUS); assert(pp == PRV_M || pp == PRV_S || pp == PRV_U); #ifdef RV32 xstatus = set_field_u32(xstatus, CSR_XSTATUS_IE, 0); xstatus = set_field_u32(xstatus, CSR_XSTATUS_PIE, pie); xstatus = set_field_u32(xstatus, CSR_XSTATUS_SPP, pp); #else /* RV64 */ xstatus = set_field_u64(xstatus, CSR_XSTATUS_IE, 0); xstatus = set_field_u64(xstatus, CSR_XSTATUS_PIE, pie); xstatus = set_field_u64(xstatus, CSR_XSTATUS_SPP, pp); #endif return xstatus; } static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7, void *pc) { memset(&thread->regs, 0, sizeof(thread->regs)); thread->regs.epc = (uintptr_t)pc; /* Set up xstatus */ thread->regs.status = xstatus_for_xret(true, PRV_S); /* Enable native interrupt */ thread->regs.ie = THREAD_EXCP_NATIVE_INTR; /* Reinitialize stack pointer */ thread->regs.sp = thread->stack_va_end; /* Set up GP and TP */ thread->regs.gp = read_gp(); thread->regs.tp = read_tp(); /* * Copy arguments into context. This will make the * arguments appear in a0-a7 when thread is started. */ thread->regs.a0 = a0; thread->regs.a1 = a1; thread->regs.a2 = a2; thread->regs.a3 = a3; thread->regs.a4 = a4; thread->regs.a5 = a5; thread->regs.a6 = a6; thread->regs.a7 = a7; } static void __thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6, uint32_t a7, void *pc) { struct thread_core_local *l = thread_get_core_local(); bool found_thread = false; size_t n = 0; assert(l->curr_thread == THREAD_ID_INVALID); thread_lock_global(); for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].state == THREAD_STATE_FREE) { threads[n].state = THREAD_STATE_ACTIVE; found_thread = true; break; } } thread_unlock_global(); if (!found_thread) return; l->curr_thread = n; threads[n].flags = 0; init_regs(threads + n, a0, a1, a2, a3, a4, a5, a6, a7, pc); thread_lazy_save_ns_vfp(); l->flags &= ~THREAD_CLF_TMP; thread_resume(&threads[n].regs); /*NOTREACHED*/ panic(); } void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5) { __thread_alloc_and_run(a0, a1, a2, a3, a4, a5, 0, 0, thread_std_abi_entry); } static void copy_a0_to_a3(struct thread_ctx_regs *regs, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) { regs->a0 = a0; regs->a1 = a1; regs->a2 = a2; regs->a3 = a3; } static bool is_from_user(unsigned long status) { return (status & CSR_XSTATUS_SPP) == 0; } #ifdef CFG_SYSCALL_FTRACE static void __noprof ftrace_suspend(void) { struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); if (s && s->fbuf) s->fbuf->syscall_trace_suspended = true; } static void __noprof ftrace_resume(void) { struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); if (s && s->fbuf) s->fbuf->syscall_trace_suspended = false; } #else static void __maybe_unused __noprof ftrace_suspend(void) { } static void __noprof ftrace_resume(void) { } #endif static bool is_user_mode(struct thread_ctx_regs *regs) { return is_from_user((uint32_t)regs->status); } vaddr_t thread_get_saved_thread_sp(void) { struct thread_core_local *l = thread_get_core_local(); int ct = l->curr_thread; assert(ct != THREAD_ID_INVALID); return threads[ct].kern_sp; } void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) { size_t n = thread_id; struct thread_core_local *l = thread_get_core_local(); bool found_thread = false; assert(l->curr_thread == THREAD_ID_INVALID); thread_lock_global(); if (n < CFG_NUM_THREADS && threads[n].state == THREAD_STATE_SUSPENDED) { threads[n].state = THREAD_STATE_ACTIVE; found_thread = true; } thread_unlock_global(); if (!found_thread) return; l->curr_thread = n; if (threads[n].have_user_map) { core_mmu_set_user_map(&threads[n].user_map); if (threads[n].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) tee_ta_ftrace_update_times_resume(); } if (is_user_mode(&threads[n].regs)) tee_ta_update_session_utime_resume(); /* * We may resume thread at another hart, so we need to re-assign value * of tp to be current hart's thread_core_local. */ if (!is_user_mode(&threads[n].regs)) threads[n].regs.tp = read_tp(); /* * Return from RPC to request service of a foreign interrupt must not * get parameters from non-secure world. */ if (threads[n].flags & THREAD_FLAGS_COPY_ARGS_ON_RETURN) { copy_a0_to_a3(&threads[n].regs, a0, a1, a2, a3); threads[n].flags &= ~THREAD_FLAGS_COPY_ARGS_ON_RETURN; } thread_lazy_save_ns_vfp(); if (threads[n].have_user_map) ftrace_resume(); l->flags &= ~THREAD_CLF_TMP; thread_resume(&threads[n].regs); /*NOTREACHED*/ panic(); } void thread_state_free(void) { struct thread_core_local *l = thread_get_core_local(); int ct = l->curr_thread; assert(ct != THREAD_ID_INVALID); thread_lazy_restore_ns_vfp(); thread_lock_global(); assert(threads[ct].state == THREAD_STATE_ACTIVE); threads[ct].state = THREAD_STATE_FREE; threads[ct].flags = 0; l->curr_thread = THREAD_ID_INVALID; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); thread_unlock_global(); } int thread_state_suspend(uint32_t flags, unsigned long status, vaddr_t pc) { struct thread_core_local *l = thread_get_core_local(); int ct = l->curr_thread; assert(ct != THREAD_ID_INVALID); if (core_mmu_user_mapping_is_active()) ftrace_suspend(); thread_check_canaries(); if (is_from_user(status)) { thread_user_save_vfp(); tee_ta_update_session_utime_suspend(); tee_ta_gprof_sample_pc(pc); } thread_lazy_restore_ns_vfp(); thread_lock_global(); assert(threads[ct].state == THREAD_STATE_ACTIVE); threads[ct].flags |= flags; threads[ct].regs.status = status; threads[ct].regs.epc = pc; threads[ct].state = THREAD_STATE_SUSPENDED; threads[ct].have_user_map = core_mmu_user_mapping_is_active(); if (threads[ct].have_user_map) { if (threads[ct].flags & THREAD_FLAGS_EXIT_ON_FOREIGN_INTR) tee_ta_ftrace_update_times_suspend(); core_mmu_get_user_map(&threads[ct].user_map); core_mmu_set_user_map(NULL); } l->curr_thread = THREAD_ID_INVALID; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); thread_unlock_global(); return ct; } bool thread_init_stack(uint32_t thread_id, vaddr_t sp) { if (thread_id >= CFG_NUM_THREADS) return false; threads[thread_id].stack_va_end = sp; return true; } static void init_user_kcode(void) { } void thread_init_primary(void) { /* Initialize canaries around the stacks */ thread_init_canaries(); init_user_kcode(); } static vaddr_t get_trap_vect(void) { return (vaddr_t)thread_trap_vect; } void thread_init_tvec(void) { unsigned long tvec = (unsigned long)get_trap_vect(); write_csr(CSR_XTVEC, tvec); assert(read_csr(CSR_XTVEC) == tvec); } void thread_init_per_cpu(void) { thread_init_tvec(); /* * We may receive traps from now, therefore, zeroize xSCRATCH such * that thread_trap_vect() can distinguish between user traps * and kernel traps. */ write_csr(CSR_XSCRATCH, 0); #ifndef CFG_PAN /* * Allow access to user pages. When CFG_PAN is enabled, the SUM bit will * be set and clear at runtime when necessary. */ set_csr(CSR_XSTATUS, CSR_XSTATUS_SUM); #endif } static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, unsigned long status, unsigned long ie, struct thread_pauth_keys *keys __unused) { *regs = (struct thread_ctx_regs){ .a0 = a0, .a1 = a1, .a2 = a2, .a3 = a3, .s0 = 0, .sp = user_sp, .ra = entry_func, .status = status, .ie = ie, }; } uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, bool is_32bit __unused, uint32_t *exit_status0, uint32_t *exit_status1) { unsigned long status = 0; unsigned long ie = 0; uint32_t exceptions = 0; uint32_t rc = 0; struct thread_ctx_regs *regs = NULL; tee_ta_update_session_utime_resume(); /* Read current interrupt masks */ ie = read_csr(CSR_XIE); /* * Mask all exceptions, the CSR_XSTATUS.IE will be set from * setup_unwind_user_mode() after exiting. */ exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); regs = thread_get_ctx_regs(); status = xstatus_for_xret(true, PRV_U); set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, status, ie, NULL); rc = __thread_enter_user_mode(regs, exit_status0, exit_status1); thread_unmask_exceptions(exceptions); return rc; } void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) { thread_rpc_xstatus(rv, xstatus_for_xret(false, PRV_S)); } optee_os-4.3.0/core/arch/riscv/kernel/thread_optee_abi.c000066400000000000000000000430651464416617300232540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2021, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static bool thread_prealloc_rpc_cache; static unsigned int thread_rpc_pnum; static_assert(NOTIF_VALUE_DO_BOTTOM_HALF == OPTEE_ABI_ASYNC_NOTIF_VALUE_DO_BOTTOM_HALF); void thread_handle_fast_abi(struct thread_abi_args *args) { thread_check_canaries(); if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(args->a7)) { args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; goto out; } tee_entry_fast(args); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); out: /* Fast handlers must not unmask any exceptions */ assert(thread_get_exceptions() == THREAD_EXCP_ALL); } uint32_t thread_handle_std_abi(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, uint32_t a6 __unused, uint32_t a7 __maybe_unused) { uint32_t rv = OPTEE_ABI_RETURN_OK; thread_check_canaries(); if (IS_ENABLED(CFG_NS_VIRTUALIZATION) && virt_set_guest(a7)) return OPTEE_ABI_RETURN_ENOTAVAIL; /* * thread_resume_from_rpc() and thread_alloc_and_run() only return * on error. Successful return is done via thread_exit() or * thread_rpc(). */ if (a0 == OPTEE_ABI_CALL_RETURN_FROM_RPC) { thread_resume_from_rpc(a3, a1, a2, a4, a5); rv = OPTEE_ABI_RETURN_ERESUME; } else { thread_alloc_and_run(a0, a1, a2, a3, 0, 0); rv = OPTEE_ABI_RETURN_ETHREAD_LIMIT; } if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_unset_guest(); return rv; } /** * Free physical memory previously allocated with thread_rpc_alloc_arg() * * @cookie: cookie received when allocating the buffer */ static void thread_rpc_free_arg(uint64_t cookie) { if (cookie) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_ABI_RETURN_RPC_FREE }; reg_pair_from_64(cookie, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); } } static uint32_t get_msg_arg(struct mobj *mobj, size_t offset, size_t *num_params, struct optee_msg_arg **arg, struct optee_msg_arg **rpc_arg) { void *p = NULL; size_t sz = 0; if (!mobj) return OPTEE_ABI_RETURN_EBADADDR; p = mobj_get_va(mobj, offset, sizeof(struct optee_msg_arg)); if (!p || !IS_ALIGNED_WITH_TYPE(p, struct optee_msg_arg)) return OPTEE_ABI_RETURN_EBADADDR; *arg = p; *num_params = READ_ONCE((*arg)->num_params); if (*num_params > OPTEE_MSG_MAX_NUM_PARAMS) return OPTEE_ABI_RETURN_EBADADDR; sz = OPTEE_MSG_GET_ARG_SIZE(*num_params); if (!mobj_get_va(mobj, offset, sz)) return OPTEE_ABI_RETURN_EBADADDR; if (rpc_arg) { size_t rpc_sz = 0; rpc_sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); p = mobj_get_va(mobj, offset + sz, rpc_sz); if (!p) return OPTEE_ABI_RETURN_EBADADDR; *rpc_arg = p; } return OPTEE_ABI_RETURN_OK; } static void clear_prealloc_rpc_cache(struct thread_ctx *thr) { thread_rpc_free_arg(mobj_get_cookie(thr->rpc_mobj)); mobj_put(thr->rpc_mobj); thr->rpc_arg = NULL; thr->rpc_mobj = NULL; } static uint32_t call_entry_std(struct optee_msg_arg *arg, size_t num_params, struct optee_msg_arg *rpc_arg) { struct thread_ctx *thr = threads + thread_get_id(); uint32_t rv = 0; if (rpc_arg) { /* * In case the prealloc RPC arg cache is enabled, clear the * cached object for this thread. * * Normally it doesn't make sense to have the prealloc RPC * arg cache enabled together with a supplied RPC arg * struct. But if it is we must use the supplied struct and * at the same time make sure to not break anything. */ if (IS_ENABLED(CFG_PREALLOC_RPC_CACHE) && thread_prealloc_rpc_cache) clear_prealloc_rpc_cache(thr); thr->rpc_arg = rpc_arg; } if (tee_entry_std(arg, num_params)) rv = OPTEE_ABI_RETURN_EBADCMD; else rv = OPTEE_ABI_RETURN_OK; thread_rpc_shm_cache_clear(&thr->shm_cache); if (rpc_arg) thr->rpc_arg = NULL; if (rv == OPTEE_ABI_RETURN_OK && !(IS_ENABLED(CFG_PREALLOC_RPC_CACHE) && thread_prealloc_rpc_cache)) clear_prealloc_rpc_cache(thr); return rv; } static uint32_t std_entry_with_parg(paddr_t parg, bool with_rpc_arg) { size_t sz = sizeof(struct optee_msg_arg); struct optee_msg_arg *rpc_arg = NULL; struct optee_msg_arg *arg = NULL; struct mobj *mobj = NULL; size_t num_params = 0; uint32_t rv = 0; /* Check if this region is in static shared space */ if (core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sz)) { if (!IS_ALIGNED_WITH_TYPE(parg, struct optee_msg_arg)) goto bad_addr; arg = phys_to_virt(parg, MEM_AREA_NSEC_SHM, sizeof(struct optee_msg_arg)); if (!arg) goto bad_addr; num_params = READ_ONCE(arg->num_params); if (num_params > OPTEE_MSG_MAX_NUM_PARAMS) return OPTEE_ABI_RETURN_EBADADDR; sz = OPTEE_MSG_GET_ARG_SIZE(num_params); if (with_rpc_arg) { rpc_arg = (void *)((uint8_t *)arg + sz); sz += OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); } if (!core_pbuf_is(CORE_MEM_NSEC_SHM, parg, sz)) goto bad_addr; return call_entry_std(arg, num_params, rpc_arg); } if (parg & SMALL_PAGE_MASK) goto bad_addr; /* * mobj_mapped_shm_alloc checks if parg resides in nonsec * ddr. */ mobj = mobj_mapped_shm_alloc(&parg, 1, 0, 0); if (!mobj) goto bad_addr; if (with_rpc_arg) rv = get_msg_arg(mobj, 0, &num_params, &arg, &rpc_arg); else rv = get_msg_arg(mobj, 0, &num_params, &arg, NULL); if (!rv) rv = call_entry_std(arg, num_params, rpc_arg); mobj_put(mobj); return rv; bad_addr: EMSG("Bad arg address 0x%"PRIxPA, parg); return OPTEE_ABI_RETURN_EBADADDR; } static uint32_t std_entry_with_regd_arg(uint64_t cookie, size_t offset) { struct optee_msg_arg *rpc_arg = NULL; struct optee_msg_arg *arg = NULL; size_t num_params = 0; struct mobj *mobj = NULL; uint32_t rv = 0; mobj = mobj_reg_shm_get_by_cookie(cookie); if (!mobj) { EMSG("Bad arg cookie 0x%"PRIx64, cookie); return OPTEE_ABI_RETURN_EBADADDR; } if (mobj_inc_map(mobj)) { rv = OPTEE_ABI_RETURN_ENOMEM; goto out; } rv = get_msg_arg(mobj, offset, &num_params, &arg, &rpc_arg); if (!rv) rv = call_entry_std(arg, num_params, rpc_arg); mobj_dec_map(mobj); out: mobj_put(mobj); return rv; } static uint32_t std_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3 __unused) { const bool with_rpc_arg = true; switch (a0) { case OPTEE_ABI_CALL_WITH_ARG: return std_entry_with_parg(reg_pair_to_64(a1, a2), !with_rpc_arg); case OPTEE_ABI_CALL_WITH_RPC_ARG: return std_entry_with_parg(reg_pair_to_64(a1, a2), with_rpc_arg); case OPTEE_ABI_CALL_WITH_REGD_ARG: return std_entry_with_regd_arg(reg_pair_to_64(a1, a2), a3); default: EMSG("Unknown ABI 0x%"PRIx32, a0); return OPTEE_ABI_RETURN_EBADCMD; } } /* * Helper routine for the assembly function thread_std_abi_entry() * * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ uint32_t __weak __thread_std_abi_entry(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4 __unused, uint32_t a5 __unused) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_on_stdcall(); return std_abi_entry(a0, a1, a2, a3); } bool thread_disable_prealloc_rpc_cache(uint64_t *cookie) { bool rv = false; size_t n = 0; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); thread_lock_global(); for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].state != THREAD_STATE_FREE) { rv = false; goto out; } } rv = true; if (IS_ENABLED(CFG_PREALLOC_RPC_CACHE)) { for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].rpc_arg) { *cookie = mobj_get_cookie(threads[n].rpc_mobj); mobj_put(threads[n].rpc_mobj); threads[n].rpc_arg = NULL; threads[n].rpc_mobj = NULL; goto out; } } } *cookie = 0; thread_prealloc_rpc_cache = false; out: thread_unlock_global(); thread_unmask_exceptions(exceptions); return rv; } bool thread_enable_prealloc_rpc_cache(void) { bool rv = false; size_t n = 0; uint32_t exceptions = 0; if (!IS_ENABLED(CFG_PREALLOC_RPC_CACHE)) return true; exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); thread_lock_global(); for (n = 0; n < CFG_NUM_THREADS; n++) { if (threads[n].state != THREAD_STATE_FREE) { rv = false; goto out; } } rv = true; thread_prealloc_rpc_cache = true; out: thread_unlock_global(); thread_unmask_exceptions(exceptions); return rv; } static struct mobj *rpc_shm_mobj_alloc(paddr_t pa, size_t sz, uint64_t cookie) { /* Check if this region is in static shared space */ if (core_pbuf_is(CORE_MEM_NSEC_SHM, pa, sz)) return mobj_shm_alloc(pa, sz, cookie); if (IS_ENABLED(CFG_CORE_DYN_SHM) && !(pa & SMALL_PAGE_MASK) && sz <= SMALL_PAGE_SIZE) return mobj_mapped_shm_alloc(&pa, 1, 0, cookie); return NULL; } /** * Allocates data for struct optee_msg_arg. * * @size: size in bytes of struct optee_msg_arg * * @returns mobj that describes allocated buffer or NULL on error */ static struct mobj *thread_rpc_alloc_arg(size_t size) { paddr_t pa; uint64_t co; uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_ABI_RETURN_RPC_ALLOC, size }; struct mobj *mobj = NULL; thread_rpc(rpc_args); /* Registers 1 and 2 passed from normal world */ pa = reg_pair_to_64(rpc_args[0], rpc_args[1]); /* Registers 4 and 5 passed from normal world */ co = reg_pair_to_64(rpc_args[2], rpc_args[3]); if (!IS_ALIGNED_WITH_TYPE(pa, struct optee_msg_arg)) goto err; mobj = rpc_shm_mobj_alloc(pa, size, co); if (!mobj) goto err; return mobj; err: thread_rpc_free_arg(co); mobj_put(mobj); return NULL; } static bool set_rmem(struct optee_msg_param *param, struct thread_param *tpm) { param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; param->u.rmem.offs = tpm->u.memref.offs; param->u.rmem.size = tpm->u.memref.size; if (tpm->u.memref.mobj) { param->u.rmem.shm_ref = mobj_get_cookie(tpm->u.memref.mobj); if (!param->u.rmem.shm_ref) return false; } else { param->u.rmem.shm_ref = 0; } return true; } static bool set_tmem(struct optee_msg_param *param, struct thread_param *tpm) { paddr_t pa = 0; uint64_t shm_ref = 0; struct mobj *mobj = tpm->u.memref.mobj; param->attr = tpm->attr - THREAD_PARAM_ATTR_MEMREF_IN + OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; if (mobj) { shm_ref = mobj_get_cookie(mobj); if (!shm_ref) return false; if (mobj_get_pa(mobj, tpm->u.memref.offs, 0, &pa)) return false; } param->u.tmem.size = tpm->u.memref.size; param->u.tmem.buf_ptr = pa; param->u.tmem.shm_ref = shm_ref; return true; } static uint32_t get_rpc_arg(uint32_t cmd, size_t num_params, struct thread_param *params, void **arg_ret, uint64_t *carg_ret) { struct thread_ctx *thr = threads + thread_get_id(); struct optee_msg_arg *arg = thr->rpc_arg; size_t sz = OPTEE_MSG_GET_ARG_SIZE(THREAD_RPC_MAX_NUM_PARAMS); if (num_params > THREAD_RPC_MAX_NUM_PARAMS) return TEE_ERROR_BAD_PARAMETERS; if (!arg) { struct mobj *mobj = thread_rpc_alloc_arg(sz); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; arg = mobj_get_va(mobj, 0, sz); if (!arg) { thread_rpc_free_arg(mobj_get_cookie(mobj)); return TEE_ERROR_OUT_OF_MEMORY; } thr->rpc_arg = arg; thr->rpc_mobj = mobj; } memset(arg, 0, OPTEE_MSG_GET_ARG_SIZE(num_params)); arg->cmd = cmd; arg->num_params = num_params; arg->ret = TEE_ERROR_GENERIC; /* in case value isn't updated */ for (size_t n = 0; n < num_params; n++) { switch (params[n].attr) { case THREAD_PARAM_ATTR_NONE: arg->params[n].attr = OPTEE_MSG_ATTR_TYPE_NONE; break; case THREAD_PARAM_ATTR_VALUE_IN: case THREAD_PARAM_ATTR_VALUE_OUT: case THREAD_PARAM_ATTR_VALUE_INOUT: arg->params[n].attr = params[n].attr - THREAD_PARAM_ATTR_VALUE_IN + OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; arg->params[n].u.value.a = params[n].u.value.a; arg->params[n].u.value.b = params[n].u.value.b; arg->params[n].u.value.c = params[n].u.value.c; break; case THREAD_PARAM_ATTR_MEMREF_IN: case THREAD_PARAM_ATTR_MEMREF_OUT: case THREAD_PARAM_ATTR_MEMREF_INOUT: if (!params[n].u.memref.mobj || mobj_matches(params[n].u.memref.mobj, CORE_MEM_NSEC_SHM)) { if (!set_tmem(arg->params + n, params + n)) return TEE_ERROR_BAD_PARAMETERS; } else if (mobj_matches(params[n].u.memref.mobj, CORE_MEM_REG_SHM)) { if (!set_rmem(arg->params + n, params + n)) return TEE_ERROR_BAD_PARAMETERS; } else { return TEE_ERROR_BAD_PARAMETERS; } break; default: return TEE_ERROR_BAD_PARAMETERS; } } *arg_ret = arg; *carg_ret = mobj_get_cookie(thr->rpc_mobj); return TEE_SUCCESS; } static uint32_t get_rpc_arg_res(struct optee_msg_arg *arg, size_t num_params, struct thread_param *params) { for (size_t n = 0; n < num_params; n++) { switch (params[n].attr) { case THREAD_PARAM_ATTR_VALUE_OUT: case THREAD_PARAM_ATTR_VALUE_INOUT: params[n].u.value.a = arg->params[n].u.value.a; params[n].u.value.b = arg->params[n].u.value.b; params[n].u.value.c = arg->params[n].u.value.c; break; case THREAD_PARAM_ATTR_MEMREF_OUT: case THREAD_PARAM_ATTR_MEMREF_INOUT: /* * rmem.size and tmem.size is the same type and * location. */ params[n].u.memref.size = arg->params[n].u.rmem.size; break; default: break; } } return arg->ret; } uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, struct thread_param *params) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_ABI_RETURN_RPC_CMD }; void *arg = NULL; uint64_t carg = 0; uint32_t ret = 0; /* The source CRYPTO_RNG_SRC_JITTER_RPC is safe to use here */ plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_RPC, &thread_rpc_pnum); ret = get_rpc_arg(cmd, num_params, params, &arg, &carg); if (ret) return ret; reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); return get_rpc_arg_res(arg, num_params, params); } /** * Free physical memory previously allocated with thread_rpc_alloc() * * @cookie: cookie received when allocating the buffer * @bt: must be the same as supplied when allocating * @mobj: mobj that describes allocated buffer * * This function also frees corresponding mobj. */ static void thread_rpc_free(unsigned int bt, uint64_t cookie, struct mobj *mobj) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_ABI_RETURN_RPC_CMD }; void *arg = NULL; uint64_t carg = 0; struct thread_param param = THREAD_PARAM_VALUE(IN, bt, cookie, 0); uint32_t ret = get_rpc_arg(OPTEE_RPC_CMD_SHM_FREE, 1, ¶m, &arg, &carg); mobj_put(mobj); if (!ret) { reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); } } static struct mobj *get_rpc_alloc_res(struct optee_msg_arg *arg, unsigned int bt, size_t size) { struct mobj *mobj = NULL; uint64_t cookie = 0; size_t sz = 0; paddr_t p = 0; if (arg->ret || arg->num_params != 1) goto err; if (arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT && arg->params[0].attr != (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG)) goto err; p = arg->params[0].u.tmem.buf_ptr; sz = READ_ONCE(arg->params[0].u.tmem.size); cookie = arg->params[0].u.tmem.shm_ref; if (sz < size) goto err; if (arg->params[0].attr == OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT) mobj = rpc_shm_mobj_alloc(p, sz, cookie); else mobj = msg_param_mobj_from_noncontig(p, sz, cookie, true); if (!mobj) { thread_rpc_free(bt, cookie, mobj); goto err; } assert(mobj_is_nonsec(mobj)); return mobj; err: EMSG("RPC allocation failed. Non-secure world result: ret=%#" PRIx32" ret_origin=%#"PRIx32, arg->ret, arg->ret_origin); return NULL; } /** * Allocates shared memory buffer via RPC * * @size: size in bytes of shared memory buffer * @align: required alignment of buffer * @bt: buffer type OPTEE_RPC_SHM_TYPE_* * * Returns a pointer to MOBJ for the memory on success, or NULL on failure. */ static struct mobj *thread_rpc_alloc(size_t size, size_t align, unsigned int bt) { uint32_t rpc_args[THREAD_RPC_NUM_ARGS] = { OPTEE_ABI_RETURN_RPC_CMD }; void *arg = NULL; uint64_t carg = 0; struct thread_param param = THREAD_PARAM_VALUE(IN, bt, size, align); uint32_t ret = get_rpc_arg(OPTEE_RPC_CMD_SHM_ALLOC, 1, ¶m, &arg, &carg); if (ret) return NULL; reg_pair_from_64(carg, rpc_args + 1, rpc_args + 2); thread_rpc(rpc_args); return get_rpc_alloc_res(arg, bt, size); } struct mobj *thread_rpc_alloc_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_APPL); } struct mobj *thread_rpc_alloc_kernel_payload(size_t size) { /* * Error out early since kernel private dynamic shared memory * allocations don't currently use the `OPTEE_MSG_ATTR_NONCONTIG` bit * and therefore cannot be larger than a page. */ if (IS_ENABLED(CFG_CORE_DYN_SHM) && size > SMALL_PAGE_SIZE) return NULL; return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_KERNEL); } void thread_rpc_free_kernel_payload(struct mobj *mobj) { thread_rpc_free(OPTEE_RPC_SHM_TYPE_KERNEL, mobj_get_cookie(mobj), mobj); } void thread_rpc_free_payload(struct mobj *mobj) { thread_rpc_free(OPTEE_RPC_SHM_TYPE_APPL, mobj_get_cookie(mobj), mobj); } struct mobj *thread_rpc_alloc_global_payload(size_t size) { return thread_rpc_alloc(size, 8, OPTEE_RPC_SHM_TYPE_GLOBAL); } void thread_rpc_free_global_payload(struct mobj *mobj) { thread_rpc_free(OPTEE_RPC_SHM_TYPE_GLOBAL, mobj_get_cookie(mobj), mobj); } optee_os-4.3.0/core/arch/riscv/kernel/thread_optee_abi_rv.S000066400000000000000000000126241464416617300237400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP * Copyright (c) 2023 Andes Technology Corporation */ #include #include #include #include #include #include #include #include #include #include #include /* * Implement based on the transport method used to communicate between * untrusted domain and trusted domain. It could be an SBI/ECALL-based to * a security monitor running in M-Mode and panic or messaging-based across * domains where we return to a messaging callback which parses and handles * messages. * * void thread_return_to_udomain(unsigned long arg0, unsigned long arg1, * unsigned long arg2, unsigned long arg3, * unsigned long arg4, unsigned long arg5); */ FUNC thread_return_to_udomain , : /* Caller should provide arguments in a0~a5 */ #if defined(CFG_RISCV_WITH_M_MODE_SM) li a7, SBI_EXT_TEE /* extension ID */ li a6, 0 /* function ID (unused) */ ecall #else /* Other protocol */ #endif /* ABI to REE should not return */ panic_at_abi_return END_FUNC thread_return_to_udomain FUNC thread_std_abi_entry , : jal __thread_std_abi_entry /* Save return value */ mv s0, a0 /* Disable all interrupts */ csrc CSR_XSTATUS, CSR_XSTATUS_IE /* Switch to temporary stack */ jal thread_get_tmp_sp mv sp, a0 /* * We are returning from thread_alloc_and_run() * set thread state as free */ jal thread_state_free /* Restore __thread_std_abi_entry() return value */ mv a1, s0 li a2, 0 li a3, 0 li a4, 0 li a0, TEEABI_OPTEED_RETURN_CALL_DONE /* Return to untrusted domain */ jal thread_return_to_udomain END_FUNC thread_std_abi_entry /* * void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS], * unsigned long status); */ FUNC thread_rpc_xstatus , : /* Use stack for temporary storage */ addi sp, sp, -REGOFF(8) /* Read xSTATUS */ csrr a2, CSR_XSTATUS /* Mask all maskable exceptions before switching to temporary stack */ csrw CSR_XIE, x0 /* Save return address xSTATUS and pointer to rv */ STR a0, REGOFF(0)(sp) STR a1, REGOFF(1)(sp) STR s0, REGOFF(2)(sp) STR ra, REGOFF(3)(sp) STR a2, REGOFF(4)(sp) #ifdef CFG_UNWIND addi s0, sp, REGOFF(8) #endif /* Save thread state */ jal thread_get_ctx_regs LDR ra, REGOFF(3)(sp) /* Save ra, sp, gp, tp, and s0~s11 */ store_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP store_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 store_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 /* Get to tmp stack */ jal thread_get_tmp_sp /* Get pointer to rv */ LDR s1, REGOFF(0)(sp) /* xSTATUS to restore */ LDR a1, REGOFF(1)(sp) /* Switch to tmp stack */ mv sp, a0 /* Early load rv[] into s2-s4 */ lw s2, 0(s1) lw s3, 4(s1) lw s4, 8(s1) li a0, THREAD_FLAGS_COPY_ARGS_ON_RETURN la a2, .thread_rpc_return jal thread_state_suspend mv a4, a0 /* thread index */ mv a1, s2 /* rv[0] */ mv a2, s3 /* rv[1] */ mv a3, s4 /* rv[2] */ li a0, TEEABI_OPTEED_RETURN_CALL_DONE /* Return to untrusted domain */ jal thread_return_to_udomain .thread_rpc_return: /* * Jumps here from thread_resume() above when RPC has returned. * At this point has the stack pointer been restored to the value * stored in THREAD_CTX above. */ /* Get pointer to rv[] */ LDR a4, REGOFF(0)(sp) /* Store a0-a3 into rv[] */ sw a0, 0(a4) sw a1, 4(a4) sw a2, 8(a4) sw a3, 12(a4) /* Pop saved XSTATUS from stack */ LDR s0, REGOFF(4)(sp) csrw CSR_XSTATUS, s0 /* Pop s0 from stack */ LDR s0, REGOFF(2)(sp) addi sp, sp, REGOFF(8) ret END_FUNC thread_rpc_xstatus DECLARE_KEEP_PAGER thread_rpc_xstatus LOCAL_FUNC vector_std_abi_entry, : , .identity_map jal thread_handle_std_abi /* * Normally thread_handle_std_abi() should return via * thread_exit(), thread_rpc(), but if thread_handle_std_abi() * hasn't switched stack (error detected) it will do a normal "C" * return. */ /* Restore thread_handle_std_abi() return value */ mv a1, a0 li a2, 0 li a3, 0 li a4, 0 li a0, TEEABI_OPTEED_RETURN_CALL_DONE /* Return to untrusted domain */ j thread_return_to_udomain END_FUNC vector_std_abi_entry LOCAL_FUNC vector_fast_abi_entry , : , .identity_map addi sp, sp, -THREAD_ABI_ARGS_SIZE store_xregs sp, THREAD_ABI_ARGS_A0, REG_A0, REG_A7 mv a0, sp jal thread_handle_fast_abi load_xregs sp, THREAD_ABI_ARGS_A0, REG_A1, REG_A7 addi sp, sp, THREAD_ABI_ARGS_SIZE li a0, TEEABI_OPTEED_RETURN_CALL_DONE /* Return to untrusted domain */ j thread_return_to_udomain END_FUNC vector_fast_abi_entry LOCAL_FUNC vector_fiq_entry , : , .identity_map /* Secure Monitor received a FIQ and passed control to us. */ jal interrupt_main_handler li a0, TEEABI_OPTEED_RETURN_FIQ_DONE /* Return to untrusted domain */ j thread_return_to_udomain END_FUNC vector_fiq_entry /* * Vector table supplied to M-mode secure monitor (e.g., openSBI) at * initialization. * * Note that M-mode secure monitor depends on the layout of this vector table, * any change in layout has to be synced with M-mode secure monitor. */ FUNC thread_vector_table , : , .identity_map, , nobti .option push .option norvc j vector_std_abi_entry j vector_fast_abi_entry j . j . j . j . j vector_fiq_entry j . j . .option pop END_FUNC thread_vector_table DECLARE_KEEP_PAGER thread_vector_table optee_os-4.3.0/core/arch/riscv/kernel/thread_rv.S000066400000000000000000000452301464416617300217300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP * Copyright 2024 Andes Technology Corporation */ #include #include #include #include #include #include #include #include .macro get_thread_ctx res, tmp0 lw \tmp0, THREAD_CORE_LOCAL_CURR_THREAD(tp) la \res, threads 1: beqz \tmp0, 2f addi \res, \res, THREAD_CTX_SIZE addi \tmp0, \tmp0, -1 bnez \tmp0, 1b 2: .endm .macro b_if_prev_priv_is_u reg, label andi \reg, \reg, CSR_XSTATUS_SPP beqz \reg, \label .endm /* size_t __get_core_pos(void); */ FUNC __get_core_pos , : , .identity_map lw a0, THREAD_CORE_LOCAL_HART_ID(tp) ret END_FUNC __get_core_pos FUNC thread_trap_vect , : csrrw tp, CSR_XSCRATCH, tp bnez tp, 0f /* Read tp back */ csrrw tp, CSR_XSCRATCH, tp j trap_from_kernel 0: /* Now tp is thread_core_local */ j trap_from_user thread_trap_vect_end: END_FUNC thread_trap_vect LOCAL_FUNC trap_from_kernel, : /* Save sp, a0, a1 into temporary spaces of thread_core_local */ store_xregs tp, THREAD_CORE_LOCAL_X0, REG_SP store_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 csrr a0, CSR_XCAUSE /* MSB of cause differentiates between interrupts and exceptions */ bge a0, zero, exception_from_kernel interrupt_from_kernel: /* Get thread context as sp */ get_thread_ctx sp, a0 /* Load and save kernel sp */ load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0 store_xregs sp, THREAD_CTX_REG_SP, REG_A0 /* Restore user a0, a1 which can be saved later */ load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 /* Save all other GPRs */ store_xregs sp, THREAD_CTX_REG_RA, REG_RA store_xregs sp, THREAD_CTX_REG_GP, REG_GP store_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2 store_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1 store_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7 store_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11 store_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6 /* Save XIE */ csrr t0, CSR_XIE store_xregs sp, THREAD_CTX_REG_IE, REG_T0 /* Mask all interrupts */ csrw CSR_XIE, x0 /* Save XSTATUS */ csrr t0, CSR_XSTATUS store_xregs sp, THREAD_CTX_REG_STATUS, REG_T0 /* Save XEPC */ csrr t0, CSR_XEPC store_xregs sp, THREAD_CTX_REG_EPC, REG_T0 /* * a0 = cause * a1 = sp * Call thread_interrupt_handler(cause, regs) */ csrr a0, CSR_XCAUSE mv a1, sp /* Load tmp_stack_va_end as current sp. */ load_xregs tp, THREAD_CORE_LOCAL_TMP_STACK_VA_END, REG_SP call thread_interrupt_handler /* Get thread context as sp */ get_thread_ctx sp, t0 /* Restore XEPC */ load_xregs sp, THREAD_CTX_REG_EPC, REG_T0 csrw CSR_XEPC, t0 /* Restore XIE */ load_xregs sp, THREAD_CTX_REG_IE, REG_T0 csrw CSR_XIE, t0 /* Restore XSTATUS */ load_xregs sp, THREAD_CTX_REG_STATUS, REG_T0 csrw CSR_XSTATUS, t0 /* Set scratch as thread_core_local */ csrw CSR_XSCRATCH, tp /* Restore all GPRs */ load_xregs sp, THREAD_CTX_REG_RA, REG_RA load_xregs sp, THREAD_CTX_REG_GP, REG_GP load_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2 load_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1 load_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7 load_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11 load_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6 load_xregs sp, THREAD_CTX_REG_SP, REG_SP XRET exception_from_kernel: /* * Update core local flags. * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT; */ lw a0, THREAD_CORE_LOCAL_FLAGS(tp) slli a0, a0, THREAD_CLF_SAVED_SHIFT ori a0, a0, THREAD_CLF_ABORT li a1, (THREAD_CLF_ABORT << THREAD_CLF_SAVED_SHIFT) and a1, a0, a1 bnez a1, sel_tmp_sp /* Select abort stack */ load_xregs tp, THREAD_CORE_LOCAL_ABT_STACK_VA_END, REG_A1 j set_sp sel_tmp_sp: /* We have an abort while using the abort stack, select tmp stack */ load_xregs tp, THREAD_CORE_LOCAL_TMP_STACK_VA_END, REG_A1 ori a0, a0, THREAD_CLF_TMP /* flags |= THREAD_CLF_TMP; */ set_sp: mv sp, a1 sw a0, THREAD_CORE_LOCAL_FLAGS(tp) /* * Save state on stack */ addi sp, sp, -THREAD_ABT_REGS_SIZE /* Save kernel sp */ load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0 store_xregs sp, THREAD_ABT_REG_SP, REG_A0 /* Restore kernel a0, a1 which can be saved later */ load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 /* Save all other GPRs */ store_xregs sp, THREAD_ABT_REG_RA, REG_RA store_xregs sp, THREAD_ABT_REG_GP, REG_GP store_xregs sp, THREAD_ABT_REG_TP, REG_TP store_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2 store_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1 store_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7 store_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11 store_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6 /* Save XIE */ csrr t0, CSR_XIE store_xregs sp, THREAD_ABT_REG_IE, REG_T0 /* Mask all interrupts */ csrw CSR_XIE, x0 /* Save XSTATUS */ csrr t0, CSR_XSTATUS store_xregs sp, THREAD_ABT_REG_STATUS, REG_T0 /* Save XEPC */ csrr t0, CSR_XEPC store_xregs sp, THREAD_ABT_REG_EPC, REG_T0 /* Save XTVAL */ csrr t0, CSR_XTVAL store_xregs sp, THREAD_ABT_REG_TVAL, REG_T0 /* Save XCAUSE */ csrr a0, CSR_XCAUSE store_xregs sp, THREAD_ABT_REG_CAUSE, REG_A0 /* * a0 = cause * a1 = sp (struct thread_abort_regs *regs) * Call abort_handler(cause, regs) */ mv a1, sp call abort_handler /* * Restore state from stack */ /* Restore XEPC */ load_xregs sp, THREAD_ABT_REG_EPC, REG_T0 csrw CSR_XEPC, t0 /* Restore XIE */ load_xregs sp, THREAD_ABT_REG_IE, REG_T0 csrw CSR_XIE, t0 /* Restore XSTATUS */ load_xregs sp, THREAD_ABT_REG_STATUS, REG_T0 csrw CSR_XSTATUS, t0 /* Set scratch as thread_core_local */ csrw CSR_XSCRATCH, tp /* Update core local flags */ lw a0, THREAD_CORE_LOCAL_FLAGS(tp) srli a0, a0, THREAD_CLF_SAVED_SHIFT sw a0, THREAD_CORE_LOCAL_FLAGS(tp) /* Restore all GPRs */ load_xregs sp, THREAD_ABT_REG_RA, REG_RA load_xregs sp, THREAD_ABT_REG_GP, REG_GP load_xregs sp, THREAD_ABT_REG_TP, REG_TP load_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2 load_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1 load_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7 load_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11 load_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6 load_xregs sp, THREAD_ABT_REG_SP, REG_SP XRET END_FUNC trap_from_kernel LOCAL_FUNC trap_from_user, : /* Save user sp, a0, a1 into temporary spaces of thread_core_local */ store_xregs tp, THREAD_CORE_LOCAL_X0, REG_SP store_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 csrr a0, CSR_XCAUSE /* MSB of cause differentiates between interrupts and exceptions */ bge a0, zero, exception_from_user interrupt_from_user: /* Get thread context as sp */ get_thread_ctx sp, a0 /* Save user sp */ load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0 store_xregs sp, THREAD_CTX_REG_SP, REG_A0 /* Restore user a0, a1 which can be saved later */ load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 /* Save user gp */ store_xregs sp, THREAD_CTX_REG_GP, REG_GP /* * Set the scratch register to 0 such in case of a recursive * exception thread_trap_vect() knows that it is emitted from kernel. */ csrrw gp, CSR_XSCRATCH, zero /* Save user tp we previously swapped into CSR_XSCRATCH */ store_xregs sp, THREAD_CTX_REG_TP, REG_GP /* Set kernel gp */ .option push .option norelax la gp, __global_pointer$ .option pop /* Save all other GPRs */ store_xregs sp, THREAD_CTX_REG_RA, REG_RA store_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2 store_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1 store_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7 store_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11 store_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6 /* Save XIE */ csrr t0, CSR_XIE store_xregs sp, THREAD_CTX_REG_IE, REG_T0 /* Mask all interrupts */ csrw CSR_XIE, x0 /* Save XSTATUS */ csrr t0, CSR_XSTATUS store_xregs sp, THREAD_CTX_REG_STATUS, REG_T0 /* Save XEPC */ csrr t0, CSR_XEPC store_xregs sp, THREAD_CTX_REG_EPC, REG_T0 /* * a0 = cause * a1 = sp * Call thread_interrupt_handler(cause, regs) */ csrr a0, CSR_XCAUSE mv a1, sp /* Load tmp_stack_va_end as current sp. */ load_xregs tp, THREAD_CORE_LOCAL_TMP_STACK_VA_END, REG_SP call thread_interrupt_handler /* Get thread context as sp */ get_thread_ctx sp, t0 /* Restore XEPC */ load_xregs sp, THREAD_CTX_REG_EPC, REG_T0 csrw CSR_XEPC, t0 /* Restore XIE */ load_xregs sp, THREAD_CTX_REG_IE, REG_T0 csrw CSR_XIE, t0 /* Restore XSTATUS */ load_xregs sp, THREAD_CTX_REG_STATUS, REG_T0 csrw CSR_XSTATUS, t0 /* Set scratch as thread_core_local */ csrw CSR_XSCRATCH, tp /* Restore all GPRs */ load_xregs sp, THREAD_CTX_REG_RA, REG_RA load_xregs sp, THREAD_CTX_REG_GP, REG_GP load_xregs sp, THREAD_CTX_REG_TP, REG_TP load_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2 load_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1 load_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7 load_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11 load_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6 load_xregs sp, THREAD_CTX_REG_SP, REG_SP XRET exception_from_user: /* a0 is CSR_XCAUSE */ li a1, CAUSE_USER_ECALL bne a0, a1, abort_from_user ecall_from_user: /* Load and set kernel sp from thread context */ get_thread_ctx a0, a1 load_xregs a0, THREAD_CTX_KERN_SP, REG_SP /* Now sp is kernel sp, create stack for struct thread_scall_regs */ addi sp, sp, -THREAD_SCALL_REGS_SIZE /* Save user sp */ load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0 store_xregs sp, THREAD_SCALL_REG_SP, REG_A0 /* Restore user a0, a1 which can be saved later */ load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 /* Save user gp */ store_xregs sp, THREAD_SCALL_REG_GP, REG_GP /* * Set the scratch register to 0 such in case of a recursive * exception thread_trap_vect() knows that it is emitted from kernel. */ csrrw gp, CSR_XSCRATCH, zero /* Save user tp we previously swapped into CSR_XSCRATCH */ store_xregs sp, THREAD_SCALL_REG_TP, REG_GP /* Set kernel gp */ .option push .option norelax la gp, __global_pointer$ .option pop /* Save other caller-saved registers */ store_xregs sp, THREAD_SCALL_REG_RA, REG_RA store_xregs sp, THREAD_SCALL_REG_T0, REG_T0, REG_T2 store_xregs sp, THREAD_SCALL_REG_A0, REG_A0, REG_A7 store_xregs sp, THREAD_SCALL_REG_T3, REG_T3, REG_T6 /* Save XIE */ csrr a0, CSR_XIE store_xregs sp, THREAD_SCALL_REG_IE, REG_A0 /* Mask all interrupts */ csrw CSR_XIE, zero /* Save XSTATUS */ csrr a0, CSR_XSTATUS store_xregs sp, THREAD_SCALL_REG_STATUS, REG_A0 /* Save XEPC */ csrr a0, CSR_XEPC store_xregs sp, THREAD_SCALL_REG_EPC, REG_A0 /* * a0 = struct thread_scall_regs *regs * Call thread_scall_handler(regs) */ mv a0, sp call thread_scall_handler /* * Save kernel sp we'll had at the beginning of this function. * This is when this TA has called another TA because * __thread_enter_user_mode() also saves the stack pointer in this * field. */ get_thread_ctx a0, a1 addi t0, sp, THREAD_SCALL_REGS_SIZE store_xregs a0, THREAD_CTX_KERN_SP, REG_T0 /* * We are returning to U-Mode, on return, the program counter * is set to xsepc (pc=xepc), we add 4 (size of an instruction) * to continue to next instruction. */ load_xregs sp, THREAD_SCALL_REG_EPC, REG_T0 addi t0, t0, 4 csrw CSR_XEPC, t0 /* Restore XIE */ load_xregs sp, THREAD_SCALL_REG_IE, REG_T0 csrw CSR_XIE, t0 /* Restore XSTATUS */ load_xregs sp, THREAD_SCALL_REG_STATUS, REG_T0 csrw CSR_XSTATUS, t0 /* Set scratch as thread_core_local */ csrw CSR_XSCRATCH, tp /* Restore caller-saved registers */ load_xregs sp, THREAD_SCALL_REG_RA, REG_RA load_xregs sp, THREAD_SCALL_REG_GP, REG_GP load_xregs sp, THREAD_SCALL_REG_TP, REG_TP load_xregs sp, THREAD_SCALL_REG_T0, REG_T0, REG_T2 load_xregs sp, THREAD_SCALL_REG_A0, REG_A0, REG_A7 load_xregs sp, THREAD_SCALL_REG_T3, REG_T3, REG_T6 load_xregs sp, THREAD_SCALL_REG_SP, REG_SP XRET abort_from_user: /* * Update core local flags */ lw a0, THREAD_CORE_LOCAL_FLAGS(tp) slli a0, a0, THREAD_CLF_SAVED_SHIFT ori a0, a0, THREAD_CLF_ABORT sw a0, THREAD_CORE_LOCAL_FLAGS(tp) /* * Save state on stack */ /* Load abt_stack_va_end and set it as sp */ load_xregs tp, THREAD_CORE_LOCAL_ABT_STACK_VA_END, REG_SP /* Now sp is abort sp, create stack for struct thread_abort_regs */ addi sp, sp, -THREAD_ABT_REGS_SIZE /* Save user sp */ load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0 store_xregs sp, THREAD_ABT_REG_SP, REG_A0 /* Restore user a0, a1 which can be saved later */ load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1 /* Save user gp */ store_xregs sp, THREAD_ABT_REG_GP, REG_GP /* * Set the scratch register to 0 such in case of a recursive * exception thread_trap_vect() knows that it is emitted from kernel. */ csrrw gp, CSR_XSCRATCH, zero /* Save user tp we previously swapped into CSR_XSCRATCH */ store_xregs sp, THREAD_ABT_REG_TP, REG_GP /* Set kernel gp */ .option push .option norelax la gp, __global_pointer$ .option pop /* Save all other GPRs */ store_xregs sp, THREAD_ABT_REG_RA, REG_RA store_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2 store_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1 store_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7 store_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11 store_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6 /* Save XIE */ csrr t0, CSR_XIE store_xregs sp, THREAD_ABT_REG_IE, REG_T0 /* Mask all interrupts */ csrw CSR_XIE, x0 /* Save XSTATUS */ csrr t0, CSR_XSTATUS store_xregs sp, THREAD_ABT_REG_STATUS, REG_T0 /* Save XEPC */ csrr t0, CSR_XEPC store_xregs sp, THREAD_ABT_REG_EPC, REG_T0 /* Save XTVAL */ csrr t0, CSR_XTVAL store_xregs sp, THREAD_ABT_REG_TVAL, REG_T0 /* Save XCAUSE */ csrr a0, CSR_XCAUSE store_xregs sp, THREAD_ABT_REG_CAUSE, REG_A0 /* * a0 = cause * a1 = sp (struct thread_abort_regs *regs) * Call abort_handler(cause, regs) */ mv a1, sp call abort_handler /* * Restore state from stack */ /* Restore XEPC */ load_xregs sp, THREAD_ABT_REG_EPC, REG_T0 csrw CSR_XEPC, t0 /* Restore XIE */ load_xregs sp, THREAD_ABT_REG_IE, REG_T0 csrw CSR_XIE, t0 /* Restore XSTATUS */ load_xregs sp, THREAD_ABT_REG_STATUS, REG_T0 csrw CSR_XSTATUS, t0 /* Set scratch as thread_core_local */ csrw CSR_XSCRATCH, tp /* Update core local flags */ lw a0, THREAD_CORE_LOCAL_FLAGS(tp) srli a0, a0, THREAD_CLF_SAVED_SHIFT sw a0, THREAD_CORE_LOCAL_FLAGS(tp) /* Restore all GPRs */ load_xregs sp, THREAD_ABT_REG_RA, REG_RA load_xregs sp, THREAD_ABT_REG_GP, REG_GP load_xregs sp, THREAD_ABT_REG_TP, REG_TP load_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2 load_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1 load_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7 load_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11 load_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6 load_xregs sp, THREAD_ABT_REG_SP, REG_SP XRET END_FUNC trap_from_user /* * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, * uint32_t exit_status1); * See description in thread.h */ FUNC thread_unwind_user_mode , : /* Store the exit status */ load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A3, REG_A5 sw a1, (a4) sw a2, (a5) /* Save user callee regs */ store_xregs a3, THREAD_CTX_REG_S0, REG_S0, REG_S1 store_xregs a3, THREAD_CTX_REG_S2, REG_S2, REG_S11 store_xregs a3, THREAD_CTX_REG_SP, REG_SP, REG_TP /* Restore kernel callee regs */ mv a1, sp load_xregs a1, THREAD_USER_MODE_REC_X1, REG_RA, REG_GP load_xregs a1, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1 load_xregs a1, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11 add sp, sp, THREAD_USER_MODE_REC_SIZE /* Return from the call of thread_enter_user_mode() */ ret END_FUNC thread_unwind_user_mode /* * void thread_exit_user_mode(unsigned long a0, unsigned long a1, * unsigned long a2, unsigned long a3, * unsigned long sp, unsigned long pc, * unsigned long status); */ FUNC thread_exit_user_mode , : /* Set kernel stack pointer */ mv sp, a4 /* Set xSTATUS */ csrw CSR_XSTATUS, a6 /* * Zeroize xSCRATCH to indicate to thread_trap_vect() * that we are executing in kernel. */ csrw CSR_XSCRATCH, zero /* * Mask all interrupts first. Interrupts will be unmasked after * returning from __thread_enter_user_mode(). */ csrw CSR_XIE, zero /* Set epc as thread_unwind_user_mode() */ csrw CSR_XEPC, a5 XRET END_FUNC thread_exit_user_mode /* * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs, * uint32_t *exit_status0, * uint32_t *exit_status1); */ FUNC __thread_enter_user_mode , : /* Disable kernel mode exceptions first */ csrc CSR_XSTATUS, CSR_XSTATUS_IE /* * Create and fill in the struct thread_user_mode_rec */ addi sp, sp, -THREAD_USER_MODE_REC_SIZE store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A0, REG_A2 store_xregs sp, THREAD_USER_MODE_REC_X1, REG_RA, REG_GP store_xregs sp, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1 store_xregs sp, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11 /* * Save the kernel stack pointer in the thread context */ /* Get pointer to current thread context */ get_thread_ctx s0, s1 /* * Save kernel stack pointer to ensure that * thread_exit_user_mode() uses correct stack pointer. */ store_xregs s0, THREAD_CTX_KERN_SP, REG_SP /* * Save thread_core_local in xSCRATCH to ensure that thread_trap_vect() * uses correct core local structure. */ csrw CSR_XSCRATCH, tp /* Set user ie */ load_xregs a0, THREAD_CTX_REG_IE, REG_S0 csrw CSR_XIE, s0 /* Set user status */ load_xregs a0, THREAD_CTX_REG_STATUS, REG_S0 csrw CSR_XSTATUS, s0 /* Load the rest of the general purpose registers */ load_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP load_xregs a0, THREAD_CTX_REG_T0, REG_T0, REG_T2 load_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 load_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 load_xregs a0, THREAD_CTX_REG_T3, REG_T3, REG_T6 load_xregs a0, THREAD_CTX_REG_A0, REG_A0, REG_A7 /* Set exception program counter */ csrw CSR_XEPC, ra /* Jump into user mode */ XRET END_FUNC __thread_enter_user_mode /* void thread_resume(struct thread_ctx_regs *regs) */ FUNC thread_resume , : /* Disable global interrupts first */ csrc CSR_XSTATUS, CSR_XSTATUS_IE /* Restore epc */ load_xregs a0, THREAD_CTX_REG_EPC, REG_T0 csrw CSR_XEPC, t0 /* Restore ie */ load_xregs a0, THREAD_CTX_REG_IE, REG_T0 csrw CSR_XIE, t0 /* Restore status */ load_xregs a0, THREAD_CTX_REG_STATUS, REG_T0 csrw CSR_XSTATUS, t0 /* Check if previous privilege mode by status.SPP */ b_if_prev_priv_is_u t0, 1f /* Set scratch as zero to indicate that we are in kernel mode */ csrw CSR_XSCRATCH, zero j 2f 1: /* Resume to U-mode, set scratch as tp to be used in the trap handler */ csrw CSR_XSCRATCH, tp 2: /* Restore all general-purpose registers */ load_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP load_xregs a0, THREAD_CTX_REG_T0, REG_T0, REG_T2 load_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1 load_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11 load_xregs a0, THREAD_CTX_REG_T3, REG_T3, REG_T6 load_xregs a0, THREAD_CTX_REG_A0, REG_A0, REG_A7 XRET END_FUNC thread_resume optee_os-4.3.0/core/arch/riscv/kernel/unwind_rv.c000066400000000000000000000013501464416617300220000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /*- * Copyright (c) 2023 Andes Technology Corporation * Copyright (c) 2015 Linaro Limited * Copyright (c) 2015 The FreeBSD Foundation */ #include #include #include #include #include #if defined(CFG_UNWIND) && (TRACE_LEVEL > 0) void print_kernel_stack(void) { struct unwind_state_riscv state = { }; vaddr_t stack_start = 0; vaddr_t stack_end = 0; state.pc = read_pc(); state.fp = read_fp(); trace_printf_helper_raw(TRACE_ERROR, true, "TEE load address @ %#"PRIxVA, VCORE_START_VA); get_stack_hard_limits(&stack_start, &stack_end); print_stack_riscv(&state, stack_start, stack_end - stack_start); } #endif optee_os-4.3.0/core/arch/riscv/mm/000077500000000000000000000000001464416617300167535ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/mm/core_mmu_arch.c000066400000000000000000000440431464416617300217270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef RV64 #error implement #endif #ifndef DEBUG_XLAT_TABLE #define DEBUG_XLAT_TABLE 0 #endif #if DEBUG_XLAT_TABLE #define debug_print(...) DMSG_RAW(__VA_ARGS__) #else #define debug_print(...) ((void)0) #endif static bitstr_t bit_decl(g_asid, RISCV_MMU_ASID_WIDTH) __nex_bss; static unsigned int g_asid_spinlock __nex_bss = SPINLOCK_UNLOCK; struct mmu_pte { unsigned long entry; }; struct mmu_pgt { struct mmu_pte entries[RISCV_PTES_PER_PT]; }; #define RISCV_MMU_PGT_SIZE (sizeof(struct mmu_pgt)) static struct mmu_pgt root_pgt[CFG_TEE_CORE_NB_CORE] __aligned(RISCV_PGSIZE) __section(".nozi.mmu.root_pgt"); static struct mmu_pgt pool_pgts[RISCV_MMU_MAX_PGTS] __aligned(RISCV_PGSIZE) __section(".nozi.mmu.pool_pgts"); static struct mmu_pgt user_pgts[CFG_NUM_THREADS] __aligned(RISCV_PGSIZE) __section(".nozi.mmu.usr_pgts"); static int user_va_idx __nex_data = -1; struct mmu_partition { struct mmu_pgt *root_pgt; struct mmu_pgt *pool_pgts; struct mmu_pgt *user_pgts; unsigned int pgts_used; unsigned int asid; }; static struct mmu_partition default_partition __nex_data = { .root_pgt = root_pgt, .pool_pgts = pool_pgts, .user_pgts = user_pgts, .pgts_used = 0, .asid = 0 }; static struct mmu_pte *core_mmu_table_get_entry(struct mmu_pgt *pgt, unsigned int idx) { return &pgt->entries[idx & RISCV_MMU_VPN_MASK]; } static void core_mmu_entry_set(struct mmu_pte *pte, uint64_t val) { pte->entry = val; } static uint64_t core_mmu_entry_get(struct mmu_pte *pte) { return pte->entry; } static bool core_mmu_entry_is_valid(struct mmu_pte *pte) { return pte->entry & PTE_V; } static bool core_mmu_entry_is_invalid(struct mmu_pte *pte) { return !core_mmu_entry_is_valid(pte); } static bool core_mmu_entry_is_leaf(struct mmu_pte *pte) { /* A leaf has one or more RWX bits set */ return pte->entry & (PTE_R | PTE_W | PTE_X); } static bool __maybe_unused core_mmu_entry_is_branch(struct mmu_pte *pte) { return !core_mmu_entry_is_leaf(pte); } static unsigned long core_mmu_pte_create(unsigned long ppn, uint8_t pte_bits) { /* * This function may be called from core_mmu_set_entry(). There is a * case that MM core wants to clear PTE by calling core_mmu_set_entry() * with zero physical address and zero memory attributes, which turns * @ppn and @pte_bits in this function to be both zero. In this case, we * should create zero PTE without setting its V bit. */ return SHIFT_U64(ppn, PTE_PPN_SHIFT) | pte_bits; } static unsigned long core_mmu_ptp_create(unsigned long ppn) { /* Set V bit to create PTE points to next level of the page table. */ return core_mmu_pte_create(ppn, PTE_V); } static unsigned long core_mmu_pte_ppn(struct mmu_pte *pte) { return pte->entry >> PTE_PPN_SHIFT; } static unsigned long pa_to_ppn(paddr_t pa) { return pa >> RISCV_PGSHIFT; } static paddr_t pte_to_pa(struct mmu_pte *pte) { return SHIFT_U64(core_mmu_pte_ppn(pte), RISCV_PGSHIFT); } static unsigned long core_mmu_pgt_to_satp(unsigned long asid, struct mmu_pgt *pgt) { unsigned long satp = 0; unsigned long pgt_ppn = virt_to_phys(pgt) >> RISCV_PGSHIFT; assert(asid & g_asid == asid); satp |= SHIFT_U64(asid, RISCV_SATP_ASID_SHIFT); satp |= SHIFT_U64(RISCV_SATP_MODE, RISCV_SATP_MODE_SHIFT); satp |= pgt_ppn; return satp; } static unsigned long pte_to_mattr(unsigned level __maybe_unused, struct mmu_pte *pte) { unsigned long mattr = TEE_MATTR_SECURE; unsigned long entry = core_mmu_entry_get(pte); if (entry & PTE_V) { if (!(entry & (PTE_R | PTE_W | PTE_X))) return TEE_MATTR_TABLE; mattr |= TEE_MATTR_VALID_BLOCK; } if (entry & PTE_U) { if (entry & PTE_R) mattr |= TEE_MATTR_UR | TEE_MATTR_PR; if (entry & PTE_W) mattr |= TEE_MATTR_UW | TEE_MATTR_PW; if (entry & PTE_X) mattr |= TEE_MATTR_UX | TEE_MATTR_PX; } else { if (entry & PTE_R) mattr |= TEE_MATTR_PR; if (entry & PTE_W) mattr |= TEE_MATTR_PW; if (entry & PTE_X) mattr |= TEE_MATTR_PX; } if (entry & PTE_G) mattr |= TEE_MATTR_GLOBAL; return mattr; } static uint8_t mattr_to_pte_bits(unsigned level __maybe_unused, uint32_t attr) { unsigned long pte_bits = 0; if (attr & TEE_MATTR_TABLE) return PTE_V; if (attr & TEE_MATTR_VALID_BLOCK) pte_bits |= PTE_V; if (attr & TEE_MATTR_UR) pte_bits |= PTE_R | PTE_U; if (attr & TEE_MATTR_UW) pte_bits |= PTE_W | PTE_U; if (attr & TEE_MATTR_UX) pte_bits |= PTE_X | PTE_U; if (attr & TEE_MATTR_PR) pte_bits |= PTE_R; if (attr & TEE_MATTR_PW) pte_bits |= PTE_W | PTE_R; if (attr & TEE_MATTR_PX) pte_bits |= PTE_X | PTE_R; if (attr & (TEE_MATTR_UR | TEE_MATTR_PR)) pte_bits |= PTE_A; if (attr & (TEE_MATTR_UW | TEE_MATTR_PW)) pte_bits |= PTE_D; if (attr & TEE_MATTR_GLOBAL) pte_bits |= PTE_G; return pte_bits; } static unsigned int core_mmu_pgt_idx(vaddr_t va, unsigned int level) { unsigned int idx = va >> CORE_MMU_SHIFT_OF_LEVEL(level); return idx & RISCV_MMU_VPN_MASK; } static struct mmu_partition *core_mmu_get_prtn(void) { return &default_partition; } static struct mmu_pgt *core_mmu_get_root_pgt_va(struct mmu_partition *prtn) { return prtn->root_pgt + get_core_pos(); } static struct mmu_pgt *core_mmu_get_ta_pgt_va(struct mmu_partition *prtn) { return &prtn->user_pgts[thread_get_id()]; } static struct mmu_pgt *core_mmu_pgt_alloc(struct mmu_partition *prtn) { struct mmu_pgt *pgt = NULL; if (prtn->pgts_used >= RISCV_MMU_MAX_PGTS) { debug_print("%u pgts exhausted", RISCV_MMU_MAX_PGTS); panic(); return NULL; } pgt = &prtn->pool_pgts[prtn->pgts_used++]; memset(pgt, 0, RISCV_MMU_PGT_SIZE); debug_print("pgts used %u / %u", prtn->pgts_used, RISCV_MMU_MAX_PGTS); return pgt; } static void core_init_mmu_prtn_ta_core(struct mmu_partition *prtn __unused, unsigned int core __unused) { /* * user_va_idx is the index in CORE_MMU_BASE_TABLE_LEVEL. * The entry holds pointer to the user mapping table in next level * that changes per core. Therefore, nothing to do. */ } static void core_init_mmu_prtn_ta(struct mmu_partition *prtn) { unsigned int core = 0; assert(user_va_idx != -1); memset(prtn->user_pgts, 0, CFG_NUM_THREADS * RISCV_MMU_PGT_SIZE); for (core = 0; core < CFG_TEE_CORE_NB_CORE; core++) core_init_mmu_prtn_ta_core(prtn, core); } static void core_init_mmu_prtn_tee(struct mmu_partition *prtn, struct tee_mmap_region *mm) { size_t n = 0; void *pgt = core_mmu_get_root_pgt_va(prtn); /* Clear table before using it. */ memset(prtn->root_pgt, 0, RISCV_MMU_PGT_SIZE * CFG_TEE_CORE_NB_CORE); memset(pgt, 0, RISCV_MMU_PGT_SIZE); memset(prtn->pool_pgts, 0, RISCV_MMU_MAX_PGTS * RISCV_MMU_PGT_SIZE); for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) if (!core_mmu_is_dynamic_vaspace(mm + n)) core_mmu_map_region(prtn, mm + n); /* * Primary mapping table is ready at index `get_core_pos()` * whose value may not be ZERO. Take this index as copy source. */ for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { if (n != get_core_pos()) memcpy(&prtn->root_pgt[n], &prtn->root_pgt[get_core_pos()], RISCV_MMU_PGT_SIZE); } } void tlbi_va_range(vaddr_t va, size_t len, size_t granule) { assert(granule == CORE_MMU_PGDIR_SIZE || granule == SMALL_PAGE_SIZE); assert(!(va & (granule - 1)) && !(len & (granule - 1))); /* * Ensure operations are completed or observed before proceeding * with TLB invalidation. */ mb(); while (len) { tlbi_va_allasid(va); len -= granule; va += granule; } /* * After invalidating TLB entries, a memory barrier is required * to ensure that the page table entries become visible to other harts * before subsequent memory accesses are performed. */ mb(); } void tlbi_va_range_asid(vaddr_t va, size_t len, size_t granule, uint32_t asid) { assert(granule == CORE_MMU_PGDIR_SIZE || granule == SMALL_PAGE_SIZE); assert(!(va & (granule - 1)) && !(len & (granule - 1))); /* * A memory barrier is necessary here to ensure the consistency * and correctness of memory accesses. */ mb(); while (len) { tlbi_va_asid(va, asid); len -= granule; va += granule; } /* Enforce ordering of memory operations and ensure that all * preceding memory operations are completed after TLB * invalidation. */ mb(); } TEE_Result cache_op_inner(enum cache_op op, void *va, size_t len) { switch (op) { case DCACHE_CLEAN: dcache_op_all(DCACHE_OP_CLEAN); break; case DCACHE_AREA_CLEAN: dcache_clean_range(va, len); break; case DCACHE_INVALIDATE: dcache_op_all(DCACHE_OP_INV); break; case DCACHE_AREA_INVALIDATE: dcache_inv_range(va, len); break; case ICACHE_INVALIDATE: icache_inv_all(); break; case ICACHE_AREA_INVALIDATE: icache_inv_range(va, len); break; case DCACHE_CLEAN_INV: dcache_op_all(DCACHE_OP_CLEAN_INV); break; case DCACHE_AREA_CLEAN_INV: dcache_cleaninv_range(va, len); break; default: return TEE_ERROR_NOT_IMPLEMENTED; } return TEE_SUCCESS; } unsigned int asid_alloc(void) { uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); unsigned int r = 0; int i = 0; bit_ffc(g_asid, RISCV_MMU_ASID_WIDTH, &i); if (i == -1) { r = 0; } else { bit_set(g_asid, i); r = i + 1; } cpu_spin_unlock_xrestore(&g_asid_spinlock, exceptions); return r; } void asid_free(unsigned int asid) { uint32_t exceptions = cpu_spin_lock_xsave(&g_asid_spinlock); if (asid) { int i = asid - 1; assert(i < RISCV_MMU_ASID_WIDTH && bit_test(&g_asid, i)); bit_clear(g_asid, i); } cpu_spin_unlock_xrestore(&g_asid_spinlock, exceptions); } bool arch_va2pa_helper(void *va, paddr_t *pa) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); vaddr_t vaddr = (vaddr_t)va; struct mmu_pgt *pgt = NULL; struct mmu_pte *pte = NULL; int level = 0; unsigned int idx = 0; struct mmu_partition *prtn = core_mmu_get_prtn(); assert(pa); pgt = core_mmu_get_root_pgt_va(prtn); for (level = CORE_MMU_BASE_TABLE_LEVEL; level >= 0; level--) { idx = core_mmu_pgt_idx(vaddr, level); pte = core_mmu_table_get_entry(pgt, idx); if (core_mmu_entry_is_invalid(pte)) { thread_unmask_exceptions(exceptions); return false; } else if (core_mmu_entry_is_leaf(pte)) { *pa = pte_to_pa(pte) | (vaddr & (BIT64(RISCV_PGSHIFT) - 1)); thread_unmask_exceptions(exceptions); return true; } pgt = phys_to_virt(pte_to_pa(pte), MEM_AREA_TEE_RAM_RW_DATA, sizeof(*pgt)); } thread_unmask_exceptions(exceptions); return false; } bool cpu_mmu_enabled(void) { return read_satp(); } bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, unsigned int max_level, struct core_mmu_table_info *tbl_info) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); struct mmu_pgt *pgt = NULL; struct mmu_pte *pte = NULL; unsigned int level = CORE_MMU_BASE_TABLE_LEVEL; unsigned int idx = 0; unsigned int deepest_level = max_level; vaddr_t va_base = 0; bool ret = false; if (max_level == UINT_MAX) deepest_level = 0; if (!prtn) prtn = core_mmu_get_prtn(); pgt = core_mmu_get_root_pgt_va(prtn); while (true) { idx = core_mmu_pgt_idx(va - va_base, level); pte = core_mmu_table_get_entry(pgt, idx); if (level == deepest_level || level == 0 || core_mmu_entry_is_invalid(pte) || core_mmu_entry_is_leaf(pte)) { core_mmu_set_info_table(tbl_info, level, va_base, pgt); ret = true; goto out; } pgt = phys_to_virt(pte_to_pa(pte), MEM_AREA_TEE_RAM_RW_DATA, sizeof(*pgt)); if (!pgt) goto out; va_base += SHIFT_U64(idx, CORE_MMU_SHIFT_OF_LEVEL(level)); level--; } out: thread_unmask_exceptions(exceptions); return ret; } bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, unsigned int idx, bool secure __unused) { struct mmu_pgt *pgt = NULL; struct mmu_pte *pte = NULL; struct mmu_partition *prtn = core_mmu_get_prtn(); unsigned long ptp = 0; if (!core_mmu_level_in_range(tbl_info->level)) return false; pgt = tbl_info->table; pte = core_mmu_table_get_entry(pgt, idx); if (core_mmu_entry_is_invalid(pte)) { pgt = core_mmu_pgt_alloc(prtn); if (!pgt) return false; ptp = core_mmu_ptp_create(pa_to_ppn((paddr_t)pgt)); core_mmu_entry_set(pte, ptp); } return true; } void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, unsigned int level, vaddr_t va_base, void *table) { tbl_info->level = level; tbl_info->next_level = level - 1; tbl_info->table = table; tbl_info->va_base = va_base; tbl_info->shift = CORE_MMU_SHIFT_OF_LEVEL(level); assert(level < RISCV_PGLEVELS); tbl_info->num_entries = RISCV_PTES_PER_PT; } void core_mmu_get_entry_primitive(const void *table, size_t level, size_t idx, paddr_t *pa, uint32_t *attr) { struct mmu_pgt *pgt = (struct mmu_pgt *)table; struct mmu_pte *pte = core_mmu_table_get_entry(pgt, idx); if (core_mmu_entry_is_valid(pte)) { if (pa) *pa = pte_to_pa(pte); if (attr) *attr = pte_to_mattr(level, pte); } else { if (pa) *pa = 0; if (attr) *attr = 0; } } void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, paddr_t pa, uint32_t attr) { struct mmu_pgt *pgt = (struct mmu_pgt *)table; struct mmu_pte *pte = core_mmu_table_get_entry(pgt, idx); uint8_t pte_bits = mattr_to_pte_bits(level, attr); core_mmu_entry_set(pte, core_mmu_pte_create(pa_to_ppn(pa), pte_bits)); } static void set_user_va_idx(struct mmu_partition *prtn) { struct mmu_pgt *pgt = NULL; struct mmu_pte *pte = NULL; unsigned int idx = 0; pgt = core_mmu_get_root_pgt_va(prtn); for (idx = 1 ; idx < RISCV_PTES_PER_PT; idx++) { pte = core_mmu_table_get_entry(pgt, idx); if (core_mmu_entry_is_invalid(pte)) { user_va_idx = idx; return; } } if (user_va_idx < 0) panic(); } static struct mmu_pte * core_mmu_get_user_mapping_entry(struct mmu_partition *prtn) { struct mmu_pgt *pgt = core_mmu_get_root_pgt_va(prtn); assert(user_va_idx != -1); return core_mmu_table_get_entry(pgt, user_va_idx); } void core_mmu_set_user_map(struct core_mmu_user_map *map) { unsigned long satp = 0; uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); struct mmu_partition *prtn = core_mmu_get_prtn(); struct mmu_pte *pte = NULL; unsigned long ptp = 0; satp = read_satp(); /* Clear ASID */ satp &= ~SHIFT_U64(RISCV_SATP_ASID_MASK, RISCV_SATP_ASID_SHIFT); pte = core_mmu_get_user_mapping_entry(prtn); if (map && map->user_map) { ptp = core_mmu_ptp_create(pa_to_ppn((paddr_t)map->user_map)); core_mmu_entry_set(pte, ptp); core_mmu_table_write_barrier(); satp |= SHIFT_U64(map->asid, RISCV_SATP_ASID_SHIFT); write_satp(satp); } else { core_mmu_entry_set(pte, 0); core_mmu_table_write_barrier(); } tlbi_all(); thread_unmask_exceptions(exceptions); } void core_mmu_get_user_va_range(vaddr_t *base, size_t *size) { assert(user_va_idx != -1); if (base) *base = SHIFT_U64(user_va_idx, CORE_MMU_BASE_TABLE_SHIFT); if (size) *size = BIT64(CORE_MMU_BASE_TABLE_SHIFT); } void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info) { vaddr_t va_range_base = 0; struct mmu_partition *prtn = core_mmu_get_prtn(); struct mmu_pgt *pgt = core_mmu_get_ta_pgt_va(prtn); core_mmu_get_user_va_range(&va_range_base, NULL); core_mmu_set_info_table(pgd_info, CORE_MMU_PGDIR_LEVEL + 1, va_range_base, pgt); } void core_mmu_create_user_map(struct user_mode_ctx *uctx, struct core_mmu_user_map *map) { struct core_mmu_table_info tbl_info = { }; core_mmu_get_user_pgdir(&tbl_info); memset(tbl_info.table, 0, RISCV_MMU_PGT_SIZE); core_mmu_populate_user_map(&tbl_info, uctx); map->user_map = virt_to_phys(tbl_info.table); map->asid = uctx->vm_info.asid; } void core_mmu_get_user_map(struct core_mmu_user_map *map) { struct mmu_partition *prtn = core_mmu_get_prtn(); struct mmu_pte *pte = core_mmu_get_user_mapping_entry(prtn); map->user_map = pte_to_pa(pte); if (map->user_map) map->asid = (read_satp() >> RISCV_SATP_ASID_SHIFT) & RISCV_SATP_ASID_MASK; else map->asid = 0; } bool core_mmu_user_mapping_is_active(void) { struct mmu_partition *prtn = core_mmu_get_prtn(); bool ret = false; struct mmu_pte *pte = NULL; uint32_t exceptions = 0; exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); pte = core_mmu_get_user_mapping_entry(prtn); ret = core_mmu_entry_is_valid(pte); thread_unmask_exceptions(exceptions); return ret; } void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm) { core_init_mmu_prtn_tee(prtn, mm); core_init_mmu_prtn_ta(prtn); } void core_init_mmu(struct tee_mmap_region *mm) { uint64_t max_va = 0; size_t n = 0; static_assert((RISCV_MMU_MAX_PGTS * RISCV_MMU_PGT_SIZE) == sizeof(pool_pgts)); /* Initialize default pagetables */ core_init_mmu_prtn_tee(&default_partition, mm); for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) { vaddr_t va_end = mm[n].va + mm[n].size - 1; if (va_end > max_va) max_va = va_end; } set_user_va_idx(&default_partition); core_init_mmu_prtn_ta(&default_partition); assert(max_va < BIT64(RISCV_MMU_VA_WIDTH)); } void core_init_mmu_regs(struct core_mmu_config *cfg) { struct mmu_partition *p = core_mmu_get_prtn(); unsigned int n = 0; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) cfg->satp[n] = core_mmu_pgt_to_satp(p->asid, p->root_pgt + n); } enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr) { switch (fault_descr) { case CAUSE_MISALIGNED_FETCH: case CAUSE_MISALIGNED_LOAD: case CAUSE_MISALIGNED_STORE: return CORE_MMU_FAULT_ALIGNMENT; case CAUSE_STORE_ACCESS: case CAUSE_LOAD_ACCESS: return CORE_MMU_FAULT_ACCESS_BIT; case CAUSE_FETCH_PAGE_FAULT: case CAUSE_LOAD_PAGE_FAULT: case CAUSE_STORE_PAGE_FAULT: case CAUSE_FETCH_GUEST_PAGE_FAULT: case CAUSE_LOAD_GUEST_PAGE_FAULT: case CAUSE_STORE_GUEST_PAGE_FAULT: return CORE_MMU_FAULT_TRANSLATION; case CAUSE_BREAKPOINT: return CORE_MMU_FAULT_DEBUG_EVENT; default: return CORE_MMU_FAULT_OTHER; } } optee_os-4.3.0/core/arch/riscv/mm/sub.mk000066400000000000000000000005761464416617300201050ustar00rootroot00000000000000srcs-y += core_mmu_arch.c srcs-y += tlb_helpers_rv.S ifeq ($(CFG_SYSCALL_FTRACE),y) # We would not like to profile MMU APIs as these are used to switch TA # context which may cause undesired behaviour as ftrace requires TA context # to be active. Moreover profiling code uses some of MMU APIs to check # if TA context is active or not. cflags-remove-core_mmu_arch.c-y += -pg endif optee_os-4.3.0/core/arch/riscv/mm/tlb_helpers_rv.S000066400000000000000000000011021464416617300221030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation * Copyright 2022 NXP */ #include /* void tlbi_all(void); */ FUNC tlbi_all , : sfence.vma zero, zero ret END_FUNC tlbi_all /* void tlbi_va_allasid(vaddr_t va); */ FUNC tlbi_va_allasid , : sfence.vma a0, zero ret END_FUNC tlbi_va_allasid /* void tlbi_asid(unsigned int asid); */ FUNC tlbi_asid , : sfence.vma zero, a0 ret END_FUNC tlbi_asid /* void tlbi_va_asid(vaddr_t va, uint32_t asid); */ FUNC tlbi_va_asid , : sfence.vma a0, a1 ret END_FUNC tlbi_va_asid optee_os-4.3.0/core/arch/riscv/plat-spike/000077500000000000000000000000001464416617300204135ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/plat-spike/conf.mk000066400000000000000000000052041464416617300216720ustar00rootroot00000000000000CFG_RV64_core ?= y $(call force,CFG_WITH_USER_TA,n) $(call force,CFG_WITH_SOFTWARE_PRNG,y) $(call force,CFG_CORE_FFA,n) $(call force,CFG_CORE_DYN_SHM,n) $(call force,CFG_SECURE_PARTITION,n) $(call force,CFG_PAGED_USER_TA,n) $(call force,CFG_WITH_PAGER,n) $(call force,CFG_TEE_TA_LOG_LEVEL,0) $(call force,CFG_EMBEDDED_TS,n) $(call force,CFG_CORE_ASLR,n) $(call force,CFG_LIBUTILS_WITH_ISOC,y) $(call force,CFG_UNWIND,n) $(call force,CFG_DT,n) $(call force,CFG_NS_VIRTUALIZATION,n) $(call force,CFG_WITH_VFP,n) $(call force,CFG_WITH_STATS,n) $(call force,CFG_WITH_STMM_SP,n) $(call force,CFG_WITH_STACK_CANARIES,n) $(call force,CFG_TEE_TA_MALLOC_DEBUG,n) $(call force,CFG_COMPAT_GP10_DES,n) $(call force,CFG_TEE_CORE_TA_TRACE,n) $(call force,CFG_TEE_CORE_NB_CORE,4) $(call force,CFG_TEE_CORE_MALLOC_DEBUG,n) $(call force,CFG_TEE_CORE_DEBUG,n) $(call force,CFG_SYSTEM_PTA,n) $(call force,CFG_SYSCALL_FTRACE,n) $(call force,CFG_CORE_DEBUG_CHECK_STACKS,n) $(call force,CFG_BOOT_SECONDARY_REQUEST,n) $(call force,CFG_CORE_DUMP_OOM,n) $(call force,CFG_CORE_LARGE_PHYS_ADDR,n) $(call force,CFG_CORE_RESERVED_SHM,y) $(call force,CFG_CORE_RODATA_NOEXEC,n) $(call force,CFG_CORE_RWDATA_NOEXEC,y) $(call force,CFG_CORE_SANITIZE_KADDRESS,n) $(call force,CFG_CORE_SANITIZE_UNDEFINED,n) $(call force,CFG_CORE_THREAD_SHIFT,0) $(call force,CFG_CORE_TPM_EVENT_LOG,n) $(call force,CFG_DEBUG_INFO,n) $(call force,CFG_DEVICE_ENUM_PTA,n) $(call force,CFG_DRIVERS_CLK,n) $(call force,CFG_DRIVERS_CLK_DT,n) $(call force,CFG_DRIVERS_CLK_FIXED,n) $(call force,CFG_EARLY_TA,n) $(call force,CFG_EARLY_TA_COMPRESS,n) $(call force,CFG_EMBED_DTB,n) $(call force,CFG_ENABLE_EMBEDDED_TESTS,n) $(call force,CFG_ENABLE_SCTLR_Z,n) $(call force,CFG_EXTERNAL_DTB_OVERLAY,n) $(call force,CFG_FTRACE_SUPPORT,n) $(call force,CFG_GENERATE_DTB_OVERLAY,n) $(call force,CFG_GIC,n) $(call force,CFG_GP_SOCKETS,n) $(call force,CFG_LOCKDEP,n) $(call force,CFG_TEE_CORE_EMBED_INTERNAL_TESTS,n) $(call force,CFG_MMAP_REGIONS,13) $(call force,CFG_NUM_THREADS,4) $(call force,CFG_PAGED_USER_TA,n) $(call force,CFG_REE_FS,n) $(call force,CFG_REE_FS_ALLOW_RESET,n) $(call force,CFG_REE_FS_TA,n) $(call force,CFG_REE_FS_TA_BUFFERED,n) $(call force,CFG_RPMB_FS,n) $(call force,CFG_SCMI_PTA,n) $(call force,CFG_SCTLR_ALIGNMENT_CHECK,n) $(call force,CFG_SECSTOR_TA,n) $(call force,CFG_SHOW_CONF_ON_BOOT,n) $(call force,CFG_SYSCALL_WRAPPERS_MCOUNT,n) $(call force,CFG_BOOT_SYNC_CPU,y) $(call force,CFG_INSECURE,y) $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y) CFG_RISCV_MTIME_RATE ?= 10000000 CFG_TDDRAM_START ?= 0xbdb00000 CFG_TDDRAM_SIZE ?= 0x00f00000 CFG_SHMEM_START ?= 0x7fe00000 CFG_SHMEM_SIZE ?= 0x00200000 CFG_TEE_RAM_VA_SIZE ?= 0x00400000 optee_os-4.3.0/core/arch/riscv/plat-spike/drivers/000077500000000000000000000000001464416617300220715ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/plat-spike/drivers/htif.c000066400000000000000000000030701464416617300231670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include #include #include #include #include "htif.h" static unsigned int htif_global_lock __nex_bss = SPINLOCK_UNLOCK; #ifdef HTIF_BASE register_phys_mem(MEM_AREA_IO_NSEC, HTIF_BASE, ROUNDUP(HTIF_REG_SIZE, CORE_MMU_PGDIR_SIZE)); #endif void htif_lock_global(void) { cpu_spin_lock(&htif_global_lock); } void htif_unlock_global(void) { cpu_spin_unlock(&htif_global_lock); } static vaddr_t chip_to_base(struct serial_chip *chip) { struct htif_console_data *pd = container_of(chip, struct htif_console_data, chip); return io_pa_or_va(&pd->base, HTIF_REG_SIZE); } static void __maybe_unused tohost_cmd(vaddr_t base, uint64_t dev, uint64_t cmd, uint64_t data) { while (io_read64(base)) barrier(); io_write64(base, SHIFT_U64(dev, 56) | SHIFT_U64(cmd, 48) | data); } static void htif_console_putc(struct serial_chip *chip, int ch __maybe_unused) { #ifdef RV64 vaddr_t base = 0; htif_lock_global(); base = chip_to_base(chip); tohost_cmd(base, HTIF_DEV_CONSOLE, HTIF_CMD_WRITE, ch); htif_unlock_global(); #else #warning HTIF is not supported on RV32 #endif } static void htif_console_flush(struct serial_chip *chip __unused) { } static const struct serial_ops htif_console_ops = { .flush = htif_console_flush, .putc = htif_console_putc, }; DECLARE_KEEP_PAGER(htif_console_ops); void htif_console_init(struct htif_console_data *pd, paddr_t pbase) { pd->base.pa = pbase; pd->chip.ops = &htif_console_ops; } optee_os-4.3.0/core/arch/riscv/plat-spike/drivers/htif.h000066400000000000000000000010101464416617300231640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __DRIVERS_HTIF_H__ #define __DRIVERS_HTIF_H__ #include #include #define HTIF_CMD_WRITE 1 #define HTIF_DEV_CONSOLE 1 #define HTIF_REG_SIZE (2 * RISCV_XLEN_BYTES) struct htif_console_data { struct io_pa_va base; struct serial_chip chip; }; void htif_lock_global(void); void htif_unlock_global(void); void htif_console_init(struct htif_console_data *pd, paddr_t pbase); #endif /*__DRIVERS_HTIF_H__*/ optee_os-4.3.0/core/arch/riscv/plat-spike/drivers/sub.mk000066400000000000000000000000431464416617300232100ustar00rootroot00000000000000srcs-$(CFG_RISCV_M_MODE) += htif.c optee_os-4.3.0/core/arch/riscv/plat-spike/kern.ld.S000066400000000000000000000002711464416617300220740ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause) */ /* * Copyright 2022 NXP */ #include "../kernel/kern.ld.S" SECTIONS { .htif HTIF_BASE: { tohost = .; fromhost = tohost + 8; } } optee_os-4.3.0/core/arch/riscv/plat-spike/main.c000066400000000000000000000011711464416617300215030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include #include #include #include "drivers/htif.h" #ifdef CFG_RISCV_M_MODE static struct htif_console_data console_data __nex_bss; void plat_console_init(void) { #ifdef HTIF_BASE htif_console_init(&console_data, HTIF_BASE); register_serial_console(&console_data.chip); #endif /*HTIF_BASE*/ } #endif /*CFG_RISCV_M_MODE*/ TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { memset(&hwkey->data[0], 0, sizeof(hwkey->data)); return TEE_SUCCESS; } optee_os-4.3.0/core/arch/riscv/plat-spike/platform_config.h000066400000000000000000000005221464416617300237340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP * * Brief Spike platform configuration. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include #ifndef HTIF_BASE #define HTIF_BASE 0x40008000 #endif /* CLINT */ #ifndef CLINT_BASE #define CLINT_BASE 0x02000000 #endif #endif optee_os-4.3.0/core/arch/riscv/plat-spike/sub.mk000066400000000000000000000000741464416617300215360ustar00rootroot00000000000000global-incdirs-y += . subdirs-y += drivers srcs-y += main.c optee_os-4.3.0/core/arch/riscv/plat-virt/000077500000000000000000000000001464416617300202645ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/plat-virt/conf.mk000066400000000000000000000021311464416617300215370ustar00rootroot00000000000000$(call force,CFG_RV64_core,y) $(call force,CFG_CORE_LARGE_PHYS_ADDR,y) $(call force,CFG_TEE_CORE_DEBUG,n) $(call force,CFG_CORE_RESERVED_SHM,n) $(call force,CFG_CORE_DYN_SHM,y) CFG_DT ?= y # Crypto flags $(call force,CFG_WITH_SOFTWARE_PRNG,n) $(call force,CFG_HWRNG_PTA,y) $(call force,CFG_HWRNG_QUALITY,1024) $(call force,CFG_RISCV_ZKR_RNG,y) # Protection flags $(call force,CFG_CORE_ASLR,n) $(call force,CFG_WITH_STACK_CANARIES,n) $(call force,CFG_CORE_SANITIZE_KADDRESS,n) # Hart-related flags CFG_TEE_CORE_NB_CORE ?= 1 CFG_NUM_THREADS ?= 1 $(call force,CFG_BOOT_SYNC_CPU,y) # RISC-V-specific flags rv64-platform-isa ?= rv64imafdc_zicsr_zifencei $(call force,CFG_RISCV_M_MODE,n) $(call force,CFG_RISCV_S_MODE,y) $(call force,CFG_RISCV_PLIC,y) $(call force,CFG_SBI_CONSOLE,n) $(call force,CFG_16550_UART,y) $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y) CFG_RISCV_MTIME_RATE ?= 10000000 CFG_RISCV_SBI ?= y CFG_RISCV_WITH_M_MODE_SM ?= y # TA-related flags supported-ta-targets = ta_rv64 # Memory layout flags CFG_TDDRAM_START ?= 0x8e000000 CFG_TDDRAM_SIZE ?= 0x00f00000 CFG_TEE_RAM_VA_SIZE ?= 0x00200000 optee_os-4.3.0/core/arch/riscv/plat-virt/main.c000066400000000000000000000014541464416617300213600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include #include #include static struct ns16550_data console_data __nex_bss; register_ddr(DRAM_BASE, DRAM_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_NSEC, UART0_BASE, CORE_MMU_PGDIR_SIZE); #ifdef CFG_RISCV_PLIC void boot_primary_init_intc(void) { plic_init(PLIC_BASE); } void boot_secondary_init_intc(void) { plic_hart_init(); } #endif /* CFG_RISCV_PLIC */ void plat_console_init(void) { ns16550_init(&console_data, UART0_BASE, IO_WIDTH_U8, 0); register_serial_console(&console_data.chip); } void interrupt_main_handler(void) { if (IS_ENABLED(CFG_RISCV_PLIC)) plic_it_handle(); } optee_os-4.3.0/core/arch/riscv/plat-virt/platform_config.h000066400000000000000000000032531464416617300236110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP * * Brief Qemu Virt platform configuration. */ #ifndef PLATFORM_CONFIG_H #define PLATFORM_CONFIG_H #include /* The stack pointer is always kept 16-byte aligned */ #define STACK_ALIGNMENT 16 /* DRAM */ #ifndef DRAM_BASE #define DRAM_BASE 0x80000000 #define DRAM_SIZE 0x10000000 #endif /* CLINT */ #ifndef CLINT_BASE #define CLINT_BASE 0x02000000 #endif /* PLIC */ #ifndef PLIC_BASE #define PLIC_BASE 0x0c000000 #define PLIC_REG_SIZE 0x600000 #define PLIC_NUM_SOURCES 0x5f #endif /* UART */ #ifndef UART0_BASE #define UART0_BASE 0x10000000 #endif #define UART0_IRQ 0x0a /* RTC */ #ifndef RTC_BASE #define RTC_BASE 0x101000 #endif #define RTC_IRQ 0x0b /* VIRTIO MMIOs */ #define NUM_VIRTIO_MMIOS 8 #ifndef VIRTIO_MMIO1 #define VIRTIO_MMIO1 0x10001000 #define VIRTIO_MMIO1_IRQ 0x01 #endif #ifndef VIRTIO_MMIO2 #define VIRTIO_MMIO2 0x10002000 #define VIRTIO_MMIO2_IRQ 0x02 #endif #ifndef VIRTIO_MMIO3 #define VIRTIO_MMIO3 0x10003000 #define VIRTIO_MMIO3_IRQ 0x03 #endif #ifndef VIRTIO_MMIO4 #define VIRTIO_MMIO4 0x10004000 #define VIRTIO_MMIO4_IRQ 0x04 #endif #ifndef VIRTIO_MMIO5 #define VIRTIO_MMIO5 0x10005000 #define VIRTIO_MMIO5_IRQ 0x05 #endif #ifndef VIRTIO_MMIO6 #define VIRTIO_MMIO6 0x10006000 #define VIRTIO_MMIO6_IRQ 0x06 #endif #ifndef VIRTIO_MMIO7 #define VIRTIO_MMIO7 0x10007000 #define VIRTIO_MMIO7_IRQ 0x07 #endif #ifndef VIRTIO_MMIO8 #define VIRTIO_MMIO8 0x10008000 #define VIRTIO_MMIO8_IRQ 0x08 #endif #ifdef CFG_RISCV_MTIME_RATE #define RISCV_MTIME_RATE CFG_RISCV_MTIME_RATE #else #define RISCV_MTIME_RATE 1000000 #endif #endif /*PLATFORM_CONFIG_H*/ optee_os-4.3.0/core/arch/riscv/plat-virt/sub.mk000066400000000000000000000000471464416617300214070ustar00rootroot00000000000000global-incdirs-y += . srcs-y += main.c optee_os-4.3.0/core/arch/riscv/riscv.mk000066400000000000000000000206441464416617300200270ustar00rootroot00000000000000# Setup compiler for the core module ifeq ($(CFG_RV64_core),y) arch-bits-core := 64 else arch-bits-core := 32 endif CROSS_COMPILE_core := $(CROSS_COMPILE$(arch-bits-core)) COMPILER_core := $(COMPILER) include mk/$(COMPILER_core).mk # Defines the cc-option macro using the compiler set for the core module include mk/cc-option.mk CFG_MMAP_REGIONS ?= 13 CFG_RESERVED_VASPACE_SIZE ?= (1024 * 1024 * 10) ifeq ($(CFG_RV64_core),y) CFG_KERN_LINKER_FORMAT ?= elf64-littleriscv CFG_KERN_LINKER_ARCH ?= riscv else ifeq ($(CFG_RV32_core),y) CFG_KERN_LINKER_FORMAT ?= elf32-littleriscv CFG_KERN_LINKER_ARCH ?= riscv else $(error Error: CFG_RV64_core or CFG_RV32_core should be defined) endif endif CFG_CORE_RWDATA_NOEXEC ?= y CFG_CORE_RODATA_NOEXEC ?= n ifeq ($(CFG_CORE_RODATA_NOEXEC),y) $(call force,CFG_CORE_RWDATA_NOEXEC,y) endif CFG_MAX_CACHE_LINE_SHIFT ?= 6 # CFG_WITH_LPAE is ARM-related flag, however, it is used by core code. # In order to maintain the code logic, we set it when CFG_CORE_LARGE_PHYS_ADDR is set. # Platform configuration should accordingly set CFG_CORE_LARGE_PHYS_ADDR or not. ifeq ($(CFG_CORE_LARGE_PHYS_ADDR),y) $(call force,CFG_WITH_LPAE,y) endif CFG_RISCV_SBI ?= n CFG_RISCV_M_MODE ?= y ifeq ($(CFG_RISCV_M_MODE),y) ifeq ($(CFG_RISCV_S_MODE),y) $(error CFG_RISCV_M_MODE and CFG_RISCV_S_MODE cannot be both 'y') else $(call force,CFG_RISCV_S_MODE,n) $(call force,CFG_RISCV_SBI,n) endif endif ifeq ($(CFG_RISCV_S_MODE),y) $(call force,CFG_RISCV_M_MODE,n) endif ifneq (y,$(call cfg-one-enabled,CFG_RISCV_M_MODE M CFG_RISCV_S_MODE)) $(error Either CFG_RISCV_M_MODE or CFG_RISCV_S_MODE must be 'y') endif ifeq ($(CFG_RISCV_SBI_CONSOLE),y) $(call force,CFG_RISCV_SBI,y) endif # 'y' to let M-mode secure monitor handle the communication between OP-TEE OS # and untrusted domain. CFG_RISCV_WITH_M_MODE_SM ?= n ifeq ($(CFG_RISCV_WITH_M_MODE_SM),y) $(call force,CFG_RISCV_SBI,y) endif # Disable unsupported and other arch-specific flags $(call force,CFG_CORE_FFA,n) $(call force,CFG_SECURE_PARTITION,n) $(call force,CFG_PAGED_USER_TA,n) $(call force,CFG_WITH_PAGER,n) $(call force,CFG_GIC,n) $(call force,CFG_ARM_GICV3,n) $(call force,CFG_WITH_VFP,n) $(call force,CFG_WITH_STMM_SP,n) $(call force,CFG_TA_BTI,n) # Enable generic timer $(call force,CFG_CORE_HAS_GENERIC_TIMER,y) core-platform-cppflags += -I$(arch-dir)/include core-platform-subdirs += \ $(addprefix $(arch-dir)/, kernel mm tee) $(platform-dir) # Default values for "-mcmodel", "-march", and "-abi" compiler flags. # Platform-specific overrides are in core/arch/riscv/plat-*/conf.mk. riscv-platform-mcmodel ?= medany rv64-platform-isa ?= rv64imafd rv64-platform-abi ?= lp64d rv32-platform-isa ?= rv32imafd rv32-platform-abi ?= ilp32d rv64-platform-cflags += -mcmodel=$(riscv-platform-mcmodel) rv64-platform-cflags += -march=$(rv64-platform-isa) -mabi=$(rv64-platform-abi) rv64-platform-cflags += -Wno-missing-include-dirs rv32-platform-cflags += -mcmodel=$(riscv-platform-mcmodel) rv32-platform-cflags += -march=$(rv32-platform-isa) -mabi=$(rv32-platform-abi) rv64-platform-cppflags += -DRV64=1 -D__LP64__=1 rv32-platform-cppflags += -DRV32=1 -D__ILP32__=1 platform-cflags-generic ?= -ffunction-sections -fdata-sections -pipe platform-aflags-generic ?= -pipe rv64-platform-cflags-generic := -mstrict-align $(call cc-option,) # Optimize for size by default, usually gives good performance too CFG_CC_OPT_LEVEL ?= 0 platform-cflags-optimization ?= -O$(CFG_CC_OPT_LEVEL) CFG_DEBUG_INFO ?= y ifeq ($(CFG_DEBUG_INFO),y) platform-cflags-debug-info ?= -g3 platform-aflags-debug-info ?= -g endif core-platform-cflags += $(platform-cflags-optimization) core-platform-cflags += $(platform-cflags-generic) core-platform-cflags += $(platform-cflags-debug-info) core-platform-aflags += $(platform-aflags-generic) core-platform-aflags += $(platform-aflags-debug-info) ifeq ($(CFG_CORE_ASLR),y) core-platform-cflags += -fpie endif ifeq ($(CFG_UNWIND),y) core-platform-cppflags += -fno-omit-frame-pointer core-platform-cflags += -fno-omit-frame-pointer endif ifeq ($(CFG_RV64_core),y) core-platform-cppflags += $(rv64-platform-cppflags) core-platform-cflags += $(rv64-platform-cflags) core-platform-cflags += $(rv64-platform-cflags-generic) core-platform-cflags += $(rv64-platform-cflags-no-hard-float) core-platform-aflags += $(rv64-platform-aflags) else core-platform-cppflags += $(rv32-platform-cppflags) core-platform-cflags += $(rv32-platform-cflags) core-platform-cflags += $(rv32-platform-cflags-no-hard-float) ifeq ($(CFG_UNWIND),y) core-platform-cflags += -funwind-tables endif core-platform-aflags += $(core_rv32-platform-aflags) core-platform-aflags += $(rv32-platform-aflags) endif # Provide default supported-ta-targets if not set by the platform config ifeq (,$(supported-ta-targets)) supported-ta-targets = ta_rv32 ifeq ($(CFG_RV64_core),y) supported-ta-targets += ta_rv64 endif endif ta-targets := $(if $(CFG_USER_TA_TARGETS),$(filter $(supported-ta-targets),$(CFG_USER_TA_TARGETS)),$(supported-ta-targets)) unsup-targets := $(filter-out $(ta-targets),$(CFG_USER_TA_TARGETS)) ifneq (,$(unsup-targets)) $(error CFG_USER_TA_TARGETS contains unsupported value(s): $(unsup-targets). Valid values: $(supported-ta-targets)) endif ifneq ($(filter ta_rv32,$(ta-targets)),) # Variables for ta-target/sm "ta_rv32" CFG_RV32_ta_rv32 := y arch-bits-ta_rv32 := 32 ta_rv32-platform-cppflags += $(rv32-platform-cppflags) ta_rv32-platform-cflags += $(rv32-platform-cflags) ta_rv32-platform-cflags += $(platform-cflags-optimization) ta_rv32-platform-cflags += $(platform-cflags-debug-info) ta_rv32-platform-cflags += -fpic ifeq ($(CFG_UNWIND),y) ta_rv32-platform-cflags += -fno-omit-frame-pointer ta_rv32-platform-cflags += -funwind-tables endif ta_rv32-platform-aflags += $(platform-aflags-generic) ta_rv32-platform-aflags += $(platform-aflags-debug-info) ta_rv32-platform-aflags += $(rv32-platform-aflags) ta_rv32-platform-cxxflags += -fpic ta_rv32-platform-cxxflags += $(rv32-platform-cxxflags) ta_rv32-platform-cxxflags += $(platform-cflags-optimization) ta_rv32-platform-cxxflags += $(platform-cflags-debug-info) ta-mk-file-export-vars-ta_rv32 += CFG_RV32_ta_rv32 ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-cppflags ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-cflags ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-aflags ta-mk-file-export-vars-ta_rv32 += ta_rv32-platform-cxxflags ta-mk-file-export-add-ta_rv32 += CROSS_COMPILE ?= riscv32-unknown-linux-gnu-_nl_ ta-mk-file-export-add-ta_rv32 += CROSS_COMPILE32 ?= $$(CROSS_COMPILE)_nl_ ta-mk-file-export-add-ta_rv32 += CROSS_COMPILE_ta_rv32 ?= $$(CROSS_COMPILE32)_nl_ ta-mk-file-export-add-ta_rv32 += COMPILER ?= gcc_nl_ ta-mk-file-export-add-ta_rv32 += COMPILER_ta_rv32 ?= $$(COMPILER)_nl_ ta-mk-file-export-add-ta_rv32 += PYTHON3 ?= python3_nl_ endif ifneq ($(filter ta_rv64,$(ta-targets)),) # Variables for ta-target/sm "ta_rv64" CFG_RV64_ta_rv64 := y arch-bits-ta_rv64 := 64 ta_rv64-platform-cppflags += $(rv64-platform-cppflags) ta_rv64-platform-cflags += $(rv64-platform-cflags) ta_rv64-platform-cflags += $(platform-cflags-optimization) ta_rv64-platform-cflags += $(platform-cflags-debug-info) ta_rv64-platform-cflags += -fpic ta_rv64-platform-cflags += $(rv64-platform-cflags-generic) ifeq ($(CFG_UNWIND),y) ta_rv64-platform-cflags += -fno-omit-frame-pointer endif ifeq ($(rv64-platform-hard-float-enabled),y) ta_rv64-platform-cflags += $(rv64-platform-cflags-hard-float) else ta_rv64-platform-cflags += $(rv64-platform-cflags-no-hard-float) endif ta_rv64-platform-aflags += $(platform-aflags-generic) ta_rv64-platform-aflags += $(platform-aflags-debug-info) ta_rv64-platform-aflags += $(rv64-platform-aflags) ta_rv64-platform-cxxflags += -fpic ta_rv64-platform-cxxflags += $(platform-cflags-optimization) ta_rv64-platform-cxxflags += $(platform-cflags-debug-info) ta-mk-file-export-vars-ta_rv64 += CFG_RV64_ta_rv64 ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-cppflags ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-cflags ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-aflags ta-mk-file-export-vars-ta_rv64 += ta_rv64-platform-cxxflags ta-mk-file-export-add-ta_rv64 += CROSS_COMPILE64 ?= $$(CROSS_COMPILE)_nl_ ta-mk-file-export-add-ta_rv64 += CROSS_COMPILE_ta_rv64 ?= $$(CROSS_COMPILE64)_nl_ ta-mk-file-export-add-ta_rv64 += COMPILER ?= gcc_nl_ ta-mk-file-export-add-ta_rv64 += COMPILER_ta_rv64 ?= $$(COMPILER)_nl_ ta-mk-file-export-add-ta_rv64 += PYTHON3 ?= python3_nl_ endif # Set cross compiler prefix for each TA target $(foreach sm, $(ta-targets), $(eval CROSS_COMPILE_$(sm) ?= $(CROSS_COMPILE$(arch-bits-$(sm))))) optee_os-4.3.0/core/arch/riscv/tee/000077500000000000000000000000001464416617300171175ustar00rootroot00000000000000optee_os-4.3.0/core/arch/riscv/tee/entry_fast.c000066400000000000000000000172621464416617300214510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2023 NXP * Copyright (c) 2015-2021, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #ifdef CFG_CORE_RESERVED_SHM static void tee_entry_get_shm_config(struct thread_abi_args *args) { args->a0 = OPTEE_ABI_RETURN_OK; args->a1 = default_nsec_shm_paddr; args->a2 = default_nsec_shm_size; /* Should this be TEEABI cache attributes instead? */ args->a3 = core_mmu_is_shm_cached(); } #endif static void tee_entry_fastcall_l2cc_mutex(struct thread_abi_args *args) { args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; } static void tee_entry_exchange_capabilities(struct thread_abi_args *args) { bool res_shm_en = IS_ENABLED(CFG_CORE_RESERVED_SHM); bool dyn_shm_en __maybe_unused = false; /* * Currently we ignore OPTEE_ABI_NSEC_CAP_UNIPROCESSOR. * * The memory mapping of shared memory is defined as normal * shared memory for SMP systems and normal memory for UP * systems. Currently we map all memory as shared in secure * world. * * When translation tables are created with shared bit cleared for * uniprocessor systems we'll need to check * OPTEE_ABI_NSEC_CAP_UNIPROCESSOR. */ if (args->a1 & ~OPTEE_ABI_NSEC_CAP_UNIPROCESSOR) { /* Unknown capability. */ args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; return; } args->a0 = OPTEE_ABI_RETURN_OK; args->a1 = 0; if (res_shm_en) args->a1 |= OPTEE_ABI_SEC_CAP_HAVE_RESERVED_SHM; IMSG("Reserved shared memory is %sabled", res_shm_en ? "en" : "dis"); #if defined(CFG_CORE_DYN_SHM) dyn_shm_en = core_mmu_nsec_ddr_is_defined(); if (dyn_shm_en) args->a1 |= OPTEE_ABI_SEC_CAP_DYNAMIC_SHM; #endif IMSG("Dynamic shared memory is %sabled", dyn_shm_en ? "en" : "dis"); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) args->a1 |= OPTEE_ABI_SEC_CAP_VIRTUALIZATION; IMSG("Normal World virtualization support is %sabled", IS_ENABLED(CFG_NS_VIRTUALIZATION) ? "en" : "dis"); args->a1 |= OPTEE_ABI_SEC_CAP_MEMREF_NULL; if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { args->a1 |= OPTEE_ABI_SEC_CAP_ASYNC_NOTIF; args->a2 = NOTIF_VALUE_MAX; } IMSG("Asynchronous notifications are %sabled", IS_ENABLED(CFG_CORE_ASYNC_NOTIF) ? "en" : "dis"); args->a1 |= OPTEE_ABI_SEC_CAP_RPC_ARG; args->a3 = THREAD_RPC_MAX_NUM_PARAMS; } static void tee_entry_disable_shm_cache(struct thread_abi_args *args) { uint64_t cookie; if (!thread_disable_prealloc_rpc_cache(&cookie)) { args->a0 = OPTEE_ABI_RETURN_EBUSY; return; } if (!cookie) { args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; return; } args->a0 = OPTEE_ABI_RETURN_OK; args->a1 = cookie >> 32; args->a2 = cookie; } static void tee_entry_enable_shm_cache(struct thread_abi_args *args) { if (thread_enable_prealloc_rpc_cache()) args->a0 = OPTEE_ABI_RETURN_OK; else args->a0 = OPTEE_ABI_RETURN_EBUSY; } static void tee_entry_boot_secondary(struct thread_abi_args *args) { #if defined(CFG_BOOT_SECONDARY_REQUEST) if (!boot_core_release(args->a1, (paddr_t)(args->a3))) args->a0 = OPTEE_ABI_RETURN_OK; else args->a0 = OPTEE_ABI_RETURN_EBADCMD; #else args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; #endif } static void tee_entry_get_thread_count(struct thread_abi_args *args) { args->a0 = OPTEE_ABI_RETURN_OK; args->a1 = CFG_NUM_THREADS; } #if defined(CFG_NS_VIRTUALIZATION) static void tee_entry_vm_created(struct thread_abi_args *args) { uint16_t guest_id = args->a1; /* Only hypervisor can issue this request */ if (args->a7 != HYP_CLNT_ID) { args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; return; } if (virt_guest_created(guest_id)) args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; else args->a0 = OPTEE_ABI_RETURN_OK; } static void tee_entry_vm_destroyed(struct thread_abi_args *args) { uint16_t guest_id = args->a1; /* Only hypervisor can issue this request */ if (args->a7 != HYP_CLNT_ID) { args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; return; } if (virt_guest_destroyed(guest_id)) args->a0 = OPTEE_ABI_RETURN_ENOTAVAIL; else args->a0 = OPTEE_ABI_RETURN_OK; } #endif /* Note: this function is weak to let platforms add special handling */ void __weak tee_entry_fast(struct thread_abi_args *args) { __tee_entry_fast(args); } static void get_async_notif_value(struct thread_abi_args *args) { bool value_valid = false; bool value_pending = false; args->a0 = OPTEE_ABI_RETURN_OK; args->a1 = notif_get_value(&value_valid, &value_pending); args->a2 = 0; if (value_valid) args->a2 |= OPTEE_ABI_ASYNC_NOTIF_VALID; if (value_pending) args->a2 |= OPTEE_ABI_ASYNC_NOTIF_PENDING; } /* * If tee_entry_fast() is overridden, it's still supposed to call this * function. */ void __tee_entry_fast(struct thread_abi_args *args) { switch (args->a0) { /* Generic functions */ case OPTEE_ABI_CALLS_COUNT: tee_entry_get_api_call_count(args); break; case OPTEE_ABI_CALLS_UID: tee_entry_get_api_uuid(args); break; case OPTEE_ABI_CALLS_REVISION: tee_entry_get_api_revision(args); break; case OPTEE_ABI_CALL_GET_OS_UUID: tee_entry_get_os_uuid(args); break; case OPTEE_ABI_CALL_GET_OS_REVISION: tee_entry_get_os_revision(args); break; /* OP-TEE specific ABI functions */ #ifdef CFG_CORE_RESERVED_SHM case OPTEE_ABI_GET_SHM_CONFIG: tee_entry_get_shm_config(args); break; #endif case OPTEE_ABI_L2CC_MUTEX: tee_entry_fastcall_l2cc_mutex(args); break; case OPTEE_ABI_EXCHANGE_CAPABILITIES: tee_entry_exchange_capabilities(args); break; case OPTEE_ABI_DISABLE_SHM_CACHE: tee_entry_disable_shm_cache(args); break; case OPTEE_ABI_ENABLE_SHM_CACHE: tee_entry_enable_shm_cache(args); break; case OPTEE_ABI_BOOT_SECONDARY: tee_entry_boot_secondary(args); break; case OPTEE_ABI_GET_THREAD_COUNT: tee_entry_get_thread_count(args); break; #if defined(CFG_NS_VIRTUALIZATION) case OPTEE_ABI_VM_CREATED: tee_entry_vm_created(args); break; case OPTEE_ABI_VM_DESTROYED: tee_entry_vm_destroyed(args); break; #endif case OPTEE_ABI_ENABLE_ASYNC_NOTIF: if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) { notif_deliver_atomic_event(NOTIF_EVENT_STARTED, 0); args->a0 = OPTEE_ABI_RETURN_OK; } else { args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; } break; case OPTEE_ABI_GET_ASYNC_NOTIF_VALUE: if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) get_async_notif_value(args); else args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; break; default: args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION; break; } } size_t tee_entry_generic_get_api_call_count(void) { /* * All the different calls handled in this file. If the specific * target has additional calls it will call this function and * add the number of calls the target has added. */ size_t ret = 12; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) ret += 2; return ret; } void __weak tee_entry_get_api_call_count(struct thread_abi_args *args) { args->a0 = tee_entry_generic_get_api_call_count(); } void __weak tee_entry_get_api_uuid(struct thread_abi_args *args) { args->a0 = OPTEE_MSG_UID_0; args->a1 = OPTEE_MSG_UID_1; args->a2 = OPTEE_MSG_UID_2; args->a3 = OPTEE_MSG_UID_3; } void __weak tee_entry_get_api_revision(struct thread_abi_args *args) { args->a0 = OPTEE_MSG_REVISION_MAJOR; args->a1 = OPTEE_MSG_REVISION_MINOR; } void __weak tee_entry_get_os_uuid(struct thread_abi_args *args) { args->a0 = OPTEE_MSG_OS_OPTEE_UUID_0; args->a1 = OPTEE_MSG_OS_OPTEE_UUID_1; args->a2 = OPTEE_MSG_OS_OPTEE_UUID_2; args->a3 = OPTEE_MSG_OS_OPTEE_UUID_3; } void __weak tee_entry_get_os_revision(struct thread_abi_args *args) { args->a0 = CFG_OPTEE_REVISION_MAJOR; args->a1 = CFG_OPTEE_REVISION_MINOR; args->a2 = TEE_IMPL_GIT_SHA1; } optee_os-4.3.0/core/arch/riscv/tee/sub.mk000066400000000000000000000001331464416617300202360ustar00rootroot00000000000000srcs-y += entry_fast.c cppflags-entry_fast.c-y += -DTEE_IMPL_GIT_SHA1=$(TEE_IMPL_GIT_SHA1) optee_os-4.3.0/core/core.mk000066400000000000000000000114121464416617300155570ustar00rootroot00000000000000include mk/cleanvars.mk # Set current submodule (used for module specific flags compile result etc) sm := core sm-$(sm) := y arch-dir := core/arch/$(ARCH) platform-dir := $(arch-dir)/plat-$(PLATFORM) include $(platform-dir)/conf.mk include mk/config.mk # $(ARCH).mk also sets the compiler for the core module include core/arch/$(ARCH)/$(ARCH).mk ifeq ($(CFG_OS_REV_REPORTS_GIT_SHA1),y) ifeq ($(arch-bits-core),64) git-sha1-len := 16 else git-sha1-len := 8 endif TEE_IMPL_GIT_SHA1 := 0x$(shell git rev-parse --short=$(git-sha1-len) HEAD 2>/dev/null || echo 0 | cut -c -$(git-sha1-len)) else TEE_IMPL_GIT_SHA1 := 0x0 endif PLATFORM_$(PLATFORM) := y PLATFORM_FLAVOR_$(PLATFORM_FLAVOR) := y $(eval $(call cfg-depends-all,CFG_PAGED_USER_TA,CFG_WITH_PAGER CFG_WITH_USER_TA)) _CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL ?= $(CFG_CORE_ASYNC_NOTIF) include core/crypto.mk ifeq ($(CFG_SCMI_SCPFW),y) include core/lib/scmi-server/conf.mk endif cppflags$(sm) += -D__KERNEL__ cppflags$(sm) += -Icore/include cppflags$(sm) += -include $(conf-file) cppflags$(sm) += -I$(out-dir)/core/include cppflags$(sm) += $(core-platform-cppflags) cflags$(sm) += $(core-platform-cflags) core-stackp-cflags-$(CFG_CORE_STACK_PROTECTOR) := -fstack-protector core-stackp-cflags-$(CFG_CORE_STACK_PROTECTOR_STRONG) := -fstack-protector-strong core-stackp-cflags-$(CFG_CORE_STACK_PROTECTOR_ALL) := -fstack-protector-all cflags$(sm) += $(core-stackp-cflags-y) ifeq ($(CFG_CORE_SANITIZE_UNDEFINED),y) cflags$(sm) += -fsanitize=undefined endif ifeq ($(CFG_CORE_SANITIZE_KADDRESS),y) ifeq ($(CFG_ASAN_SHADOW_OFFSET),) $(error error: CFG_CORE_SANITIZE_KADDRESS not supported by platform (flavor)) endif ifeq ($(COMPILER),clang) $(error error: CFG_CORE_SANITIZE_KADDRESS not supported with Clang) endif cflags_kasan += -fsanitize=kernel-address \ -fasan-shadow-offset=$(CFG_ASAN_SHADOW_OFFSET)\ --param asan-stack=1 --param asan-globals=1 \ --param asan-instrumentation-with-call-threshold=0 cflags$(sm) += $(cflags_kasan) endif ifeq ($(CFG_CORE_DEBUG_CHECK_STACKS),y) finstrument-functions := $(call cc-option,-finstrument-functions) ifeq (,$(finstrument-functions)) $(error -finstrument-functions not supported) endif cflags$(sm) += $(finstrument-functions) endif ifeq ($(CFG_SYSCALL_FTRACE),y) cflags$(sm) += -pg endif aflags$(sm) += $(core-platform-aflags) cppflags$(sm) += -DTRACE_LEVEL=$(CFG_TEE_CORE_LOG_LEVEL) ifeq ($(CFG_TEE_CORE_MALLOC_DEBUG),y) cppflags$(sm) += -DENABLE_MDBG=1 endif ifneq ($(CFG_TEE_CORE_DEBUG),y) cppflags$(sm) += -DNDEBUG endif cppflags$(sm) += -Ildelf/include cppflags$(sm) += -Ilib/libutee/include ifeq ($(filter y, $(CFG_CORE_DYN_SHM) $(CFG_CORE_RESERVED_SHM)),) $(error error: No shared memory configured) endif # Tell all libraries and sub-directories (included below) that we have a # configuration file conf-file := $(out-dir)/include/generated/conf.h conf-mk-file := $(out-dir)/conf.mk conf-cmake-file := $(out-dir)/conf.cmake $(conf-file): $(conf-mk-file) cleanfiles += $(conf-file) cleanfiles += $(conf-mk-file) cleanfiles += $(conf-cmake-file) $(conf-file): FORCE $(call check-conf-h) $(conf-mk-file): FORCE $(call check-conf-mk) $(conf-cmake-file): FORCE $(call check-conf-cmake) # # Do libraries # # Set a prefix to avoid conflicts with user TAs that will use the same # source but with different flags below base-prefix := $(sm)- libname = utils libdir = lib/libutils include mk/lib.mk # CFG_CRYPTOLIB_NAME must not be changed beyond this line CFG_CRYPTOLIB_NAME_$(CFG_CRYPTOLIB_NAME) := y ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt) # We're compiling mbedtls too, but with a limited configuration which only # provides the MPI routines libname = mbedtls libdir = lib/libmbedtls include mk/lib.mk endif #tomcrypt ifeq ($(CFG_CRYPTOLIB_NAME),mbedtls) $(call force,CFG_CRYPTO_RSASSA_NA1,n,not supported by mbedtls) libname = tomcrypt libdir = core/lib/libtomcrypt base-prefix := include mk/lib.mk base-prefix := $(sm)- endif ifeq ($(firstword $(subst /, ,$(CFG_CRYPTOLIB_DIR))),core) # If a library can be compiled for both core and user space a base-prefix # is needed in order to avoid conflicts in the output. However, if the # library resides under core then it can't be compiled to user space. base-prefix := endif libname = $(CFG_CRYPTOLIB_NAME) libdir = $(CFG_CRYPTOLIB_DIR) include mk/lib.mk base-prefix := libname = fdt libdir = core/lib/libfdt include mk/lib.mk ifeq ($(CFG_ZLIB),y) libname = zlib libdir = core/lib/zlib include mk/lib.mk endif libname = unw libdir = lib/libunw include mk/lib.mk ifeq ($(CFG_SCMI_SCPFW),y) libname = scmi-server libdir = core/lib/scmi-server include mk/lib.mk endif # # Do main source # subdirs = $(core-platform-subdirs) core include mk/subdir.mk include mk/compile.mk include $(if $(wildcard $(platform-dir)/link.mk), \ $(platform-dir)/link.mk, \ core/arch/$(ARCH)/kernel/link.mk) optee_os-4.3.0/core/crypto.mk000066400000000000000000000270561464416617300161620ustar00rootroot00000000000000CFG_CRYPTO ?= y # Select small code size in the crypto library if applicable (for instance # LibTomCrypt has -DLTC_SMALL_CODE) # Note: the compiler flag -Os is not set here but by CFG_CC_OPT_LEVEL CFG_CRYPTO_SIZE_OPTIMIZATION ?= y ifeq (y,$(CFG_CRYPTO)) ############################################################### # Platform crypto-driver configuration. It has a higher priority over the # generic crypto configuration below. ############################################################### CRYPTO_MAKEFILES := $(sort $(wildcard core/drivers/crypto/*/crypto.mk)) include $(CRYPTO_MAKEFILES) # Ciphers CFG_CRYPTO_AES ?= y CFG_CRYPTO_DES ?= y CFG_CRYPTO_SM4 ?= y # Cipher block modes CFG_CRYPTO_ECB ?= y CFG_CRYPTO_CBC ?= y CFG_CRYPTO_CTR ?= y CFG_CRYPTO_CTS ?= y CFG_CRYPTO_XTS ?= y # Message authentication codes CFG_CRYPTO_HMAC ?= y CFG_CRYPTO_CMAC ?= y CFG_CRYPTO_CBC_MAC ?= y # Instead of calling the AES CBC encryption function for each 16 byte block of # input, bundle a maximum of N blocks when possible. A maximum of N*16 bytes of # temporary data are allocated on the heap. # Minimum value is 1. CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS ?= 64 # Hashes CFG_CRYPTO_MD5 ?= y CFG_CRYPTO_SHA1 ?= y CFG_CRYPTO_SHA224 ?= y CFG_CRYPTO_SHA256 ?= y CFG_CRYPTO_SHA384 ?= y CFG_CRYPTO_SHA512 ?= y CFG_CRYPTO_SHA512_256 ?= y CFG_CRYPTO_SM3 ?= y CFG_CRYPTO_SHA3_224 ?= y CFG_CRYPTO_SHA3_256 ?= y CFG_CRYPTO_SHA3_384 ?= y CFG_CRYPTO_SHA3_512 ?= y # Extendable-Output Functions (XOF) CFG_CRYPTO_SHAKE128 ?= y CFG_CRYPTO_SHAKE256 ?= y # Asymmetric ciphers CFG_CRYPTO_DSA ?= y CFG_CRYPTO_RSA ?= y CFG_CRYPTO_DH ?= y # ECC includes ECDSA and ECDH CFG_CRYPTO_ECC ?= y CFG_CRYPTO_SM2_PKE ?= y CFG_CRYPTO_SM2_DSA ?= y CFG_CRYPTO_SM2_KEP ?= y CFG_CRYPTO_ED25519 ?= y CFG_CRYPTO_X25519 ?= y # Authenticated encryption CFG_CRYPTO_CCM ?= y CFG_CRYPTO_GCM ?= y # Default uses the OP-TEE internal AES-GCM implementation CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB ?= n endif # PRNG configuration # If CFG_WITH_SOFTWARE_PRNG is enabled, crypto provider provided # software PRNG implementation is used. # Otherwise, you need to implement hw_get_random_bytes() for your platform CFG_WITH_SOFTWARE_PRNG ?= y # Define the maximum size, in bits, for big numbers in the TEE core (privileged # layer). # This value is an upper limit for the key size in any cryptographic algorithm # implemented by the TEE core. # Set this to a lower value to reduce the memory footprint. CFG_CORE_BIGNUM_MAX_BITS ?= 4096 ifeq ($(CFG_WITH_PAGER),y) ifneq ($(CFG_CRYPTO_SHA256),y) $(warning Warning: Enabling CFG_CRYPTO_SHA256 [required by CFG_WITH_PAGER]) CFG_CRYPTO_SHA256:=y endif endif $(eval $(call cryp-enable-all-depends,CFG_WITH_SOFTWARE_PRNG, AES ECB SHA256)) ifeq ($(CFG_CRYPTO_WITH_CE82),y) $(call force,CFG_CRYPTO_WITH_CE,y,required with CFG_CRYPTO_WITH_CE82) CFG_CRYPTO_SHA512_ARM_CE ?= $(CFG_CRYPTO_SHA512) CFG_CORE_CRYPTO_SHA512_ACCEL ?= $(CFG_CRYPTO_SHA512_ARM_CE) CFG_CRYPTO_SHA3_ARM_CE ?= $(call cfg-one-enabled, CFG_CRYPTO_SHA3_224 \ CFG_CRYPTO_SHA3_256 CFG_CRYPTO_SHA3_384 \ CFG_CRYPTO_SHA3_512 CFG_CRYPTO_SHAKE128 \ CFG_CRYPTO_SHAKE256) CFG_CORE_CRYPTO_SHA3_ACCEL ?= $(CFG_CRYPTO_SHA3_ARM_CE) CFG_CRYPTO_SM3_ARM_CE ?= $(CFG_CRYPTO_SM3) CFG_CORE_CRYPTO_SM3_ACCEL ?= $(CFG_CRYPTO_SM3_ARM_CE) # CFG_CRYPTO_SM4_ARM_CE defines whether we use SM4E to optimize SM4 CFG_CRYPTO_SM4_ARM_CE ?= $(CFG_CRYPTO_SM4) CFG_CORE_CRYPTO_SM4_ACCEL ?= $(CFG_CRYPTO_SM4_ARM_CE) endif ifeq ($(CFG_CRYPTO_WITH_CE),y) $(call force,CFG_AES_GCM_TABLE_BASED,n,conflicts with CFG_CRYPTO_WITH_CE) # CFG_HWSUPP_PMULT_64 defines whether the CPU supports polynomial multiplies # of 64-bit values (Aarch64: PMULL/PMULL2 with the 1Q specifier; Aarch32: # VMULL.P64). These operations are part of the Cryptographic Extensions, so # assume they are implicitly contained in CFG_CRYPTO_WITH_CE=y. CFG_HWSUPP_PMULT_64 ?= y CFG_CRYPTO_SHA256_ARM_CE ?= $(CFG_CRYPTO_SHA256) CFG_CORE_CRYPTO_SHA256_ACCEL ?= $(CFG_CRYPTO_SHA256_ARM_CE) CFG_CRYPTO_SHA1_ARM_CE ?= $(CFG_CRYPTO_SHA1) CFG_CORE_CRYPTO_SHA1_ACCEL ?= $(CFG_CRYPTO_SHA1_ARM_CE) CFG_CRYPTO_AES_ARM_CE ?= $(CFG_CRYPTO_AES) CFG_CORE_CRYPTO_AES_ACCEL ?= $(CFG_CRYPTO_AES_ARM_CE) # CFG_CRYPTO_SM4_ARM_AESE defines whether we use AESE to optimize SM4 CFG_CRYPTO_SM4_ARM_AESE ?= $(CFG_CRYPTO_SM4) CFG_CORE_CRYPTO_SM4_ACCEL ?= $(CFG_CRYPTO_SM4_ARM_AESE) else #CFG_CRYPTO_WITH_CE CFG_AES_GCM_TABLE_BASED ?= y endif #!CFG_CRYPTO_WITH_CE # Cryptographic extensions can only be used safely when OP-TEE knows how to # preserve the VFP context ifeq ($(CFG_CRYPTO_SHA256_ARM32_CE),y) $(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_SHA256_ARM32_CE) endif ifeq ($(CFG_CRYPTO_SHA256_ARM64_CE),y) $(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_SHA256_ARM64_CE) endif ifeq ($(CFG_CRYPTO_SHA1_ARM_CE),y) $(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_SHA1_ARM_CE) endif ifeq ($(CFG_CRYPTO_AES_ARM_CE),y) $(call force,CFG_WITH_VFP,y,required by CFG_CRYPTO_AES_ARM_CE) endif ifeq ($(CFG_CORE_CRYPTO_SM4_ACCEL),y) $(call force,CFG_WITH_VFP,y,required by CFG_CORE_CRYPTO_SM4_ACCEL) endif cryp-enable-all-depends = $(call cfg-enable-all-depends,$(strip $(1)),$(foreach v,$(2),CFG_CRYPTO_$(v))) $(eval $(call cryp-enable-all-depends,CFG_REE_FS, AES ECB CTR HMAC SHA256 GCM)) $(eval $(call cryp-enable-all-depends,CFG_RPMB_FS, AES ECB CTR HMAC SHA256 GCM)) # Dependency checks: warn and disable some features if dependencies are not met cryp-dep-one = $(call cfg-depends-one,CFG_CRYPTO_$(strip $(1)),$(patsubst %, CFG_CRYPTO_%,$(strip $(2)))) cryp-dep-all = $(call cfg-depends-all,CFG_CRYPTO_$(strip $(1)),$(patsubst %, CFG_CRYPTO_%,$(strip $(2)))) $(eval $(call cryp-dep-one, ECB, AES DES)) $(eval $(call cryp-dep-one, CBC, AES DES)) $(eval $(call cryp-dep-one, CTR, AES)) # CTS is implemented with ECB and CBC $(eval $(call cryp-dep-all, CTS, AES ECB CBC)) $(eval $(call cryp-dep-one, XTS, AES)) $(eval $(call cryp-dep-one, HMAC, AES DES)) $(eval $(call cryp-dep-one, HMAC, MD5 SHA1 SHA224 SHA256 SHA384 SHA512)) $(eval $(call cryp-dep-one, CMAC, AES)) $(eval $(call cryp-dep-one, CBC_MAC, AES DES)) $(eval $(call cryp-dep-one, CCM, AES)) $(eval $(call cryp-dep-one, GCM, AES)) # If no AES cipher mode is left, disable AES $(eval $(call cryp-dep-one, AES, ECB CBC CTR CTS XTS)) # If no DES cipher mode is left, disable DES $(eval $(call cryp-dep-one, DES, ECB CBC)) # SM2 is Elliptic Curve Cryptography, it uses some generic ECC functions $(eval $(call cryp-dep-one, SM2_PKE, ECC)) $(eval $(call cryp-dep-one, SM2_DSA, ECC)) $(eval $(call cryp-dep-one, SM2_KEP, ECC)) ############################################################### # libtomcrypt (LTC) specifics, phase #1 # LTC is only configured via _CFG_CORE_LTC_ prefixed variables # # _CFG_CORE_LTC_xxx_DESC means that LTC will only register the # descriptor of the algorithm, not provide a # crypt_xxx_alloc_ctx() function. ############################################################### # If LTC is the cryptolib, pull configuration from CFG_CRYPTO_xxx ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt) # dsa_make_params() needs all three SHA-2 algorithms. # Disable DSA if any is missing. $(eval $(call cryp-dep-all, DSA, SHA256 SHA384 SHA512)) # Assign _CFG_CORE_LTC_xxx based on CFG_CRYPTO_yyy core-ltc-vars = AES DES core-ltc-vars += ECB CBC CTR CTS XTS core-ltc-vars += MD5 SHA1 SHA224 SHA256 SHA384 SHA512 SHA512_256 core-ltc-vars += SHA3_224 SHA3_256 SHA3_384 SHA3_512 SHAKE128 SHAKE256 core-ltc-vars += HMAC CMAC CBC_MAC core-ltc-vars += CCM ifeq ($(CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB),y) core-ltc-vars += GCM endif core-ltc-vars += RSA DSA DH ECC core-ltc-vars += SIZE_OPTIMIZATION core-ltc-vars += SM2_PKE core-ltc-vars += SM2_DSA core-ltc-vars += SM2_KEP core-ltc-vars += ED25519 X25519 # Assigned selected CFG_CRYPTO_xxx as _CFG_CORE_LTC_xxx $(foreach v, $(core-ltc-vars), $(eval _CFG_CORE_LTC_$(v) := $(CFG_CRYPTO_$(v)))) _CFG_CORE_LTC_MPI := $(CFG_CORE_MBEDTLS_MPI) _CFG_CORE_LTC_AES_ACCEL := $(CFG_CORE_CRYPTO_AES_ACCEL) _CFG_CORE_LTC_SHA1_ACCEL := $(CFG_CORE_CRYPTO_SHA1_ACCEL) _CFG_CORE_LTC_SHA256_ACCEL := $(CFG_CORE_CRYPTO_SHA256_ACCEL) _CFG_CORE_LTC_SHA512_ACCEL := $(CFG_CORE_CRYPTO_SHA512_ACCEL) _CFG_CORE_LTC_SHA3_ACCEL := $(CFG_CORE_CRYPTO_SHA3_ACCEL) endif ############################################################### # mbedtls specifics ############################################################### ifeq ($(CFG_CRYPTOLIB_NAME),mbedtls) # mbedtls has to be complemented with some algorithms by LTC # Specify the algorithms here _CFG_CORE_LTC_DSA := $(CFG_CRYPTO_DSA) _CFG_CORE_LTC_MPI := $(CFG_CRYPTO_DSA) _CFG_CORE_LTC_SHA256_DESC := $(CFG_CRYPTO_DSA) _CFG_CORE_LTC_SHA384_DESC := $(CFG_CRYPTO_DSA) _CFG_CORE_LTC_SHA512_DESC := $(CFG_CRYPTO_DSA) _CFG_CORE_LTC_XTS := $(CFG_CRYPTO_XTS) _CFG_CORE_LTC_CCM := $(CFG_CRYPTO_CCM) _CFG_CORE_LTC_AES := $(call cfg-one-enabled, CFG_CRYPTO_XTS CFG_CRYPTO_CCM \ CFG_CRYPTO_AES) _CFG_CORE_LTC_AES_ACCEL := $(CFG_CORE_CRYPTO_AES_ACCEL) _CFG_CORE_LTC_X25519 := $(CFG_CRYPTO_X25519) _CFG_CORE_LTC_ED25519 := $(CFG_CRYPTO_ED25519) _CFG_CORE_LTC_SHA3_224 := $(CFG_CRYPTO_SHA3_224) _CFG_CORE_LTC_SHA3_256 := $(CFG_CRYPTO_SHA3_256) _CFG_CORE_LTC_SHA3_384 := $(CFG_CRYPTO_SHA3_384) _CFG_CORE_LTC_SHA3_512 := $(CFG_CRYPTO_SHA3_512) _CFG_CORE_LTC_SHAKE128 := $(CFG_CRYPTO_SHAKE128) _CFG_CORE_LTC_SHAKE256 := $(CFG_CRYPTO_SHAKE256) endif ############################################################### # libtomcrypt (LTC) specifics, phase #2 ############################################################### _CFG_CORE_LTC_MD5_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_MD5_DESC \ _CFG_CORE_LTC_MD5) _CFG_CORE_LTC_SHA1_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA1_DESC \ _CFG_CORE_LTC_SHA1) _CFG_CORE_LTC_SHA224_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA224_DESC \ _CFG_CORE_LTC_SHA224) _CFG_CORE_LTC_SHA256_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA256_DESC \ _CFG_CORE_LTC_SHA224 \ _CFG_CORE_LTC_SHA256) _CFG_CORE_LTC_SHA384_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA384_DESC \ _CFG_CORE_LTC_SHA384) _CFG_CORE_LTC_SHA512_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA512_DESC \ _CFG_CORE_LTC_SHA512_256 \ _CFG_CORE_LTC_SHA512) _CFG_CORE_LTC_AES_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_AES_DESC \ _CFG_CORE_LTC_AES) _CFG_CORE_LTC_SHA3_DESC := $(call cfg-one-enabled, _CFG_CORE_LTC_SHA3_224 \ _CFG_CORE_LTC_SHA3_256 _CFG_CORE_LTC_SHA3_384 \ _CFG_CORE_LTC_SHA3_512 _CFG_CORE_LTC_SHAKE128 \ _CFG_CORE_LTC_SHAKE256) # Assign system variables _CFG_CORE_LTC_CE := $(CFG_CRYPTO_WITH_CE) _CFG_CORE_LTC_VFP := $(CFG_WITH_VFP) _CFG_CORE_LTC_BIGNUM_MAX_BITS := $(CFG_CORE_BIGNUM_MAX_BITS) _CFG_CORE_LTC_PAGER := $(CFG_WITH_PAGER) ifneq ($(CFG_NUM_THREADS),1) _CFG_CORE_LTC_OPTEE_THREAD := y else _CFG_CORE_LTC_OPTEE_THREAD := n endif _CFG_CORE_LTC_HWSUPP_PMULL := $(CFG_HWSUPP_PMULL) # Assign aggregated variables ltc-one-enabled = $(call cfg-one-enabled,$(foreach v,$(1),_CFG_CORE_LTC_$(v))) _CFG_CORE_LTC_ACIPHER := $(call ltc-one-enabled, RSA DSA DH ECC) _CFG_CORE_LTC_HASH := $(call ltc-one-enabled, MD5 SHA1 SHA224 SHA256 SHA384 \ SHA512 SHA3_224 SHA3_256 \ SHA3_384 SHA3_512) ifeq ($(CFG_CRYPTO_HMAC),y) _CFG_CORE_LTC_HMAC := $(call ltc-one-enabled, MD5 SHA1 SHA224 SHA256 SHA384 \ SHA512 SHA3_224 SHA3_256 \ SHA3_384 SHA3_512) endif _CFG_CORE_LTC_CBC := $(call ltc-one-enabled, CBC CBC_MAC) _CFG_CORE_LTC_ASN1 := $(call ltc-one-enabled, RSA DSA ECC) _CFG_CORE_LTC_EC25519 := $(call ltc-one-enabled, ED25519 X25519) # Enable TEE_ALG_RSASSA_PKCS1_V1_5 algorithm for signing with PKCS#1 v1.5 EMSA # without ASN.1 around the hash. ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt) CFG_CRYPTO_RSASSA_NA1 ?= y endif optee_os-4.3.0/core/crypto/000077500000000000000000000000001464416617300156175ustar00rootroot00000000000000optee_os-4.3.0/core/crypto/aes-cts.c000066400000000000000000000155471464416617300173360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include /* From libtomcrypt doc: * Ciphertext stealing is a method of dealing with messages * in CBC mode which are not a multiple of the block * length. This is accomplished by encrypting the last * ciphertext block in ECB mode, and XOR'ing the output * against the last partial block of plaintext. LibTomCrypt * does not support this mode directly but it is fairly * easy to emulate with a call to the cipher's * ecb encrypt() callback function. * The more sane way to deal with partial blocks is to pad * them with zeroes, and then use CBC normally */ /* * From Global Platform: CTS = CBC-CS3 */ struct cts_ctx { struct crypto_cipher_ctx ctx; struct crypto_cipher_ctx *ecb; struct crypto_cipher_ctx *cbc; TEE_OperationMode mode; }; static const struct crypto_cipher_ops cts_ops; static struct cts_ctx *to_cts_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &cts_ops); return container_of(ctx, struct cts_ctx, ctx); } static TEE_Result cts_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len) { TEE_Result res = TEE_SUCCESS; struct cts_ctx *c = to_cts_ctx(ctx); c->mode = mode; res = crypto_cipher_init(c->ecb, mode, key1, key1_len, key2, key2_len, iv, iv_len); if (res) return res; return crypto_cipher_init(c->cbc, mode, key1, key1_len, key2, key2_len, iv, iv_len); } /* * From http://en.wikipedia.org/wiki/Ciphertext_stealing * CBC ciphertext stealing encryption using a standard * CBC interface: * 1. Pad the last partial plaintext block with 0. * 2. Encrypt the whole padded plaintext using the * standard CBC mode. * 3. Swap the last two ciphertext blocks. * 4. Truncate the ciphertext to the length of the * original plaintext. * * CBC ciphertext stealing decryption using a standard * CBC interface * 1. Dn = Decrypt (K, Cn-1). Decrypt the second to last * ciphertext block. * 2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the * nearest multiple of the block size using the last * B-M bits of block cipher decryption of the * second-to-last ciphertext block. * 3. Swap the last two ciphertext blocks. * 4. Decrypt the (modified) ciphertext using the standard * CBC mode. * 5. Truncate the plaintext to the length of the original * ciphertext. */ static TEE_Result cbc_cts_update(void *cbc_ctx, void *ecb_ctx, TEE_OperationMode mode, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { TEE_Result res = TEE_SUCCESS; uint8_t tmp2_block[64] = { 0 }; uint8_t tmp_block[64] = { 0 }; int len_last_block = 0; int block_size = 16; int nb_blocks = 0; if (!last_block) return tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, mode, last_block, data, len, dst); /* Compute the last block length and check constraints */ nb_blocks = (len + block_size - 1) / block_size; if (nb_blocks < 2) return TEE_ERROR_BAD_STATE; len_last_block = len % block_size; if (len_last_block == 0) len_last_block = block_size; if (mode == TEE_MODE_ENCRYPT) { memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), len_last_block); memset(tmp_block + len_last_block, 0, block_size - len_last_block); res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, mode, 0, data, (nb_blocks - 1) * block_size, dst); if (res != TEE_SUCCESS) return res; memcpy(dst + (nb_blocks - 1) * block_size, dst + (nb_blocks - 2) * block_size, len_last_block); res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, mode, 0, tmp_block, block_size, dst + (nb_blocks - 2) * block_size); if (res != TEE_SUCCESS) return res; } else { /* 1. Decrypt the second to last ciphertext block */ res = tee_do_cipher_update(ecb_ctx, TEE_ALG_AES_ECB_NOPAD, mode, 0, data + (nb_blocks - 2) * block_size, block_size, tmp2_block); if (res != TEE_SUCCESS) return res; /* 2. Cn = Cn || Tail (Dn, B-M) */ memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), len_last_block); memcpy(tmp_block + len_last_block, tmp2_block + len_last_block, block_size - len_last_block); /* 3. Swap the last two ciphertext blocks */ /* done by passing the correct buffers in step 4. */ /* 4. Decrypt the (modified) ciphertext */ if (nb_blocks > 2) { res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, mode, 0, data, (nb_blocks - 2) * block_size, dst); if (res != TEE_SUCCESS) return res; } res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, mode, 0, tmp_block, block_size, dst + ((nb_blocks - 2) * block_size)); if (res != TEE_SUCCESS) return res; res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, mode, 0, data + ((nb_blocks - 2) * block_size), block_size, tmp_block); if (res != TEE_SUCCESS) return res; /* 5. Truncate the plaintext */ memcpy(dst + (nb_blocks - 1) * block_size, tmp_block, len_last_block); } return TEE_SUCCESS; } static TEE_Result cts_update(struct crypto_cipher_ctx *ctx, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { struct cts_ctx *c = to_cts_ctx(ctx); return cbc_cts_update(c->cbc, c->ecb, c->mode, last_block, data, len, dst); } static void cts_final(struct crypto_cipher_ctx *ctx) { struct cts_ctx *c = to_cts_ctx(ctx); crypto_cipher_final(c->cbc); crypto_cipher_final(c->ecb); } static void cts_free_ctx(struct crypto_cipher_ctx *ctx) { struct cts_ctx *c = to_cts_ctx(ctx); crypto_cipher_free_ctx(c->cbc); crypto_cipher_free_ctx(c->ecb); free(c); } static void cts_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct cts_ctx *src = to_cts_ctx(src_ctx); struct cts_ctx *dst = to_cts_ctx(dst_ctx); crypto_cipher_copy_state(dst->cbc, src->cbc); crypto_cipher_copy_state(dst->ecb, src->ecb); dst->mode = src->mode; } static const struct crypto_cipher_ops cts_ops = { .init = cts_init, .update = cts_update, .final = cts_final, .free_ctx = cts_free_ctx, .copy_state = cts_copy_state, }; TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx) { TEE_Result res = TEE_SUCCESS; struct cts_ctx *c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_aes_ecb_alloc_ctx(&c->ecb); if (res) goto err; res = crypto_aes_cbc_alloc_ctx(&c->cbc); if (res) goto err; c->ctx.ops = &cts_ops; *ctx = &c->ctx; return TEE_SUCCESS; err: crypto_cipher_free_ctx(c->ecb); free(c); return res; } optee_os-4.3.0/core/crypto/aes-gcm-ghash-tbl.c000066400000000000000000000073171464416617300211560ustar00rootroot00000000000000// SPDX-License-Identifier: Apache-2.0 /* * Copyright (c) 2017-2020, Linaro Limited * * NIST SP800-38D compliant GCM implementation * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include /* * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf * * See also: * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/ gcm-revised-spec.pdf * * We use the algorithm described as Shoup's method with 4-bit tables in * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. */ /* * Precompute small multiples of H, that is set * HH[i] || HL[i] = H times i, * where i is seen as a field element as in [MGV], ie high-order bits * correspond to low powers of P. The result is stored in the same way, that * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL * corresponds to P^127. */ void internal_aes_gcm_ghash_gen_tbl(struct internal_ghash_key *ghash_key, const struct internal_aes_gcm_key *ek) { int i, j; uint64_t vl, vh; unsigned char h[16]; memset(h, 0, 16); crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, h, h); vh = get_be64(h); vl = get_be64(h + 8); /* 8 = 1000 corresponds to 1 in GF(2^128) */ ghash_key->HL[8] = vl; ghash_key->HH[8] = vh; /* 0 corresponds to 0 in GF(2^128) */ ghash_key->HH[0] = 0; ghash_key->HL[0] = 0; for (i = 4; i > 0; i >>= 1) { uint32_t T = (vl & 1) * 0xe1000000U; vl = (vh << 63) | (vl >> 1); vh = (vh >> 1) ^ ((uint64_t)T << 32); ghash_key->HL[i] = vl; ghash_key->HH[i] = vh; } for (i = 2; i <= 8; i *= 2) { uint64_t *HiL = ghash_key->HL + i; uint64_t *HiH = ghash_key->HH + i; vh = *HiH; vl = *HiL; for (j = 1; j < i; j++) { HiH[j] = vh ^ ghash_key->HH[j]; HiL[j] = vl ^ ghash_key->HL[j]; } } } /* * Shoup's method for multiplication use this table with * last4[x] = x times P^128 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] */ static const uint64_t last4[16] = { 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 }; /* * Sets output to x times H using the precomputed tables. * x and output are seen as elements of GF(2^128) as in [MGV]. */ void internal_aes_gcm_ghash_mult_tbl(struct internal_ghash_key *ghash_key, const unsigned char x[16], unsigned char output[16]) { int i = 0; unsigned char lo = 0, hi = 0, rem = 0; uint64_t zh = 0, zl = 0; lo = x[15] & 0xf; zh = ghash_key->HH[lo]; zl = ghash_key->HL[lo]; for (i = 15; i >= 0; i--) { lo = x[i] & 0xf; hi = x[i] >> 4; if (i != 15) { rem = (unsigned char)zl & 0xf; zl = (zh << 60) | (zl >> 4); zh = (zh >> 4); zh ^= (uint64_t)last4[rem] << 48; zh ^= ghash_key->HH[lo]; zl ^= ghash_key->HL[lo]; } rem = (unsigned char)zl & 0xf; zl = (zh << 60) | (zl >> 4); zh = (zh >> 4); zh ^= (uint64_t)last4[rem] << 48; zh ^= ghash_key->HH[hi]; zl ^= ghash_key->HL[hi]; } put_be64(output, zh); put_be64(output + 8, zl); } optee_os-4.3.0/core/crypto/aes-gcm-sw.c000066400000000000000000000074771464416617300177450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek) { #ifdef CFG_AES_GCM_TABLE_BASED internal_aes_gcm_ghash_gen_tbl(&state->ghash_key, ek); #else crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, state->ctr, state->ghash_key.hash_subkey); #endif } static void ghash_update_block(struct internal_aes_gcm_state *state, const void *data) { void *y = state->hash_state; internal_aes_gcm_xor_block(y, data); #ifdef CFG_AES_GCM_TABLE_BASED internal_aes_gcm_ghash_mult_tbl(&state->ghash_key, y, y); #else internal_aes_gcm_gfmul(state->ghash_key.hash_subkey, y, y); #endif } void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, const void *head, const void *data, size_t num_blocks) { size_t n = 0; if (head) ghash_update_block(state, head); if (data) for (n = 0; n < num_blocks; n++) ghash_update_block(state, (const uint8_t *)data + n * TEE_AES_BLOCK_SIZE); } static void encrypt_block(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key, const uint64_t src[2], uint64_t dst[2]) { void *buf_cryp = state->buf_cryp; internal_aes_gcm_xor_block(buf_cryp, src); internal_aes_gcm_ghash_update(state, buf_cryp, NULL, 0); memcpy(dst, buf_cryp, sizeof(state->buf_cryp)); crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), enc_key->rounds, state->ctr, state->buf_cryp); internal_aes_gcm_inc_ctr(state); } static void encrypt_pl(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, const uint8_t *src, size_t num_blocks, uint8_t *dst) { size_t n = 0; if (IS_ALIGNED_WITH_TYPE(src, uint64_t)) { for (n = 0; n < num_blocks; n++) { const void *s = src + n * TEE_AES_BLOCK_SIZE; void *d = dst + n * TEE_AES_BLOCK_SIZE; encrypt_block(state, ek, s, d); } } else { for (n = 0; n < num_blocks; n++) { uint64_t tmp[2] = { 0 }; void *d = dst + n * TEE_AES_BLOCK_SIZE; memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp)); encrypt_block(state, ek, tmp, d); } } } static void decrypt_block(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key, const uint64_t src[2], uint64_t dst[2]) { void *buf_cryp = state->buf_cryp; crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), enc_key->rounds, state->ctr, buf_cryp); internal_aes_gcm_inc_ctr(state); internal_aes_gcm_xor_block(buf_cryp, src); internal_aes_gcm_ghash_update(state, src, NULL, 0); memcpy(dst, buf_cryp, sizeof(state->buf_cryp)); } static void decrypt_pl(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, const uint8_t *src, size_t num_blocks, uint8_t *dst) { size_t n = 0; if (IS_ALIGNED_WITH_TYPE(src, uint64_t)) { for (n = 0; n < num_blocks; n++) { const void *s = src + n * TEE_AES_BLOCK_SIZE; void *d = dst + n * TEE_AES_BLOCK_SIZE; decrypt_block(state, ek, s, d); } } else { for (n = 0; n < num_blocks; n++) { uint64_t tmp[2] = { 0 }; void *d = dst + n * TEE_AES_BLOCK_SIZE; memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp)); decrypt_block(state, ek, tmp, d); } } } void internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, TEE_OperationMode m, const void *src, size_t num_blocks, void *dst) { assert(!state->buf_pos && num_blocks); if (m == TEE_MODE_ENCRYPT) encrypt_pl(state, ek, src, num_blocks, dst); else decrypt_pl(state, ek, src, num_blocks, dst); } optee_os-4.3.0/core/crypto/aes-gcm.c000066400000000000000000000341711464416617300173050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include static void xor_buf(uint8_t *dst, const uint8_t *src, size_t len) { size_t n; for (n = 0; n < len; n++) dst[n] ^= src[n]; } static void ghash_update_pad_zero(struct internal_aes_gcm_state *state, const uint8_t *data, size_t len) { size_t n = len / TEE_AES_BLOCK_SIZE; uint64_t block[2]; if (n) { if (internal_aes_gcm_ptr_is_block_aligned(data)) { internal_aes_gcm_ghash_update(state, NULL, data, n); } else { size_t m; for (m = 0; m < n; m++) { memcpy(block, data + m * sizeof(block), sizeof(block)); internal_aes_gcm_ghash_update(state, NULL, (void *)block, 1); } } } if (len - n * TEE_AES_BLOCK_SIZE) { memset(block, 0, sizeof(block)); memcpy(block, data + n * TEE_AES_BLOCK_SIZE, len - n * TEE_AES_BLOCK_SIZE); internal_aes_gcm_ghash_update(state, block, NULL, 0); } } static void ghash_update_lengths(struct internal_aes_gcm_state *state, uint32_t l1, uint32_t l2) { uint64_t len_fields[2] = { TEE_U64_TO_BIG_ENDIAN(l1 * 8), TEE_U64_TO_BIG_ENDIAN(l2 * 8) }; COMPILE_TIME_ASSERT(sizeof(len_fields) == TEE_AES_BLOCK_SIZE); internal_aes_gcm_ghash_update(state, (uint8_t *)len_fields, NULL, 0); } static TEE_Result __gcm_init(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, TEE_OperationMode mode, const void *nonce, size_t nonce_len, size_t tag_len) { COMPILE_TIME_ASSERT(sizeof(state->ctr) == TEE_AES_BLOCK_SIZE); if (tag_len > sizeof(state->buf_tag)) return TEE_ERROR_BAD_PARAMETERS; memset(state, 0, sizeof(*state)); state->tag_len = tag_len; internal_aes_gcm_set_key(state, ek); if (nonce_len == (96 / 8)) { memcpy(state->ctr, nonce, nonce_len); internal_aes_gcm_inc_ctr(state); } else { ghash_update_pad_zero(state, nonce, nonce_len); ghash_update_lengths(state, 0, nonce_len); memcpy(state->ctr, state->hash_state, sizeof(state->ctr)); memset(state->hash_state, 0, sizeof(state->hash_state)); } crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, state->ctr, state->buf_tag); internal_aes_gcm_inc_ctr(state); if (mode == TEE_MODE_ENCRYPT) { /* * Encryption uses the pre-encrypted xor-buffer to encrypt * while decryption encrypts the xor-buffer when needed * instead. * * The reason for this is that the combined encryption and * ghash implementation does both operations intertwined. * In the decrypt case the xor-buffer is needed at the end * of processing each block, while the encryption case * needs xor-buffer before processing each block. * * In a pure software implementation we wouldn't have any * use for this kind of optimization, but since this * AES-GCM implementation is aimed at being combined with * accelerated routines it's more convenient to always have * this optimization activated. */ crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, state->ctr, state->buf_cryp); internal_aes_gcm_inc_ctr(state); } return TEE_SUCCESS; } TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx, TEE_OperationMode mode, const void *key, size_t key_len, const void *nonce, size_t nonce_len, size_t tag_len) { TEE_Result res = TEE_SUCCESS; struct internal_aes_gcm_key *ek = &ctx->key; res = crypto_aes_expand_enc_key(key, key_len, ek->data, sizeof(ek->data), &ek->rounds); if (res) return res; return __gcm_init(&ctx->state, ek, mode, nonce, nonce_len, tag_len); } static TEE_Result __gcm_update_aad(struct internal_aes_gcm_state *state, const void *data, size_t len) { const uint8_t *d = data; size_t l = len; const uint8_t *head = NULL; size_t n; if (state->payload_bytes) return TEE_ERROR_BAD_PARAMETERS; state->aad_bytes += len; while (l) { if (state->buf_pos || !internal_aes_gcm_ptr_is_block_aligned(d) || l < TEE_AES_BLOCK_SIZE) { n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l); memcpy(state->buf_hash + state->buf_pos, d, n); state->buf_pos += n; if (state->buf_pos != TEE_AES_BLOCK_SIZE) return TEE_SUCCESS; state->buf_pos = 0; head = state->buf_hash; d += n; l -= n; } if (internal_aes_gcm_ptr_is_block_aligned(d)) n = l / TEE_AES_BLOCK_SIZE; else n = 0; internal_aes_gcm_ghash_update(state, head, d, n); l -= n * TEE_AES_BLOCK_SIZE; d += n * TEE_AES_BLOCK_SIZE; } return TEE_SUCCESS; } TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx, const void *data, size_t len) { return __gcm_update_aad(&ctx->state, data, len); } static TEE_Result __gcm_update_payload(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, TEE_OperationMode mode, const void *src, size_t len, void *dst) { size_t n; const uint8_t *s = src; uint8_t *d = dst; size_t l = len; if (!state->payload_bytes && state->buf_pos) { /* AAD part done, finish up the last bits. */ memset(state->buf_hash + state->buf_pos, 0, TEE_AES_BLOCK_SIZE - state->buf_pos); internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); state->buf_pos = 0; } state->payload_bytes += len; while (l) { if (state->buf_pos || l < TEE_AES_BLOCK_SIZE) { n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l); if (!state->buf_pos && mode == TEE_MODE_DECRYPT) crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, state->ctr, state->buf_cryp); xor_buf(state->buf_cryp + state->buf_pos, s, n); memcpy(d, state->buf_cryp + state->buf_pos, n); if (mode == TEE_MODE_ENCRYPT) memcpy(state->buf_hash + state->buf_pos, state->buf_cryp + state->buf_pos, n); else memcpy(state->buf_hash + state->buf_pos, s, n); state->buf_pos += n; if (state->buf_pos != TEE_AES_BLOCK_SIZE) return TEE_SUCCESS; internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); state->buf_pos = 0; d += n; s += n; l -= n; if (mode == TEE_MODE_ENCRYPT) crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, state->ctr, state->buf_cryp); internal_aes_gcm_inc_ctr(state); } else { n = l / TEE_AES_BLOCK_SIZE; internal_aes_gcm_update_payload_blocks(state, ek, mode, s, n, d); s += n * TEE_AES_BLOCK_SIZE; d += n * TEE_AES_BLOCK_SIZE; l -= n * TEE_AES_BLOCK_SIZE; } } return TEE_SUCCESS; } TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx, TEE_OperationMode mode, const void *src, size_t len, void *dst) { return __gcm_update_payload(&ctx->state, &ctx->key, mode, src, len, dst); } static TEE_Result operation_final(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key, TEE_OperationMode m, const uint8_t *src, size_t len, uint8_t *dst) { TEE_Result res; res = __gcm_update_payload(state, enc_key, m, src, len, dst); if (res) return res; if (state->buf_pos) { memset(state->buf_hash + state->buf_pos, 0, sizeof(state->buf_hash) - state->buf_pos); internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); } ghash_update_lengths(state, state->aad_bytes, state->payload_bytes); /* buf_tag was filled in with the first counter block aes_gcm_init() */ xor_buf(state->buf_tag, state->hash_state, state->tag_len); return TEE_SUCCESS; } static TEE_Result __gcm_enc_final(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key, const void *src, size_t len, void *dst, void *tag, size_t *tag_len) { TEE_Result res; if (*tag_len < state->tag_len) return TEE_ERROR_SHORT_BUFFER; res = operation_final(state, enc_key, TEE_MODE_ENCRYPT, src, len, dst); if (res) return res; memcpy(tag, state->buf_tag, state->tag_len); *tag_len = state->tag_len; return TEE_SUCCESS; } TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx, const void *src, size_t len, void *dst, void *tag, size_t *tag_len) { return __gcm_enc_final(&ctx->state, &ctx->key, src, len, dst, tag, tag_len); } static TEE_Result __gcm_dec_final(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key, const void *src, size_t len, void *dst, const void *tag, size_t tag_len) { TEE_Result res; if (tag_len != state->tag_len) return TEE_ERROR_MAC_INVALID; res = operation_final(state, enc_key, TEE_MODE_DECRYPT, src, len, dst); if (res) return res; if (consttime_memcmp(state->buf_tag, tag, tag_len)) return TEE_ERROR_MAC_INVALID; return TEE_SUCCESS; } TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx, const void *src, size_t len, void *dst, const void *tag, size_t tag_len) { return __gcm_dec_final(&ctx->state, &ctx->key, src, len, dst, tag, tag_len); } void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state) { uint64_t c = 0; uint32_t lower = 0; c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]); lower = c + 1; c = (c & GENMASK_64(63, 32)) | lower; state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c); } void internal_aes_gcm_dec_ctr(struct internal_aes_gcm_state *state) { uint64_t c = 0; uint32_t lower = 0; c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]); lower = c - 1; c = (c & GENMASK_64(63, 32)) | lower; state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c); } TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key, const void *nonce, size_t nonce_len, const void *aad, size_t aad_len, const void *src, size_t len, void *dst, void *tag, size_t *tag_len) { TEE_Result res; struct internal_aes_gcm_state state; res = __gcm_init(&state, enc_key, TEE_MODE_ENCRYPT, nonce, nonce_len, *tag_len); if (res) return res; if (aad) { res = __gcm_update_aad(&state, aad, aad_len); if (res) return res; } return __gcm_enc_final(&state, enc_key, src, len, dst, tag, tag_len); } TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key, const void *nonce, size_t nonce_len, const void *aad, size_t aad_len, const void *src, size_t len, void *dst, const void *tag, size_t tag_len) { TEE_Result res; struct internal_aes_gcm_state state; res = __gcm_init(&state, enc_key, TEE_MODE_DECRYPT, nonce, nonce_len, tag_len); if (res) return res; if (aad) { res = __gcm_update_aad(&state, aad, aad_len); if (res) return res; } return __gcm_dec_final(&state, enc_key, src, len, dst, tag, tag_len); } #ifndef CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB #include #include struct aes_gcm_ctx { struct crypto_authenc_ctx aec; struct internal_aes_gcm_ctx ctx; }; static const struct crypto_authenc_ops aes_gcm_ops; static struct aes_gcm_ctx * to_aes_gcm_ctx(struct crypto_authenc_ctx *aec) { assert(aec->ops == &aes_gcm_ops); return container_of(aec, struct aes_gcm_ctx, aec); } TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) { struct aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->aec.ops = &aes_gcm_ops; *ctx_ret = &ctx->aec; return TEE_SUCCESS; } static void aes_gcm_free_ctx(struct crypto_authenc_ctx *aec) { free(to_aes_gcm_ctx(aec)); } static void aes_gcm_copy_state(struct crypto_authenc_ctx *dst_ctx, struct crypto_authenc_ctx *src_ctx) { to_aes_gcm_ctx(dst_ctx)->ctx = to_aes_gcm_ctx(src_ctx)->ctx; } static TEE_Result aes_gcm_init(struct crypto_authenc_ctx *aec, TEE_OperationMode mode, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len __unused, size_t payload_len __unused) { return internal_aes_gcm_init(&to_aes_gcm_ctx(aec)->ctx, mode, key, key_len, nonce, nonce_len, tag_len); } static TEE_Result aes_gcm_update_aad(struct crypto_authenc_ctx *aec, const uint8_t *data, size_t len) { return internal_aes_gcm_update_aad(&to_aes_gcm_ctx(aec)->ctx, data, len); } static TEE_Result aes_gcm_update_payload(struct crypto_authenc_ctx *aec, TEE_OperationMode m, const uint8_t *src, size_t len, uint8_t *dst) { return internal_aes_gcm_update_payload(&to_aes_gcm_ctx(aec)->ctx, m, src, len, dst); } static TEE_Result aes_gcm_enc_final(struct crypto_authenc_ctx *aec, const uint8_t *src, size_t len, uint8_t *dst, uint8_t *tag, size_t *tag_len) { return internal_aes_gcm_enc_final(&to_aes_gcm_ctx(aec)->ctx, src, len, dst, tag, tag_len); } static TEE_Result aes_gcm_dec_final(struct crypto_authenc_ctx *aec, const uint8_t *src, size_t len, uint8_t *dst, const uint8_t *tag, size_t tag_len) { return internal_aes_gcm_dec_final(&to_aes_gcm_ctx(aec)->ctx, src, len, dst, tag, tag_len); } static void aes_gcm_final(struct crypto_authenc_ctx *aec __unused) { } static const struct crypto_authenc_ops aes_gcm_ops = { .init = aes_gcm_init, .update_aad = aes_gcm_update_aad, .update_payload = aes_gcm_update_payload, .enc_final = aes_gcm_enc_final, .dec_final = aes_gcm_dec_final, .final = aes_gcm_final, .free_ctx = aes_gcm_free_ctx, .copy_state = aes_gcm_copy_state, }; /* * internal_aes_gcm_gfmul() is based on ghash_gfmul() from * https://github.com/openbsd/src/blob/master/sys/crypto/gmac.c */ void internal_aes_gcm_gfmul(const uint64_t X[2], const uint64_t Y[2], uint64_t product[2]) { uint64_t y[2] = { 0 }; uint64_t z[2] = { 0 }; const uint8_t *x = (const uint8_t *)X; uint32_t mul = 0; size_t n = 0; y[0] = TEE_U64_FROM_BIG_ENDIAN(Y[0]); y[1] = TEE_U64_FROM_BIG_ENDIAN(Y[1]); for (n = 0; n < TEE_AES_BLOCK_SIZE * 8; n++) { /* update Z */ if (x[n >> 3] & (1 << (~n & 7))) internal_aes_gcm_xor_block(z, y); /* update Y */ mul = y[1] & 1; y[1] = (y[0] << 63) | (y[1] >> 1); y[0] = (y[0] >> 1) ^ (0xe100000000000000 * mul); } product[0] = TEE_U64_TO_BIG_ENDIAN(z[0]); product[1] = TEE_U64_TO_BIG_ENDIAN(z[1]); } #endif /*!CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/ optee_os-4.3.0/core/crypto/cbc-mac.c000066400000000000000000000147141464416617300172570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ /* * This is implemented here as being the plain text which is encoded with IV=0. * Result of the CBC-MAC is the last 16-bytes cipher. */ #include #include #include #include #include #include #include #define CBCMAC_MAX_BLOCK_LEN 16 struct crypto_cbc_mac_ctx { struct crypto_mac_ctx ctx; void *cbc_ctx; uint32_t cbc_algo; uint8_t block[CBCMAC_MAX_BLOCK_LEN]; uint8_t digest[CBCMAC_MAX_BLOCK_LEN]; unsigned char current_block_len; unsigned char block_len; bool is_computed; bool pkcs5_pad; }; static const struct crypto_mac_ops crypto_cbc_mac_ops; static struct crypto_cbc_mac_ctx *to_cbc_mac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == &crypto_cbc_mac_ops); return container_of(ctx, struct crypto_cbc_mac_ctx, ctx); } static TEE_Result crypto_cbc_mac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); memset(mc->block, 0, sizeof(mc->block)); memset(mc->digest, 0, sizeof(mc->digest)); mc->current_block_len = 0; mc->is_computed = false; /* IV should be zero and mc->block happens to be zero at this stage */ return crypto_cipher_init(mc->cbc_ctx, TEE_MODE_ENCRYPT, key, len, NULL, 0, mc->block, mc->block_len); } static TEE_Result crypto_cbc_mac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { size_t nblocks = 0; size_t out_len = 0; uint8_t *out_tmp = NULL; uint8_t *out = NULL; TEE_Result res = TEE_SUCCESS; struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); if ((mc->current_block_len > 0) && (len + mc->current_block_len >= mc->block_len)) { size_t pad_len = mc->block_len - mc->current_block_len; memcpy(mc->block + mc->current_block_len, data, pad_len); data += pad_len; len -= pad_len; res = crypto_cipher_update(mc->cbc_ctx, TEE_MODE_ENCRYPT, false, mc->block, mc->block_len, mc->digest); if (res) return res; mc->is_computed = 1; mc->current_block_len = 0; } nblocks = MIN(len / mc->block_len, (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); if (nblocks > 1) out_tmp = calloc(nblocks, mc->block_len); while (len >= mc->block_len) { nblocks = MIN(len / mc->block_len, (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); if (nblocks > 1 && out_tmp) { out_len = nblocks * mc->block_len; out = out_tmp; } else { out_len = mc->block_len; out = mc->digest; nblocks = 1; } res = crypto_cipher_update(mc->cbc_ctx, TEE_MODE_ENCRYPT, false, data, out_len, out); if (res) goto out; mc->is_computed = 1; data += out_len; len -= out_len; if (nblocks > 1 && len < mc->block_len) { assert(out_tmp); /* Copy last block of output */ memcpy(mc->digest, out_tmp + out_len - mc->block_len, mc->block_len); } } if (len > 0) { assert(mc->current_block_len + len < mc->block_len); memcpy(mc->block + mc->current_block_len, data, len); mc->current_block_len += len; } out: free(out_tmp); return res; } static TEE_Result crypto_cbc_mac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t digest_len) { struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); if (mc->pkcs5_pad) { /* * Padding is in whole bytes. The value of each added * byte is the number of bytes that are added, i.e. N * bytes, each of value N are added */ size_t pad_len = mc->block_len - mc->current_block_len; memset(mc->block + mc->current_block_len, pad_len, pad_len); mc->current_block_len = 0; if (crypto_cbc_mac_update(ctx, mc->block, mc->block_len)) return TEE_ERROR_BAD_STATE; } if (!mc->is_computed || mc->current_block_len) return TEE_ERROR_BAD_STATE; memcpy(digest, mc->digest, MIN(digest_len, mc->block_len)); crypto_cipher_final(mc->cbc_ctx); return TEE_SUCCESS; } static void crypto_cbc_mac_free_ctx(struct crypto_mac_ctx *ctx) { struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); crypto_cipher_free_ctx(mc->cbc_ctx); free(mc); } static void crypto_cbc_mac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct crypto_cbc_mac_ctx *dst = to_cbc_mac_ctx(dst_ctx); struct crypto_cbc_mac_ctx *src = to_cbc_mac_ctx(src_ctx); assert(dst->block_len == src->block_len); assert(dst->pkcs5_pad == src->pkcs5_pad); assert(dst->cbc_algo == src->cbc_algo); crypto_cipher_copy_state(dst->cbc_ctx, src->cbc_ctx); memcpy(dst->block, src->block, sizeof(dst->block)); memcpy(dst->digest, src->digest, sizeof(dst->digest)); dst->current_block_len = src->current_block_len; dst->is_computed = src->is_computed; } static const struct crypto_mac_ops crypto_cbc_mac_ops = { .init = crypto_cbc_mac_init, .update = crypto_cbc_mac_update, .final = crypto_cbc_mac_final, .free_ctx = crypto_cbc_mac_free_ctx, .copy_state = crypto_cbc_mac_copy_state, }; static TEE_Result crypto_cbc_mac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, uint32_t cbc_algo, bool pkcs5_pad) { TEE_Result res; void *cbc_ctx = NULL; struct crypto_cbc_mac_ctx *ctx = NULL; size_t block_size = 0; res = crypto_cipher_get_block_size(cbc_algo, &block_size); if (res) return res; res = crypto_cipher_alloc_ctx(&cbc_ctx, cbc_algo); if (res) return res; ctx = calloc(1, sizeof(*ctx)); if (!ctx) { crypto_cipher_free_ctx(cbc_ctx); return TEE_ERROR_OUT_OF_MEMORY; } ctx->cbc_ctx = cbc_ctx; ctx->cbc_algo = cbc_algo; ctx->pkcs5_pad = pkcs5_pad; ctx->block_len = block_size; ctx->ctx.ops = &crypto_cbc_mac_ops; *ctx_ret = &ctx->ctx; return TEE_SUCCESS; } TEE_Result crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) { return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, false); } TEE_Result crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) { return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, true); } TEE_Result crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) { return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, false); } TEE_Result crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) { return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, true); } TEE_Result crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) { return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, false); } TEE_Result crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) { return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, true); } optee_os-4.3.0/core/crypto/crypto.c000066400000000000000000000545501464416617300173140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited * Copyright 2020 NXP * Copyright 2021, SumUp Service GmbH */ #include #include #include #include #include #include #include TEE_Result crypto_hash_alloc_ctx(void **ctx, uint32_t algo) { TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_hash_ctx *c = NULL; /* * Use default cryptographic implementation if no matching * drvcrypt device. */ res = drvcrypt_hash_alloc_ctx(&c, algo); if (res == TEE_ERROR_NOT_IMPLEMENTED) { switch (algo) { case TEE_ALG_MD5: res = crypto_md5_alloc_ctx(&c); break; case TEE_ALG_SHA1: res = crypto_sha1_alloc_ctx(&c); break; case TEE_ALG_SHA224: res = crypto_sha224_alloc_ctx(&c); break; case TEE_ALG_SHA256: res = crypto_sha256_alloc_ctx(&c); break; case TEE_ALG_SHA384: res = crypto_sha384_alloc_ctx(&c); break; case TEE_ALG_SHA512: res = crypto_sha512_alloc_ctx(&c); break; case TEE_ALG_SHA3_224: res = crypto_sha3_224_alloc_ctx(&c); break; case TEE_ALG_SHA3_256: res = crypto_sha3_256_alloc_ctx(&c); break; case TEE_ALG_SHA3_384: res = crypto_sha3_384_alloc_ctx(&c); break; case TEE_ALG_SHA3_512: res = crypto_sha3_512_alloc_ctx(&c); break; case TEE_ALG_SHAKE128: res = crypto_shake128_alloc_ctx(&c); break; case TEE_ALG_SHAKE256: res = crypto_shake256_alloc_ctx(&c); break; case TEE_ALG_SM3: res = crypto_sm3_alloc_ctx(&c); break; default: break; } } if (!res) *ctx = c; return res; } static const struct crypto_hash_ops *hash_ops(void *ctx) { struct crypto_hash_ctx *c = ctx; assert(c && c->ops); return c->ops; } void crypto_hash_free_ctx(void *ctx) { if (ctx) hash_ops(ctx)->free_ctx(ctx); } void crypto_hash_copy_state(void *dst_ctx, void *src_ctx) { hash_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); } TEE_Result crypto_hash_init(void *ctx) { return hash_ops(ctx)->init(ctx); } TEE_Result crypto_hash_update(void *ctx, const uint8_t *data, size_t len) { return hash_ops(ctx)->update(ctx, data, len); } TEE_Result crypto_hash_final(void *ctx, uint8_t *digest, size_t len) { return hash_ops(ctx)->final(ctx, digest, len); } TEE_Result crypto_cipher_alloc_ctx(void **ctx, uint32_t algo) { TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_cipher_ctx *c = NULL; /* * Use default cryptographic implementation if no matching * drvcrypt device. */ res = drvcrypt_cipher_alloc_ctx(&c, algo); if (res == TEE_ERROR_NOT_IMPLEMENTED) { switch (algo) { case TEE_ALG_AES_ECB_NOPAD: res = crypto_aes_ecb_alloc_ctx(&c); break; case TEE_ALG_AES_CBC_NOPAD: res = crypto_aes_cbc_alloc_ctx(&c); break; case TEE_ALG_AES_CTR: res = crypto_aes_ctr_alloc_ctx(&c); break; case TEE_ALG_AES_CTS: res = crypto_aes_cts_alloc_ctx(&c); break; case TEE_ALG_AES_XTS: res = crypto_aes_xts_alloc_ctx(&c); break; case TEE_ALG_DES_ECB_NOPAD: res = crypto_des_ecb_alloc_ctx(&c); break; case TEE_ALG_DES3_ECB_NOPAD: res = crypto_des3_ecb_alloc_ctx(&c); break; case TEE_ALG_DES_CBC_NOPAD: res = crypto_des_cbc_alloc_ctx(&c); break; case TEE_ALG_DES3_CBC_NOPAD: res = crypto_des3_cbc_alloc_ctx(&c); break; case TEE_ALG_SM4_ECB_NOPAD: res = crypto_sm4_ecb_alloc_ctx(&c); break; case TEE_ALG_SM4_CBC_NOPAD: res = crypto_sm4_cbc_alloc_ctx(&c); break; case TEE_ALG_SM4_CTR: res = crypto_sm4_ctr_alloc_ctx(&c); break; case TEE_ALG_SM4_XTS: res = crypto_sm4_xts_alloc_ctx(&c); break; default: return TEE_ERROR_NOT_IMPLEMENTED; } } if (!res) *ctx = c; return res; } static const struct crypto_cipher_ops *cipher_ops(void *ctx) { struct crypto_cipher_ctx *c = ctx; assert(c && c->ops); return c->ops; } void crypto_cipher_free_ctx(void *ctx) { if (ctx) cipher_ops(ctx)->free_ctx(ctx); } void crypto_cipher_copy_state(void *dst_ctx, void *src_ctx) { cipher_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); } TEE_Result crypto_cipher_init(void *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len) { if (mode != TEE_MODE_DECRYPT && mode != TEE_MODE_ENCRYPT) return TEE_ERROR_BAD_PARAMETERS; return cipher_ops(ctx)->init(ctx, mode, key1, key1_len, key2, key2_len, iv, iv_len); } TEE_Result crypto_cipher_update(void *ctx, TEE_OperationMode mode __unused, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { return cipher_ops(ctx)->update(ctx, last_block, data, len, dst); } void crypto_cipher_final(void *ctx) { cipher_ops(ctx)->final(ctx); } TEE_Result crypto_cipher_get_block_size(uint32_t algo, size_t *size) { uint32_t class = TEE_ALG_GET_CLASS(algo); if (class != TEE_OPERATION_CIPHER && class != TEE_OPERATION_MAC && class != TEE_OPERATION_AE) return TEE_ERROR_BAD_PARAMETERS; switch (TEE_ALG_GET_MAIN_ALG(algo)) { case TEE_MAIN_ALGO_AES: *size = TEE_AES_BLOCK_SIZE; return TEE_SUCCESS; case TEE_MAIN_ALGO_DES: case TEE_MAIN_ALGO_DES3: *size = TEE_DES_BLOCK_SIZE; return TEE_SUCCESS; case TEE_MAIN_ALGO_SM4: *size = TEE_SM4_BLOCK_SIZE; return TEE_SUCCESS; default: return TEE_ERROR_NOT_SUPPORTED; } } TEE_Result crypto_mac_alloc_ctx(void **ctx, uint32_t algo) { TEE_Result res = TEE_SUCCESS; struct crypto_mac_ctx *c = NULL; /* * Use default cryptographic implementation if no matching * drvcrypt device. */ res = drvcrypt_mac_alloc_ctx(&c, algo); if (res == TEE_ERROR_NOT_IMPLEMENTED) { switch (algo) { case TEE_ALG_HMAC_MD5: res = crypto_hmac_md5_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA1: res = crypto_hmac_sha1_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA224: res = crypto_hmac_sha224_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA256: res = crypto_hmac_sha256_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA384: res = crypto_hmac_sha384_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA512: res = crypto_hmac_sha512_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA3_224: res = crypto_hmac_sha3_224_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA3_256: res = crypto_hmac_sha3_256_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA3_384: res = crypto_hmac_sha3_384_alloc_ctx(&c); break; case TEE_ALG_HMAC_SHA3_512: res = crypto_hmac_sha3_512_alloc_ctx(&c); break; case TEE_ALG_HMAC_SM3: res = crypto_hmac_sm3_alloc_ctx(&c); break; case TEE_ALG_AES_CBC_MAC_NOPAD: res = crypto_aes_cbc_mac_nopad_alloc_ctx(&c); break; case TEE_ALG_AES_CBC_MAC_PKCS5: res = crypto_aes_cbc_mac_pkcs5_alloc_ctx(&c); break; case TEE_ALG_DES_CBC_MAC_NOPAD: res = crypto_des_cbc_mac_nopad_alloc_ctx(&c); break; case TEE_ALG_DES_CBC_MAC_PKCS5: res = crypto_des_cbc_mac_pkcs5_alloc_ctx(&c); break; case TEE_ALG_DES3_CBC_MAC_NOPAD: res = crypto_des3_cbc_mac_nopad_alloc_ctx(&c); break; case TEE_ALG_DES3_CBC_MAC_PKCS5: res = crypto_des3_cbc_mac_pkcs5_alloc_ctx(&c); break; case TEE_ALG_DES3_CMAC: res = crypto_des3_cmac_alloc_ctx(&c); break; case TEE_ALG_AES_CMAC: res = crypto_aes_cmac_alloc_ctx(&c); break; default: return TEE_ERROR_NOT_SUPPORTED; } } if (!res) *ctx = c; return res; } static const struct crypto_mac_ops *mac_ops(void *ctx) { struct crypto_mac_ctx *c = ctx; assert(c && c->ops); return c->ops; } void crypto_mac_free_ctx(void *ctx) { if (ctx) mac_ops(ctx)->free_ctx(ctx); } void crypto_mac_copy_state(void *dst_ctx, void *src_ctx) { mac_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); } TEE_Result crypto_mac_init(void *ctx, const uint8_t *key, size_t len) { return mac_ops(ctx)->init(ctx, key, len); } TEE_Result crypto_mac_update(void *ctx, const uint8_t *data, size_t len) { if (!len) return TEE_SUCCESS; return mac_ops(ctx)->update(ctx, data, len); } TEE_Result crypto_mac_final(void *ctx, uint8_t *digest, size_t digest_len) { return mac_ops(ctx)->final(ctx, digest, digest_len); } TEE_Result crypto_authenc_alloc_ctx(void **ctx, uint32_t algo) { TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc_ctx *c = NULL; /* * Use default authenc implementation if no matching * drvcrypt device. */ res = drvcrypt_authenc_alloc_ctx(&c, algo); if (res == TEE_ERROR_NOT_IMPLEMENTED) { switch (algo) { #if defined(CFG_CRYPTO_CCM) case TEE_ALG_AES_CCM: res = crypto_aes_ccm_alloc_ctx(&c); break; #endif #if defined(CFG_CRYPTO_GCM) case TEE_ALG_AES_GCM: res = crypto_aes_gcm_alloc_ctx(&c); break; #endif default: break; } } if (!res) *ctx = c; return res; } static const struct crypto_authenc_ops *ae_ops(void *ctx) { struct crypto_authenc_ctx *c = ctx; assert(c && c->ops); return c->ops; } TEE_Result crypto_authenc_init(void *ctx, TEE_OperationMode mode, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len) { return ae_ops(ctx)->init(ctx, mode, key, key_len, nonce, nonce_len, tag_len, aad_len, payload_len); } TEE_Result crypto_authenc_update_aad(void *ctx, TEE_OperationMode mode __unused, const uint8_t *data, size_t len) { return ae_ops(ctx)->update_aad(ctx, data, len); } TEE_Result crypto_authenc_update_payload(void *ctx, TEE_OperationMode mode, const uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len) { if (*dst_len < src_len) return TEE_ERROR_SHORT_BUFFER; *dst_len = src_len; return ae_ops(ctx)->update_payload(ctx, mode, src_data, src_len, dst_data); } TEE_Result crypto_authenc_enc_final(void *ctx, const uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len, uint8_t *dst_tag, size_t *dst_tag_len) { if (*dst_len < src_len) return TEE_ERROR_SHORT_BUFFER; *dst_len = src_len; return ae_ops(ctx)->enc_final(ctx, src_data, src_len, dst_data, dst_tag, dst_tag_len); } TEE_Result crypto_authenc_dec_final(void *ctx, const uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len, const uint8_t *tag, size_t tag_len) { if (*dst_len < src_len) return TEE_ERROR_SHORT_BUFFER; *dst_len = src_len; return ae_ops(ctx)->dec_final(ctx, src_data, src_len, dst_data, tag, tag_len); } void crypto_authenc_final(void *ctx) { ae_ops(ctx)->final(ctx); } void crypto_authenc_free_ctx(void *ctx) { if (ctx) ae_ops(ctx)->free_ctx(ctx); } void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx) { ae_ops(dst_ctx)->copy_state(dst_ctx, src_ctx); } #if !defined(CFG_CRYPTO_RSA) && !defined(CFG_CRYPTO_DSA) && \ !defined(CFG_CRYPTO_DH) && !defined(CFG_CRYPTO_ECC) struct bignum *crypto_bignum_allocate(size_t size_bits __unused) { return NULL; } TEE_Result crypto_bignum_bin2bn(const uint8_t *from __unused, size_t fromsize __unused, struct bignum *to __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } size_t crypto_bignum_num_bytes(struct bignum *a __unused) { return 0; } size_t crypto_bignum_num_bits(struct bignum *a __unused) { return 0; } /* * crypto_bignum_allocate() and crypto_bignum_bin2bn() failing should be * enough to guarantee that the functions calling this function aren't * called, but just in case add a panic() here to avoid unexpected * behavoir. */ static void bignum_cant_happen(void) { volatile bool b = true; /* Avoid warning about function does not return */ if (b) panic(); } void crypto_bignum_bn2bin(const struct bignum *from __unused, uint8_t *to __unused) { bignum_cant_happen(); } void crypto_bignum_copy(struct bignum *to __unused, const struct bignum *from __unused) { bignum_cant_happen(); } void crypto_bignum_free(struct bignum **a) { if (a && *a) panic(); } void crypto_bignum_clear(struct bignum *a __unused) { bignum_cant_happen(); } /* return -1 if ab */ int32_t crypto_bignum_compare(struct bignum *a __unused, struct bignum *b __unused) { bignum_cant_happen(); return -1; } #endif #if !defined(CFG_CRYPTO_RSA) TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s __unused) { } void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s __unused) { } TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key __unused, const uint8_t *src __unused, size_t src_len __unused, uint8_t *dst __unused, size_t *dst_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key __unused, const uint8_t *src __unused, size_t src_len __unused, uint8_t *dst __unused, size_t *dst_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo __unused, struct rsa_keypair *key __unused, const uint8_t *label __unused, size_t label_len __unused, uint32_t mgf_algo __unused, const uint8_t *src __unused, size_t src_len __unused, uint8_t *dst __unused, size_t *dst_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo __unused, struct rsa_public_key *key __unused, const uint8_t *label __unused, size_t label_len __unused, uint32_t mgf_algo __unused, const uint8_t *src __unused, size_t src_len __unused, uint8_t *dst __unused, size_t *dst_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_rsassa_sign(uint32_t algo __unused, struct rsa_keypair *key __unused, int salt_len __unused, const uint8_t *msg __unused, size_t msg_len __unused, uint8_t *sig __unused, size_t *sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_rsassa_verify(uint32_t algo __unused, struct rsa_public_key *key __unused, int salt_len __unused, const uint8_t *msg __unused, size_t msg_len __unused, const uint8_t *sig __unused, size_t sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /*!CFG_CRYPTO_RSA*/ #if !defined(CFG_CRYPTO_DSA) TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_dsa_sign(uint32_t algo __unused, struct dsa_keypair *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, uint8_t *sig __unused, size_t *sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_dsa_verify(uint32_t algo __unused, struct dsa_public_key *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, const uint8_t *sig __unused, size_t sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /*!CFG_CRYPTO_DSA*/ #if !defined(CFG_CRYPTO_DH) TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key __unused, struct bignum *q __unused, size_t xbits __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key __unused, struct bignum *public_key __unused, struct bignum *secret __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /*!CFG_CRYPTO_DH*/ TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *key, uint32_t key_type, size_t key_size_bits) { TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; /* * Use default cryptographic implementation if no matching * drvcrypt device. */ res = drvcrypt_asym_alloc_ecc_public_key(key, key_type, key_size_bits); if (res == TEE_ERROR_NOT_IMPLEMENTED) res = crypto_asym_alloc_ecc_public_key(key, key_type, key_size_bits); return res; } TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *key, uint32_t key_type, size_t key_size_bits) { TEE_Result res = TEE_ERROR_NOT_IMPLEMENTED; /* * Use default cryptographic implementation if no matching * drvcrypt device. */ res = drvcrypt_asym_alloc_ecc_keypair(key, key_type, key_size_bits); if (res == TEE_ERROR_NOT_IMPLEMENTED) res = crypto_asym_alloc_ecc_keypair(key, key_type, key_size_bits); return res; } void crypto_acipher_free_ecc_public_key(struct ecc_public_key *key) { assert(key->ops && key->ops->free); key->ops->free(key); } TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key, size_t key_size_bits) { assert(key->ops && key->ops->generate); return key->ops->generate(key, key_size_bits); } TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { assert(key->ops); if (!key->ops->sign) return TEE_ERROR_NOT_IMPLEMENTED; return key->ops->sign(algo, key, msg, msg_len, sig, sig_len); } TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { assert(key->ops); if (!key->ops->verify) return TEE_ERROR_NOT_IMPLEMENTED; return key->ops->verify(algo, key, msg, msg_len, sig, sig_len); } TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len) { assert(private_key->ops); if (!private_key->ops->shared_secret) return TEE_ERROR_NOT_IMPLEMENTED; return private_key->ops->shared_secret(private_key, public_key, secret, secret_len); } TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { assert(key->ops); if (!key->ops->decrypt) return TEE_ERROR_NOT_IMPLEMENTED; return key->ops->decrypt(key, src, src_len, dst, dst_len); } TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { assert(key->ops); if (!key->ops->encrypt) return TEE_ERROR_NOT_IMPLEMENTED; return key->ops->encrypt(key, src, src_len, dst, dst_len); } #if !defined(CFG_CRYPTO_SM2_KEP) TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key __unused, struct ecc_keypair *my_eph_key __unused, struct ecc_public_key *peer_key __unused, struct ecc_public_key *peer_eph_key __unused, struct sm2_kep_parms *p __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #if !defined(CFG_CRYPTO_X25519) TEE_Result crypto_acipher_alloc_x25519_keypair(struct montgomery_keypair *key __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_gen_x25519_key(struct montgomery_keypair *key __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_x25519_shared_secret(struct montgomery_keypair *private_key __unused, void *public_key __unused, void *secret __unused, unsigned long *secret_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #if !defined(CFG_CRYPTO_X448) TEE_Result crypto_acipher_alloc_x448_keypair(struct montgomery_keypair *key __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_gen_x448_key(struct montgomery_keypair *key __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_x448_shared_secret(struct montgomery_keypair *private_key __unused, void *public_key __unused, void *secret __unused, unsigned long *secret_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #if !defined(CFG_CRYPTO_ED25519) TEE_Result crypto_acipher_alloc_ed25519_keypair(struct ed25519_keypair *key __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_alloc_ed25519_public_key(struct ed25519_public_key *key __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_gen_ed25519_key(struct ed25519_keypair *key __unused, size_t key_size __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, uint8_t *sig __unused, size_t *sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_ed25519_verify(struct ed25519_public_key *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, const uint8_t *sig __unused, size_t sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, uint8_t *sig __unused, size_t *sig_len __unused, bool ph_flag __unused, const uint8_t *ctx __unused, size_t ctxlen __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result crypto_acipher_ed25519ctx_verify(struct ed25519_public_key *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, const uint8_t *sig __unused, size_t sig_len __unused, bool ph_flag __unused, const uint8_t *ctx __unused, size_t ctxlen __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif __weak TEE_Result crypto_storage_obj_del(struct tee_obj *obj __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } optee_os-4.3.0/core/crypto/rng_fortuna.c000066400000000000000000000275011464416617300203140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* Copyright (c) 2018, Linaro Limited */ /* * This is an implementation of the Fortuna cryptographic PRNG as defined in * https://www.schneier.com/academic/paperfiles/fortuna.pdf * There's one small exception, see comment in restart_pool() below. */ #include #include #include #include #include #include #include #include #include #include #define NUM_POOLS 32 #define BLOCK_SIZE 16 #define KEY_SIZE 32 #define CIPHER_ALGO TEE_ALG_AES_ECB_NOPAD #define HASH_ALGO TEE_ALG_SHA256 #define MIN_POOL_SIZE 64 #define MAX_EVENT_DATA_LEN 32U #define RING_BUF_DATA_SIZE 4U /* * struct fortuna_state - state of the Fortuna PRNG * @ctx: Cipher context used to produce the random numbers * @counter: Counter which is encrypted to produce the random numbers * @pool0_length: Amount of data added to pool0 * @pool_ctx: One hash context for each pool * @reseed_ctx: Hash context used while reseeding * @reseed_count: Number of time we've reseeded the PRNG, used to tell * which pools should be used in the reseed process * @next_reseed_time: If we have a secure time, the earliest next time we * may reseed * * To minimize the delay in crypto_rng_add_event() there's @pool_spin_lock * which protects everything needed by this function. * * @next_reseed_time is used as a rate limiter for reseeding. */ static struct fortuna_state { void *ctx; uint64_t counter[2]; unsigned int pool0_length; void *pool_ctx[NUM_POOLS]; void *reseed_ctx; uint32_t reseed_count; #ifndef CFG_SECURE_TIME_SOURCE_REE TEE_Time next_reseed_time; #endif } state; static struct mutex state_mu = MUTEX_INITIALIZER; static struct { struct { uint8_t snum; uint8_t pnum; uint8_t dlen; uint8_t data[RING_BUF_DATA_SIZE]; } elem[8]; unsigned int begin; unsigned int end; } ring_buffer; unsigned int ring_buffer_spin_lock; static void inc_counter(uint64_t counter[2]) { counter[0]++; if (!counter[0]) counter[1]++; } static TEE_Result hash_init(void *ctx) { return crypto_hash_init(ctx); } static TEE_Result hash_update(void *ctx, const void *data, size_t dlen) { return crypto_hash_update(ctx, data, dlen); } static TEE_Result hash_final(void *ctx, uint8_t digest[KEY_SIZE]) { return crypto_hash_final(ctx, digest, KEY_SIZE); } static TEE_Result key_from_data(void *ctx, const void *data, size_t dlen, uint8_t key[KEY_SIZE]) { TEE_Result res; res = hash_init(ctx); if (res) return res; res = hash_update(ctx, data, dlen); if (res) return res; return hash_final(ctx, key); } static TEE_Result cipher_init(void *ctx, uint8_t key[KEY_SIZE]) { return crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, key, KEY_SIZE, NULL, 0, NULL, 0); } static void fortuna_done(void) { size_t n; for (n = 0; n < NUM_POOLS; n++) { crypto_hash_free_ctx(state.pool_ctx[n]); state.pool_ctx[n] = NULL; } crypto_hash_free_ctx(state.reseed_ctx); state.reseed_ctx = NULL; crypto_cipher_free_ctx(state.ctx); state.ctx = NULL; } TEE_Result crypto_rng_init(const void *data, size_t dlen) { TEE_Result res; uint8_t key[KEY_SIZE]; void *ctx; size_t n; COMPILE_TIME_ASSERT(sizeof(state.counter) == BLOCK_SIZE); if (state.ctx) return TEE_ERROR_BAD_STATE; memset(&state, 0, sizeof(state)); for (n = 0; n < NUM_POOLS; n++) { res = crypto_hash_alloc_ctx(&state.pool_ctx[n], HASH_ALGO); if (res) goto err; res = crypto_hash_init(state.pool_ctx[n]); if (res) goto err; } res = crypto_hash_alloc_ctx(&state.reseed_ctx, HASH_ALGO); if (res) goto err; res = key_from_data(state.reseed_ctx, data, dlen, key); if (res) return res; res = crypto_cipher_alloc_ctx(&ctx, CIPHER_ALGO); if (res) return res; res = cipher_init(ctx, key); if (res) return res; inc_counter(state.counter); state.ctx = ctx; return TEE_SUCCESS; err: fortuna_done(); return res; } static void push_ring_buffer(uint8_t snum, uint8_t pnum, const void *data, size_t dlen) { uint8_t dl = MIN(RING_BUF_DATA_SIZE, dlen); unsigned int next_begin; uint32_t old_itr_status; /* Spinlock to serialize writers */ old_itr_status = cpu_spin_lock_xsave(&ring_buffer_spin_lock); next_begin = (ring_buffer.begin + 1) % ARRAY_SIZE(ring_buffer.elem); if (next_begin == atomic_load_uint(&ring_buffer.end)) goto out; /* buffer is full */ ring_buffer.elem[next_begin].snum = snum; ring_buffer.elem[next_begin].pnum = pnum; ring_buffer.elem[next_begin].dlen = dl; memcpy(ring_buffer.elem[next_begin].data, data, dl); atomic_store_uint(&ring_buffer.begin, next_begin); out: cpu_spin_unlock_xrestore(&ring_buffer_spin_lock, old_itr_status); } static size_t pop_ring_buffer(uint8_t *snum, uint8_t *pnum, uint8_t data[RING_BUF_DATA_SIZE]) { unsigned int next_end; size_t dlen; if (atomic_load_uint(&ring_buffer.begin) == ring_buffer.end) return 0; next_end = (ring_buffer.end + 1) % ARRAY_SIZE(ring_buffer.elem); *snum = ring_buffer.elem[ring_buffer.end].snum; *pnum = ring_buffer.elem[ring_buffer.end].pnum; dlen = MIN(ring_buffer.elem[ring_buffer.end].dlen, RING_BUF_DATA_SIZE); assert(ring_buffer.elem[ring_buffer.end].dlen == dlen); memcpy(data, ring_buffer.elem[ring_buffer.end].data, dlen); atomic_store_uint(&ring_buffer.end, next_end); return dlen; } static TEE_Result add_event(uint8_t snum, uint8_t pnum, const void *data, size_t dlen) { TEE_Result res; size_t dl = MIN(MAX_EVENT_DATA_LEN, dlen); uint8_t v[] = { snum, dl }; if (pnum >= NUM_POOLS) return TEE_ERROR_BAD_PARAMETERS; res = hash_update(state.pool_ctx[pnum], v, sizeof(v)); if (res) return res; res = hash_update(state.pool_ctx[pnum], data, dl); if (res) return res; if (!pnum) { unsigned int l; if (!ADD_OVERFLOW(state.pool0_length, dl, &l)) state.pool0_length = l; } return TEE_SUCCESS; } static TEE_Result drain_ring_buffer(void) { while (true) { TEE_Result res; uint8_t snum; uint8_t pnum; uint8_t data[RING_BUF_DATA_SIZE]; size_t dlen; dlen = pop_ring_buffer(&snum, &pnum, data); if (!dlen) return TEE_SUCCESS; res = add_event(snum, pnum, data, dlen); if (res) return res; } } static unsigned int get_next_pnum(unsigned int *pnum) { unsigned int nval; unsigned int oval = atomic_load_uint(pnum); while (true) { nval = (oval + 1) % NUM_POOLS; if (atomic_cas_uint(pnum, &oval, nval)) { /* * *pnum is normally initialized to 0 and we'd like * to start feeding pool number 0 as that's the * most important one. * * If we where to take just *pnum and increase it * later multiple updaters could end up with the * same number. * * By increasing first we get the number unique for * next update and by subtracting one (using * modulus) we get the number for this update. */ return (nval + NUM_POOLS - 1) % NUM_POOLS; } /* * At this point atomic_cas_uint() has updated oval to the * current *pnum. */ } } void crypto_rng_add_event(enum crypto_rng_src sid, unsigned int *pnum, const void *data, size_t dlen) { unsigned int pn = get_next_pnum(pnum); uint8_t snum = sid >> 1; if (CRYPTO_RNG_SRC_IS_QUICK(sid)) { push_ring_buffer(snum, pn, data, dlen); } else { mutex_lock(&state_mu); add_event(snum, pn, data, dlen); drain_ring_buffer(); mutex_unlock(&state_mu); } } /* GenerateBlocks */ static TEE_Result generate_blocks(void *block, size_t nblocks) { uint8_t *b = block; size_t n; for (n = 0; n < nblocks; n++) { TEE_Result res = crypto_cipher_update(state.ctx, TEE_MODE_ENCRYPT, false, (void *)state.counter, BLOCK_SIZE, b + n * BLOCK_SIZE); /* * Make sure to increase the counter before returning an * eventual errors, we must never re-use the counter with * the same key. */ inc_counter(state.counter); if (res) return res; } return TEE_SUCCESS; } /* GenerateRandomData */ static TEE_Result generate_random_data(void *buf, size_t blen) { TEE_Result res; res = generate_blocks(buf, blen / BLOCK_SIZE); if (res) return res; if (blen % BLOCK_SIZE) { uint8_t block[BLOCK_SIZE]; uint8_t *b = (uint8_t *)buf + ROUNDDOWN(blen, BLOCK_SIZE); res = generate_blocks(block, 1); if (res) return res; memcpy(b, block, blen % BLOCK_SIZE); } return TEE_SUCCESS; } #ifdef CFG_SECURE_TIME_SOURCE_REE static bool reseed_rate_limiting(void) { /* * There's no point in checking REE time for reseed rate limiting, * and also it makes it less complicated if we can avoid doing RPC * here. */ return false; } #else static bool reseed_rate_limiting(void) { TEE_Result res; TEE_Time time; const TEE_Time time_100ms = { 0, 100 }; res = tee_time_get_sys_time(&time); /* * Failure to read time must result in allowing reseed or we could * block reseeding forever. */ if (res) return false; if (TEE_TIME_LT(time, state.next_reseed_time)) return true; /* Time to reseed, calculate next time reseed is OK */ TEE_TIME_ADD(time, time_100ms, state.next_reseed_time); return false; } #endif static TEE_Result restart_pool(void *pool_ctx, uint8_t pool_digest[KEY_SIZE]) { TEE_Result res = hash_final(pool_ctx, pool_digest); if (res) return res; res = hash_init(pool_ctx); if (res) return res; /* * Restart the pool with the digest of the old pool. This is an * extension to Fortuna. In the original Fortuna all pools was * restarted from scratch. This extension is one more defense * against spamming of the pools with known data which could lead * to the spammer knowing the state of the pools. * * This extra precaution could be useful since OP-TEE sometimes * have very few sources of good entropy and at the same time has * sources that could quite easily be predicted by an attacker. */ return hash_update(pool_ctx, pool_digest, KEY_SIZE); } static bool reseed_from_pool(uint32_t reseed_count, size_t pool_num) { /* * Specification says: use pool if * 2^pool_num is a divisor of reseed_count * * in order to avoid an expensive modulus operation we're * optimizing this below. */ return !pool_num || !((reseed_count >> (pool_num - 1)) & 1); } static TEE_Result maybe_reseed(void) { TEE_Result res; size_t n; uint8_t pool_digest[KEY_SIZE]; if (state.pool0_length < MIN_POOL_SIZE) return TEE_SUCCESS; if (reseed_rate_limiting()) return TEE_SUCCESS; state.reseed_count++; res = hash_init(state.reseed_ctx); if (res) return res; for (n = 0; n < NUM_POOLS && reseed_from_pool(state.reseed_count, n); n++) { res = restart_pool(state.pool_ctx[n], pool_digest); if (res) return res; if (!n) state.pool0_length = 0; res = hash_update(state.reseed_ctx, pool_digest, KEY_SIZE); if (res) return res; } res = hash_final(state.reseed_ctx, pool_digest); if (res) return res; crypto_cipher_final(state.ctx); res = crypto_cipher_init(state.ctx, TEE_MODE_ENCRYPT, pool_digest, KEY_SIZE, NULL, 0, NULL, 0); if (res) return res; inc_counter(state.counter); return TEE_SUCCESS; } static TEE_Result fortuna_read(void *buf, size_t blen) { TEE_Result res; if (!state.ctx) return TEE_ERROR_BAD_STATE; mutex_lock(&state_mu); res = maybe_reseed(); if (res) goto out; if (blen) { uint8_t new_key[KEY_SIZE]; res = generate_random_data(buf, blen); if (res) goto out; res = generate_blocks(new_key, KEY_SIZE / BLOCK_SIZE); if (res) goto out; crypto_cipher_final(state.ctx); res = cipher_init(state.ctx, new_key); if (res) goto out; } res = drain_ring_buffer(); out: if (res) fortuna_done(); mutex_unlock(&state_mu); return res; } TEE_Result crypto_rng_read(void *buf, size_t blen) { size_t offs = 0; while (true) { TEE_Result res; size_t n; /* Draw at most 1 MiB of random on a single key */ n = MIN(blen - offs, SIZE_1M); if (!n) return TEE_SUCCESS; res = fortuna_read((uint8_t *)buf + offs, n); if (res) return res; offs += n; } } optee_os-4.3.0/core/crypto/rng_hw.c000066400000000000000000000013321464416617300172460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* Copyright (c) 2018, Linaro Limited */ #include #include #include #include #include #include /* This is a HW RNG, no need for seeding */ TEE_Result crypto_rng_init(const void *data __unused, size_t dlen __unused) { return TEE_SUCCESS; } /* This is a HW RNG, no need to add entropy */ void crypto_rng_add_event(enum crypto_rng_src sid __unused, unsigned int *pnum __unused, const void *data __unused, size_t dlen __unused) { } TEE_Result crypto_rng_read(void *buf, size_t blen) { if (!buf) return TEE_ERROR_BAD_PARAMETERS; return hw_get_random_bytes(buf, blen); } optee_os-4.3.0/core/crypto/signed_hdr.c000066400000000000000000000231671464416617300201020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size) { size_t shdr_size; struct shdr *shdr; vaddr_t img_va = (vaddr_t)img; vaddr_t tmp = 0; size_t end = 0; if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size) return NULL; shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs)); if (!shdr_size || ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size) return NULL; if (ADD_OVERFLOW(img_va, shdr_size, &tmp)) return NULL; shdr = malloc(shdr_size); if (!shdr) return NULL; memcpy(shdr, (const uint8_t *)img + offs, shdr_size); /* Check that the data wasn't modified before the copy was completed */ if (shdr_size != SHDR_GET_SIZE(shdr)) { free(shdr); return NULL; } return shdr; } static bool is_weak_hash_algo(uint32_t algo) { return algo == TEE_ALG_MD5 || algo == TEE_ALG_SHA1 || algo == TEE_ALG_MD5SHA1; } TEE_Result shdr_verify_signature(const struct shdr *shdr) { struct rsa_public_key key = { }; TEE_Result res = TEE_SUCCESS; uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); struct ftmn ftmn = { }; unsigned int err_incr = 2; size_t hash_size = 0; size_t hash_algo = 0; if (shdr->magic != SHDR_MAGIC) goto err; if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) goto err; hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); if (is_weak_hash_algo(hash_algo)) goto err; res = tee_alg_get_digest_size(hash_algo, &hash_size); if (res) goto err; if (hash_size != shdr->hash_size) goto err; res = crypto_acipher_alloc_rsa_public_key(&key, ta_pub_key_modulus_size * 8); if (res) goto err; res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); if (res) goto err; res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, key.n); if (res) goto err; FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, crypto_acipher_rsassa_verify, shdr->algo, &key, shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size, SHDR_GET_SIG(shdr), shdr->sig_size); if (!res) { ftmn_checkpoint(&ftmn, FTMN_INCR0); goto out; } err_incr = 1; err: res = TEE_ERROR_SECURITY; FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res); out: FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res); crypto_acipher_free_rsa_public_key(&key); return res; } static const struct shdr_subkey_attr * find_attr(const struct shdr_subkey *subkey, uint32_t id) { size_t n = 0; for (n = 0; n < subkey->attr_count; n++) if (subkey->attrs[n].id == id) return subkey->attrs + n; return NULL; } static TEE_Result load_rsa_key(const struct shdr_subkey *subkey, struct rsa_public_key **key_pp) { const uint8_t *base = (const uint8_t *)subkey; const struct shdr_subkey_attr *pub_exp = NULL; const struct shdr_subkey_attr *modulus = NULL; struct rsa_public_key *key = NULL; TEE_Result res = TEE_SUCCESS; pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT); if (!pub_exp) return TEE_ERROR_SECURITY; modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS); if (!modulus) return TEE_ERROR_SECURITY; key = calloc(1, sizeof(*key)); if (!key) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8); if (res) goto err_key; res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e); if (res) goto err; res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n); if (res) goto err; *key_pp = key; return TEE_SUCCESS; err: crypto_acipher_free_rsa_public_key(key); err_key: free(key); return TEE_ERROR_SECURITY; } static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size) { const struct shdr_subkey_attr *attrs = subkey->attrs; size_t end = 0; size_t n = 0; if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) || ADD_OVERFLOW(end, sizeof(*subkey), &end) || end > img_size) return TEE_ERROR_SECURITY; for (n = 0; n < subkey->attr_count; n++) if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) || end > img_size) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)], const uint8_t my_uuid[sizeof(TEE_UUID)], const void *ns_name, size_t name_size) { TEE_Result res = TEE_ERROR_SECURITY; void *ctx = NULL; struct { uint8_t digest[TEE_SHA1_HASH_SIZE]; TEE_UUID uuid; char name_str[]; } *tmp = NULL; if (!name_size) { memcpy(uuid, my_uuid, sizeof(TEE_UUID)); return TEE_SUCCESS; } /* * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512 * instead for better collision resistance. */ if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512)) return TEE_ERROR_SECURITY; tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size); if (!tmp) goto out_ctx; memcpy(tmp->name_str, ns_name, name_size); if (crypto_hash_init(ctx) || crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) || crypto_hash_update(ctx, (const void *)tmp->name_str, strnlen(tmp->name_str, name_size)) || crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest))) goto out_mempool; tee_uuid_from_octets(&tmp->uuid, tmp->digest); /* * Set the four most significant bits (bits 12 through 15) of the * time_hi_and_version field to 5. */ tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12); tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12); /* * Set the two most significant bits (bits 6 and 7) of the * clock_seq_hi_and_reserved to zero and one, respectively. */ tmp->uuid.clockSeqAndNode[0] &= ~BIT(6); tmp->uuid.clockSeqAndNode[0] |= BIT(7); tee_uuid_to_octets(uuid, &tmp->uuid); res = TEE_SUCCESS; out_mempool: mempool_free(mempool_default, tmp); out_ctx: crypto_hash_free_ctx(ctx); return res; } TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs, const uint8_t *ns_img, size_t ns_img_size, const uint8_t next_uuid[sizeof(TEE_UUID)], uint32_t max_depth, struct shdr_pub_key *key) { struct shdr_subkey *subkey = NULL; TEE_Result res = TEE_SUCCESS; void *digest = NULL; uint8_t *img = NULL; void *ctx = NULL; size_t end = 0; if (shdr->img_type != SHDR_SUBKEY) return TEE_ERROR_SECURITY; if (shdr->img_size < sizeof(*subkey)) return TEE_ERROR_SECURITY; if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size) return TEE_ERROR_SECURITY; img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size); if (!img) return TEE_ERROR_OUT_OF_MEMORY; memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size); subkey = (void *)(img + shdr->hash_size); digest = img; if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) { res = TEE_ERROR_SECURITY; goto out_mempool; } if (crypto_hash_init(ctx) || crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) || crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) || crypto_hash_final(ctx, digest, shdr->hash_size) || memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) { res = TEE_ERROR_SECURITY; goto out_ctx; } res = check_attrs(subkey, shdr->img_size); if (res) goto out_ctx; if (subkey->max_depth >= max_depth) { res = TEE_ERROR_SECURITY; goto out_ctx; } if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) { res = TEE_ERROR_SECURITY; goto out_ctx; } key->max_depth = subkey->max_depth; key->name_size = subkey->name_size; memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID)); if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) || end > ns_img_size) { res = TEE_ERROR_SECURITY; goto out_ctx; } res = calc_next_uuid(key->next_uuid, key->uuid, ns_img + offs + shdr->img_size, key->name_size); if (res) goto out_ctx; key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo); switch (key->main_algo) { case TEE_MAIN_ALGO_RSA: res = load_rsa_key(subkey, &key->pub_key.rsa); break; default: res = TEE_ERROR_SECURITY; break; } out_ctx: crypto_hash_free_ctx(ctx); out_mempool: mempool_free(mempool_default, img); return res; } void shdr_free_pub_key(struct shdr_pub_key *key) { if (key) { switch (key->main_algo) { case TEE_MAIN_ALGO_RSA: crypto_acipher_free_rsa_public_key(key->pub_key.rsa); free(key->pub_key.rsa); break; default: panic(); } } } TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, const struct shdr *shdr) { TEE_Result res = TEE_SUCCESS; unsigned int err_incr = 2; struct ftmn ftmn = { }; size_t hash_size = 0; size_t hash_algo = 0; if (shdr->magic != SHDR_MAGIC) goto err; if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo) goto err; hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); if (is_weak_hash_algo(hash_algo)) goto err; if (tee_alg_get_digest_size(hash_algo, &hash_size) || hash_size != shdr->hash_size) goto err; switch (key->main_algo) { case TEE_MAIN_ALGO_RSA: FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, crypto_acipher_rsassa_verify, shdr->algo, key->pub_key.rsa, shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size, SHDR_GET_SIG(shdr), shdr->sig_size); break; default: panic(); } if (!res) { ftmn_checkpoint(&ftmn, FTMN_INCR0); goto out; } err_incr = 1; err: res = TEE_ERROR_SECURITY; FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res); out: FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res); return res; } optee_os-4.3.0/core/crypto/sm2-kdf.c000066400000000000000000000026451464416617300172350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include /* * GM/T 0003.1‒2012 Part 4 Sections 5.4.2 and 5.4.3 * GM/T 0003.1‒2012 Part 5 Sections 5.4.2 and 5.4.3 * Key derivation function based on the SM3 hash function */ TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, size_t tlen) { TEE_Result res = TEE_SUCCESS; size_t remain = tlen; uint32_t count = 1; uint32_t be_count = 0; void *ctx = NULL; uint8_t *out = t; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) return res; while (remain) { uint8_t tmp[TEE_SM3_HASH_SIZE] = { }; uint8_t *buf = NULL; if (remain >= TEE_SM3_HASH_SIZE) buf = out; else buf = tmp; put_be32(&be_count, count); res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, Z, Z_len); if (res) goto out; res = crypto_hash_update(ctx, (const uint8_t *)&be_count, sizeof(be_count)); if (res) goto out; res = crypto_hash_final(ctx, buf, TEE_SM3_HASH_SIZE); if (res) goto out; if (remain < TEE_SM3_HASH_SIZE) { memcpy(out, tmp, remain); break; } out += TEE_SM3_HASH_SIZE; remain -= TEE_SM3_HASH_SIZE; count++; } out: crypto_hash_free_ctx(ctx); return res; } optee_os-4.3.0/core/crypto/sm3-hash.c000066400000000000000000000047211464416617300174120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited * Copyright (C) 2019 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include "sm3.h" struct sm3_hash_ctx { struct crypto_hash_ctx hash_ctx; struct sm3_context sm3_ctx; }; static const struct crypto_hash_ops sm3_hash_ops; static struct sm3_hash_ctx *to_hash_ctx(struct crypto_hash_ctx *ctx) { assert(ctx && ctx->ops == &sm3_hash_ops); return container_of(ctx, struct sm3_hash_ctx, hash_ctx); } static TEE_Result op_sm3_hash_init(struct crypto_hash_ctx *ctx) { sm3_init(&to_hash_ctx(ctx)->sm3_ctx); return TEE_SUCCESS; } static TEE_Result op_sm3_hash_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { sm3_update(&to_hash_ctx(ctx)->sm3_ctx, data, len); return TEE_SUCCESS; } static TEE_Result op_sm3_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { struct sm3_hash_ctx *hc = to_hash_ctx(ctx); size_t hash_size = TEE_SM3_HASH_SIZE; uint8_t block_digest[TEE_SM3_HASH_SIZE] = { 0 }; uint8_t *tmp_digest = NULL; if (len == 0) return TEE_ERROR_BAD_PARAMETERS; if (hash_size > len) tmp_digest = block_digest; /* use a tempory buffer */ else tmp_digest = digest; sm3_final(&hc->sm3_ctx, tmp_digest); if (hash_size > len) memcpy(digest, tmp_digest, len); return TEE_SUCCESS; } static void op_sm3_hash_free_ctx(struct crypto_hash_ctx *ctx) { struct sm3_hash_ctx *hc = to_hash_ctx(ctx); memzero_explicit(&hc->sm3_ctx, sizeof(hc->sm3_ctx)); free(hc); } static void op_sm3_hash_copy_state(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx) { struct sm3_hash_ctx *src = to_hash_ctx(src_ctx); struct sm3_hash_ctx *dst = to_hash_ctx(dst_ctx); dst->sm3_ctx = src->sm3_ctx; } static const struct crypto_hash_ops sm3_hash_ops = { .init = op_sm3_hash_init, .update = op_sm3_hash_update, .final = op_sm3_hash_final, .free_ctx = op_sm3_hash_free_ctx, .copy_state = op_sm3_hash_copy_state, }; TEE_Result crypto_sm3_alloc_ctx(struct crypto_hash_ctx **ctx) { struct sm3_hash_ctx *hc = NULL; hc = calloc(1, sizeof(*hc)); if (!hc) return TEE_ERROR_OUT_OF_MEMORY; hc->hash_ctx.ops = &sm3_hash_ops; *ctx = &hc->hash_ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/crypto/sm3-hmac.c000066400000000000000000000046701464416617300174020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include "sm3.h" struct sm3_hmac_ctx { struct crypto_mac_ctx mac_ctx; struct sm3_context sm3_ctx; }; static const struct crypto_mac_ops sm3_hmac_ops; static struct sm3_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == &sm3_hmac_ops); return container_of(ctx, struct sm3_hmac_ctx, mac_ctx); } static TEE_Result op_sm3_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { sm3_hmac_init(&to_hmac_ctx(ctx)->sm3_ctx, key, len); return TEE_SUCCESS; } static TEE_Result op_sm3_hmac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { sm3_hmac_update(&to_hmac_ctx(ctx)->sm3_ctx, data, len); return TEE_SUCCESS; } static TEE_Result op_sm3_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { struct sm3_hmac_ctx *c = to_hmac_ctx(ctx); size_t hmac_size = TEE_SM3_HASH_SIZE; uint8_t block_digest[TEE_SM3_HASH_SIZE] = { 0 }; uint8_t *tmp_digest = NULL; if (len == 0) return TEE_ERROR_BAD_PARAMETERS; if (hmac_size > len) tmp_digest = block_digest; /* use a tempory buffer */ else tmp_digest = digest; sm3_hmac_final(&c->sm3_ctx, tmp_digest); if (hmac_size > len) memcpy(digest, tmp_digest, len); return TEE_SUCCESS; } static void op_sm3_hmac_free_ctx(struct crypto_mac_ctx *ctx) { struct sm3_hmac_ctx *c = to_hmac_ctx(ctx); memzero_explicit(&c->sm3_ctx, sizeof(c->sm3_ctx)); free(c); } static void op_sm3_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct sm3_hmac_ctx *src = to_hmac_ctx(src_ctx); struct sm3_hmac_ctx *dst = to_hmac_ctx(dst_ctx); dst->sm3_ctx = src->sm3_ctx; } static const struct crypto_mac_ops sm3_hmac_ops = { .init = op_sm3_hmac_init, .update = op_sm3_hmac_update, .final = op_sm3_hmac_final, .free_ctx = op_sm3_hmac_free_ctx, .copy_state = op_sm3_hmac_copy_state, }; TEE_Result crypto_hmac_sm3_alloc_ctx(struct crypto_mac_ctx **ctx) { struct sm3_hmac_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->mac_ctx.ops = &sm3_hmac_ops; *ctx = &c->mac_ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/crypto/sm3.c000066400000000000000000000157201464416617300164720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ /* * SM3 Hash algorithm * thanks to Xyssl * author:goldboar * email:goldboar@163.com * 2011-10-26 */ #include #include #include #include #include "sm3.h" #define SM3_BLOCK_SIZE 64 #define GET_UINT32_BE(n, b, i) \ do { \ (n) = ((uint32_t)(b)[(i)] << 24) | \ ((uint32_t)(b)[(i) + 1] << 16) | \ ((uint32_t)(b)[(i) + 2] << 8) | \ ((uint32_t)(b)[(i) + 3]); \ } while (0) #define PUT_UINT32_BE(n, b, i) \ do { \ (b)[(i)] = (uint8_t)((n) >> 24); \ (b)[(i) + 1] = (uint8_t)((n) >> 16); \ (b)[(i) + 2] = (uint8_t)((n) >> 8); \ (b)[(i) + 3] = (uint8_t)((n)); \ } while (0) void sm3_init(struct sm3_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x7380166F; ctx->state[1] = 0x4914B2B9; ctx->state[2] = 0x172442D7; ctx->state[3] = 0xDA8A0600; ctx->state[4] = 0xA96F30BC; ctx->state[5] = 0x163138AA; ctx->state[6] = 0xE38DEE4D; ctx->state[7] = 0xB0FB0E4E; } #define SHL(x, n) ((x) << (n)) static uint32_t rotl(uint32_t val, int shift) { shift &= 0x1F; if (shift == 0) return val; return SHL(val, shift) | (val >> (32 - shift)); } #define ROTL(x, n) rotl((x), (n)) static void __maybe_unused sm3_process(struct sm3_context *ctx, const uint8_t data[64]) { uint32_t SS1, SS2, TT1, TT2, W[68], W1[64]; uint32_t A, B, C, D, E, F, G, H; uint32_t T[64]; uint32_t Temp1, Temp2, Temp3, Temp4, Temp5; int j; for (j = 0; j < 16; j++) T[j] = 0x79CC4519; for (j = 16; j < 64; j++) T[j] = 0x7A879D8A; GET_UINT32_BE(W[0], data, 0); GET_UINT32_BE(W[1], data, 4); GET_UINT32_BE(W[2], data, 8); GET_UINT32_BE(W[3], data, 12); GET_UINT32_BE(W[4], data, 16); GET_UINT32_BE(W[5], data, 20); GET_UINT32_BE(W[6], data, 24); GET_UINT32_BE(W[7], data, 28); GET_UINT32_BE(W[8], data, 32); GET_UINT32_BE(W[9], data, 36); GET_UINT32_BE(W[10], data, 40); GET_UINT32_BE(W[11], data, 44); GET_UINT32_BE(W[12], data, 48); GET_UINT32_BE(W[13], data, 52); GET_UINT32_BE(W[14], data, 56); GET_UINT32_BE(W[15], data, 60); #define FF0(x, y, z) ((x) ^ (y) ^ (z)) #define FF1(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) #define GG0(x, y, z) ((x) ^ (y) ^ (z)) #define GG1(x, y, z) (((x) & (y)) | ((~(x)) & (z))) #define P0(x) ((x) ^ ROTL((x), 9) ^ ROTL((x), 17)) #define P1(x) ((x) ^ ROTL((x), 15) ^ ROTL((x), 23)) for (j = 16; j < 68; j++) { /* * W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^ * ROTL(W[j - 13],7 ) ^ W[j-6]; */ Temp1 = W[j - 16] ^ W[j - 9]; Temp2 = ROTL(W[j - 3], 15); Temp3 = Temp1 ^ Temp2; Temp4 = P1(Temp3); Temp5 = ROTL(W[j - 13], 7) ^ W[j - 6]; W[j] = Temp4 ^ Temp5; } for (j = 0; j < 64; j++) W1[j] = W[j] ^ W[j + 4]; A = ctx->state[0]; B = ctx->state[1]; C = ctx->state[2]; D = ctx->state[3]; E = ctx->state[4]; F = ctx->state[5]; G = ctx->state[6]; H = ctx->state[7]; for (j = 0; j < 16; j++) { SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7); SS2 = SS1 ^ ROTL(A, 12); TT1 = FF0(A, B, C) + D + SS2 + W1[j]; TT2 = GG0(E, F, G) + H + SS1 + W[j]; D = C; C = ROTL(B, 9); B = A; A = TT1; H = G; G = ROTL(F, 19); F = E; E = P0(TT2); } for (j = 16; j < 64; j++) { SS1 = ROTL(ROTL(A, 12) + E + ROTL(T[j], j), 7); SS2 = SS1 ^ ROTL(A, 12); TT1 = FF1(A, B, C) + D + SS2 + W1[j]; TT2 = GG1(E, F, G) + H + SS1 + W[j]; D = C; C = ROTL(B, 9); B = A; A = TT1; H = G; G = ROTL(F, 19); F = E; E = P0(TT2); } ctx->state[0] ^= A; ctx->state[1] ^= B; ctx->state[2] ^= C; ctx->state[3] ^= D; ctx->state[4] ^= E; ctx->state[5] ^= F; ctx->state[6] ^= G; ctx->state[7] ^= H; } static void sm3_process_blocks(struct sm3_context *ctx, const uint8_t *input, unsigned int block_count) { #ifdef CFG_CRYPTO_SM3_ARM_CE if (block_count) crypto_accel_sm3_compress(ctx->state, input, block_count); #else unsigned int n = 0; for (n = 0; n < block_count; n++) sm3_process(ctx, input + n * SM3_BLOCK_SIZE); #endif } void sm3_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen) { unsigned int block_count = 0; size_t fill = 0; size_t left = 0; if (!ilen) return; left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += ilen; if (ctx->total[0] < ilen) ctx->total[1]++; if (left && ilen >= fill) { memcpy(ctx->buffer + left, input, fill); sm3_process_blocks(ctx, ctx->buffer, 1); input += fill; ilen -= fill; left = 0; } block_count = ilen / SM3_BLOCK_SIZE; sm3_process_blocks(ctx, input, block_count); ilen -= block_count * SM3_BLOCK_SIZE; input += block_count * SM3_BLOCK_SIZE; if (ilen > 0) memcpy(ctx->buffer + left, input, ilen); } static const uint8_t sm3_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void sm3_final(struct sm3_context *ctx, uint8_t output[32]) { uint32_t last, padn; uint32_t high, low; uint8_t msglen[8]; high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = ctx->total[0] << 3; PUT_UINT32_BE(high, msglen, 0); PUT_UINT32_BE(low, msglen, 4); last = ctx->total[0] & 0x3F; padn = (last < 56) ? (56 - last) : (120 - last); sm3_update(ctx, sm3_padding, padn); sm3_update(ctx, msglen, 8); PUT_UINT32_BE(ctx->state[0], output, 0); PUT_UINT32_BE(ctx->state[1], output, 4); PUT_UINT32_BE(ctx->state[2], output, 8); PUT_UINT32_BE(ctx->state[3], output, 12); PUT_UINT32_BE(ctx->state[4], output, 16); PUT_UINT32_BE(ctx->state[5], output, 20); PUT_UINT32_BE(ctx->state[6], output, 24); PUT_UINT32_BE(ctx->state[7], output, 28); } void sm3(const uint8_t *input, size_t ilen, uint8_t output[32]) { struct sm3_context ctx = { }; sm3_init(&ctx); sm3_update(&ctx, input, ilen); sm3_final(&ctx, output); memzero_explicit(&ctx, sizeof(ctx)); } void sm3_hmac_init(struct sm3_context *ctx, const uint8_t *key, size_t keylen) { size_t i; uint8_t sum[32]; if (keylen > 64) { sm3(key, keylen, sum); keylen = 32; key = sum; } memset(ctx->ipad, 0x36, 64); memset(ctx->opad, 0x5C, 64); for (i = 0; i < keylen; i++) { ctx->ipad[i] ^= key[i]; ctx->opad[i] ^= key[i]; } sm3_init(ctx); sm3_update(ctx, ctx->ipad, 64); memzero_explicit(sum, sizeof(sum)); } void sm3_hmac_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen) { sm3_update(ctx, input, ilen); } void sm3_hmac_final(struct sm3_context *ctx, uint8_t output[32]) { uint8_t tmpbuf[32]; sm3_final(ctx, tmpbuf); sm3_init(ctx); sm3_update(ctx, ctx->opad, 64); sm3_update(ctx, tmpbuf, 32); sm3_final(ctx, output); memzero_explicit(tmpbuf, sizeof(tmpbuf)); } void sm3_hmac(const uint8_t *key, size_t keylen, const uint8_t *input, size_t ilen, uint8_t output[32]) { struct sm3_context ctx; sm3_hmac_init(&ctx, key, keylen); sm3_hmac_update(&ctx, input, ilen); sm3_hmac_final(&ctx, output); memzero_explicit(&ctx, sizeof(ctx)); } optee_os-4.3.0/core/crypto/sm3.h000066400000000000000000000022641464416617300164760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ /** * \file sm3.h * thanks to Xyssl * author:goldboar * email:goldboar@163.com * 2011-10-26 */ #ifndef CORE_CRYPTO_SM3_H #define CORE_CRYPTO_SM3_H #include #include struct sm3_context { uint32_t total[2]; /* number of bytes processed */ uint32_t state[8]; /* intermediate digest state */ uint8_t buffer[64]; /* data block being processed */ uint8_t ipad[64]; /* HMAC: inner padding */ uint8_t opad[64]; /* HMAC: outer padding */ }; void sm3_init(struct sm3_context *ctx); void sm3_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen); void sm3_final(struct sm3_context *ctx, uint8_t output[32]); void sm3(const uint8_t *input, size_t ilen, uint8_t output[32]); void sm3_hmac_init(struct sm3_context *ctx, const uint8_t *key, size_t keylen); void sm3_hmac_update(struct sm3_context *ctx, const uint8_t *input, size_t ilen); void sm3_hmac_final(struct sm3_context *ctx, uint8_t output[32]); void sm3_hmac(const uint8_t *key, size_t keylen, const uint8_t *input, size_t ilen, uint8_t output[32]); #endif /* CORE_CRYPTO_SM3_H */ optee_os-4.3.0/core/crypto/sm4-cbc.c000066400000000000000000000046731464416617300172250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include "sm4.h" struct sm4_cbc_ctx { struct crypto_cipher_ctx ctx; struct sm4_context state; uint8_t iv[16]; }; static const struct crypto_cipher_ops sm4_cbc_ops; static struct sm4_cbc_ctx *to_sm4_cbc_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &sm4_cbc_ops); return container_of(ctx, struct sm4_cbc_ctx, ctx); } static TEE_Result sm4_cbc_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv, size_t iv_len) { struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); if (key1_len != 16 || iv_len != sizeof(c->iv)) return TEE_ERROR_BAD_PARAMETERS; if (mode == TEE_MODE_ENCRYPT) sm4_setkey_enc(&c->state, key1); else sm4_setkey_dec(&c->state, key1); memcpy(c->iv, iv, sizeof(c->iv)); return TEE_SUCCESS; } static TEE_Result sm4_cbc_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); sm4_crypt_cbc(&c->state, len, c->iv, data, dst); return TEE_SUCCESS; } static void sm4_cbc_final(struct crypto_cipher_ctx *ctx) { struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); memzero_explicit(&c->state, sizeof(c->state)); memzero_explicit(&c->iv, sizeof(c->iv)); } static void sm4_cbc_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_sm4_cbc_ctx(ctx)); } static void sm4_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct sm4_cbc_ctx *src = to_sm4_cbc_ctx(src_ctx); struct sm4_cbc_ctx *dst = to_sm4_cbc_ctx(dst_ctx); dst->state = src->state; memcpy(dst->iv, src->iv, sizeof(src->iv)); } static const struct crypto_cipher_ops sm4_cbc_ops = { .init = sm4_cbc_init, .update = sm4_cbc_update, .final = sm4_cbc_final, .free_ctx = sm4_cbc_free_ctx, .copy_state = sm4_cbc_copy_state, }; TEE_Result crypto_sm4_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct sm4_cbc_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &sm4_cbc_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/crypto/sm4-ctr.c000066400000000000000000000046161464416617300172630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include "sm4.h" struct sm4_ctr_ctx { struct crypto_cipher_ctx ctx; struct sm4_context state; uint8_t ctr[16]; }; static const struct crypto_cipher_ops sm4_ctr_ops; static struct sm4_ctr_ctx *to_sm4_ctr_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &sm4_ctr_ops); return container_of(ctx, struct sm4_ctr_ctx, ctx); } static TEE_Result sm4_ctr_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode __unused, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv, size_t iv_len) { struct sm4_ctr_ctx *c = to_sm4_ctr_ctx(ctx); if (key1_len != 16 || iv_len != sizeof(c->ctr)) return TEE_ERROR_BAD_PARAMETERS; sm4_setkey_enc(&c->state, key1); memcpy(c->ctr, iv, sizeof(c->ctr)); return TEE_SUCCESS; } static TEE_Result sm4_ctr_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct sm4_ctr_ctx *c = to_sm4_ctr_ctx(ctx); sm4_crypt_ctr(&c->state, len, c->ctr, data, dst); return TEE_SUCCESS; } static void sm4_ctr_final(struct crypto_cipher_ctx *ctx) { struct sm4_ctr_ctx *c = to_sm4_ctr_ctx(ctx); memzero_explicit(&c->state, sizeof(c->state)); memzero_explicit(&c->ctr, sizeof(c->ctr)); } static void sm4_ctr_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_sm4_ctr_ctx(ctx)); } static void sm4_ctr_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct sm4_ctr_ctx *src = to_sm4_ctr_ctx(src_ctx); struct sm4_ctr_ctx *dst = to_sm4_ctr_ctx(dst_ctx); dst->state = src->state; memcpy(dst->ctr, src->ctr, sizeof(src->ctr)); } static const struct crypto_cipher_ops sm4_ctr_ops = { .init = sm4_ctr_init, .update = sm4_ctr_update, .final = sm4_ctr_final, .free_ctx = sm4_ctr_free_ctx, .copy_state = sm4_ctr_copy_state, }; TEE_Result crypto_sm4_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct sm4_ctr_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &sm4_ctr_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/crypto/sm4-ecb.c000066400000000000000000000044211464416617300172160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include "sm4.h" struct sm4_ecb_ctx { struct crypto_cipher_ctx ctx; struct sm4_context state; }; static const struct crypto_cipher_ops sm4_ecb_ops; static struct sm4_ecb_ctx *to_sm4_ecb_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &sm4_ecb_ops); return container_of(ctx, struct sm4_ecb_ctx, ctx); } static TEE_Result sm4_ecb_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct sm4_ecb_ctx *c = to_sm4_ecb_ctx(ctx); if (key1_len != 16) return TEE_ERROR_BAD_STATE; if (mode == TEE_MODE_ENCRYPT) sm4_setkey_enc(&c->state, key1); else sm4_setkey_dec(&c->state, key1); return TEE_SUCCESS; } static TEE_Result sm4_ecb_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct sm4_ecb_ctx *c = to_sm4_ecb_ctx(ctx); sm4_crypt_ecb(&c->state, len, data, dst); return TEE_SUCCESS; } static void sm4_ecb_final(struct crypto_cipher_ctx *ctx) { struct sm4_ecb_ctx *c = to_sm4_ecb_ctx(ctx); memzero_explicit(&c->state, sizeof(c->state)); } static void sm4_ecb_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_sm4_ecb_ctx(ctx)); } static void sm4_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct sm4_ecb_ctx *src = to_sm4_ecb_ctx(src_ctx); struct sm4_ecb_ctx *dst = to_sm4_ecb_ctx(dst_ctx); dst->state = src->state; } static const struct crypto_cipher_ops sm4_ecb_ops = { .init = sm4_ecb_init, .update = sm4_ecb_update, .final = sm4_ecb_final, .free_ctx = sm4_ecb_free_ctx, .copy_state = sm4_ecb_copy_state, }; TEE_Result crypto_sm4_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct sm4_ecb_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &sm4_ecb_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/crypto/sm4-xts.c000066400000000000000000000054261464416617300173110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include "sm4.h" struct sm4_xts_ctx { struct crypto_cipher_ctx ctx; struct sm4_context state; struct sm4_context state_ek; struct sm4_context state_dk; uint8_t iv[16]; }; static const struct crypto_cipher_ops sm4_xts_ops; static struct sm4_xts_ctx *to_sm4_xts_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &sm4_xts_ops); return container_of(ctx, struct sm4_xts_ctx, ctx); } static TEE_Result sm4_xts_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len) { struct sm4_xts_ctx *c = to_sm4_xts_ctx(ctx); if (key1_len != 16 || key2_len != 16 || iv_len != sizeof(c->iv)) return TEE_ERROR_BAD_STATE; if (iv) memcpy(c->iv, iv, sizeof(c->iv)); if (mode == TEE_MODE_ENCRYPT) sm4_setkey_enc(&c->state, key1); else sm4_setkey_dec(&c->state, key1); sm4_setkey_enc(&c->state_ek, key2); sm4_setkey_dec(&c->state_dk, key2); return TEE_SUCCESS; } static TEE_Result sm4_xts_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct sm4_xts_ctx *c = to_sm4_xts_ctx(ctx); sm4_crypt_xts(&c->state, &c->state_ek, &c->state_dk, len, c->iv, data, dst); return TEE_SUCCESS; } static void sm4_xts_final(struct crypto_cipher_ctx *ctx) { struct sm4_xts_ctx *c = to_sm4_xts_ctx(ctx); memzero_explicit(&c->state, sizeof(c->state)); memzero_explicit(&c->state_ek, sizeof(c->state_ek)); memzero_explicit(&c->state_dk, sizeof(c->state_dk)); memzero_explicit(&c->iv, sizeof(c->iv)); } static void sm4_xts_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_sm4_xts_ctx(ctx)); } static void sm4_xts_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct sm4_xts_ctx *src = to_sm4_xts_ctx(src_ctx); struct sm4_xts_ctx *dst = to_sm4_xts_ctx(dst_ctx); dst->state = src->state; dst->state_ek = src->state_ek; dst->state_dk = src->state_dk; memcpy(dst->iv, src->iv, sizeof(src->iv)); } static const struct crypto_cipher_ops sm4_xts_ops = { .init = sm4_xts_init, .update = sm4_xts_update, .final = sm4_xts_final, .free_ctx = sm4_xts_free_ctx, .copy_state = sm4_xts_copy_state, }; TEE_Result crypto_sm4_xts_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct sm4_xts_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &sm4_xts_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/crypto/sm4.c000066400000000000000000000205671464416617300165000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright Copyright (c) 2019 Huawei Technologies Co., Ltd */ /* * SM4 Encryption algorithm (SMS4 algorithm) * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/ * thanks to Xyssl * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html * author:goldboar * email:goldboar@163.com * 2012-4-20 */ #include "sm4.h" #include #include #define GET_UINT32_BE(n, b, i) \ do { \ (n) = ((uint32_t)(b)[(i)] << 24) | \ ((uint32_t)(b)[(i) + 1] << 16) | \ ((uint32_t)(b)[(i) + 2] << 8) | \ ((uint32_t)(b)[(i) + 3]); \ } while (0) #define PUT_UINT32_BE(n, b, i) \ do { \ (b)[(i)] = (uint8_t)((n) >> 24); \ (b)[(i) + 1] = (uint8_t)((n) >> 16); \ (b)[(i) + 2] = (uint8_t)((n) >> 8); \ (b)[(i) + 3] = (uint8_t)((n)); \ } while (0) #define SHL(x, n) (((x) & 0xFFFFFFFF) << (n)) #define ROTL(x, n) (SHL((x), (n)) | ((x) >> (32 - (n)))) #define SWAP(a, b) { uint32_t t = a; a = b; b = t; t = 0; } /* * Expanded SM4 S-boxes */ static const uint8_t SboxTable[16][16] = { {0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05}, {0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99}, {0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62}, {0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6}, {0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8}, {0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35}, {0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87}, {0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e}, {0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1}, {0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3}, {0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f}, {0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51}, {0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8}, {0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0}, {0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84}, {0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48} }; /* System parameter */ static const uint32_t FK[4] = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc }; /* Fixed parameter */ static const uint32_t CK[32] = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 }; static uint8_t sm4Sbox(uint8_t inch) { uint8_t *tab = (uint8_t *)SboxTable; return tab[inch]; } static uint32_t sm4Lt(uint32_t ka) { uint32_t bb = 0; uint8_t a[4]; uint8_t b[4]; PUT_UINT32_BE(ka, a, 0); b[0] = sm4Sbox(a[0]); b[1] = sm4Sbox(a[1]); b[2] = sm4Sbox(a[2]); b[3] = sm4Sbox(a[3]); GET_UINT32_BE(bb, b, 0); return bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24); } static uint32_t sm4F(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t rk) { return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk); } static uint32_t sm4CalciRK(uint32_t ka) { uint32_t bb = 0; uint8_t a[4]; uint8_t b[4]; PUT_UINT32_BE(ka, a, 0); b[0] = sm4Sbox(a[0]); b[1] = sm4Sbox(a[1]); b[2] = sm4Sbox(a[2]); b[3] = sm4Sbox(a[3]); GET_UINT32_BE(bb, b, 0); return bb ^ ROTL(bb, 13) ^ ROTL(bb, 23); } static void sm4_setkey(uint32_t SK[32], const uint8_t key[16]) { uint32_t MK[4]; uint32_t k[36]; uint32_t i = 0; GET_UINT32_BE(MK[0], key, 0); GET_UINT32_BE(MK[1], key, 4); GET_UINT32_BE(MK[2], key, 8); GET_UINT32_BE(MK[3], key, 12); k[0] = MK[0] ^ FK[0]; k[1] = MK[1] ^ FK[1]; k[2] = MK[2] ^ FK[2]; k[3] = MK[3] ^ FK[3]; for (i = 0; i < 32; i++) { k[i + 4] = k[i] ^ sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]); SK[i] = k[i + 4]; } } static void sm4_one_round(uint32_t sk[32], const uint8_t input[16], uint8_t output[16]) { uint32_t i = 0; uint32_t ulbuf[36]; memset(ulbuf, 0, sizeof(ulbuf)); GET_UINT32_BE(ulbuf[0], input, 0); GET_UINT32_BE(ulbuf[1], input, 4); GET_UINT32_BE(ulbuf[2], input, 8); GET_UINT32_BE(ulbuf[3], input, 12); for (i = 0; i < 32; i++) ulbuf[i + 4] = sm4F(ulbuf[i], ulbuf[i + 1], ulbuf[i + 2], ulbuf[i + 3], sk[i]); PUT_UINT32_BE(ulbuf[35], output, 0); PUT_UINT32_BE(ulbuf[34], output, 4); PUT_UINT32_BE(ulbuf[33], output, 8); PUT_UINT32_BE(ulbuf[32], output, 12); } void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16]) { ctx->mode = SM4_ENCRYPT; sm4_setkey(ctx->sk, key); } void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16]) { int i; ctx->mode = SM4_DECRYPT; sm4_setkey(ctx->sk, key); for (i = 0; i < 16; i++) SWAP(ctx->sk[i], ctx->sk[31 - i]); } void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input, uint8_t *output) { assert(!(length % 16)); while (length > 0) { sm4_one_round(ctx->sk, input, output); input += 16; output += 16; length -= 16; } } void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16], const uint8_t *input, uint8_t *output) { int i; uint8_t temp[16]; assert(!(length % 16)); if (ctx->mode == SM4_ENCRYPT) { while (length > 0) { for (i = 0; i < 16; i++) output[i] = (uint8_t)(input[i] ^ iv[i]); sm4_one_round(ctx->sk, output, output); memcpy(iv, output, 16); input += 16; output += 16; length -= 16; } } else { /* SM4_DECRYPT */ while (length > 0) { memcpy(temp, input, 16); sm4_one_round(ctx->sk, input, output); for (i = 0; i < 16; i++) output[i] = (uint8_t)(output[i] ^ iv[i]); memcpy(iv, temp, 16); input += 16; output += 16; length -= 16; } } } void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16], const uint8_t *input, uint8_t *output) { int i; uint8_t temp[16]; assert(!(length % 16)); while (length > 0) { memcpy(temp, ctr, 16); sm4_one_round(ctx->sk, ctr, ctr); for (i = 0; i < 16; i++) output[i] = (uint8_t)(input[i] ^ ctr[i]); memcpy(ctr, temp, 16); for (i = 16; i > 0; i--) if (++ctr[i - 1]) break; input += 16; output += 16; length -= 16; } } static void xts_multi(unsigned char *in, unsigned char *out) { uint8_t tt = 0; uint8_t t = 0; int i = 0; for (i = 0; i < 16; i++) { tt = in[i] >> 7; out[i] = ((in[i] << 1) | t) & 0xFF; t = tt; } out[0] ^= (0x87 & (0 - tt)); } static void xor_128(const uint8_t a[16], const uint8_t b[16], uint8_t c[16]) { int i = 0; for (i = 0; i < 16; i++) c[i] = a[i] ^ b[i]; } void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek, struct sm4_context *ctx_dk, size_t len, uint8_t *iv, const uint8_t *input, uint8_t *output) { uint8_t tweak[16] = { }; uint8_t tweak1[16] = { }; uint8_t ct[16] = { }; size_t i = 0; assert(len >= 16); sm4_one_round(ctx_ek->sk, iv, tweak); if (ctx->mode == SM4_DECRYPT && (len % 16)) len -= 16; while (len >= 16) { xor_128(input, tweak, ct); sm4_one_round(ctx->sk, ct, ct); xor_128(ct, tweak, output); xts_multi(tweak, tweak); len -= 16; if (len == 0) { sm4_one_round(ctx_dk->sk, tweak, iv); return; } input += 16; output += 16; } if (ctx->mode == SM4_ENCRYPT) { memcpy(ct, output - 16, 16); for (i = 0; i < len; i++) { output[i] = ct[i]; ct[i] = input[i]; } xor_128(ct, tweak, ct); sm4_one_round(ctx->sk, ct, ct); xor_128(ct, tweak, ct); memcpy(output - 16, ct, 16); } else { xts_multi(tweak, tweak1); xor_128(input, tweak1, ct); sm4_one_round(ctx->sk, ct, ct); xor_128(ct, tweak1, ct); for (i = 0; i < len; ++i) { output[16 + i] = ct[i]; ct[i] = input[16 + i]; } xor_128(ct, tweak, ct); sm4_one_round(ctx->sk, ct, ct); xor_128(ct, tweak, output); } } optee_os-4.3.0/core/crypto/sm4.h000066400000000000000000000020251464416617300164720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ #ifndef CORE_CRYPTO_SM4_H #define CORE_CRYPTO_SM4_H #include #include #define SM4_ENCRYPT 1 #define SM4_DECRYPT 0 struct sm4_context { int mode; /* SM4_ENCRYPT/SM4_DECRYPT */ uint32_t sk[32]; /* SM4 subkeys */ }; void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16]); void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16]); void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input, uint8_t *output); void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16], const uint8_t *input, uint8_t *output); void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16], const uint8_t *input, uint8_t *output); void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek, struct sm4_context *ctx_dk, size_t length, uint8_t *iv, const uint8_t *input, uint8_t *output); #endif /* CORE_CRYPTO_SM4_H */ optee_os-4.3.0/core/crypto/sm4_accel.c000066400000000000000000000032221464416617300176140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) Hisilicon Technologies Co., Ltd. 2023. All rights reserved. * * SM4 optimization for ARMv8 */ #include "sm4.h" #include #include #include void sm4_setkey_enc(struct sm4_context *ctx, const uint8_t key[16]) { ctx->mode = SM4_ENCRYPT; crypto_accel_sm4_setkey_enc(ctx->sk, key); } void sm4_setkey_dec(struct sm4_context *ctx, const uint8_t key[16]) { ctx->mode = SM4_DECRYPT; crypto_accel_sm4_setkey_dec(ctx->sk, key); } void sm4_crypt_ecb(struct sm4_context *ctx, size_t length, const uint8_t *input, uint8_t *output) { assert(!(length % 16)); crypto_accel_sm4_ecb_enc(output, input, ctx->sk, length); } void sm4_crypt_cbc(struct sm4_context *ctx, size_t length, uint8_t iv[16], const uint8_t *input, uint8_t *output) { assert(!(length % 16)); if (ctx->mode == SM4_ENCRYPT) crypto_accel_sm4_cbc_enc(output, input, ctx->sk, length, iv); else /* SM4_DECRYPT */ crypto_accel_sm4_cbc_dec(output, input, ctx->sk, length, iv); } void sm4_crypt_ctr(struct sm4_context *ctx, size_t length, uint8_t ctr[16], const uint8_t *input, uint8_t *output) { assert(!(length % 16)); crypto_accel_sm4_ctr_enc(output, input, ctx->sk, length, ctr); } void sm4_crypt_xts(struct sm4_context *ctx, struct sm4_context *ctx_ek, struct sm4_context *ctx_dk __unused, size_t len, uint8_t *iv, const uint8_t *input, uint8_t *output) { assert(len >= 16); if (ctx->mode == SM4_ENCRYPT) crypto_accel_sm4_xts_enc(output, input, ctx->sk, ctx_ek->sk, len, iv); else crypto_accel_sm4_xts_dec(output, input, ctx->sk, ctx_ek->sk, len, iv); } optee_os-4.3.0/core/crypto/sub.mk000066400000000000000000000020141464416617300167360ustar00rootroot00000000000000srcs-y += crypto.c ifeq (y-y,$(CFG_CRYPTO_AES)-$(CFG_CRYPTO_GCM)) srcs-y += aes-gcm.c ifneq ($(CFG_CRYPTO_WITH_CE),y) srcs-y += aes-gcm-sw.c ifeq ($(CFG_AES_GCM_TABLE_BASED),y) srcs-y += aes-gcm-ghash-tbl.c endif endif endif srcs-$(CFG_WITH_USER_TA) += signed_hdr.c ifeq ($(CFG_WITH_SOFTWARE_PRNG),y) srcs-y += rng_fortuna.c else srcs-y += rng_hw.c endif ifneq ($(CFG_CRYPTO_CBC_MAC_FROM_CRYPTOLIB),y) srcs-$(CFG_CRYPTO_CBC_MAC) += cbc-mac.c endif ifneq ($(CFG_CRYPTO_CTS_FROM_CRYPTOLIB),y) srcs-$(CFG_CRYPTO_CTS) += aes-cts.c endif ifneq (,$(filter y,$(CFG_CRYPTO_SM2_PKE) $(CFG_CRYPTO_SM2_KEP))) srcs-y += sm2-kdf.c endif ifeq ($(CFG_CRYPTO_SM3),y) srcs-y += sm3.c srcs-y += sm3-hash.c srcs-$(CFG_CRYPTO_HMAC) += sm3-hmac.c endif ifeq ($(CFG_CRYPTO_SM4),y) ifeq ($(CFG_CORE_CRYPTO_SM4_ACCEL)-$(CFG_ARM64_core),y-y) srcs-$(CFG_ARM64_core) += sm4_accel.c else srcs-y += sm4.c endif srcs-$(CFG_CRYPTO_ECB) += sm4-ecb.c srcs-$(CFG_CRYPTO_CBC) += sm4-cbc.c srcs-$(CFG_CRYPTO_CTR) += sm4-ctr.c srcs-$(CFG_CRYPTO_XTS) += sm4-xts.c endif optee_os-4.3.0/core/drivers/000077500000000000000000000000001464416617300157555ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/amlogic_uart.c000066400000000000000000000033251464416617300205720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020 Carlo Caione */ #include #include #include #include #include /* Registers */ #define AML_UART_WFIFO 0x0000 #define AML_UART_RFIFO 0x0004 #define AML_UART_CONTROL 0x0008 #define AML_UART_STATUS 0x000C #define AML_UART_MISC 0x0010 #define AML_UART_SIZE 0x0014 /* AML_UART_STATUS bits */ #define AML_UART_RX_EMPTY BIT(20) #define AML_UART_TX_FULL BIT(21) #define AML_UART_TX_EMPTY BIT(22) static vaddr_t chip_to_base(struct serial_chip *chip) { struct amlogic_uart_data *pd = container_of(chip, struct amlogic_uart_data, chip); return io_pa_or_va(&pd->base, AML_UART_SIZE); } static void amlogic_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + AML_UART_STATUS) & AML_UART_TX_EMPTY)) ; } static int amlogic_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); if (io_read32(base + AML_UART_STATUS) & AML_UART_RX_EMPTY) return -1; return io_read32(base + AML_UART_RFIFO) & 0xff; } static void amlogic_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); while (io_read32(base + AML_UART_STATUS) & AML_UART_TX_FULL) ; io_write32(base + AML_UART_WFIFO, ch); } static const struct serial_ops amlogic_uart_ops = { .flush = amlogic_uart_flush, .getchar = amlogic_uart_getchar, .putc = amlogic_uart_putc, }; void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base) { pd->base.pa = base; pd->chip.ops = &amlogic_uart_ops; /* * Do nothing, debug uart (AO) shared with normal world, everything for * uart initialization is done in bootloader. */ } optee_os-4.3.0/core/drivers/atmel_piobu.c000066400000000000000000000301331464416617300204210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip * * Driver for AT91 PIOBU */ #include #include #include #include #include #include #include #include #include #include #include #include #define SECUMOD_MAX_PINS (piobu_device->compat->max_pins) #define SECUMOD_PIN_MASK (BIT(SECUMOD_MAX_PINS) - 1) #define SECUMOD_PIN_SHIFT 16 #define SECUMOD_PIN_VAL(pin) BIT(SECUMOD_PIN_SHIFT + (pin)) #define DT_GPIO_CELLS 2 #define SECUMOD_CR 0x0 #define SECUMOD_CR_KEY_SHIFT 16 #define SECUMOD_CR_KEY SHIFT_U32(0x89CA, SECUMOD_CR_KEY_SHIFT) #define SECUMOD_CR_BACKUP BIT(0) #define SECUMOD_CR_NORMAL BIT(1) #define SECUMOD_SR 0x8 #define SECUMOD_SR_JTAG BIT(3) #define SECUMOD_SR_TST_PIN BIT(2) #define SECUMOD_SCR 0x10 #define SECUMOD_PIOBU(x) (0x18 + (x) * 0x4) #define SECUMOD_PIOBU_AFV_MASK GENMASK_32(3, 0) #define SECUMOD_PIOBU_RFV_SHIFT 4 #define SECUMOD_PIOBU_OUTPUT BIT(8) #define SECUMOD_PIOBU_SOD BIT(9) #define SECUMOD_PIOBU_PDS BIT(10) #define SECUMOD_PIOBU_PULLUP_SHIFT 12 #define SECUMOD_PIOBU_SWITCH_SHIFT 15 #define SECUMOD_JTAGCR_FNTRST 0x1 /* * PIOBU instance data * @compat - Reference to compat data passed at driver initialization */ struct piobu_instance { struct piobu_compat *compat; }; /* * @max_pins the number of the tamper I/Os * @of_jtagcr offset of SECUMOD JTAG Protection Control Register * @of_bmpr offset of SECUMOD Backup Mode Protection Register * @of_nmpr offset of SECUMOD Normal Mode Protection Register * @of_niepr offset of SECUMOD Normal Interrupt Enable Protection Register * @of_nidpr offset of SECUMOD Normal Interrupt Disable Protection Register * @of_nimpr offset of SECUMOD Normal Interrupt Mask Protection Register * @of_wkpr offset of SECUMOD Wake-up Register */ struct piobu_compat { uint8_t max_pins; uint8_t of_jtagcr; uint8_t of_bmpr; uint8_t of_nmpr; uint8_t of_niepr; uint8_t of_nidpr; uint8_t of_nimpr; uint8_t of_wkpr; }; /* Expects at most a single instance */ static struct piobu_instance *piobu_device; static vaddr_t secumod_base; static uint32_t gpio_protected; static struct gpio_chip secumod_chip; /* * Get value from GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin from which value needs to be read * Return target GPIO pin level. */ static enum gpio_level secumod_gpio_get_value(struct gpio_chip *chip __unused, unsigned int gpio_pin) { vaddr_t piobu_addr = 0; uint32_t piobu = 0; assert(gpio_pin < SECUMOD_MAX_PINS && !(gpio_protected & BIT32(gpio_pin))); piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); piobu = io_read32(piobu_addr); if (piobu & SECUMOD_PIOBU_PDS) return GPIO_LEVEL_HIGH; else return GPIO_LEVEL_LOW; } /* * Set value for GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin to which value needs to be written * value: Level state for the target pin */ static void secumod_gpio_set_value(struct gpio_chip *chip __unused, unsigned int gpio_pin, enum gpio_level value) { vaddr_t piobu_addr = 0; assert(gpio_pin < SECUMOD_MAX_PINS && !(gpio_protected & BIT32(gpio_pin))); piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); if (value == GPIO_LEVEL_HIGH) io_setbits32(piobu_addr, SECUMOD_PIOBU_SOD); else io_clrbits32(piobu_addr, SECUMOD_PIOBU_SOD); } /* * Get direction from GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin from which direction needs to be read */ static enum gpio_dir secumod_gpio_get_direction(struct gpio_chip *chip __unused, unsigned int gpio_pin) { vaddr_t piobu_addr = 0; uint32_t piobu = 0; assert(gpio_pin < SECUMOD_MAX_PINS && !(gpio_protected & BIT32(gpio_pin))); piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); piobu = io_read32(piobu_addr); if (piobu & SECUMOD_PIOBU_OUTPUT) return GPIO_DIR_OUT; else return GPIO_DIR_IN; } /* * Set direction for GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin on which direction needs to be set * direction: direction which needs to be set on pin */ static void secumod_gpio_set_direction(struct gpio_chip *chip __unused, unsigned int gpio_pin, enum gpio_dir direction) { vaddr_t piobu_addr = 0; assert(gpio_pin < SECUMOD_MAX_PINS && !(gpio_protected & BIT32(gpio_pin))); piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); if (direction == GPIO_DIR_OUT) io_setbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); else io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); } /* * Get interrupt from GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin from which interrupt value needs to be read */ static enum gpio_interrupt secumod_gpio_get_interrupt(struct gpio_chip *chip __unused, unsigned int gpio_pin) { vaddr_t nimpr_addr = secumod_base + piobu_device->compat->of_nimpr; uint32_t data = 0; assert(gpio_pin < SECUMOD_MAX_PINS && !(gpio_protected & BIT32(gpio_pin))); data = io_read32(nimpr_addr); if (data & SECUMOD_PIN_VAL(gpio_pin)) return GPIO_INTERRUPT_ENABLE; else return GPIO_INTERRUPT_DISABLE; } /* * Set interrupt event for GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin on which interrupt value needs to be set * interrupt: interrupt value which needs to be set on pin */ static void secumod_gpio_set_interrupt(struct gpio_chip *chip __unused, unsigned int gpio_pin, enum gpio_interrupt interrupt) { vaddr_t niepr_addr = secumod_base + piobu_device->compat->of_niepr; assert(gpio_pin < SECUMOD_MAX_PINS && !(gpio_protected & BIT32(gpio_pin))); if (interrupt == GPIO_INTERRUPT_ENABLE) io_setbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); else io_clrbits32(niepr_addr, SECUMOD_PIN_VAL(gpio_pin)); } static const struct gpio_ops atmel_piobu_ops = { .get_direction = secumod_gpio_get_direction, .set_direction = secumod_gpio_set_direction, .get_value = secumod_gpio_get_value, .set_value = secumod_gpio_set_value, .get_interrupt = secumod_gpio_get_interrupt, .set_interrupt = secumod_gpio_set_interrupt, }; static TEE_Result secumod_dt_get(struct dt_pargs *pargs, void *data, struct gpio **out_gpio) { TEE_Result res = TEE_ERROR_GENERIC; struct gpio *gpio = NULL; struct gpio_chip *chip = data; res = gpio_dt_alloc_pin(pargs, &gpio); if (res) return res; if (gpio_protected & BIT32(gpio->pin)) { free(gpio); return TEE_ERROR_GENERIC; } gpio->chip = chip; *out_gpio = gpio; return TEE_SUCCESS; } static enum itr_return secumod_it_handler(struct itr_handler *handler __unused) { int i = 0; struct optee_rtc_time tm = { }; TEE_Result res = TEE_ERROR_GENERIC; uint32_t sr = io_read32(secumod_base + SECUMOD_SR); for (i = 0; i < SECUMOD_MAX_PINS; i++) { if (sr & SECUMOD_PIN_VAL(i)) EMSG("Detected tampering on pin %d", i); } if (sr & SECUMOD_SR_JTAG) EMSG("JTAG tampering attempt"); if (sr & SECUMOD_SR_TST_PIN) EMSG("Test pin tampering attempt"); res = atmel_rtc_get_tamper_timestamp(&tm); if (!res) { EMSG("Date of tampering: %02"PRIu32"/%02"PRIu32"/%02"PRIu32"", tm.tm_mday, tm.tm_mon, tm.tm_year); EMSG("Time of tampering: %02"PRIu32":%02"PRIu32":%02"PRIu32"", tm.tm_hour, tm.tm_min, tm.tm_sec); } io_write32(secumod_base + SECUMOD_SCR, SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); panic("Tampering detected, system halted"); return ITRR_HANDLED; } static struct itr_handler secumod_itr_handler = { .it = AT91C_ID_SECUMOD, .handler = secumod_it_handler, }; static void secumod_interrupt_init(void) { TEE_Result res = TEE_ERROR_GENERIC; secumod_itr_handler.chip = interrupt_get_main_chip(); res = interrupt_add_configure_handler(&secumod_itr_handler, IRQ_TYPE_LEVEL_HIGH, 7); if (res) panic(); interrupt_enable(secumod_itr_handler.chip, secumod_itr_handler.it); } static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config) { vaddr_t piobu_addr = 0; uint8_t afv = 0; uint8_t rfv = 0; uint8_t pull_mode = PIOBU_PIN_PULL_NONE; uint8_t def_level = PIOBU_PIN_DEF_LEVEL_LOW; assert(gpio_pin < SECUMOD_MAX_PINS); piobu_addr = secumod_base + SECUMOD_PIOBU(gpio_pin); /* Set GPIO as input */ io_clrbits32(piobu_addr, SECUMOD_PIOBU_OUTPUT); afv = PIOBU_PIN_AFV(config); rfv = PIOBU_PIN_RFV(config); pull_mode = PIOBU_PIN_PULL_MODE(config); def_level = PIOBU_PIN_DEF_LEVEL(config); io_write32(piobu_addr, afv | rfv << SECUMOD_PIOBU_RFV_SHIFT | pull_mode << SECUMOD_PIOBU_PULLUP_SHIFT | def_level << SECUMOD_PIOBU_SWITCH_SHIFT); /* Enable Tampering Interrupt */ secumod_gpio_set_interrupt(&secumod_chip, gpio_pin, GPIO_INTERRUPT_ENABLE); /* Enable Intrusion Detection */ io_setbits32(secumod_base + piobu_device->compat->of_nmpr, SECUMOD_PIN_VAL(gpio_pin)); /* Enable Wakeup */ if (PIOBU_PIN_WAKEUP(config)) io_setbits32(secumod_base + piobu_device->compat->of_wkpr, SECUMOD_PIN_VAL(gpio_pin)); gpio_protected |= BIT32(gpio_pin); } static void secumod_hw_init(const void *fdt, int node) { int i = 0; int len = 0; uint8_t gpio_pin = 0; uint32_t config = 0; const uint32_t *prop = NULL; /* Disable JTAG Reset and Debug */ io_write32(secumod_base + piobu_device->compat->of_jtagcr, SECUMOD_JTAGCR_FNTRST); /* Switch IOs to normal mode */ io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | SECUMOD_CR_NORMAL); /* Clear all detection intrusion in normal mode */ io_write32(secumod_base + piobu_device->compat->of_nmpr, 0); /* Clear Alarms */ io_write32(secumod_base + SECUMOD_SCR, SECUMOD_PIN_MASK << SECUMOD_PIN_SHIFT); /* Configure each IOs */ prop = fdt_getprop(fdt, node, "gpios", &len); if (!prop) return; len /= sizeof(uint32_t); for (i = 0; i < len; i += DT_GPIO_CELLS) { gpio_pin = fdt32_to_cpu(prop[i]); config = fdt32_to_cpu(prop[i + 1]); secumod_cfg_input_pio(gpio_pin, config); } } #ifdef CFG_PM_ARM32 static TEE_Result piobu_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl __unused) { switch (op) { case PM_OP_RESUME: io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | SECUMOD_CR_NORMAL); break; case PM_OP_SUSPEND: /* Enter backup mode before suspending */ io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY | SECUMOD_CR_BACKUP); break; default: panic("Invalid PM operation"); } return TEE_SUCCESS; } static void piobu_register_pm(void) { register_pm_driver_cb(piobu_pm, NULL, "piobu"); } #else static void piobu_register_pm(void) {} #endif static TEE_Result atmel_secumod_probe(const void *fdt, int node, const void *compat_data) { size_t size = 0; if (secumod_base) return TEE_ERROR_GENERIC; piobu_device = calloc(1, sizeof(*piobu_device)); if (!piobu_device) return TEE_ERROR_OUT_OF_MEMORY; piobu_device->compat = (struct piobu_compat *)compat_data; if (dt_map_dev(fdt, node, &secumod_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; secumod_hw_init(fdt, node); secumod_interrupt_init(); secumod_chip.ops = &atmel_piobu_ops; piobu_register_pm(); assert(gpio_ops_is_valid(&atmel_piobu_ops)); return gpio_register_provider(fdt, node, secumod_dt_get, &secumod_chip); } static const struct piobu_compat sama5d2_compat = { .max_pins = 8, .of_jtagcr = 0x68, .of_bmpr = 0x7C, .of_nmpr = 0x80, .of_niepr = 0x84, .of_nidpr = 0x88, .of_nimpr = 0x8C, .of_wkpr = 0x90, }; static const struct piobu_compat sama7g54_compat = { .max_pins = 4, .of_jtagcr = 0x70, .of_bmpr = 0x84, .of_nmpr = 0x88, .of_niepr = 0x8C, .of_nidpr = 0x90, .of_nimpr = 0x94, .of_wkpr = 0x98, }; static const struct dt_device_match atmel_secumod_match_table[] = { { .compatible = "atmel,sama5d2-secumod", .compat_data = &sama5d2_compat, }, { .compatible = "microchip,sama7g5-secumod", .compat_data = &sama7g54_compat, }, { } }; DEFINE_DT_DRIVER(atmel_secumod_dt_driver) = { .name = "atmel_secumod", .type = DT_DRIVER_NOTYPE, .match_table = atmel_secumod_match_table, .probe = atmel_secumod_probe, }; optee_os-4.3.0/core/drivers/atmel_rstc.c000066400000000000000000000040101464416617300202510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #define AT91_RSTC_CR 0x0 #define AT91_RSTC_CR_KEY SHIFT_U32(0xA5, 24) #define AT91_RSTC_CR_PROCRST BIT32(0) #define AT91_RSTC_CR_PERRST BIT32(2) #define AT91_RSTC_GRSTR 0xE4 #define AT91_RSTC_GRSTR_USB(x) SHIFT_U32(1, 4 + (x)) static vaddr_t rstc_base; bool atmel_rstc_available(void) { return rstc_base != 0; } void __noreturn atmel_rstc_reset(void) { uint32_t val = AT91_RSTC_CR_KEY | AT91_RSTC_CR_PROCRST | AT91_RSTC_CR_PERRST; io_write32(rstc_base + AT91_RSTC_CR, val); /* * After the previous write, the CPU will reset so we will never hit * this loop. */ while (true) ; } void sam_rstc_usb_por(unsigned char id, bool enable) { if (!atmel_rstc_available()) panic(); if (enable) io_setbits32(rstc_base + AT91_RSTC_GRSTR, AT91_RSTC_GRSTR_USB(id)); else io_clrbits32(rstc_base + AT91_RSTC_GRSTR, AT91_RSTC_GRSTR_USB(id)); } /* Non-null reference for compat data */ static const uint8_t rstc_always_secure; static TEE_Result atmel_rstc_probe(const void *fdt, int node, const void *compat_data) { size_t size = 0; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_BAD_PARAMETERS; if (compat_data != &rstc_always_secure) matrix_configure_periph_secure(AT91C_ID_SYS); if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static const struct dt_device_match atmel_rstc_match_table[] = { { .compatible = "atmel,sama5d3-rstc" }, { .compatible = "microchip,sama7g5-rstc", .compat_data = &rstc_always_secure, }, { } }; DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = { .name = "atmel_rstc", .type = DT_DRIVER_NOTYPE, .match_table = atmel_rstc_match_table, .probe = atmel_rstc_probe, }; optee_os-4.3.0/core/drivers/atmel_rtc.c000066400000000000000000000174511464416617300201030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip * * Driver for AT91 RTC */ #include #include #include #include #include #include #include #include #include #define RTC_VAL(reg, val) (((val) >> RTC_## reg ## _SHIFT) & \ RTC_## reg ##_MASK) #define RTC_SET_VAL(reg, val) SHIFT_U32((val) & RTC_## reg ##_MASK, \ RTC_## reg ## _SHIFT) #define RTC_CR 0x0 #define RTC_CR_UPDCAL BIT(1) #define RTC_CR_UPDTIM BIT(0) #define RTC_MR 0x4 #define RTC_MR_HR_MODE BIT(0) #define RTC_MR_PERSIAN BIT(1) #define RTC_MR_UTC BIT(2) #define RTC_MR_NEGPPM BIT(4) #define RTC_MR_CORR_SHIFT 8 #define RTC_MR_CORR_MASK GENMASK_32(6, 0) #define RTC_MR_CORR(val) RTC_VAL(val, MR_CORR) #define RTC_MR_HIGHPPM BIT(15) #define RTC_TIMR 0x8 #define RTC_CALR 0xC #define RTC_SR 0x18 #define RTC_SR_ACKUPD BIT(0) #define RTC_SR_SEC BIT(2) #define RTC_SCCR 0x1C #define RTC_SCCR_ACKCLR BIT(0) #define RTC_SCCR_SECCLR BIT(2) #define RTC_VER 0x2C #define RTC_VER_NVTIM BIT(0) #define RTC_VER_NVCAL BIT(1) #define RTC_TSTR0 0xB0 #define RTC_TSDR0 0xB4 #define RTC_TSSR0 0xB8 #define RTC_TSSR_DET_OFFSET 16 #define RTC_TSSR_DET_COUNT 8 #define RTC_TSSR_TST_PIN BIT(2) #define RTC_TSSR_JTAG BIT(3) /* Layout of Time registers */ #define RTC_TIME_BACKUP BIT(31) #define RTC_TIME_HOUR_SHIFT 16 #define RTC_TIME_HOUR_MASK GENMASK_32(5, 0) #define RTC_TIME_MIN_SHIFT 8 #define RTC_TIME_MIN_MASK GENMASK_32(6, 0) #define RTC_TIME_SEC_SHIFT 0 #define RTC_TIME_SEC_MASK GENMASK_32(6, 0) /* Layout of Calendar registers */ #define RTC_CAL_DATE_SHIFT 24 #define RTC_CAL_DATE_MASK GENMASK_32(5, 0) #define RTC_CAL_DAY_SHIFT 21 #define RTC_CAL_DAY_MASK GENMASK_32(2, 0) #define RTC_CAL_MONTH_SHIFT 16 #define RTC_CAL_MONTH_MASK GENMASK_32(4, 0) #define RTC_CAL_YEAR_SHIFT 8 #define RTC_CAL_YEAR_MASK GENMASK_32(7, 0) #define RTC_CAL_CENT_SHIFT 0 #define RTC_CAL_CENT_MASK GENMASK_32(6, 0) #define ATMEL_RTC_CORR_DIVIDEND 3906000 #define ATMEL_RTC_CORR_LOW_RATIO 20 static vaddr_t rtc_base; static uint8_t bcd_decode(uint8_t dcb_val) { return (dcb_val & 0xF) + (dcb_val >> 4) * 10; } static uint8_t bcd_encode(uint32_t value) { return ((value / 10) << 4) + value % 10; } static uint32_t atmel_rtc_read(unsigned int offset) { return io_read32(rtc_base + offset); } static void atmel_rtc_write(unsigned int offset, uint32_t val) { return io_write32(rtc_base + offset, val); } static void atmel_decode_date(unsigned int time_reg, unsigned int cal_reg, struct optee_rtc_time *tm) { uint32_t time = 0; uint32_t date = 0; /* Must read twice in case it changes */ do { time = atmel_rtc_read(time_reg); date = atmel_rtc_read(cal_reg); } while ((time != atmel_rtc_read(time_reg)) || (date != atmel_rtc_read(cal_reg))); tm->tm_wday = bcd_decode(RTC_VAL(CAL_DAY, date)) - 1; tm->tm_mday = bcd_decode(RTC_VAL(CAL_DATE, date)); tm->tm_mon = bcd_decode(RTC_VAL(CAL_MONTH, date)) - 1; tm->tm_year = bcd_decode(RTC_VAL(CAL_CENT, date)) * 100; tm->tm_year += bcd_decode(RTC_VAL(CAL_YEAR, date)); tm->tm_hour = bcd_decode(RTC_VAL(TIME_HOUR, time)); tm->tm_min = bcd_decode(RTC_VAL(TIME_MIN, time)); tm->tm_sec = bcd_decode(RTC_VAL(TIME_SEC, time)); } static TEE_Result atmel_rtc_get_time(struct rtc *rtc __unused, struct optee_rtc_time *tm) { atmel_decode_date(RTC_TIMR, RTC_CALR, tm); return TEE_SUCCESS; } TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm) { if (!rtc_base) return TEE_ERROR_NOT_SUPPORTED; atmel_decode_date(RTC_TSTR0, RTC_TSDR0, tm); return TEE_SUCCESS; } static TEE_Result atmel_rtc_set_time(struct rtc *rtc __unused, struct optee_rtc_time *tm) { uint32_t cr = 0; uint32_t sr = 0; uint32_t err = 0; /* First, wait for UPDCAL/UPDTIM to be 0 */ do { cr = atmel_rtc_read(RTC_CR); } while (cr & (RTC_CR_UPDCAL | RTC_CR_UPDTIM)); /* Stop Time/Calendar for update */ atmel_rtc_write(RTC_CR, cr | RTC_CR_UPDCAL | RTC_CR_UPDTIM); do { sr = atmel_rtc_read(RTC_SR); } while (!(sr & RTC_SR_ACKUPD)); atmel_rtc_write(RTC_SCCR, RTC_SCCR_ACKCLR); atmel_rtc_write(RTC_TIMR, RTC_SET_VAL(TIME_SEC, bcd_encode(tm->tm_sec)) | RTC_SET_VAL(TIME_MIN, bcd_encode(tm->tm_min)) | RTC_SET_VAL(TIME_HOUR, bcd_encode(tm->tm_hour))); atmel_rtc_write(RTC_CALR, RTC_SET_VAL(CAL_CENT, bcd_encode(tm->tm_year / 100)) | RTC_SET_VAL(CAL_YEAR, bcd_encode(tm->tm_year % 100)) | RTC_SET_VAL(CAL_MONTH, bcd_encode(tm->tm_mon + 1)) | RTC_SET_VAL(CAL_DAY, bcd_encode(tm->tm_wday + 1)) | RTC_SET_VAL(CAL_DATE, bcd_encode(tm->tm_mday))); err = atmel_rtc_read(RTC_VER); if (err) { if (err & RTC_VER_NVTIM) DMSG("Invalid time programmed"); if (err & RTC_VER_NVCAL) DMSG("Invalid date programmed"); return TEE_ERROR_BAD_PARAMETERS; } /* Restart Time/Calendar */ atmel_rtc_write(RTC_CR, cr); return TEE_SUCCESS; } static TEE_Result atmel_rtc_get_offset(struct rtc *rtc __unused, long *offset) { uint32_t mr = atmel_rtc_read(RTC_MR); long val = RTC_VAL(MR_CORR, mr); if (!val) { *offset = 0; return TEE_SUCCESS; } val++; if (!(mr & RTC_MR_HIGHPPM)) val *= ATMEL_RTC_CORR_LOW_RATIO; val = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, val); if (!(mr & RTC_MR_NEGPPM)) val = -val; *offset = val; return TEE_SUCCESS; } static TEE_Result atmel_rtc_set_offset(struct rtc *rtc __unused, long offset) { long corr = 0; uint32_t mr = 0; if (offset > ATMEL_RTC_CORR_DIVIDEND / 2) return TEE_ERROR_BAD_PARAMETERS; if (offset < -ATMEL_RTC_CORR_DIVIDEND / 2) return TEE_ERROR_BAD_PARAMETERS; mr = atmel_rtc_read(RTC_MR); mr &= ~(RTC_MR_NEGPPM | RTC_MR_CORR_MASK | RTC_MR_HIGHPPM); if (offset > 0) mr |= RTC_MR_NEGPPM; else offset = -offset; /* offset less than 764 ppb, disable correction */ if (offset < 764) { atmel_rtc_write(RTC_MR, mr & ~RTC_MR_NEGPPM); return TEE_SUCCESS; } /* * 29208 ppb is the perfect cutoff between low range and high range * low range values are never better than high range value after that. */ if (offset < 29208) { corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, offset * ATMEL_RTC_CORR_LOW_RATIO); } else { corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, offset); mr |= RTC_MR_HIGHPPM; } corr = MIN(corr, 128); mr |= ((corr - 1) & RTC_MR_CORR_MASK) << RTC_MR_CORR_SHIFT; atmel_rtc_write(RTC_MR, mr); return TEE_SUCCESS; } static const struct rtc_ops atmel_rtc_ops = { .get_time = atmel_rtc_get_time, .set_time = atmel_rtc_set_time, .get_offset = atmel_rtc_get_offset, .set_offset = atmel_rtc_set_offset, }; static struct rtc atmel_rtc = { .ops = &atmel_rtc_ops, .range_min = { 1900, 1, 1, 0, 0, 0, 0 }, .range_max = { 2099, 12, 31, 23, 59, 59, 0 }, }; /* Non-null reference for compat data */ static const uint8_t rtc_always_secure; static TEE_Result atmel_rtc_probe(const void *fdt, int node, const void *compat_data) { size_t size = 0; if (rtc_base) return TEE_ERROR_GENERIC; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_BAD_PARAMETERS; if (compat_data != &rtc_always_secure) matrix_configure_periph_secure(AT91C_ID_SYS); if (dt_map_dev(fdt, node, &rtc_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; atmel_rtc_write(RTC_CR, 0); /* Enable 24 hours Gregorian mode (this is a clear bits operation !) */ io_clrbits32(rtc_base + RTC_MR, RTC_MR_PERSIAN | RTC_MR_UTC | RTC_MR_HR_MODE); rtc_register(&atmel_rtc); return TEE_SUCCESS; } static const struct dt_device_match atmel_rtc_match_table[] = { { .compatible = "atmel,sama5d2-rtc" }, { .compatible = "microchip,sama7g5-rtc", .compat_data = &rtc_always_secure, }, { } }; DEFINE_DT_DRIVER(atmel_rtc_dt_driver) = { .name = "atmel_rtc", .type = DT_DRIVER_NOTYPE, .match_table = atmel_rtc_match_table, .probe = atmel_rtc_probe, }; optee_os-4.3.0/core/drivers/atmel_saic.c000066400000000000000000000153451464416617300202320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #include #include #include #define AT91_AIC_MAX_PRIO 8 #define SAMA5D2_AIC_MAX_IRQS 77 #define SAMA5D2_AIC_MAX_IRQS32 ((SAMA5D2_AIC_MAX_IRQS + 31) / 32) struct saic_data { struct itr_chip chip; vaddr_t base; size_t nr_irqs; uint32_t external[SAMA5D2_AIC_MAX_IRQS32]; }; static struct saic_data saic; static void saic_register_pm(void); static void saic_write_reg(uint32_t reg, uint32_t val) { io_write32(saic.base + reg, val); } static uint32_t saic_read_reg(uint32_t reg) { return io_read32(saic.base + reg); } void interrupt_main_handler(void) { uint32_t irqnr = saic_read_reg(AT91_AIC_IVR); interrupt_call_handlers(&saic.chip, irqnr); saic_write_reg(AT91_AIC_EOICR, 0); } static void saic_select_it(size_t it) { assert(!(it & ~AT91_AIC_SSR_ITSEL_MASK)); saic_write_reg(AT91_AIC_SSR, it); } static void saic_configure_it(size_t it, uint32_t src_type, uint32_t priority) { saic_select_it(it); saic_write_reg(AT91_AIC_SMR, src_type | priority); } static bool is_external_it(size_t it) { uint32_t it_grp = it / 32; uint32_t it_off = it % 32; if (it >= saic.nr_irqs) panic(); return saic.external[it_grp] & BIT32(it_off); } static TEE_Result saic_get_src_type(uint32_t dt_level, size_t it, uint32_t *src_type) { switch (dt_level) { case IRQ_TYPE_EDGE_RISING: *src_type = AT91_AIC_SMR_POS_EDGE; break; case IRQ_TYPE_EDGE_FALLING: if (!is_external_it(it)) return TEE_ERROR_BAD_PARAMETERS; *src_type = AT91_AIC_SMR_NEG_EDGE; break; case IRQ_TYPE_LEVEL_HIGH: *src_type = AT91_AIC_SMR_HIGH_LEVEL; break; case IRQ_TYPE_LEVEL_LOW: if (!is_external_it(it)) return TEE_ERROR_BAD_PARAMETERS; *src_type = AT91_AIC_SMR_LEVEL; break; default: return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static void saic_add(struct itr_chip *chip __unused, size_t it, uint32_t type, uint32_t prio) { uint32_t src_type = AT91_AIC_SMR_HIGH_LEVEL; if (it >= saic.nr_irqs) panic(); if (saic_get_src_type(type, it, &src_type)) panic("Invalid interrupt specifier"); saic_configure_it(it, src_type, prio); } static void saic_enable(struct itr_chip *chip __unused, size_t it) { saic_select_it(it); saic_write_reg(AT91_AIC_IECR, 1); } static void saic_disable(struct itr_chip *chip __unused, size_t it) { saic_select_it(it); saic_write_reg(AT91_AIC_IDCR, 1); } static const struct itr_ops saic_ops = { .add = saic_add, .mask = saic_disable, .unmask = saic_enable, .enable = saic_enable, .disable = saic_disable, }; static int saic_dt_get_irq(const uint32_t *properties, int len, uint32_t *type, uint32_t *prio) { int it = DT_INFO_INVALID_INTERRUPT; uint32_t src_type = 0; uint32_t priority = 0; uint32_t irq_type = 0; len /= sizeof(uint32_t); if (len != 3) return DT_INFO_INVALID_INTERRUPT; it = fdt32_to_cpu(properties[0]); if (it >= (int)saic.nr_irqs) return DT_INFO_INVALID_INTERRUPT; irq_type = fdt32_to_cpu(properties[1]); if (saic_get_src_type(irq_type, it, &src_type)) return DT_INFO_INVALID_INTERRUPT; priority = fdt32_to_cpu(properties[2]); if (priority >= AT91_AIC_MAX_PRIO) return DT_INFO_INVALID_INTERRUPT; if (type) *type = irq_type; if (prio) *prio = priority; return it; } static struct saic_data saic = { .chip = { .ops = &saic_ops, .dt_get_irq = &saic_dt_get_irq, }, }; static void saic_clear_aicredir(void) { vaddr_t sfr_base = sam_sfr_base(); uint32_t aicredir_val = 0; aicredir_val = io_read32(sfr_base + AT91_SFR_SN1); aicredir_val ^= AT91_SFR_AICREDIR_XOR_KEY; aicredir_val &= AT91_SFR_AICREDIR_KEY_MASK; /* * We explicitly don't want to redirect secure interrupts to non secure * AIC. By default, AT91Bootstrap does so on some platforms. */ io_write32(sfr_base + AT91_SFR_AICREDIR, aicredir_val); } static void saic_init_external(const void *fdt, int node) { int i = 0; int len = 0; int it_grp = 0; int it_off = 0; size_t it = 0; const uint32_t *external = NULL; external = fdt_getprop(fdt, node, "atmel,external-irqs", &len); if (!external) return; len /= sizeof(uint32_t); for (i = 0; i < len; i++) { it = fdt32_to_cpu(external[i]); DMSG("IRQ %zu is external", it); if (it >= saic.nr_irqs) panic(); it_grp = it / 32; it_off = it % 32; saic.external[it_grp] |= BIT32(it_off); } } static void saic_init_hw(void) { unsigned int i = 0; saic_clear_aicredir(); /* Disable write protect if any */ saic_write_reg(AT91_AIC_WPMR, AT91_AIC_WPKEY); /* Pop the (potential) interrupt stack (8 priority) */ for (i = 0; i < 8; i++) saic_write_reg(AT91_AIC_EOICR, 0); /* Disable and clear all interrupts initially */ for (i = 0; i < saic.nr_irqs; i++) { saic_write_reg(AT91_AIC_IDCR, 1); saic_write_reg(AT91_AIC_ICCR, 1); /* Set interrupt vector to hold interrupt number */ saic_select_it(i); saic_write_reg(AT91_AIC_SVR, i); } saic_write_reg(AT91_AIC_SPU, 0xffffffff); /* Disable AIC debugging */ saic_write_reg(AT91_AIC_DCR, 0); } TEE_Result atmel_saic_setup(void) { int node = -1; int ret = 0; size_t size = 0; const void *fdt = get_embedded_dt(); /* There is only 1 SAIC controller */ if (saic.base) return TEE_ERROR_GENERIC; node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-saic"); if (node < 0) return TEE_ERROR_GENERIC; ret = dt_map_dev(fdt, node, &saic.base, &size, DT_MAP_AUTO); if (ret) { EMSG("Failed to map SAIC"); return TEE_ERROR_GENERIC; } saic.chip.ops = &saic_ops; saic.nr_irqs = SAMA5D2_AIC_MAX_IRQS; saic_init_external(fdt, node); saic_init_hw(); interrupt_main_init(&saic.chip); saic_register_pm(); return TEE_SUCCESS; } #ifdef CFG_PM_ARM32 static struct { uint8_t smr[SAMA5D2_AIC_MAX_IRQS]; } saic_state; static void saic_resume(void) { uint8_t it = 0; saic_init_hw(); for (it = 0; it < SAMA5D2_AIC_MAX_IRQS; it++) { saic_select_it(it); saic_write_reg(AT91_AIC_SMR, saic_state.smr[it]); } } static void saic_suspend(void) { uint8_t it = 0; for (it = 0; it < SAMA5D2_AIC_MAX_IRQS; it++) { saic_select_it(it); saic_state.smr[it] = saic_read_reg(AT91_AIC_SMR); } } static TEE_Result saic_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl __unused) { switch (op) { case PM_OP_RESUME: saic_resume(); break; case PM_OP_SUSPEND: saic_suspend(); break; default: panic("Invalid PM operation"); } return TEE_SUCCESS; } static void saic_register_pm(void) { register_pm_core_service_cb(saic_pm, NULL, "saic"); } #else static void saic_register_pm(void) { } #endif optee_os-4.3.0/core/drivers/atmel_shdwc.c000066400000000000000000000141441464416617300204170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015 Atmel Corporation, * Nicolas Ferre * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "at91_clk.h" #define SHDW_WK_PIN(reg, cfg) ((reg) & \ AT91_SHDW_WKUPIS((cfg)->wkup_pin_input)) #define SHDW_RTCWK(reg, cfg) (((reg) >> ((cfg)->sr_rtcwk_shift)) & 0x1) #define SHDW_RTTWK(reg, cfg) (((reg) >> ((cfg)->sr_rttwk_shift)) & 0x1) #define SHDW_RTCWKEN(cfg) BIT((cfg)->mr_rtcwk_shift) #define SHDW_RTTWKEN(cfg) BIT((cfg)->mr_rttwk_shift) #define SLOW_CLK_FREQ 32768ULL #define DBC_PERIOD_US(x) DIV_ROUND_UP((1000000ULL * (x)), SLOW_CLK_FREQ) /* * @type_offset offset of Memory Device Register * @type_mask mask of Memory Device Type in Memory Device Register * @compatible the compatible string in the device tree */ struct ddrc_reg_config { uint32_t type_offset; uint32_t type_mask; const char *compatible; }; /* * @shdwc_always_secure Is peripheral SHDWC always secured? * @ddrc DDR controller configurations */ struct shdwc_compat { bool shdwc_always_secure; struct ddrc_reg_config ddrc; }; static vaddr_t shdwc_base; static vaddr_t mpddrc_base; bool atmel_shdwc_available(void) { return shdwc_base != 0; } void __noreturn atmel_shdwc_shutdown(void) { vaddr_t pmc_base = at91_pmc_get_base(); /* * Mask exception before entering assembly which does not expect to be * interrupted. */ thread_mask_exceptions(THREAD_EXCP_ALL); __atmel_shdwc_shutdown(mpddrc_base, shdwc_base, pmc_base); /* We are going to shutdown the CPU so we will never hit this loop */ while (true) ; } static const unsigned long long sdwc_dbc_period[] = { 0, 3, 32, 512, 4096, 32768, }; static uint32_t at91_shdwc_debouncer_value(uint32_t in_period_us) { int i = 0; int max_idx = ARRAY_SIZE(sdwc_dbc_period) - 1; uint64_t period_us = 0; uint64_t max_period_us = DBC_PERIOD_US(sdwc_dbc_period[max_idx]); if (in_period_us > max_period_us) { DMSG("debouncer period %"PRIu32" too big, using %"PRIu64" us", in_period_us, max_period_us); return max_idx; } for (i = max_idx - 1; i > 0; i--) { period_us = DBC_PERIOD_US(sdwc_dbc_period[i]); if (in_period_us > period_us) break; } return i + 1; } static uint32_t at91_shdwc_get_wakeup_input(const void *fdt, int np) { const uint32_t *prop = NULL; uint32_t wk_input_mask = 0; uint32_t wuir = 0; uint32_t wk_input = 0; int child = 0; int len = 0; fdt_for_each_subnode(child, fdt, np) { prop = fdt_getprop(fdt, child, "reg", &len); if (!prop || len != sizeof(uint32_t)) { DMSG("reg property is missing for node %s", fdt_get_name(fdt, child, NULL)); continue; } wk_input = fdt32_to_cpu(*prop); wk_input_mask = BIT32(wk_input); if (!(wk_input_mask & AT91_SHDW_WKUPEN_MASK)) { DMSG("wake-up input %"PRId32" out of bounds ignore", wk_input); continue; } wuir |= wk_input_mask; if (fdt_getprop(fdt, child, "atmel,wakeup-active-high", NULL)) wuir |= AT91_SHDW_WKUPT(wk_input); } return wuir; } static void at91_shdwc_dt_configure(const void *fdt, int np) { const uint32_t *prop = NULL; uint32_t mode = 0; uint32_t tmp = 0; uint32_t input = 0; int len = 0; prop = fdt_getprop(fdt, np, "debounce-delay-us", &len); if (prop && len == sizeof(uint32_t)) { tmp = fdt32_to_cpu(*prop); mode |= AT91_SHDW_WKUPDBC(at91_shdwc_debouncer_value(tmp)); } if (fdt_getprop(fdt, np, "atmel,wakeup-rtc-timer", &len)) mode |= AT91_SHDW_RTCWKEN; if (fdt_getprop(fdt, np, "atmel,wakeup-rtt-timer", &len)) mode |= AT91_SHDW_RTTWKEN; io_write32(shdwc_base + AT91_SHDW_MR, mode); input = at91_shdwc_get_wakeup_input(fdt, np); io_write32(shdwc_base + AT91_SHDW_WUIR, input); } static TEE_Result atmel_shdwc_probe(const void *fdt, int node, const void *compat_data) { int ddr_node = 0; size_t size = 0; uint32_t ddr = AT91_DDRSDRC_MD_LPDDR2; struct shdwc_compat *compat = (struct shdwc_compat *)compat_data; /* * Assembly code relies on the fact that there is only one CPU to avoid * any other one to invalidate TLB/I-Cache. */ COMPILE_TIME_ASSERT(CFG_TEE_CORE_NB_CORE == 1); if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_BAD_PARAMETERS; if (!compat->shdwc_always_secure) matrix_configure_periph_secure(AT91C_ID_SYS); if (dt_map_dev(fdt, node, &shdwc_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; ddr_node = fdt_node_offset_by_compatible(fdt, -1, compat->ddrc.compatible); if (ddr_node < 0) return TEE_ERROR_GENERIC; if (dt_map_dev(fdt, ddr_node, &mpddrc_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; if (!compat->ddrc.type_mask) { ddr = io_read32(mpddrc_base + compat->ddrc.type_offset); ddr &= compat->ddrc.type_mask; if (ddr != AT91_DDRSDRC_MD_LPDDR2 && ddr != AT91_DDRSDRC_MD_LPDDR3) mpddrc_base = 0; } else { /* * Set the base to 0 as the code of DRAM controller for power * down is not implemented yet. */ mpddrc_base = 0; } at91_shdwc_dt_configure(fdt, node); return sam_pm_init(fdt, shdwc_base); } static const struct shdwc_compat sama5d2_compat = { .shdwc_always_secure = false, .ddrc = { .type_offset = AT91_DDRSDRC_MDR, .type_mask = AT91_DDRSDRC_MD, .compatible = "atmel,sama5d3-ddramc", } }; static const struct shdwc_compat sama7g5_compat = { .shdwc_always_secure = true, .ddrc = { .compatible = "microchip,sama7g5-uddrc", } }; static const struct dt_device_match atmel_shdwc_match_table[] = { { .compatible = "atmel,sama5d2-shdwc", .compat_data = &sama5d2_compat }, { .compatible = "microchip,sama7g5-shdwc", .compat_data = &sama7g5_compat, }, { } }; DEFINE_DT_DRIVER(atmel_shdwc_dt_driver) = { .name = "atmel_shdwc", .type = DT_DRIVER_NOTYPE, .match_table = atmel_shdwc_match_table, .probe = atmel_shdwc_probe, }; optee_os-4.3.0/core/drivers/atmel_shdwc_a32.S000066400000000000000000000036001464416617300210370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015 Atmel Corporation, * Nicolas Ferre * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include "at91_pmc.h" /* * Code size of shutdown assembly must fit in a single Cortex-A5 cache * line which is 8 words long (32 bytes) since SDRAM might be disabled and thus * not accessible to fetch code or data from it. */ .macro check_fit_in_cacheline since .if (. - \since) > 32 .error "Shutdown assembly code exceeds cache line size" .endif .endm /** * Shutdown the CPU * * This function is in assembly to be sure the code fits in a single cache line. * We are going to power down the SDRAM and thus we can't fetch code from it * once powered down. * * r0 = mpddrc_base * r1 = shdwc_base * r2 = pmc_base */ FUNC __atmel_shdwc_shutdown , : mov_imm r3, AT91_DDRSDRC_LPDDR2_PWOFF mov_imm r4, (AT91_SHDW_KEY | AT91_SHDW_SHDW) /* * Read values from both shutdown controller and PMC to ensure the * translations will be in the TLB. */ ldr r6, [r1, #AT91_SHDW_CR] ldr r6, [r2, #AT91_PMC_MCKR] /* Power down SDRAM0 if mpddrc_base is set */ tst r0, #0 beq 1f /* Align to cache line to ensure the rest of code fits in a single line */ .balign 32 __atmel_shdwc_shutdown_sdram_disabled: str r3, [r0, #AT91_DDRSDRC_LPR] /* Switch the master clock source to slow clock. */ 1: ldr r6, [r2, #AT91_PMC_MCKR] bic r6, r6, #AT91_PMC_CSS str r6, [r2, #AT91_PMC_MCKR] /* Wait for clock switch. */ 2: ldr r6, [r2, #AT91_PMC_SR] tst r6, #AT91_PMC_MCKRDY beq 2b /* Shutdown CPU */ str r4, [r1, #AT91_SHDW_CR] check_fit_in_cacheline __atmel_shdwc_shutdown_sdram_disabled /* We should never reach this since we shut down the CPU */ b . END_FUNC __atmel_shdwc_shutdown optee_os-4.3.0/core/drivers/atmel_tcb.c000066400000000000000000000115161464416617300200570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Microchip */ #include #include #include #include #include #include #include #include #include #include #define TCB_CHAN(chan) ((chan) * 0x40) #define TCB_CCR(chan) (0x0 + TCB_CHAN(chan)) #define TCB_CCR_SWTRG 0x4 #define TCB_CCR_CLKEN 0x1 #define TCB_CMR(chan) (0x4 + TCB_CHAN(chan)) #define TCB_CMR_WAVE BIT32(15) #define TCB_CMR_TIMER_CLOCK5 4 #define TCB_CMR_XC1 6 #define TCB_CMR_ACPA_SET BIT32(16) #define TCB_CMR_ACPC_CLEAR SHIFT_U32(2, 18) #define TCB_CV(chan) (0x10 + TCB_CHAN(chan)) #define TCB_RA(chan) (0x14 + TCB_CHAN(chan)) #define TCB_RB(chan) (0x18 + TCB_CHAN(chan)) #define TCB_RC(chan) (0x1c + TCB_CHAN(chan)) #define TCB_IER(chan) (0x24 + TCB_CHAN(chan)) #define TCB_IER_COVFS 0x1 #define TCB_SR(chan) (0x20 + TCB_CHAN(chan)) #define TCB_SR_COVFS 0x1 #define TCB_IDR(chan) (0x28 + TCB_CHAN(chan)) #define TCB_BCR 0xc0 #define TCB_BCR_SYNC 0x1 #define TCB_BMR 0xc4 #define TCB_BMR_TC1XC1S_TIOA0 SHIFT_U32(2, 2) #define TCB_WPMR 0xe4 #define TCB_WPMR_WAKEY 0x54494d #ifdef CFG_SAMA7G5 static const char * const tcb_clocks[] = { "t0_clk", "t1_clk", "t2_clk", "slow_clk"}; #else static const char * const tcb_clocks[] = { "t0_clk", "gclk", "slow_clk" }; #endif static vaddr_t tcb_base; static uint32_t tcb_rate; static TEE_Result atmel_tcb_enable_clocks(const void *fdt, int node) { unsigned int i = 0; struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; for (i = 0; i < ARRAY_SIZE(tcb_clocks); i++) { res = clk_dt_get_by_name(fdt, node, tcb_clocks[i], &clk); if (res) return res; clk_enable(clk); } return TEE_SUCCESS; } TEE_Result tee_time_get_sys_time(TEE_Time *time) { uint64_t cv0 = 0; uint64_t cv1 = 0; if (!tcb_base) return TEE_ERROR_BAD_STATE; do { cv1 = io_read32(tcb_base + TCB_CV(1)); cv0 = io_read32(tcb_base + TCB_CV(0)); } while (io_read32(tcb_base + TCB_CV(1)) != cv1); cv0 |= cv1 << 32; time->seconds = cv0 / tcb_rate; time->millis = (cv0 % tcb_rate) / (tcb_rate / TEE_TIME_MILLIS_BASE); return TEE_SUCCESS; } uint32_t tee_time_get_sys_time_protection_level(void) { return 1000; } static void atmel_tcb_configure(void) { /* Disable write protection */ io_write32(tcb_base + TCB_WPMR, TCB_WPMR_WAKEY); /* Disable all irqs for both channel 0 & 1 */ io_write32(tcb_base + TCB_IDR(0), 0xff); io_write32(tcb_base + TCB_IDR(1), 0xff); /* * In order to avoid wrapping, use a 64 bit counter by chaining * two channels. We use the slow_clk which runs at 32K and is sufficient * for the millisecond precision, this will wrap in approximately * 17851025 years so no worries here. * * Channel 0 is configured to generate a clock on TIOA0 which is cleared * when reaching 0x80000000 and set when reaching 0. */ io_write32(tcb_base + TCB_CMR(0), TCB_CMR_TIMER_CLOCK5 | TCB_CMR_WAVE | TCB_CMR_ACPA_SET | TCB_CMR_ACPC_CLEAR); io_write32(tcb_base + TCB_RC(0), 0x80000000); io_write32(tcb_base + TCB_RA(0), 0x1); io_write32(tcb_base + TCB_CCR(0), TCB_CCR_CLKEN); /* Channel 1 is configured to use TIOA0 as input */ io_write32(tcb_base + TCB_CMR(1), TCB_CMR_XC1 | TCB_CMR_WAVE); io_write32(tcb_base + TCB_CCR(1), TCB_CCR_CLKEN); /* Set XC1 input to be TIOA0 (ie output of Channel 0) */ io_write32(tcb_base + TCB_BMR, TCB_BMR_TC1XC1S_TIOA0); /* Sync & start all timers */ io_write32(tcb_base + TCB_BCR, TCB_BCR_SYNC); /* Enable write protection */ io_write32(tcb_base + TCB_WPMR, TCB_WPMR_WAKEY | 1); } static TEE_Result atmel_tcb_check(void) { if (!tcb_base) panic("Missing TCB base ! Check the device-tree"); return TEE_SUCCESS; } boot_final(atmel_tcb_check); static TEE_Result atmel_tcb_probe(const void *fdt, int node, const void *compat_data __unused) { size_t size = 0; struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; unsigned int peri_id = AT91C_ID_TC0; /* Enable all TCB clocks */ res = atmel_tcb_enable_clocks(fdt, node); if (res) return res; if (tcb_base) return TEE_SUCCESS; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_SUCCESS; res = clk_dt_get_by_name(fdt, node, "slow_clk", &clk); if (res) return res; res = matrix_dt_get_id(fdt, node, &peri_id); if (res) return res; if (dt_map_dev(fdt, node, &tcb_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; matrix_configure_periph_secure(peri_id); tcb_rate = clk_get_rate(clk); assert(tcb_rate); atmel_tcb_configure(); return TEE_SUCCESS; } static const struct dt_device_match atmel_tcb_match_table[] = { { .compatible = "atmel,sama5d2-tcb" }, { } }; DEFINE_DT_DRIVER(atmel_tcb_dt_driver) = { .name = "atmel_tcb", .type = DT_DRIVER_NOTYPE, .match_table = atmel_tcb_match_table, .probe = atmel_tcb_probe, }; optee_os-4.3.0/core/drivers/atmel_trng.c000066400000000000000000000047731464416617300202700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 Microchip */ #include #include #include #include #include #include #include #include #include #include #include #include /* Registers */ #define TRNG_CTRL 0x0 #define TRNG_CTRL_WAKEY_OFFSET 8 #define TRNG_CTRL_WAKEY_VALUE 0x524E47 #define TRNG_IER 0x10 #define TRNG_ISR 0x1C #define TRNG_ODATA 0x50 static unsigned int trng_lock = SPINLOCK_UNLOCK; static vaddr_t trng_base; static uint32_t atmel_trng_read32(void) { uint32_t exceptions = 0; uint32_t value = 0; exceptions = cpu_spin_lock_xsave(&trng_lock); while (!io_read32(trng_base + TRNG_ISR)) ; value = io_read32(trng_base + TRNG_ODATA); cpu_spin_unlock_xrestore(&trng_lock, exceptions); return value; } TEE_Result hw_get_random_bytes(void *buf, size_t len) { uint8_t *rngbuf = buf; uint32_t val = 0; size_t len_to_copy = 0; assert(trng_base); while (len) { val = atmel_trng_read32(); len_to_copy = MIN(len, sizeof(uint32_t)); memcpy(rngbuf, &val, len_to_copy); rngbuf += len_to_copy; len -= len_to_copy; } return TEE_SUCCESS; } /* This is a true RNG, no need for seeding */ void plat_rng_init(void) { } static void atmel_trng_reset(void) { uint32_t ctrl_val = TRNG_CTRL_WAKEY_VALUE << TRNG_CTRL_WAKEY_OFFSET; /* Disable TRNG */ io_setbits32(trng_base + TRNG_CTRL, ctrl_val); /* Enable interrupt */ io_setbits32(trng_base + TRNG_IER, 1); /* Enable TRNG */ io_setbits32(trng_base + TRNG_CTRL, ctrl_val | 1); } static TEE_Result trng_node_probe(const void *fdt, int node, const void *compat_data __unused) { int status = fdt_get_status(fdt, node); size_t size = 0; struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; if (status != DT_STATUS_OK_SEC) return TEE_ERROR_GENERIC; matrix_configure_periph_secure(AT91C_ID_TRNG); res = clk_dt_get_by_index(fdt, node, 0, &clk); if (res) return res; if (dt_map_dev(fdt, node, &trng_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; clk_enable(clk); atmel_trng_reset(); return TEE_SUCCESS; } static const struct dt_device_match atmel_trng_match_table[] = { { .compatible = "atmel,at91sam9g45-trng" }, { .compatible = "microchip,sama7g5-trng" }, { } }; DEFINE_DT_DRIVER(atmel_trng_dt_driver) = { .name = "atmel_trng", .type = DT_DRIVER_NOTYPE, .match_table = atmel_trng_match_table, .probe = trng_node_probe, }; optee_os-4.3.0/core/drivers/atmel_uart.c000066400000000000000000000071171464416617300202640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Timesys Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include /* Register definitions */ #define ATMEL_UART_CR 0x0000 /* Control Register */ #define ATMEL_UART_MR 0x0004 /* Mode Register */ #define ATMEL_UART_IER 0x0008 /* Interrupt Enable Register */ #define ATMEL_UART_IDR 0x000c /* Interrupt Disable Register */ #define ATMEL_UART_IMR 0x0010 /* Interrupt Mask Register */ #define ATMEL_UART_SR 0x0014 /* Status Register */ #define ATMEL_SR_RXRDY BIT(0) /* Receiver Ready */ #define ATMEL_SR_TXRDY BIT(1) /* Transmitter Ready */ #define ATMEL_SR_TXEMPTY BIT(1) /* Transmitter Ready */ #define ATMEL_UART_RHR 0x0018 /* Receive Holding Register */ #define ATMEL_UART_THR 0x001c /* Transmit Holding Register */ #define ATMEL_UART_BRGR 0x0020 /* Baud Rate Generator Register */ #define ATMEL_UART_CMPR 0x0024 /* Comparison Register */ #define ATMEL_UART_RTOR 0x0028 /* Receiver Time-out Register */ #define ATMEL_UART_WPMR 0x00e4 /* Write Protect Mode Register */ #define ATMEL_UART_SIZE 0x00e8 /* ATMEL_UART_WPMR + sizeof(uint32_t) */ static vaddr_t chip_to_base(struct serial_chip *chip) { struct atmel_uart_data *pd = container_of(chip, struct atmel_uart_data, chip); return io_pa_or_va(&pd->base, ATMEL_UART_SIZE); } static void atmel_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + ATMEL_UART_SR) & ATMEL_SR_TXEMPTY)) ; } static int atmel_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (io_read32(base + ATMEL_UART_SR) & ATMEL_SR_RXRDY) ; return io_read32(base + ATMEL_UART_RHR); } static void atmel_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + ATMEL_UART_SR) & ATMEL_SR_TXRDY)) ; io_write32(base + ATMEL_UART_THR, ch); } static const struct serial_ops atmel_uart_ops = { .flush = atmel_uart_flush, .getchar = atmel_uart_getchar, .putc = atmel_uart_putc, }; void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base) { pd->base.pa = base; pd->chip.ops = &atmel_uart_ops; /* * Do nothing, debug uart share with normal world, * everything for uart initialization is done in bootloader. */ } optee_os-4.3.0/core/drivers/atmel_wdt.c000066400000000000000000000235751464416617300201150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip */ #include #include #include #include #include #include #include #include #include #include #include #include #define WDT_CR 0x0 #define WDT_CR_KEY SHIFT_U32(0xA5, 24) #define WDT_CR_WDRSTT BIT(0) #define WDT_MR 0x4 #define WDT_MR_WDV GENMASK_32(11, 0) #define WDT_MR_WDV_SET(val) ((val) & WDT_MR_WDV) #define WDT_MR_WDFIEN BIT(12) #define WDT_MR_WDRSTEN BIT(13) #define WDT_MR_WDDIS BIT(15) /* Watchdog Disable of WDT on bit 15 */ #define WDT_MR_WDDIS_DWDT BIT(12) /* Watchdog Disable of DWDT on bit 12 */ #define WDT_MR_WDD_SHIFT 16 #define WDT_MR_WDD_MASK GENMASK_32(11, 0) #define WDT_MR_WDD SHIFT_U32(WDT_MR_WDD_MASK, WDT_MR_WDD_SHIFT) #define WDT_MR_WDD_SET(val) \ SHIFT_U32(((val) & WDT_MR_WDD_MASK), WDT_MR_WDD_SHIFT) #define WDT_MR_WDDBGHLT BIT(28) #define WDT_MR_WDIDLEHLT BIT(29) #define WDT_SR 0x8 #define WDT_SR_DUNF BIT(0) #define WDT_SR_DERR BIT(1) /* DWDT: Watchdog Timer Mode Register */ #define WDT_MR_PERIODRST BIT(4) #define WDT_MR_RPTHRST BIT(5) /* DWDT: Watchdog Timer Value Register (Read-only) */ #define WDT_VR 0x8 #define WDT_VR_COUNTER_SHIFT 0 #define WDT_VR_COUNTER_MASK GENMASK_32(11, 0) /* DWDT: Watchdog Timer Window Level Register */ #define WDT_WL 0xc #define WDT_WL_RPTH_SHIFT 16 #define WDT_WL_RPTH_MASK GENMASK_32(27, 16) #define WDT_WL_PERIOD_SHIFT 0 #define WDT_WL_PERIOD_MASK GENMASK_32(11, 0) /* DWDT: Watchdog Timer Interrupt Level Register */ #define WDT_IL 0x10 #define WDT_IL_LVLTH_SHIFT 0 #define WDT_IL_LVLTH_MASK GENMASK_32(11, 0) /* DWDT: Watchdog Timer Interrupt Enable/Disable/Status/Mask Register */ #define WDT_IER 0x14 #define WDT_IDR 0x18 #define WDT_ISR 0x1c #define WDT_IMR 0x20 #define WDT_NSRPTHINT BIT(4) #define WDT_NSPERINT BIT(3) #define WDT_LVLINT BIT(2) #define WDT_RPTHINT BIT(1) #define WDT_PERINT BIT(0) /* * The watchdog is clocked by a 32768Hz clock/128 and the counter is on * 12 bits. */ #define SLOW_CLOCK_FREQ (32768) #define WDT_CLOCK_FREQ (SLOW_CLOCK_FREQ / 128) #define WDT_MIN_TIMEOUT 1 #define WDT_MAX_TIMEOUT (BIT(12) / WDT_CLOCK_FREQ) #define WDT_DEFAULT_TIMEOUT WDT_MAX_TIMEOUT /* * We must wait at least 3 clocks period before accessing registers MR and CR. * Ensure that we see at least 4 edges */ #define WDT_REG_ACCESS_UDELAY (1000000ULL / SLOW_CLOCK_FREQ * 4) #define SEC_TO_WDT(sec) (((sec) * WDT_CLOCK_FREQ) - 1) #define WDT_ENABLED(mr, dis_mask) (!((mr) & (dis_mask))) enum wdt_type { WDT_TYPE_WDT, /* Watchdog Timer */ WDT_TYPE_DWDT, /* Dual Watchdog Timer */ }; struct wdt_compat { bool wdt_ps; /* Is Peripheral SHDWC Programmable Secure */ enum wdt_type type; /* Type of Watchdog Timer */ uint32_t dis_mask; /* Mask of Watchdog Disable in Mode Register */ }; struct atmel_wdt { struct wdt_chip chip; enum wdt_type type; uint32_t dis_mask; vaddr_t base; uint32_t mr; bool enabled; }; static void atmel_wdt_write_sleep(struct atmel_wdt *wdt, uint32_t reg, uint32_t val) { udelay(WDT_REG_ACCESS_UDELAY); io_write32(wdt->base + reg, val); } static TEE_Result atmel_wdt_settimeout(struct wdt_chip *chip, unsigned long timeout) { struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); if (wdt->type == WDT_TYPE_WDT) { wdt->mr &= ~WDT_MR_WDV; wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(timeout)); /* WDV and WDD only be updated when the watchdog is running */ if (WDT_ENABLED(wdt->mr, wdt->dis_mask)) atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); } else { io_write32(wdt->base + WDT_WL, SHIFT_U32(SEC_TO_WDT(timeout), WDT_WL_PERIOD_SHIFT)); } return TEE_SUCCESS; } static void atmel_wdt_ping(struct wdt_chip *chip) { struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); atmel_wdt_write_sleep(wdt, WDT_CR, WDT_CR_KEY | WDT_CR_WDRSTT); } static void atmel_wdt_start(struct atmel_wdt *wdt) { wdt->mr &= ~wdt->dis_mask; atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); } static void atmel_wdt_enable(struct wdt_chip *chip) { struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); wdt->enabled = true; atmel_wdt_start(wdt); } static void atmel_wdt_stop(struct atmel_wdt *wdt) { wdt->mr |= wdt->dis_mask; atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr); } static void atmel_wdt_disable(struct wdt_chip *chip) { struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip); wdt->enabled = false; atmel_wdt_stop(wdt); } static enum itr_return atmel_wdt_itr_cb(struct itr_handler *h) { struct atmel_wdt *wdt = h->data; uint32_t sr = 0; if (wdt->type == WDT_TYPE_WDT) { sr = io_read32(wdt->base + WDT_SR); if (sr & WDT_SR_DUNF) DMSG("Watchdog Underflow"); if (sr & WDT_SR_DERR) DMSG("Watchdog Error"); } else if (wdt->type == WDT_TYPE_DWDT) { sr = io_read32(wdt->base + WDT_ISR); if (sr & WDT_NSRPTHINT) DMSG("NS Watchdog Repeat Threshold Interrupt"); if (sr & WDT_NSPERINT) DMSG("NS Watchdog Period Interrupt"); if (sr & WDT_LVLINT) DMSG("Watchdog Level Threshold Interrupt"); if (sr & WDT_RPTHINT) DMSG("Watchdog Repeat Threshold Interrupt"); if (sr & WDT_PERINT) DMSG("Watchdog Period Interrupt"); } panic("Watchdog interrupt"); return ITRR_HANDLED; } static TEE_Result atmel_wdt_init(struct wdt_chip *chip __unused, unsigned long *min_timeout, unsigned long *max_timeout) { *min_timeout = WDT_MIN_TIMEOUT; *max_timeout = WDT_MAX_TIMEOUT; return TEE_SUCCESS; } static const struct wdt_ops atmel_wdt_ops = { .init = atmel_wdt_init, .start = atmel_wdt_enable, .stop = atmel_wdt_disable, .ping = atmel_wdt_ping, .set_timeout = atmel_wdt_settimeout, }; static void atmel_wdt_init_hw(struct atmel_wdt *wdt) { uint32_t mr = 0; /* * If we are resuming, we disabled the watchdog on suspend but the * bootloader might have enabled the watchdog. If so, disable it * properly. */ if (!WDT_ENABLED(wdt->mr, wdt->dis_mask)) { mr = io_read32(wdt->base + WDT_MR); if (WDT_ENABLED(mr, wdt->dis_mask)) io_write32(wdt->base + WDT_MR, mr | wdt->dis_mask); } if (wdt->type == WDT_TYPE_WDT) { /* Enable interrupt, and disable watchdog in debug and idle */ wdt->mr |= WDT_MR_WDFIEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT; /* Enable watchdog reset */ wdt->mr |= WDT_MR_WDRSTEN; wdt->mr |= WDT_MR_WDD_SET(SEC_TO_WDT(WDT_MAX_TIMEOUT)); wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT)); } else if (wdt->type == WDT_TYPE_DWDT) { /* Enable interrupt */ io_write32(wdt->base + WDT_ISR, WDT_PERINT); /* Disable watchdog in debug and idle */ wdt->mr |= WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT; /* Enable watchdog period reset */ wdt->mr |= WDT_MR_PERIODRST; io_write32(wdt->base + WDT_WL, SHIFT_U32(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT), WDT_WL_PERIOD_SHIFT)); } else { panic("Invalid Watchdog"); } /* * If the watchdog was enabled, write the configuration which will ping * the watchdog. */ if (WDT_ENABLED(wdt->mr, wdt->dis_mask)) io_write32(wdt->base + WDT_MR, wdt->mr); } #ifdef CFG_PM_ARM32 static TEE_Result atmel_wdt_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl) { struct atmel_wdt *wdt = hdl->handle; switch (op) { case PM_OP_RESUME: atmel_wdt_init_hw(wdt); if (wdt->enabled) atmel_wdt_start(wdt); break; case PM_OP_SUSPEND: if (wdt->enabled) atmel_wdt_stop(wdt); break; default: panic("Invalid PM operation"); } return TEE_SUCCESS; } static void atmel_wdt_register_pm(struct atmel_wdt *wdt) { register_pm_driver_cb(atmel_wdt_pm, wdt, "atmel_wdt"); } #else static void atmel_wdt_register_pm(struct atmel_wdt *wdt __unused) { } #endif static TEE_Result wdt_node_probe(const void *fdt, int node, const void *compat_data) { const struct wdt_compat *compat = compat_data; size_t size = 0; struct atmel_wdt *wdt; uint32_t irq_type = 0; uint32_t irq_prio = 0; int it = DT_INFO_INVALID_INTERRUPT; struct itr_handler *it_hdlr = NULL; TEE_Result res = TEE_ERROR_GENERIC; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_BAD_PARAMETERS; if (compat->wdt_ps) matrix_configure_periph_secure(AT91C_ID_WDT); wdt = calloc(1, sizeof(*wdt)); if (!wdt) return TEE_ERROR_OUT_OF_MEMORY; wdt->chip.ops = &atmel_wdt_ops; wdt->type = compat->type; wdt->dis_mask = compat->dis_mask; it = dt_get_irq_type_prio(fdt, node, &irq_type, &irq_prio); if (it == DT_INFO_INVALID_INTERRUPT) goto err_free; res = interrupt_alloc_add_conf_handler(interrupt_get_main_chip(), it, atmel_wdt_itr_cb, 0, wdt, irq_type, irq_prio, &it_hdlr); if (res) goto err_free; if (dt_map_dev(fdt, node, &wdt->base, &size, DT_MAP_AUTO) < 0) goto err_remove_handler; /* Get current state of the watchdog */ wdt->mr = io_read32(wdt->base + WDT_MR) & wdt->dis_mask; atmel_wdt_init_hw(wdt); interrupt_enable(it_hdlr->chip, it_hdlr->it); res = watchdog_register(&wdt->chip); if (res) goto err_disable_unmap; atmel_wdt_register_pm(wdt); return TEE_SUCCESS; err_disable_unmap: interrupt_disable(it_hdlr->chip, it_hdlr->it); core_mmu_remove_mapping(MEM_AREA_IO_SEC, (void *)wdt->base, size); err_remove_handler: interrupt_remove_free_handler(it_hdlr); err_free: free(wdt); return TEE_ERROR_GENERIC; } static const struct wdt_compat sama5d2_compat = { .wdt_ps = true, .type = WDT_TYPE_WDT, .dis_mask = WDT_MR_WDDIS, }; static const struct wdt_compat sama7g5_compat = { .wdt_ps = false, .type = WDT_TYPE_DWDT, .dis_mask = WDT_MR_WDDIS_DWDT, }; static const struct dt_device_match atmel_wdt_match_table[] = { { .compatible = "atmel,sama5d4-wdt", .compat_data = &sama5d2_compat, }, { .compatible = "microchip,sama7g5-wdt", .compat_data = &sama7g5_compat, }, { } }; DEFINE_DT_DRIVER(atmel_wdt_dt_driver) = { .name = "atmel_wdt", .type = DT_DRIVER_NOTYPE, .match_table = atmel_wdt_match_table, .probe = wdt_node_probe, }; optee_os-4.3.0/core/drivers/bcm_gpio.c000066400000000000000000000126421464416617300177050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include #define IPROC_GPIO_DATA_IN_OFFSET 0x00 #define IPROC_GPIO_DATA_OUT_OFFSET 0x04 #define IPROC_GPIO_OUT_EN_OFFSET 0x08 #define IPROC_GPIO_INT_MSK_OFFSET 0x18 #define GPIO_BANK_SIZE 0x200 #define NGPIOS_PER_BANK 32 #define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) #define IPROC_GPIO_REG(pin, reg) ((reg) + \ GPIO_BANK(pin) * GPIO_BANK_SIZE) #define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) #define GPIO_BANK_CNT 5 #define SEC_GPIO_SIZE 0x4 #define IPROC_GPIO_SEC_CFG_REG(pin) \ (((GPIO_BANK_CNT - 1) - GPIO_BANK(pin)) * SEC_GPIO_SIZE) static SLIST_HEAD(, bcm_gpio_chip) gclist = SLIST_HEAD_INITIALIZER(gclist); struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin) { struct bcm_gpio_chip *gc = NULL; SLIST_FOREACH(gc, &gclist, link) if ((pin >= gc->gpio_base) && (pin < (gc->gpio_base + gc->ngpios))) return gc; return NULL; } static bool __maybe_unused gpio_is_range_overlap(unsigned int start, unsigned int end) { struct bcm_gpio_chip *gc = NULL; SLIST_FOREACH(gc, &gclist, link) if ((start < (gc->gpio_base + gc->ngpios)) && (end > gc->gpio_base)) return true; return false; } static void iproc_set_bit(unsigned int reg, unsigned int gpio) { unsigned int offset = IPROC_GPIO_REG(gpio, reg); unsigned int shift = IPROC_GPIO_SHIFT(gpio); struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); assert(gc); io_setbits32(gc->base + offset, BIT(shift)); } static void iproc_clr_bit(unsigned int reg, unsigned int gpio) { unsigned int offset = IPROC_GPIO_REG(gpio, reg); unsigned int shift = IPROC_GPIO_SHIFT(gpio); struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); assert(gc); io_clrbits32(gc->base + offset, BIT(shift)); } static void iproc_gpio_set(struct gpio_chip *chip __unused, unsigned int gpio, enum gpio_level val) { if (val == GPIO_LEVEL_HIGH) iproc_set_bit(IPROC_GPIO_DATA_OUT_OFFSET, gpio); else iproc_clr_bit(IPROC_GPIO_DATA_OUT_OFFSET, gpio); } static enum gpio_level iproc_gpio_get(struct gpio_chip *chip __unused, unsigned int gpio) { unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_DATA_IN_OFFSET); unsigned int shift = IPROC_GPIO_SHIFT(gpio); struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); assert(gc); if (io_read32(gc->base + offset) & BIT(shift)) return GPIO_LEVEL_HIGH; else return GPIO_LEVEL_LOW; } static void iproc_gpio_set_dir(struct gpio_chip *chip __unused, unsigned int gpio, enum gpio_dir dir) { if (dir == GPIO_DIR_OUT) iproc_set_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); else iproc_clr_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); } static enum gpio_dir iproc_gpio_get_dir(struct gpio_chip *chip __unused, unsigned int gpio) { unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_OUT_EN_OFFSET); unsigned int shift = IPROC_GPIO_SHIFT(gpio); struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); assert(gc); if (io_read32(gc->base + offset) & BIT(shift)) return GPIO_DIR_OUT; else return GPIO_DIR_IN; } static enum gpio_interrupt iproc_gpio_get_itr(struct gpio_chip *chip __unused, unsigned int gpio) { unsigned int offset = IPROC_GPIO_REG(gpio, IPROC_GPIO_INT_MSK_OFFSET); unsigned int shift = IPROC_GPIO_SHIFT(gpio); struct bcm_gpio_chip *gc = bcm_gpio_pin_to_chip(gpio); assert(gc); if (io_read32(gc->base + offset) & BIT(shift)) return GPIO_INTERRUPT_ENABLE; else return GPIO_INTERRUPT_DISABLE; } static void iproc_gpio_set_itr(struct gpio_chip *chip __unused, unsigned int gpio, enum gpio_interrupt ena_dis) { if (ena_dis == GPIO_INTERRUPT_ENABLE) iproc_set_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); else iproc_clr_bit(IPROC_GPIO_OUT_EN_OFFSET, gpio); } static const struct gpio_ops bcm_gpio_ops = { .get_direction = iproc_gpio_get_dir, .set_direction = iproc_gpio_set_dir, .get_value = iproc_gpio_get, .set_value = iproc_gpio_set, .get_interrupt = iproc_gpio_get_itr, .set_interrupt = iproc_gpio_set_itr, }; DECLARE_KEEP_PAGER(bcm_gpio_ops); void iproc_gpio_set_secure(int gpiopin) { vaddr_t regaddr = 0; unsigned int shift = IPROC_GPIO_SHIFT(gpiopin); vaddr_t baseaddr = (vaddr_t)phys_to_virt(CHIP_SECURE_GPIO_CONTROL0_BASE, MEM_AREA_IO_SEC, IPROC_GPIO_SEC_CFG_REG(gpiopin) + sizeof(uint32_t)); regaddr = baseaddr + IPROC_GPIO_SEC_CFG_REG(gpiopin); io_clrbits32(regaddr, BIT(shift)); } static void iproc_gpio_init(struct bcm_gpio_chip *gc, unsigned int paddr, unsigned int gpio_base, unsigned int ngpios) { assert(!gpio_is_range_overlap(gpio_base, gpio_base + gc->ngpios)); gc->base = core_mmu_get_va(paddr, MEM_AREA_IO_SEC, 1); gc->chip.ops = &bcm_gpio_ops; gc->gpio_base = gpio_base; gc->ngpios = ngpios; SLIST_INSERT_HEAD(&gclist, gc, link); DMSG("gpio chip for <%u - %u>", gpio_base, gpio_base + ngpios); } static TEE_Result bcm_gpio_init(void) { struct bcm_gpio_chip *gc = NULL; #ifdef SECURE_GPIO_BASE0 gc = malloc(sizeof(*gc)); if (gc == NULL) return TEE_ERROR_OUT_OF_MEMORY; iproc_gpio_init(gc, SECURE_GPIO_BASE0, GPIO_NUM_START0, NUM_GPIOS0); #endif #ifdef SECURE_GPIO_BASE1 gc = malloc(sizeof(*gc)); if (gc == NULL) return TEE_ERROR_OUT_OF_MEMORY; iproc_gpio_init(gc, SECURE_GPIO_BASE1, GPIO_NUM_START1, NUM_GPIOS1); #endif return TEE_SUCCESS; } driver_init(bcm_gpio_init); optee_os-4.3.0/core/drivers/bcm_hwrng.c000066400000000000000000000040111464416617300200630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include /* Registers */ #define RNG_CTRL_OFFSET 0x00 #define RNG_CTRL_MASK 0x00001fff #define RNG_CTRL_DISABLE 0x00000000 #define RNG_CTRL_ENABLE 0x00000001 #define RNG_SOFT_RESET_OFFSET 0x04 #define RNG_SOFT_RESET_MASK 0x00000001 #define RNG_FIFO_DATA_OFFSET 0x20 #define RNG_FIFO_COUNT_OFFSET 0x24 #define RNG_FIFO_COUNT_MASK 0x000000ff #define RNG_TIMEOUT_US 10000 static vaddr_t bcm_hwrng_base; static void bcm_hwrng_reset(void) { /* Disable RBG */ io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET, RNG_CTRL_MASK, RNG_CTRL_DISABLE); /* Reset RNG and RBG */ io_setbits32(bcm_hwrng_base + RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK); io_clrbits32(bcm_hwrng_base + RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK); /* Enable RBG */ io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET, RNG_CTRL_MASK, RNG_CTRL_ENABLE); } uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read) { uint32_t available_words = 0; uint32_t num_words = 0; uint32_t i = 0; uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US); assert(bcm_hwrng_base); do { available_words = io_read32(bcm_hwrng_base + RNG_FIFO_COUNT_OFFSET); available_words = available_words & RNG_FIFO_COUNT_MASK; } while (!available_words && !timeout_elapsed(timeout)); if ((available_words > 0) && (words_to_read > 0)) { num_words = MIN(available_words, words_to_read); for (i = 0; i < num_words; i++) p_out[i] = io_read32(bcm_hwrng_base + RNG_FIFO_DATA_OFFSET); } return num_words; } static TEE_Result bcm_hwrng_init(void) { bcm_hwrng_base = (vaddr_t)phys_to_virt(HWRNG_BASE, MEM_AREA_IO_SEC, HWRNG_END - HWRNG_BASE); bcm_hwrng_reset(); DMSG("bcm_hwrng init done"); return TEE_SUCCESS; } driver_init(bcm_hwrng_init); optee_os-4.3.0/core/drivers/bcm_sotp.c000066400000000000000000000203411464416617300177270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include #include #define SOTP_PROG_CONTROL 0x00 #define SOTP_WRDATA_0 0x04 #define SOTP_WRDATA_1 0x08 #define SOTP_ADDR 0x0c #define SOTP_CTRL_0 0x10 #define SOTP_STAT_0 0x18 #define SOTP_STATUS_1 0x1c #define SOTP_RDDATA_0 0x20 #define SOTP_RDDATA_1 0x24 #define SOTP_REGS_SOTP_CHIP_STATES 0x28 #define SOTP_REGS_OTP_WR_LOCK 0x38 #define SOTP_CHIP_CTRL 0x4c #define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN BIT(15) #define SOTP_PROG_CONTROL__OTP_DISABLE_ECC BIT(9) #define SOTP_ADDR__OTP_ROW_ADDR_R 6 #define SOTP_PROG_CONTROL__OTP_ECC_WREN BIT(8) #define SOTP_CTRL_0__START 1 #define SOTP_STATUS_0__FDONE BIT(3) #define SOTP_STATUS_1__CMD_DONE BIT(1) #define SOTP_STATUS_1__ECC_DET BIT(17) #define SOTP_READ 0 #define SOTP_ADDR_MASK 0x3ff #define SOTP_TIMEOUT_US 300 #define SOTP_PROG_WORD 10 #define SOTP_STATUS__PROGOK BIT(2) #define SOTP_PROG_ENABLE 2 #define SOTP_ROW_DATA_MASK UINT32_MAX #define SOTP_ECC_ERR_BITS_MASK GENMASK_64(40, 32) #define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4 #define SOTP_CHIP_CTRL_SW_MANU_PROG 5 #define SOTP_CHIP_CTRL_SW_CID_PROG 6 #define SOTP_CHIP_CTRL_SW_AB_DEVICE 8 #define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9 #define CHIP_STATE_UNPROGRAMMED 0x1 #define CHIP_STATE_UNASSIGNED 0x2 #define CHIP_STATE_DEFAULT (CHIP_STATE_UNASSIGNED | \ CHIP_STATE_UNPROGRAMMED) static vaddr_t bcm_sotp_base; static TEE_Result otp_status_done_wait(vaddr_t addr, uint32_t bit) { uint64_t timeout = timeout_init_us(SOTP_TIMEOUT_US); while (!(io_read32(addr) & bit)) if (timeout_elapsed(timeout)) return TEE_ERROR_BUSY; return TEE_SUCCESS; } TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, bool sotp_add_ecc, uint64_t *rdata) { uint64_t read_data = 0; uint32_t reg_val = 0; TEE_Result ret = TEE_SUCCESS; assert(bcm_sotp_base); /* Check for FDONE status */ ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), SOTP_STATUS_0__FDONE); if (ret) { EMSG("FDONE status done wait failed and returned %#"PRIx32, ret); return ret; } /* Enable OTP access by CPU */ io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); /* ROWS does not support ECC */ if (row_addr <= SOTP_NO_ECC_ROWS) sotp_add_ecc = false; if (sotp_add_ecc) { io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), SOTP_PROG_CONTROL__OTP_DISABLE_ECC); } else { io_setbits32((bcm_sotp_base + SOTP_PROG_CONTROL), SOTP_PROG_CONTROL__OTP_DISABLE_ECC); } /* 10 bit row address */ reg_val = (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R; io_write32((bcm_sotp_base + SOTP_ADDR), reg_val); reg_val = SOTP_READ; io_write32((bcm_sotp_base + SOTP_CTRL_0), reg_val); /* Start bit to tell SOTP to send command to the OTP controller */ io_setbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); /* Wait for SOTP command done to be set */ ret = otp_status_done_wait((bcm_sotp_base + SOTP_STAT_0), SOTP_STATUS_1__CMD_DONE); if (ret) { EMSG("FDONE cmd done wait failed and returned %#"PRIx32, ret); return ret; } DMSG("CMD Done"); /* Clr Start bit after command done */ io_clrbits32((bcm_sotp_base + SOTP_CTRL_0), SOTP_CTRL_0__START); read_data = io_read32(bcm_sotp_base + SOTP_RDDATA_1); read_data = ((read_data & 0x1ff) << 32); read_data |= io_read32(bcm_sotp_base + SOTP_RDDATA_0); reg_val = io_read32(bcm_sotp_base + SOTP_STATUS_1); /* No ECC check till SOTP_NO_ECC_ROWS */ if (row_addr > SOTP_NO_ECC_ROWS && reg_val & SOTP_STATUS_1__ECC_DET) { EMSG("SOTP ECC ERROR Detected ROW %"PRIu32, row_addr); read_data = SOTP_ECC_ERR_DETECT; } /* Command done is cleared */ io_setbits32((bcm_sotp_base + SOTP_STATUS_1), SOTP_STATUS_1__CMD_DONE); io_clrbits32((bcm_sotp_base + SOTP_PROG_CONTROL), SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); DMSG("read done"); *rdata = read_data; return ret; } TEE_Result bcm_iproc_sotp_mem_write(uint32_t row_addr, bool sotp_add_ecc, uint64_t wdata) { uint32_t chip_state = 0; uint32_t chip_ctrl_default = 0; uint32_t chip_ctrl = 0; uint32_t loop = 0; uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D }; TEE_Result ret = TEE_SUCCESS; assert(bcm_sotp_base); chip_state = io_read32(bcm_sotp_base + SOTP_REGS_SOTP_CHIP_STATES); if (chip_state & CHIP_STATE_DEFAULT) { chip_ctrl_default = io_read32(bcm_sotp_base + SOTP_CHIP_CTRL); DMSG("SOTP: enable special prog mode"); chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) | BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) | BIT(SOTP_CHIP_CTRL_SW_CID_PROG) | BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE); io_write32(bcm_sotp_base + SOTP_CHIP_CTRL, chip_ctrl); } /* Check for FDONE status */ ret = otp_status_done_wait(bcm_sotp_base + SOTP_STAT_0, SOTP_STATUS_0__FDONE); if (ret) { EMSG("FDONE status done wait failed and returned %#"PRIx32, ret); return ret; } /* Enable OTP access by CPU */ io_setbits32(bcm_sotp_base + SOTP_PROG_CONTROL, SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); if (row_addr <= SOTP_NO_ECC_ROWS) { if (sotp_add_ecc) { io_setbits32(bcm_sotp_base + SOTP_PROG_CONTROL, SOTP_PROG_CONTROL__OTP_ECC_WREN); } else { io_clrbits32(bcm_sotp_base + SOTP_PROG_CONTROL, SOTP_PROG_CONTROL__OTP_ECC_WREN); } } else { io_clrbits32(bcm_sotp_base + SOTP_PROG_CONTROL, SOTP_PROG_CONTROL__OTP_ECC_WREN); } io_write32(bcm_sotp_base + SOTP_CTRL_0, SOTP_PROG_ENABLE << 1); /* * In order to avoid unintentional writes/programming of the OTP array, * the OTP Controller must be put into programming mode before it will * accept program commands. This is done by writing 0xF, 0x4, 0x8, 0xD * with program commands prior to starting the actual programming * sequence. */ for (loop = 0; loop < ARRAY_SIZE(prog_array); loop++) { io_write32(bcm_sotp_base + SOTP_WRDATA_0, prog_array[loop]); /* Bit to tell SOTP to send command to the OTP controller */ io_setbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); /* Wait for SOTP command done to be set */ ret = otp_status_done_wait(bcm_sotp_base + SOTP_STATUS_1, SOTP_STATUS_1__CMD_DONE); if (ret) { EMSG("FDONE cmd done wait failed and returned %"PRIx32, ret); return ret; } /* Command done is cleared w1c */ io_setbits32(bcm_sotp_base + SOTP_STATUS_1, SOTP_STATUS_1__CMD_DONE); /* Clear Start bit after command done */ io_clrbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); } /* Check for PROGOK */ ret = otp_status_done_wait(bcm_sotp_base + SOTP_STAT_0, SOTP_STATUS__PROGOK); if (ret) { EMSG("PROGOK cmd wait failed and returned %#"PRIx32, ret); return ret; } /* Set 10 bit row address */ io_write32(bcm_sotp_base + SOTP_ADDR, (row_addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R); /* Set SOTP Row data */ io_write32(bcm_sotp_base + SOTP_WRDATA_0, wdata & SOTP_ROW_DATA_MASK); /* Set SOTP ECC and error bits */ io_write32(bcm_sotp_base + SOTP_WRDATA_1, (wdata & SOTP_ECC_ERR_BITS_MASK) >> 32); /* Set prog_word command */ io_write32(bcm_sotp_base + SOTP_CTRL_0, SOTP_PROG_WORD << 1); /* Start bit to tell SOTP to send command to the OTP controller */ io_setbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); /* Wait for SOTP command done to be set */ ret = otp_status_done_wait(bcm_sotp_base + SOTP_STATUS_1, SOTP_STATUS_1__CMD_DONE); if (ret) { EMSG("CMD DONE wait failed and returned %#"PRIx32, ret); return ret; } /* Command done is cleared w1c */ io_setbits32(bcm_sotp_base + SOTP_STATUS_1, SOTP_STATUS_1__CMD_DONE); /* disable OTP access by CPU */ io_clrbits32(bcm_sotp_base + SOTP_PROG_CONTROL, SOTP_PROG_CONTROL__OTP_CPU_MODE_EN); /* Clr Start bit after command done */ io_clrbits32(bcm_sotp_base + SOTP_CTRL_0, SOTP_CTRL_0__START); if (chip_state & CHIP_STATE_DEFAULT) io_write32(bcm_sotp_base + SOTP_CHIP_CTRL, chip_ctrl_default); return TEE_SUCCESS; } static TEE_Result bcm_sotp_init(void) { bcm_sotp_base = (vaddr_t)phys_to_virt(SOTP_BASE, MEM_AREA_IO_SEC, 1); DMSG("bcm_sotp init done"); return TEE_SUCCESS; } service_init(bcm_sotp_init); optee_os-4.3.0/core/drivers/bnxt/000077500000000000000000000000001464416617300167305ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/bnxt/bnxt.c000066400000000000000000000127171464416617300200570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include #define BNXT_REG_CTRL_BASE 0x3040000 #define BNXT_REG_ECO_RESERVED 0x3042400 #define BNXT_FLASH_ACCESS_DONE_BIT 2 #define NIC400_BNXT_IDM_IO_CONTROL_DIRECT 0x60e00408 #define BNXT_INDIRECT_BASE 0x60800000 #define BNXT_INDIRECT_ADDR_MASK 0x3fffffu #define BNXT_INDIRECT_BASE_MASK (~BNXT_INDIRECT_ADDR_MASK) #define BNXT_INDIRECT_WINDOW_SIZE (BNXT_INDIRECT_ADDR_MASK + 1) #define BNXT_REG_CTRL_BPE_MODE_REG 0x0 #define BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT 2 #define BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT 1 #define BNXT_REG_CTRL_BPE_STAT_REG 0x4 #define BNXT_REG_CTRL_FSTBOOT_PTR_REG 0x8 #define BNXT_ERROR_MASK 0xf0000000 #define BNXT_CTRL_ADDR(x) (BNXT_REG_CTRL_BASE + (x)) #define BNXT_HANDSHAKE_TIMEOUT_MS 1000 #define KONG_REG_CTRL_MODE_REG 0x03900000 #define KONG_REG_CTRL_MODE_CPUHALT_N_BIT 0 #define BNXT_STICKY_BYTE_POR 0x04030088 #define BNXT_STICKY_BYTE_POR_MHB_BIT 4 #define BNXT_HEALTH_CHECK_REG 0x03100008 enum bnxt_handshake_sts { BNXT_HANDSHAKE_SUCCESS = 0, BNXT_HANDSHAKE_WAIT_ERROR, BNXT_HANDSHAKE_WAIT_TIMEOUT }; static vaddr_t bnxt_access_window_virt_addr; static vaddr_t bnxt_indirect_dest_addr; static void bnxt_prepare_access_window(uint32_t addr) { addr &= BNXT_INDIRECT_BASE_MASK; io_write32(bnxt_access_window_virt_addr, addr); } static vaddr_t bnxt_indirect_tgt_addr(uint32_t addr) { addr &= BNXT_INDIRECT_ADDR_MASK; return (vaddr_t)(bnxt_indirect_dest_addr + addr); } uint32_t bnxt_write32_multiple(uintptr_t dst, uintptr_t src, uint32_t num_entries, int src_4byte_increment) { uint32_t i = 0; vaddr_t target = 0; if (num_entries == 0) return 0; /* Only write up to the next window boundary */ if ((dst & BNXT_INDIRECT_BASE_MASK) != ((dst + num_entries * sizeof(uint32_t)) & BNXT_INDIRECT_BASE_MASK)) num_entries = (((dst + BNXT_INDIRECT_WINDOW_SIZE) & BNXT_INDIRECT_BASE_MASK) - dst) / sizeof(uint32_t); bnxt_prepare_access_window(dst); target = bnxt_indirect_tgt_addr(dst); for (i = 0; i < num_entries; i++) { io_write32(target, *(uint32_t *)src); target += sizeof(uint32_t); if (src_4byte_increment) src += sizeof(uint32_t); } return num_entries; } static uint32_t bnxt_read(uint32_t addr) { bnxt_prepare_access_window(addr); return io_read32(bnxt_indirect_tgt_addr(addr)); } static uint32_t bnxt_read_ctrl(uint32_t offset) { return bnxt_read(BNXT_CTRL_ADDR(offset)); } static void bnxt_write(uint32_t addr, uint32_t value) { bnxt_prepare_access_window(addr); io_write32(bnxt_indirect_tgt_addr(addr), value); } static void bnxt_write_ctrl(uint32_t offset, uint32_t value) { bnxt_write(BNXT_CTRL_ADDR(offset), value); } void bnxt_handshake_clear(void) { uint32_t value = bnxt_read(BNXT_REG_ECO_RESERVED); value = value & ~BIT(BNXT_FLASH_ACCESS_DONE_BIT); bnxt_write(BNXT_REG_ECO_RESERVED, value); } static int bnxt_handshake_done(void) { uint32_t value = 0; value = bnxt_read(BNXT_REG_ECO_RESERVED); value &= BIT(BNXT_FLASH_ACCESS_DONE_BIT); return value != 0; } uint32_t bnxt_wait_handshake(uint32_t max_timeout) { int ret = 0; uint32_t status = 0; uint32_t timeout = 0; /* If no timeout given we go with max timeout */ if (max_timeout == 0) max_timeout = BNXT_HANDSHAKE_TIMEOUT_MS; timeout = max_timeout; DMSG("Waiting for ChiMP handshake..."); do { if (bnxt_handshake_done()) { ret = BNXT_HANDSHAKE_SUCCESS; break; } /* No need to wait if ChiMP reported an error */ status = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_STAT_REG); if (status & BNXT_ERROR_MASK) { EMSG("ChiMP error 0x%x. Wait aborted", status); ret = BNXT_HANDSHAKE_WAIT_ERROR; break; } mdelay(1); } while (--timeout); if (!bnxt_handshake_done()) { if (timeout == 0) { ret = BNXT_HANDSHAKE_WAIT_TIMEOUT; EMSG("Timeout waiting for ChiMP handshake"); } } else { ret = BNXT_HANDSHAKE_SUCCESS; DMSG("ChiMP handshake successful"); } return ret; } void bnxt_chimp_halt(void) { uint32_t value = 0; value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG); value |= BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT); bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value); } void bnxt_kong_halt(void) { uint32_t value = 0; value = bnxt_read(KONG_REG_CTRL_MODE_REG); value &= ~BIT(KONG_REG_CTRL_MODE_CPUHALT_N_BIT); bnxt_write(KONG_REG_CTRL_MODE_REG, value); } int bnxt_fastboot(uintptr_t addr) { uint32_t value = 0; value = bnxt_read(BNXT_STICKY_BYTE_POR); value |= BIT(BNXT_STICKY_BYTE_POR_MHB_BIT); bnxt_write(BNXT_STICKY_BYTE_POR, value); /* Set the fastboot address and type */ bnxt_write_ctrl(BNXT_REG_CTRL_FSTBOOT_PTR_REG, addr); /* Set fastboot mode & take BNXT CPU1 out of reset */ value = bnxt_read_ctrl(BNXT_REG_CTRL_BPE_MODE_REG); value |= BIT(BNXT_REG_CTRL_BPE_MODE_FASTBOOT_MODE_BIT); value &= ~BIT(BNXT_REG_CTRL_BPE_MODE_CM3_RST_BIT); bnxt_write_ctrl(BNXT_REG_CTRL_BPE_MODE_REG, value); return 0; } uint32_t bnxt_health_status(void) { return bnxt_read(BNXT_HEALTH_CHECK_REG); } static TEE_Result bnxt_init(void) { bnxt_access_window_virt_addr = (vaddr_t)phys_to_virt(NIC400_BNXT_IDM_IO_CONTROL_DIRECT, MEM_AREA_IO_SEC, sizeof(uint32_t)); bnxt_indirect_dest_addr = (vaddr_t)phys_to_virt(BNXT_INDIRECT_BASE, MEM_AREA_IO_SEC, BNXT_INDIRECT_WINDOW_SIZE); return TEE_SUCCESS; } driver_init(bnxt_init); optee_os-4.3.0/core/drivers/bnxt/bnxt_fw.c000066400000000000000000000425471464416617300205570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include /* * These macros are the offsets where images reside on sec mem */ #define BNXT_BUFFER_SEC_MEM 0x8ae00000 #define BNXT_FW_SEC_MEM_SRC BNXT_BUFFER_SEC_MEM #define BNXT_FW_SEC_MEM_CFG (BNXT_BUFFER_SEC_MEM + 0x100000) #define TEMP_MEM (BNXT_BUFFER_SEC_MEM + 0x180000) #define BNXT_CRASH_SEC_MEM 0x8b000000 #define BNXT_CRASH_LEN 0x2000000 #define BNXT_CONFIG_NS3_DEST 0x03a00000 #define BNXT_BSPD_CFG_OFFSET 0x51b0 #define BNXT_CONFIG_NS3_BSPD_DEST (BNXT_CONFIG_NS3_DEST + \ BNXT_BSPD_CFG_OFFSET) #define BNXT_BSPD_CFG_SIZE 0x200 #define BNXT_CRASH_DUMP_INFO_NS3_BASE 0x3a5ff00 #define SZ_1K 0x400 #define BUFFER_PADDING SZ_1K #define INC_SRC_ADDR 1 #define EOF -1 #define BCM_BNXT_FASTBOOT_MASK 0x3u #define BCM_BNXT_FASTBOOT_TYPE_1 1 #define ADDR_IS_4BYTE_ALIGNED(addr) IS_ALIGNED(addr, 4) #define SECTION_IS_LOADABLE(section_ptr) \ ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_LOADABLE) #define SECTION_IS_ZIPPED(section_ptr) \ ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_ZIPPED) #define SECTION_IS_TOBE_COPIED(section_ptr) \ ((section_ptr)->flags_src_offset & \ (SECTION_FLAGS_IS_EXEC_INSTR | SECTION_FLAGS_IS_DATA)) #define SECTION_IS_TOBE_ZEROED(section_ptr) \ ((section_ptr)->flags_src_offset & SECTION_FLAGS_IS_BSS) #define SECTION_IS_4BYTE_ALIGNED(section_ptr) \ ADDR_IS_4BYTE_ALIGNED((section_ptr)->dest_addr) #define SECTION_SRC_OFFSET(section_ptr) \ ((section_ptr)->flags_src_offset & SECTION_SRC_OFFFSET_MASK) /* -------------------------------------------------------------------------- */ /* Section header for each image block */ struct ape_section_hdr_s { /* Destination address that this section is to be copied to */ uint32_t dest_addr; /* * bit[0:23] source offset address that this image copy from * bit[24:31] flags */ uint32_t flags_src_offset; #define SECTION_FLAGS_MASK 0xff000000 /* Session is compressed (zipped) */ #define SECTION_FLAGS_IS_ZIPPED 0x01000000 /* Session contains CRC */ #define SECTION_FLAGS_IS_CRC 0x02000000 /* Session contains executable code (e.g. .text) */ #define SECTION_FLAGS_IS_EXEC_INSTR 0x04000000 /* Session contains initialized data (e.g. .data) */ #define SECTION_FLAGS_IS_DATA 0x08000000 /* Session contains zero initialized data (e.g. .bss) */ #define SECTION_FLAGS_IS_BSS 0x10000000 /* Loadable section mask */ #define SECTION_FLAGS_IS_LOADABLE (SECTION_FLAGS_IS_EXEC_INSTR | \ SECTION_FLAGS_IS_DATA | \ SECTION_FLAGS_IS_BSS) #define SECTION_SRC_OFFFSET_MASK 0x00ffffff /* Original image length, dword (4byte) length */ uint32_t org_data_len; /* Compressed image length (if FlAGS_IS_ZIPPED is set) */ uint32_t zip_data_len; /* * checksum value for this image block, if FLAGS_IS_CRC then * this is CRC checksum; otherwise it is a simple summation */ uint32_t checksum; }; struct version_s { uint8_t version[16]; /* Null-terminated file version string */ }; struct ver_ext_offset_s { uint8_t version[12]; /* Null-terminated file version string */ uint32_t ext_hdr_offset; }; union version_and_offset_u { struct version_s version1; struct ver_ext_offset_s version2; }; struct ape_bin_hdr_s { /* APE binary header signature; expects APE_BIN_HDR_SIGNATURE */ uint32_t signature; #define APE_BIN_HDR_SIGNATURE 0x1a4d4342 /* "BCM"+0x1a */ /* Reserved for ChiMP's use */ uint8_t flags; uint8_t code_type; uint8_t device; uint8_t media; union version_and_offset_u ver; uint8_t build; uint8_t revision; uint8_t minor_ver; uint8_t major_ver; uint32_t entry_address; uint8_t reserved; uint8_t header_dword_size; uint8_t num_total_sections; uint8_t num_loadable_sections; uint32_t checksum; } __packed __aligned(1); #define APE_BIN_HDR_SIZE sizeof(struct ape_bin_hdr_s) #define APE_SECTION_HDR_SIZE sizeof(struct ape_section_hdr_s) /* MAX number of image sections that will be accepted */ #define APE_IMG_MAX_SECTIONS 16 #define APE_IMG_LOAD_DEBUG 0 /* -------------------------------------------------------------------------- */ struct ape_mem_region_s { uint32_t c_base; /* ChiMP's view of address */ uint32_t h_base; /* Host's view of address */ uint32_t size; /* Size in bytes */ }; /* Memory map into various scratchpad memories */ static struct ape_mem_region_s ape_mem_regions[] = { /* CHIMP scratchpad */ {0x00100000, 0x03100000, 1024 * SZ_1K}, /* APE scratchpad */ {0x61000000, 0x03300000, 1152 * SZ_1K}, /* BONO scratchpad */ {0x61600000, 0x03a00000, 512 * SZ_1K}, /* KONG scratchpad */ {0x61400000, 0x03800000, 512 * SZ_1K}, /* Keep this last!! */ {0, 0, 0} }; /* Nitro crash address configuration related macros */ #define BNXT_CRASH_INFO_SIGNATURE 0x20524444 #define BNXT_CRASH_INFO_VALID 0x1 #define MAX_CRASH_ADDR_ITEM 8 struct nitro_crash_addr_item { uint32_t info; uint32_t size; uint32_t addr_hi; uint32_t addr_lo; }; struct nitro_crash_addr_info { /* CRC of the struct content, starting at next field. */ uint32_t crc; uint32_t signature; uint32_t version; struct nitro_crash_addr_item table[MAX_CRASH_ADDR_ITEM]; }; static inline void memcpy32_helper(uintptr_t src, uintptr_t dst, uint32_t entries, int inc_src_addr) { uint32_t copied_entries = 0; while (entries) { copied_entries = bnxt_write32_multiple(dst, src, entries, inc_src_addr); if (copied_entries < entries) { dst += copied_entries * sizeof(uint32_t); src += (inc_src_addr) ? (copied_entries * sizeof(uint32_t)) : 0; entries -= copied_entries; } else { entries = 0; } } } static uint32_t ape_host_view_addr_get(uint32_t bnxt_view_addr, uint32_t size) { struct ape_mem_region_s *region = ape_mem_regions; uint32_t addr = 0; for (; region->size != 0; region++) { if (bnxt_view_addr < region->c_base) continue; if (bnxt_view_addr >= (region->c_base + region->size)) continue; if (size > (region->c_base + region->size - bnxt_view_addr)) { EMSG("ERROR: 0x%x + 0x%x spans memory boundary", bnxt_view_addr, size); break; } addr = bnxt_view_addr - region->c_base; addr += region->h_base; break; } return addr; } static uint32_t ape_hdr_crc_calc(const struct ape_bin_hdr_s *hdr) { uint32_t crc = 0; uint32_t dummy = 0; /* Compute the CRC up to, but not including, the checksum field */ crc = CRC32(CRC32_INIT_VAL, (const char *)hdr, (uintptr_t)(&hdr->checksum) - (uintptr_t)hdr); /* Compute the CRC with the checksum field zeroed out */ crc = CRC32(~crc, (const char *)&dummy, sizeof(uint32_t)); /* * Compute the remainder part of the image header, i.e., the * section headers */ crc = CRC32(~crc, (const char *)((uintptr_t)hdr + APE_BIN_HDR_SIZE), hdr->num_total_sections * APE_SECTION_HDR_SIZE); return crc; } static int ape_bin_hdr_valid(const struct ape_bin_hdr_s *hdr) { uint32_t checksum = 0; if (!hdr) { EMSG("ERROR: no APE image header"); return BNXT_FAILURE; } if (hdr->signature != APE_BIN_HDR_SIGNATURE) { EMSG("ERROR: bad APE image signature"); return BNXT_FAILURE; } if (hdr->num_total_sections > APE_IMG_MAX_SECTIONS) { EMSG("ERROR: too many sections in APE image"); return BNXT_FAILURE; } checksum = ape_hdr_crc_calc(hdr); if (hdr->checksum != checksum) { EMSG("ERROR: bad APE header checksum (exp: %x, act: %x)", hdr->checksum, checksum); return BNXT_FAILURE; } return BNXT_SUCCESS; } static int get_char(uint8_t *inbuf, size_t *inbuf_idx, size_t inbuf_size) { int c = 0; if (*inbuf_idx >= inbuf_size) return EOF; c = inbuf[*inbuf_idx]; *inbuf_idx += 1; return c; } static void put_char(uint8_t *outbuf, size_t *outbuf_idx, size_t outbuf_size, uint8_t ch) { if (*outbuf_idx >= outbuf_size) return; outbuf[*outbuf_idx] = ch; *outbuf_idx += 1; } static size_t ape_section_uncompress(uint8_t *inbuf, size_t inbuf_size, uint8_t *outbuf, size_t outbuf_size) { int i = 0, j = 0, k = 0, r = 0, c = 0; uint32_t flags = 0; size_t exp_size = 0, codesize = 0; size_t inbuf_idx = 0, outbuf_idx = 0; #define CODE_8U_MASK 0xff00u /* 8 code units count mask (8 bits) */ #define CODE_END_MASK 0x100u /* End of code units mask */ #define CODE_IS_UNENCODED_MASK 1 /* Unencoded code unit mask */ #define CODE_POS_MASK 0xe0u /* Encoded unit position mask and */ #define CODE_POS_SHIFT 3 /* Bit shift */ #define CODE_LEN_MASK 0x1fu /* Encoded unit length mask */ #define NS 2048 /* Size of ring buffer */ #define F 34 /* Upper limit for match_length */ #define THRESHOLD 2 /* Encode string into position and * length, if match_length is * greater than this. */ /* * Ring buffer of size NS, with an extra F-1 bytes to facilitate * string comparisons. */ uint8_t text_buf[NS + F - 1]; inbuf_idx = 0; outbuf_idx = 0; for (i = 0; i < NS - F; i++) text_buf[i] = ' '; r = NS - F; for (;;) { if (((flags >>= 1) & CODE_END_MASK) == 0) { c = get_char(inbuf, &inbuf_idx, inbuf_size); if (c == EOF) break; ++exp_size; if (exp_size > inbuf_size) break; /* Use higher byte cleverly to count to eight */ flags = c | CODE_8U_MASK; } if (flags & CODE_IS_UNENCODED_MASK) { /* Not encoded; simply copy the unit */ c = get_char(inbuf, &inbuf_idx, inbuf_size); if (c == EOF) break; ++exp_size; if (exp_size > inbuf_size) break; put_char(outbuf, &outbuf_idx, outbuf_size, c); text_buf[r++] = c; r &= (NS - 1); ++codesize; } else { /* Encoded; get the position and length & duplicate */ i = get_char(inbuf, &inbuf_idx, inbuf_size); if (i == EOF) break; ++exp_size; if (exp_size > inbuf_size) break; j = get_char(inbuf, &inbuf_idx, inbuf_size); if (j == EOF) break; ++exp_size; if (exp_size > inbuf_size) break; i |= ((j & CODE_POS_MASK) << CODE_POS_SHIFT); j = ((j & CODE_LEN_MASK) + THRESHOLD); for (k = 0; k <= j; k++) { c = text_buf[((i + k) & (NS - 1))]; put_char(outbuf, &outbuf_idx, outbuf_size, c); text_buf[r++] = c; r &= (NS - 1); ++codesize; } } } return codesize; } static int ape_section_copy(struct ape_bin_hdr_s *bin_hdr, struct ape_section_hdr_s *section) { uintptr_t src = 0; uintptr_t dst = 0; uint32_t checksum = 0; uint32_t i = 0; size_t size = 0; uint8_t *section_data = NULL; size_t work_buff_size = 0; void *work_buff = NULL; int rc = BNXT_FAILURE; if (SECTION_IS_ZIPPED(section)) { work_buff_size = section->org_data_len + BUFFER_PADDING; work_buff = (void *)phys_to_virt(TEMP_MEM, MEM_AREA_RAM_SEC, work_buff_size); if (!work_buff) { EMSG("ERROR: buffer allocation"); return BNXT_FAILURE; } section_data = (uint8_t *)((uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section)); size = ape_section_uncompress(section_data, section->zip_data_len, work_buff, work_buff_size); if (size >= work_buff_size) { EMSG("ERROR: section uncompress"); goto ape_section_copy_exit; } if (size < section->org_data_len) { EMSG("ERROR: decompressed data size mismatch "); EMSG("(exp: %d, act: %ld)", section->org_data_len, size); goto ape_section_copy_exit; } src = (uintptr_t)work_buff; } else { src = (uintptr_t)bin_hdr + SECTION_SRC_OFFSET(section); } size = section->org_data_len; if (section->flags_src_offset & SECTION_FLAGS_IS_CRC) { checksum = CRC32(CRC32_INIT_VAL, (const char *)src, size); } else { checksum = 0; for (i = 0; i < size / sizeof(uint32_t); i++) checksum += ((uint32_t *)src)[i]; } if (checksum != section->checksum) { EMSG("ERROR: checksum mismatch (exp: %x, act: %x)", section->checksum, checksum); goto ape_section_copy_exit; } dst = ape_host_view_addr_get(section->dest_addr, size); if (dst == 0) { EMSG("ERROR: ChiMP-to-host address conversion of %x", section->dest_addr); goto ape_section_copy_exit; } /* Copy the section */ size = size / sizeof(uint32_t); memcpy32_helper(src, dst, size, INC_SRC_ADDR); rc = BNXT_SUCCESS; ape_section_copy_exit: return rc; } static int ape_section_zero(struct ape_section_hdr_s *section) { uint32_t dst = 0; uint32_t size = section->org_data_len; uint32_t zero = 0; if (section->org_data_len == 0) return BNXT_SUCCESS; /* Convert ChiMP's view of the address in the image to the host view */ dst = ape_host_view_addr_get(section->dest_addr, size); if (dst == 0) { EMSG("ERROR: ChiMP-to-host address conversion of %x", section->dest_addr); return BNXT_FAILURE; } /* * Zero the section; we simply copy zeros and do not increment the * source buffer address. */ size = size / sizeof(uint32_t); memcpy32_helper((uintptr_t)&zero, dst, size, !INC_SRC_ADDR); return BNXT_SUCCESS; } static int bnxt_load(vaddr_t img_buffer) { struct ape_bin_hdr_s *bin_hdr = NULL; struct ape_section_hdr_s *section = NULL; int sidx = 0; int rc = BNXT_SUCCESS; bin_hdr = (struct ape_bin_hdr_s *)img_buffer; section = (struct ape_section_hdr_s *)(img_buffer + APE_BIN_HDR_SIZE); if (ape_bin_hdr_valid(bin_hdr) != BNXT_SUCCESS) return BNXT_FAILURE; for (sidx = 0; sidx < bin_hdr->num_total_sections; sidx++, section++) { if (!SECTION_IS_LOADABLE(section)) continue; if (!ADDR_IS_4BYTE_ALIGNED(section->dest_addr)) { EMSG("ERROR: unaligned section dest address 0x%x", section->dest_addr); rc = BNXT_FAILURE; break; } if (!ADDR_IS_4BYTE_ALIGNED(SECTION_SRC_OFFSET(section))) { EMSG("ERROR: unaligned section src offset (0x%x)", SECTION_SRC_OFFSET(section)); rc = BNXT_FAILURE; break; } if (section->org_data_len % sizeof(uint32_t)) { EMSG("ERROR: section size (%d) not divisible by 4", section->org_data_len); rc = BNXT_FAILURE; break; } if (SECTION_IS_TOBE_COPIED(section)) { rc = ape_section_copy(bin_hdr, section); if (rc != BNXT_SUCCESS) break; } else if (SECTION_IS_TOBE_ZEROED(section)) { rc = ape_section_zero(section); if (rc != BNXT_SUCCESS) break; } } /* Set up boot mode and take BNXT out of reset */ if (rc == BNXT_SUCCESS) { bnxt_fastboot((bin_hdr->entry_address & ~BCM_BNXT_FASTBOOT_MASK) | BCM_BNXT_FASTBOOT_TYPE_1); } return rc; } static TEE_Result bnxt_crash_config(uintptr_t info_dst, uint32_t crash_area_start, uint32_t crash_len) { struct nitro_crash_addr_item *item = NULL; uintptr_t dst = 0; struct nitro_crash_addr_info *info = NULL; uintptr_t src = 0; uint32_t crc = 0; size_t size = 0; /* * First we write into local memory to calculate CRC before * updating into Nitro memory */ info = malloc(sizeof(struct nitro_crash_addr_info)); if (!info) { EMSG("ERROR: buffer allocation"); return TEE_ERROR_OUT_OF_MEMORY; } memset(info, 0, sizeof(struct nitro_crash_addr_info)); info->signature = BNXT_CRASH_INFO_SIGNATURE; info->version = 0x01000000 | MAX_CRASH_ADDR_ITEM; /* As of now only one item is filled */ item = &info->table[0]; item->info = 0; item->size = crash_len | BNXT_CRASH_INFO_VALID; item->addr_hi = 0; item->addr_lo = crash_area_start; /* Checksum calculation */ crc = CRC32(CRC32_INIT_VAL, (const char *)info + sizeof(uint32_t), sizeof(struct nitro_crash_addr_info) - sizeof(uint32_t)); info->crc = crc; /* First we write the contents and then set valid bit */ item->size &= ~BNXT_CRASH_INFO_VALID; size = sizeof(struct nitro_crash_addr_info) / sizeof(uint32_t); dst = info_dst; src = (uintptr_t)info; memcpy32_helper(src, dst, size, INC_SRC_ADDR); /* Set the valid bit */ item->size |= BNXT_CRASH_INFO_VALID; dst = info_dst + offsetof(struct nitro_crash_addr_info, table) + offsetof(struct nitro_crash_addr_item, size); bnxt_write32_multiple(dst, (uintptr_t)&item->size, 1, 1); free(info); return TEE_SUCCESS; } TEE_Result bnxt_load_fw(int chip_type) { uint32_t size = 0; uintptr_t dst = 0; uintptr_t src = 0; struct bnxt_images_info bnxt_src_image_info; vaddr_t sec_mem_dest = (vaddr_t)phys_to_virt(BNXT_BUFFER_SEC_MEM, MEM_AREA_RAM_SEC, 1); memset(&bnxt_src_image_info, 0, sizeof(struct bnxt_images_info)); if (get_bnxt_images_info(&bnxt_src_image_info, chip_type, sec_mem_dest) != BNXT_SUCCESS) return TEE_ERROR_ITEM_NOT_FOUND; bnxt_handshake_clear(); bnxt_kong_halt(); bnxt_chimp_halt(); /* Copy the configs */ src = (uintptr_t)bnxt_src_image_info.bnxt_cfg_vaddr; dst = (uintptr_t)BNXT_CONFIG_NS3_DEST; size = bnxt_src_image_info.bnxt_cfg_len; size = size / sizeof(uint32_t); memcpy32_helper(src, dst, size, INC_SRC_ADDR); /* Copy bspd config */ src = (uintptr_t)bnxt_src_image_info.bnxt_bspd_cfg_vaddr; size = bnxt_src_image_info.bnxt_bspd_cfg_len; dst = (uintptr_t)BNXT_CONFIG_NS3_BSPD_DEST; size = size / sizeof(uint32_t); memcpy32_helper(src, dst, size, INC_SRC_ADDR); /* Fill the bnxt crash dump info */ bnxt_crash_config((uintptr_t)BNXT_CRASH_DUMP_INFO_NS3_BASE, BNXT_CRASH_SEC_MEM, BNXT_CRASH_LEN); /* Load bnxt firmware and fastboot */ bnxt_load(bnxt_src_image_info.bnxt_fw_vaddr); return TEE_SUCCESS; } TEE_Result bnxt_copy_crash_dump(uint8_t *d, uint32_t offset, uint32_t len) { size_t crash_len = 0; void *s = NULL; if (ADD_OVERFLOW(offset, len, &crash_len) || crash_len > BNXT_CRASH_LEN) return TEE_ERROR_BAD_PARAMETERS; s = phys_to_virt(BNXT_CRASH_SEC_MEM + offset, MEM_AREA_RAM_SEC, len); cache_op_inner(DCACHE_AREA_INVALIDATE, s, len); memcpy(d, s, len); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/bnxt/bnxt_images.c000066400000000000000000000061511464416617300213770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #define BNXT_FW_NS3_IMAGE_SIG 0xFF12345A #define BNXT_NS3_CFG_IMAGE_SIG 0xCF54321A #define BNXT_BSPD_CFG_LEN 512 #define QSPI_BASE QSPI_MEM_BASE #define QSPI_BNXT_IMG (QSPI_BASE + 0x400000) #define QSPI_BSPD_ADDR (QSPI_BASE + 0x700000) #define BCM_NS3 1 static void set_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type, vaddr_t src, vaddr_t dst); static struct bnxt_img_header { uint32_t bnxt_fw_ns3_sig; uint32_t bnxt_fw_ns3_size; uint32_t bnxt_ns3_cfg_sig; uint32_t bnxt_ns3_cfg_size; } *img_header; static int verify_header(vaddr_t mem) { img_header = (struct bnxt_img_header *)mem; if (img_header->bnxt_fw_ns3_sig == BNXT_FW_NS3_IMAGE_SIG && img_header->bnxt_ns3_cfg_sig == BNXT_NS3_CFG_IMAGE_SIG) return BNXT_SUCCESS; return BNXT_FAILURE; } static void set_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type, vaddr_t src, vaddr_t dst) { uint32_t len = 0; struct bnxt_img_header *dst_header = NULL; uint32_t fw_image_offset = sizeof(struct bnxt_img_header); img_header = (struct bnxt_img_header *)src; if (dst) { dst_header = (struct bnxt_img_header *)dst; memcpy(dst_header, img_header, sizeof(*img_header)); dst += sizeof(*img_header); if (chip_type != BCM_NS3) { dst_header->bnxt_fw_ns3_size = 0; dst_header->bnxt_ns3_cfg_size = 0; } } if (chip_type == BCM_NS3) { len = img_header->bnxt_fw_ns3_size; bnxt_info->bnxt_fw_vaddr = src + fw_image_offset; bnxt_info->bnxt_fw_len = len; if (dst) { memcpy((void *)dst, (void *)(src + fw_image_offset), len); dst += len; } fw_image_offset += len; len = img_header->bnxt_ns3_cfg_size; bnxt_info->bnxt_cfg_vaddr = src + fw_image_offset; bnxt_info->bnxt_cfg_len = len; if (dst) { memcpy((void *)dst, (void *)(src + fw_image_offset), len); } } } int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type, vaddr_t ddr_dest) { vaddr_t flash_dev_vaddr = 0; bnxt_info->bnxt_bspd_cfg_len = BNXT_BSPD_CFG_LEN; /* First verify if images are on sec mem */ if (verify_header(ddr_dest + BNXT_IMG_SECMEM_OFFSET) == BNXT_SUCCESS) { DMSG("Images found on sec memory"); bnxt_info->bnxt_bspd_cfg_vaddr = ddr_dest; set_bnxt_images_info(bnxt_info, chip_type, ddr_dest + BNXT_IMG_SECMEM_OFFSET, 0); } else { flash_dev_vaddr = (vaddr_t) phys_to_virt(QSPI_BNXT_IMG, MEM_AREA_IO_NSEC, sizeof(struct bnxt_img_header)); if (verify_header(flash_dev_vaddr) != BNXT_SUCCESS) { EMSG("failed to load fw images"); return BNXT_FAILURE; } DMSG("Images loading from flash memory"); bnxt_info->bnxt_bspd_cfg_vaddr = (vaddr_t)phys_to_virt(QSPI_BSPD_ADDR, MEM_AREA_IO_NSEC, BNXT_BSPD_CFG_LEN); memcpy((void *)ddr_dest, (void *)bnxt_info->bnxt_bspd_cfg_vaddr, BNXT_BSPD_CFG_LEN); set_bnxt_images_info(bnxt_info, chip_type, flash_dev_vaddr, ddr_dest + BNXT_IMG_SECMEM_OFFSET); } return BNXT_SUCCESS; } optee_os-4.3.0/core/drivers/bnxt/sub.mk000066400000000000000000000000751464416617300200540ustar00rootroot00000000000000srcs-y += bnxt.c srcs-y += bnxt_fw.c srcs-y += bnxt_images.c optee_os-4.3.0/core/drivers/cbmem_console.c000066400000000000000000000101171464416617300207260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Google Limited */ #include #include #include #include #include #include #include #include #include #include #include #define CURSOR_MASK (BIT(28) - 1) #define OVERFLOW BIT(31) struct cbmem_console { uint32_t size; uint32_t cursor; uint8_t body[0]; }; struct cbmem_console_data { paddr_t base; struct cbmem_console *console; struct serial_chip chip; uint32_t size; }; /* * Structures describing coreboot's in-memory descriptor tables. See * https://github.com/coreboot/coreboot/blob/ea2a38be323173075db3b13729a4006ea1fef72d/src/commonlib/include/commonlib/coreboot_tables.h * for canonical implementation. */ struct cb_header { uint8_t signature[4]; uint32_t header_bytes; uint32_t header_checksum; uint32_t table_bytes; uint32_t table_checksum; uint32_t table_entries; }; #define CB_TAG_CBMEM_CONSOLE 0x17 struct cb_entry { uint32_t tag; uint32_t size; uint64_t value; }; static struct cbmem_console_data cbmem_console; static void cbmem_console_flush(struct serial_chip *chip __unused) { } static int cbmem_console_getchar(struct serial_chip *chip __unused) { return 0; } static bool cbmem_console_have_rx_data(struct serial_chip *chip __unused) { return false; } static void cbmem_console_putc(struct serial_chip *chip, int ch) { struct cbmem_console_data *pd = container_of(chip, struct cbmem_console_data, chip); struct cbmem_console *c = pd->console; if (!pd->size) return; if ((c->cursor & CURSOR_MASK) + 1 >= pd->size) { c->cursor &= ~CURSOR_MASK; c->cursor |= OVERFLOW; c->body[0] = (uint8_t)(ch & 0xFF); } else { c->body[c->cursor & CURSOR_MASK] = (uint8_t)(ch & 0xFF); c->cursor++; } } static const struct serial_ops cbmem_console_ops = { .flush = cbmem_console_flush, .getchar = cbmem_console_getchar, .have_rx_data = cbmem_console_have_rx_data, .putc = cbmem_console_putc, }; DECLARE_KEEP_PAGER(cbmem_console_ops); static paddr_t get_cbmem_console_from_coreboot_table(paddr_t table_addr, size_t table_size) { struct cb_header *header = NULL; void *ptr = NULL; uint32_t i = 0; struct cb_entry *entry = NULL; paddr_t cbmem_console_base = 0; void *base = NULL; base = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, table_addr, table_size); if (!base) return 0; header = (struct cb_header *)base; if (memcmp(header->signature, "LBIO", 4)) goto done; if (header->header_bytes + header->table_bytes > table_size) goto done; ptr = (uint8_t *)base + header->header_bytes; for (i = 0; i < header->table_entries; ++i) { entry = (struct cb_entry *)ptr; if ((uint8_t *)ptr >= (uint8_t *)base + table_size - sizeof(struct cb_entry)) { goto done; } switch (get_le32(&entry->tag)) { case CB_TAG_CBMEM_CONSOLE: cbmem_console_base = get_le64(&entry->value); goto done; default: /* We skip all but one tag type. */ break; } ptr = (uint8_t *)ptr + get_le32(&entry->size); } done: core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, base, table_size); return cbmem_console_base; } bool cbmem_console_init_from_dt(void *fdt) { int offset = 0; paddr_t cb_addr = 0; size_t cb_size = 0; paddr_t cbmem_console_base = 0; if (!fdt) return false; offset = fdt_path_offset(fdt, "/firmware/coreboot"); if (offset < 0) return false; cb_addr = fdt_reg_base_address(fdt, offset); cb_size = fdt_reg_size(fdt, offset); cbmem_console_base = get_cbmem_console_from_coreboot_table(cb_addr, cb_size); if (!cbmem_console_base) return false; cbmem_console.base = cbmem_console_base; cbmem_console.console = (struct cbmem_console *) core_mmu_add_mapping(MEM_AREA_RAM_NSEC, cbmem_console_base, sizeof(struct cbmem_console)); if (!cbmem_console.console) return false; /* * Copy the size now to prevent non-secure world from spoofing * it later. */ cbmem_console.size = cbmem_console.console->size; cbmem_console.chip.ops = &cbmem_console_ops; register_serial_console(&cbmem_console.chip); return true; } optee_os-4.3.0/core/drivers/cdns_uart.c000066400000000000000000000076601464416617300201140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Xilinx Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #define CDNS_UART_CONTROL 0 #define CDNS_UART_MODE 4 #define CDNS_UART_IEN 8 #define CDNS_UART_IRQ_STATUS 0x14 #define CDNS_UART_CHANNEL_STATUS 0x2c #define CDNS_UART_FIFO 0x30 #define CDNS_UART_SIZE 0x34 #define CDNS_UART_CONTROL_RXRES BIT(0) #define CDNS_UART_CONTROL_TXRES BIT(1) #define CDNS_UART_CONTROL_RXEN BIT(2) #define CDNS_UART_CONTROL_TXEN BIT(4) #define CDNS_UART_MODE_8BIT (0 << 1) #define CDNS_UART_MODE_PARITY_NONE (0x4 << 3) #define CDNS_UART_MODE_1STP (0 << 6) #define CDNS_UART_CHANNEL_STATUS_TFUL BIT(4) #define CDNS_UART_CHANNEL_STATUS_TEMPTY BIT(3) #define CDNS_UART_CHANNEL_STATUS_REMPTY BIT(1) #define CDNS_UART_IRQ_RXTRIG BIT(0) #define CDNS_UART_IRQ_RXTOUT BIT(8) static vaddr_t chip_to_base(struct serial_chip *chip) { struct cdns_uart_data *pd = container_of(chip, struct cdns_uart_data, chip); return io_pa_or_va(&pd->base, CDNS_UART_SIZE); } static void cdns_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + CDNS_UART_CHANNEL_STATUS) & CDNS_UART_CHANNEL_STATUS_TEMPTY)) ; } static bool cdns_uart_have_rx_data(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); return !(io_read32(base + CDNS_UART_CHANNEL_STATUS) & CDNS_UART_CHANNEL_STATUS_REMPTY); } static int cdns_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!cdns_uart_have_rx_data(chip)) ; return io_read32(base + CDNS_UART_FIFO) & 0xff; } static void cdns_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); /* Wait until there is space in the FIFO */ while (io_read32(base + CDNS_UART_CHANNEL_STATUS) & CDNS_UART_CHANNEL_STATUS_TFUL) ; /* Send the character */ io_write32(base + CDNS_UART_FIFO, ch); } static const struct serial_ops cdns_uart_ops = { .flush = cdns_uart_flush, .getchar = cdns_uart_getchar, .have_rx_data = cdns_uart_have_rx_data, .putc = cdns_uart_putc, }; DECLARE_KEEP_PAGER(cdns_uart_ops); /* * we rely on the bootloader having set up the HW correctly, we just enable * transmitter/receiver here, just in case. */ void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate) { pd->base.pa = base; pd->chip.ops = &cdns_uart_ops; if (!uart_clk || !baud_rate) return; /* Enable UART and RX/TX */ io_write32(base + CDNS_UART_CONTROL, CDNS_UART_CONTROL_RXEN | CDNS_UART_CONTROL_TXEN); cdns_uart_flush(&pd->chip); } optee_os-4.3.0/core/drivers/clk/000077500000000000000000000000001464416617300165265ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/clk/clk-stm32-core.c000066400000000000000000000331371464416617300213460ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include "clk-stm32-core.h" #define RCC_MP_ENCLRR_OFFSET 0x4 #define TIMEOUT_US_200MS U(200000) #define TIMEOUT_US_1S U(1000000) static struct clk_stm32_priv *stm32_clock_data; struct clk_stm32_priv *clk_stm32_get_priv(void) { return stm32_clock_data; } uintptr_t clk_stm32_get_rcc_base(void) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); return priv->base; } /* STM32 MUX API */ size_t stm32_mux_get_parent(uint32_t mux_id) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct mux_cfg *mux = &priv->muxes[mux_id]; uint32_t mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); return (io_read32(priv->base + mux->offset) & mask) >> mux->shift; } TEE_Result stm32_mux_set_parent(uint16_t mux_id, uint8_t sel) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct mux_cfg *mux = &priv->muxes[mux_id]; uint32_t mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); uintptr_t address = priv->base + mux->offset; io_clrsetbits32(address, mask, (sel << mux->shift) & mask); if (mux->ready != MUX_NO_RDY) return stm32_gate_wait_ready((uint16_t)mux->ready, true); return TEE_SUCCESS; } /* STM32 GATE API */ static void stm32_gate_endisable(uint16_t gate_id, bool enable) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct gate_cfg *gate = &priv->gates[gate_id]; uintptr_t addr = priv->base + gate->offset; if (enable) { if (gate->set_clr) io_write32(addr, BIT(gate->bit_idx)); else io_setbits32_stm32shregs(addr, BIT(gate->bit_idx)); } else { if (gate->set_clr) io_write32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); else io_clrbits32_stm32shregs(addr, BIT(gate->bit_idx)); } } void stm32_gate_disable(uint16_t gate_id) { stm32_gate_endisable(gate_id, false); } void stm32_gate_enable(uint16_t gate_id) { stm32_gate_endisable(gate_id, true); } bool stm32_gate_is_enabled(uint16_t gate_id) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct gate_cfg *gate = &priv->gates[gate_id]; uintptr_t addr = priv->base + gate->offset; return (io_read32(addr) & BIT(gate->bit_idx)) != 0U; } TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct gate_cfg *gate = &priv->gates[gate_id]; uintptr_t address = priv->base + gate->offset; uint32_t mask_rdy = BIT(gate->bit_idx); uint64_t timeout = timeout_init_us(TIMEOUT_US_1S); uint32_t mask = 0U; if (ready_on) mask = BIT(gate->bit_idx); while ((io_read32(address) & mask_rdy) != mask) if (timeout_elapsed(timeout)) break; if ((io_read32(address) & mask_rdy) != mask) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } /* STM32 GATE READY clock operators */ static TEE_Result stm32_gate_ready_endisable(uint16_t gate_id, bool enable, bool wait_rdy) { stm32_gate_endisable(gate_id, enable); if (wait_rdy) return stm32_gate_wait_ready(gate_id + 1, enable); return TEE_SUCCESS; } TEE_Result stm32_gate_rdy_enable(uint16_t gate_id) { return stm32_gate_ready_endisable(gate_id, true, true); } TEE_Result stm32_gate_rdy_disable(uint16_t gate_id) { return stm32_gate_ready_endisable(gate_id, false, true); } /* STM32 DIV API */ static unsigned int _get_table_div(const struct div_table_cfg *table, unsigned int val) { const struct div_table_cfg *clkt = NULL; for (clkt = table; clkt->div; clkt++) if (clkt->val == val) return clkt->div; return 0; } static unsigned int _get_table_val(const struct div_table_cfg *table, unsigned int div) { const struct div_table_cfg *clkt = NULL; for (clkt = table; clkt->div; clkt++) if (clkt->div == div) return clkt->val; return 0; } static unsigned int _get_div(const struct div_table_cfg *table, unsigned int val, unsigned long flags, uint8_t width) { if (flags & CLK_DIVIDER_ONE_BASED) return val; if (flags & CLK_DIVIDER_POWER_OF_TWO) return BIT(val); if (flags & CLK_DIVIDER_MAX_AT_ZERO) return (val != 0U) ? val : BIT(width); if (table) return _get_table_div(table, val); return val + 1U; } static unsigned int _get_val(const struct div_table_cfg *table, unsigned int div, unsigned long flags, uint8_t width) { if (flags & CLK_DIVIDER_ONE_BASED) return div; if (flags & CLK_DIVIDER_POWER_OF_TWO) return __builtin_ffs(div) - 1; if (flags & CLK_DIVIDER_MAX_AT_ZERO) return (div != 0U) ? div : BIT(width); if (table) return _get_table_val(table, div); return div - 1U; } static bool _is_valid_table_div(const struct div_table_cfg *table, unsigned int div) { const struct div_table_cfg *clkt = NULL; for (clkt = table; clkt->div; clkt++) if (clkt->div == div) return true; return false; } static bool _is_valid_div(const struct div_table_cfg *table, unsigned int div, unsigned long flags) { if (flags & CLK_DIVIDER_POWER_OF_TWO) return IS_POWER_OF_TWO(div); if (table) return _is_valid_table_div(table, div); return true; } static int divider_get_val(unsigned long rate, unsigned long parent_rate, const struct div_table_cfg *table, uint8_t width, unsigned long flags) { unsigned int div = 0U; unsigned int value = 0U; div = UDIV_ROUND_NEAREST((uint64_t)parent_rate, rate); if (!_is_valid_div(table, div, flags)) return -1; value = _get_val(table, div, flags, width); return MIN(value, MASK_WIDTH_SHIFT(width, 0)); } uint32_t stm32_div_get_value(int div_id) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct div_cfg *divider = &priv->div[div_id]; uint32_t val = 0; val = io_read32(priv->base + divider->offset) >> divider->shift; val &= MASK_WIDTH_SHIFT(divider->width, 0); return val; } TEE_Result stm32_div_set_value(uint32_t div_id, uint32_t value) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct div_cfg *divider = NULL; uintptr_t address = 0; uint32_t mask = 0; if (div_id >= priv->nb_div) panic(); divider = &priv->div[div_id]; address = priv->base + divider->offset; mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); io_clrsetbits32(address, mask, (value << divider->shift) & mask); if (divider->ready == DIV_NO_RDY) return TEE_SUCCESS; return stm32_gate_wait_ready((uint16_t)divider->ready, true); } static unsigned long stm32_div_get_rate(int div_id, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct div_cfg *divider = &priv->div[div_id]; uint32_t val = stm32_div_get_value(div_id); unsigned int div = 0U; div = _get_div(divider->table, val, divider->flags, divider->width); if (!div) return prate; return ROUNDUP_DIV((uint64_t)prate, div); } TEE_Result stm32_div_set_rate(int div_id, unsigned long rate, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); const struct div_cfg *divider = &priv->div[div_id]; int value = 0; value = divider_get_val(rate, prate, divider->table, divider->width, divider->flags); if (value < 0) return TEE_ERROR_GENERIC; return stm32_div_set_value(div_id, value); } /* STM32 MUX clock operators */ static size_t clk_stm32_mux_get_parent(struct clk *clk) { struct clk_stm32_mux_cfg *cfg = clk->priv; return stm32_mux_get_parent(cfg->mux_id); } static TEE_Result clk_stm32_mux_set_parent(struct clk *clk, size_t pidx) { struct clk_stm32_mux_cfg *cfg = clk->priv; return stm32_mux_set_parent(cfg->mux_id, pidx); } const struct clk_ops clk_stm32_mux_ops = { .get_parent = clk_stm32_mux_get_parent, .set_parent = clk_stm32_mux_set_parent, }; /* STM32 GATE clock operators */ static TEE_Result clk_stm32_gate_enable(struct clk *clk) { struct clk_stm32_gate_cfg *cfg = clk->priv; stm32_gate_enable(cfg->gate_id); return TEE_SUCCESS; } static void clk_stm32_gate_disable(struct clk *clk) { struct clk_stm32_gate_cfg *cfg = clk->priv; stm32_gate_disable(cfg->gate_id); } const struct clk_ops clk_stm32_gate_ops = { .enable = clk_stm32_gate_enable, .disable = clk_stm32_gate_disable, }; static TEE_Result clk_stm32_gate_ready_enable(struct clk *clk) { struct clk_stm32_gate_cfg *cfg = clk->priv; return stm32_gate_rdy_enable(cfg->gate_id); } static void clk_stm32_gate_ready_disable(struct clk *clk) { struct clk_stm32_gate_cfg *cfg = clk->priv; if (stm32_gate_rdy_disable(cfg->gate_id)) panic(); } const struct clk_ops clk_stm32_gate_ready_ops = { .enable = clk_stm32_gate_ready_enable, .disable = clk_stm32_gate_ready_disable, }; /* STM32 DIV clock operators */ unsigned long clk_stm32_divider_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_stm32_div_cfg *cfg = clk->priv; return stm32_div_get_rate(cfg->div_id, parent_rate); } TEE_Result clk_stm32_divider_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_stm32_div_cfg *cfg = clk->priv; return stm32_div_set_rate(cfg->div_id, rate, parent_rate); } const struct clk_ops clk_stm32_divider_ops = { .get_rate = clk_stm32_divider_get_rate, .set_rate = clk_stm32_divider_set_rate, }; /* STM32 COMPOSITE clock operators */ size_t clk_stm32_composite_get_parent(struct clk *clk) { struct clk_stm32_composite_cfg *cfg = clk->priv; if (cfg->mux_id == NO_MUX) { /* It could be a normal case */ return 0; } return stm32_mux_get_parent(cfg->mux_id); } TEE_Result clk_stm32_composite_set_parent(struct clk *clk, size_t pidx) { struct clk_stm32_composite_cfg *cfg = clk->priv; if (cfg->mux_id == NO_MUX) panic(); return stm32_mux_set_parent(cfg->mux_id, pidx); } unsigned long clk_stm32_composite_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_stm32_composite_cfg *cfg = clk->priv; if (cfg->div_id == NO_DIV) return parent_rate; return stm32_div_get_rate(cfg->div_id, parent_rate); } TEE_Result clk_stm32_composite_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_stm32_composite_cfg *cfg = clk->priv; if (cfg->div_id == NO_DIV) return TEE_SUCCESS; return stm32_div_set_rate(cfg->div_id, rate, parent_rate); } TEE_Result clk_stm32_composite_gate_enable(struct clk *clk) { struct clk_stm32_composite_cfg *cfg = clk->priv; stm32_gate_enable(cfg->gate_id); return TEE_SUCCESS; } void clk_stm32_composite_gate_disable(struct clk *clk) { struct clk_stm32_composite_cfg *cfg = clk->priv; stm32_gate_disable(cfg->gate_id); } const struct clk_ops clk_stm32_composite_ops = { .get_parent = clk_stm32_composite_get_parent, .set_parent = clk_stm32_composite_set_parent, .get_rate = clk_stm32_composite_get_rate, .set_rate = clk_stm32_composite_set_rate, .enable = clk_stm32_composite_gate_enable, .disable = clk_stm32_composite_gate_disable, }; TEE_Result clk_stm32_set_parent_by_index(struct clk *clk, size_t pidx) { struct clk *parent = clk_get_parent_by_index(clk, pidx); TEE_Result res = TEE_ERROR_GENERIC; if (parent) res = clk_set_parent(clk, parent); return res; } int clk_stm32_parse_fdt_by_name(const void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb) { const fdt32_t *cell = NULL; int len = 0; uint32_t i = 0; cell = fdt_getprop(fdt, node, name, &len); if (cell) for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) tab[i] = fdt32_to_cpu(cell[i]); *nb = (uint32_t)len / sizeof(uint32_t); return 0; } TEE_Result clk_stm32_init(struct clk_stm32_priv *priv, uintptr_t base) { stm32_clock_data = priv; priv->base = base; return TEE_SUCCESS; } static unsigned long fixed_factor_get_rate(struct clk *clk, unsigned long parent_rate) { struct fixed_factor_cfg *d = clk->priv; unsigned long long rate = (unsigned long long)parent_rate * d->mult; if (d->div == 0U) panic("error division by zero"); return (unsigned long)(rate / d->div); }; const struct clk_ops clk_fixed_factor_ops = { .get_rate = fixed_factor_get_rate, }; static unsigned long clk_fixed_get_rate(struct clk *clk, unsigned long parent_rate __unused) { struct clk_fixed_rate_cfg *cfg = clk->priv; return cfg->rate; } const struct clk_ops clk_fixed_clk_ops = { .get_rate = clk_fixed_get_rate, }; struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); if (clock_id > priv->nb_clk_refs) return NULL; return priv->clk_refs[clock_id]; } static TEE_Result stm32mp_clk_dt_get_clk(struct dt_pargs *pargs, void *data __unused, struct clk **out_clk) { unsigned long clock_id = pargs->args[0]; struct clk *clk = NULL; if (pargs->args_count != 1) return TEE_ERROR_BAD_PARAMETERS; clk = stm32mp_rcc_clock_id_to_clk(clock_id); if (!clk) return TEE_ERROR_BAD_PARAMETERS; *out_clk = clk; return TEE_SUCCESS; } static void clk_stm32_register_clocks(struct clk_stm32_priv *priv) { unsigned int i = 0; for (i = 0; i < priv->nb_clk_refs; i++) { struct clk *clk = priv->clk_refs[i]; if (!clk) continue; refcount_set(&clk->enabled_count, 0); if (clk_register(clk)) panic(); } /* Critical clocks management */ for (i = 0; i < priv->nb_clk_refs; i++) { struct clk *clk = priv->clk_refs[i]; if (!clk) continue; if (priv->is_critical && priv->is_critical(clk)) clk_enable(clk); } } void stm32mp_clk_provider_probe_final(const void *fdt, int node, struct clk_stm32_priv *priv) { TEE_Result res = TEE_ERROR_GENERIC; clk_stm32_register_clocks(priv); res = clk_dt_register_clk_provider(fdt, node, stm32mp_clk_dt_get_clk, priv); if (res) panic("Couldn't register clock provider"); } optee_os-4.3.0/core/drivers/clk/clk-stm32-core.h000066400000000000000000000141121464416617300213430ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved */ #ifndef CLK_STM32_CORE_H #define CLK_STM32_CORE_H #include struct mux_cfg { uint16_t offset; uint8_t shift; uint8_t width; uint8_t ready; }; struct gate_cfg { uint16_t offset; uint8_t bit_idx; uint8_t set_clr; }; struct div_table_cfg { unsigned int val; unsigned int div; }; struct div_cfg { uint16_t offset; uint8_t shift; uint8_t width; uint8_t flags; uint8_t ready; const struct div_table_cfg *table; }; struct clk_stm32_priv { uintptr_t base; size_t nb_clk_refs; struct clk **clk_refs; const struct mux_cfg *muxes; const uint32_t nb_muxes; const struct gate_cfg *gates; const uint32_t nb_gates; const struct div_cfg *div; const uint32_t nb_div; bool (*is_critical)(struct clk *clk); void *pdata; }; struct clk_fixed_rate_cfg { unsigned long rate; }; struct fixed_factor_cfg { unsigned int mult; unsigned int div; }; struct clk_gate_cfg { uint32_t offset; uint8_t bit_idx; }; struct clk_stm32_mux_cfg { int mux_id; }; struct clk_stm32_gate_cfg { int gate_id; }; struct clk_stm32_div_cfg { int div_id; }; struct clk_stm32_composite_cfg { int gate_id; int div_id; int mux_id; }; struct clk_stm32_timer_cfg { uint32_t apbdiv; uint32_t timpre; }; struct clk_stm32_gate_ready_cfg { int gate_id; int gate_rdy_id; }; /* Define for divider clocks */ #define CLK_DIVIDER_ONE_BASED BIT(0) #define CLK_DIVIDER_POWER_OF_TWO BIT(1) #define CLK_DIVIDER_ALLOW_ZERO BIT(2) #define CLK_DIVIDER_HIWORD_MASK BIT(3) #define CLK_DIVIDER_ROUND_CLOSEST BIT(4) #define CLK_DIVIDER_READ_ONLY BIT(5) #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) #define CLK_DIVIDER_BIG_ENDIAN BIT(7) #define DIV_NO_RDY UINT8_MAX #define MUX_NO_RDY UINT8_MAX #define MASK_WIDTH_SHIFT(_width, _shift) \ GENMASK_32(((_width) + (_shift) - 1U), (_shift)) /* Define for composite clocks */ #define NO_MUX INT32_MAX #define NO_DIV INT32_MAX #define NO_GATE INT32_MAX void stm32_gate_enable(uint16_t gate_id); void stm32_gate_disable(uint16_t gate_id); bool stm32_gate_is_enabled(uint16_t gate_id); TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on); TEE_Result stm32_gate_rdy_enable(uint16_t gate_id); TEE_Result stm32_gate_rdy_disable(uint16_t gate_id); size_t stm32_mux_get_parent(uint32_t mux_id); TEE_Result stm32_mux_set_parent(uint16_t pid, uint8_t sel); TEE_Result stm32_div_set_rate(int div_id, unsigned long rate, unsigned long prate); uint32_t stm32_div_get_value(int div_id); TEE_Result stm32_div_set_value(uint32_t div_id, uint32_t value); int clk_stm32_parse_fdt_by_name(const void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb); unsigned long clk_stm32_divider_get_rate(struct clk *clk, unsigned long parent_rate); TEE_Result clk_stm32_divider_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate); size_t clk_stm32_composite_get_parent(struct clk *clk); TEE_Result clk_stm32_composite_set_parent(struct clk *clk, size_t pidx); unsigned long clk_stm32_composite_get_rate(struct clk *clk, unsigned long parent_rate); TEE_Result clk_stm32_composite_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate); TEE_Result clk_stm32_composite_gate_enable(struct clk *clk); void clk_stm32_composite_gate_disable(struct clk *clk); TEE_Result clk_stm32_set_parent_by_index(struct clk *clk, size_t pidx); extern const struct clk_ops clk_fixed_factor_ops; extern const struct clk_ops clk_fixed_clk_ops; extern const struct clk_ops clk_stm32_gate_ops; extern const struct clk_ops clk_stm32_gate_ready_ops; extern const struct clk_ops clk_stm32_divider_ops; extern const struct clk_ops clk_stm32_mux_ops; extern const struct clk_ops clk_stm32_composite_ops; #define PARENT(x...) { x } #define STM32_FIXED_RATE(_name, _rate)\ struct clk _name = {\ .ops = &clk_fixed_clk_ops,\ .priv = &(struct clk_fixed_rate_cfg) {\ .rate = (_rate),\ },\ .name = #_name,\ .flags = 0,\ .num_parents = 0,\ } #define STM32_FIXED_FACTOR(_name, _parent, _flags, _mult, _div)\ struct clk _name = {\ .ops = &clk_fixed_factor_ops,\ .priv = &(struct fixed_factor_cfg) {\ .mult = _mult,\ .div = _div,\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { (_parent) },\ } #define STM32_GATE(_name, _parent, _flags, _gate_id)\ struct clk _name = {\ .ops = &clk_stm32_gate_ops,\ .priv = &(struct clk_stm32_gate_cfg) {\ .gate_id = _gate_id,\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { (_parent) },\ } #define STM32_DIVIDER(_name, _parent, _flags, _div_id)\ struct clk _name = {\ .ops = &clk_stm32_divider_ops,\ .priv = &(struct clk_stm32_div_cfg) {\ .div_id = (_div_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { (_parent) },\ } #define STM32_MUX(_name, _nb_parents, _parents, _flags, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_mux_ops,\ .priv = &(struct clk_stm32_mux_cfg) {\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = (_nb_parents),\ .parents = _parents,\ } #define STM32_GATE_READY(_name, _parent, _flags, _gate_id)\ struct clk _name = {\ .ops = &clk_stm32_gate_ready_ops,\ .priv = &(struct clk_stm32_gate_cfg) {\ .gate_id = _gate_id,\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { _parent },\ } #define STM32_COMPOSITE(_name, _nb_parents, _parents, _flags,\ _gate_id, _div_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_composite_ops,\ .priv = &(struct clk_stm32_composite_cfg) {\ .gate_id = (_gate_id),\ .div_id = (_div_id),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = (_nb_parents),\ .parents = _parents,\ } struct clk_stm32_priv *clk_stm32_get_priv(void); uintptr_t clk_stm32_get_rcc_base(void); TEE_Result clk_stm32_init(struct clk_stm32_priv *priv, uintptr_t base); void stm32mp_clk_provider_probe_final(const void *fdt, int node, struct clk_stm32_priv *priv); #endif /* CLK_STM32_CORE_H */ optee_os-4.3.0/core/drivers/clk/clk-stm32mp13.c000066400000000000000000002177161464416617300211300ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include "clk-stm32-core.h" #define MAX_HSI_HZ 64000000 #define USB_PHY_48_MHZ 48000000 #define TIMEOUT_US_200MS U(200000) #define HSIDIV_TIMEOUT TIMEOUT_US_200MS #define MAX_OPP CFG_STM32MP_OPP_COUNT #define RCC_PLL_NAME_SIZE 12 struct stm32_osci_dt_cfg { unsigned long freq; bool bypass; bool digbyp; bool css; uint32_t drive; }; enum pll_mn { PLL_CFG_M, PLL_CFG_N, PLL_DIV_MN_NB }; enum pll_pqr { PLL_CFG_P, PLL_CFG_Q, PLL_CFG_R, PLL_DIV_PQR_NB }; enum pll_csg { PLL_CSG_MOD_PER, PLL_CSG_INC_STEP, PLL_CSG_SSCG_MODE, PLL_CSG_NB }; struct stm32_pll_vco { uint32_t status; uint32_t src; uint32_t div_mn[PLL_DIV_MN_NB]; uint32_t frac; bool csg_enabled; uint32_t csg[PLL_CSG_NB]; }; struct stm32_pll_output { uint32_t output[PLL_DIV_PQR_NB]; }; struct stm32_pll_dt_cfg { struct stm32_pll_vco vco; struct stm32_pll_output output; }; struct stm32_clk_opp_cfg { uint32_t frq; uint32_t src; uint32_t div; struct stm32_pll_dt_cfg pll_cfg; }; struct stm32_clk_opp_dt_cfg { struct stm32_clk_opp_cfg mpu_opp[MAX_OPP]; struct stm32_clk_opp_cfg axi_opp[MAX_OPP]; struct stm32_clk_opp_cfg mlahbs_opp[MAX_OPP]; }; struct stm32_clk_platdata { uintptr_t rcc_base; uint32_t nosci; struct stm32_osci_dt_cfg *osci; uint32_t npll; struct stm32_pll_dt_cfg *pll; struct stm32_clk_opp_dt_cfg *opp; uint32_t nclksrc; uint32_t *clksrc; uint32_t nclkdiv; uint32_t *clkdiv; }; /* * GATE CONFIG */ /* Warning GATE_XXX_RDY must follow GATE_XXX */ enum enum_gate_cfg { GATE_LSE, GATE_LSE_RDY, GATE_LSI, GATE_LSI_RDY, GATE_HSI, GATE_HSI_RDY, GATE_CSI, GATE_CSI_RDY, GATE_HSE, GATE_HSE_RDY, GATE_PLL1, GATE_PLL1_RDY, GATE_PLL2, GATE_PLL2_RDY, GATE_PLL3, GATE_PLL3_RDY, GATE_PLL4, GATE_PLL4_RDY, GATE_HSIDIVRDY, GATE_MPUSRCRDY, GATE_AXISSRCRDY, GATE_MCUSSRCRDY, GATE_PLL12SRCRDY, GATE_PLL3SRCRDY, GATE_PLL4SRCRDY, GATE_MPUDIVRDY, GATE_AXIDIVRDY, GATE_MLAHBDIVRDY, GATE_APB1DIVRDY, GATE_APB2DIVRDY, GATE_APB3DIVRDY, GATE_APB4DIVRDY, GATE_APB5DIVRDY, GATE_APB6DIVRDY, GATE_RTCCK, GATE_MCO1, GATE_MCO2, GATE_DBGCK, GATE_TRACECK, GATE_PLL1_DIVP, GATE_PLL1_DIVQ, GATE_PLL1_DIVR, GATE_PLL2_DIVP, GATE_PLL2_DIVQ, GATE_PLL2_DIVR, GATE_PLL3_DIVP, GATE_PLL3_DIVQ, GATE_PLL3_DIVR, GATE_PLL4_DIVP, GATE_PLL4_DIVQ, GATE_PLL4_DIVR, GATE_DDRC1, GATE_DDRC1LP, GATE_DDRPHYC, GATE_DDRPHYCLP, GATE_DDRCAPB, GATE_DDRCAPBLP, GATE_AXIDCG, GATE_DDRPHYCAPB, GATE_DDRPHYCAPBLP, GATE_TIM2, GATE_TIM3, GATE_TIM4, GATE_TIM5, GATE_TIM6, GATE_TIM7, GATE_LPTIM1, GATE_SPI2, GATE_SPI3, GATE_USART3, GATE_UART4, GATE_UART5, GATE_UART7, GATE_UART8, GATE_I2C1, GATE_I2C2, GATE_SPDIF, GATE_TIM1, GATE_TIM8, GATE_SPI1, GATE_USART6, GATE_SAI1, GATE_SAI2, GATE_DFSDM, GATE_ADFSDM, GATE_FDCAN, GATE_LPTIM2, GATE_LPTIM3, GATE_LPTIM4, GATE_LPTIM5, GATE_VREF, GATE_DTS, GATE_PMBCTRL, GATE_HDP, GATE_SYSCFG, GATE_DCMIPP, GATE_DDRPERFM, GATE_IWDG2APB, GATE_USBPHY, GATE_STGENRO, GATE_LTDC, GATE_RTCAPB, GATE_TZC, GATE_ETZPC, GATE_IWDG1APB, GATE_BSEC, GATE_STGENC, GATE_USART1, GATE_USART2, GATE_SPI4, GATE_SPI5, GATE_I2C3, GATE_I2C4, GATE_I2C5, GATE_TIM12, GATE_TIM13, GATE_TIM14, GATE_TIM15, GATE_TIM16, GATE_TIM17, GATE_DMA1, GATE_DMA2, GATE_DMAMUX1, GATE_DMA3, GATE_DMAMUX2, GATE_ADC1, GATE_ADC2, GATE_USBO, GATE_TSC, GATE_GPIOA, GATE_GPIOB, GATE_GPIOC, GATE_GPIOD, GATE_GPIOE, GATE_GPIOF, GATE_GPIOG, GATE_GPIOH, GATE_GPIOI, GATE_PKA, GATE_SAES, GATE_CRYP1, GATE_HASH1, GATE_RNG1, GATE_BKPSRAM, GATE_AXIMC, GATE_MCE, GATE_ETH1CK, GATE_ETH1TX, GATE_ETH1RX, GATE_ETH1MAC, GATE_FMC, GATE_QSPI, GATE_SDMMC1, GATE_SDMMC2, GATE_CRC1, GATE_USBH, GATE_ETH2CK, GATE_ETH2TX, GATE_ETH2RX, GATE_ETH2MAC, GATE_MDMA, GATE_NB }; #define GATE_CFG(_id, _offset, _bit_idx, _offset_clr)\ [(_id)] = {\ .offset = (_offset),\ .bit_idx = (_bit_idx),\ .set_clr = (_offset_clr),\ } static const struct gate_cfg gates_mp13[GATE_NB] = { GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0), GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0), GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0), GATE_CFG(GATE_LSI, RCC_RDLSICR, 0, 0), GATE_CFG(GATE_LSI_RDY, RCC_RDLSICR, 1, 0), GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1), GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0), GATE_CFG(GATE_CSI, RCC_OCENSETR, 4, 1), GATE_CFG(GATE_CSI_RDY, RCC_OCRDYR, 4, 0), GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1), GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0), GATE_CFG(GATE_HSIDIVRDY, RCC_OCRDYR, 2, 0), GATE_CFG(GATE_MPUSRCRDY, RCC_MPCKSELR, 31, 0), GATE_CFG(GATE_AXISSRCRDY, RCC_ASSCKSELR, 31, 0), GATE_CFG(GATE_MCUSSRCRDY, RCC_MSSCKSELR, 31, 0), GATE_CFG(GATE_PLL12SRCRDY, RCC_RCK12SELR, 31, 0), GATE_CFG(GATE_PLL3SRCRDY, RCC_RCK3SELR, 31, 0), GATE_CFG(GATE_PLL4SRCRDY, RCC_RCK4SELR, 31, 0), GATE_CFG(GATE_MPUDIVRDY, RCC_MPCKDIVR, 31, 0), GATE_CFG(GATE_AXIDIVRDY, RCC_AXIDIVR, 31, 0), GATE_CFG(GATE_MLAHBDIVRDY, RCC_MLAHBDIVR, 31, 0), GATE_CFG(GATE_APB1DIVRDY, RCC_APB1DIVR, 31, 0), GATE_CFG(GATE_APB2DIVRDY, RCC_APB2DIVR, 31, 0), GATE_CFG(GATE_APB3DIVRDY, RCC_APB3DIVR, 31, 0), GATE_CFG(GATE_APB4DIVRDY, RCC_APB4DIVR, 31, 0), GATE_CFG(GATE_APB5DIVRDY, RCC_APB5DIVR, 31, 0), GATE_CFG(GATE_APB6DIVRDY, RCC_APB6DIVR, 31, 0), GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 12, 0), GATE_CFG(GATE_DBGCK, RCC_DBGCFGR, 8, 0), GATE_CFG(GATE_TRACECK, RCC_DBGCFGR, 9, 0), GATE_CFG(GATE_PLL1, RCC_PLL1CR, 0, 0), GATE_CFG(GATE_PLL1_RDY, RCC_PLL1CR, 1, 0), GATE_CFG(GATE_PLL1_DIVP, RCC_PLL1CR, 4, 0), GATE_CFG(GATE_PLL1_DIVQ, RCC_PLL1CR, 5, 0), GATE_CFG(GATE_PLL1_DIVR, RCC_PLL1CR, 6, 0), GATE_CFG(GATE_PLL2, RCC_PLL2CR, 0, 0), GATE_CFG(GATE_PLL2_RDY, RCC_PLL2CR, 1, 0), GATE_CFG(GATE_PLL2_DIVP, RCC_PLL2CR, 4, 0), GATE_CFG(GATE_PLL2_DIVQ, RCC_PLL2CR, 5, 0), GATE_CFG(GATE_PLL2_DIVR, RCC_PLL2CR, 6, 0), GATE_CFG(GATE_PLL3, RCC_PLL3CR, 0, 0), GATE_CFG(GATE_PLL3_RDY, RCC_PLL3CR, 1, 0), GATE_CFG(GATE_PLL3_DIVP, RCC_PLL3CR, 4, 0), GATE_CFG(GATE_PLL3_DIVQ, RCC_PLL3CR, 5, 0), GATE_CFG(GATE_PLL3_DIVR, RCC_PLL3CR, 6, 0), GATE_CFG(GATE_PLL4, RCC_PLL4CR, 0, 0), GATE_CFG(GATE_PLL4_RDY, RCC_PLL4CR, 1, 0), GATE_CFG(GATE_PLL4_DIVP, RCC_PLL4CR, 4, 0), GATE_CFG(GATE_PLL4_DIVQ, RCC_PLL4CR, 5, 0), GATE_CFG(GATE_PLL4_DIVR, RCC_PLL4CR, 6, 0), GATE_CFG(GATE_DDRC1, RCC_DDRITFCR, 0, 0), GATE_CFG(GATE_DDRC1LP, RCC_DDRITFCR, 1, 0), GATE_CFG(GATE_DDRPHYC, RCC_DDRITFCR, 4, 0), GATE_CFG(GATE_DDRPHYCLP, RCC_DDRITFCR, 5, 0), GATE_CFG(GATE_DDRCAPB, RCC_DDRITFCR, 6, 0), GATE_CFG(GATE_DDRCAPBLP, RCC_DDRITFCR, 7, 0), GATE_CFG(GATE_AXIDCG, RCC_DDRITFCR, 8, 0), GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9, 0), GATE_CFG(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10, 0), GATE_CFG(GATE_TIM2, RCC_MP_APB1ENSETR, 0, 1), GATE_CFG(GATE_TIM3, RCC_MP_APB1ENSETR, 1, 1), GATE_CFG(GATE_TIM4, RCC_MP_APB1ENSETR, 2, 1), GATE_CFG(GATE_TIM5, RCC_MP_APB1ENSETR, 3, 1), GATE_CFG(GATE_TIM6, RCC_MP_APB1ENSETR, 4, 1), GATE_CFG(GATE_TIM7, RCC_MP_APB1ENSETR, 5, 1), GATE_CFG(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9, 1), GATE_CFG(GATE_SPI2, RCC_MP_APB1ENSETR, 11, 1), GATE_CFG(GATE_SPI3, RCC_MP_APB1ENSETR, 12, 1), GATE_CFG(GATE_USART3, RCC_MP_APB1ENSETR, 15, 1), GATE_CFG(GATE_UART4, RCC_MP_APB1ENSETR, 16, 1), GATE_CFG(GATE_UART5, RCC_MP_APB1ENSETR, 17, 1), GATE_CFG(GATE_UART7, RCC_MP_APB1ENSETR, 18, 1), GATE_CFG(GATE_UART8, RCC_MP_APB1ENSETR, 19, 1), GATE_CFG(GATE_I2C1, RCC_MP_APB1ENSETR, 21, 1), GATE_CFG(GATE_I2C2, RCC_MP_APB1ENSETR, 22, 1), GATE_CFG(GATE_SPDIF, RCC_MP_APB1ENSETR, 26, 1), GATE_CFG(GATE_TIM1, RCC_MP_APB2ENSETR, 0, 1), GATE_CFG(GATE_TIM8, RCC_MP_APB2ENSETR, 1, 1), GATE_CFG(GATE_SPI1, RCC_MP_APB2ENSETR, 8, 1), GATE_CFG(GATE_USART6, RCC_MP_APB2ENSETR, 13, 1), GATE_CFG(GATE_SAI1, RCC_MP_APB2ENSETR, 16, 1), GATE_CFG(GATE_SAI2, RCC_MP_APB2ENSETR, 17, 1), GATE_CFG(GATE_DFSDM, RCC_MP_APB2ENSETR, 20, 1), GATE_CFG(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21, 1), GATE_CFG(GATE_FDCAN, RCC_MP_APB2ENSETR, 24, 1), GATE_CFG(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0, 1), GATE_CFG(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1, 1), GATE_CFG(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2, 1), GATE_CFG(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3, 1), GATE_CFG(GATE_VREF, RCC_MP_APB3ENSETR, 13, 1), GATE_CFG(GATE_DTS, RCC_MP_APB3ENSETR, 16, 1), GATE_CFG(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17, 1), GATE_CFG(GATE_HDP, RCC_MP_APB3ENSETR, 20, 1), GATE_CFG(GATE_SYSCFG, RCC_MP_S_APB3ENSETR, 0, 1), GATE_CFG(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1, 1), GATE_CFG(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8, 1), GATE_CFG(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15, 1), GATE_CFG(GATE_USBPHY, RCC_MP_APB4ENSETR, 16, 1), GATE_CFG(GATE_STGENRO, RCC_MP_APB4ENSETR, 20, 1), GATE_CFG(GATE_LTDC, RCC_MP_S_APB4ENSETR, 0, 1), GATE_CFG(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8, 1), GATE_CFG(GATE_TZC, RCC_MP_APB5ENSETR, 11, 1), GATE_CFG(GATE_ETZPC, RCC_MP_APB5ENSETR, 13, 1), GATE_CFG(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15, 1), GATE_CFG(GATE_BSEC, RCC_MP_APB5ENSETR, 16, 1), GATE_CFG(GATE_STGENC, RCC_MP_APB5ENSETR, 20, 1), GATE_CFG(GATE_USART1, RCC_MP_APB6ENSETR, 0, 1), GATE_CFG(GATE_USART2, RCC_MP_APB6ENSETR, 1, 1), GATE_CFG(GATE_SPI4, RCC_MP_APB6ENSETR, 2, 1), GATE_CFG(GATE_SPI5, RCC_MP_APB6ENSETR, 3, 1), GATE_CFG(GATE_I2C3, RCC_MP_APB6ENSETR, 4, 1), GATE_CFG(GATE_I2C4, RCC_MP_APB6ENSETR, 5, 1), GATE_CFG(GATE_I2C5, RCC_MP_APB6ENSETR, 6, 1), GATE_CFG(GATE_TIM12, RCC_MP_APB6ENSETR, 7, 1), GATE_CFG(GATE_TIM13, RCC_MP_APB6ENSETR, 8, 1), GATE_CFG(GATE_TIM14, RCC_MP_APB6ENSETR, 9, 1), GATE_CFG(GATE_TIM15, RCC_MP_APB6ENSETR, 10, 1), GATE_CFG(GATE_TIM16, RCC_MP_APB6ENSETR, 11, 1), GATE_CFG(GATE_TIM17, RCC_MP_APB6ENSETR, 12, 1), GATE_CFG(GATE_DMA1, RCC_MP_AHB2ENSETR, 0, 1), GATE_CFG(GATE_DMA2, RCC_MP_AHB2ENSETR, 1, 1), GATE_CFG(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2, 1), GATE_CFG(GATE_DMA3, RCC_MP_AHB2ENSETR, 3, 1), GATE_CFG(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4, 1), GATE_CFG(GATE_ADC1, RCC_MP_AHB2ENSETR, 5, 1), GATE_CFG(GATE_ADC2, RCC_MP_AHB2ENSETR, 6, 1), GATE_CFG(GATE_USBO, RCC_MP_AHB2ENSETR, 8, 1), GATE_CFG(GATE_TSC, RCC_MP_AHB4ENSETR, 15, 1), GATE_CFG(GATE_GPIOA, RCC_MP_S_AHB4ENSETR, 0, 1), GATE_CFG(GATE_GPIOB, RCC_MP_S_AHB4ENSETR, 1, 1), GATE_CFG(GATE_GPIOC, RCC_MP_S_AHB4ENSETR, 2, 1), GATE_CFG(GATE_GPIOD, RCC_MP_S_AHB4ENSETR, 3, 1), GATE_CFG(GATE_GPIOE, RCC_MP_S_AHB4ENSETR, 4, 1), GATE_CFG(GATE_GPIOF, RCC_MP_S_AHB4ENSETR, 5, 1), GATE_CFG(GATE_GPIOG, RCC_MP_S_AHB4ENSETR, 6, 1), GATE_CFG(GATE_GPIOH, RCC_MP_S_AHB4ENSETR, 7, 1), GATE_CFG(GATE_GPIOI, RCC_MP_S_AHB4ENSETR, 8, 1), GATE_CFG(GATE_PKA, RCC_MP_AHB5ENSETR, 2, 1), GATE_CFG(GATE_SAES, RCC_MP_AHB5ENSETR, 3, 1), GATE_CFG(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4, 1), GATE_CFG(GATE_HASH1, RCC_MP_AHB5ENSETR, 5, 1), GATE_CFG(GATE_RNG1, RCC_MP_AHB5ENSETR, 6, 1), GATE_CFG(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8, 1), GATE_CFG(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16, 1), GATE_CFG(GATE_MCE, RCC_MP_AHB6ENSETR, 1, 1), GATE_CFG(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7, 1), GATE_CFG(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8, 1), GATE_CFG(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9, 1), GATE_CFG(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10, 1), GATE_CFG(GATE_FMC, RCC_MP_AHB6ENSETR, 12, 1), GATE_CFG(GATE_QSPI, RCC_MP_AHB6ENSETR, 14, 1), GATE_CFG(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16, 1), GATE_CFG(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17, 1), GATE_CFG(GATE_CRC1, RCC_MP_AHB6ENSETR, 20, 1), GATE_CFG(GATE_USBH, RCC_MP_AHB6ENSETR, 24, 1), GATE_CFG(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27, 1), GATE_CFG(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28, 1), GATE_CFG(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29, 1), GATE_CFG(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30, 1), GATE_CFG(GATE_MDMA, RCC_MP_S_AHB6ENSETR, 0, 1), }; /* * MUX CONFIG */ #define MUXRDY_CFG(_id, _offset, _shift, _witdh, _rdy)\ [(_id)] = {\ .offset = (_offset),\ .shift = (_shift),\ .width = (_witdh),\ .ready = (_rdy),\ } #define MUX_CFG(_id, _offset, _shift, _witdh)\ MUXRDY_CFG(_id, _offset, _shift, _witdh, MUX_NO_RDY) static const struct mux_cfg parent_mp13[MUX_NB] = { MUXRDY_CFG(MUX_MPU, RCC_MPCKSELR, 0, 2, GATE_MPUSRCRDY), MUXRDY_CFG(MUX_AXI, RCC_ASSCKSELR, 0, 3, GATE_AXISSRCRDY), MUXRDY_CFG(MUX_MLAHB, RCC_MSSCKSELR, 0, 2, GATE_MCUSSRCRDY), MUXRDY_CFG(MUX_PLL12, RCC_RCK12SELR, 0, 2, GATE_PLL12SRCRDY), MUXRDY_CFG(MUX_PLL3, RCC_RCK3SELR, 0, 2, GATE_PLL3SRCRDY), MUXRDY_CFG(MUX_PLL4, RCC_RCK4SELR, 0, 2, GATE_PLL4SRCRDY), MUX_CFG(MUX_ADC1, RCC_ADC12CKSELR, 0, 2), MUX_CFG(MUX_ADC2, RCC_ADC12CKSELR, 2, 2), MUX_CFG(MUX_CKPER, RCC_CPERCKSELR, 0, 2), MUX_CFG(MUX_DCMIPP, RCC_DCMIPPCKSELR, 0, 2), MUX_CFG(MUX_ETH1, RCC_ETH12CKSELR, 0, 2), MUX_CFG(MUX_ETH2, RCC_ETH12CKSELR, 8, 2), MUX_CFG(MUX_FDCAN, RCC_FDCANCKSELR, 0, 2), MUX_CFG(MUX_FMC, RCC_FMCCKSELR, 0, 2), MUX_CFG(MUX_I2C12, RCC_I2C12CKSELR, 0, 3), MUX_CFG(MUX_I2C3, RCC_I2C345CKSELR, 0, 3), MUX_CFG(MUX_I2C4, RCC_I2C345CKSELR, 3, 3), MUX_CFG(MUX_I2C5, RCC_I2C345CKSELR, 6, 3), MUX_CFG(MUX_LPTIM1, RCC_LPTIM1CKSELR, 0, 3), MUX_CFG(MUX_LPTIM2, RCC_LPTIM23CKSELR, 0, 3), MUX_CFG(MUX_LPTIM3, RCC_LPTIM23CKSELR, 3, 3), MUX_CFG(MUX_LPTIM45, RCC_LPTIM45CKSELR, 0, 3), MUX_CFG(MUX_MCO1, RCC_MCO1CFGR, 0, 3), MUX_CFG(MUX_MCO2, RCC_MCO2CFGR, 0, 3), MUX_CFG(MUX_QSPI, RCC_QSPICKSELR, 0, 2), MUX_CFG(MUX_RNG1, RCC_RNG1CKSELR, 0, 2), MUX_CFG(MUX_RTC, RCC_BDCR, 16, 2), MUX_CFG(MUX_SAES, RCC_SAESCKSELR, 0, 2), MUX_CFG(MUX_SAI1, RCC_SAI1CKSELR, 0, 3), MUX_CFG(MUX_SAI2, RCC_SAI2CKSELR, 0, 3), MUX_CFG(MUX_SDMMC1, RCC_SDMMC12CKSELR, 0, 3), MUX_CFG(MUX_SDMMC2, RCC_SDMMC12CKSELR, 3, 3), MUX_CFG(MUX_SPDIF, RCC_SPDIFCKSELR, 0, 2), MUX_CFG(MUX_SPI1, RCC_SPI2S1CKSELR, 0, 3), MUX_CFG(MUX_SPI23, RCC_SPI2S23CKSELR, 0, 3), MUX_CFG(MUX_SPI4, RCC_SPI45CKSELR, 0, 3), MUX_CFG(MUX_SPI5, RCC_SPI45CKSELR, 3, 3), MUX_CFG(MUX_STGEN, RCC_STGENCKSELR, 0, 2), MUX_CFG(MUX_UART1, RCC_UART12CKSELR, 0, 3), MUX_CFG(MUX_UART2, RCC_UART12CKSELR, 3, 3), MUX_CFG(MUX_UART35, RCC_UART35CKSELR, 0, 3), MUX_CFG(MUX_UART4, RCC_UART4CKSELR, 0, 3), MUX_CFG(MUX_UART6, RCC_UART6CKSELR, 0, 3), MUX_CFG(MUX_UART78, RCC_UART78CKSELR, 0, 3), MUX_CFG(MUX_USBO, RCC_USBCKSELR, 4, 1), MUX_CFG(MUX_USBPHY, RCC_USBCKSELR, 0, 2), }; /* * DIV CONFIG */ static const struct div_table_cfg axi_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 }, { 0 }, }; static const struct div_table_cfg mlahb_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 }, { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 }, { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 }, { 0 }, }; static const struct div_table_cfg apb_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, { 0 }, }; #define DIVRDY_CFG(_id, _offset, _shift, _width, _flags, _table, _ready)\ [(_id)] = {\ .offset = (_offset),\ .shift = (_shift),\ .width = (_width),\ .flags = (_flags),\ .table = (_table),\ .ready = (_ready),\ } #define DIV_CFG(_id, _offset, _shift, _width, _flags, _table)\ DIVRDY_CFG(_id, _offset, _shift, _width, _flags, _table, DIV_NO_RDY) static const struct div_cfg dividers_mp13[] = { DIVRDY_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL, GATE_MPUDIVRDY), DIVRDY_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table, GATE_AXIDIVRDY), DIVRDY_CFG(DIV_MLAHB, RCC_MLAHBDIVR, 0, 4, 0, mlahb_div_table, GATE_MLAHBDIVRDY), DIVRDY_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, GATE_APB1DIVRDY), DIVRDY_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, GATE_APB2DIVRDY), DIVRDY_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, GATE_APB3DIVRDY), DIVRDY_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, GATE_APB4DIVRDY), DIVRDY_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, GATE_APB5DIVRDY), DIVRDY_CFG(DIV_APB6, RCC_APB6DIVR, 0, 3, 0, apb_div_table, GATE_APB6DIVRDY), DIVRDY_CFG(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL, GATE_HSIDIVRDY), DIV_CFG(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL), DIV_CFG(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL), DIV_CFG(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL), DIV_CFG(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL), DIV_CFG(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL), DIV_CFG(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL), DIV_CFG(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL), DIV_CFG(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL), DIV_CFG(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL), DIV_CFG(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL), DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL), DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL), DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL), DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, CLK_DIVIDER_POWER_OF_TWO, NULL), DIV_CFG(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL), DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL), }; enum stm32_osc { OSC_HSI, OSC_HSE, OSC_CSI, OSC_LSI, OSC_LSE, NB_OSCILLATOR }; struct stm32_osc_cfg { int osc_id; }; struct clk_stm32_bypass { uint16_t offset; uint8_t bit_byp; uint8_t bit_digbyp; }; struct clk_stm32_css { uint16_t offset; uint8_t bit_css; }; struct clk_stm32_drive { uint16_t offset; uint8_t drv_shift; uint8_t drv_width; uint8_t drv_default; }; struct clk_oscillator_data { const char *name; unsigned long frequency; uint16_t gate_id; struct clk_stm32_bypass *bypass; struct clk_stm32_css *css; struct clk_stm32_drive *drive; }; #define BYPASS(_offset, _bit_byp, _bit_digbyp) (&(struct clk_stm32_bypass){\ .offset = (_offset),\ .bit_byp = (_bit_byp),\ .bit_digbyp = (_bit_digbyp),\ }) #define CSS(_offset, _bit_css) (&(struct clk_stm32_css){\ .offset = (_offset),\ .bit_css = (_bit_css),\ }) #define DRIVE(_offset, _shift, _width, _default) (&(struct clk_stm32_drive){\ .offset = (_offset),\ .drv_shift = (_shift),\ .drv_width = (_width),\ .drv_default = (_default),\ }) #define OSCILLATOR(idx_osc, _name, _gate_id, _bypass, _css, _drive) \ [(idx_osc)] = (struct clk_oscillator_data){\ .name = (_name),\ .gate_id = (_gate_id),\ .bypass = (_bypass),\ .css = (_css),\ .drive = (_drive),\ } static struct clk_oscillator_data stm32mp13_osc_data[NB_OSCILLATOR] = { OSCILLATOR(OSC_HSI, "clk-hsi", GATE_HSI, NULL, NULL, NULL), OSCILLATOR(OSC_LSI, "clk-lsi", GATE_LSI, NULL, NULL, NULL), OSCILLATOR(OSC_CSI, "clk-csi", GATE_CSI, NULL, NULL, NULL), OSCILLATOR(OSC_LSE, "clk-lse", GATE_LSE, BYPASS(RCC_BDCR, 1, 3), CSS(RCC_BDCR, 8), DRIVE(RCC_BDCR, 4, 2, 2)), OSCILLATOR(OSC_HSE, "clk-hse", GATE_HSE, BYPASS(RCC_OCENSETR, 10, 7), CSS(RCC_OCENSETR, 11), NULL), }; static struct clk_oscillator_data *clk_oscillator_get_data(int osc_id) { assert(osc_id >= 0 && osc_id < (int)ARRAY_SIZE(stm32mp13_osc_data)); return &stm32mp13_osc_data[osc_id]; } static unsigned long clk_stm32_get_rate_oscillateur(int osc_id) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_clk_platdata *pdata = priv->pdata; struct stm32_osci_dt_cfg *osci = &pdata->osci[osc_id]; return osci->freq; } static void clk_oscillator_set_bypass(struct clk_stm32_priv *priv, struct clk_oscillator_data *osc_data, bool digbyp, bool bypass) { struct clk_stm32_bypass *bypass_data = osc_data->bypass; uintptr_t address = 0; if (!bypass_data) return; address = priv->base + bypass_data->offset; if (digbyp) io_setbits32(address, BIT(bypass_data->bit_digbyp)); if (bypass || digbyp) io_setbits32(address, BIT(bypass_data->bit_byp)); } static void clk_oscillator_set_css(struct clk_stm32_priv *priv, struct clk_oscillator_data *osc_data, bool css) { struct clk_stm32_css *css_data = osc_data->css; uintptr_t address = 0; if (!css_data) return; address = priv->base + css_data->offset; if (css) io_setbits32(address, BIT(css_data->bit_css)); } static void clk_oscillator_set_drive(struct clk_stm32_priv *priv, struct clk_oscillator_data *osc_data, uint8_t lsedrv) { struct clk_stm32_drive *drive_data = osc_data->drive; uintptr_t address = 0; uint32_t mask = 0; uint32_t value = 0; if (!drive_data) return; address = priv->base + drive_data->offset; mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift; /* * Warning: not recommended to switch directly from "high drive" * to "medium low drive", and vice-versa. */ value = (io_read32(address) & mask) >> drive_data->drv_shift; while (value != lsedrv) { if (value > lsedrv) value--; else value++; io_clrsetbits32(address, mask, value << drive_data->drv_shift); } } static void stm32_enable_oscillator_hse(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_HSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE]; if (osci->freq == 0U) return; clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass); /* Enable clock and wait ready bit */ if (stm32_gate_rdy_enable(osc_data->gate_id)) { EMSG("timeout to enable hse clock"); panic(); } clk_oscillator_set_css(priv, osc_data, osci->css); } static void stm32_enable_oscillator_lse(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; if (osci->freq == 0U) return; clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass); clk_oscillator_set_drive(priv, osc_data, osci->drive); /* Enable lse clock, but don't wait ready bit */ stm32_gate_enable(osc_data->gate_id); } static void stm32_enable_oscillator_lsi(struct clk_stm32_priv *priv __maybe_unused, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSI); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSI]; if (osci->freq == 0U) return; /* Enable clock and wait ready bit */ if (stm32_gate_rdy_enable(osc_data->gate_id)) { EMSG("timeout to enable lsi clock"); panic(); } } static void stm32_enable_oscillator_csi(struct clk_stm32_priv *priv __maybe_unused, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_CSI); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_CSI]; if (osci->freq == 0U) return; /* Enable clock and wait ready bit */ if (stm32_gate_rdy_enable(osc_data->gate_id)) { EMSG("timeout to enable csi clock"); panic(); } } static int stm32_clk_oscillators_lse_set_css(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; clk_oscillator_set_css(priv, osc_data, osci->css); return 0; } static int stm32_clk_oscillators_wait_lse_ready(struct clk_stm32_priv *priv __maybe_unused, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; if (osci->freq == 0U) return 0; if (stm32_gate_wait_ready(osc_data->gate_id, true)) return -1; return 0; } static void stm32_clk_oscillators_enable(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { stm32_enable_oscillator_hse(priv, pdata); stm32_enable_oscillator_lse(priv, pdata); stm32_enable_oscillator_lsi(priv, pdata); stm32_enable_oscillator_csi(priv, pdata); } enum stm32_pll_id { PLL1_ID, PLL2_ID, PLL3_ID, PLL4_ID, PLL_NB }; enum stm32mp1_plltype { PLL_800, PLL_1600, PLL_2000, PLL_TYPE_NB }; #define RCC_OFFSET_PLLXCR 0 #define RCC_OFFSET_PLLXCFGR1 4 #define RCC_OFFSET_PLLXCFGR2 8 #define RCC_OFFSET_PLLXFRACR 12 #define RCC_OFFSET_PLLXCSGR 16 struct stm32_clk_pll { enum stm32mp1_plltype plltype; uint16_t gate_id; uint16_t mux_id; uint16_t reg_pllxcr; }; struct stm32mp1_pll { uint8_t refclk_min; uint8_t refclk_max; }; /* Define characteristic of PLL according type */ static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { [PLL_800] = { .refclk_min = 4, .refclk_max = 16, }, [PLL_1600] = { .refclk_min = 8, .refclk_max = 16, }, [PLL_2000] = { .refclk_min = 8, .refclk_max = 16, } }; #define CLK_PLL_CFG(_idx, _type, _gate_id, _mux_id, _reg)\ [(_idx)] = {\ .gate_id = (_gate_id),\ .mux_id = (_mux_id),\ .plltype = (_type),\ .reg_pllxcr = (_reg),\ } static const struct stm32_clk_pll stm32_mp13_clk_pll[PLL_NB] = { CLK_PLL_CFG(PLL1_ID, PLL_2000, GATE_PLL1, MUX_PLL12, RCC_PLL1CR), CLK_PLL_CFG(PLL2_ID, PLL_1600, GATE_PLL2, MUX_PLL12, RCC_PLL2CR), CLK_PLL_CFG(PLL3_ID, PLL_800, GATE_PLL3, MUX_PLL3, RCC_PLL3CR), CLK_PLL_CFG(PLL4_ID, PLL_800, GATE_PLL4, MUX_PLL4, RCC_PLL4CR), }; static const struct stm32_clk_pll *clk_stm32_pll_data(unsigned int idx) { return &stm32_mp13_clk_pll[idx]; } /* Clock TREE configuration */ static unsigned int stm32_clk_configure_clk_get_binding_id(uint32_t data) { return (data & CLK_ID_MASK) >> CLK_ID_SHIFT; } static int stm32_clk_configure_clk(struct clk_stm32_priv *priv __maybe_unused, uint32_t data) { int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT; int enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT; int clk_id = 0; int ret = 0; int mux = -1; int gate = -1; clk_id = stm32_clk_configure_clk_get_binding_id(data); switch (clk_id) { case CK_MCO1: mux = MUX_MCO1; gate = GATE_MCO1; break; case CK_MCO2: mux = MUX_MCO2; gate = GATE_MCO2; break; default: ret = -1; break; } if (ret != 0) return ret; if (stm32_mux_set_parent(mux, sel)) return -1; if (enable) stm32_gate_enable(gate); else stm32_gate_disable(gate); return 0; } static int stm32_clk_configure_mux(__unused struct clk_stm32_priv *priv, uint32_t data) { int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; if (mux == MUX_RTC) { /* Mux RTC clock only is selector is valid and RTC not yet * enabled */ if (sel == 0) return 0; if (stm32_gate_is_enabled(GATE_RTCCK)) return 0; } if (stm32_mux_set_parent(mux, sel)) return -1; return 0; } static TEE_Result stm32_clk_configure_div(struct clk_stm32_priv *priv __maybe_unused, uint32_t data) { int div_id = (data & DIV_ID_MASK) >> DIV_ID_SHIFT; int div_n = (data & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; return stm32_div_set_value(div_id, div_n); } static int stm32_clk_dividers_configure(struct clk_stm32_priv *priv) { struct stm32_clk_platdata *pdata = priv->pdata; unsigned int i = 0; for (i = 0; i < pdata->nclkdiv; i++) { if (stm32_clk_configure_div(priv, pdata->clkdiv[i])) return -1; } return 0; } static int stm32_clk_source_configure(struct clk_stm32_priv *priv) { struct stm32_clk_platdata *pdata = priv->pdata; bool ckper_disabled = false; int ret = 0; size_t i = 0; for (i = 0; i < pdata->nclksrc; i++) { uint32_t val = pdata->clksrc[i]; uint32_t cmd = 0; uint32_t cmd_data = 0; if (val == (uint32_t)CLK_CKPER_DISABLED) { ckper_disabled = true; continue; } cmd = (val & CMD_MASK) >> CMD_SHIFT; cmd_data = val & ~CMD_MASK; switch (cmd) { case CMD_MUX: ret = stm32_clk_configure_mux(priv, cmd_data); break; case CMD_CLK: ret = stm32_clk_configure_clk(priv, cmd_data); break; default: ret = -1; break; } if (ret != 0) return ret; } /* * CKPER is source for some peripheral clocks * (FMC-NAND / QPSI-NOR) and switching source is allowed * only if previous clock is still ON * => deactivate CKPER only after switching clock */ if (ckper_disabled) { ret = stm32_clk_configure_mux(priv, CLK_CKPER_DISABLED & CMD_MASK); if (ret != 0) return ret; } return 0; } static unsigned long clk_stm32_pll_get_oscillator_rate(int sel) { const int osc[] = { OSC_HSI, OSC_HSE, OSC_CSI }; assert(sel >= 0 && sel < (int)ARRAY_SIZE(osc)); return clk_stm32_get_rate_oscillateur(osc[sel]); } static int clk_stm32_pll_compute_cfgr1(const struct stm32_clk_pll *pll, struct stm32_pll_vco *vco, uint32_t *value) { int sel = (vco->src & MUX_SEL_MASK) >> MUX_SEL_SHIFT; uint32_t divm = vco->div_mn[PLL_CFG_M]; uint32_t divn = vco->div_mn[PLL_CFG_N]; unsigned long refclk = 0UL; refclk = clk_stm32_pll_get_oscillator_rate(sel) / (divm + 1U); if ((refclk < (stm32mp1_pll[pll->plltype].refclk_min * 1000000U)) || (refclk > (stm32mp1_pll[pll->plltype].refclk_max * 1000000U))) return -1; *value = 0; if (pll->plltype == PLL_800 && refclk >= 8000000U) *value = 1U << RCC_PLLNCFGR1_IFRGE_SHIFT; *value |= (divn << RCC_PLLNCFGR1_DIVN_SHIFT) & RCC_PLLNCFGR1_DIVN_MASK; *value |= (divm << RCC_PLLNCFGR1_DIVM_SHIFT) & RCC_PLLNCFGR1_DIVM_MASK; return 0; } static uint32_t clk_stm32_pll_compute_cfgr2(struct stm32_pll_output *out) { uint32_t value = 0; value |= (out->output[PLL_CFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & RCC_PLLNCFGR2_DIVP_MASK; value |= (out->output[PLL_CFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & RCC_PLLNCFGR2_DIVQ_MASK; value |= (out->output[PLL_CFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & RCC_PLLNCFGR2_DIVR_MASK; return value; } /* * Check if PLL1 can be configured on the fly. * @result (-1) => config on the fly is not possible. * (0) => config on the fly is possible. * (+1) => same parameters, no need to reconfigure. * Return value is 0 if no error. */ static int clk_stm32_is_pll_config_on_the_fly(struct clk_stm32_priv *priv, const struct stm32_clk_pll *pll, struct stm32_pll_dt_cfg *pll_conf, int *result) { uintptr_t pll_base = priv->base + pll->reg_pllxcr; struct stm32_pll_vco *vco = &pll_conf->vco; struct stm32_pll_output *out = &pll_conf->output; uint32_t fracr = 0; uint32_t value = 0; int ret = 0; size_t sel = 0; ret = clk_stm32_pll_compute_cfgr1(pll, vco, &value); if (ret != 0) return ret; sel = (vco->src & MUX_SEL_MASK) >> MUX_SEL_SHIFT; if (sel != stm32_mux_get_parent(pll->mux_id)) { /* Clock source of the PLL is different */ *result = -1; return 0; } if (io_read32(pll_base + RCC_OFFSET_PLLXCFGR1) != value) { /* Different DIVN/DIVM, can't config on the fly */ *result = -1; return 0; } *result = 1; fracr = vco->frac << RCC_PLLNFRACR_FRACV_SHIFT; fracr |= RCC_PLLNCFGR1_DIVM_MASK; value = clk_stm32_pll_compute_cfgr2(out); if ((io_read32(pll_base + RCC_OFFSET_PLLXFRACR) == fracr) && (io_read32(pll_base + RCC_OFFSET_PLLXCFGR2) == value)) { /* Same parameters, no need to config */ *result = 1; } else { *result = 0; } return 0; } static int stm32_clk_hsidiv_configure(struct clk_stm32_priv *priv) { struct stm32_clk_platdata *pdata = priv->pdata; struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSI]; return stm32_div_set_rate(DIV_HSI, osci->freq, MAX_HSI_HZ); } static void clk_stm32_pll_config_vco(struct clk_stm32_priv *priv, const struct stm32_clk_pll *pll, struct stm32_pll_vco *vco) { uintptr_t pll_base = priv->base + pll->reg_pllxcr; uint32_t value = 0; if (clk_stm32_pll_compute_cfgr1(pll, vco, &value) != 0) { EMSG("Invalid Vref clock"); panic(); } /* Write N / M / IFREGE fields */ io_write32(pll_base + RCC_OFFSET_PLLXCFGR1, value); /* Fractional configuration */ io_write32(pll_base + RCC_OFFSET_PLLXFRACR, 0); /* Frac must be enabled only once its configuration is loaded */ io_write32(pll_base + RCC_OFFSET_PLLXFRACR, vco->frac << RCC_PLLNFRACR_FRACV_SHIFT); io_setbits32(pll_base + RCC_OFFSET_PLLXFRACR, RCC_PLLNFRACR_FRACLE); } static void clk_stm32_pll_config_csg(struct clk_stm32_priv *priv, const struct stm32_clk_pll *pll, struct stm32_pll_vco *vco) { uintptr_t pll_base = priv->base + pll->reg_pllxcr; uint32_t mod_per = 0; uint32_t inc_step = 0; uint32_t sscg_mode = 0; uint32_t value = 0; if (!vco->csg_enabled) return; mod_per = vco->csg[PLL_CSG_MOD_PER]; inc_step = vco->csg[PLL_CSG_INC_STEP]; sscg_mode = vco->csg[PLL_CSG_SSCG_MODE]; value |= (mod_per << RCC_PLLNCSGR_MOD_PER_SHIFT) & RCC_PLLNCSGR_MOD_PER_MASK; value |= (inc_step << RCC_PLLNCSGR_INC_STEP_SHIFT) & RCC_PLLNCSGR_INC_STEP_MASK; value |= (sscg_mode << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & RCC_PLLNCSGR_SSCG_MODE_MASK; io_write32(pll_base + RCC_OFFSET_PLLXCSGR, value); io_setbits32(pll_base + RCC_OFFSET_PLLXCR, RCC_PLLNCR_SSCG_CTRL); } static void clk_stm32_pll_config_out(struct clk_stm32_priv *priv, const struct stm32_clk_pll *pll, struct stm32_pll_output *out) { uintptr_t pll_base = priv->base + pll->reg_pllxcr; uint32_t value = 0; value = clk_stm32_pll_compute_cfgr2(out); io_write32(pll_base + RCC_OFFSET_PLLXCFGR2, value); } static struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_clk_platdata *pdata = priv->pdata; return &pdata->pll[pll_idx]; } static int clk_stm32_pll_init_switch_to_hsi_clk_system(int mux_sys) { int sel = 0; if (mux_sys == -1) return -1; /* Make a backup to the current parent */ sel = stm32_mux_get_parent(mux_sys); /* Switch to HSI */ if (stm32_mux_set_parent(mux_sys, 0)) return -1; return sel; } static uint32_t clk_stm32_pll_backup_output_diven(const struct stm32_clk_pll *pll) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); uintptr_t addr = priv->base + pll->reg_pllxcr; return io_read32(addr + RCC_OFFSET_PLLXCR) & (RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); } static void clk_stm32_pll_restore_output_diven(const struct stm32_clk_pll *pll, uint32_t value) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); uintptr_t addr = priv->base + pll->reg_pllxcr; const uint32_t mask = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN; io_clrsetbits32(addr, mask, value & mask); } static int clk_stm32_pll_init(struct clk_stm32_priv *priv, int pll_idx, struct stm32_pll_dt_cfg *pll_conf) { const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx); int config_on_the_fly = -1; int ret = 0; uint8_t sel = 0; uint32_t save_div_pqr_en = 0; int mux_system[] = { MUX_MPU, MUX_AXI, MUX_MLAHB, -1 }; int mux_sys = mux_system[pll_idx]; ret = clk_stm32_is_pll_config_on_the_fly(priv, pll, pll_conf, &config_on_the_fly); if (ret != 0) return ret; /* Backup status of DIV DIVPEN / DIVQEN / DIVREN */ save_div_pqr_en = clk_stm32_pll_backup_output_diven(pll); if (config_on_the_fly == -1) { /* Make a backup to the current parent and switch to HSI */ sel = clk_stm32_pll_init_switch_to_hsi_clk_system(mux_sys); /* Stop the PLL before */ if (stm32_gate_is_enabled(pll->gate_id)) { io_clrbits32(priv->base + pll->reg_pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); if (stm32_gate_rdy_disable(pll->gate_id)) return -1; } /* Configure PLLs source */ ret = stm32_clk_configure_mux(priv, pll_conf->vco.src); if (ret) return ret; clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); } if (config_on_the_fly != 1) { clk_stm32_pll_config_out(priv, pll, &pll_conf->output); clk_stm32_pll_config_csg(priv, pll, &pll_conf->vco); } if (!stm32_gate_is_enabled(pll->gate_id)) { if (stm32_gate_rdy_enable(pll->gate_id)) return -1; clk_stm32_pll_restore_output_diven(pll, save_div_pqr_en); } if ((config_on_the_fly == -1) && (mux_sys != -1)) { /* Restore to backup parent */ if (stm32_mux_set_parent(mux_sys, sel)) return -1; } return 0; } static int stm32_clk_pll_configure(struct clk_stm32_priv *priv) { struct stm32_pll_dt_cfg *pll_conf = NULL; size_t i = 0; const int plls[] = { PLL1_ID, PLL3_ID, PLL4_ID }; for (i = 0; i < ARRAY_SIZE(plls); i++) { pll_conf = clk_stm32_pll_get_pdata(plls[i]); if (pll_conf->vco.status) { int err = 0; err = clk_stm32_pll_init(priv, plls[i], pll_conf); if (err) return err; } } return 0; } static int stm32mp1_init_clock_tree(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { int ret = 0; /* * Switch ON oscillators found in device-tree. * Note: HSI already ON after BootROM stage. */ stm32_clk_oscillators_enable(priv, pdata); ret = stm32_clk_hsidiv_configure(priv); if (ret != 0) return ret; ret = stm32_clk_dividers_configure(priv); if (ret != 0) panic(); ret = stm32_clk_pll_configure(priv); if (ret != 0) panic(); /* Wait LSE ready before to use it */ ret = stm32_clk_oscillators_wait_lse_ready(priv, pdata); if (ret != 0) panic(); /* Configure with expected clock source */ ret = stm32_clk_source_configure(priv); if (ret != 0) panic(); /* Configure LSE CSS after RTC source configuration */ ret = stm32_clk_oscillators_lse_set_css(priv, pdata); if (ret != 0) panic(); /* Software Self-Refresh mode (SSR) during DDR initilialization */ io_clrsetbits32(priv->base + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK, RCC_DDRITFCR_DDRCKMOD_SSR << RCC_DDRITFCR_DDRCKMOD_SHIFT); return 0; } static int clk_stm32_parse_oscillator_fdt(const void *fdt, int node, const char *name, struct stm32_osci_dt_cfg *osci) { int subnode = 0; fdt_for_each_subnode(subnode, fdt, node) { const char *cchar = NULL; const fdt32_t *cuint = NULL; int ret = 0; cchar = fdt_get_name(fdt, subnode, &ret); if (!cchar) return ret; if (strncmp(cchar, name, (size_t)ret) || fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) continue; cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); if (!cuint) panic(); osci->freq = fdt32_to_cpu(*cuint); if (fdt_getprop(fdt, subnode, "st,bypass", NULL)) osci->bypass = true; if (fdt_getprop(fdt, subnode, "st,digbypass", NULL)) osci->digbyp = true; if (fdt_getprop(fdt, subnode, "st,css", NULL)) osci->css = true; osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH); return 0; } return -FDT_ERR_NOTFOUND; } static int stm32_clk_parse_fdt_all_oscillator(const void *fdt, int node __maybe_unused, struct stm32_clk_platdata *pdata) { int fdt_err = 0; size_t i = 0; int osc_node = 0; osc_node = fdt_path_offset(fdt, "/clocks"); if (osc_node < 0) return -FDT_ERR_NOTFOUND; for (i = 0; i < NB_OSCILLATOR; i++) { struct stm32_osci_dt_cfg *osci = &pdata->osci[i]; struct clk_oscillator_data *osc_data = NULL; osc_data = clk_oscillator_get_data(i); fdt_err = clk_stm32_parse_oscillator_fdt(fdt, osc_node, osc_data->name, osci); if (fdt_err) { if (fdt_err == -FDT_ERR_NOTFOUND) { /* Oscillator not found means it is not wired */ osci->freq = 0; } else { panic(); } } } return 0; } static int clk_stm32_load_vco_config_fdt(const void *fdt, int subnode, struct stm32_pll_vco *vco) { int ret = 0; ret = fdt_read_uint32_array(fdt, subnode, "divmn", vco->div_mn, PLL_DIV_MN_NB); if (ret != 0) return ret; ret = fdt_read_uint32_array(fdt, subnode, "csg", vco->csg, PLL_CSG_NB); vco->csg_enabled = (ret == 0); if (ret == -FDT_ERR_NOTFOUND) ret = 0; if (ret != 0) return ret; vco->status = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN | RCC_PLLNCR_PLLON; vco->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0); vco->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX); return 0; } static int clk_stm32_load_output_config_fdt(const void *fdt, int subnode, struct stm32_pll_output *output) { return fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", output->output, (int)PLL_DIV_PQR_NB); } static int clk_stm32_parse_pll_fdt(const void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) { const fdt32_t *cuint = NULL; int subnode_pll = 0; int subnode_vco = 0; int err = 0; cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); if (!cuint) return -FDT_ERR_NOTFOUND; subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); if (subnode_pll < 0) return -FDT_ERR_NOTFOUND; cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL); if (!cuint) return -FDT_ERR_NOTFOUND; subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); if (subnode_vco < 0) return -FDT_ERR_NOTFOUND; err = clk_stm32_load_vco_config_fdt(fdt, subnode_vco, &pll->vco); if (err != 0) return err; err = clk_stm32_load_output_config_fdt(fdt, subnode_pll, &pll->output); if (err != 0) return err; return 0; } static int stm32_clk_parse_fdt_all_pll(const void *fdt, int node, struct stm32_clk_platdata *pdata) { size_t i = 0; for (i = PLL1_ID; i < pdata->npll; i++) { struct stm32_pll_dt_cfg *pll = pdata->pll + i; char name[RCC_PLL_NAME_SIZE] = { 0 }; int subnode = 0; int err = 0; snprintf(name, sizeof(name), "st,pll@%d", i); subnode = fdt_subnode_offset(fdt, node, name); if (subnode < 0) continue; err = clk_stm32_parse_pll_fdt(fdt, subnode, pll); if (err != 0) panic(); } return 0; } static int stm32_clk_parse_fdt_opp(const void *fdt, int node, const char *opp_name, struct stm32_clk_opp_cfg *opp_cfg) { int subnode = 0; int nb_opp = 0; int ret = 0; node = fdt_subnode_offset(fdt, node, opp_name); if (node == -FDT_ERR_NOTFOUND) return 0; if (node < 0) return node; fdt_for_each_subnode(subnode, fdt, node) { if (nb_opp >= MAX_OPP) { EMSG("%d MAX opp in %s", MAX_OPP, opp_name); panic(); } opp_cfg->frq = fdt_read_uint32_default(fdt, subnode, "hz", UINT32_MAX); opp_cfg->src = fdt_read_uint32_default(fdt, subnode, "st,clksrc", UINT32_MAX); opp_cfg->div = fdt_read_uint32_default(fdt, subnode, "st,clkdiv", UINT32_MAX); ret = clk_stm32_parse_pll_fdt(fdt, subnode, &opp_cfg->pll_cfg); if (ret) return ret; opp_cfg++; nb_opp++; } return 0; } static int stm32_clk_parse_fdt_all_opp(const void *fdt, int node, struct stm32_clk_platdata *pdata) { struct stm32_clk_opp_dt_cfg *opp = pdata->opp; int ret = 0; node = fdt_subnode_offset(fdt, node, "st,clk_opp"); /* No opp are defined */ if (node == -FDT_ERR_NOTFOUND) return 0; if (node < 0) return node; ret = stm32_clk_parse_fdt_opp(fdt, node, "st,ck_mpu", opp->mpu_opp); if (ret) return ret; ret = stm32_clk_parse_fdt_opp(fdt, node, "st,ck_axi", opp->axi_opp); if (ret) return ret; ret = stm32_clk_parse_fdt_opp(fdt, node, "st,ck_mlahbs", opp->mlahbs_opp); if (ret) return ret; return 0; } static int stm32_clk_parse_fdt(const void *fdt, int node, struct stm32_clk_platdata *pdata) { int err = 0; err = stm32_clk_parse_fdt_all_oscillator(fdt, node, pdata); if (err != 0) return err; err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); if (err != 0) return err; err = stm32_clk_parse_fdt_all_opp(fdt, node, pdata); if (err != 0) return err; err = clk_stm32_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, &pdata->nclkdiv); if (err != 0) return err; err = clk_stm32_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, &pdata->nclksrc); if (err != 0) return err; return 0; } struct clk_stm32_pll_cfg { uint32_t reg_pllxcr; int gate_id; int mux_id; }; static size_t clk_stm32_pll_get_parent(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; return stm32_mux_get_parent(cfg->mux_id); } static unsigned long clk_stm32_pll_get_rate(struct clk *clk, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct clk_stm32_pll_cfg *cfg = clk->priv; uintptr_t pll_base = priv->base + cfg->reg_pllxcr; uint32_t cfgr1 = 0; uint32_t fracr = 0; uint32_t divm = 0; uint32_t divn = 0; unsigned long fvco = 0UL; cfgr1 = io_read32(pll_base + RCC_OFFSET_PLLXCFGR1); fracr = io_read32(pll_base + RCC_OFFSET_PLLXFRACR); divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; /* * With FRACV : * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) * Without FRACV * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) */ if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> RCC_PLLNFRACR_FRACV_SHIFT; unsigned long long numerator = 0UL; unsigned long long denominator = 0UL; numerator = (((unsigned long long)divn + 1U) << 13) + fracv; numerator = prate * numerator; denominator = ((unsigned long long)divm + 1U) << 13; fvco = (unsigned long)(numerator / denominator); } else { fvco = (unsigned long)(prate * (divn + 1U) / (divm + 1U)); } return UDIV_ROUND_NEAREST(fvco, 100000) * 100000; }; static bool clk_stm32_pll_is_enabled(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; return stm32_gate_is_enabled(cfg->gate_id); } static TEE_Result clk_stm32_pll_enable(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; if (clk_stm32_pll_is_enabled(clk)) return TEE_SUCCESS; return stm32_gate_rdy_enable(cfg->gate_id); } static void clk_stm32_pll_disable(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; struct clk_stm32_priv *priv = clk_stm32_get_priv(); uintptr_t pll_base = priv->base + cfg->reg_pllxcr; if (!clk_stm32_pll_is_enabled(clk)) return; /* Stop all output */ io_clrbits32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); stm32_gate_rdy_disable(cfg->gate_id); } static const struct clk_ops clk_stm32_pll_ops = { .get_parent = clk_stm32_pll_get_parent, .get_rate = clk_stm32_pll_get_rate, .enable = clk_stm32_pll_enable, .disable = clk_stm32_pll_disable, }; static TEE_Result clk_stm32_composite_get_duty_cycle(struct clk *clk, struct clk_duty_cycle *duty_cycle) { struct clk_stm32_composite_cfg *cfg = clk->priv; uint32_t val = stm32_div_get_value(cfg->div_id); duty_cycle->num = (val + 1) / 2; duty_cycle->den = val + 1; return TEE_SUCCESS; } static const struct clk_ops clk_stm32_composite_duty_cycle_ops = { .get_parent = clk_stm32_composite_get_parent, .set_parent = clk_stm32_composite_set_parent, .get_rate = clk_stm32_composite_get_rate, .set_rate = clk_stm32_composite_set_rate, .enable = clk_stm32_composite_gate_enable, .disable = clk_stm32_composite_gate_disable, .get_duty_cycle = clk_stm32_composite_get_duty_cycle, }; static struct stm32_clk_opp_cfg *clk_stm32_get_opp_config(struct stm32_clk_opp_cfg *opp_cfg, unsigned long rate) { unsigned int i = 0; for (i = 0; i < MAX_OPP; i++, opp_cfg++) { if (opp_cfg->frq == 0UL) break; if (opp_cfg->frq == rate) return opp_cfg; } return NULL; } static TEE_Result clk_stm32_pll1_set_rate(struct clk *clk __maybe_unused, unsigned long rate, unsigned long prate __maybe_unused) { const struct stm32_clk_pll *pll = clk_stm32_pll_data(PLL1_ID); struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_clk_platdata *pdata = priv->pdata; struct stm32_pll_dt_cfg *pll_conf = NULL; struct stm32_clk_opp_cfg *opp = NULL; int config_on_the_fly = -1; int err = 0; size_t sel = stm32_mux_get_parent(MUX_MPU); opp = clk_stm32_get_opp_config(pdata->opp->mpu_opp, rate); if (!opp) return TEE_ERROR_GENERIC; pll_conf = &opp->pll_cfg; err = clk_stm32_is_pll_config_on_the_fly(priv, pll, pll_conf, &config_on_the_fly); if (err) return TEE_ERROR_GENERIC; if (config_on_the_fly == 1) return TEE_SUCCESS; if (config_on_the_fly == -1) { /* Switch to HSI and stop PLL1 before reconfiguration */ if (stm32_mux_set_parent(MUX_MPU, 0)) return TEE_ERROR_GENERIC; stm32_gate_disable(GATE_PLL1_DIVP); stm32_gate_rdy_disable(GATE_PLL1); clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); } clk_stm32_pll_config_out(priv, pll, &pll_conf->output); if (stm32_gate_rdy_enable(GATE_PLL1)) { EMSG("timeout to enable PLL1 clock"); panic(); } stm32_gate_enable(GATE_PLL1_DIVP); /* Restore MPU source */ if (stm32_mux_set_parent(MUX_MPU, sel)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static const struct clk_ops clk_stm32_pll1_ops = { .set_rate = clk_stm32_pll1_set_rate, .get_parent = clk_stm32_pll_get_parent, .get_rate = clk_stm32_pll_get_rate, .enable = clk_stm32_pll_enable, .disable = clk_stm32_pll_disable, }; static const struct clk_ops clk_stm32_pll1p_ops = { .get_rate = clk_stm32_composite_get_rate, .enable = clk_stm32_composite_gate_enable, .disable = clk_stm32_composite_gate_disable, }; static const struct clk_ops clk_stm32_mpu_ops = { .get_parent = clk_stm32_composite_get_parent, .set_parent = clk_stm32_composite_set_parent, }; static const struct clk_ops clk_stm32_axi_ops = { .get_parent = clk_stm32_composite_get_parent, .set_parent = clk_stm32_composite_set_parent, .set_rate = clk_stm32_composite_set_rate, .get_rate = clk_stm32_composite_get_rate, }; const struct clk_ops clk_stm32_mlahb_ops = { .get_parent = clk_stm32_composite_get_parent, .set_parent = clk_stm32_composite_set_parent, .set_rate = clk_stm32_composite_set_rate, .get_rate = clk_stm32_composite_get_rate, }; #define APB_DIV_MASK GENMASK_32(2, 0) #define TIM_PRE_MASK BIT(0) static unsigned long ck_timer_get_rate_ops(struct clk *clk, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct clk_stm32_timer_cfg *cfg = clk->priv; uint32_t prescaler, timpre; uintptr_t rcc_base = priv->base; prescaler = io_read32(rcc_base + cfg->apbdiv) & APB_DIV_MASK; timpre = io_read32(rcc_base + cfg->timpre) & TIM_PRE_MASK; if (prescaler == 0U) return prate; return prate * (timpre + 1U) * 2U; }; const struct clk_ops ck_timer_ops = { .get_rate = ck_timer_get_rate_ops, }; #define STM32_TIMER(_name, _parent, _flags, _apbdiv, _timpre)\ struct clk _name = {\ .ops = &ck_timer_ops,\ .priv = &(struct clk_stm32_timer_cfg) {\ .apbdiv = (_apbdiv),\ .timpre = (_timpre),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { _parent },\ } #define STM32_KCLK(_name, _nb_parents, _parents, _flags, _gate_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_composite_ops,\ .priv = &(struct clk_stm32_composite_cfg) {\ .gate_id = (_gate_id),\ .div_id = (NO_DIV),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = (_nb_parents),\ .parents = _parents,\ } #define STM32_PLL_VCO(_name, _nb_parents, _parents, _flags, _reg,\ _gate_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_pll_ops,\ .priv = &(struct clk_stm32_pll_cfg) {\ .reg_pllxcr = (_reg),\ .gate_id = (_gate_id),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = (_nb_parents),\ .parents = _parents,\ } #define STM32_PLL_OUPUT(_name, _nb_parents, _parents, _flags,\ _gate_id, _div_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_composite_duty_cycle_ops,\ .priv = &(struct clk_stm32_composite_cfg) {\ .gate_id = (_gate_id),\ .div_id = (_div_id),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = (_nb_parents),\ .parents = _parents,\ } /* Oscillator clocks */ static TEE_Result clk_stm32_oscillator_enable(struct clk *clk) { struct clk_stm32_gate_cfg *cfg = clk->priv; if (clk->rate == 0U) return TEE_SUCCESS; return stm32_gate_rdy_enable(cfg->gate_id); } static void clk_stm32_oscillator_disable(struct clk *clk) { struct clk_stm32_gate_cfg *cfg = clk->priv; if (clk->rate == 0U) return; if (stm32_gate_rdy_disable(cfg->gate_id)) panic(); } static const struct clk_ops clk_stm32_oscillator_ops = { .enable = clk_stm32_oscillator_enable, .disable = clk_stm32_oscillator_disable, }; /* * Each oscillator has 1 parent which reference is NULL here * but set during initialization. */ #define STM32_OSCILLATOR(_name, _gate_id)\ struct clk _name = {\ .ops = &clk_stm32_oscillator_ops,\ .priv = &(struct clk_stm32_gate_cfg) {\ .gate_id = (_gate_id),\ },\ .name = #_name,\ .num_parents = 1, \ .parents = { NULL }, \ } static STM32_OSCILLATOR(ck_hsi, GATE_HSI); static STM32_OSCILLATOR(ck_hse, GATE_HSE); static STM32_OSCILLATOR(ck_csi, GATE_CSI); static STM32_OSCILLATOR(ck_lsi, GATE_LSI); static STM32_OSCILLATOR(ck_lse, GATE_LSE); static STM32_FIXED_FACTOR(ck_i2sckin, NULL, 0, 1, 1); static STM32_FIXED_FACTOR(ck_hse_div2, &ck_hse, 0, 1, 2); static STM32_FIXED_RATE(ck_off, 0UL); static STM32_FIXED_RATE(ck_usb_phy_48Mhz, USB_PHY_48_MHZ); /* PLL1 clocks */ static struct clk ck_pll1_vco = { .ops = &clk_stm32_pll1_ops, .priv = &(struct clk_stm32_pll_cfg) { .reg_pllxcr = RCC_PLL1CR, .gate_id = GATE_PLL1, .mux_id = MUX_PLL12, }, .name = "ck_pll1_vco", .flags = 0, .num_parents = 2, .parents = { &ck_hsi, &ck_hse }, }; static struct clk ck_pll1p = { .ops = &clk_stm32_pll1p_ops, .priv = &(struct clk_stm32_composite_cfg) { .gate_id = GATE_PLL1_DIVP, .div_id = DIV_PLL1DIVP, .mux_id = NO_MUX, }, .name = "ck_pll1p", .flags = CLK_SET_RATE_PARENT, .num_parents = 1, .parents = { &ck_pll1_vco }, }; const struct clk_ops clk_stm32_pll1p_div_ops = { .get_rate = clk_stm32_divider_get_rate, }; static struct clk ck_pll1p_div = { .ops = &clk_stm32_pll1p_div_ops, .priv = &(struct clk_stm32_div_cfg) { .div_id = DIV_MPU, }, .name = "ck_pll1p_div", .flags = CLK_SET_RATE_PARENT, .num_parents = 1, .parents = { &ck_pll1p }, }; /* Other PLLs */ static STM32_PLL_VCO(ck_pll2_vco, 2, PARENT(&ck_hsi, &ck_hse), 0, RCC_PLL2CR, GATE_PLL2, MUX_PLL12); static STM32_PLL_VCO(ck_pll3_vco, 3, PARENT(&ck_hsi, &ck_hse, &ck_csi), 0, RCC_PLL3CR, GATE_PLL3, MUX_PLL3); static STM32_PLL_VCO(ck_pll4_vco, 4, PARENT(&ck_hsi, &ck_hse, &ck_csi, &ck_i2sckin), 0, RCC_PLL4CR, GATE_PLL4, MUX_PLL4); static STM32_PLL_OUPUT(ck_pll2p, 1, PARENT(&ck_pll2_vco), 0, GATE_PLL2_DIVP, DIV_PLL2DIVP, NO_MUX); static STM32_PLL_OUPUT(ck_pll2q, 1, PARENT(&ck_pll2_vco), 0, GATE_PLL2_DIVQ, DIV_PLL2DIVQ, NO_MUX); static STM32_PLL_OUPUT(ck_pll2r, 1, PARENT(&ck_pll2_vco), 0, GATE_PLL2_DIVR, DIV_PLL2DIVR, NO_MUX); static STM32_PLL_OUPUT(ck_pll3p, 1, PARENT(&ck_pll3_vco), 0, GATE_PLL3_DIVP, DIV_PLL3DIVP, NO_MUX); static STM32_PLL_OUPUT(ck_pll3q, 1, PARENT(&ck_pll3_vco), 0, GATE_PLL3_DIVQ, DIV_PLL3DIVQ, NO_MUX); static STM32_PLL_OUPUT(ck_pll3r, 1, PARENT(&ck_pll3_vco), 0, GATE_PLL3_DIVR, DIV_PLL3DIVR, NO_MUX); static STM32_PLL_OUPUT(ck_pll4p, 1, PARENT(&ck_pll4_vco), 0, GATE_PLL4_DIVP, DIV_PLL4DIVP, NO_MUX); static STM32_PLL_OUPUT(ck_pll4q, 1, PARENT(&ck_pll4_vco), 0, GATE_PLL4_DIVQ, DIV_PLL4DIVQ, NO_MUX); static STM32_PLL_OUPUT(ck_pll4r, 1, PARENT(&ck_pll4_vco), 0, GATE_PLL4_DIVR, DIV_PLL4DIVR, NO_MUX); /* System clocks */ static struct clk ck_mpu = { .ops = &clk_stm32_mpu_ops, .priv = &(struct clk_stm32_composite_cfg) { .mux_id = MUX_MPU, }, .name = "ck_mpu", .flags = CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT, .num_parents = 4, .parents = { &ck_hsi, &ck_hse, &ck_pll1p, &ck_pll1p_div }, }; static struct clk ck_axi = { .ops = &clk_stm32_axi_ops, .priv = &(struct clk_stm32_composite_cfg) { .mux_id = MUX_AXI, .div_id = DIV_AXI, }, .name = "ck_axi", .flags = CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT, .num_parents = 3, .parents = { &ck_hsi, &ck_hse, &ck_pll2p }, }; static struct clk ck_mlahb = { .ops = &clk_stm32_mlahb_ops, .priv = &(struct clk_stm32_composite_cfg) { .mux_id = MUX_MLAHB, .div_id = DIV_MLAHB, }, .name = "ck_mlahb", .flags = CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT, .num_parents = 4, .parents = { &ck_hsi, &ck_hse, &ck_csi, &ck_pll3p }, }; static STM32_MUX(ck_per, 4, PARENT(&ck_hsi, &ck_csi, &ck_hse, &ck_off), 0, MUX_CKPER); /* Bus clocks */ static STM32_DIVIDER(ck_pclk1, &ck_mlahb, 0, DIV_APB1); static STM32_DIVIDER(ck_pclk2, &ck_mlahb, 0, DIV_APB2); static STM32_DIVIDER(ck_pclk3, &ck_mlahb, 0, DIV_APB3); static STM32_DIVIDER(ck_pclk4, &ck_axi, 0, DIV_APB4); static STM32_DIVIDER(ck_pclk5, &ck_axi, 0, DIV_APB5); static STM32_DIVIDER(ck_pclk6, &ck_mlahb, 0, DIV_APB6); /* Timer Clocks */ static STM32_TIMER(ck_timg1, &ck_pclk1, 0, RCC_APB1DIVR, RCC_TIMG1PRER); static STM32_TIMER(ck_timg2, &ck_pclk2, 0, RCC_APB2DIVR, RCC_TIMG2PRER); static STM32_TIMER(ck_timg3, &ck_pclk6, 0, RCC_APB6DIVR, RCC_TIMG3PRER); /* Peripheral and Kernel Clocks */ static STM32_GATE(ck_ddrc1, &ck_axi, 0, GATE_DDRC1); static STM32_GATE(ck_ddrc1lp, &ck_axi, 0, GATE_DDRC1LP); static STM32_GATE(ck_ddrphyc, &ck_pll2r, 0, GATE_DDRPHYC); static STM32_GATE(ck_ddrphyclp, &ck_pll2r, 0, GATE_DDRPHYCLP); static STM32_GATE(ck_ddrcapb, &ck_pclk4, 0, GATE_DDRCAPB); static STM32_GATE(ck_ddrcapblp, &ck_pclk4, 0, GATE_DDRCAPBLP); static STM32_GATE(ck_axidcg, &ck_axi, 0, GATE_AXIDCG); static STM32_GATE(ck_ddrphycapb, &ck_pclk4, 0, 0); static STM32_GATE(ck_ddrphycapblp, &ck_pclk4, 0, GATE_DDRPHYCAPBLP); static STM32_GATE(ck_syscfg, &ck_pclk3, 0, GATE_SYSCFG); static STM32_GATE(ck_ddrperfm, &ck_pclk4, 0, GATE_DDRPERFM); static STM32_GATE(ck_iwdg2, &ck_pclk4, 0, GATE_IWDG2APB); static STM32_GATE(ck_rtcapb, &ck_pclk5, 0, GATE_RTCAPB); static STM32_GATE(ck_tzc, &ck_pclk5, 0, GATE_TZC); static STM32_GATE(ck_etzpcb, &ck_pclk5, 0, GATE_ETZPC); static STM32_GATE(ck_iwdg1apb, &ck_pclk5, 0, GATE_IWDG1APB); static STM32_GATE(ck_bsec, &ck_pclk5, 0, GATE_BSEC); static STM32_GATE(ck_tim12_k, &ck_timg3, 0, GATE_TIM12); static STM32_GATE(ck_tim15_k, &ck_timg3, 0, GATE_TIM15); static STM32_GATE(ck_gpioa, &ck_mlahb, 0, GATE_GPIOA); static STM32_GATE(ck_gpiob, &ck_mlahb, 0, GATE_GPIOB); static STM32_GATE(ck_gpioc, &ck_mlahb, 0, GATE_GPIOC); static STM32_GATE(ck_gpiod, &ck_mlahb, 0, GATE_GPIOD); static STM32_GATE(ck_gpioe, &ck_mlahb, 0, GATE_GPIOE); static STM32_GATE(ck_gpiof, &ck_mlahb, 0, GATE_GPIOF); static STM32_GATE(ck_gpiog, &ck_mlahb, 0, GATE_GPIOG); static STM32_GATE(ck_gpioh, &ck_mlahb, 0, GATE_GPIOH); static STM32_GATE(ck_gpioi, &ck_mlahb, 0, GATE_GPIOI); static STM32_GATE(ck_pka, &ck_axi, 0, GATE_PKA); static STM32_GATE(ck_cryp1, &ck_pclk5, 0, GATE_CRYP1); static STM32_GATE(ck_hash1, &ck_pclk5, 0, GATE_HASH1); static STM32_GATE(ck_bkpsram, &ck_pclk5, 0, GATE_BKPSRAM); static STM32_GATE(ck_dbg, &ck_axi, 0, GATE_DBGCK); static STM32_GATE(ck_mce, &ck_axi, 0, GATE_MCE); static STM32_GATE(ck_tim2_k, &ck_timg1, 0, GATE_TIM2); static STM32_GATE(ck_tim3_k, &ck_timg1, 0, GATE_TIM3); static STM32_GATE(ck_tim4_k, &ck_timg1, 0, GATE_TIM4); static STM32_GATE(ck_tim5_k, &ck_timg1, 0, GATE_TIM5); static STM32_GATE(ck_tim6_k, &ck_timg1, 0, GATE_TIM6); static STM32_GATE(ck_tim7_k, &ck_timg1, 0, GATE_TIM7); static STM32_GATE(ck_tim13_k, &ck_timg3, 0, GATE_TIM13); static STM32_GATE(ck_tim14_k, &ck_timg3, 0, GATE_TIM14); static STM32_GATE(ck_tim1_k, &ck_timg2, 0, GATE_TIM1); static STM32_GATE(ck_tim8_k, &ck_timg2, 0, GATE_TIM8); static STM32_GATE(ck_tim16_k, &ck_timg3, 0, GATE_TIM16); static STM32_GATE(ck_tim17_k, &ck_timg3, 0, GATE_TIM17); static STM32_GATE(ck_ltdc_px, &ck_pll4q, 0, GATE_LTDC); static STM32_GATE(ck_dma1, &ck_mlahb, 0, GATE_DMA1); static STM32_GATE(ck_dma2, &ck_mlahb, 0, GATE_DMA2); static STM32_GATE(ck_adc1, &ck_mlahb, 0, GATE_ADC1); static STM32_GATE(ck_adc2, &ck_mlahb, 0, GATE_ADC2); static STM32_GATE(ck_mdma, &ck_axi, 0, GATE_MDMA); static STM32_GATE(ck_eth1mac, &ck_axi, 0, GATE_ETH1MAC); static STM32_GATE(ck_usbh, &ck_axi, 0, GATE_USBH); static STM32_GATE(ck_vref, &ck_pclk3, 0, GATE_VREF); static STM32_GATE(ck_tmpsens, &ck_pclk3, 0, GATE_DTS); static STM32_GATE(ck_pmbctrl, &ck_pclk3, 0, GATE_PMBCTRL); static STM32_GATE(ck_hdp, &ck_pclk3, 0, GATE_HDP); static STM32_GATE(ck_stgenro, &ck_pclk4, 0, GATE_STGENRO); static STM32_GATE(ck_dmamux1, &ck_axi, 0, GATE_DMAMUX1); static STM32_GATE(ck_dmamux2, &ck_axi, 0, GATE_DMAMUX2); static STM32_GATE(ck_dma3, &ck_axi, 0, GATE_DMA3); static STM32_GATE(ck_tsc, &ck_axi, 0, GATE_TSC); static STM32_GATE(ck_aximc, &ck_axi, 0, GATE_AXIMC); static STM32_GATE(ck_crc1, &ck_axi, 0, GATE_CRC1); static STM32_GATE(ck_eth1tx, &ck_axi, 0, GATE_ETH1TX); static STM32_GATE(ck_eth1rx, &ck_axi, 0, GATE_ETH1RX); static STM32_GATE(ck_eth2tx, &ck_axi, 0, GATE_ETH2TX); static STM32_GATE(ck_eth2rx, &ck_axi, 0, GATE_ETH2RX); static STM32_GATE(ck_eth2mac, &ck_axi, 0, GATE_ETH2MAC); static STM32_GATE(ck_spi1, &ck_pclk2, 0, GATE_SPI1); static STM32_GATE(ck_spi2, &ck_pclk1, 0, GATE_SPI2); static STM32_GATE(ck_spi3, &ck_pclk1, 0, GATE_SPI3); static STM32_GATE(ck_spi4, &ck_pclk6, 0, GATE_SPI4); static STM32_GATE(ck_spi5, &ck_pclk6, 0, GATE_SPI5); /* Kernel Clocks */ static STM32_KCLK(ck_usbphy_k, 3, PARENT(&ck_hse, &ck_pll4r, &ck_hse_div2), 0, GATE_USBPHY, MUX_USBPHY); static STM32_KCLK(ck_usbo_k, 2, PARENT(&ck_pll4r, &ck_usb_phy_48Mhz), 0, GATE_USBO, MUX_USBO); static STM32_KCLK(ck_stgen_k, 2, PARENT(&ck_hsi, &ck_hse), 0, GATE_STGENC, MUX_STGEN); static STM32_KCLK(ck_usart1_k, 6, PARENT(&ck_pclk6, &ck_pll3q, &ck_hsi, &ck_csi, &ck_pll4q, &ck_hse), 0, GATE_USART1, MUX_UART1); static STM32_KCLK(ck_usart2_k, 6, PARENT(&ck_pclk6, &ck_pll3q, &ck_hsi, &ck_csi, &ck_pll4q, &ck_hse), 0, GATE_USART2, MUX_UART2); static STM32_KCLK(ck_i2c4_k, 4, PARENT(&ck_pclk6, &ck_pll4r, &ck_hsi, &ck_csi), 0, GATE_I2C4, MUX_I2C4); static STM32_KCLK(ck_rtc, 4, PARENT(&ck_off, &ck_lse, &ck_lsi, &ck_hse), 0, GATE_RTCCK, MUX_RTC); static STM32_KCLK(ck_saes_k, 4, PARENT(&ck_axi, &ck_per, &ck_pll4r, &ck_lsi), 0, GATE_SAES, MUX_SAES); static STM32_KCLK(ck_rng1_k, 4, PARENT(&ck_csi, &ck_pll4r, &ck_off, &ck_lsi), 0, GATE_RNG1, MUX_RNG1); static STM32_KCLK(ck_sdmmc1_k, 4, PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_hsi), 0, GATE_SDMMC1, MUX_SDMMC1); static STM32_KCLK(ck_sdmmc2_k, 4, PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_hsi), 0, GATE_SDMMC2, MUX_SDMMC2); static STM32_KCLK(ck_usart3_k, 5, PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_USART3, MUX_UART35); static STM32_KCLK(ck_uart4_k, 5, PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_UART4, MUX_UART4); static STM32_KCLK(ck_uart5_k, 5, PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_UART5, MUX_UART35); static STM32_KCLK(ck_uart7_k, 5, PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_UART7, MUX_UART78); static STM32_KCLK(ck_uart8_k, 5, PARENT(&ck_pclk1, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_UART8, MUX_UART78); static STM32_KCLK(ck_usart6_k, 5, PARENT(&ck_pclk2, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_USART6, MUX_UART6); static STM32_KCLK(ck_fmc_k, 4, PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_per), 0, GATE_FMC, MUX_FMC); static STM32_KCLK(ck_qspi_k, 4, PARENT(&ck_axi, &ck_pll3r, &ck_pll4p, &ck_per), 0, GATE_QSPI, MUX_QSPI); static STM32_KCLK(ck_lptim1_k, 6, PARENT(&ck_pclk1, &ck_pll4p, &ck_pll3q, &ck_lse, &ck_lsi, &ck_per), 0, GATE_LPTIM1, MUX_LPTIM1); static STM32_KCLK(ck_spi2_k, 5, PARENT(&ck_pll4p, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), 0, GATE_SPI2, MUX_SPI23); static STM32_KCLK(ck_spi3_k, 5, PARENT(&ck_pll4p, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), 0, GATE_SPI3, MUX_SPI23); static STM32_KCLK(ck_spdif_k, 3, PARENT(&ck_pll4p, &ck_pll3q, &ck_hsi), 0, GATE_SPDIF, MUX_SPDIF); static STM32_KCLK(ck_spi1_k, 5, PARENT(&ck_pll4p, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), 0, GATE_SPI1, MUX_SPI1); static STM32_KCLK(ck_spi4_k, 6, PARENT(&ck_pclk6, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse, &ck_i2sckin), 0, GATE_SPI4, MUX_SPI4); static STM32_KCLK(ck_spi5_k, 5, PARENT(&ck_pclk6, &ck_pll4q, &ck_hsi, &ck_csi, &ck_hse), 0, GATE_SPI5, MUX_SPI5); static STM32_KCLK(ck_sai1_k, 5, PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), 0, GATE_SAI1, MUX_SAI1); static STM32_KCLK(ck_sai2_k, 6, PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_off, &ck_pll3r), 0, GATE_SAI2, MUX_SAI2); static STM32_KCLK(ck_dfsdm_k, 5, PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), 0, GATE_DFSDM, MUX_SAI1); static STM32_KCLK(ck_fdcan_k, 4, PARENT(&ck_hse, &ck_pll3q, &ck_pll4q, &ck_pll4r), 0, GATE_FDCAN, MUX_FDCAN); static STM32_KCLK(ck_i2c1_k, 4, PARENT(&ck_pclk1, &ck_pll4r, &ck_hsi, &ck_csi), 0, GATE_I2C1, MUX_I2C12); static STM32_KCLK(ck_i2c2_k, 4, PARENT(&ck_pclk1, &ck_pll4r, &ck_hsi, &ck_csi), 0, GATE_I2C2, MUX_I2C12); static STM32_KCLK(ck_adfsdm_k, 5, PARENT(&ck_pll4q, &ck_pll3q, &ck_i2sckin, &ck_per, &ck_pll3r), 0, GATE_ADFSDM, MUX_SAI1); static STM32_KCLK(ck_lptim2_k, 5, PARENT(&ck_pclk3, &ck_pll4q, &ck_per, &ck_lse, &ck_lsi), 0, GATE_LPTIM2, MUX_LPTIM2); static STM32_KCLK(ck_lptim3_k, 5, PARENT(&ck_pclk3, &ck_pll4q, &ck_per, &ck_lse, &ck_lsi), 0, GATE_LPTIM3, MUX_LPTIM3); static STM32_KCLK(ck_lptim4_k, 6, PARENT(&ck_pclk3, &ck_pll4p, &ck_pll3q, &ck_lse, &ck_lsi, &ck_per), 0, GATE_LPTIM4, MUX_LPTIM45); static STM32_KCLK(ck_lptim5_k, 6, PARENT(&ck_pclk3, &ck_pll4p, &ck_pll3q, &ck_lse, &ck_lsi, &ck_per), 0, GATE_LPTIM5, MUX_LPTIM45); static STM32_KCLK(ck_i2c3_k, 4, PARENT(&ck_pclk6, &ck_pll4r, &ck_hsi, &ck_csi), 0, GATE_I2C3, MUX_I2C3); static STM32_KCLK(ck_i2c5_k, 4, PARENT(&ck_pclk6, &ck_pll4r, &ck_hsi, &ck_csi), 0, GATE_I2C5, MUX_I2C5); static STM32_KCLK(ck_dcmipp_k, 4, PARENT(&ck_axi, &ck_pll2q, &ck_pll4p, &ck_per), 0, GATE_DCMIPP, MUX_DCMIPP); static STM32_KCLK(ck_adc1_k, 3, PARENT(&ck_pll4r, &ck_per, &ck_pll3q), 0, GATE_ADC1, MUX_ADC1); static STM32_KCLK(ck_adc2_k, 3, PARENT(&ck_pll4r, &ck_per, &ck_pll3q), 0, GATE_ADC2, MUX_ADC2); static STM32_KCLK(ck_eth1ck_k, 2, PARENT(&ck_pll4p, &ck_pll3q), 0, GATE_ETH1CK, MUX_ETH1); static STM32_KCLK(ck_eth2ck_k, 2, PARENT(&ck_pll4p, &ck_pll3q), 0, GATE_ETH2CK, MUX_ETH2); static STM32_COMPOSITE(ck_mco1, 5, PARENT(&ck_hsi, &ck_hse, &ck_csi, &ck_lsi, &ck_lse), 0, GATE_MCO1, DIV_MCO1, MUX_MCO1); static STM32_COMPOSITE(ck_mco2, 6, PARENT(&ck_mpu, &ck_axi, &ck_mlahb, &ck_pll4p, &ck_hse, &ck_hsi), 0, GATE_MCO2, DIV_MCO2, MUX_MCO2); static STM32_COMPOSITE(ck_trace, 1, PARENT(&ck_axi), 0, GATE_TRACECK, DIV_TRACE, NO_MUX); enum { USB_PHY_48 = STM32MP1_LAST_CLK, PLL1P_DIV, CK_OFF, I2S_CKIN, STM32MP13_ALL_CLK_NB }; static struct clk *stm32mp13_clk_provided[STM32MP13_ALL_CLK_NB] = { [CK_HSE] = &ck_hse, [CK_CSI] = &ck_csi, [CK_LSI] = &ck_lsi, [CK_LSE] = &ck_lse, [CK_HSI] = &ck_hsi, [CK_HSE_DIV2] = &ck_hse_div2, [PLL1] = &ck_pll1_vco, [PLL2] = &ck_pll2_vco, [PLL3] = &ck_pll3_vco, [PLL4] = &ck_pll4_vco, [PLL1_P] = &ck_pll1p, [PLL2_P] = &ck_pll2p, [PLL2_Q] = &ck_pll2q, [PLL2_R] = &ck_pll2r, [PLL3_P] = &ck_pll3p, [PLL3_Q] = &ck_pll3q, [PLL3_R] = &ck_pll3r, [PLL4_P] = &ck_pll4p, [PLL4_Q] = &ck_pll4q, [PLL4_R] = &ck_pll4r, [PLL1P_DIV] = &ck_pll1p_div, [CK_MPU] = &ck_mpu, [CK_AXI] = &ck_axi, [CK_MLAHB] = &ck_mlahb, [CK_PER] = &ck_per, [PCLK1] = &ck_pclk1, [PCLK2] = &ck_pclk2, [PCLK3] = &ck_pclk3, [PCLK4] = &ck_pclk4, [PCLK5] = &ck_pclk5, [PCLK6] = &ck_pclk6, [CK_TIMG1] = &ck_timg1, [CK_TIMG2] = &ck_timg2, [CK_TIMG3] = &ck_timg3, [DDRC1] = &ck_ddrc1, [DDRC1LP] = &ck_ddrc1lp, [DDRPHYC] = &ck_ddrphyc, [DDRPHYCLP] = &ck_ddrphyclp, [DDRCAPB] = &ck_ddrcapb, [DDRCAPBLP] = &ck_ddrcapblp, [AXIDCG] = &ck_axidcg, [DDRPHYCAPB] = &ck_ddrphycapb, [DDRPHYCAPBLP] = &ck_ddrphycapblp, [SYSCFG] = &ck_syscfg, [DDRPERFM] = &ck_ddrperfm, [IWDG2] = &ck_iwdg2, [USBPHY_K] = &ck_usbphy_k, [USBO_K] = &ck_usbo_k, [RTCAPB] = &ck_rtcapb, [TZC] = &ck_tzc, [TZPC] = &ck_etzpcb, [IWDG1] = &ck_iwdg1apb, [BSEC] = &ck_bsec, [STGEN_K] = &ck_stgen_k, [USART1_K] = &ck_usart1_k, [USART2_K] = &ck_usart2_k, [I2C4_K] = &ck_i2c4_k, [TIM12_K] = &ck_tim12_k, [TIM15_K] = &ck_tim15_k, [RTC] = &ck_rtc, [GPIOA] = &ck_gpioa, [GPIOB] = &ck_gpiob, [GPIOC] = &ck_gpioc, [GPIOD] = &ck_gpiod, [GPIOE] = &ck_gpioe, [GPIOF] = &ck_gpiof, [GPIOG] = &ck_gpiog, [GPIOH] = &ck_gpioh, [GPIOI] = &ck_gpioi, [PKA] = &ck_pka, [SAES_K] = &ck_saes_k, [CRYP1] = &ck_cryp1, [HASH1] = &ck_hash1, [RNG1_K] = &ck_rng1_k, [BKPSRAM] = &ck_bkpsram, [SDMMC1_K] = &ck_sdmmc1_k, [SDMMC2_K] = &ck_sdmmc2_k, [CK_DBG] = &ck_dbg, [MCE] = &ck_mce, [TIM2_K] = &ck_tim2_k, [TIM3_K] = &ck_tim3_k, [TIM4_K] = &ck_tim4_k, [TIM5_K] = &ck_tim5_k, [TIM6_K] = &ck_tim6_k, [TIM7_K] = &ck_tim7_k, [TIM13_K] = &ck_tim13_k, [TIM14_K] = &ck_tim14_k, [TIM1_K] = &ck_tim1_k, [TIM8_K] = &ck_tim8_k, [TIM16_K] = &ck_tim16_k, [TIM17_K] = &ck_tim17_k, [LTDC_PX] = &ck_ltdc_px, [DMA1] = &ck_dma1, [DMA2] = &ck_dma2, [ADC1] = &ck_adc1, [ADC2] = &ck_adc2, [MDMA] = &ck_mdma, [ETH1MAC] = &ck_eth1mac, [USBH] = &ck_usbh, [VREF] = &ck_vref, [TMPSENS] = &ck_tmpsens, [PMBCTRL] = &ck_pmbctrl, [HDP] = &ck_hdp, [STGENRO] = &ck_stgenro, [DMAMUX1] = &ck_dmamux1, [DMAMUX2] = &ck_dmamux2, [DMA3] = &ck_dma3, [TSC] = &ck_tsc, [AXIMC] = &ck_aximc, [CRC1] = &ck_crc1, [ETH1TX] = &ck_eth1tx, [ETH1RX] = &ck_eth1rx, [ETH2TX] = &ck_eth2tx, [ETH2RX] = &ck_eth2rx, [ETH2MAC] = &ck_eth2mac, [USART3_K] = &ck_usart3_k, [UART4_K] = &ck_uart4_k, [UART5_K] = &ck_uart5_k, [UART7_K] = &ck_uart7_k, [UART8_K] = &ck_uart8_k, [USART6_K] = &ck_usart6_k, [FMC_K] = &ck_fmc_k, [QSPI_K] = &ck_qspi_k, [LPTIM1_K] = &ck_lptim1_k, [SPI2_K] = &ck_spi2_k, [SPI3_K] = &ck_spi3_k, [SPDIF_K] = &ck_spdif_k, [SPI1_K] = &ck_spi1_k, [SPI4_K] = &ck_spi4_k, [SPI5_K] = &ck_spi5_k, [SAI1_K] = &ck_sai1_k, [SAI2_K] = &ck_sai2_k, [DFSDM_K] = &ck_dfsdm_k, [FDCAN_K] = &ck_fdcan_k, [I2C1_K] = &ck_i2c1_k, [I2C2_K] = &ck_i2c2_k, [ADFSDM_K] = &ck_adfsdm_k, [LPTIM2_K] = &ck_lptim2_k, [LPTIM3_K] = &ck_lptim3_k, [LPTIM4_K] = &ck_lptim4_k, [LPTIM5_K] = &ck_lptim5_k, [I2C3_K] = &ck_i2c3_k, [I2C5_K] = &ck_i2c5_k, [DCMIPP_K] = &ck_dcmipp_k, [ADC1_K] = &ck_adc1_k, [ADC2_K] = &ck_adc2_k, [ETH1CK_K] = &ck_eth1ck_k, [ETH2CK_K] = &ck_eth2ck_k, [SPI1] = &ck_spi1, [SPI2] = &ck_spi2, [SPI3] = &ck_spi3, [SPI4] = &ck_spi4, [SPI5] = &ck_spi5, [CK_MCO1] = &ck_mco1, [CK_MCO2] = &ck_mco2, [CK_TRACE] = &ck_trace, [CK_OFF] = &ck_off, [USB_PHY_48] = &ck_usb_phy_48Mhz, [I2S_CKIN] = &ck_i2sckin, }; static bool clk_stm32_clock_is_critical(struct clk *clk __maybe_unused) { struct clk *clk_criticals[] = { &ck_hsi, &ck_hse, &ck_csi, &ck_lsi, &ck_lse, &ck_pll2r, &ck_mpu, &ck_ddrc1, &ck_ddrc1lp, &ck_ddrphyc, &ck_ddrphyclp, &ck_ddrcapb, &ck_ddrcapblp, &ck_axidcg, &ck_ddrphycapb, &ck_ddrphycapblp, &ck_rtcapb, &ck_tzc, &ck_etzpcb, &ck_iwdg1apb, &ck_bsec, &ck_stgen_k, &ck_bkpsram, &ck_mce, &ck_mco1, &ck_rng1_k, &ck_mlahb, }; size_t i = 0; for (i = 0; i < ARRAY_SIZE(clk_criticals); i++) { struct clk *clk_critical = clk_criticals[i]; if (clk == clk_critical) return true; } return false; } static void clk_stm32_init_oscillators(const void *fdt, int node) { size_t i = 0; const char *name[6] = { "clk-hse", "clk-hsi", "clk-lse", "clk-lsi", "clk-csi", "clk-i2sin" }; struct clk *clks[6] = { &ck_hse, &ck_hsi, &ck_lse, &ck_lsi, &ck_csi, &ck_i2sckin }; for (i = 0; i < ARRAY_SIZE(clks); i++) { struct clk *clk = NULL; clk_dt_get_by_name(fdt, node, name[i], &clk); clks[i]->parents[0] = clk; } } static struct stm32_pll_dt_cfg mp13_pll[PLL_NB]; static struct stm32_clk_opp_dt_cfg mp13_clk_opp; static struct stm32_osci_dt_cfg mp13_osci[NB_OSCILLATOR]; static uint32_t mp13_clksrc[MUX_NB]; static uint32_t mp13_clkdiv[DIV_NB]; static struct stm32_clk_platdata stm32mp13_clock_pdata = { .osci = mp13_osci, .nosci = NB_OSCILLATOR, .pll = mp13_pll, .opp = &mp13_clk_opp, .npll = PLL_NB, .clksrc = mp13_clksrc, .nclksrc = MUX_NB, .clkdiv = mp13_clkdiv, .nclkdiv = DIV_NB, }; static struct clk_stm32_priv stm32mp13_clock_data = { .muxes = parent_mp13, .nb_muxes = ARRAY_SIZE(parent_mp13), .gates = gates_mp13, .nb_gates = ARRAY_SIZE(gates_mp13), .div = dividers_mp13, .nb_div = ARRAY_SIZE(dividers_mp13), .pdata = &stm32mp13_clock_pdata, .nb_clk_refs = STM32MP13_ALL_CLK_NB, .clk_refs = stm32mp13_clk_provided, .is_critical = clk_stm32_clock_is_critical, }; static TEE_Result stm32mp13_clk_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; int fdt_rc = 0; int rc = 0; struct clk_stm32_priv *priv = &stm32mp13_clock_data; struct stm32_clk_platdata *pdata = &stm32mp13_clock_pdata; fdt_rc = stm32_clk_parse_fdt(fdt, node, pdata); if (fdt_rc) { EMSG("Failed to parse clock node: %d", fdt_rc); return TEE_ERROR_GENERIC; } res = clk_stm32_init(priv, stm32_rcc_base()); if (res) return res; rc = stm32mp1_init_clock_tree(priv, pdata); if (rc) return TEE_ERROR_GENERIC; clk_stm32_init_oscillators(fdt, node); stm32mp_clk_provider_probe_final(fdt, node, priv); return TEE_SUCCESS; } CLK_DT_DECLARE(stm32mp13_clk, "st,stm32mp13-rcc", stm32mp13_clk_probe); optee_os-4.3.0/core/drivers/clk/clk-stm32mp15.c000066400000000000000000001147011464416617300211200ustar00rootroot00000000000000// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0+) /* * Copyright (C) 2018-2022, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Identifiers for root oscillators */ enum stm32mp_osc_id { OSC_HSI, OSC_HSE, OSC_CSI, OSC_LSI, OSC_LSE, OSC_I2S_CKIN, OSC_USB_PHY_48, NB_OSC, _UNKNOWN_OSC_ID = 0xffU }; /* Identifiers for parent clocks */ enum stm32mp1_parent_id { _HSI, _HSE, _CSI, _LSI, _LSE, _I2S_CKIN, _USB_PHY_48, _HSI_KER, _HSE_KER, _HSE_KER_DIV2, _HSE_RTC, _CSI_KER, _PLL1_P, _PLL1_Q, _PLL1_R, _PLL2_P, _PLL2_Q, _PLL2_R, _PLL3_P, _PLL3_Q, _PLL3_R, _PLL4_P, _PLL4_Q, _PLL4_R, _ACLK, _PCLK1, _PCLK2, _PCLK3, _PCLK4, _PCLK5, _HCLK5, _HCLK6, _HCLK2, _CK_PER, _CK_MPU, _CK_MCU, _PARENT_NB, _UNKNOWN_ID = 0xff, }; /* * Identifiers for parent clock selectors. * This enum lists only the parent clocks we are interested in. */ enum stm32mp1_parent_sel { _STGEN_SEL, _I2C35_SEL, _I2C46_SEL, _SPI6_SEL, _USART1_SEL, _RNG1_SEL, _UART6_SEL, _UART24_SEL, _UART35_SEL, _UART78_SEL, _AXISS_SEL, _MCUSS_SEL, _USBPHY_SEL, _USBO_SEL, _RTC_SEL, _MPU_SEL, _PARENT_SEL_NB, _UNKNOWN_SEL = 0xff, }; static const uint8_t parent_id_clock_id[_PARENT_NB] = { [_HSE] = CK_HSE, [_HSI] = CK_HSI, [_CSI] = CK_CSI, [_LSE] = CK_LSE, [_LSI] = CK_LSI, [_I2S_CKIN] = _UNKNOWN_ID, [_USB_PHY_48] = _UNKNOWN_ID, [_HSI_KER] = CK_HSI, [_HSE_KER] = CK_HSE, [_HSE_KER_DIV2] = CK_HSE_DIV2, [_HSE_RTC] = _UNKNOWN_ID, [_CSI_KER] = CK_CSI, [_PLL1_P] = PLL1_P, [_PLL1_Q] = PLL1_Q, [_PLL1_R] = PLL1_R, [_PLL2_P] = PLL2_P, [_PLL2_Q] = PLL2_Q, [_PLL2_R] = PLL2_R, [_PLL3_P] = PLL3_P, [_PLL3_Q] = PLL3_Q, [_PLL3_R] = PLL3_R, [_PLL4_P] = PLL4_P, [_PLL4_Q] = PLL4_Q, [_PLL4_R] = PLL4_R, [_ACLK] = CK_AXI, [_PCLK1] = CK_AXI, [_PCLK2] = CK_AXI, [_PCLK3] = CK_AXI, [_PCLK4] = CK_AXI, [_PCLK5] = CK_AXI, [_HCLK5] = CK_AXI, [_HCLK6] = CK_AXI, [_HCLK2] = CK_AXI, [_CK_PER] = CK_PER, [_CK_MPU] = CK_MPU, [_CK_MCU] = CK_MCU, }; static enum stm32mp1_parent_id osc_id2parent_id(enum stm32mp_osc_id osc_id) { assert(osc_id >= OSC_HSI && osc_id < NB_OSC); COMPILE_TIME_ASSERT((int)OSC_HSI == (int)_HSI && (int)OSC_HSE == (int)_HSE && (int)OSC_CSI == (int)_CSI && (int)OSC_LSI == (int)_LSI && (int)OSC_LSE == (int)_LSE && (int)OSC_I2S_CKIN == (int)_I2S_CKIN && (int)OSC_USB_PHY_48 == (int)_USB_PHY_48); return (enum stm32mp1_parent_id)osc_id; } static enum stm32mp1_parent_id clock_id2parent_id(unsigned long id) { size_t n = 0; COMPILE_TIME_ASSERT(STM32MP1_LAST_CLK < _UNKNOWN_ID); for (n = 0; n < ARRAY_SIZE(parent_id_clock_id); n++) if (parent_id_clock_id[n] == id) return (enum stm32mp1_parent_id)n; return _UNKNOWN_ID; } /* Identifiers for PLLs and their configuration resources */ enum stm32mp1_pll_id { _PLL1, _PLL2, _PLL3, _PLL4, _PLL_NB }; enum stm32mp1_div_id { _DIV_P, _DIV_Q, _DIV_R, _DIV_NB, }; enum stm32mp1_plltype { PLL_800, PLL_1600, PLL_TYPE_NB }; /* * Clock generic gates clocks which state is controlled by a single RCC bit * * @offset: RCC register byte offset from RCC base where clock is controlled * @bit: Bit position in the RCC 32bit register * @clock_id: Identifier used for the clock in the clock driver API * @set_clr: Non-null if and only-if RCC register is a CLEAR/SET register * (CLEAR register is at offset RCC_MP_ENCLRR_OFFSET from SET register) * @secure: One of N_S or SEC, defined below * @sel: _UNKNOWN_ID (fixed parent) or reference to parent clock selector * (8bit storage of ID from enum stm32mp1_parent_sel) * @fixed: _UNKNOWN_ID (selectable paranet) or reference to parent clock * (8bit storage of ID from enum stm32mp1_parent_id) */ struct stm32mp1_clk_gate { uint16_t offset; uint8_t bit; uint8_t clock_id; uint8_t set_clr; uint8_t secure; uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ }; /* Parent clock selection: select register info, parent clocks references */ struct stm32mp1_clk_sel { uint16_t offset; uint8_t src; uint8_t msk; uint8_t nb_parent; const uint8_t *parent; }; #define REFCLK_SIZE 4 /* PLL control: type, control register offsets, up-to-4 selectable parent */ struct stm32mp1_clk_pll { enum stm32mp1_plltype plltype; uint16_t rckxselr; uint16_t pllxcfgr1; uint16_t pllxcfgr2; uint16_t pllxfracr; uint16_t pllxcr; uint16_t pllxcsgr; enum stm32mp_osc_id refclk[REFCLK_SIZE]; }; #define N_S 0 /* Non-secure can access RCC interface */ #define SEC 1 /* RCC[TZEN] protects RCC interface */ /* Clocks with selectable source and not set/clr register access */ #define _CLK_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ { \ .offset = (_offset), \ .bit = (_bit), \ .clock_id = (_clock_id), \ .set_clr = 0, \ .secure = (_sec), \ .sel = (_parent_sel), \ .fixed = _UNKNOWN_ID, \ } /* Clocks with fixed source and not set/clr register access */ #define _CLK_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ { \ .offset = (_offset), \ .bit = (_bit), \ .clock_id = (_clock_id), \ .set_clr = 0, \ .secure = (_sec), \ .sel = _UNKNOWN_SEL, \ .fixed = (_parent), \ } /* Clocks with selectable source and set/clr register access */ #define _CLK_SC_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ { \ .offset = (_offset), \ .bit = (_bit), \ .clock_id = (_clock_id), \ .set_clr = 1, \ .secure = (_sec), \ .sel = (_parent_sel), \ .fixed = _UNKNOWN_ID, \ } /* Clocks with fixed source and set/clr register access */ #define _CLK_SC_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ { \ .offset = (_offset), \ .bit = (_bit), \ .clock_id = (_clock_id), \ .set_clr = 1, \ .secure = (_sec), \ .sel = _UNKNOWN_SEL, \ .fixed = (_parent), \ } /* * Clocks with selectable source and set/clr register access * and enable bit position defined by a label (argument _bit) */ #define _CLK_SC2_SELEC(_sec, _offset, _bit, _clock_id, _parent_sel) \ { \ .offset = (_offset), \ .clock_id = (_clock_id), \ .bit = _offset ## _ ## _bit ## _POS, \ .set_clr = 1, \ .secure = (_sec), \ .sel = (_parent_sel), \ .fixed = _UNKNOWN_ID, \ } #define _CLK_SC2_FIXED(_sec, _offset, _bit, _clock_id, _parent) \ { \ .offset = (_offset), \ .clock_id = (_clock_id), \ .bit = _offset ## _ ## _bit ## _POS, \ .set_clr = 1, \ .secure = (_sec), \ .sel = _UNKNOWN_SEL, \ .fixed = (_parent), \ } #define _CLK_PARENT(idx, _offset, _src, _mask, _parent) \ [(idx)] = { \ .offset = (_offset), \ .src = (_src), \ .msk = (_mask), \ .parent = (_parent), \ .nb_parent = ARRAY_SIZE(_parent) \ } #define _CLK_PLL(_idx, _type, _off1, _off2, _off3, _off4, \ _off5, _off6, _p1, _p2, _p3, _p4) \ [(_idx)] = { \ .plltype = (_type), \ .rckxselr = (_off1), \ .pllxcfgr1 = (_off2), \ .pllxcfgr2 = (_off3), \ .pllxfracr = (_off4), \ .pllxcr = (_off5), \ .pllxcsgr = (_off6), \ .refclk[0] = (_p1), \ .refclk[1] = (_p2), \ .refclk[2] = (_p3), \ .refclk[3] = (_p4), \ } #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, SPI6EN, SPI6_K, _SPI6_SEL), _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C4EN, I2C4_K, _I2C46_SEL), _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, I2C6EN, I2C6_K, _I2C46_SEL), _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, USART1EN, USART1_K, _USART1_SEL), _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, RTCAPBEN, RTCAPB, _PCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC1EN, TZC1, _PCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZC2EN, TZC2, _PCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, TZPCEN, TZPC, _PCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, IWDG1APBEN, IWDG1, _PCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_APB5ENSETR, BSECEN, BSEC, _PCLK5), _CLK_SC2_SELEC(SEC, RCC_MP_APB5ENSETR, STGENEN, STGEN_K, _STGEN_SEL), _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, GPIOZEN, GPIOZ, _HCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, CRYP1EN, CRYP1, _HCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, HASH1EN, HASH1, _HCLK5), _CLK_SC2_SELEC(SEC, RCC_MP_AHB5ENSETR, RNG1EN, RNG1_K, _RNG1_SEL), _CLK_SC2_FIXED(SEC, RCC_MP_AHB5ENSETR, BKPSRAMEN, BKPSRAM, _HCLK5), _CLK_SC2_FIXED(SEC, RCC_MP_TZAHB6ENSETR, MDMA, MDMA, _HCLK6), _CLK_SELEC(SEC, RCC_BDCR, RCC_BDCR_RTCCKEN_POS, RTC, _RTC_SEL), /* Non-secure clocks */ #ifdef CFG_WITH_NSEC_I2CS _CLK_SC2_SELEC(N_S, RCC_MP_APB1ENSETR, I2C5EN, I2C5_K, _I2C35_SEL), #endif #ifdef CFG_WITH_NSEC_GPIOS _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_ID), _CLK_SC_FIXED(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_ID), #endif _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), #ifdef CFG_WITH_NSEC_UARTS _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), #endif _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), #ifdef CFG_WITH_NSEC_UARTS _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), #endif _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), }; DECLARE_KEEP_PAGER(stm32mp1_clk_gate); const uint8_t stm32mp1_clk_on[] = { CK_HSE, CK_CSI, CK_LSI, CK_LSE, CK_HSI, CK_HSE_DIV2, PLL1_P, PLL1_Q, PLL1_R, PLL2_P, PLL2_Q, PLL2_R, PLL3_P, PLL3_Q, PLL3_R, CK_AXI, CK_MPU, CK_MCU, }; /* Parents for secure aware clocks in the xxxSELR value ordering */ static const uint8_t stgen_parents[] = { _HSI_KER, _HSE_KER }; #ifdef CFG_WITH_NSEC_I2CS static const uint8_t i2c35_parents[] = { _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER }; #endif static const uint8_t i2c46_parents[] = { _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER }; static const uint8_t spi6_parents[] = { _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q }; static const uint8_t usart1_parents[] = { _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER }; static const uint8_t rng1_parents[] = { _CSI, _PLL4_R, _LSE, _LSI }; static const uint8_t mpu_parents[] = { _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ }; /* Parents for (some) non-secure clocks */ #ifdef CFG_WITH_NSEC_UARTS static const uint8_t uart6_parents[] = { _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER }; static const uint8_t uart234578_parents[] = { _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER }; #endif static const uint8_t axiss_parents[] = { _HSI, _HSE, _PLL2_P }; static const uint8_t mcuss_parents[] = { _HSI, _HSE, _CSI, _PLL3_P }; static const uint8_t rtc_parents[] = { _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC }; static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { /* Secure aware clocks */ _CLK_PARENT(_STGEN_SEL, RCC_STGENCKSELR, 0, 0x3, stgen_parents), _CLK_PARENT(_I2C46_SEL, RCC_I2C46CKSELR, 0, 0x7, i2c46_parents), _CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents), _CLK_PARENT(_USART1_SEL, RCC_UART1CKSELR, 0, 0x7, usart1_parents), _CLK_PARENT(_RNG1_SEL, RCC_RNG1CKSELR, 0, 0x3, rng1_parents), _CLK_PARENT(_RTC_SEL, RCC_BDCR, 16, 0x3, rtc_parents), _CLK_PARENT(_MPU_SEL, RCC_MPCKSELR, 0, 0x3, mpu_parents), /* Always non-secure clocks (maybe used in some way in secure world) */ #ifdef CFG_WITH_NSEC_I2CS _CLK_PARENT(_I2C35_SEL, RCC_I2C35CKSELR, 0, 0x7, i2c35_parents), #endif #ifdef CFG_WITH_NSEC_UARTS _CLK_PARENT(_UART6_SEL, RCC_UART6CKSELR, 0, 0x7, uart6_parents), _CLK_PARENT(_UART24_SEL, RCC_UART24CKSELR, 0, 0x7, uart234578_parents), _CLK_PARENT(_UART35_SEL, RCC_UART35CKSELR, 0, 0x7, uart234578_parents), _CLK_PARENT(_UART78_SEL, RCC_UART78CKSELR, 0, 0x7, uart234578_parents), #endif _CLK_PARENT(_AXISS_SEL, RCC_ASSCKSELR, 0, 0x3, axiss_parents), _CLK_PARENT(_MCUSS_SEL, RCC_MSSCKSELR, 0, 0x3, mcuss_parents), }; /* PLLNCFGR2 register divider by output */ static const uint8_t pllncfgr2[_DIV_NB] = { [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, }; static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { _CLK_PLL(_PLL1, PLL_1600, RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, OSC_HSI, OSC_HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), _CLK_PLL(_PLL2, PLL_1600, RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, OSC_HSI, OSC_HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), _CLK_PLL(_PLL3, PLL_800, RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, OSC_HSI, OSC_HSE, OSC_CSI, _UNKNOWN_OSC_ID), _CLK_PLL(_PLL4, PLL_800, RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, OSC_HSI, OSC_HSE, OSC_CSI, OSC_I2S_CKIN), }; /* Prescaler table lookups for clock computation */ /* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ static const uint8_t stm32mp1_mcu_div[16] = { 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 }; /* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ #define stm32mp1_mpu_div stm32mp1_mpu_apbx_div #define stm32mp1_apbx_div stm32mp1_mpu_apbx_div static const uint8_t stm32mp1_mpu_apbx_div[8] = { 0, 1, 2, 3, 4, 4, 4, 4 }; /* div = /1 /2 /3 /4 */ static const uint8_t stm32mp1_axi_div[8] = { 1, 2, 3, 4, 4, 4, 4, 4 }; static const char __maybe_unused *const stm32mp1_clk_parent_name[_PARENT_NB] = { [_HSI] = "HSI", [_HSE] = "HSE", [_CSI] = "CSI", [_LSI] = "LSI", [_LSE] = "LSE", [_I2S_CKIN] = "I2S_CKIN", [_HSI_KER] = "HSI_KER", [_HSE_KER] = "HSE_KER", [_HSE_KER_DIV2] = "HSE_KER_DIV2", [_HSE_RTC] = "HSE_RTC", [_CSI_KER] = "CSI_KER", [_PLL1_P] = "PLL1_P", [_PLL1_Q] = "PLL1_Q", [_PLL1_R] = "PLL1_R", [_PLL2_P] = "PLL2_P", [_PLL2_Q] = "PLL2_Q", [_PLL2_R] = "PLL2_R", [_PLL3_P] = "PLL3_P", [_PLL3_Q] = "PLL3_Q", [_PLL3_R] = "PLL3_R", [_PLL4_P] = "PLL4_P", [_PLL4_Q] = "PLL4_Q", [_PLL4_R] = "PLL4_R", [_ACLK] = "ACLK", [_PCLK1] = "PCLK1", [_PCLK2] = "PCLK2", [_PCLK3] = "PCLK3", [_PCLK4] = "PCLK4", [_PCLK5] = "PCLK5", [_HCLK2] = "HCLK2", [_HCLK5] = "HCLK5", [_HCLK6] = "HCLK6", [_CK_PER] = "CK_PER", [_CK_MPU] = "CK_MPU", [_CK_MCU] = "CK_MCU", [_USB_PHY_48] = "USB_PHY_48", }; /* * Oscillator frequency in Hz. This array shall be initialized * according to platform. */ static unsigned long stm32mp1_osc[NB_OSC]; static unsigned long osc_frequency(enum stm32mp_osc_id idx) { if (idx >= ARRAY_SIZE(stm32mp1_osc)) { DMSG("clk id %d not found", idx); return 0; } return stm32mp1_osc[idx]; } static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) { return &stm32mp1_clk_gate[idx]; } static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) { return &stm32mp1_clk_sel[idx]; } static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) { return &stm32mp1_clk_pll[idx]; } static int stm32mp1_clk_get_gated_id(unsigned long id) { unsigned int i = 0; for (i = 0; i < NB_GATES; i++) if (gate_ref(i)->clock_id == id) return i; DMSG("clk id %lu not found", id); return -1; } static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) { return (enum stm32mp1_parent_sel)gate_ref(i)->sel; } static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) { return (enum stm32mp1_parent_id)gate_ref(i)->fixed; } static int stm32mp1_clk_get_parent(unsigned long id) { const struct stm32mp1_clk_sel *sel = NULL; enum stm32mp1_parent_id parent_id = 0; uint32_t p_sel = 0; int i = 0; enum stm32mp1_parent_id p = _UNKNOWN_ID; enum stm32mp1_parent_sel s = _UNKNOWN_SEL; vaddr_t rcc_base = stm32_rcc_base(); parent_id = clock_id2parent_id(id); if (parent_id != _UNKNOWN_ID) return (int)parent_id; i = stm32mp1_clk_get_gated_id(id); if (i < 0) panic(); p = stm32mp1_clk_get_fixed_parent(i); if (p < _PARENT_NB) return (int)p; s = stm32mp1_clk_get_sel(i); if (s == _UNKNOWN_SEL) return -1; if (s >= _PARENT_SEL_NB) panic(); sel = clk_sel_ref(s); p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & sel->msk; if (p_sel < sel->nb_parent) return (int)sel->parent[p_sel]; DMSG("No parent selected for clk %lu", id); return -1; } static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) { uint32_t selr = io_read32(stm32_rcc_base() + pll->rckxselr); uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; return osc_frequency(pll->refclk[src]); } /* * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) */ static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) { unsigned long refclk = 0; unsigned long fvco = 0; uint32_t cfgr1 = 0; uint32_t fracr = 0; uint32_t divm = 0; uint32_t divn = 0; cfgr1 = io_read32(stm32_rcc_base() + pll->pllxcfgr1); fracr = io_read32(stm32_rcc_base() + pll->pllxfracr); divm = (cfgr1 & RCC_PLLNCFGR1_DIVM_MASK) >> RCC_PLLNCFGR1_DIVM_SHIFT; divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; refclk = stm32mp1_pll_get_fref(pll); /* * With FRACV : * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) * Without FRACV * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) */ if (fracr & RCC_PLLNFRACR_FRACLE) { unsigned long long numerator = 0; unsigned long long denominator = 0; uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> RCC_PLLNFRACR_FRACV_SHIFT; numerator = (((unsigned long long)divn + 1U) << 13) + fracv; numerator = refclk * numerator; denominator = ((unsigned long long)divm + 1U) << 13; fvco = (unsigned long)(numerator / denominator); } else { fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); } return fvco; } static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, enum stm32mp1_div_id div_id) { const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); unsigned long dfout = 0; uint32_t cfgr2 = 0; uint32_t divy = 0; if (div_id >= _DIV_NB) return 0; cfgr2 = io_read32(stm32_rcc_base() + pll->pllxcfgr2); divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); return dfout; } static unsigned long get_clock_rate(enum stm32mp1_parent_id p) { uint32_t reg = 0; unsigned long clock = 0; vaddr_t rcc_base = stm32_rcc_base(); switch (p) { case _CK_MPU: /* MPU sub system */ reg = io_read32(rcc_base + RCC_MPCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_MPCKSELR_HSI: clock = osc_frequency(OSC_HSI); break; case RCC_MPCKSELR_HSE: clock = osc_frequency(OSC_HSE); break; case RCC_MPCKSELR_PLL: clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); break; case RCC_MPCKSELR_PLL_MPUDIV: reg = io_read32(rcc_base + RCC_MPCKDIVR); if (reg & RCC_MPUDIV_MASK) clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P) >> stm32mp1_mpu_div[reg & RCC_MPUDIV_MASK]; else clock = 0; break; default: break; } break; /* AXI sub system */ case _ACLK: case _HCLK2: case _HCLK5: case _HCLK6: case _PCLK4: case _PCLK5: reg = io_read32(rcc_base + RCC_ASSCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_ASSCKSELR_HSI: clock = osc_frequency(OSC_HSI); break; case RCC_ASSCKSELR_HSE: clock = osc_frequency(OSC_HSE); break; case RCC_ASSCKSELR_PLL: clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); break; default: break; } /* System clock divider */ reg = io_read32(rcc_base + RCC_AXIDIVR); clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; switch (p) { case _PCLK4: reg = io_read32(rcc_base + RCC_APB4DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; case _PCLK5: reg = io_read32(rcc_base + RCC_APB5DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; default: break; } break; /* MCU sub system */ case _CK_MCU: case _PCLK1: case _PCLK2: case _PCLK3: reg = io_read32(rcc_base + RCC_MSSCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_MSSCKSELR_HSI: clock = osc_frequency(OSC_HSI); break; case RCC_MSSCKSELR_HSE: clock = osc_frequency(OSC_HSE); break; case RCC_MSSCKSELR_CSI: clock = osc_frequency(OSC_CSI); break; case RCC_MSSCKSELR_PLL: clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); break; default: break; } /* MCU clock divider */ reg = io_read32(rcc_base + RCC_MCUDIVR); clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; switch (p) { case _PCLK1: reg = io_read32(rcc_base + RCC_APB1DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; case _PCLK2: reg = io_read32(rcc_base + RCC_APB2DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; case _PCLK3: reg = io_read32(rcc_base + RCC_APB3DIVR); clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; break; case _CK_MCU: default: break; } break; case _CK_PER: reg = io_read32(rcc_base + RCC_CPERCKSELR); switch (reg & RCC_SELR_SRC_MASK) { case RCC_CPERCKSELR_HSI: clock = osc_frequency(OSC_HSI); break; case RCC_CPERCKSELR_HSE: clock = osc_frequency(OSC_HSE); break; case RCC_CPERCKSELR_CSI: clock = osc_frequency(OSC_CSI); break; default: break; } break; case _HSI: case _HSI_KER: clock = osc_frequency(OSC_HSI); break; case _CSI: case _CSI_KER: clock = osc_frequency(OSC_CSI); break; case _HSE: case _HSE_KER: clock = osc_frequency(OSC_HSE); break; case _HSE_KER_DIV2: clock = osc_frequency(OSC_HSE) >> 1; break; case _HSE_RTC: clock = osc_frequency(OSC_HSE); clock /= (io_read32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1; break; case _LSI: clock = osc_frequency(OSC_LSI); break; case _LSE: clock = osc_frequency(OSC_LSE); break; /* PLL */ case _PLL1_P: clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); break; case _PLL1_Q: clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); break; case _PLL1_R: clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); break; case _PLL2_P: clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); break; case _PLL2_Q: clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); break; case _PLL2_R: clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); break; case _PLL3_P: clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); break; case _PLL3_Q: clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); break; case _PLL3_R: clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); break; case _PLL4_P: clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); break; case _PLL4_Q: clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); break; case _PLL4_R: clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); break; /* Other */ case _USB_PHY_48: clock = osc_frequency(OSC_USB_PHY_48); break; default: break; } return clock; } static void __clk_enable(const struct stm32mp1_clk_gate *gate) { vaddr_t base = stm32_rcc_base(); uint32_t bit = BIT(gate->bit); if (gate->set_clr) io_write32(base + gate->offset, bit); else io_setbits32_stm32shregs(base + gate->offset, bit); FMSG("Clock %u has been enabled", gate->clock_id); } static void __clk_disable(const struct stm32mp1_clk_gate *gate) { vaddr_t base = stm32_rcc_base(); uint32_t bit = BIT(gate->bit); if (gate->set_clr) io_write32(base + gate->offset + RCC_MP_ENCLRR_OFFSET, bit); else io_clrbits32_stm32shregs(base + gate->offset, bit); FMSG("Clock %u has been disabled", gate->clock_id); } static long get_timer_rate(long parent_rate, unsigned int apb_bus) { uint32_t timgxpre = 0; uint32_t apbxdiv = 0; vaddr_t rcc_base = stm32_rcc_base(); switch (apb_bus) { case 1: apbxdiv = io_read32(rcc_base + RCC_APB1DIVR) & RCC_APBXDIV_MASK; timgxpre = io_read32(rcc_base + RCC_TIMG1PRER) & RCC_TIMGXPRER_TIMGXPRE; break; case 2: apbxdiv = io_read32(rcc_base + RCC_APB2DIVR) & RCC_APBXDIV_MASK; timgxpre = io_read32(rcc_base + RCC_TIMG2PRER) & RCC_TIMGXPRER_TIMGXPRE; break; default: panic(); break; } if (apbxdiv == 0) return parent_rate; return parent_rate * (timgxpre + 1) * 2; } static unsigned long _stm32_clock_get_rate(unsigned long id) { enum stm32mp1_parent_id p = _UNKNOWN_ID; unsigned long rate = 0; p = stm32mp1_clk_get_parent(id); if (p < 0) return 0; rate = get_clock_rate(p); if ((id >= TIM2_K) && (id <= TIM14_K)) rate = get_timer_rate(rate, 1); if ((id >= TIM1_K) && (id <= TIM17_K)) rate = get_timer_rate(rate, 2); return rate; } /* * Get the parent ID of the target parent clock, or -1 if no parent found. */ static enum stm32mp1_parent_id get_parent_id_parent(enum stm32mp1_parent_id id) { enum stm32mp1_parent_sel s = _UNKNOWN_SEL; enum stm32mp1_pll_id pll_id = _PLL_NB; uint32_t p_sel = 0; switch (id) { case _ACLK: case _HCLK5: case _HCLK6: case _PCLK4: case _PCLK5: s = _AXISS_SEL; break; case _PLL1_P: case _PLL1_Q: case _PLL1_R: pll_id = _PLL1; break; case _PLL2_P: case _PLL2_Q: case _PLL2_R: pll_id = _PLL2; break; case _PLL3_P: case _PLL3_Q: case _PLL3_R: pll_id = _PLL3; break; case _PLL4_P: case _PLL4_Q: case _PLL4_R: pll_id = _PLL4; break; case _PCLK1: case _PCLK2: case _HCLK2: case _CK_PER: case _CK_MPU: case _CK_MCU: case _USB_PHY_48: /* We do not expected to access these */ panic(); break; default: /* Other parents have no parent */ return -1; } if (s != _UNKNOWN_SEL) { const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); vaddr_t rcc_base = stm32_rcc_base(); p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) & sel->msk; if (p_sel < sel->nb_parent) return sel->parent[p_sel]; } else { const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); p_sel = io_read32(stm32_rcc_base() + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) return osc_id2parent_id(pll->refclk[p_sel]); } FMSG("No parent found for %s", stm32mp1_clk_parent_name[id]); return -1; } /* We are only interested in knowing if PLL3 shall be secure or not */ static void secure_parent_clocks(enum stm32mp1_parent_id parent_id) { enum stm32mp1_parent_id grandparent_id = _UNKNOWN_ID; switch (parent_id) { case _ACLK: case _HCLK2: case _HCLK5: case _HCLK6: case _PCLK4: case _PCLK5: /* Intermediate clock mux or clock, go deeper in clock tree */ break; case _HSI: case _HSI_KER: case _LSI: case _CSI: case _CSI_KER: case _HSE: case _HSE_KER: case _HSE_KER_DIV2: case _HSE_RTC: case _LSE: case _PLL1_P: case _PLL1_Q: case _PLL1_R: case _PLL2_P: case _PLL2_Q: case _PLL2_R: /* Always secure clocks, no need to go further */ return; case _PLL3_P: case _PLL3_Q: case _PLL3_R: /* PLL3 is a shared resource, registered and don't go further */ stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); return; default: DMSG("Cannot lookup parent clock %s", stm32mp1_clk_parent_name[parent_id]); panic(); } grandparent_id = get_parent_id_parent(parent_id); if (grandparent_id >= 0) secure_parent_clocks(grandparent_id); } void stm32mp_register_clock_parents_secure(unsigned long clock_id) { enum stm32mp1_parent_id parent_id = stm32mp1_clk_get_parent(clock_id); if (parent_id < 0) { DMSG("No parent for clock %lu", clock_id); return; } secure_parent_clocks(parent_id); } static const char *stm32mp_osc_node_label[NB_OSC] = { [OSC_LSI] = "clk-lsi", [OSC_LSE] = "clk-lse", [OSC_HSI] = "clk-hsi", [OSC_HSE] = "clk-hse", [OSC_CSI] = "clk-csi", [OSC_I2S_CKIN] = "i2s_ckin", [OSC_USB_PHY_48] = "ck_usbo_48m" }; static unsigned int clk_freq_prop(const void *fdt, int node) { const fdt32_t *cuint = NULL; int ret = 0; /* Disabled clocks report null rate */ if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) return 0; cuint = fdt_getprop(fdt, node, "clock-frequency", &ret); if (!cuint) panic(); return fdt32_to_cpu(*cuint); } static void get_osc_freq_from_dt(const void *fdt) { enum stm32mp_osc_id idx = _UNKNOWN_OSC_ID; int clk_node = fdt_path_offset(fdt, "/clocks"); if (clk_node < 0) panic(); COMPILE_TIME_ASSERT((int)OSC_HSI == 0); for (idx = OSC_HSI; idx < NB_OSC; idx++) { const char *name = stm32mp_osc_node_label[idx]; int subnode = 0; fdt_for_each_subnode(subnode, fdt, clk_node) { const char *cchar = NULL; int ret = 0; cchar = fdt_get_name(fdt, subnode, &ret); if (!cchar) panic(); if (strncmp(cchar, name, (size_t)ret) == 0) { stm32mp1_osc[idx] = clk_freq_prop(fdt, subnode); DMSG("Osc %s: %lu Hz", name, stm32mp1_osc[idx]); break; } } if (!stm32mp1_osc[idx]) DMSG("Osc %s: no frequency info", name); } } static void enable_static_secure_clocks(void) { unsigned int idx = 0; const unsigned long secure_enable[] = { DDRC1, DDRC1LP, DDRC2, DDRC2LP, DDRPHYC, DDRPHYCLP, DDRCAPB, AXIDCG, DDRPHYCAPB, DDRPHYCAPBLP, TZPC, TZC1, TZC2, STGEN_K, BSEC, }; for (idx = 0; idx < ARRAY_SIZE(secure_enable); idx++) { clk_enable(stm32mp_rcc_clock_id_to_clk(secure_enable[idx])); stm32mp_register_clock_parents_secure(secure_enable[idx]); } if (CFG_TEE_CORE_NB_CORE > 1) clk_enable(stm32mp_rcc_clock_id_to_clk(RTCAPB)); } static void __maybe_unused enable_rcc_tzen(void) { io_setbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN); } static void __maybe_unused disable_rcc_tzen(void) { IMSG("RCC is non-secure"); io_clrbits32(stm32_rcc_base() + RCC_TZCR, RCC_TZCR_TZEN); } static TEE_Result stm32mp1_clk_fdt_init(const void *fdt, int node) { unsigned int i = 0; int len = 0; int ignored = 0; get_osc_freq_from_dt(fdt); /* * OP-TEE core is not in charge of configuring clock parenthood. * This is expected from an earlier boot stage. Modifying the clock * tree parenthood here may jeopardize already configured clocks. * The sequence below ignores such DT directives with a friendly * debug trace. */ if (fdt_getprop(fdt, node, "st,clksrc", &len)) { DMSG("Ignore source clocks configuration from DT"); ignored++; } if (fdt_getprop(fdt, node, "st,clkdiv", &len)) { DMSG("Ignore clock divisors configuration from DT"); ignored++; } if (fdt_getprop(fdt, node, "st,pkcs", &len)) { DMSG("Ignore peripheral clocks tree configuration from DT"); ignored++; } for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { char name[] = "st,pll@X"; snprintf(name, sizeof(name), "st,pll@%d", i); node = fdt_subnode_offset(fdt, node, name); if (node < 0) continue; if (fdt_getprop(fdt, node, "cfg", &len) || fdt_getprop(fdt, node, "frac", &len)) { DMSG("Ignore PLL%u configurations from DT", i); ignored++; } } if (ignored != 0) IMSG("DT clock tree configurations were ignored"); return TEE_SUCCESS; } /* * Conversion between clk references and clock gates and clock on internals * * stm32mp1_clk first cells follow stm32mp1_clk_gate[] ordering. * stm32mp1_clk last cells follow stm32mp1_clk_on[] ordering. */ static struct clk stm32mp1_clk[ARRAY_SIZE(stm32mp1_clk_gate) + ARRAY_SIZE(stm32mp1_clk_on)]; #define CLK_ON_INDEX_OFFSET ((int)ARRAY_SIZE(stm32mp1_clk_gate)) static bool clk_is_gate(struct clk *clk) { int clk_index = clk - stm32mp1_clk; assert(clk_index >= 0 && clk_index < (int)ARRAY_SIZE(stm32mp1_clk)); return clk_index < CLK_ON_INDEX_OFFSET; } static unsigned long clk_to_clock_id(struct clk *clk) { int gate_index = clk - stm32mp1_clk; int on_index = gate_index - CLK_ON_INDEX_OFFSET; if (clk_is_gate(clk)) return stm32mp1_clk_gate[gate_index].clock_id; return stm32mp1_clk_on[on_index]; } static const struct stm32mp1_clk_gate *clk_to_gate_ref(struct clk *clk) { int gate_index = clk - stm32mp1_clk; assert(clk_is_gate(clk)); return stm32mp1_clk_gate + gate_index; } static int clock_id_to_gate_index(unsigned long clock_id) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_gate); n++) if (stm32mp1_clk_gate[n].clock_id == clock_id) return n; return -1; } static int clock_id_to_always_on_index(unsigned long clock_id) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(stm32mp1_clk_on); n++) if (stm32mp1_clk_on[n] == clock_id) return n; return -1; } static struct clk *clock_id_to_clk(unsigned long clock_id) { int gate_index = clock_id_to_gate_index(clock_id); int on_index = clock_id_to_always_on_index(clock_id); if (gate_index >= 0) return stm32mp1_clk + gate_index; if (on_index >= 0) return stm32mp1_clk + CLK_ON_INDEX_OFFSET + on_index; return NULL; } struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id) { return clock_id_to_clk(clock_id); } #if (CFG_TEE_CORE_LOG_LEVEL >= TRACE_DEBUG) && defined(CFG_TEE_CORE_DEBUG) struct clk_name { unsigned int clock_id; const char *name; }; #define CLOCK_NAME(_binding, _name) \ { .clock_id = (_binding), .name = (_name) } /* Store names only for some clocks */ const struct clk_name exposed_clk_name[] = { /* Clocks used by platform drivers not yet probed from DT */ CLOCK_NAME(CK_DBG, "dbg"), CLOCK_NAME(CK_MCU, "mcu"), CLOCK_NAME(RTCAPB, "rtcapb"), CLOCK_NAME(BKPSRAM, "bkpsram"), CLOCK_NAME(RTC, "rtc"), CLOCK_NAME(CRYP1, "crpy1"), CLOCK_NAME(SYSCFG, "syscfg"), CLOCK_NAME(GPIOA, "gpioa"), CLOCK_NAME(GPIOB, "gpiob"), CLOCK_NAME(GPIOC, "gpioc"), CLOCK_NAME(GPIOD, "gpiod"), CLOCK_NAME(GPIOE, "gpioe"), CLOCK_NAME(GPIOF, "gpiof"), CLOCK_NAME(GPIOG, "gpiog"), CLOCK_NAME(GPIOH, "gpioh"), CLOCK_NAME(GPIOI, "gpioi"), CLOCK_NAME(GPIOJ, "gpioj"), CLOCK_NAME(GPIOK, "gpiok"), CLOCK_NAME(GPIOZ, "gpioz"), /* Clock exposed by SCMI. SCMI clock fmro DT bindings to come... */ CLOCK_NAME(CK_HSE, "hse"), CLOCK_NAME(CK_HSI, "hsi"), CLOCK_NAME(CK_CSI, "csi"), CLOCK_NAME(CK_LSE, "lse"), CLOCK_NAME(CK_LSI, "lsi"), CLOCK_NAME(PLL2_Q, "pll2q"), CLOCK_NAME(PLL2_R, "pll2r"), CLOCK_NAME(PLL3_Q, "pll3q"), CLOCK_NAME(PLL3_R, "pll3r"), CLOCK_NAME(CRYP1, "cryp1"), CLOCK_NAME(HASH1, "hash1"), CLOCK_NAME(I2C4_K, "i2c4"), CLOCK_NAME(I2C6_K, "i2c6"), CLOCK_NAME(IWDG1, "iwdg"), CLOCK_NAME(RNG1_K, "rng1"), CLOCK_NAME(SPI6_K, "spi6"), CLOCK_NAME(USART1_K, "usart1"), CLOCK_NAME(CK_MCU, "mcu"), }; DECLARE_KEEP_PAGER(exposed_clk_name); static const char *clk_op_get_name(struct clk *clk) { unsigned long clock_id = clk_to_clock_id(clk); size_t n = 0; for (n = 0; n < ARRAY_SIZE(exposed_clk_name); n++) if (exposed_clk_name[n].clock_id == clock_id) return exposed_clk_name[n].name; return NULL; } #else static const char *clk_op_get_name(struct clk *clk __unused) { return NULL; } #endif /*CFG_TEE_CORE_LOG_LEVEL*/ static unsigned long clk_op_compute_rate(struct clk *clk, unsigned long parent_rate __unused) { return _stm32_clock_get_rate(clk_to_clock_id(clk)); } static TEE_Result clk_op_enable(struct clk *clk) { if (clk_is_gate(clk)) __clk_enable(clk_to_gate_ref(clk)); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(clk_op_enable); static void clk_op_disable(struct clk *clk) { if (clk_is_gate(clk)) __clk_disable(clk_to_gate_ref(clk)); } DECLARE_KEEP_PAGER(clk_op_disable); /* This variable is weak to break its dependency chain when linked as unpaged */ const struct clk_ops stm32mp1_clk_ops __weak __relrodata_unpaged("stm32mp1_clk_ops") = { .enable = clk_op_enable, .disable = clk_op_disable, .get_rate = clk_op_compute_rate, }; static TEE_Result register_stm32mp1_clocks(void) { TEE_Result res = TEE_ERROR_GENERIC; size_t n = 0; for (n = 0; n < ARRAY_SIZE(stm32mp1_clk); n++) { stm32mp1_clk[n].ops = &stm32mp1_clk_ops; stm32mp1_clk[n].name = clk_op_get_name(stm32mp1_clk + n); refcount_set(&stm32mp1_clk[n].enabled_count, 0); res = clk_register(stm32mp1_clk + n); if (res) return res; } return TEE_SUCCESS; } static TEE_Result stm32mp1_clk_dt_get_clk(struct dt_pargs *pargs, void *data __unused, struct clk **out_clk) { unsigned long clock_id = pargs->args[0]; struct clk *clk = NULL; if (pargs->args_count != 1) return TEE_ERROR_BAD_PARAMETERS; clk = clock_id_to_clk(clock_id); if (!clk) return TEE_ERROR_BAD_PARAMETERS; *out_clk = clk; return TEE_SUCCESS; } /* Non-null reference for compat data */ static const uint8_t non_secure_rcc; static TEE_Result stm32mp1_clock_provider_probe(const void *fdt, int offs, const void *compat_data) { TEE_Result res = TEE_ERROR_GENERIC; if (compat_data == &non_secure_rcc) disable_rcc_tzen(); else enable_rcc_tzen(); res = stm32mp1_clk_fdt_init(fdt, offs); if (res) { EMSG("Failed to initialize clocks from DT: %#"PRIx32, res); panic(); } res = register_stm32mp1_clocks(); if (res) { EMSG("Failed to register clocks: %#"PRIx32, res); panic(); } res = clk_dt_register_clk_provider(fdt, offs, stm32mp1_clk_dt_get_clk, NULL); if (res) { EMSG("Failed to register clock provider: %#"PRIx32, res); panic(); } enable_static_secure_clocks(); return TEE_SUCCESS; } static const struct dt_device_match stm32mp1_clock_match_table[] = { { .compatible = "st,stm32mp1-rcc", .compat_data = &non_secure_rcc, }, { .compatible = "st,stm32mp1-rcc-secure", }, { } }; DEFINE_DT_DRIVER(stm32mp1_clock_dt_driver) = { .name = "stm32mp1_clock", .type = DT_DRIVER_CLK, .match_table = stm32mp1_clock_match_table, .probe = stm32mp1_clock_provider_probe, }; optee_os-4.3.0/core/drivers/clk/clk-stm32mp25.c000066400000000000000000003061751464416617300211310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "clk-stm32-core.h" #define MAX_OPP CFG_STM32MP_OPP_COUNT #define TIMEOUT_US_100MS U(100000) #define TIMEOUT_US_200MS U(200000) #define TIMEOUT_US_1S U(1000000) #define PLLRDY_TIMEOUT TIMEOUT_US_200MS #define CLKSRC_TIMEOUT TIMEOUT_US_200MS #define CLKDIV_TIMEOUT TIMEOUT_US_200MS #define OSCRDY_TIMEOUT TIMEOUT_US_1S /* PLL minimal frequencies for clock sources */ #define PLL_REFCLK_MIN UL(5000000) #define PLL_FRAC_REFCLK_MIN UL(10000000) /* Parameters from XBAR_CFG in st,cksrc field */ #define XBAR_CKSRC_CHANNEL GENMASK_32(5, 0) #define XBAR_CKSRC_SRC GENMASK_32(9, 6) #define XBAR_CKSRC_SRC_OFFSET U(6) #define XBAR_CKSRC_PREDIV GENMASK_32(19, 10) #define XBAR_CKSRC_PREDIV_OFFSET U(10) #define XBAR_CKSRC_FINDIV GENMASK_32(25, 20) #define XBAR_CKSRC_FINDIV_OFFSET U(20) #define XBAR_CHANNEL_NB U(64) #define XBAR_ROOT_CHANNEL_NB U(7) #define FLEX_STGEN U(33) #define RCC_0_MHZ UL(0) #define RCC_4_MHZ UL(4000000) #define RCC_16_MHZ UL(16000000) enum pll_cfg { FBDIV, REFDIV, POSTDIV1, POSTDIV2, PLLCFG_NB }; enum pll_csg { DIVVAL, SPREAD, DOWNSPREAD, PLLCSG_NB }; struct stm32_pll_dt_cfg { bool enabled; uint32_t cfg[PLLCFG_NB]; uint32_t csg[PLLCSG_NB]; uint32_t frac; bool csg_enabled; uint32_t src; }; struct stm32_osci_dt_cfg { unsigned long freq; bool bypass; bool digbyp; bool css; uint32_t drive; }; struct stm32_clk_opp_cfg { uint32_t frq; uint32_t src; struct stm32_pll_dt_cfg pll_cfg; }; struct stm32_clk_opp_dt_cfg { struct stm32_clk_opp_cfg cpu1_opp[MAX_OPP]; }; struct stm32_clk_platdata { uintptr_t rcc_base; uint32_t nosci; struct stm32_osci_dt_cfg *osci; uint32_t npll; struct stm32_pll_dt_cfg *pll; struct stm32_clk_opp_dt_cfg *opp; uint32_t nbusclk; uint32_t *busclk; uint32_t nkernelclk; uint32_t *kernelclk; uint32_t nflexgen; uint32_t *flexgen; uint32_t c1msrd; bool safe_rst; }; /* * GATE CONFIG */ /* WARNING GATE_XXX_RDY MUST FOLLOW GATE_XXX */ enum enum_gate_cfg { GATE_HSI, GATE_HSI_RDY, GATE_HSE, GATE_HSE_RDY, GATE_LSE, GATE_LSE_RDY, GATE_LSI, GATE_LSI_RDY, GATE_MSI, GATE_MSI_RDY, GATE_PLL1, GATE_PLL1_RDY, GATE_PLL2, GATE_PLL2_RDY, GATE_PLL3, GATE_PLL3_RDY, GATE_PLL4, GATE_PLL4_RDY, GATE_PLL5, GATE_PLL5_RDY, GATE_PLL6, GATE_PLL6_RDY, GATE_PLL7, GATE_PLL7_RDY, GATE_PLL8, GATE_PLL8_RDY, GATE_PLL4_CKREFST, GATE_PLL5_CKREFST, GATE_PLL6_CKREFST, GATE_PLL7_CKREFST, GATE_PLL8_CKREFST, GATE_HSEDIV2, GATE_APB1DIV_RDY, GATE_APB2DIV_RDY, GATE_APB3DIV_RDY, GATE_APB4DIV_RDY, GATE_APBDBGDIV_RDY, GATE_TIMG1PRE_RDY, GATE_TIMG2PRE_RDY, GATE_LSMCUDIV_RDY, GATE_RTCCK, GATE_C3, GATE_LPTIM3C3, GATE_LPTIM4C3, GATE_LPTIM5C3, GATE_SPI8C3, GATE_LPUART1C3, GATE_I2C8C3, GATE_ADF1C3, GATE_GPIOZC3, GATE_LPDMAC3, GATE_RTCC3, GATE_I3C4C3, GATE_MCO1, GATE_MCO2, GATE_DDRCP, GATE_DDRCAPB, GATE_DDRPHYCAPB, GATE_DDRPHYC, GATE_DDRCFG, GATE_SYSRAM, GATE_VDERAM, GATE_SRAM1, GATE_SRAM2, GATE_RETRAM, GATE_BKPSRAM, GATE_LPSRAM1, GATE_LPSRAM2, GATE_LPSRAM3, GATE_OSPI1, GATE_OSPI2, GATE_FMC, GATE_DBG, GATE_TRACE, GATE_STM, GATE_ETR, GATE_GPIOA, GATE_GPIOB, GATE_GPIOC, GATE_GPIOD, GATE_GPIOE, GATE_GPIOF, GATE_GPIOG, GATE_GPIOH, GATE_GPIOI, GATE_GPIOJ, GATE_GPIOK, GATE_GPIOZ, GATE_HPDMA1, GATE_HPDMA2, GATE_HPDMA3, GATE_LPDMA, GATE_HSEM, GATE_IPCC1, GATE_IPCC2, GATE_RTC, GATE_SYSCPU1, GATE_BSEC, GATE_IS2M, GATE_HSIMON, GATE_TIM1, GATE_TIM2, GATE_TIM3, GATE_TIM4, GATE_TIM5, GATE_TIM6, GATE_TIM7, GATE_TIM8, GATE_TIM10, GATE_TIM11, GATE_TIM12, GATE_TIM13, GATE_TIM14, GATE_TIM15, GATE_TIM16, GATE_TIM17, GATE_TIM20, GATE_LPTIM1, GATE_LPTIM2, GATE_LPTIM3, GATE_LPTIM4, GATE_LPTIM5, GATE_SPI1, GATE_SPI2, GATE_SPI3, GATE_SPI4, GATE_SPI5, GATE_SPI6, GATE_SPI7, GATE_SPI8, GATE_SPDIFRX, GATE_USART1, GATE_USART2, GATE_USART3, GATE_UART4, GATE_UART5, GATE_USART6, GATE_UART7, GATE_UART8, GATE_UART9, GATE_LPUART1, GATE_I2C1, GATE_I2C2, GATE_I2C3, GATE_I2C4, GATE_I2C5, GATE_I2C6, GATE_I2C7, GATE_I2C8, GATE_SAI1, GATE_SAI2, GATE_SAI3, GATE_SAI4, GATE_MDF1, GATE_ADF1, GATE_FDCAN, GATE_HDP, GATE_ADC12, GATE_ADC3, GATE_ETH1MAC, GATE_ETH1, GATE_ETH1TX, GATE_ETH1RX, GATE_ETH1STP, GATE_ETH2MAC, GATE_ETH2, GATE_ETH2STP, GATE_ETH2TX, GATE_ETH2RX, GATE_USB2, GATE_USB2PHY1, GATE_USB2PHY2, GATE_USB3DR, GATE_USB3PCIEPHY, GATE_PCIE, GATE_USBTC, GATE_ETHSWMAC, GATE_ETHSW, GATE_ETHSWREF, GATE_STGEN, GATE_SDMMC1, GATE_SDMMC2, GATE_SDMMC3, GATE_GPU, GATE_LTDC, GATE_DSI, GATE_LVDS, GATE_CSI, GATE_DCMIPP, GATE_CCI, GATE_VDEC, GATE_VENC, GATE_RNG, GATE_PKA, GATE_SAES, GATE_HASH, GATE_CRYP1, GATE_CRYP2, GATE_IWDG1, GATE_IWDG2, GATE_IWDG3, GATE_IWDG4, GATE_IWDG5, GATE_WWDG1, GATE_WWDG2, GATE_VREF, GATE_DTS, GATE_CRC, GATE_SERC, GATE_OSPIIOM, GATE_GICV2M, GATE_I3C1, GATE_I3C2, GATE_I3C3, GATE_I3C4, GATE_NB }; #define GATE_CFG(_id, _offset, _bit_idx, _offset_clr)\ [(_id)] = {\ .offset = (_offset),\ .bit_idx = (_bit_idx),\ .set_clr = (_offset_clr),\ } static const struct gate_cfg gates_mp25[GATE_NB] = { GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0), GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0), GATE_CFG(GATE_LSI, RCC_BDCR, 9, 0), GATE_CFG(GATE_LSI_RDY, RCC_BDCR, 10, 0), GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0), GATE_CFG(GATE_MSI, RCC_D3DCR, 0, 0), GATE_CFG(GATE_MSI_RDY, RCC_D3DCR, 2, 0), GATE_CFG(GATE_PLL1, RCC_PLL2CFGR1, 8, 0), GATE_CFG(GATE_PLL1_RDY, RCC_PLL2CFGR1, 24, 0), GATE_CFG(GATE_PLL2, RCC_PLL2CFGR1, 8, 0), GATE_CFG(GATE_PLL2_RDY, RCC_PLL2CFGR1, 24, 0), GATE_CFG(GATE_PLL3, RCC_PLL3CFGR1, 8, 0), GATE_CFG(GATE_PLL3_RDY, RCC_PLL3CFGR1, 24, 0), GATE_CFG(GATE_PLL4, RCC_PLL4CFGR1, 8, 0), GATE_CFG(GATE_PLL4_RDY, RCC_PLL4CFGR1, 24, 0), GATE_CFG(GATE_PLL5, RCC_PLL5CFGR1, 8, 0), GATE_CFG(GATE_PLL5_RDY, RCC_PLL5CFGR1, 24, 0), GATE_CFG(GATE_PLL6, RCC_PLL6CFGR1, 8, 0), GATE_CFG(GATE_PLL6_RDY, RCC_PLL6CFGR1, 24, 0), GATE_CFG(GATE_PLL7, RCC_PLL7CFGR1, 8, 0), GATE_CFG(GATE_PLL7_RDY, RCC_PLL7CFGR1, 24, 0), GATE_CFG(GATE_PLL8, RCC_PLL8CFGR1, 8, 0), GATE_CFG(GATE_PLL8_RDY, RCC_PLL8CFGR1, 24, 0), GATE_CFG(GATE_PLL4_CKREFST, RCC_PLL4CFGR1, 28, 0), GATE_CFG(GATE_PLL5_CKREFST, RCC_PLL5CFGR1, 28, 0), GATE_CFG(GATE_PLL6_CKREFST, RCC_PLL6CFGR1, 28, 0), GATE_CFG(GATE_PLL7_CKREFST, RCC_PLL7CFGR1, 28, 0), GATE_CFG(GATE_PLL8_CKREFST, RCC_PLL8CFGR1, 28, 0), GATE_CFG(GATE_C3, RCC_C3CFGR, 1, 0), GATE_CFG(GATE_LPTIM3C3, RCC_C3CFGR, 16, 0), GATE_CFG(GATE_LPTIM4C3, RCC_C3CFGR, 17, 0), GATE_CFG(GATE_LPTIM5C3, RCC_C3CFGR, 18, 0), GATE_CFG(GATE_SPI8C3, RCC_C3CFGR, 19, 0), GATE_CFG(GATE_LPUART1C3, RCC_C3CFGR, 20, 0), GATE_CFG(GATE_I2C8C3, RCC_C3CFGR, 21, 0), GATE_CFG(GATE_ADF1C3, RCC_C3CFGR, 23, 0), GATE_CFG(GATE_GPIOZC3, RCC_C3CFGR, 24, 0), GATE_CFG(GATE_LPDMAC3, RCC_C3CFGR, 25, 0), GATE_CFG(GATE_RTCC3, RCC_C3CFGR, 26, 0), GATE_CFG(GATE_I3C4C3, RCC_C3CFGR, 27, 0), GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 8, 0), GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 8, 0), GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1), GATE_CFG(GATE_HSEDIV2, RCC_OCENSETR, 5, 1), GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1), GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0), GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0), GATE_CFG(GATE_APB1DIV_RDY, RCC_APB1DIVR, 31, 0), GATE_CFG(GATE_APB2DIV_RDY, RCC_APB2DIVR, 31, 0), GATE_CFG(GATE_APB3DIV_RDY, RCC_APB3DIVR, 31, 0), GATE_CFG(GATE_APB4DIV_RDY, RCC_APB4DIVR, 31, 0), GATE_CFG(GATE_APBDBGDIV_RDY, RCC_APBDBGDIVR, 31, 0), GATE_CFG(GATE_TIMG1PRE_RDY, RCC_TIMG1PRER, 31, 0), GATE_CFG(GATE_TIMG2PRE_RDY, RCC_TIMG2PRER, 31, 0), GATE_CFG(GATE_LSMCUDIV_RDY, RCC_LSMCUDIVR, 31, 0), GATE_CFG(GATE_DDRCP, RCC_DDRCPCFGR, 1, 0), GATE_CFG(GATE_DDRCAPB, RCC_DDRCAPBCFGR, 1, 0), GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRPHYCAPBCFGR, 1, 0), GATE_CFG(GATE_DDRPHYC, RCC_DDRPHYCCFGR, 1, 0), GATE_CFG(GATE_DDRCFG, RCC_DDRCFGR, 1, 0), GATE_CFG(GATE_SYSRAM, RCC_SYSRAMCFGR, 1, 0), GATE_CFG(GATE_VDERAM, RCC_VDERAMCFGR, 1, 0), GATE_CFG(GATE_SRAM1, RCC_SRAM1CFGR, 1, 0), GATE_CFG(GATE_SRAM2, RCC_SRAM2CFGR, 1, 0), GATE_CFG(GATE_RETRAM, RCC_RETRAMCFGR, 1, 0), GATE_CFG(GATE_BKPSRAM, RCC_BKPSRAMCFGR, 1, 0), GATE_CFG(GATE_LPSRAM1, RCC_LPSRAM1CFGR, 1, 0), GATE_CFG(GATE_LPSRAM2, RCC_LPSRAM2CFGR, 1, 0), GATE_CFG(GATE_LPSRAM3, RCC_LPSRAM3CFGR, 1, 0), GATE_CFG(GATE_OSPI1, RCC_OSPI1CFGR, 1, 0), GATE_CFG(GATE_OSPI2, RCC_OSPI2CFGR, 1, 0), GATE_CFG(GATE_FMC, RCC_FMCCFGR, 1, 0), GATE_CFG(GATE_DBG, RCC_DBGCFGR, 8, 0), GATE_CFG(GATE_TRACE, RCC_DBGCFGR, 9, 0), GATE_CFG(GATE_STM, RCC_STMCFGR, 1, 0), GATE_CFG(GATE_ETR, RCC_ETRCFGR, 1, 0), GATE_CFG(GATE_GPIOA, RCC_GPIOACFGR, 1, 0), GATE_CFG(GATE_GPIOB, RCC_GPIOBCFGR, 1, 0), GATE_CFG(GATE_GPIOC, RCC_GPIOCCFGR, 1, 0), GATE_CFG(GATE_GPIOD, RCC_GPIODCFGR, 1, 0), GATE_CFG(GATE_GPIOE, RCC_GPIOECFGR, 1, 0), GATE_CFG(GATE_GPIOF, RCC_GPIOFCFGR, 1, 0), GATE_CFG(GATE_GPIOG, RCC_GPIOGCFGR, 1, 0), GATE_CFG(GATE_GPIOH, RCC_GPIOHCFGR, 1, 0), GATE_CFG(GATE_GPIOI, RCC_GPIOICFGR, 1, 0), GATE_CFG(GATE_GPIOJ, RCC_GPIOJCFGR, 1, 0), GATE_CFG(GATE_GPIOK, RCC_GPIOKCFGR, 1, 0), GATE_CFG(GATE_GPIOZ, RCC_GPIOZCFGR, 1, 0), GATE_CFG(GATE_HPDMA1, RCC_HPDMA1CFGR, 1, 0), GATE_CFG(GATE_HPDMA2, RCC_HPDMA2CFGR, 1, 0), GATE_CFG(GATE_HPDMA3, RCC_HPDMA3CFGR, 1, 0), GATE_CFG(GATE_LPDMA, RCC_LPDMACFGR, 1, 0), GATE_CFG(GATE_HSEM, RCC_HSEMCFGR, 1, 0), GATE_CFG(GATE_IPCC1, RCC_IPCC1CFGR, 1, 0), GATE_CFG(GATE_IPCC2, RCC_IPCC2CFGR, 1, 0), GATE_CFG(GATE_RTC, RCC_RTCCFGR, 1, 0), GATE_CFG(GATE_SYSCPU1, RCC_SYSCPU1CFGR, 1, 0), GATE_CFG(GATE_BSEC, RCC_BSECCFGR, 1, 0), GATE_CFG(GATE_IS2M, RCC_IS2MCFGR, 1, 0), GATE_CFG(GATE_HSIMON, RCC_HSIFMONCR, 15, 0), GATE_CFG(GATE_TIM1, RCC_TIM1CFGR, 1, 0), GATE_CFG(GATE_TIM2, RCC_TIM2CFGR, 1, 0), GATE_CFG(GATE_TIM3, RCC_TIM3CFGR, 1, 0), GATE_CFG(GATE_TIM4, RCC_TIM4CFGR, 1, 0), GATE_CFG(GATE_TIM5, RCC_TIM5CFGR, 1, 0), GATE_CFG(GATE_TIM6, RCC_TIM6CFGR, 1, 0), GATE_CFG(GATE_TIM7, RCC_TIM7CFGR, 1, 0), GATE_CFG(GATE_TIM8, RCC_TIM8CFGR, 1, 0), GATE_CFG(GATE_TIM10, RCC_TIM10CFGR, 1, 0), GATE_CFG(GATE_TIM11, RCC_TIM11CFGR, 1, 0), GATE_CFG(GATE_TIM12, RCC_TIM12CFGR, 1, 0), GATE_CFG(GATE_TIM13, RCC_TIM13CFGR, 1, 0), GATE_CFG(GATE_TIM14, RCC_TIM14CFGR, 1, 0), GATE_CFG(GATE_TIM15, RCC_TIM15CFGR, 1, 0), GATE_CFG(GATE_TIM16, RCC_TIM16CFGR, 1, 0), GATE_CFG(GATE_TIM17, RCC_TIM17CFGR, 1, 0), GATE_CFG(GATE_TIM20, RCC_TIM20CFGR, 1, 0), GATE_CFG(GATE_LPTIM1, RCC_LPTIM1CFGR, 1, 0), GATE_CFG(GATE_LPTIM2, RCC_LPTIM2CFGR, 1, 0), GATE_CFG(GATE_LPTIM3, RCC_LPTIM3CFGR, 1, 0), GATE_CFG(GATE_LPTIM4, RCC_LPTIM4CFGR, 1, 0), GATE_CFG(GATE_LPTIM5, RCC_LPTIM5CFGR, 1, 0), GATE_CFG(GATE_SPI1, RCC_SPI1CFGR, 1, 0), GATE_CFG(GATE_SPI2, RCC_SPI2CFGR, 1, 0), GATE_CFG(GATE_SPI3, RCC_SPI3CFGR, 1, 0), GATE_CFG(GATE_SPI4, RCC_SPI4CFGR, 1, 0), GATE_CFG(GATE_SPI5, RCC_SPI5CFGR, 1, 0), GATE_CFG(GATE_SPI6, RCC_SPI6CFGR, 1, 0), GATE_CFG(GATE_SPI7, RCC_SPI7CFGR, 1, 0), GATE_CFG(GATE_SPI8, RCC_SPI8CFGR, 1, 0), GATE_CFG(GATE_SPDIFRX, RCC_SPDIFRXCFGR, 1, 0), GATE_CFG(GATE_USART1, RCC_USART1CFGR, 1, 0), GATE_CFG(GATE_USART2, RCC_USART2CFGR, 1, 0), GATE_CFG(GATE_USART3, RCC_USART3CFGR, 1, 0), GATE_CFG(GATE_UART4, RCC_UART4CFGR, 1, 0), GATE_CFG(GATE_UART5, RCC_UART5CFGR, 1, 0), GATE_CFG(GATE_USART6, RCC_USART6CFGR, 1, 0), GATE_CFG(GATE_UART7, RCC_UART7CFGR, 1, 0), GATE_CFG(GATE_UART8, RCC_UART8CFGR, 1, 0), GATE_CFG(GATE_UART9, RCC_UART9CFGR, 1, 0), GATE_CFG(GATE_LPUART1, RCC_LPUART1CFGR, 1, 0), GATE_CFG(GATE_I2C1, RCC_I2C1CFGR, 1, 0), GATE_CFG(GATE_I2C2, RCC_I2C2CFGR, 1, 0), GATE_CFG(GATE_I2C3, RCC_I2C3CFGR, 1, 0), GATE_CFG(GATE_I2C4, RCC_I2C4CFGR, 1, 0), GATE_CFG(GATE_I2C5, RCC_I2C5CFGR, 1, 0), GATE_CFG(GATE_I2C6, RCC_I2C6CFGR, 1, 0), GATE_CFG(GATE_I2C7, RCC_I2C7CFGR, 1, 0), GATE_CFG(GATE_I2C8, RCC_I2C8CFGR, 1, 0), GATE_CFG(GATE_SAI1, RCC_SAI1CFGR, 1, 0), GATE_CFG(GATE_SAI2, RCC_SAI2CFGR, 1, 0), GATE_CFG(GATE_SAI3, RCC_SAI3CFGR, 1, 0), GATE_CFG(GATE_SAI4, RCC_SAI4CFGR, 1, 0), GATE_CFG(GATE_MDF1, RCC_MDF1CFGR, 1, 0), GATE_CFG(GATE_ADF1, RCC_ADF1CFGR, 1, 0), GATE_CFG(GATE_FDCAN, RCC_FDCANCFGR, 1, 0), GATE_CFG(GATE_HDP, RCC_HDPCFGR, 1, 0), GATE_CFG(GATE_ADC12, RCC_ADC12CFGR, 1, 0), GATE_CFG(GATE_ADC3, RCC_ADC3CFGR, 1, 0), GATE_CFG(GATE_ETH1MAC, RCC_ETH1CFGR, 1, 0), GATE_CFG(GATE_ETH1STP, RCC_ETH1CFGR, 4, 0), GATE_CFG(GATE_ETH1, RCC_ETH1CFGR, 5, 0), GATE_CFG(GATE_ETH1TX, RCC_ETH1CFGR, 8, 0), GATE_CFG(GATE_ETH1RX, RCC_ETH1CFGR, 10, 0), GATE_CFG(GATE_ETH2MAC, RCC_ETH2CFGR, 1, 0), GATE_CFG(GATE_ETH2STP, RCC_ETH2CFGR, 4, 0), GATE_CFG(GATE_ETH2, RCC_ETH2CFGR, 5, 0), GATE_CFG(GATE_ETH2TX, RCC_ETH2CFGR, 8, 0), GATE_CFG(GATE_ETH2RX, RCC_ETH2CFGR, 10, 0), GATE_CFG(GATE_USB2, RCC_USB2CFGR, 1, 0), GATE_CFG(GATE_USB2PHY1, RCC_USB2PHY1CFGR, 1, 0), GATE_CFG(GATE_USB2PHY2, RCC_USB2PHY2CFGR, 1, 0), GATE_CFG(GATE_USB3DR, RCC_USB3DRCFGR, 1, 0), GATE_CFG(GATE_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 1, 0), GATE_CFG(GATE_PCIE, RCC_PCIECFGR, 1, 0), GATE_CFG(GATE_USBTC, RCC_USBTCCFGR, 1, 0), GATE_CFG(GATE_ETHSWMAC, RCC_ETHSWCFGR, 1, 0), GATE_CFG(GATE_ETHSW, RCC_ETHSWCFGR, 5, 0), GATE_CFG(GATE_ETHSWREF, RCC_ETHSWCFGR, 21, 0), GATE_CFG(GATE_STGEN, RCC_STGENCFGR, 1, 0), GATE_CFG(GATE_SDMMC1, RCC_SDMMC1CFGR, 1, 0), GATE_CFG(GATE_SDMMC2, RCC_SDMMC2CFGR, 1, 0), GATE_CFG(GATE_SDMMC3, RCC_SDMMC3CFGR, 1, 0), GATE_CFG(GATE_GPU, RCC_GPUCFGR, 1, 0), GATE_CFG(GATE_LTDC, RCC_LTDCCFGR, 1, 0), GATE_CFG(GATE_DSI, RCC_DSICFGR, 1, 0), GATE_CFG(GATE_LVDS, RCC_LVDSCFGR, 1, 0), GATE_CFG(GATE_CSI, RCC_CSICFGR, 1, 0), GATE_CFG(GATE_DCMIPP, RCC_DCMIPPCFGR, 1, 0), GATE_CFG(GATE_CCI, RCC_CCICFGR, 1, 0), GATE_CFG(GATE_VDEC, RCC_VDECCFGR, 1, 0), GATE_CFG(GATE_VENC, RCC_VENCCFGR, 1, 0), GATE_CFG(GATE_RNG, RCC_RNGCFGR, 1, 0), GATE_CFG(GATE_PKA, RCC_PKACFGR, 1, 0), GATE_CFG(GATE_SAES, RCC_SAESCFGR, 1, 0), GATE_CFG(GATE_HASH, RCC_HASHCFGR, 1, 0), GATE_CFG(GATE_CRYP1, RCC_CRYP1CFGR, 1, 0), GATE_CFG(GATE_CRYP2, RCC_CRYP2CFGR, 1, 0), GATE_CFG(GATE_IWDG1, RCC_IWDG1CFGR, 1, 0), GATE_CFG(GATE_IWDG2, RCC_IWDG2CFGR, 1, 0), GATE_CFG(GATE_IWDG3, RCC_IWDG3CFGR, 1, 0), GATE_CFG(GATE_IWDG4, RCC_IWDG4CFGR, 1, 0), GATE_CFG(GATE_IWDG5, RCC_IWDG5CFGR, 1, 0), GATE_CFG(GATE_WWDG1, RCC_WWDG1CFGR, 1, 0), GATE_CFG(GATE_WWDG2, RCC_WWDG2CFGR, 1, 0), GATE_CFG(GATE_VREF, RCC_VREFCFGR, 1, 0), GATE_CFG(GATE_DTS, RCC_DTSCFGR, 1, 0), GATE_CFG(GATE_CRC, RCC_CRCCFGR, 1, 0), GATE_CFG(GATE_SERC, RCC_SERCCFGR, 1, 0), GATE_CFG(GATE_OSPIIOM, RCC_OSPIIOMCFGR, 1, 0), GATE_CFG(GATE_GICV2M, RCC_GICV2MCFGR, 1, 0), GATE_CFG(GATE_I3C1, RCC_I3C1CFGR, 1, 0), GATE_CFG(GATE_I3C2, RCC_I3C2CFGR, 1, 0), GATE_CFG(GATE_I3C3, RCC_I3C3CFGR, 1, 0), GATE_CFG(GATE_I3C4, RCC_I3C4CFGR, 1, 0), }; /* * MUX CONFIG */ #define _MUX_CFG(_id, _offset, _shift, _width, _rdy)\ [(_id)] = {\ .offset = (_offset),\ .shift = (_shift),\ .width = (_width),\ .ready = (_rdy),\ } static const struct mux_cfg parent_mp25[MUX_NB] = { _MUX_CFG(MUX_MUXSEL0, RCC_MUXSELCFGR, 0, 2, GATE_PLL4_CKREFST), _MUX_CFG(MUX_MUXSEL1, RCC_MUXSELCFGR, 4, 2, GATE_PLL5_CKREFST), _MUX_CFG(MUX_MUXSEL2, RCC_MUXSELCFGR, 8, 2, GATE_PLL6_CKREFST), _MUX_CFG(MUX_MUXSEL3, RCC_MUXSELCFGR, 12, 2, GATE_PLL7_CKREFST), _MUX_CFG(MUX_MUXSEL4, RCC_MUXSELCFGR, 16, 2, GATE_PLL8_CKREFST), _MUX_CFG(MUX_MUXSEL5, RCC_MUXSELCFGR, 20, 2, MUX_NO_RDY), _MUX_CFG(MUX_MUXSEL6, RCC_MUXSELCFGR, 24, 2, MUX_NO_RDY), _MUX_CFG(MUX_MUXSEL7, RCC_MUXSELCFGR, 28, 2, MUX_NO_RDY), _MUX_CFG(MUX_XBARSEL, RCC_XBAR0CFGR, 0, 4, MUX_NO_RDY), _MUX_CFG(MUX_RTC, RCC_BDCR, 16, 2, MUX_NO_RDY), _MUX_CFG(MUX_D3PER, RCC_D3DCR, 16, 2, MUX_NO_RDY), _MUX_CFG(MUX_MCO1, RCC_MCO1CFGR, 0, 1, MUX_NO_RDY), _MUX_CFG(MUX_MCO2, RCC_MCO2CFGR, 0, 1, MUX_NO_RDY), _MUX_CFG(MUX_ADC12, RCC_ADC12CFGR, 12, 1, MUX_NO_RDY), _MUX_CFG(MUX_ADC3, RCC_ADC3CFGR, 12, 2, MUX_NO_RDY), _MUX_CFG(MUX_USB2PHY1, RCC_USB2PHY1CFGR, 15, 1, MUX_NO_RDY), _MUX_CFG(MUX_USB2PHY2, RCC_USB2PHY2CFGR, 15, 1, MUX_NO_RDY), _MUX_CFG(MUX_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 15, 1, MUX_NO_RDY), _MUX_CFG(MUX_DSIBLANE, RCC_DSICFGR, 12, 1, MUX_NO_RDY), _MUX_CFG(MUX_DSIPHY, RCC_DSICFGR, 15, 1, MUX_NO_RDY), _MUX_CFG(MUX_LVDSPHY, RCC_LVDSCFGR, 15, 1, MUX_NO_RDY), _MUX_CFG(MUX_DTS, RCC_DTSCFGR, 12, 2, MUX_NO_RDY), }; /* * DIV CONFIG */ static const struct div_table_cfg apb_div_table[] = { { .val = 0, .div = 1 }, { .val = 1, .div = 2 }, { .val = 2, .div = 4 }, { .val = 3, .div = 8 }, { .val = 4, .div = 16 }, { .val = 5, .div = 16 }, { .val = 6, .div = 16 }, { .val = 7, .div = 16 }, /* .div = 0 termination cell */ { } }; #define _DIV_CFG(_id, _offset, _shift, _width, _flags, _table, _ready)\ [(_id)] = {\ .offset = (_offset),\ .shift = (_shift),\ .width = (_width),\ .flags = (_flags),\ .table = (_table),\ .ready = (_ready),\ } static const struct div_cfg dividers_mp25[DIV_NB] = { _DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_RDY), _DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, GATE_APB1DIV_RDY), _DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, GATE_APB2DIV_RDY), _DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, GATE_APB3DIV_RDY), _DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, GATE_APB4DIV_RDY), _DIV_CFG(DIV_APBDBG, RCC_APBDBGDIVR, 0, 3, 0, apb_div_table, GATE_APBDBGDIV_RDY), _DIV_CFG(DIV_LSMCU, RCC_LSMCUDIVR, 0, 1, 0, NULL, GATE_LSMCUDIV_RDY), }; enum stm32_osc { OSC_HSI, OSC_HSE, OSC_MSI, OSC_LSI, OSC_LSE, NB_OSCILLATOR }; struct clk_stm32_bypass { uint16_t offset; uint8_t bit_byp; uint8_t bit_digbyp; }; struct clk_stm32_css { uint16_t offset; uint8_t bit_css; }; struct clk_stm32_drive { uint16_t offset; uint8_t drv_shift; uint8_t drv_width; uint8_t drv_default; }; struct clk_oscillator_data { const char *name; unsigned long frequency; uint16_t gate_id; struct clk_stm32_bypass *bypass; struct clk_stm32_css *css; struct clk_stm32_drive *drive; }; #define BYPASS(_offset, _bit_byp, _bit_digbyp) \ (&(struct clk_stm32_bypass){\ .offset = (_offset),\ .bit_byp = (_bit_byp),\ .bit_digbyp = (_bit_digbyp),\ }) #define CSS(_offset, _bit_css) \ (&(struct clk_stm32_css){\ .offset = (_offset),\ .bit_css = (_bit_css),\ }) #define DRIVE(_offset, _shift, _width, _default) \ (&(struct clk_stm32_drive){\ .offset = (_offset),\ .drv_shift = (_shift),\ .drv_width = (_width),\ .drv_default = (_default),\ }) #define OSCILLATOR(idx_osc, _name, _gate_id, _bypass, _css, _drive) \ [(idx_osc)] = (struct clk_oscillator_data){\ .name = (_name),\ .gate_id = (_gate_id),\ .bypass = (_bypass),\ .css = (_css),\ .drive = (_drive),\ } static struct clk_oscillator_data stm32mp25_osc_data[NB_OSCILLATOR] = { OSCILLATOR(OSC_HSI, "clk-hsi", GATE_HSI, NULL, NULL, NULL), OSCILLATOR(OSC_LSI, "clk-lsi", GATE_LSI, NULL, NULL, NULL), OSCILLATOR(OSC_MSI, "clk-msi", GATE_MSI, NULL, NULL, NULL), OSCILLATOR(OSC_LSE, "clk-lse", GATE_LSE, BYPASS(RCC_BDCR, RCC_BDCR_LSEBYP_BIT, RCC_BDCR_LSEDIGBYP_BIT), CSS(RCC_BDCR, RCC_BDCR_LSECSSON_BIT), DRIVE(RCC_BDCR, RCC_BDCR_LSEDRV_SHIFT, RCC_BDCR_LSEDRV_WIDTH, LSEDRV_MEDIUM_HIGH)), OSCILLATOR(OSC_HSE, "clk-hse", GATE_HSE, BYPASS(RCC_OCENSETR, RCC_OCENSETR_HSEBYP_BIT, RCC_OCENSETR_HSEDIGBYP_BIT), CSS(RCC_OCENSETR, RCC_OCENSETR_HSECSSON_BIT), NULL), }; static struct clk_oscillator_data *clk_oscillator_get_data(unsigned int osc_id) { assert(osc_id < ARRAY_SIZE(stm32mp25_osc_data)); return &stm32mp25_osc_data[osc_id]; } static unsigned long clk_stm32_get_rate_oscillator(unsigned int osc_id) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_clk_platdata *pdata = priv->pdata; struct stm32_osci_dt_cfg *osci = &pdata->osci[osc_id]; return osci->freq; } static unsigned long clk_stm32_pll_get_oscillator_rate(unsigned int sel) { unsigned int osc[] = { OSC_HSI, OSC_HSE, OSC_MSI }; assert(sel < ARRAY_SIZE(osc)); return clk_stm32_get_rate_oscillator(osc[sel]); } static void clk_oscillator_set_bypass(struct clk_stm32_priv *priv, struct clk_oscillator_data *osc_data, bool digbyp, bool bypass) { struct clk_stm32_bypass *bypass_data = osc_data->bypass; uintptr_t address = 0; if (!bypass_data) return; address = priv->base + bypass_data->offset; if (digbyp) io_setbits32(address, BIT(bypass_data->bit_digbyp)); if (bypass || digbyp) io_setbits32(address, BIT(bypass_data->bit_byp)); } static void clk_oscillator_set_css(struct clk_stm32_priv *priv, struct clk_oscillator_data *osc_data, bool css) { struct clk_stm32_css *css_data = osc_data->css; if (css_data && css) io_setbits32(priv->base + css_data->offset, BIT(css_data->bit_css)); } static void clk_oscillator_set_drive(struct clk_stm32_priv *priv, struct clk_oscillator_data *osc_data, uint8_t lsedrv) { struct clk_stm32_drive *drive_data = osc_data->drive; uintptr_t address = 0; uint32_t mask = 0; uint32_t value = 0; if (!drive_data) return; address = priv->base + drive_data->offset; mask = SHIFT_U32(BIT(drive_data->drv_width) - 1, drive_data->drv_shift); /* * Warning: not recommended to switch directly from "high drive" * to "medium low drive", and vice-versa. */ value = (io_read32(address) & mask) >> drive_data->drv_shift; while (value != lsedrv) { if (value > lsedrv) value--; else value++; io_clrsetbits32(address, mask, SHIFT_U32(value, drive_data->drv_shift)); } } static void stm32_enable_oscillator_hse(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_HSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE]; if (!osci->freq) return; clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass); /* Enable clock and wait ready bit */ if (stm32_gate_rdy_enable(osc_data->gate_id)) panic("timeout to enable hse clock"); clk_oscillator_set_css(priv, osc_data, osci->css); } static void stm32_enable_oscillator_lse(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; if (!osci->freq) return; if (stm32_gate_is_enabled(osc_data->gate_id)) return; clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass); clk_oscillator_set_drive(priv, osc_data, osci->drive); /* Enable LSE clock, but don't wait ready bit */ stm32_gate_enable(osc_data->gate_id); } static void stm32_enable_oscillator_lsi(struct clk_stm32_priv *priv __unused, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSI); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSI]; if (!osci->freq) return; /* Enable clock and wait ready bit */ if (stm32_gate_rdy_enable(osc_data->gate_id)) panic("timeout to enable lsi clock"); } static TEE_Result clk_stm32_osc_msi_set_rate(struct clk_stm32_priv *priv, unsigned long rate) { uintptr_t address = priv->base + RCC_BDCR; uint32_t mask = RCC_BDCR_MSIFREQSEL; switch (rate) { case RCC_4_MHZ: io_clrbits32_stm32shregs(address, mask); break; case RCC_16_MHZ: io_setbits32_stm32shregs(address, mask); break; default: return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static void stm32_enable_oscillator_msi(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_MSI); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_MSI]; if (!osci->freq) return; if (clk_stm32_osc_msi_set_rate(priv, osci->freq) != TEE_SUCCESS) EMSG("invalid rate %ld Hz for MSI ! (4000000 or 16000000 only)", osci->freq); /* Enable clock and wait ready bit */ if (stm32_gate_rdy_enable(osc_data->gate_id)) panic("timeout to enable msi clock"); } static void stm32_clk_oscillators_lse_set_css(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; clk_oscillator_set_css(priv, osc_data, osci->css); } static int stm32_clk_oscillators_wait_lse_ready(struct clk_stm32_priv *priv __unused, struct stm32_clk_platdata *pdata) { struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE); struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; int ret = 0; if (osci->freq) ret = stm32_gate_wait_ready(osc_data->gate_id, true); return ret; } static void stm32_clk_oscillators_enable(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { stm32_enable_oscillator_hse(priv, pdata); stm32_enable_oscillator_lse(priv, pdata); stm32_enable_oscillator_lsi(priv, pdata); stm32_enable_oscillator_msi(priv, pdata); } enum stm32_pll_id { PLL1_ID, PLL2_ID, PLL3_ID, PLL4_ID, PLL5_ID, PLL6_ID, PLL7_ID, PLL8_ID, PLL_NB }; /* PLL configuration registers offsets from RCC_PLLxCFGR1 */ #define RCC_OFFSET_PLLXCFGR1 0x00 #define RCC_OFFSET_PLLXCFGR2 0x04 #define RCC_OFFSET_PLLXCFGR3 0x08 #define RCC_OFFSET_PLLXCFGR4 0x0C #define RCC_OFFSET_PLLXCFGR5 0x10 #define RCC_OFFSET_PLLXCFGR6 0x18 #define RCC_OFFSET_PLLXCFGR7 0x1C struct stm32_clk_pll { uint16_t gate_id; uint16_t mux_id; uint16_t reg_pllxcfgr1; }; #define CLK_PLL_CFG(_idx, _gate_id, _mux_id, _reg)\ [(_idx)] = {\ .gate_id = (_gate_id),\ .mux_id = (_mux_id),\ .reg_pllxcfgr1 = (_reg),\ } static const struct stm32_clk_pll stm32mp25_clk_pll[PLL_NB] = { CLK_PLL_CFG(PLL1_ID, GATE_PLL1, MUX_MUXSEL5, 0), CLK_PLL_CFG(PLL2_ID, GATE_PLL2, MUX_MUXSEL6, RCC_PLL2CFGR1), CLK_PLL_CFG(PLL3_ID, GATE_PLL3, MUX_MUXSEL7, RCC_PLL3CFGR1), CLK_PLL_CFG(PLL4_ID, GATE_PLL4, MUX_MUXSEL0, RCC_PLL4CFGR1), CLK_PLL_CFG(PLL5_ID, GATE_PLL5, MUX_MUXSEL1, RCC_PLL5CFGR1), CLK_PLL_CFG(PLL6_ID, GATE_PLL6, MUX_MUXSEL2, RCC_PLL6CFGR1), CLK_PLL_CFG(PLL7_ID, GATE_PLL7, MUX_MUXSEL3, RCC_PLL7CFGR1), CLK_PLL_CFG(PLL8_ID, GATE_PLL8, MUX_MUXSEL4, RCC_PLL8CFGR1), }; static const struct stm32_clk_pll *clk_stm32_pll_data(unsigned int idx) { assert(idx < ARRAY_SIZE(stm32mp25_clk_pll)); return &stm32mp25_clk_pll[idx]; } static int stm32_clk_parse_oscillator_fdt(const void *fdt, int node, const char *name, struct stm32_osci_dt_cfg *osci) { int subnode = 0; /* default value when oscillator is not found */ osci->freq = 0; fdt_for_each_subnode(subnode, fdt, node) { const char *cchar = NULL; const fdt32_t *cuint = NULL; int ret = 0; cchar = fdt_get_name(fdt, subnode, &ret); if (!cchar) return ret; if (strncmp(cchar, name, (size_t)ret) || fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) continue; cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); if (!cuint) return ret; osci->freq = fdt32_to_cpu(*cuint); if (fdt_getprop(fdt, subnode, "st,bypass", NULL)) osci->bypass = true; if (fdt_getprop(fdt, subnode, "st,digbypass", NULL)) osci->digbyp = true; if (fdt_getprop(fdt, subnode, "st,css", NULL)) osci->css = true; osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH); return 0; } return 0; } static const char *stm32_clk_get_oscillator_name(enum stm32_osc id) { if (id < NB_OSCILLATOR) return stm32mp25_osc_data[id].name; return NULL; } static int stm32_clk_parse_fdt_all_oscillator(const void *fdt, int node __unused, struct stm32_clk_platdata *pdata) { int fdt_err = 0; size_t i = 0; int osc_node = 0; osc_node = fdt_path_offset(fdt, "/clocks"); if (osc_node < 0) return -FDT_ERR_NOTFOUND; for (i = 0; i < pdata->nosci; i++) { const char *name = NULL; name = stm32_clk_get_oscillator_name((enum stm32_osc)i); if (!name) continue; fdt_err = stm32_clk_parse_oscillator_fdt(fdt, osc_node, name, &pdata->osci[i]); if (fdt_err < 0) panic(); } return 0; } static int clk_stm32_parse_pll_fdt(const void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) { const fdt32_t *cuint = NULL; int subnode_pll = 0; int err = 0; cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); if (!cuint) return 0; subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); if (subnode_pll < 0) return -FDT_ERR_NOTFOUND; if (fdt_read_uint32_array(fdt, subnode_pll, "cfg", pll->cfg, PLLCFG_NB) != 0) panic("cfg property is mandatory"); err = fdt_read_uint32_array(fdt, subnode_pll, "csg", pll->csg, PLLCSG_NB); pll->csg_enabled = (err == 0); if (err == -FDT_ERR_NOTFOUND) err = 0; if (err != 0) return err; pll->enabled = true; pll->frac = fdt_read_uint32_default(fdt, subnode_pll, "frac", 0); if (fdt_read_uint32(fdt, subnode_pll, "src", &pll->src)) panic("src property is mandatory"); return 0; } #define RCC_PLL_NAME_SIZE 20 static int stm32_clk_parse_fdt_all_pll(const void *fdt, int node, struct stm32_clk_platdata *pdata) { unsigned int i = 0; for (i = 0; i < pdata->npll; i++) { struct stm32_pll_dt_cfg *pll = pdata->pll + i; char name[RCC_PLL_NAME_SIZE] = { }; int subnode = 0; snprintf(name, sizeof(name), "st,pll-%u", i + 1); subnode = fdt_subnode_offset(fdt, node, name); if (subnode < 0) continue; if (clk_stm32_parse_pll_fdt(fdt, subnode, pll)) panic(); } return 0; } static int stm32_clk_parse_fdt_opp(const void *fdt, int node, const char *opp_name, struct stm32_clk_opp_cfg *opp_cfg) { int subnode = 0; int nb_opp = 0; int ret = 0; node = fdt_subnode_offset(fdt, node, opp_name); if (node == -FDT_ERR_NOTFOUND) return 0; if (node < 0) return node; fdt_for_each_subnode(subnode, fdt, node) { assert(nb_opp <= MAX_OPP); if (fdt_read_uint32(fdt, subnode, "hz", &opp_cfg->frq)) panic("hz property is mandatory"); if (fdt_read_uint32(fdt, subnode, "st,clksrc", &opp_cfg->src)) panic("st,clksrc property is mandatory"); ret = clk_stm32_parse_pll_fdt(fdt, subnode, &opp_cfg->pll_cfg); if (ret < 0) return ret; opp_cfg++; nb_opp++; } return 0; } static int stm32_clk_parse_fdt_all_opp(const void *fdt, int node, struct stm32_clk_platdata *pdata) { struct stm32_clk_opp_dt_cfg *opp = pdata->opp; node = fdt_subnode_offset(fdt, node, "st,clk_opp"); if (node == -FDT_ERR_NOTFOUND) return 0; if (node < 0) return node; return stm32_clk_parse_fdt_opp(fdt, node, "st,ck_cpu1", opp->cpu1_opp); } static int stm32_clk_parse_fdt(const void *fdt, int node, struct stm32_clk_platdata *pdata) { int err = 0; err = stm32_clk_parse_fdt_all_oscillator(fdt, node, pdata); if (err != 0) return err; err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); if (err != 0) return err; err = stm32_clk_parse_fdt_all_opp(fdt, node, pdata); if (err != 0) return err; err = clk_stm32_parse_fdt_by_name(fdt, node, "st,busclk", pdata->busclk, &pdata->nbusclk); if (err != 0) return err; err = clk_stm32_parse_fdt_by_name(fdt, node, "st,flexgen", pdata->flexgen, &pdata->nflexgen); if (err != 0) return err; err = clk_stm32_parse_fdt_by_name(fdt, node, "st,kerclk", pdata->kernelclk, &pdata->nkernelclk); if (err != 0) return err; pdata->c1msrd = fdt_read_uint32_default(fdt, node, "st,c1msrd", 0); if (fdt_getprop(fdt, node, "st,safe_rst", NULL)) pdata->safe_rst = true; pdata->rcc_base = stm32_rcc_base(); return 0; } static void stm32mp2_a35_ss_on_hsi(void) { uint64_t timeout = 0; /* Nothing to do if clock source is already set on bypass clock */ if (stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK) return; stm32mp_syscfg_write(A35SS_SSC_CHGCLKREQ, A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_EN, A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_MASK); timeout = timeout_init_us(CLKSRC_TIMEOUT); while (!timeout_elapsed(timeout)) if (stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK) break; if (!(stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK)) panic("Cannot switch A35 to bypass clock"); stm32mp_syscfg_write(A35SS_SSC_PLL_EN, 0, A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_MASK); } static void stm32mp2_clk_xbar_on_hsi(struct clk_stm32_priv *priv) { uintptr_t xbar0cfgr = priv->base + RCC_XBAR0CFGR; uint32_t i = 0; for (i = 0; i < XBAR_ROOT_CHANNEL_NB; i++) io_clrsetbits32(xbar0cfgr + (0x4 * i), RCC_XBAR0CFGR_XBAR0SEL_MASK, XBAR_SRC_HSI); } static int stm32mp2_a35_pll1_start(void) { uint64_t timeout = 0; stm32mp_syscfg_write(A35SS_SSC_PLL_EN, A35SS_SSC_PLL_ENABLE_PD_EN, A35SS_SSC_PLL_ENABLE_PD_EN); /* Wait PLL lock */ timeout = timeout_init_us(PLLRDY_TIMEOUT); while (!timeout_elapsed(timeout)) if (stm32mp_syscfg_read(A35SS_SSC_PLL_EN) & A35SS_SSC_PLL_ENABLE_LOCKP_MASK) break; if (!(stm32mp_syscfg_read(A35SS_SSC_PLL_EN) & A35SS_SSC_PLL_ENABLE_LOCKP_MASK)) { EMSG("PLL1 not locked"); return -1; } /* De-assert reset on PLL output clock path */ stm32mp_syscfg_write(A35SS_SSC_PLL_EN, A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_EN, A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_MASK); /* Switch CPU clock to PLL clock */ stm32mp_syscfg_write(A35SS_SSC_CHGCLKREQ, 0, A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_MASK); /* Wait for clock change acknowledge */ timeout = timeout_init_us(CLKSRC_TIMEOUT); while (!timeout_elapsed(timeout)) if (!(stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK)) break; if (stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK) { EMSG("A35 switch to PLL1 failed"); return -1; } return 0; } static void stm32mp2_a35_pll1_config(uint32_t fbdiv, uint32_t refdiv, uint32_t postdiv1, uint32_t postdiv2) { stm32mp_syscfg_write(A35SS_SSC_PLL_FREQ1, SHIFT_U32(refdiv, A35SS_SSC_PLL_FREQ1_REFDIV_SHIFT) | SHIFT_U32(fbdiv, A35SS_SSC_PLL_FREQ1_FBDIV_SHIFT), A35SS_SSC_PLL_FREQ1_MASK); stm32mp_syscfg_write(A35SS_SSC_PLL_FREQ2, SHIFT_U32(postdiv1, A35SS_SSC_PLL_FREQ2_POSTDIV1_SHIFT) | SHIFT_U32(postdiv2, A35SS_SSC_PLL_FREQ2_POSTDIV2_SHIFT), A35SS_SSC_PLL_FREQ2_MASK); } static void clk_stm32_pll_config_output(struct clk_stm32_priv *priv, const struct stm32_clk_pll *pll, uint32_t pllsrc, uint32_t *pllcfg, uint32_t fracv) { uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1; uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2; uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3; uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4; uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6; uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7; int sel = (pllsrc & MUX_SEL_MASK) >> MUX_SEL_SHIFT; unsigned long refclk = clk_stm32_pll_get_oscillator_rate(sel); if (fracv == 0) { /* PLL in integer mode */ /* * No need to check max clock, as oscillator reference clocks * will always be less than 1.2GHz */ if (refclk < PLL_REFCLK_MIN) panic(); io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK); io_clrbits32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN); io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_DACEN); io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS); io_setbits32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST); } else { /* PLL in frac mode */ /* * No need to check max clock, as oscillator reference clocks * will always be less than 1.2GHz */ if (refclk < PLL_FRAC_REFCLK_MIN) panic(); io_clrsetbits32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK, fracv & RCC_PLLxCFGR3_FRACIN_MASK); io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS); io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN); } assert(pllcfg[REFDIV]); io_clrsetbits32(pllxcfgr2, RCC_PLLxCFGR2_FBDIV_MASK, SHIFT_U32(pllcfg[FBDIV], RCC_PLLxCFGR2_FBDIV_SHIFT) & RCC_PLLxCFGR2_FBDIV_MASK); io_clrsetbits32(pllxcfgr2, RCC_PLLxCFGR2_FREFDIV_MASK, pllcfg[REFDIV] & RCC_PLLxCFGR2_FREFDIV_MASK); io_clrsetbits32(pllxcfgr6, RCC_PLLxCFGR6_POSTDIV1_MASK, pllcfg[POSTDIV1] & RCC_PLLxCFGR6_POSTDIV1_MASK); io_clrsetbits32(pllxcfgr7, RCC_PLLxCFGR7_POSTDIV2_MASK, pllcfg[POSTDIV2] & RCC_PLLxCFGR7_POSTDIV2_MASK); if (pllcfg[POSTDIV1] == 0 || pllcfg[POSTDIV2] == 0) { /* Bypass mode */ io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS); io_clrbits32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN); } else { io_clrbits32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS); io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN); } } static void clk_stm32_pll_config_csg(struct clk_stm32_priv *priv, const struct stm32_clk_pll *pll, uint32_t *csg) { uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1; uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3; uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4; uintptr_t pllxcfgr5 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR5; io_clrsetbits32(pllxcfgr5, RCC_PLLxCFGR5_DIVVAL_MASK, csg[DIVVAL] & RCC_PLLxCFGR5_DIVVAL_MASK); io_clrsetbits32(pllxcfgr5, RCC_PLLxCFGR5_SPREAD_MASK, SHIFT_U32(csg[SPREAD], RCC_PLLxCFGR5_SPREAD_SHIFT) & RCC_PLLxCFGR5_SPREAD_MASK); if (csg[DOWNSPREAD] != 0) io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD); else io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD); io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS); io_clrbits32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN); udelay(1); io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN); io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_DACEN); } static struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(unsigned int pll_idx) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_clk_platdata *pdata = priv->pdata; assert(pll_idx < pdata->npll); return &pdata->pll[pll_idx]; } static int clk_stm32_pll_set_mux(struct clk_stm32_priv *priv __unused, uint32_t src) { int mux = (src & MUX_ID_MASK) >> MUX_ID_SHIFT; int sel = (src & MUX_SEL_MASK) >> MUX_SEL_SHIFT; return stm32_mux_set_parent(mux, sel); } static void clk_stm32_pll1_init(struct clk_stm32_priv *priv, int pll_idx __unused, struct stm32_pll_dt_cfg *pll_conf) { int sel = (pll_conf->src & MUX_SEL_MASK) >> MUX_SEL_SHIFT; unsigned long refclk = 0; /* * TODO: check if pll has already good parameters or if we could make * a configuration on the fly. */ stm32mp2_a35_ss_on_hsi(); if (clk_stm32_pll_set_mux(priv, pll_conf->src)) panic(); refclk = clk_stm32_pll_get_oscillator_rate(sel); /* * No need to check max clock, as oscillator reference clocks will * always be less than 1.2GHz */ if (refclk < PLL_REFCLK_MIN) panic(); stm32mp2_a35_pll1_config(pll_conf->cfg[FBDIV], pll_conf->cfg[REFDIV], pll_conf->cfg[POSTDIV1], pll_conf->cfg[POSTDIV2]); if (stm32mp2_a35_pll1_start()) panic(); } static void clk_stm32_pll_init(struct clk_stm32_priv *priv, int pll_idx, struct stm32_pll_dt_cfg *pll_conf) { const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx); uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1; bool spread_spectrum = false; /* * TODO: check if pll has already good parameters or if we could make * a configuration on the fly. */ stm32_gate_rdy_disable(pll->gate_id); if (clk_stm32_pll_set_mux(priv, pll_conf->src)) panic(); clk_stm32_pll_config_output(priv, pll, pll_conf->src, pll_conf->cfg, pll_conf->frac); if (pll_conf->csg_enabled) { clk_stm32_pll_config_csg(priv, pll, pll_conf->csg); spread_spectrum = true; } stm32_gate_rdy_enable(pll->gate_id); if (spread_spectrum) io_clrbits32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST); } static int stm32_clk_pll_configure(struct clk_stm32_priv *priv) { struct stm32_pll_dt_cfg *pll_conf = NULL; size_t i = 0; for (i = 0; i < PLL_NB; i++) { pll_conf = clk_stm32_pll_get_pdata(i); if (pll_conf->enabled) { /* Skip the pll3 (need GPU regulator to configure) */ if (i == PLL3_ID) continue; /* Skip the pll2 (reserved to DDR) */ if (i == PLL2_ID) continue; if (i == PLL1_ID) clk_stm32_pll1_init(priv, i, pll_conf); else clk_stm32_pll_init(priv, i, pll_conf); } } return 0; } #define __WORD_BIT 32 static int wait_predivsr(uint16_t channel) { uintptr_t rcc_base = stm32_rcc_base(); uintptr_t previvsr = 0; uint32_t channel_bit = 0; uint32_t value = 0; if (channel < __WORD_BIT) { previvsr = rcc_base + RCC_PREDIVSR1; channel_bit = BIT(channel); } else { previvsr = rcc_base + RCC_PREDIVSR2; channel_bit = BIT(channel - __WORD_BIT); } if (IO_READ32_POLL_TIMEOUT(previvsr, value, !(value & channel_bit), 0, CLKDIV_TIMEOUT)) { EMSG("Pre divider status: %#"PRIx32, io_read32(previvsr)); return -1; } return 0; } static int wait_findivsr(uint16_t channel) { uintptr_t rcc_base = stm32_rcc_base(); uintptr_t finvivsr = 0; uint32_t channel_bit = 0; uint32_t value = 0; if (channel < __WORD_BIT) { finvivsr = rcc_base + RCC_FINDIVSR1; channel_bit = BIT(channel); } else { finvivsr = rcc_base + RCC_FINDIVSR2; channel_bit = BIT(channel - __WORD_BIT); } if (IO_READ32_POLL_TIMEOUT(finvivsr, value, !(value & channel_bit), 0, CLKDIV_TIMEOUT)) { EMSG("Final divider status: %#"PRIx32, io_read32(finvivsr)); return -1; } return 0; } static int wait_xbar_sts(uint16_t channel) { uintptr_t rcc_base = stm32_rcc_base(); uintptr_t xbar_cfgr = rcc_base + RCC_XBAR0CFGR + (0x4 * channel); uint32_t value = 0; if (IO_READ32_POLL_TIMEOUT(xbar_cfgr, value, !(value & RCC_XBAR0CFGR_XBAR0STS), 0, CLKDIV_TIMEOUT)) { EMSG("XBAR%"PRIu16"CFGR: %#"PRIx32, channel, io_read32(xbar_cfgr)); return -1; } return 0; } static void flexclkgen_config_channel(uint16_t channel, unsigned int clk_src, unsigned int prediv, unsigned int findiv) { uintptr_t rcc_base = stm32_rcc_base(); if (wait_predivsr(channel) != 0) panic(); io_clrsetbits32(rcc_base + RCC_PREDIV0CFGR + (0x4 * channel), RCC_PREDIV0CFGR_PREDIV0_MASK, prediv); if (wait_predivsr(channel) != 0) panic(); if (wait_findivsr(channel) != 0) panic(); io_clrsetbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel), RCC_FINDIV0CFGR_FINDIV0_MASK, findiv); if (wait_findivsr(channel) != 0) panic(); if (wait_xbar_sts(channel) != 0) panic(); io_clrsetbits32(rcc_base + RCC_XBAR0CFGR + (0x4 * channel), RCC_XBAR0CFGR_XBAR0SEL_MASK, clk_src); io_setbits32(rcc_base + RCC_XBAR0CFGR + (0x4 * channel), RCC_XBAR0CFGR_XBAR0EN); if (wait_xbar_sts(channel) != 0) panic(); } static int stm32mp2_clk_flexgen_configure(struct clk_stm32_priv *priv) { struct stm32_clk_platdata *pdata = priv->pdata; uint32_t i = 0; for (i = 0; i < pdata->nflexgen; i++) { uint32_t val = pdata->flexgen[i]; uint32_t cmd = 0; uint32_t cmd_data = 0; unsigned int channel = 0; unsigned int clk_src = 0; unsigned int pdiv = 0; unsigned int fdiv = 0; cmd = (val & CMD_MASK) >> CMD_SHIFT; cmd_data = val & ~CMD_MASK; if (cmd != CMD_FLEXGEN) continue; channel = (cmd_data & FLEX_ID_MASK) >> FLEX_ID_SHIFT; /* * Skip ck_ker_stgen configuration, will be done by * stgen driver. */ if (channel == FLEX_STGEN) continue; clk_src = (cmd_data & FLEX_SEL_MASK) >> FLEX_SEL_SHIFT; pdiv = (cmd_data & FLEX_PDIV_MASK) >> FLEX_PDIV_SHIFT; fdiv = (cmd_data & FLEX_FDIV_MASK) >> FLEX_FDIV_SHIFT; flexclkgen_config_channel(channel, clk_src, pdiv, fdiv); } return 0; } static int stm32_clk_configure_div(struct clk_stm32_priv *priv __unused, uint32_t data) { uint32_t div_id = 0; uint32_t div_n = 0; div_id = (data & DIV_ID_MASK) >> DIV_ID_SHIFT; div_n = (data & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; return stm32_div_set_value(div_id, div_n); } static int stm32_clk_configure_mux(struct clk_stm32_priv *priv __unused, uint32_t data) { int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; return stm32_mux_set_parent(mux, sel); } static int stm32_clk_configure_by_addr_val(struct clk_stm32_priv *priv, uint32_t data) { uint32_t addr = data >> CLK_ADDR_SHIFT; uint32_t val = data & CLK_ADDR_VAL_MASK; io_setbits32(priv->base + addr, val); return 0; } static void stm32_clk_configure_obs(struct clk_stm32_priv *priv, uint32_t data) { uint32_t id = (data & OBS_ID_MASK) >> OBS_ID_SHIFT; uint32_t status = (data & OBS_STATUS_MASK) >> OBS_STATUS_SHIFT; uint32_t int_ext = (data & OBS_INTEXT_MASK) >> OBS_INTEXT_SHIFT; uint32_t div = (data & OBS_DIV_MASK) >> OBS_DIV_SHIFT; uint32_t inv = (data & OBS_INV_MASK) >> OBS_INV_SHIFT; uint32_t sel = (data & OBS_SEL_MASK) >> OBS_SEL_SHIFT; uint32_t reg = 0; uint32_t val = 0; if (!id) reg = RCC_FCALCOBS0CFGR; else reg = RCC_FCALCOBS1CFGR; if (status) val |= RCC_FCALCOBS0CFGR_CKOBSEN; if (int_ext == OBS_EXT) { val |= RCC_FCALCOBS0CFGR_CKOBSEXTSEL; val |= SHIFT_U32(sel, RCC_FCALCOBS0CFGR_CKEXTSEL_SHIFT); } else { val |= SHIFT_U32(sel, RCC_FCALCOBS0CFGR_CKINTSEL_SHIFT); } if (inv) val |= RCC_FCALCOBS0CFGR_CKOBSINV; val |= SHIFT_U32(div, RCC_FCALCOBS0CFGR_CKOBSDIV_SHIFT); io_write32(priv->base + reg, val); } static int stm32_clk_configure(struct clk_stm32_priv *priv, uint32_t val) { uint32_t cmd_data = 0; uint32_t cmd = 0; int ret = 0; if (val & CMD_ADDR_BIT) { cmd_data = val & ~CMD_ADDR_BIT; return stm32_clk_configure_by_addr_val(priv, cmd_data); } cmd = (val & CMD_MASK) >> CMD_SHIFT; cmd_data = val & ~CMD_MASK; switch (cmd) { case CMD_DIV: ret = stm32_clk_configure_div(priv, cmd_data); break; case CMD_MUX: ret = stm32_clk_configure_mux(priv, cmd_data); break; case CMD_OBS: stm32_clk_configure_obs(priv, cmd_data); break; default: EMSG("cmd unknown ! : %#"PRIx32, val); ret = -1; } return ret; } static int stm32_clk_bus_configure(struct clk_stm32_priv *priv) { struct stm32_clk_platdata *pdata = priv->pdata; uint32_t i = 0; for (i = 0; i < pdata->nbusclk; i++) { int ret = 0; ret = stm32_clk_configure(priv, pdata->busclk[i]); if (ret != 0) return ret; } return 0; } static int stm32_clk_kernel_configure(struct clk_stm32_priv *priv) { struct stm32_clk_platdata *pdata = priv->pdata; uint32_t i = 0; for (i = 0; i < pdata->nkernelclk; i++) { int ret = 0; ret = stm32_clk_configure(priv, pdata->kernelclk[i]); if (ret != 0) return ret; } return 0; } static void stm32mp2_init_clock_tree(struct clk_stm32_priv *priv, struct stm32_clk_platdata *pdata) { stm32_clk_oscillators_enable(priv, pdata); /* Come back to HSI for flexgen */ stm32mp2_clk_xbar_on_hsi(priv); if (stm32_clk_pll_configure(priv)) panic("Cannot configure plls"); /* Wait LSE ready before to use it */ if (stm32_clk_oscillators_wait_lse_ready(priv, pdata)) panic("Timeout: to enable LSE"); if (stm32mp2_clk_flexgen_configure(priv)) panic("Cannot configure flexgen"); if (stm32_clk_bus_configure(priv)) panic("Cannot config bus clocks"); if (stm32_clk_kernel_configure(priv)) panic("Cannot configure kernel clocks"); /* Configure LSE css after RTC source configuration */ stm32_clk_oscillators_lse_set_css(priv, pdata); } static TEE_Result clk_stm32_osc_enable(struct clk *clk) { return clk_stm32_gate_ready_ops.enable(clk); } static void clk_stm32_osc_disable(struct clk *clk) { clk_stm32_gate_ready_ops.disable(clk); } static const struct clk_ops clk_stm32_osc_ops = { .enable = clk_stm32_osc_enable, .disable = clk_stm32_osc_disable, }; static unsigned long clk_stm32_msi_get_rate(struct clk *clk __unused, unsigned long prate __unused) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); uintptr_t address = priv->base + RCC_BDCR; if ((io_read32(address) & RCC_BDCR_MSIFREQSEL)) return RCC_16_MHZ; return RCC_4_MHZ; } static TEE_Result clk_stm32_msi_set_rate(struct clk *clk __unused, unsigned long rate, unsigned long prate __unused) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); return clk_stm32_osc_msi_set_rate(priv, rate); } static const struct clk_ops clk_stm32_oscillator_msi_ops = { .enable = clk_stm32_osc_enable, .disable = clk_stm32_osc_disable, .get_rate = clk_stm32_msi_get_rate, .set_rate = clk_stm32_msi_set_rate, }; static TEE_Result clk_stm32_hse_div_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { return clk_stm32_divider_set_rate(clk, rate, parent_rate); } static const struct clk_ops clk_stm32_hse_div_ops = { .get_rate = clk_stm32_divider_get_rate, .set_rate = clk_stm32_hse_div_set_rate, }; static TEE_Result clk_stm32_hsediv2_enable(struct clk *clk) { return clk_stm32_gate_ops.enable(clk); } static void clk_stm32_hsediv2_disable(struct clk *clk) { clk_stm32_gate_ops.disable(clk); } static unsigned long clk_stm32_hsediv2_get_rate(struct clk *clk __unused, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); uintptr_t addr = priv->base + RCC_OCENSETR; if (io_read32(addr) & RCC_OCENSETR_HSEDIV2BYP) return prate; return prate / 2; } static const struct clk_ops clk_hsediv2_ops = { .enable = clk_stm32_hsediv2_enable, .disable = clk_stm32_hsediv2_disable, .get_rate = clk_stm32_hsediv2_get_rate, }; struct clk_stm32_pll_cfg { uint32_t pll_offset; int gate_id; int mux_id; }; static unsigned long clk_get_pll1_fvco_rate(unsigned long refclk) { uint32_t reg = stm32mp_syscfg_read(A35SS_SSC_PLL_FREQ1); uint32_t fbdiv = 0; uint32_t refdiv = 0; unsigned long freq = 0; fbdiv = (reg & A35SS_SSC_PLL_FREQ1_FBDIV_MASK) >> A35SS_SSC_PLL_FREQ1_FBDIV_SHIFT; refdiv = (reg & A35SS_SSC_PLL_FREQ1_REFDIV_MASK) >> A35SS_SSC_PLL_FREQ1_REFDIV_SHIFT; if (!refdiv || MUL_OVERFLOW(refclk, fbdiv, &freq)) panic(); return freq / refdiv; } static unsigned long clk_stm32_pll1_get_rate(struct clk *clk __unused, unsigned long prate) { uint32_t reg = stm32mp_syscfg_read(A35SS_SSC_PLL_FREQ2); unsigned long dfout = 0; uint32_t postdiv1 = 0; uint32_t postdiv2 = 0; postdiv1 = (reg & A35SS_SSC_PLL_FREQ2_POSTDIV1_MASK) >> A35SS_SSC_PLL_FREQ2_POSTDIV1_SHIFT; postdiv2 = (reg & A35SS_SSC_PLL_FREQ2_POSTDIV2_MASK) >> A35SS_SSC_PLL_FREQ2_POSTDIV2_SHIFT; if (postdiv1 == 0 || postdiv2 == 0) dfout = prate; else dfout = clk_get_pll1_fvco_rate(prate) / (postdiv1 * postdiv2); return dfout; } static struct stm32_clk_opp_cfg * clk_stm32_get_opp_config(struct stm32_clk_opp_cfg *opp_cfg, unsigned long rate) { unsigned int i = 0; for (i = 0; i < MAX_OPP && opp_cfg->frq; i++, opp_cfg++) if (opp_cfg->frq == rate) return opp_cfg; return NULL; } static TEE_Result clk_stm32_pll1_set_rate(struct clk *clk __unused, unsigned long rate, unsigned long parent_rate __unused) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_clk_platdata *pdata = priv->pdata; struct stm32_pll_dt_cfg *pll_conf = NULL; struct stm32_clk_opp_cfg *opp = NULL; opp = clk_stm32_get_opp_config(pdata->opp->cpu1_opp, rate); if (!opp) return TEE_ERROR_GENERIC; pll_conf = &opp->pll_cfg; clk_stm32_pll1_init(priv, PLL1_ID, pll_conf); return TEE_SUCCESS; } static size_t clk_stm32_pll_get_parent(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; return stm32_mux_get_parent(cfg->mux_id); } static const struct clk_ops clk_stm32_pll1_ops = { .get_parent = clk_stm32_pll_get_parent, .get_rate = clk_stm32_pll1_get_rate, .set_rate = clk_stm32_pll1_set_rate, }; static unsigned long clk_get_pll_fvco(uint32_t offset_base, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); uintptr_t pllxcfgr1 = priv->base + offset_base; uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2; uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3; unsigned long fvco = 0; uint32_t fracin = 0; uint32_t fbdiv = 0; uint32_t refdiv = 0; fracin = io_read32(pllxcfgr3) & RCC_PLLxCFGR3_FRACIN_MASK; fbdiv = (io_read32(pllxcfgr2) & RCC_PLLxCFGR2_FBDIV_MASK) >> RCC_PLLxCFGR2_FBDIV_SHIFT; refdiv = io_read32(pllxcfgr2) & RCC_PLLxCFGR2_FREFDIV_MASK; assert(refdiv); if (fracin) { unsigned long long numerator = 0; unsigned long long denominator = 0; numerator = SHIFT_U64(fbdiv, 24) + fracin; numerator = prate * numerator; denominator = SHIFT_U64(refdiv, 24); fvco = (unsigned long)(numerator / denominator); } else { fvco = (unsigned long)(prate * fbdiv / refdiv); } return fvco; } static unsigned long clk_stm32_pll_get_rate(struct clk *clk __unused, unsigned long prate) { struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct clk_stm32_pll_cfg *cfg = clk->priv; uintptr_t pllxcfgr1 = priv->base + cfg->pll_offset; uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4; uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6; uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7; unsigned long dfout = 0; uint32_t postdiv1 = 0; uint32_t postdiv2 = 0; postdiv1 = io_read32(pllxcfgr6) & RCC_PLLxCFGR6_POSTDIV1_MASK; postdiv2 = io_read32(pllxcfgr7) & RCC_PLLxCFGR7_POSTDIV2_MASK; if ((io_read32(pllxcfgr4) & RCC_PLLxCFGR4_BYPASS) || !postdiv1 || !postdiv2) dfout = prate; else dfout = clk_get_pll_fvco(cfg->pll_offset, prate) / (postdiv1 * postdiv2); return dfout; } static TEE_Result clk_stm32_pll_enable(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; if (stm32_gate_rdy_enable(cfg->gate_id)) { EMSG("%s timeout", clk_get_name(clk)); return TEE_ERROR_TIMEOUT; } return TEE_SUCCESS; } static void clk_stm32_pll_disable(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; if (stm32_gate_rdy_disable(cfg->gate_id)) { EMSG("%s timeout", clk_get_name(clk)); panic(); } } static const struct clk_ops clk_stm32_pll_ops = { .get_parent = clk_stm32_pll_get_parent, .get_rate = clk_stm32_pll_get_rate, .enable = clk_stm32_pll_enable, .disable = clk_stm32_pll_disable, }; static TEE_Result clk_stm32_pll3_enable(struct clk *clk) { struct clk_stm32_pll_cfg *cfg = clk->priv; struct clk_stm32_priv *priv = clk_stm32_get_priv(); struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(PLL3_ID); struct clk *parent = NULL; size_t pidx = 0; /* ck_icn_p_gpu activate */ stm32_gate_enable(GATE_GPU); clk_stm32_pll_init(priv, PLL3_ID, pll_conf); if (stm32_gate_rdy_enable(cfg->gate_id)) { EMSG("%s timeout", clk_get_name(clk)); return TEE_ERROR_TIMEOUT; } /* Update parent */ pidx = clk_stm32_pll_get_parent(clk); parent = clk_get_parent_by_index(clk, pidx); clk->parent = parent; return TEE_SUCCESS; } static void clk_stm32_pll3_disable(struct clk *clk) { clk_stm32_pll_disable(clk); stm32_gate_disable(GATE_GPU); } static const struct clk_ops clk_stm32_pll3_ops = { .get_parent = clk_stm32_pll_get_parent, .get_rate = clk_stm32_pll_get_rate, .enable = clk_stm32_pll3_enable, .disable = clk_stm32_pll3_disable, }; struct clk_stm32_flexgen_cfg { int flex_id; }; static size_t clk_stm32_flexgen_get_parent(struct clk *clk) { struct clk_stm32_flexgen_cfg *cfg = clk->priv; uintptr_t rcc_base = clk_stm32_get_rcc_base(); uint32_t address = 0; address = rcc_base + RCC_XBAR0CFGR + (cfg->flex_id * 4); return io_read32(address) & RCC_XBAR0CFGR_XBAR0SEL_MASK; } static TEE_Result clk_stm32_flexgen_set_parent(struct clk *clk, size_t pidx) { uintptr_t rcc_base = clk_stm32_get_rcc_base(); struct clk_stm32_flexgen_cfg *cfg = clk->priv; uint16_t channel = cfg->flex_id * 4; io_clrsetbits32(rcc_base + RCC_XBAR0CFGR + (channel), RCC_XBAR0CFGR_XBAR0SEL_MASK, pidx); if (wait_xbar_sts(channel)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static unsigned long clk_stm32_flexgen_get_rate(struct clk *clk __unused, unsigned long prate) { struct clk_stm32_flexgen_cfg *cfg = clk->priv; uintptr_t rcc_base = clk_stm32_get_rcc_base(); uint32_t prediv = 0; uint32_t findiv = 0; uint8_t channel = cfg->flex_id; unsigned long freq = prate; prediv = io_read32(rcc_base + RCC_PREDIV0CFGR + (0x4 * channel)) & RCC_PREDIV0CFGR_PREDIV0_MASK; findiv = io_read32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel)) & RCC_FINDIV0CFGR_FINDIV0_MASK; if (freq == 0) return 0; switch (prediv) { case 0x0: break; case 0x1: freq /= 2; break; case 0x3: freq /= 4; break; case 0x3FF: freq /= 1024; break; default: EMSG("Unsupported PREDIV value (%#"PRIx32")", prediv); panic(); break; } freq /= findiv + 1; return freq; } static unsigned long clk_stm32_flexgen_get_round_rate(unsigned long rate, unsigned long prate, unsigned int *prediv, unsigned int *findiv) { unsigned int pre_val[] = { 0x0, 0x1, 0x3, 0x3FF }; unsigned int pre_div[] = { 1, 2, 4, 1024 }; long best_diff = LONG_MAX; unsigned int i = 0; *prediv = 0; *findiv = 0; for (i = 0; i < ARRAY_SIZE(pre_div); i++) { unsigned long freq = 0; unsigned long ratio = 0; long diff = 0L; freq = UDIV_ROUND_NEAREST((uint64_t)prate, pre_div[i]); ratio = UDIV_ROUND_NEAREST((uint64_t)freq, rate); if (ratio == 0) ratio = 1; else if (ratio > 64) ratio = 64; freq = UDIV_ROUND_NEAREST((uint64_t)freq, ratio); if (freq < rate) diff = rate - freq; else diff = freq - rate; if (diff < best_diff) { best_diff = diff; *prediv = pre_val[i]; *findiv = ratio - 1; if (diff == 0) break; } } return (prate / (*prediv + 1)) / (*findiv + 1); } static TEE_Result clk_stm32_flexgen_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_stm32_flexgen_cfg *cfg = clk->priv; uint8_t channel = cfg->flex_id; uintptr_t rcc_base = stm32_rcc_base(); unsigned int prediv = 0; unsigned int findiv = 0; clk_stm32_flexgen_get_round_rate(rate, parent_rate, &prediv, &findiv); if (wait_predivsr(channel) != 0) panic(); io_clrsetbits32(rcc_base + RCC_PREDIV0CFGR + (0x4 * channel), RCC_PREDIV0CFGR_PREDIV0_MASK, prediv); if (wait_predivsr(channel) != 0) panic(); if (wait_findivsr(channel) != 0) panic(); io_clrsetbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel), RCC_FINDIV0CFGR_FINDIV0_MASK, findiv); if (wait_findivsr(channel) != 0) panic(); return TEE_SUCCESS; } static TEE_Result clk_stm32_flexgen_enable(struct clk *clk) { struct clk_stm32_flexgen_cfg *cfg = clk->priv; uintptr_t rcc_base = clk_stm32_get_rcc_base(); uint8_t channel = cfg->flex_id; io_setbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel), RCC_FINDIV0CFGR_FINDIV0EN); return TEE_SUCCESS; } static void clk_stm32_flexgen_disable(struct clk *clk) { struct clk_stm32_flexgen_cfg *cfg = clk->priv; uintptr_t rcc_base = clk_stm32_get_rcc_base(); uint8_t channel = cfg->flex_id; io_clrbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel), RCC_FINDIV0CFGR_FINDIV0EN); } static const struct clk_ops clk_stm32_flexgen_ops = { .get_rate = clk_stm32_flexgen_get_rate, .set_rate = clk_stm32_flexgen_set_rate, .get_parent = clk_stm32_flexgen_get_parent, .set_parent = clk_stm32_flexgen_set_parent, .enable = clk_stm32_flexgen_enable, .disable = clk_stm32_flexgen_disable, }; static size_t clk_cpu1_get_parent(struct clk *clk __unused) { uint32_t reg = stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ); return (reg & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK) >> A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_SHIFT; } static const struct clk_ops clk_stm32_cpu1_ops = { .get_parent = clk_cpu1_get_parent, }; #define APB_DIV_MASK GENMASK_32(2, 0) #define TIM_PRE_MASK BIT(0) static unsigned long ck_timer_get_rate_ops(struct clk *clk, unsigned long prate) { struct clk_stm32_timer_cfg *cfg = clk->priv; uintptr_t rcc_base = clk_stm32_get_rcc_base(); uint32_t prescaler = 0; uint32_t timpre = 0; prescaler = io_read32(rcc_base + cfg->apbdiv) & APB_DIV_MASK; timpre = io_read32(rcc_base + cfg->timpre) & TIM_PRE_MASK; if (prescaler == 0) return prate; return prate * (timpre + 1) * 2; }; static const struct clk_ops ck_timer_ops = { .get_rate = ck_timer_get_rate_ops, }; #define PLL_PARENTS { &ck_hsi, &ck_hse, &ck_msi } #define PLL_NUM_PATENTS 3 #define STM32_OSC(_name, _flags, _gate_id)\ struct clk _name = {\ .ops = &clk_stm32_osc_ops,\ .priv = &(struct clk_stm32_gate_cfg){\ .gate_id = (_gate_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { NULL },\ } #define STM32_OSC_MSI(_name, _flags, _gate_id)\ struct clk _name = {\ .ops = &clk_stm32_oscillator_msi_ops,\ .priv = &(struct clk_stm32_gate_cfg){\ .gate_id = (_gate_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { NULL },\ } #define STM32_HSE_DIV2(_name, _parent, _flags, _gate_id)\ struct clk _name = {\ .ops = &clk_hsediv2_ops,\ .priv = &(struct clk_stm32_gate_cfg){\ .gate_id = (_gate_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { (_parent) },\ } #define STM32_HSE_RTC(_name, _parent, _flags, _div_id)\ struct clk _name = {\ .ops = &clk_stm32_hse_div_ops,\ .priv = &(struct clk_stm32_div_cfg){\ .div_id = (_div_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { (_parent) },\ } #define STM32_PLL1(_name, _flags, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_pll1_ops,\ .priv = &(struct clk_stm32_pll_cfg){\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = PLL_NUM_PATENTS,\ .parents = PLL_PARENTS,\ } #define STM32_PLL2(_name, _flags, _reg, _gate_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_pll_ops,\ .priv = &(struct clk_stm32_pll_cfg){\ .pll_offset = (_reg),\ .gate_id = (_gate_id),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = PLL_NUM_PATENTS,\ .parents = PLL_PARENTS,\ } #define STM32_PLL3(_name, _flags, _reg, _gate_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_pll3_ops,\ .priv = &(struct clk_stm32_pll_cfg){\ .pll_offset = (_reg),\ .gate_id = (_gate_id),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = PLL_NUM_PATENTS,\ .parents = PLL_PARENTS,\ } #define STM32_PLLS(_name, _flags, _reg, _gate_id, _mux_id)\ struct clk _name = {\ .ops = &clk_stm32_pll_ops,\ .priv = &(struct clk_stm32_pll_cfg){\ .pll_offset = (_reg),\ .gate_id = (_gate_id),\ .mux_id = (_mux_id),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = PLL_NUM_PATENTS,\ .parents = PLL_PARENTS,\ } static STM32_FIXED_RATE(ck_off, RCC_0_MHZ); static STM32_FIXED_RATE(ck_obser0, 0); static STM32_FIXED_RATE(ck_obser1, 0); static STM32_FIXED_RATE(spdifsymb, 0); static STM32_FIXED_RATE(txbyteclk, 27000000); /* Oscillator clocks */ static STM32_OSC(ck_hsi, 0, GATE_HSI); static STM32_OSC(ck_hse, 0, GATE_HSE); static STM32_OSC_MSI(ck_msi, 0, GATE_MSI); static STM32_OSC(ck_lsi, 0, GATE_LSI); static STM32_OSC(ck_lse, 0, GATE_LSE); static STM32_HSE_DIV2(ck_hse_div2, &ck_hse, 0, GATE_HSEDIV2); static STM32_HSE_RTC(ck_hse_rtc, &ck_hse, 0, DIV_RTC); static STM32_FIXED_FACTOR(i2sckin, NULL, 0, 1, 1); static STM32_PLL1(ck_pll1, 0, MUX_MUXSEL5); static STM32_PLL2(ck_pll2, 0, RCC_PLL2CFGR1, GATE_PLL2, MUX_MUXSEL6); static STM32_PLL3(ck_pll3, 0, RCC_PLL3CFGR1, GATE_PLL3, MUX_MUXSEL7); static STM32_PLLS(ck_pll4, 0, RCC_PLL4CFGR1, GATE_PLL4, MUX_MUXSEL0); static STM32_PLLS(ck_pll5, 0, RCC_PLL5CFGR1, GATE_PLL5, MUX_MUXSEL1); static STM32_PLLS(ck_pll6, 0, RCC_PLL6CFGR1, GATE_PLL6, MUX_MUXSEL2); static STM32_PLLS(ck_pll7, 0, RCC_PLL7CFGR1, GATE_PLL7, MUX_MUXSEL3); static STM32_PLLS(ck_pll8, 0, RCC_PLL8CFGR1, GATE_PLL8, MUX_MUXSEL4); #define STM32_FLEXGEN(_name, _flags, _flex_id)\ struct clk _name = {\ .ops = &clk_stm32_flexgen_ops,\ .priv = &(struct clk_stm32_flexgen_cfg){\ .flex_id = (_flex_id),\ },\ .name = #_name,\ .flags = (_flags) | CLK_SET_RATE_UNGATE,\ .num_parents = 15,\ .parents = {\ &ck_pll4, &ck_pll5, &ck_pll6, &ck_pll7, &ck_pll8,\ &ck_hsi, &ck_hse, &ck_msi, &ck_hsi, &ck_hse, &ck_msi,\ &spdifsymb, &i2sckin, &ck_lsi, &ck_lse\ },\ } static STM32_FLEXGEN(ck_icn_hs_mcu, 0, 0); static STM32_FLEXGEN(ck_icn_sdmmc, 0, 1); static STM32_FLEXGEN(ck_icn_ddr, 0, 2); static STM32_FLEXGEN(ck_icn_display, 0, 3); static STM32_FLEXGEN(ck_icn_hsl, 0, 4); static STM32_FLEXGEN(ck_icn_nic, 0, 5); static STM32_FLEXGEN(ck_icn_vid, 0, 6); static STM32_DIVIDER(ck_icn_ls_mcu, &ck_icn_hs_mcu, 0, DIV_LSMCU); static STM32_FLEXGEN(ck_flexgen_07, 0, 7); static STM32_FLEXGEN(ck_flexgen_08, 0, 8); static STM32_FLEXGEN(ck_flexgen_09, 0, 9); static STM32_FLEXGEN(ck_flexgen_10, 0, 10); static STM32_FLEXGEN(ck_flexgen_11, 0, 11); static STM32_FLEXGEN(ck_flexgen_12, 0, 12); static STM32_FLEXGEN(ck_flexgen_13, 0, 13); static STM32_FLEXGEN(ck_flexgen_14, 0, 14); static STM32_FLEXGEN(ck_flexgen_15, 0, 15); static STM32_FLEXGEN(ck_flexgen_16, 0, 16); static STM32_FLEXGEN(ck_flexgen_17, 0, 17); static STM32_FLEXGEN(ck_flexgen_18, 0, 18); static STM32_FLEXGEN(ck_flexgen_19, 0, 19); static STM32_FLEXGEN(ck_flexgen_20, 0, 20); static STM32_FLEXGEN(ck_flexgen_21, 0, 21); static STM32_FLEXGEN(ck_flexgen_22, 0, 22); static STM32_FLEXGEN(ck_flexgen_23, 0, 23); static STM32_FLEXGEN(ck_flexgen_24, 0, 24); static STM32_FLEXGEN(ck_flexgen_25, 0, 25); static STM32_FLEXGEN(ck_flexgen_26, 0, 26); static STM32_FLEXGEN(ck_flexgen_27, 0, 27); static STM32_FLEXGEN(ck_flexgen_28, 0, 28); static STM32_FLEXGEN(ck_flexgen_29, 0, 29); static STM32_FLEXGEN(ck_flexgen_30, 0, 30); static STM32_FLEXGEN(ck_flexgen_31, 0, 31); static STM32_FLEXGEN(ck_flexgen_32, 0, 32); static STM32_FLEXGEN(ck_flexgen_33, 0, 33); static STM32_FLEXGEN(ck_flexgen_34, 0, 34); static STM32_FLEXGEN(ck_flexgen_35, 0, 35); static STM32_FLEXGEN(ck_flexgen_36, 0, 36); static STM32_FLEXGEN(ck_flexgen_37, 0, 37); static STM32_FLEXGEN(ck_flexgen_38, 0, 38); static STM32_FLEXGEN(ck_flexgen_39, 0, 39); static STM32_FLEXGEN(ck_flexgen_40, 0, 40); static STM32_FLEXGEN(ck_flexgen_41, 0, 41); static STM32_FLEXGEN(ck_flexgen_42, 0, 42); static STM32_FLEXGEN(ck_flexgen_43, 0, 43); static STM32_FLEXGEN(ck_flexgen_44, 0, 44); static STM32_FLEXGEN(ck_flexgen_45, 0, 45); static STM32_FLEXGEN(ck_flexgen_46, 0, 46); static STM32_FLEXGEN(ck_flexgen_47, 0, 47); static STM32_FLEXGEN(ck_flexgen_48, 0, 48); static STM32_FLEXGEN(ck_flexgen_49, 0, 49); static STM32_FLEXGEN(ck_flexgen_50, 0, 50); static STM32_FLEXGEN(ck_flexgen_51, 0, 51); static STM32_FLEXGEN(ck_flexgen_52, 0, 52); static STM32_FLEXGEN(ck_flexgen_53, 0, 53); static STM32_FLEXGEN(ck_flexgen_54, 0, 54); static STM32_FLEXGEN(ck_flexgen_55, 0, 55); static STM32_FLEXGEN(ck_flexgen_56, 0, 56); static STM32_FLEXGEN(ck_flexgen_57, 0, 57); static STM32_FLEXGEN(ck_flexgen_58, 0, 58); static STM32_FLEXGEN(ck_flexgen_59, 0, 59); static STM32_FLEXGEN(ck_flexgen_60, 0, 60); static STM32_FLEXGEN(ck_flexgen_61, 0, 61); static STM32_FLEXGEN(ck_flexgen_62, 0, 62); static STM32_FLEXGEN(ck_flexgen_63, 0, 63); static struct clk ck_cpu1 = { .ops = &clk_stm32_cpu1_ops, .name = "ck_cpu1", .flags = CLK_SET_RATE_PARENT, .num_parents = 2, .parents = { &ck_pll1, &ck_flexgen_63 }, }; static STM32_DIVIDER(ck_icn_apb1, &ck_icn_ls_mcu, 0, DIV_APB1); static STM32_DIVIDER(ck_icn_apb2, &ck_icn_ls_mcu, 0, DIV_APB2); static STM32_DIVIDER(ck_icn_apb3, &ck_icn_ls_mcu, 0, DIV_APB3); static STM32_DIVIDER(ck_icn_apb4, &ck_icn_ls_mcu, 0, DIV_APB4); static STM32_COMPOSITE(ck_icn_apbdbg, 1, { &ck_icn_ls_mcu }, 0, GATE_DBG, DIV_APBDBG, NO_MUX); #define STM32_TIMER(_name, _parent, _flags, _apbdiv, _timpre)\ struct clk _name = {\ .ops = &ck_timer_ops,\ .priv = &(struct clk_stm32_timer_cfg){\ .apbdiv = (_apbdiv),\ .timpre = (_timpre),\ },\ .name = #_name,\ .flags = (_flags),\ .num_parents = 1,\ .parents = { _parent },\ } /* Kernel Timers */ static STM32_TIMER(ck_timg1, &ck_icn_apb1, 0, RCC_APB1DIVR, RCC_TIMG1PRER); static STM32_TIMER(ck_timg2, &ck_icn_apb2, 0, RCC_APB2DIVR, RCC_TIMG2PRER); /* Clocks under RCC RIF protection */ static STM32_GATE(ck_sys_dbg, &ck_icn_apbdbg, 0, GATE_DBG); static STM32_GATE(ck_icn_p_stm, &ck_icn_apbdbg, 0, GATE_STM); static STM32_GATE(ck_icn_s_stm, &ck_icn_ls_mcu, 0, GATE_STM); static STM32_GATE(ck_ker_tsdbg, &ck_flexgen_43, 0, GATE_DBG); static STM32_GATE(ck_ker_tpiu, &ck_flexgen_44, 0, GATE_TRACE); static STM32_GATE(ck_icn_p_etr, &ck_icn_apbdbg, 0, GATE_ETR); static STM32_GATE(ck_icn_m_etr, &ck_flexgen_45, 0, GATE_ETR); static STM32_GATE(ck_sys_atb, &ck_flexgen_45, 0, GATE_DBG); static STM32_GATE(ck_icn_s_sysram, &ck_icn_hs_mcu, 0, GATE_SYSRAM); static STM32_GATE(ck_icn_s_vderam, &ck_icn_hs_mcu, 0, GATE_VDERAM); static STM32_GATE(ck_icn_s_retram, &ck_icn_hs_mcu, 0, GATE_RETRAM); static STM32_GATE(ck_icn_s_bkpsram, &ck_icn_ls_mcu, 0, GATE_BKPSRAM); static STM32_GATE(ck_icn_s_sram1, &ck_icn_hs_mcu, 0, GATE_SRAM1); static STM32_GATE(ck_icn_s_sram2, &ck_icn_hs_mcu, 0, GATE_SRAM2); static STM32_GATE(ck_icn_s_lpsram1, &ck_icn_ls_mcu, 0, GATE_LPSRAM1); static STM32_GATE(ck_icn_s_lpsram2, &ck_icn_ls_mcu, 0, GATE_LPSRAM2); static STM32_GATE(ck_icn_s_lpsram3, &ck_icn_ls_mcu, 0, GATE_LPSRAM3); static STM32_GATE(ck_icn_p_hpdma1, &ck_icn_ls_mcu, 0, GATE_HPDMA1); static STM32_GATE(ck_icn_p_hpdma2, &ck_icn_ls_mcu, 0, GATE_HPDMA2); static STM32_GATE(ck_icn_p_hpdma3, &ck_icn_ls_mcu, 0, GATE_HPDMA3); static STM32_GATE(ck_icn_p_lpdma, &ck_icn_ls_mcu, 0, GATE_LPDMA); static STM32_GATE(ck_icn_p_ipcc1, &ck_icn_ls_mcu, 0, GATE_IPCC1); static STM32_GATE(ck_icn_p_ipcc2, &ck_icn_ls_mcu, 0, GATE_IPCC2); static STM32_GATE(ck_icn_p_hsem, &ck_icn_ls_mcu, 0, GATE_HSEM); static STM32_GATE(ck_icn_p_gpioa, &ck_icn_ls_mcu, 0, GATE_GPIOA); static STM32_GATE(ck_icn_p_gpiob, &ck_icn_ls_mcu, 0, GATE_GPIOB); static STM32_GATE(ck_icn_p_gpioc, &ck_icn_ls_mcu, 0, GATE_GPIOC); static STM32_GATE(ck_icn_p_gpiod, &ck_icn_ls_mcu, 0, GATE_GPIOD); static STM32_GATE(ck_icn_p_gpioe, &ck_icn_ls_mcu, 0, GATE_GPIOE); static STM32_GATE(ck_icn_p_gpiof, &ck_icn_ls_mcu, 0, GATE_GPIOF); static STM32_GATE(ck_icn_p_gpiog, &ck_icn_ls_mcu, 0, GATE_GPIOG); static STM32_GATE(ck_icn_p_gpioh, &ck_icn_ls_mcu, 0, GATE_GPIOH); static STM32_GATE(ck_icn_p_gpioi, &ck_icn_ls_mcu, 0, GATE_GPIOI); static STM32_GATE(ck_icn_p_gpioj, &ck_icn_ls_mcu, 0, GATE_GPIOJ); static STM32_GATE(ck_icn_p_gpiok, &ck_icn_ls_mcu, 0, GATE_GPIOK); static STM32_GATE(ck_icn_p_gpioz, &ck_icn_ls_mcu, 0, GATE_GPIOZ); static STM32_GATE(ck_icn_p_rtc, &ck_icn_ls_mcu, 0, GATE_RTC); static STM32_COMPOSITE(ck_rtc, 4, PARENT(&ck_off, &ck_lse, &ck_lsi, &ck_hse_rtc), 0, GATE_RTCCK, NO_DIV, MUX_RTC); static STM32_GATE(ck_icn_p_bsec, &ck_icn_apb3, 0, GATE_BSEC); static STM32_GATE(ck_icn_p_ddrphyc, &ck_icn_ls_mcu, 0, GATE_DDRPHYCAPB); static STM32_GATE(ck_icn_p_risaf4, &ck_icn_ls_mcu, 0, GATE_DDRCP); static STM32_GATE(ck_icn_s_ddr, &ck_icn_ddr, 0, GATE_DDRCP); static STM32_GATE(ck_icn_p_ddrc, &ck_icn_apb4, 0, GATE_DDRCAPB); static STM32_GATE(ck_icn_p_ddrcfg, &ck_icn_apb4, 0, GATE_DDRCFG); static STM32_GATE(ck_icn_p_syscpu1, &ck_icn_ls_mcu, 0, GATE_SYSCPU1); static STM32_GATE(ck_icn_p_is2m, &ck_icn_apb3, 0, GATE_IS2M); static STM32_COMPOSITE(ck_mco1, 2, PARENT(&ck_flexgen_61, &ck_obser0), 0, GATE_MCO1, NO_DIV, MUX_MCO1); static STM32_COMPOSITE(ck_mco2, 2, PARENT(&ck_flexgen_62, &ck_obser1), 0, GATE_MCO2, NO_DIV, MUX_MCO2); static STM32_GATE(ck_icn_s_ospi1, &ck_icn_hs_mcu, 0, GATE_OSPI1); static STM32_GATE(ck_ker_ospi1, &ck_flexgen_48, 0, GATE_OSPI1); static STM32_GATE(ck_icn_s_ospi2, &ck_icn_hs_mcu, 0, GATE_OSPI2); static STM32_GATE(ck_ker_ospi2, &ck_flexgen_49, 0, GATE_OSPI2); static STM32_GATE(ck_icn_p_fmc, &ck_icn_ls_mcu, 0, GATE_FMC); static STM32_GATE(ck_ker_fmc, &ck_flexgen_50, 0, GATE_FMC); /* Kernel Clocks */ static STM32_GATE(ck_icn_p_cci, &ck_icn_ls_mcu, 0, GATE_CCI); static STM32_GATE(ck_icn_p_crc, &ck_icn_ls_mcu, 0, GATE_CRC); static STM32_GATE(ck_icn_p_ospiiom, &ck_icn_ls_mcu, 0, GATE_OSPIIOM); static STM32_GATE(ck_icn_p_hash, &ck_icn_ls_mcu, 0, GATE_HASH); static STM32_GATE(ck_icn_p_rng, &ck_icn_ls_mcu, 0, GATE_RNG); static STM32_GATE(ck_icn_p_cryp1, &ck_icn_ls_mcu, 0, GATE_CRYP1); static STM32_GATE(ck_icn_p_cryp2, &ck_icn_ls_mcu, 0, GATE_CRYP2); static STM32_GATE(ck_icn_p_saes, &ck_icn_ls_mcu, 0, GATE_SAES); static STM32_GATE(ck_icn_p_pka, &ck_icn_ls_mcu, 0, GATE_PKA); static STM32_GATE(ck_icn_p_adf1, &ck_icn_ls_mcu, 0, GATE_ADF1); static STM32_GATE(ck_icn_p_iwdg5, &ck_icn_ls_mcu, 0, GATE_IWDG5); static STM32_GATE(ck_icn_p_wwdg2, &ck_icn_ls_mcu, 0, GATE_WWDG2); static STM32_GATE(ck_icn_p_eth1, &ck_icn_ls_mcu, 0, GATE_ETH1); static STM32_GATE(ck_icn_p_ethsw, &ck_icn_ls_mcu, 0, GATE_ETHSWMAC); static STM32_GATE(ck_icn_p_eth2, &ck_icn_ls_mcu, 0, GATE_ETH2); static STM32_GATE(ck_icn_p_pcie, &ck_icn_ls_mcu, 0, GATE_PCIE); static STM32_GATE(ck_icn_p_adc12, &ck_icn_ls_mcu, 0, GATE_ADC12); static STM32_GATE(ck_icn_p_adc3, &ck_icn_ls_mcu, 0, GATE_ADC3); static STM32_GATE(ck_icn_p_mdf1, &ck_icn_ls_mcu, 0, GATE_MDF1); static STM32_GATE(ck_icn_p_spi8, &ck_icn_ls_mcu, 0, GATE_SPI8); static STM32_GATE(ck_icn_p_lpuart1, &ck_icn_ls_mcu, 0, GATE_LPUART1); static STM32_GATE(ck_icn_p_i2c8, &ck_icn_ls_mcu, 0, GATE_I2C8); static STM32_GATE(ck_icn_p_lptim3, &ck_icn_ls_mcu, 0, GATE_LPTIM3); static STM32_GATE(ck_icn_p_lptim4, &ck_icn_ls_mcu, 0, GATE_LPTIM4); static STM32_GATE(ck_icn_p_lptim5, &ck_icn_ls_mcu, 0, GATE_LPTIM5); static STM32_GATE(ck_icn_m_sdmmc1, &ck_icn_sdmmc, 0, GATE_SDMMC1); static STM32_GATE(ck_icn_m_sdmmc2, &ck_icn_sdmmc, 0, GATE_SDMMC2); static STM32_GATE(ck_icn_m_sdmmc3, &ck_icn_sdmmc, 0, GATE_SDMMC3); static STM32_GATE(ck_icn_m_usb2ohci, &ck_icn_hsl, 0, GATE_USB2); static STM32_GATE(ck_icn_m_usb2ehci, &ck_icn_hsl, 0, GATE_USB2); static STM32_GATE(ck_icn_m_usb3dr, &ck_icn_hsl, 0, GATE_USB3DR); static STM32_GATE(ck_icn_p_tim2, &ck_icn_apb1, 0, GATE_TIM2); static STM32_GATE(ck_icn_p_tim3, &ck_icn_apb1, 0, GATE_TIM3); static STM32_GATE(ck_icn_p_tim4, &ck_icn_apb1, 0, GATE_TIM4); static STM32_GATE(ck_icn_p_tim5, &ck_icn_apb1, 0, GATE_TIM5); static STM32_GATE(ck_icn_p_tim6, &ck_icn_apb1, 0, GATE_TIM6); static STM32_GATE(ck_icn_p_tim7, &ck_icn_apb1, 0, GATE_TIM7); static STM32_GATE(ck_icn_p_tim10, &ck_icn_apb1, 0, GATE_TIM10); static STM32_GATE(ck_icn_p_tim11, &ck_icn_apb1, 0, GATE_TIM11); static STM32_GATE(ck_icn_p_tim12, &ck_icn_apb1, 0, GATE_TIM12); static STM32_GATE(ck_icn_p_tim13, &ck_icn_apb1, 0, GATE_TIM13); static STM32_GATE(ck_icn_p_tim14, &ck_icn_apb1, 0, GATE_TIM14); static STM32_GATE(ck_icn_p_lptim1, &ck_icn_apb1, 0, GATE_LPTIM1); static STM32_GATE(ck_icn_p_lptim2, &ck_icn_apb1, 0, GATE_LPTIM2); static STM32_GATE(ck_icn_p_spi2, &ck_icn_apb1, 0, GATE_SPI2); static STM32_GATE(ck_icn_p_spi3, &ck_icn_apb1, 0, GATE_SPI3); static STM32_GATE(ck_icn_p_spdifrx, &ck_icn_apb1, 0, GATE_SPDIFRX); static STM32_GATE(ck_icn_p_usart2, &ck_icn_apb1, 0, GATE_USART2); static STM32_GATE(ck_icn_p_usart3, &ck_icn_apb1, 0, GATE_USART3); static STM32_GATE(ck_icn_p_uart4, &ck_icn_apb1, 0, GATE_UART4); static STM32_GATE(ck_icn_p_uart5, &ck_icn_apb1, 0, GATE_UART5); static STM32_GATE(ck_icn_p_i2c1, &ck_icn_apb1, 0, GATE_I2C1); static STM32_GATE(ck_icn_p_i2c2, &ck_icn_apb1, 0, GATE_I2C2); static STM32_GATE(ck_icn_p_i2c3, &ck_icn_apb1, 0, GATE_I2C3); static STM32_GATE(ck_icn_p_i2c4, &ck_icn_apb1, 0, GATE_I2C4); static STM32_GATE(ck_icn_p_i2c5, &ck_icn_apb1, 0, GATE_I2C5); static STM32_GATE(ck_icn_p_i2c6, &ck_icn_apb1, 0, GATE_I2C6); static STM32_GATE(ck_icn_p_i2c7, &ck_icn_apb1, 0, GATE_I2C7); static STM32_GATE(ck_icn_p_i3c1, &ck_icn_apb1, 0, GATE_I3C1); static STM32_GATE(ck_icn_p_i3c2, &ck_icn_apb1, 0, GATE_I3C2); static STM32_GATE(ck_icn_p_i3c3, &ck_icn_apb1, 0, GATE_I3C3); static STM32_GATE(ck_icn_p_i3c4, &ck_icn_ls_mcu, 0, GATE_I3C4); static STM32_GATE(ck_icn_p_tim1, &ck_icn_apb2, 0, GATE_TIM1); static STM32_GATE(ck_icn_p_tim8, &ck_icn_apb2, 0, GATE_TIM8); static STM32_GATE(ck_icn_p_tim15, &ck_icn_apb2, 0, GATE_TIM15); static STM32_GATE(ck_icn_p_tim16, &ck_icn_apb2, 0, GATE_TIM16); static STM32_GATE(ck_icn_p_tim17, &ck_icn_apb2, 0, GATE_TIM17); static STM32_GATE(ck_icn_p_tim20, &ck_icn_apb2, 0, GATE_TIM20); static STM32_GATE(ck_icn_p_sai1, &ck_icn_apb2, 0, GATE_SAI1); static STM32_GATE(ck_icn_p_sai2, &ck_icn_apb2, 0, GATE_SAI2); static STM32_GATE(ck_icn_p_sai3, &ck_icn_apb2, 0, GATE_SAI3); static STM32_GATE(ck_icn_p_sai4, &ck_icn_apb2, 0, GATE_SAI4); static STM32_GATE(ck_icn_p_usart1, &ck_icn_apb2, 0, GATE_USART1); static STM32_GATE(ck_icn_p_usart6, &ck_icn_apb2, 0, GATE_USART6); static STM32_GATE(ck_icn_p_uart7, &ck_icn_apb2, 0, GATE_UART7); static STM32_GATE(ck_icn_p_uart8, &ck_icn_apb2, 0, GATE_UART8); static STM32_GATE(ck_icn_p_uart9, &ck_icn_apb2, 0, GATE_UART9); static STM32_GATE(ck_icn_p_fdcan, &ck_icn_apb2, 0, GATE_FDCAN); static STM32_GATE(ck_icn_p_spi1, &ck_icn_apb2, 0, GATE_SPI1); static STM32_GATE(ck_icn_p_spi4, &ck_icn_apb2, 0, GATE_SPI4); static STM32_GATE(ck_icn_p_spi5, &ck_icn_apb2, 0, GATE_SPI5); static STM32_GATE(ck_icn_p_spi6, &ck_icn_apb2, 0, GATE_SPI6); static STM32_GATE(ck_icn_p_spi7, &ck_icn_apb2, 0, GATE_SPI7); static STM32_GATE(ck_icn_p_iwdg1, &ck_icn_apb3, 0, GATE_IWDG1); static STM32_GATE(ck_icn_p_iwdg2, &ck_icn_apb3, 0, GATE_IWDG2); static STM32_GATE(ck_icn_p_iwdg3, &ck_icn_apb3, 0, GATE_IWDG3); static STM32_GATE(ck_icn_p_iwdg4, &ck_icn_apb3, 0, GATE_IWDG4); static STM32_GATE(ck_icn_p_wwdg1, &ck_icn_apb3, 0, GATE_WWDG1); static STM32_GATE(ck_icn_p_vref, &ck_icn_apb3, 0, GATE_VREF); static STM32_GATE(ck_icn_p_dts, &ck_icn_apb3, 0, GATE_DTS); static STM32_GATE(ck_icn_p_serc, &ck_icn_apb3, 0, GATE_SERC); static STM32_GATE(ck_icn_p_hdp, &ck_icn_apb3, 0, GATE_HDP); static STM32_GATE(ck_icn_p_dsi, &ck_icn_apb4, 0, GATE_DSI); static STM32_GATE(ck_icn_p_ltdc, &ck_icn_apb4, 0, GATE_LTDC); static STM32_GATE(ck_icn_p_csi, &ck_icn_apb4, 0, GATE_CSI); static STM32_GATE(ck_icn_p_dcmipp, &ck_icn_apb4, 0, GATE_DCMIPP); static STM32_GATE(ck_icn_p_lvds, &ck_icn_apb4, 0, GATE_LVDS); static STM32_GATE(ck_icn_p_gicv2m, &ck_icn_apb4, 0, GATE_GICV2M); static STM32_GATE(ck_icn_p_usbtc, &ck_icn_apb4, 0, GATE_USBTC); static STM32_GATE(ck_icn_p_usb3pciephy, &ck_icn_apb4, 0, GATE_USB3PCIEPHY); static STM32_GATE(ck_icn_p_stgen, &ck_icn_apb4, 0, GATE_STGEN); static STM32_GATE(ck_icn_p_vdec, &ck_icn_apb4, 0, GATE_VDEC); static STM32_GATE(ck_icn_p_venc, &ck_icn_apb4, 0, GATE_VENC); static STM32_GATE(ck_ker_tim2, &ck_timg1, 0, GATE_TIM2); static STM32_GATE(ck_ker_tim3, &ck_timg1, 0, GATE_TIM3); static STM32_GATE(ck_ker_tim4, &ck_timg1, 0, GATE_TIM4); static STM32_GATE(ck_ker_tim5, &ck_timg1, 0, GATE_TIM5); static STM32_GATE(ck_ker_tim6, &ck_timg1, 0, GATE_TIM6); static STM32_GATE(ck_ker_tim7, &ck_timg1, 0, GATE_TIM7); static STM32_GATE(ck_ker_tim10, &ck_timg1, 0, GATE_TIM10); static STM32_GATE(ck_ker_tim11, &ck_timg1, 0, GATE_TIM11); static STM32_GATE(ck_ker_tim12, &ck_timg1, 0, GATE_TIM12); static STM32_GATE(ck_ker_tim13, &ck_timg1, 0, GATE_TIM13); static STM32_GATE(ck_ker_tim14, &ck_timg1, 0, GATE_TIM14); static STM32_GATE(ck_ker_tim1, &ck_timg2, 0, GATE_TIM1); static STM32_GATE(ck_ker_tim8, &ck_timg2, 0, GATE_TIM8); static STM32_GATE(ck_ker_tim15, &ck_timg2, 0, GATE_TIM15); static STM32_GATE(ck_ker_tim16, &ck_timg2, 0, GATE_TIM16); static STM32_GATE(ck_ker_tim17, &ck_timg2, 0, GATE_TIM17); static STM32_GATE(ck_ker_tim20, &ck_timg2, 0, GATE_TIM20); static STM32_GATE(ck_ker_lptim1, &ck_flexgen_07, 0, GATE_LPTIM1); static STM32_GATE(ck_ker_lptim2, &ck_flexgen_07, 0, GATE_LPTIM2); static STM32_GATE(ck_ker_usart2, &ck_flexgen_08, 0, GATE_USART2); static STM32_GATE(ck_ker_uart4, &ck_flexgen_08, 0, GATE_UART4); static STM32_GATE(ck_ker_usart3, &ck_flexgen_09, 0, GATE_USART3); static STM32_GATE(ck_ker_uart5, &ck_flexgen_09, 0, GATE_UART5); static STM32_GATE(ck_ker_spi2, &ck_flexgen_10, 0, GATE_SPI2); static STM32_GATE(ck_ker_spi3, &ck_flexgen_10, 0, GATE_SPI3); static STM32_GATE(ck_ker_spdifrx, &ck_flexgen_11, 0, GATE_SPDIFRX); static STM32_GATE(ck_ker_i2c1, &ck_flexgen_12, 0, GATE_I2C1); static STM32_GATE(ck_ker_i2c2, &ck_flexgen_12, 0, GATE_I2C2); static STM32_GATE(ck_ker_i3c1, &ck_flexgen_12, 0, GATE_I3C1); static STM32_GATE(ck_ker_i3c2, &ck_flexgen_12, 0, GATE_I3C2); static STM32_GATE(ck_ker_i2c3, &ck_flexgen_13, 0, GATE_I2C3); static STM32_GATE(ck_ker_i2c5, &ck_flexgen_13, 0, GATE_I2C5); static STM32_GATE(ck_ker_i3c3, &ck_flexgen_13, 0, GATE_I3C3); static STM32_GATE(ck_ker_i2c4, &ck_flexgen_14, 0, GATE_I2C4); static STM32_GATE(ck_ker_i2c6, &ck_flexgen_14, 0, GATE_I2C6); static STM32_GATE(ck_ker_i2c7, &ck_flexgen_15, 0, GATE_I2C7); static STM32_GATE(ck_ker_spi1, &ck_flexgen_16, 0, GATE_SPI1); static STM32_GATE(ck_ker_spi4, &ck_flexgen_17, 0, GATE_SPI4); static STM32_GATE(ck_ker_spi5, &ck_flexgen_17, 0, GATE_SPI5); static STM32_GATE(ck_ker_spi6, &ck_flexgen_18, 0, GATE_SPI6); static STM32_GATE(ck_ker_spi7, &ck_flexgen_18, 0, GATE_SPI7); static STM32_GATE(ck_ker_usart1, &ck_flexgen_19, 0, GATE_USART1); static STM32_GATE(ck_ker_usart6, &ck_flexgen_20, 0, GATE_USART6); static STM32_GATE(ck_ker_uart7, &ck_flexgen_21, 0, GATE_UART7); static STM32_GATE(ck_ker_uart8, &ck_flexgen_21, 0, GATE_UART8); static STM32_GATE(ck_ker_uart9, &ck_flexgen_22, 0, GATE_UART9); static STM32_GATE(ck_ker_mdf1, &ck_flexgen_23, 0, GATE_MDF1); static STM32_GATE(ck_ker_sai1, &ck_flexgen_23, 0, GATE_SAI1); static STM32_GATE(ck_ker_sai2, &ck_flexgen_24, 0, GATE_SAI2); static STM32_GATE(ck_ker_sai3, &ck_flexgen_25, 0, GATE_SAI3); static STM32_GATE(ck_ker_sai4, &ck_flexgen_25, 0, GATE_SAI4); static STM32_GATE(ck_ker_fdcan, &ck_flexgen_26, 0, GATE_FDCAN); static STM32_GATE(ck_ker_csi, &ck_flexgen_29, 0, GATE_CSI); static STM32_GATE(ck_ker_csitxesc, &ck_flexgen_30, 0, GATE_CSI); static STM32_GATE(ck_ker_csiphy, &ck_flexgen_31, 0, GATE_CSI); static STM32_GATE(ck_ker_stgen, &ck_flexgen_33, CLK_SET_RATE_PARENT, GATE_STGEN); static STM32_GATE(ck_ker_usbtc, &ck_flexgen_35, 0, GATE_USBTC); static STM32_GATE(ck_ker_i3c4, &ck_flexgen_36, 0, GATE_I3C4); static STM32_GATE(ck_ker_spi8, &ck_flexgen_37, 0, GATE_SPI8); static STM32_GATE(ck_ker_i2c8, &ck_flexgen_38, 0, GATE_I2C8); static STM32_GATE(ck_ker_lpuart1, &ck_flexgen_39, 0, GATE_LPUART1); static STM32_GATE(ck_ker_lptim3, &ck_flexgen_40, 0, GATE_LPTIM3); static STM32_GATE(ck_ker_lptim4, &ck_flexgen_41, 0, GATE_LPTIM4); static STM32_GATE(ck_ker_lptim5, &ck_flexgen_41, 0, GATE_LPTIM5); static STM32_GATE(ck_ker_adf1, &ck_flexgen_42, 0, GATE_ADF1); static STM32_GATE(ck_ker_sdmmc1, &ck_flexgen_51, 0, GATE_SDMMC1); static STM32_GATE(ck_ker_sdmmc2, &ck_flexgen_52, 0, GATE_SDMMC2); static STM32_GATE(ck_ker_sdmmc3, &ck_flexgen_53, 0, GATE_SDMMC3); static STM32_GATE(ck_ker_eth1, &ck_flexgen_54, 0, GATE_ETH1); static STM32_GATE(ck_ker_ethsw, &ck_flexgen_54, 0, GATE_ETHSW); static STM32_GATE(ck_ker_eth2, &ck_flexgen_55, 0, GATE_ETH2); static STM32_GATE(ck_ker_eth1ptp, &ck_flexgen_56, 0, GATE_ETH1); static STM32_GATE(ck_ker_eth2ptp, &ck_flexgen_56, 0, GATE_ETH2); static STM32_GATE(ck_ker_usb2phy2, &ck_flexgen_58, 0, GATE_USB3DR); static STM32_GATE(ck_icn_m_gpu, &ck_flexgen_59, 0, GATE_GPU); static STM32_GATE(ck_ker_gpu, &ck_pll3, 0, GATE_GPU); static STM32_GATE(ck_ker_ethswref, &ck_flexgen_60, 0, GATE_ETHSWREF); static STM32_GATE(ck_ker_eth1stp, &ck_icn_ls_mcu, 0, GATE_ETH1STP); static STM32_GATE(ck_ker_eth2stp, &ck_icn_ls_mcu, 0, GATE_ETH2STP); static STM32_GATE(ck_ker_ltdc, &ck_flexgen_27, CLK_SET_RATE_PARENT, GATE_LTDC); static STM32_COMPOSITE(ck_ker_adc12, 2, PARENT(&ck_flexgen_46, &ck_icn_ls_mcu), 0, GATE_ADC12, NO_DIV, MUX_ADC12); static STM32_COMPOSITE(ck_ker_adc3, 3, PARENT(&ck_flexgen_47, &ck_icn_ls_mcu, &ck_flexgen_46), 0, GATE_ADC3, NO_DIV, MUX_ADC3); static STM32_COMPOSITE(ck_ker_usb2phy1, 2, PARENT(&ck_flexgen_57, &ck_hse_div2), 0, GATE_USB2PHY1, NO_DIV, MUX_USB2PHY1); static STM32_COMPOSITE(ck_ker_usb2phy2_en, 2, PARENT(&ck_flexgen_58, &ck_hse_div2), 0, GATE_USB2PHY2, NO_DIV, MUX_USB2PHY2); static STM32_COMPOSITE(ck_ker_usb3pciephy, 2, PARENT(&ck_flexgen_34, &ck_hse_div2), 0, GATE_USB3PCIEPHY, NO_DIV, MUX_USB3PCIEPHY); static STM32_COMPOSITE(clk_lanebyte, 2, PARENT(&txbyteclk, &ck_ker_ltdc), 0, GATE_DSI, NO_DIV, MUX_DSIBLANE); static STM32_COMPOSITE(ck_phy_dsi, 2, PARENT(&ck_flexgen_28, &ck_hse), 0, GATE_DSI, NO_DIV, MUX_DSIPHY); static STM32_COMPOSITE(ck_ker_lvdsphy, 2, PARENT(&ck_flexgen_32, &ck_hse), 0, GATE_LVDS, NO_DIV, MUX_LVDSPHY); static STM32_COMPOSITE(ck_ker_dts, 3, PARENT(&ck_hsi, &ck_hse, &ck_msi), 0, GATE_DTS, NO_DIV, MUX_DTS); enum { CK_OFF = STM32MP25_LAST_CLK, I2SCKIN, SPDIFSYMB, CK_HSE_RTC, TXBYTECLK, CK_OBSER0, CK_OBSER1, STM32MP25_ALL_CLK_NB }; static STM32_GATE(ck_ker_eth1mac, &ck_icn_ls_mcu, 0, GATE_ETH1MAC); static STM32_GATE(ck_ker_eth1tx, &ck_icn_ls_mcu, 0, GATE_ETH1TX); static STM32_GATE(ck_ker_eth1rx, &ck_icn_ls_mcu, 0, GATE_ETH1RX); static STM32_GATE(ck_ker_eth2mac, &ck_icn_ls_mcu, 0, GATE_ETH2MAC); static STM32_GATE(ck_ker_eth2tx, &ck_icn_ls_mcu, 0, GATE_ETH2TX); static STM32_GATE(ck_ker_eth2rx, &ck_icn_ls_mcu, 0, GATE_ETH2RX); static struct clk *stm32mp25_clk_provided[STM32MP25_ALL_CLK_NB] = { [HSI_CK] = &ck_hsi, [HSE_CK] = &ck_hse, [MSI_CK] = &ck_msi, [LSI_CK] = &ck_lsi, [LSE_CK] = &ck_lse, [HSE_DIV2_CK] = &ck_hse_div2, [PLL1_CK] = &ck_pll1, [PLL2_CK] = &ck_pll2, [PLL3_CK] = &ck_pll3, [PLL4_CK] = &ck_pll4, [PLL5_CK] = &ck_pll5, [PLL6_CK] = &ck_pll6, [PLL7_CK] = &ck_pll7, [PLL8_CK] = &ck_pll8, [CK_ICN_HS_MCU] = &ck_icn_hs_mcu, [CK_ICN_LS_MCU] = &ck_icn_ls_mcu, [CK_ICN_SDMMC] = &ck_icn_sdmmc, [CK_ICN_DDR] = &ck_icn_ddr, [CK_ICN_DISPLAY] = &ck_icn_display, [CK_ICN_HSL] = &ck_icn_hsl, [CK_ICN_NIC] = &ck_icn_nic, [CK_ICN_VID] = &ck_icn_vid, [CK_FLEXGEN_07] = &ck_flexgen_07, [CK_FLEXGEN_08] = &ck_flexgen_08, [CK_FLEXGEN_09] = &ck_flexgen_09, [CK_FLEXGEN_10] = &ck_flexgen_10, [CK_FLEXGEN_11] = &ck_flexgen_11, [CK_FLEXGEN_12] = &ck_flexgen_12, [CK_FLEXGEN_13] = &ck_flexgen_13, [CK_FLEXGEN_14] = &ck_flexgen_14, [CK_FLEXGEN_15] = &ck_flexgen_15, [CK_FLEXGEN_16] = &ck_flexgen_16, [CK_FLEXGEN_17] = &ck_flexgen_17, [CK_FLEXGEN_18] = &ck_flexgen_18, [CK_FLEXGEN_19] = &ck_flexgen_19, [CK_FLEXGEN_20] = &ck_flexgen_20, [CK_FLEXGEN_21] = &ck_flexgen_21, [CK_FLEXGEN_22] = &ck_flexgen_22, [CK_FLEXGEN_23] = &ck_flexgen_23, [CK_FLEXGEN_24] = &ck_flexgen_24, [CK_FLEXGEN_25] = &ck_flexgen_25, [CK_FLEXGEN_26] = &ck_flexgen_26, [CK_FLEXGEN_27] = &ck_flexgen_27, [CK_FLEXGEN_28] = &ck_flexgen_28, [CK_FLEXGEN_29] = &ck_flexgen_29, [CK_FLEXGEN_30] = &ck_flexgen_30, [CK_FLEXGEN_31] = &ck_flexgen_31, [CK_FLEXGEN_32] = &ck_flexgen_32, [CK_FLEXGEN_33] = &ck_flexgen_33, [CK_FLEXGEN_34] = &ck_flexgen_34, [CK_FLEXGEN_35] = &ck_flexgen_35, [CK_FLEXGEN_36] = &ck_flexgen_36, [CK_FLEXGEN_37] = &ck_flexgen_37, [CK_FLEXGEN_38] = &ck_flexgen_38, [CK_FLEXGEN_39] = &ck_flexgen_39, [CK_FLEXGEN_40] = &ck_flexgen_40, [CK_FLEXGEN_41] = &ck_flexgen_41, [CK_FLEXGEN_42] = &ck_flexgen_42, [CK_FLEXGEN_43] = &ck_flexgen_43, [CK_FLEXGEN_44] = &ck_flexgen_44, [CK_FLEXGEN_45] = &ck_flexgen_45, [CK_FLEXGEN_46] = &ck_flexgen_46, [CK_FLEXGEN_47] = &ck_flexgen_47, [CK_FLEXGEN_48] = &ck_flexgen_48, [CK_FLEXGEN_49] = &ck_flexgen_49, [CK_FLEXGEN_50] = &ck_flexgen_50, [CK_FLEXGEN_51] = &ck_flexgen_51, [CK_FLEXGEN_52] = &ck_flexgen_52, [CK_FLEXGEN_53] = &ck_flexgen_53, [CK_FLEXGEN_54] = &ck_flexgen_54, [CK_FLEXGEN_55] = &ck_flexgen_55, [CK_FLEXGEN_56] = &ck_flexgen_56, [CK_FLEXGEN_57] = &ck_flexgen_57, [CK_FLEXGEN_58] = &ck_flexgen_58, [CK_FLEXGEN_59] = &ck_flexgen_59, [CK_FLEXGEN_60] = &ck_flexgen_60, [CK_FLEXGEN_61] = &ck_flexgen_61, [CK_FLEXGEN_62] = &ck_flexgen_62, [CK_FLEXGEN_63] = &ck_flexgen_63, [CK_CPU1] = &ck_cpu1, [CK_ICN_APB1] = &ck_icn_apb1, [CK_ICN_APB2] = &ck_icn_apb2, [CK_ICN_APB3] = &ck_icn_apb3, [CK_ICN_APB4] = &ck_icn_apb4, [CK_ICN_APBDBG] = &ck_icn_apbdbg, [TIMG1_CK] = &ck_timg1, [TIMG2_CK] = &ck_timg2, [CK_BUS_SYSRAM] = &ck_icn_s_sysram, [CK_BUS_VDERAM] = &ck_icn_s_vderam, [CK_BUS_RETRAM] = &ck_icn_s_retram, [CK_BUS_SRAM1] = &ck_icn_s_sram1, [CK_BUS_SRAM2] = &ck_icn_s_sram2, [CK_BUS_OSPI1] = &ck_icn_s_ospi1, [CK_BUS_OSPI2] = &ck_icn_s_ospi2, [CK_BUS_BKPSRAM] = &ck_icn_s_bkpsram, [CK_BUS_DDRPHYC] = &ck_icn_p_ddrphyc, [CK_BUS_SYSCPU1] = &ck_icn_p_syscpu1, [CK_BUS_HPDMA1] = &ck_icn_p_hpdma1, [CK_BUS_HPDMA2] = &ck_icn_p_hpdma2, [CK_BUS_HPDMA3] = &ck_icn_p_hpdma3, [CK_BUS_IPCC1] = &ck_icn_p_ipcc1, [CK_BUS_IPCC2] = &ck_icn_p_ipcc2, [CK_BUS_CCI] = &ck_icn_p_cci, [CK_BUS_CRC] = &ck_icn_p_crc, [CK_BUS_OSPIIOM] = &ck_icn_p_ospiiom, [CK_BUS_HASH] = &ck_icn_p_hash, [CK_BUS_RNG] = &ck_icn_p_rng, [CK_BUS_CRYP1] = &ck_icn_p_cryp1, [CK_BUS_CRYP2] = &ck_icn_p_cryp2, [CK_BUS_SAES] = &ck_icn_p_saes, [CK_BUS_PKA] = &ck_icn_p_pka, [CK_BUS_GPIOA] = &ck_icn_p_gpioa, [CK_BUS_GPIOB] = &ck_icn_p_gpiob, [CK_BUS_GPIOC] = &ck_icn_p_gpioc, [CK_BUS_GPIOD] = &ck_icn_p_gpiod, [CK_BUS_GPIOE] = &ck_icn_p_gpioe, [CK_BUS_GPIOF] = &ck_icn_p_gpiof, [CK_BUS_GPIOG] = &ck_icn_p_gpiog, [CK_BUS_GPIOH] = &ck_icn_p_gpioh, [CK_BUS_GPIOI] = &ck_icn_p_gpioi, [CK_BUS_GPIOJ] = &ck_icn_p_gpioj, [CK_BUS_GPIOK] = &ck_icn_p_gpiok, [CK_BUS_LPSRAM1] = &ck_icn_s_lpsram1, [CK_BUS_LPSRAM2] = &ck_icn_s_lpsram2, [CK_BUS_LPSRAM3] = &ck_icn_s_lpsram3, [CK_BUS_GPIOZ] = &ck_icn_p_gpioz, [CK_BUS_LPDMA] = &ck_icn_p_lpdma, [CK_BUS_ADF1] = &ck_icn_p_adf1, [CK_BUS_HSEM] = &ck_icn_p_hsem, [CK_BUS_RTC] = &ck_icn_p_rtc, [CK_BUS_IWDG5] = &ck_icn_p_iwdg5, [CK_BUS_WWDG2] = &ck_icn_p_wwdg2, [CK_BUS_STM] = &ck_icn_p_stm, [CK_KER_STM] = &ck_icn_s_stm, [CK_BUS_FMC] = &ck_icn_p_fmc, [CK_BUS_ETH1] = &ck_icn_p_eth1, [CK_BUS_ETHSW] = &ck_icn_p_ethsw, [CK_BUS_ETH2] = &ck_icn_p_eth2, [CK_BUS_PCIE] = &ck_icn_p_pcie, [CK_BUS_ADC12] = &ck_icn_p_adc12, [CK_BUS_ADC3] = &ck_icn_p_adc3, [CK_BUS_MDF1] = &ck_icn_p_mdf1, [CK_BUS_SPI8] = &ck_icn_p_spi8, [CK_BUS_LPUART1] = &ck_icn_p_lpuart1, [CK_BUS_I2C8] = &ck_icn_p_i2c8, [CK_BUS_LPTIM3] = &ck_icn_p_lptim3, [CK_BUS_LPTIM4] = &ck_icn_p_lptim4, [CK_BUS_LPTIM5] = &ck_icn_p_lptim5, [CK_BUS_RISAF4] = &ck_icn_p_risaf4, [CK_BUS_SDMMC1] = &ck_icn_m_sdmmc1, [CK_BUS_SDMMC2] = &ck_icn_m_sdmmc2, [CK_BUS_SDMMC3] = &ck_icn_m_sdmmc3, [CK_BUS_DDR] = &ck_icn_s_ddr, [CK_BUS_USB2OHCI] = &ck_icn_m_usb2ohci, [CK_BUS_USB2EHCI] = &ck_icn_m_usb2ehci, [CK_BUS_USB3DR] = &ck_icn_m_usb3dr, [CK_BUS_TIM2] = &ck_icn_p_tim2, [CK_BUS_TIM3] = &ck_icn_p_tim3, [CK_BUS_TIM4] = &ck_icn_p_tim4, [CK_BUS_TIM5] = &ck_icn_p_tim5, [CK_BUS_TIM6] = &ck_icn_p_tim6, [CK_BUS_TIM7] = &ck_icn_p_tim7, [CK_BUS_TIM10] = &ck_icn_p_tim10, [CK_BUS_TIM11] = &ck_icn_p_tim11, [CK_BUS_TIM12] = &ck_icn_p_tim12, [CK_BUS_TIM13] = &ck_icn_p_tim13, [CK_BUS_TIM14] = &ck_icn_p_tim14, [CK_BUS_LPTIM1] = &ck_icn_p_lptim1, [CK_BUS_LPTIM2] = &ck_icn_p_lptim2, [CK_BUS_SPI2] = &ck_icn_p_spi2, [CK_BUS_SPI3] = &ck_icn_p_spi3, [CK_BUS_SPDIFRX] = &ck_icn_p_spdifrx, [CK_BUS_USART2] = &ck_icn_p_usart2, [CK_BUS_USART3] = &ck_icn_p_usart3, [CK_BUS_UART4] = &ck_icn_p_uart4, [CK_BUS_UART5] = &ck_icn_p_uart5, [CK_BUS_I2C1] = &ck_icn_p_i2c1, [CK_BUS_I2C2] = &ck_icn_p_i2c2, [CK_BUS_I2C3] = &ck_icn_p_i2c3, [CK_BUS_I2C4] = &ck_icn_p_i2c4, [CK_BUS_I2C5] = &ck_icn_p_i2c5, [CK_BUS_I2C6] = &ck_icn_p_i2c6, [CK_BUS_I2C7] = &ck_icn_p_i2c7, [CK_BUS_I3C1] = &ck_icn_p_i3c1, [CK_BUS_I3C2] = &ck_icn_p_i3c2, [CK_BUS_I3C3] = &ck_icn_p_i3c3, [CK_BUS_I3C4] = &ck_icn_p_i3c4, [CK_BUS_TIM1] = &ck_icn_p_tim1, [CK_BUS_TIM8] = &ck_icn_p_tim8, [CK_BUS_TIM15] = &ck_icn_p_tim15, [CK_BUS_TIM16] = &ck_icn_p_tim16, [CK_BUS_TIM17] = &ck_icn_p_tim17, [CK_BUS_TIM20] = &ck_icn_p_tim20, [CK_BUS_SAI1] = &ck_icn_p_sai1, [CK_BUS_SAI2] = &ck_icn_p_sai2, [CK_BUS_SAI3] = &ck_icn_p_sai3, [CK_BUS_SAI4] = &ck_icn_p_sai4, [CK_BUS_USART1] = &ck_icn_p_usart1, [CK_BUS_USART6] = &ck_icn_p_usart6, [CK_BUS_UART7] = &ck_icn_p_uart7, [CK_BUS_UART8] = &ck_icn_p_uart8, [CK_BUS_UART9] = &ck_icn_p_uart9, [CK_BUS_FDCAN] = &ck_icn_p_fdcan, [CK_BUS_SPI1] = &ck_icn_p_spi1, [CK_BUS_SPI4] = &ck_icn_p_spi4, [CK_BUS_SPI5] = &ck_icn_p_spi5, [CK_BUS_SPI6] = &ck_icn_p_spi6, [CK_BUS_SPI7] = &ck_icn_p_spi7, [CK_BUS_BSEC] = &ck_icn_p_bsec, [CK_BUS_IWDG1] = &ck_icn_p_iwdg1, [CK_BUS_IWDG2] = &ck_icn_p_iwdg2, [CK_BUS_IWDG3] = &ck_icn_p_iwdg3, [CK_BUS_IWDG4] = &ck_icn_p_iwdg4, [CK_BUS_WWDG1] = &ck_icn_p_wwdg1, [CK_BUS_VREF] = &ck_icn_p_vref, [CK_BUS_SERC] = &ck_icn_p_serc, [CK_BUS_DTS] = &ck_icn_p_dts, [CK_BUS_HDP] = &ck_icn_p_hdp, [CK_BUS_IS2M] = &ck_icn_p_is2m, [CK_BUS_DSI] = &ck_icn_p_dsi, [CK_BUS_LTDC] = &ck_icn_p_ltdc, [CK_BUS_CSI] = &ck_icn_p_csi, [CK_BUS_DCMIPP] = &ck_icn_p_dcmipp, [CK_BUS_DDRC] = &ck_icn_p_ddrc, [CK_BUS_DDRCFG] = &ck_icn_p_ddrcfg, [CK_BUS_LVDS] = &ck_icn_p_lvds, [CK_BUS_GICV2M] = &ck_icn_p_gicv2m, [CK_BUS_USBTC] = &ck_icn_p_usbtc, [CK_BUS_USB3PCIEPHY] = &ck_icn_p_usb3pciephy, [CK_BUS_STGEN] = &ck_icn_p_stgen, [CK_BUS_VDEC] = &ck_icn_p_vdec, [CK_BUS_VENC] = &ck_icn_p_venc, [CK_SYSDBG] = &ck_sys_dbg, [CK_KER_TIM2] = &ck_ker_tim2, [CK_KER_TIM3] = &ck_ker_tim3, [CK_KER_TIM4] = &ck_ker_tim4, [CK_KER_TIM5] = &ck_ker_tim5, [CK_KER_TIM6] = &ck_ker_tim6, [CK_KER_TIM7] = &ck_ker_tim7, [CK_KER_TIM10] = &ck_ker_tim10, [CK_KER_TIM11] = &ck_ker_tim11, [CK_KER_TIM12] = &ck_ker_tim12, [CK_KER_TIM13] = &ck_ker_tim13, [CK_KER_TIM14] = &ck_ker_tim14, [CK_KER_TIM1] = &ck_ker_tim1, [CK_KER_TIM8] = &ck_ker_tim8, [CK_KER_TIM15] = &ck_ker_tim15, [CK_KER_TIM16] = &ck_ker_tim16, [CK_KER_TIM17] = &ck_ker_tim17, [CK_KER_TIM20] = &ck_ker_tim20, [CK_KER_LPTIM1] = &ck_ker_lptim1, [CK_KER_LPTIM2] = &ck_ker_lptim2, [CK_KER_USART2] = &ck_ker_usart2, [CK_KER_UART4] = &ck_ker_uart4, [CK_KER_USART3] = &ck_ker_usart3, [CK_KER_UART5] = &ck_ker_uart5, [CK_KER_SPI2] = &ck_ker_spi2, [CK_KER_SPI3] = &ck_ker_spi3, [CK_KER_SPDIFRX] = &ck_ker_spdifrx, [CK_KER_I2C1] = &ck_ker_i2c1, [CK_KER_I2C2] = &ck_ker_i2c2, [CK_KER_I3C1] = &ck_ker_i3c1, [CK_KER_I3C2] = &ck_ker_i3c2, [CK_KER_I2C3] = &ck_ker_i2c3, [CK_KER_I2C5] = &ck_ker_i2c5, [CK_KER_I3C3] = &ck_ker_i3c3, [CK_KER_I2C4] = &ck_ker_i2c4, [CK_KER_I2C6] = &ck_ker_i2c6, [CK_KER_I2C7] = &ck_ker_i2c7, [CK_KER_SPI1] = &ck_ker_spi1, [CK_KER_SPI4] = &ck_ker_spi4, [CK_KER_SPI5] = &ck_ker_spi5, [CK_KER_SPI6] = &ck_ker_spi6, [CK_KER_SPI7] = &ck_ker_spi7, [CK_KER_USART1] = &ck_ker_usart1, [CK_KER_USART6] = &ck_ker_usart6, [CK_KER_UART7] = &ck_ker_uart7, [CK_KER_UART8] = &ck_ker_uart8, [CK_KER_UART9] = &ck_ker_uart9, [CK_KER_MDF1] = &ck_ker_mdf1, [CK_KER_SAI1] = &ck_ker_sai1, [CK_KER_SAI2] = &ck_ker_sai2, [CK_KER_SAI3] = &ck_ker_sai3, [CK_KER_SAI4] = &ck_ker_sai4, [CK_KER_FDCAN] = &ck_ker_fdcan, [CK_KER_CSI] = &ck_ker_csi, [CK_KER_CSITXESC] = &ck_ker_csitxesc, [CK_KER_CSIPHY] = &ck_ker_csiphy, [CK_KER_STGEN] = &ck_ker_stgen, [CK_KER_USBTC] = &ck_ker_usbtc, [CK_KER_I3C4] = &ck_ker_i3c4, [CK_KER_SPI8] = &ck_ker_spi8, [CK_KER_I2C8] = &ck_ker_i2c8, [CK_KER_LPUART1] = &ck_ker_lpuart1, [CK_KER_LPTIM3] = &ck_ker_lptim3, [CK_KER_LPTIM4] = &ck_ker_lptim4, [CK_KER_LPTIM5] = &ck_ker_lptim5, [CK_KER_ADF1] = &ck_ker_adf1, [CK_KER_TSDBG] = &ck_ker_tsdbg, [CK_KER_TPIU] = &ck_ker_tpiu, [CK_BUS_ETR] = &ck_icn_p_etr, [CK_KER_ETR] = &ck_icn_m_etr, [CK_BUS_SYSATB] = &ck_sys_atb, [CK_KER_OSPI1] = &ck_ker_ospi1, [CK_KER_OSPI2] = &ck_ker_ospi2, [CK_KER_FMC] = &ck_ker_fmc, [CK_KER_SDMMC1] = &ck_ker_sdmmc1, [CK_KER_SDMMC2] = &ck_ker_sdmmc2, [CK_KER_SDMMC3] = &ck_ker_sdmmc3, [CK_KER_ETH1] = &ck_ker_eth1, [CK_ETH1_STP] = &ck_ker_eth1stp, [CK_KER_ETHSW] = &ck_ker_ethsw, [CK_KER_ETH2] = &ck_ker_eth2, [CK_ETH2_STP] = &ck_ker_eth2stp, [CK_KER_ETH1PTP] = &ck_ker_eth1ptp, [CK_KER_ETH2PTP] = &ck_ker_eth2ptp, [CK_BUS_GPU] = &ck_icn_m_gpu, [CK_KER_GPU] = &ck_ker_gpu, [CK_KER_ETHSWREF] = &ck_ker_ethswref, [CK_MCO1] = &ck_mco1, [CK_MCO2] = &ck_mco2, [CK_KER_ADC12] = &ck_ker_adc12, [CK_KER_ADC3] = &ck_ker_adc3, [CK_KER_USB2PHY1] = &ck_ker_usb2phy1, [CK_KER_USB2PHY2] = &ck_ker_usb2phy2, [CK_KER_USB2PHY2EN] = &ck_ker_usb2phy2_en, [CK_KER_USB3PCIEPHY] = &ck_ker_usb3pciephy, [CK_KER_LTDC] = &ck_ker_ltdc, [CK_KER_DSIBLANE] = &clk_lanebyte, [CK_KER_DSIPHY] = &ck_phy_dsi, [CK_KER_LVDSPHY] = &ck_ker_lvdsphy, [CK_KER_DTS] = &ck_ker_dts, [RTC_CK] = &ck_rtc, [CK_ETH1_MAC] = &ck_ker_eth1mac, [CK_ETH1_TX] = &ck_ker_eth1tx, [CK_ETH1_RX] = &ck_ker_eth1rx, [CK_ETH2_MAC] = &ck_ker_eth2mac, [CK_ETH2_TX] = &ck_ker_eth2tx, [CK_ETH2_RX] = &ck_ker_eth2rx, [CK_HSE_RTC] = &ck_hse_rtc, [CK_OBSER0] = &ck_obser0, [CK_OBSER1] = &ck_obser1, [CK_OFF] = &ck_off, [I2SCKIN] = &i2sckin, [SPDIFSYMB] = &spdifsymb, [TXBYTECLK] = &txbyteclk, }; static bool clk_stm32_clock_is_critical(struct clk *clk) { struct clk *clk_criticals[] = { &ck_hsi, &ck_hse, &ck_msi, &ck_lsi, &ck_lse, &ck_cpu1, &ck_icn_p_syscpu1, &ck_icn_s_ddr, &ck_icn_p_ddrc, &ck_icn_p_ddrcfg, &ck_icn_p_ddrphyc, &ck_icn_s_sysram, &ck_icn_s_bkpsram, &ck_ker_fmc, &ck_ker_ospi1, &ck_ker_ospi2, &ck_icn_s_vderam, &ck_icn_s_lpsram1, &ck_icn_s_lpsram2, &ck_icn_s_lpsram3, &ck_icn_p_hpdma1, &ck_icn_p_hpdma2, &ck_icn_p_hpdma3, &ck_icn_p_gpioa, &ck_icn_p_gpiob, &ck_icn_p_gpioc, &ck_icn_p_gpiod, &ck_icn_p_gpioe, &ck_icn_p_gpiof, &ck_icn_p_gpiog, &ck_icn_p_gpioh, &ck_icn_p_gpioi, &ck_icn_p_gpioj, &ck_icn_p_gpiok, &ck_icn_p_gpioz, &ck_icn_p_ipcc1, &ck_icn_p_ipcc2, &ck_icn_p_gicv2m, &ck_icn_p_rtc }; size_t i = 0; for (i = 0; i < ARRAY_SIZE(clk_criticals); i++) if (clk == clk_criticals[i]) return true; return false; } static void clk_stm32_init_oscillators(const void *fdt, int node) { size_t i = 0; static const char * const name[] = { "clk-hse", "clk-hsi", "clk-lse", "clk-lsi", "clk-msi", "clk-i2sin" }; struct clk *clks[ARRAY_SIZE(name)] = { &ck_hse, &ck_hsi, &ck_lse, &ck_lsi, &ck_msi, &i2sckin }; for (i = 0; i < ARRAY_SIZE(clks); i++) { struct clk *clk = NULL; if (clk_dt_get_by_name(fdt, node, name[i], &clk)) panic(); clks[i]->parents[0] = clk; } } static TEE_Result clk_stm32_apply_rcc_config(struct stm32_clk_platdata *pdata) { if (pdata->safe_rst) stm32mp25_syscfg_set_safe_reset(true); return TEE_SUCCESS; } static struct stm32_pll_dt_cfg mp25_pll[PLL_NB]; static struct stm32_clk_opp_dt_cfg mp25_clk_opp; static struct stm32_osci_dt_cfg mp25_osci[NB_OSCILLATOR]; #define DT_FLEXGEN_CLK_MAX 64 static uint32_t mp25_flexgen[DT_FLEXGEN_CLK_MAX]; #define DT_BUS_CLK_MAX 6 static uint32_t mp25_busclk[DT_BUS_CLK_MAX]; #define DT_KERNEL_CLK_MAX 20 static uint32_t mp25_kernelclk[DT_KERNEL_CLK_MAX]; static struct stm32_clk_platdata stm32mp25_clock_pdata = { .osci = mp25_osci, .nosci = NB_OSCILLATOR, .pll = mp25_pll, .npll = PLL_NB, .opp = &mp25_clk_opp, .busclk = mp25_busclk, .nbusclk = DT_BUS_CLK_MAX, .kernelclk = mp25_kernelclk, .nkernelclk = DT_KERNEL_CLK_MAX, .flexgen = mp25_flexgen, .nflexgen = DT_FLEXGEN_CLK_MAX, }; static struct clk_stm32_priv stm32mp25_clock_data = { .muxes = parent_mp25, .nb_muxes = ARRAY_SIZE(parent_mp25), .gates = gates_mp25, .nb_gates = ARRAY_SIZE(gates_mp25), .div = dividers_mp25, .nb_div = ARRAY_SIZE(dividers_mp25), .pdata = &stm32mp25_clock_pdata, .nb_clk_refs = STM32MP25_ALL_CLK_NB, .clk_refs = stm32mp25_clk_provided, .is_critical = clk_stm32_clock_is_critical, }; static TEE_Result stm32mp2_clk_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; int fdt_rc = 0; int rc = 0; struct clk_stm32_priv *priv = &stm32mp25_clock_data; struct stm32_clk_platdata *pdata = &stm32mp25_clock_pdata; fdt_rc = stm32_clk_parse_fdt(fdt, node, pdata); if (fdt_rc) { EMSG("Failed to parse clock node %s: %d", fdt_get_name(fdt, node, NULL), fdt_rc); return TEE_ERROR_GENERIC; } rc = clk_stm32_init(priv, stm32_rcc_base()); if (rc) return TEE_ERROR_GENERIC; stm32mp2_init_clock_tree(priv, pdata); clk_stm32_init_oscillators(fdt, node); res = clk_stm32_apply_rcc_config(pdata); if (res) panic("Error when applying RCC config"); stm32mp_clk_provider_probe_final(fdt, node, priv); if (IS_ENABLED(CFG_STM32_CLK_DEBUG)) clk_print_tree(); return TEE_SUCCESS; } CLK_DT_DECLARE(stm32mp25_clk, "st,stm32mp25-rcc", stm32mp2_clk_probe); optee_os-4.3.0/core/drivers/clk/clk.c000066400000000000000000000261431464416617300174510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Bootlin * Copyright (c) 2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include /* Global clock tree access protection complying the power state transitions */ static struct mutex_pm_aware mu = MUTEX_PM_AWARE_INITIALIZER; #ifdef CFG_DRIVERS_CLK_PRINT_TREE static SLIST_HEAD(, clk) clock_list = SLIST_HEAD_INITIALIZER(clock_list); #endif static void lock_clk(void) { mutex_pm_aware_lock(&mu); } static void unlock_clk(void) { mutex_pm_aware_unlock(&mu); } struct clk *clk_alloc(const char *name, const struct clk_ops *ops, struct clk **parent_clks, size_t parent_count) { struct clk *clk = NULL; size_t parent = 0; clk = calloc(1, sizeof(*clk) + parent_count * sizeof(clk)); if (!clk) return NULL; clk->num_parents = parent_count; for (parent = 0; parent < parent_count; parent++) clk->parents[parent] = parent_clks[parent]; clk->name = name; clk->ops = ops; refcount_set(&clk->enabled_count, 0); return clk; } void clk_free(struct clk *clk) { free(clk); } static bool __maybe_unused clk_check(struct clk *clk) { if (!clk || !clk->ops) return false; if (clk->ops->set_parent && !clk->ops->get_parent) return false; if (clk->num_parents > 1 && !clk->ops->get_parent) return false; return true; } static void clk_compute_rate_no_lock(struct clk *clk) { unsigned long parent_rate = 0; if (clk->parent) parent_rate = clk->parent->rate; if (clk->ops->get_rate) clk->rate = clk->ops->get_rate(clk, parent_rate); else clk->rate = parent_rate; } struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx) { if (pidx >= clk->num_parents) return NULL; return clk->parents[pidx]; } static void clk_init_parent(struct clk *clk) { size_t pidx = 0; switch (clk->num_parents) { case 0: break; case 1: clk->parent = clk->parents[0]; break; default: pidx = clk->ops->get_parent(clk); assert(pidx < clk->num_parents); clk->parent = clk->parents[pidx]; break; } } TEE_Result clk_register(struct clk *clk) { assert(clk_check(clk)); clk_init_parent(clk); clk_compute_rate_no_lock(clk); #ifdef CFG_DRIVERS_CLK_PRINT_TREE SLIST_INSERT_HEAD(&clock_list, clk, link); #endif DMSG("Registered clock %s, freq %lu", clk->name, clk_get_rate(clk)); return TEE_SUCCESS; } static bool clk_is_enabled_no_lock(struct clk *clk) { return refcount_val(&clk->enabled_count) != 0; } bool clk_is_enabled(struct clk *clk) { return clk_is_enabled_no_lock(clk); } static void clk_disable_no_lock(struct clk *clk) { struct clk *parent = NULL; if (!refcount_dec(&clk->enabled_count)) return; if (clk->ops->disable) clk->ops->disable(clk); parent = clk_get_parent(clk); if (parent) clk_disable_no_lock(parent); } static TEE_Result clk_enable_no_lock(struct clk *clk) { TEE_Result res = TEE_ERROR_GENERIC; struct clk *parent = NULL; if (refcount_inc(&clk->enabled_count)) return TEE_SUCCESS; parent = clk_get_parent(clk); if (parent) { res = clk_enable_no_lock(parent); if (res) return res; } if (clk->ops->enable) { res = clk->ops->enable(clk); if (res) { if (parent) clk_disable_no_lock(parent); return res; } } refcount_set(&clk->enabled_count, 1); return TEE_SUCCESS; } TEE_Result clk_enable(struct clk *clk) { TEE_Result res = TEE_ERROR_GENERIC; lock_clk(); res = clk_enable_no_lock(clk); unlock_clk(); return res; } void clk_disable(struct clk *clk) { lock_clk(); clk_disable_no_lock(clk); unlock_clk(); } unsigned long clk_get_rate(struct clk *clk) { return clk->rate; } static TEE_Result clk_set_rate_no_lock(struct clk *clk, unsigned long rate) { TEE_Result res = TEE_ERROR_GENERIC; unsigned long parent_rate = 0; if (clk->parent) parent_rate = clk_get_rate(clk->parent); assert(!(clk->flags & CLK_SET_RATE_PARENT) || clk->parent); if (clk->flags & CLK_SET_RATE_PARENT) { res = clk_set_rate_no_lock(clk->parent, rate); if (res) return res; rate = clk_get_rate(clk->parent); } if (clk->ops->set_rate) { if (clk->flags & CLK_SET_RATE_UNGATE) { res = clk_enable_no_lock(clk); if (res) return res; } res = clk->ops->set_rate(clk, rate, parent_rate); if (clk->flags & CLK_SET_RATE_UNGATE) clk_disable_no_lock(clk); if (res) return res; } clk_compute_rate_no_lock(clk); return TEE_SUCCESS; } TEE_Result clk_set_rate(struct clk *clk, unsigned long rate) { TEE_Result res = TEE_ERROR_GENERIC; lock_clk(); if (clk->flags & CLK_SET_RATE_GATE && clk_is_enabled_no_lock(clk)) res = TEE_ERROR_BAD_STATE; else res = clk_set_rate_no_lock(clk, rate); unlock_clk(); return res; } struct clk *clk_get_parent(struct clk *clk) { return clk->parent; } static TEE_Result clk_get_parent_idx(struct clk *clk, struct clk *parent, size_t *pidx) { size_t i = 0; for (i = 0; i < clk_get_num_parents(clk); i++) { if (clk_get_parent_by_index(clk, i) == parent) { *pidx = i; return TEE_SUCCESS; } } EMSG("Clock %s is not a parent of clock %s", parent->name, clk->name); return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result clk_set_parent_no_lock(struct clk *clk, struct clk *parent, size_t pidx) { TEE_Result res = TEE_ERROR_GENERIC; bool was_enabled = false; /* Requested parent is already the one set */ if (clk->parent == parent) return TEE_SUCCESS; was_enabled = clk_is_enabled_no_lock(clk); /* Call is needed to decrement refcount on current parent tree */ if (was_enabled) { if (clk->flags & CLK_SET_PARENT_PRE_ENABLE) { res = clk_enable_no_lock(parent); if (res) return res; } clk_disable_no_lock(clk); } res = clk->ops->set_parent(clk, pidx); if (res) goto out; clk->parent = parent; /* The parent changed and the rate might also have changed */ clk_compute_rate_no_lock(clk); out: /* Call is needed to increment refcount on the new parent tree */ if (was_enabled) { res = clk_enable_no_lock(clk); if (res) panic("Failed to re-enable clock after setting parent"); if (clk->flags & CLK_SET_PARENT_PRE_ENABLE) { /* Balance refcount when new parent was pre-enabled */ clk_disable_no_lock(parent); } } return res; } TEE_Result clk_set_parent(struct clk *clk, struct clk *parent) { size_t pidx = 0; TEE_Result res = TEE_ERROR_GENERIC; if (clk_get_parent_idx(clk, parent, &pidx) || !clk->ops->set_parent) return TEE_ERROR_BAD_PARAMETERS; lock_clk(); if (clk->flags & CLK_SET_PARENT_GATE && clk_is_enabled_no_lock(clk)) { res = TEE_ERROR_BAD_STATE; goto out; } res = clk_set_parent_no_lock(clk, parent, pidx); out: unlock_clk(); return res; } TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index, unsigned long *rates, size_t *nb_elts) { if (!clk->ops->get_rates_array) return TEE_ERROR_NOT_SUPPORTED; return clk->ops->get_rates_array(clk, start_index, rates, nb_elts); } TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min, unsigned long *max, unsigned long *step) { if (!clk->ops->get_rates_steps) return TEE_ERROR_NOT_SUPPORTED; return clk->ops->get_rates_steps(clk, min, max, step); } TEE_Result clk_get_duty_cycle(struct clk *clk, struct clk_duty_cycle *duty_cycle) { if (clk->ops->get_duty_cycle) return clk->ops->get_duty_cycle(clk, duty_cycle); if (clk->parent && (clk->flags & CLK_DUTY_CYCLE_PARENT)) return clk_get_duty_cycle(clk->parent, duty_cycle); /* Default set 50% duty cycle */ duty_cycle->num = 1; duty_cycle->den = 2; return TEE_SUCCESS; } /* Return updated message buffer position of NULL on failure */ static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...) { va_list ap = { }; int max_len = end - cur; int ret = 0; va_start(ap, fmt); ret = vsnprintf(cur, max_len, fmt, ap); va_end(ap); if (ret < 0 || ret >= max_len) return NULL; return cur + ret; } static struct clk *find_next_clk(struct clk *parent __maybe_unused, struct clk *sibling __maybe_unused) { struct clk *clk = NULL; #ifdef CFG_DRIVERS_CLK_PRINT_TREE if (sibling) clk = SLIST_NEXT(sibling, link); else clk = SLIST_FIRST(&clock_list); while (clk && clk->parent != parent) clk = SLIST_NEXT(clk, link); #endif return clk; } static bool clk_is_parent_last_child(struct clk *clk) { return !find_next_clk(clk->parent, clk); } static bool indent_last_node_already_found(struct clk *node_clk, int node_indent, int cur_indent) { struct clk *clk = node_clk; int n = 0; /* Find parent clock at level @node_indent - @cur_indent - 1 */ for (n = 0; n < node_indent - cur_indent - 1; n++) clk = clk->parent; return clk_is_parent_last_child(clk); } static void __maybe_unused print_clk(struct clk *clk, int indent) { static const char * const rate_unit[] = { "Hz", "kHz", "MHz", "GHz" }; int max_unit = ARRAY_SIZE(rate_unit); unsigned long rate = 0; char msg_buf[128] = { }; char *msg_end = msg_buf + sizeof(msg_buf); char *msg = msg_buf; int n = 0; /* * Currently prints the clock state based on the clock refcount. * A future change could print the hardware clock state when * related clock driver provides a struct clk_ops::is_enabled handler */ if (indent) { /* Indent for root clock level */ msg = add_msg(msg, msg_end, " "); if (!msg) goto out; /* Indent for root parent to clock parent levels */ for (n = 0; n < indent - 1; n++) { if (indent_last_node_already_found(clk, indent, n)) msg = add_msg(msg, msg_end, " "); else msg = add_msg(msg, msg_end, "| "); if (!msg) goto out; } /* Clock indentation */ if (clk_is_parent_last_child(clk)) msg = add_msg(msg, msg_end, "`-- "); else msg = add_msg(msg, msg_end, "|-- "); } else { /* Root clock indentation */ msg = add_msg(msg, msg_end, "o- "); } if (!msg) goto out; rate = clk_get_rate(clk); for (n = 1; rate && !(rate % 1000) && n < max_unit; n++) rate /= 1000; msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / %ld %s)", clk_get_name(clk), refcount_val(&clk->enabled_count) ? "on " : "off", refcount_val(&clk->enabled_count), rate, rate_unit[n - 1]); if (!msg) goto out; out: if (!msg) snprintf(msg_end - 4, 4, "..."); DMSG("%s", msg_buf); } static void print_tree(void) { struct clk *clk = NULL; struct clk *parent = NULL; struct clk *next = NULL; int indent = -1; #ifdef CFG_DRIVERS_CLK_PRINT_TREE if (SLIST_EMPTY(&clock_list)) { DMSG("-- No registered clock"); return; } #endif while (true) { next = find_next_clk(parent, clk); if (next) { print_clk(next, indent + 1); /* Enter the subtree of the next clock */ parent = next; indent++; clk = NULL; } else { /* * We've processed all children at this level. * If parent is NULL we're at the top and are done. */ if (!parent) break; /* * Move up one level to resume with the next * child clock of the parent. */ clk = parent; parent = clk->parent; indent--; } } } void clk_print_tree(void) { if (IS_ENABLED(CFG_DRIVERS_CLK_PRINT_TREE) && TRACE_LEVEL >= TRACE_DEBUG) { DMSG("Clock tree summary (informative):"); print_tree(); } } optee_os-4.3.0/core/drivers/clk/clk_dt.c000066400000000000000000000120361464416617300201340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Bootlin */ #include #include #include #include #include #include #include #include #include TEE_Result clk_dt_get_by_name(const void *fdt, int nodeoffset, const char *name, struct clk **clk) { int clk_id = 0; clk_id = fdt_stringlist_search(fdt, nodeoffset, "clock-names", name); if (clk_id < 0) { *clk = NULL; return TEE_ERROR_GENERIC; } return clk_dt_get_by_index(fdt, nodeoffset, clk_id, clk); } static TEE_Result clk_dt_get_by_idx_prop(const char *prop_name, const void *fdt, int nodeoffset, unsigned int clk_idx, struct clk **clk) { TEE_Result res = TEE_ERROR_GENERIC; void *out_clk = NULL; res = dt_driver_device_from_node_idx_prop(prop_name, fdt, nodeoffset, clk_idx, DT_DRIVER_CLK, &out_clk); if (!res) *clk = out_clk; return res; } TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset, unsigned int clk_idx, struct clk **clk) { return clk_dt_get_by_idx_prop("clocks", fdt, nodeoffset, clk_idx, clk); } #ifdef CFG_DRIVERS_CLK_EARLY_PROBE /* Recursively called from parse_clock_property() */ static TEE_Result clk_probe_clock_provider_node(const void *fdt, int node); static TEE_Result parse_clock_property(const void *fdt, int node) { int len = 0; int idx = 0; int parent_node = 0; int clock_cells = 0; uint32_t phandle = 0; const uint32_t *prop = NULL; TEE_Result res = TEE_ERROR_GENERIC; prop = fdt_getprop(fdt, node, "clocks", &len); if (!prop) return TEE_SUCCESS; len /= sizeof(uint32_t); while (idx < len) { phandle = fdt32_to_cpu(prop[idx]); parent_node = fdt_node_offset_by_phandle(fdt, phandle); if (parent_node < 0) return TEE_ERROR_GENERIC; /* Parent probe should not fail or clock won't be available */ res = clk_probe_clock_provider_node(fdt, parent_node); if (res) { EMSG("Probe parent clock node %s on node %s: %#"PRIx32, fdt_get_name(fdt, parent_node, NULL), fdt_get_name(fdt, node, NULL), res); panic(); } clock_cells = fdt_get_dt_driver_cells(fdt, parent_node, DT_DRIVER_CLK); if (clock_cells < 0) return TEE_ERROR_GENERIC; idx += 1 + clock_cells; } return TEE_SUCCESS; } static TEE_Result clk_probe_clock_provider_node(const void *fdt, int node) { int len = 0; int status = 0; TEE_Result res = TEE_ERROR_GENERIC; status = fdt_get_status(fdt, node); if (!(status & DT_STATUS_OK_SEC)) return TEE_ERROR_ITEM_NOT_FOUND; /* Check if the node is a clock provider */ if (!fdt_getprop(fdt, node, "#clock-cells", &len)) return TEE_ERROR_ITEM_NOT_FOUND; /* Check if node has already been probed */ if (dt_driver_get_provider_by_node(node, DT_DRIVER_CLK)) return TEE_SUCCESS; /* Check if the node has a clock property first to probe parent */ res = parse_clock_property(fdt, node); if (res) return res; return dt_driver_probe_device_by_node(fdt, node, DT_DRIVER_CLK); } static void clk_probe_node(const void *fdt, int parent_node) { int child = 0; int status = 0; __maybe_unused TEE_Result res = TEE_ERROR_GENERIC; fdt_for_each_subnode(child, fdt, parent_node) { status = fdt_get_status(fdt, child); if (status == DT_STATUS_DISABLED) continue; res = clk_probe_clock_provider_node(fdt, child); assert(res == TEE_SUCCESS || res == TEE_ERROR_ITEM_NOT_FOUND); clk_probe_node(fdt, child); } } static void parse_assigned_clock(const void *fdt, int nodeoffset) { int rate_len = 0; int clock_idx = 0; struct clk *clk = NULL; unsigned long rate = 0; struct clk *parent = NULL; const uint32_t *rate_prop = NULL; TEE_Result res = TEE_ERROR_GENERIC; rate_prop = fdt_getprop(fdt, nodeoffset, "assigned-clock-rates", &rate_len); rate_len /= sizeof(uint32_t); while (true) { res = clk_dt_get_by_idx_prop("assigned-clocks", fdt, nodeoffset, clock_idx, &clk); if (res) return; assert(clk); res = clk_dt_get_by_idx_prop("assigned-clock-parents", fdt, nodeoffset, clock_idx, &parent); if (parent) { assert(!res); if (clk_set_parent(clk, parent)) { EMSG("Could not set clk %s parent to clock %s", clk->name, parent->name); panic(); } } if (rate_prop && clock_idx < rate_len) { rate = fdt32_to_cpu(rate_prop[clock_idx]); if (rate && clk_set_rate(clk, rate) != TEE_SUCCESS) panic(); } clock_idx++; } } static void clk_probe_assigned(const void *fdt, int parent_node) { int len = 0; int child = 0; int status = 0; fdt_for_each_subnode(child, fdt, parent_node) { clk_probe_assigned(fdt, child); status = fdt_get_status(fdt, child); if (status == DT_STATUS_DISABLED) continue; if (fdt_getprop(fdt, child, "assigned-clocks", &len)) parse_assigned_clock(fdt, child); } } static TEE_Result clk_dt_probe(void) { const void *fdt = get_secure_dt(); DMSG("Probing clocks from devicetree"); if (!fdt) panic(); clk_probe_node(fdt, -1); clk_probe_assigned(fdt, -1); return TEE_SUCCESS; } early_init(clk_dt_probe); #endif optee_os-4.3.0/core/drivers/clk/fixed_clk.c000066400000000000000000000027661464416617300206350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Bootlin */ #include #include #include #include #include struct fixed_clock_data { unsigned long rate; }; static unsigned long fixed_clk_get_rate(struct clk *clk, unsigned long parent_rate __unused) { struct fixed_clock_data *d = clk->priv; return d->rate; } static const struct clk_ops fixed_clk_clk_ops = { .get_rate = fixed_clk_get_rate, }; static TEE_Result fixed_clock_probe(const void *fdt, int offs, const void *compat_data __unused) { const uint32_t *freq = NULL; const char *name = NULL; struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; struct fixed_clock_data *fcd = NULL; name = fdt_get_name(fdt, offs, NULL); if (!name) name = "fixed-clock"; clk = clk_alloc(name, &fixed_clk_clk_ops, NULL, 0); if (!clk) return TEE_ERROR_OUT_OF_MEMORY; fcd = calloc(1, sizeof(struct fixed_clock_data)); if (!fcd) { res = TEE_ERROR_OUT_OF_MEMORY; goto free_clk; } freq = fdt_getprop(fdt, offs, "clock-frequency", NULL); if (!freq) { res = TEE_ERROR_BAD_FORMAT; goto free_fcd; } fcd->rate = fdt32_to_cpu(*freq); clk->priv = fcd; res = clk_register(clk); if (res) goto free_fcd; res = clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk, clk); if (!res) return TEE_SUCCESS; free_fcd: free(fcd); free_clk: clk_free(clk); return res; } CLK_DT_DECLARE(fixed_clock, "fixed-clock", fixed_clock_probe); optee_os-4.3.0/core/drivers/clk/sam/000077500000000000000000000000001464416617300173065ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/clk/sam/at91_audio_pll.c000066400000000000000000000223351464416617300222650ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2016 Atmel Corporation, * Songjun Wu , * Nicolas Ferre * Copyright (C) 2017 Free Electrons, * Quentin Schulz * * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of * its own parent. PMC and PAD can then divide the FRAC rate to best match the * asked rate. * * Traits of FRAC clock: * enable - clk_enable writes nd, fracr parameters and enables PLL * rate - rate is adjustable. * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22)) * parent - fixed parent. No clk_set_parent support * * Traits of PMC clock: * enable - clk_enable writes qdpmc, and enables PMC output * rate - rate is adjustable. * clk->rate = parent->rate / (qdpmc + 1) * parent - fixed parent. No clk_set_parent support * * Traits of PAD clock: * enable - clk_enable writes divisors and enables PAD output * rate - rate is adjustable. * clk->rate = parent->rate / (qdaudio * div)) * parent - fixed parent. No clk_set_parent support */ #include #include #include #include #include #include #include "at91_clk.h" #define AUDIO_PLL_DIV_FRAC BIT(22) #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \ AT91_PMC_AUDIO_PLL_ND_OFFSET) #define AUDIO_PLL_QDPAD(qd, div) \ ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \ AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \ (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \ AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK)) #define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \ AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) #define AUDIO_PLL_FOUT_MIN 620000000UL #define AUDIO_PLL_FOUT_MAX 700000000UL struct clk_audio_frac { vaddr_t base; uint32_t fracr; uint8_t nd; }; struct clk_audio_pad { vaddr_t base; uint8_t qdaudio; uint8_t div; }; struct clk_audio_pmc { vaddr_t base; uint8_t qdpmc; }; static TEE_Result clk_audio_pll_frac_enable(struct clk *clk) { struct clk_audio_frac *frac = clk->priv; io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_RESETN); io_setbits32(frac->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_RESETN); io_clrsetbits32(frac->base + AT91_PMC_AUDIO_PLL1, AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr); /* * reset and enable have to be done in 2 separated writes * for AT91_PMC_AUDIO_PLL0 */ io_clrsetbits32(frac->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PLLEN | AT91_PMC_AUDIO_PLL_ND_MASK, AT91_PMC_AUDIO_PLL_PLLEN | AT91_PMC_AUDIO_PLL_ND(frac->nd)); return TEE_SUCCESS; } static TEE_Result clk_audio_pll_pad_enable(struct clk *clk) { struct clk_audio_pad *apad_ck = clk->priv; io_clrsetbits32(apad_ck->base + AT91_PMC_AUDIO_PLL1, AT91_PMC_AUDIO_PLL_QDPAD_MASK, AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div)); io_clrsetbits32(apad_ck->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN); return TEE_SUCCESS; } static TEE_Result clk_audio_pll_pmc_enable(struct clk *clk) { struct clk_audio_pmc *apmc_ck = clk->priv; io_clrsetbits32(apmc_ck->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PMCEN | AT91_PMC_AUDIO_PLL_QDPMC_MASK, AT91_PMC_AUDIO_PLL_PMCEN | AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc)); return TEE_SUCCESS; } static void clk_audio_pll_frac_disable(struct clk *clk) { struct clk_audio_frac *frac = clk->priv; io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PLLEN); /* Requires 2 separated writes */ io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_RESETN); } static void clk_audio_pll_pad_disable(struct clk *clk) { struct clk_audio_pad *apad_ck = clk->priv; io_clrbits32(apad_ck->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PADEN); } static void clk_audio_pll_pmc_disable(struct clk *clk) { struct clk_audio_pmc *apmc_ck = clk->priv; io_clrbits32(apmc_ck->base + AT91_PMC_AUDIO_PLL0, AT91_PMC_AUDIO_PLL_PMCEN); } static unsigned long clk_audio_pll_fout(unsigned long parent_rate, unsigned long nd, unsigned long fracr) { unsigned long long fr = (unsigned long long)parent_rate * fracr; fr = UDIV_ROUND_NEAREST(fr, AUDIO_PLL_DIV_FRAC); return parent_rate * (nd + 1) + fr; } static unsigned long clk_audio_pll_frac_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_audio_frac *frac = clk->priv; return clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr); } static unsigned long clk_audio_pll_pad_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_audio_pad *apad_ck = clk->priv; unsigned long apad_rate = 0; if (apad_ck->qdaudio && apad_ck->div) apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div); return apad_rate; } static unsigned long clk_audio_pll_pmc_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_audio_pmc *apmc_ck = clk->priv; return parent_rate / (apmc_ck->qdpmc + 1); } static TEE_Result clk_audio_pll_frac_compute_frac(unsigned long rate, unsigned long parent_rate, unsigned long *nd, unsigned long *fracr) { unsigned long long tmp = 0; unsigned long long rem = 0; if (!rate || !parent_rate) return TEE_ERROR_BAD_PARAMETERS; tmp = rate; rem = tmp % parent_rate; tmp /= parent_rate; if (!tmp || tmp >= AUDIO_PLL_ND_MAX) return TEE_ERROR_BAD_PARAMETERS; *nd = tmp - 1; tmp = rem * AUDIO_PLL_DIV_FRAC; tmp = UDIV_ROUND_NEAREST(tmp, parent_rate); if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK) return TEE_ERROR_BAD_PARAMETERS; /* we can cast here as we verified the bounds just above */ *fracr = (unsigned long)tmp; return TEE_SUCCESS; } static TEE_Result clk_audio_pll_frac_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_audio_frac *frac = clk->priv; unsigned long fracr = 0; unsigned long nd = 0; TEE_Result res = TEE_ERROR_GENERIC; if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX) return TEE_ERROR_BAD_PARAMETERS; res = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr); if (res) return res; frac->nd = nd; frac->fracr = fracr; return TEE_SUCCESS; } static TEE_Result clk_audio_pll_pad_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_audio_pad *apad_ck = clk->priv; uint8_t tmp_div = 1; if (!rate) return TEE_ERROR_BAD_PARAMETERS; tmp_div = parent_rate / rate; if (tmp_div % 3 == 0) { apad_ck->qdaudio = tmp_div / 3; apad_ck->div = 3; } else { apad_ck->qdaudio = tmp_div / 2; apad_ck->div = 2; } return TEE_SUCCESS; } static TEE_Result clk_audio_pll_pmc_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_audio_pmc *apmc_ck = clk->priv; if (!rate) return TEE_ERROR_BAD_PARAMETERS; apmc_ck->qdpmc = parent_rate / rate - 1; return TEE_SUCCESS; } static const struct clk_ops audio_pll_frac_ops = { .enable = clk_audio_pll_frac_enable, .disable = clk_audio_pll_frac_disable, .get_rate = clk_audio_pll_frac_get_rate, .set_rate = clk_audio_pll_frac_set_rate, }; static const struct clk_ops audio_pll_pad_ops = { .enable = clk_audio_pll_pad_enable, .disable = clk_audio_pll_pad_disable, .get_rate = clk_audio_pll_pad_get_rate, .set_rate = clk_audio_pll_pad_set_rate, }; static const struct clk_ops audio_pll_pmc_ops = { .enable = clk_audio_pll_pmc_enable, .disable = clk_audio_pll_pmc_disable, .get_rate = clk_audio_pll_pmc_get_rate, .set_rate = clk_audio_pll_pmc_set_rate, }; struct clk * at91_clk_register_audio_pll_frac(struct pmc_data *pmc, const char *name, struct clk *parent) { struct clk_audio_frac *frac_ck = NULL; struct clk *clk = NULL; clk = clk_alloc(name, &audio_pll_frac_ops, &parent, 1); if (!clk) return NULL; frac_ck = calloc(1, sizeof(*frac_ck)); if (!frac_ck) { clk_free(clk); return NULL; } clk->flags = CLK_SET_RATE_GATE; frac_ck->base = pmc->base; clk->priv = frac_ck; if (clk_register(clk)) { clk_free(clk); free(frac_ck); return NULL; } return clk; } struct clk * at91_clk_register_audio_pll_pad(struct pmc_data *pmc, const char *name, struct clk *parent) { struct clk_audio_pad *apad_ck = NULL; struct clk *clk = NULL; clk = clk_alloc(name, &audio_pll_pad_ops, &parent, 1); if (!clk) return NULL; apad_ck = calloc(1, sizeof(*apad_ck)); if (!apad_ck) { clk_free(clk); return NULL; } clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; apad_ck->base = pmc->base; clk->priv = apad_ck; if (clk_register(clk)) { clk_free(clk); free(apad_ck); return NULL; } return clk; } struct clk * at91_clk_register_audio_pll_pmc(struct pmc_data *pmc, const char *name, struct clk *parent) { struct clk_audio_pmc *apmc_ck = NULL; struct clk *clk = NULL; clk = clk_alloc(name, &audio_pll_pmc_ops, &parent, 1); if (!clk) return NULL; apmc_ck = calloc(1, sizeof(*apmc_ck)); if (!apmc_ck) { clk_free(clk); return NULL; } clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; apmc_ck->base = pmc->base; clk->priv = apmc_ck; if (clk_register(clk)) { clk_free(clk); free(apmc_ck); return NULL; } return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_clk.h000066400000000000000000000160241464416617300210710ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ /* * include/linux/clk/at91_pmc.h * * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People * Copyright (C) 2021 Microchip * * Power Management Controller (PMC) - System peripherals registers. * Based on AT91RM9200 datasheet revision E. */ #ifndef AT91_CLK_H #define AT91_CLK_H #include #include #include "at91_pmc.h" #define ffs(x) __builtin_ffs(x) #define field_get(_mask, _reg) \ ({ \ typeof(_mask) __mask = _mask; \ \ (((_reg) & (__mask)) >> (ffs(__mask) - 1)); \ }) #define field_prep(_mask, _val) \ ({ \ typeof(_mask) __mask = _mask; \ \ (((_val) << (ffs(__mask) - 1)) & (__mask)); \ }) struct clk_range { unsigned long min; unsigned long max; }; #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} struct pmc_clk { struct clk *clk; uint8_t id; }; struct pmc_data { vaddr_t base; unsigned int ncore; struct pmc_clk *chws; unsigned int nsystem; struct pmc_clk *shws; unsigned int nperiph; struct pmc_clk *phws; unsigned int ngck; struct pmc_clk *ghws; unsigned int npck; struct pmc_clk *pchws; struct pmc_clk hwtable[]; }; /* PLL */ struct clk_pll_layout { uint32_t pllr_mask; uint32_t mul_mask; uint32_t frac_mask; uint32_t div_mask; uint32_t endiv_mask; uint8_t mul_shift; uint8_t frac_shift; uint8_t div_shift; uint8_t endiv_shift; }; struct clk_pcr_layout { uint32_t offset; uint32_t cmd; uint32_t div_mask; uint32_t gckcss_mask; uint32_t pid_mask; }; struct clk_pll_charac { struct clk_range input; int num_output; const struct clk_range *output; uint16_t *icpll; uint8_t *out; uint8_t upll : 1; }; extern const struct clk_pll_layout sama5d3_pll_layout; /* Master */ struct clk_master_charac { struct clk_range output; uint32_t divisors[5]; uint8_t have_div3_pres; }; struct clk_master_layout { uint32_t offset; uint32_t mask; uint8_t pres_shift; }; struct clk_programmable_layout { uint8_t pres_mask; uint8_t pres_shift; uint8_t css_mask; uint8_t have_slck_mck; uint8_t is_pres_direct; }; extern const struct clk_master_layout at91sam9x5_master_layout; vaddr_t at91_pmc_get_base(void); TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, struct clk **clk); TEE_Result pmc_clk_get(struct pmc_data *pmc, unsigned int type, unsigned int idx, struct clk **clk); struct clk *at91_sckc_clk_get(void); struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem, unsigned int nperiph, unsigned int ngck, unsigned int npck); TEE_Result clk_dt_pmc_get(struct dt_pargs *args, void *data, struct clk **clk); struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk, const char *name); /* Main clock */ struct clk *pmc_register_main_rc_osc(struct pmc_data *pmc, const char *name, unsigned long freq); struct clk *pmc_register_main_osc(struct pmc_data *pmc, const char *name, struct clk *parent, bool bypass); struct clk *at91_clk_register_sam9x5_main(struct pmc_data *pmc, const char *name, struct clk **parent_clocks, unsigned int num_parents); /* PLL */ struct clk * at91_clk_register_pll(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id, const struct clk_pll_layout *layout, const struct clk_pll_charac *charac); struct clk * at91_clk_register_plldiv(struct pmc_data *pmc, const char *name, struct clk *parent); struct clk *sam9x60_clk_register_frac_pll(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id, const struct clk_pll_charac *charac, const struct clk_pll_layout *layout, uint32_t flags); struct clk *sam9x60_clk_register_div_pll(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id, const struct clk_pll_charac *charac, const struct clk_pll_layout *layout, uint32_t flags, uint32_t safe_div); /* UTMI */ struct clk * at91_clk_register_utmi(struct pmc_data *pmc, const char *name, struct clk *parent); struct clk *at91_clk_sama7g5_register_utmi(struct pmc_data *pmc, const char *name, struct clk *parent); struct clk *sama7_utmi_clk_register(const char *name, struct clk *parent, uint8_t id); /* Master */ struct clk * at91_clk_register_master_pres(struct pmc_data *pmc, const char *name, int num_parents, struct clk **parents, const struct clk_master_layout *layout, const struct clk_master_charac *charac, int chg_pid); struct clk * at91_clk_register_master_div(struct pmc_data *pmc, const char *name, struct clk *parent, const struct clk_master_layout *layout, const struct clk_master_charac *charac); /* * @mux_table: when @mux_table is not NULL it shall hold @num_parents cells */ struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc, const char *name, int num_parents, struct clk **parent, uint32_t *mux_table, uint8_t id, int chg_pid); /* H32MX */ struct clk * at91_clk_register_h32mx(struct pmc_data *pmc, const char *name, struct clk *parent); /* USB */ struct clk * at91sam9x5_clk_register_usb(struct pmc_data *pmc, const char *name, struct clk **parents, uint8_t num_parents); /* Programmable */ struct clk * at91_clk_register_programmable(struct pmc_data *pmc, const char *name, struct clk **parents, uint8_t num_parents, uint8_t id, const struct clk_programmable_layout *layout); struct clk * at91_clk_register_system(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id); struct clk * at91_clk_register_sam9x5_periph(struct pmc_data *pmc, const struct clk_pcr_layout *layout, const char *name, struct clk *parent, uint32_t id, const struct clk_range *range); struct clk * at91_clk_register_generated(struct pmc_data *pmc, const struct clk_pcr_layout *layout, const char *name, struct clk **parents, uint32_t *mux_table, uint8_t num_parents, uint8_t id, const struct clk_range *range, int chg_pid); struct clk * at91_clk_i2s_mux_register(const char *name, struct clk **parents, unsigned int num_parents, uint8_t bus_id); /* Audio PLL */ struct clk * at91_clk_register_audio_pll_frac(struct pmc_data *pmc, const char *name, struct clk *parent); struct clk * at91_clk_register_audio_pll_pad(struct pmc_data *pmc, const char *name, struct clk *parent); struct clk * at91_clk_register_audio_pll_pmc(struct pmc_data *pmc, const char *name, struct clk *parent); /* CPU OPP (Operation Performance Points) */ struct clk *at91_cpu_opp_clk_get(void); TEE_Result at91_clk_register_cpu_opp(const void *fdt, int node, struct clk *clk); #ifdef CFG_PM_ARM32 void pmc_register_id(uint8_t id); void pmc_register_pck(uint8_t pck); void pmc_register_pm(void); #else static inline void pmc_register_id(uint8_t id __unused) {} static inline void pmc_register_pck(uint8_t pck __unused) {} static inline void pmc_register_pm(void) {} #endif #endif optee_os-4.3.0/core/drivers/clk/sam/at91_cpu_opp.c000066400000000000000000000066721464416617300217700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2024 Microchip Technology Inc. */ #include #include #include #include #include #include #define OPP_RATES_MAX 8 /* the clock rates for CPU OPP */ struct clk_rates { size_t rate_num; /* the number of valid clock rates in @rates */ unsigned long rates[OPP_RATES_MAX]; }; static struct clk_rates *opp_rates; static TEE_Result get_rates_array(struct clk *clk __unused, size_t start_index, unsigned long *rates, size_t *nb_elts) { if (!opp_rates) panic("Invalid CPU OPP Rates Array"); if (!rates) { *nb_elts = opp_rates->rate_num; return TEE_SUCCESS; } if (start_index + *nb_elts > opp_rates->rate_num) { EMSG("Bad parameter(s): start_index %zu, nb_elts %zu", start_index, *nb_elts); return TEE_ERROR_BAD_PARAMETERS; } memcpy(rates, &opp_rates->rates[start_index], *nb_elts * sizeof(*rates)); return TEE_SUCCESS; } static TEE_Result cpu_opp_clk_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { size_t n = 0; assert(clk->parent); for (n = 0; n < opp_rates->rate_num; n++) if (rate == opp_rates->rates[n]) break; if (n == opp_rates->rate_num) return TEE_ERROR_BAD_PARAMETERS; return clk->parent->ops->set_rate(clk->parent, rate, parent_rate); } static const struct clk_ops cpu_opp_clk_ops = { .set_rate = cpu_opp_clk_set_rate, .get_rates_array = get_rates_array, }; static TEE_Result dt_get_opp_hz(const void *fdt, int node, unsigned long *value) { const char *property = "opp-hz"; const fdt64_t *p = NULL; int len = 0; p = fdt_getprop(fdt, node, property, &len); if (!p) return TEE_ERROR_ITEM_NOT_FOUND; if (len != sizeof(*p)) return TEE_ERROR_BAD_FORMAT; *value = fdt64_ld(p); return TEE_SUCCESS; } static TEE_Result opp_rates_setup(const void *fdt, int node) { const char *compatible = "operating-points-v2"; const fdt32_t *cuint = NULL; size_t rate_num = 0; int opp_table = 0; int offset = 0; cuint = fdt_getprop(fdt, node, compatible, NULL); if (!cuint) return TEE_ERROR_NOT_SUPPORTED; opp_rates = calloc(1, sizeof(*opp_rates)); if (!opp_rates) { EMSG("Fail to alloc opp_rates"); return TEE_ERROR_OUT_OF_MEMORY; } offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); if (offset < 0) panic("Invalid offset of opp-table"); if (fdt_node_check_compatible(fdt, offset, compatible)) panic("Invalid opp-table"); fdt_for_each_subnode(opp_table, fdt, offset) { if (rate_num >= OPP_RATES_MAX) panic("CPU OPP rate array shortage"); if (dt_get_opp_hz(fdt, opp_table, opp_rates->rates + rate_num)) panic("Get opp-hz failed"); rate_num++; } opp_rates->rate_num = rate_num; return TEE_SUCCESS; } static struct clk *cpu_opp_clk; struct clk *at91_cpu_opp_clk_get(void) { return cpu_opp_clk; } TEE_Result at91_clk_register_cpu_opp(const void *fdt, int node, struct clk *clk) { TEE_Result res = TEE_ERROR_GENERIC; res = opp_rates_setup(fdt, node); if (res == TEE_ERROR_NOT_SUPPORTED) return TEE_SUCCESS; if (res) return res; cpu_opp_clk = clk_alloc("cpu-opp", &cpu_opp_clk_ops, &clk, 1); if (!cpu_opp_clk) panic("CPU OPP clock alloc failed"); res = clk_register(cpu_opp_clk); if (res) { clk_free(cpu_opp_clk); return res; } /* CPU clock is likely always enabled so set its refcount */ if (clk_enable(cpu_opp_clk)) panic("CPU clock should always enabled"); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/clk/sam/at91_generated.c000066400000000000000000000111731464416617300222510ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2015 - 2021 Atmel Corporation, * Nicolas Ferre * * Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON. */ #include #include #include #include #include #include #include "at91_clk.h" #define GENERATED_MAX_DIV 255 struct clk_generated { vaddr_t base; struct clk_range range; uint32_t *mux_table; uint32_t id; uint32_t gckdiv; const struct clk_pcr_layout *layout; uint8_t parent_id; int chg_pid; }; static TEE_Result clk_generated_enable(struct clk *clk) { struct clk_generated *gck = clk->priv; io_write32(gck->base + gck->layout->offset, (gck->id & gck->layout->pid_mask)); io_clrsetbits32(gck->base + gck->layout->offset, AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask | gck->layout->cmd | AT91_PMC_PCR_GCKEN, field_prep(gck->layout->gckcss_mask, gck->parent_id) | gck->layout->cmd | ((gck->gckdiv << AT91_PMC_PCR_GCKDIV_SHIFT) & AT91_PMC_PCR_GCKDIV_MASK) | AT91_PMC_PCR_GCKEN); return TEE_SUCCESS; } static void clk_generated_disable(struct clk *clk) { struct clk_generated *gck = clk->priv; io_write32(gck->base + gck->layout->offset, gck->id & gck->layout->pid_mask); io_clrsetbits32(gck->base + gck->layout->offset, AT91_PMC_PCR_GCKEN, gck->layout->cmd); } static unsigned long clk_generated_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_generated *gck = clk->priv; return UDIV_ROUND_NEAREST(parent_rate, gck->gckdiv + 1); } /* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */ static TEE_Result clk_generated_set_parent(struct clk *clk, size_t index) { struct clk_generated *gck = clk->priv; if (index >= clk_get_num_parents(clk)) return TEE_ERROR_BAD_PARAMETERS; if (gck->mux_table) gck->parent_id = gck->mux_table[index]; else gck->parent_id = index; return TEE_SUCCESS; } static size_t clk_generated_get_parent(struct clk *clk) { struct clk_generated *gck = clk->priv; unsigned int i = 0; if (gck->mux_table) { for (i = 0; i < clk_get_num_parents(clk); i++) if (gck->mux_table[i] == gck->parent_id) return i; panic("Can't get correct parent of clock"); } else { return gck->parent_id; } } /* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */ static TEE_Result clk_generated_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_generated *gck = clk->priv; uint32_t div = 1; if (!rate) return TEE_ERROR_BAD_PARAMETERS; if (gck->range.max && rate > gck->range.max) return TEE_ERROR_BAD_PARAMETERS; div = UDIV_ROUND_NEAREST(parent_rate, rate); if (div > GENERATED_MAX_DIV + 1 || !div) return TEE_ERROR_GENERIC; gck->gckdiv = div - 1; return TEE_SUCCESS; } static const struct clk_ops generated_ops = { .enable = clk_generated_enable, .disable = clk_generated_disable, .get_rate = clk_generated_get_rate, .get_parent = clk_generated_get_parent, .set_parent = clk_generated_set_parent, .set_rate = clk_generated_set_rate, }; /** * clk_generated_startup - Initialize a given clock to its default parent and * divisor parameter. * * @gck: Generated clock to set the startup parameters for. * * Take parameters from the hardware and update local clock configuration * accordingly. */ static void clk_generated_startup(struct clk_generated *gck) { uint32_t tmp = 0; io_write32(gck->base + gck->layout->offset, (gck->id & gck->layout->pid_mask)); tmp = io_read32(gck->base + gck->layout->offset); gck->parent_id = field_get(gck->layout->gckcss_mask, tmp); gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK) >> AT91_PMC_PCR_GCKDIV_SHIFT; } struct clk * at91_clk_register_generated(struct pmc_data *pmc, const struct clk_pcr_layout *layout, const char *name, struct clk **parents, uint32_t *mux_table, uint8_t num_parents, uint8_t id, const struct clk_range *range, int chg_pid) { struct clk_generated *gck = NULL; struct clk *clk = NULL; clk = clk_alloc(name, &generated_ops, parents, num_parents); if (!clk) return NULL; gck = calloc(1, sizeof(*gck)); if (!gck) { clk_free(clk); return NULL; } clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; gck->id = id; gck->base = pmc->base; memcpy(&gck->range, range, sizeof(gck->range)); gck->chg_pid = chg_pid; gck->layout = layout; gck->mux_table = mux_table; clk->priv = gck; clk_generated_startup(gck); if (clk_register(clk)) { clk_free(clk); free(gck); return NULL; } pmc_register_id(id); return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_h32mx.c000066400000000000000000000030651464416617300212550ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2014 Atmel * * Alexandre Belloni */ #include #include #include #include #include "at91_clk.h" #define H32MX_MAX_FREQ 90000000 static unsigned long clk_sama5d4_h32mx_get_rate(struct clk *clk, unsigned long parent_rate) { struct pmc_data *pmc = clk->priv; unsigned int mckr = io_read32(pmc->base + AT91_PMC_MCKR); if (mckr & AT91_PMC_H32MXDIV) return parent_rate / 2; if (parent_rate > H32MX_MAX_FREQ) IMSG("H32MX clock is too fast"); return parent_rate; } static TEE_Result clk_sama5d4_h32mx_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct pmc_data *pmc = clk->priv; uint32_t mckr = 0; if (parent_rate != rate && (parent_rate / 2) != rate) return TEE_ERROR_BAD_PARAMETERS; if ((parent_rate / 2) == rate) mckr = AT91_PMC_H32MXDIV; io_clrsetbits32(pmc->base + AT91_PMC_MCKR, AT91_PMC_H32MXDIV, mckr); return TEE_SUCCESS; } static const struct clk_ops h32mx_ops = { .get_rate = clk_sama5d4_h32mx_get_rate, .set_rate = clk_sama5d4_h32mx_set_rate, }; struct clk * at91_clk_register_h32mx(struct pmc_data *pmc, const char *name, struct clk *parent) { struct clk *clk = NULL; clk = clk_alloc(name, &h32mx_ops, &parent, 1); if (!clk) return NULL; clk->ops = &h32mx_ops; clk->priv = pmc; clk->name = name; clk->flags = CLK_SET_RATE_GATE; if (clk_register(clk)) { clk_free(clk); return NULL; } return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_i2s_mux.c000066400000000000000000000027771464416617300217130ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2018 Microchip Technology Inc, * Codrin Ciubotariu */ #include #include #include #include #include #include #include "at91_clk.h" struct clk_i2s_mux { vaddr_t sfr_base; uint8_t bus_id; }; static size_t clk_i2s_mux_get_parent(struct clk *clk) { struct clk_i2s_mux *mux = clk->priv; uint32_t val = io_read32(mux->sfr_base + AT91_SFR_I2SCLKSEL); return (val & BIT(mux->bus_id)) >> mux->bus_id; } static TEE_Result clk_i2s_mux_set_parent(struct clk *clk, size_t index) { struct clk_i2s_mux *mux = clk->priv; io_clrsetbits32(mux->sfr_base + AT91_SFR_I2SCLKSEL, BIT(mux->bus_id), index << mux->bus_id); return TEE_SUCCESS; } static const struct clk_ops clk_i2s_mux_ops = { .get_parent = clk_i2s_mux_get_parent, .set_parent = clk_i2s_mux_set_parent, }; struct clk * at91_clk_i2s_mux_register(const char *name, struct clk **parents, unsigned int num_parents, uint8_t bus_id) { struct clk_i2s_mux *i2s_ck = NULL; struct clk *clk = NULL; clk = clk_alloc(name, &clk_i2s_mux_ops, parents, num_parents); if (!clk) return NULL; i2s_ck = calloc(1, sizeof(*i2s_ck)); if (!i2s_ck) { clk_free(clk); return NULL; } i2s_ck->bus_id = bus_id; i2s_ck->sfr_base = sam_sfr_base(); clk->priv = i2s_ck; if (clk_register(clk)) { clk_free(clk); free(i2s_ck); return NULL; } return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_main.c000066400000000000000000000144531464416617300212430ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" #define SLOW_CLOCK_FREQ 32768 #define MAINF_DIV 16 #define USEC_PER_SEC 1000000L #define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) #define OSC_READY_TIMEOUT_US 1000 #define MOR_KEY_MASK (0xFF << 16) #define CLK_MAIN_PARENT_SELECT(s) (((s) & \ (AT91_PMC_MOSCEN | \ AT91_PMC_OSCBYPASS)) ? 1 : 0) /* * Main RC Oscillator */ struct main_rc_osc { unsigned long freq; vaddr_t base; }; static bool pmc_main_rc_osc_ready(struct main_rc_osc *osc) { uint32_t status = io_read32(osc->base + AT91_PMC_SR); return status & AT91_PMC_MOSCRCS; } static TEE_Result pmc_main_rc_osc_enable(struct clk *clk) { struct main_rc_osc *osc = clk->priv; uint32_t mor = io_read32(osc->base + AT91_CKGR_MOR); /* Enable the oscillator if not */ if (!(mor & AT91_PMC_MOSCRCEN)) { io_clrsetbits32(osc->base + AT91_CKGR_MOR, MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_MOSCRCEN | AT91_PMC_KEY); } while (!pmc_main_rc_osc_ready(osc)) ; return TEE_SUCCESS; } static void pmc_main_rc_osc_disable(struct clk *clk) { struct main_rc_osc *osc = clk->priv; uint32_t mor = io_read32(osc->base + AT91_CKGR_MOR); if (!(mor & AT91_PMC_MOSCRCEN)) return; io_clrsetbits32(osc->base + AT91_CKGR_MOR, MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY); } static unsigned long pmc_main_rc_osc_get_rate(struct clk *clk, unsigned long parent_rate __unused) { struct main_rc_osc *osc = clk->priv; return osc->freq; } static const struct clk_ops pmc_main_rc_osc_clk_ops = { .enable = pmc_main_rc_osc_enable, .disable = pmc_main_rc_osc_disable, .get_rate = pmc_main_rc_osc_get_rate, }; struct clk *pmc_register_main_rc_osc(struct pmc_data *pmc, const char *name, unsigned long freq) { struct clk *clk = NULL; struct main_rc_osc *osc = NULL; clk = clk_alloc(name, &pmc_main_rc_osc_clk_ops, NULL, 0); if (!clk) return NULL; osc = calloc(1, sizeof(*osc)); if (!osc) { clk_free(clk); return NULL; } osc->freq = freq; osc->base = pmc->base; clk->priv = osc; if (clk_register(clk)) { free(osc); clk_free(clk); return NULL; } return clk; } /* * Main Oscillator */ static bool pmc_main_osc_ready(struct pmc_data *pmc) { uint32_t status = io_read32(pmc->base + AT91_PMC_SR); return status & AT91_PMC_MOSCS; } static TEE_Result pmc_main_osc_enable(struct clk *clk) { struct pmc_data *pmc = clk->priv; uint32_t mor = io_read32(pmc->base + AT91_CKGR_MOR); mor &= ~MOR_KEY_MASK; if (mor & AT91_PMC_OSCBYPASS) return TEE_SUCCESS; if (!(mor & AT91_PMC_MOSCEN)) { mor |= AT91_PMC_MOSCEN | AT91_PMC_KEY; io_write32(pmc->base + AT91_CKGR_MOR, mor); } while (!pmc_main_osc_ready(pmc)) ; return TEE_SUCCESS; } static void pmc_main_osc_disable(struct clk *clk) { struct pmc_data *pmc = clk->priv; uint32_t mor = io_read32(pmc->base + AT91_CKGR_MOR); if (mor & AT91_PMC_OSCBYPASS) return; if (!(mor & AT91_PMC_MOSCEN)) return; mor &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); io_write32(pmc->base + AT91_CKGR_MOR, mor | AT91_PMC_KEY); } static const struct clk_ops pmc_main_osc_clk_ops = { .enable = pmc_main_osc_enable, .disable = pmc_main_osc_disable, }; struct clk *pmc_register_main_osc(struct pmc_data *pmc, const char *name, struct clk *parent, bool bypass) { struct clk *clk = NULL; clk = clk_alloc(name, &pmc_main_osc_clk_ops, &parent, 1); if (!clk) panic(); clk->priv = pmc; if (bypass) io_clrsetbits32(pmc->base + AT91_CKGR_MOR, MOR_KEY_MASK | AT91_PMC_OSCBYPASS, AT91_PMC_OSCBYPASS | AT91_PMC_KEY); if (clk_register(clk)) { clk_free(clk); return NULL; } return clk; } /* * Main Clock */ static TEE_Result clk_main_probe_frequency(vaddr_t base) { while (!(io_read32(base + AT91_CKGR_MCFR) & AT91_PMC_MAINRDY)) ; return TEE_SUCCESS; } static unsigned long clk_main_get_rate(vaddr_t base, unsigned long parent_rate) { uint32_t mcfr = 0; if (parent_rate) return parent_rate; IMSG("Main crystal frequency not set, using approximate value"); mcfr = io_read32(base + AT91_CKGR_MCFR); if (!(mcfr & AT91_PMC_MAINRDY)) return 0; return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; } static bool clk_sam9x5_main_ready(vaddr_t base) { uint32_t status = io_read32(base + AT91_PMC_SR); return status & AT91_PMC_MOSCSELS; } static TEE_Result clk_sam9x5_main_enable(struct clk *clk) { struct pmc_data *pmc = clk->priv; while (!clk_sam9x5_main_ready(pmc->base)) ; return clk_main_probe_frequency(pmc->base); } static unsigned long clk_sam9x5_main_get_rate(struct clk *clk, unsigned long parent_rate) { struct pmc_data *pmc = clk->priv; return clk_main_get_rate(pmc->base, parent_rate); } static TEE_Result clk_sam9x5_main_set_parent(struct clk *clk, size_t index) { struct pmc_data *pmc = clk->priv; uint32_t tmp = 0; if (index > 1) return TEE_ERROR_BAD_PARAMETERS; tmp = io_read32(pmc->base + AT91_CKGR_MOR); if (index && !(tmp & AT91_PMC_MOSCSEL)) tmp = AT91_PMC_MOSCSEL; else if (!index && (tmp & AT91_PMC_MOSCSEL)) tmp = 0; else return TEE_SUCCESS; io_clrsetbits32(pmc->base + AT91_CKGR_MOR, AT91_PMC_MOSCSEL | MOR_KEY_MASK, tmp | AT91_PMC_KEY); while (!clk_sam9x5_main_ready(pmc->base)) ; return TEE_SUCCESS; } static size_t clk_sam9x5_main_get_parent(struct clk *clk) { struct pmc_data *pmc = clk->priv; uint32_t status = io_read32(pmc->base + AT91_CKGR_MOR); return CLK_MAIN_PARENT_SELECT(status); } static const struct clk_ops sam9x5_main_ops = { .enable = clk_sam9x5_main_enable, .get_rate = clk_sam9x5_main_get_rate, .set_parent = clk_sam9x5_main_set_parent, .get_parent = clk_sam9x5_main_get_parent, }; struct clk * at91_clk_register_sam9x5_main(struct pmc_data *pmc, const char *name, struct clk **parent_clocks, unsigned int num_parents) { struct clk *clk = NULL; if (!name) return NULL; if (!parent_clocks || !num_parents) return NULL; clk = clk_alloc(name, &sam9x5_main_ops, parent_clocks, num_parents); if (!clk) return NULL; clk->flags = CLK_SET_PARENT_GATE; clk->priv = pmc; if (clk_register(clk)) { clk_free(clk); return NULL; } return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_master.c000066400000000000000000000164601464416617300216120ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include "at91_clk.h" #define MASTER_PRES_MASK 0x7 #define MASTER_PRES_MAX MASTER_PRES_MASK #define MASTER_DIV_SHIFT 8 #define MASTER_DIV_MASK 0x7 #define MASTER_MAX_ID 4 /* Total 5 MCK clocks for SAMA7G5 */ struct clk_master { vaddr_t base; const struct clk_master_layout *layout; const struct clk_master_charac *charac; uint32_t *mux_table; uint32_t mckr; int chg_pid; uint8_t div; uint8_t id; /* ID of MCK clocks for SAMA7G5, MCK0 ~ MCK4 */ uint8_t parent; /* the source clock for SAMA7G5 MCKx */ }; static bool clk_master_ready(struct clk_master *master) { uint32_t status = io_read32(master->base + AT91_PMC_SR); return status & AT91_PMC_MCKRDY; } static TEE_Result clk_master_enable(struct clk *clk) { struct clk_master *master = clk->priv; while (!clk_master_ready(master)) ; return TEE_SUCCESS; } static unsigned long clk_master_div_get_rate(struct clk *clk, unsigned long parent_rate) { uint8_t div = 1; uint32_t mckr = 0; unsigned long rate = parent_rate; struct clk_master *master = clk->priv; const struct clk_master_layout *layout = master->layout; const struct clk_master_charac *charac = master->charac; mckr = io_read32(master->base + master->layout->offset); mckr &= layout->mask; div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK; rate /= charac->divisors[div]; if (rate < charac->output.min) IMSG("master clk div is underclocked"); else if (rate > charac->output.max) IMSG("master clk div is overclocked"); return rate; } static const struct clk_ops master_div_ops = { .enable = clk_master_enable, .get_rate = clk_master_div_get_rate, }; static unsigned long clk_master_pres_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_master *master = clk->priv; const struct clk_master_charac *charac = master->charac; uint32_t val = 0; unsigned int pres = 0; val = io_read32(master->base + master->layout->offset); pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK; if (pres != 3 || !charac->have_div3_pres) pres = BIT(pres); return UDIV_ROUND_NEAREST(parent_rate, pres); } static size_t clk_master_pres_get_parent(struct clk *clk) { struct clk_master *master = clk->priv; uint32_t mckr = 0; mckr = io_read32(master->base + master->layout->offset); return mckr & AT91_PMC_CSS; } static const struct clk_ops master_pres_ops = { .enable = clk_master_enable, .get_rate = clk_master_pres_get_rate, .get_parent = clk_master_pres_get_parent, }; static struct clk * at91_clk_register_master_internal(struct pmc_data *pmc, const char *name, int num_parents, struct clk **parents, const struct clk_master_layout *layout, const struct clk_master_charac *charac, const struct clk_ops *ops, int chg_pid) { struct clk_master *master = NULL; struct clk *clk = NULL; if (!name || !num_parents || !parents) return NULL; clk = clk_alloc(name, ops, parents, num_parents); if (!clk) return NULL; master = calloc(1, sizeof(*master)); if (!master) { clk_free(clk); return NULL; } master->layout = layout; master->charac = charac; master->base = pmc->base; master->chg_pid = chg_pid; clk->priv = master; clk->flags = CLK_SET_RATE_GATE; if (clk_register(clk)) { clk_free(clk); free(master); return NULL; } return clk; } struct clk * at91_clk_register_master_pres(struct pmc_data *pmc, const char *name, int num_parents, struct clk **parents, const struct clk_master_layout *layout, const struct clk_master_charac *charac, int chg_pid) { return at91_clk_register_master_internal(pmc, name, num_parents, parents, layout, charac, &master_pres_ops, chg_pid); } struct clk * at91_clk_register_master_div(struct pmc_data *pmc, const char *name, struct clk *parent, const struct clk_master_layout *layout, const struct clk_master_charac *charac) { return at91_clk_register_master_internal(pmc, name, 1, &parent, layout, charac, &master_div_ops, -1); } const struct clk_master_layout at91sam9x5_master_layout = { .mask = 0x373, .pres_shift = 4, .offset = AT91_PMC_MCKR, }; static size_t clk_sama7g5_master_get_parent(struct clk *hw) { struct clk_master *master = hw->priv; size_t i = 0; for (i = 0; i < hw->num_parents; i++) if (master->mux_table[i] == master->parent) return i; panic("Can't get correct parent of clock"); } static TEE_Result clk_sama7g5_master_set_parent(struct clk *hw, size_t index) { struct clk_master *master = hw->priv; if (index >= hw->num_parents) return TEE_ERROR_BAD_PARAMETERS; master->parent = master->mux_table[index]; return TEE_SUCCESS; } static TEE_Result clk_sama7g5_master_set_rate(struct clk *hw, unsigned long rate, unsigned long parent_rate) { struct clk_master *master = hw->priv; unsigned long div = 0; div = UDIV_ROUND_NEAREST(parent_rate, rate); if (div > (1 << (MASTER_PRES_MAX - 1)) || (!IS_POWER_OF_TWO(div) && div != 3)) return TEE_ERROR_BAD_PARAMETERS; /* * Divisor Value: Select the division ratio to be applied to the * selected clock to generate the corresponding MCKx. * Value | Description * 0 | Selected clock divided by 1 * 1 | Selected clock divided by 2 * 2 | Selected clock divided by 4 * 3 | Selected clock divided by 8 * 4 | Selected clock divided by 16 * 5 | Selected clock divided by 32 * 6 | Selected clock divided by 64 * 7 | Selected clock divided by 3 */ if (div == 3) master->div = MASTER_PRES_MAX; else master->div = ffs(div) - 1; return TEE_SUCCESS; } static unsigned long clk_sama7g5_master_get_rate(struct clk *hw, unsigned long parent_rate) { struct clk_master *master = hw->priv; unsigned long rate = parent_rate >> master->div; if (master->div == 7) rate = parent_rate / 3; return rate; } static const struct clk_ops sama7g5_master_ops = { .set_rate = clk_sama7g5_master_set_rate, .get_rate = clk_sama7g5_master_get_rate, .get_parent = clk_sama7g5_master_get_parent, .set_parent = clk_sama7g5_master_set_parent, }; struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc, const char *name, int num_parents, struct clk **parent, uint32_t *mux_table, uint8_t id, int chg_pid) { struct clk_master *master = NULL; struct clk *hw = NULL; unsigned int val = 0; if (!name || !num_parents || !parent || !mux_table || id > MASTER_MAX_ID) return NULL; master = calloc(1, sizeof(*master)); if (!master) return NULL; hw = clk_alloc(name, &sama7g5_master_ops, parent, num_parents); if (!hw) { free(master); return NULL; } hw->priv = master; master->base = pmc->base; master->id = id; master->chg_pid = chg_pid; master->mux_table = mux_table; io_write32(master->base + AT91_PMC_MCR_V2, master->id); val = io_read32(master->base + AT91_PMC_MCR_V2); master->parent = (val & AT91_PMC_MCR_V2_CSS_MASK) >> AT91_PMC_MCR_V2_CSS_SHIFT; master->div = (val & AT91_PMC_MCR_V2_DIV_MASK) >> MASTER_DIV_SHIFT; if (clk_register(hw)) { clk_free(hw); free(master); return NULL; } return hw; } optee_os-4.3.0/core/drivers/clk/sam/at91_peripheral.c000066400000000000000000000104441464416617300224460ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" #define PERIPHERAL_ID_MIN 2 #define PERIPHERAL_ID_MASK 31 #define PERIPHERAL_MASK(id) BIT((id) & PERIPHERAL_ID_MASK) #define PERIPHERAL_MAX_SHIFT 3 struct clk_sam9x5_peripheral { vaddr_t base; struct clk_range range; uint32_t id; uint32_t div; const struct clk_pcr_layout *layout; bool auto_div; }; static void clk_sam9x5_peripheral_autodiv(struct clk *clk) { struct clk *parent = NULL; struct clk_sam9x5_peripheral *periph = clk->priv; unsigned long parent_rate = 0; int shift = 0; if (!periph->auto_div) return; if (periph->range.max) { parent = clk_get_parent_by_index(clk, 0); parent_rate = clk_get_rate(parent); if (!parent_rate) return; for (shift = 0; shift < PERIPHERAL_MAX_SHIFT; shift++) { if (parent_rate >> shift <= periph->range.max) break; } } periph->auto_div = false; periph->div = shift; } static TEE_Result clk_sam9x5_peripheral_enable(struct clk *clk) { struct clk_sam9x5_peripheral *periph = clk->priv; if (periph->id < PERIPHERAL_ID_MIN) return TEE_SUCCESS; io_write32(periph->base + periph->layout->offset, (periph->id & periph->layout->pid_mask)); io_clrsetbits32(periph->base + periph->layout->offset, periph->layout->div_mask | periph->layout->cmd | AT91_PMC_PCR_EN, field_prep(periph->layout->div_mask, periph->div) | periph->layout->cmd | AT91_PMC_PCR_EN); return TEE_SUCCESS; } static void clk_sam9x5_peripheral_disable(struct clk *clk) { struct clk_sam9x5_peripheral *periph = clk->priv; if (periph->id < PERIPHERAL_ID_MIN) return; io_write32(periph->base + periph->layout->offset, (periph->id & periph->layout->pid_mask)); io_clrsetbits32(periph->base + periph->layout->offset, AT91_PMC_PCR_EN | periph->layout->cmd, periph->layout->cmd); } static unsigned long clk_sam9x5_peripheral_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_sam9x5_peripheral *periph = clk->priv; uint32_t status = 0; if (periph->id < PERIPHERAL_ID_MIN) return parent_rate; io_write32(periph->base + periph->layout->offset, periph->id & periph->layout->pid_mask); status = io_read32(periph->base + periph->layout->offset); if (status & AT91_PMC_PCR_EN) { periph->div = field_get(periph->layout->div_mask, status); periph->auto_div = false; } else { clk_sam9x5_peripheral_autodiv(clk); } return parent_rate >> periph->div; } static TEE_Result clk_sam9x5_peripheral_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { unsigned int shift = 0; struct clk_sam9x5_peripheral *periph = clk->priv; if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) { if (parent_rate == rate) return TEE_SUCCESS; else return TEE_ERROR_GENERIC; } if (periph->range.max && rate > periph->range.max) return TEE_ERROR_GENERIC; for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) { if (parent_rate >> shift == rate) { periph->auto_div = false; periph->div = shift; return TEE_SUCCESS; } } return TEE_ERROR_GENERIC; } static const struct clk_ops sam9x5_peripheral_ops = { .enable = clk_sam9x5_peripheral_enable, .disable = clk_sam9x5_peripheral_disable, .get_rate = clk_sam9x5_peripheral_get_rate, .set_rate = clk_sam9x5_peripheral_set_rate, }; struct clk * at91_clk_register_sam9x5_periph(struct pmc_data *pmc, const struct clk_pcr_layout *layout, const char *name, struct clk *parent, uint32_t id, const struct clk_range *range) { struct clk_sam9x5_peripheral *periph = NULL; struct clk *clk = NULL; if (!name || !parent) return NULL; clk = clk_alloc(name, &sam9x5_peripheral_ops, &parent, 1); if (!clk) return NULL; periph = calloc(1, sizeof(*periph)); if (!periph) { clk_free(clk); return NULL; } periph->id = id; periph->div = 0; periph->base = pmc->base; if (layout->div_mask) periph->auto_div = true; periph->layout = layout; periph->range = *range; clk->priv = periph; if (clk_register(clk)) { clk_free(clk); free(periph); return 0; } clk_sam9x5_peripheral_autodiv(clk); pmc_register_id(id); return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_pll.c000066400000000000000000000161401464416617300211010ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include #include "at91_clk.h" #define PLL_STATUS_MASK(id) BIT(1 + (id)) #define PLL_REG(id) (AT91_CKGR_PLLAR + ((id) * 4)) #define PLL_DIV_MASK 0xff #define PLL_DIV_MAX PLL_DIV_MASK #define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) #define PLL_MUL(reg, layout) \ ({ \ typeof(layout) __layout = layout; \ \ (((reg) >> (__layout)->mul_shift) & (__layout)->mul_mask); \ }) #define PLL_MUL_MIN 2 #define PLL_MUL_MASK(layout) ((layout)->mul_mask) #define PLL_MUL_MAX(layout) (PLL_MUL_MASK(layout) + 1) #define PLL_ICPR_SHIFT(id) ((id) * 16) #define PLL_ICPR_MASK(id) (0xffff << PLL_ICPR_SHIFT(id)) #define PLL_MAX_COUNT 0x3f #define PLL_COUNT_SHIFT 8 #define PLL_OUT_SHIFT 14 #define PLL_MAX_ID 1 struct clk_pll { vaddr_t base; uint8_t id; uint8_t div; uint8_t range; uint16_t mul; const struct clk_pll_layout *layout; const struct clk_pll_charac *charac; }; static bool clk_pll_ready(vaddr_t base, int id) { unsigned int status = io_read32(base + AT91_PMC_SR); return status & PLL_STATUS_MASK(id); } static TEE_Result clk_pll_enable(struct clk *clk) { struct clk_pll *pll = clk->priv; const struct clk_pll_layout *layout = pll->layout; const struct clk_pll_charac *charac = pll->charac; uint8_t id = pll->id; uint32_t mask = PLL_STATUS_MASK(id); int offset = PLL_REG(id); uint8_t out = 0; unsigned int pllr = 0; unsigned int status = 0; uint8_t div = 0; uint16_t mul = 0; pllr = io_read32(pll->base + offset); div = PLL_DIV(pllr); mul = PLL_MUL(pllr, layout); status = io_read32(pll->base + AT91_PMC_SR); if ((status & mask) && (div == pll->div && mul == pll->mul)) return TEE_SUCCESS; if (charac->out) out = charac->out[pll->range]; if (charac->icpll) io_clrsetbits32(pll->base + AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), charac->icpll[pll->range] << PLL_ICPR_SHIFT(id)); io_clrsetbits32(pll->base + offset, layout->pllr_mask, pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | (out << PLL_OUT_SHIFT) | ((pll->mul & layout->mul_mask) << layout->mul_shift)); while (!clk_pll_ready(pll->base, pll->id)) ; return TEE_SUCCESS; } static void clk_pll_disable(struct clk *clk) { struct clk_pll *pll = clk->priv; unsigned int mask = pll->layout->pllr_mask; io_clrsetbits32(pll->base + PLL_REG(pll->id), mask, ~mask); } static unsigned long clk_pll_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_pll *pll = clk->priv; if (!pll->div || !pll->mul) return 0; return (parent_rate / pll->div) * (pll->mul + 1); } static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, unsigned long parent_rate, uint32_t *div, uint32_t *mul, uint32_t *index) { const struct clk_pll_layout *layout = pll->layout; const struct clk_pll_charac *charac = pll->charac; unsigned long bestremainder = ULONG_MAX; unsigned long maxdiv = 1; unsigned long mindiv = 1; unsigned long tmpdiv = 1; long bestrate = -1; unsigned long bestdiv = 0; unsigned long bestmul = 0; int i = 0; /* Check if parent_rate is a valid input rate */ if (parent_rate < charac->input.min) return -1; /* * Calculate minimum divider based on the minimum multiplier, the * parent_rate and the requested rate. * Should always be 2 according to the input and output charac * of the PLL blocks. */ mindiv = (parent_rate * PLL_MUL_MIN) / rate; if (!mindiv) mindiv = 1; if (parent_rate > charac->input.max) { tmpdiv = DIV_ROUND_UP(parent_rate, charac->input.max); if (tmpdiv > PLL_DIV_MAX) return -1; if (tmpdiv > mindiv) mindiv = tmpdiv; } /* * Calculate the maximum divider which is limited by PLL register * layout (limited by the MUL or DIV field size). */ maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX(layout), rate); if (maxdiv > PLL_DIV_MAX) maxdiv = PLL_DIV_MAX; /* * Iterate over the acceptable divider values to find the best * divider/multiplier pair (the one that generates the closest * rate to the requested one). */ for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) { unsigned long remainder = 0; unsigned long tmprate = 0; unsigned long tmpmul = 0; /* * Calculate the multiplier associated with the current * divider that provide the closest rate to the requested one. */ tmpmul = UDIV_ROUND_NEAREST(rate, parent_rate / tmpdiv); tmprate = (parent_rate / tmpdiv) * tmpmul; if (tmprate > rate) remainder = tmprate - rate; else remainder = rate - tmprate; /* * Compare the remainder with the best remainder found until * now and elect a new best multiplier/divider pair if the * current remainder is smaller than the best one. */ if (remainder < bestremainder) { bestremainder = remainder; bestdiv = tmpdiv; bestmul = tmpmul; bestrate = tmprate; } /* * We've found a perfect match! * Stop searching now and use this multiplier/divider pair. */ if (!remainder) break; } /* We haven't found any multiplier/divider pair => return -ERANGE */ if (bestrate < 0) return bestrate; /* Check if bestrate is a valid output rate */ for (i = 0; i < charac->num_output; i++) { if (bestrate >= (long)charac->output[i].min && bestrate <= (long)charac->output[i].max) break; } if (i >= charac->num_output) return -1; if (div) *div = bestdiv; if (mul) *mul = bestmul - 1; if (index) *index = i; return bestrate; } static TEE_Result clk_pll_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_pll *pll = clk->priv; long ret = -1; uint32_t div = 1; uint32_t mul = 0; uint32_t index = 0; ret = clk_pll_get_best_div_mul(pll, rate, parent_rate, &div, &mul, &index); if (ret < 0) return TEE_ERROR_BAD_PARAMETERS; pll->range = index; pll->div = div; pll->mul = mul; return TEE_SUCCESS; } static const struct clk_ops pll_ops = { .enable = clk_pll_enable, .disable = clk_pll_disable, .get_rate = clk_pll_get_rate, .set_rate = clk_pll_set_rate, }; struct clk * at91_clk_register_pll(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id, const struct clk_pll_layout *layout, const struct clk_pll_charac *charac) { struct clk *clk = NULL; struct clk_pll *pll = NULL; int offset = PLL_REG(id); uint32_t pllr = 0; if (!name || !parent) return NULL; clk = clk_alloc(name, &pll_ops, &parent, 1); if (!clk) return NULL; if (id > PLL_MAX_ID) return NULL; pll = calloc(1, sizeof(*pll)); if (!pll) { clk_free(clk); return NULL; } pll->id = id; pll->layout = layout; pll->charac = charac; pll->base = pmc->base; pllr = io_read32(pmc->base + offset); pll->div = PLL_DIV(pllr); pll->mul = PLL_MUL(pllr, layout); clk->flags = CLK_SET_RATE_GATE; clk->priv = pll; if (clk_register(clk)) { clk_free(clk); free(pll); return NULL; } return clk; } const struct clk_pll_layout sama5d3_pll_layout = { .pllr_mask = 0x1FFFFFF, .mul_shift = 18, .mul_mask = 0x7F, }; optee_os-4.3.0/core/drivers/clk/sam/at91_plldiv.c000066400000000000000000000025621464416617300216070ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" static unsigned long clk_plldiv_get_rate(struct clk *clk, unsigned long parent_rate) { struct pmc_data *pmc = clk->priv; unsigned int mckr = io_read32(pmc->base + AT91_PMC_MCKR); if (mckr & AT91_PMC_PLLADIV2) return parent_rate / 2; return parent_rate; } static TEE_Result clk_plldiv_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct pmc_data *pmc = clk->priv; if (parent_rate != rate && (parent_rate / 2 != rate)) return TEE_ERROR_GENERIC; io_clrsetbits32(pmc->base + AT91_PMC_MCKR, AT91_PMC_PLLADIV2, parent_rate != rate ? AT91_PMC_PLLADIV2 : 0); return TEE_SUCCESS; } static const struct clk_ops plldiv_ops = { .get_rate = clk_plldiv_get_rate, .set_rate = clk_plldiv_set_rate, }; struct clk * at91_clk_register_plldiv(struct pmc_data *pmc, const char *name, struct clk *parent) { struct clk *clk = NULL; clk = clk_alloc(name, &plldiv_ops, &parent, 1); if (!clk) return NULL; clk->priv = pmc; clk->flags = CLK_SET_RATE_GATE; if (clk_register(clk)) { clk_free(clk); return NULL; } return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_pmc.c000066400000000000000000000152441464416617300210750ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include #include #include #include "at91_clk.h" #define PMC_MAX_IDS 128 #define PMC_MAX_PCKS 8 static struct clk *pmc_clk_get_by_id(struct pmc_clk *clks, unsigned int nclk, unsigned int id) { unsigned int i = 0; for (i = 0; i < nclk; i++) { if (clks[i].clk && clks[i].id == id) return clks[i].clk; } return NULL; } struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk, const char *name) { unsigned int i = 0; for (i = 0; i < nclk; i++) if (clks[i].clk && strcmp(clks[i].clk->name, name) == 0) return clks[i].clk; return NULL; } TEE_Result pmc_clk_get(struct pmc_data *pmc, unsigned int type, unsigned int idx, struct clk **clk) { unsigned int nclk = 0; struct pmc_clk *clks = NULL; switch (type) { case PMC_TYPE_CORE: nclk = pmc->ncore; clks = pmc->chws; break; case PMC_TYPE_SYSTEM: nclk = pmc->nsystem; clks = pmc->shws; break; case PMC_TYPE_PERIPHERAL: nclk = pmc->nperiph; clks = pmc->phws; break; case PMC_TYPE_GCK: nclk = pmc->ngck; clks = pmc->ghws; break; case PMC_TYPE_PROGRAMMABLE: nclk = pmc->npck; clks = pmc->pchws; break; default: return TEE_ERROR_BAD_PARAMETERS; } *clk = pmc_clk_get_by_id(clks, nclk, idx); if (!*clk) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } TEE_Result clk_dt_pmc_get(struct dt_pargs *clkspec, void *data, struct clk **out_clk) { unsigned int type = clkspec->args[0]; unsigned int idx = clkspec->args[1]; struct pmc_data *pmc_data = data; if (clkspec->args_count != 2) return TEE_ERROR_BAD_PARAMETERS; return pmc_clk_get(pmc_data, type, idx, out_clk); } struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem, unsigned int nperiph, unsigned int ngck, unsigned int npck) { unsigned int num_clks = ncore + nsystem + nperiph + ngck + npck; unsigned int alloc_size = sizeof(struct pmc_data) + num_clks * sizeof(struct pmc_clk); struct pmc_data *pmc_data = NULL; pmc_data = calloc(1, alloc_size); if (!pmc_data) return NULL; pmc_data->ncore = ncore; pmc_data->chws = pmc_data->hwtable; pmc_data->nsystem = nsystem; pmc_data->shws = pmc_data->chws + ncore; pmc_data->nperiph = nperiph; pmc_data->phws = pmc_data->shws + nsystem; pmc_data->ngck = ngck; pmc_data->ghws = pmc_data->phws + nperiph; pmc_data->npck = npck; pmc_data->pchws = pmc_data->ghws + ngck; return pmc_data; } #ifdef CFG_PM_ARM32 static uint8_t registered_ids[PMC_MAX_IDS]; static uint8_t registered_pcks[PMC_MAX_PCKS]; static struct { uint32_t scsr; uint32_t pcsr0; uint32_t uckr; uint32_t mor; uint32_t mcfr; uint32_t pllar; uint32_t mckr; uint32_t usb; uint32_t imr; uint32_t pcsr1; uint32_t pcr[PMC_MAX_IDS]; uint32_t audio_pll0; uint32_t audio_pll1; uint32_t pckr[PMC_MAX_PCKS]; } pmc_cache; /* * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored * without alteration in the table, and 0 is for unused clocks. */ void pmc_register_id(uint8_t id) { int i = 0; for (i = 0; i < PMC_MAX_IDS; i++) { if (registered_ids[i] == 0) { registered_ids[i] = id; return; } if (registered_ids[i] == id) return; } panic("Invalid clock ID"); } /* * As Programmable Clock 0 is valid on AT91 chips, there is an offset * of 1 between the stored value and the real clock ID. */ void pmc_register_pck(uint8_t pck) { int i = 0; for (i = 0; i < PMC_MAX_PCKS; i++) { if (registered_pcks[i] == 0) { registered_pcks[i] = pck + 1; return; } if (registered_pcks[i] == pck + 1) return; } panic("Invalid clock ID"); } static void pmc_suspend(void) { int i = 0; uint8_t num = 0; vaddr_t pmc_base = at91_pmc_get_base(); pmc_cache.scsr = io_read32(pmc_base + AT91_PMC_SCSR); pmc_cache.pcsr0 = io_read32(pmc_base + AT91_PMC_PCSR); pmc_cache.uckr = io_read32(pmc_base + AT91_CKGR_UCKR); pmc_cache.mor = io_read32(pmc_base + AT91_CKGR_MOR); pmc_cache.mcfr = io_read32(pmc_base + AT91_CKGR_MCFR); pmc_cache.pllar = io_read32(pmc_base + AT91_CKGR_PLLAR); pmc_cache.mckr = io_read32(pmc_base + AT91_PMC_MCKR); pmc_cache.usb = io_read32(pmc_base + AT91_PMC_USB); pmc_cache.imr = io_read32(pmc_base + AT91_PMC_IMR); pmc_cache.pcsr1 = io_read32(pmc_base + AT91_PMC_PCSR1); for (i = 0; registered_ids[i]; i++) { io_write32(pmc_base + AT91_PMC_PCR, registered_ids[i] & AT91_PMC_PCR_PID_MASK); pmc_cache.pcr[registered_ids[i]] = io_read32(pmc_base + AT91_PMC_PCR); } for (i = 0; registered_pcks[i]; i++) { num = registered_pcks[i] - 1; pmc_cache.pckr[num] = io_read32(pmc_base + AT91_PMC_PCKR(num)); } } static bool pmc_ready(vaddr_t pmc_base, unsigned int mask) { uint32_t status = 0; status = io_read32(pmc_base + AT91_PMC_SR); return (status & mask) == mask; } static void pmc_resume(void) { int i = 0; uint8_t num = 0; uint32_t tmp = 0; vaddr_t pmc_base = at91_pmc_get_base(); uint32_t mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA; tmp = io_read32(pmc_base + AT91_PMC_MCKR); if (pmc_cache.mckr != tmp) panic("MCKR was not configured properly by the previous bootstage"); tmp = io_read32(pmc_base + AT91_CKGR_PLLAR); if (pmc_cache.pllar != tmp) panic("PLLAR was not configured properly by the previous bootstage"); io_write32(pmc_base + AT91_PMC_SCER, pmc_cache.scsr); io_write32(pmc_base + AT91_PMC_PCER, pmc_cache.pcsr0); io_write32(pmc_base + AT91_CKGR_UCKR, pmc_cache.uckr); io_write32(pmc_base + AT91_CKGR_MOR, pmc_cache.mor); io_write32(pmc_base + AT91_CKGR_MCFR, pmc_cache.mcfr); io_write32(pmc_base + AT91_PMC_USB, pmc_cache.usb); io_write32(pmc_base + AT91_PMC_IMR, pmc_cache.imr); io_write32(pmc_base + AT91_PMC_PCER1, pmc_cache.pcsr1); for (i = 0; registered_ids[i]; i++) { io_write32(pmc_base + AT91_PMC_PCR, pmc_cache.pcr[registered_ids[i]] | AT91_PMC_PCR_CMD); } for (i = 0; registered_pcks[i]; i++) { num = registered_pcks[i] - 1; io_write32(pmc_base + AT91_PMC_PCKR(num), pmc_cache.pckr[num]); } if (pmc_cache.uckr & AT91_PMC_UPLLEN) mask |= AT91_PMC_LOCKU; while (!pmc_ready(pmc_base, mask)) ; } static TEE_Result pmc_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl __unused) { switch (op) { case PM_OP_RESUME: pmc_resume(); break; case PM_OP_SUSPEND: pmc_suspend(); break; default: panic("Invalid PM operation"); } return TEE_SUCCESS; } void pmc_register_pm(void) { /* * We register the clock as a core service since clocks must be * re-enable prior to accessing devices */ register_pm_core_service_cb(pmc_pm, NULL, "pmc"); } #endif optee_os-4.3.0/core/drivers/clk/sam/at91_pmc.h000066400000000000000000000244521464416617300211030ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ /* * Copyright (C) 2005 Ivan Kokshaysky * Copyright (C) SAN People * * Power Management Controller (PMC) - System peripherals registers. * Based on AT91RM9200 datasheet revision E. */ #ifndef DRIVERS_CLK_SAM_AT91_PM_H #define DRIVERS_CLK_SAM_AT91_PM_H #include #define AT91_PMC_V1 (1) #define AT91_PMC_V2 (2) #define AT91_PMC_SCER 0x00 #define AT91_PMC_SCDR 0x04 #define AT91_PMC_SCSR 0x08 #define AT91_PMC_PCK BIT(0) #define AT91RM9200_PMC_UDP BIT(1) #define AT91RM9200_PMC_MCKUDP BIT(2) #define AT91RM9200_PMC_UHP BIT(4) #define AT91SAM926x_PMC_UHP BIT(6) #define AT91SAM926x_PMC_UDP BIT(7) #define AT91_PMC_PCK0 BIT(8) #define AT91_PMC_PCK1 BIT(9) #define AT91_PMC_PCK2 BIT(10) #define AT91_PMC_PCK3 BIT(11) #define AT91_PMC_PCK4 BIT(12) #define AT91_PMC_HCK0 BIT(16) #define AT91_PMC_HCK1 BIT(17) #ifdef CFG_SAMA7G5 #define AT91_PMC_PCK_COUNT 8 #else #define AT91_PMC_PCK_COUNT 4 #endif #define AT91_PMC_PLL_CTRL0 0x0C #define AT91_PMC_PLL_CTRL0_ENPLL BIT(28) #define AT91_PMC_PLL_CTRL0_ENPLLCK BIT(29) #define AT91_PMC_PLL_CTRL0_ENLOCK BIT(31) #define AT91_PMC_PLL_CTRL1 0x10 #define AT91_PMC_PCER 0x10 #define AT91_PMC_PCDR 0x14 #define AT91_PMC_PCSR 0x18 #define AT91_PMC_PLL_ACR 0x18 #define AT91_PMC_PLL_ACR_DEFAULT_UPLL 0x12020010UL #define AT91_PMC_PLL_ACR_DEFAULT_PLLA 0x00020010UL #define AT91_PMC_PLL_ACR_UTMIVR BIT(12) #define AT91_PMC_PLL_ACR_UTMIBG BIT(13) #define AT91_CKGR_UCKR 0x1C #define AT91_PMC_UPLLEN BIT(16) #define AT91_PMC_UPLLCOUNT (0xf << 20) #define AT91_PMC_BIASEN BIT(24) #define AT91_PMC_BIASCOUNT (0xf << 28) #define AT91_PMC_PLL_UPDT 0x1C #define AT91_PMC_PLL_UPDT_UPDATE BIT(8) #define AT91_PMC_PLL_UPDT_ID BIT(0) #define AT91_PMC_PLL_UPDT_ID_MASK GENMASK_32(3, 0) #define AT91_PMC_PLL_UPDT_STUPTIM (0xff << 16) #define AT91_CKGR_MOR 0x20 #define AT91_PMC_MOSCEN BIT(0) #define AT91_PMC_OSCBYPASS BIT(1) #define AT91_PMC_WAITMODE BIT(2) #define AT91_PMC_MOSCRCEN BIT(3) #define AT91_PMC_OSCOUNT (0xff << 8) #define AT91_PMC_KEY_MASK (0xff << 16) #define AT91_PMC_KEY (0x37 << 16) #define AT91_PMC_MOSCSEL BIT(24) #define AT91_PMC_CFDEN BIT(25) #define AT91_CKGR_MCFR 0x24 #define AT91_PMC_MAINF (0xffff << 0) #define AT91_PMC_MAINRDY BIT(16) #define AT91_CKGR_PLLAR 0x28 #define AT91_CKGR_PLLBR 0x2c #define AT91_PMC_DIV (0xff << 0) #define AT91_PMC_PLLCOUNT (0x3f << 8) #define AT91_PMC_OUT (3 << 14) #define AT91_PMC_MUL (0x7ff << 16) #define AT91_PMC_MUL_GET(n) ((n) >> 16 & 0x7ff) #define AT91_PMC3_MUL (0x7f << 18) #define AT91_PMC3_MUL_GET(n) ((n) >> 18 & 0x7f) #define AT91_PMC_USBDIV (3 << 28) #define AT91_PMC_USBDIV_1 (0 << 28) #define AT91_PMC_USBDIV_2 BIT(28) #define AT91_PMC_USBDIV_4 (2 << 28) #define AT91_PMC_USB96M BIT(28) #define AT91_PMC_CPU_CKR 0x28 #ifdef CFG_SAMA7G5 #define AT91_PMC_MCKR 0x28 #else #define AT91_PMC_MCKR 0x30 #endif #define AT91_PMC_CSS (3 << 0) #define AT91_PMC_CSS_SLOW (0 << 0) #define AT91_PMC_CSS_MAIN BIT(0) #define AT91_PMC_CSS_PLLA (2 << 0) #define AT91_PMC_CSS_PLLB (3 << 0) #define AT91_PMC_CSS_UPLL (3 << 0) #define PMC_PRES_OFFSET 2 #define AT91_PMC_PRES (7 << PMC_PRES_OFFSET) #define AT91_PMC_PRES_1 (0 << PMC_PRES_OFFSET) #define AT91_PMC_PRES_2 BIT(PMC_PRES_OFFSET) #define AT91_PMC_PRES_4 (2 << PMC_PRES_OFFSET) #define AT91_PMC_PRES_8 (3 << PMC_PRES_OFFSET) #define AT91_PMC_PRES_16 (4 << PMC_PRES_OFFSET) #define AT91_PMC_PRES_32 (5 << PMC_PRES_OFFSET) #define AT91_PMC_PRES_64 (6 << PMC_PRES_OFFSET) #define PMC_ALT_PRES_OFFSET 4 #define AT91_PMC_ALT_PRES (7 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_1 (0 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_2 BIT(PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_4 (2 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_8 (3 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_16 (4 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_32 (5 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_ALT_PRES_64 (6 << PMC_ALT_PRES_OFFSET) #define AT91_PMC_MDIV (3 << 8) #define AT91RM9200_PMC_MDIV_1 (0 << 8) #define AT91RM9200_PMC_MDIV_2 BIT(8) #define AT91RM9200_PMC_MDIV_3 (2 << 8) #define AT91RM9200_PMC_MDIV_4 (3 << 8) #define AT91SAM9_PMC_MDIV_1 (0 << 8) #define AT91SAM9_PMC_MDIV_2 BIT(8) #define AT91SAM9_PMC_MDIV_4 (2 << 8) #define AT91SAM9_PMC_MDIV_6 (3 << 8) #define AT91SAM9_PMC_MDIV_3 (3 << 8) #define AT91_PMC_PDIV BIT(12) #define AT91_PMC_PDIV_1 (0 << 12) #define AT91_PMC_PDIV_2 BIT(12) #define AT91_PMC_PLLADIV2 BIT(12) #define AT91_PMC_PLLADIV2_OFF (0 << 12) #define AT91_PMC_PLLADIV2_ON BIT(12) #define AT91_PMC_H32MXDIV BIT(24) /* definitions for the PMC register of SAMA7G5 */ #define AT91_PMC_MCR_V2 0x30 #define AT91_PMC_MCR_V2_ID_MASK GENMASK_32(3, 0) #define AT91_PMC_MCR_V2_ID(_id) ((_id) & AT91_PMC_MCR_V2_ID_MASK) #define AT91_PMC_MCR_V2_CMD BIT(7) #define AT91_PMC_MCR_V2_DIV_MASK GENMASK_32(10, 8) #define AT91_PMC_MCR_V2_DIV1 SHIFT_U32(0, 8) #define AT91_PMC_MCR_V2_DIV2 SHIFT_U32(1, 8) #define AT91_PMC_MCR_V2_DIV4 SHIFT_U32(2, 8) #define AT91_PMC_MCR_V2_DIV8 SHIFT_U32(3, 8) #define AT91_PMC_MCR_V2_DIV16 SHIFT_U32(4, 8) #define AT91_PMC_MCR_V2_DIV32 SHIFT_U32(5, 8) #define AT91_PMC_MCR_V2_DIV64 SHIFT_U32(6, 8) #define AT91_PMC_MCR_V2_DIV3 SHIFT_U32(7, 8) #define AT91_PMC_MCR_V2_CSS_SHIFT 16 #define AT91_PMC_MCR_V2_CSS_MASK GENMASK_32(20, 16) #define AT91_PMC_MCR_V2_CSS_MD_SLCK SHIFT_U32(0, 16) #define AT91_PMC_MCR_V2_CSS_TD_SLCK SHIFT_U32(1, 16) #define AT91_PMC_MCR_V2_CSS_MAINCK SHIFT_U32(2, 16) #define AT91_PMC_MCR_V2_CSS_MCK0 SHIFT_U32(3, 16) #define AT91_PMC_MCR_V2_CSS_SYSPLL SHIFT_U32(5, 16) #define AT91_PMC_MCR_V2_CSS_DDRPLL SHIFT_U32(6, 16) #define AT91_PMC_MCR_V2_CSS_IMGPLL SHIFT_U32(7, 16) #define AT91_PMC_MCR_V2_CSS_BAUDPLL SHIFT_U32(8, 16) #define AT91_PMC_MCR_V2_CSS_AUDIOPLL SHIFT_U32(9, 16) #define AT91_PMC_MCR_V2_CSS_ETHPLL SHIFT_U32(10, 16) #define AT91_PMC_MCR_V2_EN BIT(28) #define AT91_PMC_XTALF 0x34 #define AT91_PMC_XTALF_XTALF 7 #define AT91_PMC_USB 0x38 #define AT91_PMC_USBS (0x1 << 0) #define AT91_PMC_USBS_PLLA (0 << 0) #define AT91_PMC_USBS_UPLL BIT(0) #define AT91_PMC_USBS_PLLB BIT(0) #define AT91_PMC_OHCIUSBDIV (0xF << 8) #define AT91_PMC_OHCIUSBDIV_1 (0x0 << 8) #define AT91_PMC_OHCIUSBDIV_2 (0x1 << 8) #define AT91_PMC_SMD 0x3c #define AT91_PMC_SMDS (0x1 << 0) #define AT91_PMC_SMD_DIV (0x1f << 8) #define AT91_PMC_SMDDIV(n) (((n) << 8) & AT91_PMC_SMD_DIV) #define AT91_PMC_PCKR(n) (0x40 + ((n) * 4)) #define AT91_PMC_ALT_PCKR_CSS (0x7 << 0) #define AT91_PMC_CSS_MASTER (4 << 0) #define AT91_PMC_CSSMCK (0x1 << 8) #define AT91_PMC_CSSMCK_CSS (0 << 8) #define AT91_PMC_CSSMCK_MCK BIT(8) #define AT91_PMC_IER 0x60 #define AT91_PMC_IDR 0x64 #define AT91_PMC_SR 0x68 #define AT91_PMC_MOSCS BIT(0) #define AT91_PMC_LOCKA BIT(1) #define AT91_PMC_LOCKB BIT(2) #define AT91_PMC_MCKRDY BIT(3) #define AT91_PMC_LOCKU BIT(6) #define AT91_PMC_OSCSEL BIT(7) #define AT91_PMC_PCK0RDY BIT(8) #define AT91_PMC_PCK1RDY BIT(9) #define AT91_PMC_PCK2RDY BIT(10) #define AT91_PMC_PCK3RDY BIT(11) #define AT91_PMC_MOSCSELS BIT(16) #define AT91_PMC_MOSCRCS BIT(17) #define AT91_PMC_CFDEV BIT(18) #define AT91_PMC_GCKRDY BIT(24) #define AT91_PMC_MCKXRDY BIT(26) #define AT91_PMC_IMR 0x6c #define AT91_PMC_FSMR 0x70 #define AT91_PMC_FSTT(n) BIT(n) #define AT91_PMC_RTTAL BIT(16) #define AT91_PMC_RTCAL BIT(17) #define AT91_PMC_USBAL BIT(18) #define AT91_PMC_SDMMC_CD BIT(19) #define AT91_PMC_LPM BIT(20) #define AT91_PMC_RXLP_MCE BIT(24) #define AT91_PMC_ACC_CE BIT(25) #define AT91_PMC_FSPR 0x74 #define AT91_PMC_FS_INPUT_MASK 0x7ff #define AT91_PMC_PLLICPR 0x80 #define AT91_PMC_PROT 0xe4 #define AT91_PMC_WPEN (0x1 << 0) #define AT91_PMC_WPKEY (0xffffff << 8) #define AT91_PMC_PROTKEY (0x504d43 << 8) #define AT91_PMC_WPSR 0xe8 #define AT91_PMC_WPVS (0x1 << 0) #define AT91_PMC_WPVSRC (0xffff << 8) #define AT91_PMC_PLL_ISR0 0xEC #define AT91_PMC_PCER1 0x100 #define AT91_PMC_PCDR1 0x104 #define AT91_PMC_PCSR1 0x108 #define AT91_PMC_PCR 0x10c #define AT91_PMC_PCR_PID_MASK 0x3f #define AT91_PMC_PCR_CMD (0x1 << 12) #define AT91_PMC_PCR_GCKDIV_SHIFT 20 #define AT91_PMC_PCR_GCKDIV_MASK \ GENMASK_32(27, AT91_PMC_PCR_GCKDIV_SHIFT) #define AT91_PMC_PCR_EN (0x1 << 28) #define AT91_PMC_PCR_GCKEN (0x1 << 29) #define AT91_PMC_AUDIO_PLL0 0x14c #define AT91_PMC_AUDIO_PLL_PLLEN BIT(0) #define AT91_PMC_AUDIO_PLL_PADEN BIT(1) #define AT91_PMC_AUDIO_PLL_PMCEN BIT(2) #define AT91_PMC_AUDIO_PLL_RESETN BIT(3) #define AT91_PMC_AUDIO_PLL_ND_OFFSET 8 #define AT91_PMC_AUDIO_PLL_ND_MASK \ (0x7f << AT91_PMC_AUDIO_PLL_ND_OFFSET) #define AT91_PMC_AUDIO_PLL_ND(n) \ SHIFT_U32(n, AT91_PMC_AUDIO_PLL_ND_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPMC_OFFSET 16 #define AT91_PMC_AUDIO_PLL_QDPMC_MASK \ (0x7f << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPMC(n) \ SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) #define AT91_PMC_AUDIO_PLL1 0x150 #define AT91_PMC_AUDIO_PLL_FRACR_MASK 0x3fffff #define AT91_PMC_AUDIO_PLL_QDPAD_OFFSET 24 #define AT91_PMC_AUDIO_PLL_QDPAD_MASK \ (0x7f << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPAD(n) \ SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET \ AT91_PMC_AUDIO_PLL_QDPAD_OFFSET #define AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK \ (0x3 << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPAD_DIV(n) \ SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET 26 #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX 0x1f #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK \ (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX << \ AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) #define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(n) \ SHIFT_U32(n, AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) #endif optee_os-4.3.0/core/drivers/clk/sam/at91_programmable.c000066400000000000000000000075451464416617300227730ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" #define PROG_ID_MAX 7 #define PROG_STATUS_MASK(id) (1 << ((id) + 8)) #define PROG_PRES(layout, pckr) \ ({ \ typeof(layout) __layout = layout; \ \ (((pckr) >> (__layout)->pres_shift) & (__layout)->pres_mask); \ }) #define PROG_MAX_RM9200_CSS 3 struct clk_programmable { vaddr_t base; uint8_t id; const struct clk_programmable_layout *layout; }; static unsigned long clk_programmable_get_rate(struct clk *clk, unsigned long parent_rate) { struct clk_programmable *prog = clk->priv; const struct clk_programmable_layout *layout = prog->layout; unsigned int pckr = io_read32(prog->base + AT91_PMC_PCKR(prog->id)); unsigned long rate = 0; if (layout->is_pres_direct) rate = parent_rate / (PROG_PRES(layout, pckr) + 1); else rate = parent_rate >> PROG_PRES(layout, pckr); return rate; } static TEE_Result clk_programmable_set_parent(struct clk *clk, size_t index) { struct clk_programmable *prog = clk->priv; const struct clk_programmable_layout *layout = prog->layout; unsigned int mask = layout->css_mask; unsigned int pckr = index; if (layout->have_slck_mck) mask |= AT91_PMC_CSSMCK_MCK; if (index > layout->css_mask) { if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck) return TEE_ERROR_BAD_PARAMETERS; pckr |= AT91_PMC_CSSMCK_MCK; } io_clrsetbits32(prog->base + AT91_PMC_PCKR(prog->id), mask, pckr); return TEE_SUCCESS; } static size_t clk_programmable_get_parent(struct clk *clk) { struct clk_programmable *prog = clk->priv; const struct clk_programmable_layout *layout = prog->layout; unsigned int pckr = io_read32(prog->base + AT91_PMC_PCKR(prog->id)); size_t ret = 0; ret = pckr & layout->css_mask; if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret) ret = PROG_MAX_RM9200_CSS + 1; return ret; } static unsigned int flsi(unsigned int val) { if (val == 0) return 0; return sizeof(unsigned int) * 8 - __builtin_clz(val); } static TEE_Result clk_programmable_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct clk_programmable *prog = clk->priv; const struct clk_programmable_layout *layout = prog->layout; unsigned long div = parent_rate / rate; int shift = 0; if (!div) return TEE_ERROR_BAD_PARAMETERS; if (layout->is_pres_direct) { shift = div - 1; if (shift > layout->pres_mask) return TEE_ERROR_BAD_PARAMETERS; } else { shift = flsi(div) - 1; if (div != (1ULL << shift)) return TEE_ERROR_BAD_PARAMETERS; if (shift >= layout->pres_mask) return TEE_ERROR_BAD_PARAMETERS; } io_clrsetbits32(prog->base + AT91_PMC_PCKR(prog->id), layout->pres_mask << layout->pres_shift, shift << layout->pres_shift); return TEE_SUCCESS; } static const struct clk_ops programmable_ops = { .get_rate = clk_programmable_get_rate, .get_parent = clk_programmable_get_parent, .set_parent = clk_programmable_set_parent, .set_rate = clk_programmable_set_rate, }; struct clk * at91_clk_register_programmable(struct pmc_data *pmc, const char *name, struct clk **parents, uint8_t num_parents, uint8_t id, const struct clk_programmable_layout *layout) { struct clk_programmable *prog = NULL; struct clk *clk = NULL; assert(id <= PROG_ID_MAX); clk = clk_alloc(name, &programmable_ops, parents, num_parents); prog = calloc(1, sizeof(*prog)); if (!prog || !clk) return NULL; prog->id = id; prog->layout = layout; prog->base = pmc->base; clk->priv = prog; clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; if (clk_register(clk)) { clk_free(clk); free(prog); return NULL; } pmc_register_pck(id); return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_sckc.c000066400000000000000000000026071464416617300212400ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include "at91_clk.h" #include #include static struct clk *slow_clk; #define SLOW_CLOCK_FREQ 32768 struct clk *at91_sckc_clk_get(void) { return slow_clk; } static unsigned long sckc_get_rate(struct clk *clk __unused, unsigned long parent_rate __unused) { return SLOW_CLOCK_FREQ; } static const struct clk_ops sckc_clk_ops = { .get_rate = sckc_get_rate, }; static TEE_Result sckc_pmc_setup(const void *fdt __unused, int offs, const void *data __unused) { struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; if (slow_clk) return TEE_ERROR_GENERIC; clk = clk_alloc("slowck", &sckc_clk_ops, NULL, 0); if (!clk) return TEE_ERROR_OUT_OF_MEMORY; res = clk_register(clk); if (res) { clk_free(clk); return res; } res = clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk, clk); if (res) return res; slow_clk = clk; return TEE_SUCCESS; } static const struct dt_device_match at91_sckc_match_table[] = { { .compatible = "atmel,sama5d4-sckc" }, { .compatible = "microchip,sama7g5-sckc" }, { } }; DEFINE_DT_DRIVER(at91_sckc_dt_driver) = { .name = "at91_sckc", .type = DT_DRIVER_CLK, .match_table = at91_sckc_match_table, .probe = sckc_pmc_setup, }; optee_os-4.3.0/core/drivers/clk/sam/at91_system.c000066400000000000000000000032031464416617300216320ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" #define SYSTEM_MAX_ID 31 #define SYSTEM_MAX_NAME_SZ 32 struct clk_system { vaddr_t base; uint8_t id; }; static bool is_pck(int id) { return (id >= 8) && (id <= 15); } static bool clk_system_ready(vaddr_t base, int id) { uint32_t status = io_read32(base + AT91_PMC_SR); return status & BIT(id); } static TEE_Result clk_system_enable(struct clk *clk) { struct clk_system *sys = clk->priv; io_write32(sys->base + AT91_PMC_SCER, 1 << sys->id); if (!is_pck(sys->id)) return TEE_SUCCESS; while (!clk_system_ready(sys->base, sys->id)) ; return TEE_SUCCESS; } static void clk_system_disable(struct clk *clk) { struct clk_system *sys = clk->priv; io_write32(sys->base + AT91_PMC_SCDR, 1 << sys->id); } static const struct clk_ops system_ops = { .enable = clk_system_enable, .disable = clk_system_disable, }; struct clk * at91_clk_register_system(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id) { struct clk_system *sys = NULL; struct clk *clk = NULL; if (!parent || id > SYSTEM_MAX_ID) return NULL; clk = clk_alloc(name, &system_ops, &parent, 1); if (!clk) return NULL; sys = calloc(1, sizeof(*sys)); if (!sys) { clk_free(clk); return NULL; } sys->id = id; sys->base = pmc->base; clk->priv = sys; if (clk_register(clk)) { clk_free(clk); free(sys); return NULL; } return clk; } optee_os-4.3.0/core/drivers/clk/sam/at91_usb.c000066400000000000000000000056071464416617300211110ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" #define SAM9X5_USB_DIV_SHIFT 8 #define SAM9X5_USB_DIV_COUNT BIT32(4) #define SAM9X5_USB_MAX_DIV (SAM9X5_USB_DIV_COUNT - 1) #define SAM9X5_USBS_MASK BIT(0) struct at91sam9x5_clk_usb { vaddr_t base; uint32_t usbs_mask; }; static unsigned long at91sam9x5_clk_usb_get_rate(struct clk *clk, unsigned long parent_rate) { struct at91sam9x5_clk_usb *usb = clk->priv; uint8_t usbdiv = 1; unsigned int usbr = io_read32(usb->base + AT91_PMC_USB); usbdiv = (usbr & AT91_PMC_OHCIUSBDIV) >> SAM9X5_USB_DIV_SHIFT; return UDIV_ROUND_NEAREST(parent_rate, (usbdiv + 1)); } static TEE_Result at91sam9x5_clk_usb_set_parent(struct clk *clk, size_t index) { struct at91sam9x5_clk_usb *usb = clk->priv; if (index >= clk_get_num_parents(clk)) return TEE_ERROR_BAD_PARAMETERS; io_clrsetbits32(usb->base + AT91_PMC_USB, usb->usbs_mask, index); return TEE_SUCCESS; } static size_t at91sam9x5_clk_usb_get_parent(struct clk *clk) { struct at91sam9x5_clk_usb *usb = clk->priv; unsigned int usbr = io_read32(usb->base + AT91_PMC_USB); return usbr & usb->usbs_mask; } static TEE_Result at91sam9x5_clk_usb_set_rate(struct clk *clk, unsigned long rate, unsigned long parent_rate) { struct at91sam9x5_clk_usb *usb = clk->priv; unsigned long div = 1; if (!rate) return TEE_ERROR_BAD_PARAMETERS; div = UDIV_ROUND_NEAREST(parent_rate, rate); if (div > SAM9X5_USB_MAX_DIV + 1 || !div) return TEE_ERROR_BAD_PARAMETERS; io_clrsetbits32(usb->base + AT91_PMC_USB, AT91_PMC_OHCIUSBDIV, (div - 1) << SAM9X5_USB_DIV_SHIFT); return TEE_SUCCESS; } static const struct clk_ops at91sam9x5_usb_ops = { .get_rate = at91sam9x5_clk_usb_get_rate, .get_parent = at91sam9x5_clk_usb_get_parent, .set_parent = at91sam9x5_clk_usb_set_parent, .set_rate = at91sam9x5_clk_usb_set_rate, }; static struct clk * _at91sam9x5_clk_register_usb(struct pmc_data *pmc, const char *name, struct clk **parents, uint8_t num_parents, uint32_t usbs_mask) { struct at91sam9x5_clk_usb *usb = NULL; struct clk *clk = NULL; clk = clk_alloc(name, &at91sam9x5_usb_ops, parents, num_parents); if (!clk) return NULL; usb = calloc(1, sizeof(*usb)); if (!usb) return NULL; usb->base = pmc->base; usb->usbs_mask = usbs_mask; clk->priv = usb; clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; if (clk_register(clk)) { clk_free(clk); free(usb); return NULL; } return clk; } struct clk * at91sam9x5_clk_register_usb(struct pmc_data *pmc, const char *name, struct clk **parents, uint8_t num_parents) { return _at91sam9x5_clk_register_usb(pmc, name, parents, num_parents, SAM9X5_USBS_MASK); } optee_os-4.3.0/core/drivers/clk/sam/at91_utmi.c000066400000000000000000000100331464416617300212630ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (C) 2013 Boris BREZILLON * Copyright (C) 2021 Microchip */ #include #include #include #include #include #include "at91_clk.h" /* * The purpose of this clock is to generate a 480 MHz signal. A different * rate can't be configured. */ #define UTMI_RATE 480000000 struct clk_utmi { vaddr_t pmc_base; vaddr_t sfr_base; }; static bool clk_utmi_ready(vaddr_t pmc_base) { uint32_t status = io_read32(pmc_base + AT91_PMC_SR); return status & AT91_PMC_LOCKU; } static TEE_Result clk_utmi_enable(struct clk *clk) { struct clk *clk_parent = NULL; struct clk_utmi *utmi = clk->priv; unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN; unsigned int utmi_ref_clk_freq = 0; unsigned long parent_rate = 0; /* * If mainck rate is different from 12 MHz, we have to configure the * FREQ field of the SFR_UTMICKTRIM register to generate properly * the utmi clock. */ clk_parent = clk_get_parent(clk); parent_rate = clk_get_rate(clk_parent); switch (parent_rate) { case 12000000: utmi_ref_clk_freq = 0; break; case 16000000: utmi_ref_clk_freq = 1; break; case 24000000: utmi_ref_clk_freq = 2; break; /* * Not supported on SAMA5D2 but it's not an issue since MAINCK * maximum value is 24 MHz. */ case 48000000: utmi_ref_clk_freq = 3; break; default: EMSG("UTMICK: unsupported mainck rate"); return TEE_ERROR_BAD_PARAMETERS; } if (utmi->sfr_base) { io_clrsetbits32(utmi->sfr_base + AT91_SFR_UTMICKTRIM, AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq); } else if (utmi_ref_clk_freq) { EMSG("UTMICK: sfr node required"); return TEE_ERROR_BAD_STATE; } io_clrsetbits32(utmi->pmc_base + AT91_CKGR_UCKR, uckr, uckr); while (!clk_utmi_ready(utmi->pmc_base)) ; return TEE_SUCCESS; } static void clk_utmi_disable(struct clk *clk) { struct clk_utmi *utmi = clk->priv; io_clrbits32(utmi->pmc_base + AT91_CKGR_UCKR, AT91_PMC_UPLLEN); } static unsigned long clk_utmi_get_rate(struct clk *clk __unused, unsigned long parent_rate __unused) { /* UTMI clk rate is fixed. */ return UTMI_RATE; } static const struct clk_ops utmi_ops = { .enable = clk_utmi_enable, .disable = clk_utmi_disable, .get_rate = clk_utmi_get_rate, }; static struct clk *at91_clk_register_utmi_internal(struct pmc_data *pmc, const char *name, const struct clk_ops *ops, struct clk *parent) { struct clk_utmi *utmi = NULL; struct clk *clk = NULL; clk = clk_alloc(name, ops, &parent, 1); if (!clk) return NULL; utmi = calloc(1, sizeof(*utmi)); if (!utmi) { clk_free(clk); return NULL; } utmi->pmc_base = pmc->base; utmi->sfr_base = sam_sfr_base(); clk->flags = CLK_SET_RATE_GATE; clk->priv = utmi; if (clk_register(clk)) { clk_free(clk); free(utmi); return NULL; } return clk; } struct clk *at91_clk_register_utmi(struct pmc_data *pmc, const char *name, struct clk *parent) { return at91_clk_register_utmi_internal(pmc, name, &utmi_ops, parent); } static TEE_Result clk_utmi_sama7g5_prepare(struct clk *clk) { struct clk *clk_parent = NULL; struct clk_utmi *utmi = clk->priv; unsigned long parent_rate = 0; uint32_t val = 0; clk_parent = clk_get_parent(clk); parent_rate = clk_get_rate(clk_parent); switch (parent_rate) { case 16000000: val = 0; break; case 20000000: val = 2; break; case 24000000: val = 3; break; case 32000000: val = 5; break; default: EMSG("UTMICK: unsupported main_xtal rate"); return TEE_ERROR_BAD_PARAMETERS; } io_clrsetbits32(utmi->pmc_base + AT91_PMC_XTALF, AT91_PMC_XTALF_XTALF, val); return TEE_SUCCESS; } static const struct clk_ops sama7g5_utmi_ops = { .enable = clk_utmi_sama7g5_prepare, .get_rate = clk_utmi_get_rate, }; struct clk *at91_clk_sama7g5_register_utmi(struct pmc_data *pmc, const char *name, struct clk *parent) { return at91_clk_register_utmi_internal(pmc, name, &sama7g5_utmi_ops, parent); } optee_os-4.3.0/core/drivers/clk/sam/clk-sam9x60-pll.c000066400000000000000000000321761464416617300222260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019 Microchip Technology Inc. */ #include #include #include #include #include #include "at91_clk.h" #define PMC_PLL_CTRL0_DIV_MASK 0xf #define PMC_PLL_CTRL0_DIV_POS 0 #define PMC_PLL_CTRL1_MUL_MASK 0xff #define PMC_PLL_CTRL1_MUL_POS 24 #define PMC_PLL_CTRL1_FRACR_MASK 0x3fffff #define PMC_PLL_CTRL1_FRACR_POS 0 #define PLL_STATUS_MASK(id) BIT(1 + (id)) #define PLL_REG(id) (AT91_CKGR_PLLAR + ((id) * 4)) #define PLL_DIV_MASK 0xff #define PLL_DIV_MAX PLL_DIV_MASK #define PLL_DIV(reg) ((reg) & PLL_DIV_MASK) #define PLL_MUL(reg, layout) \ ({ \ typeof(layout) __layout = layout; \ \ (((reg) >> (__layout)->mul_shift) & (__layout)->mul_mask); \ }) #define PLL_MUL_MIN 2 #define PLL_MUL_MASK(layout) ((layout)->mul_mask) #define PLL_MUL_MAX(layout) (PLL_MUL_MASK(layout) + 1) #define PLL_ICPR_SHIFT(id) ((id) * 16) #define PLL_ICPR_MASK(id) SHIFT_U64(0xffff, PLL_ICPR_SHIFT(id)) #define PLL_MAX_COUNT 0x3f #define PLL_COUNT_SHIFT 8 #define PLL_OUT_SHIFT 14 struct sam9x60_pll_core { vaddr_t base; const struct clk_pll_charac *charac; const struct clk_pll_layout *layout; struct clk *hw; uint8_t id; }; struct sam9x60_frac { struct sam9x60_pll_core core; uint32_t frac; uint16_t mul; }; struct sam9x60_div { struct sam9x60_pll_core core; uint8_t div; uint8_t safe_div; }; #define WAIT_PLL_READY_TIMEOUT(_base, _id) \ ({ \ uint32_t __timeout = 0; \ uint32_t _c = 0; \ \ while (__timeout++ < 500) { \ _c = io_read32((_base) + AT91_PMC_PLL_ISR0) & \ BIT(_id); \ if (_c) \ break; \ wait_cycles(100); \ } \ !(_c); \ }) static bool sam9x60_pll_ready(vaddr_t base, int id) { return io_read32(base + AT91_PMC_PLL_ISR0) & BIT(id); } static bool sam9x60_frac_pll_ready(vaddr_t regmap, uint8_t id) { return sam9x60_pll_ready(regmap, id); } static unsigned long sam9x60_frac_pll_recalc_rate(struct clk *hw, unsigned long parent_rate) { struct sam9x60_frac *frac = hw->priv; return parent_rate * (frac->mul + 1) + UDIV_ROUND_NEAREST((unsigned long long)parent_rate * frac->frac, 1 << 22); } static TEE_Result sam9x60_frac_pll_set(struct sam9x60_frac *frac) { struct sam9x60_pll_core *core = &frac->core; vaddr_t regmap = frac->core.base; unsigned int val = 0; unsigned int cfrac = 0; unsigned int cmul = 0; io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, core->id); val = io_read32(regmap + AT91_PMC_PLL_CTRL1); cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift; cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift; if (sam9x60_frac_pll_ready(regmap, core->id) && cmul == frac->mul && cfrac == frac->frac) return TEE_SUCCESS; /* Recommended value for PMC_PLL_ACR */ if (core->charac->upll) val = AT91_PMC_PLL_ACR_DEFAULT_UPLL; else val = AT91_PMC_PLL_ACR_DEFAULT_PLLA; io_write32(regmap + AT91_PMC_PLL_ACR, val); io_write32(regmap + AT91_PMC_PLL_CTRL1, SHIFT_U32(frac->mul, core->layout->mul_shift) | SHIFT_U32(frac->frac, core->layout->frac_shift)); if (core->charac->upll) { /* Enable the UTMI internal bandgap */ val |= AT91_PMC_PLL_ACR_UTMIBG; io_write32(regmap + AT91_PMC_PLL_ACR, val); udelay(10); /* Enable the UTMI internal regulator */ val |= AT91_PMC_PLL_ACR_UTMIVR; io_write32(regmap + AT91_PMC_PLL_ACR, val); udelay(10); } io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | core->id); io_setbits32(regmap + AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL); io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | core->id); if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) { EMSG("PLL not ready"); return TEE_ERROR_BUSY; } return TEE_SUCCESS; } static TEE_Result sam9x60_frac_pll_prepare(struct clk *hw) { struct sam9x60_frac *frac = hw->priv; return sam9x60_frac_pll_set(frac); } static void sam9x60_frac_pll_unprepare(struct clk *hw) { struct sam9x60_frac *frac = hw->priv; io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, frac->core.id); io_clrbits32(frac->core.base + AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL); if (frac->core.charac->upll) io_clrbits32(frac->core.base + AT91_PMC_PLL_ACR, AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR); io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | frac->core.id); } static TEE_Result sam9x60_frac_pll_compute_mul_frac(struct sam9x60_frac *frac, unsigned long rate, unsigned long parent_rate, bool update) { unsigned long tmprate = 0; unsigned long remainder = 0; unsigned long nmul = 0; unsigned long nfrac = 0; if (rate < frac->core.charac->output[0].min || rate > frac->core.charac->output[0].max) return TEE_ERROR_GENERIC; /* * Calculate the multiplier associated with the current * divider that provide the closest rate to the requested one. */ nmul = rate / parent_rate; tmprate = parent_rate * nmul; remainder = rate - tmprate; if (remainder) { nfrac = UDIV_ROUND_NEAREST((uint64_t)remainder * (1 << 22), parent_rate); tmprate += UDIV_ROUND_NEAREST((uint64_t)nfrac * parent_rate, 1 << 22); } /* Check if resulted rate is a valid. */ if (tmprate < frac->core.charac->output[0].min || tmprate > frac->core.charac->output[0].max) return TEE_ERROR_GENERIC; if (update) { frac->mul = nmul - 1; frac->frac = nfrac; } return TEE_SUCCESS; } static TEE_Result sam9x60_frac_pll_set_rate_chg(struct clk *hw, unsigned long rate, unsigned long parent_rate) { TEE_Result ret = TEE_SUCCESS; struct sam9x60_frac *frac = hw->priv; struct sam9x60_pll_core *core = &frac->core; vaddr_t regmap = core->base; ret = sam9x60_frac_pll_compute_mul_frac(frac, rate, parent_rate, true); if (ret == TEE_SUCCESS) { io_write32(regmap + AT91_PMC_PLL_CTRL1, SHIFT_U32(frac->mul, core->layout->mul_shift) | SHIFT_U32(frac->frac, core->layout->frac_shift)); io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | core->id); io_setbits32(regmap + AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL); io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | core->id); if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) { EMSG("PLL not ready"); return TEE_ERROR_BUSY; } } return ret; } static const struct clk_ops sam9x60_frac_pll_ops_chg = { .enable = sam9x60_frac_pll_prepare, .disable = sam9x60_frac_pll_unprepare, .get_rate = sam9x60_frac_pll_recalc_rate, .set_rate = sam9x60_frac_pll_set_rate_chg, }; static TEE_Result sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, uint32_t div, bool enable) { vaddr_t regmap = core->base; uint32_t enable_mask = enable ? core->layout->endiv_mask : 0; uint32_t ena_val = enable ? BIT(core->layout->endiv_shift) : 0; io_clrsetbits32(regmap + AT91_PMC_PLL_CTRL0, core->layout->div_mask | enable_mask, SHIFT_U32(div, core->layout->div_shift) | ena_val); io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | core->id); if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) { EMSG("PLL not ready"); return TEE_ERROR_BUSY; } return TEE_SUCCESS; } static TEE_Result sam9x60_div_pll_set(struct sam9x60_div *div) { struct sam9x60_pll_core *core = &div->core; vaddr_t regmap = core->base; unsigned int val = 0; unsigned int cdiv = 0; io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, core->id); val = io_read32(regmap + AT91_PMC_PLL_CTRL0); cdiv = (val & core->layout->div_mask) >> core->layout->div_shift; /* Stop if enabled an nothing changed. */ if ((val & core->layout->endiv_mask) && cdiv == div->div) return TEE_SUCCESS; return sam9x60_div_pll_set_div(core, div->div, 1); } static TEE_Result sam9x60_div_pll_prepare(struct clk *hw) { struct sam9x60_div *div = hw->priv; return sam9x60_div_pll_set(div); } static void sam9x60_div_pll_unprepare(struct clk *hw) { struct sam9x60_div *div = hw->priv; struct sam9x60_pll_core *core = &div->core; vaddr_t regmap = core->base; io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, core->id); io_clrbits32(regmap + AT91_PMC_PLL_CTRL0, core->layout->endiv_mask); io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK, AT91_PMC_PLL_UPDT_UPDATE | core->id); } static unsigned long sam9x60_div_pll_recalc_rate(struct clk *hw, unsigned long parent_rate) { struct sam9x60_div *div = hw->priv; return UDIV_ROUND_NEAREST(parent_rate, div->div + 1); } static TEE_Result sam9x60_div_pll_set_rate(struct clk *hw, unsigned long rate, unsigned long parent_rate) { struct sam9x60_div *div = hw->priv; div->div = UDIV_ROUND_NEAREST(parent_rate, rate) - 1; return TEE_SUCCESS; } static TEE_Result sam9x60_div_pll_set_rate_chg(struct clk *hw, unsigned long rate, unsigned long parent_rate) { struct sam9x60_div *div = hw->priv; struct sam9x60_pll_core *core = &div->core; vaddr_t regmap = core->base; unsigned int val = 0; unsigned int cdiv = 0; div->div = UDIV_ROUND_NEAREST(parent_rate, rate) - 1; io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, core->id); val = io_read32(regmap + AT91_PMC_PLL_CTRL0); cdiv = (val & core->layout->div_mask) >> core->layout->div_shift; /* Stop if nothing changed. */ if (cdiv == div->div) return TEE_SUCCESS; return sam9x60_div_pll_set_div(core, div->div, 0); } static const struct clk_ops sam9x60_div_pll_ops = { .enable = sam9x60_div_pll_prepare, .disable = sam9x60_div_pll_unprepare, .set_rate = sam9x60_div_pll_set_rate, .get_rate = sam9x60_div_pll_recalc_rate, }; static const struct clk_ops sam9x60_div_pll_ops_chg = { .enable = sam9x60_div_pll_prepare, .disable = sam9x60_div_pll_unprepare, .set_rate = sam9x60_div_pll_set_rate_chg, .get_rate = sam9x60_div_pll_recalc_rate, }; struct clk *sam9x60_clk_register_frac_pll(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id, const struct clk_pll_charac *charac, const struct clk_pll_layout *layout, uint32_t flags) { struct sam9x60_frac *frac = NULL; struct clk *hw = NULL; unsigned long parent_rate = 0; unsigned int val = 0; TEE_Result ret = TEE_SUCCESS; frac = calloc(1, sizeof(*frac)); if (!frac) return NULL; hw = clk_alloc(name, &sam9x60_frac_pll_ops_chg, &parent, 1); if (!hw) { free(frac); return NULL; } hw->priv = frac; hw->flags = flags; frac->core.id = id; frac->core.charac = charac; frac->core.layout = layout; frac->core.base = pmc->base; if (sam9x60_pll_ready(pmc->base, id)) { io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, id); val = io_read32(pmc->base + AT91_PMC_PLL_CTRL1); frac->mul = (val >> PMC_PLL_CTRL1_MUL_POS) & PMC_PLL_CTRL1_MUL_MASK; frac->frac = (val >> PMC_PLL_CTRL1_FRACR_POS) & PMC_PLL_CTRL1_FRACR_MASK; } else { /* * This means the PLL is not setup by bootloaders. In this * case we need to set the minimum rate for it. Otherwise * a clock child of this PLL may be enabled before setting * its rate leading to enabling this PLL with unsupported * rate. This will lead to PLL not being locked at all. */ parent_rate = clk_get_rate(parent); if (!parent_rate) { clk_free(hw); free(frac); return NULL; } ret = sam9x60_frac_pll_compute_mul_frac(frac, charac->output[0].min, parent_rate, true); if (ret != TEE_SUCCESS) { clk_free(hw); free(frac); return NULL; } } frac->core.hw = hw; if (clk_register(hw)) { clk_free(hw); free(frac); return NULL; } return hw; } struct clk *sam9x60_clk_register_div_pll(struct pmc_data *pmc, const char *name, struct clk *parent, uint8_t id, const struct clk_pll_charac *charac, const struct clk_pll_layout *layout, uint32_t flags, uint32_t safe_div) { struct sam9x60_div *div = NULL; struct clk *hw = NULL; unsigned int val = 0; if (safe_div >= PLL_DIV_MAX) safe_div = PLL_DIV_MAX - 1; div = calloc(1, sizeof(*div)); if (!div) return NULL; if (flags & CLK_SET_RATE_GATE) hw = clk_alloc(name, &sam9x60_div_pll_ops, &parent, 1); else hw = clk_alloc(name, &sam9x60_div_pll_ops_chg, &parent, 1); if (!hw) { free(div); return NULL; } hw->priv = div; hw->flags = flags; div->core.id = id; div->core.charac = charac; div->core.layout = layout; div->core.base = pmc->base; div->safe_div = safe_div; io_clrsetbits32(pmc->base + AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MASK, id); val = io_read32(pmc->base + AT91_PMC_PLL_CTRL0); div->div = (val >> PMC_PLL_CTRL0_DIV_POS) & PMC_PLL_CTRL0_DIV_MASK; div->core.hw = hw; if (clk_register(hw)) { clk_free(hw); free(div); return NULL; } return hw; } optee_os-4.3.0/core/drivers/clk/sam/phy-sama7-utmi-clk.c000066400000000000000000000034151464416617300230060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Driver for the Microchip SAMA7 USB 2.0 PHY Clock * * Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries * * Author: Tony Han * */ #include #include #include #include #include #include "at91_clk.h" #define SAMA7_SFR_UTMI0R(x) (0x2040 + 4 * (x)) /* offset of SFR_UTMI0Rx */ #define SAMA7_SFR_UTMI_COMMONON BIT(3) /* PLL Common ON bit */ struct sama7_utmi_clk { vaddr_t base; uint8_t id; }; static TEE_Result sama7_utmi_clk_enable(struct clk *hw) { struct sama7_utmi_clk *utmi = hw->priv; uint8_t id = utmi->id; sam_rstc_usb_por(id, true); io_clrbits32(utmi->base + SAMA7_SFR_UTMI0R(id), SAMA7_SFR_UTMI_COMMONON); sam_rstc_usb_por(id, false); /* Datasheet states a minimum of 45 us before any USB operation */ udelay(50); return TEE_SUCCESS; } static void sama7_utmi_clk_disable(struct clk *hw) { struct sama7_utmi_clk *utmi = hw->priv; uint8_t id = utmi->id; sam_rstc_usb_por(id, true); io_setbits32(utmi->base + SAMA7_SFR_UTMI0R(id), SAMA7_SFR_UTMI_COMMONON); } static const struct clk_ops sama7_utmi_ops = { .enable = sama7_utmi_clk_enable, .disable = sama7_utmi_clk_disable, }; struct clk *sama7_utmi_clk_register(const char *name, struct clk *parent, uint8_t id) { struct clk *hw = NULL; struct sama7_utmi_clk *utmi_clk = NULL; hw = clk_alloc(name, &sama7_utmi_ops, &parent, 1); if (!hw) return NULL; utmi_clk = calloc(1, sizeof(*utmi_clk)); if (!utmi_clk) { clk_free(hw); return NULL; } utmi_clk->base = sam_sfr_base(); utmi_clk->id = id; hw->priv = utmi_clk; if (clk_register(hw)) { clk_free(hw); free(utmi_clk); return NULL; } return hw; } optee_os-4.3.0/core/drivers/clk/sam/sama5d2_clk.c000066400000000000000000000335721464416617300215510ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #include "at91_clk.h" #include #define PROGCK_PARENT_COUNT 6 #define PARENT_SIZE ARRAY_SIZE(sama5d2_systemck) struct sam_clk { const char *n; uint8_t id; }; static const struct clk_master_charac mck_charac = { .output = { .min = 124000000, .max = 166000000 }, .divisors = { 1, 2, 4, 3 }, }; static uint8_t plla_out[1]; static uint16_t plla_icpll[1]; static const struct clk_range plla_outputs[] = { { .min = 600000000, .max = 1200000000 }, }; static const struct clk_pll_charac plla_charac = { .input = { .min = 12000000, .max = 24000000 }, .num_output = ARRAY_SIZE(plla_outputs), .output = plla_outputs, .icpll = plla_icpll, .out = plla_out, }; static const struct clk_pcr_layout sama5d2_pcr_layout = { .offset = 0x10c, .cmd = BIT(12), .gckcss_mask = GENMASK_32(10, 8), .pid_mask = GENMASK_32(6, 0), }; static const struct clk_programmable_layout sama5d2_prog_layout = { .pres_mask = 0xff, .pres_shift = 4, .css_mask = 0x7, .have_slck_mck = 0, .is_pres_direct = 1, }; static const struct sam_clk sama5d2_systemck[] = { { .n = "ddrck", .id = 2 }, { .n = "lcdck", .id = 3 }, { .n = "uhpck", .id = 6 }, { .n = "udpck", .id = 7 }, { .n = "pck0", .id = 8 }, { .n = "pck1", .id = 9 }, { .n = "pck2", .id = 10 }, { .n = "iscck", .id = 18 }, }; static const struct { struct sam_clk clk; struct clk_range r; } sama5d2_peri32ck[] = { { .clk = { .n = "macb0_clk", .id = 5 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "tdes_clk", .id = 11 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "matrix1_clk", .id = 14 }, }, { .clk = { .n = "hsmc_clk", .id = 17 }, }, { .clk = { .n = "pioA_clk", .id = 18 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "flx0_clk", .id = 19 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "flx1_clk", .id = 20 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "flx2_clk", .id = 21 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "flx3_clk", .id = 22 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "flx4_clk", .id = 23 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "uart0_clk", .id = 24 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "uart1_clk", .id = 25 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "uart2_clk", .id = 26 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "uart3_clk", .id = 27 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "uart4_clk", .id = 28 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "twi0_clk", .id = 29 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "twi1_clk", .id = 30 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "spi0_clk", .id = 33 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "spi1_clk", .id = 34 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "tcb0_clk", .id = 35 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "tcb1_clk", .id = 36 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "pwm_clk", .id = 38 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "adc_clk", .id = 40 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "uhphs_clk", .id = 41 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "udphs_clk", .id = 42 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "ssc0_clk", .id = 43 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "ssc1_clk", .id = 44 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "trng_clk", .id = 47 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "pdmic_clk", .id = 48 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "securam_clk", .id = 51 }, }, { .clk = { .n = "i2s0_clk", .id = 54 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "i2s1_clk", .id = 55 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "can0_clk", .id = 56 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "can1_clk", .id = 57 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "ptc_clk", .id = 58 }, .r = { .min = 0, .max = 83000000 }, }, { .clk = { .n = "classd_clk", .id = 59 }, .r = { .min = 0, .max = 83000000 }, }, }; static const struct sam_clk sama5d2_perick[] = { { .n = "dma0_clk", .id = 6 }, { .n = "dma1_clk", .id = 7 }, { .n = "aes_clk", .id = 9 }, { .n = "aesb_clk", .id = 10 }, { .n = "sha_clk", .id = 12 }, { .n = "mpddr_clk", .id = 13 }, { .n = "matrix0_clk", .id = 15 }, { .n = "sdmmc0_hclk", .id = 31 }, { .n = "sdmmc1_hclk", .id = 32 }, { .n = "lcdc_clk", .id = 45 }, { .n = "isc_clk", .id = 46 }, { .n = "qspi0_clk", .id = 52 }, { .n = "qspi1_clk", .id = 53 }, }; static const struct { struct sam_clk clk; struct clk_range r; int chg_pid; } sama5d2_gck[] = { { .clk = { .n = "sdmmc0_gclk", .id = 31 }, .chg_pid = INT_MIN, }, { .clk = { .n = "sdmmc1_gclk", .id = 32 }, .chg_pid = INT_MIN, }, { .clk = { .n = "tcb0_gclk", .id = 35 }, .r = { .min = 0, .max = 83000000 }, .chg_pid = INT_MIN, }, { .clk = { .n = "tcb1_gclk", .id = 36 }, .r = { .min = 0, .max = 83000000 }, .chg_pid = INT_MIN, }, { .clk = { .n = "pwm_gclk", .id = 38 }, .r = { .min = 0, .max = 83000000 }, .chg_pid = INT_MIN, }, { .clk = { .n = "isc_gclk", .id = 46 }, .chg_pid = INT_MIN, }, { .clk = { .n = "pdmic_gclk", .id = 48 }, .chg_pid = INT_MIN, }, { .clk = { .n = "i2s0_gclk", .id = 54 }, .chg_pid = 5, }, { .clk = { .n = "i2s1_gclk", .id = 55 }, .chg_pid = 5, }, { .clk = { .n = "can0_gclk", .id = 56 }, .r = { .min = 0, .max = 80000000 }, .chg_pid = INT_MIN, }, { .clk = { .n = "can1_gclk", .id = 57 }, .r = { .min = 0, .max = 80000000 }, .chg_pid = INT_MIN, }, { .clk = { .n = "classd_gclk", .id = 59 }, .chg_pid = 5, .r = { .min = 0, .max = 100000000 }, }, }; static const struct sam_clk sama5d2_progck[] = { { .n = "prog0", .id = 0 }, { .n = "prog1", .id = 1 }, { .n = "prog2", .id = 2 }, }; static struct pmc_data *pmc; vaddr_t at91_pmc_get_base(void) { assert(pmc); return pmc->base; } TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, struct clk **clk) { return pmc_clk_get(pmc, type, idx, clk); } static TEE_Result pmc_setup(const void *fdt, int nodeoffset, const void *data __unused) { size_t size = 0; vaddr_t base = 0; unsigned int i = 0; int bypass = 0; const uint32_t *fdt_prop = NULL; struct pmc_clk *pmc_clk = NULL; const struct sam_clk *sam_clk = NULL; struct clk_range range = CLK_RANGE(0, 0); struct clk *h32mxck = NULL; struct clk *mckdivck = NULL; struct clk *plladivck = NULL; struct clk *usbck = NULL; struct clk *audiopll_pmcck = NULL; struct clk *parents[PARENT_SIZE] = {NULL}; struct clk *main_clk = NULL; struct clk *utmi_clk = NULL; struct clk *slow_clk = NULL; struct clk *clk = NULL; struct clk *main_rc_osc = NULL; struct clk *main_osc = NULL; struct clk *main_xtal_clk = NULL; struct clk *audiopll_fracck = NULL; TEE_Result res = TEE_ERROR_GENERIC; /* * We want PARENT_SIZE to be MAX(ARRAY_SIZE(sama5d2_systemck),6) * but using this define won't allow static initialization of parents * due to dynamic size. */ COMPILE_TIME_ASSERT(ARRAY_SIZE(sama5d2_systemck) == PARENT_SIZE); COMPILE_TIME_ASSERT(PARENT_SIZE >= 6); if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0) panic(); if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC) matrix_configure_periph_secure(AT91C_ID_PMC); res = clk_dt_get_by_name(fdt, nodeoffset, "slow_clk", &slow_clk); if (res) panic(); res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); if (res) panic(); pmc = pmc_data_allocate(PMC_SAMA5D2_CORE_CLK_COUNT, ARRAY_SIZE(sama5d2_systemck), ARRAY_SIZE(sama5d2_perick) + ARRAY_SIZE(sama5d2_peri32ck), ARRAY_SIZE(sama5d2_gck), ARRAY_SIZE(sama5d2_progck)); if (!pmc) panic(); pmc->base = base; main_rc_osc = pmc_register_main_rc_osc(pmc, "main_rc_osc", 12000000); if (!main_rc_osc) panic(); fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL); if (fdt_prop) bypass = fdt32_to_cpu(*fdt_prop); main_osc = pmc_register_main_osc(pmc, "main_osc", main_xtal_clk, bypass); if (!main_osc) panic(); parents[0] = main_rc_osc; parents[1] = main_osc; main_clk = at91_clk_register_sam9x5_main(pmc, "mainck", parents, 2); if (!main_clk) panic(); pmc_clk = &pmc->chws[PMC_MAIN]; pmc_clk->clk = main_clk; pmc_clk->id = PMC_MAIN; clk = at91_clk_register_pll(pmc, "pllack", main_clk, 0, &sama5d3_pll_layout, &plla_charac); if (!clk) panic(); plladivck = at91_clk_register_plldiv(pmc, "plladivck", clk); if (!plladivck) panic(); pmc_clk = &pmc->chws[PMC_PLLACK]; pmc_clk->clk = plladivck; pmc_clk->id = PMC_PLLACK; audiopll_fracck = at91_clk_register_audio_pll_frac(pmc, "audiopll_fracck", main_clk); if (!audiopll_fracck) panic(); pmc_clk = &pmc->chws[PMC_AUDIOPLL_FRACCK]; pmc_clk->clk = audiopll_fracck; pmc_clk->id = PMC_AUDIOPLL_FRACCK; clk = at91_clk_register_audio_pll_pad(pmc, "audiopll_padck", audiopll_fracck); if (!clk) panic(); audiopll_pmcck = at91_clk_register_audio_pll_pmc(pmc, "audiopll_pmcck", audiopll_fracck); if (!audiopll_pmcck) panic(); pmc_clk = &pmc->chws[PMC_AUDIOPLLCK]; pmc_clk->clk = audiopll_pmcck; pmc_clk->id = PMC_AUDIOPLLCK; utmi_clk = at91_clk_register_utmi(pmc, "utmick", main_clk); if (!utmi_clk) panic(); pmc_clk = &pmc->chws[PMC_UTMI]; pmc_clk->clk = utmi_clk; pmc_clk->id = PMC_UTMI; parents[0] = slow_clk; parents[1] = main_clk; parents[2] = plladivck; parents[3] = utmi_clk; clk = at91_clk_register_master_pres(pmc, "masterck_pres", 4, parents, &at91sam9x5_master_layout, &mck_charac, INT_MIN); if (!clk) panic(); pmc_clk = &pmc->chws[PMC_MCK_PRES]; pmc_clk->clk = clk; pmc_clk->id = PMC_MCK_PRES; mckdivck = at91_clk_register_master_div(pmc, "masterck_div", clk, &at91sam9x5_master_layout, &mck_charac); if (!mckdivck) panic(); pmc_clk = &pmc->chws[PMC_MCK]; pmc_clk->clk = mckdivck; pmc_clk->id = PMC_MCK; h32mxck = at91_clk_register_h32mx(pmc, "h32mxck", mckdivck); if (!h32mxck) panic(); pmc_clk = &pmc->chws[PMC_MCK2]; pmc_clk->clk = h32mxck; pmc_clk->id = PMC_MCK2; parents[0] = plladivck; parents[1] = utmi_clk; usbck = at91sam9x5_clk_register_usb(pmc, "usbck", parents, 2); if (!usbck) panic(); pmc_clk = &pmc->chws[PMC_USBCK]; pmc_clk->clk = usbck; pmc_clk->id = PMC_USBCK; parents[0] = slow_clk; parents[1] = main_clk; parents[2] = plladivck; parents[3] = utmi_clk; parents[4] = mckdivck; parents[5] = audiopll_pmcck; for (i = 0; i < ARRAY_SIZE(sama5d2_progck); i++) { sam_clk = &sama5d2_progck[i]; clk = at91_clk_register_programmable(pmc, sam_clk->n, parents, PROGCK_PARENT_COUNT, i, &sama5d2_prog_layout); if (!clk) panic(); pmc_clk = &pmc->pchws[i]; pmc_clk->clk = clk; pmc_clk->id = sam_clk->id; } /* This array order must match the one in sama5d2_systemck */ parents[0] = mckdivck; parents[1] = mckdivck; parents[2] = usbck; parents[3] = usbck; parents[4] = pmc->pchws[0].clk; parents[5] = pmc->pchws[1].clk; parents[6] = pmc->pchws[2].clk; parents[7] = mckdivck; for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) { sam_clk = &sama5d2_systemck[i]; clk = at91_clk_register_system(pmc, sam_clk->n, parents[i], sam_clk->id); if (!clk) panic(); pmc_clk = &pmc->shws[i]; pmc_clk->clk = clk; pmc_clk->id = sam_clk->id; } for (i = 0; i < ARRAY_SIZE(sama5d2_perick); i++) { sam_clk = &sama5d2_perick[i]; clk = at91_clk_register_sam9x5_periph(pmc, &sama5d2_pcr_layout, sam_clk->n, mckdivck, sam_clk->id, &range); if (!clk) panic(); pmc_clk = &pmc->phws[i]; pmc_clk->clk = clk; pmc_clk->id = sam_clk->id; } for (i = 0; i < ARRAY_SIZE(sama5d2_peri32ck); i++) { sam_clk = &sama5d2_peri32ck[i].clk; clk = at91_clk_register_sam9x5_periph(pmc, &sama5d2_pcr_layout, sam_clk->n, h32mxck, sam_clk->id, &sama5d2_peri32ck[i].r); if (!clk) panic(); pmc_clk = &pmc->phws[ARRAY_SIZE(sama5d2_perick) + i]; pmc_clk->clk = clk; pmc_clk->id = sam_clk->id; } parents[0] = slow_clk; parents[1] = main_clk; parents[2] = plladivck; parents[3] = utmi_clk; parents[4] = mckdivck; parents[5] = audiopll_pmcck; for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) { sam_clk = &sama5d2_gck[i].clk; clk = at91_clk_register_generated(pmc, &sama5d2_pcr_layout, sam_clk->n, parents, NULL, 6, sam_clk->id, &sama5d2_gck[i].r, sama5d2_gck[i].chg_pid); if (!clk) panic(); pmc_clk = &pmc->ghws[i]; pmc_clk->clk = clk; pmc_clk->id = sam_clk->id; } parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s0_clk"); parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s0_gclk"); clk = at91_clk_i2s_mux_register("i2s0_muxclk", parents, 2, 0); if (!clk) panic(); pmc->chws[PMC_I2S0_MUX].clk = clk; pmc->chws[PMC_I2S0_MUX].id = PMC_I2S0_MUX; parents[0] = pmc_clk_get_by_name(pmc->phws, pmc->nperiph, "i2s1_clk"); parents[1] = pmc_clk_get_by_name(pmc->ghws, pmc->ngck, "i2s1_gclk"); clk = at91_clk_i2s_mux_register("i2s1_muxclk", parents, 2, 1); if (!clk) panic(); pmc->chws[PMC_I2S1_MUX].clk = clk; pmc->chws[PMC_I2S1_MUX].id = PMC_I2S1_MUX; clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, pmc); pmc_register_pm(); return TEE_SUCCESS; } CLK_DT_DECLARE(sama5d2_clk, "atmel,sama5d2-pmc", pmc_setup); optee_os-4.3.0/core/drivers/clk/sam/sama7g5_clk.c000066400000000000000000001031541464416617300215530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, Microchip */ #include #include #include #include #include #include #include #include #include #include #include #include "at91_clk.h" #define CLK_IS_CRITICAL 0 /* PLL clocks identifiers */ enum pll_ids { PLL_ID_CPU, PLL_ID_SYS, PLL_ID_DDR, PLL_ID_IMG, PLL_ID_BAUD, PLL_ID_AUDIO, PLL_ID_ETH, PLL_ID_MAX, }; /* PLL type identifiers */ enum pll_type { PLL_TYPE_FRAC, PLL_TYPE_DIV, PLL_TYPE_CNT, }; /* Layout for fractional PLLs */ static const struct clk_pll_layout pll_layout_frac = { .mul_mask = GENMASK_32(31, 24), .frac_mask = GENMASK_32(21, 0), .mul_shift = 24, .frac_shift = 0, }; /* Layout for DIVPMC dividers */ static const struct clk_pll_layout pll_layout_divpmc = { .div_mask = GENMASK_32(7, 0), .endiv_mask = BIT(29), .div_shift = 0, .endiv_shift = 29, }; /* Layout for DIVIO dividers */ static const struct clk_pll_layout pll_layout_divio = { .div_mask = GENMASK_32(19, 12), .endiv_mask = BIT(30), .div_shift = 12, .endiv_shift = 30, }; /* * CPU PLL output range * Notice: The upper limit has been setup to 1000000002 due to hardware * block which cannot output exactly 1GHz. */ static const struct clk_range cpu_pll_output[] = { { .min = 2343750, .max = 1000000002 }, }; /* PLL output range */ static const struct clk_range pll_output[] = { { .min = 2343750, .max = 1200000000 }, }; /* CPU PLL characteristics */ static const struct clk_pll_charac cpu_pll_characteristics = { .input = { .min = 12000000, .max = 50000000 }, .num_output = ARRAY_SIZE(cpu_pll_output), .output = cpu_pll_output, }; /* PLL characteristics */ static const struct clk_pll_charac pll_characteristics = { .input = { .min = 12000000, .max = 50000000 }, .num_output = ARRAY_SIZE(pll_output), .output = pll_output, }; /* PLL clocks description */ struct sama7g5_pll { const char *name; const char *parent; const struct clk_pll_layout *layout; const struct clk_pll_charac *charac; unsigned long flags; uint8_t type; uint8_t eid; /* export index in sama7g5->chws[] array */ uint8_t safe_div; /* intermediate divider need to be set on * PRE_RATE_CHANGE notification */ }; static const struct sama7g5_pll sama7g5_plls[][PLL_ID_MAX] = { [PLL_ID_CPU] = { { .name = "cpupll_fracck", .parent = "mainck", .layout = &pll_layout_frac, .charac = &cpu_pll_characteristics, .type = PLL_TYPE_FRAC, /* * This feeds cpupll_divpmcck which feeds CPU. It * should not be disabled. */ .flags = CLK_IS_CRITICAL, }, { .name = "cpupll_divpmcck", .parent = "cpupll_fracck", .layout = &pll_layout_divpmc, .charac = &cpu_pll_characteristics, .type = PLL_TYPE_DIV, /* This feeds CPU. It should not be disabled. */ .flags = CLK_IS_CRITICAL, .eid = PMC_CPUPLL, /* * Safe div=15 should be safe even for switching b/w * 1GHz and 90MHz (frac pll might go up to 1.2GHz). */ .safe_div = 15, }, }, [PLL_ID_SYS] = { { .name = "syspll_fracck", .parent = "mainck", .layout = &pll_layout_frac, .charac = &pll_characteristics, .type = PLL_TYPE_FRAC, /* * This feeds syspll_divpmcck which may feed critical * parts of the systems like timers. Therefore it * should not be disabled. */ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, }, { .name = "syspll_divpmcck", .parent = "syspll_fracck", .layout = &pll_layout_divpmc, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, /* * This may feed critical parts of the systems like * timers. Therefore it should not be disabled. */ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, .eid = PMC_SYSPLL, }, }, [PLL_ID_DDR] = { { .name = "ddrpll_fracck", .parent = "mainck", .layout = &pll_layout_frac, .charac = &pll_characteristics, .type = PLL_TYPE_FRAC, /* * This feeds ddrpll_divpmcck which feeds DDR. It * should not be disabled. */ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, }, { .name = "ddrpll_divpmcck", .parent = "ddrpll_fracck", .layout = &pll_layout_divpmc, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, /* This feeds DDR. It should not be disabled. */ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, .eid = PMC_DDRPLL, }, }, [PLL_ID_IMG] = { { .name = "imgpll_fracck", .parent = "mainck", .layout = &pll_layout_frac, .charac = &pll_characteristics, .type = PLL_TYPE_FRAC, .flags = CLK_SET_RATE_GATE, }, { .name = "imgpll_divpmcck", .parent = "imgpll_fracck", .layout = &pll_layout_divpmc, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, .eid = PMC_IMGPLL, }, }, [PLL_ID_BAUD] = { { .name = "baudpll_fracck", .parent = "mainck", .layout = &pll_layout_frac, .charac = &pll_characteristics, .type = PLL_TYPE_FRAC, .flags = CLK_SET_RATE_GATE, }, { .name = "baudpll_divpmcck", .parent = "baudpll_fracck", .layout = &pll_layout_divpmc, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, .eid = PMC_BAUDPLL, }, }, [PLL_ID_AUDIO] = { { .name = "audiopll_fracck", .parent = "main_xtal", .layout = &pll_layout_frac, .charac = &pll_characteristics, .type = PLL_TYPE_FRAC, .flags = CLK_SET_RATE_GATE, }, { .name = "audiopll_divck", .parent = "audiopll_fracck", .layout = &pll_layout_divpmc, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, .eid = PMC_AUDIOPMCPLL, }, { .name = "audiopll_diviock", .parent = "audiopll_fracck", .layout = &pll_layout_divio, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, .eid = PMC_AUDIOIOPLL, }, }, [PLL_ID_ETH] = { { .name = "ethpll_fracck", .parent = "main_xtal", .layout = &pll_layout_frac, .charac = &pll_characteristics, .type = PLL_TYPE_FRAC, .flags = CLK_SET_RATE_GATE, }, { .name = "ethpll_divpmcck", .parent = "ethpll_fracck", .layout = &pll_layout_divpmc, .charac = &pll_characteristics, .type = PLL_TYPE_DIV, .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE, .eid = PMC_ETHPLL, }, }, }; /* * Master clock (MCK[1..4]) description * @eparents: extra parents names array * @eparents_chg_id: index in parents array that specifies the changeable * parent * @eparents_count: extra parents count * @eparents_mux_table: mux table for extra parents * @id: clock id * @eid: export index in sama7g5->chws[] array */ struct sama7g5_mck { const char *name; const char *eparents[4]; int eparents_chg_id; uint8_t eparents_count; uint8_t eparents_mux_table[4]; uint8_t id; uint8_t eid; }; static const struct sama7g5_mck sama7g5_mckx[] = { { .name = "mck1", .id = 1, .eparents = { "syspll_divpmcck", }, .eparents_mux_table = { 5, }, .eparents_count = 1, .eparents_chg_id = INT_MIN, .eid = PMC_MCK1, }, { .name = "mck2", .id = 2, .eparents = { "ddrpll_divpmcck", }, .eparents_mux_table = { 6, }, .eparents_count = 1, .eparents_chg_id = INT_MIN, }, { .name = "mck3", .id = 3, .eparents = { "syspll_divpmcck", "ddrpll_divpmcck", "imgpll_divpmcck", }, .eparents_mux_table = { 5, 6, 7, }, .eparents_count = 3, .eparents_chg_id = 5, }, { .name = "mck4", .id = 4, .eparents = { "syspll_divpmcck", }, .eparents_mux_table = { 5, }, .eparents_count = 1, .eparents_chg_id = INT_MIN, }, }; /* System clock description */ static const struct { const char *name; const char *parent; uint8_t id; } sama7g5_systemck[] = { { .name = "pck0", .parent = "prog0", .id = 8, }, { .name = "pck1", .parent = "prog1", .id = 9, }, { .name = "pck2", .parent = "prog2", .id = 10, }, { .name = "pck3", .parent = "prog3", .id = 11, }, { .name = "pck4", .parent = "prog4", .id = 12, }, { .name = "pck5", .parent = "prog5", .id = 13, }, { .name = "pck6", .parent = "prog6", .id = 14, }, { .name = "pck7", .parent = "prog7", .id = 15, }, }; /* Peripheral clock description */ static const struct { const char *name; const char *parent; struct clk_range output; uint8_t id; } peri_clks[] = { { .name = "pioA_clk", .parent = "mck0", .id = 11, }, { .name = "securam_clk", .parent = "mck0", .id = 18, }, { .name = "sfr_clk", .parent = "mck1", .id = 19, }, { .name = "hsmc_clk", .parent = "mck1", .id = 21, }, { .name = "xdmac0_clk", .parent = "mck1", .id = 22, }, { .name = "xdmac1_clk", .parent = "mck1", .id = 23, }, { .name = "xdmac2_clk", .parent = "mck1", .id = 24, }, { .name = "acc_clk", .parent = "mck1", .id = 25, }, { .name = "aes_clk", .parent = "mck1", .id = 27, }, { .name = "tzaesbasc_clk", .parent = "mck1", .id = 28, }, { .name = "asrc_clk", .parent = "mck1", .id = 30, .output = { .max = 200000000, }, }, { .name = "cpkcc_clk", .parent = "mck0", .id = 32, }, { .name = "csi_clk", .parent = "mck3", .id = 33, .output = { .max = 266000000, }, }, { .name = "csi2dc_clk", .parent = "mck3", .id = 34, .output = { .max = 266000000, }, }, { .name = "eic_clk", .parent = "mck1", .id = 37, }, { .name = "flex0_clk", .parent = "mck1", .id = 38, }, { .name = "flex1_clk", .parent = "mck1", .id = 39, }, { .name = "flex2_clk", .parent = "mck1", .id = 40, }, { .name = "flex3_clk", .parent = "mck1", .id = 41, }, { .name = "flex4_clk", .parent = "mck1", .id = 42, }, { .name = "flex5_clk", .parent = "mck1", .id = 43, }, { .name = "flex6_clk", .parent = "mck1", .id = 44, }, { .name = "flex7_clk", .parent = "mck1", .id = 45, }, { .name = "flex8_clk", .parent = "mck1", .id = 46, }, { .name = "flex9_clk", .parent = "mck1", .id = 47, }, { .name = "flex10_clk", .parent = "mck1", .id = 48, }, { .name = "flex11_clk", .parent = "mck1", .id = 49, }, { .name = "gmac0_clk", .parent = "mck1", .id = 51, }, { .name = "gmac1_clk", .parent = "mck1", .id = 52, }, { .name = "icm_clk", .parent = "mck1", .id = 55, }, { .name = "isc_clk", .parent = "mck3", .id = 56, .output = { .max = 266000000, }, }, { .name = "i2smcc0_clk", .parent = "mck1", .id = 57, .output = { .max = 200000000, }, }, { .name = "i2smcc1_clk", .parent = "mck1", .id = 58, .output = { .max = 200000000, }, }, { .name = "matrix_clk", .parent = "mck1", .id = 60, }, { .name = "mcan0_clk", .parent = "mck1", .id = 61, .output = { .max = 200000000, }, }, { .name = "mcan1_clk", .parent = "mck1", .id = 62, .output = { .max = 200000000, }, }, { .name = "mcan2_clk", .parent = "mck1", .id = 63, .output = { .max = 200000000, }, }, { .name = "mcan3_clk", .parent = "mck1", .id = 64, .output = { .max = 200000000, }, }, { .name = "mcan4_clk", .parent = "mck1", .id = 65, .output = { .max = 200000000, }, }, { .name = "mcan5_clk", .parent = "mck1", .id = 66, .output = { .max = 200000000, }, }, { .name = "pdmc0_clk", .parent = "mck1", .id = 68, .output = { .max = 200000000, }, }, { .name = "pdmc1_clk", .parent = "mck1", .id = 69, .output = { .max = 200000000, }, }, { .name = "pit64b0_clk", .parent = "mck1", .id = 70, }, { .name = "pit64b1_clk", .parent = "mck1", .id = 71, }, { .name = "pit64b2_clk", .parent = "mck1", .id = 72, }, { .name = "pit64b3_clk", .parent = "mck1", .id = 73, }, { .name = "pit64b4_clk", .parent = "mck1", .id = 74, }, { .name = "pit64b5_clk", .parent = "mck1", .id = 75, }, { .name = "pwm_clk", .parent = "mck1", .id = 77, }, { .name = "qspi0_clk", .parent = "mck1", .id = 78, }, { .name = "qspi1_clk", .parent = "mck1", .id = 79, }, { .name = "sdmmc0_clk", .parent = "mck1", .id = 80, }, { .name = "sdmmc1_clk", .parent = "mck1", .id = 81, }, { .name = "sdmmc2_clk", .parent = "mck1", .id = 82, }, { .name = "sha_clk", .parent = "mck1", .id = 83, }, { .name = "spdifrx_clk", .parent = "mck1", .id = 84, .output = { .max = 200000000, }, }, { .name = "spdiftx_clk", .parent = "mck1", .id = 85, .output = { .max = 200000000, }, }, { .name = "ssc0_clk", .parent = "mck1", .id = 86, .output = { .max = 200000000, }, }, { .name = "ssc1_clk", .parent = "mck1", .id = 87, .output = { .max = 200000000, }, }, { .name = "tcb0_ch0_clk", .parent = "mck1", .id = 88, .output = { .max = 200000000, }, }, { .name = "tcb0_ch1_clk", .parent = "mck1", .id = 89, .output = { .max = 200000000, }, }, { .name = "tcb0_ch2_clk", .parent = "mck1", .id = 90, .output = { .max = 200000000, }, }, { .name = "tcb1_ch0_clk", .parent = "mck1", .id = 91, .output = { .max = 200000000, }, }, { .name = "tcb1_ch1_clk", .parent = "mck1", .id = 92, .output = { .max = 200000000, }, }, { .name = "tcb1_ch2_clk", .parent = "mck1", .id = 93, .output = { .max = 200000000, }, }, { .name = "tcpca_clk", .parent = "mck1", .id = 94, }, { .name = "tcpcb_clk", .parent = "mck1", .id = 95, }, { .name = "tdes_clk", .parent = "mck1", .id = 96, }, { .name = "trng_clk", .parent = "mck1", .id = 97, }, { .name = "udphsa_clk", .parent = "mck1", .id = 104, }, { .name = "udphsb_clk", .parent = "mck1", .id = 105, }, { .name = "uhphs_clk", .parent = "mck1", .id = 106, }, }; /* UTMI clock description */ static struct { const char *name; const char *parent; uint8_t id; } sama7_utmick[] = { { .name = "utmi1", .parent = "utmick", .id = 0, }, { .name = "utmi2", .parent = "utmi1", .id = 1, }, { .name = "utmi3", .parent = "utmi1", .id = 2, }, }; /* Generic clock description */ struct sama7g5_gck { const char *name; const char *parents[8]; const char parents_mux_table[8]; struct clk_range output; int parents_chg_id; /* id in parent array of changeable PLL parent */ uint8_t parents_count; uint8_t id; }; static const struct sama7g5_gck sama7g5_gcks[] = { { .name = "adc_gclk", .id = 26, .output = { .max = 100000000, }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 7, 9, }, .parents_count = 3, .parents_chg_id = INT_MIN, }, { .name = "asrc_gclk", .id = 30, .output = { .max = 200000000 }, .parents = { "audiopll_divck", }, .parents_mux_table = { 9, }, .parents_count = 1, .parents_chg_id = INT_MIN, }, { .name = "csi_gclk", .id = 33, .output = { .max = 27000000 }, .parents = { "ddrpll_divpmcck", "imgpll_divpmcck", }, .parents_mux_table = { 6, 7, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex0_gclk", .id = 38, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex1_gclk", .id = 39, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex2_gclk", .id = 40, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex3_gclk", .id = 41, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex4_gclk", .id = 42, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex5_gclk", .id = 43, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex6_gclk", .id = 44, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex7_gclk", .id = 45, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex8_gclk", .id = 46, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex9_gclk", .id = 47, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex10_gclk", .id = 48, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "flex11_gclk", .id = 49, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "gmac0_gclk", .id = 51, .output = { .max = 125000000 }, .parents = { "ethpll_divpmcck", }, .parents_mux_table = { 10, }, .parents_count = 1, .parents_chg_id = 3, }, { .name = "gmac1_gclk", .id = 52, .output = { .max = 50000000 }, .parents = { "ethpll_divpmcck", }, .parents_mux_table = { 10, }, .parents_count = 1, .parents_chg_id = INT_MIN, }, { .name = "gmac0_tsu_gclk", .id = 53, .output = { .max = 300000000 }, .parents = { "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 9, 10, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "gmac1_tsu_gclk", .id = 54, .output = { .max = 300000000 }, .parents = { "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 9, 10, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "i2smcc0_gclk", .id = 57, .output = { .max = 100000000 }, .parents = { "syspll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 9, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "i2smcc1_gclk", .id = 58, .output = { .max = 100000000 }, .parents = { "syspll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 9, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "mcan0_gclk", .id = 61, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "mcan1_gclk", .id = 62, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "mcan2_gclk", .id = 63, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "mcan3_gclk", .id = 64, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "mcan4_gclk", .id = 65, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "mcan5_gclk", .id = 66, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "pdmc0_gclk", .id = 68, .output = { .max = 50000000 }, .parents = { "syspll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 9, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "pdmc1_gclk", .id = 69, .output = { .max = 50000000, }, .parents = { "syspll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 9, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "pit64b0_gclk", .id = 70, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "pit64b1_gclk", .id = 71, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "pit64b2_gclk", .id = 72, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "pit64b3_gclk", .id = 73, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "pit64b4_gclk", .id = 74, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "pit64b5_gclk", .id = 75, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "qspi0_gclk", .id = 78, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "qspi1_gclk", .id = 79, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "sdmmc0_gclk", .id = 80, .output = { .max = 208000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = 4, }, { .name = "sdmmc1_gclk", .id = 81, .output = { .max = 208000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = 4, }, { .name = "sdmmc2_gclk", .id = 82, .output = { .max = 208000000 }, .parents = { "syspll_divpmcck", "baudpll_divpmcck", }, .parents_mux_table = { 5, 8, }, .parents_count = 2, .parents_chg_id = 4, }, { .name = "spdifrx_gclk", .id = 84, .output = { .max = 150000000 }, .parents = { "syspll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 9, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "spdiftx_gclk", .id = 85, .output = { .max = 25000000 }, .parents = { "syspll_divpmcck", "audiopll_divck", }, .parents_mux_table = { 5, 9, }, .parents_count = 2, .parents_chg_id = INT_MIN, }, { .name = "tcb0_ch0_gclk", .id = 88, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "tcb1_ch0_gclk", .id = 91, .output = { .max = 200000000 }, .parents = { "syspll_divpmcck", "imgpll_divpmcck", "baudpll_divpmcck", "audiopll_divck", "ethpll_divpmcck", }, .parents_mux_table = { 5, 7, 8, 9, 10, }, .parents_count = 5, .parents_chg_id = INT_MIN, }, { .name = "tcpca_gclk", .id = 94, .output = { .max = 32768, }, .parents_chg_id = INT_MIN, }, { .name = "tcpcb_gclk", .id = 95, .output = { .max = 32768, }, .parents_chg_id = INT_MIN, }, }; /* MCK0 characteristics */ static const struct clk_master_charac mck0_characteristics = { .output = { .min = 32768, .max = 200000000 }, .divisors = { 1, 2, 4, 3, 5 }, .have_div3_pres = 1, }; /* MCK0 layout */ static const struct clk_master_layout mck0_layout = { .mask = 0x773, .pres_shift = 4, .offset = 0x28, }; /* Peripheral clock layout */ static const struct clk_pcr_layout sama7g5_pcr_layout = { .offset = 0x88, .cmd = BIT(31), .div_mask = GENMASK_32(27, 20), .gckcss_mask = GENMASK_32(12, 8), .pid_mask = GENMASK_32(6, 0), }; static const struct clk_programmable_layout sama7g5_prog_layout = { .pres_mask = 0xff, .pres_shift = 8, .css_mask = GENMASK_32(4, 0), .have_slck_mck = 0, .is_pres_direct = 1, }; static const struct { const char *name; uint8_t id; } sama7g5_progck[] = { { .name = "prog0", .id = 0 }, { .name = "prog1", .id = 1 }, { .name = "prog2", .id = 2 }, { .name = "prog3", .id = 3 }, { .name = "prog4", .id = 4 }, { .name = "prog5", .id = 5 }, { .name = "prog6", .id = 6 }, { .name = "prog7", .id = 7 }, }; static struct pmc_data *sama7g5_pmc; vaddr_t at91_pmc_get_base(void) { assert(sama7g5_pmc); return sama7g5_pmc->base; } TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx, struct clk **clk) { return pmc_clk_get(sama7g5_pmc, type, idx, clk); } static TEE_Result pmc_setup_sama7g5(const void *fdt, int nodeoffset, const void *data __unused) { struct clk *pll_frac_clk[PLL_ID_MAX] = { }; struct clk *pll_div_clk[PLL_ID_MAX] = { }; TEE_Result res = TEE_ERROR_GENERIC; const uint32_t *fdt_prop = NULL; struct pmc_clk *pmc_clk = NULL; struct clk *parents[11] = { }; struct clk *main_xtal_clk = NULL; struct clk *main_rc_osc = NULL; struct clk *main_osc = NULL; struct clk *mck0_clk = NULL; struct clk *main_clk = NULL; struct clk *md_slck = NULL; struct clk *td_slck = NULL; struct clk *parent = NULL; struct clk *clk = NULL; unsigned int i = 0; unsigned int j = 0; vaddr_t base = 0; size_t size = 0; int bypass = 0; if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0) panic(); if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC) matrix_configure_periph_secure(ID_PMC); res = clk_dt_get_by_name(fdt, nodeoffset, "md_slck", &md_slck); if (res) return res; res = clk_dt_get_by_name(fdt, nodeoffset, "td_slck", &td_slck); if (res) return res; res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk); if (res) return res; sama7g5_pmc = pmc_data_allocate(PMC_SAMA7G5_CORE_CLK_COUNT, ARRAY_SIZE(sama7g5_systemck), ARRAY_SIZE(peri_clks), ARRAY_SIZE(sama7g5_gcks), 8); if (!sama7g5_pmc) panic(); sama7g5_pmc->base = base; main_rc_osc = pmc_register_main_rc_osc(sama7g5_pmc, "main_rc_osc", 12000000); if (!main_rc_osc) panic(); fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL); if (fdt_prop) bypass = fdt32_to_cpu(*fdt_prop); main_osc = pmc_register_main_osc(sama7g5_pmc, "main_osc", main_xtal_clk, bypass); if (!main_osc) panic(); parents[0] = main_rc_osc; parents[1] = main_osc; main_clk = at91_clk_register_sam9x5_main(sama7g5_pmc, "mainck", parents, 2); if (!main_clk) panic(); pmc_clk = &sama7g5_pmc->chws[PMC_MAIN]; pmc_clk->clk = main_clk; pmc_clk->id = PMC_MAIN; for (i = 0; i < PLL_ID_MAX; i++) { struct pmc_data *pmc = sama7g5_pmc; const struct sama7g5_pll *p = NULL; for (j = 0; j < 3; j++) { p = &sama7g5_plls[i][j]; if (!p->name) continue; switch (p->type) { case PLL_TYPE_FRAC: if (!strcmp(p->parent, "mainck")) parent = main_clk; else if (!strcmp(p->parent, "main_xtal")) parent = main_xtal_clk; else parent = pmc_clk_get_by_name(pmc->chws, pmc->ncore, p->parent); assert(parent); clk = sam9x60_clk_register_frac_pll(sama7g5_pmc, p->name, parent, i, p->charac, p->layout, p->flags); pll_frac_clk[i] = clk; break; case PLL_TYPE_DIV: parent = clk; clk = sam9x60_clk_register_div_pll(sama7g5_pmc, p->name, parent, i, p->charac, p->layout, p->flags, p->safe_div); break; default: continue; } if (!clk) panic(); if (p->eid) { sama7g5_pmc->chws[p->eid].clk = clk; sama7g5_pmc->chws[p->eid].id = p->eid; } } p = &sama7g5_plls[i][PLL_TYPE_DIV]; pll_div_clk[i] = sama7g5_pmc->chws[p->eid].clk; } parents[0] = md_slck; parents[1] = main_clk; parents[2] = pll_div_clk[PLL_ID_CPU]; parents[3] = pll_div_clk[PLL_ID_SYS]; clk = at91_clk_register_master_pres(sama7g5_pmc, "fclk", 4, parents, &mck0_layout, &mck0_characteristics, INT_MIN); if (!clk) panic(); pmc_clk = &sama7g5_pmc->chws[PMC_MCK_PRES]; pmc_clk->clk = clk; pmc_clk->id = PMC_MCK_PRES; mck0_clk = at91_clk_register_master_div(sama7g5_pmc, "mck0", clk, &mck0_layout, &mck0_characteristics); if (!mck0_clk) panic(); pmc_clk = &sama7g5_pmc->chws[PMC_MCK]; pmc_clk->clk = mck0_clk; pmc_clk->id = PMC_MCK; parents[0] = md_slck; parents[1] = td_slck; parents[2] = main_clk; parents[3] = mck0_clk; for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) { const struct sama7g5_mck *mck = &sama7g5_mckx[i]; uint8_t num_parents = 4 + mck->eparents_count; uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table)); if (!mux_table) panic(); mux_table[0] = 0; mux_table[1] = 1; mux_table[2] = 2; mux_table[3] = 3; for (j = 0; j < mck->eparents_count; j++) { parents[4 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws, sama7g5_pmc->ncore, mck->eparents[j]); assert(parents[4 + j]); mux_table[4 + j] = mck->eparents_mux_table[j]; } clk = at91_clk_sama7g5_register_master(sama7g5_pmc, mck->name, num_parents, parents, mux_table, mck->id, mck->eparents_chg_id); if (!clk) panic(); sama7g5_pmc->chws[PMC_MCK1 + i].clk = clk; } clk = at91_clk_sama7g5_register_utmi(sama7g5_pmc, "utmick", main_clk); if (!clk) panic(); sama7g5_pmc->chws[PMC_UTMI].clk = clk; sama7g5_pmc->chws[PMC_UTMI].id = PMC_UTMI; for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) { if (strcmp("utmick", sama7_utmick[i].parent) == 0) parent = clk; else if (strcmp("utmi1", sama7_utmick[i].parent) == 0) parent = sama7g5_pmc->chws[PMC_UTMI1].clk; else panic(); clk = sama7_utmi_clk_register(sama7_utmick[i].name, parent, sama7_utmick[i].id); if (!clk) panic(); pmc_clk = &sama7g5_pmc->chws[PMC_UTMI1 + i]; pmc_clk->clk = clk; pmc_clk->id = PMC_UTMI1 + i; } parents[0] = md_slck; parents[1] = td_slck; parents[2] = main_clk; parents[3] = pll_div_clk[PLL_ID_SYS]; parents[4] = pll_div_clk[PLL_ID_DDR]; parents[5] = pll_div_clk[PLL_ID_IMG]; parents[6] = pll_div_clk[PLL_ID_BAUD]; parents[7] = pll_div_clk[PLL_ID_AUDIO]; parents[8] = pll_div_clk[PLL_ID_ETH]; for (i = 0; i < ARRAY_SIZE(sama7g5_progck); i++) { clk = at91_clk_register_programmable(sama7g5_pmc, sama7g5_progck[i].name, parents, 9, i, &sama7g5_prog_layout); if (!clk) panic(); pmc_clk = &sama7g5_pmc->pchws[i]; pmc_clk->clk = clk; pmc_clk->id = sama7g5_progck[i].id; } for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) { clk = at91_clk_register_system(sama7g5_pmc, sama7g5_systemck[i].name, sama7g5_pmc->pchws[i].clk, sama7g5_systemck[i].id); if (!clk) panic(); pmc_clk = &sama7g5_pmc->shws[i]; pmc_clk->clk = clk; pmc_clk->id = sama7g5_systemck[i].id; } for (i = 0; i < ARRAY_SIZE(peri_clks); i++) { parent = pmc_clk_get_by_name(sama7g5_pmc->chws, sama7g5_pmc->ncore, peri_clks[i].parent); clk = at91_clk_register_sam9x5_periph(sama7g5_pmc, &sama7g5_pcr_layout, peri_clks[i].name, parent, peri_clks[i].id, &peri_clks[i].output); if (!clk) panic(); pmc_clk = &sama7g5_pmc->phws[i]; pmc_clk->clk = clk; pmc_clk->id = peri_clks[i].id; } parents[0] = md_slck; parents[1] = td_slck; parents[2] = main_clk; for (i = 0; i < ARRAY_SIZE(sama7g5_gcks); i++) { const struct sama7g5_gck *gck = sama7g5_gcks + i; uint8_t num_parents = 3 + gck->parents_count; uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table)); if (!mux_table) panic(); mux_table[0] = 0; mux_table[1] = 1; mux_table[2] = 2; for (j = 0; j < gck->parents_count; j++) { parents[3 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws, sama7g5_pmc->ncore, gck->parents[j]); assert(parents[3 + j]); mux_table[3 + j] = gck->parents_mux_table[j]; } clk = at91_clk_register_generated(sama7g5_pmc, &sama7g5_pcr_layout, gck->name, parents, mux_table, num_parents, gck->id, &gck->output, gck->parents_chg_id); if (!clk) panic(); pmc_clk = &sama7g5_pmc->ghws[i]; pmc_clk->clk = clk; pmc_clk->id = gck->id; } res = clk_set_rate(pll_frac_clk[PLL_ID_ETH], 625000000); if (res) panic(); res = clk_set_rate(pll_div_clk[PLL_ID_ETH], 625000000); if (res) panic(); res = clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get, sama7g5_pmc); if (res) panic(); pmc_register_pm(); return TEE_SUCCESS; } CLK_DT_DECLARE(sama7g5_clk, "microchip,sama7g5-pmc", pmc_setup_sama7g5); optee_os-4.3.0/core/drivers/clk/sam/sub.mk000066400000000000000000000007431464416617300204340ustar00rootroot00000000000000global-incdirs-y += . srcs-y += at91_sckc.c at91_main.c at91_pmc.c srcs-y += at91_utmi.c at91_master.c srcs-y += at91_programmable.c at91_system.c at91_peripheral.c srcs-y += at91_generated.c srcs-y += at91_cpu_opp.c srcs-$(CFG_SAMA5D2) += at91_pll.c at91_plldiv.c srcs-$(CFG_SAMA5D2) += at91_h32mx.c at91_usb.c srcs-$(CFG_SAMA5D2) += at91_i2s_mux.c at91_audio_pll.c srcs-$(CFG_SAMA5D2) += sama5d2_clk.c srcs-$(CFG_SAMA7G5) += clk-sam9x60-pll.c phy-sama7-utmi-clk.c sama7g5_clk.c optee_os-4.3.0/core/drivers/clk/sub.mk000066400000000000000000000005021464416617300176450ustar00rootroot00000000000000srcs-y += clk.c srcs-$(CFG_DRIVERS_CLK_DT) += clk_dt.c srcs-$(CFG_DRIVERS_CLK_FIXED) += fixed_clk.c srcs-$(CFG_STM32MP_CLK_CORE) += clk-stm32-core.c srcs-$(CFG_STM32MP13_CLK) += clk-stm32mp13.c srcs-$(CFG_STM32MP15_CLK) += clk-stm32mp15.c srcs-$(CFG_STM32MP25_CLK) += clk-stm32mp25.c subdirs-$(CFG_DRIVERS_SAM_CLK) += samoptee_os-4.3.0/core/drivers/crypto/000077500000000000000000000000001464416617300172755ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/aspeed/000077500000000000000000000000001464416617300205365ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/aspeed/crypto_ast2600.c000066400000000000000000000021631464416617300234030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Aspeed Technology Inc. */ #include #include #include #include #include #include #include #include "hace_ast2600.h" #define SCU_RST1 0x40 #define SCU_RSTCLR1 0x44 #define SCU_RST_CRYPTO BIT(4) #define SCU_CLKGATE1 0x80 #define SCU_CLKGATECLR1 0x84 #define SCU_CLKGATE_HACE BIT(13) static TEE_Result crypto_ast2600_init(void) { TEE_Result rc = TEE_ERROR_GENERIC; vaddr_t scu_virt = 0; scu_virt = core_mmu_get_va(SCU_BASE, MEM_AREA_IO_NSEC, SMALL_PAGE_SIZE); if (!scu_virt) panic(); /* ast2600 crypto engines share the same reset control */ io_write32(scu_virt + SCU_RST1, SCU_RST_CRYPTO); udelay(100); io_write32(scu_virt + SCU_RSTCLR1, SCU_RST_CRYPTO); if (IS_ENABLED(CFG_CRYPTO_DRV_HASH)) { io_write32(scu_virt + SCU_CLKGATECLR1, SCU_CLKGATE_HACE); rc = ast2600_drvcrypt_register_hash(); if (rc) { EMSG("cannot register hash driver, rc=%d", rc); return rc; } } return TEE_SUCCESS; } early_init_late(crypto_ast2600_init); optee_os-4.3.0/core/drivers/crypto/aspeed/hace_ast2600.c000066400000000000000000000227771464416617300230000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Aspeed Technology Inc. */ #include #include #include #include #include #include #include #include #include #include #include "hace_ast2600.h" #define HACE_BASE 0x1e6d0000 /* register offsets and bit fields */ #define HACE_STS 0x1C #define HACE_STS_HASH_INT BIT(9) #define HACE_STS_HASH_BUSY BIT(0) #define HACE_HASH_DATA 0x20 #define HACE_HASH_DIGEST 0x24 #define HACE_HASH_HMAC_KEY 0x28 #define HACE_HASH_DATA_LEN 0x2C #define HACE_HASH_CMD 0x30 #define HACE_HASH_CMD_ACCUM BIT(8) #define HACE_HASH_CMD_ALG_SHA1 BIT(5) #define HACE_HASH_CMD_ALG_SHA256 (BIT(6) | BIT(4)) #define HACE_HASH_CMD_ALG_SHA384 (BIT(10) | BIT(6) | BIT(5)) #define HACE_HASH_CMD_ALG_SHA512 (BIT(6) | BIT(5)) #define HACE_HASH_CMD_SHA_BE BIT(3) /* buffer size based on SHA-512 need */ #define HASH_BLK_BUFSZ 128 #define HASH_DGT_BUFSZ 64 register_phys_mem(MEM_AREA_IO_SEC, HACE_BASE, SMALL_PAGE_SIZE); struct ast2600_hace_ctx { struct crypto_hash_ctx hash_ctx; uint32_t cmd; uint32_t algo; uint32_t dgt_size; uint32_t blk_size; uint32_t pad_size; uint64_t total[2]; /* DMA memory to interact with HACE */ uint8_t *buf; uint8_t *digest; }; static vaddr_t hace_virt; struct mutex hace_mtx = MUTEX_INITIALIZER; static const uint32_t iv_sha1[8] = { 0x01234567, 0x89abcdef, 0xfedcba98, 0x76543210, 0xf0e1d2c3, 0, 0, 0 }; static const uint32_t iv_sha256[8] = { 0x67e6096a, 0x85ae67bb, 0x72f36e3c, 0x3af54fa5, 0x7f520e51, 0x8c68059b, 0xabd9831f, 0x19cde05b }; static const uint32_t iv_sha384[16] = { 0x5d9dbbcb, 0xd89e05c1, 0x2a299a62, 0x07d57c36, 0x5a015991, 0x17dd7030, 0xd8ec2f15, 0x39590ef7, 0x67263367, 0x310bc0ff, 0x874ab48e, 0x11155868, 0x0d2e0cdb, 0xa78ff964, 0x1d48b547, 0xa44ffabe }; static const uint32_t iv_sha512[16] = { 0x67e6096a, 0x08c9bcf3, 0x85ae67bb, 0x3ba7ca84, 0x72f36e3c, 0x2bf894fe, 0x3af54fa5, 0xf1361d5f, 0x7f520e51, 0xd182e6ad, 0x8c68059b, 0x1f6c3e2b, 0xabd9831f, 0x6bbd41fb, 0x19cde05b, 0x79217e13 }; static TEE_Result ast2600_hace_process(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { TEE_Result rc = TEE_ERROR_GENERIC; uint32_t sts = 0; uint64_t tref = 0; paddr_t data_phys = 0; paddr_t digest_phys = 0; struct ast2600_hace_ctx *hctx = NULL; mutex_lock(&hace_mtx); hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); sts = io_read32(hace_virt + HACE_STS); if (sts & HACE_STS_HASH_BUSY) { rc = TEE_ERROR_BUSY; goto out; } cache_operation(TEE_CACHEFLUSH, (void *)data, len); data_phys = virt_to_phys((void *)data); digest_phys = virt_to_phys(hctx->digest); io_write32(hace_virt + HACE_HASH_DATA, (uint32_t)data_phys); io_write32(hace_virt + HACE_HASH_DIGEST, (uint32_t)digest_phys); io_write32(hace_virt + HACE_HASH_HMAC_KEY, (uint32_t)digest_phys); io_write32(hace_virt + HACE_HASH_DATA_LEN, len); io_write32(hace_virt + HACE_HASH_CMD, hctx->cmd); /* poll for completion */ tref = timeout_init_us(1000 + (len >> 3)); do { sts = io_read32(hace_virt + HACE_STS); if (timeout_elapsed(tref)) { rc = TEE_ERROR_TARGET_DEAD; goto out; } } while (!(sts & HACE_STS_HASH_INT)); io_write32(hace_virt + HACE_STS, HACE_STS_HASH_INT); rc = TEE_SUCCESS; out: mutex_unlock(&hace_mtx); return rc; } static TEE_Result ast2600_hace_init(struct crypto_hash_ctx *ctx) { struct ast2600_hace_ctx *hctx = NULL; hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); switch (hctx->algo) { case TEE_ALG_SHA1: memcpy(hctx->digest, iv_sha1, sizeof(iv_sha1)); break; case TEE_ALG_SHA256: memcpy(hctx->digest, iv_sha256, sizeof(iv_sha256)); break; case TEE_ALG_SHA384: memcpy(hctx->digest, iv_sha384, sizeof(iv_sha384)); break; case TEE_ALG_SHA512: memcpy(hctx->digest, iv_sha512, sizeof(iv_sha512)); break; default: return TEE_ERROR_NOT_SUPPORTED; } hctx->total[0] = 0; hctx->total[1] = 0; cache_operation(TEE_CACHEFLUSH, hctx->digest, HASH_DGT_BUFSZ); return TEE_SUCCESS; } static TEE_Result ast2600_hace_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { TEE_Result rc = TEE_ERROR_GENERIC; uint32_t left = 0; uint32_t fill = 0; size_t blk_size = 0; struct ast2600_hace_ctx *hctx = NULL; if (!ctx || !data || !len) return TEE_ERROR_BAD_PARAMETERS; hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); blk_size = hctx->blk_size; left = hctx->total[0] & (blk_size - 1); fill = blk_size - left; hctx->total[0] += len; if (hctx->total[0] < len) hctx->total[1]++; if (left && len >= fill) { memcpy(hctx->buf + left, data, fill); rc = ast2600_hace_process(ctx, hctx->buf, blk_size); if (rc) return rc; data += fill; len -= fill; left = 0; } while (len >= blk_size) { memcpy(hctx->buf, data, blk_size); rc = ast2600_hace_process(ctx, hctx->buf, blk_size); if (rc) return rc; data += blk_size; len -= blk_size; } if (len) memcpy(hctx->buf + left, data, len); return TEE_SUCCESS; } static TEE_Result ast2600_hace_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { TEE_Result rc = TEE_ERROR_GENERIC; uint32_t last = 0; uint32_t padn = 0; uint8_t pad[HASH_BLK_BUFSZ * 2] = { }; uint64_t dbits[2] = { }; uint64_t dbits_be[2] = { }; struct ast2600_hace_ctx *hctx = NULL; size_t length = 0; hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); length = MIN(len, hctx->dgt_size); memset(pad, 0, sizeof(pad)); pad[0] = 0x80; dbits[0] = (hctx->total[0] << 3); dbits_be[0] = get_be64(&dbits[0]); dbits[1] = (hctx->total[0] >> 61) | (hctx->total[1] << 3); dbits_be[1] = get_be64(&dbits[1]); last = hctx->total[0] & (hctx->blk_size - 1); switch (hctx->algo) { case TEE_ALG_SHA1: case TEE_ALG_SHA256: if (last < 56) padn = 56 - last; else padn = 120 - last; rc = ast2600_hace_update(ctx, pad, padn); if (rc) return rc; rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[0], sizeof(dbits_be[0])); if (rc) return rc; break; case TEE_ALG_SHA384: case TEE_ALG_SHA512: if (last < 112) padn = 112 - last; else padn = 240 - last; rc = ast2600_hace_update(ctx, pad, padn); if (rc) return rc; rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[1], sizeof(dbits_be[1])); if (rc) return rc; rc = ast2600_hace_update(ctx, (uint8_t *)&dbits_be[0], sizeof(dbits_be[0])); if (rc) return rc; break; default: return TEE_ERROR_NOT_SUPPORTED; } cache_operation(TEE_CACHEINVALIDATE, hctx->digest, HASH_DGT_BUFSZ); memcpy(digest, hctx->digest, length); return TEE_SUCCESS; } static void ast2600_hace_free(struct crypto_hash_ctx *ctx) { struct ast2600_hace_ctx *hctx = NULL; hctx = container_of(ctx, struct ast2600_hace_ctx, hash_ctx); free(hctx->buf); free(hctx->digest); free(hctx); } static void ast2600_hace_copy_state(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx) { struct ast2600_hace_ctx *src_hctx = NULL; struct ast2600_hace_ctx *dst_hctx = NULL; src_hctx = container_of(src_ctx, struct ast2600_hace_ctx, hash_ctx); dst_hctx = container_of(dst_ctx, struct ast2600_hace_ctx, hash_ctx); dst_hctx->hash_ctx = src_hctx->hash_ctx; dst_hctx->cmd = src_hctx->cmd; dst_hctx->dgt_size = src_hctx->dgt_size; dst_hctx->blk_size = src_hctx->blk_size; dst_hctx->pad_size = src_hctx->pad_size; dst_hctx->total[0] = src_hctx->total[0]; dst_hctx->total[1] = src_hctx->total[1]; cache_operation(TEE_CACHEINVALIDATE, src_hctx->buf, HASH_BLK_BUFSZ); memcpy(dst_hctx->buf, src_hctx->buf, HASH_BLK_BUFSZ); cache_operation(TEE_CACHEFLUSH, dst_hctx->buf, HASH_BLK_BUFSZ); cache_operation(TEE_CACHEINVALIDATE, src_hctx->digest, HASH_DGT_BUFSZ); memcpy(dst_hctx->digest, src_hctx->digest, HASH_DGT_BUFSZ); cache_operation(TEE_CACHEFLUSH, dst_hctx->digest, HASH_DGT_BUFSZ); } static const struct crypto_hash_ops ast2600_hace_ops = { .init = ast2600_hace_init, .update = ast2600_hace_update, .final = ast2600_hace_final, .free_ctx = ast2600_hace_free, .copy_state = ast2600_hace_copy_state, }; static TEE_Result ast2600_hace_alloc(struct crypto_hash_ctx **pctx, uint32_t algo) { struct ast2600_hace_ctx *hctx = calloc(1, sizeof(*hctx)); if (!hctx) return TEE_ERROR_OUT_OF_MEMORY; hctx->buf = memalign(HASH_BLK_BUFSZ, HASH_BLK_BUFSZ); if (!hctx->buf) return TEE_ERROR_OUT_OF_MEMORY; hctx->digest = memalign(HASH_DGT_BUFSZ, HASH_DGT_BUFSZ); if (!hctx->digest) return TEE_ERROR_OUT_OF_MEMORY; hctx->hash_ctx.ops = &ast2600_hace_ops; hctx->algo = algo; hctx->cmd = HACE_HASH_CMD_ACCUM | HACE_HASH_CMD_SHA_BE; switch (algo) { case TEE_ALG_SHA1: hctx->dgt_size = 20; hctx->blk_size = 64; hctx->pad_size = 8; hctx->cmd |= HACE_HASH_CMD_ALG_SHA1; break; case TEE_ALG_SHA256: hctx->dgt_size = 32; hctx->blk_size = 64; hctx->pad_size = 8; hctx->cmd |= HACE_HASH_CMD_ALG_SHA256; break; case TEE_ALG_SHA384: hctx->dgt_size = 48; hctx->blk_size = 128; hctx->pad_size = 16; hctx->cmd |= HACE_HASH_CMD_ALG_SHA384; break; case TEE_ALG_SHA512: hctx->dgt_size = 64; hctx->blk_size = 128; hctx->pad_size = 16; hctx->cmd |= HACE_HASH_CMD_ALG_SHA512; break; default: free(hctx); return TEE_ERROR_NOT_IMPLEMENTED; } *pctx = &hctx->hash_ctx; return TEE_SUCCESS; } TEE_Result ast2600_drvcrypt_register_hash(void) { hace_virt = core_mmu_get_va(HACE_BASE, MEM_AREA_IO_SEC, SMALL_PAGE_SIZE); if (!hace_virt) { EMSG("cannot get HACE virtual address"); return TEE_ERROR_GENERIC; } return drvcrypt_register_hash(ast2600_hace_alloc); } optee_os-4.3.0/core/drivers/crypto/aspeed/hace_ast2600.h000066400000000000000000000005671464416617300227760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Aspeed Technology Inc. */ #ifndef __HACE_AST2600_H__ #define __HACE_AST2600_H__ #include #ifdef CFG_CRYPTO_DRV_HASH TEE_Result ast2600_drvcrypt_register_hash(void); #else static inline TEE_Result ast2600_drvcrypt_register_hash(void) { return TEE_ERROR_NOT_SUPPORTED; } #endif #endif optee_os-4.3.0/core/drivers/crypto/aspeed/sub.mk000066400000000000000000000001611464416617300216560ustar00rootroot00000000000000ifeq ($(PLATFORM_FLAVOR),ast2600) srcs-y += crypto_ast2600.c srcs-$(CFG_CRYPTO_DRV_HASH) += hace_ast2600.c endif optee_os-4.3.0/core/drivers/crypto/caam/000077500000000000000000000000001464416617300201765ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/acipher/000077500000000000000000000000001464416617300216115ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_dh.c000066400000000000000000000323771464416617300233450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021, 2023 NXP * * Implementation of DH */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_CAAM_64BIT #define MAX_DESC_KEY_GEN 14 #define MAX_DESC_SHARED 14 #else #define MAX_DESC_KEY_GEN 9 #define MAX_DESC_SHARED 9 #endif /* * Definition of the local DH Keypair */ struct caam_dh_keypair { struct caambuf g; /* Generator */ struct caambuf p; /* Prime Number Modulus */ struct caamkey x; /* Private key */ struct caambuf y; /* Public key */ }; /* * Free local DH keypair * * @key DH keypair */ static void do_keypair_free(struct caam_dh_keypair *key) { caam_free_buf(&key->g); caam_free_buf(&key->p); caam_key_free(&key->x); caam_free_buf(&key->y); } /* * Convert Crypto DH Key p and g bignumbers to local buffers * (via keypair object). * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format */ static enum caam_status do_keypair_conv_p_g(struct caam_dh_keypair *outkey, const struct dh_keypair *inkey) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t p_size = 0; size_t field_size = 0; p_size = crypto_bignum_num_bytes(inkey->p); DH_TRACE("DH Convert Key Parameters (p,g) size %zu bytes", p_size); /* Prime Number Modulus */ retstatus = caam_calloc_buf(&outkey->p, p_size); if (retstatus != CAAM_NO_ERROR) return retstatus; crypto_bignum_bn2bin(inkey->p, outkey->p.data); cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); /* Generator */ retstatus = caam_calloc_buf(&outkey->g, p_size); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of g to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->g); crypto_bignum_bn2bin(inkey->g, outkey->g.data + p_size - field_size); cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); return CAAM_NO_ERROR; } /* * Convert Crypto DH Private Key to a local Private Key (via keypair object) * * @outkey [out] Output local keypair * @inkey Input Private key in TEE Crypto format */ static enum caam_status do_keypriv_conv(struct caam_dh_keypair *outkey, const struct dh_keypair *inkey) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t key_size = inkey->xbits / 8; size_t p_size = 0; if (!key_size) key_size = crypto_bignum_num_bytes(inkey->x); DH_TRACE("DH Convert Private Key size %zu bytes", key_size); /* Prime */ p_size = crypto_bignum_num_bytes(inkey->p); retstatus = caam_calloc_buf(&outkey->p, p_size); if (retstatus != CAAM_NO_ERROR) return retstatus; crypto_bignum_bn2bin(inkey->p, outkey->p.data); cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); /* Private Key X */ retstatus = caam_key_deserialize_from_bn(inkey->x, &outkey->x, 0); if (retstatus != CAAM_NO_ERROR) return retstatus; caam_key_cache_op(TEE_CACHECLEAN, &outkey->x); return CAAM_NO_ERROR; } /* * Convert Crypto DH Public Key to local Public Key (via a keypair object) * * @outkey [out] Output local keypair * @inkey Input Public key in TEE Crypto format */ static enum caam_status do_keypub_conv(struct caam_dh_keypair *outkey, const struct bignum *inkey) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t key_size = 0; key_size = crypto_bignum_num_bytes((struct bignum *)inkey); DH_TRACE("DH Convert Keypair size %zu bytes", key_size); /* Public Key Y */ retstatus = caam_calloc_buf(&outkey->y, key_size); if (retstatus != CAAM_NO_ERROR) return retstatus; crypto_bignum_bn2bin(inkey, outkey->y.data); cache_operation(TEE_CACHECLEAN, outkey->y.data, outkey->y.length); return CAAM_NO_ERROR; } /* * Allocate a TEE DH keypair. * Note: The subprime q is not used but it must be allocated to prevent * system referencing issues when object is destroyed. * * @key Keypair * @size_bits Key size in bits */ static TEE_Result do_allocate_keypair(struct dh_keypair *key, size_t size_bits) { DH_TRACE("Allocate Keypair of %zu bits", size_bits); /* Initialize the key fields to NULL */ memset(key, 0, sizeof(*key)); /* Allocate Generator Scalar */ key->g = crypto_bignum_allocate(size_bits); if (!key->g) goto err; /* Allocate Prime Number Modulus */ key->p = crypto_bignum_allocate(size_bits); if (!key->p) goto err; /* Allocate Private key X */ key->x = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->x) goto err; /* Allocate Public Key Y */ key->y = crypto_bignum_allocate(size_bits); if (!key->y) goto err; /* Allocate Subprime even if not used */ key->q = crypto_bignum_allocate(size_bits); if (!key->q) goto err; return TEE_SUCCESS; err: DH_TRACE("Allocation error"); crypto_bignum_free(&key->g); crypto_bignum_free(&key->p); crypto_bignum_free(&key->x); crypto_bignum_free(&key->y); return TEE_ERROR_OUT_OF_MEMORY; } /* * Generates an DH keypair * Keypair @key contains the input prime p and generator g values * The function calculates private x and public y, knowing that the * number of bits of x is either key_size if specified or p size. * * @key [in/out] Keypair * @q Sub Prime (not used) * @key_size Key size in bits multiple of 8 bits */ static TEE_Result do_gen_keypair(struct dh_keypair *key, struct bignum *q __unused, size_t key_size) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_dh_keypair caam_dh_key = { }; struct caambuf dh_r = { }; size_t n_bytes = key_size / 8; size_t l_bytes = 0; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; int counter = 0; enum caam_key_type key_type = caam_key_default_key_gen_type(); l_bytes = crypto_bignum_num_bytes(key->p); if (!l_bytes) return TEE_ERROR_BAD_PARAMETERS; /* * If @key_size not specified, private key size is * same as the public key size (same as prime size) */ if (!n_bytes) n_bytes = l_bytes; /* * CAAM private key support is limited to the descriptor PDB * N maximum value (PDB_DL_KEY_N_MASK) */ if (n_bytes > PDB_DL_KEY_N_MASK) n_bytes = PDB_DL_KEY_N_MASK; DH_TRACE("Request %zu bits key -> so do %zu bytes key", key_size, n_bytes); /* Allocate the job used to prepare the operation */ desc = caam_calloc_desc(MAX_DESC_KEY_GEN); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Allocate Private Key to be generated */ caam_dh_key.x.key_type = key_type; caam_dh_key.x.sec_size = n_bytes; caam_dh_key.x.is_blob = false; retstatus = caam_key_alloc(&caam_dh_key.x); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } caam_key_cache_op(TEE_CACHEFLUSH, &caam_dh_key.x); /* Allocate Public Key to be generated */ retstatus = caam_calloc_align_buf(&caam_dh_key.y, l_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } cache_operation(TEE_CACHEFLUSH, caam_dh_key.y.data, caam_dh_key.y.length); /* Allocate Private Key modulus (r) and fill it with one's */ retstatus = caam_calloc_buf(&dh_r, n_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } memset(dh_r.data, UINT8_MAX, dh_r.length); cache_operation(TEE_CACHECLEAN, dh_r.data, dh_r.length); /* Generator and Prime */ retstatus = do_keypair_conv_p_g(&caam_dh_key, key); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* * Build the descriptor using the PDB Public Key generation * block (PD=0) */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_DL_KEY_L_SIZE(l_bytes) | PDB_DL_KEY_N_SIZE(n_bytes)); caam_desc_add_ptr(desc, caam_dh_key.p.paddr); caam_desc_add_ptr(desc, dh_r.paddr); caam_desc_add_ptr(desc, caam_dh_key.g.paddr); caam_desc_add_ptr(desc, caam_dh_key.x.buf.paddr); caam_desc_add_ptr(desc, caam_dh_key.y.paddr); switch (key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); DH_DUMPDESC(desc); /* * If the Secure Key X doesn't have the correct size * retry a new generation. * Retry 10 times before returing an error to not lock the system. */ for (counter = 0; counter < 10; counter++) { memset(&jobctx, 0, sizeof(jobctx)); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dh_key.x); cache_operation(TEE_CACHEINVALIDATE, caam_dh_key.y.data, caam_dh_key.y.length); /* Copy Private and Public keypair */ ret = caam_key_serialize_to_bn(key->x, &caam_dh_key.x); if (ret != TEE_SUCCESS) goto out; if (crypto_bignum_num_bytes(key->x) != n_bytes) { DH_TRACE("Error X size=%zu expected %zu", crypto_bignum_num_bytes(key->x), n_bytes); DH_DUMPBUF("X", caam_dh_key.x.data, caam_dh_key.x.length); DH_DUMPBUF("Y", caam_dh_key.y.data, caam_dh_key.y.length); continue; } ret = crypto_bignum_bin2bn(caam_dh_key.y.data, caam_dh_key.y.length, key->y); if (ret != TEE_SUCCESS) goto out; /* Set the Private Key size in bits */ key->xbits = n_bytes * 8; ret = TEE_SUCCESS; goto out; } else { DH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); goto out; } } out: caam_free_desc(&desc); caam_free_buf(&dh_r); do_keypair_free(&caam_dh_key); return ret; } /* * Compute the shared secret data from DH Private key and Public Key * * @sdata [in/out] DH Shared Secret data */ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct dh_keypair *inkeypair = sdata->key_priv; struct caam_dh_keypair caam_dh_key = { }; struct caamdmaobj secret = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; uint32_t pdb_sgt_flags = 0; DH_TRACE("DH Shared Secret"); /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_SHARED); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* * ReAllocate the secret result buffer with a maximum size * of the secret size if not cache aligned */ ret = caam_dmaobj_output_sgtbuf(&secret, sdata->secret.data, sdata->secret.length, sdata->secret.length); if (ret) goto out; if (secret.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKDH_SECRET; caam_dmaobj_cache_push(&secret); /* Convert the Private key to local key */ retstatus = do_keypriv_conv(&caam_dh_key, inkeypair); if (retstatus != CAAM_NO_ERROR) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Convert the Public key to local key */ retstatus = do_keypub_conv(&caam_dh_key, sdata->key_pub); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* * Build the descriptor using PDB Shared Secret */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, pdb_sgt_flags | PDB_DL_KEY_L_SIZE(caam_dh_key.y.length) | PDB_DL_KEY_N_SIZE(caam_dh_key.x.sec_size)); /* Prime */ caam_desc_add_ptr(desc, caam_dh_key.p.paddr); /* Modulus - Not used */ caam_desc_add_ptr(desc, 0); /* Public key */ caam_desc_add_ptr(desc, caam_dh_key.y.paddr); /* Private key */ caam_desc_add_ptr(desc, caam_dh_key.x.buf.paddr); /* Output secret */ caam_desc_add_ptr(desc, secret.sgtbuf.paddr); switch (caam_dh_key.x.key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, SHARED_SECRET(DL, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, SHARED_SECRET(DL, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, SHARED_SECRET(DL, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); DH_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { sdata->secret.length = caam_dmaobj_copy_to_orig(&secret); DH_DUMPBUF("Secret", sdata->secret.data, sdata->secret.length); ret = caam_status_to_tee_result(retstatus); } else { DH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); do_keypair_free(&caam_dh_key); caam_dmaobj_free(&secret); return ret; } /* * Registration of the ECC Driver */ static struct drvcrypt_dh driver_dh = { .alloc_keypair = do_allocate_keypair, .gen_keypair = do_gen_keypair, .shared_secret = do_shared_secret, }; enum caam_status caam_dh_init(struct caam_jrcfg *caam_jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; if (caam_hal_ctrl_pknum(jr_base) && drvcrypt_register_dh(&driver_dh) == TEE_SUCCESS) retstatus = CAAM_NO_ERROR; return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_dsa.c000066400000000000000000000531561464416617300235170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019-2021, 2023 NXP * * Implementation of DSA functions */ #include #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #include "utee_types.h" #ifdef CFG_CAAM_64BIT #define MAX_DESC_KEY_GEN 14 #define MAX_DESC_SIGN 19 #define MAX_DESC_VERIFY 21 #else #define MAX_DESC_KEY_GEN 9 #define MAX_DESC_SIGN 12 #define MAX_DESC_VERIFY 13 #endif /* * Definition of the local DSA Keypair * Domain Parameters (p, q, g) * Private Key format (x) * Public Key format (y) */ struct caam_dsa_keypair { struct caambuf g; /* Generator */ struct caambuf p; /* Prime Number (L bits) */ struct caambuf q; /* Subprime Number (N bits) */ struct caamkey x; /* Private key */ struct caambuf y; /* Public key */ }; /* * Free local DSA keypair * * @key DSA keypair */ static void do_keypair_free(struct caam_dsa_keypair *key) { caam_free_buf(&key->g); caam_free_buf(&key->p); caam_free_buf(&key->q); caam_key_free(&key->x); caam_free_buf(&key->y); } /* * If all DSA parameters p, q and g are present, convert them from bignumbers * to local buffers (via keypair object). Otherwise generate them. * * @outkey [out] Output keypair in local format * @key Input key in TEE Crypto format * @l_bytes Prime p size in bytes * @n_bytes Subprime q size in bytes */ static TEE_Result get_keypair_domain_params(struct caam_dsa_keypair *outkey, const struct dsa_keypair *key, size_t l_bytes, size_t n_bytes) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t in_q_size = 0; size_t in_p_size = 0; size_t in_g_size = 0; struct prime_data_dsa prime = { }; DSA_TRACE("DSA conv key param (p, g) of %zu bytes and (q) of %zu bytes", l_bytes, n_bytes); retstatus = caam_calloc_buf(&outkey->q, n_bytes); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); retstatus = caam_calloc_buf(&outkey->g, l_bytes); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); retstatus = caam_calloc_buf(&outkey->p, l_bytes); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); /* * Get all inputs parameters size, if one of them is not * define generate new parameters */ in_g_size = crypto_bignum_num_bytes(key->g); in_p_size = crypto_bignum_num_bytes(key->p); in_q_size = crypto_bignum_num_bytes(key->q); if (!in_q_size || !in_g_size || !in_p_size) { /* Generate DSA parameters: Generator G and Primes P/Q */ prime.g = &outkey->g; prime.p = &outkey->p; prime.q = &outkey->q; retstatus = caam_prime_dsa_gen(&prime); DSA_TRACE("Generate G and Primes P/Q returned %#x", retstatus); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); /* Copy Generated DSA Parameter */ crypto_bignum_bin2bn(outkey->q.data, outkey->q.length, key->q); crypto_bignum_bin2bn(outkey->g.data, outkey->g.length, key->g); crypto_bignum_bin2bn(outkey->p.data, outkey->p.length, key->p); } else { DSA_TRACE("Prime Q is defined"); crypto_bignum_bn2bin(key->q, outkey->q.data + n_bytes - in_q_size); cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length); DSA_TRACE("Prime G is defined"); crypto_bignum_bn2bin(key->g, outkey->g.data + l_bytes - in_g_size); cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); DSA_TRACE("Prime P is defined"); crypto_bignum_bn2bin(key->p, outkey->p.data + l_bytes - in_p_size); cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); } return TEE_SUCCESS; } /* * Convert Crypto DSA Private Key to local Keypair Key * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format * @l_bytes Prime p size in bytes * @n_bytes Subprime q size in bytes */ static enum caam_status do_keypriv_conv(struct caam_dsa_keypair *outkey, const struct dsa_keypair *inkey, size_t l_bytes, size_t n_bytes) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t field_size = 0; DSA_TRACE("DSA Convert Key Private size l=%zu bytes, n=%zu bytes", l_bytes, n_bytes); /* Generator */ retstatus = caam_calloc_buf(&outkey->g, l_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of g to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->g); crypto_bignum_bn2bin(inkey->g, outkey->g.data + l_bytes - field_size); /* Prime Number Modulus */ retstatus = caam_calloc_buf(&outkey->p, l_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of p to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->p); crypto_bignum_bn2bin(inkey->p, outkey->p.data + l_bytes - field_size); /* Subprime Number Modulus */ retstatus = caam_calloc_buf(&outkey->q, n_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of q to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->q); crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size); retstatus = caam_key_deserialize_from_bn(inkey->x, &outkey->x, n_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length); caam_key_cache_op(TEE_CACHECLEAN, &outkey->x); return CAAM_NO_ERROR; } /* * Convert Crypto DSA Public Key to local DSA Keypair Key * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format * @l_bytes Prime p size in bytes * @n_bytes Subprime q size in bytes */ static enum caam_status do_keypub_conv(struct caam_dsa_keypair *outkey, const struct dsa_public_key *inkey, size_t l_bytes, size_t n_bytes) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t field_size = 0; DSA_TRACE("DSA Convert Public Key size l=%zu bytes, n=%zu bytes", l_bytes, n_bytes); /* Generator */ retstatus = caam_calloc_buf(&outkey->g, l_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of g to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->g); crypto_bignum_bn2bin(inkey->g, outkey->g.data + l_bytes - field_size); /* Prime Number Modulus */ retstatus = caam_calloc_buf(&outkey->p, l_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of p to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->p); crypto_bignum_bn2bin(inkey->p, outkey->p.data + l_bytes - field_size); /* Subprime Number Modulus */ retstatus = caam_calloc_buf(&outkey->q, n_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of q to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->q); crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size); /* Public key is only scalar y of l bytes */ retstatus = caam_calloc_buf(&outkey->y, l_bytes); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Get the number of bytes of y to pad with 0's */ field_size = crypto_bignum_num_bytes(inkey->y); crypto_bignum_bn2bin(inkey->y, outkey->y.data + l_bytes - field_size); cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length); cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length); cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length); cache_operation(TEE_CACHECLEAN, outkey->y.data, outkey->y.length); return CAAM_NO_ERROR; } /* * Allocate a TEE DSA keypair. * * @key Keypair * @l_bits L bits size (prime p size) * @n_bits N bits size (subprime q size) */ static TEE_Result do_allocate_keypair(struct dsa_keypair *key, size_t l_bits, size_t n_bits) { DSA_TRACE("DSA allocate Keypair of L=%zu bits and N=%zu bits", l_bits, n_bits); /* Initialize the key fields to NULL */ memset(key, 0, sizeof(*key)); /* Allocate Generator Scalar */ key->g = crypto_bignum_allocate(l_bits); if (!key->g) goto err; /* Allocate Prime Number Modulus */ key->p = crypto_bignum_allocate(l_bits); if (!key->p) goto err; /* Allocate Prime Number Modulus */ key->q = crypto_bignum_allocate(n_bits); if (!key->q) goto err; /* Allocate Private key X */ key->x = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->x) goto err; /* Allocate Public Key Y */ key->y = crypto_bignum_allocate(l_bits); if (!key->y) goto err; return TEE_SUCCESS; err: DSA_TRACE("Allocation error"); crypto_bignum_free(&key->g); crypto_bignum_free(&key->p); crypto_bignum_free(&key->q); crypto_bignum_free(&key->x); return TEE_ERROR_OUT_OF_MEMORY; } /* * Allocate a DSA Public Key * * @key Public Key * @l_bits L bits size (prime p size) * @n_bits N bits size (subprime q size) */ static TEE_Result do_allocate_publickey(struct dsa_public_key *key, size_t l_bits, size_t n_bits) { DSA_TRACE("DSA Allocate Public of L=%zu bits and N=%zu bits", l_bits, n_bits); /* Initialize the key fields to NULL */ memset(key, 0, sizeof(*key)); /* Allocate Generator Scalar */ key->g = crypto_bignum_allocate(l_bits); if (!key->g) goto err; /* Allocate Prime Number Modulus */ key->p = crypto_bignum_allocate(l_bits); if (!key->p) goto err; /* Allocate Prime Number Modulus */ key->q = crypto_bignum_allocate(n_bits); if (!key->q) goto err; /* Allocate Public Key Y */ key->y = crypto_bignum_allocate(l_bits); if (!key->y) goto err; return TEE_SUCCESS; err: DSA_TRACE("Allocation error"); crypto_bignum_free(&key->g); crypto_bignum_free(&key->p); crypto_bignum_free(&key->q); return TEE_ERROR_OUT_OF_MEMORY; } /* * Generates an DSA keypair * Keypair @key contains the input primes p, g and generator g values * The function computes private x and public y. * * @key [in/out] Keypair * @l_bits L bits size (prime p size) * @n_bits N bits size (subprime q size) */ static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits, size_t n_bits) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_dsa_keypair caam_dsa_key = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; size_t l_bytes = l_bits / 8; size_t n_bytes = n_bits / 8; enum caam_key_type key_type = caam_key_default_key_gen_type(); DSA_TRACE("Generate Key - Private (%zu bits) and Public (%zu bits)", n_bits, l_bits); /* Allocate the job used to prepare the operation */ desc = caam_calloc_desc(MAX_DESC_KEY_GEN); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Allocate Private Key to be generated */ caam_dsa_key.x.key_type = caam_key_default_key_gen_type(); caam_dsa_key.x.sec_size = n_bytes; caam_dsa_key.x.is_blob = false; retstatus = caam_key_alloc(&caam_dsa_key.x); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } caam_key_cache_op(TEE_CACHEFLUSH, &caam_dsa_key.x); /* Allocate Public Key to be generated */ retstatus = caam_calloc_align_buf(&caam_dsa_key.y, l_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } cache_operation(TEE_CACHEFLUSH, caam_dsa_key.y.data, caam_dsa_key.y.length); /* Generator and Prime */ ret = get_keypair_domain_params(&caam_dsa_key, key, l_bytes, n_bytes); if (ret != TEE_SUCCESS) goto out; /* * Build the descriptor using the PDB Public Key generation * block (PD=0) */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_DL_KEY_L_SIZE(l_bytes) | PDB_DL_KEY_N_SIZE(n_bytes)); caam_desc_add_ptr(desc, caam_dsa_key.p.paddr); caam_desc_add_ptr(desc, caam_dsa_key.q.paddr); caam_desc_add_ptr(desc, caam_dsa_key.g.paddr); caam_desc_add_ptr(desc, caam_dsa_key.x.buf.paddr); caam_desc_add_ptr(desc, caam_dsa_key.y.paddr); switch (key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); DSA_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dsa_key.x); cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.y.data, caam_dsa_key.y.length); /* Copy Private and Public keypair */ ret = caam_key_serialize_to_bn(key->x, &caam_dsa_key.x); if (ret != TEE_SUCCESS) goto out; ret = crypto_bignum_bin2bn(caam_dsa_key.y.data, caam_dsa_key.y.length, key->y); if (ret != TEE_SUCCESS) goto out; DSA_DUMPBUF("X", caam_dsa_key.x.buf.data, caam_dsa_key.x.buf.length); DSA_DUMPBUF("Y", caam_dsa_key.y.data, caam_dsa_key.y.length); } else { DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); do_keypair_free(&caam_dsa_key); return ret; } /* * Signature of DSA message * Note : the message to sign is already hashed * * @sdata [in/out] DSA data to sign / Signature * @l_bytes L bytes size (prime p size) * @n_bytes N bytes size (subprime q size) */ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes, size_t n_bytes) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct dsa_keypair *inkey = sdata->key; struct caam_dsa_keypair dsakey = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; struct caamdmaobj msg = { }; size_t sign_len = 0; struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; uint32_t pdb_sgt_flags = 0; DSA_TRACE("DSA Signature"); /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_SIGN); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Convert the private key to a local key */ retstatus = do_keypriv_conv(&dsakey, inkey, l_bytes, n_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* Prepare the input message CAAM Descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, sdata->message.length); if (ret) goto out; if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG; caam_dmaobj_cache_push(&msg); DSA_DUMPBUF("Message", sdata->message.data, sdata->message.length); /* * Re-allocate the signature result buffer with a maximum size * of the roundup to 16 bytes of the secure size in bytes if * the signature buffer is not aligned or too short. * * - 1st Part: size_sec * - 2nd Part: size_sec roundup to 16 bytes */ sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec; ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data, sdata->signature.length, sign_len); if (ret) goto out; if (sign_c.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C; /* Prepare the 2nd Part of the signature. Derive from sign_c */ ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, ROUNDUP(sdata->size_sec, 16)); if (ret) goto out; if (sign_d.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D; caam_dmaobj_cache_push(&sign_c); /* * Build the descriptor using Predifined ECC curve */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_DSA_SIGN_N(n_bytes) | PDB_DSA_SIGN_L(l_bytes) | pdb_sgt_flags); /* Prime number */ caam_desc_add_ptr(desc, dsakey.p.paddr); /* Prime Modulus */ caam_desc_add_ptr(desc, dsakey.q.paddr); /* Generator */ caam_desc_add_ptr(desc, dsakey.g.paddr); /* Secret key */ caam_desc_add_ptr(desc, dsakey.x.buf.paddr); /* Input message */ caam_desc_add_ptr(desc, msg.sgtbuf.paddr); /* Signature 1st part */ caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); /* Signature 2nd part */ caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); /* Message length */ caam_desc_add_word(desc, sdata->message.length); switch (dsakey.x.key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); ECC_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { /* Limit the copy to 2 * sdata->size_sec */ sign_c.orig.length = 2 * sdata->size_sec; sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c); DSA_DUMPBUF("Signature", sdata->signature.data, sdata->signature.length); ret = caam_status_to_tee_result(retstatus); } else { DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); do_keypair_free(&dsakey); caam_dmaobj_free(&msg); caam_dmaobj_free(&sign_c); caam_dmaobj_free(&sign_d); return ret; } /* * Verification of the Signature of DSA message * Note the message is already hashed * * @sdata [in/out] DSA Signature to verify * @l_bytes L bytes size (prime p size) * @n_bytes N bytes size (subprime q size) */ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata, size_t l_bytes, size_t n_bytes) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct dsa_public_key *inkey = sdata->key; struct caam_dsa_keypair dsakey = { }; struct caambuf tmp = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; struct caamdmaobj msg = { }; struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; uint32_t pdb_sgt_flags = 0; DSA_TRACE("DSA Verify"); /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_VERIFY); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Convert the Public key to local key */ retstatus = do_keypub_conv(&dsakey, inkey, l_bytes, n_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* Prepare the input message CAAM Descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, sdata->message.length); if (ret) goto out; if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG; caam_dmaobj_cache_push(&msg); /* * Prepare the 1st Part of the signature * Handle the full signature in case signature buffer needs to * be reallocated. */ ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data, sdata->signature.length); if (ret) goto out; if (sign_c.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C; /* Prepare the 2nd Part of the signature, derive from sign_c */ ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, sdata->size_sec); if (ret) goto out; if (sign_d.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D; caam_dmaobj_cache_push(&sign_c); /* Allocate a Temporary buffer used by the CAAM */ retstatus = caam_alloc_align_buf(&tmp, l_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* * Build the descriptor using Predifined ECC curve */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_DSA_VERIF_N(n_bytes) | PDB_DSA_VERIF_L(l_bytes) | pdb_sgt_flags); /* Prime number */ caam_desc_add_ptr(desc, dsakey.p.paddr); /* Prime Modulus */ caam_desc_add_ptr(desc, dsakey.q.paddr); /* Generator */ caam_desc_add_ptr(desc, dsakey.g.paddr); /* Public key */ caam_desc_add_ptr(desc, dsakey.y.paddr); /* Input message */ caam_desc_add_ptr(desc, msg.sgtbuf.paddr); /* Signature 1st part */ caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); /* Signature 2nd part */ caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); /* Temporary buffer */ caam_desc_add_ptr(desc, tmp.paddr); /* Message length */ caam_desc_add_word(desc, sdata->message.length); caam_desc_add_word(desc, DSA_VERIFY(DL, HASHED)); desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); DSA_DUMPDESC(desc); jobctx.desc = desc; cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length); retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_JOB_STATUS && !jobctx.status) { DSA_TRACE("DSA Verify Status 0x%08" PRIx32, jobctx.status); ret = TEE_ERROR_SIGNATURE_INVALID; } else if (retstatus != CAAM_NO_ERROR) { DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } else { ret = caam_status_to_tee_result(retstatus); } out: caam_free_desc(&desc); do_keypair_free(&dsakey); caam_free_buf(&tmp); caam_dmaobj_free(&msg); caam_dmaobj_free(&sign_c); caam_dmaobj_free(&sign_d); return ret; } /* * Registration of the DSA Driver */ static struct drvcrypt_dsa driver_dsa = { .alloc_keypair = do_allocate_keypair, .alloc_publickey = do_allocate_publickey, .gen_keypair = do_gen_keypair, .sign = do_sign, .verify = do_verify, }; enum caam_status caam_dsa_init(struct caam_jrcfg *caam_jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; if (caam_hal_ctrl_pknum(jr_base) && drvcrypt_register_dsa(&driver_dsa) == TEE_SUCCESS) retstatus = CAAM_NO_ERROR; return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_ecc.c000066400000000000000000000564601464416617300235030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021, 2024 NXP * * Implementation of ECC functions */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_CAAM_64BIT #define MAX_DESC_KEY_GEN 8 #define MAX_DESC_SIGN 13 #define MAX_DESC_VERIFY 15 #define MAX_DESC_SHARED 10 #else #define MAX_DESC_KEY_GEN 6 #define MAX_DESC_SIGN 9 #define MAX_DESC_VERIFY 10 #define MAX_DESC_SHARED 7 #endif /* * Definition of the local ECC Keypair * Public Key format (x, y) * Private Key format (d) */ struct caam_ecc_keypair { struct caambuf xy; struct caamkey d; }; /* * Free local ECC keypair * * @key ECC keypair */ static void do_keypair_free(struct caam_ecc_keypair *key) { caam_free_buf(&key->xy); caam_key_free(&key->d); } /* * Convert Crypto ECC Key to local ECC Public Key * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format * @size_sec Security size in bytes */ static enum caam_status do_keypub_conv(struct caam_ecc_keypair *outkey, const struct ecc_public_key *inkey, size_t size_sec) { enum caam_status retstatus = CAAM_OUT_MEMORY; size_t x_size = 0; size_t y_size = 0; ECC_TRACE("ECC Convert Public Key size %zu bytes", size_sec); /* Point (x y) is twice security key size */ retstatus = caam_calloc_buf(&outkey->xy, 2 * size_sec); if (retstatus != CAAM_NO_ERROR) return retstatus; /* Copy x and y and get the number of bytes to pad with 0's */ x_size = crypto_bignum_num_bytes(inkey->x); crypto_bignum_bn2bin(inkey->x, outkey->xy.data + size_sec - x_size); y_size = crypto_bignum_num_bytes(inkey->y); crypto_bignum_bn2bin(inkey->y, outkey->xy.data + 2 * size_sec - y_size); cache_operation(TEE_CACHECLEAN, outkey->xy.data, outkey->xy.length); return CAAM_NO_ERROR; } /* * Convert Crypto ECC Key to local ECC Keypair Key * Don't convert the exponent e not used in decrytion * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format * @size_sec Security size in bytes */ static enum caam_status do_keypair_conv(struct caam_ecc_keypair *outkey, const struct ecc_keypair *inkey, size_t size_sec) { enum caam_status retstatus = CAAM_OUT_MEMORY; ECC_TRACE("ECC Convert Keypair size %zu bytes", size_sec); /* Private key is only scalar d of sec_size bytes */ retstatus = caam_key_deserialize_from_bn(inkey->d, &outkey->d, size_sec); if (retstatus) return retstatus; caam_key_cache_op(TEE_CACHEFLUSH, &outkey->d); ECC_DUMPBUF("Outkey", outkey->d.buf.data, outkey->d.buf.length); return CAAM_NO_ERROR; } /* * Convert TEE ECC Curve to CAAM ECC Curve * * @tee_curve TEE ECC Curve */ static enum caam_ecc_curve get_caam_curve(uint32_t tee_curve) { enum caam_ecc_curve caam_curve = CAAM_ECC_UNKNOWN; if (tee_curve > 0 && tee_curve < CAAM_ECC_MAX + TEE_ECC_CURVE_NIST_P192) { /* * Realign TEE Curve assuming NIST_P192 is the first entry in * the list of supported ECC curves. */ caam_curve = tee_curve - TEE_ECC_CURVE_NIST_P192 + CAAM_ECC_P192; } return caam_curve; } /* * Allocate a ECC keypair * * @key Keypair * @size_bits Key size in bits */ static TEE_Result do_allocate_keypair(struct ecc_keypair *key, uint32_t type, size_t size_bits) { ECC_TRACE("Allocate Keypair of %zu bits", size_bits); switch (type) { case TEE_TYPE_SM2_PKE_KEYPAIR: case TEE_TYPE_SM2_DSA_KEYPAIR: /* Software fallback */ return TEE_ERROR_NOT_IMPLEMENTED; default: break; } /* Initialize the key fields to NULL */ memset(key, 0, sizeof(*key)); /* Allocate Secure Scalar */ key->d = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->d) goto err; /* Allocate Public coordinate X */ key->x = crypto_bignum_allocate(size_bits); if (!key->x) goto err; /* Allocate Public coordinate Y */ key->y = crypto_bignum_allocate(size_bits); if (!key->y) goto err; return TEE_SUCCESS; err: ECC_TRACE("Allocation error"); crypto_bignum_free(&key->d); crypto_bignum_free(&key->x); return TEE_ERROR_OUT_OF_MEMORY; } /* * Allocate an ECC Public Key * * @key Public Key * @size_bits Key size in bits */ static TEE_Result do_allocate_publickey(struct ecc_public_key *key, uint32_t type, size_t size_bits) { ECC_TRACE("Allocate Public Key of %zu bits", size_bits); switch (type) { case TEE_TYPE_SM2_PKE_PUBLIC_KEY: case TEE_TYPE_SM2_DSA_PUBLIC_KEY: /* Software fallback */ return TEE_ERROR_NOT_IMPLEMENTED; default: break; } /* Initialize the key fields to NULL */ memset(key, 0, sizeof(*key)); /* Allocate Public coordinate X */ key->x = crypto_bignum_allocate(size_bits); if (!key->x) goto err; /* Allocate Public coordinate Y */ key->y = crypto_bignum_allocate(size_bits); if (!key->y) goto err; return TEE_SUCCESS; err: ECC_TRACE("Allocation error"); crypto_bignum_free(&key->x); return TEE_ERROR_OUT_OF_MEMORY; } /* * Free an ECC public key * * @key Public Key */ static void do_free_publickey(struct ecc_public_key *key) { crypto_bignum_free(&key->x); crypto_bignum_free(&key->y); } /* * Generate ECC keypair * * @key [out] Keypair * @key_size Key size in bits multiple of 8 bits */ static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; struct caamkey d = { }; struct caambuf xy = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; enum caam_key_type key_type = caam_key_default_key_gen_type(); ECC_TRACE("Generate Keypair of %zu bits", key_size); /* The key size must be a multiple of 8 bits */ key_size = ROUNDUP(key_size, 8); /* Verify first if the curve is supported */ curve = get_caam_curve(key->curve); if (curve == CAAM_ECC_UNKNOWN) return TEE_ERROR_BAD_PARAMETERS; /* Allocate the job used to prepare the operation */ desc = caam_calloc_desc(MAX_DESC_KEY_GEN); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* * Allocate secure and public keys in two buffers * Secure key size = key_size align in bytes * Public key size = (key_size * 2) align in bytes */ d.key_type = key_type; d.sec_size = ROUNDUP_DIV(key_size, 8); d.is_blob = false; retstatus = caam_key_alloc(&d); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } retstatus = caam_alloc_align_buf(&xy, (key_size / 8) * 2); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* Build the descriptor using Predifined ECC curve */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_PKGEN_PD1 | PDB_ECC_ECDSEL(curve)); caam_desc_add_ptr(desc, d.buf.paddr); caam_desc_add_ptr(desc, xy.paddr); switch (key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); ECC_DUMPDESC(desc); jobctx.desc = desc; caam_key_cache_op(TEE_CACHEFLUSH, &d); cache_operation(TEE_CACHEFLUSH, xy.data, xy.length); retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { caam_key_cache_op(TEE_CACHEINVALIDATE, &d); cache_operation(TEE_CACHEINVALIDATE, xy.data, xy.length); /* Copy all keypair parameters */ retstatus = caam_key_serialize_to_bn(key->d, &d); if (retstatus) { ret = caam_status_to_tee_result(retstatus); goto out; } ret = crypto_bignum_bin2bn(xy.data, xy.length / 2, key->x); if (ret != TEE_SUCCESS) goto out; ret = crypto_bignum_bin2bn(xy.data + xy.length / 2, xy.length / 2, key->y); if (ret != TEE_SUCCESS) goto out; ECC_DUMPBUF("D", d.buf.data, key_size / 8); ECC_DUMPBUF("X", xy.data, xy.length / 2); ECC_DUMPBUF("Y", xy.data + xy.length / 2, xy.length / 2); } else { ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); caam_key_free(&d); caam_free_buf(&xy); return ret; } /* * Check if MES_REP to be sent in descriptor is 00. * Only required in case message length and key size is more than 40bytes * because of limitation of Class 2 context register size on i.MX8M series. * Example case below: * When we try to do signature with P384-SHA384, in this case the key size * will be 48bytes and Message size will also be 48bytes. * This will work only when we set MES_REP = 0 in descriptor, * but in this case, we don't need the padding to be done on the message. * * @msg_length: Message Length in bytes * @key_size: Key size in bytes */ static bool msg_mes_rep(size_t msg_length, size_t key_size) { return IS_ENABLED(CFG_NXP_CAAM_C2_CTX_REG_WA) && msg_length > 40 && key_size > 40; } /* * Check if padding is required on message to make it of same length * as that of key size. * Only required in case message length and key size is more than 40bytes * because of limitation of Class 2 context register size on i.MX8M series. * So this will be applicable on P384 and P521 ECC curves because these * curves have key_size more than 40bytes. * * @msg_length: Message Length in bytes * @key_size: Key size in bytes */ static bool padding_required(size_t msg_length, size_t key_size) { return msg_mes_rep(msg_length, key_size) && msg_length < key_size; } /* * Add padding of 00s in start of message * * @buf: Buffer in which padded message will be placed. * @data: Original message * @msg_length: Message Length in bytes * @key_size: Key Size in bytes */ static TEE_Result add_padding(struct caambuf *buf, uint8_t *data, size_t msg_length, size_t key_size) { enum caam_status retstatus = CAAM_FAILURE; retstatus = caam_calloc_align_buf(buf, key_size); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); memcpy(buf->data + key_size - msg_length, data, msg_length); return TEE_SUCCESS; } /* * Signature of ECC message * Note the message to sign is already hashed * * @sdata [in/out] ECC data to sign / Signature */ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; struct ecc_keypair *inkey = sdata->key; struct caam_ecc_keypair ecckey = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; struct caamdmaobj msg = { }; size_t sign_len = 0; struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; uint32_t pdb_sgt_flags = 0; struct caambuf caambuf_msg = { }; ECC_TRACE("ECC Signature"); /* Verify first if the curve is supported */ curve = get_caam_curve(inkey->curve); if (curve == CAAM_ECC_UNKNOWN) return TEE_ERROR_BAD_PARAMETERS; /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_SIGN); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Convert the private key to a local key */ retstatus = do_keypair_conv(&ecckey, inkey, sdata->size_sec); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); if (padding_required(sdata->message.length, sdata->size_sec)) { ret = add_padding(&caambuf_msg, sdata->message.data, sdata->message.length, sdata->size_sec); if (ret) goto out; /* Prepare the input message CAAM Descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data, caambuf_msg.length); if (ret) goto out; ECC_DUMPBUF("Padded Message", caambuf_msg.data, caambuf_msg.length); } else { /* Prepare the input message CAAM Descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, sdata->message.length); if (ret) goto out; } if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_MSG; caam_dmaobj_cache_push(&msg); /* * ReAllocate the signature result buffer with a maximum size * of the roundup to 16 bytes of the secure size in bytes if * the signature buffer is not aligned or too short. * * - 1st Part: size_sec * - 2nd Part: size_sec roundup to 16 bytes */ sign_len = ROUNDUP(sdata->size_sec, 16) + sdata->size_sec; ret = caam_dmaobj_output_sgtbuf(&sign_c, sdata->signature.data, sdata->signature.length, sign_len); if (ret) goto out; if (sign_c.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_C; /* Derive sign_d from created sign_c DMA object */ ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, ROUNDUP(sdata->size_sec, 16)); if (ret) goto out; if (sign_d.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKSIGN_SIGN_D; caam_dmaobj_cache_push(&sign_c); /* Build the descriptor using Predifined ECC curve */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_PKSIGN_PD1 | PDB_ECC_ECDSEL(curve) | pdb_sgt_flags); /* Secret key */ caam_desc_add_ptr(desc, ecckey.d.buf.paddr); /* Input message */ caam_desc_add_ptr(desc, msg.sgtbuf.paddr); /* Signature 1st part */ caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); /* Signature 2nd part */ caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); if (msg_mes_rep(sdata->message.length, sdata->size_sec)) { switch (ecckey.d.key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } } else { /* Message length */ caam_desc_add_word(desc, sdata->message.length); switch (ecckey.d.key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); ECC_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { sign_c.orig.length = 2 * sdata->size_sec; sdata->signature.length = caam_dmaobj_copy_to_orig(&sign_c); ECC_DUMPBUF("Signature", sdata->signature.data, sdata->signature.length); ret = caam_status_to_tee_result(retstatus); } else { ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); do_keypair_free(&ecckey); caam_dmaobj_free(&msg); caam_dmaobj_free(&sign_d); caam_dmaobj_free(&sign_c); caam_free_buf(&caambuf_msg); return ret; } /* * Verification of the Signature of ECC message * Note the message is already hashed * * @sdata [in/out] ECC Signature to verify */ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; struct ecc_public_key *inkey = sdata->key; struct caam_ecc_keypair ecckey = { }; struct caambuf tmp = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; struct caamdmaobj msg = { }; struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; uint32_t pdb_sgt_flags = 0; struct caambuf caambuf_msg = { }; ECC_TRACE("ECC Verify"); ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length); ECC_DUMPBUF("Signature", sdata->signature.data, sdata->signature.length); /* Verify first if the curve is supported */ curve = get_caam_curve(inkey->curve); if (curve == CAAM_ECC_UNKNOWN) return TEE_ERROR_BAD_PARAMETERS; /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_VERIFY); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Convert the Public key to local key */ retstatus = do_keypub_conv(&ecckey, inkey, sdata->size_sec); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } if (padding_required(sdata->message.length, sdata->size_sec)) { ret = add_padding(&caambuf_msg, sdata->message.data, sdata->message.length, sdata->size_sec); if (ret) goto out; /* Prepare the input message CAAM Descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, caambuf_msg.data, caambuf_msg.length); if (ret) goto out; } else { /* Prepare the input message CAAM Descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, sdata->message.data, sdata->message.length); if (ret) goto out; } if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_MSG; caam_dmaobj_cache_push(&msg); /* * Prepare the 1st Part of the signature * Handle the full signature in case signature buffer needs to * be reallocated. */ ret = caam_dmaobj_input_sgtbuf(&sign_c, sdata->signature.data, sdata->signature.length); if (ret) goto out; if (sign_c.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_C; /* Prepare the 2nd Part of the signature, derived from sign_c */ ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, sdata->size_sec, sdata->size_sec); if (ret) goto out; if (sign_d.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKVERIF_SIGN_D; caam_dmaobj_cache_push(&sign_c); /* Allocate a Temporary buffer used by the CAAM */ retstatus = caam_alloc_align_buf(&tmp, 2 * sdata->size_sec); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* Build the descriptor using Predifined ECC curve */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_PKVERIFY_PD1 | PDB_ECC_ECDSEL(curve) | pdb_sgt_flags); /* Public key */ caam_desc_add_ptr(desc, ecckey.xy.paddr); /* Input message */ caam_desc_add_ptr(desc, msg.sgtbuf.paddr); /* Signature 1st part */ caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); /* Signature 2nd part */ caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); /* Temporary buffer */ caam_desc_add_ptr(desc, tmp.paddr); if (msg_mes_rep(sdata->message.length, sdata->size_sec)) { caam_desc_add_word(desc, DSA_VERIFY(ECC, MES_REP)); } else { /* Message length */ caam_desc_add_word(desc, sdata->message.length); caam_desc_add_word(desc, DSA_VERIFY(ECC, HASHED)); } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); ECC_DUMPDESC(desc); jobctx.desc = desc; cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length); cache_operation(TEE_CACHEFLUSH, ecckey.xy.data, ecckey.xy.length); retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_JOB_STATUS && !jobctx.status) { ECC_TRACE("ECC Verify Status 0x%08" PRIx32, jobctx.status); ret = TEE_ERROR_SIGNATURE_INVALID; } else if (retstatus != CAAM_NO_ERROR) { ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } else { ret = caam_status_to_tee_result(retstatus); } out: caam_free_desc(&desc); do_keypair_free(&ecckey); caam_free_buf(&tmp); caam_dmaobj_free(&msg); caam_dmaobj_free(&sign_c); caam_dmaobj_free(&sign_d); caam_free_buf(&caambuf_msg); return ret; } /* * Compute the shared secret data from ECC Private key and Public Key * * @sdata [in/out] ECC Shared Secret data */ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN; struct ecc_keypair *inprivkey = sdata->key_priv; struct ecc_public_key *inpubkey = sdata->key_pub; struct caam_ecc_keypair ecckey = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; struct caamdmaobj secret = { }; uint32_t pdb_sgt_flags = 0; ECC_TRACE("ECC Shared Secret"); /* Verify first if the curve is supported */ curve = get_caam_curve(inpubkey->curve); if (curve == CAAM_ECC_UNKNOWN) return TEE_ERROR_BAD_PARAMETERS; /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_SHARED); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Convert the Private key to local key */ retstatus = do_keypair_conv(&ecckey, inprivkey, sdata->size_sec); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* Convert the Public key to local key */ retstatus = do_keypub_conv(&ecckey, inpubkey, sdata->size_sec); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } /* * Re-allocate the secret result buffer with a maximum size * of the secret size if not cache aligned */ ret = caam_dmaobj_output_sgtbuf(&secret, sdata->secret.data, sdata->secret.length, sdata->size_sec); if (ret) goto out; if (secret.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_PKDH_SECRET; caam_dmaobj_cache_push(&secret); /* Build the descriptor using Predifined ECC curve */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_SHARED_SECRET_PD1 | PDB_ECC_ECDSEL(curve) | pdb_sgt_flags); /* Public key */ caam_desc_add_ptr(desc, ecckey.xy.paddr); /* Private key */ caam_desc_add_ptr(desc, ecckey.d.buf.paddr); /* Output secret */ caam_desc_add_ptr(desc, secret.sgtbuf.paddr); switch (ecckey.d.key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, SHARED_SECRET(ECC, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, SHARED_SECRET(ECC, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, SHARED_SECRET(ECC, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto out; } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); ECC_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { sdata->secret.length = caam_dmaobj_copy_to_orig(&secret); ECC_DUMPBUF("Secret", sdata->secret.data, sdata->secret.length); ret = caam_status_to_tee_result(retstatus); } else { ECC_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); do_keypair_free(&ecckey); caam_dmaobj_free(&secret); return ret; } /* * Registration of the ECC Driver */ static struct drvcrypt_ecc driver_ecc = { .alloc_keypair = do_allocate_keypair, .alloc_publickey = do_allocate_publickey, .free_publickey = do_free_publickey, .gen_keypair = do_gen_keypair, .sign = do_sign, .verify = do_verify, .shared_secret = do_shared_secret, }; enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; if (caam_hal_ctrl_pknum(jr_base)) if (drvcrypt_register_ecc(&driver_ecc) == TEE_SUCCESS) retstatus = CAAM_NO_ERROR; return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_math.c000066400000000000000000000060041464416617300236670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * CAAM Mathematical Operation manager. * Implementation of Mathematical operation using CAAM's MATH function */ #include #include #include #include #include #include #include #include #include /* * MATH operation A xor B modulus n * * @data [in/out] operation data */ static TEE_Result do_xor_mod_n(struct drvcrypt_mod_op *data) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; struct caamdmaobj res = { }; struct caamdmaobj data_a = { }; struct caamdmaobj data_b = { }; RSA_TRACE("(A xor B) mod n"); ret = caam_dmaobj_input_sgtbuf(&data_a, data->a.data, data->a.length); if (ret) return ret; ret = caam_dmaobj_input_sgtbuf(&data_b, data->b.data, data->b.length); if (ret) goto out; /* * ReAllocate the result buffer with a maximum size * of the Key Modulus's size (N) if not cache aligned */ ret = caam_dmaobj_output_sgtbuf(&res, data->result.data, data->result.length, data->result.length); if (ret) goto out; #ifdef CFG_CAAM_64BIT #define XOR_OP_DESC_SIZE 14 #else #define XOR_OP_DESC_SIZE 11 #endif /* Allocate the job descriptor */ desc = caam_calloc_desc(XOR_OP_DESC_SIZE); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Load in N Modulus Size */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4)); caam_desc_add_word(desc, data->n.length); /* Load in A f irst value */ caam_desc_fifo_load(desc, &data_a, CLASS_1, PKHA_A, NOACTION); caam_desc_fifo_load(desc, &data_b, CLASS_1, PKHA_B, NOACTION); /* Operation B = A xor B mod n */ caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); /* Store the result */ caam_desc_fifo_store(desc, &res, PKHA_B); caam_dmaobj_cache_push(&data_a); caam_dmaobj_cache_push(&data_b); caam_dmaobj_cache_push(&res); RSA_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { caam_dmaobj_copy_to_orig(&res); RSA_DUMPBUF("Output", data->result.data, data->result.length); ret = caam_status_to_tee_result(retstatus); } else { RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_free_desc(&desc); caam_dmaobj_free(&data_a); caam_dmaobj_free(&data_b); caam_dmaobj_free(&res); return ret; } /* * Registration of the MATH Driver */ static const struct drvcrypt_math driver_math = { .xor_mod_n = &do_xor_mod_n, }; enum caam_status caam_math_init(struct caam_jrcfg *caam_jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; if (caam_hal_ctrl_pknum(jr_base)) if (!drvcrypt_register_math(&driver_math)) retstatus = CAAM_NO_ERROR; return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_prime_dsa.c000066400000000000000000000545101464416617300247060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021, 2023 NXP * * CAAM DSA Prime Numbering. * Implementation of Prime Number functions */ #include #include #include #include #include #include #include #include #include #include #include "local.h" #define PRIME_DESC_ENTRIES 62 /* Define the number max of try to generate valid primes */ #define DSA_MAX_TRIES_PRIME_Q 50000 #define DSA_MAX_TRIES_PRIME_P 500 #define DSA_TRY_FAIL 0x42 #define DSA_NOT_PRIME 0x43 #define DSA_PRIME_TOO_SMALL 0x44 struct dsa_hash { unsigned int op; /* CAAM Hash operation code */ size_t size; /* Hash digest size */ }; /* * Build the descriptor generating a DSA prime Q * Referring to FIPS.186-4, Section A.1.1.2 Generation of the * Probable Primes p and q Using an Approved Hash Function * * @desc [out] Descriptor built * @seed [out] Resulting seed used to generate prime * @prime [in/out] Prime generation data * @hash_func Selected Hash function */ static void do_desc_prime_q(uint32_t *desc, struct caambuf *seed, struct prime_data_dsa *prime, struct dsa_hash *hash_func) { unsigned int desclen = 0; unsigned int retry_new_mr_failed = 0; unsigned int retry_mr_test = 0; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* Set the PKHA N and A register size */ caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4)); caam_desc_add_word(desc, prime->q->length); caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_A_SIZE, 4)); caam_desc_add_word(desc, prime->q->length); caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, VSOL, 4)); caam_desc_add_word(desc, DSA_MAX_TRIES_PRIME_Q); caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8)); retry_new_mr_failed = caam_desc_get_len(desc); /* Decrement the number of try */ caam_desc_add_word(desc, MATH(SUB, VSOL, ONE, VSOL, 4)); /* Exceed retry count - exit with DSA_TRY_FAIL error */ caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, MATH_N, DSA_TRY_FAIL)); /* Clear Class 2 SHA */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4)); caam_desc_add_word(desc, CLR_WR_RST_C2_CHA | CLR_WR_RST_C2_DSZ); /* * Step 5. Generate Random Seed * * Seed Length shall be equal or greater than N (Q prime length) * Seed result push in Message Data */ if (seed->length > 16) { caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4)); caam_desc_add_word(desc, NFIFO_PAD(BOTH, 0, MSG, RND, 16)); caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4)); caam_desc_add_word(desc, NFIFO_PAD(BOTH, NFIFO_LC1 | NFIFO_LC2, MSG, RND, seed->length - 16)); } else { caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE, 4)); caam_desc_add_word(desc, NFIFO_PAD(BOTH, NFIFO_LC1 | NFIFO_LC2, MSG, RND, seed->length)); } caam_desc_add_word(desc, MOVE(C1_ALIGN, OFIFO, 0, seed->length)); caam_desc_add_word(desc, FIFO_ST(CLASS_NO, MSG_DATA, seed->length)); caam_desc_add_ptr(desc, seed->paddr); /* * Hash the Seed, this is a pseudo U, bits upper N - 1 still present */ caam_desc_add_word(desc, HASH_INITFINAL(hash_func->op)); /* * Step 6. U = hash(seed) mod 2^(N-1) * Step 7. q = 2^(N-1) + U + 1 - (U mod 2) */ /* Trash the bits > N - 1, the hash size is >= N */ caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG0, hash_func->size - prime->q->length, 8)); /* Get the MSB of U and set the bit N-1 */ caam_desc_add_word(desc, MATH(OR, REG2, REG0, REG0, 8)); /* Move the candidate prime q's MSB into IFIFO */ caam_desc_add_word(desc, MOVE_WAIT(MATH_REG0, IFIFO, 0, 8)); /* * Move the candidate prime q's intermediate value into IFIFO */ caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, IFIFO, hash_func->size - prime->q->length + 8, prime->q->length - 16)); /* Get the LSB of U and set the bit 0 */ caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG0, hash_func->size - 8, 8)); caam_desc_add_word(desc, MATH(OR, ONE, REG0, REG0, 8)); /* Move the candidate prime q's LSB into IFIFO */ caam_desc_add_word(desc, MOVE_WAIT(MATH_REG0, IFIFO, 0, 8)); /* Move the IFIFO in to PKHA N */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); caam_desc_add_word(desc, NFIFO_NOPAD(C1, NFIFO_FC1, IFIFO, PKHA_N, 0)); caam_desc_add_word(desc, prime->q->length); /* Store the Prime q here because Miller-Rabin test affect PKHA N */ caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_N, prime->q->length)); caam_desc_add_ptr(desc, prime->q->paddr); /* * Step 8. Test q prime with 'miller-rabin' test * * Load the number of Miller-Rabin test iteration */ caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SIL, 4)); if (prime->p->length <= 1024 / 8) caam_desc_add_word(desc, 40); else if (prime->p->length >= 3072 / 8) caam_desc_add_word(desc, 64); else caam_desc_add_word(desc, 56); retry_mr_test = caam_desc_get_len(desc); /* Generate 8 random bytes 'miller-rabin seed' */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); caam_desc_add_word(desc, prime->q->length); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, 0x01); caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B)); desclen = caam_desc_get_len(desc); /* * Step 9. If q is not q prime back to step 5 */ caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(PKHA_IS_PRIME), retry_new_mr_failed - desclen)); caam_desc_add_word(desc, MATH(SUB, SIL, ONE, SIL, 4)); desclen = caam_desc_get_len(desc); /* Test while number of MR test iteration not complete */ caam_desc_add_word(desc, JUMP_CNO_LOCAL(ALL_COND_FALSE, JMP_COND(MATH_N) | JMP_COND(MATH_Z), retry_mr_test - desclen)); DSA_TRACE("Prime Q descriptor"); DSA_DUMPDESC(desc); } /* * Build the descriptor generating the intermediate value X (step 11.3) * Referring to FIPS.186-4, Section A.1.1.2 Generation of the * Probable Primes p and q Using an Approved Hash Function * * @desc [out] Descriptor built * @x [out] Value X * @seed [in/out] Seed to hash and next seed for next loop * @prime [in/out] Prime generation data * @hash_func Selected Hash function * @mod_n Modular value (0xFF filled buffer) * @desc_p Physical address of the descriptor doing Prime P */ static void do_desc_gen_x(uint32_t *desc, struct caambuf *x, struct caambuf *seed, struct prime_data_dsa *prime, struct dsa_hash *hash_func, struct caambuf *mod_n, paddr_t desc_p) { unsigned int desclen = 0; unsigned int loop_n = 0; size_t n = 0; size_t b = 0; size_t b_offset = 0; /* * Step 3. n = ceil(L / outlen) - 1 * where outlen is the hash size in bits * * Note build descriptor with n = ceil(L / outlen) to * pre-calculate seed for next run. */ n = (prime->p->length + hash_func->size) * 8 - 1; n /= hash_func->size * 8; /* * Step 4. b = L - 1 - (n * outlen) * * Note b determine the number of bits to keep in the last * Vn computed. * Calculate b_offset which is the offset in bytes to remove from * the calculated hash */ b = prime->p->length * 8 - 1 - (n - 1) * hash_func->size * 8; DSA_TRACE("Prime p => n = %zu | b = %zu", n - 1, b); b_offset = hash_func->size - (b + 1) / 8; DSA_TRACE("Vn offset is %zu", b_offset); caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, SEQ_OUT_PTR(x->length)); caam_desc_add_ptr(desc, x->paddr); caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8)); caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, REG0, 4)); caam_desc_add_word(desc, n); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, seed->length)); caam_desc_add_ptr(desc, mod_n->paddr); /* * Because the Sequence Out Pointer is incremental store, we need * to build w number in reverse. * * Hence, calculate the last seed number of the loop and save it. * Step 11.9 is automatically done here by incrementing seed number. */ caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, n); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, seed->length)); caam_desc_add_ptr(desc, seed->paddr); caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A)); caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_A, seed->length)); caam_desc_add_ptr(desc, seed->paddr); caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1)); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, 1); caam_desc_add_word(desc, WAIT_COND(ALL_COND_TRUE, NIFP)); /* * Step 11.1 * For j = 0 to n do * Vj = hash((seed + offset + j) mod 2^seedlen * Step 11.2 * W = V0 + (V1 * 2^outlen) + ... + * (Vn-1 * 2^((n-1)*outlen)) + * ((Vn mod 2^b) * 2^(n*outlen)) */ loop_n = caam_desc_get_len(desc); caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4)); caam_desc_add_word(desc, CLR_WR_IFIFO_NFIFO | CLR_WR_RST_C2_CHA | CLR_WR_RST_C2_DSZ); caam_desc_add_word(desc, HASH_INITFINAL(hash_func->op)); caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4)); caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_A); caam_desc_add_word(desc, MOVE_WAIT(OFIFO, IFIFO_C2_LC2, 0, seed->length)); /* If Math Register 2 is zero bypass the high bit set to one */ caam_desc_add_word(desc, MATH(SUB, REG2, ONE, NODEST, 8)); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_TRUE, JMP_COND(MATH_N) | JMP_COND(MATH_Z), 8)); /* * Step 11.3 * X = W + 2^(L-1) * * Set the high bit to one * Remark: the DSA key is a modulus 8 bytes, hence no need * to check if the b_offset is less than 8. */ caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, MATH_REG1, b_offset, 8)); caam_desc_add_word(desc, MATH(OR, REG2, REG1, REG1, 8)); caam_desc_add_word(desc, MOVE(MATH_REG1, OFIFO, 0, 8)); if (hash_func->size - b_offset > 8) caam_desc_add_word(desc, MOVE_WAIT(C2_CTX_REG, OFIFO, b_offset + 8, hash_func->size - b_offset - 8)); caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, hash_func->size - b_offset)); /* * Reset MATH Register 2 to bypass the High Bit set * operation next loop */ caam_desc_add_word(desc, MATH(AND, REG2, ZERO, REG2, 8)); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 2)); /* Bypass High Bit set */ caam_desc_add_word(desc, ST_NOIMM_SEQ(CLASS_2, REG_CTX, hash_func->size)); caam_desc_add_word(desc, PKHA_CPY_NSIZE(B1, A0)); caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, A)); caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1)); desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL_DEC(ALL_COND_FALSE, MATH_0, JMP_COND_MATH(N) | JMP_COND_MATH(Z), loop_n - desclen)); /* Jump to the next descriptor desc */ caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, JMP_COND(NONE))); caam_desc_add_ptr(desc, desc_p); DSA_TRACE("X descriptor"); DSA_DUMPDESC(desc); } /* * Build the descriptor generating the Prime P from value X * Referring to FIPS.186-4, Section A.1.1.2 Generation of the * Probable Primes p and q Using an Approved Hash Function * * @desc [out] Descriptor built * @prime [in/out] Prime generation data * @x Value X * @mod_n Modular value (0xFF filled buffer) */ static void do_desc_prime_p(uint32_t *desc, struct prime_data_dsa *prime, struct caambuf *x, struct caambuf *mod_n) { unsigned int desclen = 0; unsigned int retry_mr_test = 0; size_t index = 0; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length)); caam_desc_add_ptr(desc, mod_n->paddr); /* * Step 11.4 * c = X mod 2q */ /* Calculate 2q and store it in PKHA N */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, prime->q->length)); caam_desc_add_ptr(desc, prime->q->paddr); caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, B0)); caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0)); /* c = X mod 2q */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, x->length)); caam_desc_add_ptr(desc, x->paddr); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(NIFP), 1) | BIT(24)); caam_desc_add_word(desc, PKHA_OP(MOD_AMODN, A)); /* * Step 11.5 * p = X - (c - 1) */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length)); caam_desc_add_ptr(desc, mod_n->paddr); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_ptr(desc, 1); caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B)); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, x->length)); caam_desc_add_ptr(desc, x->paddr); caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, A)); /* * Save the candidate Prime q now because N is going to be * affected by the Miller-Rabin test */ caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0)); caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_N, prime->p->length)); caam_desc_add_ptr(desc, prime->p->paddr); caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, 0)); /* * Step 11.6 * if (p < 2^(L-1)) then go to step 11.9 * */ caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4)); caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_A); /* Keep the MSB from p candidate and check if bit 2^(L-1) is set */ caam_desc_add_word(desc, MOVE_WAIT(OFIFO, MATH_REG0, 0, 8)); for (index = 1; index < prime->p->length / 128; index++) caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, 128)); caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, 124)); caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 63, REG2, 8)); caam_desc_add_word(desc, MATH(AND, REG0, REG2, REG0, 8)); caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, MATH_Z, DSA_PRIME_TOO_SMALL)); /* * Step 11.7 * Test whether or not p is prime * * Referring to FIPS.186-4, Table C.1 * Get the number Miller-Rabin test interation function * of the prime number size */ caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, REG0, 4)); if (prime->p->length <= 1024 / 8) caam_desc_add_word(desc, 40); else if (prime->p->length >= 3072 / 8) caam_desc_add_word(desc, 64); else caam_desc_add_word(desc, 56); retry_mr_test = caam_desc_get_len(desc); /* Generate 8 random bytes 'miller-rabin seed' */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); caam_desc_add_word(desc, prime->p->length); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, 0x01); caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B)); desclen = caam_desc_get_len(desc); /* * Step 11.8 * if p is not a prime continue to step 11.9 */ caam_desc_add_word(desc, HALT_USER(ALL_COND_FALSE, PKHA_IS_PRIME, DSA_NOT_PRIME)); desclen = caam_desc_get_len(desc); /* Test while number of MR test iteration not complete */ caam_desc_add_word(desc, JUMP_CNO_LOCAL_DEC(ALL_COND_FALSE, MATH_0, JMP_COND_MATH(N) | JMP_COND_MATH(Z), retry_mr_test - desclen)); DSA_TRACE("Prime P descriptor"); DSA_DUMPDESC(desc); /* * Ensure descriptor is pushed in physical memory because it's * called from another descriptor. */ cache_operation(TEE_CACHECLEAN, desc, DESC_SZBYTES(PRIME_DESC_ENTRIES)); } /* * Run the Prime Q descriptor. * * @desc Descriptor built */ static enum caam_status run_prime_q(uint32_t *desc, struct prime_data_dsa *prime) { enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; cache_operation(TEE_CACHEFLUSH, prime->q->data, prime->q->length); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus != CAAM_NO_ERROR) { DSA_TRACE("Prime Q Status 0x%08" PRIx32 " ret 0x%08" PRIx32, jobctx.status, retstatus); retstatus = CAAM_FAILURE; } else { cache_operation(TEE_CACHEINVALIDATE, prime->q->data, prime->q->length); DSA_DUMPBUF("Prime Q", prime->q->data, prime->q->length); } return retstatus; } /* * Run the Prime P descriptors. * * @desc Descriptor built * @prime Prime generation data */ static enum caam_status run_prime_p(uint32_t *desc, struct prime_data_dsa *prime) { enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; size_t counter = 0; cache_operation(TEE_CACHEFLUSH, prime->p->data, prime->p->length); jobctx.desc = desc; for (counter = 0; counter < 4 * prime->p->length * 8; counter++) { retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { DSA_TRACE("Prime P try: counter=%zu", counter); cache_operation(TEE_CACHEINVALIDATE, prime->p->data, prime->p->length); DSA_DUMPBUF("Prime P", prime->p->data, prime->p->length); return retstatus; } if (retstatus == CAAM_JOB_STATUS) { if (JRSTA_GET_HALT_USER(jobctx.status) != DSA_NOT_PRIME && JRSTA_GET_HALT_USER(jobctx.status) != DSA_PRIME_TOO_SMALL) { DSA_TRACE("Prime P status 0x%08" PRIx32, jobctx.status); return CAAM_FAILURE; } } } /* This is not a prime, will try with another prime q */ return CAAM_BAD_PARAM; } /* * Generate the DSA parameter G (generator) * Referring to FIPS.186-4, Section A.2.1 Unverifiable Generation of the * Generator g * * @desc Descriptor buffer to use * @prime [in/out] Prime generation data * @mod_n Modular value (0xFF filled buffer) */ static enum caam_status do_generator(uint32_t *desc, struct prime_data_dsa *prime, struct caambuf *mod_n) { enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; unsigned int desclen = 0; unsigned int retry_new_h = 0; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, mod_n->length)); caam_desc_add_ptr(desc, mod_n->paddr); /* * Step 1. * e = (p - 1)/q */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, prime->p->length)); caam_desc_add_ptr(desc, prime->p->paddr); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_ptr(desc, 1); /* PKHA B = (p - 1) */ caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B)); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, prime->q->length)); caam_desc_add_ptr(desc, prime->q->paddr); /* PKHA A = 1/q */ caam_desc_add_word(desc, PKHA_OP(MOD_INV_A, A)); /* PKHA E = (p - 1)/q */ caam_desc_add_word(desc, PKHA_OP(MOD_MUL_A_B, A)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, E)); /* Load N with prime p */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, prime->p->length)); caam_desc_add_ptr(desc, prime->p->paddr); /* * Step 2. Generate a Random h * where 1 < h < (p - 1) * * To ensure h < (p - 1), generate a random of p length - 2 */ retry_new_h = caam_desc_get_len(desc); caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); caam_desc_add_word(desc, prime->p->length - 2); /* * Step 3. * g = h^e mod p */ caam_desc_add_word(desc, PKHA_OP(MOD_EXP_A_E, A)); /* * Step 4. * if (g = 1) then go to step 2 */ desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(PKHA_GCD_1), retry_new_h - desclen)); /* g is good save it */ caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_A, prime->g->length)); caam_desc_add_ptr(desc, prime->g->paddr); DSA_DUMPDESC(desc); cache_operation(TEE_CACHEFLUSH, prime->g->data, prime->g->length); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus != CAAM_NO_ERROR) { DSA_TRACE("Generator G Status 0x%08" PRIx32 " ret 0x%08" PRIx32, jobctx.status, retstatus); return CAAM_FAILURE; } cache_operation(TEE_CACHEINVALIDATE, prime->g->data, prime->g->length); DSA_DUMPBUF("Generator G", prime->g->data, prime->g->length); return CAAM_NO_ERROR; } enum caam_status caam_prime_dsa_gen(struct prime_data_dsa *data) { enum caam_status retstatus = CAAM_FAILURE; uint32_t *desc_all = NULL; uint32_t *desc_q = NULL; uint32_t *desc_x = NULL; uint32_t *desc_p = NULL; struct caambuf seed = { }; struct caambuf mod_n = { }; struct dsa_hash hash_func = { OP_ALGO(SHA256), TEE_SHA256_HASH_SIZE }; size_t nb_tries = 0; struct caambuf x = { }; /* * For the now as the DSA Prime p size is limited to 3072, Prime q * is also limited to 256. Hence the hash function to use is * SHA-256. * Ensure here that limit is not crossed because on some i.MX device * hash is limited to 256. */ if (data->q->length > 256) return CAAM_BAD_PARAM; retstatus = caam_calloc_buf(&mod_n, data->p->length); if (retstatus != CAAM_NO_ERROR) goto out; memset(mod_n.data, 0xFF, mod_n.length); cache_operation(TEE_CACHECLEAN, mod_n.data, mod_n.length); retstatus = caam_calloc_align_buf(&seed, data->q->length); if (retstatus != CAAM_NO_ERROR) return retstatus; retstatus = caam_calloc_buf(&x, data->p->length); if (retstatus != CAAM_NO_ERROR) return retstatus; desc_all = caam_calloc_desc(PRIME_DESC_ENTRIES * 3); if (!desc_all) { retstatus = CAAM_OUT_MEMORY; goto out; } DSA_TRACE("Do primes P %zu bytes, Q %zu bytes", data->p->length, data->q->length); desc_q = desc_all; desc_x = desc_q + PRIME_DESC_ENTRIES; desc_p = desc_x + PRIME_DESC_ENTRIES; do_desc_prime_q(desc_q, &seed, data, &hash_func); do_desc_gen_x(desc_x, &x, &seed, data, &hash_func, &mod_n, virt_to_phys(desc_p)); do_desc_prime_p(desc_p, data, &x, &mod_n); cache_operation(TEE_CACHEFLUSH, data->p->data, data->p->length); cache_operation(TEE_CACHEFLUSH, seed.data, seed.length); cache_operation(TEE_CACHEFLUSH, x.data, x.length); for (nb_tries = DSA_MAX_TRIES_PRIME_P; nb_tries > 0; nb_tries--) { retstatus = run_prime_q(desc_q, data); if (retstatus == CAAM_NO_ERROR) { retstatus = run_prime_p(desc_x, data); if (retstatus == CAAM_NO_ERROR) break; } if (retstatus == CAAM_FAILURE) { DSA_TRACE("DSA Prime P/Q Generation failed"); break; } } if (retstatus == CAAM_NO_ERROR) retstatus = do_generator(desc_all, data, &mod_n); out: caam_free_desc(&desc_all); caam_free_buf(&seed); caam_free_buf(&x); caam_free_buf(&mod_n); return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_prime_rsa.c000066400000000000000000001045641464416617300247310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021, 2023 NXP * * CAAM Prime Numbering. * Implementation of Prime Number functions */ #include #include #include #include #include #include #include #include #include #include "local.h" #define RSA_TRY_FAIL 0x42 #define RETRY_TOO_SMALL 0x2A #define STATUS_GOOD_Q 0xCA #define MR_PRIME_SIZE 1536 #define MAX_RETRY_PRIME_GEN 1000 #define RSA_MAX_TRIES_PRIMES 100 #ifdef CFG_CAAM_64BIT #define SETUP_RSA_DESC_ENTRIES 20 #define GEN_RSA_DESC_ENTRIES 62 #define CHECK_P_Q_DESC_ENTRIES 32 #else #define SETUP_RSA_DESC_ENTRIES 17 #define GEN_RSA_DESC_ENTRIES 58 #define CHECK_P_Q_DESC_ENTRIES 29 #endif /* * Predefined const value corresponding to the * operation sqrt(2) * (2 ^ ((nlen / 2) - 1)) * Used at step 4.4 */ static const uint8_t sqrt_value[] = { 0xb5, 0x04, 0xf3, 0x33, 0xf9, 0xde, 0x64, 0x84, 0x59, 0x7d, 0x89, 0xb3, 0x75, 0x4a, 0xbe, 0x9f, 0x1d, 0x6f, 0x60, 0xba, 0x89, 0x3b, 0xa8, 0x4c, 0xed, 0x17, 0xac, 0x85, 0x83, 0x33, 0x99, 0x15, 0x4a, 0xfc, 0x83, 0x04, 0x3a, 0xb8, 0xa2, 0xc3, 0xa8, 0xb1, 0xfe, 0x6f, 0xdc, 0x83, 0xdb, 0x39, 0x0f, 0x74, 0xa8, 0x5e, 0x43, 0x9c, 0x7b, 0x4a, 0x78, 0x04, 0x87, 0x36, 0x3d, 0xfa, 0x27, 0x68, 0xd2, 0x20, 0x2e, 0x87, 0x42, 0xaf, 0x1f, 0x4e, 0x53, 0x05, 0x9c, 0x60, 0x11, 0xbc, 0x33, 0x7b, 0xca, 0xb1, 0xbc, 0x91, 0x16, 0x88, 0x45, 0x8a, 0x46, 0x0a, 0xbc, 0x72, 0x2f, 0x7c, 0x4e, 0x33, 0xc6, 0xd5, 0xa8, 0xa3, 0x8b, 0xb7, 0xe9, 0xdc, 0xcb, 0x2a, 0x63, 0x43, 0x31, 0xf3, 0xc8, 0x4d, 0xf5, 0x2f, 0x12, 0x0f, 0x83, 0x6e, 0x58, 0x2e, 0xea, 0xa4, 0xa0, 0x89, 0x90, 0x40, 0xca, 0x4a, 0x81, 0x39, 0x4a, 0xb6, 0xd8, 0xfd, 0x0e, 0xfd, 0xf4, 0xd3, 0xa0, 0x2c, 0xeb, 0xc9, 0x3e, 0x0c, 0x42, 0x64, 0xda, 0xbc, 0xd5, 0x28, 0xb6, 0x51, 0xb8, 0xcf, 0x34, 0x1b, 0x6f, 0x82, 0x36, 0xc7, 0x01, 0x04, 0xdc, 0x01, 0xfe, 0x32, 0x35, 0x2f, 0x33, 0x2a, 0x5e, 0x9f, 0x7b, 0xda, 0x1e, 0xbf, 0xf6, 0xa1, 0xbe, 0x3f, 0xca, 0x22, 0x13, 0x07, 0xde, 0xa0, 0x62, 0x41, 0xf7, 0xaa, 0x81, 0xc2, 0xc1, 0xfc, 0xbd, 0xde, 0xa2, 0xf7, 0xdc, 0x33, 0x18, 0x83, 0x8a, 0x2e, 0xaf, 0xf5, 0xf3, 0xb2, 0xd2, 0x4f, 0x4a, 0x76, 0x3f, 0xac, 0xb8, 0x82, 0xfd, 0xfe, 0x17, 0x0f, 0xd3, 0xb1, 0xf7, 0x80, 0xf9, 0xac, 0xce, 0x41, 0x79, 0x7f, 0x28, 0x05, 0xc2, 0x46, 0x78, 0x5e, 0x92, 0x95, 0x70, 0x23, 0x5f, 0xcf, 0x8f, 0x7b, 0xca, 0x3e, 0xa3, 0x3b, 0x4d, 0x7c, 0x60, 0xa5, 0xe6, 0x33, 0xe3, 0xe1 }; /* * Speedups for prime searching * * These values are products of small primes. Information about the product * preceeds it. These values have been pre-computed by the CAAM design team. * * Per Handbook of Applied Cryptography, Menezes et al, 4.4.1, one can compute * the percentage of non-primes weeded out by checking for small prime factors * in the candidates. In the table below, "highest prime" is used for B, and * "%weeded" is the number of candidates which get through this * sieve. As you can see, even with relatively few primes, there are * diminishing returns to using larger numbers of primes. * * Percentage weeded: 1 - 1.12/ln B * * These can be used to compute GCD(prime, smallprime) before the Miller * Rabin; this will weed out those candidates with 'small' primes before doing * the costly modular exponentation inside of Miller-Rabin. (If the result is * not one, then the candidate has as a factor at least one of the small primes * in the product). * * So, where is the sweet spot for the size of the product versus the size of * the candidate? Does it depend upon the size of the PKHA multiplier? Hunt * time for primes takes a long time to actually compute, and what are the * stats for percentage of candidates that might be weeded out? If not many, * then there is an extra computation. */ struct smallprime { const size_t length; const uint8_t *data; }; /* sizes | #primes | highest prime | %weeded */ /* bits / bytes | | */ /* 64 / 8 | 15 | 53 | 72 */ static const uint8_t smallprime_8[] = { 0xe2, 0x21, 0xf9, 0x7c, 0x30, 0xe9, 0x4e, 0x1d, }; /* 128 / 16 | 25 | 101 | 76 */ static const uint8_t smallprime_16[] = { 0x57, 0x97, 0xd4, 0x7c, 0x51, 0x68, 0x15, 0x49, 0xd7, 0x34, 0xe4, 0xfc, 0x4c, 0x3e, 0xaf, 0x7f, }; /* 256 / 32 | 43 | 193 | 79 */ static const uint8_t smallprime_32[] = { 0xdb, 0xf0, 0x5b, 0x6f, 0x56, 0x54, 0xb3, 0xc0, 0xf5, 0x24, 0x35, 0x51, 0x43, 0x95, 0x86, 0x88, 0x9f, 0x15, 0x58, 0x87, 0x81, 0x9a, 0xed, 0x2a, 0xc0, 0x5b, 0x93, 0x35, 0x2b, 0xe9, 0x86, 0x77, }; /* 384 / 48 | 59 | 281 | 80 */ static const uint8_t smallprime_48[] = { 0x50, 0x12, 0x01, 0xcc, 0x51, 0xa4, 0x92, 0xa5, 0x44, 0xd3, 0x90, 0x0a, 0xd4, 0xf8, 0xb3, 0x2a, 0x20, 0x3c, 0x85, 0x84, 0x06, 0xa4, 0x45, 0x7c, 0xab, 0x0b, 0x4f, 0x80, 0x5a, 0xb1, 0x8a, 0xc6, 0xeb, 0x95, 0x72, 0xac, 0x6e, 0x93, 0x94, 0xfa, 0x52, 0x2b, 0xff, 0xb6, 0xf4, 0x4a, 0xf2, 0xf3, }; /* 512 / 64 | 74 | 379 | 81 */ static const uint8_t smallprime_64[] = { 0x10, 0x6a, 0xa9, 0xfb, 0x76, 0x46, 0xfa, 0x6e, 0xb0, 0x81, 0x3c, 0x28, 0xc5, 0xd5, 0xf0, 0x9f, 0x07, 0x7e, 0xc3, 0xba, 0x23, 0x8b, 0xfb, 0x99, 0xc1, 0xb6, 0x31, 0xa2, 0x03, 0xe8, 0x11, 0x87, 0x23, 0x3d, 0xb1, 0x17, 0xcb, 0xc3, 0x84, 0x05, 0x6e, 0xf0, 0x46, 0x59, 0xa4, 0xa1, 0x1d, 0xe4, 0x9f, 0x7e, 0xcb, 0x29, 0xba, 0xda, 0x8f, 0x98, 0x0d, 0xec, 0xec, 0xe9, 0x2e, 0x30, 0xc4, 0x8f, }; /* 576 / 72 | 81 | 421 | 82 */ static const uint8_t smallprime_72[] = { 0x01, 0x85, 0xdb, 0xeb, 0x2b, 0x8b, 0x11, 0xd3, 0x76, 0x33, 0xe9, 0xdc, 0x1e, 0xec, 0x54, 0x15, 0x65, 0xc6, 0xce, 0x84, 0x31, 0xd2, 0x27, 0xee, 0x28, 0xf0, 0x32, 0x8a, 0x60, 0xc9, 0x01, 0x18, 0xae, 0x03, 0x1c, 0xc5, 0xa7, 0x81, 0xc8, 0x24, 0xd1, 0xf1, 0x6d, 0x25, 0xf4, 0xf0, 0xcc, 0xcf, 0xf3, 0x5e, 0x97, 0x45, 0x79, 0x07, 0x2e, 0xc8, 0xca, 0xf1, 0xac, 0x8e, 0xef, 0xd5, 0x56, 0x6f, 0xa1, 0x5f, 0xb9, 0x4f, 0xe3, 0x4f, 0x5d, 0x37, }; /* 768 / 96 | 103 | 569 | 82 */ static const uint8_t smallprime_96[] = { 0x25, 0xea, 0xc8, 0x9f, 0x8d, 0x4d, 0xa3, 0x38, 0x33, 0x7b, 0x49, 0x85, 0x0d, 0x2d, 0x14, 0x89, 0x26, 0x63, 0x17, 0x7b, 0x40, 0x10, 0xaf, 0x3d, 0xd2, 0x3e, 0xeb, 0x0b, 0x22, 0x8f, 0x38, 0x32, 0xff, 0xce, 0xe2, 0xe5, 0xcb, 0xd1, 0xac, 0xc9, 0x8f, 0x47, 0xf2, 0x51, 0x87, 0x33, 0x80, 0xae, 0x10, 0xf0, 0xff, 0xdd, 0x8e, 0x60, 0x2f, 0xfa, 0x21, 0x0f, 0x41, 0xf6, 0x69, 0xa1, 0x57, 0x0a, 0x93, 0xc1, 0x58, 0xc1, 0xa9, 0xa8, 0x22, 0x7f, 0xf8, 0x1a, 0x90, 0xc5, 0x63, 0x0e, 0x9c, 0x44, 0x84, 0x5c, 0x75, 0x5c, 0x7d, 0xf3, 0x5a, 0x7d, 0x43, 0x0c, 0x67, 0x9a, 0x11, 0x57, 0x56, 0x55, }; /* 1024 / 128 | 130 | 739 | 83 */ static const uint8_t smallprime_128[] = { 0x02, 0xc8, 0x5f, 0xf8, 0x70, 0xf2, 0x4b, 0xe8, 0x0f, 0x62, 0xb1, 0xba, 0x6c, 0x20, 0xbd, 0x72, 0xb8, 0x37, 0xef, 0xdf, 0x12, 0x12, 0x06, 0xd8, 0x7d, 0xb5, 0x6b, 0x7d, 0x69, 0xfa, 0x4c, 0x02, 0x1c, 0x10, 0x7c, 0x3c, 0xa2, 0x06, 0xfe, 0x8f, 0xa7, 0x08, 0x0e, 0xf5, 0x76, 0xef, 0xfc, 0x82, 0xf9, 0xb1, 0x0f, 0x57, 0x50, 0x65, 0x6b, 0x77, 0x94, 0xb1, 0x6a, 0xfd, 0x70, 0x99, 0x6e, 0x91, 0xae, 0xf6, 0xe0, 0xad, 0x15, 0xe9, 0x1b, 0x07, 0x1a, 0xc9, 0xb2, 0x4d, 0x98, 0xb2, 0x33, 0xad, 0x86, 0xee, 0x05, 0x55, 0x18, 0xe5, 0x8e, 0x56, 0x63, 0x8e, 0xf1, 0x8b, 0xac, 0x5c, 0x74, 0xcb, 0x35, 0xbb, 0xb6, 0xe5, 0xda, 0xe2, 0x78, 0x3d, 0xd1, 0xc0, 0xce, 0x7d, 0xec, 0x4f, 0xc7, 0x0e, 0x51, 0x86, 0xd4, 0x11, 0xdf, 0x36, 0x36, 0x8f, 0x06, 0x1a, 0xa3, 0x60, 0x11, 0xf3, 0x01, 0x79, }; /* 1088 / 184 | 136 | 787 | 83 */ static const uint8_t smallprime_184[] = { 0x16, 0xaf, 0x5c, 0x18, 0xa2, 0xbe, 0xf8, 0xef, 0xf2, 0x27, 0x83, 0x32, 0x18, 0x2d, 0x0f, 0xbf, 0x00, 0x38, 0xcc, 0x20, 0x51, 0x48, 0xb8, 0x3d, 0x06, 0xe3, 0xd7, 0xd9, 0x32, 0x82, 0x8b, 0x18, 0xe1, 0x1e, 0x09, 0x40, 0x28, 0xc7, 0xea, 0xed, 0xa3, 0x39, 0x50, 0x17, 0xe0, 0x7d, 0x8a, 0xe9, 0xb5, 0x94, 0x06, 0x04, 0x51, 0xd0, 0x5f, 0x93, 0x08, 0x4c, 0xb4, 0x81, 0x66, 0x3c, 0x94, 0xc6, 0xff, 0x98, 0x0d, 0xde, 0xcc, 0xdb, 0x42, 0xad, 0x37, 0x09, 0x7f, 0x41, 0xa7, 0x83, 0x7f, 0xc9, 0x5a, 0xfe, 0x3f, 0x18, 0xad, 0x76, 0xf2, 0x34, 0x83, 0xae, 0x94, 0x2e, 0x0f, 0x0c, 0x0b, 0xc6, 0xe4, 0x00, 0x16, 0x12, 0x31, 0x89, 0x87, 0x2b, 0xe5, 0x8f, 0x6d, 0xfc, 0x23, 0x9c, 0xa2, 0x8f, 0xb0, 0xcf, 0xbf, 0x96, 0x4c, 0x8f, 0x27, 0xce, 0x05, 0xd6, 0xc7, 0x7a, 0x01, 0xf9, 0xd3, 0x32, 0x36, 0xc9, 0xd4, 0x42, 0xad, 0x69, 0xed, 0x33, }; /* 1536 / 192 | 182 | 1093 | 84 */ static const uint8_t smallprime_192[] = { 0x02, 0x1b, 0xf9, 0x49, 0x70, 0x91, 0xb8, 0xc3, 0x68, 0xcc, 0x7c, 0x8e, 0x00, 0xc1, 0x99, 0x0c, 0x60, 0x27, 0x48, 0x1b, 0x79, 0x21, 0x5a, 0xc8, 0xa7, 0x51, 0x77, 0x49, 0xa2, 0x15, 0x13, 0x77, 0x9a, 0x99, 0x3d, 0x29, 0x58, 0xfc, 0xb4, 0x9a, 0x73, 0x68, 0x02, 0x92, 0x68, 0x52, 0x79, 0x94, 0xc6, 0xcc, 0x19, 0x28, 0xad, 0xd4, 0x12, 0x95, 0x96, 0x76, 0x5f, 0x4c, 0xc3, 0x14, 0x1a, 0x04, 0x4e, 0xb1, 0xd6, 0x15, 0x78, 0x88, 0x16, 0x67, 0x57, 0xd8, 0x61, 0x87, 0x81, 0x81, 0x30, 0x62, 0x03, 0x22, 0x67, 0x98, 0x7d, 0xf0, 0xd4, 0x71, 0x9c, 0xd3, 0x8f, 0x1b, 0x70, 0x85, 0xfc, 0xa5, 0x33, 0x4b, 0xe3, 0xa6, 0x00, 0x3a, 0x3c, 0xe7, 0xe1, 0x9a, 0xba, 0x55, 0x3e, 0x80, 0xcc, 0x5a, 0xe4, 0x06, 0x0e, 0xff, 0x6e, 0x18, 0x06, 0x66, 0x1d, 0xa5, 0xee, 0xb7, 0xd1, 0x42, 0xd3, 0xb2, 0xe4, 0x07, 0x39, 0xf1, 0x44, 0x3d, 0xee, 0x3a, 0x19, 0x86, 0x37, 0xf0, 0x3c, 0x06, 0x28, 0x45, 0xea, 0xff, 0x3f, 0xf2, 0x7e, 0xa3, 0x8d, 0x93, 0x44, 0xd8, 0xa9, 0x02, 0x22, 0x47, 0x2d, 0xf0, 0x7d, 0xfb, 0x5c, 0x9c, 0x8a, 0xda, 0x77, 0xcd, 0x0d, 0x5b, 0x94, 0xef, 0xf0, 0x21, 0xe0, 0x2e, 0x30, 0x7d, 0x08, 0x01, 0x03, 0x12, 0xd5, 0x7c, 0xb5, 0xd9, 0x75, 0x76, 0x46, 0x97, 0x84, 0x2d, }; /* 2048 / 256 | 232 | 1471 | 85 */ static const uint8_t smallprime_256[] = { 0x24, 0x65, 0xa7, 0xbd, 0x85, 0x01, 0x1e, 0x1c, 0x9e, 0x05, 0x27, 0x92, 0x9f, 0xff, 0x26, 0x8c, 0x82, 0xef, 0x7e, 0xfa, 0x41, 0x68, 0x63, 0xba, 0xa5, 0xac, 0xdb, 0x09, 0x71, 0xdb, 0xa0, 0xcc, 0xac, 0x3e, 0xe4, 0x99, 0x93, 0x45, 0x02, 0x9f, 0x2c, 0xf8, 0x10, 0xb9, 0x9e, 0x40, 0x6a, 0xac, 0x5f, 0xce, 0x5d, 0xd6, 0x9d, 0x1c, 0x71, 0x7d, 0xae, 0xa5, 0xd1, 0x8a, 0xb9, 0x13, 0xf4, 0x56, 0x50, 0x56, 0x79, 0xbc, 0x91, 0xc5, 0x7d, 0x46, 0xd9, 0x88, 0x88, 0x57, 0x86, 0x2b, 0x36, 0xe2, 0xed, 0xe2, 0xe4, 0x73, 0xc1, 0xf0, 0xab, 0x35, 0x9d, 0xa2, 0x52, 0x71, 0xaf, 0xfe, 0x15, 0xff, 0x24, 0x0e, 0x29, 0x9d, 0x0b, 0x04, 0xf4, 0xcd, 0x0e, 0x4d, 0x7c, 0x0e, 0x47, 0xb1, 0xa7, 0xba, 0x00, 0x7d, 0xe8, 0x9a, 0xae, 0x84, 0x8f, 0xd5, 0xbd, 0xcd, 0x7f, 0x98, 0x15, 0x56, 0x4e, 0xb0, 0x60, 0xae, 0x14, 0xf1, 0x9c, 0xb5, 0x0c, 0x29, 0x1f, 0x0b, 0xbd, 0x8e, 0xd1, 0xc4, 0xc7, 0xf8, 0xfc, 0x5f, 0xba, 0x51, 0x66, 0x20, 0x01, 0x93, 0x9b, 0x53, 0x2d, 0x92, 0xda, 0xc8, 0x44, 0xa8, 0x43, 0x1d, 0x40, 0x0c, 0x83, 0x2d, 0x03, 0x9f, 0x5f, 0x90, 0x0b, 0x27, 0x8a, 0x75, 0x21, 0x9c, 0x29, 0x86, 0x14, 0x0c, 0x79, 0x04, 0x5d, 0x77, 0x59, 0x54, 0x08, 0x54, 0xc3, 0x15, 0x04, 0xdc, 0x56, 0xf1, 0xdf, 0x5e, 0xeb, 0xe7, 0xbe, 0xe4, 0x47, 0x65, 0x8b, 0x91, 0x7b, 0xf6, 0x96, 0xd6, 0x92, 0x7f, 0x2e, 0x24, 0x28, 0xfb, 0xeb, 0x34, 0x0e, 0x51, 0x5c, 0xb9, 0x83, 0x5d, 0x63, 0x87, 0x1b, 0xe8, 0xbb, 0xe0, 0x9c, 0xf1, 0x34, 0x45, 0x79, 0x9f, 0x2e, 0x67, 0x78, 0x81, 0x51, 0x57, 0x1a, 0x93, 0xb4, 0xc1, 0xee, 0xe5, 0x5d, 0x1b, 0x90, 0x72, 0xe0, 0xb2, 0xf5, 0xc4, 0x60, 0x7f, }; /* 3072 / 384 | 326 | 2179 | 85 */ static const uint8_t smallprime_384[] = { 0x00, 0x4d, 0xc2, 0x0e, 0x27, 0x31, 0x51, 0x23, 0xfd, 0xab, 0xcd, 0x18, 0xca, 0x81, 0x2e, 0xe0, 0xee, 0x44, 0x49, 0x23, 0x87, 0x38, 0x9e, 0xd6, 0xc9, 0x16, 0x97, 0x95, 0x89, 0x65, 0xed, 0xc5, 0x3d, 0x89, 0x13, 0xa8, 0xe6, 0xec, 0x7f, 0x83, 0x6a, 0x8b, 0xd6, 0x03, 0x7e, 0x57, 0xed, 0x0c, 0x69, 0x30, 0xef, 0x26, 0x49, 0x0d, 0xc3, 0x5d, 0x05, 0xd0, 0x98, 0xa4, 0x66, 0xad, 0xf8, 0x17, 0x9f, 0x82, 0x99, 0x69, 0xd1, 0x39, 0x55, 0x8f, 0x16, 0xe9, 0x8b, 0x3f, 0x76, 0xfc, 0x90, 0x62, 0xc1, 0x57, 0x25, 0xce, 0x09, 0x88, 0xfa, 0xed, 0xca, 0x96, 0x6a, 0x6b, 0x92, 0x5f, 0x9b, 0x9c, 0x67, 0x03, 0x43, 0xea, 0x7e, 0x84, 0x20, 0x65, 0xbd, 0x26, 0xf2, 0xbf, 0x29, 0x90, 0x4f, 0xa7, 0xf4, 0x9f, 0x33, 0x49, 0x28, 0x96, 0x33, 0x73, 0xba, 0x08, 0x95, 0x96, 0x51, 0x3d, 0xac, 0xa7, 0x39, 0x28, 0xcf, 0x30, 0x5a, 0xdf, 0x8c, 0x24, 0x6e, 0x1d, 0x99, 0xa2, 0x42, 0xd9, 0x23, 0x56, 0x23, 0xc4, 0x9a, 0xf2, 0x91, 0x45, 0x06, 0xc9, 0x11, 0x21, 0x5e, 0x1e, 0x49, 0xaf, 0x84, 0x80, 0x3e, 0xd9, 0xa2, 0xca, 0x05, 0x51, 0x72, 0x1f, 0xe6, 0x31, 0x9b, 0xf2, 0x38, 0xc0, 0x8a, 0xae, 0x6f, 0xd5, 0x01, 0x54, 0x03, 0xd9, 0xe5, 0x55, 0x09, 0xee, 0x31, 0xc9, 0x60, 0x12, 0xf9, 0x08, 0x35, 0x18, 0x5f, 0x31, 0xcb, 0xd2, 0xe4, 0x89, 0x83, 0x3c, 0x1d, 0x54, 0x62, 0xfa, 0x80, 0x53, 0x59, 0x04, 0x86, 0x7b, 0x2c, 0x94, 0x5e, 0x9a, 0x0c, 0x2f, 0x7a, 0xa3, 0x6e, 0x0a, 0xc0, 0xeb, 0x9b, 0xb4, 0xc1, 0x1b, 0xf5, 0x80, 0xcf, 0x0d, 0x6d, 0x2a, 0x49, 0xed, 0x1a, 0x2d, 0x74, 0xca, 0xe0, 0xf4, 0xc3, 0xad, 0xff, 0x61, 0xd6, 0x48, 0xca, 0x6a, 0x12, 0x08, 0x58, 0xf4, 0xab, 0xb3, 0xb3, 0x12, 0x07, 0xcf, 0x9b, 0x7c, 0x2f, 0xda, 0x74, 0xf7, 0x72, 0x2b, 0x14, 0x99, 0x17, 0x87, 0x5a, 0xac, 0x9d, 0x61, 0x53, 0xc9, 0x71, 0x13, 0xfc, 0xd3, 0x74, 0xaf, 0x93, 0xdd, 0x3f, 0xa2, 0x1a, 0x7d, 0xe5, 0x1f, 0x1a, 0x70, 0xc6, 0x31, 0xba, 0x6c, 0x92, 0x26, 0x1e, 0x89, 0x54, 0x1a, 0xa4, 0x71, 0x41, 0xf4, 0x4e, 0x07, 0x5a, 0x1c, 0x52, 0x2a, 0xe5, 0x81, 0x60, 0xda, 0xc8, 0x70, 0xdf, 0xbd, 0x86, 0x06, 0xe4, 0xec, 0xa0, 0x89, 0x2a, 0xe5, 0x1c, 0x87, 0x34, 0xf5, 0xb7, 0x71, 0x2b, 0xcd, 0x3d, 0xe3, 0x32, 0x5e, 0xc2, 0x5f, 0x07, 0xd4, 0xef, 0x94, 0x33, 0x94, 0xd5, 0xe7, 0xb3, 0x84, 0x10, 0x05, 0xa3, 0xbd, 0x1a, 0x3e, 0x4d, 0x27, 0x06, 0x1d, 0x54, 0xd2, 0x44, 0x58, 0x24, 0xf8, 0x51, 0x17, 0xd0, 0xf6, 0x97, 0x12, 0x84, 0xa8, 0xc9, 0x7a, 0x42, 0x50, 0xb9, 0x9b, }; /* 4096 / 512 | 417 | 2887 | 86 */ static const uint8_t smallprime_512[] = { 0x09, 0x62, 0x07, 0xfc, 0xcb, 0x19, 0xd6, 0x75, 0x8e, 0x37, 0x4b, 0xee, 0x6c, 0x37, 0x09, 0xaf, 0x0a, 0x54, 0xa9, 0x82, 0xbf, 0x90, 0x14, 0xe4, 0x50, 0xb7, 0x48, 0x18, 0x13, 0xb7, 0x30, 0x5b, 0x4c, 0x25, 0xf0, 0xe2, 0xea, 0x6e, 0x2b, 0x56, 0xf9, 0x1e, 0x59, 0x92, 0x14, 0x2d, 0x21, 0x6e, 0xae, 0xb2, 0xec, 0xe0, 0x05, 0xfa, 0x0d, 0x18, 0xef, 0xeb, 0x78, 0xef, 0xc3, 0x41, 0xf3, 0x1f, 0x78, 0x3e, 0xe4, 0x4a, 0xc5, 0xef, 0x5d, 0xfe, 0x35, 0x57, 0x91, 0x28, 0x21, 0x06, 0x15, 0x6c, 0x64, 0xd1, 0x67, 0xa5, 0x42, 0x1c, 0xfe, 0xc3, 0x3c, 0xbb, 0xd3, 0x88, 0x38, 0x0b, 0xe8, 0x54, 0x14, 0x9f, 0xb6, 0x5c, 0x08, 0xe7, 0x9c, 0xd0, 0x4e, 0xc4, 0x8b, 0x45, 0x62, 0x8e, 0xe6, 0x7f, 0x5c, 0x6f, 0xb0, 0x18, 0x18, 0xfa, 0x1f, 0xf7, 0x32, 0x24, 0x0c, 0x0b, 0xb1, 0xc7, 0xfe, 0xc1, 0x4c, 0x48, 0x23, 0x4c, 0x6f, 0xc3, 0xe0, 0x75, 0x76, 0x4f, 0x63, 0xc0, 0x26, 0x83, 0x61, 0x83, 0x1d, 0x89, 0x60, 0xf2, 0x4b, 0x23, 0x7e, 0x96, 0xc2, 0xca, 0xba, 0x4c, 0x1a, 0x21, 0x23, 0xff, 0x33, 0xa4, 0x9b, 0xca, 0x39, 0x49, 0xe8, 0xab, 0xad, 0xde, 0x06, 0xda, 0xc5, 0x70, 0x3d, 0x16, 0xdb, 0x76, 0x77, 0xdf, 0x2b, 0x0c, 0xe2, 0xc7, 0x84, 0x85, 0xeb, 0xd5, 0xe6, 0x9b, 0xd8, 0x0a, 0x18, 0x48, 0xa9, 0xfe, 0x28, 0x9c, 0xa2, 0xba, 0x66, 0x4a, 0x68, 0x7b, 0x3f, 0x05, 0x40, 0x15, 0x6e, 0x67, 0xae, 0x67, 0x69, 0xc0, 0x9e, 0x11, 0xce, 0x56, 0x73, 0x57, 0xf5, 0xa5, 0x76, 0xa4, 0x8e, 0xed, 0xd9, 0x63, 0x35, 0xe6, 0x28, 0x77, 0xc7, 0x3a, 0x65, 0x40, 0x8b, 0x71, 0x48, 0x4e, 0xd0, 0xf1, 0x1d, 0x20, 0xd5, 0x1e, 0x8e, 0x54, 0x67, 0xa1, 0xe4, 0xc0, 0x9b, 0xf7, 0x29, 0xba, 0x16, 0x9f, 0xcf, 0xdb, 0xa8, 0xb5, 0x5c, 0x4c, 0x5b, 0x68, 0x2f, 0xaa, 0x28, 0x71, 0x9b, 0x9f, 0x49, 0xbf, 0x36, 0x2d, 0x9f, 0x03, 0xee, 0x6b, 0xde, 0x79, 0x01, 0xe9, 0x40, 0xe2, 0x49, 0xb4, 0x1c, 0x93, 0xb9, 0xab, 0x05, 0x4a, 0xbc, 0xab, 0x10, 0x9a, 0xf1, 0x2a, 0xa6, 0x53, 0x5e, 0xd8, 0xf6, 0x23, 0xab, 0xfd, 0x31, 0x2a, 0xaa, 0x08, 0x4a, 0x74, 0x8f, 0x86, 0x53, 0x83, 0xbc, 0xe3, 0x15, 0xdc, 0x0d, 0x45, 0xcb, 0x89, 0x50, 0x8d, 0xec, 0xa9, 0x3b, 0xda, 0x22, 0xf0, 0xe7, 0x7a, 0x4f, 0xea, 0xa2, 0xa7, 0x90, 0xe0, 0x0e, 0x5a, 0xda, 0x9b, 0xbb, 0x9a, 0xe7, 0xd5, 0xfb, 0x63, 0x54, 0xa2, 0x52, 0xda, 0x7d, 0xc2, 0x6e, 0x6a, 0xc2, 0xd7, 0xa6, 0x42, 0xea, 0xbf, 0x48, 0x12, 0xe6, 0x4a, 0xe1, 0x95, 0xbf, 0x29, 0xcc, 0x9e, 0xe0, 0x25, 0x84, 0xb7, 0x74, 0xdc, 0xb1, 0x12, 0x91, 0x57, 0xbf, 0x52, 0x43, 0x8f, 0xb7, 0xb7, 0xcd, 0x6a, 0x78, 0x24, 0xa7, 0x41, 0x8b, 0xcc, 0x65, 0x83, 0x05, 0x8e, 0xc2, 0xf0, 0x69, 0x28, 0xe4, 0x42, 0x62, 0x37, 0x98, 0xb5, 0x03, 0xf6, 0x75, 0x1d, 0xce, 0xe2, 0xc0, 0x1f, 0x39, 0xac, 0xb0, 0xfb, 0x47, 0x8f, 0x6e, 0x8b, 0x16, 0xa3, 0x0f, 0xe8, 0x21, 0x9b, 0x8e, 0x67, 0x04, 0xc7, 0x26, 0xb6, 0x03, 0xe1, 0x00, 0x09, 0xf6, 0x77, 0x76, 0x46, 0x51, 0x41, 0x57, 0x0d, 0x4b, 0x4c, 0x2a, 0x30, 0xdb, 0x84, 0x02, 0x6f, 0x93, 0x4b, 0x81, 0xf0, 0xd5, 0xe9, 0x85, 0xc9, 0x75, 0xd6, 0xa9, 0x07, 0x5a, 0x41, 0xd4, 0x17, 0xc6, 0xd9, 0x93, 0xcb, 0x49, 0x73, 0xcb, 0xe5, 0x12, 0xa6, 0x7d, 0xb3, 0x1f, 0x6a, 0xec, 0x8c, 0xc3, 0xe9, 0xe5, 0xeb, 0xdc, 0x1e, 0xb7, 0xb4, 0x74, 0x54, 0x51, 0x52, 0xa1, 0x56, 0xd5, 0xac, 0x58, 0x7d, }; static const struct smallprime smallprimes[] = { { .data = smallprime_8, .length = sizeof(smallprime_8) }, { .data = smallprime_16, .length = sizeof(smallprime_16) }, { .data = smallprime_32, .length = sizeof(smallprime_32) }, { .data = smallprime_48, .length = sizeof(smallprime_48) }, { .data = smallprime_64, .length = sizeof(smallprime_64) }, { .data = smallprime_72, .length = sizeof(smallprime_72) }, { .data = smallprime_96, .length = sizeof(smallprime_96) }, { .data = smallprime_128, .length = sizeof(smallprime_128) }, { .data = smallprime_184, .length = sizeof(smallprime_184) }, { .data = smallprime_192, .length = sizeof(smallprime_192) }, { .data = smallprime_256, .length = sizeof(smallprime_256) }, { .data = smallprime_384, .length = sizeof(smallprime_384) }, { .data = smallprime_512, .length = sizeof(smallprime_512) }, }; /* * Search the small prime closed to the given input bytes size * * @size Size in bytes * @prime [out] Output predefined small prime */ static void search_smallprime(size_t size, struct caambuf *prime) { size_t nb_elem = ARRAY_SIZE(smallprimes); size_t idx = 0; size_t psize = 0; for (; idx < nb_elem; idx++) { psize = smallprimes[idx].length; if (psize == size) { /* Found a predefined prime */ RSA_TRACE("Found prime idx %zu", idx); prime->data = (uint8_t *)smallprimes[idx].data; prime->length = psize; prime->paddr = virt_to_phys(prime->data); break; } } } /* * Build the descriptor preparing the CAAM global variables used during the * prime generation * * @desc [out] Descriptor built * @data Prime generation data * @small_prime Pre-generated small prime value * @desc_prime Physical address of the prime generator descriptor */ static void do_desc_setup(uint32_t *desc, struct prime_data_rsa *data, const struct caambuf *small_prime, const paddr_t desc_prime) { size_t key_size = data->key_size / 8; /* * Referring to FIPS.186-4, B.3.3 (step 4.7) * Maximum tries = 5 * (nlen / 2) * Where nlen is the RSA security length in bit */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SOL, 4)); caam_desc_add_word(desc, 5 * (data->key_size / 2)); /* * Referring to FIPS.186-4, Table C.2 * Get the number Miller-Rabin test interation function * of the prime number size */ caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SIL, 4)); if ((key_size / 2) > (MR_PRIME_SIZE / 8)) caam_desc_add_word(desc, 0x4); else caam_desc_add_word(desc, 0x5); /* * Preload PKHA A2 with the sqrt_value array (step 4.4) * Do it once, not at each loop */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A2, NOACTION, key_size / 2)); caam_desc_add_ptr(desc, virt_to_phys((void *)sqrt_value)); if (data->era >= 8 && small_prime->paddr) { /* * Preload PKHA B2 with small prime predefined * (preload only prime size requested) * * Before Era 8, the PRIME TEST function overwrites PKHA B2 * hence PKHA B2 must be reloaded if new prime tentative after * PRIME TEST on Era < 8 */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B2, NOACTION, small_prime->length)); caam_desc_add_ptr(desc, small_prime->paddr); } /* Set the High order bit used to turn on MSB in prime candidate */ caam_desc_add_word(desc, MATHI_OP1(SHIFT_L, ONE, 0x3F, REG2, 8)); /* Load PKHA N Size with the prime size */ caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4)); caam_desc_add_word(desc, key_size / 2); /* * Set the number of maximum tries because of generated value * is too small. This value is used to not lock the system * in prime number generation */ caam_desc_add_word(desc, MATH(ADD, ZERO, IMM_DATA, DPOVRD, 4)); caam_desc_add_word(desc, MAX_RETRY_PRIME_GEN); /* Jump to the next descriptor desc */ caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, JMP_COND(NONE))); caam_desc_add_ptr(desc, desc_prime); RSA_DUMPDESC(desc); cache_operation(TEE_CACHECLEAN, (void *)sqrt_value, data->p->length); } /* * Build the descriptor generating a prime * * @desc [out] Descriptor built * @data Prime generation data * @small_prime Pre-generated small prime value * @do_prime_q Generate Prime Q * @desc_next Physical address of the next descriptor (can be NULL) */ static void do_desc_prime(uint32_t *desc, struct prime_data_rsa *data, const struct caambuf *small_prime, bool do_prime_q, const paddr_t desc_next) { uint32_t desclen = 0; uint32_t retry_too_small = 0; uint32_t retry_new_number = 0; uint32_t retry_new_mr_failed = 0; uint32_t retry_mr_test = 0; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* Setup the number of try counter = MAX (counting down) */ caam_desc_add_word(desc, MATH(ADD, SOL, ZERO, VSOL, 4)); retry_new_mr_failed = caam_desc_get_len(desc); if (data->era < 8 && small_prime->paddr) { /* * Preload PKHA B2 with small prime predefined * (preload only prime size requested) */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B2, NOACTION, small_prime->length)); caam_desc_add_ptr(desc, small_prime->paddr); } retry_new_number = caam_desc_get_len(desc); /* Decrement the number of try */ caam_desc_add_word(desc, MATH(SUB, VSOL, ONE, VSOL, 4)); /* Exceed retry count - exit with RSA_TRY_FAIL error */ caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, MATH_N, RSA_TRY_FAIL)); retry_too_small = caam_desc_get_len(desc); /* Check internal limit on random value generation */ caam_desc_add_word(desc, MATH(SUB, DPOVRD, ONE, DPOVRD, 4)); caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, MATH_Z, RETRY_TOO_SMALL)); /* * Step 4.2 - Obtain a string p of (nlen/2) bits * Step 4.3 - if (p is not odd) then p = p + 1 */ /* Generate 16 random bytes load into DECO fifo */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4)); caam_desc_add_word(desc, NFIFO_PAD(DECO, NFIFO_LC1, MSG, RND, 16)); /* Get the DECO Input fifo 8 MSB and force on high bit */ caam_desc_add_word(desc, MATH(OR, REG2, IFIFO, REG0, 8)); /* Get the DECO Input fifo 8 LSB and force it be be odd */ caam_desc_add_word(desc, MATH(OR, ONE, IFIFO, REG1, 8)); /* Move the MSB and LSB into IFIFO */ caam_desc_add_word(desc, MOVE(MATH_REG0, IFIFO, 0, 16)); /* Send the 8 MSB into PKHA N */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4)); caam_desc_add_word(desc, NFIFO_NOPAD(C1, 0, IFIFO, PKHA_N, 8)); /* * Generate the "middle" random bytes and start them * on their way into PKHA N */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); caam_desc_add_word(desc, NFIFO_PAD(C1, 0, PKHA_N, RND, 0)); caam_desc_add_word(desc, (data->key_size / 8 / 2) - 16); /* And send the 8 LSB into PKHA N */ caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4)); caam_desc_add_word(desc, NFIFO_NOPAD(C1, NFIFO_FC1, IFIFO, PKHA_N, 8)); /* * Step 4.4 - if ((prime < (sqrt 2)(2^((nlen / 2) - 1)) * ==> retry_too_small */ caam_desc_add_word(desc, PKHA_CPY_SSIZE(A2, B0)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(B0, A0)); caam_desc_add_word(desc, PKHA_OP(MOD_AMODN, A)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(A2, B0)); caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(PKHA_IS_ZERO), retry_too_small - desclen)); /* * Step 4.5 - Compute GCD(prime-1, e) and test if = 1 else try * another candidate */ caam_desc_add_word(desc, PKHA_CPY_SSIZE(N0, A0)); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, 0x01); caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(B0, N0)); caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A, NOACTION, data->e->length)); caam_desc_add_ptr(desc, data->e->paddr); caam_desc_add_word(desc, PKHA_OP(GCD_A_N, B)); desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(PKHA_GCD_1), retry_new_number - desclen)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(N0, A0)); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, 0x01); caam_desc_add_word(desc, PKHA_F2M_OP(MOD_ADD_A_B, B)); caam_desc_add_word(desc, PKHA_CPY_SSIZE(B0, N0)); /* * Step 4.5.1 - test primality */ if (small_prime->paddr) { caam_desc_add_word(desc, PKHA_CPY_SSIZE(B2, A0)); caam_desc_add_word(desc, PKHA_OP(GCD_A_N, B)); desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(PKHA_GCD_1), retry_new_number - desclen)); } /* Generate 8 random bytes 'miller-rabin seed' */ /* Load the number of Miller-Rabin test iteration */ caam_desc_add_word(desc, MATH(ADD, SIL, ZERO, VSIL, 4)); retry_mr_test = caam_desc_get_len(desc); caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8)); caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0)); caam_desc_add_word(desc, (data->key_size / 8 / 2)); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1)); caam_desc_add_word(desc, 0x01); caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B)); desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(PKHA_IS_PRIME), retry_new_mr_failed - desclen)); caam_desc_add_word(desc, MATH(SUB, VSIL, ONE, VSIL, 4)); desclen = caam_desc_get_len(desc); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ALL_COND_FALSE, JMP_COND(MATH_N) | JMP_COND(MATH_Z), retry_mr_test - desclen)); /* Save prime generated */ caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_N, (data->key_size / 8 / 2))); if (do_prime_q) caam_desc_add_ptr(desc, data->q->paddr); else caam_desc_add_ptr(desc, data->p->paddr); if (desc_next) { /* Jump to the next descriptor desc */ caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, JMP_COND(NONE))); caam_desc_add_ptr(desc, desc_next); } RSA_DUMPDESC(desc); } /* * Build the descriptor to check primes p and q not too closed. * Check the upper 100 bits with operation: * |p - q| <= 2^(nlen/2-100) * * @desc [out] Descriptor built * @p Prime P * @max_n Max N built with 0xFFFF... * @desc_new_q Physical address to generate a new Q value */ static void do_checks_primes(uint32_t *desc, const struct caambuf *p, const struct caambuf *max_n, const paddr_t desc_new_q, size_t key_size) { const uint8_t check_len = 16; /* Check 128 bits */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* Load prime p */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B, NOACTION, key_size)); caam_desc_add_ptr(desc, p->paddr); /* Retrieve Q from PKHA N, previously computed */ caam_desc_add_word(desc, PKHA_CPY_SSIZE(N0, A0)); /* Calculate p - q, need a modulus of size prime p filled with 0xFF */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_N, NOACTION, max_n->length)); caam_desc_add_ptr(desc, max_n->paddr); /* PKHA_B = p - q */ caam_desc_add_word(desc, PKHA_OP(MOD_SUB_A_B, B)); /* Unload PKHA register B to output Data FIFO */ caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CHA_CTRL, 4)); caam_desc_add_word(desc, CCTRL_ULOAD_PKHA_B); /* Get the first 128 bits in MATH 0 */ caam_desc_add_word(desc, MOVE_WAIT(OFIFO, MATH_REG0, 0, check_len)); /* * We now need to trash the rest of the result. * We started with 128, 192, or 256 bytes in the OFIFO before we moved * check_len bytes into MATH registers. */ if (key_size > 128 + (size_t)check_len) { caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, check_len)); caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, (key_size - 128 - check_len))); } else if (key_size > check_len) { caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, (key_size - check_len))); } /* * In MATH registers we have the p - q value modulo 0xFFFFF... * Check the upper 100 bits are either zero or one meaning * q is too close to p */ /* Check first 64 bits if not 0's check if 1's */ caam_desc_add_word(desc, MATH(ADD, ZERO, REG0, REG0, 8)); caam_desc_add_word(desc, JUMP_CNO_LOCAL(ANY_COND_FALSE, JMP_COND(MATH_Z), 6)); /* First 64 bits are 0's, check next 36 bits */ caam_desc_add_word(desc, MATH(AND, REG1, IMM_DATA, REG1, 8)); caam_desc_add_word(desc, UINT32_MAX); caam_desc_add_word(desc, 0xF0000000); /* Next 36 bits are 0 */ caam_desc_add_word(desc, JUMP_CNO_LOCAL(ALL_COND_TRUE, JMP_COND(MATH_Z), 10)); /* Exit status GOOD Q */ caam_desc_add_word(desc, HALT_USER(ALL_COND_TRUE, NONE, STATUS_GOOD_Q)); /* Check if 100 bits are 1's */ caam_desc_add_word(desc, MATH(ADD, ONE, REG0, REG0, 8)); /* Not all 1's exit status GOOD Q */ caam_desc_add_word(desc, HALT_USER(ANY_COND_FALSE, MATH_Z, STATUS_GOOD_Q)); /* First 64 bits are 1's, check next 36 bits */ caam_desc_add_word(desc, MATH(AND, REG1, IMM_DATA, REG1, 8)); caam_desc_add_word(desc, UINT32_MAX); caam_desc_add_word(desc, SHIFT_U32(0xF, 28)); /* Use only 4 bytes of immediate data even is operation is 8 bytes */ caam_desc_add_word(desc, MATH(ADD, REG1, IMM_DATA, REG1, 8) | MATH_IFB); caam_desc_add_word(desc, SHIFT_U32(1, 28)); /* Not all 1's exit status GOOD Q */ caam_desc_add_word(desc, HALT_USER(ANY_COND_FALSE, MATH_Z, STATUS_GOOD_Q)); if (desc_new_q) { caam_desc_add_word(desc, JUMP_NOTLOCAL(CLASS_NO, ALL_COND_TRUE, JMP_COND(NONE))); caam_desc_add_ptr(desc, desc_new_q); } RSA_DUMPDESC(desc); } /* * Run the Primes descriptor. * * @desc Descriptor built * @prime Prime generation data */ static enum caam_status run_primes(uint32_t *desc, struct prime_data_rsa *data) { enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; cache_operation(TEE_CACHEFLUSH, data->p->data, data->p->length); if (data->q) cache_operation(TEE_CACHEFLUSH, data->q->data, data->q->length); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (data->q && retstatus == CAAM_JOB_STATUS) { /* * Expect to have a retstatus == CAAM_JOB_STATUS, where * job status == STATUS_GOOD_Q */ RSA_TRACE("Check Prime Q Status 0x%08" PRIx32, jobctx.status); if (JRSTA_GET_HALT_USER(jobctx.status) == STATUS_GOOD_Q) { cache_operation(TEE_CACHEINVALIDATE, data->p->data, data->p->length); cache_operation(TEE_CACHEINVALIDATE, data->q->data, data->q->length); RSA_DUMPBUF("Prime P", data->p->data, data->p->length); RSA_DUMPBUF("Prime Q", data->q->data, data->q->length); retstatus = CAAM_NO_ERROR; } } else if (retstatus == CAAM_NO_ERROR && !data->q) { cache_operation(TEE_CACHEINVALIDATE, data->p->data, data->p->length); RSA_DUMPBUF("Prime", data->p->data, data->p->length); } else if (retstatus != CAAM_NO_ERROR) { RSA_TRACE("Prime Status 0x%08" PRIx32, jobctx.status); } return retstatus; } enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data) { enum caam_status retstatus = CAAM_FAILURE; struct caambuf small_prime = { }; struct caambuf max_n = { }; uint32_t *all_descs = NULL; uint32_t *desc_p = NULL; uint32_t *desc_q = NULL; uint32_t *desc_check_p_q = NULL; paddr_t paddr_desc_p = 0; paddr_t paddr_desc_q = 0; paddr_t paddr_desc_check_p_q = 0; size_t size_all_descs = 0; size_t nb_tries = RSA_MAX_TRIES_PRIMES; size_t key_size = data->key_size / 8 / 2; /* Allocate the job used to prepare the operation */ if (data->q) { size_all_descs = SETUP_RSA_DESC_ENTRIES + GEN_RSA_DESC_ENTRIES * 2 + CHECK_P_Q_DESC_ENTRIES; retstatus = caam_calloc_buf(&max_n, key_size + 1); if (retstatus != CAAM_NO_ERROR) goto end_gen_prime; /* Set the max_n with 0xFFF... to operate the check P and Q */ memset(max_n.data, UINT8_MAX, max_n.length); cache_operation(TEE_CACHECLEAN, max_n.data, max_n.length); } else { size_all_descs = SETUP_RSA_DESC_ENTRIES + GEN_RSA_DESC_ENTRIES; } all_descs = caam_calloc_desc(size_all_descs); if (!all_descs) { retstatus = CAAM_OUT_MEMORY; goto end_gen_prime; } /* Descriptor Prime P */ desc_p = all_descs + SETUP_RSA_DESC_ENTRIES; paddr_desc_p = virt_to_phys(desc_p); if (!paddr_desc_p) { retstatus = CAAM_FAILURE; goto end_gen_prime; } /* * Search predefined prime in the small_prime list, if the * small prime is not found in the list, continue anyway * but prime will be probably not so strong */ search_smallprime(key_size, &small_prime); RSA_TRACE("Do prime of %zu bytes (security len %zu bits) (ERA=%" PRId8 ")", key_size, data->key_size, data->era); do_desc_setup(all_descs, data, &small_prime, paddr_desc_p); if (data->q) { /* Descriptor Prime Q */ desc_q = desc_p + GEN_RSA_DESC_ENTRIES; paddr_desc_q = paddr_desc_p + DESC_SZBYTES(GEN_RSA_DESC_ENTRIES); /* Descriptor Check Primes P & Q */ desc_check_p_q = desc_q + GEN_RSA_DESC_ENTRIES; paddr_desc_check_p_q = paddr_desc_q + DESC_SZBYTES(GEN_RSA_DESC_ENTRIES); /* Generate Prime P and Q then check Q not too close than P */ do_desc_prime(desc_p, data, &small_prime, false, paddr_desc_q); do_desc_prime(desc_q, data, &small_prime, true, paddr_desc_check_p_q); do_checks_primes(desc_check_p_q, data->p, &max_n, paddr_desc_q, key_size); } else { do_desc_prime(desc_p, data, &small_prime, false, 0); } cache_operation(TEE_CACHECLEAN, small_prime.data, data->p->length); cache_operation(TEE_CACHECLEAN, data->e->data, data->e->length); cache_operation(TEE_CACHECLEAN, (void *)all_descs, DESC_SZBYTES(size_all_descs)); do { retstatus = run_primes(all_descs, data); } while (--nb_tries && retstatus != CAAM_NO_ERROR); end_gen_prime: caam_free_desc(&all_descs); caam_free_buf(&max_n); return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/caam_rsa.c000066400000000000000000001304521464416617300235300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021, 2023 NXP * * CAAM RSA manager. * Implementation of RSA functions */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "local.h" /* * Definition of the maximum bits of Exponent e * Refer to sp800-56b */ #define MAX_BITS_EXP_E 256 /* * Define the maximum number of entries in a descriptor * function of the encrypt/decrypt and private key format */ #ifdef CFG_CAAM_64BIT #define MAX_DESC_ENC (8 + 4) #define MAX_DESC_DEC_1 (7 + 2 + 4) #define MAX_DESC_DEC_2 (11 + 2 + 7) #define MAX_DESC_DEC_3 (13 + 2 + 10) /* Define the maximum number of entries in the RSA Finish Key descriptor */ #define MAX_DESC_KEY_FINISH 24 #else #define MAX_DESC_ENC 8 #define MAX_DESC_DEC_1 (7 + 2) #define MAX_DESC_DEC_2 (11 + 2) #define MAX_DESC_DEC_3 (13 + 2) /* Define the maximum number of entries in the RSA Finish Key descriptor */ #define MAX_DESC_KEY_FINISH 15 #endif /* CFG_CAAM_64BIT */ static TEE_Result do_caam_encrypt(struct drvcrypt_rsa_ed *rsa_data, uint32_t operation); static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data, uint32_t operation); /* * Definition of the local RSA keypair * Public Key Format: (n, e) * Private Key Format #1: (n, d) * Private Key Format #2: (p, q, d) * Private Key Format #3: (p, q, dp, dq, qp) */ struct caam_rsa_keypair { uint8_t format; /* Define the Private Key Format (1, 2 or 3) */ struct caambuf n; /* Modulus [n = p * q] */ struct caambuf e; /* Public Exponent 65537 <= e < 2^256 */ struct caamkey d; /* Private Exponent [d = 1/e mod LCM(p-1, q-1)] */ struct caamkey p; /* Private Prime p */ struct caamkey q; /* Private Prime q */ struct caamkey dp; /* Private [dp = d mod (p-1)] */ struct caamkey dq; /* Private [dq = d mod (q-1)] */ struct caamkey qp; /* Private [qp = 1/q mod p] */ }; #define RSA_PRIVATE_KEY_FORMAT_1 1 #define RSA_PRIVATE_KEY_FORMAT_2 2 #define RSA_PRIVATE_KEY_FORMAT_3 3 /* CAAM Era version */ static uint8_t caam_era; /* * Free RSA keypair * * @key RSA keypair */ static void do_free_keypair(struct rsa_keypair *key) { crypto_bignum_free(&key->e); crypto_bignum_free(&key->d); crypto_bignum_free(&key->n); crypto_bignum_free(&key->p); crypto_bignum_free(&key->q); crypto_bignum_free(&key->qp); crypto_bignum_free(&key->dp); crypto_bignum_free(&key->dq); } /* * Free local caam RSA keypair * * @key caam RSA keypair */ static void do_keypair_free(struct caam_rsa_keypair *key) { caam_free_buf(&key->e); caam_free_buf(&key->n); caam_key_free(&key->d); caam_key_free(&key->p); caam_key_free(&key->q); caam_key_free(&key->dp); caam_key_free(&key->dq); caam_key_free(&key->qp); } /* * Convert Crypto RSA Key to local RSA Public Key * Ensure Key is push in physical memory * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format */ static enum caam_status do_keypub_conv(struct caam_rsa_keypair *outkey, const struct rsa_public_key *inkey) { enum caam_status retstatus = CAAM_FAILURE; RSA_TRACE("RSA Convert Public Key size N=%zu", crypto_bignum_num_bytes(inkey->n)); retstatus = caam_calloc_align_buf(&outkey->e, crypto_bignum_num_bytes(inkey->e)); if (retstatus != CAAM_NO_ERROR) goto exit_conv; crypto_bignum_bn2bin(inkey->e, outkey->e.data); cache_operation(TEE_CACHECLEAN, outkey->e.data, outkey->e.length); retstatus = caam_calloc_align_buf(&outkey->n, crypto_bignum_num_bytes(inkey->n)); if (retstatus != CAAM_NO_ERROR) goto exit_conv; crypto_bignum_bn2bin(inkey->n, outkey->n.data); cache_operation(TEE_CACHECLEAN, outkey->n.data, outkey->n.length); return CAAM_NO_ERROR; exit_conv: do_keypair_free(outkey); return CAAM_OUT_MEMORY; } /* * Convert Crypto RSA Key additional fields of the key format #3 * Optional fields (dp, dq, qp) * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format */ static enum caam_status do_keypair_conv_f3(struct caam_rsa_keypair *outkey, const struct rsa_keypair *inkey) { enum caam_status retstatus = CAAM_FAILURE; size_t size_p = 0; size_t size_q = 0; size_t size_dp = 0; size_t size_dq = 0; size_t size_qp = 0; size_p = outkey->p.sec_size; size_q = outkey->q.sec_size; size_dp = crypto_bignum_num_bytes(inkey->dp); size_dq = crypto_bignum_num_bytes(inkey->dq); size_qp = crypto_bignum_num_bytes(inkey->qp); /* * If one of the parameters dp, dq or qp are not filled, * returns immediately. This is not an error. */ if (!size_dp || !size_dq || !size_qp) return CAAM_NO_ERROR; /* * CAAM is assuming that: * - dp and dq are same size as p * - dq same size as q * * Because calculation of dp, dq and qp can be less * than above assumption, force the dp, dq and qp * buffer size. */ retstatus = caam_key_deserialize_from_bn(inkey->dp, &outkey->dp, size_p); if (retstatus) return retstatus; /* Field dq */ retstatus = caam_key_deserialize_from_bn(inkey->dq, &outkey->dq, size_p); if (retstatus) return retstatus; /* Field qp */ retstatus = caam_key_deserialize_from_bn(inkey->qp, &outkey->qp, size_q); if (retstatus) return retstatus; /* Push fields value to the physical memory */ caam_key_cache_op(TEE_CACHECLEAN, &outkey->dp); caam_key_cache_op(TEE_CACHECLEAN, &outkey->qp); caam_key_cache_op(TEE_CACHECLEAN, &outkey->dq); outkey->format = RSA_PRIVATE_KEY_FORMAT_3; return CAAM_NO_ERROR; } /* * Convert Crypto RSA Key additional fields of the key format #2 * Optional fields (p, q) * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format */ static enum caam_status do_keypair_conv_f2(struct caam_rsa_keypair *outkey, const struct rsa_keypair *inkey) { enum caam_status retstatus = CAAM_FAILURE; size_t size_p = 0; size_t size_q = 0; size_p = crypto_bignum_num_bytes(inkey->p); size_q = crypto_bignum_num_bytes(inkey->q); /* * If the Prime P or Prime Q are not filled, returns * immediately. This is not an error. */ if (size_p || !size_q) return CAAM_NO_ERROR; /* Field Prime p */ retstatus = caam_key_deserialize_from_bn(inkey->p, &outkey->p, 0); if (retstatus) return retstatus; /* Field Prime q */ retstatus = caam_key_deserialize_from_bn(inkey->q, &outkey->q, 0); if (retstatus) return retstatus; /* Push fields value to the physical memory */ caam_key_cache_op(TEE_CACHECLEAN, &outkey->p); caam_key_cache_op(TEE_CACHECLEAN, &outkey->q); outkey->format = RSA_PRIVATE_KEY_FORMAT_2; if (CFG_NXP_CAAM_RSA_KEY_FORMAT > RSA_PRIVATE_KEY_FORMAT_2) { retstatus = do_keypair_conv_f3(outkey, inkey); RSA_TRACE("do_keypair_conv_f3 returned 0x%" PRIx32, retstatus); } return retstatus; } /* * Convert Crypto RSA Key to local RSA Keypair Key * Ensure Key is push in physical memory * Don't convert the exponent e not used in decrytion * * @outkey [out] Output keypair in local format * @inkey Input key in TEE Crypto format */ static enum caam_status do_keypair_conv(struct caam_rsa_keypair *outkey, const struct rsa_keypair *inkey) { enum caam_status retstatus = CAAM_FAILURE; RSA_TRACE("RSA Convert Keypair size N=%zu", crypto_bignum_num_bytes(inkey->n)); /* Mandatory fields are n and d => Private Key Format #1 */ retstatus = caam_calloc_align_buf(&outkey->n, crypto_bignum_num_bytes(inkey->n)); if (retstatus != CAAM_NO_ERROR) return retstatus; crypto_bignum_bn2bin(inkey->n, outkey->n.data); cache_operation(TEE_CACHECLEAN, outkey->n.data, outkey->n.length); retstatus = caam_key_deserialize_from_bn(inkey->d, &outkey->d, 0); if (retstatus) return retstatus; caam_key_cache_op(TEE_CACHECLEAN, &outkey->d); outkey->format = RSA_PRIVATE_KEY_FORMAT_1; if (CFG_NXP_CAAM_RSA_KEY_FORMAT > RSA_PRIVATE_KEY_FORMAT_1) { retstatus = do_keypair_conv_f2(outkey, inkey); RSA_TRACE("do_keypair_conv_f2 returned 0x%" PRIx32, retstatus); } return retstatus; } /* * Allocate a RSA keypair * * @key Keypair * @size_bits Key size in bits */ static TEE_Result do_allocate_keypair(struct rsa_keypair *key, size_t size_bits) { RSA_TRACE("Allocate Keypair of %zu bits", size_bits); /* Initialize all input key fields to 0 */ memset(key, 0, sizeof(*key)); /* Allocate the Public Exponent to maximum size */ key->e = crypto_bignum_allocate(MAX_BITS_EXP_E); if (!key->e) goto err_alloc_keypair; /* Allocate the Private Exponent [d = 1/e mod LCM(p-1, q-1)] */ key->d = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->d) goto err_alloc_keypair; /* Allocate the Modulus (size_bits) [n = p * q] */ key->n = crypto_bignum_allocate(size_bits); if (!key->n) goto err_alloc_keypair; /* Allocate the prime number p of size (size_bits / 2) */ key->p = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->p) goto err_alloc_keypair; /* Allocate the prime number q of size (size_bits / 2) */ key->q = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->q) goto err_alloc_keypair; /* Allocate dp (size_bits / 2) [d mod (p-1)] */ key->dp = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->dp) goto err_alloc_keypair; /* Allocate dq (size_bits / 2) [d mod (q-1)] */ key->dq = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->dq) goto err_alloc_keypair; /* Allocate qp (size_bits / 2) [1/q mod p] */ key->qp = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS); if (!key->qp) goto err_alloc_keypair; return TEE_SUCCESS; err_alloc_keypair: RSA_TRACE("Allocation error"); do_free_keypair(key); return TEE_ERROR_OUT_OF_MEMORY; } /* * Allocate a RSA public key * * @key Public Key * @size_bits Key size in bits */ static TEE_Result do_allocate_publickey(struct rsa_public_key *key, size_t size_bits) { RSA_TRACE("Allocate Public Key of %zu bits", size_bits); /* Initialize all input key fields to 0 */ memset(key, 0, sizeof(*key)); /* Allocate the Public Exponent to maximum size */ key->e = crypto_bignum_allocate(MAX_BITS_EXP_E); if (!key->e) goto err_alloc_publickey; /* Allocate the Modulus (size_bits) [n = p * q] */ key->n = crypto_bignum_allocate(size_bits); if (!key->n) goto err_alloc_publickey; return TEE_SUCCESS; err_alloc_publickey: RSA_TRACE("Allocation error"); crypto_bignum_free(&key->e); crypto_bignum_free(&key->n); return TEE_ERROR_OUT_OF_MEMORY; } /* * Free a RSA public key * * @key Public Key */ static void do_free_publickey(struct rsa_public_key *key) { crypto_bignum_free(&key->e); crypto_bignum_free(&key->n); } /* * Output the RSA keypair format 3 additional fields in bignumber object * * @key [out] Keypair * @key_size Key size in bits */ static TEE_Result gen_keypair_get_f3(struct rsa_keypair *key, struct caam_rsa_keypair *genkey) { enum caam_status status = CAAM_FAILURE; caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->dp); caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->dq); caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->qp); RSA_DUMPBUF("dp", genkey->dp.buf.data, genkey->dp.buf.length); RSA_DUMPBUF("dq", genkey->dq.buf.data, genkey->dq.buf.length); RSA_DUMPBUF("qp", genkey->qp.buf.data, genkey->qp.buf.length); status = caam_key_serialize_to_bn(key->dp, &genkey->dp); if (status) return caam_status_to_tee_result(status); status = caam_key_serialize_to_bn(key->dq, &genkey->dq); if (status) return caam_status_to_tee_result(status); status = caam_key_serialize_to_bn(key->qp, &genkey->qp); if (status) return caam_status_to_tee_result(status); return TEE_SUCCESS; } /* * Output the RSA keypair format 2 additional fields in big number object * * @key [out] Keypair * @key_size Key size in bits */ static TEE_Result gen_keypair_get_f2(struct rsa_keypair *key, struct caam_rsa_keypair *genkey) { enum caam_status status = CAAM_FAILURE; caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->q); caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->p); RSA_DUMPBUF("p", genkey->p.buf.data, genkey->p.buf.length); RSA_DUMPBUF("q", genkey->q.buf.data, genkey->q.buf.length); status = caam_key_serialize_to_bn(key->p, &genkey->p); if (status) return caam_status_to_tee_result(status); status = caam_key_serialize_to_bn(key->q, &genkey->q); if (status) return caam_status_to_tee_result(status); if (genkey->format > RSA_PRIVATE_KEY_FORMAT_2) return gen_keypair_get_f3(key, genkey); return TEE_SUCCESS; } static TEE_Result do_black_key_encapsulation(struct caam_rsa_keypair *rsa_keypair) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_key_type key_type = caam_key_default_key_gen_type(); ret = caam_key_black_encapsulation(&rsa_keypair->p, key_type); if (ret) { RSA_TRACE("RSA Key p component encapsulation failed"); return ret; } ret = caam_key_black_encapsulation(&rsa_keypair->q, key_type); if (ret) { RSA_TRACE("RSA Key q component encapsulation failed"); return ret; } RSA_TRACE("Black key encapsulation done"); return TEE_SUCCESS; } /* * Generates a RSA keypair * * @key [out] Keypair * @key_size Key size in bits */ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_rsa_keypair genkey = { }; size_t size_d_gen __maybe_unused = 0; uint32_t *size_d_gen_val_ptr = NULL; struct caam_jobctx jobctx = { }; uint32_t *desc = 0; uint32_t desclen = 0; struct prime_data_rsa prime = { }; enum caam_key_type key_type = caam_key_default_key_gen_type(); size_t key_size_bytes = key_size / 8; RSA_TRACE("Generate Keypair of %zu bits", key_size); genkey.format = CFG_NXP_CAAM_RSA_KEY_FORMAT; /* Allocate the job used to prepare the operation */ desc = caam_calloc_desc(MAX_DESC_KEY_FINISH); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_gen_keypair; } size_d_gen_val_ptr = caam_calloc_align(sizeof(uint32_t)); if (!size_d_gen_val_ptr) { ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_gen_keypair; } /* First allocate primes p and q */ genkey.p.key_type = CAAM_KEY_PLAIN_TEXT; genkey.p.sec_size = key_size_bytes / 2; genkey.p.is_blob = false; retstatus = caam_key_alloc(&genkey.p); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } genkey.q.key_type = CAAM_KEY_PLAIN_TEXT; genkey.q.sec_size = key_size_bytes / 2; genkey.q.is_blob = false; retstatus = caam_key_alloc(&genkey.q); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } /* Allocate Public exponent to a caam buffer */ retstatus = caam_calloc_buf(&genkey.e, crypto_bignum_num_bytes(key->e)); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } genkey.d.key_type = key_type; genkey.d.sec_size = key_size_bytes; genkey.d.is_blob = false; retstatus = caam_key_alloc(&genkey.d); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } retstatus = caam_calloc_align_buf(&genkey.n, key_size_bytes); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) { genkey.dp.key_type = key_type; genkey.dp.sec_size = key_size_bytes / 2; genkey.dp.is_blob = false; retstatus = caam_key_alloc(&genkey.dp); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } genkey.dq.key_type = key_type; genkey.dq.sec_size = key_size_bytes / 2; genkey.dq.is_blob = false; retstatus = caam_key_alloc(&genkey.dq); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } genkey.qp.key_type = key_type; genkey.qp.sec_size = key_size_bytes / 2; genkey.qp.is_blob = false; retstatus = caam_key_alloc(&genkey.qp); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } } crypto_bignum_bn2bin(key->e, genkey.e.data); prime.era = caam_era; prime.key_size = key_size; prime.e = &genkey.e; prime.p = &genkey.p.buf; prime.q = &genkey.q.buf; /* Generate prime p and q */ retstatus = caam_prime_rsa_gen(&prime); RSA_TRACE("Generate Prime P and Q returned 0x%" PRIx32, retstatus); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, 0); caam_desc_add_word(desc, PDB_RSA_KEY_P_SIZE(genkey.p.sec_size)); caam_desc_add_word(desc, PDB_RSA_KEY_N_SIZE(genkey.n.length) | PDB_RSA_KEY_E_SIZE(genkey.e.length)); caam_desc_add_ptr(desc, genkey.p.buf.paddr); caam_desc_add_ptr(desc, genkey.q.buf.paddr); caam_desc_add_ptr(desc, genkey.e.paddr); caam_desc_add_ptr(desc, genkey.n.paddr); caam_desc_add_ptr(desc, genkey.d.buf.paddr); caam_desc_add_ptr(desc, virt_to_phys(size_d_gen_val_ptr)); if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) { caam_desc_add_ptr(desc, genkey.dp.buf.paddr); caam_desc_add_ptr(desc, genkey.dq.buf.paddr); caam_desc_add_ptr(desc, genkey.qp.buf.paddr); switch (key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto exit_gen_keypair; } caam_key_cache_op(TEE_CACHEFLUSH, &genkey.dp); caam_key_cache_op(TEE_CACHEFLUSH, &genkey.dq); caam_key_cache_op(TEE_CACHEFLUSH, &genkey.qp); } else { switch (key_type) { case CAAM_KEY_PLAIN_TEXT: caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, NONE)); break; case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, ECB)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, CCM)); break; default: ret = TEE_ERROR_GENERIC; goto exit_gen_keypair; } } desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); jobctx.desc = desc; RSA_DUMPDESC(desc); cache_operation(TEE_CACHECLEAN, genkey.e.data, genkey.e.length); caam_key_cache_op(TEE_CACHEFLUSH, &genkey.p); caam_key_cache_op(TEE_CACHEFLUSH, &genkey.q); caam_key_cache_op(TEE_CACHEFLUSH, &genkey.d); cache_operation(TEE_CACHEFLUSH, genkey.n.data, genkey.n.length); cache_operation(TEE_CACHEFLUSH, size_d_gen_val_ptr, sizeof(uint32_t)); retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey.d); cache_operation(TEE_CACHEINVALIDATE, &genkey.n, genkey.n.length); cache_operation(TEE_CACHEINVALIDATE, size_d_gen_val_ptr, sizeof(uint32_t)); size_d_gen = caam_read_val32(size_d_gen_val_ptr); RSA_TRACE("D size %zu", size_d_gen); RSA_DUMPBUF("D", genkey.d.buf.data, genkey.d.buf.length); RSA_DUMPBUF("N", genkey.n.data, genkey.n.length); genkey.d.sec_size = size_d_gen; if (key_type != CAAM_KEY_PLAIN_TEXT) { ret = do_black_key_encapsulation(&genkey); if (ret != TEE_SUCCESS) goto exit_gen_keypair; } ret = crypto_bignum_bin2bn(genkey.n.data, genkey.n.length, key->n); if (ret != TEE_SUCCESS) goto exit_gen_keypair; retstatus = caam_key_serialize_to_bn(key->d, &genkey.d); if (retstatus) { ret = caam_status_to_tee_result(retstatus); goto exit_gen_keypair; } if (genkey.format > RSA_PRIVATE_KEY_FORMAT_1) ret = gen_keypair_get_f2(key, &genkey); } else { RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } exit_gen_keypair: do_keypair_free(&genkey); caam_free(size_d_gen_val_ptr); caam_free_desc(&desc); return ret; } /* * RSA EME-OAEP Decoding operation * Refer the chapter 7.1.2 Decryption operation of pkcs-1v2-1 specification * * @rsa_data [in/out] RSA Data to encode */ static TEE_Result do_oaep_decoding(struct drvcrypt_rsa_ed *rsa_data) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caambuf DB = { }; struct caambuf lHash = { }; struct caambuf seed = { }; struct caambuf dbMask = { }; struct caambuf maskedDB = { }; struct caambuf maskedSeed = { }; struct caambuf EM = { }; size_t db_size = 0; size_t b01_idx = 0; size_t db_len = 0; struct drvcrypt_rsa_mgf mgf_data = { }; struct drvcrypt_rsa_ed dec_data = { }; struct drvcrypt_mod_op mod_op = { }; RSA_TRACE("RSA OAEP Decoding"); /* * First Decryption of the Cipher to a EM of modulus size */ retstatus = caam_calloc_align_buf(&EM, rsa_data->key.n_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } memcpy(&dec_data, rsa_data, sizeof(dec_data)); dec_data.message.data = EM.data; dec_data.message.length = EM.length; ret = do_caam_decrypt(&dec_data, RSA_DECRYPT(NO)); RSA_DUMPBUF("EM", EM.data, EM.length); /* * DB = lHash' || PS || 0x01 || M * DB length = k - hLen - 1 * * PS is a 0's buffer of length h - mLen - 2hLen - 2 * * k is the key modulus length * hLen is the Hash digest length * mLen is the input RSA message length */ /* Calculate the DB size */ db_size = rsa_data->key.n_size - rsa_data->digest_size - 1; RSA_TRACE("DB is %zu bytes", db_size); /* Allocate the DB buffer */ retstatus = caam_calloc_align_buf(&DB, db_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } /* * Step a * Generate the lHash */ /* Allocate the lHash buffer */ retstatus = caam_calloc_align_buf(&lHash, rsa_data->digest_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } RSA_TRACE("Hash the RSA Label of %zu bytes", rsa_data->label.length); ret = tee_hash_createdigest(rsa_data->hash_algo, rsa_data->label.data, rsa_data->label.length, lHash.data, lHash.length); RSA_TRACE("Hash the RSA Label returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto exit_oaep_decrypt; RSA_DUMPBUF("lHash", lHash.data, lHash.length); /* Allocate the seed buffer */ retstatus = caam_calloc_align_buf(&seed, rsa_data->digest_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } /* Allocate the dbMask buffer */ retstatus = caam_calloc_align_buf(&dbMask, db_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } /* * Step b * Split the EM string * EM = Y || maskedSeed || maskedDB * * Where: * Y size = 1 byte * maskedSeed size = hLen * maskedDB size = k - hLen - 1 bytes * * k is the key modulus length * hLen is the Hash digest length * mLen is the input RSA message length * * Note Y should have been remove during the */ maskedSeed.data = &EM.data[1]; maskedSeed.length = rsa_data->digest_size; maskedSeed.paddr = EM.paddr + sizeof(uint8_t); maskedDB.data = &EM.data[1 + rsa_data->digest_size]; maskedDB.length = dbMask.length; maskedDB.paddr = EM.paddr + sizeof(uint8_t) + rsa_data->digest_size; /* * Step c * Generate a Mask of the maskedDB * seedMask = MGF(maskedDB, k - hLen - 1) * * Note: Use same buffer for seed and seedMask */ mgf_data.hash_algo = rsa_data->mgf_algo; mgf_data.digest_size = rsa_data->mgf_size; mgf_data.seed.data = maskedDB.data; mgf_data.seed.length = maskedDB.length; mgf_data.mask.data = seed.data; mgf_data.mask.length = seed.length; ret = rsa_data->mgf(&mgf_data); if (ret != TEE_SUCCESS) goto exit_oaep_decrypt; /* * Step d * seed = maskedSeed xor seedMask * * Note: Use same buffer for seed and seedMask */ mod_op.n.length = seed.length; mod_op.a.data = maskedSeed.data; mod_op.a.length = maskedSeed.length; mod_op.b.data = seed.data; mod_op.b.length = seed.length; mod_op.result.data = seed.data; mod_op.result.length = seed.length; retstatus = drvcrypt_xor_mod_n(&mod_op); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } RSA_DUMPBUF("Seed", seed.data, seed.length); /* * Step e * Generate a Mask of the seed value * dbMask = MGF(seed, k - hLen - 1) */ mgf_data.seed.data = seed.data; mgf_data.seed.length = seed.length; mgf_data.mask.data = dbMask.data; mgf_data.mask.length = dbMask.length; ret = rsa_data->mgf(&mgf_data); if (ret != TEE_SUCCESS) goto exit_oaep_decrypt; /* * Step f * DB = maskedDB xor dbMask */ mod_op.n.length = DB.length; mod_op.a.data = maskedDB.data; mod_op.a.length = maskedDB.length; mod_op.b.data = dbMask.data; mod_op.b.length = dbMask.length; mod_op.result.data = DB.data; mod_op.result.length = DB.length; retstatus = drvcrypt_xor_mod_n(&mod_op); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_decrypt; } RSA_DUMPBUF("DB", DB.data, DB.length); /* * Step g * Check the DB generated * DB = lHash' || PS || 0x01 || M * * Error if: * - lHash' != lHash (First step - Hash the Label) * - byte 0x01 between PS and M is not present */ /* Check Hash values */ if (memcmp(DB.data, lHash.data, lHash.length)) { RSA_TRACE("Hash error"); ret = TEE_ERROR_BAD_PARAMETERS; goto exit_oaep_decrypt; } /* Find the byte 0x01 separating PS and M */ for (b01_idx = rsa_data->digest_size; b01_idx < db_size && !DB.data[b01_idx]; b01_idx++) ; if (b01_idx == db_size) { RSA_TRACE("byte 0x01 not present"); ret = TEE_ERROR_BAD_PARAMETERS; goto exit_oaep_decrypt; } db_len = DB.length - b01_idx - 1; if (rsa_data->message.length < db_len) { rsa_data->message.length = db_len; ret = TEE_ERROR_SHORT_BUFFER; goto exit_oaep_decrypt; } rsa_data->message.length = db_len; memcpy(rsa_data->message.data, &DB.data[b01_idx + 1], rsa_data->message.length); RSA_DUMPBUF("Message decrypted", rsa_data->message.data, rsa_data->message.length); ret = TEE_SUCCESS; exit_oaep_decrypt: caam_free_buf(&EM); caam_free_buf(&DB); caam_free_buf(&seed); caam_free_buf(&dbMask); caam_free_buf(&lHash); return ret; } /* * RSA EME-OAEP Encoding operation * Refer the chapter 7.1.1 Encryption operation of pkcs-1v2-1 specification * * @rsa_data [int/out] RSA Data to encode */ static TEE_Result do_oaep_encoding(struct drvcrypt_rsa_ed *rsa_data) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus; struct caambuf DB = { }; struct caambuf lHash = { }; struct caambuf seed = { }; struct caambuf dbMask = { }; struct caambuf maskedDB = { }; struct caambuf maskedSeed = { }; struct caambuf EM = { }; size_t db_size = 0; size_t ps_size = 0; struct drvcrypt_rsa_mgf mgf_data = { }; struct drvcrypt_rsa_ed enc_data = { }; struct drvcrypt_mod_op mod_op = { }; RSA_TRACE("RSA OAEP Encoding"); /* * DB = lHash || PS || 0x01 || M * DB length = k - hLen - 1 * * PS is a 0's buffer of length h - mLen - 2hLen - 2 * * k is the key modulus length * hLen is the Hash digest length * mLen is the input RSA message length */ /* Calculate the DB size */ db_size = rsa_data->key.n_size - rsa_data->digest_size - 1; RSA_TRACE("DB is %zu bytes", db_size); /* Allocate the DB buffer */ retstatus = caam_calloc_align_buf(&DB, db_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_encrypt; } /* * Step a * Generate the lHash */ lHash.length = rsa_data->digest_size; lHash.data = DB.data; RSA_TRACE("Hash the RSA Label of %zu bytes", rsa_data->label.length); ret = tee_hash_createdigest(rsa_data->hash_algo, rsa_data->label.data, rsa_data->label.length, lHash.data, lHash.length); RSA_TRACE("Hash the RSA Label returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto exit_oaep_encrypt; RSA_DUMPBUF("lHash", lHash.data, lHash.length); /* * Step b * Add PS 0's * Note: DB is already filled with 0's at the allocation */ ps_size = rsa_data->key.n_size - rsa_data->message.length - 2 * rsa_data->digest_size - 2; RSA_TRACE("PS is %zu bytes", ps_size); /* * Step c * Set the value 0x01 after the lHash and the PS * Concatenate result with input message */ DB.data[lHash.length + ps_size] = 0x01; memcpy(&DB.data[lHash.length + ps_size + 1], rsa_data->message.data, rsa_data->message.length); RSA_DUMPBUF("DB", DB.data, DB.length); /* * Step d * Generate a random seed of hLen */ /* Allocate the seed buffer */ retstatus = caam_calloc_align_buf(&seed, rsa_data->digest_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_encrypt; } /* Allocate the dbMask buffer */ retstatus = caam_calloc_align_buf(&dbMask, db_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_encrypt; } ret = crypto_rng_read(seed.data, seed.length); RSA_TRACE("Get seed of %zu bytes (ret = 0x%08" PRIx32 ")", seed.length, ret); if (ret != TEE_SUCCESS) goto exit_oaep_encrypt; RSA_DUMPBUF("Seed", seed.data, seed.length); /* * Step e * Generate a Mask of the seed value * dbMask = MGF(seed, k - hLen - 1) */ mgf_data.hash_algo = rsa_data->mgf_algo; mgf_data.digest_size = rsa_data->mgf_size; mgf_data.seed.data = seed.data; mgf_data.seed.length = seed.length; mgf_data.mask.data = dbMask.data; mgf_data.mask.length = dbMask.length; ret = rsa_data->mgf(&mgf_data); if (ret != TEE_SUCCESS) goto exit_oaep_encrypt; /* * Step f * maskedDB = DB xor dbMask */ retstatus = caam_calloc_align_buf(&EM, rsa_data->key.n_size); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_oaep_encrypt; } maskedDB.data = &EM.data[1 + rsa_data->digest_size]; maskedDB.length = dbMask.length; maskedDB.paddr = EM.paddr + sizeof(uint8_t) + rsa_data->digest_size; mod_op.n.length = maskedDB.length; mod_op.a.data = DB.data; mod_op.a.length = DB.length; mod_op.b.data = dbMask.data; mod_op.b.length = dbMask.length; mod_op.result.data = maskedDB.data; mod_op.result.length = maskedDB.length; ret = drvcrypt_xor_mod_n(&mod_op); if (ret != TEE_SUCCESS) goto exit_oaep_encrypt; /* * Step g * Generate a Mask of the maskedDB * seedMask = MGF(maskedDB, hLen) * * Note: Use same buffer for seedMask and maskedSeed */ maskedSeed.data = &EM.data[1]; maskedSeed.length = rsa_data->digest_size; maskedSeed.paddr = EM.paddr + sizeof(uint8_t); mgf_data.seed.data = maskedDB.data; mgf_data.seed.length = maskedDB.length; mgf_data.mask.data = maskedSeed.data; mgf_data.mask.length = maskedSeed.length; ret = rsa_data->mgf(&mgf_data); if (ret != TEE_SUCCESS) goto exit_oaep_encrypt; /* * Step h * maskedSeed = seed xor seedMask */ mod_op.n.length = maskedSeed.length; mod_op.a.data = seed.data; mod_op.a.length = seed.length; mod_op.b.data = maskedSeed.data; mod_op.b.length = maskedSeed.length; mod_op.result.data = maskedSeed.data; mod_op.result.length = maskedSeed.length; ret = drvcrypt_xor_mod_n(&mod_op); if (ret != TEE_SUCCESS) goto exit_oaep_encrypt; RSA_DUMPBUF("EM", EM.data, EM.length); /* * Last Encryption of the EM of modulus size to Cipher */ memcpy(&enc_data, rsa_data, sizeof(enc_data)); enc_data.message.data = EM.data; enc_data.message.length = EM.length; ret = do_caam_encrypt(&enc_data, RSA_ENCRYPT(NO)); exit_oaep_encrypt: caam_free_buf(&DB); caam_free_buf(&seed); caam_free_buf(&dbMask); caam_free_buf(&EM); return ret; } /* * CAAM RSA Encryption of the input message to a cipher * * @rsa_data [in/out] RSA Data to encrypt * @operation CAAM RSA Encryption operation */ static TEE_Result do_caam_encrypt(struct drvcrypt_rsa_ed *rsa_data, uint32_t operation) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_rsa_keypair key = { }; struct caamdmaobj msg = { }; struct caamdmaobj cipher = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; uint32_t pdb_sgt_flags = 0; RSA_TRACE("RSA Encrypt mode %d", rsa_data->rsa_id); /* Allocate the job descriptor */ desc = caam_calloc_desc(MAX_DESC_ENC); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_encrypt; } /* * Convert TEE rsa key type to CAAM rsa key type * Push key value to memory */ retstatus = do_keypub_conv(&key, rsa_data->key.key); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_encrypt; } /* * ReAllocate the cipher result buffer with a maximum size * of the Key Modulus's size (N) if not cache aligned */ ret = caam_dmaobj_output_sgtbuf(&cipher, rsa_data->cipher.data, rsa_data->cipher.length, key.n.length); if (ret) goto exit_encrypt; if (cipher.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_RSA_ENC_SGT_G; caam_dmaobj_cache_push(&cipher); /* Prepare the input message CAAM descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&msg, rsa_data->message.data, rsa_data->message.length); if (ret) goto exit_encrypt; if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_RSA_ENC_SGT_F; caam_dmaobj_cache_push(&msg); caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PDB_RSA_ENC_E_SIZE(key.e.length) | PDB_RSA_ENC_N_SIZE(key.n.length) | pdb_sgt_flags); caam_desc_add_ptr(desc, msg.sgtbuf.paddr); caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); caam_desc_add_ptr(desc, key.n.paddr); caam_desc_add_ptr(desc, key.e.paddr); caam_desc_add_word(desc, PDB_RSA_ENC_F_SIZE(rsa_data->message.length)); caam_desc_add_word(desc, operation); /* Set the descriptor Header with length */ desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); RSA_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { rsa_data->cipher.length = caam_dmaobj_copy_to_orig(&cipher); RSA_DUMPBUF("Output", rsa_data->cipher.data, rsa_data->cipher.length); ret = caam_status_to_tee_result(retstatus); } else { RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } exit_encrypt: caam_free_desc(&desc); do_keypair_free(&key); caam_dmaobj_free(&msg); caam_dmaobj_free(&cipher); return ret; } /* * Get RSA key pair key type * * @kp RSA key pair */ static enum caam_key_type get_caam_key_type(const struct caam_rsa_keypair kp) { switch (kp.format) { case RSA_PRIVATE_KEY_FORMAT_1: return kp.d.key_type; case RSA_PRIVATE_KEY_FORMAT_2: if (kp.p.key_type == kp.q.key_type && kp.q.key_type == kp.d.key_type) return kp.p.key_type; else return CAAM_KEY_MAX_VALUE; case RSA_PRIVATE_KEY_FORMAT_3: if (kp.p.key_type == kp.q.key_type && kp.q.key_type == kp.dp.key_type && kp.dp.key_type == kp.dq.key_type && kp.dq.key_type == kp.qp.key_type) return kp.p.key_type; else return CAAM_KEY_MAX_VALUE; default: return CAAM_KEY_MAX_VALUE; } } /* * CAAM RSA Decryption of the input cipher to a message * * @rsa_data [in/out] RSA Data to decrypt * @operation CAAM RSA Decryption operation */ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data, uint32_t operation) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_rsa_keypair key = { }; struct caamdmaobj cipher = { }; struct caamdmaobj msg = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; uint32_t pdb_sgt_flags = 0; struct caambuf size_msg = { }; struct caamkey tmp_1 = { }; struct caamkey tmp_2 = { }; enum caam_key_type g_key_type = CAAM_KEY_MAX_VALUE; RSA_TRACE("RSA Decrypt mode %d", rsa_data->rsa_id); /* * Convert TEE rsa key type to CAAM rsa key type * Push key value to memory */ retstatus = do_keypair_conv(&key, rsa_data->key.key); if (retstatus != CAAM_NO_ERROR) { RSA_TRACE("do_keypair_conv returned 0x%" PRIx32, retstatus); ret = caam_status_to_tee_result(retstatus); goto exit_decrypt; } /* * Allocate the temporary result buffer with a maximum size * of the Key Modulus's size (N) */ ret = caam_dmaobj_output_sgtbuf(&msg, rsa_data->message.data, rsa_data->message.length, key.n.length); if (ret) goto exit_decrypt; if (msg.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_RSA_DEC_SGT_F; caam_dmaobj_cache_push(&msg); /* Allocate the returned computed size when PKCS V1.5 */ if (operation == RSA_DECRYPT(PKCS_V1_5)) { retstatus = caam_alloc_align_buf(&size_msg, 4); if (retstatus != CAAM_NO_ERROR) goto exit_decrypt; cache_operation(TEE_CACHEFLUSH, size_msg.data, size_msg.length); } /* Prepare the input cipher CAAM descriptor entry */ ret = caam_dmaobj_input_sgtbuf(&cipher, rsa_data->cipher.data, rsa_data->cipher.length); if (cipher.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_RSA_DEC_SGT_G; caam_dmaobj_cache_push(&cipher); /* Allocate the job descriptor function of the Private key format */ switch (key.format) { case RSA_PRIVATE_KEY_FORMAT_1: desc = caam_calloc_desc(MAX_DESC_DEC_1); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_decrypt; } break; case RSA_PRIVATE_KEY_FORMAT_2: case RSA_PRIVATE_KEY_FORMAT_3: if (key.format == RSA_PRIVATE_KEY_FORMAT_2) desc = caam_calloc_desc(MAX_DESC_DEC_2); else desc = caam_calloc_desc(MAX_DESC_DEC_3); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_decrypt; } /* Allocate two temporary buffers used by the CAAM */ tmp_1.key_type = CAAM_KEY_PLAIN_TEXT; tmp_1.sec_size = key.p.sec_size; tmp_1.is_blob = false; retstatus = caam_key_alloc(&tmp_1); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_decrypt; } tmp_2.key_type = CAAM_KEY_PLAIN_TEXT; tmp_2.sec_size = key.q.sec_size; tmp_2.is_blob = false; retstatus = caam_key_alloc(&tmp_2); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto exit_decrypt; } caam_key_cache_op(TEE_CACHEFLUSH, &tmp_1); caam_key_cache_op(TEE_CACHEFLUSH, &tmp_2); break; default: ret = TEE_ERROR_GENERIC; goto exit_decrypt; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* Build the descriptor function of the Private Key format */ switch (key.format) { case RSA_PRIVATE_KEY_FORMAT_1: caam_desc_add_word(desc, PDB_RSA_DEC_D_SIZE(key.d.sec_size) | PDB_RSA_DEC_N_SIZE(key.n.length) | pdb_sgt_flags); caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); caam_desc_add_ptr(desc, msg.sgtbuf.paddr); caam_desc_add_ptr(desc, key.n.paddr); caam_desc_add_ptr(desc, key.d.buf.paddr); break; case RSA_PRIVATE_KEY_FORMAT_2: caam_desc_add_word(desc, PDB_RSA_DEC_D_SIZE(key.d.sec_size) | PDB_RSA_DEC_N_SIZE(key.n.length) | pdb_sgt_flags); caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); caam_desc_add_ptr(desc, msg.sgtbuf.paddr); caam_desc_add_ptr(desc, key.d.buf.paddr); caam_desc_add_ptr(desc, key.p.buf.paddr); caam_desc_add_ptr(desc, key.q.buf.paddr); caam_desc_add_ptr(desc, tmp_1.buf.paddr); caam_desc_add_ptr(desc, tmp_2.buf.paddr); caam_desc_add_word(desc, PDB_RSA_DEC_Q_SIZE(key.q.sec_size) | PDB_RSA_DEC_P_SIZE(key.p.sec_size)); break; case RSA_PRIVATE_KEY_FORMAT_3: caam_desc_add_word(desc, PDB_RSA_DEC_N_SIZE(key.n.length) | pdb_sgt_flags); caam_desc_add_ptr(desc, cipher.sgtbuf.paddr); caam_desc_add_ptr(desc, msg.sgtbuf.paddr); caam_desc_add_ptr(desc, key.qp.buf.paddr); caam_desc_add_ptr(desc, key.p.buf.paddr); caam_desc_add_ptr(desc, key.q.buf.paddr); caam_desc_add_ptr(desc, key.dp.buf.paddr); caam_desc_add_ptr(desc, key.dq.buf.paddr); caam_desc_add_ptr(desc, tmp_1.buf.paddr); caam_desc_add_ptr(desc, tmp_2.buf.paddr); caam_desc_add_word(desc, PDB_RSA_DEC_Q_SIZE(key.q.sec_size) | PDB_RSA_DEC_P_SIZE(key.p.sec_size)); break; default: ret = TEE_ERROR_GENERIC; goto exit_decrypt; } /* Set the Decryption operation type */ operation |= PROT_RSA_DEC_KEYFORM(key.format); /* Get key type */ g_key_type = get_caam_key_type(key); switch (g_key_type) { case CAAM_KEY_PLAIN_TEXT: operation |= PROT_RSA_KEY_ENC(NONE); break; case CAAM_KEY_BLACK_ECB: operation |= PROT_RSA_KEY_ENC(ECB); break; case CAAM_KEY_BLACK_CCM: operation |= PROT_RSA_KEY_ENC(CCM); break; default: ret = TEE_ERROR_GENERIC; goto exit_decrypt; } caam_desc_add_word(desc, operation); if (operation == RSA_DECRYPT(PKCS_V1_5)) { /* Get the PPKCS1 v1.5 Message length generated */ caam_desc_add_word(desc, ST_NOIMM_OFF(CLASS_DECO, REG_MATH0, 4, 4)); caam_desc_add_ptr(desc, size_msg.paddr); /* Set the descriptor Header with length */ desclen = caam_desc_get_len(desc); #ifdef CFG_CAAM_64BIT caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1 - 3)); #else caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1 - 2)); #endif /* CFG_CAAM_64BIT */ } else { desclen = caam_desc_get_len(desc); /* Set the descriptor Header with length */ caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); } RSA_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus != CAAM_NO_ERROR) { RSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); goto exit_decrypt; } if (operation == RSA_DECRYPT(NO) && rsa_data->rsa_id == DRVCRYPT_RSA_NOPAD) { rsa_data->message.length = caam_dmaobj_copy_ltrim_to_orig(&msg); } else { if (operation == RSA_DECRYPT(PKCS_V1_5)) { /* PKCS 1 v1.5 */ cache_operation(TEE_CACHEINVALIDATE, size_msg.data, size_msg.length); /* Check if the original buffer size is large enough */ if (msg.orig.length < caam_read_val32(size_msg.data)) { rsa_data->message.length = caam_read_val32(size_msg.data); ret = TEE_ERROR_SHORT_BUFFER; goto exit_decrypt; } msg.orig.length = caam_read_val32(size_msg.data); RSA_TRACE("New length %zu", msg.orig.length); } rsa_data->message.length = caam_dmaobj_copy_to_orig(&msg); } RSA_DUMPBUF("Output", rsa_data->message.data, rsa_data->message.length); ret = TEE_SUCCESS; exit_decrypt: caam_free_desc(&desc); do_keypair_free(&key); caam_free_buf(&size_msg); caam_dmaobj_free(&msg); caam_dmaobj_free(&cipher); caam_key_free(&tmp_1); caam_key_free(&tmp_2); return ret; } /* * RSA Encryption * * @rsa_data [in/out] RSA Data to encrypt / Cipher resulting */ static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; switch (rsa_data->rsa_id) { case DRVCRYPT_RSA_NOPAD: case DRVCRYPT_RSASSA_PKCS_V1_5: case DRVCRYPT_RSASSA_PSS: ret = do_caam_encrypt(rsa_data, RSA_ENCRYPT(NO)); break; case DRVCRYPT_RSA_PKCS_V1_5: ret = do_caam_encrypt(rsa_data, RSA_ENCRYPT(PKCS_V1_5)); break; case DRVCRYPT_RSA_OAEP: ret = do_oaep_encoding(rsa_data); break; default: break; } return ret; } /* * RSA Decryption * * @rsa_data [in/out] RSA Data to decrypt / Message resulting */ static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; switch (rsa_data->rsa_id) { case DRVCRYPT_RSA_NOPAD: case DRVCRYPT_RSASSA_PKCS_V1_5: case DRVCRYPT_RSASSA_PSS: ret = do_caam_decrypt(rsa_data, RSA_DECRYPT(NO)); break; case DRVCRYPT_RSA_PKCS_V1_5: ret = do_caam_decrypt(rsa_data, RSA_DECRYPT(PKCS_V1_5)); break; case DRVCRYPT_RSA_OAEP: ret = do_oaep_decoding(rsa_data); break; default: break; } return ret; } /* * Registration of the RSA Driver */ static const struct drvcrypt_rsa driver_rsa = { .alloc_keypair = do_allocate_keypair, .alloc_publickey = do_allocate_publickey, .free_publickey = do_free_publickey, .free_keypair = do_free_keypair, .gen_keypair = do_gen_keypair, .encrypt = do_encrypt, .decrypt = do_decrypt, .optional.ssa_sign = NULL, .optional.ssa_verify = NULL, }; enum caam_status caam_rsa_init(struct caam_jrcfg *caam_jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; if (caam_hal_ctrl_pknum(jr_base)) { caam_era = caam_hal_ctrl_era(jr_base); RSA_TRACE("CAAM Era %d", caam_era); if (!drvcrypt_register_rsa(&driver_rsa)) retstatus = CAAM_NO_ERROR; } return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/acipher/local.h000066400000000000000000000021421464416617300230530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * CAAM Cipher Local header. */ #ifndef __LOCAL_H__ #define __LOCAL_H__ #include "caam_common.h" /* * Prime generator structure for RSA */ struct prime_data_rsa { uint8_t era; /* CAAM Era version */ size_t key_size; /* Key size in bits */ struct caambuf *e; /* Key exponent e */ struct caambuf *p; /* Prime p */ struct caambuf *q; /* Prime q (can be NULL of only p asked) */ }; /* * Generate prime numbers for RSA * Algorithm based on the Chapter B.3.3 of the FIPS.184-6 specification * * @data [in/out] Prime generation data */ enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data); /* * Prime generator structure for DSA */ struct prime_data_dsa { struct caambuf *g; /* Generator g */ struct caambuf *p; /* Prime p */ struct caambuf *q; /* Prime q */ }; /* * Generate prime numbers for DSA * Algorithm based on the Chapter A.1.2 of the FIPS.186-4 specification * * @data [in/out] Prime generation data */ enum caam_status caam_prime_dsa_gen(struct prime_data_dsa *data); #endif /* __LOCAL_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/acipher/sub.mk000066400000000000000000000004221464416617300227310ustar00rootroot00000000000000incdirs-y += ../include srcs-$(CFG_NXP_CAAM_RSA_DRV) += caam_rsa.c caam_prime_rsa.c srcs-$(CFG_NXP_CAAM_DH_DRV) += caam_dh.c srcs-$(CFG_NXP_CAAM_ECC_DRV) += caam_ecc.c srcs-$(CFG_NXP_CAAM_DSA_DRV) += caam_dsa.c caam_prime_dsa.c srcs-$(CFG_NXP_CAAM_MATH_DRV) += caam_math.coptee_os-4.3.0/core/drivers/crypto/caam/blob/000077500000000000000000000000001464416617300211145ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/blob/caam_blob.c000066400000000000000000000036031464416617300231610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020 Pengutronix, Rouven Czerwinski */ #include #include #include #include #include #include #include #include #include #include #include #define MKVB_SIZE 32 static uint8_t stored_key[MKVB_SIZE]; static bool mkvb_retrieved; enum caam_status caam_blob_mkvb_init(vaddr_t baseaddr) { struct caam_jobctx jobctx = { }; enum caam_status res = CAAM_NO_ERROR; struct caambuf buf = { }; uint32_t *desc = NULL; assert(!mkvb_retrieved); res = caam_calloc_align_buf(&buf, MKVB_SIZE); if (res != CAAM_NO_ERROR) goto out; desc = caam_calloc_desc(8); if (!desc) { res = CAAM_OUT_MEMORY; goto out_buf; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, SEQ_OUT_PTR(32)); caam_desc_add_ptr(desc, buf.paddr); caam_desc_add_word(desc, BLOB_MSTR_KEY); BLOB_DUMPDESC(desc); cache_operation(TEE_CACHEFLUSH, buf.data, buf.length); jobctx.desc = desc; res = caam_jr_enqueue(&jobctx, NULL); if (res != CAAM_NO_ERROR) { BLOB_TRACE("JR return code: %#"PRIx32, res); BLOB_TRACE("MKVB failed: Job status %#"PRIx32, jobctx.status); } else { cache_operation(TEE_CACHEINVALIDATE, buf.data, MKVB_SIZE); BLOB_DUMPBUF("MKVB", buf.data, buf.length); memcpy(&stored_key, buf.data, buf.length); mkvb_retrieved = true; } out_buf: caam_free_desc(&desc); caam_free_buf(&buf); out: caam_hal_ctrl_inc_priblob(baseaddr); return res; } TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { COMPILE_TIME_ASSERT(sizeof(hwkey->data) <= sizeof(stored_key)); if (!mkvb_retrieved) return TEE_ERROR_SECURITY; memcpy(&hwkey->data, &stored_key, sizeof(hwkey->data)); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/crypto/caam/blob/caam_dek.c000066400000000000000000000065231464416617300230120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019-2021, 2023 NXP */ #include #include #include #include #include #include #include #include #include #ifdef CFG_PHYS_64BIT #define BLOB_OPERATE_DESC_ENTRIES 12 #else #define BLOB_OPERATE_DESC_ENTRIES 10 #endif /* Secure Memory Access Permission allowed */ #define SM_GRP_BLOB BIT32(3) /* Export/Import Secure Memory blobs allowed */ /* Secure Memory Page(s)/Partition definition for DEK Blob generation */ static const struct caam_sm_page_desc dek_sm_page = { .partition = 1, .page = 3, .page_count = 1, }; TEE_Result caam_dek_generate(const uint8_t *payload, size_t payload_size, uint8_t *dek, size_t dek_size) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_sm_page_addr dek_sm_addr = { }; struct caamdmaobj resblob = { }; struct caam_jobctx jobctx = { }; uint32_t key_modifier[2] = { }; uint32_t *desc = NULL; unsigned int opflags = 0; assert(payload && dek); assert(payload_size && dek_size); /* Re-allocate output buffer if alignment needed */ ret = caam_dmaobj_output_sgtbuf(&resblob, dek, dek_size, dek_size); if (ret) return ret; /* Allocate page(s) in one Secure Memory partition */ ret = caam_sm_alloc(&dek_sm_page, &dek_sm_addr); if (ret != CAAM_NO_ERROR) { BLOB_TRACE("Secure memory allocation error 0x%" PRIx32, ret); goto out; } /* Copy input data to encapsulate in Secure Memory allocated */ memcpy((void *)dek_sm_addr.vaddr, payload, payload_size); /* * Set the partition access rights for the group #1 to be * a blob export/import */ caam_sm_set_access_perm(&dek_sm_page, SM_GRP_BLOB, 0); /* * Create the key modifier: * 31 16 8 0 * --------------------------------------------------- * | Length of the payload | AES - 0x55 | CCM - 0x66 | * --------------------------------------------------- */ key_modifier[0] = SHIFT_U32(payload_size, 16) | SHIFT_U32(0x55, 8) | SHIFT_U32(0x66, 0); key_modifier[1] = 0; /* Allocate the descriptor */ desc = caam_calloc_desc(BLOB_OPERATE_DESC_ENTRIES); if (!desc) { BLOB_TRACE("CAAM Context Descriptor Allocation error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, LD_IMM_OFF(CLASS_2, REG_KEY, 8, 12)); caam_desc_add_word(desc, key_modifier[0]); caam_desc_add_word(desc, key_modifier[1]); caam_desc_add_word(desc, SEQ_IN_PTR(payload_size)); caam_desc_add_ptr(desc, dek_sm_addr.paddr); caam_desc_seq_out(desc, &resblob); caam_desc_add_word(desc, BLOB_ENCAPS | PROT_BLOB_SEC_MEM | opflags); BLOB_DUMPDESC(desc); cache_operation(TEE_CACHECLEAN, (void *)payload, payload_size); caam_dmaobj_cache_push(&resblob); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus) { BLOB_TRACE("CAAM Status 0x%08" PRIx32 "", jobctx.status); goto out; } caam_dmaobj_copy_to_orig(&resblob); BLOB_TRACE("Done CAAM BLOB from Secure Memory encaps"); BLOB_DUMPBUF("Blob Output", resblob.orig.data, resblob.orig.length); out: caam_sm_free(&dek_sm_page); caam_free_desc(&desc); caam_dmaobj_free(&resblob); return caam_status_to_tee_result(retstatus); } optee_os-4.3.0/core/drivers/crypto/caam/blob/sub.mk000066400000000000000000000001611464416617300222340ustar00rootroot00000000000000srcs-$(CFG_NXP_CAAM_BLOB_DRV) += caam_blob.c srcs-$(CFG_NXP_CAAM_DEK_DRV) += caam_dek.c incdirs-y += ../include optee_os-4.3.0/core/drivers/crypto/caam/caam_ctrl.c000066400000000000000000000113331464416617300222700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2021, 2023 NXP * * Brief CAAM Global Controller. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * If the CAAM DMA only supports 32 bits physical addresses, OPTEE must * be located within the 32 bits address space. */ #ifndef CFG_CAAM_64BIT static_assert((CFG_TZDRAM_START + CFG_TZDRAM_SIZE) < UINT32_MAX); #endif /* Crypto driver initialization */ static TEE_Result crypto_driver_init(void) { TEE_Result retresult = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_jrcfg jrcfg = {}; /* Enable the CAAM Clock */ caam_hal_clk_enable(true); /* Set OTP as master key if the platform is closed */ if (snvs_is_device_closed()) { retresult = imx_snvs_set_master_otpmk(); if (retresult && retresult != TEE_ERROR_NOT_IMPLEMENTED) goto exit_init; } retstatus = caam_hal_cfg_get_conf(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_NOT_SUPPORTED; goto exit_init; } /* Initialize the CAAM Controller */ caam_hal_ctrl_init(jrcfg.base); /* Initialize the Job Ring to be used */ retstatus = caam_jr_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the RNG Module */ retstatus = caam_rng_init(jrcfg.base); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the Hash Module */ retstatus = caam_hash_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the MATH Module */ retstatus = caam_math_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the RSA Module */ retstatus = caam_rsa_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the Cipher Module */ retstatus = caam_cipher_init(jrcfg.base); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the HMAC Module */ retstatus = caam_hmac_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the BLOB Module */ retstatus = caam_blob_mkvb_init(jrcfg.base); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the CMAC Module */ retstatus = caam_cmac_init(jrcfg.base); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the ECC Module */ retstatus = caam_ecc_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the DH Module */ retstatus = caam_dh_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the DSA Module */ retstatus = caam_dsa_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the Manufacturing Protection Module */ retstatus = caam_mp_init(jrcfg.base); if (retstatus != CAAM_NO_ERROR && retstatus != CAAM_NOT_SUPPORTED) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the secure memory */ retstatus = caam_sm_init(&jrcfg); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Initialize the KEY Module */ retstatus = caam_key_init(); if (retstatus != CAAM_NO_ERROR) { retresult = TEE_ERROR_GENERIC; goto exit_init; } /* Everything is OK, register the Power Management handler */ caam_pwr_init(); /* * Configure Job Rings to NS World * If the Driver Crypto is not used CFG_NXP_CAAM_RUNTIME_JR is not * enable, hence relax the JR used for the CAAM configuration to * the Non-Secure */ if (jrcfg.base) caam_hal_cfg_setup_nsjobring(&jrcfg); retresult = TEE_SUCCESS; exit_init: if (retresult != TEE_SUCCESS) { EMSG("CAAM Driver initialization (0x%" PRIx32 ")", retresult); panic(); } return retresult; } early_init(crypto_driver_init); /* Crypto driver late initialization to complete on-going CAAM operations */ static TEE_Result init_caam_late(void) { enum caam_status ret = CAAM_BUSY; ret = caam_jr_complete(); if (ret != CAAM_NO_ERROR) { EMSG("CAAM initialization failed"); panic(); } return TEE_SUCCESS; } early_init_late(init_caam_late); optee_os-4.3.0/core/drivers/crypto/caam/caam_desc.c000066400000000000000000000073201464416617300222430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019, 2021 NXP * * Brief Descriptor construction functions. */ #include #include #include #include struct ptr_addr { #ifdef CFG_CAAM_BIG_ENDIAN uint32_t high; uint32_t low; #else uint32_t low; uint32_t high; #endif /* CFG_CAAM_BIG_ENDIAN */ }; uint32_t caam_desc_get_len(uint32_t *desc) { return GET_JD_DESCLEN(caam_read_val32((void *)desc)); } void caam_desc_init(uint32_t *desc) { *desc = 0; } void caam_desc_update_hdr(uint32_t *desc, uint32_t word) { /* Update first word of desc */ caam_write_val32((void *)desc, word); } void caam_desc_add_word(uint32_t *desc, uint32_t word) { uint32_t len = caam_desc_get_len(desc); uint32_t *last = desc + len; /* Add Word at Last */ caam_write_val32((void *)last, word); /* Increase the length */ caam_write_val32((void *)desc, caam_read_val32((void *)desc) + 1); } void caam_desc_add_ptr(uint32_t *desc, paddr_t ptr) { uint32_t len = caam_desc_get_len(desc); uint32_t *last = desc + len; uint32_t inc = 1; /* Add Word at Last */ #ifdef CFG_CAAM_64BIT struct ptr_addr *ptr_addr = (struct ptr_addr *)(uintptr_t)last; #ifdef CFG_ARM64_core caam_write_val32(&ptr_addr->high, ptr >> 32); #else caam_write_val32(&ptr_addr->high, 0); #endif /* CFG_ARM64_core */ caam_write_val32(&ptr_addr->low, ptr); inc++; #else caam_write_val32((void *)last, ptr); #endif /* CFG_CAAM_64BIT */ /* Increase the length */ caam_write_val32((void *)desc, caam_read_val32((void *)desc) + inc); } #ifdef CFG_CAAM_64BIT void caam_desc_push(struct caam_inring_entry *in_entry, paddr_t paddr) { #ifdef CFG_CAAM_BIG_ENDIAN put_be64(&in_entry->desc, paddr); #else put_le64(&in_entry->desc, paddr); #endif /* CFG_CAAM_BIG_ENDIAN */ } paddr_t caam_desc_pop(struct caam_outring_entry *out_entry) { const uintptr_t v_desc = (uintptr_t)&out_entry->desc; const uint32_t *a32 = (const uint32_t *)v_desc; #ifdef CFG_CAAM_BIG_ENDIAN return SHIFT_U64(get_be32(&a32[0]), 32) | get_be32(&a32[1]); #else return SHIFT_U64(a32[1], 32) | a32[0]; #endif /* CFG_CAAM_BIG_ENDIAN */ } #else /* CFG_CAAM_64BIT */ void caam_desc_push(struct caam_inring_entry *in_entry, paddr_t paddr) { caam_write_val32(&in_entry->desc, paddr); } paddr_t caam_desc_pop(struct caam_outring_entry *out_entry) { return caam_read_val32(&out_entry->desc); } #endif /* CFG_CAAM_64BIT */ uint32_t caam_read_jobstatus(struct caam_outring_entry *out) { return caam_read_val32(&out->status); } void caam_desc_add_dmaobj(uint32_t *desc, struct caamdmaobj *data, unsigned int pre_op) { uint32_t operation = pre_op; size_t op_length = 0; uint32_t op_ext_length = 0; if (data->sgtbuf.sgt_type) operation |= CMD_SGT; /* Check the operation length to set extension length or not */ switch (GET_CMD_TYPE(pre_op)) { case CMD_FIFO_LOAD_TYPE: op_length = FIFO_LOAD_LENGTH(data->sgtbuf.length); op_ext_length = FIFO_LOAD_EXT; break; case CMD_STORE_TYPE: /* Note: there is extension length for the STORE command */ op_length = STORE_LENGTH(data->sgtbuf.length); break; case CMD_FIFO_STORE_TYPE: op_length = FIFO_STORE_LENGTH(data->sgtbuf.length); op_ext_length = FIFO_STORE_EXT; break; case CMD_KEY_TYPE: /* Note: there is extension length for the KEY command */ op_length = KEY_LENGTH(data->sgtbuf.length); break; case CMD_SEQ_OUT_TYPE: op_length = SEQ_LENGTH(data->sgtbuf.length); op_ext_length = SEQ_EXT; break; default: break; } if (op_length == data->sgtbuf.length) operation |= op_length; else operation |= op_ext_length; caam_desc_add_word(desc, operation); caam_desc_add_ptr(desc, data->sgtbuf.paddr); if (op_length != data->sgtbuf.length) caam_desc_add_word(desc, data->sgtbuf.length); } optee_os-4.3.0/core/drivers/crypto/caam/caam_jr.c000066400000000000000000000433301464416617300217410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Job Rings manager. * Implementation of functions to enqueue/dequeue CAAM Job Descriptor */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Job Free define */ #define JR_JOB_FREE 0 /* * Caller information context object */ struct caller_info { struct caam_jobctx *jobctx; /* Caller job context object */ uint32_t job_id; /* Current Job ID */ paddr_t pdesc; /* Physical address of the descriptor */ }; /* * Job Ring module private data */ struct jr_privdata { vaddr_t baseaddr; /* Job Ring base address */ vaddr_t ctrladdr; /* CAAM virtual base address */ paddr_t jroffset; /* Job Ring address offset */ uint64_t paddr_inrings; /* CAAM physical addr of input queue */ uint64_t paddr_outrings; /* CAAM physical addr of output queue */ uint8_t nb_jobs; /* Number of Job ring entries managed */ /* Input Job Ring Variables */ struct caam_inring_entry *inrings; /* Input JR HW queue */ unsigned int inlock; /* Input JR spin lock */ uint16_t inwrite_index; /* SW Index - next JR entry free */ /* Output Job Ring Variables */ struct caam_outring_entry *outrings; /* Output JR HW queue */ unsigned int outlock; /* Output JR spin lock */ uint16_t outread_index; /* SW Index - next JR output done */ /* Caller Information Variables */ struct caller_info *callers; /* Job Ring Caller information */ unsigned int callers_lock; /* Job Ring Caller spin lock */ struct itr_handler it_handler; /* Interrupt handler */ }; /* * Job Ring module private data reference */ static struct jr_privdata *jr_privdata; /* * Free module resources * * @jr_priv Reference to the module private data */ static void do_jr_free(struct jr_privdata *jr_priv) { if (jr_priv) { caam_free(jr_priv->inrings); caam_free(jr_priv->outrings); caam_free(jr_priv->callers); caam_free(jr_priv); } } /* * Allocate module resources * * @privdata [out] Allocated Job Ring private data * @nb_jobs Number of jobs to manage in the queue */ static enum caam_status do_jr_alloc(struct jr_privdata **privdata, uint8_t nb_jobs) { enum caam_status retstatus = CAAM_OUT_MEMORY; struct jr_privdata *jr_priv = NULL; /* Allocate the Job Ring private data */ jr_priv = caam_calloc(sizeof(*jr_priv)); if (!jr_priv) { JR_TRACE("Private Data allocation error"); goto end_alloc; } /* Setup the number of jobs */ jr_priv->nb_jobs = nb_jobs; /* Allocate the input and output job ring queues */ jr_priv->inrings = caam_calloc_align(nb_jobs * sizeof(struct caam_inring_entry)); jr_priv->outrings = caam_calloc_align(nb_jobs * sizeof(struct caam_outring_entry)); /* Allocate the callers information */ jr_priv->callers = caam_calloc(nb_jobs * sizeof(struct caller_info)); if (!jr_priv->inrings || !jr_priv->outrings || !jr_priv->callers) { JR_TRACE("JR resources allocation error"); goto end_alloc; } /* Initialize the spin locks */ jr_priv->inlock = SPINLOCK_UNLOCK; jr_priv->outlock = SPINLOCK_UNLOCK; jr_priv->callers_lock = SPINLOCK_UNLOCK; /* Initialize the queue counter */ jr_priv->inwrite_index = 0; jr_priv->outread_index = 0; /* * Ensure that allocated queue initialization is pushed to the physical * memory */ cache_operation(TEE_CACHEFLUSH, jr_priv->inrings, nb_jobs * sizeof(struct caam_inring_entry)); cache_operation(TEE_CACHEFLUSH, jr_priv->outrings, nb_jobs * sizeof(struct caam_outring_entry)); retstatus = CAAM_NO_ERROR; end_alloc: if (retstatus != CAAM_NO_ERROR) do_jr_free(jr_priv); else *privdata = jr_priv; return retstatus; } /* * Job Ring Interrupt handler * * @handler Interrupt Handler structure */ static enum itr_return caam_jr_irqhandler(struct itr_handler *handler) { JR_TRACE("Disable the interrupt"); interrupt_disable(handler->chip, handler->it); /* Send a signal to exit WFE loop */ sev(); return ITRR_HANDLED; } /* * Returns all jobs completed depending on the input @wait_job_ids mask. * * Dequeues all Jobs completed. Call the job context callback * function. Function returns the bit mask of the expected completed job * (@wait_job_ids parameter) * * @wait_job_ids Expected Jobs to be complete */ static uint32_t do_jr_dequeue(uint32_t wait_job_ids) { uint32_t ret_job_id = 0; struct caller_info *caller = NULL; struct caam_outring_entry *jr_out = NULL; struct caam_jobctx *jobctx = NULL; uint32_t exceptions = 0; bool found = false; uint16_t idx_jr = 0; uint32_t nb_jobs_done = 0; size_t nb_jobs_inv = 0; exceptions = cpu_spin_lock_xsave(&jr_privdata->outlock); nb_jobs_done = caam_hal_jr_get_nbjob_done(jr_privdata->baseaddr); if (nb_jobs_done == 0) { cpu_spin_unlock_xrestore(&jr_privdata->outlock, exceptions); return ret_job_id; } /* Ensure that output ring descriptor entries are not in cache */ if ((jr_privdata->outread_index + nb_jobs_done) > jr_privdata->nb_jobs) { /* * Invalidate the whole circular job buffer because some * completed job rings are at the beginning of the buffer */ jr_out = jr_privdata->outrings; nb_jobs_inv = jr_privdata->nb_jobs; } else { /* Invalidate only the completed job */ jr_out = &jr_privdata->outrings[jr_privdata->outread_index]; nb_jobs_inv = nb_jobs_done; } cache_operation(TEE_CACHEINVALIDATE, jr_out, sizeof(struct caam_outring_entry) * nb_jobs_inv); for (; nb_jobs_done; nb_jobs_done--) { jr_out = &jr_privdata->outrings[jr_privdata->outread_index]; /* * Lock the caller information array because enqueue is * also touching it */ cpu_spin_lock(&jr_privdata->callers_lock); for (idx_jr = 0, found = false; idx_jr < jr_privdata->nb_jobs; idx_jr++) { /* * Search for the caller information corresponding to * the completed JR. * Don't use the outread_index or inwrite_index because * completion can be out of order compared to input * buffer */ caller = &jr_privdata->callers[idx_jr]; if (caam_desc_pop(jr_out) == caller->pdesc) { jobctx = caller->jobctx; jobctx->status = caam_read_jobstatus(jr_out); /* Update return Job IDs mask */ if (caller->job_id & wait_job_ids) ret_job_id |= caller->job_id; JR_TRACE("JR id=%" PRId32 ", context @0x%08" PRIxVA, caller->job_id, (vaddr_t)jobctx); /* Clear the Entry Descriptor DMA */ caller->pdesc = 0; caller->jobctx = NULL; caller->job_id = JR_JOB_FREE; found = true; JR_TRACE("Free space #%" PRId16 " in the callers array", idx_jr); break; } } cpu_spin_unlock(&jr_privdata->callers_lock); /* * Remove the JR from the output list even if no * JR caller found */ caam_hal_jr_del_job(jr_privdata->baseaddr); /* * Increment index to next JR output entry taking care that * it is a circular buffer of nb_jobs size. */ jr_privdata->outread_index++; jr_privdata->outread_index %= jr_privdata->nb_jobs; if (found && jobctx->callback) { /* Finally, execute user's callback */ jobctx->callback(jobctx); } } cpu_spin_unlock_xrestore(&jr_privdata->outlock, exceptions); return ret_job_id; } /* * Enqueues a new job in the Job Ring input queue. Keep the caller's * job context in private array. * * @jobctx Caller's job context * @job_id [out] Job ID enqueued */ static enum caam_status do_jr_enqueue(struct caam_jobctx *jobctx, uint32_t *job_id) { enum caam_status retstatus = CAAM_BUSY; struct caam_inring_entry *cur_inrings = NULL; struct caller_info *caller = NULL; uint32_t exceptions = 0; uint32_t job_mask = 0; uint8_t idx_jr = 0; bool found = false; exceptions = cpu_spin_lock_xsave(&jr_privdata->inlock); caam_hal_clk_enable(true); /* * Stay locked until a job is available * Check if there is an available JR index in the HW */ while (caam_hal_jr_read_nbslot_available(jr_privdata->baseaddr) == 0) { /* * WFE will return thanks to a SEV generated by the * interrupt handler or by a spin_unlock */ wfe(); }; /* * There is a space free in the input ring but it doesn't mean * that the job pushed is completed. * Completion is out of order. Look for a free space in the * caller data to push them and get a job ID for the completion * * Lock the caller information array because dequeue is * also touching it */ cpu_spin_lock(&jr_privdata->callers_lock); for (idx_jr = 0; idx_jr < jr_privdata->nb_jobs; idx_jr++) { if (jr_privdata->callers[idx_jr].job_id == JR_JOB_FREE) { JR_TRACE("Found a space #%" PRId8 " free in the callers array", idx_jr); job_mask = 1 << idx_jr; /* Store the caller information for the JR completion */ caller = &jr_privdata->callers[idx_jr]; caller->job_id = job_mask; caller->jobctx = jobctx; caller->pdesc = virt_to_phys((void *)jobctx->desc); found = true; break; } } cpu_spin_unlock(&jr_privdata->callers_lock); if (!found) { JR_TRACE("Error didn't find a free space in the callers array"); goto end_enqueue; } JR_TRACE("Push id=%" PRId16 ", job (0x%08" PRIx32 ") context @0x%08" PRIxVA, jr_privdata->inwrite_index, job_mask, (vaddr_t)jobctx); cur_inrings = &jr_privdata->inrings[jr_privdata->inwrite_index]; /* Push the descriptor into the JR HW list */ caam_desc_push(cur_inrings, caller->pdesc); /* Ensure that physical memory is up to date */ cache_operation(TEE_CACHECLEAN, cur_inrings, sizeof(struct caam_inring_entry)); /* * Increment index to next JR input entry taking care that * it is a circular buffer of nb_jobs size. */ jr_privdata->inwrite_index++; jr_privdata->inwrite_index %= jr_privdata->nb_jobs; /* Ensure that input descriptor is pushed in physical memory */ cache_operation(TEE_CACHECLEAN, jobctx->desc, DESC_SZBYTES(caam_desc_get_len(jobctx->desc))); /* Inform HW that a new JR is available */ caam_hal_jr_add_newjob(jr_privdata->baseaddr); *job_id = job_mask; retstatus = CAAM_NO_ERROR; end_enqueue: cpu_spin_unlock_xrestore(&jr_privdata->inlock, exceptions); return retstatus; } /* * Synchronous job completion callback * * @jobctx Job context */ static void job_done(struct caam_jobctx *jobctx) { jobctx->completion = true; } void caam_jr_cancel(uint32_t job_id) { unsigned int idx = 0; cpu_spin_lock(&jr_privdata->callers_lock); JR_TRACE("Job cancel 0x%" PRIx32, job_id); for (idx = 0; idx < jr_privdata->nb_jobs; idx++) { /* * Search for the caller information corresponding to * the job_id mask. */ if (jr_privdata->callers[idx].job_id == job_id) { /* Clear the Entry Descriptor */ jr_privdata->callers[idx].pdesc = 0; jr_privdata->callers[idx].jobctx = NULL; jr_privdata->callers[idx].job_id = JR_JOB_FREE; return; } } cpu_spin_unlock(&jr_privdata->callers_lock); } enum caam_status caam_jr_dequeue(uint32_t job_ids, unsigned int timeout_ms) { uint32_t job_complete = 0; uint32_t nb_loop = 0; bool infinite = false; bool it_active = false; if (timeout_ms == UINT_MAX) infinite = true; else nb_loop = timeout_ms * 100; do { /* Call the do_jr_dequeue function to dequeue the jobs */ job_complete = do_jr_dequeue(job_ids); /* Check if new job has been submitted and acknowledge it */ it_active = caam_hal_jr_check_ack_itr(jr_privdata->baseaddr); if (job_complete & job_ids) return CAAM_NO_ERROR; /* Check if JR interrupt otherwise wait a bit */ if (!it_active) caam_udelay(10); } while (infinite || (nb_loop--)); return CAAM_TIMEOUT; } enum caam_status caam_jr_enqueue(struct caam_jobctx *jobctx, uint32_t *job_id) { enum caam_status retstatus = CAAM_FAILURE; __maybe_unused int timeout = 10; /* Nb loops to pool job completion */ if (!jobctx) return CAAM_BAD_PARAM; JR_DUMPDESC(jobctx->desc); if (!jobctx->callback && job_id) { JR_TRACE("Job Callback not defined whereas asynchronous"); return CAAM_BAD_PARAM; } if (jobctx->callback && !job_id) { JR_TRACE("Job Id not defined whereas asynchronous"); return CAAM_BAD_PARAM; } jobctx->completion = false; jobctx->status = 0; /* * If parameter job_id is NULL, the job is synchronous, hence use * the local job_done callback function */ if (!jobctx->callback && !job_id) { jobctx->callback = job_done; jobctx->context = jobctx; } retstatus = do_jr_enqueue(jobctx, &jobctx->id); if (retstatus != CAAM_NO_ERROR) { JR_TRACE("enqueue job error 0x%08x", retstatus); return retstatus; } /* * If parameter job_id is defined, the job is asynchronous, so * returns with setting the job_id value */ if (job_id) { *job_id = jobctx->id; return CAAM_PENDING; } #ifdef TIMEOUT_COMPLETION /* * Job is synchronous wait until job completion or timeout */ while (!jobctx->completion && timeout--) caam_jr_dequeue(jobctx->id, 100); if (timeout <= 0) { /* Job timeout, cancel it and return in error */ caam_jr_cancel(jobctx->id); retstatus = CAAM_TIMEOUT; } else { if (JRSTA_SRC_GET(jobctx->status) != JRSTA_SRC(NONE)) retstatus = CAAM_JOB_STATUS; else retstatus = CAAM_NO_ERROR; } #else /* * Job is synchronous wait until job complete * Don't use a timeout because there is no HW timer and * so the timeout is not precise */ while (!jobctx->completion) caam_jr_dequeue(jobctx->id, 100); if (JRSTA_SRC_GET(jobctx->status) != JRSTA_SRC(NONE)) retstatus = CAAM_JOB_STATUS; else retstatus = CAAM_NO_ERROR; #endif /* Erase local callback function */ jobctx->callback = NULL; return retstatus; } enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg) { enum caam_status retstatus = CAAM_FAILURE; JR_TRACE("Initialization"); /* Allocate the Job Ring resources */ retstatus = do_jr_alloc(&jr_privdata, jrcfg->nb_jobs); if (retstatus != CAAM_NO_ERROR) goto end_init; jr_privdata->ctrladdr = jrcfg->base; jr_privdata->jroffset = jrcfg->offset; retstatus = caam_hal_jr_setowner(jrcfg->base, jrcfg->offset, JROWN_ARM_S); JR_TRACE("JR setowner returned 0x%x", retstatus); if (retstatus != CAAM_NO_ERROR) goto end_init; jr_privdata->baseaddr = jrcfg->base + jrcfg->offset; retstatus = caam_hal_jr_reset(jr_privdata->baseaddr); if (retstatus != CAAM_NO_ERROR) goto end_init; /* * Get the physical address of the Input/Output queue * The HW configuration is 64 bits registers regardless * the CAAM or CPU addressing mode. */ jr_privdata->paddr_inrings = virt_to_phys(jr_privdata->inrings); jr_privdata->paddr_outrings = virt_to_phys(jr_privdata->outrings); if (!jr_privdata->paddr_inrings || !jr_privdata->paddr_outrings) { JR_TRACE("JR bad queue pointers"); retstatus = CAAM_FAILURE; goto end_init; } caam_hal_jr_config(jr_privdata->baseaddr, jr_privdata->nb_jobs, jr_privdata->paddr_inrings, jr_privdata->paddr_outrings); /* * Prepare the interrupt handler to secure the interrupt even * if the interrupt is not used */ jr_privdata->it_handler.chip = interrupt_get_main_chip(); jr_privdata->it_handler.it = jrcfg->it_num; jr_privdata->it_handler.flags = ITRF_TRIGGER_LEVEL; jr_privdata->it_handler.handler = caam_jr_irqhandler; jr_privdata->it_handler.data = jr_privdata; #if defined(CFG_NXP_CAAM_RUNTIME_JR) && defined(CFG_CAAM_ITR) if (interrupt_add_handler(&jr_privdata->it_handler)) { retstatus = CAAM_FAILURE; goto end_init; } #endif caam_hal_jr_enable_itr(jr_privdata->baseaddr); retstatus = CAAM_NO_ERROR; end_init: if (retstatus != CAAM_NO_ERROR) do_jr_free(jr_privdata); return retstatus; } enum caam_status caam_jr_halt(void) { enum caam_status retstatus = CAAM_FAILURE; __maybe_unused uint32_t job_complete = 0; retstatus = caam_hal_jr_halt(jr_privdata->baseaddr); /* * All jobs in the input queue have been done, call the * dequeue function to complete them. */ job_complete = do_jr_dequeue(UINT32_MAX); JR_TRACE("Completion of jobs mask 0x%" PRIx32, job_complete); return retstatus; } enum caam_status caam_jr_flush(void) { enum caam_status retstatus = CAAM_FAILURE; __maybe_unused uint32_t job_complete = 0; retstatus = caam_hal_jr_flush(jr_privdata->baseaddr); /* * All jobs in the input queue have been done, call the * dequeue function to complete them. */ job_complete = do_jr_dequeue(UINT32_MAX); JR_TRACE("Completion of jobs mask 0x%" PRIx32, job_complete); return retstatus; } void caam_jr_resume(uint32_t pm_hint) { if (pm_hint == PM_HINT_CONTEXT_STATE) { #ifndef CFG_NXP_CAAM_RUNTIME_JR /* * In case the CAAM is not used the JR used to * instantiate the RNG has been released to Non-Secure * hence, need reconfigure the Secure JR and release * it after RNG instantiation */ caam_hal_jr_setowner(jr_privdata->ctrladdr, jr_privdata->jroffset, JROWN_ARM_S); caam_hal_jr_config(jr_privdata->baseaddr, jr_privdata->nb_jobs, jr_privdata->paddr_inrings, jr_privdata->paddr_outrings); #endif /* CFG_NXP_CAAM_RUNTIME_JR */ /* Read the current job ring index */ jr_privdata->inwrite_index = caam_hal_jr_input_index(jr_privdata->baseaddr); /* Read the current output ring index */ jr_privdata->outread_index = caam_hal_jr_output_index(jr_privdata->baseaddr); if (caam_rng_instantiation() != CAAM_NO_ERROR) panic(); #ifndef CFG_NXP_CAAM_RUNTIME_JR caam_hal_jr_setowner(jr_privdata->ctrladdr, jr_privdata->jroffset, JROWN_ARM_NS); #endif /* CFG_NXP_CAAM_RUNTIME_JR */ } else { caam_hal_jr_resume(jr_privdata->baseaddr); } } enum caam_status caam_jr_complete(void) { enum caam_status ret = CAAM_BUSY; ret = caam_hal_jr_flush(jr_privdata->baseaddr); if (ret == CAAM_NO_ERROR) caam_hal_jr_resume(jr_privdata->baseaddr); return ret; } optee_os-4.3.0/core/drivers/crypto/caam/caam_key.c000066400000000000000000000451531464416617300221230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * CAAM Key magic number. * When the first 32 bits of a key buffer are equal to this value, the buffer * is a serialized CAAM key structure. */ #define MAGIC_NUMBER 0xCAAFBFFB /* * Because the CAAM driver relies on this magic number to determine if the key * is plain text or black, collision can happen. A randomly generated plain text * key could feature the magic number. That's unlikely but still possible. * * Regarding the possibility of collision or forging attack, there are no * security concerns. Forging and trying to make a plain text key look like a * black key, won't do much. If the key is forged to look like an ECB Black * key, the singing operation will output a corrupted result. If the key is * forged to look like a CCM Black key, the import key will fail (because the * MAC verification) and no signing operation will be done. */ #define BLOB_BKEK_SIZE 32 /* Blob key encryption key size */ #define BLOB_MAC_SIZE 16 /* Blob MAC size */ #define BLOB_PAD_SIZE (BLOB_BKEK_SIZE + BLOB_MAC_SIZE) /* * CAAM Blob key modifier * Key modifier used to derive Blob-key encryption key (BKEK) from the CAAM * master key. * * A CAAM black key is encrypted using a volatile Job Descriptor key encryption * key or JDKEK. Black keys are not intended for storage of keys across SoC * power cycles. The JDKEK is re-generated upon every power cycle (reset, * suspend/resume ...) or CAAM RNG re-seed. * * To retain key across power cycles, the black key must be encapsulated as a * blob. The blob key encryption key is derived from the CAAM master key which * makes it non-volatile and can be re-created when the chip powers up again. */ #define KEY_BLOB_MODIFIER_SIZE 16 static const uint8_t key_blob_modifier[KEY_BLOB_MODIFIER_SIZE] = "NXP_OPTEE_BLOB"; /* * Serialized CAAM key structure format. * * If the incoming key buffer is the following: * | Magic number | key type | key size | key blob buffer | * The CAAM Key structure will be populated as following: * struct caamkey { * .key_type = key type, * .key_size = key size, * .is_blob = true, * .buf = key blob buffer * } * * If the incoming key buffer is the following: * | Key buffer | * The CAAM Key structure will be populated as following: * struct caamkey { * .key_type = CAAM_KEY_PLAIN_TEXT, * .key_size = sizeof(Key buffer), * .is_blob = false, * .buf = key buffer * } */ struct caam_key_serialized { uint32_t magic_number; /* Magic number */ uint32_t key_type; /* Black key type */ uint32_t sec_size; /* The original plain text key size */ uint8_t key[]; }; /* * CAAM key type enumeration to string */ static const char *const caam_key_type_to_str[] __maybe_unused = { [CAAM_KEY_PLAIN_TEXT] = "Plain Text", [CAAM_KEY_BLACK_ECB] = "Black ECB", [CAAM_KEY_BLACK_CCM] = "Black CCM", }; static struct caam_key_serialized *data_to_serialized_key(const uint8_t *data, size_t size) { assert(data && size); assert(size > sizeof(struct caam_key_serialized)); /* * It's important to make sure uint8_t and caam_key_serialized{} are * actually aligned for performance purpose. * * A __packed attribute to caam_key_serialized{} could solve the * alignment issue but at the cost of un-optimize memory access. * To avoid using the __packed attribute, caam_key_serialized{} is * defined to be aligned on uint8_t. The following assert checks * for this alignment. */ assert(IS_ALIGNED_WITH_TYPE(data, struct caam_key_serialized)); /* * The cast to void* instead of struct caam_key_serialized* is needed * to avoid the cast alignment compilation warning. */ return (void *)data; } /* * Return the CAAM key type of the given key buffer * * @data Input buffer * @size Input buffer size */ static enum caam_key_type get_key_type(const uint8_t *data, size_t size) { struct caam_key_serialized *key = data_to_serialized_key(data, size); if (key->magic_number != MAGIC_NUMBER) return CAAM_KEY_PLAIN_TEXT; return key->key_type; } /* * Return the CAAM key size of the given key buffer * * @data Input buffer * @size Input buffer size */ static size_t get_key_sec_size(const uint8_t *data, size_t size) { struct caam_key_serialized *key = data_to_serialized_key(data, size); if (key->magic_number != MAGIC_NUMBER) return size; return key->sec_size; } /* * Return the CAAM key buffer pointer of the given key buffer * * @data Input buffer * @size Input buffer size */ static unsigned long get_key_buf_offset(const uint8_t *data, size_t size) { struct caam_key_serialized *key = data_to_serialized_key(data, size); if (key->magic_number != MAGIC_NUMBER) return 0; else return offsetof(struct caam_key_serialized, key); } /* * Return the CAAM key buffer size of the given key buffer * * @data Input buffer * @size Input buffer size */ static size_t get_key_buf_size(const uint8_t *data, size_t size) { struct caam_key_serialized *key = data_to_serialized_key(data, size); /* * In the caam_key_serialized{}, the last element of the structure is * a variable-sized buffer. */ return size - sizeof(*key); } size_t caam_key_get_alloc_size(const struct caamkey *key) { if (!key) return 0; /* A blob size is independent from the key encryption algorithm */ if (key->is_blob) return key->sec_size + BLOB_PAD_SIZE; switch (key->key_type) { case CAAM_KEY_PLAIN_TEXT: /* * If the key is plain text, the allocation size is equal to the * key size and no blob operation on this key is possible. */ return key->sec_size; case CAAM_KEY_BLACK_ECB: /* ECB-black key must be a multiple of 16 bytes */ return ROUNDUP(key->sec_size, 16); case CAAM_KEY_BLACK_CCM: /* * CCM-black key must be a multiple of 8 bytes. The nonce and * ICV add another 12 bytes to the allocation size */ return ROUNDUP(key->sec_size, 8) + BLACK_KEY_NONCE_SIZE + BLACK_KEY_ICV_SIZE; default: return 0; } } void caam_key_dump(const char *trace, const struct caamkey *key) { if (!key || !trace) return; if (key->key_type >= CAAM_KEY_MAX_VALUE) return; KEY_TRACE("%s key_type:%s key_size:%zu is_blob:%s addr:%p", caam_key_type_to_str[key->key_type], trace, key->sec_size, key->is_blob ? "yes" : "no", key->buf.data); if (key->buf.data) KEY_DUMPBUF("Key data", key->buf.data, key->buf.length); } enum caam_status caam_key_alloc(struct caamkey *key) { size_t alloc_size = 0; if (!key) return CAAM_BAD_PARAM; if (key->buf.data) { KEY_TRACE("Key already allocated"); return CAAM_BAD_PARAM; } alloc_size = caam_key_get_alloc_size(key); if (!alloc_size) return CAAM_FAILURE; return caam_calloc_align_buf(&key->buf, alloc_size); } void caam_key_free(struct caamkey *key) { if (!key) return; caam_free_buf(&key->buf); } void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key) { if (!key) return; if (!key->buf.nocache) cache_operation(op, key->buf.data, key->buf.length); } #define BLOB_OP_DESC_ENTRIES 12 enum caam_status caam_key_operation_blob(const struct caamkey *in_key, struct caamkey *out_key) { enum caam_status status = CAAM_FAILURE; struct caam_jobctx jobctx = { }; uint32_t opflag = PROT_BLOB_TYPE(BLACK_KEY); uint32_t *desc = NULL; size_t output_buffer_size = 0; size_t input_buffer_size = 0; assert(in_key && out_key); KEY_TRACE("Blob %scapsulation of the following key", in_key->is_blob ? "de" : "en"); caam_key_dump("Blob input key", in_key); /* This function blobs or un-blobs */ if (in_key->is_blob == out_key->is_blob) { KEY_TRACE("Only one key must be defined as a blob"); return CAAM_BAD_PARAM; } /* A black blob cannot take a plain test key as input */ if (out_key->key_type == CAAM_KEY_PLAIN_TEXT || in_key->key_type == CAAM_KEY_PLAIN_TEXT) { KEY_TRACE("A blob in/out operation cannot be plain text"); return CAAM_BAD_PARAM; } /* The key type must remain the same */ if (out_key->key_type != in_key->key_type) { KEY_TRACE("The in/out keys must have the same key type"); return CAAM_BAD_PARAM; } /* Define blob operation direction */ if (out_key->is_blob) opflag |= BLOB_ENCAPS; else opflag |= BLOB_DECAPS; /* Build OP flags depending on the blob type */ switch (out_key->key_type) { case CAAM_KEY_BLACK_ECB: opflag |= PROT_BLOB_INFO(ECB); break; case CAAM_KEY_BLACK_CCM: opflag |= PROT_BLOB_INFO(CCM); break; default: return CAAM_BAD_PARAM; } /* Allocate the descriptor */ desc = caam_calloc_desc(BLOB_OP_DESC_ENTRIES); if (!desc) { KEY_TRACE("CAAM Context Descriptor Allocation error"); return CAAM_OUT_MEMORY; } status = caam_key_alloc(out_key); if (status) { KEY_TRACE("Key output allocation error"); goto err; } /* Define input and output buffer size */ if (out_key->is_blob) { /* * For a blob operation, the input key size is the original key * size of the black key. * The output key size is the final blob size. */ input_buffer_size = in_key->sec_size; output_buffer_size = out_key->buf.length; } else { /* * For an non-blob operation, the input key size is the original * key size of the black key. * The output key size is the key security size. */ input_buffer_size = in_key->buf.length; output_buffer_size = out_key->sec_size; } /* Create the blob encapsulation/decapsulation descriptor */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* Load the key modifier */ caam_desc_add_word(desc, LD_NOIMM(CLASS_2, REG_KEY, KEY_BLOB_MODIFIER_SIZE)); caam_desc_add_ptr(desc, virt_to_phys((void *)key_blob_modifier)); /* Define the Input data sequence */ caam_desc_add_word(desc, SEQ_IN_PTR(input_buffer_size)); caam_desc_add_ptr(desc, in_key->buf.paddr); /* Define the Output data sequence */ caam_desc_add_word(desc, SEQ_OUT_PTR(output_buffer_size)); caam_desc_add_ptr(desc, out_key->buf.paddr); caam_desc_add_word(desc, opflag); KEY_DUMPDESC(desc); caam_key_cache_op(TEE_CACHECLEAN, in_key); caam_key_cache_op(TEE_CACHECLEAN, out_key); jobctx.desc = desc; status = caam_jr_enqueue(&jobctx, NULL); if (status == CAAM_NO_ERROR) { KEY_TRACE("CAAM Blob %scapsulation Done", out_key->is_blob ? "En" : "De"); caam_key_cache_op(TEE_CACHEINVALIDATE, out_key); caam_key_dump("Blob output key", out_key); goto out; } else { KEY_TRACE("CAAM Blob Status 0x%08" PRIx32 "", jobctx.status); } err: caam_key_free(out_key); out: caam_free_desc(&desc); return status; } enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size, struct caamkey *key, size_t sec_size) { enum caam_status status = CAAM_FAILURE; struct caamkey blob = { }; assert(data && size && key); KEY_TRACE("Deserialization binary buffer"); KEY_DUMPBUF("Deserialize key buffer input", data, size); /* * If a security key size is given, use it. Otherwise, rely on * the buffer size. * In some case, like ECC keys, the bignum size is less than the * security size and it requires the key to be padded with 0's. */ if (sec_size == 0) sec_size = get_key_sec_size(data, size); blob.key_type = get_key_type(data, size); blob.sec_size = sec_size; blob.is_blob = true; if (blob.key_type == CAAM_KEY_PLAIN_TEXT) { key->sec_size = blob.sec_size; key->key_type = blob.key_type; key->is_blob = false; status = caam_key_alloc(key); if (status) { KEY_TRACE("Key allocation error"); return status; } /* Some asymmetric keys have leading zeros we must preserve */ memcpy(key->buf.data + key->buf.length - size, data, size); return CAAM_NO_ERROR; } status = caam_key_alloc(&blob); if (status) { KEY_TRACE("Key allocation error"); return status; } memcpy(blob.buf.data, data + get_key_buf_offset(data, size), get_key_buf_size(data, size)); /* Set destination key */ key->key_type = blob.key_type; key->sec_size = blob.sec_size; key->is_blob = false; /* De-blob operation */ status = caam_key_operation_blob(&blob, key); if (status) { KEY_TRACE("De-blob operation fail"); goto out; } KEY_TRACE("Deserialization binary buffer done"); caam_key_dump("Deserialization output key", key); out: caam_key_free(&blob); return status; } enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size, const struct caamkey *key) { struct caam_key_serialized key_ser = { }; struct caamkey blob = { }; enum caam_status status = CAAM_FAILURE; size_t serialized_size = 0; assert(data && size && key); caam_key_dump("Serialization input key", key); /* If the key is plain text, just copy key to buffer */ if (key->key_type == CAAM_KEY_PLAIN_TEXT) { if (size < key->buf.length) { KEY_TRACE("Buffer is too short"); return CAAM_SHORT_BUFFER; } memcpy(data, key->buf.data, key->buf.length); return CAAM_NO_ERROR; } /* The input key must not be a blob */ assert(!key->is_blob); /* Blob the given key for serialization and export */ blob.is_blob = true; blob.sec_size = key->sec_size; blob.key_type = key->key_type; /* * Check if the destination is big enough for the black blob buffer and * header. */ status = caam_key_serialized_size(&blob, &serialized_size); if (status) return status; if (size < serialized_size) { KEY_TRACE("Destination buffer is too short %zu < %zu", size, serialized_size); return CAAM_OUT_MEMORY; } /* Blob the given key */ status = caam_key_operation_blob(key, &blob); if (status) { KEY_TRACE("Blob operation fail"); return status; } /* Copy the header to destination */ key_ser.magic_number = MAGIC_NUMBER; key_ser.key_type = blob.key_type; key_ser.sec_size = blob.sec_size; memcpy(data, &key_ser, sizeof(key_ser)); /* Copy the key buffer */ memcpy(data + sizeof(key_ser), blob.buf.data, blob.buf.length); KEY_DUMPBUF("Key data", data, size); caam_key_free(&blob); return status; } enum caam_status caam_key_serialized_size(const struct caamkey *key, size_t *size) { assert(key && size); /* For a plain text key, the serialized key is identical to the key */ *size = key->buf.length; /* * For black keys, the serialized key includes the header and must be * in a blob format */ if (key->key_type != CAAM_KEY_PLAIN_TEXT) { size_t alloc = 0; const struct caamkey tmp = { .key_type = key->key_type, .sec_size = key->sec_size, .is_blob = true, }; alloc = caam_key_get_alloc_size(&tmp); if (!alloc) return CAAM_FAILURE; *size = alloc + sizeof(struct caam_key_serialized); } return CAAM_NO_ERROR; } enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey, struct caamkey *outkey, size_t size_sec) { enum caam_status status = CAAM_FAILURE; uint8_t *buf = NULL; size_t size = 0; assert(inkey && outkey); KEY_TRACE("Deserialization bignum"); /* Get bignum size */ size = crypto_bignum_num_bytes((struct bignum *)inkey); /* Allocate temporary buffer */ buf = caam_calloc(size); if (!buf) return CAAM_OUT_MEMORY; /* Convert bignum to binary */ crypto_bignum_bn2bin(inkey, buf); status = caam_key_deserialize_from_bin(buf, size, outkey, size_sec); caam_key_dump("Output key", outkey); caam_free(buf); return status; } enum caam_status caam_key_serialize_to_bn(struct bignum *outkey, const struct caamkey *inkey) { enum caam_status status = CAAM_FAILURE; TEE_Result res = TEE_ERROR_GENERIC; uint8_t *buf = NULL; size_t size = 0; assert(inkey && outkey); KEY_TRACE("Serialization bignum"); caam_key_dump("Input key", inkey); status = caam_key_serialized_size(inkey, &size); if (status) return status; buf = caam_calloc(size); if (!buf) return CAAM_OUT_MEMORY; status = caam_key_serialize_to_bin(buf, size, inkey); if (status) goto out; res = crypto_bignum_bin2bn(buf, size, outkey); if (res) status = CAAM_FAILURE; out: caam_free(buf); return status; } #define MAX_DESC_ENTRIES 22 enum caam_status caam_key_black_encapsulation(struct caamkey *key, enum caam_key_type key_type) { enum caam_status status = CAAM_FAILURE; struct caambuf input_buf = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; assert(key); assert(!key->is_blob && key->key_type == CAAM_KEY_PLAIN_TEXT); assert(key_type != CAAM_KEY_PLAIN_TEXT); KEY_TRACE("Black key encapsulation"); /* Copy input plain text key to temp buffer */ status = caam_calloc_align_buf(&input_buf, key->buf.length); if (status) return status; memcpy(input_buf.data, key->buf.data, key->buf.length); cache_operation(TEE_CACHEFLUSH, input_buf.data, input_buf.length); /* Re-allocate the output key for black format */ caam_key_free(key); key->key_type = key_type; status = caam_key_alloc(key); if (status) goto out; /* Allocate the descriptor */ desc = caam_calloc_desc(MAX_DESC_ENTRIES); if (!desc) { KEY_TRACE("Allocation descriptor error"); status = CAAM_OUT_MEMORY; goto out; } caam_key_dump("Input key", key); caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, LD_KEY(CLASS_1, PKHA_E, key->sec_size)); caam_desc_add_ptr(desc, input_buf.paddr); switch (key->key_type) { case CAAM_KEY_BLACK_ECB: caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_ECB_JKEK, key->sec_size)); break; case CAAM_KEY_BLACK_CCM: caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_CCM_JKEK, key->sec_size)); break; default: status = CAAM_FAILURE; goto out; } caam_desc_add_ptr(desc, key->buf.paddr); KEY_DUMPDESC(desc); caam_key_cache_op(TEE_CACHEFLUSH, key); jobctx.desc = desc; status = caam_jr_enqueue(&jobctx, NULL); if (status != CAAM_NO_ERROR) { KEY_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, status, jobctx.status); status = CAAM_FAILURE; goto out; } caam_key_cache_op(TEE_CACHEINVALIDATE, key); caam_key_dump("Output Key", key); out: caam_free_buf(&input_buf); caam_free_desc(&desc); return status; } enum caam_status caam_key_init(void) { size_t alloc_size = 0; const struct caamkey key = { .key_type = caam_key_default_key_gen_type(), .sec_size = 4096, /* Max RSA key size */ .is_blob = true, }; /* * Ensure bignum format maximum size is enough to store a black key * blob. The largest key is a 4096 bits RSA key pair. */ if (caam_key_serialized_size(&key, &alloc_size)) return CAAM_FAILURE; assert(alloc_size <= CFG_CORE_BIGNUM_MAX_BITS); KEY_TRACE("Max serialized key size %zu", alloc_size); KEY_TRACE("Default CAAM key generation type %s", caam_key_type_to_str[caam_key_default_key_gen_type()]); return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/caam_pwr.c000066400000000000000000000100651464416617300221350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019, 2021, 2023 NXP * * Brief CAAM Power state management. */ #include #include #include #include #include #include #include #include #include #include #include static SLIST_HEAD(, backup_data) data_list = SLIST_HEAD_INITIALIZER(backup_data); void caam_pwr_add_backup(vaddr_t baseaddr, const struct reglist *regs, size_t nbentries) { struct backup_data *newelem = NULL; struct backup_data *elem = NULL; uint32_t idx = 0; uint32_t nbregs = 0; newelem = malloc(sizeof(*newelem)); if (!newelem) panic(); /* Count the number of registers to save/restore */ for (idx = 0; idx < nbentries; idx++) nbregs += regs[idx].nbregs; newelem->baseaddr = baseaddr; newelem->nbentries = nbentries; newelem->regs = regs; newelem->val = malloc(nbregs * sizeof(*newelem->val)); if (!newelem->val) panic(); /* Add the new backup data element at the end of the list */ elem = SLIST_FIRST(&data_list); if (elem) { while (SLIST_NEXT(elem, next)) elem = SLIST_NEXT(elem, next); SLIST_INSERT_AFTER(elem, newelem, next); } else { SLIST_INSERT_HEAD(&data_list, newelem, next); } } /* Backup all registers present in the data_list */ static void do_save_regs(void) { struct backup_data *elem = NULL; const struct reglist *reg = NULL; uint32_t idx = 0; uint32_t validx = 0; uint32_t regidx = 0; SLIST_FOREACH(elem, &data_list, next) { reg = elem->regs; validx = 0; for (idx = 0; idx < elem->nbentries; idx++, reg++) { for (regidx = 0; regidx < reg->nbregs; regidx++, validx++) { elem->val[validx] = io_caam_read32(elem->baseaddr + reg->offset + (4 * regidx)); elem->val[validx] &= ~reg->mask_clr; PWR_TRACE("Save @0x%" PRIxPTR "=0x%" PRIx32, elem->baseaddr + reg->offset + 4 * regidx, elem->val[validx]); } } } } /* Restore all registers present in the data_list */ static void do_restore_regs(void) { struct backup_data *elem = NULL; const struct reglist *reg = NULL; uint32_t idx = 0; uint32_t validx = 0; uint32_t regidx = 0; SLIST_FOREACH(elem, &data_list, next) { reg = elem->regs; validx = 0; for (idx = 0; idx < elem->nbentries; idx++, reg++) { for (regidx = 0; regidx < reg->nbregs; regidx++, validx++) { PWR_TRACE("Restore @0x%" PRIxPTR "=0x%" PRIx32, elem->baseaddr + reg->offset + 4 * regidx, elem->val[validx]); io_caam_write32(elem->baseaddr + reg->offset + 4 * regidx, elem->val[validx] | reg->mask_set); } } } } /* * CAAM Power state preparation/entry * * @pm_hint Power mode type */ static TEE_Result pm_enter(uint32_t pm_hint) { enum caam_status ret = CAAM_BUSY; PWR_TRACE("CAAM power mode %" PRIu32 " entry", pm_hint); if (pm_hint == PM_HINT_CLOCK_STATE) { ret = caam_jr_halt(); } else if (pm_hint == PM_HINT_CONTEXT_STATE) { do_save_regs(); ret = caam_jr_flush(); } if (ret == CAAM_NO_ERROR) return TEE_SUCCESS; else return TEE_ERROR_GENERIC; } /* * CAAM Power state resume * * @pm_hint Power mode type */ static TEE_Result pm_resume(uint32_t pm_hint) { enum caam_status ret = CAAM_FAILURE; PWR_TRACE("CAAM power mode %" PRIu32 " resume", pm_hint); if (pm_hint == PM_HINT_CONTEXT_STATE) { caam_hal_clk_enable(true); do_restore_regs(); } caam_jr_resume(pm_hint); ret = caam_mp_resume(pm_hint); return caam_status_to_tee_result(ret); } /* * Power Management Callback function executed when system enter or resume * from a power mode * * @op Operation mode SUSPEND/RESUME * @pm_hint Power mode type * @pm_handle Driver private handle (not used) */ static TEE_Result pm_enter_resume(enum pm_op op, uint32_t pm_hint, const struct pm_callback_handle *pm_handle __unused) { if (op == PM_OP_SUSPEND) return pm_enter(pm_hint); else return pm_resume(pm_hint); } void caam_pwr_init(void) { register_pm_driver_cb(pm_enter_resume, NULL, "caam_pwr"); } optee_os-4.3.0/core/drivers/crypto/caam/caam_rng.c000066400000000000000000000352671464416617300221260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /** * Copyright 2017-2021 NXP * * Brief CAAM Random Number Generator manager. * Implementation of RNG functions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Define the RNG Data buffer size and number */ #define RNG_DATABUF_SIZE 1024 #define RNG_DATABUF_NB 2 /* * Define the number of descriptor entry to generate random data */ #define RNG_GEN_DESC_ENTRIES 5 /* * Status of the data generation */ enum rngsta { DATA_EMPTY = 0, /* Data bufer empty */ DATA_ONGOING, /* Data generation on going */ DATA_FAILURE, /* Error during data generation */ DATA_OK, /* Data generation complete with success */ }; /* * RNG Data generation */ struct rngdata { struct caam_jobctx jobctx; /* Job Ring Context */ uint32_t job_id; /* Job Id enqueued */ uint8_t *data; /* Random Data buffer */ size_t size; /* Size in bytes of the Random data buffer */ size_t rdindex; /* Current data index in the buffer */ enum rngsta status; /* Status of the data generation */ }; /* * RNG module private data */ struct rng_privdata { vaddr_t baseaddr; /* RNG base address */ bool instantiated; /* RNG instantiated */ bool pr_enabled; /* RNG prediction resistance */ struct rngdata databuf[RNG_DATABUF_NB]; /* RNG Data generation */ uint8_t dataidx; /* Current RNG Data buffer */ }; static struct rng_privdata *rng_privdata; /* Allocate and initialize module private data */ static enum caam_status do_allocate(void) { struct rngdata *rngdata = NULL; unsigned int idx = 0; /* Allocate the Module resources */ rng_privdata = caam_calloc(sizeof(*rng_privdata)); if (!rng_privdata) { RNG_TRACE("Private Data allocation error"); return CAAM_OUT_MEMORY; } rng_privdata->instantiated = false; /* Allocates the RNG Data Buffers */ for (idx = 0; idx < RNG_DATABUF_NB; idx++) { rngdata = &rng_privdata->databuf[idx]; rngdata->data = caam_calloc_align(RNG_DATABUF_SIZE); if (!rngdata->data) return CAAM_OUT_MEMORY; rngdata->size = RNG_DATABUF_SIZE; rngdata->jobctx.desc = caam_calloc_desc(RNG_GEN_DESC_ENTRIES); if (!rngdata->jobctx.desc) return CAAM_OUT_MEMORY; } return CAAM_NO_ERROR; } /* Free module private data */ static void do_free(void) { struct rngdata *rng = NULL; unsigned int idx = 0; if (rng_privdata) { for (idx = 0; idx < RNG_DATABUF_NB; idx++) { rng = &rng_privdata->databuf[idx]; /* Check if there is a Job ongoing to cancel it */ if (atomic_load_u32(&rng->status) == DATA_ONGOING) caam_jr_cancel(rng->job_id); caam_free_desc(&rng->jobctx.desc); caam_free(rng->data); rng->data = NULL; } caam_free(rng_privdata); rng_privdata = NULL; } } #ifdef CFG_NXP_CAAM_RNG_DRV /* * RNG data generation job ring callback completion * * @jobctx RNG data JR Job Context */ static void rng_data_done(struct caam_jobctx *jobctx) { struct rngdata *rng = jobctx->context; RNG_TRACE("RNG Data id 0x%08" PRIx32 " done with status 0x%" PRIx32, rng->job_id, jobctx->status); if (JRSTA_SRC_GET(jobctx->status) == JRSTA_SRC(NONE)) { atomic_store_u32(&rng->status, DATA_OK); /* Invalidate the data buffer to ensure software gets it */ cache_operation(TEE_CACHEINVALIDATE, rng->data, rng->size); } else { RNG_TRACE("RNG Data completion in error 0x%" PRIx32, jobctx->status); atomic_store_u32(&rng->status, DATA_FAILURE); } rng->job_id = 0; rng->rdindex = 0; } /* * Prepares the data generation descriptors * * @rng Reference to the RNG Data object */ static enum caam_status prepare_gen_desc(struct rngdata *rng) { paddr_t paddr = 0; uint32_t *desc = NULL; uint32_t op = RNG_GEN_DATA; if (rng_privdata->pr_enabled) op |= ALGO_RNG_PR; /* Convert the buffer virtual address to physical address */ paddr = virt_to_phys(rng->data); if (!paddr) return CAAM_FAILURE; desc = rng->jobctx.desc; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, op); caam_desc_add_word(desc, FIFO_ST(CLASS_NO, RNG_TO_MEM, rng->size)); caam_desc_add_ptr(desc, paddr); RNG_DUMPDESC(desc); /* Prepare the job context */ rng->jobctx.context = rng; rng->jobctx.callback = rng_data_done; return CAAM_NO_ERROR; } /* * Launches a RNG Data generation * * @rng RNG Data context */ static enum caam_status do_rng_start(struct rngdata *rng) { enum caam_status ret = CAAM_FAILURE; /* Ensure that data buffer is visible from the HW */ cache_operation(TEE_CACHEFLUSH, rng->data, rng->size); rng->job_id = 0; atomic_store_u32(&rng->status, DATA_EMPTY); ret = caam_jr_enqueue(&rng->jobctx, &rng->job_id); if (ret == CAAM_PENDING) { atomic_store_u32(&rng->status, DATA_ONGOING); ret = CAAM_NO_ERROR; } else { RNG_TRACE("RNG Job Ring Error 0x%08x", ret); atomic_store_u32(&rng->status, DATA_FAILURE); ret = CAAM_FAILURE; } return ret; } /* Checks if there are random data available */ static enum caam_status do_check_data(void) { enum caam_status ret = CAAM_FAILURE; struct rngdata *rng = NULL; uint32_t wait_jobs = 0; unsigned int idx = 0; unsigned int loop = 4; /* Check if there is a RNG Job to be run */ for (idx = 0; idx < RNG_DATABUF_NB; idx++) { rng = &rng_privdata->databuf[idx]; if (atomic_load_u32(&rng->status) == DATA_EMPTY) { RNG_TRACE("Start RNG #%" PRIu32 " data generation", idx); ret = do_rng_start(rng); if (ret != CAAM_NO_ERROR) return CAAM_FAILURE; } } /* Check if the current data buffer contains data */ rng = &rng_privdata->databuf[rng_privdata->dataidx]; switch (atomic_load_u32(&rng->status)) { case DATA_OK: return CAAM_NO_ERROR; case DATA_FAILURE: return CAAM_FAILURE; default: /* Wait until one of the data buffer completes */ do { wait_jobs = 0; for (idx = 0; idx < RNG_DATABUF_NB; idx++) { rng = &rng_privdata->databuf[idx]; wait_jobs |= rng->job_id; if (atomic_load_u32(&rng->status) == DATA_OK) { RNG_TRACE("RNG Data buffer #%" PRIu32 " ready", idx); rng_privdata->dataidx = idx; return CAAM_NO_ERROR; } } if (!wait_jobs) { RNG_TRACE("There are no Data Buffers ongoing"); return CAAM_FAILURE; } /* Need to wait until one of the jobs completes */ (void)caam_jr_dequeue(wait_jobs, 100); } while (loop--); break; } return CAAM_FAILURE; } /* * Return the requested random data * * @buf [out] data buffer * @len number of bytes to returns */ static TEE_Result do_rng_read(uint8_t *buf, size_t len) { struct rngdata *rng = NULL; size_t remlen = len; uint8_t *rngbuf = buf; if (!rng_privdata) { RNG_TRACE("RNG Driver not initialized"); return TEE_ERROR_BAD_STATE; } if (!rng_privdata->instantiated) { RNG_TRACE("RNG Driver not initialized"); return TEE_ERROR_BAD_STATE; } do { if (do_check_data() != CAAM_NO_ERROR) { RNG_TRACE("No Data available or Error"); return TEE_ERROR_BAD_STATE; } rng = &rng_privdata->databuf[rng_privdata->dataidx]; RNG_TRACE("Context #%" PRIu8 " contains %zu data asked %zu (%zu)", rng_privdata->dataidx, rng->size - rng->rdindex, remlen, len); /* Check that current context data are available */ if ((rng->size - rng->rdindex) <= remlen) { /* * There is no or just enough data available, * copy all data */ RNG_TRACE("Copy all available data"); memcpy(rngbuf, &rng->data[rng->rdindex], rng->size - rng->rdindex); remlen -= rng->size - rng->rdindex; rngbuf += rng->size - rng->rdindex; /* Set the RNG data status as empty */ atomic_store_u32(&rng->status, DATA_EMPTY); } else { /* There is enough data in the current context */ RNG_TRACE("Copy %zu data", remlen); memcpy(rngbuf, &rng->data[rng->rdindex], remlen); rng->rdindex += remlen; remlen = 0; } } while (remlen); return TEE_SUCCESS; } /* Initialize the RNG module to generate data */ static enum caam_status caam_rng_init_data(void) { enum caam_status retstatus = CAAM_FAILURE; struct rngdata *rng = NULL; unsigned int idx = 0; for (idx = 0; idx < RNG_DATABUF_NB; idx++) { rng = &rng_privdata->databuf[idx]; retstatus = prepare_gen_desc(rng); if (retstatus != CAAM_NO_ERROR) break; } return retstatus; } #endif /* CFG_NXP_CAAM_RNG_DRV */ /* * Prepares the instantiation descriptor * * @nb_sh Number of the State Handle * @sh_status State Handles status * @desc Reference to the descriptor * @desc [out] Descriptor filled */ static void prepare_inst_desc(uint32_t nb_sh, uint32_t sh_status, uint32_t *desc) { bool key_loaded = false; unsigned int sh_idx = 0; unsigned int nb_max_sh = nb_sh; /* Read the SH and secure key status */ key_loaded = caam_hal_rng_key_loaded(rng_privdata->baseaddr); RNG_TRACE("RNG SH Status 0x%08" PRIx32 " - Key Status %" PRId8, sh_status, key_loaded); while (sh_status & BIT(sh_idx)) sh_idx++; RNG_TRACE("Instantiation start at SH%" PRIu32 " (%" PRIu32 ")", sh_idx, nb_max_sh); /* Don't set the descriptor header now */ caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* First State Handle to instantiate */ caam_desc_add_word(desc, RNG_SH_INST(sh_idx)); /* Next State Handles */ for (sh_idx++; sh_idx < nb_max_sh; sh_idx++) { if (!(sh_status & BIT(sh_idx))) { /* * If there is more SH to instantiate, add a wait loop * followed by a reset of the done status to execute * next command */ caam_desc_add_word(desc, JUMP_C1_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 1)); caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CLEAR_WRITTEN, sizeof(uint32_t))); caam_desc_add_word(desc, 0x1); caam_desc_add_word(desc, RNG_SH_INST(sh_idx)); } } /* Load the Key if needed */ if (!key_loaded) { /* * Add a wait loop while previous operation not completed, * followed by a register clear before executing next command */ caam_desc_add_word(desc, JUMP_C1_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 1)); caam_desc_add_word(desc, LD_NOCLASS_IMM(REG_CLEAR_WRITTEN, sizeof(uint32_t))); caam_desc_add_word(desc, 0x1); caam_desc_add_word(desc, RNG_GEN_SECKEYS); } RNG_DUMPDESC(desc); } enum caam_status caam_rng_instantiation(void) { enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = {}; uint32_t *desc = NULL; uint32_t sh_status = 0; uint32_t nb_sh = 0; uint32_t sh_mask = 0; uint32_t inc_delay = 0; RNG_TRACE("RNG Instantation"); /* Check if RNG is already instantiated */ retstatus = caam_hal_rng_instantiated(rng_privdata->baseaddr); /* RNG is already instantiated or an error occurred */ if (retstatus != CAAM_NOT_INIT) goto end_inst; /* * RNG needs to be instantiated. Allocate and prepare the * Job Descriptor */ /* Calculate the State Handles bit mask */ nb_sh = caam_hal_rng_get_nb_sh(rng_privdata->baseaddr); sh_mask = GENMASK_32(nb_sh - 1, 0); /* * The maximum size of the descriptor is: * |----------------------| * | Header | = 1 * |----------------------| * | First instantation | = 1 * |----------------------|------------------------- * | wait complete | = 1 * |----------------------| * | Clear done status | Repeat (nb_sh - 1) * | | = 2 * |----------------------| * | next SH instantation | = 1 * |----------------------|------------------------- * | wait complete | = 1 * |----------------------| * | Clear done status | = 2 * | | * |----------------------| * | Generate Secure Keys | = 1 * |----------------------| * | Pad with a 0 | = 1 */ desc = caam_calloc_desc(2 + (nb_sh - 1) * 4 + 4 + 1); if (!desc) { RNG_TRACE("Descriptor Allocation error"); retstatus = CAAM_OUT_MEMORY; goto end_inst; } jobctx.desc = desc; do { /* Check if all State Handles are instantiated */ sh_status = caam_hal_rng_get_sh_status(rng_privdata->baseaddr); if ((sh_status & sh_mask) == sh_mask) { RNG_TRACE("RNG All SH are instantiated (0x%08" PRIx32 ")", sh_status); retstatus = CAAM_NO_ERROR; goto end_inst; } if (sh_status == 0) { retstatus = caam_hal_rng_kick(rng_privdata->baseaddr, inc_delay); RNG_TRACE("RNG Kick (inc=%" PRIu32 ") ret 0x%08x", inc_delay, retstatus); if (retstatus != CAAM_NO_ERROR) { retstatus = CAAM_FAILURE; goto end_inst; } inc_delay += 200; } prepare_inst_desc(nb_sh, sh_status, desc); retstatus = caam_jr_enqueue(&jobctx, NULL); RNG_TRACE("RNG Job returned 0x%08x", retstatus); if (retstatus != CAAM_NO_ERROR && retstatus != CAAM_JOB_STATUS) goto end_inst; if (retstatus == CAAM_JOB_STATUS) { RNG_TRACE("RNG Job status 0x%08" PRIx32, jobctx.status); if ((JRSTA_SRC_GET(jobctx.status) != JRSTA_SRC(CCB)) || (JRSTA_CCB_GET_ERR(jobctx.status) != (JRSTA_CCB_CHAID_RNG | JRSTA_CCB_ERRID_HW))) retstatus = CAAM_FAILURE; else retstatus = CAAM_NO_ERROR; } } while (retstatus == CAAM_NO_ERROR); end_inst: if (retstatus == CAAM_NO_ERROR) { rng_privdata->instantiated = true; rng_privdata->pr_enabled = caam_hal_rng_pr_enabled(rng_privdata->baseaddr); RNG_TRACE("RNG prediction resistance is %sabled", rng_privdata->pr_enabled ? "en" : "dis"); } caam_free_desc(&desc); RNG_TRACE("RNG Instantiation return 0x%08x", retstatus); return retstatus; } enum caam_status caam_rng_init(vaddr_t ctrl_addr) { enum caam_status retstatus = CAAM_FAILURE; RNG_TRACE("Initialization"); retstatus = do_allocate(); if (retstatus == CAAM_NO_ERROR) { rng_privdata->baseaddr = ctrl_addr; retstatus = caam_rng_instantiation(); } #ifdef CFG_NXP_CAAM_RNG_DRV if (retstatus == CAAM_NO_ERROR) retstatus = caam_rng_init_data(); #endif if (retstatus != CAAM_NO_ERROR) do_free(); return retstatus; } #ifdef CFG_NXP_CAAM_RNG_DRV #ifdef CFG_WITH_SOFTWARE_PRNG void plat_rng_init(void) { TEE_Result res = TEE_SUCCESS; uint8_t buf[64] = { }; res = do_rng_read(buf, sizeof(buf)); if (res) { EMSG("Failed to read RNG: %#" PRIx32, res); panic(); } res = crypto_rng_init(buf, sizeof(buf)); if (res) { EMSG("Failed to initialize RNG: %#" PRIx32, res); panic(); } RNG_TRACE("PRNG seeded from CAAM"); } #else /* !CFG_WITH_SOFTWARE_PRNG */ TEE_Result hw_get_random_bytes(void *buf, size_t blen) { if (!buf) return TEE_ERROR_BAD_PARAMETERS; return do_rng_read(buf, blen); } void plat_rng_init(void) { } #endif /* CFG_WITH_SOFTWARE_PRNG */ #endif /* CFG_NXP_CAAM_RNG_DRV */ optee_os-4.3.0/core/drivers/crypto/caam/caam_sm.c000066400000000000000000000122371464416617300217470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019, 2023 NXP */ #include #include #include #include #include #include #include /* * Secure memory module private data */ static struct sm_privdata { vaddr_t baseaddr; /* Secure memory base address */ vaddr_t ctrl_addr; /* CAAM base address */ vaddr_t jr_addr; /* Job Ring base address */ paddr_t jr_offset; /* Job Ring offset */ } sm_privdata; enum caam_status caam_sm_alloc(const struct caam_sm_page_desc *page_desc, struct caam_sm_page_addr *page_addr) { enum caam_status ret = CAAM_FAILURE; if (!page_desc || !page_addr) return TEE_ERROR_BAD_PARAMETERS; ret = caam_hal_sm_check_page_partition(sm_privdata.jr_addr, page_desc); if (ret != CAAM_NO_ERROR) { SM_TRACE("Pages %u to %u or partition %u are out of bounds", page_desc->page, page_desc->page + page_desc->page_count - 1, page_desc->partition); return ret; } /* Check if partition is already allocated */ if (!caam_hal_sm_prtn_is_free(sm_privdata.jr_addr, page_desc->partition)) { SM_TRACE("Partition %u not available", page_desc->partition); return CAAM_BUSY; } /* Open secure memory partition to all groups */ caam_hal_sm_open_access_perm(sm_privdata.jr_addr, page_desc->partition); caam_hal_sm_set_access_all_group(sm_privdata.jr_addr, page_desc->partition); ret = caam_hal_sm_allocate_page(sm_privdata.jr_addr, page_desc); if (ret != CAAM_NO_ERROR) { SM_TRACE("Error allocation Pages %u to %u into partition %u", page_desc->page, page_desc->page + page_desc->page_count - 1, page_desc->partition); /* Free all potientiel pages allocated before failure */ return caam_hal_sm_deallocate_pages(sm_privdata.jr_addr, page_desc); } page_addr->paddr = caam_hal_ctrl_get_smvaddr(sm_privdata.ctrl_addr, sm_privdata.jr_offset) + caam_hal_sm_get_pages_size(sm_privdata.jr_addr, page_desc->page); page_addr->vaddr = sm_privdata.baseaddr + caam_hal_sm_get_pages_size(sm_privdata.jr_addr, page_desc->page); SM_TRACE("Partition %u Pages %u to %u allocated @0x%" PRIxVA " (phys 0x@%" PRIxPA, page_desc->partition, page_desc->page, page_desc->page + page_desc->page_count - 1, page_addr->vaddr, page_addr->paddr); return CAAM_NO_ERROR; } enum caam_status caam_sm_free(const struct caam_sm_page_desc *page_desc) { enum caam_status ret = CAAM_FAILURE; SM_TRACE("Free Secure Memory pages %u to %u from partition %u", page_desc->page, page_desc->page + page_desc->page_count, page_desc->partition); /* * De-allocate partition. It automatically releases partition's pages * to the pool of available pages. if the partition if marked as CSP, * pages will be zeroized. If the partition is marked as PSP, * partition and pages will not be de-allocated and a PSP will be * returned. */ if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr, page_desc->partition)) { SM_TRACE("Partition %u not owned by used JR", page_desc->partition); return TEE_ERROR_ACCESS_DENIED; } ret = caam_hal_sm_deallocate_pages(sm_privdata.jr_addr, page_desc); if (ret) { SM_TRACE("De-alloc pages %u to %u error 0x%" PRIx32, page_desc->page, page_desc->page + page_desc->page_count, ret); return ret; } ret = caam_hal_sm_deallocate_partition(sm_privdata.jr_addr, page_desc->partition); if (ret) { SM_TRACE("De-alloc partition %u error 0x%" PRIx32, page_desc->partition, ret); return ret; } return CAAM_NO_ERROR; } enum caam_status caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc, unsigned int grp1_perm, unsigned int grp2_perm) { uint32_t grp1 = UINT32_MAX; uint32_t grp2 = UINT32_MAX; if (!page_desc) return CAAM_BAD_PARAM; /* Check if the partition is already owned */ if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr, page_desc->partition)) { SM_TRACE("Partition %d not owned by current JR", page_desc->partition); return CAAM_FAILURE; } /* * Set ourself to access Secure Memory group 1 and/or group 2 * function if @grp1_perm and/or @grp2_perm not equal 0. * * The Access Group is related to the Job Ring owner setting without * the Secure Bit setting already managed by the Job Ring. */ if (grp1_perm) grp1 = JROWN_ARM_NS; if (grp2_perm) grp2 = JROWN_ARM_NS; caam_hal_sm_set_access_group(sm_privdata.jr_addr, page_desc->partition, grp1, grp2); caam_hal_sm_set_access_perm(sm_privdata.jr_addr, page_desc->partition, grp1_perm, grp2_perm); return CAAM_NO_ERROR; } enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg) { if (!jrcfg) return CAAM_FAILURE; sm_privdata.ctrl_addr = jrcfg->base; sm_privdata.jr_addr = jrcfg->base + jrcfg->offset; sm_privdata.jr_offset = jrcfg->offset; sm_privdata.baseaddr = caam_hal_sm_get_base(); if (!sm_privdata.baseaddr) return CAAM_FAILURE; SM_TRACE("Secure Memory Base address = 0x%" PRIxVA, sm_privdata.baseaddr); SM_TRACE("CAAM controller address = 0x%" PRIxVA, sm_privdata.ctrl_addr); SM_TRACE("CAAM Job Ring address = 0x%" PRIxVA, sm_privdata.jr_addr); return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/cipher/000077500000000000000000000000001464416617300214505ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/cipher/caam_cipher.c000066400000000000000000000535331464416617300240600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Implementation of Cipher functions */ #include #include #include #include #include #include #include #include #include #include #include #include "local.h" /* Local Function declaration */ static TEE_Result do_update_streaming(struct drvcrypt_cipher_update *dupdate); static TEE_Result do_update_cipher(struct drvcrypt_cipher_update *dupdate); /* * Constants definition of the AES algorithm */ static const struct cipheralg aes_alg[] = { [TEE_CHAIN_MODE_ECB_NOPAD] = { .type = OP_ALGO(AES) | ALGO_AAI(AES_ECB), .size_block = TEE_AES_BLOCK_SIZE, .size_ctx = 0, .ctx_offset = 0, .require_key = NEED_KEY1, .def_key = { .min = 16, .max = 32, .mod = 8 }, .update = do_update_cipher, }, [TEE_CHAIN_MODE_CBC_NOPAD] = { .type = OP_ALGO(AES) | ALGO_AAI(AES_CBC), .size_block = TEE_AES_BLOCK_SIZE, .size_ctx = 2 * sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 16, .max = 32, .mod = 8 }, .update = do_update_cipher, }, [TEE_CHAIN_MODE_CTR] = { .type = OP_ALGO(AES) | ALGO_AAI(AES_CTR_MOD128), .size_block = TEE_AES_BLOCK_SIZE, .size_ctx = 2 * sizeof(uint64_t), .ctx_offset = 16, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 16, .max = 32, .mod = 8 }, .update = do_update_streaming, }, [TEE_CHAIN_MODE_CTS] = { .type = 0, }, [TEE_CHAIN_MODE_XTS] = { .type = OP_ALGO(AES) | ALGO_AAI(AES_ECB), .size_block = TEE_AES_BLOCK_SIZE, .size_ctx = 0, .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_KEY2 | NEED_TWEAK, .def_key = { .min = 16, .max = 32, .mod = 8 }, .update = caam_cipher_update_xts, }, }; /* * Constants definition of the DES algorithm */ static const struct cipheralg des_alg[] = { [TEE_CHAIN_MODE_ECB_NOPAD] = { .type = OP_ALGO(DES) | ALGO_AAI(DES_ECB), .size_block = TEE_DES_BLOCK_SIZE, .size_ctx = 0, .ctx_offset = 0, .require_key = NEED_KEY1, .def_key = { .min = 8, .max = 8, .mod = 8 }, .update = do_update_cipher, }, [TEE_CHAIN_MODE_CBC_NOPAD] = { .type = OP_ALGO(DES) | ALGO_AAI(DES_CBC), .size_block = TEE_DES_BLOCK_SIZE, .size_ctx = sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 8, .max = 8, .mod = 8 }, .update = do_update_cipher, }, }; /* * Constants definition of the DES3 algorithm */ static const struct cipheralg des3_alg[] = { [TEE_CHAIN_MODE_ECB_NOPAD] = { .type = OP_ALGO(3DES) | ALGO_AAI(DES_ECB), .size_block = TEE_DES_BLOCK_SIZE, .size_ctx = 0, .ctx_offset = 0, .require_key = NEED_KEY1, .def_key = { .min = 16, .max = 24, .mod = 8 }, .update = do_update_cipher, }, [TEE_CHAIN_MODE_CBC_NOPAD] = { /* Triple-DES CBC No Pad */ .type = OP_ALGO(3DES) | ALGO_AAI(DES_CBC), .size_block = TEE_DES_BLOCK_SIZE, .size_ctx = sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 16, .max = 24, .mod = 8 }, .update = do_update_cipher, }, }; /* * Allocate context data and copy input data into * * @dst [out] Destination data to allocate and fill * @src Source of data to copy */ static enum caam_status copy_ctx_data(struct caambuf *dst, struct drvcrypt_buf *src) { enum caam_status ret = CAAM_OUT_MEMORY; if (!dst->data) { /* Allocate the destination buffer */ ret = caam_alloc_align_buf(dst, src->length); if (ret != CAAM_NO_ERROR) return CAAM_OUT_MEMORY; } /* Do the copy */ memcpy(dst->data, src->data, dst->length); /* Push data to physical memory */ cache_operation(TEE_CACHEFLUSH, dst->data, dst->length); return CAAM_NO_ERROR; } /* * Verify the input key size with the requirements * * @def Key requirements * @size Key size to verify */ static enum caam_status do_check_keysize(const struct caamdefkey *def, size_t size) { if (size >= def->min && size <= def->max && !(size % def->mod)) return CAAM_NO_ERROR; return CAAM_BAD_PARAM; } enum caam_status caam_cipher_block(struct cipherdata *ctx, bool savectx, uint8_t keyid, bool encrypt, struct caamdmaobj *src, struct caamdmaobj *dst) { enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; uint32_t *desc = ctx->descriptor; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); if (keyid == NEED_KEY1) { /* Build the descriptor */ caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG, ctx->key1.length)); caam_desc_add_ptr(desc, ctx->key1.paddr); } else if (keyid == NEED_KEY2) { /* Build the descriptor */ caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG, ctx->key2.length)); caam_desc_add_ptr(desc, ctx->key2.paddr); } /* If there is a context register load it */ if (ctx->ctx.length && ctx->alg->size_ctx) { caam_desc_add_word(desc, LD_NOIMM_OFF(CLASS_1, REG_CTX, ctx->ctx.length, ctx->alg->ctx_offset)); caam_desc_add_ptr(desc, ctx->ctx.paddr); /* Operation with the direction */ caam_desc_add_word(desc, CIPHER_INIT(ctx->alg->type, encrypt)); } else { /* Operation with the direction */ caam_desc_add_word(desc, CIPHER_INITFINAL(ctx->alg->type, encrypt)); } /* Load the source data if any */ if (src) { caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1); caam_dmaobj_cache_push(src); } /* Store the output data if any */ if (dst) { caam_desc_fifo_store(desc, dst, MSG_DATA); caam_dmaobj_cache_push(dst); } if (ctx->ctx.length && ctx->alg->size_ctx) { if (savectx) { /* Store the context */ caam_desc_add_word(desc, ST_NOIMM_OFF(CLASS_1, REG_CTX, ctx->ctx.length, ctx->alg->ctx_offset)); caam_desc_add_ptr(desc, ctx->ctx.paddr); } /* Ensure Context register data are not in cache */ cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, ctx->ctx.length); } CIPHER_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus != CAAM_NO_ERROR) { CIPHER_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, retstatus, jobctx.status); retstatus = CAAM_FAILURE; } return retstatus; } /* * Checks if the algorithm @algo is supported and returns the * local algorithm entry in the corresponding cipher array */ static const struct cipheralg *get_cipheralgo(uint32_t algo) { unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo); unsigned int algo_md = TEE_ALG_GET_CHAIN_MODE(algo); const struct cipheralg *ca = NULL; CIPHER_TRACE("Algo id:%" PRId32 " md:%" PRId32, algo_id, algo_md); switch (algo_id) { case TEE_MAIN_ALGO_AES: if (algo_md < ARRAY_SIZE(aes_alg)) ca = &aes_alg[algo_md]; break; case TEE_MAIN_ALGO_DES: if (algo_md < ARRAY_SIZE(des_alg)) ca = &des_alg[algo_md]; break; case TEE_MAIN_ALGO_DES3: if (algo_md < ARRAY_SIZE(des3_alg)) ca = &des3_alg[algo_md]; break; default: break; } if (ca && ca->type) return ca; return NULL; } /* * Allocate the SW cipher data context * * @ctx [out] Caller context variable * @algo Algorithm ID of the context */ static TEE_Result do_allocate(void **ctx, uint32_t algo) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct cipherdata *cipherdata = NULL; const struct cipheralg *alg = NULL; CIPHER_TRACE("Allocate Algo 0x%" PRIX32 " Context (%p)", algo, ctx); alg = get_cipheralgo(algo); if (!alg) { CIPHER_TRACE("Algorithm not supported"); return TEE_ERROR_NOT_IMPLEMENTED; } cipherdata = caam_calloc(sizeof(*cipherdata)); if (!cipherdata) { CIPHER_TRACE("Allocation Cipher data error"); return TEE_ERROR_OUT_OF_MEMORY; } /* Allocate the descriptor */ cipherdata->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES); if (!cipherdata->descriptor) { CIPHER_TRACE("Allocation descriptor error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Setup the Algorithm pointer */ cipherdata->alg = alg; /* Initialize the block buffer */ cipherdata->blockbuf.max = cipherdata->alg->size_block; *ctx = cipherdata; return TEE_SUCCESS; out: caam_free_desc(&cipherdata->descriptor); caam_free(cipherdata); return ret; } /* * Free the internal cipher data context * * @ctx Caller context variable or NULL */ static void do_free_intern(struct cipherdata *ctx) { CIPHER_TRACE("Free Context (%p)", ctx); if (ctx) { /* Free the descriptor */ caam_free_desc(&ctx->descriptor); /* Free the Key 1 */ caam_free_buf(&ctx->key1); /* Free the Key 2 */ caam_free_buf(&ctx->key2); /* Free the Tweak */ caam_free_buf(&ctx->tweak); /* Free the Context Register */ caam_free_buf(&ctx->ctx); /* Free Temporary buffer */ caam_free_buf(&ctx->blockbuf.buf); } } void caam_cipher_free(void *ctx) { CIPHER_TRACE("Free Context (%p)", ctx); if (ctx) { do_free_intern(ctx); caam_free(ctx); } } void caam_cipher_copy_state(void *dst_ctx, void *src_ctx) { struct cipherdata *dst = dst_ctx; struct cipherdata *src = src_ctx; CIPHER_TRACE("Copy State context (%p) to (%p)", src_ctx, dst_ctx); dst->alg = src->alg; dst->encrypt = src->encrypt; if (src->blockbuf.filled) { struct caambuf srcdata = { .data = src->blockbuf.buf.data, .length = src->blockbuf.filled }; caam_cpy_block_src(&dst->blockbuf, &srcdata, 0); } if (src->key1.length) { struct drvcrypt_buf key1 = { .data = src->key1.data, .length = src->key1.length }; copy_ctx_data(&dst->key1, &key1); } if (src->key2.length) { struct drvcrypt_buf key2 = { .data = src->key2.data, .length = src->key2.length }; copy_ctx_data(&dst->key2, &key2); } if (src->ctx.length) { struct drvcrypt_buf ctx = { .data = src->ctx.data, .length = src->ctx.length }; cache_operation(TEE_CACHEINVALIDATE, ctx.data, ctx.length); copy_ctx_data(&dst->ctx, &ctx); } if (src->tweak.length) { struct drvcrypt_buf tweak = { .data = src->tweak.data, .length = src->tweak.length }; copy_ctx_data(&dst->tweak, &tweak); } } TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; enum caam_status retstatus = CAAM_FAILURE; struct cipherdata *cipherdata = dinit->ctx; const struct cipheralg *alg = NULL; CIPHER_TRACE("Action %s", dinit->encrypt ? "Encrypt" : "Decrypt"); if (!cipherdata) return ret; alg = cipherdata->alg; /* Check if all required keys are defined */ if (alg->require_key & NEED_KEY1) { if (!dinit->key1.data || !dinit->key1.length) goto out; retstatus = do_check_keysize(&alg->def_key, dinit->key1.length); if (retstatus != CAAM_NO_ERROR) { CIPHER_TRACE("Bad Key 1 size"); goto out; } /* Copy the key 1 */ retstatus = copy_ctx_data(&cipherdata->key1, &dinit->key1); CIPHER_TRACE("Copy Key 1 returned 0x%" PRIx32, retstatus); if (retstatus != CAAM_NO_ERROR) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } } if (alg->require_key & NEED_KEY2) { if (!dinit->key2.data || !dinit->key2.length) goto out; retstatus = do_check_keysize(&alg->def_key, dinit->key2.length); if (retstatus != CAAM_NO_ERROR) { CIPHER_TRACE("Bad Key 2 size"); goto out; } /* Copy the key 2 */ retstatus = copy_ctx_data(&cipherdata->key2, &dinit->key2); CIPHER_TRACE("Copy Key 2 returned 0x%" PRIx32, retstatus); if (retstatus != CAAM_NO_ERROR) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } } if (alg->require_key & NEED_IV) { if (!dinit->iv.data || !dinit->iv.length) goto out; if (dinit->iv.length != alg->size_ctx) { CIPHER_TRACE("Bad IV size %zu (expected %" PRId32 ")", dinit->iv.length, alg->size_ctx); goto out; } CIPHER_TRACE("Allocate CAAM Context Register (%" PRId32 " bytes)", alg->size_ctx); /* Copy the IV into the context register */ retstatus = copy_ctx_data(&cipherdata->ctx, &dinit->iv); CIPHER_TRACE("Copy IV returned 0x%" PRIx32, retstatus); if (retstatus != CAAM_NO_ERROR) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } } if (alg->require_key & NEED_TWEAK) { /* This is accepted to start with a NULL Tweak */ if (dinit->iv.length) { if (dinit->iv.length != alg->size_block) { CIPHER_TRACE("Bad tweak 2 size"); goto out; } /* Copy the tweak */ retstatus = copy_ctx_data(&cipherdata->tweak, &dinit->iv); CIPHER_TRACE("Copy Tweak returned 0x%" PRIx32, retstatus); if (retstatus != CAAM_NO_ERROR) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } } else { /* Create tweak 0's */ if (!cipherdata->tweak.data) { /* * Allocate the destination buffer and * fill it with 0's */ ret = caam_calloc_align_buf(&cipherdata->tweak, alg->size_block); if (ret != CAAM_NO_ERROR) goto out; } else { /* Fill it with 0's */ memset(cipherdata->tweak.data, 0, cipherdata->tweak.length); } /* Push data to physical memory */ cache_operation(TEE_CACHEFLUSH, cipherdata->tweak.data, cipherdata->tweak.length); } } /* Save the operation direction */ cipherdata->encrypt = dinit->encrypt; cipherdata->blockbuf.filled = 0; ret = TEE_SUCCESS; out: /* Free the internal context in case of error */ if (ret != TEE_SUCCESS) do_free_intern(cipherdata); return ret; } /* * Update of the cipher operation in streaming mode, meaning * doing partial intermediate block. * If there is a context, the context is saved only when a * full block is done. * The partial block (if not the last block) is encrypted or * decrypted to return the result and it's saved to be concatened * to next data to rebuild a full block. * * @dupdate Data update object */ static TEE_Result do_update_streaming(struct drvcrypt_cipher_update *dupdate) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct cipherdata *ctx = dupdate->ctx; struct caamdmaobj src = { }; struct caamdmaobj dst = { }; struct caamblock trash_bck = { }; size_t fullsize = 0; size_t size_topost = 0; size_t size_todo = 0; size_t size_inmade = 0; size_t size_done = 0; size_t offset = 0; CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, ctx->encrypt ? "Encrypt" : "Decrypt"); /* Calculate the total data to be handled */ fullsize = ctx->blockbuf.filled + dupdate->src.length; CIPHER_TRACE("Fullsize %zu", fullsize); if (fullsize < ctx->alg->size_block) { size_topost = dupdate->src.length; goto end_streaming_post; } else { size_topost = fullsize % ctx->alg->size_block; /* Total size that is a cipher block multiple */ size_todo = fullsize - size_topost; size_inmade = size_todo - ctx->blockbuf.filled; } CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", fullsize, size_topost, size_todo); if (size_todo) { ret = caam_dmaobj_init_input(&src, dupdate->src.data, dupdate->src.length); if (ret) goto end_streaming; ret = caam_dmaobj_init_output(&dst, dupdate->dst.data, dupdate->dst.length, dupdate->dst.length); if (ret) goto end_streaming; ret = caam_dmaobj_prepare(&src, &dst, ctx->alg->size_block); if (ret) goto end_streaming; } /* * Check first if there is some data saved to complete the * buffer. */ if (ctx->blockbuf.filled) { ret = caam_dmaobj_add_first_block(&src, &ctx->blockbuf); if (ret) goto end_streaming; ret = caam_dmaobj_add_first_block(&dst, &ctx->blockbuf); if (ret) goto end_streaming; ctx->blockbuf.filled = 0; } size_done = size_todo; dupdate->dst.length = 0; for (offset = 0; size_todo; offset += size_done, size_todo -= size_done) { CIPHER_TRACE("Do input %zu bytes (%zu), offset %zu", size_done, size_todo, offset); size_done = size_todo; ret = caam_dmaobj_sgtbuf_inout_build(&src, &dst, &size_done, offset, ctx->alg->size_block); if (ret) goto end_streaming; retstatus = caam_cipher_block(ctx, true, NEED_KEY1, ctx->encrypt, &src, &dst); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto end_streaming; } dupdate->dst.length += caam_dmaobj_copy_to_orig(&dst); } CIPHER_DUMPBUF("Source", dupdate->src.data, dupdate->src.length); CIPHER_DUMPBUF("Result", dupdate->dst.data, dupdate->dst.length); end_streaming_post: if (size_topost) { /* * Save the input data in the block buffer for next operation * and prepare the source DMA Object with the overall saved * data to generate destination bytes. */ struct caambuf cpysrc = { .data = dupdate->src.data, .length = dupdate->src.length }; caam_dmaobj_free(&src); caam_dmaobj_free(&dst); CIPHER_TRACE("Save input data %zu bytes (done %zu) - off %zu", size_topost, size_inmade, offset); size_todo = size_topost + ctx->blockbuf.filled; /* * Prepare the destination DMA Object: * - Use given destination parameter bytes to return * - If the previous operation saved data, use a trash * buffer to do the operation but not use unneeded data. */ ret = caam_dmaobj_init_output(&dst, dupdate->dst.data + size_inmade, size_topost, size_topost); if (ret) goto end_streaming; ret = caam_dmaobj_prepare(NULL, &dst, ctx->alg->size_block); if (ret) goto end_streaming; if (ctx->blockbuf.filled) { /* * Because there are some bytes to trash, use * a block buffer that will be added to the * destination SGT/Buffer structure to do the * cipher operation. */ ret = caam_alloc_align_buf(&trash_bck.buf, ctx->blockbuf.filled); if (ret != CAAM_NO_ERROR) { CIPHER_TRACE("Allocation Trash Block error"); goto end_streaming; } trash_bck.filled = ctx->blockbuf.filled; ret = caam_dmaobj_add_first_block(&dst, &trash_bck); if (ret) goto end_streaming; } retstatus = caam_cpy_block_src(&ctx->blockbuf, &cpysrc, size_inmade); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto end_streaming; } ret = caam_dmaobj_init_input(&src, ctx->blockbuf.buf.data, ctx->blockbuf.filled); if (ret) goto end_streaming; ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block); if (ret) goto end_streaming; /* * Build input and output DMA Object with the same size. */ size_done = size_todo; ret = caam_dmaobj_sgtbuf_inout_build(&src, &dst, &size_done, 0, size_todo); if (ret) goto end_streaming; if (size_todo != size_done) { CIPHER_TRACE("Invalid end streaming size %zu vs %zu", size_done, size_todo); ret = TEE_ERROR_GENERIC; goto end_streaming; } retstatus = caam_cipher_block(ctx, false, NEED_KEY1, ctx->encrypt, &src, &dst); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto end_streaming; } dupdate->dst.length += caam_dmaobj_copy_to_orig(&dst); CIPHER_DUMPBUF("Source", ctx->blockbuf.buf.data, ctx->blockbuf.filled); CIPHER_DUMPBUF("Result", dupdate->dst.data + size_inmade, size_topost); } ret = TEE_SUCCESS; end_streaming: caam_dmaobj_free(&src); caam_dmaobj_free(&dst); /* Free Trash block buffer */ caam_free_buf(&trash_bck.buf); return ret; } /* * Update of the cipher operation with complete block except * if last block. Last block can be partial block. * * @dupdate Data update object */ static TEE_Result do_update_cipher(struct drvcrypt_cipher_update *dupdate) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct cipherdata *ctx = dupdate->ctx; struct caamdmaobj src = { }; struct caamdmaobj dst = { }; size_t offset = 0; size_t size_todo = 0; size_t size_done = 0; CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, (ctx->encrypt ? "Encrypt" : "Decrypt")); /* * Check the length of the payload/cipher to be at least * one or n cipher block. */ if (dupdate->src.length < ctx->alg->size_block || dupdate->src.length % ctx->alg->size_block) { CIPHER_TRACE("Bad payload/cipher size %zu bytes", dupdate->src.length); return TEE_ERROR_BAD_PARAMETERS; } ret = caam_dmaobj_init_input(&src, dupdate->src.data, dupdate->src.length); if (ret) goto end_cipher; ret = caam_dmaobj_init_output(&dst, dupdate->dst.data, dupdate->dst.length, dupdate->dst.length); if (ret) goto end_cipher; ret = caam_dmaobj_prepare(&src, &dst, ctx->alg->size_block); if (ret) goto end_cipher; size_todo = dupdate->src.length; dupdate->dst.length = 0; for (offset = 0; size_todo; offset += size_done, size_todo -= size_done) { size_done = size_todo; CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, offset); ret = caam_dmaobj_sgtbuf_inout_build(&src, &dst, &size_done, offset, ctx->alg->size_block); if (ret) goto end_cipher; retstatus = caam_cipher_block(ctx, true, NEED_KEY1, ctx->encrypt, &src, &dst); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto end_cipher; } dupdate->dst.length += caam_dmaobj_copy_to_orig(&dst); } ret = TEE_SUCCESS; end_cipher: caam_dmaobj_free(&src); caam_dmaobj_free(&dst); return ret; } /* * Update of the cipher operation. Call the algorithm update * function associated. * * @dupdate Data update object */ static TEE_Result do_update(struct drvcrypt_cipher_update *dupdate) { struct cipherdata *cipherdata = dupdate->ctx; return cipherdata->alg->update(dupdate); } /* * Finalize of the cipher operation * * @ctx Caller context variable or NULL */ static void do_final(void *ctx __unused) { } /* * Registration of the Cipher Driver */ static struct drvcrypt_cipher driver_cipher = { .alloc_ctx = do_allocate, .free_ctx = caam_cipher_free, .init = caam_cipher_initialize, .update = do_update, .final = do_final, .copy_state = caam_cipher_copy_state, }; /* * Initialize the Cipher module * * @ctrl_addr Controller base address */ enum caam_status caam_cipher_init(vaddr_t ctrl_addr __unused) { enum caam_status retstatus = CAAM_FAILURE; if (drvcrypt_register_cipher(&driver_cipher) == TEE_SUCCESS) retstatus = CAAM_NO_ERROR; return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/cipher/caam_cipher_mac.c000066400000000000000000000474721464416617300247050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Implementation of CMAC functions */ #include #include #include #include #include #include #include #include #include #include #include "local.h" static TEE_Result do_update_mac(struct drvcrypt_cipher_update *dupdate); static TEE_Result do_update_cmac(struct drvcrypt_cipher_update *dupdate); /* * Constant definitions of AES MAC algorithms */ static const struct cipheralg aes_cbc_mac_alg = { .type = OP_ALGO(AES) | ALGO_AAI(AES_CBC), .size_block = TEE_AES_BLOCK_SIZE, .size_ctx = 2 * sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 16, .max = 32, .mod = 8 }, .update = do_update_mac, }; static const struct cipheralg aes_cmac_alg = { .type = OP_ALGO(AES) | ALGO_AAI(AES_CMAC), .size_block = TEE_AES_BLOCK_SIZE, .size_ctx = 4 * sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1, .def_key = { .min = 16, .max = 32, .mod = 8 }, .update = do_update_cmac, }; /* * Constant definitions of DES MAC algorithm */ static const struct cipheralg des_mac_alg = { .type = OP_ALGO(DES) | ALGO_AAI(DES_CBC), .size_block = TEE_DES_BLOCK_SIZE, .size_ctx = sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 8, .max = 8, .mod = 8 }, .update = do_update_mac, }; /* * Constant definitions of DES3 MAC algorithm */ static const struct cipheralg des3_mac_alg = { .type = OP_ALGO(3DES) | ALGO_AAI(DES_CBC), .size_block = TEE_DES_BLOCK_SIZE, .size_ctx = sizeof(uint64_t), .ctx_offset = 0, .require_key = NEED_KEY1 | NEED_IV, .def_key = { .min = 16, .max = 24, .mod = 8 }, .update = do_update_mac, }; static const struct crypto_mac_ops cmac_ops; /* * Format the MAC context to keep the reference to the operation driver */ struct crypto_mac { struct crypto_mac_ctx mac_ctx; /* Crypto MAC API context */ struct cipherdata *ctx; /* CMAC context */ }; /* * Returns the reference to the driver context * * @ctx API context */ static struct crypto_mac *to_mac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == &cmac_ops); return container_of(ctx, struct crypto_mac, mac_ctx); } /* * Checks if the algorithm @algo is supported and returns the * local algorithm entry in the corresponding cipher array. * * @algo Algorithm ID */ static const struct cipheralg *get_macalgo(uint32_t algo) { switch (algo) { case TEE_ALG_AES_CBC_MAC_NOPAD: case TEE_ALG_AES_CBC_MAC_PKCS5: return &aes_cbc_mac_alg; case TEE_ALG_AES_CMAC: return &aes_cmac_alg; case TEE_ALG_DES_CBC_MAC_NOPAD: case TEE_ALG_DES_CBC_MAC_PKCS5: return &des_mac_alg; case TEE_ALG_DES3_CBC_MAC_NOPAD: case TEE_ALG_DES3_CBC_MAC_PKCS5: return &des3_mac_alg; default: return NULL; } } /* * MAC update of the cipher operation of complete block except * if last block. Last block can be partial block. * * @dupdate Data update object */ static TEE_Result do_update_mac(struct drvcrypt_cipher_update *dupdate) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; enum caam_status retstatus = CAAM_FAILURE; struct cipherdata *ctx = dupdate->ctx; struct caamdmaobj src = { }; struct caamdmaobj dst = { }; size_t full_size = 0; size_t size_topost = 0; size_t size_todo = 0; size_t size_done = 0; size_t size_inmade = 0; size_t offset = 0; CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, ctx->encrypt ? "Encrypt" : "Decrypt"); /* Calculate the total data to be handled */ full_size = ctx->blockbuf.filled + dupdate->src.length; if (full_size < ctx->alg->size_block) { size_topost = dupdate->src.length; } else { size_topost = full_size % ctx->alg->size_block; size_inmade = dupdate->src.length - size_topost; /* Total size that is a cipher block multiple */ size_todo = full_size - size_topost; } CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", full_size, size_topost, size_todo); if (!size_todo) { /* * There is no complete block to do: * - either input size + already saved data < block size * - or no input data and this is the last block */ if (dupdate->last) memcpy(dupdate->dst.data, ctx->ctx.data, MIN(dupdate->dst.length, ctx->alg->size_ctx)); ret = TEE_SUCCESS; goto end_mac_post; } if (dupdate->src.length) { ret = caam_dmaobj_init_input(&src, dupdate->src.data, dupdate->src.length); if (ret) goto end_mac; ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block); if (ret) goto end_mac; } if (dupdate->last) { ret = caam_dmaobj_output_sgtbuf(&dst, dupdate->dst.data, dupdate->dst.length, dupdate->dst.length); if (ret) goto end_mac; /* Remove a block of data to do the last block */ if (size_todo > ctx->alg->size_block) size_todo -= ctx->alg->size_block; else size_todo = 0; } /* Check if there is some data saved to complete the buffer */ if (ctx->blockbuf.filled) { ret = caam_dmaobj_add_first_block(&src, &ctx->blockbuf); if (ret) goto end_mac; ctx->blockbuf.filled = 0; } size_done = ctx->alg->size_block; for (offset = 0; size_todo; offset += size_done, size_todo -= size_done) { CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, offset); ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, ctx->alg->size_block); if (ret) goto end_mac; if (size_done != ctx->alg->size_block) { ret = TEE_ERROR_GENERIC; goto end_mac; } retstatus = caam_cipher_block(ctx, true, NEED_KEY1, true, &src, NULL); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto end_mac; } } if (dupdate->last) { CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, offset); ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, ctx->alg->size_block); if (ret) goto end_mac; if (size_done != ctx->alg->size_block) { ret = TEE_ERROR_GENERIC; goto end_mac; } retstatus = caam_cipher_block(ctx, true, NEED_KEY1, true, &src, &dst); if (retstatus == CAAM_NO_ERROR) caam_dmaobj_copy_to_orig(&dst); ret = caam_status_to_tee_result(retstatus); } end_mac_post: if (size_topost) { struct caambuf cpysrc = { .data = dupdate->src.data, .length = dupdate->src.length }; CIPHER_TRACE("Save input data %zu bytes of %zu (%zu)", size_topost, dupdate->src.length, size_inmade); retstatus = caam_cpy_block_src(&ctx->blockbuf, &cpysrc, size_inmade); ret = caam_status_to_tee_result(retstatus); } end_mac: caam_dmaobj_free(&src); caam_dmaobj_free(&dst); return ret; } /* * Build and run the CMAC descriptor (AES only) * * @ctx Cipher Data context * @src Input data * @dstbuf [out] Output data if last block * @last Last block flag */ static TEE_Result run_cmac_desc(struct cipherdata *ctx, struct caamdmaobj *src, struct caamdmaobj *dst, bool last) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; desc = ctx->descriptor; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); if (ctx->alg->require_key & NEED_KEY1) { /* Build the descriptor */ caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG, ctx->key1.length)); caam_desc_add_ptr(desc, ctx->key1.paddr); } /* If context already allocated, this is an update */ if (ctx->ctx.length) { CIPHER_TRACE("%s operation", last ? "Final" : "Update"); caam_desc_add_word(desc, LD_NOIMM_OFF(CLASS_1, REG_CTX, ctx->ctx.length, ctx->alg->ctx_offset)); caam_desc_add_ptr(desc, ctx->ctx.paddr); if (last) caam_desc_add_word(desc, CIPHER_FINAL(ctx->alg->type, true)); else caam_desc_add_word(desc, CIPHER_UPDATE(ctx->alg->type, true)); } else if (last) { CIPHER_TRACE("Init/Final operation"); caam_desc_add_word(desc, CIPHER_INITFINAL(ctx->alg->type, true)); } else { CIPHER_TRACE("Init operation"); caam_desc_add_word(desc, CIPHER_INIT(ctx->alg->type, true)); if (!ctx->ctx.data) { retstatus = caam_alloc_align_buf(&ctx->ctx, ctx->alg->size_ctx); if (retstatus != CAAM_NO_ERROR) return TEE_ERROR_OUT_OF_MEMORY; } } /* Check first if there is some pending data from previous updates */ if (ctx->blockbuf.filled) { /* Add the temporary buffer */ if (src) caam_desc_add_word(desc, FIFO_LD_EXT(CLASS_1, MSG, NOACTION)); else caam_desc_add_word(desc, FIFO_LD_EXT(CLASS_1, MSG, LAST_C1)); caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr); caam_desc_add_word(desc, ctx->blockbuf.filled); /* Clean the circular buffer data to be loaded */ cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data, ctx->blockbuf.filled); } if (src) { caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1); caam_dmaobj_cache_push(src); } else { if (last && !ctx->blockbuf.filled) { /* * Add the input data of 0 bytes to start * algorithm by setting the input data size */ caam_desc_add_word(desc, FIFO_LD(CLASS_1, MSG, LAST_C1, 0)); caam_desc_add_ptr(desc, 0); } } ctx->blockbuf.filled = 0; if (last) { caam_desc_store(desc, dst, CLASS_1, REG_CTX); caam_dmaobj_cache_push(dst); } else { /* Store the context */ caam_desc_add_word(desc, ST_NOIMM_OFF(CLASS_1, REG_CTX, ctx->ctx.length, ctx->alg->ctx_offset)); caam_desc_add_ptr(desc, ctx->ctx.paddr); } CIPHER_DUMPDESC(desc); /* Invalidate Context register */ if (ctx->ctx.length) cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, ctx->ctx.length); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { ret = TEE_SUCCESS; } else { CIPHER_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } return ret; } /* * Update of the CMAC operation of complete block except * if last block. Last block can be a partial block. * * @dupdate Data update object */ static TEE_Result do_update_cmac(struct drvcrypt_cipher_update *dupdate) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; enum caam_status retstatus = CAAM_FAILURE; struct cipherdata *ctx = dupdate->ctx; size_t full_size = 0; size_t size_topost = 0; size_t size_todo = 0; size_t size_inmade = 0; size_t size_done = 0; size_t offset = 0; struct caamdmaobj src = { }; struct caamdmaobj dst = { }; CIPHER_TRACE("Length=%zu - %s", dupdate->src.length, dupdate->encrypt ? "Encrypt" : "Decrypt"); /* Calculate the total data to be handled */ full_size = ctx->blockbuf.filled + dupdate->src.length; if (!dupdate->last) { /* * In case there is no data to save and because it's * not the final operation, ensure that a block of data * is kept for the final operation. */ if (full_size <= ctx->alg->size_block) { size_topost = dupdate->src.length; goto end_cmac_post; } size_topost = full_size % ctx->alg->size_block; if (!size_topost) size_topost = ctx->alg->size_block; size_inmade = dupdate->src.length - size_topost; size_todo = full_size - size_topost; } else { ret = caam_dmaobj_output_sgtbuf(&dst, dupdate->dst.data, dupdate->dst.length, dupdate->dst.length); if (ret) goto end_cmac; /* * If there more than one block to do, keep the last * block to build the CMAC output. */ if (full_size > ctx->alg->size_block) { size_todo = full_size - ctx->alg->size_block; size_inmade = size_todo - ctx->blockbuf.filled; } } if (size_inmade) { ret = caam_dmaobj_init_input(&src, dupdate->src.data, size_inmade); if (ret) goto end_cmac; ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block); if (ret) goto end_cmac; } CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", full_size, size_topost, size_todo); for (offset = 0; size_todo; offset += size_done, size_todo -= size_done) { /* * At least one block is to be done. * At first iteration, we can have less than one block * data available from previous update operation which * was not block modulus. * Remove the previous saved data (blockbuf) from the data to * take from input data. * Next iteration, blockbuf will be empty. */ size_todo -= ctx->blockbuf.filled; size_done = size_todo; if (size_inmade) { ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, ctx->alg->size_block); if (ret) goto end_cmac; /* * Need to re-adjust the length of the data if the * posted data block is not empty and the SGT/Buffer * is part of the full input data to do. */ if (ctx->blockbuf.filled && size_done < size_todo) { size_done -= ctx->blockbuf.filled; src.sgtbuf.length = size_done; } CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done, offset); ret = run_cmac_desc(ctx, &src, NULL, false); } else { CIPHER_TRACE("Do saved blockbuf %zu bytes (done = %zu)", ctx->blockbuf.filled, size_done); ret = run_cmac_desc(ctx, NULL, NULL, false); } if (ret) goto end_cmac; } if (dupdate->last) { if (dupdate->src.length - size_inmade) { size_done = dupdate->src.length - size_inmade; ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, ctx->alg->size_block); if (ret) goto end_cmac; if (size_done != dupdate->src.length - size_inmade) { ret = TEE_ERROR_GENERIC; goto end_cmac; } ret = run_cmac_desc(ctx, &src, &dst, true); } else { ret = run_cmac_desc(ctx, NULL, &dst, true); } if (!ret) caam_dmaobj_copy_to_orig(&dst); } end_cmac_post: if (size_topost) { struct caambuf srcbuf = { .data = dupdate->src.data, .length = dupdate->src.length }; CIPHER_TRACE("Post %zu of input len %zu made %zu", size_topost, srcbuf.length, size_inmade); retstatus = caam_cpy_block_src(&ctx->blockbuf, &srcbuf, size_inmade); ret = caam_status_to_tee_result(retstatus); } end_cmac: caam_dmaobj_free(&src); caam_dmaobj_free(&dst); return ret; } /* * Initialization of the CMAC operation. * * @ctx Operation software context * @key Input key to compute * @len Key length */ static TEE_Result do_cmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; uint8_t *iv_tmp = NULL; struct drvcrypt_cipher_init dinit = { }; struct crypto_mac *mac = to_mac_ctx(ctx); struct cipherdata *macdata = mac->ctx; if (macdata->mode != TEE_CHAIN_MODE_CMAC) { /* Allocate temporary IV initialize with 0's */ iv_tmp = caam_calloc(macdata->alg->size_ctx); if (!iv_tmp) return TEE_ERROR_OUT_OF_MEMORY; } else { /* * Check if the context register is allocated to free it, * because in case of CMAC mode, the context register * is allocated during do_update_cmac() operation if * necessary. */ if (macdata->ctx.data) caam_free_buf(&macdata->ctx); } macdata->countdata = 0; /* Prepare the initialization data */ dinit.ctx = macdata; dinit.encrypt = true; dinit.key1.data = (uint8_t *)key; dinit.key1.length = len; dinit.key2.data = NULL; dinit.key2.length = 0; dinit.iv.data = iv_tmp; dinit.iv.length = macdata->alg->size_ctx; ret = caam_cipher_initialize(&dinit); caam_free(iv_tmp); return ret; } /* * Update of the CMAC operation. * * @ctx Operation software context * @data Data to encrypt * @len Data length */ static TEE_Result do_cmac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; struct crypto_mac *mac = to_mac_ctx(ctx); struct cipherdata *macdata = mac->ctx; struct drvcrypt_cipher_update dupdate = { }; /* Prepare the update data */ dupdate.ctx = macdata; dupdate.encrypt = true; dupdate.last = false; dupdate.src.data = (uint8_t *)data; dupdate.src.length = len; dupdate.dst.data = NULL; dupdate.dst.length = 0; ret = macdata->alg->update(&dupdate); if (!ret && macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5) macdata->countdata += len; return ret; } /* * Finalize the CMAC operation * * @ctx Operation software context * @digest [out] Digest buffer * @len Digest buffer length */ static TEE_Result do_cmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; uint8_t *pad_src = NULL; size_t pad_size = 0; struct crypto_mac *mac = to_mac_ctx(ctx); struct cipherdata *macdata = mac->ctx; struct drvcrypt_cipher_update dupdate = { }; if (macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5) { /* Calculate the last block PAD size */ pad_size = macdata->alg->size_block - (macdata->countdata % macdata->alg->size_block); CIPHER_TRACE("Pad size = %zu", pad_size); if (pad_size) { /* Need to pad the last block */ pad_src = caam_calloc(pad_size); if (!pad_src) { CIPHER_TRACE("Pad src allocation error"); return TEE_ERROR_OUT_OF_MEMORY; } memset(pad_src, pad_size, pad_size); } } /* Prepare the update data */ dupdate.ctx = macdata; dupdate.encrypt = true; dupdate.last = true; dupdate.src.data = pad_src; dupdate.src.length = pad_size; dupdate.dst.data = digest; dupdate.dst.length = MIN(len, macdata->alg->size_block); ret = macdata->alg->update(&dupdate); caam_free(pad_src); return ret; } /* * Free the software context * * @ctx [in/out] Caller context variable */ static void do_cmac_free(struct crypto_mac_ctx *ctx) { struct crypto_mac *mac = to_mac_ctx(ctx); caam_cipher_free(mac->ctx); free(mac); } /* * Copy software CMAC context * * @dst_ctx [out] Reference the context destination * @src_ctx Reference the context source */ static void do_cmac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct crypto_mac *mac_src = to_mac_ctx(src_ctx); struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx); struct cipherdata *macdata_dst = mac_dst->ctx; struct cipherdata *macdata_src = mac_src->ctx; caam_cipher_copy_state(macdata_dst, macdata_src); macdata_dst->countdata = macdata_src->countdata; macdata_dst->mode = macdata_src->mode; } /* * Registration of the CMAC driver */ static const struct crypto_mac_ops cmac_ops = { .init = do_cmac_init, .update = do_cmac_update, .final = do_cmac_final, .free_ctx = do_cmac_free, .copy_state = do_cmac_copy_state, }; /* * Allocate the software context * * @ctx [out] Caller context variable * @algo Algorithm ID */ static TEE_Result caam_cmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_mac *mac = NULL; const struct cipheralg *alg = NULL; struct cipherdata *macdata = NULL; CIPHER_TRACE("Allocate Context (%p) algo %" PRIx32, ctx, algo); alg = get_macalgo(algo); if (!alg) { CIPHER_TRACE("Algorithm not supported"); return TEE_ERROR_NOT_IMPLEMENTED; } mac = calloc(1, sizeof(*mac)); if (!mac) return TEE_ERROR_OUT_OF_MEMORY; macdata = caam_calloc(sizeof(*macdata)); if (!macdata) { CIPHER_TRACE("Allocation MAC data error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } /* Allocate the descriptor */ macdata->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES); if (!macdata->descriptor) { CIPHER_TRACE("Allocation descriptor error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } /* Setup the algorithm pointer */ macdata->alg = alg; /* Initialize the block buffer */ macdata->blockbuf.max = alg->size_block; /* Keep the MAC mode */ macdata->mode = TEE_ALG_GET_CHAIN_MODE(algo); mac->mac_ctx.ops = &cmac_ops; mac->ctx = macdata; *ctx = &mac->mac_ctx; return TEE_SUCCESS; err: if (macdata) caam_free_desc(&macdata->descriptor); caam_free(macdata); free(mac); return ret; } /* * Initialize the CMAC module * * @ctrl_addr Controller base address */ enum caam_status caam_cmac_init(vaddr_t ctrl_addr __unused) { if (drvcrypt_register(CRYPTO_CMAC, &caam_cmac_allocate)) return CAAM_FAILURE; return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/cipher/caam_cipher_xts.c000066400000000000000000000146771464416617300247640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Implementation of Cipher XTS functions */ #include #include #include #include #include #include "local.h" /* * Galois Multiplication * * @buf [in/out] buffer to multiply */ static void do_galois_mult(struct caambuf *buf) { size_t idx = 0; uint8_t tmp = 0; uint8_t tmptmp = 0; for (idx = 0; idx < buf->length; idx++) { tmptmp = buf->data[idx] >> 7; buf->data[idx] = (buf->data[idx] << 1) | tmp; tmp = tmptmp; } if (tmptmp) buf->data[0] ^= 0x87; } /* * Tweak a cipher block (XTS mode) * * @ctx Cipher context * @enc_tweak [in/out] Encrypted tweak (Galois multiplication) * @srcbuf Source data to encrypt/decrypt * @dstbuf [out] Destination data encrypted/decrypted * @tmp Temporary data buffer */ static TEE_Result do_tweak_block(struct cipherdata *ctx, struct caambuf *enc_tweak, struct caambuf *srcbuf, struct caambuf *dstbuf, struct caamdmaobj *tmp) { enum caam_status retstatus = CAAM_FAILURE; unsigned int idx = 0; /* * TODO: Optimization by using CAAM to do it with MATH op in the * operation description */ for (idx = 0; idx < ctx->alg->size_block; idx++) tmp->orig.data[idx] = srcbuf->data[idx] ^ enc_tweak->data[idx]; retstatus = caam_cipher_block(ctx, false, NEED_KEY1, ctx->encrypt, tmp, tmp); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); caam_dmaobj_copy_to_orig(tmp); for (idx = 0; idx < ctx->alg->size_block; idx++) dstbuf->data[idx] = tmp->orig.data[idx] ^ enc_tweak->data[idx]; /* Galois field multiplication of the tweak */ do_galois_mult(enc_tweak); return TEE_SUCCESS; } TEE_Result caam_cipher_update_xts(struct drvcrypt_cipher_update *dupdate) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct cipherdata *ctx = dupdate->ctx; struct caambuf tmpsrc = { }; struct caamdmaobj tmpdst = { }; struct caamdmaobj tweak = { }; struct caamdmaobj enc_tweak = { }; struct caambuf srcbuf = { }; struct caambuf dstbuf = { }; size_t idx = 0; size_t fullsize = 0; size_t lastblk = 0; paddr_t psrc = 0; paddr_t pdst = 0; CIPHER_TRACE("Algo AES XTS length=%zu - %s", dupdate->src.length, ctx->encrypt ? "Encrypt" : " Decrypt"); psrc = virt_to_phys(dupdate->src.data); pdst = virt_to_phys(dupdate->dst.data); /* Check the payload/cipher physical addresses */ if (!psrc || !pdst) { CIPHER_TRACE("Bad Addr (src %#" PRIxPA ") (dst %#" PRIxPA ")", psrc, pdst); return TEE_ERROR_GENERIC; } ret = caam_dmaobj_input_sgtbuf(&tweak, ctx->tweak.data, ctx->tweak.length); if (ret) goto out; /* * First operation is to encrypt the tweak with the key #2 * Allocate the encrypted tweak buffer */ ret = caam_dmaobj_output_sgtbuf(&enc_tweak, NULL, 0, ctx->tweak.length); if (ret) goto out; ret = caam_dmaobj_output_sgtbuf(&tmpdst, NULL, 0, ctx->alg->size_block); if (ret) goto out; retstatus = caam_cipher_block(ctx, false, NEED_KEY2, true, &tweak, &enc_tweak); if (retstatus != CAAM_NO_ERROR) { CIPHER_TRACE("Tweak encryption error"); ret = caam_status_to_tee_result(retstatus); goto out; } caam_dmaobj_copy_to_orig(&enc_tweak); /* * Encrypt or Decrypt input data. * Check if the last block is partial or not * - if last block is partial, rebuild a complete * block using the penultimate complete block * encryption/decryption. * - else do all blocks. */ /* Calculate the number of complete block */ fullsize = dupdate->src.length; lastblk = fullsize % ctx->alg->size_block; fullsize -= lastblk; /* One full block is needed */ if (!fullsize) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } if (lastblk) fullsize -= ctx->alg->size_block; srcbuf.data = dupdate->src.data; srcbuf.length = ctx->alg->size_block; srcbuf.paddr = psrc; dstbuf.data = dupdate->dst.data; dstbuf.length = ctx->alg->size_block; dstbuf.paddr = pdst; for (; fullsize > 0; fullsize -= ctx->alg->size_block) { CIPHER_TRACE("Tweak block fullsize %zu", fullsize); ret = do_tweak_block(ctx, &enc_tweak.orig, &srcbuf, &dstbuf, &tmpdst); CIPHER_TRACE("Tweak block ret 0x%" PRIx32, ret); if (ret) goto out; CIPHER_DUMPBUF("Source", srcbuf.data, srcbuf.length); CIPHER_DUMPBUF("Dest", dstbuf.data, dstbuf.length); /* Increment the source and destination block */ srcbuf.data += ctx->alg->size_block; srcbuf.paddr += ctx->alg->size_block; dstbuf.data += ctx->alg->size_block; dstbuf.paddr += ctx->alg->size_block; } if (lastblk) { CIPHER_TRACE("Last block size is %zu", lastblk); /* * Allocate the temporary buffer containing the * penultimate block computed */ retstatus = caam_alloc_align_buf(&tmpsrc, ctx->alg->size_block); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } if (!ctx->encrypt) { /* * In case of decryption, need to multiply * the tweak first */ memcpy(tmpsrc.data, enc_tweak.orig.data, enc_tweak.orig.length); do_galois_mult(&tmpsrc); ret = do_tweak_block(ctx, &tmpsrc, &srcbuf, &tmpdst.orig, &tmpdst); } else { ret = do_tweak_block(ctx, &enc_tweak.orig, &srcbuf, &tmpdst.orig, &tmpdst); } CIPHER_TRACE("Tweak penultimate block ret 0x%" PRIx32, ret); if (ret) goto out; /* Build the last block and create the last destination block */ for (idx = 0; idx < lastblk; idx++) { tmpsrc.data[idx] = srcbuf.data[ctx->alg->size_block + idx]; dstbuf.data[ctx->alg->size_block + idx] = tmpdst.orig.data[idx]; } for (; idx < ctx->alg->size_block; idx++) tmpsrc.data[idx] = tmpdst.orig.data[idx]; ret = do_tweak_block(ctx, &enc_tweak.orig, &tmpsrc, &dstbuf, &tmpdst); CIPHER_TRACE("Tweak last block ret 0x%" PRIx32, ret); if (ret) goto out; CIPHER_DUMPBUF("Source", tmpsrc.data, tmpsrc.length); CIPHER_DUMPBUF("Dest", dstbuf.data, dstbuf.length); } /* Finalize by decrypting the tweak back */ retstatus = caam_cipher_block(ctx, false, NEED_KEY2, false, &enc_tweak, &tweak); if (retstatus != CAAM_NO_ERROR) { CIPHER_TRACE("Tweak decryption error"); ret = caam_status_to_tee_result(retstatus); goto out; } caam_dmaobj_copy_to_orig(&tweak); ret = TEE_SUCCESS; out: caam_free_buf(&tmpsrc); caam_dmaobj_free(&tmpdst); caam_dmaobj_free(&tweak); caam_dmaobj_free(&enc_tweak); return ret; } optee_os-4.3.0/core/drivers/crypto/caam/cipher/local.h000066400000000000000000000057161464416617300227240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * CAAM Cipher Local header. */ #ifndef __LOCAL_H__ #define __LOCAL_H__ #include #include #include /* * Definition of the maximum number of CAAM Job descriptor entries */ #ifdef CFG_CAAM_64BIT #define MAX_DESC_ENTRIES 22 #else #define MAX_DESC_ENTRIES 16 #endif /* * Definition of flags tagging which key(s) is required */ #define NEED_KEY1 BIT(0) #define NEED_KEY2 BIT(1) #define NEED_IV BIT(2) #define NEED_TWEAK BIT(3) /* * Cipher Algorithm definition */ struct cipheralg { uint32_t type; /* Algo type for operation */ uint8_t size_block; /* Computing block size */ uint8_t size_ctx; /* CAAM Context Register size */ uint8_t ctx_offset; /* CAAM Context Register offset */ uint8_t require_key; /* Tag defining key(s) required */ struct caamdefkey def_key; /* Key size accepted */ TEE_Result (*update)(struct drvcrypt_cipher_update *dupdate); }; /* * Full Cipher data SW context */ struct cipherdata { uint32_t *descriptor; /* Job descriptor */ bool encrypt; /* Encrypt direction */ struct caambuf key1; /* First Key */ struct caambuf key2; /* Second Key */ struct caambuf tweak; /* XTS Tweak */ struct caambuf ctx; /* CAAM Context Register */ struct caamblock blockbuf; /* Temporary Block buffer */ const struct cipheralg *alg; /* Reference to the algo constants */ /* Additionnal Data for the MAC */ unsigned int mode; /* MAC TEE_CHAIN_MODE* */ size_t countdata; /* MAC Number of input data */ }; /* * Cipher additionnal data block */ enum caam_cipher_block { CIPHER_BLOCK_NONE = 0, CIPHER_BLOCK_IN, CIPHER_BLOCK_OUT, CIPHER_BLOCK_BOTH, }; /* * Update of the cipher operation of complete block except * if last block. Last block can be partial block. * * @ctx Cipher context * @savectx Save or not the context * @keyid Id of the key to be used during operation * @encrypt Encrypt or decrypt direction * @src Source data to encrypt/decrypt * @dst [out] Destination data encrypted/decrypted */ enum caam_status caam_cipher_block(struct cipherdata *ctx, bool savectx, uint8_t keyid, bool encrypt, struct caamdmaobj *src, struct caamdmaobj *dst); /* * Update of the cipher operation in xts mode. * * @dupdate Data update object */ TEE_Result caam_cipher_update_xts(struct drvcrypt_cipher_update *dupdate); /* * Initialization of the cipher operation * * @dinit Data initialization object */ TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit); /* * Free software context * * @ctx Caller context variable */ void caam_cipher_free(void *ctx); /* * Copy software Context * * @dst_ctx [out] Reference the context destination * @src_ctx Reference the context source */ void caam_cipher_copy_state(void *dst_ctx, void *src_ctx); #endif /* __LOCAL_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/cipher/sub.mk000066400000000000000000000002001464416617300225620ustar00rootroot00000000000000incdirs-y += ../include srcs-y += caam_cipher.c srcs-y += caam_cipher_xts.c srcs-$(CFG_NXP_CAAM_CMAC_DRV) += caam_cipher_mac.c optee_os-4.3.0/core/drivers/crypto/caam/crypto.mk000066400000000000000000000163451464416617300220600ustar00rootroot00000000000000ifeq ($(CFG_NXP_CAAM),y) # CAAM Debug: define 3x32 bits value (same bit used to debug a module) # CFG_DBG_CAAM_TRACE Module print trace # CFG_DBG_CAAM_DESC Module descriptor dump # CFG_DBG_CAAM_BUF Module buffer dump # # DBG_HAL BIT32(0) // HAL trace # DBG_CTRL BIT32(1) // Controller trace # DBG_MEM BIT32(2) // Memory utility trace # DBG_SGT BIT32(3) // Scatter Gather trace # DBG_PWR BIT32(4) // Power trace # DBG_JR BIT32(5) // Job Ring trace # DBG_RNG BIT32(6) // RNG trace # DBG_HASH BIT32(7) // Hash trace # DBG_RSA BIT32(8) // RSA trace # DBG_CIPHER BIT32(9) // Cipher trace # DBG_BLOB BIT32(10) // BLOB trace # DBG_DMAOBJ BIT32(11) // DMA Object Trace # DBG_ECC BIT32(12) // ECC trace # DBG_DH BIT32(13) // DH Trace # DBG_DSA BIT32(14) // DSA trace # DBG_MP BIT32(15) // MP trace CFG_DBG_CAAM_TRACE ?= 0x2 CFG_DBG_CAAM_DESC ?= 0x0 CFG_DBG_CAAM_BUF ?= 0x0 # CAAM default drivers caam-drivers = RNG BLOB # CAAM default drivers connected to the HW crypto API caam-crypto-drivers = CIPHER HASH HMAC CMAC ifneq (,$(filter $(PLATFORM_FLAVOR),ls1012ardb ls1043ardb ls1046ardb)) $(call force, CFG_CAAM_BIG_ENDIAN,y) $(call force, CFG_JR_BLOCK_SIZE,0x10000) $(call force, CFG_JR_INDEX,2) $(call force, CFG_JR_INT,105) $(call force, CFG_CAAM_SGT_ALIGN,4) $(call force, CFG_CAAM_64BIT,y) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_CAAM_ITR,n) caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),ls1088ardb ls2088ardb ls1028ardb)) $(call force, CFG_CAAM_LITTLE_ENDIAN,y) $(call force, CFG_JR_BLOCK_SIZE,0x10000) $(call force, CFG_JR_INDEX,2) $(call force, CFG_JR_INT,174) $(call force, CFG_NXP_CAAM_SGT_V2,y) $(call force, CFG_CAAM_SGT_ALIGN,4) $(call force, CFG_CAAM_64BIT,y) $(call force, CFG_CAAM_ITR,n) caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),lx2160aqds lx2160ardb)) $(call force, CFG_CAAM_LITTLE_ENDIAN,y) $(call force, CFG_JR_BLOCK_SIZE,0x10000) $(call force, CFG_JR_INDEX,2) $(call force, CFG_JR_INT, 174) $(call force, CFG_NB_JOBS_QUEUE, 80) $(call force, CFG_NXP_CAAM_SGT_V2,y) $(call force, CFG_CAAM_SGT_ALIGN,4) $(call force, CFG_CAAM_64BIT,y) $(call force, CFG_CAAM_ITR,n) caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qm-flavorlist) $(mx8qx-flavorlist))) $(call force, CFG_CAAM_SIZE_ALIGN,4) $(call force, CFG_JR_BLOCK_SIZE,0x10000) $(call force, CFG_JR_INDEX,3) $(call force, CFG_JR_INT,486) $(call force, CFG_NXP_CAAM_SGT_V1,y) caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8dxl-flavorlist))) $(call force, CFG_CAAM_SIZE_ALIGN,4) $(call force, CFG_JR_BLOCK_SIZE,0x10000) $(call force, CFG_JR_INDEX,3) $(call force, CFG_JR_INT,356) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_CAAM_JR_DISABLE_NODE,n) caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mm-flavorlist) $(mx8mn-flavorlist) \ $(mx8mp-flavorlist) $(mx8mq-flavorlist))) $(call force, CFG_JR_BLOCK_SIZE,0x1000) $(call force, CFG_JR_INDEX,2) $(call force, CFG_JR_INT,146) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_JR_HAB_INDEX,0) # There is a limitation on i.MX8M platforms regarding ECDSA Sign/Verify # Size of Class 2 Context register is 40bytes, because of which sign/verify # of a hash of more than 40bytes fails. So a workaround is implemented for # this issue, controlled by CFG_NXP_CAAM_C2_CTX_REG_WA flag. $(call force, CFG_NXP_CAAM_C2_CTX_REG_WA,y) caam-drivers += MP DEK caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist))) $(call force, CFG_JR_BLOCK_SIZE,0x1000) $(call force, CFG_JR_INDEX,2) $(call force, CFG_JR_INT,114) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_CAAM_ITR,n) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7ulp-flavorlist))) $(call force, CFG_JR_BLOCK_SIZE,0x1000) $(call force, CFG_JR_INDEX,0) $(call force, CFG_JR_INT,137) $(call force, CFG_NXP_CAAM_SGT_V1,y) $(call force, CFG_CAAM_ITR,n) else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ul-flavorlist) $(mx7d-flavorlist) \ $(mx7s-flavorlist))) $(call force, CFG_JR_BLOCK_SIZE,0x1000) $(call force, CFG_JR_INDEX,0) $(call force, CFG_JR_INT,137) $(call force, CFG_NXP_CAAM_SGT_V1,y) caam-drivers += MP caam-crypto-drivers += RSA DSA ECC DH MATH else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6q-flavorlist) $(mx6qp-flavorlist) \ $(mx6sx-flavorlist) $(mx6d-flavorlist) $(mx6dl-flavorlist) \ $(mx6s-flavorlist) $(mx8ulp-flavorlist))) $(call force, CFG_JR_BLOCK_SIZE,0x1000) $(call force, CFG_JR_INDEX,0) $(call force, CFG_JR_INT,137) $(call force, CFG_NXP_CAAM_SGT_V1,y) else $(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)") endif # Disable the i.MX CAAM driver $(call force,CFG_IMX_CAAM,n,Mandated by CFG_NXP_CAAM) # CAAM buffer alignment size CFG_CAAM_SIZE_ALIGN ?= 1 # Default padding number for SGT allocation CFG_CAAM_SGT_ALIGN ?= 1 # Enable job ring interruption CFG_CAAM_ITR ?= y # Keep the CFG_JR_INDEX as secure at runtime CFG_NXP_CAAM_RUNTIME_JR ?= y # Define the RSA Private Key Format used by the CAAM # Format #1: (n, d) # Format #2: (p, q, d) # Format #3: (p, q, dp, dq, qp) CFG_NXP_CAAM_RSA_KEY_FORMAT ?= 3 # Disable device tree status of the secure job ring CFG_CAAM_JR_DISABLE_NODE ?= y # Define the default CAAM private key encryption generation and the bignum # maximum size needed. # CAAM_KEY_PLAIN_TEXT -> 4096 bits # CAAM_KEY_BLACK_ECB|CCM -> 4156 bits CFG_CORE_BIGNUM_MAX_BITS ?= 4156 # Enable CAAM non-crypto drivers $(foreach drv, $(caam-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y)) # Prefer CAAM HWRNG over PRNG seeded by CAAM ifeq ($(CFG_NXP_CAAM_RNG_DRV), y) CFG_WITH_SOFTWARE_PRNG ?= n endif # DEK driver requires the SM driver to be enabled ifeq ($(CFG_NXP_CAAM_DEK_DRV), y) $(call force, CFG_NXP_CAAM_SM_DRV,y,Mandated by CFG_NXP_CAAM_DEK_DRV) endif ifeq ($(CFG_CRYPTO_DRIVER), y) CFG_CRYPTO_DRIVER_DEBUG ?= 0 # Enable CAAM Crypto drivers $(foreach drv, $(caam-crypto-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y)) # Enable MAC crypto driver ifeq ($(call cfg-one-enabled,CFG_NXP_CAAM_HMAC_DRV CFG_NXP_CAAM_CMAC_DRV),y) $(call force, CFG_CRYPTO_DRV_MAC,y,Mandated by CFG_NXP_CAAM_HMAC/CMAC_DRV) endif # Enable CIPHER crypto driver ifeq ($(CFG_NXP_CAAM_CIPHER_DRV), y) $(call force, CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_NXP_CAAM_CIPHER_DRV) endif # Enable HASH crypto driver ifeq ($(CFG_NXP_CAAM_HASH_DRV), y) $(call force, CFG_CRYPTO_DRV_HASH,y,Mandated by CFG_NXP_CAAM_HASH_DRV) endif # Enable RSA crypto driver ifeq ($(CFG_NXP_CAAM_RSA_DRV), y) $(call force, CFG_CRYPTO_DRV_RSA,y,Mandated by CFG_NXP_CAAM_RSA_DRV) endif # Enable ECC crypto driver ifeq ($(CFG_NXP_CAAM_ECC_DRV), y) $(call force, CFG_CRYPTO_DRV_ECC,y,Mandated by CFG_NXP_CAAM_ECC_DRV) endif # Enable DSA crypto driver ifeq ($(CFG_NXP_CAAM_DSA_DRV), y) $(call force, CFG_CRYPTO_DRV_DSA,y,Mandated by CFG_NXP_CAAM_DSA_DRV) endif # Enable DH crypto driver ifeq ($(CFG_NXP_CAAM_DH_DRV), y) $(call force, CFG_CRYPTO_DRV_DH,y,Mandated by CFG_NXP_CAAM_DH_DRV) endif # Enable ACIPHER crypto driver ifeq ($(call cfg-one-enabled,CFG_CRYPTO_DRV_RSA CFG_CRYPTO_DRV_ECC \ CFG_CRYPTO_DRV_DSA CFG_CRYPTO_DRV_DH),y) $(call force, CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_CRYPTO_DRV_{RSA|ECC|DSA|DH}) endif endif # CFG_CRYPTO_DRIVER endif # CFG_NXP_CAAM optee_os-4.3.0/core/drivers/crypto/caam/hal/000077500000000000000000000000001464416617300207425ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/common/000077500000000000000000000000001464416617300222325ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/common/hal_cfg.c000066400000000000000000000045421464416617300237660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2019, 2021 NXP * * Brief CAAM Configuration. */ #include #include #include #include #include #include #include #include #include #include enum caam_status caam_hal_cfg_get_conf(struct caam_jrcfg *jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t ctrl_base = 0; void *fdt = NULL; fdt = get_dt(); /* * First get the CAAM Controller base address from the DTB, * if DTB present and if the CAAM Controller defined in it. */ if (fdt) caam_hal_cfg_get_ctrl_dt(fdt, &ctrl_base); if (!ctrl_base) { ctrl_base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, CAAM_BASE, CAAM_SIZE); if (!ctrl_base) { EMSG("Unable to map CAAM Registers"); goto exit_get_conf; } } jrcfg->base = ctrl_base; /* * Next get the Job Ring reserved for the Secure environment * into the DTB. If nothing reserved use the default hard coded * value. */ if (fdt) caam_hal_cfg_get_jobring_dt(fdt, jrcfg); if (!jrcfg->offset) { jrcfg->offset = (CFG_JR_INDEX + 1) * JRX_BLOCK_SIZE; jrcfg->it_num = CFG_JR_INT; if (IS_ENABLED(CFG_NXP_CAAM_RUNTIME_JR) && !is_embedded_dt(fdt)) { if (fdt) { /* Ensure Secure Job Ring is secure in DTB */ caam_hal_cfg_disable_jobring_dt(fdt, jrcfg); } } } jrcfg->nb_jobs = NB_JOBS_QUEUE; retstatus = CAAM_NO_ERROR; exit_get_conf: HAL_TRACE("HAL CFG Get CAAM config ret (0x%x)\n", retstatus); return retstatus; } void __weak caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg) { enum caam_status status = CAAM_FAILURE; paddr_t jr_offset = 0; uint8_t jrnum = 0; for (jrnum = caam_hal_ctrl_jrnum(jrcfg->base); jrnum; jrnum--) { jr_offset = jrnum * JRX_BLOCK_SIZE; #ifdef CFG_NXP_CAAM_RUNTIME_JR /* * When the Cryptographic driver is enabled, keep the * Secure Job Ring don't release it. * But save the configuration to restore it when * device reset after suspend. */ if (jr_offset == jrcfg->offset) { caam_hal_jr_prepare_backup(jrcfg->base, jr_offset); continue; } #endif status = caam_hal_jr_setowner(jrcfg->base, jr_offset, JROWN_ARM_NS); if (status == CAAM_NO_ERROR) caam_hal_jr_prepare_backup(jrcfg->base, jr_offset); } } optee_os-4.3.0/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c000066400000000000000000000066031464416617300244550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2019, 2021 NXP * * Brief CAAM Configuration. */ #include #include #include #include #include #include #include #include #include #include static const char *dt_caam_match_table = { "fsl,sec-v4.0", }; static const char *dt_jr_match_table = { "fsl,sec-v4.0-job-ring", }; /* * Finds the Job Ring reserved for the Secure Mode in the DTB * * @fdt Reference to the Device Tree * @status Status mask flag of the node to found * @find_node [out] Node offset found */ static paddr_t find_jr_offset(void *fdt, int status, int *find_node) { paddr_t jr_offset = 0; int node = fdt_node_offset_by_compatible(fdt, 0, dt_jr_match_table); for (; node != -FDT_ERR_NOTFOUND; node = fdt_node_offset_by_compatible(fdt, node, dt_jr_match_table)) { HAL_TRACE("Found Job Ring node status @%" PRId32, node); if (fdt_get_status(fdt, node) == status) { HAL_TRACE("Found Job Ring node @%" PRId32, node); jr_offset = fdt_reg_base_address(fdt, node); *find_node = node; break; } } HAL_TRACE("JR Offset return 0x%" PRIxPTR, jr_offset); return jr_offset; } void caam_hal_cfg_get_ctrl_dt(void *fdt, vaddr_t *ctrl_base) { size_t size = 0; int node = 0; paddr_t pctrl_base = 0; *ctrl_base = 0; /* Get the CAAM Node to get the controller base address */ node = fdt_node_offset_by_compatible(fdt, 0, dt_caam_match_table); if (node < 0) return; /* * Map CAAM controller base address as Secure IO if not * already present in the MMU table. * Then get the virtual address of the CAAM controller */ pctrl_base = fdt_reg_base_address(fdt, node); if (pctrl_base == DT_INFO_INVALID_REG) { HAL_TRACE("CAAM control base address not defined"); return; } size = fdt_reg_size(fdt, node); if (size == DT_INFO_INVALID_REG_SIZE) { HAL_TRACE("CAAM control base address size not defined"); return; } *ctrl_base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, pctrl_base, size); if (!*ctrl_base) { EMSG("CAAM control base MMU PA mapping failure"); return; } HAL_TRACE("Map Controller 0x%" PRIxVA, *ctrl_base); } void caam_hal_cfg_get_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg) { paddr_t jr_offset = 0; int jr_it_num = 0; int node = 0; jr_offset = find_jr_offset(fdt, DT_STATUS_OK_SEC, &node); if (jr_offset) { if (!is_embedded_dt(fdt)) { /* Disable JR for Normal World */ if (dt_enable_secure_status(fdt, node)) { EMSG("Not able to disable JR DTB entry"); return; } } /* Get the job ring interrupt */ jr_it_num = dt_get_irq(fdt, node); if (jr_it_num == DT_INFO_INVALID_INTERRUPT) { EMSG("Job Ring interrupt number not defined in DTB"); return; } jrcfg->offset = jr_offset; jrcfg->it_num = jr_it_num; } } void caam_hal_cfg_disable_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg) { int node = fdt_node_offset_by_compatible(fdt, 0, dt_jr_match_table); for (; node != -FDT_ERR_NOTFOUND; node = fdt_node_offset_by_compatible(fdt, node, dt_jr_match_table)) { HAL_TRACE("Found Job Ring node @%" PRId32, node); if (fdt_reg_base_address(fdt, node) == jrcfg->offset) { HAL_TRACE("Disable Job Ring node @%" PRId32, node); if (dt_enable_secure_status(fdt, node)) panic(); break; } } } optee_os-4.3.0/core/drivers/crypto/caam/hal/common/hal_ctrl.c000066400000000000000000000146741464416617300242020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * Brief CAAM Controller Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include #include #include #include #include #include #include uint8_t caam_hal_ctrl_era(vaddr_t baseaddr) { /* Read the number of instance */ uint32_t val = io_caam_read32(baseaddr + CCBVID); return GET_CCBVID_CAAM_ERA(val); } uint8_t caam_hal_ctrl_jrnum(vaddr_t baseaddr) { uint32_t val = 0; uint8_t jrnum = 0; if (caam_hal_ctrl_era(baseaddr) < 10) { val = io_caam_read32(baseaddr + CHANUM_MS); jrnum = GET_CHANUM_MS_JRNUM(val); } else { val = io_caam_read32(baseaddr + JR_VERSION); jrnum = GET_JR_VERSION_JRNUM(val); } return jrnum; } uint8_t caam_hal_ctrl_hash_limit(vaddr_t baseaddr) { uint32_t val = 0; if (caam_hal_ctrl_era(baseaddr) < 10) { /* Read the number of instance */ val = io_caam_read32(baseaddr + CHANUM_LS); if (GET_CHANUM_LS_MDNUM(val)) { /* Hashing is supported */ val = io_caam_read32(baseaddr + CHAVID_LS); val &= BM_CHAVID_LS_MDVID; if (val == CHAVID_LS_MDVID_LP256) return TEE_MAIN_ALGO_SHA256; return TEE_MAIN_ALGO_SHA512; } } else { /* Read the number of instance */ val = io_caam_read32(baseaddr + MDHA_VERSION); if (GET_MDHA_VERSION_MDNUM(val)) { /* Hashing is supported */ val &= BM_MDHA_VERSION_MDVID; if (val == MDHA_VERSION_MDVID_LP256) return TEE_MAIN_ALGO_SHA256; return TEE_MAIN_ALGO_SHA512; } } return UINT8_MAX; } bool caam_hal_ctrl_splitkey_support(vaddr_t baseaddr) { uint32_t val = io_caam_read32(baseaddr + CTPR_LS); return GET_CTPR_LS_SPLIT_KEY(val); } uint8_t caam_hal_ctrl_pknum(vaddr_t baseaddr) { uint32_t val = 0; uint8_t pknum = 0; if (caam_hal_ctrl_era(baseaddr) < 10) { val = io_caam_read32(baseaddr + CHANUM_LS); pknum = GET_CHANUM_LS_PKNUM(val); } else { val = io_caam_read32(baseaddr + PKHA_VERSION); pknum = GET_PKHA_VERSION_PKNUM(val); } return pknum; } #define PRIBLOB_MASK GENMASK_32(1, 0) void caam_hal_ctrl_inc_priblob(vaddr_t baseaddr) { uint32_t val = 0; uint32_t blob = 0; if (!IS_ENABLED(CFG_CAAM_INC_PRIBLOB)) return; val = io_caam_read32(baseaddr + SCFGR); val &= PRIBLOB_MASK; CTRL_TRACE("Reading CAAM PRIBLOB: 0x%"PRIx32, val); if (val == 0 || val == 2) blob = val + 1; else if (val == 1) blob = val + 2; else panic("Error locking PRIBLOB, PRIBLOB =3"); CTRL_TRACE("New CAAM PRIBLOB value: 0x%"PRIx32, blob); val = io_caam_read32(baseaddr + SCFGR); val |= blob; io_caam_write32(baseaddr + SCFGR, val); val = io_caam_read32(baseaddr + SCFGR); val &= PRIBLOB_MASK; CTRL_TRACE("Checking: CAAM PRIBLOB: 0x%"PRIx32 " want: 0x%"PRIx32, val, blob); if (val != blob) panic("Written PRIBLOB and read PRIBLOB do not match!"); } #ifdef CFG_NXP_CAAM_MP_DRV uint8_t caam_hal_ctrl_get_mpcurve(vaddr_t ctrl_addr) { uint32_t val_scfgr = 0; /* * On i.MX8MQ B0, the MP is not usable, hence * return UINT8_MAX */ if (soc_is_imx8mq_b0_layer()) return UINT8_MAX; /* * Verify if the device is closed or not * If device is closed, check get the MPCurve */ if (snvs_is_device_closed()) { /* Get the SCFGR content */ val_scfgr = io_caam_read32(ctrl_addr + SCFGR); /* Get the MPCurve field value - 4 bits */ val_scfgr = (val_scfgr & BM_SCFGR_MPCURVE) >> BS_SCFGR_MPCURVE; /* * If the device is closed and the MPCurve field is 0 * return UINT8_MAX indicating that there is a problem and the * MP can not be supported. */ if (!val_scfgr) return UINT8_MAX; } return val_scfgr; } TEE_Result caam_hal_ctrl_read_mpmr(vaddr_t ctrl_addr, struct caambuf *mpmr) { unsigned int i = 0; uint32_t val = 0; if (mpmr->length < MPMR_NB_REG) { mpmr->length = MPMR_NB_REG; return TEE_ERROR_SHORT_BUFFER; } /* MPMR endianness is reverted between write and read */ for (i = 0; i < MPMR_NB_REG; i += 4) { val = io_caam_read32(ctrl_addr + MPMR + i); mpmr->data[i] = (uint8_t)(val >> 24); mpmr->data[i + 1] = (uint8_t)(val >> 16); mpmr->data[i + 2] = (uint8_t)(val >> 8); mpmr->data[i + 3] = (uint8_t)val; } mpmr->length = MPMR_NB_REG; return TEE_SUCCESS; } bool caam_hal_ctrl_is_mp_set(vaddr_t ctrl_addr) { return io_caam_read32(ctrl_addr + SCFGR) & BM_SCFGR_MPMRL; } void caam_hal_ctrl_fill_mpmr(vaddr_t ctrl_addr, struct caambuf *msg_mpmr) { size_t i = 0; vaddr_t reg = ctrl_addr + MPMR; bool is_filled = false; uint32_t val = 0; size_t min_size = 0; size_t remain_size = 0; /* check if the MPMR is filled */ is_filled = caam_hal_ctrl_is_mp_set(ctrl_addr); DMSG("is_filled = %s", is_filled ? "true" : "false"); if (!is_filled) { /* * Fill the MPMR with the most significant input value and * complete with 0's if value too short. */ min_size = MIN(msg_mpmr->length, (size_t)MPMR_NB_REG); remain_size = min_size % 4; for (i = 0; i < min_size - remain_size; i += 4, reg += 4) { val = msg_mpmr->data[i] | msg_mpmr->data[i + 1] << 8 | msg_mpmr->data[i + 2] << 16 | msg_mpmr->data[i + 3] << 24; io_caam_write32(reg, val); } /* Last input bytes value */ if (remain_size) { val = 0; /* * Fill the MPMR with the 8 bits values * until the end of the message length */ for (i = 0; i < remain_size; i++) val |= msg_mpmr->data[i] << (i * 8); io_caam_write32(reg, val); reg += 4; } /* Complete with 0's */ remain_size = (MPMR_NB_REG - ROUNDUP(msg_mpmr->length, 4)) / 4; for (i = 0; i < remain_size; i++, reg += 4) io_caam_write32(reg, 0x0); /* * Locks the MPMR for writing and remains locked until * the next power-on session. */ io_caam_write32(ctrl_addr + SCFGR, io_caam_read32(ctrl_addr + SCFGR) | BM_SCFGR_MPMRL); DMSG("val_scfgr = %#"PRIx32, io_caam_read32(ctrl_addr + SCFGR)); } } #endif /* CFG_NXP_CAAM_MP_DRV */ #ifdef CFG_NXP_CAAM_SM_DRV vaddr_t caam_hal_ctrl_get_smvaddr(vaddr_t ctrl_addr, paddr_t jr_offset) { /* * The Secure Memory Virtual Base Address contains only the upper * bits of the base address of Secure Memory in this Job Ring's virtual * address space. Since the base address of Secure Memory must be on a * 64 kbyte boundary, the least significant 16 bits are omitted. */ return io_caam_read32(ctrl_addr + JRX_SMVBAR(JRX_IDX(jr_offset))) << 16; } #endif /* CFG_NXP_CAAM_SM_DRV */ optee_os-4.3.0/core/drivers/crypto/caam/hal/common/hal_jr.c000066400000000000000000000143271464416617300236440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Job Rings Hardware Abstration Layer. * Implementation of primitives to access HW */ #include #include #include #include #include #include #include #ifdef CFG_NXP_CAAM_RUNTIME_JR /* * List of common JR registers to save/restore */ static const struct reglist jr_backup[] = { BACKUP_REG(JRX_IRBAR, 2, 0, 0), BACKUP_REG(JRX_IRSR, 1, 0, 0), BACKUP_REG(JRX_ORBAR, 2, 0, 0), BACKUP_REG(JRX_ORSR, 1, 0, 0), BACKUP_REG(JRX_JRCFGR_LS, 1, 0, 0), }; #endif /* CFG_NXP_CAAM_RUNTIME_JR */ enum caam_status caam_hal_jr_reset(vaddr_t baseaddr) { uint16_t timeout = 10000; uint32_t reg_val = 0; /* * Reset is done in 2 steps: * - Flush all pending jobs (Set RESET bit) * - Reset the Job Ring (Set RESET bit second time) */ /* Mask interrupts to poll for reset completion status */ io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); /* Initiate flush (required prior to reset) */ io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET); do { caam_udelay(100); reg_val = io_caam_read32(baseaddr + JRX_JRINTR); reg_val &= BM_JRX_JRINTR_HALT; } while ((reg_val == JRINTR_HALT_ONGOING) && --timeout); if (!timeout || reg_val != JRINTR_HALT_DONE) { EMSG("Failed to flush job ring"); return CAAM_FAILURE; } /* Initiate reset */ timeout = 100; io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET); do { caam_udelay(100); reg_val = io_caam_read32(baseaddr + JRX_JRCR); } while ((reg_val & JRX_JRCR_RESET) && --timeout); if (!timeout) { EMSG("Failed to reset job ring"); return CAAM_FAILURE; } return CAAM_NO_ERROR; } void caam_hal_jr_config(vaddr_t baseaddr, uint8_t nbjobs, uint64_t inrings, uint64_t outrings) { uint32_t value = 0; /* Setup the JR input queue */ #if defined(CFG_CAAM_64BIT) && defined(CFG_CAAM_LITTLE_ENDIAN) io_caam_write32(baseaddr + JRX_IRBAR, inrings); io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings >> 32); #else io_caam_write32(baseaddr + JRX_IRBAR, inrings >> 32); io_caam_write32(baseaddr + JRX_IRBAR + 4, inrings); #endif io_caam_write32(baseaddr + JRX_IRSR, nbjobs); /* Setup the JR output queue */ #if defined(CFG_CAAM_64BIT) && defined(CFG_CAAM_LITTLE_ENDIAN) io_caam_write32(baseaddr + JRX_ORBAR, outrings); io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings >> 32); #else io_caam_write32(baseaddr + JRX_ORBAR, outrings >> 32); io_caam_write32(baseaddr + JRX_ORBAR + 4, outrings); #endif io_caam_write32(baseaddr + JRX_ORSR, nbjobs); /* Disable the JR interrupt */ caam_hal_jr_disable_itr(baseaddr); /* * Configure interrupt and disable it: * Optimization to generate an interrupt either when there are * half of the job done * or when there is a job done and 10 clock cycles elapsed without * new job completion */ value = JRX_JRCFGR_LS_ICTT(10); value |= JRX_JRCFGR_LS_ICDCT(nbjobs / 2); value |= JRX_JRCFGR_LS_ICEN; value |= JRX_JRCFGR_LS_IMSK; io_caam_write32(baseaddr + JRX_JRCFGR_LS, value); #ifdef CFG_NXP_CAAM_RUNTIME_JR caam_pwr_add_backup(baseaddr, jr_backup, ARRAY_SIZE(jr_backup)); #endif } uint32_t caam_hal_jr_read_nbslot_available(vaddr_t baseaddr) { return io_caam_read32(baseaddr + JRX_IRSAR); } void caam_hal_jr_add_newjob(vaddr_t baseaddr) { io_caam_write32(baseaddr + JRX_IRJAR, 1); } uint32_t caam_hal_jr_get_nbjob_done(vaddr_t baseaddr) { return io_caam_read32(baseaddr + JRX_ORSFR); } void caam_hal_jr_del_job(vaddr_t baseaddr) { io_caam_write32(baseaddr + JRX_ORJRR, 1); } #ifdef CFG_CAAM_ITR void caam_hal_jr_disable_itr(vaddr_t baseaddr) { io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI); } void caam_hal_jr_enable_itr(vaddr_t baseaddr) { io_mask32(baseaddr + JRX_JRCFGR_LS, ~JRX_JRCFGR_LS_IMSK, JRX_JRCFGR_LS_IMSK); } #else void caam_hal_jr_disable_itr(vaddr_t baseaddr __unused) {} void caam_hal_jr_enable_itr(vaddr_t baseaddr __unused) {} #endif /* CFG_CAAM_ITR */ bool caam_hal_jr_check_ack_itr(vaddr_t baseaddr) { uint32_t val = 0; val = io_caam_read32(baseaddr + JRX_JRINTR); if ((val & JRX_JRINTR_JRI) == JRX_JRINTR_JRI) { /* Acknowledge interrupt */ io_setbits32(baseaddr + JRX_JRINTR, JRX_JRINTR_JRI); return true; } return false; } enum caam_status caam_hal_jr_halt(vaddr_t baseaddr) { uint16_t timeout = 10000; uint32_t val = 0; /* Mask interrupts to poll for completion status */ io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); /* Request Job ring halt */ io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_PARK); /* Check if there is a job running */ val = io_caam_read32(baseaddr + JRX_IRSR); if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) && (io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY)) return CAAM_NO_ERROR; /* Wait until all jobs complete */ do { caam_udelay(10); val = io_caam_read32(baseaddr + JRX_JRINTR); val &= BM_JRX_JRINTR_HALT; } while ((val != JRINTR_HALT_DONE) && --timeout); if (!timeout) return CAAM_BUSY; return CAAM_NO_ERROR; } enum caam_status caam_hal_jr_flush(vaddr_t baseaddr) { uint16_t timeout = 10000; uint32_t val = 0; /* Mask interrupts to poll for completion status */ io_setbits32(baseaddr + JRX_JRCFGR_LS, JRX_JRCFGR_LS_IMSK); /* Request Job ring to flush input queue */ io_caam_write32(baseaddr + JRX_JRCR, JRX_JRCR_RESET); /* Check if there is a job running */ val = io_caam_read32(baseaddr + JRX_IRSR); if ((caam_hal_jr_read_nbslot_available(baseaddr) == val) && (io_caam_read32(baseaddr + JRX_CSTA) != JRX_CSTA_BSY)) return CAAM_NO_ERROR; /* Wait until all jobs complete */ do { caam_udelay(10); val = io_caam_read32(baseaddr + JRX_JRINTR); val &= BM_JRX_JRINTR_HALT; } while ((val == JRINTR_HALT_ONGOING) && --timeout); if (!timeout) return CAAM_BUSY; return CAAM_NO_ERROR; } void caam_hal_jr_resume(vaddr_t baseaddr) { io_caam_write32(baseaddr + JRX_JRINTR, JRINTR_HALT_RESUME); caam_hal_jr_enable_itr(baseaddr); } uint8_t caam_hal_jr_input_index(vaddr_t baseaddr) { return io_caam_read32(baseaddr + JRX_IRRIR) >> 2; } uint8_t caam_hal_jr_output_index(vaddr_t baseaddr) { return io_caam_read32(baseaddr + JRX_ORWIR) >> 3; } optee_os-4.3.0/core/drivers/crypto/caam/hal/common/hal_rng.c000066400000000000000000000115071464416617300240140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Brief CAAM Random Number Generator Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include #include #include enum caam_status __weak caam_hal_rng_instantiated(vaddr_t baseaddr) { uint32_t vid = 0; uint32_t nb_sh = 0; uint32_t status = 0; /* RNG version < 4 and RNG state handle is already instantiated */ if (caam_hal_ctrl_era(baseaddr) < 10) { vid = io_caam_read32(baseaddr + CHAVID_LS); if (GET_CHAVID_LS_RNGVID(vid) < 4) return CAAM_NO_ERROR; } else { vid = io_caam_read32(baseaddr + RNG_VERSION); if (GET_RNG_VERSION_VID(vid) < 4) return CAAM_NO_ERROR; } /* Get the Number of State Handles */ nb_sh = caam_hal_rng_get_nb_sh(baseaddr); /* Read the RNG Status and checks if all channels are instantiatied */ status = caam_hal_rng_get_sh_status(baseaddr); if (status != GENMASK_32(nb_sh - 1, 0)) return CAAM_NOT_INIT; return CAAM_NO_ERROR; } uint32_t caam_hal_rng_get_nb_sh(vaddr_t baseaddr) { uint32_t reg = 0; reg = io_caam_read32(baseaddr + CTPR_MS); return GET_CTPR_MS_RNG_I(reg); } uint32_t caam_hal_rng_get_sh_status(vaddr_t baseaddr) { return io_caam_read32(baseaddr + RNG_STA) & (RNG_STA_IF1 | RNG_STA_IF0); } bool caam_hal_rng_key_loaded(vaddr_t baseaddr) { return io_caam_read32(baseaddr + RNG_STA) & RNG_STA_SKVN; } /* * This function will be overridden for i.MX8QX and i.MX8DX platforms. */ bool __weak caam_hal_rng_pr_enabled(vaddr_t baseaddr) { uint32_t bitmask = RNG_STA_PR0; if (caam_hal_rng_get_nb_sh(baseaddr) > 1) bitmask |= RNG_STA_PR1; return (io_caam_read32(baseaddr + RNG_STA) & bitmask) == bitmask; } enum caam_status caam_hal_rng_kick(vaddr_t baseaddr, uint32_t inc_delay) { uint32_t val = 0; uint32_t ent_delay = TRNG_SDCTL_ENT_DLY_MIN + inc_delay; if (ent_delay > TRNG_SDCTL_ENT_DLY_MAX) return CAAM_OUT_OF_BOUND; /* * Switch RNG in program mode * Setting both RTMCTL:PRGM and RTMCTL:TRNG_ACC causes TRNG to * properly invalidate the entropy in the entropy register and * force re-generation */ io_setbits32(baseaddr + TRNG_MCTL, TRNG_MCTL_PRGM | TRNG_MCTL_ACC); /* * Configure the RNG Entropy Delay * Performance-wise, it does not make sense to * set the delay to a value that is lower * than the last one that worked (i.e. the state handles * were instantiated correctly). Thus, instead of wasting * time trying to set the values controlling the sample * frequency, the function simply returns. */ val = io_caam_read32(baseaddr + TRNG_SDCTL); val = GET_TRNG_SDCTL_ENT_DLY(val); if (ent_delay < val) { /* * In this case do the programmation anyway because on some * device the other registers value can be wrong. */ ent_delay = val; } io_caam_write32(baseaddr + TRNG_SDCTL, TRNG_SDCTL_ENT_DLY(ent_delay) | TRNG_SDCTL_SAMP_SIZE(512)); /* min. freq. count, equal to 1/4 of the entropy sample length */ io_caam_write32(baseaddr + TRNG_FRQMIN, ent_delay >> 2); /* max. freq. count, equal to 16 times the entropy sample length */ io_caam_write32(baseaddr + TRNG_FRQMAX, ent_delay << 4); io_caam_write32(baseaddr + TRNG_RTSCMISC, TRNG_RTSCMISC_RTY_CNT(2) | TRNG_RTSCMISC_LRUN_MAX(32)); io_caam_write32(baseaddr + TRNG_RTPKRRNG, TRNG_RTPKRRNG_PKR_RNG(570)); io_caam_write32(baseaddr + TRNG_RTPKRMAX, TRNG_RTPKRMAX_PKR_MAX(1600)); io_caam_write32(baseaddr + TRNG_RTSCML, TRNG_RTSCML_MONO_RNG(122) | TRNG_RTSCML_MONO_MAX(317)); io_caam_write32(baseaddr + TRNG_RTSCR1L, TRNG_RTSCR1L_RUN1_RNG(80) | TRNG_RTSCR1L_RUN1_MAX(107)); io_caam_write32(baseaddr + TRNG_RTSCR2L, TRNG_RTSCR2L_RUN2_RNG(57) | TRNG_RTSCR2L_RUN2_MAX(62)); io_caam_write32(baseaddr + TRNG_RTSCR3L, TRNG_RTSCR3L_RUN3_RNG(39) | TRNG_RTSCR3L_RUN3_MAX(39)); io_caam_write32(baseaddr + TRNG_RTSCR4L, TRNG_RTSCR4L_RUN4_RNG(27) | TRNG_RTSCR4L_RUN4_MAX(26)); io_caam_write32(baseaddr + TRNG_RTSCR5L, TRNG_RTSCR5L_RUN5_RNG(19) | TRNG_RTSCR5L_RUN5_MAX(18)); io_caam_write32(baseaddr + TRNG_RTSCR6PL, TRNG_RTSCR5L_RUN5_RNG(18) | TRNG_RTSCR5L_RUN5_MAX(17)); val = io_caam_read32(baseaddr + TRNG_MCTL); /* * Select raw sampling in both entropy shifter * and statistical checker */ val &= ~BM_TRNG_MCTL_SAMP_MODE; val |= TRNG_MCTL_SAMP_MODE_RAW_ES_SC; /* Put RNG4 into run mode with handling CAAM/RNG4-TRNG Errata */ val &= ~(TRNG_MCTL_PRGM | TRNG_MCTL_ACC); io_caam_write32(baseaddr + TRNG_MCTL, val); /* * Clear the ERR bit in RTMCTL if set. The TRNG error can occur when * the RNG clock is not within 1/2x to 8x the system clock. * This error is possible if ROM code does not initialize the system * PLLs immediately after PoR. */ io_setbits32(baseaddr + TRNG_MCTL, TRNG_MCTL_ERR); return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/hal/common/hal_sm.c000066400000000000000000000131141464416617300236410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019, 2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Issue a Secure Memory Command to the @page and @partition. * Returns the command status when completed * * @jr_base JR virtual base address * @page Memory Page * @partition Partition * @cmd Command to sent */ static uint32_t issue_cmd(vaddr_t jr_base, unsigned int page, unsigned int partition, uint8_t cmd) { uint32_t status = 0; uint64_t timeout_ref = timeout_init_us(10000); assert(jr_base); /* Send cmd */ io_caam_write32(jr_base + SM_SMCR, SM_SMCR_PAGE(page) | SM_SMCR_PRTN(partition) | SM_SMCR_CMD(cmd)); /* Wait for the command to complete */ do { if (timeout_elapsed(timeout_ref)) break; status = io_caam_read32(jr_base + SM_SMCSR); } while (SM_SMCSR_CERR(status) == SM_SMCSR_CERR_NOT_COMPLETED); return io_caam_read32(jr_base + SM_SMCSR); } enum caam_status caam_hal_sm_check_page_partition(vaddr_t jr_base, const struct caam_sm_page_desc *page_desc) { uint32_t val = 0; if (!jr_base || !page_desc) return CAAM_BAD_PARAM; val = io_caam_read32(jr_base + SMVID_MS); if (page_desc->page + page_desc->page_count > GET_SMVID_MS_MAX_NPAG(val) || page_desc->partition > GET_SMVID_MS_NPRT(val)) return CAAM_BAD_PARAM; return CAAM_NO_ERROR; } size_t caam_hal_sm_get_pages_size(vaddr_t jr_base, unsigned int page) { size_t page_size = 0; page_size = GET_SMVID_LS_PSIZ(io_caam_read32(jr_base + SMVID_LS)); return SHIFT_U32(1, page_size) * (size_t)page * 1024; } bool caam_hal_sm_prtn_is_free(vaddr_t jr_base, unsigned int partition) { return SM_SMPO_OWNER(io_caam_read32(jr_base + SM_SMPO), partition) == SMPO_PO_AVAIL; } bool caam_hal_sm_prtn_is_owned(vaddr_t jr_base, unsigned int partition) { return SM_SMPO_OWNER(io_caam_read32(jr_base + SM_SMPO), partition) == SMPO_PO_OWNED; } void caam_hal_sm_set_access_all_group(vaddr_t jr_base, unsigned int partition) { io_caam_write32(jr_base + SM_SMAG1(partition), UINT32_MAX); io_caam_write32(jr_base + SM_SMAG2(partition), UINT32_MAX); } void caam_hal_sm_set_access_group(vaddr_t jr_base, unsigned int partition, uint32_t grp1, uint32_t grp2) { if (!jr_base) return; if (grp1 != UINT32_MAX) io_caam_write32(jr_base + SM_SMAG1(partition), SHIFT_U32(1, grp1)); if (grp2 != UINT32_MAX) io_caam_write32(jr_base + SM_SMAG2(partition), SHIFT_U32(1, grp2)); } void caam_hal_sm_open_access_perm(vaddr_t jr_base, unsigned int partition) { io_caam_write32(jr_base + SM_SMAPR(partition), SM_SMAPR_GRP1(UINT8_MAX) | SM_SMAPR_GRP2(UINT8_MAX)); } void caam_hal_sm_set_access_perm(vaddr_t jr_base, unsigned int partition, unsigned int grp1_perm, unsigned int grp2_perm) { io_caam_write32(jr_base + SM_SMAPR(partition), SM_SMAPR_GRP1(grp1_perm) | SM_SMAPR_GRP2(grp2_perm) | SM_SMAPR_CSP | SM_SMAPR_SMAP_LCK | SM_SMAPR_SMAG_LCK); } enum caam_status caam_hal_sm_allocate_page(vaddr_t jr_base, const struct caam_sm_page_desc *page_desc) { unsigned int page = 0; uint32_t status = 0; if (!jr_base || !page_desc) return CAAM_BAD_PARAM; /* Check if pages are available */ for (page = page_desc->page; page < page_desc->page + page_desc->page_count; page++) { status = issue_cmd(jr_base, page, page_desc->partition, SM_SMCR_PAGE_INQ); if (SM_SMCSR_PO(status) != SM_SMCSR_PO_AVAILABLE) return CAAM_BUSY; } /* Allocate pages to partition */ for (page = page_desc->page; page < page_desc->page + page_desc->page_count; page++) { status = issue_cmd(jr_base, page, page_desc->partition, SM_SMCR_PAGE_ALLOC); if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR) return CAAM_FAILURE; } /* Check if pages are available */ for (page = page_desc->page; page < page_desc->page + page_desc->page_count; page++) { status = issue_cmd(jr_base, page, page_desc->partition, SM_SMCR_PAGE_INQ); if (SM_SMCSR_PO(status) != SM_SMCSR_PO_OWNED || SM_SMCSR_PRTN(status) != page_desc->partition) return CAAM_FAILURE; } return CAAM_NO_ERROR; } enum caam_status caam_hal_sm_deallocate_partition(vaddr_t jr_base, unsigned int partition) { unsigned int status = 0; if (!jr_base) return CAAM_BAD_PARAM; /* De-Allocate partition and so all partition's page */ status = issue_cmd(jr_base, 0, partition, SM_SMCR_PARTITION_DEALLOC); if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR) return CAAM_FAILURE; return CAAM_NO_ERROR; } enum caam_status caam_hal_sm_deallocate_pages(vaddr_t jr_base, const struct caam_sm_page_desc *page_desc) { unsigned int page = 0; uint32_t status = 0; if (!jr_base || !page_desc) return CAAM_BAD_PARAM; for (page = page_desc->page; page < page_desc->page + page_desc->page_count; page++) { /* Deallocate page, set partition as not used */ status = issue_cmd(jr_base, page, 0, SM_SMCR_PAGE_DEALLOC); if (SM_SMCSR_AERR(status) != SM_SMCSR_AERR_NO_ERROR) return CAAM_FAILURE; } return CAAM_NO_ERROR; } register_phys_mem(MEM_AREA_IO_SEC, SECMEM_BASE, SECMEM_SIZE); vaddr_t caam_hal_sm_get_base(void) { vaddr_t sm_base = 0; void *fdt = NULL; fdt = get_dt(); if (fdt) caam_hal_sm_get_base_dt(fdt, &sm_base); if (!sm_base) sm_base = core_mmu_get_va(SECMEM_BASE, MEM_AREA_IO_SEC, SECMEM_SIZE); return sm_base; } optee_os-4.3.0/core/drivers/crypto/caam/hal/common/registers/000077500000000000000000000000001464416617300242415ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/common/registers/jr_regs.h000066400000000000000000000031701464416617300260460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief Job Ring Registers. */ #ifndef __JR_REGS_H__ #define __JR_REGS_H__ #include /* Job Ring Block Register Size */ #define JRX_BLOCK_SIZE CFG_JR_BLOCK_SIZE #define JRX_IDX(offset) (((offset) - JRX_BLOCK_SIZE) / JRX_BLOCK_SIZE) /* * Input Ring */ /* Base Address */ #define JRX_IRBAR 0x0000 /* Size */ #define JRX_IRSR 0x000C /* Slots Available */ #define JRX_IRSAR 0x0014 /* Jobs Added */ #define JRX_IRJAR 0x001C /* * Output Ring */ /* Base Address */ #define JRX_ORBAR 0x0020 /* Size */ #define JRX_ORSR 0x002C /* Jobs Removed */ #define JRX_ORJRR 0x0034 /* Slots Full */ #define JRX_ORSFR 0x003C /* Interrupt Status */ #define JRX_JRINTR 0x004C #define BM_JRX_JRINTR_HALT SHIFT_U32(0x3, 2) #define JRINTR_HALT_RESUME SHIFT_U32(0x2, 2) #define JRINTR_HALT_ONGOING SHIFT_U32(0x1, 2) #define JRINTR_HALT_DONE SHIFT_U32(0x2, 2) #define JRX_JRINTR_JRI BIT32(0) /* Configuration */ #define JRX_JRCFGR_LS 0x0054 #define JRX_JRCFGR_LS_ICTT(val) SHIFT_U32((val) & 0xFFFF, 16) #define JRX_JRCFGR_LS_ICDCT(val) SHIFT_U32((val) & 0xFF, 8) #define JRX_JRCFGR_LS_ICEN BIT32(1) #define JRX_JRCFGR_LS_IMSK BIT32(0) /* Input Ring Read Index */ #define JRX_IRRIR 0x005C /* Output Ring Write Index */ #define JRX_ORWIR 0x0064 /* Command */ #define JRX_JRCR 0x006C #define JRX_JRCR_PARK BIT32(1) #define JRX_JRCR_RESET BIT32(0) /* CAAM Status register - duplicated */ #define JRX_CSTA 0x0FD4 #define JRX_CSTA_TRNG_IDLE BIT32(2) #define JRX_CSTA_IDLE BIT32(1) #define JRX_CSTA_BSY BIT32(0) #endif /* __JR_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/common/registers/rng_regs.h000066400000000000000000000103501464416617300262170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Brief Random Number Generator Registers. */ #ifndef __RNG_REGS_H__ #define __RNG_REGS_H__ #include /* * RNG Test Registers */ /* Miscellaneous Control */ #define TRNG_MCTL 0x0600 #define TRNG_MCTL_PRGM BIT32(16) #define TRNG_MCTL_ERR BIT32(12) #define TRNG_MCTL_ACC BIT32(5) #define BM_TRNG_MCTL_SAMP_MODE SHIFT_U32(0x3, 0) /* Use raw data in both entropy shifter and statistical checker */ #define TRNG_MCTL_SAMP_MODE_RAW_ES_SC SHIFT_U32(1, 0) /* Seed Control */ #define TRNG_SDCTL 0x0610 #define BM_TRNG_SDCTL_ENT_DLY SHIFT_U32(0xFFFF, 16) #define GET_TRNG_SDCTL_ENT_DLY(val) (((val) & BM_TRNG_SDCTL_ENT_DLY) >> 16) #define TRNG_SDCTL_ENT_DLY(val) SHIFT_U32(((val) & 0xFFFF), 16) #define TRNG_SDCTL_SAMP_SIZE(val) ((val) & 0xFFFF) #ifdef CFG_MX6SX #define TRNG_SDCTL_ENT_DLY_MIN 12000 #else #define TRNG_SDCTL_ENT_DLY_MIN 3200 #endif #define TRNG_SDCTL_ENT_DLY_MAX 12800 /* Frequency Count Minimum Limit */ #define TRNG_FRQMIN 0x0618 /* Frequency Count Maximum Limit */ #define TRNG_FRQMAX 0x061C /* Statistical Check Miscellaneous */ #define TRNG_RTSCMISC 0x0604 #define BM_TRNG_RTSCMISC_RTY_CNT SHIFT_U32(0xF, 16) #define TRNG_RTSCMISC_RTY_CNT(val) SHIFT_U32(((val) & (0xF)), 16) #define BM_TRNG_RTSCMISC_LRUN_MAX SHIFT_U32(0xFF, 0) #define TRNG_RTSCMISC_LRUN_MAX(val) SHIFT_U32(((val) & (0xFF)), 0) /* Poker Range */ #define TRNG_RTPKRRNG 0x0608 #define BM_TRNG_RTPKRRNG_PKR_RNG SHIFT_U32(0xFFFF, 0) #define TRNG_RTPKRRNG_PKR_RNG(val) SHIFT_U32(((val) & (0xFFFF)), 0) /* Poker Maximum Limit */ #define TRNG_RTPKRMAX 0x060C #define BM_TRNG_RTPKRMAX_PKR_MAX SHIFT_U32(0xFFFFFF, 0) #define TRNG_RTPKRMAX_PKR_MAX(val) SHIFT_U32(((val) & (0xFFFFFF)), 0) /* Statistical Check Monobit Limit */ #define TRNG_RTSCML 0x0620 #define BM_TRNG_RTSCML_MONO_RNG SHIFT_U32(0xFFFF, 16) #define TRNG_RTSCML_MONO_RNG(val) SHIFT_U32(((val) & (0xFFFF)), 16) #define BM_TRNG_RTSCML_MONO_MAX SHIFT_U32(0xFFFF, 0) #define TRNG_RTSCML_MONO_MAX(val) SHIFT_U32(((val) & (0xFFFF)), 0) /* Statistical Check Run Length 1 Limit */ #define TRNG_RTSCR1L 0x0624 #define BM_TRNG_RTSCR1L_RUN1_RNG SHIFT_U32(0x7FFF, 16) #define TRNG_RTSCR1L_RUN1_RNG(val) SHIFT_U32(((val) & (0x7FFF)), 16) #define BM_TRNG_RTSCR1L_RUN1_MAX SHIFT_U32(0x7FFF, 0) #define TRNG_RTSCR1L_RUN1_MAX(val) SHIFT_U32(((val) & (0x7FFF)), 0) /* Statistical Check Run Length 2 Limit */ #define TRNG_RTSCR2L 0x0628 #define BM_TRNG_RTSCR2L_RUN2_RNG SHIFT_U32(0x3FFF, 16) #define TRNG_RTSCR2L_RUN2_RNG(val) SHIFT_U32(((val) & (0x3FFF)), 16) #define BM_TRNG_RTSCR2L_RUN2_MAX SHIFT_U32(0x3FFF, 0) #define TRNG_RTSCR2L_RUN2_MAX(val) SHIFT_U32(((val) & (0x3FFF)), 0) /* Statistical Check Run Length 3 Limit */ #define TRNG_RTSCR3L 0x062C #define BM_TRNG_RTSCR3L_RUN3_RNG SHIFT_U32(0x1FFF, 16) #define TRNG_RTSCR3L_RUN3_RNG(val) SHIFT_U32(((val) & (0x1FFF)), 16) #define BM_TRNG_RTSCR3L_RUN3_MAX SHIFT_U32(0x1FFF, 0) #define TRNG_RTSCR3L_RUN3_MAX(val) SHIFT_U32(((val) & (0x1FFF)), 0) /* Statistical Check Run Length 4 Limit */ #define TRNG_RTSCR4L 0x0630 #define BM_TRNG_RTSCR4L_RUN4_RNG SHIFT_U32(0xFFF, 16) #define TRNG_RTSCR4L_RUN4_RNG(val) SHIFT_U32(((val) & (0xFFF)), 16) #define BM_TRNG_RTSCR4L_RUN4_MAX SHIFT_U32(0xFFF, 0) #define TRNG_RTSCR4L_RUN4_MAX(val) SHIFT_U32(((val) & (0xFFF)), 0) /* Statistical Check Run Length 5 Limit */ #define TRNG_RTSCR5L 0x0634 #define BM_TRNG_RTSCR5L_RUN5_RNG SHIFT_U32(0x7FF, 16) #define TRNG_RTSCR5L_RUN5_RNG(val) SHIFT_U32(((val) & (0x7FF)), 16) #define BM_TRNG_RTSCR5L_RUN5_MAX SHIFT_U32(0x7FF, 0) #define TRNG_RTSCR5L_RUN5_MAX(val) SHIFT_U32(((val) & (0x7FF)), 0) /* Statistical Check Run Length 6+ Limit */ #define TRNG_RTSCR6PL 0x0638 #define BM_TRNG_RTSCR6PL_RUN6P_RNG SHIFT_U32(0x7FF, 16) #define TRNG_RTSCR6PL_RUN6P_RNG(val) SHIFT_U32(((val) & (0x7FF)), 16) #define BM_TRNG_RTSCR6PL_RUN6P_MAX SHIFT_U32(0x7FF, 0) #define TRNG_RTSCR6PL_RUN6P_MAX(val) SHIFT_U32(((val) & (0x7FF)), 0) /* * RNG Registers */ /* Status */ #define RNG_STA 0x06C0 #define RNG_STA_SKVN BIT32(30) #define RNG_STA_IF1 BIT32(1) #define RNG_STA_IF0 BIT32(0) #define RNG_STA_PR0 BIT32(4) #define RNG_STA_PR1 BIT32(5) #endif /* __RNG_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/common/registers/sm_regs.h000066400000000000000000000031261464416617300260530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 NXP */ #ifndef __SM_REGS_H__ #define __SM_REGS_H__ #include /* Access Permission */ #define SM_SMAPR(prtn) (0x0A04 + (prtn) * 16) #define SM_SMAPR_GRP1(perm) SHIFT_U32((perm) & 0xF, 0) #define SM_SMAPR_GRP2(perm) SHIFT_U32((perm) & 0xF, 4) #define SM_SMAPR_CSP BIT32(15) #define SM_SMAPR_SMAP_LCK BIT32(13) #define SM_SMAPR_SMAG_LCK BIT32(12) /* Access Group */ #define SM_SMAG2(prtn) (0x0A08 + (prtn) * 16) #define SM_SMAG1(prtn) (0x0A0C + (prtn) * 16) /* Command */ #define SM_SMCR 0x0BE4 #define SM_SMCR_PAGE(page) SHIFT_U32((page) & UINT16_MAX, 16) #define SM_SMCR_PRTN(prtn) SHIFT_U32((prtn) & 0xF, 8) #define SM_SMCR_CMD(cmd) SHIFT_U32((cmd) & 0xF, 0) #define SM_SMCR_PAGE_ALLOC 0x1 #define SM_SMCR_PAGE_DEALLOC 0x2 #define SM_SMCR_PARTITION_DEALLOC 0x3 #define SM_SMCR_PAGE_INQ 0x5 /* Command Status */ #define SM_SMCSR 0x0BEC #define SM_SMCSR_CERR(val) (((val) >> 14) & 0x3) #define SM_SMCSR_CERR_NO_ERROR 0x0 #define SM_SMCSR_CERR_NOT_COMPLETED 0x1 #define SM_SMCSR_AERR(val) (((val) >> 12) & 0x3) #define SM_SMCSR_AERR_NO_ERROR 0x0 #define SM_SMCSR_PO(val) (((val) >> 6) & 0x3) #define SM_SMCSR_PO_AVAILABLE 0x0 #define SM_SMCSR_PO_UNKNOWN 0x1 #define SM_SMCSR_PO_OWNED_BY_OTHER 0x2 #define SM_SMCSR_PO_OWNED 0x3 #define SM_SMCSR_PRTN(val) ((val) & 0x3) /* Partition Owners */ #define SM_SMPO 0x0FBC #define SM_SMPO_PART(prtn) ((prtn) * 2) #define SM_SMPO_OWNER(val, prtn) (((val) >> SM_SMPO_PART(prtn)) & 0x3) #define SMPO_PO_AVAIL 0x0 #define SMPO_PO_OWNED 0x3 #endif /* __SM_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/common/registers/version_regs.h000066400000000000000000000053711464416617300271250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2020 NXP * * Brief Version Registers. */ #ifndef __VERSION_REGS_H__ #define __VERSION_REGS_H__ #include /* Compile Time Parameters */ #define CTPR_MS 0x0FA8 #define BM_CTPR_MS_RNG_I SHIFT_U32(0x7, 8) #define GET_CTPR_MS_RNG_I(val) (((val) & BM_CTPR_MS_RNG_I) >> 8) #define CTPR_LS 0x0FAC #define BM_CTPR_LS_SPLIT_KEY BIT(14) #define GET_CTPR_LS_SPLIT_KEY(val) (((val) & BM_CTPR_LS_SPLIT_KEY) >> 14) /* Secure Memory Version ID */ #define SMVID_MS 0x0FD8 #define BM_SMVID_MS_MAX_NPAG SHIFT_U32(0x3FF, 16) #define GET_SMVID_MS_MAX_NPAG(val) (((val) & BM_SMVID_MS_MAX_NPAG) >> 16) #define BM_SMVID_MS_NPRT SHIFT_U32(0xF, 12) #define GET_SMVID_MS_NPRT(val) (((val) & BM_SMVID_MS_NPRT) >> 12) #define SMVID_LS 0x0FDC #define BM_SMVID_LS_PSIZ SHIFT_U32(0x7, 16) #define GET_SMVID_LS_PSIZ(val) (((val) & BM_SMVID_LS_PSIZ) >> 16) /* CHA Cluster Block Version ID */ #define CCBVID 0x0FE4 #define BM_CCBVID_CAAM_ERA SHIFT_U32(0xFF, 24) #define GET_CCBVID_CAAM_ERA(val) (((val) & BM_CCBVID_CAAM_ERA) >> 24) /* CHA Version ID */ #define CHAVID_LS 0x0FEC #define BM_CHAVID_LS_RNGVID SHIFT_U32(0xF, 16) #define GET_CHAVID_LS_RNGVID(val) (((val) & BM_CHAVID_LS_RNGVID) >> 16) #define BM_CHAVID_LS_MDVID SHIFT_U32(0xF, 12) #define CHAVID_LS_MDVID_LP256 SHIFT_U32(0, 12) /* CHA Number */ #define CHANUM_MS 0x0FF0 #define BM_CHANUM_MS_JRNUM SHIFT_U32(0xF, 28) #define GET_CHANUM_MS_JRNUM(val) (((val) & BM_CHANUM_MS_JRNUM) >> 28) #define CHANUM_LS 0x0FF4 #define BM_CHANUM_LS_PKNUM SHIFT_U32(0xF, 28) #define GET_CHANUM_LS_PKNUM(val) (((val) & BM_CHANUM_LS_PKNUM) >> 28) #define BM_CHANUM_LS_MDNUM SHIFT_U32(0xF, 12) #define GET_CHANUM_LS_MDNUM(val) (((val) & BM_CHANUM_LS_MDNUM) >> 12) /* PKHA Version for Era > 10 */ #define PKHA_VERSION 0x0E8C #define BM_PKHA_VERSION_PKNUM 0xFF #define GET_PKHA_VERSION_PKNUM(val) ((val) & BM_PKHA_VERSION_PKNUM) /* MDHA Version for Era > 10 */ #define MDHA_VERSION 0xE94 #define BM_MDHA_VERSION_MDNUM 0xFF #define GET_MDHA_VERSION_MDNUM(val) ((val) & BM_MDHA_VERSION_MDNUM) #define BM_MDHA_VERSION_MDVID SHIFT_U32(0xFF, 24) #define MDHA_VERSION_MDVID_LP256 SHIFT_U32(0, 24) /* RNG Version for Era > 10 */ #define RNG_VERSION 0x0EF8 #define BM_RNG_VERSION_VID SHIFT_U32(0xFF, 24) #define GET_RNG_VERSION_VID(val) ((val) & BM_RNG_VERSION_VID) /* JR Version for Era > 10 */ #define JR_VERSION 0x0EF8 #define BM_JR_VERSION_JRNUM 0xFF #define GET_JR_VERSION_JRNUM(val) ((val) & BM_JR_VERSION_JRNUM) #endif /* __VERSION_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/common/sub.mk000066400000000000000000000003421464416617300233530ustar00rootroot00000000000000incdirs-y += ../../include incdirs-y += ../$(CAAM_HAL_DIR) incdirs-y += . srcs-$(CFG_DT) += hal_cfg_dt.c srcs-y += hal_cfg.c srcs-y += hal_rng.c srcs-y += hal_jr.c srcs-y += hal_ctrl.c srcs-$(CFG_NXP_CAAM_SM_DRV) += hal_sm.c optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/000077500000000000000000000000001464416617300222125ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx6.c000066400000000000000000000015151464416617300245470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Clock functions. */ #include #include #include #include void caam_hal_clk_enable(bool enable) { vaddr_t ccm_base = (vaddr_t)phys_to_virt(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); uint32_t reg = 0; uint32_t mask = 0; reg = io_read32(ccm_base + CCM_CCGR0); mask = BM_CCM_CCGR0_CAAM_WRAPPER_IPG | BM_CCM_CCGR0_CAAM_WRAPPER_ACLK | BM_CCM_CCGR0_CAAM_SECURE_MEM; if (enable) reg |= mask; else reg &= ~mask; io_write32(ccm_base + CCM_CCGR0, reg); if (!soc_is_imx6ul()) { /* EMI slow clk */ reg = io_read32(ccm_base + CCM_CCGR6); mask = BM_CCM_CCGR6_EMI_SLOW; if (enable) reg |= mask; else reg &= ~mask; io_write32(ccm_base + CCM_CCGR6, reg); } } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7.c000066400000000000000000000010361464416617300245460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Clock functions. */ #include #include #include #include void caam_hal_clk_enable(bool enable) { vaddr_t ccm_base = (vaddr_t)phys_to_virt(CCM_BASE, MEM_AREA_IO_SEC, 1); if (enable) { io_write32(ccm_base + CCM_CCGRx_SET(CCM_CLOCK_DOMAIN_CAAM), CCM_CCGRx_ALWAYS_ON(0)); } else { io_write32(ccm_base + CCM_CCGRx_CLR(CCM_CLOCK_DOMAIN_CAAM), CCM_CCGRx_ALWAYS_ON(0)); } } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/hal_clk_mx7ulp.c000066400000000000000000000007541464416617300252750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Clock functions. */ #include #include #include #include void caam_hal_clk_enable(bool enable) { vaddr_t pcc2_base = (vaddr_t)phys_to_virt(PCC2_BASE, MEM_AREA_IO_SEC, PCC_CAAM + sizeof(uint32_t)); if (enable) io_write32(pcc2_base + PCC_CAAM, PCC_ENABLE_CLOCK); else io_write32(pcc2_base + PCC_CAAM, PCC_DISABLE_CLOCK); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/hal_ctrl.c000066400000000000000000000025001464416617300241430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Controller Hardware Abstration Layer. * Implementation of primitives to access HW */ #include #include #include #include /* * List of control registers to save/restore */ static const struct reglist ctrl_backup[] = { BACKUP_REG(MCFGR, 1, 0, 0), #ifdef CFG_NXP_CAAM_MP_DRV BACKUP_REG(SCFGR, 1, BM_SCFGR_MPMRL | BM_SCFGR_MPCURVE, 0), #else /* For device not supporting MP (bits not defined) */ BACKUP_REG(SCFGR, 1, 0, 0), #endif }; void caam_hal_ctrl_init(vaddr_t baseaddr) { /* Enable DECO watchdogs */ io_setbits32(baseaddr + MCFGR, MCFGR_WDE); /* * ERRATA: mx6 devices have an issue wherein AXI bus transactions * may not occur in the correct order. This isn't a problem running * single descriptors, but can be if running multiple concurrent * descriptors. Reworking the driver to throttle to single requests * is impractical, thus the workaround is to limit the AXI pipeline * to a depth of 1 (default depth is 4) to preclude this situation * from occurring. * * mx7 devices, this bit has no effect. */ io_mask32(baseaddr + MCFGR, MCFGR_AXIPIPE(1), BM_MCFGR_AXIPIPE); caam_pwr_add_backup(baseaddr, ctrl_backup, ARRAY_SIZE(ctrl_backup)); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/hal_jr.c000066400000000000000000000052521464416617300236210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Job Rings Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include #include #include /* * List of JR configuration registers to save/restore */ static const struct reglist jrcfg_backup[] = { BACKUP_REG(JR0MIDR_LS, 1, 0, 0), BACKUP_REG(JR0MIDR_MS, 1, 0, 0), }; enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, enum caam_jr_owner owner) { enum caam_status retstatus = CAAM_FAILURE; uint32_t val = 0; uint32_t cfg_ms = 0; uint32_t cfg_ls = 0; unsigned int jr_idx = JRX_IDX(jr_offset); /* Read the Job Ring Lock bit */ val = io_caam_read32(ctrl_base + JRxMIDR_MS(jr_idx)); HAL_TRACE("JR%" PRIu32 "MIDR_MS value 0x%" PRIx32, jr_idx, val); /* Prepare the Job Ring MS/LS registers */ if (owner & JROWNER_SECURE) { /* Configuration only lock for the Secure JR */ cfg_ms = JRxMIDR_MS_JROWN_MID(owner & ~JROWNER_SECURE); cfg_ms |= JRxMIDR_MS_AMTD; #ifdef CFG_NXP_CAAM_RUNTIME_JR cfg_ms |= JRxMIDR_MS_LAMTD; cfg_ms |= JRxMIDR_MS_LMID; #endif cfg_ls = JRxMIDR_LS_SEQ_MID(owner & ~JROWNER_SECURE); cfg_ls |= JRxMIDR_LS_NONSEQ_MID(owner & ~JROWNER_SECURE); } else { cfg_ms = JRxMIDR_MS_JROWN_MID(owner) | JRxMIDR_MS_JROWN_NS; cfg_ls = JRxMIDR_LS_SEQ_MID(owner) | JRxMIDR_LS_SEQ_NS; cfg_ls |= JRxMIDR_LS_NONSEQ_MID(owner) | JRxMIDR_LS_NONSEQ_NS; } if (val & JRxMIDR_MS_LMID) { /* * Configuration already locked, check it is the * expected configuration. */ HAL_TRACE("JR%" PRIu32 "MIDR_MS value 0x%" PRIx32 " (0x%" PRIx32 ")", jr_idx, val, cfg_ms); if ((cfg_ms | JRxMIDR_MS_LMID) == val) { /* * Read the LS register and compare with expected * value */ val = io_caam_read32(ctrl_base + JRxMIDR_LS(jr_idx)); HAL_TRACE("JR%" PRIu32 "MIDR_LS value 0x%" PRIx32 " (0x%" PRIX32 ")", jr_idx, val, cfg_ls); if (val == cfg_ls) retstatus = CAAM_NO_ERROR; } } else { HAL_TRACE("JR%" PRIu32 "MIDR_LS set value 0x%" PRIx32, jr_idx, cfg_ls); HAL_TRACE("JR%" PRIu32 "MIDR_MS set value 0x%" PRIx32, jr_idx, cfg_ms); /* Set the configuration */ io_caam_write32(ctrl_base + JRxMIDR_LS(jr_idx), cfg_ls); io_caam_write32(ctrl_base + JRxMIDR_MS(jr_idx), cfg_ms); retstatus = CAAM_NO_ERROR; } return retstatus; } void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset) { unsigned int jr_idx = JRX_IDX(jr_offset); caam_pwr_add_backup(ctrl_base + (jr_idx * JRxMIDR_SIZE), jrcfg_backup, ARRAY_SIZE(jrcfg_backup)); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/registers/000077500000000000000000000000001464416617300242215ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/registers/ctrl_regs.h000066400000000000000000000031171464416617300263600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Brief Control Registers. */ #ifndef __CTRL_REGS_H__ #define __CTRL_REGS_H__ #include /* Master Configuration */ #define MCFGR 0x0004 #define MCFGR_WDE BIT32(30) #define MCFGR_AXIPIPE(val) SHIFT_U32(val, 4) #define BM_MCFGR_AXIPIPE SHIFT_U32(0xF, 4) /* Job Ring x MID */ #define JRxMIDR_SIZE 0x8 #define JR0MIDR_MS 0x0010 #define JR0MIDR_LS 0x0014 #define JRxMIDR_MS(idx) (JR0MIDR_MS + (idx) * JRxMIDR_SIZE) #define JRxMIDR_LS(idx) (JR0MIDR_LS + (idx) * JRxMIDR_SIZE) #define JRxMIDR_MS_LMID BIT32(31) #define JRxMIDR_MS_LAMTD BIT32(17) #define JRxMIDR_MS_AMTD BIT32(16) #if !defined(CFG_MX7ULP) #define JRxMIDR_MS_JROWN_NS BIT32(3) #define JRxMIDR_MS_JROWN_MID(val) SHIFT_U32((val) & 0x7, 0) #define JRxMIDR_LS_NONSEQ_NS BIT32(19) #define JRxMIDR_LS_NONSEQ_MID(val) SHIFT_U32((val) & 0x7, 16) #define JRxMIDR_LS_SEQ_NS BIT32(3) #define JRxMIDR_LS_SEQ_MID(val) SHIFT_U32((val) & 0x7, 0) #else #define JRxMIDR_MS_JROWN_NS BIT32(4) #define JRxMIDR_MS_JROWN_MID(val) SHIFT_U32((val) & 0xF, 0) #define JRxMIDR_LS_NONSEQ_NS BIT32(20) #define JRxMIDR_LS_NONSEQ_MID(val) SHIFT_U32((val) & 0xF, 16) #define JRxMIDR_LS_SEQ_NS BIT32(4) #define JRxMIDR_LS_SEQ_MID(val) SHIFT_U32((val) & 0xF, 0) #endif /* Security Configuration */ #define SCFGR 0x000C #define BS_SCFGR_MPCURVE 28 #define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) #define BM_SCFGR_MPMRL BIT32(26) /* Manufacturing Protection Message */ #define MPMR 0x0380 #define MPMR_NB_REG 0x20 #endif /* __CTRL_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_6_7/sub.mk000066400000000000000000000003231464416617300233320ustar00rootroot00000000000000incdirs-y += ../common incdirs-y += ../../include incdirs-y += . srcs-$(CFG_MX6) += hal_clk_mx6.c srcs-$(CFG_MX7) += hal_clk_mx7.c srcs-$(CFG_MX7ULP) += hal_clk_mx7ulp.c srcs-y += hal_ctrl.c srcs-y += hal_jr.c optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/000077500000000000000000000000001464416617300221435ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/hal_clk.c000066400000000000000000000003161464416617300237040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018 NXP * * Brief CAAM Clock functions. */ #include #include void caam_hal_clk_enable(bool enable __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/hal_ctrl.c000066400000000000000000000006031464416617300240760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Controller Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include void caam_hal_ctrl_init(vaddr_t baseaddr) { /* Enable DECO watchdogs */ io_setbits32(baseaddr + MCFGR, MCFGR_WDE); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/hal_jr.c000066400000000000000000000050221464416617300235450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief CAAM Job Rings Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include #include #include /* * List of JR configuration registers to save/restore */ static const struct reglist jrcfg_backup[] = { BACKUP_REG(JR0DID_MS, 1, 0, 0), BACKUP_REG(JR0DID_LS, 1, 0, 0), }; enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, enum caam_jr_owner owner) { enum caam_status retstatus = CAAM_FAILURE; uint32_t val = 0; uint32_t cfg_ms = 0; uint32_t cfg_ls = 0; unsigned int jr_idx = JRX_IDX(jr_offset); /* Read the Job Ring Lock bit */ val = io_caam_read32(ctrl_base + JRxDID_MS(jr_idx)); HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32, jr_idx, val); /* Prepare the Job Ring MS/LS registers */ if (owner & JROWNER_SECURE) { /* Configuration only locked for the Secure JR */ cfg_ms = JRxDID_MS_PRIM_DID(owner & ~JROWNER_SECURE); cfg_ms |= JRxDID_MS_PRIM_TZ | JRxDID_MS_TZ_OWN; cfg_ms |= JRxDID_MS_AMTD; cfg_ms |= JRxDID_MS_PRIM_ICID(owner & ~JROWNER_SECURE); #ifdef CFG_NXP_CAAM_RUNTIME_JR cfg_ms |= JRxDID_MS_LDID; cfg_ms |= JRxDID_MS_LAMTD; #endif } else { cfg_ms = JRxDID_MS_PRIM_DID(owner); cfg_ms |= JRxDID_MS_PRIM_ICID(owner); } if (val & JRxDID_MS_LDID) { /* * Configuration already locked, check it is the * expected configuration. */ HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32 " (0x%" PRIx32 ")", jr_idx, val, cfg_ms); if ((cfg_ms | JRxDID_MS_LDID) == val) { /* Read LS register and compare with expected value */ val = io_caam_read32(ctrl_base + JRxDID_LS(jr_idx)); HAL_TRACE("JR%" PRIu32 "DID_LS value 0x%" PRIx32 " (0x%" PRIx32 ")", jr_idx, val, cfg_ls); if (val == cfg_ls) retstatus = CAAM_NO_ERROR; } } else { HAL_TRACE("JR%" PRIu32 "DID_LS set value 0x%" PRIx32, jr_idx, cfg_ls); HAL_TRACE("JR%" PRIu32 "DID_MS set value 0x%" PRIx32, jr_idx, cfg_ms); /* Set the configuration */ io_caam_write32(ctrl_base + JRxDID_LS(jr_idx), cfg_ls); io_caam_write32(ctrl_base + JRxDID_MS(jr_idx), cfg_ms); retstatus = CAAM_NO_ERROR; } return retstatus; } void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset) { unsigned int jr_idx = JRX_IDX(jr_offset); caam_pwr_add_backup(ctrl_base + (jr_idx * JRxDID_SIZE), jrcfg_backup, ARRAY_SIZE(jrcfg_backup)); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/registers/000077500000000000000000000000001464416617300241525ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/registers/ctrl_regs.h000066400000000000000000000022301464416617300263040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Brief Control Registers. */ #ifndef __CTRL_REGS_H__ #define __CTRL_REGS_H__ #include /* Master Configuration */ #define MCFGR 0x0004 #define MCFGR_WDE BIT32(30) /* Job Ring x MID */ #define JRxDID_SIZE 0x8 #define JR0DID_MS 0x0010 #define JR0DID_LS 0x0014 #define JRxDID_MS(idx) (JR0DID_MS + ((idx) * JRxDID_SIZE)) #define JRxDID_LS(idx) (JR0DID_LS + ((idx) * JRxDID_SIZE)) #define JRxDID_MS_LDID BIT32(31) #define JRxDID_MS_PRIM_ICID(val) SHIFT_U32(((val) & 0x3FF), 19) #define JRxDID_MS_LAMTD BIT32(17) #define JRxDID_MS_AMTD BIT32(16) #define JRxDID_MS_TZ_OWN BIT32(15) #define JRxDID_MS_PRIM_TZ BIT32(4) #define JRxDID_MS_PRIM_DID(val) SHIFT_U32(((val) & 0xF), 0) /* Security Configuration */ #define SCFGR 0x000C #define BS_SCFGR_MPCURVE 28 #define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) #define BM_SCFGR_MPMRL BIT32(26) /* Manufacturing Protection Message */ #define MPMR 0x0380 #define MPMR_NB_REG U(32) /* Secure Memory physical base address */ #define JRX_SMVBAR(idx) (0x0184 + (idx) * 8) #endif /* __CTRL_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8m/sub.mk000066400000000000000000000001761464416617300232710ustar00rootroot00000000000000incdirs-y += ../common incdirs-y += ../../include incdirs-y += . srcs-y += hal_clk.c srcs-y += hal_ctrl.c srcs-y += hal_jr.c optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/000077500000000000000000000000001464416617300221475ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/hal_cfg.c000066400000000000000000000002571464416617300237020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021 NXP */ #include void caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/hal_clk.c000066400000000000000000000002571464416617300237140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021 NXP */ #include #include void caam_hal_clk_enable(bool enable __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/hal_ctrl.c000066400000000000000000000002641464416617300241050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021 NXP */ #include #include void caam_hal_ctrl_init(vaddr_t baseaddr __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/hal_jr.c000066400000000000000000000012621464416617300235530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021 NXP */ #include #include #include #include #include enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base __unused, paddr_t jr_offset __unused, enum caam_jr_owner owner __unused) { TEE_Result ret = TEE_ERROR_GENERIC; ret = imx_sc_driver_init(); if (ret != TEE_SUCCESS) return CAAM_FAILURE; ret = imx_sc_rm_enable_jr(CFG_JR_INDEX); if (ret != TEE_SUCCESS) return CAAM_FAILURE; else return CAAM_NO_ERROR; } void caam_hal_jr_prepare_backup(vaddr_t ctrl_base __unused, paddr_t jr_offset __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c000066400000000000000000000011671464416617300237320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021, 2024 NXP */ #include #include #include #include #include enum caam_status caam_hal_rng_instantiated(vaddr_t baseaddr __unused) { TEE_Result ret = TEE_ERROR_GENERIC; ret = imx_sc_seco_start_rng(); if (ret != TEE_SUCCESS) return CAAM_FAILURE; else return CAAM_NO_ERROR; } bool caam_hal_rng_pr_enabled(vaddr_t baseaddr __unused) { /* * On platforms i.MX8Q and i.MX8DXL CAAM RNG Prediction * resistance is enabled by default. So returning true. */ return true; } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/registers/000077500000000000000000000000001464416617300241565ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/registers/ctrl_regs.h000066400000000000000000000020621464416617300263130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 NXP */ #ifndef __CTRL_REGS_H__ #define __CTRL_REGS_H__ /* Global includes */ #include /* Job Ring x MID */ #define JRxDID_SIZE 0x8 #define JR0DID_MS 0x0010 #define JR0DID_LS 0x0014 #define JRxDID_MS(idx) (JR0DID_MS + (idx) * (JRxDID_SIZE)) #define JRxDID_LS(idx) (JR0DID_LS + (idx) * (JRxDID_SIZE)) #define JRxDID_MS_LDID BIT32(31) #define JRxDID_MS_PRIM_ICID(val) SHIFT_U32((val) & (0x3FF), 19) #define JRxDID_MS_LAMTD BIT32(17) #define JRxDID_MS_AMTD BIT32(16) #define JRxDID_MS_TZ_OWN BIT32(15) #define JRxDID_MS_PRIM_TZ BIT32(4) #define JRxDID_MS_PRIM_DID(val) SHIFT_U32((val) & (0xF), 0) /* Security Configuration */ #define SCFGR 0x000C #define BS_SCFGR_MPCURVE 28 #define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) #define BM_SCFGR_MPMRL BIT32(26) /* Secure Memory Virtual Base Address */ #define JRX_SMVBAR(idx) (0x0184 + (idx) * (8)) /* Manufacturing Protection Message */ #define MPMR 0x0380 #define MPMR_NB_REG 0x20 #endif /* __CTRL_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8q/sub.mk000066400000000000000000000002461464416617300232730ustar00rootroot00000000000000incdirs-y += ../common incdirs-y += ../../include incdirs-y += . srcs-y += hal_clk.c srcs-y += hal_ctrl.c srcs-y += hal_jr.c srcs-y += hal_cfg.c srcs-y += hal_rng.c optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/000077500000000000000000000000001464416617300225075ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/hal_clk.c000066400000000000000000000007301464416617300242500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Brief CAAM Clock functions. */ #include #include #include #include void caam_hal_clk_enable(bool enable) { vaddr_t pcc3_base = (vaddr_t)phys_to_virt(PCC3_BASE, MEM_AREA_IO_SEC, PCC3_SIZE); if (enable) io_setbits32(pcc3_base + PCC_CAAM, PCC_ENABLE_CLOCK); else io_clrbits32(pcc3_base + PCC_CAAM, PCC_ENABLE_CLOCK); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/hal_ctrl.c000066400000000000000000000006121464416617300244420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Brief CAAM Controller Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include void caam_hal_ctrl_init(vaddr_t baseaddr) { /* Enable DECO watchdogs */ io_setbits32(baseaddr + MCFGR, MCFGR_WDE); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/hal_jr.c000066400000000000000000000050561464416617300241200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Brief CAAM Job Rings Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include #include #include #include /* * List of JR configuration registers to save/restore */ static const struct reglist jrcfg_backup[] = { BACKUP_REG(JR0DID_MS, 1, 0, 0), BACKUP_REG(JR0DID_LS, 1, 0, 0), }; enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, enum caam_jr_owner owner) { enum caam_status retstatus = CAAM_FAILURE; uint32_t val = 0; uint32_t cfg_ms = 0; uint32_t cfg_ls = 0; unsigned int jr_idx = JRX_IDX(jr_offset); /* Read the Job Ring Lock bit */ val = io_caam_read32(ctrl_base + JRxDID_MS(jr_idx)); HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32, jr_idx, val); /* Prepare the Job Ring MS/LS registers */ if (owner & JROWNER_SECURE) { /* Configuration only locked for the Secure JR */ cfg_ms = JRxDID_MS_PRIM_DID(owner & ~JROWNER_SECURE); cfg_ms |= JRxDID_MS_PRIM_TZ | JRxDID_MS_TZ_OWN; cfg_ms |= JRxDID_MS_AMTD; cfg_ms |= JRxDID_MS_PRIM_ICID(owner & ~JROWNER_SECURE); if (IS_ENABLED(CFG_NXP_CAAM_RUNTIME_JR)) { cfg_ms |= JRxDID_MS_LDID; cfg_ms |= JRxDID_MS_LAMTD; } } else { cfg_ms = JRxDID_MS_PRIM_DID(owner); cfg_ms |= JRxDID_MS_PRIM_ICID(owner); } if (val & JRxDID_MS_LDID) { /* * Configuration already locked, check it is the * expected configuration. */ HAL_TRACE("JR%" PRIu32 "DID_MS value 0x%" PRIx32 " (0x%" PRIx32 ")", jr_idx, val, cfg_ms); if ((cfg_ms | JRxDID_MS_LDID) == val) { /* Read LS register and compare with expected value */ val = io_caam_read32(ctrl_base + JRxDID_LS(jr_idx)); HAL_TRACE("JR%" PRIu32 "DID_LS value 0x%" PRIx32 " (0x%" PRIx32 ")", jr_idx, val, cfg_ls); if (val == cfg_ls) retstatus = CAAM_NO_ERROR; } } else { HAL_TRACE("JR%" PRIu32 "DID_LS set value 0x%" PRIx32, jr_idx, cfg_ls); HAL_TRACE("JR%" PRIu32 "DID_MS set value 0x%" PRIx32, jr_idx, cfg_ms); /* Set the configuration */ io_caam_write32(ctrl_base + JRxDID_LS(jr_idx), cfg_ls); io_caam_write32(ctrl_base + JRxDID_MS(jr_idx), cfg_ms); retstatus = CAAM_NO_ERROR; } return retstatus; } void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset) { unsigned int jr_idx = JRX_IDX(jr_offset); caam_pwr_add_backup(ctrl_base + (jr_idx * JRxDID_SIZE), jrcfg_backup, ARRAY_SIZE(jrcfg_backup)); } optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/registers/000077500000000000000000000000001464416617300245165ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/registers/ctrl_regs.h000066400000000000000000000022241464416617300266530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP * * Brief Control Registers. */ #ifndef __CTRL_REGS_H__ #define __CTRL_REGS_H__ #include /* Master Configuration */ #define MCFGR 0x0004 #define MCFGR_WDE BIT32(30) /* Job Ring x MID */ #define JRxDID_SIZE 0x8 #define JR0DID_MS 0x0010 #define JR0DID_LS 0x0014 #define JRxDID_MS(idx) (JR0DID_MS + ((idx) * (JRxDID_SIZE))) #define JRxDID_LS(idx) (JR0DID_LS + ((idx) * (JRxDID_SIZE))) #define JRxDID_MS_LDID BIT32(31) #define JRxDID_MS_PRIM_ICID(val) SHIFT_U32(((val) & (0x3FF)), 19) #define JRxDID_MS_LAMTD BIT32(17) #define JRxDID_MS_AMTD BIT32(16) #define JRxDID_MS_TZ_OWN BIT32(15) #define JRxDID_MS_PRIM_TZ BIT32(4) #define JRxDID_MS_PRIM_DID(val) SHIFT_U32(((val) & (0xF)), 0) /* Security Configuration */ #define SCFGR 0x000C #define BS_SCFGR_MPCURVE 28 #define BM_SCFGR_MPCURVE SHIFT_U32(0xF, BS_SCFGR_MPCURVE) #define BM_SCFGR_MPMRL BIT32(26) /* Secure Memory Virtual Base Address */ #define JRX_SMVBAR(idx) (0x0184 + (idx) * (8)) /* Manufacturing Protection Message */ #define MPMR 0x0380 #define MPMR_NB_REG 0x20 #endif /* __CTRL_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/imx_8ulp/sub.mk000066400000000000000000000001761464416617300236350ustar00rootroot00000000000000incdirs-y += ../common incdirs-y += ../../include incdirs-y += . srcs-y += hal_clk.c srcs-y += hal_ctrl.c srcs-y += hal_jr.c optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/000077500000000000000000000000001464416617300213605ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/hal_clk.c000066400000000000000000000003161464416617300231210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 NXP * * Brief CAAM Clock functions. */ #include #include void caam_hal_clk_enable(bool enable __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/hal_ctrl.c000066400000000000000000000004361464416617300233170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 NXP * * Brief CAAM Controller Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include void caam_hal_ctrl_init(vaddr_t baseaddr __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/hal_jr.c000066400000000000000000000015671464416617300227740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 NXP * * Brief CAAM Job Rings Hardware Abstration Layer. * Implementation of primitives to access HW. */ #include #include #include #include #include enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, enum caam_jr_owner owner) { uint32_t val = 0; unsigned int jr_idx = JRX_IDX(jr_offset); if (owner == JROWN_ARM_S) { /* Read the Job Ring Lock bit */ val = io_caam_read32(ctrl_base + JRxMIDR_MS(jr_idx)); HAL_TRACE("JR%" PRIu32 "MIDR_MS value 0x%" PRIx32, jr_idx, val); val |= JRxMIDR_MS_TZ; io_caam_write32(ctrl_base + JRxMIDR_MS(jr_idx), val); } return CAAM_NO_ERROR; } void caam_hal_jr_prepare_backup(vaddr_t ctrl_base __unused, paddr_t jr_offset __unused) { } optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/registers/000077500000000000000000000000001464416617300233675ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/registers/ctrl_regs.h000066400000000000000000000021151464416617300255230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019, 2021 NXP * * Brief Control Registers. */ #ifndef __CTRL_REGS_H__ #define __CTRL_REGS_H__ #include /* Master Configuration */ #define MCFGR 0x0004 #define MCFGR_WDE BIT32(30) #define MCFGR_AXIPIPE(val) SHIFT_U32(val, 4) #define BM_MCFGR_AXIPIPE SHIFT_U32(0xF, 4) /* Job Ring x MID */ #define JRxMIDR_SIZE 0x8 #define JR0MIDR_MS 0x0010 #define JR0MIDR_LS 0x0014 #define JRxMIDR_MS(idx) (JR0MIDR_MS + (idx) * JRxMIDR_SIZE) #define JRxMIDR_LS(idx) (JR0MIDR_LS + (idx) * JRxMIDR_SIZE) #define JRxMIDR_MS_LMID BIT32(31) #define JRxMIDR_MS_LAMTD BIT32(17) #define JRxMIDR_MS_TZ BIT32(15) #define JRxMIDR_MS_AMTD BIT32(16) #define JRxMIDR_MS_JROWN_NS BIT32(3) #define JRxMIDR_MS_JROWN_MID(val) SHIFT_U32((val) & 0x7, 0) #define JRxMIDR_LS_NONSEQ_NS BIT32(19) #define JRxMIDR_LS_NONSEQ_MID(val) SHIFT_U32((val) & 0x7, 16) #define JRxMIDR_LS_SEQ_NS BIT32(3) #define JRxMIDR_LS_SEQ_MID(val) SHIFT_U32((val) & 0x7, 0) /* Security Configuration */ #define SCFGR 0x000C #endif /* __CTRL_REGS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hal/ls/sub.mk000066400000000000000000000001761464416617300225060ustar00rootroot00000000000000incdirs-y += ../common incdirs-y += ../../include incdirs-y += . srcs-y += hal_clk.c srcs-y += hal_ctrl.c srcs-y += hal_jr.c optee_os-4.3.0/core/drivers/crypto/caam/hal/sub.mk000066400000000000000000000006671464416617300220750ustar00rootroot00000000000000ifeq ($(CFG_LS),y) CAAM_HAL_DIR = ls endif ifeq ($(filter y, $(CFG_MX6) $(CFG_MX7) $(CFG_MX7ULP)),y) CAAM_HAL_DIR = imx_6_7 endif ifeq ($(filter y, $(CFG_MX8MQ) $(CFG_MX8MM) $(CFG_MX8MN) $(CFG_MX8MP)),y) CAAM_HAL_DIR = imx_8m endif ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX) $(CFG_MX8DXL)),y) CAAM_HAL_DIR = imx_8q endif ifeq ($(filter y, $(CFG_MX8ULP)),y) CAAM_HAL_DIR = imx_8ulp endif subdirs-y += common subdirs-y += $(CAAM_HAL_DIR) optee_os-4.3.0/core/drivers/crypto/caam/hash/000077500000000000000000000000001464416617300211215ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/hash/caam_hash.c000066400000000000000000000406211464416617300231740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019, 2021 NXP * * Implementation of Hashing functions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "local.h" static const struct crypto_hash_ops hash_ops; /* * Maximum number of entries in the descriptor */ #define MAX_DESC_ENTRIES 20 /* * Constants definition of the hash/HMAC algorithm */ static const struct hashalg hash_alg[] = { { /* md5 */ .type = OP_ALGO(MD5), .size_digest = TEE_MD5_HASH_SIZE, .size_block = TEE_MD5_HASH_SIZE * 4, .size_ctx = HASH_MSG_LEN + TEE_MD5_HASH_SIZE, .size_key = 32, }, { /* sha1 */ .type = OP_ALGO(SHA1), .size_digest = TEE_SHA1_HASH_SIZE, .size_block = TEE_MAX_HASH_SIZE, .size_ctx = HASH_MSG_LEN + TEE_SHA1_HASH_SIZE, .size_key = 40, }, { /* sha224 */ .type = OP_ALGO(SHA224), .size_digest = TEE_SHA224_HASH_SIZE, .size_block = TEE_MAX_HASH_SIZE, .size_ctx = HASH_MSG_LEN + TEE_SHA256_HASH_SIZE, .size_key = 64, }, { /* sha256 */ .type = OP_ALGO(SHA256), .size_digest = TEE_SHA256_HASH_SIZE, .size_block = TEE_MAX_HASH_SIZE, .size_ctx = HASH_MSG_LEN + TEE_SHA256_HASH_SIZE, .size_key = 64, }, { /* sha384 */ .type = OP_ALGO(SHA384), .size_digest = TEE_SHA384_HASH_SIZE, .size_block = TEE_MAX_HASH_SIZE * 2, .size_ctx = HASH_MSG_LEN + TEE_SHA512_HASH_SIZE, .size_key = 128, }, { /* sha512 */ .type = OP_ALGO(SHA512), .size_digest = TEE_SHA512_HASH_SIZE, .size_block = TEE_MAX_HASH_SIZE * 2, .size_ctx = HASH_MSG_LEN + TEE_SHA512_HASH_SIZE, .size_key = 128, }, }; /* * Format the hash context to keep the reference to the * operation driver */ struct crypto_hash { struct crypto_hash_ctx hash_ctx; /* Crypto Hash API context */ struct hashctx *ctx; /* Hash Context */ }; /* * Keep the HW hash limit because after the initialization * of the module, we don't have the CAAM Controller base address * to call the function returning the HW capacity. */ static uint8_t caam_hash_limit; /* * Returns the reference to the driver context * * @ctx API Context */ static struct crypto_hash *to_hash_ctx(struct crypto_hash_ctx *ctx) { assert(ctx && ctx->ops == &hash_ops); return container_of(ctx, struct crypto_hash, hash_ctx); } /* * Add the load key in the CAAM descriptor and clean the key buffer. * * @desc CAAM Descriptor * @key Key to load */ static void do_desc_load_key(uint32_t *desc, struct caambuf *key) { HASH_TRACE("Insert Key"); caam_desc_add_word(desc, LD_KEY_SPLIT(key->length)); caam_desc_add_ptr(desc, key->paddr); cache_operation(TEE_CACHECLEAN, key->data, key->length); } /* * Free the internal hashing data context * * @ctx [in/out] Caller context variable */ static void do_free_intern(struct hashctx *ctx) { HASH_TRACE("Free Context (%p)", ctx); if (ctx) { /* Free the descriptor */ caam_free_desc(&ctx->descriptor); /* Free the Temporary buffer */ caam_free_buf(&ctx->blockbuf.buf); /* Free the context register */ caam_free_buf(&ctx->ctx); /* Free the HMAC Key */ caam_free_buf(&ctx->key); } } /* * Initialization of the Hash operation * Call common initialization operation between hash and HMAC * * @ctx Operation software context */ static TEE_Result do_hash_init(struct crypto_hash_ctx *ctx) { struct crypto_hash *hash = to_hash_ctx(ctx); return caam_hash_hmac_init(hash->ctx); } /* * Update the Hash operation * Call common update operation between hash and HMAC * * @ctx Operation software context * @data Data to hash * @len Data length */ static TEE_Result do_hash_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { struct crypto_hash *hash = to_hash_ctx(ctx); return caam_hash_hmac_update(hash->ctx, data, len); } /* * Finalize the Hash operation * Call common final operation between hash and HMAC * * @ctx Operation software context * @digest [out] Hash digest buffer * @len Digest buffer length */ static TEE_Result do_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { struct crypto_hash *hash = to_hash_ctx(ctx); return caam_hash_hmac_final(hash->ctx, digest, len); } /* * Free the SW hashing data context * Call common free operation between hash and HMAC * * @ctx [in/out] Caller context variable */ static void do_hash_free(struct crypto_hash_ctx *ctx) { struct crypto_hash *hash = to_hash_ctx(ctx); caam_hash_hmac_free(hash->ctx); free(hash); } /* * Copy Software Hashing Context * Call common copy operation between hash and HMAC * * @dst_ctx [out] Reference the context destination * @src_ctx Reference the context source */ static void do_hash_copy_state(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx) { struct crypto_hash *hash_src = to_hash_ctx(src_ctx); struct crypto_hash *hash_dst = to_hash_ctx(dst_ctx); return caam_hash_hmac_copy_state(hash_dst->ctx, hash_src->ctx); } /* * Registration of the hash Driver */ static const struct crypto_hash_ops hash_ops = { .init = do_hash_init, .update = do_hash_update, .final = do_hash_final, .free_ctx = do_hash_free, .copy_state = do_hash_copy_state, }; /* * Allocate the internal hashing data context * * @ctx [out] Caller context variable * @algo Algorithm ID */ static TEE_Result caam_hash_allocate(struct crypto_hash_ctx **ctx, uint32_t algo) { struct crypto_hash *hash = NULL; struct hashctx *hash_ctx = NULL; const struct hashalg *alg = NULL; TEE_Result ret = TEE_ERROR_GENERIC; HASH_TRACE("Allocate Context (%p) algo %" PRId32, ctx, algo); *ctx = NULL; alg = caam_hash_get_alg(algo); if (!alg) return TEE_ERROR_NOT_IMPLEMENTED; hash = calloc(1, sizeof(*hash)); if (!hash) return TEE_ERROR_OUT_OF_MEMORY; hash_ctx = caam_calloc(sizeof(*hash_ctx)); if (!hash_ctx) { ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } hash_ctx->alg = alg; hash->hash_ctx.ops = &hash_ops; hash->ctx = hash_ctx; *ctx = &hash->hash_ctx; ret = caam_hash_hmac_allocate(hash_ctx); if (ret != TEE_SUCCESS) goto err; HASH_TRACE("Allocated Context (%p)", hash_ctx); return TEE_SUCCESS; err: free(hash); if (hash_ctx) caam_free(hash_ctx); return ret; } TEE_Result caam_hash_hmac_allocate(struct hashctx *ctx) { TEE_Result ret = TEE_ERROR_GENERIC; HASH_TRACE("Allocate Context (%p)", ctx); /* Allocate the descriptor */ ctx->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES); if (!ctx->descriptor) { HASH_TRACE("Allocation context descriptor error"); return TEE_ERROR_OUT_OF_MEMORY; } /* Initialize the block buffer */ ctx->blockbuf.filled = 0; ctx->blockbuf.max = ctx->alg->size_block; /* Allocate the CAAM Context register */ if (caam_calloc_align_buf(&ctx->ctx, ctx->alg->size_ctx) != CAAM_NO_ERROR) { HASH_TRACE("Allocation context register error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } /* Allocate the Hash Key */ if (caam_calloc_align_buf(&ctx->key, ctx->alg->size_key) != CAAM_NO_ERROR) { HASH_TRACE("Allocation context key error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } cache_operation(TEE_CACHEFLUSH, ctx->ctx.data, ctx->ctx.length); /* Ensure buffer length is 0 */ ctx->ctx.length = 0; return TEE_SUCCESS; err: do_free_intern(ctx); return ret; } /* * Free the SW hashing data context * * @ctx Caller context variable */ void caam_hash_hmac_free(struct hashctx *ctx) { HASH_TRACE("Free Context (%p)", ctx); if (ctx) { do_free_intern(ctx); caam_free(ctx); } } const struct hashalg *caam_hash_get_alg(uint32_t algo) { uint8_t hash_id = TEE_ALG_GET_MAIN_ALG(algo); unsigned int idx = hash_id - TEE_MAIN_ALGO_MD5; if (hash_id > caam_hash_limit || idx > ARRAY_SIZE(hash_alg)) return NULL; return &hash_alg[idx]; } TEE_Result caam_hash_hmac_init(struct hashctx *ctx) { HASH_TRACE("Hash/HMAC Init (%p)", ctx); if (!ctx) return TEE_ERROR_BAD_PARAMETERS; /* Initialize the block buffer */ ctx->blockbuf.filled = 0; ctx->blockbuf.max = ctx->alg->size_block; /* Ensure Context length is 0 */ ctx->ctx.length = 0; /* Initialize the HMAC Key */ ctx->key.length = 0; ctx->initialized = true; return TEE_SUCCESS; } /* * Build and run the CAAM Hash descriptor to update (or start) the * data digest. * * @ctx [in/out] Caller context variable * @src Input data to digest */ static TEE_Result do_update_hash(struct hashctx *ctx, struct caamdmaobj *src) { enum caam_status retstatus = CAAM_FAILURE; const struct hashalg *alg = ctx->alg; struct caam_jobctx jobctx = { }; uint32_t *desc = ctx->descriptor; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* There are blocks to hash - Create the Descriptor */ if (ctx->ctx.length) { HASH_TRACE("Update Operation"); /* Algo Operation - Update */ caam_desc_add_word(desc, HASH_UPDATE(alg->type)); /* Running context to restore */ caam_desc_add_word(desc, LD_NOIMM(CLASS_2, REG_CTX, ctx->ctx.length)); caam_desc_add_ptr(desc, ctx->ctx.paddr); } else { HASH_TRACE("Init Operation"); /* Check if there is a key to load it */ if (ctx->key.length) { do_desc_load_key(desc, &ctx->key); /* Algo Operation - HMAC Init */ caam_desc_add_word(desc, HMAC_INIT_PRECOMP(alg->type)); } else { /* Algo Operation - Init */ caam_desc_add_word(desc, HASH_INIT(alg->type)); } ctx->ctx.length = alg->size_ctx; } if (ctx->blockbuf.filled) { caam_desc_add_word(desc, FIFO_LD(CLASS_2, MSG, NOACTION, ctx->blockbuf.filled)); caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr); cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data, ctx->blockbuf.filled); } caam_desc_fifo_load(desc, src, CLASS_2, MSG, LAST_C2); caam_dmaobj_cache_push(src); ctx->blockbuf.filled = 0; if (ctx->ctx.length) { /* Save the running context */ caam_desc_add_word(desc, ST_NOIMM(CLASS_2, REG_CTX, ctx->ctx.length)); caam_desc_add_ptr(desc, ctx->ctx.paddr); /* Ensure Context register data are not in cache */ cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, ctx->ctx.length); } HASH_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus != CAAM_NO_ERROR) { HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); return job_status_to_tee_result(jobctx.status); } HASH_DUMPBUF("CTX", ctx->ctx.data, ctx->ctx.length); return TEE_SUCCESS; } TEE_Result caam_hash_hmac_update(struct hashctx *ctx, const uint8_t *data, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; const struct hashalg *alg = NULL; size_t fullsize = 0; size_t size_topost = 0; size_t size_todo = 0; size_t size_done = 0; size_t size_inmade = 0; struct caamdmaobj src = { }; size_t offset = 0; HASH_TRACE("Hash/HMAC Update (%p) %p - %zu", ctx, data, len); if ((!data && len) || !ctx) return TEE_ERROR_BAD_PARAMETERS; alg = ctx->alg; if (!ctx->ctx.data) return TEE_ERROR_GENERIC; HASH_TRACE("Update Type 0x%" PRIX32 " - Input @%p-%zu", alg->type, data, len); /* Calculate the total data to be handled */ fullsize = ctx->blockbuf.filled + len; size_topost = fullsize % alg->size_block; size_todo = fullsize - size_topost; size_inmade = len - size_topost; HASH_TRACE("FullSize %zu - posted %zu - todo %zu", fullsize, size_topost, size_todo); if (!size_todo) { ret = TEE_SUCCESS; /* All input data must be saved */ if (size_topost) size_inmade = 0; goto save_posted; } ret = caam_dmaobj_init_input(&src, data, size_inmade); if (ret) goto exit_update; ret = caam_dmaobj_prepare(&src, NULL, alg->size_block); if (ret) goto exit_update; size_todo = size_inmade; for (offset = 0; offset < size_inmade; offset += size_done, size_todo -= size_done) { size_done = size_todo; HASH_TRACE("Do input %zu bytes, offset %zu", size_done, offset); ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset, alg->size_block); if (ret) goto exit_update; /* * Need to re-adjust the length of the data if the * posted data block is not empty and the SGT/Buffer * is part of the full input data to do. */ if (ctx->blockbuf.filled && size_done < size_todo) { size_done -= ctx->blockbuf.filled; src.sgtbuf.length = size_done; } ret = do_update_hash(ctx, &src); if (ret) goto exit_update; } save_posted: if (size_topost && data) { struct caambuf srcdata = { .data = (uint8_t *)data, .length = len, }; HASH_TRACE("Posted %zu of input len %zu made %zu", size_topost, len, size_inmade); retstatus = caam_cpy_block_src(&ctx->blockbuf, &srcdata, size_inmade); ret = caam_status_to_tee_result(retstatus); } exit_update: caam_dmaobj_free(&src); if (ret) do_free_intern(ctx); return ret; } TEE_Result caam_hash_hmac_final(struct hashctx *ctx, uint8_t *digest, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; const struct hashalg *alg = NULL; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; struct caamdmaobj dig = { }; HASH_TRACE("Hash/HMAC Final (%p)", ctx); if (!digest || !len || !ctx) return TEE_ERROR_BAD_PARAMETERS; alg = ctx->alg; if (!ctx->ctx.data) return TEE_ERROR_GENERIC; ret = caam_dmaobj_output_sgtbuf(&dig, digest, len, alg->size_digest); if (ret) goto out; HASH_TRACE("Final Type 0x%" PRIX32 " - Digest %zu", alg->type, len); desc = ctx->descriptor; caam_desc_init(desc); /* Set the descriptor Header with length */ caam_desc_add_word(desc, DESC_HEADER(0)); /* Load key if any */ if (ctx->key.length) do_desc_load_key(desc, &ctx->key); if (ctx->ctx.length) { HASH_TRACE("Final Operation"); if (ctx->key.length) caam_desc_add_word(desc, HMAC_FINAL_PRECOMP(alg->type)); else caam_desc_add_word(desc, HASH_FINAL(alg->type)); /* Running context to restore */ caam_desc_add_word(desc, LD_NOIMM(CLASS_2, REG_CTX, ctx->ctx.length)); caam_desc_add_ptr(desc, ctx->ctx.paddr); cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data, ctx->ctx.length); HASH_DUMPBUF("CTX", ctx->ctx.data, ctx->ctx.length); ctx->ctx.length = 0; } else { HASH_TRACE("Init/Final Operation"); if (ctx->key.length) caam_desc_add_word(desc, HMAC_INITFINAL_PRECOMP(alg->type)); else caam_desc_add_word(desc, HASH_INITFINAL(alg->type)); } HASH_DUMPBUF("Temporary Block", ctx->blockbuf.buf.data, ctx->blockbuf.filled); caam_desc_add_word(desc, FIFO_LD_EXT(CLASS_2, MSG, LAST_C2)); caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr); caam_desc_add_word(desc, ctx->blockbuf.filled); if (ctx->blockbuf.filled) cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data, ctx->blockbuf.filled); ctx->blockbuf.filled = 0; /* Save the final digest */ caam_desc_store(desc, &dig, CLASS_2, REG_CTX); caam_dmaobj_cache_push(&dig); HASH_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { caam_dmaobj_copy_to_orig(&dig); HASH_DUMPBUF("Digest", digest, (size_t)alg->size_digest); ret = TEE_SUCCESS; } else { HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_dmaobj_free(&dig); return ret; } void caam_hash_hmac_copy_state(struct hashctx *dst, struct hashctx *src) { HASH_TRACE("Copy State context (%p) to (%p)", src, dst); assert(dst && src); if (!dst->initialized && caam_hash_hmac_init(dst)) panic(); dst->alg = src->alg; if (src->ctx.length) { cache_operation(TEE_CACHEINVALIDATE, src->ctx.data, src->ctx.length); memcpy(dst->ctx.data, src->ctx.data, src->ctx.length); dst->ctx.length = src->ctx.length; cache_operation(TEE_CACHECLEAN, dst->ctx.data, dst->ctx.length); } if (src->blockbuf.filled) { struct caambuf srcdata = { .data = src->blockbuf.buf.data, .length = src->blockbuf.filled }; caam_cpy_block_src(&dst->blockbuf, &srcdata, 0); } if (src->key.data) { memcpy(dst->key.data, src->key.data, src->key.length); dst->key.length = src->key.length; } } enum caam_status caam_hash_init(struct caam_jrcfg *caam_jrcfg) { enum caam_status retstatus = CAAM_FAILURE; vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; caam_hash_limit = caam_hal_ctrl_hash_limit(jr_base); if (caam_hash_limit != UINT8_MAX) { if (drvcrypt_register_hash(&caam_hash_allocate) == TEE_SUCCESS) retstatus = CAAM_NO_ERROR; } return retstatus; } optee_os-4.3.0/core/drivers/crypto/caam/hash/caam_hash_mac.c000066400000000000000000000202601464416617300240110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Implementation of Hashing functions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #ifdef CFG_PHYS_64BIT #define KEY_REDUCE_DESC_ENTRIES 10 #define KEY_COMPUTE_DESC_ENTRIES 10 #else #define KEY_REDUCE_DESC_ENTRIES 8 #define KEY_COMPUTE_DESC_ENTRIES 8 #endif static const struct crypto_mac_ops hmac_ops; /* * Format the MAC context to keep the reference to the operation driver. */ struct crypto_mac { struct crypto_mac_ctx mac_ctx; /* Crypto MAC API context */ struct hashctx *ctx; /* HMAC context */ }; /* * Keep the HW hash limit because after the initialization * of the module, we don't have the CAAM Controller base address * to call the function returning the HW capacity. */ static uint8_t caam_hash_limit; /* * Returns the reference to the driver context * * @ctx API Context */ static struct crypto_mac *to_mac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == &hmac_ops); return container_of(ctx, struct crypto_mac, mac_ctx); } /* * Reduce key to be a hash algorithm block size maximum * * @alg Reference to the algorithm definition * @inkey Key to be reduced * @outkey [out] key resulting */ static enum caam_status do_reduce_key(struct caamdmaobj *reduce_key, const struct hashalg *alg, const uint8_t *inkey, size_t len) { enum caam_status retstatus = CAAM_FAILURE; struct caamdmaobj key = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; if (caam_dmaobj_input_sgtbuf(&key, inkey, len)) return CAAM_OUT_MEMORY; /* Allocate the job descriptor */ desc = caam_calloc_desc(KEY_REDUCE_DESC_ENTRIES); if (!desc) { retstatus = CAAM_OUT_MEMORY; goto out; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, HASH_INITFINAL(alg->type)); /* Load the input key */ caam_desc_fifo_load(desc, &key, CLASS_2, MSG, LAST_C2); /* Store key reduced */ caam_desc_store(desc, reduce_key, CLASS_2, REG_CTX); caam_dmaobj_cache_push(&key); caam_dmaobj_cache_push(reduce_key); HASH_DUMPDESC(desc); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus != CAAM_NO_ERROR) { HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); retstatus = CAAM_FAILURE; } out: caam_dmaobj_free(&key); caam_free_desc(&desc); return retstatus; } /* * Initialization of the HMAC operation. * Split the input key using the CAAM HW HMAC operation * Call common initialization operation between hash and HMAC * * @ctx Operation software context * @key Input key to compute * @len Key length */ static TEE_Result do_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *inkey, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct crypto_mac *mac = to_mac_ctx(ctx); struct hashctx *hmac_ctx = mac->ctx; const struct hashalg *alg = hmac_ctx->alg; struct caamdmaobj reduce_key = { }; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; /* First initialize the context */ ret = caam_hash_hmac_init(hmac_ctx); if (ret != TEE_SUCCESS) return ret; HASH_TRACE("split key length %zu", len); /* Allocate the job descriptor */ desc = caam_calloc_desc(KEY_COMPUTE_DESC_ENTRIES); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } hmac_ctx->key.length = alg->size_key; if (len > alg->size_block) { HASH_TRACE("Input key must be reduced"); ret = caam_dmaobj_output_sgtbuf(&reduce_key, NULL, 0, alg->size_digest); if (ret) { HASH_TRACE("Reduced Key allocation error"); goto out; } retstatus = do_reduce_key(&reduce_key, alg, inkey, len); if (retstatus != CAAM_NO_ERROR) goto out; } else { /* Key size is correct use directly the input key */ ret = caam_dmaobj_input_sgtbuf(&reduce_key, inkey, len); if (ret) goto out; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); /* Load either input key or the reduced input key into key register */ caam_desc_load_key(desc, &reduce_key, CLASS_2, REG); /* Split the key */ caam_desc_add_word(desc, HMAC_INIT_DECRYPT(alg->type)); caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_2, MSG, LAST_C2, 0)); /* Store the split key */ caam_desc_add_word(desc, FIFO_ST(CLASS_NO, C2_MDHA_SPLIT_KEY_AES_ECB_JKEK, hmac_ctx->key.length)); caam_desc_add_ptr(desc, hmac_ctx->key.paddr); HASH_DUMPDESC(desc); caam_dmaobj_cache_push(&reduce_key); cache_operation(TEE_CACHEFLUSH, hmac_ctx->key.data, hmac_ctx->key.length); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { HASH_DUMPBUF("Split Key", hmac_ctx->key.data, hmac_ctx->key.length); ret = TEE_SUCCESS; } else { HASH_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_dmaobj_free(&reduce_key); caam_free_desc(&desc); return ret; } /* * Update the HMAC operation * Call common update operation between hash and HMAC * * @ctx Operation Software context * @data Data to hash * @len Data length */ static TEE_Result do_hmac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { struct crypto_mac *mac = to_mac_ctx(ctx); return caam_hash_hmac_update(mac->ctx, data, len); } /* * Finalize the HMAC operation * Call common final operation between hash and HMAC * * @ctx Operation Software context * @digest [out] Hash digest buffer * @len Digest buffer length */ static TEE_Result do_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { struct crypto_mac *mac = to_mac_ctx(ctx); return caam_hash_hmac_final(mac->ctx, digest, len); } /* * Free the software context * Call common free operation between hash and HMAC * * @ctx Caller context variable */ static void do_hmac_free(struct crypto_mac_ctx *ctx) { struct crypto_mac *mac = to_mac_ctx(ctx); caam_hash_hmac_free(mac->ctx); free(mac); } /* * Copy sofware HMAC context * Call common copy operation between hash and HMAC * * @dst_ctx [out] Reference the context destination * @src_ctx Reference the context source */ static void do_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct crypto_mac *mac_src = to_mac_ctx(src_ctx); struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx); return caam_hash_hmac_copy_state(mac_dst->ctx, mac_src->ctx); } /* * Registration of the HMAC driver */ static const struct crypto_mac_ops hmac_ops = { .init = do_hmac_init, .update = do_hmac_update, .final = do_hmac_final, .free_ctx = do_hmac_free, .copy_state = do_hmac_copy_state, }; /* * Allocate the internal hashing data context * * @ctx [out] Caller context reference * @algo Algorithm ID */ static TEE_Result caam_hmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo) { struct crypto_mac *mac = NULL; struct hashctx *hmac_ctx = NULL; const struct hashalg *alg = NULL; TEE_Result ret = TEE_ERROR_GENERIC; HASH_TRACE("Allocate Context (%p) algo %" PRId32, ctx, algo); *ctx = NULL; alg = caam_hash_get_alg(algo); if (!alg) return TEE_ERROR_NOT_IMPLEMENTED; mac = calloc(1, sizeof(*mac)); if (!mac) return TEE_ERROR_OUT_OF_MEMORY; hmac_ctx = caam_calloc(sizeof(*hmac_ctx)); if (!hmac_ctx) { ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } hmac_ctx->alg = alg; mac->mac_ctx.ops = &hmac_ops; mac->ctx = hmac_ctx; *ctx = &mac->mac_ctx; ret = caam_hash_hmac_allocate(hmac_ctx); if (ret != TEE_SUCCESS) goto err; HASH_TRACE("Allocated Context (%p)", hmac_ctx); return TEE_SUCCESS; err: free(mac); if (hmac_ctx) caam_free(hmac_ctx); return ret; } enum caam_status caam_hmac_init(struct caam_jrcfg *caam_jrcfg) { vaddr_t jr_base = caam_jrcfg->base + caam_jrcfg->offset; caam_hash_limit = caam_hal_ctrl_hash_limit(jr_base); if (caam_hash_limit != UINT8_MAX && caam_hal_ctrl_splitkey_support(jr_base)) { if (drvcrypt_register_hmac(&caam_hmac_allocate)) return CAAM_FAILURE; } return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/hash/local.h000066400000000000000000000042671464416617300223750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019-2021 NXP * * CAAM hash/HMAC local header. */ #ifndef __LOCAL_H__ #define __LOCAL_H__ #include /* * Full hashing/HMAC data SW context */ struct hashctx { uint32_t *descriptor; /* Job descriptor */ struct caamblock blockbuf; /* Temporary block buffer */ struct caambuf ctx; /* Hash context used by the CAAM */ const struct hashalg *alg; /* Reference to the algo constants */ struct caambuf key; /* HMAC split key */ bool initialized; /* Context initialization flag */ }; /* * Hash/HMAC algorithm definition */ struct hashalg { uint32_t type; /* Algo type for operation */ uint8_t size_digest; /* Digest size */ uint8_t size_block; /* Computing block size */ uint8_t size_ctx; /* CAAM context register size (8 + digest size) */ uint8_t size_key; /* HMAC split key size */ }; /* First part CAAM HW context - message length */ #define HASH_MSG_LEN 8 /* * Initialization of the hash/HMAC operation * * @ctx Operation software context */ TEE_Result caam_hash_hmac_init(struct hashctx *ctx); /* * Update the hash/HMAC operation * * @ctx Operation software context * @data Data to hash * @len Data length */ TEE_Result caam_hash_hmac_update(struct hashctx *ctx, const uint8_t *data, size_t len); /* * Finalize the hash/HMAC operation * * @ctx Operation software context * @digest [out] Hash digest buffer * @len Digest buffer length */ TEE_Result caam_hash_hmac_final(struct hashctx *ctx, uint8_t *digest, size_t len); /* * Copy sofware hashing context * * @dst [out] Reference the destination context * @src Reference the source context */ void caam_hash_hmac_copy_state(struct hashctx *dst, struct hashctx *src); /* * Free the software context * * @ctx [in/out] Caller context variable */ void caam_hash_hmac_free(struct hashctx *ctx); /* * Get hash/HMAC algorithm definition * * @algo Hash algorithm */ const struct hashalg *caam_hash_get_alg(uint32_t algo); /* * Allocate the internal hashing data context * * @ctx [in/out] Caller context variable */ TEE_Result caam_hash_hmac_allocate(struct hashctx *ctx); #endif /* __LOCAL_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/hash/sub.mk000066400000000000000000000001401464416617300222360ustar00rootroot00000000000000incdirs-y += ../include srcs-y += caam_hash.c srcs-$(CFG_NXP_CAAM_HMAC_DRV) += caam_hash_mac.c optee_os-4.3.0/core/drivers/crypto/caam/include/000077500000000000000000000000001464416617300216215ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/include/caam_acipher.h000066400000000000000000000035571464416617300244000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief CAAM Asymmetric Cipher manager header. */ #ifndef __CAAM_ACIPHER_H__ #define __CAAM_ACIPHER_H__ #include #include #ifdef CFG_NXP_CAAM_RSA_DRV /* * Initialize the RSA module * * @caam_jrcfg JR configuration structure */ enum caam_status caam_rsa_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_rsa_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_RSA_DRV */ #ifdef CFG_NXP_CAAM_DH_DRV /* * Initialize the DH module * * @caam_jrcfg JR configuration structure */ enum caam_status caam_dh_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_dh_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_DH_DRV */ #ifdef CFG_NXP_CAAM_MATH_DRV /* * Initialize the MATH module * * @caam_jrcfg JR configuration structure */ enum caam_status caam_math_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_math_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_MATH_DRV */ #ifdef CFG_NXP_CAAM_ECC_DRV /* * Initialize the Cipher module * * @caam_jrcfg JR configuration structure */ enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_ecc_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_ECC_DRV */ #ifdef CFG_NXP_CAAM_DSA_DRV /* * Initialize the DSA module * * @caam_jrcfg CAAM job ring configuration */ enum caam_status caam_dsa_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_dsa_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_DSA_DRV */ #endif /* __CAAM_ACIPHER_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_blob.h000066400000000000000000000010411464416617300236650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 Pengutronix, Rouven Czerwinski */ #ifndef __CAAM_BLOB_H__ #define __CAAM_BLOB_H__ #include #ifdef CFG_NXP_CAAM_BLOB_DRV /* * Initialize the BLOB module * * @ctrl_addr Controller base address */ enum caam_status caam_blob_mkvb_init(vaddr_t baseaddr); #else static inline enum caam_status caam_blob_mkvb_init(vaddr_t baseaddr __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_BLOB_DRV */ #endif /* __CAAM_BLOB_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_cipher.h000066400000000000000000000015161464416617300242300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Brief CAAM Cipher manager header. */ #ifndef __CAAM_CIPHER_H__ #define __CAAM_CIPHER_H__ #include #ifdef CFG_NXP_CAAM_CIPHER_DRV /* * Initialize the Cipher module * * @ctrl_addr Controller base address */ enum caam_status caam_cipher_init(vaddr_t ctrl_addr); #else static inline enum caam_status caam_cipher_init(vaddr_t ctrl_addr __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_CIPHER_DRV */ #ifdef CFG_NXP_CAAM_CMAC_DRV /* * Initialize the CMAC module * * @ctrl_addr Controller base address */ enum caam_status caam_cmac_init(vaddr_t ctrl_addr); #else static inline enum caam_status caam_cmac_init(vaddr_t ctrl_addr __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_CMAC_DRV */ #endif /* __CAAM_CIPHER_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_common.h000066400000000000000000000021051464416617300242410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019, 2021 NXP * * CAAM driver common include file. */ #ifndef __CAAM_COMMON_H__ #define __CAAM_COMMON_H__ #include #include #include #include /* * Definition of the number of CAAM Jobs to manage in JR queues */ #if defined(CFG_NB_JOBS_QUEUE) #define NB_JOBS_QUEUE CFG_NB_JOBS_QUEUE #else #define NB_JOBS_QUEUE 10 #endif /* * Flag Job Ring Owner is Secure */ #define JROWNER_SECURE 0x10 /* * Job Ring Owner. Enumerate Id (expect the Secure Flag) correspond * to the HW ID. */ #if defined(CFG_MX7ULP) enum caam_jr_owner { JROWN_ARM_NS = 0x4, /* Non-Secure ARM */ JROWN_ARM_S = JROWNER_SECURE | 0x4, /* Secure ARM */ }; #elif defined(CFG_MX8ULP) enum caam_jr_owner { JROWN_ARM_NS = 0x7, /* Non-Secure ARM */ JROWN_ARM_S = JROWNER_SECURE | 0x7, /* Secure ARM */ }; #else enum caam_jr_owner { JROWN_ARM_NS = 0x1, /* Non-Secure ARM */ JROWN_ARM_S = JROWNER_SECURE | 0x1, /* Secure ARM */ }; #endif #endif /* __CAAM_COMMON_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h000066400000000000000000000035671464416617300262100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief Define the CCB Registers to use in the CAAM descriptor */ #ifndef __CAAM_DESC_CCB_DEFINES_H__ #define __CAAM_DESC_CCB_DEFINES_H__ /* CCB CHA Control Register */ #define CCTRL_ULOAD_PKHA_B BIT32(27) #define CCTRL_ULOAD_PKHA_A BIT32(26) /* CCB Clear Written Register */ #define CLR_WR_IFIFO_NFIFO BIT32(31) #define CLR_WR_RST_C2_CHA BIT32(28) #define CLR_WR_RST_C2_DSZ BIT32(18) /* CCB NFIFO */ #define NFIFO_CLASS(cla) SHIFT_U32(NFIFO_CLASS_##cla & 0x3, 30) #define NFIFO_CLASS_DECO 0x0 #define NFIFO_CLASS_C1 0x1 #define NFIFO_CLASS_BOTH 0x3 #define NFIFO_LC2 BIT32(29) #define NFIFO_LC1 BIT32(28) #define NFIFO_FC1 BIT32(26) #define NFIFO_STYPE(src) SHIFT_U32(NFIFO_STYPE_##src & 0x3, 24) #define NFIFO_STYPE_IFIFO 0x0 #define NFIFO_STYPE_PAD 0x2 #define NFIFO_DTYPE(data) SHIFT_U32(NFIFO_DTYPE_##data & 0xF, 20) #define NFIFO_DTYPE_MSG 0xF #define NFIFO_DTYPE_PKHA_N 0x8 #define NFIFO_DTYPE_PKHA_A 0xC #define NFIFO_PTYPE(pad) SHIFT_U32(NFIFO_PTYPE_##pad & 0x7, 16) #define NFIFO_PTYPE_ZERO 0x0 #define NFIFO_PTYPE_RND 0x3 #define NFIFO_DATA_LENGTH(len) SHIFT_U32((len) & 0xFFF, 0) #define NFIFO_PAD_LENGTH(len) SHIFT_U32((len) & 0x7F, 0) /* * CCB NFIFO Entry to pad data with pad type */ #define NFIFO_PAD(cla, options, data, pad, len) \ (NFIFO_CLASS(cla) | (options) | NFIFO_STYPE(PAD) | NFIFO_DTYPE(data) | \ NFIFO_PTYPE(pad) | NFIFO_PAD_LENGTH(len)) /* * CCB NFIFO Entry to move data from src to data */ #define NFIFO_NOPAD(cla, options, src, data, len) \ (NFIFO_CLASS(cla) | (options) | NFIFO_STYPE(src) | NFIFO_DTYPE(data) | \ NFIFO_PTYPE(ZERO) | NFIFO_DATA_LENGTH(len)) #endif /* __CAAM_DESC_CCB_DEFINES_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_desc_defines.h000066400000000000000000000536651464416617300254050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021, 2023 NXP * * Brief CAAM Descriptor defines. */ #ifndef __CAAM_DESC_DEFINES_H__ #define __CAAM_DESC_DEFINES_H__ #include /* * Common Command constants */ #define CMD_TYPE(cmd) SHIFT_U32((cmd) & 0x1F, 27) #define GET_CMD_TYPE(op) ((op) & (SHIFT_U32(0x1F, 27))) #define CMD_CLASS(val) SHIFT_U32((val) & 0x3, 25) #define CLASS_NO 0x0 #define CLASS_1 0x1 #define CLASS_2 0x2 #define CLASS_DECO 0x3 #define CMD_SGT BIT32(24) #define CMD_IMM BIT32(23) /* * HEADER Job Descriptor Header format */ #define CMD_HDR_JD_TYPE CMD_TYPE(0x16) /* Must be ONE */ #define HDR_JD_ONE BIT32(23) /* Start Index if SHR = 0 */ #define HDR_JD_START_IDX(line) SHIFT_U32((line) & 0x3F, 16) /* Descriptor Length */ #define HDR_JD_DESCLEN(len) SHIFT_U32((len) & 0x7F, 0) #define GET_JD_DESCLEN(entry) ((entry) & 0x7F) /* * KEY Command fields */ #define CMD_KEY_TYPE CMD_TYPE(0x00) /* Key Destination */ #define KEY_DEST(val) SHIFT_U32((KEY_DEST_##val) & 0x3, 16) #define KEY_DEST_REG 0x0 #define KEY_DEST_PKHA_E 0x1 #define KEY_DEST_AFHA_SBOX 0x2 #define KEY_DEST_MDHA_SPLIT 0x3 /* Plaintext Store */ #define KEY_PTS BIT32(14) /* Key Length */ #define KEY_LENGTH(len) SHIFT_U32((len) & 0x3FF, 0) /* * LOAD Command fields */ #define CMD_LOAD_TYPE CMD_TYPE(0x02) /* Load Destination */ #define LOAD_DST(reg) SHIFT_U32((reg) & 0x7F, 16) /* Offset in destination register */ #define LOAD_OFFSET(off) SHIFT_U32((off) & 0xFF, 8) /* Length */ #define LOAD_LENGTH(len) SHIFT_U32((len) & 0xFF, 0) /* * STORE Command fields */ #define CMD_STORE_TYPE CMD_TYPE(0x0A) #define CMD_STORE_SEQ_TYPE CMD_TYPE(0x0B) /* Store Source */ #define STORE_SRC(reg) SHIFT_U32((reg) & 0x7F, 16) /* Offset in source register */ #define STORE_OFFSET(off) SHIFT_U32((off) & 0xFF, 8) /* Length */ #define STORE_LENGTH(len) SHIFT_U32((len) & 0xFF, 0) /* * Define the Load/Store Registers Source and Destination */ #define REG_MODE 0x00 #define REG_KEY_SIZE 0x01 #define REG_DATA_SIZE 0x02 #define REG_ICV_SIZE 0x03 #define REG_DECO_MID_STATUS 0x04 #define REG_DECO_CTRL2 0x05 #define REG_CHA_CTRL 0x06 #define REG_DECO_CTRL 0x06 #define REG_IRQ_CTRL 0x07 #define REG_DECO_PROT_OVERWRITE 0x07 #define REG_CLEAR_WRITTEN 0x08 #define REG_MATH0 0x08 #define REG_MATH1 0x09 #define REG_MATH2 0x0A #define REG_CHA_INST_SELECT 0x0A #define REG_AAD_SIZE 0x0B #define REG_MATH3 0x0B #define REG_ALT_DATA_SIZE_C1 0x0F #define REG_PKHA_A_SIZE 0x10 #define REG_PKHA_B_SIZE 0x11 #define REG_PKHA_N_SIZE 0x12 #define REG_PKHA_E_SIZE 0x13 #define REG_CTX 0x20 #define REG_MATH0_DW 0x30 #define REG_MATH1_DW 0x31 #define REG_MATH2_DW 0x32 #define REG_MATH3_DW 0x33 #define REG_MATH0_B 0x38 #define REG_MATH1_B 0x39 #define REG_MATH2_B 0x3A #define REG_MATH3_B 0x3B #define REG_KEY 0x40 #define REG_DECO_DESC 0x40 #define REG_NFIFO_n_SIZE 0x70 #define REG_NFIFO_MATH 0x73 #define REG_SIZE 0x74 #define REG_SIZE_MATH 0x75 #define REG_IFIFO_SHIFT 0x76 #define REG_OFIFO_SHIFT 0x77 #define REG_AUX_FIFO 0x78 #define REG_NFIFO 0x7A #define REG_IFIFO 0x7C #define REG_OFIFO 0x7E /* * FIFO LOAD Command fields */ #define CMD_FIFO_LOAD_TYPE CMD_TYPE(0x04) /* Extended Length */ #define FIFO_LOAD_EXT BIT32(22) /* Input data */ #define FIFO_LOAD_INPUT(reg) SHIFT_U32((FIFO_LOAD_##reg) & 0x3F, 16) #define FIFO_LOAD_ACTION(act) SHIFT_U32((FIFO_LOAD_##act) & 0x3F, 16) /* Length */ #define FIFO_LOAD_MAX 0xFFFF #define FIFO_LOAD_LENGTH(len) SHIFT_U32((len) & FIFO_LOAD_MAX, 0) /* * Define the FIFO Load Type Input */ #define FIFO_LOAD_PKHA_A0 0x00 #define FIFO_LOAD_PKHA_A1 0x01 #define FIFO_LOAD_PKHA_A2 0x02 #define FIFO_LOAD_PKHA_A3 0x03 #define FIFO_LOAD_PKHA_B0 0x04 #define FIFO_LOAD_PKHA_B1 0x05 #define FIFO_LOAD_PKHA_B2 0x06 #define FIFO_LOAD_PKHA_B3 0x07 #define FIFO_LOAD_PKHA_N 0x08 #define FIFO_LOAD_PKHA_A 0x0C #define FIFO_LOAD_PKHA_B 0x0D #define FIFO_LOAD_NO_INFO_NFIFO 0x0F #define FIFO_LOAD_MSG 0x10 #define FIFO_LOAD_MSG_C1_OUT_C2 0x18 #define FIFO_LOAD_IV 0x20 #define FIFO_LOAD_BITDATA 0x2C #define FIFO_LOAD_AAD 0x30 #define FIFO_LOAD_ICV 0x38 /* Define Action of some FIFO Data */ #define FIFO_LOAD_NOACTION 0x0 #define FIFO_LOAD_FLUSH 0x1 #define FIFO_LOAD_LAST_C1 0x2 #define FIFO_LOAD_LAST_C2 0x4 /* * FIFO STORE Command fields */ #define CMD_FIFO_STORE_TYPE CMD_TYPE(0x0C) #define CMD_SEQ_FIFO_STORE_TYPE CMD_TYPE(0x0D) /* Extended Length */ #define FIFO_STORE_EXT BIT32(22) /* Output data */ #define FIFO_STORE_OUTPUT(reg) SHIFT_U32((FIFO_STORE_##reg) & 0x3F, 16) /* Length */ #define FIFO_STORE_MAX 0xFFFF #define FIFO_STORE_LENGTH(len) SHIFT_U32((len) & FIFO_STORE_MAX, 0) /* * Define the FIFO Store Type Output */ #define FIFO_STORE_PKHA_A0 0x00 #define FIFO_STORE_PKHA_A1 0x01 #define FIFO_STORE_PKHA_A2 0x02 #define FIFO_STORE_PKHA_A3 0x03 #define FIFO_STORE_PKHA_B0 0x04 #define FIFO_STORE_PKHA_B1 0x05 #define FIFO_STORE_PKHA_B2 0x06 #define FIFO_STORE_PKHA_B3 0x07 #define FIFO_STORE_PKHA_N 0x08 #define FIFO_STORE_PKHA_A 0x0C #define FIFO_STORE_PKHA_B 0x0D #define FIFO_STORE_AFHA_SBOX_AES_CCM_JKEK 0x10 #define FIFO_STORE_AFHA_SBOX_AES_CCM_TKEK 0x11 #define FIFO_STORE_PKHA_E_AES_CCM_JKEK 0x12 #define FIFO_STORE_PKHA_E_AES_CCM_TKEK 0x13 #define FIFO_STORE_KEY_AES_CCM_JKEK 0x14 #define FIFO_STORE_KEY_AES_CCM_TKEK 0x15 #define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_CCM_JKEK 0x16 #define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_CCM_TKEK 0x17 #define FIFO_STORE_AFHA_SBOX_AES_ECB_JKEK 0x20 #define FIFO_STORE_AFHA_SBOX_AES_ECB_TKEK 0x21 #define FIFO_STORE_PKHA_E_AES_ECB_JKEK 0x22 #define FIFO_STORE_PKHA_E_AES_ECB_TKEK 0x23 #define FIFO_STORE_KEY_AES_ECB_JKEK 0x24 #define FIFO_STORE_KEY_AES_ECB_TKEK 0x25 #define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_ECB_JKEK 0x26 #define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_ECB_TKEK 0x27 #define FIFO_STORE_MSG_DATA 0x30 #define FIFO_STORE_RNG_TO_MEM 0x34 #define FIFO_STORE_RNG_STAY_FIFO 0x35 #define FIFO_STORE_SKIP 0x3F /* * MOVE Command fields */ #define CMD_MOVE_TYPE CMD_TYPE(0x0F) /* Auxiliary */ #define MOVE_AUX(val) SHIFT_U32((val) & 0x3, 25) /* Wait for completion */ #define MOVE_WC BIT32(24) /* Source */ #define MOVE_SRC(src) MOVE_SRC_##src #define MOVE_REG_SRC(reg) SHIFT_U32((reg) & 0xF, 20) #define MOVE_SRC_C1_CTX_REG MOVE_REG_SRC(0x0) #define MOVE_SRC_C2_CTX_REG MOVE_REG_SRC(0x1) #define MOVE_SRC_OFIFO MOVE_REG_SRC(0x2) #define MOVE_SRC_DESC_BUF MOVE_REG_SRC(0x3) #define MOVE_SRC_MATH_REG0 MOVE_REG_SRC(0x4) #define MOVE_SRC_MATH_REG1 MOVE_REG_SRC(0x5) #define MOVE_SRC_MATH_REG2 MOVE_REG_SRC(0x6) #define MOVE_SRC_MATH_REG3 MOVE_REG_SRC(0x7) #define MOVE_SRC_NFIFO_DECO_ALIGN MOVE_REG_SRC(0x8) #define MOVE_SRC_NFIFO_C1_ALIGN (MOVE_REG_SRC(0x9) | MOVE_AUX(0x1)) #define MOVE_SRC_NFIFO_C2_ALIGN (MOVE_REG_SRC(0x9) | MOVE_AUX(0x0)) #define MOVE_SRC_DECO_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x0)) #define MOVE_SRC_C1_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x1)) #define MOVE_SRC_C2_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x2)) #define MOVE_SRC_C1_KEY MOVE_REG_SRC(0xD) #define MOVE_SRC_C2_KEY MOVE_REG_SRC(0xE) /* Destination */ #define MOVE_DST(dst) SHIFT_U32((MOVE_DST_##dst), 16) #define MOVE_DST_C1_CTX_REG 0x0 #define MOVE_DST_C2_CTX_REG 0x1 #define MOVE_DST_OFIFO 0x2 #define MOVE_DST_DESC_BUF 0x3 #define MOVE_DST_MATH_REG0 0x4 #define MOVE_DST_MATH_REG1 0x5 #define MOVE_DST_MATH_REG2 0x6 #define MOVE_DST_MATH_REG3 0x7 #define MOVE_DST_IFIFO_C1 0x8 #define MOVE_DST_IFIFO_C2 0x9 #define MOVE_DST_IFIFO_C2_LC2 ((0x9 << 16 | MOVE_AUX(0x1)) >> 16) #define MOVE_DST_IFIFO 0xA #define MOVE_DST_PKHA_A 0xC #define MOVE_DST_C1_KEY 0xD #define MOVE_DST_C2_KEY 0xE #define MOVE_DST_AUX_FIFO 0xF /* Offset */ #define MOVE_OFFSET(off) SHIFT_U32((off) & 0xFF, 8) /* Length */ #define MOVE_LENGTH(len) SHIFT_U32((len) & 0xFF, 0) /* * Operation Command fields * Algorithm/Protocol/PKHA */ #define CMD_OP_TYPE CMD_TYPE(0x10) /* Operation Type */ #define OP_TYPE(type) SHIFT_U32((OP_TYPE_##type) & 0x7, 24) #define OP_TYPE_UNI 0x0 #define OP_TYPE_PKHA 0x1 #define OP_TYPE_CLASS1 0x2 #define OP_TYPE_CLASS2 0x4 #define OP_TYPE_DECAPS 0x6 #define OP_TYPE_ENCAPS 0x7 /* Protocol Identifier */ #define PROTID(id) SHIFT_U32((PROTID_##id) & 0xFF, 16) #define PROTID_BLOB 0x0D #define PROTID_MPKEY 0x14 #define PROTID_PKKEY 0x14 #define PROTID_MPSIGN 0x15 #define PROTID_DSASIGN 0x15 #define PROTID_DSAVERIFY 0x16 #define PROTID_SHARED_SECRET 0x17 #define PROTID_RSA_ENC 0x18 #define PROTID_RSA_DEC 0x19 #define PROTID_RSA_FINISH_KEY 0x1A /* * RSA Protocol Information */ #define PROT_RSA_FMT(format) SHIFT_U32((PROT_RSA_FMT_##format) & 0x1, 12) #define PROT_RSA_FMT_NO 0 #define PROT_RSA_FMT_PKCS_V1_5 1 #define PROT_RSA_DEC_KEYFORM(format) SHIFT_U32(((format) - 1) & 0x3, 0) /* RSA Key Protocol Information */ #define PROT_RSA_KEY(format) SHIFT_U32((PROT_RSA_KEY_##format) & 0x3, 0) #define PROT_RSA_KEY_ALL 0 #define PROT_RSA_KEY_N_D 2 #define PROT_RSA_FINISH_KEY_ENC_OUT(alg) PROT_RSA_FINISH_KEY_ENC_OUT_##alg #define PROT_RSA_FINISH_KEY_ENC_OUT_ECB BIT32(6) #define PROT_RSA_FINISH_KEY_ENC_OUT_CCM BIT32(6) #define PROT_RSA_FINISH_KEY_ENC(alg) PROT_RSA_FINISH_KEY_ENC_##alg #define PROT_RSA_FINISH_KEY_ENC_ECB 0 #define PROT_RSA_FINISH_KEY_ENC_CCM BIT32(4) #define PROT_RSA_FINISH_KEY(alg) PROT_RSA_FINISH_KEY_##alg #define PROT_RSA_FINISH_KEY_NONE 0 #define PROT_RSA_FINISH_KEY_ECB (PROT_RSA_FINISH_KEY_ENC_OUT_ECB | \ PROT_RSA_FINISH_KEY_ENC_ECB) #define PROT_RSA_FINISH_KEY_CCM (PROT_RSA_FINISH_KEY_ENC_OUT_CCM | \ PROT_RSA_FINISH_KEY_ENC_CCM) #define PROT_RSA_KEY_ENC(format) SHIFT_U32((PROT_RSA_KEY_ENC_##format) & 0x3, 8) #define PROT_RSA_KEY_ENC_NONE 0 #define PROT_RSA_KEY_ENC_ECB 1 #define PROT_RSA_KEY_ENC_CCM 3 /* * ECC Protocol Information */ #define PROT_PK_MSG(type) SHIFT_U32(PROT_PK_MSG_##type, 10) #define PROT_PK_MSG_MES_REP 0 #define PROT_PK_MSG_HASHED 2 #define PROT_PK_TYPE(type) SHIFT_U32(PROT_PK_##type, 1) #define PROT_PK_DL 0 #define PROT_PK_ECC 1 #define PROT_PRI_ENC(alg) PROT_PRI_ENC_##alg #define PROT_PRI_ENC_ECB BIT32(2) #define PROT_PRI_ENC_CCM BIT32(2) #define PROT_PRI_EXT(type) PROT_PRI_EXT_##type #define PROT_PRI_EXT_ECB 0 #define PROT_PRI_EXT_CCM BIT32(4) #define PROT_PRI(alg) PROT_PRI_##alg #define PROT_PRI_NONE 0 #define PROT_PRI_ECB (PROT_PRI_ENC(ECB) | PROT_PRI_EXT(ECB)) #define PROT_PRI_CCM (PROT_PRI_ENC(CCM) | PROT_PRI_EXT(CCM)) /* * BLOB Protocol Information */ #define PROT_BLOB_FMT_MSTR BIT32(1) #define PROT_BLOB_TYPE(type) SHIFT_U32(1, PROT_BLOB_TYPE_##type) #define PROT_BLOB_TYPE_BLACK_KEY 2 #define PROT_BLOB_SEC_MEM BIT32(3) #define PROT_BLOB_EKT 8 #define PROT_BLOB_INFO(aes) SHIFT_U32(PROT_BLOB_AES_##aes, \ PROT_BLOB_EKT) #define PROT_BLOB_AES_CCM 1 #define PROT_BLOB_AES_ECB 0 #define PROT_BLOB_FORMAT(format) SHIFT_U32(0, PROT_BLOB_FORMAT_##format) #define PROT_BLOB_FORMAT_NORMAL 0 /* * MP Protocol Information */ #define PROT_MP_PUBK_SGT BIT32(31) #define PROT_MP_CURVE(curve) SHIFT_U32((curve) & 0xF, 17) /* * Algorithm Identifier */ #define OP_ALGO(algo) SHIFT_U32((ALGO_##algo) & 0xFF, 16) #define ALGO_AES 0x10 #define ALGO_DES 0x20 #define ALGO_3DES 0x21 #define ALGO_ARC4 0x30 #define ALGO_RNG 0x50 #define ALGO_MD5 0x40 #define ALGO_SHA1 0x41 #define ALGO_SHA224 0x42 #define ALGO_SHA256 0x43 #define ALGO_SHA384 0x44 #define ALGO_SHA512 0x45 #define ALGO_SHA512_224 0x46 #define ALGO_SHA512_256 0x47 /* Algorithm Additional Information */ #define ALGO_AAI(info) SHIFT_U32((AAI_##info) & 0x1FF, 4) /* AES AAI */ #define AAI_AES_CTR_MOD128 0x00 #define AAI_AES_CBC 0x10 #define AAI_AES_ECB 0x20 #define AAI_AES_CFB 0x30 #define AAI_AES_OFB 0x40 #define AAI_AES_CMAC 0x60 #define AAI_AES_XCBC_MAC 0x70 #define AAI_AES_CCM 0x80 #define AAI_AES_GCM 0x90 /* DES AAI */ #define AAI_DES_CBC 0x10 #define AAI_DES_ECB 0x20 #define AAI_DES_CFB 0x30 #define AAI_DES_OFB 0x40 /* Digest MD5/SHA AAI */ #define AAI_DIGEST_HASH 0x00 #define AAI_DIGEST_HMAC 0x01 #define AAI_DIGEST_SMAC 0x02 #define AAI_DIGEST_HMAC_PRECOMP 0x04 /* Algorithm State */ #define ALGO_AS(state) SHIFT_U32((AS_##state) & 0x3, 2) #define AS_UPDATE 0x0 #define AS_INIT 0x1 #define AS_FINAL 0x2 #define AS_INIT_FINAL 0x3 /* Algorithm Encrypt/Decrypt */ #define ALGO_DECRYPT SHIFT_U32(0x0, 0) #define ALGO_ENCRYPT SHIFT_U32(0x1, 0) /* * Specific RNG Algorithm bits 12-0 */ /* Secure Key */ #define ALGO_RNG_SK BIT32(12) /* State Handle */ #define ALGO_RNG_SH(sh) SHIFT_U32((sh) & 0x3, 4) /* Prediction Resistance */ #define ALGO_RNG_PR BIT32(1) /* State */ #define AS_RNG_GENERATE 0x0 #define AS_RNG_INSTANTIATE 0x1 #define AS_RNG_RESEED 0x2 #define AS_RNG_UNINSTANTIATE 0x3 /* * JUMP Command fields */ #define CMD_JUMP_TYPE CMD_TYPE(0x14) /* Jump Select Type */ #define JMP_JSL BIT32(24) /* Jump Type */ #define JUMP_TYPE(type) SHIFT_U32((JMP_##type) & 0xF, 20) #define JMP_LOCAL 0x0 #define JMP_LOCAL_INC 0x1 #define JMP_SUBROUTINE_CALL 0x2 #define JMP_LOCAL_DEC 0x3 #define JMP_NON_LOCAL 0x4 #define JMP_SUBROUTINE_RET 0x6 #define JMP_HALT 0x8 #define JMP_HALT_USER_STATUS 0xC /* Test Type */ #define JUMP_TST_TYPE(type) SHIFT_U32((JMP_TST_##type) & 0x3, 16) #define JMP_TST_ALL_COND_TRUE 0x0 #define JMP_TST_ALL_COND_FALSE 0x1 #define JMP_TST_ANY_COND_TRUE 0x2 #define JMP_TST_ANY_COND_FALSE 0x3 /* Jump Source to increment/decrement */ #define JMP_SRC(src) SHIFT_U32((JMP_SRC_##src) & 0xF, 12) #define JMP_SRC_MATH_0 0x0 /* Test Condition */ #define JMP_COND(cond) SHIFT_U32((JMP_COND_##cond) & 0xFF, 8) #define JMP_COND_MATH(cond) SHIFT_U32((JMP_COND_MATH_##cond) & 0xF, 8) #define JMP_COND_NONE 0x00 #define JMP_COND_PKHA_IS_ZERO 0x80 #define JMP_COND_PKHA_GCD_1 0x40 #define JMP_COND_PKHA_IS_PRIME 0x20 #define JMP_COND_MATH_N 0x08 #define JMP_COND_MATH_Z 0x04 #define JMP_COND_NIFP 0x04 #define JMP_COND_MATH_C 0x02 #define JMP_COND_MATH_NV 0x01 /* Local Offset */ #define JMP_LOCAL_OFFSET(off) SHIFT_U32((off) & 0xFF, 0) /* * MATH Command fields */ #define CMD_MATH_TYPE CMD_TYPE(0x15) #define CMD_MATHI_TYPE CMD_TYPE(0x1D) /* Immediate Four Bytes */ #define MATH_IFB BIT32(26) /* Function Mathematical */ #define MATH_FUNC(func) SHIFT_U32((MATH_FUNC_##func) & 0xF, 20) #define MATH_FUNC_ADD 0x0 #define MATH_FUNC_ADD_W_CARRY 0x1 #define MATH_FUNC_SUB 0x2 #define MATH_FUNC_SUB_W_BORROW 0x3 #define MATH_FUNC_OR 0x4 #define MATH_FUNC_AND 0x5 #define MATH_FUNC_XOR 0x6 #define MATH_FUNC_SHIFT_L 0x7 #define MATH_FUNC_SHIFT_R 0x8 #define MATH_FUNC_SHLD 0x9 #define MATH_FUNC_ZBYTE 0xA #define MATH_FUNC_SWAP_BYTES 0xB /* Source 0 */ #define MATH_SRC0(reg) SHIFT_U32((MATH_SRC0_##reg) & 0xF, 16) #define MATH_SRC0_REG0 0x0 #define MATH_SRC0_REG1 0x1 #define MATH_SRC0_REG2 0x2 #define MATH_SRC0_IMM_DATA 0x4 #define MATH_SRC0_DPOVRD 0x7 #define MATH_SRC0_SIL 0x8 #define MATH_SRC0_SOL 0x9 #define MATH_SRC0_VSIL 0xA #define MATH_SRC0_VSOL 0xB #define MATH_SRC0_ZERO 0xC #define MATH_SRC0_ONE 0xF /* Source 1 */ #define MATH_SRC1(reg) SHIFT_U32((MATH_SRC1_##reg) & 0xF, 12) #define MATH_SRC1_REG0 0x0 #define MATH_SRC1_REG1 0x1 #define MATH_SRC1_REG2 0x2 #define MATH_SRC1_IMM_DATA 0x4 #define MATH_SRC1_DPOVRD 0x7 #define MATH_SRC1_VSIL 0x8 #define MATH_SRC1_VSOL 0x9 #define MATH_SRC1_IFIFO 0xA #define MATH_SRC1_OFIFO 0xB #define MATH_SRC1_ONE 0xC #define MATH_SRC1_ZERO 0xF /* Destination */ #define MATH_DST(reg) SHIFT_U32((MATH_DST_##reg) & 0xF, 8) #define MATH_DST_REG0 0x0 #define MATH_DST_REG1 0x1 #define MATH_DST_REG2 0x2 #define MATH_DST_DPOVRD 0x7 #define MATH_DST_SIL 0x8 #define MATH_DST_SOL 0x9 #define MATH_DST_VSIL 0xA #define MATH_DST_VSOL 0xB #define MATH_DST_NODEST 0xF /* Length */ #define MATH_LENGTH(len) SHIFT_U32((len) & 0xF, 0) /* Immediate Value - MATHI operation */ #define MATHI_SRC(reg) SHIFT_U32((MATH_SRC0_##reg) & 0xF, 16) #define MATHI_DST(reg) SHIFT_U32((MATH_DST_##reg) & 0xF, 12) #define MATHI_IMM_VALUE(val) SHIFT_U32((val) & 0xFF, 4) /* * Sequence Input/Output */ #define CMD_SEQ_IN_TYPE CMD_TYPE(0x1E) #define CMD_SEQ_OUT_TYPE CMD_TYPE(0x1F) /* Extended Length */ #define SEQ_EXT BIT(22) /* Length */ #define SEQ_LENGTH(len) SHIFT_U32((len) & 0xFFFF, 0) /* * PKHA Operation */ #define PKHA_ALG SHIFT_U32(0x8, 20) #define PKHA_F2M BIT32(17) #define PKHA_OUTSEL(dst) SHIFT_U32((PKHA_OUTSEL_##dst) & 0x3, 8) #define PKHA_OUTSEL_B 0x0 #define PKHA_OUTSEL_A 0x1 #define PKHA_FUNC(func) SHIFT_U32((PKHA_FUNC_##func) & 0x3F, 0) #define PKHA_FUNC_CPY_NSIZE 0x10 #define PKHA_FUNC_CPY_SSIZE 0x11 #define PKHA_FUNC_MOD_ADD_A_B 0x02 #define PKHA_FUNC_MOD_SUB_A_B 0x03 #define PKHA_FUNC_MOD_SUB_B_A 0x04 #define PKHA_FUNC_MOD_MUL_A_B 0x05 #define PKHA_FUNC_MOD_EXP_A_E 0x06 #define PKHA_FUNC_MOD_AMODN 0x07 #define PKHA_FUNC_MOD_INV_A 0x08 #define PKHA_FUNC_ECC_POINT_ADD_P1_P2 0x09 #define PKHA_FUNC_ECC_POINT_DBL_P1 0x0A #define PKHA_FUNC_ECC_POINT_MUL_E_P1 0x0B #define PKHA_FUNC_MONT_RADIX_R2_MODE_N 0x0C #define PKHA_FUNC_GCD_A_N 0x0E #define PKHA_FUNC_MR_PRIMER_TEST 0x0F #define PKHA_FUNC_MOD_CHECK_POINT 0x1C /* PKHA Copy Memory Source and Destination */ #define PKHA_REG_SRC(reg) SHIFT_U32((PKHA_REG_##reg) & 0x7, 17) #define PKHA_REG_DST(reg) SHIFT_U32((PKHA_REG_##reg) & 0x3, 10) #define PKHA_REG_A 0x0 #define PKHA_REG_B 0x1 #define PKHA_REG_E 0x2 #define PKHA_REG_N 0x3 #define PKHA_SEG_SRC(seg) SHIFT_U32((seg) & 0x3, 8) #define PKHA_SEG_DST(seg) SHIFT_U32((seg) & 0x3, 6) #define PKHA_CPY_SRC(src) PKHA_CPY_SRC_##src #define PKHA_CPY_SRC_A0 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(0)) #define PKHA_CPY_SRC_A1 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(1)) #define PKHA_CPY_SRC_A2 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(2)) #define PKHA_CPY_SRC_A3 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(3)) #define PKHA_CPY_SRC_B0 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(0)) #define PKHA_CPY_SRC_B1 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(1)) #define PKHA_CPY_SRC_B2 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(2)) #define PKHA_CPY_SRC_B3 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(3)) #define PKHA_CPY_SRC_N0 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(0)) #define PKHA_CPY_SRC_N1 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(1)) #define PKHA_CPY_SRC_N2 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(2)) #define PKHA_CPY_SRC_N3 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(3)) #define PKHA_CPY_DST(dst) PKHA_CPY_DST_##dst #define PKHA_CPY_DST_A0 (PKHA_REG_DST(A) | PKHA_SEG_DST(0)) #define PKHA_CPY_DST_A1 (PKHA_REG_DST(A) | PKHA_SEG_DST(1)) #define PKHA_CPY_DST_A2 (PKHA_REG_DST(A) | PKHA_SEG_DST(2)) #define PKHA_CPY_DST_A3 (PKHA_REG_DST(A) | PKHA_SEG_DST(3)) #define PKHA_CPY_DST_B0 (PKHA_REG_DST(B) | PKHA_SEG_DST(0)) #define PKHA_CPY_DST_B1 (PKHA_REG_DST(B) | PKHA_SEG_DST(1)) #define PKHA_CPY_DST_B2 (PKHA_REG_DST(B) | PKHA_SEG_DST(2)) #define PKHA_CPY_DST_B3 (PKHA_REG_DST(B) | PKHA_SEG_DST(3)) #define PKHA_CPY_DST_N0 (PKHA_REG_DST(N) | PKHA_SEG_DST(0)) #define PKHA_CPY_DST_N1 (PKHA_REG_DST(N) | PKHA_SEG_DST(1)) #define PKHA_CPY_DST_N2 (PKHA_REG_DST(N) | PKHA_SEG_DST(2)) #define PKHA_CPY_DST_N3 (PKHA_REG_DST(N) | PKHA_SEG_DST(3)) #define PKHA_CPY_DST_E (PKHA_REG_DST(E)) /* * Descriptor Protocol Data Block */ /* RSA Encryption */ #define PDB_RSA_ENC_SGT_F SHIFT_U32(1, 31) #define PDB_RSA_ENC_SGT_G SHIFT_U32(1, 30) #define PDB_RSA_ENC_E_SIZE(len) SHIFT_U32((len) & 0xFFF, 12) #define PDB_RSA_ENC_N_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) #define PDB_RSA_ENC_F_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) /* RSA Decryption */ #define PDB_RSA_DEC_SGT_G SHIFT_U32(1, 31) #define PDB_RSA_DEC_SGT_F SHIFT_U32(1, 30) #define PDB_RSA_DEC_D_SIZE(len) SHIFT_U32((len) & 0xFFF, 12) #define PDB_RSA_DEC_N_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) #define PDB_RSA_DEC_Q_SIZE(len) SHIFT_U32((len) & 0xFFF, 12) #define PDB_RSA_DEC_P_SIZE(len) SHIFT_U32((len) & 0xFFF, 0) /* RSA Finalize Key */ #define PDB_RSA_KEY_P_SIZE(len) SHIFT_U32((len) & 0x1FF, 0) #define PDB_RSA_KEY_E_SIZE(len) SHIFT_U32((len) & 0x3FF, 0) #define PDB_RSA_KEY_N_SIZE(len) SHIFT_U32((len) & 0x3FF, 16) /* Manufacturing Curve Select */ #define PDB_SGT_MP_SIGN_MSG SHIFT_U32(1, 31) #define PDB_SGT_MP_SIGN_C SHIFT_U32(1, 29) #define PDB_SGT_MP_SIGN_D SHIFT_U32(1, 28) #define PDB_MP_CSEL_P256 0x03 #define PDB_MP_CSEL_P384 0x04 #define PDB_MP_CSEL_P521 0x05 /* Public Key Generation */ #define PDB_PKGEN_PD1 SHIFT_U32(1, 25) /* Public Key Signature */ #define PDB_PKSIGN_PD1 SHIFT_U32(1, 22) /* Public Key Verify */ #define PDB_PKVERIFY_PD1 SHIFT_U32(1, 22) /* Shared Secret */ #define PDB_SHARED_SECRET_PD1 SHIFT_U32(1, 25) /* DSA Signatures */ #define PDB_DSA_SIGN_N(len) SHIFT_U32((len) & (0x7F), 0) #define PDB_DSA_SIGN_L(len) SHIFT_U32((len) & (0x3FF), 7) /* SGT Flags Signature */ #define PDB_SGT_PKSIGN_MSG SHIFT_U32(1, 27) #define PDB_SGT_PKSIGN_SIGN_C SHIFT_U32(1, 26) #define PDB_SGT_PKSIGN_SIGN_D SHIFT_U32(1, 25) /* DSA Verify */ #define PDB_DSA_VERIF_N(len) SHIFT_U32((len) & (0x7F), 0) #define PDB_DSA_VERIF_L(len) SHIFT_U32((len) & (0x3FF), 7) /* SGT Flags Verify */ #define PDB_SGT_PKVERIF_MSG SHIFT_U32(1, 27) #define PDB_SGT_PKVERIF_SIGN_C SHIFT_U32(1, 26) #define PDB_SGT_PKVERIF_SIGN_D SHIFT_U32(1, 25) /* SGT Flags Shared Secret */ #define PDB_SGT_PKDH_SECRET SHIFT_U32(1, 27) /* DL Keypair Generation */ #define PDB_DL_KEY_L_SIZE(len) SHIFT_U32((len) & (0x3FF), 7) #define PDB_DL_KEY_N_MASK 0x7F #define PDB_DL_KEY_N_SIZE(len) SHIFT_U32((len) & (PDB_DL_KEY_N_MASK), 0) /* ECC Domain Selection */ #define PDB_ECC_ECDSEL(curve) SHIFT_U32((curve) & 0x3F, 7) /* Black key padding */ #define BLACK_KEY_NONCE_SIZE 6 #define BLACK_KEY_ICV_SIZE 6 /* * ECC Predefined Domain */ enum caam_ecc_curve { CAAM_ECC_P192 = (0x00), CAAM_ECC_P224, CAAM_ECC_P256, CAAM_ECC_P384, CAAM_ECC_P521, CAAM_ECC_MAX, CAAM_ECC_UNKNOWN = (0xFF), }; #endif /* __CAAM_DESC_DEFINES_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_desc_helper.h000066400000000000000000000450731464416617300252410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021, 2024 NXP * * Brief CAAM Descriptor interface. */ #ifndef __CAAM_DESC_HELPER_H__ #define __CAAM_DESC_HELPER_H__ #include #include #include #include /* * Returns the number of entries of the descriptor */ uint32_t caam_desc_get_len(uint32_t *desc); /* Descriptor Modification function */ void caam_desc_init(uint32_t *desc); void caam_desc_update_hdr(uint32_t *desc, uint32_t word); void caam_desc_add_ptr(uint32_t *desc, paddr_t ptr); void caam_desc_add_word(uint32_t *desc, uint32_t word); void caam_desc_add_dmaobj(uint32_t *desc, struct caamdmaobj *data, uint32_t pre_operation); #define caam_desc_fifo_load(desc, data, cla, dst, act) \ caam_desc_add_dmaobj(desc, data, FIFO_LD(cla, dst, act, 0)) #define caam_desc_load_key(desc, data, cla, dst) \ caam_desc_add_dmaobj(desc, data, LD_KEY_PLAIN(cla, dst, 0)) #define caam_desc_store(desc, data, cla, src) \ caam_desc_add_dmaobj(desc, data, ST_NOIMM(cla, src, 0)) #define caam_desc_fifo_store(desc, data, src) \ caam_desc_add_dmaobj(desc, data, FIFO_ST(CLASS_NO, src, 0)) #define caam_desc_seq_out(desc, data) \ caam_desc_add_dmaobj(desc, data, SEQ_OUT_PTR(0)) /* Push/Pop descriptor rings queue */ void caam_desc_push(struct caam_inring_entry *in_entry, paddr_t paddr); paddr_t caam_desc_pop(struct caam_outring_entry *out_entry); uint32_t caam_read_jobstatus(struct caam_outring_entry *out); /* Debug print function to dump a Descriptor in hex */ static inline void dump_desc(uint32_t *desc) { size_t idx = 0; size_t len = 0; len = caam_desc_get_len(desc); for (idx = 0; idx < len; idx++) trace_printf(NULL, 0, 0, false, "[%02zu] %08" PRIX32, idx, desc[idx]); } /* * Returns the descriptor size in bytes of nbEntries */ #define DESC_SZBYTES(nbentries) ((nbentries) * sizeof(uint32_t)) /* * Descriptor Header starting at idx w/o descriptor length */ #define DESC_HDR(idx) (CMD_HDR_JD_TYPE | HDR_JD_ONE | HDR_JD_START_IDX(idx)) /* * Descriptor Header starting at index 0 with descriptor length len */ #define DESC_HEADER(len) (DESC_HDR(0) | HDR_JD_DESCLEN(len)) /* * Descriptor Header starting at idx with descriptor length len */ #define DESC_HEADER_IDX(len, idx) (DESC_HDR(idx) | HDR_JD_DESCLEN(len)) /* * Jump Local of class cla to descriptor offset if test meet the * condition cond */ #define JUMP_LOCAL(cla, test, cond, offset) \ (CMD_JUMP_TYPE | CMD_CLASS(cla) | JUMP_TYPE(LOCAL) | \ JUMP_TST_TYPE(test) | (cond) | JMP_LOCAL_OFFSET(offset)) /* * Jump Local of no class to descriptor offset if test meet the * condition cond */ #define JUMP_CNO_LOCAL(test, cond, offset) \ JUMP_LOCAL(CLASS_NO, test, cond, offset) /* * Jump Local of class 1 to descriptor offset if test meet the * condition cond */ #define JUMP_C1_LOCAL(test, cond, offset) \ JUMP_LOCAL(CLASS_1, test, cond, offset) /* * First decrement specified source then * Jump Local of no class to descriptor offset if test meet the * condition cond */ #define JUMP_CNO_LOCAL_DEC(test, src, cond, offset) \ (CMD_JUMP_TYPE | CMD_CLASS(CLASS_NO) | JUMP_TYPE(LOCAL_DEC) | \ JUMP_TST_TYPE(test) | JMP_SRC(src) | (cond) | \ JMP_LOCAL_OFFSET(offset)) /* * Wait until test condition meet and jump next */ #define WAIT_COND(test, cond) \ (JUMP_LOCAL(CLASS_NO, test, JMP_COND(cond), 1) | JMP_JSL) /* * Jump No Local of class cla to descriptor offset if test meet the * condition cond */ #define JUMP_NOTLOCAL(cla, test, cond) \ (CMD_JUMP_TYPE | CMD_CLASS(cla) | JUMP_TYPE(NON_LOCAL) | \ JUMP_TST_TYPE(test) | (cond)) /* * User Halt with error if test meet the condition cond */ #define HALT_USER(test, cond, error) \ (CMD_JUMP_TYPE | JUMP_TYPE(HALT_USER_STATUS) | JUMP_TST_TYPE(test) | \ JMP_COND(cond) | JMP_LOCAL_OFFSET(error)) /* * Load Immediate value of length len to register dst of class cla */ #define LD_IMM(cla, dst, len) \ (CMD_LOAD_TYPE | CMD_CLASS(cla) | CMD_IMM | LOAD_DST(dst) | \ LOAD_LENGTH(len)) /* * Load Immediate value of length len to register dst of class starting of * register offset. */ #define LD_IMM_OFF(cla, dst, len, off) \ (CMD_LOAD_TYPE | CMD_CLASS(cla) | CMD_IMM | LOAD_DST(dst) | \ LOAD_OFFSET(off) | LOAD_LENGTH(len)) /* * Load Immediate value of length len to register dst w/o class */ #define LD_NOCLASS_IMM(dst, len) LD_IMM(CLASS_NO, dst, len) /* * Load value of length len to register dst of class cla */ #define LD_NOIMM(cla, dst, len) \ (CMD_LOAD_TYPE | CMD_CLASS(cla) | LOAD_DST(dst) | LOAD_LENGTH(len)) /* * Load value of length len to register dst of class cla starting * at register offset off */ #define LD_NOIMM_OFF(cla, dst, len, off) \ (CMD_LOAD_TYPE | CMD_CLASS(cla) | LOAD_DST(dst) | LOAD_OFFSET(off) | \ LOAD_LENGTH(len)) /* * FIFO Load to register dst class cla with action act */ #define FIFO_LD(cla, dst, act, len) \ (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | FIFO_LOAD_INPUT(dst) | \ FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len)) /* * FIFO Load to register dst class cla with action act. * Pointer is a Scatter/Gather Table */ #define FIFO_LD_SGT(cla, dst, act, len) \ (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | CMD_SGT | \ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len)) /* * FIFO Load to register dst class cla with action act. * Pointer is a Scatter/Gather Table * The length is externally defined */ #define FIFO_LD_SGT_EXT(cla, dst, act) \ (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | CMD_SGT | FIFO_LOAD_EXT | \ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act)) /* * FIFO Load to register dst class cla with action act. * The length is externally defined */ #define FIFO_LD_EXT(cla, dst, act) \ (CMD_FIFO_LOAD_TYPE | FIFO_LOAD_EXT | CMD_CLASS(cla) | \ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act)) /* * FIFO Load Immediate data length len to register dst class cla * with action act. */ #define FIFO_LD_IMM(cla, dst, act, len) \ (CMD_FIFO_LOAD_TYPE | CMD_IMM | CMD_CLASS(cla) | \ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len)) /* * Store value of length len from register src of class cla */ #define ST_NOIMM(cla, src, len) \ (CMD_STORE_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | STORE_LENGTH(len)) /* * Store value of length len from register src of class cla * Pointer is a Scatter/Gather Table */ #define ST_SGT_NOIMM(cla, src, len) \ (CMD_STORE_TYPE | CMD_CLASS(cla) | CMD_SGT | STORE_SRC(src) | \ STORE_LENGTH(len)) /* * Store value of length len from register src of class cla starting * at register offset off */ #define ST_NOIMM_OFF(cla, src, len, off) \ (CMD_STORE_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | \ STORE_OFFSET(off) | STORE_LENGTH(len)) /* * Store value of length len from register src of class cla */ #define ST_NOIMM_SEQ(cla, src, len) \ (CMD_STORE_SEQ_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | \ STORE_LENGTH(len)) /* * FIFO Store from register src of length len */ #define FIFO_ST(cla, src, len) \ (CMD_FIFO_STORE_TYPE | CMD_CLASS(cla) | FIFO_STORE_OUTPUT(src) | \ FIFO_STORE_LENGTH(len)) /* * FIFO Store from register src. * The length is externally defined */ #define FIFO_ST_EXT(src) \ (CMD_FIFO_STORE_TYPE | FIFO_STORE_EXT | FIFO_STORE_OUTPUT(src)) /* * FIFO Store from register src of length len. * Pointer is a Scatter/Gather Table */ #define FIFO_ST_SGT(src, len) \ (CMD_FIFO_STORE_TYPE | CMD_SGT | FIFO_STORE_OUTPUT(src) | \ FIFO_STORE_LENGTH(len)) /* * FIFO Store from register src. * Pointer is a Scatter/Gather Table * The length is externally defined */ #define FIFO_ST_SGT_EXT(src) \ (CMD_FIFO_STORE_TYPE | CMD_SGT | FIFO_STORE_EXT | \ FIFO_STORE_OUTPUT(src)) /* * SEQ FIFO Store from register src of length len */ #define FIFO_ST_SEQ(src, len) \ (CMD_SEQ_FIFO_STORE_TYPE | FIFO_STORE_OUTPUT(src) | \ FIFO_STORE_LENGTH(len)) /* * RNG State Handle instantation operation for sh ID */ #define RNG_SH_INST(sh) \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_RNG_SH(sh) | \ ALGO_AS(RNG_INSTANTIATE) | ALGO_RNG_PR) /* * RNG Generates Secure Keys */ #define RNG_GEN_SECKEYS \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_RNG_SK | \ ALGO_AS(RNG_GENERATE)) /* * RNG Generates Data */ #define RNG_GEN_DATA \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_AS(RNG_GENERATE)) /* * Hash Init Operation of algorithm algo */ #define HASH_INIT(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | ALGO_ENCRYPT) /* * Hash Update Operation of algorithm algo */ #define HASH_UPDATE(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(UPDATE) | \ ALGO_ENCRYPT) /* * Hash Final Operation of algorithm algo */ #define HASH_FINAL(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(FINAL) | ALGO_ENCRYPT) /* * Hash Init and Final Operation of algorithm algo */ #define HASH_INITFINAL(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT_FINAL) | \ ALGO_ENCRYPT) /* * HMAC Init Decryption Operation of algorithm algo */ #define HMAC_INIT_DECRYPT(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | \ ALGO_AAI(DIGEST_HMAC) | ALGO_DECRYPT) /* * HMAC Init and Final Operation of algorithm algo with Precomp key */ #define HMAC_INITFINAL_PRECOMP(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT_FINAL) | \ ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT) /* * HMAC Init Operation of algorithm algo with Precomp key */ #define HMAC_INIT_PRECOMP(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | \ ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT) /* * HMAC Final Operation of algorithm algo with Precomp key */ #define HMAC_FINAL_PRECOMP(algo) \ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(FINAL) | \ ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT) /* * Cipher Init and Final Operation of algorithm algo */ #define CIPHER_INITFINAL(algo, encrypt) \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT_FINAL) | \ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) /* * Cipher Init Operation of algorithm algo */ #define CIPHER_INIT(algo, encrypt) \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT) | \ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) /* * Cipher Update Operation of algorithm algo */ #define CIPHER_UPDATE(algo, encrypt) \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(UPDATE) | \ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) /* * Cipher Final Operation of algorithm algo */ #define CIPHER_FINAL(algo, encrypt) \ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(FINAL) | \ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT)) /* * Load a class cla key of length len to register dst. * Key can be stored in plain text. */ #define LD_KEY_PLAIN(cla, dst, len) \ (CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_PTS | KEY_DEST(dst) | \ KEY_LENGTH(len)) /* * Load a class cla key of length len to register dst. * Key can be stored in plain text. * Pointer is a Scatter/Gatter Table */ #define LD_KEY_SGT_PLAIN(cla, dst, len) \ (CMD_KEY_TYPE | CMD_CLASS(cla) | CMD_SGT | KEY_PTS | KEY_DEST(dst) | \ KEY_LENGTH(len)) /* * Load a split key of length len. */ #define LD_KEY_SPLIT(len) \ (CMD_KEY_TYPE | CMD_CLASS(CLASS_2) | KEY_DEST(MDHA_SPLIT) | \ KEY_LENGTH(len)) /* * Load a class cla key of length len to register dst. */ #define LD_KEY(cla, dst, len) \ (CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_DEST(dst) | KEY_LENGTH(len)) /* * MPPRIVK generation function. */ #define MPPRIVK (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(MPKEY)) /* * MPPUBK generation function. */ #define MPPUBK (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(MPKEY)) /* * MPSIGN function. */ #define MPSIGN_OP (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(MPSIGN)) /* * Operation Mathematical of length len * dest = src0 (operation func) src1 */ #define MATH(func, src0, src1, dst, len) \ (CMD_MATH_TYPE | MATH_FUNC(func) | MATH_SRC0(src0) | MATH_SRC1(src1) | \ MATH_DST(dst) | MATH_LENGTH(len)) /* * Operation Mathematical of length len using an immediate value as operand 1 * dest = src (operation func) val */ #define MATHI_OP1(func, src, val, dst, len) \ (CMD_MATHI_TYPE | MATH_FUNC(func) | MATHI_SRC(src) | \ MATHI_IMM_VALUE(val) | MATHI_DST(dst) | MATH_LENGTH(len)) /* * PKHA Copy function from src to dst. Copy number of words specified * in Source size register */ #define PKHA_CPY_SSIZE(src, dst) \ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(CPY_SSIZE) | \ PKHA_CPY_SRC(src) | PKHA_CPY_DST(dst)) /* * PKHA Copy N-Size function from src to dst. Copy number of words specified * in PKHA N size register */ #define PKHA_CPY_NSIZE(src, dst) \ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(CPY_NSIZE) | \ PKHA_CPY_SRC(src) | PKHA_CPY_DST(dst)) /* * PKHA Operation op result into dst */ #define PKHA_OP(op, dst) \ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(op) | \ PKHA_OUTSEL(dst)) /* * PKHA Binomial operation op result into dst */ #define PKHA_F2M_OP(op, dst) \ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_F2M | PKHA_FUNC(op) | \ PKHA_OUTSEL(dst)) /* * Move src to dst */ #define MOVE(src, dst, off, len) \ (CMD_MOVE_TYPE | MOVE_SRC(src) | MOVE_DST(dst) | MOVE_OFFSET(off) | \ MOVE_LENGTH(len)) /* * Move src to dst and wait until completion */ #define MOVE_WAIT(src, dst, off, len) \ (CMD_MOVE_TYPE | MOVE_WC | MOVE_SRC(src) | MOVE_DST(dst) | \ MOVE_OFFSET(off) | MOVE_LENGTH(len)) /* * RSA Encryption using format */ #define RSA_ENCRYPT(format) \ (CMD_OP_TYPE | PROTID(RSA_ENC) | PROT_RSA_FMT(format)) /* * RSA Decryption using format */ #define RSA_DECRYPT(format) \ (CMD_OP_TYPE | PROTID(RSA_DEC) | PROT_RSA_FMT(format)) /* * RSA Finalize Key in format */ #define RSA_FINAL_KEY(format, alg) \ (CMD_OP_TYPE | PROTID(RSA_FINISH_KEY) | PROT_RSA_KEY(format) | \ PROT_RSA_FINISH_KEY(alg)) /* * Public Keypair generation */ #define PK_KEYPAIR_GEN(type, alg) \ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type) | \ PROT_PRI(alg)) /* * DSA/ECDSA signature of message of msg_type */ #define DSA_SIGN(type, msg_type, alg) \ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | \ PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type) | PROT_PRI(alg)) /* * DSA/ECDSA signature verify message of msg_type */ #define DSA_VERIFY(type, msg_type) \ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \ PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type)) /* * DH/ECC Shared Secret */ #define SHARED_SECRET(type, alg) \ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(SHARED_SECRET) | \ PROT_PK_TYPE(type) | PROT_PRI(alg)) /* * Blob Master Key Verification */ #define BLOB_MSTR_KEY \ (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(BLOB) | PROT_BLOB_FMT_MSTR) /* * Blob encapsulation */ #define BLOB_ENCAPS \ (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(BLOB) | \ PROT_BLOB_FORMAT(NORMAL)) /* * Blob decapsulation */ #define BLOB_DECAPS \ (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(BLOB) | \ PROT_BLOB_FORMAT(NORMAL)) /* * Black key CCM size */ #define BLACK_KEY_CCM_SIZE(size) \ (ROUNDUP(size, 8) + BLACK_KEY_NONCE_SIZE + BLACK_KEY_ICV_SIZE) /* * Black key ECB size */ #define BLACK_KEY_ECB_SIZE(size) ROUNDUP(size, 16) /* * Sequence Inout Pointer of length len */ #define SEQ_IN_PTR(len) (CMD_SEQ_IN_TYPE | SEQ_LENGTH(len)) /* * Sequence Output Pointer of length len */ #define SEQ_OUT_PTR(len) (CMD_SEQ_OUT_TYPE | SEQ_LENGTH(len)) #endif /* __CAAM_DESC_HELPER_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hal_cfg.h000066400000000000000000000032341464416617300243400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief CAAM Configuration header. */ #ifndef __CAAM_HAL_CFG_H__ #define __CAAM_HAL_CFG_H__ #include /* * Returns the Job Ring Configuration to be used by the TEE * * @jrcfg [out] Job Ring Configuration * * Returns: * CAAM_NO_ERROR Success * CAAM_FAILURE An error occurred */ enum caam_status caam_hal_cfg_get_conf(struct caam_jrcfg *jrcfg); /* * Setup the Non-Secure Job Ring * * @jrcfg Job Ring configuration */ void caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg); #ifdef CFG_DT /* * Returns the Job Ring configuration to be used by the TEE * * @fdt Device Tree handle * @ctrl_base [out] CAAM Controller base address */ void caam_hal_cfg_get_ctrl_dt(void *fdt, vaddr_t *ctrl_base); /* * Returns the Job Ring configuration to be used by the TEE * * @fdt Device Tree handle * @jrcfg [out] Job Ring configuration */ void caam_hal_cfg_get_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg); /* * Disable the DT node related to the Job Ring used by secure world * * @fdt Device Tree handle * @jrcfg Job Ring configuration */ void caam_hal_cfg_disable_jobring_dt(void *fdt, struct caam_jrcfg *jrcfg); #else static inline void caam_hal_cfg_get_ctrl_dt(void *fdt __unused, vaddr_t *ctrl_base) { *ctrl_base = 0; } static inline void caam_hal_cfg_get_jobring_dt(void *fdt __unused, struct caam_jrcfg *jrcfg) { jrcfg->offset = 0; jrcfg->it_num = 0; } static inline void caam_hal_cfg_disable_jobring_dt(void *fdt __unused, struct caam_jrcfg *jrcfg __unused) { } #endif /* CFG_DT */ #endif /* __CAAM_HAL_CFG_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hal_clk.h000066400000000000000000000005411464416617300243500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief CAAM Clock functions header. */ #ifndef __CAAM_HAL_CLK_H__ #define __CAAM_HAL_CLK_H__ #include /* * Enable/disable the CAAM clocks * * @enable Enable the clock if true */ void caam_hal_clk_enable(bool enable); #endif /* __CAAM_HAL_CLK_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hal_ctrl.h000066400000000000000000000050341464416617300245450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Brief CAAM Controller Hardware Abstration Layer header. */ #ifndef __CAAM_HAL_CTRL_H__ #define __CAAM_HAL_CTRL_H__ #include #include /* * Initializes the CAAM HW Controller * * @baseaddr Controller base address */ void caam_hal_ctrl_init(vaddr_t baseaddr); /* * Returns the number of Job Ring supported * * @baseaddr Controller base address */ uint8_t caam_hal_ctrl_jrnum(vaddr_t baseaddr); /* * If Hash operation is supported, returns the Maximum Hash Algorithm * supported by the HW else UINT8_MAX * * @baseaddr Controller base address */ uint8_t caam_hal_ctrl_hash_limit(vaddr_t baseaddr); /* * Returns the number of Public Key module supported * * @baseaddr Controller base address */ uint8_t caam_hal_ctrl_pknum(vaddr_t baseaddr); /* * Returns if the HW support the split key operation. * * @baseaddr Controller base address */ bool caam_hal_ctrl_splitkey_support(vaddr_t baseaddr); /* * Returns the CAAM Era * * @baseaddr Controller base address */ uint8_t caam_hal_ctrl_era(vaddr_t baseaddr); /* * Increment the CAAM PRIBLOB field * * @baseaddr Controller base address */ void caam_hal_ctrl_inc_priblob(vaddr_t baseaddr); #ifdef CFG_NXP_CAAM_MP_DRV /* * Get the SCFGR content and check the MPCURVE fields. * The function returns either: * - UINT8_MAX if the Manafacturing Protection is not supported * - The MP Curve Value if programmed (4 bits value) * - 0 if the MP Curve is not programmed * * @ctrl_addr Controller base address */ uint8_t caam_hal_ctrl_get_mpcurve(vaddr_t ctrl_addr); /* * Read the MPMR content * * @ctrl_addr Controller base address * @mpmr [out] MPMR buffer read */ TEE_Result caam_hal_ctrl_read_mpmr(vaddr_t ctrl_addr, struct caambuf *mpmr); /* * Fill the MPMR content then lock the register * * @ctrl_addr Controller base address * @msg_mpmr Buffer with the message and length to fill the MPMR content */ void caam_hal_ctrl_fill_mpmr(vaddr_t ctrl_addr, struct caambuf *msg_mpmr); /* * Indicate if the MP is set * * @ctrl_addr Controller base address */ bool caam_hal_ctrl_is_mp_set(vaddr_t ctrl_addr); #endif /* CFG_NXP_CAAM_MP_DRV */ #ifdef CFG_NXP_CAAM_SM_DRV /* * Get the Secure Memory Virtual base address setup in the given job ring * * @ctrl_addr Controller base address * @jr_offset Job ring offset */ vaddr_t caam_hal_ctrl_get_smvaddr(vaddr_t ctrl_addr, paddr_t jr_offset); #endif /* CFG_NXP_CAAM_SM_DRV */ #endif /* __CAAM_HAL_CTRL_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hal_jr.h000066400000000000000000000066171464416617300242240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief CAAM Job Rings Hardware Abstration Layer header. */ #ifndef __CAAM_HAL_JR_H__ #define __CAAM_HAL_JR_H__ #include /* * Configures the Job Ring Owner and lock it. * If the configuration is already locked, checks the configuration * set and returns an error if value is not corresponding to the * expected value. * * @ctrl_base Base address of the controller * @jr_offset Job Ring offset to configure * @owner Onwer ID to configure */ enum caam_status caam_hal_jr_setowner(vaddr_t ctrl_base, paddr_t jr_offset, enum caam_jr_owner owner); /* * Resets the Job Ring to ensure that all pending jobs are completed * and no other will be executed * * @baseaddr Job Ring Base address */ enum caam_status caam_hal_jr_reset(vaddr_t baseaddr); /* * Configures the Job Ring HW queues. * * @baseaddr Job Ring Base Address * @nbjobs Number of job rings supported * @inrings physical address of the JR input queue * @outrings physical address of the JR output queue */ void caam_hal_jr_config(vaddr_t baseaddr, uint8_t nbjobs, uint64_t inrings, uint64_t outrings); /* * Returns the number of slots available in the input job ring * * @baseaddr Job Ring Base address */ uint32_t caam_hal_jr_read_nbslot_available(vaddr_t baseaddr); /* * Indicates to HW that a new job is available * * @baseaddr Job Ring Base Address */ void caam_hal_jr_add_newjob(vaddr_t baseaddr); /* * Returns the number of job completed and present in the output ring slots * * @baseaddr Job Ring Base Address */ uint32_t caam_hal_jr_get_nbjob_done(vaddr_t baseaddr); /* * Removes a job from the job ring output queue * * @baseaddr Job Ring Base Address */ void caam_hal_jr_del_job(vaddr_t baseaddr); /* * Disable and acknwoledge the Job Ring interrupt * * @baseaddr Job Ring Base Address */ void caam_hal_jr_disable_itr(vaddr_t baseaddr); /* * Enable the Job Ring interrupt * * @baseaddr Job Ring Base Address */ void caam_hal_jr_enable_itr(vaddr_t baseaddr); /* * If an interrupt is pending, acknowledges it and returns true. * * @baseaddr Job Ring Base Address */ bool caam_hal_jr_check_ack_itr(vaddr_t baseaddr); /* * Halt the Job Ring processing. Stop fetching input queue and wait * all running jobs normal completion. * * @baseaddr Job Ring Base Address */ enum caam_status caam_hal_jr_halt(vaddr_t baseaddr); /* * Wait all Input queue Job Ring processing. * * @baseaddr Job Ring Base Address */ enum caam_status caam_hal_jr_flush(vaddr_t baseaddr); /* * Resume the Job Ring processing. * * @baseaddr Job Ring Base Address */ void caam_hal_jr_resume(vaddr_t baseaddr); /* * Returns the next entry free in the JR input queue. * The HW increments register by 4. Convert it to a software index number * * @baseaddr CAAM JR Base Address */ uint8_t caam_hal_jr_input_index(vaddr_t baseaddr); /* * Returns the next entry to read from the JR output queue. * The HW increments register by 8. Convert it to a software index number * * @baseaddr CAAM JR Base Address */ uint8_t caam_hal_jr_output_index(vaddr_t baseaddr); /* * Let the JR prepare data that need backup * * @ctrl_base CAAM JR Base Address * @jr_offset Job Ring offset to prepare backup for */ void caam_hal_jr_prepare_backup(vaddr_t ctrl_base, paddr_t jr_offset); #endif /* __CAAM_HAL_JR_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hal_rng.h000066400000000000000000000024001464416617300243610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019-2021 NXP * * Brief CAAM Random Number Generator Hardware Abstration Layer. * Implementation of primitives to access HW */ #ifndef __CAAM_HAL_RNG_H__ #define __CAAM_HAL_RNG_H__ #include #include /* * Returns if all RNG State Handler already instantiated or not * * @baseaddr RNG Base Address */ enum caam_status caam_hal_rng_instantiated(vaddr_t baseaddr); /* * Returns the number of RNG State Handle * * @baseaddr RNG Base Address */ uint32_t caam_hal_rng_get_nb_sh(vaddr_t baseaddr); /* * Returns the RNG Status State Handle * * @baseaddr RNG Base Address */ uint32_t caam_hal_rng_get_sh_status(vaddr_t baseaddr); /* * Returns true if the RNG Key is loaded, false otherwise * * @baseaddr RNG Base Address */ bool caam_hal_rng_key_loaded(vaddr_t baseaddr); /* * Returns true if the RNG was initialized for prediction resistance * * @baseaddr RNG Base Address */ bool caam_hal_rng_pr_enabled(vaddr_t baseaddr); /* * Configures the RNG entropy delay * * @baseaddr RNG Base Address * @inc_delay Entropy Delay incrementation */ enum caam_status caam_hal_rng_kick(vaddr_t baseaddr, uint32_t inc_delay); #endif /* __CAAM_HAL_RNG_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hal_sm.h000066400000000000000000000061651464416617300242260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019, 2023 NXP */ #ifndef __CAAM_HAL_SM_H__ #define __CAAM_HAL_SM_H__ #include #include /* * Checks if @page and @partition number are valid * * @jr_base JR base address * @sm_page_desc Secure Memory page */ enum caam_status caam_hal_sm_check_page_partition(vaddr_t jr_base, const struct caam_sm_page_desc *sm_page_desc); /* * Return the Pages Size in KBytes * * @jr_base JR base address * @page Page number */ size_t caam_hal_sm_get_pages_size(vaddr_t jr_base, unsigned int page); /* * Return if the partition is free (available) * * @jr_base JR base address * @partition Partition number */ bool caam_hal_sm_prtn_is_free(vaddr_t jr_base, unsigned int partition); /* * Return if the partition is owned (by the HW register reader) * * @jr_base JR base address * @partition Partition number */ bool caam_hal_sm_prtn_is_owned(vaddr_t jr_base, unsigned int partition); /* * Set the Secure Memory access to all groups * * @jr_base JR base address * @partition Partition number * @grp1 Group 1 value * @grp2 Group 2 value */ void caam_hal_sm_set_access_all_group(vaddr_t jr_base, unsigned int partition); /* * Set the Secure Memory access to group 1 and/or group 2 * * @jr_base JR base address * @partition Partition number * @grp1 Group 1 value * @grp2 Group 2 value */ void caam_hal_sm_set_access_group(vaddr_t jr_base, unsigned int partition, uint32_t grp1, uint32_t grp2); /* * Open all Secure Memory Permissions * * @jr_base JR base address * @partition Partition number */ void caam_hal_sm_open_access_perm(vaddr_t jr_base, unsigned int partition); /* * Set the Secure Memory access permission for group 1 and group 2. * Enable Critical Security and lock configuration * * @jr_base JR base address * @partition Partition number * @grp1_perm Group 1 Permissions * @grp2_perm Group 2 Permissions */ void caam_hal_sm_set_access_perm(vaddr_t jr_base, unsigned int partition, unsigned int grp1_perm, unsigned int grp2_perm); /* * Allocate a @page to the @partition. * * @jr_base JR base address * @sm_page_desc Secure Memory page */ enum caam_status caam_hal_sm_allocate_page(vaddr_t jr_base, const struct caam_sm_page_desc *sm_page_desc); /* * De-allocate a @partition and all partition's page. * * @jr_base JR base address * @partition Partition number */ enum caam_status caam_hal_sm_deallocate_partition(vaddr_t jr_base, unsigned int partition); /* * De-allocate all pages specified in the @sm struct * * @jr_base JR base address * @sm_page_desc Secure Memory page */ enum caam_status caam_hal_sm_deallocate_pages(vaddr_t jr_base, const struct caam_sm_page_desc *sm_page_desc); /* Return the virtual base address of the Secure Memory registers */ vaddr_t caam_hal_sm_get_base(void); #ifdef CFG_DT void caam_hal_sm_get_base_dt(void *fdt, vaddr_t *sm_base); #else static inline void caam_hal_sm_get_base_dt(void *fdt __unused, vaddr_t *sm_base) { *sm_base = 0; } #endif /* CFG_DT */ #endif /* __CAAM_HAL_SM_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_hash.h000066400000000000000000000015551464416617300237040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief CAAM Hash manager header. */ #ifndef __CAAM_HASH_H__ #define __CAAM_HASH_H__ #include #ifdef CFG_NXP_CAAM_HASH_DRV /* * Initialize the Hash module * * @caam_jrcfg JR configuration structure */ enum caam_status caam_hash_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_hash_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_HASH_DRV */ #ifdef CFG_NXP_CAAM_HMAC_DRV /* * Initialize the HMAC module * * @caam_jrcfg JR configuration structure */ enum caam_status caam_hmac_init(struct caam_jrcfg *caam_jrcfg); #else static inline enum caam_status caam_hmac_init(struct caam_jrcfg *caam_jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_HMAC_DRV */ #endif /* __CAAM_HASH_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_io.h000066400000000000000000000020041464416617300233560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019, 2021 NXP * * Brief Specific Macro used to read/write value with a specific * format (BE/LE, 32/64 bits) to be updated for future platform * support. */ #ifndef __CAAM_IO_H__ #define __CAAM_IO_H__ #include #ifdef CFG_CAAM_BIG_ENDIAN /* Big Endian 32 bits Registers access */ #define io_caam_read32(a) TEE_U32_FROM_BIG_ENDIAN(io_read32(a)) #define io_caam_write32(a, val) io_write32(a, TEE_U32_TO_BIG_ENDIAN(val)) /* Big Endian 32 bits Value access */ #define caam_read_val32(a) get_be32(a) #define caam_write_val32(a, v) put_be32(a, v) #else /* Little Endian 32 bits Registers access */ #define io_caam_read32(a) io_read32(a) #define io_caam_write32(a, val) io_write32(a, val) /* Little Endian 32 bits Value access */ #define caam_read_val32(a) get_le32(a) #define caam_write_val32(a, v) put_le32(a, v) #define caam_read_val64(a) get_le64(a) #define caam_write_val64(a, v) put_le64(a, v) #endif #endif /* __CAAM_IO_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_jr.h000066400000000000000000000061511464416617300233710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief CAAM Job Rings module header. */ #ifndef __CAAM_JR_H__ #define __CAAM_JR_H__ #include #include /* * Job context to enqueue/dequeue */ struct caam_jobctx { uint32_t *desc; /* reference to the descriptor */ uint32_t status; /* executed job status */ uint32_t id; /* Job identifier */ bool completion; /* job completion flag */ void *context; /* caller job context */ void (*callback)(struct caam_jobctx *ctx); /* job completion callback */ }; /* * Job Ring module configuration */ struct caam_jrcfg { vaddr_t base; /* CAAM virtual base address */ paddr_t offset; /* Job Ring address offset */ int it_num; /* Job Ring interrupt number */ uint8_t nb_jobs; /* Number of Jobs to managed */ }; /* * The CAAM physical address is decorrelated from the CPU addressing mode. * CAAM can manage 32 or 64 bits address depending on its version and the * device. */ /* * Definition of input and output ring object */ #ifdef CFG_CAAM_64BIT struct caam_inring_entry { uint64_t desc; /* Physical address of the descriptor */ }; struct caam_outring_entry { uint64_t desc; /* Physical address of the descriptor */ uint32_t status; /* Status of the executed job */ } __packed; #else struct caam_inring_entry { uint32_t desc; /* Physical address of the descriptor */ }; struct caam_outring_entry { uint32_t desc; /* Physical address of the descriptor */ uint32_t status; /* Status of the executed job */ } __packed; #endif /* CFG_CAAM_64BIT */ /* * Initialization of the CAAM Job Ring module * * @jrcfg Job Ring Configuration */ enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg); /* * Cancels a job ID. Remove the job from SW Job array * * @job_id Job ID */ void caam_jr_cancel(uint32_t job_id); /* * Checks if one of the given job IDs in bit mask format * is completed. If none is completed, wait until timeout expires. * Endlessly wait if @timeout_ms = UINT_MAX * * @job_ids Job IDs Mask * @timeout_ms Timeout in millisecond */ enum caam_status caam_jr_dequeue(uint32_t job_ids, unsigned int timeout_ms); /* * Enqueues a job in the Job Ring input queue and either wait until job * completion or if job is asynchrnous, returns immediately (if status * success, the output parameter job_id is filled with the Job Id pushed) * * @jobctx Reference to the job context * @job_id [out] If pointer not NULL, job is asynchronous and parameter is * the Job Id enqueued */ enum caam_status caam_jr_enqueue(struct caam_jobctx *jobctx, uint32_t *job_id); /* * Request the CAAM JR to halt. * Stop fetching input queue and wait running job completion. */ enum caam_status caam_jr_halt(void); /* Request the CAAM JR to flush all job running. */ enum caam_status caam_jr_flush(void); /* * Resume the CAAM JR processing. * * @pm_hints Hint on current power transition */ void caam_jr_resume(uint32_t pm_hints); /* Forces the completion of all CAAM Job to ensure CAAM is not BUSY. */ enum caam_status caam_jr_complete(void); #endif /* __CAAM_JR_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_jr_status.h000066400000000000000000000024541464416617300247760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief CAAM Job Ring Status definition header. */ #ifndef __JR_STATUS_H__ #define __JR_STATUS_H__ #include /* Source */ #define BM_JRSTA_SRC SHIFT_U32(0xF, 28) #define JRSTA_SRC_GET(status) ((status) & BM_JRSTA_SRC) #define JRSTA_SRC(src) SHIFT_U32(JRSTA_SRC_##src, 28) #define JRSTA_SRC_NONE 0x0 #define JRSTA_SRC_CCB 0x2 #define JRSTA_SRC_JMP_HALT_USER 0x3 #define JRSTA_SRC_DECO 0x4 #define JRSTA_SRC_JR 0x6 #define JRSTA_SRC_JMP_HALT_COND 0x7 #define JRSTA_CCB_GET_ERR(status) ((status) & SHIFT_U32(0xFF, 0)) #define JRSTA_CCB_CHAID_RNG SHIFT_U32(0x5, 4) #define JRSTA_CCB_ERRID_HW SHIFT_U32(0xB, 0) #define JRSTA_DECO_ERRID_FORMAT SHIFT_U32(0x88, 0) #define JRSTA_DECO_INV_SIGNATURE SHIFT_U32(0x86, 0) /* Return the Halt User status else 0 if not a Jump Halt User */ #define JRSTA_GET_HALT_USER(status) \ (__extension__({ \ __typeof__(status) _status = (status); \ JRSTA_SRC_GET(_status) == JRSTA_SRC(JMP_HALT_USER) ? \ _status & UINT8_MAX : \ 0; })) #endif /* __CAAM_JR_STATUS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_key.h000066400000000000000000000075161464416617300235540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP */ #ifndef __CAAM_KEY_H__ #define __CAAM_KEY_H__ #include #include #include /* * CAAM Key types */ enum caam_key_type { CAAM_KEY_PLAIN_TEXT = 0, /* Plain text key or red key */ CAAM_KEY_BLACK_ECB, /* Black key AES-ECB encrypted */ CAAM_KEY_BLACK_CCM, /* Black key AES-CCM encrypted */ CAAM_KEY_MAX_VALUE, /* Max value - not valid */ }; /* * CAAM key structure */ struct caamkey { struct caambuf buf; /* Key buffer */ enum caam_key_type key_type; /* CAAM Key type */ size_t sec_size; /* Security key size */ bool is_blob; /* Shows if the key is in blob format */ }; /* * Returns the default key type for CAAM key generation. * The CAAM can only generate one key type. */ static inline enum caam_key_type caam_key_default_key_gen_type(void) { return CAAM_KEY_BLACK_CCM; } /* * Print CAAM Key structure * * @trace Additional log string * @key Key to print */ void caam_key_dump(const char *trace, const struct caamkey *key); /* * Allocate CAAM key buffer based on the CAAM key type, key security size, and * whether it is in a blob format or not. * * @key CAAM key to allocate */ enum caam_status caam_key_alloc(struct caamkey *key); /* * Free the CAAM key buffer * * @key CAAM key to free */ void caam_key_free(struct caamkey *key); /* * Perform a cache operation on CAAM key buffer. * * @op Cache operation type * @key CAAM key buffer to operate */ void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key); /* * Encapsulate or decapsulate the given CAAM key * * @in_key CAAM Key to encapsulate or decapsulate * @out_key CAAM Key operation result. The out_key is allocated by the function. */ enum caam_status caam_key_operation_blob(const struct caamkey *in_key, struct caamkey *out_key); /* * Deserialize CAAM key structure from binary buffer * * @data Buffer input * @size Buffer input size * @key CAAM key structure to populate * @sec_size Security key size to deserialize, optional. If not needed, * set it to 0. */ enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size, struct caamkey *key, size_t sec_size); /* * Serialize CAAM key structure to binary buffer * * @data Buffer output * @size Buffer output size * @key CAAM key structure to serialize */ enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size, const struct caamkey *key); /* * Deserialize CAAM key structure from bignum * * @inkey Bignum input * @outkey CAAM key structure to populate * @size_sec Security key size to deserialize, optional. If not needed, * set it to zero. */ enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey, struct caamkey *outkey, size_t size_sec); /* * Serialize CAAM key structure to bignum * * @outkey Bignum output * @inkey CAAM key structure to serialize */ enum caam_status caam_key_serialize_to_bn(struct bignum *outkey, const struct caamkey *inkey); /* * Return the key buffer size needed given the CAAM key type, key security size, * and whether it is in a blob format or not * * @key CAAM key structure input */ size_t caam_key_get_alloc_size(const struct caamkey *key); /* * Return the buffer size needed to serialize the given CAAM key structure * * @key CAAM Key structure to serialize * @size returned buffer size */ enum caam_status caam_key_serialized_size(const struct caamkey *key, size_t *size); /* * Encapsulate a plain text key to CAAM black key. * * @key CAAM key to encapsulate * @key_type CAAM key encapsulation type */ enum caam_status caam_key_black_encapsulation(struct caamkey *key, enum caam_key_type key_type); /* * CAAM Key initialization */ enum caam_status caam_key_init(void); #endif /* __CAAM_KEY_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_mp.h000066400000000000000000000013641464416617300233730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019, 2021, 2023 NXP */ #ifndef __CAAM_MP_H__ #define __CAAM_MP_H__ #include "tee_api_types.h" #include "types_ext.h" #ifdef CFG_NXP_CAAM_MP_DRV /* * Initialize the MP module and generate the private key * * @ctrl_addr Controller base address */ enum caam_status caam_mp_init(vaddr_t ctrl_addr); /* * Power Management for MP * * @pm_hint Power mode type */ enum caam_status caam_mp_resume(uint32_t pm_hint); #else static inline enum caam_status caam_mp_init(vaddr_t ctrl_addr __unused) { return CAAM_NO_ERROR; } static inline enum caam_status caam_mp_resume(uint32_t pm_hint __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_MP_DRV */ #endif /* __CAAM_MP_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_pwr.h000066400000000000000000000034041464416617300235640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief CAAM driver common include file. * Definition of the structure type to save and restore * HW registers configuration */ #ifndef __CAAM_PWR_H__ #define __CAAM_PWR_H__ #include /* * Definition of the structure type used to list HW registers * to be saved and restored. */ struct reglist { uint32_t offset; /* Register offset */ uint32_t nbregs; /* Number of consecutive registers */ uint32_t mask_clr; /* Clear mask of bit to exclude in restore value */ uint32_t mask_set; /* Set mask of bit to force in restore value */ }; #define BACKUP_REG(_offset, _nbregs, _mask_clr, _mask_set) \ { \ .offset = _offset, .nbregs = _nbregs, .mask_clr = _mask_clr, \ .mask_set = _mask_set, \ } /* * Definition of the structure type used to store registers to backup */ struct backup_data { vaddr_t baseaddr; /* Register virtual base address */ size_t nbentries; /* Number of entries in the list */ const struct reglist *regs; /* Register list */ uint32_t *val; /* Register value */ SLIST_ENTRY(backup_data) next; /* Link to next data */ }; /* * Add definition of the backup data in the list * * @baseaddr Register base address * @regs Register list * @nbentries Number of entries in the list */ void caam_pwr_add_backup(vaddr_t baseaddr, const struct reglist *regs, size_t nbentries); /* * Power Initialization function called when all CAAM modules are * initialized correctly. * Register the PM callback in the system. */ void caam_pwr_init(void); #endif /* __CAAM_PWR_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_rng.h000066400000000000000000000007251464416617300235450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Brief CAAM Random Number Generator manager header. */ #ifndef __CAAM_RNG_H__ #define __CAAM_RNG_H__ /* * Initialize the RNG module to generate data * * @ctrl_addr Controller base address */ enum caam_status caam_rng_init(vaddr_t ctrl_addr); /* Instantiates the RNG State Handles if not already done */ enum caam_status caam_rng_instantiation(void); #endif /* __CAAM_RNG_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_sm.h000066400000000000000000000034561464416617300234020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019, 2023 NXP */ #ifndef __CAAM_SM_H__ #define __CAAM_SM_H__ #include "caam_jr.h" #include "drivers/caam_extension.h" /* * Secure Memory data */ struct caam_sm_page_addr { paddr_t paddr; /* Secure memory base address */ vaddr_t vaddr; /* Secure memory virtual base address */ }; /* * Secure Memory Page(s)/Partition definition */ struct caam_sm_page_desc { unsigned int partition; /* Partition number */ unsigned int page; /* Page number */ unsigned int page_count; /* Number of pages used */ }; #ifdef CFG_NXP_CAAM_SM_DRV /* * CAAM Secure memory module initialization * * @jrcfg JR configuration structure */ enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg); /* * Allocate page(s) to one partition in the CAAM secure memory. * Reset the group access and permission access to remove restrictions. * * @sm_page_descriptor Secure Memory page * @sm_page_addr [out] Secure Memory page addresses */ enum caam_status caam_sm_alloc(const struct caam_sm_page_desc *sm_page_descriptor, struct caam_sm_page_addr *sm_page_addr); /* * Set the Secure Memory group 1 and group 2 access rights to allocated * partition and lock configuration. * * @page_desc Secure Memory page * @grp1_perm Group 1 Permission value * @grp2_perm Group 2 Permission value */ enum caam_status caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc, unsigned int grp1_perm, unsigned int grp2_perm); /* * Free a Secure Memory pages * * @sm_page_descriptor Secure Memory page */ enum caam_status caam_sm_free(const struct caam_sm_page_desc *sm_page_descriptor); #else static inline enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg __unused) { return CAAM_NO_ERROR; } #endif /* CFG_NXP_CAAM_SM_DRV */ #endif /* __CAAM_SM_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_status.h000066400000000000000000000015541464416617300243030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019, 2021 NXP * * Brief CAAM driver internal status definition */ #ifndef __CAAM_STATUS_H__ #define __CAAM_STATUS_H__ /* * Internal CAAM Driver status codes */ enum caam_status { CAAM_NO_ERROR = 0, /* No Error */ CAAM_FAILURE, /* General failure */ CAAM_NOT_SUPPORTED, /* Feature not supported */ CAAM_OUT_MEMORY, /* Out of memory */ CAAM_BAD_PARAM, /* Bad parameters */ CAAM_SHORT_BUFFER, /* Buffer is too short */ CAAM_BUSY, /* Operation is not possible, system busy */ CAAM_PENDING, /* Operation is pending */ CAAM_TIMEOUT, /* Operation timeout */ CAAM_OUT_OF_BOUND, /* Value is out of boundary */ CAAM_JOB_STATUS, /* A job status is available */ CAAM_NOT_INIT, /* Feature is not initialized */ }; #endif /* __CAAM_STATUS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_trace.h000066400000000000000000000227771464416617300240700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019-2021, 2023 NXP * * Brief CAAM driver trace include file. * Definition of the internal driver trace macros. */ #ifndef __CAAM_TRACE_H__ #define __CAAM_TRACE_H__ #include #include #define CAAM_DBG_TRACE(var) (CFG_DBG_CAAM_TRACE & DBG_TRACE_##var) #define CAAM_DBG_DESC(var) (CFG_DBG_CAAM_DESC & DBG_TRACE_##var) #define CAAM_DBG_BUF(var) (CFG_DBG_CAAM_BUF & DBG_TRACE_##var) /* * Debug Macros function of CAAM Debug Level setting * CFG_DBG_CAAM_TRACE Module print trace * CFG_DBG_CAAM_DESC Module descriptor dump * CFG_DBG_CAAM_BUF Module buffer dump * * A module is represented with the same bit in each configuration value. * Module Bit definition is as follow: */ #define DBG_TRACE_HAL BIT32(0) /* HAL trace */ #define DBG_TRACE_CTRL BIT32(1) /* Controller trace */ #define DBG_TRACE_MEM BIT32(2) /* Memory utility trace */ #define DBG_TRACE_SGT BIT32(3) /* Scatter Gather trace */ #define DBG_TRACE_PWR BIT32(4) /* Power trace */ #define DBG_TRACE_JR BIT32(5) /* Job Ring trace */ #define DBG_TRACE_RNG BIT32(6) /* RNG trace */ #define DBG_TRACE_HASH BIT32(7) /* Hash trace */ #define DBG_TRACE_RSA BIT32(8) /* RSA trace */ #define DBG_TRACE_CIPHER BIT32(9) /* Cipher dump Buffer */ #define DBG_TRACE_BLOB BIT32(10) /* BLOB trace */ #define DBG_TRACE_DMAOBJ BIT32(11) /* DMA Object trace */ #define DBG_TRACE_ECC BIT32(12) /* ECC trace */ #define DBG_TRACE_DH BIT32(13) /* DH trace */ #define DBG_TRACE_DSA BIT32(14) /* DSA trace */ #define DBG_TRACE_MP BIT32(15) /* MP trace */ #define DBG_TRACE_SM BIT32(16) /* Secure Memory trace */ #define DBG_TRACE_KEY BIT32(17) /* KEY trace */ /* HAL */ #if CAAM_DBG_TRACE(HAL) #define HAL_TRACE DRV_TRACE #else #define HAL_TRACE(...) #endif /* Controller */ #if CAAM_DBG_TRACE(CTRL) #define CTRL_TRACE DRV_TRACE #else #define CTRL_TRACE(...) #endif /* Memory Utility */ #if CAAM_DBG_TRACE(MEM) #define MEM_TRACE DRV_TRACE #else #define MEM_TRACE(...) #endif /* Scatter Gether Table */ #if CAAM_DBG_TRACE(SGT) #define SGT_TRACE DRV_TRACE #else #define SGT_TRACE(...) #endif /* Power */ #if CAAM_DBG_TRACE(PWR) #define PWR_TRACE DRV_TRACE #else #define PWR_TRACE(...) #endif /* Job Ring */ #if CAAM_DBG_TRACE(JR) #define JR_TRACE DRV_TRACE #if CAAM_DBG_DESC(JR) #define JR_DUMPDESC(desc) \ do { \ JR_TRACE("Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define JR_DUMPDESC(desc) #endif #else #define JR_TRACE(...) #define JR_DUMPDESC(desc) #endif /* RNG */ #if CAAM_DBG_TRACE(RNG) #define RNG_TRACE DRV_TRACE #if CAAM_DBG_DESC(RNG) #define RNG_DUMPDESC(desc) \ do { \ RNG_TRACE("RNG Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define RNG_DUMPDESC(desc) #endif #else #define RNG_TRACE(...) #define RNG_DUMPDESC(desc) #endif /* Hash */ #if CAAM_DBG_TRACE(HASH) #define HASH_TRACE DRV_TRACE #if CAAM_DBG_DESC(HASH) #define HASH_DUMPDESC(desc) \ do { \ HASH_TRACE("HASH Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define HASH_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(HASH) #define HASH_DUMPBUF DRV_DUMPBUF #else #define HASH_DUMPBUF(...) #endif #else #define HASH_TRACE(...) #define HASH_DUMPDESC(desc) #define HASH_DUMPBUF(...) #endif /* RSA */ #if CAAM_DBG_TRACE(RSA) #define RSA_TRACE DRV_TRACE #if CAAM_DBG_DESC(RSA) #define RSA_DUMPDESC(desc) \ do { \ RSA_TRACE("RSA Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define RSA_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(RSA) #define RSA_DUMPBUF DRV_DUMPBUF #else #define RSA_DUMPBUF(...) #endif #else #define RSA_TRACE(...) #define RSA_DUMPDESC(desc) #define RSA_DUMPBUF(...) #endif /* Cipher */ #if CAAM_DBG_TRACE(CIPHER) #define CIPHER_TRACE DRV_TRACE #if CAAM_DBG_DESC(CIPHER) #define CIPHER_DUMPDESC(desc) \ do { \ CIPHER_TRACE("CIPHER Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define CIPHER_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(CIPHER) #define CIPHER_DUMPBUF DRV_DUMPBUF #else #define CIPHER_DUMPBUF(...) #endif #else #define CIPHER_TRACE(...) #define CIPHER_DUMPDESC(desc) #define CIPHER_DUMPBUF(...) #endif /* DMA Object */ #if CAAM_DBG_TRACE(DMAOBJ) #define DMAOBJ_TRACE DRV_TRACE #else #define DMAOBJ_TRACE(...) #endif /* ECC */ #if CAAM_DBG_TRACE(ECC) #define ECC_TRACE DRV_TRACE #if CAAM_DBG_DESC(ECC) #define ECC_DUMPDESC(desc) \ do { \ ECC_TRACE("ECC Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define ECC_DUMPDESC(desc) do { } while (0) #endif #if CAAM_DBG_BUF(ECC) #define ECC_DUMPBUF DRV_DUMPBUF #else #define ECC_DUMPBUF(...) do { } while (0) #endif #else #define ECC_TRACE(...) do { } while (0) #define ECC_DUMPDESC(desc) do { } while (0) #define ECC_DUMPBUF(...) do { } while (0) #endif /* DH */ #if CAAM_DBG_TRACE(DH) #define DH_TRACE DRV_TRACE #if CAAM_DBG_DESC(DH) #define DH_DUMPDESC(desc) \ { \ DH_TRACE("DH Descriptor"); \ DRV_DUMPDESC(desc); \ } #else #define DH_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(DH) #define DH_DUMPBUF DRV_DUMPBUF #else #define DH_DUMPBUF(...) #endif #else #define DH_TRACE(...) #define DH_DUMPDESC(desc) #define DH_DUMPBUF(...) #endif /* DSA */ #if CAAM_DBG_TRACE(DSA) #define DSA_TRACE DRV_TRACE #if CAAM_DBG_DESC(DSA) #define DSA_DUMPDESC(desc) \ do { \ DSA_TRACE("DSA Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define DSA_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(DSA) #define DSA_DUMPBUF DRV_DUMPBUF #else #define DSA_DUMPBUF(...) #endif #else #define DSA_TRACE(...) #define DSA_DUMPDESC(desc) #define DSA_DUMPBUF(...) #endif /* MP */ #if CAAM_DBG_TRACE(MP) #define MP_TRACE DRV_TRACE #if CAAM_DBG_DESC(MP) #define MP_DUMPDESC(desc) \ do { \ MP_TRACE("MP Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define MP_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(MP) #define MP_DUMPBUF DRV_DUMPBUF #else #define MP_DUMPBUF(...) #endif #else #define MP_TRACE(...) do { } while (0) #define MP_DUMPDESC(desc) #define MP_DUMPBUF(...) #endif /* KEY */ #if CAAM_DBG_TRACE(KEY) #define KEY_TRACE DRV_TRACE #if CAAM_DBG_DESC(KEY) #define KEY_DUMPDESC(desc) \ do { \ KEY_TRACE("KEY Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define KEY_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(KEY) #define KEY_DUMPBUF DRV_DUMPBUF #else #define KEY_DUMPBUF(...) #endif #else #define KEY_TRACE(...) do { } while (0) #define KEY_DUMPDESC(desc) do { } while (0) #define KEY_DUMPBUF(...) do { } while (0) #endif #if (TRACE_LEVEL >= TRACE_DEBUG) #define DRV_TRACE(...) \ trace_printf(__func__, __LINE__, TRACE_DEBUG, true, __VA_ARGS__) #define DRV_DUMPDESC(desc) dump_desc(desc) #define DRV_DUMPBUF(title, buf, len) \ do { \ __typeof__(buf) _buf = (buf); \ __typeof__(len) _len = (len); \ \ DRV_TRACE("%s @%p : %zu", title, _buf, _len); \ dhex_dump(NULL, 0, 0, _buf, _len); \ } while (0) #else #define DRV_TRACE(...) #define DRV_DUMPDESC(...) #define DRV_DUMPBUF(...) #endif /* BLOB */ #if CAAM_DBG_TRACE(BLOB) #define BLOB_TRACE DRV_TRACE #if CAAM_DBG_DESC(BLOB) #define BLOB_DUMPDESC(desc) \ do { \ BLOB_TRACE("BLOB Descriptor"); \ DRV_DUMPDESC(desc); \ } while (0) #else #define BLOB_DUMPDESC(desc) #endif #if CAAM_DBG_BUF(BLOB) #define BLOB_DUMPBUF DRV_DUMPBUF #else #define BLOB_DUMPBUF(...) #endif #else #define BLOB_TRACE(...) #define BLOB_DUMPDESC(desc) #define BLOB_DUMPBUF(...) #endif /* Secure Memory */ #if CAAM_DBG_TRACE(SM) #define SM_TRACE DRV_TRACE #else #define SM_TRACE(...) #endif #endif /* CAAM_TRACE_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_types.h000066400000000000000000000016731464416617300241260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020-2021 NXP * * CAAM driver data type definition. */ #ifndef __CAAM_TYPES_H__ #define __CAAM_TYPES_H__ #include /* * Definition of a CAAM buffer type */ struct caambuf { uint8_t *data; /* Data buffer */ paddr_t paddr; /* Physical address of the buffer */ size_t length; /* Number of bytes in the data buffer */ uint8_t nocache; /* =1 if buffer is not cacheable, 0 otherwise */ }; /* * Definition of a CAAM Block buffer. Buffer used to store * user source data to build a full algorithm block buffer */ struct caamblock { struct caambuf buf; /* Data buffer */ size_t filled; /* Current length filled in the buffer */ size_t max; /* Maximum size of the block */ }; /* * Definition of key size */ struct caamdefkey { uint8_t min; /* Minimum size */ uint8_t max; /* Maximum size */ uint8_t mod; /* Key modulus */ }; #endif /* __CAAM_TYPES_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_utils_delay.h000066400000000000000000000005061464416617300252720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019 NXP * * Brief Delay management utilities header. */ #ifndef __CAAM_UTILS_DELAY_H__ #define __CAAM_UTILS_DELAY_H__ /* * Wait given microsecond * * @time Time in microsecond */ void caam_udelay(uint32_t time); #endif /* __CAAM_UTILS_DELAY_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_utils_dmaobj.h000066400000000000000000000145251464416617300254360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020-2021 NXP * * CAAM DMA data object utilities include file. */ #ifndef __CAAM_UTILS_DMAOBJ_H__ #define __CAAM_UTILS_DMAOBJ_H__ #include #include #include /* * CAAM DMA Object type * @priv Private object data not used externally. * @orig Original data buffer * @sgtbuf CAAM SGT/Buffer object */ struct caamdmaobj { void *priv; struct caambuf orig; struct caamsgtbuf sgtbuf; }; /* * Initialize a CAAM DMA object of type input data. * If necessary, a new CAAM Buffer will be reallocated if given @data is not * accessible by the CAAM DMA and input data copied into. * * @obj [out] CAAM DMA object initialized * @data Input data pointer * @length Length in bytes of the input data */ TEE_Result caam_dmaobj_init_input(struct caamdmaobj *obj, const void *data, size_t len); /* * Initialize and build the SGT/Buffer Object of a CAAM DMA object of type * input data. * Function call the caam_dmaobj_init_input function and if success * the caam_dmaobj_sgtbuf_build function. If the full size of the input * data can't be handled in the SGT/Buffer Object, returns in error. * * @obj [out] CAAM DMA object initialized * @data Input data pointer * @length Length in bytes of the input data */ TEE_Result caam_dmaobj_input_sgtbuf(struct caamdmaobj *obj, const void *data, size_t len); /* * Initialize a CAAM DMA object of type output data. * If necessary, a new CAAM Buffer will be reallocated if given @data is not * accessible by the CAAM DMA or if the given @length is lower than * @min_length requested for the CAAM operation. * * @obj [out] CAAM DMA object initialized * @data Output data pointer * @length Length in bytes of the output data * @min_length Minimum length in bytes needed for the output data */ TEE_Result caam_dmaobj_init_output(struct caamdmaobj *obj, void *data, size_t length, size_t min_length); /* * Initialize and build the SGT/Buffer Object of a CAAM DMA object of type * output data. * Function call the caam_dmaobj_init_output function and if success * the caam_dmaobj_sgtbuf_build function. If the full size of the output * data can't be handled in the SGT/Buffer Object, returns in error. * * Note: to allocate a output buffer, set @data = NULL and length = 0, the * buffer size allocated will be the @min_length size. Caution, the field * orig of the @obj is kept empty. * * @obj [out] CAAM DMA object initialized * @data Output data pointer * @length Length in bytes of the output data * @min_length Minimum length in bytes needed for the output data */ TEE_Result caam_dmaobj_output_sgtbuf(struct caamdmaobj *obj, void *data, size_t length, size_t min_length); /* * Push the data to physical memory with a cache clean or flush depending * on the type of data, respectively input or output. * * @obj CAAM DMA object */ void caam_dmaobj_cache_push(struct caamdmaobj *obj); /* * Copy the CAAM DMA object buffer to the original data buffer. * Return the number of bytes copied. * * @obj CAAM DMA object */ size_t caam_dmaobj_copy_to_orig(struct caamdmaobj *obj); /* * Copy the CAAM DMA object buffer to the original data buffer removing * non-significant first zeros (left zeros). * If all DMA object buffer is zero, left only one zero in the destination. * Return the number of bytes copied. * * @obj CAAM DMA object */ size_t caam_dmaobj_copy_ltrim_to_orig(struct caamdmaobj *obj); /* * Free the CAAM DMA object. * If a buffer has been reallocated, free it. * Free the sgtbuf object. * * @obj CAAM DMA object */ void caam_dmaobj_free(struct caamdmaobj *obj); /* * Create a CAAM DMA object SGT type with the block buffer @block first and * the CAAM DMA Object after * * @res CAAM DMA object resulting * @block CAAM Block buffer to add first * @obj CAAM DMA object to add secondly */ TEE_Result caam_dmaobj_add_first_block(struct caamdmaobj *obj, struct caamblock *block); /* * Derive a CAAM DMA object's sgtbuf object to a new DMA object. * The @from CAAM DMA object sgtbuf must have to be created first to * allocate the DMA Buffers. * * @obj [out] CAAM DMA object derived * @from Original CAAM DMA object * @offset Offset to start from * @length Length in bytes of the data */ TEE_Result caam_dmaobj_derive_sgtbuf(struct caamdmaobj *obj, const struct caamdmaobj *from, size_t offset, size_t length); /* * Build the CAAM DMA Object's sgtbuf input and output with the same data * length. * First try to build input sgtbuf of maximum @length starting at @offset. * Then build output sgtbuf with same input data length built start at @offset. * If output sgtbuf built data length is not the same as the input's one, * rebuild the input with same output data length. * * If the both input and output length are not equal returns an error. * * @input CAAM DMA Input object * @output CAAM DMA Output object * @length [in/out] maximum length to do/done * @off Starting offset * @align Buffer allocation alignment */ TEE_Result caam_dmaobj_sgtbuf_inout_build(struct caamdmaobj *input, struct caamdmaobj *output, size_t *length, size_t off, size_t align); /* * Prepare input/output CAAM DMA Object's by allocating the DMA Buffers * if needed. * If @input or @output is NULL, allocates DMA buffer of given object. * Else if both objects are set, allocates DMA buffer of the same * size for the @input and @output objects. * Minimum DMA Buffer size allocated is the @min_size value. Even if this * minimum size allocation failed, returns an error. * * @input CAAM DMA object input * @output CAAM DMA object output * @min_size Mimimum length to allocate */ TEE_Result caam_dmaobj_prepare(struct caamdmaobj *input, struct caamdmaobj *output, size_t min_size); /* * Build the CAAM DMA Object's sgtbuf object. Try to build a sgtbuf of * maximum @length starting at @offset. * Return the @length mapped in the sgtbuf object. * * @obj CAAM DMA object * @length [in/out] maximum length to do/done * @off Starting offset * @align Buffer allocation alignment */ TEE_Result caam_dmaobj_sgtbuf_build(struct caamdmaobj *obj, size_t *length, size_t off, size_t align); #endif /* __CAAM_UTILS_DMAOBJ_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_utils_mem.h000066400000000000000000000064461464416617300247630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief Memory management utilities. * Primitive to allocate, free memory. */ #ifndef __CAAM_UTILS_MEM_H__ #define __CAAM_UTILS_MEM_H__ #include /* * Allocate normal memory. * * @size size in bytes of the memory to allocate */ void *caam_alloc(size_t size); /* * Allocate normal memory and initialize it to 0's. * * @size size in bytes of the memory to allocate */ void *caam_calloc(size_t size); /* * Allocate memory aligned with a cache line and initialize it to 0's. * * @size size in bytes of the memory to allocate */ void *caam_calloc_align(size_t size); /* * Free allocated memory * * @ptr reference to the object to free */ void caam_free(void *ptr); /* * Allocate Job descriptor and initialize it to 0's. * * @nbentries Number of descriptor entries */ uint32_t *caam_calloc_desc(uint8_t nbentries); /* * Free descriptor * * @ptr Reference to the descriptor to free */ void caam_free_desc(uint32_t **ptr); /* * Allocate internal driver buffer and initialize it with 0s. * * @buf [out] buffer allocated * @size size in bytes of the memory to allocate */ enum caam_status caam_calloc_buf(struct caambuf *buf, size_t size); /* * Allocate internal driver buffer. * * @buf [out] buffer allocated * @size size in bytes of the memory to allocate */ enum caam_status caam_alloc_buf(struct caambuf *buf, size_t size); /* * Allocate internal driver buffer aligned with a cache line and initialize * if with 0's. * * @buf [out] buffer allocated * @size size in bytes of the memory to allocate */ enum caam_status caam_calloc_align_buf(struct caambuf *buf, size_t size); /* * Allocate internal driver buffer aligned with a cache line. * * @buf [out] buffer allocated * @size size in bytes of the memory to allocate */ enum caam_status caam_alloc_align_buf(struct caambuf *buf, size_t size); /* * Free internal driver buffer allocated memory * * @buf Driver buffer to free */ void caam_free_buf(struct caambuf *buf); /* * Copy source data into the block buffer. Allocate block buffer if * it's not defined. * * @block [in/out] Block buffer information. Return buffer filled. * @src Source to copy * @offset Source offset to start */ enum caam_status caam_cpy_block_src(struct caamblock *block, struct caambuf *src, size_t offset); /* * Return the number of Physical Areas used by the buffer @buf. * If @pabufs is not NULL, function fills it with the Physical Areas used * to map the buffer @buf. * * @buf Data buffer to analyze * @pabufs[out] If not NULL, list the Physical Areas of the @buf * * Returns: * Number of physical area used * (-1) if error */ int caam_mem_get_pa_area(struct caambuf *buf, struct caambuf **pabufs); /* * Return if the buffer @buf is cacheable or not * * @buf Buffer address * @size Buffer size */ bool caam_mem_is_cached_buf(void *buf, size_t size); /* * Copy source data into the destination buffer removing non-significant * first zeros (left zeros). * If all source @src buffer is zero, left only one zero in the destination. * * @dst [out] Destination buffer * @src Source to copy */ void caam_mem_cpy_ltrim_buf(struct caambuf *dst, struct caambuf *src); #endif /* __CAAM_UTILS_MEM_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_utils_sgt.h000066400000000000000000000102171464416617300247710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019, 2021 NXP * * Brief Scatter-Gather Table management utilities header. */ #ifndef __CAAM_UTILS_SGT_H__ #define __CAAM_UTILS_SGT_H__ #include #include #define BP_SGT_V2_OFFSET 48 #define BS_SGT_V2_OFFSET 12 #define SGT_V2_OFFSET_MAX_VALUE GENMASK_64(BS_SGT_V2_OFFSET - 1, 0) #define BM_SGT_V2_OFFSET \ SHIFT_U64(GENMASK_64(BS_SGT_V2_OFFSET - 1, 0), BP_SGT_V2_OFFSET) #define BV_SGT_V2_OFFSET(_x) SHIFT_U64(((uint64_t)_x), BP_SGT_V2_OFFSET) #define SGT_V2_ENTRY_OFFSET(_x) \ ((((uint64_t)_x) & BM_SGT_V2_OFFSET) >> BP_SGT_V2_OFFSET) #define BP_SGT_V2_AVAIL_LENGTH 0 #define BS_SGT_V2_AVAIL_LENGTH 32 #define SGT_V2_AVAIL_LENGTH_MAX_VALUE GENMASK_64(BS_SGT_V2_AVAIL_LENGTH - 1, 0) #define BM_SGT_V2_AVAIL_LENGTH \ SHIFT_U64(SGT_V2_AVAIL_LENGTH_MAX_VALUE, BP_SGT_V2_AVAIL_LENGTH) #define BV_SGT_V2_AVAIL_LENGTH(_x) \ SHIFT_U64(((uint64_t)_x), BP_SGT_V2_AVAIL_LENGTH) #define SGT_V2_ENTRY_AVAIL_LENGTH(_x) \ ((((uint64_t)_x) & BM_SGT_V2_AVAIL_LENGTH) >> BP_SGT_V2_AVAIL_LENGTH) #define BP_SGT_V2_F 63 #define BM_SGT_V2_F BIT64(BP_SGT_V2_F) #define BP_SGT_V2_IVP 46 #define BM_SGT_V2_IVP BIT64(BP_SGT_V2_IVP) /* * Scatter/Gather Table type for input and output data */ union caamsgt { struct { /* W0 - Address pointer (MS 8 LSBs) */ uint32_t ptr_ms; /* W1 - Address pointer (LS 32 bits) */ uint32_t ptr_ls; /* W2 - Length 30bits, 1bit Final, 1bit Extension */ uint32_t len_f_e; /* W3- Offset in memory buffer (13 LSBs) */ uint32_t offset; } v1; struct { uint64_t w1; /* Address of the data */ uint64_t w2; /* Final bit, offset and length */ } v2; }; /* * Data buffer encoded in SGT format */ struct caamsgtbuf { union caamsgt *sgt; /* SGT Array */ struct caambuf *buf; /* Buffer Array */ unsigned int number; /* Number of SGT/Buf */ size_t length; /* Total length of the data encoded */ paddr_t paddr; /* Physical address to use in CAAM descriptor */ bool sgt_type; /* Define the data format */ }; /* * Allocate data of type struct caamsgtbuf * * @data [out] Data object allocated */ enum caam_status caam_sgtbuf_alloc(struct caamsgtbuf *data); /* * Free data of type struct caamsgtbuf * * @data Data object to free */ void caam_sgtbuf_free(struct caamsgtbuf *data); /* * Cache operation on SGT table * * @op Cache operation * @insgt SGT table * @length Length of data to maintain */ void caam_sgt_cache_op(enum utee_cache_operation op, struct caamsgtbuf *insgt, size_t length); /* * Set a Scatter Gather Table Entry * * @sgt SGT entry * @paddr Data's physical address * @len Data's length * @offset Offset to start in data buffer * @final_e Final entry in the table if true */ void caam_sgt_set_entry(union caamsgt *sgt, vaddr_t paddr, size_t len, unsigned int offset, bool final_e); #define CAAM_SGT_ENTRY(sgt, paddr, len) \ caam_sgt_set_entry(sgt, paddr, len, 0, false) #define CAAM_SGT_ENTRY_FINAL(sgt, paddr, len) \ caam_sgt_set_entry(sgt, paddr, len, 0, true) /* * Build a SGT object with @data buffer. * If the @data buffer is a buffer mapped on non-contiguous physical areas, * convert it in SGT entries. * Fill the CAAM SGT table with the buffer list in @sgt parameter * * @sgt [in/out] SGT buffer list and table */ void caam_sgt_fill_table(struct caamsgtbuf *sgt); /* * Derive a CAAM SGT table from the @from SGT table starting @offset. * Allocate the resulting SGT table derived. * * @sgt [out] SGT buffer list and table * @from Input SGT table * @offset Offset to start * @length Length of the new SGT data */ enum caam_status caam_sgt_derive(struct caamsgtbuf *sgt, const struct caamsgtbuf *from, size_t offset, size_t length); /* * Print the details of an SGT entry using the trace macro * * @idx [in]Index of the sgt to print * @sgt [in] SGT buffer list and table */ void sgt_entry_trace(unsigned int idx, const struct caamsgtbuf *sgt); /* * Add an @offset to the SGT entry * * @sgt [in/out] Sgt entry * @offset Offset to add */ void sgt_entry_offset(union caamsgt *sgt, unsigned int offset); #endif /* __CAAM_UTILS_SGT_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/include/caam_utils_status.h000066400000000000000000000011161464416617300255150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019, 2021 NXP * * Brief Status code management utilities header. */ #ifndef __CAAM_UTILS_STATUS_H__ #define __CAAM_UTILS_STATUS_H__ #include #include #include /* * Convert Job status code to TEE Result * * @status Job status code */ TEE_Result job_status_to_tee_result(uint32_t status); /* * Convert caam status code to TEE Result * * @status caam status code */ TEE_Result caam_status_to_tee_result(enum caam_status status); #endif /* __CAAM_UTILS_STATUS_H__ */ optee_os-4.3.0/core/drivers/crypto/caam/mp/000077500000000000000000000000001464416617300206125ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/mp/caam_mp.c000066400000000000000000000242421464416617300223570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021, 2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define MP_SIGN_MAX_MSG_SIZE (4 * 1024) #ifdef CFG_PHYS_64BIT #define MP_PRIV_DESC_ENTRIES 7 #define MP_PUB_DESC_ENTRIES 7 #define MP_SIGN_DESC_ENTRIES 13 #else #define MP_PRIV_DESC_ENTRIES 6 #define MP_PUB_DESC_ENTRIES 6 #define MP_SIGN_DESC_ENTRIES 9 #endif /* * MP module private data */ static struct mp_privdata { uint8_t curve; /* Protocol Data Block curve selection */ uint8_t sec_size; /* Security key size in bytes */ vaddr_t ctrl_addr; /* Base address of the controller */ enum caam_status mp_status; /* Indicate the MP status */ } mp_privdata; /* * Generate manufacturing private key. * The ECDSA private key is securely stored in the MPPKR. * This register is locked to prevent reading or writing. * * @passphrase Passphrase * @len Passphrase length */ static enum caam_status do_mppriv_gen(const char *passphrase, size_t len) { enum caam_status ret = CAAM_FAILURE; struct caam_jobctx jobctx = { }; uint32_t *desc = NULL; uint32_t desclen = 0; MP_TRACE("MP private key generation"); assert(passphrase && len); desc = caam_calloc_desc(MP_PRIV_DESC_ENTRIES); if (!desc) return CAAM_OUT_MEMORY; caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PROT_MP_CURVE(mp_privdata.curve)); caam_desc_add_ptr(desc, virt_to_phys((void *)passphrase)); caam_desc_add_word(desc, len); caam_desc_add_word(desc, MPPRIVK); desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); MP_DUMPDESC(desc); cache_operation(TEE_CACHECLEAN, (void *)passphrase, len); jobctx.desc = desc; ret = caam_jr_enqueue(&jobctx, NULL); if (ret != CAAM_NO_ERROR) { MP_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = CAAM_NOT_SUPPORTED; } caam_free_desc(&desc); return ret; } TEE_Result caam_mp_export_mpmr(uint8_t *mpmr, size_t *size) { TEE_Result ret = TEE_ERROR_GENERIC; struct caambuf caam_mpmr = { .data = mpmr, .length = *size, }; MP_TRACE("Get MP message"); ret = caam_hal_ctrl_read_mpmr(mp_privdata.ctrl_addr, &caam_mpmr); *size = caam_mpmr.length; return ret; } TEE_Result caam_mp_export_publickey(uint8_t *pubkey, size_t *size) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; struct caamdmaobj reskey = { }; uint32_t pdb_sgt_flag = 0; uint32_t desclen = 0; uint32_t *desc = NULL; /* Check if MP is operational */ if (mp_privdata.mp_status != CAAM_NO_ERROR) return caam_status_to_tee_result(mp_privdata.mp_status); if (!pubkey || !size) return TEE_ERROR_BAD_PARAMETERS; /* The public key size is twice the private key size */ if (*size < 2 * mp_privdata.sec_size) { *size = 2 * mp_privdata.sec_size; return TEE_ERROR_SHORT_BUFFER; } ret = caam_dmaobj_output_sgtbuf(&reskey, pubkey, *size, 2 * mp_privdata.sec_size); if (ret) return ret; if (reskey.sgtbuf.sgt_type) pdb_sgt_flag = PROT_MP_PUBK_SGT; desc = caam_calloc_desc(MP_PUB_DESC_ENTRIES); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PROT_MP_CURVE(mp_privdata.curve) | pdb_sgt_flag); caam_desc_add_ptr(desc, reskey.sgtbuf.paddr); caam_desc_add_word(desc, reskey.sgtbuf.length); caam_desc_add_word(desc, MPPUBK); desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); MP_DUMPDESC(desc); caam_dmaobj_cache_push(&reskey); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { MP_TRACE("MP Public Key generated"); reskey.orig.length = 2 * mp_privdata.sec_size; *size = caam_dmaobj_copy_to_orig(&reskey); MP_DUMPBUF("MP PubKey", pubkey, *size); ret = caam_status_to_tee_result(retstatus); } else { MP_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } out: caam_dmaobj_free(&reskey); caam_free_desc(&desc); return ret; } TEE_Result caam_mp_sign(uint8_t *msg, size_t *msg_size, uint8_t *sig, size_t *sig_size) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct caam_jobctx jobctx = { }; struct caamdmaobj msg_input = { }; struct caamdmaobj sign_c = { }; struct caamdmaobj sign_d = { }; struct caambuf hash = { }; uint32_t *desc = NULL; uint32_t desclen = 0; uint32_t pdb_sgt_flags = 0; uint8_t *aligned_msg = NULL; size_t sign_len = 0; MP_TRACE("MP sign operation"); /* Check if MP is operational */ if (mp_privdata.mp_status != CAAM_NO_ERROR) return caam_status_to_tee_result(mp_privdata.mp_status); if (!msg || !msg_size || !sig || !sig_size) return TEE_ERROR_BAD_PARAMETERS; if (*sig_size < 2 * mp_privdata.sec_size) { *sig_size = 2 * mp_privdata.sec_size; return TEE_ERROR_SHORT_BUFFER; } if (*msg_size > MP_SIGN_MAX_MSG_SIZE) return TEE_ERROR_EXCESS_DATA; /* Re-allocate the message to a cache-aligned buffer */ aligned_msg = caam_alloc(*msg_size); if (!aligned_msg) { MP_TRACE("Message reallocation error"); ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_mpsign; } memcpy(aligned_msg, msg, *msg_size); /* * Allocate the hash buffer of the Message + MPMR payload * Note: Hash is not retrieve, hence no need to do cache * maintenance */ retstatus = caam_alloc_align_buf(&hash, TEE_MAX_HASH_SIZE); if (retstatus != CAAM_NO_ERROR) { MP_TRACE("Hash allocation error"); ret = caam_status_to_tee_result(retstatus); goto exit_mpsign; } /* * Re-allocate the signature result buffer with a maximum size * of the roundup to 16 bytes of the secure size in bytes if * the signature buffer is not aligned or too short. * * - 1st Part: size_sec * - 2nd Part: size_sec roundup to 16 bytes */ sign_len = ROUNDUP(mp_privdata.sec_size, 16) + mp_privdata.sec_size; ret = caam_dmaobj_output_sgtbuf(&sign_c, sig, *sig_size, sign_len); if (ret) goto exit_mpsign; if (sign_c.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_MP_SIGN_C; /* Prepare the 2nd Part of the signature. Derived from sign_c */ ret = caam_dmaobj_derive_sgtbuf(&sign_d, &sign_c, mp_privdata.sec_size, ROUNDUP(mp_privdata.sec_size, 16)); if (ret) goto exit_mpsign; if (sign_d.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_MP_SIGN_D; ret = caam_dmaobj_input_sgtbuf(&msg_input, aligned_msg, *msg_size); if (ret) goto exit_mpsign; if (msg_input.sgtbuf.sgt_type) pdb_sgt_flags |= PDB_SGT_MP_SIGN_MSG; desc = caam_calloc_desc(MP_SIGN_DESC_ENTRIES); if (!desc) { ret = TEE_ERROR_OUT_OF_MEMORY; goto exit_mpsign; } caam_desc_init(desc); caam_desc_add_word(desc, DESC_HEADER(0)); caam_desc_add_word(desc, PROT_MP_CURVE(mp_privdata.curve) | pdb_sgt_flags); caam_desc_add_ptr(desc, msg_input.sgtbuf.paddr); caam_desc_add_ptr(desc, hash.paddr); caam_desc_add_ptr(desc, sign_c.sgtbuf.paddr); caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr); caam_desc_add_word(desc, msg_input.sgtbuf.length); caam_desc_add_word(desc, MPSIGN_OP); desclen = caam_desc_get_len(desc); caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1)); MP_DUMPDESC(desc); caam_dmaobj_cache_push(&msg_input); caam_dmaobj_cache_push(&sign_c); jobctx.desc = desc; retstatus = caam_jr_enqueue(&jobctx, NULL); if (retstatus == CAAM_NO_ERROR) { sign_c.orig.length = 2 * mp_privdata.sec_size; *sig_size = caam_dmaobj_copy_to_orig(&sign_c); MP_DUMPBUF("MP Signature", sdata->signature.data, sdata->signature.length); ret = caam_status_to_tee_result(retstatus); } else { MP_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status); ret = job_status_to_tee_result(jobctx.status); } exit_mpsign: caam_free(aligned_msg); caam_free_buf(&hash); caam_free_desc(&desc); caam_dmaobj_free(&msg_input); caam_dmaobj_free(&sign_c); caam_dmaobj_free(&sign_d); return ret; } enum caam_status caam_mp_init(vaddr_t ctrl_addr) { /* * Manufacturing protection secret values for DSA key pair * generation. */ static const char passphrase[] = "manufacturing protection"; static const char mpmr_data[] = "value to fill the MPMR content"; enum caam_status retstatus = CAAM_FAILURE; uint8_t curve = 0; uint8_t hash_limit = 0; struct caambuf msg_mpmr = { .data = (uint8_t *)mpmr_data, .length = strlen(mpmr_data) }; mp_privdata.ctrl_addr = ctrl_addr; mp_privdata.mp_status = CAAM_NOT_INIT; curve = caam_hal_ctrl_get_mpcurve(ctrl_addr); if (curve == UINT8_MAX) { mp_privdata.mp_status = CAAM_NOT_SUPPORTED; return mp_privdata.mp_status; } if (caam_hal_ctrl_is_mp_set(ctrl_addr)) { mp_privdata.mp_status = CAAM_NO_ERROR; return CAAM_NO_ERROR; } if (!curve) { /* Get the device HASH Limit to select the MP Curve */ hash_limit = caam_hal_ctrl_hash_limit(ctrl_addr); switch (hash_limit) { case TEE_MAIN_ALGO_SHA256: mp_privdata.curve = PDB_MP_CSEL_P256; mp_privdata.sec_size = 32; break; case TEE_MAIN_ALGO_SHA512: mp_privdata.curve = PDB_MP_CSEL_P521; mp_privdata.sec_size = 66; break; default: MP_TRACE("This curve doesn't exist"); return CAAM_FAILURE; } MP_TRACE("Generating MP Private key"); retstatus = do_mppriv_gen(passphrase, strlen(passphrase)); if (retstatus != CAAM_NO_ERROR) { MP_TRACE("do_mppriv_gen failed!"); return retstatus; } } else { /* MP Curve is already programmed. Set the right key size */ mp_privdata.curve = curve; switch (curve) { case PDB_MP_CSEL_P256: mp_privdata.sec_size = 32; break; case PDB_MP_CSEL_P521: mp_privdata.sec_size = 66; break; default: MP_TRACE("This curve is not supported"); return CAAM_FAILURE; } } /* Fill the MPMR content then lock it */ caam_hal_ctrl_fill_mpmr(ctrl_addr, &msg_mpmr); mp_privdata.mp_status = CAAM_NO_ERROR; return CAAM_NO_ERROR; } enum caam_status caam_mp_resume(uint32_t pm_hint) { if (pm_hint == PM_HINT_CONTEXT_STATE) return caam_mp_init(mp_privdata.ctrl_addr); return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/mp/sub.mk000066400000000000000000000000551464416617300217340ustar00rootroot00000000000000incdirs-y += ../include srcs-y += caam_mp.c optee_os-4.3.0/core/drivers/crypto/caam/sub.mk000066400000000000000000000007351464416617300213250ustar00rootroot00000000000000incdirs-y += include subdirs-y += hal subdirs-y += utils srcs-y += caam_pwr.c srcs-y += caam_ctrl.c srcs-y += caam_jr.c srcs-y += caam_rng.c srcs-y += caam_desc.c srcs-$(CFG_NXP_CAAM_SM_DRV) += caam_sm.c srcs-y += caam_key.c subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_HASH_DRV CFG_NXP_CAAM_HMAC_DRV) += hash subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_CIPHER_DRV CFG_NXP_CAAM_CMAC_DRV) += cipher subdirs-y += acipher subdirs-y += blob subdirs-$(CFG_NXP_CAAM_MP_DRV) += mp optee_os-4.3.0/core/drivers/crypto/caam/utils/000077500000000000000000000000001464416617300213365ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/caam/utils/sub.mk000066400000000000000000000003531464416617300224610ustar00rootroot00000000000000incdirs-y += ../include srcs-y += utils_mem.c srcs-y += utils_delay.c srcs-y += utils_sgt.c srcs-$(CFG_NXP_CAAM_SGT_V1) += utils_sgt_v1.c srcs-$(CFG_NXP_CAAM_SGT_V2) += utils_sgt_v2.c srcs-y += utils_status.c srcs-y += utils_dmaobj.c optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_delay.c000066400000000000000000000005751464416617300240270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018 NXP * * Brief Delay management utilities. * Primitive to delay a delay. */ #include #include void caam_udelay(uint32_t time) { uint32_t counter = time * 500; /* Implementation of a Software loop assuming CPU clock of 500MHz */ while (counter--) { isb(); dsb(); }; } optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_dmaobj.c000066400000000000000000001052531464416617300241640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2021, 2023 NXP * * CAAM DMA data object utilities. */ #include #include #include #include #include #include #include #include #include #include #define IS_DMA_OVERFLOW(addr) ((addr) > UINT32_MAX) #define MAX_BUFFER_ALLOC_SIZE ((size_t)(8 * 1024)) /* * Local defines used to identify Object type as: * - input or output data * - SGT object created because buffer is not physical contiguous * - derived object (not buffer reallocation) * - allocated origin buffer */ #define DMAOBJ_INPUT BIT(0) #define DMAOBJ_OUTPUT BIT(1) #define DMAOBJ_ALLOC_ORIG BIT(2) #define DMAOBJ_DONT_COPY BIT(3) /* * DMA Buffer * * @require DMA Buffer size require * @allocated Size of the buffer allocated * @remind Size available in the buffer * @buf CAAM Buffer */ struct caamdmabuf { size_t require; size_t allocated; size_t remind; struct caambuf buf; }; /* * DMA Object buffer entry * * @newbuf True if list entry is a new DMA Buffer * @nodma_access Buffer is not accessible from CAAM DMA * @nocopy Buffer doesn't have to be copied back to the origin * @origbuf Original buffer reference * @link Pointer to next entry */ struct dmaentry { bool newbuf; bool nodma_access; bool nocopy; struct caambuf origbuf; TAILQ_ENTRY(dmaentry) link; }; /* * SGT/Buffer Data currently handled * * @orig Original buffer reference * @dma DMA Buffer (new or original) * @length Buffer length */ struct sgtdata { uint8_t *orig; uint8_t *dma; size_t length; }; /* * CAAM DMA private Object data * @type Type of DMA Object * @nb_sgtbuf Number of SGT/Buffer entries allocated * @dmabuf DMA Buffer allocated * @sgtdata Reference to SGT/Buffer list in used * @list List of the DMA Object buffer entry */ struct priv_dmaobj { unsigned int type; unsigned int nb_sgtbuf; struct caamdmabuf dmabuf; struct sgtdata *sgtdata; TAILQ_HEAD(dmalist, dmaentry) list; }; /* * Memory allocation and free spinlock to ensure that in case * of big buffer reallocation, memory used is freed */ static unsigned int memlock; /* * Try to allocate a DMA Buffer of type input or output data of @size bytes. * If allocation success, set the DMA Buffer settings, else * return in error. * * @priv CAAM DMA object private data * @size Size of the DMA Buffer to allocate */ static TEE_Result try_allocate_dmabuf(struct priv_dmaobj *priv, size_t size) { enum caam_status retstatus = CAAM_FAILURE; if (priv->dmabuf.allocated) { caam_free_buf(&priv->dmabuf.buf); priv->dmabuf.allocated = 0; } if (priv->type & DMAOBJ_INPUT) retstatus = caam_alloc_buf(&priv->dmabuf.buf, size); else retstatus = caam_alloc_align_buf(&priv->dmabuf.buf, size); DMAOBJ_TRACE("Alloc %s DMA buffer (%zu) ret 0x%" PRIx32, (priv->type & DMAOBJ_INPUT) ? "Input" : "Output", size, retstatus); if (retstatus == CAAM_NO_ERROR) { DMAOBJ_TRACE("DMA buffer Allocation Success"); /* Set the Object's DMA Buffer settings */ priv->dmabuf.allocated = size; priv->dmabuf.remind = size; priv->dmabuf.buf.length = 0; return TEE_SUCCESS; } DMAOBJ_TRACE("DMA buffer Allocation Failure"); return TEE_ERROR_OUT_OF_MEMORY; } /* * Allocate and initialize the CAAM DMA object's private data. * * @obj CAAM DMA Object * @type Type of the CAAM DMA Object (i.e. Input or Output) */ static TEE_Result allocate_private(struct caamdmaobj *obj, unsigned int type) { struct priv_dmaobj *priv = NULL; priv = caam_calloc(sizeof(*priv)); if (!priv) return TEE_ERROR_OUT_OF_MEMORY; obj->priv = priv; /* Set the object type as input */ priv->type = type; TAILQ_INIT(&priv->list); return TEE_SUCCESS; } /* * Fill the @sgtdata object to record the current input/output data * handled in the DMA SGT/Buffer object. * Increment the SGT/Buffer length according * * @obj CAAM DMA object * @sgtdata [out] SGT Data handled * @entry DMA Object buffer entry * @dma DMA SGT/Buffer object * @offset Start offset of the DMA Object buffer */ static void add_sgtdata_entry(struct caamdmaobj *obj, struct sgtdata *sgtdata, struct dmaentry *entry, struct caambuf *dma, size_t offset) { if (entry->nocopy) { sgtdata->orig = 0; sgtdata->length = 0; sgtdata->dma = 0; } else { sgtdata->orig = entry->origbuf.data + offset; sgtdata->length = dma->length; sgtdata->dma = dma->data; } obj->sgtbuf.length += dma->length; } /* * Add a new DMA Buffer entry as first element of the list. * Return NULL if error, else the new entry in the list * * @priv DMA Object private data * @orig Original buffer reference */ static struct dmaentry *dmalist_add_entry_head(struct priv_dmaobj *priv, struct caambuf *orig) { struct dmaentry *entry = NULL; entry = caam_calloc(sizeof(*entry)); if (entry) { /* Save the original buffer reference */ memcpy(&entry->origbuf, orig, sizeof(entry->origbuf)); DMAOBJ_TRACE("entry %p - insert head entry of %zu bytes", entry, orig->length); TAILQ_INSERT_HEAD(&priv->list, entry, link); } return entry; } /* * Add a new DMA Buffer entry in the list. * Return NULL if error, else the new entry in the list * * @priv DMA Object private data * @orig Original buffer reference */ static struct dmaentry *dmalist_add_entry(struct priv_dmaobj *priv, struct caambuf *orig) { struct dmaentry *entry = NULL; entry = caam_calloc(sizeof(*entry)); if (entry) { /* Save the original buffer reference */ memcpy(&entry->origbuf, orig, sizeof(entry->origbuf)); DMAOBJ_TRACE("entry %p - insert entry of %zu bytes", entry, orig->length); if (TAILQ_EMPTY(&priv->list)) TAILQ_INSERT_HEAD(&priv->list, entry, link); else TAILQ_INSERT_TAIL(&priv->list, entry, link); } return entry; } /* * Insert and allocate a DMA entry in the list before the given DMA entry. * Return the allocated DMA entry. * * @priv DMA Object private data * @before DMA entry after the new DMA entry * @new CAAM buffer of the new DMA entry */ static struct dmaentry *dmalist_insert_before_entry(struct priv_dmaobj *priv, struct dmaentry *before, struct caambuf *new) { struct dmaentry *entry = NULL; entry = caam_calloc(sizeof(*entry)); if (entry) { /* Save the original buffer reference */ memcpy(&entry->origbuf, new, sizeof(entry->origbuf)); DMAOBJ_TRACE("entry %p - insert entry of %zu bytes", entry, new->length); if (TAILQ_FIRST(&priv->list) == before) TAILQ_INSERT_HEAD(&priv->list, entry, link); else TAILQ_INSERT_BEFORE(before, entry, link); } return entry; } /* * Insert and allocate a DMA entry in the list after the given DMA entry. * Return the allocated DMA entry. * * @priv DMA Object private data * @after DMA entry before the new DMA entry * @new CAAM buffer of the new DMA entry */ static struct dmaentry *dmalist_insert_after_entry(struct priv_dmaobj *priv, struct dmaentry *after, struct caambuf *new) { struct dmaentry *entry = NULL; entry = caam_calloc(sizeof(*entry)); if (entry) { /* Save the original buffer reference */ memcpy(&entry->origbuf, new, sizeof(entry->origbuf)); DMAOBJ_TRACE("entry %p - insert entry of %zu bytes", entry, new->length); TAILQ_INSERT_AFTER(&priv->list, after, entry, link); } return entry; } /* * Apply the cache operation @op to the DMA Object (SGT or buffer) * * @op Cache operation * @obj CAAM DMA object */ static inline void dmaobj_cache_operation(enum utee_cache_operation op, struct caamdmaobj *obj) { if (!obj->sgtbuf.length) return; if (obj->sgtbuf.sgt_type) caam_sgt_cache_op(op, &obj->sgtbuf, obj->sgtbuf.length); else if (!obj->sgtbuf.buf->nocache) cache_operation(op, obj->sgtbuf.buf->data, obj->sgtbuf.length); } /* * Set the required allocation size for the DMA buffer. * * @priv DMA Object private data * @length Required buffer size */ static inline void add_dma_require(struct priv_dmaobj *priv, size_t length) { size_t tmp = 0; if (ADD_OVERFLOW(priv->dmabuf.require, length, &tmp)) priv->dmabuf.require = SIZE_MAX; else priv->dmabuf.require = tmp; } /* * Check if the buffer start/end addresses are aligned on the cache line. * If not flags as start and/or end addresses not aligned, expect if the * maximum length @maxlen to use is inside a cache line size. In this case, * flags to allocate a new buffer. * * @priv DMA Object private data * @maxlen Maximum length to use */ static TEE_Result check_buffer_alignment(struct priv_dmaobj *priv, size_t maxlen) { unsigned int cacheline_size = 0; struct dmaentry *entry = NULL; struct dmaentry *new_entry = NULL; struct caambuf newbuf = {}; vaddr_t va_start = 0; vaddr_t va_end = 0; vaddr_t va_end_align = 0; vaddr_t va_start_align = 0; size_t remlen = 0; size_t acclen = 0; cacheline_size = dcache_get_line_size(); TAILQ_FOREACH(entry, &priv->list, link) { DMAOBJ_TRACE("Entry %p: start %p len %zu (%zu >= %zu)", entry, entry->origbuf.data, entry->origbuf.length, acclen, maxlen); /* No need to continue if we convert the needed length */ if (acclen >= maxlen) return TEE_SUCCESS; acclen += entry->origbuf.length; if (entry->nodma_access || entry->newbuf) continue; if (entry->origbuf.length < cacheline_size) { /* * Length of the entry is not aligned on cache size * Require a full aligned buffer */ DMAOBJ_TRACE("Length %zu vs cache line %u", entry->origbuf.length, cacheline_size); entry->newbuf = true; add_dma_require(priv, entry->origbuf.length); continue; } va_start = (vaddr_t)entry->origbuf.data; va_start_align = ROUNDUP(va_start, cacheline_size); if (va_start_align != va_start) { DMAOBJ_TRACE("Start 0x%" PRIxVA " vs align 0x%" PRIxVA, va_start, va_start_align); remlen = entry->origbuf.length - (va_start_align - va_start); if (remlen <= cacheline_size) { /* * Start address is not aligned and the * remaining length if after re-alignment * is not cache size aligned. * Require a full aligned buffer */ DMAOBJ_TRACE("Rem length %zu vs cache line %u", remlen, cacheline_size); entry->newbuf = true; add_dma_require(priv, entry->origbuf.length); continue; } /* * Insert a new entry to make buffer on a cache line. */ newbuf.data = entry->origbuf.data; newbuf.length = va_start_align - va_start; newbuf.paddr = entry->origbuf.paddr; newbuf.nocache = entry->origbuf.nocache; add_dma_require(priv, newbuf.length); new_entry = dmalist_insert_before_entry(priv, entry, &newbuf); if (!new_entry) return TEE_ERROR_OUT_OF_MEMORY; new_entry->newbuf = true; /* * Update current entry with align address and new * length. */ entry->origbuf.data = (uint8_t *)va_start_align; entry->origbuf.length -= newbuf.length; entry->origbuf.paddr += newbuf.length; /* * Set current entry to new entry to continue * the FOREACH loop from this new_entry and then * verify the rest of the entry modified. */ entry = new_entry; acclen -= entry->origbuf.length; continue; } va_end = (vaddr_t)entry->origbuf.data + entry->origbuf.length; va_end_align = ROUNDUP(va_end, cacheline_size); if (va_end != va_end_align) { DMAOBJ_TRACE("End 0x%" PRIxVA " vs align 0x%" PRIxVA, va_end, va_end_align); va_end_align = ROUNDDOWN(va_end, cacheline_size); remlen = entry->origbuf.length - va_end_align; if (remlen <= cacheline_size) { /* * End address is not aligned and the remaining * length if after re-alignment is not cache * size aligned. * Require a full aligned buffer */ DMAOBJ_TRACE("Rem length %zu vs cache line %u", remlen, cacheline_size); entry->newbuf = true; add_dma_require(priv, entry->origbuf.length); continue; } /* * Insert a new entry to make buffer on a cache line. */ newbuf.data = (uint8_t *)va_end_align; newbuf.length = va_end - va_end_align; newbuf.paddr = entry->origbuf.paddr + newbuf.length; newbuf.nocache = entry->origbuf.nocache; add_dma_require(priv, newbuf.length); new_entry = dmalist_insert_after_entry(priv, entry, &newbuf); if (!new_entry) return TEE_ERROR_OUT_OF_MEMORY; new_entry->newbuf = true; /* Update current entry with new length */ entry->origbuf.length -= newbuf.length; /* * Set current entry to new entry to continue * the FOREACH loop from this new_entry and then * verify the rest of the entry modified. */ entry = new_entry; acclen -= newbuf.length; continue; } } return TEE_SUCCESS; } /* * Go through all the @orig space to extract all physical area used to * map the buffer. * If one of the physical area is not accessible by the CAAM DMA, flag it * to be reallocated with DMA accessible buffer. * If the DMA Object is an output buffer, check and flag the start/end * address of the buffer to be aligned on a cache line. * * @obj CAAM DMA object * @orig Original Data * @maxlen Maximum length to use */ static TEE_Result check_buffer_boundary(struct caamdmaobj *obj, struct caambuf *orig, size_t maxlen) { TEE_Result ret = TEE_ERROR_OUT_OF_MEMORY; struct priv_dmaobj *priv = obj->priv; struct dmaentry *entry = NULL; struct caambuf *pabufs = NULL; int nb_pa_area = -1; int idx = 0; paddr_t last_pa = 0; size_t remlen = maxlen; size_t tmp = 0; /* * Get the number of physical areas used by the * DMA Buffer */ nb_pa_area = caam_mem_get_pa_area(orig, &pabufs); DMAOBJ_TRACE("Number of pa areas = %d (for max length %zu bytes)", nb_pa_area, remlen); if (nb_pa_area == -1) goto out; for (idx = 0; idx < nb_pa_area && remlen; idx++) { DMAOBJ_TRACE("Remaining length = %zu", remlen); if (ADD_OVERFLOW(pabufs[idx].paddr, pabufs[idx].length, &last_pa)) goto out; DMAOBJ_TRACE("PA 0x%" PRIxPA " = 0x%" PRIxPA " + %zu", last_pa, pabufs[idx].paddr, pabufs[idx].length); entry = dmalist_add_entry(priv, &pabufs[idx]); if (!entry) goto out; if (IS_DMA_OVERFLOW(last_pa)) { entry->nodma_access = true; if (ADD_OVERFLOW(priv->dmabuf.require, pabufs[idx].length, &tmp)) priv->dmabuf.require = SIZE_MAX; else priv->dmabuf.require = tmp; } if (remlen > pabufs[idx].length) remlen -= pabufs[idx].length; else remlen = 0; } /* * Check the buffer alignment if the buffer is cacheable and * an output buffer. */ if (priv->type & DMAOBJ_OUTPUT && !orig->nocache) { ret = check_buffer_alignment(priv, maxlen); if (ret) goto out; } orig->length = maxlen; ret = TEE_SUCCESS; out: caam_free(pabufs); return ret; } /* * Re-map a DMA entry into a CAAM DMA accessible buffer. * Create the SGT/Buffer entry to be used in the CAAM Descriptor * Record this entry in the SGT/Buffer Data to get information on current * working data. * * @obj CAAM DMA object * @entry DMA entry to re-map * @index Index in the SGT/Buffer table * @off Start offset of the DMA entry data */ static enum caam_status entry_sgtbuf_dmabuf(struct caamdmaobj *obj, struct dmaentry *entry, unsigned int index, size_t off) { struct priv_dmaobj *priv = obj->priv; struct caambuf *sgtbuf = &obj->sgtbuf.buf[index]; struct caamdmabuf *dmabuf = &priv->dmabuf; if (!priv->dmabuf.allocated) return CAAM_OUT_MEMORY; sgtbuf->data = dmabuf->buf.data + dmabuf->buf.length; sgtbuf->length = MIN(dmabuf->remind, entry->origbuf.length - off); sgtbuf->paddr = dmabuf->buf.paddr + dmabuf->buf.length; sgtbuf->nocache = dmabuf->buf.nocache; dmabuf->remind -= sgtbuf->length; dmabuf->buf.length += sgtbuf->length; if (priv->type & DMAOBJ_INPUT) memcpy(sgtbuf->data, &entry->origbuf.data[off], sgtbuf->length); else entry->newbuf = true; add_sgtdata_entry(obj, &priv->sgtdata[index], entry, sgtbuf, off); return CAAM_NO_ERROR; } /* * Create the SGT/Buffer entry mapping the DMA @entry. * Record these entry in the SGT/buffer Data to get information on current * working data. * * @obj CAAM DMA object * @entry DMA entry to re-map * @index Index in the SGT/Buffer table * @off Start offset of the DMA entry data */ static enum caam_status entry_sgtbuf(struct caamdmaobj *obj, struct dmaentry *entry, unsigned int index, size_t off) { struct priv_dmaobj *priv = obj->priv; struct caambuf *sgtbuf = &obj->sgtbuf.buf[index]; struct sgtdata *sgtdata = &priv->sgtdata[index]; memcpy(sgtbuf, &entry->origbuf, sizeof(*sgtbuf)); sgtbuf->data += off; sgtbuf->paddr += off; sgtbuf->length -= off; DMAOBJ_TRACE("DMA buffer %p - %zu", sgtbuf->data, sgtbuf->length); add_sgtdata_entry(obj, sgtdata, entry, sgtbuf, off); return CAAM_NO_ERROR; } TEE_Result caam_dmaobj_init_input(struct caamdmaobj *obj, const void *data, size_t length) { TEE_Result ret = TEE_ERROR_GENERIC; DMAOBJ_TRACE("Input object with data @%p of %zu bytes", data, length); if (!data || !length || !obj) { ret = TEE_ERROR_BAD_PARAMETERS; goto err; } obj->orig.paddr = virt_to_phys((void *)data); if (!obj->orig.paddr) { DMAOBJ_TRACE("Object virtual address error"); ret = TEE_ERROR_BAD_PARAMETERS; goto err; } obj->orig.data = (void *)data; obj->orig.length = length; if (!caam_mem_is_cached_buf((void *)data, length)) obj->orig.nocache = 1; ret = allocate_private(obj, DMAOBJ_INPUT); if (ret) goto err; ret = check_buffer_boundary(obj, &obj->orig, obj->orig.length); goto out; err: caam_dmaobj_free(obj); out: DMAOBJ_TRACE("Object returns 0x%" PRIx32, ret); return ret; } TEE_Result caam_dmaobj_input_sgtbuf(struct caamdmaobj *obj, const void *data, size_t length) { TEE_Result ret = TEE_ERROR_GENERIC; size_t size_done = length; ret = caam_dmaobj_init_input(obj, data, length); if (ret) goto err; ret = caam_dmaobj_prepare(obj, NULL, length); if (ret) goto err; ret = caam_dmaobj_sgtbuf_build(obj, &size_done, 0, length); if (ret) goto err; if (size_done != length) { ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } return TEE_SUCCESS; err: caam_dmaobj_free(obj); return ret; } TEE_Result caam_dmaobj_init_output(struct caamdmaobj *obj, void *data, size_t length, size_t min_length) { TEE_Result ret = TEE_ERROR_GENERIC; struct dmaentry *entry = NULL; struct caambuf newbuf = {}; DMAOBJ_TRACE("Output object with data @%p of %zu bytes (%zu)", data, length, min_length); if (!obj) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } ret = allocate_private(obj, DMAOBJ_OUTPUT); if (ret) goto err; if (data) { obj->orig.paddr = virt_to_phys((void *)data); if (!obj->orig.paddr) { DMAOBJ_TRACE("Object virtual address error"); ret = TEE_ERROR_BAD_PARAMETERS; goto err; } obj->orig.data = (void *)data; obj->orig.length = length; if (!caam_mem_is_cached_buf((void *)data, length)) obj->orig.nocache = 1; ret = check_buffer_boundary(obj, &obj->orig, MIN(min_length, obj->orig.length)); if (ret) goto err; } if (length < min_length || !data) { DMAOBJ_TRACE("Output buffer too short need %zu bytes (+%zu)", min_length, min_length - length); newbuf.length = min_length - length; entry = dmalist_add_entry(obj->priv, &newbuf); if (!entry) { ret = TEE_ERROR_OUT_OF_MEMORY; goto err; } /* Add the additional size in the DMA buffer length */ add_dma_require(obj->priv, newbuf.length); entry->nocopy = true; entry->newbuf = true; } ret = TEE_SUCCESS; goto out; err: caam_dmaobj_free(obj); out: DMAOBJ_TRACE("Object returns 0x%" PRIx32, ret); return ret; } TEE_Result caam_dmaobj_output_sgtbuf(struct caamdmaobj *obj, void *data, size_t length, size_t min_length) { enum caam_status retstatus = CAAM_FAILURE; TEE_Result ret = TEE_ERROR_GENERIC; struct priv_dmaobj *priv = NULL; size_t size = 0; struct caambuf buf = {}; if (!data && !length && min_length) { /* * We are sure that the minimum size of the allocated * buffer is a cache line, hence we know that * start/end address are cache aligned. * If the @min_length is less than a cache line size, we * can initializing the output buffer with the cache line size * to prevent end buffer misalignement so reallocate a not used * buffer. */ size = MAX(min_length, dcache_get_line_size()); /* Allocate a new cache aligned buffer */ retstatus = caam_alloc_align_buf(&buf, size); DMAOBJ_TRACE("New output buffer of %zu bytes ret 0x%" PRIx32, min_length, retstatus); if (retstatus != CAAM_NO_ERROR) return caam_status_to_tee_result(retstatus); ret = caam_dmaobj_init_output(obj, buf.data, buf.length, size); if (ret) return ret; /* Set the correct origin buffer length asked */ obj->orig.length = min_length; /* Flag origin buffer as new allocation to free it */ priv = obj->priv; priv->type |= DMAOBJ_ALLOC_ORIG; } else { ret = caam_dmaobj_init_output(obj, data, length, min_length); if (ret) return ret; } ret = caam_dmaobj_prepare(NULL, obj, min_length); if (ret) return ret; size = min_length; ret = caam_dmaobj_sgtbuf_build(obj, &size, 0, min_length); if (ret) return ret; if (size != min_length) return TEE_ERROR_OUT_OF_MEMORY; return TEE_SUCCESS; } void caam_dmaobj_cache_push(struct caamdmaobj *obj) { struct priv_dmaobj *priv = NULL; enum utee_cache_operation op = TEE_CACHECLEAN; if (!obj || !obj->priv) return; priv = obj->priv; if (priv->type & DMAOBJ_OUTPUT) op = TEE_CACHEFLUSH; dmaobj_cache_operation(op, obj); } size_t caam_dmaobj_copy_to_orig(struct caamdmaobj *obj) { struct priv_dmaobj *priv = NULL; unsigned int idx = 0; size_t length = 0; size_t dst_rlen = 0; size_t copy_size = 0; if (!obj || !obj->orig.data || !obj->priv) return 0; dmaobj_cache_operation(TEE_CACHEINVALIDATE, obj); priv = obj->priv; /* * The maximum data size to copy cannot exceed the output buffer size * (obj->orig.length) and cannot exceed the data processed by the * CAAM (obj->sgtbuf.length). */ dst_rlen = MIN(obj->orig.length, obj->sgtbuf.length); DMAOBJ_TRACE("Copy (len=%zu)", dst_rlen); for (idx = 0; idx < obj->sgtbuf.number; idx++) { struct sgtdata *sgtdata = &priv->sgtdata[idx]; copy_size = MIN(dst_rlen, sgtdata->length); if (sgtdata->orig != sgtdata->dma && sgtdata->orig) { copy_size = MIN(dst_rlen, sgtdata->length); memcpy(sgtdata->orig, sgtdata->dma, copy_size); } length += copy_size; dst_rlen -= copy_size; } return length; } size_t caam_dmaobj_copy_ltrim_to_orig(struct caamdmaobj *obj) { struct priv_dmaobj *priv = NULL; uint8_t *dst = NULL; size_t off = 0; size_t offset = 0; size_t dst_rlen = 0; size_t copy_size = 0; unsigned int idx = 0; size_t length = 0; if (!obj || !obj->orig.data || !obj->priv) return 0; dmaobj_cache_operation(TEE_CACHEINVALIDATE, obj); priv = obj->priv; /* Parse the SGT data list to discard leading zeros */ for (idx = 0; idx < obj->sgtbuf.number; idx++) { struct sgtdata *sgtdata = &priv->sgtdata[idx]; if (!sgtdata->orig) continue; for (offset = 0; offset < sgtdata->length; off++, offset++) { if (sgtdata->dma[offset]) goto do_copy; } } do_copy: if (off < obj->orig.length) dst_rlen = obj->orig.length - off; dst = obj->orig.data; DMAOBJ_TRACE("Copy/Move Offset=%zu (len=%zu) TYPE=%d", off, dst_rlen, obj->sgtbuf.sgt_type); if (!dst_rlen) { dst[0] = 0; return 1; } /* * After discarding leading zeros in the SGT data list, start the copy * operation on the remaining elements of the data list. * List index must not be re-initialized before entering this loop. */ for (; idx < obj->sgtbuf.number; idx++) { struct sgtdata *sgtdata = &priv->sgtdata[idx]; if (!sgtdata->orig) continue; if (offset) { copy_size = MIN(dst_rlen, sgtdata->length - offset); memmove(dst, &sgtdata->dma[offset], copy_size); offset = 0; } else { copy_size = MIN(dst_rlen, sgtdata->length); if (dst != sgtdata->dma) memmove(dst, sgtdata->dma, copy_size); } dst += copy_size; dst_rlen -= copy_size; length += copy_size; } return length; } void caam_dmaobj_free(struct caamdmaobj *obj) { struct priv_dmaobj *priv = NULL; struct dmaentry *entry = NULL; struct dmaentry *next = NULL; uint32_t exceptions = 0; if (!obj) return; exceptions = cpu_spin_lock_xsave(&memlock); priv = obj->priv; if (!priv) goto out; DMAOBJ_TRACE("Free %s object with data @%p of %zu bytes", priv->type & DMAOBJ_INPUT ? "Input" : "Output", obj->orig.data, obj->orig.length); TAILQ_FOREACH_SAFE(entry, &priv->list, link, next) { DMAOBJ_TRACE("Is type 0x%" PRIx8 " newbuf %s", priv->type, entry->newbuf ? "true" : "false"); DMAOBJ_TRACE("Free entry %p", entry); caam_free(entry); } if (priv->nb_sgtbuf) { DMAOBJ_TRACE("Free #%d SGT data %p", priv->nb_sgtbuf, priv->sgtdata); caam_free(priv->sgtdata); obj->sgtbuf.number = priv->nb_sgtbuf; obj->sgtbuf.sgt_type = (priv->nb_sgtbuf > 1) ? true : false; } if (priv->dmabuf.allocated) { DMAOBJ_TRACE("Free CAAM DMA buffer"); caam_free_buf(&priv->dmabuf.buf); } if (priv->type & DMAOBJ_ALLOC_ORIG) { DMAOBJ_TRACE("Free Allocated origin"); caam_free_buf(&obj->orig); } DMAOBJ_TRACE("Free private object %p", priv); caam_free(priv); out: if (obj->sgtbuf.number) { DMAOBJ_TRACE("Free #%d SGT/Buffer %p", obj->sgtbuf.number, &obj->sgtbuf); caam_sgtbuf_free(&obj->sgtbuf); } memset(obj, 0, sizeof(*obj)); cpu_spin_unlock_xrestore(&memlock, exceptions); } TEE_Result caam_dmaobj_add_first_block(struct caamdmaobj *obj, struct caamblock *block) { struct priv_dmaobj *priv = NULL; struct caambuf newbuf = {}; struct dmaentry *entry = NULL; if (!obj || !obj->priv || !block) return TEE_ERROR_BAD_PARAMETERS; priv = obj->priv; /* Save the block buffer reference and insert it at the head list */ newbuf.data = block->buf.data; newbuf.length = block->filled; newbuf.paddr = block->buf.paddr; newbuf.nocache = block->buf.nocache; entry = dmalist_add_entry_head(priv, &newbuf); if (!entry) return TEE_ERROR_OUT_OF_MEMORY; /* * Block buffer added in the output DMA buffer doesn't have to * be part of the output copy to origin buffer. */ if (priv->type & DMAOBJ_OUTPUT) entry->nocopy = true; return TEE_SUCCESS; } TEE_Result caam_dmaobj_derive_sgtbuf(struct caamdmaobj *obj, const struct caamdmaobj *from, size_t offset, size_t length) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct priv_dmaobj *priv = NULL; DMAOBJ_TRACE("Derive object %p - offset %zu - length %zu bytes", from, offset, length); if (!obj || !from || !length || !from->priv) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } if (!from->orig.data || !from->orig.length) { DMAOBJ_TRACE("No data/length to derive from"); ret = TEE_ERROR_NO_DATA; goto out; } priv = from->priv; if (!priv->nb_sgtbuf) { DMAOBJ_TRACE("From SGT/Buffer not prepared"); ret = TEE_ERROR_NO_DATA; goto out; } retstatus = caam_sgt_derive(&obj->sgtbuf, &from->sgtbuf, offset, length); ret = caam_status_to_tee_result(retstatus); out: DMAOBJ_TRACE("Object returns 0x%" PRIx32, ret); return ret; } /* * Get the maximum allocation size for the given CAAM DMA object. * Return the maximum allocation size. * * @obj CAAM DMA object */ static size_t get_dma_max_alloc_size(struct caamdmaobj *obj) { size_t alloc_size = 0; struct priv_dmaobj *priv = NULL; if (!obj) return 0; priv = obj->priv; DMAOBJ_TRACE("DMA buffer size require %zu", priv->dmabuf.require); alloc_size = MIN(priv->dmabuf.require, MAX_BUFFER_ALLOC_SIZE); if (alloc_size > 1024) alloc_size = ROUNDDOWN(alloc_size, 1024); return alloc_size; } /* * Allocate the CAAM DMA buffer. * First, try to allocate the with the maximum size. If it fails, try to * allocate with the same size divided by two. Try to allocate until * minimum size is reached. If the allocation cannot be done with the * minimum size, return TEE_ERROR_OUT_OF_MEMORY, TEE_SUCCESS otherwise. * * @obj CAAM DMA object * @min_size minimum size allocation * @size[out] successful allocation size */ static TEE_Result try_allocate_dmabuf_max_size(struct caamdmaobj *obj, size_t min_size, size_t *size) { TEE_Result ret = TEE_ERROR_GENERIC; size_t alloc_size = 0; struct priv_dmaobj *priv = NULL; bool try_alloc = false; uint32_t exceptions = 0; alloc_size = get_dma_max_alloc_size(obj); if (alloc_size) { try_alloc = true; } else { ret = TEE_SUCCESS; goto out; } priv = obj->priv; exceptions = cpu_spin_lock_xsave(&memlock); while (try_alloc) { ret = try_allocate_dmabuf(priv, alloc_size); if (!ret) { try_alloc = false; } else { if (alloc_size > min_size) alloc_size = MAX(min_size, alloc_size / 2); else try_alloc = false; } } cpu_spin_unlock_xrestore(&memlock, exceptions); out: *size = alloc_size; return ret; } TEE_Result caam_dmaobj_prepare(struct caamdmaobj *input, struct caamdmaobj *output, size_t min_size) { TEE_Result ret = TEE_ERROR_GENERIC; size_t alloc_input = 0; size_t alloc_output = 0; if (!input && !output) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((input && !input->priv) || (output && !output->priv)) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } DMAOBJ_TRACE("input=%p - output=%p - min=%zu", input, output, min_size); ret = try_allocate_dmabuf_max_size(input, min_size, &alloc_input); if (ret) goto out; ret = try_allocate_dmabuf_max_size(output, min_size, &alloc_output); if (ret) goto out; out: DMAOBJ_TRACE("Allocation (input %zu, output %zu) returns 0x%" PRIx32, input ? alloc_input : 0, output ? alloc_output : 0, ret); return ret; } TEE_Result caam_dmaobj_sgtbuf_inout_build(struct caamdmaobj *input, struct caamdmaobj *output, size_t *length, size_t off, size_t align) { TEE_Result ret = TEE_ERROR_GENERIC; size_t len = 0; DMAOBJ_TRACE("input=%p/output=%p %zu bytes (offset=%zu, align=%zu)", input, output, *length, off, align); if (!input || !output || !length || !input->priv || !output->priv || !*length) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * First build the input SGT/Buffer */ ret = caam_dmaobj_sgtbuf_build(input, length, off, align); if (ret) goto out; /* * Next build the output SGT/Buffer. * If returned length is not same as input, redo the input * SGT/Buffer with the same length as the output. */ len = *length; ret = caam_dmaobj_sgtbuf_build(output, &len, off, *length); if (ret) goto out; if (len != *length) { DMAOBJ_TRACE("Retry In %zu bytes vs Out %zu bytes", *length, len); /* Redo the input with the output length */ *length = len; ret = caam_dmaobj_sgtbuf_build(input, length, off, len); if (!ret && *length != len) { DMAOBJ_TRACE("Error In %zu bytes vs Out %zu bytes", *length, len); ret = TEE_ERROR_OUT_OF_MEMORY; } } out: DMAOBJ_TRACE("Input/Output SGTBUF returns 0x%" PRIx32, ret); return ret; } TEE_Result caam_dmaobj_sgtbuf_build(struct caamdmaobj *obj, size_t *length, size_t off, size_t align) { TEE_Result ret = TEE_ERROR_GENERIC; enum caam_status retstatus = CAAM_FAILURE; struct priv_dmaobj *priv = NULL; struct dmaentry *entry = NULL; struct dmaentry *start_entry = NULL; size_t max_length = 0; size_t acc_length = 0; size_t offset = off; unsigned int idx = 0; unsigned int nb_sgt = 0; DMAOBJ_TRACE("obj=%p of %zu bytes (offset=%zu) - align %zu", obj, *length, off, align); if (!obj || !obj->priv || !length || !*length) { ret = TEE_ERROR_BAD_PARAMETERS; goto out; } priv = obj->priv; max_length = *length; if (priv->dmabuf.allocated && max_length > priv->dmabuf.allocated && priv->dmabuf.allocated > align) max_length = ROUNDDOWN(priv->dmabuf.allocated, align); DMAOBJ_TRACE("Prepare SGT/Buffer to do %zu of %zu", max_length, *length); /* Find the first DMA buffer to start with */ TAILQ_FOREACH(entry, &priv->list, link) { if (offset < entry->origbuf.length) break; offset -= entry->origbuf.length; } if (!entry) { DMAOBJ_TRACE("There is no DMA Object available"); ret = TEE_ERROR_GENERIC; goto out; } start_entry = entry; DMAOBJ_TRACE("Start with %p data %p offset %zu", start_entry, start_entry->origbuf.data, offset); acc_length = entry->origbuf.length - offset; nb_sgt = 1; /* Calculate the number of SGT entry */ for (entry = TAILQ_NEXT(entry, link); entry && acc_length < max_length; entry = TAILQ_NEXT(entry, link)) { acc_length += entry->origbuf.length; nb_sgt++; } DMAOBJ_TRACE("%d of %d SGT/Buffer entries to handle", nb_sgt, priv->nb_sgtbuf); if (priv->nb_sgtbuf < nb_sgt) { if (priv->nb_sgtbuf) { obj->sgtbuf.number = priv->nb_sgtbuf; obj->sgtbuf.sgt_type = (priv->nb_sgtbuf > 1); caam_sgtbuf_free(&obj->sgtbuf); caam_free(priv->sgtdata); priv->nb_sgtbuf = 0; } obj->sgtbuf.number = nb_sgt; obj->sgtbuf.sgt_type = (nb_sgt > 1) ? true : false; /* Allocate a new SGT/Buffer object */ retstatus = caam_sgtbuf_alloc(&obj->sgtbuf); DMAOBJ_TRACE("Allocate %d SGT entries ret 0x%" PRIx32, obj->sgtbuf.number, retstatus); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } priv->sgtdata = caam_calloc(nb_sgt * sizeof(*priv->sgtdata)); if (!priv->sgtdata) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } priv->nb_sgtbuf = nb_sgt; } else { obj->sgtbuf.number = nb_sgt; obj->sgtbuf.sgt_type = (nb_sgt > 1) ? true : false; } /* Reset the DMA Buffer index if allocated */ if (priv->dmabuf.allocated) { priv->dmabuf.remind = priv->dmabuf.allocated; priv->dmabuf.buf.length = 0; } obj->sgtbuf.length = 0; for (entry = start_entry; entry && idx < nb_sgt; entry = TAILQ_NEXT(entry, link), idx++) { DMAOBJ_TRACE("entry %p (%d)", entry, idx); if (entry->nodma_access || entry->newbuf) { retstatus = entry_sgtbuf_dmabuf(obj, entry, idx, offset); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } } else { retstatus = entry_sgtbuf(obj, entry, idx, offset); if (retstatus != CAAM_NO_ERROR) { ret = caam_status_to_tee_result(retstatus); goto out; } } if (obj->sgtbuf.length >= max_length) { DMAOBJ_TRACE("Hold-on enough length %zu", max_length); obj->sgtbuf.length = max_length; break; } offset = 0; } if (obj->sgtbuf.sgt_type) { /* Build the SGT table based on the physical area list */ caam_sgt_fill_table(&obj->sgtbuf); obj->sgtbuf.paddr = virt_to_phys(obj->sgtbuf.sgt); } else { obj->sgtbuf.paddr = obj->sgtbuf.buf->paddr; } *length = obj->sgtbuf.length; ret = TEE_SUCCESS; out: DMAOBJ_TRACE("SGTBUF (%zu) returns 0x%" PRIx32, *length, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_mem.c000066400000000000000000000170351464416617300235060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Brief Memory management utilities. * Primitive to allocate, free memory. */ #include #include #include #include #include #include #include #include #define MEM_TYPE_NORMAL 0 /* Normal allocation */ #define MEM_TYPE_ZEROED BIT(0) /* Buffer filled with 0's */ #define MEM_TYPE_ALIGN BIT(1) /* Address and size aligned on a cache line */ /* * Read the first byte at the given @addr to ensure that * virtual page is mapped before getting its physical address. * * @addr: address to read */ static inline void touch_page(vaddr_t addr) { io_read8(addr); } /* * Allocate an area of given size in bytes. Add the memory allocator * information in the newly allocated area. * * @size Size in bytes to allocate * @type Type of area to allocate (refer to MEM_TYPE_*) */ static void *mem_alloc(size_t size, uint8_t type) { void *ptr = NULL; size_t alloc_size = size; MEM_TRACE("alloc %zu bytes of type %" PRIu8, size, type); if (type & MEM_TYPE_ALIGN) { size_t cacheline_size = dcache_get_line_size(); if (ROUNDUP_OVERFLOW(alloc_size, CFG_CAAM_SIZE_ALIGN, &alloc_size)) return NULL; if (ROUNDUP_OVERFLOW(alloc_size, cacheline_size, &alloc_size)) return NULL; ptr = memalign(cacheline_size, alloc_size); } else { ptr = malloc(alloc_size); } if (!ptr) { MEM_TRACE("alloc Error - NULL"); return NULL; } if (type & MEM_TYPE_ZEROED) memset(ptr, 0, alloc_size); MEM_TRACE("alloc returned %p", ptr); return ptr; } /* * Free allocated area * * @ptr area to free */ static void mem_free(void *ptr) { if (ptr) { MEM_TRACE("free %p", ptr); free(ptr); } } /* * Allocate internal driver buffer aligned with a cache line. * * @buf [out] buffer allocated * @size size in bytes of the memory to allocate * @type Type of area to allocate (refer to MEM_TYPE_*) */ static enum caam_status mem_alloc_buf(struct caambuf *buf, size_t size, uint8_t type) { buf->data = mem_alloc(size, type); if (!buf->data) return CAAM_OUT_MEMORY; buf->paddr = virt_to_phys(buf->data); if (!buf->paddr) { caam_free_buf(buf); return CAAM_OUT_MEMORY; } buf->length = size; buf->nocache = 0; return CAAM_NO_ERROR; } void *caam_alloc(size_t size) { return mem_alloc(size, MEM_TYPE_NORMAL); } void *caam_calloc(size_t size) { return mem_alloc(size, MEM_TYPE_ZEROED); } void *caam_calloc_align(size_t size) { return mem_alloc(size, MEM_TYPE_ZEROED | MEM_TYPE_ALIGN); } void caam_free(void *ptr) { mem_free(ptr); } uint32_t *caam_calloc_desc(uint8_t nbentries) { return mem_alloc(DESC_SZBYTES(nbentries), MEM_TYPE_ZEROED | MEM_TYPE_ALIGN); } void caam_free_desc(uint32_t **ptr) { mem_free(*ptr); *ptr = NULL; } enum caam_status caam_alloc_buf(struct caambuf *buf, size_t size) { return mem_alloc_buf(buf, size, MEM_TYPE_NORMAL); } enum caam_status caam_calloc_buf(struct caambuf *buf, size_t size) { return mem_alloc_buf(buf, size, MEM_TYPE_ZEROED); } enum caam_status caam_calloc_align_buf(struct caambuf *buf, size_t size) { return mem_alloc_buf(buf, size, MEM_TYPE_ZEROED | MEM_TYPE_ALIGN); } enum caam_status caam_alloc_align_buf(struct caambuf *buf, size_t size) { return mem_alloc_buf(buf, size, MEM_TYPE_ALIGN); } void caam_free_buf(struct caambuf *buf) { if (buf) { if (buf->data) { caam_free(buf->data); buf->data = NULL; } buf->length = 0; buf->paddr = 0; buf->nocache = 0; } } bool caam_mem_is_cached_buf(void *buf, size_t size) { enum teecore_memtypes mtype = MEM_AREA_MAXTYPE; bool is_cached = false; /* * First check if the buffer is a known memory area mapped * with a type listed in the teecore_memtypes enum. * If not mapped, this is a User Area and so assume * it cacheable */ mtype = core_mmu_get_type_by_pa(virt_to_phys(buf)); if (mtype == MEM_AREA_MAXTYPE) is_cached = true; else is_cached = core_vbuf_is(CORE_MEM_CACHED, buf, size); return is_cached; } enum caam_status caam_cpy_block_src(struct caamblock *block, struct caambuf *src, size_t offset) { enum caam_status ret = CAAM_FAILURE; size_t cpy_size = 0; if (!src->data) return CAAM_FAILURE; /* Check if the temporary buffer is allocated, else allocate it */ if (!block->buf.data) { ret = caam_alloc_align_buf(&block->buf, block->max); if (ret != CAAM_NO_ERROR) { MEM_TRACE("Allocation Block buffer error"); goto end_cpy; } } /* Calculate the number of bytes to copy in the block buffer */ MEM_TRACE("Current buffer is %zu (%zu) bytes", block->filled, block->max); cpy_size = block->max - block->filled; cpy_size = MIN(cpy_size, src->length - offset); memcpy(&block->buf.data[block->filled], &src->data[offset], cpy_size); block->filled += cpy_size; ret = CAAM_NO_ERROR; end_cpy: return ret; } int caam_mem_get_pa_area(struct caambuf *buf, struct caambuf **out_pabufs) { int nb_pa_area = 0; size_t len = 0; size_t len_tohandle = 0; vaddr_t va = 0; vaddr_t next_va = 0; paddr_t pa = 0; paddr_t next_pa = 0; struct caambuf *pabufs = NULL; MEM_TRACE("Get PA Areas of %p-%zu (out %p)", buf->data, buf->length, out_pabufs); if (out_pabufs) { /* * Caller asked for the extracted contiguous * physical areas. * Allocate maximum possible small pages */ if (buf->length > SMALL_PAGE_SIZE) { nb_pa_area = buf->length / SMALL_PAGE_SIZE + 1; if (buf->length % SMALL_PAGE_SIZE) nb_pa_area++; } else { nb_pa_area = 2; } pabufs = caam_calloc(nb_pa_area * sizeof(*pabufs)); if (!pabufs) return -1; MEM_TRACE("Allocate max %d Physical Areas", nb_pa_area); } /* * Go thru all the VA space to extract the contiguous * physical areas */ va = (vaddr_t)buf->data; pa = virt_to_phys((void *)va); if (!pa) goto err; nb_pa_area = 0; if (pabufs) { pabufs[nb_pa_area].data = (uint8_t *)va; pabufs[nb_pa_area].paddr = pa; pabufs[nb_pa_area].length = 0; pabufs[nb_pa_area].nocache = buf->nocache; MEM_TRACE("Add %d PA 0x%" PRIxPA " VA 0x%" PRIxVA, nb_pa_area, pa, va); } for (len = buf->length; len; len -= len_tohandle) { len_tohandle = MIN(SMALL_PAGE_SIZE - (va & SMALL_PAGE_MASK), len); next_va = va + len_tohandle; if (pabufs) pabufs[nb_pa_area].length += len_tohandle; /* * Reaches the end of buffer, exits here because * the next virtual address is out of scope. */ if (len == len_tohandle) break; touch_page(next_va); next_pa = virt_to_phys((void *)next_va); if (!next_pa) goto err; if (next_pa != (pa + len_tohandle)) { nb_pa_area++; if (pabufs) { pabufs[nb_pa_area].data = (uint8_t *)next_va; pabufs[nb_pa_area].paddr = next_pa; pabufs[nb_pa_area].length = 0; pabufs[nb_pa_area].nocache = buf->nocache; } MEM_TRACE("Add %d PA 0x%" PRIxPA " VA 0x%" PRIxVA, nb_pa_area, next_pa, next_va); } va = next_va; pa = next_pa; } if (out_pabufs) *out_pabufs = pabufs; MEM_TRACE("Nb Physical Area %d", nb_pa_area + 1); return nb_pa_area + 1; err: free(pabufs); return -1; } void caam_mem_cpy_ltrim_buf(struct caambuf *dst, struct caambuf *src) { size_t offset = 0; size_t cpy_size = 0; /* Calculate the offset to start the copy */ while (!src->data[offset] && offset < src->length) offset++; if (offset >= src->length) offset = src->length - 1; cpy_size = MIN(dst->length, (src->length - offset)); MEM_TRACE("Copy %zu of src %zu bytes (offset = %zu)", cpy_size, src->length, offset); memcpy(dst->data, &src->data[offset], cpy_size); dst->length = cpy_size; } optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_sgt.c000066400000000000000000000077211464416617300235260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019, 2021 NXP * * Brief Scatter-Gatter Table management utilities. */ #include #include #include #include #include #include #include #include #include #include /* * Perform cache management clean operation on the SGT table entry * * @sgtbuf SGT table to manage */ static void caam_sgt_entries_cache_clean(const struct caamsgtbuf *sgtbuf) { cache_operation(TEE_CACHECLEAN, (void *)sgtbuf->sgt, ROUNDUP(sgtbuf->number, CFG_CAAM_SGT_ALIGN) * sizeof(*sgtbuf->sgt)); } void caam_sgt_cache_op(enum utee_cache_operation op, struct caamsgtbuf *insgt, size_t length) { unsigned int idx = 0; size_t op_size = 0; size_t rem_length = length; caam_sgt_entries_cache_clean(insgt); SGT_TRACE("SGT @%p %d entries", insgt, insgt->number); for (idx = 0; idx < insgt->number && rem_length; idx++) { op_size = MIN(rem_length, insgt->buf[idx].length); if (!insgt->buf[idx].nocache) cache_operation(op, (void *)insgt->buf[idx].data, op_size); rem_length -= op_size; } } void caam_sgt_fill_table(struct caamsgtbuf *sgt) { unsigned int idx = 0; SGT_TRACE("Create %d SGT entries", sgt->number); for (idx = 0; idx < sgt->number - 1; idx++) { CAAM_SGT_ENTRY(&sgt->sgt[idx], sgt->buf[idx].paddr, sgt->buf[idx].length); sgt_entry_trace(idx, sgt); } CAAM_SGT_ENTRY_FINAL(&sgt->sgt[idx], sgt->buf[idx].paddr, sgt->buf[idx].length); sgt_entry_trace(idx, sgt); } enum caam_status caam_sgt_derive(struct caamsgtbuf *sgt, const struct caamsgtbuf *from, size_t offset, size_t length) { enum caam_status retstatus = CAAM_FAILURE; unsigned int idx = 0; unsigned int st_idx = 0; size_t off = offset; size_t rlength = length; SGT_TRACE("Derive from %p - offset %zu, %d SGT entries", from, offset, from->number); if (from->length - offset < length) { SGT_TRACE("From SGT/Buffer too short (%zu)", from->length); return CAAM_SHORT_BUFFER; } for (; idx < from->number && off >= from->buf[idx].length; idx++) off -= from->buf[idx].length; st_idx = idx; sgt->number = 1; rlength -= MIN(rlength, from->buf[idx].length - off); for (idx++; idx < from->number && rlength; idx++) { rlength -= MIN(rlength, from->buf[idx].length); sgt->number++; } sgt->sgt_type = (sgt->number > 1) ? true : false; /* Allocate a new SGT/Buffer object */ retstatus = caam_sgtbuf_alloc(sgt); SGT_TRACE("Allocate %d SGT entries ret 0x%" PRIx32, sgt->number, retstatus); if (retstatus != CAAM_NO_ERROR) return retstatus; memcpy(sgt->buf, &from->buf[st_idx], sgt->number * sizeof(*sgt->buf)); if (sgt->sgt_type) { memcpy(sgt->sgt, &from->sgt[st_idx], sgt->number * sizeof(*sgt->sgt)); /* Set the offset of the first sgt entry */ sgt_entry_offset(sgt->sgt, off); /* * Push the SGT Table into memory now because * derived objects are not pushed. */ caam_sgt_entries_cache_clean(sgt); sgt->paddr = virt_to_phys(sgt->sgt); } else { sgt->paddr = sgt->buf->paddr + off; } sgt->length = length; return CAAM_NO_ERROR; } void caam_sgtbuf_free(struct caamsgtbuf *data) { if (data->sgt_type) caam_free(data->sgt); else caam_free(data->buf); data->sgt = NULL; data->buf = NULL; } enum caam_status caam_sgtbuf_alloc(struct caamsgtbuf *data) { unsigned int nb_sgt = 0; if (!data || !data->number) return CAAM_BAD_PARAM; if (data->sgt_type) { nb_sgt = ROUNDUP(data->number, CFG_CAAM_SGT_ALIGN); data->sgt = caam_calloc(nb_sgt * (sizeof(union caamsgt) + sizeof(struct caambuf))); data->buf = (void *)(((uint8_t *)data->sgt) + (nb_sgt * sizeof(union caamsgt))); } else { data->buf = caam_calloc(data->number * sizeof(struct caambuf)); data->sgt = NULL; } if (!data->buf || (!data->sgt && data->sgt_type)) { caam_sgtbuf_free(data); return CAAM_OUT_MEMORY; } return CAAM_NO_ERROR; } optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_sgt_v1.c000066400000000000000000000034251464416617300241310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Scatter-gather entry management code for version 1 */ #include #include #include #define ENTRY_LEN(len) (((uint32_t)len) & GENMASK_32(29, 0)) #define BS_ENTRY_FINAL BIT32(30) void sgt_entry_trace(unsigned int idx __maybe_unused, const struct caamsgtbuf *sgt __maybe_unused) { SGT_TRACE("SGT[%d] (%p)", idx, &sgt->sgt[idx]); SGT_TRACE("SGT[%d]->data = %p", idx, sgt->buf[idx].data); SGT_TRACE("SGT[%d]->length = %zu", idx, sgt->buf[idx].length); SGT_TRACE("SGT[%d]->paddr = 0x%" PRIxPA, idx, sgt->buf[idx].paddr); SGT_TRACE("SGT[%d]->ptr_ms = %" PRIx32, idx, sgt->sgt[idx].v1.ptr_ms); SGT_TRACE("SGT[%d]->ptr_ls = %" PRIx32, idx, sgt->sgt[idx].v1.ptr_ls); SGT_TRACE("SGT[%d]->len_f_e = %" PRIx32, idx, sgt->sgt[idx].v1.len_f_e); SGT_TRACE("SGT[%d]->offset = %" PRIx32, idx, sgt->sgt[idx].v1.offset); } void sgt_entry_offset(union caamsgt *sgt, unsigned int offset) { uint32_t len_f_e = 0; len_f_e = caam_read_val32(&sgt->v1.len_f_e); /* Set the new length and keep the Final bit if set */ len_f_e = (ENTRY_LEN(len_f_e) - offset) | (len_f_e & BS_ENTRY_FINAL); caam_write_val32(&sgt->v1.len_f_e, len_f_e); caam_write_val32(&sgt->v1.offset, offset); } void caam_sgt_set_entry(union caamsgt *sgt, paddr_t paddr, size_t len, unsigned int offset, bool final_e) { unsigned int len_f_e = 0; caam_write_val32(&sgt->v1.ptr_ls, paddr); #if defined(CFG_CAAM_64BIT) && defined(CFG_ARM64_core) caam_write_val32(&sgt->v1.ptr_ms, paddr >> 32); #else caam_write_val32(&sgt->v1.ptr_ms, 0); #endif len_f_e = ENTRY_LEN(len); if (final_e) len_f_e |= BS_ENTRY_FINAL; caam_write_val32(&sgt->v1.len_f_e, len_f_e); caam_write_val32(&sgt->v1.offset, offset); } optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_sgt_v2.c000066400000000000000000000033301464416617300241250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Scatter-gather entry management code for version 2 */ #include #include #include void sgt_entry_trace(unsigned int idx __maybe_unused, const struct caamsgtbuf *sgt __maybe_unused) { SGT_TRACE("SGT[%d] (%p)", idx, &sgt->sgt[idx]); SGT_TRACE("SGT[%d]->data = %p", idx, sgt->buf[idx].data); SGT_TRACE("SGT[%d]->length = %zu", idx, sgt->buf[idx].length); SGT_TRACE("SGT[%d]->paddr = 0x%" PRIxPA, idx, sgt->buf[idx].paddr); SGT_TRACE("SGT[%d]->w1 = %" PRIx64, idx, sgt->sgt[idx].v2.w1); SGT_TRACE("SGT[%d]->w2 = %" PRIx64, idx, sgt->sgt[idx].v2.w2); } void sgt_entry_offset(union caamsgt *sgt, unsigned int offset) { uint64_t w2 = 0; uint64_t len = 0; uint64_t off = 0; w2 = caam_read_val64(&sgt->v2.w2); /* * Compute the new offset reading the one present and adding the * input */ off = SGT_V2_ENTRY_OFFSET(w2); off += offset; /* Reading length and computing new value by subtracting the offset */ len = SGT_V2_ENTRY_AVAIL_LENGTH(w2); len = (offset > len) ? 0 : len - offset; /* Clear the offset and length fields */ w2 &= ~(BM_SGT_V2_OFFSET | BM_SGT_V2_AVAIL_LENGTH); /* Update offset and field */ w2 |= BV_SGT_V2_OFFSET(offset) | BV_SGT_V2_AVAIL_LENGTH(len); caam_write_val64(&sgt->v2.w2, w2); } void caam_sgt_set_entry(union caamsgt *sgt, paddr_t paddr, size_t len, unsigned int offset, bool final_e) { uint64_t w2 = 0; /* Write the address to set */ caam_write_val64(&sgt->v2.w1, paddr); /* Compute the second word */ w2 = (final_e ? BM_SGT_V2_F : 0) | BV_SGT_V2_OFFSET(offset) | BM_SGT_V2_IVP | BV_SGT_V2_AVAIL_LENGTH(len); caam_write_val64(&sgt->v2.w2, w2); } optee_os-4.3.0/core/drivers/crypto/caam/utils/utils_status.c000066400000000000000000000021671464416617300242530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019, 2021 NXP * * Brief Status management utilities. */ #include #include #include TEE_Result job_status_to_tee_result(uint32_t status) { /* * Add all status code that can be translated * to a TEE_Result other than TEE_ERROR_GENERIC */ switch (JRSTA_SRC_GET(status)) { case JRSTA_SRC(NONE): return TEE_SUCCESS; case JRSTA_SRC(DECO): if (JRSTA_CCB_GET_ERR(status) == JRSTA_DECO_ERRID_FORMAT) return TEE_ERROR_BAD_PARAMETERS; if (JRSTA_CCB_GET_ERR(status) == JRSTA_DECO_INV_SIGNATURE) return TEE_ERROR_SIGNATURE_INVALID; break; default: break; } return TEE_ERROR_GENERIC; } TEE_Result caam_status_to_tee_result(enum caam_status status) { switch (status) { case CAAM_NO_ERROR: return TEE_SUCCESS; case CAAM_OUT_MEMORY: return TEE_ERROR_OUT_OF_MEMORY; case CAAM_BAD_PARAM: return TEE_ERROR_BAD_PARAMETERS; case CAAM_SHORT_BUFFER: return TEE_ERROR_SHORT_BUFFER; case CAAM_NOT_SUPPORTED: return TEE_ERROR_NOT_SUPPORTED; default: break; } return TEE_ERROR_GENERIC; } optee_os-4.3.0/core/drivers/crypto/crypto_api/000077500000000000000000000000001464416617300214465ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/000077500000000000000000000000001464416617300230615ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/dh.c000066400000000000000000000046211464416617300236230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Crypto DH interface implementation to enable HW driver. */ #include #include #include #include TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *key, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_dh *dh = NULL; if (!key || !size_bits) { CRYPTO_TRACE("Param error key @%#" PRIxPTR " size %zu bits", (uintptr_t)key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } dh = drvcrypt_get_ops(CRYPTO_DH); if (dh) ret = dh->alloc_keypair(key, size_bits); CRYPTO_TRACE("DH Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, size_t xbits, size_t key_size) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_dh *dh = NULL; if (!key) { CRYPTO_TRACE("Parameters error key is NULL"); return TEE_ERROR_BAD_PARAMETERS; } if (key_size != 8 * crypto_bignum_num_bytes(key->p)) return TEE_ERROR_BAD_PARAMETERS; dh = drvcrypt_get_ops(CRYPTO_DH); if (dh) ret = dh->gen_keypair(key, q, xbits); CRYPTO_TRACE("DH Keypair (%zu bits) generate ret = 0x%" PRIx32, key_size, ret); return ret; } TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, struct bignum *public_key, struct bignum *secret) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_dh *dh = NULL; struct drvcrypt_secret_data sdata = { }; uint8_t *secret_buf = NULL; if (!private_key || !public_key || !secret) { CRYPTO_TRACE("Input parameters reference error"); return TEE_ERROR_BAD_PARAMETERS; } dh = drvcrypt_get_ops(CRYPTO_DH); if (dh) { /* Allocate the binary Secret buffer */ sdata.secret.length = crypto_bignum_num_bytes(private_key->p); secret_buf = malloc(sdata.secret.length); if (!secret_buf) return TEE_ERROR_OUT_OF_MEMORY; /* Prepare the Secret structure data */ sdata.key_priv = private_key; sdata.key_pub = public_key; sdata.secret.data = secret_buf; ret = dh->shared_secret(&sdata); if (ret == TEE_SUCCESS) ret = crypto_bignum_bin2bn(secret_buf, sdata.secret.length, secret); free(secret_buf); } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Shared Secret returned 0x%" PRIx32, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/dsa.c000066400000000000000000000135351464416617300240030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Crypto DSA interface implementation to enable HW driver. */ #include #include #include /* * Get the recommended L and N bits parameters corresponding * respectively to the size of the Primes P and G (and so * the Public Key and Private Key). * * Refer the NIST.FIPS 186-4 section 4.2 * * @size_bits Maximum key size bits * @l_bits [out] L size in bits * @n_bits [out] N size in bits */ static TEE_Result get_keys_size(size_t size_bits, size_t *l_bits, size_t *n_bits) { if (size_bits <= 1024) *n_bits = 160; else if (size_bits <= 3072) *n_bits = 256; else return TEE_ERROR_NOT_IMPLEMENTED; *l_bits = size_bits; return TEE_SUCCESS; } TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *key, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_dsa *dsa = NULL; size_t l_bits = 0; size_t n_bits = 0; if (!key || !size_bits) { CRYPTO_TRACE("Param error key @0x%" PRIxPTR " size %zu bits", (uintptr_t)key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } ret = get_keys_size(size_bits, &l_bits, &n_bits); if (ret == TEE_SUCCESS) { dsa = drvcrypt_get_ops(CRYPTO_DSA); if (dsa) ret = dsa->alloc_keypair(key, l_bits, n_bits); else ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("DSA Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *key, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_dsa *dsa = NULL; size_t l_bits = 0; size_t n_bits = 0; if (!key || !size_bits) { CRYPTO_TRACE("Param error key @0x%" PRIxPTR " size %zu bits", (uintptr_t)key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } ret = get_keys_size(size_bits, &l_bits, &n_bits); if (ret == TEE_SUCCESS) { dsa = drvcrypt_get_ops(CRYPTO_DSA); if (dsa) ret = dsa->alloc_publickey(key, l_bits, n_bits); else ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("DSA Public Key (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_dsa *dsa = NULL; size_t l_bits = 0; size_t n_bits = 0; if (!key || !key_size) { CRYPTO_TRACE("Param error key @0x%" PRIxPTR " size %zu bits", (uintptr_t)key, key_size); return TEE_ERROR_BAD_PARAMETERS; } ret = get_keys_size(key_size, &l_bits, &n_bits); if (ret == TEE_SUCCESS) { dsa = drvcrypt_get_ops(CRYPTO_DSA); if (dsa) ret = dsa->gen_keypair(key, l_bits, n_bits); else ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("DSA Keypair (%zu bits) generate ret = 0x%" PRIx32, key_size, ret); return ret; } TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_dsa *dsa = NULL; struct drvcrypt_sign_data sdata = { }; size_t l_bytes = 0; size_t n_bytes = 0; if (!key || !msg || !sig_len) { CRYPTO_TRACE("Input parameters reference error"); return TEE_ERROR_BAD_PARAMETERS; } /* * Verify the signature length function of the key size * * Prime number sizes are not stored but deducted from bignum size. * This requires prime numbers p and q to have their MSB set otherwise * crypto_bignum_num_bytes() will return a wrong size. */ n_bytes = crypto_bignum_num_bytes(key->q); l_bytes = crypto_bignum_num_bytes(key->p); if (*sig_len < 2 * n_bytes) { CRYPTO_TRACE("Length (%zu) too short expected %zu bytes", *sig_len, 2 * n_bytes); *sig_len = 2 * n_bytes; return TEE_ERROR_SHORT_BUFFER; } if (!sig) { CRYPTO_TRACE("Parameter \"sig\" reference error"); return TEE_ERROR_BAD_PARAMETERS; } dsa = drvcrypt_get_ops(CRYPTO_DSA); if (dsa) { sdata.algo = algo; sdata.key = key; sdata.size_sec = n_bytes; sdata.message.data = (uint8_t *)msg; sdata.message.length = msg_len; sdata.signature.data = sig; sdata.signature.length = *sig_len; ret = dsa->sign(&sdata, l_bytes, n_bytes); /* Set the signature length */ *sig_len = sdata.signature.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Sign algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, ret); return ret; } TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_dsa *dsa = NULL; struct drvcrypt_sign_data sdata = { }; size_t l_bytes = 0; size_t n_bytes = 0; if (!key || !msg || !sig) { CRYPTO_TRACE("Input parameters reference error"); return TEE_ERROR_BAD_PARAMETERS; } /* * Verify the signature length function of the key size * * Prime number sizes are not stored but deducted from bignum size. * This requires prime numbers p and q to have their MSB set otherwise * crypto_bignum_num_bytes() will return a wrong size. */ n_bytes = crypto_bignum_num_bytes(key->q); l_bytes = crypto_bignum_num_bytes(key->p); if (sig_len != 2 * n_bytes) { CRYPTO_TRACE("Length (%zu) is invalid expected %zu bytes", sig_len, 2 * n_bytes); return TEE_ERROR_SIGNATURE_INVALID; } dsa = drvcrypt_get_ops(CRYPTO_DSA); if (dsa) { sdata.algo = algo; sdata.key = key; sdata.size_sec = n_bytes; sdata.message.data = (uint8_t *)msg; sdata.message.length = msg_len; sdata.signature.data = (uint8_t *)sig; sdata.signature.length = sig_len; ret = dsa->verify(&sdata, l_bytes, n_bytes); } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Verify algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/ecc.c000066400000000000000000000332241464416617300237630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2021 NXP * * Crypto ECC interface implementation to enable HW driver. */ #include #include #include #include /* * Returns the key size in bytes for the given ECC curve * * @curve ECC Curve ID */ static size_t get_ecc_key_size_bytes(uint32_t curve) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: return 24; case TEE_ECC_CURVE_NIST_P224: return 28; case TEE_ECC_CURVE_NIST_P256: case TEE_ECC_CURVE_SM2: return 32; case TEE_ECC_CURVE_NIST_P384: return 48; case TEE_ECC_CURVE_NIST_P521: return 66; default: return 0; } } /* * Returns the key size in bits for the given ECC curve * * @curve ECC Curve ID */ static size_t get_ecc_key_size_bits(uint32_t curve) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: case TEE_ECC_CURVE_NIST_P224: case TEE_ECC_CURVE_NIST_P256: case TEE_ECC_CURVE_NIST_P384: case TEE_ECC_CURVE_SM2: return get_ecc_key_size_bytes(curve) * 8; case TEE_ECC_CURVE_NIST_P521: return 521; default: return 0; } } /* * Verify if the cryptographic algorithm @algo is valid for * the ECC curve * * @curve ECC curve * @algo Cryptographic algorithm */ static bool algo_is_valid(uint32_t curve, uint32_t algo) { unsigned int algo_op = TEE_ALG_GET_CLASS(algo); unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo); unsigned int algo_curve = TEE_ALG_GET_DIGEST_HASH(algo); /* Check first the algo operation and id */ if ((algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE && algo_id == TEE_MAIN_ALGO_ECDSA) || (algo_op == TEE_OPERATION_KEY_DERIVATION && algo_id == TEE_MAIN_ALGO_ECDH)) { if (curve == algo_curve) { CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32 " is valid", algo, curve); return true; } } if (algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE && algo_id == TEE_MAIN_ALGO_SM2_DSA_SM3) { if (curve == TEE_ECC_CURVE_SM2) return true; } CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32 " is not valid", algo, curve); return false; } /* * Free an ECC public key * * @key Public Key */ static void ecc_free_public_key(struct ecc_public_key *key) { struct drvcrypt_ecc *ecc = NULL; if (key) { ecc = drvcrypt_get_ops(CRYPTO_ECC); if (ecc) { CRYPTO_TRACE("ECC Public Key free"); ecc->free_publickey(key); } } } /* * Generates an ECC keypair * * @key Keypair * @size_bits Key size in bits */ static TEE_Result ecc_generate_keypair(struct ecc_keypair *key, size_t size_bits __maybe_unused) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_ecc *ecc = NULL; size_t key_size_bits = 0; /* Check input parameters */ if (!key) { CRYPTO_TRACE("Parameters error key is NULL"); return TEE_ERROR_BAD_PARAMETERS; } key_size_bits = get_ecc_key_size_bits(key->curve); ecc = drvcrypt_get_ops(CRYPTO_ECC); if (ecc) ret = ecc->gen_keypair(key, key_size_bits); CRYPTO_TRACE("ECC Keypair (%zu bits) generate ret = 0x%" PRIx32, key_size_bits, ret); return ret; } /* * Sign the message with the ECC Key given by the Keypair * * @algo ECC algorithm * @key ECC Keypair * @msg Message to sign * @msg_len Length of the message (bytes) * @sig Signature * @sig_len [in/out] Length of the signature (bytes) */ static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_ecc *ecc = NULL; struct drvcrypt_sign_data sdata = { }; size_t size_bytes = 0; /* Verify first the input parameters */ if (!key || !msg || !sig_len) { CRYPTO_TRACE("Input parameters reference error"); return ret; } if (!algo_is_valid(key->curve, algo)) return ret; size_bytes = get_ecc_key_size_bytes(key->curve); if (!size_bytes) return TEE_ERROR_BAD_PARAMETERS; /* Verify the signature length function of the key size */ if (*sig_len < 2 * size_bytes) { CRYPTO_TRACE("Length (%zu) too short expected %zu bytes", *sig_len, 2 * size_bytes); *sig_len = 2 * size_bytes; return TEE_ERROR_SHORT_BUFFER; } if (!sig) { CRYPTO_TRACE("Parameter \"sig\" reference error"); return TEE_ERROR_BAD_PARAMETERS; } ecc = drvcrypt_get_ops(CRYPTO_ECC); if (ecc) { /* * Prepare the Signature structure data */ sdata.algo = algo; sdata.key = key; sdata.size_sec = size_bytes; sdata.message.data = (uint8_t *)msg; sdata.message.length = msg_len; sdata.signature.data = (uint8_t *)sig; sdata.signature.length = *sig_len; ret = ecc->sign(&sdata); /* Set the signature length */ *sig_len = sdata.signature.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Sign algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, ret); return ret; } /* * Verify if signature is signed with the given public key. * * @algo ECC algorithm * @key ECC Public key * @msg Message to sign * @msg_len Length of the message (bytes) * @sig Signature * @sig_len Length of the signature (bytes) */ static TEE_Result ecc_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_ecc *ecc = NULL; struct drvcrypt_sign_data sdata = { }; size_t size_bytes = 0; /* Verify first the input parameters */ if (!key || !msg || !sig) { CRYPTO_TRACE("Input parameters reference error"); return ret; } if (!algo_is_valid(key->curve, algo)) return ret; size_bytes = get_ecc_key_size_bytes(key->curve); if (!size_bytes) return TEE_ERROR_BAD_PARAMETERS; /* Verify the signature length against key size */ if (sig_len != 2 * size_bytes) { CRYPTO_TRACE("Length (%zu) is invalid expected %zu bytes", sig_len, 2 * size_bytes); return TEE_ERROR_SIGNATURE_INVALID; } ecc = drvcrypt_get_ops(CRYPTO_ECC); if (ecc) { sdata.algo = algo; sdata.key = key; sdata.size_sec = size_bytes; sdata.message.data = (uint8_t *)msg; sdata.message.length = msg_len; sdata.signature.data = (uint8_t *)sig; sdata.signature.length = sig_len; ret = ecc->verify(&sdata); } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Verify algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, ret); return ret; } /* * Compute the shared secret data from ECC Private key and Public Key * * @private_key ECC Private key * @public_key ECC Public key * @secret Secret * @secret_len Length of the secret (bytes) */ static TEE_Result ecc_shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_ecc *ecc = NULL; struct drvcrypt_secret_data sdata = { }; size_t size_bytes = 0; /* Verify first the input parameters */ if (!private_key || !public_key || !secret_len) { CRYPTO_TRACE("Input parameters reference error"); return ret; } if (private_key->curve != public_key->curve) { CRYPTO_TRACE("Private Key curve (%d) != Public Key curve (%d)", private_key->curve, public_key->curve); return ret; } size_bytes = get_ecc_key_size_bytes(public_key->curve); if (!size_bytes) return ret; if (*secret_len < size_bytes) { *secret_len = size_bytes; return TEE_ERROR_SHORT_BUFFER; } if (!secret) { CRYPTO_TRACE("Parameter \"secret\" reference error"); return ret; } ecc = drvcrypt_get_ops(CRYPTO_ECC); if (ecc) { /* * Prepare the Secret structure data */ sdata.key_priv = private_key; sdata.key_pub = public_key; sdata.size_sec = size_bytes; sdata.secret.data = secret; sdata.secret.length = *secret_len; ret = ecc->shared_secret(&sdata); /* Set the secret length */ *secret_len = sdata.secret.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Shared Secret returned 0x%" PRIx32, ret); return ret; } static TEE_Result ecc_sm2_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_ecc_ed cdata = { }; struct drvcrypt_ecc *ecc = NULL; size_t ciphertext_len = 0; size_t size_bytes = 0; ecc = drvcrypt_get_ops(CRYPTO_ECC); size_bytes = get_ecc_key_size_bytes(key->curve); if (!size_bytes) { CRYPTO_TRACE("Curve 0x%08"PRIx32" not supported", key->curve); return TEE_ERROR_BAD_PARAMETERS; } /* Uncompressed form indicator */ dst[0] = 0x04; ciphertext_len = 2 * size_bytes + src_len + TEE_SM3_HASH_SIZE; cdata.key = key; cdata.size_sec = size_bytes; cdata.plaintext.data = (uint8_t *)src; cdata.plaintext.length = src_len; cdata.ciphertext.data = dst + 1; cdata.ciphertext.length = ciphertext_len; ret = ecc->encrypt(&cdata); if (!ret || ret == TEE_ERROR_SHORT_BUFFER) *dst_len = cdata.ciphertext.length + 1; return ret; } static TEE_Result ecc_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { struct drvcrypt_ecc *ecc = NULL; if (!key || !src || !dst) { CRYPTO_TRACE("Input parameters reference error"); return TEE_ERROR_BAD_PARAMETERS; } ecc = drvcrypt_get_ops(CRYPTO_ECC); if (!ecc || !ecc->encrypt) return TEE_ERROR_NOT_IMPLEMENTED; switch (key->curve) { case TEE_ECC_CURVE_SM2: return ecc_sm2_encrypt(key, src, src_len, dst, dst_len); default: return TEE_ERROR_NOT_IMPLEMENTED; } } static TEE_Result ecc_sm2_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_ecc_ed cdata = { }; struct drvcrypt_ecc *ecc = NULL; uint8_t *ciphertext = NULL; size_t ciphertext_len = 0; size_t size_bytes = 0; size_t plaintext_len = 0; /* Point Compression */ uint8_t pc = 0; ecc = drvcrypt_get_ops(CRYPTO_ECC); size_bytes = get_ecc_key_size_bytes(key->curve); if (!size_bytes) { CRYPTO_TRACE("Curve 0x%08"PRIx32" not supported", key->curve); return TEE_ERROR_BAD_PARAMETERS; } pc = src[0]; switch (pc) { case 0x02: case 0x03: /* Compressed form */ return TEE_ERROR_NOT_SUPPORTED; case 0x04: /* Uncompressed form */ ciphertext = (uint8_t *)src + 1; ciphertext_len = src_len - 1; break; case 0x06: case 0x07: /* Hybrid form */ return TEE_ERROR_NOT_SUPPORTED; default: return TEE_ERROR_BAD_PARAMETERS; } if (SUB_OVERFLOW(ciphertext_len, 2 * size_bytes + TEE_SM3_HASH_SIZE, &plaintext_len)) return TEE_ERROR_BAD_PARAMETERS; cdata.key = key; cdata.size_sec = size_bytes; cdata.ciphertext.data = ciphertext; cdata.ciphertext.length = ciphertext_len; cdata.plaintext.data = dst; cdata.plaintext.length = plaintext_len; ret = ecc->decrypt(&cdata); /* Set the plaintext length */ if (!ret || ret == TEE_ERROR_SHORT_BUFFER) *dst_len = cdata.plaintext.length; return ret; } static TEE_Result ecc_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { struct drvcrypt_ecc *ecc = NULL; if (!key || !src || !dst) { CRYPTO_TRACE("Input parameters reference error"); return TEE_ERROR_BAD_PARAMETERS; } ecc = drvcrypt_get_ops(CRYPTO_ECC); if (!ecc || !ecc->decrypt) return TEE_ERROR_NOT_IMPLEMENTED; switch (key->curve) { case TEE_ECC_CURVE_SM2: return ecc_sm2_decrypt(key, src, src_len, dst, dst_len); default: return TEE_ERROR_NOT_IMPLEMENTED; } } static const struct crypto_ecc_keypair_ops ecc_keypair_ops = { .generate = ecc_generate_keypair, .sign = ecc_sign, .shared_secret = ecc_shared_secret, .decrypt = ecc_decrypt, }; TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key, uint32_t type, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_ecc *ecc = NULL; if (!key || !size_bits) { CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } switch (type) { case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: case TEE_TYPE_SM2_PKE_KEYPAIR: case TEE_TYPE_SM2_DSA_KEYPAIR: ecc = drvcrypt_get_ops(CRYPTO_ECC); break; default: break; } if (ecc) ret = ecc->alloc_keypair(key, type, size_bits); if (!ret) { key->ops = &ecc_keypair_ops; /* ecc->alloc_keypair() can not get type to set curve */ switch (type) { case TEE_TYPE_SM2_PKE_KEYPAIR: case TEE_TYPE_SM2_DSA_KEYPAIR: key->curve = TEE_ECC_CURVE_SM2; break; default: break; } } CRYPTO_TRACE("ECC Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } static const struct crypto_ecc_public_ops ecc_public_key_ops = { .free = ecc_free_public_key, .verify = ecc_verify, .encrypt = ecc_encrypt, }; TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key, uint32_t type, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_ecc *ecc = NULL; if (!key || !size_bits) { CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } switch (type) { case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDH_PUBLIC_KEY: case TEE_TYPE_SM2_PKE_PUBLIC_KEY: case TEE_TYPE_SM2_DSA_PUBLIC_KEY: ecc = drvcrypt_get_ops(CRYPTO_ECC); break; default: break; } if (ecc) ret = ecc->alloc_publickey(key, type, size_bits); if (!ret) { key->ops = &ecc_public_key_ops; /* ecc->alloc_publickey() can not get type to set curve */ switch (type) { case TEE_TYPE_SM2_PKE_PUBLIC_KEY: case TEE_TYPE_SM2_DSA_PUBLIC_KEY: key->curve = TEE_ECC_CURVE_SM2; break; default: break; } } CRYPTO_TRACE("ECC Public Key (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/local.h000066400000000000000000000014601464416617300243250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Definition of the functions shared locally. */ #ifndef __LOCAL_H__ #define __LOCAL_H__ #include /* * Mask Generation function. Use a Hash operation * to generate an output @mask from an input @seed * * @mgf_data [in/out] MGF data */ TEE_Result drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf *mgf_data); /* * PKCS#1 - Signature of RSA message and encodes the signature. * * @ssa_data [in/out] RSA data to sign / Signature */ TEE_Result drvcrypt_rsassa_sign(struct drvcrypt_rsa_ssa *ssa_data); /* * PKCS#1 - Verification the encoded signature of RSA message. * * @ssa_data RSA Encoded signature data */ TEE_Result drvcrypt_rsassa_verify(struct drvcrypt_rsa_ssa *ssa_data); #endif /* __LOCAL_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/rsa.c000066400000000000000000000327401464416617300240200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * Crypto RSA interface implementation to enable HW driver. */ #include #include #include #include #include #include #include #include "local.h" TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *key, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; if (!key || !size_bits) { CRYPTO_TRACE("Parameters error (key @%p) (size %zu bits)", key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) ret = rsa->alloc_keypair(key, size_bits); CRYPTO_TRACE("RSA Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *key, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; if (!key || !size_bits) { CRYPTO_TRACE("Parameters error (key @%p) (size %zu bits)", key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) ret = rsa->alloc_publickey(key, size_bits); CRYPTO_TRACE("RSA Public Key (%zu bits) alloc ret = 0x%" PRIx32, size_bits, ret); return ret; } void crypto_acipher_free_rsa_public_key(struct rsa_public_key *key) { struct drvcrypt_rsa *rsa = NULL; if (key) { rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { CRYPTO_TRACE("RSA Public Key free"); rsa->free_publickey(key); } } } void crypto_acipher_free_rsa_keypair(struct rsa_keypair *key) { struct drvcrypt_rsa *rsa = NULL; if (key) { rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { CRYPTO_TRACE("RSA Keypair free"); rsa->free_keypair(key); } } } TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t size_bits) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; if (!key || !size_bits) { CRYPTO_TRACE("Parameters error (key @%p) (size %zu bits) ", key, size_bits); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) ret = rsa->gen_keypair(key, size_bits); CRYPTO_TRACE("RSA Keypair (%zu bits) generate ret = 0x%" PRIx32, size_bits, ret); return ret; } TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *cipher, size_t cipher_len, uint8_t *msg, size_t *msg_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; struct drvcrypt_rsa_ed rsa_data = { }; if (!key || !msg || !cipher || !msg_len) { CRYPTO_TRACE("Parameters error (key @%p)\n" "(msg @%p size %zu bytes)\n" "(cipher @0%p size %zu bytes)", key, msg, msg_len ? *msg_len : 0, cipher, cipher_len); return TEE_ERROR_BAD_PARAMETERS; } rsa_data.key.key = key; rsa_data.key.isprivate = true; rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { rsa_data.rsa_id = DRVCRYPT_RSA_NOPAD; rsa_data.message.data = msg; rsa_data.message.length = *msg_len; rsa_data.cipher.data = (uint8_t *)cipher; rsa_data.cipher.length = cipher_len; ret = rsa->decrypt(&rsa_data); *msg_len = rsa_data.message.length; } CRYPTO_TRACE("RSA Decrypt NO PAD ret = 0x%" PRIx32, ret); return ret; } TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *msg, size_t msg_len, uint8_t *cipher, size_t *cipher_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; struct drvcrypt_rsa_ed rsa_data = { }; if (!key || !msg || !cipher_len) { CRYPTO_TRACE("Parameters error (key @%p)\n" "(msg @%p size %zu bytes)\n" "(cipher @%p size %zu bytes)", key, msg, msg_len, cipher, cipher_len ? *cipher_len : 0); return TEE_ERROR_BAD_PARAMETERS; } rsa_data.key.key = key; rsa_data.key.isprivate = false; rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); if (rsa_data.key.n_size > *cipher_len) { CRYPTO_TRACE("Cipher length (%zu) too short expected %zu bytes", *cipher_len, rsa_data.key.n_size); *cipher_len = rsa_data.key.n_size; return TEE_ERROR_SHORT_BUFFER; } if (!cipher) { CRYPTO_TRACE("Parameter \"cipher\" reference error"); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSA_NOPAD; rsa_data.message.data = (uint8_t *)msg; rsa_data.message.length = msg_len; rsa_data.cipher.data = cipher; rsa_data.cipher.length = *cipher_len; ret = rsa->encrypt(&rsa_data); /* Set the cipher size */ *cipher_len = rsa_data.cipher.length; } CRYPTO_TRACE("RSA Encrypt NO PAD ret = 0x%" PRIx32, ret); return ret; } TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *cipher, size_t cipher_len, uint8_t *msg, size_t *msg_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; struct drvcrypt_rsa_ed rsa_data = { }; if (!key || !msg || !cipher || !msg_len || (!label && label_len)) { CRYPTO_TRACE("Parameters error (key @%p)\n" "(msg @%p size %zu bytes)\n" "(cipher @%p size %zu bytes)\n" "(label @%p size %zu bytes)", key, msg, msg_len ? *msg_len : 0, cipher, cipher_len, label, label_len); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { rsa_data.rsa_id = DRVCRYPT_RSA_PKCS_V1_5; } else { rsa_data.rsa_id = DRVCRYPT_RSA_OAEP; rsa_data.hash_algo = TEE_INTERNAL_HASH_TO_ALGO(algo); ret = tee_alg_get_digest_size(rsa_data.hash_algo, &rsa_data.digest_size); if (ret != TEE_SUCCESS) return ret; rsa_data.mgf_algo = mgf_algo; ret = tee_alg_get_digest_size(rsa_data.mgf_algo, &rsa_data.mgf_size); if (ret != TEE_SUCCESS) return ret; rsa_data.mgf = &drvcrypt_rsa_mgf1; } rsa_data.key.key = key; rsa_data.key.isprivate = true; rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); rsa_data.message.data = msg; rsa_data.message.length = *msg_len; rsa_data.cipher.data = (uint8_t *)cipher; rsa_data.cipher.length = cipher_len; rsa_data.label.data = ((label_len > 0) ? (uint8_t *)label : NULL); rsa_data.label.length = label_len; rsa_data.algo = algo; ret = rsa->decrypt(&rsa_data); /* Set the message size */ *msg_len = rsa_data.message.length; } CRYPTO_TRACE("RSAES Decrypt ret = 0x%" PRIx32, ret); return ret; } TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *msg, size_t msg_len, uint8_t *cipher, size_t *cipher_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct drvcrypt_rsa *rsa = NULL; struct drvcrypt_rsa_ed rsa_data = { }; if (!key || !msg || !cipher_len || (!label && label_len)) { CRYPTO_TRACE("Parameters error (key @%p\n" "(msg @%p size %zu bytes)\n" "(cipher @%p size %zu bytes)\n" "(label @%p size %zu bytes)", key, msg, msg_len, cipher, cipher_len ? *cipher_len : 0, label, label_len); return TEE_ERROR_BAD_PARAMETERS; } rsa_data.key.key = key; rsa_data.key.isprivate = false; rsa_data.key.n_size = crypto_bignum_num_bytes(key->n); if (rsa_data.key.n_size > *cipher_len) { CRYPTO_TRACE("Cipher length (%zu) too short expected %zu bytes", *cipher_len, rsa_data.key.n_size); *cipher_len = rsa_data.key.n_size; return TEE_ERROR_SHORT_BUFFER; } if (!cipher) { CRYPTO_TRACE("Parameter \"cipher\" reference error"); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { rsa_data.rsa_id = DRVCRYPT_RSA_PKCS_V1_5; /* Message length <= (modulus_size - 11) */ if (msg_len > rsa_data.key.n_size - 11) return TEE_ERROR_BAD_PARAMETERS; } else { rsa_data.rsa_id = DRVCRYPT_RSA_OAEP; rsa_data.hash_algo = TEE_INTERNAL_HASH_TO_ALGO(algo); /* Message length <= (modulus_size - 2 * hLength - 2) */ ret = tee_alg_get_digest_size(rsa_data.hash_algo, &rsa_data.digest_size); if (ret != TEE_SUCCESS) return ret; if (2 * rsa_data.digest_size >= rsa_data.key.n_size - 2) return TEE_ERROR_BAD_PARAMETERS; if (msg_len > rsa_data.key.n_size - 2 * rsa_data.digest_size - 2) return TEE_ERROR_BAD_PARAMETERS; rsa_data.mgf_algo = mgf_algo; ret = tee_alg_get_digest_size(rsa_data.mgf_algo, &rsa_data.mgf_size); if (ret != TEE_SUCCESS) return ret; rsa_data.mgf = &drvcrypt_rsa_mgf1; } rsa_data.message.data = (uint8_t *)msg; rsa_data.message.length = msg_len; rsa_data.cipher.data = cipher; rsa_data.cipher.length = rsa_data.key.n_size; rsa_data.label.data = (label_len > 0) ? (uint8_t *)label : NULL; rsa_data.label.length = label_len; rsa_data.algo = algo; ret = rsa->encrypt(&rsa_data); /* Set the cipher size */ *cipher_len = rsa_data.cipher.length; } CRYPTO_TRACE("RSAES Encrypt ret = 0x%" PRIx32, ret); return ret; } TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_rsa *rsa = NULL; struct drvcrypt_rsa_ssa rsa_ssa = { }; if (!key || !msg || !sig_len) { CRYPTO_TRACE("Input parameters reference error"); return ret; } if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { /* Prepare the Digest */ rsa_ssa.hash_algo = TEE_DIGEST_HASH_TO_ALGO(algo); /* Check if the message length is digest hash size */ ret = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &rsa_ssa.digest_size); if (ret != TEE_SUCCESS) return ret; if (msg_len != rsa_ssa.digest_size) { CRYPTO_TRACE("Msg length (%zu expected %zu)", msg_len, rsa_ssa.digest_size); return TEE_ERROR_BAD_PARAMETERS; } } else { rsa_ssa.hash_algo = 0; rsa_ssa.digest_size = 0; } /* Prepare the Key */ rsa_ssa.key.key = key; rsa_ssa.key.isprivate = true; rsa_ssa.key.n_size = crypto_bignum_num_bytes(key->n); if (rsa_ssa.key.n_size > *sig_len) { CRYPTO_TRACE("Sign length (%zu) too short must be %zu bytes", *sig_len, rsa_ssa.key.n_size); *sig_len = rsa_ssa.key.n_size; return TEE_ERROR_SHORT_BUFFER; } if (!sig) { CRYPTO_TRACE("Parameter \"sig\" reference error"); return TEE_ERROR_BAD_PARAMETERS; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the Encoded Signature structure data */ rsa_ssa.algo = algo; rsa_ssa.message.data = (uint8_t *)msg; rsa_ssa.message.length = msg_len; rsa_ssa.signature.data = (uint8_t *)sig; rsa_ssa.signature.length = rsa_ssa.key.n_size; rsa_ssa.salt_len = salt_len; rsa_ssa.mgf = &drvcrypt_rsa_mgf1; ret = TEE_ERROR_NOT_IMPLEMENTED; if (rsa->optional.ssa_sign) ret = rsa->optional.ssa_sign(&rsa_ssa); if (ret == TEE_ERROR_NOT_IMPLEMENTED) ret = drvcrypt_rsassa_sign(&rsa_ssa); /* Set the signature length */ *sig_len = rsa_ssa.signature.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Encode signature algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, ret); return ret; } TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_rsa *rsa = NULL; struct drvcrypt_rsa_ssa rsa_ssa = { }; if (!key || !msg || !sig) { CRYPTO_TRACE("Input parameters reference error"); goto out; } if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { /* Prepare the Digest */ rsa_ssa.hash_algo = TEE_DIGEST_HASH_TO_ALGO(algo); /* Check if the message length is digest hash size */ ret = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &rsa_ssa.digest_size); if (ret != TEE_SUCCESS) goto out; if (msg_len != rsa_ssa.digest_size) { CRYPTO_TRACE("Input msg length (%zu expected %zu)", msg_len, rsa_ssa.digest_size); ret = TEE_ERROR_BAD_PARAMETERS; goto out; } } else { rsa_ssa.hash_algo = 0; rsa_ssa.digest_size = 0; } /* Prepare the Key */ rsa_ssa.key.key = key; rsa_ssa.key.isprivate = false; rsa_ssa.key.n_size = crypto_bignum_num_bytes(key->n); if (rsa_ssa.key.n_size > sig_len) { CRYPTO_TRACE("Signature length expected %zu", rsa_ssa.key.n_size); ret = TEE_ERROR_SIGNATURE_INVALID; goto out; } rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the Encoded Signature structure data */ rsa_ssa.algo = algo; rsa_ssa.message.data = (uint8_t *)msg; rsa_ssa.message.length = msg_len; rsa_ssa.signature.data = (uint8_t *)sig; rsa_ssa.signature.length = sig_len; rsa_ssa.salt_len = salt_len; rsa_ssa.mgf = &drvcrypt_rsa_mgf1; ret = TEE_ERROR_NOT_IMPLEMENTED; if (rsa->optional.ssa_verify) ret = rsa->optional.ssa_verify(&rsa_ssa); if (ret == TEE_ERROR_NOT_IMPLEMENTED) ret = drvcrypt_rsassa_verify(&rsa_ssa); } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } CRYPTO_TRACE("Signature verif algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo, ret); out: FTMN_CALLEE_DONE(ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/rsamgf.c000066400000000000000000000050611464416617300245060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * RSA Mask Generation function implementation. */ #include #include #include #include #include "local.h" TEE_Result drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf *mgf_data) { TEE_Result ret = TEE_ERROR_GENERIC; void *ctx = NULL; size_t lastBlock_size = 0; size_t nbBlock = 0; uint32_t counter = 0; uint32_t swapcount = 0; uint8_t *cur_mask = mgf_data->mask.data; uint8_t *tmpdigest = NULL; CRYPTO_TRACE("Generate Mask (%zu bytes) with seed of %zu bytes", mgf_data->mask.length, mgf_data->seed.length); /* Calculate the number of complet hash digest */ lastBlock_size = mgf_data->mask.length % mgf_data->digest_size; if (lastBlock_size) { /* Allocate a digest buffer for the last block */ tmpdigest = calloc(1, mgf_data->digest_size); if (!tmpdigest) return TEE_ERROR_OUT_OF_MEMORY; } /* Allocate the Hash Context */ ret = crypto_hash_alloc_ctx(&ctx, mgf_data->hash_algo); if (ret != TEE_SUCCESS) goto exit_mgf; nbBlock = (mgf_data->mask.length - lastBlock_size) / mgf_data->digest_size; CRYPTO_TRACE("Nb Loop (%zu bytes) = %zu, last Block = %zu bytes", mgf_data->digest_size, nbBlock, lastBlock_size); for (; counter < nbBlock; counter++, cur_mask += mgf_data->digest_size) { swapcount = TEE_U32_TO_BIG_ENDIAN(counter); ret = crypto_hash_init(ctx); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, mgf_data->seed.data, mgf_data->seed.length); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, (uint8_t *)&swapcount, sizeof(swapcount)); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_final(ctx, cur_mask, mgf_data->digest_size); if (ret != TEE_SUCCESS) goto exit_mgf; } if (lastBlock_size) { CRYPTO_TRACE("Last Block = %zu bytes", lastBlock_size); swapcount = TEE_U32_TO_BIG_ENDIAN(counter); ret = crypto_hash_init(ctx); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, mgf_data->seed.data, mgf_data->seed.length); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, (uint8_t *)&swapcount, sizeof(swapcount)); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_final(ctx, tmpdigest, mgf_data->digest_size); if (ret != TEE_SUCCESS) goto exit_mgf; memcpy(cur_mask, tmpdigest, lastBlock_size); } ret = TEE_SUCCESS; exit_mgf: crypto_hash_free_ctx(ctx); free(tmpdigest); CRYPTO_TRACE("return 0x%08" PRIx32, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/rsassa.c000066400000000000000000000553441464416617300245340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * RSA Signature Software common implementation. * Functions preparing and/or verifying the signature * encoded string. * * PKCS #1 v2.1: RSA Cryptography Standard * https://www.ietf.org/rfc/rfc3447.txt */ #include #include #include #include #include #include #include #include #include #include #include "local.h" /* * PKCS#1 V1.5 - Encode the message in Distinguished Encoding Rules * (DER) format. * Refer to EMSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @EM [out] Encoded Message */ static TEE_Result emsa_pkcs1_v1_5_encode(struct drvcrypt_rsa_ssa *ssa_data, struct drvcrypt_buf *EM) { const struct drvcrypt_oid *hash_oid = NULL; size_t ps_size = 0; uint8_t *buf = NULL; hash_oid = drvcrypt_get_alg_hash_oid(ssa_data->hash_algo); if (!hash_oid) return TEE_ERROR_NOT_SUPPORTED; /* * Calculate the PS size * EM Size (modulus size) - 3 bytes - DigestInfo DER format size */ ps_size = ssa_data->key.n_size - 3; ps_size -= ssa_data->digest_size; ps_size -= 10 + hash_oid->asn1_length; CRYPTO_TRACE("PS size = %zu (n %zu)", ps_size, ssa_data->key.n_size); /* * EM = 0x00 || 0x01 || PS || 0x00 || T * * where T represent the message DigestInfo in DER: * DigestInfo ::= SEQUENCE { * digestAlgorithm AlgorithmIdentifier, * digest OCTET STRING * } * * T Length = digest length + oid length * EM Length = T Length + 11 + PS Length */ buf = EM->data; /* Set the EM first byte to 0x00 */ *buf++ = 0x00; /* Set the EM second byte to 0x01 */ *buf++ = 0x01; /* Fill PS with 0xFF */ memset(buf, UINT8_MAX, ps_size); buf += ps_size; /* Set the Byte after PS to 0x00 */ *buf++ = 0x00; /* * Create the DigestInfo DER Sequence * * DigestInfo ::= SEQUENCE { * digestAlgorithm AlgorithmIdentifier, * digest OCTET STRING * } * */ /* SEQUENCE { */ *buf++ = DRVCRYPT_ASN1_SEQUENCE | DRVCRYPT_ASN1_CONSTRUCTED; *buf++ = 0x08 + hash_oid->asn1_length + ssa_data->digest_size; /* digestAlgorithm AlgorithmIdentifier */ *buf++ = DRVCRYPT_ASN1_SEQUENCE | DRVCRYPT_ASN1_CONSTRUCTED; *buf++ = 0x04 + hash_oid->asn1_length; *buf++ = DRVCRYPT_ASN1_OID; *buf++ = hash_oid->asn1_length; /* digest OCTET STRING */ memcpy(buf, hash_oid->asn1, hash_oid->asn1_length); buf += hash_oid->asn1_length; *buf++ = DRVCRYPT_ASN1_NULL; *buf++ = 0x00; *buf++ = DRVCRYPT_ASN1_OCTET_STRING; *buf++ = ssa_data->digest_size; /* } */ memcpy(buf, ssa_data->message.data, ssa_data->digest_size); CRYPTO_DUMPBUF("Encoded Message", EM->data, (size_t)EM->length); return TEE_SUCCESS; } /* * PKCS#1 V1.5 - Encode the message in Distinguished Encoding Rules * (DER) format. * Refer to EMSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @EM [out] Encoded Message */ static TEE_Result emsa_pkcs1_v1_5_encode_noasn1(struct drvcrypt_rsa_ssa *ssa_data, struct drvcrypt_buf *EM) { size_t ps_size = 0; uint8_t *buf = NULL; /* * Calculate the PS size * EM Size (modulus size) - 3 bytes - Message Length */ ps_size = ssa_data->key.n_size - 3; if (ps_size < ssa_data->message.length) return TEE_ERROR_BAD_PARAMETERS; ps_size -= ssa_data->message.length; CRYPTO_TRACE("PS size = %zu (n %zu)", ps_size, ssa_data->key.n_size); /* * EM = 0x00 || 0x01 || PS || 0x00 || T * * T Length = message length * EM Length = T Length + PS Length */ buf = EM->data; /* Set the EM first byte to 0x00 */ *buf++ = 0x00; /* Set the EM second byte to 0x01 */ *buf++ = 0x01; /* Fill PS with 0xFF */ memset(buf, UINT8_MAX, ps_size); buf += ps_size; /* Set the Byte after PS to 0x00 */ *buf++ = 0x00; memcpy(buf, ssa_data->message.data, ssa_data->message.length); CRYPTO_DUMPBUF("Encoded Message", EM->data, EM->length); return TEE_SUCCESS; } /* * PKCS#1 V1.5 - Signature of RSA message and encodes the signature. * Refer to RSASSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data [in/out] RSA data to sign / Signature */ static TEE_Result rsassa_pkcs1_v1_5_sign(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_buf EM = { }; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; EM.length = ssa_data->key.n_size; EM.data = malloc(EM.length); if (!EM.data) return TEE_ERROR_OUT_OF_MEMORY; /* Encode the Message */ if (ssa_data->algo != TEE_ALG_RSASSA_PKCS1_V1_5) ret = emsa_pkcs1_v1_5_encode(ssa_data, &EM); else ret = emsa_pkcs1_v1_5_encode_noasn1(ssa_data, &EM); if (ret != TEE_SUCCESS) goto out; /* * RSA Encrypt/Decrypt are doing the same operation except * that decrypt takes a RSA Private key in parameter */ rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = true; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (!rsa) { ret = TEE_ERROR_NOT_IMPLEMENTED; goto out; } /* Prepare the decryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PKCS_V1_5; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; rsa_data.hash_algo = ssa_data->hash_algo; rsa_data.algo = ssa_data->algo; ret = rsa->decrypt(&rsa_data); /* Set the message decrypted size */ ssa_data->signature.length = rsa_data.message.length; out: free(EM.data); return ret; } /* * PKCS#1 V1.5 - Verification of the RSA message's signature. * Refer to RSASSA-PKCS1-v1_5 chapter of the PKCS#1 v2.1 * * @ssa_data [int/out] RSA data signed and encoded signature */ static TEE_Result rsassa_pkcs1_v1_5_verify(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; struct drvcrypt_buf EM = { }; struct drvcrypt_buf EM_gen = { }; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; EM.length = ssa_data->key.n_size; EM.data = malloc(EM.length); if (!EM.data) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_verify; } EM_gen.length = ssa_data->key.n_size; EM_gen.data = malloc(EM.length); if (!EM_gen.data) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_verify; } /* * RSA Encrypt/Decrypt are doing the same operation except * that the encrypt takes a RSA Public key in parameter */ rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = false; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PKCS_V1_5; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; rsa_data.hash_algo = ssa_data->hash_algo; ret = rsa->encrypt(&rsa_data); /* Set the cipher size */ EM.length = rsa_data.cipher.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } if (ret != TEE_SUCCESS) goto end_verify; /* Encode the Message */ if (ssa_data->algo != TEE_ALG_RSASSA_PKCS1_V1_5) ret = emsa_pkcs1_v1_5_encode(ssa_data, &EM_gen); else ret = emsa_pkcs1_v1_5_encode_noasn1(ssa_data, &EM_gen); if (ret != TEE_SUCCESS) goto end_verify; /* Check if EM decrypted and EM re-generated are identical */ ret = TEE_ERROR_SIGNATURE_INVALID; if (EM.length == EM_gen.length) { if (!memcmp(EM.data, EM_gen.data, EM.length)) ret = TEE_SUCCESS; } end_verify: free(EM.data); free(EM_gen.data); return ret; } /* * PSS - Encode the message using a Probabilistic Signature Scheme (PSS) * Refer to EMSA-PSS (encoding) chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @emBits EM size in bits * @EM [out] Encoded Message */ static TEE_Result emsa_pss_encode(struct drvcrypt_rsa_ssa *ssa_data, size_t emBits, struct drvcrypt_buf *EM) { TEE_Result ret = TEE_ERROR_GENERIC; struct drvcrypt_rsa_mgf mgf_data = { }; struct drvcrypt_buf hash = { }; struct drvcrypt_buf dbMask = { }; struct drvcrypt_buf DB = { }; size_t db_size = 0; size_t ps_size = 0; size_t msg_size = 0; uint8_t *buf = NULL; uint8_t *msg_db = NULL; uint8_t *salt = NULL; struct drvcrypt_mod_op mod_op = { }; /* * Build EM = maskedDB || H || 0xbc * * where * maskedDB = DB xor dbMask * DB = PS || 0x01 || salt * dbMask = MGF(H, emLen - hLen - 1) * * H = Hash(M') * M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * PS size = emLen - sLen - hLen - 2 (may be = 0) */ /* * Calculate the M' and DB size to allocate a temporary buffer * used for both object */ ps_size = EM->length - ssa_data->digest_size - ssa_data->salt_len - 2; db_size = EM->length - ssa_data->digest_size - 1; msg_size = 8 + ssa_data->digest_size + ssa_data->salt_len; CRYPTO_TRACE("PS Len = %zu, DB Len = %zu, M' Len = %zu", ps_size, db_size, msg_size); msg_db = malloc(MAX(db_size, msg_size)); if (!msg_db) return TEE_ERROR_OUT_OF_MEMORY; if (ssa_data->salt_len) { salt = malloc(ssa_data->salt_len); if (!salt) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_pss_encode; } } /* * Step 4 and 5 * Generate the M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * where * mHash is the input message (already hash) * salt is a random number of salt_len (input data) can be empty */ buf = msg_db; memset(buf, 0, 8); buf += 8; memcpy(buf, ssa_data->message.data, ssa_data->message.length); buf += ssa_data->message.length; /* Get salt random number if salt length not 0 */ if (ssa_data->salt_len) { ret = crypto_rng_read(salt, ssa_data->salt_len); CRYPTO_TRACE("Get salt of %zu bytes (ret = 0x%08" PRIx32 ")", ssa_data->salt_len, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; memcpy(buf, salt, ssa_data->salt_len); } /* * Step 6 * Hash the M' generated new message * H = hash(M') */ hash.data = &EM->data[db_size]; hash.length = ssa_data->digest_size; ret = tee_hash_createdigest(ssa_data->hash_algo, msg_db, msg_size, hash.data, hash.length); CRYPTO_TRACE("H = hash(M') returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; CRYPTO_DUMPBUF("H = hash(M')", hash.data, hash.length); /* * Step 7 and 8 * DB = PS || 0x01 || salt */ buf = msg_db; if (ps_size) memset(buf, 0, ps_size); buf += ps_size; *buf++ = 0x01; if (ssa_data->salt_len) memcpy(buf, salt, ssa_data->salt_len); DB.data = msg_db; DB.length = db_size; CRYPTO_DUMPBUF("DB", DB.data, DB.length); /* * Step 9 * Generate a Mask of the seed value * dbMask = MGF(H, emLen - hLen - 1) * * Note: Will use the same buffer for the dbMask and maskedDB * maskedDB is in the EM output */ dbMask.data = EM->data; dbMask.length = db_size; mgf_data.hash_algo = ssa_data->hash_algo; mgf_data.digest_size = ssa_data->digest_size; mgf_data.seed.data = hash.data; mgf_data.seed.length = hash.length; mgf_data.mask.data = dbMask.data; mgf_data.mask.length = dbMask.length; ret = ssa_data->mgf(&mgf_data); CRYPTO_TRACE("dbMask = MGF(H, emLen - hLen - 1) returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; CRYPTO_DUMPBUF("dbMask", dbMask.data, dbMask.length); /* * Step 10 * maskedDB = DB xor dbMask */ mod_op.n.length = dbMask.length; mod_op.a.data = DB.data; mod_op.a.length = DB.length; mod_op.b.data = dbMask.data; mod_op.b.length = dbMask.length; mod_op.result.data = dbMask.data; mod_op.result.length = dbMask.length; ret = drvcrypt_xor_mod_n(&mod_op); CRYPTO_TRACE("maskedDB = DB xor dbMask returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_encode; CRYPTO_DUMPBUF("maskedDB", dbMask.data, dbMask.length); /* * Step 11 * Set the leftmost 8emLen - emBits of the leftmost octet * in maskedDB to 0' */ EM->data[0] &= (UINT8_MAX >> ((EM->length * 8) - emBits)); /* * Step 12 * EM = maskedDB || H || 0xbc */ EM->data[EM->length - 1] = 0xbc; CRYPTO_DUMPBUF("EM", EM->data, EM->length); ret = TEE_SUCCESS; end_pss_encode: free(msg_db); free(salt); return ret; } /* * PSS - Verify the message using a Probabilistic Signature Scheme (PSS) * Refer to EMSA-PSS (verification) chapter of the PKCS#1 v2.1 * * @ssa_data RSA data to encode * @emBits EM size in bits * @EM [out] Encoded Message */ static TEE_Result emsa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data, size_t emBits, struct drvcrypt_buf *EM) { TEE_Result ret = TEE_ERROR_GENERIC; struct drvcrypt_rsa_mgf mgf_data = { }; struct drvcrypt_buf hash = { }; struct drvcrypt_buf hash_gen = { }; size_t db_size = 0; size_t ps_size = 0; size_t msg_size = 0; uint8_t *msg_db = NULL; uint8_t *salt = NULL; uint8_t *buf = NULL; struct drvcrypt_mod_op mod_op = { }; /* * EM = maskedDB || H || 0xbc * * where * maskedDB = DB xor dbMask * DB = PS || 0x01 || salt * dbMask = MGF(H, emLen - hLen - 1) * * H = Hash(M') * M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * PS size = emLen - sLen - hLen - 2 (may be = 0) */ /* * Calculate the M' and DB size to allocate a temporary buffer * used for both object */ ps_size = EM->length - ssa_data->digest_size - ssa_data->salt_len - 2; db_size = EM->length - ssa_data->digest_size - 1; msg_size = 8 + ssa_data->digest_size + ssa_data->salt_len; CRYPTO_TRACE("PS Len = %zu, DB Len = %zu, M' Len = %zu", ps_size, db_size, msg_size); msg_db = malloc(MAX(db_size, msg_size)); if (!msg_db) return TEE_ERROR_OUT_OF_MEMORY; /* * Step 4 * Check if rightmost octet of EM is 0xbc */ if (EM->data[EM->length - 1] != 0xbc) { CRYPTO_TRACE("rigthmost octet != 0xbc (0x%" PRIX8 ")", EM->data[EM->length - 1]); ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } /* * Step 6 * Check if the leftmost 8emLen - emBits of the leftmost octet * in maskedDB are 0's */ if (EM->data[0] & ~(UINT8_MAX >> (EM->length * 8 - emBits))) { CRYPTO_TRACE("Error leftmost octet maskedDB not 0's"); CRYPTO_TRACE("EM[0] = 0x%" PRIX8 " - EM Len = %zu, emBits = %zu", EM->data[0], EM->length, emBits); ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } hash.data = &EM->data[db_size]; hash.length = ssa_data->digest_size; /* * Step 7 * dbMask = MGF(H, emLen - hLen - 1) * * Note: Will use the same buffer for the dbMask and DB */ mgf_data.hash_algo = ssa_data->hash_algo; mgf_data.digest_size = ssa_data->digest_size; mgf_data.seed.data = hash.data; mgf_data.seed.length = hash.length; mgf_data.mask.data = msg_db; mgf_data.mask.length = db_size; ret = ssa_data->mgf(&mgf_data); CRYPTO_TRACE("dbMask = MGF(H, emLen - hLen - 1) returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_verify; CRYPTO_DUMPBUF("dbMask", msg_db, db_size); /* * Step 8 * DB = maskedDB xor dbMask * * * Note: maskedDB is in the EM input */ mod_op.n.length = db_size; mod_op.a.data = EM->data; mod_op.a.length = db_size; mod_op.b.data = msg_db; mod_op.b.length = db_size; mod_op.result.data = msg_db; mod_op.result.length = db_size; ret = drvcrypt_xor_mod_n(&mod_op); CRYPTO_TRACE("DB = maskedDB xor dbMask returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_verify; /* * Step 9 * Set the leftmost 8emLen - emBits of the leftmost octet in * DB to zero */ *msg_db &= UINT8_MAX >> (EM->length * 8 - emBits); CRYPTO_DUMPBUF("DB", msg_db, db_size); /* * Step 10 * Expected to have * DB = PS || 0x01 || salt * * PS must be 0 * PS size = emLen - sLen - hLen - 2 (may be = 0) */ buf = msg_db; while (buf < msg_db + ps_size) { if (*buf++ != 0) { ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } } if (*buf++ != 0x01) { ret = TEE_ERROR_SIGNATURE_INVALID; goto end_pss_verify; } /* * Step 11 * Get the salt value */ if (ssa_data->salt_len) { salt = malloc(ssa_data->salt_len); if (!salt) { ret = TEE_ERROR_OUT_OF_MEMORY; goto end_pss_verify; } memcpy(salt, buf, ssa_data->salt_len); } /* * Step 12 * Generate the M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt * * where * mHash is the input message (already hash) * salt is a random number of salt_len (input data) can be empty */ buf = msg_db; memset(buf, 0, 8); buf += 8; memcpy(buf, ssa_data->message.data, ssa_data->message.length); buf += ssa_data->message.length; if (ssa_data->salt_len) memcpy(buf, salt, ssa_data->salt_len); /* * Step 13 * Hash the M' generated new message * H' = hash(M') * * Note: reuse the msg_db buffer as Hash result */ hash_gen.data = msg_db; hash_gen.length = ssa_data->digest_size; ret = tee_hash_createdigest(ssa_data->hash_algo, msg_db, msg_size, hash_gen.data, hash_gen.length); CRYPTO_TRACE("H' = hash(M') returned 0x%08" PRIx32, ret); if (ret != TEE_SUCCESS) goto end_pss_verify; CRYPTO_DUMPBUF("H' = hash(M')", hash_gen.data, hash_gen.length); /* * Step 14 * Compare H and H' */ ret = TEE_ERROR_SIGNATURE_INVALID; if (!memcmp(hash_gen.data, hash.data, hash_gen.length)) ret = TEE_SUCCESS; end_pss_verify: free(msg_db); free(salt); return ret; } /* * PSS - Signature of RSA message and encodes the signature. * Refer to RSASSA-PSS chapter of the PKCS#1 v2.1 * * @ssa_data [in/out] RSA data to sign / Signature */ static TEE_Result rsassa_pss_sign(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_GENERIC; struct rsa_keypair *key = NULL; struct drvcrypt_buf EM = { }; size_t modBits = 0; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; key = ssa_data->key.key; /* Get modulus length in bits */ modBits = crypto_bignum_num_bits(key->n); if (modBits <= 0) return TEE_ERROR_BAD_PARAMETERS; /* * EM Length = (modBits - 1) / 8 * if (modBits - 1) is not divisible by 8, one more byte is needed */ modBits--; EM.length = ROUNDUP(modBits, 8) / 8; if (EM.length < ssa_data->digest_size + ssa_data->salt_len + 2) return TEE_ERROR_BAD_PARAMETERS; EM.data = malloc(EM.length); if (!EM.data) return TEE_ERROR_OUT_OF_MEMORY; CRYPTO_TRACE("modBits = %zu, hence EM Length = %zu", modBits + 1, EM.length); /* Encode the Message */ ret = emsa_pss_encode(ssa_data, modBits, &EM); CRYPTO_TRACE("EMSA PSS Encode returned 0x%08" PRIx32, ret); /* * RSA Encrypt/Decrypt are doing the same operation * expect that the decrypt takes a RSA Private key in parameter */ if (ret == TEE_SUCCESS) { rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = true; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the decryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PSS; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; rsa_data.algo = ssa_data->algo; ret = rsa->decrypt(&rsa_data); /* Set the message decrypted size */ ssa_data->signature.length = rsa_data.message.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; } } free(EM.data); return ret; } /* * PSS - Signature verification of RSA message. * Refer to RSASSA-PSS chapter of the PKCS#1 v2.1 * * @ssa_data [in/out] RSA Signature vs. message to verify */ static TEE_Result rsassa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data) { TEE_Result ret = TEE_ERROR_GENERIC; struct rsa_public_key *key = NULL; struct drvcrypt_buf EM = { }; size_t modBits = 0; struct drvcrypt_rsa_ed rsa_data = { }; struct drvcrypt_rsa *rsa = NULL; key = ssa_data->key.key; /* Get modulus length in bits */ modBits = crypto_bignum_num_bits(key->n); if (modBits <= 0) return TEE_ERROR_BAD_PARAMETERS; /* * EM Length = (modBits - 1) / 8 * if (modBits - 1) is not divisible by 8, one more byte is needed */ modBits--; EM.length = ROUNDUP(modBits, 8) / 8; if (EM.length < ssa_data->digest_size + ssa_data->salt_len + 2) return TEE_ERROR_BAD_PARAMETERS; EM.data = malloc(EM.length); if (!EM.data) return TEE_ERROR_OUT_OF_MEMORY; CRYPTO_TRACE("modBits = %zu, hence EM Length = %zu", modBits + 1, EM.length); /* * RSA Encrypt/Decrypt are doing the same operation * expect that the encrypt takes a RSA Public key in parameter */ rsa_data.key.key = ssa_data->key.key; rsa_data.key.isprivate = false; rsa_data.key.n_size = ssa_data->key.n_size; rsa = drvcrypt_get_ops(CRYPTO_RSA); if (rsa) { /* Prepare the encryption data parameters */ rsa_data.rsa_id = DRVCRYPT_RSASSA_PSS; rsa_data.message.data = ssa_data->signature.data; rsa_data.message.length = ssa_data->signature.length; rsa_data.cipher.data = EM.data; rsa_data.cipher.length = EM.length; rsa_data.algo = ssa_data->algo; ret = rsa->encrypt(&rsa_data); /* Set the cipher size */ EM.length = rsa_data.cipher.length; } else { ret = TEE_ERROR_NOT_IMPLEMENTED; goto end_pss_verify; } if (ret == TEE_SUCCESS) { /* Verify the Message */ ret = emsa_pss_verify(ssa_data, modBits, &EM); CRYPTO_TRACE("EMSA PSS Verify returned 0x%08" PRIx32, ret); } else { CRYPTO_TRACE("RSA NO PAD returned 0x%08" PRIx32, ret); ret = TEE_ERROR_SIGNATURE_INVALID; } end_pss_verify: free(EM.data); return ret; } TEE_Result drvcrypt_rsassa_sign(struct drvcrypt_rsa_ssa *ssa_data) { switch (ssa_data->algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: return rsassa_pkcs1_v1_5_sign(ssa_data); case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return rsassa_pss_sign(ssa_data); default: break; } return TEE_ERROR_BAD_PARAMETERS; } TEE_Result drvcrypt_rsassa_verify(struct drvcrypt_rsa_ssa *ssa_data) { switch (ssa_data->algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: return rsassa_pkcs1_v1_5_verify(ssa_data); case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return rsassa_pss_verify(ssa_data); default: break; } return TEE_ERROR_BAD_PARAMETERS; } optee_os-4.3.0/core/drivers/crypto/crypto_api/acipher/sub.mk000066400000000000000000000002411464416617300242000ustar00rootroot00000000000000srcs-$(CFG_CRYPTO_DRV_RSA) += rsa.c rsamgf.c rsassa.c srcs-$(CFG_CRYPTO_DRV_ECC) += ecc.c srcs-$(CFG_CRYPTO_DRV_DH) += dh.c srcs-$(CFG_CRYPTO_DRV_DSA) += dsa.c optee_os-4.3.0/core/drivers/crypto/crypto_api/authenc/000077500000000000000000000000001464416617300230755ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/authenc/authenc.c000066400000000000000000000213211464416617300246670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved * * Crypto authenc interface implementation to enable HW driver. */ #include #include #include #include #include #include #include #include #include static const struct crypto_authenc_ops authenc_ops; /* * Returns the reference to the driver context * * @ctx Reference the API context pointer */ static struct crypto_authenc *to_authenc_ctx(struct crypto_authenc_ctx *ctx) { assert(ctx && ctx->ops == &authenc_ops); return container_of(ctx, struct crypto_authenc, authenc_ctx); } /* * Free authenc context * * @ctx Reference the API context pointer */ static void authenc_free_ctx(struct crypto_authenc_ctx *ctx) { struct crypto_authenc *authenc = to_authenc_ctx(ctx); if (authenc->op && authenc->op->free_ctx) authenc->op->free_ctx(authenc->ctx); free(authenc); } /* * Copy authenc context * * @dst_ctx [out] Reference the API context pointer destination * @src_ctx Reference the API context pointer source */ static void authenc_copy_state(struct crypto_authenc_ctx *dst_ctx, struct crypto_authenc_ctx *src_ctx) { struct crypto_authenc *authenc_src = to_authenc_ctx(src_ctx); struct crypto_authenc *authenc_dst = to_authenc_ctx(dst_ctx); if (authenc_src->op && authenc_src->op->copy_state) authenc_src->op->copy_state(authenc_dst->ctx, authenc_src->ctx); } /* * Initialization of the authenc operation * * @ctx Reference the API context pointer * @mode Operation mode * @key Key * @key_len Length of the key * @nonce Nonce * @nonce_len Length of the nonce * @tag_len Length of the requested tag * @aad_len Length of the associated authenticated data * @payload_len Length of payload */ static TEE_Result authenc_init(struct crypto_authenc_ctx *ctx, TEE_OperationMode mode, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc *authenc = to_authenc_ctx(ctx); if ((!key && key_len) || (!nonce && nonce_len)) { CRYPTO_TRACE("One of the key is not correct"); CRYPTO_TRACE("key @%p-%zu bytes", key, key_len); CRYPTO_TRACE("nonce @%p-%zu bytes", nonce, nonce_len); return TEE_ERROR_BAD_PARAMETERS; } if (authenc->op && authenc->op->init) { struct drvcrypt_authenc_init dinit = { .ctx = authenc->ctx, .encrypt = (mode == TEE_MODE_ENCRYPT), .key.data = (uint8_t *)key, .key.length = key_len, .nonce.data = (uint8_t *)nonce, .nonce.length = nonce_len, .tag_len = tag_len, .aad_len = aad_len, .payload_len = payload_len, }; ret = authenc->op->init(&dinit); } CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); return ret; } /* * Update Additional Authenticated Data part of the authenc operation * * @ctx Reference the API context pointer * @data Data to authenticate without encrypt/decrypt (AAD) * @len AAD length in bytes */ static TEE_Result authenc_update_aad(struct crypto_authenc_ctx *ctx, const uint8_t *data, size_t len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc *authenc = to_authenc_ctx(ctx); if (!data && len) { CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len); return TEE_ERROR_BAD_PARAMETERS; } if (authenc->op && authenc->op->update_aad) { struct drvcrypt_authenc_update_aad dupdate = { .ctx = authenc->ctx, .aad.data = (uint8_t *)data, .aad.length = len, }; ret = authenc->op->update_aad(&dupdate); } CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); return ret; } /* * Update payload part of the authenc operation * * @ctx Reference the API context pointer * @data Data to authenticate and encrypt/decrypt * @len Length of the input data and output result * @dst [out] Output data of the operation */ static TEE_Result authenc_update_payload(struct crypto_authenc_ctx *ctx, TEE_OperationMode mode, const uint8_t *data, size_t len, uint8_t *dst) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc *authenc = to_authenc_ctx(ctx); if (!dst) { CRYPTO_TRACE("Destination buffer error"); return TEE_ERROR_BAD_PARAMETERS; } if (!data && len) { CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len); return TEE_ERROR_BAD_PARAMETERS; } if (authenc->op && authenc->op->update_payload) { struct drvcrypt_authenc_update_payload dupdate = { .ctx = authenc->ctx, .encrypt = (mode == TEE_MODE_ENCRYPT), .src.data = (uint8_t *)data, .src.length = len, .dst.data = dst, .dst.length = len, }; ret = authenc->op->update_payload(&dupdate); } CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); return ret; } /* * Last block for the authenc encrypt and get tag operation * * @ctx Reference the API context pointer * @data Data to authenticate and encrypt (can be NULL) * @len Length of the input data and output result (can be 0) * @dst [out] Output data of the operation * @tag [out] Output tag of the operation * @tag_len [in/out] in: size of the dst_tag buffer * out: size of the computed tag */ static TEE_Result authenc_enc_final(struct crypto_authenc_ctx *ctx, const uint8_t *data, size_t len, uint8_t *dst, uint8_t *tag, size_t *tag_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc *authenc = to_authenc_ctx(ctx); if (!dst && len) { CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len); return TEE_ERROR_BAD_PARAMETERS; } if (!data && len) { CRYPTO_TRACE("Bad input @%p-%zu bytes", data, len); return TEE_ERROR_BAD_PARAMETERS; } if (authenc->op && authenc->op->enc_final) { struct drvcrypt_authenc_final dfinal = { .ctx = authenc->ctx, .src.data = (uint8_t *)data, .src.length = len, .dst.data = dst, .dst.length = len, .tag.data = tag, .tag.length = *tag_len }; ret = authenc->op->enc_final(&dfinal); if (ret == TEE_SUCCESS) *tag_len = dfinal.tag.length; } CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); return ret; } /* * Last block for the authenc decrypt and check tag operation * * @ctx Reference the API context pointer * @src_data Data to authenticate and encrypt (can be NULL) * @len Length of the input data and output result (can be 0) * @dst [out] Output data of the operation * @tag Tag to check at end of operation * @tag_len Length of @tag */ static TEE_Result authenc_dec_final(struct crypto_authenc_ctx *ctx, const uint8_t *data, size_t len, uint8_t *dst, const uint8_t *tag, size_t tag_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc *authenc = to_authenc_ctx(ctx); if (!dst && len) { CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len); return TEE_ERROR_BAD_PARAMETERS; } if (!data && len) { CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len); return TEE_ERROR_BAD_PARAMETERS; } if (authenc->op && authenc->op->dec_final) { struct drvcrypt_authenc_final dfinal = { .ctx = authenc->ctx, .src.data = (uint8_t *)data, .src.length = len, .dst.data = dst, .dst.length = len, .tag.data = (uint8_t *)tag, .tag.length = tag_len }; ret = authenc->op->dec_final(&dfinal); } CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret); return ret; } /* * Finalize the authenc operation * * @ctx Reference the API context pointer */ static void authenc_final(struct crypto_authenc_ctx *ctx) { struct crypto_authenc *authenc = to_authenc_ctx(ctx); if (authenc->op && authenc->op->final) authenc->op->final(authenc->ctx); } static const struct crypto_authenc_ops authenc_ops = { .init = authenc_init, .update_aad = authenc_update_aad, .update_payload = authenc_update_payload, .enc_final = authenc_enc_final, .dec_final = authenc_dec_final, .final = authenc_final, .free_ctx = authenc_free_ctx, .copy_state = authenc_copy_state, }; TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx, uint32_t algo) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_authenc *authenc = NULL; CRYPTO_TRACE("authenc alloc_ctx algo 0x%" PRIx32, algo); assert(ctx); authenc = calloc(1, sizeof(*authenc)); if (!authenc) return TEE_ERROR_OUT_OF_MEMORY; authenc->op = drvcrypt_get_ops(CRYPTO_AUTHENC); if (authenc->op && authenc->op->alloc_ctx) ret = authenc->op->alloc_ctx(&authenc->ctx, algo); if (ret != TEE_SUCCESS) { free(authenc); } else { authenc->authenc_ctx.ops = &authenc_ops; *ctx = &authenc->authenc_ctx; } CRYPTO_TRACE("authenc alloc_ctx ret 0x%" PRIx32, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/authenc/sub.mk000066400000000000000000000000241464416617300242130ustar00rootroot00000000000000srcs-y += authenc.c optee_os-4.3.0/core/drivers/crypto/crypto_api/cipher/000077500000000000000000000000001464416617300227205ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/cipher/cipher.c000066400000000000000000000116261464416617300243440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * Crypto Cipher interface implementation to enable HW driver. */ #include #include #include #include #include #include #include static const struct crypto_cipher_ops cipher_ops; /* * Returns the reference to the driver context * * @ctx Reference the API context pointer */ static struct crypto_cipher *to_cipher_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &cipher_ops); return container_of(ctx, struct crypto_cipher, cipher_ctx); } /* * Free cipher context * * @ctx Reference the API context pointer */ static void cipher_free_ctx(struct crypto_cipher_ctx *ctx) { struct crypto_cipher *cipher = to_cipher_ctx(ctx); if (cipher->op && cipher->op->free_ctx) cipher->op->free_ctx(cipher->ctx); free(cipher); } /* * Copy cipher context * * @dst_ctx [out] Reference the API context pointer destination * @src_ctx Reference the API context pointer source */ static void cipher_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct crypto_cipher *cipher_src = to_cipher_ctx(src_ctx); struct crypto_cipher *cipher_dst = to_cipher_ctx(dst_ctx); if (cipher_src->op && cipher_src->op->copy_state) cipher_src->op->copy_state(cipher_dst->ctx, cipher_src->ctx); } /* * Initialization of the cipher operation * * @ctx Reference the API context pointer * @mode Operation mode * @key1 First Key * @key1_len Length of the first key * @key2 Second Key * @key2_len Length of the second key * @iv Initial Vector * @iv_len Length of the IV */ static TEE_Result cipher_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_cipher *cipher = to_cipher_ctx(ctx); if ((!key1 && key1_len) || (!key2 && key2_len) || (!iv && iv_len)) { CRYPTO_TRACE("One of the key is not correct"); CRYPTO_TRACE("key1 @%p-%zu bytes", key1, key1_len); CRYPTO_TRACE("key2 @%p-%zu bytes", key1, key1_len); CRYPTO_TRACE("iv @%p-%zu bytes", iv, iv_len); return TEE_ERROR_BAD_PARAMETERS; } if (cipher->op && cipher->op->init) { struct drvcrypt_cipher_init dinit = { .ctx = cipher->ctx, .encrypt = (mode == TEE_MODE_ENCRYPT), .key1.data = (uint8_t *)key1, .key1.length = key1_len, .key2.data = (uint8_t *)key2, .key2.length = key2_len, .iv.data = (uint8_t *)iv, .iv.length = iv_len, }; ret = cipher->op->init(&dinit); } CRYPTO_TRACE("cipher ret 0x%" PRIX32, ret); return ret; } /* * Update of the cipher operation * * @ctx Reference the API context pointer * @last_block True if last block to handle * @data Data to encrypt/decrypt * @len Length of the input data and output result * @dst [out] Output data of the operation */ static TEE_Result cipher_update(struct crypto_cipher_ctx *ctx, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_cipher *cipher = to_cipher_ctx(ctx); if (!dst) { CRYPTO_TRACE("Destination buffer error"); return TEE_ERROR_BAD_PARAMETERS; } if (!data && len) { CRYPTO_TRACE("Bad data data @%p-%zu bytes", data, len); return TEE_ERROR_BAD_PARAMETERS; } if (cipher->op && cipher->op->update) { struct drvcrypt_cipher_update dupdate = { .ctx = cipher->ctx, .last = last_block, .src.data = (uint8_t *)data, .src.length = len, .dst.data = dst, .dst.length = len, }; ret = cipher->op->update(&dupdate); } CRYPTO_TRACE("cipher ret 0x%" PRIX32, ret); return ret; } /* * Finalize the cipher operation * * @ctx Reference the API context pointer */ static void cipher_final(struct crypto_cipher_ctx *ctx) { struct crypto_cipher *cipher = to_cipher_ctx(ctx); if (cipher->op && cipher->op->final) cipher->op->final(cipher->ctx); } static const struct crypto_cipher_ops cipher_ops = { .init = cipher_init, .update = cipher_update, .final = cipher_final, .free_ctx = cipher_free_ctx, .copy_state = cipher_copy_state, }; TEE_Result drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx, uint32_t algo) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; struct crypto_cipher *cipher = NULL; CRYPTO_TRACE("Cipher alloc_ctx algo 0x%" PRIX32, algo); assert(ctx); cipher = calloc(1, sizeof(*cipher)); if (!cipher) return TEE_ERROR_OUT_OF_MEMORY; cipher->op = drvcrypt_get_ops(CRYPTO_CIPHER); if (cipher->op && cipher->op->alloc_ctx) ret = cipher->op->alloc_ctx(&cipher->ctx, algo); if (ret != TEE_SUCCESS) { free(cipher); } else { cipher->cipher_ctx.ops = &cipher_ops; *ctx = &cipher->cipher_ctx; } CRYPTO_TRACE("Cipher alloc_ctx ret 0x%" PRIX32, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/cipher/sub.mk000066400000000000000000000000231464416617300240350ustar00rootroot00000000000000srcs-y += cipher.c optee_os-4.3.0/core/drivers/crypto/crypto_api/drvcrypt.c000066400000000000000000000015321464416617300234700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief This driver interfaces TEE Cryptographic API crypto_* */ #include #include #include static void *crypt_algo[CRYPTO_MAX_ALGO]; TEE_Result drvcrypt_register(enum drvcrypt_algo_id algo_id, void *ops) { if (!crypt_algo[algo_id]) { CRYPTO_TRACE("Registering module id %d with 0x%p", algo_id, ops); crypt_algo[algo_id] = ops; return TEE_SUCCESS; } CRYPTO_TRACE("Fail to register module id %d with 0x%p", algo_id, ops); return TEE_ERROR_GENERIC; } void drvcrypt_register_change(enum drvcrypt_algo_id algo_id, void *ops) { CRYPTO_TRACE("Change registered module id %d with 0x%p", algo_id, ops); crypt_algo[algo_id] = ops; } void *drvcrypt_get_ops(enum drvcrypt_algo_id algo_id) { return crypt_algo[algo_id]; } optee_os-4.3.0/core/drivers/crypto/crypto_api/hash/000077500000000000000000000000001464416617300223715ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/hash/hash.c000066400000000000000000000011731464416617300234620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019 NXP * * Brief Crypto Hash interface implementation to enable HW driver. */ #include #include #include #include TEE_Result drvcrypt_hash_alloc_ctx(struct crypto_hash_ctx **ctx, uint32_t algo) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; hw_hash_allocate hash_alloc = NULL; CRYPTO_TRACE("hash alloc_ctx algo 0x%" PRIX32, algo); assert(ctx); hash_alloc = drvcrypt_get_ops(CRYPTO_HASH); if (hash_alloc) ret = hash_alloc(ctx, algo); CRYPTO_TRACE("hash alloc_ctx ret 0x%" PRIX32, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/hash/sub.mk000066400000000000000000000000211464416617300235040ustar00rootroot00000000000000srcs-y += hash.c optee_os-4.3.0/core/drivers/crypto/crypto_api/include/000077500000000000000000000000001464416617300230715ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt.h000066400000000000000000000050731464416617300251240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief Crypto Driver exported constants and interfaces. */ #ifndef __DRVCRYPT_H__ #define __DRVCRYPT_H__ #include #include #include /* * Debug Macros function of Crypto Driver Debug Level setting * The CFG_CRYPTO_DRV_DBG is a bit mask 32 bits value defined * as followed: */ #define DRV_DBG_TRACE BIT32(0) /* Driver trace */ #define DRV_DBG_BUF BIT32(1) /* Driver dump Buffer */ #if (CFG_CRYPTO_DRIVER_DEBUG & DRV_DBG_TRACE) #define CRYPTO_TRACE DMSG #else #define CRYPTO_TRACE(...) #endif #if (CFG_CRYPTO_DRIVER_DEBUG & DRV_DBG_BUF) #define CRYPTO_DUMPBUF(title, buf, len) \ do { \ __typeof__(buf) _buf = (buf); \ __typeof__(len) _len = (len); \ CRYPTO_TRACE("%s @%p: %zu", title, _buf, _len); \ dhex_dump(NULL, 0, 0, _buf, _len); \ } while (0) #else #define CRYPTO_DUMPBUF(...) #endif /* * Definition of a crypto buffer type */ struct drvcrypt_buf { uint8_t *data; size_t length; }; /* * Crypto Library Algorithm enumeration */ enum drvcrypt_algo_id { CRYPTO_HASH = 0, /* Hash driver */ CRYPTO_HMAC, /* HMAC driver */ CRYPTO_CMAC, /* CMAC driver */ CRYPTO_RSA, /* Asymmetric RSA driver */ CRYPTO_MATH, /* Mathematical driver */ CRYPTO_CIPHER, /* Cipher driver */ CRYPTO_ECC, /* Asymmetric ECC driver */ CRYPTO_X25519, /* Asymmetric X25519 driver */ CRYPTO_X448, /* Asymmetric X448 driver */ CRYPTO_DH, /* Asymmetric DH driver */ CRYPTO_DSA, /* Asymmetric DSA driver */ CRYPTO_AUTHENC, /* Authenticated Encryption driver */ CRYPTO_MAX_ALGO /* Maximum number of algo supported */ }; /* * Register the Cryptographic's operation in the table of modules * * @algo_id ID of the Cryptographic module * @ops Operation (function/structure) to register */ TEE_Result drvcrypt_register(enum drvcrypt_algo_id algo_id, void *ops); /* * Modify the Cryptographic algorithm in the table of modules * * @algo_id ID of the Cryptographic module * @ops Operation (function/structure) to register */ void drvcrypt_register_change(enum drvcrypt_algo_id algo_id, void *ops); /* * Return the Cryptographic's operation (function/structure) registered in * the table of modules. * * @algo_id ID of the Cryptographic module */ void *drvcrypt_get_ops(enum drvcrypt_algo_id algo_id); #endif /* __DRVCRYPT_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h000066400000000000000000000201751464416617300266170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2021 NXP * * Brief Asymmetric Cipher interface calling the HW crypto driver. */ #ifndef __DRVCRYPT_ACIPHER_H__ #define __DRVCRYPT_ACIPHER_H__ #include #include /* * Assymetric Cipher RSA Algorithm enumerate */ enum drvcrypt_rsa_id { DRVCRYPT_RSA_NOPAD = 0, /* RSA Algo mode NO PAD */ DRVCRYPT_RSA_OAEP, /* RSA Algo mode OAEP */ DRVCRYPT_RSA_PKCS_V1_5, /* RSA Algo mode PKCSv1.5 */ DRVCRYPT_RSASSA_PKCS_V1_5, /* RSA Signature Algo mode PKCSv1.5 */ DRVCRYPT_RSASSA_PSS, /* RSA Signature Algo mode PSS */ }; /* * RSA Key object */ struct drvcrypt_rsakey { void *key; /* Public or Private key */ size_t n_size; /* Size in bytes of the Modulus N */ bool isprivate; /* True if private key */ }; /* * RSA Mask Generation data */ struct drvcrypt_rsa_mgf { uint32_t hash_algo; /* HASH Algorithm */ size_t digest_size; /* Hash Digest Size */ struct drvcrypt_buf seed; /* Seed to generate mask */ struct drvcrypt_buf mask; /* Mask generated */ }; /* * RSA Encoded Signature data */ struct drvcrypt_rsa_ssa { uint32_t algo; /* Operation algorithm */ uint32_t hash_algo; /* HASH Algorithm */ size_t digest_size; /* Hash Digest Size */ struct drvcrypt_rsakey key; /* Public or Private Key */ struct drvcrypt_buf message; /* Message to sign or signed */ struct drvcrypt_buf signature; /* Signature of the message */ size_t salt_len; /* Signature Salt length */ /* RSA Mask Generation function */ TEE_Result (*mgf)(struct drvcrypt_rsa_mgf *mgf_data); }; /* * RSA Encrypt/Decrypt data */ struct drvcrypt_rsa_ed { uint32_t algo; /* Operation algorithm */ enum drvcrypt_rsa_id rsa_id; /* RSA Algorithm Id */ uint32_t hash_algo; /* HASH Algorithm */ size_t digest_size; /* Hash Digest Size */ struct drvcrypt_rsakey key; /* Public or Private key */ struct drvcrypt_buf message; /* Message to encrypt or decrypted */ struct drvcrypt_buf cipher; /* Cipher encrypted or to decrypt */ struct drvcrypt_buf label; /* Additional Label (RSAES) */ uint32_t mgf_algo; /* MGF1 hash algorithm (RSAES) */ size_t mgf_size; /* MGF1 hash digest size (RSAES) */ /* RSA Mask Generation function */ TEE_Result (*mgf)(struct drvcrypt_rsa_mgf *mgf_data); }; /* * Crypto Library RSA driver operations */ struct drvcrypt_rsa { /* Allocates the RSA keypair */ TEE_Result (*alloc_keypair)(struct rsa_keypair *key, size_t size_bits); /* Allocates the RSA public key */ TEE_Result (*alloc_publickey)(struct rsa_public_key *key, size_t size_bits); /* Free RSA public key */ void (*free_publickey)(struct rsa_public_key *key); /* Free RSA keypair */ void (*free_keypair)(struct rsa_keypair *key); /* Generates the RSA keypair */ TEE_Result (*gen_keypair)(struct rsa_keypair *key, size_t size_bits); /* RSA Encryption */ TEE_Result (*encrypt)(struct drvcrypt_rsa_ed *rsa_data); /* RSA Decryption */ TEE_Result (*decrypt)(struct drvcrypt_rsa_ed *rsa_data); struct { /* RSA Sign a message and encode the signature */ TEE_Result (*ssa_sign)(struct drvcrypt_rsa_ssa *ssa_data); /* RSA Encoded Signature Verification */ TEE_Result (*ssa_verify)(struct drvcrypt_rsa_ssa *ssa_data); } optional; }; /* * Register a RSA processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_rsa(const struct drvcrypt_rsa *ops) { return drvcrypt_register(CRYPTO_RSA, (void *)ops); } /* * Signature data */ struct drvcrypt_sign_data { uint32_t algo; /* Operation algorithm */ void *key; /* Public or Private Key */ size_t size_sec; /* Security size in bytes */ struct drvcrypt_buf message; /* Message to sign or signed */ struct drvcrypt_buf signature; /* Signature of the message */ }; /* * Shared Secret data */ struct drvcrypt_secret_data { void *key_priv; /* Private Key */ void *key_pub; /* Public Key */ size_t size_sec; /* Security size in bytes */ struct drvcrypt_buf secret; /* Shared secret */ }; /* * Encrypt/Decrypt data */ struct drvcrypt_ecc_ed { uint32_t algo; /* Operation algorithm */ void *key; /* Public or Private Key */ size_t size_sec; /* Security size in bytes */ struct drvcrypt_buf plaintext; /* Clear text message */ struct drvcrypt_buf ciphertext; /* Encrypted message */ }; /* * Crypto ECC driver operations */ struct drvcrypt_ecc { /* Allocates the ECC keypair */ TEE_Result (*alloc_keypair)(struct ecc_keypair *key, uint32_t type, size_t size_bits); /* Allocates the ECC public key */ TEE_Result (*alloc_publickey)(struct ecc_public_key *key, uint32_t type, size_t size_bits); /* Free ECC public key */ void (*free_publickey)(struct ecc_public_key *key); /* Generates the ECC keypair */ TEE_Result (*gen_keypair)(struct ecc_keypair *key, size_t size_bits); /* ECC Sign a message and returns the signature */ TEE_Result (*sign)(struct drvcrypt_sign_data *sdata); /* ECC Verify a message's signature */ TEE_Result (*verify)(struct drvcrypt_sign_data *sdata); /* ECC Shared Secret */ TEE_Result (*shared_secret)(struct drvcrypt_secret_data *sdata); /* ECC Encrypt */ TEE_Result (*encrypt)(struct drvcrypt_ecc_ed *cdata); /* ECC Decrypt */ TEE_Result (*decrypt)(struct drvcrypt_ecc_ed *cdata); }; /* * Register an ECC processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_ecc(struct drvcrypt_ecc *ops) { return drvcrypt_register(CRYPTO_ECC, (void *)ops); } /* * Crypto Library DH driver operations */ struct drvcrypt_dh { /* Allocates the DH keypair */ TEE_Result (*alloc_keypair)(struct dh_keypair *key, size_t size_bits); /* Generates the DH keypair */ TEE_Result (*gen_keypair)(struct dh_keypair *key, struct bignum *q, size_t size_bits); /* DH Shared Secret */ TEE_Result (*shared_secret)(struct drvcrypt_secret_data *sdata); }; /* * Register a DH processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_dh(struct drvcrypt_dh *ops) { return drvcrypt_register(CRYPTO_DH, (void *)ops); } /* * Crypto Library DSA driver operations */ struct drvcrypt_dsa { /* Allocates the DSA keypair */ TEE_Result (*alloc_keypair)(struct dsa_keypair *key, size_t l_bits, size_t n_bits); /* Allocates the DSA public key */ TEE_Result (*alloc_publickey)(struct dsa_public_key *key, size_t l_bits, size_t n_bits); /* Generates the DSA keypair */ TEE_Result (*gen_keypair)(struct dsa_keypair *key, size_t l_bits, size_t n_bits); /* DSA Sign a message and returns the signature */ TEE_Result (*sign)(struct drvcrypt_sign_data *sdata, size_t l_bytes, size_t n_bytes); /* DSA Verify a message's signature */ TEE_Result (*verify)(struct drvcrypt_sign_data *sdata, size_t l_bytes, size_t n_bytes); }; /* * Register a DSA processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_dsa(struct drvcrypt_dsa *ops) { return drvcrypt_register(CRYPTO_DSA, (void *)ops); } /* * Crypto Library Montgomery driver operations */ struct drvcrypt_montgomery { /* Allocates the Montgomery key pair */ TEE_Result (*alloc_keypair)(struct montgomery_keypair *key, size_t size_bits); /* Generates the Montgomery key pair */ TEE_Result (*gen_keypair)(struct montgomery_keypair *key, size_t key_size); /* Montgomery Shared Secret */ TEE_Result (*shared_secret)(struct drvcrypt_secret_data *sdata); }; /* * Register a X25519 processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_x25519(struct drvcrypt_montgomery *ops) { return drvcrypt_register(CRYPTO_X25519, (void *)ops); } /* * Register a X448 processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_x448(struct drvcrypt_montgomery *ops) { return drvcrypt_register(CRYPTO_X448, (void *)ops); } #endif /* __DRVCRYPT_ACIPHER_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_asn1_oid.h000066400000000000000000000104771464416617300267050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Brief Definition of the cryptographic algorthim's OID in the * ASN1 String format. * Definition of the ASN1 DER tags. * * Computer Security Objects Register * http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html */ #ifndef __ASN1_OID_H__ #define __ASN1_OID_H__ #include #include /* * ASN1 Tags */ #define DRVCRYPT_ASN1_CONSTRUCTED 0x20 #define DRVCRYPT_ASN1_SEQUENCE 0x10 #define DRVCRYPT_ASN1_OID 0x06 #define DRVCRYPT_ASN1_NULL 0x05 #define DRVCRYPT_ASN1_OCTET_STRING 0x04 /* * OID Top Level = first two Node (Standard and Registration-authority) * * iso(1) member-body(2) * iso(1) identified-organization(3) * joint-iso-itu-t(2) country(16) */ #define DRVCRYPT_OID_ISO_MEMBER_BODY "\x2a" #define DRVCRYPT_OID_ISO_ID_ORG "\x2b" #define DRVCRYPT_OID_ISO_ITU_COUNTRY "\x60" /* * ISO Member body * * us(840) * us(840) rsadsi(113549) */ #define DRVCRYPT_OID_MB_US "\x86\x48" #define DRVCRYPT_OID_MB_US_RSADSI DRVCRYPT_OID_MB_US "\x86\xF7\x0D" /* * ISO Identified organization * * oiw(14) * oiw(14) secsig(3) */ #define DRVCRYPT_OID_IO_OIW "\x0e" #define DRVCRYPT_OID_IO_OIW_SECSIG DRVCRYPT_OID_IO_OIW "\x03" /* * ISO ITU OID * * organization(1) * organization(1) gov(101) */ #define DRVCRYPT_OID_ITU_ORG "\x01" #define DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_ITU_ORG "\x65" /* * Digest Algorithm * * digestAlgorithm(2) * csor(3) nistalgotrithm(4) */ #define DRVCRYPT_OID_DIGEST "\x02" #define DRVCRYPT_OID_DIGEST_CSOR_NIST "\x03\x04" /* * Definition of the Hash OID String * * id-md5 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 * } * id-sha1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 * } * id-sha224 OBJECT IDENTIFIER ::= { * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) * csor(3) nistalgorithm(4) hashalgs(2) 4 * } * id-sha256 OBJECT IDENTIFIER ::= { * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) * csor(3) nistalgorithm(4) hashalgs(2) 1 * } * id-sha384 OBJECT IDENTIFIER ::= { * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) * csor(3) nistalgorithm(4) hashalgs(2) 2 * } * id-sha512 OBJECT IDENTIFIER ::= { * joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) * csor(3) nistalgorithm(4) hashalgs(2) 3 * } * */ #define DRVCRYPT_OID_ID_MD5 \ DRVCRYPT_OID_ISO_MEMBER_BODY DRVCRYPT_OID_MB_US_RSADSI \ DRVCRYPT_OID_DIGEST "\x05" #define DRVCRYPT_OID_ID_SHA1 \ DRVCRYPT_OID_ISO_ID_ORG DRVCRYPT_OID_IO_OIW_SECSIG DRVCRYPT_OID_DIGEST \ "\x1a" #define DRVCRYPT_OID_ID_SHA224 \ DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ DRVCRYPT_OID_DIGEST "\x04" #define DRVCRYPT_OID_ID_SHA256 \ DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ DRVCRYPT_OID_DIGEST "\x01" #define DRVCRYPT_OID_ID_SHA384 \ DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ DRVCRYPT_OID_DIGEST "\x02" #define DRVCRYPT_OID_ID_SHA512 \ DRVCRYPT_OID_ISO_ITU_COUNTRY DRVCRYPT_OID_MB_US \ DRVCRYPT_OID_ITU_ORG_GOV DRVCRYPT_OID_DIGEST_CSOR_NIST \ DRVCRYPT_OID_DIGEST "\x03" #define DRVCRYPT_OID_LEN(_id) (sizeof(_id) - 1) /* * Definition of the ASN1 OID structure */ struct drvcrypt_oid { const char *asn1; /* OID ASN1 string */ const size_t asn1_length; /* OID ASN1 string length */ }; /* * Hash OID constant array */ extern const struct drvcrypt_oid drvcrypt_hash_oid[]; /* * Return the Hash OID value registered in the Hash OID table. * * @algo Hash algorithm identifier */ const struct drvcrypt_oid *drvcrypt_get_alg_hash_oid(uint32_t algo); #endif /* __ASN1_OID_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_authenc.h000066400000000000000000000062051464416617300266310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved * * Authenticated Encryption interface calling the crypto driver */ #ifndef __DRVCRYPT_AUTHENC_H__ #define __DRVCRYPT_AUTHENC_H__ #include #include /* * Authenticated Encryption operation context */ struct crypto_authenc { struct crypto_authenc_ctx authenc_ctx; /* Crypto authenc API context */ void *ctx; /* Authenc context */ struct drvcrypt_authenc *op; /* Reference to the operation */ }; /* * Authenticated Encryption algorithm initialization data */ struct drvcrypt_authenc_init { void *ctx; /* Software context */ bool encrypt; /* Encrypt or decrypt direction */ struct drvcrypt_buf key; /* First key */ struct drvcrypt_buf nonce; /* Nonce */ size_t tag_len; /* Tag length */ size_t aad_len; /* Additional Authenticated Data length */ size_t payload_len; /* Payload length */ }; /* * Authenticated Encryption algorithm update_aad data */ struct drvcrypt_authenc_update_aad { void *ctx; /* Software context */ bool encrypt; /* Encrypt or decrypt direction */ struct drvcrypt_buf aad; /* Additional Authenticated Data buffer */ }; /* * Authenticated Encryption algorithm update_aad data */ struct drvcrypt_authenc_update_payload { void *ctx; /* Software context */ bool encrypt; /* Encrypt or decrypt direction */ struct drvcrypt_buf src; /* Buffer source (message or cipher) */ struct drvcrypt_buf dst; /* Buffer destination (cipher or message) */ }; /* * Authenticated Encryption algorithm final data */ struct drvcrypt_authenc_final { void *ctx; /* Software context */ bool encrypt; /* Encrypt or decrypt direction */ struct drvcrypt_buf src; /* Buffer source (message or cipher) */ struct drvcrypt_buf dst; /* Buffer destination (cipher or message) */ struct drvcrypt_buf tag; /* Tag buffer */ }; /* * Crypto library authenc driver operations */ struct drvcrypt_authenc { /* Allocate context */ TEE_Result (*alloc_ctx)(void **ctx, uint32_t algo); /* Free context */ void (*free_ctx)(void *ctx); /* Initialize the authenc operation */ TEE_Result (*init)(struct drvcrypt_authenc_init *dinit); /* Update the authenc operation with associated data */ TEE_Result (*update_aad)(struct drvcrypt_authenc_update_aad *dupdate); /* Update the authenc operation with payload data */ TEE_Result (*update_payload)(struct drvcrypt_authenc_update_payload *d); /* Update (or not) with payload data and get tag for encrypt op. */ TEE_Result (*enc_final)(struct drvcrypt_authenc_final *dfinal); /* Update (or not) with payload data and verify tag for decrypt op. */ TEE_Result (*dec_final)(struct drvcrypt_authenc_final *dfinal); /* Finalize the authenc operation */ void (*final)(void *ctx); /* Copy authenc context */ void (*copy_state)(void *dst_ctx, void *src_ctx); }; /* * Register an authenc processing driver in the crypto API * * @ops - Driver operations */ static inline TEE_Result drvcrypt_register_authenc(struct drvcrypt_authenc *ops) { return drvcrypt_register(CRYPTO_AUTHENC, (void *)ops); } #endif /* __DRVCRYPT_AUTHENC_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_cipher.h000066400000000000000000000036541464416617300264610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Cipher interface calling the crypto driver. */ #ifndef __DRVCRYPT_CIPHER_H__ #define __DRVCRYPT_CIPHER_H__ #include #include /* * Cipher operation context */ struct crypto_cipher { struct crypto_cipher_ctx cipher_ctx; /* Crypto cipher API context */ void *ctx; /* Cipher context */ struct drvcrypt_cipher *op; /* Reference to the operation */ }; /* * Cipher algorithm initialization data */ struct drvcrypt_cipher_init { void *ctx; /* Software context */ bool encrypt; /* Encrypt or decrypt direction */ struct drvcrypt_buf key1; /* First key */ struct drvcrypt_buf key2; /* Second key */ struct drvcrypt_buf iv; /* Initial vector */ }; /* * Cipher algorithm update data */ struct drvcrypt_cipher_update { void *ctx; /* Software context */ bool encrypt; /* Encrypt or decrypt direction */ bool last; /* Last block to handle */ struct drvcrypt_buf src; /* Buffer source (message or cipher) */ struct drvcrypt_buf dst; /* Buffer dest (message or cipher) */ }; /* * Crypto library cipher driver operations */ struct drvcrypt_cipher { /* Allocate context */ TEE_Result (*alloc_ctx)(void **ctx, uint32_t algo); /* Free context */ void (*free_ctx)(void *ctx); /* Initialize the cipher operation */ TEE_Result (*init)(struct drvcrypt_cipher_init *dinit); /* Update the cipher operation */ TEE_Result (*update)(struct drvcrypt_cipher_update *dupdate); /* Finalize the cipher operation */ void (*final)(void *ctx); /* Copy cipher context */ void (*copy_state)(void *dst_ctx, void *src_ctx); }; /* * Register a cipher processing driver in the crypto API * * @ops - Driver operations */ static inline TEE_Result drvcrypt_register_cipher(struct drvcrypt_cipher *ops) { return drvcrypt_register(CRYPTO_CIPHER, (void *)ops); } #endif /* __DRVCRYPT_CIPHER_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_hash.h000066400000000000000000000013561464416617300261270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Brief Hash interface calling the HW crypto driver. */ #ifndef __DRVCRYPT_HASH_H__ #define __DRVCRYPT_HASH_H__ #include #include #include /* * Crypto Library Hash driver allocation function prototype */ typedef TEE_Result (*hw_hash_allocate)(struct crypto_hash_ctx **ctx, uint32_t algo); /* * Register a hash processing driver in the crypto API * * @allocate - Callback for driver context allocation in the crypto layer */ static inline TEE_Result drvcrypt_register_hash(hw_hash_allocate allocate) { return drvcrypt_register(CRYPTO_HASH, (void *)allocate); } #endif /* __DRVCRYPT_HASH_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_mac.h000066400000000000000000000020021464416617300257310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019-2020 NXP * * MAC interface calling the HW crypto driver. */ #ifndef __DRVCRYPT_MAC_H__ #define __DRVCRYPT_MAC_H__ #include #include #include /* * Crypto library HMAC driver allocation function prototype */ typedef TEE_Result (*drvcrypt_mac_allocate)(struct crypto_mac_ctx **ctx, uint32_t algo); /* * Register a HMAC processing driver in the crypto API * * @allocate - Callback for driver context allocation in the crypto layer */ static inline TEE_Result drvcrypt_register_hmac(drvcrypt_mac_allocate allocate) { return drvcrypt_register(CRYPTO_HMAC, (void *)allocate); } /* * Register a CMAC processing driver in the crypto API * * @allocate - Callback for driver context allocation in the crypto layer */ static inline TEE_Result drvcrypt_register_cmac(drvcrypt_mac_allocate allocate) { return drvcrypt_register(CRYPTO_CMAC, (void *)allocate); } #endif /* __DRVCRYPT_MAC_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/include/drvcrypt_math.h000066400000000000000000000021501464416617300261260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2020 NXP * * Brief Cryptographic library using the HW crypto driver. * Mathematical operation using HW if available. */ #ifndef __DRVCRYPT_MATH_H__ #define __DRVCRYPT_MATH_H__ #include /* * Binary Modular operation data */ struct drvcrypt_mod_op { struct drvcrypt_buf n; /* Modulus N */ struct drvcrypt_buf a; /* Operand A */ struct drvcrypt_buf b; /* Operand B */ struct drvcrypt_buf result; /* Result of operation */ }; /* * Operation (A xor B) mod N * * @data [in/out] Data operation */ TEE_Result drvcrypt_xor_mod_n(struct drvcrypt_mod_op *data); /* * Crypto Library Binaries Modular driver operations */ struct drvcrypt_math { /* (A xor B) mod N */ TEE_Result (*xor_mod_n)(struct drvcrypt_mod_op *op_data); }; /* * Register a mathematical processing driver in the crypto API * * @ops - Driver operations in the HW layer */ static inline TEE_Result drvcrypt_register_math(const struct drvcrypt_math *ops) { return drvcrypt_register(CRYPTO_MATH, (void *)ops); } #endif /* __DRVCRYPT_MATH_H__ */ optee_os-4.3.0/core/drivers/crypto/crypto_api/mac/000077500000000000000000000000001464416617300222065ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/mac/mac.c000066400000000000000000000014661464416617300231210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * Crypto MAC interface implementation to enable HW driver. */ #include #include #include #include #include TEE_Result drvcrypt_mac_alloc_ctx(struct crypto_mac_ctx **ctx, uint32_t algo) { TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; drvcrypt_mac_allocate mac_alloc = NULL; unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo); CRYPTO_TRACE("mac alloc_ctx algo 0x%" PRIX32, algo); assert(ctx); if (algo_id >= TEE_MAIN_ALGO_MD5 && algo_id <= TEE_MAIN_ALGO_SHA512) mac_alloc = drvcrypt_get_ops(CRYPTO_HMAC); else mac_alloc = drvcrypt_get_ops(CRYPTO_CMAC); if (mac_alloc) ret = mac_alloc(ctx, algo); CRYPTO_TRACE("mac alloc_ctx ret 0x%" PRIX32, ret); return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/mac/sub.mk000066400000000000000000000000201464416617300233200ustar00rootroot00000000000000srcs-y += mac.c optee_os-4.3.0/core/drivers/crypto/crypto_api/math/000077500000000000000000000000001464416617300223775ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/math/modulus.c000066400000000000000000000030731464416617300242360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * Brief Cryptographic library using the NXP CAAM driver. * Mathematical Modulus operation implementation. */ #include #include #include #include TEE_Result drvcrypt_xor_mod_n(struct drvcrypt_mod_op *data) { TEE_Result ret = TEE_ERROR_GENERIC; struct drvcrypt_math *math = NULL; if (!data->a.data || !data->a.length || !data->b.data || !data->b.length || !data->result.data || !data->result.length || !data->n.length) return TEE_ERROR_BAD_PARAMETERS; if (data->result.length < data->n.length) return TEE_ERROR_BAD_PARAMETERS; math = drvcrypt_get_ops(CRYPTO_MATH); if (math) { /* Operation done by Math driver */ ret = math->xor_mod_n(data); } else { /* Operation done by Software */ size_t min = 0, idx = 0; /* Calculate the minimum size to do A xor B */ min = MIN(data->a.length, data->b.length); min = MIN(min, data->n.length); for (; idx < min; idx++) data->result.data[idx] = data->a.data[idx] ^ data->b.data[idx]; if (min < data->n.length) { /* Complete result to make a N modulus number */ if (data->a.length > min) { memcpy(&data->result.data[idx], &data->a.data[idx], data->n.length - min); } else if (data->b.length > min) { memcpy(&data->result.data[idx], &data->b.data[idx], data->n.length - min); } else { memset(&data->result.data[idx], 0, data->n.length - min); } } ret = TEE_SUCCESS; } return ret; } optee_os-4.3.0/core/drivers/crypto/crypto_api/math/sub.mk000066400000000000000000000000241464416617300235150ustar00rootroot00000000000000srcs-y += modulus.c optee_os-4.3.0/core/drivers/crypto/crypto_api/oid/000077500000000000000000000000001464416617300222215ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/crypto_api/oid/hash_oid.c000066400000000000000000000020151464416617300241410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * Brief Definition of the Hash's OID */ /* Driver Crypto includes */ #include #include /* * Hash OID values */ const struct drvcrypt_oid drvcrypt_hash_oid[] = { /* empty entry */ { NULL, 0 }, /* MD5 */ { DRVCRYPT_OID_ID_MD5, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_MD5) }, /* SHA1 */ { DRVCRYPT_OID_ID_SHA1, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA1) }, /* SHA224 */ { DRVCRYPT_OID_ID_SHA224, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA224) }, /* SHA256 */ { DRVCRYPT_OID_ID_SHA256, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA256) }, /* SHA384 */ { DRVCRYPT_OID_ID_SHA384, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA384) }, /* SHA512 */ { DRVCRYPT_OID_ID_SHA512, DRVCRYPT_OID_LEN(DRVCRYPT_OID_ID_SHA512) }, }; const struct drvcrypt_oid *drvcrypt_get_alg_hash_oid(uint32_t algo) { uint32_t main_alg = TEE_ALG_GET_MAIN_ALG(algo); if (main_alg < ARRAY_SIZE(drvcrypt_hash_oid)) return &drvcrypt_hash_oid[main_alg]; return NULL; } optee_os-4.3.0/core/drivers/crypto/crypto_api/oid/sub.mk000066400000000000000000000000251464416617300233400ustar00rootroot00000000000000srcs-y += hash_oid.c optee_os-4.3.0/core/drivers/crypto/crypto_api/sub.mk000066400000000000000000000004461464416617300225740ustar00rootroot00000000000000srcs-y += drvcrypt.c subdirs-y += math subdirs-$(CFG_CRYPTO_DRV_HASH) += hash subdirs-$(CFG_CRYPTO_DRV_ACIPHER) += acipher subdirs-$(CFG_CRYPTO_DRV_ACIPHER) += oid subdirs-$(CFG_CRYPTO_DRV_CIPHER) += cipher subdirs-$(CFG_CRYPTO_DRV_MAC) += mac subdirs-$(CFG_CRYPTO_DRV_AUTHENC) += authenc optee_os-4.3.0/core/drivers/crypto/hisilicon/000077500000000000000000000000001464416617300212565ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/hisilicon/crypto.mk000066400000000000000000000007061464416617300231320ustar00rootroot00000000000000ifeq ($(CFG_HISILICON_CRYPTO_DRIVER), y) $(call force,CFG_CRYPTO_DRIVER,y) CFG_CRYPTO_DRIVER_DEBUG ?= 0 $(call force, CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER) $(call force, CFG_CRYPTO_DRV_HASH,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER) $(call force, CFG_CRYPTO_DRV_MAC,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER) ifeq ($(CFG_HISILICON_ACC_V3), y) $(call force, CFG_CRYPTO_DRV_DH,y,Mandated by CFG_HISILICON_ACC_V3) endif endif optee_os-4.3.0/core/drivers/crypto/hisilicon/hisi_qm.c000066400000000000000000000524161464416617300230630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 HiSilicon Limited. * Kunpeng hardware accelerator queue management module. */ #include "hisi_qm.h" #define QM_FVT_CFG_RDY_BIT 0x1 /* Doorbell */ #define QM_DOORBELL_SQ_CQ_BASE 0x1000 #define QM_DB_CMD_SHIFT 12 #define QM_DB_RAND_DATA_SHIFT 16 #define QM_DB_INDEX_SHIFT 32 #define QM_DB_PRIORITY_SHIFT 48 #define QM_DB_RAND_DATA 0x5a #define QM_DOORBELL_CMD_SQ 0 #define QM_DOORBELL_CMD_CQ 1 /* Mailbox */ #define QM_MAILBOX_BASE 0x300 #define QM_MAILBOX_DATA_ADDR_L 0x304 #define QM_MAILBOX_DATA_ADDR_H 0x308 #define QM_MB_BUSY_SHIFT 13 #define QM_MB_BUSY_BIT BIT32(QM_MB_BUSY_SHIFT) #define QM_MB_OP_SHIFT 14 #define QM_MB_OP_WR 0 #define QM_MB_OP_RD 1 #define QM_MB_STATUS_MASK GENMASK_32(12, 9) #define QM_MB_WAIT_READY_CNT 10 #define QM_MB_WAIT_MAX_CNT 21000 #define QM_MB_WAIT_PERIOD 200 /* XQC_VFT */ #define QM_VFT_CFG_OP_ENABLE 0x100054 #define QM_VFT_CFG_OP_WR 0x100058 #define QM_VFT_CFG_TYPE 0x10005c #define QM_VFT_CFG_ADDRESS 0x100060 #define QM_VFT_CFG_DATA_L 0x100064 #define QM_VFT_CFG_DATA_H 0x100068 #define QM_VFT_CFG_RDY 0x10006c #define QM_SQC_VFT 0 #define QM_CQC_VFT 1 #define QM_SQC_VFT_START_SQN_SHIFT 28 #define QM_SQC_VFT_VALID BIT64(44) #define QM_SQC_VFT_SQ_NUM_SHIFT 45 #define QM_CQC_VFT_VALID BIT(28) #define QM_VFT_WRITE 0 #define QM_VFT_READ 1 #define QM_SQC_VFT_BASE_MASK 0x3ff #define QM_SQC_VFT_NUM_MASK 0x3ff /* QM INIT */ #define QM_MEM_START_INIT 0x100040 #define QM_MEM_INIT_DONE 0x100044 #define QM_VF_AEQ_INT_MASK 0x4 #define QM_VF_AEQ_INT_MASK_EN 0x1 #define QM_VF_EQ_INT_MASK 0xc #define QM_VF_EQ_INT_MASK_EN 0x1 #define QM_ARUSER_M_CFG_1 0x100088 #define QM_ARUSER_M_CFG_ENABLE 0x100090 #define QM_AWUSER_M_CFG_1 0x100098 #define QM_AWUSER_M_CFG_ENABLE 0x1000a0 #define QM_AXUSER_CFG 0x40001070 #define AXUSER_M_CFG_ENABLE 0x7ffffc #define QM_AXI_M_CFG 0x1000ac #define AXI_M_CFG 0xffff #define QM_PEH_AXUSER_CFG 0x1000cc #define PEH_AXUSER_CFG 0x400801 #define QM_CACHE_CTL 0x100050 #define QM_CACHE_CFG 0x4893 #define QM_CACHE_WB_START 0x204 #define QM_CACHE_WB_DONE 0x208 #define QM_PM_CTRL0 0x100148 #define QM_IDLE_DISABLE BIT(9) #define QM_DB_TIMEOUT_CFG 0x100074 #define QM_DB_TIMEOUT_SET 0x1fffff /* XQC shift */ #define QM_SQ_SQE_SIZE_SHIFT 12 #define QM_SQ_ORDER_SHIFT 4 #define QM_SQ_TYPE_SHIFT 8 #define QM_CQE_SIZE 4 #define QM_CQ_CQE_SIZE_SHIFT 12 /* CQE */ #define QM_CQE_PHASE(cqe) (((cqe)->w7) & QM_FVT_CFG_RDY_BIT) enum qm_mailbox_common_cmd { QM_MB_CMD_SQC = 0x0, QM_MB_CMD_CQC, QM_MB_CMD_EQC, QM_MB_CMD_AEQC, QM_MB_CMD_SQC_BT, QM_MB_CMD_CQC_BT, QM_MB_CMD_SQC_VFT, }; enum qm_mailbox_cmd_v3 { QM_MB_CM_CLOSE_QM = 0x7, QM_MB_CMD_CLOSE_QP, QM_MB_CMD_FLUSH_QM, QM_MB_CMD_FLUSH_QP, QM_MB_CMD_SRC = 0xc, QM_MB_CMD_DST, QM_MB_CMD_STOP_QM, }; struct qm_mailbox { union { struct { uint16_t w0; uint16_t queue; uint32_t base_l; uint32_t base_h; uint32_t token; }; uint64_t x[2]; }; }; struct qm_dfx_registers { const char *reg_name; uint32_t reg_offset; }; static const struct qm_dfx_registers qm_dfx_regs[] = { { .reg_name = "QM_ECC_1BIT_CNT ", .reg_offset = 0x104000 }, { .reg_name = "QM_ECC_MBIT_CNT ", .reg_offset = 0x104008 }, { .reg_name = "QM_DFX_MB_CNT ", .reg_offset = 0x104018 }, { .reg_name = "QM_DFX_DB_CNT ", .reg_offset = 0x104028 }, { .reg_name = "QM_DFX_SQE_CNT ", .reg_offset = 0x104038 }, { .reg_name = "QM_DFX_CQE_CNT ", .reg_offset = 0x104048 }, { .reg_name = "QM_DFX_SEND_SQE_TO_ACC_CNT", .reg_offset = 0x104050 }, { .reg_name = "QM_DFX_WB_SQE_FROM_ACC_CNT", .reg_offset = 0x104058 }, { .reg_name = "QM_DFX_ACC_FINISH_CNT ", .reg_offset = 0x104060 }, { .reg_name = "QM_DFX_CQE_ERR_CNT ", .reg_offset = 0x1040b4 }, { } }; void hisi_qm_get_version(struct hisi_qm *qm) { qm->version = io_read32(qm->io_base + HISI_QM_REVISON_ID_BASE) & HISI_QM_REVISON_ID_MASK; } static void qm_db(struct hisi_qm *qm, uint16_t qn, uint8_t cmd, uint16_t index, uint8_t priority) { uint64_t doorbell = 0; doorbell = qn | SHIFT_U64(cmd, QM_DB_CMD_SHIFT) | SHIFT_U64(QM_DB_RAND_DATA, QM_DB_RAND_DATA_SHIFT) | SHIFT_U64(index, QM_DB_INDEX_SHIFT) | SHIFT_U64(priority, QM_DB_PRIORITY_SHIFT); io_write64(qm->io_base + QM_DOORBELL_SQ_CQ_BASE, doorbell); } static void qm_mb_write(struct hisi_qm *qm, struct qm_mailbox *mb) { vaddr_t dst = qm->io_base + QM_MAILBOX_BASE; write_64bit_pair(dst, mb->x[1], mb->x[0]); dsb_osh(); } static void qm_mb_read(struct hisi_qm *qm, struct qm_mailbox *mb) { vaddr_t mb_base = qm->io_base + QM_MAILBOX_BASE; read_64bit_pair(mb_base, mb->x + 1, mb->x); dsb_osh(); } static enum hisi_drv_status qm_wait_mb_ready(struct hisi_qm *qm) { struct qm_mailbox mb = { }; uint32_t timeout = 0; timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_READY_CNT); while (!timeout_elapsed(timeout)) { /* 128 bits should be read from hardware at one time*/ qm_mb_read(qm, &mb); if (!(mb.w0 & QM_MB_BUSY_BIT)) return HISI_QM_DRVCRYPT_NO_ERR; } EMSG("QM mailbox is busy to start!"); return HISI_QM_DRVCRYPT_EBUSY; } static enum hisi_drv_status qm_wait_mb_finish(struct hisi_qm *qm, struct qm_mailbox *mb) { uint32_t timeout = 0; timeout = timeout_init_us(QM_MB_WAIT_PERIOD * QM_MB_WAIT_MAX_CNT); while (!timeout_elapsed(timeout)) { qm_mb_read(qm, mb); if (!(mb->w0 & QM_MB_BUSY_BIT)) { if (mb->w0 & QM_MB_STATUS_MASK) { EMSG("QM mailbox operation failed!"); return HISI_QM_DRVCRYPT_EIO; } else { return HISI_QM_DRVCRYPT_NO_ERR; } } } return HISI_QM_DRVCRYPT_ETMOUT; } static void qm_mb_init(struct qm_mailbox *mb, uint8_t cmd, uint64_t base, uint16_t qnum, uint8_t op) { mb->w0 = cmd | SHIFT_U32(op, QM_MB_OP_SHIFT) | QM_MB_BUSY_BIT; mb->queue = qnum; reg_pair_from_64(base, &mb->base_h, &mb->base_l); mb->token = 0; } static enum hisi_drv_status qm_mb_nolock(struct hisi_qm *qm, struct qm_mailbox *mb) { if (qm_wait_mb_ready(qm)) return HISI_QM_DRVCRYPT_EBUSY; qm_mb_write(qm, mb); return qm_wait_mb_finish(qm, mb); } static enum hisi_drv_status hisi_qm_mb_write(struct hisi_qm *qm, uint8_t cmd, uintptr_t dma_addr, uint16_t qnum) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct qm_mailbox mb = { }; qm_mb_init(&mb, cmd, dma_addr, qnum, QM_MB_OP_WR); mutex_lock(&qm->mailbox_lock); ret = qm_mb_nolock(qm, &mb); mutex_unlock(&qm->mailbox_lock); return ret; } static enum hisi_drv_status hisi_qm_mb_read(struct hisi_qm *qm, uint64_t *base, uint8_t cmd, uint16_t qnum) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct qm_mailbox mb = { }; qm_mb_init(&mb, cmd, 0, qnum, QM_MB_OP_RD); mutex_lock(&qm->mailbox_lock); ret = qm_mb_nolock(qm, &mb); mutex_unlock(&qm->mailbox_lock); if (ret) return ret; reg_pair_from_64(*base, &mb.base_h, &mb.base_l); return HISI_QM_DRVCRYPT_NO_ERR; } static void qm_cfg_vft_data(struct hisi_qm *qm, uint8_t vft_type, uint32_t base, uint32_t number) { uint32_t data_h = 0; uint32_t data_l = 0; uint64_t data = 0; switch (vft_type) { case QM_SQC_VFT: data = SHIFT_U64(base, QM_SQC_VFT_START_SQN_SHIFT) | QM_SQC_VFT_VALID | SHIFT_U64((number - 1), QM_SQC_VFT_SQ_NUM_SHIFT); break; case QM_CQC_VFT: data = QM_CQC_VFT_VALID; break; default: panic("Invalid vft type"); } reg_pair_from_64(data, &data_h, &data_l); io_write32(qm->io_base + QM_VFT_CFG_DATA_L, data_l); io_write32(qm->io_base + QM_VFT_CFG_DATA_H, data_h); } static enum hisi_drv_status qm_set_vft_common(struct hisi_qm *qm, uint8_t vft_type, uint32_t function, uint32_t base, uint32_t num) { uint32_t val = 0; if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val, val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, POLL_TIMEOUT)) { EMSG("QM VFT is not ready"); return HISI_QM_DRVCRYPT_EBUSY; } io_write32(qm->io_base + QM_VFT_CFG_OP_WR, QM_VFT_WRITE); io_write32(qm->io_base + QM_VFT_CFG_TYPE, vft_type); io_write32(qm->io_base + QM_VFT_CFG_ADDRESS, function); qm_cfg_vft_data(qm, vft_type, base, num); io_write32(qm->io_base + QM_VFT_CFG_RDY, 0x0); io_write32(qm->io_base + QM_VFT_CFG_OP_ENABLE, QM_FVT_CFG_RDY_BIT); if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_VFT_CFG_RDY, val, val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, POLL_TIMEOUT)) { EMSG("QM VFT is not ready"); return HISI_QM_DRVCRYPT_EBUSY; } return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status qm_set_xqc_vft(struct hisi_qm *qm, uint32_t function, uint32_t base, uint32_t num) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; int i = 0; for (i = QM_SQC_VFT; i <= QM_CQC_VFT; i++) { ret = qm_set_vft_common(qm, i, function, base, num); if (ret) { EMSG("QM set type %d fail", i); return ret; } } return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status qm_get_vft(struct hisi_qm *qm, uint32_t *base, uint32_t *num) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; uint64_t sqc_vft = 0; ret = hisi_qm_mb_read(qm, &sqc_vft, QM_MB_CMD_SQC_VFT, 0); if (ret) return ret; *base = (sqc_vft >> QM_SQC_VFT_START_SQN_SHIFT) & QM_SQC_VFT_BASE_MASK; *num = ((sqc_vft >> QM_SQC_VFT_SQ_NUM_SHIFT) & QM_SQC_VFT_NUM_MASK) + 1; return HISI_QM_DRVCRYPT_NO_ERR; } static void qp_free(struct hisi_qm *qm, uint32_t id) { struct hisi_qp *qp = &qm->qp_array[id]; free(qp->sqe); free(qp->cqe); } static enum hisi_drv_status qp_alloc(struct hisi_qm *qm, uint32_t id) { size_t sq_size = qm->sqe_size * HISI_QM_Q_DEPTH; size_t cq_size = sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH; struct hisi_qp *qp = &qm->qp_array[id]; enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; qp->sqe = memalign(HISI_QM_ALIGN128, sq_size); if (!qp->sqe) { EMSG("Fail to malloc sq[%"PRIu32"]", id); return HISI_QM_DRVCRYPT_ENOMEM; } qp->sqe_dma = virt_to_phys(qp->sqe); qp->cqe = memalign(HISI_QM_ALIGN32, cq_size); if (!qp->cqe) { EMSG("Fail to malloc cq[%"PRIu32"]", id); ret = HISI_QM_DRVCRYPT_ENOMEM; goto free_sqe; } qp->cqe_dma = virt_to_phys(qp->cqe); qp->qp_id = id; qp->qm = qm; return HISI_QM_DRVCRYPT_NO_ERR; free_sqe: free(qp->sqe); return ret; } static void hisi_qm_free_xqc(struct qm_xqc *xqc) { free(xqc->cqc); free(xqc->sqc); } static void qm_free(struct hisi_qm *qm) { unsigned int i = 0; for (i = 0; i < qm->qp_num; i++) qp_free(qm, i); free(qm->qp_array); hisi_qm_free_xqc(&qm->xqc); hisi_qm_free_xqc(&qm->cfg_xqc); } static enum hisi_drv_status hisi_qm_alloc_xqc(struct qm_xqc *xqc, uint32_t qp_num) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; size_t sqc_size = 0; size_t cqc_size = 0; sqc_size = sizeof(struct qm_sqc) * qp_num; cqc_size = sizeof(struct qm_cqc) * qp_num; xqc->sqc = memalign(HISI_QM_ALIGN32, sqc_size); if (!xqc->sqc) { EMSG("Fail to malloc sqc"); return HISI_QM_DRVCRYPT_ENOMEM; } memset(xqc->sqc, 0, sqc_size); xqc->sqc_dma = virt_to_phys(xqc->sqc); xqc->cqc = memalign(HISI_QM_ALIGN32, cqc_size); if (!xqc->cqc) { EMSG("Fail to malloc cqc"); ret = HISI_QM_DRVCRYPT_ENOMEM; goto free_sqc; } memset(xqc->cqc, 0, cqc_size); xqc->cqc_dma = virt_to_phys(xqc->cqc); return HISI_QM_DRVCRYPT_NO_ERR; free(xqc->cqc); free_sqc: free(xqc->sqc); return ret; } static enum hisi_drv_status qm_alloc(struct hisi_qm *qm) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; int32_t j; uint32_t i; ret = hisi_qm_alloc_xqc(&qm->xqc, qm->qp_num); if (ret) return ret; ret = hisi_qm_alloc_xqc(&qm->cfg_xqc, 1); if (ret) goto free_xqc; qm->qp_array = calloc(qm->qp_num, sizeof(struct hisi_qp)); if (!qm->qp_array) { EMSG("Fail to malloc qp_array"); ret = HISI_QM_DRVCRYPT_ENOMEM; goto free_cfg_xqc; } for (i = 0; i < qm->qp_num; i++) { ret = qp_alloc(qm, i); if (ret) goto free_qp_mem; } return HISI_QM_DRVCRYPT_NO_ERR; free_qp_mem: for (j = (int)i - 1; j >= 0; j--) qp_free(qm, j); free(qm->qp_array); free_cfg_xqc: hisi_qm_free_xqc(&qm->cfg_xqc); free_xqc: hisi_qm_free_xqc(&qm->xqc); return ret; } enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; if (qm->fun_type == HISI_QM_HW_VF) { ret = qm_get_vft(qm, &qm->qp_base, &qm->qp_num); if (ret) { EMSG("Fail to get function vft config"); return ret; } } if (!qm->qp_num || !qm->sqe_size) { EMSG("Invalid QM parameters"); return HISI_QM_DRVCRYPT_EINVAL; } ret = qm_alloc(qm); if (ret) return ret; qm->qp_in_used = 0; qm->qp_idx = 0; mutex_init(&qm->qp_lock); mutex_init(&qm->mailbox_lock); return HISI_QM_DRVCRYPT_NO_ERR; } static void qm_cache_writeback(struct hisi_qm *qm) { uint32_t val = 0; io_write32(qm->io_base + QM_CACHE_WB_START, QM_FVT_CFG_RDY_BIT); if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_CACHE_WB_DONE, val, val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, POLL_TIMEOUT)) panic("QM writeback sqc cache fail"); } void hisi_qm_uninit(struct hisi_qm *qm) { qm_cache_writeback(qm); qm_free(qm); mutex_destroy(&qm->qp_lock); mutex_destroy(&qm->mailbox_lock); } static enum hisi_drv_status qm_hw_mem_reset(struct hisi_qm *qm) { uint32_t val = 0; io_write32(qm->io_base + QM_MEM_START_INIT, QM_FVT_CFG_RDY_BIT); if (IO_READ32_POLL_TIMEOUT(qm->io_base + QM_MEM_INIT_DONE, val, val & QM_FVT_CFG_RDY_BIT, POLL_PERIOD, POLL_TIMEOUT)) return HISI_QM_DRVCRYPT_EBUSY; return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status qm_func_vft_cfg(struct hisi_qm *qm) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; uint32_t q_base = qm->qp_num; uint32_t act_q_num = 0; unsigned int i = 0; unsigned int j = 0; if (!qm->vfs_num) return HISI_QM_DRVCRYPT_NO_ERR; if (qm->vfs_num > HISI_QM_MAX_VFS_NUM) { EMSG("Invalid QM vfs_num"); return HISI_QM_DRVCRYPT_EINVAL; } for (i = 1; i <= qm->vfs_num; i++) { act_q_num = HISI_QM_VF_Q_NUM; ret = qm_set_xqc_vft(qm, i, q_base, act_q_num); if (ret) { for (j = 1; j < i; j++) (void)qm_set_xqc_vft(qm, j, 0, 0); return ret; } q_base += act_q_num; } return HISI_QM_DRVCRYPT_NO_ERR; } enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; if (qm->fun_type == HISI_QM_HW_PF) { ret = qm_hw_mem_reset(qm); if (ret) { EMSG("Fail to reset QM hardware mem"); return ret; } ret = qm_set_xqc_vft(qm, 0, qm->qp_base, qm->qp_num); if (ret) { EMSG("Fail to set PF xqc_vft"); return ret; } ret = qm_func_vft_cfg(qm); if (ret) { EMSG("Fail to set VF xqc_vft"); return ret; } } ret = hisi_qm_mb_write(qm, QM_MB_CMD_SQC_BT, qm->xqc.sqc_dma, 0); if (ret) { EMSG("Fail to set sqc_bt"); return ret; } ret = hisi_qm_mb_write(qm, QM_MB_CMD_CQC_BT, qm->xqc.cqc_dma, 0); if (ret) { EMSG("Fail to set cqc_bt"); return ret; } /* Security mode does not support msi */ io_write32(qm->io_base + QM_VF_AEQ_INT_MASK, QM_VF_AEQ_INT_MASK_EN); io_write32(qm->io_base + QM_VF_EQ_INT_MASK, QM_VF_EQ_INT_MASK_EN); return HISI_QM_DRVCRYPT_NO_ERR; } static void qm_disable_clock_gate(struct hisi_qm *qm) { if (qm->version == HISI_QM_HW_V2) return; io_setbits32(qm->io_base + QM_PM_CTRL0, QM_IDLE_DISABLE); } void hisi_qm_dev_init(struct hisi_qm *qm) { if (qm->fun_type == HISI_QM_HW_VF) return; qm_disable_clock_gate(qm); /* QM user domain */ io_write32(qm->io_base + QM_ARUSER_M_CFG_1, QM_AXUSER_CFG); io_write32(qm->io_base + QM_ARUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE); io_write32(qm->io_base + QM_AWUSER_M_CFG_1, QM_AXUSER_CFG); io_write32(qm->io_base + QM_AWUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE); /* QM cache */ io_write32(qm->io_base + QM_AXI_M_CFG, AXI_M_CFG); if (qm->version == HISI_QM_HW_V2) { /* Disable FLR triggered by BME(bus master enable) */ io_write32(qm->io_base + QM_PEH_AXUSER_CFG, PEH_AXUSER_CFG); /* Set sec sqc and cqc cache wb threshold 4 */ io_write32(qm->io_base + QM_CACHE_CTL, QM_CACHE_CFG); } /* Disable QM ras */ io_write32(qm->io_base + HISI_QM_ABNML_INT_MASK, HISI_QM_ABNML_INT_MASK_CFG); /* Set doorbell timeout to QM_DB_TIMEOUT_SET ns */ io_write32(qm->io_base + QM_DB_TIMEOUT_CFG, QM_DB_TIMEOUT_SET); } static enum hisi_drv_status qm_sqc_cfg(struct hisi_qp *qp) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct hisi_qm *qm = qp->qm; struct qm_sqc *sqc = qm->cfg_xqc.sqc; struct qm_mailbox mb = { }; mutex_lock(&qm->mailbox_lock); memset(sqc, 0, sizeof(struct qm_sqc)); reg_pair_from_64(qp->sqe_dma, &sqc->base_h, &sqc->base_l); sqc->dw3 = (HISI_QM_Q_DEPTH - 1) | SHIFT_U32(qm->sqe_log2_size, QM_SQ_SQE_SIZE_SHIFT); sqc->rand_data = QM_DB_RAND_DATA; sqc->cq_num = qp->qp_id; sqc->w13 = BIT32(QM_SQ_ORDER_SHIFT) | SHIFT_U32(qp->sq_type, QM_SQ_TYPE_SHIFT); qm_mb_init(&mb, QM_MB_CMD_SQC, qm->cfg_xqc.sqc_dma, qp->qp_id, QM_MB_OP_WR); ret = qm_mb_nolock(qm, &mb); mutex_unlock(&qm->mailbox_lock); return ret; } static enum hisi_drv_status qm_cqc_cfg(struct hisi_qp *qp) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct hisi_qm *qm = qp->qm; struct qm_cqc *cqc = qm->cfg_xqc.cqc; struct qm_mailbox mb = { }; mutex_lock(&qm->mailbox_lock); memset(cqc, 0, sizeof(struct qm_cqc)); reg_pair_from_64(qp->cqe_dma, &cqc->base_h, &cqc->base_l); cqc->dw3 = (HISI_QM_Q_DEPTH - 1) | SHIFT_U32(QM_CQE_SIZE, QM_CQ_CQE_SIZE_SHIFT); cqc->rand_data = QM_DB_RAND_DATA; cqc->dw6 = PHASE_DEFAULT_VAL; qm_mb_init(&mb, QM_MB_CMD_CQC, qm->cfg_xqc.cqc_dma, qp->qp_id, QM_MB_OP_WR); ret = qm_mb_nolock(qm, &mb); mutex_unlock(&qm->mailbox_lock); return ret; } struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type) { struct hisi_qp *qp = NULL; int cur_idx = 0; uint32_t i = 0; mutex_lock(&qm->qp_lock); if (qm->qp_in_used == qm->qp_num) { EMSG("All %"PRIu32" queues of QM are busy", qm->qp_num); goto err_proc; } for (i = 0; i < qm->qp_num; i++) { cur_idx = (qm->qp_idx + i) % qm->qp_num; if (!qm->qp_array[cur_idx].used) { qm->qp_array[cur_idx].used = true; qm->qp_idx = cur_idx + 1; break; } } qp = qm->qp_array + cur_idx; memset(qp->cqe, 0, sizeof(struct qm_cqe) * HISI_QM_Q_DEPTH); qp->sq_type = sq_type; qp->sq_tail = 0; qp->cq_head = 0; qp->cqc_phase = true; if (qm_sqc_cfg(qp)) { EMSG("Fail to set qp[%"PRIu32"] sqc", qp->qp_id); goto err_qp_release; } if (qm_cqc_cfg(qp)) { EMSG("Fail to set qp[%"PRIu32"] cqc", qp->qp_id); goto err_qp_release; } qm->qp_in_used++; mutex_unlock(&qm->qp_lock); return qp; err_qp_release: qp->used = false; err_proc: qp->sq_type = 0; qp->cqc_phase = false; mutex_unlock(&qm->qp_lock); return NULL; } void hisi_qm_release_qp(struct hisi_qp *qp) { struct hisi_qm *qm = NULL; if (!qp) { EMSG("QP is NULL"); return; } qm = qp->qm; mutex_lock(&qm->qp_lock); qm->qp_in_used--; qp->used = false; mutex_unlock(&qm->qp_lock); } static void qm_sq_tail_update(struct hisi_qp *qp) { if (qp->sq_tail == HISI_QM_Q_DEPTH - 1) qp->sq_tail = 0; else qp->sq_tail++; } /* * One task thread will just bind to one hardware queue, and * hardware does not support msi. So we have no lock here. */ enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct hisi_qm *qm = NULL; void *sqe = NULL; if (!qp) { EMSG("QP is NULL"); return HISI_QM_DRVCRYPT_EINVAL; } qm = qp->qm; ret = qm->dev_status_check(qm); if (ret) return ret; sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * qp->sq_tail); memset(sqe, 0, qm->sqe_size); ret = qp->fill_sqe(sqe, msg); if (ret) { EMSG("Fail to fill sqe"); return ret; } qm_sq_tail_update(qp); dsb(); qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_SQ, qp->sq_tail, 0); return HISI_QM_DRVCRYPT_NO_ERR; } static void qm_cq_head_update(struct hisi_qp *qp) { if (qp->cq_head == HISI_QM_Q_DEPTH - 1) { qp->cqc_phase = !qp->cqc_phase; qp->cq_head = 0; } else { qp->cq_head++; } } static enum hisi_drv_status hisi_qp_recv(struct hisi_qp *qp, void *msg) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct hisi_qm *qm = qp->qm; struct qm_cqe *cqe = NULL; void *sqe = NULL; ret = qm->dev_status_check(qm); if (ret) return ret; cqe = qp->cqe + qp->cq_head; if (QM_CQE_PHASE(cqe) == qp->cqc_phase) { dsb_osh(); sqe = (void *)((vaddr_t)qp->sqe + qm->sqe_size * cqe->sq_head); ret = qp->parse_sqe(sqe, msg); qm_cq_head_update(qp); qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ, qp->cq_head, 0); if (ret) { EMSG("Fail to parse sqe"); return ret; } } else { return HISI_QM_DRVCRYPT_NO_ERR; } return HISI_QM_DRVCRYPT_RECV_DONE; } static void qm_dfx_dump(struct hisi_qm *qm) { const struct qm_dfx_registers *regs = qm_dfx_regs; __maybe_unused uint32_t val = 0; if (qm->fun_type == HISI_QM_HW_VF) return; while (regs->reg_name) { val = io_read32(qm->io_base + regs->reg_offset); EMSG("%s= 0x%" PRIx32, regs->reg_name, val); regs++; } } enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; uint32_t timeout = 0; if (!qp || !qp->qm || !msg) { EMSG("Invalid qp recv sync parameters"); return HISI_QM_DRVCRYPT_EINVAL; } timeout = timeout_init_us(QM_SINGLE_WAIT_TIME * HISI_QM_RECV_SYNC_TIMEOUT); while (!timeout_elapsed(timeout)) { ret = hisi_qp_recv(qp, msg); if (ret) { if (ret != HISI_QM_DRVCRYPT_RECV_DONE) { EMSG("QM recv task error"); qm_dfx_dump(qp->qm); return ret; } else { return HISI_QM_DRVCRYPT_NO_ERR; } } } EMSG("QM recv task timeout"); qm_dfx_dump(qp->qm); return HISI_QM_DRVCRYPT_ETMOUT; } optee_os-4.3.0/core/drivers/crypto/hisilicon/hisi_qm.h000066400000000000000000000132711464416617300230640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022-2023, Huawei Technologies Co., Ltd */ #ifndef __HISI_QM_H__ #define __HISI_QM_H__ #include #include #include #include #include #include #include #include #include #define HISI_QM_HW_V2 0x21 #define HISI_QM_HW_V3 0x30 #define HISI_QM_MAX_VFS_NUM 63 #define HISI_QM_PF_Q_BASE 0 #define HISI_QM_PF_Q_NUM 64 #define HISI_QM_VF_Q_NUM 15 #define HISI_QM_Q_DEPTH 8 #define PHASE_DEFAULT_VAL 0x1 #define HISI_QM_ABNML_INT_MASK 0x100004 #define HISI_QM_ABNML_INT_MASK_CFG 0x7fff #define HISI_QM_ABNML_INT_SRC 0x100000 #define HISI_QM_HPRE_NFE_INT_MASK 0x6fb7 #define HISI_QM_SEC_NFE_INT_MASK 0x6ff7 #define HISI_QM_INVALID_DB BIT(12) #define HISI_QM_REVISON_ID_BASE 0x1000dc #define HISI_QM_REVISON_ID_MASK GENMASK_32(7, 0) #define POLL_PERIOD 10 #define POLL_TIMEOUT 1000 #define HISI_QM_RECV_SYNC_TIMEOUT 0xfffff #define HISI_QM_ALIGN128 128 #define HISI_QM_ALIGN32 32 #define QM_SINGLE_WAIT_TIME 5 #define ADDR_U64(upper, lower) ((uint64_t)(upper) << 32 | (lower)) enum qm_fun_type { HISI_QM_HW_PF, HISI_QM_HW_VF, }; enum qm_sq_type { HISI_QM_CHANNEL_TYPE0 = 0, HISI_QM_CHANNEL_TYPE1, HISI_QM_CHANNEL_TYPE2, }; struct qm_sqc { uint16_t head; uint16_t tail; uint32_t base_l; uint32_t base_h; /* * qes : 12 * sqe : 4 * rsv(stash_nid/stash_en) : 16 */ uint32_t dw3; uint16_t rand_data; uint16_t rsv0; uint16_t pasid; /* * rsv : 5 * head_sig : 1 * tail_sig : 1 * pasid_en : 1 * rsv : 8 */ uint16_t w11; uint16_t cq_num; /* * priority(Credit): 4 * order(order/fc/close/rsv) : 4 * type : 4 * rsv : 4 */ uint16_t w13; uint32_t rsv1; }; struct qm_cqc { uint16_t head; uint16_t tail; uint32_t base_l; uint32_t base_h; /* * qes : 12 * cqe_size : 4 * rsv(stash_nid/stash_en) : 16 */ uint32_t dw3; uint16_t rand_data; uint16_t rsv0; uint16_t pasid; /* * pasid_en : 1 * rsv : 4 * head_sig : 1 * tail_sig : 1 * rsv : 9 */ uint16_t w11; /* * phase : 1 * c_flag : 1 * stash_vld : 1 */ uint32_t dw6; uint32_t rsv1; }; struct qm_cqe { uint32_t rsv0; uint16_t cmd_id; uint16_t rsv1; uint16_t sq_head; uint16_t sq_id; uint16_t rsv2; /* * p : 1 * status : 15 */ uint16_t w7; }; struct hisi_qp { struct hisi_qm *qm; uint32_t qp_id; uint8_t sq_type; uint16_t sq_tail; uint16_t cq_head; bool cqc_phase; bool used; void *sqe; struct qm_cqe *cqe; paddr_t sqe_dma; paddr_t cqe_dma; enum hisi_drv_status (*fill_sqe)(void *sqe, void *msg); enum hisi_drv_status (*parse_sqe)(void *sqe, void *msg); }; struct qm_xqc { struct qm_sqc *sqc; struct qm_cqc *cqc; paddr_t sqc_dma; paddr_t cqc_dma; }; struct hisi_qm { enum qm_fun_type fun_type; vaddr_t io_base; uint32_t io_size; uint32_t vfs_num; uint32_t version; struct qm_xqc xqc; struct qm_xqc cfg_xqc; uint32_t sqe_size; uint32_t sqe_log2_size; uint32_t qp_base; uint32_t qp_num; uint32_t qp_in_used; uint32_t qp_idx; struct hisi_qp *qp_array; struct mutex qp_lock; /* protect the qp instance */ struct mutex mailbox_lock; enum hisi_drv_status (*dev_status_check)(struct hisi_qm *qm); }; enum hisi_drv_status { HISI_QM_DRVCRYPT_NO_ERR = 0, HISI_QM_DRVCRYPT_FAIL = 1, HISI_QM_DRVCRYPT_EIO = 5, HISI_QM_DRVCRYPT_EAGAIN = 11, HISI_QM_DRVCRYPT_ENOMEM = 12, HISI_QM_DRVCRYPT_EFAULT = 14, HISI_QM_DRVCRYPT_EBUSY = 16, HISI_QM_DRVCRYPT_ENODEV = 19, HISI_QM_DRVCRYPT_EINVAL = 22, HISI_QM_DRVCRYPT_ETMOUT = 110, HISI_QM_DRVCRYPT_RECV_DONE = 175, HISI_QM_DRVCRYPT_ENOPROC, HISI_QM_DRVCRYPT_IN_EPARA, HISI_QM_DRVCRYPT_VERIFY_ERR, HISI_QM_DRVCRYPT_HW_EACCESS, }; struct acc_device { struct hisi_qm qm; vaddr_t io_base; uint32_t io_size; uint32_t vfs_num; uint32_t endian; enum qm_fun_type fun_type; SLIST_ENTRY(acc_device) link; }; /** * @Description: Get the version information of QM hardware * @param qm: Handle of Queue Management module */ void hisi_qm_get_version(struct hisi_qm *qm); /** * @Description: Init QM for Kunpeng drv * @param qm: Handle of Queue Management module * @return success: HISI_QM_DRVCRYPT_NO_ERR, * fail: HISI_QM_DRVCRYPT_EBUSY/HISI_QM_DRVCRYPT_EINVAL */ enum hisi_drv_status hisi_qm_init(struct hisi_qm *qm); /** * @Description:deinit QM for Kunpeng drv * @param qm: Handle of Queue Management module */ void hisi_qm_uninit(struct hisi_qm *qm); /** * @Description: Start QM for Kunpeng drv * @param qm: Handle of Queue Management module */ enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm); /** * @Description: Config QM for Kunpeng drv * @param qm: Handle of Queue Management module */ void hisi_qm_dev_init(struct hisi_qm *qm); /** * @Description: Create Queue Pair, allocated to PF/VF for configure * and service use. Each QP includes one SQ and one CQ * @param qm: Handle of Queue Management module * @param sq_type: Accelerator specific algorithm type in sqc * @return success: Handle of QP,fail: NULL */ struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type); /** * @Description:Release Queue Pair * @param qp: Handle of Queue Pair */ void hisi_qm_release_qp(struct hisi_qp *qp); /** * @Description: Send SQE(Submmision Queue Element) to Kunpeng dev * @param qp: Handle of Queue Pair * @param msg: The message * @return success: HISI_QM_DRVCRYPT_NO_ERR,fail: HISI_QM_DRVCRYPT_EINVAL */ enum hisi_drv_status hisi_qp_send(struct hisi_qp *qp, void *msg); /** * @Description: Recevice result from Kunpeng dev * @param qp: Handle of Queue Pair * @param msg: The message * @return success: HISI_QM_DRVCRYPT_NO_ERR * fail: HISI_QM_DRVCRYPT_EINVAL/ETMOUT */ enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg); #endif optee_os-4.3.0/core/drivers/crypto/hisilicon/hpre_dh.c000066400000000000000000000206401464416617300230350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd. * Kunpeng hardware accelerator hpre dh algorithm implementation. */ #include #include #include #include #include #include #include #include #include #include "hpre_dh.h" #include "hpre_main.h" static TEE_Result hpre_dh_alloc_keypair(struct dh_keypair *key, size_t size_bits) { if (!key || !size_bits) { EMSG("Invalid input parameter"); return TEE_ERROR_BAD_PARAMETERS; } memset(key, 0, sizeof(*key)); key->g = crypto_bignum_allocate(size_bits); if (!key->g) goto g_err; key->p = crypto_bignum_allocate(size_bits); if (!key->p) goto p_err; key->x = crypto_bignum_allocate(size_bits); if (!key->x) goto x_err; key->y = crypto_bignum_allocate(size_bits); if (!key->y) goto y_err; /* Allocate subprime even if not used */ key->q = crypto_bignum_allocate(size_bits); if (!key->q) goto q_err; return TEE_SUCCESS; q_err: crypto_bignum_free(&key->y); y_err: crypto_bignum_free(&key->x); x_err: crypto_bignum_free(&key->p); p_err: crypto_bignum_free(&key->g); g_err: EMSG("HPRE dh alloc key pair fail."); return TEE_ERROR_OUT_OF_MEMORY; } static enum hisi_drv_status hpre_dh_fill_sqe(void *bd, void *info) { struct hpre_dh_msg *msg = info; struct hpre_sqe *sqe = bd; sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT); sqe->task_len1 = TASK_LENGTH(msg->key_bytes); sqe->key = msg->x_p_dma; sqe->in = msg->g_dma; sqe->out = msg->out_dma; return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status hpre_dh_parse_sqe(void *bd, void *info) { struct hpre_dh_msg *msg = info; struct hpre_sqe *sqe = bd; uint16_t err = 0; uint16_t done = 0; err = HPRE_TASK_ETYPE(sqe->w0); done = HPRE_TASK_DONE(sqe->w0); if (done != HPRE_HW_TASK_DONE || err) { EMSG("HPRE do dh fail! done=0x%"PRIx16", etype=0x%"PRIx16, done, err); return HISI_QM_DRVCRYPT_IN_EPARA; } if (hpre_bin_to_crypto_bin(msg->out, msg->out, msg->key_bytes, msg->out_bytes)) { EMSG("Fail to transfer dh_y from hpre_bin to crypto_bin"); return HISI_QM_DRVCRYPT_EINVAL; } return HISI_QM_DRVCRYPT_NO_ERR; } static TEE_Result hpre_dh_do_task(void *msg) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; TEE_Result res = TEE_SUCCESS; struct hisi_qp *qp = NULL; qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE0); if (!qp) { EMSG("Fail to create dh qp"); return TEE_ERROR_BUSY; } qp->fill_sqe = hpre_dh_fill_sqe; qp->parse_sqe = hpre_dh_parse_sqe; ret = hisi_qp_send(qp, msg); if (ret) { EMSG("Fail to send task, ret=%d", ret); res = TEE_ERROR_BAD_STATE; goto done_proc; } ret = hisi_qp_recv_sync(qp, msg); if (ret) { EMSG("Recv task error, ret=%d", ret); res = TEE_ERROR_BAD_STATE; goto done_proc; } done_proc: hisi_qm_release_qp(qp); return res; } static size_t round_key_size_to_hw_size(size_t key_bytes) { size_t size = 0; if (key_bytes <= 96) size = 96; else if (key_bytes <= 128) size = 128; else if (key_bytes <= 192) size = 192; else if (key_bytes <= 256) size = 256; else if (key_bytes <= 384) size = 384; else if (key_bytes <= 512) size = 512; else EMSG("Invalid key_bytes[%zu]", key_bytes); return size; } static TEE_Result hpre_dh_gen_privkey(struct bignum *x, size_t key_bits) { size_t key_bytes = BITS_TO_BYTES(key_bits); uint8_t buf[HPRE_DH_MAX_KEY_BYTES] = { }; TEE_Result ret = TEE_SUCCESS; if (hw_get_random_bytes(buf, key_bytes)) { EMSG("Fail to fill privkey"); return TEE_ERROR_NO_DATA; } ret = crypto_bignum_bin2bn(buf, key_bytes, x); memzero_explicit(buf, key_bytes); return ret; } static enum hisi_drv_status hpre_dh_params_alloc(struct hpre_dh_msg *msg) { uint32_t size = HPRE_DH_TOTAL_BUF_SIZE(msg->key_bytes); uint8_t *data = NULL; data = calloc(1, size); if (!data) { EMSG("Fail to alloc dh total buf"); return HISI_QM_DRVCRYPT_ENOMEM; } msg->x_p = data; msg->x_p_dma = virt_to_phys(msg->x_p); msg->g = msg->x_p + (msg->key_bytes << 1); msg->g_dma = msg->x_p_dma + (msg->key_bytes << 1); msg->out = msg->g + msg->key_bytes; msg->out_dma = msg->g_dma + msg->key_bytes; return HISI_QM_DRVCRYPT_NO_ERR; } static void hpre_dh_params_free(struct hpre_dh_msg *msg) { if (msg->x_p) { free_wipe(msg->x_p); msg->x_p = NULL; } } static enum hisi_drv_status hpre_dh_params_bn2bin(struct hpre_dh_msg *msg, struct dh_keypair *key, struct bignum *pubkey) { uint8_t *p = msg->x_p + msg->key_bytes; uint8_t *x = msg->x_p; enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; msg->xbytes = BITS_TO_BYTES(key->xbits); msg->out_bytes = msg->pbytes; crypto_bignum_bn2bin(key->x, x); crypto_bignum_bn2bin(key->p, p); if (!pubkey) { msg->gbytes = crypto_bignum_num_bytes(key->g); crypto_bignum_bn2bin(key->g, msg->g); } else { msg->gbytes = crypto_bignum_num_bytes(pubkey); if (msg->gbytes != msg->pbytes) return HISI_QM_DRVCRYPT_EINVAL; crypto_bignum_bn2bin(pubkey, msg->g); } ret = hpre_bin_from_crypto_bin(x, x, msg->key_bytes, msg->xbytes); if (ret) { EMSG("Fail to transfer dh_x from crypto_bin to hpre_bin"); return ret; } ret = hpre_bin_from_crypto_bin(p, p, msg->key_bytes, msg->pbytes); if (ret) { EMSG("Fail to transfer dh_p from crypto_bin to hpre_bin"); return ret; } ret = hpre_bin_from_crypto_bin(msg->g, msg->g, msg->key_bytes, msg->gbytes); if (ret) EMSG("Fail to transfer dh_g from crypto_bin to hpre_bin"); return ret; } static TEE_Result hpre_dh_request_init(struct hpre_dh_msg *msg, struct dh_keypair *key, struct bignum *pubkey) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; msg->alg_type = HPRE_ALG_DH; msg->key_bytes = round_key_size_to_hw_size(msg->pbytes); if (!msg->key_bytes) return TEE_ERROR_BAD_PARAMETERS; ret = hpre_dh_params_alloc(msg); if (ret) return TEE_ERROR_OUT_OF_MEMORY; ret = hpre_dh_params_bn2bin(msg, key, pubkey); if (ret) { hpre_dh_params_free(msg); return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static void hpre_dh_request_deinit(struct hpre_dh_msg *msg) { hpre_dh_params_free(msg); } static TEE_Result hpre_dh_gen_keypair(struct dh_keypair *key, struct bignum *q __unused, size_t key_size) { struct hpre_dh_msg msg = { }; TEE_Result ret = TEE_SUCCESS; size_t p_bits = 0; if (!key || !key->g || !key->p || !key->x || !key->y) { EMSG("Invalid dh_gen_keypair input parameters"); return TEE_ERROR_BAD_PARAMETERS; } p_bits = crypto_bignum_num_bits(key->p); if (!p_bits) { EMSG("p_bits can not be zero"); return TEE_ERROR_BAD_PARAMETERS; } msg.pbytes = BITS_TO_BYTES(p_bits); if (!key_size) { /* xbits */ key->xbits = p_bits; ret = hpre_dh_gen_privkey(key->x, key->xbits); if (ret) { EMSG("Fail to gen dh privkey"); return ret; } } else { key->xbits = key_size; } ret = hpre_dh_request_init(&msg, key, NULL); if (ret) { EMSG("Fail to init dh msg"); return ret; } ret = hpre_dh_do_task(&msg); if (ret) goto req_deinit; ret = crypto_bignum_bin2bn(msg.out, msg.out_bytes, key->y); if (ret) EMSG("Fail to bin2bn msg out"); req_deinit: hpre_dh_request_deinit(&msg); return ret; } static TEE_Result hpre_dh_do_shared_secret(struct drvcrypt_secret_data *sdata) { struct hpre_dh_msg msg = { }; struct dh_keypair *key = NULL; TEE_Result ret = TEE_SUCCESS; if (!sdata || !sdata->key_priv || !sdata->key_pub) { EMSG("Invalid dh_do_shared_secret input parameters"); return TEE_ERROR_BAD_PARAMETERS; } key = sdata->key_priv; key->xbits = crypto_bignum_num_bits(key->x); if (!key->xbits) { EMSG("xbits can not be zero"); return TEE_ERROR_BAD_PARAMETERS; } msg.pbytes = crypto_bignum_num_bytes(key->p); ret = hpre_dh_request_init(&msg, key, (struct bignum *)sdata->key_pub); if (ret) { EMSG("Fail to init dh msg"); return ret; } ret = hpre_dh_do_task(&msg); if (ret) goto req_deinit; sdata->secret.length = msg.out_bytes; memcpy(sdata->secret.data, msg.out, msg.out_bytes); memzero_explicit(msg.out, msg.out_bytes); req_deinit: hpre_dh_request_deinit(&msg); return ret; } static struct drvcrypt_dh driver_dh = { .alloc_keypair = hpre_dh_alloc_keypair, .gen_keypair = hpre_dh_gen_keypair, .shared_secret = hpre_dh_do_shared_secret, }; TEE_Result hpre_dh_init(void) { TEE_Result ret = drvcrypt_register_dh(&driver_dh); if (ret != TEE_SUCCESS) EMSG("hpre dh register to crypto fail."); return ret; } driver_init(hpre_dh_init); optee_os-4.3.0/core/drivers/crypto/hisilicon/hpre_dh.h000066400000000000000000000011631464416617300230410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd. */ #ifndef __HPRE_DH_H__ #define __HPRE_DH_H__ #include #include #include #define HPRE_DH_MAX_KEY_BYTES 512 #define HPRE_DH_TOTAL_BUF_SIZE(key_bytes) ((key_bytes) * 4) struct hpre_dh_msg { uint8_t *x_p; /* X and p data in order */ paddr_t x_p_dma; uint8_t *g; paddr_t g_dma; uint8_t *out; paddr_t out_dma; uint32_t alg_type; uint32_t key_bytes; uint32_t xbytes; uint32_t pbytes; uint32_t gbytes; uint32_t out_bytes; }; TEE_Result hpre_dh_init(void); #endif optee_os-4.3.0/core/drivers/crypto/hisilicon/hpre_main.c000066400000000000000000000212531464416617300233670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2024 HiSilicon Limited. * Kunpeng hardware accelerator HPRE module init. */ #include #include "hpre_main.h" /* base config */ #define HPRE_COMMON_CNT_CLR_CE 0x301000 #define HPRE_CFG_AXCACHE 0x301010 #define HPRE_RDCHN_INI_CFG 0x301014 #define HPRE_BD_ENDIAN 0x301020 #define HPRE_ECC_BYPASS 0x301024 #define HPRE_POISON_BYPASS 0x30102c #define HPRE_BD_ARUSR_CFG 0x301030 #define HPRE_BD_AWUSR_CFG 0x301034 #define HPRE_TYPES_ENB 0x301038 #define HPRE_DATA_RUSER_CFG 0x30103c #define HPRE_DATA_WUSER_CFG 0x301040 #define HPRE_HAC_INT_MASK 0x301400 #define HPRE_RAS_ECC_1BIT_TH 0x30140c #define HPRE_RAS_CE_ENB 0x301410 #define HPRE_RAS_NFE_ENB 0x301414 #define HPRE_RAS_FE_ENB 0x301418 #define HPRE_HAC_INT_SRC 0x301600 #define HPRE_RDCHN_INI_ST 0x301a00 #define HPRE_OOO_SHUTDOWN_SEL 0x301a3c #define HPRE_CORE_ENB 0x302004 #define HPRE_CORE_INI_CFG 0x302020 #define HPRE_CORE_INI_STATUS 0x302080 /* clock gate */ #define HPRE_CLKGATE_CTL 0x301a10 #define HPRE_PEH_CFG_AUTO_GATE 0x301a2c #define HPRE_CLUSTER_DYN_CTL 0x302010 #define HPRE_CORE_SHB_CFG 0x302088 #define HPRE_CORE_GATE_ENABLE GENMASK_32(31, 30) #define HPRE_AXCACHE_MASK 0xff #define HPRE_HAC_INT_DISABLE 0x1ffffff #define HPRE_RAS_CE_MASK 0x1 #define HPRE_RAS_NFE_MASK 0x1fffffe #define HPRE_RAS_FE_MASK 0 #define HPRE_BD_LITTLE_ENDIAN 0 #define HPRE_RSA_ENB BIT(0) #define HPRE_ECC_ENB BIT(1) #define HPRE_BD_ARUSR_MASK 0x2 #define HPRE_BD_AWUSR_MASK 0x102 #define HPRE_DATA_USR_MASK 0x32 #define HPRE_CLUSTER_CORE_MASK GENMASK_32(9, 0) static SLIST_HEAD(, acc_device) hpre_list = SLIST_HEAD_INITIALIZER(hpre_list); struct hisi_qp *hpre_create_qp(uint8_t sq_type) { struct acc_device *hpre_dev = NULL; struct acc_device *cur_dev = NULL; struct hisi_qm *qm = NULL; uint32_t free_qp_num = 0; uint32_t max_qp_num = 0; /* Find the HPRE device with the most remaining qp numbers */ SLIST_FOREACH(cur_dev, &hpre_list, link) { qm = &cur_dev->qm; if (qm->fun_type == HISI_QM_HW_PF) free_qp_num = HISI_QM_PF_Q_NUM - qm->qp_in_used; else free_qp_num = HISI_QM_VF_Q_NUM - qm->qp_in_used; if (free_qp_num > max_qp_num) { max_qp_num = free_qp_num; hpre_dev = cur_dev; } } if (!hpre_dev) { EMSG("No available hpre device"); return NULL; } return hisi_qm_create_qp(&hpre_dev->qm, sq_type); } enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src, uint32_t bsize, uint32_t dsize) { if (!src || !dst || !dsize || !bsize) { EMSG("parameter error"); return HISI_QM_DRVCRYPT_EINVAL; } if (bsize < dsize) { EMSG("dsize is too long"); return HISI_QM_DRVCRYPT_EINVAL; } if (src == dst && bsize == dsize) return HISI_QM_DRVCRYPT_NO_ERR; /* * Copying non-zero data and padding with zeroes in high-bits * (eg: 1 2 3 0 0 -> 0 0 1 2 3) */ memmove(dst + bsize - dsize, src, dsize); memset(dst, 0, bsize - dsize); return HISI_QM_DRVCRYPT_NO_ERR; } enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src, uint32_t bsize, uint32_t dsize) { if (!dst || !src || !bsize || !dsize) { EMSG("parameter error"); return HISI_QM_DRVCRYPT_EINVAL; } if (bsize < dsize) { EMSG("dsize is too long"); return HISI_QM_DRVCRYPT_EINVAL; } if (src == dst && bsize == dsize) return HISI_QM_DRVCRYPT_NO_ERR; /* * Copying non-zero data and padding with zeroes in low-bits * (eg: 0 0 1 2 3 -> 1 2 3 0 0) */ memmove(dst, src + bsize - dsize, dsize); memset(dst + dsize, 0, bsize - dsize); return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status hpre_set_cluster(struct hisi_qm *qm) { uint32_t val = 0; io_write32(qm->io_base + HPRE_CORE_ENB, HPRE_CLUSTER_CORE_MASK); io_write32(qm->io_base + HPRE_CORE_INI_CFG, 0x1); if (IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_CORE_INI_STATUS, val, (val & HPRE_CLUSTER_CORE_MASK) == HPRE_CLUSTER_CORE_MASK, POLL_PERIOD, POLL_TIMEOUT)) return HISI_QM_DRVCRYPT_EBUSY; return HISI_QM_DRVCRYPT_NO_ERR; } static void hpre_disable_clock_gate(struct hisi_qm *qm) { io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x0); io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x0); io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x0); io_clrbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE); } static void hpre_enable_clock_gate(struct hisi_qm *qm) { io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x1); io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x1); io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x1); io_setbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE); } static TEE_Result hpre_engine_init(struct acc_device *hpre_dev) { struct hisi_qm *qm = &hpre_dev->qm; uint32_t val = 0; int32_t ret = 0; if (qm->fun_type == HISI_QM_HW_VF) return TEE_SUCCESS; hpre_disable_clock_gate(qm); hisi_qm_dev_init(qm); io_write32(qm->io_base + HPRE_CFG_AXCACHE, HPRE_AXCACHE_MASK); io_write32(qm->io_base + HPRE_BD_ENDIAN, HPRE_BD_LITTLE_ENDIAN); io_write32(qm->io_base + HPRE_RAS_CE_ENB, HPRE_RAS_CE_MASK); io_write32(qm->io_base + HPRE_RAS_NFE_ENB, HPRE_RAS_NFE_MASK); io_write32(qm->io_base + HPRE_RAS_FE_ENB, HPRE_RAS_FE_MASK); io_write32(qm->io_base + HPRE_HAC_INT_MASK, HPRE_HAC_INT_DISABLE); io_write32(qm->io_base + HPRE_POISON_BYPASS, 0x0); io_write32(qm->io_base + HPRE_COMMON_CNT_CLR_CE, 0x0); io_write32(qm->io_base + HPRE_ECC_BYPASS, 0x0); /* cmd_type is controlled by hac subctrl */ io_write32(qm->io_base + HPRE_BD_ARUSR_CFG, HPRE_BD_ARUSR_MASK); io_write32(qm->io_base + HPRE_BD_AWUSR_CFG, HPRE_BD_AWUSR_MASK); io_write32(qm->io_base + HPRE_DATA_RUSER_CFG, HPRE_DATA_USR_MASK); io_write32(qm->io_base + HPRE_DATA_WUSER_CFG, HPRE_DATA_USR_MASK); io_write32(qm->io_base + HPRE_TYPES_ENB, HPRE_RSA_ENB | HPRE_ECC_ENB); io_write32(qm->io_base + HPRE_RDCHN_INI_CFG, 0x1); ret = IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_RDCHN_INI_ST, val, val & 0x1, POLL_PERIOD, POLL_TIMEOUT); if (ret) { EMSG("Fail to init rd channel"); return TEE_ERROR_BUSY; } ret = hpre_set_cluster(qm); if (ret) { EMSG("Fail to init hpre cluster cores"); return TEE_ERROR_BUSY; } hpre_enable_clock_gate(qm); return TEE_SUCCESS; } static enum hisi_drv_status hpre_dev_status_check(struct hisi_qm *qm) { uint32_t val = 0; val = io_read32(qm->io_base + HPRE_HAC_INT_SRC); if (val & HPRE_RAS_NFE_MASK) { EMSG("HPRE NFE RAS happened, need to reset"); return HISI_QM_DRVCRYPT_HW_EACCESS; } val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC); if (val) { if (val & HISI_QM_HPRE_NFE_INT_MASK) EMSG("QM NFE RAS happened, need to reset"); if (val & HISI_QM_INVALID_DB) { EMSG("QM invalid db happened, please check"); io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC, HISI_QM_INVALID_DB); } return HISI_QM_DRVCRYPT_HW_EACCESS; } return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status hpre_qm_init(struct acc_device *hpre_dev) { struct hisi_qm *qm = &hpre_dev->qm; if (cpu_mmu_enabled()) { qm->io_base = (uintptr_t)phys_to_virt_io(hpre_dev->io_base, hpre_dev->io_size); if (!qm->io_base) { EMSG("Fail to get qm io_base"); return HISI_QM_DRVCRYPT_EFAULT; } } else { qm->io_base = hpre_dev->io_base; } qm->vfs_num = hpre_dev->vfs_num; qm->fun_type = hpre_dev->fun_type; qm->sqe_size = HPRE_SQE_SIZE; qm->sqe_log2_size = HPRE_SQE_LOG2_SIZE; if (qm->fun_type == HISI_QM_HW_PF) { hisi_qm_get_version(qm); DMSG("HPRE hardware version is 0x%"PRIx32, qm->version); qm->qp_base = HISI_QM_PF_Q_BASE; qm->qp_num = HISI_QM_PF_Q_NUM; qm->dev_status_check = hpre_dev_status_check; } return hisi_qm_init(qm); } static struct acc_device *hpre_pre_init(void) { struct acc_device *hpre_dev = NULL; hpre_dev = calloc(1, sizeof(*hpre_dev)); if (!hpre_dev) { EMSG("Fail to alloc hpre_dev"); return NULL; } hpre_dev->io_base = HPRE_BAR_BASE; hpre_dev->io_size = HPRE_BAR_SIZE; hpre_dev->fun_type = HISI_QM_HW_PF; SLIST_INSERT_HEAD(&hpre_list, hpre_dev, link); return hpre_dev; } static TEE_Result hpre_probe(void) { TEE_Result ret = TEE_ERROR_GENERIC; struct acc_device *hpre_dev = NULL; struct hisi_qm *qm = NULL; DMSG("HPRE driver init start"); hpre_dev = hpre_pre_init(); if (!hpre_dev) return TEE_ERROR_OUT_OF_MEMORY; qm = &hpre_dev->qm; if (hpre_qm_init(hpre_dev)) { EMSG("Fail to init hpre qm"); goto err_with_pre_init; } ret = hpre_engine_init(hpre_dev); if (ret) { EMSG("Fail to init engine"); goto err_with_qm_init; } if (hisi_qm_start(qm)) { EMSG("Fail to start qm"); ret = TEE_ERROR_BAD_STATE; goto err_with_qm_init; } DMSG("HPRE driver init done"); return TEE_SUCCESS; err_with_qm_init: hisi_qm_uninit(qm); err_with_pre_init: SLIST_REMOVE_HEAD(&hpre_list, link); free(hpre_dev); return ret; } driver_init(hpre_probe); optee_os-4.3.0/core/drivers/crypto/hisilicon/hpre_main.h000066400000000000000000000041561464416617300233770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024 HiSilicon Limited. */ #ifndef _HPRE_MAIN_H #define _HPRE_MAIN_H #include "hisi_qm.h" #define HPRE_BAR_BASE 0x150000000 #define HPRE_BAR_SIZE 0x400000 #define HPRE_SQE_SIZE 64 #define HPRE_SQE_LOG2_SIZE 6 #define HPRE_SQE_SM2_KSEL_SHIFT 1 #define HPRE_SQE_BD_RSV2_SHIFT 7 #define HPRE_HW_TASK_INIT 0x1 #define HPRE_HW_TASK_DONE 0x3 #define TASK_LENGTH(len) ((len) / 8 - 1) #define BITS_TO_BYTES(len) (((len) + 7) / 8) #define BYTES_TO_BITS(len) ((len) * 8) #define HPRE_ETYPE_SHIFT 5 #define HPRE_ETYPE_MASK 0x7ff #define HPRE_ETYPE1_SHIFT 16 #define HPRE_ETYPE1_MASK 0x3fff #define HPRE_DONE_SHIFT 30 #define HPRE_DONE_MASK 0x3 #define HPRE_TASK_ETYPE(w0) (((w0) >> HPRE_ETYPE_SHIFT) & HPRE_ETYPE_MASK) #define HPRE_TASK_ETYPE1(w0) (((w0) >> HPRE_ETYPE1_SHIFT) & HPRE_ETYPE1_MASK) #define HPRE_TASK_DONE(w0) (((w0) >> HPRE_DONE_SHIFT) & HPRE_DONE_MASK) struct hpre_sqe { /* * alg : 5 * etype : 11 * etype1 : 14 * done : 2 */ uint32_t w0; uint8_t task_len1; uint8_t task_len2; uint8_t mrttest_num; /* * uwkey_enb : 1 * sm2_ksel : 1 * sva_bypass : 1 * sva_status : 4 * bd_rsv2 : 1 */ uint8_t ext1; uint64_t key; uint64_t in; uint64_t out; uint64_t tag; uint16_t sm2enc_klen; /* * uwkey_sel : 4 * uwkey_wrap_num : 3 * rsvd2 : 9 */ uint16_t ext2; uint64_t kek_key; uint32_t rsv[3]; }; enum hpre_alg_type { HPRE_ALG_NC_NCRT = 0x0, HPRE_ALG_NC_CRT = 0x1, HPRE_ALG_KG_STD = 0x2, HPRE_ALG_KG_CRT = 0x3, HPRE_ALG_DH_G2 = 0x4, HPRE_ALG_DH = 0x5, HPRE_ALG_ECDH_MULTIPLY = 0xD, HPRE_ALG_ECDSA_SIGN = 0xE, HPRE_ALG_ECDSA_VERF = 0xF, HPRE_ALG_X_DH_MULTIPLY = 0x10, HPRE_ALG_SM2_KEY_GEN = 0x11, HPRE_ALG_SM2_SIGN = 0x12, HPRE_ALG_SM2_VERF = 0x13, HPRE_ALG_SM2_ENC = 0x14, HPRE_ALG_SM2_DEC = 0x15 }; uint32_t hpre_init(void); struct hisi_qp *hpre_create_qp(uint8_t sq_type); enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src, uint32_t bsize, uint32_t dsize); enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src, uint32_t bsize, uint32_t dsize); #endif optee_os-4.3.0/core/drivers/crypto/hisilicon/sec_hash.c000066400000000000000000000376631464416617300232160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2024 HiSilicon Limited. * Kunpeng hardware accelerator sec hash algorithm implementation. */ #include #include #include "sec_hash.h" #include "sec_main.h" static enum hisi_drv_status sec_digest_set_hmac_key(struct hashctx *ctx, struct hisi_sec_sqe *sqe) { if (ctx->key_len > SEC_DIGEST_MAX_KEY_SIZE || !ctx->key_len) { EMSG("Invalid digest key len(%ld)", ctx->key_len); return HISI_QM_DRVCRYPT_IN_EPARA; } /* If the length of key is not word-aligned, increment by 1 */ sqe->type2.mac_key_alg |= SHIFT_U64(DIV_ROUND_UP(ctx->key_len, SEC_ENCODE_BYTES), SEC_AKEY_OFFSET); sqe->type2.a_key_addr = ctx->key_dma; return HISI_QM_DRVCRYPT_NO_ERR; } static void sec_digest_fill_long_bd2(struct hashctx *ctx, struct hisi_sec_sqe *sqe) { uint64_t total_bits = 0; if (ctx->has_next && !ctx->iv_len) { /* LONG BD FIRST */ sqe->ai_apd_cs |= AI_GEN_INNER; sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_NOPAD, SEC_APAD_OFFSET); ctx->iv_len = ctx->mac_len; } else if (ctx->has_next && ctx->iv_len) { /* LONG BD MIDDLE */ sqe->ai_apd_cs |= AI_GEN_IVIN_ADDR; sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_NOPAD, SEC_APAD_OFFSET); sqe->type2.a_ivin_addr = sqe->type2.mac_addr; ctx->iv_len = ctx->mac_len; } else if (!ctx->has_next && ctx->iv_len) { /* LONG BD END */ sqe->ai_apd_cs |= AI_GEN_IVIN_ADDR; sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_PAD, SEC_APAD_OFFSET); sqe->type2.a_ivin_addr = sqe->type2.mac_addr; total_bits = ctx->long_data_len * BYTE_BITS; sqe->type2.long_a_data_len = total_bits; ctx->iv_len = 0; } else { /* SHORT BD */ ctx->iv_len = 0; } } static struct crypto_hash *to_hash_ctx(struct crypto_hash_ctx *ctx) { return container_of(ctx, struct crypto_hash, hash_ctx); } static uint32_t sec_digest_get_alg_type(uint32_t algo) { switch (algo) { case TEE_ALG_MD5: return A_ALG_MD5; case TEE_ALG_HMAC_MD5: return A_ALG_HMAC_MD5; case TEE_ALG_SHA1: return A_ALG_SHA1; case TEE_ALG_HMAC_SHA1: return A_ALG_HMAC_SHA1; case TEE_ALG_SHA224: return A_ALG_SHA224; case TEE_ALG_HMAC_SHA224: return A_ALG_HMAC_SHA224; case TEE_ALG_SM3: return A_ALG_SM3; case TEE_ALG_HMAC_SM3: return A_ALG_HMAC_SM3; case TEE_ALG_SHA256: return A_ALG_SHA256; case TEE_ALG_HMAC_SHA256: return A_ALG_HMAC_SHA256; case TEE_ALG_SHA384: return A_ALG_SHA384; case TEE_ALG_HMAC_SHA384: return A_ALG_HMAC_SHA384; case TEE_ALG_SHA512: return A_ALG_SHA512; case TEE_ALG_HMAC_SHA512: return A_ALG_HMAC_SHA512; default: return A_ALG_MAX; } } static enum hisi_drv_status sec_digest_fill_sqe(void *bd, void *msg) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct hisi_sec_sqe *sqe = bd; struct hashctx *ctx = msg; uint32_t alg_type = 0; if (!ctx->in_len) { EMSG("Digest bd2 not support 0 packet"); return HISI_QM_DRVCRYPT_IN_EPARA; } sqe->type_auth_cipher = BD_TYPE2; sqe->sds_sa_type = SHIFT_U32(SCENE_NOTHING, SEC_SCENE_OFFSET); sqe->type_auth_cipher |= SHIFT_U32(AUTH_MAC_CALCULATE, SEC_AUTH_OFFSET); sqe->type2.alen_ivllen = ctx->in_len; sqe->type2.data_src_addr = ctx->in_dma; sqe->type2.mac_addr = ctx->out_dma; sqe->type2.mac_key_alg |= ctx->mac_len / SEC_ENCODE_BYTES; if (ctx->mode == WCRYPTO_DIGEST_HMAC) { ret = sec_digest_set_hmac_key(ctx, sqe); if (ret) return ret; } alg_type = sec_digest_get_alg_type(ctx->algo); if (alg_type >= A_ALG_MAX) { EMSG("Fail to get digest alg type"); return HISI_QM_DRVCRYPT_IN_EPARA; } sqe->type2.mac_key_alg |= SHIFT_U32(alg_type, SEC_AEAD_ALG_OFFSET); sec_digest_fill_long_bd2(ctx, sqe); return ret; } static enum hisi_drv_status sec_digest_set_hmac_bd3_key(struct hashctx *ctx, struct hisi_sec_bd3_sqe *sqe) { if (ctx->key_len > SEC_DIGEST_MAX_KEY_SIZE || !ctx->key_len) { EMSG("Invalid digest key len(%ld)", ctx->key_len); return HISI_QM_DRVCRYPT_IN_EPARA; } /* If the length of key is not word-aligned, increment by 1 */ sqe->auth_mac_key |= SHIFT_U64(DIV_ROUND_UP(ctx->key_len, SEC_ENCODE_BYTES), SEC_AKEY_OFFSET_V3); sqe->a_key_addr = ctx->key_dma; return HISI_QM_DRVCRYPT_NO_ERR; } static void sec_digest_fill_long_bd3(struct hashctx *ctx, struct hisi_sec_bd3_sqe *sqe) { uint64_t total_bits = 0; if (ctx->has_next && !ctx->iv_len) { /* LONG BD FIRST */ sqe->auth_mac_key |= SHIFT_U32(AI_GEN_INNER, SEC_AI_GEN_OFFSET_V3); sqe->stream_scene.auth_pad = AUTHPAD_NOPAD; ctx->iv_len = ctx->mac_len; } else if (ctx->has_next && ctx->iv_len) { /* LONG BD MIDDLE */ sqe->auth_mac_key |= SHIFT_U32(AI_GEN_IVIN_ADDR, SEC_AI_GEN_OFFSET_V3); sqe->stream_scene.auth_pad = AUTHPAD_NOPAD; sqe->a_ivin_addr = sqe->mac_addr; ctx->iv_len = ctx->mac_len; } else if (!ctx->has_next && ctx->iv_len) { /* LONG BD END */ sqe->auth_mac_key |= SHIFT_U32(AI_GEN_IVIN_ADDR, SEC_AI_GEN_OFFSET_V3); sqe->stream_scene.auth_pad = AUTHPAD_PAD; sqe->a_ivin_addr = sqe->mac_addr; total_bits = ctx->long_data_len * BYTE_BITS; sqe->stream_scene.long_a_data_len = total_bits; ctx->iv_len = 0; } else { /* SHORT BD */ ctx->iv_len = 0; } } static enum hisi_drv_status sec_digest_fill_bd3_sqe(void *bd, void *msg) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct hisi_sec_bd3_sqe *sqe = bd; struct hashctx *ctx = msg; uint32_t alg_type = 0; sqe->bd_param = BD_TYPE3 | SHIFT_U32(ctx->scene, SEC_SCENE_OFFSET_V3); sqe->a_len_key = ctx->in_len; sqe->auth_mac_key = AUTH_MAC_CALCULATE; sqe->data_src_addr = ctx->in_dma; sqe->mac_addr = ctx->out_dma; if (ctx->mode == WCRYPTO_DIGEST_HMAC) { ret = sec_digest_set_hmac_bd3_key(ctx, sqe); if (ret) return HISI_QM_DRVCRYPT_IN_EPARA; } sqe->auth_mac_key |= SHIFT_U64(ctx->mac_len / SEC_ENCODE_BYTES, SEC_MAC_OFFSET_V3); alg_type = sec_digest_get_alg_type(ctx->algo); if (alg_type >= A_ALG_MAX) { EMSG("Fail to get digest bd3 alg"); return HISI_QM_DRVCRYPT_IN_EPARA; } sqe->auth_mac_key |= SHIFT_U32(alg_type, SEC_AUTH_ALG_OFFSET_V3); sec_digest_fill_long_bd3(ctx, sqe); return HISI_QM_DRVCRYPT_NO_ERR; } static TEE_Result sec_digest_do_task(struct hisi_qp *qp, void *msg) { TEE_Result ret = TEE_SUCCESS; ret = hisi_qp_send(qp, msg); if (ret) { EMSG("Fail to send task, ret=%d", ret); return TEE_ERROR_BAD_STATE; } ret = hisi_qp_recv_sync(qp, msg); if (ret) { EMSG("Recv task error, ret=%d", ret); return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static enum hisi_drv_status sec_parse_digest_sqe(void *bd, void *msg __unused) { struct hisi_sec_sqe *sqe = bd; uint16_t done = 0; done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0); if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) { EMSG("SEC BD2 fail! done=%#"PRIx16", etype=%#"PRIx8, done, sqe->type2.error_type); return HISI_QM_DRVCRYPT_IN_EPARA; } return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status sec_parse_digest_bd3_sqe(void *bd, void *msg __unused) { struct hisi_sec_bd3_sqe *sqe = bd; uint16_t done = 0; done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0); if (done != SEC_HW_TASK_DONE || sqe->error_type) { EMSG("SEC BD3 fail! done=%#"PRIx16", etype=%#"PRIx8, done, sqe->error_type); return HISI_QM_DRVCRYPT_IN_EPARA; } return HISI_QM_DRVCRYPT_NO_ERR; } TEE_Result hisi_sec_digest_ctx_init(struct hashctx *hash_ctx, const uint8_t *key, size_t len) { if (!hash_ctx) { EMSG("Input hash_ctx is NULL"); return TEE_ERROR_BAD_PARAMETERS; } hash_ctx->in_len = 0; hash_ctx->iv_len = 0; hash_ctx->has_next = false; hash_ctx->long_data_len = 0; hash_ctx->scene = SCENE_NOTHING; /* * In reset ctx scenarios, sec_hash_initialize will be called. * To ensure in data is NULL, reset ctx need to free in data * which is not NULL. */ free(hash_ctx->in); hash_ctx->in = NULL; if (len) { hash_ctx->key_len = len; memcpy(hash_ctx->key, key, len); } return TEE_SUCCESS; } static TEE_Result sec_hash_initialize(struct crypto_hash_ctx *ctx) { struct crypto_hash *hash = NULL; struct hashctx *hash_ctx = NULL; if (!ctx) { EMSG("Input ctx is NULL"); return TEE_ERROR_BAD_PARAMETERS; } hash = to_hash_ctx(ctx); hash_ctx = hash->ctx; return hisi_sec_digest_ctx_init(hash_ctx, NULL, 0); } TEE_Result hisi_sec_digest_do_update(struct hashctx *hash_ctx, const uint8_t *data, size_t len) { TEE_Result ret = TEE_SUCCESS; size_t left_size = 0; hash_ctx->long_data_len += len; if (!hash_ctx->in) { if (len <= SMALL_BUF_SIZE) hash_ctx->buf_len = SMALL_BUF_SIZE; else if (len <= MAX_AUTH_LENGTH) hash_ctx->buf_len = ROUNDUP(len, HISI_QM_ALIGN128); else hash_ctx->buf_len = MAX_AUTH_LENGTH; hash_ctx->in_len = 0; hash_ctx->in = malloc(hash_ctx->buf_len); if (!hash_ctx->in) { EMSG("Fail to alloc in data buf"); return TEE_ERROR_STORAGE_NO_SPACE; } hash_ctx->in_dma = virt_to_phys(hash_ctx->in); if (!hash_ctx->in_dma) { free(hash_ctx->in); hash_ctx->in = NULL; EMSG("Fail to get in_dma"); return TEE_ERROR_STORAGE_NO_SPACE; } } while (len > 0) { if (hash_ctx->in_len + len <= hash_ctx->buf_len) { memcpy(hash_ctx->in + hash_ctx->in_len, data, len); hash_ctx->in_len += len; len = 0; } else { left_size = hash_ctx->buf_len - hash_ctx->in_len; memcpy(hash_ctx->in + hash_ctx->in_len, data, left_size); hash_ctx->in_len = hash_ctx->buf_len; hash_ctx->scene = SCENE_STREAM; hash_ctx->has_next = true; data += left_size; len -= left_size; ret = sec_digest_do_task(hash_ctx->qp, hash_ctx); if (ret) { EMSG("Fail to do digest task! ret = %#"PRIx32, ret); return ret; } hash_ctx->iv_len = hash_ctx->mac_len; hash_ctx->in_len = 0; } } return TEE_SUCCESS; } static TEE_Result sec_hash_do_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { struct crypto_hash *hash = NULL; struct hashctx *hash_ctx = NULL; if (!len) { IMSG("This is 0 len task, skip"); return TEE_SUCCESS; } if (!ctx || (!data && len)) { EMSG("Invalid input parameters"); return TEE_ERROR_BAD_PARAMETERS; } hash = to_hash_ctx(ctx); hash_ctx = hash->ctx; return hisi_sec_digest_do_update(hash_ctx, data, len); } TEE_Result hisi_sec_digest_do_final(struct hashctx *hash_ctx, uint8_t *digest, size_t len) { TEE_Result ret = TEE_SUCCESS; if (!digest || len == 0) { EMSG("Invalid input parameters"); return TEE_ERROR_BAD_PARAMETERS; } if (hash_ctx->mac_len & WORD_ALIGNMENT_MASK) { EMSG("Invalid digest out_bytes"); return TEE_ERROR_BAD_PARAMETERS; } hash_ctx->has_next = false; ret = sec_digest_do_task(hash_ctx->qp, hash_ctx); if (ret) { EMSG("Fail to do digest task! ret = %#"PRIx32, ret); return ret; } memcpy(digest, hash_ctx->out, MIN(hash_ctx->mac_len, len)); return TEE_SUCCESS; } static TEE_Result sec_hash_do_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { struct crypto_hash *hash = to_hash_ctx(ctx); struct hashctx *hash_ctx = hash->ctx; return hisi_sec_digest_do_final(hash_ctx, digest, len); } void hisi_sec_digest_ctx_free(struct hashctx *hash_ctx) { hisi_qm_release_qp(hash_ctx->qp); free(hash_ctx->in); hash_ctx->in = NULL; memzero_explicit(hash_ctx->key, SEC_DIGEST_MAX_KEY_SIZE); free(hash_ctx); } static void sec_hash_ctx_free(struct crypto_hash_ctx *ctx) { struct crypto_hash *hash = NULL; struct hashctx *hash_ctx = NULL; if (!ctx) return; hash = to_hash_ctx(ctx); hash_ctx = hash->ctx; if (!hash_ctx) return; hisi_sec_digest_ctx_free(hash_ctx); hash->ctx = NULL; free(hash); } void hisi_sec_digest_copy_state(struct hashctx *out_hash_ctx, struct hashctx *in_hash_ctx) { out_hash_ctx->iv_len = in_hash_ctx->iv_len; out_hash_ctx->buf_len = in_hash_ctx->buf_len; out_hash_ctx->key_len = in_hash_ctx->key_len; out_hash_ctx->has_next = in_hash_ctx->has_next; out_hash_ctx->long_data_len = in_hash_ctx->long_data_len; if (in_hash_ctx->in) { out_hash_ctx->in = malloc(out_hash_ctx->buf_len); if (!out_hash_ctx->in) { EMSG("Fail to alloc in buf"); return; } out_hash_ctx->in_dma = virt_to_phys(out_hash_ctx->in); if (!out_hash_ctx->in_dma) { free(out_hash_ctx->in); out_hash_ctx->in = NULL; EMSG("Fail to get in_dma"); return; } out_hash_ctx->in_len = in_hash_ctx->in_len; memcpy(out_hash_ctx->in, in_hash_ctx->in, out_hash_ctx->buf_len); } memcpy(out_hash_ctx->iv, in_hash_ctx->iv, out_hash_ctx->iv_len); memcpy(out_hash_ctx->key, in_hash_ctx->key, out_hash_ctx->key_len); } static void sec_hash_copy_state(struct crypto_hash_ctx *out_ctx, struct crypto_hash_ctx *in_ctx) { struct crypto_hash *out_hash = NULL; struct crypto_hash *in_hash = NULL; struct hashctx *out_hash_ctx = NULL; struct hashctx *in_hash_ctx = NULL; if (!out_ctx || !in_ctx) { EMSG("Invalid input parameters"); return; } out_hash = to_hash_ctx(out_ctx); in_hash = to_hash_ctx(in_ctx); out_hash_ctx = out_hash->ctx; in_hash_ctx = in_hash->ctx; hisi_sec_digest_copy_state(out_hash_ctx, in_hash_ctx); } static struct crypto_hash_ops hash_ops = { .init = sec_hash_initialize, .update = sec_hash_do_update, .final = sec_hash_do_final, .free_ctx = sec_hash_ctx_free, .copy_state = sec_hash_copy_state, }; static size_t sec_hash_get_mac_len(uint32_t type) { switch (type) { case TEE_ALG_MD5: case TEE_ALG_HMAC_MD5: return HASH_MAC_LEN128; case TEE_ALG_SHA1: case TEE_ALG_HMAC_SHA1: return HASH_MAC_LEN160; case TEE_ALG_SHA224: case TEE_ALG_HMAC_SHA224: return HASH_MAC_LEN224; case TEE_ALG_SM3: case TEE_ALG_HMAC_SM3: case TEE_ALG_SHA256: case TEE_ALG_HMAC_SHA256: return HASH_MAC_LEN256; case TEE_ALG_SHA384: case TEE_ALG_HMAC_SHA384: return HASH_MAC_LEN384; case TEE_ALG_SHA512: case TEE_ALG_HMAC_SHA512: return HASH_MAC_LEN512; default: return 0; } } static TEE_Result sec_hash_get_dma(struct hashctx *hash_ctx) { hash_ctx->key_dma = virt_to_phys(hash_ctx->key); if (!hash_ctx->key_dma) { EMSG("Fail to get key_dma"); return TEE_ERROR_STORAGE_NO_SPACE; } hash_ctx->iv_dma = virt_to_phys(hash_ctx->iv); if (!hash_ctx->iv_dma) { EMSG("Fail to get iv_dma"); return TEE_ERROR_STORAGE_NO_SPACE; } hash_ctx->out_dma = virt_to_phys(hash_ctx->out); if (!hash_ctx->out_dma) { EMSG("Fail to get out_dma"); return TEE_ERROR_STORAGE_NO_SPACE; } return TEE_SUCCESS; } TEE_Result hisi_sec_hash_ctx_init(struct hashctx *hash_ctx, uint32_t algo) { TEE_Result ret = TEE_SUCCESS; hash_ctx->mac_len = sec_hash_get_mac_len(algo); if (!hash_ctx->mac_len) { EMSG("Invalid algo type %#"PRIx32, algo); return TEE_ERROR_NOT_IMPLEMENTED; } hash_ctx->algo = algo; hash_ctx->mode = algo >> HASH_MODE_OFFSET; ret = sec_hash_get_dma(hash_ctx); if (ret) return ret; hash_ctx->qp = sec_create_qp(HISI_QM_CHANNEL_TYPE0); if (!hash_ctx->qp) { EMSG("Fail to create hash qp"); return TEE_ERROR_BUSY; } if (hash_ctx->qp->qm->version == HISI_QM_HW_V2) { hash_ctx->qp->fill_sqe = sec_digest_fill_sqe; hash_ctx->qp->parse_sqe = sec_parse_digest_sqe; } else { hash_ctx->qp->fill_sqe = sec_digest_fill_bd3_sqe; hash_ctx->qp->parse_sqe = sec_parse_digest_bd3_sqe; } return TEE_SUCCESS; } static TEE_Result sec_hash_ctx_allocate(struct crypto_hash_ctx **ctx, uint32_t algo) { struct crypto_hash *hash = NULL; struct hashctx *hash_ctx = NULL; TEE_Result ret = TEE_SUCCESS; if (!ctx) { EMSG("Ctx is NULL"); return TEE_ERROR_BAD_PARAMETERS; } hash = calloc(1, sizeof(*hash)); if (!hash) { EMSG("Fail to alloc hash"); return TEE_ERROR_STORAGE_NO_SPACE; } hash_ctx = calloc(1, sizeof(*hash_ctx)); if (!hash_ctx) { EMSG("Fail to alloc hash_ctx"); ret = TEE_ERROR_STORAGE_NO_SPACE; goto free_hash; } ret = hisi_sec_hash_ctx_init(hash_ctx, algo); if (ret) goto free_ctx; hash->hash_ctx.ops = &hash_ops; hash->ctx = hash_ctx; *ctx = &hash->hash_ctx; return TEE_SUCCESS; free_ctx: free(hash_ctx); free_hash: free(hash); return ret; } static TEE_Result sec_hash_init(void) { TEE_Result ret = TEE_SUCCESS; ret = drvcrypt_register_hash(&sec_hash_ctx_allocate); if (ret) EMSG("Sec hash register to crypto fail"); return ret; } driver_init(sec_hash_init); optee_os-4.3.0/core/drivers/crypto/hisilicon/sec_hash.h000066400000000000000000000054001464416617300232030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2022-2024 HiSilicon Limited. */ #ifndef __SEC_HASH_H__ #define __SEC_HASH_H__ #include #include #define WORD_ALIGNMENT_MASK 0x3 #define HASH_MODE_OFFSET 28 #define WCRYPTO_DIGEST_HMAC 3 #define WCRYPTO_DIGEST_NORMAL 5 #define MAX_AUTH_LENGTH 16776704 #define HASH_MAC_LEN128 16 #define HASH_MAC_LEN160 20 #define HASH_MAC_LEN224 28 #define HASH_MAC_LEN256 32 #define HASH_MAC_LEN384 48 #define HASH_MAC_LEN512 64 #define SEC_DIGEST_MAX_KEY_SIZE 128 #define SEC_DIGEST_MAX_MAC_SIZE 64 #define SEC_DIGEST_MAX_IV_SIZE 64 #define SMALL_BUF_SIZE 0x1000 struct hashctx { uint8_t key[SEC_DIGEST_MAX_KEY_SIZE]; uint8_t iv[SEC_DIGEST_MAX_IV_SIZE]; uint8_t out[SEC_DIGEST_MAX_MAC_SIZE]; bool has_next; uint8_t mode; uint32_t algo; uint32_t scene; struct hisi_qp *qp; uint8_t *in; uint64_t in_dma; size_t buf_len; size_t in_len; uint64_t out_dma; size_t mac_len; uint64_t key_dma; size_t key_len; uint64_t iv_dma; size_t iv_len; uint64_t long_data_len; }; /* * Format the hash context to keep the reference to the * operation driver */ struct crypto_hash { struct crypto_hash_ctx hash_ctx; /* Crypto Hash API context */ struct hashctx *ctx; /* Hash Context */ }; /* * Format the hmac context to keep the reference to the * operation driver */ struct crypto_hmac { struct crypto_mac_ctx hmac_op; /* Crypto Hash API context */ struct hashctx *ctx; /* Hash Context */ }; enum A_ALG { A_ALG_SHA1 = 0x0, A_ALG_SHA256 = 0x1, A_ALG_MD5 = 0x2, A_ALG_SHA224 = 0x3, A_ALG_SHA384 = 0x4, A_ALG_SHA512 = 0x5, A_ALG_SHA512_224 = 0x6, A_ALG_SHA512_256 = 0x7, A_ALG_HMAC_SHA1 = 0x10, A_ALG_HMAC_SHA256 = 0x11, A_ALG_HMAC_MD5 = 0x12, A_ALG_HMAC_SHA224 = 0x13, A_ALG_HMAC_SHA384 = 0x14, A_ALG_HMAC_SHA512 = 0x15, A_ALG_HMAC_SHA512_224 = 0x16, A_ALG_HMAC_SHA512_256 = 0x17, A_ALG_AES_XCBC_MAC_96 = 0x20, A_ALG_AES_XCBC_PRF_128 = 0x20, A_ALG_AES_CMAC = 0x21, A_ALG_AES_GMAC = 0x22, A_ALG_SM3 = 0x25, A_ALG_HMAC_SM3 = 0x26, A_ALG_MAX }; enum { AI_GEN_INNER = 0x0, AI_GEN_IVIN_ADDR = 0x1, AI_GEN_CAL_IV_ADDR = 0x2, AI_GEN_TRNG = 0x3, }; enum { AUTHPAD_PAD, AUTHPAD_NOPAD, }; TEE_Result hisi_sec_hash_ctx_init(struct hashctx *hash_ctx, uint32_t algo); TEE_Result hisi_sec_digest_ctx_init(struct hashctx *hash_ctx, const uint8_t *key, size_t len); TEE_Result hisi_sec_digest_do_update(struct hashctx *hashctx, const uint8_t *data, size_t len); TEE_Result hisi_sec_digest_do_final(struct hashctx *hashctx, uint8_t *digest, size_t len); void hisi_sec_digest_ctx_free(struct hashctx *hash_ctx); void hisi_sec_digest_copy_state(struct hashctx *out_hash_ctx, struct hashctx *in_hash_ctx); #endif optee_os-4.3.0/core/drivers/crypto/hisilicon/sec_hmac.c000066400000000000000000000067161464416617300231760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2024 HiSilicon Limited. * Kunpeng hardware accelerator sec hmac algorithm implementation. */ #include #include #include "sec_hash.h" #include "sec_main.h" static struct crypto_hmac *to_hmac_ctx(struct crypto_mac_ctx *ctx) { return container_of(ctx, struct crypto_hmac, hmac_op); } static TEE_Result sec_hmac_initialize(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { struct crypto_hmac *hash = NULL; struct hashctx *hash_ctx = NULL; if (!ctx || !key) { EMSG("Input ctx is NULL"); return TEE_ERROR_BAD_PARAMETERS; } hash = to_hmac_ctx(ctx); hash_ctx = hash->ctx; return hisi_sec_digest_ctx_init(hash_ctx, key, len); } static TEE_Result sec_hmac_do_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { struct crypto_hmac *hash = NULL; struct hashctx *hashctx = NULL; if (!len) { IMSG("This is 0 len task, skip"); return TEE_SUCCESS; } if (!ctx || (!data && len)) { EMSG("Invalid input parameters"); return TEE_ERROR_BAD_PARAMETERS; } hash = to_hmac_ctx(ctx); hashctx = hash->ctx; return hisi_sec_digest_do_update(hashctx, data, len); } static TEE_Result sec_hmac_do_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { struct crypto_hmac *hash = to_hmac_ctx(ctx); struct hashctx *hash_ctx = hash->ctx; return hisi_sec_digest_do_final(hash_ctx, digest, len); } static void sec_hmac_ctx_free(struct crypto_mac_ctx *ctx) { struct crypto_hmac *hash = NULL; struct hashctx *hash_ctx = NULL; if (!ctx) return; hash = to_hmac_ctx(ctx); hash_ctx = hash->ctx; if (!hash_ctx) return; memzero_explicit(hash_ctx->key, hash_ctx->key_len); hisi_sec_digest_ctx_free(hash_ctx); hash->ctx = NULL; free(hash); } static void sec_hmac_copy_state(struct crypto_mac_ctx *out_ctx, struct crypto_mac_ctx *in_ctx) { struct crypto_hmac *out_hash = NULL; struct crypto_hmac *in_hash = NULL; struct hashctx *out_hash_ctx = NULL; struct hashctx *in_hash_ctx = NULL; if (!out_ctx || !in_ctx) { EMSG("Invalid input parameters"); return; } out_hash = to_hmac_ctx(out_ctx); in_hash = to_hmac_ctx(in_ctx); out_hash_ctx = out_hash->ctx; in_hash_ctx = in_hash->ctx; hisi_sec_digest_copy_state(out_hash_ctx, in_hash_ctx); } static struct crypto_mac_ops hash_ops = { .init = sec_hmac_initialize, .update = sec_hmac_do_update, .final = sec_hmac_do_final, .free_ctx = sec_hmac_ctx_free, .copy_state = sec_hmac_copy_state, }; static TEE_Result sec_hmac_ctx_allocate(struct crypto_mac_ctx **ctx, uint32_t algo) { struct crypto_hmac *hash = NULL; struct hashctx *hash_ctx = NULL; TEE_Result ret = TEE_SUCCESS; if (!ctx) { EMSG("Ctx is NULL"); return TEE_ERROR_BAD_PARAMETERS; } hash = calloc(1, sizeof(*hash)); if (!hash) { EMSG("Fail to alloc hash"); return TEE_ERROR_OUT_OF_MEMORY; } hash_ctx = calloc(1, sizeof(*hash_ctx)); if (!hash_ctx) { EMSG("Fail to alloc hashctx"); ret = TEE_ERROR_OUT_OF_MEMORY; goto free_hash; } ret = hisi_sec_hash_ctx_init(hash_ctx, algo); if (ret) goto free_ctx; hash->hmac_op.ops = &hash_ops; hash->ctx = hash_ctx; *ctx = &hash->hmac_op; return 0; free_ctx: free(hash_ctx); free_hash: free(hash); return ret; } static TEE_Result sec_hmac_init(void) { TEE_Result ret = TEE_SUCCESS; ret = drvcrypt_register_hmac(&sec_hmac_ctx_allocate); if (ret) EMSG("Sec hmac register to crypto fail"); return ret; } driver_init(sec_hmac_init); optee_os-4.3.0/core/drivers/crypto/hisilicon/sec_main.c000066400000000000000000000170131464416617300232020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2024 HiSilicon Limited. * Kunpeng hardware accelerator SEC module init. */ #include #include #include #include #include #include #include "sec_main.h" #define AM_CFG_SINGLE_PORT_MAX_TRANS 0x300014 #define SEC_CORE_INT_MASK 0x301000 #define SEC_CORE_INT_SOURCE 0x301010 #define SEC_RAS_CE_ENABLE 0x301050 #define SEC_RAS_FE_ENABLE 0x301054 #define SEC_RAS_NFE_ENABLE 0x301058 #define SEC_MEM_START_INIT 0x301100 #define SEC_MEM_INIT_DONE 0x301104 #define SEC_CONTROL_REG 0x301200 #define SEC_INTERFACE_USER_CTRL0 0x301220 #define SEC_INTERFACE_USER_CTRL1 0x301224 #define SEC_SAA_EN 0x301270 #define SEC_BD_ERR_CHK_EN0 0x301380 #define SEC_BD_ERR_CHK_EN1 0x301384 #define SEC_BD_ERR_CHK_EN2 0x301388 #define SEC_BD_ERR_CHK_EN3 0x30138c #define SEC_DYNAMIC_GATE_V3 0x30121c #define SEC_BD_ERR_CHK_EN2_V3 0x301508 #define SEC_CORE_AUTO_GATE_V3 0x30212c #define SEC_INTERFACE_USER_CTRL0_V3 0x302220 #define SEC_INTERFACE_USER_CTRL1_V3 0x302224 #define SEC_SINGLE_PORT_MAX_TRANS 0x2060 #define SEC_ABNML_INT_DISABLE 0x0 #define SEC_RAS_CE_ENB_MASK 0x88 #define SEC_RAS_FE_ENB 0x0 #define SEC_RAS_NFE_ENB_MASK 0x177 #define SEC_CLK_GATE_ENABLE BIT(3) #define SEC_DYNAMIC_GATE_EN 0x7bff #define SEC_CORE_AUTO_GATE_EN GENMASK_32(3, 0) #define SEC_TRNG_EN_MASK BIT(8) #define SEC_SAA_ENABLE 0x17f #define SEC_SAA_ENABLE_V3 0xf #define SEC_BD_ERR_CHK0 0xefffffff #define SEC_BD_ERR_CHK1 0x7ffff7fd #define SEC_BD_ERR_CHK2 0xffff7fff #define SEC_BD_ERR_CHK3 0xffffbfff #define SEC_USER0_CFG 0x20200 #define SEC_USER0_SMMU_NORMAL (BIT(23) | BIT(15)) #define SEC_USER1_CFG 0x12141214 #define SEC_USER1_SMMU_NORMAL (BIT(31) | BIT(23) | BIT(15) | BIT(7)) #define SEC_USER0_CFG_V3 0x20200 #define SEC_USER1_CFG_V3 0x8c494 static SLIST_HEAD(, acc_device) sec_list = SLIST_HEAD_INITIALIZER(sec_list); struct hisi_qp *sec_create_qp(uint8_t sq_type) { struct acc_device *sec_dev = NULL; struct acc_device *cur_dev = NULL; uint32_t free_qp_num = 0; uint32_t max_qp_num = 0; /* Find the SEC device with the most remaining qp numbers */ SLIST_FOREACH(cur_dev, &sec_list, link) { if (cur_dev->qm.fun_type == HISI_QM_HW_PF) free_qp_num = HISI_QM_PF_Q_NUM - cur_dev->qm.qp_in_used; else free_qp_num = HISI_QM_VF_Q_NUM - cur_dev->qm.qp_in_used; if (free_qp_num > max_qp_num) { max_qp_num = free_qp_num; sec_dev = cur_dev; } } if (!sec_dev) { EMSG("No available sec device"); return NULL; } return hisi_qm_create_qp(&sec_dev->qm, sq_type); } static void sec_enable_clock_gate(struct hisi_qm *qm) { if (qm->version == HISI_QM_HW_V2) return; io_setbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE); io_write32(qm->io_base + SEC_DYNAMIC_GATE_V3, SEC_DYNAMIC_GATE_EN); io_write32(qm->io_base + SEC_CORE_AUTO_GATE_V3, SEC_CORE_AUTO_GATE_EN); } static enum hisi_drv_status sec_engine_init(struct acc_device *sec_dev) { struct hisi_qm *qm = &sec_dev->qm; uint32_t val = 0; if (qm->fun_type == HISI_QM_HW_VF) return HISI_QM_DRVCRYPT_NO_ERR; /* QM_HW_V2 version need to close clock gating */ io_clrbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE); hisi_qm_dev_init(qm); io_write32(qm->io_base + SEC_MEM_START_INIT, 0x1); if (IO_READ32_POLL_TIMEOUT(qm->io_base + SEC_MEM_INIT_DONE, val, val & 0x1, POLL_PERIOD, POLL_TIMEOUT)) { EMSG("Fail to init sec mem"); return HISI_QM_DRVCRYPT_ETMOUT; } io_setbits32(qm->io_base + SEC_CONTROL_REG, sec_dev->endian); if (qm->version == HISI_QM_HW_V2) { /* SMMU bypass */ io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0, SEC_USER0_CFG); io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1, SEC_USER1_CFG); io_write32(qm->io_base + AM_CFG_SINGLE_PORT_MAX_TRANS, SEC_SINGLE_PORT_MAX_TRANS); io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE); /* HW V2 enable SM4 extra mode, as CTR/ECB */ io_write32(qm->io_base + SEC_BD_ERR_CHK_EN0, SEC_BD_ERR_CHK0); /* Enable SM4 xts mode multiple iv */ io_write32(qm->io_base + SEC_BD_ERR_CHK_EN1, SEC_BD_ERR_CHK1); /* disable PBKDF2 len check */ io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2, SEC_BD_ERR_CHK2); io_write32(qm->io_base + SEC_BD_ERR_CHK_EN3, SEC_BD_ERR_CHK3); } else { /* cmd_type is controlled by HAC subctrl, default normal */ io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0_V3, SEC_USER0_CFG_V3); io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1_V3, SEC_USER1_CFG_V3); io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE_V3); /* disable PBKDF2 salt len check */ io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2_V3, SEC_BD_ERR_CHK2); } io_write32(qm->io_base + SEC_RAS_CE_ENABLE, SEC_RAS_CE_ENB_MASK); io_write32(qm->io_base + SEC_RAS_FE_ENABLE, SEC_RAS_FE_ENB); io_write32(qm->io_base + SEC_RAS_NFE_ENABLE, SEC_RAS_NFE_ENB_MASK); io_write32(qm->io_base + SEC_CORE_INT_MASK, SEC_ABNML_INT_DISABLE); sec_enable_clock_gate(qm); return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status sec_dev_status_check(struct hisi_qm *qm) { uint32_t val = 0; val = io_read32(qm->io_base + SEC_CORE_INT_SOURCE); if (val & SEC_RAS_NFE_ENB_MASK) { EMSG("SEC NFE RAS happened, need to reset"); return HISI_QM_DRVCRYPT_HW_EACCESS; } val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC); if (val) { if (val & HISI_QM_SEC_NFE_INT_MASK) EMSG("QM NFE RAS happened, need to reset"); if (val & HISI_QM_INVALID_DB) { EMSG("QM invalid db happened, please check"); io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC, HISI_QM_INVALID_DB); } return HISI_QM_DRVCRYPT_HW_EACCESS; } return HISI_QM_DRVCRYPT_NO_ERR; } static enum hisi_drv_status sec_qm_init(struct acc_device *sec_dev) { struct hisi_qm *qm = &sec_dev->qm; qm->io_base = (vaddr_t)phys_to_virt_io(sec_dev->io_base, sec_dev->io_size); if (!qm->io_base) { EMSG("Fail to get qm io_base"); return HISI_QM_DRVCRYPT_EFAULT; } qm->fun_type = sec_dev->fun_type; qm->vfs_num = sec_dev->vfs_num; qm->sqe_size = SEC_SQE_SIZE; qm->sqe_log2_size = SEC_SQE_LOG2_SIZE; if (qm->fun_type == HISI_QM_HW_PF) { hisi_qm_get_version(qm); DMSG("SEC hardware version is %#"PRIx32, qm->version); qm->qp_base = HISI_QM_PF_Q_BASE; qm->qp_num = HISI_QM_PF_Q_NUM; qm->dev_status_check = sec_dev_status_check; } return hisi_qm_init(qm); } static struct acc_device *sec_alloc(void) { struct acc_device *sec_dev = NULL; sec_dev = calloc(1, sizeof(*sec_dev)); if (!sec_dev) { EMSG("Fail to alloc sec_dev"); return NULL; } sec_dev->io_base = SEC_BAR; sec_dev->io_size = SEC_SIZE; sec_dev->fun_type = HISI_QM_HW_PF; SLIST_INSERT_HEAD(&sec_list, sec_dev, link); return sec_dev; } static void sec_free(struct acc_device *sec_dev) { SLIST_REMOVE_HEAD(&sec_list, link); free(sec_dev); } static TEE_Result sec_probe(void) { enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; struct acc_device *sec_dev = NULL; struct hisi_qm *qm = NULL; DMSG("SEC driver init start"); sec_dev = sec_alloc(); if (!sec_dev) return TEE_ERROR_OUT_OF_MEMORY; qm = &sec_dev->qm; ret = sec_qm_init(sec_dev); if (ret) { EMSG("Fail to init sec qm, ret=%d", ret); goto err_with_pre_init; } ret = sec_engine_init(sec_dev); if (ret) { EMSG("fail to init engine, ret=%d", ret); goto err_with_qm_init; } ret = hisi_qm_start(qm); if (ret) { EMSG("Fail to start qm, ret=%d", ret); goto err_with_qm_init; } DMSG("SEC driver init done"); return TEE_SUCCESS; err_with_qm_init: hisi_qm_uninit(qm); err_with_pre_init: sec_free(sec_dev); return TEE_ERROR_BAD_STATE; } driver_init(sec_probe); optee_os-4.3.0/core/drivers/crypto/hisilicon/sec_main.h000066400000000000000000000142671464416617300232170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2022-2024 HiSilicon Limited. */ #ifndef __SEC_MAIN_H #define __SEC_MAIN_H #include "hisi_qm.h" #ifdef CFG_HISILICON_ACC_V3 #define SEC_BAR 0x160000000 #else #define SEC_BAR 0x141800000 #endif #define SEC_SIZE 0x400000 #define SEC_SQE_SIZE 128 #define SEC_SQE_LOG2_SIZE 7 #define AES_KEYSIZE_128 16 #define AES_KEYSIZE_192 24 #define AES_KEYSIZE_256 32 #define SEC_HW_TASK_DONE 0x1 #define SEC_DONE_MASK 0x0001 #define SEC_ICV_MASK 0x000E #define SEC_HW_ICV_ERR 0x2 #define SEC_ENCODE_BYTES 4 #define BYTE_BITS 0x8 #define SEC_SCENE_OFFSET 3 #define SEC_DE_OFFSET 1 #define SEC_CIPHER_OFFSET 4 #define SEC_AUTH_OFFSET 6 #define SEC_CMODE_OFFSET 12 #define SEC_CKEY_OFFSET 9 #define SEC_AKEY_OFFSET 5 #define SEC_AEAD_ALG_OFFSET 11 #define SEC_HUK_OFFSET 4 #define SEC_APAD_OFFSET 2 #define SEC_DE_OFFSET_V3 9 #define SEC_SCENE_OFFSET_V3 5 #define SEC_CKEY_OFFSET_V3 13 #define SEC_CALG_OFFSET_V3 4 #define SEC_AKEY_OFFSET_V3 9 #define SEC_MAC_OFFSET_V3 4 #define SEC_AUTH_ALG_OFFSET_V3 15 #define SEC_CIPHER_AUTH_V3 0xbf #define SEC_AUTH_CIPHER_V3 0x40 #define SEC_AI_GEN_OFFSET_V3 2 #define SEC_SEQ_OFFSET_V3 6 #define SEC_ICV_LEN_OFFSET_V3 4 #define SEC_DK_LEN_OFFSET_V3 16 #define SEC_KEY_SEL_OFFSET_V3 21 #define SEC_GET_FIELD(val, mask, shift) (((val) & (mask)) >> (shift)) struct hisi_sec_sqe_type2 { /* * mac_len: 0~4 bits * a_key_len: 5~10 bits * a_alg: 11~16 bits */ uint32_t mac_key_alg; /* * c_icv_len: 0~5 bits * c_width: 6~8 bits * c_key_len: 9~11 bits * c_mode: 12~15 bits */ uint16_t icvw_kmode; /* c_alg: 0~3 bits */ uint8_t c_alg; uint8_t rsvd4; /* * a_len: 0~23 bits * iv_offset_l: 24~31 bits */ uint32_t alen_ivllen; /* * c_len: 0~23 bits * iv_offset_h: 24~31 bits */ uint32_t clen_ivhlen; uint16_t auth_src_offset; uint16_t cipher_src_offset; uint16_t cs_ip_header_offset; uint16_t cs_udp_header_offset; uint16_t pass_word_len; uint16_t dk_len; uint8_t salt3; uint8_t salt2; uint8_t salt1; uint8_t salt0; uint16_t tag; uint16_t rsvd5; /* * c_pad_type: 0~3 bits * c_pad_len: 4~11 bits * c_pad_data_type: 12~15 bits */ uint16_t cph_pad; /* c_pad_len_field: 0~1 bits */ uint16_t c_pad_len_field; uint64_t long_a_data_len; uint64_t a_ivin_addr; uint64_t a_key_addr; uint64_t mac_addr; uint64_t c_ivin_addr; uint64_t c_key_addr; uint64_t data_src_addr; uint64_t data_dst_addr; /* * done: 0 bit * icv: 1~3 bits * csc: 4~6 bits * flag: 7~10 bits */ uint16_t done_flag; uint8_t error_type; uint8_t warning_type; uint8_t mac_i3; uint8_t mac_i2; uint8_t mac_i1; uint8_t mac_i0; uint16_t check_sum_i; uint8_t tls_pad_len_i; uint8_t rsvd12; uint32_t counter; }; struct hisi_sec_sqe { /* * type: 0~3 bits; * cipher: 4~5 bits; * auth: 6~7 bits; */ uint8_t type_auth_cipher; /* * seq: 0 bits; * de: 1~2 bits; * scene: 3~6 bits; * src_addr_type: 7 bits; */ uint8_t sds_sa_type; /* * src_addr_type: 0~1 bits not used now. * dst_addr_type: 2~4 bits; * mac_addr_type: 5~7 bits; */ uint8_t sdm_addr_type; uint8_t rsvd0; /* * nonce_len(type): 0~3 bits; * huk: 4 bit; * key_s: 5 bit * ci_gen: 6~7 bits */ uint8_t huk_ci_key; /* * ai_gen: 0~1 bits; * a_pad : 2~3 bits; * c_s : 4~5 bits; */ uint8_t ai_apd_cs; /* * rhf(type2): 0 bit; * c_key_type: 1~2 bits; * a_key_type: 3~4 bits * write_frame_len(type2): 5~7bits; */ uint8_t rca_key_frm; uint8_t iv_tls_ld; struct hisi_sec_sqe_type2 type2; /* the other scene */ }; struct bd3_stream_scene { uint64_t c_ivin_addr; uint64_t long_a_data_len; /* * auth_pad: 0~1 bits * stream_protocol: 2~4 bits * reserved: 5~7 bits */ uint8_t auth_pad; uint8_t plaintext_type; uint16_t pad_len_1p3; } __packed __aligned(4); struct bd3_no_scene { uint64_t c_ivin_addr; uint32_t rsvd0; uint32_t rsvd1; uint32_t rsvd2; } __packed __aligned(4); struct bd3_pbkdf2_scene { uint64_t c_ivin_addr; /* * pbkdf2_salt_len: 0~23 bits * rsvd0: 24~31 bits */ uint32_t pbkdf2_salt_len; /* * c_num: 0~23 bits * rsvd1: 24~31 bits */ uint32_t c_num; /* * pass_word_len: 0~15 bits * dk_len: 16~31 bits */ uint32_t pass_word_dk_len; } __packed __aligned(4); struct hisi_sec_bd3_sqe { /* * type: 0~3 bit * bd_invalid: 4 bit * scene: 5~8 bit * de: 9~10 bit * src_addr_type: 11~13 bit * dst_addr_type: 14~16 bit * mac_addr_type: 17~19 bit * reserved: 20~31 bits */ uint32_t bd_param; /* * cipher: 0~1 bits * ci_gen: 2~3 bit * c_icv_len: 4~9 bit * c_width: 10~12 bits * c_key_len: 13~15 bits */ uint16_t c_icv_key; /* * c_mode : 0~3 bits * c_alg : 4~7 bits */ uint8_t c_mode_alg; /* * nonce_len : 0~3 bits * huk : 4 bits * cal_iv_addr_en : 5 bits * seq : 6 bits * reserved : 7 bits */ uint8_t huk_iv_seq; uint64_t tag; uint64_t data_src_addr; uint64_t a_key_addr; uint64_t a_ivin_addr; uint64_t rsvd; uint64_t c_key_addr; /* * auth: 0~1 bits * ai_gen: 2~3 bits * mac_len: 4~8 bits * akey_len: 9~14 bits * a_alg: 15~20 bits * key_sel: 21~24 bits * ctr_count_mode/sm4_xts: 25~26 bits * sva_prefetch: 27 bits * key_wrap_num:28~30 bits * update_key: 31 bits */ uint32_t auth_mac_key; uint32_t salt; uint16_t auth_src_offset; uint16_t cipher_src_offset; /* * auth_len: 0~23 bit * auth_key_offset: 24~31 bits */ uint32_t a_len_key; /* * cipher_len: 0~23 bit * auth_ivin_offset: 24~31 bits */ uint32_t c_len_ivin; uint64_t data_dst_addr; uint64_t mac_addr; union { struct bd3_stream_scene stream_scene; struct bd3_no_scene no_scene; struct bd3_pbkdf2_scene pbkdf2_scene; }; /* * done: 0 bit * icv: 1~3 bit * csc: 4~6 bit * flag: 7~10 bit * reserved: 11~15 bit */ uint16_t done_flag; uint8_t error_type; uint8_t warning_type; uint64_t kek_key_addr; uint32_t counter; } __packed __aligned(4); enum sec_bd_type { BD_TYPE1 = 0x1, BD_TYPE2 = 0x2, BD_TYPE3 = 0x3, }; enum sec_bd_scene { SCENE_NOTHING = 0x0, SCENE_STREAM = 0x7, SCENE_PBKDF2 = 0x8, }; enum sec_auth_dir { NO_AUTH, AUTH_MAC_CALCULATE, AUTH_MAC_VERIFY, }; /* * Create task queue pair for SEC. * * @sq_type Task type of the submmission queue. */ struct hisi_qp *sec_create_qp(uint8_t sq_type); #endif optee_os-4.3.0/core/drivers/crypto/hisilicon/sub.mk000066400000000000000000000002511464416617300223760ustar00rootroot00000000000000srcs-y += hisi_qm.c srcs-y += sec_main.c srcs-y += sec_hash.c srcs-y += sec_hmac.c srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c srcs-$(CFG_HISILICON_ACC_V3) += hpre_dh.c optee_os-4.3.0/core/drivers/crypto/se050/000077500000000000000000000000001464416617300201315ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/adaptors/000077500000000000000000000000001464416617300217465ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/adaptors/apis/000077500000000000000000000000001464416617300227025ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/adaptors/apis/apdu.c000066400000000000000000000464211464416617300240060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include sss_status_t se050_factory_reset(pSe05xSession_t ctx) { if (!ctx) return kStatus_SSS_Fail; if (Se05x_API_DeleteAll_Iterative(ctx) == SM_OK) return kStatus_SSS_Success; return kStatus_SSS_Fail; } bool se050_key_exists(uint32_t key_id, pSe05xSession_t ctx) { SE05x_Result_t inuse = kSE05x_Result_FAILURE; smStatus_t status = SM_OK; if (!ctx) return false; status = Se05x_API_CheckObjectExists(ctx, key_id, &inuse); if (status != SM_OK) return false; if (inuse == kSE05x_Result_SUCCESS) return true; return false; } static sss_status_t set_rsa_public(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, struct se050_rsa_keypub *keypub, size_t key_bit_len) { SE05x_TransientType_t type = kSE05x_TransientType_Transient; SE05x_RSAKeyFormat_t rsa_format = kSE05x_RSAKeyFormat_RAW; smStatus_t status = SM_OK; if (k_object->isPersistant) type = kSE05x_TransientType_Persistent; switch (k_object->cipherType) { case kSSS_CipherType_RSA: rsa_format = kSE05x_RSAKeyFormat_RAW; break; case kSSS_CipherType_RSA_CRT: rsa_format = kSE05x_RSAKeyFormat_CRT; break; default: return kStatus_SSS_Fail; } status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, (U16)key_bit_len, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, keypub->e, keypub->e_len, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_Public, rsa_format); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, keypub->n, keypub->n_len, (SE05x_INS_t)type, kSE05x_KeyPart_NA, rsa_format); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_rsa_private_rsa(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, struct se050_rsa_keypair *keypair, size_t key_bit_len) { SE05x_TransientType_t type = kSE05x_TransientType_Transient; smStatus_t status = SM_OK; if (k_object->isPersistant) type = kSE05x_TransientType_Persistent; status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, (U16)key_bit_len, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, keypair->d, keypair->d_len, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_Pair, kSE05x_RSAKeyFormat_RAW); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, keypair->n, keypair->n_len, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_RAW); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_rsa_private_rsa_crt(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, struct se050_rsa_keypair *keypair, size_t key_bit_len) { SE05x_TransientType_t type = kSE05x_TransientType_Transient; smStatus_t status = SM_OK; if (k_object->isPersistant) type = kSE05x_TransientType_Persistent; status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, (U16)key_bit_len, keypair->p, keypair->p_len, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_Private, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, keypair->q, keypair->q_len, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, keypair->dp, keypair->dp_len, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, keypair->dq, keypair->dq_len, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, keypair->qp, keypair->qp_len, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_rsa_keypair_rsa(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, struct se050_rsa_keypair *keypair, size_t key_bit_len) { SE05x_TransientType_t type = kSE05x_TransientType_Transient; smStatus_t status = SM_OK; if (k_object->isPersistant) type = kSE05x_TransientType_Persistent; status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, (U16)key_bit_len, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, keypair->e, keypair->e_len, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_Pair, kSE05x_RSAKeyFormat_RAW); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, keypair->d, keypair->d_len, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_RAW); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, keypair->n, keypair->n_len, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_RAW); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_rsa_keypair_rsa_crt(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, struct se050_rsa_keypair *keypair, size_t key_bit_len) { SE05x_TransientType_t type = kSE05x_TransientType_Transient; smStatus_t status = SM_OK; if (k_object->isPersistant) type = kSE05x_TransientType_Persistent; status = Se05x_API_WriteRSAKey(s_ctx, policy, k_object->keyId, (U16)key_bit_len, keypair->p, keypair->p_len, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_Pair, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, keypair->q, keypair->q_len, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, keypair->dp, keypair->dp_len, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, keypair->dq, keypair->dq_len, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, keypair->qp, keypair->qp_len, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, keypair->e, keypair->e_len, SE05X_RSA_NO_priv, SE05X_RSA_NO_pubMod, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; status = Se05x_API_WriteRSAKey(s_ctx, NULL, k_object->keyId, 0, SE05X_RSA_NO_p, SE05X_RSA_NO_q, SE05X_RSA_NO_dp, SE05X_RSA_NO_dq, SE05X_RSA_NO_qInv, SE05X_RSA_NO_pubExp, SE05X_RSA_NO_priv, keypair->n, keypair->n_len, (SE05x_INS_t)type, kSE05x_KeyPart_NA, kSE05x_RSAKeyFormat_CRT); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } sss_status_t se050_key_store_set_rsa_key_bin(sss_se05x_key_store_t *store, sss_se05x_object_t *k_object, struct se050_rsa_keypair *keypair, struct se050_rsa_keypub *keypub, size_t key_bit_len) { Se05xPolicy_t policy = { }; if (!store || !store->session || !k_object) return kStatus_SSS_Fail; if (se050_key_exists(k_object->keyId, &store->session->s_ctx)) key_bit_len = 0; switch (k_object->objectType) { case kSSS_KeyPart_Public: return set_rsa_public(&store->session->s_ctx, &policy, k_object, keypub, key_bit_len); case kSSS_KeyPart_Private: if (k_object->cipherType == kSSS_CipherType_RSA) return set_rsa_private_rsa(&store->session->s_ctx, &policy, k_object, keypair, key_bit_len); if (k_object->cipherType == kSSS_CipherType_RSA_CRT) return set_rsa_private_rsa_crt(&store->session->s_ctx, &policy, k_object, keypair, key_bit_len); return kStatus_SSS_Fail; case kSSS_KeyPart_Pair: if (k_object->cipherType == kSSS_CipherType_RSA) return set_rsa_keypair_rsa(&store->session->s_ctx, &policy, k_object, keypair, key_bit_len); if (k_object->cipherType == kSSS_CipherType_RSA_CRT) return set_rsa_keypair_rsa_crt(&store->session->s_ctx, &policy, k_object, keypair, key_bit_len); return kStatus_SSS_Fail; default: return kStatus_SSS_Fail; } } sss_status_t se050_get_free_memory(pSe05xSession_t ctx, uint16_t *p, SE05x_MemoryType_t type) { if (p && ctx && Se05x_API_GetFreeMemory(ctx, type, p) == SM_OK) return kStatus_SSS_Success; return kStatus_SSS_Fail; } sss_status_t se050_scp03_send_rotate_cmd(pSe05xSession_t ctx, struct s050_scp_rotate_cmd *cmd) { uint8_t rsp[64] = { 0 }; size_t rsp_len = sizeof(rsp); tlvHeader_t hdr = { .hdr = { [0] = 0x80, [1] = 0xd8, [2] = 0, [3] = PUT_KEYS_KEY_IDENTIFIER, }, }; smStatus_t st = SM_NOT_OK; if (!ctx || !cmd) return kStatus_SSS_Fail; hdr.hdr[2] = cmd->cmd[0]; st = DoAPDUTxRx_s_Case4(ctx, &hdr, cmd->cmd, cmd->cmd_len, rsp, &rsp_len); if ((rsp_len - 1 > sizeof(rsp)) || rsp_len < 2) return kStatus_SSS_Fail; st = (rsp[rsp_len - 2] << 8) + rsp[rsp_len - 1]; if (st != SM_OK) return kStatus_SSS_Fail; if (!memcmp(rsp, cmd->kcv, cmd->kcv_len)) return kStatus_SSS_Success; return kStatus_SSS_Fail; } static uint8_t *alloc_pubkey_buf(struct se050_ecc_keypub *keypub, size_t *len) { size_t pubkey_len = 0; uint8_t *pubkey = NULL; uint8_t *buf = NULL; pubkey_len = keypub->x_len + keypub->y_len + 1; buf = malloc(pubkey_len); if (!buf) return NULL; *buf = 0x04; pubkey = buf + 1; memcpy(pubkey, keypub->x, keypub->x_len); memcpy(pubkey + keypub->x_len, keypub->y, keypub->y_len); *len = pubkey_len; return buf; } sss_status_t se050_ecc_gen_shared_secret(pSe05xSession_t ctx, uint32_t kid, struct se050_ecc_keypub *keypub, uint8_t *secret, size_t *len) { smStatus_t status = SM_OK; uint8_t *buf = NULL; size_t pubkey_len = 0; if (!keypub || !secret || !len) return kStatus_SSS_Fail; buf = alloc_pubkey_buf(keypub, &pubkey_len); if (!buf) return kStatus_SSS_Fail; status = Se05x_API_ECGenSharedSecret(ctx, kid, buf, pubkey_len, secret, len); free(buf); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_ecc_public(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, SE05x_TransientType_t type, struct se050_ecc_keypub *keypub) { size_t pubkey_len = 0; smStatus_t status = SM_NOT_OK; uint8_t *buf = NULL; buf = alloc_pubkey_buf(keypub, &pubkey_len); if (!buf) return kStatus_SSS_Fail; k_object->curve_id = keypub->curve; status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, k_object->keyId, keypub->curve, NULL, 0, buf, pubkey_len, (SE05x_INS_t)type, kSE05x_KeyPart_Public); free(buf); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_ecc_private(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, SE05x_TransientType_t type, struct se050_ecc_keypair *keypair) { smStatus_t status = SM_NOT_OK; k_object->curve_id = keypair->pub.curve; status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, k_object->keyId, keypair->pub.curve, keypair->d, keypair->d_len, NULL, 0, (SE05x_INS_t)type, kSE05x_KeyPart_Private); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } static sss_status_t set_ecc_pair(Se05xSession_t *s_ctx, Se05xPolicy_t *policy, sss_se05x_object_t *k_object, SE05x_TransientType_t type, struct se050_ecc_keypair *keypair) { size_t pubkey_len = 0; smStatus_t status = SM_NOT_OK; uint8_t *buf = NULL; buf = alloc_pubkey_buf(&keypair->pub, &pubkey_len); if (!buf) return kStatus_SSS_Fail; k_object->curve_id = keypair->pub.curve; status = Se05x_API_WriteECKey(s_ctx, policy, SE05x_MaxAttemps_UNLIMITED, k_object->keyId, keypair->pub.curve, keypair->d, keypair->d_len, buf, pubkey_len, (SE05x_INS_t)type, kSE05x_KeyPart_Pair); free(buf); if (status != SM_OK) return kStatus_SSS_Fail; return kStatus_SSS_Success; } sss_status_t se050_key_store_set_ecc_key_bin(sss_se05x_key_store_t *store, sss_se05x_object_t *k_object, struct se050_ecc_keypair *keypair, struct se050_ecc_keypub *keypub) { SE05x_TransientType_t type = kSE05x_TransientType_Transient; Se05xPolicy_t policy = { }; if (!store || !store->session || !k_object) return kStatus_SSS_Fail; if (k_object->isPersistant) type = kSE05x_TransientType_Persistent; switch (k_object->objectType) { case kSSS_KeyPart_Public: if (!keypub) return kStatus_SSS_Fail; return set_ecc_public(&store->session->s_ctx, &policy, k_object, type, keypub); case kSSS_KeyPart_Private: if (!keypair) return kStatus_SSS_Fail; return set_ecc_private(&store->session->s_ctx, &policy, k_object, type, keypair); case kSSS_KeyPart_Pair: if (!keypair) return kStatus_SSS_Fail; return set_ecc_pair(&store->session->s_ctx, &policy, k_object, type, keypair); default: return kStatus_SSS_Fail; } } sss_status_t se050_key_store_get_ecc_key_bin(sss_se05x_key_store_t *store, sss_se05x_object_t *k_object, uint8_t *key, size_t *key_len) { smStatus_t status = SM_NOT_OK; uint8_t *buf = NULL; size_t buflen = 0; if (!store || !store->session || !k_object || !key || !key_len) return kStatus_SSS_Fail; switch (k_object->cipherType) { case kSSS_CipherType_EC_NIST_P: case kSSS_CipherType_EC_NIST_K: case kSSS_CipherType_EC_BRAINPOOL: case kSSS_CipherType_EC_BARRETO_NAEHRIG: case kSSS_CipherType_EC_MONTGOMERY: case kSSS_CipherType_EC_TWISTED_ED: add_ecc_header(key, key_len, &buf, &buflen, k_object->curve_id); status = Se05x_API_ReadObject(&store->session->s_ctx, k_object->keyId, 0, 0, buf, key_len); if (status != SM_OK) return kStatus_SSS_Fail; *key_len += buflen; buflen = *key_len; get_ecc_raw_data(key, *key_len, &buf, &buflen, k_object->curve_id); /* return only the binary data */ *key_len = buflen; memcpy(key, buf, buflen); return kStatus_SSS_Success; default: return kStatus_SSS_Fail; } } optee_os-4.3.0/core/drivers/crypto/se050/adaptors/apis/sss.c000066400000000000000000000131121464416617300236540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include static const sss_policy_u asym_key = { .type = KPolicy_Asym_Key, .auth_obj_id = 0, .policy = { .asymmkey = { .can_Sign = 1, .can_Verify = 1, .can_Encrypt = 1, .can_Decrypt = 1, .can_KD = 1, .can_Wrap = 1, .can_Write = 1, .can_Gen = 1, .can_Import_Export = 1, .can_KA = 1, .can_Read = 1, .can_Attest = 1, } } }; static const sss_policy_u common = { .type = KPolicy_Common, .auth_obj_id = 0, .policy = { .common = { .can_Delete = 1, .can_Read = 1, .can_Write = 1, .req_Sm = 1, }, }, }; sss_policy_t se050_asym_policy = { .nPolicies = 2, .policies = { &asym_key, &common }, }; sss_status_t se050_rotate_scp03_keys(struct sss_se05x_ctx *ctx) { struct s050_scp_rotate_cmd cmd = { }; sss_status_t status = kStatus_SSS_Fail; struct se050_scp_key cur_keys = { }; struct se050_scp_key new_keys = { }; SE_Connect_Ctx_t *connect_ctx = NULL; sss_se05x_session_t *session = NULL; if (!ctx) return kStatus_SSS_Fail; if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS)) { /* Public */ status = se050_scp03_get_keys(&new_keys, SCP03_OFID); if (status != kStatus_SSS_Success) return status; } else { /* Secret */ status = se050_scp03_subkey_derive(&new_keys); if (status != kStatus_SSS_Success) return status; } status = se050_scp03_get_current_keys(&cur_keys); if (status != kStatus_SSS_Success) return status; if (IS_ENABLED(CFG_CORE_SE05X_DISPLAY_SCP03_KEYS)) { IMSG("scp03: current keys"); nLog_au8("scp03", 0xff, "dek: ", cur_keys.dek, SE050_SCP03_KEY_SZ); nLog_au8("scp03", 0xff, "mac: ", cur_keys.mac, SE050_SCP03_KEY_SZ); nLog_au8("scp03", 0xff, "enc: ", cur_keys.enc, SE050_SCP03_KEY_SZ); IMSG("scp03: proposed new keys"); nLog_au8("scp03", 0xff, "dek: ", new_keys.dek, SE050_SCP03_KEY_SZ); nLog_au8("scp03", 0xff, "mac: ", new_keys.mac, SE050_SCP03_KEY_SZ); nLog_au8("scp03", 0xff, "enc: ", new_keys.enc, SE050_SCP03_KEY_SZ); } if (!consttime_memcmp(new_keys.enc, cur_keys.enc, SE050_SCP03_KEY_SZ) && !consttime_memcmp(new_keys.mac, cur_keys.mac, SE050_SCP03_KEY_SZ) && !consttime_memcmp(new_keys.dek, cur_keys.dek, SE050_SCP03_KEY_SZ)) return kStatus_SSS_Success; connect_ctx = &ctx->open_ctx; session = &ctx->session; status = se050_scp03_prepare_rotate_cmd(ctx, &cmd, &new_keys); if (status != kStatus_SSS_Success) return status; sss_se05x_refresh_session(se050_session, NULL); sss_se05x_session_close(session); /* re-open session with same keys */ connect_ctx->skip_select_applet = 1; status = sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0, kSSS_ConnectionType_Encrypted, connect_ctx); if (status != kStatus_SSS_Success) { se050_scp03_set_disable(); EMSG("scp03 re-open failed, session lost"); return kStatus_SSS_Fail; } status = se050_scp03_send_rotate_cmd(&session->s_ctx, &cmd); if (status != kStatus_SSS_Success) { EMSG("scp03 keys not updated"); return kStatus_SSS_Fail; } sss_host_session_close(&ctx->host_session); sss_se05x_session_close(se050_session); memset(ctx, 0, sizeof(*ctx)); /* open session with new keys */ if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS)) se050_scp03_set_enable(SCP03_OFID); else se050_scp03_set_enable(SCP03_DERIVED); if (se050_core_early_init(&new_keys)) { se050_scp03_set_disable(); EMSG("scp03 keys rejected, session lost"); return kStatus_SSS_Fail; } return kStatus_SSS_Success; } sss_status_t se050_enable_scp03(sss_se05x_session_t *session) { struct se050_scp_key keys = { }; sss_status_t status = kStatus_SSS_Success; enum se050_scp03_ksrc key_src[] = { SCP03_DERIVED, SCP03_CFG, SCP03_OFID }; size_t i = 0; if (se050_scp03_enabled()) return kStatus_SSS_Success; for (i = 0; i < ARRAY_SIZE(key_src); i++) { status = se050_scp03_get_keys(&keys, key_src[i]); if (status != kStatus_SSS_Success) continue; if (session->subsystem) sss_se05x_session_close(session); if (!se050_core_early_init(&keys)) { se050_scp03_set_enable(key_src[i]); goto out; } sss_host_session_close(&se050_ctx.host_session); } return kStatus_SSS_Fail; out: if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION_ON_INIT)) return se050_rotate_scp03_keys(&se050_ctx); return kStatus_SSS_Success; } sss_status_t se050_session_open(struct sss_se05x_ctx *ctx, struct se050_scp_key *current_keys) { sss_status_t status = kStatus_SSS_Fail; SE_Connect_Ctx_t *connect_ctx = NULL; sss_se05x_session_t *session = NULL; if (!ctx) return kStatus_SSS_Fail; connect_ctx = &ctx->open_ctx; session = &ctx->session; connect_ctx->connType = kType_SE_Conn_Type_T1oI2C; connect_ctx->portName = NULL; if (!current_keys) { return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0, kSSS_ConnectionType_Plain, connect_ctx); } status = se050_configure_host(&ctx->host_session, &ctx->host_ks, &ctx->open_ctx, &ctx->se05x_auth, kSSS_AuthType_SCP03, current_keys); if (status != kStatus_SSS_Success) return status; return sss_se05x_session_open(session, kType_SSS_SE_SE05x, 0, kSSS_ConnectionType_Encrypted, connect_ctx); } sss_status_t se050_key_store_and_object_init(struct sss_se05x_ctx *ctx) { if (!ctx) return kStatus_SSS_Fail; return sss_se05x_key_store_context_init(&ctx->ks, &ctx->session); } optee_os-4.3.0/core/drivers/crypto/se050/adaptors/apis/user.c000066400000000000000000000101101464416617300240150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include static sss_status_t alloc_scp_key_to_auth(sss_object_t *k_object, sss_key_store_t *k_store, uint32_t key_id) { sss_status_t status = kStatus_SSS_Fail; if (!k_object || !k_store) return kStatus_SSS_Fail; status = sss_host_key_object_init(k_object, k_store); if (status != kStatus_SSS_Success) return status; return sss_host_key_object_allocate_handle(k_object, key_id, kSSS_KeyPart_Default, kSSS_CipherType_AES, 16, kKeyObject_Mode_Transient); } static sss_status_t prepare_host_scp(NXSCP03_AuthCtx_t *scp, struct se050_auth_ctx *auth, sss_key_store_t *k_store, struct se050_scp_key *keys, uint32_t oid) { sss_status_t status = kStatus_SSS_Fail; NXSCP03_StaticCtx_t *pStatic_ctx = NULL; NXSCP03_DynCtx_t *pDyn_ctx = NULL; size_t len = 0; if (!scp || !auth || !k_store) return kStatus_SSS_Fail; pStatic_ctx = &auth->static_ctx; pDyn_ctx = &auth->dynamic_ctx; scp->pStatic_ctx = pStatic_ctx; scp->pDyn_ctx = pDyn_ctx; pStatic_ctx->keyVerNo = 0x0B; status = alloc_scp_key_to_auth(&pStatic_ctx->Enc, k_store, oid++); if (status != kStatus_SSS_Success) return status; len = sizeof(keys->enc); status = sss_host_key_store_set_key(k_store, &pStatic_ctx->Enc, keys->enc, len, len * 8, NULL, 0); if (status != kStatus_SSS_Success) return status; status = alloc_scp_key_to_auth(&pStatic_ctx->Mac, k_store, oid++); if (status != kStatus_SSS_Success) return status; len = sizeof(keys->mac); status = sss_host_key_store_set_key(k_store, &pStatic_ctx->Mac, keys->mac, len, len * 8, NULL, 0); if (status != kStatus_SSS_Success) return status; status = alloc_scp_key_to_auth(&pStatic_ctx->Dek, k_store, oid++); if (status != kStatus_SSS_Success) return status; len = sizeof(keys->dek); status = sss_host_key_store_set_key(k_store, &pStatic_ctx->Dek, keys->dek, len, len * 8, NULL, 0); if (status != kStatus_SSS_Success) return status; status = alloc_scp_key_to_auth(&pDyn_ctx->Enc, k_store, oid++); if (status != kStatus_SSS_Success) return status; status = alloc_scp_key_to_auth(&pDyn_ctx->Mac, k_store, oid++); if (status != kStatus_SSS_Success) return status; return alloc_scp_key_to_auth(&pDyn_ctx->Rmac, k_store, oid++); } sss_status_t se050_configure_host(sss_user_impl_session_t *host_session, sss_key_store_t *host_ks, SE_Connect_Ctx_t *open_ctx, struct se050_auth_ctx *auth, SE_AuthType_t auth_type, struct se050_scp_key *keys) { sss_status_t status = kStatus_SSS_Fail; uint32_t host_oid = 0; if (!host_session || !host_ks || !open_ctx || !auth) return kStatus_SSS_Fail; if (host_session->subsystem != kType_SSS_SubSystem_NONE) goto prepare; status = sss_host_session_open(host_session, kType_SSS_Software, 0, kSSS_ConnectionType_Plain, NULL); if (status != kStatus_SSS_Success) return status; status = sss_host_key_store_context_init(host_ks, host_session); if (status != kStatus_SSS_Success) goto error; status = sss_host_key_store_allocate(host_ks, host_oid++); if (status != kStatus_SSS_Success) goto error; prepare: status = prepare_host_scp(&open_ctx->auth.ctx.scp03, auth, host_ks, keys, host_oid); if (status != kStatus_SSS_Success) goto error; open_ctx->auth.authType = auth_type; return status; error: sss_host_session_close(host_session); return status; } TEE_Result se050_host_key_store_get_key(sss_key_store_t *ks __unused, sss_object_t *ko, uint8_t *data, size_t *byte_len, size_t *bit_len) { sss_user_impl_object_t *key_object = (sss_user_impl_object_t *)ko; if (!ko) return TEE_ERROR_GENERIC; if (*byte_len < sizeof(key_object->key)) return TEE_ERROR_EXCESS_DATA; memcpy(data, key_object->key, sizeof(key_object->key)); *byte_len = sizeof(key_object->key); *bit_len = 8 * sizeof(key_object->key); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/crypto/se050/adaptors/include/000077500000000000000000000000001464416617300233715ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/adaptors/include/se050.h000066400000000000000000000023431464416617300244000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef SE050_H_ #define SE050_H_ #include #include #include #include #include #include #include #include #include #include /* Supported Devices*/ #define SE050A1_ID 0xA204 #define SE050A2_ID 0xA205 #define SE050B1_ID 0xA202 #define SE050B2_ID 0xA203 #define SE050C1_ID 0xA200 #define SE050C2_ID 0xA201 #define SE050DV_ID 0xA1F4 #define SE051A2_ID 0xA565 #define SE051C2_ID 0xA564 #define SE050F2_ID 0xA77E #define SE050E_ID 0xA921 #define SE051A_ID 0xA920 #define SE051C_ID 0xA8FA #define SE051W_ID 0xA739 #define SE050F_ID 0xA92A #define SE052F2_ID 0xB501 TEE_Result se050_core_early_init(struct se050_scp_key *keys); extern sss_se05x_key_store_t *se050_kstore; extern sss_se05x_session_t *se050_session; extern struct sss_se05x_ctx se050_ctx; static inline uint32_t se050_get_oefid(void) { return SHIFT_U32(se050_ctx.se_info.oefid[0], 8) | SHIFT_U32(se050_ctx.se_info.oefid[1], 0); } #endif /* SE050_H_ */ optee_os-4.3.0/core/drivers/crypto/se050/adaptors/include/se050_apdu_apis.h000066400000000000000000000035361464416617300264320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef SE050_APDU_APIS_H_ #define SE050_APDU_APIS_H_ #include struct s050_scp_rotate_cmd; sss_status_t se050_factory_reset(pSe05xSession_t ctx); bool se050_key_exists(uint32_t k_id, pSe05xSession_t ctx); struct se050_rsa_keypair { uint8_t *e; size_t e_len; uint8_t *d; size_t d_len; uint8_t *n; size_t n_len; uint8_t *p; size_t p_len; uint8_t *q; size_t q_len; uint8_t *qp; size_t qp_len; uint8_t *dp; size_t dp_len; uint8_t *dq; size_t dq_len; }; struct se050_rsa_keypub { uint8_t *e; size_t e_len; uint8_t *n; size_t n_len; }; sss_status_t se050_key_store_set_rsa_key_bin(sss_se05x_key_store_t *k_store, sss_se05x_object_t *k_object, struct se050_rsa_keypair *k_pair, struct se050_rsa_keypub *k_pub, size_t k_bit_len); sss_status_t se050_get_free_memory(pSe05xSession_t ctx, uint16_t *t, SE05x_MemoryType_t type); sss_status_t se050_scp03_send_rotate_cmd(pSe05xSession_t ctx, struct s050_scp_rotate_cmd *cmd); struct se050_ecc_keypub { uint8_t *x; size_t x_len; uint8_t *y; size_t y_len; uint32_t curve; }; struct se050_ecc_keypair { struct se050_ecc_keypub pub; uint8_t *d; size_t d_len; }; sss_status_t se050_key_store_set_ecc_key_bin(sss_se05x_key_store_t *store, sss_se05x_object_t *object, struct se050_ecc_keypair *pair, struct se050_ecc_keypub *pub); sss_status_t se050_key_store_get_ecc_key_bin(sss_se05x_key_store_t *store, sss_se05x_object_t *object, uint8_t *key, size_t *len); sss_status_t se050_ecc_gen_shared_secret(pSe05xSession_t ctx, uint32_t id, struct se050_ecc_keypub *pub, uint8_t *secret, size_t *len); #endif /* SE050_APDU_APIS_H_ */ optee_os-4.3.0/core/drivers/crypto/se050/adaptors/include/se050_sss_apis.h000066400000000000000000000017731464416617300263120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef SE050_SSS_APIS_H_ #define SE050_SSS_APIS_H_ #include #include extern sss_policy_t se050_asym_policy; struct se050_scp_key; struct sss_se05x_ctx { SE_Connect_Ctx_t open_ctx; sss_se05x_session_t session; sss_se05x_key_store_t ks; struct se050_auth_ctx { NXSCP03_StaticCtx_t static_ctx; NXSCP03_DynCtx_t dynamic_ctx; } se05x_auth; sss_user_impl_session_t host_session; sss_key_store_t host_ks; struct se05x_se_info { uint8_t applet[3]; uint8_t oefid[2]; } se_info; }; sss_status_t se050_key_store_and_object_init(struct sss_se05x_ctx *ctx); sss_status_t se050_enable_scp03(sss_se05x_session_t *session); sss_status_t se050_rotate_scp03_keys(struct sss_se05x_ctx *ctx); sss_status_t se050_session_open(struct sss_se05x_ctx *ctx, struct se050_scp_key *key); #endif /* SE050_SSS_APIS_H_ */ optee_os-4.3.0/core/drivers/crypto/se050/adaptors/include/se050_user_apis.h000066400000000000000000000014201464416617300264450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef SE050_USER_APIS_H_ #define SE050_USER_APIS_H_ #include #include #include #include #include sss_status_t se050_configure_host(sss_user_impl_session_t *host_session, sss_key_store_t *host_ks, SE_Connect_Ctx_t *open_ctx, struct se050_auth_ctx *auth_ctx, SE_AuthType_t auth_type, struct se050_scp_key *keys); TEE_Result se050_host_key_store_get_key(sss_key_store_t *ks __unused, sss_object_t *ko, uint8_t *data, size_t *byte_len, size_t *bit_len); #endif /* SE050_USER_APIS_H_ */ optee_os-4.3.0/core/drivers/crypto/se050/adaptors/include/se050_utils.h000066400000000000000000000033431464416617300256210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef SE050_UTILS_H_ #define SE050_UTILS_H_ #include #include #define SE050_SCP03_KEY_SZ 16 struct se050_scp_key { uint8_t enc[SE050_SCP03_KEY_SZ]; uint8_t mac[SE050_SCP03_KEY_SZ]; uint8_t dek[SE050_SCP03_KEY_SZ]; }; struct s050_scp_rotate_cmd { uint8_t cmd[128]; size_t cmd_len; uint8_t kcv[16]; size_t kcv_len; }; #define OID_MIN ((uint32_t)(0x00000001)) #define OID_MAX ((uint32_t)(OID_MIN + 0x7BFFFFFE)) #define SE050_KEY_WATERMARK 0x57721566 #define WATERMARKED(x) \ ((uint64_t)(((uint64_t)SE050_KEY_WATERMARK) << 32) + (x)) sss_status_t se050_get_oid(uint32_t *val); struct rsa_keypair; struct ecc_keypair; uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key); uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key); uint64_t se050_generate_private_key(uint32_t oid); void se050_refcount_init_ctx(uint8_t **cnt); int se050_refcount_final_ctx(uint8_t *cnt); sss_status_t se050_get_se_info(sss_se05x_session_t *session, bool display); enum se050_scp03_ksrc { SCP03_CFG, SCP03_DERIVED, SCP03_OFID }; void se050_scp03_set_enable(enum se050_scp03_ksrc ksrc); void se050_scp03_set_disable(void); bool se050_scp03_enabled(void); sss_status_t se050_scp03_get_current_keys(struct se050_scp_key *keys); sss_status_t se050_scp03_get_keys(struct se050_scp_key *keys, enum se050_scp03_ksrc); sss_status_t se050_scp03_subkey_derive(struct se050_scp_key *keys); sss_status_t se050_scp03_prepare_rotate_cmd(struct sss_se05x_ctx *ctx, struct s050_scp_rotate_cmd *cmd, struct se050_scp_key *keys); #endif /* SE050_UTILS_H_ */ optee_os-4.3.0/core/drivers/crypto/se050/adaptors/sub.mk000066400000000000000000000004741464416617300230750ustar00rootroot00000000000000cflags-y += -Wno-strict-aliasing include ${CFG_NXP_SE05X_PLUG_AND_TRUST}/cflags.mk incdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST}/optee_lib/include incdirs-y += ./include srcs-y += utils/scp_config.c srcs-y += utils/utils.c srcs-y += utils/info.c srcs-y += apis/apdu.c srcs-y += apis/user.c srcs-y += apis/sss.c optee_os-4.3.0/core/drivers/crypto/se050/adaptors/utils/000077500000000000000000000000001464416617300231065ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/adaptors/utils/info.c000066400000000000000000000173161464416617300242150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include /* Force the output until the P&T stack fixes its verbosity */ #define LOG_MAU8_I(msg, buf, len) nLog_au8("Info", 0xff, msg, buf, len) #define LOG_I(format, ...) nLog("Info", 0xff, format, ##__VA_ARGS__) #define LOG_E(format, ...) nLog("Info", NX_LEVEL_ERROR, format, ##__VA_ARGS__) #define LOG_MAU8_E(msg, buf, len) \ nLog_au8("Info", NX_LEVEL_ERROR, msg, buf, len) static sss_status_t jcop4_get_id(void *ctx, bool display) { char jcop_platform_id[17] = { 0 }; smStatus_t ret = SM_OK; unsigned char cmd[] = { 0x80, /* CLA '80' / '00' GlobalPlatform / ISO / IEC */ 0xCA, /* INS 'CA' GET DATA(IDENTIFY) */ 0x00, /* P1 '00' High order tag value */ 0xFE, /* P2 'FE' Low order tag value - proprietary data */ 0x02, /* Lc '02' Length of data field */ 0xDF, 0x28, /* Data 'DF28' Card identification data */ 0x00 /* Le '00' Length of response data */ }; struct msg_rsp { uint8_t vTag_value_proprietary_data; uint8_t vLength_of_following_data; uint8_t vTag_card_identification_data[0x02]; uint8_t vLength_of_card_identification_data; uint8_t vTag_configuration_ID; uint8_t vLength_configuration_ID; uint8_t vConfiguration_ID[0x0C]; uint8_t vTag_patch_ID; uint8_t vLength_patch_ID; uint8_t vPatch_ID[0x08]; uint8_t vTag_platform_build_ID1; uint8_t vLength_platform_build_ID; uint8_t vPlatform_build_ID[0x18]; uint8_t vTag_FIPS_mode; uint8_t vLength_FIPS_mode; uint8_t vFIPS_mode; uint8_t vTag_pre_perso_state; uint8_t vLength_pre_perso_state; uint8_t vBit_mask_of_pre_perso_state; uint8_t vTag_ROM_ID; uint8_t vLength_ROM_ID; uint8_t vROM_ID[0x08]; uint8_t vStatus_Word_SW_[0x02]; } rsp = { 0 }; uint8_t *p = (uint8_t *)&rsp; uint32_t len = sizeof(struct msg_rsp); uint16_t dummy = sizeof(struct msg_rsp); ret = GP_Select(ctx, p, 0, p, &dummy); if (ret != SM_OK) { LOG_E("Could not select ISD."); return kStatus_SSS_Fail; } ret = smCom_TransceiveRaw(ctx, cmd, sizeof(cmd), p, &len); if (ret != SM_OK || len != sizeof(rsp)) { LOG_MAU8_E("Error reading JCOP ID", p, sizeof(rsp)); return kStatus_SSS_Fail; } memcpy(se050_ctx.se_info.oefid, &rsp.vConfiguration_ID[2], 2); if (!display) return kStatus_SSS_Success; LOG_I("SE050 JCOP4 Information:"); LOG_I("%s = 0x%02X", "Tag value - proprietary data 0xFE", rsp.vTag_value_proprietary_data); LOG_I("%s = 0x%02X", "Length of following data 0x45", rsp.vLength_of_following_data); LOG_MAU8_I("Tag card identification data", rsp.vTag_card_identification_data, sizeof(rsp.vTag_card_identification_data)); LOG_I("%s = 0x%02X", "Length of card identification data", rsp.vLength_of_card_identification_data); LOG_I("%s = 0x%02X", "Tag configuration ID (Must be 0x01)", rsp.vTag_configuration_ID); LOG_I("%s = 0x%02X", "Length configuration ID 0x0C", rsp.vLength_configuration_ID); LOG_MAU8_I("Configuration ID", rsp.vConfiguration_ID, sizeof(rsp.vConfiguration_ID)); LOG_MAU8_I("OEF ID", &rsp.vConfiguration_ID[2], 2); LOG_I("%s = 0x%02X", "Tag patch ID (Must be 0x02)", rsp.vTag_patch_ID); LOG_I("%s = 0x%02X", "Length patch ID 0x08", rsp.vLength_patch_ID); LOG_MAU8_I("Patch ID", rsp.vPatch_ID, sizeof(rsp.vPatch_ID)); LOG_I("%s = 0x%02X", "Tag platform build ID1 (Must be 0x03)", rsp.vTag_platform_build_ID1); LOG_I("%s = 0x%02X", "Length platform build ID 0x18", rsp.vLength_platform_build_ID); LOG_MAU8_I("Platform build ID", rsp.vPlatform_build_ID, sizeof(rsp.vPlatform_build_ID)); memcpy(jcop_platform_id, rsp.vPlatform_build_ID, 16); LOG_I("%s = %s", "JCOP Platform ID", jcop_platform_id); LOG_I("%s = 0x%02X", "Tag FIPS mode (Must be 0x05)", rsp.vTag_FIPS_mode); LOG_I("%s = 0x%02X", "Length FIPS mode 0x01", rsp.vLength_FIPS_mode); LOG_I("%s = 0x%02X", "FIPS mode var", rsp.vFIPS_mode); LOG_I("%s = 0x%02X", "Tag pre-perso state (Must be 0x07)", rsp.vTag_pre_perso_state); LOG_I("%s = 0x%02X", "Length pre-perso state 0x01", rsp.vLength_pre_perso_state); LOG_I("%s = 0x%02X", "Bit mask of pre-perso state var", rsp.vBit_mask_of_pre_perso_state); LOG_I("%s = 0x%02X", "Tag ROM ID (Must be 0x08)", rsp.vTag_ROM_ID); LOG_I("%s = 0x%02X", "Length ROM ID 0x08", rsp.vLength_ROM_ID); LOG_MAU8_I("ROM ID", rsp.vROM_ID, sizeof(rsp.vROM_ID)); LOG_MAU8_I("Status Word (SW)", rsp.vStatus_Word_SW_, sizeof(rsp.vStatus_Word_SW_)); return kStatus_SSS_Success; } #define ITEM(__x) { \ .name = #__x, \ .val = (kSE05x_AppletConfig_##__x), \ } static void show_config(uint16_t cfg) { struct items { uint16_t val; const char *name; } features[] = { ITEM(ECDAA), ITEM(ECDSA_ECDH_ECDHE), ITEM(EDDSA), ITEM(DH_MONT), ITEM(HMAC), ITEM(RSA_PLAIN), ITEM(RSA_CRT), ITEM(AES), ITEM(DES), ITEM(PBKDF), ITEM(TLS), ITEM(MIFARE), ITEM(I2CM), }; size_t i = 0; for (i = 0; i < ARRAY_SIZE(features); i++) { LOG_I("\t%s%s", cfg & features[i].val ? "with\t" : "without\t", features[i].name); } } static sss_status_t applet_get_id(sss_se05x_session_t *session, bool display) { SE05x_Result_t result = kSE05x_Result_NA; smStatus_t ret = SM_OK; uint8_t uid[SE050_MODULE_UNIQUE_ID_LEN] = { 0 }; size_t uidLen = sizeof(uid); uint8_t applet_version[7] = { 0 }; size_t applet_versionLen = sizeof(applet_version); ret = Se05x_API_CheckObjectExists(&session->s_ctx, kSE05x_AppletResID_UNIQUE_ID, &result); if (ret != SM_OK) return kStatus_SSS_Fail; ret = Se05x_API_ReadObject(&session->s_ctx, kSE05x_AppletResID_UNIQUE_ID, 0, (uint16_t)uidLen, uid, &uidLen); if (ret != SM_OK) return kStatus_SSS_Fail; /* * VersionInfo is a 7 - byte value consisting of: * - 1 - byte Major applet version * - 1 - byte Minor applet version * - 1 - byte patch applet version * - 2 - byte AppletConfig, indicating the supported applet features * - 2-byte Secure Box version: major version (MSB) concatenated with * minor version (LSB). */ ret = Se05x_API_GetVersion(&session->s_ctx, applet_version, &applet_versionLen); if (ret != SM_OK) { LOG_E("Failed Se05x_API_GetVersion"); return kStatus_SSS_Fail; } memcpy(se050_ctx.se_info.applet, applet_version, 3); if (!display) return kStatus_SSS_Success; LOG_MAU8_I("Applet ID", uid, uidLen); LOG_I("Applet Major = %d", applet_version[0]); LOG_I("Applet Minor = %d", applet_version[1]); LOG_I("Applet patch = %d", applet_version[2]); LOG_I("AppletConfig = %02X%02X", applet_version[3], applet_version[4]); show_config(applet_version[3] << 8 | applet_version[4]); LOG_I("Internal = %02X%02X", applet_version[5], applet_version[6]); return kStatus_SSS_Success; } sss_status_t se050_get_se_info(sss_se05x_session_t *session, bool display) { sss_status_t ret = kStatus_SSS_Fail; __maybe_unused uint32_t oefid = 0; if (session) { ret = applet_get_id(session, display); if (ret != kStatus_SSS_Success) { EMSG("Can't retrieve Applet information"); return ret; } ret = jcop4_get_id(session->s_ctx.conn_ctx, display); if (ret != kStatus_SSS_Success) { EMSG("Can't retrieve JCOP information"); return ret; } #ifdef CFG_CORE_SE05X_OEFID /* validate the requested OEFID against the runtime detected */ oefid = SHIFT_U32(se050_ctx.se_info.oefid[0], 8) | SHIFT_U32(se050_ctx.se_info.oefid[1], 0); if (oefid != CFG_CORE_SE05X_OEFID) { EMSG("OEFID configuration error, 0x%x != 0x%"PRIx32, CFG_CORE_SE05X_OEFID, oefid); return kStatus_SSS_Fail; } #endif return kStatus_SSS_Success; } return kStatus_SSS_Fail; } optee_os-4.3.0/core/drivers/crypto/se050/adaptors/utils/scp_config.c000066400000000000000000000330601464416617300253660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static enum se050_scp03_ksrc scp03_ksrc; static bool scp03_enabled; #define SE050A1 0 #define SE050A2 1 #define SE050B1 2 #define SE050B2 3 #define SE050C1 4 #define SE050C2 5 #define SE050DV 6 #define SE051A2 7 #define SE051C2 8 #define SE050F2 9 #define SE050E 10 #define SE051A 11 #define SE051C 12 #define SE051W 13 #define SE050F 14 #define SE052F2 15 static const struct se050_scp_key se050_default_keys[] = { [SE050A1] = { .enc = { 0x34, 0xae, 0x09, 0x67, 0xe3, 0x29, 0xe9, 0x51, 0x8e, 0x72, 0x65, 0xd5, 0xad, 0xcc, 0x01, 0xc2 }, .mac = { 0x52, 0xb2, 0x53, 0xca, 0xdf, 0x47, 0x2b, 0xdb, 0x3d, 0x0f, 0xb3, 0x8e, 0x09, 0x77, 0x00, 0x99 }, .dek = { 0xac, 0xc9, 0x14, 0x31, 0xfe, 0x26, 0x81, 0x1b, 0x5e, 0xcb, 0xc8, 0x45, 0x62, 0x0d, 0x83, 0x44 }, }, [SE050A2] = { .enc = { 0x46, 0xa9, 0xc4, 0x8c, 0x34, 0xef, 0xe3, 0x44, 0xa5, 0x22, 0xe6, 0x67, 0x44, 0xf8, 0x99, 0x6a }, .mac = { 0x12, 0x03, 0xff, 0x61, 0xdf, 0xbc, 0x9c, 0x86, 0x19, 0x6a, 0x22, 0x74, 0xae, 0xf4, 0xed, 0x28 }, .dek = { 0xf7, 0x56, 0x1c, 0x6f, 0x48, 0x33, 0x61, 0x19, 0xee, 0x39, 0x43, 0x9a, 0xab, 0x34, 0x09, 0x8e }, }, [SE050B1] = { .enc = { 0xd4, 0x99, 0xbc, 0x90, 0xde, 0xa5, 0x42, 0xcf, 0x78, 0xd2, 0x5e, 0x13, 0xd6, 0x4c, 0xbb, 0x1f }, .mac = { 0x08, 0x15, 0x55, 0x96, 0x43, 0xfb, 0x79, 0xeb, 0x85, 0x01, 0xa0, 0xdc, 0x83, 0x3d, 0x90, 0x1f }, .dek = { 0xbe, 0x7d, 0xdf, 0xb4, 0x06, 0xe8, 0x1a, 0xe4, 0xe9, 0x66, 0x5a, 0x9f, 0xed, 0x64, 0x26, 0x7c }, }, [SE050B2] = { .enc = { 0x5f, 0xa4, 0x3d, 0x82, 0x02, 0xd2, 0x5e, 0x9a, 0x85, 0xb1, 0xfe, 0x7e, 0x2d, 0x26, 0x47, 0x8d }, .mac = { 0x10, 0x5c, 0xea, 0x22, 0x19, 0xf5, 0x2b, 0xd1, 0x67, 0xa0, 0x74, 0x63, 0xc6, 0x93, 0x79, 0xc3 }, .dek = { 0xd7, 0x02, 0x81, 0x57, 0xf2, 0xad, 0x37, 0x2c, 0x74, 0xbe, 0x96, 0x9b, 0xcc, 0x39, 0x06, 0x27 }, }, [SE050C1] = { .enc = { 0x85, 0x2b, 0x59, 0x62, 0xe9, 0xcc, 0xe5, 0xd0, 0xbe, 0x74, 0x6b, 0x83, 0x3b, 0xcc, 0x62, 0x87 }, .mac = { 0xdb, 0x0a, 0xa3, 0x19, 0xa4, 0x08, 0x69, 0x6c, 0x8e, 0x10, 0x7a, 0xb4, 0xe3, 0xc2, 0x6b, 0x47 }, .dek = { 0x4c, 0x2f, 0x75, 0xc6, 0xa2, 0x78, 0xa4, 0xae, 0xe5, 0xc9, 0xaf, 0x7c, 0x50, 0xee, 0xa8, 0x0c }, }, [SE050C2] = { .enc = { 0xbd, 0x1d, 0xe2, 0x0a, 0x81, 0xea, 0xb2, 0xbf, 0x3b, 0x70, 0x9a, 0x9d, 0x69, 0xa3, 0x12, 0x54 }, .mac = { 0x9a, 0x76, 0x1b, 0x8d, 0xba, 0x6b, 0xed, 0xf2, 0x27, 0x41, 0xe4, 0x5d, 0x8d, 0x42, 0x36, 0xf5 }, .dek = { 0x9b, 0x99, 0x3b, 0x60, 0x0f, 0x1c, 0x64, 0xf5, 0xad, 0xc0, 0x63, 0x19, 0x2a, 0x96, 0xc9, 0x47 }, }, [SE050DV] = { .enc = { 0x35, 0xc2, 0x56, 0x45, 0x89, 0x58, 0xa3, 0x4f, 0x61, 0x36, 0x15, 0x5f, 0x82, 0x09, 0xd6, 0xcd }, .mac = { 0xaf, 0x17, 0x7d, 0x5d, 0xbd, 0xf7, 0xc0, 0xd5, 0xc1, 0x0a, 0x05, 0xb9, 0xf1, 0x60, 0x7f, 0x78 }, .dek = { 0xa1, 0xbc, 0x84, 0x38, 0xbf, 0x77, 0x93, 0x5b, 0x36, 0x1a, 0x44, 0x25, 0xfe, 0x79, 0xfa, 0x29 }, }, [SE051A2] = { .enc = { 0x84, 0x0a, 0x5d, 0x51, 0x79, 0x55, 0x11, 0xc9, 0xce, 0xf0, 0xc9, 0x6f, 0xd2, 0xcb, 0xf0, 0x41 }, .mac = { 0x64, 0x6b, 0xc2, 0xb8, 0xc3, 0xa4, 0xd9, 0xc1, 0xfa, 0x8d, 0x71, 0x16, 0xbe, 0x04, 0xfd, 0xfe }, .dek = { 0x03, 0xe6, 0x69, 0x9a, 0xca, 0x94, 0x26, 0xd9, 0xc3, 0x89, 0x22, 0xf8, 0x91, 0x4c, 0xe5, 0xf7 }, }, [SE051C2] = { .enc = { 0x88, 0xdb, 0xcd, 0x65, 0x82, 0x0d, 0x2a, 0xa0, 0x6f, 0xfa, 0xb9, 0x2a, 0xa8, 0xe7, 0x93, 0x64 }, .mac = { 0xa8, 0x64, 0x4e, 0x2a, 0x04, 0xd9, 0xe9, 0xc8, 0xc0, 0xea, 0x60, 0x86, 0x68, 0x29, 0x99, 0xe5 }, .dek = { 0x8a, 0x38, 0x72, 0x38, 0x99, 0x88, 0x18, 0x44, 0xe2, 0xc1, 0x51, 0x3d, 0xac, 0xd9, 0xf8, 0x0d }, }, [SE050F2] = { .enc = { 0x91, 0x88, 0xda, 0x8c, 0xf3, 0x69, 0xcf, 0xa9, 0xa0, 0x08, 0x91, 0x62, 0x7b, 0x65, 0x34, 0x5a }, .mac = { 0xcb, 0x20, 0xf8, 0x09, 0xc7, 0xa0, 0x39, 0x32, 0xbc, 0x20, 0x3b, 0x0a, 0x01, 0x81, 0x6c, 0x81 }, .dek = { 0x27, 0x8e, 0x61, 0x9d, 0x83, 0x51, 0x8e, 0x14, 0xc6, 0xf1, 0xe4, 0xfa, 0x96, 0x8b, 0xe5, 0x1c }, }, [SE050E] = { .enc = { 0xd2, 0xdb, 0x63, 0xe7, 0xa0, 0xa5, 0xae, 0xd7, 0x2a, 0x64, 0x60, 0xc4, 0xdf, 0xdc, 0xaf, 0x64 }, .mac = { 0x73, 0x8d, 0x5b, 0x79, 0x8e, 0xd2, 0x41, 0xb0, 0xb2, 0x47, 0x68, 0x51, 0x4b, 0xfb, 0xa9, 0x5b }, .dek = { 0x67, 0x02, 0xda, 0xc3, 0x09, 0x42, 0xb2, 0xc8, 0x5e, 0x7f, 0x47, 0xb4, 0x2c, 0xed, 0x4e, 0x7f }, }, [SE051A] = { .enc = { 0x88, 0xea, 0x9f, 0xa6, 0x86, 0xf3, 0xcf, 0x2f, 0xfc, 0xaf, 0x4b, 0x1c, 0xba, 0x93, 0xe4, 0x42 }, .mac = { 0x4f, 0x16, 0x3f, 0x59, 0xf0, 0x74, 0x31, 0xf4, 0x3e, 0xe2, 0xee, 0x18, 0x34, 0xa5, 0x23, 0x34 }, .dek = { 0xd4, 0x76, 0xcf, 0x47, 0xaa, 0x27, 0xb5, 0x4a, 0xb3, 0xdb, 0xeb, 0xe7, 0x65, 0x6d, 0x67, 0x70 }, }, [SE051C] = { .enc = { 0xbf, 0xc2, 0xdb, 0xe1, 0x82, 0x8e, 0x03, 0x5d, 0x3e, 0x7f, 0xa3, 0x6b, 0x90, 0x2a, 0x05, 0xc6 }, .mac = { 0xbe, 0xf8, 0x5b, 0xd7, 0xba, 0x04, 0x97, 0xd6, 0x28, 0x78, 0x1c, 0xe4, 0x7b, 0x18, 0x8c, 0x96 }, .dek = { 0xd8, 0x73, 0xf3, 0x16, 0xbe, 0x29, 0x7f, 0x2f, 0xc9, 0xc0, 0xe4, 0x5f, 0x54, 0x71, 0x06, 0x99 } }, [SE051W] = { .enc = { 0x18, 0xb3, 0xb4, 0xe3, 0x40, 0xc0, 0x80, 0xd9, 0x9b, 0xeb, 0xb8, 0xb8, 0x64, 0x4b, 0x8c, 0x52 }, .mac = { 0x3d, 0x0c, 0xfa, 0xc8, 0x7b, 0x96, 0x7c, 0x00, 0xe3, 0x3b, 0xa4, 0x96, 0x61, 0x38, 0x38, 0xa2 }, .dek = { 0x68, 0x06, 0x83, 0xf9, 0x4e, 0x6b, 0xcb, 0x94, 0x73, 0xec, 0xc1, 0x56, 0x7a, 0x1b, 0xd1, 0x09 }, }, [SE050F] = { .enc = { 0xB5, 0x0E, 0x1F, 0x12, 0xB8, 0x1F, 0xE5, 0x3B, 0x6C, 0x3B, 0x53, 0x87, 0x91, 0x2A, 0x1A, 0x5A, }, .mac = { 0x71, 0x93, 0x69, 0x59, 0xD3, 0x7F, 0x2B, 0x22, 0xC5, 0xA0, 0xC3, 0x49, 0x19, 0xA2, 0xBC, 0x1F, }, .dek = { 0x86, 0x95, 0x93, 0x23, 0x98, 0x54, 0xDC, 0x0D, 0x86, 0x99, 0x00, 0x50, 0x0C, 0xA7, 0x9C, 0x15, }, }, [SE052F2] = { .enc = { 0x3a, 0xe4, 0x41, 0xc7, 0x47, 0xe3, 0x2e, 0xbc, 0x16, 0xb3, 0xbb, 0x2d, 0x84, 0x3c, 0x6d, 0xd8 }, .mac = { 0x6c, 0x18, 0xf3, 0xd0, 0x8f, 0xee, 0x1c, 0xb9, 0x6a, 0x3c, 0x8d, 0xe5, 0xd3, 0x53, 0x8a, 0xaa }, .dek = { 0xb0, 0xe6, 0xa5, 0x69, 0x7d, 0xbd, 0x92, 0x92, 0x43, 0xa4, 0x82, 0xcf, 0x9e, 0x4d, 0x65, 0x22 }, }, }; static sss_status_t get_id_from_ofid(uint32_t ofid, uint32_t *id) { switch (ofid) { case SE050A1_ID: *id = SE050A1; break; case SE050A2_ID: *id = SE050A2; break; case SE050B1_ID: *id = SE050B1; break; case SE050B2_ID: *id = SE050B2; break; case SE050C1_ID: *id = SE050C1; break; case SE050C2_ID: *id = SE050C2; break; case SE050DV_ID: *id = SE050DV; break; case SE051A2_ID: *id = SE051A2; break; case SE051C2_ID: *id = SE051C2; break; case SE050F2_ID: *id = SE050F2; break; case SE050E_ID: *id = SE050E; break; case SE051A_ID: *id = SE051A; break; case SE051C_ID: *id = SE051C; break; case SE051W_ID: *id = SE051W; break; case SE050F_ID: *id = SE050F; break; case SE052F2_ID: *id = SE052F2; break; default: return kStatus_SSS_Fail; } return kStatus_SSS_Success; } static sss_status_t encrypt_key_and_get_kcv(uint8_t *enc, uint8_t *kc, uint8_t *key, struct sss_se05x_ctx *ctx, uint32_t id) { static const uint8_t ones[] = { [0 ... AES_KEY_LEN_nBYTE - 1] = 1 }; uint8_t enc_len = AES_KEY_LEN_nBYTE; uint8_t kc_len = AES_KEY_LEN_nBYTE; sss_status_t st = kStatus_SSS_Fail; sss_object_t *dek_object = NULL; sss_se05x_symmetric_t symm = { }; sss_se05x_object_t ko = { }; uint8_t dek[AES_KEY_LEN_nBYTE] = { 0 }; size_t dek_len = sizeof(dek); size_t dek_bit_len = dek_len * 8; st = sss_se05x_key_object_init(&ko, &ctx->ks); if (st != kStatus_SSS_Success) return kStatus_SSS_Fail; st = sss_se05x_key_object_allocate_handle(&ko, id, kSSS_KeyPart_Default, kSSS_CipherType_AES, AES_KEY_LEN_nBYTE, kKeyObject_Mode_Transient); if (st != kStatus_SSS_Success) return kStatus_SSS_Fail; st = sss_se05x_key_store_set_key(&ctx->ks, &ko, key, AES_KEY_LEN_nBYTE, AES_KEY_LEN_nBYTE * 8, NULL, 0); if (st != kStatus_SSS_Success) goto out; st = sss_se05x_symmetric_context_init(&symm, &ctx->session, &ko, kAlgorithm_SSS_AES_ECB, kMode_SSS_Encrypt); if (st != kStatus_SSS_Success) goto out; st = sss_se05x_cipher_one_go(&symm, NULL, 0, ones, kc, kc_len); if (st != kStatus_SSS_Success) goto out; dek_object = &ctx->open_ctx.auth.ctx.scp03.pStatic_ctx->Dek; if (se050_host_key_store_get_key(&ctx->host_ks, dek_object, dek, &dek_len, &dek_bit_len)) goto out; st = sss_se05x_key_store_set_key(&ctx->ks, &ko, dek, AES_KEY_LEN_nBYTE, AES_KEY_LEN_nBYTE * 8, NULL, 0); if (st != kStatus_SSS_Success) goto out; st = sss_se05x_cipher_one_go(&symm, NULL, 0, key, enc, enc_len); out: if (symm.keyObject) sss_se05x_symmetric_context_free(&symm); sss_se05x_key_object_free(&ko); Se05x_API_DeleteSecureObject(&ctx->session.s_ctx, id); return st; } static sss_status_t prepare_key_data(uint8_t *key, uint8_t *cmd, struct sss_se05x_ctx *ctx, uint32_t id) { uint8_t kc[AES_KEY_LEN_nBYTE] = { 0 }; sss_status_t status = kStatus_SSS_Fail; cmd[0] = PUT_KEYS_KEY_TYPE_CODING_AES; cmd[1] = AES_KEY_LEN_nBYTE + 1; cmd[2] = AES_KEY_LEN_nBYTE; cmd[3 + AES_KEY_LEN_nBYTE] = CRYPTO_KEY_CHECK_LEN; status = encrypt_key_and_get_kcv(&cmd[3], kc, key, ctx, id); if (status != kStatus_SSS_Success) return status; memcpy(&cmd[3 + AES_KEY_LEN_nBYTE + 1], kc, CRYPTO_KEY_CHECK_LEN); return kStatus_SSS_Success; } sss_status_t se050_scp03_prepare_rotate_cmd(struct sss_se05x_ctx *ctx, struct s050_scp_rotate_cmd *cmd, struct se050_scp_key *keys) { sss_status_t status = kStatus_SSS_Fail; size_t kcv_len = 0; size_t cmd_len = 0; uint8_t key_version = 0; uint8_t *key[] = { [0] = keys->enc, [1] = keys->mac, [2] = keys->dek, }; uint32_t oid = 0; size_t i = 0; key_version = ctx->open_ctx.auth.ctx.scp03.pStatic_ctx->keyVerNo; cmd->cmd[cmd_len] = key_version; cmd_len += 1; cmd->kcv[kcv_len] = key_version; kcv_len += 1; for (i = 0; i < ARRAY_SIZE(key); i++) { status = se050_get_oid(&oid); if (status != kStatus_SSS_Success) return kStatus_SSS_Fail; status = prepare_key_data(key[i], &cmd->cmd[cmd_len], ctx, oid); if (status != kStatus_SSS_Success) return kStatus_SSS_Fail; memcpy(&cmd->kcv[kcv_len], &cmd->cmd[cmd_len + 3 + AES_KEY_LEN_nBYTE + 1], CRYPTO_KEY_CHECK_LEN); cmd_len += 3 + AES_KEY_LEN_nBYTE + 1 + CRYPTO_KEY_CHECK_LEN; kcv_len += CRYPTO_KEY_CHECK_LEN; } cmd->cmd_len = cmd_len; cmd->kcv_len = kcv_len; return kStatus_SSS_Success; } static sss_status_t get_ofid_key(struct se050_scp_key *keys) { uint32_t oefid = SHIFT_U32(se050_ctx.se_info.oefid[0], 8) | SHIFT_U32(se050_ctx.se_info.oefid[1], 0); sss_status_t status = kStatus_SSS_Success; uint32_t id = 0; status = get_id_from_ofid(oefid, &id); if (status != kStatus_SSS_Success) return status; memcpy(keys, &se050_default_keys[id], sizeof(*keys)); return kStatus_SSS_Success; } static sss_status_t get_config_key(struct se050_scp_key *keys __maybe_unused) { #ifdef CFG_CORE_SE05X_SCP03_CURRENT_DEK struct se050_scp_key current_keys = { .dek = { CFG_CORE_SE05X_SCP03_CURRENT_DEK }, .mac = { CFG_CORE_SE05X_SCP03_CURRENT_MAC }, .enc = { CFG_CORE_SE05X_SCP03_CURRENT_ENC }, }; memcpy(keys, ¤t_keys, sizeof(*keys)); return kStatus_SSS_Success; #else return kStatus_SSS_Fail; #endif } static const char * __maybe_unused get_scp03_ksrc_name(enum se050_scp03_ksrc k) { switch (k) { case SCP03_DERIVED: return "derived"; case SCP03_CFG: return "built-in"; case SCP03_OFID: return "factory"; default: panic(); } return NULL; } sss_status_t se050_scp03_subkey_derive(struct se050_scp_key *keys) { struct { const char *name; uint8_t *data; } key[3] = { [0] = { .name = "dek", .data = keys->dek }, [1] = { .name = "mac", .data = keys->mac }, [2] = { .name = "enc", .data = keys->enc }, }; uint8_t msg[SE050_SCP03_KEY_SZ + 3] = { 0 }; size_t i = 0; if (IS_ENABLED(CFG_CORE_SCP03_ONLY)) { memset(msg, 0x55, sizeof(msg)); } else { /* add some randomness */ if (tee_otp_get_die_id(msg + 3, SE050_SCP03_KEY_SZ)) return kStatus_SSS_Fail; } for (i = 0; i < ARRAY_SIZE(key); i++) { memcpy(msg, key[i].name, 3); if (huk_subkey_derive(HUK_SUBKEY_SE050, msg, sizeof(msg), key[i].data, SE050_SCP03_KEY_SZ)) return kStatus_SSS_Fail; } return kStatus_SSS_Success; } bool se050_scp03_enabled(void) { return scp03_enabled; } void se050_scp03_set_enable(enum se050_scp03_ksrc ksrc) { scp03_enabled = true; scp03_ksrc = ksrc; IMSG("SE05X SCP03 using %s keys", get_scp03_ksrc_name(ksrc)); } void se050_scp03_set_disable(void) { scp03_enabled = false; } sss_status_t se050_scp03_get_keys(struct se050_scp_key *keys, enum se050_scp03_ksrc ksrc) { switch (ksrc) { case SCP03_CFG: return get_config_key(keys); case SCP03_DERIVED: return se050_scp03_subkey_derive(keys); case SCP03_OFID: return get_ofid_key(keys); default: return kStatus_SSS_Fail; } } sss_status_t se050_scp03_get_current_keys(struct se050_scp_key *keys) { if (se050_scp03_enabled()) return se050_scp03_get_keys(keys, scp03_ksrc); return kStatus_SSS_Fail; } optee_os-4.3.0/core/drivers/crypto/se050/adaptors/utils/utils.c000066400000000000000000000073131464416617300244160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include /* exp: minimal amount of transient memory required to generate an RSA key */ #define TRANSIENT_MEMORY_THRESHOLD 0x140 #define NBR_OID ((uint32_t)(OID_MAX - OID_MIN)) #define IS_WATERMARKED(x) (((x) & WATERMARKED(0)) == WATERMARKED(0)) static void delete_transient_objects(void) { SE05x_AttestationType_t att = kSE05x_AttestationType_None; SE05x_SecureObjectType_t type = kSE05x_SecObjTyp_HMAC_KEY; uint8_t more = kSE05x_MoreIndicator_NA; smStatus_t status = SM_NOT_OK; Se05xSession_t *ctx = NULL; uint8_t *list = NULL; size_t len = 1024; uint16_t offset = 0; uint8_t mode = 0; uint32_t id = 0; size_t i = 0; if (!se050_session) return; ctx = &se050_session->s_ctx; list = calloc(1, len); if (!list) return; do { status = Se05x_API_ReadIDList(ctx, offset, 0xFF, &more, list, &len); if (status != SM_OK) break; offset = len; for (i = 0; i < len; i += 4) { id = (list[i + 0] << (3 * 8)) | (list[i + 1] << (2 * 8)) | (list[i + 2] << (1 * 8)) | (list[i + 3] << (0 * 8)); if (id >= OID_MAX || id == 0) continue; status = Se05x_API_ReadType(ctx, id, &type, &mode, att); if (status != SM_OK) continue; if (mode == kKeyObject_Mode_Transient) Se05x_API_DeleteSecureObject(ctx, id); } } while (more == kSE05x_MoreIndicator_MORE); free(list); } static sss_status_t generate_oid(uint32_t *val) { uint32_t oid = OID_MIN; uint32_t random = 0; size_t i = 0; for (i = 0; i < NBR_OID; i++) { if (crypto_rng_read(&random, sizeof(random))) return kStatus_SSS_Fail; oid = OID_MIN + (random & OID_MAX); /* * The less significant byte different than zero prevents bignum * conversions from discarding it */ if (oid > OID_MAX || !(oid & 0xFF)) continue; if (!se050_key_exists(oid, &se050_session->s_ctx)) { *val = oid; return kStatus_SSS_Success; } } return kStatus_SSS_Fail; } sss_status_t se050_get_oid(uint32_t *val) { sss_status_t status = kStatus_SSS_Success; uint16_t mem_t = 0; if (!val) return kStatus_SSS_Fail; status = se050_get_free_memory(&se050_session->s_ctx, &mem_t, kSE05x_MemoryType_TRANSIENT_DESELECT); if (status != kStatus_SSS_Success) return kStatus_SSS_Fail; if (mem_t < TRANSIENT_MEMORY_THRESHOLD) delete_transient_objects(); return generate_oid(val); } static uint32_t se050_key(uint64_t key) { uint32_t oid = (uint32_t)key; if (!IS_WATERMARKED(key)) return 0; /* oid > OID_MAX could have been created by an external client */ if (oid < OID_MIN) return 0; return oid; } uint32_t se050_rsa_keypair_from_nvm(struct rsa_keypair *key) { uint64_t key_id = 0; if (!key) return 0; if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t)) return 0; crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id); return se050_key(key_id); } uint32_t se050_ecc_keypair_from_nvm(struct ecc_keypair *key) { uint64_t key_id = 0; if (!key) return 0; if (crypto_bignum_num_bytes(key->d) != sizeof(uint64_t)) return 0; crypto_bignum_bn2bin(key->d, (uint8_t *)&key_id); return se050_key(key_id); } uint64_t se050_generate_private_key(uint32_t oid) { return WATERMARKED(oid); } void se050_refcount_init_ctx(uint8_t **cnt) { if (!*cnt) { *cnt = calloc(1, sizeof(uint8_t)); if (*cnt) **cnt = 1; else EMSG("can't allocate refcount"); } else { **cnt = **cnt + 1; } } int se050_refcount_final_ctx(uint8_t *cnt) { if (!cnt) return 1; if (!*cnt) { free(cnt); return 1; } *cnt = *cnt - 1; return 0; } optee_os-4.3.0/core/drivers/crypto/se050/core/000077500000000000000000000000001464416617300210615ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/core/apdu.c000066400000000000000000000012501464416617300221540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include TEE_Result crypto_se_do_apdu(enum crypto_apdu_type type, uint8_t *hdr, size_t hdr_len, uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len) { sss_status_t status = kStatus_SSS_Fail; status = sss_se05x_do_apdu(&se050_session->s_ctx, type, hdr, hdr_len, src_data, src_len, dst_data, dst_len); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/crypto/se050/core/cipher.c000066400000000000000000000035371464416617300225070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include static TEE_Result do_init(struct drvcrypt_cipher_init *dinit) { struct crypto_cipher_ctx *ctx = dinit->ctx; TEE_OperationMode mode = TEE_MODE_DECRYPT; if (dinit->encrypt) mode = TEE_MODE_ENCRYPT; return ctx->ops->init(dinit->ctx, mode, dinit->key1.data, dinit->key1.length, dinit->key2.data, dinit->key2.length, dinit->iv.data, dinit->iv.length); } static TEE_Result do_update(struct drvcrypt_cipher_update *dupdate) { struct crypto_cipher_ctx *ctx = dupdate->ctx; return ctx->ops->update(ctx, dupdate->last, dupdate->src.data, dupdate->src.length, dupdate->dst.data); } static void do_final(void *context) { struct crypto_cipher_ctx *ctx = context; ctx->ops->final(ctx); } static void do_free(void *context) { struct crypto_cipher_ctx *ctx = context; ctx->ops->free_ctx(ctx); } static void do_copy_state(void *out, void *in) { struct crypto_cipher_ctx *dst_ctx = out; struct crypto_cipher_ctx *src_ctx = in; src_ctx->ops->copy_state(dst_ctx, src_ctx); } static TEE_Result do_allocate(void **ctx, uint32_t algo) { switch (algo) { case TEE_ALG_AES_CTR: return se050_aes_ctr_allocate(ctx); default: return TEE_ERROR_NOT_IMPLEMENTED; } } static struct drvcrypt_cipher driver_cipher = { .alloc_ctx = do_allocate, .free_ctx = do_free, .init = do_init, .update = do_update, .final = do_final, .copy_state = do_copy_state, }; static TEE_Result se050_cipher_init(void) { return drvcrypt_register_cipher(&driver_cipher); } driver_init_late(se050_cipher_init); optee_os-4.3.0/core/drivers/crypto/se050/core/ctr.c000066400000000000000000000100431464416617300220130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include struct se050_aes_ctr_ctx { struct crypto_cipher_ctx ctx; sss_se05x_symmetric_t aes_ctx; sss_se05x_object_t key_obj; uint8_t *cnt; /* shared reference counter for duplicated ciphers */ int nc_off; unsigned char counter[TEE_AES_BLOCK_SIZE]; unsigned char block[TEE_AES_BLOCK_SIZE]; }; static struct se050_aes_ctr_ctx *to_aes_ctr_ctx(struct crypto_cipher_ctx *ctx) { return container_of(ctx, struct se050_aes_ctr_ctx, ctx); } static TEE_Result se050_aes_ctr_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode __unused, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv, size_t iv_len __unused) { struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); sss_status_t st = kStatus_SSS_Success; uint32_t oid = 0; if (c->key_obj.keyId) goto init; memcpy(c->counter, iv, sizeof(c->counter)); st = sss_se05x_key_object_init(&c->key_obj, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_key_object_allocate_handle(&c->key_obj, oid, kSSS_KeyPart_Default, kSSS_CipherType_AES, 0, kKeyObject_Mode_Transient); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_key_store_set_key(se050_kstore, &c->key_obj, key1, key1_len, key1_len * 8, NULL, 0); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_symmetric_context_init(&c->aes_ctx, se050_session, &c->key_obj, kAlgorithm_SSS_AES_ECB, kMode_SSS_Encrypt); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; init: st = sss_se05x_cipher_init(&c->aes_ctx, (uint8_t *)NULL, 0); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result se050_aes_ctr_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); sss_status_t st = kStatus_SSS_Success; size_t dst_len = len; int i = 0; int n = 0; int j = 0; n = c->nc_off; while (len--) { dst_len = sizeof(c->counter); if (n == 0) { st = sss_se05x_cipher_update(&c->aes_ctx, c->counter, 16, c->block, &dst_len); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_STATE; for (i = 16; i > 0; i--) if (++c->counter[i - 1] != 0) break; } j = *data++; *dst++ = (unsigned char)(j ^ c->block[n]); n = (n + 1) & 0x0F; } c->nc_off = n; return TEE_SUCCESS; } static void do_final(struct crypto_cipher_ctx *ctx) { struct se050_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); if (!se050_refcount_final_ctx(c->cnt)) { memset(c->block, 0, sizeof(c->block)); return; } if (c->key_obj.keyId) sss_se05x_key_store_erase_key(se050_kstore, &c->key_obj); sss_se05x_symmetric_context_free(&c->aes_ctx); } static void do_free(struct crypto_cipher_ctx *ctx) { free(to_aes_ctr_ctx(ctx)); } static void do_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct se050_aes_ctr_ctx *src = to_aes_ctr_ctx(src_ctx); struct se050_aes_ctr_ctx *dst = to_aes_ctr_ctx(dst_ctx); se050_refcount_init_ctx(&src->cnt); memcpy(dst, src, sizeof(*dst)); } static struct crypto_cipher_ops aes_ctr_ops = { .update = se050_aes_ctr_update, .copy_state = do_copy_state, .init = se050_aes_ctr_init, .free_ctx = do_free, .final = do_final, }; TEE_Result se050_aes_ctr_allocate(void **ctx) { struct se050_aes_ctr_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &aes_ctr_ops; *ctx = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/crypto/se050/core/die_id.c000066400000000000000000000013371464416617300224460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include int tee_otp_get_die_id(uint8_t *buffer, size_t len) { uint8_t die_id[SE050_MODULE_UNIQUE_ID_LEN] = { 0 }; size_t die_id_len = sizeof(die_id); sss_status_t status = kStatus_SSS_Fail; status = sss_se05x_session_prop_get_au8(se050_session, kSSS_SessionProp_UID, die_id, &die_id_len); if (status != kStatus_SSS_Success) return -1; if (tee_hash_createdigest(TEE_ALG_SHA256, die_id, die_id_len, buffer, len)) return -1; return 0; } optee_os-4.3.0/core/drivers/crypto/se050/core/ecc.c000066400000000000000000000475671464416617300220020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const struct crypto_ecc_keypair_ops *pair_ops; static const struct crypto_ecc_public_ops *pub_ops; static bool oefid_key_supported(size_t bits) { switch (se050_get_oefid()) { case SE050F_ID: return bits >= 224; default: return true; } } static bool oefid_algo_supported(uint32_t algo) { switch (se050_get_oefid()) { case SE050F_ID: switch (algo) { case TEE_ALG_ECDSA_SHA224: case TEE_ALG_ECDSA_SHA256: case TEE_ALG_ECDSA_SHA384: case TEE_ALG_ECDSA_SHA512: return true; default: return false; } default: return true; } } static uint32_t algo_tee2se050(uint32_t algo) { switch (algo) { case TEE_ALG_ECDSA_SHA1: return kAlgorithm_SSS_ECDSA_SHA1; case TEE_ALG_ECDSA_SHA224: return kAlgorithm_SSS_ECDSA_SHA224; case TEE_ALG_ECDSA_SHA256: return kAlgorithm_SSS_ECDSA_SHA256; case TEE_ALG_ECDSA_SHA384: return kAlgorithm_SSS_ECDSA_SHA384; case TEE_ALG_ECDSA_SHA512: return kAlgorithm_SSS_ECDSA_SHA512; default: EMSG("algorithm %#"PRIx32" not enabled", algo); return kAlgorithm_None; } } static uint32_t cipher_tee2se050(uint32_t curve) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: case TEE_ECC_CURVE_NIST_P224: case TEE_ECC_CURVE_NIST_P256: case TEE_ECC_CURVE_NIST_P384: case TEE_ECC_CURVE_NIST_P521: return kSSS_CipherType_EC_NIST_P; default: EMSG("cipher %#"PRIx32" not enabled", curve); return kSSS_CipherType_NONE; } } static uint32_t curve_tee2se050(uint32_t curve) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: return kSE05x_ECCurve_NIST_P192; case TEE_ECC_CURVE_NIST_P224: return kSE05x_ECCurve_NIST_P224; case TEE_ECC_CURVE_NIST_P256: return kSE05x_ECCurve_NIST_P256; case TEE_ECC_CURVE_NIST_P384: return kSE05x_ECCurve_NIST_P384; case TEE_ECC_CURVE_NIST_P521: return kSE05x_ECCurve_NIST_P521; default: EMSG("curve %#"PRIx32" not enabled", curve); return kSE05x_ECCurve_NA; } } static uint32_t curve_se0502tee(uint32_t curve) { switch (curve) { case kSE05x_ECCurve_NIST_P192: return TEE_ECC_CURVE_NIST_P192; case kSE05x_ECCurve_NIST_P224: return TEE_ECC_CURVE_NIST_P224; case kSE05x_ECCurve_NIST_P256: return TEE_ECC_CURVE_NIST_P256; case kSE05x_ECCurve_NIST_P384: return TEE_ECC_CURVE_NIST_P384; case kSE05x_ECCurve_NIST_P521: return TEE_ECC_CURVE_NIST_P521; default: EMSG("curve %#"PRIx32" not enabled", curve); return TEE_CRYPTO_ELEMENT_NONE; } } static bool bn_alloc_max(struct bignum **s) { *s = crypto_bignum_allocate(4096); return *s; } static TEE_Result ecc_get_key_size(uint32_t curve, uint32_t algo, size_t *bytes, size_t *bits) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: *bits = 192; *bytes = 24; break; case TEE_ECC_CURVE_NIST_P224: *bits = 224; *bytes = 28; break; case TEE_ECC_CURVE_NIST_P256: *bits = 256; *bytes = 32; break; case TEE_ECC_CURVE_NIST_P384: *bits = 384; *bytes = 48; break; case TEE_ECC_CURVE_NIST_P521: *bits = 521; *bytes = 66; break; default: return TEE_ERROR_NOT_IMPLEMENTED; } if (!oefid_key_supported(*bits)) return TEE_ERROR_NOT_IMPLEMENTED; if (!oefid_algo_supported(algo)) return TEE_ERROR_NOT_IMPLEMENTED; return TEE_SUCCESS; } static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg, size_t *msg_len, uint8_t **msg_padded) { struct { uint32_t algo; size_t len; } map[] = { { kAlgorithm_SSS_ECDSA_SHA1, TEE_SHA1_HASH_SIZE }, { kAlgorithm_SSS_ECDSA_SHA224, TEE_SHA224_HASH_SIZE }, { kAlgorithm_SSS_ECDSA_SHA256, TEE_SHA256_HASH_SIZE }, { kAlgorithm_SSS_ECDSA_SHA384, TEE_SHA384_HASH_SIZE }, { kAlgorithm_SSS_ECDSA_SHA512, TEE_SHA512_HASH_SIZE }, }; size_t i = 0; for (i = 0; i < ARRAY_SIZE(map); i++) { if (algo == map[i].algo) break; } if (i >= ARRAY_SIZE(map)) return TEE_ERROR_BAD_PARAMETERS; if (*msg_len >= map[i].len) { /* truncate */ *msg_len = map[i].len; return TEE_SUCCESS; } /* pad */ *msg_padded = calloc(1, map[i].len); if (!*msg_padded) return TEE_ERROR_OUT_OF_MEMORY; memcpy(*msg_padded, msg, *msg_len); *msg_len = map[i].len; return TEE_SUCCESS; } static TEE_Result set_binary_data(struct bignum *b, size_t key_len, uint8_t **p, size_t *len) { size_t a = crypto_bignum_num_bytes(b); uint8_t leading_zeros = 0; uint8_t *q = NULL; if (!a) return TEE_ERROR_GENERIC; if (a != key_len) { leading_zeros = key_len - a; a = key_len; } q = calloc(1, a); if (!q) return TEE_ERROR_OUT_OF_MEMORY; crypto_bignum_bn2bin(b, q + leading_zeros); *len = a; *p = q; return TEE_SUCCESS; } static TEE_Result se050_inject_public_key(sss_se05x_object_t *k_object, struct ecc_public_key *key, size_t key_len) { struct se050_ecc_keypub key_bin = { }; TEE_Result ret = TEE_ERROR_GENERIC; sss_status_t st = kStatus_SSS_Fail; uint32_t oid = 0; st = sss_se05x_key_object_init(k_object, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; /* * This function might return an error if the curve already * exists in the secure element. An actual error creating the * curve will be caught when attempting to set the key. */ sss_se05x_key_store_create_curve(&se050_session->s_ctx, curve_tee2se050(key->curve)); st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_key_object_allocate_handle(k_object, oid, kSSS_KeyPart_Public, cipher_tee2se050(key->curve), 0, kKeyObject_Mode_Transient); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; ret = set_binary_data(key->x, key_len, &key_bin.x, &key_bin.x_len); if (ret != TEE_SUCCESS) return ret; ret = set_binary_data(key->y, key_len, &key_bin.y, &key_bin.y_len); if (ret != TEE_SUCCESS) { free(key_bin.x); return ret; } key_bin.curve = curve_tee2se050(key->curve); st = se050_key_store_set_ecc_key_bin(se050_kstore, k_object, NULL, &key_bin); free(key_bin.x); free(key_bin.y); if (st != kStatus_SSS_Success) { EMSG("Can't inject transient key, curve: %#"PRIx32, key->curve); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result se050_inject_keypair(sss_se05x_object_t *k_object, struct ecc_keypair *key, size_t key_len) { struct se050_ecc_keypair key_bin = { }; sss_status_t st = kStatus_SSS_Fail; TEE_Result ret = TEE_ERROR_GENERIC; uint32_t key_id = 0; uint32_t oid = 0; st = sss_se05x_key_object_init(k_object, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; key_id = se050_ecc_keypair_from_nvm(key); if (key_id) { st = sss_se05x_key_object_get_handle(k_object, key_id); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } /* * This function might return an error if the curve already * exists in the secure element. An actual error creating the * curve will be caught when attempting to set the key. */ sss_se05x_key_store_create_curve(&se050_session->s_ctx, curve_tee2se050(key->curve)); st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_key_object_allocate_handle(k_object, oid, kSSS_KeyPart_Pair, cipher_tee2se050(key->curve), 0, kKeyObject_Mode_Transient); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; ret = set_binary_data(key->d, key_len, &key_bin.d, &key_bin.d_len); if (ret != TEE_SUCCESS) return ret; ret = set_binary_data(key->x, key_len, &key_bin.pub.x, &key_bin.pub.x_len); if (ret != TEE_SUCCESS) { free(key_bin.d); return ret; } ret = set_binary_data(key->y, key_len, &key_bin.pub.y, &key_bin.pub.y_len); if (ret != TEE_SUCCESS) { free(key_bin.d); free(key_bin.pub.x); return ret; } key_bin.pub.curve = curve_tee2se050(key->curve); st = se050_key_store_set_ecc_key_bin(se050_kstore, k_object, &key_bin, NULL); free(key_bin.d); free(key_bin.pub.x); free(key_bin.pub.y); if (st != kStatus_SSS_Success) { EMSG("Can't inject transient key, curve: %#"PRIx32, key->curve); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result gen_fallback(struct ecc_keypair *key, size_t len) { if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: ECC software fallback: KEYGEN"); return pair_ops->generate(key, len); } static TEE_Result shared_secret_fallback(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, size_t *secret_len) { const struct crypto_ecc_keypair_ops *ops = NULL; if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; if (se050_ecc_keypair_from_nvm(private_key)) return TEE_ERROR_NOT_IMPLEMENTED; ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR); if (!ops) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: ECC software fallback: ECDH"); return ops->shared_secret(private_key, public_key, secret, (unsigned long *)secret_len); } static TEE_Result verify_fallback(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: ECC software fallback: VERIFY"); return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len); } static TEE_Result sign_fallback(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { if (!IS_ENABLED(CFG_NXP_SE05X_ECC_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; if (se050_ecc_keypair_from_nvm(key)) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: ECC software fallback: SIGN"); return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len); } static TEE_Result shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, size_t *secret_len) { struct se050_ecc_keypub key = { }; sss_status_t st = kStatus_SSS_Fail; sss_se05x_derive_key_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result ret = TEE_SUCCESS; size_t key_bits = 0; size_t key_bytes = 0; if (private_key->curve != public_key->curve) return TEE_ERROR_BAD_PARAMETERS; ret = ecc_get_key_size(private_key->curve, 0, &key_bytes, &key_bits); if (ret) { if (ret != TEE_ERROR_NOT_IMPLEMENTED) return ret; return shared_secret_fallback(private_key, public_key, secret, secret_len); } ret = se050_inject_keypair(&kobject, private_key, key_bytes); if (ret != TEE_SUCCESS) return TEE_ERROR_BAD_PARAMETERS; st = sss_se05x_derive_key_context_init(&ctx, se050_session, &kobject, kAlgorithm_SSS_ECDH, kMode_SSS_ComputeSharedSecret); if (st != kStatus_SSS_Success) { ret = TEE_ERROR_BAD_PARAMETERS; goto exit; } /* prepare the public key (must be in raw format) */ ret = set_binary_data(public_key->x, key_bytes, &key.x, &key.x_len); if (ret != TEE_SUCCESS) { ret = TEE_ERROR_BAD_PARAMETERS; goto exit; } ret = set_binary_data(public_key->y, key_bytes, &key.y, &key.y_len); if (ret != TEE_SUCCESS) { ret = TEE_ERROR_BAD_PARAMETERS; goto exit; } st = se050_ecc_gen_shared_secret(&se050_session->s_ctx, kobject.keyId, &key, secret, secret_len); if (st != kStatus_SSS_Success) ret = TEE_ERROR_BAD_PARAMETERS; exit: if (!se050_ecc_keypair_from_nvm(private_key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); free(key.x); free(key.y); return ret; } static TEE_Result sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; uint8_t *sig_der = NULL; size_t sig_der_len = 0; size_t key_bytes = 0; size_t key_bits = 0; uint8_t *p = NULL; res = ecc_get_key_size(key->curve, algo, &key_bytes, &key_bits); if (res) { if (res != TEE_ERROR_NOT_IMPLEMENTED) goto exit; return sign_fallback(algo, key, msg, msg_len, sig, sig_len); } /* allocate temporary buffer to retrieve the signature in DER format */ sig_der_len = 2 * key_bytes + DER_SIGNATURE_SZ; sig_der = malloc(sig_der_len); if (!sig_der) { res = TEE_ERROR_OUT_OF_MEMORY; goto exit; } /* truncate or pad the message as needed */ res = ecc_prepare_msg(algo_tee2se050(algo), msg, &msg_len, &p); if (res != TEE_SUCCESS) goto exit; res = se050_inject_keypair(&kobject, key, key_bytes); if (res != TEE_SUCCESS) goto exit; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, algo_tee2se050(algo), kMode_SSS_Sign); if (st != kStatus_SSS_Success) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } st = sss_se05x_asymmetric_sign_digest(&ctx, p ? p : (uint8_t *)msg, msg_len, sig_der, &sig_der_len); if (st != kStatus_SSS_Success) { EMSG("curve: %#"PRIx32, key->curve); res = TEE_ERROR_BAD_PARAMETERS; goto exit; } sss_se05x_signature_der2bin(sig_der, &sig_der_len); if (sig_der_len > *sig_len) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } memcpy(sig, sig_der, sig_der_len); *sig_len = sig_der_len; exit: if (!se050_ecc_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); free(sig_der); free(p); return res; } static TEE_Result verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; uint8_t *signature = NULL; size_t signature_len = sig_len + DER_SIGNATURE_SZ; size_t key_bytes = 0; size_t key_bits = 0; uint8_t *p = NULL; res = ecc_get_key_size(key->curve, algo, &key_bytes, &key_bits); if (res) { if (res != TEE_ERROR_NOT_IMPLEMENTED) goto exit; return verify_fallback(algo, key, msg, msg_len, sig, sig_len); } /* truncate or pad the message as needed */ res = ecc_prepare_msg(algo_tee2se050(algo), msg, &msg_len, &p); if (res != TEE_SUCCESS) goto exit; res = se050_inject_public_key(&kobject, key, key_bytes); if (res != TEE_SUCCESS) goto exit; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, algo_tee2se050(algo), kMode_SSS_Verify); if (st != kStatus_SSS_Success) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } signature = calloc(1, signature_len); if (!signature) { res = TEE_ERROR_OUT_OF_MEMORY; goto exit; } st = sss_se05x_signature_bin2der(signature, &signature_len, (uint8_t *)sig, sig_len); if (st != kStatus_SSS_Success) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } st = sss_se05x_asymmetric_verify_digest(&ctx, p ? p : (uint8_t *)msg, msg_len, (uint8_t *)signature, signature_len); if (st != kStatus_SSS_Success) res = TEE_ERROR_SIGNATURE_INVALID; exit: sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); free(p); free(signature); return res; } static TEE_Result gen_keypair(struct ecc_keypair *key, size_t key_size) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_object_t k_object = { }; TEE_Result ret = TEE_SUCCESS; uint8_t kf[512] = { }; uint32_t oid = 0; uint64_t kid = 0; size_t bytes = 0; size_t bits = 0; ret = ecc_get_key_size(key->curve, 0, &bytes, &bits); if (ret) { if (ret != TEE_ERROR_NOT_IMPLEMENTED) return ret; return gen_fallback(key, key_size); } st = sss_se05x_key_object_init(&k_object, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_key_object_allocate_handle(&k_object, oid, kSSS_KeyPart_Pair, cipher_tee2se050(key->curve), 0, kKeyObject_Mode_Persistent); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; st = sss_se05x_key_store_generate_key(se050_kstore, &k_object, bits, &se050_asym_policy); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; bytes = sizeof(kf); st = se050_key_store_get_ecc_key_bin(se050_kstore, &k_object, kf, &bytes); if (st != kStatus_SSS_Success) { sss_se05x_key_store_erase_key(se050_kstore, &k_object); return TEE_ERROR_BAD_PARAMETERS; } /* skip the DER tag */ crypto_bignum_bin2bn(kf + 1, bytes / 2, key->x); crypto_bignum_bin2bn(kf + 1 + bytes / 2, bytes / 2, key->y); kid = se050_generate_private_key(oid); crypto_bignum_bin2bn((uint8_t *)&kid, sizeof(kid), key->d); key->curve = curve_se0502tee(k_object.curve_id); if (key->curve != TEE_CRYPTO_ELEMENT_NONE) return TEE_SUCCESS; EMSG("ecc key generation failed"); sss_se05x_key_store_erase_key(se050_kstore, &k_object); return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t size_bytes) { return gen_keypair(key, size_bytes); } static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) { return shared_secret(sdata->key_priv, sdata->key_pub, sdata->secret.data, &sdata->secret.length); } static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) { return sign(sdata->algo, sdata->key, sdata->message.data, sdata->message.length, sdata->signature.data, &sdata->signature.length); } static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) { return verify(sdata->algo, sdata->key, sdata->message.data, sdata->message.length, sdata->signature.data, sdata->signature.length); } static TEE_Result do_alloc_keypair(struct ecc_keypair *s, uint32_t type, size_t size_bits __unused) { /* This driver only supports ECDH/ECDSA */ if (type != TEE_TYPE_ECDSA_KEYPAIR && type != TEE_TYPE_ECDH_KEYPAIR) return TEE_ERROR_NOT_IMPLEMENTED; memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->d)) goto err; if (!bn_alloc_max(&s->x)) goto err; if (!bn_alloc_max(&s->y)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->d); crypto_bignum_free(&s->x); crypto_bignum_free(&s->y); return TEE_ERROR_OUT_OF_MEMORY; } static TEE_Result do_alloc_publickey(struct ecc_public_key *s, uint32_t type, size_t size_bits __unused) { /* This driver only supports ECDH/ECDSA */ if (type != TEE_TYPE_ECDSA_PUBLIC_KEY && type != TEE_TYPE_ECDH_PUBLIC_KEY) return TEE_ERROR_NOT_IMPLEMENTED; memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->x)) goto err; if (!bn_alloc_max(&s->y)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->x); crypto_bignum_free(&s->y); return TEE_ERROR_OUT_OF_MEMORY; } static void do_free_publickey(struct ecc_public_key *s) { if (!s) return; crypto_bignum_free(&s->x); crypto_bignum_free(&s->y); } static struct drvcrypt_ecc driver_ecc = { .alloc_keypair = do_alloc_keypair, .alloc_publickey = do_alloc_publickey, .free_publickey = do_free_publickey, .gen_keypair = do_gen_keypair, .sign = do_sign, .verify = do_verify, .shared_secret = do_shared_secret, }; static TEE_Result ecc_init(void) { pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY); if (!pub_ops) return TEE_ERROR_GENERIC; pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR); if (!pair_ops) return TEE_ERROR_GENERIC; /* This driver supports both ECDH and ECDSA */ assert((pub_ops == crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) && (pair_ops == crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR))); return drvcrypt_register_ecc(&driver_ecc); } driver_init_late(ecc_init); optee_os-4.3.0/core/drivers/crypto/se050/core/include/000077500000000000000000000000001464416617300225045ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/core/include/se050_cipher_algorithms.h000066400000000000000000000007641464416617300273030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef SE050_CIPHER_ALGORITHMS_H_ #define SE050_CIPHER_ALGORITHMS_H_ #include #if defined(CFG_NXP_SE05X_CTR_DRV) TEE_Result se050_aes_ctr_allocate(void **ctx); #else static inline TEE_Result se050_aes_ctr_allocate(void **ctx __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #endif /* SE050_CIPHER_ALGORITHMS_H_ */ optee_os-4.3.0/core/drivers/crypto/se050/core/rng.c000066400000000000000000000014251464416617300220150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include static TEE_Result do_rng_read(void *buf, size_t blen) { sss_status_t status = kStatus_SSS_Success; sss_se05x_rng_context_t rng = { }; sss_se05x_rng_context_init(&rng, se050_session); status = sss_se05x_rng_get_random(&rng, buf, blen); sss_se05x_rng_context_free(&rng); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } void plat_rng_init(void) { } TEE_Result hw_get_random_bytes(void *buf, size_t blen) { if (!buf) return TEE_ERROR_BAD_PARAMETERS; return do_rng_read(buf, blen); } optee_os-4.3.0/core/drivers/crypto/se050/core/rsa.c000066400000000000000000000616741464416617300220300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #include #include #include #include static sss_cipher_type_t oefid_cipher_type(void) { switch (se050_get_oefid()) { case SE050F_ID: return kSSS_CipherType_RSA_CRT; default: return kSSS_CipherType_RSA; } } static bool oefid_keylen_supported(size_t bits) { switch (se050_get_oefid()) { case SE050F_ID: return bits >= 2048; default: return true; } } static bool rsa_keypair_has_crt(struct rsa_keypair *key) { if (key->p && crypto_bignum_num_bytes(key->p) && key->q && crypto_bignum_num_bytes(key->q) && key->qp && crypto_bignum_num_bytes(key->qp) && key->dp && crypto_bignum_num_bytes(key->dp) && key->dq && crypto_bignum_num_bytes(key->dq)) return true; return false; } static bool keypair_supported(struct rsa_keypair *key, sss_cipher_type_t ctype) { if (se050_rsa_keypair_from_nvm(key)) return true; if (ctype == kSSS_CipherType_RSA_CRT) return rsa_keypair_has_crt(key); return true; } static uint32_t tee2se050(uint32_t algo) { switch (algo) { case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA1; case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA224; case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA256; case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA384; case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_SHA512; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA1; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA224; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA256; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA384; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return kAlgorithm_SSS_RSASSA_PKCS1_PSS_MGF1_SHA512; case TEE_ALG_RSAES_PKCS1_V1_5: return kAlgorithm_SSS_RSAES_PKCS1_V1_5_SHA256; case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA1; case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA224; case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA256; case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA384; case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: return kAlgorithm_SSS_RSAES_PKCS1_OAEP_SHA512; case TEE_ALG_RSA_NOPAD: return kAlgorithm_SSS_RSASSA_NO_PADDING; #ifdef CFG_CRYPTO_RSASSA_NA1 case TEE_ALG_RSASSA_PKCS1_V1_5: return kAlgorithm_SSS_RSASSA_PKCS1_V1_5_NO_HASH; #endif case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1: default: return kAlgorithm_None; } } static bool bn_alloc_max(struct bignum **s) { *s = crypto_bignum_allocate(4096); return *s; } static TEE_Result set_binary_data(struct bignum *b, uint8_t **p, size_t *len) { *len = crypto_bignum_num_bytes(b); if (*len) { *p = (uint8_t *)calloc(1, *len); if (!*p) return TEE_ERROR_OUT_OF_MEMORY; crypto_bignum_bn2bin(b, *p); } return TEE_SUCCESS; } static TEE_Result se050_inject_public_key(sss_se05x_object_t *k_object, struct rsa_public_key *key) { sss_status_t st = kStatus_SSS_Fail; struct se050_rsa_keypub key_bin = { }; uint32_t oid = 0; st = sss_se05x_key_object_init(k_object, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; /* * Keys 2048 and above MUST to be placed on persistent storage even * though the keys will be deleted after the operation. This is a * memory restriction in the secure element. */ st = sss_se05x_key_object_allocate_handle(k_object, oid, kSSS_KeyPart_Public, oefid_cipher_type(), 0, kKeyObject_Mode_Persistent); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; set_binary_data(key->e, &key_bin.e, &key_bin.e_len); set_binary_data(key->n, &key_bin.n, &key_bin.n_len); st = se050_key_store_set_rsa_key_bin(se050_kstore, k_object, NULL, &key_bin, key_bin.n_len * 8); free(key_bin.n); free(key_bin.e); if (st != kStatus_SSS_Success) { sss_se05x_key_store_erase_key(se050_kstore, k_object); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result se050_inject_keypair(sss_se05x_object_t *k_object, struct rsa_keypair *key) { sss_status_t st = kStatus_SSS_Fail; struct se050_rsa_keypair key_bin = { }; uint32_t key_id = 0; uint32_t oid = 0; st = sss_se05x_key_object_init(k_object, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; key_id = se050_rsa_keypair_from_nvm(key); if (key_id) { st = sss_se05x_key_object_get_handle(k_object, key_id); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; /* Keys 2048 and above need to be placed on persistent storage */ st = sss_se05x_key_object_allocate_handle(k_object, oid, kSSS_KeyPart_Pair, oefid_cipher_type(), 0, kKeyObject_Mode_Persistent); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; set_binary_data(key->e, &key_bin.e, &key_bin.e_len); set_binary_data(key->d, &key_bin.d, &key_bin.d_len); set_binary_data(key->n, &key_bin.n, &key_bin.n_len); set_binary_data(key->p, &key_bin.p, &key_bin.p_len); set_binary_data(key->q, &key_bin.q, &key_bin.q_len); set_binary_data(key->qp, &key_bin.qp, &key_bin.qp_len); set_binary_data(key->dp, &key_bin.dp, &key_bin.dp_len); set_binary_data(key->dq, &key_bin.dq, &key_bin.dq_len); st = se050_key_store_set_rsa_key_bin(se050_kstore, k_object, &key_bin, NULL, crypto_bignum_num_bits(key->n)); free(key_bin.e); free(key_bin.d); free(key_bin.n); free(key_bin.p); free(key_bin.q); free(key_bin.qp); free(key_bin.dp); free(key_bin.dq); if (st != kStatus_SSS_Success) { sss_se05x_key_store_erase_key(se050_kstore, k_object); return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result decrypt_es(uint32_t algo, struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; uint8_t *buf = NULL; size_t buf_len = src_len; res = se050_inject_keypair(&kobject, key); if (res) return res; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, tee2se050(algo), kMode_SSS_Decrypt); if (st != kStatus_SSS_Success) { if (!se050_rsa_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); return TEE_ERROR_BAD_PARAMETERS; } /* we don't know the size of the decrypted data, just the upper limit */ buf = mempool_calloc(mempool_default, 1, buf_len); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } st = sss_se05x_asymmetric_decrypt(&ctx, src, src_len, buf, &buf_len); if (st != kStatus_SSS_Success) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (buf_len > *dst_len) { *dst_len = buf_len; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = buf_len; memcpy(dst, buf, buf_len); out: if (!se050_rsa_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); mempool_free(mempool_default, buf); return res; } static TEE_Result encrypt_es(uint32_t algo, struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; if (*dst_len < crypto_bignum_num_bytes(key->n)) { *dst_len = crypto_bignum_num_bytes(key->n); return TEE_ERROR_SHORT_BUFFER; } if (se050_inject_public_key(&kobject, key)) return TEE_ERROR_BAD_PARAMETERS; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, tee2se050(algo), kMode_SSS_Encrypt); if (st != kStatus_SSS_Success) { sss_se05x_key_store_erase_key(se050_kstore, &kobject); return TEE_ERROR_BAD_PARAMETERS; } st = sss_se05x_asymmetric_encrypt(&ctx, src, src_len, dst, dst_len); if (st != kStatus_SSS_Success) res = TEE_ERROR_BAD_PARAMETERS; sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); return res; } static TEE_Result decrypt_nopad(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; uint8_t *buf = NULL; size_t offset = 0; size_t blen = 0; size_t rsa_len = 0; res = se050_inject_keypair(&kobject, key); if (res) return res; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, kAlgorithm_SSS_RSASSA_NO_PADDING, kMode_SSS_Decrypt); if (st != kStatus_SSS_Success) { if (!se050_rsa_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); return TEE_ERROR_BAD_PARAMETERS; } blen = CFG_CORE_BIGNUM_MAX_BITS / 8; buf = mempool_calloc(mempool_default, 1, blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } rsa_len = crypto_bignum_num_bytes(key->n); memcpy(buf + rsa_len - src_len, src, src_len); st = sss_se05x_asymmetric_decrypt(&ctx, buf, rsa_len, buf, &blen); if (st != kStatus_SSS_Success) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* Remove the zero-padding (leave one zero if buff is all zeroes) */ offset = 0; while ((offset < blen - 1) && (buf[offset] == 0)) offset++; if (*dst_len < blen - offset) { *dst_len = blen - offset; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = blen - offset; memcpy(dst, buf + offset, *dst_len); out: mempool_free(mempool_default, buf); if (!se050_rsa_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); return res; } static TEE_Result encrypt_nopad(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; uint8_t *buf = NULL; size_t offset = 0; size_t blen = 0; size_t rsa_len = 0; if (se050_inject_public_key(&kobject, key)) return TEE_ERROR_BAD_PARAMETERS; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, kAlgorithm_SSS_RSASSA_NO_PADDING, kMode_SSS_Encrypt); if (st != kStatus_SSS_Success) { sss_se05x_key_store_erase_key(se050_kstore, &kobject); return TEE_ERROR_BAD_PARAMETERS; } blen = CFG_CORE_BIGNUM_MAX_BITS / 8; buf = mempool_calloc(mempool_default, 1, blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } rsa_len = crypto_bignum_num_bytes(key->n); memcpy(buf + rsa_len - src_len, src, src_len); st = sss_se05x_asymmetric_encrypt(&ctx, buf, rsa_len, buf, &blen); if (st != kStatus_SSS_Success) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* Remove the zero-padding (leave one zero if buff is all zeroes) */ offset = 0; while ((offset < blen - 1) && (buf[offset] == 0)) offset++; if (*dst_len < blen - offset) { *dst_len = blen - offset; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = blen - offset; memcpy(dst, buf + offset, *dst_len); out: mempool_free(mempool_default, buf); sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); return res; } static TEE_Result sign_ssa(uint32_t algo, struct rsa_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; if (*sig_len < crypto_bignum_num_bytes(key->n)) { *sig_len = crypto_bignum_num_bytes(key->n); return TEE_ERROR_SHORT_BUFFER; } res = se050_inject_keypair(&kobject, key); if (res) return res; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, tee2se050(algo), kMode_SSS_Sign); if (st != kStatus_SSS_Success) { if (!se050_rsa_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); return TEE_ERROR_BAD_PARAMETERS; } st = sss_se05x_asymmetric_sign_digest(&ctx, (uint8_t *)msg, msg_len, sig, sig_len); if (st != kStatus_SSS_Success) res = TEE_ERROR_BAD_PARAMETERS; if (!se050_rsa_keypair_from_nvm(key)) sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); return res; } static TEE_Result verify_ssa(uint32_t algo, struct rsa_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_asymmetric_t ctx = { }; sss_se05x_object_t kobject = { }; TEE_Result res = TEE_SUCCESS; if (se050_inject_public_key(&kobject, key)) return TEE_ERROR_BAD_PARAMETERS; st = sss_se05x_asymmetric_context_init(&ctx, se050_session, &kobject, tee2se050(algo), kMode_SSS_Verify); if (st != kStatus_SSS_Success) { sss_se05x_key_store_erase_key(se050_kstore, &kobject); return TEE_ERROR_BAD_PARAMETERS; } st = sss_se05x_asymmetric_verify_digest(&ctx, (uint8_t *)msg, msg_len, (uint8_t *)sig, sig_len); if (st != kStatus_SSS_Success) res = TEE_ERROR_SIGNATURE_INVALID; sss_se05x_key_store_erase_key(se050_kstore, &kobject); sss_se05x_asymmetric_context_free(&ctx); return res; } static TEE_Result do_alloc_keypair(struct rsa_keypair *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->e)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->d)) goto err; if (!bn_alloc_max(&s->n)) goto err; if (!bn_alloc_max(&s->p)) goto err; if (!bn_alloc_max(&s->q)) goto err; if (!bn_alloc_max(&s->qp)) goto err; if (!bn_alloc_max(&s->dp)) goto err; if (!bn_alloc_max(&s->dq)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->e); crypto_bignum_free(&s->d); crypto_bignum_free(&s->n); crypto_bignum_free(&s->p); crypto_bignum_free(&s->q); crypto_bignum_free(&s->qp); crypto_bignum_free(&s->dp); crypto_bignum_free(&s->dq); return TEE_ERROR_OUT_OF_MEMORY; } static TEE_Result do_alloc_publickey(struct rsa_public_key *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->e)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->n)) { crypto_bignum_free(&s->e); return TEE_ERROR_OUT_OF_MEMORY; } return TEE_SUCCESS; } static void do_free_publickey(struct rsa_public_key *s) { if (s) { crypto_bignum_free(&s->n); crypto_bignum_free(&s->e); } } static void do_free_keypair(struct rsa_keypair *s) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_object_t k_object = { }; uint32_t key_id = 0; if (!s) return; key_id = se050_rsa_keypair_from_nvm(s); if (key_id) { st = sss_se05x_key_object_get_handle(&k_object, key_id); if (st == kStatus_SSS_Success) sss_se05x_key_store_erase_key(se050_kstore, &k_object); } crypto_bignum_free(&s->e); crypto_bignum_free(&s->d); crypto_bignum_free(&s->n); crypto_bignum_free(&s->p); crypto_bignum_free(&s->q); crypto_bignum_free(&s->qp); crypto_bignum_free(&s->dp); crypto_bignum_free(&s->dq); } static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t kb) { sss_status_t st = kStatus_SSS_Fail; sss_se05x_object_t k_object = { }; uint32_t oid = 0; uint64_t kid = 0; uint8_t k[2048] = { 0 }; uint8_t *n = NULL; uint8_t *e = NULL; size_t n_len = 0; size_t e_len = 0; size_t k_len = sizeof(k); if (!oefid_keylen_supported(kb)) { if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: RSA software fallback: KEYGEN"); return sw_crypto_acipher_gen_rsa_key(key, kb); } st = sss_se05x_key_object_init(&k_object, se050_kstore); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; st = se050_get_oid(&oid); if (st != kStatus_SSS_Success) return TEE_ERROR_GENERIC; st = sss_se05x_key_object_allocate_handle(&k_object, oid, kSSS_KeyPart_Pair, oefid_cipher_type(), 0, kKeyObject_Mode_Persistent); if (st != kStatus_SSS_Success) return TEE_ERROR_BAD_PARAMETERS; st = sss_se05x_key_store_generate_key(se050_kstore, &k_object, kb, &se050_asym_policy); if (st != kStatus_SSS_Success) goto error; st = sss_se05x_key_store_get_key(se050_kstore, &k_object, k, &k_len, &kb); if (st != kStatus_SSS_Success) goto error; st = sss_util_asn1_rsa_parse_public(k, k_len, &n, &n_len, &e, &e_len); if (st != kStatus_SSS_Success) goto error; crypto_bignum_bin2bn(n, n_len, key->n); crypto_bignum_bin2bn(e, e_len, key->e); kid = se050_generate_private_key(oid); crypto_bignum_bin2bn((uint8_t *)&kid, sizeof(kid), (key->d)); crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->p); crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->q); crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->qp); crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->dp); crypto_bignum_bin2bn((uint8_t *)&oid, sizeof(oid), key->dq); free(n); free(e); return TEE_SUCCESS; error: sss_se05x_key_store_erase_key(se050_kstore, &k_object); return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result encrypt_fallback(struct drvcrypt_rsa_ed *p) { if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; switch (p->rsa_id) { case DRVCRYPT_RSA_NOPAD: DMSG("se050: debug: RSA software fallback: ENCRYPT_NOPAD"); return sw_crypto_acipher_rsanopad_encrypt(p->key.key, p->message.data, p->message.length, p->cipher.data, &p->cipher.length); case DRVCRYPT_RSA_OAEP: case DRVCRYPT_RSA_PKCS_V1_5: case DRVCRYPT_RSASSA_PKCS_V1_5: case DRVCRYPT_RSASSA_PSS: default: DMSG("se050: debug: RSA software fallback: ENCRYPT_ES"); return sw_crypto_acipher_rsaes_encrypt(p->algo, p->key.key, p->label.data, p->label.length, p->mgf_algo, p->message.data, p->message.length, p->cipher.data, &p->cipher.length); } } static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) { if (!oefid_keylen_supported(rsa_data->key.n_size * 8)) return encrypt_fallback(rsa_data); switch (rsa_data->rsa_id) { case DRVCRYPT_RSA_NOPAD: case DRVCRYPT_RSASSA_PSS: case DRVCRYPT_RSASSA_PKCS_V1_5: return encrypt_nopad(rsa_data->key.key, rsa_data->message.data, rsa_data->message.length, rsa_data->cipher.data, &rsa_data->cipher.length); case DRVCRYPT_RSA_PKCS_V1_5: return encrypt_es(TEE_ALG_RSAES_PKCS1_V1_5, rsa_data->key.key, rsa_data->message.data, rsa_data->message.length, rsa_data->cipher.data, &rsa_data->cipher.length); case DRVCRYPT_RSA_OAEP: if (rsa_data->hash_algo != TEE_ALG_SHA1 || rsa_data->hash_algo != rsa_data->mgf_algo) return encrypt_fallback(rsa_data); return encrypt_es(TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, rsa_data->key.key, rsa_data->message.data, rsa_data->message.length, rsa_data->cipher.data, &rsa_data->cipher.length); default: break; } return encrypt_fallback(rsa_data); } static TEE_Result decrypt_fallback(struct drvcrypt_rsa_ed *p) { if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; if (se050_rsa_keypair_from_nvm(p->key.key)) return TEE_ERROR_NOT_IMPLEMENTED; switch (p->rsa_id) { case DRVCRYPT_RSA_NOPAD: DMSG("se050: debug: RSA software fallback: DECRYPT_NOPAD"); return sw_crypto_acipher_rsanopad_decrypt(p->key.key, p->cipher.data, p->cipher.length, p->message.data, &p->message.length); case DRVCRYPT_RSA_OAEP: case DRVCRYPT_RSA_PKCS_V1_5: case DRVCRYPT_RSASSA_PKCS_V1_5: case DRVCRYPT_RSASSA_PSS: default: DMSG("se050: debug: RSA software fallback: DECRYPT_ES"); return sw_crypto_acipher_rsaes_decrypt(p->algo, p->key.key, p->label.data, p->label.length, p->mgf_algo, p->cipher.data, p->cipher.length, p->message.data, &p->message.length); } } static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) { if (!oefid_keylen_supported(rsa_data->key.n_size * 8)) return decrypt_fallback(rsa_data); if (!keypair_supported(rsa_data->key.key, oefid_cipher_type())) return decrypt_fallback(rsa_data); switch (rsa_data->rsa_id) { case DRVCRYPT_RSA_NOPAD: case DRVCRYPT_RSASSA_PSS: case DRVCRYPT_RSASSA_PKCS_V1_5: return decrypt_nopad(rsa_data->key.key, rsa_data->cipher.data, rsa_data->cipher.length, rsa_data->message.data, &rsa_data->message.length); case DRVCRYPT_RSA_PKCS_V1_5: return decrypt_es(TEE_ALG_RSAES_PKCS1_V1_5, rsa_data->key.key, rsa_data->cipher.data, rsa_data->cipher.length, rsa_data->message.data, &rsa_data->message.length); case DRVCRYPT_RSA_OAEP: if (rsa_data->hash_algo != TEE_ALG_SHA1 || rsa_data->hash_algo != rsa_data->mgf_algo) return decrypt_fallback(rsa_data); return decrypt_es(TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1, rsa_data->key.key, rsa_data->cipher.data, rsa_data->cipher.length, rsa_data->message.data, &rsa_data->message.length); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } static TEE_Result sign_ssa_fallback(struct drvcrypt_rsa_ssa *p) { if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; if (se050_rsa_keypair_from_nvm(p->key.key)) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: RSA software fallback: SIGN"); return sw_crypto_acipher_rsassa_sign(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, &p->signature.length); } static TEE_Result do_ssa_sign(struct drvcrypt_rsa_ssa *ssa_data) { if (!oefid_keylen_supported(ssa_data->key.n_size * 8)) return sign_ssa_fallback(ssa_data); if (!keypair_supported(ssa_data->key.key, oefid_cipher_type())) return sign_ssa_fallback(ssa_data); /* PKCS1_PSS_MGF1 padding limitations */ switch (ssa_data->algo) { case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: if (ssa_data->key.n_size * 8 <= 512) return sign_ssa_fallback(ssa_data); break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: if (ssa_data->key.n_size * 8 <= 1024) return sign_ssa_fallback(ssa_data); break; default: break; } return sign_ssa(ssa_data->algo, ssa_data->key.key, ssa_data->message.data, ssa_data->message.length, ssa_data->signature.data, &ssa_data->signature.length); } static TEE_Result verify_ssa_fallback(struct drvcrypt_rsa_ssa *p) { if (!IS_ENABLED(CFG_NXP_SE05X_RSA_DRV_FALLBACK)) return TEE_ERROR_NOT_IMPLEMENTED; DMSG("se050: debug: RSA software fallback: VERIFY"); return sw_crypto_acipher_rsassa_verify(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, p->signature.length); } static TEE_Result do_ssa_verify(struct drvcrypt_rsa_ssa *ssa_data) { if (!oefid_keylen_supported(ssa_data->key.n_size * 8)) return verify_ssa_fallback(ssa_data); /* PKCS1_PSS_MGF1 padding limitations */ switch (ssa_data->algo) { case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: if (ssa_data->key.n_size * 8 <= 512) return verify_ssa_fallback(ssa_data); break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: if (ssa_data->key.n_size * 8 <= 1024) return verify_ssa_fallback(ssa_data); break; default: break; } return verify_ssa(ssa_data->algo, ssa_data->key.key, ssa_data->message.data, ssa_data->message.length, ssa_data->signature.data, ssa_data->signature.length); } static const struct drvcrypt_rsa driver_rsa = { .alloc_keypair = do_alloc_keypair, .alloc_publickey = do_alloc_publickey, .free_publickey = do_free_publickey, .free_keypair = do_free_keypair, .gen_keypair = do_gen_keypair, .encrypt = do_encrypt, .decrypt = do_decrypt, .optional.ssa_sign = do_ssa_sign, .optional.ssa_verify = do_ssa_verify, }; static TEE_Result rsa_init(void) { return drvcrypt_register_rsa(&driver_rsa); } driver_init_late(rsa_init); optee_os-4.3.0/core/drivers/crypto/se050/core/scp03.c000066400000000000000000000013071464416617300221560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include TEE_Result crypto_se_enable_scp03(bool rotate_keys) { sss_status_t status = kStatus_SSS_Success; status = se050_enable_scp03(se050_session); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; if (rotate_keys) { if (IS_ENABLED(CFG_CORE_SE05X_SCP03_PROVISION)) { status = se050_rotate_scp03_keys(&se050_ctx); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/crypto/se050/core/storage.c000066400000000000000000000051201464416617300226670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include TEE_Result crypto_storage_obj_del(struct tee_obj *o) { sss_status_t status = kStatus_SSS_Success; uint32_t val = SE050_KEY_WATERMARK; TEE_Result ret = TEE_ERROR_GENERIC; sss_se05x_object_t k_object = { }; uint8_t *data = NULL; uint8_t *p = NULL; bool found = false; size_t len = 0; if (!o) return TEE_ERROR_BAD_PARAMETERS; len = o->info.dataSize; /* Supported keys (ECC/RSA) require less than 4KB of storage */ if (len > SMALL_PAGE_SIZE || len <= sizeof(uint64_t)) return TEE_SUCCESS; data = calloc(1, len); if (!data) return TEE_ERROR_OUT_OF_MEMORY; /* Read the object into memory */ ret = o->pobj->fops->read(o->fh, o->info.dataPosition, data, NULL, &len); if (ret) { EMSG("se05x: can not read the object prior removal"); free(data); goto out; } /* Scan the object for the watermark */ p = data; while (len >= sizeof(uint32_t) && !found) { if (memcmp(p, &val, sizeof(val)) != 0) { p++; len--; continue; } found = true; } if (!found) { free(data); return TEE_SUCCESS; } /* Retrieve the object identifier */ p = p - 4; memcpy((void *)&val, p, sizeof(val)); free(data); if (val < OID_MIN || val > OID_MAX) return TEE_SUCCESS; status = sss_se05x_key_object_init(&k_object, se050_kstore); if (status != kStatus_SSS_Success) { ret = TEE_ERROR_BAD_STATE; goto out; } status = sss_se05x_key_object_get_handle(&k_object, val); if (status != kStatus_SSS_Success) { EMSG("se05x: can not communicate with the secure element"); ret = TEE_ERROR_BAD_STATE; goto out; } status = sss_se05x_key_store_erase_key(se050_kstore, &k_object); if (status != kStatus_SSS_Success) { EMSG("se05x: can not communicate with the secure element"); ret = TEE_ERROR_BAD_STATE; goto out; } out: /* * Users can delete the SE05X NVM objects during boot using a built * time configuration flag (CFG_CORE_SE05X_INIT_NVM). * * This could cause the deletion of the secure storage objects holding * references to those IDs via crypto_storage_obj_del() to fail, leaving * broken links in the file system. * * Therefore we only permit this call to block the deletion upon an * additional specific config. */ if (ret && IS_ENABLED(CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR)) return ret; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/crypto/se050/core/sub.mk000066400000000000000000000010121464416617300221750ustar00rootroot00000000000000include ${CFG_NXP_SE05X_PLUG_AND_TRUST}/cflags.mk incdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST}/optee_lib/include incdirs-y += ../adaptors/include incdirs-y += include srcs-y += storage.c srcs-$(CFG_NXP_SE05X_RSA_DRV) += rsa.c srcs-$(CFG_NXP_SE05X_ECC_DRV) += ecc.c srcs-$(CFG_NXP_SE05X_CTR_DRV) += ctr.c srcs-$(CFG_NXP_SE05X_DIEID_DRV) += die_id.c srcs-$(CFG_NXP_SE05X_RNG_DRV) += rng.c srcs-$(CFG_NXP_SE05X_CIPHER_DRV) += cipher.c srcs-$(CFG_NXP_SE05X_SCP03_DRV) += scp03.c srcs-$(CFG_NXP_SE05X_APDU_DRV) += apdu.c optee_os-4.3.0/core/drivers/crypto/se050/crypto.mk000066400000000000000000000072271464416617300220120ustar00rootroot00000000000000ifeq ($(CFG_NXP_SE05X),y) # Enable the crypto driver $(call force,CFG_CRYPTO_DRIVER,y) CFG_CRYPTO_DRIVER_DEBUG ?= 0 # SE050 initialization # Some secure elements can only be accessed over an SCP03 enabled session. # Some of the NXP SE05X devices fall in this category (i.e NXP SE050F). # Only enable this configuration to support those systems. CFG_CORE_SCP03_ONLY ?= n # Rotate the SCP03 keys during SCP03 init (does not require user intervention). # CAUTION: the provisioning configuration chosen might require a stable HUK. CFG_CORE_SE05X_SCP03_PROVISION_ON_INIT ?= n # Rotate the SCP03 keys via PTA (request from Normal World). CFG_CORE_SE05X_SCP03_PROVISION ?= n # The Provision request will rotate the SCP03 keys back to its factory settings. CFG_CORE_SE05X_SCP03_PROVISION_WITH_FACTORY_KEYS ?= n # CAUTION: Leaks the SCP03 keys that are going to be programmed on the device's # NVM during a provisioning operation. CFG_CORE_SE05X_DISPLAY_SCP03_KEYS ?= n # Displays the SE050 device information on the console at boot (i.e. OEFID) CFG_CORE_SE05X_DISPLAY_INFO ?= y # Enables SCP03 protocol during boot (does not require user intervention) CFG_CORE_SE05X_SCP03_EARLY ?= y # CAUTION: Deletes all persistent storage (keys/certs) from the SE05X at boot CFG_CORE_SE05X_INIT_NVM ?= n # Prevents the deletion of the secure storage object holding a reference to a # Secure Element (SE) Non Volatile Memory object unless there is explicit # confirmation from the SE that the NVM object has been removed. CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR ?= n # Select the SE05X applet version for aligning the built-in features CFG_CORE_SE05X_VER ?= 03_XX # I2C bus baudrate (depends on SoC) CFG_CORE_SE05X_BAUDRATE ?= 3400000 # I2C bus [0..2] (depends on board) CFG_CORE_SE05X_I2C_BUS ?= 2 # I2C access via REE after TEE boot CFG_CORE_SE05X_I2C_TRAMPOLINE ?= y # Extra stacks required to support the Plug and Trust external library ifeq ($(shell test $(CFG_STACK_THREAD_EXTRA) -lt 8192; echo $$?), 0) $(error Error: SE050 requires CFG_STACK_THREAD_EXTRA at least 8192) endif ifeq ($(shell test $(CFG_STACK_TMP_EXTRA) -lt 8192; echo $$?), 0) $(error Error: SE050 requires CFG_STACK_TMP_EXTRA at least 8192) endif # SE05X Die Identifier CFG_NXP_SE05X_DIEID_DRV ?= y # Allow a secure client to enable the SCP03 session CFG_NXP_SE05X_SCP03_DRV ?= y ifeq ($(CFG_NXP_SE05X_SCP03_DRV),y) $(call force,CFG_SCP03_PTA,y,Mandated by CFG_NXP_SE05X_SCP03) endif # Allow a secure client to send APDU raw frames CFG_NXP_SE05X_APDU_DRV ?= y ifeq ($(CFG_NXP_SE05X_APDU_DRV),y) $(call force,CFG_APDU_PTA,y,Mandated by CFG_NXP_SE05X_APDU) endif # Random Number Generator CFG_NXP_SE05X_RNG_DRV ?= y ifeq ($(CFG_NXP_SE05X_RNG_DRV),y) $(call force,CFG_WITH_SOFTWARE_PRNG,n) endif se050-one-enabled = $(call cfg-one-enabled, \ $(foreach v,$(1), CFG_NXP_SE05X_$(v)_DRV)) # Asymmetric ciphers CFG_NXP_SE05X_RSA_DRV ?= y CFG_NXP_SE05X_RSA_DRV_FALLBACK ?= n CFG_NXP_SE05X_ECC_DRV ?= y CFG_NXP_SE05X_ECC_DRV_FALLBACK ?= n $(call force,CFG_NXP_SE05X_ACIPHER_DRV,$(call se050-one-enabled,RSA ECC)) # Asymmetric driver ifeq ($(CFG_NXP_SE05X_ACIPHER_DRV),y) $(call force,CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_NXP_SE05X_ACIPHER_DRV) endif # Asymmetric ciphers configuration # - RSA ifeq ($(CFG_NXP_SE05X_RSA_DRV),y) $(call force,CFG_CRYPTO_DRV_RSA,y) CFG_CRYPTO_RSASSA_NA1 ?= y endif # - ECC ifeq ($(CFG_NXP_SE05X_ECC_DRV),y) $(call force,CFG_CRYPTO_DRV_ECC,y) endif # Symmetric ciphers CFG_NXP_SE05X_CTR_DRV ?= y $(call force,CFG_NXP_SE05X_CIPHER_DRV,$(call se050-one-enabled,CTR)) # Symmetric driver ifeq ($(CFG_NXP_SE05X_CIPHER_DRV),y) $(call force,CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_NXP_SE05X_CIPHER_DRV) endif endif # CFG_NXP_SE05X optee_os-4.3.0/core/drivers/crypto/se050/glue/000077500000000000000000000000001464416617300210655ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/glue/i2c.c000066400000000000000000000024551464416617300217140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include #include static TEE_Result (*transfer)(struct rpc_i2c_request *req, size_t *bytes); static int i2c_transfer(uint8_t *buffer, int len, enum rpc_i2c_mode mode) { struct rpc_i2c_request request = { .bus = CFG_CORE_SE05X_I2C_BUS, .chip = SMCOM_I2C_ADDRESS >> 1, .mode = mode, .buffer = buffer, .buffer_len = len, .flags = 0, }; size_t bytes = 0; int retry = 5; do { if ((*transfer)(&request, &bytes) == TEE_SUCCESS) return bytes; } while (--retry); return -1; } int glue_i2c_read(uint8_t *buffer, int len) { return i2c_transfer(buffer, len, RPC_I2C_MODE_READ); } int glue_i2c_write(uint8_t *buffer, int len) { return i2c_transfer(buffer, len, RPC_I2C_MODE_WRITE); } int glue_i2c_init(void) { if (transfer == rpc_io_i2c_transfer) return 0; transfer = native_i2c_transfer; return native_i2c_init(); } static TEE_Result load_trampoline(void) { if (IS_ENABLED(CFG_CORE_SE05X_I2C_TRAMPOLINE)) transfer = rpc_io_i2c_transfer; return TEE_SUCCESS; } boot_final(load_trampoline); optee_os-4.3.0/core/drivers/crypto/se050/glue/i2c_imx.c000066400000000000000000000014751464416617300225720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes) { TEE_Result ret = TEE_ERROR_GENERIC; if (req->mode == RPC_I2C_MODE_READ) ret = imx_i2c_read(req->bus, req->chip, req->buffer, req->buffer_len); else ret = imx_i2c_write(req->bus, req->chip, req->buffer, req->buffer_len); if (!ret) *bytes = req->buffer_len; return ret; } int native_i2c_init(void) { if (imx_i2c_init(CFG_CORE_SE05X_I2C_BUS, CFG_CORE_SE05X_BAUDRATE)) return -1; if (imx_i2c_probe(CFG_CORE_SE05X_I2C_BUS, SMCOM_I2C_ADDRESS >> 1)) return -1; return 0; } optee_os-4.3.0/core/drivers/crypto/se050/glue/i2c_stm32.c000066400000000000000000000043651464416617300227460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved * Author: Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #include static_assert(CFG_CORE_SE05X_I2C_BUS < 10); static struct i2c_handle_s i2c; TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes) { if (req->mode == RPC_I2C_MODE_READ) { if (stm32_i2c_master_receive(&i2c, req->chip << 1, req->buffer, req->buffer_len, 25)) return TEE_ERROR_GENERIC; } else { if (stm32_i2c_master_transmit(&i2c, req->chip << 1, req->buffer, req->buffer_len, 25)) return TEE_ERROR_GENERIC; } *bytes = req->buffer_len; return TEE_SUCCESS; } static int dt_i2c_bus_config(struct stm32_i2c_init_s *init, struct pinctrl_state **pinctrl_active, struct pinctrl_state **pinctrl_sleep) { const fdt32_t *cuint = NULL; const char *path = NULL; char bus[6] = { }; void *fdt = NULL; int node = 0; fdt = get_embedded_dt(); if (!fdt) return -FDT_ERR_NOTFOUND; snprintf(bus, sizeof(bus), "i2c%d", CFG_CORE_SE05X_I2C_BUS); path = fdt_get_alias(fdt, bus); if (!path) return -FDT_ERR_NOTFOUND; node = fdt_path_offset(fdt, path); if (node < 0) return -FDT_ERR_NOTFOUND; cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); if (cuint && fdt32_to_cpu(*cuint) != CFG_CORE_SE05X_BAUDRATE) IMSG("SE05X ignoring CFG_CORE_SE05X_BAUDRATE, use DTB"); else if (I2C_STANDARD_RATE != CFG_CORE_SE05X_BAUDRATE) IMSG("SE05x ignoring CFG_CORE_SE05X_BAUDRATE, use built-in"); return stm32_i2c_get_setup_from_fdt(fdt, node, init, pinctrl_active, pinctrl_sleep); } int native_i2c_init(void) { struct stm32_i2c_init_s i2c_init = { }; /* No need to re-initialize */ if (i2c.base.pa) return 0; /* Support only one device on the platform */ if (dt_i2c_bus_config(&i2c_init, &i2c.pinctrl, &i2c.pinctrl_sleep)) return -1; /* Probe the device */ i2c_init.own_address1 = SMCOM_I2C_ADDRESS; i2c_init.digital_filter_coef = 0; i2c_init.analog_filter = true; stm32_i2c_resume(&i2c); return stm32_i2c_init(&i2c, &i2c_init); } optee_os-4.3.0/core/drivers/crypto/se050/glue/include/000077500000000000000000000000001464416617300225105ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/se050/glue/include/i2c_native.h000066400000000000000000000005431464416617300247060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2022 - All Rights Reserved * Author: Jorge Ramirez */ #ifndef I2C_NATIVE_H_ #define I2C_NATIVE_H_ #include TEE_Result native_i2c_transfer(struct rpc_i2c_request *req, size_t *bytes); int native_i2c_init(void); #endif optee_os-4.3.0/core/drivers/crypto/se050/glue/user.c000066400000000000000000000041751464416617300222160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include #include #include sss_status_t glue_mac_context_init(void **mac, const uint8_t *key, size_t len) { if (crypto_mac_alloc_ctx(mac, TEE_ALG_AES_CMAC)) return kStatus_SSS_Fail; if (crypto_mac_init(*mac, key, len)) return kStatus_SSS_Fail; return kStatus_SSS_Success; } void glue_mac_context_free(void *mac) { crypto_mac_free_ctx(mac); } sss_status_t glue_mac_update(void *mac, const uint8_t *msg, size_t len) { if (crypto_mac_update(mac, msg, len)) return kStatus_SSS_Fail; return kStatus_SSS_Success; } sss_status_t glue_mac_final(void *mac, uint8_t *buf, size_t len) { if (crypto_mac_final(mac, buf, len)) return kStatus_SSS_Fail; return kStatus_SSS_Success; } sss_status_t glue_mac_one_go(void *mac, const uint8_t *msg, size_t msg_len, uint8_t *buf, size_t mac_len) { if (crypto_mac_update(mac, msg, msg_len)) return kStatus_SSS_Fail; if (crypto_mac_final(mac, buf, mac_len)) return kStatus_SSS_Fail; return kStatus_SSS_Success; } sss_status_t glue_symmetric_context_init(void **cipher) { if (crypto_cipher_alloc_ctx(cipher, TEE_ALG_AES_CBC_NOPAD)) return kStatus_SSS_Fail; return kStatus_SSS_Success; } sss_status_t glue_cipher_one_go(void *cipher, TEE_OperationMode mode, uint8_t *iv, size_t iv_len, uint8_t *key, size_t key_len, const uint8_t *src, uint8_t *dst, size_t len) { if (crypto_cipher_init(cipher, mode, key, key_len, NULL, 0, iv, iv_len)) return kStatus_SSS_Fail; if (crypto_cipher_update(cipher, 0, true, src, len, dst)) return kStatus_SSS_Fail; crypto_cipher_final(cipher); return kStatus_SSS_Success; } void glue_context_free(void *cipher) { crypto_cipher_free_ctx(cipher); } sss_status_t glue_rng_get_random(uint8_t *data, size_t len) { if (IS_ENABLED(CFG_NXP_SE05X_RNG_DRV)) return kStatus_SSS_InvalidArgument; if (crypto_rng_read(data, len)) return kStatus_SSS_Fail; return kStatus_SSS_Success; } optee_os-4.3.0/core/drivers/crypto/se050/session.c000066400000000000000000000056741464416617300217740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #include sss_se05x_key_store_t *se050_kstore; sss_se05x_session_t *se050_session; struct sss_se05x_ctx se050_ctx; TEE_Result se050_core_early_init(struct se050_scp_key *keys) { sss_status_t status = kStatus_SSS_Success; status = se050_session_open(&se050_ctx, keys); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; if (IS_ENABLED(CFG_CORE_SE05X_INIT_NVM)) { status = se050_factory_reset(&se050_ctx.session.s_ctx); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; } if (se050_ctx.session.subsystem == kType_SSS_SubSystem_NONE) return TEE_ERROR_GENERIC; status = se050_key_store_and_object_init(&se050_ctx); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; se050_session = (sss_se05x_session_t *)((void *)&se050_ctx.session); se050_kstore = (sss_se05x_key_store_t *)((void *)&se050_ctx.ks); return TEE_SUCCESS; } static TEE_Result update_se_info(void) { sss_status_t status = kStatus_SSS_Success; status = se050_get_se_info(se050_session, IS_ENABLED(CFG_CORE_SE05X_DISPLAY_INFO)); /* the session must be closed after accessing the board information */ sss_se05x_session_close(se050_session); se050_scp03_set_disable(); if (status != kStatus_SSS_Success) return TEE_ERROR_GENERIC; if (IS_ENABLED(CFG_CORE_SCP03_ONLY)) return TEE_SUCCESS; return se050_core_early_init(NULL); } static TEE_Result enable_scp03(void) { if (se050_enable_scp03(se050_session) != kStatus_SSS_Success) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result se050_early_init_default(void) { if (se050_core_early_init(NULL)) { EMSG("Failed to open the default session"); panic(); } if (update_se_info()) { EMSG("Failed to read the secure element configuration"); panic(); } if (IS_ENABLED(CFG_CORE_SE05X_SCP03_EARLY)) { if (enable_scp03()) { EMSG("Failed to open the SCP03 session"); panic(); } } return TEE_SUCCESS; } static TEE_Result se050_early_init_scp03(void) { /* Initialize session */ se050_session = (sss_se05x_session_t *)((void *)&se050_ctx.session); se050_kstore = (sss_se05x_key_store_t *)((void *)&se050_ctx.ks); #ifdef CFG_CORE_SE05X_OEFID se050_ctx.se_info.oefid[0] = CFG_CORE_SE05X_OEFID >> 8; se050_ctx.se_info.oefid[1] = CFG_CORE_SE05X_OEFID & 0xff; #endif if (enable_scp03()) { EMSG("Failed to enable SCP03 session"); panic(); } if (update_se_info()) { EMSG("Failed to read the secure element configuration"); panic(); } if (enable_scp03()) { EMSG("Failed to re-open the SCP03 session"); panic(); } return TEE_SUCCESS; } static TEE_Result se050_session_init(void) { if (IS_ENABLED(CFG_CORE_SCP03_ONLY)) return se050_early_init_scp03(); return se050_early_init_default(); } driver_init(se050_session_init); optee_os-4.3.0/core/drivers/crypto/se050/sub.mk000066400000000000000000000006301464416617300212520ustar00rootroot00000000000000include ${CFG_NXP_SE05X_PLUG_AND_TRUST}/cflags.mk incdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST}/optee_lib/include incdirs-y += adaptors/include incdirs-y += glue/include subdirs-y += adaptors subdirs-y += core subdirs_ext-y += ${CFG_NXP_SE05X_PLUG_AND_TRUST} srcs-y += session.c srcs-$(CFG_IMX_I2C) += glue/i2c_imx.c srcs-$(CFG_STM32_I2C) += glue/i2c_stm32.c srcs-y += glue/i2c.c srcs-y += glue/user.c optee_os-4.3.0/core/drivers/crypto/stm32/000077500000000000000000000000001464416617300202455ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/stm32/authenc.c000066400000000000000000000222421464416617300220420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "stm32_cryp.h" #define MAX_TAG_SIZE 16U struct stm32_ae_ctx { struct crypto_authenc_ctx a_ctx; struct stm32_cryp_context cryp; enum stm32_cryp_algo_mode algo; uint8_t tag_mask[MAX_TAG_SIZE]; }; static void xor_vec(uint8_t *r, uint8_t *a, uint8_t *b, size_t len) { size_t i = 0; for (i = 0; i < len; i++) r[i] = a[i] ^ b[i]; } static struct stm32_ae_ctx *to_stm32_ae_ctx(struct crypto_authenc_ctx *ctx) { assert(ctx); return container_of(ctx, struct stm32_ae_ctx, a_ctx); } static TEE_Result stm32_ae_gcm_generate_iv(struct stm32_ae_ctx *c, uint32_t *iv, struct drvcrypt_authenc_init *dinit) { TEE_Result res = TEE_SUCCESS; uint8_t tag1[MAX_TAG_SIZE] = { 0 }; uint8_t tag2[MAX_TAG_SIZE] = { 0 }; uint32_t j0[MAX_TAG_SIZE / sizeof(uint32_t)] = { 0 }; uint8_t dummy_iv[MAX_TAG_SIZE] = { 0 }; struct stm32_cryp_context ctx = { }; uint8_t *data_out = NULL; if (dinit->nonce.length == 12) { memcpy(iv, dinit->nonce.data, dinit->nonce.length); iv[3] = TEE_U32_TO_BIG_ENDIAN(2); return TEE_SUCCESS; } /* Calculate GHASH(dinit->nonce.data) */ dummy_iv[15] = 2; res = stm32_cryp_init(&ctx, true, STM32_CRYP_MODE_AES_GCM, dinit->key.data, dinit->key.length, dummy_iv, sizeof(dummy_iv)); if (res) return res; res = stm32_cryp_final(&ctx, tag1, sizeof(tag1)); if (res) return res; memset(&ctx, 0, sizeof(ctx)); res = stm32_cryp_init(&ctx, true, STM32_CRYP_MODE_AES_GCM, dinit->key.data, dinit->key.length, dummy_iv, sizeof(dummy_iv)); if (res) return res; data_out = malloc(dinit->nonce.length); if (!data_out) return TEE_ERROR_OUT_OF_MEMORY; res = stm32_cryp_update_load(&ctx, dinit->nonce.data, data_out, dinit->nonce.length); free(data_out); if (res) return res; res = stm32_cryp_final(&ctx, tag2, sizeof(tag2)); if (res) return res; xor_vec((uint8_t *)j0, tag1, tag2, sizeof(tag1)); memcpy(iv, j0, sizeof(j0)); iv[3] = TEE_U32_TO_BIG_ENDIAN(TEE_U32_FROM_BIG_ENDIAN(iv[3]) + 1); /* Compute first mask=AES_ECB(J0_real) into tag1 */ memset(&ctx, 0, sizeof(ctx)); res = stm32_cryp_init(&ctx, false, STM32_CRYP_MODE_AES_ECB, dinit->key.data, dinit->key.length, NULL, 0); if (res) return res; res = stm32_cryp_update(&ctx, true, (uint8_t *)j0, tag1, sizeof(tag1)); if (res) return res; /* Compute second mask=AES_ECB(J0_used_by_HW) into tag2 */ memset(&ctx, 0, sizeof(ctx)); j0[3] = TEE_U32_TO_BIG_ENDIAN(1); res = stm32_cryp_init(&ctx, false, STM32_CRYP_MODE_AES_ECB, dinit->key.data, dinit->key.length, NULL, 0); if (res) return res; res = stm32_cryp_update(&ctx, true, (uint8_t *)j0, tag2, sizeof(tag2)); if (res) return res; /* * Save the mask we will apply in {enc,dec}_final() to the * (wrongly) computed tag to get the expected one. */ xor_vec(c->tag_mask, tag1, tag2, sizeof(c->tag_mask)); return TEE_SUCCESS; } static void stm32_ae_ccm_generate_b0(uint8_t *b0, struct drvcrypt_authenc_init *dinit) { size_t m = dinit->tag_len; size_t l = 15 - dinit->nonce.length; size_t payload_len = dinit->payload_len; size_t i = 15; /* The tag_len should be 4, 6, 8, 10, 12, 14 or 16 */ assert(m >= 4 && m <= 16 && (m % 2) == 0); memset(b0, 0, TEE_AES_BLOCK_SIZE); /* Flags: (Adata << 6) | (M' << 3) | L' */ b0[0] = ((dinit->aad_len ? 1 : 0) << 6) | (((m - 2) / 2) << 3) | (l - 1); /* Nonce */ memcpy(b0 + 1, dinit->nonce.data, dinit->nonce.length); /* Payload length */ for (i = 15; i >= 15 - l + 1; i--, payload_len >>= 8) b0[i] = payload_len & 0xFF; } static TEE_Result stm32_ae_ccm_push_b1(struct stm32_ae_ctx *c, struct drvcrypt_authenc_init *dinit) { uint8_t b1[TEE_AES_BLOCK_SIZE] = { 0 }; size_t len = 0; if (dinit->aad_len == 0) return TEE_SUCCESS; if (dinit->aad_len < 0x100) { b1[1] = dinit->aad_len; len = 2; } else if (dinit->aad_len < 0xFF00) { b1[0] = dinit->aad_len / 0x100; b1[1] = dinit->aad_len % 0x100; len = 2; } else if (dinit->aad_len <= UINT32_MAX) { b1[0] = 0xFF; b1[1] = 0xFE; b1[2] = dinit->aad_len & GENMASK_32(7, 0); b1[3] = (dinit->aad_len & GENMASK_32(15, 8)) >> 8; b1[4] = (dinit->aad_len & GENMASK_32(23, 16)) >> 16; b1[5] = (dinit->aad_len & GENMASK_32(31, 24)) >> 24; len = 6; } else { b1[0] = 0xFF; b1[1] = 0xFF; b1[2] = dinit->aad_len & GENMASK_64(7, 0); b1[3] = (dinit->aad_len & GENMASK_64(15, 8)) >> 8; b1[4] = (dinit->aad_len & GENMASK_64(23, 16)) >> 16; b1[5] = (dinit->aad_len & GENMASK_64(31, 24)) >> 24; b1[6] = (dinit->aad_len & GENMASK_64(39, 32)) >> 32; b1[7] = (dinit->aad_len & GENMASK_64(47, 40)) >> 40; b1[8] = (dinit->aad_len & GENMASK_64(55, 48)) >> 48; b1[9] = (dinit->aad_len & GENMASK_64(63, 56)) >> 56; len = 10; } return stm32_cryp_update_assodata(&c->cryp, b1, len); } static TEE_Result stm32_ae_initialize(struct drvcrypt_authenc_init *dinit) { TEE_Result res = TEE_SUCCESS; uint32_t iv[4] = { 0 }; struct stm32_ae_ctx *c = to_stm32_ae_ctx(dinit->ctx); if (c->algo == STM32_CRYP_MODE_AES_GCM) { res = stm32_ae_gcm_generate_iv(c, iv, dinit); if (res) return res; } else if (c->algo == STM32_CRYP_MODE_AES_CCM) { stm32_ae_ccm_generate_b0((uint8_t *)iv, dinit); } res = stm32_cryp_init(&c->cryp, !dinit->encrypt, c->algo, dinit->key.data, dinit->key.length, iv, sizeof(iv)); if (res) return res; if (c->algo == STM32_CRYP_MODE_AES_CCM) return stm32_ae_ccm_push_b1(c, dinit); return TEE_SUCCESS; } static TEE_Result stm32_ae_update_aad(struct drvcrypt_authenc_update_aad *dupdate) { struct stm32_ae_ctx *c = to_stm32_ae_ctx(dupdate->ctx); return stm32_cryp_update_assodata(&c->cryp, dupdate->aad.data, dupdate->aad.length); } static TEE_Result stm32_ae_update_payload(struct drvcrypt_authenc_update_payload *dupdate) { struct stm32_ae_ctx *c = to_stm32_ae_ctx(dupdate->ctx); size_t len = MIN(dupdate->src.length, dupdate->dst.length); return stm32_cryp_update_load(&c->cryp, dupdate->src.data, dupdate->dst.data, len); } static TEE_Result stm32_ae_encdec_final(struct stm32_ae_ctx *c, uint8_t *tag, size_t tag_size) { TEE_Result res = TEE_SUCCESS; uint8_t t[MAX_TAG_SIZE] = { 0 }; res = stm32_cryp_final(&c->cryp, t, sizeof(t)); if (res) return res; xor_vec(tag, t, c->tag_mask, tag_size); return TEE_SUCCESS; } static TEE_Result stm32_ae_enc_final(struct drvcrypt_authenc_final *dfinal) { TEE_Result res = TEE_SUCCESS; struct stm32_ae_ctx *c = to_stm32_ae_ctx(dfinal->ctx); size_t len = MIN(dfinal->src.length, dfinal->dst.length); res = stm32_cryp_update_load(&c->cryp, dfinal->src.data, dfinal->dst.data, len); if (res) return res; return stm32_ae_encdec_final(c, dfinal->tag.data, dfinal->tag.length); } static TEE_Result stm32_ae_dec_final(struct drvcrypt_authenc_final *dfinal) { TEE_Result res = TEE_SUCCESS; struct stm32_ae_ctx *c = to_stm32_ae_ctx(dfinal->ctx); size_t len = MIN(dfinal->src.length, dfinal->dst.length); unsigned char tag_buf[MAX_TAG_SIZE] = { 0 }; res = stm32_cryp_update_load(&c->cryp, dfinal->src.data, dfinal->dst.data, len); if (res) return res; res = stm32_ae_encdec_final(c, tag_buf, sizeof(tag_buf)); if (res) return res; if (consttime_memcmp(tag_buf, dfinal->tag.data, dfinal->tag.length)) return TEE_ERROR_MAC_INVALID; return TEE_SUCCESS; } static void stm32_ae_final(void *ctx __unused) { } static void stm32_ae_free(void *ctx) { struct stm32_ae_ctx *c = to_stm32_ae_ctx(ctx); free(c); } static void stm32_ae_copy_state(void *dst_ctx, void *src_ctx) { struct stm32_ae_ctx *src = to_stm32_ae_ctx(src_ctx); struct stm32_ae_ctx *dst = to_stm32_ae_ctx(dst_ctx); memcpy(dst, src, sizeof(*dst)); } static TEE_Result alloc_ctx(void **ctx, enum stm32_cryp_algo_mode algo) { struct stm32_ae_ctx *c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->algo = algo; *ctx = &c->a_ctx; return TEE_SUCCESS; } /* * Allocate the SW authenc data context * * @ctx [out] Caller context variable * @algo Algorithm ID of the context */ static TEE_Result stm32_ae_allocate(void **ctx, uint32_t algo) { /* Convert TEE_ALGO id to CRYP id */ switch (algo) { case TEE_ALG_AES_CCM: return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CCM); case TEE_ALG_AES_GCM: return alloc_ctx(ctx, STM32_CRYP_MODE_AES_GCM); default: return TEE_ERROR_NOT_IMPLEMENTED; } } /* * Registration of the Authenc Driver */ static struct drvcrypt_authenc driver_authenc = { .alloc_ctx = stm32_ae_allocate, .free_ctx = stm32_ae_free, .init = stm32_ae_initialize, .update_aad = stm32_ae_update_aad, .update_payload = stm32_ae_update_payload, .enc_final = stm32_ae_enc_final, .dec_final = stm32_ae_dec_final, .final = stm32_ae_final, .copy_state = stm32_ae_copy_state, }; TEE_Result stm32_register_authenc(void) { return drvcrypt_register_authenc(&driver_authenc); } optee_os-4.3.0/core/drivers/crypto/stm32/cipher.c000066400000000000000000000231371464416617300216710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include "common.h" #include "stm32_cryp.h" #include "stm32_saes.h" #define DES3_KEY_SIZE 24 struct cryp_ctx { struct stm32_cryp_context ctx; enum stm32_cryp_algo_mode algo; }; struct saes_ctx { struct stm32_saes_context ctx; enum stm32_saes_chaining_mode algo; /* Fallback to software implementation on 192bit AES key */ bool use_fallback; struct crypto_cipher_ctx *fallback_ctx; }; /* * Internal peripheral context * SAES and CRYP are registered under the same ID in the crypto framework. * Therefore, only one of them can be registered. */ union ip_ctx { struct saes_ctx saes; struct cryp_ctx cryp; }; /* Internal Peripheral cipher ops*/ struct ip_cipher_ops { TEE_Result (*init)(union ip_ctx *ctx, bool is_decrypt, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len); TEE_Result (*update)(union ip_ctx *ctx, bool last_block, uint8_t *src, uint8_t *dst, size_t len); void (*final)(union ip_ctx *ctx); void (*copy_state)(union ip_ctx *dst_ctx, union ip_ctx *src_ctx); }; struct stm32_cipher_ctx { struct crypto_cipher_ctx c_ctx; union ip_ctx ip_ctx; const struct ip_cipher_ops *ops; }; static TEE_Result cryp_init(union ip_ctx *ip_ctx, bool is_decrypt, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len) { uint8_t temp_key[DES3_KEY_SIZE] = { }; if (!IS_ENABLED(CFG_STM32_CRYP)) return TEE_ERROR_NOT_IMPLEMENTED; if (key_len == 16 && (ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_ECB || ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_CBC)) { /* Manage DES2: i.e. K=K1.K2.K1 */ memcpy(temp_key, key, key_len); memcpy(temp_key + key_len, key, key_len / 2); key_len = DES3_KEY_SIZE; key = temp_key; } return stm32_cryp_init(&ip_ctx->cryp.ctx, is_decrypt, ip_ctx->cryp.algo, key, key_len, iv, iv_len); } static TEE_Result cryp_update(union ip_ctx *ip_ctx, bool last_block, uint8_t *src, uint8_t *dst, size_t len) { if (!IS_ENABLED(CFG_STM32_CRYP)) return TEE_ERROR_NOT_IMPLEMENTED; return stm32_cryp_update(&ip_ctx->cryp.ctx, last_block, src, dst, len); } static void cryp_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx) { memcpy(&dst_ip_ctx->cryp, &src_ip_ctx->cryp, sizeof(dst_ip_ctx->cryp)); } static const struct ip_cipher_ops cryp_ops = { .init = cryp_init, .update = cryp_update, .copy_state = cryp_copy_state, }; static TEE_Result saes_init(union ip_ctx *ip_ctx, bool is_decrypt, const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len) { enum stm32_saes_key_selection key_sel = STM32_SAES_KEY_SOFT; if (!IS_ENABLED(CFG_STM32_SAES)) return TEE_ERROR_NOT_IMPLEMENTED; if (key_len == AES_KEYSIZE_192) { struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx; TEE_OperationMode mode = TEE_MODE_ILLEGAL_VALUE; TEE_Result res = TEE_ERROR_GENERIC; if (!IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) { EMSG("STM32 SAES does not support 192bit keys"); return TEE_ERROR_NOT_IMPLEMENTED; } if (is_decrypt) mode = TEE_MODE_DECRYPT; else mode = TEE_MODE_ENCRYPT; res = ctx->ops->init(ctx, mode, key, key_len, NULL, 0, iv, iv_len); if (res) return res; ip_ctx->saes.use_fallback = true; return TEE_SUCCESS; } ip_ctx->saes.use_fallback = false; return stm32_saes_init(&ip_ctx->saes.ctx, is_decrypt, ip_ctx->saes.algo, key_sel, key, key_len, iv, iv_len); } static TEE_Result saes_update(union ip_ctx *ip_ctx, bool last_block, uint8_t *src, uint8_t *dst, size_t len) { if (!IS_ENABLED(CFG_STM32_SAES)) return TEE_ERROR_NOT_IMPLEMENTED; if (ip_ctx->saes.use_fallback) { struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx; assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)); return ctx->ops->update(ctx, last_block, src, len, dst); } return stm32_saes_update(&ip_ctx->saes.ctx, last_block, src, dst, len); } static void saes_final(union ip_ctx *ip_ctx) { struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx; if (ip_ctx->saes.use_fallback) { assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)); ctx->ops->final(ctx); } } static void saes_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx) { struct saes_ctx *src_ctx = &src_ip_ctx->saes; struct crypto_cipher_ctx *fb_ctx = src_ctx->fallback_ctx; memcpy(&dst_ip_ctx->saes.ctx, &src_ctx->ctx, sizeof(src_ctx->ctx)); dst_ip_ctx->saes.algo = src_ctx->algo; dst_ip_ctx->saes.use_fallback = src_ctx->use_fallback; if (src_ctx->use_fallback) { assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)); fb_ctx->ops->copy_state(dst_ip_ctx->saes.fallback_ctx, fb_ctx); } } static const struct ip_cipher_ops saes_ops = { .init = saes_init, .update = saes_update, .final = saes_final, .copy_state = saes_copy_state, }; static struct stm32_cipher_ctx * to_stm32_cipher_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx); return container_of(ctx, struct stm32_cipher_ctx, c_ctx); } static TEE_Result stm32_cipher_initialize(struct drvcrypt_cipher_init *dinit) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dinit->ctx); return c->ops->init(&c->ip_ctx, !dinit->encrypt, dinit->key1.data, dinit->key1.length, dinit->iv.data, dinit->iv.length); } static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dupdate->ctx); size_t len = MIN(dupdate->src.length, dupdate->dst.length); return c->ops->update(&c->ip_ctx, dupdate->last, dupdate->src.data, dupdate->dst.data, len); } static void stm32_cipher_final(void *ctx __unused) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); if (c->ops->final) c->ops->final(&c->ip_ctx); } static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx) { struct stm32_cipher_ctx *src_c = to_stm32_cipher_ctx(src_ctx); struct stm32_cipher_ctx *dst_c = to_stm32_cipher_ctx(dst_ctx); src_c->ops->copy_state(&dst_c->ip_ctx, &src_c->ip_ctx); } static TEE_Result alloc_cryp_ctx(void **ctx, enum stm32_cryp_algo_mode algo) { struct stm32_cipher_ctx *c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; FMSG("Using CRYP %d", algo); c->ip_ctx.cryp.algo = algo; c->ops = &cryp_ops; *ctx = &c->c_ctx; return TEE_SUCCESS; } static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo) { /* * Convert TEE_ALGO id to internal id */ switch (algo) { case TEE_ALG_DES_ECB_NOPAD: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_ECB); case TEE_ALG_DES_CBC_NOPAD: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_CBC); case TEE_ALG_DES3_ECB_NOPAD: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_ECB); case TEE_ALG_DES3_CBC_NOPAD: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_CBC); case TEE_ALG_AES_ECB_NOPAD: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_ECB); case TEE_ALG_AES_CBC_NOPAD: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CBC); case TEE_ALG_AES_CTR: return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CTR); default: return TEE_ERROR_NOT_IMPLEMENTED; } } static void stm32_cryp_cipher_free(void *ctx) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); free(c); } static TEE_Result stm32_saes_cipher_allocate(void **ctx, uint32_t algo) { enum stm32_saes_chaining_mode saes_algo = STM32_SAES_MODE_ECB; struct crypto_cipher_ctx *fallback_ctx = NULL; struct stm32_cipher_ctx *saes_ctx = NULL; TEE_Result res = TEE_SUCCESS; switch (algo) { case TEE_ALG_AES_ECB_NOPAD: saes_algo = STM32_SAES_MODE_ECB; if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) res = crypto_aes_ecb_alloc_ctx(&fallback_ctx); break; case TEE_ALG_AES_CBC_NOPAD: saes_algo = STM32_SAES_MODE_CBC; if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) res = crypto_aes_cbc_alloc_ctx(&fallback_ctx); break; case TEE_ALG_AES_CTR: saes_algo = STM32_SAES_MODE_CTR; if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) res = crypto_aes_ctr_alloc_ctx(&fallback_ctx); break; default: return TEE_ERROR_NOT_IMPLEMENTED; } if (res) return res; saes_ctx = calloc(1, sizeof(*saes_ctx)); if (!saes_ctx) { if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) fallback_ctx->ops->free_ctx(fallback_ctx); return TEE_ERROR_OUT_OF_MEMORY; } FMSG("Using SAES %d", saes_algo); saes_ctx->ip_ctx.saes.algo = saes_algo; saes_ctx->ops = &saes_ops; saes_ctx->ip_ctx.saes.fallback_ctx = fallback_ctx; *ctx = &saes_ctx->c_ctx; return TEE_SUCCESS; } static void stm32_saes_cipher_free(void *ctx) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) { struct crypto_cipher_ctx *fb_ctx = c->ip_ctx.saes.fallback_ctx; fb_ctx->ops->free_ctx(fb_ctx); } free(c); } static struct drvcrypt_cipher driver_cipher_cryp = { .alloc_ctx = stm32_cryp_cipher_allocate, .free_ctx = stm32_cryp_cipher_free, .init = stm32_cipher_initialize, .update = stm32_cipher_update, .final = stm32_cipher_final, .copy_state = stm32_cipher_copy_state, }; static struct drvcrypt_cipher driver_cipher_saes = { .alloc_ctx = stm32_saes_cipher_allocate, .free_ctx = stm32_saes_cipher_free, .init = stm32_cipher_initialize, .update = stm32_cipher_update, .final = stm32_cipher_final, .copy_state = stm32_cipher_copy_state, }; TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id cipher_ip) { if (cipher_ip == SAES_IP) return drvcrypt_register_cipher(&driver_cipher_saes); else if (cipher_ip == CRYP_IP) return drvcrypt_register_cipher(&driver_cipher_cryp); else return TEE_ERROR_BAD_PARAMETERS; } optee_os-4.3.0/core/drivers/crypto/stm32/common.h000066400000000000000000000021001464416617300216770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #ifndef __DRIVERS_CRYPTO_STM32_COMMON_H #define __DRIVERS_CRYPTO_STM32_COMMON_H #include enum stm32_cipher_ip_id { CRYP_IP, SAES_IP, }; /* * Crypto algorithm common macro used in stm32_saes and stm32_cryp driver */ #define INT8_BIT U(8) #define AES_BLOCK_SIZE_BIT U(128) #define AES_BLOCK_SIZE (AES_BLOCK_SIZE_BIT / INT8_BIT) #define AES_BLOCK_NB_U32 (AES_BLOCK_SIZE / sizeof(uint32_t)) #define DES_BLOCK_SIZE_BIT U(64) #define DES_BLOCK_SIZE (DES_BLOCK_SIZE_BIT / INT8_BIT) #define DES_BLOCK_NB_U32 (DES_BLOCK_SIZE / sizeof(uint32_t)) #define MAX_BLOCK_SIZE_BIT AES_BLOCK_SIZE_BIT #define MAX_BLOCK_SIZE AES_BLOCK_SIZE #define MAX_BLOCK_NB_U32 AES_BLOCK_NB_U32 #define AES_KEYSIZE_128 U(16) #define AES_KEYSIZE_192 U(24) #define AES_KEYSIZE_256 U(32) #define AES_IVSIZE U(16) TEE_Result stm32_register_authenc(void); TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id); #endif /* __DRIVERS_CRYPTO_STM32_COMMON_H */ optee_os-4.3.0/core/drivers/crypto/stm32/crypto.mk000066400000000000000000000011521464416617300221150ustar00rootroot00000000000000# CFG_STM32_CRYPTO_DRIVER, when enabled, embeds # STM32 HW cryptographic support and OP-TEE Crypto Driver. # CFG_STM32_CRYP, when enabled, embeds # STM32 CRYP module support, # CIPHER Crypto Driver, # AUTHENC Crypto Driver. ifeq ($(CFG_STM32_CRYPTO_DRIVER),y) $(call force,CFG_CRYPTO_DRIVER,y) CFG_CRYPTO_DRIVER_DEBUG ?= 0 ifeq ($(call cfg-one-enabled, CFG_STM32_CRYP CFG_STM32_SAES),y) $(call force,CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_STM32_CRYP) endif ifeq ($(CFG_STM32_CRYP),y) $(call force,CFG_CRYPTO_DRV_AUTHENC,y,Mandated by CFG_STM32_CRYP) endif endif # CFG_STM32_CRYPTO_DRIVER optee_os-4.3.0/core/drivers/crypto/stm32/stm32_cryp.c000066400000000000000000001015711464416617300224230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "stm32_cryp.h" #include "common.h" /* CRYP control register */ #define _CRYP_CR 0x0U /* CRYP status register */ #define _CRYP_SR 0x04U /* CRYP data input register */ #define _CRYP_DIN 0x08U /* CRYP data output register */ #define _CRYP_DOUT 0x0CU /* CRYP DMA control register */ #define _CRYP_DMACR 0x10U /* CRYP interrupt mask set/clear register */ #define _CRYP_IMSCR 0x14U /* CRYP raw interrupt status register */ #define _CRYP_RISR 0x18U /* CRYP masked interrupt status register */ #define _CRYP_MISR 0x1CU /* CRYP key registers */ #define _CRYP_K0LR 0x20U #define _CRYP_K0RR 0x24U #define _CRYP_K1LR 0x28U #define _CRYP_K1RR 0x2CU #define _CRYP_K2LR 0x30U #define _CRYP_K2RR 0x34U #define _CRYP_K3LR 0x38U #define _CRYP_K3RR 0x3CU /* CRYP initialization vector registers */ #define _CRYP_IV0LR 0x40U #define _CRYP_IV0RR 0x44U #define _CRYP_IV1LR 0x48U #define _CRYP_IV1RR 0x4CU /* CRYP context swap GCM-CCM registers */ #define _CRYP_CSGCMCCM0R 0x50U #define _CRYP_CSGCMCCM1R 0x54U #define _CRYP_CSGCMCCM2R 0x58U #define _CRYP_CSGCMCCM3R 0x5CU #define _CRYP_CSGCMCCM4R 0x60U #define _CRYP_CSGCMCCM5R 0x64U #define _CRYP_CSGCMCCM6R 0x68U #define _CRYP_CSGCMCCM7R 0x6CU /* CRYP context swap GCM registers */ #define _CRYP_CSGCM0R 0x70U #define _CRYP_CSGCM1R 0x74U #define _CRYP_CSGCM2R 0x78U #define _CRYP_CSGCM3R 0x7CU #define _CRYP_CSGCM4R 0x80U #define _CRYP_CSGCM5R 0x84U #define _CRYP_CSGCM6R 0x88U #define _CRYP_CSGCM7R 0x8CU /* CRYP hardware configuration register */ #define _CRYP_HWCFGR 0x3F0U /* CRYP HW version register */ #define _CRYP_VERR 0x3F4U /* CRYP identification */ #define _CRYP_IPIDR 0x3F8U /* CRYP HW magic ID */ #define _CRYP_MID 0x3FCU #define CRYP_TIMEOUT_US 1000000U #define TIMEOUT_US_1MS 1000U #define CRYP_RESET_DELAY_US U(2) /* CRYP control register fields */ #define _CRYP_CR_RESET_VALUE 0x0U #define _CRYP_CR_NPBLB_MSK GENMASK_32(23, 20) #define _CRYP_CR_NPBLB_OFF 20U #define _CRYP_CR_GCM_CCMPH_MSK GENMASK_32(17, 16) #define _CRYP_CR_GCM_CCMPH_OFF 16U #define _CRYP_CR_GCM_CCMPH_INIT 0U #define _CRYP_CR_GCM_CCMPH_HEADER 1U #define _CRYP_CR_GCM_CCMPH_PAYLOAD 2U #define _CRYP_CR_GCM_CCMPH_FINAL 3U #define _CRYP_CR_CRYPEN BIT(15) #define _CRYP_CR_FFLUSH BIT(14) #define _CRYP_CR_KEYSIZE_MSK GENMASK_32(9, 8) #define _CRYP_CR_KEYSIZE_OFF 8U #define _CRYP_CR_KSIZE_128 0U #define _CRYP_CR_KSIZE_192 1U #define _CRYP_CR_KSIZE_256 2U #define _CRYP_CR_DATATYPE_MSK GENMASK_32(7, 6) #define _CRYP_CR_DATATYPE_OFF 6U #define _CRYP_CR_DATATYPE_NONE 0U #define _CRYP_CR_DATATYPE_HALF_WORD 1U #define _CRYP_CR_DATATYPE_BYTE 2U #define _CRYP_CR_DATATYPE_BIT 3U #define _CRYP_CR_ALGOMODE_MSK (BIT(19) | GENMASK_32(5, 3)) #define _CRYP_CR_ALGOMODE_OFF 3U #define _CRYP_CR_ALGOMODE_TDES_ECB 0x0U #define _CRYP_CR_ALGOMODE_TDES_CBC 0x1U #define _CRYP_CR_ALGOMODE_DES_ECB 0x2U #define _CRYP_CR_ALGOMODE_DES_CBC 0x3U #define _CRYP_CR_ALGOMODE_AES_ECB 0x4U #define _CRYP_CR_ALGOMODE_AES_CBC 0x5U #define _CRYP_CR_ALGOMODE_AES_CTR 0x6U #define _CRYP_CR_ALGOMODE_AES 0x7U #define _CRYP_CR_ALGOMODE_AES_GCM BIT(16) #define _CRYP_CR_ALGOMODE_AES_CCM (BIT(16) | BIT(0)) #define _CRYP_CR_ALGODIR BIT(2) #define _CRYP_CR_ALGODIR_ENC 0U #define _CRYP_CR_ALGODIR_DEC BIT(2) /* CRYP status register fields */ #define _CRYP_SR_BUSY BIT(4) #define _CRYP_SR_OFFU BIT(3) #define _CRYP_SR_OFNE BIT(2) #define _CRYP_SR_IFNF BIT(1) #define _CRYP_SR_IFEM BIT(0) /* CRYP DMA control register fields */ #define _CRYP_DMACR_DOEN BIT(1) #define _CRYP_DMACR_DIEN BIT(0) /* CRYP interrupt fields */ #define _CRYP_I_OUT BIT(1) #define _CRYP_I_IN BIT(0) /* CRYP hardware configuration register fields */ #define _CRYP_HWCFGR_CFG1_MSK GENMASK_32(3, 0) #define _CRYP_HWCFGR_CFG1_OFF 0U #define _CRYP_HWCFGR_CFG2_MSK GENMASK_32(7, 4) #define _CRYP_HWCFGR_CFG2_OFF 4U #define _CRYP_HWCFGR_CFG3_MSK GENMASK_32(11, 8) #define _CRYP_HWCFGR_CFG3_OFF 8U #define _CRYP_HWCFGR_CFG4_MSK GENMASK_32(15, 12) #define _CRYP_HWCFGR_CFG4_OFF 12U /* CRYP HW version register */ #define _CRYP_VERR_MSK GENMASK_32(7, 0) #define _CRYP_VERR_OFF 0U /* * Macro to manage bit manipulation when we work on a local variable * before writing only once to the hardware register. */ #define CLRBITS(v, bits) ((v) &= ~(bits)) #define SETBITS(v, bits) ((v) |= (bits)) #define IS_ALGOMODE(cr, mod) \ (((cr) & _CRYP_CR_ALGOMODE_MSK) == (_CRYP_CR_ALGOMODE_##mod << \ _CRYP_CR_ALGOMODE_OFF)) #define SET_ALGOMODE(mod, cr) \ clrsetbits(&(cr), _CRYP_CR_ALGOMODE_MSK, (_CRYP_CR_ALGOMODE_##mod << \ _CRYP_CR_ALGOMODE_OFF)) #define GET_ALGOMODE(cr) \ (((cr) & _CRYP_CR_ALGOMODE_MSK) >> _CRYP_CR_ALGOMODE_OFF) static struct stm32_cryp_platdata cryp_pdata; static struct mutex cryp_lock = MUTEX_INITIALIZER; static void clrsetbits(uint32_t *v, uint32_t mask, uint32_t bits) { *v = (*v & ~mask) | bits; } static bool algo_mode_needs_iv(uint32_t cr) { return !IS_ALGOMODE(cr, TDES_ECB) && !IS_ALGOMODE(cr, DES_ECB) && !IS_ALGOMODE(cr, AES_ECB); } static bool algo_mode_is_ecb_cbc(uint32_t cr) { return GET_ALGOMODE(cr) < _CRYP_CR_ALGOMODE_AES_CTR; } static bool algo_mode_is_aes(uint32_t cr) { return ((cr & _CRYP_CR_ALGOMODE_MSK) >> _CRYP_CR_ALGOMODE_OFF) >= _CRYP_CR_ALGOMODE_AES_ECB; } static bool is_decrypt(uint32_t cr) { return (cr & _CRYP_CR_ALGODIR) == _CRYP_CR_ALGODIR_DEC; } static bool is_encrypt(uint32_t cr) { return !is_decrypt(cr); } static bool does_need_npblb(uint32_t cr) { return (IS_ALGOMODE(cr, AES_GCM) && is_encrypt(cr)) || (IS_ALGOMODE(cr, AES_CCM) && is_decrypt(cr)); } static TEE_Result wait_sr_bits(vaddr_t base, uint32_t bits) { uint64_t timeout_ref = timeout_init_us(CRYP_TIMEOUT_US); while ((io_read32(base + _CRYP_SR) & bits) != bits) if (timeout_elapsed(timeout_ref)) break; if ((io_read32(base + _CRYP_SR) & bits) != bits) return TEE_ERROR_BUSY; return TEE_SUCCESS; } static TEE_Result wait_end_busy(vaddr_t base) { uint64_t timeout_ref = timeout_init_us(CRYP_TIMEOUT_US); while (io_read32(base + _CRYP_SR) & _CRYP_SR_BUSY) if (timeout_elapsed(timeout_ref)) break; if (io_read32(base + _CRYP_SR) & _CRYP_SR_BUSY) return TEE_ERROR_BUSY; return TEE_SUCCESS; } static TEE_Result wait_end_enable(vaddr_t base) { uint64_t timeout_ref = timeout_init_us(CRYP_TIMEOUT_US); while (io_read32(base + _CRYP_CR) & _CRYP_CR_CRYPEN) if (timeout_elapsed(timeout_ref)) break; if (io_read32(base + _CRYP_CR) & _CRYP_CR_CRYPEN) return TEE_ERROR_BUSY; return TEE_SUCCESS; } static TEE_Result __must_check write_align_block(struct stm32_cryp_context *ctx, uint32_t *data) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; res = wait_sr_bits(ctx->base, _CRYP_SR_IFNF); if (res) return res; for (i = 0; i < ctx->block_u32; i++) { /* No need to htobe() as we configure the HW to swap bytes */ io_write32(ctx->base + _CRYP_DIN, data[i]); } return TEE_SUCCESS; } static TEE_Result __must_check write_block(struct stm32_cryp_context *ctx, uint8_t *data) { if (!IS_ALIGNED_WITH_TYPE(data, uint32_t)) { uint32_t data_u32[MAX_BLOCK_NB_U32] = { 0 }; memcpy(data_u32, data, ctx->block_u32 * sizeof(uint32_t)); return write_align_block(ctx, data_u32); } return write_align_block(ctx, (void *)data); } static TEE_Result __must_check read_align_block(struct stm32_cryp_context *ctx, uint32_t *data) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; res = wait_sr_bits(ctx->base, _CRYP_SR_OFNE); if (res) return res; for (i = 0; i < ctx->block_u32; i++) { /* No need to htobe() as we configure the HW to swap bytes */ data[i] = io_read32(ctx->base + _CRYP_DOUT); } return TEE_SUCCESS; } static TEE_Result __must_check read_block(struct stm32_cryp_context *ctx, uint8_t *data) { if (!IS_ALIGNED_WITH_TYPE(data, uint32_t)) { TEE_Result res = TEE_SUCCESS; uint32_t data_u32[MAX_BLOCK_NB_U32] = { 0 }; res = read_align_block(ctx, data_u32); if (res) return res; memcpy(data, data_u32, ctx->block_u32 * sizeof(uint32_t)); return TEE_SUCCESS; } return read_align_block(ctx, (void *)data); } static TEE_Result stm32_cryp_reset(void) { TEE_Result res = TEE_ERROR_GENERIC; if (!cryp_pdata.reset) return TEE_SUCCESS; res = rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS); if (res) return res; udelay(CRYP_RESET_DELAY_US); return rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS); } static void cryp_end(struct stm32_cryp_context *ctx, TEE_Result prev_error) { if (prev_error && stm32_cryp_reset()) panic(); /* Disable the CRYP peripheral */ io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); } static void cryp_write_iv(struct stm32_cryp_context *ctx) { if (algo_mode_needs_iv(ctx->cr)) { unsigned int i = 0; /* Restore the _CRYP_IVRx */ for (i = 0; i < ctx->block_u32; i++) io_write32(ctx->base + _CRYP_IV0LR + i * sizeof(uint32_t), ctx->iv[i]); } } static void cryp_save_suspend(struct stm32_cryp_context *ctx) { unsigned int i = 0; if (IS_ALGOMODE(ctx->cr, AES_GCM) || IS_ALGOMODE(ctx->cr, AES_CCM)) for (i = 0; i < ARRAY_SIZE(ctx->pm_gcmccm); i++) ctx->pm_gcmccm[i] = io_read32(ctx->base + _CRYP_CSGCMCCM0R + i * sizeof(uint32_t)); if (IS_ALGOMODE(ctx->cr, AES_GCM)) for (i = 0; i < ARRAY_SIZE(ctx->pm_gcm); i++) ctx->pm_gcm[i] = io_read32(ctx->base + _CRYP_CSGCM0R + i * sizeof(uint32_t)); } static void cryp_restore_suspend(struct stm32_cryp_context *ctx) { unsigned int i = 0; if (IS_ALGOMODE(ctx->cr, AES_GCM) || IS_ALGOMODE(ctx->cr, AES_CCM)) for (i = 0; i < ARRAY_SIZE(ctx->pm_gcmccm); i++) io_write32(ctx->base + _CRYP_CSGCMCCM0R + i * sizeof(uint32_t), ctx->pm_gcmccm[i]); if (IS_ALGOMODE(ctx->cr, AES_GCM)) for (i = 0; i < ARRAY_SIZE(ctx->pm_gcm); i++) io_write32(ctx->base + _CRYP_CSGCM0R + i * sizeof(uint32_t), ctx->pm_gcm[i]); } static void cryp_write_key(struct stm32_cryp_context *ctx) { vaddr_t reg = 0; int i = 0; uint32_t algo = GET_ALGOMODE(ctx->cr); if (algo == _CRYP_CR_ALGOMODE_DES_ECB || algo == _CRYP_CR_ALGOMODE_DES_CBC) reg = ctx->base + _CRYP_K1RR; else reg = ctx->base + _CRYP_K3RR; for (i = ctx->key_size / sizeof(uint32_t) - 1; i >= 0; i--, reg -= sizeof(uint32_t)) io_write32(reg, ctx->key[i]); } static TEE_Result cryp_prepare_key(struct stm32_cryp_context *ctx) { TEE_Result res = TEE_SUCCESS; /* * For AES ECB/CBC decryption, key preparation mode must be selected * to populate the key. */ if (is_decrypt(ctx->cr) && (IS_ALGOMODE(ctx->cr, AES_ECB) || IS_ALGOMODE(ctx->cr, AES_CBC))) { /* Select Algomode "prepare key" */ io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_ALGOMODE_MSK, _CRYP_CR_ALGOMODE_AES << _CRYP_CR_ALGOMODE_OFF); cryp_write_key(ctx); /* Enable CRYP */ io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); res = wait_end_busy(ctx->base); if (res) return res; /* Reset 'real' algomode */ io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_ALGOMODE_MSK, ctx->cr & _CRYP_CR_ALGOMODE_MSK); } else { cryp_write_key(ctx); } return TEE_SUCCESS; } static TEE_Result save_context(struct stm32_cryp_context *ctx) { /* Device should not be in a processing phase */ if (io_read32(ctx->base + _CRYP_SR) & _CRYP_SR_BUSY) return TEE_ERROR_BAD_STATE; /* Disable the CRYP peripheral */ io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); /* Save CR */ ctx->cr = io_read32(ctx->base + _CRYP_CR); cryp_save_suspend(ctx); /* If algo mode needs to save current IV */ if (algo_mode_needs_iv(ctx->cr)) { unsigned int i = 0; /* Save IV */ for (i = 0; i < ctx->block_u32; i++) ctx->iv[i] = io_read32(ctx->base + _CRYP_IV0LR + i * sizeof(uint32_t)); } return TEE_SUCCESS; } /* To resume the processing of a message */ static TEE_Result restore_context(struct stm32_cryp_context *ctx) { TEE_Result res = TEE_SUCCESS; /* IP should be disabled */ if (io_read32(ctx->base + _CRYP_CR) & _CRYP_CR_CRYPEN) { DMSG("Device is still enabled"); return TEE_ERROR_BAD_STATE; } /* Restore the _CRYP_CR */ io_write32(ctx->base + _CRYP_CR, ctx->cr); /* Write key and, in case of AES_CBC or AES_ECB decrypt, prepare it */ res = cryp_prepare_key(ctx); if (res) return res; cryp_restore_suspend(ctx); cryp_write_iv(ctx); /* Flush internal fifo */ io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_FFLUSH); /* Enable the CRYP peripheral */ io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); return TEE_SUCCESS; } /* * Translate a byte index in an array of BE uint32_t into the index of same * byte in the corresponding LE uint32_t array. */ static size_t be_index(size_t index) { return (index & ~0x3) + 3 - (index & 0x3); } static TEE_Result ccm_first_context(struct stm32_cryp_context *ctx) { TEE_Result res = TEE_SUCCESS; uint32_t b0[AES_BLOCK_NB_U32] = { 0 }; uint8_t *iv = (uint8_t *)ctx->iv; size_t l = 0; size_t i = 15; /* IP should be disabled */ if (io_read32(ctx->base + _CRYP_CR) & _CRYP_CR_CRYPEN) return TEE_ERROR_BAD_STATE; /* Write the _CRYP_CR */ io_write32(ctx->base + _CRYP_CR, ctx->cr); /* Write key */ res = cryp_prepare_key(ctx); if (res) return res; /* Save full IV that will be b0 */ memcpy(b0, iv, sizeof(b0)); /* * Update IV to become CTR0/1 before setting it. * IV is saved as LE uint32_t[4] as expected by hardware, * but CCM RFC defines bytes to update in a BE array. */ /* Set flag bits to 0 (5 higher bits), keep 3 low bits */ iv[be_index(0)] &= 0x7; /* Get size of length field (can be from 2 to 8) */ l = iv[be_index(0)] + 1; /* Set Q to 0 */ for (i = 15; i >= 15 - l + 1; i--) iv[be_index(i)] = 0; /* Save CTR0 */ memcpy(ctx->ctr0_ccm, iv, sizeof(b0)); /* Increment Q */ iv[be_index(15)] |= 0x1; cryp_write_iv(ctx); /* Enable the CRYP peripheral */ io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); res = write_align_block(ctx, b0); return res; } static TEE_Result do_from_init_to_phase(struct stm32_cryp_context *ctx, uint32_t new_phase) { TEE_Result res = TEE_SUCCESS; /* * We didn't run the init phase yet * CCM need a specific restore_context phase for the init phase */ if (IS_ALGOMODE(ctx->cr, AES_CCM)) res = ccm_first_context(ctx); else res = restore_context(ctx); if (res) return res; res = wait_end_enable(ctx->base); if (res) return res; /* Move to 'new_phase' */ io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_GCM_CCMPH_MSK, new_phase << _CRYP_CR_GCM_CCMPH_OFF); /* Enable the CRYP peripheral (init disabled it) */ io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); return TEE_SUCCESS; } static TEE_Result do_from_header_to_phase(struct stm32_cryp_context *ctx, uint32_t new_phase) { TEE_Result res = TEE_SUCCESS; res = restore_context(ctx); if (res) return res; if (ctx->extra_size) { /* Manage unaligned header data before moving to next phase */ memset((uint8_t *)ctx->extra + ctx->extra_size, 0, ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); res = write_align_block(ctx, ctx->extra); if (res) return res; ctx->assoc_len += (ctx->extra_size) * INT8_BIT; ctx->extra_size = 0; } /* Move to 'new_phase' */ io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_GCM_CCMPH_MSK, new_phase << _CRYP_CR_GCM_CCMPH_OFF); return TEE_SUCCESS; } /** * @brief Start a AES computation. * @param ctx: CRYP process context * @param is_dec: true if decryption, false if encryption * @param algo: define the algo mode * @param key: pointer to key * @param key_size: key size * @param iv: pointer to initialization vector (unused if algo is ECB) * @param iv_size: iv size * @note this function doesn't access to hardware but stores in ctx the values * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_cryp_init(struct stm32_cryp_context *ctx, bool is_dec, enum stm32_cryp_algo_mode algo, const void *key, size_t key_size, const void *iv, size_t iv_size) { unsigned int i = 0; const uint32_t *iv_u32 = NULL; uint32_t local_iv[4] = { 0 }; const uint32_t *key_u32 = NULL; uint32_t local_key[8] = { 0 }; ctx->assoc_len = 0; ctx->load_len = 0; ctx->extra_size = 0; ctx->lock = &cryp_lock; ctx->base = io_pa_or_va(&cryp_pdata.base, 1); ctx->cr = _CRYP_CR_RESET_VALUE; /* We want buffer to be u32 aligned */ if (IS_ALIGNED_WITH_TYPE(key, uint32_t)) { key_u32 = key; } else { memcpy(local_key, key, key_size); key_u32 = local_key; } if (IS_ALIGNED_WITH_TYPE(iv, uint32_t)) { iv_u32 = iv; } else { memcpy(local_iv, iv, iv_size); iv_u32 = local_iv; } if (is_dec) SETBITS(ctx->cr, _CRYP_CR_ALGODIR); else CLRBITS(ctx->cr, _CRYP_CR_ALGODIR); /* Save algo mode */ switch (algo) { case STM32_CRYP_MODE_TDES_ECB: SET_ALGOMODE(TDES_ECB, ctx->cr); break; case STM32_CRYP_MODE_TDES_CBC: SET_ALGOMODE(TDES_CBC, ctx->cr); break; case STM32_CRYP_MODE_DES_ECB: SET_ALGOMODE(DES_ECB, ctx->cr); break; case STM32_CRYP_MODE_DES_CBC: SET_ALGOMODE(DES_CBC, ctx->cr); break; case STM32_CRYP_MODE_AES_ECB: SET_ALGOMODE(AES_ECB, ctx->cr); break; case STM32_CRYP_MODE_AES_CBC: SET_ALGOMODE(AES_CBC, ctx->cr); break; case STM32_CRYP_MODE_AES_CTR: SET_ALGOMODE(AES_CTR, ctx->cr); break; case STM32_CRYP_MODE_AES_GCM: SET_ALGOMODE(AES_GCM, ctx->cr); break; case STM32_CRYP_MODE_AES_CCM: SET_ALGOMODE(AES_CCM, ctx->cr); break; default: return TEE_ERROR_BAD_PARAMETERS; } /* * We will use HW Byte swap (_CRYP_CR_DATATYPE_BYTE) for data. * So we won't need to * TEE_U32_TO_BIG_ENDIAN(data) before write to DIN register * nor * TEE_U32_FROM_BIG_ENDIAN after reading from DOUT register. */ clrsetbits(&ctx->cr, _CRYP_CR_DATATYPE_MSK, _CRYP_CR_DATATYPE_BYTE << _CRYP_CR_DATATYPE_OFF); /* * Configure keysize for AES algorithms * And save block size */ if (algo_mode_is_aes(ctx->cr)) { switch (key_size) { case AES_KEYSIZE_128: clrsetbits(&ctx->cr, _CRYP_CR_KEYSIZE_MSK, _CRYP_CR_KSIZE_128 << _CRYP_CR_KEYSIZE_OFF); break; case AES_KEYSIZE_192: clrsetbits(&ctx->cr, _CRYP_CR_KEYSIZE_MSK, _CRYP_CR_KSIZE_192 << _CRYP_CR_KEYSIZE_OFF); break; case AES_KEYSIZE_256: clrsetbits(&ctx->cr, _CRYP_CR_KEYSIZE_MSK, _CRYP_CR_KSIZE_256 << _CRYP_CR_KEYSIZE_OFF); break; default: return TEE_ERROR_BAD_PARAMETERS; } /* And set block size */ ctx->block_u32 = AES_BLOCK_NB_U32; } else { /* And set DES/TDES block size */ ctx->block_u32 = DES_BLOCK_NB_U32; } /* Save key in HW order */ ctx->key_size = key_size; for (i = 0; i < key_size / sizeof(uint32_t); i++) ctx->key[i] = TEE_U32_TO_BIG_ENDIAN(key_u32[i]); /* Save IV */ if (algo_mode_needs_iv(ctx->cr)) { if (!iv || iv_size != ctx->block_u32 * sizeof(uint32_t)) return TEE_ERROR_BAD_PARAMETERS; /* * We save IV in the byte order expected by the * IV registers */ for (i = 0; i < ctx->block_u32; i++) ctx->iv[i] = TEE_U32_TO_BIG_ENDIAN(iv_u32[i]); } /* Reset suspend registers */ memset(ctx->pm_gcmccm, 0, sizeof(ctx->pm_gcmccm)); memset(ctx->pm_gcm, 0, sizeof(ctx->pm_gcm)); return TEE_SUCCESS; } /** * @brief Update (or start) a AES authenticate process of * associated data (CCM or GCM). * @param ctx: CRYP process context * @param data: pointer to associated data * @param data_size: data size * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_cryp_update_assodata(struct stm32_cryp_context *ctx, uint8_t *data, size_t data_size) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; uint32_t previous_phase = 0; /* If no associated data, nothing to do */ if (!data || !data_size) return TEE_SUCCESS; mutex_lock(ctx->lock); previous_phase = (ctx->cr & _CRYP_CR_GCM_CCMPH_MSK) >> _CRYP_CR_GCM_CCMPH_OFF; switch (previous_phase) { case _CRYP_CR_GCM_CCMPH_INIT: res = do_from_init_to_phase(ctx, _CRYP_CR_GCM_CCMPH_HEADER); break; case _CRYP_CR_GCM_CCMPH_HEADER: /* * Function update_assodata was already called. * We only need to restore the context. */ res = restore_context(ctx); break; default: assert(0); res = TEE_ERROR_BAD_STATE; } if (res) goto out; /* Manage if remaining data from a previous update_assodata call */ if (ctx->extra_size && (ctx->extra_size + data_size >= ctx->block_u32 * sizeof(uint32_t))) { uint32_t block[MAX_BLOCK_NB_U32] = { 0 }; memcpy(block, ctx->extra, ctx->extra_size); memcpy((uint8_t *)block + ctx->extra_size, data, ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); res = write_align_block(ctx, block); if (res) goto out; i += ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size; ctx->extra_size = 0; ctx->assoc_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; } while (data_size - i >= ctx->block_u32 * sizeof(uint32_t)) { res = write_block(ctx, data + i); if (res) goto out; /* Process next block */ i += ctx->block_u32 * sizeof(uint32_t); ctx->assoc_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; } /* * Manage last block if not a block size multiple: * Save remaining data to manage them later (potentially with new * associated data). */ if (i < data_size) { memcpy((uint8_t *)ctx->extra + ctx->extra_size, data + i, data_size - i); ctx->extra_size += data_size - i; } res = save_context(ctx); out: if (res) cryp_end(ctx, res); mutex_unlock(ctx->lock); return res; } /** * @brief Update (or start) a AES authenticate and de/encrypt with * payload data (CCM or GCM). * @param ctx: CRYP process context * @param data_in: pointer to payload * @param data_out: pointer where to save de/encrypted payload * @param data_size: payload size * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_cryp_update_load(struct stm32_cryp_context *ctx, uint8_t *data_in, uint8_t *data_out, size_t data_size) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; uint32_t previous_phase = 0; if (!data_in || !data_size) return TEE_SUCCESS; mutex_lock(ctx->lock); previous_phase = (ctx->cr & _CRYP_CR_GCM_CCMPH_MSK) >> _CRYP_CR_GCM_CCMPH_OFF; switch (previous_phase) { case _CRYP_CR_GCM_CCMPH_INIT: res = do_from_init_to_phase(ctx, _CRYP_CR_GCM_CCMPH_PAYLOAD); break; case _CRYP_CR_GCM_CCMPH_HEADER: res = do_from_header_to_phase(ctx, _CRYP_CR_GCM_CCMPH_PAYLOAD); break; case _CRYP_CR_GCM_CCMPH_PAYLOAD: /* new update_load call, we only need to restore context */ res = restore_context(ctx); break; default: assert(0); res = TEE_ERROR_BAD_STATE; } if (res) goto out; /* Manage if incomplete block from a previous update_load call */ if (ctx->extra_size && (ctx->extra_size + data_size >= ctx->block_u32 * sizeof(uint32_t))) { uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; memcpy((uint8_t *)ctx->extra + ctx->extra_size, data_in + i, ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); res = write_align_block(ctx, ctx->extra); if (res) goto out; res = read_align_block(ctx, block_out); if (res) goto out; memcpy(data_out + i, (uint8_t *)block_out + ctx->extra_size, ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); i += ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size; ctx->extra_size = 0; ctx->load_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; } while (data_size - i >= ctx->block_u32 * sizeof(uint32_t)) { res = write_block(ctx, data_in + i); if (res) goto out; res = read_block(ctx, data_out + i); if (res) goto out; /* Process next block */ i += ctx->block_u32 * sizeof(uint32_t); ctx->load_len += ctx->block_u32 * sizeof(uint32_t) * INT8_BIT; } res = save_context(ctx); if (res) goto out; /* * Manage last block if not a block size multiple * We saved context, * Complete block with 0 and send to CRYP to get {en,de}crypted data * Store data to resend as last block in final() * or to complete next update_load() to get correct tag. */ if (i < data_size) { uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; size_t prev_extra_size = ctx->extra_size; /* Re-enable the CRYP peripheral */ io_setbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); memcpy((uint8_t *)ctx->extra + ctx->extra_size, data_in + i, data_size - i); ctx->extra_size += data_size - i; memset((uint8_t *)ctx->extra + ctx->extra_size, 0, ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size); res = write_align_block(ctx, ctx->extra); if (res) goto out; res = read_align_block(ctx, block_out); if (res) goto out; memcpy(data_out + i, (uint8_t *)block_out + prev_extra_size, data_size - i); /* Disable the CRYP peripheral */ io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN); } out: if (res) cryp_end(ctx, res); mutex_unlock(ctx->lock); return res; } /** * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM). * @param ctx: CRYP process context * @param tag: pointer where to save the tag * @param data_size: tag size * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_cryp_final(struct stm32_cryp_context *ctx, uint8_t *tag, size_t tag_size) { TEE_Result res = TEE_SUCCESS; uint32_t tag_u32[4] = { 0 }; uint32_t previous_phase = 0; mutex_lock(ctx->lock); previous_phase = (ctx->cr & _CRYP_CR_GCM_CCMPH_MSK) >> _CRYP_CR_GCM_CCMPH_OFF; switch (previous_phase) { case _CRYP_CR_GCM_CCMPH_INIT: res = do_from_init_to_phase(ctx, _CRYP_CR_GCM_CCMPH_FINAL); break; case _CRYP_CR_GCM_CCMPH_HEADER: res = do_from_header_to_phase(ctx, _CRYP_CR_GCM_CCMPH_FINAL); break; case _CRYP_CR_GCM_CCMPH_PAYLOAD: res = restore_context(ctx); if (res) break; /* Manage if incomplete block from a previous update_load() */ if (ctx->extra_size) { uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; size_t sz = ctx->block_u32 * sizeof(uint32_t) - ctx->extra_size; if (does_need_npblb(ctx->cr)) { io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_NPBLB_MSK, sz << _CRYP_CR_NPBLB_OFF); } memset((uint8_t *)ctx->extra + ctx->extra_size, 0, sz); res = write_align_block(ctx, ctx->extra); if (res) break; /* Don't care {en,de}crypted data, already saved */ res = read_align_block(ctx, block_out); if (res) break; ctx->load_len += (ctx->extra_size * INT8_BIT); ctx->extra_size = 0; } /* Move to final phase */ io_clrsetbits32(ctx->base + _CRYP_CR, _CRYP_CR_GCM_CCMPH_MSK, _CRYP_CR_GCM_CCMPH_FINAL << _CRYP_CR_GCM_CCMPH_OFF); break; default: assert(0); res = TEE_ERROR_BAD_STATE; } if (res) goto out; if (IS_ALGOMODE(ctx->cr, AES_GCM)) { /* No need to htobe() as we configure the HW to swap bytes */ io_write32(ctx->base + _CRYP_DIN, 0U); io_write32(ctx->base + _CRYP_DIN, ctx->assoc_len); io_write32(ctx->base + _CRYP_DIN, 0U); io_write32(ctx->base + _CRYP_DIN, ctx->load_len); } else if (IS_ALGOMODE(ctx->cr, AES_CCM)) { /* No need to htobe() in this phase */ res = write_align_block(ctx, ctx->ctr0_ccm); if (res) goto out; } res = read_align_block(ctx, tag_u32); if (res) goto out; memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size)); out: cryp_end(ctx, res); mutex_unlock(ctx->lock); return res; } /** * @brief Update (or start) a de/encrypt process. * @param ctx: CRYP process context * @param last_block: true if last payload data block * @param data_in: pointer to payload * @param data_out: pointer where to save de/encrypted payload * @param data_size: payload size * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_cryp_update(struct stm32_cryp_context *ctx, bool last_block, uint8_t *data_in, uint8_t *data_out, size_t data_size) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; mutex_lock(ctx->lock); /* * In CBC and ECB encryption we need to manage specifically last * 2 blocks if total size in not aligned to a block size. * Currently return TEE_ERROR_NOT_IMPLEMENTED. Moreover as we need to * know last 2 blocks, if unaligned and call with less than two blocks, * return TEE_ERROR_BAD_STATE. */ if (last_block && algo_mode_is_ecb_cbc(ctx->cr) && is_encrypt(ctx->cr) && (ROUNDDOWN(data_size, ctx->block_u32 * sizeof(uint32_t)) != data_size)) { if (data_size < ctx->block_u32 * sizeof(uint32_t) * 2) { /* * If CBC, size of the last part should be at * least 2*BLOCK_SIZE */ EMSG("Unexpected last block size"); res = TEE_ERROR_BAD_STATE; goto out; } /* * Moreover the ECB/CBC specific padding for encrypt is not * yet implemented, and not used in OPTEE */ res = TEE_ERROR_NOT_IMPLEMENTED; goto out; } /* Manage remaining CTR mask from previous update call */ if (IS_ALGOMODE(ctx->cr, AES_CTR) && ctx->extra_size) { unsigned int j = 0; uint8_t *mask = (uint8_t *)ctx->extra; for (j = 0; j < ctx->extra_size && i < data_size; j++, i++) data_out[i] = data_in[i] ^ mask[j]; if (j != ctx->extra_size) { /* * We didn't consume all saved mask, * but no more data. */ /* We save remaining mask and its new size */ memmove(ctx->extra, ctx->extra + j, ctx->extra_size - j); ctx->extra_size -= j; /* * We don't need to save HW context we didn't * modify HW state. */ res = TEE_SUCCESS; goto out; } /* All extra mask consumed */ ctx->extra_size = 0; } res = restore_context(ctx); if (res) goto out; while (data_size - i >= ctx->block_u32 * sizeof(uint32_t)) { /* * We only write/read one block at a time * but CRYP use a in (and out) FIFO of 8 * uint32_t */ res = write_block(ctx, data_in + i); if (res) goto out; res = read_block(ctx, data_out + i); if (res) goto out; /* Process next block */ i += ctx->block_u32 * sizeof(uint32_t); } /* Manage last block if not a block size multiple */ if (i < data_size) { uint32_t block_in[MAX_BLOCK_NB_U32] = { 0 }; uint32_t block_out[MAX_BLOCK_NB_U32] = { 0 }; if (!IS_ALGOMODE(ctx->cr, AES_CTR)) { /* * Other algorithm than CTR can manage only multiple * of block_size. */ res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * For CTR we save the generated mask to use it at next * update call. */ memcpy(block_in, data_in + i, data_size - i); res = write_align_block(ctx, block_in); if (res) goto out; res = read_align_block(ctx, block_out); if (res) goto out; memcpy(data_out + i, block_out, data_size - i); /* Save mask for possibly next call */ ctx->extra_size = ctx->block_u32 * sizeof(uint32_t) - (data_size - i); memcpy(ctx->extra, (uint8_t *)block_out + data_size - i, ctx->extra_size); } if (!last_block) res = save_context(ctx); out: /* If last block or error, end of CRYP process */ if (last_block || res) cryp_end(ctx, res); mutex_unlock(ctx->lock); return res; } static TEE_Result stm32_cryp_pm(enum pm_op op, uint32_t pm_hint, const struct pm_callback_handle *hdl __unused) { switch (op) { case PM_OP_SUSPEND: clk_disable(cryp_pdata.clock); return TEE_SUCCESS; case PM_OP_RESUME: if (clk_enable(cryp_pdata.clock)) panic(); if (PM_HINT_IS_STATE(pm_hint, CONTEXT) && stm32_cryp_reset()) panic(); return TEE_SUCCESS; default: /* Unexpected PM operation */ assert(0); return TEE_ERROR_NOT_IMPLEMENTED; } } DECLARE_KEEP_PAGER(stm32_cryp_pm); static TEE_Result stm32_cryp_probe(const void *fdt, int node, const void *compt_data __unused) { TEE_Result res = TEE_SUCCESS; struct dt_node_info dt_cryp = { }; struct rstctrl *rstctrl = NULL; struct clk *clk = NULL; fdt_fill_device_info(fdt, &dt_cryp, node); if (dt_cryp.reg == DT_INFO_INVALID_REG || dt_cryp.reg_size == DT_INFO_INVALID_REG_SIZE) panic(); res = clk_dt_get_by_index(fdt, node, 0, &clk); if (res) return res; res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) return res; cryp_pdata.clock = clk; cryp_pdata.reset = rstctrl; cryp_pdata.base.pa = dt_cryp.reg; io_pa_or_va_secure(&cryp_pdata.base, dt_cryp.reg_size); if (!cryp_pdata.base.va) panic(); stm32mp_register_secure_periph_iomem(cryp_pdata.base.pa); if (clk_enable(cryp_pdata.clock)) panic(); if (stm32_cryp_reset()) panic(); if (IS_ENABLED(CFG_CRYPTO_DRV_AUTHENC)) { res = stm32_register_authenc(); if (res) { EMSG("Failed to register to authenc: %#"PRIx32, res); panic(); } } if (IS_ENABLED(CFG_CRYPTO_DRV_CIPHER)) { res = stm32_register_cipher(CRYP_IP); if (res) { EMSG("Failed to register to cipher: %#"PRIx32, res); panic(); } } register_pm_core_service_cb(stm32_cryp_pm, NULL, "stm32-cryp"); return TEE_SUCCESS; } static const struct dt_device_match stm32_cryp_match_table[] = { { .compatible = "st,stm32mp1-cryp" }, { } }; DEFINE_DT_DRIVER(stm32_cryp_dt_driver) = { .name = "stm32-cryp", .match_table = stm32_cryp_match_table, .probe = stm32_cryp_probe, }; optee_os-4.3.0/core/drivers/crypto/stm32/stm32_cryp.h000066400000000000000000000040171464416617300224250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #ifndef STM32_CRYP_H #define STM32_CRYP_H #include #include #include #include #include #include #include /* * Platform data related to CRYP instance * @base - IO memory base address * @clk - CRYP clock reference * @rstctrl - CRYP reset controller reference */ struct stm32_cryp_platdata { struct io_pa_va base; struct clk *clock; struct rstctrl *reset; }; enum stm32_cryp_algo_mode { STM32_CRYP_MODE_TDES_ECB, STM32_CRYP_MODE_TDES_CBC, STM32_CRYP_MODE_DES_ECB, STM32_CRYP_MODE_DES_CBC, STM32_CRYP_MODE_AES_ECB, STM32_CRYP_MODE_AES_CBC, STM32_CRYP_MODE_AES_CTR, STM32_CRYP_MODE_AES_GCM, STM32_CRYP_MODE_AES_CCM, }; /* * Full CRYP context. * Store CRYP internal state to be able to compute any supported algorithm. */ struct stm32_cryp_context { vaddr_t base; uint32_t cr; struct mutex *lock; /* Protect CRYP HW instance access */ uint32_t assoc_len; uint32_t load_len; uint32_t key[8]; /* In HW byte order */ size_t key_size; size_t block_u32; uint32_t iv[4]; /* In HW byte order */ uint32_t pm_gcmccm[8]; union { uint32_t pm_gcm[8]; uint32_t ctr0_ccm[4]; }; uint32_t extra[4]; size_t extra_size; }; TEE_Result stm32_cryp_init(struct stm32_cryp_context *ctx, bool is_decrypt, enum stm32_cryp_algo_mode mode, const void *key, size_t key_size, const void *iv, size_t iv_size); TEE_Result stm32_cryp_update(struct stm32_cryp_context *ctx, bool last_block, uint8_t *data_in, uint8_t *data_out, size_t data_size); TEE_Result stm32_cryp_update_assodata(struct stm32_cryp_context *ctx, uint8_t *data, size_t data_size); TEE_Result stm32_cryp_update_load(struct stm32_cryp_context *ctx, uint8_t *data_in, uint8_t *data_out, size_t data_size); TEE_Result stm32_cryp_final(struct stm32_cryp_context *ctx, uint8_t *tag, size_t tag_size); #endif optee_os-4.3.0/core/drivers/crypto/stm32/stm32_saes.c000066400000000000000000001057321464416617300224040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "stm32_saes.h" /* SAES control register */ #define _SAES_CR U(0x0) /* SAES status register */ #define _SAES_SR U(0x04) /* SAES data input register */ #define _SAES_DINR U(0x08) /* SAES data output register */ #define _SAES_DOUTR U(0x0c) /* SAES key registers [0-3] */ #define _SAES_KEYR0 U(0x10) #define _SAES_KEYR1 U(0x14) #define _SAES_KEYR2 U(0x18) #define _SAES_KEYR3 U(0x1c) /* SAES initialization vector registers [0-3] */ #define _SAES_IVR0 U(0x20) #define _SAES_IVR1 U(0x24) #define _SAES_IVR2 U(0x28) #define _SAES_IVR3 U(0x2c) /* SAES key registers [4-7] */ #define _SAES_KEYR4 U(0x30) #define _SAES_KEYR5 U(0x34) #define _SAES_KEYR6 U(0x38) #define _SAES_KEYR7 U(0x3c) /* SAES suspend registers [0-7] */ #define _SAES_SUSPR0 U(0x40) #define _SAES_SUSPR1 U(0x44) #define _SAES_SUSPR2 U(0x48) #define _SAES_SUSPR3 U(0x4c) #define _SAES_SUSPR4 U(0x50) #define _SAES_SUSPR5 U(0x54) #define _SAES_SUSPR6 U(0x58) #define _SAES_SUSPR7 U(0x5c) /* SAES Interrupt Enable Register */ #define _SAES_IER U(0x300) /* SAES Interrupt Status Register */ #define _SAES_ISR U(0x304) /* SAES Interrupt Clear Register */ #define _SAES_ICR U(0x308) /* SAES control register fields */ #define _SAES_CR_RESET_VALUE U(0x0) #define _SAES_CR_IPRST BIT(31) #define _SAES_CR_KEYSEL_MASK GENMASK_32(30, 28) #define _SAES_CR_KEYSEL_SHIFT U(28) #define _SAES_CR_KEYSEL_SOFT U(0x0) #define _SAES_CR_KEYSEL_DHUK U(0x1) #define _SAES_CR_KEYSEL_BHK U(0x2) #define _SAES_CR_KEYSEL_BHU_XOR_BH_K U(0x4) #define _SAES_CR_KEYSEL_TEST U(0x7) #define _SAES_CR_KSHAREID_MASK GENMASK_32(27, 26) #define _SAES_CR_KSHAREID_SHIFT U(26) #define _SAES_CR_KSHAREID_CRYP U(0x0) #define _SAES_CR_KEYMOD_MASK GENMASK_32(25, 24) #define _SAES_CR_KEYMOD_SHIFT U(24) #define _SAES_CR_KEYMOD_NORMAL U(0x0) #define _SAES_CR_KEYMOD_WRAPPED U(0x1) #define _SAES_CR_KEYMOD_SHARED U(0x2) #define _SAES_CR_NPBLB_MASK GENMASK_32(23, 20) #define _SAES_CR_NPBLB_SHIFT U(20) #define _SAES_CR_KEYPROT BIT(19) #define _SAES_CR_KEYSIZE BIT(18) #define _SAES_CR_GCMPH_MASK GENMASK_32(14, 13) #define _SAES_CR_GCMPH_SHIFT U(13) #define _SAES_CR_GCMPH_INIT U(0) #define _SAES_CR_GCMPH_HEADER U(1) #define _SAES_CR_GCMPH_PAYLOAD U(2) #define _SAES_CR_GCMPH_FINAL U(3) #define _SAES_CR_DMAOUTEN BIT(12) #define _SAES_CR_DMAINEN BIT(11) #define _SAES_CR_CHMOD_MASK (BIT(16) | GENMASK_32(6, 5)) #define _SAES_CR_CHMOD_SHIFT U(5) #define _SAES_CR_CHMOD_ECB U(0x0) #define _SAES_CR_CHMOD_CBC U(0x1) #define _SAES_CR_CHMOD_CTR U(0x2) #define _SAES_CR_CHMOD_GCM U(0x3) #define _SAES_CR_CHMOD_GMAC U(0x3) #define _SAES_CR_CHMOD_CCM U(0x800) #define _SAES_CR_MODE_MASK GENMASK_32(4, 3) #define _SAES_CR_MODE_SHIFT U(3) #define _SAES_CR_MODE_ENC U(0) #define _SAES_CR_MODE_KEYPREP U(1) #define _SAES_CR_MODE_DEC U(2) #define _SAES_CR_DATATYPE_MASK GENMASK_32(2, 1) #define _SAES_CR_DATATYPE_SHIFT U(1) #define _SAES_CR_DATATYPE_NONE U(0) #define _SAES_CR_DATATYPE_HALF_WORD U(1) #define _SAES_CR_DATATYPE_BYTE U(2) #define _SAES_CR_DATATYPE_BIT U(3) #define _SAES_CR_EN BIT(0) /* SAES status register fields */ #define _SAES_SR_KEYVALID BIT(7) #define _SAES_SR_BUSY BIT(3) #define _SAES_SR_WRERR BIT(2) #define _SAES_SR_RDERR BIT(1) #define _SAES_SR_CCF BIT(0) /* SAES interrupt registers fields */ #define _SAES_I_RNG_ERR BIT(3) #define _SAES_I_KEY_ERR BIT(2) #define _SAES_I_RW_ERR BIT(1) #define _SAES_I_CC BIT(0) #define SAES_TIMEOUT_US U(100000) #define TIMEOUT_US_1MS U(1000) #define SAES_RESET_DELAY U(2) #define IS_CHAINING_MODE(mode, cr) \ (((cr) & _SAES_CR_CHMOD_MASK) == (_SAES_CR_CHMOD_##mode << \ _SAES_CR_CHMOD_SHIFT)) #define SET_CHAINING_MODE(mode, cr) \ set_field_u32(cr, _SAES_CR_CHMOD_MASK, _SAES_CR_CHMOD_##mode) static struct mutex saes_lock = MUTEX_INITIALIZER; static struct stm32_saes_platdata { vaddr_t base; struct clk *clk; struct rstctrl *reset; } saes_pdata; static bool does_chaining_mode_need_iv(uint32_t cr) { return !IS_CHAINING_MODE(ECB, cr); } static bool is_encrypt(uint32_t cr) { return (cr & _SAES_CR_MODE_MASK) == SHIFT_U32(_SAES_CR_MODE_ENC, _SAES_CR_MODE_SHIFT); } static bool is_decrypt(uint32_t cr) { return (cr & _SAES_CR_MODE_MASK) == SHIFT_U32(_SAES_CR_MODE_DEC, _SAES_CR_MODE_SHIFT); } static bool does_need_npblb(uint32_t cr) { return (IS_CHAINING_MODE(GCM, cr) && is_encrypt(cr)) || (IS_CHAINING_MODE(CCM, cr) && is_decrypt(cr)); } static bool can_suspend(uint32_t cr) { return !IS_CHAINING_MODE(GCM, cr); } static void write_aligned_block(vaddr_t base, uint32_t *data) { unsigned int i = 0; /* SAES is configured to swap bytes as expected */ for (i = 0; i < AES_BLOCK_NB_U32; i++) io_write32(base + _SAES_DINR, data[i]); } static void write_block(vaddr_t base, uint8_t *data) { if (IS_ALIGNED_WITH_TYPE(data, uint32_t)) { write_aligned_block(base, (void *)data); } else { uint32_t data_u32[AES_BLOCK_NB_U32] = { }; memcpy(data_u32, data, sizeof(data_u32)); write_aligned_block(base, data_u32); } } static void read_aligned_block(vaddr_t base, uint32_t *data) { unsigned int i = 0; /* SAES is configured to swap bytes as expected */ for (i = 0; i < AES_BLOCK_NB_U32; i++) data[i] = io_read32(base + _SAES_DOUTR); } static void read_block(vaddr_t base, uint8_t *data) { if (IS_ALIGNED_WITH_TYPE(data, uint32_t)) { read_aligned_block(base, (void *)data); } else { uint32_t data_u32[AES_BLOCK_NB_U32] = { }; read_aligned_block(base, data_u32); memcpy(data, data_u32, sizeof(data_u32)); } } static TEE_Result wait_computation_completed(vaddr_t base) { uint64_t timeout_ref = timeout_init_us(SAES_TIMEOUT_US); while ((io_read32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) if (timeout_elapsed(timeout_ref)) break; if ((io_read32(base + _SAES_SR) & _SAES_SR_CCF) != _SAES_SR_CCF) { DMSG("CCF timeout"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static void clear_computation_completed(uintptr_t base) { io_setbits32(base + _SAES_ICR, _SAES_I_CC); } static TEE_Result wait_key_valid(vaddr_t base) { uint64_t timeout_ref = timeout_init_us(SAES_TIMEOUT_US); while (!(io_read32(base + _SAES_SR) & _SAES_SR_KEYVALID)) if (timeout_elapsed(timeout_ref)) break; if (!(io_read32(base + _SAES_SR) & _SAES_SR_KEYVALID)) { DMSG("CCF timeout"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static TEE_Result saes_start(struct stm32_saes_context *ctx) { uint64_t timeout_ref = 0; /* Reset SAES */ io_setbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); timeout_ref = timeout_init_us(SAES_TIMEOUT_US); while (io_read32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) if (timeout_elapsed(timeout_ref)) break; if (io_read32(ctx->base + _SAES_SR) & _SAES_SR_BUSY) { DMSG("busy timeout"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static void saes_end(struct stm32_saes_context *ctx, int prev_error) { if (prev_error) { /* Reset SAES */ io_setbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); } /* Disable the SAES peripheral */ io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_EN); } static void saes_write_iv(struct stm32_saes_context *ctx) { /* If chaining mode need to restore IV */ if (does_chaining_mode_need_iv(ctx->cr)) { unsigned int i = 0; for (i = 0; i < AES_IVSIZE / sizeof(uint32_t); i++) { io_write32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t), ctx->iv[i]); } } } static void saes_save_suspend(struct stm32_saes_context *ctx) { size_t i = 0; for (i = 0; i < 8; i++) ctx->susp[i] = io_read32(ctx->base + _SAES_SUSPR0 + i * sizeof(uint32_t)); } static void saes_restore_suspend(struct stm32_saes_context *ctx) { size_t i = 0; for (i = 0; i < 8; i++) io_write32(ctx->base + _SAES_SUSPR0 + i * sizeof(uint32_t), ctx->susp[i]); } static void saes_write_key(struct stm32_saes_context *ctx) { /* Restore the _SAES_KEYRx if SOFTWARE key */ if ((ctx->cr & _SAES_CR_KEYSEL_MASK) == SHIFT_U32(_SAES_CR_KEYSEL_SOFT, _SAES_CR_KEYSEL_SHIFT)) { size_t i = 0; for (i = 0; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) io_write32(ctx->base + _SAES_KEYR0 + i * sizeof(uint32_t), ctx->key[i]); if ((ctx->cr & _SAES_CR_KEYSIZE) == _SAES_CR_KEYSIZE) { for (i = 0; i < (AES_KEYSIZE_256 / 2) / sizeof(uint32_t); i++) { io_write32(ctx->base + _SAES_KEYR4 + i * sizeof(uint32_t), ctx->key[i + 4]); } } } } static TEE_Result saes_prepare_key(struct stm32_saes_context *ctx) { TEE_Result res = TEE_ERROR_GENERIC; /* Disable the SAES peripheral */ io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_EN); /* Set key size */ if ((ctx->cr & _SAES_CR_KEYSIZE)) io_setbits32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); else io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_KEYSIZE); saes_write_key(ctx); res = wait_key_valid(ctx->base); if (res) return res; /* * For ECB/CBC decryption, key preparation mode must be selected * to populate the key. */ if ((IS_CHAINING_MODE(ECB, ctx->cr) || IS_CHAINING_MODE(CBC, ctx->cr)) && is_decrypt(ctx->cr)) { /* Select Mode 2 */ io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, SHIFT_U32(_SAES_CR_MODE_KEYPREP, _SAES_CR_MODE_SHIFT)); /* Enable SAES */ io_setbits32(ctx->base + _SAES_CR, _SAES_CR_EN); res = wait_computation_completed(ctx->base); if (res) return res; clear_computation_completed(ctx->base); /* Set Mode 3 */ io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_MODE_MASK, SHIFT_U32(_SAES_CR_MODE_DEC, _SAES_CR_MODE_SHIFT)); } return TEE_SUCCESS; } static TEE_Result save_context(struct stm32_saes_context *ctx) { if ((io_read32(ctx->base + _SAES_SR) & _SAES_SR_CCF)) { /* Device should not be in a processing phase */ return TEE_ERROR_BAD_STATE; } /* Save CR */ ctx->cr = io_read32(ctx->base + _SAES_CR); if (!can_suspend(ctx->cr)) return TEE_SUCCESS; saes_save_suspend(ctx); /* If chaining mode need to save current IV */ if (does_chaining_mode_need_iv(ctx->cr)) { uint8_t i = 0; /* Save IV */ for (i = 0; i < AES_IVSIZE / sizeof(uint32_t); i++) { ctx->iv[i] = io_read32(ctx->base + _SAES_IVR0 + i * sizeof(uint32_t)); } } /* Disable the SAES peripheral */ io_clrbits32(ctx->base + _SAES_CR, _SAES_CR_EN); return TEE_SUCCESS; } /* To resume the processing of a message */ static TEE_Result restore_context(struct stm32_saes_context *ctx) { TEE_Result res = TEE_SUCCESS; /* SAES shall be disabled */ if ((io_read32(ctx->base + _SAES_CR) & _SAES_CR_EN)) { DMSG("Device is still enabled"); return TEE_ERROR_BAD_STATE; } /* Reset internal state */ io_setbits32(ctx->base + _SAES_CR, _SAES_CR_IPRST); /* Restore configuration register */ io_write32(ctx->base + _SAES_CR, ctx->cr); /* Write key and, in case of CBC or ECB decrypt, prepare it */ res = saes_prepare_key(ctx); if (res) return res; saes_restore_suspend(ctx); saes_write_iv(ctx); /* Enable the SAES peripheral */ io_setbits32(ctx->base + _SAES_CR, _SAES_CR_EN); return TEE_SUCCESS; } static TEE_Result do_from_init_to_phase(struct stm32_saes_context *ctx, uint32_t new_phase) { TEE_Result res = TEE_SUCCESS; /* We didn't run the init phase yet */ res = restore_context(ctx); if (res) return res; res = wait_computation_completed(ctx->base); if (res) return res; clear_computation_completed(ctx->base); /* Move to 'new_phase' */ io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, SHIFT_U32(new_phase, _SAES_CR_GCMPH_SHIFT)); /* Enable the SAES peripheral (init disabled it) */ io_setbits32(ctx->base + _SAES_CR, _SAES_CR_EN); return TEE_SUCCESS; } static TEE_Result do_from_header_to_phase(struct stm32_saes_context *ctx, uint32_t new_phase) { TEE_Result res = TEE_SUCCESS; if (can_suspend(ctx->cr)) { res = restore_context(ctx); if (res) return res; } if (ctx->extra_size) { /* Manage unaligned header data before moving to next phase */ memset((uint8_t *)ctx->extra + ctx->extra_size, 0, AES_BLOCK_SIZE - ctx->extra_size); write_aligned_block(ctx->base, ctx->extra); res = wait_computation_completed(ctx->base); if (res) return res; clear_computation_completed(ctx->base); ctx->assoc_len += ctx->extra_size * INT8_BIT; ctx->extra_size = U(0); } /* Move to 'new_phase' */ io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, SHIFT_U32(new_phase, _SAES_CR_GCMPH_SHIFT)); return TEE_SUCCESS; } /** * @brief Start an AES computation. * @param ctx: SAES process context * @param is_dec: true if decryption, false if encryption * @param ch_mode: define the chaining mode * @param key_select: define where the key comes from * @param key: pointer to key (if key_select is KEY_SOFT, else unused) * @param key_size: key size * @param iv: pointer to initialization vector (unused if ch_mode is ECB) * @param iv_size: iv size * @note this function doesn't access to hardware but stores in ctx the values * * @retval TEE_SUCCESS if OK or a TEE_Result compliant code. */ TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec, enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select, const void *key, size_t key_size, const void *iv, size_t iv_size) { const uint32_t *key_u32 = NULL; const uint32_t *iv_u32 = NULL; uint32_t local_key[8] = { }; uint32_t local_iv[4] = { }; unsigned int i = 0; if (!ctx) return TEE_ERROR_BAD_PARAMETERS; *ctx = (struct stm32_saes_context){ .lock = &saes_lock, .base = saes_pdata.base, .cr = _SAES_CR_RESET_VALUE }; /* We want buffer to be u32 aligned */ if (IS_ALIGNED_WITH_TYPE(key, uint32_t)) { key_u32 = key; } else { memcpy(local_key, key, key_size); key_u32 = local_key; } if (IS_ALIGNED_WITH_TYPE(iv, uint32_t)) { iv_u32 = iv; } else { memcpy(local_iv, iv, iv_size); iv_u32 = local_iv; } if (is_dec) ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_MODE_MASK, _SAES_CR_MODE_DEC); else ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_MODE_MASK, _SAES_CR_MODE_ENC); /* Save chaining mode */ switch (ch_mode) { case STM32_SAES_MODE_ECB: ctx->cr |= SET_CHAINING_MODE(ECB, ctx->cr); break; case STM32_SAES_MODE_CBC: ctx->cr |= SET_CHAINING_MODE(CBC, ctx->cr); break; case STM32_SAES_MODE_CTR: ctx->cr |= SET_CHAINING_MODE(CTR, ctx->cr); break; case STM32_SAES_MODE_GCM: ctx->cr |= SET_CHAINING_MODE(GCM, ctx->cr); break; case STM32_SAES_MODE_CCM: ctx->cr |= SET_CHAINING_MODE(CCM, ctx->cr); break; default: return TEE_ERROR_BAD_PARAMETERS; } /* * We will use HW Byte swap (_SAES_CR_DATATYPE_BYTE) for data. * So we won't need to * TEE_U32_TO_BIG_ENDIAN(data) before write to DINR * nor * TEE_U32_FROM_BIG_ENDIAN after reading from DOUTR. * * But note that wrap key only accept _SAES_CR_DATATYPE_NONE. */ ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_DATATYPE_MASK, _SAES_CR_DATATYPE_BYTE); /* Configure keysize */ switch (key_size) { case AES_KEYSIZE_128: ctx->cr &= ~_SAES_CR_KEYSIZE; break; case AES_KEYSIZE_256: ctx->cr |= _SAES_CR_KEYSIZE; break; default: return TEE_ERROR_BAD_PARAMETERS; } /* Configure key */ switch (key_select) { case STM32_SAES_KEY_SOFT: ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, SHIFT_U32(_SAES_CR_KEYSEL_SOFT, _SAES_CR_KEYSEL_SHIFT)); /* Save key */ switch (key_size) { case AES_KEYSIZE_128: /* First 16 bytes == 4 u32 */ for (i = 0; i < AES_KEYSIZE_128 / sizeof(uint32_t); i++) { ctx->key[i] = TEE_U32_TO_BIG_ENDIAN(key_u32[3 - i]); /* * /!\ we save the key in HW byte order * and word order: key[i] is for _SAES_KEYRi. */ } break; case AES_KEYSIZE_256: for (i = 0; i < AES_KEYSIZE_256 / sizeof(uint32_t); i++) { ctx->key[i] = TEE_U32_TO_BIG_ENDIAN(key_u32[7 - i]); /* * /!\ we save the key in HW byte order * and word order: key[i] is for _SAES_KEYRi. */ } break; default: return TEE_ERROR_BAD_PARAMETERS; } break; case STM32_SAES_KEY_DHU: ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, SHIFT_U32(_SAES_CR_KEYSEL_DHUK, _SAES_CR_KEYSEL_SHIFT)); break; case STM32_SAES_KEY_BH: ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, SHIFT_U32(_SAES_CR_KEYSEL_BHK, _SAES_CR_KEYSEL_SHIFT)); break; case STM32_SAES_KEY_BHU_XOR_BH: ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, SHIFT_U32(_SAES_CR_KEYSEL_BHU_XOR_BH_K, _SAES_CR_KEYSEL_SHIFT)); break; case STM32_SAES_KEY_WRAPPED: ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK, SHIFT_U32(_SAES_CR_KEYSEL_SOFT, _SAES_CR_KEYSEL_SHIFT)); break; default: return TEE_ERROR_BAD_PARAMETERS; } /* Save IV */ if (ch_mode != STM32_SAES_MODE_ECB) { if (!iv || iv_size != AES_IVSIZE) return TEE_ERROR_BAD_PARAMETERS; for (i = 0; i < AES_IVSIZE / sizeof(uint32_t); i++) ctx->iv[i] = TEE_U32_TO_BIG_ENDIAN(iv_u32[3 - i]); } /* Reset suspend registers */ memset(ctx->susp, 0, sizeof(ctx->susp)); return saes_start(ctx); } /** * @brief Update (or start) an AES authentificate process of * associated data (CCM or GCM). * @param ctx: SAES process context * @param data: pointer to associated data * @param data_size: data size * * @retval 0 if OK. */ TEE_Result stm32_saes_update_assodata(struct stm32_saes_context *ctx, uint8_t *data, size_t data_size) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; uint32_t previous_phase = 0; if (!ctx) return TEE_ERROR_BAD_PARAMETERS; /* If no associated data, nothing to do */ if (!data || !data_size) return TEE_SUCCESS; mutex_lock(ctx->lock); previous_phase = (ctx->cr & _SAES_CR_GCMPH_MASK) >> _SAES_CR_GCMPH_SHIFT; switch (previous_phase) { case _SAES_CR_GCMPH_INIT: res = do_from_init_to_phase(ctx, _SAES_CR_GCMPH_HEADER); break; case _SAES_CR_GCMPH_HEADER: /* * Function update_assodata() was already called. * We only need to restore the context. */ if (can_suspend(ctx->cr)) res = restore_context(ctx); break; default: DMSG("out of order call"); res = TEE_ERROR_BAD_STATE; } if (res) goto out; /* Manage if remaining data from a previous update_assodata() call */ if (ctx->extra_size && ((ctx->extra_size + data_size) >= AES_BLOCK_SIZE)) { uint32_t block[AES_BLOCK_NB_U32] = { }; memcpy(block, ctx->extra, ctx->extra_size); memcpy((uint8_t *)block + ctx->extra_size, data, AES_BLOCK_SIZE - ctx->extra_size); write_aligned_block(ctx->base, block); res = wait_computation_completed(ctx->base); if (res) goto out; clear_computation_completed(ctx->base); i += AES_BLOCK_SIZE - ctx->extra_size; ctx->extra_size = 0; ctx->assoc_len += AES_BLOCK_SIZE_BIT; } while (data_size - i >= AES_BLOCK_SIZE) { write_block(ctx->base, data + i); res = wait_computation_completed(ctx->base); if (res) goto out; clear_computation_completed(ctx->base); /* Process next block */ i += AES_BLOCK_SIZE; ctx->assoc_len += AES_BLOCK_SIZE_BIT; } /* * Manage last block if not a block size multiple: * Save remaining data to manage them later (potentially with new * associated data). */ if (i < data_size) { memcpy((uint8_t *)ctx->extra + ctx->extra_size, data + i, data_size - i); ctx->extra_size += data_size - i; } res = save_context(ctx); out: if (res) saes_end(ctx, res); mutex_unlock(ctx->lock); return res; } /** * @brief Update (or start) an AES authenticate and de/encrypt with * payload data (CCM or GCM). * @param ctx: SAES process context * @param last_block: true if last payload data block * @param data_in: pointer to payload * @param data_out: pointer where to save de/encrypted payload * @param data_size: payload size * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block, uint8_t *data_in, uint8_t *data_out, size_t data_size) { TEE_Result res = TEE_SUCCESS; unsigned int i = 0; uint32_t previous_phase = 0; if (!ctx) return TEE_ERROR_BAD_PARAMETERS; /* If there is no data, nothing to do */ if (!data_in || !data_size) return TEE_SUCCESS; mutex_lock(ctx->lock); previous_phase = ((ctx->cr & _SAES_CR_GCMPH_MASK) >> _SAES_CR_GCMPH_SHIFT); switch (previous_phase) { case _SAES_CR_GCMPH_INIT: res = do_from_init_to_phase(ctx, _SAES_CR_GCMPH_PAYLOAD); break; case _SAES_CR_GCMPH_HEADER: res = do_from_header_to_phase(ctx, _SAES_CR_GCMPH_PAYLOAD); break; case _SAES_CR_GCMPH_PAYLOAD: /* new update_load call, we only need to restore context */ if (can_suspend(ctx->cr)) res = restore_context(ctx); break; default: DMSG("out of order call"); res = TEE_ERROR_BAD_STATE; } if (res) goto out; while (i < ROUNDDOWN(data_size, AES_BLOCK_SIZE)) { write_block(ctx->base, data_in + i); res = wait_computation_completed(ctx->base); if (res) goto out; read_block(ctx->base, data_out + i); clear_computation_completed(ctx->base); /* Process next block */ i += AES_BLOCK_SIZE; ctx->load_len += AES_BLOCK_SIZE_BIT; } /* Manage last block if not a block size multiple */ if (last_block && i < data_size) { uint32_t block_in[AES_BLOCK_NB_U32] = { }; uint32_t block_out[AES_BLOCK_NB_U32] = { }; memcpy(block_in, data_in + i, data_size - i); if (does_need_npblb(ctx->cr)) { uint32_t npblb = AES_BLOCK_SIZE - (data_size - i); io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_NPBLB_MASK, SHIFT_U32(npblb, _SAES_CR_NPBLB_SHIFT)); } write_aligned_block(ctx->base, block_in); res = wait_computation_completed(ctx->base); if (res) goto out; read_aligned_block(ctx->base, block_out); clear_computation_completed(ctx->base); memcpy(data_out + i, block_out, data_size - i); ctx->load_len += (data_size - i) * INT8_BIT; } res = save_context(ctx); out: if (res) saes_end(ctx, res); mutex_unlock(ctx->lock); return res; } /** * @brief Get authentication tag for AES authenticated algorithms (CCM or GCM). * @param ctx: SAES process context * @param tag: pointer where to save the tag * @param data_size: tag size * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, size_t tag_size) { TEE_Result res = TEE_SUCCESS; uint32_t tag_u32[4] = { }; uint32_t previous_phase = 0; if (!ctx) return TEE_ERROR_BAD_PARAMETERS; mutex_lock(ctx->lock); previous_phase = (ctx->cr & _SAES_CR_GCMPH_MASK) >> _SAES_CR_GCMPH_SHIFT; switch (previous_phase) { case _SAES_CR_GCMPH_INIT: res = do_from_init_to_phase(ctx, _SAES_CR_GCMPH_FINAL); break; case _SAES_CR_GCMPH_HEADER: res = do_from_header_to_phase(ctx, _SAES_CR_GCMPH_FINAL); break; case _SAES_CR_GCMPH_PAYLOAD: if (can_suspend(ctx->cr)) res = restore_context(ctx); /* Move to final phase */ io_clrsetbits32(ctx->base + _SAES_CR, _SAES_CR_GCMPH_MASK, SHIFT_U32(_SAES_CR_GCMPH_FINAL, _SAES_CR_GCMPH_SHIFT)); break; default: DMSG("out of order call"); res = TEE_ERROR_BAD_STATE; } if (res) goto out; if (IS_CHAINING_MODE(GCM, ctx->cr)) { /* SAES is configured to swap bytes as expected */ io_write32(ctx->base + _SAES_DINR, 0); io_write32(ctx->base + _SAES_DINR, ctx->assoc_len); io_write32(ctx->base + _SAES_DINR, 0); io_write32(ctx->base + _SAES_DINR, ctx->load_len); } res = wait_computation_completed(ctx->base); if (res) goto out; read_aligned_block(ctx->base, tag_u32); clear_computation_completed(ctx->base); memcpy(tag, tag_u32, MIN(sizeof(tag_u32), tag_size)); out: saes_end(ctx, res); mutex_unlock(ctx->lock); return res; } /** * @brief Update (or start) an AES de/encrypt process (ECB, CBC or CTR). * @param ctx: SAES process context * @param last_block: true if last payload data block * @param data_in: pointer to payload * @param data_out: pointer where to save de/encrypted payload * @param data_size: payload size * * @retval TEE_SUCCESS if OK. */ TEE_Result stm32_saes_update(struct stm32_saes_context *ctx, bool last_block, uint8_t *data_in, uint8_t *data_out, size_t data_size) { TEE_Result res = TEE_SUCCESS; unsigned int i = U(0); if (!ctx) return TEE_ERROR_BAD_PARAMETERS; mutex_lock(ctx->lock); /* * CBC encryption requires the 2 last blocks to be aligned with AES * block size. */ if (last_block && IS_CHAINING_MODE(CBC, ctx->cr) && is_encrypt(ctx->cr) && (ROUNDDOWN(data_size, AES_BLOCK_SIZE) != data_size)) { if (data_size < AES_BLOCK_SIZE * 2) { /* * If CBC, size of the last part should be at * least 2*AES_BLOCK_SIZE */ EMSG("Unexpected last block size"); res = TEE_ERROR_BAD_STATE; goto out; } /* * Do not support padding if the total size is not aligned with * the size of a block. */ res = TEE_ERROR_NOT_IMPLEMENTED; goto out; } /* Manage remaining CTR mask from previous update call */ if (IS_CHAINING_MODE(CTR, ctx->cr) && ctx->extra_size) { unsigned int j = 0; uint8_t *mask = (uint8_t *)ctx->extra; for (i = 0, j = 0; j < ctx->extra_size && i < data_size; j++, i++) data_out[i] = data_in[i] ^ mask[j]; if (j != ctx->extra_size) { /* * We didn't consume all saved mask, * but no more data. */ /* We save remaining mask and its new size */ memmove(ctx->extra, ctx->extra + j, ctx->extra_size - j); ctx->extra_size -= j; /* * We don't need to save HW context we didn't * modify HW state. */ res = TEE_SUCCESS; goto out; } /* All extra mask consumed */ ctx->extra_size = 0; } res = restore_context(ctx); if (res) goto out; while (data_size - i >= AES_BLOCK_SIZE) { write_block(ctx->base, data_in + i); res = wait_computation_completed(ctx->base); if (res) goto out; read_block(ctx->base, data_out + i); clear_computation_completed(ctx->base); /* Process next block */ i += AES_BLOCK_SIZE; } /* Manage last block if not a block size multiple */ if (i < data_size) { if (IS_CHAINING_MODE(CTR, ctx->cr)) { /* * For CTR we save the generated mask to use it at next * update call. */ uint32_t block_in[AES_BLOCK_NB_U32] = { }; uint32_t block_out[AES_BLOCK_NB_U32] = { }; memcpy(block_in, data_in + i, data_size - i); write_aligned_block(ctx->base, block_in); res = wait_computation_completed(ctx->base); if (res) goto out; read_aligned_block(ctx->base, block_out); clear_computation_completed(ctx->base); memcpy(data_out + i, block_out, data_size - i); /* Save mask for possibly next call */ ctx->extra_size = AES_BLOCK_SIZE - (data_size - i); memcpy(ctx->extra, (uint8_t *)block_out + data_size - i, ctx->extra_size); } else { /* CBC and ECB can manage only multiple of block_size */ res = TEE_ERROR_BAD_PARAMETERS; goto out; } } if (!last_block) res = save_context(ctx); out: /* If last block or error, end of SAES process */ if (last_block || res) saes_end(ctx, res); mutex_unlock(ctx->lock); return res; } static void xor_block(uint8_t *b1, uint8_t *b2, size_t size) { size_t i = 0; for (i = 0; i < size; i++) b1[i] ^= b2[i]; } static TEE_Result stm32_saes_cmac_prf_128(struct stm32_saes_context *ctx, enum stm32_saes_key_selection key_sel, const void *key, size_t key_size, uint8_t *data, size_t data_size, uint8_t *out) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t block[AES_BLOCK_SIZE] = { }; uint8_t k1[AES_BLOCK_SIZE] = { }; uint8_t k2[AES_BLOCK_SIZE] = { }; uint8_t l[AES_BLOCK_SIZE] = { }; size_t processed = 0; uint8_t bit = 0; int i = 0; if (!ctx) return TEE_ERROR_BAD_PARAMETERS; /* Get K1 and K2 */ res = stm32_saes_init(ctx, false, STM32_SAES_MODE_ECB, key_sel, key, key_size, NULL, 0); if (res) return res; res = stm32_saes_update(ctx, true, l, l, sizeof(l)); if (res) return res; /* MSB(L) == 0 => K1 = L << 1 */ bit = 0; for (i = sizeof(l) - 1; i >= 0; i--) { k1[i] = (l[i] << 1) | bit; bit = (l[i] & 0x80) >> 7; } /* MSB(L) == 1 => K1 = (L << 1) XOR const_Rb */ if ((l[0] & 0x80)) k1[sizeof(k1) - 1] = k1[sizeof(k1) - 1] ^ 0x87; /* MSB(K1) == 0 => K2 = K1 << 1 */ bit = 0; for (i = sizeof(k1) - 1; i >= 0; i--) { k2[i] = (k1[i] << 1) | bit; bit = (k1[i] & 0x80) >> 7; } /* MSB(K1) == 1 => K2 = (K1 << 1) XOR const_Rb */ if ((k1[0] & 0x80)) k2[sizeof(k2) - 1] = k2[sizeof(k2) - 1] ^ 0x87; if (data_size > AES_BLOCK_SIZE) { uint8_t *data_out = NULL; /* All block but last in CBC mode */ res = stm32_saes_init(ctx, false, STM32_SAES_MODE_CBC, key_sel, key, key_size, block, sizeof(block)); if (res) return res; processed = ROUNDDOWN(data_size - 1, AES_BLOCK_SIZE); data_out = malloc(processed); if (!data_out) return TEE_ERROR_OUT_OF_MEMORY; res = stm32_saes_update(ctx, true, data, data_out, processed); if (!res) { /* Copy last out block or keep block as { 0 } */ memcpy(block, data_out + processed - AES_BLOCK_SIZE, AES_BLOCK_SIZE); } free(data_out); if (res) return res; } /* Manage last block */ xor_block(block, data + processed, data_size - processed); if (data_size - processed == AES_BLOCK_SIZE) { xor_block(block, k1, AES_BLOCK_SIZE); } else { /* xor with padding = 0b100... */ block[data_size - processed] ^= 0x80; xor_block(block, k2, AES_BLOCK_SIZE); } /* * AES last block. * We need to use same chaining mode to keep same key if DHUK is * selected so we reuse l as a zero initialized IV. */ memset(l, 0, sizeof(l)); res = stm32_saes_init(ctx, false, STM32_SAES_MODE_CBC, key_sel, key, key_size, l, sizeof(l)); if (res) return res; return stm32_saes_update(ctx, true, block, out, AES_BLOCK_SIZE); } TEE_Result stm32_saes_kdf(struct stm32_saes_context *ctx, enum stm32_saes_key_selection key_sel, const void *key, size_t key_size, const void *input, size_t input_size, uint8_t *subkey, size_t subkey_size) { TEE_Result res = TEE_SUCCESS; uint32_t index = 0; uint32_t index_be = 0; uint8_t *data = NULL; size_t data_index = 0; size_t subkey_index = 0; size_t data_size = input_size + sizeof(index_be); uint8_t cmac[AES_BLOCK_SIZE] = { }; if (!ctx || !input || !input_size) return TEE_ERROR_BAD_PARAMETERS; /* For each K(i) we will add an index */ data = malloc(data_size); if (!data) return TEE_ERROR_OUT_OF_MEMORY; data_index = 0; index_be = TEE_U32_TO_BIG_ENDIAN(index); memcpy(data + data_index, &index_be, sizeof(index_be)); data_index += sizeof(index_be); memcpy(data + data_index, input, input_size); data_index += input_size; /* K(i) computation. */ index = 0; while (subkey_index < subkey_size) { index++; index_be = TEE_U32_TO_BIG_ENDIAN(index); memcpy(data, &index_be, sizeof(index_be)); res = stm32_saes_cmac_prf_128(ctx, key_sel, key, key_size, data, data_size, cmac); if (res) goto out; memcpy(subkey + subkey_index, cmac, MIN(subkey_size - subkey_index, sizeof(cmac))); subkey_index += sizeof(cmac); } out: free(data); if (res) memzero_explicit(subkey, subkey_size); return res; } /* Implement hardware HUK derivation using SAES resources */ TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, const void *const_data, size_t const_data_len, uint8_t *subkey, size_t subkey_len) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *input = NULL; size_t input_index = 0; size_t subkey_bitlen = 0; struct stm32_saes_context ctx = { }; uint8_t separator = 0; /* Check if driver is probed */ if (!saes_pdata.base) { return __huk_subkey_derive(usage, const_data, const_data_len, subkey, subkey_len); } input = malloc(const_data_len + sizeof(separator) + sizeof(usage) + sizeof(subkey_bitlen) + AES_BLOCK_SIZE); if (!input) return TEE_ERROR_OUT_OF_MEMORY; input_index = 0; if (const_data) { memcpy(input + input_index, const_data, const_data_len); input_index += const_data_len; memcpy(input + input_index, &separator, sizeof(separator)); input_index += sizeof(separator); } memcpy(input + input_index, &usage, sizeof(usage)); input_index += sizeof(usage); /* * We should add the subkey_len in bits at end of input. * And we choose to put in a MSB first uint32_t. */ subkey_bitlen = TEE_U32_TO_BIG_ENDIAN(subkey_len * INT8_BIT); memcpy(input + input_index, &subkey_bitlen, sizeof(subkey_bitlen)); input_index += sizeof(subkey_bitlen); /* * We get K(0) to avoid some key control attack * and store it at end of input. */ res = stm32_saes_cmac_prf_128(&ctx, STM32_SAES_KEY_DHU, NULL, AES_KEYSIZE_128, input, input_index, input + input_index); if (res) goto out; /* We just added K(0) to input */ input_index += AES_BLOCK_SIZE; res = stm32_saes_kdf(&ctx, STM32_SAES_KEY_DHU, NULL, AES_KEYSIZE_128, input, input_index, subkey, subkey_len); out: free(input); return res; } static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata, const void *fdt, int node) { struct dt_node_info dt_saes = { }; TEE_Result res = TEE_ERROR_GENERIC; dt_saes.reg = fdt_reg_base_address(fdt, node); dt_saes.reg_size = fdt_reg_size(fdt, node); if (dt_saes.reg == DT_INFO_INVALID_REG || dt_saes.reg_size == DT_INFO_INVALID_REG_SIZE) return TEE_ERROR_BAD_PARAMETERS; res = clk_dt_get_by_index(fdt, node, 0, &pdata->clk); if (res != TEE_SUCCESS) return res; res = rstctrl_dt_get_by_index(fdt, node, 0, &pdata->reset); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) return res; pdata->base = (vaddr_t)phys_to_virt(dt_saes.reg, MEM_AREA_IO_SEC, dt_saes.reg_size); if (!pdata->base) panic(); return TEE_SUCCESS; } static TEE_Result stm32_saes_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_SUCCESS; assert(!saes_pdata.base); res = stm32_saes_parse_fdt(&saes_pdata, fdt, node); if (res) return res; if (clk_enable(saes_pdata.clk)) panic(); if (saes_pdata.reset) { /* External reset of SAES */ if (rstctrl_assert_to(saes_pdata.reset, TIMEOUT_US_1MS)) panic(); udelay(SAES_RESET_DELAY); if (rstctrl_deassert_to(saes_pdata.reset, TIMEOUT_US_1MS)) panic(); } else { /* Internal reset of SAES */ io_setbits32(saes_pdata.base + _SAES_CR, _SAES_CR_IPRST); udelay(SAES_RESET_DELAY); io_clrbits32(saes_pdata.base + _SAES_CR, _SAES_CR_IPRST); } if (IS_ENABLED(CFG_CRYPTO_DRV_CIPHER)) { res = stm32_register_cipher(SAES_IP); if (res) { EMSG("Failed to register to cipher: %#"PRIx32, res); panic(); } } return TEE_SUCCESS; } static const struct dt_device_match saes_match_table[] = { { .compatible = "st,stm32mp13-saes" }, { } }; DEFINE_DT_DRIVER(stm32_saes_dt_driver) = { .name = "stm32-saes", .match_table = saes_match_table, .probe = stm32_saes_probe, }; optee_os-4.3.0/core/drivers/crypto/stm32/stm32_saes.h000066400000000000000000000037411464416617300224060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved */ #ifndef STM32_SAES_H #define STM32_SAES_H #include #include #include #include #include #include #include enum stm32_saes_chaining_mode { STM32_SAES_MODE_ECB, STM32_SAES_MODE_CBC, STM32_SAES_MODE_CTR, STM32_SAES_MODE_GCM, STM32_SAES_MODE_CCM, }; enum stm32_saes_key_selection { STM32_SAES_KEY_SOFT, STM32_SAES_KEY_DHU, /* Derived HW unique key */ STM32_SAES_KEY_BH, /* Boot HW key */ STM32_SAES_KEY_BHU_XOR_BH, /* XOR of DHUK and BHK */ STM32_SAES_KEY_WRAPPED }; struct stm32_saes_context { vaddr_t base; uint32_t cr; struct mutex *lock; /* Save the HW instance mutex */ uint32_t assoc_len; uint32_t load_len; uint32_t key[8]; /* In HW byte order */ uint32_t iv[4]; /* In HW byte order */ uint32_t susp[8]; uint32_t extra[4]; size_t extra_size; }; TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_decrypt, enum stm32_saes_chaining_mode ch_mode, enum stm32_saes_key_selection key_select, const void *key, size_t key_len, const void *iv, size_t iv_len); TEE_Result stm32_saes_update(struct stm32_saes_context *ctx, bool last_block, uint8_t *data_in, uint8_t *data_out, size_t data_len); TEE_Result stm32_saes_update_assodata(struct stm32_saes_context *ctx, uint8_t *data, size_t data_len); TEE_Result stm32_saes_update_load(struct stm32_saes_context *ctx, bool last_block, uint8_t *data_in, uint8_t *data_out, size_t data_len); TEE_Result stm32_saes_final(struct stm32_saes_context *ctx, uint8_t *tag, size_t tag_len); TEE_Result stm32_saes_kdf(struct stm32_saes_context *ctx, enum stm32_saes_key_selection key_sel, const void *key, size_t key_size, const void *input, size_t input_size, uint8_t *subkey, size_t subkey_size); #endif optee_os-4.3.0/core/drivers/crypto/stm32/sub.mk000066400000000000000000000002441464416617300213670ustar00rootroot00000000000000srcs-$(CFG_STM32_CRYP) += stm32_cryp.c srcs-$(CFG_STM32_SAES) += stm32_saes.c srcs-$(CFG_CRYPTO_DRV_CIPHER) += cipher.c srcs-$(CFG_CRYPTO_DRV_AUTHENC) += authenc.c optee_os-4.3.0/core/drivers/crypto/sub.mk000066400000000000000000000005521464416617300204210ustar00rootroot00000000000000global-incdirs-$(CFG_CRYPTO_DRIVER) += crypto_api/include subdirs-$(CFG_CRYPTO_DRIVER) += crypto_api subdirs-$(CFG_NXP_CAAM) += caam subdirs-$(CFG_NXP_SE05X) += se050 subdirs-$(CFG_STM32_CRYPTO_DRIVER) += stm32 subdirs-$(CFG_ASPEED_CRYPTO_DRIVER) += aspeed subdirs-$(CFG_VERSAL_CRYPTO_DRIVER) += versal subdirs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisilicon optee_os-4.3.0/core/drivers/crypto/versal/000077500000000000000000000000001464416617300205715ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/versal/authenc.c000066400000000000000000000514321464416617300223710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022. * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * This driver does not queue/pad non-aligned data. * * Allow debug information for future PLM work: if the PLM can not implement * the required changes, we might be able to do it in OP-TEE. */ #define DEBUG_VERSAL_AES 0 #define GCM_TAG_LEN 16 #define XSECURE_AES_KEY_SIZE_128 0 /* Key Length = 32 bytes = 256 bits */ #define XSECURE_AES_KEY_SIZE_256 2 /* Key Length = 16 bytes = 128 bits */ #define XSECURE_ENCRYPT 0 #define XSECURE_DECRYPT 1 enum versal_aes_err { AES_GCM_TAG_MISMATCH = 0x40, AES_KEY_CLEAR_ERROR, AES_DPA_CM_NOT_SUPPORTED, AES_KAT_WRITE_KEY_FAILED_ERROR, AES_KAT_DECRYPT_INIT_FAILED_ERROR, AES_KAT_GCM_TAG_MISMATCH_ERROR, AES_KAT_DATA_MISMATCH_ERROR, AES_KAT_FAILED_ERROR, AESDPACM_KAT_WRITE_KEY_FAILED_ERROR, AESDPACM_KAT_KEYLOAD_FAILED_ERROR, AESDPACM_SSS_CFG_FAILED_ERROR, AESDPACM_KAT_FAILED_ERROR, AESDPACM_KAT_CHECK1_FAILED_ERROR, AESDPACM_KAT_CHECK2_FAILED_ERROR, AESDPACM_KAT_CHECK3_FAILED_ERROR, AESDPACM_KAT_CHECK4_FAILED_ERROR, AESDPACM_KAT_CHECK5_FAILED_ERROR, AES_INVALID_PARAM, AESKAT_INVALID_PARAM, AES_STATE_MISMATCH_ERROR, AES_DEVICE_KEY_NOT_ALLOWED, }; #define VERSAL_AES_ERROR(m) { . error = (m), .name = TO_STR(m) } static const char *versal_aes_error(uint8_t err) { const struct { enum versal_aes_err error; const char *name; } elist[] = { VERSAL_AES_ERROR(AES_GCM_TAG_MISMATCH), VERSAL_AES_ERROR(AES_KEY_CLEAR_ERROR), VERSAL_AES_ERROR(AES_DPA_CM_NOT_SUPPORTED), VERSAL_AES_ERROR(AES_KAT_WRITE_KEY_FAILED_ERROR), VERSAL_AES_ERROR(AES_KAT_DECRYPT_INIT_FAILED_ERROR), VERSAL_AES_ERROR(AES_KAT_GCM_TAG_MISMATCH_ERROR), VERSAL_AES_ERROR(AES_KAT_DATA_MISMATCH_ERROR), VERSAL_AES_ERROR(AES_KAT_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_WRITE_KEY_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_KEYLOAD_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_SSS_CFG_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_CHECK1_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_CHECK2_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_CHECK3_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_CHECK4_FAILED_ERROR), VERSAL_AES_ERROR(AESDPACM_KAT_CHECK5_FAILED_ERROR), VERSAL_AES_ERROR(AES_INVALID_PARAM), VERSAL_AES_ERROR(AESKAT_INVALID_PARAM), VERSAL_AES_ERROR(AES_STATE_MISMATCH_ERROR), VERSAL_AES_ERROR(AES_DEVICE_KEY_NOT_ALLOWED), }; if (err >= AES_GCM_TAG_MISMATCH && err <= AES_DEVICE_KEY_NOT_ALLOWED) { if (elist[err - AES_GCM_TAG_MISMATCH].name) return elist[err - AES_GCM_TAG_MISMATCH].name; return "Invalid"; } return "Unknown"; } enum aes_key_src { XSECURE_AES_BBRAM_KEY = 0, /* BBRAM Key */ XSECURE_AES_BBRAM_RED_KEY, /* BBRAM Red Key */ XSECURE_AES_BH_KEY, /* BH Key */ XSECURE_AES_BH_RED_KEY, /* BH Red Key */ XSECURE_AES_EFUSE_KEY, /* eFUSE Key */ XSECURE_AES_EFUSE_RED_KEY, /* eFUSE Red Key */ XSECURE_AES_EFUSE_USER_KEY_0, /* eFUSE User Key 0 */ XSECURE_AES_EFUSE_USER_KEY_1, /* eFUSE User Key 1 */ XSECURE_AES_EFUSE_USER_RED_KEY_0, /* eFUSE User Red Key 0 */ XSECURE_AES_EFUSE_USER_RED_KEY_1, /* eFUSE User Red Key 1 */ XSECURE_AES_KUP_KEY, /* KUP key */ XSECURE_AES_PUF_KEY, /* PUF key */ XSECURE_AES_USER_KEY_0, /* User Key 0 */ XSECURE_AES_USER_KEY_1, /* User Key 1 */ XSECURE_AES_USER_KEY_2, /* User Key 2 */ XSECURE_AES_USER_KEY_3, /* User Key 3 */ XSECURE_AES_USER_KEY_4, /* User Key 4 */ XSECURE_AES_USER_KEY_5, /* User Key 5 */ XSECURE_AES_USER_KEY_6, /* User Key 6 */ XSECURE_AES_USER_KEY_7, /* User Key 7 */ XSECURE_AES_EXPANDED_KEYS, /* Expanded keys */ XSECURE_AES_ALL_KEYS, /* AES All keys */ }; struct versal_payload { struct versal_mbox_mem input_cmd; struct versal_mbox_mem src; struct versal_mbox_mem dst; bool encrypt; }; struct versal_aad { struct versal_mbox_mem mem; }; struct versal_node { struct versal_payload payload; struct versal_aad aad; bool is_aad; STAILQ_ENTRY(versal_node) link; }; struct versal_init { uint32_t key_len; uint32_t operation; struct versal_mbox_mem key; struct versal_mbox_mem nonce; struct versal_mbox_mem init_buf; }; struct versal_ae_ctx { struct crypto_authenc_ctx a_ctx; }; struct versal_context_node { struct versal_ae_ctx *ctx; STAILQ_ENTRY(versal_context_node) link; }; enum engine_state { READY = 1, INIT = 2, FINALIZED = 3, }; static struct mutex engine_lock = MUTEX_INITIALIZER; static struct versal_engine { enum aes_key_src key_src; enum engine_state state; struct versal_init init; struct refcount refc; struct mutex *lock; /* protect the HW instance */ STAILQ_HEAD(authenc_context_list, versal_context_node) context_list; STAILQ_HEAD(authenc_replay_list, versal_node) replay_list; } engine = { .key_src = XSECURE_AES_USER_KEY_0, .lock = &engine_lock, }; static struct versal_ae_ctx *to_versal_ctx(struct crypto_authenc_ctx *ctx) { assert(ctx); return container_of(ctx, struct versal_ae_ctx, a_ctx); } static TEE_Result replay_init(void) { struct versal_cmd_args arg = { }; uint32_t err = 0; if (versal_crypto_request(VERSAL_AES_INIT, &arg, &err)) { EMSG("AES_INIT error"); return TEE_ERROR_GENERIC; } arg.data[arg.dlen++] = engine.init.key_len; arg.data[arg.dlen++] = engine.key_src; arg.ibuf[0].mem = engine.init.key; if (versal_crypto_request(VERSAL_AES_WRITE_KEY, &arg, &err)) { EMSG("AES_WRITE_KEY error"); return TEE_ERROR_GENERIC; } memset(&arg, 0, sizeof(arg)); arg.ibuf[0].mem = engine.init.init_buf; arg.ibuf[1].mem = engine.init.nonce; arg.ibuf[1].only_cache = true; if (versal_crypto_request(VERSAL_AES_OP_INIT, &arg, &err)) { EMSG("AES_OP_INIT error"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static TEE_Result replay_aad(struct versal_aad *p) { struct versal_cmd_args arg = { }; uint32_t err = 0; arg.data[arg.dlen++] = p->mem.len % 16 ? p->mem.alloc_len : p->mem.len; arg.ibuf[0].mem = p->mem; if (versal_crypto_request(VERSAL_AES_UPDATE_AAD, &arg, &err)) { EMSG("AES_UPDATE_AAD error: %s", versal_aes_error(err)); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static TEE_Result replay_payload(struct versal_payload *p) { enum versal_crypto_api id = VERSAL_AES_DECRYPT_UPDATE; struct versal_cmd_args arg = { }; uint32_t err = 0; arg.ibuf[0].mem = p->input_cmd; arg.ibuf[1].mem = p->dst; arg.ibuf[2].mem = p->src; if (p->encrypt) id = VERSAL_AES_ENCRYPT_UPDATE; if (versal_crypto_request(id, &arg, &err)) { EMSG("AES_UPDATE_PAYLOAD error: %s", versal_aes_error(err)); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static TEE_Result do_replay(void) { struct versal_node *node = NULL; TEE_Result ret = TEE_SUCCESS; ret = replay_init(); if (ret) return ret; STAILQ_FOREACH(node, &engine.replay_list, link) { if (node->is_aad) { ret = replay_aad(&node->aad); if (ret) return ret; } else { ret = replay_payload(&node->payload); if (ret) return ret; } } /* Engine has been init */ engine.state = INIT; return TEE_SUCCESS; } static bool engine_in_use(void) { if (STAILQ_EMPTY(&engine.context_list)) return false; return true; } static bool context_allowed(struct crypto_authenc_ctx *ctx) { struct versal_context_node *node = NULL; STAILQ_FOREACH(node, &engine.context_list, link) { if (node->ctx == to_versal_ctx(ctx)) return true; } return false; } static TEE_Result do_init(struct drvcrypt_authenc_init *dinit) { uint32_t key_len = XSECURE_AES_KEY_SIZE_128; struct versal_context_node *node = NULL; struct versal_aes_init *init = NULL; struct versal_mbox_mem init_buf = { }; struct versal_mbox_mem key = { }; struct versal_mbox_mem nonce = { }; struct versal_cmd_args arg = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; if (engine_in_use()) { EMSG("Versal: AES-GCM Engine busy"); return TEE_ERROR_BUSY; } if (dinit->key.length != 32 && dinit->key.length != 16) return TEE_ERROR_BAD_PARAMETERS; if (dinit->key.length == 32) key_len = XSECURE_AES_KEY_SIZE_256; if (engine.state != READY) return TEE_ERROR_BAD_STATE; /* Initialize the AES engine */ if (versal_crypto_request(VERSAL_AES_INIT, &arg, &err)) { EMSG("AES_INIT error: %s", versal_aes_error(err)); return TEE_ERROR_GENERIC; } /* Write the key */ versal_mbox_alloc(dinit->key.length, dinit->key.data, &key); arg.data[arg.dlen++] = key_len; arg.data[arg.dlen++] = engine.key_src; arg.ibuf[0].mem = key; if (versal_crypto_request(VERSAL_AES_WRITE_KEY, &arg, &err)) { EMSG("AES_WRITE_KEY error: %s", versal_aes_error(err)); ret = TEE_ERROR_GENERIC; goto error; } memset(&arg, 0, sizeof(arg)); /* Send the initialization structure */ versal_mbox_alloc(sizeof(*init), NULL, &init_buf); versal_mbox_alloc(dinit->nonce.length, dinit->nonce.data, &nonce); init = init_buf.buf; init->iv_addr = virt_to_phys(nonce.buf); init->operation = dinit->encrypt ? XSECURE_ENCRYPT : XSECURE_DECRYPT; init->key_src = engine.key_src; init->key_len = key_len; arg.ibuf[0].mem = init_buf; arg.ibuf[1].mem = nonce; arg.ibuf[1].only_cache = true; if (versal_crypto_request(VERSAL_AES_OP_INIT, &arg, &err)) { EMSG("AES_OP_INIT error: %s", versal_aes_error(err)); ret = TEE_ERROR_GENERIC; goto error; } node = calloc(1, sizeof(*node)); if (!node) { ret = TEE_ERROR_OUT_OF_MEMORY; goto error; } /* Save key context */ engine.init.operation = dinit->encrypt ? XSECURE_ENCRYPT : XSECURE_DECRYPT; engine.init.key_len = key_len; engine.init.init_buf = init_buf; engine.init.nonce = nonce; engine.init.key = key; /* Active context */ node->ctx = to_versal_ctx(dinit->ctx); STAILQ_INSERT_TAIL(&engine.context_list, node, link); /* Engine has been init*/ engine.state = INIT; return TEE_SUCCESS; error: free(key.buf); free(init_buf.buf); free(nonce.buf); return ret; } static TEE_Result do_update_aad(struct drvcrypt_authenc_update_aad *dupdate) { struct versal_cmd_args arg = { }; struct versal_mbox_mem p = { }; TEE_Result ret = TEE_SUCCESS; struct versal_node *node = NULL; uint32_t err = 0; /* This context has not been inited */ if (!context_allowed(dupdate->ctx)) return TEE_ERROR_BUSY; /* There is a copy of the context: don't allow updates, only finalize */ if (refcount_val(&engine.refc) > 1) return TEE_ERROR_BUSY; /* There was a copy of the context and it was finalized, then replay */ if (engine.state == FINALIZED) do_replay(); versal_mbox_alloc(dupdate->aad.length, dupdate->aad.data, &p); arg.data[arg.dlen++] = p.len % 16 ? p.alloc_len : p.len; arg.ibuf[0].mem = p; #if DEBUG_VERSAL_AES IMSG("versal: aad length - requested: %zu, sent to plm: %"PRIu32, dupdate->aad.length, arg.data[0]); #endif if (versal_crypto_request(VERSAL_AES_UPDATE_AAD, &arg, &err)) { EMSG("AES_UPDATE_AAD error: %s", versal_aes_error(err)); ret = TEE_ERROR_GENERIC; goto error; } node = calloc(1, sizeof(*node)); if (!node) { ret = TEE_ERROR_OUT_OF_MEMORY; goto error; } /* Save the context */ node->aad.mem = p; node->is_aad = true; STAILQ_INSERT_TAIL(&engine.replay_list, node, link); return TEE_SUCCESS; error: free(p.buf); return ret; } static TEE_Result update_payload(struct drvcrypt_authenc_update_payload *dupdate, bool is_last) { enum versal_crypto_api id = VERSAL_AES_DECRYPT_UPDATE; struct versal_aes_input_param *input = NULL; struct versal_mbox_mem input_cmd = { }; struct versal_mbox_mem p = { }; struct versal_mbox_mem q = { }; TEE_Result ret = TEE_SUCCESS; struct versal_cmd_args arg = { }; struct versal_node *node = NULL; uint32_t err = 0; if (!context_allowed(dupdate->ctx)) return TEE_ERROR_BUSY; if (!dupdate->src.length || dupdate->src.length % 4) { EMSG("Versal AES payload length not word aligned (len = %zu)", dupdate->src.length); return TEE_ERROR_BAD_PARAMETERS; } versal_mbox_alloc(dupdate->src.length, dupdate->src.data, &p); versal_mbox_alloc(dupdate->dst.length, NULL, &q); versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); input = input_cmd.buf; input->input_addr = virt_to_phys(p.buf); input->input_len = p.len % 16 ? p.alloc_len : p.len; input->is_last = is_last; arg.ibuf[0].mem = input_cmd; arg.ibuf[1].mem = q; arg.ibuf[2].mem = p; if (dupdate->encrypt) id = VERSAL_AES_ENCRYPT_UPDATE; #if DEBUG_VERSAL_AES IMSG("versal: payload length - requested %zu, sent to plm: %"PRIu32, dupdate->src.length, input->input_len); IMSG("versal: destination length - %zu ", dupdate->dst.length); #endif if (versal_crypto_request(id, &arg, &err)) { EMSG("AES_UPDATE_PAYLOAD error: %s", versal_aes_error(err)); ret = TEE_ERROR_GENERIC; goto out; } if (dupdate->dst.data) memcpy(dupdate->dst.data, q.buf, dupdate->dst.length); if (!is_last) { node = calloc(1, sizeof(*node)); if (!node) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } node->is_aad = false; node->payload.dst = q; node->payload.src = p; node->payload.input_cmd = input_cmd; node->payload.encrypt = dupdate->encrypt; STAILQ_INSERT_TAIL(&engine.replay_list, node, link); return TEE_SUCCESS; } out: free(p.buf); free(q.buf); free(input_cmd.buf); return ret; } static TEE_Result do_update_payload(struct drvcrypt_authenc_update_payload *p) { TEE_Result ret = TEE_SUCCESS; if (!context_allowed(p->ctx)) return TEE_ERROR_BUSY; /* * If there is a copy, we don't allow updates until one of the copies * has been deleted */ if (refcount_val(&engine.refc) > 1) return TEE_ERROR_BUSY; /* * If there was a copy and it was finalized, we need to replay before * we can update; do not clear the list so the state can be copied */ if (engine.state == FINALIZED) { ret = do_replay(); if (ret) return ret; } return update_payload(p, false); } static TEE_Result do_enc_final(struct drvcrypt_authenc_final *dfinal) { struct drvcrypt_authenc_update_payload last = { }; struct versal_cmd_args arg = { }; struct versal_mbox_mem p = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; if (!context_allowed(dfinal->ctx)) return TEE_ERROR_BUSY; if (engine.state == FINALIZED) { DMSG("Operation was already finalized"); ret = do_replay(); if (ret) return ret; } if (engine.state != INIT) panic(); last.ctx = dfinal->ctx; last.dst = dfinal->dst; last.encrypt = true; last.src = dfinal->src; ret = update_payload(&last, true); if (ret) return ret; memcpy(dfinal->dst.data, last.dst.data, dfinal->dst.length); versal_mbox_alloc(GCM_TAG_LEN, NULL, &p); arg.ibuf[0].mem = p; if (versal_crypto_request(VERSAL_AES_ENCRYPT_FINAL, &arg, &err)) { EMSG("AES_ENCRYPT_FINAL error: %s", versal_aes_error(err)); ret = TEE_ERROR_GENERIC; goto out; } memcpy(dfinal->tag.data, p.buf, GCM_TAG_LEN); dfinal->tag.length = GCM_TAG_LEN; out: free(p.buf); if (refcount_val(&engine.refc) > 1) engine.state = FINALIZED; else engine.state = READY; return ret; } static TEE_Result do_dec_final(struct drvcrypt_authenc_final *dfinal) { struct drvcrypt_authenc_update_payload last = { }; struct versal_cmd_args arg = { }; struct versal_mbox_mem p = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; if (!context_allowed(dfinal->ctx)) return TEE_ERROR_BUSY; if (engine.state == FINALIZED) { DMSG("Operation was already finalized"); ret = do_replay(); if (ret) return ret; } if (engine.state != INIT) panic(); last.encrypt = false; last.ctx = dfinal->ctx; last.dst = dfinal->dst; last.src = dfinal->src; ret = update_payload(&last, true); if (ret) return ret; versal_mbox_alloc(dfinal->tag.length, dfinal->tag.data, &p); arg.ibuf[0].mem = p; if (versal_crypto_request(VERSAL_AES_DECRYPT_FINAL, &arg, &err)) { EMSG("AES_DECRYPT_FINAL error: %s", versal_aes_error(err)); ret = TEE_ERROR_GENERIC; goto out; } memcpy(dfinal->dst.data, last.dst.data, dfinal->dst.length); memcpy(dfinal->tag.data, p.buf, GCM_TAG_LEN); dfinal->tag.length = GCM_TAG_LEN; out: free(p.buf); if (refcount_val(&engine.refc) > 1) engine.state = FINALIZED; else engine.state = READY; return ret; } static void do_final(void *ctx __unused) { } static void do_free(void *ctx) { struct versal_ae_ctx *c = to_versal_ctx(ctx); struct versal_node *next = NULL; struct versal_node *node = NULL; struct versal_context_node *ctx_next = NULL; struct versal_context_node *ctx_node = NULL; bool release = false; if (refcount_dec(&engine.refc)) { /* this is a final release */ release = true; refcount_set(&engine.refc, 1); engine.state = READY; free(engine.init.init_buf.buf); free(engine.init.nonce.buf); free(engine.init.key.buf); memset(&engine.init, 0, sizeof(engine.init)); STAILQ_FOREACH_SAFE(node, &engine.replay_list, link, next) { STAILQ_REMOVE(&engine.replay_list, node, versal_node, link); if (node->is_aad) { free(node->aad.mem.buf); } else { free(node->payload.dst.buf); free(node->payload.src.buf); free(node->payload.input_cmd.buf); } free(node); } } STAILQ_FOREACH_SAFE(ctx_node, &engine.context_list, link, ctx_next) { if (c == ctx_node->ctx) { STAILQ_REMOVE(&engine.context_list, ctx_node, versal_context_node, link); free(ctx_node); } } if (release && engine_in_use()) panic(); free(c); } static void do_copy_state(void *dst_ctx, void *src_ctx) { struct versal_context_node *node = NULL; STAILQ_FOREACH(node, &engine.context_list, link) { if (node->ctx != to_versal_ctx(src_ctx)) continue; /* * The running context has been copied: from now on we can only * finalize any of the contexts until there is only one active * again. */ node = calloc(1, sizeof(*node)); if (!node) panic(); node->ctx = to_versal_ctx(dst_ctx); STAILQ_INSERT_TAIL(&engine.context_list, node, link); /* number of active contexts */ refcount_inc(&engine.refc); return; } panic(); } static TEE_Result do_allocate(void **ctx, uint32_t algo) { struct versal_ae_ctx *c = NULL; if (algo != TEE_ALG_AES_GCM) return TEE_ERROR_NOT_IMPLEMENTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; *ctx = &c->a_ctx; return TEE_SUCCESS; } static TEE_Result do_update_payload_locked(struct drvcrypt_authenc_update_payload *p) { TEE_Result ret = TEE_SUCCESS; mutex_lock(engine.lock); ret = do_update_payload(p); mutex_unlock(engine.lock); return ret; } static TEE_Result do_update_aad_locked(struct drvcrypt_authenc_update_aad *p) { TEE_Result ret = TEE_SUCCESS; mutex_lock(engine.lock); ret = do_update_aad(p); mutex_unlock(engine.lock); return ret; } static void do_copy_state_locked(void *dst, void *src) { mutex_lock(engine.lock); do_copy_state(dst, src); mutex_unlock(engine.lock); } static TEE_Result do_enc_final_locked(struct drvcrypt_authenc_final *p) { TEE_Result ret = TEE_SUCCESS; mutex_lock(engine.lock); ret = do_enc_final(p); mutex_unlock(engine.lock); return ret; } static TEE_Result do_dec_final_locked(struct drvcrypt_authenc_final *p) { TEE_Result ret = TEE_SUCCESS; mutex_lock(engine.lock); ret = do_dec_final(p); mutex_unlock(engine.lock); return ret; } static void do_free_locked(void *p) { mutex_lock(engine.lock); do_free(p); mutex_unlock(engine.lock); } static TEE_Result do_init_locked(struct drvcrypt_authenc_init *p) { TEE_Result ret = TEE_SUCCESS; mutex_lock(engine.lock); ret = do_init(p); mutex_unlock(engine.lock); return ret; } static struct drvcrypt_authenc versal_authenc = { .update_payload = do_update_payload_locked, .update_aad = do_update_aad_locked, .copy_state = do_copy_state_locked, .enc_final = do_enc_final_locked, .dec_final = do_dec_final_locked, .free_ctx = do_free_locked, .alloc_ctx = do_allocate, .init = do_init_locked, .final = do_final, }; static TEE_Result enable_secure_status(void) { /* Once Linux has support, we need to reserve the device */ return TEE_SUCCESS; } static TEE_Result versal_register_authenc(void) { TEE_Result ret = TEE_SUCCESS; ret = drvcrypt_register_authenc(&versal_authenc); if (ret) return ret; if (engine.key_src < XSECURE_AES_USER_KEY_0 || engine.key_src > XSECURE_AES_USER_KEY_7) return TEE_ERROR_GENERIC; engine.state = READY; STAILQ_INIT(&engine.replay_list); STAILQ_INIT(&engine.context_list); refcount_set(&engine.refc, 1); return enable_secure_status(); } driver_init_late(versal_register_authenc); optee_os-4.3.0/core/drivers/crypto/versal/crypto.mk000066400000000000000000000004331464416617300224420ustar00rootroot00000000000000ifeq ($(CFG_VERSAL_CRYPTO_DRIVER),y) # Enable the crypto driver $(call force,CFG_CRYPTO_DRIVER,y) CFG_CRYPTO_DRIVER_DEBUG ?= 0 $(call force,CFG_CRYPTO_DRV_ACIPHER,y) $(call force,CFG_CRYPTO_DRV_ECC,y) $(call force,CFG_CRYPTO_DRV_RSA,y) $(call force,CFG_CRYPTO_DRV_AUTHENC,y) endif optee_os-4.3.0/core/drivers/crypto/versal/ecc.c000066400000000000000000000267671464416617300215110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022. * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #include #include /* AMD/Xilinx Versal's Known Answer Tests */ #define XSECURE_ECDSA_KAT_NIST_P384 0 #define XSECURE_ECDSA_KAT_NIST_P521 2 /* Software based ECDSA operations */ static const struct crypto_ecc_keypair_ops *pair_ops; static const struct crypto_ecc_public_ops *pub_ops; enum versal_ecc_err { KAT_KEY_NOTVALID_ERROR = 0xC0, KAT_FAILED_ERROR, NON_SUPPORTED_CURVE, KEY_ZERO, KEY_WRONG_ORDER, KEY_NOT_ON_CURVE, BAD_SIGN, GEN_SIGN_INCORRECT_HASH_LEN, VER_SIGN_INCORRECT_HASH_LEN, GEN_SIGN_BAD_RAND_NUM, GEN_KEY_ERR, INVALID_PARAM, VER_SIGN_R_ZERO, VER_SIGN_S_ZERO, VER_SIGN_R_ORDER_ERROR, VER_SIGN_S_ORDER_ERROR, KAT_INVLD_CRV_ERROR, }; #define VERSAL_ECC_ERROR(m) { .error = (m), .name = TO_STR(m) } static const char *versal_ecc_error(uint8_t err) { struct { enum versal_ecc_err error; const char *name; } elist[] = { VERSAL_ECC_ERROR(KAT_KEY_NOTVALID_ERROR), VERSAL_ECC_ERROR(KAT_FAILED_ERROR), VERSAL_ECC_ERROR(NON_SUPPORTED_CURVE), VERSAL_ECC_ERROR(KEY_ZERO), VERSAL_ECC_ERROR(KEY_WRONG_ORDER), VERSAL_ECC_ERROR(KEY_NOT_ON_CURVE), VERSAL_ECC_ERROR(BAD_SIGN), VERSAL_ECC_ERROR(GEN_SIGN_INCORRECT_HASH_LEN), VERSAL_ECC_ERROR(VER_SIGN_INCORRECT_HASH_LEN), VERSAL_ECC_ERROR(GEN_SIGN_BAD_RAND_NUM), VERSAL_ECC_ERROR(GEN_KEY_ERR), VERSAL_ECC_ERROR(INVALID_PARAM), VERSAL_ECC_ERROR(VER_SIGN_R_ZERO), VERSAL_ECC_ERROR(VER_SIGN_S_ZERO), VERSAL_ECC_ERROR(VER_SIGN_R_ORDER_ERROR), VERSAL_ECC_ERROR(VER_SIGN_S_ORDER_ERROR), VERSAL_ECC_ERROR(KAT_INVLD_CRV_ERROR), }; if (err <= KAT_INVLD_CRV_ERROR && err >= KAT_KEY_NOTVALID_ERROR) { if (elist[err - KAT_KEY_NOTVALID_ERROR].name) return elist[err - KAT_KEY_NOTVALID_ERROR].name; return "Invalid"; } return "Unknown"; } static TEE_Result ecc_get_key_size(uint32_t curve, size_t *bytes, size_t *bits) { switch (curve) { case TEE_ECC_CURVE_NIST_P384: *bits = 384; *bytes = 48; break; case TEE_ECC_CURVE_NIST_P521: *bits = 521; *bytes = 66; break; default: return TEE_ERROR_NOT_SUPPORTED; } return TEE_SUCCESS; } static void memcpy_swp(uint8_t *to, const uint8_t *from, size_t len) { size_t i = 0; for (i = 0; i < len; i++) to[i] = from[len - 1 - i]; } static void crypto_bignum_bn2bin_eswap(uint32_t curve, struct bignum *from, uint8_t *to) { uint8_t pad[66] = { 0 }; size_t len = crypto_bignum_num_bytes(from); size_t bytes = 0; size_t bits = 0; if (ecc_get_key_size(curve, &bytes, &bits)) panic(); crypto_bignum_bn2bin(from, pad + bytes - len); memcpy_swp(to, pad, bytes); } static TEE_Result ecc_prepare_msg(uint32_t algo, const uint8_t *msg, size_t msg_len, struct versal_mbox_mem *p) { uint8_t swp[TEE_SHA512_HASH_SIZE + 2] = { 0 }; size_t len = 0; if (msg_len > TEE_SHA512_HASH_SIZE + 2) return TEE_ERROR_BAD_PARAMETERS; if (algo == TEE_ALG_ECDSA_SHA384) len = TEE_SHA384_HASH_SIZE; else if (algo == TEE_ALG_ECDSA_SHA512) len = TEE_SHA512_HASH_SIZE + 2; else return TEE_ERROR_NOT_SUPPORTED; /* Swap the hash/message and pad if necessary */ memcpy_swp(swp, msg, msg_len); return versal_mbox_alloc(len, swp, p); } static TEE_Result verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result ret = TEE_SUCCESS; struct versal_ecc_verify_param *cmd = NULL; struct versal_cmd_args arg = { }; struct versal_mbox_mem x = { }; struct versal_mbox_mem s = { }; struct versal_mbox_mem p = { }; struct versal_mbox_mem cmd_buf = { }; uint32_t err = 0; size_t bytes = 0; size_t bits = 0; if (sig_len % 2) return TEE_ERROR_SIGNATURE_INVALID; ret = ecc_get_key_size(key->curve, &bytes, &bits); if (ret != TEE_SUCCESS) { if (ret != TEE_ERROR_NOT_SUPPORTED) return ret; /* Fallback to software */ return pub_ops->verify(algo, key, msg, msg_len, sig, sig_len); } ret = ecc_prepare_msg(algo, msg, msg_len, &p); if (ret) return ret; versal_mbox_alloc(bytes * 2, NULL, &x); crypto_bignum_bn2bin_eswap(key->curve, key->x, x.buf); crypto_bignum_bn2bin_eswap(key->curve, key->y, (uint8_t *)x.buf + bytes); /* Validate the public key for the curve */ arg.data[0] = key->curve; arg.dlen = 1; arg.ibuf[0].mem = x; if (versal_crypto_request(VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, &arg, &err)) { EMSG("Versal ECC: %s", versal_ecc_error(err)); ret = TEE_ERROR_GENERIC; goto out; } memset(&arg, 0, sizeof(arg)); versal_mbox_alloc(sig_len, NULL, &s); /* Swap the {R,S} components */ memcpy_swp(s.buf, sig, sig_len / 2); memcpy_swp((uint8_t *)s.buf + sig_len / 2, sig + sig_len / 2, sig_len / 2); versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); cmd = cmd_buf.buf; cmd->signature_addr = virt_to_phys(s.buf); cmd->pub_key_addr = virt_to_phys(x.buf); cmd->hash_addr = virt_to_phys(p.buf); cmd->hash_len = p.len; cmd->curve = key->curve; arg.ibuf[0].mem = cmd_buf; arg.ibuf[1].mem = p; arg.ibuf[1].only_cache = true; arg.ibuf[2].mem = x; arg.ibuf[3].mem = s; if (versal_crypto_request(VERSAL_ELLIPTIC_VERIFY_SIGN, &arg, &err)) { EMSG("Versal ECC: %s", versal_ecc_error(err)); ret = TEE_ERROR_GENERIC; } out: free(p.buf); free(x.buf); free(s.buf); free(cmd); return ret; } static TEE_Result sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { struct versal_ecc_sign_param *cmd = NULL; struct versal_mbox_mem cmd_buf = { }; struct ecc_keypair ephemeral = { }; struct versal_cmd_args arg = { }; struct versal_mbox_mem p = { }; struct versal_mbox_mem k = { }; struct versal_mbox_mem d = { }; struct versal_mbox_mem s = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; size_t bytes = 0; size_t bits = 0; ret = ecc_get_key_size(key->curve, &bytes, &bits); if (ret != TEE_SUCCESS) { if (ret != TEE_ERROR_NOT_SUPPORTED) return ret; /* Fallback to software */ return pair_ops->sign(algo, key, msg, msg_len, sig, sig_len); } /* Hash and update the length */ ret = ecc_prepare_msg(algo, msg, msg_len, &p); if (ret) return ret; /* Ephemeral private key */ ret = drvcrypt_asym_alloc_ecc_keypair(&ephemeral, TEE_TYPE_ECDSA_KEYPAIR, bits); if (ret) { EMSG("Versal, can't allocate the ephemeral key"); return ret; } ephemeral.curve = key->curve; ret = crypto_acipher_gen_ecc_key(&ephemeral, bits); if (ret) { EMSG("Versal, can't generate the ephemeral key"); return ret; } versal_mbox_alloc(bytes, NULL, &k); crypto_bignum_bn2bin_eswap(key->curve, ephemeral.d, k.buf); crypto_bignum_free(&ephemeral.d); crypto_bignum_free(&ephemeral.x); crypto_bignum_free(&ephemeral.y); /* Private key*/ versal_mbox_alloc(bytes, NULL, &d); crypto_bignum_bn2bin_eswap(key->curve, key->d, d.buf); /* Signature */ versal_mbox_alloc(*sig_len, NULL, &s); /* IPI command */ versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); cmd = cmd_buf.buf; cmd->priv_key_addr = virt_to_phys(d.buf); cmd->epriv_key_addr = virt_to_phys(k.buf); cmd->hash_addr = virt_to_phys(p.buf); cmd->hash_len = p.len; cmd->curve = key->curve; arg.ibuf[0].mem = cmd_buf; arg.ibuf[1].mem = s; arg.ibuf[2].mem = k; arg.ibuf[3].mem = d; arg.ibuf[4].mem = p; if (versal_crypto_request(VERSAL_ELLIPTIC_GENERATE_SIGN, &arg, &err)) { EMSG("Versal ECC: %s", versal_ecc_error(err)); ret = TEE_ERROR_GENERIC; goto out; } *sig_len = 2 * bytes; /* Swap the {R,S} components */ memcpy_swp(sig, s.buf, *sig_len / 2); memcpy_swp(sig + *sig_len / 2, (uint8_t *)s.buf + *sig_len / 2, *sig_len / 2); out: free(cmd); free(k.buf); free(p.buf); free(s.buf); free(d.buf); return ret; } static TEE_Result shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, size_t *secret_len) { return pair_ops->shared_secret(private_key, public_key, secret, secret_len); } static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata) { return shared_secret(sdata->key_priv, sdata->key_pub, sdata->secret.data, &sdata->secret.length); } static TEE_Result do_sign(struct drvcrypt_sign_data *sdata) { return sign(sdata->algo, sdata->key, sdata->message.data, sdata->message.length, sdata->signature.data, &sdata->signature.length); } static TEE_Result do_verify(struct drvcrypt_sign_data *sdata) { return verify(sdata->algo, sdata->key, sdata->message.data, sdata->message.length, sdata->signature.data, sdata->signature.length); } static TEE_Result do_gen_keypair(struct ecc_keypair *s, size_t size_bits) { /* * Versal requires little endian so need to memcpy_swp on Versal IP ops. * We chose not to do it here because some tests might be using * their own keys */ return pair_ops->generate(s, size_bits); } static TEE_Result do_alloc_keypair(struct ecc_keypair *s, uint32_t type, size_t size_bits) { TEE_Result ret = TEE_SUCCESS; /* This driver only supports ECDH/ECDSA */ if (type != TEE_TYPE_ECDSA_KEYPAIR && type != TEE_TYPE_ECDH_KEYPAIR) return TEE_ERROR_NOT_IMPLEMENTED; ret = crypto_asym_alloc_ecc_keypair(s, TEE_TYPE_ECDSA_KEYPAIR, size_bits); if (ret) return TEE_ERROR_NOT_IMPLEMENTED; /* * Ignore the software operations, the crypto API will populate * this interface. */ s->ops = NULL; return TEE_SUCCESS; } static TEE_Result do_alloc_publickey(struct ecc_public_key *s, uint32_t type, size_t size_bits) { TEE_Result ret = TEE_SUCCESS; /* This driver only supports ECDH/ECDSA */ if (type != TEE_TYPE_ECDSA_PUBLIC_KEY && type != TEE_TYPE_ECDH_PUBLIC_KEY) return TEE_ERROR_NOT_IMPLEMENTED; ret = crypto_asym_alloc_ecc_public_key(s, TEE_TYPE_ECDSA_PUBLIC_KEY, size_bits); if (ret) return TEE_ERROR_NOT_IMPLEMENTED; /* * Ignore the software operations, the crypto API will populate * this interface. */ s->ops = NULL; return TEE_SUCCESS; } static void do_free_publickey(struct ecc_public_key *s) { return pub_ops->free(s); } static struct drvcrypt_ecc driver_ecc = { .shared_secret = do_shared_secret, .alloc_publickey = do_alloc_publickey, .free_publickey = do_free_publickey, .alloc_keypair = do_alloc_keypair, .gen_keypair = do_gen_keypair, .verify = do_verify, .sign = do_sign, }; static TEE_Result ecc_init(void) { struct versal_cmd_args arg = { }; uint32_t err = 0; arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P384; if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) { EMSG("Versal KAG NIST_P384: %s", versal_ecc_error(err)); return TEE_ERROR_GENERIC; } /* Clean previous request */ arg.dlen = 0; arg.data[arg.dlen++] = XSECURE_ECDSA_KAT_NIST_P521; if (versal_crypto_request(VERSAL_ELLIPTIC_KAT, &arg, &err)) { EMSG("Versal KAG NIST_P521 %s", versal_ecc_error(err)); return TEE_ERROR_GENERIC; } pair_ops = crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDSA_KEYPAIR); if (!pair_ops) return TEE_ERROR_GENERIC; pub_ops = crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDSA_PUBLIC_KEY); if (!pub_ops) return TEE_ERROR_GENERIC; /* This driver supports both ECDH and ECDSA */ assert((pub_ops == crypto_asym_get_ecc_public_ops(TEE_TYPE_ECDH_PUBLIC_KEY)) && (pair_ops == crypto_asym_get_ecc_keypair_ops(TEE_TYPE_ECDH_KEYPAIR))); return drvcrypt_register_ecc(&driver_ecc); } driver_init(ecc_init); optee_os-4.3.0/core/drivers/crypto/versal/include/000077500000000000000000000000001464416617300222145ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/crypto/versal/include/ipi.h000066400000000000000000000036641464416617300231570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2022 * Author: Jorge Ramirez */ #ifndef IPI_H #define IPI_H #include struct versal_rsa_input_param { uint64_t key_addr; uint64_t data_addr; uint32_t key_len; }; struct versal_rsa_sign_param { uint64_t sign_addr; uint64_t hash_addr; uint32_t hash_len; }; struct versal_ecc_sign_param { uint64_t hash_addr; uint64_t priv_key_addr; uint64_t epriv_key_addr; uint32_t curve; uint32_t hash_len; }; struct versal_ecc_verify_param { uint64_t hash_addr; uint64_t pub_key_addr; uint64_t signature_addr; uint32_t curve; uint32_t hash_len; }; enum versal_aes_operation { VERSAL_AES_ENCRYPT, VERSAL_AES_DECRYPT }; struct versal_aes_init { uint64_t iv_addr; uint32_t operation; uint32_t key_src; uint32_t key_len; }; struct versal_aes_input_param { uint64_t input_addr; uint32_t input_len; uint32_t is_last; }; enum versal_crypto_api { VERSAL_FEATURES = 0U, VERSAL_RSA_SIGN_VERIFY, VERSAL_RSA_PUBLIC_ENCRYPT, VERSAL_RSA_PRIVATE_DECRYPT, VERSAL_RSA_KAT, VERSAL_SHA3_UPDATE = 32U, VERSAL_SHA3_KAT, VERSAL_ELLIPTIC_GENERATE_PUBLIC_KEY = 64U, VERSAL_ELLIPTIC_GENERATE_SIGN, VERSAL_ELLIPTIC_VALIDATE_PUBLIC_KEY, VERSAL_ELLIPTIC_VERIFY_SIGN, VERSAL_ELLIPTIC_KAT, VERSAL_AES_INIT = 96U, VERSAL_AES_OP_INIT, VERSAL_AES_UPDATE_AAD, VERSAL_AES_ENCRYPT_UPDATE, VERSAL_AES_ENCRYPT_FINAL, VERSAL_AES_DECRYPT_UPDATE, VERSAL_AES_DECRYPT_FINAL, VERSAL_AES_KEY_ZERO, VERSAL_AES_WRITE_KEY, VERSAL_AES_LOCK_USER_KEY, VERSAL_AES_KEK_DECRYPT, VERSAL_AES_SET_DPA_CM, VERSAL_AES_DECRYPT_KAT, VERSAL_AES_DECRYPT_CM_KAT, VERSAL_CRYPTO_API_MAX }; #define VERSAL_MAX_IPI_REGS 6 struct versal_cmd_args { uint32_t data[VERSAL_MAX_IPI_REGS]; size_t dlen; struct versal_ipi_buf ibuf[VERSAL_MAX_IPI_BUF]; }; TEE_Result versal_crypto_request(enum versal_crypto_api id, struct versal_cmd_args *arg, uint32_t *err); #endif optee_os-4.3.0/core/drivers/crypto/versal/ipi.c000066400000000000000000000046271464416617300215270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022 * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #define SEC_MODULE_SHIFT 8 #define SEC_MODULE_ID 5 #define CRYPTO_API_ID(__x) ((SEC_MODULE_ID << SEC_MODULE_SHIFT) | (__x)) static TEE_Result versal_sha3_request(enum versal_crypto_api id, struct versal_cmd_args *arg) { struct versal_ipi_cmd cmd = { }; uint32_t a = 0; uint32_t b = 0; cmd.data[0] = CRYPTO_API_ID(id); if (arg->data[0]) { /* write */ reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); cmd.data[1] = a; cmd.data[2] = b; cmd.data[3] = arg->data[0]; cmd.ibuf[0].mem = arg->ibuf[0].mem; } else { /* read */ reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); cmd.data[4] = a; cmd.data[5] = b; cmd.ibuf[0].mem = arg->ibuf[0].mem; } return versal_mbox_notify(&cmd, NULL, NULL); } static TEE_Result versal_aes_update_aad_request(enum versal_crypto_api id, struct versal_cmd_args *arg) { struct versal_ipi_cmd cmd = { }; uint32_t a = 0; uint32_t b = 0; reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); cmd.data[0] = CRYPTO_API_ID(id); cmd.data[1] = a; cmd.data[2] = b; cmd.data[3] = arg->data[0]; cmd.ibuf[0].mem = arg->ibuf[0].mem; return versal_mbox_notify(&cmd, NULL, NULL); } TEE_Result versal_crypto_request(enum versal_crypto_api id, struct versal_cmd_args *arg, uint32_t *err) { struct versal_ipi_cmd cmd = { }; uint32_t a = 0; uint32_t b = 0; size_t i = 0; if (id == VERSAL_SHA3_UPDATE) return versal_sha3_request(id, arg); if (id == VERSAL_AES_UPDATE_AAD) return versal_aes_update_aad_request(id, arg); cmd.data[0] = CRYPTO_API_ID(id); for (i = 1; i < arg->dlen + 1; i++) cmd.data[i] = arg->data[i - 1]; /* src */ if (!arg->ibuf[0].mem.buf) goto notify; reg_pair_from_64(virt_to_phys(arg->ibuf[0].mem.buf), &b, &a); cmd.data[i++] = a; cmd.data[i++] = b; /* dst */ if (!arg->ibuf[1].mem.buf) goto cache; if (arg->ibuf[1].only_cache) goto cache; reg_pair_from_64(virt_to_phys(arg->ibuf[1].mem.buf), &b, &a); cmd.data[i++] = a; cmd.data[i++] = b; cache: for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) cmd.ibuf[i].mem = arg->ibuf[i].mem; notify: return versal_mbox_notify(&cmd, NULL, err); } optee_os-4.3.0/core/drivers/crypto/versal/rsa.c000066400000000000000000000231641464416617300215300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022. * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #define RSA_MAX_PRIV_EXP_LEN 512 #define RSA_MAX_PUB_EXP_LEN 4 #define RSA_MAX_MOD_LEN 512 static void crypto_bignum_bn2bin_pad(size_t size, struct bignum *from, uint8_t *to) { size_t len = crypto_bignum_num_bytes(from); crypto_bignum_bn2bin(from, to + size - len); } static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data) { struct rsa_public_key *p = rsa_data->key.key; struct versal_rsa_input_param *cmd = NULL; struct versal_mbox_mem cmd_buf = { }; struct versal_mbox_mem cipher = { }; struct versal_mbox_mem key = { }; struct versal_mbox_mem msg = { }; struct versal_cmd_args arg = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; switch (rsa_data->rsa_id) { case DRVCRYPT_RSA_PKCS_V1_5: return sw_crypto_acipher_rsaes_encrypt(rsa_data->algo, rsa_data->key.key, rsa_data->label.data, rsa_data->label.length, rsa_data->mgf_algo, rsa_data->message.data, rsa_data->message.length, rsa_data->cipher.data, &rsa_data->cipher.length); case DRVCRYPT_RSA_OAEP: return sw_crypto_acipher_rsaes_encrypt(rsa_data->algo, rsa_data->key.key, rsa_data->label.data, rsa_data->label.length, rsa_data->mgf_algo, rsa_data->message.data, rsa_data->message.length, rsa_data->cipher.data, &rsa_data->cipher.length); case DRVCRYPT_RSA_NOPAD: return sw_crypto_acipher_rsanopad_encrypt(rsa_data->key.key, rsa_data->message.data, rsa_data->message.length, rsa_data->cipher.data, &rsa_data->cipher.length); case DRVCRYPT_RSASSA_PKCS_V1_5: assert(rsa_data->hash_algo != TEE_ALG_SHA1); assert(rsa_data->key.n_size != 128); break; case DRVCRYPT_RSASSA_PSS: default: assert(0); } versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PUB_EXP_LEN, NULL, &key); crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); crypto_bignum_bn2bin_pad(RSA_MAX_PUB_EXP_LEN, p->e, (uint8_t *)key.buf + RSA_MAX_MOD_LEN); versal_mbox_alloc(rsa_data->message.length, rsa_data->message.data, &msg); versal_mbox_alloc(rsa_data->cipher.length, NULL, &cipher); versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); cmd = cmd_buf.buf; cmd->key_len = rsa_data->key.n_size; cmd->data_addr = virt_to_phys(msg.buf); cmd->key_addr = virt_to_phys(key.buf); arg.ibuf[0].mem = cmd_buf; arg.ibuf[1].mem = cipher; arg.ibuf[2].mem = msg; arg.ibuf[3].mem = key; if (versal_crypto_request(VERSAL_RSA_PUBLIC_ENCRYPT, &arg, &err)) { EMSG("Versal RSA: encrypt: error 0x%x [id:0x%x, len:%zu]", err, rsa_data->rsa_id, rsa_data->key.n_size); if (rsa_data->rsa_id == DRVCRYPT_RSASSA_PKCS_V1_5) ret = TEE_ERROR_SIGNATURE_INVALID; else ret = TEE_ERROR_GENERIC; } if (!ret) { rsa_data->cipher.length = rsa_data->key.n_size; memcpy(rsa_data->cipher.data, cipher.buf, rsa_data->key.n_size); } free(cipher.buf); free(cmd); free(msg.buf); free(key.buf); return ret; } static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data) { struct versal_rsa_input_param *cmd = NULL; struct rsa_keypair *p = rsa_data->key.key; struct versal_mbox_mem cmd_buf = { }; struct versal_mbox_mem cipher = { }; struct versal_mbox_mem key = { }; struct versal_mbox_mem msg = { }; struct versal_cmd_args arg = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; switch (rsa_data->rsa_id) { case DRVCRYPT_RSA_PKCS_V1_5: return sw_crypto_acipher_rsaes_decrypt(rsa_data->algo, rsa_data->key.key, rsa_data->label.data, rsa_data->label.length, rsa_data->mgf_algo, rsa_data->cipher.data, rsa_data->cipher.length, rsa_data->message.data, &rsa_data->message.length); case DRVCRYPT_RSA_OAEP: return sw_crypto_acipher_rsaes_decrypt(rsa_data->algo, rsa_data->key.key, rsa_data->label.data, rsa_data->label.length, rsa_data->mgf_algo, rsa_data->cipher.data, rsa_data->cipher.length, rsa_data->message.data, &rsa_data->message.length); case DRVCRYPT_RSA_NOPAD: return sw_crypto_acipher_rsanopad_decrypt(rsa_data->key.key, rsa_data->cipher.data, rsa_data->cipher.length, rsa_data->message.data, &rsa_data->message.length); case DRVCRYPT_RSASSA_PKCS_V1_5: assert(rsa_data->hash_algo != TEE_ALG_SHA1); assert(rsa_data->key.n_size != 128); break; case DRVCRYPT_RSASSA_PSS: default: assert(0); } versal_mbox_alloc(RSA_MAX_MOD_LEN + RSA_MAX_PRIV_EXP_LEN, NULL, &key); crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->n, key.buf); crypto_bignum_bn2bin_pad(rsa_data->key.n_size, p->d, (uint8_t *)key.buf + RSA_MAX_MOD_LEN); versal_mbox_alloc(rsa_data->cipher.length, rsa_data->cipher.data, &cipher); versal_mbox_alloc(rsa_data->message.length, NULL, &msg); versal_mbox_alloc(sizeof(*cmd), NULL, &cmd_buf); cmd = cmd_buf.buf; cmd->key_len = rsa_data->key.n_size; cmd->data_addr = virt_to_phys(cipher.buf); cmd->key_addr = virt_to_phys(key.buf); arg.ibuf[0].mem = cmd_buf; arg.ibuf[1].mem = msg; arg.ibuf[2].mem = cipher; arg.ibuf[3].mem = key; if (versal_crypto_request(VERSAL_RSA_PRIVATE_DECRYPT, &arg, &err)) { EMSG("Versal RSA: decrypt: error 0x%x [id:0x%x, len:%zu]", err, rsa_data->rsa_id, rsa_data->key.n_size); ret = TEE_ERROR_GENERIC; } if (!ret) { rsa_data->message.length = rsa_data->key.n_size; memcpy(rsa_data->message.data, msg.buf, rsa_data->key.n_size); } free(cipher.buf); free(cmd); free(key.buf); free(msg.buf); return ret; } static TEE_Result do_ssa_sign(struct drvcrypt_rsa_ssa *p) { switch (p->algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: if (p->key.n_size != 128) { /* use DRVCRYPT_RSASSA_PKCS_V1_5, decrypt */ return TEE_ERROR_NOT_IMPLEMENTED; } return sw_crypto_acipher_rsassa_sign(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, &p->signature.length); case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: return sw_crypto_acipher_rsassa_sign(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, &p->signature.length); case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return sw_crypto_acipher_rsassa_sign(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, &p->signature.length); default: break; } return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result do_ssa_verify(struct drvcrypt_rsa_ssa *p) { switch (p->algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: if (p->key.n_size != 128) { /* use DRVCRYPT_RSASSA_PKCS_V1_5, encrypt */ return TEE_ERROR_NOT_IMPLEMENTED; } return sw_crypto_acipher_rsassa_verify(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, p->signature.length); case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: return sw_crypto_acipher_rsassa_verify(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, p->signature.length); case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: return sw_crypto_acipher_rsassa_verify(p->algo, p->key.key, p->salt_len, p->message.data, p->message.length, p->signature.data, p->signature.length); default: break; } return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result do_gen_keypair(struct rsa_keypair *s, size_t size_bits) { return sw_crypto_acipher_gen_rsa_key(s, size_bits); } static TEE_Result do_alloc_keypair(struct rsa_keypair *s, size_t size_bits) { return sw_crypto_acipher_alloc_rsa_keypair(s, size_bits); } static TEE_Result do_alloc_publickey(struct rsa_public_key *key, size_t bits) { return sw_crypto_acipher_alloc_rsa_public_key(key, bits); } static void do_free_publickey(struct rsa_public_key *s) { sw_crypto_acipher_free_rsa_public_key(s); } static void do_free_keypair(struct rsa_keypair *s) { sw_crypto_acipher_free_rsa_keypair(s); } static struct drvcrypt_rsa driver_rsa = { .alloc_publickey = do_alloc_publickey, .free_publickey = do_free_publickey, .alloc_keypair = do_alloc_keypair, .optional.ssa_verify = do_ssa_verify, .optional.ssa_sign = do_ssa_sign, .free_keypair = do_free_keypair, .gen_keypair = do_gen_keypair, .encrypt = do_encrypt, .decrypt = do_decrypt, }; static TEE_Result rsa_init(void) { struct versal_cmd_args arg = { }; if (versal_crypto_request(VERSAL_RSA_KAT, &arg, NULL)) return TEE_ERROR_GENERIC; return drvcrypt_register_rsa(&driver_rsa); } driver_init(rsa_init); optee_os-4.3.0/core/drivers/crypto/versal/sub.mk000066400000000000000000000001321464416617300217070ustar00rootroot00000000000000incdirs-y += include srcs-y += ipi.c srcs-y += authenc.c srcs-y += ecc.c srcs-y += rsa.c optee_os-4.3.0/core/drivers/dra7_rng.c000066400000000000000000000127371464416617300176360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #define RNG_OUTPUT_L 0x0000 #define RNG_OUTPUT_H 0x0004 #define RNG_STATUS 0x0008 # define RNG_READY BIT(0) # define SHUTDOWN_OFLO BIT(1) #define RNG_INTMASK 0x000C #define RNG_INTACK 0x0010 #define RNG_CONTROL 0x0014 # define ENABLE_TRNG BIT(10) #define RNG_CONFIG 0x0018 #define RNG_ALARMCNT 0x001C #define RNG_FROENABLE 0x0020 #define RNG_FRODETUNE 0x0024 #define RNG_ALARMMASK 0x0028 #define RNG_ALARMSTOP 0x002C #define RNG_LFSR_L 0x0030 #define RNG_LFSR_M 0x0034 #define RNG_LFSR_H 0x0038 #define RNG_COUNT 0x003C #define RNG_OPTIONS 0x0078 #define RNG_EIP_REV 0x007C #define RNG_MMR_STATUS_EN 0x1FD8 #define RNG_REV 0x1FE0 #define RNG_SYS_CONFIG_REG 0x1FE4 # define RNG_AUTOIDLE BIT(0) #define RNG_MMR_STATUS_SET 0x1FEC #define RNG_SOFT_RESET_REG 0x1FF0 # define RNG_SOFT_RESET BIT(0) #define RNG_IRQ_EOI_REG 0x1FF4 #define RNG_IRQSTATUS 0x1FF8 #define RNG_CONTROL_STARTUP_CYCLES_SHIFT 16 #define RNG_CONTROL_STARTUP_CYCLES_MASK GENMASK_32(31, 16) #define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT 16 #define RNG_CONFIG_MAX_REFIL_CYCLES_MASK GENMASK_32(31, 16) #define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT 0 #define RNG_CONFIG_MIN_REFIL_CYCLES_MASK GENMASK_32(7, 0) #define RNG_ALARMCNT_ALARM_TH_SHIFT 0 #define RNG_ALARMCNT_ALARM_TH_MASK GENMASK_32(7, 0) #define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT 16 #define RNG_ALARMCNT_SHUTDOWN_TH_MASK GENMASK_32(20, 16) #define RNG_CONTROL_STARTUP_CYCLES 0xff #define RNG_CONFIG_MIN_REFIL_CYCLES 0x21 #define RNG_CONFIG_MAX_REFIL_CYCLES 0x22 #define RNG_ALARM_THRESHOLD 0xff #define RNG_SHUTDOWN_THRESHOLD 0x4 #define RNG_FRO_MASK GENMASK_32(23, 0) #define RNG_REG_SIZE 0x2000 register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); static unsigned int rng_lock = SPINLOCK_UNLOCK; static vaddr_t rng; static void dra7_rng_read64(uint32_t *low_word, uint32_t *high_word) { /* Is the result ready (available)? */ while (!(io_read32(rng + RNG_STATUS) & RNG_READY)) { /* Is the shutdown threshold reached? */ if (io_read32(rng + RNG_STATUS) & SHUTDOWN_OFLO) { uint32_t alarm = io_read32(rng + RNG_ALARMSTOP); uint32_t tune = io_read32(rng + RNG_FRODETUNE); /* Clear the alarm events */ io_write32(rng + RNG_ALARMMASK, 0x0); io_write32(rng + RNG_ALARMSTOP, 0x0); /* De-tune offending FROs */ io_write32(rng + RNG_FRODETUNE, tune ^ alarm); /* Re-enable the shut down FROs */ io_write32(rng + RNG_FROENABLE, RNG_FRO_MASK); /* Clear the shutdown overflow event */ io_write32(rng + RNG_INTACK, SHUTDOWN_OFLO); DMSG("Fixed FRO shutdown"); } } /* Read random value */ *low_word = io_read32(rng + RNG_OUTPUT_L); *high_word = io_read32(rng + RNG_OUTPUT_H); /* Acknowledge read complete */ io_write32(rng + RNG_INTACK, RNG_READY); } TEE_Result hw_get_random_bytes(void *buf, size_t len) { static union { uint32_t val[2]; uint8_t byte[8]; } fifo; static size_t fifo_pos; uint8_t *buffer = buf; size_t buffer_pos = 0; while (buffer_pos < len) { uint32_t exceptions = cpu_spin_lock_xsave(&rng_lock); /* Refill our FIFO */ if (fifo_pos == 0) dra7_rng_read64(&fifo.val[0], &fifo.val[1]); buffer[buffer_pos++] = fifo.byte[fifo_pos++]; fifo_pos %= 8; cpu_spin_unlock_xrestore(&rng_lock, exceptions); } return TEE_SUCCESS; } static TEE_Result dra7_rng_init(void) { uint32_t val; rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); /* Execute a software reset */ io_write32(rng + RNG_SOFT_RESET_REG, RNG_SOFT_RESET); /* Wait for the software reset completion by polling */ while (io_read32(rng + RNG_SOFT_RESET_REG) & RNG_SOFT_RESET) ; /* Switch to low-power operating mode */ io_write32(rng + RNG_SYS_CONFIG_REG, RNG_AUTOIDLE); /* * Select the number of clock input cycles to the * FROs between two samples */ val = 0; /* Ensure initial latency */ val |= RNG_CONFIG_MIN_REFIL_CYCLES << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; io_write32(rng + RNG_CONFIG, val); /* Configure the desired FROs */ io_write32(rng + RNG_FRODETUNE, 0x0); /* Enable all FROs */ io_write32(rng + RNG_FROENABLE, 0xffffff); /* * Select the maximum number of samples after * which if a repeating pattern is still detected, an * alarm event is generated */ val = RNG_ALARM_THRESHOLD << RNG_ALARMCNT_ALARM_TH_SHIFT; /* * Set the shutdown threshold to the number of FROs * allowed to be shut downed */ val |= RNG_SHUTDOWN_THRESHOLD << RNG_ALARMCNT_SHUTDOWN_TH_SHIFT; io_write32(rng + RNG_ALARMCNT, val); /* Enable the RNG module */ val = RNG_CONTROL_STARTUP_CYCLES << RNG_CONTROL_STARTUP_CYCLES_SHIFT; val |= ENABLE_TRNG; io_write32(rng + RNG_CONTROL, val); IMSG("DRA7x TRNG initialized"); return TEE_SUCCESS; } driver_init(dra7_rng_init); optee_os-4.3.0/core/drivers/ffa_console.c000066400000000000000000000012141464416617300203750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, NVIDIA CORPORATION */ #include #include #include #include #include #define FFA_CONSOLE_LOG_32 (0x8400008A) static void ffa_console_putc(struct serial_chip *chip __unused, int ch) { thread_hvc(FFA_CONSOLE_LOG_32, 1, ch, 0); } static const struct serial_ops ffa_console_ops = { .putc = ffa_console_putc, }; DECLARE_KEEP_PAGER(ffa_console_ops); static struct serial_chip ffa_console = { .ops = &ffa_console_ops }; void ffa_console_init(void) { register_serial_console(&ffa_console); } optee_os-4.3.0/core/drivers/firewall/000077500000000000000000000000001464416617300175625ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/firewall/firewall.c000066400000000000000000000122551464416617300215400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2024, STMicroelectronics */ #include #include #include #include #include #include #include #include /* The firewall framework requires device tree support */ static_assert(IS_ENABLED(CFG_DT)); static TEE_Result firewall_get(struct dt_pargs *parg, void *data, struct firewall_query **out_fw) { struct firewall_query *fw = NULL; unsigned int i = 0; assert(parg->args_count >= 0); fw = calloc(1, sizeof(*fw)); if (!fw) return TEE_ERROR_OUT_OF_MEMORY; fw->ctrl = (struct firewall_controller *)data; fw->arg_count = parg->args_count; if (fw->arg_count) { fw->args = calloc(fw->arg_count, sizeof(*fw->args)); if (!fw->args) { free(fw); return TEE_ERROR_OUT_OF_MEMORY; } } for (i = 0; i < (unsigned int)parg->args_count; i++) fw->args[i] = parg->args[i]; *out_fw = fw; return TEE_SUCCESS; } /* Firewall device API */ void firewall_put(struct firewall_query *fw) { if (fw) { free(fw->args); free(fw); } } TEE_Result firewall_dt_get_by_index(const void *fdt, int node, uint32_t index, struct firewall_query **out_fw) { return dt_driver_device_from_node_idx_prop("access-controllers", fdt, node, index, DT_DRIVER_FIREWALL, out_fw); } TEE_Result firewall_dt_get_by_name(const void *fdt, int node, const char *name, struct firewall_query **out_fw) { int index = 0; index = fdt_stringlist_search(fdt, node, "access-controllers-names", name); if (index == -FDT_ERR_NOTFOUND) return TEE_ERROR_ITEM_NOT_FOUND; else if (index < 0) return TEE_ERROR_GENERIC; return firewall_dt_get_by_index(fdt, node, index, out_fw); } TEE_Result firewall_set_configuration(struct firewall_query *fw) { assert(fw && fw->ctrl && fw->ctrl->ops); if (!fw->ctrl->ops->set_conf) return TEE_ERROR_NOT_SUPPORTED; return fw->ctrl->ops->set_conf(fw); } TEE_Result firewall_check_access(struct firewall_query *fw) { assert(fw && fw->ctrl && fw->ctrl->ops); if (!fw->ctrl->ops->check_access) return TEE_ERROR_NOT_SUPPORTED; return fw->ctrl->ops->check_access(fw); } TEE_Result firewall_acquire_access(struct firewall_query *fw) { assert(fw && fw->ctrl && fw->ctrl->ops); if (!fw->ctrl->ops->acquire_access) return TEE_ERROR_NOT_SUPPORTED; return fw->ctrl->ops->acquire_access(fw); } TEE_Result firewall_check_memory_access(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write) { assert(fw && fw->ctrl && fw->ctrl->ops); if (!fw->ctrl->ops->check_memory_access) return TEE_ERROR_NOT_SUPPORTED; return fw->ctrl->ops->check_memory_access(fw, paddr, size, read, write); } TEE_Result firewall_acquire_memory_access(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write) { assert(fw && fw->ctrl && fw->ctrl->ops); if (!fw->ctrl->ops->acquire_memory_access) return TEE_ERROR_NOT_SUPPORTED; return fw->ctrl->ops->acquire_memory_access(fw, paddr, size, read, write); } void firewall_release_access(struct firewall_query *fw) { assert(fw && fw->ctrl && fw->ctrl->ops); if (fw->ctrl->ops->release_access) fw->ctrl->ops->release_access(fw); } void firewall_release_memory_access(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write) { assert(fw && fw->ctrl && fw->ctrl->ops); if (fw->ctrl->ops->release_memory_access) fw->ctrl->ops->release_memory_access(fw, paddr, size, read, write); } /* Firewall controller API */ TEE_Result firewall_dt_controller_register(const void *fdt, int node, struct firewall_controller *ctrl) { assert(ctrl); DMSG("Registering %s firewall controller", ctrl->name); return dt_driver_register_provider(fdt, node, (get_of_device_func)firewall_get, ctrl, DT_DRIVER_FIREWALL); } TEE_Result firewall_dt_probe_bus(const void *fdt, int node, struct firewall_controller *ctrl __maybe_unused) { TEE_Result res = TEE_ERROR_GENERIC; struct firewall_query *fw = NULL; int subnode = 0; DMSG("Populating %s firewall bus", ctrl->name); fdt_for_each_subnode(subnode, fdt, node) { unsigned int i = 0; if (fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) continue; DMSG("Acquiring firewall access for %s when probing bus", fdt_get_name(fdt, subnode, NULL)); do { /* * The access-controllers property is mandatory for * firewall bus devices */ res = firewall_dt_get_by_index(fdt, subnode, i, &fw); if (res == TEE_ERROR_ITEM_NOT_FOUND) { /* Stop when nothing more to parse */ break; } else if (res) { EMSG("%s: Error on node %s: %#"PRIx32, ctrl->name, fdt_get_name(fdt, subnode, NULL), res); panic(); } res = firewall_acquire_access(fw); if (res) { EMSG("%s: %s not accessible: %#"PRIx32, ctrl->name, fdt_get_name(fdt, subnode, NULL), res); panic(); } firewall_put(fw); i++; } while (true); res = dt_driver_maybe_add_probe_node(fdt, subnode); if (res) { EMSG("Failed on node %s with %#"PRIx32, fdt_get_name(fdt, subnode, NULL), res); panic(); } } return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/firewall/stm32_rif.c000066400000000000000000000071741464416617300215470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2024, STMicroelectronics */ #include #include #include #include #include #include #define MAX_CID_BITFIELD U(3) /** * get_scid_mask() - Get the static CID mask according to the number of * supported CIDs * * @nb_cid_supp: Number of CIDs supported. Cannot be 0. */ static uint32_t get_scid_mask(unsigned int nb_cid_supp) { uint32_t msb_nb_cid_supp = 0; assert(nb_cid_supp); msb_nb_cid_supp = sizeof(nb_cid_supp) * 8 - __builtin_clz((nb_cid_supp - 1) | 1); /* SCID bitfield highend can't be > SCID_SHIFT + MAX_CID_BITFIELD */ assert(msb_nb_cid_supp <= MAX_CID_BITFIELD); return GENMASK_32(SCID_SHIFT + msb_nb_cid_supp - 1, SCID_SHIFT); } TEE_Result stm32_rif_check_access(uint32_t cidcfgr, uint32_t semcr, unsigned int nb_cid_supp, unsigned int cid_to_check) { uint32_t scid_mask = get_scid_mask(nb_cid_supp); if (!(cidcfgr & _CIDCFGR_CFEN)) return TEE_SUCCESS; if (stm32_rif_scid_ok(cidcfgr, scid_mask, cid_to_check)) return TEE_SUCCESS; if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, cid_to_check)) { if (!(semcr & _SEMCR_MUTEX) || ((semcr & scid_mask) >> SCID_SHIFT) == cid_to_check) { return TEE_SUCCESS; } } return TEE_ERROR_ACCESS_DENIED; } void stm32_rif_parse_cfg(uint32_t rif_conf, struct rif_conf_data *conf_data, unsigned int nb_cid_supp, unsigned int nb_channel) { uint32_t scid_mask = get_scid_mask(nb_cid_supp); uint32_t cidcfdg_conf_mask = 0; uint32_t channel_id = 0; uint32_t semwl_mask = 0; unsigned int conf_index = 0; semwl_mask = GENMASK_32(SEMWL_SHIFT + nb_cid_supp - 1, SEMWL_SHIFT); cidcfdg_conf_mask = scid_mask | semwl_mask | _CIDCFGR_CFEN | _CIDCFGR_SEMEN; /* Shift corresponding to the desired resources */ channel_id = RIF_CHANNEL_ID(rif_conf); if (channel_id >= nb_channel) panic("Bad RIF controllers number"); /* Some peripherals have more than 32 RIF channels */ conf_index = channel_id / 32; /* Privilege configuration */ if (rif_conf & RIFPROT_PRIV) conf_data->priv_conf[conf_index] |= BIT(channel_id); /* Security RIF configuration */ if (rif_conf & RIFPROT_SEC) conf_data->sec_conf[conf_index] |= BIT(channel_id); /* RIF configuration lock */ if (rif_conf & RIFPROT_LOCK && conf_data->lock_conf) conf_data->lock_conf[conf_index] |= BIT(channel_id); /* CID configuration */ conf_data->cid_confs[channel_id] = rif_conf & cidcfdg_conf_mask; /* Store that this RIF resource is to be configured */ conf_data->access_mask[conf_index] |= BIT(channel_id); } bool stm32_rif_semaphore_is_available(vaddr_t addr) { return !(io_read32(addr) & _SEMCR_MUTEX); } TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr, unsigned int nb_cid_supp) { uint32_t scid_mask = get_scid_mask(nb_cid_supp); /* Take the semaphore */ io_setbits32(addr, _SEMCR_MUTEX); /* Check that the Cortex-A has the semaphore */ if (stm32_rif_semaphore_is_available(addr) || ((io_read32(addr) & scid_mask) >> SCID_SHIFT) != RIF_CID1) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } TEE_Result stm32_rif_release_semaphore(vaddr_t addr, unsigned int nb_cid_supp) { uint32_t scid_mask = get_scid_mask(nb_cid_supp); if (stm32_rif_semaphore_is_available(addr)) return TEE_SUCCESS; /* Release the semaphore */ io_clrbits32(addr, _SEMCR_MUTEX); /* Check that current compartment no more owns the semaphore */ if (!stm32_rif_semaphore_is_available(addr) && ((io_read32(addr) & scid_mask) >> SCID_SHIFT) == RIF_CID1) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/firewall/stm32_rifsc.c000066400000000000000000000366611464416617300221000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* RIFSC offset register */ #define _RIFSC_RISC_SECCFGR0 U(0x10) #define _RIFSC_RISC_PRIVCFGR0 U(0x30) #define _RIFSC_RISC_RCFGLOCKR0 U(0x50) #define _RIFSC_RISC_PER0_CIDCFGR U(0x100) #define _RIFSC_RISC_PER0_SEMCR U(0x104) #define _RIFSC_RIMC_CR U(0xC00) #define _RIFSC_RIMC_ATTR0 U(0xC10) #define _RIFSC_HWCFGR3 U(0xFE8) #define _RIFSC_HWCFGR2 U(0xFEC) #define _RIFSC_HWCFGR1 U(0xFF0) #define _RIFSC_VERR U(0xFF4) /* RIFSC_HWCFGR2 register fields */ #define _RIFSC_HWCFGR2_CFG1_MASK GENMASK_32(15, 0) #define _RIFSC_HWCFGR2_CFG1_SHIFT U(0) #define _RIFSC_HWCFGR2_CFG2_MASK GENMASK_32(23, 16) #define _RIFSC_HWCFGR2_CFG2_SHIFT U(16) #define _RIFSC_HWCFGR2_CFG3_MASK GENMASK_32(31, 24) #define _RIFSC_HWCFGR2_CFG3_SHIFT U(24) /* RIFSC_HWCFGR1 register fields */ #define _RIFSC_HWCFGR1_CFG1_MASK GENMASK_32(3, 0) #define _RIFSC_HWCFGR1_CFG1_SHIFT U(0) #define _RIFSC_HWCFGR1_CFG2_MASK GENMASK_32(7, 4) #define _RIFSC_HWCFGR1_CFG2_SHIFT U(4) #define _RIFSC_HWCFGR1_CFG3_MASK GENMASK_32(11, 8) #define _RIFSC_HWCFGR1_CFG3_SHIFT U(8) #define _RIFSC_HWCFGR1_CFG4_MASK GENMASK_32(15, 12) #define _RIFSC_HWCFGR1_CFG4_SHIFT U(12) #define _RIFSC_HWCFGR1_CFG5_MASK GENMASK_32(19, 16) #define _RIFSC_HWCFGR1_CFG5_SHIFT U(16) #define _RIFSC_HWCFGR1_CFG6_MASK GENMASK_32(23, 20) #define _RIFSC_HWCFGR1_CFG6_SHIFT U(20) /* * RISC_CR register fields */ #define _RIFSC_RISC_CR_GLOCK BIT(0) /* * RIMC_CR register fields */ #define _RIFSC_RIMC_CR_GLOCK BIT(0) #define _RIFSC_RIMC_CR_TDCID_MASK GENMASK_32(6, 4) /* RIFSC_VERR register fields */ #define _RIFSC_VERR_MINREV_MASK GENMASK_32(3, 0) #define _RIFSC_VERR_MINREV_SHIFT U(0) #define _RIFSC_VERR_MAJREV_MASK GENMASK_32(7, 4) #define _RIFSC_VERR_MAJREV_SHIFT U(4) /* Periph id per register */ #define _PERIPH_IDS_PER_REG U(32) #define _OFFSET_PERX_CIDCFGR U(0x8) #define RIFSC_RISC_CFEN_MASK BIT(0) #define RIFSC_RISC_CFEN_SHIFT U(0) #define RIFSC_RISC_SEM_EN_MASK BIT(1) #define RIFSC_RISC_SEM_EN_SHIFT U(1) #define RIFSC_RISC_SCID_MASK GENMASK_32(6, 4) #define RIFSC_RISC_SCID_SHIFT U(4) #define RIFSC_RISC_SEC_MASK BIT(8) #define RIFSC_RISC_SEC_SHIFT U(8) #define RIFSC_RISC_PRIV_MASK BIT(9) #define RIFSC_RISC_PRIV_SHIFT U(9) #define RIFSC_RISC_LOCK_MASK BIT(10) #define RIFSC_RISC_LOCK_SHIFT U(10) #define RIFSC_RISC_SEML_MASK GENMASK_32(23, 16) #define RIFSC_RISC_SEML_SHIFT U(16) #define RIFSC_RISC_PER_ID_MASK GENMASK_32(31, 24) #define RIFSC_RISC_PER_ID_SHIFT U(24) #define RIFSC_RISC_PERx_CID_MASK (RIFSC_RISC_CFEN_MASK | \ RIFSC_RISC_SEM_EN_MASK | \ RIFSC_RISC_SCID_MASK | \ RIFSC_RISC_SEML_MASK) #define RIFSC_RISC_PERx_CID_SHIFT U(0) #define RIFSC_RIMC_MODE_MASK BIT(2) #define RIFSC_RIMC_MCID_MASK GENMASK_32(6, 4) #define RIFSC_RIMC_MSEC_MASK BIT(8) #define RIFSC_RIMC_MPRIV_MASK BIT(9) #define RIFSC_RIMC_M_ID_MASK GENMASK_32(23, 16) #define RIFSC_RIMC_ATTRx_MASK (RIFSC_RIMC_MODE_MASK | \ RIFSC_RIMC_MCID_MASK | \ RIFSC_RIMC_MSEC_MASK | \ RIFSC_RIMC_MPRIV_MASK) /* max entries */ #define MAX_RIMU U(16) #define MAX_RISUP U(128) #define _RIF_FLD_GET(field, value) (((uint32_t)(value) & \ (field ## _MASK)) >>\ (field ## _SHIFT)) struct risup_cfg { uint32_t cid_attr; uint32_t id; bool sec; bool priv; bool lock; bool pm_sem; }; struct rimu_cfg { uint32_t id; uint32_t attr; }; struct rifsc_driver_data { bool rif_en; bool sec_en; bool priv_en; uint8_t nb_rimu; uint8_t nb_risup; uint8_t nb_risal; uint8_t version; }; struct rifsc_platdata { uintptr_t base; struct rifsc_driver_data *drv_data; struct risup_cfg *risup; unsigned int nrisup; struct rimu_cfg *rimu; unsigned int nrimu; }; /* There is only 1 instance of the RIFSC subsystem */ static struct rifsc_driver_data rifsc_drvdata; static struct rifsc_platdata rifsc_pdata; static void stm32_rifsc_get_driverdata(struct rifsc_platdata *pdata) { uint32_t regval = 0; regval = io_read32(pdata->base + _RIFSC_HWCFGR1); rifsc_drvdata.rif_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG1, regval) != 0; rifsc_drvdata.sec_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG2, regval) != 0; rifsc_drvdata.priv_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG3, regval) != 0; regval = io_read32(pdata->base + _RIFSC_HWCFGR2); rifsc_drvdata.nb_risup = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG1, regval); rifsc_drvdata.nb_rimu = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG2, regval); rifsc_drvdata.nb_risal = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG3, regval); pdata->drv_data = &rifsc_drvdata; rifsc_drvdata.version = io_read8(pdata->base + _RIFSC_VERR); DMSG("RIFSC version %"PRIu32".%"PRIu32, _RIF_FLD_GET(_RIFSC_VERR_MAJREV, rifsc_drvdata.version), _RIF_FLD_GET(_RIFSC_VERR_MINREV, rifsc_drvdata.version)); DMSG("HW cap: enabled[rif:sec:priv]:[%s:%s:%s] nb[risup|rimu|risal]:[%"PRIu8",%"PRIu8",%"PRIu8"]", rifsc_drvdata.rif_en ? "true" : "false", rifsc_drvdata.sec_en ? "true" : "false", rifsc_drvdata.priv_en ? "true" : "false", rifsc_drvdata.nb_risup, rifsc_drvdata.nb_rimu, rifsc_drvdata.nb_risal); } static TEE_Result stm32_rifsc_glock_config(const void *fdt, int node, struct rifsc_platdata *pdata) { const fdt32_t *cuint = NULL; uint32_t glock_conf = 0; int len = 0; cuint = fdt_getprop(fdt, node, "st,glocked", &len); if (!cuint) { DMSG("No global lock on RIF configuration"); return TEE_SUCCESS; } assert(len == sizeof(uint32_t)); glock_conf = fdt32_to_cpu(*cuint); if (glock_conf & RIFSC_RIMU_GLOCK) { DMSG("Setting global lock on RIMU configuration"); io_setbits32(pdata->base + _RIFSC_RIMC_CR, _RIFSC_RIMC_CR_GLOCK); if (!(io_read32(pdata->base + _RIFSC_RIMC_CR) & _RIFSC_RIMC_CR_GLOCK)) return TEE_ERROR_ACCESS_DENIED; } if (glock_conf & RIFSC_RISUP_GLOCK) { DMSG("Setting global lock on RISUP configuration"); io_setbits32(pdata->base, _RIFSC_RISC_CR_GLOCK); if (!(io_read32(pdata->base) & _RIFSC_RISC_CR_GLOCK)) return TEE_ERROR_ACCESS_DENIED; } return TEE_SUCCESS; } static TEE_Result stm32_rifsc_dt_conf_risup(const void *fdt, int node, struct rifsc_platdata *pdata) { const fdt32_t *conf_list = NULL; unsigned int i = 0; int len = 0; conf_list = fdt_getprop(fdt, node, "st,protreg", &len); if (!conf_list) { DMSG("No RISUP configuration in DT"); return TEE_ERROR_ITEM_NOT_FOUND; } assert(!(len % sizeof(uint32_t))); pdata->nrisup = len / sizeof(uint32_t); pdata->risup = calloc(pdata->nrisup, sizeof(*pdata->risup)); if (!pdata->risup) return TEE_ERROR_OUT_OF_MEMORY; for (i = 0; i < pdata->nrisup; i++) { uint32_t value = fdt32_to_cpu(conf_list[i]); struct risup_cfg *risup = pdata->risup + i; risup->id = _RIF_FLD_GET(RIFSC_RISC_PER_ID, value); risup->sec = _RIF_FLD_GET(RIFSC_RISC_SEC, value) != 0; risup->priv = _RIF_FLD_GET(RIFSC_RISC_PRIV, value) != 0; risup->lock = _RIF_FLD_GET(RIFSC_RISC_LOCK, value) != 0; risup->cid_attr = _RIF_FLD_GET(RIFSC_RISC_PERx_CID, value); } return TEE_SUCCESS; } static TEE_Result stm32_rifsc_dt_conf_rimu(const void *fdt, int node, struct rifsc_platdata *pdata) { const fdt32_t *conf_list = NULL; unsigned int i = 0; int len = 0; conf_list = fdt_getprop(fdt, node, "st,rimu", &len); if (!conf_list) { DMSG("No RIMU configuration in DT"); return TEE_ERROR_ITEM_NOT_FOUND; } assert(!(len % sizeof(uint32_t))); pdata->nrimu = len / sizeof(uint32_t); pdata->rimu = calloc(pdata->nrimu, sizeof(*pdata->rimu)); if (!pdata->rimu) return TEE_ERROR_OUT_OF_MEMORY; for (i = 0; i < pdata->nrimu; i++) { uint32_t value = fdt32_to_cpu(*conf_list); struct rimu_cfg *rimu = pdata->rimu + i; rimu->id = _RIF_FLD_GET(RIFSC_RIMC_M_ID, value); rimu->attr = _RIF_FLD_GET(RIFSC_RIMC_ATTRx, value); } return TEE_SUCCESS; } static TEE_Result stm32_rifsc_parse_fdt(const void *fdt, int node, struct rifsc_platdata *pdata) { TEE_Result res = TEE_ERROR_GENERIC; struct io_pa_va base = { }; size_t reg_size = 0; base.pa = fdt_reg_base_address(fdt, node); if (base.pa == DT_INFO_INVALID_REG) return TEE_ERROR_BAD_PARAMETERS; reg_size = fdt_reg_size(fdt, node); if (reg_size == DT_INFO_INVALID_REG_SIZE) return TEE_ERROR_BAD_PARAMETERS; pdata->base = io_pa_or_va_secure(&base, reg_size); res = stm32_rifsc_dt_conf_risup(fdt, node, pdata); if (res) return res; return stm32_rifsc_dt_conf_rimu(fdt, node, pdata); } static TEE_Result stm32_risup_cfg(struct rifsc_platdata *pdata, struct risup_cfg *risup) { uintptr_t offset = sizeof(uint32_t) * (risup->id / _PERIPH_IDS_PER_REG); uintptr_t cidcfgr_offset = _OFFSET_PERX_CIDCFGR * risup->id; struct rifsc_driver_data *drv_data = pdata->drv_data; uint32_t shift = risup->id % _PERIPH_IDS_PER_REG; TEE_Result res = TEE_ERROR_GENERIC; if (!risup || risup->id >= drv_data->nb_risup) return TEE_ERROR_BAD_PARAMETERS; if (drv_data->sec_en) io_clrsetbits32(pdata->base + _RIFSC_RISC_SECCFGR0 + offset, BIT(shift), SHIFT_U32(risup->sec, shift)); if (drv_data->priv_en) io_clrsetbits32(pdata->base + _RIFSC_RISC_PRIVCFGR0 + offset, BIT(shift), SHIFT_U32(risup->priv, shift)); if (drv_data->rif_en) io_write32(pdata->base + _RIFSC_RISC_PER0_CIDCFGR + cidcfgr_offset, risup->cid_attr); /* Lock configuration for this RISUP */ if (risup->lock) { DMSG("Locking RIF conf for peripheral %"PRIu32, risup->id); io_setbits32(pdata->base + _RIFSC_RISC_RCFGLOCKR0 + offset, BIT(shift)); } /* Take semaphore if the resource is in semaphore mode and secured */ if (!stm32_rif_semaphore_enabled_and_ok(risup->cid_attr, RIF_CID1) || !(io_read32(pdata->base + _RIFSC_RISC_SECCFGR0 + offset) & BIT(shift))) { res = stm32_rif_release_semaphore(pdata->base + _RIFSC_RISC_PER0_SEMCR + cidcfgr_offset, MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't release semaphore for resource %"PRIu32, risup->id); return TEE_ERROR_ACCESS_DENIED; } } else { res = stm32_rif_acquire_semaphore(pdata->base + _RIFSC_RISC_PER0_SEMCR + cidcfgr_offset, MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't acquire semaphore for resource %"PRIu32, risup->id); return TEE_ERROR_ACCESS_DENIED; } } return TEE_SUCCESS; } static TEE_Result stm32_risup_setup(struct rifsc_platdata *pdata) { struct rifsc_driver_data *drv_data = pdata->drv_data; TEE_Result res = TEE_ERROR_GENERIC; unsigned int i = 0; for (i = 0; i < pdata->nrisup && i < drv_data->nb_risup; i++) { struct risup_cfg *risup = pdata->risup + i; res = stm32_risup_cfg(pdata, risup); if (res) { EMSG("risup cfg(%d/%d) error", i + 1, pdata->nrisup); return res; } } return TEE_SUCCESS; } static TEE_Result stm32_rimu_cfg(struct rifsc_platdata *pdata, struct rimu_cfg *rimu) { uintptr_t offset = _RIFSC_RIMC_ATTR0 + (sizeof(uint32_t) * rimu->id); struct rifsc_driver_data *drv_data = pdata->drv_data; if (!rimu || rimu->id >= drv_data->nb_rimu) return TEE_ERROR_BAD_PARAMETERS; if (drv_data->rif_en) io_write32(pdata->base + offset, rimu->attr); return TEE_SUCCESS; } static TEE_Result stm32_rimu_setup(struct rifsc_platdata *pdata) { struct rifsc_driver_data *drv_data = pdata->drv_data; TEE_Result res = TEE_ERROR_GENERIC; unsigned int i = 0; for (i = 0; i < pdata->nrimu && i < drv_data->nb_rimu; i++) { struct rimu_cfg *rimu = pdata->rimu + i; res = stm32_rimu_cfg(pdata, rimu); if (res) { EMSG("rimu cfg(%d/%d) error", i + 1, pdata->nrimu); return res; } } return TEE_SUCCESS; } static TEE_Result stm32_rifsc_sem_pm_suspend(void) { unsigned int i = 0; for (i = 0; i < rifsc_pdata.nrisup && i < rifsc_drvdata.nb_risup; i++) { uint32_t semcfgr = io_read32(rifsc_pdata.base + _RIFSC_RISC_PER0_SEMCR + _OFFSET_PERX_CIDCFGR * i); struct risup_cfg *risup = rifsc_pdata.risup + i; /* Save semaphores that were taken by the CID1 */ risup->pm_sem = semcfgr & _SEMCR_MUTEX && ((semcfgr & _SEMCR_SEMCID_MASK) >> _SEMCR_SEMCID_SHIFT) == RIF_CID1; FMSG("RIF semaphore %s for ID: %"PRIu32, risup->pm_sem ? "SAVED" : "NOT SAVED", risup->id); } return TEE_SUCCESS; } static TEE_Result stm32_rifsc_sem_pm_resume(void) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int i = 0; for (i = 0; i < rifsc_pdata.nrisup && i < rifsc_drvdata.nb_risup; i++) { struct risup_cfg *risup = rifsc_pdata.risup + i; uintptr_t cidcfgr_offset = _OFFSET_PERX_CIDCFGR * risup->id; uintptr_t offset = sizeof(uint32_t) * (risup->id / _PERIPH_IDS_PER_REG); uintptr_t perih_offset = risup->id % _PERIPH_IDS_PER_REG; uint32_t seccgfr = io_read32(rifsc_pdata.base + _RIFSC_RISC_SECCFGR0 + offset); uint32_t privcgfr = io_read32(rifsc_pdata.base + _RIFSC_RISC_PRIVCFGR0 + offset); uint32_t lockcfgr = io_read32(rifsc_pdata.base + _RIFSC_RISC_RCFGLOCKR0 + offset); /* Update RISUPs fields */ risup->cid_attr = io_read32(rifsc_pdata.base + _RIFSC_RISC_PER0_CIDCFGR + cidcfgr_offset); risup->sec = (seccgfr & BIT(perih_offset)) != 0; risup->priv = (privcgfr & BIT(perih_offset)) != 0; risup->lock = (lockcfgr & BIT(perih_offset)) != 0; /* Acquire available appropriate semaphores */ if (!stm32_rif_semaphore_enabled_and_ok(risup->cid_attr, RIF_CID1) || !risup->pm_sem) continue; res = stm32_rif_acquire_semaphore(rifsc_pdata.base + _RIFSC_RISC_PER0_SEMCR + cidcfgr_offset, MAX_CID_SUPPORTED); if (res) { EMSG("Could not acquire semaphore for resource %"PRIu32, risup->id); return TEE_ERROR_ACCESS_DENIED; } } return TEE_SUCCESS; } static TEE_Result stm32_rifsc_sem_pm(enum pm_op op, unsigned int pm_hint, const struct pm_callback_handle *pm_handle __unused) { TEE_Result res = TEE_ERROR_GENERIC; if (pm_hint != PM_HINT_CONTEXT_STATE) return TEE_SUCCESS; if (op == PM_OP_RESUME) res = stm32_rifsc_sem_pm_resume(); else res = stm32_rifsc_sem_pm_suspend(); return res; } TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state) { if (!rifsc_pdata.base) return TEE_ERROR_DEFER_DRIVER_INIT; if (((io_read32(rifsc_pdata.base + _RIFSC_RIMC_CR) & _RIFSC_RIMC_CR_TDCID_MASK)) == (RIF_CID1 << SCID_SHIFT)) *tdcid_state = true; else *tdcid_state = false; return TEE_SUCCESS; } static TEE_Result stm32_rifsc_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; res = stm32_rifsc_parse_fdt(fdt, node, &rifsc_pdata); if (res) { EMSG("Could not parse RIFSC node, res = %#"PRIx32, res); panic(); } if (!rifsc_pdata.drv_data) stm32_rifsc_get_driverdata(&rifsc_pdata); res = stm32_risup_setup(&rifsc_pdata); if (res) { EMSG("Could not setup RISUPs, res = %#"PRIx32, res); panic(); } res = stm32_rimu_setup(&rifsc_pdata); if (res) { EMSG("Could not setup RIMUs, res = %#"PRIx32, res); panic(); } res = stm32_rifsc_glock_config(fdt, node, &rifsc_pdata); if (res) panic("Couldn't lock RIFSC configuration"); register_pm_core_service_cb(stm32_rifsc_sem_pm, NULL, "stm32-rifsc-semaphores"); return TEE_SUCCESS; } static const struct dt_device_match rifsc_match_table[] = { { .compatible = "st,stm32mp25-rifsc" }, { } }; DEFINE_DT_DRIVER(rifsc_dt_driver) = { .name = "stm32-rifsc", .match_table = rifsc_match_table, .probe = stm32_rifsc_probe, }; optee_os-4.3.0/core/drivers/firewall/sub.mk000066400000000000000000000001721464416617300207040ustar00rootroot00000000000000srcs-$(CFG_STM32_RIF) += stm32_rif.c srcs-$(CFG_STM32_RIFSC) += stm32_rifsc.c srcs-$(CFG_DRIVERS_FIREWALL) += firewall.c optee_os-4.3.0/core/drivers/gic.c000066400000000000000000000673171464416617300167010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2017, 2023-2024 Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Offsets from gic.gicc_base */ #define GICC_CTLR (0x000) #define GICC_PMR (0x004) #define GICC_IAR (0x00C) #define GICC_EOIR (0x010) #define GICC_CTLR_ENABLEGRP0 (1 << 0) #define GICC_CTLR_ENABLEGRP1 (1 << 1) #define GICC_CTLR_FIQEN (1 << 3) /* Offsets from gic.gicd_base */ #define GICD_CTLR (0x000) #define GICD_TYPER (0x004) #define GICD_IGROUPR(n) (0x080 + (n) * 4) #define GICD_ISENABLER(n) (0x100 + (n) * 4) #define GICD_ICENABLER(n) (0x180 + (n) * 4) #define GICD_ISPENDR(n) (0x200 + (n) * 4) #define GICD_ICPENDR(n) (0x280 + (n) * 4) #define GICD_IPRIORITYR(n) (0x400 + (n) * 4) #define GICD_ITARGETSR(n) (0x800 + (n) * 4) #define GICD_IGROUPMODR(n) (0xd00 + (n) * 4) #define GICD_SGIR (0xF00) #ifdef CFG_ARM_GICV3 #define GICD_PIDR2 (0xFFE8) #else /* Called ICPIDR2 in GICv2 specification */ #define GICD_PIDR2 (0xFE8) #endif #define GICD_CTLR_ENABLEGRP0 BIT32(0) #define GICD_CTLR_ENABLEGRP1NS BIT32(1) #define GICD_CTLR_ENABLEGRP1S BIT32(2) #define GICD_CTLR_ARE_S BIT32(4) #define GICD_CTLR_ARE_NS BIT32(5) /* Offsets from gic.gicr_base[core_pos] */ #define GICR_V3_PCPUBASE_SIZE (2 * 64 * 1024) #define GICR_SGI_BASE_OFFSET (64 * 1024) #define GICR_CTLR (0x00) #define GICR_TYPER (0x08) #define GICR_IGROUPR0 (GICR_SGI_BASE_OFFSET + 0x080) #define GICR_IGRPMODR0 (GICR_SGI_BASE_OFFSET + 0xD00) #define GICR_ICENABLER0 (GICR_SGI_BASE_OFFSET + 0x180) #define GICR_ICPENDR0 (GICR_SGI_BASE_OFFSET + 0x280) #define GICR_ISENABLER0 (GICR_SGI_BASE_OFFSET + 0x100) #define GICR_ICFGR0 (GICR_SGI_BASE_OFFSET + 0xC00) #define GICR_ICFGR1 (GICR_SGI_BASE_OFFSET + 0xC04) #define GICR_IPRIORITYR(n) (GICR_SGI_BASE_OFFSET + 0x400 + (n) * 4) #define GICR_CTLR_RWP BIT32(3) #define GICR_TYPER_LAST BIT64(4) #define GICR_TYPER_AFF3_SHIFT 56 #define GICR_TYPER_AFF2_SHIFT 48 #define GICR_TYPER_AFF1_SHIFT 40 #define GICR_TYPER_AFF0_SHIFT 32 /* GICD IDR2 name differs on GICv3 and GICv2 but uses same bit map */ #define GICD_PIDR2_ARCHREV_SHIFT 4 #define GICD_PIDR2_ARCHREV_MASK 0xF /* Number of Private Peripheral Interrupt */ #define NUM_PPI 32 /* Number of Software Generated Interrupt */ #define NUM_SGI 16 /* Number of Non-secure Software Generated Interrupt */ #define NUM_NS_SGI 8 /* Number of interrupts in one register */ #define NUM_INTS_PER_REG 32 /* Number of targets in one register */ #define NUM_TARGETS_PER_REG 4 /* Accessors to access ITARGETSRn */ #define ITARGETSR_FIELD_BITS 8 #define ITARGETSR_FIELD_MASK 0xff #define GICD_TYPER_IT_LINES_NUM_MASK 0x1f #define GICC_IAR_IT_ID_MASK 0x3ff #define GICC_IAR_CPU_ID_MASK 0x7 #define GICC_IAR_CPU_ID_SHIFT 10 #define GICC_SGI_IRM_BIT 40 #define GICC_SGI_AFF1_SHIFT 16 #define GICC_SGI_AFF2_SHIFT 32 #define GICC_SGI_AFF3_SHIFT 48 #define GICD_SGIR_SIGINTID_MASK 0xf #define GICD_SGIR_TO_OTHER_CPUS 0x1 #define GICD_SGIR_TO_THIS_CPU 0x2 #define GICD_SGIR_TARGET_LIST_FILTER_SHIFT 24 #define GICD_SGIR_NSATT_SHIFT 15 #define GICD_SGIR_CPU_TARGET_LIST_SHIFT 16 struct gic_data { vaddr_t gicc_base; vaddr_t gicd_base; #if defined(CFG_ARM_GICV3) vaddr_t gicr_base[CFG_TEE_CORE_NB_CORE]; #endif size_t max_it; uint32_t per_cpu_group_status; uint32_t per_cpu_group_modifier; uint32_t per_cpu_enable; struct itr_chip chip; }; static bool gic_primary_done __nex_bss; static struct gic_data gic_data __nex_bss; static void gic_op_add(struct itr_chip *chip, size_t it, uint32_t type, uint32_t prio); static void gic_op_enable(struct itr_chip *chip, size_t it); static void gic_op_disable(struct itr_chip *chip, size_t it); static void gic_op_raise_pi(struct itr_chip *chip, size_t it); static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, uint32_t cpu_mask); static void gic_op_set_affinity(struct itr_chip *chip, size_t it, uint8_t cpu_mask); static const struct itr_ops gic_ops = { .add = gic_op_add, .mask = gic_op_disable, .unmask = gic_op_enable, .enable = gic_op_enable, .disable = gic_op_disable, .raise_pi = gic_op_raise_pi, .raise_sgi = gic_op_raise_sgi, .set_affinity = gic_op_set_affinity, }; DECLARE_KEEP_PAGER(gic_ops); static vaddr_t __maybe_unused get_gicr_base(struct gic_data *gd __maybe_unused) { #if defined(CFG_ARM_GICV3) return gd->gicr_base[get_core_pos()]; #else return 0; #endif } static bool affinity_routing_is_enabled(struct gic_data *gd) { return IS_ENABLED(CFG_ARM_GICV3) && io_read32(gd->gicd_base + GICD_CTLR) & GICD_CTLR_ARE_S; } static size_t probe_max_it(vaddr_t gicc_base __maybe_unused, vaddr_t gicd_base) { int i; uint32_t old_ctlr; size_t ret = 0; size_t max_regs = io_read32(gicd_base + GICD_TYPER) & GICD_TYPER_IT_LINES_NUM_MASK; /* * Probe which interrupt number is the largest. */ #if defined(CFG_ARM_GICV3) old_ctlr = read_icc_ctlr(); write_icc_ctlr(0); #else old_ctlr = io_read32(gicc_base + GICC_CTLR); io_write32(gicc_base + GICC_CTLR, 0); #endif for (i = max_regs; i >= 0; i--) { uint32_t old_reg; uint32_t reg; int b; old_reg = io_read32(gicd_base + GICD_ISENABLER(i)); io_write32(gicd_base + GICD_ISENABLER(i), 0xffffffff); reg = io_read32(gicd_base + GICD_ISENABLER(i)); io_write32(gicd_base + GICD_ICENABLER(i), ~old_reg); for (b = NUM_INTS_PER_REG - 1; b >= 0; b--) { if (BIT32(b) & reg) { ret = i * NUM_INTS_PER_REG + b; goto out; } } } out: #if defined(CFG_ARM_GICV3) write_icc_ctlr(old_ctlr); #else io_write32(gicc_base + GICC_CTLR, old_ctlr); #endif return ret; } static void gicr_wait_for_pending_write(vaddr_t gicr_base) { /* * Wait for changes to * - GICR_ICENABLER0 * - GICR_CTLR.DPG1S * - GICR_CTLR.DPG1NS * - GICR_CTLR.DPG0 * to be visible to all agents in the system. */ while (io_read32(gicr_base + GICR_CTLR) & GICR_CTLR_RWP) ; } static void gicv3_sync_redist_config(struct gic_data *gd) { vaddr_t gicr_base = get_gicr_base(gd); bool need_sync = false; uint32_t gmod0 = 0; uint32_t grp0 = 0; size_t n = 0; /* * If gicr_base isn't available there's no need to synchronize SGI * configuration since gic_init_donate_sgi_to_ns() would panic. */ if (!gicr_base) return; grp0 = io_read32(gicr_base + GICR_IGROUPR0); gmod0 = io_read32(gicr_base + GICR_IGRPMODR0); for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) { /* Ignore matching bits */ if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)) && !(BIT32(n) & (gmod0 ^ gd->per_cpu_group_modifier))) continue; /* * SGI/PPI-n differs from primary CPU configuration, * let's sync up. */ need_sync = true; /* Disable interrupt */ io_write32(gicr_base + GICR_ICENABLER0, BIT32(n)); /* Wait for the write to GICR_ICENABLER0 to propagate */ gicr_wait_for_pending_write(gicr_base); /* Make interrupt non-pending */ io_write32(gicr_base + GICR_ICPENDR0, BIT32(n)); if (BIT32(n) & gd->per_cpu_group_status) grp0 |= BIT32(n); else grp0 &= ~BIT32(n); if (BIT32(n) & gd->per_cpu_group_modifier) gmod0 |= BIT32(n); else gmod0 &= ~BIT32(n); } if (need_sync) { io_write32(gicr_base + GICR_IGROUPR0, grp0); io_write32(gicr_base + GICR_IGRPMODR0, gmod0); io_write32(gicr_base + GICR_ISENABLER0, gd->per_cpu_enable); } } static void gic_legacy_sync_dist_config(struct gic_data *gd) { bool need_sync = false; uint32_t grp0 = 0; size_t n = 0; grp0 = io_read32(gd->gicd_base + GICD_IGROUPR(0)); for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) { /* Ignore matching bits */ if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status))) continue; /* * SGI/PPI-n differs from primary CPU configuration, * let's sync up. */ need_sync = true; /* Disable interrupt */ io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(n)); /* Make interrupt non-pending */ io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(n)); if (BIT32(n) & gd->per_cpu_group_status) grp0 |= BIT32(n); else grp0 &= ~BIT32(n); } if (need_sync) { io_write32(gd->gicd_base + GICD_IGROUPR(0), grp0); io_write32(gd->gicd_base + GICD_ISENABLER(0), gd->per_cpu_enable); } } static void init_gic_per_cpu(struct gic_data *gd) { io_write32(gd->gicd_base + GICD_IGROUPR(0), gd->per_cpu_group_status); /* * Set the priority mask to permit Non-secure interrupts, and to * allow the Non-secure world to adjust the priority mask itself */ #if defined(CFG_ARM_GICV3) write_icc_pmr(0x80); write_icc_igrpen1(1); #else io_write32(gd->gicc_base + GICC_PMR, 0x80); /* Enable GIC */ io_write32(gd->gicc_base + GICC_CTLR, GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1 | GICC_CTLR_FIQEN); #endif } void gic_init_per_cpu(void) { struct gic_data *gd = &gic_data; #if defined(CFG_ARM_GICV3) assert(gd->gicd_base); #else assert(gd->gicd_base && gd->gicc_base); #endif if (IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) { /* * GIC is already initialized by TF-A, we only need to * handle eventual SGI or PPI configuration changes. */ if (affinity_routing_is_enabled(gd)) gicv3_sync_redist_config(gd); else gic_legacy_sync_dist_config(gd); } else { /* * Non-TF-A case where all CPU specific configuration * of GIC must be done here. */ init_gic_per_cpu(gd); } } void gic_init_donate_sgi_to_ns(size_t it) { struct gic_data *gd = &gic_data; assert(it >= GIC_SGI_SEC_BASE && it <= GIC_SGI_SEC_MAX); /* Assert it's secure to start with. */ assert(!(gd->per_cpu_group_status & BIT32(it)) && (gd->per_cpu_group_modifier & BIT32(it))); gd->per_cpu_group_modifier &= ~BIT32(it); gd->per_cpu_group_status |= BIT32(it); if (affinity_routing_is_enabled(gd)) { vaddr_t gicr_base = get_gicr_base(gd); if (!gicr_base) panic("GICR_BASE missing"); /* Disable interrupt */ io_write32(gicr_base + GICR_ICENABLER0, BIT32(it)); /* Wait for the write to GICR_ICENABLER0 to propagate */ gicr_wait_for_pending_write(gicr_base); /* Make interrupt non-pending */ io_write32(gicr_base + GICR_ICPENDR0, BIT32(it)); /* Make it to non-secure */ io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status); io_write32(gicr_base + GICR_IGRPMODR0, gd->per_cpu_group_modifier); } else { /* Disable interrupt */ io_write32(gd->gicd_base + GICD_ICENABLER(0), BIT(it)); /* Make interrupt non-pending */ io_write32(gd->gicd_base + GICD_ICPENDR(0), BIT(it)); /* Make it to non-secure */ io_write32(gd->gicd_base + GICD_IGROUPR(0), gd->per_cpu_group_status); } } static int gic_dt_get_irq(const uint32_t *properties, int count, uint32_t *type, uint32_t *prio) { int it_num = DT_INFO_INVALID_INTERRUPT; if (type) *type = IRQ_TYPE_NONE; if (prio) *prio = 0; if (!properties || count < 2) return DT_INFO_INVALID_INTERRUPT; it_num = fdt32_to_cpu(properties[1]); switch (fdt32_to_cpu(properties[0])) { case GIC_PPI: it_num += 16; break; case GIC_SPI: it_num += 32; break; default: it_num = DT_INFO_INVALID_INTERRUPT; } return it_num; } static void __maybe_unused probe_redist_base_addrs(vaddr_t *gicr_base_addrs, paddr_t gicr_base_pa) { size_t sz = GICR_V3_PCPUBASE_SIZE; paddr_t pa = gicr_base_pa; size_t core_pos = 0; uint64_t mt_bit = 0; uint64_t mpidr = 0; uint64_t tv = 0; vaddr_t va = 0; #ifdef ARM64 mt_bit = read_mpidr_el1() & MPIDR_MT_MASK; #endif do { va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz); if (!va) panic(); tv = io_read64(va + GICR_TYPER); /* * Extract an mpidr from the Type register to calculate the * core position of this redistributer instance. */ mpidr = mt_bit; mpidr |= SHIFT_U64((tv >> GICR_TYPER_AFF3_SHIFT) & MPIDR_AFFLVL_MASK, MPIDR_AFF3_SHIFT); mpidr |= (tv >> GICR_TYPER_AFF0_SHIFT) & (MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | MPIDR_AFF2_MASK); core_pos = get_core_pos_mpidr(mpidr); if (core_pos < CFG_TEE_CORE_NB_CORE) { DMSG("GICR_BASE[%zu] at %#"PRIxVA, core_pos, va); gicr_base_addrs[core_pos] = va; } else { EMSG("Skipping too large core_pos %zu from GICR_TYPER", core_pos); } pa += sz; } while (!(tv & GICR_TYPER_LAST)); } static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa, paddr_t gicr_base_pa __maybe_unused) { struct gic_data *gd = &gic_data; vaddr_t gicc_base = 0; vaddr_t gicd_base = 0; uint32_t vers __maybe_unused = 0; assert(cpu_mmu_enabled()); gicd_base = core_mmu_get_va(gicd_base_pa, MEM_AREA_IO_SEC, GIC_DIST_REG_SIZE); if (!gicd_base) panic(); vers = io_read32(gicd_base + GICD_PIDR2); vers >>= GICD_PIDR2_ARCHREV_SHIFT; vers &= GICD_PIDR2_ARCHREV_MASK; if (IS_ENABLED(CFG_ARM_GICV3)) { assert(vers == 3); } else { assert(vers == 2 || vers == 1); gicc_base = core_mmu_get_va(gicc_base_pa, MEM_AREA_IO_SEC, GIC_CPU_REG_SIZE); if (!gicc_base) panic(); } gd->gicc_base = gicc_base; gd->gicd_base = gicd_base; gd->max_it = probe_max_it(gicc_base, gicd_base); #if defined(CFG_ARM_GICV3) if (affinity_routing_is_enabled(gd) && gicr_base_pa) probe_redist_base_addrs(gd->gicr_base, gicr_base_pa); #endif gd->chip.ops = &gic_ops; if (IS_ENABLED(CFG_DT)) gd->chip.dt_get_irq = gic_dt_get_irq; } void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, paddr_t gicr_base_pa) { struct gic_data __maybe_unused *gd = &gic_data; size_t __maybe_unused n = 0; gic_init_base_addr(gicc_base_pa, gicd_base_pa, gicr_base_pa); #if defined(CFG_WITH_ARM_TRUSTED_FW) /* GIC configuration is initialized from TF-A when embedded */ if (affinity_routing_is_enabled(gd)) { /* Secure affinity routing enabled */ vaddr_t gicr_base = get_gicr_base(gd); if (gicr_base) { gd->per_cpu_group_status = io_read32(gicr_base + GICR_IGROUPR0); gd->per_cpu_group_modifier = io_read32(gicr_base + GICR_IGRPMODR0); } else { IMSG("GIC redistributor base address not provided"); IMSG("Assuming default GIC group status and modifier"); gd->per_cpu_group_status = 0xffff00ff; gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; } } else { /* Legacy operation with secure affinity routing disabled */ gd->per_cpu_group_status = io_read32(gd->gicd_base + GICD_IGROUPR(0)); gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; } #else /*!CFG_WITH_ARM_TRUSTED_FW*/ /* * Without TF-A, GIC is always configured in for legacy operation * with secure affinity routing disabled. */ for (n = 0; n <= gd->max_it / NUM_INTS_PER_REG; n++) { /* Disable interrupts */ io_write32(gd->gicd_base + GICD_ICENABLER(n), 0xffffffff); /* Make interrupts non-pending */ io_write32(gd->gicd_base + GICD_ICPENDR(n), 0xffffffff); /* Mark interrupts non-secure */ if (n == 0) { /* per-CPU inerrupts config: * ID0-ID7(SGI) for Non-secure interrupts * ID8-ID15(SGI) for Secure interrupts. * All PPI config as Non-secure interrupts. */ gd->per_cpu_group_status = 0xffff00ff; gd->per_cpu_group_modifier = ~gd->per_cpu_group_status; io_write32(gd->gicd_base + GICD_IGROUPR(n), gd->per_cpu_group_status); } else { io_write32(gd->gicd_base + GICD_IGROUPR(n), 0xffffffff); } } /* Set the priority mask to permit Non-secure interrupts, and to * allow the Non-secure world to adjust the priority mask itself */ #if defined(CFG_ARM_GICV3) write_icc_pmr(0x80); write_icc_igrpen1(1); io_setbits32(gd->gicd_base + GICD_CTLR, GICD_CTLR_ENABLEGRP1S); #else io_write32(gd->gicc_base + GICC_PMR, 0x80); /* Enable GIC */ io_write32(gd->gicc_base + GICC_CTLR, GICC_CTLR_FIQEN | GICC_CTLR_ENABLEGRP0 | GICC_CTLR_ENABLEGRP1); io_setbits32(gd->gicd_base + GICD_CTLR, GICD_CTLR_ENABLEGRP0 | GICD_CTLR_ENABLEGRP1NS); #endif #endif /*!CFG_WITH_ARM_TRUSTED_FW*/ interrupt_main_init(&gic_data.chip); } static void gic_it_add(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Disable the interrupt */ io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask); /* Make it non-pending */ io_write32(gd->gicd_base + GICD_ICPENDR(idx), mask); /* Assign it to group0 */ io_clrbits32(gd->gicd_base + GICD_IGROUPR(idx), mask); #if defined(CFG_ARM_GICV3) /* Assign it to group1S */ io_setbits32(gd->gicd_base + GICD_IGROUPMODR(idx), mask); #endif } static void gic_it_set_cpu_mask(struct gic_data *gd, size_t it, uint8_t cpu_mask) { size_t idx __maybe_unused = it / NUM_INTS_PER_REG; uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); uint32_t target, target_shift; vaddr_t itargetsr = gd->gicd_base + GICD_ITARGETSR(it / NUM_TARGETS_PER_REG); assert(gd == &gic_data); /* Assigned to group0 */ assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); /* Route it to selected CPUs */ target = io_read32(itargetsr); target_shift = (it % NUM_TARGETS_PER_REG) * ITARGETSR_FIELD_BITS; target &= ~(ITARGETSR_FIELD_MASK << target_shift); target |= cpu_mask << target_shift; DMSG("cpu_mask: writing 0x%x to 0x%" PRIxVA, target, itargetsr); io_write32(itargetsr, target); DMSG("cpu_mask: 0x%x", io_read32(itargetsr)); } static void gic_it_set_prio(struct gic_data *gd, size_t it, uint8_t prio) { size_t idx __maybe_unused = it / NUM_INTS_PER_REG; uint32_t mask __maybe_unused = 1 << (it % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Assigned to group0 */ assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); /* Set prio it to selected CPUs */ DMSG("prio: writing 0x%x to 0x%" PRIxVA, prio, gd->gicd_base + GICD_IPRIORITYR(0) + it); io_write8(gd->gicd_base + GICD_IPRIORITYR(0) + it, prio); } static void gic_it_enable(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); vaddr_t base = gd->gicd_base; assert(gd == &gic_data); /* Assigned to group0 */ assert(!(io_read32(base + GICD_IGROUPR(idx)) & mask)); /* Enable the interrupt */ io_write32(base + GICD_ISENABLER(idx), mask); } static void gic_it_disable(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Assigned to group0 */ assert(!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask)); /* Disable the interrupt */ io_write32(gd->gicd_base + GICD_ICENABLER(idx), mask); } static void gic_it_set_pending(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = BIT32(it % NUM_INTS_PER_REG); assert(gd == &gic_data); /* Should be Peripheral Interrupt */ assert(it >= NUM_SGI); /* Raise the interrupt */ io_write32(gd->gicd_base + GICD_ISPENDR(idx), mask); } static void assert_cpu_mask_is_valid(uint32_t cpu_mask) { bool __maybe_unused to_others = cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS; bool __maybe_unused to_current = cpu_mask & ITR_CPU_MASK_TO_THIS_CPU; bool __maybe_unused to_list = cpu_mask & 0xff; /* One and only one of the bit fields shall be non-zero */ assert(to_others + to_current + to_list == 1); } static void gic_it_raise_sgi(struct gic_data *gd __maybe_unused, size_t it, uint32_t cpu_mask, bool ns) { #if defined(CFG_ARM_GICV3) uint32_t mask_id = it & 0xf; uint64_t mask = SHIFT_U64(mask_id, 24); assert_cpu_mask_is_valid(cpu_mask); if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) { mask |= BIT64(GICC_SGI_IRM_BIT); } else { uint64_t mpidr = read_mpidr(); uint64_t mask_aff1 = (mpidr & MPIDR_AFF1_MASK) >> MPIDR_AFF1_SHIFT; uint64_t mask_aff2 = (mpidr & MPIDR_AFF2_MASK) >> MPIDR_AFF2_SHIFT; uint64_t mask_aff3 = (mpidr & MPIDR_AFF3_MASK) >> MPIDR_AFF3_SHIFT; mask |= SHIFT_U64(mask_aff1, GICC_SGI_AFF1_SHIFT); mask |= SHIFT_U64(mask_aff2, GICC_SGI_AFF2_SHIFT); mask |= SHIFT_U64(mask_aff3, GICC_SGI_AFF3_SHIFT); if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) { mask |= BIT32(mpidr & 0xf); } else { /* * Only support sending SGI to the cores in the * same cluster now. */ mask |= cpu_mask & 0xff; } } /* Raise the interrupt */ if (ns) write_icc_asgi1r(mask); else write_icc_sgi1r(mask); #else uint32_t mask_id = it & GICD_SGIR_SIGINTID_MASK; uint32_t mask_group = ns; uint32_t mask = mask_id; assert_cpu_mask_is_valid(cpu_mask); mask |= SHIFT_U32(mask_group, GICD_SGIR_NSATT_SHIFT); if (cpu_mask & ITR_CPU_MASK_TO_OTHER_CPUS) { mask |= SHIFT_U32(GICD_SGIR_TO_OTHER_CPUS, GICD_SGIR_TARGET_LIST_FILTER_SHIFT); } else if (cpu_mask & ITR_CPU_MASK_TO_THIS_CPU) { mask |= SHIFT_U32(GICD_SGIR_TO_THIS_CPU, GICD_SGIR_TARGET_LIST_FILTER_SHIFT); } else { mask |= SHIFT_U32(cpu_mask & 0xff, GICD_SGIR_CPU_TARGET_LIST_SHIFT); } /* Raise the interrupt */ io_write32(gd->gicd_base + GICD_SGIR, mask); #endif } static uint32_t gic_read_iar(struct gic_data *gd __maybe_unused) { assert(gd == &gic_data); #if defined(CFG_ARM_GICV3) return read_icc_iar1(); #else return io_read32(gd->gicc_base + GICC_IAR); #endif } static void gic_write_eoir(struct gic_data *gd __maybe_unused, uint32_t eoir) { assert(gd == &gic_data); #if defined(CFG_ARM_GICV3) write_icc_eoir1(eoir); #else io_write32(gd->gicc_base + GICC_EOIR, eoir); #endif } static bool gic_it_is_enabled(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); assert(gd == &gic_data); return !!(io_read32(gd->gicd_base + GICD_ISENABLER(idx)) & mask); } static bool __maybe_unused gic_it_get_group(struct gic_data *gd, size_t it) { size_t idx = it / NUM_INTS_PER_REG; uint32_t mask = 1 << (it % NUM_INTS_PER_REG); assert(gd == &gic_data); return !!(io_read32(gd->gicd_base + GICD_IGROUPR(idx)) & mask); } static uint32_t __maybe_unused gic_it_get_target(struct gic_data *gd, size_t it) { size_t reg_idx = it / NUM_TARGETS_PER_REG; uint32_t target_shift = (it % NUM_TARGETS_PER_REG) * ITARGETSR_FIELD_BITS; uint32_t target_mask = ITARGETSR_FIELD_MASK << target_shift; uint32_t target = io_read32(gd->gicd_base + GICD_ITARGETSR(reg_idx)); assert(gd == &gic_data); return (target & target_mask) >> target_shift; } void gic_dump_state(void) { struct gic_data *gd = &gic_data; int i = 0; #if defined(CFG_ARM_GICV3) DMSG("GICC_CTLR: 0x%x", read_icc_ctlr()); #else DMSG("GICC_CTLR: 0x%x", io_read32(gd->gicc_base + GICC_CTLR)); #endif DMSG("GICD_CTLR: 0x%x", io_read32(gd->gicd_base + GICD_CTLR)); for (i = 0; i <= (int)gd->max_it; i++) { if (gic_it_is_enabled(gd, i)) { DMSG("irq%d: enabled, group:%d, target:%x", i, gic_it_get_group(gd, i), gic_it_get_target(gd, i)); } } } static void __maybe_unused gic_native_itr_handler(void) { struct gic_data *gd = &gic_data; uint32_t iar = 0; uint32_t id = 0; iar = gic_read_iar(gd); id = iar & GICC_IAR_IT_ID_MASK; if (id <= gd->max_it) interrupt_call_handlers(&gd->chip, id); else DMSG("ignoring interrupt %" PRIu32, id); gic_write_eoir(gd, iar); } #ifndef CFG_CORE_WORKAROUND_ARM_NMFI /* Override interrupt_main_handler() with driver implementation */ void interrupt_main_handler(void) { gic_native_itr_handler(); } #endif /*CFG_CORE_WORKAROUND_ARM_NMFI*/ static void gic_op_add(struct itr_chip *chip, size_t it, uint32_t type __unused, uint32_t prio __unused) { struct gic_data *gd = container_of(chip, struct gic_data, chip); assert(gd == &gic_data); if (it > gd->max_it) panic(); if (it < GIC_SPI_BASE) { if (gic_primary_done) panic("Cannot add SGI or PPI after boot"); /* Assign it to Secure Group 1, G1S */ gd->per_cpu_group_modifier |= BIT32(it); gd->per_cpu_group_status &= ~BIT32(it); } if (it < GIC_SPI_BASE && affinity_routing_is_enabled(gd)) { vaddr_t gicr_base = get_gicr_base(gd); if (!gicr_base) panic("GICR_BASE missing"); /* Disable interrupt */ io_write32(gicr_base + GICR_ICENABLER0, BIT32(it)); /* Wait for the write to GICR_ICENABLER0 to propagate */ gicr_wait_for_pending_write(gicr_base); /* Make interrupt non-pending */ io_write32(gicr_base + GICR_ICPENDR0, BIT32(it)); /* Make it to Secure */ io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status); io_write32(gicr_base + GICR_IGRPMODR0, gd->per_cpu_group_modifier); } else { gic_it_add(gd, it); /* Set the CPU mask to deliver interrupts to any online core */ gic_it_set_cpu_mask(gd, it, 0xff); gic_it_set_prio(gd, it, 0x1); } } static void gic_op_enable(struct itr_chip *chip, size_t it) { struct gic_data *gd = container_of(chip, struct gic_data, chip); assert(gd == &gic_data); if (it > gd->max_it) panic(); if (it < GIC_SPI_BASE) gd->per_cpu_enable |= BIT(it); if (it < GIC_SPI_BASE && affinity_routing_is_enabled(gd)) { vaddr_t gicr_base = get_gicr_base(gd); if (!gicr_base) panic("GICR_BASE missing"); /* Assigned to G1S */ assert(gd->per_cpu_group_modifier & BIT(it) && !(gd->per_cpu_group_status & BIT(it))); io_write32(gicr_base + GICR_ISENABLER0, gd->per_cpu_enable); } else { gic_it_enable(gd, it); } } static void gic_op_disable(struct itr_chip *chip, size_t it) { struct gic_data *gd = container_of(chip, struct gic_data, chip); assert(gd == &gic_data); if (it > gd->max_it) panic(); gic_it_disable(gd, it); } static void gic_op_raise_pi(struct itr_chip *chip, size_t it) { struct gic_data *gd = container_of(chip, struct gic_data, chip); assert(gd == &gic_data); if (it > gd->max_it) panic(); gic_it_set_pending(gd, it); } static void gic_op_raise_sgi(struct itr_chip *chip, size_t it, uint32_t cpu_mask) { struct gic_data *gd = container_of(chip, struct gic_data, chip); bool ns = false; assert(gd == &gic_data); /* Should be Software Generated Interrupt */ assert(it < NUM_SGI); ns = BIT32(it) & gd->per_cpu_group_status; gic_it_raise_sgi(gd, it, cpu_mask, ns); } static void gic_op_set_affinity(struct itr_chip *chip, size_t it, uint8_t cpu_mask) { struct gic_data *gd = container_of(chip, struct gic_data, chip); assert(gd == &gic_data); if (it > gd->max_it) panic(); gic_it_set_cpu_mask(gd, it, cpu_mask); } #ifdef CFG_DT /* Callback for "interrupts" and "interrupts-extended" DT node properties */ static TEE_Result dt_get_gic_chip_cb(struct dt_pargs *arg, void *priv_data, struct itr_desc *itr_desc) { int itr_num = DT_INFO_INVALID_INTERRUPT; struct itr_chip *chip = priv_data; uint32_t phandle_args[2] = { }; uint32_t type = 0; uint32_t prio = 0; assert(arg && itr_desc); /* * gic_dt_get_irq() expects phandle arguments passed are still in DT * format (big-endian) whereas struct dt_pargs carries converted * formats. Therefore swap again phandle arguments. gic_dt_get_irq() * consumes only the 2 first arguments. */ if (arg->args_count < 2) return TEE_ERROR_GENERIC; phandle_args[0] = cpu_to_fdt32(arg->args[0]); phandle_args[1] = cpu_to_fdt32(arg->args[1]); itr_num = gic_dt_get_irq((const void *)phandle_args, 2, &type, &prio); if (itr_num == DT_INFO_INVALID_INTERRUPT) return TEE_ERROR_GENERIC; gic_op_add(chip, itr_num, type, prio); itr_desc->chip = chip; itr_desc->itr_num = itr_num; return TEE_SUCCESS; } static TEE_Result gic_probe(const void *fdt, int offs, const void *cd __unused) { if (interrupt_register_provider(fdt, offs, dt_get_gic_chip_cb, &gic_data.chip)) panic(); return TEE_SUCCESS; } static const struct dt_device_match gic_match_table[] = { { .compatible = "arm,cortex-a15-gic" }, { .compatible = "arm,cortex-a7-gic" }, { .compatible = "arm,cortex-a5-gic" }, { .compatible = "arm,cortex-a9-gic" }, { .compatible = "arm,gic-400" }, { } }; DEFINE_DT_DRIVER(gic_dt_driver) = { .name = "gic", .match_table = gic_match_table, .probe = gic_probe, }; #endif /*CFG_DT*/ static TEE_Result gic_set_primary_done(void) { gic_primary_done = true; return TEE_SUCCESS; } nex_release_init_resource(gic_set_primary_done); optee_os-4.3.0/core/drivers/gpio/000077500000000000000000000000001464416617300167135ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/gpio/gpio.c000066400000000000000000000027201464416617300200160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Microchip */ #include #include #include #include #include #include TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **out_gpio) { struct gpio *gpio = NULL; if (pargs->args_count != 2) return TEE_ERROR_BAD_PARAMETERS; gpio = calloc(1, sizeof(struct gpio)); if (!gpio) return TEE_ERROR_OUT_OF_MEMORY; gpio->pin = pargs->args[0]; gpio->dt_flags = pargs->args[1]; *out_gpio = gpio; return TEE_SUCCESS; } static char *gpio_get_dt_prop_name(const char *gpio_name) { int ret = 0; char *prop_name = NULL; size_t max_len = strlen(gpio_name) + strlen("-gpios") + 1; prop_name = calloc(1, max_len); if (!prop_name) return NULL; ret = snprintf(prop_name, max_len, "%s-gpios", gpio_name); if (ret < 0 || (size_t)ret >= max_len) { free(prop_name); return NULL; } return prop_name; } TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, unsigned int index, const char *gpio_name, struct gpio **gpio) { TEE_Result res = TEE_ERROR_GENERIC; char *prop_name = NULL; void *out_gpio = NULL; prop_name = gpio_get_dt_prop_name(gpio_name); if (!prop_name) return TEE_ERROR_OUT_OF_MEMORY; res = dt_driver_device_from_node_idx_prop(prop_name, fdt, nodeoffset, index, DT_DRIVER_GPIO, &out_gpio); free(prop_name); if (!res) *gpio = out_gpio; return res; } optee_os-4.3.0/core/drivers/gpio/sub.mk000066400000000000000000000000211464416617300200260ustar00rootroot00000000000000srcs-y += gpio.c optee_os-4.3.0/core/drivers/hfic.c000066400000000000000000000043321464416617300170340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #include #include #include #include #include /* * For documentation of the paravirtualized interface see: * https://hafnium.readthedocs.io/en/latest/design/secure-partition-manager.html#paravirtualized-interfaces */ #define HF_INTERRUPT_ENABLE 0xff03 #define HF_INTERRUPT_GET 0xff04 #define HF_INTERRUPT_DEACTIVATE 0xff08 #define HF_INTERRUPT_RECONFIGURE 0xff09 #define HF_INVALID_INTID 0xffffffff #define HF_MANAGED_EXIT_INTID 4 #define HF_INTERRUPT_TYPE_IRQ 0 #define HF_INTERRUPT_TYPE_FIQ 1 #define HF_ENABLE 1 #define HF_DISABLE 0 #define HF_INT_RECONFIGURE_STATUS 2 struct hfic_data { struct itr_chip chip; }; static struct hfic_data hfic_data __nex_bss; static void hfic_op_add(struct itr_chip *chip __unused, size_t it, uint32_t type __unused, uint32_t prio __unused) { uint32_t res __maybe_unused = 0; res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE, HF_INTERRUPT_TYPE_IRQ); assert(!res); } static void hfic_op_enable(struct itr_chip *chip __unused, size_t it) { uint32_t res __maybe_unused = 0; res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it, HF_INT_RECONFIGURE_STATUS, HF_ENABLE); assert(!res); } static void hfic_op_disable(struct itr_chip *chip __unused, size_t it) { uint32_t res __maybe_unused = 0; res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it, HF_INT_RECONFIGURE_STATUS, HF_DISABLE); assert(!res); } static const struct itr_ops hfic_ops = { .add = hfic_op_add, .mask = hfic_op_disable, .unmask = hfic_op_enable, .enable = hfic_op_enable, .disable = hfic_op_disable, }; void hfic_init(void) { hfic_data.chip.ops = &hfic_ops; interrupt_main_init(&hfic_data.chip); } /* Override interrupt_main_handler() with driver implementation */ void interrupt_main_handler(void) { uint32_t id = 0; uint32_t res __maybe_unused = 0; id = thread_hvc(HF_INTERRUPT_GET, 0, 0, 0); if (id == HF_INVALID_INTID) { DMSG("ignoring invalid interrupt %#"PRIx32, id); return; } interrupt_call_handlers(&hfic_data.chip, id); res = thread_hvc(HF_INTERRUPT_DEACTIVATE, id, id, 0); assert(!res); } optee_os-4.3.0/core/drivers/hi16xx_rng.c000066400000000000000000000050221464416617300201150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ /* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */ #include #include #include #include #include #include #include #include #include #include #include /* ALG sub-controller registers */ #define ALG_SC_RNG_RESET_DREQ 0xAB4 /* RNG reset cancel */ # define ALG_SC_SRST_DREQ_RNG BIT(0) /* RNG registers */ #define RNG_SEED 0x0 /* Initial seed */ #define RNG_CTRL 0x4 /* Control register */ # define RNG_SEED_SEL BIT(2) /* Re-seed source: 1: ring osc., 0: LFSR */ # define RNG_RING_EN BIT(1) /* Enable ring oscillator */ # define RNG_EN BIT(0) /* Enable RNG */ #define RNG_NUM 0x10 /* Random number output */ #define RNG_PHY_SEED 0x14 /* Ring oscillator output */ register_phys_mem_pgdir(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); static unsigned int rng_lock = SPINLOCK_UNLOCK; static TEE_Result hi16xx_rng_init(void) { vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC, ALG_SC_REG_SIZE); vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_REG_SIZE); TEE_Time time; /* ALG sub-controller must allow RNG out of reset */ io_write32(alg + ALG_SC_RNG_RESET_DREQ, ALG_SC_SRST_DREQ_RNG); /* Set initial seed */ tee_time_get_sys_time(&time); io_write32(rng + RNG_SEED, time.seconds * 1000 + time.millis); /* * Enable RNG and configure it to re-seed automatically from the * internal ring oscillator */ io_write32(rng + RNG_CTRL, RNG_EN | RNG_RING_EN | RNG_SEED_SEL); IMSG("Hi16xx RNG initialized"); return TEE_SUCCESS; } TEE_Result hw_get_random_bytes(void *buf, size_t len) { static vaddr_t r; static int pos; static union { uint32_t val; uint8_t byte[4]; } random; size_t buffer_pos = 0; uint8_t *buffer = buf; uint32_t exceptions; exceptions = cpu_spin_lock_xsave(&rng_lock); if (!r) r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, 1) + RNG_NUM; cpu_spin_unlock_xrestore(&rng_lock, exceptions); while (buffer_pos < len) { exceptions = cpu_spin_lock_xsave(&rng_lock); /* Refill our FIFO */ if (pos == 0) random.val = io_read32(r); buffer[buffer_pos++] = random.byte[pos++]; if (pos == 4) pos = 0; cpu_spin_unlock_xrestore(&rng_lock, exceptions); } return TEE_SUCCESS; } driver_init(hi16xx_rng_init); optee_os-4.3.0/core/drivers/hi16xx_uart.c000066400000000000000000000067571464416617300203220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include /* Register offsets */ #define UART_RBR 0x00 /* RX data buffer register */ #define UART_THR 0x00 /* TX data buffer register */ #define UART_DLL 0x00 /* Lower-bit frequency divider register */ #define UART_IEL 0x04 /* Interrupt enable register */ #define UART_DLH 0x04 /* Upper-bit frequency divider register */ #define UART_FCR 0x08 /* FIFO control register */ #define UART_LCR 0x0C /* Line control register */ #define UART_LSR 0x14 /* Line status register */ #define UART_USR 0x7C /* Status register */ /* * Line control register */ /* Data length selection */ #define UART_LCR_DLS5 0x0 /* 5 bits */ #define UART_LCR_DLS6 0x1 /* 6 bits */ #define UART_LCR_DLS7 0x2 /* 7 bits */ #define UART_LCR_DLS8 0x3 /* 8 bits */ /* Enable access to UART_DLL and UART_DLH */ #define UART_LCR_DLAB 0x80 /* * FIFO control register */ #define UART_FCR_FIFO_EN 0x1 /* Enable FIFO (depth: 32 bytes) */ #define UART_FCR_RX_FIFO_RST 0x2 /* Clear receive FIFO (auto reset) */ #define UART_FCR_TX_FIFO_RST 0x4 /* Clear send FIFO (auto reset) */ /* * Status register */ #define UART_USR_BUSY_BIT 0 /* 0: idle/non-activated, 1: busy */ #define UART_USR_TFNF_BIT 1 /* Transmit FIFO not full bit */ #define UART_USR_TFE_BIT 2 /* Transmit FIFO empty bit */ #define UART_USR_RFNE_BIT 3 /* Receive FIFO not empty bit */ #define UART_USR_RFF_BIT 4 /* Receive FIFO full bit */ static vaddr_t chip_to_base(struct serial_chip *chip) { struct hi16xx_uart_data *pd = container_of(chip, struct hi16xx_uart_data, chip); return io_pa_or_va(&pd->base, HI16XX_UART_REG_SIZE); } static void hi16xx_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + UART_USR) & UART_USR_TFE_BIT)) ; } static void hi16xx_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); /* Wait until TX FIFO is empty */ while (!(io_read32(base + UART_USR) & UART_USR_TFE_BIT)) ; /* Put character into TX FIFO */ io_write32(base + UART_THR, ch & 0xFF); } static bool hi16xx_uart_have_rx_data(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); return (io_read32(base + UART_USR) & UART_USR_RFNE_BIT); } static int hi16xx_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!hi16xx_uart_have_rx_data(chip)) ; return io_read32(base + UART_RBR) & 0xFF; } static const struct serial_ops hi16xx_uart_ops = { .flush = hi16xx_uart_flush, .getchar = hi16xx_uart_getchar, .have_rx_data = hi16xx_uart_have_rx_data, .putc = hi16xx_uart_putc, }; DECLARE_KEEP_PAGER(hi16xx_uart_ops); void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate) { uint16_t freq_div = uart_clk / (16 * baud_rate); pd->base.pa = base; pd->chip.ops = &hi16xx_uart_ops; /* Enable (and clear) FIFOs */ io_write32(base + UART_FCR, UART_FCR_FIFO_EN); /* Enable access to _DLL and _DLH */ io_write32(base + UART_LCR, UART_LCR_DLAB); /* Calculate and set UART_DLL */ io_write32(base + UART_DLL, freq_div & 0xFF); /* Calculate and set UART_DLH */ io_write32(base + UART_DLH, (freq_div >> 8) & 0xFF); /* Clear _DLL/_DLH access bit, set data size (8 bits), parity etc. */ io_write32(base + UART_LCR, UART_LCR_DLS8); /* Disable interrupt mode */ io_write32(base + UART_IEL, 0); hi16xx_uart_flush(&pd->chip); } optee_os-4.3.0/core/drivers/hisi_trng.c000066400000000000000000000036731464416617300201200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* Copyright (c) 2023 HiSilicon Limited. */ #include #include #include #include #include #include #include #include #define HTRNG_RANDATA_REG 0xF0 #define HTRNG_BYTES 4U #define POLL_PERIOD 10 #define POLL_TIMEOUT 1000 struct hisi_trng { vaddr_t base; }; static unsigned int trng_lock = SPINLOCK_UNLOCK; static struct hisi_trng *trng_dev; static TEE_Result trng_read(uint32_t *val) { TEE_Result ret = TEE_SUCCESS; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&trng_lock); if (IO_READ32_POLL_TIMEOUT(trng_dev->base + HTRNG_RANDATA_REG, *val, *val, POLL_PERIOD, POLL_TIMEOUT)) { EMSG("Hardware busy"); ret = TEE_ERROR_BUSY; } cpu_spin_unlock_xrestore(&trng_lock, exceptions); return ret; } TEE_Result hw_get_random_bytes(void *buf, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; size_t current_len = 0; uint32_t val = 0; size_t size = 0; if (!trng_dev) { EMSG("No valid TRNG device"); return TEE_ERROR_NOT_SUPPORTED; } if (!buf || !len) { EMSG("Invalid input parameter"); return TEE_ERROR_BAD_PARAMETERS; } while (current_len < len) { ret = trng_read(&val); if (ret) return TEE_ERROR_BUSY; size = MIN(HTRNG_BYTES, len - current_len); memcpy((uint8_t *)buf + current_len, &val, size); current_len += size; } return TEE_SUCCESS; } static TEE_Result trng_init(void) { DMSG("TRNG driver init start"); trng_dev = calloc(1, sizeof(struct hisi_trng)); if (!trng_dev) { EMSG("Fail to calloc trng device"); return TEE_ERROR_OUT_OF_MEMORY; } trng_dev->base = (vaddr_t)phys_to_virt_io(HISI_TRNG_BASE, HISI_TRNG_SIZE); if (!trng_dev->base) { EMSG("Fail to get trng io_base"); free(trng_dev); trng_dev = NULL; return TEE_ERROR_ACCESS_DENIED; } DMSG("TRNG driver init done"); return TEE_SUCCESS; } early_init(trng_init); optee_os-4.3.0/core/drivers/i2c/000077500000000000000000000000001464416617300164325ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/i2c/atmel_i2c.c000066400000000000000000000200251464416617300204340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021-2023 Microchip */ #include #include #include #include #include #include #include #include #include #include #include #define TWIHS_CR 0x0 #define TWIHS_CR_SWRST BIT(7) #define TWIHS_CR_SVDIS BIT(5) #define TWIHS_CR_MSEN BIT(2) #define TWIHS_CR_STOP BIT(1) #define TWIHS_CR_START BIT(0) #define TWIHS_MMR 0x4 #define TWIHS_MMR_DADR_SHIFT 16 #define TWIHS_MMR_DADR_MASK 0x7F #define TWIHS_MMR_MREAD BIT32(12) #define TWIHS_CWGR 0x10 #define TWIHS_CWGR_HOLD_SHIFT 24 #define TWIHS_CWGR_HOLD_MAX 0x1F #define TWIHS_CWGR_CKDIV_SHIFT 16 #define TWIHS_CWGR_CKDIV_MAX 0x7 #define TWIHS_CWGR_CHDIV_SHIFT 8 #define TWIHS_CKSRC BIT32(20) #define TWIHS_SR 0x20 #define TWIHS_SR_NACK BIT32(8) #define TWIHS_SR_TXRDY BIT32(2) #define TWIHS_SR_RXRDY BIT32(1) #define TWIHS_SR_TXCOMP BIT32(0) #define TWIHS_RHR 0x30 #define TWIHS_THR 0x34 #define TWIHS_WPMR 0xE4 #define TWIHS_WPMR_WPKEY SHIFT_U32(0x545749, 8) #define I2C_BUS_FREQ 400000 struct atmel_i2c { uint32_t sda_hold_time; vaddr_t base; struct clk *clk; struct i2c_ctrl i2c_ctrl; }; static struct atmel_i2c *atmel_i2c_from_i2c_ctrl(struct i2c_ctrl *i2c_ctrl) { return container_of(i2c_ctrl, struct atmel_i2c, i2c_ctrl); } static TEE_Result atmel_i2c_send_one_byte(struct atmel_i2c *i2c, uint8_t byte) { uint32_t sr = 0; io_write32(i2c->base + TWIHS_THR, byte); while (true) { sr = io_read32(i2c->base + TWIHS_SR); if (sr & TWIHS_SR_NACK) { EMSG("I2C received NACK while writing"); return TEE_ERROR_GENERIC; } if (sr & TWIHS_SR_TXRDY) break; } return TEE_SUCCESS; } static void atmel_i2c_wait_txcomp(struct atmel_i2c *i2c) { uint32_t sr = 0; while (true) { sr = io_read32(i2c->base + TWIHS_SR); if (sr & TWIHS_SR_TXCOMP) return; } } static void atmel_i2c_send_start(struct atmel_i2c *i2c) { io_write32(i2c->base + TWIHS_CR, TWIHS_CR_START); } static void atmel_i2c_send_stop(struct atmel_i2c *i2c) { io_write32(i2c->base + TWIHS_CR, TWIHS_CR_STOP); } static TEE_Result atmel_i2c_write_data_no_stop(struct i2c_dev *i2c_dev, const uint8_t *buf, size_t len) { size_t i = 0; TEE_Result res = TEE_ERROR_GENERIC; struct atmel_i2c *i2c = atmel_i2c_from_i2c_ctrl(i2c_dev->ctrl); uint32_t mmr = SHIFT_U32(i2c_dev->addr, TWIHS_MMR_DADR_SHIFT); io_write32(i2c->base + TWIHS_MMR, mmr); for (i = 0; i < len; i++) { res = atmel_i2c_send_one_byte(i2c, buf[i]); if (res) return res; } return TEE_SUCCESS; } static TEE_Result atmel_i2c_write_data(struct i2c_dev *i2c_dev, const uint8_t *buf, size_t len) { TEE_Result res = TEE_ERROR_GENERIC; struct atmel_i2c *i2c = atmel_i2c_from_i2c_ctrl(i2c_dev->ctrl); res = atmel_i2c_write_data_no_stop(i2c_dev, buf, len); if (res) return res; atmel_i2c_send_stop(i2c); atmel_i2c_wait_txcomp(i2c); return TEE_SUCCESS; } static TEE_Result atmel_i2c_recv_one_byte(struct atmel_i2c *i2c, uint8_t *byte) { uint32_t sr = 0; while (true) { sr = io_read32(i2c->base + TWIHS_SR); if (sr & TWIHS_SR_NACK) { EMSG("I2C received NACK while reading"); return TEE_ERROR_GENERIC; } if (sr & TWIHS_SR_RXRDY) break; } *byte = io_read32(i2c->base + TWIHS_RHR); return TEE_SUCCESS; } static TEE_Result atmel_i2c_read_data(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len) { size_t i = 0; TEE_Result res = TEE_ERROR_GENERIC; struct atmel_i2c *i2c = atmel_i2c_from_i2c_ctrl(i2c_dev->ctrl); uint32_t mmr = TWIHS_MMR_MREAD | SHIFT_U32(i2c_dev->addr, TWIHS_MMR_DADR_SHIFT); io_write32(i2c->base + TWIHS_MMR, mmr); atmel_i2c_send_start(i2c); for (i = 0; i < len; i++) { if (i == len - 1) atmel_i2c_send_stop(i2c); res = atmel_i2c_recv_one_byte(i2c, &buf[i]); if (res) return res; } atmel_i2c_wait_txcomp(i2c); return TEE_SUCCESS; } static TEE_Result atmel_i2c_smbus(struct i2c_dev *i2c_dev, enum i2c_smbus_dir dir, enum i2c_smbus_protocol proto __unused, uint8_t cmd_code, uint8_t buf[I2C_SMBUS_MAX_BUF_SIZE], size_t len) { TEE_Result res = TEE_ERROR_GENERIC; /* Send command code first */ res = atmel_i2c_write_data_no_stop(i2c_dev, &cmd_code, 1); if (res) return res; if (dir == I2C_SMBUS_READ) return atmel_i2c_read_data(i2c_dev, buf, len); else return atmel_i2c_write_data(i2c_dev, buf, len); } static unsigned int flsi(unsigned int val) { if (val == 0) return 0; return sizeof(unsigned int) * 8 - __builtin_clz(val); } static TEE_Result atmel_i2c_init_clk(struct atmel_i2c *i2c) { long div = 0; long hold = 0; uint32_t cwgr = 0; uint32_t cxdiv = 0; uint32_t ckdiv = 0; unsigned long clk = clk_get_rate(i2c->clk); /* * Since we will configure both CHDIV and CLDIV with the same value * use 2 * clk */ div = UDIV_ROUND_NEAREST(clk, 2 * I2C_BUS_FREQ) - 3; if (div < 0) div = 0; /* CHDIV/CLDIV are on 8 bits, CKDIV on 3 bits */ ckdiv = flsi(div >> 8); if (ckdiv > TWIHS_CWGR_CKDIV_MAX) { EMSG("CKDIV value too large"); return TEE_ERROR_BAD_PARAMETERS; } cxdiv = div >> ckdiv; if (i2c->sda_hold_time) { /* hold_time = (HOLD + 3) x tperipheral clock */ hold = UDIV_ROUND_NEAREST(i2c->sda_hold_time * clk, 1000000000); hold -= 3; if (hold < 0 || hold > TWIHS_CWGR_HOLD_MAX) { EMSG("Incorrect hold value"); return TEE_ERROR_BAD_PARAMETERS; } cwgr |= hold << TWIHS_CWGR_HOLD_SHIFT; } cwgr |= ckdiv << TWIHS_CWGR_CKDIV_SHIFT; /* CHDIV == CLDIV */ cwgr |= cxdiv << TWIHS_CWGR_CHDIV_SHIFT; cwgr |= cxdiv; io_write32(i2c->base + TWIHS_CWGR, cwgr); return TEE_SUCCESS; } static TEE_Result atmel_i2c_init_hw(struct atmel_i2c *i2c) { /* Unlock TWIHS IP */ io_write32(i2c->base + TWIHS_WPMR, TWIHS_WPMR_WPKEY); /* Configure master mode */ io_write32(i2c->base + TWIHS_CR, TWIHS_CR_SWRST); io_write32(i2c->base + TWIHS_CR, TWIHS_CR_SVDIS); io_write32(i2c->base + TWIHS_CR, TWIHS_CR_MSEN); return atmel_i2c_init_clk(i2c); } static const struct i2c_ctrl_ops atmel_i2c_ops = { .read = atmel_i2c_read_data, .write = atmel_i2c_write_data, .smbus = atmel_i2c_smbus, }; static TEE_Result atmel_i2c_get_dt_i2c(struct dt_pargs *args, void *data, struct i2c_dev **out_device) { struct i2c_dev *i2c_dev = NULL; struct i2c_ctrl *i2c_ctrl = data; i2c_dev = i2c_create_dev(i2c_ctrl, args->fdt, args->phandle_node); if (!i2c_dev) return TEE_ERROR_OUT_OF_MEMORY; *out_device = i2c_dev; return TEE_SUCCESS; } static TEE_Result atmel_i2c_node_probe(const void *fdt, int node, const void *compat_data __unused) { size_t size = 0; const uint32_t *cuint = 0; unsigned int matrix_id = 0; struct i2c_ctrl *i2c_ctrl = NULL; struct atmel_i2c *atmel_i2c = NULL; TEE_Result res = TEE_ERROR_GENERIC; int status = fdt_get_status(fdt, node); if (status != DT_STATUS_OK_SEC) return TEE_SUCCESS; atmel_i2c = calloc(1, sizeof(struct atmel_i2c)); if (!atmel_i2c) return TEE_ERROR_OUT_OF_MEMORY; i2c_ctrl = &atmel_i2c->i2c_ctrl; i2c_ctrl->ops = &atmel_i2c_ops; res = clk_dt_get_by_index(fdt, node, 0, &atmel_i2c->clk); if (res) goto err_free; res = matrix_dt_get_id(fdt, node, &matrix_id); if (res) goto err_free; if (dt_map_dev(fdt, node, &atmel_i2c->base, &size, DT_MAP_AUTO) < 0) { res = TEE_ERROR_GENERIC; goto err_free; } matrix_configure_periph_secure(matrix_id); cuint = fdt_getprop(fdt, node, "i2c-sda-hold-time-ns", NULL); if (cuint) atmel_i2c->sda_hold_time = fdt32_to_cpu(*cuint); clk_enable(atmel_i2c->clk); res = atmel_i2c_init_hw(atmel_i2c); if (res) goto err_clk_disable; res = i2c_register_provider(fdt, node, atmel_i2c_get_dt_i2c, i2c_ctrl); if (res) goto err_clk_disable; return TEE_SUCCESS; err_clk_disable: clk_disable(atmel_i2c->clk); err_free: free(atmel_i2c); return res; } static const struct dt_device_match atmel_i2c_match_table[] = { { .compatible = "atmel,sama5d2-i2c" }, { } }; DEFINE_DT_DRIVER(atmel_i2c_dt_driver) = { .name = "atmel_i2c", .type = DT_DRIVER_NOTYPE, .match_table = atmel_i2c_match_table, .probe = atmel_i2c_node_probe, }; optee_os-4.3.0/core/drivers/i2c/i2c.c000066400000000000000000000012141464416617300172510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2023 Microchip */ #include #include #include #include #include #include #include #include struct i2c_dev *i2c_create_dev(struct i2c_ctrl *i2c_ctrl, const void *fdt, int node) { struct i2c_dev *i2c_dev = NULL; paddr_t addr = fdt_reg_base_address(fdt, node); if (addr == DT_INFO_INVALID_REG) return NULL; i2c_dev = calloc(1, sizeof(struct i2c_dev)); if (!i2c_dev) return NULL; i2c_dev->addr = addr; i2c_dev->ctrl = i2c_ctrl; return i2c_dev; } optee_os-4.3.0/core/drivers/i2c/sub.mk000066400000000000000000000000641464416617300175540ustar00rootroot00000000000000srcs-y += i2c.c srcs-$(CFG_ATMEL_I2C) += atmel_i2c.coptee_os-4.3.0/core/drivers/imx/000077500000000000000000000000001464416617300165525ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/imx/dcp/000077500000000000000000000000001464416617300173205ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/imx/dcp/dcp.c000066400000000000000000000447771464416617300202550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const uint8_t sha1_null_msg[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09, }; static const uint8_t sha256_null_msg[] = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, }; static vaddr_t dcp_base; static bool driver_initialized; static unsigned int clk_refcount; static unsigned int key_store_spinlock = SPINLOCK_UNLOCK; static unsigned int clock_spinlock = SPINLOCK_UNLOCK; static struct dcp_align_buf hw_context_buffer; static struct mutex lock_channel[DCP_NB_CHANNELS] = { [DCP_CHANN0] = MUTEX_INITIALIZER, [DCP_CHANN1] = MUTEX_INITIALIZER, [DCP_CHANN2] = MUTEX_INITIALIZER, [DCP_CHANN3] = MUTEX_INITIALIZER, }; static const struct dcp_hashalg hash_alg[2] = { [DCP_SHA1] = { .type = DCP_CONTROL1_HASH_SELECT_SHA1, .size = TEE_SHA1_HASH_SIZE, }, [DCP_SHA256] = { .type = DCP_CONTROL1_HASH_SELECT_SHA256, .size = TEE_SHA256_HASH_SIZE, }, }; /* * Enable/disable DCP clock. * * @enable Enable the clock if true, disable if false. */ static void dcp_clk_enable(bool enable) { vaddr_t ccm_base = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_CCGR0 + sizeof(uint32_t)); uint32_t clock_except = cpu_spin_lock_xsave(&clock_spinlock); if (enable) { if (clk_refcount > 0) { clk_refcount++; goto out; } else { clk_refcount++; io_setbits32(ccm_base + CCM_CCGR0, DCP_CLK_ENABLE_MASK); } } else { assert(clk_refcount != 0); clk_refcount--; if (clk_refcount > 0) goto out; else io_clrbits32(ccm_base + CCM_CCGR0, DCP_CLK_ENABLE_MASK); } out: cpu_spin_unlock_xrestore(&clock_spinlock, clock_except); } /* * Lock the given channel with a mutex. * * @chan DCP channel to lock */ static TEE_Result dcp_lock_known_channel(enum dcp_channel chan) { if (mutex_trylock(&lock_channel[chan])) return TEE_SUCCESS; else return TEE_ERROR_BUSY; } /* * Lock a DCP channel * * @channel Pointer on operation channel parameter */ static TEE_Result dcp_lock_channel(enum dcp_channel *channel) { TEE_Result ret = TEE_ERROR_BUSY; enum dcp_channel chan = DCP_CHANN0; for (chan = DCP_CHANN0; chan < DCP_NB_CHANNELS; chan++) { ret = dcp_lock_known_channel(chan); if (ret == TEE_SUCCESS) { *channel = chan; return ret; } } EMSG("All channels are busy"); return ret; } /* * Unlock the given channel. * * @chan DCP channel to unlock */ static void dcp_unlock_channel(enum dcp_channel chan) { mutex_unlock(&lock_channel[chan]); } /* * Start the DCP operation. * * @dcp_data Structure containing dcp_descriptor configuration and channel to * use. */ static TEE_Result dcp_run(struct dcp_data *dcp_data) { TEE_Result ret = TEE_SUCCESS; unsigned int timeout = 0; uint32_t val = 0; dcp_data->desc.next = 0; cache_operation(TEE_CACHEFLUSH, &dcp_data->desc, sizeof(dcp_data->desc)); /* Enable clock if it's not done */ dcp_clk_enable(true); /* Clear DCP_STAT IRQ field for the channel used by the operation */ io_clrbits32(dcp_base + DCP_STAT, BIT32(dcp_data->channel)); /* Clear CH_N_STAT to clear IRQ and error codes */ io_write32(dcp_base + DCP_CH_N_STAT(dcp_data->channel), 0x0); /* Update descriptor structure to be processed for the channel */ io_write32(dcp_base + DCP_CH_N_CMDPTR(dcp_data->channel), virt_to_phys(&dcp_data->desc)); /* Increment the semaphore to start the transfer */ io_write32(dcp_base + DCP_CH_N_SEMA(dcp_data->channel), 0x1); for (timeout = 0; timeout < DCP_MAX_TIMEOUT; timeout++) { dcp_udelay(10); val = io_read32(dcp_base + DCP_STAT); if (val & BIT(dcp_data->channel)) break; } if (timeout == DCP_MAX_TIMEOUT) { EMSG("Timeout elapsed before operation"); ret = TEE_ERROR_GENERIC; goto out; } val = io_read32(dcp_base + DCP_CH_N_STAT(dcp_data->channel)); if (val & DCP_CH_STAT_ERROR_MASK) { EMSG("Error operation, 0x%" PRIx32, val); ret = TEE_ERROR_GENERIC; } out: dcp_clk_enable(false); return ret; } static TEE_Result dcp_cmac_subkey_generation(struct dcp_cipher_init *init, uint8_t *k1, uint8_t *k2) { TEE_Result ret = TEE_ERROR_GENERIC; struct dcp_cipher_data data = { }; uint8_t l[16] = { }; uint8_t tmp[16] = { }; uint8_t const_zero[16] = { }; uint8_t const_rb[16] = { [15] = 0x87 }; ret = dcp_cipher_do_init(&data, init); if (ret != TEE_SUCCESS) return ret; ret = dcp_cipher_do_update(&data, const_zero, l, sizeof(l)); if (ret != TEE_SUCCESS) goto out; if ((l[0] & BIT(7)) == 0) { dcp_left_shift_buffer(l, k1, 16); } else { dcp_left_shift_buffer(l, tmp, 16); dcp_xor(tmp, const_rb, k1, 16); } if ((k1[0] & BIT(7)) == 0) { dcp_left_shift_buffer(k1, k2, 16); } else { dcp_left_shift_buffer(k1, tmp, 16); dcp_xor(tmp, const_rb, k2, 16); } ret = TEE_SUCCESS; out: dcp_cipher_do_final(&data); return ret; } TEE_Result dcp_store_key(uint32_t *key, unsigned int index) { uint32_t val = 0; unsigned int i = 0; uint32_t key_store_except = 0; if (!key) return TEE_ERROR_BAD_PARAMETERS; if (index > DCP_SRAM_KEY_NB_SUBWORD - 1) { EMSG("Bad parameters, index must be < %u", DCP_SRAM_KEY_NB_SUBWORD); return TEE_ERROR_BAD_PARAMETERS; } key_store_except = cpu_spin_lock_xsave(&key_store_spinlock); dcp_clk_enable(true); val = DCP_SRAM_KEY_INDEX(index); io_write32(dcp_base + DCP_KEY, val); /* * Key is stored as four uint32 values, starting with subword0 * (least-significant word) */ for (i = 0; i < DCP_SRAM_KEY_NB_SUBWORD; i++) { val = TEE_U32_TO_BIG_ENDIAN(key[i]); io_write32(dcp_base + DCP_KEYDATA, val); } dcp_clk_enable(false); cpu_spin_unlock_xrestore(&key_store_spinlock, key_store_except); return TEE_SUCCESS; } TEE_Result dcp_cmac(struct dcp_cipher_init *init, uint8_t *input, size_t input_size, uint8_t *output) { TEE_Result ret = TEE_ERROR_GENERIC; uint8_t key1[DCP_AES128_KEY_SIZE] = { }; uint8_t key2[DCP_AES128_KEY_SIZE] = { }; unsigned int nb_blocks = 0; bool block_complete = false; struct dcp_cipher_data data = { }; uint8_t y[DCP_AES128_BLOCK_SIZE] = { }; uint8_t x[DCP_AES128_BLOCK_SIZE] = { }; uint8_t last[DCP_AES128_BLOCK_SIZE] = { }; unsigned int i = 0; uint8_t offset = 0; if (!output || !init) return TEE_ERROR_BAD_PARAMETERS; if (!input && input_size) return TEE_ERROR_BAD_PARAMETERS; ret = dcp_cipher_do_init(&data, init); if (ret != TEE_SUCCESS) { ret = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* Generate CMAC subkeys */ ret = dcp_cmac_subkey_generation(init, key1, key2); if (ret != TEE_SUCCESS) goto out; /* Get number of block */ nb_blocks = ROUNDUP(input_size, DCP_AES128_BLOCK_SIZE) / DCP_AES128_BLOCK_SIZE; block_complete = nb_blocks && !(input_size % DCP_AES128_BLOCK_SIZE); if (nb_blocks == 0) nb_blocks = 1; for (i = 0; i < nb_blocks - 1; i++) { dcp_xor(x, input + offset, y, DCP_AES128_BLOCK_SIZE); ret = dcp_cipher_do_update(&data, y, x, DCP_AES128_BLOCK_SIZE); if (ret) goto out; offset += DCP_AES128_BLOCK_SIZE; } /* Process the last block */ memcpy(last, input + offset, input_size - offset); if (block_complete) { dcp_xor(last, key1, last, DCP_AES128_BLOCK_SIZE); } else { dcp_cmac_padding(last, input_size % DCP_AES128_BLOCK_SIZE); dcp_xor(last, key2, last, DCP_AES128_BLOCK_SIZE); } dcp_xor(x, last, y, DCP_AES128_BLOCK_SIZE); ret = dcp_cipher_do_update(&data, y, x, DCP_AES128_BLOCK_SIZE); if (ret) goto out; memcpy(output, x, DCP_AES128_BLOCK_SIZE); out: dcp_cipher_do_final(&data); return ret; } TEE_Result dcp_cipher_do_init(struct dcp_cipher_data *data, struct dcp_cipher_init *init) { struct dcp_descriptor *desc = NULL; TEE_Result ret = TEE_ERROR_GENERIC; if (!init || !data) return TEE_ERROR_BAD_PARAMETERS; ret = dcp_lock_channel(&data->dcp_data.channel); if (ret != TEE_SUCCESS) return ret; desc = &data->dcp_data.desc; desc->ctrl0 = DCP_CONTROL0_DECR_SEMAPHORE | DCP_CONTROL0_ENABLE_CIPHER | DCP_CONTROL0_INTERRUPT_ENABLE; desc->ctrl1 = DCP_CONTROL1_CIPHER_SELECT_AES128; if (init->op == DCP_ENCRYPT) desc->ctrl0 |= DCP_CONTROL0_CIPHER_ENCRYPT; if (init->key_mode == DCP_OTP) { desc->ctrl0 &= ~DCP_CONTROL0_OTP_KEY; desc->ctrl1 |= DCP_CONTROL1_KEY_SELECT_OTP_CRYPTO; } else if (init->key_mode == DCP_PAYLOAD) { desc->ctrl0 |= DCP_CONTROL0_PAYLOAD_KEY; if (!init->key) return TEE_ERROR_BAD_PARAMETERS; memcpy(data->key, init->key, DCP_AES128_KEY_SIZE); } else { desc->ctrl1 |= SHIFT_U32(init->key_mode, 8); } if (init->mode == DCP_CBC) { desc->ctrl0 |= DCP_CONTROL0_CIPHER_INIT; desc->ctrl1 |= DCP_CONTROL1_CIPHER_MODE_CBC; if (!init->iv) return TEE_ERROR_BAD_PARAMETERS; memcpy(data->iv, init->iv, DCP_AES128_IV_SIZE); } /* Allocate aligned buffer for dcp iv and key */ ret = dcp_calloc_align_buf(&data->payload, DCP_AES128_IV_SIZE + DCP_AES128_KEY_SIZE); if (ret != TEE_SUCCESS) return ret; desc->src_buffer = 0; desc->dest_buffer = 0; desc->status = 0; desc->buff_size = 0; desc->next = virt_to_phys(desc); data->initialized = true; return ret; } TEE_Result dcp_cipher_do_update(struct dcp_cipher_data *data, const uint8_t *src, uint8_t *dst, size_t size) { TEE_Result ret = TEE_ERROR_GENERIC; struct dcp_align_buf output = { }; struct dcp_align_buf input = { }; struct dcp_descriptor *desc = NULL; if (!data || !src || !dst) return TEE_ERROR_BAD_PARAMETERS; if (!data->initialized) { EMSG("Error, please call dcp_aes_do_init() before"); return TEE_ERROR_BAD_STATE; } if (size % DCP_AES128_BLOCK_SIZE) { EMSG("Input size has to be a multiple of %zu bytes", DCP_AES128_BLOCK_SIZE); return TEE_ERROR_BAD_PARAMETERS; } ret = dcp_calloc_align_buf(&output, size); if (ret != TEE_SUCCESS) goto out; ret = dcp_calloc_align_buf(&input, size); if (ret != TEE_SUCCESS) goto out; desc = &data->dcp_data.desc; /* Copy input data */ memcpy(input.data, src, size); /* Copy key and IV */ memcpy(data->payload.data, data->key, DCP_AES128_KEY_SIZE); data->payload_size = DCP_AES128_KEY_SIZE; if (desc->ctrl0 & DCP_CONTROL0_CIPHER_INIT) { memcpy(data->payload.data + DCP_AES128_KEY_SIZE, data->iv, DCP_AES128_IV_SIZE); data->payload_size += DCP_AES128_IV_SIZE; } desc->src_buffer = input.paddr; desc->dest_buffer = output.paddr; desc->payload = data->payload.paddr; desc->buff_size = size; cache_operation(TEE_CACHECLEAN, data->payload.data, data->payload_size); cache_operation(TEE_CACHECLEAN, input.data, size); cache_operation(TEE_CACHEINVALIDATE, output.data, size); ret = dcp_run(&data->dcp_data); if (ret) goto out; cache_operation(TEE_CACHEINVALIDATE, output.data, size); desc->ctrl0 &= ~DCP_CONTROL0_CIPHER_INIT; memcpy(dst, output.data, size); out: dcp_free(&output); dcp_free(&input); return ret; } void dcp_cipher_do_final(struct dcp_cipher_data *data) { if (data) data->initialized = false; dcp_free(&data->payload); dcp_unlock_channel(data->dcp_data.channel); } TEE_Result dcp_sha_do_init(struct dcp_hash_data *hashdata) { struct dcp_descriptor *desc = NULL; TEE_Result ret = TEE_ERROR_GENERIC; if (!hashdata) { EMSG("Bad parameters, hashdata is NULL"); return TEE_ERROR_BAD_PARAMETERS; } desc = &hashdata->dcp_data.desc; /* DCP descriptor init */ desc->status = 0; desc->payload = 0; desc->dest_buffer = 0; desc->ctrl0 = DCP_CONTROL0_ENABLE_HASH | DCP_CONTROL0_INTERRUPT_ENABLE | DCP_CONTROL0_DECR_SEMAPHORE | DCP_CONTROL0_HASH_INIT; desc->ctrl1 = hash_alg[hashdata->alg].type; desc->buff_size = 0; desc->next = 0; desc->src_buffer = 0; ret = dcp_lock_channel(&hashdata->dcp_data.channel); if (ret != TEE_SUCCESS) { EMSG("Channel is busy, can't start operation now"); return ret; } /* Allocate context data */ ret = dcp_calloc_align_buf(&hashdata->ctx, DCP_SHA_BLOCK_SIZE); if (ret != TEE_SUCCESS) return ret; hashdata->initialized = true; hashdata->ctx_size = 0; return ret; } TEE_Result dcp_sha_do_update(struct dcp_hash_data *hashdata, const uint8_t *data, size_t len) { TEE_Result ret = TEE_ERROR_GENERIC; struct dcp_descriptor *desc = NULL; struct dcp_align_buf input = { }; uint32_t offset = 0; uint32_t nb_blocks = 0; size_t size_todo = 0; size_t size_left = 0; size_t size_total = 0; if (!hashdata || !data || !len) return TEE_ERROR_BAD_PARAMETERS; if (!hashdata->initialized) { EMSG("hashdata is uninitialized"); return TEE_ERROR_BAD_STATE; } /* Get number of blocks */ if (ADD_OVERFLOW(hashdata->ctx_size, len, &size_total)) return TEE_ERROR_BAD_PARAMETERS; nb_blocks = size_total / DCP_SHA_BLOCK_SIZE; size_todo = nb_blocks * DCP_SHA_BLOCK_SIZE; size_left = len - size_todo + hashdata->ctx_size; desc = &hashdata->dcp_data.desc; if (size_todo) { /* Allocate buffer as input */ ret = dcp_calloc_align_buf(&input, size_todo); if (ret != TEE_SUCCESS) return ret; /* Copy previous data if any */ offset = size_todo - hashdata->ctx_size; memcpy(input.data, hashdata->ctx.data, hashdata->ctx_size); memcpy(input.data + hashdata->ctx_size, data, offset); hashdata->ctx_size = 0; desc->src_buffer = input.paddr; desc->buff_size = size_todo; cache_operation(TEE_CACHECLEAN, input.data, size_todo); ret = dcp_run(&hashdata->dcp_data); desc->ctrl0 &= ~DCP_CONTROL0_HASH_INIT; dcp_free(&input); } else { size_left = len; offset = 0; ret = TEE_SUCCESS; } /* Save any data left */ memcpy(hashdata->ctx.data + hashdata->ctx_size, data + offset, size_left); hashdata->ctx_size += size_left; return ret; } TEE_Result dcp_sha_do_final(struct dcp_hash_data *hashdata, uint8_t *digest, size_t digest_size) { TEE_Result ret = TEE_ERROR_GENERIC; size_t payload_size = 0; struct dcp_descriptor *desc = NULL; struct dcp_align_buf payload = { }; if (!hashdata || !digest) return TEE_ERROR_BAD_PARAMETERS; if (!hashdata->initialized) { EMSG("hashdata is uninitialized"); return TEE_ERROR_BAD_STATE; } if (digest_size < hash_alg[hashdata->alg].size) { EMSG("Digest buffer size is to small, should be %" PRId32, hash_alg[hashdata->alg].size); return TEE_ERROR_BAD_PARAMETERS; } desc = &hashdata->dcp_data.desc; payload_size = hash_alg[hashdata->alg].size; /* Handle the case where the input message is NULL */ if ((desc->ctrl0 & DCP_CONTROL0_HASH_INIT) && hashdata->ctx_size == 0) { if (hashdata->alg == DCP_SHA1) memcpy(digest, sha1_null_msg, payload_size); if (hashdata->alg == DCP_SHA256) memcpy(digest, sha256_null_msg, payload_size); ret = TEE_SUCCESS; } else { /* Allocate buffer for the digest */ ret = dcp_calloc_align_buf(&payload, payload_size); if (ret != TEE_SUCCESS) return ret; /* Set work packet for last iteration */ desc->ctrl0 |= DCP_CONTROL0_HASH_TERM; desc->src_buffer = hashdata->ctx.paddr; desc->buff_size = hashdata->ctx_size; desc->payload = payload.paddr; cache_operation(TEE_CACHECLEAN, hashdata->ctx.data, hashdata->ctx_size); cache_operation(TEE_CACHEINVALIDATE, payload.data, payload_size); ret = dcp_run(&hashdata->dcp_data); /* Copy the result */ cache_operation(TEE_CACHEINVALIDATE, payload.data, payload_size); /* DCP payload result is flipped */ dcp_reverse(payload.data, digest, payload_size); dcp_free(&payload); } dcp_free(&hashdata->ctx); /* Reset hashdata strcuture */ hashdata->initialized = false; dcp_unlock_channel(hashdata->dcp_data.channel); return ret; } void dcp_disable_unique_key(void) { dcp_clk_enable(true); io_setbits32(dcp_base + DCP_CAPABILITY0, DCP_CAPABILITY0_DISABLE_UNIQUE_KEY); dcp_clk_enable(false); } #ifdef CFG_DT static const char *const dt_ctrl_match_table[] = { "fsl,imx28-dcp", "fsl,imx6sl-dcp", }; /* * Fetch DCP base address from DT * * @base [out] DCP base address */ static TEE_Result dcp_pbase(paddr_t *base) { void *fdt = NULL; int node = -1; unsigned int i = 0; fdt = get_dt(); if (!fdt) { EMSG("DTB no present"); return TEE_ERROR_ITEM_NOT_FOUND; } for (i = 0; i < ARRAY_SIZE(dt_ctrl_match_table); i++) { node = fdt_node_offset_by_compatible(fdt, 0, dt_ctrl_match_table[i]); if (node >= 0) break; } if (node < 0) { EMSG("DCP node not found err = %d", node); return TEE_ERROR_ITEM_NOT_FOUND; } if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) return TEE_ERROR_ITEM_NOT_FOUND; /* Force secure-status = "okay" and status="disabled" */ if (dt_enable_secure_status(fdt, node)) { EMSG("Not able to set DCP Control DTB entry secure"); return TEE_ERROR_NOT_SUPPORTED; } *base = fdt_reg_base_address(fdt, node); if (*base == DT_INFO_INVALID_REG) { EMSG("Unable to get the DCP Base address"); return TEE_ERROR_ITEM_NOT_FOUND; } return TEE_SUCCESS; } #endif /* CFG_DT */ TEE_Result dcp_init(void) { TEE_Result ret = TEE_ERROR_GENERIC; paddr_t pbase = 0; if (driver_initialized) return TEE_SUCCESS; dcp_clk_enable(true); ret = dcp_pbase(&pbase); if (ret != TEE_SUCCESS) pbase = DCP_BASE; dcp_base = core_mmu_get_va(pbase, MEM_AREA_IO_SEC, DCP_CONTEXT + sizeof(uint32_t)); if (!dcp_base) { EMSG("Unable to get DCP physical address"); return TEE_ERROR_ITEM_NOT_FOUND; } /* Context switching buffer memory allocation */ ret = dcp_calloc_align_buf(&hw_context_buffer, DCP_CONTEXT_BUFFER_SIZE); if (ret != TEE_SUCCESS) { EMSG("hw_context_buffer allocation failed"); return ret; } /* * Reset the DCP before initialization. Depending on the SoC lifecycle * state, the DCP needs to be reset to reload the OTP master key from * the SNVS. */ io_write32(dcp_base + DCP_CTRL_SET, DCP_CTRL_SFTRST | DCP_CTRL_CLKGATE); /* * Initialize control register. * Enable normal DCP operation (SFTRST & CLKGATE bits set to 0) */ io_write32(dcp_base + DCP_CTRL_CLR, DCP_CTRL_SFTRST | DCP_CTRL_CLKGATE); io_write32(dcp_base + DCP_CTRL_SET, DCP_CTRL_GATHER_RESIDUAL_WRITES | DCP_CTRL_ENABLE_CONTEXT_SWITCHING); /* Enable all DCP channels */ io_write32(dcp_base + DCP_CHANNELCTRL, DCP_CHANNELCTRL_ENABLE_CHANNEL_MASK); /* Clear DCP_STAT register */ io_write32(dcp_base + DCP_STAT_CLR, DCP_STAT_CLEAR); /* Copy context switching buffer address in DCP_CONTEXT register */ io_write32(dcp_base + DCP_CONTEXT, (uint32_t)hw_context_buffer.paddr); driver_initialized = true; dcp_clk_enable(false); return ret; } optee_os-4.3.0/core/drivers/imx/dcp/dcp_huk.c000066400000000000000000000041041464416617300211000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020 NXP */ #include #include #include #include #define HUK_MESSAGE_NULL_BYTE 0 #define NB_ITERATION_HUK 1 #define HUK_SIZE_BITS 128 /* State of the generated HUK */ enum dcp_huk_state { DCP_HUK_EMPTY = 0, DCP_HUK_GENERATED, DCP_HUK_ERROR, }; /* Information about HUK */ static struct { enum dcp_huk_state state; uint8_t data[HW_UNIQUE_KEY_LENGTH]; } dcp_huk = { .state = DCP_HUK_EMPTY }; /* * Generate Hardware Unique Key using the Data Co-Processor (DCP) AES128-CMAC * cryptographic operation * Follow dcp_aes_cmac() message format * * @hwkey [out] Hardware Unique Key private data */ static TEE_Result dcp_generate_huk(struct tee_hw_unique_key *hwkey) { TEE_Result res = TEE_ERROR_GENERIC; struct dcp_cipher_init init = { .key_mode = DCP_OTP, .mode = DCP_ECB, .op = DCP_ENCRYPT, }; uint8_t content[DCP_AES128_BLOCK_SIZE] = { NB_ITERATION_HUK, 'h', 'u', 'k', HUK_MESSAGE_NULL_BYTE, 'o', 'p', 't', 'e', 'e', 'o', 's', 'd', 'c', 'p', HUK_SIZE_BITS }; res = dcp_cmac(&init, content, DCP_AES128_BLOCK_SIZE, hwkey->data); dcp_disable_unique_key(); return res; } TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { TEE_Result ret = TEE_ERROR_GENERIC; if (!hwkey) { EMSG("HUK generation failed, hwkey structure is NULL"); return TEE_ERROR_BAD_PARAMETERS; } ret = dcp_init(); if (ret != TEE_SUCCESS) { dcp_huk.state = DCP_HUK_ERROR; return ret; } if (dcp_huk.state == DCP_HUK_EMPTY) { ret = dcp_generate_huk(hwkey); if (ret != TEE_SUCCESS) { dcp_huk.state = DCP_HUK_ERROR; } else { memcpy(dcp_huk.data, hwkey->data, HW_UNIQUE_KEY_LENGTH); dcp_huk.state = DCP_HUK_GENERATED; } } else if (dcp_huk.state == DCP_HUK_GENERATED) { memcpy(hwkey->data, dcp_huk.data, HW_UNIQUE_KEY_LENGTH); ret = TEE_SUCCESS; } else { ret = TEE_ERROR_GENERIC; } return ret; } optee_os-4.3.0/core/drivers/imx/dcp/dcp_utils.c000066400000000000000000000032701464416617300214540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020 NXP */ #include #include #include #include #include #include #include TEE_Result dcp_calloc_align_buf(struct dcp_align_buf *buf, size_t size) { if (!buf) { EMSG("Error, buf is null"); return TEE_ERROR_BAD_PARAMETERS; } buf->data = alloc_cache_aligned(size); if (!buf->data) return TEE_ERROR_OUT_OF_MEMORY; buf->paddr = virt_to_phys(buf->data); if (!buf->paddr) { dcp_free(buf); return TEE_ERROR_OUT_OF_MEMORY; } buf->size = size; return TEE_SUCCESS; } void dcp_free(struct dcp_align_buf *buf) { free(buf->data); } void dcp_left_shift_buffer(uint8_t *input, uint8_t *result, size_t buffer_size) { unsigned int i = 0; uint8_t overflow = 0; /* For each byte */ for (i = 0; i < buffer_size; i++) { /* Left shift a bytes by one */ result[buffer_size - 1 - i] = input[buffer_size - 1 - i] << 1 | overflow; overflow = input[buffer_size - 1 - i] >> 7; } } void dcp_udelay(uint32_t time) { uint32_t counter = time * 500; /* Implementation of a Software loop assuming CPU clock of 500MHz */ while (counter--) { isb(); dsb(); }; } void dcp_reverse(uint8_t *in, uint8_t *out, size_t size) { unsigned int i = 0; for (i = 0; i < size; i++) out[i] = in[size - 1 - i]; } void dcp_xor(uint8_t *a, uint8_t *b, uint8_t *out, size_t size) { unsigned int i = 0; for (i = 0; i < size; i++) out[i] = a[i] ^ b[i]; } void dcp_cmac_padding(uint8_t *block, size_t len) { unsigned int i = 0; for (i = len; i < DCP_AES128_BLOCK_SIZE; i++) { if (i == len) block[i] = BIT(7); else block[i] = 0x0; } } optee_os-4.3.0/core/drivers/imx/dcp/include/000077500000000000000000000000001464416617300207435ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/imx/dcp/include/dcp_utils.h000066400000000000000000000036771464416617300231170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 NXP */ #ifndef __DCP_UTILS_H__ #define __DCP_UTILS_H__ #include #include /* Adjust index value for writing in register */ #define DCP_SRAM_KEY_INDEX(idx) SHIFT_U32(idx, 4) /* Calculate context switching buffer offset */ #define DCP_CONTEXT_SW_OFFSET(chann) ((DCP_NB_CHANNELS - 1 - (chann)) * 52) /* * Allocate internal driver buffer aligned with a cache line and initialize it * with 0s * * @buf [out] Buffer to allocate * @size Size in bytes of the memory to allocate */ TEE_Result dcp_calloc_align_buf(struct dcp_align_buf *buf, size_t size); /* * Free allocated memory * * @buf buffer to free. */ void dcp_free(struct dcp_align_buf *buf); /* * Left shifting a multi bytes buffer by one bit * * @result [out] Buffer containing the result of the operation * @input Input buffer for the operation * @buffer_size Size of the buffer in bytes */ void dcp_left_shift_buffer(uint8_t *result, uint8_t *input, size_t buffer_size); /* * Wait given microsecond * * @time Time in microsecond */ void dcp_udelay(uint32_t time); /* * Copies elements from a buffer to another one. These elements are copied in * reverse order. * * @in input buffer * @out output buffer * @size bytes to copy */ void dcp_reverse(uint8_t *in, uint8_t *out, size_t size); /* * Operate a XOR between two same size buffers * * @a Input buffer to XOR * @b Input buffer to XOR * @out Result of the XOR operation * @size Size of input and output buffers */ void dcp_xor(uint8_t *a, uint8_t *b, uint8_t *out, size_t size); /* * CMAC padding. * The padding result is the concatenation of the input buffer block and a * single '1' followed by the minimum number of '0's to get a 128 bits * block. * * @block Block to pad * @len Length of the padding */ void dcp_cmac_padding(uint8_t *block, size_t len); #endif /* __DCP_UTILS_H__ */ optee_os-4.3.0/core/drivers/imx/dcp/include/local.h000066400000000000000000000004351464416617300222100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 NXP */ #ifndef __LOCAL_H__ #define __LOCAL_H__ #define DCP_CONTEXT_BUFFER_SIZE 208 #define DCP_MAX_TIMEOUT 10 #define DCP_SRAM_KEY_NB_SUBWORD 4 #define DCP_CLK_ENABLE_MASK GENMASK_32(11, 10) #endif /* __LOCAL_H__ */ optee_os-4.3.0/core/drivers/imx/dcp/sub.mk000066400000000000000000000001201464416617300204330ustar00rootroot00000000000000srcs-y += dcp_huk.c srcs-y += dcp.c srcs-y += dcp_utils.c incdirs-y += include optee_os-4.3.0/core/drivers/imx/mu/000077500000000000000000000000001464416617300171735ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/imx/mu/imx_mu.c000066400000000000000000000063111464416617300206360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 NXP */ #include #include #include #include #include #include #include "imx_mu_platform.h" #define RX_TIMEOUT (100 * 1000) static unsigned int mu_spinlock = SPINLOCK_UNLOCK; __weak void imx_mu_plat_init(vaddr_t base __unused) { } __weak TEE_Result imx_mu_plat_send(vaddr_t base __unused, unsigned int index __unused, uint32_t msg __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } __weak TEE_Result imx_mu_plat_receive(vaddr_t base __unused, unsigned int index __unused, uint32_t *msg __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } /* * Receive a message via the MU * * @base: virtual base address of the MU controller * @[out]msg: message received */ static TEE_Result imx_mu_receive_msg(vaddr_t base, struct imx_mu_msg *msg) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int count = 0; uint32_t response = 0; unsigned int nb_channel = 0; uint64_t tout_rx = timeout_init_us(RX_TIMEOUT); assert(base && msg); do { res = imx_mu_plat_receive(base, 0, &response); if (timeout_elapsed(tout_rx)) break; } while (res == TEE_ERROR_NO_DATA); if (res) return res; memcpy(&msg->header, &response, sizeof(response)); /* Check the size of the message to receive */ if (msg->header.size > IMX_MU_MSG_SIZE) { EMSG("Size of the message is > than IMX_MU_MSG_SIZE"); return TEE_ERROR_BAD_FORMAT; } nb_channel = imx_mu_plat_get_rx_channel(base); for (count = 1; count < msg->header.size; count++) { res = imx_mu_plat_receive(base, count % nb_channel, &msg->data.u32[count - 1]); if (res) return res; } return TEE_SUCCESS; } /* * Send a message via the MU * * @base: virtual base address of the MU controller * @[in]msg: message to send */ static TEE_Result imx_mu_send_msg(vaddr_t base, struct imx_mu_msg *msg) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int count = 0; unsigned int nb_channel = 0; uint32_t word = 0; assert(base && msg); if (msg->header.size > IMX_MU_MSG_SIZE) { EMSG("msg->size is > than IMX_MU_MSG_SIZE"); return TEE_ERROR_BAD_FORMAT; } memcpy(&word, &msg->header, sizeof(uint32_t)); res = imx_mu_plat_send(base, 0, word); if (res) return res; nb_channel = imx_mu_plat_get_tx_channel(base); for (count = 1; count < msg->header.size; count++) { res = imx_mu_plat_send(base, count % nb_channel, msg->data.u32[count - 1]); if (res) return res; } return TEE_SUCCESS; } void imx_mu_init(vaddr_t base) { uint32_t exceptions = 0; if (!base) { EMSG("Bad MU base address"); return; } exceptions = cpu_spin_lock_xsave(&mu_spinlock); imx_mu_plat_init(base); cpu_spin_unlock_xrestore(&mu_spinlock, exceptions); } TEE_Result imx_mu_call(vaddr_t base, struct imx_mu_msg *msg, bool wait_for_answer) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t exceptions = 0; if (!base || !msg) return TEE_ERROR_BAD_PARAMETERS; exceptions = cpu_spin_lock_xsave(&mu_spinlock); res = imx_mu_send_msg(base, msg); if (res == TEE_SUCCESS && wait_for_answer) res = imx_mu_receive_msg(base, msg); cpu_spin_unlock_xrestore(&mu_spinlock, exceptions); return res; } optee_os-4.3.0/core/drivers/imx/mu/imx_mu_8q.c000066400000000000000000000037221464416617300212510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2020-2022 NXP */ #include #include #include #include #include #include "imx_mu_platform.h" #define MU_ATR(n) (0x0 + (n) * (4)) #define MU_ARR(n) (0x10 + (n) * (4)) #define MU_ASR_OFFSET 0x20 #define MU_ACR_OFFSET 0x24 #define MU_SR_RF(n) SHIFT_U32(1, 27 - (n)) #define MU_SR_TE(n) SHIFT_U32(1, 23 - (n)) #define MU_CR_GIE_MASK GENMASK_32(31, 28) #define MU_CR_RIE_MASK GENMASK_32(27, 24) #define MU_CR_TIE_MASK GENMASK_32(23, 20) #define MU_CR_GIR_MASK GENMASK_32(19, 16) #define MU_CR_F_MASK GENMASK_32(2, 0) #define MU_MAX_CHANNEL 4 static TEE_Result mu_wait_for(vaddr_t addr, uint32_t mask) { uint64_t timeout = timeout_init_us(1000); while (!(io_read32(addr) & mask)) if (timeout_elapsed(timeout)) break; if (io_read32(addr) & mask) return TEE_SUCCESS; else return TEE_ERROR_BUSY; return TEE_SUCCESS; } unsigned int imx_mu_plat_get_rx_channel(vaddr_t base __unused) { return MU_MAX_CHANNEL; } unsigned int imx_mu_plat_get_tx_channel(vaddr_t base __unused) { return MU_MAX_CHANNEL; } void imx_mu_plat_init(vaddr_t base) { io_clrbits32(base + MU_ACR_OFFSET, MU_CR_GIE_MASK | MU_CR_RIE_MASK | MU_CR_TIE_MASK | MU_CR_GIR_MASK | MU_CR_F_MASK); } TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg) { assert(index < MU_MAX_CHANNEL); /* Wait TX register to be empty */ if (mu_wait_for(base + MU_ASR_OFFSET, MU_SR_TE(index))) return TEE_ERROR_BUSY; /* Write message in TX register */ io_write32(base + MU_ATR(index), msg); return TEE_SUCCESS; } TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg) { assert(index < MU_MAX_CHANNEL); /* Wait RX register to be full */ if (mu_wait_for(base + MU_ASR_OFFSET, MU_SR_RF(index))) return TEE_ERROR_NO_DATA; /* Read message in RX register */ *msg = io_read32(base + MU_ARR(index)); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/imx/mu/imx_mu_8ulp.c000066400000000000000000000035111464416617300216050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include #include #include "imx_mu_platform.h" #define MU_PAR 0x004 #define MU_TCR 0x120 #define MU_TSR 0x124 #define MU_RCR 0x128 #define MU_RSR 0x12C #define MU_TR(n) (0x200 + 0x4 * (n)) #define MU_RR(n) (0x280 + 0x4 * (n)) #define MU_TSR_TE(n) BIT32(n) #define MU_RSR_RF(n) BIT32(n) #define RR_NUM_MASK GENMASK_32(15, 8) #define RR_NUM_SHIFT 8 #define TR_NUM_MASK GENMASK_32(7, 0) static TEE_Result mu_wait_for(vaddr_t addr, uint32_t mask) { uint64_t timeout = timeout_init_us(1000); while (!(io_read32(addr) & mask)) if (timeout_elapsed(timeout)) break; if (io_read32(addr) & mask) return TEE_SUCCESS; else return TEE_ERROR_BUSY; return TEE_SUCCESS; } unsigned int imx_mu_plat_get_rx_channel(vaddr_t base) { return (io_read32(base + MU_PAR) & RR_NUM_MASK) >> RR_NUM_SHIFT; } unsigned int imx_mu_plat_get_tx_channel(vaddr_t base) { return io_read32(base + MU_PAR) & TR_NUM_MASK; } TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg) { assert(index < imx_mu_plat_get_tx_channel(base)); /* Wait TX register to be empty */ if (mu_wait_for(base + MU_TSR, MU_TSR_TE(index))) return TEE_ERROR_BUSY; io_write32(base + MU_TR(index), msg); return TEE_SUCCESS; } TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg) { assert(index < imx_mu_plat_get_rx_channel(base)); /* Wait RX register to be full */ if (mu_wait_for(base + MU_RSR, MU_RSR_RF(index))) return TEE_ERROR_NO_DATA; *msg = io_read32(base + MU_RR(index)); return TEE_SUCCESS; } void imx_mu_plat_init(vaddr_t base) { /* Reset status registers */ io_write32(base + MU_TCR, 0x0); io_write32(base + MU_RCR, 0x0); } optee_os-4.3.0/core/drivers/imx/mu/imx_mu_platform.h000066400000000000000000000017301464416617300225470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 NXP */ #ifndef __IMX_MU_PLATFORM_H__ #define __IMX_MU_PLATFORM_H__ /* * Return the number of reception channels */ unsigned int imx_mu_plat_get_rx_channel(vaddr_t base); /* * Return the number of transmission channels */ unsigned int imx_mu_plat_get_tx_channel(vaddr_t base); /* * Send a 32bits word via the MU * * @base: virtual base address of the MU controller * @index: MU channel index * @[in]msg: word to send */ TEE_Result imx_mu_plat_send(vaddr_t base, unsigned int index, uint32_t msg); /* * Get the 32bits word received by the MU * * @base: virtual base address of the MU controller * @index: MU channel index * @[out]msg: word received */ TEE_Result imx_mu_plat_receive(vaddr_t base, unsigned int index, uint32_t *msg); /* * Initialize the MU interface * * @base: virtual base address of the MU controller */ void imx_mu_plat_init(vaddr_t base); #endif /* __IMX_MU_PLATFORM_H__ */ optee_os-4.3.0/core/drivers/imx/mu/sub.mk000066400000000000000000000002571464416617300203210ustar00rootroot00000000000000srcs-y += imx_mu.c srcs-$(call cfg-one-enabled,CFG_MX8ULP CFG_MX93) += imx_mu_8ulp.c ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX) $(CFG_MX8DXL)),y) srcs-y += imx_mu_8q.c endif optee_os-4.3.0/core/drivers/imx/sub.mk000066400000000000000000000000711464416617300176720ustar00rootroot00000000000000subdirs-$(CFG_IMX_DCP) += dcp subdirs-$(CFG_IMX_MU) += muoptee_os-4.3.0/core/drivers/imx_caam.c000066400000000000000000000033561464416617300177060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019 Bryan O'Donoghue * Copyright 2019, 2023 NXP * * Bryan O'Donoghue */ #include #include #include struct imx_caam_job_ring { uint32_t jrmidr_ms; uint32_t jrmidr_ls; }; #define CAAM_NUM_JOB_RINGS 4 /* CAAM ownersip definition bits */ #define JROWN_NS BIT(3) #define JROWN_MID 0x01 /* A basic sub-set of the CAAM */ struct imx_caam_ctrl { uint32_t res0; uint32_t mcfgr; uint32_t res1; uint32_t scfgr; struct imx_caam_job_ring jr[CAAM_NUM_JOB_RINGS]; }; register_phys_mem_pgdir(MEM_AREA_IO_SEC, CAAM_BASE, CORE_MMU_PGDIR_SIZE); static TEE_Result init_caam(void) { struct imx_caam_ctrl *caam; uint32_t reg; int i; caam = (struct imx_caam_ctrl *) core_mmu_get_va(CAAM_BASE, MEM_AREA_IO_SEC, sizeof(struct imx_caam_ctrl)); if (!caam) return TEE_ERROR_GENERIC; /* * Set job-ring ownership to non-secure by default. * A Linux kernel that runs after OP-TEE will run in normal-world * so we want to enable that kernel to have total ownership of the * CAAM job-rings. * * It is possible to use CAAM job-rings inside of OP-TEE i.e. in * secure world code but, to do that OP-TEE and kernel should agree * via a DTB which job-rings are owned by OP-TEE and which are * owned by Kernel, something that the OP-TEE CAAM driver should * set up. * * This code below simply sets a default for the case where no * runtime OP-TEE CAAM code will be run */ for (i = 0; i < CAAM_NUM_JOB_RINGS; i++) { reg = io_read32((vaddr_t)&caam->jr[i].jrmidr_ms); reg |= JROWN_NS | JROWN_MID; io_write32((vaddr_t)&caam->jr[i].jrmidr_ms, reg); } return TEE_SUCCESS; } driver_init(init_caam); optee_os-4.3.0/core/drivers/imx_csu.c000066400000000000000000000103241464416617300175700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2023 NXP * */ #include #include #include #include #include #include #include struct csu_setting { int csu_index; uint32_t value; }; const struct csu_setting csu_setting_imx6[] = { {13, 0xFF0033}, /* Protect ROMCP */ {16, 0x330033}, /* Protect TZASC */ {26, 0xFF0033}, /* Protect OCRAM */ {(-1), 0}, }; struct csu_sa_setting { uint32_t access_value; uint32_t lock_value; }; struct csu_config { const struct csu_sa_setting * const sa; const struct csu_setting * const csl; }; const struct csu_setting csu_setting_imx6ul[] = { {13, 0xFF0033}, /* Protect ROMCP */ {16, 0x3300FF}, /* Protect TZASC */ {39, 0x3300FF}, /* Protect OCRAM */ {(-1), 0}, }; const struct csu_setting csu_setting_imx6ull[] = { { 13, 0xFF0033 }, /* Protect ROMCP */ { 16, 0x3300FF }, /* Protect TZASC */ { 34, 0xFF0033 }, /* Protect DCP */ { 39, 0x3300FF }, /* Protect OCRAM */ { (-1), 0 }, }; const struct csu_setting csu_setting_imx6sl[] = { { 13, 0x3F0033 }, /* Protect DCP/ROMCP */ { 16, 0xFF0033 }, /* Protect TZASC */ { 26, 0xFF0033 }, /* Protect OCRAM */ { (-1), 0 }, }; const struct csu_setting csu_setting_imx6sx[] = { {13, 0xFF0033}, /* Protect ROMCP */ {15, 0xFF0033}, /* Protect RDC */ {16, 0x3300FF}, /* Protect TZASC */ {34, 0x3300FF}, /* Protect OCRAM */ {(-1), 0}, }; const struct csu_setting csu_setting_imx7ds[] = { {14, 0x3300FF}, /* Protect RDC */ {15, 0xFF0033}, /* Protect CSU */ {28, 0xFF0033}, /* Protect TZASC */ {59, 0x3300FF}, /* Protect OCRAM_S */ {(-1), 0}, }; /* Set all masters to non-secure except the Cortex-A7 */ const struct csu_sa_setting csu_sa_imx6ul = { 0x10554550, 0x20aa8aa2 }; const struct csu_sa_setting csu_sa_imx7ds = { 0x15554554, 0x2aaa8aaa }; const struct csu_config csu_imx6 = { NULL, csu_setting_imx6 }; const struct csu_config csu_imx6ul = { &csu_sa_imx6ul, csu_setting_imx6ul }; const struct csu_config csu_imx6ull = { NULL, csu_setting_imx6ull }; const struct csu_config csu_imx6sl = { NULL, csu_setting_imx6sl }; const struct csu_config csu_imx6sx = { NULL, csu_setting_imx6sx }; const struct csu_config csu_imx7ds = { &csu_sa_imx7ds, csu_setting_imx7ds }; static void rngb_configure(vaddr_t csu_base) { int csu_index = 0; if (soc_is_imx6sl() || soc_is_imx6sll()) csu_index = 16; else if (soc_is_imx6ull()) csu_index = 34; else return; /* Protect RNGB */ io_mask32(csu_base + csu_index * 4, 0x330000, 0xFF0000); } static TEE_Result csu_configure(void) { vaddr_t csu_base; vaddr_t offset; const struct csu_config *csu_config = NULL; const struct csu_setting *csu_setting = NULL; csu_base = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, 1); if (!csu_base) panic(); if (soc_is_imx6sx()) csu_config = &csu_imx6sx; else if (soc_is_imx6ul()) csu_config = &csu_imx6ul; else if (soc_is_imx6ull()) csu_config = &csu_imx6ull; else if (soc_is_imx6sll() || soc_is_imx6sl()) csu_config = &csu_imx6sl; else if (soc_is_imx6()) csu_config = &csu_imx6; else if (soc_is_imx7ds()) csu_config = &csu_imx7ds; else return TEE_SUCCESS; /* first grant all peripherals */ for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4) io_write32(csu_base + offset, CSU_ACCESS_ALL); csu_setting = csu_config->csl; while (csu_setting->csu_index >= 0) { io_write32(csu_base + (csu_setting->csu_index * 4), csu_setting->value); csu_setting++; } if (IS_ENABLED(CFG_IMX_RNGB)) rngb_configure(csu_base); /* lock the settings */ for (offset = CSU_CSL_START; offset < CSU_CSL_END; offset += 4) { io_write32(csu_base + offset, io_read32(csu_base + offset) | CSU_SETTING_LOCK); } if (csu_config->sa) { io_write32(csu_base + CSU_SA, csu_config->sa->access_value); io_setbits32(csu_base + CSU_SA, csu_config->sa->lock_value); } return TEE_SUCCESS; } static TEE_Result pm_enter_resume(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *pm_handle __unused) { if (op == PM_OP_RESUME) csu_configure(); return TEE_SUCCESS; } static TEE_Result csu_init(void) { csu_configure(); register_pm_driver_cb(pm_enter_resume, NULL, "imx-csu"); return TEE_SUCCESS; } driver_init(csu_init); optee_os-4.3.0/core/drivers/imx_ele.c000066400000000000000000000305711464416617300175510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ELE_BASE_ADDR MU_BASE #define ELE_BASE_SIZE MU_SIZE #define ELE_VERSION_BASELINE 0x06 #define ELE_VERSION_HSM 0x07 #define ELE_COMMAND_SUCCEED 0xd6 #define ELE_REQUEST_TAG 0x17 #define ELE_RESPONSE_TAG 0xe1 #define ELE_CMD_SESSION_OPEN 0x10 #define ELE_CMD_SESSION_CLOSE 0x11 #define ELE_CMD_SESSION_DEVICE_INFO 0x16 #define ELE_CMD_RNG_GET 0xCD #define ELE_CMD_TRNG_STATE 0xA4 #define ELE_CMD_GET_INFO 0xDA #define ELE_CMD_DERIVE_KEY 0xA9 #define IMX_ELE_TRNG_STATUS_READY 0x3 #define ELE_MU_ID 0x2 #define ELE_MU_IRQ 0x0 #if defined(CFG_MX8ULP) #define ELE_MU_DID 0x7 #define CACHELINE_SIZE 64 #elif defined(CFG_MX93) #define ELE_MU_DID 0x3 #define CACHELINE_SIZE 64 #else #error "Platform DID is not defined" #endif #define SIZE_MSG_32(_msg) size_msg_32(sizeof(_msg)) register_phys_mem_pgdir(MEM_AREA_IO_SEC, ELE_BASE_ADDR, ELE_BASE_SIZE); struct get_info_msg_rsp { uint32_t rsp_code; uint16_t soc_id; uint16_t soc_rev; uint16_t lifecycle; uint16_t sssm_state; uint32_t uid[4]; uint32_t sha256_rom_patch[8]; uint32_t sha256_fw[8]; } __packed; struct session_get_device_info_rsp { uint32_t rsp_code; uint32_t user_sab_id; uint32_t chip_uid[4]; uint16_t chip_life_cycle; uint16_t chip_monotonic_counter; uint32_t ele_version; uint32_t ele_version_ext; uint8_t fips_mode; uint8_t reserved[3]; uint32_t crc; } __packed; struct response_code { uint8_t status; uint8_t rating; uint16_t rating_extension; } __packed; /* * Print ELE response status and rating * * @rsp response code structure */ static void print_rsp_code(struct response_code rsp __maybe_unused) { DMSG("Response status %#"PRIx8", rating %#"PRIx8" (ext %#"PRIx16")", rsp.status, rsp.rating, rsp.rating_extension); } /* * Print ELE message header * * @hdr message header */ static void print_msg_header(struct imx_mu_msg_header hdr __maybe_unused) { DMSG("Header ver %#"PRIx8", size %"PRId8", tag %#"PRIx8", cmd %#"PRIx8, hdr.version, hdr.size, hdr.tag, hdr.command); } /* * Print full ELE message content * * @msg message */ static void dump_message(const struct imx_mu_msg *msg __maybe_unused) { size_t i = 0; size_t size __maybe_unused = msg->header.size; uint32_t *data __maybe_unused = (uint32_t *)msg; DMSG("Dump of message %p(%zu)", data, size); for (i = 0; i < size; i++) DMSG("word %zu: %#"PRIx32, i, data[i]); } /* * Return the number of 32 bits words of the given message. * * @cmd command size in byte */ static size_t size_msg_32(size_t cmd) { /* Roundup and add header size */ return ROUNDUP_DIV(cmd, sizeof(uint32_t)) + 1; } /* * The CRC for the message is computed xor-ing all the words of the message: * the header and all the words except the word storing the CRC. * * @msg MU message to hash */ static uint32_t compute_crc(const struct imx_mu_msg *msg) { uint32_t crc = 0; uint8_t i = 0; uint32_t *payload = (uint32_t *)msg; assert(msg); for (i = 0; i < msg->header.size - 1; i++) crc ^= payload[i]; return crc; } /* * Compute message CRC and update CRC in message header. * * @msg MU message to hash */ static void update_crc(struct imx_mu_msg *msg) { assert(msg); /* * The CRC field is the last element of array. The size of the header * is also subtracted from CRC computation. */ msg->data.u32[msg->header.size - 2] = compute_crc(msg); } /* * Return the given MU base address, depending on the MMU state. * * @pa MU physical base address * @sz MU size */ static vaddr_t imx_ele_init(paddr_t pa, size_t sz) { static bool is_initialized; vaddr_t va = 0; assert(pa && sz); if (cpu_mmu_enabled()) va = core_mmu_get_va(pa, MEM_AREA_IO_SEC, sz); else va = (vaddr_t)pa; if (!is_initialized) { imx_mu_init(va); is_initialized = true; } return va; } /* * Extract response codes from the given word * * @word 32 bits word MU response */ static struct response_code get_response_code(uint32_t word) { struct response_code rsp = { .rating_extension = (word & GENMASK_32(31, 16)) >> 16, .rating = (word & GENMASK_32(15, 8)) >> 8, .status = (word & GENMASK_32(7, 0)) >> 0, }; return rsp; } /* * Initiate a communication with the EdgeLock Enclave. It sends a message * and expects an answer. * * @msg MU message */ static TEE_Result imx_ele_call(struct imx_mu_msg *msg) { TEE_Result res = TEE_ERROR_GENERIC; struct response_code rsp = { }; vaddr_t va = 0; assert(msg); if (msg->header.tag != ELE_REQUEST_TAG) { EMSG("Request has invalid tag: %#"PRIx8" instead of %#"PRIx8, msg->header.tag, ELE_REQUEST_TAG); return TEE_ERROR_BAD_PARAMETERS; } va = imx_ele_init(ELE_BASE_ADDR, ELE_BASE_SIZE); if (!va) { EMSG("Fail to get base address"); return TEE_ERROR_GENERIC; } res = imx_mu_call(va, msg, true); if (res) { EMSG("Failed to transmit message: %#"PRIx32, res); print_msg_header(msg->header); dump_message(msg); return res; } rsp = get_response_code(msg->data.u32[0]); if (msg->header.tag != ELE_RESPONSE_TAG) { EMSG("Response has invalid tag: %#"PRIx8" instead of %#"PRIx8, msg->header.tag, ELE_RESPONSE_TAG); print_msg_header(msg->header); return TEE_ERROR_GENERIC; } if (rsp.status != ELE_COMMAND_SUCCEED) { EMSG("Command has failed"); print_rsp_code(rsp); return TEE_ERROR_GENERIC; } /* The rating can be different in success and failing cases */ if (rsp.rating != 0) { EMSG("Command has invalid rating: %#"PRIx8, rsp.rating); print_rsp_code(rsp); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } /* * Get device information from EdgeLock Enclave * * @session_handle EdgeLock Enclave session handle * @rsp Device info */ static TEE_Result imx_ele_session_get_device_info(uint32_t session_handle, struct session_get_device_info_rsp *rsp) { TEE_Result res = TEE_ERROR_GENERIC; struct session_get_device_info_cmd { uint32_t session_handle; } cmd = { .session_handle = session_handle, }; struct imx_mu_msg msg = { .header.version = ELE_VERSION_HSM, .header.size = SIZE_MSG_32(cmd), .header.tag = ELE_REQUEST_TAG, .header.command = ELE_CMD_SESSION_DEVICE_INFO, }; assert(rsp); memcpy(msg.data.u8, &cmd, sizeof(cmd)); res = imx_ele_call(&msg); if (res) return res; memcpy(rsp, msg.data.u32, sizeof(*rsp)); if (compute_crc(&msg) != rsp->crc) return TEE_ERROR_CORRUPT_OBJECT; return TEE_SUCCESS; } /* * Open a session with EdgeLock Enclave. It returns a session handle. * * @session_handle EdgeLock Enclave session handle */ static TEE_Result imx_ele_session_open(uint32_t *session_handle) { TEE_Result res = TEE_ERROR_GENERIC; struct open_session_cmd { uint8_t mu_id; uint8_t interrupt_num; uint8_t tz; uint8_t did; uint8_t priority; uint8_t op_mode; uint16_t reserved; } __packed cmd = { .mu_id = ELE_MU_ID, .interrupt_num = ELE_MU_IRQ, .tz = 0, .did = ELE_MU_DID, .priority = 0, .op_mode = 0, .reserved = 0, }; struct open_session_rsp { uint32_t rsp_code; uint32_t session_handle; } rsp = { }; struct imx_mu_msg msg = { .header.version = ELE_VERSION_HSM, .header.size = SIZE_MSG_32(cmd), .header.tag = ELE_REQUEST_TAG, .header.command = ELE_CMD_SESSION_OPEN, }; assert(session_handle); memcpy(msg.data.u8, &cmd, sizeof(cmd)); res = imx_ele_call(&msg); if (res) return res; memcpy(&rsp, msg.data.u8, sizeof(rsp)); *session_handle = rsp.session_handle; return TEE_SUCCESS; } /* * Close a session with EdgeLock Enclave. * * @session_handle EdgeLock Enclave session handle */ static TEE_Result imx_ele_session_close(uint32_t session_handle) { struct close_session_cmd { uint32_t session_handle; } cmd = { .session_handle = session_handle, }; struct imx_mu_msg msg = { .header.version = ELE_VERSION_HSM, .header.size = SIZE_MSG_32(cmd), .header.tag = ELE_REQUEST_TAG, .header.command = ELE_CMD_SESSION_CLOSE, }; memcpy(msg.data.u8, &cmd, sizeof(cmd)); return imx_ele_call(&msg); } /* * Get the current state of the ELE TRNG */ static TEE_Result imx_ele_rng_get_trng_state(void) { TEE_Result res = TEE_ERROR_GENERIC; struct rng_get_trng_state_msg_rsp { uint32_t rsp_code; uint8_t trng_state; uint8_t csal_state; } __packed rsp = { }; struct imx_mu_msg msg = { .header.version = ELE_VERSION_BASELINE, .header.size = 1, .header.tag = ELE_REQUEST_TAG, .header.command = ELE_CMD_TRNG_STATE, }; res = imx_ele_call(&msg); if (res) return res; memcpy(&rsp, msg.data.u8, sizeof(rsp)); if (rsp.trng_state != IMX_ELE_TRNG_STATUS_READY) return TEE_ERROR_BUSY; else return TEE_SUCCESS; } unsigned long plat_get_aslr_seed(void) { TEE_Result res = TEE_ERROR_GENERIC; uint64_t timeout = timeout_init_us(10 * 1000); struct rng_get_random_cmd { uint32_t addr_msb; uint32_t addr_lsb; uint32_t size; uint32_t crc; } cmd = { }; struct imx_mu_msg msg = { .header.version = ELE_VERSION_HSM, .header.size = SIZE_MSG_32(cmd), .header.tag = ELE_REQUEST_TAG, .header.command = ELE_CMD_RNG_GET, }; unsigned long aslr __aligned(CACHELINE_SIZE) = 0; /* * This function can only be called when the MMU is off. No * virtual/physical address translation is performed, nor cache * maintenance. */ assert(!cpu_mmu_enabled()); reg_pair_from_64((uint64_t)&aslr, &cmd.addr_msb, &cmd.addr_lsb); cmd.size = sizeof(aslr); /* * Check the current TRNG state of the ELE. The TRNG must be * started with a command earlier in the boot to allow the TRNG * to generate enough entropy. */ while (imx_ele_rng_get_trng_state() == TEE_ERROR_BUSY) if (timeout_elapsed(timeout)) panic("ELE RNG is busy"); memcpy(msg.data.u8, &cmd, sizeof(cmd)); update_crc(&msg); res = imx_ele_call(&msg); if (res) panic("Cannot retrieve random data from ELE"); return aslr; } int tee_otp_get_die_id(uint8_t *buffer, size_t len) { uint32_t session_handle = 0; /* * The die ID must be cached because some board configuration prevents * the MU to be used by OPTEE at runtime. */ static struct session_get_device_info_rsp rsp; if (rsp.rsp_code) goto out; if (imx_ele_session_open(&session_handle)) goto err; if (imx_ele_session_get_device_info(session_handle, &rsp)) goto err; if (imx_ele_session_close(session_handle)) goto err; out: /* * In the device info array return by the ELE, the words 2, 3, 4 and 5 * are the device UID. */ memcpy(buffer, rsp.chip_uid, MIN(sizeof(rsp.chip_uid), len)); return 0; err: panic("Fail to get the device UID"); } #if defined(CFG_MX93) TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { TEE_Result res = TEE_ERROR_GENERIC; const char pattern[16] __aligned(CACHELINE_SIZE) = "TEE_for_HUK_ELE"; static uint8_t key[CACHELINE_SIZE] __aligned(CACHELINE_SIZE); static bool is_fetched; uint32_t msb = 0; uint32_t lsb = 0; struct key_derive_cmd { uint32_t key_addr_msb; uint32_t key_addr_lsb; uint32_t ctx_addr_msb; uint32_t ctx_addr_lsb; uint16_t key_size; uint16_t ctx_size; uint32_t crc; } __packed cmd = { }; struct imx_mu_msg msg = { .header.version = ELE_VERSION_BASELINE, .header.size = SIZE_MSG_32(cmd), .header.tag = ELE_REQUEST_TAG, .header.command = ELE_CMD_DERIVE_KEY, }; if (is_fetched) goto out; /* * Intermediate msb and lsb values are needed. Directly using * key_addr_msb and key_addr_lsb might be unaligned because of the * __packed attribute of key_derive_cmd {} */ reg_pair_from_64((uint64_t)virt_to_phys(key), &msb, &lsb); cmd.key_addr_lsb = lsb; cmd.key_addr_msb = msb; cmd.key_size = HW_UNIQUE_KEY_LENGTH; reg_pair_from_64((uint64_t)virt_to_phys((void *)pattern), &msb, &lsb); cmd.ctx_addr_lsb = lsb; cmd.ctx_addr_msb = msb; cmd.ctx_size = sizeof(pattern); memcpy(msg.data.u8, &cmd, sizeof(cmd)); update_crc(&msg); cache_operation(TEE_CACHEFLUSH, key, HW_UNIQUE_KEY_LENGTH); cache_operation(TEE_CACHECLEAN, (void *)pattern, sizeof(pattern)); res = imx_ele_call(&msg); if (res) panic("failed to get the huk"); cache_operation(TEE_CACHEINVALIDATE, key, HW_UNIQUE_KEY_LENGTH); is_fetched = true; out: memcpy(hwkey->data, key, MIN(sizeof(key), (size_t)HW_UNIQUE_KEY_LENGTH)); return TEE_SUCCESS; } #endif /* CFG_MX93 */ optee_os-4.3.0/core/drivers/imx_i2c.c000066400000000000000000000327151464416617300174630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * (c) 2020 Jorge Ramirez , Foundries Ltd. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define I2C_CLK_RATE 24000000 /* Bits per second */ /* Utility macros (__x identifies the bus [1 .. 3]) */ #define I2C_CFG_SCL(__x) (IOMUXC_I2C1_SCL_CFG_OFF + ((__x) - 1) * 0x8) #define I2C_CFG_SDA(__x) (IOMUXC_I2C1_SDA_CFG_OFF + ((__x) - 1) * 0x8) #define I2C_MUX_SCL(__x) (IOMUXC_I2C1_SCL_MUX_OFF + ((__x) - 1) * 0x8) #define I2C_MUX_SDA(__x) (IOMUXC_I2C1_SDA_MUX_OFF + ((__x) - 1) * 0x8) #if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MP) || \ defined(CFG_MX8MN) /* IOMUX */ #define I2C_INP_SCL(__x) 0 /* Not implemented */ #define I2C_INP_SDA(__x) 0 /* Not implemented */ #define I2C_INP_VAL(__x) 0 /* Not implemented */ #define I2C_MUX_VAL(__x) 0x010 #define I2C_CFG_VAL(__x) 0x1c3 /* Clock */ #define I2C_CLK_CGRBM(__x) 0 /* Not implemented */ #define I2C_CLK_CGR6BM(__x) 0 #define I2C_CLK_CGR(__x) CCM_CCRG_I2C##__x #elif defined(CFG_MX6ULL) /* IOMUX */ #define I2C_INP_SCL(__x) (IOMUXC_I2C1_SCL_INP_OFF + ((__x) - 1) * 0x8) #define I2C_INP_SDA(__x) (IOMUXC_I2C1_SDA_INP_OFF + ((__x) - 1) * 0x8) #define I2C_INP_VAL(__x) (((__x) == 1) ? 0x1 : 0x2) #define I2C_MUX_VAL(__x) 0x012 #define I2C_CFG_VAL(__x) 0x1b8b0 /* Clock */ #define I2C_CLK_CGRBM(__x) BM_CCM_CCGR2_I2C##__x##_SERIAL #define I2C_CLK_CGR6BM(__x) BM_CCM_CCGR6_I2C##__x##_SERIAL #define I2C_CLK_CGR(__x) (((__x) == 4) ? CCM_CCGR6 : CCM_CCGR2) #else #error IMX_I2C driver not supported on this platform #endif #if !defined(CFG_MX8MP) static struct io_pa_va i2c_bus[4] = { #if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY) #if defined(I2C1_BASE) [0] = { .pa = I2C1_BASE, }, #endif #if defined(I2C2_BASE) [1] = { .pa = I2C2_BASE, }, #endif #if defined(I2C3_BASE) [2] = { .pa = I2C3_BASE, }, #endif #if defined(I2C4_BASE) [3] = { .pa = I2C4_BASE, }, #endif #endif }; #else static struct io_pa_va i2c_bus[6] = { #if !defined(CFG_DT) || defined(CFG_EXTERNAL_DTB_OVERLAY) #if defined(I2C1_BASE) [0] = { .pa = I2C1_BASE, }, #endif #if defined(I2C2_BASE) [1] = { .pa = I2C2_BASE, }, #endif #if defined(I2C3_BASE) [2] = { .pa = I2C3_BASE, }, #endif #if defined(I2C4_BASE) [3] = { .pa = I2C4_BASE, }, #endif #if defined(I2C5_BASE) [4] = { .pa = I2C5_BASE, }, #endif #if defined(I2C6_BASE) [5] = { .pa = I2C6_BASE, }, #endif #endif }; #endif static struct imx_i2c_clk { struct io_pa_va base; uint32_t i2c[ARRAY_SIZE(i2c_bus)]; uint32_t cgrbm[ARRAY_SIZE(i2c_bus)]; } i2c_clk = { .base.pa = CCM_BASE, .i2c = { I2C_CLK_CGR(1), I2C_CLK_CGR(2), I2C_CLK_CGR(3), I2C_CLK_CGR(4), }, .cgrbm = { I2C_CLK_CGRBM(1), I2C_CLK_CGRBM(2), I2C_CLK_CGRBM(3), I2C_CLK_CGR6BM(4),}, }; static struct imx_i2c_mux { struct io_pa_va base; struct imx_i2c_mux_regs { uint32_t scl_mux; uint32_t scl_cfg; uint32_t scl_inp; uint32_t sda_mux; uint32_t sda_cfg; uint32_t sda_inp; } i2c[ARRAY_SIZE(i2c_bus)]; } i2c_mux = { .base.pa = IOMUXC_BASE, .i2c = {{ .scl_mux = I2C_MUX_SCL(1), .scl_cfg = I2C_CFG_SCL(1), .scl_inp = I2C_INP_SCL(1), .sda_mux = I2C_MUX_SDA(1), .sda_cfg = I2C_CFG_SDA(1), .sda_inp = I2C_INP_SDA(1), }, { .scl_mux = I2C_MUX_SCL(2), .scl_cfg = I2C_CFG_SCL(2), .scl_inp = I2C_INP_SCL(2), .sda_mux = I2C_MUX_SDA(2), .sda_cfg = I2C_CFG_SDA(2), .sda_inp = I2C_INP_SDA(2), }, { .scl_mux = I2C_MUX_SCL(3), .scl_cfg = I2C_CFG_SCL(3), .scl_inp = I2C_INP_SCL(3), .sda_mux = I2C_MUX_SDA(3), .sda_cfg = I2C_CFG_SDA(3), .sda_inp = I2C_INP_SDA(3), }, { .scl_mux = I2C_MUX_SCL(4), .scl_cfg = I2C_CFG_SCL(4), .scl_inp = I2C_INP_SCL(4), .sda_mux = I2C_MUX_SDA(4), .sda_cfg = I2C_CFG_SDA(4), .sda_inp = I2C_INP_SDA(4), },}, }; #define I2DR 0x10 #define I2SR 0x0C #define I2CR 0x08 #define IFDR 0x04 #define I2CR_IEN BIT(7) #define I2CR_IIEN BIT(6) #define I2CR_MSTA BIT(5) #define I2CR_MTX BIT(4) #define I2CR_TX_NO_AK BIT(3) #define I2CR_RSTA BIT(2) #define I2SR_ICF BIT(7) #define I2SR_IBB BIT(5) #define I2SR_IAL BIT(4) #define I2SR_IIF BIT(1) #define I2SR_RX_NO_AK BIT(0) static uint8_t i2c_io_read8(uint8_t bid, uint32_t address) { return io_read8(i2c_bus[bid].va + address); } static void i2c_io_write8(uint8_t bid, uint32_t address, uint8_t data) { return io_write8(i2c_bus[bid].va + address, data); } static bool bus_is_idle(uint32_t sr) { return (sr & I2SR_IBB) == 0; } static bool bus_is_busy(uint32_t sr) { return !bus_is_idle(sr); } static bool isr_active(uint32_t sr) { return (sr & I2SR_IIF) == I2SR_IIF; } static struct ifdr_pair { uint32_t divider; uint8_t prescaler; } ifdr_table[] = { { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2A }, { 72, 0x2B }, { 80, 0x2C }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, { 112, 0x2E }, { 128, 0x2F }, { 144, 0x0C }, { 160, 0x30 }, { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 }, { 448, 0x36 }, { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x38 }, { 768, 0x39 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, { 1152, 0x18 }, { 1280, 0x3C }, { 1536, 0x3D }, { 1792, 0x3E }, { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, { 3072, 0x1E }, { 3840, 0x1F } }; static void i2c_set_prescaler(uint8_t bid, uint32_t bps) { struct ifdr_pair *p = ifdr_table; struct ifdr_pair *q = p + ARRAY_SIZE(ifdr_table) - 1; uint32_t div = (I2C_CLK_RATE + bps - 1) / bps; if (div < p->divider) q = p; else if (div > q->divider) p = q; while (p != q) { if (div <= p->divider) break; p++; } i2c_io_write8(bid, IFDR, p->prescaler); } static void i2c_set_bus_speed(uint8_t bid, int bps) { vaddr_t addr = i2c_clk.base.va; uint32_t val = 0; #if defined(CFG_MX8MM) || defined(CFG_MX8MQ) || defined(CFG_MX8MP) || \ defined(CFG_MX8MN) addr += CCM_CCGRx_SET(i2c_clk.i2c[bid]); val = CCM_CCGRx_ALWAYS_ON(0); #elif defined(CFG_MX6ULL) addr += i2c_clk.i2c[bid]; val = i2c_clk.cgrbm[bid] | io_read32(addr); #else #error IMX_I2C driver not supported on this platform #endif io_write32(addr, val); i2c_set_prescaler(bid, bps); } static TEE_Result i2c_sync_bus(uint8_t bid, bool (*match)(uint32_t), uint32_t *status) { uint64_t tref = timeout_init_us(100000); uint32_t sr = 0; while (!timeout_elapsed(tref)) { sr = i2c_io_read8(bid, I2SR); if (sr & I2SR_IAL) { EMSG("bus arbitration lost"); i2c_io_write8(bid, I2SR, sr & ~I2SR_IAL); return TEE_ERROR_COMMUNICATION; } if ((*match)(sr)) { if (status) *status = sr; return TEE_SUCCESS; } } return TEE_ERROR_BUSY; } static TEE_Result i2c_idle_bus(uint8_t bid) { uint8_t tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MSTA; TEE_Result ret = TEE_SUCCESS; i2c_io_write8(bid, I2CR, tmp); ret = i2c_sync_bus(bid, &bus_is_idle, NULL); i2c_io_write8(bid, I2SR, 0); return ret; } static TEE_Result i2c_write_byte(uint8_t bid, uint8_t byte) { TEE_Result ret = TEE_SUCCESS; uint32_t status = 0; i2c_io_write8(bid, I2DR, byte); ret = i2c_sync_bus(bid, &isr_active, &status); i2c_io_write8(bid, I2SR, 0); if (!ret && (status & I2SR_RX_NO_AK)) return TEE_ERROR_BAD_STATE; return ret; } static TEE_Result i2c_read_byte(uint8_t bid, uint8_t *p) { TEE_Result ret = TEE_SUCCESS; *p = i2c_io_read8(bid, I2DR); ret = i2c_sync_bus(bid, &isr_active, NULL); i2c_io_write8(bid, I2SR, 0); return ret; } static TEE_Result i2c_write_data(uint8_t bid, const uint8_t *buf, int len) { TEE_Result ret = TEE_SUCCESS; uint32_t tmp = 0; if (!len) return TEE_SUCCESS; tmp = i2c_io_read8(bid, I2CR) | I2CR_MTX | I2CR_TX_NO_AK; i2c_io_write8(bid, I2CR, tmp); while (len--) { ret = i2c_write_byte(bid, *buf++); if (ret) return ret; } return ret; } static TEE_Result i2c_read_data(uint8_t bid, uint8_t *buf, int len) { TEE_Result ret = TEE_SUCCESS; uint8_t dummy = 0; uint32_t tmp = 0; if (!len) return TEE_SUCCESS; tmp = i2c_io_read8(bid, I2CR) & ~I2CR_MTX; tmp = (len == 1) ? tmp | I2CR_TX_NO_AK : tmp & ~I2CR_TX_NO_AK; i2c_io_write8(bid, I2CR, tmp); i2c_io_read8(bid, I2DR); ret = i2c_read_byte(bid, &dummy); if (ret) return ret; /* * A data transfer ends when the master signals a stop; for a master * receiver to terminate a transfer it must inform the slave transmiter * by not acknowledging the last data byte. This is done by setting the * transmit acknowledge bit before reading the next-to-last byte. */ do { if (len == 2) { tmp = i2c_io_read8(bid, I2CR) | I2CR_TX_NO_AK; i2c_io_write8(bid, I2CR, tmp); } ret = i2c_read_byte(bid, buf++); if (ret) return ret; } while (len--); return ret; } static TEE_Result i2c_init_transfer(uint8_t bid, uint8_t chip) { TEE_Result ret = TEE_SUCCESS; uint32_t tmp = 0; ret = i2c_idle_bus(bid); if (ret) return ret; /* Enable the interface */ tmp = !(i2c_io_read8(bid, I2CR) & I2CR_IEN); if (tmp) { i2c_io_write8(bid, I2CR, I2CR_IEN); udelay(50); } i2c_io_write8(bid, I2SR, 0); tmp = i2c_io_read8(bid, I2CR) | I2CR_MSTA; i2c_io_write8(bid, I2CR, tmp); /* Wait until the bus is active */ ret = i2c_sync_bus(bid, &bus_is_busy, NULL); if (ret) return ret; /* Slave address on the bus */ return i2c_write_data(bid, &chip, 1); } TEE_Result imx_i2c_read(uint8_t bid, uint8_t chip, uint8_t *buf, int len) { TEE_Result ret = TEE_SUCCESS; if (bid >= ARRAY_SIZE(i2c_bus)) return TEE_ERROR_BAD_PARAMETERS; if ((len && !buf) || chip > 0x7F) return TEE_ERROR_BAD_PARAMETERS; if (!i2c_bus[bid].va) return TEE_ERROR_BAD_PARAMETERS; ret = i2c_init_transfer(bid, chip << 1 | BIT(0)); if (!ret) ret = i2c_read_data(bid, buf, len); if (i2c_idle_bus(bid)) IMSG("bus not idle"); return ret; } TEE_Result imx_i2c_write(uint8_t bid, uint8_t chip, const uint8_t *buf, int len) { TEE_Result ret = TEE_SUCCESS; if (bid >= ARRAY_SIZE(i2c_bus)) return TEE_ERROR_BAD_PARAMETERS; if ((len && !buf) || chip > 0x7F) return TEE_ERROR_BAD_PARAMETERS; if (!i2c_bus[bid].va) return TEE_ERROR_BAD_PARAMETERS; ret = i2c_init_transfer(bid, chip << 1); if (!ret) ret = i2c_write_data(bid, buf, len); if (i2c_idle_bus(bid)) IMSG("bus not idle"); return ret; } TEE_Result imx_i2c_probe(uint8_t bid, uint8_t chip) { if (bid >= ARRAY_SIZE(i2c_bus)) return TEE_ERROR_BAD_PARAMETERS; if (!i2c_bus[bid].va) return TEE_ERROR_BAD_PARAMETERS; if (chip > 0x7F) return TEE_ERROR_BAD_PARAMETERS; return imx_i2c_write(bid, chip, NULL, 0); } /* * I2C bus initialization: configure the IOMUX and enable the clock. * @bid: Bus ID: (0=I2C1), (1=I2C2), (2=I2C3), (3=I2C4). * @bps: Bus baud rate, in bits per second. */ TEE_Result imx_i2c_init(uint8_t bid, int bps) { struct imx_i2c_mux *mux = &i2c_mux; if (bid >= ARRAY_SIZE(i2c_bus)) return TEE_ERROR_BAD_PARAMETERS; if (!bps) return TEE_ERROR_BAD_PARAMETERS; if (!i2c_bus[bid].va) return TEE_ERROR_BAD_PARAMETERS; io_write32(mux->base.va + mux->i2c[bid].scl_mux, I2C_MUX_VAL(bid)); io_write32(mux->base.va + mux->i2c[bid].scl_cfg, I2C_CFG_VAL(bid)); if (mux->i2c[bid].scl_inp) io_write32(mux->base.va + mux->i2c[bid].scl_inp, I2C_INP_VAL(bid + 1)); io_write32(mux->base.va + mux->i2c[bid].sda_mux, I2C_MUX_VAL(bid)); io_write32(mux->base.va + mux->i2c[bid].sda_cfg, I2C_CFG_VAL(bid)); if (mux->i2c[bid].sda_inp) io_write32(mux->base.va + mux->i2c[bid].sda_inp, I2C_INP_VAL(bid + 2)); /* Baud rate in bits per second */ i2c_set_bus_speed(bid, bps); return TEE_SUCCESS; } static TEE_Result get_va(paddr_t pa, vaddr_t *va) { *va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, pa, 0x10000); if (!*va) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) static const char *const dt_i2c_match_table[] = { "fsl,imx21-i2c", }; static TEE_Result i2c_mapped(const char *i2c_match) { TEE_Result ret = TEE_ERROR_GENERIC; void *fdt = get_dt(); size_t size = 0; size_t i = 0; int off = 0; if (!fdt) return TEE_ERROR_NOT_SUPPORTED; for (i = 0; i < ARRAY_SIZE(i2c_bus); i++) { off = fdt_node_offset_by_compatible(fdt, off, i2c_match); if (off < 0) break; if (!(fdt_get_status(fdt, off) & DT_STATUS_OK_SEC)) { EMSG("i2c%zu not enabled", i + 1); continue; } if (dt_map_dev(fdt, off, &i2c_bus[i].va, &size, DT_MAP_AUTO) < 0) { EMSG("i2c%zu not enabled", i + 1); continue; } i2c_bus[i].pa = virt_to_phys((void *)i2c_bus[i].va); ret = TEE_SUCCESS; } return ret; } static TEE_Result i2c_map_controller(void) { TEE_Result ret = TEE_ERROR_GENERIC; size_t i = 0; for (i = 0; i < ARRAY_SIZE(dt_i2c_match_table); i++) { ret = i2c_mapped(dt_i2c_match_table[i]); if (!ret || ret == TEE_ERROR_NOT_SUPPORTED) return ret; } return ret; } #else static TEE_Result i2c_map_controller(void) { TEE_Result ret = TEE_ERROR_GENERIC; size_t n = 0; for (n = 0; n < ARRAY_SIZE(i2c_bus); n++) { if (i2c_bus[n].pa) { if (get_va(i2c_bus[n].pa, &i2c_bus[n].va)) EMSG("i2c%zu not enabled", n + 1); else ret = TEE_SUCCESS; } else { IMSG("i2c%zu not enabled", n + 1); } } return ret; } #endif static TEE_Result i2c_init(void) { if (get_va(i2c_clk.base.pa, &i2c_clk.base.va)) return TEE_ERROR_GENERIC; if (get_va(i2c_mux.base.pa, &i2c_mux.base.va)) return TEE_ERROR_GENERIC; return i2c_map_controller(); } early_init(i2c_init); optee_os-4.3.0/core/drivers/imx_lpuart.c000066400000000000000000000052511464416617300203100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2019 NXP */ #include #include #include #include #include #include #include #define STAT 0x14 #define DATA 0x1C #define UART_SIZE 0x20 #define STAT_TDRE BIT(23) #define STAT_RDRF BIT(21) #define STAT_OR BIT(19) static vaddr_t chip_to_base(struct serial_chip *chip) { struct imx_uart_data *pd = container_of(chip, struct imx_uart_data, chip); return io_pa_or_va(&pd->base, UART_SIZE); } static int imx_lpuart_getchar(struct serial_chip *chip) { int ch = 0; vaddr_t base = chip_to_base(chip); while (io_read32(base + STAT) & STAT_RDRF) ; ch = io_read32(base + DATA) & 0x3ff; if (io_read32(base + STAT) & STAT_OR) io_write32(base + STAT, STAT_OR); return ch; } static void imx_lpuart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + STAT) & STAT_TDRE)) ; io_write32(base + DATA, ch); } static const struct serial_ops imx_lpuart_ops = { .getchar = imx_lpuart_getchar, .putc = imx_lpuart_putc, }; DECLARE_KEEP_PAGER(imx_lpuart_ops); void imx_uart_init(struct imx_uart_data *pd, paddr_t base) { pd->base.pa = base; pd->chip.ops = &imx_lpuart_ops; /* * Do nothing, debug uart(sc lpuart) shared with normal world, * everything for uart initialization is done in bootloader. */ } #ifdef CFG_DT static struct serial_chip *imx_lpuart_dev_alloc(void) { struct imx_uart_data *pd = calloc(1, sizeof(*pd)); if (!pd) return NULL; return &pd->chip; } static int imx_lpuart_dev_init(struct serial_chip *chip, const void *fdt, int offs, const char *parms) { struct imx_uart_data *pd = container_of(chip, struct imx_uart_data, chip); vaddr_t vbase = 0; paddr_t pbase = 0; size_t size = 0; if (parms && parms[0]) IMSG("imx_lpuart: device parameters ignored (%s)", parms); if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) return -1; pbase = virt_to_phys((void *)vbase); imx_uart_init(pd, pbase); return 0; } static void imx_lpuart_dev_free(struct serial_chip *chip) { struct imx_uart_data *pd = container_of(chip, struct imx_uart_data, chip); free(pd); } static const struct serial_driver imx_lpuart_driver = { .dev_alloc = imx_lpuart_dev_alloc, .dev_init = imx_lpuart_dev_init, .dev_free = imx_lpuart_dev_free, }; static const struct dt_device_match imx_match_table[] = { { .compatible = "fsl,imx7ulp-lpuart" }, { .compatible = "fsl,imx8qm-lpuart" }, { 0 } }; DEFINE_DT_DRIVER(imx_dt_driver) = { .name = "imx_lpuart", .type = DT_DRIVER_UART, .match_table = imx_match_table, .driver = &imx_lpuart_driver, }; #endif /* CFG_DT */ optee_os-4.3.0/core/drivers/imx_ocotp.c000066400000000000000000000142771464416617300201350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP */ #include #include #include #include #include #include #include #include #define OCOTP_CTRL 0x0 #define OCOTP_CTRL_ERROR BIT32(9) #define OCOTP_CTRL_BUSY BIT32(8) #if defined(CFG_MX6) || defined(CFG_MX7ULP) #define OCOTP_SHADOW_OFFSET(_b, _w) ((_b) * (0x80) + (_w) * (0x10) + 0x400) #else #define OCOTP_SHADOW_OFFSET(_b, _w) ((_b) * (0x40) + (_w) * (0x10) + 0x400) #endif struct ocotp_instance { unsigned char nb_banks; unsigned char nb_words; TEE_Result (*get_die_id)(uint64_t *ret_uid); }; static vaddr_t g_base_addr; static struct mutex fuse_read = MUTEX_INITIALIZER; static const struct ocotp_instance *g_ocotp; #if defined(CFG_MX6) static void ocotp_clock_enable(void) { vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); io_setbits32(va + CCM_CCGR2, BM_CCM_CCGR2_OCOTP_CTRL); } #elif defined(CFG_MX7) static void ocotp_clock_enable(void) { vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); io_setbits32(va + CCM_CCGRx_SET(CCM_CLOCK_DOMAIN_OCOTP), CCM_CCGRx_ALWAYS_ON(0)); } #elif defined(CFG_MX8M) static void ocotp_clock_enable(void) { vaddr_t va = core_mmu_get_va(CCM_BASE, MEM_AREA_IO_SEC, CCM_SIZE); io_setbits32(va + CCM_CCGRx_SET(CCM_CCRG_OCOTP), CCM_CCGRx_ALWAYS_ON(0)); } #elif defined(CFG_MX7ULP) /* The i.MX7ULP has the OCOTP always powered on */ static inline void ocotp_clock_enable(void) { } #else #error "Platform not supported" #endif static TEE_Result ocotp_ctrl_wait_for(uint32_t mask) { unsigned int loop = 0; uint32_t reg = 0; assert(g_base_addr); /* 20us delay assuming the CPU clock running at 500MHz */ for (loop = 10000; loop > 0; loop--) { reg = io_read32(g_base_addr + OCOTP_CTRL) & mask; if (!reg) return TEE_SUCCESS; dsb(); isb(); } return TEE_ERROR_BUSY; } TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val) { TEE_Result ret = TEE_ERROR_GENERIC; if (!val) return TEE_ERROR_BAD_PARAMETERS; if (bank > g_ocotp->nb_banks || word > g_ocotp->nb_words) return TEE_ERROR_BAD_PARAMETERS; assert(g_base_addr && g_ocotp); mutex_lock(&fuse_read); ocotp_clock_enable(); /* Clear error bit */ io_clrbits32(g_base_addr + OCOTP_CTRL, OCOTP_CTRL_ERROR); /* Wait for busy flag to be cleared */ ret = ocotp_ctrl_wait_for(OCOTP_CTRL_BUSY); if (ret) { EMSG("OCOTP is busy"); goto out; } /* Read shadow register */ *val = io_read32(g_base_addr + OCOTP_SHADOW_OFFSET(bank, word)); DMSG("OCOTP Bank %d Word %d Fuse 0x%" PRIx32, bank, word, *val); out: mutex_unlock(&fuse_read); return ret; } static TEE_Result ocotp_get_die_id_mx7ulp(uint64_t *ret_uid) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t val = 0; uint64_t uid = 0; res = imx_ocotp_read(1, 6, &val); if (res) goto out; uid = val & GENMASK_32(15, 0); res = imx_ocotp_read(1, 5, &val); if (res) goto out; uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); res = imx_ocotp_read(1, 4, &val); if (res) goto out; uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); res = imx_ocotp_read(1, 3, &val); if (res) goto out; uid = SHIFT_U64(uid, 16) | (val & GENMASK_32(15, 0)); out: if (res == TEE_SUCCESS) *ret_uid = uid; return res; } static TEE_Result ocotp_get_die_id_mx(uint64_t *ret_uid) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t val = 0; uint64_t uid = 0; res = imx_ocotp_read(0, 2, &val); if (res) goto out; uid = val; res = imx_ocotp_read(0, 1, &val); if (res) goto out; uid = SHIFT_U64(uid, 32) | val; out: if (res == TEE_SUCCESS) *ret_uid = uid; return res; } static const struct ocotp_instance ocotp_imx6q = { .nb_banks = 16, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx6sl = { .nb_banks = 8, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx6sll = { .nb_banks = 16, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx6sx = { .nb_banks = 16, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx6ul = { .nb_banks = 16, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx6ull = { .nb_banks = 8, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx7d = { .nb_banks = 8, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx7ulp = { .nb_banks = 32, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx7ulp, }; static const struct ocotp_instance ocotp_imx8m = { .nb_banks = 32, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; static const struct ocotp_instance ocotp_imx8mp = { .nb_banks = 48, .nb_words = 8, .get_die_id = ocotp_get_die_id_mx, }; int tee_otp_get_die_id(uint8_t *buffer, size_t len) { size_t max_size_uid = IMX_UID_SIZE; uint64_t uid = 0; assert(buffer); assert(g_base_addr && g_ocotp); if (g_ocotp->get_die_id(&uid)) goto err; memcpy(buffer, &uid, MIN(max_size_uid, len)); return 0; err: EMSG("Error while getting die ID"); return -1; } register_phys_mem_pgdir(MEM_AREA_IO_SEC, OCOTP_BASE, CORE_MMU_PGDIR_SIZE); static TEE_Result imx_ocotp_init(void) { g_base_addr = core_mmu_get_va(OCOTP_BASE, MEM_AREA_IO_SEC, OCOTP_SIZE); if (!g_base_addr) return TEE_ERROR_GENERIC; if (soc_is_imx6sdl() || soc_is_imx6dq() || soc_is_imx6dqp()) { g_ocotp = &ocotp_imx6q; } else if (soc_is_imx6sl()) { g_ocotp = &ocotp_imx6sl; } else if (soc_is_imx6sll()) { g_ocotp = &ocotp_imx6sll; } else if (soc_is_imx6sx()) { g_ocotp = &ocotp_imx6sx; } else if (soc_is_imx6ul()) { g_ocotp = &ocotp_imx6ul; } else if (soc_is_imx6ull()) { g_ocotp = &ocotp_imx6ull; } else if (soc_is_imx7ds()) { g_ocotp = &ocotp_imx7d; } else if (soc_is_imx7ulp()) { g_ocotp = &ocotp_imx7ulp; } else if (soc_is_imx8mm() || soc_is_imx8mn() || soc_is_imx8mq()) { g_ocotp = &ocotp_imx8m; } else if (soc_is_imx8mp()) { g_ocotp = &ocotp_imx8mp; } else { g_ocotp = NULL; return TEE_ERROR_NOT_SUPPORTED; } return TEE_SUCCESS; } service_init(imx_ocotp_init); optee_os-4.3.0/core/drivers/imx_rngb.c000066400000000000000000000107121464416617300177270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * (c) 2021 Jorge Ramirez , Foundries Ltd. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RNG_VER 0x00 #define RNG_CMD 0x04 #define RNG_CR 0x08 #define RNG_SR 0x0C #define RNG_ESR 0x10 #define RNG_OUT 0x14 #define RNG_CMD_CLR_INT BIT(4) #define RNG_CMD_CLR_ERR BIT(5) #define RNG_CR_AR BIT(4) #define RNG_CR_MASK_DONE BIT(5) #define RNG_CR_MASK_ERROR BIT(6) #define RNG_SR_ST_DONE BIT(4) #define RNG_SR_SEED_DONE BIT(5) #define RNG_SR_ERROR BIT(16) #define RNG_SR_FIFO_LEVEL_SHIFT 8 #define RNG_SR_FIFO_LEVEL_MASK GENMASK_32(11, RNG_SR_FIFO_LEVEL_SHIFT) #define RNG_VER_TYPE_SHIFT 28 #define RNG_VER_TYPE_MASK GENMASK_32(31, RNG_VER_TYPE_SHIFT) #define RNG_ESR_STATUS_STAT_ERR BIT(3) #define RNG_TYPE_RNGA 0 #define RNG_TYPE_RNGB 1 #define RNG_TYPE_RNGC 2 #define SEED_TIMEOUT 2000000 #define IRQ_TIMEOUT 1000000 #define WORDS_IN_FIFO(__rng_sr) \ (((__rng_sr) & RNG_SR_FIFO_LEVEL_MASK) >> RNG_SR_FIFO_LEVEL_SHIFT) #define RNG_TYPE(__rng_vr) \ (((__rng_vr) & RNG_VER_TYPE_MASK) >> RNG_VER_TYPE_SHIFT) static struct imx_rng { struct io_pa_va base; size_t size; bool ready; uint32_t error; } rngb = { .base.pa = RNGB_BASE, .size = 0x4000, }; static void wait_for_irq(struct imx_rng *rng) { uint64_t tref = timeout_init_us(IRQ_TIMEOUT); uint32_t status = 0; do { rng->error = io_read32(rng->base.va + RNG_ESR); status = io_read32(rng->base.va + RNG_SR); if (timeout_elapsed(tref)) panic(); } while ((status & (RNG_SR_SEED_DONE | RNG_SR_ST_DONE)) == 0); } static void irq_clear(struct imx_rng *rng) { io_setbits32(rng->base.va + RNG_CR, RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); io_setbits32(rng->base.va + RNG_CMD, RNG_CMD_CLR_INT | RNG_CMD_CLR_ERR); } static void irq_unmask(struct imx_rng *rng) { io_clrbits32(rng->base.va + RNG_CR, RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR); } static void rng_seed(struct imx_rng *rng) { uint64_t tref = timeout_init_us(SEED_TIMEOUT); irq_clear(rng); do { irq_unmask(rng); /* configure continuous auto-reseed */ io_setbits32(rng->base.va + RNG_CR, RNG_CR_AR); wait_for_irq(rng); irq_clear(rng); if (timeout_elapsed(tref)) panic(); } while (rng->error); } static TEE_Result map_controller_static(void) { rngb.base.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, rngb.base.pa, rngb.size); if (!rngb.base.va) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } #if !defined(CFG_DT) static TEE_Result map_controller(void) { return map_controller_static(); } #else static const char *const rng_match_table[] = { "fsl,imx25-rngb", }; static TEE_Result map_controller(void) { void *fdt = get_dt(); unsigned int i = 0; int off = -1; if (!fdt) return map_controller_static(); for (i = 0; i < ARRAY_SIZE(rng_match_table); i++) { off = fdt_node_offset_by_compatible(fdt, 0, rng_match_table[i]); if (off >= 0) break; } if (off < 0) return map_controller_static(); if (dt_enable_secure_status(fdt, off)) return TEE_ERROR_NOT_SUPPORTED; if (dt_map_dev(fdt, off, &rngb.base.va, &rngb.size, DT_MAP_AUTO) < 0) return TEE_ERROR_NOT_SUPPORTED; rngb.base.pa = virt_to_phys((void *)rngb.base.va); return TEE_SUCCESS; } #endif TEE_Result hw_get_random_bytes(void *buf, size_t len) { uint32_t *rngbuf = buf; uint32_t status = 0; uint32_t val = 0; if (!rngb.ready) return TEE_ERROR_BAD_STATE; while (len) { status = io_read32(rngb.base.va + RNG_SR); if (status & RNG_SR_ERROR) return TEE_ERROR_BAD_STATE; if (WORDS_IN_FIFO(status)) { val = io_read32(rngb.base.va + RNG_OUT); if (len > sizeof(uint32_t)) { len = len - sizeof(uint32_t); memcpy(rngbuf, &val, sizeof(uint32_t)); rngbuf++; } else { memcpy(rngbuf, &val, len); len = 0; } } } return TEE_SUCCESS; } void plat_rng_init(void) { } static TEE_Result rngb_init(void) { uint32_t type = 0; if (map_controller()) panic(); type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER)); if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC) panic(); rng_seed(&rngb); rngb.ready = true; return TEE_SUCCESS; } driver_init(rngb_init); optee_os-4.3.0/core/drivers/imx_sc_api.c000066400000000000000000000155051464416617300202420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * Copyright 2017-2022 NXP */ #include #include #include #include #include #include #include #include #define RNG_INIT_RETRY 100 #define SC_RPC_VERSION 1 #define SC_RPC_MAX_MSG 8 /* Defines for struct sc_rpc_msg svc field */ #define SC_RPC_SVC_PM 2 #define SC_RPC_SVC_RM 3 #define SC_RPC_SVC_SECO 9 /* Define for PM function calls */ enum sc_pm_func { SC_PM_FUNC_SET_RESOURCE_POWER_MODE = 3 }; /* Defines for RM function calls */ enum sc_rm_func { SC_RM_FUNC_GET_PARTITION = 5, SC_RM_FUNC_ASSIGN_RESOURCE = 8 }; /* Define for SECO function calls */ enum sc_seco_func { SC_SECO_FUNC_START_RNG = 22 }; /* Internal SCFW API error codes */ enum sc_error { SC_ERR_NONE = 0, /* Success */ SC_ERR_VERSION, /* Incompatible API version */ SC_ERR_CONFIG, /* Configuration error */ SC_ERR_PARM, /* Bad parameter */ SC_ERR_NOACCESS, /* Permission error (no access) */ SC_ERR_LOCKED, /* Permission error (locked) */ SC_ERR_UNAVAILABLE, /* Unavailable (out of resources) */ SC_ERR_NOTFOUND, /* Not found */ SC_ERR_NOPOWER, /* No power */ SC_ERR_IPC, /* Generic IPC error */ SC_ERR_BUSY, /* Resource is currently busy/active */ SC_ERR_FAIL, /* General I/O failure */ SC_ERR_LAST }; /* RNG SECO states */ enum sc_seco_rng_status { SC_SECO_RNG_STAT_UNAVAILABLE = 0, SC_SECO_RNG_STAT_INPROGRESS, SC_SECO_RNG_STAT_READY }; /* Resources IDs */ enum sc_resource { SC_RES_CAAM_JR1 = 500, SC_RES_CAAM_JR2, SC_RES_CAAM_JR3, SC_RES_CAAM_JR1_OUT = 514, SC_RES_CAAM_JR2_OUT, SC_RES_CAAM_JR3_OUT, SC_RES_CAAM_JR0 = 519, SC_RES_CAAM_JR0_OUT, SC_RES_LAST = 546 }; /* Power modes */ enum sc_power_mode { SC_PM_PW_MODE_OFF = 0, SC_PM_PW_MODE_STBY, SC_PM_PW_MODE_LP, SC_PM_PW_MODE_ON }; static vaddr_t secure_ipc_addr; register_phys_mem(MEM_AREA_IO_SEC, SC_IPC_BASE_SECURE, SC_IPC_SIZE); /* * Get the partition ID of secure world * * @partition Partition ID */ static TEE_Result sc_rm_get_partition(uint8_t *partition) { TEE_Result res = TEE_ERROR_GENERIC; enum sc_error err = SC_ERR_LAST; struct imx_mu_msg msg = { .header.version = SC_RPC_VERSION, .header.size = 1, .header.tag = SC_RPC_SVC_RM, .header.command = SC_RM_FUNC_GET_PARTITION, }; res = imx_mu_call(secure_ipc_addr, &msg, true); if (res != TEE_SUCCESS) { EMSG("Communication error"); return res; } err = msg.header.command; if (err != SC_ERR_NONE) { EMSG("Unable to get partition ID, sc_error: %d", err); return TEE_ERROR_GENERIC; } *partition = IMX_MU_DATA_U8(&msg, 0); return TEE_SUCCESS; } /* * Set the given power mode of a resource * * @resource ID of the resource * @mode Power mode to apply */ static TEE_Result sc_pm_set_resource_power_mode(enum sc_resource resource, enum sc_power_mode mode) { TEE_Result res = TEE_ERROR_GENERIC; enum sc_error scu_error = SC_ERR_LAST; struct imx_mu_msg msg = { .header.version = SC_RPC_VERSION, .header.size = 2, .header.tag = SC_RPC_SVC_PM, .header.command = SC_PM_FUNC_SET_RESOURCE_POWER_MODE, }; IMX_MU_DATA_U16(&msg, 0) = (uint16_t)resource; IMX_MU_DATA_U8(&msg, 2) = (uint8_t)mode; res = imx_mu_call(secure_ipc_addr, &msg, true); if (res != TEE_SUCCESS) { EMSG("Communication error"); return res; } scu_error = msg.header.command; if (scu_error != SC_ERR_NONE) { EMSG("Unable to set resource power mode sc_error: %d", scu_error); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } /* * Assign ownership of a resource to the secure partition * * @resource Resource to assign */ static TEE_Result sc_rm_assign_resource(enum sc_resource resource) { TEE_Result res = TEE_ERROR_GENERIC; enum sc_error err = SC_ERR_LAST; uint8_t secure_partition = 0; struct imx_mu_msg msg = { .header.version = SC_RPC_VERSION, .header.size = 2, .header.tag = SC_RPC_SVC_RM, .header.command = SC_RM_FUNC_ASSIGN_RESOURCE, }; res = sc_rm_get_partition(&secure_partition); if (res != TEE_SUCCESS) { EMSG("Cannot get secure partition ID"); return res; } IMX_MU_DATA_U16(&msg, 0) = (uint16_t)resource; IMX_MU_DATA_U8(&msg, 2) = secure_partition; res = imx_mu_call(secure_ipc_addr, &msg, true); if (res != TEE_SUCCESS) { EMSG("Communication error"); return res; } err = msg.header.command; if (err != SC_ERR_NONE) { EMSG("Unable to assign resource, sc_error: %d", err); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } TEE_Result imx_sc_rm_enable_jr(unsigned int jr_index) { TEE_Result res = TEE_ERROR_GENERIC; enum sc_resource jr_res = SC_RES_LAST; enum sc_resource jr_out_res = SC_RES_LAST; switch (jr_index) { case 0: jr_res = SC_RES_CAAM_JR0; jr_out_res = SC_RES_CAAM_JR0_OUT; break; case 1: jr_res = SC_RES_CAAM_JR1; jr_out_res = SC_RES_CAAM_JR1_OUT; break; case 2: jr_res = SC_RES_CAAM_JR2; jr_out_res = SC_RES_CAAM_JR2_OUT; break; case 3: jr_res = SC_RES_CAAM_JR3; jr_out_res = SC_RES_CAAM_JR3_OUT; break; default: EMSG("Wrong JR Index, should be 0, 1, 2 or 3"); return TEE_ERROR_GENERIC; } /* Assign JR resources to secure world */ res = sc_rm_assign_resource(jr_res); if (res != TEE_SUCCESS) { EMSG("Assign SC_R_CAAM_JR%u resource failed", jr_index); return res; } res = sc_rm_assign_resource(jr_out_res); if (res != TEE_SUCCESS) { EMSG("Assign SC_R_CAAM_JR%u_OUT resource failed", jr_index); return res; } /* Power ON JR resources */ res = sc_pm_set_resource_power_mode(jr_res, SC_PM_PW_MODE_ON); if (res != TEE_SUCCESS) { EMSG("POWER ON SC_R_CAAM_JR%u resource failed", jr_index); return res; } res = sc_pm_set_resource_power_mode(jr_out_res, SC_PM_PW_MODE_ON); if (res != TEE_SUCCESS) { EMSG("POWER ON SC_R_CAAM_JR%u_OUT resource failed", jr_index); return res; } return TEE_SUCCESS; } TEE_Result imx_sc_seco_start_rng(void) { TEE_Result res = TEE_ERROR_GENERIC; enum sc_error err = SC_ERR_LAST; enum sc_seco_rng_status status = SC_SECO_RNG_STAT_UNAVAILABLE; unsigned int retry = 0; struct imx_mu_msg msg = { .header.version = SC_RPC_VERSION, .header.size = 1, .header.tag = SC_RPC_SVC_SECO, .header.command = SC_SECO_FUNC_START_RNG, }; for (retry = RNG_INIT_RETRY; retry; retry--) { res = imx_mu_call(secure_ipc_addr, &msg, true); if (res != TEE_SUCCESS) { EMSG("Configuration error"); return res; } err = msg.header.command; if (err != SC_ERR_NONE) { EMSG("RNG status: %d", err); return TEE_ERROR_GENERIC; } status = IMX_MU_DATA_U32(&msg, 0); if (status == SC_SECO_RNG_STAT_READY) return TEE_SUCCESS; } return TEE_ERROR_GENERIC; } TEE_Result imx_sc_driver_init(void) { vaddr_t va = 0; va = core_mmu_get_va(SC_IPC_BASE_SECURE, MEM_AREA_IO_SEC, SC_IPC_SIZE); if (!va) return TEE_ERROR_GENERIC; imx_mu_init(va); secure_ipc_addr = va; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/imx_scu.c000066400000000000000000000016341464416617300175740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2019, 2023 NXP * */ #include #include #include #include #include /* Invalidate all registers */ #define SCU_INV_CTRL_INIT 0xFFFFFFFF /* Both secure CPU access SCU */ #define SCU_SAC_CTRL_INIT 0x0000000F /* Both non-secure CPU access SCU, private and global timer */ #define SCU_NSAC_CTRL_INIT 0x00000FFF static TEE_Result scu_init(void) { vaddr_t scu_base = core_mmu_get_va(SCU_BASE, MEM_AREA_IO_SEC, SCU_SIZE); if (!scu_base) return TEE_ERROR_GENERIC; /* SCU config */ io_write32(scu_base + SCU_INV_SEC, SCU_INV_CTRL_INIT); io_write32(scu_base + SCU_SAC, SCU_SAC_CTRL_INIT); io_write32(scu_base + SCU_NSAC, SCU_NSAC_CTRL_INIT); /* SCU enable */ io_write32(scu_base + SCU_CTRL, io_read32(scu_base + SCU_CTRL) | 0x1); return TEE_SUCCESS; } driver_init(scu_init); optee_os-4.3.0/core/drivers/imx_snvs.c000066400000000000000000000114341464416617300177720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2020 Pengutronix * Rouven Czerwinski * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include #define SNVS_HPLR 0x00 #define SNVS_HPCOMR 0x04 #define SNVS_HPSR 0x14 #define SNVS_LPLR 0x34 #define SNVS_LPCR 0x38 #define SNVS_LPMKCR 0x3C #define HPSR_SSM_ST_MASK GENMASK_32(11, 8) #define HPSR_SSM_ST_SHIFT 8 #define SNVS_HPSR_SYS_SECURITY_CFG_OFFSET 12 #define SNVS_HPSR_SYS_SECURITY_CFG GENMASK_32(14, 12) #define SNVS_HPSR_OTPMK_SYND GENMASK_32(24, 16) #define SNVS_HPSR_OTPMK_ZERO BIT(27) #define SNVS_HPLR_MKS_SL BIT32(9) #define SNVS_LPLR_MKS_HL BIT32(9) #define SNVS_HPCOMR_MKS_EN BIT32(13) #define SNVS_HPCOMR_NPSWA_EN BIT32(31) #define SNVS_LPMKCR_MKCR_MKS_SEL GENMASK_32(1, 0) #define SNVS_LPCR_TOP_MASK BIT(6) #define SNVS_LPCR_DP_EN_MASK BIT(5) #define SNVS_LPCR_SRTC_ENV_MASK BIT(1) enum snvs_ssm_mode { SNVS_SSM_MODE_INIT, SNVS_SSM_MODE_HARD_FAIL, SNVS_SSM_MODE_SOFT_FAIL = 3, SNVS_SSM_MODE_INIT_INTERMEDIATE = 8, SNVS_SSM_MODE_CHECK, SNVS_SSM_MODE_NON_SECURE = 11, SNVS_SSM_MODE_TRUSTED = 13, SNVS_SSM_MODE_SECURE = 15, }; enum snvs_security_cfg { SNVS_SECURITY_CFG_FAB, SNVS_SECURITY_CFG_OPEN, SNVS_SECURITY_CFG_CLOSED, SNVS_SECURITY_CFG_FIELD_RETURN, }; /* * Return true if the master key is OTPMK, false otherwise. */ static bool is_otpmk_selected(void) { uint32_t hp_mks = 0; vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); hp_mks = io_read32(base + SNVS_HPCOMR); /* * The master key selection might be done by the MASTER_KEY_SEL field * of LPMKCR instead. */ if (hp_mks & SNVS_HPCOMR_MKS_EN) { uint32_t lp_mks = io_read32(base + SNVS_LPMKCR); if (lp_mks & SNVS_LPMKCR_MKCR_MKS_SEL) return false; } return true; } /* * Return true if the master key selection is locked, false otherwise. */ static bool is_mks_locked(void) { vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); return io_read32(base + SNVS_HPLR) & SNVS_HPLR_MKS_SL || io_read32(base + SNVS_LPLR) & SNVS_LPLR_MKS_HL; } /* Set the Master key to use OTPMK and lock it. */ static void set_mks_otpmk(void) { vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); io_setbits32(base + SNVS_HPCOMR, SNVS_HPCOMR_MKS_EN); io_clrbits32(base + SNVS_LPMKCR, SNVS_LPMKCR_MKCR_MKS_SEL); io_clrbits32(base + SNVS_HPLR, SNVS_HPLR_MKS_SL); io_setbits32(base + SNVS_LPLR, SNVS_LPLR_MKS_HL); } /* * Return true if OTPMK is valid, false otherwise. */ static bool is_otpmk_valid(void) { vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); uint32_t status = io_read32(base + SNVS_HPSR); return !(status & (SNVS_HPSR_OTPMK_ZERO | SNVS_HPSR_OTPMK_SYND)); } static enum snvs_security_cfg snvs_get_security_cfg(void) { uint32_t val = 0; vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); val = (io_read32(base + SNVS_HPSR) & SNVS_HPSR_SYS_SECURITY_CFG) >> SNVS_HPSR_SYS_SECURITY_CFG_OFFSET; switch (val) { case 0b000: return SNVS_SECURITY_CFG_FAB; case 0b001: return SNVS_SECURITY_CFG_OPEN; case 0b011: return SNVS_SECURITY_CFG_CLOSED; default: return SNVS_SECURITY_CFG_FIELD_RETURN; } } bool snvs_is_device_closed(void) { return (snvs_get_security_cfg() == SNVS_SECURITY_CFG_CLOSED); } #ifdef CFG_RPMB_FS static enum snvs_ssm_mode snvs_get_ssm_mode(void) { vaddr_t snvs = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_HPSR + sizeof(uint32_t)); uint32_t val = 0; val = io_read32(snvs + SNVS_HPSR); val &= HPSR_SSM_ST_MASK; val = val >> HPSR_SSM_ST_SHIFT; DMSG("HPSR: SSM ST Mode: 0x%01"PRIx32, val); return val; } bool plat_rpmb_key_is_ready(void) { enum snvs_ssm_mode mode = SNVS_SSM_MODE_INIT; bool ssm_secure = false; mode = snvs_get_ssm_mode(); ssm_secure = (mode == SNVS_SSM_MODE_TRUSTED || mode == SNVS_SSM_MODE_SECURE); /* * On i.MX6SDL and i.MX6DQ, the security cfg always returns * SNVS_SECURITY_CFG_FAB (000), therefore we ignore the security * configuration for this SoC. */ if (soc_is_imx6sdl() || soc_is_imx6dq()) return ssm_secure; return ssm_secure && snvs_is_device_closed(); } #endif /* CFG_RPMB_FS */ TEE_Result imx_snvs_set_master_otpmk(void) { if (!is_otpmk_valid()) return TEE_ERROR_BAD_STATE; if (is_mks_locked()) { if (is_otpmk_selected()) return TEE_SUCCESS; return TEE_ERROR_BAD_STATE; } set_mks_otpmk(); return TEE_SUCCESS; } void imx_snvs_shutdown(void) { vaddr_t base = core_mmu_get_va(SNVS_BASE, MEM_AREA_IO_SEC, SNVS_SIZE); io_write32(base + SNVS_LPCR, SNVS_LPCR_TOP_MASK | SNVS_LPCR_DP_EN_MASK | SNVS_LPCR_SRTC_ENV_MASK); } optee_os-4.3.0/core/drivers/imx_uart.c000066400000000000000000000143471464416617300177620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * All rights reserved. * Copyright 2018-2019 NXP. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include /* Register definitions */ #define URXD 0x0 /* Receiver Register */ #define UTXD 0x40 /* Transmitter Register */ #define UCR1 0x80 /* Control Register 1 */ #define UCR2 0x84 /* Control Register 2 */ #define UCR3 0x88 /* Control Register 3 */ #define UCR4 0x8c /* Control Register 4 */ #define UFCR 0x90 /* FIFO Control Register */ #define USR1 0x94 /* Status Register 1 */ #define USR2 0x98 /* Status Register 2 */ #define UESC 0x9c /* Escape Character Register */ #define UTIM 0xa0 /* Escape Timer Register */ #define UBIR 0xa4 /* BRM Incremental Register */ #define UBMR 0xa8 /* BRM Modulator Register */ #define UBRC 0xac /* Baud Rate Count Register */ #define UTS 0xb4 /* UART Test Register (mx31) */ #define USIZE 0xb8 /* UTS + sizeof(uint32_t) */ /* UART Control Register Bit Fields.*/ #define URXD_CHARRDY (1<<15) #define URXD_ERR (1<<14) #define URXD_OVRRUN (1<<13) #define URXD_FRMERR (1<<12) #define URXD_BRK (1<<11) #define URXD_PRERR (1<<10) #define URXD_RX_DATA (0xFF) #define UCR1_ADEN (1<<15) /* Auto dectect interrupt */ #define UCR1_ADBR (1<<14) /* Auto detect baud rate */ #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */ #define UCR1_IDEN (1<<12) /* Idle condition interrupt */ #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */ #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */ #define UCR1_IREN (1<<7) /* Infrared interface enable */ #define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */ #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */ #define UCR1_SNDBRK (1<<4) /* Send break */ #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */ #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */ #define UCR1_DOZE (1<<1) /* Doze */ #define UCR1_UARTEN (1<<0) /* UART enabled */ #define UTS_FRCPERR (1<<13) /* Force parity error */ #define UTS_LOOP (1<<12) /* Loop tx and rx */ #define UTS_TXEMPTY (1<<6) /* TxFIFO empty */ #define UTS_RXEMPTY (1<<5) /* RxFIFO empty */ #define UTS_TXFULL (1<<4) /* TxFIFO full */ #define UTS_RXFULL (1<<3) /* RxFIFO full */ #define UTS_SOFTRST (1<<0) /* Software reset */ static vaddr_t chip_to_base(struct serial_chip *chip) { struct imx_uart_data *pd = container_of(chip, struct imx_uart_data, chip); return io_pa_or_va(&pd->base, USIZE); } static void imx_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + UTS) & UTS_TXEMPTY)) if (!(io_read32(base + UCR1) & UCR1_UARTEN)) return; } static int imx_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (io_read32(base + UTS) & UTS_RXEMPTY) ; return (io_read32(base + URXD) & URXD_RX_DATA); } static void imx_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); /* Wait until there's space in the TX FIFO */ while (io_read32(base + UTS) & UTS_TXFULL) if (!(io_read32(base + UCR1) & UCR1_UARTEN)) return; io_write32(base + UTXD, ch); } static const struct serial_ops imx_uart_ops = { .flush = imx_uart_flush, .getchar = imx_uart_getchar, .putc = imx_uart_putc, }; DECLARE_KEEP_PAGER(imx_uart_ops); void imx_uart_init(struct imx_uart_data *pd, paddr_t base) { pd->base.pa = base; pd->chip.ops = &imx_uart_ops; /* * Do nothing, debug uart(uart0) share with normal world, * everything for uart0 initialization is done in bootloader. */ } #ifdef CFG_DT static struct serial_chip *imx_uart_dev_alloc(void) { struct imx_uart_data *pd = calloc(1, sizeof(*pd)); if (!pd) return NULL; return &pd->chip; } static int imx_uart_dev_init(struct serial_chip *chip, const void *fdt, int offs, const char *parms) { struct imx_uart_data *pd = container_of(chip, struct imx_uart_data, chip); vaddr_t vbase = 0; paddr_t pbase = 0; size_t size = 0; if (parms && parms[0]) IMSG("imx_uart: device parameters ignored (%s)", parms); if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) return -1; pbase = virt_to_phys((void *)vbase); imx_uart_init(pd, pbase); return 0; } static void imx_uart_dev_free(struct serial_chip *chip) { struct imx_uart_data *pd = container_of(chip, struct imx_uart_data, chip); free(pd); } static const struct serial_driver imx_uart_driver = { .dev_alloc = imx_uart_dev_alloc, .dev_init = imx_uart_dev_init, .dev_free = imx_uart_dev_free, }; static const struct dt_device_match imx_match_table[] = { { .compatible = "fsl,imx6q-uart" }, { 0 } }; DEFINE_DT_DRIVER(imx_dt_driver) = { .name = "imx_uart", .type = DT_DRIVER_UART, .match_table = imx_match_table, .driver = &imx_uart_driver, }; #endif /* CFG_DT */ optee_os-4.3.0/core/drivers/imx_wdog.c000066400000000000000000000103211464416617300177330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2019 NXP * * Peng Fan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include static bool ext_reset_output __maybe_unused; static vaddr_t wdog_base; void imx_wdog_restart(bool external_reset __maybe_unused) { uint32_t val = 0; if (!wdog_base) { EMSG("No wdog mapped"); panic(); } #ifdef CFG_MX7ULP val = io_read32(wdog_base + WDOG_CS); io_write32(wdog_base + WDOG_CNT, UNLOCK); /* Enable wdog */ io_write32(wdog_base + WDOG_CS, val | WDOG_CS_EN); io_write32(wdog_base + WDOG_CNT, UNLOCK); io_write32(wdog_base + WDOG_TOVAL, 1000); io_write32(wdog_base + WDOG_CNT, REFRESH); #else if (external_reset && ext_reset_output) val = 0x14; else val = 0x24; DMSG("val %x", val); io_write16(wdog_base + WDT_WCR, val); dsb(); if (io_read16(wdog_base + WDT_WCR) & WDT_WCR_WDE) { io_write16(wdog_base + WDT_WSR, WDT_SEQ1); io_write16(wdog_base + WDT_WSR, WDT_SEQ2); } io_write16(wdog_base + WDT_WCR, val); io_write16(wdog_base + WDT_WCR, val); #endif while (1) ; } DECLARE_KEEP_PAGER(imx_wdog_restart); #if defined(CFG_DT) && !defined(CFG_EXTERNAL_DTB_OVERLAY) static const char * const dt_wdog_match_table[] = { "fsl,imx21-wdt", "fsl,imx7ulp-wdt", }; static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) { const char *match = NULL; void *fdt = NULL; vaddr_t vbase = 0; int found_off = 0; size_t sz = 0; int off = 0; int st = 0; uint32_t i = 0; fdt = get_dt(); if (!fdt) { EMSG("No DTB"); return TEE_ERROR_NOT_SUPPORTED; } /* search the first usable wdog */ for (i = 0; i < ARRAY_SIZE(dt_wdog_match_table); i++) { match = dt_wdog_match_table[i]; off = 0; while (off >= 0) { off = fdt_node_offset_by_compatible(fdt, off, match); if (off > 0) { st = fdt_get_status(fdt, off); if (st & DT_STATUS_OK_SEC) { DMSG("Wdog found at %u", off); found_off = off; break; } } } if (found_off) break; else DMSG("%s not found in DTB", dt_wdog_match_table[i]); } if (!found_off) { EMSG("No Watchdog found in DTB"); return TEE_ERROR_ITEM_NOT_FOUND; } ext_reset_output = dt_have_prop(fdt, found_off, "fsl,ext-reset-output"); if (dt_map_dev(fdt, found_off, &vbase, &sz, DT_MAP_AUTO) < 0) { EMSG("Failed to map Watchdog"); return TEE_ERROR_ITEM_NOT_FOUND; } *wdog_vbase = vbase; return TEE_SUCCESS; } #else register_phys_mem_pgdir(MEM_AREA_IO_SEC, WDOG_BASE, CORE_MMU_PGDIR_SIZE); static TEE_Result imx_wdog_base(vaddr_t *wdog_vbase) { *wdog_vbase = (vaddr_t)phys_to_virt(WDOG_BASE, MEM_AREA_IO_SEC, 1); #if defined(CFG_IMX_WDOG_EXT_RESET) ext_reset_output = true; #endif return TEE_SUCCESS; } #endif static TEE_Result imx_wdog_init(void) { return imx_wdog_base(&wdog_base); } driver_init(imx_wdog_init); optee_os-4.3.0/core/drivers/lpc_uart.c000066400000000000000000000047211464416617300177360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, HiSilicon Limited */ #include #include #include #include #include #include static paddr_t chip_to_base(struct serial_chip *chip) { struct lpc_uart_data *pd = container_of(chip, struct lpc_uart_data, chip); return io_pa_or_va(&pd->base, LPC_SIZE); } static void lpc_byte_read(paddr_t addr, uint8_t *data) { uint32_t status = 0; uint32_t cnt = 0; io_write32(LPC_CMD_REG_OFFSET + addr, LPC_SINGLE_READ); io_write32(LPC_OP_LEN_REG_OFFSET + addr, 1); io_write32(LPC_ADDR_REG_OFFSET + addr, UART_BASE + UART_LSR); io_write32(LPC_START_REG_OFFSET + addr, 1); status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); while (!(status & LPC_IRQ_ST_ON)) { if (cnt > UART_SEND_LOOP_MAX) return; cnt++; status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); } io_write32(LPC_IRQ_ST_REG_OFFSET + addr, LPC_IRQ_ST_ON); if (io_read32(LPC_OP_STATUS_REG_OFFSET + addr) & LPC_IRQ_ST_ON) *data = io_read32(LPC_RDATA_REG_OFFSET + addr); } static void lpc_byte_write(paddr_t addr, uint8_t data) { uint32_t status = 0; uint32_t cnt = 0; io_write32(LPC_CMD_REG_OFFSET + addr, LPC_SINGLE_WRITE); io_write32(LPC_OP_LEN_REG_OFFSET + addr, 1); io_write32(LPC_WDATA_REG_OFFSET + addr, data); io_write32(LPC_ADDR_REG_OFFSET + addr, UART_BASE + UART_THR); io_write32(LPC_START_REG_OFFSET + addr, 1); status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); while (!(status & LPC_IRQ_ST_ON)) { if (cnt > UART_SEND_LOOP_MAX) return; cnt++; status = io_read32(LPC_IRQ_ST_REG_OFFSET + addr); } io_write32(LPC_IRQ_ST_REG_OFFSET + addr, LPC_IRQ_ST_ON); } static void lpc_uart_core_putc(paddr_t base, int ch) { uint8_t var = '\0'; uint32_t i = 0; for (i = 0; i < UART_SEND_LOOP_MAX; i++) { lpc_byte_read(base, &var); if ((var & LPC_RADTA_LEN) == LPC_RADTA_LEN) break; } lpc_byte_write(base, ch); for (i = 0; i < UART_SEND_LOOP_MAX; i++) { lpc_byte_read(base, &var); if ((var & LPC_RADTA_LEN) == LPC_RADTA_LEN) break; } } static void lpc_uart_putc(struct serial_chip *chip, int ch) { paddr_t base = chip_to_base(chip); lpc_uart_core_putc(base, ch); } static const struct serial_ops lpc_uart_ops = { .putc = lpc_uart_putc, }; DECLARE_KEEP_PAGER(lpc_uart_ops); void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base, uint32_t uart_clk __unused, uint32_t baud_rate __unused) { pd->base.pa = base; pd->chip.ops = &lpc_uart_ops; } optee_os-4.3.0/core/drivers/ls_dspi.c000066400000000000000000000413351464416617300175640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Driver for DSPI Controller * */ #include #include #include #include #include #include #include #include #include #include /* SPI register offset */ #define DSPI_MCR 0x0 /* Module Configuration Register */ #define DSPI_TCR 0x8 /* Transfer Count Register */ #define DSPI_CTAR0 \ 0xC /* Clock and Transfer Attributes Register (in Master mode) */ #define DSPI_CTAR1 \ 0x10 /* Clock and Transfer Attributes Register (in Master mode) */ #define DSPI_SR 0x2C /* Status Register */ #define DSPI_RSER 0x30 /* DMA/Interrupt Request Select and Enable Register */ #define DSPI_PUSHR 0x34 /* PUSH TX FIFO Register In Master Mode */ #define DSPI_POPR 0x38 /* POP RX FIFO Register */ #define DSPI_TXFR0 0x3C /* Transmit FIFO Registers */ #define DSPI_TXFR1 0x40 /* Transmit FIFO Registers */ #define DSPI_TXFR2 0x44 /* Transmit FIFO Registers */ #define DSPI_TXFR3 0x48 /* Transmit FIFO Registers */ #define DSPI_RXFR0 0x7C /* Receive FIFO Registers */ #define DSPI_RXFR1 0x80 /* Receive FIFO Registers */ #define DSPI_RXFR2 0x84 /* Receive FIFO Registers */ #define DSPI_RXFR3 0x88 /* Receive FIFO Registers */ #define DSPI_CTARE0 0x11C /* Clock and Transfer Attributes Register Extended */ #define DSPI_CTARE1 0x120 /* Clock and Transfer Attributes Register Extended */ #define DSPI_SREX 0x13C /* Status Register Extended */ /* Module configuration */ #define DSPI_MCR_MSTR 0x80000000 /* Master/Slave Mode Select [0] */ #define DSPI_MCR_CSCK 0x40000000 /* Continuous SCK Enable [1] */ #define DSPI_MCR_DCONF(x) (((x) & 0x03) << 28) /* SPI Configuration [2-3] */ #define DSPI_MCR_ROOE \ 0x01000000 /* Receive FIFO Overflow Overwrite Enable[7] */ #define DSPI_MCR_PCSIS(x) \ (1 << (16 + (x))) /* Peripheral Chip Select x Inactive State [12-15] */ #define DSPI_MCR_PCSIS_MASK (0xff << 16) #define DSPI_MCR_MDIS 0x00004000 /* Module Disable [17] */ #define DSPI_MCR_DTXF 0x00002000 /* Disable Transmit FIFO [18] */ #define DSPI_MCR_DRXF 0x00001000 /* Disable Receive FIFO [19] */ #define DSPI_MCR_CTXF 0x00000800 /* Clear TX FIFO [20] */ #define DSPI_MCR_CRXF 0x00000400 /* Clear RX FIFO [21] */ #define DPSI_XSPI 0x00000008 /* Extended SPI Mode [28] */ #define DSPI_MCR_PES 0x00000002 /* Parity Error Stop [30] */ #define DSPI_MCR_HALT 0x00000001 /* Halt [31] */ #define DPSI_ENABLE 0x0 #define DSPI_DISABLE 0x1 /* Transfer count */ #define DSPI_TCR_SPI_TCNT(x) (((x) & 0x0000FFFF) << 16) /* Status */ #define DSPI_SR_TXRXS 0x40000000 /* TX and RX Status [1] */ #define DSPI_SR_TXCTR(x) \ (((x) & 0x0000F000) >> 12) /* TX FIFO Counter [16-19] */ #define DSPI_SR_RXCTR(x) \ (((x) & 0x000000F0) >> 4) /* RX FIFO Counter [24-27] */ #define DSPI_DATA_8BIT SHIFT_U32(8, 0) #define DSPI_DATA_16BIT SHIFT_U32(0xF, 0) #define DSPI_TFR_CONT (0x80000000) #define DSPI_TFR_CTAS(x) (((x) & 0x07) << 12) #define DSPI_TFR_PCS(x) (((1 << (x)) & 0x0000003f) << 16) #define DSPI_IDLE_DATA 0x0 /* tx/rx data wait timeout value, unit: us */ #define DSPI_TXRX_WAIT_TIMEOUT 1000000 /* Transfer Fifo */ #define DSPI_TFR_TXDATA(x) (((x) & 0x0000FFFF)) /* Bit definitions and macros for DRFR */ #define DSPI_RFR_RXDATA(x) (((x) & 0x0000FFFF)) /* CTAR register pre-configure mask */ #define DSPI_CTAR_SET_MODE_MASK \ (DSPI_CTAR_FMSZ(15) | DSPI_CTAR_PCS_SCK(3) | DSPI_CTAR_PA_SCK(3) | \ DSPI_CTAR_P_DT(3) | DSPI_CTAR_CS_SCK(15) | DSPI_CTAR_A_SCK(15) | \ DSPI_CTAR_A_DT(15)) /* default SCK frequency, unit: HZ */ #define PLATFORM_CLK 650000000 #define DSPI_DEFAULT_SCK_FREQ 10000000 #define DSPI_CLK_DIV 4 /* prescaler divisor */ #define DSPI_CLK (PLATFORM_CLK / DSPI_CLK_DIV) /* DSPI clock */ #define CS_SPEED_MAX_HZ 1000000 /* Slave max speed */ /* * Calculate the divide scaler value between expected SCK frequency * and input clk frequency * req_pbr: pre-scaler value of baud rate for slave * req_br: scaler value of baud rate for slave * speed_hz: speed value of slave * clkrate: clock value of slave */ static TEE_Result dspi_convert_hz_to_baud(unsigned int *req_pbr, unsigned int *req_br, unsigned int speed_hz, unsigned int clkrate) { /* Valid pre-scaler values for baud rate*/ static const unsigned int pbr_val[4] = { 2, 3, 5, 7 }; /* Valid baud rate scaler values*/ static const unsigned int brs_val[16] = { 2, 4, 6, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 }; unsigned int tmp_val = 0; unsigned int curr_val = 0; unsigned int i = 0; unsigned int j = 0; tmp_val = clkrate / speed_hz; for (i = 0; i < ARRAY_SIZE(pbr_val); i++) { for (j = 0; j < ARRAY_SIZE(brs_val); j++) { curr_val = pbr_val[i] * brs_val[j]; if (curr_val >= tmp_val) { *req_pbr = i; *req_br = j; return TEE_SUCCESS; } } } EMSG("Can not find valid baud rate, speed_hz is %d, ", speed_hz); EMSG("clkrate is %d, using max prescaler value", clkrate); return TEE_ERROR_ITEM_NOT_FOUND; } /* * Configure speed of slave * dspi_data: DSPI controller chip instance * speed: speed of slave */ static void dspi_setup_speed(struct ls_dspi_data *dspi_data, unsigned int speed) { TEE_Result status = TEE_ERROR_GENERIC; unsigned int bus_setup = 0; unsigned int bus_clock = 0; unsigned int req_i = 0; unsigned int req_j = 0; bus_clock = dspi_data->bus_clk_hz; DMSG("DSPI set_speed: expected SCK speed %u, bus_clk %u", speed, bus_clock); bus_setup = io_read32(dspi_data->base + DSPI_CTAR0); bus_setup &= ~(DSPI_CTAR_BRD | DSPI_CTAR_BRP(0x3) | DSPI_CTAR_BR(0xf)); status = dspi_convert_hz_to_baud(&req_i, &req_j, speed, bus_clock); /* In case of failure scenario with max speed, setting default speed */ if (status == TEE_ERROR_ITEM_NOT_FOUND) { speed = dspi_data->speed_hz; status = dspi_convert_hz_to_baud(&req_i, &req_j, speed, bus_clock); } if (status == TEE_SUCCESS) { bus_setup |= (DSPI_CTAR_BRP(req_i) | DSPI_CTAR_BR(req_j)); io_write32(dspi_data->base + DSPI_CTAR0, bus_setup); dspi_data->speed_hz = speed; } else { EMSG("Unable to set speed"); } } /* * Transferred data to TX FIFO * dspi_data: DSPI controller chip instance */ static void dspi_tx(struct ls_dspi_data *dspi_data, uint32_t ctrl, uint16_t data) { int timeout = DSPI_TXRX_WAIT_TIMEOUT; uint32_t dspi_val_addr = dspi_data->base + DSPI_PUSHR; uint32_t dspi_val = ctrl | data; /* wait for empty entries in TXFIFO or timeout */ while (DSPI_SR_TXCTR(io_read32(dspi_data->base + DSPI_SR)) >= 4 && timeout--) udelay(1); if (timeout >= 0) io_write32(dspi_val_addr, dspi_val); else EMSG("waiting timeout!"); } /* * Read data from RX FIFO * dspi_data: DSPI controller chip instance */ static uint16_t dspi_rx(struct ls_dspi_data *dspi_data) { int timeout = DSPI_TXRX_WAIT_TIMEOUT; uint32_t dspi_val_addr = dspi_data->base + DSPI_POPR; /* wait for valid entries in RXFIFO or timeout */ while (DSPI_SR_RXCTR(io_read32(dspi_data->base + DSPI_SR)) == 0 && timeout--) udelay(1); if (timeout >= 0) return (uint16_t)DSPI_RFR_RXDATA(io_read32(dspi_val_addr)); EMSG("waiting timeout!"); return 0xFFFF; } /* * Transfer and Receive 8-bit data * chip: spi_chip instance * wdata: TX data queue * rdata: RX data queue * num_pkts: number of data packets */ static enum spi_result ls_dspi_txrx8(struct spi_chip *chip, uint8_t *wdata, uint8_t *rdata, size_t num_pkts) { uint8_t *spi_rd = NULL; uint8_t *spi_wr = NULL; uint32_t ctrl = 0; struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, chip); unsigned int cs = data->slave_cs; spi_wr = wdata; spi_rd = rdata; /* * Assert PCSn signals between transfers * select which CTAR register and slave to be used for TX * CTAS selects which CTAR to be used, here we are using CTAR0 * PCS (peripheral chip select) is selecting the slave. */ ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs); if (data->slave_mode & SPI_CONT) ctrl |= DSPI_TFR_CONT; if (data->slave_data_size_bits != 8) { EMSG("data_size_bits should be 8, not %u", data->slave_data_size_bits); return SPI_ERR_CFG; } while (num_pkts) { if (wdata && rdata) { dspi_tx(data, ctrl, *spi_wr++); *spi_rd++ = dspi_rx(data); } else if (wdata) { dspi_tx(data, ctrl, *spi_wr++); dspi_rx(data); } else if (rdata) { dspi_tx(data, ctrl, DSPI_IDLE_DATA); *spi_rd++ = dspi_rx(data); } num_pkts = num_pkts - 1; } return SPI_OK; } /* * Transfer and Receive 16-bit data * chip: spi_chip instance * wdata: TX data queue * rdata: RX data queue * num_pkts: number of data packets */ static enum spi_result ls_dspi_txrx16(struct spi_chip *chip, uint16_t *wdata, uint16_t *rdata, size_t num_pkts) { uint32_t ctrl = 0; uint16_t *spi_rd = NULL; uint16_t *spi_wr = NULL; struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, chip); unsigned int cs = data->slave_cs; spi_wr = wdata; spi_rd = rdata; /* * Assert PCSn signals between transfers * select which CTAR register and slave to be used for TX * CTAS selects which CTAR to be used, here we are using CTAR0 * PCS (peripheral chip select) is selecting the slave. */ ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs); if (data->slave_mode & SPI_CONT) ctrl |= DSPI_TFR_CONT; if (data->slave_data_size_bits != 16) { EMSG("data_size_bits should be 16, not %u", data->slave_data_size_bits); return SPI_ERR_CFG; } while (num_pkts) { if (wdata && rdata) { dspi_tx(data, ctrl, *spi_wr++); *spi_rd++ = dspi_rx(data); } else if (wdata) { dspi_tx(data, ctrl, *spi_wr++); dspi_rx(data); } else if (rdata) { dspi_tx(data, ctrl, DSPI_IDLE_DATA); *spi_rd++ = dspi_rx(data); } num_pkts = num_pkts - 1; } return SPI_OK; } /* * Statrt DSPI module * chip: spi_chip instance */ static void ls_dspi_start(struct spi_chip *chip) { struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, chip); DMSG("Start DSPI Module"); io_clrbits32(data->base + DSPI_MCR, DSPI_MCR_HALT); } /* * Stop DSPI module * chip: spi_chip instance */ static void ls_dspi_end(struct spi_chip *chip) { struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, chip); /* De-assert PCSn if in CONT mode */ if (data->slave_mode & SPI_CONT) { unsigned int cs = data->slave_cs; unsigned int ctrl = DSPI_TFR_CTAS(data->ctar_sel) | DSPI_TFR_PCS(cs); /* Dummy read to deassert */ dspi_tx(data, ctrl, DSPI_IDLE_DATA); dspi_rx(data); } DMSG("Stop DSPI Module"); io_setbits32(data->base + DSPI_MCR, DSPI_MCR_HALT); } /* * Clear RX and TX FIFO * dspi_data: DSPI controller chip instance */ static void dspi_flush_fifo(struct ls_dspi_data *dspi_data) { unsigned int mcr_val = 0; mcr_val = io_read32(dspi_data->base + DSPI_MCR); /* flush RX and TX FIFO */ mcr_val |= (DSPI_MCR_CTXF | DSPI_MCR_CRXF); io_write32(dspi_data->base + DSPI_MCR, mcr_val); } /* * Flush DSPI module * chip: spi_chip instance */ static void ls_dspi_flush(struct spi_chip *chip) { struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, chip); dspi_flush_fifo(data); } /* * Configure active state of slave * dspi_data: DSPI controller chip instance * cs: chip select value of slave * state: slave mode */ static void dspi_set_cs_active_state(struct ls_dspi_data *dspi_data, unsigned int cs, unsigned int state) { DMSG("Set CS active state cs=%d state=%d", cs, state); if (state & SPI_CS_HIGH) /* CSx inactive state is low */ io_clrbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs)); else /* CSx inactive state is high */ io_setbits32(dspi_data->base + DSPI_MCR, DSPI_MCR_PCSIS(cs)); } /* * Configure transfer state of slave * dspi_data: DSPI controller chip instance * state: slave mode */ static void dspi_set_transfer_state(struct ls_dspi_data *dspi_data, unsigned int state) { unsigned int bus_setup = 0; DMSG("Set transfer state=%d bits=%d", state, dspi_data->slave_data_size_bits); bus_setup = io_read32(dspi_data->base + DSPI_CTAR0); bus_setup &= ~DSPI_CTAR_SET_MODE_MASK; bus_setup |= dspi_data->ctar_val; bus_setup &= ~(DSPI_CTAR_CPOL | DSPI_CTAR_CPHA | DSPI_CTAR_LSBFE); if (state & SPI_CPOL) bus_setup |= DSPI_CTAR_CPOL; if (state & SPI_CPHA) bus_setup |= DSPI_CTAR_CPHA; if (state & SPI_LSB_FIRST) bus_setup |= DSPI_CTAR_LSBFE; if (dspi_data->slave_data_size_bits == 8) bus_setup |= DSPI_CTAR_FMSZ(7); else if (dspi_data->slave_data_size_bits == 16) bus_setup |= DSPI_CTAR_FMSZ(15); if (dspi_data->ctar_sel == 0) io_write32(dspi_data->base + DSPI_CTAR0, bus_setup); else io_write32(dspi_data->base + DSPI_CTAR1, bus_setup); } /* * Configure speed of slave * dspi_data: DSPI controller chip instance * speed_max_hz: maximum speed for slave */ static void dspi_set_speed(struct ls_dspi_data *dspi_data, unsigned int speed_max_hz) { dspi_setup_speed(dspi_data, speed_max_hz); } /* * Configure slave for DSPI controller * dspi_data: DSPI controller chip instance * cs: chip select value of slave * speed_max_hz: maximum speed of slave * state: slave mode */ static void dspi_config_slave_state(struct ls_dspi_data *dspi_data, unsigned int cs, unsigned int speed_max_hz, unsigned int state) { unsigned int sr_val = 0; /* configure speed */ dspi_set_speed(dspi_data, speed_max_hz); /* configure transfer state */ dspi_set_transfer_state(dspi_data, state); /* configure active state of CSX */ dspi_set_cs_active_state(dspi_data, cs, state); /* clear FIFO */ dspi_flush_fifo(dspi_data); /* check module TX and RX status */ sr_val = io_read32(dspi_data->base + DSPI_SR); if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS) EMSG("DSPI RX/TX not ready"); } /* * Configure master for DSPI controller * dspi_data: DSPI controller chip instance * mcr_val: value of master configuration register */ static void dspi_set_master_state(struct ls_dspi_data *dspi_data, unsigned int mcr_val) { DMSG("Set master state val=0x%x", mcr_val); io_write32(dspi_data->base + DSPI_MCR, mcr_val); } /* * Configure DSPI controller * chip: spi_chip instance */ static void ls_dspi_configure(struct spi_chip *chip) { struct ls_dspi_data *data = container_of(chip, struct ls_dspi_data, chip); unsigned int mcr_cfg_val = 0; mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK | DSPI_MCR_CRXF | DSPI_MCR_CTXF; /* Configure Master */ dspi_set_master_state(data, mcr_cfg_val); /* Configure DSPI slave */ dspi_config_slave_state(data, data->slave_cs, data->slave_speed_max_hz, data->slave_mode); } /* * Extract information for DSPI Controller from the DTB * dspi_data: DSPI controller chip instance */ static TEE_Result get_info_from_device_tree(struct ls_dspi_data *dspi_data) { const fdt32_t *bus_num = NULL; const fdt32_t *chip_select_num = NULL; size_t size = 0; int node = 0; vaddr_t ctrl_base = 0; void *fdt = NULL; /* * First get the DSPI Controller base address from the DTB * if DTB present and if the DSPI Controller defined in it. */ fdt = get_dt(); if (!fdt) { EMSG("Unable to get DTB, DSPI init failed"); return TEE_ERROR_ITEM_NOT_FOUND; } node = 0; while (node != -FDT_ERR_NOTFOUND) { node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-dspi"); if (!(fdt_get_status(fdt, node) & DT_STATUS_OK_SEC)) continue; bus_num = fdt_getprop(fdt, node, "bus-num", NULL); if (bus_num && dspi_data->slave_bus == (unsigned int)fdt32_to_cpu(*bus_num)) { if (dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO) < 0) { EMSG("Unable to get virtual address"); return TEE_ERROR_GENERIC; } break; } } dspi_data->base = ctrl_base; dspi_data->bus_clk_hz = DSPI_CLK; chip_select_num = fdt_getprop(fdt, node, "spi-num-chipselects", NULL); if (chip_select_num) dspi_data->num_chipselect = (int)fdt32_to_cpu(*chip_select_num); else return TEE_ERROR_ITEM_NOT_FOUND; dspi_data->speed_hz = DSPI_DEFAULT_SCK_FREQ; return TEE_SUCCESS; } static const struct spi_ops ls_dspi_ops = { .configure = ls_dspi_configure, .start = ls_dspi_start, .txrx8 = ls_dspi_txrx8, .txrx16 = ls_dspi_txrx16, .end = ls_dspi_end, .flushfifo = ls_dspi_flush, }; DECLARE_KEEP_PAGER(ls_dspi_ops); TEE_Result ls_dspi_init(struct ls_dspi_data *dspi_data) { TEE_Result status = TEE_ERROR_GENERIC; /* * First get the DSPI Controller base address from the DTB, * if DTB present and if the DSPI Controller defined in it. */ if (dspi_data) status = get_info_from_device_tree(dspi_data); if (status == TEE_SUCCESS) /* generic DSPI chip handle */ dspi_data->chip.ops = &ls_dspi_ops; else EMSG("Unable to get info from device tree"); return status; } optee_os-4.3.0/core/drivers/ls_gpio.c000066400000000000000000000143161464416617300175620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * Driver for GPIO Controller * */ #include #include #include #include #include #include #include static const char * const gpio_controller_map[] = { "/soc/gpio@2300000", "/soc/gpio@2310000", "/soc/gpio@2320000", "/soc/gpio@2330000" }; /* * Get value from GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin from which value needs to be read */ static enum gpio_level ls_gpio_get_value(struct gpio_chip *chip, unsigned int gpio_pin) { vaddr_t gpio_data_addr = 0; uint32_t data = 0; struct ls_gpio_chip_data *gc_data = container_of(chip, struct ls_gpio_chip_data, chip); assert(gpio_pin <= MAX_GPIO_PINS); gpio_data_addr = gc_data->gpio_base + GPIODAT; data = io_read32(gpio_data_addr); if (data & PIN_SHIFT(gpio_pin)) return GPIO_LEVEL_HIGH; else return GPIO_LEVEL_LOW; } /* * Set value for GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin to which value needs to be write * value: value needs to be written to the pin */ static void ls_gpio_set_value(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_level value) { vaddr_t gpio_data_addr = 0; struct ls_gpio_chip_data *gc_data = container_of(chip, struct ls_gpio_chip_data, chip); assert(gpio_pin <= MAX_GPIO_PINS); gpio_data_addr = gc_data->gpio_base + GPIODAT; if (value == GPIO_LEVEL_HIGH) /* if value is high then set pin value */ io_setbits32(gpio_data_addr, PIN_SHIFT(gpio_pin)); else /* if value is low then clear pin value */ io_clrbits32(gpio_data_addr, PIN_SHIFT(gpio_pin)); } /* * Get direction from GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin from which direction needs to be read */ static enum gpio_dir ls_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio_pin) { vaddr_t gpio_dir_addr = 0; uint32_t data = 0; struct ls_gpio_chip_data *gc_data = container_of(chip, struct ls_gpio_chip_data, chip); assert(gpio_pin <= MAX_GPIO_PINS); gpio_dir_addr = gc_data->gpio_base + GPIODIR; data = io_read32(gpio_dir_addr); if (data & PIN_SHIFT(gpio_pin)) return GPIO_DIR_OUT; else return GPIO_DIR_IN; } /* * Set direction for GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin on which direction needs to be set * direction: direction which needs to be set on pin */ static void ls_gpio_set_direction(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_dir direction) { vaddr_t gpio_dir_addr = 0; struct ls_gpio_chip_data *gc_data = container_of(chip, struct ls_gpio_chip_data, chip); assert(gpio_pin <= MAX_GPIO_PINS); gpio_dir_addr = gc_data->gpio_base + GPIODIR; if (direction == GPIO_DIR_OUT) io_setbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin)); else io_clrbits32(gpio_dir_addr, PIN_SHIFT(gpio_pin)); } /* * Get interrupt from GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin from which interrupt value needs to be read */ static enum gpio_interrupt gpio_get_interrupt(struct gpio_chip *chip, unsigned int gpio_pin) { vaddr_t gpio_ier_addr = 0; uint32_t data = 0; struct ls_gpio_chip_data *gc_data = container_of(chip, struct ls_gpio_chip_data, chip); assert(gpio_pin <= MAX_GPIO_PINS); gpio_ier_addr = gc_data->gpio_base + GPIOIER; data = io_read32(gpio_ier_addr); if (data & PIN_SHIFT(gpio_pin)) return GPIO_INTERRUPT_ENABLE; else return GPIO_INTERRUPT_DISABLE; } /* * Set interrupt event for GPIO controller * chip: pointer to GPIO controller chip instance * gpio_pin: pin on which interrupt value needs to be set * interrupt: interrupt valie which needs to be set on pin */ static void gpio_set_interrupt(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_interrupt interrupt) { vaddr_t gpio_ier_addr = 0; struct ls_gpio_chip_data *gc_data = container_of(chip, struct ls_gpio_chip_data, chip); assert(gpio_pin <= MAX_GPIO_PINS); gpio_ier_addr = gc_data->gpio_base + GPIOIER; if (interrupt == GPIO_INTERRUPT_ENABLE) io_setbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin)); else io_clrbits32(gpio_ier_addr, PIN_SHIFT(gpio_pin)); } /* * Extract information for GPIO Controller from the DTB * gpio_data: GPIO controller chip instance */ static TEE_Result get_info_from_device_tree(struct ls_gpio_chip_data *gpio_data) { size_t size = 0; int node = 0; vaddr_t ctrl_base = 0; void *fdt = NULL; /* * First get the GPIO Controller base address from the DTB * if DTB present and if the GPIO Controller defined in it. */ fdt = get_embedded_dt(); if (!fdt) { EMSG("Unable to get the Embedded DTB, GPIO init failed"); return TEE_ERROR_GENERIC; } node = fdt_path_offset(fdt, gpio_controller_map [gpio_data->gpio_controller]); if (node > 0) { if (dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO) < 0) { EMSG("Unable to get virtual address"); return TEE_ERROR_GENERIC; } } else { EMSG("Unable to get gpio offset node"); return TEE_ERROR_ITEM_NOT_FOUND; } gpio_data->gpio_base = ctrl_base; return TEE_SUCCESS; } static const struct gpio_ops ls_gpio_ops = { .get_direction = ls_gpio_get_direction, .set_direction = ls_gpio_set_direction, .get_value = ls_gpio_get_value, .set_value = ls_gpio_set_value, .get_interrupt = gpio_get_interrupt, .set_interrupt = gpio_set_interrupt, }; DECLARE_KEEP_PAGER(ls_gpio_ops); TEE_Result ls_gpio_init(struct ls_gpio_chip_data *gpio_data) { TEE_Result status = TEE_ERROR_GENERIC; /* * First get the GPIO Controller base address from the DTB, * if DTB present and if the GPIO Controller defined in it. */ status = get_info_from_device_tree(gpio_data); if (status == TEE_SUCCESS) { /* set GPIO Input Buffer Enable register */ io_setbits32(gpio_data->gpio_base + GPIOIBE, UINT32_MAX); /* generic GPIO chip handle */ gpio_data->chip.ops = &ls_gpio_ops; } else { EMSG("Unable to get info from device tree"); } return status; } optee_os-4.3.0/core/drivers/ls_i2c.c000066400000000000000000000276351464416617300173110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP * * I2C driver for I2C Controller * */ #include #include #include #include #include #include #include #include #include static const char * const i2c_controller_map[] = { "/soc/i2c@2000000", "/soc/i2c@2010000", "/soc/i2c@2020000", "/soc/i2c@2030000", "/soc/i2c@2040000", "/soc/i2c@2050000", "/soc/i2c@2060000", "/soc/i2c@2070000" }; /* * I2C divisor and ibfd register values when glitch filter is enabled * In case of duplicate SCL divisor value, the ibfd value with high MUL value * has been selected. A higher MUL value results in a lower sampling rate of * the I2C signals. This gives the I2C module greater immunity against glitches * in the I2C signals. */ static const struct i2c_clock_divisor_pair clk_div_glitch_enabled[] = { { 34, 0x0 }, { 36, 0x1 }, { 38, 0x2 }, { 40, 0x3 }, { 42, 0x4 }, { 44, 0x8 }, { 48, 0x9 }, { 52, 0xA }, { 54, 0x7 }, { 56, 0xB }, { 60, 0xC }, { 64, 0x10 }, { 68, 0x40 }, { 72, 0x41 }, { 76, 0x42 }, { 80, 0x43 }, { 84, 0x44 }, { 88, 0x48 }, { 96, 0x49 }, { 104, 0x4A }, { 108, 0x47 }, { 112, 0x4B }, { 120, 0x4C }, { 128, 0x50 }, { 136, 0x80 }, { 144, 0x81 }, { 152, 0x82 }, { 160, 0x83 }, { 168, 0x84 }, { 176, 0x88 }, { 192, 0x89 }, { 208, 0x8A }, { 216, 0x87 }, { 224, 0x8B }, { 240, 0x8C }, { 256, 0x90 }, { 288, 0x91 }, { 320, 0x92 }, { 336, 0x8F }, { 352, 0x93 }, { 384, 0x98 }, { 416, 0x95 }, { 448, 0x99 }, { 480, 0x96 }, { 512, 0x9A }, { 576, 0x9B }, { 640, 0xA0 }, { 704, 0x9D }, { 768, 0xA1 }, { 832, 0x9E }, { 896, 0xA2 }, { 960, 0x67 }, { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, { 2560, 0xB0 }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } }; /* * I2C divisor and ibfd register values when glitch filter is disabled. * In case of duplicate SCL divisor value, the ibfd value with high MUL value * has been selected. A higher MUL value results in a lower sampling rate of * the I2C signals. This gives the I2C module greater immunity against glitches * in the I2C signals. */ static const struct i2c_clock_divisor_pair clk_div_glitch_disabled[] = { { 20, 0x0 }, { 22, 0x1 }, { 24, 0x2 }, { 26, 0x3 }, { 28, 0x8 }, { 30, 0x5 }, { 32, 0x9 }, { 34, 0x6 }, { 36, 0x0A }, { 40, 0x40 }, { 44, 0x41 }, { 48, 0x42 }, { 52, 0x43 }, { 56, 0x48 }, { 60, 0x45 }, { 64, 0x49 }, { 68, 0x46 }, { 72, 0x4A }, { 80, 0x80 }, { 88, 0x81 }, { 96, 0x82 }, { 104, 0x83 }, { 112, 0x88 }, { 120, 0x85 }, { 128, 0x89 }, { 136, 0x86 }, { 144, 0x8A }, { 160, 0x8B }, { 176, 0x8C }, { 192, 0x90 }, { 208, 0x56 }, { 224, 0x91 }, { 240, 0x1F }, { 256, 0x92 }, { 272, 0x8F }, { 288, 0x93 }, { 320, 0x98 }, { 352, 0x95 }, { 384, 0x99 }, { 416, 0x96 }, { 448, 0x9A }, { 480, 0x5F }, { 512, 0x9B }, { 576, 0x9C }, { 640, 0xA0 }, { 768, 0xA1 }, { 896, 0xA2 }, { 960, 0x9F }, { 1024, 0xA3 }, { 1152, 0xA4 }, { 1280, 0xA8 }, { 1536, 0xA9 }, { 1792, 0xAA }, { 1920, 0xA7 }, { 2048, 0xAB }, { 2304, 0xAC }, { 2560, 0xAD }, { 3072, 0xB1 }, { 3584, 0xB2 }, { 3840, 0xAF }, { 4096, 0xB3 }, { 4608, 0xB4 }, { 5120, 0xB8 }, { 6144, 0xB9 }, { 7168, 0xBA }, { 7680, 0xB7 }, { 8192, 0xBB }, { 9216, 0xBC }, { 10240, 0xBD }, { 12288, 0xBE }, { 15360, 0xBF } }; void i2c_reset(vaddr_t base) { struct i2c_regs *regs = (struct i2c_regs *)base; io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_IBIE | I2C_IBCR_DMAEN); io_clrbits8((vaddr_t)®s->ibic, I2C_IBIC_BIIE); } /* * Get I2c Bus Frequency Divider Register value based on clock_divisor * and if the glitch is enabled or not in I2c controller. * base Base address of I2C controller * clock_divisor Clock Divisor */ static uint8_t i2c_get_ibfd(vaddr_t base, uint16_t clock_divisor) { struct i2c_regs *regs = (struct i2c_regs *)base; const struct i2c_clock_divisor_pair *dpair = NULL; size_t dpair_sz = 0; unsigned int n = 0; if (io_read8((vaddr_t)®s->ibdbg) & I2C_IBDBG_GLFLT_EN) { dpair = clk_div_glitch_enabled; dpair_sz = ARRAY_SIZE(clk_div_glitch_enabled); } else { dpair = clk_div_glitch_disabled; dpair_sz = ARRAY_SIZE(clk_div_glitch_disabled); } for (n = 0; n < dpair_sz - 1; n++) if (clock_divisor < dpair[n].divisor) break; return dpair[n].ibfd; } TEE_Result i2c_init(struct ls_i2c_data *i2c_data) { struct i2c_regs *regs = NULL; uint16_t clock_divisor = 0; uint8_t ibfd = 0; /* I2c Bus Frequency Divider Register */ size_t size = 0; int node = 0; vaddr_t ctrl_base = 0; void *fdt = NULL; /* * First get the I2C Controller base address from the DTB * if DTB present and if the I2C Controller defined in it. */ fdt = get_embedded_dt(); if (!fdt) { EMSG("Unable to get the Embedded DTB, I2C init failed"); return TEE_ERROR_GENERIC; } node = fdt_path_offset(fdt, i2c_controller_map[i2c_data->i2c_controller]); if (node > 0) { if (dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO) < 0) { EMSG("Unable to get virtual address"); return TEE_ERROR_GENERIC; } } else { EMSG("Unable to get I2C offset node"); return TEE_ERROR_ITEM_NOT_FOUND; } i2c_data->base = ctrl_base; regs = (struct i2c_regs *)ctrl_base; clock_divisor = (i2c_data->i2c_bus_clock + i2c_data->speed - 1) / i2c_data->speed; ibfd = i2c_get_ibfd(ctrl_base, clock_divisor); io_write8((vaddr_t)®s->ibfd, ibfd); i2c_reset(ctrl_base); return TEE_SUCCESS; } /* * Check if I2C bus is busy with previous transaction or not. * regs pointer to I2c controller registers * test_busy this flag tells if we need to check the busy bit in IBSR reg */ static TEE_Result i2c_bus_test_bus_busy(struct i2c_regs *regs, bool test_busy) { unsigned int n = 0; uint8_t reg = 0; for (n = 0; n < I2C_NUM_RETRIES; n++) { reg = io_read8((vaddr_t)®s->ibsr); if (reg & I2C_IBSR_IBAL) { io_write8((vaddr_t)®s->ibsr, reg); return TEE_ERROR_BUSY; } if (test_busy && (reg & I2C_IBSR_IBB)) break; if (!test_busy && !(reg & I2C_IBSR_IBB)) break; mdelay(1); } if (n == I2C_NUM_RETRIES) return TEE_ERROR_BUSY; return TEE_SUCCESS; } /* * Check if data transfer to/from i2c controller is complete. * regs pointer to I2c controller registers * test_rx_ack this flag tells if we need to check RXAK bit in IBSR reg */ static TEE_Result i2c_transfer_complete(struct i2c_regs *regs, bool test_rx_ack) { unsigned int n = 0; uint8_t reg = 0; for (n = 0; n < I2C_NUM_RETRIES; n++) { reg = io_read8((vaddr_t)®s->ibsr); if (reg & I2C_IBSR_IBIF) { /* Write 1 to clear the IBIF field */ io_write8((vaddr_t)®s->ibsr, reg); break; } mdelay(1); } if (n == I2C_NUM_RETRIES) return TEE_ERROR_BUSY; if (test_rx_ack && (reg & I2C_IBSR_RXAK)) return TEE_ERROR_NO_DATA; if (reg & I2C_IBSR_TCF) return TEE_SUCCESS; return TEE_ERROR_GENERIC; } /* * Read data from I2c controller. * regs pointer to I2c controller registers * slave_address slave address from which to read * operation pointer to i2c_operation struct * is_last_operation if current operation is last operation */ static TEE_Result i2c_read(struct i2c_regs *regs, unsigned int slave_address, struct i2c_operation *operation, bool is_last_operation) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int n = 0; /* Write Slave Address */ io_write8((vaddr_t)®s->ibdr, (slave_address << 0x1) | BIT(0)); res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); if (res) return res; /* select Receive mode. */ io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX); if (operation->length_in_bytes > 1) { /* Set No ACK = 0 */ io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); } /* Perform a dummy read to initiate the receive operation. */ io_read8((vaddr_t)®s->ibdr); for (n = 0; n < operation->length_in_bytes; n++) { res = i2c_transfer_complete(regs, I2C_BUS_NO_TEST_RX_ACK); if (res) return res; if (n == (operation->length_in_bytes - 2)) { /* Set No ACK = 1 */ io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_NOACK); } else if (n == (operation->length_in_bytes - 1)) { if (!is_last_operation) { /* select Transmit mode (for repeat start) */ io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX); } else { /* Generate Stop Signal */ io_clrbits8((vaddr_t)®s->ibcr, (I2C_IBCR_MSSL | I2C_IBCR_TXRX)); res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); if (res) return res; } } operation->buffer[n] = io_read8((vaddr_t)®s->ibdr); } return TEE_SUCCESS; } /* * Write data to I2c controller * regs pointer to I2c controller registers * slave_address slave address from which to read * operation pointer to i2c_operation struct */ static TEE_Result i2c_write(struct i2c_regs *regs, unsigned int slave_address, struct i2c_operation *operation) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int n = 0; /* Write Slave Address */ io_write8((vaddr_t)®s->ibdr, (slave_address << 0x1) & ~(BIT(0))); res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); if (res) return res; /* Write Data */ for (n = 0; n < operation->length_in_bytes; n++) { io_write8((vaddr_t)®s->ibdr, operation->buffer[n]); res = i2c_transfer_complete(regs, I2C_BUS_TEST_RX_ACK); if (res) return res; } return TEE_SUCCESS; } /* * Generate Stop Signal and disable I2C controller. * regs pointer to I2c controller registers */ static TEE_Result i2c_stop(struct i2c_regs *regs) { TEE_Result res = TEE_SUCCESS; uint8_t reg = 0; reg = io_read8((vaddr_t)®s->ibsr); if (reg & I2C_IBSR_IBB) { /* Generate Stop Signal */ io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_MSSL | I2C_IBCR_TXRX); res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); if (res) return res; } /* Disable I2c Controller */ io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); return TEE_SUCCESS; } /* * Generate Start Signal and set I2C controller in transmit mode. * regs pointer to I2c controller registers */ static TEE_Result i2c_start(struct i2c_regs *regs) { TEE_Result res = TEE_ERROR_GENERIC; io_setbits8((vaddr_t)®s->ibsr, I2C_IBSR_IBAL | I2C_IBSR_IBIF); io_clrbits8((vaddr_t)®s->ibcr, I2C_IBCR_MDIS); /* Wait controller to be stable */ mdelay(1); /* Generate Start Signal */ io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_MSSL); res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); if (res) return res; /* Select Transmit Mode. set No ACK = 1 */ io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_TXRX | I2C_IBCR_NOACK); return TEE_SUCCESS; } TEE_Result i2c_bus_xfer(vaddr_t base, unsigned int slave_address, struct i2c_operation *i2c_operation, unsigned int operation_count) { unsigned int n = 0; struct i2c_regs *regs = (struct i2c_regs *)base; struct i2c_operation *operation = NULL; TEE_Result res = TEE_ERROR_GENERIC; bool is_last_operation = false; res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_IDLE); if (res) goto out; res = i2c_start(regs); if (res) goto out; for (n = 0, operation = i2c_operation; n < operation_count; n++, operation++) { if (n == (operation_count - 1)) is_last_operation = true; /* Send repeat start after first transmit/receive */ if (n) { io_setbits8((vaddr_t)®s->ibcr, I2C_IBCR_RSTA); res = i2c_bus_test_bus_busy(regs, I2C_BUS_TEST_BUSY); if (res) goto out; } /* Read/write data */ if (operation->flags & I2C_FLAG_READ) res = i2c_read(regs, slave_address, operation, is_last_operation); else res = i2c_write(regs, slave_address, operation); if (res) goto out; } out: i2c_stop(regs); return res; } optee_os-4.3.0/core/drivers/ls_sec_mon.c000066400000000000000000000116551464416617300202520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microsoft * * Driver for the NXP LX2160A-series Security Monitor (SecMon). */ #include #include #include #include #include #include #include /** * struct ls_sec_mon_registers - Memory map of the SecMon registers. * hplr; HP Lock Register. * @hpcomr: HP Command Register. * @rsvd0: Reserved. * @hpsicr: HP Security Interrupt Control Register. * @hpsvcr: HP Security Violation Control Register. * @hpsr: HP Status Register. * @hpsvsr: HP Security Violation Status Register. * @hphacivr: HP High Assurance Counter IV Register. * @hphacr: HP High Assurance Counter Register. * @rsvd1[0x4]: Reserved. * @lplr: LP Lock Register. * @lpcr: LP Control Register. * @lpmkcr: LP Master Key Control Register. * @lpsvcr: LP Security Violation Control Register. * @rsvd2: Reserved. * @lptdcr: LP Tamper Detectors Configuration. * @lpsr: LP Status Register. * @rsvd3[0x3]: Reserved. * @lpsmcmr: LP Secure Monotonic Counter MSB Register. * @lpsmclr: LP Secure Monotonic Counter LSB Register. * @lppgdr: LP Power Glitch Detector Register. * @rsvd4: Reserved. * @lpzmkr[0x8]: LP Zeroizable Master Key Registers. * @lpgpr[0x4]: LP General Purpose Registers. * @rsvd5[0x2d2]: Reserved. * @hpvidr1: HP Version ID Register 1. * @hpvidr2: HP Version ID Register 2. */ static struct ls_sec_mon_registers { uint32_t hplr; /* 0x000 */ uint32_t hpcomr; /* 0x004 */ uint32_t rsvd0; /* 0x008 */ uint32_t hpsicr; /* 0x00C */ uint32_t hpsvcr; /* 0x010 */ uint32_t hpsr; /* 0x014 */ uint32_t hpsvsr; /* 0x018 */ uint32_t hphacivr; /* 0x01C */ uint32_t hphacr; /* 0x020 */ uint32_t rsvd1[0x4]; /* 0x024 */ uint32_t lplr; /* 0x034 */ uint32_t lpcr; /* 0x038 */ uint32_t lpmkcr; /* 0x03C */ uint32_t lpsvcr; /* 0x040 */ uint32_t rsvd2; /* 0x044 */ uint32_t lptdcr; /* 0x048 */ uint32_t lpsr; /* 0x04C */ uint32_t rsvd3[0x3]; /* 0x050 */ uint32_t lpsmcmr; /* 0x05C */ uint32_t lpsmclr; /* 0x060 */ uint32_t lppgdr; /* 0x064 */ uint32_t rsvd4; /* 0x068 */ uint32_t lpzmkr[0x8]; /* 0x06C */ uint32_t lpgpr[0x4]; /* 0x090 */ uint32_t rsvd5[0x2d2]; /* 0x0B0 */ uint32_t hpvidr1; /* 0xBF8 */ uint32_t hpvidr2; /* 0xBFC */ } *sec_mon_regs; /** * ls_sec_mon_init() - Initialize the SecMon driver and assign the sec_mon_regs * pointer to the SecMon base address detailed in the device * tree. * * Return: 0 if successful or > 0 on error. */ static TEE_Result ls_sec_mon_init(void) { void *fdt = NULL; size_t size = 0; uint32_t node = 0; vaddr_t ctrl_base = 0; fdt = get_embedded_dt(); if (!fdt) { EMSG("Unable to find the device tree"); return TEE_ERROR_ITEM_NOT_FOUND; } node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-sec-mon"); if (node <= 0) { EMSG("Unable to find the SecMon device tree node"); return TEE_ERROR_ITEM_NOT_FOUND; } if (dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO) < 0) { EMSG("Unable to get the SecMon virtual address"); return TEE_ERROR_GENERIC; } sec_mon_regs = (struct ls_sec_mon_registers *)ctrl_base; return TEE_SUCCESS; } TEE_Result ls_sec_mon_read(struct ls_sec_mon_data *data) { if (!sec_mon_regs) { EMSG("SecMon driver is not initialized"); return TEE_ERROR_GENERIC; } if (!data) { EMSG("Given buffer is uninitialized"); return TEE_ERROR_BAD_PARAMETERS; } data->hplr = io_read32((vaddr_t)&sec_mon_regs->hplr); data->hpcomr = io_read32((vaddr_t)&sec_mon_regs->hpcomr); data->hpsicr = io_read32((vaddr_t)&sec_mon_regs->hpsicr); data->hpsvcr = io_read32((vaddr_t)&sec_mon_regs->hpsvcr); data->hpsr = io_read32((vaddr_t)&sec_mon_regs->hpsr); data->hpsvsr = io_read32((vaddr_t)&sec_mon_regs->hpsvsr); data->hphacivr = io_read32((vaddr_t)&sec_mon_regs->hphacivr); data->hphacr = io_read32((vaddr_t)&sec_mon_regs->hphacr); data->lplr = io_read32((vaddr_t)&sec_mon_regs->lplr); data->lpcr = io_read32((vaddr_t)&sec_mon_regs->lpcr); data->lpmkcr = io_read32((vaddr_t)&sec_mon_regs->lpmkcr); data->lpsvcr = io_read32((vaddr_t)&sec_mon_regs->lpsvcr); data->lptdcr = io_read32((vaddr_t)&sec_mon_regs->lptdcr); data->lpsr = io_read32((vaddr_t)&sec_mon_regs->lpsr); data->lpsmcmr = io_read32((vaddr_t)&sec_mon_regs->lpsmcmr); data->lpsmclr = io_read32((vaddr_t)&sec_mon_regs->lpsmclr); data->lppgdr = io_read32((vaddr_t)&sec_mon_regs->lppgdr); data->hpvidr1 = io_read32((vaddr_t)&sec_mon_regs->hpvidr1); data->hpvidr2 = io_read32((vaddr_t)&sec_mon_regs->hpvidr2); for (uint32_t i = 0; i < ARRAY_SIZE(data->lpzmkr); ++i) data->lpzmkr[i] = io_read32((vaddr_t)&sec_mon_regs->lpzmkr[i]); for (uint32_t i = 0; i < ARRAY_SIZE(data->lpgpr); ++i) data->lpgpr[i] = io_read32((vaddr_t)&sec_mon_regs->lpgpr[i]); return TEE_SUCCESS; } TEE_Result ls_sec_mon_status(void) { if (!sec_mon_regs) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } driver_init(ls_sec_mon_init); optee_os-4.3.0/core/drivers/ls_sfp.c000066400000000000000000000243551464416617300174200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microsoft * * Driver for the NXP LX2160A-series Security Fuse Processor (SFP). */ #include #include #include #include #include #include #include #include #include #include #include /** * struct ls_sfp_registers - Memory map of the SFP registers. * @rsvd0[0x8]: Reserved. * @ingr: Instruction Register. * @svhesr: Secret Value Hamming Error Status Registers. * @sfpcr: SFP Configuration Register. * @rsvd1[0x3]: Reserved. * @version: SFP Version Register. * @rsvd2[0x71]: Reserved. * @ospr0: OEM Security Policy Register 0. * @ospr1: OEM Security Policy Register 1. * @dcvr0: Debug Challenge Value Register 0. * @dcvr1: Debug Challenge Value Register 1. * @drvr0: Debug Response Value Register 0. * @drvr1: Debug Response Value Register 1 * @fswpr: Factory Section Write Protect Register. * @fuidr0: Factory Unique ID Register 0. * @fuidr1: Factory Unique ID Register 1. * @isbccr: ISBC Configuration Register. * @fspfr[0x3]: Factory Scratch Pad Fuse Registers. * @otpmkr[0x8]: One Time Programmable Master Key. * @srkhr[0x8]: Super Root Key Hash. * @ouidr[0x5]: OEM Unique ID Scratch Pad Fuse Registers. */ static struct ls_sfp_registers { uint32_t rsvd0[0x8]; /* 0x000 */ uint32_t ingr; /* 0x020 */ uint32_t svhesr; /* 0x024 */ uint32_t sfpcr; /* 0x028 */ uint32_t rsvd1[0x3]; /* 0x02C */ uint32_t version; /* 0x038 */ uint32_t rsvd2[0x71]; /* 0x03C */ uint32_t ospr0; /* 0x200 */ uint32_t ospr1; /* 0x204 */ uint32_t dcvr0; /* 0x208 */ uint32_t dcvr1; /* 0x20C */ uint32_t drvr0; /* 0x210 */ uint32_t drvr1; /* 0x214 */ uint32_t fswpr; /* 0x218 */ uint32_t fuidr0; /* 0x21C */ uint32_t fuidr1; /* 0x220 */ uint32_t isbccr; /* 0x224 */ uint32_t fspfr[0x3]; /* 0x228 */ uint32_t otpmkr[0x8]; /* 0x234 */ uint32_t srkhr[0x8]; /* 0x254 */ uint32_t ouidr[0x5]; /* 0x274 */ } *sfp_regs; /** * struct ls_gpio_info - Data struct containing GPIO specific information. * @gpio_pin: GPIO pin number. * @gpio_chip: GPIO controller instance data. */ static struct ls_gpio_info { uint32_t gpio_pin; struct ls_gpio_chip_data gpio_chip; } gpio_info; /** * ls_sfp_init() - Get SFP info from the embedded device tree and initialize * sfp_regs and gpio_info. * * Return: TEE_SUCCESS or > 0 on error. */ static TEE_Result ls_sfp_init(void) { size_t size = 0; int node = 0; int rc = 0; int povdd_node = 0; int prop_len = 0; vaddr_t ctrl_base = 0; struct ls_gpio_chip_data *gc = NULL; const char *fdt_prop_gpio = "povdd-gpio-controller"; const char *fdt_prop_pin = "povdd-gpio-pin"; const fdt32_t *gpio_val = NULL; const fdt32_t *pin_val = NULL; void *fdt = get_embedded_dt(); if (!fdt) { EMSG("Unable to get the Embedded DTB, SFP init failed"); return TEE_ERROR_GENERIC; } node = fdt_node_offset_by_compatible(fdt, node, "fsl,lx2160a-sfp"); if (node <= 0) { EMSG("Unable to find SFP FDT node - rc = 0x%#"PRIx32, rc); return TEE_ERROR_ITEM_NOT_FOUND; } rc = dt_map_dev(fdt, node, &ctrl_base, &size, DT_MAP_AUTO); if (rc < 0) { EMSG("Unable to get SFP virtual address - rc = 0x%#"PRIx32, rc); return TEE_ERROR_GENERIC; } povdd_node = fdt_path_offset(fdt, "/povdd"); if (povdd_node <= 0) { EMSG("Unable to find POVDD FDT node - rc = 0x%#"PRIx32, povdd_node); return TEE_ERROR_ITEM_NOT_FOUND; } sfp_regs = (struct ls_sfp_registers *)ctrl_base; gpio_val = fdt_getprop(fdt, povdd_node, fdt_prop_gpio, &prop_len); if (!gpio_val) { EMSG("Missing %s from POVDD FDT node", fdt_prop_gpio); return TEE_ERROR_ITEM_NOT_FOUND; } pin_val = fdt_getprop(fdt, povdd_node, fdt_prop_pin, &prop_len); if (!pin_val) { EMSG("Missing %s from POVDD FDT node", fdt_prop_pin); return TEE_ERROR_ITEM_NOT_FOUND; } gc = &gpio_info.gpio_chip; gc->gpio_controller = (uint8_t)fdt32_to_cpu(*gpio_val); gpio_info.gpio_pin = fdt32_to_cpu(*pin_val); return ls_gpio_init(gc); } /** * ls_sfp_program_fuses() - Write to fuses and verify that the correct value was * written. * * Return: TEE_SUCCESS or > 0 on error. */ static TEE_Result ls_sfp_program_fuses(void) { TEE_Result ret = TEE_SUCCESS; struct gpio_chip *gc = NULL; uint32_t pin = gpio_info.gpio_pin; vaddr_t sfp_ingr_va = (vaddr_t)&sfp_regs->ingr; uint64_t timeout = 0; /* Enable POVDD */ gc = &gpio_info.gpio_chip.chip; DMSG("Set GPIO %"PRIu32" pin %"PRIu32" to HIGH", (uint32_t)gpio_info.gpio_chip.gpio_controller, pin); gc->ops->set_direction(gc, pin, GPIO_DIR_OUT); gc->ops->set_value(gc, pin, GPIO_LEVEL_HIGH); if (gc->ops->get_value(gc, pin) != GPIO_LEVEL_HIGH) { EMSG("Error setting POVDD to HIGH"); return TEE_ERROR_GENERIC; } /* TA_PROG_SFP ramp rate requires up to 5ms for stability */ mdelay(5); /* Send SFP write command */ io_write32(sfp_ingr_va, SFP_INGR_PROGFB_CMD); /* Wait until fuse programming is successful */ timeout = timeout_init_us(SFP_INGR_FUSE_TIMEOUT_US); while (io_read32(sfp_ingr_va) & SFP_INGR_PROGFB_CMD) { if (timeout_elapsed(timeout)) { EMSG("SFP fusing timed out"); ret = TEE_ERROR_GENERIC; break; } } /* Disable POVDD */ DMSG("Set GPIO %"PRIu8" pin %"PRIu32" to LOW", gpio_info.gpio_chip.gpio_controller, pin); gc->ops->set_value(gc, pin, GPIO_LEVEL_LOW); gc->ops->set_direction(gc, pin, GPIO_DIR_IN); if (ret) return ret; /* Check for SFP fuse programming error */ if (io_read32(sfp_ingr_va) & SFP_INGR_ERROR_MASK) { EMSG("Error writing SFP fuses"); return TEE_ERROR_GENERIC; } DMSG("Programmed fuse successfully"); return TEE_SUCCESS; } TEE_Result ls_sfp_read(struct ls_sfp_data *data) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!data) return TEE_ERROR_BAD_PARAMETERS; data->ingr = io_read32((vaddr_t)&sfp_regs->ingr); data->svhesr = io_read32((vaddr_t)&sfp_regs->svhesr); data->sfpcr = io_read32((vaddr_t)&sfp_regs->sfpcr); data->version = io_read32((vaddr_t)&sfp_regs->version); data->ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); data->ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); data->dcvr0 = io_read32((vaddr_t)&sfp_regs->dcvr0); data->dcvr1 = io_read32((vaddr_t)&sfp_regs->dcvr1); data->drvr0 = io_read32((vaddr_t)&sfp_regs->drvr0); data->drvr1 = io_read32((vaddr_t)&sfp_regs->drvr1); data->fswpr = io_read32((vaddr_t)&sfp_regs->fswpr); data->fuidr0 = io_read32((vaddr_t)&sfp_regs->fuidr0); data->fuidr1 = io_read32((vaddr_t)&sfp_regs->fuidr1); data->isbccr = io_read32((vaddr_t)&sfp_regs->isbccr); for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->fspfr); ++i) data->fspfr[i] = io_read32((vaddr_t)&sfp_regs->fspfr[i]); for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->otpmkr); ++i) data->otpmkr[i] = io_read32((vaddr_t)&sfp_regs->otpmkr[i]); for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->srkhr); ++i) data->srkhr[i] = io_read32((vaddr_t)&sfp_regs->srkhr[i]); for (uint32_t i = 0; i < ARRAY_SIZE(sfp_regs->ouidr); ++i) data->ouidr[i] = io_read32((vaddr_t)&sfp_regs->ouidr[i]); return TEE_SUCCESS; } TEE_Result ls_sfp_get_debug_level(uint32_t *dblev) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!dblev) return TEE_ERROR_BAD_PARAMETERS; *dblev = io_read32((vaddr_t)&sfp_regs->ospr1) & SFP_OSPR1_DBLEV_MASK; return TEE_SUCCESS; } TEE_Result ls_sfp_get_its(uint32_t *its) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!its) return TEE_ERROR_BAD_PARAMETERS; *its = (io_read32((vaddr_t)&sfp_regs->ospr0) & SFP_OSPR0_ITS_MASK) >> SFP_OSPR0_ITS_OFFSET; return TEE_SUCCESS; } TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!ouid) return TEE_ERROR_BAD_PARAMETERS; if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { DMSG("Index greater or equal to ouid: %"PRIu32" >= %zu", index, ARRAY_SIZE(sfp_regs->ouidr)); return TEE_ERROR_BAD_PARAMETERS; } *ouid = io_read32((vaddr_t)&sfp_regs->ouidr[index]); return TEE_SUCCESS; } TEE_Result ls_sfp_get_sb(uint32_t *sb) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!sb) return TEE_ERROR_BAD_PARAMETERS; *sb = (io_read32((vaddr_t)&sfp_regs->sfpcr) & SFP_SFPCR_SB_MASK) >> SFP_SFPCR_SB_OFFSET; return TEE_SUCCESS; } TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!srkh) return TEE_ERROR_BAD_PARAMETERS; if (index >= ARRAY_SIZE(sfp_regs->srkhr)) { DMSG("Index greater or equal to srkhr: %"PRIu32" >= %zu", index, ARRAY_SIZE(sfp_regs->srkhr)); return TEE_ERROR_BAD_PARAMETERS; } *srkh = io_read32((vaddr_t)&sfp_regs->srkhr[index]); return TEE_SUCCESS; } TEE_Result ls_sfp_set_debug_level(uint32_t dblev) { uint32_t ospr1 = 0; if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (!dblev) return TEE_SUCCESS; ospr1 = io_read32((vaddr_t)&sfp_regs->ospr1); if (ospr1 & SFP_OSPR1_DBLEV_MASK) { DMSG("Debug level has already been fused"); return TEE_ERROR_SECURITY; } io_write32((vaddr_t)&sfp_regs->ospr1, ospr1 | dblev); return ls_sfp_program_fuses(); } TEE_Result ls_sfp_set_its_wp(void) { uint32_t ospr0 = 0; if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } ospr0 = io_read32((vaddr_t)&sfp_regs->ospr0); if (ospr0 & (SFP_OSPR0_WP_MASK | SFP_OSPR0_ITS_MASK)) { DMSG("SFP is already fused"); return TEE_ERROR_SECURITY; } ospr0 |= SFP_OSPR0_WP_MASK | SFP_OSPR0_ITS_MASK; io_write32((vaddr_t)&sfp_regs->ospr0, ospr0); return ls_sfp_program_fuses(); } TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid) { if (!sfp_regs) { EMSG("SFP driver not initialized"); return TEE_ERROR_GENERIC; } if (index >= ARRAY_SIZE(sfp_regs->ouidr)) { DMSG("Index greater or equal to ouid: %"PRIu32" >= %"PRIu32, index, ARRAY_SIZE(sfp_regs->ouidr)); return TEE_ERROR_BAD_PARAMETERS; } io_write32((vaddr_t)&sfp_regs->ouidr[index], ouid); return ls_sfp_program_fuses(); } TEE_Result ls_sfp_status(void) { if (!sfp_regs) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } driver_init(ls_sfp_init); optee_os-4.3.0/core/drivers/mvebu_uart.c000066400000000000000000000103211464416617300202670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017 Marvell International Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include /* MVEBU UART Registers */ #define UART_RX_REG 0x00 #define UART_TX_REG 0x04 #define UART_CTRL_REG 0x08 #define UART_STATUS_REG 0x0c #define UART_BAUD_REG 0x10 #define UART_POSSR_REG 0x14 #define UART_SIZE 0x18 /* Line Status Register bits */ #define UARTLSR_TXFIFOFULL (1 << 11) /* Tx Fifo Full */ #define UARTLSR_TXFIFOEMPTY (1 << 13) #define UARTLSR_TXEMPTY (1 << 6) #define UART_RX_READY (1 << 4) /* UART Control Register bits */ #define UART_CTRL_RXFIFO_RESET (1 << 14) #define UART_CTRL_TXFIFO_RESET (1 << 15) static vaddr_t chip_to_base(struct serial_chip *chip) { struct mvebu_uart_data *pd = container_of(chip, struct mvebu_uart_data, chip); return io_pa_or_va(&pd->base, UART_SIZE); } static void mvebu_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); /* * Wait for the transmit FIFO to be empty. * It can happen that Linux initializes the OP-TEE driver with the * console UART disabled; avoid an infinite loop by checking the UART * enabled flag. Checking it in the loop makes the code safe against * asynchronous disable. */ while (!(io_read32(base + UART_STATUS_REG) & UARTLSR_TXFIFOEMPTY)) ; } static bool mvebu_uart_have_rx_data(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); return (io_read32(base + UART_STATUS_REG) & UART_RX_READY); } static int mvebu_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!mvebu_uart_have_rx_data(chip)) ; return io_read32(base + UART_RX_REG) & 0xff; } static void mvebu_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); uint32_t tmp; /* wait for space in tx FIFO */ do { tmp = io_read32(base + UART_STATUS_REG); tmp &= UARTLSR_TXFIFOFULL; } while (tmp == UARTLSR_TXFIFOFULL); io_write32(base + UART_TX_REG, ch); } static const struct serial_ops mvebu_uart_ops = { .flush = mvebu_uart_flush, .getchar = mvebu_uart_getchar, .have_rx_data = mvebu_uart_have_rx_data, .putc = mvebu_uart_putc, }; DECLARE_KEEP_PAGER(mvebu_uart_ops); void mvebu_uart_init(struct mvebu_uart_data *pd, paddr_t pbase, uint32_t uart_clk, uint32_t baud_rate) { vaddr_t base; uint32_t dll = 0; pd->base.pa = pbase; pd->chip.ops = &mvebu_uart_ops; base = io_pa_or_va(&pd->base, UART_SIZE); dll = (uart_clk / (baud_rate << 4)) & 0x3FF; /* init UART */ io_clrsetbits32(base + UART_BAUD_REG, 0x3FF, dll); /* set UART to default 16x scheme */ io_write32(base + UART_POSSR_REG, 0); /* reset FIFO */ io_write32(base + UART_CTRL_REG, UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET); /* No Parity, 1 stop */ io_write32(base + UART_CTRL_REG, 0); mvebu_uart_flush(&pd->chip); } optee_os-4.3.0/core/drivers/ns16550.c000066400000000000000000000072161464416617300171500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2017, 2020, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include /* uart register defines */ #define UART_RBR 0x0 #define UART_THR 0x0 #define UART_IER 0x1 #define UART_FCR 0x2 #define UART_LCR 0x3 #define UART_MCR 0x4 #define UART_LSR 0x5 #define UART_MSR 0x6 #define UART_SPR 0x7 /* uart status register bits */ #define UART_LSR_DR 0x01 /* DATA Ready */ #define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ static vaddr_t chip_to_base_and_data(struct serial_chip *chip, struct ns16550_data **pd) { *pd = container_of(chip, struct ns16550_data, chip); return io_pa_or_va(&(*pd)->base, NS16550_UART_REG_SIZE); } static void ns16550_flush(struct serial_chip *chip) { struct ns16550_data *pd = NULL; vaddr_t base = chip_to_base_and_data(chip, &pd); while ((serial_in(base + (UART_LSR << pd->reg_shift), pd->io_width) & UART_LSR_THRE) == 0) ; } static void ns16550_putc(struct serial_chip *chip, int ch) { struct ns16550_data *pd = NULL; vaddr_t base = chip_to_base_and_data(chip, &pd); ns16550_flush(chip); /* write out charset to Transmit-hold-register */ serial_out(base + (UART_THR << pd->reg_shift), pd->io_width, ch); } static bool ns16550_have_rx_data(struct serial_chip *chip) { struct ns16550_data *pd = NULL; vaddr_t base = chip_to_base_and_data(chip, &pd); return serial_in(base + (UART_LSR << pd->reg_shift), pd->io_width) & UART_LSR_DR; } static int ns16550_getchar(struct serial_chip *chip) { struct ns16550_data *pd = NULL; vaddr_t base = chip_to_base_and_data(chip, &pd); while (!ns16550_have_rx_data(chip)) { /* Data is not ready, waiting again */ ; } return serial_in(base + (UART_RBR << pd->reg_shift), pd->io_width) & 0xFF; } static const struct serial_ops ns16550_ops = { .flush = ns16550_flush, .putc = ns16550_putc, .getchar = ns16550_getchar, .have_rx_data = ns16550_have_rx_data, }; DECLARE_KEEP_PAGER(ns16550_ops); void ns16550_init(struct ns16550_data *pd, paddr_t base, uint8_t io_width, uint8_t reg_shift) { pd->base.pa = base; pd->io_width = io_width; pd->reg_shift = reg_shift; pd->chip.ops = &ns16550_ops; /* * Do nothing, uart driver shared with normal world, * everything for uart driver initialization is done in bootloader. */ } optee_os-4.3.0/core/drivers/nvmem/000077500000000000000000000000001464416617300170775ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/nvmem/atmel_sfc.c000066400000000000000000000054471464416617300212120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #include #define ATMEL_SFC_KR 0x0 #define ATMEL_SFC_SR 0x1C #define ATMEL_SFC_SR_PGMC BIT(0) #define ATMEL_SFC_SR_PGMF BIT(1) #define ATMEL_SFC_DR 0x20 #define ATMEL_SFC_CELLS_32 17 #define ATMEL_SFC_CELLS_8 (ATMEL_SFC_CELLS_32 * sizeof(uint32_t)) struct atmel_sfc { vaddr_t base; uint8_t fuses[ATMEL_SFC_CELLS_8]; }; static TEE_Result atmel_sfc_read_cell(struct nvmem_cell *cell, uint8_t *data) { struct atmel_sfc *atmel_sfc = cell->drv_data; memcpy(data, &atmel_sfc->fuses[cell->offset], cell->len); return TEE_SUCCESS; } static void atmel_sfc_put_cell(struct nvmem_cell *cell) { free(cell); } static const struct nvmem_ops atmel_sfc_nvmem_ops = { .read_cell = atmel_sfc_read_cell, .put_cell = atmel_sfc_put_cell, }; static TEE_Result atmel_sfc_dt_get(struct dt_pargs *args, void *data, struct nvmem_cell **out_cell) { TEE_Result res = TEE_ERROR_GENERIC; struct nvmem_cell *cell = NULL; /* Freed from atmel_sfc_put_cell() */ cell = calloc(1, sizeof(*cell)); if (!cell) return TEE_ERROR_OUT_OF_MEMORY; res = nvmem_cell_parse_dt(args->fdt, args->phandle_node, cell); if (res) goto out_free; if (cell->offset + cell->len > ATMEL_SFC_CELLS_8) { res = TEE_ERROR_GENERIC; goto out_free; } cell->ops = &atmel_sfc_nvmem_ops; cell->drv_data = data; *out_cell = cell; return TEE_SUCCESS; out_free: free(cell); return res; } static void atmel_sfc_read_fuse(struct atmel_sfc *atmel_sfc) { size_t i = 0; uint32_t val = 0; for (i = 0; i < ATMEL_SFC_CELLS_32; i++) { val = io_read32(atmel_sfc->base + ATMEL_SFC_DR + i * 4); memcpy(&atmel_sfc->fuses[i * 4], &val, sizeof(val)); } } static TEE_Result atmel_sfc_probe(const void *fdt, int node, const void *compat_data __unused) { vaddr_t base = 0; size_t size = 0; struct atmel_sfc *atmel_sfc = NULL; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_NODE_DISABLED; matrix_configure_periph_secure(AT91C_ID_SFC); if (dt_map_dev(fdt, node, &base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; atmel_sfc = calloc(1, sizeof(*atmel_sfc)); if (!atmel_sfc) return TEE_ERROR_OUT_OF_MEMORY; atmel_sfc->base = base; atmel_sfc_read_fuse(atmel_sfc); return nvmem_register_provider(fdt, node, atmel_sfc_dt_get, atmel_sfc); } static const struct dt_device_match atmel_sfc_match_table[] = { { .compatible = "atmel,sama5d2-sfc" }, { } }; DEFINE_DT_DRIVER(atmel_sfc_dt_driver) = { .name = "atmel_sfc", .type = DT_DRIVER_NVMEM, .match_table = atmel_sfc_match_table, .probe = atmel_sfc_probe, }; optee_os-4.3.0/core/drivers/nvmem/nvmem.c000066400000000000000000000032121464416617300203630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Microchip */ #include #include #include TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset, struct nvmem_cell *cell) { size_t buf_len = 0; paddr_t offset = 0; buf_len = fdt_reg_size(fdt, nodeoffset); if (buf_len == DT_INFO_INVALID_REG_SIZE) return TEE_ERROR_GENERIC; offset = fdt_reg_base_address(fdt, nodeoffset); if (offset == DT_INFO_INVALID_REG) return TEE_ERROR_GENERIC; cell->len = buf_len; cell->offset = offset; return TEE_SUCCESS; } TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset, const char *name, struct nvmem_cell **cell) { int index = 0; index = fdt_stringlist_search(fdt, nodeoffset, "nvmem-cell-names", name); if (index < 0) return TEE_ERROR_ITEM_NOT_FOUND; return nvmem_get_cell_by_index(fdt, nodeoffset, index, cell); } TEE_Result nvmem_get_cell_by_index(const void *fdt, int nodeoffset, unsigned int index, struct nvmem_cell **out_cell) { TEE_Result res = TEE_ERROR_GENERIC; void *cell = NULL; res = dt_driver_device_from_node_idx_prop("nvmem-cells", fdt, nodeoffset, index, DT_DRIVER_NVMEM, &cell); if (!res) *out_cell = cell; return res; } TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell, uint8_t **out_data) { TEE_Result res = TEE_ERROR_GENERIC; if (!cell->ops->read_cell) return TEE_ERROR_NOT_SUPPORTED; *out_data = malloc(cell->len); if (!out_data) return TEE_ERROR_OUT_OF_MEMORY; res = cell->ops->read_cell(cell, *out_data); if (res) free(*out_data); return res; } optee_os-4.3.0/core/drivers/nvmem/nvmem_die_id.c000066400000000000000000000024111464416617300216600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Microchip */ #include #include #include #include #include #include #include #include #include static uint8_t *die_id; static size_t die_id_len; int tee_otp_get_die_id(uint8_t *buffer, size_t len) { if (!die_id) { if (huk_subkey_derive(HUK_SUBKEY_DIE_ID, NULL, 0, buffer, len)) return -1; return 0; } memcpy(buffer, die_id, MIN(die_id_len, len)); return 0; } static TEE_Result nvmem_die_id_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct nvmem_cell *cell = NULL; uint8_t *data = NULL; res = nvmem_get_cell_by_name(fdt, node, "die_id", &cell); if (res) return res; res = nvmem_cell_malloc_and_read(cell, &data); if (!res) die_id = data; nvmem_put_cell(cell); return res; } static const struct dt_device_match nvmem_die_id_match_table[] = { { .compatible = "optee,nvmem-die-id" }, { } }; DEFINE_DT_DRIVER(nvmem_die_id_dt_driver) = { .name = "nvmem_die_id_key", .type = DT_DRIVER_NVMEM, .match_table = nvmem_die_id_match_table, .probe = nvmem_die_id_probe, }; optee_os-4.3.0/core/drivers/nvmem/nvmem_huk.c000066400000000000000000000024711464416617300212400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Microchip */ #include #include #include #include #include #include #include #include #include static struct nvmem_cell *huk_cell; TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *huk = NULL; size_t len = 0; res = nvmem_cell_malloc_and_read(huk_cell, &huk); if (res) goto out_free_cell; if (len != HW_UNIQUE_KEY_LENGTH) { res = TEE_ERROR_GENERIC; goto out_free_cell; } memcpy(hwkey->data, huk, HW_UNIQUE_KEY_LENGTH); out_free_cell: nvmem_put_cell(huk_cell); return res; } static TEE_Result nvmem_huk_get_cell(const void *fdt, int node) { return nvmem_get_cell_by_name(fdt, node, "hw_unique_key", &huk_cell); } static TEE_Result nvmem_huk_probe(const void *fdt, int node, const void *compat_data __unused) { return nvmem_huk_get_cell(fdt, node); } static const struct dt_device_match nvmem_huk_match_table[] = { { .compatible = "optee,nvmem-huk" }, { } }; DEFINE_DT_DRIVER(nvmem_huk_dt_driver) = { .name = "nvmem_huk", .type = DT_DRIVER_NVMEM, .match_table = nvmem_huk_match_table, .probe = nvmem_huk_probe, }; optee_os-4.3.0/core/drivers/nvmem/sub.mk000066400000000000000000000002071464416617300202200ustar00rootroot00000000000000srcs-y += nvmem.c srcs-$(CFG_ATMEL_SFC) += atmel_sfc.c srcs-$(CFG_NVMEM_DIE_ID) += nvmem_die_id.c srcs-$(CFG_NVMEM_HUK) += nvmem_huk.c optee_os-4.3.0/core/drivers/pinctrl/000077500000000000000000000000001464416617300174305ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/pinctrl/atmel_pio.c000066400000000000000000000130511464416617300215450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Microchip. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PIO_GROUP_COUNT 4 #define PIO_GROUP_OFFSET 0x40 #define PIO_REG(reg, group) ((reg) + ((group) * PIO_GROUP_OFFSET)) /* Mask register */ #define PIO_MSKR(group) PIO_REG(0x0, (group)) /* Configuration register */ #define PIO_CFGR(group) PIO_REG(0x4, (group)) #define PIO_CFGR_FUNC GENMASK(2, 0) #define PIO_CFGR_PUEN BIT(9) #define PIO_CFGR_PDEN BIT(10) /* Non-Secure configuration register */ #define PIO_SIONR(group) PIO_REG(0x30, (group)) /* Secure configuration register */ #define PIO_SIOSR(group) PIO_REG(0x34, (group)) #define DT_GET_PIN_NO(val) ((val) & 0xFF) #define DT_GET_FUNC(val) (((val) >> 16) & 0xF) struct atmel_pio { vaddr_t base; }; struct atmel_pio_pin_conf { uint32_t pin_mask; uint32_t pin_cfg; uint8_t pio_group; struct atmel_pio *pio; }; static void pio_write(struct atmel_pio *pio, unsigned int offset, uint32_t val) { io_write32(pio->base + offset, val); } static TEE_Result pio_conf_apply(struct pinconf *conf) { struct atmel_pio_pin_conf *pio_conf = conf->priv; struct atmel_pio *pio = pio_conf->pio; DMSG("Apply cfg %#" PRIx32 " on group %" PRIu8 ", pins %#" PRIx32, pio_conf->pin_cfg, pio_conf->pio_group, pio_conf->pin_mask); pio_write(pio, PIO_SIOSR(pio_conf->pio_group), pio_conf->pin_mask); pio_write(pio, PIO_MSKR(pio_conf->pio_group), pio_conf->pin_mask); pio_write(pio, PIO_CFGR(pio_conf->pio_group), pio_conf->pin_cfg); return TEE_SUCCESS; } static void pio_conf_free(struct pinconf *conf) { free(conf); } static const struct pinctrl_ops pio_pinctrl_ops = { .conf_apply = pio_conf_apply, .conf_free = pio_conf_free, }; static TEE_Result pio_pinctrl_dt_get(struct dt_pargs *pargs, void *data, struct pinconf **out_pinconf) { TEE_Result res = TEE_ERROR_GENERIC; int i = 0; int func = 0; int group = 0; int pin_no = 0; uint32_t cfg = 0; int prop_count = 0; int pio_group = -1; uint32_t pinmux = 0; uint32_t pin_mask = 0; bitstr_t *cfg_modes = NULL; const uint32_t *prop = NULL; struct pinconf *pinconf = NULL; struct atmel_pio *atmel_pio = data; struct atmel_pio_pin_conf *pio_conf = NULL; prop = fdt_getprop(pargs->fdt, pargs->phandle_node, "pinmux", &prop_count); if (!prop) return TEE_ERROR_ITEM_NOT_FOUND; prop_count /= sizeof(uint32_t); for (i = 0; i < prop_count; i++) { pinmux = fdt32_to_cpu(prop[i]); pin_no = DT_GET_PIN_NO(pinmux); func = DT_GET_FUNC(pinmux); group = pin_no / 32; if (pio_group == -1) { pio_group = group; } else { if (group != pio_group) { EMSG("Unexpected group %d vs %d", group, pio_group); return TEE_ERROR_GENERIC; } } pin_mask |= BIT(pin_no % 32); } cfg = func; res = pinctrl_parse_dt_pin_modes(pargs->fdt, pargs->phandle_node, &cfg_modes); if (res) return res; for (i = 0; i < PINCTRL_DT_PROP_MAX; i++) { if (!bit_test(cfg_modes, i)) continue; switch (i) { case PINCTRL_DT_PROP_BIAS_PULL_UP: cfg |= PIO_CFGR_PUEN; cfg &= ~PIO_CFGR_PDEN; break; case PINCTRL_DT_PROP_BIAS_PULL_DOWN: cfg |= PIO_CFGR_PDEN; cfg &= ~PIO_CFGR_PUEN; break; case PINCTRL_DT_PROP_BIAS_DISABLE: break; default: EMSG("Unhandled config %u", i); break; } } free(cfg_modes); pinconf = calloc(1, sizeof(*pinconf) + sizeof(*pio_conf)); if (!pinconf) return TEE_ERROR_OUT_OF_MEMORY; pio_conf = (struct atmel_pio_pin_conf *)(pinconf + 1); pio_conf->pin_mask = pin_mask; pio_conf->pin_cfg = cfg; pio_conf->pio = atmel_pio; pio_conf->pio_group = pio_group; pinconf->priv = pio_conf; pinconf->ops = &pio_pinctrl_ops; *out_pinconf = pinconf; return TEE_SUCCESS; } static void pio_init_hw(struct atmel_pio *pio) { int i = 0; /* Set all IOs as non-secure */ for (i = 0; i < PIO_GROUP_COUNT; i++) pio_write(pio, PIO_SIONR(PIO_GROUP_COUNT), GENMASK_32(31, 0)); } /* Non-null reference for compat data */ static const uint8_t has_pioe; static TEE_Result pio_node_probe(const void *fdt, int node, const void *compat_data) { size_t size = 0; struct clk *clk = NULL; struct atmel_pio *pio = NULL; TEE_Result res = TEE_ERROR_GENERIC; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_BAD_STATE; pio = calloc(1, sizeof(*pio)); if (!pio) return TEE_ERROR_OUT_OF_MEMORY; res = clk_dt_get_by_index(fdt, node, 0, &clk); if (res) goto free_pio; if (dt_map_dev(fdt, node, &pio->base, &size, DT_MAP_AUTO) < 0) goto free_pio; res = clk_enable(clk); if (res) goto free_pio; matrix_configure_periph_secure(AT91C_ID_PIOA); matrix_configure_periph_secure(AT91C_ID_PIOB); matrix_configure_periph_secure(AT91C_ID_PIOC); matrix_configure_periph_secure(AT91C_ID_PIOD); if (compat_data == &has_pioe) matrix_configure_periph_secure(AT91C_ID_PIOD + 1); pio_init_hw(pio); res = pinctrl_register_provider(fdt, node, pio_pinctrl_dt_get, pio); if (res) goto disable_clock; return TEE_SUCCESS; disable_clock: clk_disable(clk); free_pio: free(pio); return res; } static const struct dt_device_match atmel_pio_match_table[] = { { .compatible = "atmel,sama5d2-pinctrl" }, { .compatible = "microchip,sama7g5-pinctrl", .compat_data = &has_pioe, }, { } }; DEFINE_DT_DRIVER(atmel_pio_dt_driver) = { .name = "atmel_pio", .type = DT_DRIVER_PINCTRL, .match_table = atmel_pio_match_table, .probe = pio_node_probe, }; optee_os-4.3.0/core/drivers/pinctrl/pinctrl.c000066400000000000000000000062141464416617300212520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Microchip */ #include #include #include #include #include #include #include #include static const char * const pin_modes[PINCTRL_DT_PROP_MAX] = { [PINCTRL_DT_PROP_BIAS_DISABLE] = "bias-disable", [PINCTRL_DT_PROP_BIAS_PULL_UP] = "bias-pull-up", [PINCTRL_DT_PROP_BIAS_PULL_DOWN] = "bias-pull-down", }; TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt, int node, bitstr_t **modes) { unsigned int i = 0; bitstr_t *modes_ptr = NULL; modes_ptr = bit_alloc(PINCTRL_DT_PROP_MAX); if (!modes_ptr) return TEE_ERROR_OUT_OF_MEMORY; for (i = 0; i < ARRAY_SIZE(pin_modes); i++) if (fdt_getprop(fdt, node, pin_modes[i], NULL)) bit_set(modes_ptr, i); *modes = modes_ptr; return TEE_SUCCESS; } TEE_Result pinctrl_apply_state(struct pinctrl_state *state) { unsigned int i = 0; struct pinconf *conf = NULL; TEE_Result res = TEE_ERROR_GENERIC; for (i = 0; i < state->conf_count; i++) { conf = state->confs[i]; res = conf->ops->conf_apply(conf); if (res) { EMSG("Failed to apply pin conf"); return res; } } return TEE_SUCCESS; } void pinctrl_free_state(struct pinctrl_state *state) { unsigned int i = 0; for (i = 0; i < state->conf_count; i++) state->confs[i]->ops->conf_free(state->confs[i]); free(state); } TEE_Result pinctrl_get_state_by_idx(const void *fdt, int nodeoffset, unsigned int pinctrl_index, struct pinctrl_state **state_ret) { int bw = 0; unsigned int conf_id = 0; const uint32_t *prop = NULL; unsigned int conf_count = 0; /* Enough char to hold "pinctrl-" */ char prop_name[8 + 20 + 1] = { }; struct pinctrl_state *state = NULL; TEE_Result res = TEE_ERROR_GENERIC; bw = snprintf(prop_name, sizeof(prop_name), "pinctrl-%d", pinctrl_index); if (bw >= (int)sizeof(prop_name)) return TEE_ERROR_OVERFLOW; prop = fdt_getprop(fdt, nodeoffset, prop_name, (int *)&conf_count); if (!prop) return TEE_ERROR_ITEM_NOT_FOUND; conf_count /= sizeof(uint32_t); state = calloc(1, sizeof(struct pinctrl_state) + conf_count * sizeof(struct pinconf *)); if (!state) return TEE_ERROR_OUT_OF_MEMORY; state->conf_count = conf_count; for (conf_id = 0; conf_id < conf_count; conf_id++) { void *pinconf = NULL; res = dt_driver_device_from_node_idx_prop(prop_name, fdt, nodeoffset, conf_id, DT_DRIVER_PINCTRL, &pinconf); if (res) { free(state); return res; } state->confs[conf_id] = pinconf; } *state_ret = state; return TEE_SUCCESS; } TEE_Result pinctrl_get_state_by_name(const void *fdt, int nodeoffset, const char *name, struct pinctrl_state **state) { int pinctrl_index = 0; if (!name) name = "default"; pinctrl_index = fdt_stringlist_search(fdt, nodeoffset, "pinctrl-names", name); if (pinctrl_index < 0) { *state = NULL; if (pinctrl_index == -FDT_ERR_NOTFOUND) return TEE_ERROR_ITEM_NOT_FOUND; else return TEE_ERROR_GENERIC; } return pinctrl_get_state_by_idx(fdt, nodeoffset, pinctrl_index, state); } optee_os-4.3.0/core/drivers/pinctrl/sub.mk000066400000000000000000000001161464416617300205500ustar00rootroot00000000000000srcs-$(CFG_DRIVERS_PINCTRL) += pinctrl.c srcs-$(CFG_ATMEL_PIO) += atmel_pio.c optee_os-4.3.0/core/drivers/pl011.c000066400000000000000000000143651464416617300167670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #define UART_DR 0x00 /* data register */ #define UART_RSR_ECR 0x04 /* receive status or error clear */ #define UART_DMAWM 0x08 /* DMA watermark configure */ #define UART_TIMEOUT 0x0C /* Timeout period */ /* reserved space */ #define UART_FR 0x18 /* flag register */ #define UART_ILPR 0x20 /* IrDA low-poer */ #define UART_IBRD 0x24 /* integer baud register */ #define UART_FBRD 0x28 /* fractional baud register */ #define UART_LCR_H 0x2C /* line control register */ #define UART_CR 0x30 /* control register */ #define UART_IFLS 0x34 /* interrupt FIFO level select */ #define UART_IMSC 0x38 /* interrupt mask set/clear */ #define UART_RIS 0x3C /* raw interrupt register */ #define UART_MIS 0x40 /* masked interrupt register */ #define UART_ICR 0x44 /* interrupt clear register */ #define UART_DMACR 0x48 /* DMA control register */ /* flag register bits */ #define UART_FR_RTXDIS (1 << 13) #define UART_FR_TERI (1 << 12) #define UART_FR_DDCD (1 << 11) #define UART_FR_DDSR (1 << 10) #define UART_FR_DCTS (1 << 9) #define UART_FR_RI (1 << 8) #define UART_FR_TXFE (1 << 7) #define UART_FR_RXFF (1 << 6) #define UART_FR_TXFF (1 << 5) #define UART_FR_RXFE (1 << 4) #define UART_FR_BUSY (1 << 3) #define UART_FR_DCD (1 << 2) #define UART_FR_DSR (1 << 1) #define UART_FR_CTS (1 << 0) /* transmit/receive line register bits */ #define UART_LCRH_SPS (1 << 7) #define UART_LCRH_WLEN_8 (3 << 5) #define UART_LCRH_WLEN_7 (2 << 5) #define UART_LCRH_WLEN_6 (1 << 5) #define UART_LCRH_WLEN_5 (0 << 5) #define UART_LCRH_FEN (1 << 4) #define UART_LCRH_STP2 (1 << 3) #define UART_LCRH_EPS (1 << 2) #define UART_LCRH_PEN (1 << 1) #define UART_LCRH_BRK (1 << 0) /* control register bits */ #define UART_CR_CTSEN (1 << 15) #define UART_CR_RTSEN (1 << 14) #define UART_CR_OUT2 (1 << 13) #define UART_CR_OUT1 (1 << 12) #define UART_CR_RTS (1 << 11) #define UART_CR_DTR (1 << 10) #define UART_CR_RXE (1 << 9) #define UART_CR_TXE (1 << 8) #define UART_CR_LPE (1 << 7) #define UART_CR_OVSFACT (1 << 3) #define UART_CR_UARTEN (1 << 0) #define UART_IMSC_RTIM (1 << 6) #define UART_IMSC_RXIM (1 << 4) static vaddr_t chip_to_base(struct serial_chip *chip) { struct pl011_data *pd = container_of(chip, struct pl011_data, chip); return io_pa_or_va(&pd->base, PL011_REG_SIZE); } static void pl011_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); /* * Wait for the transmit FIFO to be empty. * It can happen that Linux initializes the OP-TEE driver with the * console UART disabled; avoid an infinite loop by checking the UART * enabled flag. Checking it in the loop makes the code safe against * asynchronous disable. */ while ((io_read32(base + UART_CR) & UART_CR_UARTEN) && !(io_read32(base + UART_FR) & UART_FR_TXFE)) ; } static bool pl011_have_rx_data(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); return !(io_read32(base + UART_FR) & UART_FR_RXFE); } static int pl011_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!pl011_have_rx_data(chip)) ; return io_read32(base + UART_DR) & 0xff; } static void pl011_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); /* Wait until there is space in the FIFO or device is disabled */ while (io_read32(base + UART_FR) & UART_FR_TXFF) ; /* Send the character */ io_write32(base + UART_DR, ch); } static void pl011_rx_intr_enable(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); io_write32(base + UART_IMSC, UART_IMSC_RXIM); } static void pl011_rx_intr_disable(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); io_write32(base + UART_IMSC, 0); } static const struct serial_ops pl011_ops = { .flush = pl011_flush, .getchar = pl011_getchar, .have_rx_data = pl011_have_rx_data, .putc = pl011_putc, .rx_intr_enable = pl011_rx_intr_enable, .rx_intr_disable = pl011_rx_intr_disable, }; DECLARE_KEEP_PAGER(pl011_ops); void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk, uint32_t baud_rate) { vaddr_t base; pd->base.pa = pbase; pd->chip.ops = &pl011_ops; base = io_pa_or_va(&pd->base, PL011_REG_SIZE); /* Clear all errors */ io_write32(base + UART_RSR_ECR, 0); /* Disable everything */ io_write32(base + UART_CR, 0); if (baud_rate) { uint32_t divisor = (uart_clk * 4) / baud_rate; io_write32(base + UART_IBRD, divisor >> 6); io_write32(base + UART_FBRD, divisor & 0x3f); } /* Configure TX to 8 bits, 1 stop bit, no parity, fifo disabled. */ io_write32(base + UART_LCR_H, UART_LCRH_WLEN_8); /* Enable receive interrupt */ io_write32(base + UART_IMSC, UART_IMSC_RXIM); /* Enable UART and RX/TX */ io_write32(base + UART_CR, UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE); pl011_flush(&pd->chip); } #ifdef CFG_DT static struct serial_chip *pl011_dev_alloc(void) { struct pl011_data *pd = nex_calloc(1, sizeof(*pd)); if (!pd) return NULL; return &pd->chip; } static int pl011_dev_init(struct serial_chip *chip, const void *fdt, int offs, const char *parms) { struct pl011_data *pd = container_of(chip, struct pl011_data, chip); vaddr_t vbase; paddr_t pbase; size_t size; if (parms && parms[0]) IMSG("pl011: device parameters ignored (%s)", parms); if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) return -1; if (size != 0x1000) { EMSG("pl011: unexpected register size: %zx", size); return -1; } pbase = virt_to_phys((void *)vbase); pl011_init(pd, pbase, 0, 0); return 0; } static void pl011_dev_free(struct serial_chip *chip) { struct pl011_data *pd = container_of(chip, struct pl011_data, chip); nex_free(pd); } static const struct serial_driver pl011_driver = { .dev_alloc = pl011_dev_alloc, .dev_init = pl011_dev_init, .dev_free = pl011_dev_free, }; static const struct dt_device_match pl011_match_table[] = { { .compatible = "arm,pl011" }, { 0 } }; DEFINE_DT_DRIVER(pl011_dt_driver) = { .name = "pl011", .type = DT_DRIVER_UART, .match_table = pl011_match_table, .driver = &pl011_driver, }; #endif /* CFG_DT */ optee_os-4.3.0/core/drivers/pl022_spi.c000066400000000000000000000305771464416617300176470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited * */ #include #include #include #include #include #include #include #include #include #include /* SPI register offsets */ #define SSPCR0 0x000 #define SSPCR1 0x004 #define SSPDR 0x008 #define SSPSR 0x00C #define SSPCPSR 0x010 #define SSPIMSC 0x014 #define SSPRIS 0x018 #define SSPMIS 0x01C #define SSPICR 0x020 #define SSPDMACR 0x024 #ifdef PLATFORM_hikey /* HiKey extensions */ #define SSPTXFIFOCR 0x028 #define SSPRXFIFOCR 0x02C #define SSPB2BTRANS 0x030 #endif /* test registers */ #define SSPTCR 0x080 #define SSPITIP 0x084 #define SSPITOP 0x088 #define SSPTDR 0x08C #define SSPPeriphID0 0xFE0 #define SSPPeriphID1 0xFE4 #define SSPPeriphID2 0xFE8 #define SSPPeriphID3 0xFEC #define SSPPCellID0 0xFF0 #define SSPPCellID1 0xFF4 #define SSPPCellID2 0xFF8 #define SSPPCellID3 0xFFC /* SPI register masks */ #define SSPCR0_SCR SHIFT_U32(0xFF, 8) #define SSPCR0_SPH SHIFT_U32(1, 7) #define SSPCR0_SPH1 SHIFT_U32(1, 7) #define SSPCR0_SPH0 SHIFT_U32(0, 7) #define SSPCR0_SPO SHIFT_U32(1, 6) #define SSPCR0_SPO1 SHIFT_U32(1, 6) #define SSPCR0_SPO0 SHIFT_U32(0, 6) #define SSPCR0_FRF SHIFT_U32(3, 4) #define SSPCR0_FRF_SPI SHIFT_U32(0, 4) #define SSPCR0_DSS SHIFT_U32(0xFF, 0) #define SSPCR0_DSS_16BIT SHIFT_U32(0xF, 0) #define SSPCR0_DSS_8BIT SHIFT_U32(7, 0) #define SSPCR1_SOD SHIFT_U32(1, 3) #define SSPCR1_SOD_ENABLE SHIFT_U32(1, 3) #define SSPCR1_SOD_DISABLE SHIFT_U32(0, 3) #define SSPCR1_MS SHIFT_U32(1, 2) #define SSPCR1_MS_SLAVE SHIFT_U32(1, 2) #define SSPCR1_MS_MASTER SHIFT_U32(0, 2) #define SSPCR1_SSE SHIFT_U32(1, 1) #define SSPCR1_SSE_ENABLE SHIFT_U32(1, 1) #define SSPCR1_SSE_DISABLE SHIFT_U32(0, 1) #define SSPCR1_LBM SHIFT_U32(1, 0) #define SSPCR1_LBM_YES SHIFT_U32(1, 0) #define SSPCR1_LBM_NO SHIFT_U32(0, 0) #define SSPDR_DATA SHIFT_U32(0xFFFF, 0) #define SSPSR_BSY SHIFT_U32(1, 4) #define SSPSR_RNF SHIFT_U32(1, 3) #define SSPSR_RNE SHIFT_U32(1, 2) #define SSPSR_TNF SHIFT_U32(1, 1) #define SSPSR_TFE SHIFT_U32(1, 0) #define SSPCPSR_CPSDVR SHIFT_U32(0xFF, 0) #define SSPIMSC_TXIM SHIFT_U32(1, 3) #define SSPIMSC_RXIM SHIFT_U32(1, 2) #define SSPIMSC_RTIM SHIFT_U32(1, 1) #define SSPIMSC_RORIM SHIFT_U32(1, 0) #define SSPRIS_TXRIS SHIFT_U32(1, 3) #define SSPRIS_RXRIS SHIFT_U32(1, 2) #define SSPRIS_RTRIS SHIFT_U32(1, 1) #define SSPRIS_RORRIS SHIFT_U32(1, 0) #define SSPMIS_TXMIS SHIFT_U32(1, 3) #define SSPMIS_RXMIS SHIFT_U32(1, 2) #define SSPMIS_RTMIS SHIFT_U32(1, 1) #define SSPMIS_RORMIS SHIFT_U32(1, 0) #define SSPICR_RTIC SHIFT_U32(1, 1) #define SSPICR_RORIC SHIFT_U32(1, 0) #define SSPDMACR_TXDMAE SHIFT_U32(1, 1) #define SSPDMACR_RXDMAE SHIFT_U32(1, 0) #define SSPPeriphID0_PartNumber0 SHIFT_U32(0xFF, 0) /* 0x22 */ #define SSPPeriphID1_Designer0 SHIFT_U32(0xF, 4) /* 0x1 */ #define SSPPeriphID1_PartNumber1 SHIFT_U32(0xF, 0) /* 0x0 */ #define SSPPeriphID2_Revision SHIFT_U32(0xF, 4) #define SSPPeriphID2_Designer1 SHIFT_U32(0xF, 0) /* 0x4 */ #define SSPPeriphID3_Configuration SHIFT_U32(0xFF, 0) /* 0x00 */ #define SSPPCellID_0 SHIFT_U32(0xFF, 0) /* 0x0D */ #define SSPPCellID_1 SHIFT_U32(0xFF, 0) /* 0xF0 */ #define SSPPPCellID_2 SHIFT_U32(0xFF, 0) /* 0x05 */ #define SSPPPCellID_3 SHIFT_U32(0xFF, 0) /* 0xB1 */ #define MASK_32 0xFFFFFFFF #define MASK_28 0xFFFFFFF #define MASK_24 0xFFFFFF #define MASK_20 0xFFFFF #define MASK_16 0xFFFF #define MASK_12 0xFFF #define MASK_8 0xFF #define MASK_4 0xF /* SPI register masks */ #define SSP_CPSDVR_MAX 254 #define SSP_CPSDVR_MIN 2 #define SSP_SCR_MAX 255 #define SSP_SCR_MIN 0 #define SSP_DATASIZE_MAX 16 static enum spi_result pl022_txrx8(struct spi_chip *chip, uint8_t *wdat, uint8_t *rdat, size_t num_pkts) { size_t i = 0; size_t j = 0; struct pl022_data *pd = container_of(chip, struct pl022_data, chip); if (pd->data_size_bits != 8) { EMSG("data_size_bits should be 8, not %u", pd->data_size_bits); return SPI_ERR_CFG; } if (wdat) while (i < num_pkts) { if (io_read8(pd->base + SSPSR) & SSPSR_TNF) { /* tx 1 packet */ io_write8(pd->base + SSPDR, wdat[i++]); } if (rdat) if (io_read8(pd->base + SSPSR) & SSPSR_RNE) { /* rx 1 packet */ rdat[j++] = io_read8(pd->base + SSPDR); } } /* Capture remaining rdat not read above */ if (rdat) { while ((j < num_pkts) && (io_read8(pd->base + SSPSR) & SSPSR_RNE)) { /* rx 1 packet */ rdat[j++] = io_read8(pd->base + SSPDR); } if (j < num_pkts) { EMSG("Packets requested %zu, received %zu", num_pkts, j); return SPI_ERR_PKTCNT; } } return SPI_OK; } static enum spi_result pl022_txrx16(struct spi_chip *chip, uint16_t *wdat, uint16_t *rdat, size_t num_pkts) { size_t i = 0; size_t j = 0; struct pl022_data *pd = container_of(chip, struct pl022_data, chip); if (pd->data_size_bits != 16) { EMSG("data_size_bits should be 16, not %u", pd->data_size_bits); return SPI_ERR_CFG; } if (wdat) while (i < num_pkts) { if (io_read8(pd->base + SSPSR) & SSPSR_TNF) { /* tx 1 packet */ io_write16(pd->base + SSPDR, wdat[i++]); } if (rdat) if (io_read8(pd->base + SSPSR) & SSPSR_RNE) { /* rx 1 packet */ rdat[j++] = io_read16(pd->base + SSPDR); } } /* Capture remaining rdat not read above */ if (rdat) { while ((j < num_pkts) && (io_read8(pd->base + SSPSR) & SSPSR_RNE)) { /* rx 1 packet */ rdat[j++] = io_read16(pd->base + SSPDR); } if (j < num_pkts) { EMSG("Packets requested %zu, received %zu", num_pkts, j); return SPI_ERR_PKTCNT; } } return SPI_OK; } static void pl022_print_peri_id(struct pl022_data *pd __maybe_unused) { DMSG("Expected: 0x 22 10 ?4 00"); DMSG("Read: 0x %02x %02x %02x %02x", io_read8(pd->base + SSPPeriphID0), io_read8(pd->base + SSPPeriphID1), io_read8(pd->base + SSPPeriphID2), io_read8(pd->base + SSPPeriphID3)); } static void pl022_print_cell_id(struct pl022_data *pd __maybe_unused) { DMSG("Expected: 0x 0d f0 05 b1"); DMSG("Read: 0x %02x %02x %02x %02x", io_read8(pd->base + SSPPCellID0), io_read8(pd->base + SSPPCellID1), io_read8(pd->base + SSPPCellID2), io_read8(pd->base + SSPPCellID3)); } static void pl022_sanity_check(struct pl022_data *pd) { assert(pd); assert(pd->chip.ops); assert(pd->cs_control <= PL022_CS_CTRL_MANUAL); switch (pd->cs_control) { case PL022_CS_CTRL_AUTO_GPIO: assert(pd->cs_data.gpio_data.chip); assert(pd->cs_data.gpio_data.chip->ops); break; case PL022_CS_CTRL_CB: assert(pd->cs_data.cs_cb); break; default: break; } assert(pd->clk_hz); assert(pd->speed_hz && pd->speed_hz <= pd->clk_hz/2); assert(pd->mode <= SPI_MODE3); assert(pd->data_size_bits == 8 || pd->data_size_bits == 16); #ifdef PLATFORM_hikey DMSG("SSPB2BTRANS: Expected: 0x2. Read: 0x%x", io_read8(pd->base + SSPB2BTRANS)); #endif pl022_print_peri_id(pd); pl022_print_cell_id(pd); } static inline uint32_t pl022_calc_freq(struct pl022_data *pd, uint8_t cpsdvr, uint8_t scr) { return pd->clk_hz / (cpsdvr * (1 + scr)); } static void pl022_control_cs(struct spi_chip *chip, enum gpio_level value) { struct pl022_data *pd = container_of(chip, struct pl022_data, chip); switch (pd->cs_control) { case PL022_CS_CTRL_AUTO_GPIO: if (io_read8(pd->base + SSPSR) & SSPSR_BSY) DMSG("pl022 busy - do NOT set CS!"); while (io_read8(pd->base + SSPSR) & SSPSR_BSY) ; DMSG("pl022 done - set CS!"); pd->cs_data.gpio_data.chip->ops->set_value(NULL, pd->cs_data.gpio_data.pin_num, value); break; case PL022_CS_CTRL_CB: pd->cs_data.cs_cb(value); break; default: break; } } static void pl022_calc_clk_divisors(struct pl022_data *pd, uint8_t *cpsdvr, uint8_t *scr) { unsigned int freq1 = 0; unsigned int freq2 = 0; uint8_t tmp_cpsdvr1; uint8_t tmp_scr1; uint8_t tmp_cpsdvr2 = 0; uint8_t tmp_scr2 = 0; for (tmp_scr1 = SSP_SCR_MIN; tmp_scr1 < SSP_SCR_MAX; tmp_scr1++) { for (tmp_cpsdvr1 = SSP_CPSDVR_MIN; tmp_cpsdvr1 < SSP_CPSDVR_MAX; tmp_cpsdvr1++) { freq1 = pl022_calc_freq(pd, tmp_cpsdvr1, tmp_scr1); if (freq1 == pd->speed_hz) goto done; else if (freq1 < pd->speed_hz) goto stage2; } } stage2: for (tmp_cpsdvr2 = SSP_CPSDVR_MIN; tmp_cpsdvr2 < SSP_CPSDVR_MAX; tmp_cpsdvr2++) { for (tmp_scr2 = SSP_SCR_MIN; tmp_scr2 < SSP_SCR_MAX; tmp_scr2++) { freq2 = pl022_calc_freq(pd, tmp_cpsdvr2, tmp_scr2); if (freq2 <= pd->speed_hz) goto done; } } done: if (freq1 >= freq2) { *cpsdvr = tmp_cpsdvr1; *scr = tmp_scr1; DMSG("speed: requested: %u, closest1: %u", pd->speed_hz, freq1); } else { *cpsdvr = tmp_cpsdvr2; *scr = tmp_scr2; DMSG("speed: requested: %u, closest2: %u", pd->speed_hz, freq2); } DMSG("CPSDVR: %u (0x%x), SCR: %u (0x%x)", *cpsdvr, *cpsdvr, *scr, *scr); } static void pl022_flush_fifo(struct spi_chip *chip) { uint32_t __maybe_unused rdat; struct pl022_data *pd = container_of(chip, struct pl022_data, chip); do { while (io_read32(pd->base + SSPSR) & SSPSR_RNE) { rdat = io_read32(pd->base + SSPDR); DMSG("rdat: 0x%x", rdat); } } while (io_read32(pd->base + SSPSR) & SSPSR_BSY); } static void pl022_configure(struct spi_chip *chip) { uint16_t mode; uint16_t data_size; uint8_t cpsdvr; uint8_t scr; uint8_t lbm; struct pl022_data *pd = container_of(chip, struct pl022_data, chip); pl022_sanity_check(pd); switch (pd->cs_control) { case PL022_CS_CTRL_AUTO_GPIO: DMSG("Use auto GPIO CS control"); DMSG("Mask/disable interrupt for CS GPIO"); pd->cs_data.gpio_data.chip->ops->set_interrupt(NULL, pd->cs_data.gpio_data.pin_num, GPIO_INTERRUPT_DISABLE); DMSG("Set CS GPIO dir to out"); pd->cs_data.gpio_data.chip->ops->set_direction(NULL, pd->cs_data.gpio_data.pin_num, GPIO_DIR_OUT); break; case PL022_CS_CTRL_CB: DMSG("Use registered CS callback"); break; case PL022_CS_CTRL_MANUAL: DMSG("Use manual CS control"); break; default: EMSG("Invalid CS control type: %d", pd->cs_control); panic(); } DMSG("Pull CS high"); pl022_control_cs(chip, GPIO_LEVEL_HIGH); pl022_calc_clk_divisors(pd, &cpsdvr, &scr); /* configure ssp based on platform settings */ switch (pd->mode) { case SPI_MODE0: DMSG("SPI mode 0"); mode = SSPCR0_SPO0 | SSPCR0_SPH0; break; case SPI_MODE1: DMSG("SPI mode 1"); mode = SSPCR0_SPO0 | SSPCR0_SPH1; break; case SPI_MODE2: DMSG("SPI mode 2"); mode = SSPCR0_SPO1 | SSPCR0_SPH0; break; case SPI_MODE3: DMSG("SPI mode 3"); mode = SSPCR0_SPO1 | SSPCR0_SPH1; break; default: EMSG("Invalid SPI mode: %u", pd->mode); panic(); } switch (pd->data_size_bits) { case 8: DMSG("Data size: 8"); data_size = SSPCR0_DSS_8BIT; break; case 16: DMSG("Data size: 16"); data_size = SSPCR0_DSS_16BIT; break; default: EMSG("Unsupported data size: %u bits", pd->data_size_bits); panic(); } if (pd->loopback) { DMSG("Starting in loopback mode!"); lbm = SSPCR1_LBM_YES; } else { DMSG("Starting in regular (non-loopback) mode!"); lbm = SSPCR1_LBM_NO; } DMSG("Set Serial Clock Rate (SCR), SPI mode (phase and clock)"); DMSG("Set frame format (SPI) and data size (8- or 16-bit)"); io_mask16(pd->base + SSPCR0, SHIFT_U32(scr, 8) | mode | SSPCR0_FRF_SPI | data_size, MASK_16); DMSG("Set master mode, disable SSP, set loopback mode"); io_mask8(pd->base + SSPCR1, SSPCR1_SOD_DISABLE | SSPCR1_MS_MASTER | SSPCR1_SSE_DISABLE | lbm, MASK_4); DMSG("Set clock prescale"); io_mask8(pd->base + SSPCPSR, cpsdvr, SSPCPSR_CPSDVR); DMSG("Disable interrupts"); io_mask8(pd->base + SSPIMSC, 0, MASK_4); DMSG("Clear interrupts"); io_mask8(pd->base + SSPICR, SSPICR_RORIC | SSPICR_RTIC, SSPICR_RORIC | SSPICR_RTIC); DMSG("Empty FIFO before starting"); pl022_flush_fifo(chip); } static void pl022_start(struct spi_chip *chip) { struct pl022_data *pd = container_of(chip, struct pl022_data, chip); DMSG("Enable SSP"); io_mask8(pd->base + SSPCR1, SSPCR1_SSE_ENABLE, SSPCR1_SSE); pl022_control_cs(chip, GPIO_LEVEL_LOW); } static void pl022_end(struct spi_chip *chip) { struct pl022_data *pd = container_of(chip, struct pl022_data, chip); pl022_control_cs(chip, GPIO_LEVEL_HIGH); DMSG("Disable SSP"); io_mask8(pd->base + SSPCR1, SSPCR1_SSE_DISABLE, SSPCR1_SSE); } static const struct spi_ops pl022_ops = { .configure = pl022_configure, .start = pl022_start, .txrx8 = pl022_txrx8, .txrx16 = pl022_txrx16, .end = pl022_end, .flushfifo = pl022_flush_fifo, }; DECLARE_KEEP_PAGER(pl022_ops); void pl022_init(struct pl022_data *pd) { assert(pd); pd->chip.ops = &pl022_ops; } optee_os-4.3.0/core/drivers/pl061_gpio.c000066400000000000000000000131401464416617300200000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #ifndef PLAT_PL061_MAX_GPIOS # define PLAT_PL061_MAX_GPIOS 32 #endif /* PLAT_PL061_MAX_GPIOS */ #define MAX_GPIO_DEVICES ((PLAT_PL061_MAX_GPIOS + \ (GPIOS_PER_PL061 - 1)) / GPIOS_PER_PL061) #define GPIOS_PER_PL061 8 /* gpio register offsets */ #define GPIODIR 0x400 #define GPIOIS 0x404 #define GPIOIBE 0x408 #define GPIOIEV 0x40C #define GPIOIE 0x410 #define GPIORIS 0x414 #define GPIOMIS 0x418 #define GPIOIC 0x41C #define GPIOAFSEL 0x420 /* gpio register masks */ #define GPIOIE_ENABLED SHIFT_U32(1, 0) #define GPIOIE_MASKED SHIFT_U32(0, 0) #define GPIOAFSEL_HW SHIFT_U32(1, 0) #define GPIOAFSEL_SW SHIFT_U32(0, 0) #define GPIODIR_OUT SHIFT_U32(1, 0) #define GPIODIR_IN SHIFT_U32(0, 0) static vaddr_t pl061_reg_base[MAX_GPIO_DEVICES]; static enum gpio_dir pl061_get_direction(struct gpio_chip *chip __unused, unsigned int gpio_pin) { vaddr_t base_addr; uint8_t data; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; data = io_read8(base_addr + GPIODIR); if (data & BIT(offset)) return GPIO_DIR_OUT; return GPIO_DIR_IN; } static void pl061_set_direction(struct gpio_chip *chip __unused, unsigned int gpio_pin, enum gpio_dir direction) { vaddr_t base_addr; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; if (direction == GPIO_DIR_OUT) io_setbits8(base_addr + GPIODIR, BIT(offset)); else io_clrbits8(base_addr + GPIODIR, BIT(offset)); } /* * The offset of GPIODATA register is 0. * The values read from GPIODATA are determined for each bit, by the mask bit * derived from the address used to access the data register, PADDR[9:2]. * Bits that are 1 in the address mask cause the corresponding bits in GPIODATA * to be read, and bits that are 0 in the address mask cause the corresponding * bits in GPIODATA to be read as 0, regardless of their value. */ static enum gpio_level pl061_get_value(struct gpio_chip *chip __unused, unsigned int gpio_pin) { vaddr_t base_addr; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; if (io_read8(base_addr + BIT(offset + 2))) return GPIO_LEVEL_HIGH; return GPIO_LEVEL_LOW; } /* * In order to write GPIODATA, the corresponding bits in the mask, resulting * from the address bus, PADDR[9:2], must be HIGH. Otherwise the bit values * remain unchanged by the write. */ static void pl061_set_value(struct gpio_chip *chip __unused, unsigned int gpio_pin, enum gpio_level value) { vaddr_t base_addr; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; if (value == GPIO_LEVEL_HIGH) io_write8(base_addr + BIT(offset + 2), BIT(offset)); else io_write8(base_addr + BIT(offset + 2), 0); } static enum gpio_interrupt pl061_get_interrupt(struct gpio_chip *chip __unused, unsigned int gpio_pin) { vaddr_t base_addr; uint8_t data; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; data = io_read8(base_addr + GPIOIE); if (data & BIT(offset)) return GPIO_INTERRUPT_ENABLE; return GPIO_INTERRUPT_DISABLE; } static void pl061_set_interrupt(struct gpio_chip *chip __unused, unsigned int gpio_pin, enum gpio_interrupt ena_dis) { vaddr_t base_addr; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; if (ena_dis == GPIO_INTERRUPT_ENABLE) io_setbits8(base_addr + GPIOIE, BIT(offset)); else io_clrbits8(base_addr + GPIOIE, BIT(offset)); } /* * Register the PL061 GPIO controller with a base address and the offset * of start pin in this GPIO controller. * This function is called after pl061_init(). */ void pl061_register(vaddr_t base_addr, unsigned int gpio_dev) { assert(gpio_dev < MAX_GPIO_DEVICES); pl061_reg_base[gpio_dev] = base_addr; } static const struct gpio_ops pl061_ops = { .get_direction = pl061_get_direction, .set_direction = pl061_set_direction, .get_value = pl061_get_value, .set_value = pl061_set_value, .get_interrupt = pl061_get_interrupt, .set_interrupt = pl061_set_interrupt, }; DECLARE_KEEP_PAGER(pl061_ops); /* * Initialize PL061 GPIO controller */ void pl061_init(struct pl061_data *pd) { COMPILE_TIME_ASSERT(PLAT_PL061_MAX_GPIOS > 0); assert(pd); pd->chip.ops = &pl061_ops; } enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin) { vaddr_t base_addr; uint8_t data; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; data = io_read8(base_addr + GPIOAFSEL); if (data & BIT(offset)) return PL061_MC_HW; return PL061_MC_SW; } void pl061_set_mode_control(unsigned int gpio_pin, enum pl061_mode_control hw_sw) { vaddr_t base_addr; unsigned int offset; assert(gpio_pin < PLAT_PL061_MAX_GPIOS); base_addr = pl061_reg_base[gpio_pin / GPIOS_PER_PL061]; offset = gpio_pin % GPIOS_PER_PL061; if (hw_sw == PL061_MC_HW) io_setbits8(base_addr + GPIOAFSEL, BIT(offset)); else io_clrbits8(base_addr + GPIOAFSEL, BIT(offset)); } optee_os-4.3.0/core/drivers/plic.c000066400000000000000000000151221464416617300170510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022-2023 NXP */ #include #include #include #include #include #include #include #include #include #include #define PLIC_PRIORITY_OFFSET 0 #define PLIC_PENDING_OFFSET 0x1000 #define PLIC_ENABLE_OFFSET 0x2000 #define PLIC_THRESHOLD_OFFSET 0x200000 #define PLIC_CLAIM_OFFSET 0x200004 #define PLIC_PRIORITY_SHIFT_PER_SOURCE U(2) #define PLIC_PENDING_SHIFT_PER_SOURCE U(0) #define PLIC_ENABLE_SHIFT_PER_TARGET U(7) #define PLIC_THRESHOLD_SHIFT_PER_TARGET U(12) #define PLIC_CLAIM_SHIFT_PER_TARGET U(12) #define PLIC_PRIORITY(base, source) \ ((base) + PLIC_PRIORITY_OFFSET + \ SHIFT_U32(source, PLIC_PRIORITY_SHIFT_PER_SOURCE) \ ) #define PLIC_PENDING(base, source) \ ((base) + PLIC_PENDING_OFFSET + \ (4 * ((source) / 32)) \ ) #define PLIC_ENABLE(base, source, context) \ ((base) + PLIC_ENABLE_OFFSET + \ SHIFT_U32(context, PLIC_ENABLE_SHIFT_PER_TARGET) +\ (4 * ((source) / 32)) \ ) #define PLIC_THRESHOLD(base, context) \ ((base) + PLIC_THRESHOLD_OFFSET + \ SHIFT_U32(context, PLIC_THRESHOLD_SHIFT_PER_TARGET) \ ) #define PLIC_COMPLETE(base, context) \ ((base) + PLIC_CLAIM_OFFSET + \ SHIFT_U32(context, PLIC_CLAIM_SHIFT_PER_TARGET) \ ) #define PLIC_CLAIM(base, context) PLIC_COMPLETE(base, context) register_phys_mem_pgdir(MEM_AREA_IO_SEC, PLIC_BASE, PLIC_REG_SIZE); struct plic_data { vaddr_t plic_base; size_t max_it; struct itr_chip chip; }; static struct plic_data plic_data __nex_bss; /* * We assume that each hart has M-mode and S-mode, so the contexts look like: * PLIC context 0 is hart 0 M-mode * PLIC context 1 is hart 0 S-mode * PLIC context 2 is hart 1 M-mode * PLIC context 3 is hart 1 S-mode * ... */ static uint32_t plic_get_context(void) { size_t hartid = get_core_pos(); bool smode = IS_ENABLED(CFG_RISCV_S_MODE) ? true : false; return hartid * 2 + smode; } static bool __maybe_unused plic_is_pending(struct plic_data *pd, uint32_t source) { return io_read32(PLIC_PENDING(pd->plic_base, source)) & BIT(source % 32); } static void plic_set_pending(struct plic_data *pd, uint32_t source) { io_setbits32(PLIC_PENDING(pd->plic_base, source), BIT(source % 32)); } static void plic_enable_interrupt(struct plic_data *pd, uint32_t source) { uint32_t context = plic_get_context(); io_setbits32(PLIC_ENABLE(pd->plic_base, source, context), BIT(source & 0x1f)); } static uint32_t __maybe_unused plic_get_interrupt_enable(struct plic_data *pd, uint32_t source) { uint32_t context = plic_get_context(); return io_read32(PLIC_ENABLE(pd->plic_base, source, context)) & BIT(source & 0x1f); } static void plic_disable_interrupt(struct plic_data *pd, uint32_t source) { uint32_t context = plic_get_context(); io_clrbits32(PLIC_ENABLE(pd->plic_base, source, context), BIT(source & 0x1f)); } static uint32_t __maybe_unused plic_get_threshold(struct plic_data *pd) { uint32_t context = plic_get_context(); return io_read32(PLIC_THRESHOLD(pd->plic_base, context)); } static void plic_set_threshold(struct plic_data *pd, uint32_t threshold) { uint32_t context = plic_get_context(); io_write32(PLIC_THRESHOLD(pd->plic_base, context), threshold); } static uint32_t __maybe_unused plic_get_priority(struct plic_data *pd, uint32_t source) { return io_read32(PLIC_PRIORITY(pd->plic_base, source)); } static void plic_set_priority(struct plic_data *pd, uint32_t source, uint32_t priority) { io_write32(PLIC_PRIORITY(pd->plic_base, source), priority); } static uint32_t plic_claim_interrupt(struct plic_data *pd) { uint32_t context = plic_get_context(); return io_read32(PLIC_CLAIM(pd->plic_base, context)); } static void plic_complete_interrupt(struct plic_data *pd, uint32_t source) { uint32_t context = plic_get_context(); io_write32(PLIC_CLAIM(pd->plic_base, context), source); } static void plic_op_add(struct itr_chip *chip, size_t it, uint32_t type __unused, uint32_t prio) { struct plic_data *pd = container_of(chip, struct plic_data, chip); if (it > pd->max_it) panic(); plic_disable_interrupt(pd, it); plic_set_priority(pd, it, prio); } static void plic_op_enable(struct itr_chip *chip, size_t it) { struct plic_data *pd = container_of(chip, struct plic_data, chip); if (it > pd->max_it) panic(); plic_enable_interrupt(pd, it); } static void plic_op_disable(struct itr_chip *chip, size_t it) { struct plic_data *pd = container_of(chip, struct plic_data, chip); if (it > pd->max_it) panic(); plic_disable_interrupt(pd, it); } static void plic_op_raise_pi(struct itr_chip *chip, size_t it) { struct plic_data *pd = container_of(chip, struct plic_data, chip); if (it > pd->max_it) panic(); plic_set_pending(pd, it); } static void plic_op_raise_sgi(struct itr_chip *chip __unused, size_t it __unused, uint32_t cpu_mask __unused) { } static void plic_op_set_affinity(struct itr_chip *chip __unused, size_t it __unused, uint8_t cpu_mask __unused) { } static int plic_dt_get_irq(const uint32_t *properties __unused, int count __unused, uint32_t *type __unused, uint32_t *prio __unused) { return DT_INFO_INVALID_INTERRUPT; } static size_t probe_max_it(vaddr_t plic_base __unused) { return PLIC_NUM_SOURCES; } static const struct itr_ops plic_ops = { .add = plic_op_add, .mask = plic_op_disable, .unmask = plic_op_enable, .enable = plic_op_enable, .disable = plic_op_disable, .raise_pi = plic_op_raise_pi, .raise_sgi = plic_op_raise_sgi, .set_affinity = plic_op_set_affinity, }; static void plic_init_base_addr(struct plic_data *pd, paddr_t plic_base_pa) { vaddr_t plic_base = 0; assert(cpu_mmu_enabled()); plic_base = core_mmu_get_va(plic_base_pa, MEM_AREA_IO_SEC, PLIC_REG_SIZE); if (!plic_base) panic(); pd->plic_base = plic_base; pd->max_it = probe_max_it(plic_base); pd->chip.ops = &plic_ops; if (IS_ENABLED(CFG_DT)) pd->chip.dt_get_irq = plic_dt_get_irq; } void plic_hart_init(void) { /* TODO: To be called by secondary harts */ } void plic_init(paddr_t plic_base_pa) { struct plic_data *pd = &plic_data; size_t n = 0; plic_init_base_addr(pd, plic_base_pa); for (n = 0; n <= pd->max_it; n++) { plic_disable_interrupt(pd, n); plic_set_priority(pd, n, 1); } plic_set_threshold(pd, 0); interrupt_main_init(&plic_data.chip); } void plic_it_handle(void) { struct plic_data *pd = &plic_data; uint32_t id = plic_claim_interrupt(pd); if (id > 0 && id <= pd->max_it) interrupt_call_handlers(&pd->chip, id); else DMSG("ignoring interrupt %" PRIu32, id); plic_complete_interrupt(pd, id); } optee_os-4.3.0/core/drivers/pm/000077500000000000000000000000001464416617300163715ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/pm/imx/000077500000000000000000000000001464416617300171665ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/pm/imx/gpcv2.c000066400000000000000000000022621464416617300203550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2017, 2023 NXP * * Peng Fan */ #include #include #include #include "local.h" #define GPC_PGC_C1 0x840 #define GPC_PGC_PCG_MASK BIT(0) #define GPC_CPU_PGC_SW_PUP_REQ 0xf0 #define GPC_PU_PGC_SW_PUP_REQ 0xf8 #define GPC_CPU_PGC_SW_PDN_REQ 0xfc #define GPC_PU_PGC_SW_PDN_REQ 0x104 #define GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK BIT(1) static void imx_gpcv2_set_core_pgc(bool enable, uint32_t offset) { vaddr_t va = core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, GPC_SIZE); if (enable) io_setbits32(va + offset, GPC_PGC_PCG_MASK); else io_clrbits32(va + offset, GPC_PGC_PCG_MASK); } void imx_gpcv2_set_core1_pup_by_software(void) { vaddr_t va = core_mmu_get_va(GPC_BASE, MEM_AREA_IO_SEC, GPC_SIZE); uint64_t timeout = timeout_init_us(10 * 1000); imx_gpcv2_set_core_pgc(true, GPC_PGC_C1); io_setbits32(va + GPC_CPU_PGC_SW_PUP_REQ, GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK); while ((io_read32(va + GPC_CPU_PGC_SW_PUP_REQ) & GPC_PGC_SW_PDN_PUP_REQ_CORE1_MASK)) { if (timeout_elapsed(timeout)) return; } imx_gpcv2_set_core_pgc(false, GPC_PGC_C1); } optee_os-4.3.0/core/drivers/pm/imx/local.h000066400000000000000000000017631464416617300204400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP */ #include /* * Read the SRC GPR ARG register for the given core number * @cpu Core number */ uint32_t imx_get_src_gpr_arg(unsigned int cpu); /* * Set the SRC GPR ARG register for the given core number * @cpu Core number * @val Register value to set */ void imx_set_src_gpr_arg(unsigned int cpu, uint32_t val); /* * Read the SRC GPR ENTRY register for the given core number * @cpu Core number */ uint32_t imx_get_src_gpr_entry(unsigned int cpu); /* * Set the SRC GPR ENTRY register for the given core number * @cpu Core number * @val Register value to set */ void imx_set_src_gpr_entry(unsigned int cpu, uint32_t val); /* * Release the given core * @cpu Core number */ void imx_src_release_secondary_core(unsigned int cpu); /* * Shutdown the given core * @cpu Core number */ void imx_src_shutdown_core(unsigned int cpu); /* * GPC Core 1 power down */ void imx_gpcv2_set_core1_pup_by_software(void); optee_os-4.3.0/core/drivers/pm/imx/psci.c000066400000000000000000000053611464416617300202750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * Copyright 2023 NXP * * Peng Fan */ #include #include #include #include #include #include #include #include #include #include #include #include "local.h" #define IOMUXC_GPR5_OFFSET 0x14 #define ARM_WFI_STAT_MASK(n) BIT(n) int psci_features(uint32_t psci_fid) { switch (psci_fid) { case ARM_SMCCC_VERSION: case PSCI_PSCI_FEATURES: case PSCI_VERSION: case PSCI_CPU_OFF: #ifdef CFG_BOOT_SECONDARY_REQUEST case PSCI_CPU_ON: #endif case PSCI_AFFINITY_INFO: case PSCI_SYSTEM_OFF: case PSCI_SYSTEM_RESET: case PSCI_SYSTEM_RESET2: return PSCI_RET_SUCCESS; default: return PSCI_RET_NOT_SUPPORTED; } } uint32_t psci_version(void) { return PSCI_VERSION_1_0; } #ifdef CFG_BOOT_SECONDARY_REQUEST int psci_cpu_on(uint32_t core_idx, uint32_t entry, uint32_t context_id) { if (core_idx == 0 || core_idx >= CFG_TEE_CORE_NB_CORE) return PSCI_RET_INVALID_PARAMETERS; /* set secondary cores' NS entry addresses */ boot_set_core_ns_entry(core_idx, entry, context_id); imx_set_src_gpr_entry(core_idx, virt_to_phys((void *)TEE_LOAD_ADDR)); #ifdef CFG_MX7 imx_gpcv2_set_core1_pup_by_software(); imx_src_release_secondary_core(core_idx); #else imx_src_release_secondary_core(core_idx); imx_set_src_gpr_arg(core_idx, 0); #endif /* CFG_MX7 */ IMSG("psci on ok"); return PSCI_RET_SUCCESS; } int __noreturn psci_cpu_off(void) { uint32_t core_id = get_core_pos(); IMSG("core_id: %" PRIu32, core_id); psci_armv7_cpu_off(); imx_set_src_gpr_arg(core_id, UINT32_MAX); thread_mask_exceptions(THREAD_EXCP_ALL); while (true) wfi(); } int psci_affinity_info(uint32_t affinity, uint32_t lowest_affnity_level __unused) { vaddr_t base = core_mmu_get_va(IOMUXC_BASE, MEM_AREA_IO_SEC, IOMUXC_SIZE); uint32_t cpu = affinity; bool wfi = true; if (!soc_is_imx7ds()) wfi = io_read32(base + IOMUXC_GPR5_OFFSET) & ARM_WFI_STAT_MASK(cpu); if (imx_get_src_gpr_arg(cpu) == 0 || !wfi) return PSCI_AFFINITY_LEVEL_ON; DMSG("cpu: %" PRIu32 "GPR: %" PRIx32, cpu, imx_get_src_gpr_arg(cpu)); while (imx_get_src_gpr_arg(cpu) != UINT_MAX) ; imx_src_shutdown_core(cpu); imx_set_src_gpr_arg(cpu, 0); return PSCI_AFFINITY_LEVEL_OFF; } #endif void __noreturn psci_system_off(void) { #ifndef CFG_MX7ULP imx_snvs_shutdown(); #endif dsb(); while (1) ; } void __noreturn psci_system_reset(void) { imx_wdog_restart(true); } int __noreturn psci_system_reset2(uint32_t reset_type __unused, uint32_t cookie __unused) { /* force WDOG reset */ imx_wdog_restart(false); } optee_os-4.3.0/core/drivers/pm/imx/src.c000066400000000000000000000042061464416617300201230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019, 2023 NXP */ #include #include #include #include #include "local.h" #define SRC_SCR 0x000 #define SRC_A7RCR0 0x004 #define SRC_A7RCR1 0x008 #if defined(CFG_MX7) #define SRC_GPR1 0x074 #else #define SRC_GPR1 0x020 #endif #define SRC_SCR_CORE1_RST_BIT(_cpu) BIT32(14 + (_cpu) - 1) #define SRC_SCR_CORE1_ENABLE_BIT(_cpu) BIT32(22 + (_cpu) - 1) #define SRC_A7RCR0_A7_CORE_RESET0_BIT(_cpu) BIT32((_cpu) - 1) #define SRC_A7RCR1_A7_CORE1_ENABLE_BIT(_cpu) BIT32(1 + (_cpu) - 1) #define ENTRY_OFFSET(_cpu) ((_cpu) * 8) #define ARG_OFFSET(_cpu) (ENTRY_OFFSET(_cpu) + 4) register_phys_mem(MEM_AREA_IO_SEC, SRC_BASE, SRC_SIZE); uint32_t imx_get_src_gpr_arg(unsigned int cpu) { vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); return io_read32(va + SRC_GPR1 + ARG_OFFSET(cpu)); } void imx_set_src_gpr_arg(unsigned int cpu, uint32_t val) { vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); io_write32(va + SRC_GPR1 + ARG_OFFSET(cpu), val); } uint32_t imx_get_src_gpr_entry(unsigned int cpu) { vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); return io_read32(va + SRC_GPR1 + ENTRY_OFFSET(cpu)); } void imx_set_src_gpr_entry(unsigned int cpu, uint32_t val) { vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); io_write32(va + SRC_GPR1 + ENTRY_OFFSET(cpu), val); } void imx_src_release_secondary_core(unsigned int cpu) { vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); if (soc_is_imx7ds()) io_setbits32(va + SRC_A7RCR1, SRC_A7RCR1_A7_CORE1_ENABLE_BIT(cpu)); else io_setbits32(va + SRC_SCR, SRC_SCR_CORE1_ENABLE_BIT(cpu) | SRC_SCR_CORE1_RST_BIT(cpu)); } void imx_src_shutdown_core(unsigned int cpu) { vaddr_t va = core_mmu_get_va(SRC_BASE, MEM_AREA_IO_SEC, SRC_SIZE); if (soc_is_imx7ds()) { io_clrbits32(va + SRC_A7RCR1, SRC_A7RCR1_A7_CORE1_ENABLE_BIT(cpu)); } else { uint32_t mask = io_read32(va + SRC_SCR); mask &= ~SRC_SCR_CORE1_ENABLE_BIT(cpu); mask |= SRC_SCR_CORE1_RST_BIT(cpu); io_write32(va + SRC_SCR, mask); } } optee_os-4.3.0/core/drivers/pm/imx/sub.mk000066400000000000000000000001171464416617300203070ustar00rootroot00000000000000srcs-y += psci.c srcs-$(CFG_MX7) += gpcv2.c srcs-$(CFG_MX6)$(CFG_MX7) += src.c optee_os-4.3.0/core/drivers/pm/sam/000077500000000000000000000000001464416617300171515ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/pm/sam/at91_pm.c000066400000000000000000000326541464416617300206010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "at91_pm.h" #if CFG_ATMEL_PM_SUSPEND_MODE < AT91_PM_STANDBY || \ CFG_ATMEL_PM_SUSPEND_MODE > AT91_PM_BACKUP #error Invalid suspend mode, please check CFG_ATMEL_PM_SUSPEND_MODE #endif #define AT91_SECUMOD_SYSR 0x04 #define AT91_SECUMOD_RAMRDY 0x14 #define AT91_SECUMOD_RAMRDY_READY BIT(0) static struct at91_pm_data soc_pm; /* Backup canary */ static uint32_t canary = 0xA5A5A5A5; /* Backup mode information used by at91bootstrap */ static struct at91bootstrap_bu { uint32_t suspended; uint32_t reserved; uint32_t *canary; uint32_t resume; } *at91bootstrap_bu; static vaddr_t at91_suspend_sram_base; static void (*at91_suspend_sram_fn)(struct at91_pm_data *); enum sm_handler_ret at91_pm_set_suspend_mode(struct thread_smc_args *args) { unsigned int mode = args->a1; /* * We don't expect this function to be called simultaneously while we * are entering suspend/resume function. On sama5d2, this is not a * problem since this SoC is a single core one but in order to prevent * any other SoC support to be added without handling this concurrency, * check that we are compiled for a single core. */ COMPILE_TIME_ASSERT(CFG_TEE_CORE_NB_CORE == 1); if (mode > AT91_PM_BACKUP) { args->a0 = SAMA5_SMC_SIP_RETURN_EINVAL; return SM_HANDLER_SMC_HANDLED; } DMSG("Setting suspend mode to %u", mode); args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; soc_pm.mode = mode; return SM_HANDLER_SMC_HANDLED; } enum sm_handler_ret at91_pm_get_suspend_mode(struct thread_smc_args *args) { args->a1 = soc_pm.mode; args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS; return SM_HANDLER_SMC_HANDLED; } static void at91_pm_copy_suspend_to_sram(void) { memcpy((void *)at91_suspend_sram_base, &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); cache_op_inner(DCACHE_AREA_CLEAN, (void *)at91_suspend_sram_base, at91_pm_suspend_in_sram_sz); cache_op_inner(ICACHE_AREA_INVALIDATE, at91_suspend_sram_fn, at91_pm_suspend_in_sram_sz); } void atmel_pm_cpu_idle(void) { uint32_t lpr0 = 0; uint32_t saved_lpr0 = 0; saved_lpr0 = io_read32(soc_pm.ramc + AT91_DDRSDRC_LPR); lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB; lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN; io_write32(soc_pm.ramc + AT91_DDRSDRC_LPR, lpr0); cpu_idle(); io_write32(soc_pm.ramc + AT91_DDRSDRC_LPR, saved_lpr0); } static void at91_sam_config_shdwc_ws(vaddr_t shdwc, uint32_t *mode, uint32_t *polarity) { uint32_t val = 0; /* SHDWC.WUIR */ val = io_read32(shdwc + AT91_SHDW_WUIR); *mode |= val & AT91_SHDW_WKUPEN_MASK; *polarity |= (val >> AT91_SHDW_WKUPT_SHIFT) & AT91_SHDW_WKUPT_MASK; } static int at91_sam_config_pmc_ws(vaddr_t pmc, uint32_t mode, uint32_t polarity) { io_write32(pmc + AT91_PMC_FSMR, mode); if (IS_ENABLED(CFG_SAMA5D2)) io_write32(pmc + AT91_PMC_FSPR, polarity); return 0; } struct wakeup_source_info { unsigned int pmc_fsmr_bit; unsigned int shdwc_mr_bit; bool set_polarity; }; static const struct wakeup_source_info ws_info[] = { { .pmc_fsmr_bit = AT91_PMC_FSTT(10), .set_polarity = true }, { .pmc_fsmr_bit = AT91_PMC_RTCAL, .shdwc_mr_bit = BIT(17) }, { .pmc_fsmr_bit = AT91_PMC_USBAL }, { .pmc_fsmr_bit = AT91_PMC_SDMMC_CD }, { .pmc_fsmr_bit = AT91_PMC_RTTAL }, { .pmc_fsmr_bit = AT91_PMC_RXLP_MCE }, }; struct wakeup_src { const char *compatible; const struct wakeup_source_info *info; }; static const struct wakeup_src sam_ws_ids[] = { #ifdef CFG_SAMA5D2 { .compatible = "atmel,sama5d2-gem", .info = &ws_info[0] }, { .compatible = "atmel,at91rm9200-rtc", .info = &ws_info[1] }, { .compatible = "atmel,sama5d3-udc", .info = &ws_info[2] }, { .compatible = "atmel,at91rm9200-ohci", .info = &ws_info[2] }, { .compatible = "usb-ohci", .info = &ws_info[2] }, { .compatible = "atmel,at91sam9g45-ehci", .info = &ws_info[2] }, { .compatible = "usb-ehci", .info = &ws_info[2] }, { .compatible = "atmel,sama5d2-sdhci", .info = &ws_info[3] } #endif #ifdef CFG_SAMA7G5 { .compatible = "microchip,sama7g5-rtc", .info = &ws_info[1] }, { .compatible = "microchip,sama7g5-ohci", .info = &ws_info[2] }, { .compatible = "usb-ohci", .info = &ws_info[2] }, { .compatible = "atmel,at91sam9g45-ehci", .info = &ws_info[2] }, { .compatible = "usb-ehci", .info = &ws_info[2] }, { .compatible = "microchip,sama7g5-sdhci", .info = &ws_info[3] }, { .compatible = "microchip,sama7g5-rtt", .info = &ws_info[4] }, #endif }; static bool dev_is_wakeup_source(const void *fdt, int node) { return fdt_get_property(fdt, node, "wakeup-source", NULL); } static int at91_pm_config_ws_ulp1(bool set) { const struct wakeup_source_info *wsi = NULL; const struct wakeup_src *wsrc = NULL; unsigned int polarity = 0; unsigned int mode = 0; unsigned int val = 0; unsigned int src = 0; int node = 0; if (!set) { io_write32(soc_pm.pmc + AT91_PMC_FSMR, mode); return TEE_SUCCESS; } at91_sam_config_shdwc_ws(soc_pm.shdwc, &mode, &polarity); val = io_read32(soc_pm.shdwc + AT91_SHDW_MR); /* Loop through defined wakeup sources. */ for (src = 0; src < ARRAY_SIZE(sam_ws_ids); src++) { wsrc = &sam_ws_ids[src]; wsi = wsrc->info; node = fdt_node_offset_by_compatible(soc_pm.fdt, -1, wsrc->compatible); while (node >= 0) { if (dev_is_wakeup_source(soc_pm.fdt, node)) { /* Check if enabled on SHDWC. */ if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit)) goto next_node; mode |= wsi->pmc_fsmr_bit; if (wsi->set_polarity) polarity |= wsi->pmc_fsmr_bit; } next_node: node = fdt_node_offset_by_compatible(soc_pm.fdt, node, wsrc->compatible); } } if (!mode) { EMSG("AT91: PM: no ULP1 wakeup sources found!"); return TEE_ERROR_BAD_STATE; } at91_sam_config_pmc_ws(soc_pm.pmc, mode, polarity); return TEE_SUCCESS; } /* * Verify that all the clocks are correct before entering * slow-clock mode. */ static bool at91_pm_verify_clocks(void) { int i = 0; uint32_t scsr = 0; scsr = io_read32(soc_pm.pmc + AT91_PMC_SCSR); /* USB must not be using PLLB */ if ((scsr & (AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP)) != 0) { EMSG("AT91: PM - Suspend-to-RAM with USB still active"); return false; } /* PCK0..PCKx must be disabled, or configured to use clk32k */ for (i = 0; i < AT91_PMC_PCK_COUNT; i++) { uint32_t css = 0; if ((scsr & (AT91_PMC_PCK0 << i)) == 0) continue; css = io_read32(soc_pm.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS; if (css != AT91_PMC_CSS_SLOW) { EMSG("AT91: PM - Suspend-to-RAM with PCK%d src %"PRId32, i, css); return false; } } return true; } static TEE_Result at91_write_backup_data(void) { uint32_t val = 0; while (true) { val = io_read32(soc_pm.secumod + AT91_SECUMOD_RAMRDY); if (val & AT91_SECUMOD_RAMRDY_READY) break; } io_write32((vaddr_t)&at91bootstrap_bu->suspended, 1); io_write32((vaddr_t)&at91bootstrap_bu->canary, virt_to_phys(&canary)); io_write32((vaddr_t)&at91bootstrap_bu->resume, virt_to_phys((void *)(vaddr_t)at91_pm_cpu_resume)); return TEE_SUCCESS; } static TEE_Result at91_enter_backup(void) { int ret = -1; TEE_Result res = TEE_ERROR_GENERIC; res = at91_write_backup_data(); if (res) return res; pm_change_state(PM_OP_SUSPEND, 0); ret = sm_pm_cpu_suspend((uint32_t)&soc_pm, (void *)at91_suspend_sram_fn); if (ret < 0) { DMSG("Suspend failed"); res = TEE_ERROR_BAD_STATE; } else { res = TEE_SUCCESS; } pm_change_state(PM_OP_RESUME, 0); if (res) return res; /* SRAM content is lost after resume */ at91_pm_copy_suspend_to_sram(); return TEE_SUCCESS; } TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t sctlr = 0; DMSG("Entering suspend mode %d", soc_pm.mode); if (soc_pm.mode >= AT91_PM_ULP0) { if (!at91_pm_verify_clocks()) return TEE_ERROR_BAD_STATE; } if (soc_pm.mode == AT91_PM_ULP1) at91_pm_config_ws_ulp1(true); sm_save_unbanked_regs(&nsec->ub_regs); /* * In order to run code for low-power out of SRAM without abort, * configure regions with write permission with not forced to * XN (Execute-never) attribute. */ if (IS_ENABLED(CFG_HWSUPP_MEM_PERM_WXN)) { sctlr = read_sctlr(); if (sctlr & SCTLR_WXN) { write_sctlr(sctlr & ~SCTLR_WXN); tlbi_all(); } } if (soc_pm.mode == AT91_PM_BACKUP) { res = at91_enter_backup(); } else { at91_suspend_sram_fn(&soc_pm); res = TEE_SUCCESS; } /* Restore the XN attribute */ if (IS_ENABLED(CFG_HWSUPP_MEM_PERM_WXN)) { if (sctlr & SCTLR_WXN) { write_sctlr(sctlr); tlbi_all(); } } if (soc_pm.mode == AT91_PM_ULP1) at91_pm_config_ws_ulp1(false); sm_restore_unbanked_regs(&nsec->ub_regs); /* * If the system went to backup mode, register state was lost and must * be restored by jumping to the user provided entry point */ if (res == TEE_SUCCESS && soc_pm.mode == AT91_PM_BACKUP) nsec->mon_lr = entry; DMSG("Exiting suspend mode %d, res %"PRIx32, soc_pm.mode, res); return res; } static TEE_Result at91_pm_dt_dram_init(const void *fdt) { const struct { const char *compatible; vaddr_t *address; } dram_map[] = { #ifdef CFG_SAMA5D2 { .compatible = "atmel,sama5d3-ddramc", .address = &soc_pm.ramc, }, #endif #ifdef CFG_SAMA7G5 { .compatible = "microchip,sama7g5-uddrc", .address = &soc_pm.ramc, }, { .compatible = "microchip,sama7g5-ddr3phy", .address = &soc_pm.ramc_phy, }, #endif }; uint32_t i = 0; int node = -1; size_t size = 0; for (i = 0; i < ARRAY_SIZE(dram_map); i++) { node = fdt_node_offset_by_compatible(fdt, -1, dram_map[i].compatible); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; if (dt_map_dev(fdt, node, dram_map[i].address, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static TEE_Result at91_pm_backup_init(const void *fdt) { enum dt_map_dev_directive mapping = DT_MAP_AUTO; int node = -1; size_t size = 0; node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-sfrbu"); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; if (IS_ENABLED(CFG_SAMA7G5)) mapping = DT_MAP_SECURE; if (dt_map_dev(fdt, node, &soc_pm.sfrbu, &size, mapping) < 0) return TEE_ERROR_GENERIC; if (fdt_get_status(fdt, node) == DT_STATUS_OK_SEC) /* for SAMA7G5 SFRBU is always secured, no need to configre */ if (!IS_ENABLED(CFG_SAMA7G5)) matrix_configure_periph_secure(AT91C_ID_SFRBU); return TEE_SUCCESS; } static TEE_Result at91_pm_sram_init(const void *fdt) { int node = -1; size_t size = 0; paddr_t at91_suspend_sram_pbase; size_t suspend_sz = at91_pm_suspend_in_sram_sz; node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-sram"); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_GENERIC; if (dt_map_dev(fdt, node, &at91_suspend_sram_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; at91_suspend_sram_pbase = virt_to_phys((void *)at91_suspend_sram_base); /* * Map the secure ram suspend code with the memory area type * "MEM_AREA_TEE_COHERENT" to make it non-cacheable. * Mapping with memory area type "MEM_AREA_TEE_RAM" would enable * cacheable attribute and might cause abort in some cases. */ at91_suspend_sram_fn = core_mmu_add_mapping(MEM_AREA_TEE_COHERENT, at91_suspend_sram_pbase, suspend_sz); if (!at91_suspend_sram_fn) { EMSG("Failed to remap sram as executable"); return TEE_ERROR_GENERIC; } at91_pm_copy_suspend_to_sram(); return TEE_SUCCESS; } static TEE_Result at91_securam_init(const void *fdt) { int node = -1; size_t size = 0; struct clk *clk = NULL; TEE_Result res = TEE_ERROR_GENERIC; node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-securam"); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_GENERIC; if (dt_map_dev(fdt, node, &soc_pm.securam, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; res = clk_dt_get_by_index(fdt, node, 0, &clk); if (res) return res; if (clk_enable(clk)) return TEE_ERROR_GENERIC; if (size < sizeof(struct at91bootstrap_bu)) return TEE_ERROR_SHORT_BUFFER; at91bootstrap_bu = (void *)soc_pm.securam; node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d2-secumod"); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) return TEE_ERROR_GENERIC; if (dt_map_dev(fdt, node, &soc_pm.secumod, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result sam_pm_init_all(const void *fdt, vaddr_t shdwc) { TEE_Result res = TEE_ERROR_GENERIC; soc_pm.fdt = fdt; soc_pm.shdwc = shdwc; soc_pm.pmc = at91_pmc_get_base(); if (!soc_pm.pmc) return TEE_ERROR_GENERIC; soc_pm.mode = CFG_ATMEL_PM_SUSPEND_MODE; res = at91_securam_init(fdt); if (res) return res; res = at91_pm_dt_dram_init(fdt); if (res) return res; res = at91_pm_backup_init(fdt); if (res) return res; res = at91_pm_sram_init(fdt); if (res) return res; return TEE_SUCCESS; } TEE_Result sam_pm_init(const void *fdt, vaddr_t shdwc) { if (sam_pm_init_all(fdt, shdwc)) panic("Failed to setup PM for this MPU"); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/pm/sam/at91_pm.h000066400000000000000000000014461464416617300206010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Microchip */ #ifndef AT91_PM_H #define AT91_PM_H #define AT91_PM_STANDBY 0x00 #define AT91_PM_ULP0 0x01 #define AT91_PM_ULP0_FAST 0x02 #define AT91_PM_ULP1 0x03 #define AT91_PM_BACKUP 0x04 #ifndef __ASSEMBLER__ #include #include #include #include struct at91_pm_data { vaddr_t shdwc; vaddr_t securam; vaddr_t secumod; vaddr_t sfrbu; vaddr_t pmc; vaddr_t ramc; vaddr_t ramc_phy; unsigned int mode; const void *fdt; }; void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data); void at91_pm_cpu_resume(void); extern uint32_t at91_pm_suspend_in_sram_sz; void at91_pm_resume(struct at91_pm_data *pm_data); #endif /* __ASSEMBLER__ */ #endif /* AT91_PM_H */ optee_os-4.3.0/core/drivers/pm/sam/pm-defines.c000066400000000000000000000011111464416617300213360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include "at91_pm.h" #include #include #include DEFINES { DEFINE(PM_DATA_PMC, offsetof(struct at91_pm_data, pmc)); DEFINE(PM_DATA_RAMC0, offsetof(struct at91_pm_data, ramc)); DEFINE(PM_DATA_RAMC_PHY, offsetof(struct at91_pm_data, ramc_phy)); DEFINE(PM_DATA_MODE, offsetof(struct at91_pm_data, mode)); DEFINE(PM_DATA_SHDWC, offsetof(struct at91_pm_data, shdwc)); DEFINE(PM_DATA_SFRBU, offsetof(struct at91_pm_data, sfrbu)); } optee_os-4.3.0/core/drivers/pm/sam/pm_resume.S000066400000000000000000000004421464416617300212710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Microchip */ #include #include #include FUNC at91_pm_cpu_resume, : UNWIND( .cantunwind) cps #CPSR_MODE_MON blx plat_cpu_reset_early b sm_pm_cpu_resume END_FUNC at91_pm_cpu_resume optee_os-4.3.0/core/drivers/pm/sam/pm_suspend.S000066400000000000000000000534541464416617300214650ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* * This file was imported from Linux arch/arm/mach-at91/pm_suspend.S and * relicensed with dual GPL-2.0/BSD-2-Clause with Microchip agreement. * * Copyright (c) 2021, Microchip */ #include #include #include #include #ifdef CFG_SAMA7G5 #include #else #include #endif #include #include "at91_pm.h" #define SRAMC_SELF_FRESH_ACTIVE 0x01 #define SRAMC_SELF_FRESH_EXIT 0x00 pmc .req r0 tmp1 .req r4 tmp2 .req r5 tmp3 .req r6 /* * Wait until master clock is ready (after switching master clock source) * @r_mckid: register holding master clock identifier * * Side effects: overwrites tmp1 */ .macro wait_mckrdy r_mckid #ifdef CFG_SAMA7G5 cmp \r_mckid, #0 beq 1f 2: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MCKXRDY beq 2b b 3f #endif 1: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MCKRDY beq 1b 3: .endm /* * Wait until master oscillator has stabilized. */ .macro wait_moscrdy 1: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MOSCS beq 1b .endm /* * Wait for main oscillator selection is done */ .macro wait_moscsels 1: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MOSCSELS beq 1b .endm /* * Put the processor to enter the idle state */ .macro at91_cpu_idle mov tmp1, #AT91_PMC_PCK str tmp1, [pmc, #AT91_PMC_SCDR] dsb wfi @ Wait For Interrupt .endm .section .text.psci.suspend .arm #ifdef CFG_SAMA7G5 /* * Enable self-refresh * * Side effects: overwrites tmp1, tmp2, tmp3 */ .macro at91_sramc_self_refresh_ena dsb ldr tmp2, .sramc_base /* Disable all AXI ports. */ ldr tmp1, [tmp2, #UDDRC_PCTRL_0] bic tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_0] ldr tmp1, [tmp2, #UDDRC_PCTRL_1] bic tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_1] ldr tmp1, [tmp2, #UDDRC_PCTRL_2] bic tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_2] ldr tmp1, [tmp2, #UDDRC_PCTRL_3] bic tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_3] ldr tmp1, [tmp2, #UDDRC_PCTRL_4] bic tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_4] sr_ena_1: /* Wait for all ports to disable. */ ldr tmp1, [tmp2, #UDDRC_PSTAT] ldr tmp3, =UDDRC_PSTAT_ALL_PORTS tst tmp1, tmp3 bne sr_ena_1 /* Switch to self-refresh. */ ldr tmp1, [tmp2, #UDDRC_PWRCTL] orr tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW str tmp1, [tmp2, #UDDRC_PWRCTL] sr_ena_2: /* Wait for self-refresh enter. */ ldr tmp1, [tmp2, #UDDRC_STAT] bic tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK cmp tmp1, #UDDRC_STAT_SELFREF_TYPE_SW bne sr_ena_2 ldr tmp2, .sramc_phy_base /* Disable DX DLLs for non-backup modes. */ ldr tmp1, .pm_mode cmp tmp1, #AT91_PM_BACKUP beq sr_ena_3 /* Do not soft reset the AC DLL. */ ldr tmp1, [tmp2, #DDR3PHY_ACDLLCR] bic tmp1, tmp1, #DDR3PHY_ACDLLCR_DLLSRST str tmp1, [tmp2, #DDR3PHY_ACDLLCR] /* Disable DX DLLs. */ ldr tmp1, [tmp2, #DDR3PHY_DX0DLLCR] orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS str tmp1, [tmp2, #DDR3PHY_DX0DLLCR] ldr tmp1, [tmp2, #DDR3PHY_DX1DLLCR] orr tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS str tmp1, [tmp2, #DDR3PHY_DX1DLLCR] sr_ena_3: /* Power down DDR PHY data receivers. */ ldr tmp1, [tmp2, #DDR3PHY_DXCCR] orr tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR str tmp1, [tmp2, #DDR3PHY_DXCCR] /* Power down ADDR/CMD IO. */ ldr tmp1, [tmp2, #DDR3PHY_ACIOCR] orr tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD orr tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0 orr tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0 str tmp1, [tmp2, #DDR3PHY_ACIOCR] /* Power down ODT. */ ldr tmp1, [tmp2, #DDR3PHY_DSGCR] orr tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0 str tmp1, [tmp2, #DDR3PHY_DSGCR] .endm /* * Disable self-refresh * * Side effects: overwrites tmp1, tmp2 */ .macro at91_sramc_self_refresh_dis ldr tmp2, .sramc_phy_base /* Power up DDR PHY data receivers. */ ldr tmp1, [tmp2, #DDR3PHY_DXCCR] bic tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR str tmp1, [tmp2, #DDR3PHY_DXCCR] /* Power up the output of CK and CS pins. */ ldr tmp1, [tmp2, #DDR3PHY_ACIOCR] bic tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD bic tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0 bic tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0 str tmp1, [tmp2, #DDR3PHY_ACIOCR] /* Power up ODT. */ ldr tmp1, [tmp2, #DDR3PHY_DSGCR] bic tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0 str tmp1, [tmp2, #DDR3PHY_DSGCR] /* Enable DX DLLs. */ ldr tmp1, [tmp2, #DDR3PHY_DX0DLLCR] bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS str tmp1, [tmp2, #DDR3PHY_DX0DLLCR] ldr tmp1, [tmp2, #DDR3PHY_DX1DLLCR] bic tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS str tmp1, [tmp2, #DDR3PHY_DX1DLLCR] ldr tmp2, .sramc_base /* Enable quasi-dynamic programming. */ mov tmp1, #0 str tmp1, [tmp2, #UDDRC_SWCTRL] /* De-assert SDRAM initialization. */ ldr tmp1, [tmp2, #UDDRC_DFIMISC] bic tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN str tmp1, [tmp2, #UDDRC_DFIMISC] /* Quasi-dynamic programming done. */ mov tmp1, #UDDRC_SWCTRL_SW_DONE str tmp1, [tmp2, #UDDRC_SWCTRL] sr_dis_1: ldr tmp1, [tmp2, #UDDRC_SWSTAT] tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK beq sr_dis_1 ldr tmp2, .sramc_phy_base /* DLL soft-reset + DLL lock wait + ITM reset */ mov tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \ DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST) str tmp1, [tmp2, #DDR3PHY_PIR] sr_dis_4: /* Wait for it. */ ldr tmp1, [tmp2, #DDR3PHY_PGSR] tst tmp1, #DDR3PHY_PGSR_IDONE beq sr_dis_4 ldr tmp2, .sramc_base /* Enable quasi-dynamic programming. */ mov tmp1, #0 str tmp1, [tmp2, #UDDRC_SWCTRL] /* Assert PHY init complete enable signal. */ ldr tmp1, [tmp2, #UDDRC_DFIMISC] orr tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN str tmp1, [tmp2, #UDDRC_DFIMISC] /* Programming is done. Set sw_done. */ mov tmp1, #UDDRC_SWCTRL_SW_DONE str tmp1, [tmp2, #UDDRC_SWCTRL] sr_dis_5: /* Wait for it. */ ldr tmp1, [tmp2, #UDDRC_SWSTAT] tst tmp1, #UDDRC_SWSTAT_SW_DONE_ACK beq sr_dis_5 /* Trigger self-refresh exit. */ ldr tmp1, [tmp2, #UDDRC_PWRCTL] bic tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW str tmp1, [tmp2, #UDDRC_PWRCTL] sr_dis_6: /* Wait for self-refresh exit done. */ ldr tmp1, [tmp2, #UDDRC_STAT] bic tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK cmp tmp1, #UDDRC_STAT_OPMODE_NORMAL bne sr_dis_6 /* Enable all AXI ports. */ ldr tmp1, [tmp2, #UDDRC_PCTRL_0] orr tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_0] ldr tmp1, [tmp2, #UDDRC_PCTRL_1] orr tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_1] ldr tmp1, [tmp2, #UDDRC_PCTRL_2] orr tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_2] ldr tmp1, [tmp2, #UDDRC_PCTRL_3] orr tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_3] ldr tmp1, [tmp2, #UDDRC_PCTRL_4] orr tmp1, tmp1, #0x1 str tmp1, [tmp2, #UDDRC_PCTRL_4] dsb .endm #endif #define SUSPEND_FUNC(__name) \ __name: #define SUSPEND_END_FUNC(__name) \ .size __name, .-__name .macro check_fit_in_sram since .if (. - \since) > 0x10000 .error "Suspend assembly code exceeds dedicated SRAM size" .endif .endm /* * void at91_suspend_sram_fn(struct at91_pm_data*) * @input param: * @r0: base address of struct at91_pm_data */ .align 3 .global at91_pm_suspend_in_sram SUSPEND_FUNC(at91_pm_suspend_in_sram) /* Save registers on stack */ stmfd sp!, {r4 - r12, lr} /* Drain write buffer */ mov tmp1, #0 mcr p15, 0, tmp1, c7, c10, 4 write_tlbiall isb /* * ldrne below are here to preload their address in the TLB as access * to RAM may be limited while in self-refresh. */ ldr tmp1, [r0, #PM_DATA_PMC] str tmp1, .pmc_base cmp tmp1, #0 ldrne tmp2, [tmp1, #0] ldr tmp1, [r0, #PM_DATA_RAMC0] str tmp1, .sramc_base cmp tmp1, #0 ldrne tmp2, [tmp1, #0] ldr tmp1, [r0, #PM_DATA_RAMC_PHY] str tmp1, .sramc_phy_base cmp tmp1, #0 ldrne tmp2, [tmp1, #0] ldr tmp1, [r0, #PM_DATA_MODE] str tmp1, .pm_mode /* Both ldrne below are here to preload their address in the TLB */ ldr tmp1, [r0, #PM_DATA_SHDWC] str tmp1, .shdwc cmp tmp1, #0 ldrne tmp2, [tmp1, #0] ldr tmp1, [r0, #PM_DATA_SFRBU] str tmp1, .sfrbu cmp tmp1, #0 ldrne tmp2, [tmp1, #0x10] /* Active the self-refresh mode */ #ifdef CFG_SAMA5D2 mov r0, #SRAMC_SELF_FRESH_ACTIVE bl at91_sramc_self_refresh #endif #ifdef CFG_SAMA7G5 at91_sramc_self_refresh_ena #endif ldr r0, .pm_mode cmp r0, #AT91_PM_STANDBY beq standby cmp r0, #AT91_PM_BACKUP beq backup_mode bl at91_ulp_mode b exit_suspend standby: /* Wait for interrupt */ ldr pmc, .pmc_base at91_cpu_idle b exit_suspend backup_mode: bl at91_backup_mode b exit_suspend exit_suspend: /* Exit the self-refresh mode */ #ifdef CFG_SAMA5D2 mov r0, #SRAMC_SELF_FRESH_EXIT bl at91_sramc_self_refresh #endif #ifdef CFG_SAMA7G5 at91_sramc_self_refresh_dis #endif /* Restore registers, and return */ ldmfd sp!, {r4 - r12, pc} SUSPEND_END_FUNC(at91_pm_suspend_in_sram) SUSPEND_FUNC(at91_backup_mode) /* Switch the master clock source to slow clock. */ ldr pmc, .pmc_base ldr tmp1, [pmc, #AT91_PMC_MCKR] bic tmp1, tmp1, #AT91_PMC_CSS str tmp1, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 /*BUMEN*/ ldr r0, .sfrbu mov tmp1, #0x1 str tmp1, [r0, #0x10] /* Shutdown */ ldr r0, .shdwc mov tmp1, #0xA5000000 add tmp1, tmp1, #0x1 #ifdef CFG_SAMA7G5 /* LPM Pad Enable: The LPM pad is set high */ orr tmp1, tmp1, #0x200000 #endif str tmp1, [r0, #0] SUSPEND_END_FUNC(at91_backup_mode) /* * Set LPM * @ena: 0 - disable LPM * 1 - enable LPM * * Side effects: overwrites tmp1, tmp3 */ .macro at91_set_lpm ena #ifdef CFG_SAMA7G5 mov tmp1, #\ena cmp tmp1, #1 movne tmp3, #0x400000 /* LPM Pad Disable: The LPM pad is set low */ moveq tmp3, #0x200000 /* LPM Pad Enable: The LPM pad is set high */ add tmp3, #0xA5000000 ldr tmp1, .shdwc cmp tmp1, #0 strne tmp3, [tmp1] #endif .endm .macro at91_pm_ulp0_mode ldr pmc, .pmc_base ldr tmp2, .pm_mode /* Check if ULP0 fast variant has been requested. */ cmp tmp2, #AT91_PM_ULP0_FAST bne 0f /* Set highest prescaler for power saving */ ldr tmp1, [pmc, #AT91_PMC_MCKR] bic tmp1, tmp1, #AT91_PMC_PRES orr tmp1, tmp1, #AT91_PMC_PRES_64 str tmp1, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 b 1f 0: /* Turn off the crystal oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] bic tmp1, tmp1, #AT91_PMC_MOSCEN orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Save RC oscillator state */ ldr tmp1, [pmc, #AT91_PMC_SR] str tmp1, .saved_osc_status tst tmp1, #AT91_PMC_MOSCRCS bne 7f /* Turn off RC oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] bic tmp1, tmp1, #AT91_PMC_MOSCRCEN bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Wait main RC disabled done */ 2: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MOSCRCS bne 2b /* Enable LPM. */ 7: at91_set_lpm 1 /* Wait for interrupt */ 1: at91_cpu_idle /* Check if ULP0 fast variant has been requested. */ cmp tmp2, #AT91_PM_ULP0_FAST bne 8f /* Set lowest prescaler for fast resume. */ ldr tmp1, [pmc, #AT91_PMC_MCKR] bic tmp1, tmp1, #AT91_PMC_PRES str tmp1, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 b 6f 8: at91_set_lpm 0 5: /* Restore RC oscillator state */ ldr tmp1, .saved_osc_status tst tmp1, #AT91_PMC_MOSCRCS beq 4f /* Turn on RC oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCRCEN bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Wait main RC stabilization */ 3: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MOSCRCS beq 3b /* Turn on the crystal oscillator */ 4: ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCEN orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] wait_moscrdy 6: .endm /** * Note: This procedure only applies on the platform which uses * the external crystal oscillator as a main clock source. */ .macro at91_pm_ulp1_mode ldr pmc, .pmc_base /* Save RC oscillator state and check if it is enabled. */ ldr tmp1, [pmc, #AT91_PMC_SR] str tmp1, .saved_osc_status tst tmp1, #AT91_PMC_MOSCRCS bne 2f /* Enable RC oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCRCEN bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Wait main RC stabilization */ 1: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MOSCRCS beq 1b /* Switch the main clock source to 12-MHz RC oscillator */ 2: ldr tmp1, [pmc, #AT91_CKGR_MOR] bic tmp1, tmp1, #AT91_PMC_MOSCSEL bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] wait_moscsels /* Disable the crystal oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] bic tmp1, tmp1, #AT91_PMC_MOSCEN bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Switch the master clock source to main clock */ ldr tmp1, [pmc, #AT91_PMC_MCKR] bic tmp1, tmp1, #AT91_PMC_CSS orr tmp1, tmp1, #AT91_PMC_CSS_MAIN str tmp1, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 /* Enable LPM */ at91_set_lpm 1 /* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_WAITMODE bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Quirk for SAM9X60's PMC */ nop nop mov tmp3, #0 wait_mckrdy tmp3 /* Disable LPM. */ at91_set_lpm 0 /* Enable the crystal oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCEN bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] wait_moscrdy /* Switch the master clock source to slow clock */ ldr tmp1, [pmc, #AT91_PMC_MCKR] bic tmp1, tmp1, #AT91_PMC_CSS str tmp1, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 /* Switch main clock source to crystal oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] orr tmp1, tmp1, #AT91_PMC_MOSCSEL bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] wait_moscsels /* Switch the master clock source to main clock */ ldr tmp1, [pmc, #AT91_PMC_MCKR] bic tmp1, tmp1, #AT91_PMC_CSS orr tmp1, tmp1, #AT91_PMC_CSS_MAIN str tmp1, [pmc, #AT91_PMC_MCKR] wait_mckrdy tmp3 /* Restore RC oscillator state */ ldr tmp1, .saved_osc_status tst tmp1, #AT91_PMC_MOSCRCS bne 3f /* Disable RC oscillator */ ldr tmp1, [pmc, #AT91_CKGR_MOR] bic tmp1, tmp1, #AT91_PMC_MOSCRCEN bic tmp1, tmp1, #AT91_PMC_KEY_MASK orr tmp1, tmp1, #AT91_PMC_KEY str tmp1, [pmc, #AT91_CKGR_MOR] /* Wait RC oscillator disable done */ 4: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_MOSCRCS bne 4b 3: .endm /* * Save PLLA setting and disable it * * Side effects: overwrites tmp1, tmp2 */ .macro at91_plla_disable #ifdef CFG_SAMA7G5 /* Save PLLA settings */ ldr tmp2, [pmc, #AT91_PMC_PLL_UPDT] bic tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID str tmp2, [pmc, #AT91_PMC_PLL_UPDT] /* save div */ mov tmp1, #0 ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL0] bic tmp2, tmp2, #0xffffff00 orr tmp1, tmp1, tmp2 /* save mul */ ldr tmp2, [pmc, #AT91_PMC_PLL_CTRL1] bic tmp2, tmp2, #0xffffff orr tmp1, tmp1, tmp2 str tmp1, .saved_pllar /* step 2 */ ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID str tmp1, [pmc, #AT91_PMC_PLL_UPDT] /* step 3 */ ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] /* step 4 */ ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID str tmp1, [pmc, #AT91_PMC_PLL_UPDT] /* step 5 */ ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] bic tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] /* step 6 */ ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID str tmp1, [pmc, #AT91_PMC_PLL_UPDT] #else /* Save PLLA setting and disable it */ ldr tmp1, [pmc, #AT91_CKGR_PLLAR] str tmp1, .saved_pllar /* Disable PLLA. */ mov tmp1, #AT91_PMC_PLLCOUNT orr tmp1, tmp1, #(1 << 29) /* bit 29 always set */ str tmp1, [pmc, #AT91_CKGR_PLLAR] #endif 2: .endm /* * Enable PLLA with the saved setting * * Side effects: overwrites tmp1, tmp2 */ .macro at91_plla_enable #ifdef CFG_SAMA7G5 /* step 1 */ ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE str tmp1, [pmc, #AT91_PMC_PLL_UPDT] /* step 2 */ ldr tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA str tmp1, [pmc, #AT91_PMC_PLL_ACR] /* step 3 */ ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL1] ldr tmp2, .saved_pllar bic tmp2, tmp2, #0xffffff orr tmp1, tmp1, tmp2 str tmp1, [pmc, #AT91_PMC_PLL_CTRL1] /* step 4 */ ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE str tmp1, [pmc, #AT91_PMC_PLL_UPDT] /* step 5 */ ldr tmp1, [pmc, #AT91_PMC_PLL_CTRL0] orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL orr tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK bic tmp1, tmp1, #0xff ldr tmp2, .saved_pllar bic tmp2, tmp2, #0xffffff00 orr tmp1, tmp1, tmp2 str tmp1, [pmc, #AT91_PMC_PLL_CTRL0] /* step 6 */ ldr tmp1, [pmc, #AT91_PMC_PLL_UPDT] orr tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE bic tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID str tmp1, [pmc, #AT91_PMC_PLL_UPDT] /* step 7 */ 3: ldr tmp1, [pmc, #AT91_PMC_PLL_ISR0] tst tmp1, #0x1 beq 3b #else ldr tmp2, .saved_pllar /* Restore PLLA setting */ str tmp2, [pmc, #AT91_CKGR_PLLAR] /* Enable PLLA. */ tst tmp2, #(AT91_PMC_MUL & 0xff0000) bne 1f tst tmp2, #(AT91_PMC_MUL & ~0xff0000) beq 2f 1: ldr tmp1, [pmc, #AT91_PMC_SR] tst tmp1, #AT91_PMC_LOCKA beq 1b 2: #endif .endm #ifdef CFG_SAMA7G5 /* * at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock * * Side effects: overwrites tmp1, tmp2, tmp3 */ .macro at91_mckx_ps_enable ldr pmc, .pmc_base /* There are 4 MCKs we need to handle: MCK1..4 */ mov tmp1, #1 e_loop: /* Write MCK ID to retrieve the settings */ str tmp1, [pmc, #AT91_PMC_MCR_V2] ldr tmp2, [pmc, #AT91_PMC_MCR_V2] cmp tmp1, #1 streq tmp2, .saved_mck1 cmp tmp1, #2 streq tmp2, .saved_mck2 cmp tmp1, #3 streq tmp2, .saved_mck3 cmp tmp1, #4 streq tmp2, .saved_mck4 /* Use CSS=MD_SLOW_CLK and DIV=64. */ bic tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK bic tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK orr tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK orr tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64 orr tmp2, tmp2, #AT91_PMC_MCR_V2_CMD str tmp2, [pmc, #AT91_PMC_MCR_V2] mov tmp2, tmp1 wait_mckrdy tmp1 mov tmp1, tmp2 add tmp1, tmp1, #1 cmp tmp1, #5 bne e_loop .endm /* * at91_mckx_ps_restore: restore MCK1..4 settings * * Side effects: overwrites tmp1, tmp2, tmp3 */ .macro at91_mckx_ps_restore ldr pmc, .pmc_base /* There are 4 MCKs we need to handle: MCK1..4 */ mov tmp1, #1 ldr tmp2, .saved_mck1 r_loop: cmp tmp1, #2 ldreq tmp2, .saved_mck2 cmp tmp1, #3 ldreq tmp2, .saved_mck3 cmp tmp1, #4 ldreq tmp2, .saved_mck4 /* Write MCK ID to retrieve the settings */ str tmp1, [pmc, #AT91_PMC_MCR_V2] ldr tmp3, [pmc, #AT91_PMC_MCR_V2] /* We need to restore CSS and DIV. */ bic tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK bic tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK orr tmp3, tmp3, tmp2 bic tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK orr tmp3, tmp3, tmp1 orr tmp3, tmp3, #AT91_PMC_MCR_V2_CMD str tmp3, [pmc, #AT91_PMC_MCR_V2] mov tmp2, tmp1 wait_mckrdy tmp1 mov tmp1, tmp2 add tmp1, tmp1, #1 cmp tmp1, #5 bne r_loop .endm #endif SUSPEND_FUNC(at91_ulp_mode) #ifdef CFG_SAMA7G5 at91_mckx_ps_enable #endif ldr pmc, .pmc_base ldr tmp3, .pm_mode /* Save Master clock setting */ ldr tmp1, [pmc, #AT91_PMC_MCKR] str tmp1, .saved_mckr /* * Set master clock source to: * - MAINCK if using ULP0 fast variant * - slow clock, otherwise */ bic tmp1, tmp1, #AT91_PMC_CSS cmp tmp3, #AT91_PM_ULP0_FAST bne save_mck orr tmp1, tmp1, #AT91_PMC_CSS_MAIN save_mck: str tmp1, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 at91_plla_disable ldr tmp3, .pm_mode cmp tmp3, #AT91_PM_ULP1 beq ulp1_mode at91_pm_ulp0_mode b ulp_exit ulp1_mode: at91_pm_ulp1_mode b ulp_exit ulp_exit: ldr pmc, .pmc_base at91_plla_enable /* * Restore master clock setting */ ldr tmp2, .saved_mckr str tmp2, [pmc, #AT91_PMC_MCKR] mov tmp3, #0 wait_mckrdy tmp3 #ifdef CFG_SAMA7G5 at91_mckx_ps_restore #endif mov pc, lr SUSPEND_END_FUNC(at91_ulp_mode) #ifdef CFG_SAMA5D2 /* * void at91_sramc_self_refresh(unsigned int is_active) * * @input param: * @r0: 1 - active self-refresh mode * 0 - exit self-refresh mode * register usage: * @r2: base address of the sram controller */ SUSPEND_FUNC(at91_sramc_self_refresh) ldr r2, .sramc_base /* * DDR Memory controller */ tst r0, #SRAMC_SELF_FRESH_ACTIVE beq ddrc_exit_sf /* LPDDR1 --> force DDR2 mode during self-refresh */ ldr r3, [r2, #AT91_DDRSDRC_MDR] str r3, .saved_sam9_mdr bic r3, r3, #~AT91_DDRSDRC_MD cmp r3, #AT91_DDRSDRC_MD_LOW_POWER_DDR ldreq r3, [r2, #AT91_DDRSDRC_MDR] biceq r3, r3, #AT91_DDRSDRC_MD orreq r3, r3, #AT91_DDRSDRC_MD_DDR2 streq r3, [r2, #AT91_DDRSDRC_MDR] /* Active DDRC self-refresh mode */ ldr r3, [r2, #AT91_DDRSDRC_LPR] str r3, .saved_sam9_lpr bic r3, r3, #AT91_DDRSDRC_LPCB orr r3, r3, #AT91_DDRSDRC_LPCB_SELF_REFRESH str r3, [r2, #AT91_DDRSDRC_LPR] b exit_sramc_sf ddrc_exit_sf: /* Restore MDR in case of LPDDR1 */ ldr r3, .saved_sam9_mdr str r3, [r2, #AT91_DDRSDRC_MDR] /* Restore LPR on AT91 with DDRAM */ ldr r3, .saved_sam9_lpr str r3, [r2, #AT91_DDRSDRC_LPR] exit_sramc_sf: mov pc, lr SUSPEND_END_FUNC(at91_sramc_self_refresh) #endif .pmc_base: .word 0 .sramc_base: .word 0 .sramc_phy_base: .word 0 .shdwc: .word 0 .sfrbu: .word 0 .pm_mode: .word 0 .saved_mckr: .word 0 .saved_pllar: .word 0 .saved_sam9_lpr: .word 0 .saved_sam9_mdr: .word 0 .saved_osc_status: .word 0 #ifdef CFG_SAMA7G5 .saved_mck1: .word 0 .saved_mck2: .word 0 .saved_mck3: .word 0 .saved_mck4: .word 0 #endif .global at91_pm_suspend_in_sram_sz at91_pm_suspend_in_sram_sz: .word .-at91_pm_suspend_in_sram check_fit_in_sram at91_pm_suspend_in_sram optee_os-4.3.0/core/drivers/pm/sam/sub.mk000066400000000000000000000001121464416617300202650ustar00rootroot00000000000000srcs-y += at91_pm.c pm_suspend.S pm_resume.S asm-defines-y += pm-defines.coptee_os-4.3.0/core/drivers/pm/sub.mk000066400000000000000000000000741464416617300175140ustar00rootroot00000000000000subdirs-$(CFG_ATMEL_PM) += sam subdirs-$(CFG_IMX_PM) += imx optee_os-4.3.0/core/drivers/regulator/000077500000000000000000000000001464416617300177615ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/regulator/regulator.c000066400000000000000000000273261464416617300221430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static SLIST_HEAD(, regulator) regulator_device_list = SLIST_HEAD_INITIALIZER(regulator); /* Access protection mutex complying the power state transitions context */ static void lock_regulator(struct regulator *regulator) { mutex_pm_aware_lock(®ulator->mutex); } static void unlock_regulator(struct regulator *regulator) { mutex_pm_aware_unlock(®ulator->mutex); } static TEE_Result set_state(struct regulator *regulator, bool on_not_off) { if (!regulator->ops->set_state) return TEE_SUCCESS; return regulator->ops->set_state(regulator, on_not_off); } static TEE_Result regulator_refcnt_enable(struct regulator *regulator) { TEE_Result res = TEE_ERROR_GENERIC; FMSG("%s", regulator_name(regulator)); if (regulator->supply) { res = regulator_enable(regulator->supply); if (res) return res; } lock_regulator(regulator); if (!regulator->refcount) { res = set_state(regulator, true); if (res) { EMSG("regul %s set state failed with %#"PRIx32, regulator_name(regulator), res); unlock_regulator(regulator); if (regulator->supply && regulator_disable(regulator->supply)) panic(); return res; } } regulator->refcount++; if (!regulator->refcount) panic(); FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount); unlock_regulator(regulator); return TEE_SUCCESS; } TEE_Result regulator_enable(struct regulator *regulator) { assert(regulator); FMSG("%s", regulator_name(regulator)); if (regulator_is_always_on(regulator)) return TEE_SUCCESS; return regulator_refcnt_enable(regulator); } static TEE_Result regulator_refcnt_disable(struct regulator *regulator) { FMSG("%s", regulator_name(regulator)); lock_regulator(regulator); if (regulator->refcount == 1) { TEE_Result res = set_state(regulator, false); if (res) { EMSG("regul %s set state failed with %#"PRIx32, regulator_name(regulator), res); unlock_regulator(regulator); return res; } } if (!regulator->refcount) { EMSG("Unbalanced %s", regulator_name(regulator)); panic(); } regulator->refcount--; FMSG("%s refcount: %u", regulator_name(regulator), regulator->refcount); unlock_regulator(regulator); if (regulator->supply && regulator_disable(regulator->supply)) { /* We can't leave this unbalanced */ EMSG("Can't disable %s", regulator_name(regulator->supply)); panic(); } return TEE_SUCCESS; } TEE_Result regulator_disable(struct regulator *regulator) { assert(regulator); FMSG("%s", regulator_name(regulator)); if (regulator_is_always_on(regulator)) return TEE_SUCCESS; return regulator_refcnt_disable(regulator); } bool regulator_is_enabled(struct regulator *regulator) { TEE_Result res = TEE_SUCCESS; bool enabled = false; if (!regulator->ops->get_state) return true; lock_regulator(regulator); res = regulator->ops->get_state(regulator, &enabled); unlock_regulator(regulator); if (res) EMSG("regul %s get state failed with %#"PRIx32, regulator_name(regulator), res); return !res && enabled; } int regulator_get_voltage(struct regulator *regulator) { TEE_Result res = TEE_SUCCESS; int level_uv = regulator->min_uv; if (regulator->ops->get_voltage) { res = regulator->ops->get_voltage(regulator, &level_uv); if (res) { EMSG("%s get_voltage failed with %#"PRIx32, regulator_name(regulator), res); level_uv = 0; } } return level_uv; } TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv) { TEE_Result res = TEE_ERROR_GENERIC; int cur_uv = 0; assert(regulator); FMSG("%s %duV", regulator_name(regulator), level_uv); if (level_uv < regulator->min_uv || level_uv > regulator->max_uv) return TEE_ERROR_BAD_PARAMETERS; cur_uv = regulator_get_voltage(regulator); if (level_uv == cur_uv) return TEE_SUCCESS; if (!regulator->ops->set_voltage) return TEE_ERROR_NOT_SUPPORTED; lock_regulator(regulator); res = regulator->ops->set_voltage(regulator, level_uv); unlock_regulator(regulator); if (res) { EMSG("regul %s set volt failed with %#"PRIx32, regulator_name(regulator), res); return res; } return TEE_SUCCESS; } TEE_Result regulator_supported_voltages(struct regulator *regulator, struct regulator_voltages_desc **desc, const int **levels) { TEE_Result res = TEE_ERROR_NOT_SUPPORTED; assert(regulator && desc && levels); if (regulator->ops->supported_voltages) res = regulator->ops->supported_voltages(regulator, desc, levels); if (res == TEE_ERROR_NOT_SUPPORTED) { *desc = ®ulator->voltages_fallback.desc; *levels = regulator->voltages_fallback.levels; } else if (res) { return res; } if ((*desc)->type == VOLTAGE_TYPE_FULL_LIST) { assert((*desc)->num_levels); assert((*levels)[0] >= regulator->min_uv); assert((*levels)[(*desc)->num_levels - 1] <= regulator->max_uv); } else if ((*desc)->type == VOLTAGE_TYPE_INCREMENT) { assert((*levels)[0] >= regulator->min_uv); assert((*levels)[1] <= regulator->max_uv); } else { assert(0); } return TEE_SUCCESS; } TEE_Result regulator_register(struct regulator *regulator) { TEE_Result res = TEE_SUCCESS; int min_uv = 0; int max_uv = 0; int uv = 0; if (!regulator || !regulator->ops || regulator->flags & ~REGULATOR_FLAGS_MASK) return TEE_ERROR_BAD_PARAMETERS; mutex_pm_aware_init(®ulator->mutex); regulator_get_range(regulator, &min_uv, &max_uv); if (min_uv > max_uv) return TEE_ERROR_BAD_PARAMETERS; /* Sanitize regulator effective level */ uv = regulator_get_voltage(regulator); if (uv < min_uv || uv > max_uv) { res = regulator_set_voltage(regulator, min_uv); if (res) return res; } /* Unbalanced enable refcount to keep always-on regulators enabled */ if (regulator_is_always_on(regulator)) { res = regulator_refcnt_enable(regulator); if (res) return res; } /* Preset voltage list in case ops::supported_voltages is NULL */ if (regulator->min_uv == regulator->max_uv) { regulator->voltages_fallback.desc.type = VOLTAGE_TYPE_FULL_LIST; regulator->voltages_fallback.desc.num_levels = 1; regulator->voltages_fallback.levels[0] = regulator->min_uv; } else { regulator->voltages_fallback.desc.type = VOLTAGE_TYPE_INCREMENT; regulator->voltages_fallback.levels[0] = regulator->min_uv; regulator->voltages_fallback.levels[1] = regulator->max_uv; regulator->voltages_fallback.levels[2] = 1; } SLIST_INSERT_HEAD(®ulator_device_list, regulator, link); return TEE_SUCCESS; } /* * Clean-up regulators that are not used. */ static TEE_Result regulator_core_cleanup(void) { struct regulator *regulator = NULL; SLIST_FOREACH(regulator, ®ulator_device_list, link) { if (!regulator->refcount) { DMSG("disable %s", regulator_name(regulator)); lock_regulator(regulator); set_state(regulator, false /* disable */); unlock_regulator(regulator); } } regulator_print_tree(); return TEE_SUCCESS; } release_init_resource(regulator_core_cleanup); /* Return updated message buffer position of NULL on failure */ static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...) { va_list ap = { }; int max_len = end - cur; int ret = 0; va_start(ap, fmt); ret = vsnprintf(cur, max_len, fmt, ap); va_end(ap); if (ret < 0 || ret >= max_len) return NULL; return cur + ret; } static struct regulator *find_next_regulator(struct regulator *parent, struct regulator *sibling) { struct regulator *regulator = NULL; if (sibling) regulator = SLIST_NEXT(sibling, link); else regulator = SLIST_FIRST(®ulator_device_list); while (regulator && regulator->supply != parent) regulator = SLIST_NEXT(regulator, link); return regulator; } /* Regulator is the last supplied one by its supply in the registered list */ static bool regulator_is_supply_last_supplied(struct regulator *regulator) { return !find_next_regulator(regulator->supply, regulator); } /* Supply last node may already be printed for indentation level @cur_indent */ static bool indent_with_empty_string(struct regulator *node_regulator, int node_indent, int cur_indent) { struct regulator *r = node_regulator; int n = 0; /* Find supply at indentation level @node_indent - @cur_indent - 1 */ for (n = 0; n < node_indent - cur_indent - 1; n++) r = r->supply; return regulator_is_supply_last_supplied(r); } static void __maybe_unused print_regulator(struct regulator *regulator, int indent) { static const char * const level_unit[] = { "uV", "mV", "V" }; int max_unit = ARRAY_SIZE(level_unit); int level_max = 0; int level_min = 0; int level_cur = 0; char msg_buf[128] = { }; char *msg_end = msg_buf + sizeof(msg_buf); char *msg = msg_buf; int n_max = 0; int n_min = 0; int n_cur = 0; int n = 0; if (indent) { /* Indent for root clock level */ msg = add_msg(msg, msg_end, " "); if (!msg) goto out; /* Indent for root supply to regulator supply levels */ for (n = 0; n < indent - 1; n++) { if (indent_with_empty_string(regulator, indent, n)) msg = add_msg(msg, msg_end, " "); else msg = add_msg(msg, msg_end, "| "); if (!msg) goto out; } /* Regulator indentation */ if (regulator_is_supply_last_supplied(regulator)) msg = add_msg(msg, msg_end, "`-- "); else msg = add_msg(msg, msg_end, "|-- "); if (!msg) goto out; } else { /* Root supply indentation */ msg = add_msg(msg, msg_end, "o- "); } regulator_get_range(regulator, &level_min, &level_max); level_cur = regulator_get_voltage(regulator); for (n_cur = 1; !(level_cur % 1000) && n_cur < max_unit; n_cur++) level_cur /= 1000; for (n_max = 1; !(level_max % 1000) && n_max < max_unit; n_max++) level_max /= 1000; for (n_min = 1; !(level_min % 1000) && n_min < max_unit; n_min++) level_min /= 1000; msg = add_msg(msg, msg_end, "%s \t(%3s / refcnt %u / flags %#"PRIx32 " / %d %s ", regulator_name(regulator), regulator_is_enabled(regulator) ? "on " : "off", regulator->refcount, regulator->flags, level_cur, level_unit[n_cur - 1]); if (!msg) goto out; if (level_min == level_max) msg = add_msg(msg, msg_end, "fixed)"); else if (level_max == INT_MAX) msg = add_msg(msg, msg_end, "[%d %s .. MAX])", level_min, level_unit[n_min - 1]); else msg = add_msg(msg, msg_end, "[%d %s .. %d %s])", level_min, level_unit[n_min - 1], level_max, level_unit[n_max - 1]); out: if (!msg) snprintf(msg_end - 4, 4, "..."); DMSG("%s", msg_buf); } static void print_tree(void) { struct regulator *regulator = NULL; struct regulator *parent = NULL; struct regulator *next = NULL; int indent = -1; while (true) { next = find_next_regulator(parent, regulator); if (next) { print_regulator(next, indent + 1); /* Enter the subtree of the next regulator */ parent = next; indent++; regulator = NULL; } else { /* * We've processed all children at this level. * If parent is NULL we're at the top and are done. */ if (!parent) break; /* * Move up one level to resume with the next * regulator of the parent. */ regulator = parent; parent = regulator->supply; indent--; } } } void regulator_print_tree(void) { if (IS_ENABLED(CFG_DRIVERS_REGULATOR_PRINT_TREE) && TRACE_LEVEL >= TRACE_DEBUG) { DMSG("Regulator tree summary"); if (SLIST_EMPTY(®ulator_device_list)) DMSG("-- No registered regulator"); else print_tree(); } } optee_os-4.3.0/core/drivers/regulator/regulator_dt.c000066400000000000000000000243601464416617300226250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* * struct regulator_property - DT binding boolean property names * @name: Property name in the regulator DT node * @flag: Mask of the related REGULATOR_* boolean property */ struct regulator_property { const char *name; unsigned int flag; }; static struct regulator_property flag_prop[] = { { .name = "regulator-always-on", .flag = REGULATOR_ALWAYS_ON, }, { .name = "regulator-pull-down", .flag = REGULATOR_PULL_DOWN, }, { .name = "regulator-boot-on", .flag = REGULATOR_BOOT_ON, }, }; /* * struct pending_regu - Regulators waiting for their supply to be ready * * @fdt: DT to work on * @node: Node of the regulator in @fdt * @supply_phandle: Phandle in @fdt of the regulator supply, or 0 if no supply * @regulator_allocated: True if framework allocates and frees @regulator * @regulator: Regulator device instance * @link: Link in pending regulators list * * When calling regulator_dt_register(), either the regulator depends on a * supply that is not initialized, or this dependency is resolved (there is * no supply or the supply is ready to use). * * In the former case, the regulator is placed in a pending regulator list. * Each time a new regulator is successfully registered, we process the * pending regulator list in case some pending regulators find their * supply and finalize their registration and initialization. * * In the latter case, the regulator registration and initialization * are processed. */ struct pending_regu { const void *fdt; int node; int supply_phandle; bool regulator_allocated; struct regulator *regulator; SLIST_ENTRY(pending_regu) link; }; static SLIST_HEAD(, pending_regu) pending_regu_list = SLIST_HEAD_INITIALIZER(pending_regu); /* Helper to find the phandle of a regulator supply */ static TEE_Result get_supply_phandle(const void *fdt, int node, const char *supply_name, uint32_t *supply_phandle) { char *supply_prop = NULL; size_t prop_len = 0; const fdt32_t *cuint = NULL; int len = 0; prop_len = strlen(supply_name) + strlen("-supply") + 1; supply_prop = calloc(1, prop_len); if (!supply_prop) return TEE_ERROR_OUT_OF_MEMORY; len = snprintf(supply_prop, prop_len, "%s-supply", supply_name); assert(len > 0 && (size_t)len == prop_len - 1); cuint = fdt_getprop(fdt, node, supply_prop, &len); free(supply_prop); if (!cuint || (size_t)len != sizeof(*cuint)) { if (len != -FDT_ERR_NOTFOUND) return TEE_ERROR_GENERIC; *supply_phandle = 0; return TEE_SUCCESS; } *supply_phandle = fdt32_to_cpu(*cuint); assert(*supply_phandle); return TEE_SUCCESS; } TEE_Result regulator_dt_get_supply(const void *fdt, int node, const char *supply_name, struct regulator **regulator) { struct dt_driver_provider *provider = NULL; TEE_Result res = TEE_ERROR_GENERIC; uint32_t supply_phandle = 0; res = get_supply_phandle(fdt, node, supply_name, &supply_phandle); if (res) return res; provider = dt_driver_get_provider_by_phandle(supply_phandle, DT_DRIVER_REGULATOR); if (!provider) return TEE_ERROR_DEFER_DRIVER_INIT; *regulator = dt_driver_provider_priv_data(provider); assert(*regulator); return TEE_SUCCESS; } /* Helper function to register a regulator provider instance */ static TEE_Result regulator_register_provider(const void *fdt, int node, struct regulator *regulator) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t phandle = 0; phandle = fdt_get_phandle(fdt, node); switch (phandle) { case 0: /* We can ignore regulators without any phandle */ return TEE_SUCCESS; case (uint32_t)-1: DMSG("Failed to find provider phandle"); return TEE_ERROR_GENERIC; default: res = dt_driver_register_provider(fdt, node, NULL, regulator, DT_DRIVER_REGULATOR); if (res) EMSG("Can't register regulator provider %s: %#"PRIx32, regulator_name(regulator), res); return res; } } static TEE_Result register_final(const void *fdt, int node, struct regulator *regulator) { TEE_Result res = TEE_ERROR_GENERIC; FMSG("Regulator: finalize %s registering", regulator_name(regulator)); res = regulator_register(regulator); if (res) return res; if (regulator->ops->supplied_init) { res = regulator->ops->supplied_init(regulator, fdt, node); if (res) return res; } return regulator_register_provider(fdt, node, regulator); } /* * Pending regulators list: stores all regulator devices registered by their * driver but not yet available to consumers as their dependency on their * regulator supply is not yet resolved (supply has not been initialized yet). */ static void __maybe_unused print_pending_regulators(void) { struct pending_regu *pending = NULL; SLIST_FOREACH(pending, &pending_regu_list, link) DMSG("Pending regulator %s", regulator_name(pending->regulator)); } /* * Returns true if at least 1 regulator found its supply and finalized its * registration. */ static bool process_pending_list(void) { struct dt_driver_provider *p = NULL; struct pending_regu *pending = NULL; struct pending_regu *next = NULL; bool supplied = false; SLIST_FOREACH_SAFE(pending, &pending_regu_list, link, next) { p = dt_driver_get_provider_by_phandle(pending->supply_phandle, DT_DRIVER_REGULATOR); if (!p) continue; pending->regulator->supply = dt_driver_provider_priv_data(p); if (register_final(pending->fdt, pending->node, pending->regulator)) panic(); SLIST_REMOVE(&pending_regu_list, pending, pending_regu, link); free(pending); supplied = true; } return supplied; } /* * Attempt to register pending regulators once their supply is found. * Return true if pending regulator list is empty upon processing. */ static bool resolve_pending_list(void) { while (process_pending_list()) ; return SLIST_EMPTY(&pending_regu_list); } /* Adds a regulator to the pending list: those waiting for their supply */ static TEE_Result add_to_pending_list(const void *fdt, int node, struct regulator *regulator, uint32_t supply_phandle, bool regulator_allocated) { struct pending_regu *pending = NULL; pending = calloc(1, sizeof(*pending)); if (!pending) return TEE_ERROR_OUT_OF_MEMORY; *pending = (struct pending_regu){ .fdt = fdt, .node = node, .supply_phandle = supply_phandle, .regulator = regulator, .regulator_allocated = regulator_allocated, }; SLIST_INSERT_HEAD(&pending_regu_list, pending, link); return TEE_SUCCESS; } static TEE_Result parse_dt(const void *fdt, int node, struct regulator *regulator) { struct regulator_property *fp = NULL; const fdt32_t *cuint = NULL; int len = 0; FMSG("Regulator: parse DT node %s", fdt_get_name(fdt, node, NULL)); cuint = fdt_getprop(fdt, node, "regulator-name", NULL); if (cuint) { /* Replace name with the one found from the DT node */ char *name = (char *)cuint; free(regulator->name); regulator->name = strdup(name); if (!regulator->name) return TEE_ERROR_OUT_OF_MEMORY; } for (fp = flag_prop; fp < (flag_prop + ARRAY_SIZE(flag_prop)); fp++) if (fdt_getprop(fdt, node, fp->name, NULL)) regulator->flags |= fp->flag; cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", &len); if (cuint && len == sizeof(*cuint)) regulator->min_uv = fdt32_to_cpu(*cuint); else if (cuint || len != -FDT_ERR_NOTFOUND) panic(); cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", &len); if (cuint && len == sizeof(*cuint)) { regulator->max_uv = fdt32_to_cpu(*cuint); if (regulator->max_uv < regulator->min_uv) { EMSG("Regulator %s max_uv %d < %d", regulator_name(regulator), regulator->max_uv, regulator->min_uv); return TEE_ERROR_GENERIC; } } else if (cuint || len != -FDT_ERR_NOTFOUND) { panic(); } else { regulator->max_uv = INT_MAX; } return TEE_SUCCESS; } /* * API function to register a DRIVER_REGULATOR provider instance. * The registration can be deferred if the regulator supply (if any) * is not yet registered, in which case the regulator is placed in * a regulator pending list. */ TEE_Result regulator_dt_register(const void *fdt, int node, int provider_node, const struct regu_dt_desc *desc) { TEE_Result res = TEE_ERROR_OUT_OF_MEMORY; struct regulator *regulator = NULL; uint32_t supply_phandle = 0; char *name = NULL; assert(desc); if (!desc->regulator) { regulator = calloc(1, sizeof(*regulator)); if (!regulator) return TEE_ERROR_OUT_OF_MEMORY; } else { regulator = desc->regulator; memset(regulator, 0, sizeof(*regulator)); } if (desc->name) { /* Will be freed if overridden by DT node content */ name = strdup(desc->name); if (!name) goto err_free; } *regulator = (struct regulator){ .name = name, .ops = desc->ops, .priv = desc->priv, }; res = parse_dt(fdt, node, regulator); if (res) goto err_free; if (desc->supply_name) { res = get_supply_phandle(fdt, provider_node, desc->supply_name, &supply_phandle); if (res) goto err_free; } if (supply_phandle) { res = add_to_pending_list(fdt, node, regulator, supply_phandle, !desc->regulator); if (res) goto err_free; } else { res = register_final(fdt, node, regulator); if (res) goto err_free; } resolve_pending_list(); return TEE_SUCCESS; err_free: /* This function cannot return TEE_ERROR_DEFER_DRIVER_INIT */ assert(res != TEE_ERROR_DEFER_DRIVER_INIT); free(regulator->name); if (!desc->regulator) free(regulator); return res; } static TEE_Result release_regulator_pending_lists(void) { struct pending_regu *pending = NULL; struct pending_regu *next = NULL; if (!SLIST_EMPTY(&pending_regu_list)) DMSG("Some regulators were not supplied:"); SLIST_FOREACH_SAFE(pending, &pending_regu_list, link, next) { DMSG(" Unsupplied regulator %s", regulator_name(pending->regulator)); SLIST_REMOVE(&pending_regu_list, pending, pending_regu, link); if (pending->regulator_allocated) free(pending->regulator); free(pending); } return TEE_SUCCESS; } release_init_resource(release_regulator_pending_lists); optee_os-4.3.0/core/drivers/regulator/regulator_fixed.c000066400000000000000000000111201464416617300233030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0); /* * struct regulator_gpio - GPIO controlled regulator * @regulator: Preallocated regulator instance * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on * @enable_delay: Time (in microsecond) for the regulator to get enabled * @off_on_delay: Min time (in microsecond) between enable and disable request * @off_on_us: Timestamp of the last disable request */ struct regulator_fixed { struct regulator regulator; struct gpio *enable_gpio; unsigned int enable_delay; unsigned int off_on_delay; uint64_t off_on_us; }; static struct regulator_fixed *regulator_priv(struct regulator *regulator) { return container_of(regulator, struct regulator_fixed, regulator); } static TEE_Result fixed_set_state(struct regulator *regulator, bool enabled) { struct regulator_fixed *regu = regulator_priv(regulator); if (regu->enable_gpio) { if (enabled) { while (!timeout_elapsed(regu->off_on_us)) udelay(1); gpio_set_value(regu->enable_gpio, GPIO_LEVEL_HIGH); udelay(regu->enable_delay); } else { regu->off_on_us = timeout_init_us(regu->off_on_delay); gpio_set_value(regu->enable_gpio, GPIO_LEVEL_LOW); } } return TEE_SUCCESS; } static TEE_Result fixed_get_state(struct regulator *regulator, bool *enabled) { struct regulator_fixed *regu = regulator_priv(regulator); if (regu->enable_gpio) *enabled = gpio_get_value(regu->enable_gpio); else *enabled = true; return TEE_SUCCESS; } static const struct regulator_ops fixed_regulator_ops = { .set_state = fixed_set_state, .get_state = fixed_get_state, }; static TEE_Result get_enable_gpio(const void *fdt, int node, struct regulator_fixed *regu) { TEE_Result res = TEE_ERROR_GENERIC; const fdt32_t *cuint = NULL; struct gpio *gpio = NULL; void *gpio_ref = &gpio; res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0, DT_DRIVER_GPIO, gpio_ref); if (res == TEE_ERROR_ITEM_NOT_FOUND) res = dt_driver_device_from_node_idx_prop("gpio", fdt, node, 0, DT_DRIVER_GPIO, gpio_ref); if (res == TEE_ERROR_ITEM_NOT_FOUND) { regu->enable_gpio = NULL; return TEE_SUCCESS; } if (res) return res; /* Override active level phandle flag, as per DT bindings */ if (dt_have_prop(fdt, node, "enable-active-high")) gpio->dt_flags &= ~GPIO_ACTIVE_LOW; else gpio->dt_flags |= GPIO_ACTIVE_LOW; /* Override open drain/open source phandle flag, as per DT bindings */ if (dt_have_prop(fdt, node, "gpio-open-drain")) gpio->dt_flags |= GPIO_LINE_OPEN_DRAIN; else gpio->dt_flags &= ~GPIO_LINE_OPEN_DRAIN; cuint = fdt_getprop(fdt, node, "startup-delay-us", NULL); if (cuint) regu->enable_delay = fdt32_to_cpu(*cuint); cuint = fdt_getprop(fdt, node, "off-on-delay-us", NULL); if (cuint) regu->off_on_delay = fdt32_to_cpu(*cuint); gpio_set_direction(gpio, GPIO_DIR_OUT); regu->enable_gpio = gpio; return TEE_SUCCESS; } static TEE_Result fixed_regulator_probe(const void *fdt, int node, const void *compat_data __unused) { struct regulator_fixed *regu = NULL; TEE_Result res = TEE_ERROR_GENERIC; struct regu_dt_desc desc = { }; const char *supply_name = NULL; const char *type = NULL; char *regu_name = NULL; regu_name = (char *)fdt_get_name(fdt, node, NULL); type = fdt_getprop(fdt, node, "regulator-type", NULL); if (type && strcmp(type, "voltage")) { EMSG("Regulator gpio node %s: type %s not supported", regu_name, type); return TEE_ERROR_GENERIC; } regu = calloc(1, sizeof(*regu)); if (!regu) return TEE_ERROR_OUT_OF_MEMORY; res = get_enable_gpio(fdt, node, regu); if (res) goto err; if (fdt_getprop(fdt, node, "vin-supply", NULL)) supply_name = "vin"; desc = (struct regu_dt_desc){ .name = regu_name, .ops = &fixed_regulator_ops, .supply_name = supply_name, .regulator = ®u->regulator, }; res = regulator_dt_register(fdt, node, node, &desc); if (res) { EMSG("Can't register regulator %s: %#"PRIx32, regu_name, res); goto err; } return TEE_SUCCESS; err: free(regu); return res; } static const struct dt_device_match regulator_match_table[] = { { .compatible = "regulator-fixed" }, { } }; DEFINE_DT_DRIVER(fixed_regulator_dt_driver) = { .name = "regulator-fixed", .match_table = regulator_match_table, .probe = fixed_regulator_probe, }; optee_os-4.3.0/core/drivers/regulator/regulator_gpio.c000066400000000000000000000170751464416617300231610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, STMicroelectronics */ #include #include #include #include #include #include #include #include static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0); /* * struct regulator_gpio - GPIO controlled regulator * @regulator: Preallocated regulator instance * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on * @enable_delay: Time (in microsecond) for the regulator to get enabled * @voltage_gpio: GPIO for the voltage level selection * @levels_desc: Supported voltage levels description * @voltage_levels_uv: 2 cells array supported voltage levels, increasing order * @voltage_level_high: True if higher voltage level relates to GPIO state 1 */ struct regulator_gpio { struct regulator regulator; struct gpio *enable_gpio; unsigned int enable_delay; struct gpio *voltage_gpio; struct regulator_voltages_desc levels_desc; int voltage_levels_uv[2]; bool voltage_level_high; }; static struct regulator_gpio *regulator_priv(struct regulator *regulator) { return container_of(regulator, struct regulator_gpio, regulator); } static TEE_Result regulator_gpio_set_state(struct regulator *regulator, bool enabled) { struct regulator_gpio *regu = regulator_priv(regulator); if (regu->enable_gpio) { if (enabled) { gpio_set_value(regu->enable_gpio, GPIO_LEVEL_HIGH); if (regu->enable_delay) udelay(regu->enable_delay); } else { gpio_set_value(regu->enable_gpio, GPIO_LEVEL_LOW); } } return TEE_SUCCESS; } static TEE_Result regulator_gpio_read_state(struct regulator *regulator, bool *enabled) { struct regulator_gpio *regu = regulator_priv(regulator); if (regu->enable_gpio) *enabled = gpio_get_value(regu->enable_gpio); else *enabled = true; return TEE_SUCCESS; } static TEE_Result regulator_gpio_set_voltage(struct regulator *regulator, int level_uv) { struct regulator_gpio *regu = regulator_priv(regulator); enum gpio_level value = GPIO_LEVEL_LOW; if (level_uv == regu->voltage_levels_uv[0]) value = GPIO_LEVEL_LOW; else if (level_uv == regu->voltage_levels_uv[1]) value = GPIO_LEVEL_HIGH; else return TEE_ERROR_BAD_PARAMETERS; if (!regu->voltage_level_high) value = !value; gpio_set_value(regu->voltage_gpio, value); return TEE_SUCCESS; } static TEE_Result regulator_gpio_read_voltage(struct regulator *regulator, int *level_uv) { struct regulator_gpio *regu = regulator_priv(regulator); enum gpio_level value = gpio_get_value(regu->voltage_gpio); if (!regu->voltage_level_high) value = !value; *level_uv = regu->voltage_levels_uv[value]; return TEE_SUCCESS; } static TEE_Result regulator_gpio_voltages(struct regulator *regulator, struct regulator_voltages_desc **desc, const int **levels) { struct regulator_gpio *regu = regulator_priv(regulator); *desc = ®u->levels_desc; *levels = regu->voltage_levels_uv; return TEE_SUCCESS; } static const struct regulator_ops regulator_gpio_ops = { .set_state = regulator_gpio_set_state, .get_state = regulator_gpio_read_state, .set_voltage = regulator_gpio_set_voltage, .get_voltage = regulator_gpio_read_voltage, .supported_voltages = regulator_gpio_voltages, }; static TEE_Result get_enable_gpio(const void *fdt, int node, struct regulator_gpio *regu) { TEE_Result res = TEE_ERROR_GENERIC; const fdt32_t *cuint = NULL; struct gpio *gpio = NULL; res = gpio_dt_get_by_index(fdt, node, 0, "enable", &gpio); if (res == TEE_ERROR_ITEM_NOT_FOUND) { regu->enable_gpio = NULL; return TEE_SUCCESS; } if (res) return res; /* Override active level phandle flag, as per DT bindings */ if (dt_have_prop(fdt, node, "enable-active-high")) gpio->dt_flags &= ~GPIO_ACTIVE_LOW; else gpio->dt_flags |= GPIO_ACTIVE_LOW; /* Override open drain/open source phandle flag, as per DT bindings */ if (dt_have_prop(fdt, node, "gpio-open-drain")) gpio->dt_flags |= GPIO_LINE_OPEN_DRAIN; else gpio->dt_flags &= ~GPIO_LINE_OPEN_DRAIN; cuint = fdt_getprop(fdt, node, "startup-delay-us", NULL); if (cuint) regu->enable_delay = fdt32_to_cpu(*cuint); gpio_set_direction(gpio, GPIO_DIR_OUT); regu->enable_gpio = gpio; return TEE_SUCCESS; } static TEE_Result get_voltage_level_gpio(const void *fdt, int node, struct regulator_gpio *regu) { TEE_Result res = TEE_ERROR_GENERIC; const fdt32_t *cuint = NULL; struct gpio *gpio = NULL; void *gpio_ref = &gpio; int level0 = 0; int level1 = 0; int len = 0; res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0, DT_DRIVER_GPIO, gpio_ref); if (res) return res; /* * DT bindings allows more than 1 GPIO to control more than * 2 voltage levels. As it's not used so far in known platforms * this implementation is simplified to support only 2 voltage * levels controlled with a single GPIO. */ if (dt_driver_device_from_node_idx_prop("gpios", fdt, node, 1, DT_DRIVER_GPIO, gpio_ref) != TEE_ERROR_ITEM_NOT_FOUND) { EMSG("Multiple GPIOs not supported for level control"); return TEE_ERROR_GENERIC; } cuint = fdt_getprop(fdt, node, "states", &len); if (!cuint || len != 4 * sizeof(fdt32_t)) { EMSG("Node %s expects 2 levels from property \"states\"", fdt_get_name(fdt, node, NULL)); return TEE_ERROR_GENERIC; } if (fdt32_to_cpu(*(cuint + 1))) { assert(!fdt32_to_cpu(*(cuint + 3))); level1 = fdt32_to_cpu(*(cuint)); level0 = fdt32_to_cpu(*(cuint + 2)); } else { assert(fdt32_to_cpu(*(cuint + 3)) == 1); level0 = fdt32_to_cpu(*(cuint)); level1 = fdt32_to_cpu(*(cuint + 2)); } /* Get the 2 supported levels in increasing order */ regu->levels_desc.type = VOLTAGE_TYPE_FULL_LIST; regu->levels_desc.num_levels = 2; if (level0 < level1) { regu->voltage_levels_uv[0] = level0; regu->voltage_levels_uv[1] = level1; regu->voltage_level_high = true; } else { regu->voltage_levels_uv[0] = level1; regu->voltage_levels_uv[1] = level0; regu->voltage_level_high = false; } gpio_set_direction(gpio, GPIO_DIR_OUT); regu->voltage_gpio = gpio; return TEE_SUCCESS; } static TEE_Result regulator_gpio_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct regulator_gpio *regu = NULL; struct regu_dt_desc desc = { }; const char *supply_name = NULL; const char *type = NULL; char *regu_name = NULL; regu_name = (char *)fdt_get_name(fdt, node, NULL); type = fdt_getprop(fdt, node, "regulator-type", NULL); if (type && strcmp(type, "voltage")) { EMSG("Regulator node %s: type \"%s\" not supported", regu_name, type); res = TEE_ERROR_GENERIC; goto err; } regu = calloc(1, sizeof(*regu)); if (!regu) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } res = get_enable_gpio(fdt, node, regu); if (res) goto err; res = get_voltage_level_gpio(fdt, node, regu); if (res) goto err; if (fdt_getprop(fdt, node, "vin-supply", NULL)) supply_name = "vin"; desc = (struct regu_dt_desc){ .name = regu_name, .ops = ®ulator_gpio_ops, .supply_name = supply_name, .regulator = ®u->regulator, }; res = regulator_dt_register(fdt, node, node, &desc); if (res) { EMSG("Can't register regulator %s: %#"PRIx32, regu_name, res); goto err; } return TEE_SUCCESS; err: free(regu); return res; } static const struct dt_device_match regulator_gpio_match_table[] = { { .compatible = "regulator-gpio" }, { } }; DEFINE_DT_DRIVER(regulator_gpio_dt_driver) = { .name = "regulator-gpio", .match_table = regulator_gpio_match_table, .probe = regulator_gpio_probe, }; optee_os-4.3.0/core/drivers/regulator/stm32_vrefbuf.c000066400000000000000000000220351464416617300226160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include /* STM32 VREFBUF registers */ #define VREFBUF_CSR U(0) /* STM32 VREFBUF CSR bitfields */ /* VRS bit 3 is unused because the voltage is not specified */ #define VREFBUF_CSR_VRS GENMASK_32(5, 4) #define VREFBUF_CSR_VRS_SHIFT U(4) #define INV_VRS(x) ((~(x)) & VREFBUF_CSR_VRS) #define VREFBUF_CSR_VRR BIT(3) #define VREFBUF_CSR_HIZ BIT(1) #define VREFBUF_CSR_ENVR BIT(0) #define TIMEOUT_US_10MS U(10 * 1000) #define TIMEOUT_US_1MS U(1 * 1000) #define VREFBUF_LEVELS_COUNT U(4) /* * struct vrefbuf_compat - Compatibility data * @voltages: Voltage levels supported */ struct vrefbuf_compat { int voltages[VREFBUF_LEVELS_COUNT]; }; /* * struct vrefbuf_regul - VREFBUF regulator * @base: IO memory base address * @clock: VREFBUF access bus clock * @regulator: Preallocated instance for the regulator * @compat: Compatibility data * @voltages_desc: Supported voltage level description * @voltages_level: Supplorted levels description * @voltages_start_index: start index in compat for supported levels */ struct vrefbuf_regul { vaddr_t base; struct clk *clock; uint64_t disable_timeout; struct regulator regulator; const struct vrefbuf_compat *compat; struct regulator_voltages_desc voltages_desc; size_t voltages_start_index; }; static const struct vrefbuf_compat stm32mp15_vrefbuf_compat = { .voltages = { /* Matches resp. VRS = 011b, 010b, 001b, 000b */ 1500000, 1800000, 2048000, 2500000, }, }; static const struct vrefbuf_compat stm32mp13_vrefbuf_compat = { .voltages = { /* Matches resp. VRS = 011b, 010b, 001b, 000b */ 1650000, 1800000, 2048000, 2500000, }, }; /* Expect at most 1 instance */ static struct vrefbuf_regul *stm32_vrefbuf; struct regulator *stm32_vrefbuf_regulator(void) { if (!stm32_vrefbuf) return NULL; return &stm32_vrefbuf->regulator; } static struct vrefbuf_regul *regulator_to_vr(struct regulator *regulator) { return container_of(regulator, struct vrefbuf_regul, regulator); } static TEE_Result vrefbuf_wait_ready(struct vrefbuf_regul *vr) { uint32_t val = 0; if (IO_READ32_POLL_TIMEOUT(vr->base + VREFBUF_CSR, val, val & VREFBUF_CSR_VRR, 0, TIMEOUT_US_10MS)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result vrefbuf_set_state(struct regulator *regulator, bool enable) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); TEE_Result res = TEE_ERROR_GENERIC; res = clk_enable(vr->clock); if (res) return res; if (enable) { io_clrbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_HIZ); /* * If first enable after boot or if it was disabled since * less than 1ms, then wait for 1ms in pull down mode to * avoid an overshoot. */ if (!vr->disable_timeout || !timeout_elapsed(vr->disable_timeout)) udelay(1000); io_setbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_ENVR); if (vrefbuf_wait_ready(vr) != TEE_SUCCESS) { clk_disable(vr->clock); return TEE_ERROR_GENERIC; } } else { io_clrbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_ENVR); vr->disable_timeout = timeout_init_us(TIMEOUT_US_1MS); } clk_disable(vr->clock); return TEE_SUCCESS; } static TEE_Result vrefbuf_get_state(struct regulator *regulator, bool *enabled) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); TEE_Result res = TEE_ERROR_GENERIC; res = clk_enable(vr->clock); if (res) return res; *enabled = io_read32(vr->base + VREFBUF_CSR) & VREFBUF_CSR_VRR; clk_disable(vr->clock); return TEE_SUCCESS; } static TEE_Result vrefbuf_get_voltage(struct regulator *regulator, int *level_uv) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); TEE_Result res = TEE_ERROR_GENERIC; uint32_t index = 0; res = clk_enable(vr->clock); if (res) return res; index = io_read32(vr->base + VREFBUF_CSR) & VREFBUF_CSR_VRS; index = INV_VRS(index) >> VREFBUF_CSR_VRS_SHIFT; clk_disable(vr->clock); *level_uv = vr->compat->voltages[index]; return TEE_SUCCESS; } static TEE_Result vrefbuf_set_voltage(struct regulator *regulator, int level_uv) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); TEE_Result res = TEE_ERROR_GENERIC; size_t i = 0; for (i = 0 ; i < ARRAY_SIZE(vr->compat->voltages) ; i++) { if (vr->compat->voltages[i] == level_uv) { uint32_t val = INV_VRS(i << VREFBUF_CSR_VRS_SHIFT); res = clk_enable(vr->clock); if (res) return res; io_clrsetbits32(vr->base + VREFBUF_CSR, VREFBUF_CSR_VRS, val); clk_disable(vr->clock); return TEE_SUCCESS; } } EMSG("Failed to set voltage on vrefbuf"); return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result vrefbuf_list_voltages(struct regulator *regulator __unused, struct regulator_voltages_desc **desc, const int **levels) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); const int *levels_ref = vr->compat->voltages; *desc = &vr->voltages_desc; *levels = levels_ref + vr->voltages_start_index; return TEE_SUCCESS; } static TEE_Result set_voltages_desc(struct regulator *regulator) { struct vrefbuf_regul *vr = regulator_to_vr(regulator); size_t num_levels = ARRAY_SIZE(vr->compat->voltages); int index_high = num_levels - 1; int index_low = 0; int n = 0; vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; for (n = 0; n <= index_high; n++) if (vr->compat->voltages[n] >= regulator->min_uv) break; if (n > index_high) return TEE_ERROR_GENERIC; index_low = n; for (n = index_high; n >= index_low; n--) if (vr->compat->voltages[n] <= regulator->max_uv) break; if (n < index_low) return TEE_ERROR_GENERIC; index_high = n; assert(index_high - index_low + 1 >= 0 && index_low >= 0); vr->voltages_desc.type = VOLTAGE_TYPE_FULL_LIST; vr->voltages_desc.num_levels = index_high - index_low + 1; vr->voltages_start_index = index_low; return TEE_SUCCESS; } static TEE_Result stm32_vrefbuf_pm(enum pm_op op, unsigned int pm_hint __unused, const struct pm_callback_handle *hdl) { struct regulator *regulator = hdl->handle; struct vrefbuf_regul *vr = regulator_to_vr(regulator); vaddr_t csr_va = vr->base + VREFBUF_CSR; TEE_Result res = TEE_ERROR_GENERIC; /* Context to save/restore on PM suspend/resume */ static uint32_t pm_val; assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); res = clk_enable(vr->clock); if (res) return res; if (op == PM_OP_SUSPEND) { pm_val = io_read32(csr_va); if (pm_val & VREFBUF_CSR_ENVR && vrefbuf_wait_ready(vr)) { clk_disable(vr->clock); return TEE_ERROR_GENERIC; } } else { io_clrsetbits32(csr_va, VREFBUF_CSR_VRS, pm_val); if (pm_val & VREFBUF_CSR_ENVR) { vr->disable_timeout = 0; vrefbuf_set_state(&vr->regulator, true); } } clk_disable(vr->clock); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(stm32_vrefbuf_pm); static TEE_Result stm32_vrefbuf_init(struct regulator *regulator, const void *fdt __unused, int node __unused) { TEE_Result res = TEE_ERROR_GENERIC; res = set_voltages_desc(regulator); if (res) return res; register_pm_driver_cb(stm32_vrefbuf_pm, regulator, "stm32-vrefbuf"); return TEE_SUCCESS; } static const struct regulator_ops vrefbuf_ops = { .set_state = vrefbuf_set_state, .get_state = vrefbuf_get_state, .set_voltage = vrefbuf_set_voltage, .get_voltage = vrefbuf_get_voltage, .supported_voltages = vrefbuf_list_voltages, .supplied_init = stm32_vrefbuf_init, }; static TEE_Result stm32_vrefbuf_regulator_probe(const void *fdt, int node, const void *compat_data) { TEE_Result res = TEE_ERROR_GENERIC; struct vrefbuf_regul *vr = NULL; struct regu_dt_desc desc = { }; char *regu_name = NULL; struct clk *clk = NULL; paddr_t reg_base = 0; size_t reg_size = 0; assert(!stm32_vrefbuf); res = clk_dt_get_by_index(fdt, node, 0, &clk); if (res) return res; vr = calloc(1, sizeof(*vr)); if (!vr) panic(); vr->compat = compat_data; regu_name = strdup(fdt_get_name(fdt, node, NULL)); if (!regu_name) panic(); reg_base = fdt_reg_base_address(fdt, node); reg_size = fdt_reg_size(fdt, node); if (reg_base == DT_INFO_INVALID_REG || reg_size == DT_INFO_INVALID_REG_SIZE) panic(); vr->base = (vaddr_t)phys_to_virt(reg_base, MEM_AREA_IO_SEC, reg_size); if (!vr->base) panic(); vr->clock = clk; desc = (struct regu_dt_desc){ .name = regu_name, .ops = &vrefbuf_ops, .supply_name = "vdda", .regulator = &vr->regulator, }; res = regulator_dt_register(fdt, node, node, &desc); if (res) panic(); stm32_vrefbuf = vr; return TEE_SUCCESS; } static const struct dt_device_match stm32_vrefbuf_match_table[] = { { .compatible = "st,stm32-vrefbuf", .compat_data = &stm32mp15_vrefbuf_compat, }, { .compatible = "st,stm32mp13-vrefbuf", .compat_data = &stm32mp13_vrefbuf_compat }, { } }; DEFINE_DT_DRIVER(stm32_vrefbuf_regulator_dt_driver) = { .name = "stm32-vrefbuf-regulator", .match_table = stm32_vrefbuf_match_table, .probe = &stm32_vrefbuf_regulator_probe, }; optee_os-4.3.0/core/drivers/regulator/stm32mp13_regulator_iod.c000066400000000000000000000170231464416617300245200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TIMEOUT_US_10MS U(10000) #define IO_VOLTAGE_THRESHOLD_UV 2700000 /* * struct iod_regul - IO domain regulator instance * * @enable_reg: PWR register offset for the IO domain * @enable_mask: Domain enable register bit mask in PWR register * @ready_mask: Domain ready bit mask in PWR register * @valid_mask: Domain valid bit mask in PWR register * @hslv_id: ID of the related HSLV domain * @io_comp_id: ID of the related IO compensation domain * @suspend_state: True if regulator is enabled before suspend, false otherwise * @suspend_level_uv: Voltage level before suspend, in microvolts */ struct iod_regul { uint32_t enable_reg; uint32_t enable_mask; uint32_t ready_mask; uint32_t valid_mask; enum stm32mp13_hslv_id hslv_id; enum stm32mp13_vddsd_comp_id io_comp_id; bool suspend_state; int suspend_level_uv; }; static struct iod_regul iod_regulator_priv[IOD_REGU_COUNT] = { [IOD_SDMMC1] = { .enable_reg = PWR_CR3_OFF, .enable_mask = PWR_CR3_VDDSD1EN, .ready_mask = PWR_CR3_VDDSD1RDY, .valid_mask = PWR_CR3_VDDSD1VALID, .hslv_id = SYSCFG_HSLV_IDX_SDMMC1, .io_comp_id = SYSCFG_IO_COMP_IDX_SD1, }, [IOD_SDMMC2] = { .enable_reg = PWR_CR3_OFF, .enable_mask = PWR_CR3_VDDSD2EN, .ready_mask = PWR_CR3_VDDSD2RDY, .valid_mask = PWR_CR3_VDDSD2VALID, .hslv_id = SYSCFG_HSLV_IDX_SDMMC2, .io_comp_id = SYSCFG_IO_COMP_IDX_SD2, }, }; static struct regulator *iod_regulator[IOD_REGU_COUNT]; struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index) { assert(index >= IOD_SDMMC1 && index < IOD_REGU_COUNT); return iod_regulator[index]; } static TEE_Result iod_set_state(struct regulator *regu, bool enable) { struct iod_regul *iod = regu->priv; uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg; FMSG("%s: set state %u", regulator_name(regu), enable); if (enable) { uint32_t value = 0; io_setbits32(pwr_reg, iod->enable_mask); if (IO_READ32_POLL_TIMEOUT(pwr_reg, value, value & iod->ready_mask, 0, TIMEOUT_US_10MS)) return TEE_ERROR_GENERIC; io_setbits32(pwr_reg, iod->valid_mask); io_clrbits32(pwr_reg, iod->enable_mask); stm32mp_set_vddsd_comp_state(iod->io_comp_id, true); } else { stm32mp_set_vddsd_comp_state(iod->io_comp_id, false); io_clrbits32(pwr_reg, iod->enable_mask | iod->valid_mask); } return TEE_SUCCESS; } static TEE_Result iod_get_state(struct regulator *regu, bool *enabled) { struct iod_regul *iod = regu->priv; uintptr_t pwr_reg = stm32_pwr_base() + iod->enable_reg; *enabled = io_read32(pwr_reg) & (iod->enable_mask | iod->valid_mask); return TEE_SUCCESS; } static TEE_Result iod_get_voltage(struct regulator *regu, int *level_uv) { *level_uv = regulator_get_voltage(regu->supply); return TEE_SUCCESS; } static TEE_Result iod_set_voltage(struct regulator *regu, int level_uv) { struct iod_regul *iod = regu->priv; TEE_Result res = TEE_ERROR_GENERIC; bool iod_enabled = false; FMSG("%s: set voltage level to %duV", regulator_name(regu), level_uv); res = iod_get_state(regu, &iod_enabled); if (res) return res; /* Isolate IOs and disable IOs compensation when changing voltage */ if (iod_enabled) { res = iod_set_state(regu, false); if (res) return res; } /* * Set IO to low speed. * Setting high voltage with IOs in high speed mode may damage the IOs. */ stm32mp_set_hslv_state(iod->hslv_id, false); /* Forward set voltage request to the power supply */ res = regulator_set_voltage(regu->supply, level_uv); if (res) { EMSG("regulator %s set voltage failed: %#"PRIx32, regulator_name(regu), res); /* Ensure IO domain consistency for current voltage level */ level_uv = regulator_get_voltage(regu->supply); } if (level_uv <= IO_VOLTAGE_THRESHOLD_UV) stm32mp_set_hslv_state(iod->hslv_id, true); if (iod_enabled) { TEE_Result res2 = TEE_ERROR_GENERIC; res2 = iod_set_state(regu, true); if (res2) return res2; } return res; } static TEE_Result iod_list_voltages(struct regulator *regu, struct regulator_voltages_desc **desc, const int **levels) { /* Return supply voltage list */ return regulator_supported_voltages(regu->supply, desc, levels); } /* * To protect the IOs, we disable High Speed Low Voltage mode before * entering suspend state and restore the configuration when resuming. */ static TEE_Result iod_pm(enum pm_op op, unsigned int pm_hint __unused, const struct pm_callback_handle *hdl) { struct regulator *regu = hdl->handle; struct iod_regul *iod = regu->priv; TEE_Result res = TEE_ERROR_GENERIC; assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); if (op == PM_OP_SUSPEND) { FMSG("%s: suspend", regulator_name(regu)); res = iod_get_state(regu, &iod->suspend_state); if (res) return res; res = iod_get_voltage(regu, &iod->suspend_level_uv); if (res) return res; stm32mp_set_hslv_state(iod->hslv_id, false); } else { FMSG("%s: resume", regulator_name(regu)); res = iod_set_voltage(regu, iod->suspend_level_uv); if (res) return res; res = iod_set_state(regu, iod->suspend_state); if (res) return res; } return TEE_SUCCESS; } static TEE_Result iod_supplied_init(struct regulator *regu, const void *fdt __unused, int node __unused) { struct iod_regul *iod = regu->priv; int index = iod - iod_regulator_priv; assert(index >= 0 && index < IOD_REGU_COUNT); if (regulator_get_voltage(regu) < IO_VOLTAGE_THRESHOLD_UV) stm32mp_set_hslv_state(iod->hslv_id, true); /* Save regulator reference */ iod_regulator[index] = regu; register_pm_driver_cb(iod_pm, regu, "iod-regulator"); FMSG("IOD regulator %s intiialized", regulator_name(regu)); return TEE_SUCCESS; } static const struct regulator_ops iod_ops = { .set_state = iod_set_state, .get_state = iod_get_state, .set_voltage = iod_set_voltage, .get_voltage = iod_get_voltage, .supported_voltages = iod_list_voltages, .supplied_init = iod_supplied_init, }; #define DEFINE_REG(_id, _name, _supply_name) { \ .name = (_name), \ .ops = &iod_ops, \ .priv = iod_regulator_priv + (_id), \ .supply_name = (_supply_name), \ } static struct regu_dt_desc iod_regul_desc[IOD_REGU_COUNT] = { [IOD_SDMMC1] = DEFINE_REG(IOD_SDMMC1, "sdmmc1_io", "vddsd1"), [IOD_SDMMC2] = DEFINE_REG(IOD_SDMMC2, "sdmmc2_io", "vddsd2"), }; static TEE_Result iod_regulator_probe(const void *fdt, int node, const void *compat_data __unused) { const char *node_name = NULL; size_t i = 0; node_name = fdt_get_name(fdt, node, NULL); FMSG("iod probe node '%s'", node_name); /* Look up matching regulator name defined in SoC DTSI file */ for (i = 0; i < IOD_REGU_COUNT; i++) if (!strcmp(iod_regul_desc[i].name, node_name)) break; if (i == IOD_REGU_COUNT) { EMSG("Unexpected IO domain node name '%s'", node_name); return TEE_ERROR_GENERIC; } return regulator_dt_register(fdt, node, node, iod_regul_desc + i); } static const struct dt_device_match iod_regulator_match_table[] = { { .compatible = "st,stm32mp13-iod" }, { } }; DEFINE_DT_DRIVER(stm32mp13_regulator_iod_dt_driver) = { .name = "stm32mp13-iod-regulator", .match_table = iod_regulator_match_table, .probe = iod_regulator_probe, }; optee_os-4.3.0/core/drivers/regulator/sub.mk000066400000000000000000000004051464416617300211020ustar00rootroot00000000000000srcs-y += regulator.c srcs-$(CFG_DT) += regulator_dt.c srcs-$(CFG_REGULATOR_FIXED) += regulator_fixed.c srcs-$(CFG_REGULATOR_GPIO) += regulator_gpio.c srcs-$(CFG_STM32_VREFBUF) += stm32_vrefbuf.c srcs-$(CFG_STM32MP13_REGULATOR_IOD) += stm32mp13_regulator_iod.c optee_os-4.3.0/core/drivers/remoteproc/000077500000000000000000000000001464416617300201345ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/remoteproc/stm32_remoteproc.c000066400000000000000000000217101464416617300235100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #define TIMEOUT_US_1MS U(1000) /** * struct stm32_rproc_mem - Memory regions used by the remote processor * * @addr: physical base address from the CPU space perspective * @da: device address corresponding to the physical base address * from remote processor space perspective * @size: size of the region */ struct stm32_rproc_mem { paddr_t addr; paddr_t da; size_t size; }; /** * struct stm32_rproc_instance - rproc instance context * * @cdata: pointer to the device compatible data * @link: the node in the rproc_list * @n_regions: number of memory regions * @regions: memory regions used * @mcu_rst: remote processor reset control * @hold_boot: remote processor hold boot control */ struct stm32_rproc_instance { const struct stm32_rproc_compat_data *cdata; SLIST_ENTRY(stm32_rproc_instance) link; size_t n_regions; struct stm32_rproc_mem *regions; struct rstctrl *mcu_rst; struct rstctrl *hold_boot; }; /** * struct stm32_rproc_compat_data - rproc associated data for compatible list * * @rproc_id: identifies the remote processor */ struct stm32_rproc_compat_data { uint32_t rproc_id; }; static SLIST_HEAD(, stm32_rproc_instance) rproc_list = SLIST_HEAD_INITIALIZER(rproc_list); void *stm32_rproc_get(uint32_t rproc_id) { struct stm32_rproc_instance *rproc = NULL; SLIST_FOREACH(rproc, &rproc_list, link) if (rproc->cdata->rproc_id == rproc_id) break; return rproc; } TEE_Result stm32_rproc_start(uint32_t rproc_id) { struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); TEE_Result res = TEE_ERROR_GENERIC; if (!rproc || !rproc->hold_boot) return TEE_ERROR_GENERIC; /* * The firmware is started by de-asserting the hold boot and * asserting it back to avoid auto restart on a crash. * No need to release the MCU reset as it is automatically released by * the hardware. */ res = rstctrl_deassert_to(rproc->hold_boot, TIMEOUT_US_1MS); if (!res) res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); return res; } static TEE_Result rproc_stop(struct stm32_rproc_instance *rproc) { TEE_Result res = TEE_ERROR_GENERIC; if (!rproc->hold_boot || !rproc->mcu_rst) return TEE_ERROR_GENERIC; res = rstctrl_assert_to(rproc->hold_boot, TIMEOUT_US_1MS); if (!res) res = rstctrl_assert_to(rproc->mcu_rst, TIMEOUT_US_1MS); return res; } TEE_Result stm32_rproc_stop(uint32_t rproc_id) { struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); if (!rproc) return TEE_ERROR_BAD_PARAMETERS; return rproc_stop(rproc); } TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, paddr_t *pa) { struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); struct stm32_rproc_mem *mems = NULL; unsigned int i = 0; if (!rproc) return TEE_ERROR_BAD_PARAMETERS; mems = rproc->regions; for (i = 0; i < rproc->n_regions; i++) { if (core_is_buffer_inside(da, size, mems[i].da, mems[i].size)) { /* * A match between the requested DA memory area and the * registered regions has been found. * The PA is the reserved-memory PA address plus the * delta between the requested DA and the * reserved-memory DA address. */ *pa = mems[i].addr + da - mems[i].da; return TEE_SUCCESS; } } return TEE_ERROR_ACCESS_DENIED; } TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, void **va) { struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); struct stm32_rproc_mem *mems = NULL; unsigned int i = 0; if (!rproc) return TEE_ERROR_BAD_PARAMETERS; mems = rproc->regions; for (i = 0; i < rproc->n_regions; i++) { if (!core_is_buffer_inside(pa, size, mems[i].addr, mems[i].size)) continue; *va = core_mmu_add_mapping(MEM_AREA_RAM_NSEC, pa, size); if (!*va) { EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } return TEE_ERROR_ACCESS_DENIED; } TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size) { struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id); struct stm32_rproc_mem *mems = NULL; paddr_t pa = virt_to_phys(va); unsigned int i = 0; if (!rproc || !pa) return TEE_ERROR_BAD_PARAMETERS; mems = rproc->regions; for (i = 0; i < rproc->n_regions; i++) { if (!core_is_buffer_inside(pa, size, mems[i].addr, mems[i].size)) continue; /* Flush the cache before unmapping the memory */ dcache_clean_range(va, size); if (core_mmu_remove_mapping(MEM_AREA_RAM_NSEC, va, size)) { EMSG("Can't unmap region %#"PRIxPA" size %zu", pa, size); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } return TEE_ERROR_ACCESS_DENIED; } static TEE_Result stm32_rproc_get_dma_range(struct stm32_rproc_mem *region, const void *fdt, int node) { const fdt32_t *list = NULL; int ahb_node = 0; int len = 0; int nranges = 0; int i = 0; /* * The match between local and remote processor memory mapping is * described in the dma-ranges defined by the bus parent node. */ ahb_node = fdt_parent_offset(fdt, node); list = fdt_getprop(fdt, ahb_node, "dma-ranges", &len); if (!list) { if (len != -FDT_ERR_NOTFOUND) return TEE_ERROR_GENERIC; /* Same memory mapping */ DMSG("No dma-ranges found in DT"); region->da = region->addr; return TEE_SUCCESS; } if ((len % (sizeof(uint32_t) * 3))) return TEE_ERROR_GENERIC; nranges = len / sizeof(uint32_t); for (i = 0; i < nranges; i += 3) { uint32_t da = fdt32_to_cpu(list[i]); uint32_t pa = fdt32_to_cpu(list[i + 1]); uint32_t size = fdt32_to_cpu(list[i + 2]); if (core_is_buffer_inside(region->addr, region->size, pa, size)) { region->da = da + (region->addr - pa); return TEE_SUCCESS; } } return TEE_ERROR_BAD_PARAMETERS; } /* Get device tree memory regions reserved for the Cortex-M and the IPC */ static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc, const void *fdt, int node) { const fdt32_t *list = NULL; TEE_Result res = TEE_ERROR_GENERIC; struct stm32_rproc_mem *regions = NULL; int len = 0; int n_regions = 0; int i = 0; list = fdt_getprop(fdt, node, "memory-region", &len); if (!list) { EMSG("No memory regions found in DT"); return TEE_ERROR_GENERIC; } n_regions = len / sizeof(uint32_t); regions = calloc(n_regions, sizeof(*regions)); if (!regions) return TEE_ERROR_OUT_OF_MEMORY; for (i = 0; i < n_regions; i++) { int pnode = 0; pnode = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(list[i])); if (pnode < 0) { res = TEE_ERROR_GENERIC; goto err; } regions[i].addr = fdt_reg_base_address(fdt, pnode); regions[i].size = fdt_reg_size(fdt, pnode); if (regions[i].addr <= 0 || regions[i].size <= 0) { res = TEE_ERROR_GENERIC; goto err; } res = stm32_rproc_get_dma_range(®ions[i], fdt, node); if (res) goto err; if (!regions[i].addr || !regions[i].size) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } DMSG("register region %#"PRIxPA" size %#zx", regions[i].addr, regions[i].size); } rproc->n_regions = n_regions; rproc->regions = regions; return TEE_SUCCESS; err: free(regions); return res; } static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc) { free(rproc->regions); free(rproc); } static TEE_Result stm32_rproc_probe(const void *fdt, int node, const void *comp_data) { struct stm32_rproc_instance *rproc = NULL; TEE_Result res = TEE_ERROR_GENERIC; rproc = calloc(1, sizeof(*rproc)); if (!rproc) return TEE_ERROR_OUT_OF_MEMORY; rproc->cdata = comp_data; res = stm32_rproc_parse_mems(rproc, fdt, node); if (res) goto err; res = rstctrl_dt_get_by_name(fdt, node, "mcu_rst", &rproc->mcu_rst); if (res) goto err; res = rstctrl_dt_get_by_name(fdt, node, "hold_boot", &rproc->hold_boot); if (res) goto err; /* Ensure that the MCU is HOLD */ if (rproc->mcu_rst) { res = rproc_stop(rproc); if (res) goto err; } /* * The memory management should be enhance with firewall * mechanism to map the memory in secure area for the firmware * loading and then to give exclusive access right to the * coprocessor (except for the shared memory). */ IMSG("Warning: the remoteproc memories are not protected by firewall"); SLIST_INSERT_HEAD(&rproc_list, rproc, link); return TEE_SUCCESS; err: stm32_rproc_cleanup(rproc); return res; } static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = { .rproc_id = STM32_M4_RPROC_ID, }; static const struct dt_device_match stm32_rproc_match_table[] = { { .compatible = "st,stm32mp1-m4-tee", .compat_data = &stm32_rproc_m4_compat, }, { } }; DEFINE_DT_DRIVER(stm32_rproc_dt_driver) = { .name = "stm32-rproc", .match_table = stm32_rproc_match_table, .probe = &stm32_rproc_probe, }; optee_os-4.3.0/core/drivers/remoteproc/sub.mk000066400000000000000000000000651464416617300212570ustar00rootroot00000000000000srcs-$(CFG_STM32MP_REMOTEPROC) += stm32_remoteproc.c optee_os-4.3.0/core/drivers/riscv_zkr_rng.c000066400000000000000000000021371464416617300210060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024 Andes Technology Corporation */ #include #include #include #include #include #define OPST_BIST 0b00 #define OPST_WAIT 0b01 #define OPST_ES16 0b10 #define OPST_DEAD 0b11 TEE_Result hw_get_random_bytes(void *buf, size_t len) { uint8_t *ptr = buf; uint32_t val = 0; while (len > 0) { /* * The seed register must be accessed using CSR read-write * instructions. The write operation is ignored and serves * to indicate polling and flushing. */ val = swap_csr(CSR_SEED, val); switch (val >> 30) { case OPST_BIST: case OPST_WAIT: continue; case OPST_ES16: *ptr++ = val & 0xff; len--; if (len > 0) { *ptr++ = val >> 8; len--; } break; case OPST_DEAD: /* Unrecoverable self-test error */ return TEE_ERROR_BAD_STATE; default: break; /* can't happen */ } } return TEE_SUCCESS; } void plat_rng_init(void) { if (!riscv_detect_csr_seed()) panic("RISC-V Zkr is not supported or unavailable in S-mode"); } optee_os-4.3.0/core/drivers/rstctrl/000077500000000000000000000000001464416617300174525ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/rstctrl/rstctrl.c000066400000000000000000000021231464416617300213110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Linaro Limited */ #include #include #include #include #include #include /* Global reset controller access lock */ TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl) { uint32_t exceptions = 0; TEE_Result res = TEE_ERROR_ACCESS_CONFLICT; static unsigned int rstctrl_lock = SPINLOCK_UNLOCK; exceptions = cpu_spin_lock_xsave(&rstctrl_lock); if (!rstctrl->exclusive) { rstctrl->exclusive = true; res = TEE_SUCCESS; } cpu_spin_unlock_xrestore(&rstctrl_lock, exceptions); return res; } void rstctrl_put_exclusive(struct rstctrl *rstctrl) { assert(rstctrl->exclusive); WRITE_ONCE(rstctrl->exclusive, false); } TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, const char *name, struct rstctrl **rstctrl) { int index = 0; index = fdt_stringlist_search(fdt, nodeoffset, "reset-names", name); if (index < 0) return TEE_ERROR_ITEM_NOT_FOUND; return rstctrl_dt_get_by_index(fdt, nodeoffset, index, rstctrl); } optee_os-4.3.0/core/drivers/rstctrl/stm32_rstctrl.c000066400000000000000000000046741464416617300223560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2022, Linaro Limited * Copyright (c) 2018-2022, STMicroelectronics */ #include #include #include #include "stm32_rstctrl.h" static struct stm32_reset_data *stm32_reset_pdata; static SLIST_HEAD(, stm32_rstline) stm32_rst_list = SLIST_HEAD_INITIALIZER(stm32_rst_list); static struct stm32_rstline *find_rstctrl_device(unsigned int control_id) { struct stm32_rstline *stm32_rstline = NULL; SLIST_FOREACH(stm32_rstline, &stm32_rst_list, link) if (stm32_rstline->id == control_id) break; return stm32_rstline; } static struct stm32_rstline *find_or_allocate_rstline(unsigned int binding_id, const struct stm32_reset_data *pdata) { struct stm32_rstline *stm32_rstline = find_rstctrl_device(binding_id); if (stm32_rstline) return stm32_rstline; stm32_rstline = calloc(1, sizeof(*stm32_rstline)); if (stm32_rstline) { assert(pdata->get_rstctrl_ops); stm32_rstline->id = binding_id; stm32_rstline->data = pdata; stm32_rstline->rstctrl.ops = pdata->get_rstctrl_ops(binding_id); SLIST_INSERT_HEAD(&stm32_rst_list, stm32_rstline, link); } return stm32_rstline; } struct stm32_rstline *to_stm32_rstline(struct rstctrl *rstctrl) { assert(rstctrl); return container_of(rstctrl, struct stm32_rstline, rstctrl); } struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id) { struct stm32_rstline *rstline = NULL; rstline = find_or_allocate_rstline(binding_id, stm32_reset_pdata); assert(rstline); return &rstline->rstctrl; } static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg, void *priv_data, struct rstctrl **out_device) { struct stm32_rstline *stm32_rstline = NULL; uintptr_t control_id = 0; if (arg->args_count != 1) return TEE_ERROR_BAD_PARAMETERS; control_id = arg->args[0]; stm32_rstline = find_or_allocate_rstline(control_id, priv_data); if (!stm32_rstline) return TEE_ERROR_OUT_OF_MEMORY; *out_device = &stm32_rstline->rstctrl; return TEE_SUCCESS; } TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs, const void *compat_data) { struct dt_node_info info = { }; stm32_reset_pdata = (struct stm32_reset_data *)compat_data; fdt_fill_device_info(fdt, &info, offs); assert(info.reg == RCC_BASE && info.reg_size != DT_INFO_INVALID_REG_SIZE); return rstctrl_register_provider(fdt, offs, stm32_rstctrl_get_dev, stm32_reset_pdata); } optee_os-4.3.0/core/drivers/rstctrl/stm32_rstctrl.h000066400000000000000000000032141464416617300223500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024, STMicroelectronics */ #include #include #include /* * struct stm32_reset_cfg - Reset line controller data * @offset: Byte offset in reset controller IOMEM * @bit_index: Bit position of reset line control at IOMEM @offset * @set_clr: True is @offset is an atomic SET/CLR register, false otherwise * @inverted: True is reset line is asserted at level 0, false otherwise * @no_deassert: True is reset line cannot be deasserted, false otherwise * @no_timeout: True if reset state cannot be read back for timeout detection */ struct stm32_reset_cfg { unsigned int offset; unsigned int bit_index; bool set_clr; bool inverted; bool no_deassert; bool no_timeout; }; /* * struct stm32_reset_data - Reset controller platform data * @nb_lines: Number of reset lines * @rst_lines: Table of reset lines * @get_rstctrl_ops: Handler to retrieve the controller operation handlers */ struct stm32_reset_data { unsigned int nb_lines; const struct stm32_reset_cfg **rst_lines; const struct rstctrl_ops * (*get_rstctrl_ops)(unsigned int id); }; /* * struct stm32_rstline - Exposed rstctrl instance * @id: Identifier used in the device tree bindings * @rstctrl: Related reset controller instance * @link: Reference in reset controller list */ struct stm32_rstline { unsigned int id; struct rstctrl rstctrl; const struct stm32_reset_data *data; SLIST_ENTRY(stm32_rstline) link; }; struct stm32_rstline *to_stm32_rstline(struct rstctrl *rstctrl); TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs, const void *compat_data); optee_os-4.3.0/core/drivers/rstctrl/stm32mp1_rstctrl.c000066400000000000000000000072331464416617300227660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2022, Linaro Limited * Copyright (c) 2018-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include "stm32_rstctrl.h" #define RESET_ID_MASK GENMASK_32(31, 5) #define RESET_ID_SHIFT U(5) #define RESET_BIT_POS_MASK GENMASK_32(4, 0) #define RESET_OFFSET_MAX U(1024) static size_t reset_id2reg_offset(unsigned int id) { size_t offset = (id & RESET_ID_MASK) >> RESET_ID_SHIFT; assert(offset < RESET_OFFSET_MAX); return offset * sizeof(uint32_t); } static uint32_t reset_id2reg_bit_pos(unsigned int reset_id) { uint32_t pos = reset_id & RESET_BIT_POS_MASK; assert(pos < 32); return pos; } static TEE_Result reset_assert(struct rstctrl *rstctrl, unsigned int to_us) { unsigned int id = to_stm32_rstline(rstctrl)->id; vaddr_t rcc_base = stm32_rcc_base(); uint32_t bit_mask = 0; size_t offset = 0; #ifdef CFG_STM32MP15 switch (id) { case MCU_HOLD_BOOT_R: /* * The RCC_MP_GCR is a read/write register. * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit */ io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); return TEE_SUCCESS; case MCU_R: /* MCU reset can only be written */ to_us = 0; break; default: break; } #endif offset = reset_id2reg_offset(id); bit_mask = BIT(reset_id2reg_bit_pos(id)); io_write32(rcc_base + offset, bit_mask); if (to_us) { uint32_t value = 0; if (IO_READ32_POLL_TIMEOUT(rcc_base + offset, value, value & bit_mask, 0, to_us)) return TEE_ERROR_GENERIC; } else { /* Make sure the above write is performed */ dsb(); } return TEE_SUCCESS; } static TEE_Result reset_deassert(struct rstctrl *rstctrl, unsigned int to_us) { unsigned int id = to_stm32_rstline(rstctrl)->id; vaddr_t rcc_base = stm32_rcc_base(); uint32_t bit_mask = 0; size_t offset = 0; #ifdef CFG_STM32MP15 switch (id) { case MCU_HOLD_BOOT_R: /* * The RCC_MP_GCR is a read/write register. * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit */ io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); return TEE_SUCCESS; case MCU_R: /* MCU reset deasserts by its own */ return TEE_SUCCESS; default: break; } #endif offset = reset_id2reg_offset(id) + RCC_MP_RSTCLRR_OFFSET; bit_mask = BIT(reset_id2reg_bit_pos(id)); io_write32(rcc_base + offset, bit_mask); if (to_us) { uint32_t value = 0; if (IO_READ32_POLL_TIMEOUT(rcc_base + offset, value, !(value & bit_mask), 0, to_us)) return TEE_ERROR_GENERIC; } else { /* Make sure the above write is performed */ dsb(); } return TEE_SUCCESS; } static const struct rstctrl_ops stm32_rstctrl_ops = { .assert_level = reset_assert, .deassert_level = reset_deassert, }; DECLARE_KEEP_PAGER(stm32_rstctrl_ops); static const struct rstctrl_ops *stm32_reset_get_ops(unsigned int id __unused) { return &stm32_rstctrl_ops; } static const struct stm32_reset_data stm32mp1_reset_data = { .get_rstctrl_ops = stm32_reset_get_ops }; DECLARE_KEEP_PAGER(stm32mp1_reset_data); static const struct dt_device_match stm32_rstctrl_match_table[] = { { .compatible = "st,stm32mp1-rcc", .compat_data = &stm32mp1_reset_data, }, { .compatible = "st,stm32mp1-rcc-secure", .compat_data = &stm32mp1_reset_data, }, { .compatible = "st,stm32mp13-rcc", .compat_data = &stm32mp1_reset_data, }, { } }; DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = { .name = "stm32_rstctrl", .type = DT_DRIVER_RSTCTRL, .match_table = stm32_rstctrl_match_table, .probe = stm32_rstctrl_provider_probe, }; optee_os-4.3.0/core/drivers/rstctrl/stm32mp25_rstctrl.c000066400000000000000000000201661464416617300230540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include "stm32_rstctrl.h" static TEE_Result stm32_reset_update(struct rstctrl *rstctrl, bool status, unsigned int to_us) { unsigned int id = to_stm32_rstline(rstctrl)->id; const struct stm32_reset_data *data = NULL; const struct stm32_reset_cfg *rst_line = NULL; vaddr_t address = stm32_rcc_base(); uint32_t bit_mask = 0; uint32_t value = 0; data = to_stm32_rstline(rstctrl)->data; rst_line = data->rst_lines[id]; if (!rst_line) return TEE_SUCCESS; address += rst_line->offset; bit_mask = BIT(rst_line->bit_index); if (!status && rst_line->no_deassert) return TEE_SUCCESS; status = rst_line->inverted ^ status; if (status) { if (rst_line->set_clr) io_write32(address, bit_mask); else io_setbits32_stm32shregs(address, bit_mask); } else { if (rst_line->set_clr) io_write32(address + RCC_MP_ENCLRR_OFFSET, bit_mask); else io_clrbits32_stm32shregs(address, bit_mask); } if (to_us && !rst_line->no_timeout) { if (IO_READ32_POLL_TIMEOUT(address, value, ((value & bit_mask) == bit_mask) == status, 0, to_us)) return TEE_ERROR_GENERIC; } else { /* Make sure the above write is performed */ dsb(); } return TEE_SUCCESS; } static TEE_Result stm32_reset_assert(struct rstctrl *rstctrl, unsigned int to_us) { return stm32_reset_update(rstctrl, true, to_us); } static TEE_Result stm32_reset_deassert(struct rstctrl *rstctrl, unsigned int to_us) { return stm32_reset_update(rstctrl, false, to_us); } static const struct rstctrl_ops stm32_rstctrl_ops = { .assert_level = stm32_reset_assert, .deassert_level = stm32_reset_deassert, }; #define STM32_RESET(id, _offset, _bit_index, _set_clr, _inverted, _no_deassert,\ _no_timeout)\ [(id)] = &(struct stm32_reset_cfg){\ .offset = (_offset),\ .bit_index = (_bit_index),\ .set_clr = (_set_clr),\ .inverted = (_inverted),\ .no_deassert = (_no_deassert),\ .no_timeout = (_no_timeout),\ } #define RST(id, _offset, _bit_index)\ STM32_RESET((id), (_offset), (_bit_index), false, false, false, false) #define RST_SETR(id, _offset, _bit_index)\ STM32_RESET((id), (_offset), (_bit_index), true, false, false, false) #define RST_INV(id, _offset, _bit_index)\ STM32_RESET((id), (_offset), (_bit_index), false, true, false, false) #define RST_SETR_NO_DEASSERT(id, _offset, _bit_index)\ STM32_RESET((id), (_offset), (_bit_index), false, false, true, false) #define RST_SETR_NO_DEASSERT_TIMEOUT(id, _offset, _bit_index)\ STM32_RESET((id), (_offset), (_bit_index), false, false, true, true) static const struct stm32_reset_cfg *stm32mp25_reset_cfg[STM32MP25_LAST_RESET] = { RST(TIM1_R, RCC_TIM1CFGR, 0), RST(TIM2_R, RCC_TIM2CFGR, 0), RST(TIM3_R, RCC_TIM3CFGR, 0), RST(TIM4_R, RCC_TIM4CFGR, 0), RST(TIM5_R, RCC_TIM5CFGR, 0), RST(TIM6_R, RCC_TIM6CFGR, 0), RST(TIM7_R, RCC_TIM7CFGR, 0), RST(TIM8_R, RCC_TIM8CFGR, 0), RST(TIM10_R, RCC_TIM10CFGR, 0), RST(TIM11_R, RCC_TIM11CFGR, 0), RST(TIM12_R, RCC_TIM12CFGR, 0), RST(TIM13_R, RCC_TIM13CFGR, 0), RST(TIM14_R, RCC_TIM14CFGR, 0), RST(TIM15_R, RCC_TIM15CFGR, 0), RST(TIM16_R, RCC_TIM16CFGR, 0), RST(TIM17_R, RCC_TIM17CFGR, 0), RST(TIM20_R, RCC_TIM20CFGR, 0), RST(LPTIM1_R, RCC_LPTIM1CFGR, 0), RST(LPTIM2_R, RCC_LPTIM2CFGR, 0), RST(LPTIM3_R, RCC_LPTIM3CFGR, 0), RST(LPTIM4_R, RCC_LPTIM4CFGR, 0), RST(LPTIM5_R, RCC_LPTIM5CFGR, 0), RST(SPI1_R, RCC_SPI1CFGR, 0), RST(SPI2_R, RCC_SPI2CFGR, 0), RST(SPI3_R, RCC_SPI3CFGR, 0), RST(SPI4_R, RCC_SPI4CFGR, 0), RST(SPI5_R, RCC_SPI5CFGR, 0), RST(SPI6_R, RCC_SPI6CFGR, 0), RST(SPI7_R, RCC_SPI7CFGR, 0), RST(SPI8_R, RCC_SPI8CFGR, 0), RST(SPDIFRX_R, RCC_SPDIFRXCFGR, 0), RST(USART1_R, RCC_USART1CFGR, 0), RST(USART2_R, RCC_USART2CFGR, 0), RST(USART3_R, RCC_USART3CFGR, 0), RST(UART4_R, RCC_UART4CFGR, 0), RST(UART5_R, RCC_UART5CFGR, 0), RST(USART6_R, RCC_USART6CFGR, 0), RST(UART7_R, RCC_UART7CFGR, 0), RST(UART8_R, RCC_UART8CFGR, 0), RST(UART9_R, RCC_UART9CFGR, 0), RST(LPUART1_R, RCC_LPUART1CFGR, 0), RST(IS2M_R, RCC_IS2MCFGR, 0), RST(I2C1_R, RCC_I2C1CFGR, 0), RST(I2C2_R, RCC_I2C2CFGR, 0), RST(I2C3_R, RCC_I2C3CFGR, 0), RST(I2C4_R, RCC_I2C4CFGR, 0), RST(I2C5_R, RCC_I2C5CFGR, 0), RST(I2C6_R, RCC_I2C6CFGR, 0), RST(I2C7_R, RCC_I2C7CFGR, 0), RST(I2C8_R, RCC_I2C8CFGR, 0), RST(SAI1_R, RCC_SAI1CFGR, 0), RST(SAI2_R, RCC_SAI2CFGR, 0), RST(SAI3_R, RCC_SAI3CFGR, 0), RST(SAI4_R, RCC_SAI4CFGR, 0), RST(MDF1_R, RCC_MDF1CFGR, 0), RST(MDF2_R, RCC_ADF1CFGR, 0), RST(FDCAN_R, RCC_FDCANCFGR, 0), RST(HDP_R, RCC_HDPCFGR, 0), RST(ADC12_R, RCC_ADC12CFGR, 0), RST(ADC3_R, RCC_ADC3CFGR, 0), RST(ETH1_R, RCC_ETH1CFGR, 0), RST(ETH2_R, RCC_ETH2CFGR, 0), RST(USB2_R, RCC_USB2CFGR, 0), RST(USB2PHY1_R, RCC_USB2PHY1CFGR, 0), RST(USB2PHY2_R, RCC_USB2PHY2CFGR, 0), RST(USB3DR_R, RCC_USB3DRCFGR, 0), RST(USB3PCIEPHY_R, RCC_USB3PCIEPHYCFGR, 0), RST(USBTC_R, RCC_USBTCCFGR, 0), RST(ETHSW_R, RCC_ETHSWCFGR, 0), RST(SDMMC1_R, RCC_SDMMC1CFGR, 0), RST(SDMMC1DLL_R, RCC_SDMMC1CFGR, 16), RST(SDMMC2_R, RCC_SDMMC2CFGR, 0), RST(SDMMC2DLL_R, RCC_SDMMC2CFGR, 16), RST(SDMMC3_R, RCC_SDMMC3CFGR, 0), RST(SDMMC3DLL_R, RCC_SDMMC3CFGR, 16), RST(GPU_R, RCC_GPUCFGR, 0), RST(LTDC_R, RCC_LTDCCFGR, 0), RST(DSI_R, RCC_DSICFGR, 0), RST(LVDS_R, RCC_LVDSCFGR, 0), RST(CSI_R, RCC_CSICFGR, 0), RST(DCMIPP_R, RCC_DCMIPPCFGR, 0), RST(CCI_R, RCC_CCICFGR, 0), RST(VDEC_R, RCC_VDECCFGR, 0), RST(VENC_R, RCC_VENCCFGR, 0), RST(WWDG1_R, RCC_WWDG1CFGR, 0), RST(WWDG2_R, RCC_WWDG2CFGR, 0), RST(VREF_R, RCC_VREFCFGR, 0), RST(DTS_R, RCC_DTSCFGR, 0), RST(CRC_R, RCC_CRCCFGR, 0), RST(SERC_R, RCC_SERCCFGR, 0), RST(OSPIIOM_R, RCC_OSPIIOMCFGR, 0), RST(I3C1_R, RCC_I3C1CFGR, 0), RST(I3C2_R, RCC_I3C2CFGR, 0), RST(I3C3_R, RCC_I3C3CFGR, 0), RST(I3C4_R, RCC_I3C4CFGR, 0), RST(RNG_R, RCC_RNGCFGR, 0), RST(PKA_R, RCC_PKACFGR, 0), RST(SAES_R, RCC_SAESCFGR, 0), RST(HASH_R, RCC_HASHCFGR, 0), RST(CRYP1_R, RCC_CRYP1CFGR, 0), RST(CRYP2_R, RCC_CRYP2CFGR, 0), RST(PCIE_R, RCC_PCIECFGR, 0), RST(OSPI1_R, RCC_OSPI1CFGR, 0), RST(OSPI1DLL_R, RCC_OSPI1CFGR, 16), RST(OSPI2_R, RCC_OSPI2CFGR, 0), RST(OSPI2DLL_R, RCC_OSPI2CFGR, 16), RST(DBG_R, RCC_DBGCFGR, 12), RST_SETR(IWDG2_KER_R, RCC_IWDGC1CFGSETR, 18), RST_SETR(IWDG4_KER_R, RCC_IWDGC2CFGSETR, 18), RST_SETR(IWDG1_SYS_R, RCC_IWDGC1CFGSETR, 0), RST_SETR(IWDG2_SYS_R, RCC_IWDGC1CFGSETR, 2), RST_SETR(IWDG3_SYS_R, RCC_IWDGC2CFGSETR, 0), RST_SETR(IWDG4_SYS_R, RCC_IWDGC2CFGSETR, 2), RST_INV(C2_HOLDBOOT_R, RCC_CPUBOOTCR, 0), RST_INV(C1_HOLDBOOT_R, RCC_CPUBOOTCR, 1), RST_SETR_NO_DEASSERT_TIMEOUT(C1_R, RCC_C1RSTCSETR, 0), RST_SETR_NO_DEASSERT_TIMEOUT(C1P1POR_R, RCC_C1P1RSTCSETR, 0), RST_SETR_NO_DEASSERT_TIMEOUT(C1P1_R, RCC_C1P1RSTCSETR, 1), RST_SETR_NO_DEASSERT_TIMEOUT(C2_R, RCC_C2RSTCSETR, 0), RST_SETR_NO_DEASSERT_TIMEOUT(SYS_R, RCC_GRSTCSETR, 0), /* * Don't manage reset lines of RIF aware resources * DDRCP_R, DDRCAPB_R, DDRPHYCAPB_R, DDRCFG_R, DDR_R, * IPCC1_R, IPCC2_R, * HPDMA1_R, HPDMA2_R, HPDMA3_R, LPDMA_R, * GPIOA_R, GPIOB_R, GPIOC_R, GPIOD_R, * GPIOE_R, GPIOF_R, GPIOG_R, GPIOH_R, * GPIOI_R, GPIOJ_R, GPIOK_R, GPIOZ_R, * HSEM_R, * FMC_R, */ }; static const struct rstctrl_ops *stm32_reset_get_ops(unsigned int id __unused) { return &stm32_rstctrl_ops; } static const struct stm32_reset_data stm32mp25_reset_data = { .nb_lines = ARRAY_SIZE(stm32mp25_reset_cfg), .rst_lines = stm32mp25_reset_cfg, .get_rstctrl_ops = stm32_reset_get_ops, }; static const struct dt_device_match stm32_rstctrl_match_table[] = { { .compatible = "st,stm32mp25-rcc", .compat_data = &stm32mp25_reset_data, }, { } }; DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = { .name = "stm32_rstctrl", .type = DT_DRIVER_RSTCTRL, .match_table = stm32_rstctrl_match_table, .probe = stm32_rstctrl_provider_probe, }; optee_os-4.3.0/core/drivers/rstctrl/sub.mk000066400000000000000000000002511464416617300205720ustar00rootroot00000000000000srcs-y += rstctrl.c srcs-$(CFG_STM32_RSTCTRL) += stm32_rstctrl.c srcs-$(CFG_STM32MP1_RSTCTRL) += stm32mp1_rstctrl.c srcs-$(CFG_STM32MP25_RSTCTRL) += stm32mp25_rstctrl.c optee_os-4.3.0/core/drivers/rtc/000077500000000000000000000000001464416617300165455ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/rtc/rtc.c000066400000000000000000000006051464416617300175020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip */ #include #include #include struct rtc *rtc_device; void rtc_register(struct rtc *rtc) { /* One RTC is supported only */ assert(!rtc_device); /* RTC should *at least* allow to get the time */ assert(rtc && rtc->ops && rtc->ops->get_time); rtc_device = rtc; } optee_os-4.3.0/core/drivers/rtc/sub.mk000066400000000000000000000000411464416617300176620ustar00rootroot00000000000000srcs-$(CFG_DRIVERS_RTC) += rtc.c optee_os-4.3.0/core/drivers/scif.c000066400000000000000000000055361464416617300170560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, GlobalLogic * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #define SCIF_SCSCR (0x08) #define SCIF_SCFSR (0x10) #define SCIF_SCFTDR (0x0C) #define SCIF_SCFCR (0x18) #define SCIF_SCFDR (0x1C) #define SCSCR_TE BIT(5) #define SCFSR_TDFE BIT(5) #define SCFSR_TEND BIT(6) #define SCFDR_T_SHIFT 8 #define SCIF_TX_FIFO_SIZE 16 static vaddr_t chip_to_base(struct serial_chip *chip) { struct scif_uart_data *pd = container_of(chip, struct scif_uart_data, chip); return io_pa_or_va(&pd->base, SCIF_REG_SIZE); } static void scif_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read16(base + SCIF_SCFSR) & SCFSR_TEND)) ; } static void scif_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); /* Wait until there is space in the FIFO */ while ((io_read16(base + SCIF_SCFDR) >> SCFDR_T_SHIFT) >= SCIF_TX_FIFO_SIZE) ; io_write8(base + SCIF_SCFTDR, ch); io_clrbits16(base + SCIF_SCFSR, SCFSR_TEND | SCFSR_TDFE); } static const struct serial_ops scif_uart_ops = { .flush = scif_uart_flush, .putc = scif_uart_putc, }; DECLARE_KEEP_PAGER(scif_uart_ops); void scif_uart_init(struct scif_uart_data *pd, paddr_t pbase) { vaddr_t base; pd->base.pa = pbase; pd->chip.ops = &scif_uart_ops; base = io_pa_or_va(&pd->base, SCIF_REG_SIZE); /* Set Transmit Enable in Control register */ io_setbits16(base + SCIF_SCSCR, SCSCR_TE); scif_uart_flush(&pd->chip); } optee_os-4.3.0/core/drivers/scmi-msg/000077500000000000000000000000001464416617300174745ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/scmi-msg/base.c000066400000000000000000000115671464416617300205640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include "base.h" #include "common.h" static bool message_id_is_supported(unsigned int message_id); static void report_version(struct scmi_msg *msg) { struct scmi_protocol_version_p2a return_values = { .status = SCMI_SUCCESS, .version = SCMI_PROTOCOL_VERSION_BASE, }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void report_attributes(struct scmi_msg *msg) { size_t protocol_count = plat_scmi_protocol_count(); struct scmi_protocol_attributes_p2a return_values = { .status = SCMI_SUCCESS, /* Null agent count since agent discovery is not supported */ .attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0), }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void report_message_attributes(struct scmi_msg *msg) { struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; struct scmi_protocol_message_attributes_p2a return_values = { .status = SCMI_SUCCESS, /* For this protocol, attributes shall be zero */ .attributes = 0, }; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (!message_id_is_supported(in_args->message_id)) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void discover_vendor(struct scmi_msg *msg) { const char *name = plat_scmi_vendor_name(); struct scmi_base_discover_vendor_p2a return_values = { .status = SCMI_SUCCESS, }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name); scmi_write_response(msg, &return_values, sizeof(return_values)); } static void discover_sub_vendor(struct scmi_msg *msg) { const char *name = plat_scmi_sub_vendor_name(); struct scmi_base_discover_sub_vendor_p2a return_values = { .status = SCMI_SUCCESS, }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name); scmi_write_response(msg, &return_values, sizeof(return_values)); } static void discover_implementation_version(struct scmi_msg *msg) { struct scmi_protocol_version_p2a return_values = { .status = SCMI_SUCCESS, .version = SCMI_IMPL_VERSION, }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static unsigned int count_protocols_in_list(const uint8_t *protocol_list) { unsigned int count = 0; if (protocol_list) while (protocol_list[count]) count++; return count; } static void discover_list_protocols(struct scmi_msg *msg) { const struct scmi_base_discover_list_protocols_a2p *a2p = NULL; struct scmi_base_discover_list_protocols_p2a p2a = { .status = SCMI_SUCCESS, }; const uint8_t *list = NULL; unsigned int count = 0; if (msg->in_size != sizeof(*a2p)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } a2p = (void *)msg->in; list = plat_scmi_protocol_list(msg->channel_id); count = count_protocols_in_list(list); if (count > a2p->skip) count = MIN(count - a2p->skip, msg->out_size - sizeof(p2a)); else count = 0; p2a.num_protocols = count; memcpy(msg->out, &p2a, sizeof(p2a)); memcpy(msg->out + sizeof(p2a), list + a2p->skip, count); msg->out_size_out = sizeof(p2a) + ROUNDUP(count, sizeof(uint32_t)); } static const scmi_msg_handler_t scmi_base_handler_table[] = { [SCMI_PROTOCOL_VERSION] = report_version, [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, [SCMI_BASE_DISCOVER_VENDOR] = discover_vendor, [SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor, [SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] = discover_implementation_version, [SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols, }; static bool message_id_is_supported(unsigned int message_id) { return message_id < ARRAY_SIZE(scmi_base_handler_table) && scmi_base_handler_table[message_id]; } scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg) { const size_t array_size = ARRAY_SIZE(scmi_base_handler_table); unsigned int message_id = 0; if (msg->message_id >= array_size) { DMSG("Base handle not found %u", msg->message_id); return NULL; } message_id = confine_array_index(msg->message_id, array_size); return scmi_base_handler_table[message_id]; } optee_os-4.3.0/core/drivers/scmi-msg/base.h000066400000000000000000000040331464416617300205570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #ifndef SCMI_MSG_BASE_H #define SCMI_MSG_BASE_H #include #include #include "common.h" #define SCMI_PROTOCOL_VERSION_BASE 0x20000 #define SCMI_DEFAULT_STRING_LENGTH 16 enum scmi_base_message_id { SCMI_BASE_DISCOVER_VENDOR = 0x003, SCMI_BASE_DISCOVER_SUB_VENDOR = 0x004, SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x005, SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x006, SCMI_BASE_DISCOVER_AGENT = 0x007, SCMI_BASE_NOTIFY_ERRORS = 0x008, }; /* * PROTOCOL_ATTRIBUTES */ #define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS 0 #define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS 8 #define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK 0xFF #define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK 0xFF00 #define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \ ((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \ SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \ (((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \ SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK)) /* * BASE_DISCOVER_VENDOR */ struct scmi_base_discover_vendor_p2a { int32_t status; char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; }; /* * BASE_DISCOVER_SUB_VENDOR */ struct scmi_base_discover_sub_vendor_p2a { int32_t status; char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; }; /* * BASE_DISCOVER_IMPLEMENTATION_VERSION * No special structure right now, see protocol_version. */ /* * BASE_DISCOVER_LIST_PROTOCOLS */ struct scmi_base_discover_list_protocols_a2p { uint32_t skip; }; struct scmi_base_discover_list_protocols_p2a { int32_t status; uint32_t num_protocols; uint32_t protocols[]; }; /* * scmi_msg_get_base_handler - Return a handler for a base message * @msg - message to process * Return a function handler for the message or NULL */ scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg); #endif /* SCMI_MSG_BASE_H */ optee_os-4.3.0/core/drivers/scmi-msg/clock.c000066400000000000000000000244101464416617300207340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include "clock.h" #include "common.h" static bool message_id_is_supported(unsigned int message_id); size_t __weak plat_scmi_clock_count(unsigned int channel_id __unused) { return 0; } const char __weak *plat_scmi_clock_get_name(unsigned int channel_id __unused, unsigned int scmi_id __unused) { return NULL; } int32_t __weak plat_scmi_clock_rates_array(unsigned int channel_id __unused, unsigned int scmi_id __unused, size_t start_index __unused, unsigned long *rates __unused, size_t *nb_elts __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_clock_rates_by_step(unsigned int channel_id __unused, unsigned int scmi_id __unused, unsigned long *steps __unused) { return SCMI_NOT_SUPPORTED; } unsigned long __weak plat_scmi_clock_get_rate(unsigned int channel_id __unused, unsigned int scmi_id __unused) { return 0; } int32_t __weak plat_scmi_clock_set_rate(unsigned int channel_id __unused, unsigned int scmi_id __unused, unsigned long rate __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_clock_get_state(unsigned int channel_id __unused, unsigned int scmi_id __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_clock_set_state(unsigned int channel_id __unused, unsigned int scmi_id __unused, bool enable_not_disable __unused) { return SCMI_NOT_SUPPORTED; } static void report_version(struct scmi_msg *msg) { struct scmi_protocol_version_p2a return_values = { .status = SCMI_SUCCESS, .version = SCMI_PROTOCOL_VERSION_CLOCK, }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void report_attributes(struct scmi_msg *msg) { size_t clk_count = plat_scmi_clock_count(msg->channel_id); struct scmi_protocol_attributes_p2a return_values = { .status = SCMI_SUCCESS, .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1, clk_count), }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void report_message_attributes(struct scmi_msg *msg) { struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; struct scmi_protocol_message_attributes_p2a return_values = { .status = SCMI_SUCCESS, /* For this protocol, attributes shall be zero */ .attributes = 0, }; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (!message_id_is_supported(in_args->message_id)) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void scmi_clock_attributes(struct scmi_msg *msg) { const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in; struct scmi_clock_attributes_p2a return_values = { .status = SCMI_SUCCESS, }; const char *name = NULL; unsigned int clock_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } clock_id = confine_array_index(in_args->clock_id, plat_scmi_clock_count(msg->channel_id)); name = plat_scmi_clock_get_name(msg->channel_id, clock_id); if (!name) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } COPY_NAME_IDENTIFIER(return_values.clock_name, name); return_values.attributes = plat_scmi_clock_get_state(msg->channel_id, clock_id); scmi_write_response(msg, &return_values, sizeof(return_values)); } static void scmi_clock_rate_get(struct scmi_msg *msg) { const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in; unsigned long rate = 0; struct scmi_clock_rate_get_p2a return_values = { }; unsigned int clock_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } clock_id = confine_array_index(in_args->clock_id, plat_scmi_clock_count(msg->channel_id)); rate = plat_scmi_clock_get_rate(msg->channel_id, clock_id); reg_pair_from_64(rate, return_values.rate + 1, return_values.rate); scmi_write_response(msg, &return_values, sizeof(return_values)); } static void scmi_clock_rate_set(struct scmi_msg *msg) { const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in; uint64_t rate_64 = 0; unsigned long rate = 0; int32_t status = 0; unsigned int clock_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } clock_id = confine_array_index(in_args->clock_id, plat_scmi_clock_count(msg->channel_id)); rate_64 = reg_pair_to_64(in_args->rate[1], in_args->rate[0]); rate = rate_64; status = plat_scmi_clock_set_rate(msg->channel_id, clock_id, rate); scmi_status_response(msg, status); } static void scmi_clock_config_set(struct scmi_msg *msg) { const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in; int32_t status = SCMI_GENERIC_ERROR; bool enable = false; unsigned int clock_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } clock_id = confine_array_index(in_args->clock_id, plat_scmi_clock_count(msg->channel_id)); enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK; status = plat_scmi_clock_set_state(msg->channel_id, clock_id, enable); scmi_status_response(msg, status); } #define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \ SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \ SCMI_CLOCK_RATE_FORMAT_LIST, \ (_rem_rates)) #define SCMI_RATES_BY_STEP \ SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3, \ SCMI_CLOCK_RATE_FORMAT_RANGE, \ 0) #define RATE_DESC_SIZE sizeof(struct scmi_clock_rate) static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates, size_t nb_elt) { uint32_t *out = NULL; size_t n = 0; assert(IS_ALIGNED_WITH_TYPE(dest, uint32_t)); out = (uint32_t *)(uintptr_t)dest; for (n = 0; n < nb_elt; n++) { uint64_t rate = rates[n]; reg_pair_from_64(rate, out + 2 * n + 1, out + 2 * n); } } static void scmi_clock_describe_rates(struct scmi_msg *msg) { const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in; struct scmi_clock_describe_rates_p2a p2a = { }; size_t nb_rates = 0; int32_t status = SCMI_GENERIC_ERROR; unsigned int clock_id = 0; unsigned int out_count = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->clock_id >= plat_scmi_clock_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } clock_id = confine_array_index(in_args->clock_id, plat_scmi_clock_count(msg->channel_id)); /* Platform may support array rate description */ status = plat_scmi_clock_rates_array(msg->channel_id, clock_id, 0, NULL, &nb_rates); if (status == SCMI_SUCCESS) { unsigned int rate_index = in_args->rate_index; unsigned int remaining = 0; size_t avail_sz = msg->out_size - sizeof(p2a); char *out_rates = msg->out + sizeof(p2a); if (avail_sz < RATE_DESC_SIZE && nb_rates) { status = SCMI_PROTOCOL_ERROR; goto out; } while (avail_sz >= RATE_DESC_SIZE && rate_index < nb_rates) { unsigned long rate = 0; size_t cnt = 1; status = plat_scmi_clock_rates_array(msg->channel_id, clock_id, rate_index, &rate, &cnt); if (status) goto out; write_rate_desc_array_in_buffer(out_rates, &rate, cnt); avail_sz -= RATE_DESC_SIZE; out_rates += RATE_DESC_SIZE; rate_index++; } out_count = rate_index - in_args->rate_index; remaining = nb_rates - in_args->rate_index; p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(out_count, remaining); } else if (status == SCMI_NOT_SUPPORTED) { unsigned long triplet[3] = { 0, 0, 0 }; if (msg->out_size < sizeof(p2a) + 3 * RATE_DESC_SIZE) { status = SCMI_PROTOCOL_ERROR; goto out; } /* Platform may support min/max/step triplet description */ status = plat_scmi_clock_rates_by_step(msg->channel_id, clock_id, triplet); if (status) goto out; write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), triplet, 3); out_count = 3; p2a.num_rates_flags = SCMI_RATES_BY_STEP; } else { /* Fallthrough generic exit sequence below with error status */ } out: if (status) { scmi_status_response(msg, status); } else { p2a.status = SCMI_SUCCESS; memcpy(msg->out, &p2a, sizeof(p2a)); msg->out_size_out = sizeof(p2a) + out_count * RATE_DESC_SIZE; } } static const scmi_msg_handler_t scmi_clock_handler_table[] = { [SCMI_PROTOCOL_VERSION] = report_version, [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes, [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates, [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set, [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get, [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set, }; static bool message_id_is_supported(unsigned int message_id) { return message_id < ARRAY_SIZE(scmi_clock_handler_table) && scmi_clock_handler_table[message_id]; } scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg) { const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table); unsigned int message_id = 0; if (msg->message_id >= array_size) { DMSG("Clock handle not found %u", msg->message_id); return NULL; } message_id = confine_array_index(msg->message_id, array_size); return scmi_clock_handler_table[message_id]; } optee_os-4.3.0/core/drivers/scmi-msg/clock.h000066400000000000000000000075761464416617300207570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #ifndef SCMI_MSG_CLOCK_H #define SCMI_MSG_CLOCK_H #include #include #include "common.h" #define SCMI_PROTOCOL_VERSION_CLOCK 0x20000 /* * Identifiers of the SCMI Clock Management Protocol commands */ enum scmi_clock_command_id { SCMI_CLOCK_ATTRIBUTES = 0x003, SCMI_CLOCK_DESCRIBE_RATES = 0x004, SCMI_CLOCK_RATE_SET = 0x005, SCMI_CLOCK_RATE_GET = 0x006, SCMI_CLOCK_CONFIG_SET = 0x007, }; /* Protocol attributes */ #define SCMI_CLOCK_CLOCK_COUNT_MASK GENMASK_32(15, 0) #define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK GENMASK_32(23, 16) #define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \ ((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \ (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK))) struct scmi_clock_attributes_a2p { uint32_t clock_id; }; #define SCMI_CLOCK_NAME_LENGTH_MAX 16 struct scmi_clock_attributes_p2a { int32_t status; uint32_t attributes; char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; }; /* * Clock Rate Get */ struct scmi_clock_rate_get_a2p { uint32_t clock_id; }; struct scmi_clock_rate_get_p2a { int32_t status; uint32_t rate[2]; }; /* * Clock Rate Set */ /* If set, set the new clock rate asynchronously */ #define SCMI_CLOCK_RATE_SET_ASYNC_POS 0 /* If set, do not send a delayed asynchronous response */ #define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS 1 /* Round up, if set, otherwise round down */ #define SCMI_CLOCK_RATE_SET_ROUND_UP_POS 2 /* If set, the platform chooses the appropriate rounding mode */ #define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS 3 #define SCMI_CLOCK_RATE_SET_ASYNC_MASK \ BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS) #define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \ BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS) #define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \ BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS) #define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \ BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS) struct scmi_clock_rate_set_a2p { uint32_t flags; uint32_t clock_id; uint32_t rate[2]; }; struct scmi_clock_rate_set_p2a { int32_t status; }; /* * Clock Config Set */ #define SCMI_CLOCK_CONFIG_SET_ENABLE_POS 0 #define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \ BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS) struct scmi_clock_config_set_a2p { uint32_t clock_id; uint32_t attributes; }; struct scmi_clock_config_set_p2a { int32_t status; }; /* * Clock Describe Rates */ #define SCMI_CLOCK_RATE_FORMAT_RANGE 1 #define SCMI_CLOCK_RATE_FORMAT_LIST 0 #define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK GENMASK_32(31, 16) #define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS 16 #define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK BIT(12) #define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS 12 #define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK GENMASK_32(11, 0) #define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \ ( \ ((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \ (((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \ SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \ (((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \ SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \ ) struct scmi_clock_rate { uint32_t low; uint32_t high; }; struct scmi_clock_describe_rates_a2p { uint32_t clock_id; uint32_t rate_index; }; struct scmi_clock_describe_rates_p2a { int32_t status; uint32_t num_rates_flags; struct scmi_clock_rate rates[]; }; #ifdef CFG_SCMI_MSG_CLOCK /* * scmi_msg_get_clock_handler - Return a handler for a clock message * @msg - message to process * Return a function handler for the message or NULL */ scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg); #else static inline scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg __unused) { return NULL; } #endif #endif /* SCMI_MSG_CLOCK_H */ optee_os-4.3.0/core/drivers/scmi-msg/clock_generic.c000066400000000000000000000112101464416617300224220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Microchip */ #include #include #include #include #include #include #include "clock.h" /** * struct scmi_clk - Binds an SCMI channel/clock to a core clk reference * @clk: Core clock reference * @channel_id: SCMI server channel handle exposing the clock * @scmi_id: SCMI clock domain ID * @enabled: SCMI clock state * @link: Reference in SCMI server clock list */ struct scmi_clk { struct clk *clk; unsigned int channel_id; unsigned int scmi_id; bool enabled; SLIST_ENTRY(scmi_clk) link; }; static bool scmi_clk_init_done; static SLIST_HEAD(, scmi_clk) scmi_clk_list = SLIST_HEAD_INITIALIZER(scmi_clk_list); size_t plat_scmi_clock_count(unsigned int channel_id) { unsigned int count = 0; unsigned int max_id = 0; struct scmi_clk *clk = NULL; SLIST_FOREACH(clk, &scmi_clk_list, link) { if (clk->channel_id == channel_id) { count++; max_id = MAX(max_id, clk->scmi_id); } } if (!count) return 0; /* IDs are starting from 0 so we need to return max_id + 1 for count */ return max_id + 1; } static struct scmi_clk *clk_scmi_get_by_id(unsigned int channel_id, unsigned int scmi_id) { struct scmi_clk *clk = NULL; SLIST_FOREACH(clk, &scmi_clk_list, link) if (clk->channel_id == channel_id && clk->scmi_id == scmi_id) return clk; return NULL; } const char *plat_scmi_clock_get_name(unsigned int channel_id, unsigned int scmi_id) { struct scmi_clk *clk = NULL; clk = clk_scmi_get_by_id(channel_id, scmi_id); if (!clk) return "dummy"; return clk_get_name(clk->clk); } int32_t plat_scmi_clock_rates_array(unsigned int channel_id, unsigned int scmi_id, size_t start_index, unsigned long *rates, size_t *nb_elts) { struct scmi_clk *clk = NULL; clk = clk_scmi_get_by_id(channel_id, scmi_id); if (!clk) return SCMI_DENIED; if (clk_get_rates_array(clk->clk, start_index, rates, nb_elts)) return SCMI_GENERIC_ERROR; return SCMI_SUCCESS; } unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, unsigned int scmi_id) { struct scmi_clk *clk = NULL; clk = clk_scmi_get_by_id(channel_id, scmi_id); if (!clk) return 0; return clk_get_rate(clk->clk); } int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id, unsigned long rate) { TEE_Result res = TEE_ERROR_GENERIC; struct scmi_clk *clk = NULL; clk = clk_scmi_get_by_id(channel_id, scmi_id); if (!clk) return SCMI_DENIED; res = clk_set_rate(clk->clk, rate); if (res) return SCMI_GENERIC_ERROR; return SCMI_SUCCESS; } int32_t plat_scmi_clock_get_state(unsigned int channel_id, unsigned int scmi_id) { struct scmi_clk *clk = NULL; clk = clk_scmi_get_by_id(channel_id, scmi_id); if (!clk) return false; return clk->enabled; } int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, bool enable_not_disable) { struct scmi_clk *clk = NULL; clk = clk_scmi_get_by_id(channel_id, scmi_id); if (!clk) { if (enable_not_disable) return SCMI_DENIED; else return SCMI_SUCCESS; } if (enable_not_disable) { if (!clk->enabled) { if (clk_enable(clk->clk)) return SCMI_GENERIC_ERROR; clk->enabled = true; } } else { if (clk->enabled) { clk_disable(clk->clk); clk->enabled = false; } } return SCMI_SUCCESS; } static TEE_Result clk_check_scmi_id(struct clk *new_clk, unsigned int channel_id, unsigned int scmi_id) { struct scmi_clk *clk = NULL; SLIST_FOREACH(clk, &scmi_clk_list, link) { if (clk->channel_id == channel_id && clk->scmi_id == scmi_id) { EMSG("SCMI channel %u, clock %u already registered", channel_id, scmi_id); return TEE_ERROR_BAD_PARAMETERS; } } if (strlen(clk_get_name(new_clk)) >= SCMI_CLOCK_NAME_LENGTH_MAX) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } TEE_Result scmi_clk_add(struct clk *clk, unsigned int channel_id, unsigned int scmi_id) { TEE_Result res = TEE_ERROR_GENERIC; struct scmi_clk *scmi_clk = NULL; if (scmi_clk_init_done) return TEE_ERROR_BAD_STATE; res = clk_check_scmi_id(clk, channel_id, scmi_id); if (res) return res; scmi_clk = calloc(1, sizeof(*scmi_clk)); if (!scmi_clk) return TEE_ERROR_OUT_OF_MEMORY; scmi_clk->clk = clk; scmi_clk->channel_id = channel_id; scmi_clk->scmi_id = scmi_id; scmi_clk->enabled = false; SLIST_INSERT_HEAD(&scmi_clk_list, scmi_clk, link); return TEE_SUCCESS; } static TEE_Result scmi_clk_init_fini(void) { scmi_clk_init_done = true; return TEE_SUCCESS; } release_init_resource(scmi_clk_init_fini); optee_os-4.3.0/core/drivers/scmi-msg/common.h000066400000000000000000000110071464416617300211340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #ifndef SCMI_MSG_COMMON_H #define SCMI_MSG_COMMON_H #include #include #include #include #include #define SCMI_VERSION 0x30000 #define SCMI_IMPL_VERSION 0 /* * Secure copy of input payload: we expect small messages, at most the legacy * SMT messages that are 128 bytes (Linux kernel) including SMT header. */ #define SCMI_SEC_PAYLOAD_SIZE 92 /* * Copy name identifier in target buffer following the SCMI specification * that state name identifier shall be a null terminated string. */ #define COPY_NAME_IDENTIFIER(_dst_array, _name) \ do { \ assert(strlen(_name) < sizeof(_dst_array)); \ strncpy((_dst_array), (_name), sizeof(_dst_array)); \ } while (0) /* Common command identifiers shared by all procotols */ enum scmi_common_message_id { SCMI_PROTOCOL_VERSION = 0x000, SCMI_PROTOCOL_ATTRIBUTES = 0x001, SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002 }; /* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */ struct scmi_protocol_version_p2a { int32_t status; uint32_t version; }; /* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */ struct scmi_protocol_attributes_p2a { int32_t status; uint32_t attributes; }; /* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */ struct scmi_protocol_message_attributes_a2p { uint32_t message_id; }; /* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */ struct scmi_protocol_message_attributes_p2a { int32_t status; uint32_t attributes; }; /* * struct scmi_msg - SCMI message context * * @channel_id: SCMI channel ID, safely set from secure world * @protocol_id: SCMI protocol ID for the related message, set by caller agent * @message_id: SCMI message ID for the related message, set by caller agent * @in: Address of the incoming message payload copied in secure memory * @in_size: Byte length of the incoming message payload, set by caller agent * @out: Address of of the output message payload message in non-secure memory * @out_size: Byte length of the provisionned output buffer * @out_size_out: Byte length of the output message payload */ struct scmi_msg { unsigned int channel_id; unsigned int protocol_id; unsigned int message_id; char *in; size_t in_size; char *out; size_t out_size; size_t out_size_out; }; /* * Type scmi_msg_handler_t is used by procotol drivers to safely find * the handler function for the incoming message ID. */ typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg); /* * Process Read, process and write response for input SCMI message * * @msg: SCMI message context */ void scmi_process_message(struct scmi_msg *msg); /* * Write SCMI response payload to output message shared memory * * @msg: SCMI message context * @payload: Output message payload * @size: Byte size of output message payload */ void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size); /* * Write status only SCMI response payload to output message shared memory * * @msg: SCMI message context * @status: SCMI status value returned to caller */ void scmi_status_response(struct scmi_msg *msg, int32_t status); /* * Claim access to channel * @channel: SCMI channel reference * Return true upon success or false if the channel is already busy */ bool scmi_msg_claim_channel(struct scmi_msg_channel *channel); /* * Release access channel * @channel: SCMI channel reference */ void scmi_msg_release_channel(struct scmi_msg_channel *channel); /* * Entry for processing a channel using SMT shared memory protocol * @channel_id: SCMI channel identifier provided by client * @payload_buf: Secure buffer where to copy input message */ void scmi_entry_smt(unsigned int channel_id, uint32_t *payload_buf); /* * Entry for processing a channel using SMT shared memory protocol * * @channel_id: SCMI channel identifier provided by client * @in_buf: Shared buffer storing input SCMI message * @in_size: Byte size of @in_buf, including MSG header and message payload * @out_buf: Shared buffer storing input SCMI message * @out_size: [in] @out_buf max byte size * [out] @out_buf output byte size (MSG header and message payload) * @sec_buf: Secure buffer where to copy input message */ TEE_Result scmi_entry_msg(unsigned int channel_id, void *in_buf, size_t in_size, void *out_buf, size_t *out_size, uint32_t *sec_buf); #endif /* SCMI_MSG_COMMON_H */ optee_os-4.3.0/core/drivers/scmi-msg/entry.c000066400000000000000000000071731464416617300210110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include "base.h" #include "clock.h" #include "common.h" #include "reset_domain.h" #include "voltage_domain.h" /* Provision input message payload buffers for each supported entry channel */ #define SCMI_PAYLOAD_U32_MAX (SCMI_SEC_PAYLOAD_SIZE / sizeof(uint32_t)) static uint32_t threaded_payload[CFG_NUM_THREADS][SCMI_PAYLOAD_U32_MAX] __maybe_unused; static uint32_t interrupt_payload[CFG_TEE_CORE_NB_CORE][SCMI_PAYLOAD_U32_MAX] __maybe_unused; static uint32_t fastcall_payload[CFG_TEE_CORE_NB_CORE][SCMI_PAYLOAD_U32_MAX] __maybe_unused; /* SMP protection on channel->busy field */ static unsigned int smt_channels_lock; /* If channel is not busy, set busy and return true, otherwise return false */ bool scmi_msg_claim_channel(struct scmi_msg_channel *channel) { uint32_t exceptions = cpu_spin_lock_xsave(&smt_channels_lock); bool channel_is_busy = channel->busy; if (!channel_is_busy) channel->busy = true; cpu_spin_unlock_xrestore(&smt_channels_lock, exceptions); return !channel_is_busy; } void scmi_msg_release_channel(struct scmi_msg_channel *channel) { channel->busy = false; } void scmi_status_response(struct scmi_msg *msg, int32_t status) { assert(msg->out && msg->out_size >= sizeof(int32_t)); memcpy(msg->out, &status, sizeof(int32_t)); msg->out_size_out = sizeof(int32_t); } void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size) { if (msg->out_size < size) { DMSG("SCMI resp. payload %zu > %zu bytes", size, msg->out_size); scmi_status_response(msg, SCMI_PROTOCOL_ERROR); } else { memcpy(msg->out, payload, size); msg->out_size_out = size; } } void scmi_process_message(struct scmi_msg *msg) { scmi_msg_handler_t handler = NULL; switch (msg->protocol_id) { case SCMI_PROTOCOL_ID_BASE: handler = scmi_msg_get_base_handler(msg); break; case SCMI_PROTOCOL_ID_CLOCK: handler = scmi_msg_get_clock_handler(msg); break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: handler = scmi_msg_get_rd_handler(msg); break; case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: handler = scmi_msg_get_voltd_handler(msg); break; default: break; } if (handler) { handler(msg); return; } DMSG("Channel %u Protocol %#x Message %#x: not supported", msg->channel_id, msg->protocol_id, msg->message_id); scmi_status_response(msg, SCMI_NOT_SUPPORTED); } #ifdef CFG_SCMI_MSG_SMT_FASTCALL_ENTRY void scmi_smt_fastcall_smc_entry(unsigned int channel_id) { assert(!plat_scmi_get_channel(channel_id)->threaded); scmi_entry_smt(channel_id, fastcall_payload[get_core_pos()]); } #endif #ifdef CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY void scmi_smt_interrupt_entry(unsigned int channel_id) { assert(!plat_scmi_get_channel(channel_id)->threaded); scmi_entry_smt(channel_id, interrupt_payload[get_core_pos()]); } #endif #ifdef CFG_SCMI_MSG_SMT_THREAD_ENTRY void scmi_smt_threaded_entry(unsigned int channel_id) { assert(plat_scmi_get_channel(channel_id)->threaded); scmi_entry_smt(channel_id, threaded_payload[thread_get_id()]); } #endif #ifdef CFG_SCMI_MSG_SHM_MSG TEE_Result scmi_msg_threaded_entry(unsigned int channel_id, void *in_buf, size_t in_size, void *out_buf, size_t *out_size) { assert(plat_scmi_get_channel(channel_id)->threaded); return scmi_entry_msg(channel_id, in_buf, in_size, out_buf, out_size, threaded_payload[thread_get_id()]); } #endif optee_os-4.3.0/core/drivers/scmi-msg/reset_domain.c000066400000000000000000000121751464416617300223170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include "common.h" #include "reset_domain.h" static bool message_id_is_supported(unsigned int message_id); size_t __weak plat_scmi_rd_count(unsigned int channel_id __unused) { return 0; } const char __weak *plat_scmi_rd_get_name(unsigned int channel_id __unused, unsigned int scmi_id __unused) { return NULL; } int32_t __weak plat_scmi_rd_autonomous(unsigned int channel_id __unused, unsigned int scmi_id __unused, unsigned int state __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_rd_set_state(unsigned int channel_id __unused, unsigned int scmi_id __unused, bool assert_not_deassert __unused) { return SCMI_NOT_SUPPORTED; } static void report_version(struct scmi_msg *msg) { struct scmi_protocol_version_p2a return_values = { .status = SCMI_SUCCESS, .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void report_attributes(struct scmi_msg *msg) { struct scmi_protocol_attributes_p2a return_values = { .status = SCMI_SUCCESS, .attributes = plat_scmi_rd_count(msg->channel_id), }; if (msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void report_message_attributes(struct scmi_msg *msg) { struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; struct scmi_protocol_message_attributes_p2a return_values = { .status = SCMI_SUCCESS, /* For this protocol, attributes shall be zero */ .attributes = 0, }; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (!message_id_is_supported(in_args->message_id)) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } scmi_write_response(msg, &return_values, sizeof(return_values)); } static void reset_domain_attributes(struct scmi_msg *msg) { struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in; struct scmi_reset_domain_attributes_p2a return_values = { }; const char *name = NULL; unsigned int domain_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_rd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } domain_id = confine_array_index(in_args->domain_id, plat_scmi_rd_count(msg->channel_id)); name = plat_scmi_rd_get_name(msg->channel_id, domain_id); if (!name) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } COPY_NAME_IDENTIFIER(return_values.name, name); return_values.status = SCMI_SUCCESS; return_values.flags = 0; /* Async and Notif are not supported */ return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT; scmi_write_response(msg, &return_values, sizeof(return_values)); } static void reset_request(struct scmi_msg *msg) { struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in; struct scmi_reset_domain_request_p2a out_args = { .status = SCMI_SUCCESS, }; unsigned int domain_id = 0; domain_id = confine_array_index(in_args->domain_id, plat_scmi_rd_count(msg->channel_id)); if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_rd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } if (in_args->flags & SCMI_RESET_DOMAIN_AUTO) out_args.status = plat_scmi_rd_autonomous(msg->channel_id, domain_id, in_args->reset_state); else if (in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) out_args.status = plat_scmi_rd_set_state(msg->channel_id, domain_id, true); else out_args.status = plat_scmi_rd_set_state(msg->channel_id, domain_id, false); if (out_args.status) scmi_status_response(msg, out_args.status); else scmi_write_response(msg, &out_args, sizeof(out_args)); } static const scmi_msg_handler_t scmi_rd_handler_table[] = { [SCMI_PROTOCOL_VERSION] = report_version, [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes, [SCMI_RESET_DOMAIN_REQUEST] = reset_request, }; static bool message_id_is_supported(unsigned int message_id) { return message_id < ARRAY_SIZE(scmi_rd_handler_table) && scmi_rd_handler_table[message_id]; } scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg) { const size_t array_size = ARRAY_SIZE(scmi_rd_handler_table); unsigned int message_id = 0; if (msg->message_id >= array_size) { DMSG("Reset domain handle not found %u", msg->message_id); return NULL; } message_id = confine_array_index(msg->message_id, array_size); return scmi_rd_handler_table[message_id]; } optee_os-4.3.0/core/drivers/scmi-msg/reset_domain.h000066400000000000000000000055701464416617300223250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #ifndef SCMI_MSG_RESET_DOMAIN_H #define SCMI_MSG_RESET_DOMAIN_H #include #include #include #include #include #include "common.h" #define SCMI_PROTOCOL_VERSION_RESET_DOMAIN 0x10000 #define SCMI_RESET_STATE_ARCH BIT(31) #define SCMI_RESET_STATE_IMPL 0 /* * Identifiers of the SCMI Reset Domain Management Protocol commands */ enum scmi_reset_domain_command_id { SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03, SCMI_RESET_DOMAIN_REQUEST = 0x04, SCMI_RESET_DOMAIN_NOTIFY = 0x05, }; /* * Identifiers of the SCMI Reset Domain Management Protocol responses */ enum scmi_reset_domain_response_id { SCMI_RESET_ISSUED = 0x00, SCMI_RESET_COMPLETE = 0x04, }; /* * PROTOCOL_ATTRIBUTES */ #define SCMI_RESET_DOMAIN_COUNT_MASK GENMASK_32(15, 0) struct scmi_reset_domain_protocol_attributes_p2a { int32_t status; uint32_t attributes; }; /* Value for scmi_reset_domain_attributes_p2a:flags */ #define SCMI_RESET_DOMAIN_ATTR_ASYNC BIT(31) #define SCMI_RESET_DOMAIN_ATTR_NOTIF BIT(30) /* Value for scmi_reset_domain_attributes_p2a:latency */ #define SCMI_RESET_DOMAIN_ATTR_UNK_LAT 0x7fffffff #define SCMI_RESET_DOMAIN_ATTR_MAX_LAT 0x7ffffffe /* Macro for scmi_reset_domain_attributes_p2a:name */ #define SCMI_RESET_DOMAIN_ATTR_NAME_SZ 16 struct scmi_reset_domain_attributes_a2p { uint32_t domain_id; }; struct scmi_reset_domain_attributes_p2a { int32_t status; uint32_t flags; uint32_t latency; char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ]; }; /* * RESET */ /* Values for scmi_reset_domain_request_a2p:flags */ #define SCMI_RESET_DOMAIN_ASYNC BIT(2) #define SCMI_RESET_DOMAIN_EXPLICIT BIT(1) #define SCMI_RESET_DOMAIN_AUTO BIT(0) struct scmi_reset_domain_request_a2p { uint32_t domain_id; uint32_t flags; uint32_t reset_state; }; struct scmi_reset_domain_request_p2a { int32_t status; }; /* * RESET_NOTIFY */ /* Values for scmi_reset_notify_p2a:flags */ #define SCMI_RESET_DOMAIN_DO_NOTIFY BIT(0) struct scmi_reset_domain_notify_a2p { uint32_t domain_id; uint32_t notify_enable; }; struct scmi_reset_domain_notify_p2a { int32_t status; }; /* * RESET_COMPLETE */ struct scmi_reset_domain_complete_p2a { int32_t status; uint32_t domain_id; }; /* * RESET_ISSUED */ struct scmi_reset_domain_issued_p2a { uint32_t domain_id; uint32_t reset_state; }; #ifdef CFG_SCMI_MSG_RESET_DOMAIN /* * scmi_msg_get_rd_handler - Return a handler for a reset domain message * @msg - message to process * Return a function handler for the message or NULL */ scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg); #else static inline scmi_msg_handler_t scmi_msg_get_rd_handler(struct scmi_msg *msg __unused) { return NULL; } #endif #endif /* SCMI_MSG_RESET_DOMAIN_H */ optee_os-4.3.0/core/drivers/scmi-msg/shm_msg.c000066400000000000000000000055771464416617300213130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include "common.h" /** * struct msg_header - MSG formatted header for MSG base shared memory transfer * * @message_header: 32bit header used in MSG shared memory protocol * @payload: SCMI message payload data */ struct msg_header { uint32_t message_header; uint32_t payload[]; }; /* Bit fields packed in msg_header::message_header */ #define MSG_ID_MASK GENMASK_32(7, 0) #define MSG_ID(_hdr) ((_hdr) & MSG_ID_MASK) #define MSG_TYPE_MASK GENMASK_32(9, 8) #define MSG_TYPE(_hdr) (((_hdr) & MSG_TYPE_MASK) >> 8) #define MSG_PROT_ID_MASK GENMASK_32(17, 10) #define MSG_PROT_ID(_hdr) (((_hdr) & MSG_PROT_ID_MASK) >> 10) /* * Creates a SCMI message instance in secure memory and push it in the SCMI * message drivers. Message structure contains SCMI protocol meta-data and * references to input payload in secure memory and output message buffer * in shared memory. */ TEE_Result scmi_entry_msg(unsigned int channel_id, void *in_buf, size_t in_size, void *out_buf, size_t *out_size, uint32_t *sec_buf) { struct scmi_msg_channel *channel = plat_scmi_get_channel(channel_id); struct msg_header *hdr = NULL; struct scmi_msg msg = { }; uint32_t msg_header = 0; if (!channel) { DMSG("Invalid channel ID %u", channel_id); return TEE_ERROR_BAD_PARAMETERS; } assert(in_buf && out_buf && out_size && sec_buf); if (in_size < sizeof(struct msg_header) || in_size - sizeof(struct msg_header) > SCMI_SEC_PAYLOAD_SIZE || !IS_ALIGNED_WITH_TYPE(in_buf, uint32_t) || *out_size < sizeof(struct msg_header) || !IS_ALIGNED_WITH_TYPE(out_buf, uint32_t)) { DMSG("Invalid SCMI buffer references %zu@%p / %zu@%p", in_size, in_buf, *out_size, out_buf); return TEE_ERROR_BAD_PARAMETERS; } if (!scmi_msg_claim_channel(channel)) { DMSG("SCMI channel %u busy", channel_id); return TEE_ERROR_BUSY; } /* Copy SCMI protocol data and message payload in secure memory */ hdr = (struct msg_header *)in_buf; msg_header = READ_ONCE(hdr->message_header); msg.protocol_id = MSG_PROT_ID(msg_header); msg.message_id = MSG_ID(msg_header); msg.channel_id = channel_id; msg.in = (char *)sec_buf; msg.in_size = in_size - sizeof(struct msg_header); memcpy(msg.in, hdr->payload, msg.in_size); /* Prepare output message buffer references */ hdr = (struct msg_header *)out_buf; msg.out = (char *)hdr->payload; msg.out_size = *out_size - sizeof(struct msg_header); scmi_process_message(&msg); /* Update SCMI protocol data and output shared buffer size */ hdr->message_header = msg_header; *out_size = msg.out_size_out + sizeof(struct msg_header); scmi_msg_release_channel(channel); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/scmi-msg/smt.c000066400000000000000000000110741464416617300204460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include "common.h" /** * struct smt_header - SMT formatted header for SMT base shared memory transfer * * @status: Bit flags, see SMT_STATUS_* * @flags: Bit flags, see SMT_FLAG_* * @length: Byte size of message payload (variable) + ::message_header (32bit) * payload: SCMI message payload data */ struct smt_header { uint32_t reserved0; uint32_t status; uint64_t reserved1; uint32_t flags; uint32_t length; /* message_header + payload */ uint32_t message_header; uint32_t payload[]; }; /* Flag set in smt_header::status when SMT does not contain pending message */ #define SMT_STATUS_FREE BIT(0) /* Flag set in smt_header::status when SMT reports an error */ #define SMT_STATUS_ERROR BIT(1) /* Flag set in smt_header::flags when SMT uses interrupts */ #define SMT_FLAG_INTR_ENABLED BIT(1) /* Bit fields packed in smt_header::message_header */ #define SMT_MSG_ID_MASK GENMASK_32(7, 0) #define SMT_HDR_MSG_ID(_hdr) ((_hdr) & SMT_MSG_ID_MASK) #define SMT_MSG_TYPE_MASK GENMASK_32(9, 8) #define SMT_HDR_TYPE_ID(_hdr) (((_hdr) & SMT_MSG_TYPE_MASK) >> 8) #define SMT_MSG_PROT_ID_MASK GENMASK_32(17, 10) #define SMT_HDR_PROT_ID(_hdr) (((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10) static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *channel) { if (!channel) return NULL; return (struct smt_header *)io_pa_or_va(&channel->shm_addr, sizeof(struct smt_header)); } /* * Creates a SCMI message instance in secure memory and push it in the SCMI * message drivers. Message structure contains SCMI protocol meta-data and * references to input payload in secure memory and output message buffer * in shared memory. */ void scmi_entry_smt(unsigned int channel_id, uint32_t *payload_buf) { struct scmi_msg_channel *channel = NULL; struct smt_header *smt_hdr = NULL; size_t in_payload_size = 0; uint32_t smt_status = 0; struct scmi_msg msg = { }; bool error = true; channel = plat_scmi_get_channel(channel_id); if (!channel) { DMSG("Invalid channel ID %u", channel_id); return; } smt_hdr = channel_to_smt_hdr(channel); if (!smt_hdr) { DMSG("No shared buffer for channel ID %u", channel_id); return; } if (!scmi_msg_claim_channel(channel)) { DMSG("SCMI channel %u busy", channel_id); goto out; } smt_status = READ_ONCE(smt_hdr->status); in_payload_size = READ_ONCE(smt_hdr->length) - sizeof(smt_hdr->message_header); if (in_payload_size > SCMI_SEC_PAYLOAD_SIZE) { DMSG("SCMI payload too big %zu", in_payload_size); goto out; } if (smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) { DMSG("SCMI channel bad status 0x%x", smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)); goto out; } /* Fill message */ msg.in = (char *)payload_buf; msg.in_size = in_payload_size; msg.out = (char *)smt_hdr->payload; msg.out_size = channel->shm_size - sizeof(*smt_hdr); assert(msg.out && msg.out_size >= sizeof(int32_t)); /* Here the payload is copied in secure memory */ memcpy(msg.in, smt_hdr->payload, in_payload_size); msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header); msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header); msg.channel_id = channel_id; scmi_process_message(&msg); /* Update message length with the length of the response message */ smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header); scmi_msg_release_channel(channel); error = false; out: if (error) { DMSG("SCMI error"); smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE; } else { smt_hdr->status |= SMT_STATUS_FREE; } } /* Init a SMT header for a shared memory buffer: state it a free/no-error */ void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel) { struct smt_header *smt_header = channel_to_smt_hdr(channel); static_assert(SCMI_SEC_PAYLOAD_SIZE + sizeof(struct smt_header) <= SMT_BUF_SLOT_SIZE && IS_ALIGNED(SCMI_SEC_PAYLOAD_SIZE, sizeof(uint32_t))); assert(smt_header); memset(smt_header, 0, sizeof(*smt_header)); smt_header->status = SMT_STATUS_FREE; } void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel, void *base) { paddr_t p_base = 0; if (base) { assert(!channel->shm_addr.va && !channel->shm_addr.pa); p_base = virt_to_phys(base); assert(p_base); } channel->shm_addr.va = (vaddr_t)base; channel->shm_addr.pa = p_base; } optee_os-4.3.0/core/drivers/scmi-msg/sub.mk000066400000000000000000000004611464416617300206170ustar00rootroot00000000000000srcs-y += base.c srcs-$(CFG_SCMI_MSG_CLOCK) += clock.c srcs-$(CFG_SCMI_MSG_USE_CLK) += clock_generic.c srcs-y += entry.c srcs-$(CFG_SCMI_MSG_RESET_DOMAIN) += reset_domain.c srcs-$(CFG_SCMI_MSG_SHM_MSG) += shm_msg.c srcs-$(CFG_SCMI_MSG_SMT) += smt.c srcs-$(CFG_SCMI_MSG_VOLTAGE_DOMAIN) += voltage_domain.c optee_os-4.3.0/core/drivers/scmi-msg/voltage_domain.c000066400000000000000000000253311464416617300226340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include #include #include "common.h" #include "voltage_domain.h" static bool message_id_is_supported(unsigned int message_id); size_t __weak plat_scmi_voltd_count(unsigned int channel_id __unused) { return 0; } const char __weak *plat_scmi_voltd_get_name(unsigned int channel_id __unused, unsigned int scmi_id __unused) { return NULL; } int32_t __weak plat_scmi_voltd_levels_array(unsigned int channel_id __unused, unsigned int scmi_id __unused, size_t start_index __unused, long *levels __unused, size_t *nb_elts __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_voltd_levels_by_step(unsigned int channel_id __unused, unsigned int scmi_id __unused, long *steps __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_voltd_get_level(unsigned int channel_id __unused, unsigned int scmi_id __unused, long *level __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_voltd_set_level(unsigned int channel_id __unused, unsigned int scmi_id __unused, long microvolt __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_voltd_get_config(unsigned int channel_id __unused, unsigned int scmi_id __unused, uint32_t *config __unused) { return SCMI_NOT_SUPPORTED; } int32_t __weak plat_scmi_voltd_set_config(unsigned int channel_id __unused, unsigned int scmi_id __unused, uint32_t config __unused) { return SCMI_NOT_SUPPORTED; } static void report_version(struct scmi_msg *msg) { struct scmi_protocol_version_p2a out_args = { .status = SCMI_SUCCESS, .version = SCMI_PROTOCOL_VERSION_VOLTAGE_DOMAIN, }; if (IS_ENABLED(CFG_SCMI_MSG_STRICT_ABI) && msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &out_args, sizeof(out_args)); } static void report_attributes(struct scmi_msg *msg) { size_t domain_count = plat_scmi_voltd_count(msg->channel_id); struct scmi_protocol_attributes_p2a out_args = { .status = SCMI_SUCCESS, .attributes = domain_count, }; assert(!(domain_count & ~SCMI_VOLTAGE_DOMAIN_COUNT_MASK)); if (IS_ENABLED(CFG_SCMI_MSG_STRICT_ABI) && msg->in_size) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } scmi_write_response(msg, &out_args, sizeof(out_args)); } static void report_message_attributes(struct scmi_msg *msg) { struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; struct scmi_protocol_message_attributes_p2a out_args = { .status = SCMI_SUCCESS, /* For this protocol, attributes shall be zero */ .attributes = 0, }; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (!message_id_is_supported(in_args->message_id)) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } scmi_write_response(msg, &out_args, sizeof(out_args)); } static void scmi_voltd_domain_attributes(struct scmi_msg *msg) { const struct scmi_voltd_attributes_a2p *in_args = (void *)msg->in; struct scmi_voltd_attributes_p2a out_args = { .status = SCMI_SUCCESS, }; const char *name = NULL; unsigned int domain_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } domain_id = confine_array_index(in_args->domain_id, plat_scmi_voltd_count(msg->channel_id)); name = plat_scmi_voltd_get_name(msg->channel_id, domain_id); if (!name) { scmi_status_response(msg, SCMI_NOT_FOUND); return; } COPY_NAME_IDENTIFIER(out_args.name, name); scmi_write_response(msg, &out_args, sizeof(out_args)); } #define LEVELS_BY_ARRAY(_nb_rates, _rem_rates) \ SCMI_VOLTAGE_DOMAIN_LEVELS_FLAGS((_nb_rates), \ SCMI_VOLTD_LEVELS_FORMAT_LIST, \ (_rem_rates)) #define LEVELS_BY_STEP \ SCMI_VOLTAGE_DOMAIN_LEVELS_FLAGS(3, SCMI_VOLTD_LEVELS_FORMAT_RANGE, 0) #define LEVEL_DESC_SIZE sizeof(int32_t) static void scmi_voltd_describe_levels(struct scmi_msg *msg) { const struct scmi_voltd_describe_levels_a2p *in_args = (void *)msg->in; struct scmi_voltd_describe_levels_p2a out_args = { }; int32_t status = SCMI_GENERIC_ERROR; unsigned int out_count = 0; unsigned int domain_id = 0; int32_t *out_levels = NULL; size_t nb_levels = 0; if (msg->in_size != sizeof(*in_args)) { status = SCMI_PROTOCOL_ERROR; goto out; } if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { status = SCMI_INVALID_PARAMETERS; goto out; } if (msg->out_size < sizeof(out_args)) { status = SCMI_INVALID_PARAMETERS; goto out; } assert(IS_ALIGNED_WITH_TYPE(msg->out + sizeof(out_args), int32_t)); out_levels = (int32_t *)(uintptr_t)(msg->out + sizeof(out_args)); domain_id = confine_array_index(in_args->domain_id, plat_scmi_voltd_count(msg->channel_id)); /* Platform may support array rate description */ status = plat_scmi_voltd_levels_array(msg->channel_id, domain_id, 0, NULL, &nb_levels); if (status == SCMI_SUCCESS) { size_t avail_sz = msg->out_size - sizeof(out_args); unsigned int level_index = in_args->level_index; unsigned int remaining = 0; if (avail_sz < LEVEL_DESC_SIZE && nb_levels) { status = SCMI_PROTOCOL_ERROR; goto out; } while (avail_sz >= LEVEL_DESC_SIZE && level_index < nb_levels) { long plat_level = 0; size_t cnt = 1; status = plat_scmi_voltd_levels_array(msg->channel_id, domain_id, level_index, &plat_level, &cnt); if (status) goto out; *out_levels = plat_level; avail_sz -= LEVEL_DESC_SIZE; out_levels++; level_index++; } remaining = nb_levels - in_args->level_index; out_count = level_index - in_args->level_index; out_args.flags = LEVELS_BY_ARRAY(out_count, remaining); } else if (status == SCMI_NOT_SUPPORTED) { long triplet[3] = { 0, 0, 0 }; if (msg->out_size < sizeof(out_args) + 3 * LEVEL_DESC_SIZE) { status = SCMI_PROTOCOL_ERROR; goto out; } /* Platform may support min/max/step triplet description */ status = plat_scmi_voltd_levels_by_step(msg->channel_id, domain_id, triplet); if (status) goto out; out_levels[0] = triplet[0]; out_levels[1] = triplet[1]; out_levels[2] = triplet[2]; out_count = 3; out_args.flags = LEVELS_BY_STEP; } out: if (status) { scmi_status_response(msg, status); } else { out_args.status = SCMI_SUCCESS; memcpy(msg->out, &out_args, sizeof(out_args)); msg->out_size_out = sizeof(out_args) + out_count * LEVEL_DESC_SIZE; } } static void scmi_voltd_config_set(struct scmi_msg *msg) { const struct scmi_voltd_config_set_a2p *in_args = (void *)msg->in; unsigned int domain_id = 0; unsigned long config = 0; int32_t status = SCMI_GENERIC_ERROR; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } domain_id = confine_array_index(in_args->domain_id, plat_scmi_voltd_count(msg->channel_id)); config = in_args->config & SCMI_VOLTAGE_DOMAIN_CONFIG_MASK; status = plat_scmi_voltd_set_config(msg->channel_id, domain_id, config); scmi_status_response(msg, status); } static void scmi_voltd_config_get(struct scmi_msg *msg) { const struct scmi_voltd_config_get_a2p *in_args = (void *)msg->in; struct scmi_voltd_config_get_p2a out_args = { }; unsigned int domain_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } domain_id = confine_array_index(in_args->domain_id, plat_scmi_voltd_count(msg->channel_id)); if (plat_scmi_voltd_get_config(msg->channel_id, domain_id, &out_args.config)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } scmi_write_response(msg, &out_args, sizeof(out_args)); } static void scmi_voltd_level_set(struct scmi_msg *msg) { const struct scmi_voltd_level_set_a2p *in_args = (void *)msg->in; int32_t status = SCMI_GENERIC_ERROR; unsigned int domain_id = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } domain_id = confine_array_index(in_args->domain_id, plat_scmi_voltd_count(msg->channel_id)); status = plat_scmi_voltd_set_level(msg->channel_id, domain_id, in_args->voltage_level); scmi_status_response(msg, status); } static void scmi_voltd_level_get(struct scmi_msg *msg) { const struct scmi_voltd_level_get_a2p *in_args = (void *)msg->in; struct scmi_voltd_level_get_p2a out_args = { .status = SCMI_SUCCESS, }; unsigned int domain_id = 0; long level = 0; if (msg->in_size != sizeof(*in_args)) { scmi_status_response(msg, SCMI_PROTOCOL_ERROR); return; } if (in_args->domain_id >= plat_scmi_voltd_count(msg->channel_id)) { scmi_status_response(msg, SCMI_INVALID_PARAMETERS); return; } domain_id = confine_array_index(in_args->domain_id, plat_scmi_voltd_count(msg->channel_id)); out_args.status = plat_scmi_voltd_get_level(msg->channel_id, domain_id, &level); out_args.voltage_level = level; scmi_write_response(msg, &out_args, sizeof(out_args)); } static const scmi_msg_handler_t handler_array[] = { [SCMI_PROTOCOL_VERSION] = report_version, [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, [SCMI_VOLTAGE_DOMAIN_ATTRIBUTES] = scmi_voltd_domain_attributes, [SCMI_VOLTAGE_DESCRIBE_LEVELS] = scmi_voltd_describe_levels, [SCMI_VOLTAGE_CONFIG_SET] = scmi_voltd_config_set, [SCMI_VOLTAGE_CONFIG_GET] = scmi_voltd_config_get, [SCMI_VOLTAGE_LEVEL_SET] = scmi_voltd_level_set, [SCMI_VOLTAGE_LEVEL_GET] = scmi_voltd_level_get, }; static bool message_id_is_supported(unsigned int id) { return id < ARRAY_SIZE(handler_array) && handler_array[id]; } scmi_msg_handler_t scmi_msg_get_voltd_handler(struct scmi_msg *msg) { const size_t array_size = ARRAY_SIZE(handler_array); unsigned int message_id = 0; if (msg->message_id >= array_size) { DMSG("Voltage domain handle not found %u", msg->message_id); return NULL; } message_id = confine_array_index(msg->message_id, array_size); return handler_array[message_id]; } optee_os-4.3.0/core/drivers/scmi-msg/voltage_domain.h000066400000000000000000000056161464416617300226450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019, Linaro Limited */ #ifndef SCMI_MSG_VOLTAGE_DOMAIN_H #define SCMI_MSG_VOLTAGE_DOMAIN_H #include #include #include "common.h" #define SCMI_PROTOCOL_VERSION_VOLTAGE_DOMAIN 0x30000 /* * Identifiers of the SCMI Clock Management Protocol commands */ enum scmi_voltd_command_id { SCMI_VOLTAGE_DOMAIN_ATTRIBUTES = 0x3, SCMI_VOLTAGE_DESCRIBE_LEVELS = 0x4, SCMI_VOLTAGE_CONFIG_SET = 0x5, SCMI_VOLTAGE_CONFIG_GET = 0x6, SCMI_VOLTAGE_LEVEL_SET = 0x7, SCMI_VOLTAGE_LEVEL_GET = 0x8, }; #define SCMI_VOLTAGE_DOMAIN_COUNT_MASK GENMASK_32(15, 0) struct scmi_voltd_protocol_attrs_p2a { int32_t status; uint32_t attributes; }; struct scmi_voltd_attributes_a2p { uint32_t domain_id; }; #define SCMI_VOLTAGE_DOMAIN_NAME_MAX 16 struct scmi_voltd_attributes_p2a { int32_t status; uint32_t attributes; char name[SCMI_VOLTAGE_DOMAIN_NAME_MAX]; }; struct scmi_voltd_describe_levels_a2p { uint32_t domain_id; uint32_t level_index; }; #define SCMI_VOLTD_LEVELS_REMAINING_MASK GENMASK_32(31, 16) #define SCMI_VOLTD_LEVELS_REMAINING_POS 16 #define SCMI_VOLTD_LEVELS_FORMAT_RANGE 1 #define SCMI_VOLTD_LEVELS_FORMAT_LIST 0 #define SCMI_VOLTD_LEVELS_FORMAT_MASK BIT(12) #define SCMI_VOLTD_LEVELS_FORMAT_POS 12 #define SCMI_VOLTD_LEVELS_COUNT_MASK GENMASK_32(11, 0) #define SCMI_VOLTAGE_DOMAIN_LEVELS_FLAGS(_count, _fmt, _rem_rates) \ ( \ ((_count) & SCMI_VOLTD_LEVELS_COUNT_MASK) | \ (((_rem_rates) << SCMI_VOLTD_LEVELS_REMAINING_POS) & \ SCMI_VOLTD_LEVELS_REMAINING_MASK) | \ (((_fmt) << SCMI_VOLTD_LEVELS_FORMAT_POS) & \ SCMI_VOLTD_LEVELS_FORMAT_MASK) \ ) struct scmi_voltd_level { int32_t mircovolt; }; struct scmi_voltd_describe_levels_p2a { int32_t status; uint32_t flags; struct scmi_voltd_level voltage[]; }; struct scmi_voltd_level_set_a2p { uint32_t domain_id; uint32_t flags; int32_t voltage_level; }; struct scmi_voltd_level_set_p2a { uint32_t status; }; struct scmi_voltd_level_get_a2p { uint32_t domain_id; }; struct scmi_voltd_level_get_p2a { int32_t status; int32_t voltage_level; }; #define SCMI_VOLTAGE_DOMAIN_CONFIG_MASK GENMASK_32(3, 0) struct scmi_voltd_config_set_a2p { uint32_t domain_id; uint32_t config; }; struct scmi_voltd_config_set_p2a { uint32_t status; }; struct scmi_voltd_config_get_a2p { uint32_t domain_id; }; struct scmi_voltd_config_get_p2a { int32_t status; uint32_t config; }; #ifdef CFG_SCMI_MSG_VOLTAGE_DOMAIN /* * scmi_msg_get_voltd_handler - Return a handler for a voltage domain message * @msg - message to process * Return a function handler for the message or NULL */ scmi_msg_handler_t scmi_msg_get_voltd_handler(struct scmi_msg *msg); #else static inline scmi_msg_handler_t scmi_msg_get_voltd_handler(struct scmi_msg *msg __unused) { return NULL; } #endif #endif /* SCMI_MSG_CLOCK_H */ optee_os-4.3.0/core/drivers/semihosting_console.c000066400000000000000000000035351464416617300222020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024 Andes Technology Corporation */ #include #include #include #include #include #include /* * struct semihosting_console_data - Structure for semihosting console driver * @chip - General structure for each serial chip * @fd - Handle of the file at @file_path when semihosting_console_init() is * called, or -1 if using the semihosting console */ struct semihosting_console_data { struct serial_chip chip; int fd; }; static struct semihosting_console_data sh_console_data __nex_bss; static void semihosting_console_putc(struct serial_chip *chip __unused, int ch) { semihosting_sys_writec(ch); } static int semihosting_console_getchar(struct serial_chip *chip __unused) { return semihosting_sys_readc(); } static const struct serial_ops semihosting_console_ops = { .putc = semihosting_console_putc, .getchar = semihosting_console_getchar, }; DECLARE_KEEP_PAGER(semihosting_console_ops); static void semihosting_console_fd_putc(struct serial_chip *chip __unused, int ch) { if (sh_console_data.fd >= 0) semihosting_write(sh_console_data.fd, &ch, 1); } static const struct serial_ops semihosting_console_fd_ops = { .putc = semihosting_console_fd_putc, }; DECLARE_KEEP_PAGER(semihosting_console_fd_ops); void semihosting_console_init(const char *file_path) { if (file_path) { /* Output log to given file on the semihosting host system. */ sh_console_data.chip.ops = &semihosting_console_fd_ops; sh_console_data.fd = semihosting_open(file_path, O_RDWR | O_CREAT | O_TRUNC); } else { /* Output log to semihosting host debug console. */ sh_console_data.chip.ops = &semihosting_console_ops; sh_console_data.fd = -1; } register_serial_console(&sh_console_data.chip); } optee_os-4.3.0/core/drivers/serial8250_uart.c000066400000000000000000000074461464416617300207650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include #include #include #include #include /* uart register defines */ #define UART_RHR 0x0 #define UART_THR 0x0 #define UART_IER 0x4 #define UART_ISR 0x8 #define UART_FCR 0x8 #define UART_LCR 0xc #define UART_MCR 0x10 #define UART_LSR 0x14 #define UART_MSR 0x18 #define UART_SPR 0x1c /* uart status register bits */ #define LSR_TEMT 0x40 /* Transmitter empty */ #define LSR_THRE 0x20 /* Transmit-hold-register empty */ #define LSR_EMPTY (LSR_TEMT | LSR_THRE) #define LSR_DR 0x01 /* DATA Ready */ static vaddr_t chip_to_base(struct serial_chip *chip) { struct serial8250_uart_data *pd = container_of(chip, struct serial8250_uart_data, chip); return io_pa_or_va(&pd->base, SERIAL8250_UART_REG_SIZE); } static void serial8250_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (1) { uint32_t state = io_read32(base + UART_LSR); /* Wait until transmit FIFO is empty */ if ((state & LSR_EMPTY) == LSR_EMPTY) break; } } static bool serial8250_uart_have_rx_data(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); return (io_read32(base + UART_LSR) & LSR_DR); } static int serial8250_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!serial8250_uart_have_rx_data(chip)) { /* Transmit FIFO is empty, waiting again */ ; } return io_read32(base + UART_RHR) & 0xff; } static void serial8250_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); serial8250_uart_flush(chip); /* Write out character to transmit FIFO */ io_write32(base + UART_THR, ch); } static const struct serial_ops serial8250_uart_ops = { .flush = serial8250_uart_flush, .getchar = serial8250_uart_getchar, .have_rx_data = serial8250_uart_have_rx_data, .putc = serial8250_uart_putc, }; DECLARE_KEEP_PAGER(serial8250_uart_ops); void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, uint32_t __unused uart_clk, uint32_t __unused baud_rate) { pd->base.pa = base; pd->chip.ops = &serial8250_uart_ops; /* * do nothing, debug uart(uart0) share with normal world, * everything for uart0 is ready now. */ } #ifdef CFG_DT static struct serial_chip *serial8250_uart_dev_alloc(void) { struct serial8250_uart_data *pd = calloc(1, sizeof(*pd)); if (!pd) return NULL; return &pd->chip; } static int serial8250_uart_dev_init(struct serial_chip *chip, const void *fdt, int offs, const char *parms) { struct serial8250_uart_data *pd = container_of(chip, struct serial8250_uart_data, chip); vaddr_t vbase; paddr_t pbase; size_t size; if (parms && parms[0]) IMSG("serial8250_uart: device parameters ignored (%s)", parms); if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0) return -1; if (size < SERIAL8250_UART_REG_SIZE) { EMSG("serial8250_uart: register size too small: %zx", size); return -1; } pbase = virt_to_phys((void *)vbase); serial8250_uart_init(pd, pbase, 0, 0); return 0; } static void serial8250_uart_dev_free(struct serial_chip *chip) { struct serial8250_uart_data *pd = container_of(chip, struct serial8250_uart_data, chip); free(pd); } static const struct serial_driver serial8250_driver = { .dev_alloc = serial8250_uart_dev_alloc, .dev_init = serial8250_uart_dev_init, .dev_free = serial8250_uart_dev_free, }; static const struct dt_device_match serial8250_match_table[] = { { .compatible = "snps,dw-apb-uart" }, { 0 } }; DEFINE_DT_DRIVER(serial8250_dt_driver) = { .name = "serial8250_uart", .type = DT_DRIVER_UART, .match_table = serial8250_match_table, .driver = &serial8250_driver, }; #endif /* CFG_DT */ optee_os-4.3.0/core/drivers/smccc_trng.c000066400000000000000000000123621464416617300202470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2022 Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Arm SMCCC TRNG firmware interface specification: * https://developer.arm.com/documentation/den0098/ */ #define ARM_SMCCC_TRNG_VERSION 0x84000050 #define ARM_SMCCC_TRNG_FEATURES 0x84000051 #define ARM_SMCCC_TRNG_GET_UUID 0x84000052 #define ARM_SMCCC_TRNG_RND_32 0x84000053 #define ARM_SMCCC_TRNG_RND_64 0xc4000053 #define ARM_SMCCC_RET_TRNG_SUCCESS U(0) #define ARM_SMCCC_RET_TRNG_NOT_SUPPORTED ((unsigned long)-1) #define ARM_SMCCC_RET_TRNG_INVALID_PARAMETER ((unsigned long)-2) #define ARM_SMCCC_RET_TRNG_NO_ENTROPY ((unsigned long)-3) #define TRNG_MAJOR_MASK GENMASK_32(30, 16) #define TRNG_MAJOR_SHIFT 16 #define TRNG_MINOR_MASK GENMASK_32(15, 0) #define TRNG_MINOR_SHIFT 0 #define TRNG_MAKE_VERSION(major, minor) \ ((SHIFT_U32(major, TRNG_MAJOR_SHIFT) & TRNG_MAJOR_MASK) | \ (SHIFT_U32(minor, TRNG_MINOR_SHIFT) & TRNG_MINOR_MASK)) #define TRNG_VERSION_1_0 TRNG_MAKE_VERSION(1, 0) #define TRNG_MAX_RND_64 (192 / 8) #define TRNG_MAX_RND_32 (96 / 8) /* Function ID discovered for getting random bytes or 0 if not supported */ static uint32_t trng_rnd_fid; static bool smccc_trng_is_supported(void) { struct thread_smc_args args = { }; static bool inited; if (inited) return trng_rnd_fid != 0; inited = true; /* * TRNG ABI requires caller to check that Arm SMCCC version is * larger or equal to v1.1 */ args.a0 = ARM_SMCCC_VERSION; thread_smccc(&args); if (args.a0 & BIT32(31) || args.a0 < SMCCC_V_1_1) return false; /* * Check TRNG version, if successful we're guaranteed to have at least * the ARM_SMCCC_TRNG_FEATURES fid. */ args.a0 = ARM_SMCCC_TRNG_VERSION; thread_smccc(&args); if (args.a0 & BIT32(31) || args.a0 < TRNG_VERSION_1_0) return false; #ifdef ARM64 args.a0 = ARM_SMCCC_TRNG_FEATURES; args.a1 = ARM_SMCCC_TRNG_RND_64; thread_smccc(&args); if (args.a0 == ARM_SMCCC_RET_SUCCESS) { trng_rnd_fid = ARM_SMCCC_TRNG_RND_64; return true; } #endif args.a0 = ARM_SMCCC_TRNG_FEATURES; args.a1 = ARM_SMCCC_TRNG_RND_32; thread_smccc(&args); if (args.a0 == ARM_SMCCC_RET_TRNG_SUCCESS) { trng_rnd_fid = ARM_SMCCC_TRNG_RND_32; return true; } return false; } static void read_bytes(unsigned long val, size_t byte_count, uint8_t **buf, size_t *rem) { size_t count = MIN(byte_count, *rem); size_t n = 0; for (n = 0; n < count; n++) (*buf)[n] = val >> (n * 8); *buf += count; *rem -= count; } static void read_samples(struct thread_smc_args *args, uint8_t *buf, size_t len) { uint8_t *ptr = buf; size_t rem = len; size_t byte_count = 4; #ifdef ARM64 if (trng_rnd_fid == ARM_SMCCC_TRNG_RND_64) byte_count = 8; #endif read_bytes(args->a3, byte_count, &ptr, &rem); read_bytes(args->a2, byte_count, &ptr, &rem); read_bytes(args->a1, byte_count, &ptr, &rem); } static TEE_Result __maybe_unused smccc_trng_read(void *buf, size_t len) { struct thread_smc_args args = { }; uint8_t *ptr = buf; size_t rem = len; size_t max_burst = 0; if (!smccc_trng_is_supported()) return TEE_ERROR_NOT_SUPPORTED; if (trng_rnd_fid == ARM_SMCCC_TRNG_RND_64) max_burst = TRNG_MAX_RND_64; else max_burst = TRNG_MAX_RND_32; while (rem) { size_t burst = MIN(rem, max_burst); args.a0 = trng_rnd_fid; args.a1 = burst * 8; thread_smccc(&args); switch (args.a0) { case ARM_SMCCC_RET_TRNG_SUCCESS: read_samples(&args, ptr, burst); rem -= burst; ptr += burst; break; case ARM_SMCCC_RET_TRNG_NO_ENTROPY: break; default: return TEE_ERROR_GENERIC; } } return TEE_SUCCESS; } static void __maybe_unused smccc_trng_print_info(void) { struct thread_smc_args args = { }; unsigned int __maybe_unused major = 0; unsigned int __maybe_unused minor = 0; if (!IS_ENABLED(CFG_TEE_CORE_DEBUG)) return; args.a0 = ARM_SMCCC_TRNG_VERSION; thread_smccc(&args); assert((args.a0 & BIT32(31)) == 0); major = (args.a0 & TRNG_MAJOR_MASK) >> TRNG_MAJOR_SHIFT; minor = (args.a0 & TRNG_MINOR_MASK) >> TRNG_MINOR_SHIFT; args.a0 = ARM_SMCCC_TRNG_GET_UUID; thread_smccc(&args); assert(args.a0 != ARM_SMCCC_RET_TRNG_NOT_SUPPORTED); DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx", major, minor, (unsigned long)args.a0, (unsigned long)args.a1 >> 16, (unsigned long)args.a1 & GENMASK_32(16, 0), (unsigned long)args.a2 >> 16, (unsigned long)args.a2 & GENMASK_32(16, 0), (unsigned long)args.a3); } void plat_rng_init(void) { if (!smccc_trng_is_supported()) panic("SMCCC TRNG not supported"); smccc_trng_print_info(); if (IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)) { /* If CFG_WITH_SOFTWARE_PRNG is enabled, seed PRNG with TRNG */ uint8_t seed[32] = { 0 }; if (smccc_trng_read(seed, sizeof(seed))) panic("SMCCC TRNG not supported"); if (crypto_rng_init(seed, sizeof(seed))) panic(); } } /* If CFG_WITH_SOFTWARE_PRNG is disabled, TRNG is our HW RNG */ #ifndef CFG_WITH_SOFTWARE_PRNG TEE_Result hw_get_random_bytes(void *buf, size_t len) { return smccc_trng_read(buf, len); } #endif optee_os-4.3.0/core/drivers/sp805_wdt.c000066400000000000000000000064601464416617300176640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Broadcom */ #include #include #include #include #include #include #include #include static vaddr_t chip_to_base(struct wdt_chip *chip) { struct sp805_wdt_data *pd = container_of(chip, struct sp805_wdt_data, chip); return io_pa_or_va(&pd->base, WDT_SIZE); } static TEE_Result sp805_setload(struct wdt_chip *chip, unsigned long timeout) { struct sp805_wdt_data *pd = container_of(chip, struct sp805_wdt_data, chip); uint32_t load = 0; /* * sp805 runs counter with given value twice, after the end of first * counter it gives an interrupt and then starts counter again. If * interrupt already occurred then it resets the system. This is why * load is half of what should be required. */ if (MUL_OVERFLOW(timeout, pd->clk_rate, &load)) return TEE_ERROR_SECURITY; load = (load / 2) - 1; if (load < WDT_LOAD_MIN) load = WDT_LOAD_MIN; pd->load_val = load; return TEE_SUCCESS; } static void sp805_config(struct wdt_chip *chip, bool enable) { struct sp805_wdt_data *pd = container_of(chip, struct sp805_wdt_data, chip); vaddr_t base = chip_to_base(chip); io_write32(base + WDT_LOCK_OFFSET, WDT_UNLOCK_KEY); io_write32(base + WDT_LOAD_OFFSET, pd->load_val); io_write32(base + WDT_INTCLR_OFFSET, WDT_INT_CLR); if (enable) io_write32(base + WDT_CONTROL_OFFSET, WDT_INT_EN | WDT_RESET_EN); io_write32(base + WDT_LOCK_OFFSET, WDT_LOCK_KEY); /* Flush posted writes. */ (void)io_read32(base + WDT_LOCK_OFFSET); } static void sp805_ping(struct wdt_chip *chip) { sp805_config(chip, false); } static void sp805_enable(struct wdt_chip *chip) { sp805_config(chip, true); } static void sp805_disable(struct wdt_chip *chip) { vaddr_t base = chip_to_base(chip); io_write32(base + WDT_LOCK_OFFSET, WDT_UNLOCK_KEY); io_write32(base + WDT_CONTROL_OFFSET, 0); io_write32(base + WDT_LOCK_OFFSET, WDT_LOCK_KEY); /* Flush posted writes. */ (void)io_read32(base + WDT_LOCK_OFFSET); } static enum itr_return wdt_itr_cb(struct itr_handler *h) { struct wdt_chip *chip = h->data; struct sp805_wdt_data *pd = container_of(chip, struct sp805_wdt_data, chip); if (pd->itr_handler) pd->itr_handler(chip); return ITRR_HANDLED; } DECLARE_KEEP_PAGER(wdt_itr_cb); TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd, uint32_t itr_num, uint32_t itr_flags, sp805_itr_handler_func_t itr_handler) { TEE_Result res = TEE_ERROR_GENERIC; struct itr_handler *wdt_itr = NULL; assert(!pd->chip.wdt_itr); res = interrupt_alloc_add_handler(interrupt_get_main_chip(), itr_num, wdt_itr_cb, itr_flags, &pd->chip, &wdt_itr); if (res) return res; pd->itr_handler = itr_handler; pd->chip.wdt_itr = wdt_itr; interrupt_enable(wdt_itr->chip, wdt_itr->it); return TEE_SUCCESS; } static const struct wdt_ops sp805_wdt_ops = { .start = sp805_enable, .stop = sp805_disable, .ping = sp805_ping, .set_timeout = sp805_setload, }; DECLARE_KEEP_PAGER(sp805_wdt_ops); TEE_Result sp805_wdt_init(struct sp805_wdt_data *pd, paddr_t base, uint32_t clk_rate, uint32_t timeout) { assert(pd); pd->base.pa = base; pd->clk_rate = clk_rate; pd->chip.ops = &sp805_wdt_ops; return sp805_setload(&pd->chip, timeout); } optee_os-4.3.0/core/drivers/sprd_uart.c000066400000000000000000000057511464416617300201340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Spreadtrum Communications Inc. * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include /* Register definitions */ #define UART_TXD 0x0000 #define UART_RXD 0x0004 #define UART_STS1 0x000C /* data number in TX and RX fifo */ #define UART_SIZE 0x0010 /* Register Bit Fields*/ #define STS1_RXF_CNT_MASK 0x00ff /* Rx FIFO data counter mask */ #define STS1_TXF_CNT_MASK 0xff00 /* Tx FIFO data counter mask */ static vaddr_t chip_to_base(struct serial_chip *chip) { struct sprd_uart_data *pd = container_of(chip, struct sprd_uart_data, chip); return io_pa_or_va(&pd->base, UART_SIZE); } static void sprd_uart_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (io_read32(base + UART_STS1) & STS1_TXF_CNT_MASK) ; } static bool sprd_uart_have_rx_data(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); return !!(io_read32(base + UART_STS1) & STS1_RXF_CNT_MASK); } static void sprd_uart_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); sprd_uart_flush(chip); io_write32(base + UART_TXD, ch); } static int sprd_uart_getchar(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!sprd_uart_have_rx_data(chip)) ; return io_read32(base + UART_RXD) & 0xff; } static const struct serial_ops sprd_uart_ops = { .flush = sprd_uart_flush, .getchar = sprd_uart_getchar, .have_rx_data = sprd_uart_have_rx_data, .putc = sprd_uart_putc, }; DECLARE_KEEP_PAGER(sprd_uart_ops); void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base) { pd->base.pa = base; pd->chip.ops = &sprd_uart_ops; } optee_os-4.3.0/core/drivers/stih_asc.c000066400000000000000000000021571464416617300177230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #define ASC_BAUDRATE 0x00 #define ASC_TXBUFFER 0x04 #define ASC_STATUS 0x14 #define ASC_STATUS_TX_EMPTY BIT(1) #define ASC_STATUS_TX_HALF_EMPTY BIT(2) static vaddr_t chip_to_base(struct serial_chip *chip) { struct stih_asc_pd *pd = container_of(chip, struct stih_asc_pd, chip); return io_pa_or_va(&pd->base, STIH_ASC_REG_SIZE); } static void stih_asc_flush(struct serial_chip *chip) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + ASC_STATUS) & ASC_STATUS_TX_EMPTY)) ; } static void stih_asc_putc(struct serial_chip *chip, int ch) { vaddr_t base = chip_to_base(chip); while (!(io_read32(base + ASC_STATUS) & ASC_STATUS_TX_HALF_EMPTY)) ; io_write32(base + ASC_TXBUFFER, ch); } static const struct serial_ops stih_asc_ops = { .flush = stih_asc_flush, .putc = stih_asc_putc, }; DECLARE_KEEP_PAGER(stih_asc_ops); void stih_asc_init(struct stih_asc_pd *pd, vaddr_t base) { pd->base.pa = base; pd->chip.ops = &stih_asc_ops; } optee_os-4.3.0/core/drivers/stm32_bsec.c000066400000000000000000000545211464416617300200740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2017-2021, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_STM32MP13 #define DT_BSEC_COMPAT "st,stm32mp13-bsec" #endif #ifdef CFG_STM32MP15 #define DT_BSEC_COMPAT "st,stm32mp15-bsec" #endif #define BSEC_OTP_MASK GENMASK_32(4, 0) #define BSEC_OTP_BANK_SHIFT U(5) /* Permanent lock bitmasks */ #define DATA_LOWER_OTP_PERLOCK_BIT U(3) #define DATA_UPPER_OTP_PERLOCK_BIT U(1) /* BSEC register offset */ #define BSEC_OTP_CONF_OFF U(0x000) #define BSEC_OTP_CTRL_OFF U(0x004) #define BSEC_OTP_WRDATA_OFF U(0x008) #define BSEC_OTP_STATUS_OFF U(0x00C) #define BSEC_OTP_LOCK_OFF U(0x010) #define BSEC_DEN_OFF U(0x014) #define BSEC_FEN_OFF U(0x018) #define BSEC_DISTURBED_OFF U(0x01C) #define BSEC_DISTURBED1_OFF U(0x020) #define BSEC_DISTURBED2_OFF U(0x024) #define BSEC_ERROR_OFF U(0x034) #define BSEC_ERROR1_OFF U(0x038) #define BSEC_ERROR2_OFF U(0x03C) #define BSEC_WRLOCK_OFF U(0x04C) #define BSEC_WRLOCK1_OFF U(0x050) #define BSEC_WRLOCK2_OFF U(0x054) #define BSEC_SPLOCK_OFF U(0x064) #define BSEC_SPLOCK1_OFF U(0x068) #define BSEC_SPLOCK2_OFF U(0x06C) #define BSEC_SWLOCK_OFF U(0x07C) #define BSEC_SWLOCK1_OFF U(0x080) #define BSEC_SWLOCK2_OFF U(0x084) #define BSEC_SRLOCK_OFF U(0x094) #define BSEC_SRLOCK1_OFF U(0x098) #define BSEC_SRLOCK2_OFF U(0x09C) #define BSEC_JTAG_IN_OFF U(0x0AC) #define BSEC_JTAG_OUT_OFF U(0x0B0) #define BSEC_SCRATCH_OFF U(0x0B4) #define BSEC_OTP_DATA_OFF U(0x200) #define BSEC_IPHW_CFG_OFF U(0xFF0) #define BSEC_IPVR_OFF U(0xFF4) #define BSEC_IP_ID_OFF U(0xFF8) #define BSEC_IP_MAGIC_ID_OFF U(0xFFC) /* BSEC_CONFIGURATION Register */ #define BSEC_CONF_POWER_UP_MASK BIT(0) #define BSEC_CONF_POWER_UP_SHIFT U(0) #define BSEC_CONF_FRQ_MASK GENMASK_32(2, 1) #define BSEC_CONF_FRQ_SHIFT U(1) #define BSEC_CONF_PRG_WIDTH_MASK GENMASK_32(6, 3) #define BSEC_CONF_PRG_WIDTH_SHIFT U(3) #define BSEC_CONF_TREAD_MASK GENMASK_32(8, 7) #define BSEC_CONF_TREAD_SHIFT U(7) /* BSEC_CONTROL Register */ #define BSEC_READ U(0x000) #define BSEC_WRITE U(0x100) #define BSEC_LOCK U(0x200) /* BSEC_STATUS Register */ #define BSEC_MODE_SECURED BIT(0) #define BSEC_MODE_INVALID BIT(2) #define BSEC_MODE_BUSY BIT(3) #define BSEC_MODE_PROGFAIL BIT(4) #define BSEC_MODE_PWR BIT(5) #define BSEC_MODE_CLOSED BIT(8) /* BSEC_DEBUG bitfields */ #ifdef CFG_STM32MP13 #define BSEC_DEN_ALL_MSK (GENMASK_32(11, 10) | GENMASK_32(8, 1)) #endif #ifdef CFG_STM32MP15 #define BSEC_DEN_ALL_MSK GENMASK_32(11, 1) #endif /* * OTP Lock services definition * Value must corresponding to the bit position in the register */ #define BSEC_LOCK_UPPER_OTP U(0x00) #define BSEC_LOCK_DEBUG U(0x02) #define BSEC_LOCK_PROGRAM U(0x04) /* Timeout when polling on status */ #define BSEC_TIMEOUT_US U(10000) struct bsec_dev { struct io_pa_va base; unsigned int upper_base; unsigned int max_id; uint32_t *nsec_access; }; /* Only 1 instance of BSEC is expected per platform */ static struct bsec_dev bsec_dev; /* BSEC access protection */ static unsigned int lock = SPINLOCK_UNLOCK; static uint32_t bsec_lock(void) { return may_spin_lock(&lock); } static void bsec_unlock(uint32_t exceptions) { may_spin_unlock(&lock, exceptions); } static uint32_t otp_max_id(void) { return bsec_dev.max_id; } static uint32_t otp_upper_base(void) { return bsec_dev.upper_base; } static uint32_t otp_bank_offset(uint32_t otp_id) { assert(otp_id <= otp_max_id()); return ((otp_id & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * sizeof(uint32_t); } static vaddr_t bsec_base(void) { return io_pa_or_va_secure(&bsec_dev.base, BSEC_IP_MAGIC_ID_OFF + 1); } static uint32_t bsec_status(void) { return io_read32(bsec_base() + BSEC_OTP_STATUS_OFF); } static bool state_is_invalid_mode(void) { return bsec_status() & BSEC_MODE_INVALID; } static bool state_is_secured_mode(void) { return bsec_status() & BSEC_MODE_SECURED; } static bool state_is_closed_mode(void) { uint32_t otp_cfg = 0; uint32_t close_mode = 0; TEE_Result res = TEE_ERROR_GENERIC; size_t __maybe_unused sz = 0; uint8_t __maybe_unused offset = 0; if (IS_ENABLED(CFG_STM32MP13)) return bsec_status() & BSEC_MODE_CLOSED; res = stm32_bsec_find_otp_in_nvmem_layout("cfg0_otp", &otp_cfg, &offset, &sz); if (res || sz != 8 || offset) panic("CFG0 OTP not found or invalid"); if (stm32_bsec_read_otp(&close_mode, otp_cfg)) panic("Unable to read OTP"); return close_mode & CFG0_OTP_CLOSED_DEVICE; } /* * Check that BSEC interface does not report an error * @otp_id : OTP number * @check_disturbed: check only error (false) or all sources (true) * Return a TEE_Result compliant value */ static TEE_Result check_no_error(uint32_t otp_id, bool check_disturbed) { uint32_t bit = BIT(otp_id & BSEC_OTP_MASK); uint32_t bank = otp_bank_offset(otp_id); if (io_read32(bsec_base() + BSEC_ERROR_OFF + bank) & bit) return TEE_ERROR_GENERIC; if (check_disturbed && io_read32(bsec_base() + BSEC_DISTURBED_OFF + bank) & bit) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result power_up_safmem(void) { uint64_t timeout_ref = 0; io_mask32(bsec_base() + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP_MASK, BSEC_CONF_POWER_UP_MASK); timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); while (!timeout_elapsed(timeout_ref)) if (bsec_status() & BSEC_MODE_PWR) break; if (bsec_status() & BSEC_MODE_PWR) return TEE_SUCCESS; return TEE_ERROR_GENERIC; } static TEE_Result power_down_safmem(void) { uint64_t timeout_ref = 0; io_mask32(bsec_base() + BSEC_OTP_CONF_OFF, 0, BSEC_CONF_POWER_UP_MASK); timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); while (!timeout_elapsed(timeout_ref)) if (!(bsec_status() & BSEC_MODE_PWR)) break; if (!(bsec_status() & BSEC_MODE_PWR)) return TEE_SUCCESS; return TEE_ERROR_GENERIC; } TEE_Result stm32_bsec_shadow_register(uint32_t otp_id) { TEE_Result result = 0; uint32_t exceptions = 0; uint64_t timeout_ref = 0; bool locked = false; /* Check if shadowing of OTP is locked, informative only */ result = stm32_bsec_read_sr_lock(otp_id, &locked); if (result) return result; if (locked) DMSG("BSEC shadow warning: OTP locked"); if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; exceptions = bsec_lock(); result = power_up_safmem(); if (result) goto out; io_write32(bsec_base() + BSEC_OTP_CTRL_OFF, otp_id | BSEC_READ); timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); while (!timeout_elapsed(timeout_ref)) if (!(bsec_status() & BSEC_MODE_BUSY)) break; if (bsec_status() & BSEC_MODE_BUSY) result = TEE_ERROR_BUSY; else result = check_no_error(otp_id, true /* check-disturbed */); power_down_safmem(); out: bsec_unlock(exceptions); return result; } TEE_Result stm32_bsec_read_otp(uint32_t *value, uint32_t otp_id) { if (otp_id > otp_max_id()) return TEE_ERROR_BAD_PARAMETERS; if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; *value = io_read32(bsec_base() + BSEC_OTP_DATA_OFF + (otp_id * sizeof(uint32_t))); return TEE_SUCCESS; } TEE_Result stm32_bsec_shadow_read_otp(uint32_t *otp_value, uint32_t otp_id) { TEE_Result result = 0; result = stm32_bsec_shadow_register(otp_id); if (result) { EMSG("BSEC %"PRIu32" Shadowing Error %#"PRIx32, otp_id, result); return result; } result = stm32_bsec_read_otp(otp_value, otp_id); if (result) EMSG("BSEC %"PRIu32" Read Error %#"PRIx32, otp_id, result); return result; } TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id) { TEE_Result result = 0; uint32_t exceptions = 0; vaddr_t otp_data_base = bsec_base() + BSEC_OTP_DATA_OFF; bool locked = false; /* Check if write of OTP is locked, informative only */ result = stm32_bsec_read_sw_lock(otp_id, &locked); if (result) return result; if (locked) DMSG("BSEC write warning: OTP locked"); if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; exceptions = bsec_lock(); io_write32(otp_data_base + (otp_id * sizeof(uint32_t)), value); bsec_unlock(exceptions); return TEE_SUCCESS; } #ifdef CFG_STM32_BSEC_WRITE TEE_Result stm32_bsec_program_otp(uint32_t value, uint32_t otp_id) { TEE_Result result = 0; uint32_t exceptions = 0; uint64_t timeout_ref = 0; bool locked = false; /* Check if shadowing of OTP is locked, informative only */ result = stm32_bsec_read_sp_lock(otp_id, &locked); if (result) return result; if (locked) DMSG("BSEC program warning: OTP locked"); if (io_read32(bsec_base() + BSEC_OTP_LOCK_OFF) & BIT(BSEC_LOCK_PROGRAM)) DMSG("BSEC program warning: GPLOCK activated"); if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; exceptions = bsec_lock(); result = power_up_safmem(); if (result) goto out; io_write32(bsec_base() + BSEC_OTP_WRDATA_OFF, value); io_write32(bsec_base() + BSEC_OTP_CTRL_OFF, otp_id | BSEC_WRITE); timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); while (!timeout_elapsed(timeout_ref)) if (!(bsec_status() & BSEC_MODE_BUSY)) break; if (bsec_status() & BSEC_MODE_BUSY) result = TEE_ERROR_BUSY; else if (bsec_status() & BSEC_MODE_PROGFAIL) result = TEE_ERROR_BAD_PARAMETERS; else result = check_no_error(otp_id, true /* check-disturbed */); power_down_safmem(); out: bsec_unlock(exceptions); return result; } TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id) { TEE_Result result = 0; uint32_t data = 0; uint32_t addr = 0; uint32_t exceptions = 0; vaddr_t base = bsec_base(); uint64_t timeout_ref = 0; uint32_t upper_base = otp_upper_base(); if (otp_id > otp_max_id()) return TEE_ERROR_BAD_PARAMETERS; /* * 2 bits per words for lower OTPs: 2:1 Redundancy * 1 bit per word for upper OTPs : ECC support * e.g with 32 lower and 64 upper OTPs: * OTP word to be ADDR[6:0] WRDATA[31:0] * locked * 0 0x00 0x0000 0003 * 1 0x00 0x0000 000C * ... ... ... * 7 0x00 0x0000 C000 * 8 0x01 0x0000 0003 * ... ... ... * 31 0x03 0x0000 C000 * 32 0x04 0x0000 0001 * 33 0x04 0x0000 0002 * 95 0x07 0x0000 8000 */ if (otp_id < upper_base) { addr = otp_id / 8U; data = DATA_LOWER_OTP_PERLOCK_BIT << ((otp_id * 2U) & 0xF); } else { addr = upper_base / 8U + (otp_id - upper_base) / 16U; data = DATA_UPPER_OTP_PERLOCK_BIT << (otp_id & 0xF); } if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; exceptions = bsec_lock(); result = power_up_safmem(); if (result) goto out; io_write32(base + BSEC_OTP_WRDATA_OFF, data); io_write32(base + BSEC_OTP_CTRL_OFF, addr | BSEC_WRITE | BSEC_LOCK); timeout_ref = timeout_init_us(BSEC_TIMEOUT_US); while (!timeout_elapsed(timeout_ref)) if (!(bsec_status() & BSEC_MODE_BUSY)) break; if (bsec_status() & BSEC_MODE_BUSY) result = TEE_ERROR_BUSY; else if (bsec_status() & BSEC_MODE_PROGFAIL) result = TEE_ERROR_BAD_PARAMETERS; else result = check_no_error(otp_id, false /* not-disturbed */); #ifdef CFG_STM32MP13 io_write32(base + BSEC_OTP_CTRL_OFF, addr | BSEC_READ | BSEC_LOCK); #endif power_down_safmem(); out: bsec_unlock(exceptions); return result; } #endif /*CFG_STM32_BSEC_WRITE*/ TEE_Result stm32_bsec_write_debug_conf(uint32_t value) { TEE_Result result = TEE_ERROR_GENERIC; uint32_t exceptions = 0; assert(!(value & ~BSEC_DEN_ALL_MSK)); if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; exceptions = bsec_lock(); io_clrsetbits32(bsec_base() + BSEC_DEN_OFF, BSEC_DEN_ALL_MSK, value); if (stm32_bsec_read_debug_conf() == value) result = TEE_SUCCESS; bsec_unlock(exceptions); return result; } uint32_t stm32_bsec_read_debug_conf(void) { return io_read32(bsec_base() + BSEC_DEN_OFF) & BSEC_DEN_ALL_MSK; } static TEE_Result set_bsec_lock(uint32_t otp_id, size_t lock_offset) { uint32_t bank = otp_bank_offset(otp_id); uint32_t otp_mask = BIT(otp_id & BSEC_OTP_MASK); vaddr_t lock_addr = bsec_base() + bank + lock_offset; uint32_t exceptions = 0; if (otp_id > STM32MP1_OTP_MAX_ID) return TEE_ERROR_BAD_PARAMETERS; if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; exceptions = bsec_lock(); io_write32(lock_addr, otp_mask); bsec_unlock(exceptions); return TEE_SUCCESS; } TEE_Result stm32_bsec_set_sr_lock(uint32_t otp_id) { return set_bsec_lock(otp_id, BSEC_SRLOCK_OFF); } TEE_Result stm32_bsec_set_sw_lock(uint32_t otp_id) { return set_bsec_lock(otp_id, BSEC_SWLOCK_OFF); } TEE_Result stm32_bsec_set_sp_lock(uint32_t otp_id) { return set_bsec_lock(otp_id, BSEC_SPLOCK_OFF); } static TEE_Result read_bsec_lock(uint32_t otp_id, bool *locked, size_t lock_offset) { uint32_t bank = otp_bank_offset(otp_id); uint32_t otp_mask = BIT(otp_id & BSEC_OTP_MASK); vaddr_t lock_addr = bsec_base() + bank + lock_offset; if (otp_id > STM32MP1_OTP_MAX_ID) return TEE_ERROR_BAD_PARAMETERS; if (state_is_invalid_mode()) return TEE_ERROR_SECURITY; *locked = (io_read32(lock_addr) & otp_mask) != 0; return TEE_SUCCESS; } TEE_Result stm32_bsec_read_sr_lock(uint32_t otp_id, bool *locked) { return read_bsec_lock(otp_id, locked, BSEC_SRLOCK_OFF); } TEE_Result stm32_bsec_read_sw_lock(uint32_t otp_id, bool *locked) { return read_bsec_lock(otp_id, locked, BSEC_SWLOCK_OFF); } TEE_Result stm32_bsec_read_sp_lock(uint32_t otp_id, bool *locked) { return read_bsec_lock(otp_id, locked, BSEC_SPLOCK_OFF); } TEE_Result stm32_bsec_read_permanent_lock(uint32_t otp_id, bool *locked) { return read_bsec_lock(otp_id, locked, BSEC_WRLOCK_OFF); } static size_t nsec_access_array_size(void) { size_t upper_count = otp_max_id() - otp_upper_base() + 1; return ROUNDUP_DIV(upper_count, BSEC_BITS_PER_WORD); } static bool nsec_access_granted(unsigned int index) { uint32_t *array = bsec_dev.nsec_access; return array && (index / BSEC_BITS_PER_WORD) < nsec_access_array_size() && array[index / BSEC_BITS_PER_WORD] & BIT(index % BSEC_BITS_PER_WORD); } bool stm32_bsec_can_access_otp(uint32_t otp_id) { return (otp_id <= otp_max_id()) && !state_is_invalid_mode(); } bool stm32_bsec_nsec_can_access_otp(uint32_t otp_id) { return otp_id < otp_upper_base() || nsec_access_granted(otp_id - otp_upper_base()); } /* * struct nvmem_layout - NVMEM cell description * @name: Name of the nvmem node in the DT * @otp_id: BSEC base index for the OTP words * @bit_offset: Bit offset in the OTP word * @bit_len: Bit size of the OTP word * @phandle: Associated phandle in embedded DTB */ struct nvmem_layout { char *name; uint32_t otp_id; uint8_t bit_offset; size_t bit_len; uint32_t phandle; }; static struct nvmem_layout *nvmem_layout; static size_t nvmem_layout_count; static TEE_Result stm32_bsec_otp_setting(size_t i, uint32_t *otp_id, uint8_t *otp_bit_offset, size_t *otp_bit_len) { if (otp_id) *otp_id = nvmem_layout[i].otp_id; if (otp_bit_offset) *otp_bit_offset = nvmem_layout[i].bit_offset; if (otp_bit_len) *otp_bit_len = nvmem_layout[i].bit_len; DMSG("nvmem[%zu] = %s at BSEC word %" PRIu32 " bits [%" PRIu8 " %zu]", i, nvmem_layout[i].name, nvmem_layout[i].otp_id, nvmem_layout[i].bit_offset, nvmem_layout[i].bit_len); return TEE_SUCCESS; } TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, uint32_t *otp_id, uint8_t *otp_bit_offset, size_t *otp_bit_len) { size_t i = 0; if (!name) return TEE_ERROR_BAD_PARAMETERS; for (i = 0; i < nvmem_layout_count; i++) { if (!nvmem_layout[i].name || strcmp(name, nvmem_layout[i].name)) continue; return stm32_bsec_otp_setting(i, otp_id, otp_bit_offset, otp_bit_len); } DMSG("nvmem %s failed", name); return TEE_ERROR_ITEM_NOT_FOUND; } TEE_Result stm32_bsec_find_otp_by_phandle(const uint32_t phandle, uint32_t *otp_id, uint8_t *otp_bit_offset, size_t *otp_bit_len) { size_t i = 0; if (!phandle) return TEE_ERROR_GENERIC; for (i = 0; i < nvmem_layout_count; i++) { if (nvmem_layout[i].phandle != phandle) continue; return stm32_bsec_otp_setting(i, otp_id, otp_bit_offset, otp_bit_len); } DMSG("nvmem %u not found", phandle); return TEE_ERROR_ITEM_NOT_FOUND; } TEE_Result stm32_bsec_get_state(enum stm32_bsec_sec_state *state) { if (!state) return TEE_ERROR_BAD_PARAMETERS; if (state_is_invalid_mode() || !state_is_secured_mode()) { *state = BSEC_STATE_INVALID; } else { if (state_is_closed_mode()) *state = BSEC_STATE_SEC_CLOSED; else *state = BSEC_STATE_SEC_OPEN; } return TEE_SUCCESS; } static void enable_nsec_access(unsigned int otp_id) { unsigned int idx = (otp_id - otp_upper_base()) / BSEC_BITS_PER_WORD; if (otp_id < otp_upper_base()) return; if (otp_id > otp_max_id() || stm32_bsec_shadow_register(otp_id)) panic(); bsec_dev.nsec_access[idx] |= BIT(otp_id % BSEC_BITS_PER_WORD); } static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) { int bsec_subnode = 0; bsec_dev.nsec_access = calloc(nsec_access_array_size(), sizeof(*bsec_dev.nsec_access)); if (!bsec_dev.nsec_access) panic(); fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { unsigned int reg_offset = 0; unsigned int reg_size = 0; unsigned int otp_id = 0; unsigned int i = 0; size_t size = 0; reg_offset = fdt_reg_base_address(fdt, bsec_subnode); reg_size = fdt_reg_size(fdt, bsec_subnode); assert(reg_offset != DT_INFO_INVALID_REG && reg_size != DT_INFO_INVALID_REG_SIZE); otp_id = reg_offset / sizeof(uint32_t); if (otp_id < STM32MP1_UPPER_OTP_START) { unsigned int otp_end = ROUNDUP_DIV(reg_offset + reg_size, sizeof(uint32_t)); if (otp_end > STM32MP1_UPPER_OTP_START) { /* * OTP crosses Lower/Upper boundary, consider * only the upper part. */ otp_id = STM32MP1_UPPER_OTP_START; reg_size -= (STM32MP1_UPPER_OTP_START * sizeof(uint32_t)) - reg_offset; reg_offset = STM32MP1_UPPER_OTP_START * sizeof(uint32_t); DMSG("OTP crosses Lower/Upper boundary"); } else { continue; } } /* Handle different kinds of non-secure accesses */ if (fdt_getprop(fdt, bsec_subnode, "st,non-secure-otp-provisioning", NULL)) { bool locked = false; bool locked_2 = false; /* Check if write of OTP is locked */ if (stm32_bsec_read_permanent_lock(otp_id, &locked)) panic("Cannot read permanent lock"); /* * Check if fuses of the subnode * have the same lock status */ for (i = 1; i < (reg_size / sizeof(uint32_t)); i++) { if (stm32_bsec_read_permanent_lock(otp_id + i, &locked_2)) panic("Cannot read permanent lock"); if (locked != locked_2) { EMSG("Inconsistent status OTP ID %u", otp_id + i); locked = true; } } if (locked) { DMSG("BSEC: OTP locked"); continue; } } else if (!fdt_getprop(fdt, bsec_subnode, "st,non-secure-otp", NULL)) { continue; } if ((reg_offset % sizeof(uint32_t)) || (reg_size % sizeof(uint32_t))) panic("Unaligned non-secure OTP"); size = reg_size / sizeof(uint32_t); if (otp_id + size > OTP_MAX_SIZE) panic("OTP range oversized"); for (i = otp_id; i < otp_id + size; i++) enable_nsec_access(i); } } static void save_dt_nvmem_layout(void *fdt, int bsec_node) { int cell_max = 0; int cell_cnt = 0; int node = 0; fdt_for_each_subnode(node, fdt, bsec_node) cell_max++; if (!cell_max) return; nvmem_layout = calloc(cell_max, sizeof(*nvmem_layout)); if (!nvmem_layout) panic(); fdt_for_each_subnode(node, fdt, bsec_node) { unsigned int reg_offset = 0; unsigned int reg_length = 0; const char *string = NULL; const char *s = NULL; int len = 0; struct nvmem_layout *layout_cell = &nvmem_layout[cell_cnt]; uint32_t bits[2] = { }; string = fdt_get_name(fdt, node, &len); if (!string || !len) continue; layout_cell->phandle = fdt_get_phandle(fdt, node); assert(layout_cell->phandle != (uint32_t)-1); reg_offset = fdt_reg_base_address(fdt, node); reg_length = fdt_reg_size(fdt, node); if (reg_offset == DT_INFO_INVALID_REG || reg_length == DT_INFO_INVALID_REG_SIZE) { DMSG("Malformed nvmem %s: ignored", string); continue; } layout_cell->otp_id = reg_offset / sizeof(uint32_t); layout_cell->bit_offset = (reg_offset % sizeof(uint32_t)) * CHAR_BIT; layout_cell->bit_len = reg_length * CHAR_BIT; if (!fdt_read_uint32_array(fdt, node, "bits", bits, 2)) { layout_cell->bit_offset += bits[0]; layout_cell->bit_len = bits[1]; } s = strchr(string, '@'); if (s) len = s - string; layout_cell->name = strndup(string, len); if (!layout_cell->name) panic(); cell_cnt++; DMSG("nvmem[%d] = %s at BSEC word %" PRIu32 " bits [%" PRIu8 " %zu]", cell_cnt, layout_cell->name, layout_cell->otp_id, layout_cell->bit_offset, layout_cell->bit_len); } if (cell_cnt != cell_max) { nvmem_layout = realloc(nvmem_layout, cell_cnt * sizeof(*nvmem_layout)); if (!nvmem_layout) panic(); } nvmem_layout_count = cell_cnt; } static void initialize_bsec_from_dt(void) { void *fdt = NULL; int node = 0; struct dt_node_info bsec_info = { }; fdt = get_embedded_dt(); node = fdt_node_offset_by_compatible(fdt, 0, DT_BSEC_COMPAT); if (node < 0) panic(); fdt_fill_device_info(fdt, &bsec_info, node); if (bsec_info.reg != bsec_dev.base.pa || !(bsec_info.status & DT_STATUS_OK_SEC)) panic(); bsec_dt_otp_nsec_access(fdt, node); save_dt_nvmem_layout(fdt, node); } static TEE_Result bsec_pm(enum pm_op op, uint32_t pm_hint __unused, const struct pm_callback_handle *hdl __unused) { static uint32_t debug_conf; assert(op == PM_OP_SUSPEND || op == PM_OP_RESUME); if (op == PM_OP_SUSPEND) debug_conf = stm32_bsec_read_debug_conf(); else stm32_bsec_write_debug_conf(debug_conf); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(bsec_pm); static TEE_Result initialize_bsec(void) { struct stm32_bsec_static_cfg cfg = { }; stm32mp_get_bsec_static_cfg(&cfg); bsec_dev.base.pa = cfg.base; bsec_dev.upper_base = cfg.upper_start; bsec_dev.max_id = cfg.max_id; if (state_is_invalid_mode()) panic(); initialize_bsec_from_dt(); register_pm_core_service_cb(bsec_pm, NULL, "stm32_bsec"); return TEE_SUCCESS; } early_init(initialize_bsec); optee_os-4.3.0/core/drivers/stm32_etzpc.c000066400000000000000000000225471464416617300203100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2017-2019, STMicroelectronics */ /* * STM32 ETPZC acts as a firewall on stm32mp SoC peripheral interfaces and * internal memories. The driver expects a single instance of the controller * in the platform. * * The driver API is defined in header file stm32_etzpc.h. * * Driver registers a PM callback for restoration of the access permissions * when it resumes. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* Devicetree compatibility */ #define ETZPC_COMPAT "st,stm32-etzpc" /* ID Registers */ #define ETZPC_TZMA0_SIZE 0x000U #define ETZPC_DECPROT0 0x010U #define ETZPC_DECPROT_LOCK0 0x030U #define ETZPC_HWCFGR 0x3F0U #define ETZPC_VERR 0x3F4U /* ID Registers fields */ #define ETZPC_TZMA0_SIZE_LOCK BIT(31) #define ETZPC_DECPROT0_MASK GENMASK_32(1, 0) #define ETZPC_HWCFGR_NUM_TZMA_MASK GENMASK_32(7, 0) #define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0 #define ETZPC_HWCFGR_NUM_PER_SEC_MASK GENMASK_32(15, 8) #define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8 #define ETZPC_HWCFGR_NUM_AHB_SEC_MASK GENMASK_32(23, 16) #define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16 #define ETZPC_HWCFGR_CHUNCKS1N4_MASK GENMASK_32(31, 24) #define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24 #define DECPROT_SHIFT 1 #define IDS_PER_DECPROT_REGS 16U #define IDS_PER_DECPROT_LOCK_REGS 32U /* * Implementation uses uint8_t to store each securable DECPROT configuration * and uint16_t to store each securable TZMA configuration. When resuming * from deep suspend, the DECPROT configurations are restored. */ #define PERIPH_PM_LOCK_BIT BIT(7) #define PERIPH_PM_ATTR_MASK GENMASK_32(2, 0) #define TZMA_PM_LOCK_BIT BIT(15) #define TZMA_PM_VALUE_MASK GENMASK_32(9, 0) /* * @base - iobase for interface base address * @num_tzma - number of TZMA zone, read from the hardware * @num_ahb_sec - number of securable AHB master zone, read from the hardware * @num_per_sec - number of securable AHB & APB periphs, read from the hardware * @periph_cfg - Backup for restoring DECPROT when resuming (PERIH_PM_*) * @tzma_cfg - Backup for restoring TZMA when resuming (TZMA_PM_*) */ struct etzpc_instance { struct io_pa_va base; unsigned int num_tzma; unsigned int num_per_sec; unsigned int num_ahb_sec; uint8_t *periph_cfg; uint16_t *tzma_cfg; }; /* Only 1 instance of the ETZPC is expected per platform */ static struct etzpc_instance etzpc_dev; static vaddr_t etzpc_base(void) { return io_pa_or_va_secure(&etzpc_dev.base, 1); } static bool __maybe_unused valid_decprot_id(unsigned int id) { return id < etzpc_dev.num_per_sec; } static bool __maybe_unused valid_tzma_id(unsigned int id) { return id < etzpc_dev.num_tzma; } void etzpc_configure_decprot(uint32_t decprot_id, enum etzpc_decprot_attributes decprot_attr) { size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK; vaddr_t base = etzpc_base(); assert(valid_decprot_id(decprot_id)); io_clrsetbits32(base + ETZPC_DECPROT0 + offset, ETZPC_DECPROT0_MASK << shift, masked_decprot << shift); /* Save for PM */ assert((decprot_attr & ~PERIPH_PM_ATTR_MASK) == 0); COMPILE_TIME_ASSERT(ETZPC_DECPROT_MAX <= UINT8_MAX); etzpc_dev.periph_cfg[decprot_id] &= ~PERIPH_PM_ATTR_MASK; etzpc_dev.periph_cfg[decprot_id] |= (uint8_t)decprot_attr; } enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id) { size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; vaddr_t base = etzpc_base(); uint32_t value = 0; assert(valid_decprot_id(decprot_id)); value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) & ETZPC_DECPROT0_MASK; return (enum etzpc_decprot_attributes)value; } void etzpc_lock_decprot(uint32_t decprot_id) { size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); vaddr_t base = etzpc_base(); assert(valid_decprot_id(decprot_id)); io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask); /* Save for PM */ etzpc_dev.periph_cfg[decprot_id] |= PERIPH_PM_LOCK_BIT; } bool etzpc_get_lock_decprot(uint32_t decprot_id) { size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); vaddr_t base = etzpc_base(); assert(valid_decprot_id(decprot_id)); return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask; } void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value) { size_t offset = sizeof(uint32_t) * tzma_id; vaddr_t base = etzpc_base(); assert(valid_tzma_id(tzma_id)); io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value); /* Save for PM */ assert((tzma_value & ~TZMA_PM_VALUE_MASK) == 0); etzpc_dev.tzma_cfg[tzma_id] &= ~TZMA_PM_VALUE_MASK; etzpc_dev.tzma_cfg[tzma_id] |= tzma_value; } uint16_t etzpc_get_tzma(uint32_t tzma_id) { size_t offset = sizeof(uint32_t) * tzma_id; vaddr_t base = etzpc_base(); assert(valid_tzma_id(tzma_id)); return io_read32(base + ETZPC_TZMA0_SIZE + offset); } void etzpc_lock_tzma(uint32_t tzma_id) { size_t offset = sizeof(uint32_t) * tzma_id; vaddr_t base = etzpc_base(); assert(valid_tzma_id(tzma_id)); io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK); /* Save for PM */ etzpc_dev.tzma_cfg[tzma_id] |= TZMA_PM_LOCK_BIT; } bool etzpc_get_lock_tzma(uint32_t tzma_id) { size_t offset = sizeof(uint32_t) * tzma_id; vaddr_t base = etzpc_base(); assert(valid_tzma_id(tzma_id)); return io_read32(base + ETZPC_TZMA0_SIZE + offset) & ETZPC_TZMA0_SIZE_LOCK; } static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused, const struct pm_callback_handle *pm_handle) { struct etzpc_instance *dev = NULL; unsigned int n = 0; if (op != PM_OP_RESUME) return TEE_SUCCESS; dev = (struct etzpc_instance *)PM_CALLBACK_GET_HANDLE(pm_handle); for (n = 0; n < dev->num_per_sec; n++) { unsigned int attr = dev->periph_cfg[n] & PERIPH_PM_ATTR_MASK; etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr); if (dev->periph_cfg[n] & PERIPH_PM_LOCK_BIT) etzpc_lock_decprot(n); } for (n = 0; n < dev->num_tzma; n++) { uint16_t value = dev->tzma_cfg[n] & TZMA_PM_VALUE_MASK; etzpc_configure_tzma(n, value); if (dev->tzma_cfg[n] & TZMA_PM_LOCK_BIT) etzpc_lock_tzma(n); } return TEE_SUCCESS; } DECLARE_KEEP_PAGER(etzpc_pm); static void init_pm(struct etzpc_instance *dev) { unsigned int n = 0; dev->periph_cfg = calloc(dev->num_per_sec, sizeof(*dev->periph_cfg)); dev->tzma_cfg = calloc(dev->num_tzma, sizeof(*dev->tzma_cfg)); if (!dev->periph_cfg || !dev->tzma_cfg) panic(); for (n = 0; n < dev->num_per_sec; n++) { dev->periph_cfg[n] = (uint8_t)etzpc_get_decprot(n); if (etzpc_get_lock_decprot(n)) dev->periph_cfg[n] |= PERIPH_PM_LOCK_BIT; } for (n = 0; n < dev->num_tzma; n++) { dev->tzma_cfg[n] = (uint8_t)etzpc_get_tzma(n); if (etzpc_get_lock_tzma(n)) dev->tzma_cfg[n] |= TZMA_PM_LOCK_BIT; } register_pm_core_service_cb(etzpc_pm, dev, "stm32-etzpc"); } struct etzpc_hwcfg { unsigned int num_tzma; unsigned int num_per_sec; unsigned int num_ahb_sec; unsigned int chunk_size; }; static void get_hwcfg(struct etzpc_hwcfg *hwcfg) { uint32_t reg = io_read32(etzpc_base() + ETZPC_HWCFGR); hwcfg->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >> ETZPC_HWCFGR_NUM_TZMA_SHIFT; hwcfg->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >> ETZPC_HWCFGR_NUM_PER_SEC_SHIFT; hwcfg->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >> ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT; hwcfg->chunk_size = (reg & ETZPC_HWCFGR_CHUNCKS1N4_MASK) >> ETZPC_HWCFGR_CHUNCKS1N4_SHIFT; } static void init_device_from_hw_config(struct etzpc_instance *dev, paddr_t pbase) { struct etzpc_hwcfg hwcfg = { }; assert(!dev->base.pa && cpu_mmu_enabled()); dev->base.pa = pbase; dev->base.va = (vaddr_t)phys_to_virt(dev->base.pa, MEM_AREA_IO_SEC, 1); assert(etzpc_base()); get_hwcfg(&hwcfg); dev->num_tzma = hwcfg.num_tzma; dev->num_per_sec = hwcfg.num_per_sec; dev->num_ahb_sec = hwcfg.num_ahb_sec; DMSG("ETZPC revison 0x02%" PRIu8 ", per_sec %u, ahb_sec %u, tzma %u", io_read8(etzpc_base() + ETZPC_VERR), hwcfg.num_per_sec, hwcfg.num_ahb_sec, hwcfg.num_tzma); init_pm(dev); } static TEE_Result stm32_etzpc_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; paddr_t pbase = 0; int subnode = 0; pbase = fdt_reg_base_address(fdt, node); if (pbase == DT_INFO_INVALID_REG) panic(); init_device_from_hw_config(&etzpc_dev, pbase); fdt_for_each_subnode(subnode, fdt, node) { res = dt_driver_maybe_add_probe_node(fdt, subnode); if (res) { EMSG("Failed to add node %s to probe list: %#"PRIx32, fdt_get_name(fdt, subnode, NULL), res); panic(); } } return TEE_SUCCESS; } static const struct dt_device_match etzpc_match_table[] = { { .compatible = "st,stm32-etzpc" }, { } }; DEFINE_DT_DRIVER(etzpc_dt_driver) = { .name = "stm32-etzpc", .match_table = etzpc_match_table, .probe = stm32_etzpc_probe, }; optee_os-4.3.0/core/drivers/stm32_fmc.c000066400000000000000000000301041464416617300177140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _FMC_CFGR U(0x020) #define _FMC_SECCFGR U(0x300) #define _FMC_PRIVCFGR U(0x304) #define _FMC_RCFGLOCKR U(0x308) #define _FMC_CIDCFGR(x) (U(0x30C) + U(0x8) * (x)) #define _FMC_SEMCR(x) (U(0x310) + U(0x8) * (x)) /* * CFGR register bitfields */ #define _FMC_CFGR_CLKDIV_MASK GENMASK_32(19, 16) #define _FMC_CFGR_CLKDIV_SHIFT U(16) #define _FMC_CFGR_CCLKEN BIT(20) #define _FMC_CFGR_ENABLE BIT(31) /* * CIDCFGR register bitfields */ #define _FMC_CIDCFGR_SEMWL_MASK GENMASK_32(23, 16) #define _FMC_CIDCFGR_SCID_MASK GENMASK_32(6, 4) #define _FMC_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ _CIDCFGR_SEMEN | \ _FMC_CIDCFGR_SCID_MASK |\ _FMC_CIDCFGR_SEMWL_MASK) /* * PRIVCFGR register bitfields */ #define _FMC_PRIVCFGR_MASK GENMASK_32(5, 0) /* * RCFGLOCKR register bitfields */ #define _FMC_RCFGLOCKR_MASK GENMASK_32(5, 0) /* * SECCFGR register bitfields */ #define _FMC_SECCFGR_EN BIT(0) #define _FMC_SECCFGR_MASK GENMASK_32(5, 0) /* * SEMCR register bitfields */ #define _FMC_SEMCR_SCID_MASK GENMASK_32(7, 5) #define _FMC_SEMCR_SCID_SHIFT U(5) /* * Miscellaneous */ #define FMC_RIF_CONTROLLERS U(6) #define FMC_NB_MAX_CID_SUPPORTED U(7) #define FMC_NSEC_PER_SEC UL(1000000000) struct fmc_pdata { struct clk *fmc_clock; struct pinctrl_state *pinctrl_d; struct pinctrl_state *pinctrl_s; struct rif_conf_data conf_data; unsigned int nb_controller; vaddr_t base; uint32_t clk_period_ns; bool cclken; }; static struct fmc_pdata *fmc_d; static bool fmc_controller_is_secure(uint8_t controller) { return io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(controller); } static TEE_Result apply_rif_config(void) { TEE_Result res = TEE_ERROR_ACCESS_DENIED; uint32_t cidcfgr = 0; unsigned int i = 0; res = clk_enable(fmc_d->fmc_clock); if (res) panic("Cannot access FMC clock"); for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { if (!(BIT(i) & fmc_d->conf_data.access_mask[0])) continue; /* * Whatever the TDCID state, try to clear the configurable part * of the CIDCFGR register. * If TDCID, register will be cleared, if not, the clear will * be ignored. * When TDCID, OP-TEE should be the one to set the CID filtering * configuration. Clearing previous configuration prevents * undesired events during the only legitimate configuration. */ io_clrbits32(fmc_d->base + _FMC_CIDCFGR(i), _FMC_CIDCFGR_CONF_MASK); cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); /* Check if the controller is in semaphore mode */ if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1)) continue; /* If not TDCID, we want to acquire semaphores assigned to us */ res = stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(i), FMC_NB_MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't acquire semaphore for controller %u", i); clk_disable(fmc_d->fmc_clock); return res; } } /* Security and privilege RIF configuration */ io_clrsetbits32(fmc_d->base + _FMC_PRIVCFGR, _FMC_PRIVCFGR_MASK, fmc_d->conf_data.priv_conf[0]); io_clrsetbits32(fmc_d->base + _FMC_SECCFGR, _FMC_SECCFGR_MASK, fmc_d->conf_data.sec_conf[0]); for (i = 0; i < FMC_RIF_CONTROLLERS; i++) { if (!(BIT(i) & fmc_d->conf_data.access_mask[0])) continue; io_clrsetbits32(fmc_d->base + _FMC_CIDCFGR(i), _FMC_CIDCFGR_CONF_MASK, fmc_d->conf_data.cid_confs[i]); cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); /* * Take semaphore if the resource is in semaphore mode * and secured */ if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) || !(io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(i))) { res = stm32_rif_release_semaphore(fmc_d->base + _FMC_SEMCR(i), FMC_NB_MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't release semaphore for res%u", i); clk_disable(fmc_d->fmc_clock); return res; } } else { res = stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(i), FMC_NB_MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't acquire semaphore for res%u", i); clk_disable(fmc_d->fmc_clock); return res; } } } /* * Lock RIF configuration if configured. This cannot be undone until * next reset. */ io_clrsetbits32(fmc_d->base + _FMC_RCFGLOCKR, _FMC_RCFGLOCKR_MASK, fmc_d->conf_data.lock_conf[0]); if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) { /* Check that RIF config are applied, panic otherwise */ if ((io_read32(fmc_d->base + _FMC_PRIVCFGR) & fmc_d->conf_data.access_mask[0]) != fmc_d->conf_data.priv_conf[0]) { EMSG("FMC controller priv conf is incorrect"); panic(); } if ((io_read32(fmc_d->base + _FMC_SECCFGR) & fmc_d->conf_data.access_mask[0]) != fmc_d->conf_data.sec_conf[0]) { EMSG("FMC controller sec conf is incorrect"); panic(); } } /* Disable the clock to allow RCC RIF re-configuration on this clock */ clk_disable(fmc_d->fmc_clock); return TEE_SUCCESS; } static TEE_Result parse_dt(const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t rif_conf = 0; unsigned int i = 0; int lenp = 0; const fdt32_t *cuint = NULL; struct dt_node_info info = { }; struct io_pa_va addr = { }; int ctrl_node = 0; fdt_fill_device_info(fdt, &info, node); assert(info.reg != DT_INFO_INVALID_REG && info.reg_size != DT_INFO_INVALID_REG_SIZE); addr.pa = info.reg; fmc_d->base = io_pa_or_va(&addr, info.reg_size); res = clk_dt_get_by_index(fdt, node, 0, &fmc_d->fmc_clock); if (res) return res; res = pinctrl_get_state_by_name(fdt, node, "default", &fmc_d->pinctrl_d); if (res && res != TEE_ERROR_ITEM_NOT_FOUND) return res; res = pinctrl_get_state_by_name(fdt, node, "sleep", &fmc_d->pinctrl_s); if (res && res != TEE_ERROR_ITEM_NOT_FOUND) return res; cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); if (!cuint) panic("No RIF configuration available"); fmc_d->nb_controller = (unsigned int)(lenp / sizeof(uint32_t)); assert(fmc_d->nb_controller <= FMC_RIF_CONTROLLERS); fmc_d->conf_data.cid_confs = calloc(FMC_RIF_CONTROLLERS, sizeof(uint32_t)); fmc_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t)); fmc_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t)); fmc_d->conf_data.lock_conf = calloc(1, sizeof(uint32_t)); fmc_d->conf_data.access_mask = calloc(1, sizeof(uint32_t)); assert(fmc_d->conf_data.cid_confs && fmc_d->conf_data.sec_conf && fmc_d->conf_data.priv_conf && fmc_d->conf_data.access_mask); for (i = 0; i < fmc_d->nb_controller; i++) { rif_conf = fdt32_to_cpu(cuint[i]); stm32_rif_parse_cfg(rif_conf, &fmc_d->conf_data, FMC_NB_MAX_CID_SUPPORTED, FMC_RIF_CONTROLLERS); } fdt_for_each_subnode(ctrl_node, fdt, node) { int status = fdt_get_status(fdt, ctrl_node); uint32_t bank = 0; if (status == DT_STATUS_DISABLED) continue; if (fdt_read_uint32(fdt, ctrl_node, "reg", &bank) < 0) return TEE_ERROR_BAD_PARAMETERS; if (bank != 0) continue; if (fdt_getprop(fdt, ctrl_node, "st,fmc2-ebi-cs-cclk-enable", NULL)) fmc_d->cclken = true; if (!fmc_d->cclken) continue; if (fdt_read_uint32(fdt, ctrl_node, "st,fmc2-ebi-cs-clk-period-ns", &fmc_d->clk_period_ns) < 0) return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result __maybe_unused check_fmc_rif_conf(void) { unsigned int i = 0; TEE_Result res = TEE_ERROR_GENERIC; res = clk_enable(fmc_d->fmc_clock); if (res) panic("Cannot access FMC clock"); if (fmc_controller_is_secure(0)) goto end; for (i = 1; i < fmc_d->nb_controller; i++) { uint32_t cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i)); uint32_t semcr = io_read32(fmc_d->base + _FMC_SEMCR(i)); /* Check if a controller is secure */ if (fmc_controller_is_secure(i)) { res = TEE_ERROR_BAD_STATE; goto end; } /* * Check if a controller is shared with incorrect CID * (!= RIF_CID1) */ res = stm32_rif_check_access(cidcfgr, semcr, FMC_NB_MAX_CID_SUPPORTED, RIF_CID1); if (res) break; } end: clk_disable(fmc_d->fmc_clock); return res; } static void configure_fmc(void) { uint32_t cidcfgr = 0; uint32_t semcr = 0; if (clk_enable(fmc_d->fmc_clock)) panic("Cannot access FMC clock"); semcr = io_read32(fmc_d->base + _FMC_SEMCR(0)); cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(0)); /* * If OP-TEE doesn't have access to the controller 0, * then we don't want to try to enable the FMC. */ if (stm32_rif_check_access(cidcfgr, semcr, FMC_NB_MAX_CID_SUPPORTED, RIF_CID1)) goto end; /* Check controller 0 access */ if (!fmc_controller_is_secure(0)) { DMSG("Controller 0 non-secure, FMC not enabled"); goto end; } if (cidcfgr & _CIDCFGR_SEMEN && stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(0), FMC_NB_MAX_CID_SUPPORTED)) panic("Couldn't acquire controller 0 semaphore"); if (fmc_d->pinctrl_d && pinctrl_apply_state(fmc_d->pinctrl_d)) panic("Could not apply FMC pinctrl"); if (fmc_d->cclken) { unsigned long hclk = clk_get_rate(fmc_d->fmc_clock); unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000); unsigned long timing = DIV_ROUND_UP(fmc_d->clk_period_ns * 1000, hclkp); uint32_t clk_div = SHIFT_U32(1, _FMC_CFGR_CLKDIV_SHIFT); if (timing > 1) { timing--; if (timing > _FMC_CFGR_CLKDIV_MASK >> _FMC_CFGR_CLKDIV_SHIFT) clk_div = _FMC_CFGR_CLKDIV_MASK; else clk_div = SHIFT_U32(timing, _FMC_CFGR_CLKDIV_SHIFT); } io_clrsetbits32(fmc_d->base + _FMC_CFGR, _FMC_CFGR_CLKDIV_MASK | _FMC_CFGR_CCLKEN, clk_div | _FMC_CFGR_CCLKEN); } /* Set the FMC enable BIT */ io_setbits32(fmc_d->base + _FMC_CFGR, _FMC_CFGR_ENABLE); end: clk_disable(fmc_d->fmc_clock); } static void fmc_setup(void) { if (apply_rif_config()) panic("Failed to apply rif_config"); /* Sanity check for FMC RIF config */ assert(check_fmc_rif_conf()); configure_fmc(); } static void fmc_suspend(void) { unsigned int i = 0; if (clk_enable(fmc_d->fmc_clock)) panic("Cannot access FMC clock"); if (fmc_controller_is_secure(0) && fmc_d->pinctrl_s && pinctrl_apply_state(fmc_d->pinctrl_s)) panic(); for (i = 0; i < FMC_RIF_CONTROLLERS; i++) fmc_d->conf_data.cid_confs[i] = io_read32(fmc_d->base + _FMC_CIDCFGR(i)) & _FMC_CIDCFGR_CONF_MASK; fmc_d->conf_data.priv_conf[0] = io_read32(fmc_d->base + _FMC_PRIVCFGR) & _FMC_PRIVCFGR_MASK; fmc_d->conf_data.sec_conf[0] = io_read32(fmc_d->base + _FMC_SECCFGR) & _FMC_SECCFGR_MASK; fmc_d->conf_data.lock_conf[0] = io_read32(fmc_d->base + _FMC_RCFGLOCKR) & _FMC_RCFGLOCKR_MASK; fmc_d->conf_data.access_mask[0] = GENMASK_32(FMC_RIF_CONTROLLERS - 1, 0); clk_disable(fmc_d->fmc_clock); } static TEE_Result fmc_pm(enum pm_op op, unsigned int pm_hint, const struct pm_callback_handle *pm_handle __unused) { if (pm_hint != PM_HINT_CONTEXT_STATE) return TEE_SUCCESS; if (op == PM_OP_RESUME) fmc_setup(); else fmc_suspend(); return TEE_SUCCESS; } static TEE_Result fmc_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; fmc_d = calloc(1, sizeof(*fmc_d)); if (!fmc_d) return TEE_ERROR_OUT_OF_MEMORY; res = parse_dt(fdt, node); if (res) goto err; fmc_setup(); register_pm_core_service_cb(fmc_pm, NULL, "stm32-fmc"); return TEE_SUCCESS; err: /* Free all allocated resources */ free(fmc_d->conf_data.cid_confs); free(fmc_d->conf_data.sec_conf); free(fmc_d->conf_data.priv_conf); free(fmc_d->conf_data.access_mask); free(fmc_d); return res; } static const struct dt_device_match stm32_fmc_match_table[] = { { .compatible = "st,stm32mp25-fmc2-ebi" }, { } }; DEFINE_DT_DRIVER(stm32_fmc_dt_driver) = { .name = "stm32_fmc", .match_table = stm32_fmc_match_table, .probe = fmc_probe, }; optee_os-4.3.0/core/drivers/stm32_gpio.c000066400000000000000000000600521464416617300201120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2017-2023, STMicroelectronics * * STM32 GPIO driver is used as pin controller for stm32mp SoCs. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef CFG_DRIVERS_GPIO #error stm32_gpio driver expects CFG_DRIVERS_GPIO #endif #define GPIO_PIN_MAX 15 #define GPIO_MODER_OFFSET U(0x00) #define GPIO_OTYPER_OFFSET U(0x04) #define GPIO_OSPEEDR_OFFSET U(0x08) #define GPIO_PUPDR_OFFSET U(0x0c) #define GPIO_IDR_OFFSET U(0x10) #define GPIO_ODR_OFFSET U(0x14) #define GPIO_BSRR_OFFSET U(0x18) #define GPIO_AFRL_OFFSET U(0x20) #define GPIO_AFRH_OFFSET U(0x24) #define GPIO_SECR_OFFSET U(0x30) #define GPIO_ALT_LOWER_LIMIT U(0x8) #define GPIO_MODE_MASK GENMASK_32(1, 0) #define GPIO_OSPEED_MASK GENMASK_32(1, 0) #define GPIO_PUPD_PULL_MASK GENMASK_32(1, 0) #define GPIO_ALTERNATE_MASK GENMASK_32(3, 0) #define DT_GPIO_BANK_SHIFT U(12) #define DT_GPIO_BANK_MASK GENMASK_32(16, 12) #define DT_GPIO_PIN_SHIFT U(8) #define DT_GPIO_PIN_MASK GENMASK_32(11, 8) #define DT_GPIO_MODE_MASK GENMASK_32(7, 0) #define DT_GPIO_BANK_NAME0 "GPIOA" #define GPIO_MODE_INPUT U(0x0) #define GPIO_MODE_OUTPUT U(0x1) #define GPIO_MODE_ALTERNATE U(0x2) #define GPIO_MODE_ANALOG U(0x3) #define GPIO_OTYPE_PUSH_PULL U(0x0) #define GPIO_OTYPE_OPEN_DRAIN U(0x1) #define GPIO_OSPEED_LOW U(0x0) #define GPIO_OSPEED_MEDIUM U(0x1) #define GPIO_OSPEED_HIGH U(0x2) #define GPIO_OSPEED_VERY_HIGH U(0x3) #define GPIO_PUPD_NO_PULL U(0x0) #define GPIO_PUPD_PULL_UP U(0x1) #define GPIO_PUPD_PULL_DOWN U(0x2) #define GPIO_OD_LEVEL_LOW U(0x0) #define GPIO_OD_LEVEL_HIGH U(0x1) /* * GPIO configuration description structured as single 16bit word * for efficient save/restore when GPIO pin suspends or resumes. * * @mode: One of GPIO_MODE_* * @otype: One of GPIO_OTYPE_* * @ospeed: One of GPIO_OSPEED_* * @pupd: One of GPIO_PUPD_* * @od: One of GPIO_OD_* * @af: Alternate function numerical ID between 0 and 15 */ struct gpio_cfg { uint16_t mode: 2; uint16_t otype: 1; uint16_t ospeed: 2; uint16_t pupd: 2; uint16_t od: 1; uint16_t af: 4; }; /* * Description of a pin and its muxing * * @bank: GPIO bank identifier as assigned by the platform * @pin: Pin number in the GPIO bank * @cfg: Pin configuration */ struct stm32_pinctrl { uint8_t bank; uint8_t pin; struct gpio_cfg cfg; }; /* * struct stm32_pinctrl_array - Array of pins in a pin control state * @count: Number of cells in @pinctrl * @pinctrl: Pin control configuration */ struct stm32_pinctrl_array { size_t count; struct stm32_pinctrl pinctrl[]; }; /** * struct stm32_gpio_bank - GPIO bank instance * * @base: base address of the GPIO controller registers. * @clock: clock identifier. * @gpio_chip: GPIO chip reference for that GPIO bank * @ngpios: number of GPIOs. * @bank_id: Id of the bank. * @lock: lock protecting the GPIO bank access. * @sec_support: True if bank supports pin security protection, otherwise false * @link: Link in bank list */ struct stm32_gpio_bank { vaddr_t base; struct clk *clock; struct gpio_chip gpio_chip; unsigned int ngpios; unsigned int bank_id; unsigned int lock; bool sec_support; STAILQ_ENTRY(stm32_gpio_bank) link; }; /** * Compatibility information of supported banks * * @gpioz: True if bank is a GPIOZ bank * @secure_control: Identify GPIO security bank capability. */ struct bank_compat { bool gpioz; bool secure_control; }; static unsigned int gpio_lock; static STAILQ_HEAD(, stm32_gpio_bank) bank_list = STAILQ_HEAD_INITIALIZER(bank_list); static bool is_stm32_gpio_chip(struct gpio_chip *chip); static struct stm32_gpio_bank *gpio_chip_to_bank(struct gpio_chip *chip) { return container_of(chip, struct stm32_gpio_bank, gpio_chip); } static enum gpio_level stm32_gpio_get_level(struct gpio_chip *chip, unsigned int gpio_pin) { struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); enum gpio_level level = GPIO_LEVEL_HIGH; unsigned int reg_offset = 0; unsigned int mode = 0; assert(gpio_pin < bank->ngpios); if (clk_enable(bank->clock)) panic(); mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & GPIO_MODE_MASK; switch (mode) { case GPIO_MODE_INPUT: reg_offset = GPIO_IDR_OFFSET; break; case GPIO_MODE_OUTPUT: reg_offset = GPIO_ODR_OFFSET; break; default: panic(); } if (io_read32(bank->base + reg_offset) & BIT(gpio_pin)) level = GPIO_LEVEL_HIGH; else level = GPIO_LEVEL_LOW; clk_disable(bank->clock); return level; } static void stm32_gpio_set_level(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_level level) { struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); assert(gpio_pin < bank->ngpios); if (clk_enable(bank->clock)) panic(); assert(((io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & GPIO_MODE_MASK) == GPIO_MODE_OUTPUT); if (level == GPIO_LEVEL_HIGH) io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin)); else io_write32(bank->base + GPIO_BSRR_OFFSET, BIT(gpio_pin + 16)); clk_disable(bank->clock); } static enum gpio_dir stm32_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio_pin) { struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); uint32_t mode = 0; assert(gpio_pin < bank->ngpios); if (clk_enable(bank->clock)) panic(); mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (gpio_pin << 1)) & GPIO_MODE_MASK; clk_disable(bank->clock); switch (mode) { case GPIO_MODE_INPUT: return GPIO_DIR_IN; case GPIO_MODE_OUTPUT: return GPIO_DIR_OUT; default: panic(); } } static void stm32_gpio_set_direction(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_dir direction) { struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip); uint32_t exceptions = 0; uint32_t mode = 0; assert(gpio_pin < bank->ngpios); if (direction == GPIO_DIR_IN) mode = GPIO_MODE_INPUT; else mode = GPIO_MODE_OUTPUT; if (clk_enable(bank->clock)) panic(); exceptions = cpu_spin_lock_xsave(&gpio_lock); io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, SHIFT_U32(GPIO_MODE_MASK, gpio_pin << 1), SHIFT_U32(mode, gpio_pin << 1)); cpu_spin_unlock_xrestore(&gpio_lock, exceptions); clk_disable(bank->clock); } static void stm32_gpio_put_gpio(struct gpio_chip *chip __maybe_unused, struct gpio *gpio) { assert(is_stm32_gpio_chip(chip)); free(gpio); } static const struct gpio_ops stm32_gpio_ops = { .get_direction = stm32_gpio_get_direction, .set_direction = stm32_gpio_set_direction, .get_value = stm32_gpio_get_level, .set_value = stm32_gpio_set_level, .put = stm32_gpio_put_gpio, }; static bool __maybe_unused is_stm32_gpio_chip(struct gpio_chip *chip) { return chip && chip->ops == &stm32_gpio_ops; } static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id) { struct stm32_gpio_bank *bank = NULL; STAILQ_FOREACH(bank, &bank_list, link) if (bank_id == bank->bank_id) return bank; panic(); } /* Save to output @cfg the current GPIO (@bank_id/@pin) configuration */ static void __maybe_unused get_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) { struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); if (clk_enable(bank->clock)) panic(); /* * Save GPIO configuration bits spread over the few bank registers. * 1bit fields are accessed at bit position being the pin index. * 2bit fields are accessed at bit position being twice the pin index. * 4bit fields are accessed at bit position being fourth the pin index * but accessed from 2 32bit registers at incremental addresses. */ cfg->mode = (io_read32(bank->base + GPIO_MODER_OFFSET) >> (pin << 1)) & GPIO_MODE_MASK; cfg->otype = (io_read32(bank->base + GPIO_OTYPER_OFFSET) >> pin) & 1; cfg->ospeed = (io_read32(bank->base + GPIO_OSPEEDR_OFFSET) >> (pin << 1)) & GPIO_OSPEED_MASK; cfg->pupd = (io_read32(bank->base + GPIO_PUPDR_OFFSET) >> (pin << 1)) & GPIO_PUPD_PULL_MASK; cfg->od = (io_read32(bank->base + GPIO_ODR_OFFSET) >> (pin << 1)) & 1; if (pin < GPIO_ALT_LOWER_LIMIT) cfg->af = (io_read32(bank->base + GPIO_AFRL_OFFSET) >> (pin << 2)) & GPIO_ALTERNATE_MASK; else cfg->af = (io_read32(bank->base + GPIO_AFRH_OFFSET) >> ((pin - GPIO_ALT_LOWER_LIMIT) << 2)) & GPIO_ALTERNATE_MASK; clk_disable(bank->clock); } /* Apply GPIO (@bank/@pin) configuration described by @cfg */ static void set_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg) { struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); uint32_t exceptions = 0; if (clk_enable(bank->clock)) panic(); exceptions = cpu_spin_lock_xsave(&gpio_lock); /* Load GPIO MODE value, 2bit value shifted by twice the pin number */ io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, SHIFT_U32(GPIO_MODE_MASK, pin << 1), SHIFT_U32(cfg->mode, pin << 1)); /* Load GPIO Output TYPE value, 1bit shifted by pin number value */ io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, BIT(pin), SHIFT_U32(cfg->otype, pin)); /* Load GPIO Output Speed confguration, 2bit value */ io_clrsetbits32(bank->base + GPIO_OSPEEDR_OFFSET, SHIFT_U32(GPIO_OSPEED_MASK, pin << 1), SHIFT_U32(cfg->ospeed, pin << 1)); /* Load GPIO pull configuration, 2bit value */ io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, BIT(pin), SHIFT_U32(cfg->pupd, pin << 1)); /* Load pin mux Alternate Function configuration, 4bit value */ if (pin < GPIO_ALT_LOWER_LIMIT) { io_clrsetbits32(bank->base + GPIO_AFRL_OFFSET, SHIFT_U32(GPIO_ALTERNATE_MASK, pin << 2), SHIFT_U32(cfg->af, pin << 2)); } else { size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; io_clrsetbits32(bank->base + GPIO_AFRH_OFFSET, SHIFT_U32(GPIO_ALTERNATE_MASK, shift), SHIFT_U32(cfg->af, shift)); } /* Load GPIO Output direction confuguration, 1bit */ io_clrsetbits32(bank->base + GPIO_ODR_OFFSET, BIT(pin), cfg->od << pin); cpu_spin_unlock_xrestore(&gpio_lock, exceptions); clk_disable(bank->clock); } /* Count pins described in the DT node and get related data if possible */ static int get_pinctrl_from_fdt(const void *fdt, int node, struct stm32_pinctrl *pinctrl, size_t count) { const fdt32_t *cuint = NULL; const fdt32_t *slewrate = NULL; int len = 0; uint32_t i = 0; uint32_t speed = GPIO_OSPEED_LOW; uint32_t pull = GPIO_PUPD_NO_PULL; size_t found = 0; cuint = fdt_getprop(fdt, node, "pinmux", &len); if (!cuint) return -FDT_ERR_NOTFOUND; slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); if (slewrate) speed = fdt32_to_cpu(*slewrate); if (fdt_getprop(fdt, node, "bias-pull-up", NULL)) pull = GPIO_PUPD_PULL_UP; if (fdt_getprop(fdt, node, "bias-pull-down", NULL)) pull = GPIO_PUPD_PULL_DOWN; for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { uint32_t pincfg = 0; uint32_t bank = 0; uint32_t pin = 0; uint32_t mode = 0; uint32_t alternate = 0; uint32_t odata = 0; bool opendrain = false; pincfg = fdt32_to_cpu(*cuint); cuint++; bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; mode = pincfg & DT_GPIO_MODE_MASK; switch (mode) { case 0: mode = GPIO_MODE_INPUT; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: alternate = mode - 1U; mode = GPIO_MODE_ALTERNATE; break; case 17: mode = GPIO_MODE_ANALOG; break; default: mode = GPIO_MODE_OUTPUT; break; } if (fdt_getprop(fdt, node, "drive-open-drain", NULL)) opendrain = true; if (fdt_getprop(fdt, node, "output-high", NULL) && mode == GPIO_MODE_INPUT) { mode = GPIO_MODE_OUTPUT; odata = 1; } if (fdt_getprop(fdt, node, "output-low", NULL) && mode == GPIO_MODE_INPUT) { mode = GPIO_MODE_OUTPUT; odata = 0; } if (found < count) { struct stm32_pinctrl *ref = &pinctrl[found]; ref->bank = (uint8_t)bank; ref->pin = (uint8_t)pin; ref->cfg.mode = mode; if (opendrain) ref->cfg.otype = GPIO_OTYPE_OPEN_DRAIN; else ref->cfg.otype = GPIO_OTYPE_PUSH_PULL; ref->cfg.ospeed = speed; ref->cfg.pupd = pull; ref->cfg.od = odata; ref->cfg.af = alternate; } found++; } return (int)found; } static TEE_Result stm32_gpio_get_dt(struct dt_pargs *pargs, void *data, struct gpio **out_gpio) { TEE_Result res = TEE_ERROR_GENERIC; struct stm32_gpio_bank *bank = data; struct gpio *gpio = NULL; unsigned int shift_1b = 0; unsigned int shift_2b = 0; uint32_t exceptions = 0; uint32_t otype = 0; uint32_t pupd = 0; uint32_t mode = 0; res = gpio_dt_alloc_pin(pargs, &gpio); if (res) return res; if (gpio->pin >= bank->ngpios) { DMSG("Invalid GPIO reference"); free(gpio); return TEE_ERROR_GENERIC; } shift_1b = gpio->pin; shift_2b = SHIFT_U32(gpio->pin, 1); if (gpio->dt_flags & GPIO_PULL_UP) pupd = GPIO_PUPD_PULL_UP; else if (gpio->dt_flags & GPIO_PULL_DOWN) pupd = GPIO_PUPD_PULL_DOWN; else pupd = GPIO_PUPD_NO_PULL; if (gpio->dt_flags & GPIO_LINE_OPEN_DRAIN) otype = GPIO_OTYPE_OPEN_DRAIN; else otype = GPIO_OTYPE_PUSH_PULL; if (clk_enable(bank->clock)) panic(); exceptions = cpu_spin_lock_xsave(&gpio_lock); io_clrsetbits32(bank->base + GPIO_MODER_OFFSET, SHIFT_U32(GPIO_MODE_MASK, shift_2b), SHIFT_U32(mode, shift_2b)); io_clrsetbits32(bank->base + GPIO_OTYPER_OFFSET, SHIFT_U32(GPIO_OTYPE_OPEN_DRAIN, shift_1b), SHIFT_U32(otype, shift_1b)); io_clrsetbits32(bank->base + GPIO_PUPDR_OFFSET, SHIFT_U32(GPIO_PUPD_PULL_MASK, shift_2b), SHIFT_U32(pupd, shift_2b)); cpu_spin_unlock_xrestore(&gpio_lock, exceptions); clk_disable(bank->clock); gpio->chip = &bank->gpio_chip; *out_gpio = gpio; return TEE_SUCCESS; } /* Get bank ID from bank node property st,bank-name or panic on failure */ static unsigned int dt_get_bank_id(const void *fdt, int node) { const int dt_name_len = strlen(DT_GPIO_BANK_NAME0); const fdt32_t *cuint = NULL; int len = 0; /* Parse "st,bank-name" to get its id (eg: GPIOA -> 0) */ cuint = fdt_getprop(fdt, node, "st,bank-name", &len); if (!cuint || (len != dt_name_len + 1)) panic("Missing/wrong st,bank-name property"); if (strncmp((const char *)cuint, DT_GPIO_BANK_NAME0, dt_name_len - 1) || strcmp((const char *)cuint, DT_GPIO_BANK_NAME0) < 0) panic("Wrong st,bank-name property"); return (unsigned int)strcmp((const char *)cuint, DT_GPIO_BANK_NAME0); } /* * Return whether or not the GPIO bank related to a DT node is already * registered in the GPIO bank link. */ static bool bank_is_registered(const void *fdt, int node) { unsigned int bank_id = dt_get_bank_id(fdt, node); struct stm32_gpio_bank *bank = NULL; STAILQ_FOREACH(bank, &bank_list, link) if (bank->bank_id == bank_id) return true; return false; } /* Get GPIO bank information from the DT */ static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node, const void *compat_data, int range_offset, struct stm32_gpio_bank **out_bank) { const struct bank_compat *compat = compat_data; TEE_Result res = TEE_ERROR_GENERIC; struct stm32_gpio_bank *bank = NULL; const fdt32_t *cuint = NULL; struct io_pa_va pa_va = { }; struct clk *clk = NULL; size_t blen = 0; paddr_t pa = 0; int len = 0; int i = 0; assert(out_bank); /* Probe deferrable devices first */ res = clk_dt_get_by_index(fdt, node, 0, &clk); if (res) return res; bank = calloc(1, sizeof(*bank)); if (!bank) return TEE_ERROR_OUT_OF_MEMORY; /* * Do not rely *only* on the "reg" property to get the address, * but consider also the "ranges" translation property */ pa = fdt_reg_base_address(fdt, node); if (pa == DT_INFO_INVALID_REG) panic("missing reg property"); pa_va.pa = pa + range_offset; blen = fdt_reg_size(fdt, node); if (blen == DT_INFO_INVALID_REG_SIZE) panic("missing reg size property"); DMSG("Bank name %s", fdt_get_name(fdt, node, NULL)); bank->bank_id = dt_get_bank_id(fdt, node); bank->clock = clk; bank->gpio_chip.ops = &stm32_gpio_ops; bank->sec_support = compat->secure_control; if (bank->sec_support) bank->base = io_pa_or_va_secure(&pa_va, blen); else bank->base = io_pa_or_va_nsec(&pa_va, blen); assert(bank->base); /* Parse gpio-ranges with its 4 parameters */ cuint = fdt_getprop(fdt, node, "gpio-ranges", &len); len /= sizeof(*cuint); if (len % 4) panic("wrong gpio-ranges syntax"); /* Get the last defined gpio line (offset + nb of pins) */ for (i = 0; i < len / 4; i++) { bank->ngpios = MAX(bank->ngpios, (unsigned int)(fdt32_to_cpu(*(cuint + 1)) + fdt32_to_cpu(*(cuint + 3)))); cuint += 4; } if (compat->gpioz) stm32mp_register_gpioz_pin_count(bank->ngpios); *out_bank = bank; return TEE_SUCCESS; } static void set_bank_gpio_non_secure(struct stm32_gpio_bank *bank) { unsigned int pin = 0; for (pin = 0; pin < bank->ngpios; pin++) stm32_gpio_set_secure_cfg(bank->bank_id, pin, false); } /* Parse a pinctrl node to register and configure the GPIO banks it describes */ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node, const void *compat_data) { TEE_Result res = TEE_SUCCESS; const fdt32_t *cuint = NULL; int range_offs = 0; int b_node = 0; int len = 0; /* Read the ranges property (for regs memory translation) */ cuint = fdt_getprop(fdt, node, "ranges", &len); if (!cuint) panic("missing ranges property"); len /= sizeof(*cuint); if (len == 3) range_offs = fdt32_to_cpu(*(cuint + 1)) - fdt32_to_cpu(*cuint); fdt_for_each_subnode(b_node, fdt, node) { cuint = fdt_getprop(fdt, b_node, "gpio-controller", &len); if (cuint) { /* * We found a property "gpio-controller" in the node: * the node is a GPIO bank description, add it to the * bank list. */ struct stm32_gpio_bank *bank = NULL; if (fdt_get_status(fdt, b_node) == DT_STATUS_DISABLED || bank_is_registered(fdt, b_node)) continue; res = dt_stm32_gpio_bank(fdt, b_node, compat_data, range_offs, &bank); if (res) return res; /* Registering a provider should not defer probe */ res = gpio_register_provider(fdt, b_node, stm32_gpio_get_dt, bank); if (res) panic(); STAILQ_INSERT_TAIL(&bank_list, bank, link); DMSG("Registered GPIO bank %c (%d pins) @%#"PRIxVA, bank->bank_id + 'A', bank->ngpios, bank->base); assert(bank->ngpios <= GPIO_PIN_MAX + 1); if (bank->sec_support) { uint32_t seccfgr = 0; unsigned int i = 0; int lenp = 0; cuint = fdt_getprop(fdt, b_node, "st,protreg", &lenp); if (!cuint) { set_bank_gpio_non_secure(bank); continue; } seccfgr = fdt32_to_cpu(*cuint); for (i = 0; i < bank->ngpios; i++) stm32_gpio_set_secure_cfg(bank->bank_id, i, seccfgr & TZPROT(i)); } } else { if (len != -FDT_ERR_NOTFOUND) panic(); } } return TEE_SUCCESS; } void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin, bool secure) { struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id); uint32_t exceptions = 0; if (clk_enable(bank->clock)) panic(); exceptions = cpu_spin_lock_xsave(&gpio_lock); if (secure) io_setbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); else io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin)); FMSG("Set secure GPIO: bank %c pin %u", bank->bank_id + 'A', pin); cpu_spin_unlock_xrestore(&gpio_lock, exceptions); clk_disable(bank->clock); } #ifdef CFG_DRIVERS_PINCTRL static TEE_Result stm32_pinctrl_conf_apply(struct pinconf *conf) { struct stm32_pinctrl_array *ref = conf->priv; struct stm32_pinctrl *p = ref->pinctrl; size_t pin_count = ref->count; size_t n = 0; for (n = 0; n < pin_count; n++) set_gpio_cfg(p[n].bank, p[n].pin, &p[n].cfg); return TEE_SUCCESS; } static void stm32_pinctrl_conf_free(struct pinconf *conf) { free(conf); } static const struct pinctrl_ops stm32_pinctrl_ops = { .conf_apply = stm32_pinctrl_conf_apply, .conf_free = stm32_pinctrl_conf_free, }; DECLARE_KEEP_PAGER(stm32_pinctrl_ops); void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, unsigned int *bank, unsigned int *pin, unsigned int *count) { size_t conf_index = 0; size_t pin_count = 0; size_t n = 0; assert(count); if (!pinctrl) goto out; for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { struct pinconf *pinconf = pinctrl->confs[conf_index]; struct stm32_pinctrl_array *ref = pinconf->priv; /* Consider only the stm32_gpio pins */ if (pinconf->ops != &stm32_pinctrl_ops) continue; if (bank || pin) { for (n = 0; n < ref->count; n++) { if (bank && pin_count < *count) bank[pin_count] = ref->pinctrl[n].bank; if (pin && pin_count < *count) pin[pin_count] = ref->pinctrl[n].pin; pin_count++; } } else { pin_count += ref->count; } } out: *count = pin_count; } void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure) { size_t conf_index = 0; if (!pinctrl) return; for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) { struct pinconf *pinconf = pinctrl->confs[conf_index]; struct stm32_pinctrl_array *ref = pinconf->priv; struct stm32_pinctrl *pc = NULL; size_t n = 0; for (n = 0; n < ref->count; n++) { if (pinconf->ops != &stm32_pinctrl_ops) continue; pc = ref->pinctrl + n; stm32_gpio_set_secure_cfg(pc->bank, pc->pin, secure); } } } /* Allocate and return a pinctrl configuration from a DT reference */ static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs, void *data __unused, struct pinconf **out_pinconf) { struct conf { struct pinconf pinconf; struct stm32_pinctrl_array array_ref; } *loc_conf = NULL; struct stm32_pinctrl *pinctrl = NULL; struct pinconf *pinconf = NULL; const void *fdt = NULL; size_t pin_count = 0; int pinctrl_node = 0; int pinmux_node = 0; int count = 0; pinctrl_node = pargs->phandle_node; fdt = pargs->fdt; assert(fdt && pinctrl_node); fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { if (fdt_getprop(fdt, pinmux_node, "pinmux", &count)) pin_count += (size_t)count / sizeof(uint32_t); else if (count != -FDT_ERR_NOTFOUND) panic(); } loc_conf = calloc(1, sizeof(*loc_conf) + sizeof(*pinctrl) * pin_count); if (!loc_conf) return TEE_ERROR_OUT_OF_MEMORY; pinconf = &loc_conf->pinconf; pinconf->ops = &stm32_pinctrl_ops; pinconf->priv = &loc_conf->array_ref; loc_conf->array_ref.count = pin_count; pinctrl = loc_conf->array_ref.pinctrl; count = 0; fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) { int found = 0; found = get_pinctrl_from_fdt(fdt, pinmux_node, pinctrl + count, pin_count - count); if (found <= 0 && found > ((int)pin_count - count)) { /* We can't recover from an error here so let's panic */ panic(); } count += found; } *out_pinconf = pinconf; return TEE_SUCCESS; } #endif /*CFG_DRIVERS_PINCTRL*/ static TEE_Result stm32_pinctrl_probe(const void *fdt, int node, const void *compat_data) { TEE_Result res = TEE_ERROR_GENERIC; /* Register GPIO banks described in this pin control node */ res = dt_stm32_gpio_pinctrl(fdt, node, compat_data); if (res) return res; #ifdef CFG_DRIVERS_PINCTRL res = pinctrl_register_provider(fdt, node, stm32_pinctrl_dt_get, (void *)compat_data); if (res) return res; #endif return TEE_SUCCESS; } static const struct dt_device_match stm32_pinctrl_match_table[] = { { .compatible = "st,stm32mp135-pinctrl", .compat_data = &(struct bank_compat){ .secure_control = true, }, }, { .compatible = "st,stm32mp157-pinctrl", .compat_data = &(struct bank_compat){ .secure_control = false, }, }, { .compatible = "st,stm32mp157-z-pinctrl", .compat_data = &(struct bank_compat){ .gpioz = true, .secure_control = true, }, }, { } }; DEFINE_DT_DRIVER(stm32_pinctrl_dt_driver) = { .name = "stm32_gpio-pinctrl", .type = DT_DRIVER_PINCTRL, .match_table = stm32_pinctrl_match_table, .probe = stm32_pinctrl_probe, }; optee_os-4.3.0/core/drivers/stm32_hpdma.c000066400000000000000000000217331464416617300202500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define _HPDMA_SECCFGR U(0x000) #define _HPDMA_PRIVCFGR U(0x004) #define _HPDMA_RCFGLOCKR U(0x008) #define _HPDMA_CIDCFGR(x) (U(0x054) + U(0x080) * (x)) #define _HPDMA_SEMCR(x) (U(0x058) + U(0x080) * (x)) /* * CFGR register bitfields */ #define _HPDMA_CFGR_ENABLE BIT(31) /* * CIDCFGR register bitfields */ #define _HPDMA_CIDCFGR_SEMWL_MASK GENMASK_32(23, 16) #define _HPDMA_CIDCFGR_SCID_MASK GENMASK_32(5, 4) #define _HPDMA_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ _CIDCFGR_SEMEN | \ _HPDMA_CIDCFGR_SCID_MASK |\ _HPDMA_CIDCFGR_SEMWL_MASK) /* * PRIVCFGR register bitfields */ #define _HPDMA_PRIVCFGR_MASK GENMASK_32(15, 0) /* * RCFGLOCKR register bitfields */ #define _HPDMA_RCFGLOCKR_MASK GENMASK_32(15, 0) /* * SECCFGR register bitfields */ #define _HPDMA_SECCFGR_EN BIT(0) #define _HPDMA_SECCFGR_MASK GENMASK_32(15, 0) /* * SEMCR register bitfields */ #define _HPDMA_SEMCR_SCID_MASK GENMASK_32(5, 4) #define _HPDMA_SEMCR_SCID_SHIFT U(4) /* * Miscellaneous */ #define HPDMA_RIF_CHANNELS U(16) #define HPDMA_NB_MAX_CID_SUPPORTED U(3) struct hpdma_pdata { struct clk *hpdma_clock; struct rif_conf_data conf_data; unsigned int nb_channels; vaddr_t base; SLIST_ENTRY(hpdma_pdata) link; }; static SLIST_HEAD(, hpdma_pdata) hpdma_list = SLIST_HEAD_INITIALIZER(hpdma_list); /* This function expects HPDMA bus clock is enabled */ static TEE_Result apply_rif_config(struct hpdma_pdata *hpdma_d, bool is_tdcid) { TEE_Result res = TEE_ERROR_ACCESS_DENIED; uint32_t cidcfgr = 0; unsigned int i = 0; for (i = 0; i < HPDMA_RIF_CHANNELS; i++) { if (!(BIT(i) & hpdma_d->conf_data.access_mask[0])) continue; /* * When TDCID, OP-TEE should be the one to set the CID filtering * configuration. Clearing previous configuration prevents * undesired events during the only legitimate configuration. */ if (is_tdcid) io_clrbits32(hpdma_d->base + _HPDMA_CIDCFGR(i), _HPDMA_CIDCFGR_CONF_MASK); cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i)); /* Check if the channel is in semaphore mode */ if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1)) continue; /* If not TDCID, we want to acquire semaphores assigned to us */ res = stm32_rif_acquire_semaphore(hpdma_d->base + _HPDMA_SEMCR(i), HPDMA_NB_MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't acquire semaphore for channel %u", i); return res; } } /* Security and privilege RIF configuration */ io_clrsetbits32(hpdma_d->base + _HPDMA_PRIVCFGR, _HPDMA_PRIVCFGR_MASK & hpdma_d->conf_data.access_mask[0], hpdma_d->conf_data.priv_conf[0]); io_clrsetbits32(hpdma_d->base + _HPDMA_SECCFGR, _HPDMA_SECCFGR_MASK & hpdma_d->conf_data.access_mask[0], hpdma_d->conf_data.sec_conf[0]); /* Skip CID/semaphore configuration if not in TDCID state. */ if (!is_tdcid) goto end; for (i = 0; i < HPDMA_RIF_CHANNELS; i++) { if (!(BIT(i) & hpdma_d->conf_data.access_mask[0])) continue; io_clrsetbits32(hpdma_d->base + _HPDMA_CIDCFGR(i), _HPDMA_CIDCFGR_CONF_MASK, hpdma_d->conf_data.cid_confs[i]); cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i)); /* * Take semaphore if the resource is in semaphore * mode and secured. */ if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) || !(io_read32(hpdma_d->base + _HPDMA_SECCFGR) & BIT(i))) { res = stm32_rif_release_semaphore(hpdma_d->base + _HPDMA_SEMCR(i), HPDMA_NB_MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't release semaphore for res%u", i); return TEE_ERROR_ACCESS_DENIED; } } else { res = stm32_rif_acquire_semaphore(hpdma_d->base + _HPDMA_SEMCR(i), HPDMA_NB_MAX_CID_SUPPORTED); if (res) { EMSG("Couldn't acquire semaphore for res%u", i); return TEE_ERROR_ACCESS_DENIED; } } } /* * Lock RIF configuration if configured. This cannot be undone until * next reset. */ io_clrsetbits32(hpdma_d->base + _HPDMA_RCFGLOCKR, _HPDMA_RCFGLOCKR_MASK, hpdma_d->conf_data.lock_conf[0]); end: if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) { /* Check that RIF config are applied, panic otherwise */ if ((io_read32(hpdma_d->base + _HPDMA_PRIVCFGR) & hpdma_d->conf_data.access_mask[0]) != hpdma_d->conf_data.priv_conf[0]) panic("HPDMA channel priv conf is incorrect"); if ((io_read32(hpdma_d->base + _HPDMA_SECCFGR) & hpdma_d->conf_data.access_mask[0]) != hpdma_d->conf_data.sec_conf[0]) panic("HPDMA channel sec conf is incorrect"); } return TEE_SUCCESS; } static TEE_Result parse_dt(const void *fdt, int node, struct hpdma_pdata *hpdma_d) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int i = 0; int lenp = 0; const fdt32_t *cuint = NULL; struct dt_node_info info = { }; struct io_pa_va addr = { }; fdt_fill_device_info(fdt, &info, node); assert(info.reg != DT_INFO_INVALID_REG && info.reg_size != DT_INFO_INVALID_REG_SIZE); addr.pa = info.reg; hpdma_d->base = io_pa_or_va_secure(&addr, info.reg_size); /* Gate the IP */ res = clk_dt_get_by_index(fdt, node, 0, &hpdma_d->hpdma_clock); if (res) return res; cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); if (!cuint) panic("No RIF configuration available"); hpdma_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t)); assert(hpdma_d->nb_channels <= HPDMA_RIF_CHANNELS); hpdma_d->conf_data.cid_confs = calloc(HPDMA_RIF_CHANNELS, sizeof(uint32_t)); hpdma_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t)); hpdma_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t)); hpdma_d->conf_data.access_mask = calloc(1, sizeof(uint32_t)); hpdma_d->conf_data.lock_conf = calloc(1, sizeof(uint32_t)); assert(hpdma_d->conf_data.cid_confs && hpdma_d->conf_data.sec_conf && hpdma_d->conf_data.priv_conf && hpdma_d->conf_data.access_mask && hpdma_d->conf_data.lock_conf); for (i = 0; i < hpdma_d->nb_channels; i++) stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), &hpdma_d->conf_data, HPDMA_NB_MAX_CID_SUPPORTED, HPDMA_RIF_CHANNELS); return TEE_SUCCESS; } static void stm32_hpdma_pm_resume(struct hpdma_pdata *hpdma) { if (apply_rif_config(hpdma, true)) panic("Failed to resume HPDMA"); } static void stm32_hpdma_pm_suspend(struct hpdma_pdata *hpdma) { size_t i = 0; for (i = 0; i < HPDMA_RIF_CHANNELS; i++) hpdma->conf_data.cid_confs[i] = io_read32(hpdma->base + _HPDMA_CIDCFGR(i)) & _HPDMA_CIDCFGR_CONF_MASK; hpdma->conf_data.priv_conf[0] = io_read32(hpdma->base + _HPDMA_PRIVCFGR) & _HPDMA_PRIVCFGR_MASK; hpdma->conf_data.sec_conf[0] = io_read32(hpdma->base + _HPDMA_SECCFGR) & _HPDMA_SECCFGR_MASK; hpdma->conf_data.lock_conf[0] = io_read32(hpdma->base + _HPDMA_RCFGLOCKR) & _HPDMA_RCFGLOCKR_MASK; /* * The access mask is modified to restore the conf for all * resources. */ hpdma->conf_data.access_mask[0] = GENMASK_32(HPDMA_RIF_CHANNELS - 1, 0); } static TEE_Result stm32_hpdma_pm(enum pm_op op, unsigned int pm_hint, const struct pm_callback_handle *pm_handle) { struct hpdma_pdata *hpdma = pm_handle->handle; TEE_Result res = TEE_ERROR_GENERIC; bool is_tdcid = false; res = stm32_rifsc_check_tdcid(&is_tdcid); if (res) panic(); if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid) return TEE_SUCCESS; res = clk_enable(hpdma->hpdma_clock); if (res) return res; if (op == PM_OP_RESUME) stm32_hpdma_pm_resume(hpdma); else stm32_hpdma_pm_suspend(hpdma); clk_disable(hpdma->hpdma_clock); return TEE_SUCCESS; } static TEE_Result stm32_hpdma_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct hpdma_pdata *hpdma_d = NULL; bool is_tdcid = false; res = stm32_rifsc_check_tdcid(&is_tdcid); if (res) return res; hpdma_d = calloc(1, sizeof(*hpdma_d)); if (!hpdma_d) return TEE_ERROR_OUT_OF_MEMORY; res = parse_dt(fdt, node, hpdma_d); if (res) { free(hpdma_d); return res; } if (clk_enable(hpdma_d->hpdma_clock)) panic("Cannot access hpdma clock"); res = apply_rif_config(hpdma_d, is_tdcid); if (res) panic("Failed to apply RIF config"); clk_disable(hpdma_d->hpdma_clock); SLIST_INSERT_HEAD(&hpdma_list, hpdma_d, link); register_pm_core_service_cb(stm32_hpdma_pm, hpdma_d, "stm32-hpdma"); return TEE_SUCCESS; } static const struct dt_device_match stm32_hpdma_match_table[] = { { .compatible = "st,stm32-dma3" }, { } }; DEFINE_DT_DRIVER(stm32_hpdma_dt_driver) = { .name = "st,stm32-hpdma", .match_table = stm32_hpdma_match_table, .probe = stm32_hpdma_probe, }; optee_os-4.3.0/core/drivers/stm32_hsem.c000066400000000000000000000162431464416617300201130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define HSEM_SECCFGR U(0x200) #define HSEM_PRIVCFGR U(0x210) #define HSEM_CnCIDCFGR(x) (U(0x220) + U(0x004) * ((x) - 1)) #define HSEM_GpCIDCFGR(x) (U(0x240) + U(0x004) * (x)) /* * CnCIDCFGR register bitfields */ #define HSEM_CnCIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ HSEM_CnCIDCFGR_SCID_MASK) #define HSEM_CnCIDCFGR_SCID_MASK GENMASK_32(6, 4) /* * GpCIDCFGR register bitfields */ #define HSEM_GpCIDCFGR_SEM_WLIST_C_MASK GENMASK_32(18, 16) #define HSEM_GpCIDCFGR_SEM_WLIST_SHIFT U(16) #define HSEM_GpCIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ HSEM_GpCIDCFGR_SEM_WLIST_C_MASK) /* * PRIVCFGR register bitfields */ #define HSEM_PRIVCFGR_MASK GENMASK_32(15, 0) /* * SECCFGR register bitfields */ #define HSEM_SECCFGR_MASK GENMASK_32(15, 0) /* * Miscellaneous */ #define HSEM_NB_PROC U(3) #define HSEM_NB_SEM_GROUPS U(4) #define HSEM_NB_SEM_PER_GROUP U(4) #define HSEM_NB_MAX_CID_SUPPORTED U(7) #define HSEM_RIF_RESOURCES U(16) struct hsem_pdata { struct clk *hsem_clock; struct rif_conf_data conf_data; unsigned int nb_channels; vaddr_t base; uint32_t *rif_proc_conf; }; static struct hsem_pdata *hsem_d; static void apply_rif_config(bool is_tdcid) { unsigned int i = 0; unsigned int j = 0; uint32_t prev_cid_value = 0; /* * When TDCID, OP-TEE should be the one to set the CID filtering * configuration. Clearing previous configuration prevents * undesired events during the only legitimate configuration. */ if (is_tdcid) { for (i = 0; i < HSEM_NB_PROC; i++) io_clrbits32(hsem_d->base + HSEM_CnCIDCFGR(i + 1), HSEM_CnCIDCFGR_CONF_MASK); /* Clean HSEM groups configuration registers */ for (i = 0; i < HSEM_NB_SEM_GROUPS; i++) io_clrbits32(hsem_d->base + HSEM_GpCIDCFGR(i), HSEM_GpCIDCFGR_CONF_MASK); } /* Security and privilege RIF configuration */ io_clrsetbits32(hsem_d->base + HSEM_SECCFGR, HSEM_SECCFGR_MASK & hsem_d->conf_data.access_mask[0], hsem_d->conf_data.sec_conf[0]); io_clrsetbits32(hsem_d->base + HSEM_PRIVCFGR, HSEM_PRIVCFGR_MASK & hsem_d->conf_data.access_mask[0], hsem_d->conf_data.priv_conf[0]); if (!is_tdcid) return; /* Configure HSEM processors configuration registers */ for (i = 0; i < HSEM_NB_PROC; i++) { /* * If a processor CID configuration is present, enable it. * Else, nothing to do. */ if (!hsem_d->rif_proc_conf[i]) continue; io_clrsetbits32(hsem_d->base + HSEM_CnCIDCFGR(i + 1), HSEM_CnCIDCFGR_CONF_MASK, _CIDCFGR_CFEN | hsem_d->rif_proc_conf[i]); } /* * Configure HSEM groups configuration registers * If one semaphore is configured, all semaphores of its group * must be configured too and MUST have the same RIF * configuration. */ for (i = 0; i < HSEM_NB_SEM_GROUPS; i++) { unsigned int hsem_idx = i * HSEM_NB_SEM_PER_GROUP; unsigned int hsem_cid = 0; unsigned int known_cid_idx = 0; prev_cid_value = hsem_d->conf_data.cid_confs[hsem_idx]; /* If CID filtering is disabled, do nothing */ if (!(prev_cid_value & _CIDCFGR_CFEN)) continue; /* * Check if configured CID corresponds to a processor's * CID in HSEM_CnCIDCFGR. */ for (j = 0; j < HSEM_NB_PROC; j++) { uint32_t proc_cid = hsem_d->rif_proc_conf[j]; hsem_cid = (prev_cid_value & HSEM_CnCIDCFGR_SCID_MASK); DMSG("hsem_cid %u", hsem_cid); DMSG("proc_cid %u", proc_cid); if (proc_cid == hsem_cid) { known_cid_idx = BIT(j + HSEM_GpCIDCFGR_SEM_WLIST_SHIFT); break; } } if (!known_cid_idx) panic("Unknown HSEM processor CID"); /* * HSEM resources in the same group must have the same CID * filtering configuration. Else it is inconsistent. */ for (j = 0; j < HSEM_NB_SEM_PER_GROUP; j++) if (hsem_d->conf_data.cid_confs[j + hsem_idx] != prev_cid_value) panic("Inconsistent HSEM RIF group config"); io_clrsetbits32(hsem_d->base + HSEM_GpCIDCFGR(i), HSEM_GpCIDCFGR_CONF_MASK, _CIDCFGR_CFEN | known_cid_idx); } } static TEE_Result parse_dt(const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int i = 0; int lenp = 0; const fdt32_t *cuint = NULL; struct dt_node_info info = { }; struct io_pa_va addr = { }; fdt_fill_device_info(fdt, &info, node); assert(info.reg != DT_INFO_INVALID_REG && info.reg_size != DT_INFO_INVALID_REG_SIZE); addr.pa = info.reg; hsem_d->base = io_pa_or_va_secure(&addr, info.reg_size); /* Gate the IP */ res = clk_dt_get_by_index(fdt, node, 0, &hsem_d->hsem_clock); if (res) return res; cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); if (!cuint) panic("No RIF configuration available"); hsem_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t)); assert(hsem_d->nb_channels <= HSEM_RIF_RESOURCES); hsem_d->rif_proc_conf = calloc(HSEM_NB_PROC, sizeof(uint32_t)); assert(hsem_d->rif_proc_conf); hsem_d->conf_data.cid_confs = calloc(HSEM_RIF_RESOURCES, sizeof(uint32_t)); hsem_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t)); hsem_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t)); hsem_d->conf_data.access_mask = calloc(1, sizeof(uint32_t)); assert(hsem_d->conf_data.cid_confs && hsem_d->conf_data.sec_conf && hsem_d->conf_data.priv_conf && hsem_d->conf_data.access_mask); for (i = 0; i < hsem_d->nb_channels; i++) stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), &hsem_d->conf_data, HSEM_NB_MAX_CID_SUPPORTED, HSEM_RIF_RESOURCES); cuint = fdt_getprop(fdt, node, "st,proccid", &lenp); if (!cuint) panic("No RIF proc configuration available"); lenp = (unsigned int)(lenp / sizeof(uint32_t)); /* * There should be maximum (HSEM_NB_PROC * 2) property argument. * First argument for a processor is its number, the second is its CID. */ assert((unsigned int)lenp <= (HSEM_NB_PROC * 2)); for (i = 0; i < (unsigned int)lenp / 2; i++) { unsigned int pos = fdt32_to_cpu(cuint[i * 2]) - 1; unsigned int cid_value = fdt32_to_cpu(cuint[(i * 2) + 1]); hsem_d->rif_proc_conf[pos] = SHIFT_U32(cid_value, SCID_SHIFT); } return TEE_SUCCESS; } static TEE_Result stm32_hsem_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; bool is_tdcid = false; res = stm32_rifsc_check_tdcid(&is_tdcid); if (res) return res; hsem_d = calloc(1, sizeof(*hsem_d)); if (!hsem_d) return TEE_ERROR_OUT_OF_MEMORY; res = parse_dt(fdt, node); if (res) return res; res = clk_enable(hsem_d->hsem_clock); if (res) panic("Cannot access HSEM clock"); apply_rif_config(is_tdcid); clk_disable(hsem_d->hsem_clock); return TEE_SUCCESS; } static const struct dt_device_match stm32_hsem_match_table[] = { { .compatible = "st,stm32mp25-hsem" }, { } }; DEFINE_DT_DRIVER(stm32_hsem_dt_driver) = { .name = "st,stm32-hsem", .match_table = stm32_hsem_match_table, .probe = stm32_hsem_probe, }; optee_os-4.3.0/core/drivers/stm32_i2c.c000066400000000000000000001300471464416617300176330ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * Copyright (c) 2017-2024, STMicroelectronics * * The driver API is defined in header file stm32_i2c.h. * * I2C bus driver does not register to the PM framework. It is the * responsibility of the bus owner to call the related STM32 I2C driver * API functions when bus suspends or resumes. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* STM32 I2C registers offsets */ #define I2C_CR1 0x00U #define I2C_CR2 0x04U #define I2C_OAR1 0x08U #define I2C_OAR2 0x0CU #define I2C_TIMINGR 0x10U #define I2C_TIMEOUTR 0x14U #define I2C_ISR 0x18U #define I2C_ICR 0x1CU #define I2C_PECR 0x20U #define I2C_RXDR 0x24U #define I2C_TXDR 0x28U #define I2C_SIZE 0x2CU /* Bit definition for I2C_CR1 register */ #define I2C_CR1_PE BIT(0) #define I2C_CR1_TXIE BIT(1) #define I2C_CR1_RXIE BIT(2) #define I2C_CR1_ADDRIE BIT(3) #define I2C_CR1_NACKIE BIT(4) #define I2C_CR1_STOPIE BIT(5) #define I2C_CR1_TCIE BIT(6) #define I2C_CR1_ERRIE BIT(7) #define I2C_CR1_DNF GENMASK_32(11, 8) #define I2C_CR1_ANFOFF BIT(12) #define I2C_CR1_SWRST BIT(13) #define I2C_CR1_TXDMAEN BIT(14) #define I2C_CR1_RXDMAEN BIT(15) #define I2C_CR1_SBC BIT(16) #define I2C_CR1_NOSTRETCH BIT(17) #define I2C_CR1_WUPEN BIT(18) #define I2C_CR1_GCEN BIT(19) #define I2C_CR1_SMBHEN BIT(22) #define I2C_CR1_SMBDEN BIT(21) #define I2C_CR1_ALERTEN BIT(22) #define I2C_CR1_PECEN BIT(23) /* Bit definition for I2C_CR2 register */ #define I2C_CR2_SADD GENMASK_32(9, 0) #define I2C_CR2_RD_WRN BIT(10) #define I2C_CR2_RD_WRN_OFFSET 10U #define I2C_CR2_ADD10 BIT(11) #define I2C_CR2_HEAD10R BIT(12) #define I2C_CR2_START BIT(13) #define I2C_CR2_STOP BIT(14) #define I2C_CR2_NACK BIT(15) #define I2C_CR2_NBYTES GENMASK_32(23, 16) #define I2C_CR2_NBYTES_OFFSET 16U #define I2C_CR2_RELOAD BIT(24) #define I2C_CR2_AUTOEND BIT(25) #define I2C_CR2_PECBYTE BIT(26) /* Bit definition for I2C_OAR1 register */ #define I2C_OAR1_OA1 GENMASK_32(9, 0) #define I2C_OAR1_OA1MODE BIT(10) #define I2C_OAR1_OA1EN BIT(15) /* Bit definition for I2C_OAR2 register */ #define I2C_OAR2_OA2 GENMASK_32(7, 1) #define I2C_OAR2_OA2MSK GENMASK_32(10, 8) #define I2C_OAR2_OA2NOMASK 0 #define I2C_OAR2_OA2MASK01 BIT(8) #define I2C_OAR2_OA2MASK02 BIT(9) #define I2C_OAR2_OA2MASK03 GENMASK_32(9, 8) #define I2C_OAR2_OA2MASK04 BIT(10) #define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10)) #define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10)) #define I2C_OAR2_OA2MASK07 GENMASK_32(10, 8) #define I2C_OAR2_OA2EN BIT(15) /* Bit definition for I2C_TIMINGR register */ #define I2C_TIMINGR_SCLL GENMASK_32(7, 0) #define I2C_TIMINGR_SCLH GENMASK_32(15, 8) #define I2C_TIMINGR_SDADEL GENMASK_32(19, 16) #define I2C_TIMINGR_SCLDEL GENMASK_32(23, 20) #define I2C_TIMINGR_PRESC GENMASK_32(31, 28) #define I2C_TIMINGR_SCLL_MAX (I2C_TIMINGR_SCLL + 1) #define I2C_TIMINGR_SCLH_MAX ((I2C_TIMINGR_SCLH >> 8) + 1) #define I2C_TIMINGR_SDADEL_MAX ((I2C_TIMINGR_SDADEL >> 16) + 1) #define I2C_TIMINGR_SCLDEL_MAX ((I2C_TIMINGR_SCLDEL >> 20) + 1) #define I2C_TIMINGR_PRESC_MAX ((I2C_TIMINGR_PRESC >> 28) + 1) #define I2C_SET_TIMINGR_SCLL(n) ((n) & \ (I2C_TIMINGR_SCLL_MAX - 1)) #define I2C_SET_TIMINGR_SCLH(n) (((n) & \ (I2C_TIMINGR_SCLH_MAX - 1)) << 8) #define I2C_SET_TIMINGR_SDADEL(n) (((n) & \ (I2C_TIMINGR_SDADEL_MAX - 1)) << 16) #define I2C_SET_TIMINGR_SCLDEL(n) (((n) & \ (I2C_TIMINGR_SCLDEL_MAX - 1)) << 20) #define I2C_SET_TIMINGR_PRESC(n) (((n) & \ (I2C_TIMINGR_PRESC_MAX - 1)) << 28) /* Bit definition for I2C_TIMEOUTR register */ #define I2C_TIMEOUTR_TIMEOUTA GENMASK_32(11, 0) #define I2C_TIMEOUTR_TIDLE BIT(12) #define I2C_TIMEOUTR_TIMOUTEN BIT(15) #define I2C_TIMEOUTR_TIMEOUTB GENMASK_32(27, 16) #define I2C_TIMEOUTR_TEXTEN BIT(31) /* Bit definition for I2C_ISR register */ #define I2C_ISR_TXE BIT(0) #define I2C_ISR_TXIS BIT(1) #define I2C_ISR_RXNE BIT(2) #define I2C_ISR_ADDR BIT(3) #define I2C_ISR_NACKF BIT(4) #define I2C_ISR_STOPF BIT(5) #define I2C_ISR_TC BIT(6) #define I2C_ISR_TCR BIT(7) #define I2C_ISR_BERR BIT(8) #define I2C_ISR_ARLO BIT(9) #define I2C_ISR_OVR BIT(10) #define I2C_ISR_PECERR BIT(11) #define I2C_ISR_TIMEOUT BIT(12) #define I2C_ISR_ALERT BIT(13) #define I2C_ISR_BUSY BIT(15) #define I2C_ISR_DIR BIT(16) #define I2C_ISR_ADDCODE GENMASK_32(23, 17) /* Bit definition for I2C_ICR register */ #define I2C_ICR_ADDRCF BIT(3) #define I2C_ICR_NACKCF BIT(4) #define I2C_ICR_STOPCF BIT(5) #define I2C_ICR_BERRCF BIT(8) #define I2C_ICR_ARLOCF BIT(9) #define I2C_ICR_OVRCF BIT(10) #define I2C_ICR_PECCF BIT(11) #define I2C_ICR_TIMOUTCF BIT(12) #define I2C_ICR_ALERTCF BIT(13) /* Max data size for a single I2C transfer */ #define MAX_NBYTE_SIZE 255U #define I2C_NSEC_PER_SEC 1000000000UL #define I2C_TIMEOUT_BUSY_MS 25 #define I2C_TIMEOUT_BUSY_US (I2C_TIMEOUT_BUSY_MS * 1000) #define I2C_TIMEOUT_RXNE_MS 5 #define I2C_TIMEOUT_DEFAULT_MS 100 #define CR2_RESET_MASK (I2C_CR2_SADD | I2C_CR2_HEAD10R | \ I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ I2C_CR2_RD_WRN) #define TIMINGR_CLEAR_MASK (I2C_TIMINGR_SCLL | I2C_TIMINGR_SCLH | \ I2C_TIMINGR_SDADEL | \ I2C_TIMINGR_SCLDEL | I2C_TIMINGR_PRESC) /* * I2C transfer modes * I2C_RELOAD: Enable Reload mode * I2C_AUTOEND_MODE: Enable automatic end mode * I2C_SOFTEND_MODE: Enable software end mode */ #define I2C_RELOAD_MODE I2C_CR2_RELOAD #define I2C_AUTOEND_MODE I2C_CR2_AUTOEND #define I2C_SOFTEND_MODE 0x0 /* * Start/restart/stop I2C transfer requests. * * I2C_NO_STARTSTOP: Don't Generate stop and start condition * I2C_GENERATE_STOP: Generate stop condition (size should be set to 0) * I2C_GENERATE_START_READ: Generate Restart for read request. * I2C_GENERATE_START_WRITE: Generate Restart for write request */ #define I2C_NO_STARTSTOP 0x0 #define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) #define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ I2C_CR2_RD_WRN) #define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) /* Memory address byte sizes */ #define I2C_MEMADD_SIZE_8BIT 1 #define I2C_MEMADD_SIZE_16BIT 2 /* Effective rate cannot be lower than 80% target rate */ #define RATE_MIN(rate) (((rate) * 80U) / 100U) /* * struct i2c_spec_s - Private I2C timing specifications. * @rate: I2C bus speed (Hz) * @fall_max: Max fall time of both SDA and SCL signals (ns) * @rise_max: Max rise time of both SDA and SCL signals (ns) * @hddat_min: Min data hold time (ns) * @vddat_max: Max data valid time (ns) * @sudat_min: Min data setup time (ns) * @l_min: Min low period of the SCL clock (ns) * @h_min: Min high period of the SCL clock (ns) */ struct i2c_spec_s { uint32_t rate; uint32_t fall_max; uint32_t rise_max; uint32_t hddat_min; uint32_t vddat_max; uint32_t sudat_min; uint32_t l_min; uint32_t h_min; }; /* * struct i2c_timing_s - Private I2C output parameters. * @scldel: Data setup time * @sdadel: Data hold time * @sclh: SCL high period (master mode) * @sclh: SCL low period (master mode) * @is_saved: True if relating to a configuration candidate */ struct i2c_timing_s { uint8_t scldel; uint8_t sdadel; uint8_t sclh; uint8_t scll; bool is_saved; }; /* This table must be sorted in increasing value for field @rate */ static const struct i2c_spec_s i2c_specs[] = { /* Standard - 100KHz */ { .rate = I2C_STANDARD_RATE, .fall_max = 300, .rise_max = 1000, .hddat_min = 0, .vddat_max = 3450, .sudat_min = 250, .l_min = 4700, .h_min = 4000, }, /* Fast - 400KHz */ { .rate = I2C_FAST_RATE, .fall_max = 300, .rise_max = 300, .hddat_min = 0, .vddat_max = 900, .sudat_min = 100, .l_min = 1300, .h_min = 600, }, /* FastPlus - 1MHz */ { .rate = I2C_FAST_PLUS_RATE, .fall_max = 100, .rise_max = 120, .hddat_min = 0, .vddat_max = 450, .sudat_min = 50, .l_min = 500, .h_min = 260, }, }; /* * I2C request parameters * @dev_addr: I2C address of the target device * @mode: Communication mode, one of I2C_MODE_(MASTER|MEM) * @mem_addr: Target memory cell accessed in device (memory mode) * @mem_addr_size: Byte size of the memory cell address (memory mode) * @timeout_ms: Timeout in millisenconds for the request */ struct i2c_request { uint32_t dev_addr; enum i2c_mode_e mode; uint32_t mem_addr; uint32_t mem_addr_size; unsigned int timeout_ms; }; static vaddr_t get_base(struct i2c_handle_s *hi2c) { return io_pa_or_va_secure(&hi2c->base, hi2c->reg_size); } static void notif_i2c_timeout(struct i2c_handle_s *hi2c) { hi2c->i2c_err |= I2C_ERROR_TIMEOUT; hi2c->i2c_state = I2C_STATE_READY; } static const struct i2c_spec_s *get_specs(uint32_t rate) { size_t i = 0; for (i = 0; i < ARRAY_SIZE(i2c_specs); i++) if (rate <= i2c_specs[i].rate) return i2c_specs + i; return NULL; } static void save_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) { vaddr_t base = get_base(hi2c); clk_enable(hi2c->clock); cfg->cr1 = io_read32(base + I2C_CR1); cfg->cr2 = io_read32(base + I2C_CR2); cfg->oar1 = io_read32(base + I2C_OAR1); cfg->oar2 = io_read32(base + I2C_OAR2); cfg->timingr = io_read32(base + I2C_TIMINGR); clk_disable(hi2c->clock); } static void restore_cfg(struct i2c_handle_s *hi2c, struct i2c_cfg *cfg) { vaddr_t base = get_base(hi2c); clk_enable(hi2c->clock); io_clrbits32(base + I2C_CR1, I2C_CR1_PE); io_write32(base + I2C_TIMINGR, cfg->timingr & TIMINGR_CLEAR_MASK); io_write32(base + I2C_OAR1, cfg->oar1); io_write32(base + I2C_CR2, cfg->cr2); io_write32(base + I2C_OAR2, cfg->oar2); io_write32(base + I2C_CR1, cfg->cr1 & ~I2C_CR1_PE); io_setbits32(base + I2C_CR1, cfg->cr1 & I2C_CR1_PE); clk_disable(hi2c->clock); } static void __maybe_unused dump_cfg(struct i2c_cfg *cfg __maybe_unused) { DMSG("CR1: %#"PRIx32, cfg->cr1); DMSG("CR2: %#"PRIx32, cfg->cr2); DMSG("OAR1: %#"PRIx32, cfg->oar1); DMSG("OAR2: %#"PRIx32, cfg->oar2); DMSG("TIM: %#"PRIx32, cfg->timingr); } static void __maybe_unused dump_i2c(struct i2c_handle_s *hi2c) { vaddr_t __maybe_unused base = get_base(hi2c); clk_enable(hi2c->clock); DMSG("CR1: %#"PRIx32, io_read32(base + I2C_CR1)); DMSG("CR2: %#"PRIx32, io_read32(base + I2C_CR2)); DMSG("OAR1: %#"PRIx32, io_read32(base + I2C_OAR1)); DMSG("OAR2: %#"PRIx32, io_read32(base + I2C_OAR2)); DMSG("TIM: %#"PRIx32, io_read32(base + I2C_TIMINGR)); clk_disable(hi2c->clock); } /* * Compute the I2C device timings * * @init: Ref to the initialization configuration structure * @clock_src: I2C clock source frequency (Hz) * @timing: Pointer to the final computed timing result * Return 0 on success or a negative value */ static int i2c_compute_timing(struct stm32_i2c_init_s *init, unsigned long clock_src, uint32_t *timing) { const struct i2c_spec_s *specs = NULL; uint32_t speed_freq = 0; uint32_t i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq); uint32_t i2cclk = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, clock_src); uint32_t p_prev = I2C_TIMINGR_PRESC_MAX; uint32_t af_delay_min = 0; uint32_t af_delay_max = 0; uint32_t dnf_delay = 0; uint32_t tsync = 0; uint32_t clk_min = 0; uint32_t clk_max = 0; int clk_error_prev = 0; uint16_t p = 0; uint16_t l = 0; uint16_t a = 0; uint16_t h = 0; unsigned int sdadel_min = 0; unsigned int sdadel_max = 0; unsigned int scldel_min = 0; unsigned int delay = 0; int s = -1; struct i2c_timing_s solutions[I2C_TIMINGR_PRESC_MAX] = { 0 }; specs = get_specs(init->bus_rate); if (!specs) { DMSG("I2C speed out of bound: %"PRId32"Hz", init->bus_rate); return -1; } speed_freq = specs->rate; i2cbus = UDIV_ROUND_NEAREST(I2C_NSEC_PER_SEC, speed_freq); clk_error_prev = INT_MAX; if (init->rise_time > specs->rise_max || init->fall_time > specs->fall_max) { DMSG("I2C rise{%"PRId32">%"PRId32"}/fall{%"PRId32">%"PRId32"}", init->rise_time, specs->rise_max, init->fall_time, specs->fall_max); return -1; } if (init->digital_filter_coef > STM32_I2C_DIGITAL_FILTER_MAX) { DMSG("DNF out of bound %"PRId8"/%d", init->digital_filter_coef, STM32_I2C_DIGITAL_FILTER_MAX); return -1; } /* Analog and Digital Filters */ if (init->analog_filter) { af_delay_min = STM32_I2C_ANALOG_FILTER_DELAY_MIN; af_delay_max = STM32_I2C_ANALOG_FILTER_DELAY_MAX; } dnf_delay = init->digital_filter_coef * i2cclk; sdadel_min = specs->hddat_min + init->fall_time; delay = af_delay_min - ((init->digital_filter_coef + 3) * i2cclk); if (SUB_OVERFLOW(sdadel_min, delay, &sdadel_min)) sdadel_min = 0; sdadel_max = specs->vddat_max - init->rise_time; delay = af_delay_max - ((init->digital_filter_coef + 4) * i2cclk); if (SUB_OVERFLOW(sdadel_max, delay, &sdadel_max)) sdadel_max = 0; scldel_min = init->rise_time + specs->sudat_min; DMSG("I2C SDADEL(min/max): %u/%u, SCLDEL(Min): %u", sdadel_min, sdadel_max, scldel_min); /* Compute possible values for PRESC, SCLDEL and SDADEL */ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { for (l = 0; l < I2C_TIMINGR_SCLDEL_MAX; l++) { uint32_t scldel = (l + 1) * (p + 1) * i2cclk; if (scldel < scldel_min) continue; for (a = 0; a < I2C_TIMINGR_SDADEL_MAX; a++) { uint32_t sdadel = (a * (p + 1) + 1) * i2cclk; if ((sdadel >= sdadel_min) && (sdadel <= sdadel_max) && (p != p_prev)) { solutions[p].scldel = l; solutions[p].sdadel = a; solutions[p].is_saved = true; p_prev = p; break; } } if (p_prev == p) break; } } if (p_prev == I2C_TIMINGR_PRESC_MAX) { DMSG("I2C no Prescaler solution"); return -1; } tsync = af_delay_min + dnf_delay + (2 * i2cclk); clk_max = I2C_NSEC_PER_SEC / RATE_MIN(specs->rate); clk_min = I2C_NSEC_PER_SEC / specs->rate; /* * Among prescaler possibilities discovered above figures out SCL Low * and High Period. Provided: * - SCL Low Period has to be higher than Low Period of the SCL Clock * defined by I2C Specification. I2C Clock has to be lower than * (SCL Low Period - Analog/Digital filters) / 4. * - SCL High Period has to be lower than High Period of the SCL Clock * defined by I2C Specification. * - I2C Clock has to be lower than SCL High Period. */ for (p = 0; p < I2C_TIMINGR_PRESC_MAX; p++) { uint32_t prescaler = (p + 1) * i2cclk; if (!solutions[p].is_saved) continue; for (l = 0; l < I2C_TIMINGR_SCLL_MAX; l++) { uint32_t tscl_l = ((l + 1) * prescaler) + tsync; if (tscl_l < specs->l_min || i2cclk >= ((tscl_l - af_delay_min - dnf_delay) / 4)) continue; for (h = 0; h < I2C_TIMINGR_SCLH_MAX; h++) { uint32_t tscl_h = ((h + 1) * prescaler) + tsync; uint32_t tscl = tscl_l + tscl_h + init->rise_time + init->fall_time; if (tscl >= clk_min && tscl <= clk_max && tscl_h >= specs->h_min && i2cclk < tscl_h) { int clk_error = tscl - i2cbus; if (clk_error < 0) clk_error = -clk_error; if (clk_error < clk_error_prev) { clk_error_prev = clk_error; solutions[p].scll = l; solutions[p].sclh = h; s = p; } } } } } if (s < 0) { DMSG("I2C no solution at all"); return -1; } /* Finalize timing settings */ *timing = I2C_SET_TIMINGR_PRESC(s) | I2C_SET_TIMINGR_SCLDEL(solutions[s].scldel) | I2C_SET_TIMINGR_SDADEL(solutions[s].sdadel) | I2C_SET_TIMINGR_SCLH(solutions[s].sclh) | I2C_SET_TIMINGR_SCLL(solutions[s].scll); DMSG("I2C TIMINGR (PRESC/SCLDEL/SDADEL): %i/%"PRIu8"/%"PRIu8, s, solutions[s].scldel, solutions[s].sdadel); DMSG("I2C TIMINGR (SCLH/SCLL): %"PRIu8"/%"PRIu8, solutions[s].sclh, solutions[s].scll); DMSG("I2C TIMINGR: 0x%"PRIx32, *timing); return 0; } /* i2c_specs[] must be sorted by increasing rate */ static bool __maybe_unused i2c_specs_is_consistent(void) { size_t i = 0; COMPILE_TIME_ASSERT(ARRAY_SIZE(i2c_specs)); for (i = 1; i < ARRAY_SIZE(i2c_specs); i++) if (i2c_specs[i - 1].rate >= i2c_specs[i].rate) return false; return true; } /* * @brief From requested rate, get the closest I2C rate without exceeding it, * within I2C specification values defined in @i2c_specs. * @param rate: The requested rate. * @retval Found rate, else the lowest value supported by platform. */ static uint32_t get_lower_rate(uint32_t rate) { size_t i = 0; for (i = ARRAY_SIZE(i2c_specs); i > 0; i--) if (rate > i2c_specs[i - 1].rate) return i2c_specs[i - 1].rate; return i2c_specs[0].rate; } /* * Setup the I2C device timings * * @hi2c: I2C handle structure * @init: Ref to the initialization configuration structure * @timing: Output TIMINGR register configuration value * @retval 0 if OK, negative value else */ static int i2c_setup_timing(struct i2c_handle_s *hi2c, struct stm32_i2c_init_s *init, uint32_t *timing) { int rc = 0; unsigned long clock_src = 0; assert(i2c_specs_is_consistent()); clock_src = clk_get_rate(hi2c->clock); if (!clock_src) { DMSG("Null I2C clock rate"); return -1; } /* * If the timing has already been computed, and the frequency is the * same as when it was computed, then use the saved timing. */ if (clock_src == hi2c->saved_frequency) { *timing = hi2c->saved_timing; return 0; } do { rc = i2c_compute_timing(init, clock_src, timing); if (rc) { DMSG("Failed to compute I2C timings"); if (init->bus_rate > I2C_STANDARD_RATE) { init->bus_rate = get_lower_rate(init->bus_rate); IMSG("Downgrade I2C speed to %"PRIu32"Hz)", init->bus_rate); } else { break; } } } while (rc); if (rc) { DMSG("Impossible to compute I2C timings"); return rc; } DMSG("I2C Freq(%"PRIu32"Hz), Clk Source(%lu)", init->bus_rate, clock_src); DMSG("I2C Rise(%"PRId32") and Fall(%"PRId32") Time", init->rise_time, init->fall_time); DMSG("I2C Analog Filter(%s), DNF(%"PRIu8")", init->analog_filter ? "On" : "Off", init->digital_filter_coef); hi2c->saved_timing = *timing; hi2c->saved_frequency = clock_src; return 0; } /* * Configure I2C Analog noise filter. * @hi2c: I2C handle structure * @analog_filter_on: True if enabling analog filter, false otherwise */ static void i2c_config_analog_filter(struct i2c_handle_s *hi2c, bool analog_filter_on) { vaddr_t base = get_base(hi2c); /* Disable the selected I2C peripheral */ io_clrbits32(base + I2C_CR1, I2C_CR1_PE); /* Reset I2Cx ANOFF bit */ io_clrbits32(base + I2C_CR1, I2C_CR1_ANFOFF); /* Set analog filter bit if filter is disabled */ if (!analog_filter_on) io_setbits32(base + I2C_CR1, I2C_CR1_ANFOFF); /* Enable the selected I2C peripheral */ io_setbits32(base + I2C_CR1, I2C_CR1_PE); } TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, struct stm32_i2c_init_s *init, struct pinctrl_state **pinctrl, struct pinctrl_state **pinctrl_sleep) { TEE_Result res = TEE_ERROR_GENERIC; const fdt32_t *cuint = NULL; struct dt_node_info info = { .status = 0 }; int __maybe_unused count = 0; /* Default STM32 specific configs caller may need to overwrite */ memset(init, 0, sizeof(*init)); fdt_fill_device_info(fdt, &info, node); assert(info.reg != DT_INFO_INVALID_REG && info.reg_size != DT_INFO_INVALID_REG_SIZE); init->dt_status = info.status; init->pbase = info.reg; init->reg_size = info.reg_size; res = clk_dt_get_by_index(fdt, node, 0, &init->clock); if (res) return res; cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); if (cuint) init->rise_time = fdt32_to_cpu(*cuint); else init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); if (cuint) init->fall_time = fdt32_to_cpu(*cuint); else init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); if (cuint) { init->bus_rate = fdt32_to_cpu(*cuint); if (init->bus_rate > I2C_FAST_PLUS_RATE) { DMSG("Invalid bus speed (%"PRIu32" > %i)", init->bus_rate, I2C_FAST_PLUS_RATE); return TEE_ERROR_GENERIC; } } else { init->bus_rate = I2C_STANDARD_RATE; } if (pinctrl) { res = pinctrl_get_state_by_name(fdt, node, "default", pinctrl); if (res) return res; } if (pinctrl_sleep) { res = pinctrl_get_state_by_name(fdt, node, "sleep", pinctrl_sleep); if (res == TEE_ERROR_ITEM_NOT_FOUND) res = TEE_SUCCESS; if (res) return res; } return TEE_SUCCESS; } int stm32_i2c_init(struct i2c_handle_s *hi2c, struct stm32_i2c_init_s *init_data) { int rc = 0; uint32_t timing = 0; vaddr_t base = 0; uint32_t val = 0; mutex_pm_aware_init(&hi2c->mu); rc = i2c_setup_timing(hi2c, init_data, &timing); if (rc) return rc; clk_enable(hi2c->clock); base = get_base(hi2c); hi2c->i2c_state = I2C_STATE_BUSY; /* Disable the selected I2C peripheral */ io_clrbits32(base + I2C_CR1, I2C_CR1_PE); /* Configure I2Cx: Frequency range */ io_write32(base + I2C_TIMINGR, timing & TIMINGR_CLEAR_MASK); /* Disable Own Address1 before set the Own Address1 configuration */ io_write32(base + I2C_OAR1, 0); /* Configure I2Cx: Own Address1 and ack own address1 mode */ if (init_data->addr_mode_10b_not_7b) io_write32(base + I2C_OAR1, I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | init_data->own_address1); else io_write32(base + I2C_OAR1, I2C_OAR1_OA1EN | init_data->own_address1); /* Configure I2Cx: Addressing Master mode */ io_write32(base + I2C_CR2, 0); if (init_data->addr_mode_10b_not_7b) io_setbits32(base + I2C_CR2, I2C_CR2_ADD10); /* * Enable the AUTOEND by default, and enable NACK * (should be disabled only during Slave process). */ io_setbits32(base + I2C_CR2, I2C_CR2_AUTOEND | I2C_CR2_NACK); /* Disable Own Address2 before set the Own Address2 configuration */ io_write32(base + I2C_OAR2, 0); /* Configure I2Cx: Dual mode and Own Address2 */ if (init_data->dual_address_mode) io_write32(base + I2C_OAR2, I2C_OAR2_OA2EN | init_data->own_address2 | (init_data->own_address2_masks << 8)); /* Configure I2Cx: Generalcall and NoStretch mode */ val = 0; if (init_data->general_call_mode) val |= I2C_CR1_GCEN; if (init_data->no_stretch_mode) val |= I2C_CR1_NOSTRETCH; io_write32(base + I2C_CR1, val); /* Enable the selected I2C peripheral */ io_setbits32(base + I2C_CR1, I2C_CR1_PE); hi2c->i2c_err = I2C_ERROR_NONE; hi2c->i2c_state = I2C_STATE_READY; i2c_config_analog_filter(hi2c, init_data->analog_filter); if (IS_ENABLED(CFG_STM32MP13)) stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true); clk_disable(hi2c->clock); if (hi2c->pinctrl && pinctrl_apply_state(hi2c->pinctrl)) return -1; return 0; } /* I2C transmit (TX) data register flush sequence */ static void i2c_flush_txdr(struct i2c_handle_s *hi2c) { vaddr_t base = get_base(hi2c); /* * If a pending TXIS flag is set, * write a dummy data in TXDR to clear it. */ if (io_read32(base + I2C_ISR) & I2C_ISR_TXIS) io_write32(base + I2C_TXDR, 0); /* Flush TX register if not empty */ if ((io_read32(base + I2C_ISR) & I2C_ISR_TXE) == 0) io_setbits32(base + I2C_ISR, I2C_ISR_TXE); } /* * Wait for a single target I2C_ISR bit to reach an awaited value (0 or 1) * * @hi2c: I2C handle structure * @bit_mask: Bit mask for the target single bit position to consider * @awaited_value: Awaited value of the target bit in I2C_ISR, 0 or 1 * @timeout_ref: Expriation timeout reference * Return 0 on success and a non-zero value on timeout */ static int wait_isr_event(struct i2c_handle_s *hi2c, uint32_t bit_mask, unsigned int awaited_value, uint64_t timeout_ref) { vaddr_t isr = get_base(hi2c) + I2C_ISR; assert(IS_POWER_OF_TWO(bit_mask) && !(awaited_value & ~1U)); /* May timeout while TEE thread is suspended */ while (!timeout_elapsed(timeout_ref)) if (!!(io_read32(isr) & bit_mask) == awaited_value) break; if (!!(io_read32(isr) & bit_mask) == awaited_value) return 0; notif_i2c_timeout(hi2c); return -1; } /* Handle Acknowledge-Failed sequence detection during an I2C Communication */ static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) { vaddr_t base = get_base(hi2c); if ((io_read32(base + I2C_ISR) & I2C_ISR_NACKF) == 0U) return 0; /* * Wait until STOP Flag is reset. Use polling method. * AutoEnd should be initiate after AF. * Timeout may elpased while TEE thread is suspended. */ while (!timeout_elapsed(timeout_ref)) if (io_read32(base + I2C_ISR) & I2C_ISR_STOPF) break; if ((io_read32(base + I2C_ISR) & I2C_ISR_STOPF) == 0) { notif_i2c_timeout(hi2c); return -1; } io_write32(base + I2C_ICR, I2C_ISR_NACKF); io_write32(base + I2C_ICR, I2C_ISR_STOPF); i2c_flush_txdr(hi2c); io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); hi2c->i2c_err |= I2C_ERROR_ACKF; hi2c->i2c_state = I2C_STATE_READY; return -1; } /* Wait TXIS bit is 1 in I2C_ISR register */ static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) { while (!timeout_elapsed(timeout_ref)) { if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_TXIS) break; if (i2c_ack_failed(hi2c, timeout_ref)) return -1; } if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_TXIS) return 0; if (i2c_ack_failed(hi2c, timeout_ref)) return -1; notif_i2c_timeout(hi2c); return -1; } /* Wait STOPF bit is 1 in I2C_ISR register */ static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) { while (!timeout_elapsed(timeout_ref)) { if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_STOPF) break; if (i2c_ack_failed(hi2c, timeout_ref)) return -1; } if (io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_STOPF) return 0; if (i2c_ack_failed(hi2c, timeout_ref)) return -1; notif_i2c_timeout(hi2c); return -1; } /* * Load I2C_CR2 register for a I2C transfer * * @hi2c: I2C handle structure * @dev_addr: Slave address to be transferred * @size: Number of bytes to be transferred * @i2c_mode: One of I2C_{RELOAD|AUTOEND|SOFTEND}_MODE: Enable Reload mode. * @startstop: One of I2C_NO_STARTSTOP, I2C_GENERATE_STOP, * I2C_GENERATE_START_{READ|WRITE} */ static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint32_t size, uint32_t i2c_mode, uint32_t startstop) { uint32_t clr_value = I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP | (I2C_CR2_RD_WRN & (startstop >> (31U - I2C_CR2_RD_WRN_OFFSET))); uint32_t set_value = (dev_addr & I2C_CR2_SADD) | ((size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | i2c_mode | startstop; io_clrsetbits32(get_base(hi2c) + I2C_CR2, clr_value, set_value); } /* * Master sends target device address followed by internal memory * address for a memory write request. * Function returns 0 on success or a negative value. */ static int i2c_request_mem_write(struct i2c_handle_s *hi2c, struct i2c_request *request, uint64_t timeout_ref) { vaddr_t base = get_base(hi2c); i2c_transfer_config(hi2c, request->dev_addr, request->mem_addr_size, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); if (i2c_wait_txis(hi2c, timeout_ref)) return -1; if (request->mem_addr_size == I2C_MEMADD_SIZE_8BIT) { /* Send memory address */ io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); } else { /* Send MSB of memory address */ io_write8(base + I2C_TXDR, (request->mem_addr & 0xFF00U) >> 8); if (i2c_wait_txis(hi2c, timeout_ref)) return -1; /* Send LSB of memory address */ io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); } if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref)) return -1; return 0; } /* * Master sends target device address followed by internal memory * address to prepare a memory read request. * Function returns 0 on success or a negative value. */ static int i2c_request_mem_read(struct i2c_handle_s *hi2c, struct i2c_request *request, uint64_t timeout_ref) { vaddr_t base = get_base(hi2c); i2c_transfer_config(hi2c, request->dev_addr, request->mem_addr_size, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); if (i2c_wait_txis(hi2c, timeout_ref)) return -1; if (request->mem_addr_size == I2C_MEMADD_SIZE_8BIT) { /* Send memory address */ io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); } else { /* Send MSB of memory address */ io_write8(base + I2C_TXDR, (request->mem_addr & 0xFF00U) >> 8); if (i2c_wait_txis(hi2c, timeout_ref)) return -1; /* Send LSB of memory address */ io_write8(base + I2C_TXDR, request->mem_addr & 0x00FFU); } if (wait_isr_event(hi2c, I2C_ISR_TC, 1, timeout_ref)) return -1; return 0; } /* * Write an amount of data in blocking mode * * @hi2c: Reference to struct i2c_handle_s * @request: I2C request parameters * @p_data: Pointer to data buffer * @size: Amount of data to be sent * Return 0 on success or a negative value */ static int do_write(struct i2c_handle_s *hi2c, struct i2c_request *request, uint8_t *p_data, uint16_t size) { uint64_t timeout_ref = 0; vaddr_t base = get_base(hi2c); int rc = -1; uint8_t *p_buff = p_data; size_t xfer_size = 0; size_t xfer_count = size; if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM) return -1; if (!p_data || !size) return -1; mutex_pm_aware_lock(&hi2c->mu); if (hi2c->i2c_state != I2C_STATE_READY) { mutex_pm_aware_unlock(&hi2c->mu); return -1; } clk_enable(hi2c->clock); timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref)) goto bail; hi2c->i2c_state = I2C_STATE_BUSY_TX; hi2c->i2c_err = I2C_ERROR_NONE; timeout_ref = timeout_init_us(request->timeout_ms * 1000); if (request->mode == I2C_MODE_MEM) { /* In memory mode, send slave address and memory address */ if (i2c_request_mem_write(hi2c, request, timeout_ref)) goto bail; if (xfer_count > MAX_NBYTE_SIZE) { xfer_size = MAX_NBYTE_SIZE; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { xfer_size = xfer_count; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } else { /* In master mode, send slave address */ if (xfer_count > MAX_NBYTE_SIZE) { xfer_size = MAX_NBYTE_SIZE; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); } else { xfer_size = xfer_count; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); } } do { if (i2c_wait_txis(hi2c, timeout_ref)) goto bail; io_write8(base + I2C_TXDR, *p_buff); p_buff++; xfer_count--; xfer_size--; if (xfer_count && !xfer_size) { /* Wait until TCR flag is set */ if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref)) goto bail; if (xfer_count > MAX_NBYTE_SIZE) { xfer_size = MAX_NBYTE_SIZE; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { xfer_size = xfer_count; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } } while (xfer_count > 0U); /* * No need to Check TC flag, with AUTOEND mode the stop * is automatically generated. * Wait until STOPF flag is reset. */ if (i2c_wait_stop(hi2c, timeout_ref)) goto bail; io_write32(base + I2C_ICR, I2C_ISR_STOPF); io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); hi2c->i2c_state = I2C_STATE_READY; rc = 0; bail: clk_disable(hi2c->clock); mutex_pm_aware_unlock(&hi2c->mu); return rc; } int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint32_t mem_addr, uint32_t mem_addr_size, uint8_t *p_data, size_t size, unsigned int timeout_ms) { struct i2c_request request = { .dev_addr = dev_addr, .mode = I2C_MODE_MEM, .mem_addr = mem_addr, .mem_addr_size = mem_addr_size, .timeout_ms = timeout_ms, }; return do_write(hi2c, &request, p_data, size); } int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint8_t *p_data, size_t size, unsigned int timeout_ms) { struct i2c_request request = { .dev_addr = dev_addr, .mode = I2C_MODE_MASTER, .timeout_ms = timeout_ms, }; return do_write(hi2c, &request, p_data, size); } int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr, unsigned int mem_addr, uint8_t *p_data, bool write) { uint64_t timeout_ref = 0; uintptr_t base = get_base(hi2c); int rc = -1; uint8_t *p_buff = p_data; uint32_t event_mask = 0; mutex_pm_aware_lock(&hi2c->mu); if (hi2c->i2c_state != I2C_STATE_READY || !p_data) { mutex_pm_aware_unlock(&hi2c->mu); return -1; } clk_enable(hi2c->clock); timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref)) goto bail; hi2c->i2c_state = write ? I2C_STATE_BUSY_TX : I2C_STATE_BUSY_RX; hi2c->i2c_err = I2C_ERROR_NONE; i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT, write ? I2C_RELOAD_MODE : I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); if (i2c_wait_txis(hi2c, timeout_ref)) goto bail; io_write8(base + I2C_TXDR, mem_addr); if (write) event_mask = I2C_ISR_TCR; else event_mask = I2C_ISR_TC; timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); if (wait_isr_event(hi2c, event_mask, 1, timeout_ref)) goto bail; i2c_transfer_config(hi2c, dev_addr, I2C_MEMADD_SIZE_8BIT, I2C_AUTOEND_MODE, write ? I2C_NO_STARTSTOP : I2C_GENERATE_START_READ); timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); if (write) { if (i2c_wait_txis(hi2c, timeout_ref)) goto bail; io_write8(base + I2C_TXDR, *p_buff); } else { if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1, timeout_ref)) goto bail; *p_buff = io_read8(base + I2C_RXDR); } timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_US); if (i2c_wait_stop(hi2c, timeout_ref)) goto bail; io_write32(base + I2C_ICR, I2C_ISR_STOPF); io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); hi2c->i2c_state = I2C_STATE_READY; rc = 0; bail: clk_disable(hi2c->clock); mutex_pm_aware_unlock(&hi2c->mu); return rc; } /* * Read an amount of data in blocking mode * * @hi2c: Reference to struct i2c_handle_s * @request: I2C request parameters * @p_data: Pointer to data buffer * @size: Amount of data to be sent * Return 0 on success or a negative value */ static int do_read(struct i2c_handle_s *hi2c, struct i2c_request *request, uint8_t *p_data, uint32_t size) { vaddr_t base = get_base(hi2c); uint64_t timeout_ref = 0; int rc = -1; uint8_t *p_buff = p_data; size_t xfer_count = size; size_t xfer_size = 0; if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM) return -1; if (!p_data || !size) return -1; mutex_pm_aware_lock(&hi2c->mu); if (hi2c->i2c_state != I2C_STATE_READY) { mutex_pm_aware_unlock(&hi2c->mu); return -1; } clk_enable(hi2c->clock); timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); if (wait_isr_event(hi2c, I2C_ISR_BUSY, 0, timeout_ref)) goto bail; hi2c->i2c_state = I2C_STATE_BUSY_RX; hi2c->i2c_err = I2C_ERROR_NONE; timeout_ref = timeout_init_us(request->timeout_ms * 1000); if (request->mode == I2C_MODE_MEM) { /* Send memory address */ if (i2c_request_mem_read(hi2c, request, timeout_ref)) goto bail; } /* * Send slave address. * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE * and generate RESTART. */ if (xfer_count > MAX_NBYTE_SIZE) { xfer_size = MAX_NBYTE_SIZE; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); } else { xfer_size = xfer_count; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); } do { if (wait_isr_event(hi2c, I2C_ISR_RXNE, 1, timeout_init_us(I2C_TIMEOUT_RXNE_MS * 1000))) goto bail; *p_buff = io_read8(base + I2C_RXDR); p_buff++; xfer_size--; xfer_count--; if (xfer_count && !xfer_size) { if (wait_isr_event(hi2c, I2C_ISR_TCR, 1, timeout_ref)) goto bail; if (xfer_count > MAX_NBYTE_SIZE) { xfer_size = MAX_NBYTE_SIZE; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { xfer_size = xfer_count; i2c_transfer_config(hi2c, request->dev_addr, xfer_size, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } } while (xfer_count > 0U); /* * No need to Check TC flag, with AUTOEND mode the stop * is automatically generated. * Wait until STOPF flag is reset. */ if (i2c_wait_stop(hi2c, timeout_ref)) goto bail; /* Clear the NACK generated at the end of the transfer */ if ((io_read32(get_base(hi2c) + I2C_ISR) & I2C_ISR_NACKF)) io_write32(get_base(hi2c) + I2C_ICR, I2C_ICR_NACKCF); io_write32(base + I2C_ICR, I2C_ISR_STOPF); io_clrbits32(base + I2C_CR2, CR2_RESET_MASK); hi2c->i2c_state = I2C_STATE_READY; rc = 0; bail: clk_disable(hi2c->clock); mutex_pm_aware_unlock(&hi2c->mu); return rc; } int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint32_t mem_addr, uint32_t mem_addr_size, uint8_t *p_data, size_t size, unsigned int timeout_ms) { struct i2c_request request = { .dev_addr = dev_addr, .mode = I2C_MODE_MEM, .mem_addr = mem_addr, .mem_addr_size = mem_addr_size, .timeout_ms = timeout_ms, }; return do_read(hi2c, &request, p_data, size); } int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint8_t *p_data, size_t size, unsigned int timeout_ms) { struct i2c_request request = { .dev_addr = dev_addr, .mode = I2C_MODE_MASTER, .timeout_ms = timeout_ms, }; return do_read(hi2c, &request, p_data, size); } static struct i2c_handle_s *stm32_i2c_dev_to_handle(struct i2c_dev *i2c_dev) { struct stm32_i2c_dev *dev = container_of(i2c_dev, struct stm32_i2c_dev, i2c_dev); return dev->handle; } static TEE_Result stm32_i2c_read_data(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len) { struct i2c_handle_s *i2c_handle = stm32_i2c_dev_to_handle(i2c_dev); int rc = 0; rc = stm32_i2c_master_receive(i2c_handle, i2c_dev->addr, buf, len, I2C_TIMEOUT_DEFAULT_MS); if (!rc) return TEE_SUCCESS; else return TEE_ERROR_GENERIC; } static TEE_Result stm32_i2c_write_data(struct i2c_dev *i2c_dev, const uint8_t *buf, size_t len) { struct i2c_handle_s *i2c_handle = stm32_i2c_dev_to_handle(i2c_dev); uint8_t *buf2 = (uint8_t *)buf; int rc = 0; rc = stm32_i2c_master_transmit(i2c_handle, i2c_dev->addr, buf2, len, I2C_TIMEOUT_DEFAULT_MS); if (!rc) return TEE_SUCCESS; else return TEE_ERROR_GENERIC; } static const struct i2c_ctrl_ops stm32_i2c_ops = { .read = stm32_i2c_read_data, .write = stm32_i2c_write_data, }; bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr, unsigned int trials, unsigned int timeout_ms) { vaddr_t base = get_base(hi2c); unsigned int i2c_trials = 0U; bool rc = false; mutex_pm_aware_lock(&hi2c->mu); if (hi2c->i2c_state != I2C_STATE_READY) { mutex_pm_aware_unlock(&hi2c->mu); return rc; } clk_enable(hi2c->clock); if (io_read32(base + I2C_ISR) & I2C_ISR_BUSY) goto bail; hi2c->i2c_state = I2C_STATE_BUSY; hi2c->i2c_err = I2C_ERROR_NONE; do { uint64_t timeout_ref = 0; vaddr_t isr = base + I2C_ISR; /* Generate Start */ if ((io_read32(base + I2C_OAR1) & I2C_OAR1_OA1MODE) == 0) io_write32(base + I2C_CR2, ((dev_addr & I2C_CR2_SADD) | I2C_CR2_START | I2C_CR2_AUTOEND) & ~I2C_CR2_RD_WRN); else io_write32(base + I2C_CR2, ((dev_addr & I2C_CR2_SADD) | I2C_CR2_START | I2C_CR2_ADD10) & ~I2C_CR2_RD_WRN); /* * No need to Check TC flag, with AUTOEND mode the stop * is automatically generated. * Wait until STOPF flag is set or a NACK flag is set. */ timeout_ref = timeout_init_us(timeout_ms * 1000); while (!timeout_elapsed(timeout_ref)) if (io_read32(isr) & (I2C_ISR_STOPF | I2C_ISR_NACKF)) break; if ((io_read32(isr) & (I2C_ISR_STOPF | I2C_ISR_NACKF)) == 0) { notif_i2c_timeout(hi2c); goto bail; } if ((io_read32(base + I2C_ISR) & I2C_ISR_NACKF) == 0U) { if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref)) goto bail; io_write32(base + I2C_ICR, I2C_ISR_STOPF); hi2c->i2c_state = I2C_STATE_READY; rc = true; goto bail; } if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref)) goto bail; io_write32(base + I2C_ICR, I2C_ISR_NACKF); io_write32(base + I2C_ICR, I2C_ISR_STOPF); if (i2c_trials == trials) { io_setbits32(base + I2C_CR2, I2C_CR2_STOP); if (wait_isr_event(hi2c, I2C_ISR_STOPF, 1, timeout_ref)) goto bail; io_write32(base + I2C_ICR, I2C_ISR_STOPF); } i2c_trials++; } while (i2c_trials < trials); notif_i2c_timeout(hi2c); bail: clk_disable(hi2c->clock); mutex_pm_aware_unlock(&hi2c->mu); return rc; } void stm32_i2c_resume(struct i2c_handle_s *hi2c) { if (hi2c->i2c_state == I2C_STATE_READY) return; if ((hi2c->i2c_state != I2C_STATE_RESET) && (hi2c->i2c_state != I2C_STATE_SUSPENDED)) panic(); if (pinctrl_apply_state(hi2c->pinctrl)) panic(); if (hi2c->i2c_state == I2C_STATE_RESET) { /* There is no valid I2C configuration to be loaded yet */ return; } restore_cfg(hi2c, &hi2c->sec_cfg); if (IS_ENABLED(CFG_STM32MP13)) stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true); hi2c->i2c_state = I2C_STATE_READY; } void stm32_i2c_suspend(struct i2c_handle_s *hi2c) { if (hi2c->i2c_state == I2C_STATE_SUSPENDED) return; if (hi2c->i2c_state != I2C_STATE_READY) panic(); save_cfg(hi2c, &hi2c->sec_cfg); if (hi2c->pinctrl_sleep && pinctrl_apply_state(hi2c->pinctrl_sleep)) panic(); hi2c->i2c_state = I2C_STATE_SUSPENDED; } static TEE_Result stm32_get_i2c_dev(struct dt_pargs *args, void *data, struct i2c_dev **out_device) { struct stm32_i2c_dev *stm32_i2c_dev = NULL; paddr_t addr = 0; addr = fdt_reg_base_address(args->fdt, args->phandle_node); if (addr == DT_INFO_INVALID_REG) { DMSG("Can't get device I2C address"); return TEE_ERROR_GENERIC; } stm32_i2c_dev = calloc(1, sizeof(*stm32_i2c_dev)); if (!stm32_i2c_dev) return TEE_ERROR_OUT_OF_MEMORY; stm32_i2c_dev->handle = data; stm32_i2c_dev->i2c_dev.addr = addr; stm32_i2c_dev->i2c_ctrl.ops = &stm32_i2c_ops; stm32_i2c_dev->i2c_dev.ctrl = &stm32_i2c_dev->i2c_ctrl; *out_device = &stm32_i2c_dev->i2c_dev; return TEE_SUCCESS; } static TEE_Result stm32_i2c_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_SUCCESS; int subnode = 0; struct i2c_handle_s *i2c_handle_p = NULL; struct stm32_i2c_init_s init_data = { }; struct pinctrl_state *pinctrl_active = NULL; struct pinctrl_state *pinctrl_idle = NULL; res = stm32_i2c_get_setup_from_fdt((void *)fdt, node, &init_data, &pinctrl_active, &pinctrl_idle); if (res) return res; i2c_handle_p = calloc(1, sizeof(struct i2c_handle_s)); if (!i2c_handle_p) return TEE_ERROR_OUT_OF_MEMORY; i2c_handle_p->dt_status = init_data.dt_status; i2c_handle_p->reg_size = init_data.reg_size; i2c_handle_p->clock = init_data.clock; i2c_handle_p->base.pa = init_data.pbase; i2c_handle_p->base.va = io_pa_or_va(&i2c_handle_p->base, init_data.reg_size); assert(i2c_handle_p->base.va); i2c_handle_p->clock = init_data.clock; i2c_handle_p->i2c_state = I2C_STATE_RESET; i2c_handle_p->pinctrl = pinctrl_active; i2c_handle_p->pinctrl_sleep = pinctrl_idle; init_data.analog_filter = true; init_data.digital_filter_coef = 0; if (stm32_i2c_init(i2c_handle_p, &init_data)) panic("Couldn't initialise I2C"); res = i2c_register_provider(fdt, node, stm32_get_i2c_dev, i2c_handle_p); if (res) panic("Couldn't register I2C provider"); fdt_for_each_subnode(subnode, fdt, node) { res = dt_driver_maybe_add_probe_node(fdt, subnode); if (res) { EMSG("Failed on node %s with %#"PRIx32, fdt_get_name(fdt, subnode, NULL), res); panic(); } } return res; } static const struct dt_device_match stm32_i2c_match_table[] = { { .compatible = "st,stm32mp15-i2c" }, { .compatible = "st,stm32mp13-i2c" }, { .compatible = "st,stm32mp15-i2c-non-secure" }, { } }; DEFINE_DT_DRIVER(stm32_i2c_dt_driver) = { .name = "stm32_i2c", .match_table = stm32_i2c_match_table, .probe = stm32_i2c_probe, .type = DT_DRIVER_I2C }; optee_os-4.3.0/core/drivers/stm32_ipcc.c000066400000000000000000000212011464416617300200630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022-2024, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define IPCC_C1SECCFGR U(0x80) #define IPCC_C1PRIVCFGR U(0x84) #define IPCC_C1CIDCFGR U(0x88) #define IPCC_C2SECCFGR U(0x90) #define IPCC_C2PRIVCFGR U(0x94) #define IPCC_C2CIDCFGR U(0x98) #define IPCC_HWCFGR U(0x3F0) /* * CIDCFGR register bitfields */ #define IPCC_CIDCFGR_SCID_MASK GENMASK_32(6, 4) #define IPCC_CIDCFGR_CONF_MASK (_CIDCFGR_CFEN | \ IPCC_CIDCFGR_SCID_MASK) /* * PRIVCFGR register bitfields */ #define IPCC_PRIVCFGR_MASK GENMASK_32(15, 0) /* * SECCFGR register bitfields */ #define IPCC_SECCFGR_MASK GENMASK_32(15, 0) /* * IPCC_HWCFGR register bitfields */ #define IPCC_HWCFGR_CHAN_MASK GENMASK_32(7, 0) /* * Miscellaneous */ #define IPCC_NB_MAX_RIF_CHAN U(16) #define IPCC_NB_MAX_CID_SUPPORTED U(7) struct ipcc_pdata { /* * An IPCC has nb_channels_cfg channel configuration for its * (nb_channels_cfg / 2) bi-directionnal channels */ unsigned int nb_channels_cfg; struct clk *ipcc_clock; vaddr_t base; struct rif_conf_data conf_data; STAILQ_ENTRY(ipcc_pdata) link; }; static STAILQ_HEAD(, ipcc_pdata) ipcc_list = STAILQ_HEAD_INITIALIZER(ipcc_list); /* This function expects IPCC bus clock is enabled */ static void apply_rif_config(struct ipcc_pdata *ipcc_d, bool is_tdcid) { uint32_t priv_proc_1 = 0; uint32_t priv_proc_2 = 0; uint32_t sec_proc_1 = 0; uint32_t sec_proc_2 = 0; unsigned int i = 0; bool is_cid_configured = false; /* * Check that the number of channel supported by hardware * is coherent with the config */ assert((io_read32(ipcc_d->base + IPCC_HWCFGR) & IPCC_HWCFGR_CHAN_MASK) >= ipcc_d->nb_channels_cfg / 2); /* * When TDCID, OP-TEE should be the one to set the CID filtering * configuration. Clearing previous configuration prevents * undesired events during the only legitimate configuration. */ if (is_tdcid) { /* IPCC Processor 1 */ io_clrbits32(ipcc_d->base + IPCC_C1CIDCFGR, IPCC_CIDCFGR_CONF_MASK); /* IPCC Processor 2 */ io_clrbits32(ipcc_d->base + IPCC_C2CIDCFGR, IPCC_CIDCFGR_CONF_MASK); } /* Split the sec and priv configuration for IPCC processor 1 and 2 */ sec_proc_1 = ipcc_d->conf_data.sec_conf[0] & GENMASK_32(IPCC_NB_MAX_RIF_CHAN - 1, 0); priv_proc_1 = ipcc_d->conf_data.priv_conf[0] & GENMASK_32(IPCC_NB_MAX_RIF_CHAN - 1, 0); sec_proc_2 = (ipcc_d->conf_data.sec_conf[0] & GENMASK_32((IPCC_NB_MAX_RIF_CHAN * 2) - 1, IPCC_NB_MAX_RIF_CHAN)) >> IPCC_NB_MAX_RIF_CHAN; priv_proc_2 = (ipcc_d->conf_data.priv_conf[0] & GENMASK_32((IPCC_NB_MAX_RIF_CHAN * 2) - 1, IPCC_NB_MAX_RIF_CHAN)) >> IPCC_NB_MAX_RIF_CHAN; /* Security and privilege RIF configuration */ io_clrsetbits32(ipcc_d->base + IPCC_C1PRIVCFGR, IPCC_PRIVCFGR_MASK, priv_proc_1); io_clrsetbits32(ipcc_d->base + IPCC_C2PRIVCFGR, IPCC_PRIVCFGR_MASK, priv_proc_2); io_clrsetbits32(ipcc_d->base + IPCC_C1SECCFGR, IPCC_SECCFGR_MASK, sec_proc_1); io_clrsetbits32(ipcc_d->base + IPCC_C2SECCFGR, IPCC_SECCFGR_MASK, sec_proc_2); /* * Evaluate RIF CID filtering configuration before setting it. * Parsed configuration must have consistency. If CID filtering * is enabled for an IPCC channel, then it must be the case for all * channels of this processor. This is a configuration check. */ for (i = 0; i < IPCC_NB_MAX_RIF_CHAN; i++) { if (!(BIT(i) & ipcc_d->conf_data.access_mask[0])) continue; if (!is_cid_configured && (BIT(0) & ipcc_d->conf_data.cid_confs[i])) { is_cid_configured = true; if (i == IPCC_NB_MAX_RIF_CHAN - 1) panic("Inconsistent IPCC CID filtering RIF configuration"); } if (is_cid_configured && !(BIT(0) & ipcc_d->conf_data.cid_confs[i])) panic("Inconsistent IPCC CID filtering RIF configuration"); } /* IPCC processor 1 CID filtering configuration */ if (!is_tdcid) return; io_clrsetbits32(ipcc_d->base + IPCC_C1CIDCFGR, IPCC_CIDCFGR_CONF_MASK, ipcc_d->conf_data.cid_confs[0]); /* * Reset this field to evaluate CID filtering configuration * for processor 2 */ is_cid_configured = false; for (i = IPCC_NB_MAX_RIF_CHAN; i < IPCC_NB_MAX_RIF_CHAN * 2; i++) { if (!(BIT(i) & ipcc_d->conf_data.access_mask[0])) continue; if (!is_cid_configured && (BIT(0) & ipcc_d->conf_data.cid_confs[i])) { is_cid_configured = true; if (i == (IPCC_NB_MAX_RIF_CHAN * 2) - 1) panic("Inconsistent IPCC CID filtering RIF configuration"); } if (is_cid_configured && !(BIT(0) & ipcc_d->conf_data.cid_confs[i])) panic("Inconsistent IPCC CID filtering RIF configuration"); } /* IPCC Processor 2 CID filtering configuration */ io_clrsetbits32(ipcc_d->base + IPCC_C2CIDCFGR, IPCC_CIDCFGR_CONF_MASK, ipcc_d->conf_data.cid_confs[IPCC_NB_MAX_RIF_CHAN]); } static void stm32_ipcc_pm_resume(struct ipcc_pdata *ipcc) { apply_rif_config(ipcc, true); } static void stm32_ipcc_pm_suspend(struct ipcc_pdata *ipcc __unused) { /* * Do nothing because IPCC forbids RIF configuration read if CID * filtering is enabled. We'll simply restore the device tree RIF * configuration. */ } static TEE_Result stm32_ipcc_pm(enum pm_op op, unsigned int pm_hint, const struct pm_callback_handle *pm_handle) { struct ipcc_pdata *ipcc = pm_handle->handle; TEE_Result res = TEE_ERROR_GENERIC; bool is_tdcid = false; if (stm32_rifsc_check_tdcid(&is_tdcid)) panic(); if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid) return TEE_SUCCESS; res = clk_enable(ipcc->ipcc_clock); if (res) return res; if (op == PM_OP_RESUME) stm32_ipcc_pm_resume(ipcc); else stm32_ipcc_pm_suspend(ipcc); clk_disable(ipcc->ipcc_clock); return TEE_SUCCESS; } static TEE_Result parse_dt(const void *fdt, int node, struct ipcc_pdata *ipcc_d) { int lenp = 0; unsigned int i = 0; TEE_Result res = TEE_ERROR_GENERIC; const fdt32_t *cuint = NULL; struct dt_node_info info = { }; struct io_pa_va addr = { }; fdt_fill_device_info(fdt, &info, node); assert(info.reg != DT_INFO_INVALID_REG && info.reg_size != DT_INFO_INVALID_REG_SIZE); addr.pa = info.reg; ipcc_d->base = io_pa_or_va_secure(&addr, info.reg_size); assert(ipcc_d->base); /* Gate the IP */ res = clk_dt_get_by_index(fdt, node, 0, &ipcc_d->ipcc_clock); if (res) return res; cuint = fdt_getprop(fdt, node, "st,protreg", &lenp); if (!cuint) panic("No RIF configuration available"); ipcc_d->nb_channels_cfg = (unsigned int)(lenp / sizeof(uint32_t)); assert(ipcc_d->nb_channels_cfg <= (IPCC_NB_MAX_RIF_CHAN * 2)); ipcc_d->conf_data.cid_confs = calloc(IPCC_NB_MAX_RIF_CHAN * 2, sizeof(uint32_t)); ipcc_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t)); ipcc_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t)); ipcc_d->conf_data.access_mask = calloc(1, sizeof(uint32_t)); assert(ipcc_d->conf_data.cid_confs && ipcc_d->conf_data.sec_conf && ipcc_d->conf_data.priv_conf && ipcc_d->conf_data.access_mask); for (i = 0; i < ipcc_d->nb_channels_cfg; i++) stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), &ipcc_d->conf_data, IPCC_NB_MAX_CID_SUPPORTED, IPCC_NB_MAX_RIF_CHAN * 2); return TEE_SUCCESS; } static TEE_Result stm32_ipcc_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct ipcc_pdata *ipcc_d = NULL; bool is_tdcid = false; res = stm32_rifsc_check_tdcid(&is_tdcid); if (res) return res; ipcc_d = calloc(1, sizeof(*ipcc_d)); if (!ipcc_d) return TEE_ERROR_OUT_OF_MEMORY; res = parse_dt(fdt, node, ipcc_d); if (res) goto err; res = clk_enable(ipcc_d->ipcc_clock); if (res) panic("Cannot access IPCC clock"); apply_rif_config(ipcc_d, is_tdcid); clk_disable(ipcc_d->ipcc_clock); STAILQ_INSERT_TAIL(&ipcc_list, ipcc_d, link); register_pm_core_service_cb(stm32_ipcc_pm, ipcc_d, "stm32-ipcc"); return res; err: /* Free all allocated resources */ free(ipcc_d->conf_data.access_mask); free(ipcc_d->conf_data.cid_confs); free(ipcc_d->conf_data.priv_conf); free(ipcc_d->conf_data.sec_conf); free(ipcc_d); return res; } static const struct dt_device_match stm32_ipcc_match_table[] = { { .compatible = "st,stm32mp25-ipcc" }, { } }; DEFINE_DT_DRIVER(stm32_ipcc_dt_driver) = { .name = "st,stm32mp-ipcc", .match_table = stm32_ipcc_match_table, .probe = stm32_ipcc_probe, }; optee_os-4.3.0/core/drivers/stm32_iwdg.c000066400000000000000000000243001464416617300201020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* IWDG Compatibility */ #define IWDG_TIMEOUT_US U(1000) #define IWDG_CNT_MASK GENMASK_32(11, 0) /* IWDG registers offsets */ #define IWDG_KR_OFFSET U(0x00) #define IWDG_PR_OFFSET U(0x04) #define IWDG_RLR_OFFSET U(0x08) #define IWDG_SR_OFFSET U(0x0C) #define IWDG_EWCR_OFFSET U(0x14) #define IWDG_KR_ACCESS_KEY U(0x5555) #define IWDG_KR_RELOAD_KEY U(0xAAAA) #define IWDG_KR_START_KEY U(0xCCCC) /* Use a fixed prescaler divider of 256 */ #define IWDG_PRESCALER_256 U(256) #define IWDG_PR_DIV_256 U(0x06) #define IWDG_PR_DIV_MASK GENMASK_32(3, 0) #define IWDG_SR_PVU BIT(0) #define IWDG_SR_RVU BIT(1) #define IWDG_SR_WVU BIT(2) #define IWDG_SR_EWU BIT(3) #define IWDG_SR_UPDATE_MASK (IWDG_SR_PVU | IWDG_SR_RVU | IWDG_SR_WVU | \ IWDG_SR_EWU) #define IWDG_EWCR_EWIE BIT(15) #define IWDG_EWCR_EWIC BIT(14) /* * Values for struct stm32_iwdg_device::flags * IWDG_FLAGS_HW_ENABLED Watchdog is enabled by BootROM * IWDG_FLAGS_DISABLE_ON_STOP Watchdog is freezed in SoC STOP mode * IWDG_FLAGS_DISABLE_ON_STANDBY Watchdog is freezed in SoC STANDBY mode * IWDG_FLAGS_NON_SECURE Instance is assigned to non-secure world * IWDG_FLAGS_ENABLED Watchdog has been enabled */ #define IWDG_FLAGS_HW_ENABLED BIT(0) #define IWDG_FLAGS_DISABLE_ON_STOP BIT(1) #define IWDG_FLAGS_DISABLE_ON_STANDBY BIT(2) #define IWDG_FLAGS_NON_SECURE BIT(3) #define IWDG_FLAGS_ENABLED BIT(4) /* * IWDG watch instance data * @base - IWDG interface IOMEM base address * @clk_pclk - Bus clock * @clk_lsi - IWDG source clock * @flags - Property flags for the IWDG instance * @timeout - Watchdog elaspure timeout * @wdt_chip - Wathcdog chip instance * @link - Link in registered watchdog instance list */ struct stm32_iwdg_device { struct io_pa_va base; struct clk *clk_pclk; struct clk *clk_lsi; uint32_t flags; unsigned long timeout; struct wdt_chip wdt_chip; SLIST_ENTRY(stm32_iwdg_device) link; }; static SLIST_HEAD(iwdg_dev_list_head, stm32_iwdg_device) iwdg_dev_list = SLIST_HEAD_INITIALIZER(iwdg_dev_list_head); static vaddr_t get_base(struct stm32_iwdg_device *iwdg) { return io_pa_or_va(&iwdg->base, 1); } static bool is_assigned_to_nsec(struct stm32_iwdg_device *iwdg) { return iwdg->flags & IWDG_FLAGS_NON_SECURE; } static void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg) { iwdg->flags |= IWDG_FLAGS_ENABLED; } static bool iwdg_wdt_is_enabled(struct stm32_iwdg_device *iwdg) { return iwdg->flags & IWDG_FLAGS_ENABLED; } /* Return counter value to related to input timeout in seconds, or 0 on error */ static uint32_t iwdg_timeout_cnt(struct stm32_iwdg_device *iwdg, unsigned long to_sec) { uint64_t reload = (uint64_t)to_sec * clk_get_rate(iwdg->clk_lsi); uint64_t cnt = (reload / IWDG_PRESCALER_256) - 1; /* Be safe and expect any counter to be above 2 */ if (cnt > IWDG_CNT_MASK || cnt < 3) return 0; return cnt; } /* Wait IWDG programming completes */ static TEE_Result iwdg_wait_sync(struct stm32_iwdg_device *iwdg) { uint64_t timeout_ref = timeout_init_us(IWDG_TIMEOUT_US); vaddr_t iwdg_base = get_base(iwdg); while (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK) if (timeout_elapsed(timeout_ref)) break; if (io_read32(iwdg_base + IWDG_SR_OFFSET) & IWDG_SR_UPDATE_MASK) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result configure_timeout(struct stm32_iwdg_device *iwdg) { TEE_Result res = TEE_ERROR_GENERIC; vaddr_t iwdg_base = get_base(iwdg); uint32_t rlr_value = 0; assert(iwdg_wdt_is_enabled(iwdg)); rlr_value = iwdg_timeout_cnt(iwdg, iwdg->timeout); if (!rlr_value) return TEE_ERROR_GENERIC; io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_ACCESS_KEY); io_write32(iwdg_base + IWDG_PR_OFFSET, IWDG_PR_DIV_256); io_write32(iwdg_base + IWDG_RLR_OFFSET, rlr_value); io_write32(iwdg_base + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); res = iwdg_wait_sync(iwdg); return res; } static void iwdg_start(struct stm32_iwdg_device *iwdg) { io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_START_KEY); iwdg_wdt_set_enabled(iwdg); } static void iwdg_refresh(struct stm32_iwdg_device *iwdg) { io_write32(get_base(iwdg) + IWDG_KR_OFFSET, IWDG_KR_RELOAD_KEY); } /* Operators for watchdog OP-TEE interface */ static struct stm32_iwdg_device *wdt_chip_to_iwdg(struct wdt_chip *chip) { return container_of(chip, struct stm32_iwdg_device, wdt_chip); } static TEE_Result iwdg_wdt_init(struct wdt_chip *chip, unsigned long *min_timeout, unsigned long *max_timeout) { struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); unsigned long rate = clk_get_rate(iwdg->clk_lsi); if (!rate) return TEE_ERROR_GENERIC; /* Be safe and expect any counter to be above 2 */ *min_timeout = 3 * IWDG_PRESCALER_256 / rate; *max_timeout = (IWDG_CNT_MASK + 1) * IWDG_PRESCALER_256 / rate; return TEE_SUCCESS; } static void iwdg_wdt_start(struct wdt_chip *chip) { struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); iwdg_start(iwdg); if (configure_timeout(iwdg)) panic(); } static void iwdg_wdt_refresh(struct wdt_chip *chip) { struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); iwdg_refresh(iwdg); } static TEE_Result iwdg_wdt_set_timeout(struct wdt_chip *chip, unsigned long timeout) { struct stm32_iwdg_device *iwdg = wdt_chip_to_iwdg(chip); if (!iwdg_timeout_cnt(iwdg, timeout)) return TEE_ERROR_BAD_PARAMETERS; iwdg->timeout = timeout; if (iwdg_wdt_is_enabled(iwdg)) { TEE_Result res = TEE_ERROR_GENERIC; res = configure_timeout(iwdg); if (res) return res; } return TEE_SUCCESS; } static const struct wdt_ops stm32_iwdg_ops = { .init = iwdg_wdt_init, .start = iwdg_wdt_start, .ping = iwdg_wdt_refresh, .set_timeout = iwdg_wdt_set_timeout, }; DECLARE_KEEP_PAGER(stm32_iwdg_ops); /* Driver initialization */ static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg, const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; struct dt_node_info dt_info = { }; const fdt32_t *cuint = NULL; fdt_fill_device_info(fdt, &dt_info, node); if (dt_info.reg == DT_INFO_INVALID_REG || dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) panic(); res = clk_dt_get_by_name(fdt, node, "pclk", &iwdg->clk_pclk); if (res) return res; res = clk_dt_get_by_name(fdt, node, "lsi", &iwdg->clk_lsi); if (res) return res; if (dt_info.status == DT_STATUS_OK_NSEC) iwdg->flags |= IWDG_FLAGS_NON_SECURE; /* Get IOMEM address */ iwdg->base.pa = dt_info.reg; if (iwdg->flags & IWDG_FLAGS_NON_SECURE) io_pa_or_va_nsec(&iwdg->base, dt_info.reg_size); else io_pa_or_va_secure(&iwdg->base, dt_info.reg_size); assert(iwdg->base.va); /* Get and check timeout value */ cuint = fdt_getprop(fdt, node, "timeout-sec", NULL); if (!cuint) return TEE_ERROR_BAD_PARAMETERS; iwdg->timeout = (int)fdt32_to_cpu(*cuint); if (!iwdg->timeout) return TEE_ERROR_BAD_PARAMETERS; if (!iwdg_timeout_cnt(iwdg, iwdg->timeout)) { EMSG("Timeout %lu not applicable", iwdg->timeout); return TEE_ERROR_BAD_PARAMETERS; } /* DT can specify low power cases */ if (!fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL)) iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP; if (!fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL)) iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; return TEE_SUCCESS; } /* Platform should override this function to provide IWDG fuses configuration */ TEE_Result __weak stm32_get_iwdg_otp_config(paddr_t pbase __unused, struct stm32_iwdg_otp_data *otp_d) { otp_d->hw_enabled = false; otp_d->disable_on_stop = false; otp_d->disable_on_standby = false; return TEE_SUCCESS; } static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg, const void *fdt, int node) { struct stm32_iwdg_otp_data otp_data = { }; TEE_Result res = TEE_SUCCESS; res = stm32_iwdg_parse_fdt(iwdg, fdt, node); if (res) return res; res = stm32_get_iwdg_otp_config(iwdg->base.pa, &otp_data); if (res) return res; if (otp_data.hw_enabled) iwdg->flags |= IWDG_FLAGS_HW_ENABLED; if (otp_data.disable_on_stop) iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STOP; if (otp_data.disable_on_standby) iwdg->flags |= IWDG_FLAGS_DISABLE_ON_STANDBY; /* Enable watchdog source and bus clocks once for all */ clk_enable(iwdg->clk_lsi); clk_enable(iwdg->clk_pclk); if (otp_data.hw_enabled) { iwdg->flags |= IWDG_FLAGS_ENABLED; /* Configure timeout if watchdog is already enabled */ res = configure_timeout(iwdg); if (res) return res; iwdg_refresh(iwdg); } return TEE_SUCCESS; } static TEE_Result stm32_iwdg_register(struct stm32_iwdg_device *iwdg) { TEE_Result res = TEE_ERROR_GENERIC; if (is_assigned_to_nsec(iwdg)) { stm32mp_register_non_secure_periph_iomem(iwdg->base.pa); } else { stm32mp_register_secure_periph_iomem(iwdg->base.pa); /* Expose watchdog runtime service only to secure IWDG */ iwdg->wdt_chip.ops = &stm32_iwdg_ops; res = watchdog_register(&iwdg->wdt_chip); if (res) return res; } SLIST_INSERT_HEAD(&iwdg_dev_list, iwdg, link); return TEE_SUCCESS; } static TEE_Result stm32_iwdg_probe(const void *fdt, int node, const void *compat_data __unused) { struct stm32_iwdg_device *iwdg = NULL; TEE_Result res = TEE_SUCCESS; iwdg = calloc(1, sizeof(*iwdg)); if (!iwdg) return TEE_ERROR_OUT_OF_MEMORY; res = stm32_iwdg_setup(iwdg, fdt, node); if (res) goto err; res = stm32_iwdg_register(iwdg); if (res) goto err; return TEE_SUCCESS; err: free(iwdg); return res; } static const struct dt_device_match stm32_iwdg_match_table[] = { { .compatible = "st,stm32mp1-iwdg" }, { } }; DEFINE_DT_DRIVER(stm32_iwdg_dt_driver) = { .name = "stm32-iwdg", .match_table = stm32_iwdg_match_table, .probe = stm32_iwdg_probe, }; optee_os-4.3.0/core/drivers/stm32_rng.c000066400000000000000000000443261464416617300177500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2018-2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RNG_CR U(0x00) #define RNG_SR U(0x04) #define RNG_DR U(0x08) #define RNG_NSCR U(0x0C) #define RNG_HTCR U(0x10) #define RNG_VERR U(0x3F4) #define RNG_CR_RNGEN BIT(2) #define RNG_CR_IE BIT(3) #define RNG_CR_CED BIT(5) #define RNG_CR_CONFIG1 GENMASK_32(11, 8) #define RNG_CR_NISTC BIT(12) #define RNG_CR_POWER_OPTIM BIT(13) #define RNG_CR_CONFIG2 GENMASK_32(15, 13) #define RNG_CR_CLKDIV GENMASK_32(19, 16) #define RNG_CR_CLKDIV_SHIFT U(16) #define RNG_CR_CONFIG3 GENMASK_32(25, 20) #define RNG_CR_CONDRST BIT(30) #define RNG_CR_ENTROPY_SRC_MASK (RNG_CR_CONFIG1 | RNG_CR_NISTC | \ RNG_CR_CONFIG2 | RNG_CR_CONFIG3) #define RNG_SR_DRDY BIT(0) #define RNG_SR_CECS BIT(1) #define RNG_SR_SECS BIT(2) #define RNG_SR_CEIS BIT(5) #define RNG_SR_SEIS BIT(6) #define RNG_NSCR_MASK GENMASK_32(17, 0) #define RNG_VERR_MINOR_MASK GENMASK_32(3, 0) #define RNG_VERR_MAJOR_MASK GENMASK_32(7, 4) #define RNG_VERR_MAJOR_SHIFT U(4) #if TRACE_LEVEL > TRACE_DEBUG #define RNG_READY_TIMEOUT_US U(100000) #else #define RNG_READY_TIMEOUT_US U(10000) #endif #define RNG_RESET_TIMEOUT_US U(1000) #define RNG_FIFO_BYTE_DEPTH U(16) #define RNG_CONFIG_MASK (RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | \ RNG_CR_CLKDIV) struct stm32_rng_driver_data { unsigned long max_noise_clk_freq; unsigned long nb_clock; uint32_t cr; uint32_t nscr; uint32_t htcr; bool has_power_optim; bool has_cond_reset; }; struct stm32_rng_instance { struct io_pa_va base; struct clk *clock; struct clk *bus_clock; struct rstctrl *rstctrl; const struct stm32_rng_driver_data *ddata; unsigned int lock; uint64_t error_to_ref; uint32_t pm_cr; uint32_t pm_health; uint32_t pm_noise_ctrl; uint32_t health_test_conf; uint32_t noise_ctrl_conf; uint32_t rng_config; bool release_post_boot; bool clock_error; bool error_conceal; }; /* Expect at most a single RNG instance */ static struct stm32_rng_instance *stm32_rng; static vaddr_t get_base(void) { assert(stm32_rng); return io_pa_or_va(&stm32_rng->base, 1); } /* * Extracts from the STM32 RNG specification when RNG supports CONDRST. * * When a noise source (or seed) error occurs, the RNG stops generating * random numbers and sets to “1” both SEIS and SECS bits to indicate * that a seed error occurred. (...) * * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield * description for details). This step is needed only if SECS is set. * Indeed, when SEIS is set and SECS is cleared it means RNG performed * the reset automatically (auto-reset). * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST * to be cleared in the RNG_CR register, then confirm that SEIS is * cleared in the RNG_SR register. Otherwise just clear SEIS bit in * the RNG_SR register. * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be * cleared by RNG. The random number generation is now back to normal. */ static void conceal_seed_error_cond_reset(void) { struct stm32_rng_instance *dev = stm32_rng; vaddr_t rng_base = get_base(); if (!dev->error_conceal) { uint32_t sr = io_read32(rng_base + RNG_SR); if (sr & RNG_SR_SECS) { /* Conceal by resetting the subsystem (step 1.) */ io_setbits32(rng_base + RNG_CR, RNG_CR_CONDRST); io_clrbits32(rng_base + RNG_CR, RNG_CR_CONDRST); /* Arm timeout for error_conceal sequence */ dev->error_to_ref = timeout_init_us(RNG_READY_TIMEOUT_US); dev->error_conceal = true; } else { /* RNG auto-reset (step 2.) */ io_clrbits32(rng_base + RNG_SR, RNG_SR_SEIS); } } else { /* Measure time before possible reschedule */ bool timed_out = timeout_elapsed(dev->error_to_ref); /* Wait CONDRST is cleared (step 2.) */ if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) { if (timed_out) panic(); /* Wait subsystem reset cycle completes */ return; } /* Check SEIS is cleared (step 2.) */ if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) panic(); /* Wait SECS is cleared (step 3.) */ if (io_read32(rng_base + RNG_SR) & RNG_SR_SECS) { if (timed_out) panic(); /* Wait subsystem reset cycle completes */ return; } dev->error_conceal = false; } } /* * Extracts from the STM32 RNG specification, when CONDRST is not supported * * When a noise source (or seed) error occurs, the RNG stops generating * random numbers and sets to “1” both SEIS and SECS bits to indicate * that a seed error occurred. (...) * * The following sequence shall be used to fully recover from a seed * error after the RNG initialization: * 1. Clear the SEIS bit by writing it to “0”. * 2. Read out 12 words from the RNG_DR register, and discard each of * them in order to clean the pipeline. * 3. Confirm that SEIS is still cleared. Random number generation is * back to normal. */ static void conceal_seed_error_sw_reset(void) { vaddr_t rng_base = get_base(); size_t i = 0; io_clrbits32(rng_base + RNG_SR, RNG_SR_SEIS); for (i = 12; i != 0; i--) (void)io_read32(rng_base + RNG_DR); if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) panic("RNG noise"); } static void conceal_seed_error(void) { if (stm32_rng->ddata->has_cond_reset) conceal_seed_error_cond_reset(); else conceal_seed_error_sw_reset(); } static TEE_Result read_available(vaddr_t rng_base, uint8_t *out, size_t *size) { struct stm32_rng_instance *dev = stm32_rng; uint8_t *buf = NULL; size_t req_size = 0; size_t len = 0; if (dev->error_conceal || io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) conceal_seed_error(); if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) { FMSG("RNG not ready"); return TEE_ERROR_NO_DATA; } if (io_read32(rng_base + RNG_SR) & RNG_SR_SEIS) { FMSG("RNG noise error"); return TEE_ERROR_NO_DATA; } buf = out; req_size = MIN(RNG_FIFO_BYTE_DEPTH, *size); len = req_size; /* RNG is ready: read up to 4 32bit words */ while (len) { uint32_t data32 = 0; size_t sz = MIN(len, sizeof(uint32_t)); if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY)) break; data32 = io_read32(rng_base + RNG_DR); /* Late seed error case: DR being 0 is an error status */ if (!data32) { conceal_seed_error(); return TEE_ERROR_NO_DATA; } memcpy(buf, &data32, sz); buf += sz; len -= sz; } *size = req_size - len; return TEE_SUCCESS; } static uint32_t stm32_rng_clock_freq_restrain(void) { struct stm32_rng_instance *dev = stm32_rng; unsigned long clock_rate = 0; uint32_t clock_div = 0; clock_rate = clk_get_rate(dev->clock); /* * Get the exponent to apply on the CLKDIV field in RNG_CR register * No need to handle the case when clock-div > 0xF as it is physically * impossible */ while ((clock_rate >> clock_div) > dev->ddata->max_noise_clk_freq) clock_div++; DMSG("RNG clk rate : %lu", clk_get_rate(dev->clock) >> clock_div); return clock_div; } static TEE_Result init_rng(void) { vaddr_t rng_base = get_base(); uint32_t cr_ced_mask = 0; uint32_t value = 0; if (!stm32_rng->clock_error) cr_ced_mask = RNG_CR_CED; /* Clean error indications */ io_write32(rng_base + RNG_SR, 0); if (stm32_rng->ddata->has_cond_reset) { uint32_t clock_div = stm32_rng_clock_freq_restrain(); /* * Keep default RNG configuration if none was specified. * 0 is an invalid value as it disables all entropy sources. */ if (!stm32_rng->rng_config) stm32_rng->rng_config = io_read32(rng_base + RNG_CR) & RNG_CR_ENTROPY_SRC_MASK; /* * Configuration must be set in the same access that sets * RNG_CR_CONDRST bit. Otherwise, the configuration setting is * not taken into account. CONFIGLOCK bit is always cleared at * this stage. */ io_clrsetbits32(rng_base + RNG_CR, RNG_CONFIG_MASK, stm32_rng->rng_config | RNG_CR_CONDRST | cr_ced_mask | SHIFT_U32(clock_div, RNG_CR_CLKDIV_SHIFT)); /* * Write health test and noise source control configuration * according to current RNG entropy source configuration */ if (stm32_rng->noise_ctrl_conf) io_write32(rng_base + RNG_NSCR, stm32_rng->noise_ctrl_conf); if (stm32_rng->health_test_conf) io_write32(rng_base + RNG_HTCR, stm32_rng->health_test_conf); io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); if (IO_READ32_POLL_TIMEOUT(rng_base + RNG_CR, value, !(value & RNG_CR_CONDRST), 0, RNG_READY_TIMEOUT_US)) panic(); DMSG("RNG control register %#"PRIx32, io_read32(rng_base + RNG_CR)); DMSG("RNG noise source control register %#"PRIx32, io_read32(rng_base + RNG_NSCR)); DMSG("RNG health test register %#"PRIx32, io_read32(rng_base + RNG_HTCR)); } else { io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask); } if (IO_READ32_POLL_TIMEOUT(rng_base + RNG_SR, value, value & RNG_SR_DRDY, 0, RNG_READY_TIMEOUT_US)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result stm32_rng_read(uint8_t *out, size_t size) { TEE_Result rc = TEE_ERROR_GENERIC; bool burst_timeout = false; uint64_t timeout_ref = 0; uint32_t exceptions = 0; uint8_t *out_ptr = out; vaddr_t rng_base = 0; size_t out_size = 0; if (!stm32_rng) { DMSG("No RNG"); return TEE_ERROR_NOT_SUPPORTED; } rc = clk_enable(stm32_rng->clock); if (rc) return rc; if (stm32_rng->bus_clock) { rc = clk_enable(stm32_rng->bus_clock); if (rc) { clk_disable(stm32_rng->clock); return rc; } } rng_base = get_base(); /* Arm timeout */ timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); burst_timeout = false; while (out_size < size) { /* Read by chunks of the size the RNG FIFO depth */ size_t sz = size - out_size; exceptions = may_spin_lock(&stm32_rng->lock); rc = read_available(rng_base, out_ptr, &sz); /* Raise timeout only if we failed to get some samples */ assert(!rc || rc == TEE_ERROR_NO_DATA); if (rc) burst_timeout = timeout_elapsed(timeout_ref); may_spin_unlock(&stm32_rng->lock, exceptions); if (burst_timeout) { rc = TEE_ERROR_GENERIC; goto out; } if (!rc) { out_size += sz; out_ptr += sz; /* Re-arm timeout */ timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); burst_timeout = false; } } out: assert(!rc || rc == TEE_ERROR_GENERIC); clk_disable(stm32_rng->clock); if (stm32_rng->bus_clock) clk_disable(stm32_rng->bus_clock); return rc; } #ifdef CFG_WITH_SOFTWARE_PRNG /* Override weak plat_rng_init with platform handler to seed PRNG */ void plat_rng_init(void) { uint8_t seed[RNG_FIFO_BYTE_DEPTH] = { }; if (stm32_rng_read(seed, sizeof(seed))) panic(); if (crypto_rng_init(seed, sizeof(seed))) panic(); DMSG("PRNG seeded with RNG"); } #else TEE_Result hw_get_random_bytes(void *out, size_t size) { return stm32_rng_read(out, size); } void plat_rng_init(void) { } #endif static TEE_Result stm32_rng_pm_resume(void) { vaddr_t base = get_base(); /* Clean error indications */ io_write32(base + RNG_SR, 0); if (stm32_rng->ddata->has_cond_reset) { uint64_t timeout_ref = 0; /* * Configuration must be set in the same access that sets * RNG_CR_CONDRST bit. Otherwise, the configuration setting is * not taken into account. CONFIGLOCK bit is always cleared in * this configuration. */ io_write32(base + RNG_CR, stm32_rng->pm_cr | RNG_CR_CONDRST); /* Restore health test and noise control configuration */ io_write32(base + RNG_NSCR, stm32_rng->pm_noise_ctrl); io_write32(base + RNG_HTCR, stm32_rng->pm_health); io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); while (io_read32(base + RNG_CR) & RNG_CR_CONDRST) if (timeout_elapsed(timeout_ref)) break; if (io_read32(base + RNG_CR) & RNG_CR_CONDRST) panic(); } else { io_write32(base + RNG_CR, RNG_CR_RNGEN | stm32_rng->pm_cr); } return TEE_SUCCESS; } static TEE_Result stm32_rng_pm_suspend(void) { vaddr_t rng_base = get_base(); stm32_rng->pm_cr = io_read32(rng_base + RNG_CR); if (stm32_rng->ddata->has_cond_reset) { stm32_rng->pm_health = io_read32(rng_base + RNG_HTCR); stm32_rng->pm_noise_ctrl = io_read32(rng_base + RNG_NSCR); } if (stm32_rng->ddata->has_power_optim) { uint64_t timeout_ref = 0; /* * As per reference manual, it is recommended to set * RNG_CONFIG2[bit0] when RNG power consumption is critical. */ io_setbits32(rng_base + RNG_CR, RNG_CR_POWER_OPTIM | RNG_CR_CONDRST); io_clrbits32(rng_base + RNG_CR, RNG_CR_CONDRST); timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US); while (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) if (timeout_elapsed(timeout_ref)) break; if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST) panic(); } else { io_clrbits32(rng_base + RNG_CR, RNG_CR_RNGEN); } return TEE_SUCCESS; } static TEE_Result stm32_rng_pm(enum pm_op op, unsigned int pm_hint __unused, const struct pm_callback_handle *pm_handle __unused) { TEE_Result res = TEE_ERROR_GENERIC; assert(stm32_rng && (op == PM_OP_SUSPEND || op == PM_OP_RESUME)); res = clk_enable(stm32_rng->clock); if (res) return res; if (stm32_rng->bus_clock) { res = clk_enable(stm32_rng->bus_clock); if (res) { clk_disable(stm32_rng->clock); return res; } } if (op == PM_OP_RESUME) res = stm32_rng_pm_resume(); else res = stm32_rng_pm_suspend(); clk_disable(stm32_rng->clock); if (stm32_rng->bus_clock) clk_disable(stm32_rng->bus_clock); return res; } DECLARE_KEEP_PAGER(stm32_rng_pm); static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; struct dt_node_info dt_rng = { }; fdt_fill_device_info(fdt, &dt_rng, node); if (dt_rng.reg == DT_INFO_INVALID_REG) return TEE_ERROR_BAD_PARAMETERS; stm32_rng->base.pa = dt_rng.reg; stm32_rng->base.va = io_pa_or_va_secure(&stm32_rng->base, dt_rng.reg_size); assert(stm32_rng->base.va); res = rstctrl_dt_get_by_index(fdt, node, 0, &stm32_rng->rstctrl); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) return res; if (stm32_rng->ddata->nb_clock > 1) { res = clk_dt_get_by_name(fdt, node, "rng_clk", &stm32_rng->clock); if (res) return res; res = clk_dt_get_by_name(fdt, node, "rng_hclk", &stm32_rng->bus_clock); if (res) return res; } else { res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock); if (res) return res; } if (fdt_getprop(fdt, node, "clock-error-detect", NULL)) stm32_rng->clock_error = true; /* Release device if not used after initialization */ stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG); stm32_rng->rng_config = stm32_rng->ddata->cr; if (stm32_rng->rng_config & ~RNG_CR_ENTROPY_SRC_MASK) panic("Incorrect entropy source configuration"); stm32_rng->health_test_conf = stm32_rng->ddata->htcr; stm32_rng->noise_ctrl_conf = stm32_rng->ddata->nscr; if (stm32_rng->noise_ctrl_conf & ~RNG_NSCR_MASK) panic("Incorrect noise source control configuration"); return TEE_SUCCESS; } static TEE_Result stm32_rng_probe(const void *fdt, int offs, const void *compat_data) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int __maybe_unused version = 0; /* Expect a single RNG instance */ assert(!stm32_rng); stm32_rng = calloc(1, sizeof(*stm32_rng)); if (!stm32_rng) panic(); stm32_rng->ddata = compat_data; assert(stm32_rng->ddata); res = stm32_rng_parse_fdt(fdt, offs); if (res) goto err; res = clk_enable(stm32_rng->clock); if (res) goto err; if (stm32_rng->bus_clock) { res = clk_enable(stm32_rng->bus_clock); if (res) { clk_disable(stm32_rng->clock); goto err; } } version = io_read32(get_base() + RNG_VERR); DMSG("RNG version Major %u, Minor %u", (version & RNG_VERR_MAJOR_MASK) >> RNG_VERR_MAJOR_SHIFT, version & RNG_VERR_MINOR_MASK); if (stm32_rng->rstctrl && rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) { res = TEE_ERROR_GENERIC; goto err_clk; } if (stm32_rng->rstctrl && rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) { res = TEE_ERROR_GENERIC; goto err_clk; } res = init_rng(); if (res) goto err_clk; clk_disable(stm32_rng->clock); if (stm32_rng->bus_clock) clk_disable(stm32_rng->bus_clock); if (stm32_rng->release_post_boot) stm32mp_register_non_secure_periph_iomem(stm32_rng->base.pa); else stm32mp_register_secure_periph_iomem(stm32_rng->base.pa); /* Power management implementation expects both or none are set */ assert(stm32_rng->ddata->has_power_optim == stm32_rng->ddata->has_cond_reset); register_pm_core_service_cb(stm32_rng_pm, &stm32_rng, "rng-service"); return TEE_SUCCESS; err_clk: clk_disable(stm32_rng->clock); if (stm32_rng->bus_clock) clk_disable(stm32_rng->bus_clock); err: free(stm32_rng); stm32_rng = NULL; return res; } static const struct stm32_rng_driver_data mp13_data[] = { { .max_noise_clk_freq = U(48000000), .nb_clock = 1, .has_cond_reset = true, .has_power_optim = true, .cr = 0x00F00D00, .nscr = 0x2B5BB, .htcr = 0x969D, }, }; static const struct stm32_rng_driver_data mp15_data[] = { { .max_noise_clk_freq = U(48000000), .nb_clock = 1, .has_cond_reset = false, .has_power_optim = false, }, }; DECLARE_KEEP_PAGER(mp15_data); static const struct stm32_rng_driver_data mp25_data[] = { { .max_noise_clk_freq = U(48000000), .nb_clock = 2, .has_cond_reset = true, .has_power_optim = true, .cr = 0x00F00D00, .nscr = 0x2B5BB, .htcr = 0x969D, }, }; static const struct dt_device_match rng_match_table[] = { { .compatible = "st,stm32-rng", .compat_data = &mp15_data }, { .compatible = "st,stm32mp13-rng", .compat_data = &mp13_data }, { .compatible = "st,stm32mp25-rng", .compat_data = &mp25_data }, { } }; DEFINE_DT_DRIVER(stm32_rng_dt_driver) = { .name = "stm32_rng", .match_table = rng_match_table, .probe = stm32_rng_probe, }; static TEE_Result stm32_rng_release(void) { if (stm32_rng && stm32_rng->release_post_boot) { DMSG("Release RNG driver"); free(stm32_rng); stm32_rng = NULL; } return TEE_SUCCESS; } release_init_resource(stm32_rng_release); optee_os-4.3.0/core/drivers/stm32_shared_io.c000066400000000000000000000014461464416617300211130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2022, STMicroelectronics */ #include #include #include #include static unsigned int shregs_lock = SPINLOCK_UNLOCK; static uint32_t lock_stm32shregs(void) { return may_spin_lock(&shregs_lock); } static void unlock_stm32shregs(uint32_t exceptions) { may_spin_unlock(&shregs_lock, exceptions); } void io_mask32_stm32shregs(vaddr_t va, uint32_t value, uint32_t mask) { uint32_t exceptions = lock_stm32shregs(); io_mask32(va, value, mask); unlock_stm32shregs(exceptions); } void io_clrsetbits32_stm32shregs(vaddr_t va, uint32_t clr, uint32_t set) { uint32_t exceptions = lock_stm32shregs(); io_clrsetbits32(va, clr, set); unlock_stm32shregs(exceptions); } optee_os-4.3.0/core/drivers/stm32_tamp.c000066400000000000000000000210461464416617300201150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2021-2022, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include /* STM32 Registers */ #define _TAMP_CR1 0x00U #define _TAMP_CR2 0x04U #define _TAMP_CR3 0x08U #define _TAMP_FLTCR 0x0CU #define _TAMP_ATCR1 0x10U #define _TAMP_ATSEEDR 0x14U #define _TAMP_ATOR 0x18U #define _TAMP_ATCR2 0x1CU #define _TAMP_SECCFGR 0x20U #define _TAMP_SMCR 0x20U #define _TAMP_PRIVCFGR 0x24U #define _TAMP_IER 0x2CU #define _TAMP_SR 0x30U #define _TAMP_MISR 0x34U #define _TAMP_SMISR 0x38U #define _TAMP_SCR 0x3CU #define _TAMP_COUNTR 0x40U #define _TAMP_COUNT2R 0x44U #define _TAMP_OR 0x50U #define _TAMP_ERCFGR 0X54U #define _TAMP_HWCFGR2 0x3ECU #define _TAMP_HWCFGR1 0x3F0U #define _TAMP_VERR 0x3F4U #define _TAMP_IPIDR 0x3F8U #define _TAMP_SIDR 0x3FCU /* _TAMP_SECCFGR bit fields */ #define _TAMP_SECCFGR_BKPRWSEC_MASK GENMASK_32(7, 0) #define _TAMP_SECCFGR_BKPRWSEC_SHIFT 0U #define _TAMP_SECCFGR_CNT2SEC BIT(14) #define _TAMP_SECCFGR_CNT1SEC BIT(15) #define _TAMP_SECCFGR_BKPWSEC_MASK GENMASK_32(23, 16) #define _TAMP_SECCFGR_BKPWSEC_SHIFT 16U #define _TAMP_SECCFGR_BHKLOCK BIT(30) #define _TAMP_SECCFGR_TAMPSEC BIT(31) #define _TAMP_SECCFGR_BUT_BKP_MASK (GENMASK_32(31, 30) | \ GENMASK_32(15, 14)) /* _TAMP_SMCR bit fields */ #define _TAMP_SMCR_BKPRWDPROT_MASK GENMASK_32(7, 0) #define _TAMP_SMCR_BKPRWDPROT_SHIFT 0U #define _TAMP_SMCR_BKPWDPROT_MASK GENMASK_32(23, 16) #define _TAMP_SMCR_BKPWDPROT_SHIFT 16U #define _TAMP_SMCR_DPROT BIT(31) /* * _TAMP_PRIVCFGR bit fields */ #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ GENMASK_32(15, 14)) /* * _TAMP_PRIVCFGR bit fields */ #define _TAMP_PRIVCFG_CNT2PRIV BIT(14) #define _TAMP_PRIVCFG_CNT1PRIV BIT(15) #define _TAMP_PRIVCFG_BKPRWPRIV BIT(29) #define _TAMP_PRIVCFG_BKPWPRIV BIT(30) #define _TAMP_PRIVCFG_TAMPPRIV BIT(31) #define _TAMP_PRIVCFGR_MASK (GENMASK_32(31, 29) | \ GENMASK_32(15, 14)) /* _TAMP_HWCFGR2 bit fields */ #define _TAMP_HWCFGR2_TZ GENMASK_32(11, 8) #define _TAMP_HWCFGR2_OR GENMASK_32(7, 0) /* _TAMP_HWCFGR1 bit fields */ #define _TAMP_HWCFGR1_BKPREG GENMASK_32(7, 0) #define _TAMP_HWCFGR1_TAMPER GENMASK_32(11, 8) #define _TAMP_HWCFGR1_ACTIVE GENMASK_32(15, 12) #define _TAMP_HWCFGR1_INTERN GENMASK_32(31, 16) #define _TAMP_HWCFGR1_ITAMP_MAX_ID 16U #define _TAMP_HWCFGR1_ITAMP(id) BIT((id) - INT_TAMP1 + 16U) /* _TAMP_VERR bit fields */ #define _TAMP_VERR_MINREV GENMASK_32(3, 0) #define _TAMP_VERR_MAJREV GENMASK_32(7, 4) /* * TAMP instance data * @base - IOMEM base address * @clock - TAMP clock * @it - TAMP interrupt number * @hwconf1 - Copy of TAMP HWCONF1 register content * @hwconf2 - Copy of TAMP HWCONF2 register content * @compat - Reference to compat data passed at driver initialization */ struct stm32_tamp_instance { struct io_pa_va base; struct clk *clock; int it; uint32_t hwconf1; uint32_t hwconf2; struct stm32_tamp_compat *compat; }; /* * Compatibility capabilities * TAMP_HAS_REGISTER_SECCFG - Supports SECCFGR, otherwise supports SMCR register * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register */ #define TAMP_HAS_REGISTER_SECCFG BIT(0) #define TAMP_HAS_REGISTER_PRIVCFGR BIT(1) /* * @nb_monotonic_counter - Number of monotic counter supported * @tags - Bit flags TAMP_HAS_* for compatibily management */ struct stm32_tamp_compat { int nb_monotonic_counter; uint32_t tags; }; /* Expects at most a single instance */ static struct stm32_tamp_instance *stm32_tamp_device; TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf) { struct stm32_tamp_instance *tamp = stm32_tamp_device; vaddr_t base = 0; uint32_t first_z2 = 0; uint32_t first_z3 = 0; if (!tamp) return TEE_ERROR_DEFER_DRIVER_INIT; if (!bkr_conf) return TEE_ERROR_BAD_PARAMETERS; base = io_pa_or_va(&tamp->base, 1); first_z2 = bkr_conf->nb_zone1_regs; first_z3 = bkr_conf->nb_zone1_regs + bkr_conf->nb_zone2_regs; if ((first_z2 > (tamp->hwconf1 & _TAMP_HWCFGR1_BKPREG)) || (first_z3 > (tamp->hwconf1 & _TAMP_HWCFGR1_BKPREG))) return TEE_ERROR_BAD_PARAMETERS; if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_SECCFG)) { io_clrsetbits32(base + _TAMP_SECCFGR, _TAMP_SECCFGR_BKPRWSEC_MASK, (first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) & _TAMP_SECCFGR_BKPRWSEC_MASK); io_clrsetbits32(base + _TAMP_SECCFGR, _TAMP_SECCFGR_BKPWSEC_MASK, (first_z3 << _TAMP_SECCFGR_BKPWSEC_SHIFT) & _TAMP_SECCFGR_BKPWSEC_MASK); } else { io_clrsetbits32(base + _TAMP_SMCR, _TAMP_SMCR_BKPRWDPROT_MASK, (first_z2 << _TAMP_SMCR_BKPRWDPROT_SHIFT) & _TAMP_SMCR_BKPRWDPROT_MASK); io_clrsetbits32(base + _TAMP_SMCR, _TAMP_SMCR_BKPWDPROT_MASK, (first_z3 << _TAMP_SMCR_BKPWDPROT_SHIFT) & _TAMP_SMCR_BKPWDPROT_MASK); } return TEE_SUCCESS; } static void stm32_tamp_set_secure(struct stm32_tamp_instance *tamp, uint32_t mode) { vaddr_t base = io_pa_or_va(&tamp->base, 1); if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_SECCFG)) { io_clrsetbits32(base + _TAMP_SECCFGR, _TAMP_SECCFGR_BUT_BKP_MASK, mode & _TAMP_SECCFGR_BUT_BKP_MASK); } else { /* * Note: MP15 doesn't use SECCFG register and * inverts the secure bit. */ if (mode & _TAMP_SECCFGR_TAMPSEC) io_clrbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); else io_setbits32(base + _TAMP_SMCR, _TAMP_SMCR_DPROT); } } static void stm32_tamp_set_privilege(struct stm32_tamp_instance *tamp, uint32_t mode) { vaddr_t base = io_pa_or_va(&tamp->base, 1); if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_PRIVCFGR)) io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK, mode & _TAMP_PRIVCFGR_MASK); } static TEE_Result stm32_tamp_parse_fdt(struct stm32_tamp_instance *tamp, const void *fdt, int node, const void *compat) { struct dt_node_info dt_tamp = { }; fdt_fill_device_info(fdt, &dt_tamp, node); if (dt_tamp.reg == DT_INFO_INVALID_REG || dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE) return TEE_ERROR_BAD_PARAMETERS; tamp->compat = (struct stm32_tamp_compat *)compat; tamp->it = dt_tamp.interrupt; tamp->base.pa = dt_tamp.reg; io_pa_or_va_secure(&tamp->base, dt_tamp.reg_size); return clk_dt_get_by_index(fdt, node, 0, &tamp->clock); } static TEE_Result stm32_tamp_probe(const void *fdt, int node, const void *compat_data) { struct stm32_tamp_instance *tamp = NULL; uint32_t __maybe_unused revision = 0; TEE_Result res = TEE_SUCCESS; vaddr_t base = 0; tamp = calloc(1, sizeof(*tamp)); if (!tamp) return TEE_ERROR_OUT_OF_MEMORY; res = stm32_tamp_parse_fdt(tamp, fdt, node, compat_data); if (res) goto err; clk_enable(tamp->clock); base = io_pa_or_va(&tamp->base, 1); tamp->hwconf1 = io_read32(base + _TAMP_HWCFGR1); tamp->hwconf2 = io_read32(base + _TAMP_HWCFGR2); revision = io_read32(base + _TAMP_VERR); FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32, (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV); if (!(tamp->hwconf2 & _TAMP_HWCFGR2_TZ)) { EMSG("TAMP doesn't support TrustZone"); res = TEE_ERROR_NOT_SUPPORTED; goto err_clk; } /* * Enforce secure only access to protected TAMP registers. * Allow non-secure access to monotonic counter. */ stm32_tamp_set_secure(tamp, _TAMP_SECCFGR_TAMPSEC); /* * Enforce privilege only access to TAMP registers, backup * registers and monotonic counter. */ stm32_tamp_set_privilege(tamp, _TAMP_PRIVCFG_TAMPPRIV | _TAMP_PRIVCFG_BKPRWPRIV | _TAMP_PRIVCFG_BKPWPRIV); stm32_tamp_device = tamp; return TEE_SUCCESS; err_clk: clk_disable(tamp->clock); err: free(tamp); return res; } static const struct stm32_tamp_compat mp13_compat = { .nb_monotonic_counter = 2, .tags = TAMP_HAS_REGISTER_SECCFG | TAMP_HAS_REGISTER_PRIVCFGR, }; static const struct stm32_tamp_compat mp15_compat = { .nb_monotonic_counter = 1, .tags = 0, }; static const struct dt_device_match stm32_tamp_match_table[] = { { .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat }, { .compatible = "st,stm32-tamp", .compat_data = &mp15_compat }, { } }; DEFINE_DT_DRIVER(stm32_tamp_dt_driver) = { .name = "stm32-tamp", .match_table = stm32_tamp_match_table, .probe = stm32_tamp_probe, }; optee_os-4.3.0/core/drivers/stm32_uart.c000066400000000000000000000115551464416617300201330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2018, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UART_REG_CR1 0x00 /* Control register 1 */ #define UART_REG_CR2 0x04 /* Control register 2 */ #define UART_REG_CR3 0x08 /* Control register 3 */ #define UART_REG_BRR 0x0c /* Baud rate register */ #define UART_REG_RQR 0x18 /* Request register */ #define UART_REG_ISR 0x1c /* Interrupt & status reg. */ #define UART_REG_ICR 0x20 /* Interrupt flag clear reg. */ #define UART_REG_RDR 0x24 /* Receive data register */ #define UART_REG_TDR 0x28 /* Transmit data register */ #define UART_REG_PRESC 0x2c /* Prescaler register */ #define PUTC_TIMEOUT_US 1000 #define FLUSH_TIMEOUT_US 16000 /* * Uart Interrupt & status register bits * * Bit 5 RXNE: Read data register not empty/RXFIFO not empty * Bit 6 TC: Transmission complete * Bit 7 TXE/TXFNF: Transmit data register empty/TXFIFO not full * Bit 23 TXFE: TXFIFO empty */ #define USART_ISR_RXNE_RXFNE BIT(5) #define USART_ISR_TC BIT(6) #define USART_ISR_TXE_TXFNF BIT(7) #define USART_ISR_TXFE BIT(23) static vaddr_t loc_chip_to_base(struct serial_chip *chip) { struct stm32_uart_pdata *pd = NULL; pd = container_of(chip, struct stm32_uart_pdata, chip); return io_pa_or_va(&pd->base, 1); } static void loc_flush(struct serial_chip *chip) { vaddr_t base = loc_chip_to_base(chip); uint64_t timeout = timeout_init_us(FLUSH_TIMEOUT_US); while (!(io_read32(base + UART_REG_ISR) & USART_ISR_TXFE)) if (timeout_elapsed(timeout)) return; } static void loc_putc(struct serial_chip *chip, int ch) { vaddr_t base = loc_chip_to_base(chip); uint64_t timeout = timeout_init_us(PUTC_TIMEOUT_US); while (!(io_read32(base + UART_REG_ISR) & USART_ISR_TXE_TXFNF)) if (timeout_elapsed(timeout)) return; io_write32(base + UART_REG_TDR, ch); } static bool loc_have_rx_data(struct serial_chip *chip) { vaddr_t base = loc_chip_to_base(chip); return io_read32(base + UART_REG_ISR) & USART_ISR_RXNE_RXFNE; } static int loc_getchar(struct serial_chip *chip) { vaddr_t base = loc_chip_to_base(chip); while (!loc_have_rx_data(chip)) ; return io_read32(base + UART_REG_RDR) & 0xff; } static const struct serial_ops stm32_uart_serial_ops = { .flush = loc_flush, .putc = loc_putc, .have_rx_data = loc_have_rx_data, .getchar = loc_getchar, }; DECLARE_KEEP_PAGER(stm32_uart_serial_ops); void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base) { pd->base.pa = base; pd->chip.ops = &stm32_uart_serial_ops; } static void register_secure_uart(struct stm32_uart_pdata *pd) { #ifndef CFG_STM32MP25 stm32mp_register_secure_periph_iomem(pd->base.pa); stm32mp_register_secure_pinctrl(pd->pinctrl); if (pd->pinctrl_sleep) stm32mp_register_secure_pinctrl(pd->pinctrl_sleep); #else stm32_pinctrl_set_secure_cfg(pd->pinctrl, true); if (pd->pinctrl_sleep) stm32_pinctrl_set_secure_cfg(pd->pinctrl, true); #endif } static void register_non_secure_uart(struct stm32_uart_pdata *pd) { #ifndef CFG_STM32MP25 stm32mp_register_non_secure_periph_iomem(pd->base.pa); stm32mp_register_non_secure_pinctrl(pd->pinctrl); if (pd->pinctrl_sleep) stm32mp_register_non_secure_pinctrl(pd->pinctrl_sleep); #else stm32_pinctrl_set_secure_cfg(pd->pinctrl, false); if (pd->pinctrl_sleep) stm32_pinctrl_set_secure_cfg(pd->pinctrl, false); #endif } struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; struct stm32_uart_pdata *pd = NULL; struct dt_node_info info = { }; fdt_fill_device_info(fdt, &info, node); if (info.status == DT_STATUS_DISABLED) return NULL; assert(info.reg != DT_INFO_INVALID_REG && info.reg_size != DT_INFO_INVALID_REG_SIZE); pd = calloc(1, sizeof(*pd)); if (!pd) panic(); pd->chip.ops = &stm32_uart_serial_ops; pd->base.pa = info.reg; pd->secure = (info.status == DT_STATUS_OK_SEC); res = clk_dt_get_by_index(fdt, node, 0, &pd->clock); if (res) { EMSG("Failed to get clock: %#"PRIx32, res); panic(); } res = clk_enable(pd->clock); if (res) panic(); assert(cpu_mmu_enabled()); pd->base.va = (vaddr_t)phys_to_virt(pd->base.pa, pd->secure ? MEM_AREA_IO_SEC : MEM_AREA_IO_NSEC, info.reg_size); res = pinctrl_get_state_by_name(fdt, node, "default", &pd->pinctrl); if (res) panic(); res = pinctrl_get_state_by_name(fdt, node, "sleep", &pd->pinctrl_sleep); if (res && res != TEE_ERROR_ITEM_NOT_FOUND) panic(); res = pinctrl_apply_state(pd->pinctrl); if (res) panic(); if (pd->secure) register_secure_uart(pd); else register_non_secure_uart(pd); return pd; } optee_os-4.3.0/core/drivers/stm32mp15_huk.c000066400000000000000000000123141464416617300204440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited * Copyright (c) 2022, Foundries.io Limited */ #include #include #include #include #include #include #include #include #include #include #define HUK_NB_OTP (HW_UNIQUE_KEY_LENGTH / sizeof(uint32_t)) static bool stm32mp15_huk_init; static TEE_Result stm32mp15_read_uid(uint32_t *uid) { TEE_Result ret = TEE_ERROR_GENERIC; uint32_t *q = uid; uint32_t otp_idx = 0; size_t __maybe_unused sz = 0; uint8_t __maybe_unused offset = 0; ret = stm32_bsec_find_otp_in_nvmem_layout("uid_otp", &otp_idx, &offset, &sz); if (ret) return ret; assert(sz == 3 * 32); assert(offset == 0); /* * Shadow memory for UID words might not be locked: to guarante that * the final values are read we must lock them. */ if (stm32_bsec_set_sw_lock(otp_idx) || stm32_bsec_shadow_read_otp(q++, otp_idx)) return TEE_ERROR_GENERIC; if (stm32_bsec_set_sw_lock(otp_idx + 1) || stm32_bsec_shadow_read_otp(q++, otp_idx + 1)) return TEE_ERROR_GENERIC; if (stm32_bsec_set_sw_lock(otp_idx + 2) || stm32_bsec_shadow_read_otp(q++, otp_idx + 2)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result stm32mp15_read_otp(uint32_t otp, uint32_t *key, bool *locked) { bool tmp = true; uint32_t state = 0; if (stm32_bsec_get_state(&state)) panic(); if (state != BSEC_STATE_SEC_CLOSED) { /* * When the device is not closed, the shadow memory for these * words might not be locked: check and report them */ if (stm32_bsec_read_permanent_lock(otp, &tmp)) return TEE_ERROR_GENERIC; if (tmp && stm32_bsec_read_sw_lock(otp, &tmp)) return TEE_ERROR_GENERIC; } if (stm32_bsec_shadow_read_otp(key, otp)) return TEE_ERROR_GENERIC; *locked = *locked && tmp; return TEE_SUCCESS; } /* * AES-GCM: nonce must be unique per message and key. * * This function always uses the same key - once its locked - with the same * unique message hence the nonce can be any constant. */ static TEE_Result aes_gcm_encrypt_uid(uint8_t *key, size_t key_len, uint8_t *out, size_t *out_len) { TEE_Result ret = TEE_ERROR_GENERIC; const uint8_t nonce[12] = { 0x55 }; uint32_t uid[4] = { 0 }; uint8_t tag[16] = { 0 }; size_t nonce_len = sizeof(nonce); size_t tag_len = sizeof(tag); size_t uid_len = sizeof(uid); void *ctx = NULL; ret = stm32mp15_read_uid(uid); if (ret) goto out; ret = crypto_authenc_alloc_ctx(&ctx, TEE_ALG_AES_GCM); if (ret) goto out; ret = crypto_authenc_init(ctx, TEE_MODE_ENCRYPT, key, key_len, nonce, nonce_len, TEE_AES_BLOCK_SIZE, 0, uid_len); if (ret) goto out_free_ctx; ret = crypto_authenc_enc_final(ctx, (uint8_t *)uid, sizeof(uid), out, out_len, tag, &tag_len); if (ret) goto out_free_ctx; crypto_authenc_final(ctx); out_free_ctx: crypto_authenc_free_ctx(ctx); out: if (ret) memzero_explicit(out, *out_len); return ret; } static __maybe_unused TEE_Result pos_from_dt(uint32_t otp_id[HUK_NB_OTP]) { TEE_Result ret = TEE_SUCCESS; uint32_t otp_start = 0; size_t sz = 0; uint8_t offset = 0; size_t i = 0; ret = stm32_bsec_find_otp_in_nvmem_layout("huk-otp", &otp_start, &offset, &sz); if (ret) return ret; if (sz != (HW_UNIQUE_KEY_LENGTH * CHAR_BIT) || offset != 0) return TEE_ERROR_SECURITY; for (i = 0; i < HUK_NB_OTP; i++) otp_id[i] = otp_start + i; return TEE_SUCCESS; } static TEE_Result get_otp_pos(uint32_t otp_id[HUK_NB_OTP]) { #ifdef CFG_STM32_HUK_FROM_DT return pos_from_dt(otp_id); #else /* CFG_STM32_HUK_FROM_DT */ static_assert(CFG_STM32MP15_HUK_BSEC_KEY_0 < STM32MP1_OTP_MAX_ID); static_assert(CFG_STM32MP15_HUK_BSEC_KEY_1 < STM32MP1_OTP_MAX_ID); static_assert(CFG_STM32MP15_HUK_BSEC_KEY_2 < STM32MP1_OTP_MAX_ID); static_assert(CFG_STM32MP15_HUK_BSEC_KEY_3 < STM32MP1_OTP_MAX_ID); otp_id[0] = CFG_STM32MP15_HUK_BSEC_KEY_0; otp_id[1] = CFG_STM32MP15_HUK_BSEC_KEY_1; otp_id[2] = CFG_STM32MP15_HUK_BSEC_KEY_2; otp_id[3] = CFG_STM32MP15_HUK_BSEC_KEY_3; return TEE_SUCCESS; #endif /* CFG_STM32_HUK_FROM_DT */ } TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { uint32_t otp_key[HUK_NB_OTP] = { }; uint32_t otp_id[HUK_NB_OTP] = { }; size_t len = HW_UNIQUE_KEY_LENGTH; TEE_Result ret = TEE_SUCCESS; uint32_t *key = otp_key; bool lock = true; size_t i = 0; ret = get_otp_pos(otp_id); if (ret) return ret; for (i = 0; i < HUK_NB_OTP; i++) { ret = stm32mp15_read_otp(otp_id[i], key++, &lock); if (ret) goto out; } if (IS_ENABLED(CFG_STM32MP15_HUK_BSEC_KEY)) { static_assert(sizeof(otp_key) == HW_UNIQUE_KEY_LENGTH); memcpy(hwkey->data, otp_key, HW_UNIQUE_KEY_LENGTH); ret = TEE_SUCCESS; goto out; } if (IS_ENABLED(CFG_STM32MP15_HUK_BSEC_DERIVE_UID)) { ret = aes_gcm_encrypt_uid((uint8_t *)otp_key, len, hwkey->data, &len); if (len != HW_UNIQUE_KEY_LENGTH) ret = TEE_ERROR_GENERIC; goto out; } panic(); out: memzero_explicit(otp_key, HW_UNIQUE_KEY_LENGTH); if (!ret && !stm32mp15_huk_init) { stm32mp15_huk_init = true; IMSG("HUK %slocked", lock ? "" : "un"); DHEXDUMP(hwkey->data, HW_UNIQUE_KEY_LENGTH); } return ret; } optee_os-4.3.0/core/drivers/stpmic1.c000066400000000000000000000453531464416617300175130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2016-2020, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #define VOLTAGE_INDEX_INVALID ((unsigned int)~0) struct regul_struct { const char *dt_node_name; const uint16_t *voltage_table; uint8_t voltage_table_size; uint8_t control_reg; uint8_t low_power_reg; uint8_t enable_pos; uint8_t pull_down_reg; uint8_t pull_down_pos; uint8_t mask_reset_reg; uint8_t mask_reset_pos; }; static struct i2c_handle_s *pmic_i2c_handle; static uint16_t pmic_i2c_addr; /* Voltage tables in mV */ static const uint16_t buck1_voltage_table[] = { 725, 725, 725, 725, 725, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500, }; static const uint16_t buck2_voltage_table[] = { 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1050, 1050, 1100, 1100, 1150, 1150, 1200, 1200, 1250, 1250, 1300, 1300, 1350, 1350, 1400, 1400, 1450, 1450, 1500, }; static const uint16_t buck3_voltage_table[] = { 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1100, 1100, 1100, 1100, 1200, 1200, 1200, 1200, 1300, 1300, 1300, 1300, 1400, 1400, 1400, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400, }; static const uint16_t buck4_voltage_table[] = { 600, 625, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, 1300, 1350, 1350, 1400, 1400, 1450, 1450, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400, 3500, 3600, 3700, 3800, 3900, }; static const uint16_t ldo1_voltage_table[] = { 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, }; static const uint16_t ldo2_voltage_table[] = { 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, }; static const uint16_t ldo3_voltage_table[] = { 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3300, 3300, 3300, 3300, 3300, 3300, 500, /* VOUT2/2 (Sink/source mode) */ 0xFFFF, /* VREFDDR */ }; static const uint16_t ldo5_voltage_table[] = { 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, 3400, 3500, 3600, 3700, 3800, 3900, }; static const uint16_t ldo6_voltage_table[] = { 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300, }; static const uint16_t ldo4_voltage_table[] = { 3300, }; static const uint16_t vref_ddr_voltage_table[] = { 3300, }; static const uint16_t fixed_5v_voltage_table[] = { 5000, }; /* Table of Regulators in PMIC SoC */ static const struct regul_struct regulators_table[] = { { .dt_node_name = "buck1", .voltage_table = buck1_voltage_table, .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), .control_reg = BUCK1_CONTROL_REG, .low_power_reg = BUCK1_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down_pos = BUCK1_PULL_DOWN_SHIFT, .mask_reset_reg = MASK_RESET_BUCK_REG, .mask_reset_pos = BUCK1_MASK_RESET_SHIFT, }, { .dt_node_name = "buck2", .voltage_table = buck2_voltage_table, .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), .control_reg = BUCK2_CONTROL_REG, .low_power_reg = BUCK2_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down_pos = BUCK2_PULL_DOWN_SHIFT, .mask_reset_reg = MASK_RESET_BUCK_REG, .mask_reset_pos = BUCK2_MASK_RESET_SHIFT, }, { .dt_node_name = "buck3", .voltage_table = buck3_voltage_table, .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), .control_reg = BUCK3_CONTROL_REG, .low_power_reg = BUCK3_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down_pos = BUCK3_PULL_DOWN_SHIFT, .mask_reset_reg = MASK_RESET_BUCK_REG, .mask_reset_pos = BUCK3_MASK_RESET_SHIFT, }, { .dt_node_name = "buck4", .voltage_table = buck4_voltage_table, .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), .control_reg = BUCK4_CONTROL_REG, .low_power_reg = BUCK4_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .pull_down_reg = BUCK_PULL_DOWN_REG, .pull_down_pos = BUCK4_PULL_DOWN_SHIFT, .mask_reset_reg = MASK_RESET_BUCK_REG, .mask_reset_pos = BUCK4_MASK_RESET_SHIFT, }, { .dt_node_name = "ldo1", .voltage_table = ldo1_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), .control_reg = LDO1_CONTROL_REG, .low_power_reg = LDO1_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = LDO1_MASK_RESET_SHIFT, }, { .dt_node_name = "ldo2", .voltage_table = ldo2_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), .control_reg = LDO2_CONTROL_REG, .low_power_reg = LDO2_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = LDO2_MASK_RESET_SHIFT, }, { .dt_node_name = "ldo3", .voltage_table = ldo3_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), .control_reg = LDO3_CONTROL_REG, .low_power_reg = LDO3_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = LDO3_MASK_RESET_SHIFT, }, { .dt_node_name = "ldo4", .voltage_table = ldo4_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), .control_reg = LDO4_CONTROL_REG, .low_power_reg = LDO4_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = LDO4_MASK_RESET_SHIFT, }, { .dt_node_name = "ldo5", .voltage_table = ldo5_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), .control_reg = LDO5_CONTROL_REG, .low_power_reg = LDO5_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = LDO5_MASK_RESET_SHIFT, }, { .dt_node_name = "ldo6", .voltage_table = ldo6_voltage_table, .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), .control_reg = LDO6_CONTROL_REG, .low_power_reg = LDO6_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = LDO6_MASK_RESET_SHIFT, }, { .dt_node_name = "vref_ddr", .voltage_table = vref_ddr_voltage_table, .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), .control_reg = VREF_DDR_CONTROL_REG, .low_power_reg = VREF_DDR_PWRCTRL_REG, .enable_pos = LDO_BUCK_ENABLE_POS, .mask_reset_reg = MASK_RESET_LDO_REG, .mask_reset_pos = VREF_DDR_MASK_RESET_SHIFT, }, { .dt_node_name = "boost", .voltage_table = fixed_5v_voltage_table, .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), .control_reg = USB_CONTROL_REG, .enable_pos = BOOST_ENABLED_POS, }, { .dt_node_name = "pwr_sw1", .voltage_table = fixed_5v_voltage_table, .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), .control_reg = USB_CONTROL_REG, .enable_pos = USBSW_OTG_SWITCH_ENABLED_POS, }, { .dt_node_name = "pwr_sw2", .voltage_table = fixed_5v_voltage_table, .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), .control_reg = USB_CONTROL_REG, .enable_pos = SWIN_SWOUT_ENABLED_POS, }, }; static const struct regul_struct *get_regulator_data(const char *name) { unsigned int i = 0; for (i = 0; i < ARRAY_SIZE(regulators_table); i++) if (strcmp(name, regulators_table[i].dt_node_name) == 0) return ®ulators_table[i]; DMSG("Regulator %s not found", name); return NULL; } bool stpmic1_regulator_is_valid(const char *name) { return get_regulator_data(name); } void stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, size_t *levels_count) { const struct regul_struct *regul = get_regulator_data(name); assert(regul); if (levels_count) { *levels_count = regul->voltage_table_size; /* Remove last cell 0xFFFF that is not a voltage level */ if (regul->voltage_table == ldo3_voltage_table) (*levels_count)--; } if (levels) *levels = regul->voltage_table; } static size_t voltage_to_index(const char *name, uint16_t millivolts) { const struct regul_struct *regul = get_regulator_data(name); unsigned int i = 0; assert(regul->voltage_table); for (i = 0; i < regul->voltage_table_size; i++) if (regul->voltage_table[i] == millivolts) return i; return VOLTAGE_INDEX_INVALID; } int stpmic1_powerctrl_on(void) { return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, PWRCTRL_PIN_VALID); } int stpmic1_switch_off(void) { return stpmic1_register_update(MAIN_CONTROL_REG, 1, SOFTWARE_SWITCH_OFF_ENABLED); } int stpmic1_regulator_enable(const char *name) { const struct regul_struct *regul = get_regulator_data(name); return stpmic1_register_update(regul->control_reg, BIT(regul->enable_pos), BIT(regul->enable_pos)); } int stpmic1_regulator_disable(const char *name) { const struct regul_struct *regul = get_regulator_data(name); return stpmic1_register_update(regul->control_reg, 0, BIT(regul->enable_pos)); } bool stpmic1_is_regulator_enabled(const char *name) { const struct regul_struct *regul = get_regulator_data(name); uint8_t val = 0; if (stpmic1_register_read(regul->control_reg, &val)) panic(); return val & BIT(regul->enable_pos); } /* Voltage can be set for buck or ldo (except ldo4) regulators */ static uint8_t find_plat_mask(const char *name) { if (!strncmp(name, "buck", 4)) return BUCK_VOLTAGE_MASK; if (!strncmp(name, "ldo", 3) && strcmp(name, "ldo4")) return LDO_VOLTAGE_MASK; return 0; } int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) { size_t voltage_index = voltage_to_index(name, millivolts); const struct regul_struct *regul = get_regulator_data(name); uint8_t mask = 0; if (voltage_index == VOLTAGE_INDEX_INVALID) return -1; mask = find_plat_mask(name); if (!mask) return 0; return stpmic1_register_update(regul->control_reg, voltage_index << LDO_BUCK_VOLTAGE_SHIFT, mask); } int stpmic1_regulator_mask_reset_set(const char *name) { const struct regul_struct *regul = get_regulator_data(name); if (regul->control_reg == USB_CONTROL_REG) { DMSG("No reset for USB control"); return -1; } return stpmic1_register_update(regul->mask_reset_reg, BIT(regul->mask_reset_pos), LDO_BUCK_RESET_MASK << regul->mask_reset_pos); } int stpmic1_bo_enable_cfg(const char *name, struct stpmic1_bo_cfg *cfg) { const struct regul_struct *regul = get_regulator_data(name); cfg->ctrl_reg = regul->control_reg; cfg->enable_pos = regul->enable_pos; return 0; } int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg) { return stpmic1_register_update(cfg->ctrl_reg, BIT(cfg->enable_pos), BIT(cfg->enable_pos)); } /* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ int stpmic1_bo_voltage_cfg(const char *name, uint16_t min_millivolt, struct stpmic1_bo_cfg *cfg) { size_t min_index = voltage_to_index(name, min_millivolt); const struct regul_struct *regul = get_regulator_data(name); uint8_t mask = 0; if (min_index == VOLTAGE_INDEX_INVALID) panic(); mask = find_plat_mask(name); if (!mask) return 1; cfg->ctrl_reg = regul->control_reg; cfg->min_value = min_index << LDO_BUCK_VOLTAGE_SHIFT; cfg->mask = mask; return 0; } int stpmic1_bo_voltage_unpg(struct stpmic1_bo_cfg *cfg) { uint8_t value = 0; assert(cfg->ctrl_reg); if (stpmic1_register_read(cfg->ctrl_reg, &value)) return -1; if ((value & cfg->mask) >= cfg->min_value) return 0; return stpmic1_register_update(cfg->ctrl_reg, cfg->min_value, cfg->mask); } int stpmic1_bo_pull_down_cfg(const char *name, struct stpmic1_bo_cfg *cfg) { const struct regul_struct *regul = get_regulator_data(name); if (!regul->pull_down_reg) { DMSG("No pull down for regu %s", name); panic(); } cfg->pd_reg = regul->pull_down_reg; cfg->pd_value = BIT(regul->pull_down_pos); cfg->pd_mask = LDO_BUCK_PULL_DOWN_MASK << regul->pull_down_pos; return 0; } int stpmic1_bo_pull_down_unpg(struct stpmic1_bo_cfg *cfg) { assert(cfg->pd_reg); return stpmic1_register_update(cfg->pd_reg, cfg->pd_value, cfg->pd_mask); } int stpmic1_bo_mask_reset_cfg(const char *name, struct stpmic1_bo_cfg *cfg) { const struct regul_struct *regul = get_regulator_data(name); if (!regul->mask_reset_reg) { DMSG("No reset mask for regu %s", name); panic(); } cfg->mrst_reg = regul->mask_reset_reg; cfg->mrst_value = BIT(regul->mask_reset_pos); cfg->mrst_mask = LDO_BUCK_RESET_MASK << regul->mask_reset_pos; return 0; } int stpmic1_bo_mask_reset_unpg(struct stpmic1_bo_cfg *cfg) { assert(cfg->mrst_reg); return stpmic1_register_update(cfg->mrst_reg, cfg->mrst_value, cfg->mrst_mask); } int stpmic1_regulator_voltage_get(const char *name) { const struct regul_struct *regul = get_regulator_data(name); uint8_t value = 0; uint8_t mask = 0; mask = find_plat_mask(name); if (!mask) return 0; if (stpmic1_register_read(regul->control_reg, &value)) return -1; value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; if (value > regul->voltage_table_size) return -1; return regul->voltage_table[value]; } int stpmic1_lp_copy_reg(const char *name) { const struct regul_struct *regul = get_regulator_data(name); uint8_t val = 0; int status = 0; if (!regul->low_power_reg) return -1; status = stpmic1_register_read(regul->control_reg, &val); if (status) return status; return stpmic1_register_write(regul->low_power_reg, val); } bool stpmic1_regu_has_lp_cfg(const char *name) { return get_regulator_data(name)->low_power_reg; } int stpmic1_lp_cfg(const char *name, struct stpmic1_lp_cfg *cfg) { const struct regul_struct *regul = get_regulator_data(name); if (!regul->low_power_reg) return -1; cfg->ctrl_reg = regul->control_reg; cfg->lp_reg = regul->low_power_reg; return 0; } int stpmic1_lp_load_unpg(struct stpmic1_lp_cfg *cfg) { uint8_t val = 0; int status = 0; assert(cfg->lp_reg); status = stpmic1_register_read(cfg->ctrl_reg, &val); if (!status) status = stpmic1_register_write(cfg->lp_reg, val); return status; } int stpmic1_lp_reg_on_off(const char *name, uint8_t enable) { const struct regul_struct *regul = get_regulator_data(name); if (!regul->low_power_reg) return -1; return stpmic1_register_update(regul->low_power_reg, enable, LDO_BUCK_ENABLE_MASK); } int stpmic1_lp_on_off_unpg(struct stpmic1_lp_cfg *cfg, int enable) { assert(cfg->lp_reg && (enable == 0 || enable == 1)); return stpmic1_register_update(cfg->lp_reg, enable, LDO_BUCK_ENABLE_MASK); } int stpmic1_lp_set_mode(const char *name, uint8_t hplp) { const struct regul_struct *regul = get_regulator_data(name); assert(regul->low_power_reg && (hplp == 0 || hplp == 1)); return stpmic1_register_update(regul->low_power_reg, hplp << LDO_BUCK_HPLP_POS, BIT(LDO_BUCK_HPLP_POS)); } int stpmic1_lp_mode_unpg(struct stpmic1_lp_cfg *cfg, unsigned int mode) { assert(cfg->lp_reg && (mode == 0 || mode == 1)); return stpmic1_register_update(cfg->lp_reg, mode << LDO_BUCK_HPLP_POS, BIT(LDO_BUCK_HPLP_POS)); } int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts) { size_t voltage_index = voltage_to_index(name, millivolts); const struct regul_struct *regul = get_regulator_data(name); uint8_t mask = 0; assert(voltage_index != VOLTAGE_INDEX_INVALID); mask = find_plat_mask(name); if (!mask) return 0; return stpmic1_register_update(regul->low_power_reg, voltage_index << 2, mask); } /* Returns 1 if no configuration are expected applied at runtime, 0 otherwise */ int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, struct stpmic1_lp_cfg *cfg) { size_t voltage_index = voltage_to_index(name, millivolts); uint8_t mask = 0; mask = find_plat_mask(name); if (!mask) return 1; assert(voltage_index != VOLTAGE_INDEX_INVALID && cfg->lp_reg == get_regulator_data(name)->low_power_reg); cfg->value = voltage_index << 2; cfg->mask = mask; return 0; } int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg) { assert(cfg->lp_reg); return stpmic1_register_update(cfg->lp_reg, cfg->value, cfg->mask); } int stpmic1_register_read(uint8_t register_id, uint8_t *value) { struct i2c_handle_s *i2c = pmic_i2c_handle; return stm32_i2c_read_write_membyte(i2c, pmic_i2c_addr, register_id, value, false /* !write */); } int stpmic1_register_write(uint8_t register_id, uint8_t value) { struct i2c_handle_s *i2c = pmic_i2c_handle; uint8_t val = value; return stm32_i2c_read_write_membyte(i2c, pmic_i2c_addr, register_id, &val, true /* write */); } int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) { int status = 0; uint8_t val = 0; status = stpmic1_register_read(register_id, &val); if (status) return status; val = (val & ~mask) | (value & mask); return stpmic1_register_write(register_id, val); } void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) { pmic_i2c_handle = i2c_handle; pmic_i2c_addr = i2c_addr; } void stpmic1_dump_regulators(void) { size_t i = 0; char __maybe_unused const *name = NULL; for (i = 0; i < ARRAY_SIZE(regulators_table); i++) { if (!regulators_table[i].control_reg) continue; name = regulators_table[i].dt_node_name; DMSG("PMIC regul %s: %sable, %dmV", name, stpmic1_is_regulator_enabled(name) ? "en" : "dis", stpmic1_regulator_voltage_get(name)); } } int stpmic1_get_version(unsigned long *version) { uint8_t read_val = 0; if (stpmic1_register_read(VERSION_STATUS_REG, &read_val)) return -1; *version = read_val; return 0; } optee_os-4.3.0/core/drivers/sub.mk000066400000000000000000000075071464416617300171100ustar00rootroot00000000000000incdirs-$(CFG_VERSAL_SHA3_384) += crypto/versal/include srcs-$(CFG_CDNS_UART) += cdns_uart.c srcs-$(CFG_PL011) += pl011.c srcs-$(CFG_TZC400) += tzc400.c srcs-$(CFG_TZC380) += tzc380.c srcs-$(CFG_GIC) += gic.c srcs-$(CFG_CORE_HAFNIUM_INTC) += hfic.c srcs-$(CFG_PL061) += pl061_gpio.c srcs-$(CFG_PL022) += pl022_spi.c srcs-$(CFG_SP805_WDT) += sp805_wdt.c srcs-$(CFG_8250_UART) += serial8250_uart.c srcs-$(CFG_16550_UART) += ns16550.c srcs-$(CFG_IMX_SNVS) += imx_snvs.c srcs-$(CFG_IMX_UART) += imx_uart.c srcs-$(CFG_IMX_I2C) += imx_i2c.c srcs-$(CFG_IMX_LPUART) += imx_lpuart.c srcs-$(CFG_IMX_WDOG) += imx_wdog.c srcs-$(CFG_SPRD_UART) += sprd_uart.c srcs-$(CFG_HI16XX_UART) += hi16xx_uart.c srcs-$(CFG_HI16XX_RNG) += hi16xx_rng.c srcs-$(CFG_LPC_UART) += lpc_uart.c srcs-$(CFG_SCIF) += scif.c srcs-$(CFG_DRA7_RNG) += dra7_rng.c srcs-$(CFG_STIH_UART) += stih_asc.c srcs-$(CFG_ATMEL_UART) += atmel_uart.c srcs-$(CFG_ATMEL_TRNG) += atmel_trng.c srcs-$(CFG_ATMEL_RSTC) += atmel_rstc.c srcs-$(CFG_ATMEL_SHDWC) += atmel_shdwc.c atmel_shdwc_a32.S srcs-$(CFG_ATMEL_SAIC) += atmel_saic.c srcs-$(CFG_ATMEL_WDT) += atmel_wdt.c srcs-$(CFG_ATMEL_RTC) += atmel_rtc.c srcs-$(CFG_ATMEL_PIOBU) += atmel_piobu.c srcs-$(CFG_ATMEL_TCB) += atmel_tcb.c srcs-$(CFG_AMLOGIC_UART) += amlogic_uart.c srcs-$(CFG_MVEBU_UART) += mvebu_uart.c srcs-$(CFG_STM32_BSEC) += stm32_bsec.c srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c srcs-$(CFG_STM32_FMC) += stm32_fmc.c srcs-$(CFG_STM32_GPIO) += stm32_gpio.c srcs-$(CFG_STM32_HPDMA) += stm32_hpdma.c srcs-$(CFG_STM32_HSEM) += stm32_hsem.c srcs-$(CFG_STM32_IWDG) += stm32_iwdg.c srcs-$(CFG_STM32_IPCC) += stm32_ipcc.c srcs-$(CFG_STM32_I2C) += stm32_i2c.c srcs-$(CFG_STM32_RNG) += stm32_rng.c srcs-$(CFG_STM32_SHARED_IO) += stm32_shared_io.c srcs-$(CFG_STM32_TAMP) += stm32_tamp.c srcs-$(CFG_STM32_UART) += stm32_uart.c srcs-$(CFG_STPMIC1) += stpmic1.c srcs-$(CFG_BCM_HWRNG) += bcm_hwrng.c srcs-$(CFG_BCM_SOTP) += bcm_sotp.c srcs-$(CFG_BCM_GPIO) += bcm_gpio.c srcs-$(CFG_LS_I2C) += ls_i2c.c srcs-$(CFG_LS_GPIO) += ls_gpio.c srcs-$(CFG_LS_DSPI) += ls_dspi.c srcs-$(CFG_LS_SEC_MON) += ls_sec_mon.c srcs-$(CFG_LS_SFP) += ls_sfp.c srcs-$(CFG_IMX_RNGB) += imx_rngb.c srcs-$(CFG_IMX_OCOTP) += imx_ocotp.c srcs-$(CFG_IMX_CAAM) += imx_caam.c srcs-$(CFG_IMX_SCU) += imx_scu.c srcs-$(CFG_IMX_CSU) += imx_csu.c srcs-$(CFG_XIPHERA_TRNG) += xiphera_trng.c srcs-$(CFG_IMX_SC) += imx_sc_api.c srcs-$(CFG_IMX_ELE) += imx_ele.c srcs-$(CFG_ZYNQMP_CSU_PUF) += zynqmp_csu_puf.c srcs-$(CFG_ZYNQMP_CSUDMA) += zynqmp_csudma.c srcs-$(CFG_ZYNQMP_CSU_AES) += zynqmp_csu_aes.c srcs-$(CFG_ZYNQMP_PM) += zynqmp_pm.c srcs-$(CFG_ZYNQMP_HUK) += zynqmp_huk.c srcs-$(CFG_ARM_SMCCC_TRNG) += smccc_trng.c srcs-$(CFG_VERSAL_GPIO) += versal_gpio.c srcs-$(CFG_VERSAL_MBOX) += versal_mbox.c srcs-$(CFG_VERSAL_PM) += versal_pm.c srcs-$(CFG_STM32MP15_HUK) += stm32mp15_huk.c srcs-$(CFG_VERSAL_RNG_DRV) += versal_trng.c srcs-$(CFG_VERSAL_NVM) += versal_nvm.c srcs-$(CFG_VERSAL_SHA3_384) += versal_sha3_384.c srcs-$(CFG_VERSAL_PUF) += versal_puf.c srcs-$(CFG_VERSAL_HUK) += versal_huk.c srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c srcs-$(CFG_RISCV_PLIC) += plic.c srcs-$(CFG_RISCV_ZKR_RNG) += riscv_zkr_rng.c srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c srcs-$(CFG_WIDEVINE_HUK) += widevine_huk.c srcs-$(CFG_SEMIHOSTING_CONSOLE) += semihosting_console.c srcs-$(CFG_FFA_CONSOLE) += ffa_console.c subdirs-y += crypto subdirs-$(CFG_BNXT_FW) += bnxt subdirs-$(CFG_DRIVERS_CLK) += clk subdirs-$(CFG_DRIVERS_FIREWALL) += firewall subdirs-$(CFG_DRIVERS_GPIO) += gpio subdirs-$(CFG_DRIVERS_I2C) += i2c subdirs-$(CFG_DRIVERS_NVMEM) += nvmem subdirs-$(CFG_DRIVERS_PINCTRL) += pinctrl subdirs-$(CFG_DRIVERS_REGULATOR) += regulator subdirs-$(CFG_DRIVERS_RSTCTRL) += rstctrl subdirs-$(CFG_DRIVERS_REMOTEPROC) += remoteproc subdirs-$(CFG_SCMI_MSG_DRIVERS) += scmi-msg subdirs-y += imx subdirs-y += pm subdirs-y += wdt subdirs-y += rtc subdirs-y += firewall optee_os-4.3.0/core/drivers/tzc380.c000066400000000000000000000230231464416617300171540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2017-2020 NXP * All rights reserved. * * Peng Fan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include /* * Implementation defined values used to validate inputs later. * Filters : max of 4 ; 0 to 3 * Regions : max of 9 ; 0 to 8 * Address width : Values between 32 to 64 */ struct tzc_instance { vaddr_t base; uint8_t addr_width; uint8_t num_regions; }; static struct tzc_instance tzc; static uint32_t tzc_read_build_config(vaddr_t base) { return io_read32(base + BUILD_CONFIG_OFF); } static void tzc_write_action(vaddr_t base, enum tzc_action action) { io_write32(base + ACTION_OFF, action); } static uint32_t tzc_read_action(vaddr_t base) { return io_read32(base + ACTION_OFF); } static void tzc_write_region_base_low(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_SETUP_LOW_OFF(region), val); } static void tzc_write_region_base_high(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_SETUP_HIGH_OFF(region), val); } static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) { return io_read32(base + REGION_ATTRIBUTES_OFF(region)); } static void tzc_write_region_attributes(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_ATTRIBUTES_OFF(region), val); } void tzc_init(vaddr_t base) { uint32_t tzc_build; assert(base); tzc.base = base; /* Save values we will use later. */ tzc_build = tzc_read_build_config(tzc.base); tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & BUILD_CONFIG_AW_MASK) + 1; tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & BUILD_CONFIG_NR_MASK) + 1; } /* * There are two modes of operation for the region security * permissions, with or without security inversion. * Check TZC380 "2.2.5 Region security permissions" for * more details. */ void tzc_security_inversion_en(vaddr_t base) { io_write32(base + SECURITY_INV_EN_OFF, 1); } /* * Enable a single region. Sometimes we could not use tzc_configure_region * to enable the region, when security inversion is on. * When need security inversion, we need to first configure * region address and attribute, then configure security inversion, * then enable the regions. */ void tzc_region_enable(uint8_t region) { uint32_t val; val = tzc_read_region_attributes(tzc.base, region); val |= TZC_ATTR_REGION_EN_MASK; tzc_write_region_attributes(tzc.base, region, val); } /* * Dump info when TZC380 catchs an unallowed access with TZC * interrupt enabled. */ void tzc_fail_dump(void) { vaddr_t base __maybe_unused = core_mmu_get_va(tzc.base, MEM_AREA_IO_SEC, TZC400_REG_SIZE); EMSG("Fail address Low 0x%" PRIx32, io_read32(base + FAIL_ADDRESS_LOW_OFF)); EMSG("Fail address High 0x%" PRIx32, io_read32(base + FAIL_ADDRESS_HIGH_OFF)); EMSG("Fail Control 0x%" PRIx32, io_read32(base + FAIL_CONTROL_OFF)); EMSG("Fail Id 0x%" PRIx32, io_read32(base + FAIL_ID)); } void tzc_int_clear(void) { vaddr_t base = core_mmu_get_va(tzc.base, MEM_AREA_IO_SEC, TZC400_REG_SIZE); io_write32(base + INT_CLEAR, 0); } static uint32_t addr_low(vaddr_t addr) { return (uint32_t)addr; } static uint32_t addr_high(vaddr_t addr __maybe_unused) { #if (UINTPTR_MAX == UINT64_MAX) return addr >> 32; #else return 0; #endif } /* * `tzc_configure_region` is used to program regions into the TrustZone * controller. */ void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr) { assert(tzc.base); assert(region < tzc.num_regions); /* * For region 0, this high/low/size/en field is Read Only (RO). * So should not configure those field for region 0. */ if (region) { tzc_write_region_base_low(tzc.base, region, addr_low(region_base)); tzc_write_region_base_high(tzc.base, region, addr_high(region_base)); tzc_write_region_attributes(tzc.base, region, attr); } else { tzc_write_region_attributes(tzc.base, region, attr & TZC_ATTR_SP_MASK); } } void tzc_set_action(enum tzc_action action) { assert(tzc.base); /* * - Currently no handler is provided to trap an error via interrupt * or exception. * - The interrupt action has not been tested. */ tzc_write_action(tzc.base, action); } uint32_t tzc_get_action(void) { assert(tzc.base); return tzc_read_action(tzc.base); } int tzc_auto_configure(vaddr_t addr, vaddr_t size, uint32_t attr, uint8_t region) { uint64_t sub_region_size = 0; uint64_t area = 0; uint8_t lregion = region; uint64_t region_size = 0; vaddr_t sub_address = 0; vaddr_t address = addr; uint64_t lsize = size; uint32_t mask = 0; int i = 0; uint8_t pow = 0; assert(tzc.base); /* * TZC380 RM * For region_attributes_ registers, region_size: * Note: The AXI address width, that is AXI_ADDRESS_MSB+1, controls the * upper limit value of the field. */ pow = tzc.addr_width; while (lsize != 0 && pow >= 15) { region_size = 1ULL << pow; /* Case region fits alignment and covers requested area */ if ((address % region_size == 0) && ((address + lsize) % region_size == 0)) { tzc_configure_region(lregion, address, TZC_ATTR_REGION_SIZE(pow - 1) | TZC_ATTR_REGION_EN_MASK | attr); lregion++; address += region_size; lsize -= region_size; pow = tzc.addr_width; continue; } /* Cover area using several subregions */ sub_region_size = region_size / 8; if (address % sub_region_size == 0 && lsize > 2 * sub_region_size) { sub_address = (address / region_size) * region_size; mask = 0; for (i = 0; i < 8; i++) { area = (i + 1) * sub_region_size; if (sub_address + area <= address || sub_address + area > address + lsize) { mask |= TZC_ATTR_SUBREGION_DIS(i); } else { address += sub_region_size; lsize -= sub_region_size; } } tzc_configure_region(lregion, sub_address, TZC_ATTR_REGION_SIZE(pow - 1) | TZC_ATTR_REGION_EN_MASK | mask | attr); lregion++; pow = tzc.addr_width; continue; } pow--; } assert(lsize == 0); assert(address == addr + size); return lregion; } /* * `region_lockdown` is used to lockdown the TZC380 configuration to prevent * unintended overwrites of the configuration. Returns TEE_ERROR_SECURITY in * case the lockdown fails. */ TEE_Result tzc_regions_lockdown(void) { uint32_t val = 0; uint32_t check = 0; val = LOCKDOWN_RANGE_ENABLE | (tzc.num_regions - 1); io_write32(tzc.base + LOCKDOWN_RANGE_OFF, val); check = io_read32(tzc.base + LOCKDOWN_RANGE_OFF); if (check != val) return TEE_ERROR_SECURITY; val = LOCKDOWN_SELECT_RANGE_ENABLE; io_write32(tzc.base + LOCKDOWN_SELECT_OFF, val); check = io_read32(tzc.base + LOCKDOWN_SELECT_OFF); if (check != val) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } #if TRACE_LEVEL >= TRACE_DEBUG static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) { return io_read32(base + REGION_SETUP_LOW_OFF(region)); } static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) { return io_read32(base + REGION_SETUP_HIGH_OFF(region)); } #define REGION_MAX 16 void tzc_dump_state(void) { uint32_t n; uint32_t temp_32reg, temp_32reg_h; DMSG("TZC380 configuration:"); DMSG("security_inversion_en %x", io_read32(tzc.base + SECURITY_INV_EN_OFF)); for (n = 0; n <= REGION_MAX; n++) { temp_32reg = tzc_read_region_attributes(tzc.base, n); if (!(temp_32reg & TZC_ATTR_REGION_EN_MASK)) continue; DMSG(""); DMSG("region %d", n); temp_32reg = tzc_read_region_base_low(tzc.base, n); temp_32reg_h = tzc_read_region_base_high(tzc.base, n); DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); temp_32reg = tzc_read_region_attributes(tzc.base, n); DMSG("region sp: %x", temp_32reg >> TZC_ATTR_SP_SHIFT); DMSG("region size: %x", (temp_32reg & TZC_REGION_SIZE_MASK) >> TZC_REGION_SIZE_SHIFT); } DMSG("Lockdown select: %"PRIx32, io_read32(tzc.base + LOCKDOWN_SELECT_OFF)); DMSG("Lockdown range: %"PRIx32, io_read32(tzc.base + LOCKDOWN_RANGE_OFF)); DMSG("Action register: %"PRIx32, tzc_get_action()); DMSG("exit"); } #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ optee_os-4.3.0/core/drivers/tzc400.c000066400000000000000000000343711464416617300171550ustar00rootroot00000000000000// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) /* * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include /* * Implementation defined values used to validate inputs later. * Filters : max of 4 ; 0 to 3 * Regions : max of 9 ; 0 to 8 * Address width : Values between 32 to 64 */ struct tzc_instance { vaddr_t base; uint8_t addr_width; uint8_t num_filters; uint8_t num_regions; }; static struct tzc_instance tzc; static uint32_t tzc_read_build_config(vaddr_t base) { return io_read32(base + BUILD_CONFIG_OFF); } static uint32_t tzc_read_gate_keeper(vaddr_t base) { return io_read32(base + GATE_KEEPER_OFF); } static void tzc_write_gate_keeper(vaddr_t base, uint32_t val) { io_write32(base + GATE_KEEPER_OFF, val); } static void tzc_write_action(vaddr_t base, enum tzc_action action) { io_write32(base + ACTION_OFF, action); } static uint32_t tzc_read_region_base_low(vaddr_t base, uint32_t region) { return io_read32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region)); } static void tzc_write_region_base_low(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_BASE_LOW_OFF + REGION_NUM_OFF(region), val); } static uint32_t tzc_read_region_base_high(vaddr_t base, uint32_t region) { return io_read32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region)); } static void tzc_write_region_base_high(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_BASE_HIGH_OFF + REGION_NUM_OFF(region), val); } static uint32_t tzc_read_region_top_low(vaddr_t base, uint32_t region) { return io_read32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region)); } static void tzc_write_region_top_low(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_TOP_LOW_OFF + REGION_NUM_OFF(region), val); } static uint32_t tzc_read_region_top_high(vaddr_t base, uint32_t region) { return io_read32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region)); } static void tzc_write_region_top_high(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_TOP_HIGH_OFF + REGION_NUM_OFF(region), val); } static uint32_t tzc_read_region_attributes(vaddr_t base, uint32_t region) { return io_read32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region)); } static void tzc_write_region_attributes(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region), val); } static uint32_t tzc_read_region_id_access(vaddr_t base, uint32_t region) { return io_read32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region)); } static void tzc_write_region_id_access(vaddr_t base, uint32_t region, uint32_t val) { io_write32(base + REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region), val); } static uint32_t tzc_read_component_id(vaddr_t base) { uint32_t id; id = io_read8(base + CID0_OFF); id |= SHIFT_U32(io_read8(base + CID1_OFF), 8); id |= SHIFT_U32(io_read8(base + CID2_OFF), 16); id |= SHIFT_U32(io_read8(base + CID3_OFF), 24); return id; } static uint32_t tzc_get_gate_keeper(vaddr_t base, uint8_t filter) { uint32_t tmp; tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & GATE_KEEPER_OS_MASK; return (tmp >> filter) & GATE_KEEPER_FILTER_MASK; } /* This function is not MP safe. */ static void tzc_set_gate_keeper(vaddr_t base, uint8_t filter, uint32_t val) { uint32_t tmp; /* Upper half is current state. Lower half is requested state. */ tmp = (tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & GATE_KEEPER_OS_MASK; if (val) tmp |= (1 << filter); else tmp &= ~(1 << filter); tzc_write_gate_keeper(base, (tmp & GATE_KEEPER_OR_MASK) << GATE_KEEPER_OR_SHIFT); /* Wait here until we see the change reflected in the TZC status. */ while (((tzc_read_gate_keeper(base) >> GATE_KEEPER_OS_SHIFT) & GATE_KEEPER_OS_MASK) != tmp) ; } void tzc_init(vaddr_t base) { uint32_t tzc_id, tzc_build; assert(base); tzc.base = base; /* * We expect to see a tzc400. Check component ID. The TZC-400 TRM shows * component ID is expected to be "0xB105F00D". */ tzc_id = tzc_read_component_id(tzc.base); if (tzc_id != TZC400_COMPONENT_ID) { EMSG("TZC : Wrong device ID (0x%" PRIx32 ")", tzc_id); panic(); } /* Save values we will use later. */ tzc_build = tzc_read_build_config(tzc.base); tzc.num_filters = ((tzc_build >> BUILD_CONFIG_NF_SHIFT) & BUILD_CONFIG_NF_MASK) + 1; tzc.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & BUILD_CONFIG_AW_MASK) + 1; tzc.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & BUILD_CONFIG_NR_MASK) + 1; } static uint32_t addr_low(vaddr_t addr) { return (uint32_t)addr; } static uint32_t addr_high(vaddr_t addr __unused) { #if (UINTPTR_MAX == UINT64_MAX) return (addr >> 32); #else return 0; #endif } /* * `tzc_configure_region` is used to program regions into the TrustZone * controller. A region can be associated with more than one filter. The * associated filters are passed in as a bitmap (bit0 = filter0). * NOTE: * The region 0 covers the whole address space and is enabled on all filters, * this cannot be changed. It is, however, possible to change some region 0 * permissions. */ void tzc_configure_region(uint8_t region, const struct tzc_region_config *cfg) { assert(tzc.base && cfg); /* Do range checks on filters and regions. */ assert(((cfg->filters >> tzc.num_filters) == 0) && (region < tzc.num_regions)); /* * Do address range check based on TZC configuration. A 64bit address is * the max and expected case. */ #if (UINTPTR_MAX == UINT64_MAX) assert(((cfg->top <= (UINT64_MAX >> (64 - tzc.addr_width))) && (cfg->base < cfg->top))); #endif /* region_base and (region_top + 1) must be 4KB aligned */ assert(((cfg->base | (cfg->top + 1)) & (4096 - 1)) == 0); assert(cfg->sec_attr <= TZC_REGION_S_RDWR); /* * Inputs look ok, start programming registers. * All the address registers are 32 bits wide and have a LOW and HIGH * component used to construct a up to a 64bit address. */ tzc_write_region_base_low(tzc.base, region, addr_low(cfg->base)); tzc_write_region_base_high(tzc.base, region, addr_high(cfg->base)); tzc_write_region_top_low(tzc.base, region, addr_low(cfg->top)); tzc_write_region_top_high(tzc.base, region, addr_high(cfg->top)); /* Assign the region to a filter and set secure attributes */ tzc_write_region_attributes(tzc.base, region, (cfg->sec_attr << REG_ATTR_SEC_SHIFT) | cfg->filters); /* * Specify which non-secure devices have permission to access this * region. */ tzc_write_region_id_access(tzc.base, region, cfg->ns_device_access); } TEE_Result tzc_get_region_config(uint8_t region, struct tzc_region_config *cfg) { uint32_t val32 = 0; if (region >= tzc.num_regions) return TEE_ERROR_GENERIC; cfg->base = reg_pair_to_64(tzc_read_region_base_high(tzc.base, region), tzc_read_region_base_low(tzc.base, region)); cfg->top = reg_pair_to_64(tzc_read_region_top_high(tzc.base, region), tzc_read_region_top_low(tzc.base, region)); cfg->ns_device_access = tzc_read_region_id_access(tzc.base, region); val32 = tzc_read_region_attributes(tzc.base, region); cfg->sec_attr = val32 >> REG_ATTR_SEC_SHIFT; cfg->filters = val32 & REG_ATTR_F_EN_MASK; return TEE_SUCCESS; } void tzc_set_action(enum tzc_action action) { assert(tzc.base); /* * - Currently no handler is provided to trap an error via interrupt * or exception. * - The interrupt action has not been tested. */ tzc_write_action(tzc.base, action); } void tzc_enable_filters(void) { uint32_t state; uint32_t filter; assert(tzc.base); for (filter = 0; filter < tzc.num_filters; filter++) { state = tzc_get_gate_keeper(tzc.base, filter); if (state) { /* * The TZC filter is already configured. Changing the * programmer's view in an active system can cause * unpredictable behavior therefore panic for now rather * than try to determine whether this is safe in this * instance. See: * http://infocenter.arm.com/help/index.jsp?\ * topic=/com.arm.doc.ddi0504c/CJHHECBF.html */ EMSG("TZC : Filter %d Gatekeeper already enabled", filter); panic(); } tzc_set_gate_keeper(tzc.base, filter, 1); } } void tzc_disable_filters(void) { uint32_t filter; assert(tzc.base); /* * We don't do the same state check as above as the Gatekeepers are * disabled after reset. */ for (filter = 0; filter < tzc.num_filters; filter++) tzc_set_gate_keeper(tzc.base, filter, 0); } static bool __maybe_unused write_not_read(unsigned int filter) { return io_read32(tzc.base + FAIL_CONTROL(filter)) & FAIL_CONTROL_DIRECTION_WRITE; } static bool __maybe_unused nonsecure_not_secure(unsigned int filter) { return io_read32(tzc.base + FAIL_CONTROL(filter)) & FAIL_CONTROL_NONSECURE; } static bool __maybe_unused priv_not_unpriv(unsigned int filter) { return io_read32(tzc.base + FAIL_CONTROL(filter)) & FAIL_CONTROL_PRIVILEGED; } static void dump_fail_filter(unsigned int filter) { uint64_t __maybe_unused addr = 0; uint32_t status = io_read32(tzc.base + INT_STATUS); if (!(status & BIT(filter + INT_STATUS_OVERLAP_SHIFT)) && !(status & BIT(filter + INT_STATUS_OVERRUN_SHIFT)) && !(status & BIT(filter + INT_STATUS_STATUS_SHIFT))) return; if (status & BIT(filter + INT_STATUS_OVERLAP_SHIFT)) EMSG("Overlap violation on filter %u", filter); if (status & BIT(filter + INT_STATUS_OVERRUN_SHIFT)) EMSG("Overrun violation on filter %u", filter); if (status & BIT(filter + INT_STATUS_STATUS_SHIFT)) EMSG("Permission violation on filter %u", filter); addr = reg_pair_to_64(io_read32(tzc.base + FAIL_ADDRESS_HIGH(filter)), io_read32(tzc.base + FAIL_ADDRESS_LOW(filter))); EMSG("Violation @0x%"PRIx64", %ssecure %sprivileged %s, AXI ID %"PRIx32, addr, nonsecure_not_secure(filter) ? "non-" : "", priv_not_unpriv(filter) ? "" : "un", write_not_read(filter) ? "write" : "read", io_read32(tzc.base + FAIL_ID(filter))); } /* * Dump info when TZC400 catches an unallowed access with TZC * interrupt enabled. */ void tzc_fail_dump(void) { unsigned int filter = 0; for (filter = 0; filter < tzc.num_filters; filter++) dump_fail_filter(filter); } void tzc_int_clear(void) { assert(tzc.base); io_setbits32(tzc.base + INT_CLEAR, GENMASK_32(tzc.num_filters - 1, 0)); } #if TRACE_LEVEL >= TRACE_DEBUG #define REGION_MAX 8 static const __maybe_unused char * const tzc_attr_msg[] = { "TZC_REGION_S_NONE", "TZC_REGION_S_RD", "TZC_REGION_S_WR", "TZC_REGION_S_RDWR" }; void tzc_dump_state(void) { uint32_t n; uint32_t temp_32reg, temp_32reg_h; unsigned int filter = 0; for (n = 0; n <= REGION_MAX; n++) { temp_32reg = tzc_read_region_attributes(tzc.base, n); if (!(temp_32reg & REG_ATTR_F_EN_MASK)) continue; DMSG("region %d", n); temp_32reg = tzc_read_region_base_low(tzc.base, n); temp_32reg_h = tzc_read_region_base_high(tzc.base, n); DMSG("region_base: 0x%08x%08x", temp_32reg_h, temp_32reg); temp_32reg = tzc_read_region_top_low(tzc.base, n); temp_32reg_h = tzc_read_region_top_high(tzc.base, n); DMSG("region_top: 0x%08x%08x", temp_32reg_h, temp_32reg); temp_32reg = tzc_read_region_attributes(tzc.base, n); DMSG("secure rw: %s", tzc_attr_msg[temp_32reg >> REG_ATTR_SEC_SHIFT]); for (filter = 0; filter < tzc.num_filters; filter++) if (temp_32reg & BIT(filter)) DMSG("filter %u enable", filter); } } #endif /* CFG_TRACE_LEVEL >= TRACE_DEBUG */ optee_os-4.3.0/core/drivers/versal_gpio.c000066400000000000000000000146771464416617300204520ustar00rootroot00000000000000// SPDX-License-Identifier: MIT /* * Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved. * Copyright (c) 2022 Foundries.io Ltd. (jorge@foundries.io) */ #include #include #include #include #include #include #include #include #include #include #include #include "drivers/versal_gpio.h" #define VERSAL_GPIO_LEN 0x10000 #define DATA_LSW_OFFSET(__bank) (0x000 + 0x08 * (__bank)) #define DATA_MSW_OFFSET(__bank) (0x004 + 0x08 * (__bank)) #define DATA_RO_OFFSET(__bank) (0x060 + 0x04 * (__bank)) #define DIRM_OFFSET(__bank) (0x204 + 0x40 * (__bank)) #define OUTEN_OFFSET(__bank) (0x208 + 0x40 * (__bank)) #define VERSAL_GPIO_MID_PIN 16 #define VERSAL_GPIO_UPPER_MASK 0xFFFF0000 /* Max pins in the PMC_GPIO devices * 00 - 025, Bank 0 * 26 - 051, Bank 1 * 52 - 083, Bank 3 * 84 - 115, Bank 4 */ #define VERSAL_GPIO_PMC_BASE 0xf1020000 #define VERSAL_GPIO_PMC_NR_GPIOS 116 #define VERSAL_GPIO_PMC_MAX_BANK 5 static const struct versal_gpio_platform_data versal_gpio_pmc_def = { .max_bank = VERSAL_GPIO_PMC_MAX_BANK, .ngpio = VERSAL_GPIO_PMC_NR_GPIOS, .label = "versal_pmc_gpio", .bank_min[0] = 0, .bank_max[0] = 25, .bank_min[1] = 26, .bank_max[1] = 51, .bank_min[3] = 52, .bank_max[3] = 83, .bank_min[4] = 84, .bank_max[4] = 115, }; /* Max pins in the PS_GPIO devices * 00 - 25, Bank 0 * 26 - 57, Bank 3 */ #define VERSAL_GPIO_PS_BASE 0xff0b0000 #define VERSAL_GPIO_PS_NR_GPIOS 58 #define VERSAL_GPIO_PS_MAX_BANK 4 static const struct versal_gpio_platform_data versal_gpio_ps_def = { .max_bank = VERSAL_GPIO_PS_MAX_BANK, .ngpio = VERSAL_GPIO_PS_NR_GPIOS, .label = "versal_ps_gpio", .bank_min[0] = 0, .bank_max[0] = 25, .bank_min[3] = 26, .bank_max[3] = 57, }; static void versal_gpio_get_pin(struct versal_gpio_chip *chip, uint32_t gpio, uint32_t *bank, uint32_t *pin) { struct versal_gpio_platdata *platdata = &chip->plat; uint32_t bnk = 0; assert(gpio < platdata->p_data->ngpio); for (bnk = 0; bnk < platdata->p_data->max_bank; bnk++) { if (gpio < platdata->p_data->bank_min[bnk]) continue; if (gpio > platdata->p_data->bank_max[bnk]) continue; *bank = bnk; *pin = gpio - platdata->p_data->bank_min[bnk]; return; } EMSG("GPIO_%d not found", gpio); panic(); } static enum gpio_level versal_gpio_get_value(struct versal_gpio_chip *chip, uint32_t gpio) { uint32_t bank = 0; uint32_t pin = 0; versal_gpio_get_pin(chip, gpio, &bank, &pin); return (io_read32(chip->base + DATA_RO_OFFSET(bank)) >> pin) & 1; } static void versal_gpio_set_value(struct versal_gpio_chip *chip, uint32_t gpio, enum gpio_level val) { uint32_t bank = 0; uint32_t off = 0; uint32_t pin = 0; versal_gpio_get_pin(chip, gpio, &bank, &pin); if (bank >= VERSAL_GPIO_MID_PIN) { bank -= VERSAL_GPIO_MID_PIN; off = DATA_MSW_OFFSET(bank); } else { off = DATA_LSW_OFFSET(bank); } /* * get the 32 bit value to be written to the mask/data register where * the upper 16 bits is the mask and lower 16 bits is the data */ val = !!val; val = ~BIT32(pin + VERSAL_GPIO_MID_PIN) & (SHIFT_U32(val, pin) | VERSAL_GPIO_UPPER_MASK); io_write32(chip->base + off, val); } static void versal_gpio_set_direction(struct versal_gpio_chip *chip, uint32_t gpio, enum gpio_dir direction) { uint32_t bank = 0; uint32_t reg = 0; uint32_t pin = 0; versal_gpio_get_pin(chip, gpio, &bank, &pin); if (direction == GPIO_DIR_OUT) { /* set the GPIO pin as output */ reg = io_read32(chip->base + DIRM_OFFSET(bank)); reg |= BIT(pin); io_write32(chip->base + DIRM_OFFSET(bank), reg); /* configure the output enable reg for the pin */ reg = io_read32(chip->base + OUTEN_OFFSET(bank)); reg |= BIT(pin); io_write32(chip->base + OUTEN_OFFSET(bank), reg); /* set the state of the pin */ versal_gpio_set_value(chip, gpio, GPIO_LEVEL_LOW); } else { /* bnk 0 pins 7 and 8 cannot be used as inputs */ assert(!(bank == 0 && (pin == 7 || pin == 8))); reg = io_read32(chip->base + DIRM_OFFSET(bank)); reg &= ~BIT(pin); io_write32(chip->base + DIRM_OFFSET(bank), reg); } } static enum gpio_dir versal_gpio_get_direction(struct versal_gpio_chip *chip, uint32_t gpio) { uint32_t pin = 0; uint32_t bank = 0; versal_gpio_get_pin(chip, gpio, &bank, &pin); if (io_read32(chip->base + DIRM_OFFSET(bank)) & BIT(pin)) return GPIO_DIR_OUT; return GPIO_DIR_IN; } static enum gpio_level do_get_value(struct gpio_chip *chip, uint32_t gpio) { struct versal_gpio_chip *p = container_of(chip, struct versal_gpio_chip, chip); return versal_gpio_get_value(p, gpio); } static void do_set_value(struct gpio_chip *chip, uint32_t gpio, enum gpio_level val) { struct versal_gpio_chip *p = container_of(chip, struct versal_gpio_chip, chip); return versal_gpio_set_value(p, gpio, val); } static void do_set_dir(struct gpio_chip *chip, uint32_t gpio, enum gpio_dir direction) { struct versal_gpio_chip *p = container_of(chip, struct versal_gpio_chip, chip); return versal_gpio_set_direction(p, gpio, direction); } static enum gpio_dir do_get_dir(struct gpio_chip *chip, uint32_t gpio) { struct versal_gpio_chip *p = container_of(chip, struct versal_gpio_chip, chip); return versal_gpio_get_direction(p, gpio); } static const struct gpio_ops versal_gpio_ops = { .get_direction = do_get_dir, .set_direction = do_set_dir, .get_value = do_get_value, .set_value = do_set_value, .get_interrupt = NULL, .set_interrupt = NULL, }; TEE_Result versal_gpio_pmc_init(struct versal_gpio_chip *chip) { if (chip->base) return TEE_SUCCESS; chip->plat.p_data = &versal_gpio_pmc_def; chip->plat.base = VERSAL_GPIO_PMC_BASE; chip->chip.ops = &versal_gpio_ops; chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, VERSAL_GPIO_PMC_BASE, VERSAL_GPIO_LEN); if (!chip->base) { EMSG("Failed to map gpio"); chip->chip.ops = NULL; return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } TEE_Result versal_gpio_ps_init(struct versal_gpio_chip *chip) { if (chip->base) return TEE_SUCCESS; chip->plat.p_data = &versal_gpio_ps_def; chip->plat.base = VERSAL_GPIO_PS_BASE; chip->chip.ops = &versal_gpio_ops; chip->base = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, VERSAL_GPIO_PS_BASE, VERSAL_GPIO_LEN); if (!chip->base) { EMSG("Failed to map gpio"); chip->chip.ops = NULL; return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/versal_huk.c000066400000000000000000000205361464416617300202720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Foundries.io Ltd. * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #include #include #include #include #include #include static struct { uint8_t key[HW_UNIQUE_KEY_LENGTH]; bool ready; } huk; #define MODULE_SHIFT 8 #define MODULE_ID 5 #define API_ID(__x) ((MODULE_ID << MODULE_SHIFT) | (__x)) #define VERSAL_AES_KEY_SIZE_256 2 #define VERSAL_AES_GCM_ENCRYPT 0 enum versal_aes_key_src { VERSAL_AES_BBRAM_KEY = 0, VERSAL_AES_BBRAM_RED_KEY, VERSAL_AES_BH_KEY, VERSAL_AES_BH_RED_KEY, VERSAL_AES_EFUSE_KEY, VERSAL_AES_EFUSE_RED_KEY, VERSAL_AES_EFUSE_USER_KEY_0, VERSAL_AES_EFUSE_USER_KEY_1, VERSAL_AES_EFUSE_USER_RED_KEY_0, VERSAL_AES_EFUSE_USER_RED_KEY_1, VERSAL_AES_KUP_KEY, VERSAL_AES_PUF_KEY, VERSAL_AES_USER_KEY_0, VERSAL_AES_USER_KEY_1, VERSAL_AES_USER_KEY_2, VERSAL_AES_USER_KEY_3, VERSAL_AES_USER_KEY_4, VERSAL_AES_USER_KEY_5, VERSAL_AES_USER_KEY_6, VERSAL_AES_USER_KEY_7, VERSAL_AES_EXPANDED_KEYS, VERSAL_AES_ALL_KEYS, }; enum versal_crypto_api { VERSAL_AES_INIT = 96U, VERSAL_AES_OP_INIT, VERSAL_AES_UPDATE_AAD, VERSAL_AES_ENCRYPT_UPDATE, VERSAL_AES_ENCRYPT_FINAL, VERSAL_AES_DECRYPT_UPDATE, VERSAL_AES_DECRYPT_FINAL, VERSAL_AES_KEY_ZERO, VERSAL_AES_WRITE_KEY, VERSAL_AES_LOCK_USER_KEY, VERSAL_AES_KEK_DECRYPT, VERSAL_AES_SET_DPA_CM, VERSAL_AES_DECRYPT_KAT, VERSAL_AES_DECRYPT_CM_KAT, }; struct versal_aes_input_param { uint64_t input_addr; uint32_t input_len; uint32_t is_last; }; struct versal_aes_init { uint64_t iv_addr; uint32_t operation; uint32_t key_src; uint32_t key_len; }; /* * The PLM is little endian. When programming the keys in uint32_t the driver * will BE swap the values. * * This way the test key below corresponds to the byte array 0xf8, 0x78, 0xb8, * 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, .... * * NOTICE: This hardcoded value in DEVEL_KEY could have just been zeroes as done * in the weak implementation found in otp_stubs.c. */ #define DEVEL_KEY { \ 0xf878b838, 0xd8589818, 0xe868a828, 0xc8488808, \ 0xf070b030, 0xd0509010, 0xe060a020, 0xc0408000, \ } #define AAD { \ 0x67, 0xe2, 0x1c, 0xf3, 0xcb, 0x29, 0xe0, 0xdc, 0xbc, 0x4d, \ 0x8b, 0x1d, 0x0c, 0xc5, 0x33, 0x4b, \ } #define NONCE { \ 0xd2, 0x45, 0x0e, 0x07, 0xea, 0x5d, 0xe0, 0x42, 0x6c, 0x0f, \ 0xa1, 0x33, \ } static bool versal_persistent_key(enum versal_aes_key_src src, bool *secure) { struct versal_efuse_puf_sec_ctrl_bits puf_ctrl = { }; struct versal_efuse_sec_ctrl_bits ctrl = { }; struct versal_puf_data puf_data = { }; struct versal_puf_cfg cfg = { .global_var_filter = VERSAL_PUF_GLBL_VAR_FLTR_OPTION, .read_option = VERSAL_PUF_READ_FROM_EFUSE_CACHE, .puf_operation = VERSAL_PUF_REGEN_ON_DEMAND, .shutter_value = VERSAL_PUF_SHUTTER_VALUE, .reg_mode = VERSAL_PUF_SYNDROME_MODE_4K, }; switch (src) { case VERSAL_AES_EFUSE_USER_KEY_0: if (versal_efuse_read_sec_ctrl(&ctrl)) panic(); *secure = ctrl.user_key0_wr_lk; return true; case VERSAL_AES_EFUSE_USER_KEY_1: if (versal_efuse_read_sec_ctrl(&ctrl)) panic(); *secure = ctrl.user_key1_wr_lk; return true; case VERSAL_AES_PUF_KEY: if (versal_efuse_read_puf_sec_ctrl(&puf_ctrl)) panic(); if (versal_puf_regenerate(&puf_data, &cfg)) panic(); *secure = puf_ctrl.puf_syn_lk; return true; case VERSAL_AES_USER_KEY_0: *secure = false; return false; default: EMSG("Trying to use an invalid key for the HUK"); panic(); } return false; } /* Encrypt using an AES-GCM key selectable with CFG_VERSAL_HUK_KEY */ static TEE_Result aes_gcm_encrypt(uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len) { struct versal_aes_input_param *input = NULL; struct versal_aes_init *init = NULL; struct versal_mbox_mem input_cmd = { }; struct versal_mbox_mem init_buf = { }; struct versal_mbox_mem p = { }; struct versal_mbox_mem q = { }; uint32_t key_data[8] = DEVEL_KEY; uint8_t nce_data[12] = NONCE; uint8_t aad_data[16] = AAD; size_t nce_len = sizeof(nce_data); size_t key_len = sizeof(key_data); size_t aad_len = sizeof(aad_data); TEE_Result ret = TEE_SUCCESS; struct versal_ipi_cmd cmd = { }; bool secure = false; size_t i = 0; uint32_t key_id = CFG_VERSAL_HUK_KEY; if (key_id > VERSAL_AES_ALL_KEYS) return TEE_ERROR_BAD_PARAMETERS; cmd.data[0] = API_ID(VERSAL_AES_INIT); if (versal_mbox_notify(&cmd, NULL, NULL)) { EMSG("AES_INIT error"); return TEE_ERROR_GENERIC; } if (!versal_persistent_key(key_id, &secure)) { for (i = 0; i < ARRAY_SIZE(key_data); i++) key_data[i] = TEE_U32_BSWAP(key_data[i]); versal_mbox_alloc(key_len, key_data, &p); cmd.data[0] = API_ID(VERSAL_AES_WRITE_KEY); cmd.data[1] = VERSAL_AES_KEY_SIZE_256; cmd.data[2] = key_id; reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[4], &cmd.data[3]); cmd.ibuf[0].mem = p; if (versal_mbox_notify(&cmd, NULL, NULL)) { EMSG("AES_WRITE_KEY error"); ret = TEE_ERROR_GENERIC; } free(p.buf); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; } /* Trace indication that it is safe to generate a RPMB key */ IMSG("Using %s HUK", secure ? "Production" : "Development"); versal_mbox_alloc(sizeof(*init), NULL, &init_buf); versal_mbox_alloc(nce_len, nce_data, &p); init = init_buf.buf; init->operation = VERSAL_AES_GCM_ENCRYPT; init->key_len = VERSAL_AES_KEY_SIZE_256; init->iv_addr = virt_to_phys(p.buf); init->key_src = key_id; cmd.data[0] = API_ID(VERSAL_AES_OP_INIT); reg_pair_from_64(virt_to_phys(init), &cmd.data[2], &cmd.data[1]); cmd.ibuf[0].mem = init_buf; cmd.ibuf[1].mem = p; if (versal_mbox_notify(&cmd, NULL, NULL)) { EMSG("AES_OP_INIT error"); ret = TEE_ERROR_GENERIC; } free(init); free(p.buf); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; versal_mbox_alloc(aad_len, aad_data, &p); cmd.data[0] = API_ID(VERSAL_AES_UPDATE_AAD); reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]); if (p.len % 16) cmd.data[3] = p.alloc_len; else cmd.data[3] = p.len; cmd.ibuf[0].mem = p; if (versal_mbox_notify(&cmd, NULL, NULL)) { EMSG("AES_UPDATE_AAD error"); ret = TEE_ERROR_GENERIC; } free(p.buf); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; versal_mbox_alloc(sizeof(*input), NULL, &input_cmd); versal_mbox_alloc(src_len, src, &p); versal_mbox_alloc(dst_len, NULL, &q); input = input_cmd.buf; input->input_addr = virt_to_phys(p.buf); input->input_len = p.len; input->is_last = true; cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_UPDATE); reg_pair_from_64(virt_to_phys(input), &cmd.data[2], &cmd.data[1]); reg_pair_from_64(virt_to_phys(q.buf), &cmd.data[4], &cmd.data[3]); cmd.ibuf[0].mem = input_cmd; cmd.ibuf[1].mem = p; cmd.ibuf[2].mem = q; if (versal_mbox_notify(&cmd, NULL, NULL)) { EMSG("AES_UPDATE_PAYLOAD error"); ret = TEE_ERROR_GENERIC; } memcpy(dst, q.buf, dst_len); free(input); free(p.buf); free(q.buf); memset(&cmd, 0, sizeof(cmd)); if (ret) return ret; versal_mbox_alloc(16, NULL, &p); cmd.data[0] = API_ID(VERSAL_AES_ENCRYPT_FINAL); reg_pair_from_64(virt_to_phys(p.buf), &cmd.data[2], &cmd.data[1]); if (versal_mbox_notify(&cmd, NULL, NULL)) { EMSG("AES_ENCRYPT_FINAL error"); ret = TEE_ERROR_GENERIC; } free(p.buf); memzero_explicit(&cmd, sizeof(cmd)); return ret; } TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { uint32_t dna[EFUSE_DNA_LEN / sizeof(uint32_t)] = { }; uint8_t enc_data[64] = { }; uint8_t sha[48] = { }; TEE_Result ret = TEE_SUCCESS; if (huk.ready) goto out; if (versal_efuse_read_dna(dna, sizeof(dna))) return TEE_ERROR_GENERIC; if (versal_sha3_384((uint8_t *)dna, sizeof(dna), sha, sizeof(sha))) { ret = TEE_ERROR_GENERIC; goto cleanup; } if (aes_gcm_encrypt(sha, sizeof(sha), enc_data, sizeof(enc_data))) { ret = TEE_ERROR_GENERIC; goto cleanup; } if (tee_hash_createdigest(TEE_ALG_SHA256, enc_data, sizeof(enc_data), huk.key, sizeof(huk.key))) { ret = TEE_ERROR_GENERIC; goto cleanup; } cleanup: memzero_explicit(enc_data, sizeof(enc_data)); memzero_explicit(dna, sizeof(dna)); memzero_explicit(sha, sizeof(sha)); if (ret) return ret; huk.ready = true; out: memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/versal_mbox.c000066400000000000000000000210001464416617300204330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2022 Foundries.io Ltd * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include "drivers/versal_mbox.h" #define PM_SIP_SVC 0xc2000000 /* IPI targets */ #define IPI_ID_PMC 1 #define IPI_ID_0 2 #define IPI_ID_RPU0 3 #define IPI_ID_RPU1 4 #define IPI_ID_3 5 #define IPI_ID_4 6 #define IPI_ID_5 7 /* Buffers */ #define IPI_BUFFER_BASEADDR 0xFF3F0000 #define IPI_BUFFER_APU_ID_0_BASE (IPI_BUFFER_BASEADDR + 0x400) #define IPI_BUFFER_APU_ID_3_BASE (IPI_BUFFER_BASEADDR + 0xA00) #define IPI_BUFFER_APU_ID_4_BASE (IPI_BUFFER_BASEADDR + 0xC00) #define IPI_BUFFER_APU_ID_5_BASE (IPI_BUFFER_BASEADDR + 0xE00) #define IPI_BUFFER_PMC_BASE (IPI_BUFFER_BASEADDR + 0x200) #define IPI_BUFFER_TARGET_APU_OFFSET 0x80 #define IPI_BUFFER_TARGET_PMC_OFFSET 0x40 #define IPI_BUFFER_REQ_OFFSET 0x0 #define IPI_BUFFER_RESP_OFFSET 0x20 #define IPI_BUFFER_LOCAL_OFFSET IPI_BUFFER_TARGET_APU_OFFSET #define IPI_BUFFER_REMOTE_OFFSET IPI_BUFFER_TARGET_PMC_OFFSET #define IPI_BLOCK 1 #define IPI_NON_BLOCK 0 /* Mailbox api */ enum versal_ipi_api_id { IPI_MAILBOX_OPEN = 0x1000, IPI_MAILBOX_RELEASE, IPI_MAILBOX_STATUS_ENQUIRY, IPI_MAILBOX_NOTIFY, IPI_MAILBOX_ACK, IPI_MAILBOX_ENABLE_IRQ, IPI_MAILBOX_DISABLE_IRQ }; static struct versal_ipi { uint32_t lcl; const uint32_t rmt; paddr_t buf; /* Exclusive access to the IPI shared buffer */ struct mutex lock; void *rsp; void *req; } ipi = { .buf = IPI_BUFFER_APU_ID_3_BASE, .rmt = IPI_ID_PMC, .lcl = IPI_ID_3, }; static const char *const nvm_id[] = { [0] = "API_FEATURES", [1] = "BBRAM_WRITE_AES_KEY", [2] = "BBRAM_ZEROIZE", [3] = "BBRAM_WRITE_USER_DATA", [4] = "BBRAM_READ_USER_DATA", [5] = "BBRAM_LOCK_WRITE_USER_DATA", [6] = "EFUSE_WRITE", [7] = "EFUSE_WRITE_PUF", [8] = "EFUSE_PUF_USER_FUSE_WRITE", [9] = "EFUSE_READ_IV", [10] = "EFUSE_READ_REVOCATION_ID", [11] = "EFUSE_READ_OFFCHIP_REVOCATION_ID", [12] = "EFUSE_READ_USER_FUSES", [13] = "EFUSE_READ_MISC_CTRL", [14] = "EFUSE_READ_SEC_CTRL", [15] = "EFUSE_READ_SEC_MISC1", [16] = "EFUSE_READ_BOOT_ENV_CTRL", [17] = "EFUSE_READ_PUF_SEC_CTRL", [18] = "EFUSE_READ_PPK_HASH", [19] = "EFUSE_READ_DEC_EFUSE_ONLY", [20] = "EFUSE_READ_DNA", [21] = "EFUSE_READ_PUF_USER_FUSES", [22] = "EFUSE_READ_PUF", [23] = "EFUSE_INVALID", }; static const char *const crypto_id[] = { [0] = "FEATURES", [1] = "RSA_SIGN_VERIFY", [2] = "RSA_PUBLIC_ENCRYPT", [3] = "RSA_PRIVATE_DECRYPT", [4] = "RSA_KAT", [32] = "SHA3_UPDATE", [33] = "SHA3_KAT", [64] = "ELLIPTIC_GENERATE_PUBLIC_KEY", [65] = "ELLIPTIC_GENERATE_SIGN", [66] = "ELLIPTIC_VALIDATE_PUBLIC_KEY", [67] = "ELLIPTIC_VERIFY_SIGN", [68] = "ELLIPTIC_KAT", [96] = "AES_INIT", [97] = "AES_OP_INIT", [98] = "AES_UPDATE_AAD", [99] = "AES_ENCRYPT_UPDATE", [100] = "AES_ENCRYPT_FINAL", [101] = "AES_DECRYPT_UPDATE", [102] = "AES_DECRYPT_FINAL", [103] = "AES_KEY_ZERO", [104] = "AES_WRITE_KEY", [105] = "AES_LOCK_USER_KEY", [106] = "AES_KEK_DECRYPT", [107] = "AES_SET_DPA_CM", [108] = "AES_DECRYPT_KAT", [109] = "AES_DECRYPT_CM_KAT", [110] = "MAX", }; static const char *const puf_id[] = { [0] = "PUF_API_FEATURES", [1] = "PUF_REGISTRATION", [2] = "PUF_REGENERATION", [3] = "PUF_CLEAR_PUF_ID", }; static const char *const module[] = { [5] = "CRYPTO", [7] = "FPGA", [11] = "NVM", [12] = "PUF", }; static const char *const fpga_id[] = { [1] = "LOAD", }; static void versal_mbox_call_trace(uint32_t call) { uint32_t mid = call >> 8 & 0xff; uint32_t api = call & 0xff; const char *val = NULL; switch (mid) { case 5: if (api < ARRAY_SIZE(crypto_id)) val = crypto_id[api]; break; case 7: if (api < ARRAY_SIZE(fpga_id)) val = fpga_id[api]; break; case 11: if (api < ARRAY_SIZE(nvm_id)) val = nvm_id[api]; break; case 12: if (api < ARRAY_SIZE(puf_id)) val = puf_id[api]; break; default: break; } IMSG("--- mbox: service: %s\t call: %s", module[mid], val ? val : "Invalid"); }; static TEE_Result mbox_call(enum versal_ipi_api_id id, uint32_t blocking_call) { struct thread_smc_args args = { .a0 = PM_SIP_SVC | id, .a1 = reg_pair_to_64(0, ipi.lcl), .a2 = reg_pair_to_64(0, ipi.rmt), .a3 = reg_pair_to_64(0, blocking_call), }; thread_smccc(&args); /* Give the PLM time to access the console */ if (IS_ENABLED(CFG_VERSAL_TRACE_PLM)) mdelay(500); if (args.a0) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result versal_mbox_write_req(struct versal_ipi_cmd *cmd) { size_t i = 0; for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { if (!cmd->ibuf[i].mem.buf) continue; if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf, CACHELINE_LEN)) { EMSG("address not aligned: buffer %zu - %p", i, cmd->ibuf[i].mem.buf); return TEE_ERROR_GENERIC; } if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) { EMSG("length not aligned: buffer %zu - %zu", i, cmd->ibuf[i].mem.alloc_len); return TEE_ERROR_GENERIC; } cache_operation(TEE_CACHEFLUSH, cmd->ibuf[i].mem.buf, cmd->ibuf[i].mem.alloc_len); } memcpy(ipi.req, cmd->data, sizeof(cmd->data)); /* Cache operation on the IPI buffer is safe */ cache_operation(TEE_CACHEFLUSH, ipi.req, sizeof(cmd->data)); return TEE_SUCCESS; } static TEE_Result versal_mbox_read_rsp(struct versal_ipi_cmd *cmd, struct versal_ipi_cmd *rsp, uint32_t *status) { size_t i = 0; /* Cache operation on the IPI buffer is safe */ cache_operation(TEE_CACHEINVALIDATE, ipi.rsp, sizeof(rsp->data)); *status = *(uint32_t *)ipi.rsp; if (*status) return TEE_ERROR_GENERIC; if (rsp) memcpy(rsp->data, ipi.rsp, sizeof(rsp->data)); for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { if (!cmd->ibuf[i].mem.buf) continue; if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf, CACHELINE_LEN)) { EMSG("address not aligned: buffer %zu - %p", i, cmd->ibuf[i].mem.buf); return TEE_ERROR_GENERIC; } if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) { EMSG("length not aligned: buffer %zu - %zu", i, cmd->ibuf[i].mem.alloc_len); return TEE_ERROR_GENERIC; } cache_operation(TEE_CACHEINVALIDATE, cmd->ibuf[i].mem.buf, cmd->ibuf[i].mem.alloc_len); } return TEE_SUCCESS; } TEE_Result versal_mbox_alloc(size_t len, const void *init, struct versal_mbox_mem *mem) { mem->buf = memalign(CACHELINE_LEN, ROUNDUP(len, CACHELINE_LEN)); if (!mem->buf) panic(); memset(mem->buf, 0, ROUNDUP(len, CACHELINE_LEN)); if (init) memcpy(mem->buf, init, len); mem->alloc_len = ROUNDUP(len, CACHELINE_LEN); mem->len = len; return TEE_SUCCESS; } TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd, struct versal_ipi_cmd *rsp, uint32_t *err) { TEE_Result ret = TEE_SUCCESS; uint32_t remote_status = 0; mutex_lock(&ipi.lock); ret = versal_mbox_write_req(cmd); if (ret) { EMSG("Can't write the request command"); goto out; } if (IS_ENABLED(CFG_VERSAL_TRACE_MBOX)) versal_mbox_call_trace(cmd->data[0]); ret = mbox_call(IPI_MAILBOX_NOTIFY, IPI_BLOCK); if (ret) { EMSG("IPI error"); goto out; } ret = versal_mbox_read_rsp(cmd, rsp, &remote_status); if (ret) EMSG("Can't read the remote response"); if (remote_status) { if (err) *err = remote_status; /* * Check the remote code (FSBL repository) in xplmi_status.h * and the relevant service error (ie, xsecure_error.h) for * detailed information. */ DMSG("PLM: plm status = 0x%" PRIx32 ", lib_status = 0x%" PRIx32, (remote_status & 0xFFFF0000) >> 16, (remote_status & 0x0000FFFF)); ret = TEE_ERROR_GENERIC; } out: mutex_unlock(&ipi.lock); return ret; } static TEE_Result versal_mbox_init(void) { switch (CFG_VERSAL_MBOX_IPI_ID) { case 0: ipi.buf = IPI_BUFFER_APU_ID_0_BASE; ipi.lcl = IPI_ID_0; break; case 3: break; case 4: ipi.buf = IPI_BUFFER_APU_ID_4_BASE; ipi.lcl = IPI_ID_4; break; case 5: ipi.buf = IPI_BUFFER_APU_ID_5_BASE; ipi.lcl = IPI_ID_5; break; default: EMSG("Invalid IPI requested"); return TEE_ERROR_GENERIC; } ipi.req = core_mmu_add_mapping(MEM_AREA_RAM_SEC, ipi.buf + IPI_BUFFER_REMOTE_OFFSET + IPI_BUFFER_REQ_OFFSET, sizeof(struct versal_ipi_cmd)); ipi.rsp = core_mmu_add_mapping(MEM_AREA_RAM_SEC, ipi.buf + IPI_BUFFER_REMOTE_OFFSET + IPI_BUFFER_RESP_OFFSET, sizeof(struct versal_ipi_cmd)); if (!ipi.req || !ipi.rsp) panic(); mutex_init(&ipi.lock); return mbox_call(IPI_MAILBOX_OPEN, IPI_BLOCK); } early_init(versal_mbox_init); optee_os-4.3.0/core/drivers/versal_nvm.c000066400000000000000000000553171464416617300203100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2022 Foundries.io Ltd * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #include #include #include "drivers/versal_nvm.h" #define NVM_WORD_LEN 4 /* Protocol API with the remote processor */ #define NVM_MODULE_SHIFT 8 #define NVM_MODULE 11 #define NVM_API_ID(_id) ((NVM_MODULE << NVM_MODULE_SHIFT) | (_id)) #define __aligned_efuse __aligned(CACHELINE_LEN) /* Internal */ struct versal_efuse_puf_fuse_addr { uint64_t data_addr; uint32_t start_row; uint32_t num_rows; uint8_t env_monitor_dis; uint8_t prgm_puf_fuse; uint8_t pad[46]; }; /* * Max size of the buffer needed for the remote processor to DMA efuse _data_ * to/from */ #define EFUSE_MAX_LEN (EFUSE_MAX_USER_FUSES * sizeof(uint32_t)) enum versal_nvm_api_id { API_FEATURES = 0, BBRAM_WRITE_AES_KEY = 1, BBRAM_ZEROIZE = 2, BBRAM_WRITE_USER_DATA = 3, BBRAM_READ_USER_DATA = 4, BBRAM_LOCK_WRITE_USER_DATA = 5, EFUSE_WRITE = 6, EFUSE_WRITE_PUF = 7, EFUSE_PUF_USER_FUSE_WRITE = 8, EFUSE_READ_IV = 9, EFUSE_READ_REVOCATION_ID = 10, EFUSE_READ_OFFCHIP_REVOCATION_ID = 11, EFUSE_READ_USER_FUSES = 12, EFUSE_READ_MISC_CTRL = 13, EFUSE_READ_SEC_CTRL = 14, EFUSE_READ_SEC_MISC1 = 15, EFUSE_READ_BOOT_ENV_CTRL = 16, EFUSE_READ_PUF_SEC_CTRL = 17, EFUSE_READ_PPK_HASH = 18, EFUSE_READ_DEC_EFUSE_ONLY = 19, EFUSE_READ_DNA = 20, EFUSE_READ_PUF_USER_FUSES = 21, EFUSE_READ_PUF = 22, EFUSE_INVALID = 23, }; /* uint64_t are memory addresses */ struct versal_efuse_data { uint64_t env_mon_dis_flag; uint64_t aes_key_addr; uint64_t ppk_hash_addr; uint64_t dec_only_addr; uint64_t sec_ctrl_addr; uint64_t misc_ctrl_addr; uint64_t revoke_id_addr; uint64_t iv_addr; uint64_t user_fuse_addr; uint64_t glitch_cfg_addr; uint64_t boot_env_ctrl_addr; uint64_t misc1_ctrl_addr; uint64_t offchip_id_addr; uint8_t pad[24]; }; /* Helper read and write requests (not part of the protocol) */ struct versal_nvm_buf { size_t len; void *buf; }; struct versal_nvm_read_req { enum versal_nvm_api_id efuse_id; enum versal_nvm_revocation_id revocation_id; enum versal_nvm_offchip_id offchip_id; enum versal_nvm_ppk_type ppk_type; enum versal_nvm_iv_type iv_type; struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF]; }; struct versal_bbram_data { size_t aes_key_len; uint32_t user_data; }; struct versal_nvm_write_req { struct versal_efuse_data data; struct versal_bbram_data bbram; struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF]; enum versal_nvm_api_id efuse_id; }; static TEE_Result prepare_cmd(struct versal_ipi_cmd *cmd, enum versal_nvm_api_id efuse, struct versal_nvm_buf *ibufs, uint32_t *arg) { uint32_t a = 0; uint32_t b = 0; size_t i = 0; cmd->data[i++] = NVM_API_ID(efuse); if (arg) cmd->data[i++] = *arg; if (!ibufs[0].buf) return TEE_SUCCESS; reg_pair_from_64(virt_to_phys(ibufs[0].buf), &b, &a); cmd->data[i++] = a; cmd->data[i++] = b; for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) { cmd->ibuf[i].mem.alloc_len = ibufs[i].len; cmd->ibuf[i].mem.buf = ibufs[i].buf; } return TEE_SUCCESS; } static TEE_Result efuse_req(enum versal_nvm_api_id efuse, struct versal_nvm_buf *ibufs, uint32_t *arg) { struct versal_ipi_cmd cmd = { }; TEE_Result ret = TEE_SUCCESS; ret = prepare_cmd(&cmd, efuse, ibufs, arg); if (ret) return ret; ret = versal_mbox_notify(&cmd, NULL, NULL); if (ret) EMSG("Mailbox error"); return ret; } static TEE_Result versal_alloc_read_buffer(struct versal_nvm_read_req *req) { assert(req); req->ibuf[0].len = 1024; req->ibuf[0].buf = alloc_cache_aligned(req->ibuf[0].len); if (!req->ibuf[0].buf) return TEE_ERROR_OUT_OF_MEMORY; return TEE_SUCCESS; } static void versal_free_read_buffer(struct versal_nvm_read_req *req) { assert(req); free(req->ibuf[0].buf); } static void *versal_get_read_buffer(struct versal_nvm_read_req *req) { assert(req); return req->ibuf[0].buf; } static TEE_Result versal_nvm_read(struct versal_nvm_read_req *req) { uint32_t *arg = NULL; uint32_t val = 0; if (!req) return TEE_ERROR_GENERIC; switch (req->efuse_id) { case EFUSE_READ_DNA: case EFUSE_READ_DEC_EFUSE_ONLY: case EFUSE_READ_PUF_SEC_CTRL: case EFUSE_READ_BOOT_ENV_CTRL: case EFUSE_READ_SEC_CTRL: case EFUSE_READ_MISC_CTRL: case EFUSE_READ_SEC_MISC1: case EFUSE_READ_USER_FUSES: case EFUSE_READ_PUF_USER_FUSES: case EFUSE_READ_PUF: break; case EFUSE_READ_OFFCHIP_REVOCATION_ID: val = req->offchip_id; arg = &val; break; case EFUSE_READ_REVOCATION_ID: val = req->revocation_id; arg = &val; break; case EFUSE_READ_IV: val = req->iv_type; arg = &val; break; case EFUSE_READ_PPK_HASH: val = req->ppk_type; arg = &val; break; case BBRAM_READ_USER_DATA: break; default: return TEE_ERROR_GENERIC; } return efuse_req(req->efuse_id, req->ibuf, arg); } static TEE_Result versal_nvm_write(struct versal_nvm_write_req *req) { uint32_t *arg = NULL; uint32_t val = 0; switch (req->efuse_id) { case BBRAM_WRITE_AES_KEY: val = req->bbram.aes_key_len; arg = &val; break; case BBRAM_WRITE_USER_DATA: val = req->bbram.user_data; arg = &val; break; case EFUSE_PUF_USER_FUSE_WRITE: case EFUSE_WRITE_PUF: case EFUSE_WRITE: break; default: return TEE_ERROR_GENERIC; } return efuse_req(req->efuse_id, req->ibuf, arg); } TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len, uint32_t first, size_t num) { struct versal_efuse_user_data cfg __aligned_efuse = { .start = first, .num = num, }; struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_USER_FUSES, }; void *rsp = NULL; if (first + num > EFUSE_MAX_USER_FUSES || len < num * sizeof(uint32_t)) return TEE_ERROR_BAD_PARAMETERS; rsp = alloc_cache_aligned(1024); if (!rsp) return TEE_ERROR_OUT_OF_MEMORY; req.ibuf[0].buf = &cfg; req.ibuf[0].len = sizeof(cfg); req.ibuf[1].buf = rsp; req.ibuf[1].len = 1024; cfg.addr = virt_to_phys((void *)rsp); if (versal_nvm_read(&req)) { free(rsp); return TEE_ERROR_GENERIC; } memcpy(buf, rsp, num * sizeof(uint32_t)); free(rsp); return TEE_SUCCESS; } TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_DNA, }; if (len < EFUSE_DNA_LEN) return TEE_ERROR_BAD_PARAMETERS; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), EFUSE_DNA_LEN); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len, enum versal_nvm_iv_type type) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_IV, .iv_type = type, }; if (len < EFUSE_IV_LEN) return TEE_ERROR_BAD_PARAMETERS; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), EFUSE_IV_LEN); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len, enum versal_nvm_ppk_type type) { struct versal_nvm_read_req req = { req.efuse_id = EFUSE_READ_PPK_HASH, .ppk_type = type, }; if (len < EFUSE_PPK_LEN) return TEE_ERROR_BAD_PARAMETERS; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) return TEE_ERROR_GENERIC; memcpy(buf, versal_get_read_buffer(&req), EFUSE_PPK_LEN); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_write_user_data(uint32_t *buf, size_t len, uint32_t first, size_t num) { uint32_t lbuf[EFUSE_MAX_USER_FUSES] __aligned_efuse = { 0 }; struct versal_efuse_user_data cfg __aligned_efuse = { .addr = (uintptr_t)lbuf, .start = first, .num = num, }; struct versal_nvm_write_req __aligned_efuse req = { .data.user_fuse_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; size_t i = 0; if (first + num > EFUSE_MAX_USER_FUSES || len < num * sizeof(uint32_t)) return TEE_ERROR_BAD_PARAMETERS; req.data.user_fuse_addr = virt_to_phys((void *)req.data.user_fuse_addr); cfg.addr = virt_to_phys(lbuf); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); req.ibuf[2].buf = lbuf; req.ibuf[2].len = sizeof(lbuf); for (i = 0; i < cfg.num; i++) lbuf[i] = buf[i]; return versal_nvm_write(&req); } TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys) { struct versal_efuse_aes_keys cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.aes_key_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, keys, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash) { struct versal_efuse_ppk_hash cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.ppk_hash_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, hash, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p) { struct versal_efuse_ivs cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.iv_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p) { struct versal_efuse_dec_only cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.dec_only_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p) { struct versal_efuse_sec_ctrl_bits cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.sec_ctrl_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p) { struct versal_efuse_misc_ctrl_bits cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.misc_ctrl_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits *p) { struct versal_efuse_glitch_cfg_bits cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.glitch_cfg_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits *p) { struct versal_efuse_boot_env_ctrl_bits cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.boot_env_ctrl_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p) { struct versal_efuse_sec_misc1_bits cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.misc1_ctrl_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p) { struct versal_efuse_offchip_ids cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.offchip_id_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; memcpy(&cfg, p, sizeof(cfg)); req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type) { struct versal_efuse_misc_ctrl_bits cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.misc_ctrl_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; req.data.misc_ctrl_addr = virt_to_phys((void *)req.data.misc_ctrl_addr); if (type == EFUSE_PPK0) cfg.ppk0_invalid = 1; else if (type == EFUSE_PPK1) cfg.ppk1_invalid = 1; else if (type == EFUSE_PPK2) cfg.ppk2_invalid = 1; else return TEE_ERROR_BAD_PARAMETERS; req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_write_revoke_id(uint32_t id) { struct versal_efuse_revoke_ids cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .data.revoke_id_addr = virt_to_phys(&cfg), .data.env_mon_dis_flag = 1, .efuse_id = EFUSE_WRITE, }; uint32_t row = 0; uint32_t bit = 0; row = id >> (NVM_WORD_LEN + 1); bit = id & (NVM_WORD_LEN - 1); cfg.revoke_id[row] = BIT(bit); cfg.prgm_revoke_id = 1; req.ibuf[0].buf = &req.data; req.ibuf[0].len = sizeof(req.data); req.ibuf[1].buf = &cfg; req.ibuf[1].len = sizeof(cfg); return versal_nvm_write(&req); } TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, enum versal_nvm_revocation_id id) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_REVOCATION_ID, .revocation_id = id, }; if (len < EFUSE_REVOCATION_ID_LEN) return TEE_ERROR_BAD_PARAMETERS; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), EFUSE_REVOCATION_ID_LEN); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_MISC_CTRL, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_SEC_CTRL, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_SEC_MISC1, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_BOOT_ENV_CTRL, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, enum versal_nvm_offchip_id id) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_OFFCHIP_REVOCATION_ID, .offchip_id = id, }; if (len < EFUSE_OFFCHIP_REVOCATION_ID_LEN) return TEE_ERROR_BAD_PARAMETERS; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), EFUSE_REVOCATION_ID_LEN); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_DEC_EFUSE_ONLY, }; if (len < EFUSE_DEC_ONLY_LEN) return TEE_ERROR_BAD_PARAMETERS; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), EFUSE_DEC_ONLY_LEN); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits *buf) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_PUF_SEC_CTRL, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf) { struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_PUF, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; memcpy(versal_get_read_buffer(&req), buf, sizeof(*buf)); if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf)); versal_free_read_buffer(&req); return TEE_SUCCESS; } /* * This functionality requires building the PLM with XNVM_ACCESS_PUF_USER_DATA * Calls will fail otherwise. * When available, efuse_read_puf becomes unavailable. */ TEE_Result versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p) { uint32_t fuses[PUF_EFUSES_WORDS]__aligned_efuse = { 0 }; struct versal_efuse_puf_fuse_addr lbuf __aligned_efuse = { .env_monitor_dis = p->env_monitor_dis, .prgm_puf_fuse = p->prgm_puf_fuse, .start_row = p->start_row, .num_rows = p->num_rows, .data_addr = virt_to_phys(fuses), }; struct versal_nvm_read_req req = { .efuse_id = EFUSE_READ_PUF_USER_FUSES, }; req.ibuf[0].buf = &lbuf; req.ibuf[0].len = sizeof(lbuf); req.ibuf[1].buf = fuses; req.ibuf[1].len = sizeof(fuses); if (versal_nvm_read(&req)) return TEE_ERROR_GENERIC; memcpy(p->data_addr, fuses, sizeof(fuses)); return TEE_SUCCESS; } /* * This functionality requires building the PLM with XNVM_ACCESS_PUF_USER_DATA. * Calls will fail otherwise. * When available, efuse_write_puf becomes unavailable. */ TEE_Result versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p) { uint32_t fuses[PUF_EFUSES_WORDS]__aligned_efuse = { 0 }; struct versal_efuse_puf_fuse_addr lbuf __aligned_efuse = { .env_monitor_dis = p->env_monitor_dis, .prgm_puf_fuse = p->prgm_puf_fuse, .start_row = p->start_row, .num_rows = p->num_rows, .data_addr = virt_to_phys(fuses), }; struct versal_nvm_write_req req = { .efuse_id = EFUSE_PUF_USER_FUSE_WRITE, }; memcpy(fuses, p->data_addr, sizeof(p->data_addr)); req.ibuf[0].buf = &lbuf; req.ibuf[0].len = sizeof(lbuf); req.ibuf[1].buf = fuses; req.ibuf[1].len = sizeof(fuses); if (versal_nvm_write(&req)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf) { struct versal_efuse_puf_header cfg __aligned_efuse = { }; struct versal_nvm_write_req req __aligned_efuse = { .efuse_id = EFUSE_WRITE_PUF, }; memcpy(&cfg, buf, sizeof(*buf)); req.ibuf[0].buf = &cfg; req.ibuf[0].len = sizeof(cfg); if (versal_nvm_write(&req)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len) { struct versal_nvm_write_req req __aligned_efuse = { .efuse_id = BBRAM_WRITE_AES_KEY, .bbram.aes_key_len = len, }; void *buf = NULL; if (len != 32) return TEE_ERROR_BAD_PARAMETERS; buf = alloc_cache_aligned(1024); if (!buf) return TEE_ERROR_OUT_OF_MEMORY; memcpy(buf, key, len); req.ibuf[0].buf = buf; req.ibuf[0].len = 1024; if (versal_nvm_write(&req)) { free(buf); return TEE_ERROR_GENERIC; } free(buf); return TEE_SUCCESS; } TEE_Result versal_bbram_zeroize(void) { struct versal_nvm_write_req req __aligned_efuse = { .efuse_id = BBRAM_ZEROIZE, }; if (versal_nvm_write(&req)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } TEE_Result versal_bbram_write_user_data(uint32_t data) { struct versal_nvm_write_req req __aligned_efuse = { .efuse_id = BBRAM_WRITE_USER_DATA, .bbram.user_data = data, }; if (versal_nvm_write(&req)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } TEE_Result versal_bbram_read_user_data(uint32_t *data) { struct versal_nvm_read_req req = { .efuse_id = BBRAM_READ_USER_DATA, }; if (versal_alloc_read_buffer(&req)) return TEE_ERROR_OUT_OF_MEMORY; if (versal_nvm_read(&req)) { versal_free_read_buffer(&req); return TEE_ERROR_GENERIC; } memcpy(data, versal_get_read_buffer(&req), sizeof(*data)); versal_free_read_buffer(&req); return TEE_SUCCESS; } TEE_Result versal_bbram_lock_write_user_data(void) { struct versal_nvm_write_req req __aligned_efuse = { .efuse_id = BBRAM_LOCK_WRITE_USER_DATA, }; if (versal_nvm_write(&req)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/versal_pm.c000066400000000000000000000126421464416617300201160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2022 Foundries.io Ltd * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* VERSAL_SIP_UID: 2ab9e4ec-93b9-11e7-a019dfe0dbad0ae0 */ #define VERSAL_SIP_UID_0 U(0xece4b92a) #define VERSAL_SIP_UID_1 U(0xe711b993) #define VERSAL_SIP_UID_2 U(0xe0df19a0) #define VERSAL_SIP_UID_3 U(0xe00aaddb) #define VERSAL_SIP_MAJOR 0 #define VERSAL_SIP_MINOR 1 #define VERSAL_SIP_SVC_VERSION 0x8200ff03 #define VERSAL_SIP_SVC_UID 0x8200ff01 #define VERSAL_SIP_SVC 0xc2000000 #define PAYLOAD_ARG_CNT 8 /* MBOX IPI */ #define PM_MODULE_SHIFT 8 #define PM_MODULE 2 #define PM_API_ID(x) ((PM_MODULE << PM_MODULE_SHIFT) | (x)) #define VERSAL_PM_MAJOR 0 #define VERSAL_PM_MINOR 1 /* PM API ids */ #define PM_GET_API_VERSION 1 #define PM_GET_DEVICE_STATUS 3 #define PM_GET_OP_CHARACTERISTIC 4 #define PM_REGISTER_NOTIFIER 5 #define PM_REQ_SUSPEND 6 #define PM_SELF_SUSPEND 7 #define PM_FORCE_POWERDOWN 8 #define PM_ABORT_SUSPEND 9 #define PM_REQ_WAKEUP 10 #define PM_SET_WAKEUP_SOURCE 11 #define PM_SYSTEM_SHUTDOWN 12 #define PM_REQUEST_DEVICE 13 #define PM_RELEASE_DEVICE 14 #define PM_SET_REQUIREMENT 15 #define PM_SET_MAX_LATENCY 16 #define PM_RESET_ASSERT 17 #define PM_RESET_GET_STATUS 18 #define PM_INIT_FINALIZE 21 #define PM_GET_CHIPID 24 #define PM_PINCTRL_REQUEST 28 #define PM_PINCTRL_RELEASE 29 #define PM_PINCTRL_GET_FUNCTION 30 #define PM_PINCTRL_SET_FUNCTION 31 #define PM_PINCTRL_CONFIG_PARAM_GET 32 #define PM_PINCTRL_CONFIG_PARAM_SET 33 #define PM_IOCTL 34 #define PM_QUERY_DATA 35 #define PM_CLOCK_ENABLE 36 #define PM_CLOCK_DISABLE 37 #define PM_CLOCK_GETSTATE 38 #define PM_CLOCK_SETDIVIDER 39 #define PM_CLOCK_GETDIVIDER 40 #define PM_CLOCK_SETRATE 41 #define PM_CLOCK_GETRATE 42 #define PM_CLOCK_SETPARENT 43 #define PM_CLOCK_GETPARENT 44 #define PM_PLL_SET_PARAMETER 48 #define PM_PLL_GET_PARAMETER 49 #define PM_PLL_SET_MODE 50 #define PM_PLL_GET_MODE 51 #define PM_FEATURE_CHECK 63 /* Loader API id */ #define PM_LOAD_PDI 0x701 /* PDI sources */ #define PDI_SRC_JTAG 0x0 #define PDI_SRC_QSPI24 0x1 #define PDI_SRC_QSPI32 0x2 #define PDI_SRC_SD0 0x3 #define PDI_SRC_EMMC0 0x4 #define PDI_SRC_SD1 0x5 #define PDI_SRC_EMMC1 0x6 #define PDI_SRC_USB 0x7 #define PDI_SRC_OSPI 0x8 #define PDI_SRC_SBI 0x9 #define PDI_SRC_SMAP 0xA #define PDI_SRC_PCIE 0xB #define PDI_SRC_SD1_LS 0xE #define PDI_SRC_DDR 0xF struct versal_sip_payload { uint32_t data[PAYLOAD_ARG_CNT]; }; static uint32_t versal_sip_call(uint32_t smc_fid, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, struct versal_sip_payload *payload) { struct thread_smc_args args = { .a0 = smc_fid, .a1 = reg_pair_to_64(arg1, arg0), .a2 = reg_pair_to_64(arg3, arg2), }; thread_smccc(&args); if (payload) { reg_pair_from_64(args.a0, &payload->data[1], &payload->data[0]); reg_pair_from_64(args.a1, &payload->data[3], &payload->data[2]); reg_pair_from_64(args.a2, &payload->data[5], &payload->data[4]); reg_pair_from_64(args.a3, &payload->data[7], &payload->data[6]); } /* allow the PLM to output its debug information */ if (IS_ENABLED(CFG_VERSAL_TRACE_PLM)) mdelay(500); return args.a0; } /* SIP call to program the FPGA has been obsoleted, use the PLM */ TEE_Result versal_write_fpga(paddr_t pa) { struct versal_ipi_cmd cmd = { }; cmd.data[0] = PM_LOAD_PDI; cmd.data[1] = PDI_SRC_DDR; reg_pair_from_64(pa, &cmd.data[2], &cmd.data[3]); if (versal_mbox_notify(&cmd, NULL, NULL)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } TEE_Result versal_soc_version(uint8_t *version) { struct versal_sip_payload p = { }; const uint32_t version_shift = 12; if (!version) return TEE_ERROR_BAD_PARAMETERS; if (versal_sip_call(VERSAL_SIP_SVC | PM_GET_CHIPID, 0, 0, 0, 0, &p)) return TEE_ERROR_GENERIC; *version = p.data[2] >> version_shift; return TEE_SUCCESS; } static bool uuid_is_versal_pm(void) { struct versal_sip_payload p = { }; versal_sip_call(VERSAL_SIP_SVC_UID, 0, 0, 0, 0, &p); if (p.data[0] == VERSAL_SIP_UID_0 && p.data[2] == VERSAL_SIP_UID_1 && p.data[4] == VERSAL_SIP_UID_2 && p.data[6] == VERSAL_SIP_UID_3) return true; return false; } static TEE_Result versal_check_pm_abi(void) { struct versal_sip_payload p = { }; struct versal_ipi_cmd cmd = { }; struct versal_ipi_cmd rsp = { }; unsigned int major = 0; unsigned int minor = 0; if (!uuid_is_versal_pm()) { EMSG("Invalid SiP Service"); return TEE_ERROR_GENERIC; } if (versal_sip_call(VERSAL_SIP_SVC_VERSION, 0, 0, 0, 0, &p)) return TEE_ERROR_GENERIC; major = p.data[0]; minor = p.data[2]; if (major != VERSAL_SIP_MAJOR || minor < VERSAL_SIP_MINOR) { EMSG("Invalid SiP version: Major %d, Minor %d", major, minor); return TEE_ERROR_GENERIC; } cmd.data[0] = PM_API_ID(PM_GET_API_VERSION); if (versal_mbox_notify(&cmd, &rsp, NULL)) return TEE_ERROR_GENERIC; major = rsp.data[1] & 0xFFFF; minor = rsp.data[1] >> 16; if (major != VERSAL_PM_MAJOR || minor < VERSAL_PM_MINOR) { EMSG("Invalid PM version: Major %d, Minor %d", major, minor); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } early_init_late(versal_check_pm_abi); optee_os-4.3.0/core/drivers/versal_puf.c000066400000000000000000000204351464416617300202730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2022 Foundries.io Ltd * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #include #include /* Protocol API with the remote processor */ #define VERSAL_PUF_MODULE_SHIFT 8 #define VERSAL_PUF_MODULE 12 #define PUF_API_ID(_id) ((VERSAL_PUF_MODULE << VERSAL_PUF_MODULE_SHIFT) | (_id)) enum versal_puf_error { /* Registration */ ERROR_INVALID_PARAM = 0x02, ERROR_INVALID_SYNDROME_MODE = 0x03, ERROR_SYNDROME_WORD_WAIT_TIMEOUT = 0x04, ERROR_PUF_DONE_WAIT_TIMEOUT = 0x07, ERROR_REGISTRATION_INVALID = 0x08, SHUTTER_GVF_MISMATCH = 0x09, ERROR_SYN_DATA_ERROR = 0x0A, IRO_FREQ_WRITE_MISMATCH = 0x0B, /* Regeneration */ ERROR_CHASH_NOT_PROGRAMMED = 0x10, ERROR_PUF_STATUS_DONE_TIMEOUT = 0x11, ERROR_INVALID_REGENERATION_TYPE = 0x12, ERROR_INVALID_PUF_OPERATION = 0x13, ERROR_REGENERATION_INVALID = 0x14, ERROR_REGEN_PUF_HD_INVALID = 0x15, ERROR_INVALID_READ_HD_INPUT = 0x16, ERROR_PUF_DONE_KEY_NT_RDY = 0x17, ERROR_PUF_DONE_ID_NT_RDY = 0x18, ERROR_PUF_ID_ZERO_TIMEOUT = 0x19, }; #define VERSAL_PUF_ERROR(m) { .error = (m), .name = TO_STR(m) } static const char *versal_puf_error(uint8_t err) { struct { enum versal_puf_error error; const char *name; } elist[] = { /* Registration */ VERSAL_PUF_ERROR(ERROR_INVALID_PARAM), VERSAL_PUF_ERROR(ERROR_INVALID_SYNDROME_MODE), VERSAL_PUF_ERROR(ERROR_SYNDROME_WORD_WAIT_TIMEOUT), VERSAL_PUF_ERROR(ERROR_PUF_DONE_WAIT_TIMEOUT), VERSAL_PUF_ERROR(ERROR_REGISTRATION_INVALID), VERSAL_PUF_ERROR(SHUTTER_GVF_MISMATCH), VERSAL_PUF_ERROR(ERROR_SYN_DATA_ERROR), VERSAL_PUF_ERROR(IRO_FREQ_WRITE_MISMATCH), /* Regeneration */ VERSAL_PUF_ERROR(ERROR_CHASH_NOT_PROGRAMMED), VERSAL_PUF_ERROR(ERROR_PUF_STATUS_DONE_TIMEOUT), VERSAL_PUF_ERROR(ERROR_INVALID_REGENERATION_TYPE), VERSAL_PUF_ERROR(ERROR_INVALID_PUF_OPERATION), VERSAL_PUF_ERROR(ERROR_REGENERATION_INVALID), VERSAL_PUF_ERROR(ERROR_REGEN_PUF_HD_INVALID), VERSAL_PUF_ERROR(ERROR_INVALID_READ_HD_INPUT), VERSAL_PUF_ERROR(ERROR_PUF_DONE_KEY_NT_RDY), VERSAL_PUF_ERROR(ERROR_PUF_DONE_ID_NT_RDY), VERSAL_PUF_ERROR(ERROR_PUF_ID_ZERO_TIMEOUT), }; size_t error = 0; size_t index = 0; if (err <= ERROR_PUF_ID_ZERO_TIMEOUT && err >= ERROR_INVALID_PARAM) { index = err - ERROR_INVALID_PARAM; /* Spectre gadget protection: array index is external event */ error = confine_array_index(index, ARRAY_SIZE(elist)); if (elist[error].name) return elist[error].name; return "Invalid"; } return "Unknown"; } /* * Register the Physical Unclonable Function (prior operating with it) * * This must happen during the device provisioning phase and can be done from * the Secure World via this interface or from an earlier firmware. */ TEE_Result versal_puf_register(struct versal_puf_data *buf, struct versal_puf_cfg *cfg) { struct versal_puf_data_req req __aligned_puf = { }; struct versal_mbox_mem request = { .alloc_len = sizeof(req), .len = sizeof(req), .buf = &req, }; struct versal_mbox_mem efuse_syn_data_addr = { }; struct versal_mbox_mem syndrome_data_addr = { }; struct versal_mbox_mem puf_id_addr = { }; struct versal_mbox_mem hash_addr = { }; struct versal_mbox_mem aux_addr = { }; struct versal_ipi_cmd arg = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data, &efuse_syn_data_addr); versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, &syndrome_data_addr); arg.ibuf[0].mem = request; arg.ibuf[1].mem = syndrome_data_addr; arg.ibuf[2].mem = hash_addr; arg.ibuf[3].mem = aux_addr; arg.ibuf[4].mem = puf_id_addr; arg.ibuf[5].mem = efuse_syn_data_addr; req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf); req.syndrome_data_addr = virt_to_phys(syndrome_data_addr.buf); req.puf_id_addr = virt_to_phys(puf_id_addr.buf); req.hash_addr = virt_to_phys(hash_addr.buf); req.aux_addr = virt_to_phys(aux_addr.buf); req.global_var_filter = cfg->global_var_filter; req.shutter_value = cfg->shutter_value; req.puf_operation = cfg->puf_operation; req.read_option = cfg->read_option; req.reg_mode = cfg->reg_mode; arg.data[0] = PUF_API_ID(VERSAL_PUF_REGISTER); reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf), &arg.data[2], &arg.data[1]); if (versal_mbox_notify(&arg, NULL, &err)) { EMSG("Versal, failed to register the PUF [%s]", versal_puf_error(err)); ret = TEE_ERROR_GENERIC; } /* Return the generated data */ memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id)); memcpy(&buf->chash, hash_addr.buf, sizeof(buf->chash)); memcpy(&buf->aux, aux_addr.buf, sizeof(buf->aux)); memcpy(buf->efuse_syn_data, efuse_syn_data_addr.buf, sizeof(buf->efuse_syn_data)); memcpy(buf->syndrome_data, syndrome_data_addr.buf, sizeof(buf->syndrome_data)); free(syndrome_data_addr.buf); free(hash_addr.buf); free(aux_addr.buf); free(puf_id_addr.buf); free(efuse_syn_data_addr.buf); return ret; } /* * Re-seed the PUF circuitry so it can re-generate the Key Encryption Key. * * Depending on the configuration options it might use eFused data instead of * the helper data provided via the interface. */ TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, struct versal_puf_cfg *cfg) { struct versal_puf_data_req req __aligned_puf = { }; struct versal_mbox_mem request = { .alloc_len = sizeof(req), .len = sizeof(req), .buf = &req, }; struct versal_mbox_mem efuse_syn_data_addr = { }; struct versal_mbox_mem syndrome_data_addr = { }; struct versal_mbox_mem puf_id_addr = { }; struct versal_mbox_mem hash_addr = { }; struct versal_mbox_mem aux_addr = { }; struct versal_ipi_cmd arg = { }; TEE_Result ret = TEE_SUCCESS; uint32_t err = 0; versal_mbox_alloc(sizeof(buf->puf_id), buf->puf_id, &puf_id_addr); versal_mbox_alloc(sizeof(buf->chash), &buf->chash, &hash_addr); versal_mbox_alloc(sizeof(buf->aux), &buf->aux, &aux_addr); versal_mbox_alloc(sizeof(buf->efuse_syn_data), buf->efuse_syn_data, &efuse_syn_data_addr); versal_mbox_alloc(sizeof(buf->syndrome_data), buf->syndrome_data, &syndrome_data_addr); arg.ibuf[0].mem = request; arg.ibuf[1].mem = syndrome_data_addr; arg.ibuf[2].mem = hash_addr; arg.ibuf[3].mem = aux_addr; arg.ibuf[4].mem = puf_id_addr; arg.ibuf[5].mem = efuse_syn_data_addr; req.efuse_syn_data_addr = virt_to_phys(efuse_syn_data_addr.buf); req.syndrome_addr = virt_to_phys(syndrome_data_addr.buf); req.puf_id_addr = virt_to_phys(puf_id_addr.buf); req.hash_addr = virt_to_phys(hash_addr.buf); req.aux_addr = virt_to_phys(aux_addr.buf); req.global_var_filter = cfg->global_var_filter; req.shutter_value = cfg->shutter_value; req.puf_operation = cfg->puf_operation; req.read_option = cfg->read_option; req.reg_mode = cfg->reg_mode; arg.data[0] = PUF_API_ID(VERSAL_PUF_REGENERATE); reg_pair_from_64(virt_to_phys(arg.ibuf[0].mem.buf), &arg.data[2], &arg.data[1]); if (versal_mbox_notify(&arg, NULL, &err)) { EMSG("Versal, failed to regenerate the PUF [%s]", versal_puf_error(err)); ret = TEE_ERROR_GENERIC; } /* Return the updated PUF_ID */ memcpy(buf->puf_id, puf_id_addr.buf, sizeof(buf->puf_id)); free(syndrome_data_addr.buf); free(hash_addr.buf); free(aux_addr.buf); free(puf_id_addr.buf); free(efuse_syn_data_addr.buf); return ret; } /* * Clear/Hide the PUF Unique ID * * The fully accessible (non-secret) Unique ID is generated from the PUF */ TEE_Result versal_puf_clear_id(void) { struct versal_ipi_cmd arg = { }; arg.data[0] = PUF_API_ID(VERSAL_PUF_CLEAR_ID); if (versal_mbox_notify(&arg, NULL, NULL)) { EMSG("Versal, failed to clear the PUF_ID"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } /* Check that the API id is available to the client */ TEE_Result versal_puf_check_api(enum versal_puf_api id) { struct versal_ipi_cmd arg = { }; arg.data[0] = PUF_API_ID(VERSAL_PUF_API_FEATURES); arg.data[1] = id; if (versal_mbox_notify(&arg, NULL, NULL)) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/versal_sha3_384.c000066400000000000000000000043031464416617300207310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2022 * Author: Jorge Ramirez */ #include #include #include #include #include #define VERSAL_SHA3_384_FIRST_PACKET BIT(30) #define VERSAL_SHA3_384_NEXT_PACKET BIT(31) static struct mutex lock = MUTEX_INITIALIZER; static bool engine_ready; static TEE_Result input_plaintext(const uint8_t *src, size_t src_len) { uint32_t first = VERSAL_SHA3_384_FIRST_PACKET; struct versal_cmd_args arg = { .dlen = 1, }; struct versal_mbox_mem p = { }; TEE_Result ret = TEE_SUCCESS; size_t len = 0; size_t i = 0; while (src_len && !ret) { len = MIN(src_len, SMALL_PAGE_SIZE); src_len -= len; versal_mbox_alloc(len, src + i * SMALL_PAGE_SIZE, &p); arg.data[0] = first | VERSAL_SHA3_384_NEXT_PACKET | len; arg.ibuf[0].mem = p; ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL); if (ret) EMSG("VERSAL_SHA3_UPDATE [%ld, len = %zu]", i, len); free(p.buf); first = 0; i++; } return ret; } static TEE_Result get_ciphertext(uint8_t *dst, size_t dst_len) { struct versal_cmd_args arg = { }; struct versal_mbox_mem p = { }; TEE_Result ret = TEE_SUCCESS; versal_mbox_alloc(TEE_SHA384_HASH_SIZE, NULL, &p); arg.ibuf[0].mem = p; ret = versal_crypto_request(VERSAL_SHA3_UPDATE, &arg, NULL); if (!ret) memcpy(dst, p.buf, MIN(dst_len, (size_t)TEE_SHA384_HASH_SIZE)); else EMSG("VERSAL_SHA3_UPDATE final"); free(p.buf); return ret; } TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len) { TEE_Result ret = TEE_ERROR_BAD_PARAMETERS; if (!src_len || !dst_len || !src || !dst) return ret; if (!engine_ready) return TEE_ERROR_BAD_STATE; mutex_lock(&lock); ret = input_plaintext(src, src_len); if (!ret) ret = get_ciphertext(dst, dst_len); mutex_unlock(&lock); return ret; } static TEE_Result versal_sha3_384_init(void) { struct versal_cmd_args arg = { }; TEE_Result ret = TEE_SUCCESS; ret = versal_crypto_request(VERSAL_SHA3_KAT, &arg, NULL); if (!ret) engine_ready = true; return ret; } /* Be available for the HUK */ service_init(versal_sha3_384_init); optee_os-4.3.0/core/drivers/versal_trng.c000066400000000000000000000755221464416617300204620ustar00rootroot00000000000000// SPDX-License-Identifier: MIT /* * Copyright (C) 2022 Xilinx, Inc. All rights reserved. * Copyright (C) 2022 Foundries Ltd. * * Driver port from Xilinx's FSBL implementation, jorge@foundries.io * * The Xilinx True Random Number Generator(TRNG) module in Versal - PMC TRNG * consists of an entropy source, a deterministic random bit generator (DRBG) * and health test logic, which tests the randomness of the generated data. * The entropy source for the unit is an array of Ring Oscillators. * * The Versal PMC TRNG is envisaged to operate in three basic modes: DRNG, PTRNG * and HRNG . Each of these can be operated with or without Derivative Function * (DF), resulting in a total of 6 different modes of operation. * * NIST SP-800-90A practically requires the true random generators based on * CTR_DRBG to include a derivation function (DF). This is expected to be * implemented inside the Silicon (TRNG IP). However, the version of the IP used * in Versal PMC does not have this capability. Hence, a software * implementation of the DF is done in this driver. * * DRNG mode: Deterministic Random Number Generator mode. * In this mode, the DRBG portion of the TRNG is used. User provides * the (external) seed. * PTRNG mode: Physical True Random Number Generator mode (aka Entropy mode). * In this mode digitized Entropy source is output as random number. * HRNG mode: Hybrid Random Number Generator mode. * This is combination of above two modes in which the Entropy source * is used to provide the seed, which is fed to the DRBG, which in * turn generates the random number. * * DRNG mode with DF: It may not be common usecase to use the DF with DRNG as * the general expectation would be that the seed would have sufficient entropy. * However, the below guideline from section 10.2.1 of NIST SP-800-90A implies * that need for DF for DRNG mode too: "..the DRBG mechanism is specified to * allow an implementation tradeoff with respect to the use of this derivation * function. The use of the derivation function is optional if either an * approved RBG or an entropy source provides full entropy output when entropy * input is requested by the DRBG mechanism. Otherwise, the derivation function * shall be used". Sufficient large entropy data from user is fed to DF to * generate the seed which will be loaded into the external seed registers. * From here, it is similar to regular DRNG mode. * * PTRNG mode with DF: This mode is similar to PTRNG mode, however, the entropy * data from the core output registers are accumulated and fed to the DF * (instead of directly consuming it). The output of the DF would be final * random data. In this mode, the output of DF is not seed but the random data. * * HRNG mode with DF: This mode is the combination of the above two modes. * The entropy data is fed to the DF to produce seed. This seed is loaded to the * external seed registers which provide seed to the DRBG. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define TRNG_BASE 0xF1230000 #define TRNG_SIZE 0x10000 #define TRNG_STATUS 0x04 #define TRNG_STATUS_QCNT_SHIFT 9 #define TRNG_STATUS_QCNT_MASK (BIT(9) | BIT(10) | BIT(11)) #define TRNG_STATUS_CERTF_MASK BIT(3) #define TRNG_STATUS_DTF_MASK BIT(1) #define TRNG_STATUS_DONE_MASK BIT(0) #define TRNG_CTRL 0x08 #define TRNG_CTRL_EUMODE_MASK BIT(8) #define TRNG_CTRL_PRNGMODE_MASK BIT(7) #define TRNG_CTRL_PRNGSTART_MASK BIT(5) #define TRNG_CTRL_PRNGXS_MASK BIT(3) #define TRNG_CTRL_TRSSEN_MASK BIT(2) #define TRNG_CTRL_PRNGSRST_MASK BIT(0) #define TRNG_EXT_SEED_0 0x40 /* * Below registers are not directly referenced in driver but are accessed * with offset from TRNG_EXT_SEED_0 * Register: TRNG_EXT_SEED_1 0x00000044 * Register: TRNG_EXT_SEED_2 0x00000048 * Register: TRNG_EXT_SEED_3 0x0000004C * Register: TRNG_EXT_SEED_4 0x00000050 * Register: TRNG_EXT_SEED_5 0x00000054 * Register: TRNG_EXT_SEED_6 0x00000058 * Register: TRNG_EXT_SEED_7 0x0000005C * Register: TRNG_EXT_SEED_8 0x00000060 * Register: TRNG_EXT_SEED_9 0x00000064 * Register: TRNG_EXT_SEED_10 0x00000068 * Register: TRNG_EXT_SEED_11 0x0000006C */ #define TRNG_PER_STRING_0 0x80 /* * Below registers are not directly referenced in driver but are accessed * with offset from TRNG_PER_STRING_0 * Register: TRNG_PER_STRING_1 0x00000084 * Register: TRNG_PER_STRING_2 0x00000088 * Register: TRNG_PER_STRING_3 0x0000008C * Register: TRNG_PER_STRING_4 0x00000090 * Register: TRNG_PER_STRING_5 0x00000094 * Register: TRNG_PER_STRING_6 0x00000098 * Register: TRNG_PER_STRING_7 0x0000009C * Register: TRNG_PER_STRING_8 0x000000A0 * Register: TRNG_PER_STRING_9 0x000000A4 * Register: TRNG_PER_STRING_10 0x000000A8 * Register: TRNG_PER_STRING_11 0x000000AC */ #define TRNG_CORE_OUTPUT 0xC0 #define TRNG_RESET 0xD0 #define TRNG_RESET_VAL_MASK BIT(0) #define TRNG_OSC_EN 0xD4 #define TRNG_OSC_EN_VAL_MASK BIT(0) /* TRNG configuration */ #define TRNG_BURST_SIZE 16 #define TRNG_BURST_SIZE_BITS 128 #define TRNG_NUM_INIT_REGS 12 #define TRNG_REG_SIZE 32 #define TRNG_BYTES_PER_REG 4 #define TRNG_MAX_QCNT 4 #define TRNG_RESEED_TIMEOUT 15000 #define TRNG_GENERATE_TIMEOUT 8000 #define TRNG_MIN_DFLENMULT 2 #define TRNG_MAX_DFLENMULT 9 #define PRNGMODE_RESEED 0 #define PRNGMODE_GEN TRNG_CTRL_PRNGMODE_MASK #define RESET_DELAY 10 #define TRNG_SEC_STRENGTH_LEN 32 #define TRNG_PERS_STR_REGS 12 #define TRNG_PERS_STR_LEN 48 #define TRNG_SEED_REGS 12 #define TRNG_SEED_LEN 48 #define TRNG_GEN_LEN 32 #define RAND_BUF_LEN 4 #define BYTES_PER_BLOCK 16 #define ALL_A_PATTERN_32 0xAAAAAAAA #define ALL_5_PATTERN_32 0x55555555 /* Derivative function helper macros */ #define DF_SEED 0 #define DF_RAND 1 #define DF_IP_IV_LEN 4 #define DF_PAD_DATA_LEN 8 #define MAX_PRE_DF_LEN 160 #define MAX_PRE_DF_LEN_WORDS 40 #define DF_PERS_STR_LEN TRNG_PERS_STR_LEN #define DF_PAD_VAL 0x80 #define DF_KEY_LEN 32 #define BLK_SIZE 16 #define MAX_ROUNDS 14 enum trng_status { TRNG_UNINITIALIZED = 0, TRNG_HEALTHY, TRNG_ERROR, TRNG_CATASTROPHIC }; enum trng_mode { TRNG_HRNG = 0, TRNG_DRNG, TRNG_PTRNG }; struct trng_cfg { paddr_t base; vaddr_t addr; size_t len; }; struct trng_usr_cfg { enum trng_mode mode; uint64_t seed_life; /* number of TRNG requests per seed */ bool predict_en; /* enable prediction resistance */ bool pstr_en; /* enable personalization string */ uint32_t pstr[TRNG_PERS_STR_REGS]; bool iseed_en; /* enable an initial seed */ uint32_t init_seed[MAX_PRE_DF_LEN_WORDS]; uint32_t df_disable; /* disable the derivative function */ uint32_t dfmul; /* derivative function multiplier */ }; struct trng_stats { uint64_t bytes; uint64_t bytes_reseed; uint64_t elapsed_seed_life; }; /* block cipher derivative function algorithm */ struct trng_dfin { uint32_t ivc[DF_IP_IV_LEN]; uint32_t val1; uint32_t val2; uint8_t entropy[MAX_PRE_DF_LEN]; /* input entropy */ uint8_t pstr[DF_PERS_STR_LEN]; /* personalization string */ uint8_t pad_data[DF_PAD_DATA_LEN]; /* pad to multiples of 16 bytes*/ }; struct versal_trng { struct trng_cfg cfg; struct trng_usr_cfg usr_cfg; struct trng_stats stats; enum trng_status status; uint32_t buf[RAND_BUF_LEN]; /* buffer of random bits */ size_t len; struct trng_dfin dfin; uint8_t dfout[TRNG_SEED_LEN]; /* output of the DF operation */ }; /* Derivative function variables */ static unsigned char sbx1[256]; static unsigned char sbx2[256]; static unsigned char sbx3[256]; static unsigned char schedule[BLK_SIZE * (MAX_ROUNDS + 1)]; static unsigned int rounds; static void rota4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d) { uint8_t t = *a; *a = sbx1[*b]; *b = sbx1[*c]; *c = sbx1[*d]; *d = sbx1[t]; } static void rota2(uint8_t *a, uint8_t *b) { uint8_t t = *a; *a = sbx1[*b]; *b = sbx1[t]; } static void sbox4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d) { *a = sbx1[*a]; *b = sbx1[*b]; *c = sbx1[*c]; *d = sbx1[*d]; } static void xorb(uint8_t *res, const uint8_t *in) { size_t i = 0; for (i = 0; i < BLK_SIZE; ++i) res[i] ^= in[i]; } static void set_key(uint8_t *res, const uint8_t *src, unsigned int roundval) { memcpy(res, src, BLK_SIZE); xorb(res, schedule + roundval * BLK_SIZE); } static void mix_column_sbox(uint8_t *dst, const uint8_t *f) { size_t i = 0; size_t a = 0; size_t b = 0; size_t c = 0; size_t d = 0; for (i = 0; i < 4; i++) { a = 4 * i; b = (0x5 + a) % 16; c = (0xa + a) % 16; d = (0xf + a) % 16; dst[0 + a] = sbx2[f[a]] ^ sbx3[f[b]] ^ sbx1[f[c]] ^ sbx1[f[d]]; dst[1 + a] = sbx1[f[a]] ^ sbx2[f[b]] ^ sbx3[f[c]] ^ sbx1[f[d]]; dst[2 + a] = sbx1[f[a]] ^ sbx1[f[b]] ^ sbx2[f[c]] ^ sbx3[f[d]]; dst[3 + a] = sbx3[f[a]] ^ sbx1[f[b]] ^ sbx1[f[c]] ^ sbx2[f[d]]; } } static void shift_row_sbox(uint8_t *f) { sbox4(&f[0], &f[4], &f[8], &f[12]); rota4(&f[1], &f[5], &f[9], &f[13]); rota2(&f[2], &f[10]); rota2(&f[6], &f[14]); rota4(&f[15], &f[11], &f[7], &f[3]); } static void encrypt(uint8_t *in, uint8_t *out) { uint8_t fa[BLK_SIZE] = { 0 }; uint8_t fb[BLK_SIZE] = { 0 }; size_t roundval = 0; set_key(fa, in, 0); for (roundval = 1; roundval < rounds; ++roundval) { mix_column_sbox(fb, fa); set_key(fa, fb, roundval); } shift_row_sbox(fa); set_key(out, fa, roundval); } static void checksum(unsigned char *in, uint8_t *iv, int max_blk) { while (max_blk > 0) { xorb(iv, in); encrypt(iv, iv); in += BLK_SIZE; max_blk -= 1; } } static void setup_key(const unsigned char *k, size_t klen) { unsigned char rcon = 1; size_t sch_size = 240; size_t i = 0; rounds = MAX_ROUNDS; memcpy(schedule, k, klen); for (i = klen; i < sch_size; i += 4) { unsigned char t0 = 0; unsigned char t1 = 0; unsigned char t2 = 0; unsigned char t3 = 0; int ik = 0; t0 = schedule[i - 4]; t1 = schedule[i - 3]; t2 = schedule[i - 2]; t3 = schedule[i - 1]; if (i % klen == 0) { rota4(&t0, &t1, &t2, &t3); t0 ^= rcon; rcon = (rcon << 1) ^ (((rcon >> 7) & 1) * 0x1B); } else if (i % klen == 16) { sbox4(&t0, &t1, &t2, &t3); } ik = i - klen; schedule[i + 0] = schedule[ik + 0] ^ t0; schedule[i + 1] = schedule[ik + 1] ^ t1; schedule[i + 2] = schedule[ik + 2] ^ t2; schedule[i + 3] = schedule[ik + 3] ^ t3; } } static void trng_df_init(void) { const uint8_t sb[] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, }; size_t i = 0; memcpy(sbx1, sb, sizeof(sb)); for (i = 0; i < sizeof(sb); i++) { sbx2[i] = (sb[i] << 1) ^ (((sb[i] >> 7) & 1) * 0x1B); sbx3[i] = sbx2[i] ^ sb[i]; } } /* * This function implements the Derivative Function by distilling the entropy * available in its input into a smaller number of bits on the output. * - per NIST SP80090A. * * The Block Cipher algorithm follows sections 10.3.2 and 10.3.3 of the * NIST.SP.800-90Ar1 document */ static void trng_df_algorithm(struct versal_trng *trng, uint8_t *dfout, uint32_t flag, const uint8_t *pstr) { static bool df_init; const uint8_t df_key[DF_KEY_LEN] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; size_t dfin_len = sizeof(struct trng_dfin) + trng->len; uint8_t *inp_blk = NULL; uint8_t *out_blk = NULL; uintptr_t reminder = 0; size_t xfer_len = 0; uint32_t index = 0; uintptr_t src = 0; uintptr_t dst = 0; size_t offset = 0; if (!df_init) { trng_df_init(); df_init = true; } if (flag == DF_SEED) trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_PERS_STR_LEN); else trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_GEN_LEN); trng->dfin.pad_data[0] = DF_PAD_VAL; if (!pstr) { if (trng->len > (MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN)) panic(); dfin_len = dfin_len - TRNG_PERS_STR_LEN - MAX_PRE_DF_LEN; trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len); xfer_len = DF_PAD_DATA_LEN; src = (uintptr_t)trng->dfin.pad_data; offset = MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN - trng->len; } else { if (trng->len > MAX_PRE_DF_LEN) panic(); memcpy(trng->dfin.pstr, pstr, TRNG_PERS_STR_LEN); dfin_len = dfin_len - MAX_PRE_DF_LEN; trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len + TRNG_PERS_STR_LEN); xfer_len = DF_PAD_DATA_LEN + TRNG_PERS_STR_LEN; src = (uintptr_t)trng->dfin.pstr; offset = MAX_PRE_DF_LEN - trng->len; } /* Move back into the dfin structure */ dst = src - offset; reminder = (uintptr_t)&trng->dfin + sizeof(trng->dfin) - offset; if (offset) { if (xfer_len > offset) panic("Overlapping data"); memcpy((void *)dst, (void *)src, xfer_len); memset((void *)reminder, 0, offset); } /* DF algorithm - step 1 */ setup_key(df_key, DF_KEY_LEN); for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) { memset((void *)(trng->dfout + index), 0, BLK_SIZE); trng->dfin.ivc[0] = TEE_U32_TO_BIG_ENDIAN(index / BLK_SIZE); checksum((unsigned char *)&trng->dfin, trng->dfout + index, dfin_len / BLK_SIZE); } /* DF algorithm - step 2 */ setup_key(trng->dfout, DF_KEY_LEN); for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) { if (!index) inp_blk = &dfout[TRNG_SEC_STRENGTH_LEN]; else inp_blk = &dfout[index - BLK_SIZE]; out_blk = &dfout[index]; encrypt(inp_blk, out_blk); } } static uint32_t trng_read32(vaddr_t addr, size_t off) { return io_read32(addr + off); } static void trng_write32(vaddr_t addr, size_t off, uint32_t val) { io_write32(addr + off, val); } static void trng_clrset32(vaddr_t addr, size_t off, uint32_t mask, uint32_t val) { io_clrsetbits32(addr + off, mask, mask & val); } static void trng_write32_range(const struct versal_trng *trng, uint32_t start, uint32_t num_regs, const uint8_t *buf) { size_t off = 0; uint32_t val = 0; size_t cnt = 0; size_t i = 0; for (i = 0; i < num_regs; ++i) { if (!buf) { off = start + i * TRNG_BYTES_PER_REG; trng_write32(trng->cfg.addr, off, 0); continue; } val = 0; for (cnt = 0; cnt < TRNG_BYTES_PER_REG; ++cnt) val = (val << 8) | buf[i * TRNG_BYTES_PER_REG + cnt]; off = start + (TRNG_NUM_INIT_REGS - 1 - i) * TRNG_BYTES_PER_REG; trng_write32(trng->cfg.addr, off, val); } } static TEE_Result trng_wait_for_event(vaddr_t addr, size_t off, uint32_t mask, uint32_t event, uint32_t time_out) { uint64_t tref = timeout_init_us(time_out); do { if (timeout_elapsed(tref)) break; } while ((io_read32(addr + off) & mask) != event); /* Normal world might have suspended the OP-TEE thread, check again */ if ((io_read32(addr + off) & mask) != event) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static void trng_soft_reset(const struct versal_trng *trng) { trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, TRNG_CTRL_PRNGSRST_MASK); udelay(RESET_DELAY); trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, 0); } static void trng_reset(const struct versal_trng *trng) { trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK); udelay(RESET_DELAY); trng_write32(trng->cfg.addr, TRNG_RESET, 0); trng_soft_reset(trng); } static void trng_hold_reset(const struct versal_trng *trng) { trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, TRNG_CTRL_PRNGSRST_MASK); trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK); udelay(RESET_DELAY); } static TEE_Result trng_check_seed(uint8_t *entropy, uint32_t len) { uint32_t *p = (void *)entropy; size_t i = 0; for (i = 0; i < len / sizeof(*p); i++) { if (p[i] == ALL_A_PATTERN_32) return TEE_ERROR_GENERIC; if (p[i] == ALL_5_PATTERN_32) return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } static TEE_Result trng_collect_random(struct versal_trng *trng, uint8_t *dst, size_t len) { const size_t bursts = len / TRNG_BURST_SIZE; const size_t words = TRNG_BURST_SIZE_BITS / TRNG_REG_SIZE; uint32_t *p = (void *)dst; size_t bcnt = 0; size_t wcnt = 0; size_t index = 0; uint32_t val = 0; bool match = false; trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, TRNG_CTRL_PRNGSTART_MASK); /* * Loop as many times based on len requested. In each burst 128 bits * are generated, which is reflected in QCNT value of 4 by hardware. */ for (bcnt = 0; bcnt < bursts; bcnt++) { if (trng_wait_for_event(trng->cfg.addr, TRNG_STATUS, TRNG_STATUS_QCNT_MASK, TRNG_MAX_QCNT << TRNG_STATUS_QCNT_SHIFT, TRNG_GENERATE_TIMEOUT)) { EMSG("Timeout waiting for randomness"); return TEE_ERROR_GENERIC; } /* * DTF flag set during generate indicates catastrophic * condition, which needs to be checked for every time unless we * are in PTRNG mode */ if (trng->usr_cfg.mode != TRNG_PTRNG) { val = trng_read32(trng->cfg.addr, TRNG_STATUS); if (val & TRNG_STATUS_DTF_MASK) { EMSG("Catastrophic DFT error"); trng->status = TRNG_CATASTROPHIC; return TEE_ERROR_GENERIC; } } /* * Read the core output register 4 times to consume the random * data generated for every burst. */ match = true; for (wcnt = 0; wcnt < words; wcnt++) { val = trng_read32(trng->cfg.addr, TRNG_CORE_OUTPUT); if (bcnt > 0 && trng->buf[wcnt] != val) match = false; trng->buf[wcnt] = val; if (dst) { p[index] = TEE_U32_TO_BIG_ENDIAN(val); index++; } } if (bursts > 1 && bcnt > 0 && match) { EMSG("Catastrophic software error"); trng->status = TRNG_CATASTROPHIC; return TEE_ERROR_GENERIC; } } return TEE_SUCCESS; } static TEE_Result trng_reseed_internal_nodf(struct versal_trng *trng, uint8_t *eseed, uint8_t *str) { uint8_t entropy[TRNG_SEED_LEN] = { 0 }; uint8_t *seed = NULL; switch (trng->usr_cfg.mode) { case TRNG_HRNG: trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); trng_soft_reset(trng); trng_write32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK); if (trng_collect_random(trng, entropy, TRNG_SEED_LEN)) return TEE_ERROR_GENERIC; if (trng_check_seed(entropy, TRNG_SEED_LEN)) return TEE_ERROR_GENERIC; seed = entropy; break; case TRNG_DRNG: seed = eseed; break; default: seed = NULL; break; } trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, seed); if (str) trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS, str); return TEE_SUCCESS; } static TEE_Result trng_reseed_internal_df(struct versal_trng *trng, uint8_t *eseed, uint8_t *str) { memset(&trng->dfin, 0, sizeof(trng->dfin)); switch (trng->usr_cfg.mode) { case TRNG_HRNG: trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); trng_soft_reset(trng); trng_write32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK); if (trng_collect_random(trng, trng->dfin.entropy, trng->len)) return TEE_ERROR_GENERIC; if (trng_check_seed(trng->dfin.entropy, trng->len)) return TEE_ERROR_GENERIC; break; case TRNG_DRNG: memcpy(trng->dfin.entropy, eseed, trng->len); break; default: break; } trng_df_algorithm(trng, trng->dfout, DF_SEED, str); trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, trng->dfout); return TEE_SUCCESS; } static TEE_Result trng_reseed_internal(struct versal_trng *trng, uint8_t *eseed, uint8_t *str, uint32_t mul) { uint32_t val = 0; trng->stats.bytes_reseed = 0; trng->stats.elapsed_seed_life = 0; if (trng->usr_cfg.df_disable) trng->len = TRNG_SEED_LEN; else trng->len = (mul + 1) * BYTES_PER_BLOCK; if (trng->usr_cfg.df_disable) { if (trng_reseed_internal_nodf(trng, eseed, str)) goto error; } else { if (trng_reseed_internal_df(trng, eseed, str)) goto error; } trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_RESEED | TRNG_CTRL_PRNGXS_MASK); /* Start the reseed operation */ trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, TRNG_CTRL_PRNGSTART_MASK); if (trng_wait_for_event(trng->cfg.addr, TRNG_STATUS, TRNG_STATUS_DONE_MASK, TRNG_STATUS_DONE_MASK, TRNG_RESEED_TIMEOUT)) goto error; /* Check SP800 - 90B (entropy health test error) */ val = trng_read32(trng->cfg.addr, TRNG_STATUS) & TRNG_STATUS_CERTF_MASK; if (val == TRNG_STATUS_CERTF_MASK) goto error; trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, 0); return TEE_SUCCESS; error: trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } static TEE_Result trng_instantiate(struct versal_trng *trng, const struct trng_usr_cfg *usr_cfg) { uint8_t *seed = NULL; uint8_t *pers = NULL; if (!trng) return TEE_ERROR_GENERIC; if (!usr_cfg) goto error; if (trng->status != TRNG_UNINITIALIZED) goto error; if (usr_cfg->mode != TRNG_HRNG && usr_cfg->mode != TRNG_DRNG && usr_cfg->mode != TRNG_PTRNG) goto error; if (usr_cfg->mode != TRNG_PTRNG && !usr_cfg->seed_life) goto error; if (!usr_cfg->iseed_en && usr_cfg->mode == TRNG_DRNG) goto error; if (usr_cfg->iseed_en && usr_cfg->mode == TRNG_HRNG) goto error; if (!usr_cfg->df_disable && (usr_cfg->dfmul < TRNG_MIN_DFLENMULT || usr_cfg->dfmul > TRNG_MAX_DFLENMULT)) goto error; if (usr_cfg->df_disable && usr_cfg->dfmul) goto error; if (usr_cfg->mode == TRNG_PTRNG && (usr_cfg->iseed_en || usr_cfg->pstr_en || usr_cfg->predict_en || usr_cfg->seed_life)) goto error; memcpy(&trng->usr_cfg, usr_cfg, sizeof(struct trng_usr_cfg)); trng_reset(trng); if (trng->usr_cfg.iseed_en) seed = (void *)trng->usr_cfg.init_seed; if (trng->usr_cfg.pstr_en) pers = (void *)trng->usr_cfg.pstr; if (trng->usr_cfg.mode != TRNG_PTRNG) { if (trng_reseed_internal(trng, seed, pers, trng->usr_cfg.dfmul)) goto error; } trng->status = TRNG_HEALTHY; return TEE_SUCCESS; error: trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } static TEE_Result trng_reseed(struct versal_trng *trng, uint8_t *eseed, uint32_t mul) { if (!trng) return TEE_ERROR_GENERIC; if (trng->status != TRNG_HEALTHY) goto error; if (trng->usr_cfg.mode != TRNG_DRNG && trng->usr_cfg.mode != TRNG_HRNG) goto error; if (trng->usr_cfg.mode == TRNG_DRNG && !eseed) goto error; if (trng->usr_cfg.mode != TRNG_DRNG && eseed) goto error; if (!trng->usr_cfg.df_disable) { if (mul < TRNG_MIN_DFLENMULT || mul > TRNG_MAX_DFLENMULT) goto error; } if (trng->usr_cfg.df_disable && mul) goto error; if (eseed && !memcmp(eseed, trng->usr_cfg.init_seed, trng->len)) goto error; if (trng_reseed_internal(trng, eseed, NULL, mul)) goto error; return TEE_SUCCESS; error: trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } static TEE_Result trng_generate(struct versal_trng *trng, uint8_t *buf, size_t blen, bool predict) { uint32_t len = TRNG_SEC_STRENGTH_LEN; uint8_t *p = buf; if (!trng) return TEE_ERROR_GENERIC; if (!p) goto error; if (blen < TRNG_SEC_STRENGTH_LEN) goto error; if (trng->status != TRNG_HEALTHY) goto error; if (trng->usr_cfg.mode == TRNG_PTRNG && predict) goto error; if (!trng->usr_cfg.predict_en && predict) goto error; switch (trng->usr_cfg.mode) { case TRNG_HRNG: if (trng->stats.elapsed_seed_life >= trng->usr_cfg.seed_life) { if (trng_reseed_internal(trng, NULL, NULL, 0)) goto error; } if (predict && trng->stats.elapsed_seed_life > 0) { if (trng_reseed_internal(trng, NULL, NULL, 0)) goto error; } trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_GEN); break; case TRNG_DRNG: if (trng->stats.elapsed_seed_life > trng->usr_cfg.seed_life) goto error; if (predict && trng->stats.elapsed_seed_life > 0) goto error; trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_GEN); break; default: if (!trng->usr_cfg.df_disable) { memset(&trng->dfin, 0, sizeof(trng->dfin)); len = (trng->usr_cfg.dfmul + 1) * BYTES_PER_BLOCK; trng->len = len; p = trng->dfin.entropy; } /* Enable the 8 ring oscillators used for entropy source */ trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); trng_soft_reset(trng); trng_write32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK); break; } if (trng_collect_random(trng, p, len)) goto error; trng->stats.bytes_reseed += len; trng->stats.bytes += len; trng->stats.elapsed_seed_life++; if (!trng->usr_cfg.df_disable && trng->usr_cfg.mode == TRNG_PTRNG) trng_df_algorithm(trng, buf, DF_RAND, NULL); return TEE_SUCCESS; error: if (trng->status != TRNG_CATASTROPHIC) trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } static TEE_Result trng_release(struct versal_trng *trng) { if (!trng) return TEE_ERROR_GENERIC; if (trng->status == TRNG_UNINITIALIZED) goto error; trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, NULL); trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS, NULL); trng_hold_reset(trng); /* Clear the instance */ memset(&trng->usr_cfg, 0, sizeof(trng->usr_cfg)); memset(trng->buf, 0, sizeof(trng->buf)); memset(trng->dfout, 0, sizeof(trng->dfout)); trng->status = TRNG_UNINITIALIZED; return TEE_SUCCESS; error: trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } /* Health tests should be run when the configured mode is of PTRNG or HRNG */ static TEE_Result trng_health_test(struct versal_trng *trng) { struct trng_usr_cfg tests = { .mode = TRNG_HRNG, .seed_life = 10, .dfmul = 7, .predict_en = false, .iseed_en = false, .pstr_en = false, .df_disable = false, }; if (trng_instantiate(trng, &tests)) goto error; if (trng_release(trng)) goto error; return TEE_SUCCESS; error: trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } /* * The KAT test should be run when the TRNG is configured in DRNG or HRNG mode. * If KAT fails, the driver has to be put in error state. */ static TEE_Result trng_kat_test(struct versal_trng *trng) { struct trng_usr_cfg tests = { .mode = TRNG_DRNG, .seed_life = 5, .dfmul = 2, .predict_en = false, .iseed_en = true, .pstr_en = true, .df_disable = false, }; const uint8_t ext_seed[TRNG_SEED_LEN] = { 0x3BU, 0xC3U, 0xEDU, 0x64U, 0xF4U, 0x80U, 0x1CU, 0xC7U, 0x14U, 0xCCU, 0x35U, 0xEDU, 0x57U, 0x01U, 0x2AU, 0xE4U, 0xBCU, 0xEFU, 0xDEU, 0xF6U, 0x7CU, 0x46U, 0xA6U, 0x34U, 0xC6U, 0x79U, 0xE8U, 0x91U, 0x5DU, 0xB1U, 0xDBU, 0xA7U, 0x49U, 0xA5U, 0xBBU, 0x4FU, 0xEDU, 0x30U, 0xB3U, 0x7BU, 0xA9U, 0x8BU, 0xF5U, 0x56U, 0x4DU, 0x40U, 0x18U, 0x9FU, }; const uint8_t pers_str[TRNG_PERS_STR_LEN] = { 0xB2U, 0x80U, 0x7EU, 0x4CU, 0xD0U, 0xE4U, 0xE2U, 0xA9U, 0x2FU, 0x1FU, 0x5DU, 0xC1U, 0xA2U, 0x1FU, 0x40U, 0xFCU, 0x1FU, 0x24U, 0x5DU, 0x42U, 0x61U, 0x80U, 0xE6U, 0xE9U, 0x71U, 0x05U, 0x17U, 0x5BU, 0xAFU, 0x70U, 0x30U, 0x18U, 0xBCU, 0x23U, 0x18U, 0x15U, 0xCBU, 0xB8U, 0xA6U, 0x3EU, 0x83U, 0xB8U, 0x4AU, 0xFEU, 0x38U, 0xFCU, 0x25U, 0x87U, }; const uint8_t expected_out[TRNG_GEN_LEN] = { 0x91U, 0x9AU, 0x6BU, 0x99U, 0xD5U, 0xBCU, 0x2CU, 0x11U, 0x5FU, 0x3AU, 0xFCU, 0x0BU, 0x0EU, 0x7BU, 0xC7U, 0x69U, 0x4DU, 0xE1U, 0xE5U, 0xFEU, 0x59U, 0x9EU, 0xAAU, 0x41U, 0xD3U, 0x48U, 0xFDU, 0x3DU, 0xD2U, 0xC4U, 0x50U, 0x1EU, }; uint8_t out[TRNG_GEN_LEN] = { 0 }; if (!trng) return TEE_ERROR_GENERIC; memcpy(&tests.init_seed, ext_seed, sizeof(ext_seed)); memcpy(tests.pstr, pers_str, sizeof(pers_str)); if (trng_instantiate(trng, &tests)) goto error; if (trng_generate(trng, out, sizeof(out), false)) goto error; if (memcmp(out, expected_out, TRNG_GEN_LEN)) { EMSG("K.A.T mismatch"); goto error; } if (trng_release(trng)) goto error; return TEE_SUCCESS; error: trng->status = TRNG_ERROR; return TEE_ERROR_GENERIC; } static struct versal_trng versal_trng = { .cfg.base = TRNG_BASE, .cfg.len = TRNG_SIZE, }; TEE_Result hw_get_random_bytes(void *buf, size_t len) { uint8_t random[TRNG_SEC_STRENGTH_LEN] = { 0 }; uint8_t *p = buf; size_t i = 0; for (i = 0; i < len / TRNG_SEC_STRENGTH_LEN; i++) { if (trng_generate(&versal_trng, p + i * TRNG_SEC_STRENGTH_LEN, TRNG_SEC_STRENGTH_LEN, false)) panic(); } if (len % TRNG_SEC_STRENGTH_LEN) { if (trng_generate(&versal_trng, random, TRNG_SEC_STRENGTH_LEN, false)) panic(); memcpy(p + i * TRNG_SEC_STRENGTH_LEN, random, len % TRNG_SEC_STRENGTH_LEN); } return TEE_SUCCESS; } void plat_rng_init(void) { } static TEE_Result trng_hrng_mode_init(void) { const uint8_t pers_str[TRNG_PERS_STR_LEN] = { 0xB2, 0x80, 0x7E, 0x4C, 0xD0, 0xE4, 0xE2, 0xA9, 0x2F, 0x1F, 0x5D, 0xC1, 0xA2, 0x1F, 0x40, 0xFC, 0x1F, 0x24, 0x5D, 0x42, 0x61, 0x80, 0xE6, 0xE9, 0x71, 0x05, 0x17, 0x5B, 0xAF, 0x70, 0x30, 0x18, 0xBC, 0x23, 0x18, 0x15, 0xCB, 0xB8, 0xA6, 0x3E, 0x83, 0xB8, 0x4A, 0xFE, 0x38, 0xFC, 0x25, 0x87, }; /* configure in hybrid mode with derivative function enabled */ struct trng_usr_cfg usr_cfg = { .mode = TRNG_HRNG, .seed_life = CFG_VERSAL_TRNG_SEED_LIFE, .predict_en = false, .df_disable = false, .dfmul = CFG_VERSAL_TRNG_DF_MUL, .iseed_en = false, .pstr_en = true, }; memcpy(usr_cfg.pstr, pers_str, TRNG_PERS_STR_LEN); versal_trng.cfg.addr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC, versal_trng.cfg.base, versal_trng.cfg.len); if (!versal_trng.cfg.addr) { EMSG("Failed to map TRNG"); panic(); } if (trng_kat_test(&versal_trng)) { EMSG("KAT Failed"); panic(); } if (trng_health_test(&versal_trng)) { EMSG("RunHealthTest Failed"); panic(); } if (trng_instantiate(&versal_trng, &usr_cfg)) { EMSG("Driver instantiation Failed"); panic(); } if (trng_reseed(&versal_trng, NULL, usr_cfg.dfmul)) { EMSG("Reseed Failed"); panic(); } return TEE_SUCCESS; } driver_init(trng_hrng_mode_init); optee_os-4.3.0/core/drivers/wdt/000077500000000000000000000000001464416617300165535ustar00rootroot00000000000000optee_os-4.3.0/core/drivers/wdt/sub.mk000066400000000000000000000001121464416617300176670ustar00rootroot00000000000000srcs-$(CFG_WDT) += watchdog.c srcs-$(CFG_WDT_SM_HANDLER) += watchdog_sm.c optee_os-4.3.0/core/drivers/wdt/watchdog.c000066400000000000000000000005171464416617300205220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip */ #include struct wdt_chip *wdt_chip; TEE_Result watchdog_register(struct wdt_chip *chip) { if (!chip->ops->start || !chip->ops->ping || !chip->ops->set_timeout) return TEE_ERROR_BAD_PARAMETERS; wdt_chip = chip; return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/wdt/watchdog_sm.c000066400000000000000000000033651464416617300212250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2022 Microchip */ #include #include #include #include #include static unsigned long wdt_min_timeout; static unsigned long wdt_max_timeout; /* Lock for timeout variables */ static unsigned int wdt_lock = SPINLOCK_UNLOCK; enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t exceptions = 0; unsigned long min_timeout = 0; unsigned long max_timeout = 0; switch (args->a1) { case SMCWD_INIT: exceptions = cpu_spin_lock_xsave(&wdt_lock); res = watchdog_init(&wdt_min_timeout, &wdt_max_timeout); cpu_spin_unlock_xrestore(&wdt_lock, exceptions); if (res) { args->a0 = PSCI_RET_INTERNAL_FAILURE; } else { args->a0 = PSCI_RET_SUCCESS; args->a1 = wdt_min_timeout; args->a2 = wdt_max_timeout; } break; case SMCWD_SET_TIMEOUT: exceptions = cpu_spin_lock_xsave(&wdt_lock); min_timeout = wdt_min_timeout; max_timeout = wdt_max_timeout; cpu_spin_unlock_xrestore(&wdt_lock, exceptions); if (args->a2 < min_timeout || args->a2 > max_timeout) { args->a0 = PSCI_RET_INVALID_PARAMETERS; break; } watchdog_settimeout(args->a2); args->a0 = PSCI_RET_SUCCESS; break; case SMCWD_ENABLE: if (args->a2 == 0) { watchdog_stop(); args->a0 = PSCI_RET_SUCCESS; } else if (args->a2 == 1) { watchdog_start(); args->a0 = PSCI_RET_SUCCESS; } else { args->a0 = PSCI_RET_INVALID_PARAMETERS; } break; case SMCWD_PET: watchdog_ping(); args->a0 = PSCI_RET_SUCCESS; break; /* SMCWD_GET_TIMELEFT is optional */ case SMCWD_GET_TIMELEFT: default: args->a0 = PSCI_RET_NOT_SUPPORTED; } return SM_HANDLER_SMC_HANDLED; } optee_os-4.3.0/core/drivers/widevine_huk.c000066400000000000000000000024551464416617300206100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, The ChromiumOS Authors */ #include #include #include #include static uint8_t dt_huk[HW_UNIQUE_KEY_LENGTH]; static bool dt_huk_initialized; static TEE_Result init_widevine_huk_dt_data(void) { int node = 0; int len = 0; void *fdt = NULL; const void *value = NULL; if (dt_huk_initialized) return TEE_SUCCESS; fdt = get_secure_dt(); if (!fdt) return TEE_ERROR_NO_DATA; node = fdt_path_offset(fdt, "/options/op-tee/widevine"); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; value = fdt_getprop(fdt, node, "op-tee,hardware-unique-key", &len); if (!value) return TEE_ERROR_ITEM_NOT_FOUND; if (len >= HW_UNIQUE_KEY_LENGTH) len = HW_UNIQUE_KEY_LENGTH; else return TEE_ERROR_BAD_FORMAT; memcpy(dt_huk, value, len); dt_huk_initialized = true; return TEE_SUCCESS; } service_init(init_widevine_huk_dt_data); TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { TEE_Result result = TEE_SUCCESS; /* * Ensure we get data from the DT, in case called before service_init() * handler. */ result = init_widevine_huk_dt_data(); if (result != TEE_SUCCESS) return result; memcpy(hwkey->data, dt_huk, HW_UNIQUE_KEY_LENGTH); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/xiphera_trng.c000066400000000000000000000113051464416617300206130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Vaisala Oyj */ #include #include #include #include #include #include #include #include #include #include #include #include #define CONTROL_REG 0x00000000 #define STATUS_REG 0x00000004 #define RAND_REG 0x00000000 #define HOST_TO_TRNG_RESET 0x00000001 #define HOST_TO_TRNG_RELEASE_RESET 0x00000002 #define HOST_TO_TRNG_ENABLE 0x80000000 #define HOST_TO_TRNG_ZEROIZE 0x80000004 #define HOST_TO_TRNG_ACK_ZEROIZE 0x80000008 #define HOST_TO_TRNG_READ 0x8000000F /* trng statuses */ #define TRNG_ACK_RESET 0x000000AC #define TRNG_SUCCESSFUL_STARTUP 0x00000057 #define TRNG_FAILED_STARTUP 0x000000FA #define TRNG_NEW_RAND_AVAILABLE 0x000000ED static unsigned int trng_lock = SPINLOCK_UNLOCK; static vaddr_t xiphera_trng_base; static bool xiphera_trng_random_available(void) { uint32_t status = 0; status = io_read32(xiphera_trng_base + STATUS_REG); return status == TRNG_NEW_RAND_AVAILABLE; } static uint32_t xiphera_trng_read32(void) { uint32_t value = 0; value = io_read32(xiphera_trng_base + RAND_REG); /* * Ack that RNG value has been consumed and trigger new one to be * generated */ io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_READ); io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); return value; } /* This is a true RNG, no need for seeding */ void plat_rng_init(void) { } TEE_Result hw_get_random_bytes(void *buf, size_t len) { uint8_t *rngbuf = buf; uint32_t val = 0; size_t len_to_copy = 0; assert(buf); assert(xiphera_trng_base); while (len) { uint32_t exceptions = cpu_spin_lock_xsave(&trng_lock); if (xiphera_trng_random_available()) { val = xiphera_trng_read32(); len_to_copy = MIN(len, sizeof(uint32_t)); memcpy(rngbuf, &val, len_to_copy); rngbuf += len_to_copy; len -= len_to_copy; } cpu_spin_unlock_xrestore(&trng_lock, exceptions); } return TEE_SUCCESS; } static TEE_Result xiphera_trng_probe(const void *fdt, int node, const void *compat_data __unused) { int dt_status = fdt_get_status(fdt, node); uint32_t status = 0; size_t size = 0; /* Skip non-secure instances */ if (dt_status != DT_STATUS_OK_SEC) return TEE_ERROR_NODE_DISABLED; if (xiphera_trng_base) { EMSG("Only one secure instance is supported"); return TEE_ERROR_GENERIC; } if (dt_map_dev(fdt, node, &xiphera_trng_base, &size, DT_MAP_AUTO) < 0) return TEE_ERROR_GENERIC; /* * The TRNG needs to be first reset in order to provide stable * operation. * * Reset of the chip should complete within 200 us but in some cases it * could take up to 400 us. If it is not ready within 400 us assume * there is problem. */ io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RESET); udelay(200); status = io_read32(xiphera_trng_base + STATUS_REG); if (status != TRNG_ACK_RESET) { /* * Give it additional 200 us to allow it to reset. * * If still not done -> error out. */ udelay(200); status = io_read32(xiphera_trng_base + STATUS_REG); if (status != TRNG_ACK_RESET) { EMSG("Failed to reset TRNG"); return TEE_ERROR_GENERIC; } } /* * Now TRNG should be internally stable. * * Clear internal random number generation engine to start in stable * state and give it 20 ms to enable good random number entropy and * then check that random number engine is ready. */ io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RELEASE_RESET); io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ZEROIZE); mdelay(20); status = io_read32(xiphera_trng_base + STATUS_REG); if (status != TRNG_SUCCESSFUL_STARTUP) { /* * Check specifically if there were startup test errors to aid * in debugging TRNG implementation in FPGA */ if (status == TRNG_FAILED_STARTUP) { EMSG("Startup tests have failed"); return TEE_ERROR_GENERIC; } EMSG("Startup tests yielded no response -> TRNG stuck"); return TEE_ERROR_GENERIC; } io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); DMSG("TRNG initialized"); return TEE_SUCCESS; } static const struct dt_device_match xiphera_trng_match_table[] = { { .compatible = "xiphera,xip8001b-trng" }, { } }; DEFINE_DT_DRIVER(xiphera_trng_dt_driver) = { .name = "xiphera_trng", .type = DT_DRIVER_NOTYPE, .match_table = xiphera_trng_match_table, .probe = xiphera_trng_probe, }; optee_os-4.3.0/core/drivers/zynqmp_csu_aes.c000066400000000000000000000234251464416617300211670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2021 * Author: Jorge Ramirez */ #include #include #include #include #include #include #include #include #include #include #include #include /* CSU AES registers */ #define AES_STS_OFFSET 0x00 #define AES_KEY_SRC_OFFSET 0x04 #define AES_KEY_LOAD_OFFSET 0x08 #define AES_START_MSG_OFFSET 0x0C #define AES_RESET_OFFSET 0x10 #define AES_KEY_CLR_OFFSET 0x14 #define AES_CFG_OFFSET 0x18 #define AES_KEY_LOAD 1 #define AES_STS_AES_BUSY BIT(0) #define AES_STS_AES_KEY_ZEROED BIT(8) #define AES_STS_KUP_ZEROED BIT(9) #define AES_STS_KEY_INIT_DONE BIT(4) #define AES_STS_GCM_TAG_OK BIT(3) #define AES_START_MSG 1 #define AES_CFG_ENC 1 #define AES_CFG_DEC 0 #define AES_RESET_SET 1 #define AES_RESET_CLR 0 #define AES_KEY_ZERO BIT(0) #define AES_KUP_ZERO BIT(1) #define AES_TIMEOUT_USEC 2000000 enum aes_op { AES_DEC, AES_ENC }; static TEE_Result aes_wait(uint32_t event, bool set) { vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_AES_SIZE); uint64_t tref = timeout_init_us(AES_TIMEOUT_USEC); uint32_t status = 0; if (!aes) return TEE_ERROR_GENERIC; while (!timeout_elapsed(tref)) { status = io_read32(aes + AES_STS_OFFSET) & event; if ((set && status == event) || (!set && status != event)) return TEE_SUCCESS; } return TEE_ERROR_GENERIC; } static TEE_Result aes_transfer_enc(const void *src, void *dst, size_t dst_len, void *tag, const void *iv) { void *p = (uint8_t *)dst + dst_len - ZYNQMP_GCM_TAG_SIZE; uint8_t iv_padded[ZYNQMP_CSUDMA_MIN_SIZE] __aligned_csudma = { 0 }; TEE_Result ret = TEE_SUCCESS; if (dst_len < ZYNQMP_GCM_TAG_SIZE) { EMSG("Invalid length"); return TEE_ERROR_GENERIC; } ret = zynqmp_csudma_prepare(); if (ret) { EMSG("DMA can't initialize"); return ret; } /* Prepare destination */ ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_DST_CHANNEL, dst, dst_len, 0); if (ret) { EMSG("DMA transfer failed, invalid destination buffer"); goto out; } /* Inputs */ memcpy(iv_padded, iv, ZYNQMP_GCM_IV_SIZE); ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)iv_padded, ZYNQMP_CSUDMA_MIN_SIZE, 0); if (ret) { EMSG("DMA transfer failed, invalid IV buffer"); goto out; } ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); if (ret) { EMSG("DMA IV transfer timeout"); goto out; } ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)src, dst_len - ZYNQMP_GCM_TAG_SIZE, ZYNQMP_CSUDMA_DONE); if (ret) { EMSG("DMA transfer failed, invalid source buffer"); goto out; } ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); if (ret) { EMSG("DMA source transfer timeout"); goto out; } /* Wait for completion */ ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_DST_CHANNEL); if (ret) { EMSG("DMA destination transfer timeout"); goto out; } /* Transfer the GCM tag */ memcpy(tag, p, ZYNQMP_GCM_TAG_SIZE); out: zynqmp_csudma_unprepare(); return ret; } static TEE_Result aes_transfer_dec(const void *src, void *dst, size_t len, const void *tag, const void *iv) { uint8_t iv_padded[ZYNQMP_CSUDMA_MIN_SIZE] __aligned_csudma = { 0 }; TEE_Result ret = TEE_SUCCESS; ret = zynqmp_csudma_prepare(); if (ret) { EMSG("DMA can't initialize"); return ret; } /* Prepare destination */ ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_DST_CHANNEL, dst, len, 0); if (ret) { EMSG("DMA transfer failed, invalid destination buffer"); goto out; } /* Inputs */ memcpy(iv_padded, iv, ZYNQMP_GCM_IV_SIZE); ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)iv_padded, ZYNQMP_CSUDMA_MIN_SIZE, 0); if (ret) { EMSG("DMA transfer failed, invalid IV buffer"); goto out; } ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); if (ret) { EMSG("DMA IV transfer timeout"); goto out; } ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)src, len, ZYNQMP_CSUDMA_DONE); if (ret) { EMSG("DMA transfer failed, invalid source buffer"); goto out; } ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); if (ret) { EMSG("DMA source transfer timeout"); goto out; } ret = zynqmp_csudma_transfer(ZYNQMP_CSUDMA_SRC_CHANNEL, (void *)tag, ZYNQMP_GCM_TAG_SIZE, ZYNQMP_CSUDMA_DONE); if (ret) { EMSG("DMA transfer failed, invalid tag buffer"); goto out; } ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_SRC_CHANNEL); if (ret) { EMSG("DMA tag transfer timeout"); goto out; } /* Wait for completion*/ ret = zynqmp_csudma_sync(ZYNQMP_CSUDMA_DST_CHANNEL); if (ret) EMSG("DMA destination transfer timeout"); out: zynqmp_csudma_unprepare(); return ret; } static TEE_Result aes_prepare_op(enum aes_op op, enum zynqmp_csu_key key) { vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_AES_SIZE); vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); TEE_Result ret = TEE_SUCCESS; if (!aes || !csu) return TEE_ERROR_GENERIC; /* Connect DMA0 in/out to AES */ io_write32(csu + ZYNQMP_CSU_SSS_CFG_OFFSET, ZYNQMP_CSU_SSS_DMA0_STREAM_TO_AES); /* Reset the AES */ io_write32(aes + AES_RESET_OFFSET, AES_RESET_SET); io_write32(aes + AES_RESET_OFFSET, AES_RESET_CLR); /* Load the key */ io_write32(aes + AES_KEY_CLR_OFFSET, 0); io_write32(aes + AES_KEY_SRC_OFFSET, key); io_write32(aes + AES_KEY_LOAD_OFFSET, AES_KEY_LOAD); ret = aes_wait(AES_STS_KEY_INIT_DONE, true); if (ret) { EMSG("Timeout loading the key"); return TEE_ERROR_GENERIC; } /* Configure operation */ io_write32(aes + AES_CFG_OFFSET, op == AES_DEC ? AES_CFG_DEC : AES_CFG_ENC); /* Prepare the CSU for the DMA */ io_write32(csu + ZYNQMP_CSU_DMA_RESET_OFFSET, ZYNQMP_CSU_DMA_RESET_SET); io_write32(csu + ZYNQMP_CSU_DMA_RESET_OFFSET, ZYNQMP_CSU_DMA_RESET_CLR); /* Start the message */ io_write32(aes + AES_START_MSG_OFFSET, AES_START_MSG); return TEE_SUCCESS; } static TEE_Result aes_done_op(enum aes_op op, TEE_Result ret) { vaddr_t aes = core_mmu_get_va(ZYNQMP_CSU_AES_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_AES_SIZE); uint32_t val = 0; if (!aes) return TEE_ERROR_GENERIC; if (!ret && op == AES_DEC) { /* on decompression we must validate the GCM tag */ val = io_read32(aes + AES_STS_OFFSET) & AES_STS_GCM_TAG_OK; if (!val) { EMSG("AES-GCM tag mismatch"); return TEE_ERROR_GENERIC; } } val = io_read32(aes + AES_KEY_CLR_OFFSET); io_write32(aes + AES_KEY_CLR_OFFSET, val | AES_KEY_ZERO | AES_KUP_ZERO); if (aes_wait(AES_STS_AES_KEY_ZEROED | AES_STS_KUP_ZEROED, true)) EMSG("Failed to clear the AES key"); io_write32(aes + AES_KEY_CLR_OFFSET, val); io_write32(aes + AES_RESET_OFFSET, AES_RESET_SET); return ret; } TEE_Result zynqmp_csu_aes_decrypt_data(const void *src, size_t src_len, void *dst, size_t dst_len, const void *tag, size_t tag_len, const void *iv, size_t iv_len, enum zynqmp_csu_key key) { TEE_Result ret = TEE_SUCCESS; if (key != ZYNQMP_CSU_AES_KEY_SRC_DEV) { EMSG("Key type not supported"); return TEE_ERROR_NOT_IMPLEMENTED; } if (src_len % 4 || dst_len != src_len) { EMSG("Invalid source size"); return TEE_ERROR_BAD_PARAMETERS; } if (iv_len != ZYNQMP_GCM_IV_SIZE) { EMSG("Invalid IV size"); return TEE_ERROR_BAD_PARAMETERS; } if (tag_len != ZYNQMP_GCM_TAG_SIZE) { EMSG("Invalid tag size"); return TEE_ERROR_BAD_PARAMETERS; } if (!src || !dst || !tag || !iv) { EMSG("Invalid input value"); return TEE_ERROR_BAD_PARAMETERS; } ret = aes_prepare_op(AES_DEC, key); if (ret) { EMSG("Decrypt init failed"); goto out; } ret = aes_transfer_dec(src, dst, src_len, tag, iv); if (ret) { EMSG("DMA transfer failed"); goto out; } ret = aes_wait(AES_STS_AES_BUSY, false); if (ret) EMSG("AES-GCM transfer failed"); out: return aes_done_op(AES_DEC, ret); } TEE_Result zynqmp_csu_aes_encrypt_data(const void *src, size_t src_len, void *dst, size_t dst_len, void *tag, size_t tag_len, const void *iv, size_t iv_len, enum zynqmp_csu_key key) { TEE_Result ret = TEE_SUCCESS; if (key != ZYNQMP_CSU_AES_KEY_SRC_DEV) { EMSG("Key type not supported"); return TEE_ERROR_NOT_IMPLEMENTED; } if (src_len % 4 || dst_len != ZYNQMP_CSU_AES_DST_LEN(src_len)) { EMSG("Invalid source size"); return TEE_ERROR_BAD_PARAMETERS; } if (iv_len != ZYNQMP_GCM_IV_SIZE) { EMSG("Invalid IV size"); return TEE_ERROR_BAD_PARAMETERS; } if (tag_len != ZYNQMP_GCM_TAG_SIZE) { EMSG("Invalid tag size"); return TEE_ERROR_BAD_PARAMETERS; } if (!src || !dst || !tag || !iv) { EMSG("Invalid input value"); return TEE_ERROR_BAD_PARAMETERS; } ret = aes_prepare_op(AES_ENC, key); if (ret) { EMSG("Encrypt init failed"); goto out; } ret = aes_transfer_enc(src, dst, dst_len, tag, iv); if (ret) { EMSG("DMA transfer failed"); goto out; } ret = aes_wait(AES_STS_AES_BUSY, false); if (ret) EMSG("AES transfer failed"); out: return aes_done_op(AES_ENC, ret); } static const char *const dt_ctrl_match_table[] = { "xlnx,zynqmp-aes", }; TEE_Result zynqmp_csu_aes_dt_enable_secure_status(void) { unsigned int i = 0; void *fdt = NULL; int node = -1; fdt = get_external_dt(); if (!fdt) return TEE_SUCCESS; for (i = 0; i < ARRAY_SIZE(dt_ctrl_match_table); i++) { node = fdt_node_offset_by_compatible(fdt, 0, dt_ctrl_match_table[i]); if (node >= 0) break; } if (node < 0) return TEE_SUCCESS; if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) return TEE_SUCCESS; if (dt_enable_secure_status(fdt, node)) { EMSG("Not able to set the AES-GCM DTB entry secure"); return TEE_ERROR_NOT_SUPPORTED; } return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/zynqmp_csu_puf.c000066400000000000000000000035761464416617300212160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 Foundries.io Ltd. * * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #define PUF_CMD_OFFSET 0x00 #define PUF_CFG0_OFFSET 0x04 #define PUF_CFG1_OFFSET 0x08 #define PUF_SHUT_OFFSET 0x0C #define PUF_STATUS_OFFSET 0x10 #define PUF_WORD_OFFSET 0x18 #define PUF_REGENERATION 4 #define PUF_RESET 6 #define PUF_CFG0_DEFAULT 0x02 #define PUF_SHUT_DEFAULT 0x01000100 #define PUF_REGEN_TIME_MS 6 TEE_Result zynqmp_csu_puf_regenerate(void) { vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_PUF_SIZE); vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); uint32_t status = 0; if (!puf || !csu) return TEE_ERROR_GENERIC; io_write32(puf + PUF_CFG0_OFFSET, PUF_CFG0_DEFAULT); io_write32(puf + PUF_SHUT_OFFSET, PUF_SHUT_DEFAULT); io_write32(puf + PUF_CMD_OFFSET, PUF_REGENERATION); mdelay(PUF_REGEN_TIME_MS); status = io_read32(csu + ZYNQMP_CSU_ISR_OFFSET); if (status & ZYNQMP_CSU_ISR_PUF_ACC_ERROR_MASK) { EMSG("regeneration failed"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } void zynqmp_csu_puf_reset(void) { vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_PUF_SIZE); io_write32(puf + PUF_CMD_OFFSET, PUF_RESET); } static TEE_Result zynqmp_csu_puf_init(void) { vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); uint32_t status = 0; /* if the bootloader has been authenticated, reserve the PUF */ status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); if (status & ZYNQMP_CSU_STATUS_AUTH) return zynqmp_csu_aes_dt_enable_secure_status(); return TEE_SUCCESS; } driver_init(zynqmp_csu_puf_init); optee_os-4.3.0/core/drivers/zynqmp_csudma.c000066400000000000000000000076261464416617300210260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 Foundries.io Ltd. * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #define CSUDMA_ADDR_OFFSET 0x00 #define CSUDMA_SIZE_OFFSET 0x04 #define CSUDMA_STS_OFFSET 0x08 #define CSUDMA_CTRL_OFFSET 0x0C #define CSUDMA_CRC_OFFSET 0x10 #define CSUDMA_I_STS_OFFSET 0x14 #define CSUDMA_I_EN_OFFSET 0x18 #define CSUDMA_I_DIS_OFFSET 0x1C #define CSUDMA_I_MASK_OFFSET 0x20 #define CSUDMA_CTRL2_OFFSET 0x24 #define CSUDMA_ADDR_MSB_OFFSET 0x28 #define CSUDMA_OFFSET_DIFF 0x0800 #define CSUDMA_ADDR_MASK GENMASK_32(31, 2) #define CSUDMA_ADDR_LSB_MASK (BIT(0) | BIT(1)) #define CSUDMA_ADDR_MSB_MASK GENMASK_32(16, 0) #define CSUDMA_ADDR_MSB_SHIFT 32 #define CSUDMA_SIZE_SHIFT 2 #define CSUDMA_STS_BUSY_MASK BIT(0) #define CSUDMA_CTRL_ENDIAN_MASK BIT(23) #define CSUDMA_LAST_WORD_MASK BIT(0) #define CSUDMA_IXR_DONE_MASK BIT(1) #define CSUDMA_IXR_SRC_MASK GENMASK_32(6, 0) #define CSUDMA_IXR_DST_MASK GENMASK_32(7, 1) #define CSUDMA_DONE_TIMEOUT_USEC 3000000 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CSUDMA_BASE, CSUDMA_SIZE); static void csudma_clear_intr(enum zynqmp_csudma_channel channel, uint32_t mask) { vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, CSUDMA_SIZE); uint32_t val = CSUDMA_IXR_SRC_MASK; if (channel == ZYNQMP_CSUDMA_DST_CHANNEL) { dma += CSUDMA_OFFSET_DIFF; val = CSUDMA_IXR_DST_MASK; } io_write32(dma + CSUDMA_I_STS_OFFSET, val & mask); } TEE_Result zynqmp_csudma_sync(enum zynqmp_csudma_channel channel) { vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, CSUDMA_SIZE); uint64_t tref = timeout_init_us(CSUDMA_DONE_TIMEOUT_USEC); uint32_t status = 0; if (!dma) return TEE_ERROR_GENERIC; if (channel == ZYNQMP_CSUDMA_DST_CHANNEL) dma = dma + CSUDMA_OFFSET_DIFF; while (!timeout_elapsed(tref)) { status = io_read32(dma + CSUDMA_I_STS_OFFSET); if ((status & CSUDMA_IXR_DONE_MASK) == CSUDMA_IXR_DONE_MASK) { csudma_clear_intr(channel, CSUDMA_IXR_DONE_MASK); return TEE_SUCCESS; } } return TEE_ERROR_GENERIC; } TEE_Result zynqmp_csudma_prepare(void) { vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, CSUDMA_SIZE); if (!dma) return TEE_ERROR_GENERIC; io_setbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); dma = dma + CSUDMA_OFFSET_DIFF; io_setbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); return TEE_SUCCESS; } void zynqmp_csudma_unprepare(void) { vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, CSUDMA_SIZE); io_clrbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); dma = dma + CSUDMA_OFFSET_DIFF; io_clrbits32(dma + CSUDMA_CTRL_OFFSET, CSUDMA_CTRL_ENDIAN_MASK); } TEE_Result zynqmp_csudma_transfer(enum zynqmp_csudma_channel channel, void *addr, size_t len, uint8_t notify) { vaddr_t dma = core_mmu_get_va(CSUDMA_BASE, MEM_AREA_IO_SEC, CSUDMA_SIZE); paddr_t phys = virt_to_phys(addr); uint32_t addr_offset = 0; if (!dma) return TEE_ERROR_GENERIC; if (len % sizeof(uint32_t)) return TEE_ERROR_BAD_PARAMETERS; if (!IS_ALIGNED(phys, ZYNQMP_CSUDMA_ALIGN)) { EMSG("Invalid alignment"); return TEE_ERROR_BAD_PARAMETERS; } /* convert to 32 bit word transfers */ len = len / sizeof(uint32_t); if (channel == ZYNQMP_CSUDMA_DST_CHANNEL) { dma = dma + CSUDMA_OFFSET_DIFF; dcache_inv_range(addr, SHIFT_U64(len, CSUDMA_SIZE_SHIFT)); } else { dcache_clean_range(addr, SHIFT_U64(len, CSUDMA_SIZE_SHIFT)); } addr_offset = phys & CSUDMA_ADDR_MASK; io_write32(dma + CSUDMA_ADDR_OFFSET, addr_offset); addr_offset = phys >> CSUDMA_ADDR_MSB_SHIFT; io_write32(dma + CSUDMA_ADDR_MSB_OFFSET, addr_offset); io_write32(dma + CSUDMA_SIZE_OFFSET, SHIFT_U32(len, CSUDMA_SIZE_SHIFT) | notify); return TEE_SUCCESS; } optee_os-4.3.0/core/drivers/zynqmp_huk.c000066400000000000000000000144421464416617300203330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 Foundries.io Ltd. * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #include #include #include #include #include static struct { uint8_t key[HW_UNIQUE_KEY_LENGTH]; bool ready; } huk; __weak TEE_Result tee_zynqmp_get_device_dna(uint8_t *device_dna, size_t size) { if (size != ZYNQMP_EFUSE_LEN(DNA)) return TEE_ERROR_BAD_PARAMETERS; /* Get Device DNA from the PS eFuses */ return zynqmp_efuse_read(device_dna, size, DNA, false); } /* * Generate HUK source data * * Performs SHA256 over of data: * - Device DNA (from PL preferably) * - Selected user eFuses (HUK seed) * * HUK source data is later on AES encrypted with device key to shuffle source * data even further with secret key. * * Note: Even though the device key is secret used details for HUK source data * should not be exposed to REE environment. * * Note: You should not change HUK source data generation parameters after * devices have been deployed. * * @device_dna: Value of Device DNA * @device_dna_size: Size of Device DNA * @huk_source: Output buffer for HUK source data * @huk_source_size: Output buffer size for HUK source data * Return a TEE_Result compliant status */ static TEE_Result tee_zynqmp_generate_huk_src(const uint8_t *device_dna, size_t device_dna_size, uint8_t *huk_source, size_t huk_source_size) { TEE_Result res = TEE_ERROR_GENERIC; uint32_t user_efuse = 0; void *ctx = NULL; int i = 0; assert(device_dna_size == ZYNQMP_EFUSE_LEN(DNA)); assert(huk_source_size == HW_UNIQUE_KEY_LENGTH); res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); if (res) return res; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, device_dna, device_dna_size); if (res) goto out; /* Hash selected user eFuses */ for (i = 0; i < (USER7 - USER0 + 1); i++) { if (CFG_ZYNQMP_HUK_USER_EFUSE_MASK & BIT(i)) { DMSG("Use User eFuse %d for HUK source data", i); res = zynqmp_efuse_read((uint8_t *)&user_efuse, sizeof(user_efuse), USER0 + i, false); if (res) goto out; res = crypto_hash_update(ctx, (uint8_t *)&user_efuse, sizeof(user_efuse)); if (res) goto out; } } res = crypto_hash_final(ctx, huk_source, huk_source_size); out: crypto_hash_free_ctx(ctx); memzero_explicit(&user_efuse, sizeof(user_efuse)); return res; } TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); uint8_t device_dna[ZYNQMP_EFUSE_LEN(DNA)] = { 0 }; uint8_t src[HW_UNIQUE_KEY_LENGTH] __aligned_csuaes = { 0 }; uint8_t iv[ZYNQMP_GCM_IV_SIZE] = { 0 }; uint8_t tag[ZYNQMP_GCM_TAG_SIZE] __aligned_csuaes = { 0 }; uint8_t sha[HW_UNIQUE_KEY_LENGTH] = { 0 }; uint8_t dst[ZYNQMP_CSU_AES_DST_LEN(sizeof(src))] __aligned_csuaes = { 0 }; TEE_Result ret = TEE_ERROR_GENERIC; uint32_t status = 0; static_assert(sizeof(device_dna) == ZYNQMP_GCM_IV_SIZE); if (huk.ready) goto out; ret = tee_zynqmp_get_device_dna(device_dna, sizeof(device_dna)); if (ret) { EMSG("Can't read the Device DNA"); goto cleanup; } status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); if (!(status & ZYNQMP_CSU_STATUS_AUTH)) { /* The DNA is a unique identifier valid but not secure */ IMSG("CSU authentication disabled, using development HUK"); /* Use hash of device DNA for development HUK */ ret = tee_hash_createdigest(TEE_ALG_SHA256, device_dna, sizeof(device_dna), huk.key, sizeof(huk.key)); if (ret) { EMSG("Can't generate the SHA256 for the DNA eFuse"); goto cleanup; } huk.ready = true; goto out; } /* Use device DNA for IV */ memcpy(iv, device_dna, sizeof(device_dna)); /* Generate HUK source data */ ret = tee_zynqmp_generate_huk_src(device_dna, sizeof(device_dna), src, sizeof(src)); if (ret) { EMSG("Failed to generate HUK source data"); goto cleanup; } #ifdef CFG_ZYNQMP_CSU_PUF /* * Neither the PMUFW nor the PUF hardware provide an indication of the * PUF KEK registration status. The verification algorithm that follows * encrypts and then decrypts the resulting string regenerating the * PUF KEK in between: if the outputs match, then the PUF KEK was * registered properly and we can use it to generate the HUK. */ zynqmp_csu_puf_reset(); ret = zynqmp_csu_puf_regenerate(); if (ret) { EMSG("PUF regeneration error"); goto cleanup; } #endif memcpy(sha, src, sizeof(sha)); /* The dst buffer must be large enough to include the generated tag */ ret = zynqmp_csu_aes_encrypt_data(src, sizeof(src), dst, sizeof(dst), tag, sizeof(tag), iv, sizeof(iv), ZYNQMP_CSU_AES_KEY_SRC_DEV); if (ret) { EMSG("Can't encrypt DNA, please make sure PUF was registered"); goto cleanup; } #ifdef CFG_ZYNQMP_CSU_PUF /* regenerate the PUF KEK */ ret = zynqmp_csu_puf_regenerate(); if (ret) { EMSG("PUF regeneration error"); goto cleanup; } #endif memset(src, 0, sizeof(src)); /* Ignore the tag data from the dst buffer - pass a smaller size */ ret = zynqmp_csu_aes_decrypt_data(dst, sizeof(src), src, sizeof(src), tag, sizeof(tag), iv, ZYNQMP_EFUSE_LEN(DNA), ZYNQMP_CSU_AES_KEY_SRC_DEV); if (ret) { EMSG("Can't decrypt DNA, please make sure PUF was registered"); goto cleanup; } if (memcmp(src, sha, sizeof(sha))) { EMSG("PUF not ready, can't create HUK"); ret = TEE_ERROR_GENERIC; goto cleanup; } IMSG("HUK ready"); /* * The HUK is the SHA-256 of Device DNA with optional User eFuses * included and then AES-GCM encrypted with the selected Device Key * using the Device DNA as the IV. */ memcpy(huk.key, dst, sizeof(huk.key)); huk.ready = true; out: memcpy(hwkey->data, huk.key, HW_UNIQUE_KEY_LENGTH); ret = TEE_SUCCESS; cleanup: /* Cleanup stack memory so that there are no left overs */ memzero_explicit(dst, sizeof(dst)); memzero_explicit(sha, sizeof(sha)); memzero_explicit(tag, sizeof(tag)); memzero_explicit(iv, sizeof(iv)); memzero_explicit(src, sizeof(src)); memzero_explicit(device_dna, sizeof(device_dna)); return ret; } optee_os-4.3.0/core/drivers/zynqmp_pm.c000066400000000000000000000110401464416617300201470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2021 Foundries.io Ltd */ #include #include #include #include #include #include #include #include #include #include #include /* * For additional details about ZynqMP specific SMC ID's and PM request * handling in TF-A check * https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842107/Arm+Trusted+Firmware */ #define EFUSE_ACCESS_SMC 0xC2000035 #define VERSION_ACCESS_SMC 0xC2000018 #define EFUSE_NOT_ENABLED 29 #define VERSION_MASK GENMASK_32(3, 0) static uint32_t zynqmp_sip_call(uint32_t pm_api_id, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t *payload) { struct thread_smc_args args = { .a0 = pm_api_id, .a1 = reg_pair_to_64(arg1, arg0), .a2 = reg_pair_to_64(arg3, arg2), }; thread_smccc(&args); if (payload) { switch (pm_api_id) { case EFUSE_ACCESS_SMC: *payload = args.a0 >> 32; break; case VERSION_ACCESS_SMC: *payload = args.a1 & VERSION_MASK; break; default: break; } } return args.a0; } /* * Stores all required details to read/write eFuse memory. * @src: Physical address of the buffer to store the data to be * written/read (in LE) * @size: number of 32-bit words to be read/written * @offset: offset in bytes to be read from/written to * @flag: EFUSE_READ - represents eFuse read operation * EFUSE_WRITE - represents eFuse write operation * @pufuserfuse:0 - represents non-PUF eFuses, offset is used for read/write * 1 - represents PUF user eFuse row number. */ struct xilinx_efuse { uint64_t src; uint32_t size; uint32_t offset; uint32_t flag; uint32_t pufuserfuse; }; enum efuse_op { EFUSE_READ = 0, EFUSE_WRITE = 1 }; #define EFUSE_ELT(__x) \ [__x] = { \ .offset = ZYNQMP_EFUSE_##__x##_OFFSET, \ .bytes = ZYNQMP_EFUSE_##__x##_LENGTH, \ } static const struct { uint32_t offset; uint32_t bytes; } efuse_tbl[] = { EFUSE_ELT(DNA), EFUSE_ELT(IP_DISABLE), EFUSE_ELT(USER0), EFUSE_ELT(USER1), EFUSE_ELT(USER2), EFUSE_ELT(USER3), EFUSE_ELT(USER4), EFUSE_ELT(USER5), EFUSE_ELT(USER6), EFUSE_ELT(USER7), EFUSE_ELT(MISC_USER_CTRL), EFUSE_ELT(SEC_CTRL), }; static TEE_Result efuse_op(enum efuse_op op, uint8_t *buf, size_t buf_sz, enum zynqmp_efuse_id id, bool puf) { struct xilinx_efuse *efuse_op = NULL; uint8_t *tmpbuf = NULL; paddr_t addr = 0; uint32_t efuse_ret = 0; TEE_Result res = TEE_ERROR_GENERIC; if (!buf) return TEE_ERROR_BAD_PARAMETERS; if (id >= ARRAY_SIZE(efuse_tbl)) { EMSG("Invalid efuse"); return TEE_ERROR_BAD_PARAMETERS; } efuse_op = alloc_cache_aligned(sizeof(*efuse_op)); if (!efuse_op) { EMSG("Failed to allocate cache aligned buffer for operation"); return TEE_ERROR_OUT_OF_MEMORY; } tmpbuf = alloc_cache_aligned(buf_sz); if (!tmpbuf) { EMSG("Failed to allocate cache aligned buffer for data"); res = TEE_ERROR_OUT_OF_MEMORY; goto out; } if (op == EFUSE_WRITE) memcpy(tmpbuf, buf, buf_sz); efuse_op->size = efuse_tbl[id].bytes / sizeof(uint32_t); efuse_op->offset = efuse_tbl[id].offset; efuse_op->src = virt_to_phys(tmpbuf); efuse_op->pufuserfuse = puf; efuse_op->flag = op; cache_operation(TEE_CACHECLEAN, tmpbuf, buf_sz); cache_operation(TEE_CACHECLEAN, efuse_op, sizeof(*efuse_op)); addr = virt_to_phys(efuse_op); efuse_ret = zynqmp_sip_call(EFUSE_ACCESS_SMC, addr >> 32, addr, 0, 0, NULL); if (efuse_ret) { if (efuse_ret == EFUSE_NOT_ENABLED) EMSG("eFuse access is not enabled"); else EMSG("Error in eFuse access %#"PRIx32, efuse_ret); res = TEE_ERROR_GENERIC; goto out; } if (op == EFUSE_READ) { res = cache_operation(TEE_CACHEINVALIDATE, tmpbuf, buf_sz); if (res) goto out; memcpy(buf, tmpbuf, buf_sz); } res = TEE_SUCCESS; out: free(tmpbuf); free(efuse_op); return res; } TEE_Result zynqmp_efuse_read(uint8_t *buf, size_t sz, enum zynqmp_efuse_id id, bool puf) { return efuse_op(EFUSE_READ, buf, sz, id, puf); } TEE_Result zynqmp_efuse_write(uint8_t *buf, size_t sz, enum zynqmp_efuse_id id, bool puf) { return efuse_op(EFUSE_WRITE, buf, sz, id, puf); } TEE_Result zynqmp_soc_version(uint32_t *version) { uint32_t res = 0; if (!version) return TEE_ERROR_BAD_PARAMETERS; res = zynqmp_sip_call(VERSION_ACCESS_SMC, 0, 0, 0, 0, version); if (res) { EMSG("Failed to retrieve version"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } optee_os-4.3.0/core/include/000077500000000000000000000000001464416617300157225ustar00rootroot00000000000000optee_os-4.3.0/core/include/console.h000066400000000000000000000031711464416617300175370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __CONSOLE_H #define __CONSOLE_H #include #include void console_init(void); void console_putc(int ch); void console_flush(void); void plat_console_init(void); struct serial_chip; void register_serial_console(struct serial_chip *chip); #ifdef CFG_DT /* * Get console info from a reacheable DTB. Check the embedded DTB and fall * back to the external DTB. * * If the DTB does not specify a chosen (or secure-chosen) node, we assume * DTB does not provide specific console directive. Early console may remain. * If the DTB does not specify any console in the chosen (or secure-chosen) * node, we assume there is no console. Early console would be disabled. * * @fdt_out: Output DTB address where console directive is found * @offs_out: Output offset in the DTB where console directive is found * @path_out: Output string configuration of the console from the DTB. * (*path_out) shall be freed using nex_free(). * @params_out: Output console parameters found from the DTB. * (*params_out) shall be freed using nex_free(). * * Return a TEE_Result compliant return value * */ TEE_Result get_console_node_from_dt(void *fdt, int *offs_out, char **path_out, char **params_out); /* * Check if the /secure-chosen or /chosen node in the DT contains an * stdout-path value for which we have a compatible driver. If so, switch * the console to this device. */ void configure_console_from_dt(void); #else static inline void configure_console_from_dt(void) {} #endif /* !CFG_DT */ #endif /* __CONSOLE_H */ optee_os-4.3.0/core/include/crypto/000077500000000000000000000000001464416617300172425ustar00rootroot00000000000000optee_os-4.3.0/core/include/crypto/crypto.h000066400000000000000000000370471464416617300207460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2017, Linaro Limited */ /* * This is the Cryptographic Provider API (CP API). * * This defines how most crypto syscalls that implement the Cryptographic * Operations API can invoke the actual providers of cryptographic algorithms * (such as LibTomCrypt). * * To add a new provider, you need to provide an implementation of this * interface. * * The following parameters are commonly used. * * @ctx: context allocated by the syscall, for later use by the algorithm * @algo: algorithm identifier (TEE_ALG_*) */ #ifndef __CRYPTO_CRYPTO_H #define __CRYPTO_CRYPTO_H #include #include TEE_Result crypto_init(void); /* Message digest functions */ TEE_Result crypto_hash_alloc_ctx(void **ctx, uint32_t algo); TEE_Result crypto_hash_init(void *ctx); TEE_Result crypto_hash_update(void *ctx, const uint8_t *data, size_t len); TEE_Result crypto_hash_final(void *ctx, uint8_t *digest, size_t len); void crypto_hash_free_ctx(void *ctx); void crypto_hash_copy_state(void *dst_ctx, void *src_ctx); /* Symmetric ciphers */ TEE_Result crypto_cipher_alloc_ctx(void **ctx, uint32_t algo); TEE_Result crypto_cipher_init(void *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len); TEE_Result crypto_cipher_update(void *ctx, TEE_OperationMode mode, bool last_block, const uint8_t *data, size_t len, uint8_t *dst); void crypto_cipher_final(void *ctx); TEE_Result crypto_cipher_get_block_size(uint32_t algo, size_t *size); void crypto_cipher_free_ctx(void *ctx); void crypto_cipher_copy_state(void *dst_ctx, void *src_ctx); /* Message Authentication Code functions */ TEE_Result crypto_mac_alloc_ctx(void **ctx, uint32_t algo); TEE_Result crypto_mac_init(void *ctx, const uint8_t *key, size_t len); TEE_Result crypto_mac_update(void *ctx, const uint8_t *data, size_t len); TEE_Result crypto_mac_final(void *ctx, uint8_t *digest, size_t digest_len); void crypto_mac_free_ctx(void *ctx); void crypto_mac_copy_state(void *dst_ctx, void *src_ctx); /* Authenticated encryption */ TEE_Result crypto_authenc_alloc_ctx(void **ctx, uint32_t algo); TEE_Result crypto_authenc_init(void *ctx, TEE_OperationMode mode, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); TEE_Result crypto_authenc_update_aad(void *ctx, TEE_OperationMode mode, const uint8_t *data, size_t len); TEE_Result crypto_authenc_update_payload(void *ctx, TEE_OperationMode mode, const uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len); TEE_Result crypto_authenc_enc_final(void *ctx, const uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len, uint8_t *dst_tag, size_t *dst_tag_len); TEE_Result crypto_authenc_dec_final(void *ctx, const uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len, const uint8_t *tag, size_t tag_len); void crypto_authenc_final(void *ctx); void crypto_authenc_free_ctx(void *ctx); void crypto_authenc_copy_state(void *dst_ctx, void *src_ctx); /* Informs crypto that the data in the buffer will be removed from storage */ TEE_Result crypto_storage_obj_del(struct tee_obj *obj); /* Implementation-defined big numbers */ /* * Allocate a bignum capable of holding an unsigned integer value of * up to bitsize bits */ struct bignum *crypto_bignum_allocate(size_t size_bits); TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, struct bignum *to); size_t crypto_bignum_num_bytes(struct bignum *a); size_t crypto_bignum_num_bits(struct bignum *a); void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to); void crypto_bignum_copy(struct bignum *to, const struct bignum *from); void crypto_bignum_free(struct bignum **a); void crypto_bignum_clear(struct bignum *a); /* return -1 if ab */ int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b); /* Asymmetric algorithms */ struct rsa_keypair { struct bignum *e; /* Public exponent */ struct bignum *d; /* Private exponent */ struct bignum *n; /* Modulus */ /* Optional CRT parameters (all NULL if unused) */ struct bignum *p; /* N = pq */ struct bignum *q; struct bignum *qp; /* 1/q mod p */ struct bignum *dp; /* d mod (p-1) */ struct bignum *dq; /* d mod (q-1) */ }; struct rsa_public_key { struct bignum *e; /* Public exponent */ struct bignum *n; /* Modulus */ }; struct dsa_keypair { struct bignum *g; /* Generator of subgroup (public) */ struct bignum *p; /* Prime number (public) */ struct bignum *q; /* Order of subgroup (public) */ struct bignum *y; /* Public key */ struct bignum *x; /* Private key */ }; struct dsa_public_key { struct bignum *g; /* Generator of subgroup (public) */ struct bignum *p; /* Prime number (public) */ struct bignum *q; /* Order of subgroup (public) */ struct bignum *y; /* Public key */ }; struct dh_keypair { struct bignum *g; /* Generator of Z_p (shared) */ struct bignum *p; /* Prime modulus (shared) */ struct bignum *x; /* Private key */ struct bignum *y; /* Public key y = g^x */ /* * Optional parameters used by key generation. * When not used, q == NULL and xbits == 0 */ struct bignum *q; /* x must be in the range [2, q-2] */ uint32_t xbits; /* Number of bits in the private key */ }; struct ecc_public_key { struct bignum *x; /* Public value x */ struct bignum *y; /* Public value y */ uint32_t curve; /* Curve type */ const struct crypto_ecc_public_ops *ops; /* Key Operations */ }; struct ecc_keypair { struct bignum *d; /* Private value */ struct bignum *x; /* Public value x */ struct bignum *y; /* Public value y */ uint32_t curve; /* Curve type */ const struct crypto_ecc_keypair_ops *ops; /* Key Operations */ }; struct montgomery_keypair { uint8_t *priv; /* Private value */ uint8_t *pub; /* Public value */ }; struct ed25519_keypair { uint8_t *priv; uint8_t *pub; uint32_t curve; }; struct ed25519_public_key { uint8_t *pub; uint32_t curve; }; /* * Key allocation functions * Allocate the bignum's inside a key structure. * TEE core will later use crypto_bignum_free(). */ TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, size_t key_size_bits); void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s); void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s); TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_ecc_public_key(struct ecc_public_key *s, uint32_t key_type, size_t key_size_bits); TEE_Result crypto_acipher_alloc_ecc_keypair(struct ecc_keypair *s, uint32_t key_type, size_t key_size_bits); void crypto_acipher_free_ecc_public_key(struct ecc_public_key *s); TEE_Result crypto_acipher_alloc_x25519_keypair(struct montgomery_keypair *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_x448_keypair(struct montgomery_keypair *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_ed25519_keypair(struct ed25519_keypair *s, size_t key_size_bits); TEE_Result crypto_acipher_alloc_ed25519_public_key(struct ed25519_public_key *key, size_t key_size); /* * Key generation functions */ TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size); TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size); TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, size_t xbits, size_t key_size); TEE_Result crypto_acipher_gen_ecc_key(struct ecc_keypair *key, size_t key_size); TEE_Result crypto_acipher_gen_x25519_key(struct montgomery_keypair *key, size_t key_size); TEE_Result crypto_acipher_gen_x448_key(struct montgomery_keypair *key, size_t key_size); TEE_Result crypto_acipher_gen_ed25519_key(struct ed25519_keypair *key, size_t key_size); TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len, bool ph_flag, const uint8_t *ctx, size_t ctxlen); TEE_Result crypto_acipher_ed25519_verify(struct ed25519_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); TEE_Result crypto_acipher_ed25519ctx_verify(struct ed25519_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, bool ph_flag, const uint8_t *ctx, size_t ctxlen); TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, struct bignum *public_key, struct bignum *secret); TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); /* RSA SSA sign/verify: if salt_len == -1, use default value */ TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len); TEE_Result crypto_acipher_sm2_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result crypto_acipher_x25519_shared_secret(struct montgomery_keypair *private_key, void *public_key, void *secret, unsigned long *secret_len); TEE_Result crypto_acipher_x448_shared_secret(struct montgomery_keypair *private_key, void *public_key, void *secret, unsigned long *secret_len); struct sm2_kep_parms { uint8_t *out; size_t out_len; bool is_initiator; const uint8_t *initiator_id; size_t initiator_id_len; const uint8_t *responder_id; size_t responder_id_len; const uint8_t *conf_in; size_t conf_in_len; uint8_t *conf_out; size_t conf_out_len; }; TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key, struct ecc_keypair *my_eph_key, struct ecc_public_key *peer_key, struct ecc_public_key *peer_eph_key, struct sm2_kep_parms *p); /* * Verifies a SHA-256 hash, doesn't require crypto_init() to be called in * advance and has as few dependencies as possible. * * This function is primarily used by pager and early initialization code * where the complete crypto library isn't available. */ TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, size_t data_size); /* * Computes a SHA-512/256 hash, vetted conditioner as per NIST.SP.800-90B. * It doesn't require crypto_init() to be called in advance and has as few * dependencies as possible. * * This function could be used inside interrupt context where the crypto * library can't be used due to mutex handling. */ TEE_Result hash_sha512_256_compute(uint8_t *digest, const uint8_t *data, size_t data_size); #define CRYPTO_RNG_SRC_IS_QUICK(sid) (!!((sid) & 1)) /* * enum crypto_rng_src - RNG entropy source * * Identifiers for different RNG entropy sources. The lowest bit indicates * if the source is to be merely queued (bit is 1) or if it's delivered * directly to the pool. The difference is that in the latter case RPC to * normal world can be performed and in the former it must not. */ enum crypto_rng_src { CRYPTO_RNG_SRC_JITTER_SESSION = (0 << 1 | 0), CRYPTO_RNG_SRC_JITTER_RPC = (1 << 1 | 1), CRYPTO_RNG_SRC_NONSECURE = (1 << 1 | 0), }; /* * crypto_rng_init() - initialize the RNG * @data: buffer with initial seed * @dlen: length of @data */ TEE_Result crypto_rng_init(const void *data, size_t dlen); /* * crypto_rng_add_event() - supply entropy to RNG from a source * @sid: Source identifier, should be unique for a specific source * @pnum: Pool number, acquired using crypto_rng_get_next_pool_num() * @data: Data associated with the event * @dlen: Length of @data * * @sid controls whether the event is merly queued in a ring buffer or if * it's added to one of the pools directly. If CRYPTO_RNG_SRC_IS_QUICK() is * true (lowest bit set) events are queue otherwise added to corresponding * pool. If CRYPTO_RNG_SRC_IS_QUICK() is false, eventual queued events are * added to their queues too. */ void crypto_rng_add_event(enum crypto_rng_src sid, unsigned int *pnum, const void *data, size_t dlen); /* * crypto_rng_read() - read cryptograhically secure RNG * @buf: Buffer to hold the data * @len: Length of buffer. * * Eventual queued events are also added to their pools during this * function call. */ TEE_Result crypto_rng_read(void *buf, size_t len); /* * crypto_aes_expand_enc_key() - Expand an AES key * @key: AES key buffer * @key_len: Size of the @key buffer in bytes * @enc_key: Expanded AES encryption key buffer * @enc_keylen: Size of the @enc_key buffer in bytes * @rounds: Number of rounds to be used during encryption */ TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len, void *enc_key, size_t enc_keylen, unsigned int *rounds); /* * crypto_aes_enc_block() - Encrypt an AES block * @enc_key: Expanded AES encryption key * @enc_keylen: Size of @enc_key in bytes * @rounds: Number of rounds * @src: Source buffer of one AES block (16 bytes) * @dst: Destination buffer of one AES block (16 bytes) */ void crypto_aes_enc_block(const void *enc_key, size_t enc_keylen, unsigned int rounds, const void *src, void *dst); #endif /* __CRYPTO_CRYPTO_H */ optee_os-4.3.0/core/include/crypto/crypto_accel.h000066400000000000000000000055361464416617300220730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020-2023, Linaro Limited */ #ifndef __CRYPTO_CRYPTO_ACCEL_H #define __CRYPTO_CRYPTO_ACCEL_H #include TEE_Result crypto_accel_aes_expand_keys(const void *key, size_t key_len, void *enc_key, void *dec_key, size_t expanded_key_len, unsigned int *round_count); void crypto_accel_aes_ecb_enc(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count); void crypto_accel_aes_ecb_dec(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count); void crypto_accel_aes_cbc_enc(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count, void *iv); void crypto_accel_aes_cbc_dec(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count, void *iv); void crypto_accel_aes_ctr_be_enc(void *out, const void *in, const void *key, unsigned int round_count, unsigned int block_count, void *iv); void crypto_accel_aes_xts_enc(void *out, const void *in, const void *key1, unsigned int round_count, unsigned int block_count, const void *key2, void *tweak); void crypto_accel_aes_xts_dec(void *out, const void *in, const void *key1, unsigned int round_count, unsigned int block_count, const void *key2, void *tweak); void crypto_accel_sha1_compress(uint32_t state[5], const void *src, unsigned int block_count); void crypto_accel_sha256_compress(uint32_t state[8], const void *src, unsigned int block_count); void crypto_accel_sha512_compress(uint64_t state[8], const void *src, unsigned int block_count); void crypto_accel_sha3_compress(uint64_t state[25], const void *src, unsigned int block_count, unsigned int digest_size); void crypto_accel_sm3_compress(uint32_t state[8], const void *src, unsigned int block_count); void crypto_accel_sm4_setkey_enc(uint32_t sk[32], const uint8_t key[16]); void crypto_accel_sm4_setkey_dec(uint32_t sk[32], const uint8_t key[16]); void crypto_accel_sm4_ecb_enc(void *out, const void *in, const void *key, unsigned int len); void crypto_accel_sm4_cbc_enc(void *out, const void *in, const void *key, unsigned int len, void *iv); void crypto_accel_sm4_cbc_dec(void *out, const void *in, const void *key, unsigned int len, void *iv); void crypto_accel_sm4_ctr_enc(void *out, const void *in, const void *key, unsigned int len, void *iv); void crypto_accel_sm4_xts_enc(void *out, const void *in, const void *key1, const void *key2, unsigned int len, void *iv); void crypto_accel_sm4_xts_dec(void *out, const void *in, const void *key1, const void *key2, unsigned int len, void *iv); #endif /*__CRYPTO_CRYPTO_ACCEL_H*/ optee_os-4.3.0/core/include/crypto/crypto_impl.h000066400000000000000000000426601464416617300217640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2021, SumUp Services GmbH */ #ifndef __CRYPTO_CRYPTO_IMPL_H #define __CRYPTO_CRYPTO_IMPL_H #include #include /* * The crypto context used by the crypto_hash_*() functions is defined by * struct crypto_hash_ctx. */ struct crypto_hash_ctx { const struct crypto_hash_ops *ops; }; struct crypto_hash_ops { TEE_Result (*init)(struct crypto_hash_ctx *ctx); TEE_Result (*update)(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len); TEE_Result (*final)(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len); void (*free_ctx)(struct crypto_hash_ctx *ctx); void (*copy_state)(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx); }; #define CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(name, type) \ static inline TEE_Result \ crypto_##name##_alloc_ctx(struct crypto_##type##_ctx **ctx __unused) \ { return TEE_ERROR_NOT_IMPLEMENTED; } #if defined(CFG_CRYPTO_MD5) TEE_Result crypto_md5_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(md5, hash) #endif #if defined(CFG_CRYPTO_SHA1) TEE_Result crypto_sha1_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha1, hash) #endif #if defined(CFG_CRYPTO_SHA224) TEE_Result crypto_sha224_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha224, hash) #endif #if defined(CFG_CRYPTO_SHA256) TEE_Result crypto_sha256_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha256, hash) #endif #if defined(CFG_CRYPTO_SHA384) TEE_Result crypto_sha384_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha384, hash) #endif #if defined(CFG_CRYPTO_SHA512) TEE_Result crypto_sha512_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha512, hash) #endif #if defined(CFG_CRYPTO_SM3) TEE_Result crypto_sm3_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm3, hash) #endif #if defined(CFG_CRYPTO_SHA3_224) TEE_Result crypto_sha3_224_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_224, hash) #endif #if defined(CFG_CRYPTO_SHA3_256) TEE_Result crypto_sha3_256_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_256, hash) #endif #if defined(CFG_CRYPTO_SHA3_384) TEE_Result crypto_sha3_384_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_384, hash) #endif #if defined(CFG_CRYPTO_SHA3_512) TEE_Result crypto_sha3_512_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sha3_512, hash) #endif #if defined(CFG_CRYPTO_SHAKE128) TEE_Result crypto_shake128_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(shake128, hash) #endif #if defined(CFG_CRYPTO_SHAKE256) TEE_Result crypto_shake256_alloc_ctx(struct crypto_hash_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(shake256, hash) #endif /* * The crypto context used by the crypto_mac_*() functions is defined by * struct crypto_mac_ctx. */ struct crypto_mac_ctx { const struct crypto_mac_ops *ops; }; struct crypto_mac_ops { TEE_Result (*init)(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len); TEE_Result (*update)(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len); TEE_Result (*final)(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len); void (*free_ctx)(struct crypto_mac_ctx *ctx); void (*copy_state)(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx); }; #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_MD5) TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_md5, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA1) TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha1, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA224) TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha224, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA256) TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha256, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA384) TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha384, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA512) TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha512, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_224) TEE_Result crypto_hmac_sha3_224_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_224, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_256) TEE_Result crypto_hmac_sha3_256_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_256, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_384) TEE_Result crypto_hmac_sha3_384_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_384, mac) #endif #if defined(CFG_CRYPTO_HMAC) && defined(CFG_CRYPTO_SHA3_512) TEE_Result crypto_hmac_sha3_512_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sha3_512, mac) #endif #if defined(CFG_CRYPTO_SM3) && defined(CFG_CRYPTO_HMAC) TEE_Result crypto_hmac_sm3_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(hmac_sm3, mac) #endif #if defined(CFG_CRYPTO_CBC_MAC) TEE_Result crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx); TEE_Result crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx); TEE_Result crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx); TEE_Result crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx); TEE_Result crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx); TEE_Result crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cbc_mac_nopad, mac) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cbc_mac_pkcs5, mac) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc_mac_nopad, mac) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc_mac_pkcs5, mac) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc_mac_nopad, mac) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc_mac_pkcs5, mac) #endif #if defined(CFG_CRYPTO_CMAC) TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx); TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cmac, mac) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cmac, mac) #endif /* * The crypto context used by the crypto_cipher_*() functions is defined by * struct crypto_cipher_ctx. */ struct crypto_cipher_ctx { const struct crypto_cipher_ops *ops; }; struct crypto_cipher_ops { TEE_Result (*init)(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2, size_t key2_len, const uint8_t *iv, size_t iv_len); TEE_Result (*update)(struct crypto_cipher_ctx *ctx, bool last_block, const uint8_t *data, size_t len, uint8_t *dst); void (*final)(struct crypto_cipher_ctx *ctx); void (*free_ctx)(struct crypto_cipher_ctx *ctx); void (*copy_state)(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx); }; #if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_ECB) TEE_Result crypto_aes_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_ecb, cipher) #endif #if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_CBC) TEE_Result crypto_aes_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cbc, cipher) #endif #if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_CTR) TEE_Result crypto_aes_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_ctr, cipher) #endif #if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_CTS) TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_cts, cipher) #endif #if defined(CFG_CRYPTO_AES) && defined(CFG_CRYPTO_XTS) TEE_Result crypto_aes_xts_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(aes_xts, cipher) #endif #if defined(CFG_CRYPTO_DES) && defined(CFG_CRYPTO_ECB) TEE_Result crypto_des_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); TEE_Result crypto_des3_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_ecb, cipher) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_ecb, cipher) #endif #if defined(CFG_CRYPTO_DES) && defined(CFG_CRYPTO_CBC) TEE_Result crypto_des_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des_cbc, cipher) CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(des3_cbc, cipher) #endif #if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_ECB) TEE_Result crypto_sm4_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_ecb, cipher) #endif #if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_CBC) TEE_Result crypto_sm4_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_cbc, cipher) #endif #if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_CTR) TEE_Result crypto_sm4_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_ctr, cipher) #endif #if defined(CFG_CRYPTO_SM4) && defined(CFG_CRYPTO_XTS) TEE_Result crypto_sm4_xts_alloc_ctx(struct crypto_cipher_ctx **ctx); #else CRYPTO_ALLOC_CTX_NOT_IMPLEMENTED(sm4_xts, cipher) #endif /* * The crypto context used by the crypto_authen_*() functions below is * defined by struct crypto_authenc_ctx. */ struct crypto_authenc_ctx { const struct crypto_authenc_ops *ops; }; struct crypto_authenc_ops { TEE_Result (*init)(struct crypto_authenc_ctx *ctx, TEE_OperationMode mode, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); TEE_Result (*update_aad)(struct crypto_authenc_ctx *ctx, const uint8_t *data, size_t len); TEE_Result (*update_payload)(struct crypto_authenc_ctx *ctx, TEE_OperationMode mode, const uint8_t *src_data, size_t len, uint8_t *dst_data); TEE_Result (*enc_final)(struct crypto_authenc_ctx *ctx, const uint8_t *src_data, size_t len, uint8_t *dst_data, uint8_t *dst_tag, size_t *dst_tag_len); TEE_Result (*dec_final)(struct crypto_authenc_ctx *ctx, const uint8_t *src_data, size_t len, uint8_t *dst_data, const uint8_t *tag, size_t tag_len); void (*final)(struct crypto_authenc_ctx *ctx); void (*free_ctx)(struct crypto_authenc_ctx *ctx); void (*copy_state)(struct crypto_authenc_ctx *dst_ctx, struct crypto_authenc_ctx *src_ctx); }; TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx); TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx); #ifdef CFG_CRYPTO_DRV_HASH TEE_Result drvcrypt_hash_alloc_ctx(struct crypto_hash_ctx **ctx, uint32_t algo); #else static inline TEE_Result drvcrypt_hash_alloc_ctx(struct crypto_hash_ctx **ctx __unused, uint32_t algo __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_CRYPTO_DRV_HASH */ #ifdef CFG_CRYPTO_DRV_CIPHER TEE_Result drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx, uint32_t algo); #else static inline TEE_Result drvcrypt_cipher_alloc_ctx(struct crypto_cipher_ctx **ctx __unused, uint32_t algo __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_CRYPTO_DRV_CIPHER */ #ifdef CFG_CRYPTO_DRV_MAC /* Cryptographic MAC driver context allocation */ TEE_Result drvcrypt_mac_alloc_ctx(struct crypto_mac_ctx **ctx, uint32_t algo); #else static inline TEE_Result drvcrypt_mac_alloc_ctx(struct crypto_mac_ctx **ctx __unused, uint32_t algo __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_CRYPTO_DRV_MAC */ #ifdef CFG_CRYPTO_DRV_AUTHENC /* Cryptographic Authenticated Encryption driver context allocation */ TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx, uint32_t algo); #else static inline TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx __unused, uint32_t algo __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_CRYPTO_DRV_AUTHENC */ /* * The ECC public key operations used by the crypto_acipher_ecc_*() and * crypto_acipher_free_ecc_*() functions. * Reference set in ecc_public_key when key allocated. * * @free is mandatory * @verify is optional * @encrypt is optional */ struct crypto_ecc_public_ops { void (*free)(struct ecc_public_key *key); TEE_Result (*verify)(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); TEE_Result (*encrypt)(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); }; /* * The ECC keypair operations used by the crypto_acipher_ecc_*() and * crypto_acipher_gen_ecc_*() functions. * Reference set in ecc_keypair when key allocated. * * @generate is mandatory * @sign is optional * @shared_secret is optional * @decrypt is optional */ struct crypto_ecc_keypair_ops { TEE_Result (*generate)(struct ecc_keypair *key, size_t key_size_bits); TEE_Result (*sign)(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result (*shared_secret)(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len); TEE_Result (*decrypt)(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); }; #ifdef CFG_CRYPTO_ECC const struct crypto_ecc_keypair_ops * crypto_asym_get_ecc_keypair_ops(uint32_t key_type); const struct crypto_ecc_public_ops * crypto_asym_get_ecc_public_ops(uint32_t key_type); TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *key, uint32_t key_type, size_t key_size_bits); TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *key, uint32_t key_type, size_t key_size_bits); #else static inline TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *key __unused, uint32_t key_type __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline const struct crypto_ecc_keypair_ops * crypto_asym_get_ecc_keypair_ops(uint32_t key_type __unused) { return NULL; } static inline const struct crypto_ecc_public_ops * crypto_asym_get_ecc_public_ops(uint32_t key_type __unused) { return NULL; } static inline TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *key __unused, uint32_t key_type __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_CRYPTO_ECC */ #ifdef CFG_CRYPTO_DRV_ECC TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key, uint32_t key_type, size_t key_size_bits); TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key, uint32_t key_type, size_t key_size_bits); #else static inline TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key __unused, uint32_t key_type __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key __unused, uint32_t key_type __unused, size_t key_size_bits __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_CRYPTO_DRV_ECC */ TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, size_t key_size_bits); TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, size_t key_size_bits); void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s); void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s); TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size); TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); #endif /*__CRYPTO_CRYPTO_IMPL_H*/ optee_os-4.3.0/core/include/crypto/crypto_se.h000066400000000000000000000027271464416617300214320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved * Author: Jorge Ramirez */ /* * This is the Cryptographic Secure Element API, part of the Cryptographic * Provider API. * * These requests shall be handled in the secure element normally placed on * a serial communication bus (SPI, I2C). */ #ifndef __CRYPTO_CRYPTO_SE_H #define __CRYPTO_CRYPTO_SE_H #include /* * Type identifier for the APDU message as described by Smart Card Standard * ISO7816-4 about ADPU message bodies decoding convention: * * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 */ enum crypto_apdu_type { CRYPTO_APDU_CASE_NO_HINT, CRYPTO_APDU_CASE_1, CRYPTO_APDU_CASE_2, CRYPTO_APDU_CASE_2E, CRYPTO_APDU_CASE_3, CRYPTO_APDU_CASE_3E, CRYPTO_APDU_CASE_4, CRYPTO_APDU_CASE_4E, }; TEE_Result crypto_se_do_apdu(enum crypto_apdu_type type, uint8_t *header, size_t hdr_len, uint8_t *src_data, size_t src_len, uint8_t *dst_data, size_t *dst_len); /* * Enable Secure Channel Protocol 03 to communicate with the Secure Element. * * Since SCP03 uses symmetric encryption, this interface also allows the user to * attempt the rotation the keys stored in the Secure Element. * * https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf */ TEE_Result crypto_se_enable_scp03(bool rotate_keys); #endif optee_os-4.3.0/core/include/crypto/internal_aes-gcm.h000066400000000000000000000076011464416617300226270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited * */ #ifndef __CRYPTO_INTERNAL_AES_GCM_H #define __CRYPTO_INTERNAL_AES_GCM_H #include #include #include #include #ifdef CFG_CRYPTO_WITH_CE #include #else struct internal_ghash_key { #ifdef CFG_AES_GCM_TABLE_BASED uint64_t HL[16]; uint64_t HH[16]; #else uint64_t hash_subkey[2]; #endif }; #endif struct internal_aes_gcm_key { /* AES (CTR) encryption key and number of rounds */ uint64_t data[30]; unsigned int rounds; }; struct internal_aes_gcm_state { uint64_t ctr[2]; struct internal_ghash_key ghash_key; uint8_t hash_state[TEE_AES_BLOCK_SIZE]; uint8_t buf_tag[TEE_AES_BLOCK_SIZE]; uint8_t buf_hash[TEE_AES_BLOCK_SIZE]; uint8_t buf_cryp[TEE_AES_BLOCK_SIZE]; unsigned int tag_len; unsigned int aad_bytes; unsigned int payload_bytes; unsigned int buf_pos; }; struct internal_aes_gcm_ctx { struct internal_aes_gcm_state state; struct internal_aes_gcm_key key; }; TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx, TEE_OperationMode mode, const void *key, size_t key_len, const void *nonce, size_t nonce_len, size_t tag_len); TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx, const void *data, size_t len); TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx, TEE_OperationMode mode, const void *src, size_t len, void *dst); TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx, const void *src, size_t len, void *dst, void *tag, size_t *tag_len); TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx, const void *src, size_t len, void *dst, const void *tag, size_t tag_len); void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state); void internal_aes_gcm_dec_ctr(struct internal_aes_gcm_state *state); TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key, const void *nonce, size_t nonce_len, const void *aad, size_t aad_len, const void *src, size_t len, void *dst, void *tag, size_t *tag_len); TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key, const void *nonce, size_t nonce_len, const void *aad, size_t aad_len, const void *src, size_t len, void *dst, const void *tag, size_t tag_len); void internal_aes_gcm_gfmul(const uint64_t X[2], const uint64_t Y[2], uint64_t product[2]); static inline void internal_aes_gcm_xor_block(void *dst, const void *src) { uint64_t *d = dst; const uint64_t *s = src; assert(IS_ALIGNED_WITH_TYPE(dst, uint64_t)); assert(IS_ALIGNED_WITH_TYPE(src, uint64_t)); d[0] ^= s[0]; d[1] ^= s[1]; } static inline bool internal_aes_gcm_ptr_is_block_aligned(const void *p) { return !((vaddr_t)p & (TEE_AES_BLOCK_SIZE - 1)); } #ifdef CFG_AES_GCM_TABLE_BASED void internal_aes_gcm_ghash_gen_tbl(struct internal_ghash_key *ghash_key, const struct internal_aes_gcm_key *enc_key); void internal_aes_gcm_ghash_mult_tbl(struct internal_ghash_key *ghash_key, const unsigned char x[16], unsigned char output[16]); #endif /* * Must be implemented in core/arch/arm/crypto/ if CFG_CRYPTO_WITH_CE=y */ void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *enc_key); void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, const void *head, const void *data, size_t num_blocks); /* * Internal weak function that can be overridden with hardware specific * implementation. */ void internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, const struct internal_aes_gcm_key *ek, TEE_OperationMode mode, const void *src, size_t num_blocks, void *dst); #endif /*__CRYPTO_INTERNAL_AES_GCM_H*/ optee_os-4.3.0/core/include/crypto/sm2-kdf.h000066400000000000000000000005011464416617300206520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020-2021, Huawei Technologies Co., Ltd */ #ifndef __CRYPTO_SM2_KDF_H #define __CRYPTO_SM2_KDF_H #include #include TEE_Result sm2_kdf(const uint8_t *Z, size_t Z_len, uint8_t *t, size_t tlen); #endif /* __CRYPTO_SM2_KDF_H */ optee_os-4.3.0/core/include/drivers/000077500000000000000000000000001464416617300174005ustar00rootroot00000000000000optee_os-4.3.0/core/include/drivers/amlogic_uart.h000066400000000000000000000005371464416617300222240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ #ifndef __DRIVERS_AMLOGIC_UART_H #define __DRIVERS_AMLOGIC_UART_H #include #include struct amlogic_uart_data { struct io_pa_va base; struct serial_chip chip; }; void amlogic_uart_init(struct amlogic_uart_data *pd, paddr_t base); #endif /* __DRIVERS_AMLOGIC_UART_H */ optee_os-4.3.0/core/include/drivers/atmel_rstc.h000066400000000000000000000011341464416617300217050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Microchip */ #ifndef __DRIVERS_ATMEL_RSTC_H #define __DRIVERS_ATMEL_RSTC_H #include #include #if defined(CFG_ATMEL_RSTC) bool atmel_rstc_available(void); void __noreturn atmel_rstc_reset(void); void sam_rstc_usb_por(unsigned char id, bool enable); #else static inline bool atmel_rstc_available(void) { return false; } static inline void atmel_rstc_reset(void) {} static inline void sam_rstc_usb_por(unsigned char id __unused, bool enable __unused) {} #endif #endif /* __DRIVERS_ATMEL_RSTC_H */ optee_os-4.3.0/core/include/drivers/atmel_rtc.h000066400000000000000000000007241464416617300215260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Microchip */ #ifndef __DRIVERS_ATMEL_RTC_H #define __DRIVERS_ATMEL_RTC_H #include #include #ifdef CFG_ATMEL_RTC TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm); #else static inline TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif #endif /* __DRIVERS_ATMEL_RTC_H */ optee_os-4.3.0/core/include/drivers/atmel_saic.h000066400000000000000000000022361464416617300216550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Microchip */ #ifndef __DRIVERS_ATMEL_SAIC_H #define __DRIVERS_ATMEL_SAIC_H #include #include #define AT91_AIC_WPKEY 0x414943 #define AT91_AIC_SSR 0x0 #define AT91_AIC_SSR_ITSEL_MASK GENMASK_32(6, 0) #define AT91_AIC_SMR 0x4 #define AT91_AIC_SMR_SRC_SHIFT 5 #define AT91_AIC_SMR_LEVEL SHIFT_U32(0, AT91_AIC_SMR_SRC_SHIFT) #define AT91_AIC_SMR_NEG_EDGE SHIFT_U32(1, AT91_AIC_SMR_SRC_SHIFT) #define AT91_AIC_SMR_HIGH_LEVEL SHIFT_U32(2, AT91_AIC_SMR_SRC_SHIFT) #define AT91_AIC_SMR_POS_EDGE SHIFT_U32(3, AT91_AIC_SMR_SRC_SHIFT) #define AT91_AIC_SVR 0x8 #define AT91_AIC_IVR 0x10 #define AT91_AIC_ISR 0x18 #define AT91_AIC_IPR0 0x20 #define AT91_AIC_IPR1 0x24 #define AT91_AIC_IPR2 0x28 #define AT91_AIC_IPR3 0x2c #define AT91_AIC_IMR 0x30 #define AT91_AIC_CISR 0x34 #define AT91_AIC_EOICR 0x38 #define AT91_AIC_SPU 0x3c #define AT91_AIC_IECR 0x40 #define AT91_AIC_IDCR 0x44 #define AT91_AIC_ICCR 0x48 #define AT91_AIC_ISCR 0x4c #define AT91_AIC_DCR 0x6c #define AT91_AIC_WPMR 0xe4 #define AT91_AIC_WPSR 0xe8 TEE_Result atmel_saic_setup(void); #endif /*__DRIVERS_ATMEL_SAIC_H*/ optee_os-4.3.0/core/include/drivers/atmel_shdwc.h000066400000000000000000000034351464416617300220500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015 Atmel Corporation, * Nicolas Ferre * Copyright (c) 2021, Microchip */ #ifndef __DRIVERS_ATMEL_SHDWC_H #define __DRIVERS_ATMEL_SHDWC_H #include #include #include #include /* Shut Down Control Register */ #define AT91_SHDW_CR 0x00 /* Shut Down command */ #define AT91_SHDW_SHDW BIT(0) /* KEY Password */ #define AT91_SHDW_KEY SHIFT_U32(0xa5UL, 24) /* Shut Down Mode Register */ #define AT91_SHDW_MR 0x04 #define AT91_SHDW_WKUPDBC_SHIFT 24 #define AT91_SHDW_WKUPDBC_MASK GENMASK_32(26, 24) #define AT91_SHDW_WKUPDBC(x) (SHIFT_U32((x), AT91_SHDW_WKUPDBC_SHIFT) & \ AT91_SHDW_WKUPDBC_MASK) #define AT91_SHDW_RTCWKEN BIT32(17) #define AT91_SHDW_RTTWKEN BIT32(16) /* Shut Down Status Register */ #define AT91_SHDW_SR 0x08 #define AT91_SHDW_WKUPIS_SHIFT 16 #define AT91_SHDW_WKUPIS_MASK GENMASK_32(31, 16) #define AT91_SHDW_WKUPIS(x) (BIT32((x) + AT91_SHDW_WKUPIS_SHIFT)) /* Shutdown Wake-up Inputs Register */ #define AT91_SHDW_WUIR 0x0c #define AT91_SHDW_WKUPEN_MASK GENMASK_32(15, 0) #define AT91_SHDW_WKUPEN(x) (BIT32(x) & AT91_SHDW_WKUPEN_MASK) #define AT91_SHDW_WKUPT_SHIFT 16 #define AT91_SHDW_WKUPT_MASK GENMASK_32(31, 16) #define AT91_SHDW_WKUPT(x) (BIT32((x) + AT91_SHDW_WKUPT_SHIFT)) #ifndef __ASSEMBLER__ #if defined(CFG_ATMEL_SHDWC) void __atmel_shdwc_shutdown(uint32_t mpddrc_base, uint32_t shdwc_base, uint32_t pmc_base); bool atmel_shdwc_available(void); void __noreturn atmel_shdwc_shutdown(void); #else static inline bool atmel_shdwc_available(void) { return false; } static inline void atmel_shdwc_shutdown(void) {} #endif /* defined(CFG_ATMEL_SHDWC) */ #endif /* __ASSEMBLER__*/ #endif /* __DRIVERS_ATMEL_SHDWC_H */ optee_os-4.3.0/core/include/drivers/atmel_uart.h000066400000000000000000000032571464416617300217150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Timesys Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_ATMEL_UART_H #define __DRIVERS_ATMEL_UART_H #include #include struct atmel_uart_data { struct io_pa_va base; struct serial_chip chip; }; void atmel_uart_init(struct atmel_uart_data *pd, paddr_t base); #endif /* __DRIVERS_ATMEL_UART_H */ optee_os-4.3.0/core/include/drivers/bcm/000077500000000000000000000000001464416617300201415ustar00rootroot00000000000000optee_os-4.3.0/core/include/drivers/bcm/bnxt.h000066400000000000000000000021411464416617300212630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef __DRIVERS_BCM_BNXT_H #define __DRIVERS_BCM_BNXT_H #include #include #include #include #define BNXT_SUCCESS 0 #define BNXT_FAILURE (!BNXT_SUCCESS) uint32_t bnxt_write32_multiple(uintptr_t dst, uintptr_t src, uint32_t num_entries, int src_4byte_increment); void bnxt_handshake_clear(void); void bnxt_chimp_halt(void); void bnxt_kong_halt(void); int bnxt_fastboot(uintptr_t addr); uint32_t bnxt_wait_handshake(uint32_t timeout); uint32_t bnxt_health_status(void); TEE_Result bnxt_load_fw(int chip_type); TEE_Result bnxt_copy_crash_dump(uint8_t *d, uint32_t offset, uint32_t len); struct bnxt_images_info { vaddr_t bnxt_fw_vaddr; uint32_t bnxt_fw_len; vaddr_t bnxt_cfg_vaddr; uint32_t bnxt_cfg_len; vaddr_t bnxt_bspd_cfg_vaddr; uint32_t bnxt_bspd_cfg_len; }; /* Reserve 1K for BSPD data */ #define BNXT_IMG_SECMEM_OFFSET 0x400 int get_bnxt_images_info(struct bnxt_images_info *bnxt_info, int chip_type, vaddr_t ddr_dest); #endif optee_os-4.3.0/core/include/drivers/bcm_gpio.h000066400000000000000000000015741464416617300213370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef __DRIVERS_BCM_GPIO_H #define __DRIVERS_BCM_GPIO_H #include #include #include /** * struct bcm_gpio_chip describes GPIO controller chip instance * @chip: generic GPIO chip handle. * @gpio_base: starting GPIO number managed by this GPIO controller. * @ngpios: number of GPIOs managed by this GPIO controller. * @base: virtual base address of the GPIO controller registers. */ struct bcm_gpio_chip { struct gpio_chip chip; unsigned int gpio_base; unsigned int ngpios; vaddr_t base; SLIST_ENTRY(bcm_gpio_chip) link; }; /* Returns bcm_gpio_chip handle for a GPIO pin */ struct bcm_gpio_chip *bcm_gpio_pin_to_chip(unsigned int pin); /* Set gpiopin as secure */ void iproc_gpio_set_secure(int gpiopin); #endif /* __DRIVERS_BCM_GPIO_H */ optee_os-4.3.0/core/include/drivers/bcm_hwrng.h000066400000000000000000000004141464416617300215160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef __DRIVERS_BCM_HWRNG_H #define __DRIVERS_BCM_HWRNG_H #include uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read); #endif /* __DRIVERS_BCM_HWRNG_H */ optee_os-4.3.0/core/include/drivers/bcm_sotp.h000066400000000000000000000014501464416617300213570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef __DRIVERS_BCM_SOTP_H #define __DRIVERS_BCM_SOTP_H #include #include #define SOTP_ECC_ERR_DETECT BIT64(63) /** * Reads from sotp fuse at given row address. * @row_addr: row address * @sotp_add_ecc: ecc memory support flag * @rdata: pointer to sotp data value * @returns TEE_Result value */ TEE_Result bcm_iproc_sotp_mem_read(uint32_t row_addr, bool sotp_add_ecc, uint64_t *rdata); /** * Writes to sotp fuse at given row address. * @row_addr: row address * @sotp_add_ecc: ecc memory support flag * @wdata: data to be written to sotp fuse * @returns TEE_Result value */ TEE_Result bcm_iproc_sotp_mem_write(uint32_t row_addr, bool sotp_add_ecc, uint64_t wdata); #endif optee_os-4.3.0/core/include/drivers/caam_extension.h000066400000000000000000000030021464416617300225410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2023 NXP */ #ifndef __DRIVERS_CAAM_EXTENSION_H__ #define __DRIVERS_CAAM_EXTENSION_H__ #include #include #include #ifdef CFG_NXP_CAAM_MP_DRV /* * Export the MPMR content. * We assume that it is filled with message given in parameter. * It contains 32 registers of 8 bits (32 bytes). * * @mpmr [out] MPMR buffer read * @size [in/out] MPMR buffer size exported */ TEE_Result caam_mp_export_mpmr(uint8_t *mpmr, size_t *size); /* * Export the Manufacturing Protection Public Key. * * @pubkey [out] Public key read * @size [in/out] Public key size exported */ TEE_Result caam_mp_export_publickey(uint8_t *pubkey, size_t *size); /* * MPSign function. * This function takes the value in the MPMR if it exists * and concatenates any additional data (certificate). * The signature over the message is done with the private key. * * @data [in] Data to sign * @data_size [in] Data size to sign * @sig [out] Signature * @sig_size [in/out] Signature size */ TEE_Result caam_mp_sign(uint8_t *data, size_t *data_size, uint8_t *sig, size_t *sig_size); #endif /* CFG_NXP_CAAM_MP_DRV */ #ifdef CFG_NXP_CAAM_DEK_DRV /* * Data encryption key generation using CAAM Secure Memory. * * @blob_data [in/out] Blob data */ TEE_Result caam_dek_generate(const uint8_t *payload, size_t payload_size, uint8_t *dek, size_t dek_size); #endif /* CFG_NXP_CAAM_DEK_DRV */ #endif /* __DRIVERS_CAAM_EXTENSION_H__ */ optee_os-4.3.0/core/include/drivers/cbmem_console.h000066400000000000000000000004111464416617300223520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, Google Limited */ #ifndef __DRIVERS_CBMEM_CONSOLE_H #define __DRIVERS_CBMEM_CONSOLE_H #include bool cbmem_console_init_from_dt(void *fdt); #endif /* __DRIVERS_CBMEM_CONSOLE_H */ optee_os-4.3.0/core/include/drivers/cdns_uart.h000066400000000000000000000033571464416617300215430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Xilinx Inc * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_CDNS_UART_H #define __DRIVERS_CDNS_UART_H #include #include struct cdns_uart_data { struct io_pa_va base; struct serial_chip chip; }; void cdns_uart_init(struct cdns_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); #endif /* __DRIVERS_CDNS_UART_H */ optee_os-4.3.0/core/include/drivers/clk.h000066400000000000000000000163761464416617300203370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Bootlin */ #ifndef __DRIVERS_CLK_H #define __DRIVERS_CLK_H #include #include #include #include /* Flags for clock */ #define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */ #define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ #define CLK_DUTY_CYCLE_PARENT BIT(2) /* forward duty cycle call to parent */ #define CLK_SET_RATE_PARENT BIT(3) /* propagate rate change up to parent */ #define CLK_SET_RATE_UNGATE BIT(4) /* clock needs to run to set rate */ #define CLK_SET_PARENT_PRE_ENABLE BIT(5) /* enable new parent if needed */ /** * struct clk - Clock structure * * @name: Clock name * @priv: Private data for the clock provider * @ops: Clock operations * @parent: Current parent * @rate: Current clock rate (cached after init or rate change) * @flags: Specific clock flags * @enabled_count: Enable/disable reference counter * @num_parents: Number of parents * @parents: Array of possible parents of the clock * @link: Link the clock list */ struct clk { const char *name; void *priv; const struct clk_ops *ops; struct clk *parent; unsigned long rate; unsigned int flags; struct refcount enabled_count; #ifdef CFG_DRIVERS_CLK_PRINT_TREE SLIST_ENTRY(clk) link; #endif size_t num_parents; struct clk *parents[]; }; /** * struct clk_duty_cycle - Encoding the duty cycle ratio of a clock * * @num: Numerator of the duty cycle ratio * @den: Denominator of the duty cycle ratio */ struct clk_duty_cycle { unsigned int num; unsigned int den; }; /** * struct clk_ops - Clock operations * * @enable: Enable the clock * @disable: Disable the clock * @set_parent: Set the clock parent based on index * @get_parent: Get the current parent index of the clock * @set_rate: Set the clock rate * @get_rate: Get the clock rate * @get_rates_array: Get the supported clock rates as array * @get_rates_steps: Get support clock rates by min/max/step representation * @get_duty_cycle: Get duty cytcle of the clock * * All clock operations are expected to execute in a interruptible thread * context at the exclusion of power management sequence where non secure * world is not operating (power off, suspend, resume). */ struct clk_ops { TEE_Result (*enable)(struct clk *clk); void (*disable)(struct clk *clk); TEE_Result (*set_parent)(struct clk *clk, size_t index); size_t (*get_parent)(struct clk *clk); TEE_Result (*set_rate)(struct clk *clk, unsigned long rate, unsigned long parent_rate); unsigned long (*get_rate)(struct clk *clk, unsigned long parent_rate); TEE_Result (*get_rates_array)(struct clk *clk, size_t start_index, unsigned long *rates, size_t *nb_elts); TEE_Result (*get_rates_steps)(struct clk *clk, unsigned long *min, unsigned long *max, unsigned long *step); TEE_Result (*get_duty_cycle)(struct clk *clk, struct clk_duty_cycle *duty_cycle); }; /** * clk_get_name() - Return the clock name * * @clk: Clock for which the name is needed * Return a const char * pointing to the clock name */ static inline const char *clk_get_name(struct clk *clk) { return clk->name; } /** * clk_alloc() - Allocate a clock structure * * @name: Clock name * @ops: Clock operations * @parent_clks: Parents of the clock * @parent_count: Number of parents of the clock * * Return a clock struct properly initialized or NULL if allocation failed */ struct clk *clk_alloc(const char *name, const struct clk_ops *ops, struct clk **parent_clks, size_t parent_count); /** * clk_free() - Free a clock structure * * @clk: Clock to be freed or NULL */ void clk_free(struct clk *clk); /** * clk_register() - Register a clock within the clock framework * * @clk: Clock struct to be registered * Return a TEE_Result compliant value */ TEE_Result clk_register(struct clk *clk); /** * clk_get_rate() - Get clock rate * * @clk: Clock for which the rate is needed * Return the clock rate in Hz */ unsigned long clk_get_rate(struct clk *clk); /** * clk_set_rate() - Set a clock rate * * @clk: Clock to be set with the rate * @rate: Rate to set in Hz * Return a TEE_Result compliant value */ TEE_Result clk_set_rate(struct clk *clk, unsigned long rate); /** * clk_enable() - Enable a clock and its ascendance * * @clk: Clock to be enabled * Return a TEE_Result compliant value */ TEE_Result clk_enable(struct clk *clk); /** * clk_disable() - Disable a clock * * @clk: Clock to be disabled */ void clk_disable(struct clk *clk); /** * clk_is_enabled() - Informative state on the clock * * This function is useful during specific system sequences where core * executes atomically (primary core boot, some low power sequences). * * @clk: Clock refernece */ bool clk_is_enabled(struct clk *clk); /** * clk_get_parent() - Get the current clock parent * * @clk: Clock for which the parent is needed * Return the clock parent or NULL if there is no parent */ struct clk *clk_get_parent(struct clk *clk); /** * clk_get_num_parents() - Get the number of parents for a clock * * @clk: Clock for which the number of parents is needed * Return the number of parents */ static inline size_t clk_get_num_parents(struct clk *clk) { return clk->num_parents; } /** * clk_get_parent_by_index() - Get a clock parent by its index * * @clk: Clock for which the parent is needed * @pidx: Parent index for the clock * Return the clock parent at index @pidx or NULL if out of bound */ struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx); /** * clk_set_parent() - Set the current clock parent * * @clk: Clock for which the parent should be set * @parent: Parent clock to set * Return a TEE_Result compliant value */ TEE_Result clk_set_parent(struct clk *clk, struct clk *parent); /** * clk_get_rates_array() - Get supported rates as an array * * @clk: Clock for which the rates are requested * @start_index: start index of requested rates * @rates: Array of rates allocated by caller or NULL to query count of rates * @nb_elts: Max number of elements that the array can hold as input. Contains * the number of elements that was added in the array as output. * Returns a TEE_Result compliant value */ TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index, unsigned long *rates, size_t *nb_elts); /** * clk_get_rates_steps() - Get supported rates as min/max/step triplet * * @clk: Clock for which the rates are requested * @min: Output min supported rate in Hz * @max: Output max supported rate in Hz * @step: Output rate step in Hz * Returns a TEE_Result compliant value */ TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min, unsigned long *max, unsigned long *step); /** * clk_get_duty_cycle() - Get clock duty cycle * * @clk: Clock for which the duty cycle is requested * @duty: Output duty cycle info * Return a TEE_Result compliant value */ TEE_Result clk_get_duty_cycle(struct clk *clk, struct clk_duty_cycle *duty_cycle); #ifdef CFG_DRIVERS_CLK /** * clk_print_tree() - Print current clock tree summary to output console * * The clock is printed with the debug trace level. */ void clk_print_tree(void); #else static inline void clk_print_tree(void) { } #endif /* CFG_DRIVERS_CLK */ #endif /* __DRIVERS_CLK_H */ optee_os-4.3.0/core/include/drivers/clk_dt.h000066400000000000000000000066171464416617300210230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Bootlin */ #ifndef __DRIVERS_CLK_DT_H #define __DRIVERS_CLK_DT_H #include #include #include #include #include /** * CLK_DT_DECLARE() - Declare a clock driver * @__name: Clock driver name * @__compat: Compatible string * @__probe: Clock probe function */ #define CLK_DT_DECLARE(__name, __compat, __probe) \ static const struct dt_device_match __name ## _match_table[] = { \ { .compatible = __compat }, \ { } \ }; \ DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ .name = # __name, \ .type = DT_DRIVER_CLK, \ .match_table = __name ## _match_table, \ .probe = __probe, \ } /** * clk_dt_get_by_index() - Get a clock at a specific index in "clocks" property * * @fdt: Device tree to work on * @nodeoffset: Node offset of the subnode containing a clock property * @clk_idx: Clock index to get * @clk: Output clock reference upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not provide a clock reference * Return any other TEE_Result compliant code in case of error */ TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset, unsigned int clk_idx, struct clk **clk); /** * clk_dt_get_by_name() - Get a clock matching a name in "clock-names" property * * @fdt: Device tree to work on * @nodeoffset: Node offset of the subnode containing a clock property * @name: Clock name to get * @clk: Output clock reference upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if clock is not initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not provide a clock reference * Return any other TEE_Result compliant code in case of error */ TEE_Result clk_dt_get_by_name(const void *fdt, int nodeoffset, const char *name, struct clk **clk); /** * clk_dt_get_func - Typedef of function to get clock from devicetree properties * * @args: Pointer to devicetree description of the clock to parse * @data: Pointer to data given at clk_dt_register_clk_provider() call * @clk: Output clock reference upon success */ typedef TEE_Result (*clk_dt_get_func)(struct dt_pargs *args, void *data, struct clk **out_clk); /** * clk_dt_register_clk_provider() - Register a clock provider * * @fdt: Device tree to work on * @nodeoffset: Node offset of the clock * @func: Callback to match the devicetree clock with a clock struct * @data: Data which will be passed to the get_dt_clk callback * Returns TEE_Result value */ static inline TEE_Result clk_dt_register_clk_provider(const void *fdt, int nodeoffset, clk_dt_get_func func, void *data) { return dt_driver_register_provider(fdt, nodeoffset, (get_of_device_func)func, data, DT_DRIVER_CLK); } /** * clk_dt_get_simple_clk() - Simple clock matching function for single clock * providers * * @args: Unused argument as there is no description to parse * @data: Pointer to data given at clk_dt_register_clk_provider() call * @out_clk: Output clock reference filled with @data */ static inline TEE_Result clk_dt_get_simple_clk(struct dt_pargs *args __unused, void *data, struct clk **out_clk) { *out_clk = data; return TEE_SUCCESS; } #endif /* __DRIVERS_CLK_DT_H */ optee_os-4.3.0/core/include/drivers/ffa_console.h000066400000000000000000000005321464416617300220270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024, NVIDIA CORPORATION */ #ifndef FFA_CONSOLE_H #define FFA_CONSOLE_H #ifdef CFG_FFA_CONSOLE /* * Initialize console which uses FFA_CONSOLE_LOG of hafnium. */ void ffa_console_init(void); #else static inline void ffa_console_init(void) { } #endif #endif /* FFA_CONSOLE_H */ optee_os-4.3.0/core/include/drivers/firewall.h000066400000000000000000000075031464416617300213630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2024, STMicroelectronics */ #ifndef __DRIVERS_FIREWALL_H #define __DRIVERS_FIREWALL_H #include #include #include #include #include #include #include struct firewall_controller_ops; /** * struct firewall_controller - Firewall controller supplying services * * @ops: Operation handlers * @name: Name of the firewall controller * @base: Base address of the firewall controller * @priv: Private data of the firewall controller */ struct firewall_controller { const struct firewall_controller_ops *ops; const char *name; struct io_pa_va *base; void *priv; }; /** * struct firewall_controller_ops - Firewall controller operation handlers * * @set_conf: Callback used to set given firewall configuration * @check_access: Callback used to check access for a consumer on a resource * against a firewall controller * @acquire_access: Callback used to acquire access for OP-TEE on a resource * against a firewall controller * @release_access: Callback used to release resources taken by a consumer when * the access was acquired with @acquire_access * @check_memory_access: Callback used to check access for a consumer to a * memory range covered by a firewall controller, for read and/or write accesses * @acquire_memory_access: Callback used to acquire access for OP-TEE to a * memory range covered by a firewall controller, for read and/or write accesses * @release_memory_access: Callback used to release resources taken by a * consumer when the memory access was acquired with @acquire_memory_access */ struct firewall_controller_ops { TEE_Result (*set_conf)(struct firewall_query *conf); TEE_Result (*check_access)(struct firewall_query *conf); TEE_Result (*acquire_access)(struct firewall_query *conf); void (*release_access)(struct firewall_query *conf); TEE_Result (*check_memory_access)(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write); TEE_Result (*acquire_memory_access)(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write); void (*release_memory_access)(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write); }; #ifdef CFG_DRIVERS_FIREWALL /** * firewall_dt_controller_register() - Register a firewall controller to the * firewall framework * @fdt: FDT to work on * @node: DT node of the controller * @ctrl: Firewall controller to register */ TEE_Result firewall_dt_controller_register(const void *fdt, int node, struct firewall_controller *ctrl); /** * firewall_dt_probe_bus() - Add bus device tree subnodes that are accessible by * OP-TEE to the driver probe list. This is used at boot time only, as a sanity * check between device tree and firewalls hardware configurations to prevent * undesired accesses when access to a device is not authorized. This function * tries to acquire access to every resource entries listed in the * access-controllers property of each of the subnodes. It panics if it fails * to do so. * * @fdt: FDT to work on * @node: Firewall controller node * @ctrl:Firewall controller which subnodes will be populated or not */ TEE_Result firewall_dt_probe_bus(const void *fdt, int node, struct firewall_controller *ctrl); #else /* CFG_DRIVERS_FIREWALL */ static inline TEE_Result firewall_dt_controller_register(const void *fdt __unused, int node __unused, struct firewall_controller *ctrl __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result firewall_dt_probe_bus(const void *fdt __unused, int node __unused, struct firewall_controller *ctrl __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /* CFG_DRIVERS_FIREWALL */ #endif /* __DRIVERS_FIREWALL_H */ optee_os-4.3.0/core/include/drivers/firewall_device.h000066400000000000000000000152141464416617300227000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2024, STMicroelectronics */ #ifndef __DRIVERS_FIREWALL_DEVICE_H #define __DRIVERS_FIREWALL_DEVICE_H #include #include #include #include /* Opaque reference to firewall_controller */ struct firewall_controller; /** * struct firewall_query - Information on a device's firewall. * * @ctrl: Pointer referencing a firewall controller of the device. It is opaque * so a device cannot manipulate the controller's ops or access the controller's * data * @args: Firewall arguments that are implementation dependent * @arg_count: Number of arguments */ struct firewall_query { struct firewall_controller *ctrl; uint32_t *args; size_t arg_count; }; #ifdef CFG_DRIVERS_FIREWALL /** * firewall_dt_get_by_index() - Get the firewall configuration associated to a * given index for a device node. * * @fdt: FDT to work on * @node: Device node to read from * @index: Index of the entry in the property * @out_fw: Firewall query reference * * Returns TEE_SUCCESS on success, TEE_ERROR_ITEM_NOT_FOUND if there's no match * with a firewall controller or appropriate TEE_Result error code if an * error occurred. */ TEE_Result firewall_dt_get_by_index(const void *fdt, int node, unsigned int index, struct firewall_query **out_fw); /** * firewall_dt_get_by_name() - Get the firewall configuration associated to a * given name for a device node. * * @fdt: FDT to work on * @node: Device node to read from * @name: Name of the firewall configuration to search for * @out_fw: Firewall query reference * * Returns TEE_SUCCESS on success, TEE_ERROR_ITEM_NOT_FOUND if there's no match * with a firewall controller or appropriate TEE_Result error code if an * error occurred. */ TEE_Result firewall_dt_get_by_name(const void *fdt, int node, const char *name, struct firewall_query **out_fw); /** * firewall_set_configuration() - Reconfigure the firewall controller associated * to the given firewall configuration with it. * * @fw: Firewall query containing the configuration to set */ TEE_Result firewall_set_configuration(struct firewall_query *fw); /** * firewall_check_access() - Check if the access is authorized for a consumer * and the given firewall configuration according to the settings of its * firewall controller * * @fw: Firewall query containing the configuration to check against its * firewall controller */ TEE_Result firewall_check_access(struct firewall_query *fw); /** * firewall_acquire_access() - Check if OP-TEE can access the consumer and * acquire potential resources to allow the access * * @fw: Firewall query containing the configuration to check against its * firewall controller */ TEE_Result firewall_acquire_access(struct firewall_query *fw); /** * firewall_check_memory_access() - Check if a consumer can access the memory * address range, in read and/or write mode and given the firewall * configuration, against a firewall controller * * @fw: Firewall query containing the configuration to check against its * firewall controller * @paddr: Physical base address of the memory range to check * @size: Size of the memory range to check * @read: If true, check rights for a read access * @write: If true, check rights for a write access */ TEE_Result firewall_check_memory_access(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write); /** * firewall_acquire_memory_access() - Request OP-TEE access, in read and/or * write mode, to the given memory address range against a firewall controller * and acquire potential resources to allow the access * * @fw: Firewall query containing the configuration to check against its * firewall controller * @paddr: Physical base address of the memory range to check * @size: Size of the memory range to check * @read: Check rights for a read access * @write: Check rights for a write access */ TEE_Result firewall_acquire_memory_access(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write); /** * firewall_release_access() - Release resources obtained by a call to * firewall_acquire_access() * * @fw: Firewall query containing the configuration to release */ void firewall_release_access(struct firewall_query *fw); /** * firewall_release_memory_access() - Release resources obtained by a call to * firewall_acquire_memory_access() * * @fw: Firewall configuration to release * @paddr: Physical base address of the memory range to release * @size: Size of the memory range to release * @read: Release rights for read accesses * @write: Release rights for write accesses */ void firewall_release_memory_access(struct firewall_query *fw, paddr_t paddr, size_t size, bool read, bool write); /** * firewall_put() - Release a firewall_query structure allocated by * firewall_dt_get_by_index() or firewall_dt_get_by_name() * * @fw: Firewall query to put */ void firewall_put(struct firewall_query *fw); #else /* CFG_DRIVERS_FIREWALL */ static inline TEE_Result firewall_dt_get_by_index(const void *fdt __unused, int node __unused, unsigned int index __unused, struct firewall_query **out_fw __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result firewall_dt_get_by_name(const void *fdt __unused, int node __unused, const char *name __unused, struct firewall_query **out_fw __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result firewall_check_access(struct firewall_query *fw __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result firewall_acquire_access(struct firewall_query *fw __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result firewall_check_memory_access(struct firewall_query *fw __unused, paddr_t paddr __unused, size_t size __unused, bool read __unused, bool write __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result firewall_acquire_memory_access(struct firewall_query *fw __unused, paddr_t paddr __unused, size_t size __unused, bool read __unused, bool write __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline void firewall_release_access(struct firewall_query *fw __unused) { } static inline void firewall_release_memory_access(struct firewall_query *fw __unused, paddr_t paddr __unused, size_t size __unused, bool read __unused, bool write __unused) { } static inline TEE_Result firewall_set_configuration(struct firewall_query *fw __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline void firewall_put(struct firewall_query *fw __unused) { } #endif /* CFG_DRIVERS_FIREWALL */ #endif /* __DRIVERS_FIREWALL_DEVICE_H */ optee_os-4.3.0/core/include/drivers/gic.h000066400000000000000000000031431464416617300203140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __DRIVERS_GIC_H #define __DRIVERS_GIC_H #include #include #if defined(CFG_ARM_GICV3) #define GIC_DIST_REG_SIZE 0x10000 #define GIC_CPU_REG_SIZE 0x10000 #else #define GIC_DIST_REG_SIZE 0x1000 #define GIC_CPU_REG_SIZE 0x1000 #endif #define GIC_PPI_BASE U(16) #define GIC_SPI_BASE U(32) #define GIC_SGI_TO_ITNUM(x) (x) #define GIC_PPI_TO_ITNUM(x) ((x) + GIC_PPI_BASE) #define GIC_SPI_TO_ITNUM(x) ((x) + GIC_SPI_BASE) /* * Default lowest ID for secure SGIs, note that this does not account for * interrupts donated to non-secure world with gic_init_donate_sgi_to_ns(). */ #define GIC_SGI_SEC_BASE 8 /* Max ID for secure SGIs */ #define GIC_SGI_SEC_MAX 15 /* * The two gic_init() and gic_init_v3() functions initializes the struct * gic_data which is then used by the other functions. These two functions * also initializes the GIC and are only supposed to be called from the * primary boot CPU. */ void gic_init_v3(paddr_t gicc_base_pa, paddr_t gicd_base_pa, paddr_t gicr_base_pa); static inline void gic_init(paddr_t gicc_base_pa, paddr_t gicd_base_pa) { gic_init_v3(gicc_base_pa, gicd_base_pa, 0); } /* Donates one of the secure SGIs to normal world */ void gic_init_donate_sgi_to_ns(size_t it); /* * Does per-CPU specific GIC initialization, should be called by all * secondary CPUs when booting. */ void gic_init_per_cpu(void); /* Print GIC state to console */ void gic_dump_state(void); #endif /*__DRIVERS_GIC_H*/ optee_os-4.3.0/core/include/drivers/gpio.h000066400000000000000000000145071464416617300205160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __DRIVERS_GPIO_H #define __DRIVERS_GPIO_H #include #include #include #include #include /** * GPIO_DT_DECLARE - Declare a GPIO controller driver with a single * device tree compatible string. * * @__name: GPIO controller driver name * @__compat: Compatible string * @__probe: GPIO controller probe function */ #define GPIO_DT_DECLARE(__name, __compat, __probe) \ static const struct dt_device_match __name ## _match_table[] = { \ { .compatible = __compat }, \ { } \ }; \ DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ .name = # __name, \ .type = DT_DRIVER_GPIO, \ .match_table = __name ## _match_table, \ .probe = __probe, \ } enum gpio_dir { GPIO_DIR_OUT, GPIO_DIR_IN }; enum gpio_level { GPIO_LEVEL_LOW, GPIO_LEVEL_HIGH }; enum gpio_interrupt { GPIO_INTERRUPT_DISABLE, GPIO_INTERRUPT_ENABLE }; struct gpio; struct gpio_ops; struct gpio_chip { const struct gpio_ops *ops; }; struct gpio_ops { /* Get GPIO direction current configuration */ enum gpio_dir (*get_direction)(struct gpio_chip *chip, unsigned int gpio_pin); /* Set GPIO direction configuration */ void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_dir direction); /* Get GPIO current level */ enum gpio_level (*get_value)(struct gpio_chip *chip, unsigned int gpio_pin); /* Set GPIO level */ void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_level value); /* Get GPIO interrupt state */ enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin); /* Enable or disable a GPIO interrupt */ void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_interrupt enable_disable); /* Release GPIO resources */ void (*put)(struct gpio_chip *chip, struct gpio *gpio); }; /* * struct gpio - GPIO pin description * @chip: GPIO controller chip reference * @dt_flags: Pin boolean properties set from DT node * @pin: Pin number in GPIO controller */ struct gpio { struct gpio_chip *chip; uint32_t dt_flags; unsigned int pin; }; static inline bool gpio_ops_is_valid(const struct gpio_ops *ops) { return ops->set_direction && ops->get_direction && ops->get_value && ops->set_value; } static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir) { gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir); } static inline enum gpio_dir gpio_get_direction(struct gpio *gpio) { return gpio->chip->ops->get_direction(gpio->chip, gpio->pin); } static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value) { if (gpio->dt_flags & GPIO_ACTIVE_LOW) value = !value; gpio->chip->ops->set_value(gpio->chip, gpio->pin, value); } static inline enum gpio_level gpio_get_value(struct gpio *gpio) { enum gpio_level value = GPIO_LEVEL_LOW; value = gpio->chip->ops->get_value(gpio->chip, gpio->pin); if (gpio->dt_flags & GPIO_ACTIVE_LOW) value = !value; return value; } static inline void gpio_put(struct gpio *gpio) { assert(!gpio || (gpio->chip && gpio->chip->ops)); if (gpio && gpio->chip->ops->put) gpio->chip->ops->put(gpio->chip, gpio); } #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO) /** * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle * * @pargs: Pointer to devicetree description of the GPIO controller to parse * @res: Output result code of the operation: * TEE_SUCCESS in case of success * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized * Any TEE_Result compliant code in case of error. * * Returns a struct gpio pointer pointing to a GPIO instance matching * the devicetree description or NULL if invalid description in which case * @res provides the error code. */ TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio); /** * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in * 'gpios' property * * @fdt: Device tree to work on * @nodeoffset: Node offset of the subnode containing a 'gpios' property * @index: GPIO pin index in '*-gpios' property * @gpio_name: Name of the GPIO pin * @gpio: Output GPIO pin reference upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized * Return a TEE_Result compliant code in case of error */ TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, unsigned int index, const char *gpio_name, struct gpio **gpio); #else static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused, int nodeoffset __unused, unsigned int index __unused, const char *gpio_name __unused, struct gpio **gpio __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused, struct gpio **gpio __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /*CFG_DT*/ /** * gpio_dt_get_func - Typedef of function to get GPIO instance from * devicetree properties * * @pargs: Pointer to GPIO phandle and its argument in the FDT * @data: Pointer to the data given at gpio_dt_register_provider() call * @res: Output result code of the operation: * TEE_SUCCESS in case of success * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized * Any TEE_Result compliant code in case of error. * * Returns a struct GPIO pointer pointing to a GPIO instance matching * the devicetree description or NULL if invalid description in which case * @res provides the error code. */ typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data, struct gpio **out_gpio); /** * gpio_dt_register_provider() - Register a GPIO controller provider * * @fdt: Device tree to work on * @nodeoffset: Node offset of the GPIO controller * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio * @data: Opaque reference which will be passed to the get_dt_gpio callback * Returns TEE_Result value */ static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset, gpio_dt_get_func get_dt_gpio, void *data) { return dt_driver_register_provider(fdt, nodeoffset, (get_of_device_func)get_dt_gpio, data, DT_DRIVER_GPIO); } #endif /* __DRIVERS_GPIO_H */ optee_os-4.3.0/core/include/drivers/hfic.h000066400000000000000000000003001464416617300204530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Linaro Limited */ #ifndef __DRIVERS_HFIC_H #define __DRIVERS_HFIC_H void hfic_init(void); #endif /*__DRIVERS_HFIC_H*/ optee_os-4.3.0/core/include/drivers/hi16xx_uart.h000066400000000000000000000010431464416617300217310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ /* * UART driver for Hisilicon Hi16xx and Phosphor V660 (hip05) SoCs */ #ifndef __DRIVERS_HI16XX_UART_H #define __DRIVERS_HI16XX_UART_H #include #include #define HI16XX_UART_REG_SIZE 0xF8 struct hi16xx_uart_data { struct io_pa_va base; struct serial_chip chip; }; void hi16xx_uart_init(struct hi16xx_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); #endif /* __DRIVERS_HI16XX_UART_H */ optee_os-4.3.0/core/include/drivers/i2c.h000066400000000000000000000225571464416617300202410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Microchip */ #ifndef __DRIVERS_I2C_H #define __DRIVERS_I2C_H #include #include #include /** * DEFINE_I2C_DEV_DRIVER - Declare an I2C driver * * @__name: I2C device driver name * @__match_table: match table associated to the driver * @__i2c_probe: I2C probe function with the following prototype: * TEE_Result (*probe)(struct i2c_dev *i2c_dev, const void *fdt, * int node, const void *compat_data); */ #define DEFINE_I2C_DEV_DRIVER(__name, __match_table, __i2c_probe) \ static TEE_Result __name ## _probe_i2c_dev(const void *fdt, int node, \ const void *compat_data) \ { \ struct i2c_dev *i2c_dev = NULL; \ TEE_Result res = TEE_ERROR_GENERIC; \ \ res = i2c_dt_get_dev(fdt, node, &i2c_dev); \ if (res) \ return res; \ return __i2c_probe(i2c_dev, fdt, node, compat_data); \ } \ DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ .name = # __name, \ .type = DT_DRIVER_I2C, \ .match_table = __match_table, \ .probe = __name ## _probe_i2c_dev, \ } #define I2C_SMBUS_MAX_BUF_SIZE 32 enum i2c_smbus_dir { I2C_SMBUS_READ, I2C_SMBUS_WRITE, }; enum i2c_smbus_protocol { I2C_SMBUS_PROTO_BYTE, /* * Like block but does not insert "count" in sent data, useful for * EEPROM read for instance which is not SMBus but requires such * sequence. */ I2C_SMBUS_PROTO_BLOCK_RAW, }; struct i2c_ctrl; /** * struct i2c_dev - I2C device * * @ctrl: I2C controller associated to the device * @addr: device address on the I2C bus */ struct i2c_dev { struct i2c_ctrl *ctrl; uint16_t addr; }; /** * struct i2c_ctrl_ops - Operations provided by I2C controller drivers * * @read: I2C read operation * @write: I2C write operation * @smbus: SMBus protocol operation */ struct i2c_ctrl_ops { TEE_Result (*read)(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len); TEE_Result (*write)(struct i2c_dev *i2c_dev, const uint8_t *buf, size_t len); TEE_Result (*smbus)(struct i2c_dev *i2c_dev, enum i2c_smbus_dir dir, enum i2c_smbus_protocol proto, uint8_t cmd_code, uint8_t *buf, size_t len); }; /** * struct i2c_ctrl - I2C controller * * @ops: Operations associated to the I2C controller */ struct i2c_ctrl { const struct i2c_ctrl_ops *ops; }; #ifdef CFG_DRIVERS_I2C /** * i2c_create_dev - Create and i2c_dev struct from device-tree * * @i2c_ctrl: Controller to be used with this device * @fdt: Device-tree to work on * @node: Node to work on in @fdt provided device-tree * * Return an i2c_dev struct filled from device-tree description */ struct i2c_dev *i2c_create_dev(struct i2c_ctrl *i2c_ctrl, const void *fdt, int node); /** * i2c_write() - Execute an I2C write on the I2C bus * * @i2c_dev: I2C device used for writing * @buf: Buffer of data to be written * @len: Length of data to be written * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev, const uint8_t *buf, size_t len) { if (!i2c_dev->ctrl->ops->write) return TEE_ERROR_NOT_SUPPORTED; return i2c_dev->ctrl->ops->write(i2c_dev, buf, len); } /** * i2c_read() - Execute an I2C read on the I2C bus * * @i2c_dev: I2C device used for reading * @buf: Buffer containing the read data * @len: Length of data to be read * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len) { if (!i2c_dev->ctrl->ops->read) return TEE_ERROR_NOT_SUPPORTED; return i2c_dev->ctrl->ops->read(i2c_dev, buf, len); } /** * i2c_smbus_raw() - Execute a raw SMBUS request * * @i2c_dev: I2C device used for SMBus operation * @dir: Direction for the SMBus transfer * @proto: SMBus Protocol to be executed * @cmd_code: Command code * @buf: Buffer used for read/write operation * @len: Length of buffer to be read/write * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev, enum i2c_smbus_dir dir, enum i2c_smbus_protocol proto, uint8_t cmd_code, uint8_t *buf, size_t len) { if (!i2c_dev->ctrl->ops->smbus) return TEE_ERROR_NOT_SUPPORTED; if (len > I2C_SMBUS_MAX_BUF_SIZE) return TEE_ERROR_BAD_PARAMETERS; return i2c_dev->ctrl->ops->smbus(i2c_dev, dir, proto, cmd_code, buf, len); } /** * i2c_dt_get_dev - Get an I2C device from a DT node * * @fdt: Device tree to work on * @nodeoffset: Node offset of the I2C bus consumer * @i2c_dev: Output I2C bus device upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if I2C controller is not initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the I2C controller node does not exist * Return a TEE_Result compliant code in case of error */ static inline TEE_Result i2c_dt_get_dev(const void *fdt, int nodeoffset, struct i2c_dev **out_i2c_dev) { TEE_Result res = TEE_ERROR_GENERIC; void *i2c_dev = NULL; res = dt_driver_device_from_parent(fdt, nodeoffset, DT_DRIVER_I2C, &i2c_dev); if (!res) *out_i2c_dev = i2c_dev; return res; } #else static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev __unused, const uint8_t *buf __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev __unused, uint8_t *buf __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev __unused, enum i2c_smbus_dir dir __unused, enum i2c_smbus_protocol proto __unused, uint8_t cmd_code __unused, uint8_t *buf __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result i2c_dt_get_dev(const void *fdt __unused, int nodeoffset __unused, struct i2c_dev **i2c_dev __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /** * i2c_dt_get_func - Typedef of function to get I2C bus device from * devicetree properties * * @args: Pointer to devicetree description of the I2C bus device to parse * @data: Pointer to data given at i2c_dt_register_provider() call * @out_device: Output pointer to I2C device upon success */ typedef TEE_Result (*i2c_dt_get_func)(struct dt_pargs *args, void *data, struct i2c_dev **out_device); /** * i2c_dt_register_provider - Register a I2C controller provider and add all the * child nodes of this controller in the DT probe list. * * @fdt: Device tree to work on * @nodeoffset: Node offset of the I2C controller * @get_dt_i2c: Callback to match the I2C controller with a struct i2c * @data: Data which will be passed to the get_dt_i2c callback * Returns TEE_Result value */ static inline TEE_Result i2c_register_provider(const void *fdt, int nodeoffset, i2c_dt_get_func get_dt_i2c, void *data) { int subnode = -1; TEE_Result res = TEE_ERROR_GENERIC; res = dt_driver_register_provider(fdt, nodeoffset, (get_of_device_func)get_dt_i2c, data, DT_DRIVER_I2C); if (res) return res; fdt_for_each_subnode(subnode, fdt, nodeoffset) dt_driver_maybe_add_probe_node(fdt, subnode); return TEE_SUCCESS; } /** * i2c_smbus_read_byte_data() - Execute a read byte SMBus protocol operation * * @i2c_dev: I2C device used for SMBus operation * @cmd_code: Command code to read * @byte: Returned byte value read from device * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_smbus_read_byte_data(struct i2c_dev *i2c_dev, uint8_t cmd_code, uint8_t *byte) { return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BYTE, cmd_code, byte, 1); } /** * i2c_smbus_write_byte_data() - Execute a write byte SMBus protocol operation * * @i2c_dev: I2C device used for SMBus operation * @cmd_code: Command code for write operation * @byte: Byte to be written to the device * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_smbus_write_byte_data(struct i2c_dev *i2c_dev, uint8_t cmd_code, uint8_t byte) { return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, I2C_SMBUS_PROTO_BYTE, cmd_code, &byte, 1); } /** * i2c_bus_read_block_raw() - Execute a non-standard SMBus raw block read. * This does not insert the "count" of byte to be written unlike the SMBus block * read operation. * * @i2c_dev: I2C device used for SMBus operation * @cmd_code: Command code for read operation * @buf: Buffer of data read from device * @len: Length of data to be read from the device * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_bus_read_block_raw(struct i2c_dev *i2c_dev, uint8_t cmd_code, uint8_t *buf, size_t len) { return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BLOCK_RAW, cmd_code, buf, len); } /** * i2c_bus_write_block_raw() - Execute a non-standard SMBus raw block write. * This does not insert the "count" of byte to be written unlike the SMBus block * write operation. * * @i2c_dev: I2C device used for SMBus operation * @cmd_code: Command code for write operation * @buf: Buffer of data to be written to the device * @len: Length of data to be written to the device * * Return a TEE_Result compliant value */ static inline TEE_Result i2c_bus_write_block_raw(struct i2c_dev *i2c_dev, uint8_t cmd_code, uint8_t *buf, size_t len) { return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, I2C_SMBUS_PROTO_BLOCK_RAW, cmd_code, buf, len); } #endif optee_os-4.3.0/core/include/drivers/imx/000077500000000000000000000000001464416617300201755ustar00rootroot00000000000000optee_os-4.3.0/core/include/drivers/imx/dcp.h000066400000000000000000000076711464416617300211270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020 NXP */ #ifndef __DRIVERS_IMX_DCP_H #define __DRIVERS_IMX_DCP_H #include #include #include #include #define DCP_SHA_BLOCK_SIZE U(64) #define DCP_AES128_BLOCK_SIZE U(16) #define DCP_AES128_KEY_SIZE DCP_AES128_BLOCK_SIZE #define DCP_AES128_IV_SIZE DCP_AES128_BLOCK_SIZE enum dcp_key_mode { DCP_SRAM0 = 0, DCP_SRAM1, DCP_SRAM2, DCP_SRAM3, DCP_PAYLOAD, DCP_OTP, }; enum dcp_aes_mode { DCP_ECB = 0, DCP_CBC, }; enum dcp_aes_op { DCP_ENCRYPT = 0, DCP_DECRYPT, }; enum dcp_hash_config { DCP_SHA1 = 0, DCP_SHA256, }; enum dcp_channel { DCP_CHANN0 = 0, DCP_CHANN1, DCP_CHANN2, DCP_CHANN3, DCP_NB_CHANNELS, }; /* DCP work packet descriptor is a hardware data structure */ struct dcp_descriptor { uint32_t next; uint32_t ctrl0; uint32_t ctrl1; /* Source buffer physical address */ uint32_t src_buffer; /* Destination buffer physical address */ uint32_t dest_buffer; uint32_t buff_size; /* Payload buffer physical address */ uint32_t payload; uint32_t status; }; struct dcp_align_buf { uint8_t *data; paddr_t paddr; size_t size; }; struct dcp_data { struct dcp_descriptor desc; enum dcp_channel channel; }; struct dcp_hash_data { struct dcp_data dcp_data; bool initialized; enum dcp_hash_config alg; struct dcp_align_buf ctx; size_t ctx_size; }; struct dcp_hashalg { unsigned int type; unsigned int size; }; struct dcp_cipher_data { struct dcp_data dcp_data; bool initialized; uint8_t iv[DCP_AES128_IV_SIZE]; uint8_t key[DCP_AES128_KEY_SIZE]; /* payload buffer holds the key and the iv */ struct dcp_align_buf payload; size_t payload_size; }; struct dcp_cipher_init { enum dcp_aes_op op; enum dcp_aes_mode mode; enum dcp_key_mode key_mode; uint8_t *key; uint8_t *iv; }; /* * Perform AES-CMAC operation * * @init Cipher operation context * @input Input message * @input_size Input message size * @output Output MAC */ TEE_Result dcp_cmac(struct dcp_cipher_init *init, uint8_t *input, size_t input_size, uint8_t *output); /* * Store key in the SRAM * * @key Buffer containing the key to store (128 bit) * @index Index of the key (0, 1, 2 or 3) */ TEE_Result dcp_store_key(uint32_t *key, unsigned int index); /* * Initialize AES-128 operation * * @data Cipher operation context * @init Data for aesdata initialization */ TEE_Result dcp_cipher_do_init(struct dcp_cipher_data *data, struct dcp_cipher_init *init); /* * Update AES-128 operation * * @data Cipher operation context * @src Source data to encrypt/decrypt * @dst [out] Destination buffer * @size Size of source data in bytes, must be 16 bytes multiple */ TEE_Result dcp_cipher_do_update(struct dcp_cipher_data *data, const uint8_t *src, uint8_t *dst, size_t size); /* * Finalize AES-128 operation * * @data Cipher operation context */ void dcp_cipher_do_final(struct dcp_cipher_data *data); /* * Initialize hash operation * * @hashdata Hash operation context */ TEE_Result dcp_sha_do_init(struct dcp_hash_data *hashdata); /* * Update hash operation * * @hashdata Hash operation context * @data Buffer to hash * @len Size of the input buffer in bytes */ TEE_Result dcp_sha_do_update(struct dcp_hash_data *hashdata, const uint8_t *data, size_t len); /* * Finalize the hash operation * * @hashdata Hash operation context * @digest [out] Result of the hash operation * @digest_size Digest buffer size in bytes */ TEE_Result dcp_sha_do_final(struct dcp_hash_data *hashdata, uint8_t *digest, size_t digest_size); /* * Disable the use of the DCP unique key (0xFE in the DCP key-select field). */ void dcp_disable_unique_key(void); /* Initialize DCP */ TEE_Result dcp_init(void); #ifndef CFG_DT static inline TEE_Result dcp_vbase(vaddr_t *base __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* CFG_DT */ #endif /* __DRIVERS_IMX_DCP_H */ optee_os-4.3.0/core/include/drivers/imx_i2c.h000066400000000000000000000010041464416617300210760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2020 Foundries.io * Jorge Ramirez-Ortiz */ #ifndef __DRIVERS_IMX_I2C_H #define __DRIVERS_IMX_I2C_H #include #include TEE_Result imx_i2c_write(uint8_t bid, uint8_t chip, const uint8_t *p, int l); TEE_Result imx_i2c_read(uint8_t bid, uint8_t chip, uint8_t *p, int l); TEE_Result imx_i2c_probe(uint8_t bid, uint8_t chip); TEE_Result imx_i2c_init(uint8_t bid, int bps); #endif /*__DRIVERS_IMX_I2C_H*/ optee_os-4.3.0/core/include/drivers/imx_mu.h000066400000000000000000000031461464416617300210530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2020-2022 NXP */ #ifndef __DRIVERS_IMX_MU_H #define __DRIVERS_IMX_MU_H #include #include #include #define IMX_MU_DATA_U32(mesg, idx) ((mesg)->data.u32[(idx)]) #define IMX_MU_DATA_U16(mesg, idx) ((mesg)->data.u16[(idx)]) #define IMX_MU_DATA_U8(mesg, idx) ((mesg)->data.u8[(idx)]) #define IMX_MU_MSG_SIZE 17 #define IMX_MU_NB_CHANNEL 4 #if defined(CFG_MX8ULP) || defined(CFG_MX93) struct imx_mu_msg_header { uint8_t version; uint8_t size; uint8_t command; uint8_t tag; }; #elif defined(CFG_MX8QM) || defined(CFG_MX8QX) || defined(CFG_MX8DXL) struct imx_mu_msg_header { uint8_t version; uint8_t size; uint8_t tag; uint8_t command; }; #else #error "Platform not supported" #endif /* * i.MX MU message format * Note: the header format differs depending of the platform. */ struct imx_mu_msg { struct imx_mu_msg_header header; union { uint32_t u32[IMX_MU_MSG_SIZE]; uint16_t u16[IMX_MU_MSG_SIZE * 2]; uint8_t u8[IMX_MU_MSG_SIZE * 4]; } data; }; /* * Initialize the MU interface * * @base: virtual base address of the MU controller */ void imx_mu_init(vaddr_t base); /* * Initiate a communication with the external controller. It sends a message * and return the answer of the controller. * * @base: virtual base address of the MU controller * @[in/out]msg: message sent and received * @wait_for_answer: true if an answer from the controller is expected, false * otherwise */ TEE_Result imx_mu_call(vaddr_t base, struct imx_mu_msg *msg, bool wait_for_answer); #endif /* __DRIVERS_IMX_MU_H */ optee_os-4.3.0/core/include/drivers/imx_ocotp.h000066400000000000000000000007471464416617300215620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP */ #ifndef __DRIVERS_IMX_OCOTP_H #define __DRIVERS_IMX_OCOTP_H #include /* The i.MX UID is 64 bits long */ #define IMX_UID_SIZE sizeof(uint64_t) /* * Read OCOTP shadow register * * @bank Fuse bank number * @word Fuse word number * @[out]val Shadow register value */ TEE_Result imx_ocotp_read(unsigned int bank, unsigned int word, uint32_t *val); #endif /* __DRIVERS_IMX_OCOTP_H */ optee_os-4.3.0/core/include/drivers/imx_sc_api.h000066400000000000000000000015701464416617300216670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * Copyright 2017-2021 NXP */ #ifndef __DRIVERS_IMX_SC_API_H #define __DRIVERS_IMX_SC_API_H #include /* * Initializes the Secure Controller */ TEE_Result imx_sc_driver_init(void); /* * Enables a CAAM Job Ring for the secure world with the following steps: * - Assign CAAM JR resources to secure world * - Power ON CAAM JR resources * * @jr_index Index of the CAAM Job Ring to enable */ TEE_Result imx_sc_rm_enable_jr(unsigned int jr_index); /* * Starts the random number generator and returns the RNG status. * * Note that the RNG is started automatically after all CPUs are booted. This * function can then be used to start the RNG earlier or to check the RNG * status. */ TEE_Result imx_sc_seco_start_rng(void); #endif /* __DRIVERS_IMX_SC_API_H */ optee_os-4.3.0/core/include/drivers/imx_snvs.h000066400000000000000000000012411464416617300214150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2020 Pengutronix * Rouven Czerwinski * Copyright 2022-2023 NXP */ #ifndef __DRIVERS_IMX_SNVS_H #define __DRIVERS_IMX_SNVS_H #include /* Set the OTPMK Key as Master key */ #ifdef CFG_IMX_SNVS TEE_Result imx_snvs_set_master_otpmk(void); bool snvs_is_device_closed(void); void imx_snvs_shutdown(void); #else static inline bool snvs_is_device_closed(void) { return false; } static inline TEE_Result imx_snvs_set_master_otpmk(void) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline void imx_snvs_shutdown(void) {} #endif #endif /* __DRIVERS_IMX_SNVS_H */ optee_os-4.3.0/core/include/drivers/imx_uart.h000066400000000000000000000033221464416617300214010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_IMX_UART_H #define __DRIVERS_IMX_UART_H #include #include struct imx_uart_data { struct io_pa_va base; struct serial_chip chip; }; void imx_uart_init(struct imx_uart_data *pd, paddr_t base); #endif /* __DRIVERS_IMX_UART_H */ optee_os-4.3.0/core/include/drivers/imx_wdog.h000066400000000000000000000043041464416617300213670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017-2019 NXP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_IMX_WDOG_H #define __DRIVERS_IMX_WDOG_H #include /* i.MX6/7D */ #define WDT_WCR 0x00 #define WDT_WCR_WDA BIT(5) #define WDT_WCR_SRS BIT(4) #define WDT_WCR_WRE BIT(3) #define WDT_WCR_WDE BIT(2) #define WDT_WCR_WDZST BIT(0) #define WDT_WSR 0x02 #define WDT_SEQ1 0x5555 #define WDT_SEQ2 0xAAAA /* 7ULP */ #define WDOG_CNT 0x4 #define WDOG_TOVAL 0x8 #define REFRESH_SEQ0 0xA602 #define REFRESH_SEQ1 0xB480 #define REFRESH ((REFRESH_SEQ1 << 16) | REFRESH_SEQ0) #define UNLOCK_SEQ0 0xC520 #define UNLOCK_SEQ1 0xD928 #define UNLOCK ((UNLOCK_SEQ1 << 16) | UNLOCK_SEQ0) #define WDOG_CS 0x0 #define WDOG_CS_CMD32EN BIT(13) #define WDOG_CS_ULK BIT(11) #define WDOG_CS_RCS BIT(10) #define WDOG_CS_EN BIT(7) #define WDOG_CS_UPDATE BIT(5) /* Exposed for psci reset */ void __noreturn imx_wdog_restart(bool external_reset); #endif optee_os-4.3.0/core/include/drivers/lpc_uart.h000066400000000000000000000027761464416617300213760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, HiSilicon Limited */ #ifndef __DRIVERS_LPC_UART_H #define __DRIVERS_LPC_UART_H #include #include #define UART_SEND_LOOP_MAX 1000000 #define UART_THR 0x00 #define UART_LSR 0x05 #define UART_USR_BUS 0x01 #define LPC_BASE 0x201190000 #define LPC_SIZE 0x1000000 #define LPC_START_REG_OFFSET (0x00) #define LPC_OP_STATUS_REG_OFFSET (0x04) #define LPC_IRQ_ST_REG_OFFSET (0x08) #define LPC_OP_LEN_REG_OFFSET (0x10) #define LPC_CMD_REG_OFFSET (0x14) #define LPC_FWH_ID_MSIZE_REG_OFFSET (0x18) #define LPC_ADDR_REG_OFFSET (0x20) #define LPC_WDATA_REG_OFFSET (0x24) #define LPC_RDATA_REG_OFFSET (0x28) #define LPC_LONG_CNT_REG_OFFSET (0x30) #define LPC_TX_FIFO_ST_REG_OFFSET (0x50) #define LPC_RX_FIFO_ST_REG_OFFSET (0x54) #define LPC_TIME_OUT_REG_OFFSET (0x58) #define LPC_SIRQ_CTRL0_REG_OFFSET (0x80) #define LPC_SIRQ_CTRL1_REG_OFFSET (0x84) #define LPC_SIRQ_INT_REG_OFFSET (0x90) #define LPC_SIRQ_INT_MASK_REG_OFFSET (0x94) #define LPC_SIRQ_STAT_REG_OFFSET (0xa0) #define LPC_SINGLE_READ (0x8) #define LPC_SINGLE_WRITE (0x9) #define LPC_IRQ_ST_ON (0x2) #define LPC_RADTA_LEN (0x40) struct lpc_uart_data { struct io_pa_va base; struct serial_chip chip; }; void lpc_uart_init(struct lpc_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); #endif /* __DRIVERS_LPC_UART_H */ optee_os-4.3.0/core/include/drivers/ls_dspi.h000066400000000000000000000050041464416617300212050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP * * Helper Code for DSPI Controller driver */ #ifndef __DRIVERS_LS_DSPI_H #define __DRIVERS_LS_DSPI_H #include #include /* Clock and transfer attributes */ #define DSPI_CTAR_BRD 0x80000000 /* Double Baud Rate [0] */ #define DSPI_CTAR_FMSZ(x) (((x) & 0x0F) << 27) /* Frame Size [1-4] */ #define DSPI_CTAR_CPOL 0x04000000 /* Clock Polarity [5] */ #define DSPI_CTAR_CPHA 0x02000000 /* Clock Phase [6] */ #define DSPI_CTAR_LSBFE 0x01000000 /* LSB First [7] */ #define DSPI_CTAR_PCS_SCK(x) (((x) & 0x03) << 22) /* PCSSCK [8-9] */ #define DSPI_CTAR_PA_SCK(x) (((x) & 0x03) << 20) /* PASC [10-11] */ #define DSPI_CTAR_P_DT(x) (((x) & 0x03) << 18) /* PDT [12-13] */ #define DSPI_CTAR_BRP(x) \ (((x) & 0x03) << 16) /* Baud Rate Prescaler [14-15] */ #define DSPI_CTAR_CS_SCK(x) (((x) & 0x0F) << 12) /* CSSCK [16-19] */ #define DSPI_CTAR_A_SCK(x) (((x) & 0x0F) << 8) /* ASC [20-23] */ #define DSPI_CTAR_A_DT(x) (((x) & 0x0F) << 4) /* DT [24-27] */ #define DSPI_CTAR_BR(x) ((x) & 0x0F) /* Baud Rate Scaler [28-31] */ /* SPI mode flags */ #define SPI_CPHA BIT(0) /* clock phase */ #define SPI_CPOL BIT(1) /* clock polarity */ #define SPI_CS_HIGH BIT(2) /* CS active high */ #define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */ #define SPI_CONT BIT(4) /* Continuous CS mode */ /* * struct ls_dspi_data describes DSPI controller chip instance * The structure contains below members: * chip: generic spi_chip instance * base: DSPI controller base address * bus_clk_hz: DSPI input clk frequency * speed_hz: Default SCK frequency=1mhz * num_chipselect: chip/slave selection * slave_bus: bus value of slave * slave_cs: chip slect value of slave * slave_speed_max_hz: max spped of slave * slave_mode: mode of slave * slave_data_size_bits:Data size to be transferred (8 or 16 bits) * ctar_val: value of Clock and Transfer Attributes Register (CTAR) * ctar_sel: CTAR0 or CTAR1 */ struct ls_dspi_data { struct spi_chip chip; vaddr_t base; unsigned int bus_clk_hz; unsigned int speed_hz; unsigned int num_chipselect; unsigned int slave_bus; unsigned int slave_cs; unsigned int slave_speed_max_hz; unsigned int slave_mode; unsigned int slave_data_size_bits; unsigned int ctar_val; unsigned int ctar_sel; }; /* * Initialize DSPI Controller * dspi_data: DSPI controller chip instance */ TEE_Result ls_dspi_init(struct ls_dspi_data *dspi_data); #endif /* __DRIVERS_LS_DSPI_H */ optee_os-4.3.0/core/include/drivers/ls_gpio.h000066400000000000000000000026461464416617300212150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP * * Helper Code for GPIO controller driver * */ #ifndef __DRIVERS_LS_GPIO_H #define __DRIVERS_LS_GPIO_H #include #include #include #include /* supported ports for GPIO controller */ #define MAX_GPIO_PINS U(31) /* map register values to LE by subtracting pin number from MAX GPIO PINS */ #define PIN_SHIFT(x) BIT(MAX_GPIO_PINS - (x)) /* gpio register offsets */ #define GPIODIR U(0x0) /* direction register */ #define GPIOODR U(0x4) /* open drain register */ #define GPIODAT U(0x8) /* data register */ #define GPIOIER U(0xc) /* interrupt event register */ #define GPIOIMR U(0x10) /* interrupt mask register */ #define GPIOICR U(0x14) /* interrupt control register */ #define GPIOIBE U(0x18) /* input buffer enable register */ /* * struct ls_gpio_chip_data describes GPIO controller chip instance * The structure contains below members: * chip: generic GPIO chip handle. * gpio_base: starting GPIO module base address managed by this GPIO * controller. * gpio_controller: GPIO controller to be used. */ struct ls_gpio_chip_data { struct gpio_chip chip; vaddr_t gpio_base; uint8_t gpio_controller; }; /* * Initialize GPIO Controller * gpio_data is a pointer of type 'struct ls_gpio_chip_data'. */ TEE_Result ls_gpio_init(struct ls_gpio_chip_data *gpio_data); #endif /* __DRIVERS_LS_GPIO_H */ optee_os-4.3.0/core/include/drivers/ls_i2c.h000066400000000000000000000126531464416617300207330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP * I2C driver for I2C Controller */ #ifndef __DRIVERS_LS_I2C_H #define __DRIVERS_LS_I2C_H #include #include #include /* * Module Disable * 0b - The module is enabled. You must clear this field before any other IBCR * fields have any effect. * 1b - The module is reset and disabled. This is the power-on reset situation. * When high, the interface is held in reset, but registers can still be * accessed. Status register fields (IBSR) are not valid when the module * is disabled. */ #define I2C_IBCR_MDIS U(0x80) /* I2c Bus Interrupt Enable */ #define I2C_IBCR_IBIE U(0x40) /* * Master / Slave Mode 0b - Slave mode 1b - Master mode * When you change this field from 0 to 1, the module generates a START signal * on the bus and selects the master mode. When you change this field from 1 to * 0, the module generates a STOP signal and changes the operation mode from * master to slave. You should generate a STOP signal only if IBSR[IBIF]=1. * The module clears this field without generating a STOP signal when the * master loses arbitration. */ #define I2C_IBCR_MSSL U(0x20) /* 0b - Receive 1b - Transmit */ #define I2C_IBCR_TXRX U(0x10) /* * Data acknowledge disable * Values written to this field are only used when the I2C module is a receiver, * not a transmitter. * 0b - The module sends an acknowledge signal to the bus at the 9th clock bit * after receiving one byte of data. * 1b - The module does not send an acknowledge-signal response (that is, * acknowledge bit = 1). */ #define I2C_IBCR_NOACK U(0x08) /* * Repeat START * If the I2C module is the current bus master, and you program RSTA=1, the I2C * module generates a repeated START condition. This field always reads as a 0. * If you attempt a repeated START at the wrong time, if the bus is owned by * another master the result is loss of arbitration. */ #define I2C_IBCR_RSTA U(0x04) /* DMA enable */ #define I2C_IBCR_DMAEN U(0x02) /* Transfer Complete */ #define I2C_IBSR_TCF U(0x80) /* I2C bus Busy. 0b - Bus is idle, 1b - Bus is busy */ #define I2C_IBSR_IBB U(0x20) /* Arbitration Lost. software must clear this field by writing a one to it. */ #define I2C_IBSR_IBAL U(0x10) /* I2C bus interrupt flag */ #define I2C_IBSR_IBIF U(0x02) /* * Received acknowledge * 0b - Acknowledge received * 1b - No acknowledge received */ #define I2C_IBSR_RXAK U(0x01) /* Bus idle interrupt enable */ #define I2C_IBIC_BIIE U(0x80) /* Glitch filter enable */ #define I2C_IBDBG_GLFLT_EN U(0x08) #define I2C_FLAG_WRITE U(0x00000000) #define I2C_FLAG_READ U(0x00000001) #define I2C_BUS_TEST_BUSY true #define I2C_BUS_TEST_IDLE !I2C_BUS_TEST_BUSY #define I2C_BUS_TEST_RX_ACK true #define I2C_BUS_NO_TEST_RX_ACK !I2C_BUS_TEST_RX_ACK #define I2C_NUM_RETRIES U(500) struct i2c_regs { uint8_t ibad; /* I2c Bus Address Register */ uint8_t ibfd; /* I2c Bus Frequency Divider Register */ uint8_t ibcr; /* I2c Bus Control Register */ uint8_t ibsr; /* I2c Bus Status Register */ uint8_t ibdr; /* I2C Bus Data I/O Register */ uint8_t ibic; /* I2C Bus Interrupt Config Register */ uint8_t ibdbg; /* I2C Bus Debug Register */ }; /* * sorted list of clock divisor, ibfd register value pairs */ struct i2c_clock_divisor_pair { uint16_t divisor; uint8_t ibfd; /* I2c Bus Frequency Divider Register value */ }; /* * I2C device operation * The i2c_operation describes a subset of an I2C transaction in which * the I2C controller is either sending or receiving bytes from the bus. * Some transactions will consist of a single operation while others will * be two or more. */ struct i2c_operation { /* Flags to qualify the I2C operation. */ uint32_t flags; /* * Number of bytes to send to or receive from the I2C device.A ping * is indicated by setting the length_in_bytes to zero. */ unsigned int length_in_bytes; /* * Pointer to a buffer containing the data to send or to receive from * the I2C device. The Buffer must be at least length_in_bytes in size. */ uint8_t *buffer; }; /* * Structure to initialize I2C controller. */ struct ls_i2c_data { /* I2C Controller to initialize */ uint8_t i2c_controller; /* * base will be filled by i2c_init() which will be used in * subsequent calls for reading/writing data. */ vaddr_t base; /* I2C bus clock frequency */ uint64_t i2c_bus_clock; /* I2C speed */ uint64_t speed; }; /* * Structure to fill for I2C read/write operation */ struct i2c_reg_request { /* * Number of operations to perform. * This will depend on peripheral for which it is used. */ unsigned int operation_count; /* Operation to perform */ struct i2c_operation *operation; }; /* * Initialize I2C Controller, based on data passed in * i2c_data. */ TEE_Result i2c_init(struct ls_i2c_data *i2c_data); /* * Software reset of the entire I2C module. * The module is reset and disabled. * Status register fields (IBSR) are cleared. * base Base Address of I2c controller's registers */ void i2c_reset(vaddr_t base); /* * Transfer data to/from I2c slave device * base Base Address of I2c controller's registers * slave_address Slave Address from which data is to be read * i2c_operation Pointer to an i2c_operation structure * operation_count Number of operations. */ TEE_Result i2c_bus_xfer(vaddr_t base, uint32_t slave_address, struct i2c_operation *i2c_operation, unsigned int operation_count); #endif /* __DRIVERS_LS_I2C_H */ optee_os-4.3.0/core/include/drivers/ls_sec_mon.h000066400000000000000000000042311464416617300216720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 Microsoft * * Definitions for the NXP LX2160A-series Security Monitor (SecMon) driver. */ #ifndef __DRIVERS_LS_SEC_MON_H #define __DRIVERS_LS_SEC_MON_H #include #include /** * struct ls_sec_mon_data - Compact data struct of all SecMon registers. * @hplr: HP Lock Register. * @hpcomr: HP Command Register. * @hpsicr: HP Security Interrupt Control Register. * @hpsvcr: HP Security Violation Control Register. * @hpsr: HP Status Register. * @hpsvsr: HP Security Violation Status Register. * @hphacivr: HP High Assurance Counter IV Register. * @hphacr: HP High Assurance Counter Register. * @lplr: LP Lock Register. * @lpcr: LP Control Register. * @lpmkcr: LP Master Key Control Register. * @lpsvcr: LP Security Violation Control Register. * @lptdcr: LP Tamper Detectors Configuration Register. * @lpsr: LP Status Register. * @lpsmcmr: LP Secure Monotonic Counter MSB Register. * @lpsmclr: LP Secure Monotonic Counter LSB Register. * @lppgdr: LP Power Glitch Detector Register. * @lpzmkr[8]: LP Zeroizable Master Key Registers. * @lpgpr[4]: LP General Purpose Registers. * @hpvidr1: HP Version ID Register 1. * @hpvidr2: HP Version ID Register 2. */ struct ls_sec_mon_data { uint32_t hplr; uint32_t hpcomr; uint32_t hpsicr; uint32_t hpsvcr; uint32_t hpsr; uint32_t hpsvsr; uint32_t hphacivr; uint32_t hphacr; uint32_t lplr; uint32_t lpcr; uint32_t lpmkcr; uint32_t lpsvcr; uint32_t lptdcr; uint32_t lpsr; uint32_t lpsmcmr; uint32_t lpsmclr; uint32_t lppgdr; uint32_t lpzmkr[8]; uint32_t lpgpr[4]; uint32_t hpvidr1; uint32_t hpvidr2; }; /** * ls_sec_mon_read() - Read a copy of the SecMon register data if the SecMon * driver was successfully initialized. * @data: Location to save SecMon data. * * Return: 0 if successful or > 0 on error. */ TEE_Result ls_sec_mon_read(struct ls_sec_mon_data *data); /** * ls_sec_mon_status() - Check if the SecMon driver was initialized * successfully. * * Return: 0 if init was successful or TEE_ERROR_GENERIC on init failed. */ TEE_Result ls_sec_mon_status(void); #endif /* __DRIVERS_LS_SEC_MON_H */ optee_os-4.3.0/core/include/drivers/ls_sfp.h000066400000000000000000000117431464416617300210450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 Microsoft * * Definitions for the NXP LX2160A-series Security Fuse Processor (SFP) driver. */ #ifndef __DRIVERS_LS_SFP_H #define __DRIVERS_LS_SFP_H #include #include #include /* SFP instruction register */ /* SFP is big endian */ #define SFP_INGR_PROGFB_CMD 0x2 #define SFP_INGR_ERROR_MASK 0x100 #define SFP_INGR_FUSE_TIMEOUT_US 150000 /* SFP configuration register */ #define SFP_SFPCR_SB_MASK 0x20000000 #define SFP_SFPCR_SB_OFFSET 29 /* SFP OEM security policy register 0 */ #define SFP_OSPR0_WP_MASK 0x1 #define SFP_OSPR0_ITS_MASK 0x4 #define SFP_OSPR0_ITS_OFFSET 0x2 /* SFP OEM security policy register 1 */ #define SFP_OSPR1_DBLEV_MASK 0x7 #define SFP_OSPR1_DBLEV_OPEN 0x0 #define SFP_OSPR1_DBLEV_CLOSED_NOTIFY 0x1 #define SFP_OSPR1_DBLEV_CLOSED_SILENT 0x2 #define SFP_OSPR1_DBLEV_CLOSED 0x4 /** * struct ls_sfp_data - Compact data struct of all SFP registers. * @ingr: Instruction Register. * @svhesr: Secret Value Hamming Error Status Register. * @sfpcr: SFP Configuration Register. * @version: SFP Version Register. * @ospr0: OEM Security Policy Register 0. * @ospr1: OEM Security Policy Register 1. * @dcvr0: Debug Challenge Value Register 0. * @dcvr1: Debug Challenge Value Register 1. * @drvr0: Debug Response Value Register 0. * @drvr1: Debug Response Value Register 1. * @fswpr: Factory Section Write Protect Register. * @fuidr0: Factory Unique ID Register 0. * @fuidr1: Factory Unique ID Register 1. * @isbccr: ISBC Configuration Register. * @fspfr[0x3]: Factory Scratch Pad Fuse Registers. * @otpmkr[0x8]: One Time Programmable Master Key. * @srkhr[0x8]: Super Root Key Hash Register. * @ouidr[0x5]: OEM Unique ID/Scratch Pad Fuse Registers. */ struct ls_sfp_data { uint32_t ingr; uint32_t svhesr; uint32_t sfpcr; uint32_t version; uint32_t ospr0; uint32_t ospr1; uint32_t dcvr0; uint32_t dcvr1; uint32_t drvr0; uint32_t drvr1; uint32_t fswpr; uint32_t fuidr0; uint32_t fuidr1; uint32_t isbccr; uint32_t fspfr[0x3]; uint32_t otpmkr[0x8]; uint32_t srkhr[0x8]; uint32_t ouidr[0x5]; }; /** * ls_sfp_read() - Read a copy of the SFP register data if the SFP driver was * successfully initialized. * @data: Location to save SFP data. * * Return: TEE_SUCCESS or > 0 on error */ TEE_Result ls_sfp_read(struct ls_sfp_data *data); /** * ls_sfp_get_debug_level() - Read the last 3 bits of the SFP OSPR1 register * which denotes the debug level. * @dblev: Pointer location to store the read debug level. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_get_debug_level(uint32_t *dblev); /** * ls_sfp_get_its() - Read bit 29 of the SFP OSPR0 register which denotes the * ITS flag. * @its: Pointer location to store the ITS flag. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_get_its(uint32_t *its); /** * ls_sfp_get_ouid() - Read the SFP OUID register at the given index. * @index: Index of the OUID register to read. * @ouid: Pointer location to store the OIUD register value. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_get_ouid(uint32_t index, uint32_t *ouid); /** * ls_sfp_get_sb() - Read bit 2 of the SFP SFPCR register which denotes the * secure boot flag. * @sb: Pointer location to store the secure boot flag. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_get_sb(uint32_t *sb); /** * ls_sfp_get_srkh() - Read the SFP SRKH register at the given index. * @index: Index of the SRKH register to read. * @srkh: Pointer location to store the SRKH register value. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_get_srkh(uint32_t index, uint32_t *srkh); /** * ls_sfp_set_debug_level() - Set the last 3 bits of the SFP OSPR1 register * which denotes the debug level. * @dblev: Value to write into the SFP OSPR1 register. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_set_debug_level(uint32_t dblev); /** * ls_sfp_set_its_wp() - Set bits 29 and 31 of the SFP OSPR0 register which * denote the ITS and write protect flags respectively. * * WARNING - Setting the ITS and write protect flags will lock the mirror * registers and permanently prevent any further programming of the fuse block. * The system will also be forced to always attempt to secure boot which * requires signature validation and the absence of any hardware security * violations when booting. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_set_its_wp(void); /** * ls_sfp_set_ouid() - Write to the SFP OUID register at the given index. * @index: Index of the OUID register to write. * @ouid: Value to write into the SFP OUID register. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_set_ouid(uint32_t index, uint32_t ouid); /** * ls_sfp_status() - Check if the SFP driver was initialized successfully. * * Return: TEE_SUCCESS or > 0 on error. */ TEE_Result ls_sfp_status(void); #endif /* __DRIVERS_LS_SFP_H */ optee_os-4.3.0/core/include/drivers/mvebu_uart.h000066400000000000000000000033371464416617300217300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2017 Marvell International Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_MVEBU_UART_H #define __DRIVERS_MVEBU_UART_H #include #include struct mvebu_uart_data { struct io_pa_va base; struct serial_chip chip; }; void mvebu_uart_init(struct mvebu_uart_data *pd, paddr_t pbase, uint32_t uart_clk, uint32_t baud_rate); #endif /* __DRIVERS_MVEBU_UART_H */ optee_os-4.3.0/core/include/drivers/ns16550.h000066400000000000000000000043031464416617300205720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2015 Freescale Semiconductor, Inc. * Copyright (c) 2020, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_NS16550_H #define __DRIVERS_NS16550_H #include #include #include #define NS16550_UART_REG_SIZE 0x1000 #define IO_WIDTH_U8 0 #define IO_WIDTH_U32 1 struct ns16550_data { struct io_pa_va base; struct serial_chip chip; uint8_t io_width; uint8_t reg_shift; }; static inline unsigned int serial_in(vaddr_t addr, uint8_t io_width) { if (io_width == IO_WIDTH_U32) return io_read32(addr); else return io_read8(addr); } static inline void serial_out(vaddr_t addr, uint8_t io_width, int ch) { if (io_width == IO_WIDTH_U32) io_write32(addr, ch); else io_write8(addr, ch); } void ns16550_init(struct ns16550_data *pd, paddr_t base, uint8_t io_width, uint8_t reg_shift); #endif /* __DRIVERS_NS16550_H */ optee_os-4.3.0/core/include/drivers/nvmem.h000066400000000000000000000130561464416617300207000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, Microchip */ #ifndef __DRIVERS_NVMEM_H #define __DRIVERS_NVMEM_H #include #include #include #include struct nvmem_cell; /* * struct nvmem_ops - NVMEM device driver operations * @read_cell: Allocate @data in the heap and load @len bytes to from an * NVMEM cell * @put_cell: Release resources allocated from nvmem_dt_get_func callback * function */ struct nvmem_ops { /* * Read data from an NVMEM cell. * @cell: Cell to read data from * @data: Output buffer of size greater or equal to @cell->size */ TEE_Result (*read_cell)(struct nvmem_cell *cell, uint8_t *data); void (*put_cell)(struct nvmem_cell *cell); }; /* * struct nvmem_cell - Description of an NVMEM cell * @offset: Cell byte offset in the NVMEM device * @len: Cell byte size * @ops: NVMEM device driver operation handlers * @drv_data: NVMEM device driver private data */ struct nvmem_cell { paddr_t offset; size_t len; const struct nvmem_ops *ops; void *drv_data; }; /* * nvmem_dt_get_func - Typedef of handlers to get an NVMEM cell from a npode * @args: Reference to phandle arguments * @data: Pointer to data given at nvmem_dt_get_func() call * @cell: Output reference to cell instance upon success * * Return TEE_SUCCESS in case of success. * Return TEE_ERROR_DEFER_DRIVER_INIT if NVMEM driver is not initialized * Return another TEE_Result compliant code otherwise. */ typedef TEE_Result (*nvmem_dt_get_func)(struct dt_pargs *args, void *data, struct nvmem_cell **cell); #ifdef CFG_DRIVERS_NVMEM /** * nvmem_register_provider() - Register a NVMEM controller * * @fdt: Device tree to work on * @nodeoffset: Node offset of NVMEM cell consumer * @get_dt_nvmem: Callback to match the devicetree NVMEM reference with * nvmem_cell * @data: Data which will be passed to the get_dt_nvmem callback * Return a TEE_Result compliant value */ static inline TEE_Result nvmem_register_provider(const void *fdt, int nodeoffset, nvmem_dt_get_func get_dt_nvmem, void *data) { return dt_driver_register_provider(fdt, nodeoffset, (get_of_device_func)get_dt_nvmem, data, DT_DRIVER_NVMEM); } /** * nvmem_get_cell_by_name() - Obtain a NVMEM cell from its name in the DT node * * @fdt: Device tree to work on * @nodeoffset: Node offset of NVMEM cell consumer * @name: name of the NVMEM cell defined by property nvmem-cell-names to obtain * from the device tree * @cell: Pointer filled with the retrieved cell, must be freed after use using nvmem_put_cell() * Return a TEE_Result compliant value */ TEE_Result nvmem_get_cell_by_name(const void *fdt, int nodeoffset, const char *name, struct nvmem_cell **cell); /** * nvmem_get_cell_by_index() - Obtain a NVMEM cell from property nvmem-cells * * @fdt: Device tree to work on * @nodeoffset: Node offset of NVMEM cell consumer * @index: Index of the NVMEM cell to obtain from device-tree * @out_cell: Pointer filled with the retrieved cell, must be freed after use * using nvmem_put_cell() * Return a TEE_Result compliant value */ TEE_Result nvmem_get_cell_by_index(const void *fdt, int nodeoffset, unsigned int index, struct nvmem_cell **out_cell); /** * nvmem_cell_parse_dt() - Parse device-tree information to fill a NVMEM cell * * @fdt: Device tree to work on * @nodeoffset: Node offset of the NVMEM cell controller * @cell: Pointer to cell that will be filled */ TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset, struct nvmem_cell *cell); /** * nvmem_put_cell() - Free resource allocated from nvmem_get_cell_by_*() * * @cell: Cell to be freed */ static inline void nvmem_put_cell(struct nvmem_cell *cell) { if (cell->ops->put_cell) cell->ops->put_cell(cell); } /* * nvmem_cell_read() - Read data from a NVMEM cell * @cell: Cell to read from NVMEM * @data: Output data read from the cell upon success, byte size >= @cell->size */ static inline TEE_Result nvmem_cell_read(struct nvmem_cell *cell, uint8_t *data) { if (!cell->ops->read_cell) return TEE_ERROR_NOT_SUPPORTED; return cell->ops->read_cell(cell, data); } /* * nvmem_cell_malloc_and_read() - Allocate and read data from a NVMEM cell * @cell: Cell to read from NVMEM * @data: Output allocated buffer where NVMEM cell data are stored upon success * * Upon success, the output buffer is allocated with malloc(). Caller is * responsible for freeing the buffer with free() if needed. */ TEE_Result nvmem_cell_malloc_and_read(struct nvmem_cell *cell, uint8_t **out_data); #else /* CFG_DRIVERS_NVMEM */ static inline TEE_Result nvmem_register_provider(const void *fdt __unused, int nodeoffset __unused, nvmem_dt_get_func fn __unused, void *data __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result nvmem_get_cell_by_name(const void *fdt __unused, int nodeoffset __unused, const char *name __unused, struct nvmem_cell **c __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result nvmem_get_cell_by_index(const void *fdt __unused, int nodeoffset __unused, unsigned int index __unused, struct nvmem_cell **cell __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result nvmem_cell_parse_dt(const void *fdt __unused, int nodeoffset __unused, struct nvmem_cell *cell __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void nvmem_put_cell(struct nvmem_cell *cell __unused) { } #endif /* CFG_DRIVERS_NVMEM */ #endif /* __DRIVERS_NVMEM_H */ optee_os-4.3.0/core/include/drivers/pinctrl.h000066400000000000000000000117751464416617300212370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022-2023, Microchip */ #ifndef __DRIVERS_PINCTRL_H #define __DRIVERS_PINCTRL_H #include #include #include #include enum pinctrl_dt_prop { /* Property "bias-disable" found in pinctrl node */ PINCTRL_DT_PROP_BIAS_DISABLE, /* Property "bias-pull-up" found in pinctrl node */ PINCTRL_DT_PROP_BIAS_PULL_UP, /* Property "bias-pull-down" found in pinctrl node */ PINCTRL_DT_PROP_BIAS_PULL_DOWN, /* Terminal ID */ PINCTRL_DT_PROP_MAX }; /* * struct pinconf - Pinctrl device * @ops: Operation handlers * @priv: Pinctrl driver private data */ struct pinconf { const struct pinctrl_ops *ops; void *priv; }; /* * struct pinctrl_state - Pinctrl configuration state * @conf_count: Number of cells in @confs * @confs: Array of pin configurations related to the pinctrl config state */ struct pinctrl_state { unsigned int conf_count; struct pinconf *confs[]; }; struct pinctrl_ops { /* Apply a pinctrl configuration */ TEE_Result (*conf_apply)(struct pinconf *conf); /* Release resources allocated for a pinctrl configuration */ void (*conf_free)(struct pinconf *conf); }; /** * pinctrl_dt_get_func - Typedef of function to get a pin configuration from * a device tree property * * @args: Pointer to device tree phandle arguments of the pin control reference * @data: Pointer to data given at pinctrl_register_provider() call * @out_pinconf: Output pin configuration reference upon success */ typedef TEE_Result (*pinctrl_dt_get_func)(struct dt_pargs *pargs, void *data, struct pinconf **out_pinconf); #ifdef CFG_DRIVERS_PINCTRL /** * pinctrl_dt_register_provider - Register a pinctrl controller provider * * @fdt: Device tree to work on * @nodeoffset: Node offset of the pin controller * @get_pinctrl: Callback to match the pin controller with a struct pinconf * @data: Data which will be passed to the get_pinctrl callback * Return a TEE_Result compliant value */ static inline TEE_Result pinctrl_register_provider(const void *fdt, int nodeoffset, pinctrl_dt_get_func func, void *data) { return dt_driver_register_provider(fdt, nodeoffset, (get_of_device_func)func, data, DT_DRIVER_PINCTRL); } /** * pinctrl_get_state_by_name - Obtain a pinctrl state by name * * @fdt: Device tree to work on * @nodeoffset: Node offset of the pin controller * @name: name of the pinctrl state to obtain from device-tree * @state: Pointer filled with the retrieved state, must be freed after use using pinctrl_free_state() * Return a TEE_Result compliant value */ TEE_Result pinctrl_get_state_by_name(const void *fdt, int nodeoffset, const char *name, struct pinctrl_state **state); /** * pinctrl_get_state_by_idx - Obtain a pinctrl state by index * * @fdt: Device tree to work on * @nodeoffset: Node offset of the pin controller * @pinctrl_id: Index of the pinctrl state to obtain from device-tree * @state: Pointer filled with the retrieved state, must be freed after use using pinctrl_free_state() * Return a TEE_Result compliant value */ TEE_Result pinctrl_get_state_by_idx(const void *fdt, int nodeoffset, unsigned int pinctrl_id, struct pinctrl_state **state); /** * pinctrl_free_state - Free a pinctrl state that was previously obtained * * @state: State to be freed */ void pinctrl_free_state(struct pinctrl_state *state); /** * pinctrl_apply_state - apply a pinctrl state * * @state: State to be applied * Return a TEE_Result compliant value */ TEE_Result pinctrl_apply_state(struct pinctrl_state *state); /* * pinctrl_parse_dt_pin_modes - Parse DT node properties * @fdt: Device tree to work on * @nodeoffset: Pinctrl node * @modes: Output allocated regulator properties * Return a TEE_Result compliant value */ TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt, int nodeoffset, bitstr_t **modes); #else /* CFG_DRIVERS_PINCTRL */ static inline TEE_Result pinctrl_register_provider(const void *fdt __unused, int nodeoffset __unused, get_of_device_func func __unused, void *data __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result pinctrl_get_state_by_name(const void *fdt __unused, int nodeoffset __unused, const char *name __unused, struct pinctrl_state **state __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result pinctrl_get_state_by_idx(const void *fdt __unused, int nodeoffset __unused, unsigned int pinctrl_id __unused, struct pinctrl_state **state __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void pinctrl_free_state(struct pinctrl_state *state __unused) { } static inline TEE_Result pinctrl_apply_state(struct pinctrl_state *s __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result pinctrl_parse_dt_pin_modes(const void *fdt __unused, int nodeoffset __unused, bitstr_t **modes __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* CFG_DRIVERS_PINCTRL */ #endif /* __DRIVERS_PINCTRL_H */ optee_os-4.3.0/core/include/drivers/pl011.h000066400000000000000000000006521464416617300204110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __DRIVERS_PL011_H #define __DRIVERS_PL011_H #include #include #define PL011_REG_SIZE 0x1000 struct pl011_data { struct io_pa_va base; struct serial_chip chip; }; void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk, uint32_t baud_rate); #endif /* __DRIVERS_PL011_H */ optee_os-4.3.0/core/include/drivers/pl022_spi.h000066400000000000000000000015051464416617300212640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * */ #ifndef __DRIVERS_PL022_SPI_H #define __DRIVERS_PL022_SPI_H #include #include #define PL022_REG_SIZE 0x1000 enum pl022_cs_control { PL022_CS_CTRL_AUTO_GPIO, PL022_CS_CTRL_CB, PL022_CS_CTRL_MANUAL }; struct pl022_cs_gpio_data { struct gpio_chip *chip; unsigned int pin_num; }; union pl022_cs_data { struct pl022_cs_gpio_data gpio_data; void (*cs_cb)(enum gpio_level value); }; struct pl022_data { union pl022_cs_data cs_data; struct spi_chip chip; vaddr_t base; enum spi_mode mode; enum pl022_cs_control cs_control; unsigned int clk_hz; unsigned int speed_hz; unsigned int data_size_bits; bool loopback; }; void pl022_init(struct pl022_data *pd); #endif /* __DRIVERS_PL022_SPI_H */ optee_os-4.3.0/core/include/drivers/pl061_gpio.h000066400000000000000000000011721464416617300214320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __DRIVERS_PL061_GPIO_H #define __DRIVERS_PL061_GPIO_H #include #include #define PL061_REG_SIZE 0x1000 enum pl061_mode_control { PL061_MC_SW, PL061_MC_HW }; struct pl061_data { struct gpio_chip chip; }; void pl061_register(vaddr_t base_addr, unsigned int gpio_dev); void pl061_init(struct pl061_data *pd); enum pl061_mode_control pl061_get_mode_control(unsigned int gpio_pin); void pl061_set_mode_control(unsigned int gpio_pin, enum pl061_mode_control hw_sw); #endif /* __DRIVERS_PL061_GPIO_H */ optee_os-4.3.0/core/include/drivers/plic.h000066400000000000000000000005541464416617300205040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #ifndef __DRIVERS_PLIC_H #define __DRIVERS_PLIC_H #include #include #include void plic_init(paddr_t plic_base_pa); void plic_hart_init(void); void plic_it_handle(void); void plic_dump_state(void); #endif /*__DRIVERS_PLIC_H*/ optee_os-4.3.0/core/include/drivers/pm/000077500000000000000000000000001464416617300200145ustar00rootroot00000000000000optee_os-4.3.0/core/include/drivers/pm/sam/000077500000000000000000000000001464416617300205745ustar00rootroot00000000000000optee_os-4.3.0/core/include/drivers/pm/sam/atmel_pm.h000066400000000000000000000026471464416617300225540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Microchip */ #ifndef __DRIVERS_PM_SAM_ATMEL_PM_H #define __DRIVERS_PM_SAM_ATMEL_PM_H #include #include #include #include #include #include struct sm_nsec_ctx; #if defined(CFG_ATMEL_PM) static inline bool atmel_pm_suspend_available(void) { return true; } void atmel_pm_cpu_idle(void); TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec); TEE_Result sam_pm_init(const void *fdt, vaddr_t shdwc); enum sm_handler_ret at91_pm_set_suspend_mode(struct thread_smc_args *args); enum sm_handler_ret at91_pm_get_suspend_mode(struct thread_smc_args *args); #else static inline void atmel_pm_cpu_idle(void) {}; static inline bool atmel_pm_suspend_available(void) { return false; } static inline TEE_Result atmel_pm_suspend(uintptr_t entry __unused, struct sm_nsec_ctx *nsec __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result sam_pm_init(const void *fdt __unused, vaddr_t shdwc __unused) { return TEE_SUCCESS; } static inline enum sm_handler_ret at91_pm_set_suspend_mode(struct thread_smc_args *args __unused) { return SM_HANDLER_PENDING_SMC; } static inline enum sm_handler_ret at91_pm_get_suspend_mode(struct thread_smc_args *args __unused) { return SM_HANDLER_PENDING_SMC; } #endif #endif /* __DRIVERS_PM_SAM_ATMEL_PM_H */ optee_os-4.3.0/core/include/drivers/regulator.h000066400000000000000000000244231464416617300215620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, STMicroelectronics */ #ifndef __DRIVERS_REGULATOR_H #define __DRIVERS_REGULATOR_H #include #include #include #include #include #include #include #include /* Regulator property flags: related to device tree binding properties */ /* Regulator should never be disabled. DT property: regulator-always-on */ #define REGULATOR_ALWAYS_ON BIT(0) /* Enables pull down mode. DT property: regulator-pull-down */ #define REGULATOR_PULL_DOWN BIT(1) /* * It's expected that this regulator was left on by the bootloader. * The core shouldn't prevent it from being turned off later. * DT property: regulator-boot-on */ #define REGULATOR_BOOT_ON BIT(2) #define REGULATOR_FLAGS_MASK (REGULATOR_ALWAYS_ON | REGULATOR_PULL_DOWN | \ REGULATOR_BOOT_ON) struct regulator_ops; /* * struct regu_dt_desc - Regulator description passed to regulator_dt_register() * @priv: Regulator driver private data * @name: Regulator string name for debug purpose * @supply_name: Regulator supply name for node property *-supply or NULL * @ops: Operation handlers for the regulator * @regulator: Pointer to preallocated regulator or NULL if none */ struct regu_dt_desc { void *priv; const char *name; const char *supply_name; const struct regulator_ops *ops; struct regulator *regulator; }; /* * Defines the format of struct voltages::entries * * If regulator_voltages::type is VOLTAGE_TYPE_FULL_LIST, then * regulator_voltages@entries stores regulator_voltages::num_levels cells, * listing supported voltage levels in uV from lowest to highest value. * * If regulator_voltages::type is VOLTAGE_TYPE_INCREMENT, then * regulator_voltages::entries stores 3 cells: min level, max level and * level increment step, all in uV. When so, regulator_voltages::num_levels * is meaningless. */ enum voltage_type { VOLTAGE_TYPE_INVALID = 0, VOLTAGE_TYPE_FULL_LIST, /* extensive list in uV */ VOLTAGE_TYPE_INCREMENT /* min, max, increment (in uV) */ }; /* * struct regulator_voltages_desc - Voltage levels description * @type: Type of level description * @num_levels: Number of voltage levels when @type is VOLTAGE_TYPE_FULL_LIST * */ struct regulator_voltages_desc { enum voltage_type type; size_t num_levels; }; /* * struct regulator - A regulator instance * @ops: Operation handlers for the regulator * @supply: Regulator supply reference or NULL if none * @priv: Regulator driver private data * @name: Regulator string name for debug purpose or NULL * @min_uv: Min possible voltage level in microvolt (uV) * @max_uv: Max possible voltage level in microvolt (uV) * @flags: REGULATOR_* property flags * @refcount: Regulator enable request reference counter * @mutex: Concurrent access protection considering PM context sequences * @voltages_fallback: Default supported voltage range description * @link: Link in initialized regulator list */ struct regulator { /* Fields initialized by caller of regulator_register() */ const struct regulator_ops *ops; struct regulator *supply; void *priv; char *name; int min_uv; int max_uv; /* Fields internal to regulator framework */ unsigned int flags; unsigned int refcount; struct mutex_pm_aware mutex; struct voltages_fallback { struct regulator_voltages_desc desc; int levels[3]; } voltages_fallback; size_t levels_count_fallback; SLIST_ENTRY(regulator) link; }; /* * struct regulator_ops - Regulator operation handlers * * @set_state: Enable or disable a regulator * @get_state: Get regulator effective state * @set_voltage: Set voltage level in microvolt (uV) * @get_voltage: Get current voltage in microvolt (uV) * @supported_voltages: Get supported levels description * @supplied_init: Optional, finalize initialization once supply is ready */ struct regulator_ops { TEE_Result (*set_state)(struct regulator *r, bool enabled); TEE_Result (*get_state)(struct regulator *r, bool *enabled); TEE_Result (*set_voltage)(struct regulator *r, int level_uv); TEE_Result (*get_voltage)(struct regulator *r, int *level_uv); TEE_Result (*supported_voltages)(struct regulator *r, struct regulator_voltages_desc **desc, const int **levels); TEE_Result (*supplied_init)(struct regulator *r, const void *fdt, int node); }; #ifdef CFG_DRIVERS_REGULATOR /* * regulator_enable() - Enable regulator * @regulator: Regulator reference */ TEE_Result regulator_enable(struct regulator *regulator); /* * regulator_disable() - Disable regulator * @regulator: Regulator reference */ TEE_Result regulator_disable(struct regulator *regulator); /* * regulator_is_enabled() - Return whether or not regulator is currently enabled * despite its refcount value. * @regulator: Regulator reference */ bool regulator_is_enabled(struct regulator *regulator); /* * regulator_set_voltage() - Set regulator to target level in microvolt * @regulator: Regulator reference * @level_uv: Level in microvolt */ TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv); /* * regulator_register() - Register and initialize a regulator * @regulator: Regulator reference */ TEE_Result regulator_register(struct regulator *regulator); /* Print registered regulators and their state to the output console */ void regulator_print_state(const char *message); #else static inline TEE_Result regulator_enable(struct regulator *regulator __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result regulator_disable(struct regulator *regulator __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline bool regulator_is_enabled(struct regulator *regulator __unused) { return false; } static inline TEE_Result regulator_set_voltage(struct regulator *regul __unused, int level_mv __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result regulator_init(struct regulator *regulator __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void regulator_print_state(const char *message __unused) { } #endif /*CFG_DRIVERS_REGULATOR*/ #if defined(CFG_DRIVERS_REGULATOR) && defined(CFG_DT) /* * regulator_dt_get_supply() - Get a regulator supply from name and DT node * @fdt: FDT to work on * @node: DT node of the regulator consumer * @supply_name: Name of the supply in DT property xxx-supply * @regulator: Output regulator upon success * * Upon success, this function provides the pointer to regulator * defined by DT binding property @name-supply phandle reference. * * This function returns TEE_ERROR_DEFER_DRIVER_INIT if supply exists but is * not yet initialized. */ TEE_Result regulator_dt_get_supply(const void *fdt, int node, const char *supply_name, struct regulator **regulator); /* * regulator_dt_register() - Register a regulator to related to a DT node * @fdt: FDT to work on * @node: DT node of the regulator exposed by regulator driver * @provider_node: Node where xxx-supply property is found or -1 if no supply. * @desc: Description of the regulator to register * * This function registers and initializes a regulator instance once its supply * if found, if any. Regulators registered with this function can be found by * their consumer drivers using API function regulator_dt_get_supply() or like. * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_OUT_OF_MEMORY if failed on memory allocation * Return any other TEE_Result compliant code in case of error */ TEE_Result regulator_dt_register(const void *fdt, int node, int provider_node, const struct regu_dt_desc *desc); #else static inline TEE_Result regulator_dt_get_supply(const void *fdt __unused, int node __unused, const char *supply __unused, struct regulator **r __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result regulator_dt_register(const void *fdt __unused, int node __unused, int provider_node __unused, const struct regu_dt_desc *d __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* CFG_DRIVERS_REGULATOR && CFG_DT */ /* * regulator_name() - Return regulator name or NULL * @regulator: Regulator reference */ static inline const char *regulator_name(struct regulator *regulator) { return regulator->name; } /* * regulator_is_always_on() - Return the state of REGULATOR_ALWAYS_ON flag * @regulator: Regulator reference */ static inline bool regulator_is_always_on(struct regulator *regulator) { return regulator->flags & REGULATOR_ALWAYS_ON; } /* * regulator_set_min_voltage() - Set regulator to its min level * @regulator: Regulator reference */ static inline TEE_Result regulator_set_min_voltage(struct regulator *regulator) { return regulator_set_voltage(regulator, regulator->min_uv); } /* * regulator_get_voltage() - Get regulator effective voltage level in microvolt * @regulator: Regulator reference */ int regulator_get_voltage(struct regulator *regulator); /* * regulator_get_range() - Get regulator min and/or max support levels * @regulator: Regulator reference * @min_mv: Output reference to min level in microvolt (uV) or NULL * @max_mv: Output reference to max level in microvolt (uV) or NULL */ static inline void regulator_get_range(struct regulator *regulator, int *min_uv, int *max_uv) { assert(regulator); if (min_uv) *min_uv = regulator->min_uv; if (max_uv) *max_uv = regulator->max_uv; } /* * regulator_supported_voltages() - Get regulator supported levels in microvolt * @regulator: Regulator reference * @desc: Output reference to supported voltage levels description * @levels: Output reference to voltage level array, in microvolts * * When @desc->type is VOLTAGE_TYPE_FULL_LIST, number of cells of @*levels * is defined by @desc->num_levels, each cell being a level in microvolts (uV). * When @desc->type is VOLTAGE_TYPE_INCREMENT, @levels has 3 cells: * @levels[0] is the min voltage level, @levels[1] is the max level, @levels[2] * is the incremental level step, all in microvolts (uV). */ TEE_Result regulator_supported_voltages(struct regulator *regulator, struct regulator_voltages_desc **desc, const int **levels); /* Print current regulator tree summary to console with debug trace level */ #ifdef CFG_DRIVERS_REGULATOR void regulator_print_tree(void); #else static inline void regulator_print_tree(void) { } #endif /* CFG_DRIVERS_REGULATOR */ #endif /* __DRIVERS_REGULATOR_H */ optee_os-4.3.0/core/include/drivers/rstctrl.h000066400000000000000000000154061464416617300212540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Linaro Limited */ #ifndef __DRIVERS_RSTCTRL_H #define __DRIVERS_RSTCTRL_H #include #include #include struct rstctrl; struct rstctrl_ops { /* * Operators on reset control(s) exposed by a reset controller * * @assert_level: Assert reset level on control with a timeout hint * @deassert_level: Deassert reset level on control with a timeout hint * @get_name: Get a string name for the controller, or NULL is none * * Operator functions @assert_level and @deassert_level use arguments: * @rstctrl: Reset controller * @id: Identifier for the reset level control in the reset controller * @to_ms: Timeout in microseconds or RSTCTRL_NO_TIMEOUT, may be ignored * by reset controller. * Return a TEE_Result compliant code. */ TEE_Result (*assert_level)(struct rstctrl *rstctrl, unsigned int to_us); TEE_Result (*deassert_level)(struct rstctrl *rstctrl, unsigned int to_us); const char *(*get_name)(struct rstctrl *rstctrl); }; /* * struct rstctrl - Instance of a control exposed by a reset controller * @ops: Operators of the reset controller * @exclusive: Set when a consumer has exclusive control on the reset level */ struct rstctrl { const struct rstctrl_ops *ops; bool exclusive; }; /** * RSTCTRL_DECLARE - Declare a reset controller driver with a single * device tree compatible string. * * @__name: Reset controller driver name * @__compat: Compatible string * @__probe: Reset controller probe function */ #define RSTCTRL_DT_DECLARE(__name, __compat, __probe) \ static const struct dt_device_match __name ## _match_table[] = { \ { .compatible = __compat }, \ { } \ }; \ DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ .name = # __name, \ .type = DT_DRIVER_RSTCTRL, \ .match_table = __name ## _match_table, \ .probe = __probe, \ } /* * Platform driver may ignore the timeout hint according to their * capabilities. RSTCTRL_NO_TIMEOUT specifies no timeout hint. */ #define RSTCTRL_NO_TIMEOUT 0 /* * rstctrl_assert_to - Assert reset control possibly with timeout * rstctrl_assert - Assert reset control * rstctrl_deassert_to - Deassert reset control possibly with timeout * rstctrl_deassert - Deassert reset control * * @rstctrl: Reset controller * @to_us: Timeout in microseconds * Return a TEE_Result compliant code */ static inline TEE_Result rstctrl_assert_to(struct rstctrl *rstctrl, unsigned int to_us) { return rstctrl->ops->assert_level(rstctrl, to_us); } static inline TEE_Result rstctrl_assert(struct rstctrl *rstctrl) { return rstctrl_assert_to(rstctrl, RSTCTRL_NO_TIMEOUT); } static inline TEE_Result rstctrl_deassert_to(struct rstctrl *rstctrl, unsigned int to_us) { return rstctrl->ops->deassert_level(rstctrl, to_us); } static inline TEE_Result rstctrl_deassert(struct rstctrl *rstctrl) { return rstctrl_deassert_to(rstctrl, RSTCTRL_NO_TIMEOUT); } /* * rstctrl_name - Get a name for the reset level control or NULL * * @rstctrl: Reset controller * Return a pointer to controller name or NULL */ static inline const char *rstctrl_name(struct rstctrl *rstctrl) { if (rstctrl->ops->get_name) return rstctrl->ops->get_name(rstctrl); return NULL; } /** * rstctrl_dt_get_exclusive - Get exclusive access to reset controller * * @rstctrl: Reset controller * Return a TEE_Result compliant value */ TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl); /** * rstctrl_put_exclusive - Release exclusive access to target * * @rstctrl: Reset controller */ void rstctrl_put_exclusive(struct rstctrl *rstctrl); /** * rstctrl_ops_is_valid - Check reset controller ops is valid * * @ops: Reference to reset controller operator instance */ static inline bool rstctrl_ops_is_valid(const struct rstctrl_ops *ops) { return ops && ops->assert_level && ops->deassert_level; } #ifdef CFG_DT /** * rstctrl_dt_get_by_index - Get a reset controller at a specific index in * 'resets' property * * @fdt: Device tree to work on * @nodeoffset: Node offset of the subnode containing a 'resets' property * @index: Reset controller index in 'resets' property * @rstctrl: Output reset controller reference upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the resets property does not exist * Return a TEE_Result compliant code in case of error */ static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt, int nodeoffset, unsigned int index, struct rstctrl **out_rstctrl) { TEE_Result res = TEE_ERROR_GENERIC; void *rstctrl = NULL; res = dt_driver_device_from_node_idx_prop("resets", fdt, nodeoffset, index, DT_DRIVER_RSTCTRL, &rstctrl); if (!res) *out_rstctrl = rstctrl; return res; } #else static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused, int nodeoffset __unused, unsigned int index __unused, struct rstctrl **ctrl __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /*CFG_DT*/ /** * rstctrl_dt_get_by_name - Get a reset controller matching a name in the * 'reset-names' property * * @fdt: Device tree to work on * @nodeoffset: Node offset of the subnode containing a 'resets' property * @name: Reset controller name to get * @rstctrl: Output reset controller reference upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if reset controller is not initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the reset-names property does not exist * Return a TEE_Result compliant code in case of error */ TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset, const char *name, struct rstctrl **rstctrl); /** * rstctrl_dt_get_func - Typedef of function to get reset controller from * devicetree properties * * @args: Pointer to devicetree description of the reset controller to parse * @data: Pointer to data given at rstctrl_dt_register_provider() call * @rstctrl: Output reset controller reference upon success */ typedef TEE_Result (*rstctrl_dt_get_func)(struct dt_pargs *args, void *data, struct rstctrl **out_rstctrl); /** * rstctrl_dt_register_provider - Register a reset controller provider * * @fdt: Device tree to work on * @nodeoffset: Node offset of the reset controller * @func: Callback to match the reset controller with a struct rstctrl * @data: Data which will be passed to the get_dt_rstctrl callback * Returns TEE_Result value */ static inline TEE_Result rstctrl_register_provider(const void *fdt, int nodeoffset, rstctrl_dt_get_func func, void *data) { return dt_driver_register_provider(fdt, nodeoffset, (get_of_device_func)func, data, DT_DRIVER_RSTCTRL); } #endif /* __DRIVERS_RSTCTRL_H */ optee_os-4.3.0/core/include/drivers/rtc.h000066400000000000000000000057321464416617300203500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 Microchip. */ #ifndef __DRIVERS_RTC_H #define __DRIVERS_RTC_H #include #include /* The RTC allows to set/get offset for correction */ #define RTC_CORRECTION_FEATURE BIT(0) struct optee_rtc_time { uint32_t tm_year; uint32_t tm_mon; uint32_t tm_mday; uint32_t tm_hour; uint32_t tm_min; uint32_t tm_sec; uint32_t tm_wday; }; struct rtc { const struct rtc_ops *ops; struct optee_rtc_time range_min; struct optee_rtc_time range_max; }; /* * struct rtc_ops - The RTC device operations * * @get_time: Get the RTC time. * @set_time: Set the RTC time. * @get_offset: Get the RTC offset. * @set_offset: Set the RTC offset */ struct rtc_ops { TEE_Result (*get_time)(struct rtc *rtc, struct optee_rtc_time *tm); TEE_Result (*set_time)(struct rtc *rtc, struct optee_rtc_time *tm); TEE_Result (*get_offset)(struct rtc *rtc, long *offset); TEE_Result (*set_offset)(struct rtc *rtc, long offset); }; #ifdef CFG_DRIVERS_RTC extern struct rtc *rtc_device; /* Register a RTC device as the system RTC */ void rtc_register(struct rtc *rtc); static inline TEE_Result rtc_get_info(uint64_t *features, struct optee_rtc_time *range_min, struct optee_rtc_time *range_max) { if (!rtc_device) return TEE_ERROR_NOT_SUPPORTED; if (rtc_device->ops->set_offset) *features = RTC_CORRECTION_FEATURE; *range_min = rtc_device->range_min; *range_max = rtc_device->range_max; return TEE_SUCCESS; } static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm) { if (!rtc_device) return TEE_ERROR_NOT_SUPPORTED; return rtc_device->ops->get_time(rtc_device, tm); } static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm) { if (!rtc_device || !rtc_device->ops->set_time) return TEE_ERROR_NOT_SUPPORTED; return rtc_device->ops->set_time(rtc_device, tm); } static inline TEE_Result rtc_get_offset(long *offset) { if (!rtc_device || !rtc_device->ops->get_offset) return TEE_ERROR_NOT_SUPPORTED; return rtc_device->ops->get_offset(rtc_device, offset); } static inline TEE_Result rtc_set_offset(long offset) { if (!rtc_device || !rtc_device->ops->set_offset) return TEE_ERROR_NOT_SUPPORTED; return rtc_device->ops->set_offset(rtc_device, offset); } #else static inline void rtc_register(struct rtc *rtc __unused) {} static inline TEE_Result rtc_get_info(uint64_t *features __unused, struct optee_rtc_time *range_min __unused, struct optee_rtc_time *range_max __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result rtc_get_time(struct optee_rtc_time *tm __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result rtc_set_time(struct optee_rtc_time *tm __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result rtc_get_offset(long *offset __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result rtc_set_offset(long offset __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif #endif /* __DRIVERS_RTC_H */ optee_os-4.3.0/core/include/drivers/sam/000077500000000000000000000000001464416617300201605ustar00rootroot00000000000000optee_os-4.3.0/core/include/drivers/sam/at91_ddr.h000066400000000000000000000144471464416617300217520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Header file for the Atmel DDR/SDR SDRAM Controller * * Copyright (C) 2010 Atmel Corporation * Nicolas Ferre */ #ifndef __DRIVERS_SAM_AT91_DDRSDR_H #define __DRIVERS_SAM_AT91_DDRSDR_H /* Mode Register */ #define AT91_DDRSDRC_MR 0x00 /* Command Mode */ #define AT91_DDRSDRC_MODE SHIFT_U32(0x7, 0) #define AT91_DDRSDRC_MODE_NORMAL 0 #define AT91_DDRSDRC_MODE_NOP 1 #define AT91_DDRSDRC_MODE_PRECHARGE 2 #define AT91_DDRSDRC_MODE_LMR 3 #define AT91_DDRSDRC_MODE_REFRESH 4 #define AT91_DDRSDRC_MODE_EXT_LMR 5 #define AT91_DDRSDRC_MODE_DEEP 6 /* Refresh Timer Register */ #define AT91_DDRSDRC_RTR 0x04 /* Refresh Timer Counter */ #define AT91_DDRSDRC_COUNT SHIFT_U32(0xfff, 0) /* Configuration Register */ #define AT91_DDRSDRC_CR 0x08 /* Number of Column Bits */ #define AT91_DDRSDRC_NC SHIFT_U32(3, 0) #define AT91_DDRSDRC_NC_SDR8 SHIFT_U32(0, 0) #define AT91_DDRSDRC_NC_SDR9 BIT(0) #define AT91_DDRSDRC_NC_SDR10 SHIFT_U32(2, 0) #define AT91_DDRSDRC_NC_SDR11 SHIFT_U32(3, 0) #define AT91_DDRSDRC_NC_DDR9 SHIFT_U32(0, 0) #define AT91_DDRSDRC_NC_DDR10 BIT(0) #define AT91_DDRSDRC_NC_DDR11 SHIFT_U32(2, 0) #define AT91_DDRSDRC_NC_DDR12 SHIFT_U32(3, 0) /* Number of Row Bits */ #define AT91_DDRSDRC_NR SHIFT_U32(3, 2) #define AT91_DDRSDRC_NR_11 SHIFT_U32(0, 2) #define AT91_DDRSDRC_NR_12 BIT(2) #define AT91_DDRSDRC_NR_13 SHIFT_U32(2, 2) #define AT91_DDRSDRC_NR_14 SHIFT_U32(3, 2) /* CAS Latency */ #define AT91_DDRSDRC_CAS SHIFT_U32(7, 4) #define AT91_DDRSDRC_CAS_2 SHIFT_U32(2, 4) #define AT91_DDRSDRC_CAS_3 SHIFT_U32(3, 4) #define AT91_DDRSDRC_CAS_25 SHIFT_U32(6, 4) /* Reset DLL */ #define AT91_DDRSDRC_RST_DLL BIT(7) /* Output impedance control */ #define AT91_DDRSDRC_DICDS BIT(8) /* Disable DLL [SAM9 Only] */ #define AT91_DDRSDRC_DIS_DLL BIT(9) /* Off-Chip Driver [SAM9 Only] */ #define AT91_DDRSDRC_OCD BIT(12) /* Mask Data is Shared [SAM9 Only] */ #define AT91_DDRSDRC_DQMS BIT(16) /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */ #define AT91_DDRSDRC_ACTBST BIT(18) /* Timing 0 Register */ #define AT91_DDRSDRC_T0PR 0x0C /* Active to Precharge delay */ #define AT91_DDRSDRC_TRAS SHIFT_U32(0xf, 0) /* Row to Column delay */ #define AT91_DDRSDRC_TRCD SHIFT_U32(0xf, 4) /* Write recovery delay */ #define AT91_DDRSDRC_TWR SHIFT_U32(0xf, 8) /* Row cycle delay */ #define AT91_DDRSDRC_TRC SHIFT_U32(0xf, 12) /* Row precharge delay */ #define AT91_DDRSDRC_TRP SHIFT_U32(0xf, 16) /* Active BankA to BankB */ #define AT91_DDRSDRC_TRRD SHIFT_U32(0xf, 20) /* Internal Write to Read delay */ #define AT91_DDRSDRC_TWTR SHIFT_U32(0x7, 24) /* Reduce Write to Read Delay [SAM9 Only] */ #define AT91_DDRSDRC_RED_WRRD SHIFT_U32(0x1, 27) /* Load mode to active/refresh delay */ #define AT91_DDRSDRC_TMRD SHIFT_U32(0xf, 28) /* Timing 1 Register */ #define AT91_DDRSDRC_T1PR 0x10 /* Row Cycle Delay */ #define AT91_DDRSDRC_TRFC SHIFT_U32(0x1f, 0) /* Exit self-refresh to non-read */ #define AT91_DDRSDRC_TXSNR SHIFT_U32(0xff, 8) /* Exit self-refresh to read */ #define AT91_DDRSDRC_TXSRD SHIFT_U32(0xff, 16) /* Exit power-down delay */ #define AT91_DDRSDRC_TXP SHIFT_U32(0xf, 24) /* Timing 2 Register [SAM9 Only] */ #define AT91_DDRSDRC_T2PR 0x14 /* Exit active power down delay to read command in mode "Fast Exit" */ #define AT91_DDRSDRC_TXARD SHIFT_U32(0xf, 0) /* Exit active power down delay to read command in mode "Slow Exit" */ #define AT91_DDRSDRC_TXARDS SHIFT_U32(0xf, 4) /* Row Precharge All delay */ #define AT91_DDRSDRC_TRPA SHIFT_U32(0xf, 8) /* Read to Precharge delay */ #define AT91_DDRSDRC_TRTP SHIFT_U32(0x7, 12) /* Low Power Register */ #define AT91_DDRSDRC_LPR 0x1C /* Low-power Configurations */ #define AT91_DDRSDRC_LPCB SHIFT_U32(3, 0) #define AT91_DDRSDRC_LPCB_DISABLE 0 #define AT91_DDRSDRC_LPCB_SELF_REFRESH 1 #define AT91_DDRSDRC_LPCB_POWER_DOWN 2 #define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3 /* Clock Frozen */ #define AT91_DDRSDRC_CLKFR BIT(2) /* LPDDR Power Off */ #define AT91_DDRSDRC_LPDDR2_PWOFF BIT(3) /* Partial Array Self Refresh */ #define AT91_DDRSDRC_PASR SHIFT_U32(7, 4) /* Temperature Compensated Self Refresh */ #define AT91_DDRSDRC_TCSR SHIFT_U32(3, 8) /* Drive Strength */ #define AT91_DDRSDRC_DS SHIFT_U32(3, 10) /* Time to define when Low Power Mode is enabled */ #define AT91_DDRSDRC_TIMEOUT SHIFT_U32(3, 12) #define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES SHIFT_U32(0, 12) #define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES BIT(12) #define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES SHIFT_U32(2, 12) /* Active power down exit time */ #define AT91_DDRSDRC_APDE BIT(16) /* Update load mode register and extended mode register */ #define AT91_DDRSDRC_UPD_MR SHIFT_U32(3, 20) /* Memory Device Register */ #define AT91_DDRSDRC_MDR 0x20 /* Memory Device Type */ #define AT91_DDRSDRC_MD SHIFT_U32(7, 0) #define AT91_DDRSDRC_MD_SDR 0 #define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 #define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 #define AT91_DDRSDRC_MD_LPDDR3 5 /* [SAM9 Only] */ #define AT91_DDRSDRC_MD_DDR2 6 #define AT91_DDRSDRC_MD_LPDDR2 7 /* Data Bus Width */ #define AT91_DDRSDRC_DBW BIT(4) #define AT91_DDRSDRC_DBW_32BITS SHIFT_U32(0, 4) #define AT91_DDRSDRC_DBW_16BITS BIT(4) /* DLL Information Register */ #define AT91_DDRSDRC_DLL 0x24 /* Master Delay increment */ #define AT91_DDRSDRC_MDINC BIT(0) /* Master Delay decrement */ #define AT91_DDRSDRC_MDDEC BIT(1) /* Master Delay Overflow */ #define AT91_DDRSDRC_MDOVF BIT(2) /* Master Delay value */ #define AT91_DDRSDRC_MDVAL SHIFT_U32(0xff, 8) /* High Speed Register [SAM9 Only] */ #define AT91_DDRSDRC_HS 0x2C /* Anticip read access is disabled */ #define AT91_DDRSDRC_DIS_ATCP_RD BIT(2) /* Delay I/O Register n */ #define AT91_DDRSDRC_DELAY(n) (0x30 + (0x4 * (n))) /* Write Protect Mode Register [SAM9 Only] */ #define AT91_DDRSDRC_WPMR 0xE4 /* Write protect enable */ #define AT91_DDRSDRC_WP BIT(0) /* Write protect key */ #define AT91_DDRSDRC_WPKEY SHIFT_U32(0xffffff, 8) /* Write protect key = "DDR" */ #define AT91_DDRSDRC_KEY SHIFT_U32(0x444452, 8) /* Write Protect Status Register [SAM9 Only] */ #define AT91_DDRSDRC_WPSR 0xE8 /* Write protect violation status */ #define AT91_DDRSDRC_WPVS BIT(0) /* Write protect violation source */ #define AT91_DDRSDRC_WPVSRC SHIFT_U32(0xffff, 8) #endif optee_os-4.3.0/core/include/drivers/sam/sama7-ddr.h000066400000000000000000000103411464416617300221070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets * and bit definitions. * * Copyright (C) [2024] Microchip Technology Inc. and its subsidiaries * * Author: Tony Han */ #ifndef __SAMA7_DDR_H__ #define __SAMA7_DDR_H__ /* DDR3PHY */ /* DDR3PHY PHY Initialization Register */ #define DDR3PHY_PIR 0x04 #define DDR3PHY_PIR_DLLBYP BIT(17) /* DLL Bypass */ #define DDR3PHY_PIR_ITMSRST BIT(4) /* Interface Timing Module Soft Reset */ #define DDR3PHY_PIR_DLLLOCK BIT(2) /* DLL Lock */ #define DDR3PHY_PIR_DLLSRST BIT(1) /* DLL Soft Rest */ #define DDR3PHY_PIR_INIT BIT(0) /* Initialization Trigger */ /* DDR3PHY PHY General Configuration Register */ #define DDR3PHY_PGCR 0x08 #define DDR3PHY_PGCR_CKDV1 BIT(13) /* CK# Disable Value */ #define DDR3PHY_PGCR_CKDV0 BIT(12) /* CK Disable Value */ /* DDR3PHY PHY General Status Register */ #define DDR3PHY_PGSR 0x0C #define DDR3PHY_PGSR_IDONE BIT(0) /* Initialization Done */ /* DDR3PHY AC DLL Control Register */ #define DDR3PHY_ACDLLCR 0x14 #define DDR3PHY_ACDLLCR_DLLSRST BIT(30) /* DLL Soft Reset */ /* DDR3PHY AC I/O Configuration Register */ #define DDR3PHY_ACIOCR 0x24 #define DDR3PHY_ACIOCR_CSPDD_CS0 BIT(18) /* CS#[0] Power Down Driver */ #define DDR3PHY_ACIOCR_CKPDD_CK0 BIT(8) /* CK[0] Power Down Driver */ #define DDR3PHY_ACIORC_ACPDD BIT(3) /* AC Power Down Driver */ /* DDR3PHY DATX8 Common Configuration Register */ #define DDR3PHY_DXCCR 0x28 #define DDR3PHY_DXCCR_DXPDR BIT(3) /* Data Power Down Receiver */ /* DDR3PHY DDR System General Configuration Register */ #define DDR3PHY_DSGCR 0x2C #define DDR3PHY_DSGCR_ODTPDD_ODT0 BIT(20) /* ODT[0] Power Down Driver */ /* ZQ status register 0 */ #define DDR3PHY_ZQ0SR0 0x188 /* impedance select offset */ #define DDR3PHY_ZQ0SR0_PDO_OFF 0 /* Pull-down output */ #define DDR3PHY_ZQ0SR0_PUO_OFF 5 /* Pull-up output */ #define DDR3PHY_ZQ0SR0_PDODT_OFF 10 /* Pull-down on-die termination*/ #define DDR3PHY_ZQ0SRO_PUODT_OFF 15 /* Pull-up on-die termination */ /* DDR3PHY DATX8 DLL Control Register */ #define DDR3PHY_DX0DLLCR 0x1CC #define DDR3PHY_DX1DLLCR 0x20C /* DATX8 DLL Control Register */ #define DDR3PHY_DXDLLCR_DLLDIS BIT(31) /* DLL Disable */ /* UDDRC */ /* UDDRC Operating Mode Status Register */ #define UDDRC_STAT 0x04 /* SDRAM is not in Self-refresh */ #define UDDRC_STAT_SELFREF_TYPE_DIS SHIFT_U32(0, 4) /* SDRAM is in Self-refresh, which was caused by PHY Master Request */ #define UDDRC_STAT_SELFREF_TYPE_PHY SHIFT_U32(1, 4) /* SDRAM is in Self-refresh, which was not caused solely under * Automatic Self-refresh control */ #define UDDRC_STAT_SELFREF_TYPE_SW SHIFT_U32(2, 4) /* SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */ #define UDDRC_STAT_SELFREF_TYPE_AUTO SHIFT_U32(3, 4) #define UDDRC_STAT_SELFREF_TYPE_MSK GENMASK_32(5, 4) #define UDDRC_STAT_OPMODE_INIT 0 #define UDDRC_STAT_OPMODE_NORMAL 1 #define UDDRC_STAT_OPMODE_PWRDOWN 2 #define UDDRC_STAT_OPMODE_SELF_REFRESH 3 #define UDDRC_STAT_OPMODE_MSK GENMASK_32(2, 0) /* UDDRC Low Power Control Register */ #define UDDRC_PWRCTL 0x30 #define UDDRC_PWRCTL_SELFREF_EN BIT(0) /* Automatic self-refresh */ #define UDDRC_PWRCTL_SELFREF_SW BIT(5) /* Software self-refresh */ /* UDDRC DFI Miscellaneous Control Register */ #define UDDRC_DFIMISC 0x1B0 /* PHY initialization complete enable signal */ #define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) /* UDDRC Software Register Programming Control Enable */ #define UDDRC_SWCTRL 0x320 /* Enable quasi-dynamic register programming outside reset */ #define UDDRC_SWCTRL_SW_DONE BIT(0) /* UDDRC Software Register Programming Control Status */ #define UDDRC_SWSTAT 0x324 #define UDDRC_SWSTAT_SW_DONE_ACK BIT(0) /* Register programming done */ /* UDDRC Port Status Register */ #define UDDRC_PSTAT 0x3FC /* Read + writes outstanding transactions on all ports */ #define UDDRC_PSTAT_ALL_PORTS 0x1F001F #define UDDRC_PCTRL_0 0x490 /* Port 0 Control Register */ #define UDDRC_PCTRL_1 0x540 /* Port 1 Control Register */ #define UDDRC_PCTRL_2 0x5F0 /* Port 2 Control Register */ #define UDDRC_PCTRL_3 0x6A0 /* Port 3 Control Register */ #define UDDRC_PCTRL_4 0x750 /* Port 4 Control Register */ #endif /* __SAMA7_DDR_H__ */ optee_os-4.3.0/core/include/drivers/scif.h000066400000000000000000000033261464416617300205010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, GlobalLogic * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_SCIF_H #define __DRIVERS_SCIF_H #include #include #define SCIF_REG_SIZE 0x1000 struct scif_uart_data { struct io_pa_va base; struct serial_chip chip; }; void scif_uart_init(struct scif_uart_data *pd, paddr_t base); #endif /* __DRIVERS_SCIF_H */ optee_os-4.3.0/core/include/drivers/scmi-msg.h000066400000000000000000000305501464416617300212730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019-2021, Linaro Limited */ #ifndef __DRIVERS_SCMI_MSG_H #define __DRIVERS_SCMI_MSG_H #include #include #include #include #include #include /* Minimum size expected for SMT based shared memory message buffers */ #define SMT_BUF_SLOT_SIZE U(128) /* Standard values for SCMI voltage domain protocol configuration state */ #define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_ON U(0x7) #define SCMI_VOLTAGE_DOMAIN_CONFIG_ARCH_OFF U(0) /* A channel abstract a communication path between agent and server */ struct scmi_msg_channel; /* * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel * * @shm_addr: Address of the shared memory for the SCMI channel * @shm_size: Byte size of the shared memory for the SCMI channel * @busy: True when channel is busy, flase when channel is free * @threaded: True is executed in a threaded context, false otherwise */ struct scmi_msg_channel { struct io_pa_va shm_addr; size_t shm_size; bool busy; bool threaded; }; #ifdef CFG_SCMI_MSG_SMT /* * Initialize SMT memory buffer, called by platform at init for each * agent channel using the SMT header format. * This function depends on CFG_SCMI_MSG_SMT. * * @channel: Pointer to the channel shared memory to be initialized */ void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel); /* * Set SMT shared buffer location * * @channel: SCMI channel reference * @base: virtual address of the shared buffer or NULL to clear the reference */ void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel, void *base); #else static inline void scmi_smt_init_agent_channel(struct scmi_msg_channel *channel __unused) { panic(); } static inline void scmi_smt_set_shared_buffer(struct scmi_msg_channel *channel __unused, void *base __unused) { } #endif /* CFG_SCMI_MSG_SMT */ #ifdef CFG_SCMI_MSG_SMT_FASTCALL_ENTRY /* * Process SMT formatted message in a fastcall SMC execution context. * Called by platform on SMC entry. When returning, output message is * available in shared memory for agent to read the response. * This function depends on CFG_SCMI_MSG_SMT_FASTCALL_ENTRY. * * @channel_id: SCMI channel ID the SMT belongs to */ void scmi_smt_fastcall_smc_entry(unsigned int channel_id); #else static inline void scmi_smt_fastcall_smc_entry(unsigned int channel_id __unused) { } #endif #ifdef CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY /* * Process SMT formatted message in a secure interrupt execution context. * Called by platform interrupt handler. When returning, output message is * available in shared memory for agent to read the response. * This function depends on CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY. * * @channel_id: SCMI channel ID the SMT belongs to */ void scmi_smt_interrupt_entry(unsigned int channel_id); #else static inline void scmi_smt_interrupt_entry(unsigned int channel_id __unused) { } #endif #ifdef CFG_SCMI_MSG_SMT_THREAD_ENTRY /* * Process SMT formatted message in a TEE thread execution context. * When returning, output message is available in shared memory for * agent to read the response. * This function depends on CFG_SCMI_MSG_SMT_THREAD_ENTRY. * * @channel_id: SCMI channel ID the SMT belongs to */ void scmi_smt_threaded_entry(unsigned int channel_id); #else static inline void scmi_smt_threaded_entry(unsigned int channel_id __unused) { } #endif #ifdef CFG_SCMI_MSG_SHM_MSG /* * Process MSG formatted message in a TEE thread execution context. * When returning, output message is available in shared memory for * agent to read the response. * This function depends on CFG_SCMI_MSG_MSG_THREAD_ENTRY. * * @channel_id: SCMI channel ID * @in_buf: Shared buffer storing input SCMI message * @in_size: Byte size of @in_buf, including MSG header and message payload * @out_buf: Shared buffer storing input SCMI message * @out_size: [in] @out_buf max byte size * [out] @out_buf output byte size (MSG header and message payload) */ TEE_Result scmi_msg_threaded_entry(unsigned int channel_id, void *in_buf, size_t in_size, void *out_buf, size_t *out_size); #else static inline TEE_Result scmi_msg_threaded_entry(unsigned int chan_id __unused, void *in_buf __unused, size_t in_size __unused, void *out_buf __unused, size_t *out_size __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif struct clk; #ifdef CFG_SCMI_MSG_USE_CLK /* * Expose a clock through SCMI * @clk: Clock to be exposed * @channel_id: SCMI server channel exposing the clock * @scmi_id: SCMI ID of the clock within the channel */ TEE_Result scmi_clk_add(struct clk *clk, unsigned int channel_id, unsigned int scmi_id); #else static inline TEE_Result scmi_clk_add(struct clk *clk __unused, unsigned int channel_id __unused, unsigned int scmi_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* Platform callback functions */ /* * Return the SCMI channel related to an agent * @channel_id: SCMI channel ID * Return a pointer to channel on success, NULL otherwise */ struct scmi_msg_channel *plat_scmi_get_channel(unsigned int channel_id); /* Scmi-msg uses the channel ID as handle. Must channel_id is valid */ static inline unsigned int scmi_smt_channel_handle(unsigned int channel_id) { assert(plat_scmi_get_channel(channel_id)); return channel_id; } /* * Return how many SCMI protocols supported by the platform * According to the SCMI specification, this function does not target * a specific channel ID and shall return all platform known capabilities. */ size_t plat_scmi_protocol_count(void); /* * Get the count and list of SCMI protocols (but base) supported for an agent * * @channel_id: SCMI channel ID * Return a pointer to a null terminated array supported protocol IDs. */ const uint8_t *plat_scmi_protocol_list(unsigned int channel_id); /* Get the name of the SCMI vendor for the platform */ const char *plat_scmi_vendor_name(void); /* Get the name of the SCMI sub-vendor for the platform */ const char *plat_scmi_sub_vendor_name(void); /* Handlers for SCMI Clock protocol services */ /* * Return number of clock controllers for an agent * @channel_id: SCMI channel ID * Return number of clock controllers */ size_t plat_scmi_clock_count(unsigned int channel_id); /* * Get clock controller string ID (aka name) * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * Return pointer to name or NULL */ const char *plat_scmi_clock_get_name(unsigned int channel_id, unsigned int scmi_id); /* * Get clock possible rate as an array of frequencies in Hertz. * * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * @start_index: Requested start index for the exposed rates array * @rates: Output rates array or NULL if only querying @nb_elts * @nb_elts: [in] Array size of @rates, [out] Number of rates loaded in @rates * Return an SCMI compliant error code */ int32_t plat_scmi_clock_rates_array(unsigned int channel_id, unsigned int scmi_id, size_t start_index, unsigned long *rates, size_t *nb_elts); /* * Get clock possible rate as range with regular steps in Hertz * * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * @min_max_step: 3 cell array for min, max and step rate data * Return an SCMI compliant error code */ int32_t plat_scmi_clock_rates_by_step(unsigned int channel_id, unsigned int scmi_id, unsigned long *min_max_step); /* * Get clock rate in Hertz * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * Return clock rate or 0 if not supported */ unsigned long plat_scmi_clock_get_rate(unsigned int channel_id, unsigned int scmi_id); /* * Set clock rate in Hertz * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * @rate: Target clock frequency in Hertz * Return a compliant SCMI error code */ int32_t plat_scmi_clock_set_rate(unsigned int channel_id, unsigned int scmi_id, unsigned long rate); /* * Get clock state (enabled or disabled) * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code */ int32_t plat_scmi_clock_get_state(unsigned int channel_id, unsigned int scmi_id); /* * Get clock state (enabled or disabled) * @channel_id: SCMI channel ID * @scmi_id: SCMI clock ID * @enable_not_disable: Enable clock if true, disable clock otherwise * Return a compliant SCMI error code */ int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id, bool enable_not_disable); /* Handlers for SCMI Reset Domain protocol services */ /* * Return number of reset domains for the agent * @channel_id: SCMI channel ID * Return number of reset domains */ size_t plat_scmi_rd_count(unsigned int channel_id); /* * Get reset domain string ID (aka name) * @channel_id: SCMI channel ID * @scmi_id: SCMI reset domain ID * Return pointer to name or NULL */ const char *plat_scmi_rd_get_name(unsigned int channel_id, unsigned int scmi_id); /* * Perform a reset cycle on a target reset domain * @channel_id: SCMI channel ID * @scmi_id: SCMI reset domain ID * @state: Target reset state (see SCMI specification, 0 means context loss) * Return a compliant SCMI error code */ int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id, unsigned int state); /* * Assert or deassert target reset domain * @channel_id: SCMI channel ID * @scmi_id: SCMI reset domain ID * @assert_not_deassert: Assert domain if true, otherwise deassert domain * Return a compliant SCMI error code */ int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id, bool assert_not_deassert); /* Handlers for SCMI Voltage Domain protocol services */ /* * Return number of voltage domain for an agent * @channel_id: SCMI channel ID * Return number of voltage domains */ size_t plat_scmi_voltd_count(unsigned int channel_id); /* * Get voltage domain string ID (aka name) * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * Return pointer to name or NULL */ const char *plat_scmi_voltd_get_name(unsigned int channel_id, unsigned int scmi_id); /* * Get voltage domain possible levels as an array of voltages in microvolt. * * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * @start_index: Level index to start from. * @levels: If NULL, function returns, else output rates array * @nb_elts: Array size of @levels. * Return an SCMI compliant error code */ int32_t plat_scmi_voltd_levels_array(unsigned int channel_id, unsigned int scmi_id, size_t start_index, long *levels, size_t *nb_elts); /* * Get voltage domain possible levels as range with regular steps in microvolt * * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * @min_max_step: 3 cell array for min, max and step voltage data * Return an SCMI compliant error code */ int32_t plat_scmi_voltd_levels_by_step(unsigned int channel_id, unsigned int scmi_id, long *min_max_step); /* * Get current voltage domain level in microvolt * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * @level: Out parameter for the current voltage level * Return an SCMI compliant error code */ int32_t plat_scmi_voltd_get_level(unsigned int channel_id, unsigned int scmi_id, long *level); /* * Set voltage domain level voltage domain * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * @level: Target voltage domain level in microvolt * Return a compliant SCMI error code */ int32_t plat_scmi_voltd_set_level(unsigned int channel_id, unsigned int scmi_id, long level); /* * Get voltage domain state configuration (enabled or disabled) * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * @config: output state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* * Return a compliant SCMI error code */ int32_t plat_scmi_voltd_get_config(unsigned int channel_id, unsigned int scmi_id, uint32_t *config); /* * Get voltage domain state configuration (enabled or disabled) * @channel_id: SCMI channel ID * @scmi_id: SCMI voltage domain ID * @config: Target state configuration value SCMI_VOLTAGE_DOMAIN_CONFIG_* * Return a compliant SCMI error code */ int32_t plat_scmi_voltd_set_config(unsigned int channel_id, unsigned int scmi_id, uint32_t config); #endif /* __DRIVERS_SCMI_MSG_H */ optee_os-4.3.0/core/include/drivers/scmi.h000066400000000000000000000017271464416617300205130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. */ #ifndef __DRIVERS_SCMI_MSG_SCMI_H #define __DRIVERS_SCMI_MSG_SCMI_H #define SCMI_PROTOCOL_ID_BASE 0x10 #define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11 #define SCMI_PROTOCOL_ID_SYS_POWER 0x12 #define SCMI_PROTOCOL_ID_PERF 0x13 #define SCMI_PROTOCOL_ID_CLOCK 0x14 #define SCMI_PROTOCOL_ID_SENSOR 0x15 #define SCMI_PROTOCOL_ID_RESET_DOMAIN 0x16 #define SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN 0x17 /* SCMI error codes reported to agent through server-to-agent messages */ #define SCMI_SUCCESS 0 #define SCMI_NOT_SUPPORTED (-1) #define SCMI_INVALID_PARAMETERS (-2) #define SCMI_DENIED (-3) #define SCMI_NOT_FOUND (-4) #define SCMI_OUT_OF_RANGE (-5) #define SCMI_BUSY (-6) #define SCMI_COMMS_ERROR (-7) #define SCMI_GENERIC_ERROR (-8) #define SCMI_HARDWARE_ERROR (-9) #define SCMI_PROTOCOL_ERROR (-10) #endif /* __DRIVERS_SCMI_MSG_SCMI_H */ optee_os-4.3.0/core/include/drivers/semihosting_console.h000066400000000000000000000013251464416617300236250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024 Andes Technology Corporation */ #ifndef __DRIVERS_SEMIHOSTING_CONSOLE_H #define __DRIVERS_SEMIHOSTING_CONSOLE_H #ifdef CFG_SEMIHOSTING_CONSOLE /* * Initialize console which uses architecture-specific semihosting mechanism. * If @file_path is not NULL, OP-TEE OS will try to output log to that file, * which is on the semihosting host system. * Otherwise, if @file_path is NULL, OP-TEE OS will try to output log to the * semihosting host debug console. */ void semihosting_console_init(const char *file_path); #else static inline void semihosting_console_init(const char *file_path __unused) { } #endif #endif /* __DRIVERS_SEMIHOSTING_CONSOLE_H */ optee_os-4.3.0/core/include/drivers/serial.h000066400000000000000000000026161464416617300210350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __DRIVERS_SERIAL_H #define __DRIVERS_SERIAL_H #include #include #include #include #include struct serial_chip { const struct serial_ops *ops; }; struct serial_ops { /* Mandatory handler */ void (*putc)(struct serial_chip *chip, int ch); /* Optional handlers */ void (*flush)(struct serial_chip *chip); bool (*have_rx_data)(struct serial_chip *chip); int (*getchar)(struct serial_chip *chip); void (*rx_intr_enable)(struct serial_chip *chip); void (*rx_intr_disable)(struct serial_chip *chip); }; struct serial_driver { /* Allocate device data and return the inner serial_chip */ struct serial_chip *(*dev_alloc)(void); /* * Initialize device from FDT node. @parms is device-specific, * its meaning is as defined by the DT bindings for the characters * following the ":" in /chosen/stdout-path. Typically for UART * devices this is {{{}}} where: * baud - baud rate in decimal * parity - 'n' (none), 'o', (odd) or 'e' (even) * bits - number of data bits * flow - 'r' (rts) * For example: 115200n8r */ int (*dev_init)(struct serial_chip *dev, const void *fdt, int offset, const char *parms); void (*dev_free)(struct serial_chip *dev); }; #endif /*__DRIVERS_SERIASERIAL_H*/ optee_os-4.3.0/core/include/drivers/serial8250_uart.h000066400000000000000000000007611464416617300224060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __DRIVERS_SERIAL8250_UART_H #define __DRIVERS_SERIAL8250_UART_H #include #include #define SERIAL8250_UART_REG_SIZE 0x20 struct serial8250_uart_data { struct io_pa_va base; struct serial_chip chip; }; void serial8250_uart_init(struct serial8250_uart_data *pd, paddr_t base, uint32_t uart_clk, uint32_t baud_rate); #endif /* __DRIVERS_SERIAL8250_UART_H */ optee_os-4.3.0/core/include/drivers/sp805_wdt.h000066400000000000000000000035301464416617300213070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef __DRIVERS_SP805_WDT_H #define __DRIVERS_SP805_WDT_H #include #include #include #include /* SP805 register offset */ #define WDT_LOAD_OFFSET 0x000 #define WDT_CONTROL_OFFSET 0x008 #define WDT_INTCLR_OFFSET 0x00c #define WDT_LOCK_OFFSET 0xc00 #define WDT_SIZE 0xc04 /* Magic word to unlock the wd registers */ #define WDT_UNLOCK_KEY 0x1ACCE551 #define WDT_LOCK_KEY 0x1 /* Register field definitions */ #define WDT_INT_EN BIT(0) #define WDT_RESET_EN BIT(1) #define WDT_INT_CLR BIT(0) #define WDT_LOAD_MIN 0x1 typedef void (*sp805_itr_handler_func_t)(struct wdt_chip *chip); struct sp805_wdt_data { struct io_pa_va base; struct wdt_chip chip; uint32_t clk_rate; uint32_t load_val; uint32_t itr_num; sp805_itr_handler_func_t itr_handler; }; /* * Initialize sp805 watchdog timer * * @pd: allocated sp805 watchdog timer platform data * @base: physical base address of sp805 watchdog timer * @clk_rate: rate of the clock driving the watchdog timer hardware * @timeout: watchdog timer timeout in seconds * Return a TEE_Result compliant status */ TEE_Result sp805_wdt_init(struct sp805_wdt_data *pd, paddr_t base, uint32_t clk_rate, uint32_t timeout); /* * Optionally register sp805 watchdog timer interrupt handler * * @pd: platform data of sp805 watchdog timer for which interrupt handler * is to be registered * @itr_num: sp805 watchdog timer interrupt id * @itr_flag: interrupt attributes * @itr_handler: Optional interrupt handler callback * Return a TEE_Result compliant status */ TEE_Result sp805_register_itr_handler(struct sp805_wdt_data *pd, uint32_t itr_num, uint32_t itr_flag, sp805_itr_handler_func_t itr_handler); #endif /* __DRIVERS_SP805_WDT_H */ optee_os-4.3.0/core/include/drivers/sprd_uart.h000066400000000000000000000033331464416617300215560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Spreadtrum Communications Inc. * Copyright (c) 2017, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_SPRD_UART_H #define __DRIVERS_SPRD_UART_H #include #include struct sprd_uart_data { struct io_pa_va base; struct serial_chip chip; }; void sprd_uart_init(struct sprd_uart_data *pd, paddr_t base); #endif /* __DRIVERS_SPRD_UART_H */ optee_os-4.3.0/core/include/drivers/stih_asc.h000066400000000000000000000006221464416617300213460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __DRIVERS_STIH_ASC_H #define __DRIVERS_STIH_ASC_H #include #include #define STIH_ASC_REG_SIZE 0x1000 struct stih_asc_pd { struct io_pa_va base; struct serial_chip chip; }; void stih_asc_init(struct stih_asc_pd *pb, vaddr_t base); #endif /* __DRIVERS_STIH_ASC_H */ optee_os-4.3.0/core/include/drivers/stm32_bsec.h000066400000000000000000000124401464416617300215160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2017-2022, STMicroelectronics */ #ifndef __DRIVERS_STM32_BSEC_H #define __DRIVERS_STM32_BSEC_H #include #include #include /* BSEC_DEBUG */ #define BSEC_HDPEN BIT(4) #define BSEC_SPIDEN BIT(5) #define BSEC_SPINDEN BIT(6) #define BSEC_DBGSWGEN BIT(10) #define BSEC_DEBUG_ALL (BSEC_HDPEN | \ BSEC_SPIDEN | \ BSEC_SPINDEN | \ BSEC_DBGSWGEN) #define BSEC_BITS_PER_WORD (8U * sizeof(uint32_t)) #define BSEC_BYTES_PER_WORD sizeof(uint32_t) /* BSEC different global states */ enum stm32_bsec_sec_state { BSEC_STATE_SEC_CLOSED, BSEC_STATE_SEC_OPEN, BSEC_STATE_INVALID }; /* * Load OTP from SAFMEM and provide its value * @value: Output read value * @otp_id: OTP number * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_shadow_read_otp(uint32_t *value, uint32_t otp_id); /* * Copy SAFMEM OTP to BSEC data. * @otp_id: OTP number. * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_shadow_register(uint32_t otp_id); /* * Read an OTP data value * @value: Output read value * @otp_id: OTP number * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_read_otp(uint32_t *value, uint32_t otp_id); /* * Write value in BSEC data register * @value: Value to write * @otp_id: OTP number * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id); /* * Program a bit in SAFMEM without BSEC data refresh * @value: Value to program. * @otp_id: OTP number. * Return a TEE_Result compliant return value */ #ifdef CFG_STM32_BSEC_WRITE TEE_Result stm32_bsec_program_otp(uint32_t value, uint32_t otp_id); #else static inline TEE_Result stm32_bsec_program_otp(uint32_t value __unused, uint32_t otp_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* * Permanent lock of OTP in SAFMEM * @otp_id: OTP number * Return a TEE_Result compliant return value */ #ifdef CFG_STM32_BSEC_WRITE TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id); #else static inline TEE_Result stm32_bsec_permanent_lock_otp(uint32_t otp_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* * Enable/disable debug service * @value: Value to write * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_write_debug_conf(uint32_t value); /* Return debug configuration read from BSEC */ uint32_t stm32_bsec_read_debug_conf(void); /* * Write shadow-read lock * @otp_id: OTP number * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_set_sr_lock(uint32_t otp_id); /* * Read shadow-read lock * @otp_id: OTP number * @locked: (out) true if shadow-read is locked, false if not locked. * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_read_sr_lock(uint32_t otp_id, bool *locked); /* * Write shadow-write lock * @otp_id: OTP number * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_set_sw_lock(uint32_t otp_id); /* * Read shadow-write lock * @otp_id: OTP number * @locked: (out) true if shadow-write is locked, false if not locked. * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_read_sw_lock(uint32_t otp_id, bool *locked); /* * Write shadow-program lock * @otp_id: OTP number * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_set_sp_lock(uint32_t otp_id); /* * Read shadow-program lock * @otp_id: OTP number * @locked: (out) true if shadow-program is locked, false if not locked. * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_read_sp_lock(uint32_t otp_id, bool *locked); /* * Read permanent lock status * @otp_id: OTP number * @locked: (out) true if permanent lock is locked, false if not locked. * Return a TEE_Result compliant return value */ TEE_Result stm32_bsec_read_permanent_lock(uint32_t otp_id, bool *locked); /* * Return true if OTP can be read, false otherwise * @otp_id: OTP number */ bool stm32_bsec_can_access_otp(uint32_t otp_id); /* * Return true if non-secure world is allowed to read the target OTP * @otp_id: OTP number */ bool stm32_bsec_nsec_can_access_otp(uint32_t otp_id); /* * Find and get OTP location from its name. * @name: sub-node name to look up. * @otp_id: pointer to output OTP number or NULL. * @otp_bit_offset: pointer to output OTP bit offset in the NVMEM cell or NULL. * @otp_bit_len: pointer to output OTP length in bits or NULL. * Return a TEE_Result compliant status */ TEE_Result stm32_bsec_find_otp_in_nvmem_layout(const char *name, uint32_t *otp_id, uint8_t *otp_bit_offset, size_t *otp_bit_len); /* * Find and get OTP location from its phandle. * @phandle: node phandle to look up. * @otp_id: pointer to read OTP number or NULL. * @otp_bit_offset: pointer to read offset in OTP in bits or NULL. * @otp_bit_len: pointer to read OTP length in bits or NULL. * Return a TEE_Result compliant status */ TEE_Result stm32_bsec_find_otp_by_phandle(const uint32_t phandle, uint32_t *otp_id, uint8_t *otp_bit_offset, size_t *otp_bit_len); /* * Get BSEC global sec state. * @sec_state: Global BSEC current sec state * Return a TEE_Result compliant status */ TEE_Result stm32_bsec_get_state(enum stm32_bsec_sec_state *sec_state); #endif /*__DRIVERS_STM32_BSEC_H*/ optee_os-4.3.0/core/include/drivers/stm32_etzpc.h000066400000000000000000000042031464416617300217250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2018-2019, STMicroelectronics */ #ifndef __DRIVERS_STM32_ETZPC_H #define __DRIVERS_STM32_ETZPC_H #include #include enum etzpc_decprot_attributes { ETZPC_DECPROT_S_RW = 0, ETZPC_DECPROT_NS_R_S_W = 1, ETZPC_DECPROT_MCU_ISOLATION = 2, ETZPC_DECPROT_NS_RW = 3, ETZPC_DECPROT_MAX = 4, }; #define ETZPC_TZMA_ALL_SECURE GENMASK_32(9, 0) #define ETZPC_TZMA_ALL_NO_SECURE 0x0 /* * Load a DECPROT configuration * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface * @decprot_attr: Restriction access attributes */ void etzpc_configure_decprot(uint32_t decprot_id, enum etzpc_decprot_attributes decprot_attr); /* * Get the DECPROT attribute * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface * Return attribute of this DECPROT */ enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id); /* * Lock access to the DECPROT attributes * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface */ void etzpc_lock_decprot(uint32_t decprot_id); /* * Return the lock status of the target DECPROT * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface */ bool etzpc_get_lock_decprot(uint32_t decprot_id); /* * Configure the target TZMA read only size * @tzma_id: ID that is the index of the TZMA in the ETZPC interface * @tzma_value: Read-only size */ void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value); /* * Get the target TZMA read only size * @tzma_id: ID that is the index of the TZMA in the ETZPC interface * Return the size of read-only area */ uint16_t etzpc_get_tzma(uint32_t tzma_id); /* * Lock the target TZMA * @tzma_id: ID that is the index of the TZMA in the ETZPC interface */ void etzpc_lock_tzma(uint32_t tzma_id); /* * Return the lock status of the target TZMA * @tzma_id: ID that is the index of the TZMA in the ETZPC interface * Return true if TZMA is locked, false otherwise */ bool etzpc_get_lock_tzma(uint32_t tzma_id); #endif /*__DRIVERS_STM32_ETZPC_H*/ optee_os-4.3.0/core/include/drivers/stm32_gpio.h000066400000000000000000000032721464416617300215430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2017-2023, STMicroelectronics */ #ifndef __DRIVERS_STM32_GPIO_H #define __DRIVERS_STM32_GPIO_H #include #include #include #include #include struct pinctrl_state; struct stm32_pinctrl; #ifdef CFG_STM32_GPIO /* * Configure pin muxing access permission: can be secure or not * * @bank: GPIO bank identifier as assigned by the platform * @pin: Pin number in the GPIO bank * @secure: True if pin is secure, false otherwise */ void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin, bool secure); /* * Configure pin muxing access permission: can be secure or not * * @pinctrl: Pin control state where STM32_GPIO pin are to configure * @secure: True if pin is secure, false otherwise */ void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure); /* * Get the bank and pin indices related to a pin control state * @pinctrl: Pinctrl state * @bank: Output bank indices array or NULL * @pin: Output pin indices array or NULL * @count: [in] Number of cells of @bank and @pin, [out] pin count in @pinctrl */ void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl, unsigned int *bank, unsigned int *pin, unsigned int *count); #else static inline void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl __unused, bool secure __unused) { } static inline void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *p __unused, unsigned int *bank __unused, unsigned int *pin __unused, unsigned int *count __unused) { } #endif /*CFG_STM32_GPIO*/ #endif /*__DRIVERS_STM32_GPIO_H*/ optee_os-4.3.0/core/include/drivers/stm32_i2c.h000066400000000000000000000215221464416617300212600ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Copyright (c) 2017-2023, STMicroelectronics */ #ifndef __DRIVERS_STM32_I2C_H #define __DRIVERS_STM32_I2C_H #include #include #include #include #include #include #include #include #include #include #include /* * I2C specification values as per version 6.0, 4th of April 2014 [1], * table 10 page 48: Characteristics of the SDA and SCL bus lines for * Standard, Fast, and Fast-mode Plus I2C-bus devices. * * [1] https://www.nxp.com/docs/en/user-guide/UM10204.pdf */ #define I2C_STANDARD_RATE U(100000) #define I2C_FAST_RATE U(400000) #define I2C_FAST_PLUS_RATE U(1000000) /* * struct stm32_i2c_init_s - STM32 I2C configuration data * * @dt_status: non-secure/secure status read from DT * @pbase: I2C interface base address * @reg_size: I2C interface register map size * @clock: I2C bus/interface clock * @addr_mode_10b_not_7b: True if 10bit addressing mode, otherwise 7bit mode * @own_address1: 7-bit or 10-bit first device own address. * @dual_address_mode: True if enabling Dual-Addressing mode * @own_address2: 7-bit second device own address (Dual-Addressing mode) * @own_address2_masks: Acknowledge mask address (Dual-Addressing mode) * @general_call_mode: True if enbling General-Call mode * @no_stretch_mode: If enabling the No-Stretch mode * @rise_time: SCL clock pin rising time in nanoseconds * @fall_time: SCL clock pin falling time in nanoseconds * @bus_rate: Specifies the I2C clock frequency in Hertz * @analog_filter: True if enabling analog filter * @digital_filter_coef: filter coef (below STM32_I2C_DIGITAL_FILTER_MAX) */ struct stm32_i2c_init_s { unsigned int dt_status; paddr_t pbase; size_t reg_size; struct clk *clock; bool addr_mode_10b_not_7b; uint32_t own_address1; bool dual_address_mode; uint32_t own_address2; uint32_t own_address2_masks; bool general_call_mode; bool no_stretch_mode; uint32_t rise_time; uint32_t fall_time; uint32_t bus_rate; bool analog_filter; uint8_t digital_filter_coef; }; enum i2c_state_e { I2C_STATE_RESET, /* Not yet initialized */ I2C_STATE_READY, /* Ready for use */ I2C_STATE_BUSY, /* Internal process ongoing */ I2C_STATE_BUSY_TX, /* Data Transmission ongoing */ I2C_STATE_BUSY_RX, /* Data Reception ongoing */ I2C_STATE_SUSPENDED, /* Bus is supended */ }; enum i2c_mode_e { I2C_MODE_NONE, /* No active communication */ I2C_MODE_MASTER, /* Communication in Master Mode */ I2C_MODE_SLAVE, /* Communication in Slave Mode */ I2C_MODE_MEM, /* Communication in Memory Mode */ }; #define I2C_ERROR_NONE U(0x0) #define I2C_ERROR_BERR BIT(0) #define I2C_ERROR_ARLO BIT(1) #define I2C_ERROR_ACKF BIT(2) #define I2C_ERROR_OVR BIT(3) #define I2C_ERROR_DMA BIT(4) #define I2C_ERROR_TIMEOUT BIT(5) #define I2C_ERROR_SIZE BIT(6) /* I2C interface registers state */ struct i2c_cfg { uint32_t timingr; uint32_t oar1; uint32_t oar2; uint32_t cr1; uint32_t cr2; }; /* * I2C bus device * @base: I2C SoC registers base address * @reg_size: I2C SoC registers address map size * @dt_status: non-secure/secure status read from DT * @clock: clock ID * @i2c_state: Driver state ID I2C_STATE_* * @i2c_err: Last error code I2C_ERROR_* * @saved_timing: Saved timing value if already computed * @saved_frequency: Saved frequency value if already computed * @sec_cfg: I2C registers configuration storage * @pinctrl: Pin control configuration for the I2C bus in active state * @pinctrl_sleep: Pin control configuration for the I2C bus in standby state * @mu: Protection on concurrent access to the I2C bus considering PM context */ struct i2c_handle_s { struct io_pa_va base; size_t reg_size; unsigned int dt_status; struct clk *clock; enum i2c_state_e i2c_state; uint32_t i2c_err; uint32_t saved_timing; unsigned long saved_frequency; struct i2c_cfg sec_cfg; struct pinctrl_state *pinctrl; struct pinctrl_state *pinctrl_sleep; struct mutex_pm_aware mu; }; /* * struct stm32_i2c_dev - Bus consumer device over an STM32 I2C bus * @i2c_dev: I2C consumer instance * @i2c_ctrl: I2C bus control operation * @handle: Handle on a single STM32 I2C bus interface */ struct stm32_i2c_dev { struct i2c_dev i2c_dev; struct i2c_ctrl i2c_ctrl; struct i2c_handle_s *handle; }; /* STM32 specific defines */ #define STM32_I2C_RISE_TIME_DEFAULT U(25) /* ns */ #define STM32_I2C_FALL_TIME_DEFAULT U(10) /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MIN U(50) /* ns */ #define STM32_I2C_ANALOG_FILTER_DELAY_MAX U(260) /* ns */ #define STM32_I2C_DIGITAL_FILTER_MAX U(16) /* * Fill struct stm32_i2c_init_s from DT content for a given I2C node * * @fdt: Reference to DT * @node: Target I2C node in the DT * @init: Output stm32_i2c_init_s structure * @pinctrl_active: Output active I2C pinctrl state * @pinctrl_sleep: Output suspended I2C pinctrl state * Return a TEE_Result compliant value */ TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node, struct stm32_i2c_init_s *init, struct pinctrl_state **pinctrl_active, struct pinctrl_state **pinctrl_sleep); /* * Initialize I2C bus handle from input configuration directives * * @hi2c: Reference to I2C bus handle structure * @init_data: Input stm32_i2c_init_s structure * Return 0 on success else a negative value */ int stm32_i2c_init(struct i2c_handle_s *hi2c, struct stm32_i2c_init_s *init_data); /* * Send a memory write request in the I2C bus * * @hi2c: Reference to I2C bus handle structure * @dev_addr: Target device I2C address * @mem_addr: Target device memory address * @mem_addr_size: Byte size of internal memory address * @p_data: Data to be written * @size: Byte size of the data to be written * @timeout_ms: Timeout value in milliseconds * Return 0 on success else a negative value */ int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint32_t mem_addr, uint32_t mem_addr_size, uint8_t *p_data, size_t size, unsigned int timeout_ms); /* * Send a memory read request in the I2C bus * * @hi2c: Reference to I2C bus handle structure * @dev_addr: Target device I2C address * @mem_addr: Target device memory address * @mem_addr_size: Byte size of internal memory address * @p_data: Data to be read * @size: Byte size of the data to be read * @timeout_ms: Timeout value in milliseconds * Return 0 on success else a negative value */ int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint32_t mem_addr, uint32_t mem_addr_size, uint8_t *p_data, size_t size, unsigned int timeout_ms); /* * Send a data buffer in master mode on the I2C bus * * @hi2c: Reference to I2C bus handle structure * @dev_addr: Target device I2C address * @p_data: Data to be sent * @size: Byte size of the data to be sent * @timeout_ms: Timeout value in milliseconds * Return 0 on success else a negative value */ int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint8_t *p_data, size_t size, unsigned int timeout_ms); /* * Receive a data buffer in master mode on the I2C bus * * @hi2c: Reference to I2C bus handle structure * @dev_addr: Target device I2C address * @p_data: Buffer for the received data * @size: Byte size of the data to be received * @timeout_ms: Timeout value in milliseconds * Return 0 on success else a negative value */ int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint32_t dev_addr, uint8_t *p_data, size_t size, unsigned int timeout_ms); /* * Optimized 1 byte read/write function for unpaged sequences. * 8-bit addressing mode / single byte transferred / use default I2C timeout. * Return 0 on success else a negative value */ int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr, unsigned int mem_addr, uint8_t *p_data, bool write); /* * Check link with the I2C device * * @hi2c: Reference to I2C bus handle structure * @dev_addr: Target device I2C address * @trials: Number of attempts of I2C request * @timeout_ms: Timeout value in milliseconds for each I2C request * Return 0 on success else a negative value */ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr, unsigned int trials, unsigned int timeout_ms); /* * Suspend I2C bus. * Bus owner is reponsible for calling stm32_i2c_suspend(). * * @hi2c: Reference to I2C bus handle structure */ void stm32_i2c_suspend(struct i2c_handle_s *hi2c); /* * Resume I2C bus. * Bus owner is reponsible for calling stm32_i2c_resume(). * * @hi2c: Reference to I2C bus handle structure */ void stm32_i2c_resume(struct i2c_handle_s *hi2c); /* * Return true if I2C bus is enabled for secure world only, false otherwise */ static inline bool i2c_is_secure(struct i2c_handle_s *hi2c) { return hi2c->dt_status == DT_STATUS_OK_SEC; } #endif /* __DRIVERS_STM32_I2C_H*/ optee_os-4.3.0/core/include/drivers/stm32_iwdg.h000066400000000000000000000015141464416617300215340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved */ #ifndef __DRIVERS_STM32_IWDG_H #define __DRIVERS_STM32_IWDG_H #include /* * struct stm32_iwdg_otp_data - Fuses configuration related to an IWDG * @hw_enabled - IWDDG instance is enabled by early hardware boot stage * @disable_on_stop - IWDG instance freezes when SoC is in STOP mode * @disable_on_standby - IWDG instance freezes when SoC is in STANDBY mode */ struct stm32_iwdg_otp_data { bool hw_enabled; bool disable_on_stop; bool disable_on_standby; }; /* * Platform shall implement this function for IWDG instance to retrieve its * OTP/fuse configuration. */ TEE_Result stm32_get_iwdg_otp_config(paddr_t pbase, struct stm32_iwdg_otp_data *otp_data); #endif /*__DRIVERS_STM32_IWDG_H*/ optee_os-4.3.0/core/include/drivers/stm32_remoteproc.h000066400000000000000000000043121464416617300227600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, STMicroelectronics - All Rights Reserved */ #ifndef __DRIVERS_STM32_REMOTEPROC_H #define __DRIVERS_STM32_REMOTEPROC_H #include #include #include /* IDs of the supported remote processors*/ #define STM32_M4_RPROC_ID 0 /* * stm32_rproc_get() - get the rproc handle associated to a remote processor ID * @rproc_id unique identifier of the remote processor * Return a pointer to the rproc firmware handle related to @rproc_id or NULL. */ void *stm32_rproc_get(uint32_t rproc_id); /* * stm32_rproc_da_to_pa() - Convert the coprocessor device address to a CPU * physical address. * @rproc_id unique identifier of the remote processor * @da device memory address from the remote processor space * perspective. * @size size of the memory * @pa Output CPU physical address associated to @da. * Return TEE_SUCCESS or appropriate error. */ TEE_Result stm32_rproc_da_to_pa(uint32_t rproc_id, paddr_t da, size_t size, paddr_t *pa); /* * stm32_rproc_map() - map the physical address if valid * @rproc_id unique identifier of the remote processor * @pa physical address from the CPU space perspective * @size size of the memory * @va Output CPU virtual address associated to @pa. * Return TEE_SUCCESS or appropriate error. */ TEE_Result stm32_rproc_map(uint32_t rproc_id, paddr_t pa, size_t size, void **va); /* * stm32_rproc_unmap() - ummap the virtual address mapped with stm32_rproc_map * @rproc_id unique identifier of the remote processor * @va virtual address * @size size of the memory * Return TEE_SUCCESS or appropriate error. */ TEE_Result stm32_rproc_unmap(uint32_t rproc_id, void *va, size_t size); /* * stm32_rproc_start() - start the remote processor core * @rproc_id unique identifier of the remote processor * Return TEE_SUCCESS or appropriate error. */ TEE_Result stm32_rproc_start(uint32_t rproc_id); /* * stm32_rproc_stop() - stop the remote processor core * @rproc_id unique identifier of the remote processor * Return TEE_SUCCESS or appropriate error. */ TEE_Result stm32_rproc_stop(uint32_t rproc_id); #endif /* __DRIVERS_STM32_REMOTEPROC_H */ optee_os-4.3.0/core/include/drivers/stm32_rif.h000066400000000000000000000137201464416617300213640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022-2024, STMicroelectronics */ #ifndef __DRIVERS_STM32_RIF_H #define __DRIVERS_STM32_RIF_H #include #include #include #include /* * CIDCFGR register */ #define _CIDCFGR_CFEN BIT(0) #define _CIDCFGR_SEMEN BIT(1) #define _CIDCFGR_SEMWL(x) BIT(SEMWL_SHIFT + (x)) /* * SEMCR register */ #define _SEMCR_MUTEX BIT(0) #define _SEMCR_SEMCID_SHIFT U(4) #define _SEMCR_SEMCID_MASK GENMASK_32(6, 4) /* * Miscellaneous */ #define MAX_CID_SUPPORTED U(8) #define SCID_SHIFT U(4) #define SEMWL_SHIFT U(16) #define RIF_ID_SHIFT U(24) #define RIF_ID_MASK GENMASK_32(31, 24) #define RIF_CHANNEL_ID(x) ((RIF_ID_MASK & (x)) >> RIF_ID_SHIFT) #define RIFPROT_SEC BIT(8) #define RIFPROT_PRIV BIT(9) #define RIFPROT_LOCK BIT(10) /** * struct rif_conf_data - Structure containing RIF configuration data * * @access_mask: Array of the masks of the registers which will be configured. * @sec_conf: Secure configuration registers. * @priv_conf: Privilege configuration registers. * @cid_confs: CID filtering configuration register value for a peripheral * resource (e.g: GPIO pins, FMC controllers) * @lock_conf: RIF configuration locking registers * * For a hardware block having 56 channels, there will be 56 cid_confs * registers and 2 sec_conf and priv_conf registers */ struct rif_conf_data { uint32_t *access_mask; uint32_t *sec_conf; uint32_t *priv_conf; uint32_t *cid_confs; uint32_t *lock_conf; }; #ifdef CFG_STM32_RIF /** * stm32_rif_scid_ok() - Check if a given static CID configuration authorizes * access to a given CID * * @cidcfgr: Value of the CIDCFGR register * @scid_m: Mask of the static CID in the register * @cid_to_check: CID of the target compartment * * Returns true if given CID is authorized, false otherwise. */ static inline bool stm32_rif_scid_ok(uint32_t cidcfgr, uint32_t scid_m, uint32_t cid_to_check) { return (cidcfgr & scid_m) == SHIFT_U32(cid_to_check, SCID_SHIFT) && !(cidcfgr & _CIDCFGR_SEMEN); } /** * stm32_rif_semaphore_enabled_and_ok() - Check if semaphore mode is enabled and * that a given CID can request the * semaphore ownership * * @cidcfgr: Value of the cidcfgr register * @cid_to_check: CID to check * * Returns true if the requested CID can request the semaphore ownership, * false otherwise. */ static inline bool stm32_rif_semaphore_enabled_and_ok(uint32_t cidcfgr, uint32_t cid_to_check) { return (cidcfgr & _CIDCFGR_CFEN) && (cidcfgr & _CIDCFGR_SEMEN) && (cidcfgr & _CIDCFGR_SEMWL(cid_to_check)); } /** * stm32_rifsc_check_tdcid() - Check if the execution context is TDCID or not * * @tdcid_state: [out] Set to true if TDCID, false otherwise. * * Returns TEE_ERROR_DEFER_DRIVER_INIT if RIFSC driver isn't probed, TEE_SUCCESS * otherwise. */ TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state); /** * stm32_rif_check_access() - Test peripheral access for a given compartment * * @cidcfgr: CIDCFGR configuration register value * @semcr: SEMCR register value * @nb_cid_supp: Number of supported CID for the peripheral * @cid_to_check: CID of the target compartment * * Returns TEE_SUCCESS if access is authorized, a TEE_Result error value * otherwise. */ TEE_Result stm32_rif_check_access(uint32_t cidcfgr, uint32_t semcr, unsigned int nb_cid_supp, unsigned int cid_to_check); /** * stm32_rif_parse_cfg() - Parse RIF config from Device Tree extracted * information * * @rif_conf: Configuration read in the device tree * @conf_data: Buffer containing the RIF configuration to apply for a peripheral * @nb_cid_supp: Number of supported CID for the peripheral * @nb_channel: Number of channels for the peripheral */ void stm32_rif_parse_cfg(uint32_t rif_conf, struct rif_conf_data *conf_data, unsigned int nb_cid_supp, unsigned int nb_channel); /** * stm32_rif_semaphore_is_available() - Checks if the _SEMCR_MUTEX bit is set * * @addr: Address of the register to read from */ bool stm32_rif_semaphore_is_available(vaddr_t addr); /** * stm32_rif_semaphore_is_available() - Acquires the semaphore by setting the * _SEMCR_MUTEX bit * * @addr: Address of the register to write to * @nb_cid_supp: Number of CID supported */ TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr, unsigned int nb_cid_supp); /** * stm32_rif_semaphore_is_available() - Releases the semaphore by clearing the * _SEMCR_MUTEX bit * * @addr: Address of the register to write to * @nb_cid_supp: Number of CID supported */ TEE_Result stm32_rif_release_semaphore(vaddr_t addr, unsigned int nb_cid_supp); #else static inline bool stm32_rif_scid_ok(uint32_t cidcfgr, uint32_t scid_m, uint32_t cid_to_check) { return true; } static inline bool stm32_rif_semaphore_enabled_and_ok(uint32_t cidcfgr, uint32_t cid_to_check) { return true; } static inline TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state) { /* Without CFG_STM32_RIF every CPU can behave as TDCID */ *tdcid_state = true; return TEE_SUCCESS; } static inline TEE_Result stm32_rif_check_access(uint32_t cidcfgr __unused, uint32_t semcr __unused, unsigned int nb_cid_supp __unused, unsigned int cid_to_check __unused) { return TEE_SUCCESS; } static inline void stm32_rif_parse_cfg(uint32_t rif_conf __unused, struct rif_conf_data *conf_data __unused, unsigned int nb_cid_supp __unused, unsigned int nb_channel __unused) { } static inline bool stm32_rif_semaphore_is_available(vaddr_t addr __unused) { return true; } static inline TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr __unused, unsigned int nb_cid_supp __unused) { return TEE_SUCCESS; } static inline TEE_Result stm32_rif_release_semaphore(vaddr_t addr __unused, unsigned int nb_cid_supp __unused) { return TEE_SUCCESS; } #endif /* CFG_STM32_RIF */ #endif /* __DRIVERS_STM32_RIF_H */ optee_os-4.3.0/core/include/drivers/stm32_shared_io.h000066400000000000000000000013551464416617300225420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, STMicroelectronics */ #ifndef __DRIVERS_STM32_SHARED_IO_H__ #define __DRIVERS_STM32_SHARED_IO_H__ #include #include /* * Shared registers support: common lock for accessing SoC registers * shared between several drivers. */ void io_clrsetbits32_stm32shregs(vaddr_t va, uint32_t clr, uint32_t set); void io_mask32_stm32shregs(vaddr_t va, uint32_t value, uint32_t mask); static inline void io_setbits32_stm32shregs(vaddr_t va, uint32_t value) { io_mask32_stm32shregs(va, value, value); } static inline void io_clrbits32_stm32shregs(vaddr_t va, uint32_t value) { io_mask32_stm32shregs(va, 0, value); } #endif /* __DRIVERS_STM32_SHARED_IO_H__ */ optee_os-4.3.0/core/include/drivers/stm32_tamp.h000066400000000000000000000033421464416617300215440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2021-2022, STMicroelectronics */ #ifndef __DRIVERS_STM32_TAMP_H__ #define __DRIVERS_STM32_TAMP_H__ #include #include #include /* * struct stm32_bkpregs_conf - Interface for stm32_tamp_set_secure_bkpregs() * @nb_zone1_regs - Number of backup registers in zone 1 * @nb_zone2_regs - Number of backup registers in zone 2 * * TAMP backup registers access permissions * * Zone 1: read/write in secure state, no access in non-secure state * Zone 2: read/write in secure state, read-only in non-secure state * Zone 3: read/write in secure state, read/write in non-secure state * * Protection zone 1 * If nb_zone1_regs == 0 no backup register are in zone 1. * Otherwise backup registers from TAMP_BKP0R to TAMP_BKPR are in zone 1, * with = (@nb_zone1_regs - 1). * * Protection zone 2 * If nb_zone2_regs == 0 no backup register are in zone 2. * Otherwise backup registers from TAMP_BKPR ro TAMP_BKPR are in zone 2, * with = @nb_zone1_regs and = (@nb_zone1_regs1 + @nb_zone2_regs - 1). * * Protection zone 3 * Backup registers from TAMP_BKPR to last backup register are in zone 3, * with = (@nb_zone1_regs1 + @nb_zone2_regs). */ struct stm32_bkpregs_conf { uint32_t nb_zone1_regs; uint32_t nb_zone2_regs; }; #ifdef CFG_STM32_TAMP /* * stm32_tamp_set_secure_bkprwregs() - Configure backup registers zone. * @conf - Configuration to be programmed */ TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *conf); #else static inline TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *c __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif #endif /* __DRIVERS_STM32_TAMP_H__ */ optee_os-4.3.0/core/include/drivers/stm32_uart.h000066400000000000000000000024271464416617300215610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2023, STMicroelectronics */ #ifndef __DRIVERS_STM32_UART_H #define __DRIVERS_STM32_UART_H #include #include #include #include #include #include struct stm32_uart_pdata { struct io_pa_va base; struct serial_chip chip; bool secure; struct clk *clock; struct pinctrl_state *pinctrl; struct pinctrl_state *pinctrl_sleep; }; /* * stm32_uart_init - Initialize a UART serial chip and base address * @pd: Output initialized UART platform data * @base: UART interface physical base address */ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base); /* * stm32_uart_init_from_dt_node - Initialize a UART instance from a DTB node * @fdt: DTB base address * @node: Target node offset in the DTB * Returns an alloced (malloc) and inited UART platform data on success or NULL * * This function gets a STM32 UART configuration directives from a DTB node * and initializes a UART driver instance. * When the DTB specifies that the device is disabled, the function returns * NULL. Other issues panic the sequence. */ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node); #endif /*__DRIVERS_STM32_UART_H*/ optee_os-4.3.0/core/include/drivers/stm32_vrefbuf.h000066400000000000000000000006761464416617300222510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, STMicroelectronics */ #ifndef DRIVERS_STM32_VREFBUF_H #define DRIVERS_STM32_VREFBUF_H #include #ifdef CFG_STM32_VREFBUF /* Return VREFBUF regulator handler if registered */ struct regulator *stm32_vrefbuf_regulator(void); #else static inline struct regulator *stm32_vrefbuf_regulator(void) { return NULL; } #endif #endif /*DRIVERS_STM32_VREFBUF_H*/ optee_os-4.3.0/core/include/drivers/stm32mp13_rcc.h000066400000000000000000002065031464416617300220570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #ifndef __DRIVERS_STM32MP13_RCC_H__ #define __DRIVERS_STM32MP13_RCC_H__ #include #define RCC_SECCFGR U(0x0) #define RCC_MP_SREQSETR U(0x100) #define RCC_MP_SREQCLRR U(0x104) #define RCC_MP_APRSTCR U(0x108) #define RCC_MP_APRSTSR U(0x10C) #define RCC_PWRLPDLYCR U(0x110) #define RCC_MP_GRSTCSETR U(0x114) #define RCC_BR_RSTSCLRR U(0x118) #define RCC_MP_RSTSSETR U(0x11C) #define RCC_MP_RSTSCLRR U(0x120) #define RCC_MP_IWDGFZSETR U(0x124) #define RCC_MP_IWDGFZCLRR U(0x128) #define RCC_MP_CIER U(0x200) #define RCC_MP_CIFR U(0x204) #define RCC_BDCR U(0x400) #define RCC_RDLSICR U(0x404) #define RCC_OCENSETR U(0x420) #define RCC_OCENCLRR U(0x424) #define RCC_OCRDYR U(0x428) #define RCC_HSICFGR U(0x440) #define RCC_CSICFGR U(0x444) #define RCC_MCO1CFGR U(0x460) #define RCC_MCO2CFGR U(0x464) #define RCC_DBGCFGR U(0x468) #define RCC_RCK12SELR U(0x480) #define RCC_RCK3SELR U(0x484) #define RCC_RCK4SELR U(0x488) #define RCC_PLL1CR U(0x4A0) #define RCC_PLL1CFGR1 U(0x4A4) #define RCC_PLL1CFGR2 U(0x4A8) #define RCC_PLL1FRACR U(0x4AC) #define RCC_PLL1CSGR U(0x4B0) #define RCC_PLL2CR U(0x4D0) #define RCC_PLL2CFGR1 U(0x4D4) #define RCC_PLL2CFGR2 U(0x4D8) #define RCC_PLL2FRACR U(0x4DC) #define RCC_PLL2CSGR U(0x4E0) #define RCC_PLL3CR U(0x500) #define RCC_PLL3CFGR1 U(0x504) #define RCC_PLL3CFGR2 U(0x508) #define RCC_PLL3FRACR U(0x50C) #define RCC_PLL3CSGR U(0x510) #define RCC_PLL4CR U(0x520) #define RCC_PLL4CFGR1 U(0x524) #define RCC_PLL4CFGR2 U(0x528) #define RCC_PLL4FRACR U(0x52C) #define RCC_PLL4CSGR U(0x530) #define RCC_MPCKSELR U(0x540) #define RCC_ASSCKSELR U(0x544) #define RCC_MSSCKSELR U(0x548) #define RCC_CPERCKSELR U(0x54C) #define RCC_RTCDIVR U(0x560) #define RCC_MPCKDIVR U(0x564) #define RCC_AXIDIVR U(0x568) #define RCC_MLAHBDIVR U(0x56C) #define RCC_APB1DIVR U(0x570) #define RCC_APB2DIVR U(0x574) #define RCC_APB3DIVR U(0x578) #define RCC_APB4DIVR U(0x57C) #define RCC_APB5DIVR U(0x580) #define RCC_APB6DIVR U(0x584) #define RCC_TIMG1PRER U(0x5A0) #define RCC_TIMG2PRER U(0x5A4) #define RCC_TIMG3PRER U(0x5A8) #define RCC_DDRITFCR U(0x5C0) #define RCC_I2C12CKSELR U(0x600) #define RCC_I2C345CKSELR U(0x604) #define RCC_SPI2S1CKSELR U(0x608) #define RCC_SPI2S23CKSELR U(0x60C) #define RCC_SPI45CKSELR U(0x610) #define RCC_UART12CKSELR U(0x614) #define RCC_UART35CKSELR U(0x618) #define RCC_UART4CKSELR U(0x61C) #define RCC_UART6CKSELR U(0x620) #define RCC_UART78CKSELR U(0x624) #define RCC_LPTIM1CKSELR U(0x628) #define RCC_LPTIM23CKSELR U(0x62C) #define RCC_LPTIM45CKSELR U(0x630) #define RCC_SAI1CKSELR U(0x634) #define RCC_SAI2CKSELR U(0x638) #define RCC_FDCANCKSELR U(0x63C) #define RCC_SPDIFCKSELR U(0x640) #define RCC_ADC12CKSELR U(0x644) #define RCC_SDMMC12CKSELR U(0x648) #define RCC_ETH12CKSELR U(0x64C) #define RCC_USBCKSELR U(0x650) #define RCC_QSPICKSELR U(0x654) #define RCC_FMCCKSELR U(0x658) #define RCC_RNG1CKSELR U(0x65C) #define RCC_STGENCKSELR U(0x660) #define RCC_DCMIPPCKSELR U(0x664) #define RCC_SAESCKSELR U(0x668) #define RCC_APB1RSTSETR U(0x6A0) #define RCC_APB1RSTCLRR U(0x6A4) #define RCC_APB2RSTSETR U(0x6A8) #define RCC_APB2RSTCLRR U(0x6AC) #define RCC_APB3RSTSETR U(0x6B0) #define RCC_APB3RSTCLRR U(0x6B4) #define RCC_APB4RSTSETR U(0x6B8) #define RCC_APB4RSTCLRR U(0x6BC) #define RCC_APB5RSTSETR U(0x6C0) #define RCC_APB5RSTCLRR U(0x6C4) #define RCC_APB6RSTSETR U(0x6C8) #define RCC_APB6RSTCLRR U(0x6CC) #define RCC_AHB2RSTSETR U(0x6D0) #define RCC_AHB2RSTCLRR U(0x6D4) #define RCC_AHB4RSTSETR U(0x6E0) #define RCC_AHB4RSTCLRR U(0x6E4) #define RCC_AHB5RSTSETR U(0x6E8) #define RCC_AHB5RSTCLRR U(0x6EC) #define RCC_AHB6RSTSETR U(0x6F0) #define RCC_AHB6RSTCLRR U(0x6F4) #define RCC_MP_APB1ENSETR U(0x700) #define RCC_MP_APB1ENCLRR U(0x704) #define RCC_MP_APB2ENSETR U(0x708) #define RCC_MP_APB2ENCLRR U(0x70C) #define RCC_MP_APB3ENSETR U(0x710) #define RCC_MP_APB3ENCLRR U(0x714) #define RCC_MP_S_APB3ENSETR U(0x718) #define RCC_MP_S_APB3ENCLRR U(0x71C) #define RCC_MP_NS_APB3ENSETR U(0x720) #define RCC_MP_NS_APB3ENCLRR U(0x724) #define RCC_MP_APB4ENSETR U(0x728) #define RCC_MP_APB4ENCLRR U(0x72C) #define RCC_MP_S_APB4ENSETR U(0x730) #define RCC_MP_S_APB4ENCLRR U(0x734) #define RCC_MP_NS_APB4ENSETR U(0x738) #define RCC_MP_NS_APB4ENCLRR U(0x73C) #define RCC_MP_APB5ENSETR U(0x740) #define RCC_MP_APB5ENCLRR U(0x744) #define RCC_MP_APB6ENSETR U(0x748) #define RCC_MP_APB6ENCLRR U(0x74C) #define RCC_MP_AHB2ENSETR U(0x750) #define RCC_MP_AHB2ENCLRR U(0x754) #define RCC_MP_AHB4ENSETR U(0x760) #define RCC_MP_AHB4ENCLRR U(0x764) #define RCC_MP_S_AHB4ENSETR U(0x768) #define RCC_MP_S_AHB4ENCLRR U(0x76C) #define RCC_MP_NS_AHB4ENSETR U(0x770) #define RCC_MP_NS_AHB4ENCLRR U(0x774) #define RCC_MP_AHB5ENSETR U(0x778) #define RCC_MP_AHB5ENCLRR U(0x77C) #define RCC_MP_AHB6ENSETR U(0x780) #define RCC_MP_AHB6ENCLRR U(0x784) #define RCC_MP_S_AHB6ENSETR U(0x788) #define RCC_MP_S_AHB6ENCLRR U(0x78C) #define RCC_MP_NS_AHB6ENSETR U(0x790) #define RCC_MP_NS_AHB6ENCLRR U(0x794) #define RCC_MP_APB1LPENSETR U(0x800) #define RCC_MP_APB1LPENCLRR U(0x804) #define RCC_MP_APB2LPENSETR U(0x808) #define RCC_MP_APB2LPENCLRR U(0x80C) #define RCC_MP_APB3LPENSETR U(0x810) #define RCC_MP_APB3LPENCLRR U(0x814) #define RCC_MP_S_APB3LPENSETR U(0x818) #define RCC_MP_S_APB3LPENCLRR U(0x81C) #define RCC_MP_NS_APB3LPENSETR U(0x820) #define RCC_MP_NS_APB3LPENCLRR U(0x824) #define RCC_MP_APB4LPENSETR U(0x828) #define RCC_MP_APB4LPENCLRR U(0x82C) #define RCC_MP_S_APB4LPENSETR U(0x830) #define RCC_MP_S_APB4LPENCLRR U(0x834) #define RCC_MP_NS_APB4LPENSETR U(0x838) #define RCC_MP_NS_APB4LPENCLRR U(0x83C) #define RCC_MP_APB5LPENSETR U(0x840) #define RCC_MP_APB5LPENCLRR U(0x844) #define RCC_MP_APB6LPENSETR U(0x848) #define RCC_MP_APB6LPENCLRR U(0x84C) #define RCC_MP_AHB2LPENSETR U(0x850) #define RCC_MP_AHB2LPENCLRR U(0x854) #define RCC_MP_AHB4LPENSETR U(0x858) #define RCC_MP_AHB4LPENCLRR U(0x85C) #define RCC_MP_S_AHB4LPENSETR U(0x868) #define RCC_MP_S_AHB4LPENCLRR U(0x86C) #define RCC_MP_NS_AHB4LPENSETR U(0x870) #define RCC_MP_NS_AHB4LPENCLRR U(0x874) #define RCC_MP_AHB5LPENSETR U(0x878) #define RCC_MP_AHB5LPENCLRR U(0x87C) #define RCC_MP_AHB6LPENSETR U(0x880) #define RCC_MP_AHB6LPENCLRR U(0x884) #define RCC_MP_S_AHB6LPENSETR U(0x888) #define RCC_MP_S_AHB6LPENCLRR U(0x88C) #define RCC_MP_NS_AHB6LPENSETR U(0x890) #define RCC_MP_NS_AHB6LPENCLRR U(0x894) #define RCC_MP_S_AXIMLPENSETR U(0x898) #define RCC_MP_S_AXIMLPENCLRR U(0x89C) #define RCC_MP_NS_AXIMLPENSETR U(0x8A0) #define RCC_MP_NS_AXIMLPENCLRR U(0x8A4) #define RCC_MP_MLAHBLPENSETR U(0x8A8) #define RCC_MP_MLAHBLPENCLRR U(0x8AC) #define RCC_APB3SECSR U(0x8C0) #define RCC_APB4SECSR U(0x8C4) #define RCC_APB5SECSR U(0x8C8) #define RCC_APB6SECSR U(0x8CC) #define RCC_AHB2SECSR U(0x8D0) #define RCC_AHB4SECSR U(0x8D4) #define RCC_AHB5SECSR U(0x8D8) #define RCC_AHB6SECSR U(0x8DC) #define RCC_VERR U(0xFF4) #define RCC_IDR U(0xFF8) #define RCC_SIDR U(0xFFC) /* RCC_SECCFGR register fields */ #define RCC_SECCFGR_HSISEC BIT(0) #define RCC_SECCFGR_CSISEC BIT(1) #define RCC_SECCFGR_HSESEC BIT(2) #define RCC_SECCFGR_LSISEC BIT(3) #define RCC_SECCFGR_LSESEC BIT(4) #define RCC_SECCFGR_PLL12SEC BIT(8) #define RCC_SECCFGR_PLL3SEC BIT(9) #define RCC_SECCFGR_PLL4SEC BIT(10) #define RCC_SECCFGR_MPUSEC BIT(11) #define RCC_SECCFGR_AXISEC BIT(12) #define RCC_SECCFGR_MLAHBSEC BIT(13) #define RCC_SECCFGR_APB3DIVSEC BIT(16) #define RCC_SECCFGR_APB4DIVSEC BIT(17) #define RCC_SECCFGR_APB5DIVSEC BIT(18) #define RCC_SECCFGR_APB6DIVSEC BIT(19) #define RCC_SECCFGR_TIMG3SEC BIT(20) #define RCC_SECCFGR_CPERSEC BIT(21) #define RCC_SECCFGR_MCO1SEC BIT(22) #define RCC_SECCFGR_MCO2SEC BIT(23) #define RCC_SECCFGR_STPSEC BIT(24) #define RCC_SECCFGR_RSTSEC BIT(25) #define RCC_SECCFGR_PWRSEC BIT(31) /* RCC_MP_SREQSETR register fields */ #define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) /* RCC_MP_SREQCLRR register fields */ #define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) /* RCC_MP_APRSTCR register fields */ #define RCC_MP_APRSTCR_RDCTLEN BIT(0) #define RCC_MP_APRSTCR_RSTTO_MASK GENMASK_32(14, 8) #define RCC_MP_APRSTCR_RSTTO_SHIFT 8 /* RCC_MP_APRSTSR register fields */ #define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK_32(14, 8) #define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 /* RCC_PWRLPDLYCR register fields */ #define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK_32(21, 0) #define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 /* RCC_MP_GRSTCSETR register fields */ #define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) #define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) /* RCC_BR_RSTSCLRR register fields */ #define RCC_BR_RSTSCLRR_PORRSTF BIT(0) #define RCC_BR_RSTSCLRR_BORRSTF BIT(1) #define RCC_BR_RSTSCLRR_PADRSTF BIT(2) #define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) #define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) #define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) #define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) #define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) #define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) #define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) /* RCC_MP_RSTSSETR register fields */ #define RCC_MP_RSTSSETR_PORRSTF BIT(0) #define RCC_MP_RSTSSETR_BORRSTF BIT(1) #define RCC_MP_RSTSSETR_PADRSTF BIT(2) #define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) #define RCC_MP_RSTSSETR_VCORERSTF BIT(4) #define RCC_MP_RSTSSETR_VCPURSTF BIT(5) #define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) #define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) #define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) #define RCC_MP_RSTSSETR_STP2RSTF BIT(10) #define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) #define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) #define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) #define RCC_MP_RSTSSETR_SPARE BIT(15) /* RCC_MP_RSTSCLRR register fields */ #define RCC_MP_RSTSCLRR_PORRSTF BIT(0) #define RCC_MP_RSTSCLRR_BORRSTF BIT(1) #define RCC_MP_RSTSCLRR_PADRSTF BIT(2) #define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) #define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) #define RCC_MP_RSTSCLRR_VCPURSTF BIT(5) #define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) #define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) #define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) #define RCC_MP_RSTSCLRR_STP2RSTF BIT(10) #define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) #define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) #define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) #define RCC_MP_RSTSCLRR_SPARE BIT(15) /* RCC_MP_IWDGFZSETR register fields */ #define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) #define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) /* RCC_MP_IWDGFZCLRR register fields */ #define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) #define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) /* RCC_MP_CIER register fields */ #define RCC_MP_CIER_LSIRDYIE BIT(0) #define RCC_MP_CIER_LSERDYIE BIT(1) #define RCC_MP_CIER_HSIRDYIE BIT(2) #define RCC_MP_CIER_HSERDYIE BIT(3) #define RCC_MP_CIER_CSIRDYIE BIT(4) #define RCC_MP_CIER_PLL1DYIE BIT(8) #define RCC_MP_CIER_PLL2DYIE BIT(9) #define RCC_MP_CIER_PLL3DYIE BIT(10) #define RCC_MP_CIER_PLL4DYIE BIT(11) #define RCC_MP_CIER_LSECSSIE BIT(16) #define RCC_MP_CIER_WKUPIE BIT(20) /* RCC_MP_CIFR register fields */ #define RCC_MP_CIFR_LSIRDYF BIT(0) #define RCC_MP_CIFR_LSERDYF BIT(1) #define RCC_MP_CIFR_HSIRDYF BIT(2) #define RCC_MP_CIFR_HSERDYF BIT(3) #define RCC_MP_CIFR_CSIRDYF BIT(4) #define RCC_MP_CIFR_PLL1DYF BIT(8) #define RCC_MP_CIFR_PLL2DYF BIT(9) #define RCC_MP_CIFR_PLL3DYF BIT(10) #define RCC_MP_CIFR_PLL4DYF BIT(11) #define RCC_MP_CIFR_LSECSSF BIT(16) #define RCC_MP_CIFR_WKUPF BIT(20) /* RCC_BDCR register fields */ #define RCC_BDCR_LSEON BIT(0) #define RCC_BDCR_LSEBYP BIT(1) #define RCC_BDCR_LSERDY BIT(2) #define RCC_BDCR_DIGBYP BIT(3) #define RCC_BDCR_LSEDRV_MASK GENMASK_32(5, 4) #define RCC_BDCR_LSEDRV_SHIFT 4 #define RCC_BDCR_LSECSSON BIT(8) #define RCC_BDCR_LSECSSD BIT(9) #define RCC_BDCR_RTCSRC_MASK GENMASK_32(17, 16) #define RCC_BDCR_RTCSRC_SHIFT 16 #define RCC_BDCR_RTCCKEN BIT(20) #define RCC_BDCR_VSWRST BIT(31) #define RCC_BDCR_LSEBYP_BIT 1 #define RCC_BDCR_LSERDY_BIT 2 #define RCC_BDCR_DIGBYP_BIT 3 #define RCC_BDCR_LSECSSON_BIT 8 #define RCC_BDCR_LSEDRV_WIDTH 2 /* RCC_RDLSICR register fields */ #define RCC_RDLSICR_LSION BIT(0) #define RCC_RDLSICR_LSIRDY BIT(1) #define RCC_RDLSICR_MRD_MASK GENMASK_32(20, 16) #define RCC_RDLSICR_MRD_SHIFT 16 #define RCC_RDLSICR_EADLY_MASK GENMASK_32(26, 24) #define RCC_RDLSICR_EADLY_SHIFT 24 #define RCC_RDLSICR_SPARE_MASK GENMASK_32(31, 27) #define RCC_RDLSICR_SPARE_SHIFT 27 #define RCC_RDLSICR_LSIRDY_BIT 1 /* RCC_OCENSETR register fields */ #define RCC_OCENSETR_HSION BIT(0) #define RCC_OCENSETR_HSIKERON BIT(1) #define RCC_OCENSETR_CSION BIT(4) #define RCC_OCENSETR_CSIKERON BIT(5) #define RCC_OCENSETR_DIGBYP BIT(7) #define RCC_OCENSETR_HSEON BIT(8) #define RCC_OCENSETR_HSEKERON BIT(9) #define RCC_OCENSETR_HSEBYP BIT(10) #define RCC_OCENSETR_HSECSSON BIT(11) #define RCC_OCENR_DIGBYP_BIT 7 #define RCC_OCENR_HSEBYP_BIT 10 #define RCC_OCENR_HSECSSON_BIT 11 /* RCC_OCENCLRR register fields */ #define RCC_OCENCLRR_HSION BIT(0) #define RCC_OCENCLRR_HSIKERON BIT(1) #define RCC_OCENCLRR_CSION BIT(4) #define RCC_OCENCLRR_CSIKERON BIT(5) #define RCC_OCENCLRR_DIGBYP BIT(7) #define RCC_OCENCLRR_HSEON BIT(8) #define RCC_OCENCLRR_HSEKERON BIT(9) #define RCC_OCENCLRR_HSEBYP BIT(10) /* RCC_OCRDYR register fields */ #define RCC_OCRDYR_HSIRDY BIT(0) #define RCC_OCRDYR_HSIDIVRDY BIT(2) #define RCC_OCRDYR_CSIRDY BIT(4) #define RCC_OCRDYR_HSERDY BIT(8) #define RCC_OCRDYR_MPUCKRDY BIT(23) #define RCC_OCRDYR_AXICKRDY BIT(24) #define RCC_OCRDYR_HSIRDY_BIT 0 #define RCC_OCRDYR_HSIDIVRDY_BIT 2 #define RCC_OCRDYR_CSIRDY_BIT 4 #define RCC_OCRDYR_HSERDY_BIT 8 /* RCC_HSICFGR register fields */ #define RCC_HSICFGR_HSIDIV_MASK GENMASK_32(1, 0) #define RCC_HSICFGR_HSIDIV_SHIFT 0 #define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) #define RCC_HSICFGR_HSITRIM_SHIFT 8 #define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) #define RCC_HSICFGR_HSICAL_SHIFT 16 /* RCC_CSICFGR register fields */ #define RCC_CSICFGR_CSITRIM_MASK GENMASK_32(12, 8) #define RCC_CSICFGR_CSITRIM_SHIFT 8 #define RCC_CSICFGR_CSICAL_MASK GENMASK_32(23, 16) #define RCC_CSICFGR_CSICAL_SHIFT 16 /* RCC_MCO1CFGR register fields */ #define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK_32(2, 0) #define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 #define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK_32(7, 4) #define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 #define RCC_MCO1CFGR_MCO1ON BIT(12) /* RCC_MCO2CFGR register fields */ #define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK_32(2, 0) #define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 #define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK_32(7, 4) #define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 #define RCC_MCO2CFGR_MCO2ON BIT(12) /* RCC_DBGCFGR register fields */ #define RCC_DBGCFGR_TRACEDIV_MASK GENMASK_32(2, 0) #define RCC_DBGCFGR_TRACEDIV_SHIFT 0 #define RCC_DBGCFGR_DBGCKEN BIT(8) #define RCC_DBGCFGR_TRACECKEN BIT(9) #define RCC_DBGCFGR_DBGRST BIT(12) /* RCC_RCK12SELR register fields */ #define RCC_RCK12SELR_PLL12SRC_MASK GENMASK_32(1, 0) #define RCC_RCK12SELR_PLL12SRC_SHIFT 0 #define RCC_RCK12SELR_PLL12SRCRDY BIT(31) /* RCC_RCK3SELR register fields */ #define RCC_RCK3SELR_PLL3SRC_MASK GENMASK_32(1, 0) #define RCC_RCK3SELR_PLL3SRC_SHIFT 0 #define RCC_RCK3SELR_PLL3SRCRDY BIT(31) /* RCC_RCK4SELR register fields */ #define RCC_RCK4SELR_PLL4SRC_MASK GENMASK_32(1, 0) #define RCC_RCK4SELR_PLL4SRC_SHIFT 0 #define RCC_RCK4SELR_PLL4SRCRDY BIT(31) /* RCC_PLL1CR register fields */ #define RCC_PLL1CR_PLLON BIT(0) #define RCC_PLL1CR_PLL1RDY BIT(1) #define RCC_PLL1CR_SSCG_CTRL BIT(2) #define RCC_PLL1CR_DIVPEN BIT(4) #define RCC_PLL1CR_DIVQEN BIT(5) #define RCC_PLL1CR_DIVREN BIT(6) /* RCC_PLL1CFGR1 register fields */ #define RCC_PLL1CFGR1_DIVN_MASK GENMASK_32(8, 0) #define RCC_PLL1CFGR1_DIVN_SHIFT 0 #define RCC_PLL1CFGR1_DIVM1_MASK GENMASK_32(21, 16) #define RCC_PLL1CFGR1_DIVM1_SHIFT 16 /* RCC_PLL1CFGR2 register fields */ #define RCC_PLL1CFGR2_DIVP_MASK GENMASK_32(6, 0) #define RCC_PLL1CFGR2_DIVP_SHIFT 0 #define RCC_PLL1CFGR2_DIVQ_MASK GENMASK_32(14, 8) #define RCC_PLL1CFGR2_DIVQ_SHIFT 8 #define RCC_PLL1CFGR2_DIVR_MASK GENMASK_32(22, 16) #define RCC_PLL1CFGR2_DIVR_SHIFT 16 /* RCC_PLL1FRACR register fields */ #define RCC_PLL1FRACR_FRACV_MASK GENMASK_32(15, 3) #define RCC_PLL1FRACR_FRACV_SHIFT 3 #define RCC_PLL1FRACR_FRACLE BIT(16) /* RCC_PLL1CSGR register fields */ #define RCC_PLL1CSGR_MOD_PER_MASK GENMASK_32(12, 0) #define RCC_PLL1CSGR_MOD_PER_SHIFT 0 #define RCC_PLL1CSGR_TPDFN_DIS BIT(13) #define RCC_PLL1CSGR_RPDFN_DIS BIT(14) #define RCC_PLL1CSGR_SSCG_MODE BIT(15) #define RCC_PLL1CSGR_INC_STEP_MASK GENMASK_32(30, 16) #define RCC_PLL1CSGR_INC_STEP_SHIFT 16 /* RCC_PLL2CR register fields */ #define RCC_PLL2CR_PLLON BIT(0) #define RCC_PLL2CR_PLL2RDY BIT(1) #define RCC_PLL2CR_SSCG_CTRL BIT(2) #define RCC_PLL2CR_DIVPEN BIT(4) #define RCC_PLL2CR_DIVQEN BIT(5) #define RCC_PLL2CR_DIVREN BIT(6) /* RCC_PLL2CFGR1 register fields */ #define RCC_PLL2CFGR1_DIVN_MASK GENMASK_32(8, 0) #define RCC_PLL2CFGR1_DIVN_SHIFT 0 #define RCC_PLL2CFGR1_DIVM2_MASK GENMASK_32(21, 16) #define RCC_PLL2CFGR1_DIVM2_SHIFT 16 /* RCC_PLL2CFGR2 register fields */ #define RCC_PLL2CFGR2_DIVP_MASK GENMASK_32(6, 0) #define RCC_PLL2CFGR2_DIVP_SHIFT 0 #define RCC_PLL2CFGR2_DIVQ_MASK GENMASK_32(14, 8) #define RCC_PLL2CFGR2_DIVQ_SHIFT 8 #define RCC_PLL2CFGR2_DIVR_MASK GENMASK_32(22, 16) #define RCC_PLL2CFGR2_DIVR_SHIFT 16 /* RCC_PLL2FRACR register fields */ #define RCC_PLL2FRACR_FRACV_MASK GENMASK_32(15, 3) #define RCC_PLL2FRACR_FRACV_SHIFT 3 #define RCC_PLL2FRACR_FRACLE BIT(16) /* RCC_PLL2CSGR register fields */ #define RCC_PLL2CSGR_MOD_PER_MASK GENMASK_32(12, 0) #define RCC_PLL2CSGR_MOD_PER_SHIFT 0 #define RCC_PLL2CSGR_TPDFN_DIS BIT(13) #define RCC_PLL2CSGR_RPDFN_DIS BIT(14) #define RCC_PLL2CSGR_SSCG_MODE BIT(15) #define RCC_PLL2CSGR_INC_STEP_MASK GENMASK_32(30, 16) #define RCC_PLL2CSGR_INC_STEP_SHIFT 16 /* RCC_PLL3CR register fields */ #define RCC_PLL3CR_PLLON BIT(0) #define RCC_PLL3CR_PLL3RDY BIT(1) #define RCC_PLL3CR_SSCG_CTRL BIT(2) #define RCC_PLL3CR_DIVPEN BIT(4) #define RCC_PLL3CR_DIVQEN BIT(5) #define RCC_PLL3CR_DIVREN BIT(6) /* RCC_PLL3CFGR1 register fields */ #define RCC_PLL3CFGR1_DIVN_MASK GENMASK_32(8, 0) #define RCC_PLL3CFGR1_DIVN_SHIFT 0 #define RCC_PLL3CFGR1_DIVM3_MASK GENMASK_32(21, 16) #define RCC_PLL3CFGR1_DIVM3_SHIFT 16 #define RCC_PLL3CFGR1_IFRGE_MASK GENMASK_32(25, 24) #define RCC_PLL3CFGR1_IFRGE_SHIFT 24 /* RCC_PLL3CFGR2 register fields */ #define RCC_PLL3CFGR2_DIVP_MASK GENMASK_32(6, 0) #define RCC_PLL3CFGR2_DIVP_SHIFT 0 #define RCC_PLL3CFGR2_DIVQ_MASK GENMASK_32(14, 8) #define RCC_PLL3CFGR2_DIVQ_SHIFT 8 #define RCC_PLL3CFGR2_DIVR_MASK GENMASK_32(22, 16) #define RCC_PLL3CFGR2_DIVR_SHIFT 16 /* RCC_PLL3FRACR register fields */ #define RCC_PLL3FRACR_FRACV_MASK GENMASK_32(15, 3) #define RCC_PLL3FRACR_FRACV_SHIFT 3 #define RCC_PLL3FRACR_FRACLE BIT(16) /* RCC_PLL3CSGR register fields */ #define RCC_PLL3CSGR_MOD_PER_MASK GENMASK_32(12, 0) #define RCC_PLL3CSGR_MOD_PER_SHIFT 0 #define RCC_PLL3CSGR_TPDFN_DIS BIT(13) #define RCC_PLL3CSGR_RPDFN_DIS BIT(14) #define RCC_PLL3CSGR_SSCG_MODE BIT(15) #define RCC_PLL3CSGR_INC_STEP_MASK GENMASK_32(30, 16) #define RCC_PLL3CSGR_INC_STEP_SHIFT 16 /* RCC_PLL4CR register fields */ #define RCC_PLL4CR_PLLON BIT(0) #define RCC_PLL4CR_PLL4RDY BIT(1) #define RCC_PLL4CR_SSCG_CTRL BIT(2) #define RCC_PLL4CR_DIVPEN BIT(4) #define RCC_PLL4CR_DIVQEN BIT(5) #define RCC_PLL4CR_DIVREN BIT(6) /* RCC_PLL4CFGR1 register fields */ #define RCC_PLL4CFGR1_DIVN_MASK GENMASK_32(8, 0) #define RCC_PLL4CFGR1_DIVN_SHIFT 0 #define RCC_PLL4CFGR1_DIVM4_MASK GENMASK_32(21, 16) #define RCC_PLL4CFGR1_DIVM4_SHIFT 16 #define RCC_PLL4CFGR1_IFRGE_MASK GENMASK_32(25, 24) #define RCC_PLL4CFGR1_IFRGE_SHIFT 24 /* RCC_PLL4CFGR2 register fields */ #define RCC_PLL4CFGR2_DIVP_MASK GENMASK_32(6, 0) #define RCC_PLL4CFGR2_DIVP_SHIFT 0 #define RCC_PLL4CFGR2_DIVQ_MASK GENMASK_32(14, 8) #define RCC_PLL4CFGR2_DIVQ_SHIFT 8 #define RCC_PLL4CFGR2_DIVR_MASK GENMASK_32(22, 16) #define RCC_PLL4CFGR2_DIVR_SHIFT 16 /* RCC_PLL4FRACR register fields */ #define RCC_PLL4FRACR_FRACV_MASK GENMASK_32(15, 3) #define RCC_PLL4FRACR_FRACV_SHIFT 3 #define RCC_PLL4FRACR_FRACLE BIT(16) /* RCC_PLL4CSGR register fields */ #define RCC_PLL4CSGR_MOD_PER_MASK GENMASK_32(12, 0) #define RCC_PLL4CSGR_MOD_PER_SHIFT 0 #define RCC_PLL4CSGR_TPDFN_DIS BIT(13) #define RCC_PLL4CSGR_RPDFN_DIS BIT(14) #define RCC_PLL4CSGR_SSCG_MODE BIT(15) #define RCC_PLL4CSGR_INC_STEP_MASK GENMASK_32(30, 16) #define RCC_PLL4CSGR_INC_STEP_SHIFT 16 /* RCC_MPCKSELR register fields */ #define RCC_MPCKSELR_MPUSRC_MASK GENMASK_32(1, 0) #define RCC_MPCKSELR_MPUSRC_SHIFT 0 #define RCC_MPCKSELR_MPUSRCRDY BIT(31) /* RCC_ASSCKSELR register fields */ #define RCC_ASSCKSELR_AXISSRC_MASK GENMASK_32(2, 0) #define RCC_ASSCKSELR_AXISSRC_SHIFT 0 #define RCC_ASSCKSELR_AXISSRCRDY BIT(31) /* RCC_MSSCKSELR register fields */ #define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK_32(1, 0) #define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 #define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) /* RCC_CPERCKSELR register fields */ #define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK_32(1, 0) #define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 /* RCC_RTCDIVR register fields */ #define RCC_RTCDIVR_RTCDIV_MASK GENMASK_32(5, 0) #define RCC_RTCDIVR_RTCDIV_SHIFT 0 /* RCC_MPCKDIVR register fields */ #define RCC_MPCKDIVR_MPUDIV_MASK GENMASK_32(3, 0) #define RCC_MPCKDIVR_MPUDIV_SHIFT 0 #define RCC_MPCKDIVR_MPUDIVRDY BIT(31) /* RCC_AXIDIVR register fields */ #define RCC_AXIDIVR_AXIDIV_MASK GENMASK_32(2, 0) #define RCC_AXIDIVR_AXIDIV_SHIFT 0 #define RCC_AXIDIVR_AXIDIVRDY BIT(31) /* RCC_MLAHBDIVR register fields */ #define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK_32(3, 0) #define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 #define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) /* RCC_APB1DIVR register fields */ #define RCC_APB1DIVR_APB1DIV_MASK GENMASK_32(2, 0) #define RCC_APB1DIVR_APB1DIV_SHIFT 0 #define RCC_APB1DIVR_APB1DIVRDY BIT(31) /* RCC_APB2DIVR register fields */ #define RCC_APB2DIVR_APB2DIV_MASK GENMASK_32(2, 0) #define RCC_APB2DIVR_APB2DIV_SHIFT 0 #define RCC_APB2DIVR_APB2DIVRDY BIT(31) /* RCC_APB3DIVR register fields */ #define RCC_APB3DIVR_APB3DIV_MASK GENMASK_32(2, 0) #define RCC_APB3DIVR_APB3DIV_SHIFT 0 #define RCC_APB3DIVR_APB3DIVRDY BIT(31) /* RCC_APB4DIVR register fields */ #define RCC_APB4DIVR_APB4DIV_MASK GENMASK_32(2, 0) #define RCC_APB4DIVR_APB4DIV_SHIFT 0 #define RCC_APB4DIVR_APB4DIVRDY BIT(31) /* RCC_APB5DIVR register fields */ #define RCC_APB5DIVR_APB5DIV_MASK GENMASK_32(2, 0) #define RCC_APB5DIVR_APB5DIV_SHIFT 0 #define RCC_APB5DIVR_APB5DIVRDY BIT(31) /* RCC_APB6DIVR register fields */ #define RCC_APB6DIVR_APB6DIV_MASK GENMASK_32(2, 0) #define RCC_APB6DIVR_APB6DIV_SHIFT 0 #define RCC_APB6DIVR_APB6DIVRDY BIT(31) /* RCC_TIMG1PRER register fields */ #define RCC_TIMG1PRER_TIMG1PRE BIT(0) #define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) /* RCC_TIMG2PRER register fields */ #define RCC_TIMG2PRER_TIMG2PRE BIT(0) #define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) /* RCC_TIMG3PRER register fields */ #define RCC_TIMG3PRER_TIMG3PRE BIT(0) #define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) /* RCC_DDRITFCR register fields */ #define RCC_DDRITFCR_DDRC1EN BIT(0) #define RCC_DDRITFCR_DDRC1LPEN BIT(1) #define RCC_DDRITFCR_DDRPHYCEN BIT(4) #define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) #define RCC_DDRITFCR_DDRCAPBEN BIT(6) #define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) #define RCC_DDRITFCR_AXIDCGEN BIT(8) #define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) #define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) #define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK_32(13, 11) #define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 #define RCC_DDRITFCR_DDRCAPBRST BIT(14) #define RCC_DDRITFCR_DDRCAXIRST BIT(15) #define RCC_DDRITFCR_DDRCORERST BIT(16) #define RCC_DDRITFCR_DPHYAPBRST BIT(17) #define RCC_DDRITFCR_DPHYRST BIT(18) #define RCC_DDRITFCR_DPHYCTLRST BIT(19) #define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK_32(22, 20) #define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 #define RCC_DDRITFCR_GSKPMOD BIT(23) #define RCC_DDRITFCR_GSKPCTRL BIT(24) #define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK_32(27, 25) #define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 #define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK_32(31, 28) #define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 /* RCC_I2C12CKSELR register fields */ #define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK_32(2, 0) #define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 /* RCC_I2C345CKSELR register fields */ #define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK_32(2, 0) #define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 #define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK_32(5, 3) #define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 #define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK_32(8, 6) #define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 /* RCC_SPI2S1CKSELR register fields */ #define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK_32(2, 0) #define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 /* RCC_SPI2S23CKSELR register fields */ #define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK_32(2, 0) #define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 /* RCC_SPI45CKSELR register fields */ #define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK_32(2, 0) #define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 #define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK_32(5, 3) #define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 /* RCC_UART12CKSELR register fields */ #define RCC_UART12CKSELR_UART1SRC_MASK GENMASK_32(2, 0) #define RCC_UART12CKSELR_UART1SRC_SHIFT 0 #define RCC_UART12CKSELR_UART2SRC_MASK GENMASK_32(5, 3) #define RCC_UART12CKSELR_UART2SRC_SHIFT 3 /* RCC_UART35CKSELR register fields */ #define RCC_UART35CKSELR_UART35SRC_MASK GENMASK_32(2, 0) #define RCC_UART35CKSELR_UART35SRC_SHIFT 0 /* RCC_UART4CKSELR register fields */ #define RCC_UART4CKSELR_UART4SRC_MASK GENMASK_32(2, 0) #define RCC_UART4CKSELR_UART4SRC_SHIFT 0 /* RCC_UART6CKSELR register fields */ #define RCC_UART6CKSELR_UART6SRC_MASK GENMASK_32(2, 0) #define RCC_UART6CKSELR_UART6SRC_SHIFT 0 /* RCC_UART78CKSELR register fields */ #define RCC_UART78CKSELR_UART78SRC_MASK GENMASK_32(2, 0) #define RCC_UART78CKSELR_UART78SRC_SHIFT 0 /* RCC_LPTIM1CKSELR register fields */ #define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK_32(2, 0) #define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 /* RCC_LPTIM23CKSELR register fields */ #define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK_32(2, 0) #define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 #define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK_32(5, 3) #define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 /* RCC_LPTIM45CKSELR register fields */ #define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK_32(2, 0) #define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 /* RCC_SAI1CKSELR register fields */ #define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK_32(2, 0) #define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 /* RCC_SAI2CKSELR register fields */ #define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK_32(2, 0) #define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 /* RCC_FDCANCKSELR register fields */ #define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK_32(1, 0) #define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 /* RCC_SPDIFCKSELR register fields */ #define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK_32(1, 0) #define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 /* RCC_ADC12CKSELR register fields */ #define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK_32(1, 0) #define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 #define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK_32(3, 2) #define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 /* RCC_SDMMC12CKSELR register fields */ #define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK_32(2, 0) #define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 #define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK_32(5, 3) #define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 /* RCC_ETH12CKSELR register fields */ #define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK_32(1, 0) #define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 #define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK_32(7, 4) #define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 #define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK_32(9, 8) #define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 #define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK_32(15, 12) #define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 /* RCC_USBCKSELR register fields */ #define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK_32(1, 0) #define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 #define RCC_USBCKSELR_USBOSRC BIT(4) /* RCC_QSPICKSELR register fields */ #define RCC_QSPICKSELR_QSPISRC_MASK GENMASK_32(1, 0) #define RCC_QSPICKSELR_QSPISRC_SHIFT 0 /* RCC_FMCCKSELR register fields */ #define RCC_FMCCKSELR_FMCSRC_MASK GENMASK_32(1, 0) #define RCC_FMCCKSELR_FMCSRC_SHIFT 0 /* RCC_RNG1CKSELR register fields */ #define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK_32(1, 0) #define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 /* RCC_STGENCKSELR register fields */ #define RCC_STGENCKSELR_STGENSRC_MASK GENMASK_32(1, 0) #define RCC_STGENCKSELR_STGENSRC_SHIFT 0 /* RCC_DCMIPPCKSELR register fields */ #define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK_32(1, 0) #define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 /* RCC_SAESCKSELR register fields */ #define RCC_SAESCKSELR_SAESSRC_MASK GENMASK_32(1, 0) #define RCC_SAESCKSELR_SAESSRC_SHIFT 0 /* RCC_APB1RSTSETR register fields */ #define RCC_APB1RSTSETR_TIM2RST BIT(0) #define RCC_APB1RSTSETR_TIM3RST BIT(1) #define RCC_APB1RSTSETR_TIM4RST BIT(2) #define RCC_APB1RSTSETR_TIM5RST BIT(3) #define RCC_APB1RSTSETR_TIM6RST BIT(4) #define RCC_APB1RSTSETR_TIM7RST BIT(5) #define RCC_APB1RSTSETR_LPTIM1RST BIT(9) #define RCC_APB1RSTSETR_SPI2RST BIT(11) #define RCC_APB1RSTSETR_SPI3RST BIT(12) #define RCC_APB1RSTSETR_USART3RST BIT(15) #define RCC_APB1RSTSETR_UART4RST BIT(16) #define RCC_APB1RSTSETR_UART5RST BIT(17) #define RCC_APB1RSTSETR_UART7RST BIT(18) #define RCC_APB1RSTSETR_UART8RST BIT(19) #define RCC_APB1RSTSETR_I2C1RST BIT(21) #define RCC_APB1RSTSETR_I2C2RST BIT(22) #define RCC_APB1RSTSETR_SPDIFRST BIT(26) /* RCC_APB1RSTCLRR register fields */ #define RCC_APB1RSTCLRR_TIM2RST BIT(0) #define RCC_APB1RSTCLRR_TIM3RST BIT(1) #define RCC_APB1RSTCLRR_TIM4RST BIT(2) #define RCC_APB1RSTCLRR_TIM5RST BIT(3) #define RCC_APB1RSTCLRR_TIM6RST BIT(4) #define RCC_APB1RSTCLRR_TIM7RST BIT(5) #define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) #define RCC_APB1RSTCLRR_SPI2RST BIT(11) #define RCC_APB1RSTCLRR_SPI3RST BIT(12) #define RCC_APB1RSTCLRR_USART3RST BIT(15) #define RCC_APB1RSTCLRR_UART4RST BIT(16) #define RCC_APB1RSTCLRR_UART5RST BIT(17) #define RCC_APB1RSTCLRR_UART7RST BIT(18) #define RCC_APB1RSTCLRR_UART8RST BIT(19) #define RCC_APB1RSTCLRR_I2C1RST BIT(21) #define RCC_APB1RSTCLRR_I2C2RST BIT(22) #define RCC_APB1RSTCLRR_SPDIFRST BIT(26) /* RCC_APB2RSTSETR register fields */ #define RCC_APB2RSTSETR_TIM1RST BIT(0) #define RCC_APB2RSTSETR_TIM8RST BIT(1) #define RCC_APB2RSTSETR_SPI1RST BIT(8) #define RCC_APB2RSTSETR_USART6RST BIT(13) #define RCC_APB2RSTSETR_SAI1RST BIT(16) #define RCC_APB2RSTSETR_SAI2RST BIT(17) #define RCC_APB2RSTSETR_DFSDMRST BIT(20) #define RCC_APB2RSTSETR_FDCANRST BIT(24) /* RCC_APB2RSTCLRR register fields */ #define RCC_APB2RSTCLRR_TIM1RST BIT(0) #define RCC_APB2RSTCLRR_TIM8RST BIT(1) #define RCC_APB2RSTCLRR_SPI1RST BIT(8) #define RCC_APB2RSTCLRR_USART6RST BIT(13) #define RCC_APB2RSTCLRR_SAI1RST BIT(16) #define RCC_APB2RSTCLRR_SAI2RST BIT(17) #define RCC_APB2RSTCLRR_DFSDMRST BIT(20) #define RCC_APB2RSTCLRR_FDCANRST BIT(24) /* RCC_APB3RSTSETR register fields */ #define RCC_APB3RSTSETR_LPTIM2RST BIT(0) #define RCC_APB3RSTSETR_LPTIM3RST BIT(1) #define RCC_APB3RSTSETR_LPTIM4RST BIT(2) #define RCC_APB3RSTSETR_LPTIM5RST BIT(3) #define RCC_APB3RSTSETR_SYSCFGRST BIT(11) #define RCC_APB3RSTSETR_VREFRST BIT(13) #define RCC_APB3RSTSETR_DTSRST BIT(16) #define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) /* RCC_APB3RSTCLRR register fields */ #define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) #define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) #define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) #define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) #define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) #define RCC_APB3RSTCLRR_VREFRST BIT(13) #define RCC_APB3RSTCLRR_DTSRST BIT(16) #define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) /* RCC_APB4RSTSETR register fields */ #define RCC_APB4RSTSETR_LTDCRST BIT(0) #define RCC_APB4RSTSETR_DCMIPPRST BIT(1) #define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) #define RCC_APB4RSTSETR_USBPHYRST BIT(16) /* RCC_APB4RSTCLRR register fields */ #define RCC_APB4RSTCLRR_LTDCRST BIT(0) #define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) #define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) #define RCC_APB4RSTCLRR_USBPHYRST BIT(16) /* RCC_APB5RSTSETR register fields */ #define RCC_APB5RSTSETR_STGENRST BIT(20) /* RCC_APB5RSTCLRR register fields */ #define RCC_APB5RSTCLRR_STGENRST BIT(20) /* RCC_APB6RSTSETR register fields */ #define RCC_APB6RSTSETR_USART1RST BIT(0) #define RCC_APB6RSTSETR_USART2RST BIT(1) #define RCC_APB6RSTSETR_SPI4RST BIT(2) #define RCC_APB6RSTSETR_SPI5RST BIT(3) #define RCC_APB6RSTSETR_I2C3RST BIT(4) #define RCC_APB6RSTSETR_I2C4RST BIT(5) #define RCC_APB6RSTSETR_I2C5RST BIT(6) #define RCC_APB6RSTSETR_TIM12RST BIT(7) #define RCC_APB6RSTSETR_TIM13RST BIT(8) #define RCC_APB6RSTSETR_TIM14RST BIT(9) #define RCC_APB6RSTSETR_TIM15RST BIT(10) #define RCC_APB6RSTSETR_TIM16RST BIT(11) #define RCC_APB6RSTSETR_TIM17RST BIT(12) /* RCC_APB6RSTCLRR register fields */ #define RCC_APB6RSTCLRR_USART1RST BIT(0) #define RCC_APB6RSTCLRR_USART2RST BIT(1) #define RCC_APB6RSTCLRR_SPI4RST BIT(2) #define RCC_APB6RSTCLRR_SPI5RST BIT(3) #define RCC_APB6RSTCLRR_I2C3RST BIT(4) #define RCC_APB6RSTCLRR_I2C4RST BIT(5) #define RCC_APB6RSTCLRR_I2C5RST BIT(6) #define RCC_APB6RSTCLRR_TIM12RST BIT(7) #define RCC_APB6RSTCLRR_TIM13RST BIT(8) #define RCC_APB6RSTCLRR_TIM14RST BIT(9) #define RCC_APB6RSTCLRR_TIM15RST BIT(10) #define RCC_APB6RSTCLRR_TIM16RST BIT(11) #define RCC_APB6RSTCLRR_TIM17RST BIT(12) /* RCC_AHB2RSTSETR register fields */ #define RCC_AHB2RSTSETR_DMA1RST BIT(0) #define RCC_AHB2RSTSETR_DMA2RST BIT(1) #define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) #define RCC_AHB2RSTSETR_DMA3RST BIT(3) #define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) #define RCC_AHB2RSTSETR_ADC1RST BIT(5) #define RCC_AHB2RSTSETR_ADC2RST BIT(6) #define RCC_AHB2RSTSETR_USBORST BIT(8) /* RCC_AHB2RSTCLRR register fields */ #define RCC_AHB2RSTCLRR_DMA1RST BIT(0) #define RCC_AHB2RSTCLRR_DMA2RST BIT(1) #define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) #define RCC_AHB2RSTCLRR_DMA3RST BIT(3) #define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) #define RCC_AHB2RSTCLRR_ADC1RST BIT(5) #define RCC_AHB2RSTCLRR_ADC2RST BIT(6) #define RCC_AHB2RSTCLRR_USBORST BIT(8) /* RCC_AHB4RSTSETR register fields */ #define RCC_AHB4RSTSETR_GPIOARST BIT(0) #define RCC_AHB4RSTSETR_GPIOBRST BIT(1) #define RCC_AHB4RSTSETR_GPIOCRST BIT(2) #define RCC_AHB4RSTSETR_GPIODRST BIT(3) #define RCC_AHB4RSTSETR_GPIOERST BIT(4) #define RCC_AHB4RSTSETR_GPIOFRST BIT(5) #define RCC_AHB4RSTSETR_GPIOGRST BIT(6) #define RCC_AHB4RSTSETR_GPIOHRST BIT(7) #define RCC_AHB4RSTSETR_GPIOIRST BIT(8) #define RCC_AHB4RSTSETR_TSCRST BIT(15) /* RCC_AHB4RSTCLRR register fields */ #define RCC_AHB4RSTCLRR_GPIOARST BIT(0) #define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) #define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) #define RCC_AHB4RSTCLRR_GPIODRST BIT(3) #define RCC_AHB4RSTCLRR_GPIOERST BIT(4) #define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) #define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) #define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) #define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) #define RCC_AHB4RSTCLRR_TSCRST BIT(15) /* RCC_AHB5RSTSETR register fields */ #define RCC_AHB5RSTSETR_PKARST BIT(2) #define RCC_AHB5RSTSETR_SAESRST BIT(3) #define RCC_AHB5RSTSETR_CRYP1RST BIT(4) #define RCC_AHB5RSTSETR_HASH1RST BIT(5) #define RCC_AHB5RSTSETR_RNG1RST BIT(6) #define RCC_AHB5RSTSETR_AXIMCRST BIT(16) /* RCC_AHB5RSTCLRR register fields */ #define RCC_AHB5RSTCLRR_PKARST BIT(2) #define RCC_AHB5RSTCLRR_SAESRST BIT(3) #define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) #define RCC_AHB5RSTCLRR_HASH1RST BIT(5) #define RCC_AHB5RSTCLRR_RNG1RST BIT(6) #define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) /* RCC_AHB6RSTSETR register fields */ #define RCC_AHB6RSTSETR_MDMARST BIT(0) #define RCC_AHB6RSTSETR_MCERST BIT(1) #define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) #define RCC_AHB6RSTSETR_FMCRST BIT(12) #define RCC_AHB6RSTSETR_QSPIRST BIT(14) #define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) #define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) #define RCC_AHB6RSTSETR_CRC1RST BIT(20) #define RCC_AHB6RSTSETR_USBHRST BIT(24) #define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) /* RCC_AHB6RSTCLRR register fields */ #define RCC_AHB6RSTCLRR_MDMARST BIT(0) #define RCC_AHB6RSTCLRR_MCERST BIT(1) #define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) #define RCC_AHB6RSTCLRR_FMCRST BIT(12) #define RCC_AHB6RSTCLRR_QSPIRST BIT(14) #define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) #define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) #define RCC_AHB6RSTCLRR_CRC1RST BIT(20) #define RCC_AHB6RSTCLRR_USBHRST BIT(24) #define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) /* RCC_MP_APB1ENSETR register fields */ #define RCC_MP_APB1ENSETR_TIM2EN BIT(0) #define RCC_MP_APB1ENSETR_TIM3EN BIT(1) #define RCC_MP_APB1ENSETR_TIM4EN BIT(2) #define RCC_MP_APB1ENSETR_TIM5EN BIT(3) #define RCC_MP_APB1ENSETR_TIM6EN BIT(4) #define RCC_MP_APB1ENSETR_TIM7EN BIT(5) #define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) #define RCC_MP_APB1ENSETR_SPI2EN BIT(11) #define RCC_MP_APB1ENSETR_SPI3EN BIT(12) #define RCC_MP_APB1ENSETR_USART3EN BIT(15) #define RCC_MP_APB1ENSETR_UART4EN BIT(16) #define RCC_MP_APB1ENSETR_UART5EN BIT(17) #define RCC_MP_APB1ENSETR_UART7EN BIT(18) #define RCC_MP_APB1ENSETR_UART8EN BIT(19) #define RCC_MP_APB1ENSETR_I2C1EN BIT(21) #define RCC_MP_APB1ENSETR_I2C2EN BIT(22) #define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) /* RCC_MP_APB1ENCLRR register fields */ #define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) #define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) #define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) #define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) #define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) #define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) #define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) #define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) #define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) #define RCC_MP_APB1ENCLRR_USART3EN BIT(15) #define RCC_MP_APB1ENCLRR_UART4EN BIT(16) #define RCC_MP_APB1ENCLRR_UART5EN BIT(17) #define RCC_MP_APB1ENCLRR_UART7EN BIT(18) #define RCC_MP_APB1ENCLRR_UART8EN BIT(19) #define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) #define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) #define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) /* RCC_MP_APB2ENSETR register fields */ #define RCC_MP_APB2ENSETR_TIM1EN BIT(0) #define RCC_MP_APB2ENSETR_TIM8EN BIT(1) #define RCC_MP_APB2ENSETR_SPI1EN BIT(8) #define RCC_MP_APB2ENSETR_USART6EN BIT(13) #define RCC_MP_APB2ENSETR_SAI1EN BIT(16) #define RCC_MP_APB2ENSETR_SAI2EN BIT(17) #define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) #define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) #define RCC_MP_APB2ENSETR_FDCANEN BIT(24) /* RCC_MP_APB2ENCLRR register fields */ #define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) #define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) #define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) #define RCC_MP_APB2ENCLRR_USART6EN BIT(13) #define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) #define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) #define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) #define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) #define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) /* RCC_MP_APB3ENSETR register fields */ #define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) #define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) #define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) #define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) #define RCC_MP_APB3ENSETR_VREFEN BIT(13) #define RCC_MP_APB3ENSETR_DTSEN BIT(16) #define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) #define RCC_MP_APB3ENSETR_HDPEN BIT(20) /* RCC_MP_APB3ENCLRR register fields */ #define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) #define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) #define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) #define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) #define RCC_MP_APB3ENCLRR_VREFEN BIT(13) #define RCC_MP_APB3ENCLRR_DTSEN BIT(16) #define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) #define RCC_MP_APB3ENCLRR_HDPEN BIT(20) /* RCC_MP_S_APB3ENSETR register fields */ #define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) /* RCC_MP_S_APB3ENCLRR register fields */ #define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) /* RCC_MP_NS_APB3ENSETR register fields */ #define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) /* RCC_MP_NS_APB3ENCLRR register fields */ #define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) /* RCC_MP_APB4ENSETR register fields */ #define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) #define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) #define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) #define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) #define RCC_MP_APB4ENSETR_STGENROEN BIT(20) /* RCC_MP_APB4ENCLRR register fields */ #define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) #define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) #define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) #define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) #define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) /* RCC_MP_S_APB4ENSETR register fields */ #define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) /* RCC_MP_S_APB4ENCLRR register fields */ #define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) /* RCC_MP_NS_APB4ENSETR register fields */ #define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) /* RCC_MP_NS_APB4ENCLRR register fields */ #define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) /* RCC_MP_APB5ENSETR register fields */ #define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) #define RCC_MP_APB5ENSETR_TZCEN BIT(11) #define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) #define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) #define RCC_MP_APB5ENSETR_BSECEN BIT(16) #define RCC_MP_APB5ENSETR_STGENCEN BIT(20) /* RCC_MP_APB5ENCLRR register fields */ #define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) #define RCC_MP_APB5ENCLRR_TZCEN BIT(11) #define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) #define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) #define RCC_MP_APB5ENCLRR_BSECEN BIT(16) #define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) /* RCC_MP_APB6ENSETR register fields */ #define RCC_MP_APB6ENSETR_USART1EN BIT(0) #define RCC_MP_APB6ENSETR_USART2EN BIT(1) #define RCC_MP_APB6ENSETR_SPI4EN BIT(2) #define RCC_MP_APB6ENSETR_SPI5EN BIT(3) #define RCC_MP_APB6ENSETR_I2C3EN BIT(4) #define RCC_MP_APB6ENSETR_I2C4EN BIT(5) #define RCC_MP_APB6ENSETR_I2C5EN BIT(6) #define RCC_MP_APB6ENSETR_TIM12EN BIT(7) #define RCC_MP_APB6ENSETR_TIM13EN BIT(8) #define RCC_MP_APB6ENSETR_TIM14EN BIT(9) #define RCC_MP_APB6ENSETR_TIM15EN BIT(10) #define RCC_MP_APB6ENSETR_TIM16EN BIT(11) #define RCC_MP_APB6ENSETR_TIM17EN BIT(12) /* RCC_MP_APB6ENCLRR register fields */ #define RCC_MP_APB6ENCLRR_USART1EN BIT(0) #define RCC_MP_APB6ENCLRR_USART2EN BIT(1) #define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) #define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) #define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) #define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) #define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) #define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) #define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) #define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) #define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) #define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) #define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) /* RCC_MP_AHB2ENSETR register fields */ #define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) #define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) #define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) #define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) #define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) #define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) #define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) #define RCC_MP_AHB2ENSETR_USBOEN BIT(8) /* RCC_MP_AHB2ENCLRR register fields */ #define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) #define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) #define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) #define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) #define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) #define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) #define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) #define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) /* RCC_MP_AHB4ENSETR register fields */ #define RCC_MP_AHB4ENSETR_TSCEN BIT(15) /* RCC_MP_AHB4ENCLRR register fields */ #define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) /* RCC_MP_S_AHB4ENSETR register fields */ #define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) #define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) #define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) #define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) #define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) #define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) #define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) #define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) #define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) /* RCC_MP_S_AHB4ENCLRR register fields */ #define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) #define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) #define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) #define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) #define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) #define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) #define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) #define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) #define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) /* RCC_MP_NS_AHB4ENSETR register fields */ #define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) #define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) #define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) #define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) #define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) #define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) #define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) #define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) #define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) /* RCC_MP_NS_AHB4ENCLRR register fields */ #define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) #define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) #define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) #define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) #define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) #define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) #define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) #define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) #define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) /* RCC_MP_AHB5ENSETR register fields */ #define RCC_MP_AHB5ENSETR_PKAEN BIT(2) #define RCC_MP_AHB5ENSETR_SAESEN BIT(3) #define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) #define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) #define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) #define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) #define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) /* RCC_MP_AHB5ENCLRR register fields */ #define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) #define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) #define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) #define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) #define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) #define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) #define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) /* RCC_MP_AHB6ENSETR register fields */ #define RCC_MP_AHB6ENSETR_MCEEN BIT(1) #define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) #define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) #define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) #define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) #define RCC_MP_AHB6ENSETR_FMCEN BIT(12) #define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) #define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) #define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) #define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) #define RCC_MP_AHB6ENSETR_USBHEN BIT(24) #define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) #define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) #define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) #define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) /* RCC_MP_AHB6ENCLRR register fields */ #define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) #define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) #define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) #define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) #define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) #define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) #define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) #define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) #define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) #define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) #define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) #define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) #define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) #define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) #define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) /* RCC_MP_S_AHB6ENSETR register fields */ #define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) /* RCC_MP_S_AHB6ENCLRR register fields */ #define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) /* RCC_MP_NS_AHB6ENSETR register fields */ #define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) /* RCC_MP_NS_AHB6ENCLRR register fields */ #define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) /* RCC_MP_APB1LPENSETR register fields */ #define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) #define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) #define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) #define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) #define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) #define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) #define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) #define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) #define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) #define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) #define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) #define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) #define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) #define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) #define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) #define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) #define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) /* RCC_MP_APB1LPENCLRR register fields */ #define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) #define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) #define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) #define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) #define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) #define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) #define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) #define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) #define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) #define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) #define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) #define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) #define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) #define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) #define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) #define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) #define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) /* RCC_MP_APB2LPENSETR register fields */ #define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) #define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) #define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) #define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) #define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) #define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) #define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) #define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) #define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) /* RCC_MP_APB2LPENCLRR register fields */ #define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) #define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) #define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) #define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) #define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) #define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) #define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) #define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) #define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) /* RCC_MP_APB3LPENSETR register fields */ #define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) #define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) #define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) #define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) #define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) #define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) #define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) /* RCC_MP_APB3LPENCLRR register fields */ #define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) #define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) #define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) #define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) #define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) #define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) #define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) /* RCC_MP_S_APB3LPENSETR register fields */ #define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) /* RCC_MP_S_APB3LPENCLRR register fields */ #define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) /* RCC_MP_NS_APB3LPENSETR register fields */ #define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) /* RCC_MP_NS_APB3LPENCLRR register fields */ #define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) /* RCC_MP_APB4LPENSETR register fields */ #define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) #define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) #define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) #define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) #define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) #define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) /* RCC_MP_APB4LPENCLRR register fields */ #define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) #define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) #define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) #define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) #define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) #define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) /* RCC_MP_S_APB4LPENSETR register fields */ #define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) /* RCC_MP_S_APB4LPENCLRR register fields */ #define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) /* RCC_MP_NS_APB4LPENSETR register fields */ #define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) /* RCC_MP_NS_APB4LPENCLRR register fields */ #define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) /* RCC_MP_APB5LPENSETR register fields */ #define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) #define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) #define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) #define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) #define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) #define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) #define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) /* RCC_MP_APB5LPENCLRR register fields */ #define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) #define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) #define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) #define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) #define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) #define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) #define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) /* RCC_MP_APB6LPENSETR register fields */ #define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) #define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) #define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) #define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) #define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) #define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) #define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) #define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) #define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) #define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) #define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) #define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) #define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) /* RCC_MP_APB6LPENCLRR register fields */ #define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) #define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) #define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) #define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) #define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) #define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) #define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) #define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) #define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) #define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) #define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) #define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) #define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) /* RCC_MP_AHB2LPENSETR register fields */ #define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) #define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) #define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) #define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) #define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) #define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) #define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) #define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) /* RCC_MP_AHB2LPENCLRR register fields */ #define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) #define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) #define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) #define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) #define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) #define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) #define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) #define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) /* RCC_MP_AHB4LPENSETR register fields */ #define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) /* RCC_MP_AHB4LPENCLRR register fields */ #define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) /* RCC_MP_S_AHB4LPENSETR register fields */ #define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) #define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) #define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) #define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) #define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) #define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) #define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) #define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) #define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) /* RCC_MP_S_AHB4LPENCLRR register fields */ #define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) #define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) #define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) #define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) #define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) #define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) #define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) #define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) #define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) /* RCC_MP_NS_AHB4LPENSETR register fields */ #define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) #define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) #define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) #define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) #define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) #define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) #define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) #define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) #define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) /* RCC_MP_NS_AHB4LPENCLRR register fields */ #define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) #define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) #define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) #define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) #define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) #define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) #define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) #define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) #define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) /* RCC_MP_AHB5LPENSETR register fields */ #define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) #define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) #define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) #define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) #define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) #define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) /* RCC_MP_AHB5LPENCLRR register fields */ #define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) #define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) #define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) #define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) #define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) #define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) /* RCC_MP_AHB6LPENSETR register fields */ #define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) #define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) #define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) #define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) #define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) #define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) #define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) #define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) #define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) #define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) #define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) #define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) #define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) #define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) #define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) #define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) #define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) /* RCC_MP_AHB6LPENCLRR register fields */ #define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) #define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) #define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) #define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) #define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) #define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) #define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) #define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) #define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) #define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) #define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) #define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) #define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) #define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) #define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) #define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) #define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) /* RCC_MP_S_AHB6LPENSETR register fields */ #define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) /* RCC_MP_S_AHB6LPENCLRR register fields */ #define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) /* RCC_MP_NS_AHB6LPENSETR register fields */ #define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) /* RCC_MP_NS_AHB6LPENCLRR register fields */ #define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) /* RCC_MP_S_AXIMLPENSETR register fields */ #define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) /* RCC_MP_S_AXIMLPENCLRR register fields */ #define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) /* RCC_MP_NS_AXIMLPENSETR register fields */ #define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) /* RCC_MP_NS_AXIMLPENCLRR register fields */ #define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) /* RCC_MP_MLAHBLPENSETR register fields */ #define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) #define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) #define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) /* RCC_MP_MLAHBLPENCLRR register fields */ #define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) #define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) #define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) /* RCC_APB3SECSR register fields */ #define RCC_APB3SECSR_LPTIM2SECF BIT(0) #define RCC_APB3SECSR_LPTIM3SECF BIT(1) #define RCC_APB3SECSR_VREFSECF BIT(13) /* RCC_APB4SECSR register fields */ #define RCC_APB4SECSR_DCMIPPSECF BIT(1) #define RCC_APB4SECSR_USBPHYSECF BIT(16) /* RCC_APB5SECSR register fields */ #define RCC_APB5SECSR_RTCSECF BIT(8) #define RCC_APB5SECSR_TZCSECF BIT(11) #define RCC_APB5SECSR_ETZPCSECF BIT(13) #define RCC_APB5SECSR_IWDG1SECF BIT(15) #define RCC_APB5SECSR_BSECSECF BIT(16) #define RCC_APB5SECSR_STGENCSECF_MASK GENMASK_32(21, 20) #define RCC_APB5SECSR_STGENCSECF_SHIFT 20 /* RCC_APB6SECSR register fields */ #define RCC_APB6SECSR_USART1SECF BIT(0) #define RCC_APB6SECSR_USART2SECF BIT(1) #define RCC_APB6SECSR_SPI4SECF BIT(2) #define RCC_APB6SECSR_SPI5SECF BIT(3) #define RCC_APB6SECSR_I2C3SECF BIT(4) #define RCC_APB6SECSR_I2C4SECF BIT(5) #define RCC_APB6SECSR_I2C5SECF BIT(6) #define RCC_APB6SECSR_TIM12SECF BIT(7) #define RCC_APB6SECSR_TIM13SECF BIT(8) #define RCC_APB6SECSR_TIM14SECF BIT(9) #define RCC_APB6SECSR_TIM15SECF BIT(10) #define RCC_APB6SECSR_TIM16SECF BIT(11) #define RCC_APB6SECSR_TIM17SECF BIT(12) /* RCC_AHB2SECSR register fields */ #define RCC_AHB2SECSR_DMA3SECF BIT(3) #define RCC_AHB2SECSR_DMAMUX2SECF BIT(4) #define RCC_AHB2SECSR_ADC1SECF BIT(5) #define RCC_AHB2SECSR_ADC2SECF BIT(6) #define RCC_AHB2SECSR_USBOSECF BIT(8) /* RCC_AHB4SECSR register fields */ #define RCC_AHB4SECSR_TSCSECF BIT(15) /* RCC_AHB5SECSR register fields */ #define RCC_AHB5SECSR_PKASECF BIT(2) #define RCC_AHB5SECSR_SAESSECF BIT(3) #define RCC_AHB5SECSR_CRYP1SECF BIT(4) #define RCC_AHB5SECSR_HASH1SECF BIT(5) #define RCC_AHB5SECSR_RNG1SECF BIT(6) #define RCC_AHB5SECSR_BKPSRAMSECF BIT(8) /* RCC_AHB6SECSR register fields */ #define RCC_AHB6SECSR_MCESECF BIT(1) #define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK_32(11, 7) #define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 #define RCC_AHB6SECSR_FMCSECF BIT(12) #define RCC_AHB6SECSR_QSPISECF BIT(14) #define RCC_AHB6SECSR_SDMMC1SECF BIT(16) #define RCC_AHB6SECSR_SDMMC2SECF BIT(17) #define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK_32(31, 27) #define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 /* RCC_VERR register fields */ #define RCC_VERR_MINREV_MASK GENMASK_32(3, 0) #define RCC_VERR_MINREV_SHIFT 0 #define RCC_VERR_MAJREV_MASK GENMASK_32(7, 4) #define RCC_VERR_MAJREV_SHIFT 4 /* RCC_IDR register fields */ #define RCC_IDR_ID_MASK GENMASK_32(31, 0) #define RCC_IDR_ID_SHIFT 0 /* RCC_SIDR register fields */ #define RCC_SIDR_SID_MASK GENMASK_32(31, 0) #define RCC_SIDR_SID_SHIFT 0 /* Used for all RCC_PLLCR registers */ #define RCC_PLLNCR_PLLON BIT(0) #define RCC_PLLNCR_PLLRDY BIT(1) #define RCC_PLLNCR_SSCG_CTRL BIT(2) #define RCC_PLLNCR_DIVPEN BIT(4) #define RCC_PLLNCR_DIVQEN BIT(5) #define RCC_PLLNCR_DIVREN BIT(6) #define RCC_PLLNCR_DIVEN_SHIFT 4 /* Used for all RCC_PLLCFGR1 registers */ #define RCC_PLLNCFGR1_DIVM_SHIFT 16 #define RCC_PLLNCFGR1_DIVM_MASK GENMASK_32(21, 16) #define RCC_PLLNCFGR1_DIVN_SHIFT 0 #define RCC_PLLNCFGR1_DIVN_MASK GENMASK_32(8, 0) /* Only for PLL3 and PLL4 */ #define RCC_PLLNCFGR1_IFRGE_SHIFT 24 #define RCC_PLLNCFGR1_IFRGE_MASK GENMASK_32(25, 24) /* Used for all RCC_PLLCFGR2 registers */ #define RCC_PLLNCFGR2_DIVX_MASK GENMASK_32(6, 0) #define RCC_PLLNCFGR2_DIVP_SHIFT 0 #define RCC_PLLNCFGR2_DIVP_MASK GENMASK_32(6, 0) #define RCC_PLLNCFGR2_DIVQ_SHIFT 8 #define RCC_PLLNCFGR2_DIVQ_MASK GENMASK_32(14, 8) #define RCC_PLLNCFGR2_DIVR_SHIFT 16 #define RCC_PLLNCFGR2_DIVR_MASK GENMASK_32(22, 16) /* Used for all RCC_PLLFRACR registers */ #define RCC_PLLNFRACR_FRACV_SHIFT 3 #define RCC_PLLNFRACR_FRACV_MASK GENMASK_32(15, 3) #define RCC_PLLNFRACR_FRACLE BIT(16) /* Used for all RCC_PLLCSGR registers */ #define RCC_PLLNCSGR_INC_STEP_SHIFT 16 #define RCC_PLLNCSGR_INC_STEP_MASK GENMASK_32(30, 16) #define RCC_PLLNCSGR_MOD_PER_SHIFT 0 #define RCC_PLLNCSGR_MOD_PER_MASK GENMASK_32(12, 0) #define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 #define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) /* Used for most of RCC_SELR registers */ #define RCC_SELR_SRC_MASK GENMASK_32(2, 0) #define RCC_SELR_REFCLK_SRC_MASK GENMASK_32(1, 0) #define RCC_SELR_SRCRDY BIT(31) /* Values of RCC_MPCKSELR register */ #define RCC_MPCKSELR_HSI 0x00000000 #define RCC_MPCKSELR_HSE 0x00000001 #define RCC_MPCKSELR_PLL 0x00000002 #define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 /* Values of RCC_ASSCKSELR register */ #define RCC_ASSCKSELR_HSI 0x00000000 #define RCC_ASSCKSELR_HSE 0x00000001 #define RCC_ASSCKSELR_PLL 0x00000002 /* Values of RCC_MSSCKSELR register */ #define RCC_MSSCKSELR_HSI 0x00000000 #define RCC_MSSCKSELR_HSE 0x00000001 #define RCC_MSSCKSELR_CSI 0x00000002 #define RCC_MSSCKSELR_PLL 0x00000003 /* Values of RCC_CPERCKSELR register */ #define RCC_CPERCKSELR_HSI 0x00000000 #define RCC_CPERCKSELR_CSI 0x00000001 #define RCC_CPERCKSELR_HSE 0x00000002 /* Used for most of DIVR register: max div for RTC */ #define RCC_DIVR_DIV_MASK GENMASK_32(5, 0) #define RCC_DIVR_DIVRDY BIT(31) /* Masks for specific DIVR registers */ #define RCC_APBXDIV_MASK GENMASK_32(2, 0) #define RCC_MPUDIV_MASK GENMASK_32(2, 0) #define RCC_AXIDIV_MASK GENMASK_32(2, 0) #define RCC_MLAHBDIV_MASK GENMASK_32(3, 0) /* Used for TIMER Prescaler */ #define RCC_TIMGXPRER_TIMGXPRE BIT(0) /* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ #define RCC_MP_ENCLRR_OFFSET U(4) /* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ #define RCC_RSTCLRR_OFFSET U(4) /* RCC_OCENSETR register fields */ #define RCC_OCENR_HSION BIT(0) #define RCC_OCENR_HSIKERON BIT(1) #define RCC_OCENR_CSION BIT(4) #define RCC_OCENR_CSIKERON BIT(5) #define RCC_OCENR_DIGBYP BIT(7) #define RCC_OCENR_HSEON BIT(8) #define RCC_OCENR_HSEKERON BIT(9) #define RCC_OCENR_HSEBYP BIT(10) #define RCC_OCENR_HSECSSON BIT(11) #define RCC_OCENR_DIGBYP_BIT 7 #define RCC_OCENR_HSEBYP_BIT 10 #define RCC_OCENR_HSECSSON_BIT 11 /* Used for RCC_MCO related operations */ #define RCC_MCOCFG_MCOON BIT(12) #define RCC_MCOCFG_MCODIV_MASK GENMASK_32(7, 4) #define RCC_MCOCFG_MCODIV_SHIFT 4 #define RCC_MCOCFG_MCOSRC_MASK GENMASK_32(2, 0) #define RCC_UART4CKSELR_HSI 0x00000002 #define RCC_CPERCKSELR_PERSRC_MASK GENMASK_32(1, 0) #define RCC_CPERCKSELR_PERSRC_SHIFT 0 #define RCC_USBCKSELR_USBOSRC_MASK BIT(4) #define RCC_USBCKSELR_USBOSRC_SHIFT 4 #define RCC_DDRITFCR_DDRCKMOD_SSR 0 #define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) #define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) #define RCC_DDRITFCR_DDRC2EN BIT(0) #define RCC_DDRITFCR_DDRC2LPEN BIT(1) #define RCC_MP_CIFR_MASK U(0x110F1F) #define RCC_OFFSET_MASK GENMASK_32(11, 0) vaddr_t stm32_rcc_base(void); #endif /*__DRIVERS_STM32MP13_RCC_H__*/ optee_os-4.3.0/core/include/drivers/stm32mp13_regulator_iod.h000066400000000000000000000011401464416617300241350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021-2023, STMicroelectronics */ #ifndef __DRIVERS_STM32MP13_REGULATOR_IOD_H #define __DRIVERS_STM32MP13_REGULATOR_IOD_H #include enum iod_regulator_id { IOD_SDMMC1, IOD_SDMMC2, IOD_REGU_COUNT }; #ifdef CFG_STM32MP13_REGULATOR_IOD struct regulator *stm32mp1_get_iod_regulator(enum iod_regulator_id index); #else static inline struct regulator * stm32mp1_get_iod_regulator(enum iod_regulator_id id __unused) { return NULL; } #endif /* CFG_STM32MP13_REGULATOR_IOD */ #endif /* __DRIVERS_STM32MP13_REGULATOR_IOD_H */ optee_os-4.3.0/core/include/drivers/stm32mp1_rcc.h000066400000000000000000000460211464416617300217710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2017-2018, STMicroelectronics */ #ifndef __DRIVERS_STM32MP1_RCC_H__ #define __DRIVERS_STM32MP1_RCC_H__ #include #include #include #define RCC_TZCR 0x00 #define RCC_OCENSETR 0x0C #define RCC_OCENCLRR 0x10 #define RCC_HSICFGR 0x18 #define RCC_CSICFGR 0x1C #define RCC_MPCKSELR 0x20 #define RCC_ASSCKSELR 0x24 #define RCC_RCK12SELR 0x28 #define RCC_MPCKDIVR 0x2C #define RCC_AXIDIVR 0x30 #define RCC_APB4DIVR 0x3C #define RCC_APB5DIVR 0x40 #define RCC_RTCDIVR 0x44 #define RCC_MSSCKSELR 0x48 #define RCC_PLL1CR 0x80 #define RCC_PLL1CFGR1 0x84 #define RCC_PLL1CFGR2 0x88 #define RCC_PLL1FRACR 0x8C #define RCC_PLL1CSGR 0x90 #define RCC_PLL2CR 0x94 #define RCC_PLL2CFGR1 0x98 #define RCC_PLL2CFGR2 0x9C #define RCC_PLL2FRACR 0xA0 #define RCC_PLL2CSGR 0xA4 #define RCC_I2C46CKSELR 0xC0 #define RCC_SPI6CKSELR 0xC4 #define RCC_UART1CKSELR 0xC8 #define RCC_RNG1CKSELR 0xCC #define RCC_CPERCKSELR 0xD0 #define RCC_STGENCKSELR 0xD4 #define RCC_DDRITFCR 0xD8 #define RCC_MP_BOOTCR 0x100 #define RCC_MP_SREQSETR 0x104 #define RCC_MP_SREQCLRR 0x108 #define RCC_MP_GCR 0x10C #define RCC_MP_APRSTCR 0x110 #define RCC_MP_APRSTSR 0x114 #define RCC_BDCR 0x140 #define RCC_RDLSICR 0x144 #define RCC_APB4RSTSETR 0x180 #define RCC_APB4RSTCLRR 0x184 #define RCC_APB5RSTSETR 0x188 #define RCC_APB5RSTCLRR 0x18C #define RCC_AHB5RSTSETR 0x190 #define RCC_AHB5RSTCLRR 0x194 #define RCC_AHB6RSTSETR 0x198 #define RCC_AHB6RSTCLRR 0x19C #define RCC_TZAHB6RSTSETR 0x1A0 #define RCC_TZAHB6RSTCLRR 0x1A4 #define RCC_MP_APB4ENSETR 0x200 #define RCC_MP_APB4ENCLRR 0x204 #define RCC_MP_APB5ENSETR 0x208 #define RCC_MP_APB5ENCLRR 0x20C #define RCC_MP_AHB5ENSETR 0x210 #define RCC_MP_AHB5ENCLRR 0x214 #define RCC_MP_AHB6ENSETR 0x218 #define RCC_MP_AHB6ENCLRR 0x21C #define RCC_MP_TZAHB6ENSETR 0x220 #define RCC_MP_TZAHB6ENCLRR 0x224 #define RCC_MC_APB4ENSETR 0x280 #define RCC_MC_APB4ENCLRR 0x284 #define RCC_MC_APB5ENSETR 0x288 #define RCC_MC_APB5ENCLRR 0x28C #define RCC_MC_AHB5ENSETR 0x290 #define RCC_MC_AHB5ENCLRR 0x294 #define RCC_MC_AHB6ENSETR 0x298 #define RCC_MC_AHB6ENCLRR 0x29C #define RCC_MP_APB4LPENSETR 0x300 #define RCC_MP_APB4LPENCLRR 0x304 #define RCC_MP_APB5LPENSETR 0x308 #define RCC_MP_APB5LPENCLRR 0x30C #define RCC_MP_AHB5LPENSETR 0x310 #define RCC_MP_AHB5LPENCLRR 0x314 #define RCC_MP_AHB6LPENSETR 0x318 #define RCC_MP_AHB6LPENCLRR 0x31C #define RCC_MP_TZAHB6LPENSETR 0x320 #define RCC_MP_TZAHB6LPENCLRR 0x324 #define RCC_MC_APB4LPENSETR 0x380 #define RCC_MC_APB4LPENCLRR 0x384 #define RCC_MC_APB5LPENSETR 0x388 #define RCC_MC_APB5LPENCLRR 0x38C #define RCC_MC_AHB5LPENSETR 0x390 #define RCC_MC_AHB5LPENCLRR 0x394 #define RCC_MC_AHB6LPENSETR 0x398 #define RCC_MC_AHB6LPENCLRR 0x39C #define RCC_BR_RSTSCLRR 0x400 #define RCC_MP_GRSTCSETR 0x404 #define RCC_MP_RSTSCLRR 0x408 #define RCC_MP_IWDGFZSETR 0x40C #define RCC_MP_IWDGFZCLRR 0x410 #define RCC_MP_CIER 0x414 #define RCC_MP_CIFR 0x418 #define RCC_PWRLPDLYCR 0x41C #define RCC_MP_RSTSSETR 0x420 #define RCC_MCO1CFGR 0x800 #define RCC_MCO2CFGR 0x804 #define RCC_OCRDYR 0x808 #define RCC_DBGCFGR 0x80C #define RCC_RCK3SELR 0x820 #define RCC_RCK4SELR 0x824 #define RCC_TIMG1PRER 0x828 #define RCC_TIMG2PRER 0x82C #define RCC_MCUDIVR 0x830 #define RCC_APB1DIVR 0x834 #define RCC_APB2DIVR 0x838 #define RCC_APB3DIVR 0x83C #define RCC_PLL3CR 0x880 #define RCC_PLL3CFGR1 0x884 #define RCC_PLL3CFGR2 0x888 #define RCC_PLL3FRACR 0x88C #define RCC_PLL3CSGR 0x890 #define RCC_PLL4CR 0x894 #define RCC_PLL4CFGR1 0x898 #define RCC_PLL4CFGR2 0x89C #define RCC_PLL4FRACR 0x8A0 #define RCC_PLL4CSGR 0x8A4 #define RCC_I2C12CKSELR 0x8C0 #define RCC_I2C35CKSELR 0x8C4 #define RCC_SAI1CKSELR 0x8C8 #define RCC_SAI2CKSELR 0x8CC #define RCC_SAI3CKSELR 0x8D0 #define RCC_SAI4CKSELR 0x8D4 #define RCC_SPI2S1CKSELR 0x8D8 #define RCC_SPI2S23CKSELR 0x8DC #define RCC_SPI45CKSELR 0x8E0 #define RCC_UART6CKSELR 0x8E4 #define RCC_UART24CKSELR 0x8E8 #define RCC_UART35CKSELR 0x8EC #define RCC_UART78CKSELR 0x8F0 #define RCC_SDMMC12CKSELR 0x8F4 #define RCC_SDMMC3CKSELR 0x8F8 #define RCC_ETHCKSELR 0x8FC #define RCC_QSPICKSELR 0x900 #define RCC_FMCCKSELR 0x904 #define RCC_FDCANCKSELR 0x90C #define RCC_SPDIFCKSELR 0x914 #define RCC_CECCKSELR 0x918 #define RCC_USBCKSELR 0x91C #define RCC_RNG2CKSELR 0x920 #define RCC_DSICKSELR 0x924 #define RCC_ADCCKSELR 0x928 #define RCC_LPTIM45CKSELR 0x92C #define RCC_LPTIM23CKSELR 0x930 #define RCC_LPTIM1CKSELR 0x934 #define RCC_APB1RSTSETR 0x980 #define RCC_APB1RSTCLRR 0x984 #define RCC_APB2RSTSETR 0x988 #define RCC_APB2RSTCLRR 0x98C #define RCC_APB3RSTSETR 0x990 #define RCC_APB3RSTCLRR 0x994 #define RCC_AHB2RSTSETR 0x998 #define RCC_AHB2RSTCLRR 0x99C #define RCC_AHB3RSTSETR 0x9A0 #define RCC_AHB3RSTCLRR 0x9A4 #define RCC_AHB4RSTSETR 0x9A8 #define RCC_AHB4RSTCLRR 0x9AC #define RCC_MP_APB1ENSETR 0xA00 #define RCC_MP_APB1ENCLRR 0xA04 #define RCC_MP_APB2ENSETR 0xA08 #define RCC_MP_APB2ENCLRR 0xA0C #define RCC_MP_APB3ENSETR 0xA10 #define RCC_MP_APB3ENCLRR 0xA14 #define RCC_MP_AHB2ENSETR 0xA18 #define RCC_MP_AHB2ENCLRR 0xA1C #define RCC_MP_AHB3ENSETR 0xA20 #define RCC_MP_AHB3ENCLRR 0xA24 #define RCC_MP_AHB4ENSETR 0xA28 #define RCC_MP_AHB4ENCLRR 0xA2C #define RCC_MP_MLAHBENSETR 0xA38 #define RCC_MP_MLAHBENCLRR 0xA3C #define RCC_MC_APB1ENSETR 0xA80 #define RCC_MC_APB1ENCLRR 0xA84 #define RCC_MC_APB2ENSETR 0xA88 #define RCC_MC_APB2ENCLRR 0xA8C #define RCC_MC_APB3ENSETR 0xA90 #define RCC_MC_APB3ENCLRR 0xA94 #define RCC_MC_AHB2ENSETR 0xA98 #define RCC_MC_AHB2ENCLRR 0xA9C #define RCC_MC_AHB3ENSETR 0xAA0 #define RCC_MC_AHB3ENCLRR 0xAA4 #define RCC_MC_AHB4ENSETR 0xAA8 #define RCC_MC_AHB4ENCLRR 0xAAC #define RCC_MC_AXIMENSETR 0xAB0 #define RCC_MC_AXIMENCLRR 0xAB4 #define RCC_MC_MLAHBENSETR 0xAB8 #define RCC_MC_MLAHBENCLRR 0xABC #define RCC_MP_APB1LPENSETR 0xB00 #define RCC_MP_APB1LPENCLRR 0xB04 #define RCC_MP_APB2LPENSETR 0xB08 #define RCC_MP_APB2LPENCLRR 0xB0C #define RCC_MP_APB3LPENSETR 0xB10 #define RCC_MP_APB3LPENCLRR 0xB14 #define RCC_MP_AHB2LPENSETR 0xB18 #define RCC_MP_AHB2LPENCLRR 0xB1C #define RCC_MP_AHB3LPENSETR 0xB20 #define RCC_MP_AHB3LPENCLRR 0xB24 #define RCC_MP_AHB4LPENSETR 0xB28 #define RCC_MP_AHB4LPENCLRR 0xB2C #define RCC_MP_AXIMLPENSETR 0xB30 #define RCC_MP_AXIMLPENCLRR 0xB34 #define RCC_MP_MLAHBLPENSETR 0xB38 #define RCC_MP_MLAHBLPENCLRR 0xB3C #define RCC_MC_APB1LPENSETR 0xB80 #define RCC_MC_APB1LPENCLRR 0xB84 #define RCC_MC_APB2LPENSETR 0xB88 #define RCC_MC_APB2LPENCLRR 0xB8C #define RCC_MC_APB3LPENSETR 0xB90 #define RCC_MC_APB3LPENCLRR 0xB94 #define RCC_MC_AHB2LPENSETR 0xB98 #define RCC_MC_AHB2LPENCLRR 0xB9C #define RCC_MC_AHB3LPENSETR 0xBA0 #define RCC_MC_AHB3LPENCLRR 0xBA4 #define RCC_MC_AHB4LPENSETR 0xBA8 #define RCC_MC_AHB4LPENCLRR 0xBAC #define RCC_MC_AXIMLPENSETR 0xBB0 #define RCC_MC_AXIMLPENCLRR 0xBB4 #define RCC_MC_MLAHBLPENSETR 0xBB8 #define RCC_MC_MLAHBLPENCLRR 0xBBC #define RCC_MC_RSTSCLRR 0xC00 #define RCC_MC_CIER 0xC14 #define RCC_MC_CIFR 0xC18 #define RCC_VERR 0xFF4 #define RCC_IDR 0xFF8 #define RCC_SIDR 0xFFC #define RCC_OFFSET_MASK GENMASK_32(11, 0) /* Values for RCC_TZCR register */ #define RCC_TZCR_TZEN BIT(0) #define RCC_TZCR_MCKPROT BIT(1) /* Used for most of RCC_SELR registers */ #define RCC_SELR_SRC_MASK GENMASK_32(2, 0) #define RCC_SELR_REFCLK_SRC_MASK GENMASK_32(1, 0) #define RCC_SELR_SRCRDY BIT(31) /* Values of RCC_MPCKSELR register */ #define RCC_MPCKSELR_HSI 0x00000000 #define RCC_MPCKSELR_HSE 0x00000001 #define RCC_MPCKSELR_PLL 0x00000002 #define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 /* Values of RCC_ASSCKSELR register */ #define RCC_ASSCKSELR_HSI 0x00000000 #define RCC_ASSCKSELR_HSE 0x00000001 #define RCC_ASSCKSELR_PLL 0x00000002 /* Values of RCC_MSSCKSELR register */ #define RCC_MSSCKSELR_HSI 0x00000000 #define RCC_MSSCKSELR_HSE 0x00000001 #define RCC_MSSCKSELR_CSI 0x00000002 #define RCC_MSSCKSELR_PLL 0x00000003 /* Values of RCC_CPERCKSELR register */ #define RCC_CPERCKSELR_HSI 0x00000000 #define RCC_CPERCKSELR_CSI 0x00000001 #define RCC_CPERCKSELR_HSE 0x00000002 /* used for most of RCC_DIVR registers: max div for RTC */ #define RCC_DIVR_DIV_MASK GENMASK_32(5, 0) #define RCC_DIVR_DIVRDY BIT(31) /* Masks for specific DIVR registers */ #define RCC_APBXDIV_MASK GENMASK_32(2, 0) #define RCC_MPUDIV_MASK GENMASK_32(2, 0) #define RCC_AXIDIV_MASK GENMASK_32(2, 0) #define RCC_MCUDIV_MASK GENMASK_32(3, 0) /* Used for TIMER Prescaler */ #define RCC_TIMGXPRER_TIMGXPRE BIT(0) /* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ #define RCC_MP_ENCLRR_OFFSET 4u /* Offset between RCC_MP_xxxRSTSETR and RCC_MP_xxxRSTCLRR registers */ #define RCC_MP_RSTCLRR_OFFSET 4u /* Fields of RCC_BDCR register */ #define RCC_BDCR_LSEON BIT(0) #define RCC_BDCR_LSEBYP BIT(1) #define RCC_BDCR_LSERDY BIT(2) #define RCC_BDCR_DIGBYP BIT(3) #define RCC_BDCR_LSEDRV_MASK GENMASK_32(5, 4) #define RCC_BDCR_LSEDRV_SHIFT 4 #define RCC_BDCR_LSECSSON BIT(8) #define RCC_BDCR_RTCCKEN_POS 20 #define RCC_BDCR_RTCCKEN BIT(RCC_BDCR_RTCCKEN_POS) #define RCC_BDCR_RTCSRC_MASK GENMASK_32(17, 16) #define RCC_BDCR_RTCSRC_SHIFT 16 #define RCC_BDCR_VSWRST BIT(31) /* Fields of RCC_RDLSICR register */ #define RCC_RDLSICR_LSION BIT(0) #define RCC_RDLSICR_LSIRDY BIT(1) /* Used for all RCC_PLLCR registers */ #define RCC_PLLNCR_PLLON BIT(0) #define RCC_PLLNCR_PLLRDY BIT(1) #define RCC_PLLNCR_SSCG_CTRL BIT(2) #define RCC_PLLNCR_DIVPEN BIT(4) #define RCC_PLLNCR_DIVQEN BIT(5) #define RCC_PLLNCR_DIVREN BIT(6) #define RCC_PLLNCR_DIVEN_SHIFT 4 /* Used for all RCC_PLLCFGR1 registers */ #define RCC_PLLNCFGR1_DIVM_SHIFT 16 #define RCC_PLLNCFGR1_DIVM_MASK GENMASK_32(21, 16) #define RCC_PLLNCFGR1_DIVN_SHIFT 0 #define RCC_PLLNCFGR1_DIVN_MASK GENMASK_32(8, 0) /* Only for PLL3 and PLL4 */ #define RCC_PLLNCFGR1_IFRGE_SHIFT 24 #define RCC_PLLNCFGR1_IFRGE_MASK GENMASK_32(25, 24) /* Used for all RCC_PLLCFGR2 registers */ #define RCC_PLLNCFGR2_DIVX_MASK GENMASK_32(6, 0) #define RCC_PLLNCFGR2_DIVP_SHIFT 0 #define RCC_PLLNCFGR2_DIVP_MASK GENMASK_32(6, 0) #define RCC_PLLNCFGR2_DIVQ_SHIFT 8 #define RCC_PLLNCFGR2_DIVQ_MASK GENMASK_32(14, 8) #define RCC_PLLNCFGR2_DIVR_SHIFT 16 #define RCC_PLLNCFGR2_DIVR_MASK GENMASK_32(22, 16) /* Used for all RCC_PLLFRACR registers */ #define RCC_PLLNFRACR_FRACV_SHIFT 3 #define RCC_PLLNFRACR_FRACV_MASK GENMASK_32(15, 3) #define RCC_PLLNFRACR_FRACLE BIT(16) /* Used for all RCC_PLLCSGR registers */ #define RCC_PLLNCSGR_INC_STEP_SHIFT 16 #define RCC_PLLNCSGR_INC_STEP_MASK GENMASK_32(30, 16) #define RCC_PLLNCSGR_MOD_PER_SHIFT 0 #define RCC_PLLNCSGR_MOD_PER_MASK GENMASK_32(12, 0) #define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 #define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) /* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ #define RCC_OCENR_HSION BIT(0) #define RCC_OCENR_HSIKERON BIT(1) #define RCC_OCENR_CSION BIT(4) #define RCC_OCENR_CSIKERON BIT(5) #define RCC_OCENR_DIGBYP BIT(7) #define RCC_OCENR_HSEON BIT(8) #define RCC_OCENR_HSEKERON BIT(9) #define RCC_OCENR_HSEBYP BIT(10) #define RCC_OCENR_HSECSSON BIT(11) /* Fields of RCC_OCRDYR register */ #define RCC_OCRDYR_HSIRDY BIT(0) #define RCC_OCRDYR_HSIDIVRDY BIT(2) #define RCC_OCRDYR_CSIRDY BIT(4) #define RCC_OCRDYR_HSERDY BIT(8) /* Fields of RCC_DDRITFCR register */ #define RCC_DDRITFCR_DDRC1EN BIT(0) #define RCC_DDRITFCR_DDRC1LPEN BIT(1) #define RCC_DDRITFCR_DDRC2EN BIT(2) #define RCC_DDRITFCR_DDRC2LPEN BIT(3) #define RCC_DDRITFCR_DDRPHYCEN BIT(4) #define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) #define RCC_DDRITFCR_DDRCAPBEN BIT(6) #define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) #define RCC_DDRITFCR_AXIDCGEN BIT(8) #define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) #define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) #define RCC_DDRITFCR_DDRCAPBRST BIT(14) #define RCC_DDRITFCR_DDRCAXIRST BIT(15) #define RCC_DDRITFCR_DDRCORERST BIT(16) #define RCC_DDRITFCR_DPHYAPBRST BIT(17) #define RCC_DDRITFCR_DPHYRST BIT(18) #define RCC_DDRITFCR_DPHYCTLRST BIT(19) #define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK_32(22, 20) #define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 #define RCC_DDRITFCR_DDRCKMOD_SSR 0 #define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) #define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) #define RCC_DDRITFCR_GSKPCTRL BIT(24) /* Fields of RCC_HSICFGR register */ #define RCC_HSICFGR_HSIDIV_MASK GENMASK_32(1, 0) #define RCC_HSICFGR_HSITRIM_SHIFT 8 #define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) #define RCC_HSICFGR_HSICAL_SHIFT 16 #define RCC_HSICFGR_HSICAL_MASK GENMASK_32(27, 16) /* Fields of RCC_CSICFGR register */ #define RCC_CSICFGR_CSITRIM_SHIFT 8 #define RCC_CSICFGR_CSITRIM_MASK GENMASK_32(12, 8) #define RCC_CSICFGR_CSICAL_SHIFT 16 #define RCC_CSICFGR_CSICAL_MASK GENMASK_32(23, 16) /* Used for RCC_MCO related operations */ #define RCC_MCOCFG_MCOON BIT(12) #define RCC_MCOCFG_MCODIV_MASK GENMASK_32(7, 4) #define RCC_MCOCFG_MCODIV_SHIFT 4 #define RCC_MCOCFG_MCOSRC_MASK GENMASK_32(2, 0) /* Fields of RCC_DBGCFGR register */ #define RCC_DBGCFGR_DBGCKEN BIT(8) /* RCC register fields for reset reasons */ #define RCC_MP_RSTSCLRR_PORRSTF BIT(0) #define RCC_MP_RSTSCLRR_BORRSTF BIT(1) #define RCC_MP_RSTSCLRR_PADRSTF BIT(2) #define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) #define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) #define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) #define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7) #define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) #define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) #define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) #define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) /* Global Reset Register */ #define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) #define RCC_MP_GRSTCSETR_MCURST BIT(1) #define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) #define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) /* Clock Source Interrupt Flag Register */ #define RCC_MP_CIFR_LSIRDYF BIT(0) #define RCC_MP_CIFR_LSERDYF BIT(1) #define RCC_MP_CIFR_HSIRDYF BIT(2) #define RCC_MP_CIFR_HSERDYF BIT(3) #define RCC_MP_CIFR_CSIRDYF BIT(4) #define RCC_MP_CIFR_PLL1DYF BIT(8) #define RCC_MP_CIFR_PLL2DYF BIT(9) #define RCC_MP_CIFR_PLL3DYF BIT(10) #define RCC_MP_CIFR_PLL4DYF BIT(11) #define RCC_MP_CIFR_LSECSSF BIT(16) #define RCC_MP_CIFR_WKUPF BIT(20) #define RCC_MP_CIFR_MASK (RCC_MP_CIFR_LSIRDYF | RCC_MP_CIFR_LSERDYF | \ RCC_MP_CIFR_HSIRDYF | RCC_MP_CIFR_HSERDYF | \ RCC_MP_CIFR_CSIRDYF | RCC_MP_CIFR_PLL1DYF | \ RCC_MP_CIFR_PLL2DYF | RCC_MP_CIFR_PLL3DYF | \ RCC_MP_CIFR_PLL4DYF | RCC_MP_CIFR_LSECSSF | \ RCC_MP_CIFR_WKUPF) /* Stop Request Set Register */ #define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) #define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) /* Stop Request Clear Register */ #define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) #define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) /* Global Control Register */ #define RCC_MP_GCR_BOOT_MCU BIT(0) /* RCC_MP_APB5RST(SET|CLR)R bit fields */ #define RCC_APB5RSTSETR_SPI6RST BIT(0) #define RCC_APB5RSTSETR_I2C4RST BIT(2) #define RCC_APB5RSTSETR_I2C6RST BIT(3) #define RCC_APB5RSTSETR_USART1RST BIT(4) #define RCC_APB5RSTSETR_STGENRST BIT(20) /* RCC_MP_APB1EN(SET|CLR)R bit fields */ #define RCC_MP_APB1ENSETR_I2C5EN_POS 24 #define RCC_MP_APB1ENSETR_I2C5EN BIT(RCC_MP_APB1ENSETR_I2C5EN_POS) /* RCC_MP_APB5EN(SET|CLR)R bit fields */ #define RCC_MP_APB5ENSETR_SPI6EN_POS 0 #define RCC_MP_APB5ENSETR_I2C4EN_POS 2 #define RCC_MP_APB5ENSETR_I2C6EN_POS 3 #define RCC_MP_APB5ENSETR_USART1EN_POS 4 #define RCC_MP_APB5ENSETR_RTCAPBEN_POS 8 #define RCC_MP_APB5ENSETR_TZC1EN_POS 11 #define RCC_MP_APB5ENSETR_TZC2EN_POS 12 #define RCC_MP_APB5ENSETR_TZPCEN_POS 13 #define RCC_MP_APB5ENSETR_IWDG1APBEN_POS 15 #define RCC_MP_APB5ENSETR_BSECEN_POS 16 #define RCC_MP_APB5ENSETR_STGENEN_POS 20 #define RCC_MP_APB5ENSETR_SPI6EN BIT(RCC_MP_APB5ENSETR_SPI6EN_POS) #define RCC_MP_APB5ENSETR_I2C4EN BIT(RCC_MP_APB5ENSETR_I2C4EN_POS) #define RCC_MP_APB5ENSETR_I2C6EN BIT(RCC_MP_APB5ENSETR_I2C6EN_POS) #define RCC_MP_APB5ENSETR_USART1EN BIT(RCC_MP_APB5ENSETR_USART1EN_POS) #define RCC_MP_APB5ENSETR_RTCAPBEN BIT(RCC_MP_APB5ENSETR_RTCAPBEN_POS) #define RCC_MP_APB5ENSETR_TZC1EN BIT(RCC_MP_APB5ENSETR_TZC1EN_POS) #define RCC_MP_APB5ENSETR_TZC2EN BIT(RCC_MP_APB5ENSETR_TZC2EN_POS) #define RCC_MP_APB5ENSETR_TZPCEN BIT(RCC_MP_APB5ENSETR_TZPCEN_POS) #define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(RCC_MP_APB5ENSETR_IWDG1APBEN_POS) #define RCC_MP_APB5ENSETR_BSECEN BIT(RCC_MP_APB5ENSETR_BSECEN_POS) #define RCC_MP_APB5ENSETR_STGENEN BIT(RCC_MP_APB5ENSETR_STGENEN_POS) /* RCC_MP_APB5LPEN(SET|CLR)R bit fields */ #define RCC_MP_APB5LPENSETR_SPI6LPEN BIT(0) #define RCC_MP_APB5LPENSETR_I2C4LPEN BIT(2) #define RCC_MP_APB5LPENSETR_I2C6LPEN BIT(3) #define RCC_MP_APB5LPENSETR_USART1LPEN BIT(4) #define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) #define RCC_MP_APB5LPENSETR_TZC1LPEN BIT(11) #define RCC_MP_APB5LPENSETR_TZC2LPEN BIT(12) #define RCC_MP_APB5LPENSETR_TZPCLPEN BIT(13) #define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) #define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) #define RCC_MP_APB5LPENSETR_STGENLPEN BIT(20) #define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) /* RCC_MP_AHB5RST(SET|CLR)R bit fields */ #define RCC_AHB5RSTSETR_GPIOZRST BIT(0) #define RCC_AHB5RSTSETR_CRYP1RST BIT(4) #define RCC_AHB5RSTSETR_HASH1RST BIT(5) #define RCC_AHB5RSTSETR_RNG1RST BIT(6) #define RCC_AHB5RSTSETR_AXIMCRST BIT(16) /* RCC_MP_AHB5EN(SET|CLR)R bit fields */ #define RCC_MP_AHB5ENSETR_GPIOZEN_POS 0 #define RCC_MP_AHB5ENSETR_CRYP1EN_POS 4 #define RCC_MP_AHB5ENSETR_HASH1EN_POS 5 #define RCC_MP_AHB5ENSETR_RNG1EN_POS 6 #define RCC_MP_AHB5ENSETR_BKPSRAMEN_POS 8 #define RCC_MP_AHB5ENSETR_AXIMCEN_POS 16 #define RCC_MP_AHB5ENSETR_GPIOZEN BIT(RCC_MP_AHB5ENSETR_GPIOZEN_POS) #define RCC_MP_AHB5ENSETR_CRYP1EN BIT(RCC_MP_AHB5ENSETR_CRYP1EN_POS) #define RCC_MP_AHB5ENSETR_HASH1EN BIT(RCC_MP_AHB5ENSETR_HASH1EN_POS) #define RCC_MP_AHB5ENSETR_RNG1EN BIT(RCC_MP_AHB5ENSETR_RNG1EN_POS) #define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(RCC_MP_AHB5ENSETR_BKPSRAMEN_POS) #define RCC_MP_AHB5ENSETR_AXIMCEN BIT(RCC_MP_AHB5ENSETR_AXIMCEN_POS) /* RCC_MP_AHB5LPEN(SET|CLR)R bit fields */ #define RCC_MP_AHB5LPENSETR_GPIOZLPEN BIT(0) #define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) #define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) #define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) #define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) /* RCC_MP_TZAHB6EN(SET|CLR)R bit fields */ #define RCC_MP_TZAHB6ENSETR_MDMA_POS 0 #define RCC_MP_TZAHB6ENSETR_MDMA BIT(RCC_MP_TZAHB6ENSETR_MDMA_POS) /* RCC_MP_IWDGFZ(SET|CLR)R bit fields */ #define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) #define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) #define DT_RCC_CLK_COMPAT "st,stm32mp1-rcc" #define DT_RCC_SECURE_CLK_COMPAT "st,stm32mp1-rcc-secure" #ifndef __ASSEMBLER__ #include static inline bool stm32_rcc_is_secure(void) { return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_TZEN; } static inline bool stm32_rcc_is_mckprot(void) { return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_MCKPROT; } static inline void stm32_rcc_set_mckprot(bool enable) { vaddr_t tzcr_reg = stm32_rcc_base() + RCC_TZCR; if (enable) io_setbits32(tzcr_reg, RCC_TZCR_MCKPROT); else io_clrbits32(tzcr_reg, RCC_TZCR_MCKPROT); } #endif /*__ASSEMBLER__*/ #endif /*__DRIVERS_STM32MP1_RCC_H__*/ optee_os-4.3.0/core/include/drivers/stm32mp25_rcc.h000066400000000000000000002307631464416617300220670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024, STMicroelectronics */ #ifndef __DRIVERS_STM32MP25_RCC_H #define __DRIVERS_STM32MP25_RCC_H #include #define RCC_SECCFGR0 U(0x0) #define RCC_SECCFGR1 U(0x4) #define RCC_SECCFGR2 U(0x8) #define RCC_SECCFGR3 U(0xC) #define RCC_PRIVCFGR0 U(0x10) #define RCC_PRIVCFGR1 U(0x14) #define RCC_PRIVCFGR2 U(0x18) #define RCC_PRIVCFGR3 U(0x1C) #define RCC_RCFGLOCKR0 U(0x20) #define RCC_RCFGLOCKR1 U(0x24) #define RCC_RCFGLOCKR2 U(0x28) #define RCC_RCFGLOCKR3 U(0x2C) #define RCC_R0CIDCFGR U(0x30) #define RCC_R0SEMCR U(0x34) #define RCC_R1CIDCFGR U(0x38) #define RCC_R1SEMCR U(0x3C) #define RCC_R2CIDCFGR U(0x40) #define RCC_R2SEMCR U(0x44) #define RCC_R3CIDCFGR U(0x48) #define RCC_R3SEMCR U(0x4C) #define RCC_R4CIDCFGR U(0x50) #define RCC_R4SEMCR U(0x54) #define RCC_R5CIDCFGR U(0x58) #define RCC_R5SEMCR U(0x5C) #define RCC_R6CIDCFGR U(0x60) #define RCC_R6SEMCR U(0x64) #define RCC_R7CIDCFGR U(0x68) #define RCC_R7SEMCR U(0x6C) #define RCC_R8CIDCFGR U(0x70) #define RCC_R8SEMCR U(0x74) #define RCC_R9CIDCFGR U(0x78) #define RCC_R9SEMCR U(0x7C) #define RCC_R10CIDCFGR U(0x80) #define RCC_R10SEMCR U(0x84) #define RCC_R11CIDCFGR U(0x88) #define RCC_R11SEMCR U(0x8C) #define RCC_R12CIDCFGR U(0x90) #define RCC_R12SEMCR U(0x94) #define RCC_R13CIDCFGR U(0x98) #define RCC_R13SEMCR U(0x9C) #define RCC_R14CIDCFGR U(0xA0) #define RCC_R14SEMCR U(0xA4) #define RCC_R15CIDCFGR U(0xA8) #define RCC_R15SEMCR U(0xAC) #define RCC_R16CIDCFGR U(0xB0) #define RCC_R16SEMCR U(0xB4) #define RCC_R17CIDCFGR U(0xB8) #define RCC_R17SEMCR U(0xBC) #define RCC_R18CIDCFGR U(0xC0) #define RCC_R18SEMCR U(0xC4) #define RCC_R19CIDCFGR U(0xC8) #define RCC_R19SEMCR U(0xCC) #define RCC_R20CIDCFGR U(0xD0) #define RCC_R20SEMCR U(0xD4) #define RCC_R21CIDCFGR U(0xD8) #define RCC_R21SEMCR U(0xDC) #define RCC_R22CIDCFGR U(0xE0) #define RCC_R22SEMCR U(0xE4) #define RCC_R23CIDCFGR U(0xE8) #define RCC_R23SEMCR U(0xEC) #define RCC_R24CIDCFGR U(0xF0) #define RCC_R24SEMCR U(0xF4) #define RCC_R25CIDCFGR U(0xF8) #define RCC_R25SEMCR U(0xFC) #define RCC_R26CIDCFGR U(0x100) #define RCC_R26SEMCR U(0x104) #define RCC_R27CIDCFGR U(0x108) #define RCC_R27SEMCR U(0x10C) #define RCC_R28CIDCFGR U(0x110) #define RCC_R28SEMCR U(0x114) #define RCC_R29CIDCFGR U(0x118) #define RCC_R29SEMCR U(0x11C) #define RCC_R30CIDCFGR U(0x120) #define RCC_R30SEMCR U(0x124) #define RCC_R31CIDCFGR U(0x128) #define RCC_R31SEMCR U(0x12C) #define RCC_R32CIDCFGR U(0x130) #define RCC_R32SEMCR U(0x134) #define RCC_R33CIDCFGR U(0x138) #define RCC_R33SEMCR U(0x13C) #define RCC_R34CIDCFGR U(0x140) #define RCC_R34SEMCR U(0x144) #define RCC_R35CIDCFGR U(0x148) #define RCC_R35SEMCR U(0x14C) #define RCC_R36CIDCFGR U(0x150) #define RCC_R36SEMCR U(0x154) #define RCC_R37CIDCFGR U(0x158) #define RCC_R37SEMCR U(0x15C) #define RCC_R38CIDCFGR U(0x160) #define RCC_R38SEMCR U(0x164) #define RCC_R39CIDCFGR U(0x168) #define RCC_R39SEMCR U(0x16C) #define RCC_R40CIDCFGR U(0x170) #define RCC_R40SEMCR U(0x174) #define RCC_R41CIDCFGR U(0x178) #define RCC_R41SEMCR U(0x17C) #define RCC_R42CIDCFGR U(0x180) #define RCC_R42SEMCR U(0x184) #define RCC_R43CIDCFGR U(0x188) #define RCC_R43SEMCR U(0x18C) #define RCC_R44CIDCFGR U(0x190) #define RCC_R44SEMCR U(0x194) #define RCC_R45CIDCFGR U(0x198) #define RCC_R45SEMCR U(0x19C) #define RCC_R46CIDCFGR U(0x1A0) #define RCC_R46SEMCR U(0x1A4) #define RCC_R47CIDCFGR U(0x1A8) #define RCC_R47SEMCR U(0x1AC) #define RCC_R48CIDCFGR U(0x1B0) #define RCC_R48SEMCR U(0x1B4) #define RCC_R49CIDCFGR U(0x1B8) #define RCC_R49SEMCR U(0x1BC) #define RCC_R50CIDCFGR U(0x1C0) #define RCC_R50SEMCR U(0x1C4) #define RCC_R51CIDCFGR U(0x1C8) #define RCC_R51SEMCR U(0x1CC) #define RCC_R52CIDCFGR U(0x1D0) #define RCC_R52SEMCR U(0x1D4) #define RCC_R53CIDCFGR U(0x1D8) #define RCC_R53SEMCR U(0x1DC) #define RCC_R54CIDCFGR U(0x1E0) #define RCC_R54SEMCR U(0x1E4) #define RCC_R55CIDCFGR U(0x1E8) #define RCC_R55SEMCR U(0x1EC) #define RCC_R56CIDCFGR U(0x1F0) #define RCC_R56SEMCR U(0x1F4) #define RCC_R57CIDCFGR U(0x1F8) #define RCC_R57SEMCR U(0x1FC) #define RCC_R58CIDCFGR U(0x200) #define RCC_R58SEMCR U(0x204) #define RCC_R59CIDCFGR U(0x208) #define RCC_R59SEMCR U(0x20C) #define RCC_R60CIDCFGR U(0x210) #define RCC_R60SEMCR U(0x214) #define RCC_R61CIDCFGR U(0x218) #define RCC_R61SEMCR U(0x21C) #define RCC_R62CIDCFGR U(0x220) #define RCC_R62SEMCR U(0x224) #define RCC_R63CIDCFGR U(0x228) #define RCC_R63SEMCR U(0x22C) #define RCC_R64CIDCFGR U(0x230) #define RCC_R64SEMCR U(0x234) #define RCC_R65CIDCFGR U(0x238) #define RCC_R65SEMCR U(0x23C) #define RCC_R66CIDCFGR U(0x240) #define RCC_R66SEMCR U(0x244) #define RCC_R67CIDCFGR U(0x248) #define RCC_R67SEMCR U(0x24C) #define RCC_R68CIDCFGR U(0x250) #define RCC_R68SEMCR U(0x254) #define RCC_R69CIDCFGR U(0x258) #define RCC_R69SEMCR U(0x25C) #define RCC_R70CIDCFGR U(0x260) #define RCC_R70SEMCR U(0x264) #define RCC_R71CIDCFGR U(0x268) #define RCC_R71SEMCR U(0x26C) #define RCC_R72CIDCFGR U(0x270) #define RCC_R72SEMCR U(0x274) #define RCC_R73CIDCFGR U(0x278) #define RCC_R73SEMCR U(0x27C) #define RCC_R74CIDCFGR U(0x280) #define RCC_R74SEMCR U(0x284) #define RCC_R75CIDCFGR U(0x288) #define RCC_R75SEMCR U(0x28C) #define RCC_R76CIDCFGR U(0x290) #define RCC_R76SEMCR U(0x294) #define RCC_R77CIDCFGR U(0x298) #define RCC_R77SEMCR U(0x29C) #define RCC_R78CIDCFGR U(0x2A0) #define RCC_R78SEMCR U(0x2A4) #define RCC_R79CIDCFGR U(0x2A8) #define RCC_R79SEMCR U(0x2AC) #define RCC_R80CIDCFGR U(0x2B0) #define RCC_R80SEMCR U(0x2B4) #define RCC_R81CIDCFGR U(0x2B8) #define RCC_R81SEMCR U(0x2BC) #define RCC_R82CIDCFGR U(0x2C0) #define RCC_R82SEMCR U(0x2C4) #define RCC_R83CIDCFGR U(0x2C8) #define RCC_R83SEMCR U(0x2CC) #define RCC_R84CIDCFGR U(0x2D0) #define RCC_R84SEMCR U(0x2D4) #define RCC_R85CIDCFGR U(0x2D8) #define RCC_R85SEMCR U(0x2DC) #define RCC_R86CIDCFGR U(0x2E0) #define RCC_R86SEMCR U(0x2E4) #define RCC_R87CIDCFGR U(0x2E8) #define RCC_R87SEMCR U(0x2EC) #define RCC_R88CIDCFGR U(0x2F0) #define RCC_R88SEMCR U(0x2F4) #define RCC_R89CIDCFGR U(0x2F8) #define RCC_R89SEMCR U(0x2FC) #define RCC_R90CIDCFGR U(0x300) #define RCC_R90SEMCR U(0x304) #define RCC_R91CIDCFGR U(0x308) #define RCC_R91SEMCR U(0x30C) #define RCC_R92CIDCFGR U(0x310) #define RCC_R92SEMCR U(0x314) #define RCC_R93CIDCFGR U(0x318) #define RCC_R93SEMCR U(0x31C) #define RCC_R94CIDCFGR U(0x320) #define RCC_R94SEMCR U(0x324) #define RCC_R95CIDCFGR U(0x328) #define RCC_R95SEMCR U(0x32C) #define RCC_R96CIDCFGR U(0x330) #define RCC_R96SEMCR U(0x334) #define RCC_R97CIDCFGR U(0x338) #define RCC_R97SEMCR U(0x33C) #define RCC_R98CIDCFGR U(0x340) #define RCC_R98SEMCR U(0x344) #define RCC_R99CIDCFGR U(0x348) #define RCC_R99SEMCR U(0x34C) #define RCC_R100CIDCFGR U(0x350) #define RCC_R100SEMCR U(0x354) #define RCC_R101CIDCFGR U(0x358) #define RCC_R101SEMCR U(0x35C) #define RCC_R102CIDCFGR U(0x360) #define RCC_R102SEMCR U(0x364) #define RCC_R103CIDCFGR U(0x368) #define RCC_R103SEMCR U(0x36C) #define RCC_R104CIDCFGR U(0x370) #define RCC_R104SEMCR U(0x374) #define RCC_R105CIDCFGR U(0x378) #define RCC_R105SEMCR U(0x37C) #define RCC_R106CIDCFGR U(0x380) #define RCC_R106SEMCR U(0x384) #define RCC_R107CIDCFGR U(0x388) #define RCC_R107SEMCR U(0x38C) #define RCC_R108CIDCFGR U(0x390) #define RCC_R108SEMCR U(0x394) #define RCC_R109CIDCFGR U(0x398) #define RCC_R109SEMCR U(0x39C) #define RCC_R110CIDCFGR U(0x3A0) #define RCC_R110SEMCR U(0x3A4) #define RCC_R111CIDCFGR U(0x3A8) #define RCC_R111SEMCR U(0x3AC) #define RCC_R112CIDCFGR U(0x3B0) #define RCC_R112SEMCR U(0x3B4) #define RCC_R113CIDCFGR U(0x3B8) #define RCC_R113SEMCR U(0x3BC) #define RCC_GRSTCSETR U(0x400) #define RCC_C1RSTCSETR U(0x404) #define RCC_C1P1RSTCSETR U(0x408) #define RCC_C2RSTCSETR U(0x40C) #define RCC_HWRSTSCLRR U(0x410) #define RCC_C1HWRSTSCLRR U(0x414) #define RCC_C2HWRSTSCLRR U(0x418) #define RCC_C1BOOTRSTSSETR U(0x41C) #define RCC_C1BOOTRSTSCLRR U(0x420) #define RCC_C2BOOTRSTSSETR U(0x424) #define RCC_C2BOOTRSTSCLRR U(0x428) #define RCC_C1SREQSETR U(0x42C) #define RCC_C1SREQCLRR U(0x430) #define RCC_CPUBOOTCR U(0x434) #define RCC_STBYBOOTCR U(0x438) #define RCC_LEGBOOTCR U(0x43C) #define RCC_BDCR U(0x440) #define RCC_D3DCR U(0x444) #define RCC_D3DSR U(0x448) #define RCC_RDCR U(0x44C) #define RCC_C1MSRDCR U(0x450) #define RCC_PWRLPDLYCR U(0x454) #define RCC_C1CIESETR U(0x458) #define RCC_C1CIFCLRR U(0x45C) #define RCC_C2CIESETR U(0x460) #define RCC_C2CIFCLRR U(0x464) #define RCC_IWDGC1FZSETR U(0x468) #define RCC_IWDGC1FZCLRR U(0x46C) #define RCC_IWDGC1CFGSETR U(0x470) #define RCC_IWDGC1CFGCLRR U(0x474) #define RCC_IWDGC2FZSETR U(0x478) #define RCC_IWDGC2FZCLRR U(0x47C) #define RCC_IWDGC2CFGSETR U(0x480) #define RCC_IWDGC2CFGCLRR U(0x484) #define RCC_IWDGC3CFGSETR U(0x488) #define RCC_IWDGC3CFGCLRR U(0x48C) #define RCC_C3CFGR U(0x490) #define RCC_MCO1CFGR U(0x494) #define RCC_MCO2CFGR U(0x498) #define RCC_OCENSETR U(0x49C) #define RCC_OCENCLRR U(0x4A0) #define RCC_OCRDYR U(0x4A4) #define RCC_HSICFGR U(0x4A8) #define RCC_MSICFGR U(0x4AC) #define RCC_RTCDIVR U(0x4B0) #define RCC_APB1DIVR U(0x4B4) #define RCC_APB2DIVR U(0x4B8) #define RCC_APB3DIVR U(0x4BC) #define RCC_APB4DIVR U(0x4C0) #define RCC_APBDBGDIVR U(0x4C4) #define RCC_TIMG1PRER U(0x4C8) #define RCC_TIMG2PRER U(0x4CC) #define RCC_LSMCUDIVR U(0x4D0) #define RCC_DDRCPCFGR U(0x4D4) #define RCC_DDRCAPBCFGR U(0x4D8) #define RCC_DDRPHYCAPBCFGR U(0x4DC) #define RCC_DDRPHYCCFGR U(0x4E0) #define RCC_DDRCFGR U(0x4E4) #define RCC_DDRITFCFGR U(0x4E8) #define RCC_SYSRAMCFGR U(0x4F0) #define RCC_VDERAMCFGR U(0x4F4) #define RCC_SRAM1CFGR U(0x4F8) #define RCC_SRAM2CFGR U(0x4FC) #define RCC_RETRAMCFGR U(0x500) #define RCC_BKPSRAMCFGR U(0x504) #define RCC_LPSRAM1CFGR U(0x508) #define RCC_LPSRAM2CFGR U(0x50C) #define RCC_LPSRAM3CFGR U(0x510) #define RCC_OSPI1CFGR U(0x514) #define RCC_OSPI2CFGR U(0x518) #define RCC_FMCCFGR U(0x51C) #define RCC_DBGCFGR U(0x520) #define RCC_STMCFGR U(0x524) #define RCC_ETRCFGR U(0x528) #define RCC_GPIOACFGR U(0x52C) #define RCC_GPIOBCFGR U(0x530) #define RCC_GPIOCCFGR U(0x534) #define RCC_GPIODCFGR U(0x538) #define RCC_GPIOECFGR U(0x53C) #define RCC_GPIOFCFGR U(0x540) #define RCC_GPIOGCFGR U(0x544) #define RCC_GPIOHCFGR U(0x548) #define RCC_GPIOICFGR U(0x54C) #define RCC_GPIOJCFGR U(0x550) #define RCC_GPIOKCFGR U(0x554) #define RCC_GPIOZCFGR U(0x558) #define RCC_HPDMA1CFGR U(0x55C) #define RCC_HPDMA2CFGR U(0x560) #define RCC_HPDMA3CFGR U(0x564) #define RCC_LPDMACFGR U(0x568) #define RCC_HSEMCFGR U(0x56C) #define RCC_IPCC1CFGR U(0x570) #define RCC_IPCC2CFGR U(0x574) #define RCC_RTCCFGR U(0x578) #define RCC_SYSCPU1CFGR U(0x580) #define RCC_BSECCFGR U(0x584) #define RCC_IS2MCFGR U(0x58C) #define RCC_PLL2CFGR1 U(0x590) #define RCC_PLL2CFGR2 U(0x594) #define RCC_PLL2CFGR3 U(0x598) #define RCC_PLL2CFGR4 U(0x59C) #define RCC_PLL2CFGR5 U(0x5A0) #define RCC_PLL2CFGR6 U(0x5A8) #define RCC_PLL2CFGR7 U(0x5AC) #define RCC_PLL3CFGR1 U(0x5B8) #define RCC_PLL3CFGR2 U(0x5BC) #define RCC_PLL3CFGR3 U(0x5C0) #define RCC_PLL3CFGR4 U(0x5C4) #define RCC_PLL3CFGR5 U(0x5C8) #define RCC_PLL3CFGR6 U(0x5D0) #define RCC_PLL3CFGR7 U(0x5D4) #define RCC_HSIFMONCR U(0x5E0) #define RCC_HSIFVALR U(0x5E4) #define RCC_TIM1CFGR U(0x700) #define RCC_TIM2CFGR U(0x704) #define RCC_TIM3CFGR U(0x708) #define RCC_TIM4CFGR U(0x70C) #define RCC_TIM5CFGR U(0x710) #define RCC_TIM6CFGR U(0x714) #define RCC_TIM7CFGR U(0x718) #define RCC_TIM8CFGR U(0x71C) #define RCC_TIM10CFGR U(0x720) #define RCC_TIM11CFGR U(0x724) #define RCC_TIM12CFGR U(0x728) #define RCC_TIM13CFGR U(0x72C) #define RCC_TIM14CFGR U(0x730) #define RCC_TIM15CFGR U(0x734) #define RCC_TIM16CFGR U(0x738) #define RCC_TIM17CFGR U(0x73C) #define RCC_TIM20CFGR U(0x740) #define RCC_LPTIM1CFGR U(0x744) #define RCC_LPTIM2CFGR U(0x748) #define RCC_LPTIM3CFGR U(0x74C) #define RCC_LPTIM4CFGR U(0x750) #define RCC_LPTIM5CFGR U(0x754) #define RCC_SPI1CFGR U(0x758) #define RCC_SPI2CFGR U(0x75C) #define RCC_SPI3CFGR U(0x760) #define RCC_SPI4CFGR U(0x764) #define RCC_SPI5CFGR U(0x768) #define RCC_SPI6CFGR U(0x76C) #define RCC_SPI7CFGR U(0x770) #define RCC_SPI8CFGR U(0x774) #define RCC_SPDIFRXCFGR U(0x778) #define RCC_USART1CFGR U(0x77C) #define RCC_USART2CFGR U(0x780) #define RCC_USART3CFGR U(0x784) #define RCC_UART4CFGR U(0x788) #define RCC_UART5CFGR U(0x78C) #define RCC_USART6CFGR U(0x790) #define RCC_UART7CFGR U(0x794) #define RCC_UART8CFGR U(0x798) #define RCC_UART9CFGR U(0x79C) #define RCC_LPUART1CFGR U(0x7A0) #define RCC_I2C1CFGR U(0x7A4) #define RCC_I2C2CFGR U(0x7A8) #define RCC_I2C3CFGR U(0x7AC) #define RCC_I2C4CFGR U(0x7B0) #define RCC_I2C5CFGR U(0x7B4) #define RCC_I2C6CFGR U(0x7B8) #define RCC_I2C7CFGR U(0x7BC) #define RCC_I2C8CFGR U(0x7C0) #define RCC_SAI1CFGR U(0x7C4) #define RCC_SAI2CFGR U(0x7C8) #define RCC_SAI3CFGR U(0x7CC) #define RCC_SAI4CFGR U(0x7D0) #define RCC_MDF1CFGR U(0x7D8) #define RCC_ADF1CFGR U(0x7DC) #define RCC_FDCANCFGR U(0x7E0) #define RCC_HDPCFGR U(0x7E4) #define RCC_ADC12CFGR U(0x7E8) #define RCC_ADC3CFGR U(0x7EC) #define RCC_ETH1CFGR U(0x7F0) #define RCC_ETH2CFGR U(0x7F4) #define RCC_USB2CFGR U(0x7FC) #define RCC_USB2PHY1CFGR U(0x800) #define RCC_USB2PHY2CFGR U(0x804) #define RCC_USB3DRCFGR U(0x808) #define RCC_USB3PCIEPHYCFGR U(0x80C) #define RCC_PCIECFGR U(0x810) #define RCC_USBTCCFGR U(0x814) #define RCC_ETHSWCFGR U(0x818) #define RCC_ETHSWACMCFGR U(0x81C) #define RCC_ETHSWACMMSGCFGR U(0x820) #define RCC_STGENCFGR U(0x824) #define RCC_SDMMC1CFGR U(0x830) #define RCC_SDMMC2CFGR U(0x834) #define RCC_SDMMC3CFGR U(0x838) #define RCC_GPUCFGR U(0x83C) #define RCC_LTDCCFGR U(0x840) #define RCC_DSICFGR U(0x844) #define RCC_LVDSCFGR U(0x850) #define RCC_CSICFGR U(0x858) #define RCC_DCMIPPCFGR U(0x85C) #define RCC_CCICFGR U(0x860) #define RCC_VDECCFGR U(0x864) #define RCC_VENCCFGR U(0x868) #define RCC_RNGCFGR U(0x870) #define RCC_PKACFGR U(0x874) #define RCC_SAESCFGR U(0x878) #define RCC_HASHCFGR U(0x87C) #define RCC_CRYP1CFGR U(0x880) #define RCC_CRYP2CFGR U(0x884) #define RCC_IWDG1CFGR U(0x888) #define RCC_IWDG2CFGR U(0x88C) #define RCC_IWDG3CFGR U(0x890) #define RCC_IWDG4CFGR U(0x894) #define RCC_IWDG5CFGR U(0x898) #define RCC_WWDG1CFGR U(0x89C) #define RCC_WWDG2CFGR U(0x8A0) #define RCC_VREFCFGR U(0x8A8) #define RCC_DTSCFGR U(0x8AC) #define RCC_CRCCFGR U(0x8B4) #define RCC_SERCCFGR U(0x8B8) #define RCC_OSPIIOMCFGR U(0x8BC) #define RCC_GICV2MCFGR U(0x8C0) #define RCC_I3C1CFGR U(0x8C8) #define RCC_I3C2CFGR U(0x8CC) #define RCC_I3C3CFGR U(0x8D0) #define RCC_I3C4CFGR U(0x8D4) #define RCC_MUXSELCFGR U(0x1000) #define RCC_XBAR0CFGR U(0x1018) #define RCC_XBAR1CFGR U(0x101C) #define RCC_XBAR2CFGR U(0x1020) #define RCC_XBAR3CFGR U(0x1024) #define RCC_XBAR4CFGR U(0x1028) #define RCC_XBAR5CFGR U(0x102C) #define RCC_XBAR6CFGR U(0x1030) #define RCC_XBAR7CFGR U(0x1034) #define RCC_XBAR8CFGR U(0x1038) #define RCC_XBAR9CFGR U(0x103C) #define RCC_XBAR10CFGR U(0x1040) #define RCC_XBAR11CFGR U(0x1044) #define RCC_XBAR12CFGR U(0x1048) #define RCC_XBAR13CFGR U(0x104C) #define RCC_XBAR14CFGR U(0x1050) #define RCC_XBAR15CFGR U(0x1054) #define RCC_XBAR16CFGR U(0x1058) #define RCC_XBAR17CFGR U(0x105C) #define RCC_XBAR18CFGR U(0x1060) #define RCC_XBAR19CFGR U(0x1064) #define RCC_XBAR20CFGR U(0x1068) #define RCC_XBAR21CFGR U(0x106C) #define RCC_XBAR22CFGR U(0x1070) #define RCC_XBAR23CFGR U(0x1074) #define RCC_XBAR24CFGR U(0x1078) #define RCC_XBAR25CFGR U(0x107C) #define RCC_XBAR26CFGR U(0x1080) #define RCC_XBAR27CFGR U(0x1084) #define RCC_XBAR28CFGR U(0x1088) #define RCC_XBAR29CFGR U(0x108C) #define RCC_XBAR30CFGR U(0x1090) #define RCC_XBAR31CFGR U(0x1094) #define RCC_XBAR32CFGR U(0x1098) #define RCC_XBAR33CFGR U(0x109C) #define RCC_XBAR34CFGR U(0x10A0) #define RCC_XBAR35CFGR U(0x10A4) #define RCC_XBAR36CFGR U(0x10A8) #define RCC_XBAR37CFGR U(0x10AC) #define RCC_XBAR38CFGR U(0x10B0) #define RCC_XBAR39CFGR U(0x10B4) #define RCC_XBAR40CFGR U(0x10B8) #define RCC_XBAR41CFGR U(0x10BC) #define RCC_XBAR42CFGR U(0x10C0) #define RCC_XBAR43CFGR U(0x10C4) #define RCC_XBAR44CFGR U(0x10C8) #define RCC_XBAR45CFGR U(0x10CC) #define RCC_XBAR46CFGR U(0x10D0) #define RCC_XBAR47CFGR U(0x10D4) #define RCC_XBAR48CFGR U(0x10D8) #define RCC_XBAR49CFGR U(0x10DC) #define RCC_XBAR50CFGR U(0x10E0) #define RCC_XBAR51CFGR U(0x10E4) #define RCC_XBAR52CFGR U(0x10E8) #define RCC_XBAR53CFGR U(0x10EC) #define RCC_XBAR54CFGR U(0x10F0) #define RCC_XBAR55CFGR U(0x10F4) #define RCC_XBAR56CFGR U(0x10F8) #define RCC_XBAR57CFGR U(0x10FC) #define RCC_XBAR58CFGR U(0x1100) #define RCC_XBAR59CFGR U(0x1104) #define RCC_XBAR60CFGR U(0x1108) #define RCC_XBAR61CFGR U(0x110C) #define RCC_XBAR62CFGR U(0x1110) #define RCC_XBAR63CFGR U(0x1114) #define RCC_PREDIV0CFGR U(0x1118) #define RCC_PREDIV1CFGR U(0x111C) #define RCC_PREDIV2CFGR U(0x1120) #define RCC_PREDIV3CFGR U(0x1124) #define RCC_PREDIV4CFGR U(0x1128) #define RCC_PREDIV5CFGR U(0x112C) #define RCC_PREDIV6CFGR U(0x1130) #define RCC_PREDIV7CFGR U(0x1134) #define RCC_PREDIV8CFGR U(0x1138) #define RCC_PREDIV9CFGR U(0x113C) #define RCC_PREDIV10CFGR U(0x1140) #define RCC_PREDIV11CFGR U(0x1144) #define RCC_PREDIV12CFGR U(0x1148) #define RCC_PREDIV13CFGR U(0x114C) #define RCC_PREDIV14CFGR U(0x1150) #define RCC_PREDIV15CFGR U(0x1154) #define RCC_PREDIV16CFGR U(0x1158) #define RCC_PREDIV17CFGR U(0x115C) #define RCC_PREDIV18CFGR U(0x1160) #define RCC_PREDIV19CFGR U(0x1164) #define RCC_PREDIV20CFGR U(0x1168) #define RCC_PREDIV21CFGR U(0x116C) #define RCC_PREDIV22CFGR U(0x1170) #define RCC_PREDIV23CFGR U(0x1174) #define RCC_PREDIV24CFGR U(0x1178) #define RCC_PREDIV25CFGR U(0x117C) #define RCC_PREDIV26CFGR U(0x1180) #define RCC_PREDIV27CFGR U(0x1184) #define RCC_PREDIV28CFGR U(0x1188) #define RCC_PREDIV29CFGR U(0x118C) #define RCC_PREDIV30CFGR U(0x1190) #define RCC_PREDIV31CFGR U(0x1194) #define RCC_PREDIV32CFGR U(0x1198) #define RCC_PREDIV33CFGR U(0x119C) #define RCC_PREDIV34CFGR U(0x11A0) #define RCC_PREDIV35CFGR U(0x11A4) #define RCC_PREDIV36CFGR U(0x11A8) #define RCC_PREDIV37CFGR U(0x11AC) #define RCC_PREDIV38CFGR U(0x11B0) #define RCC_PREDIV39CFGR U(0x11B4) #define RCC_PREDIV40CFGR U(0x11B8) #define RCC_PREDIV41CFGR U(0x11BC) #define RCC_PREDIV42CFGR U(0x11C0) #define RCC_PREDIV43CFGR U(0x11C4) #define RCC_PREDIV44CFGR U(0x11C8) #define RCC_PREDIV45CFGR U(0x11CC) #define RCC_PREDIV46CFGR U(0x11D0) #define RCC_PREDIV47CFGR U(0x11D4) #define RCC_PREDIV48CFGR U(0x11D8) #define RCC_PREDIV49CFGR U(0x11DC) #define RCC_PREDIV50CFGR U(0x11E0) #define RCC_PREDIV51CFGR U(0x11E4) #define RCC_PREDIV52CFGR U(0x11E8) #define RCC_PREDIV53CFGR U(0x11EC) #define RCC_PREDIV54CFGR U(0x11F0) #define RCC_PREDIV55CFGR U(0x11F4) #define RCC_PREDIV56CFGR U(0x11F8) #define RCC_PREDIV57CFGR U(0x11FC) #define RCC_PREDIV58CFGR U(0x1200) #define RCC_PREDIV59CFGR U(0x1204) #define RCC_PREDIV60CFGR U(0x1208) #define RCC_PREDIV61CFGR U(0x120C) #define RCC_PREDIV62CFGR U(0x1210) #define RCC_PREDIV63CFGR U(0x1214) #define RCC_PREDIVSR1 U(0x1218) #define RCC_PREDIVSR2 U(0x121C) #define RCC_FINDIV0CFGR U(0x1224) #define RCC_FINDIV1CFGR U(0x1228) #define RCC_FINDIV2CFGR U(0x122C) #define RCC_FINDIV3CFGR U(0x1230) #define RCC_FINDIV4CFGR U(0x1234) #define RCC_FINDIV5CFGR U(0x1238) #define RCC_FINDIV6CFGR U(0x123C) #define RCC_FINDIV7CFGR U(0x1240) #define RCC_FINDIV8CFGR U(0x1244) #define RCC_FINDIV9CFGR U(0x1248) #define RCC_FINDIV10CFGR U(0x124C) #define RCC_FINDIV11CFGR U(0x1250) #define RCC_FINDIV12CFGR U(0x1254) #define RCC_FINDIV13CFGR U(0x1258) #define RCC_FINDIV14CFGR U(0x125C) #define RCC_FINDIV15CFGR U(0x1260) #define RCC_FINDIV16CFGR U(0x1264) #define RCC_FINDIV17CFGR U(0x1268) #define RCC_FINDIV18CFGR U(0x126C) #define RCC_FINDIV19CFGR U(0x1270) #define RCC_FINDIV20CFGR U(0x1274) #define RCC_FINDIV21CFGR U(0x1278) #define RCC_FINDIV22CFGR U(0x127C) #define RCC_FINDIV23CFGR U(0x1280) #define RCC_FINDIV24CFGR U(0x1284) #define RCC_FINDIV25CFGR U(0x1288) #define RCC_FINDIV26CFGR U(0x128C) #define RCC_FINDIV27CFGR U(0x1290) #define RCC_FINDIV28CFGR U(0x1294) #define RCC_FINDIV29CFGR U(0x1298) #define RCC_FINDIV30CFGR U(0x129C) #define RCC_FINDIV31CFGR U(0x12A0) #define RCC_FINDIV32CFGR U(0x12A4) #define RCC_FINDIV33CFGR U(0x12A8) #define RCC_FINDIV34CFGR U(0x12AC) #define RCC_FINDIV35CFGR U(0x12B0) #define RCC_FINDIV36CFGR U(0x12B4) #define RCC_FINDIV37CFGR U(0x12B8) #define RCC_FINDIV38CFGR U(0x12BC) #define RCC_FINDIV39CFGR U(0x12C0) #define RCC_FINDIV40CFGR U(0x12C4) #define RCC_FINDIV41CFGR U(0x12C8) #define RCC_FINDIV42CFGR U(0x12CC) #define RCC_FINDIV43CFGR U(0x12D0) #define RCC_FINDIV44CFGR U(0x12D4) #define RCC_FINDIV45CFGR U(0x12D8) #define RCC_FINDIV46CFGR U(0x12DC) #define RCC_FINDIV47CFGR U(0x12E0) #define RCC_FINDIV48CFGR U(0x12E4) #define RCC_FINDIV49CFGR U(0x12E8) #define RCC_FINDIV50CFGR U(0x12EC) #define RCC_FINDIV51CFGR U(0x12F0) #define RCC_FINDIV52CFGR U(0x12F4) #define RCC_FINDIV53CFGR U(0x12F8) #define RCC_FINDIV54CFGR U(0x12FC) #define RCC_FINDIV55CFGR U(0x1300) #define RCC_FINDIV56CFGR U(0x1304) #define RCC_FINDIV57CFGR U(0x1308) #define RCC_FINDIV58CFGR U(0x130C) #define RCC_FINDIV59CFGR U(0x1310) #define RCC_FINDIV60CFGR U(0x1314) #define RCC_FINDIV61CFGR U(0x1318) #define RCC_FINDIV62CFGR U(0x131C) #define RCC_FINDIV63CFGR U(0x1320) #define RCC_FINDIVSR1 U(0x1324) #define RCC_FINDIVSR2 U(0x1328) #define RCC_FCALCOBS0CFGR U(0x1340) #define RCC_FCALCOBS1CFGR U(0x1344) #define RCC_FCALCREFCFGR U(0x1348) #define RCC_FCALCCR1 U(0x134C) #define RCC_FCALCCR2 U(0x1354) #define RCC_FCALCSR U(0x1358) #define RCC_PLL4CFGR1 U(0x1360) #define RCC_PLL4CFGR2 U(0x1364) #define RCC_PLL4CFGR3 U(0x1368) #define RCC_PLL4CFGR4 U(0x136C) #define RCC_PLL4CFGR5 U(0x1370) #define RCC_PLL4CFGR6 U(0x1378) #define RCC_PLL4CFGR7 U(0x137C) #define RCC_PLL5CFGR1 U(0x1388) #define RCC_PLL5CFGR2 U(0x138C) #define RCC_PLL5CFGR3 U(0x1390) #define RCC_PLL5CFGR4 U(0x1394) #define RCC_PLL5CFGR5 U(0x1398) #define RCC_PLL5CFGR6 U(0x13A0) #define RCC_PLL5CFGR7 U(0x13A4) #define RCC_PLL6CFGR1 U(0x13B0) #define RCC_PLL6CFGR2 U(0x13B4) #define RCC_PLL6CFGR3 U(0x13B8) #define RCC_PLL6CFGR4 U(0x13BC) #define RCC_PLL6CFGR5 U(0x13C0) #define RCC_PLL6CFGR6 U(0x13C8) #define RCC_PLL6CFGR7 U(0x13CC) #define RCC_PLL7CFGR1 U(0x13D8) #define RCC_PLL7CFGR2 U(0x13DC) #define RCC_PLL7CFGR3 U(0x13E0) #define RCC_PLL7CFGR4 U(0x13E4) #define RCC_PLL7CFGR5 U(0x13E8) #define RCC_PLL7CFGR6 U(0x13F0) #define RCC_PLL7CFGR7 U(0x13F4) #define RCC_PLL8CFGR1 U(0x1400) #define RCC_PLL8CFGR2 U(0x1404) #define RCC_PLL8CFGR3 U(0x1408) #define RCC_PLL8CFGR4 U(0x140C) #define RCC_PLL8CFGR5 U(0x1410) #define RCC_PLL8CFGR6 U(0x1418) #define RCC_PLL8CFGR7 U(0x141C) #define RCC_VERR U(0xFFF4) #define RCC_IDR U(0xFFF8) #define RCC_SIDR U(0xFFFC) /* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ #define RCC_MP_ENCLRR_OFFSET U(4) /* RCC_GRSTCSETR register fields */ #define RCC_GRSTCSETR_SYSRST BIT(0) /* RCC_C1RSTCSETR register fields */ #define RCC_C1RSTCSETR_C1RST BIT(0) /* RCC_C1P1RSTCSETR register fields */ #define RCC_C1P1RSTCSETR_C1P1PORRST BIT(0) #define RCC_C1P1RSTCSETR_C1P1RST BIT(1) /* RCC_C2RSTCSETR register fields */ #define RCC_C2RSTCSETR_C2RST BIT(0) /* RCC_CxRSTCSETR register fields */ #define RCC_CxRSTCSETR_CxRST BIT(0) /* RCC_HWRSTSCLRR register fields */ #define RCC_HWRSTSCLRR_PORRSTF BIT(0) #define RCC_HWRSTSCLRR_BORRSTF BIT(1) #define RCC_HWRSTSCLRR_PADRSTF BIT(2) #define RCC_HWRSTSCLRR_HCSSRSTF BIT(3) #define RCC_HWRSTSCLRR_VCORERSTF BIT(4) #define RCC_HWRSTSCLRR_SYSC1RSTF BIT(5) #define RCC_HWRSTSCLRR_SYSC2RSTF BIT(6) #define RCC_HWRSTSCLRR_IWDG1SYSRSTF BIT(7) #define RCC_HWRSTSCLRR_IWDG2SYSRSTF BIT(8) #define RCC_HWRSTSCLRR_IWDG3SYSRSTF BIT(9) #define RCC_HWRSTSCLRR_IWDG4SYSRSTF BIT(10) #define RCC_HWRSTSCLRR_IWDG5SYSRSTF BIT(11) #define RCC_HWRSTSCLRR_RETCRCERRRSTF BIT(12) #define RCC_HWRSTSCLRR_RETECCFAILCRCRSTF BIT(13) #define RCC_HWRSTSCLRR_RETECCFAILRESTRSTF BIT(14) /* RCC_C1HWRSTSCLRR register fields */ #define RCC_C1HWRSTSCLRR_VCPURSTF BIT(0) #define RCC_C1HWRSTSCLRR_C1RSTF BIT(1) #define RCC_C1HWRSTSCLRR_C1P1RSTF BIT(2) /* RCC_C2HWRSTSCLRR register fields */ #define RCC_C2HWRSTSCLRR_C2RSTF BIT(0) /* RCC_C1BOOTRSTSSETR register fields */ #define RCC_C1BOOTRSTSSETR_PORRSTF BIT(0) #define RCC_C1BOOTRSTSSETR_BORRSTF BIT(1) #define RCC_C1BOOTRSTSSETR_PADRSTF BIT(2) #define RCC_C1BOOTRSTSSETR_HCSSRSTF BIT(3) #define RCC_C1BOOTRSTSSETR_VCORERSTF BIT(4) #define RCC_C1BOOTRSTSSETR_VCPURSTF BIT(5) #define RCC_C1BOOTRSTSSETR_SYSC1RSTF BIT(6) #define RCC_C1BOOTRSTSSETR_SYSC2RSTF BIT(7) #define RCC_C1BOOTRSTSSETR_IWDG1SYSRSTF BIT(8) #define RCC_C1BOOTRSTSSETR_IWDG2SYSRSTF BIT(9) #define RCC_C1BOOTRSTSSETR_IWDG3SYSRSTF BIT(10) #define RCC_C1BOOTRSTSSETR_IWDG4SYSRSTF BIT(11) #define RCC_C1BOOTRSTSSETR_IWDG5SYSRSTF BIT(12) #define RCC_C1BOOTRSTSSETR_C1RSTF BIT(13) #define RCC_C1BOOTRSTSSETR_C1P1RSTF BIT(16) #define RCC_C1BOOTRSTSSETR_RETCRCERRRSTF BIT(17) #define RCC_C1BOOTRSTSSETR_RETECCFAILCRCRSTF BIT(18) #define RCC_C1BOOTRSTSSETR_RETECCFAILRESTRSTF BIT(19) #define RCC_C1BOOTRSTSSETR_STBYC1RSTF BIT(20) #define RCC_C1BOOTRSTSSETR_D1STBYRSTF BIT(22) #define RCC_C1BOOTRSTSSETR_D2STBYRSTF BIT(23) /* RCC_C1BOOTRSTSCLRR register fields */ #define RCC_C1BOOTRSTSCLRR_PORRSTF BIT(0) #define RCC_C1BOOTRSTSCLRR_BORRSTF BIT(1) #define RCC_C1BOOTRSTSCLRR_PADRSTF BIT(2) #define RCC_C1BOOTRSTSCLRR_HCSSRSTF BIT(3) #define RCC_C1BOOTRSTSCLRR_VCORERSTF BIT(4) #define RCC_C1BOOTRSTSCLRR_VCPURSTF BIT(5) #define RCC_C1BOOTRSTSCLRR_SYSC1RSTF BIT(6) #define RCC_C1BOOTRSTSCLRR_SYSC2RSTF BIT(7) #define RCC_C1BOOTRSTSCLRR_IWDG1SYSRSTF BIT(8) #define RCC_C1BOOTRSTSCLRR_IWDG2SYSRSTF BIT(9) #define RCC_C1BOOTRSTSCLRR_IWDG3SYSRSTF BIT(10) #define RCC_C1BOOTRSTSCLRR_IWDG4SYSRSTF BIT(11) #define RCC_C1BOOTRSTSCLRR_IWDG5SYSRSTF BIT(12) #define RCC_C1BOOTRSTSCLRR_C1RSTF BIT(13) #define RCC_C1BOOTRSTSCLRR_C1P1RSTF BIT(16) #define RCC_C1BOOTRSTSCLRR_RETCRCERRRSTF BIT(17) #define RCC_C1BOOTRSTSCLRR_RETECCFAILCRCRSTF BIT(18) #define RCC_C1BOOTRSTSCLRR_RETECCFAILRESTRSTF BIT(19) #define RCC_C1BOOTRSTSCLRR_STBYC1RSTF BIT(20) #define RCC_C1BOOTRSTSCLRR_D1STBYRSTF BIT(22) #define RCC_C1BOOTRSTSCLRR_D2STBYRSTF BIT(23) /* RCC_C2BOOTRSTSSETR register fields */ #define RCC_C2BOOTRSTSSETR_PORRSTF BIT(0) #define RCC_C2BOOTRSTSSETR_BORRSTF BIT(1) #define RCC_C2BOOTRSTSSETR_PADRSTF BIT(2) #define RCC_C2BOOTRSTSSETR_HCSSRSTF BIT(3) #define RCC_C2BOOTRSTSSETR_VCORERSTF BIT(4) #define RCC_C2BOOTRSTSSETR_SYSC1RSTF BIT(6) #define RCC_C2BOOTRSTSSETR_SYSC2RSTF BIT(7) #define RCC_C2BOOTRSTSSETR_IWDG1SYSRSTF BIT(8) #define RCC_C2BOOTRSTSSETR_IWDG2SYSRSTF BIT(9) #define RCC_C2BOOTRSTSSETR_IWDG3SYSRSTF BIT(10) #define RCC_C2BOOTRSTSSETR_IWDG4SYSRSTF BIT(11) #define RCC_C2BOOTRSTSSETR_IWDG5SYSRSTF BIT(12) #define RCC_C2BOOTRSTSSETR_C2RSTF BIT(14) #define RCC_C2BOOTRSTSSETR_RETCRCERRRSTF BIT(17) #define RCC_C2BOOTRSTSSETR_RETECCFAILCRCRSTF BIT(18) #define RCC_C2BOOTRSTSSETR_RETECCFAILRESTRSTF BIT(19) #define RCC_C2BOOTRSTSSETR_STBYC2RSTF BIT(21) #define RCC_C2BOOTRSTSSETR_D2STBYRSTF BIT(23) #define RCC_C2BOOTRSTSSETR_IWDG3LOCRSTF BIT(26) #define RCC_C2BOOTRSTSSETR_IWDG4LOCRSTF BIT(27) /* RCC_C2BOOTRSTSCLRR register fields */ #define RCC_C2BOOTRSTSCLRR_PORRSTF BIT(0) #define RCC_C2BOOTRSTSCLRR_BORRSTF BIT(1) #define RCC_C2BOOTRSTSCLRR_PADRSTF BIT(2) #define RCC_C2BOOTRSTSCLRR_HCSSRSTF BIT(3) #define RCC_C2BOOTRSTSCLRR_VCORERSTF BIT(4) #define RCC_C2BOOTRSTSCLRR_SYSC1RSTF BIT(6) #define RCC_C2BOOTRSTSCLRR_SYSC2RSTF BIT(7) #define RCC_C2BOOTRSTSCLRR_IWDG1SYSRSTF BIT(8) #define RCC_C2BOOTRSTSCLRR_IWDG2SYSRSTF BIT(9) #define RCC_C2BOOTRSTSCLRR_IWDG3SYSRSTF BIT(10) #define RCC_C2BOOTRSTSCLRR_IWDG4SYSRSTF BIT(11) #define RCC_C2BOOTRSTSCLRR_IWDG5SYSRSTF BIT(12) #define RCC_C2BOOTRSTSCLRR_C2RSTF BIT(14) #define RCC_C2BOOTRSTSCLRR_RETCRCERRRSTF BIT(17) #define RCC_C2BOOTRSTSCLRR_RETECCFAILCRCRSTF BIT(18) #define RCC_C2BOOTRSTSCLRR_RETECCFAILRESTRSTF BIT(19) #define RCC_C2BOOTRSTSCLRR_STBYC2RSTF BIT(21) #define RCC_C2BOOTRSTSCLRR_D2STBYRSTF BIT(23) /* RCC_C1SREQSETR register fields */ #define RCC_C1SREQSETR_STPREQ_P0 BIT(0) #define RCC_C1SREQSETR_STPREQ_P1 BIT(1) /* RCC_C1SREQCLRR register fields */ #define RCC_C1SREQCLRR_STPREQ_P0 BIT(0) #define RCC_C1SREQCLRR_STPREQ_P1 BIT(1) /* RCC_CPUBOOTCR register fields */ #define RCC_CPUBOOTCR_BOOT_CPU2 BIT(0) #define RCC_CPUBOOTCR_BOOT_CPU1 BIT(1) /* RCC_STBYBOOTCR register fields */ #define RCC_STBYBOOTCR_CPU_BEN_SEL BIT(1) #define RCC_STBYBOOTCR_COLD_CPU2 BIT(2) #define RCC_STBYBOOTCR_CPU2_HW_BEN BIT(4) #define RCC_STBYBOOTCR_CPU1_HW_BEN BIT(5) #define RCC_STBYBOOTCR_RET_CRCERR_RSTEN BIT(8) /* RCC_LEGBOOTCR register fields */ #define RCC_LEGBOOTCR_LEGACY_BEN BIT(0) /* RCC_BDCR register fields */ #define RCC_BDCR_LSEON BIT(0) #define RCC_BDCR_LSEBYP BIT(1) #define RCC_BDCR_LSERDY BIT(2) #define RCC_BDCR_LSEDIGBYP BIT(3) #define RCC_BDCR_LSEDRV_MASK GENMASK_32(5, 4) #define RCC_BDCR_LSEDRV_SHIFT 4 #define RCC_BDCR_LSECSSON BIT(6) #define RCC_BDCR_LSEGFON BIT(7) #define RCC_BDCR_LSECSSD BIT(8) #define RCC_BDCR_LSION BIT(9) #define RCC_BDCR_LSIRDY BIT(10) #define RCC_BDCR_RTCSRC_MASK GENMASK_32(17, 16) #define RCC_BDCR_RTCSRC_SHIFT 16 #define RCC_BDCR_RTCCKEN BIT(20) #define RCC_BDCR_MSIFREQSEL BIT(24) #define RCC_BDCR_C3SYSTICKSEL BIT(25) #define RCC_BDCR_VSWRST BIT(31) #define RCC_BDCR_LSEBYP_BIT 1 #define RCC_BDCR_LSEDIGBYP_BIT 3 #define RCC_BDCR_LSECSSON_BIT 6 #define RCC_BDCR_LSERDY_BIT 2 #define RCC_BDCR_LSIRDY_BIT 10 #define RCC_BDCR_LSEDRV_SHIFT 4 #define RCC_BDCR_LSEDRV_WIDTH 2 /* RCC_D3DCR register fields */ #define RCC_D3DCR_MSION BIT(0) #define RCC_D3DCR_MSIKERON BIT(1) #define RCC_D3DCR_MSIRDY BIT(2) #define RCC_D3DCR_D3PERCKSEL_MASK GENMASK_32(17, 16) #define RCC_D3DCR_D3PERCKSEL_SHIFT 16 #define RCC_D3DCR_MSIRDY_BIT 2 /* RCC_D3DSR register fields */ #define RCC_D3DSR_D3STATE_MASK GENMASK_32(1, 0) #define RCC_D3DSR_D3STATE_SHIFT 0 /* RCC_RDCR register fields */ #define RCC_RDCR_MRD_MASK GENMASK_32(20, 16) #define RCC_RDCR_MRD_SHIFT 16 #define RCC_RDCR_EADLY_MASK GENMASK_32(27, 24) #define RCC_RDCR_EADLY_SHIFT 24 /* RCC_C1MSRDCR register fields */ #define RCC_C1MSRDCR_C1MSRD_MASK GENMASK_32(4, 0) #define RCC_C1MSRDCR_C1MSRD_SHIFT 0 #define RCC_C1MSRDCR_C1MSRST BIT(8) /* RCC_PWRLPDLYCR register fields */ #define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK_32(21, 0) #define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 #define RCC_PWRLPDLYCR_CPU2TMPSKP BIT(24) /* RCC_C1CIESETR register fields */ #define RCC_C1CIESETR_LSIRDYIE BIT(0) #define RCC_C1CIESETR_LSERDYIE BIT(1) #define RCC_C1CIESETR_HSIRDYIE BIT(2) #define RCC_C1CIESETR_HSERDYIE BIT(3) #define RCC_C1CIESETR_MSIRDYIE BIT(4) #define RCC_C1CIESETR_PLL1RDYIE BIT(5) #define RCC_C1CIESETR_PLL2RDYIE BIT(6) #define RCC_C1CIESETR_PLL3RDYIE BIT(7) #define RCC_C1CIESETR_PLL4RDYIE BIT(8) #define RCC_C1CIESETR_PLL5RDYIE BIT(9) #define RCC_C1CIESETR_PLL6RDYIE BIT(10) #define RCC_C1CIESETR_PLL7RDYIE BIT(11) #define RCC_C1CIESETR_PLL8RDYIE BIT(12) #define RCC_C1CIESETR_LSECSSIE BIT(16) #define RCC_C1CIESETR_WKUPIE BIT(20) /* RCC_C1CIFCLRR register fields */ #define RCC_C1CIFCLRR_LSIRDYF BIT(0) #define RCC_C1CIFCLRR_LSERDYF BIT(1) #define RCC_C1CIFCLRR_HSIRDYF BIT(2) #define RCC_C1CIFCLRR_HSERDYF BIT(3) #define RCC_C1CIFCLRR_MSIRDYF BIT(4) #define RCC_C1CIFCLRR_PLL1RDYF BIT(5) #define RCC_C1CIFCLRR_PLL2RDYF BIT(6) #define RCC_C1CIFCLRR_PLL3RDYF BIT(7) #define RCC_C1CIFCLRR_PLL4RDYF BIT(8) #define RCC_C1CIFCLRR_PLL5RDYF BIT(9) #define RCC_C1CIFCLRR_PLL6RDYF BIT(10) #define RCC_C1CIFCLRR_PLL7RDYF BIT(11) #define RCC_C1CIFCLRR_PLL8RDYF BIT(12) #define RCC_C1CIFCLRR_LSECSSF BIT(16) #define RCC_C1CIFCLRR_WKUPF BIT(20) /* RCC_C2CIESETR register fields */ #define RCC_C2CIESETR_LSIRDYIE BIT(0) #define RCC_C2CIESETR_LSERDYIE BIT(1) #define RCC_C2CIESETR_HSIRDYIE BIT(2) #define RCC_C2CIESETR_HSERDYIE BIT(3) #define RCC_C2CIESETR_MSIRDYIE BIT(4) #define RCC_C2CIESETR_PLL1RDYIE BIT(5) #define RCC_C2CIESETR_PLL2RDYIE BIT(6) #define RCC_C2CIESETR_PLL3RDYIE BIT(7) #define RCC_C2CIESETR_PLL4RDYIE BIT(8) #define RCC_C2CIESETR_PLL5RDYIE BIT(9) #define RCC_C2CIESETR_PLL6RDYIE BIT(10) #define RCC_C2CIESETR_PLL7RDYIE BIT(11) #define RCC_C2CIESETR_PLL8RDYIE BIT(12) #define RCC_C2CIESETR_LSECSSIE BIT(16) #define RCC_C2CIESETR_WKUPIE BIT(20) /* RCC_C2CIFCLRR register fields */ #define RCC_C2CIFCLRR_LSIRDYF BIT(0) #define RCC_C2CIFCLRR_LSERDYF BIT(1) #define RCC_C2CIFCLRR_HSIRDYF BIT(2) #define RCC_C2CIFCLRR_HSERDYF BIT(3) #define RCC_C2CIFCLRR_MSIRDYF BIT(4) #define RCC_C2CIFCLRR_PLL1RDYF BIT(5) #define RCC_C2CIFCLRR_PLL2RDYF BIT(6) #define RCC_C2CIFCLRR_PLL3RDYF BIT(7) #define RCC_C2CIFCLRR_PLL4RDYF BIT(8) #define RCC_C2CIFCLRR_PLL5RDYF BIT(9) #define RCC_C2CIFCLRR_PLL6RDYF BIT(10) #define RCC_C2CIFCLRR_PLL7RDYF BIT(11) #define RCC_C2CIFCLRR_PLL8RDYF BIT(12) #define RCC_C2CIFCLRR_LSECSSF BIT(16) #define RCC_C2CIFCLRR_WKUPF BIT(20) /* RCC_CxCIESETR register fields */ #define RCC_CxCIESETR_LSIRDYIE BIT(0) #define RCC_CxCIESETR_LSERDYIE BIT(1) #define RCC_CxCIESETR_HSIRDYIE BIT(2) #define RCC_CxCIESETR_HSERDYIE BIT(3) #define RCC_CxCIESETR_MSIRDYIE BIT(4) #define RCC_CxCIESETR_SHSIRDYIE BIT(5) #define RCC_CxCIESETR_PLL1RDYIE BIT(6) #define RCC_CxCIESETR_PLL2RDYIE BIT(7) #define RCC_CxCIESETR_PLL3RDYIE BIT(8) #define RCC_CxCIESETR_PLL4RDYIE BIT(9) #define RCC_CxCIESETR_PLL5RDYIE BIT(10) #define RCC_CxCIESETR_PLL6RDYIE BIT(11) #define RCC_CxCIESETR_PLL7RDYIE BIT(12) #define RCC_CxCIESETR_PLL8RDYIE BIT(13) #define RCC_CxCIESETR_LSECSSIE BIT(16) #define RCC_CxCIESETR_WKUPIE BIT(20) /* RCC_CxCIFCLRR register fields */ #define RCC_CxCIFCLRR_LSIRDYF BIT(0) #define RCC_CxCIFCLRR_LSERDYF BIT(1) #define RCC_CxCIFCLRR_HSIRDYF BIT(2) #define RCC_CxCIFCLRR_HSERDYF BIT(3) #define RCC_CxCIFCLRR_MSIRDYF BIT(4) #define RCC_CxCIFCLRR_SHSIRDYF BIT(5) #define RCC_CxCIFCLRR_PLL1RDYF BIT(6) #define RCC_CxCIFCLRR_PLL2RDYF BIT(7) #define RCC_CxCIFCLRR_PLL3RDYF BIT(8) #define RCC_CxCIFCLRR_PLL4RDYF BIT(9) #define RCC_CxCIFCLRR_PLL5RDYF BIT(10) #define RCC_CxCIFCLRR_PLL6RDYF BIT(11) #define RCC_CxCIFCLRR_PLL7RDYF BIT(12) #define RCC_CxCIFCLRR_PLL8RDYF BIT(13) #define RCC_CxCIFCLRR_LSECSSF BIT(16) #define RCC_CxCIFCLRR_WKUPF BIT(20) /* RCC_IWDGC1FZSETR register fields */ #define RCC_IWDGC1FZSETR_FZ_IWDG1 BIT(0) #define RCC_IWDGC1FZSETR_FZ_IWDG2 BIT(1) /* RCC_IWDGC1FZCLRR register fields */ #define RCC_IWDGC1FZCLRR_FZ_IWDG1 BIT(0) #define RCC_IWDGC1FZCLRR_FZ_IWDG2 BIT(1) /* RCC_IWDGC1CFGSETR register fields */ #define RCC_IWDGC1CFGSETR_IWDG1_SYSRSTEN BIT(0) #define RCC_IWDGC1CFGSETR_IWDG2_SYSRSTEN BIT(2) #define RCC_IWDGC1CFGSETR_IWDG2_KERRST BIT(18) /* RCC_IWDGC1CFGCLRR register fields */ #define RCC_IWDGC1CFGCLRR_IWDG1_SYSRSTEN BIT(0) #define RCC_IWDGC1CFGCLRR_IWDG2_SYSRSTEN BIT(2) #define RCC_IWDGC1CFGCLRR_IWDG2_KERRST BIT(18) /* RCC_IWDGC2FZSETR register fields */ #define RCC_IWDGC2FZSETR_FZ_IWDG3 BIT(0) #define RCC_IWDGC2FZSETR_FZ_IWDG4 BIT(1) /* RCC_IWDGC2FZCLRR register fields */ #define RCC_IWDGC2FZCLRR_FZ_IWDG3 BIT(0) #define RCC_IWDGC2FZCLRR_FZ_IWDG4 BIT(1) /* RCC_IWDGC2CFGSETR register fields */ #define RCC_IWDGC2CFGSETR_IWDG3_SYSRSTEN BIT(0) #define RCC_IWDGC2CFGSETR_IWDG4_SYSRSTEN BIT(2) #define RCC_IWDGC2CFGSETR_IWDG4_KERRST BIT(18) /* RCC_IWDGC2CFGCLRR register fields */ #define RCC_IWDGC2CFGCLRR_IWDG3_SYSRSTEN BIT(0) #define RCC_IWDGC2CFGCLRR_IWDG4_SYSRSTEN BIT(2) #define RCC_IWDGC2CFGCLRR_IWDG4_KERRST BIT(18) /* RCC_IWDGC3CFGSETR register fields */ #define RCC_IWDGC3CFGSETR_IWDG5_SYSRSTEN BIT(0) /* RCC_IWDGC3CFGCLRR register fields */ #define RCC_IWDGC3CFGCLRR_IWDG5_SYSRSTEN BIT(0) /* RCC_C3CFGR register fields */ #define RCC_C3CFGR_C3RST BIT(0) #define RCC_C3CFGR_C3EN BIT(1) #define RCC_C3CFGR_C3LPEN BIT(2) #define RCC_C3CFGR_C3AMEN BIT(3) #define RCC_C3CFGR_LPTIM3C3EN BIT(16) #define RCC_C3CFGR_LPTIM4C3EN BIT(17) #define RCC_C3CFGR_LPTIM5C3EN BIT(18) #define RCC_C3CFGR_SPI8C3EN BIT(19) #define RCC_C3CFGR_LPUART1C3EN BIT(20) #define RCC_C3CFGR_I2C8C3EN BIT(21) #define RCC_C3CFGR_ADF1C3EN BIT(23) #define RCC_C3CFGR_GPIOZC3EN BIT(24) #define RCC_C3CFGR_LPDMAC3EN BIT(25) #define RCC_C3CFGR_RTCC3EN BIT(26) #define RCC_C3CFGR_I3C4C3EN BIT(27) /* RCC_MCO1CFGR register fields */ #define RCC_MCO1CFGR_MCO1SEL BIT(0) #define RCC_MCO1CFGR_MCO1ON BIT(8) /* RCC_MCO2CFGR register fields */ #define RCC_MCO2CFGR_MCO2SEL BIT(0) #define RCC_MCO2CFGR_MCO2ON BIT(8) /* RCC_MCOxCFGR register fields */ #define RCC_MCOxCFGR_MCOxSEL BIT(0) #define RCC_MCOxCFGR_MCOxON BIT(8) /* RCC_OCENSETR register fields */ #define RCC_OCENSETR_HSION BIT(0) #define RCC_OCENSETR_HSIKERON BIT(1) #define RCC_OCENSETR_HSEDIV2ON BIT(5) #define RCC_OCENSETR_HSEDIV2BYP BIT(6) #define RCC_OCENSETR_HSEDIGBYP BIT(7) #define RCC_OCENSETR_HSEON BIT(8) #define RCC_OCENSETR_HSEKERON BIT(9) #define RCC_OCENSETR_HSEBYP BIT(10) #define RCC_OCENSETR_HSECSSON BIT(11) #define RCC_OCENSETR_HSEDIGBYP_BIT 7 #define RCC_OCENSETR_HSEBYP_BIT 10 #define RCC_OCENSETR_HSECSSON_BIT 11 /* RCC_OCENCLRR register fields */ #define RCC_OCENCLRR_HSION BIT(0) #define RCC_OCENCLRR_HSIKERON BIT(1) #define RCC_OCENCLRR_HSEDIV2ON BIT(5) #define RCC_OCENCLRR_HSEDIV2BYP BIT(6) #define RCC_OCENCLRR_HSEDIGBYP BIT(7) #define RCC_OCENCLRR_HSEON BIT(8) #define RCC_OCENCLRR_HSEKERON BIT(9) #define RCC_OCENCLRR_HSEBYP BIT(10) /* RCC_OCRDYR register fields */ #define RCC_OCRDYR_HSIRDY BIT(0) #define RCC_OCRDYR_HSERDY BIT(8) #define RCC_OCRDYR_CKREST BIT(25) #define RCC_OCRDYR_HSIRDY_BIT 0 #define RCC_OCRDYR_HSERDY_BIT 8 /* RCC_HSICFGR register fields */ #define RCC_HSICFGR_HSITRIM_MASK GENMASK_32(14, 8) #define RCC_HSICFGR_HSITRIM_SHIFT 8 #define RCC_HSICFGR_HSICAL_MASK GENMASK_32(24, 16) #define RCC_HSICFGR_HSICAL_SHIFT 16 /* RCC_MSICFGR register fields */ #define RCC_MSICFGR_MSITRIM_MASK GENMASK_32(12, 8) #define RCC_MSICFGR_MSITRIM_SHIFT 8 #define RCC_MSICFGR_MSICAL_MASK GENMASK_32(23, 16) #define RCC_MSICFGR_MSICAL_SHIFT 16 /* RCC_RTCDIVR register fields */ #define RCC_RTCDIVR_RTCDIV_MASK GENMASK_32(5, 0) #define RCC_RTCDIVR_RTCDIV_SHIFT 0 /* RCC_APB1DIVR register fields */ #define RCC_APB1DIVR_APB1DIV_MASK GENMASK_32(2, 0) #define RCC_APB1DIVR_APB1DIV_SHIFT 0 #define RCC_APB1DIVR_APB1DIVRDY BIT(31) /* RCC_APB2DIVR register fields */ #define RCC_APB2DIVR_APB2DIV_MASK GENMASK_32(2, 0) #define RCC_APB2DIVR_APB2DIV_SHIFT 0 #define RCC_APB2DIVR_APB2DIVRDY BIT(31) /* RCC_APB3DIVR register fields */ #define RCC_APB3DIVR_APB3DIV_MASK GENMASK_32(2, 0) #define RCC_APB3DIVR_APB3DIV_SHIFT 0 #define RCC_APB3DIVR_APB3DIVRDY BIT(31) /* RCC_APB4DIVR register fields */ #define RCC_APB4DIVR_APB4DIV_MASK GENMASK_32(2, 0) #define RCC_APB4DIVR_APB4DIV_SHIFT 0 #define RCC_APB4DIVR_APB4DIVRDY BIT(31) /* RCC_APBDBGDIVR register fields */ #define RCC_APBDBGDIVR_APBDBGDIV_MASK GENMASK_32(2, 0) #define RCC_APBDBGDIVR_APBDBGDIV_SHIFT 0 #define RCC_APBDBGDIVR_APBDBGDIVRDY BIT(31) /* RCC_APBxDIVR register fields */ #define RCC_APBxDIVR_APBxDIV_MASK GENMASK_32(2, 0) #define RCC_APBxDIVR_APBxDIV_SHIFT 0 #define RCC_APBxDIVR_APBxDIVRDY BIT(31) /* RCC_TIMG1PRER register fields */ #define RCC_TIMG1PRER_TIMG1PRE BIT(0) #define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) /* RCC_TIMG2PRER register fields */ #define RCC_TIMG2PRER_TIMG2PRE BIT(0) #define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) /* RCC_TIMGxPRER register fields */ #define RCC_TIMGxPRER_TIMGxPRE BIT(0) #define RCC_TIMGxPRER_TIMGxPRERDY BIT(31) /* RCC_LSMCUDIVR register fields */ #define RCC_LSMCUDIVR_LSMCUDIV BIT(0) #define RCC_LSMCUDIVR_LSMCUDIVRDY BIT(31) /* RCC_DDRCPCFGR register fields */ #define RCC_DDRCPCFGR_DDRCPRST BIT(0) #define RCC_DDRCPCFGR_DDRCPEN BIT(1) #define RCC_DDRCPCFGR_DDRCPLPEN BIT(2) /* RCC_DDRCAPBCFGR register fields */ #define RCC_DDRCAPBCFGR_DDRCAPBRST BIT(0) #define RCC_DDRCAPBCFGR_DDRCAPBEN BIT(1) #define RCC_DDRCAPBCFGR_DDRCAPBLPEN BIT(2) /* RCC_DDRPHYCAPBCFGR register fields */ #define RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST BIT(0) #define RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN BIT(1) #define RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN BIT(2) /* RCC_DDRPHYCCFGR register fields */ #define RCC_DDRPHYCCFGR_DDRPHYCEN BIT(1) /* RCC_DDRCFGR register fields */ #define RCC_DDRCFGR_DDRCFGRST BIT(0) #define RCC_DDRCFGR_DDRCFGEN BIT(1) #define RCC_DDRCFGR_DDRCFGLPEN BIT(2) /* RCC_DDRITFCFGR register fields */ #define RCC_DDRITFCFGR_DDRRST BIT(0) #define RCC_DDRITFCFGR_DDRCKMOD_MASK GENMASK_32(5, 4) #define RCC_DDRITFCFGR_DDRCKMOD_SHIFT 4 #define RCC_DDRITFCFGR_DDRSHR BIT(8) #define RCC_DDRITFCFGR_DDRPHYDLP BIT(16) /* RCC_SYSRAMCFGR register fields */ #define RCC_SYSRAMCFGR_SYSRAMEN BIT(1) #define RCC_SYSRAMCFGR_SYSRAMLPEN BIT(2) /* RCC_VDERAMCFGR register fields */ #define RCC_VDERAMCFGR_VDERAMEN BIT(1) #define RCC_VDERAMCFGR_VDERAMLPEN BIT(2) /* RCC_SRAM1CFGR register fields */ #define RCC_SRAM1CFGR_SRAM1EN BIT(1) #define RCC_SRAM1CFGR_SRAM1LPEN BIT(2) /* RCC_SRAM2CFGR register fields */ #define RCC_SRAM2CFGR_SRAM2EN BIT(1) #define RCC_SRAM2CFGR_SRAM2LPEN BIT(2) /* RCC_RETRAMCFGR register fields */ #define RCC_RETRAMCFGR_RETRAMEN BIT(1) #define RCC_RETRAMCFGR_RETRAMLPEN BIT(2) /* RCC_BKPSRAMCFGR register fields */ #define RCC_BKPSRAMCFGR_BKPSRAMEN BIT(1) #define RCC_BKPSRAMCFGR_BKPSRAMLPEN BIT(2) /* RCC_LPSRAM1CFGR register fields */ #define RCC_LPSRAM1CFGR_LPSRAM1EN BIT(1) #define RCC_LPSRAM1CFGR_LPSRAM1LPEN BIT(2) #define RCC_LPSRAM1CFGR_LPSRAM1AMEN BIT(3) /* RCC_LPSRAM2CFGR register fields */ #define RCC_LPSRAM2CFGR_LPSRAM2EN BIT(1) #define RCC_LPSRAM2CFGR_LPSRAM2LPEN BIT(2) #define RCC_LPSRAM2CFGR_LPSRAM2AMEN BIT(3) /* RCC_LPSRAM3CFGR register fields */ #define RCC_LPSRAM3CFGR_LPSRAM3EN BIT(1) #define RCC_LPSRAM3CFGR_LPSRAM3LPEN BIT(2) #define RCC_LPSRAM3CFGR_LPSRAM3AMEN BIT(3) /* RCC_OSPI1CFGR register fields */ #define RCC_OSPI1CFGR_OSPI1RST BIT(0) #define RCC_OSPI1CFGR_OSPI1EN BIT(1) #define RCC_OSPI1CFGR_OSPI1LPEN BIT(2) #define RCC_OSPI1CFGR_OTFDEC1RST BIT(8) #define RCC_OSPI1CFGR_OSPI1DLLRST BIT(16) /* RCC_OSPI2CFGR register fields */ #define RCC_OSPI2CFGR_OSPI2RST BIT(0) #define RCC_OSPI2CFGR_OSPI2EN BIT(1) #define RCC_OSPI2CFGR_OSPI2LPEN BIT(2) #define RCC_OSPI2CFGR_OTFDEC2RST BIT(8) #define RCC_OSPI2CFGR_OSPI2DLLRST BIT(16) /* RCC_OSPIxCFGR register fields */ #define RCC_OSPIxCFGR_OSPIxRST BIT(0) #define RCC_OSPIxCFGR_OSPIxEN BIT(1) #define RCC_OSPIxCFGR_OSPIxLPEN BIT(2) #define RCC_OSPIxCFGR_OTFDECxRST BIT(8) #define RCC_OSPIxCFGR_OSPIxDLLRST BIT(16) /* RCC_FMCCFGR register fields */ #define RCC_FMCCFGR_FMCRST BIT(0) #define RCC_FMCCFGR_FMCEN BIT(1) #define RCC_FMCCFGR_FMCLPEN BIT(2) /* RCC_DBGCFGR register fields */ #define RCC_DBGCFGR_DBGEN BIT(8) #define RCC_DBGCFGR_TRACEEN BIT(9) #define RCC_DBGCFGR_DBGRST BIT(12) /* RCC_STMCFGR register fields */ #define RCC_STMCFGR_STMEN BIT(1) #define RCC_STMCFGR_STMLPEN BIT(2) /* RCC_ETRCFGR register fields */ #define RCC_ETRCFGR_ETREN BIT(1) #define RCC_ETRCFGR_ETRLPEN BIT(2) /* RCC_GPIOACFGR register fields */ #define RCC_GPIOACFGR_GPIOARST BIT(0) #define RCC_GPIOACFGR_GPIOAEN BIT(1) #define RCC_GPIOACFGR_GPIOALPEN BIT(2) /* RCC_GPIOBCFGR register fields */ #define RCC_GPIOBCFGR_GPIOBRST BIT(0) #define RCC_GPIOBCFGR_GPIOBEN BIT(1) #define RCC_GPIOBCFGR_GPIOBLPEN BIT(2) /* RCC_GPIOCCFGR register fields */ #define RCC_GPIOCCFGR_GPIOCRST BIT(0) #define RCC_GPIOCCFGR_GPIOCEN BIT(1) #define RCC_GPIOCCFGR_GPIOCLPEN BIT(2) /* RCC_GPIODCFGR register fields */ #define RCC_GPIODCFGR_GPIODRST BIT(0) #define RCC_GPIODCFGR_GPIODEN BIT(1) #define RCC_GPIODCFGR_GPIODLPEN BIT(2) /* RCC_GPIOECFGR register fields */ #define RCC_GPIOECFGR_GPIOERST BIT(0) #define RCC_GPIOECFGR_GPIOEEN BIT(1) #define RCC_GPIOECFGR_GPIOELPEN BIT(2) /* RCC_GPIOFCFGR register fields */ #define RCC_GPIOFCFGR_GPIOFRST BIT(0) #define RCC_GPIOFCFGR_GPIOFEN BIT(1) #define RCC_GPIOFCFGR_GPIOFLPEN BIT(2) /* RCC_GPIOGCFGR register fields */ #define RCC_GPIOGCFGR_GPIOGRST BIT(0) #define RCC_GPIOGCFGR_GPIOGEN BIT(1) #define RCC_GPIOGCFGR_GPIOGLPEN BIT(2) /* RCC_GPIOHCFGR register fields */ #define RCC_GPIOHCFGR_GPIOHRST BIT(0) #define RCC_GPIOHCFGR_GPIOHEN BIT(1) #define RCC_GPIOHCFGR_GPIOHLPEN BIT(2) /* RCC_GPIOICFGR register fields */ #define RCC_GPIOICFGR_GPIOIRST BIT(0) #define RCC_GPIOICFGR_GPIOIEN BIT(1) #define RCC_GPIOICFGR_GPIOILPEN BIT(2) /* RCC_GPIOJCFGR register fields */ #define RCC_GPIOJCFGR_GPIOJRST BIT(0) #define RCC_GPIOJCFGR_GPIOJEN BIT(1) #define RCC_GPIOJCFGR_GPIOJLPEN BIT(2) /* RCC_GPIOKCFGR register fields */ #define RCC_GPIOKCFGR_GPIOKRST BIT(0) #define RCC_GPIOKCFGR_GPIOKEN BIT(1) #define RCC_GPIOKCFGR_GPIOKLPEN BIT(2) /* RCC_GPIOZCFGR register fields */ #define RCC_GPIOZCFGR_GPIOZRST BIT(0) #define RCC_GPIOZCFGR_GPIOZEN BIT(1) #define RCC_GPIOZCFGR_GPIOZLPEN BIT(2) #define RCC_GPIOZCFGR_GPIOZAMEN BIT(3) /* RCC_GPIOxCFGR register fields */ #define RCC_GPIOxCFGR_GPIOxRST BIT(0) #define RCC_GPIOxCFGR_GPIOxEN BIT(1) #define RCC_GPIOxCFGR_GPIOxLPEN BIT(2) #define RCC_GPIOxCFGR_GPIOxAMEN BIT(3) /* RCC_HPDMA1CFGR register fields */ #define RCC_HPDMA1CFGR_HPDMA1RST BIT(0) #define RCC_HPDMA1CFGR_HPDMA1EN BIT(1) #define RCC_HPDMA1CFGR_HPDMA1LPEN BIT(2) /* RCC_HPDMA2CFGR register fields */ #define RCC_HPDMA2CFGR_HPDMA2RST BIT(0) #define RCC_HPDMA2CFGR_HPDMA2EN BIT(1) #define RCC_HPDMA2CFGR_HPDMA2LPEN BIT(2) /* RCC_HPDMA3CFGR register fields */ #define RCC_HPDMA3CFGR_HPDMA3RST BIT(0) #define RCC_HPDMA3CFGR_HPDMA3EN BIT(1) #define RCC_HPDMA3CFGR_HPDMA3LPEN BIT(2) /* RCC_HPDMAxCFGR register fields */ #define RCC_HPDMAxCFGR_HPDMAxRST BIT(0) #define RCC_HPDMAxCFGR_HPDMAxEN BIT(1) #define RCC_HPDMAxCFGR_HPDMAxLPEN BIT(2) /* RCC_LPDMACFGR register fields */ #define RCC_LPDMACFGR_LPDMARST BIT(0) #define RCC_LPDMACFGR_LPDMAEN BIT(1) #define RCC_LPDMACFGR_LPDMALPEN BIT(2) #define RCC_LPDMACFGR_LPDMAAMEN BIT(3) /* RCC_HSEMCFGR register fields */ #define RCC_HSEMCFGR_HSEMRST BIT(0) #define RCC_HSEMCFGR_HSEMEN BIT(1) #define RCC_HSEMCFGR_HSEMLPEN BIT(2) #define RCC_HSEMCFGR_HSEMAMEN BIT(3) /* RCC_IPCC1CFGR register fields */ #define RCC_IPCC1CFGR_IPCC1RST BIT(0) #define RCC_IPCC1CFGR_IPCC1EN BIT(1) #define RCC_IPCC1CFGR_IPCC1LPEN BIT(2) /* RCC_IPCC2CFGR register fields */ #define RCC_IPCC2CFGR_IPCC2RST BIT(0) #define RCC_IPCC2CFGR_IPCC2EN BIT(1) #define RCC_IPCC2CFGR_IPCC2LPEN BIT(2) #define RCC_IPCC2CFGR_IPCC2AMEN BIT(3) /* RCC_RTCCFGR register fields */ #define RCC_RTCCFGR_RTCEN BIT(1) #define RCC_RTCCFGR_RTCLPEN BIT(2) #define RCC_RTCCFGR_RTCAMEN BIT(3) /* RCC_SYSCPU1CFGR register fields */ #define RCC_SYSCPU1CFGR_SYSCPU1EN BIT(1) #define RCC_SYSCPU1CFGR_SYSCPU1LPEN BIT(2) /* RCC_BSECCFGR register fields */ #define RCC_BSECCFGR_BSECEN BIT(1) #define RCC_BSECCFGR_BSECLPEN BIT(2) /* RCC_IS2MCFGR register fields */ #define RCC_IS2MCFGR_IS2MRST BIT(0) #define RCC_IS2MCFGR_IS2MEN BIT(1) #define RCC_IS2MCFGR_IS2MLPEN BIT(2) /* RCC_PLL2CFGR1 register fields */ #define RCC_PLL2CFGR1_SSMODRST BIT(0) #define RCC_PLL2CFGR1_PLLEN BIT(8) #define RCC_PLL2CFGR1_PLLRDY BIT(24) #define RCC_PLL2CFGR1_CKREFST BIT(28) /* RCC_PLL2CFGR2 register fields */ #define RCC_PLL2CFGR2_FREFDIV_MASK GENMASK_32(5, 0) #define RCC_PLL2CFGR2_FREFDIV_SHIFT 0 #define RCC_PLL2CFGR2_FBDIV_MASK GENMASK_32(27, 16) #define RCC_PLL2CFGR2_FBDIV_SHIFT 16 /* RCC_PLL2CFGR3 register fields */ #define RCC_PLL2CFGR3_FRACIN_MASK GENMASK_32(23, 0) #define RCC_PLL2CFGR3_FRACIN_SHIFT 0 #define RCC_PLL2CFGR3_DOWNSPREAD BIT(24) #define RCC_PLL2CFGR3_DACEN BIT(25) #define RCC_PLL2CFGR3_SSCGDIS BIT(26) /* RCC_PLL2CFGR4 register fields */ #define RCC_PLL2CFGR4_DSMEN BIT(8) #define RCC_PLL2CFGR4_FOUTPOSTDIVEN BIT(9) #define RCC_PLL2CFGR4_BYPASS BIT(10) /* RCC_PLL2CFGR5 register fields */ #define RCC_PLL2CFGR5_DIVVAL_MASK GENMASK_32(3, 0) #define RCC_PLL2CFGR5_DIVVAL_SHIFT 0 #define RCC_PLL2CFGR5_SPREAD_MASK GENMASK_32(20, 16) #define RCC_PLL2CFGR5_SPREAD_SHIFT 16 /* RCC_PLL2CFGR6 register fields */ #define RCC_PLL2CFGR6_POSTDIV1_MASK GENMASK_32(2, 0) #define RCC_PLL2CFGR6_POSTDIV1_SHIFT 0 /* RCC_PLL2CFGR7 register fields */ #define RCC_PLL2CFGR7_POSTDIV2_MASK GENMASK_32(2, 0) #define RCC_PLL2CFGR7_POSTDIV2_SHIFT 0 /* RCC_PLL3CFGR1 register fields */ #define RCC_PLL3CFGR1_SSMODRST BIT(0) #define RCC_PLL3CFGR1_PLLEN BIT(8) #define RCC_PLL3CFGR1_PLLRDY BIT(24) #define RCC_PLL3CFGR1_CKREFST BIT(28) /* RCC_PLL3CFGR2 register fields */ #define RCC_PLL3CFGR2_FREFDIV_MASK GENMASK_32(5, 0) #define RCC_PLL3CFGR2_FREFDIV_SHIFT 0 #define RCC_PLL3CFGR2_FBDIV_MASK GENMASK_32(27, 16) #define RCC_PLL3CFGR2_FBDIV_SHIFT 16 /* RCC_PLL3CFGR3 register fields */ #define RCC_PLL3CFGR3_FRACIN_MASK GENMASK_32(23, 0) #define RCC_PLL3CFGR3_FRACIN_SHIFT 0 #define RCC_PLL3CFGR3_DOWNSPREAD BIT(24) #define RCC_PLL3CFGR3_DACEN BIT(25) #define RCC_PLL3CFGR3_SSCGDIS BIT(26) /* RCC_PLL3CFGR4 register fields */ #define RCC_PLL3CFGR4_DSMEN BIT(8) #define RCC_PLL3CFGR4_FOUTPOSTDIVEN BIT(9) #define RCC_PLL3CFGR4_BYPASS BIT(10) /* RCC_PLL3CFGR5 register fields */ #define RCC_PLL3CFGR5_DIVVAL_MASK GENMASK_32(3, 0) #define RCC_PLL3CFGR5_DIVVAL_SHIFT 0 #define RCC_PLL3CFGR5_SPREAD_MASK GENMASK_32(20, 16) #define RCC_PLL3CFGR5_SPREAD_SHIFT 16 /* RCC_PLL3CFGR6 register fields */ #define RCC_PLL3CFGR6_POSTDIV1_MASK GENMASK_32(2, 0) #define RCC_PLL3CFGR6_POSTDIV1_SHIFT 0 /* RCC_PLL3CFGR7 register fields */ #define RCC_PLL3CFGR7_POSTDIV2_MASK GENMASK_32(2, 0) #define RCC_PLL3CFGR7_POSTDIV2_SHIFT 0 /* RCC_PLLxCFGR1 register fields */ #define RCC_PLLxCFGR1_SSMODRST BIT(0) #define RCC_PLLxCFGR1_PLLEN BIT(8) #define RCC_PLLxCFGR1_PLLRDY BIT(24) #define RCC_PLLxCFGR1_CKREFST BIT(28) /* RCC_PLLxCFGR2 register fields */ #define RCC_PLLxCFGR2_FREFDIV_MASK GENMASK_32(5, 0) #define RCC_PLLxCFGR2_FREFDIV_SHIFT 0 #define RCC_PLLxCFGR2_FBDIV_MASK GENMASK_32(27, 16) #define RCC_PLLxCFGR2_FBDIV_SHIFT 16 /* RCC_PLLxCFGR3 register fields */ #define RCC_PLLxCFGR3_FRACIN_MASK GENMASK_32(23, 0) #define RCC_PLLxCFGR3_FRACIN_SHIFT 0 #define RCC_PLLxCFGR3_DOWNSPREAD BIT(24) #define RCC_PLLxCFGR3_DACEN BIT(25) #define RCC_PLLxCFGR3_SSCGDIS BIT(26) /* RCC_PLLxCFGR4 register fields */ #define RCC_PLLxCFGR4_DSMEN BIT(8) #define RCC_PLLxCFGR4_FOUTPOSTDIVEN BIT(9) #define RCC_PLLxCFGR4_BYPASS BIT(10) /* RCC_PLLxCFGR5 register fields */ #define RCC_PLLxCFGR5_DIVVAL_MASK GENMASK_32(3, 0) #define RCC_PLLxCFGR5_DIVVAL_SHIFT 0 #define RCC_PLLxCFGR5_SPREAD_MASK GENMASK_32(20, 16) #define RCC_PLLxCFGR5_SPREAD_SHIFT 16 /* RCC_PLLxCFGR6 register fields */ #define RCC_PLLxCFGR6_POSTDIV1_MASK GENMASK_32(2, 0) #define RCC_PLLxCFGR6_POSTDIV1_SHIFT 0 /* RCC_PLLxCFGR7 register fields */ #define RCC_PLLxCFGR7_POSTDIV2_MASK GENMASK_32(2, 0) #define RCC_PLLxCFGR7_POSTDIV2_SHIFT 0 /* RCC_HSIFMONCR register fields */ #define RCC_HSIFMONCR_HSIREF_MASK GENMASK_32(10, 0) #define RCC_HSIFMONCR_HSIREF_SHIFT 0 #define RCC_HSIFMONCR_HSIMONEN BIT(15) #define RCC_HSIFMONCR_HSIDEV_MASK GENMASK_32(21, 16) #define RCC_HSIFMONCR_HSIDEV_SHIFT 16 #define RCC_HSIFMONCR_HSIMONIE BIT(30) #define RCC_HSIFMONCR_HSIMONF BIT(31) /* RCC_HSIFVALR register fields */ #define RCC_HSIFVALR_HSIVAL_MASK GENMASK_32(10, 0) #define RCC_HSIFVALR_HSIVAL_SHIFT 0 /* RCC_TIM1CFGR register fields */ #define RCC_TIM1CFGR_TIM1RST BIT(0) #define RCC_TIM1CFGR_TIM1EN BIT(1) #define RCC_TIM1CFGR_TIM1LPEN BIT(2) /* RCC_TIM2CFGR register fields */ #define RCC_TIM2CFGR_TIM2RST BIT(0) #define RCC_TIM2CFGR_TIM2EN BIT(1) #define RCC_TIM2CFGR_TIM2LPEN BIT(2) /* RCC_TIM3CFGR register fields */ #define RCC_TIM3CFGR_TIM3RST BIT(0) #define RCC_TIM3CFGR_TIM3EN BIT(1) #define RCC_TIM3CFGR_TIM3LPEN BIT(2) /* RCC_TIM4CFGR register fields */ #define RCC_TIM4CFGR_TIM4RST BIT(0) #define RCC_TIM4CFGR_TIM4EN BIT(1) #define RCC_TIM4CFGR_TIM4LPEN BIT(2) /* RCC_TIM5CFGR register fields */ #define RCC_TIM5CFGR_TIM5RST BIT(0) #define RCC_TIM5CFGR_TIM5EN BIT(1) #define RCC_TIM5CFGR_TIM5LPEN BIT(2) /* RCC_TIM6CFGR register fields */ #define RCC_TIM6CFGR_TIM6RST BIT(0) #define RCC_TIM6CFGR_TIM6EN BIT(1) #define RCC_TIM6CFGR_TIM6LPEN BIT(2) /* RCC_TIM7CFGR register fields */ #define RCC_TIM7CFGR_TIM7RST BIT(0) #define RCC_TIM7CFGR_TIM7EN BIT(1) #define RCC_TIM7CFGR_TIM7LPEN BIT(2) /* RCC_TIM8CFGR register fields */ #define RCC_TIM8CFGR_TIM8RST BIT(0) #define RCC_TIM8CFGR_TIM8EN BIT(1) #define RCC_TIM8CFGR_TIM8LPEN BIT(2) /* RCC_TIM10CFGR register fields */ #define RCC_TIM10CFGR_TIM10RST BIT(0) #define RCC_TIM10CFGR_TIM10EN BIT(1) #define RCC_TIM10CFGR_TIM10LPEN BIT(2) /* RCC_TIM11CFGR register fields */ #define RCC_TIM11CFGR_TIM11RST BIT(0) #define RCC_TIM11CFGR_TIM11EN BIT(1) #define RCC_TIM11CFGR_TIM11LPEN BIT(2) /* RCC_TIM12CFGR register fields */ #define RCC_TIM12CFGR_TIM12RST BIT(0) #define RCC_TIM12CFGR_TIM12EN BIT(1) #define RCC_TIM12CFGR_TIM12LPEN BIT(2) /* RCC_TIM13CFGR register fields */ #define RCC_TIM13CFGR_TIM13RST BIT(0) #define RCC_TIM13CFGR_TIM13EN BIT(1) #define RCC_TIM13CFGR_TIM13LPEN BIT(2) /* RCC_TIM14CFGR register fields */ #define RCC_TIM14CFGR_TIM14RST BIT(0) #define RCC_TIM14CFGR_TIM14EN BIT(1) #define RCC_TIM14CFGR_TIM14LPEN BIT(2) /* RCC_TIM15CFGR register fields */ #define RCC_TIM15CFGR_TIM15RST BIT(0) #define RCC_TIM15CFGR_TIM15EN BIT(1) #define RCC_TIM15CFGR_TIM15LPEN BIT(2) /* RCC_TIM16CFGR register fields */ #define RCC_TIM16CFGR_TIM16RST BIT(0) #define RCC_TIM16CFGR_TIM16EN BIT(1) #define RCC_TIM16CFGR_TIM16LPEN BIT(2) /* RCC_TIM17CFGR register fields */ #define RCC_TIM17CFGR_TIM17RST BIT(0) #define RCC_TIM17CFGR_TIM17EN BIT(1) #define RCC_TIM17CFGR_TIM17LPEN BIT(2) /* RCC_TIM20CFGR register fields */ #define RCC_TIM20CFGR_TIM20RST BIT(0) #define RCC_TIM20CFGR_TIM20EN BIT(1) #define RCC_TIM20CFGR_TIM20LPEN BIT(2) /* RCC_LPTIM1CFGR register fields */ #define RCC_LPTIM1CFGR_LPTIM1RST BIT(0) #define RCC_LPTIM1CFGR_LPTIM1EN BIT(1) #define RCC_LPTIM1CFGR_LPTIM1LPEN BIT(2) /* RCC_LPTIM2CFGR register fields */ #define RCC_LPTIM2CFGR_LPTIM2RST BIT(0) #define RCC_LPTIM2CFGR_LPTIM2EN BIT(1) #define RCC_LPTIM2CFGR_LPTIM2LPEN BIT(2) /* RCC_LPTIM3CFGR register fields */ #define RCC_LPTIM3CFGR_LPTIM3RST BIT(0) #define RCC_LPTIM3CFGR_LPTIM3EN BIT(1) #define RCC_LPTIM3CFGR_LPTIM3LPEN BIT(2) #define RCC_LPTIM3CFGR_LPTIM3AMEN BIT(3) /* RCC_LPTIM4CFGR register fields */ #define RCC_LPTIM4CFGR_LPTIM4RST BIT(0) #define RCC_LPTIM4CFGR_LPTIM4EN BIT(1) #define RCC_LPTIM4CFGR_LPTIM4LPEN BIT(2) #define RCC_LPTIM4CFGR_LPTIM4AMEN BIT(3) /* RCC_LPTIM5CFGR register fields */ #define RCC_LPTIM5CFGR_LPTIM5RST BIT(0) #define RCC_LPTIM5CFGR_LPTIM5EN BIT(1) #define RCC_LPTIM5CFGR_LPTIM5LPEN BIT(2) #define RCC_LPTIM5CFGR_LPTIM5AMEN BIT(3) /* RCC_LPTIMxCFGR register fields */ #define RCC_LPTIMxCFGR_LPTIMxRST BIT(0) #define RCC_LPTIMxCFGR_LPTIMxEN BIT(1) #define RCC_LPTIMxCFGR_LPTIMxLPEN BIT(2) #define RCC_LPTIMxCFGR_LPTIMxAMEN BIT(3) /* RCC_SPI1CFGR register fields */ #define RCC_SPI1CFGR_SPI1RST BIT(0) #define RCC_SPI1CFGR_SPI1EN BIT(1) #define RCC_SPI1CFGR_SPI1LPEN BIT(2) /* RCC_SPI2CFGR register fields */ #define RCC_SPI2CFGR_SPI2RST BIT(0) #define RCC_SPI2CFGR_SPI2EN BIT(1) #define RCC_SPI2CFGR_SPI2LPEN BIT(2) /* RCC_SPI3CFGR register fields */ #define RCC_SPI3CFGR_SPI3RST BIT(0) #define RCC_SPI3CFGR_SPI3EN BIT(1) #define RCC_SPI3CFGR_SPI3LPEN BIT(2) /* RCC_SPI4CFGR register fields */ #define RCC_SPI4CFGR_SPI4RST BIT(0) #define RCC_SPI4CFGR_SPI4EN BIT(1) #define RCC_SPI4CFGR_SPI4LPEN BIT(2) /* RCC_SPI5CFGR register fields */ #define RCC_SPI5CFGR_SPI5RST BIT(0) #define RCC_SPI5CFGR_SPI5EN BIT(1) #define RCC_SPI5CFGR_SPI5LPEN BIT(2) /* RCC_SPI6CFGR register fields */ #define RCC_SPI6CFGR_SPI6RST BIT(0) #define RCC_SPI6CFGR_SPI6EN BIT(1) #define RCC_SPI6CFGR_SPI6LPEN BIT(2) /* RCC_SPI7CFGR register fields */ #define RCC_SPI7CFGR_SPI7RST BIT(0) #define RCC_SPI7CFGR_SPI7EN BIT(1) #define RCC_SPI7CFGR_SPI7LPEN BIT(2) /* RCC_SPI8CFGR register fields */ #define RCC_SPI8CFGR_SPI8RST BIT(0) #define RCC_SPI8CFGR_SPI8EN BIT(1) #define RCC_SPI8CFGR_SPI8LPEN BIT(2) #define RCC_SPI8CFGR_SPI8AMEN BIT(3) /* RCC_SPIxCFGR register fields */ #define RCC_SPIxCFGR_SPIxRST BIT(0) #define RCC_SPIxCFGR_SPIxEN BIT(1) #define RCC_SPIxCFGR_SPIxLPEN BIT(2) #define RCC_SPIxCFGR_SPIxAMEN BIT(3) /* RCC_SPDIFRXCFGR register fields */ #define RCC_SPDIFRXCFGR_SPDIFRXRST BIT(0) #define RCC_SPDIFRXCFGR_SPDIFRXEN BIT(1) #define RCC_SPDIFRXCFGR_SPDIFRXLPEN BIT(2) /* RCC_USART1CFGR register fields */ #define RCC_USART1CFGR_USART1RST BIT(0) #define RCC_USART1CFGR_USART1EN BIT(1) #define RCC_USART1CFGR_USART1LPEN BIT(2) /* RCC_USART2CFGR register fields */ #define RCC_USART2CFGR_USART2RST BIT(0) #define RCC_USART2CFGR_USART2EN BIT(1) #define RCC_USART2CFGR_USART2LPEN BIT(2) /* RCC_USART3CFGR register fields */ #define RCC_USART3CFGR_USART3RST BIT(0) #define RCC_USART3CFGR_USART3EN BIT(1) #define RCC_USART3CFGR_USART3LPEN BIT(2) /* RCC_UART4CFGR register fields */ #define RCC_UART4CFGR_UART4RST BIT(0) #define RCC_UART4CFGR_UART4EN BIT(1) #define RCC_UART4CFGR_UART4LPEN BIT(2) /* RCC_UART5CFGR register fields */ #define RCC_UART5CFGR_UART5RST BIT(0) #define RCC_UART5CFGR_UART5EN BIT(1) #define RCC_UART5CFGR_UART5LPEN BIT(2) /* RCC_USART6CFGR register fields */ #define RCC_USART6CFGR_USART6RST BIT(0) #define RCC_USART6CFGR_USART6EN BIT(1) #define RCC_USART6CFGR_USART6LPEN BIT(2) /* RCC_UART7CFGR register fields */ #define RCC_UART7CFGR_UART7RST BIT(0) #define RCC_UART7CFGR_UART7EN BIT(1) #define RCC_UART7CFGR_UART7LPEN BIT(2) /* RCC_UART8CFGR register fields */ #define RCC_UART8CFGR_UART8RST BIT(0) #define RCC_UART8CFGR_UART8EN BIT(1) #define RCC_UART8CFGR_UART8LPEN BIT(2) /* RCC_UART9CFGR register fields */ #define RCC_UART9CFGR_UART9RST BIT(0) #define RCC_UART9CFGR_UART9EN BIT(1) #define RCC_UART9CFGR_UART9LPEN BIT(2) /* RCC_USARTxCFGR register fields */ #define RCC_USARTxCFGR_USARTxRST BIT(0) #define RCC_USARTxCFGR_USARTxEN BIT(1) #define RCC_USARTxCFGR_USARTxLPEN BIT(2) /* RCC_UARTxCFGR register fields */ #define RCC_UARTxCFGR_UARTxRST BIT(0) #define RCC_UARTxCFGR_UARTxEN BIT(1) #define RCC_UARTxCFGR_UARTxLPEN BIT(2) /* RCC_LPUART1CFGR register fields */ #define RCC_LPUART1CFGR_LPUART1RST BIT(0) #define RCC_LPUART1CFGR_LPUART1EN BIT(1) #define RCC_LPUART1CFGR_LPUART1LPEN BIT(2) #define RCC_LPUART1CFGR_LPUART1AMEN BIT(3) /* RCC_I2C1CFGR register fields */ #define RCC_I2C1CFGR_I2C1RST BIT(0) #define RCC_I2C1CFGR_I2C1EN BIT(1) #define RCC_I2C1CFGR_I2C1LPEN BIT(2) /* RCC_I2C2CFGR register fields */ #define RCC_I2C2CFGR_I2C2RST BIT(0) #define RCC_I2C2CFGR_I2C2EN BIT(1) #define RCC_I2C2CFGR_I2C2LPEN BIT(2) /* RCC_I2C3CFGR register fields */ #define RCC_I2C3CFGR_I2C3RST BIT(0) #define RCC_I2C3CFGR_I2C3EN BIT(1) #define RCC_I2C3CFGR_I2C3LPEN BIT(2) /* RCC_I2C4CFGR register fields */ #define RCC_I2C4CFGR_I2C4RST BIT(0) #define RCC_I2C4CFGR_I2C4EN BIT(1) #define RCC_I2C4CFGR_I2C4LPEN BIT(2) /* RCC_I2C5CFGR register fields */ #define RCC_I2C5CFGR_I2C5RST BIT(0) #define RCC_I2C5CFGR_I2C5EN BIT(1) #define RCC_I2C5CFGR_I2C5LPEN BIT(2) /* RCC_I2C6CFGR register fields */ #define RCC_I2C6CFGR_I2C6RST BIT(0) #define RCC_I2C6CFGR_I2C6EN BIT(1) #define RCC_I2C6CFGR_I2C6LPEN BIT(2) /* RCC_I2C7CFGR register fields */ #define RCC_I2C7CFGR_I2C7RST BIT(0) #define RCC_I2C7CFGR_I2C7EN BIT(1) #define RCC_I2C7CFGR_I2C7LPEN BIT(2) /* RCC_I2C8CFGR register fields */ #define RCC_I2C8CFGR_I2C8RST BIT(0) #define RCC_I2C8CFGR_I2C8EN BIT(1) #define RCC_I2C8CFGR_I2C8LPEN BIT(2) #define RCC_I2C8CFGR_I2C8AMEN BIT(3) /* RCC_I2CxCFGR register fields */ #define RCC_I2CxCFGR_I2CxRST BIT(0) #define RCC_I2CxCFGR_I2CxEN BIT(1) #define RCC_I2CxCFGR_I2CxLPEN BIT(2) #define RCC_I2CxCFGR_I2CxAMEN BIT(3) /* RCC_SAI1CFGR register fields */ #define RCC_SAI1CFGR_SAI1RST BIT(0) #define RCC_SAI1CFGR_SAI1EN BIT(1) #define RCC_SAI1CFGR_SAI1LPEN BIT(2) /* RCC_SAI2CFGR register fields */ #define RCC_SAI2CFGR_SAI2RST BIT(0) #define RCC_SAI2CFGR_SAI2EN BIT(1) #define RCC_SAI2CFGR_SAI2LPEN BIT(2) /* RCC_SAI3CFGR register fields */ #define RCC_SAI3CFGR_SAI3RST BIT(0) #define RCC_SAI3CFGR_SAI3EN BIT(1) #define RCC_SAI3CFGR_SAI3LPEN BIT(2) /* RCC_SAI4CFGR register fields */ #define RCC_SAI4CFGR_SAI4RST BIT(0) #define RCC_SAI4CFGR_SAI4EN BIT(1) #define RCC_SAI4CFGR_SAI4LPEN BIT(2) /* RCC_SAIxCFGR register fields */ #define RCC_SAIxCFGR_SAIxRST BIT(0) #define RCC_SAIxCFGR_SAIxEN BIT(1) #define RCC_SAIxCFGR_SAIxLPEN BIT(2) /* RCC_MDF1CFGR register fields */ #define RCC_MDF1CFGR_MDF1RST BIT(0) #define RCC_MDF1CFGR_MDF1EN BIT(1) #define RCC_MDF1CFGR_MDF1LPEN BIT(2) /* RCC_MDF2CFGR register fields */ #define RCC_MDF2CFGR_MDF2RST BIT(0) #define RCC_MDF2CFGR_MDF2EN BIT(1) #define RCC_MDF2CFGR_MDF2LPEN BIT(2) #define RCC_MDF2CFGR_MDF2AMEN BIT(3) /* RCC_FDCANCFGR register fields */ #define RCC_FDCANCFGR_FDCANRST BIT(0) #define RCC_FDCANCFGR_FDCANEN BIT(1) #define RCC_FDCANCFGR_FDCANLPEN BIT(2) /* RCC_HDPCFGR register fields */ #define RCC_HDPCFGR_HDPRST BIT(0) #define RCC_HDPCFGR_HDPEN BIT(1) /* RCC_ADC12CFGR register fields */ #define RCC_ADC12CFGR_ADC12RST BIT(0) #define RCC_ADC12CFGR_ADC12EN BIT(1) #define RCC_ADC12CFGR_ADC12LPEN BIT(2) #define RCC_ADC12CFGR_ADC12KERSEL BIT(12) /* RCC_ADC3CFGR register fields */ #define RCC_ADC3CFGR_ADC3RST BIT(0) #define RCC_ADC3CFGR_ADC3EN BIT(1) #define RCC_ADC3CFGR_ADC3LPEN BIT(2) #define RCC_ADC3CFGR_ADC3KERSEL_MASK GENMASK_32(13, 12) #define RCC_ADC3CFGR_ADC3KERSEL_SHIFT 12 /* RCC_ETH1CFGR register fields */ #define RCC_ETH1CFGR_ETH1RST BIT(0) #define RCC_ETH1CFGR_ETH1MACEN BIT(1) #define RCC_ETH1CFGR_ETH1MACLPEN BIT(2) #define RCC_ETH1CFGR_ETH1STPEN BIT(4) #define RCC_ETH1CFGR_ETH1EN BIT(5) #define RCC_ETH1CFGR_ETH1LPEN BIT(6) #define RCC_ETH1CFGR_ETH1TXEN BIT(8) #define RCC_ETH1CFGR_ETH1TXLPEN BIT(9) #define RCC_ETH1CFGR_ETH1RXEN BIT(10) #define RCC_ETH1CFGR_ETH1RXLPEN BIT(11) /* RCC_ETH2CFGR register fields */ #define RCC_ETH2CFGR_ETH2RST BIT(0) #define RCC_ETH2CFGR_ETH2MACEN BIT(1) #define RCC_ETH2CFGR_ETH2MACLPEN BIT(2) #define RCC_ETH2CFGR_ETH2STPEN BIT(4) #define RCC_ETH2CFGR_ETH2EN BIT(5) #define RCC_ETH2CFGR_ETH2LPEN BIT(6) #define RCC_ETH2CFGR_ETH2TXEN BIT(8) #define RCC_ETH2CFGR_ETH2TXLPEN BIT(9) #define RCC_ETH2CFGR_ETH2RXEN BIT(10) #define RCC_ETH2CFGR_ETH2RXLPEN BIT(11) /* RCC_ETHxCFGR register fields */ #define RCC_ETHxCFGR_ETHxRST BIT(0) #define RCC_ETHxCFGR_ETHxMACEN BIT(1) #define RCC_ETHxCFGR_ETHxMACLPEN BIT(2) #define RCC_ETHxCFGR_ETHxSTPEN BIT(4) #define RCC_ETHxCFGR_ETHxEN BIT(5) #define RCC_ETHxCFGR_ETHxLPEN BIT(6) #define RCC_ETHxCFGR_ETHxTXEN BIT(8) #define RCC_ETHxCFGR_ETHxTXLPEN BIT(9) #define RCC_ETHxCFGR_ETHxRXEN BIT(10) #define RCC_ETHxCFGR_ETHxRXLPEN BIT(11) /* RCC_USB2CFGR register fields */ #define RCC_USB2CFGR_USB2RST BIT(0) #define RCC_USB2CFGR_USB2EN BIT(1) #define RCC_USB2CFGR_USB2LPEN BIT(2) #define RCC_USB2CFGR_USB2STPEN BIT(4) /* RCC_USB2PHY1CFGR register fields */ #define RCC_USB2PHY1CFGR_USB2PHY1RST BIT(0) #define RCC_USB2PHY1CFGR_USB2PHY1EN BIT(1) #define RCC_USB2PHY1CFGR_USB2PHY1LPEN BIT(2) #define RCC_USB2PHY1CFGR_USB2PHY1STPEN BIT(4) #define RCC_USB2PHY1CFGR_USB2PHY1CKREFSEL BIT(15) /* RCC_USB2PHY2CFGR register fields */ #define RCC_USB2PHY2CFGR_USB2PHY2RST BIT(0) #define RCC_USB2PHY2CFGR_USB2PHY2EN BIT(1) #define RCC_USB2PHY2CFGR_USB2PHY2LPEN BIT(2) #define RCC_USB2PHY2CFGR_USB2PHY2STPEN BIT(4) #define RCC_USB2PHY2CFGR_USB2PHY2CKREFSEL BIT(15) /* RCC_USB2PHYxCFGR register fields */ #define RCC_USB2PHYxCFGR_USB2PHY1RST BIT(0) #define RCC_USB2PHYxCFGR_USB2PHY1EN BIT(1) #define RCC_USB2PHYxCFGR_USB2PHY1LPEN BIT(2) #define RCC_USB2PHYxCFGR_USB2PHY1STPEN BIT(4) #define RCC_USB2PHYxCFGR_USB2PHY1CKREFSEL BIT(15) /* RCC_USB3DRCFGR register fields */ #define RCC_USB3DRCFGR_USB3DRRST BIT(0) #define RCC_USB3DRCFGR_USB3DREN BIT(1) #define RCC_USB3DRCFGR_USB3DRLPEN BIT(2) #define RCC_USB3DRCFGR_USB3DRSTPEN BIT(4) /* RCC_USB3PCIEPHYCFGR register fields */ #define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYRST BIT(0) #define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYEN BIT(1) #define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYLPEN BIT(2) #define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYSTPEN BIT(4) #define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYCKREFSEL BIT(15) /* RCC_PCIECFGR register fields */ #define RCC_PCIECFGR_PCIERST BIT(0) #define RCC_PCIECFGR_PCIEEN BIT(1) #define RCC_PCIECFGR_PCIELPEN BIT(2) #define RCC_PCIECFGR_PCIESTPEN BIT(4) /* RCC_USBTCCFGR register fields */ #define RCC_USBTCCFGR_USBTCRST BIT(0) #define RCC_USBTCCFGR_USBTCEN BIT(1) #define RCC_USBTCCFGR_USBTCLPEN BIT(2) /* RCC_ETHSWCFGR register fields */ #define RCC_ETHSWCFGR_ETHSWRST BIT(0) #define RCC_ETHSWCFGR_ETHSWMACEN BIT(1) #define RCC_ETHSWCFGR_ETHSWMACLPEN BIT(2) #define RCC_ETHSWCFGR_ETHSWEN BIT(5) #define RCC_ETHSWCFGR_ETHSWLPEN BIT(6) #define RCC_ETHSWCFGR_ETHSWREFEN BIT(21) #define RCC_ETHSWCFGR_ETHSWREFLPEN BIT(22) /* RCC_ETHSWACMCFGR register fields */ #define RCC_ETHSWACMCFGR_ETHSWACMEN BIT(1) #define RCC_ETHSWACMCFGR_ETHSWACMLPEN BIT(2) /* RCC_ETHSWACMMSGCFGR register fields */ #define RCC_ETHSWACMMSGCFGR_ETHSWACMMSGEN BIT(1) #define RCC_ETHSWACMMSGCFGR_ETHSWACMMSGLPEN BIT(2) /* RCC_STGENCFGR register fields */ #define RCC_STGENCFGR_STGENEN BIT(1) #define RCC_STGENCFGR_STGENLPEN BIT(2) #define RCC_STGENCFGR_STGENSTPEN BIT(4) /* RCC_SDMMC1CFGR register fields */ #define RCC_SDMMC1CFGR_SDMMC1RST BIT(0) #define RCC_SDMMC1CFGR_SDMMC1EN BIT(1) #define RCC_SDMMC1CFGR_SDMMC1LPEN BIT(2) #define RCC_SDMMC1CFGR_SDMMC1DLLRST BIT(16) /* RCC_SDMMC2CFGR register fields */ #define RCC_SDMMC2CFGR_SDMMC2RST BIT(0) #define RCC_SDMMC2CFGR_SDMMC2EN BIT(1) #define RCC_SDMMC2CFGR_SDMMC2LPEN BIT(2) #define RCC_SDMMC2CFGR_SDMMC2DLLRST BIT(16) /* RCC_SDMMC3CFGR register fields */ #define RCC_SDMMC3CFGR_SDMMC3RST BIT(0) #define RCC_SDMMC3CFGR_SDMMC3EN BIT(1) #define RCC_SDMMC3CFGR_SDMMC3LPEN BIT(2) #define RCC_SDMMC3CFGR_SDMMC3DLLRST BIT(16) /* RCC_SDMMCxCFGR register fields */ #define RCC_SDMMCxCFGR_SDMMC1RST BIT(0) #define RCC_SDMMCxCFGR_SDMMC1EN BIT(1) #define RCC_SDMMCxCFGR_SDMMC1LPEN BIT(2) #define RCC_SDMMCxCFGR_SDMMC1DLLRST BIT(16) /* RCC_GPUCFGR register fields */ #define RCC_GPUCFGR_GPURST BIT(0) #define RCC_GPUCFGR_GPUEN BIT(1) #define RCC_GPUCFGR_GPULPEN BIT(2) /* RCC_LTDCCFGR register fields */ #define RCC_LTDCCFGR_LTDCRST BIT(0) #define RCC_LTDCCFGR_LTDCEN BIT(1) #define RCC_LTDCCFGR_LTDCLPEN BIT(2) /* RCC_DSICFGR register fields */ #define RCC_DSICFGR_DSIRST BIT(0) #define RCC_DSICFGR_DSIEN BIT(1) #define RCC_DSICFGR_DSILPEN BIT(2) #define RCC_DSICFGR_DSIBLSEL BIT(12) #define RCC_DSICFGR_DSIPHYCKREFSEL BIT(15) /* RCC_LVDSCFGR register fields */ #define RCC_LVDSCFGR_LVDSRST BIT(0) #define RCC_LVDSCFGR_LVDSEN BIT(1) #define RCC_LVDSCFGR_LVDSLPEN BIT(2) #define RCC_LVDSCFGR_LVDSPHYCKREFSEL BIT(15) /* RCC_CSICFGR register fields */ #define RCC_CSICFGR_CSIRST BIT(0) #define RCC_CSICFGR_CSIEN BIT(1) #define RCC_CSICFGR_CSILPEN BIT(2) /* RCC_DCMIPPCFGR register fields */ #define RCC_DCMIPPCFGR_DCMIPPRST BIT(0) #define RCC_DCMIPPCFGR_DCMIPPEN BIT(1) #define RCC_DCMIPPCFGR_DCMIPPLPEN BIT(2) /* RCC_CCICFGR register fields */ #define RCC_CCICFGR_CCIRST BIT(0) #define RCC_CCICFGR_CCIEN BIT(1) #define RCC_CCICFGR_CCILPEN BIT(2) /* RCC_VDECCFGR register fields */ #define RCC_VDECCFGR_VDECRST BIT(0) #define RCC_VDECCFGR_VDECEN BIT(1) #define RCC_VDECCFGR_VDECLPEN BIT(2) /* RCC_VENCCFGR register fields */ #define RCC_VENCCFGR_VENCRST BIT(0) #define RCC_VENCCFGR_VENCEN BIT(1) #define RCC_VENCCFGR_VENCLPEN BIT(2) /* RCC_RNGCFGR register fields */ #define RCC_RNGCFGR_RNGRST BIT(0) #define RCC_RNGCFGR_RNGEN BIT(1) #define RCC_RNGCFGR_RNGLPEN BIT(2) /* RCC_PKACFGR register fields */ #define RCC_PKACFGR_PKARST BIT(0) #define RCC_PKACFGR_PKAEN BIT(1) #define RCC_PKACFGR_PKALPEN BIT(2) /* RCC_SAESCFGR register fields */ #define RCC_SAESCFGR_SAESRST BIT(0) #define RCC_SAESCFGR_SAESEN BIT(1) #define RCC_SAESCFGR_SAESLPEN BIT(2) /* RCC_HASHCFGR register fields */ #define RCC_HASHCFGR_HASHRST BIT(0) #define RCC_HASHCFGR_HASHEN BIT(1) #define RCC_HASHCFGR_HASHLPEN BIT(2) /* RCC_CRYP1CFGR register fields */ #define RCC_CRYP1CFGR_CRYP1RST BIT(0) #define RCC_CRYP1CFGR_CRYP1EN BIT(1) #define RCC_CRYP1CFGR_CRYP1LPEN BIT(2) /* RCC_CRYP2CFGR register fields */ #define RCC_CRYP2CFGR_CRYP2RST BIT(0) #define RCC_CRYP2CFGR_CRYP2EN BIT(1) #define RCC_CRYP2CFGR_CRYP2LPEN BIT(2) /* RCC_CRYPxCFGR register fields */ #define RCC_CRYPxCFGR_CRYPxRST BIT(0) #define RCC_CRYPxCFGR_CRYPxEN BIT(1) #define RCC_CRYPxCFGR_CRYPxLPEN BIT(2) /* RCC_IWDG1CFGR register fields */ #define RCC_IWDG1CFGR_IWDG1EN BIT(1) #define RCC_IWDG1CFGR_IWDG1LPEN BIT(2) /* RCC_IWDG2CFGR register fields */ #define RCC_IWDG2CFGR_IWDG2EN BIT(1) #define RCC_IWDG2CFGR_IWDG2LPEN BIT(2) /* RCC_IWDG3CFGR register fields */ #define RCC_IWDG3CFGR_IWDG3EN BIT(1) #define RCC_IWDG3CFGR_IWDG3LPEN BIT(2) /* RCC_IWDG4CFGR register fields */ #define RCC_IWDG4CFGR_IWDG4EN BIT(1) #define RCC_IWDG4CFGR_IWDG4LPEN BIT(2) /* RCC_IWDGxCFGR register fields */ #define RCC_IWDGxCFGR_IWDGxEN BIT(1) #define RCC_IWDGxCFGR_IWDGxLPEN BIT(2) /* RCC_IWDG5CFGR register fields */ #define RCC_IWDG5CFGR_IWDG5EN BIT(1) #define RCC_IWDG5CFGR_IWDG5LPEN BIT(2) #define RCC_IWDG5CFGR_IWDG5AMEN BIT(3) /* RCC_WWDG1CFGR register fields */ #define RCC_WWDG1CFGR_WWDG1RST BIT(0) #define RCC_WWDG1CFGR_WWDG1EN BIT(1) #define RCC_WWDG1CFGR_WWDG1LPEN BIT(2) /* RCC_WWDG2CFGR register fields */ #define RCC_WWDG2CFGR_WWDG2RST BIT(0) #define RCC_WWDG2CFGR_WWDG2EN BIT(1) #define RCC_WWDG2CFGR_WWDG2LPEN BIT(2) #define RCC_WWDG2CFGR_WWDG2AMEN BIT(3) /* RCC_VREFCFGR register fields */ #define RCC_VREFCFGR_VREFRST BIT(0) #define RCC_VREFCFGR_VREFEN BIT(1) #define RCC_VREFCFGR_VREFLPEN BIT(2) /* RCC_DTSCFGR register fields */ #define RCC_DTSCFGR_DTSRST BIT(0) #define RCC_DTSCFGR_DTSEN BIT(1) #define RCC_DTSCFGR_DTSLPEN BIT(2) #define RCC_DTSCFGR_DTSKERSEL_MASK GENMASK_32(13, 12) #define RCC_DTSCFGR_DTSKERSEL_SHIFT 12 /* RCC_CRCCFGR register fields */ #define RCC_CRCCFGR_CRCRST BIT(0) #define RCC_CRCCFGR_CRCEN BIT(1) #define RCC_CRCCFGR_CRCLPEN BIT(2) /* RCC_SERCCFGR register fields */ #define RCC_SERCCFGR_SERCRST BIT(0) #define RCC_SERCCFGR_SERCEN BIT(1) #define RCC_SERCCFGR_SERCLPEN BIT(2) /* RCC_OSPIIOMCFGR register fields */ #define RCC_OSPIIOMCFGR_OSPIIOMRST BIT(0) #define RCC_OSPIIOMCFGR_OSPIIOMEN BIT(1) #define RCC_OSPIIOMCFGR_OSPIIOMLPEN BIT(2) /* RCC_GICV2MCFGR register fields */ #define RCC_GICV2MCFGR_GICV2MEN BIT(1) #define RCC_GICV2MCFGR_GICV2MLPEN BIT(2) /* RCC_I3C1CFGR register fields */ #define RCC_I3C1CFGR_I3C1RST BIT(0) #define RCC_I3C1CFGR_I3C1EN BIT(1) #define RCC_I3C1CFGR_I3C1LPEN BIT(2) /* RCC_I3C2CFGR register fields */ #define RCC_I3C2CFGR_I3C2RST BIT(0) #define RCC_I3C2CFGR_I3C2EN BIT(1) #define RCC_I3C2CFGR_I3C2LPEN BIT(2) /* RCC_I3C3CFGR register fields */ #define RCC_I3C3CFGR_I3C3RST BIT(0) #define RCC_I3C3CFGR_I3C3EN BIT(1) #define RCC_I3C3CFGR_I3C3LPEN BIT(2) /* RCC_I3C4CFGR register fields */ #define RCC_I3C4CFGR_I3C4RST BIT(0) #define RCC_I3C4CFGR_I3C4EN BIT(1) #define RCC_I3C4CFGR_I3C4LPEN BIT(2) #define RCC_I3C4CFGR_I3C4AMEN BIT(3) /* RCC_I3CxCFGR register fields */ #define RCC_I3CxCFGR_I3CxRST BIT(0) #define RCC_I3CxCFGR_I3CxEN BIT(1) #define RCC_I3CxCFGR_I3CxLPEN BIT(2) #define RCC_I3CxCFGR_I3CxAMEN BIT(3) /* RCC_MUXSELCFGR register fields */ #define RCC_MUXSELCFGR_MUXSEL0_MASK GENMASK_32(1, 0) #define RCC_MUXSELCFGR_MUXSEL0_SHIFT 0 #define RCC_MUXSELCFGR_MUXSEL1_MASK GENMASK_32(5, 4) #define RCC_MUXSELCFGR_MUXSEL1_SHIFT 4 #define RCC_MUXSELCFGR_MUXSEL2_MASK GENMASK_32(9, 8) #define RCC_MUXSELCFGR_MUXSEL2_SHIFT 8 #define RCC_MUXSELCFGR_MUXSEL3_MASK GENMASK_32(13, 12) #define RCC_MUXSELCFGR_MUXSEL3_SHIFT 12 #define RCC_MUXSELCFGR_MUXSEL4_MASK GENMASK_32(17, 16) #define RCC_MUXSELCFGR_MUXSEL4_SHIFT 16 #define RCC_MUXSELCFGR_MUXSEL5_MASK GENMASK_32(21, 20) #define RCC_MUXSELCFGR_MUXSEL5_SHIFT 20 #define RCC_MUXSELCFGR_MUXSEL6_MASK GENMASK_32(25, 24) #define RCC_MUXSELCFGR_MUXSEL6_SHIFT 24 #define RCC_MUXSELCFGR_MUXSEL7_MASK GENMASK_32(29, 28) #define RCC_MUXSELCFGR_MUXSEL7_SHIFT 28 /* RCC_XBAR0CFGR register fields */ #define RCC_XBAR0CFGR_XBAR0SEL_MASK GENMASK_32(3, 0) #define RCC_XBAR0CFGR_XBAR0SEL_SHIFT 0 #define RCC_XBAR0CFGR_XBAR0EN BIT(6) #define RCC_XBAR0CFGR_XBAR0STS BIT(7) /* RCC_PREDIVCFGR register fields */ #define RCC_PREDIV0CFGR_PREDIV0_MASK GENMASK_32(9, 0) #define RCC_PREDIV0CFGR_PREDIV0_SHIFT 0 /* RCC_FINDIVxCFGR register fields */ #define RCC_FINDIV0CFGR_FINDIV0_MASK GENMASK_32(5, 0) #define RCC_FINDIV0CFGR_FINDIV0_SHIFT 0 #define RCC_FINDIV0CFGR_FINDIV0EN BIT(6) /* RCC_FINDIV0CFGR register fields */ #define RCC_FINDIV0CFGR_FINDIV0_MASK GENMASK_32(5, 0) #define RCC_FINDIV0CFGR_FINDIV0_SHIFT 0 #define RCC_FINDIV0CFGR_FINDIV0EN BIT(6) /* RCC_PREDIVSR1 register fields */ #define RCC_PREDIVSR1_PREDIVSTS_MASK GENMASK_32(31, 0) /* RCC_PREDIVSR2 register fields */ #define RCC_PREDIVSR2_PREDIVSTS_MASK GENMASK_32(31, 0) /* RCC_FINDIVSR1 register fields */ #define RCC_FINDIVSR1_FINDIVSTS_MASK GENMASK_32(31, 0) /* RCC_FINDIVSR2 register fields */ #define RCC_FINDIVSR2_FINDIVSTS_MASK GENMASK_32(31, 0) /* RCC_FCALCOBS0CFGR register fields */ #define RCC_FCALCOBS0CFGR_CKINTSEL_MASK GENMASK_32(7, 0) #define RCC_FCALCOBS0CFGR_CKINTSEL_SHIFT 0 #define RCC_FCALCOBS0CFGR_CKEXTSEL_MASK GENMASK_32(10, 8) #define RCC_FCALCOBS0CFGR_CKEXTSEL_SHIFT 8 #define RCC_FCALCOBS0CFGR_FCALCCKEXTSEL BIT(15) #define RCC_FCALCOBS0CFGR_CKOBSEXTSEL BIT(16) #define RCC_FCALCOBS0CFGR_FCALCCKINV BIT(17) #define RCC_FCALCOBS0CFGR_CKOBSINV BIT(18) #define RCC_FCALCOBS0CFGR_CKOBSDIV_MASK GENMASK_32(24, 22) #define RCC_FCALCOBS0CFGR_CKOBSDIV_SHIFT 22 #define RCC_FCALCOBS0CFGR_FCALCCKEN BIT(25) #define RCC_FCALCOBS0CFGR_CKOBSEN BIT(26) /* RCC_FCALCOBS1CFGR register fields */ #define RCC_FCALCOBS1CFGR_CKINTSEL_MASK GENMASK_32(7, 0) #define RCC_FCALCOBS1CFGR_CKINTSEL_SHIFT 0 #define RCC_FCALCOBS1CFGR_CKEXTSEL_MASK GENMASK_32(10, 8) #define RCC_FCALCOBS1CFGR_CKEXTSEL_SHIFT 8 #define RCC_FCALCOBS1CFGR_CKOBSEXTSEL BIT(16) #define RCC_FCALCOBS1CFGR_CKOBSINV BIT(18) #define RCC_FCALCOBS1CFGR_CKOBSDIV_MASK GENMASK_32(24, 22) #define RCC_FCALCOBS1CFGR_CKOBSDIV_SHIFT 22 #define RCC_FCALCOBS1CFGR_CKOBSEN BIT(26) #define RCC_FCALCOBS1CFGR_FCALCRSTN BIT(27) /* RCC_FCALCREFCFGR register fields */ #define RCC_FCALCREFCFGR_FCALCREFCKSEL_MASK GENMASK_32(2, 0) #define RCC_FCALCREFCFGR_FCALCREFCKSEL_SHIFT 0 /* RCC_FCALCCR1 register fields */ #define RCC_FCALCCR1_FCALCRUN BIT(0) /* RCC_FCALCCR2 register fields */ #define RCC_FCALCCR2_FCALCMD_MASK GENMASK_32(4, 3) #define RCC_FCALCCR2_FCALCMD_SHIFT 3 #define RCC_FCALCCR2_FCALCTWC_MASK GENMASK_32(14, 11) #define RCC_FCALCCR2_FCALCTWC_SHIFT 11 #define RCC_FCALCCR2_FCALCTYP_MASK GENMASK_32(21, 17) #define RCC_FCALCCR2_FCALCTYP_SHIFT 17 /* RCC_FCALCSR register fields */ #define RCC_FCALCSR_FVAL_MASK GENMASK_32(15, 0) #define RCC_FCALCSR_FVAL_SHIFT 0 #define RCC_FCALCSR_FCALCSTS BIT(19) #define RCC_FCALCSR_FVAL_OVERFLOW BIT(16) /* RCC_VERR register fields */ #define RCC_VERR_MINREV_MASK GENMASK_32(3, 0) #define RCC_VERR_MINREV_SHIFT 0 #define RCC_VERR_MAJREV_MASK GENMASK_32(7, 4) #define RCC_VERR_MAJREV_SHIFT 4 #endif /* __DRIVERS_STM32MP25_RCC_H */ optee_os-4.3.0/core/include/drivers/stm32mp2_rcc_util.h000066400000000000000000000012221464416617300230210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) STMicroelectronics 2024 - All Rights Reserved */ #ifndef __DRIVERS_STM32MP2_RCC_UTIL_H__ #define __DRIVERS_STM32MP2_RCC_UTIL_H__ #include #include #include /* Return RCC base address */ vaddr_t stm32_rcc_base(void); /* Return the clock handle related to a clock DT binding ID */ struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id); /* Return rstctrl instance related to RCC reset controller DT binding ID */ struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id); #endif /*__DRIVERS_STM32MP2_RCC_UTIL_H__*/ optee_os-4.3.0/core/include/drivers/stm32mp_dt_bindings.h000066400000000000000000000016021464416617300234210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, STMicroelectronics */ #ifndef __DRIVERS_STM32MP_DT_BINDINGS_H #define __DRIVERS_STM32MP_DT_BINDINGS_H #ifdef CFG_STM32MP13 #include #include #include #include #endif #ifdef CFG_STM32MP15 #include #include #include #endif #ifdef CFG_STM32MP25 #include #include #include #include #include #endif #endif /* __DRIVERS_STM32MP_DT_BINDINGS_H */ optee_os-4.3.0/core/include/drivers/stpmic1.h000066400000000000000000000174331464416617300211410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved */ #ifndef __DRIVERS_STPMIC1_H #define __DRIVERS_STPMIC1_H #include #include #define TURN_ON_REG 0x1U #define TURN_OFF_REG 0x2U #define ICC_LDO_TURN_OFF_REG 0x3U #define ICC_BUCK_TURN_OFF_REG 0x4U #define RESET_STATUS_REG 0x5U #define VERSION_STATUS_REG 0x6U #define MAIN_CONTROL_REG 0x10U #define PADS_PULL_REG 0x11U #define BUCK_PULL_DOWN_REG 0x12U #define LDO14_PULL_DOWN_REG 0x13U #define LDO56_PULL_DOWN_REG 0x14U #define VIN_CONTROL_REG 0x15U #define PONKEY_TIMER_REG 0x16U #define MASK_RANK_BUCK_REG 0x17U #define MASK_RESET_BUCK_REG 0x18U #define MASK_RANK_LDO_REG 0x19U #define MASK_RESET_LDO_REG 0x1AU #define WATCHDOG_CONTROL_REG 0x1BU #define WATCHDOG_TIMER_REG 0x1CU #define BUCK_ICC_TURNOFF_REG 0x1DU #define LDO_ICC_TURNOFF_REG 0x1EU #define BUCK_APM_CONTROL_REG 0x1FU #define BUCK1_CONTROL_REG 0x20U #define BUCK2_CONTROL_REG 0x21U #define BUCK3_CONTROL_REG 0x22U #define BUCK4_CONTROL_REG 0x23U #define VREF_DDR_CONTROL_REG 0x24U #define LDO1_CONTROL_REG 0x25U #define LDO2_CONTROL_REG 0x26U #define LDO3_CONTROL_REG 0x27U #define LDO4_CONTROL_REG 0x28U #define LDO5_CONTROL_REG 0x29U #define LDO6_CONTROL_REG 0x2AU #define BUCK1_PWRCTRL_REG 0x30U #define BUCK2_PWRCTRL_REG 0x31U #define BUCK3_PWRCTRL_REG 0x32U #define BUCK4_PWRCTRL_REG 0x33U #define VREF_DDR_PWRCTRL_REG 0x34U #define LDO1_PWRCTRL_REG 0x35U #define LDO2_PWRCTRL_REG 0x36U #define LDO3_PWRCTRL_REG 0x37U #define LDO4_PWRCTRL_REG 0x38U #define LDO5_PWRCTRL_REG 0x39U #define LDO6_PWRCTRL_REG 0x3AU #define FREQUENCY_SPREADING_REG 0x3BU #define USB_CONTROL_REG 0x40U #define ITLATCH1_REG 0x50U #define ITLATCH2_REG 0x51U #define ITLATCH3_REG 0x52U #define ITLATCH4_REG 0x53U #define ITSETLATCH1_REG 0x60U #define ITSETLATCH2_REG 0x61U #define ITSETLATCH3_REG 0x62U #define ITSETLATCH4_REG 0x63U #define ITCLEARLATCH1_REG 0x70U #define ITCLEARLATCH2_REG 0x71U #define ITCLEARLATCH3_REG 0x72U #define ITCLEARLATCH4_REG 0x73U #define ITMASK1_REG 0x80U #define ITMASK2_REG 0x81U #define ITMASK3_REG 0x82U #define ITMASK4_REG 0x83U #define ITSETMASK1_REG 0x90U #define ITSETMASK2_REG 0x91U #define ITSETMASK3_REG 0x92U #define ITSETMASK4_REG 0x93U #define ITCLEARMASK1_REG 0xA0U #define ITCLEARMASK2_REG 0xA1U #define ITCLEARMASK3_REG 0xA2U #define ITCLEARMASK4_REG 0xA3U #define ITSOURCE1_REG 0xB0U #define ITSOURCE2_REG 0xB1U #define ITSOURCE3_REG 0xB2U #define ITSOURCE4_REG 0xB3U /* Registers masks */ #define LDO_VOLTAGE_MASK GENMASK_32(6, 2) #define BUCK_VOLTAGE_MASK GENMASK_32(7, 2) #define LDO_BUCK_VOLTAGE_SHIFT 2 #define LDO_BUCK_ENABLE_POS 0 #define LDO_BUCK_ENABLE_MASK BIT(LDO_BUCK_ENABLE_POS) #define LDO_BUCK_HPLP_POS 1 #define LDO_BUCK_RANK_MASK BIT(0) #define LDO_BUCK_RESET_MASK BIT(0) #define LDO_BUCK_PULL_DOWN_MASK GENMASK_32(1, 0) /* Pull down register */ #define BUCK1_PULL_DOWN_SHIFT 0 #define BUCK2_PULL_DOWN_SHIFT 2 #define BUCK3_PULL_DOWN_SHIFT 4 #define BUCK4_PULL_DOWN_SHIFT 6 #define VREF_DDR_PULL_DOWN_SHIFT 4 /* Buck Mask reset register */ #define BUCK1_MASK_RESET_SHIFT 0 #define BUCK2_MASK_RESET_SHIFT 1 #define BUCK3_MASK_RESET_SHIFT 2 #define BUCK4_MASK_RESET_SHIFT 3 /* LDO Mask reset register */ #define LDO1_MASK_RESET_SHIFT 0 #define LDO2_MASK_RESET_SHIFT 1 #define LDO3_MASK_RESET_SHIFT 2 #define LDO4_MASK_RESET_SHIFT 3 #define LDO5_MASK_RESET_SHIFT 4 #define LDO6_MASK_RESET_SHIFT 5 #define VREF_DDR_MASK_RESET_SHIFT 6 /* Main PMIC Control Register (MAIN_CONTROL_REG) */ #define ICC_EVENT_ENABLED BIT(4) #define PWRCTRL_POLARITY_HIGH BIT(3) #define PWRCTRL_PIN_VALID BIT(2) #define RESTART_REQUEST_ENABLED BIT(1) #define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) /* Main PMIC PADS Control Register (PADS_PULL_REG) */ #define WAKEUP_DETECTOR_DISABLED BIT(4) #define PWRCTRL_PD_ACTIVE BIT(3) #define PWRCTRL_PU_ACTIVE BIT(2) #define WAKEUP_PD_ACTIVE BIT(1) #define PONKEY_PU_ACTIVE BIT(0) /* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ #define SWIN_DETECTOR_ENABLED BIT(7) #define SWOUT_DETECTOR_ENABLED BIT(6) #define VINLOW_HYST_MASK GENMASK_32(5, 4) #define VINLOW_HYST_SHIFT 4 #define VINLOW_THRESHOLD_MASK GENMASK_32(3, 1) #define VINLOW_THRESHOLD_SHIFT 1 #define VINLOW_ENABLED BIT(0) #define VINLOW_CTRL_REG_MASK GENMASK_32(7, 0) /* USB Control Register */ #define BOOST_OVP_DISABLED_POS 7 #define VBUS_OTG_DETECTION_DISABLED_POS 6 #define OCP_LIMIT_HIGH_POS 3 #define SWIN_SWOUT_ENABLED_POS 2 #define USBSW_OTG_SWITCH_ENABLED_POS 1 #define BOOST_ENABLED_POS 0 /* * Bind SPMIC1 device driver with a specific I2C bus instance * @i2c_handle: target I2C instance to use * @i2c_addr: I2C address of the STPMIC1 device */ void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); /* Read STPMIC1 device version information */ int stpmic1_get_version(unsigned long *version); /* Read STPMIC1 device internal registers content */ void stpmic1_dump_regulators(void); /* Enable power control in STPMIC1 device */ int stpmic1_powerctrl_on(void); /* Disable STPMIC1 device */ int stpmic1_switch_off(void); /* Read/write/update STPMIC1 device internal register */ int stpmic1_register_read(uint8_t register_id, uint8_t *value); int stpmic1_register_write(uint8_t register_id, uint8_t value); int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); int stpmic1_regulator_mask_reset_set(const char *name); /* API for low power configuration of regulators driven from STPMIC1 device */ int stpmic1_lp_copy_reg(const char *name); int stpmic1_lp_reg_on_off(const char *name, uint8_t enable); int stpmic1_lp_set_mode(const char *name, uint8_t hplp); int stpmic1_lp_set_voltage(const char *name, uint16_t millivolts); /* * Specific API for controlling regulators driven from STPMIC1 device * from unpaged execution context of the STPMIC1 driver. */ /* * The STPMIC1 is accessed during low power sequence in unpaged * execution context. To prevent adding an unpaged constraint on * STPMIC1 regulator definitions, conversion tables and device tree * content, the regulators configurations are read from device tree * at boot time and saved in memory for being applied at runtime * without needing pager support. * * There are 2 types of regulator configuration loaded during such * low power and unpaged sequences: boot-on (bo) configuration and * low power (lp) configuration. */ struct stpmic1_bo_cfg { uint8_t ctrl_reg; uint8_t min_value; uint8_t enable_pos; uint8_t mask; uint8_t pd_reg; uint8_t pd_value; uint8_t pd_mask; uint8_t mrst_reg; uint8_t mrst_value; uint8_t mrst_mask; }; struct stpmic1_lp_cfg { uint8_t ctrl_reg; uint8_t lp_reg; uint8_t value; uint8_t mask; }; int stpmic1_bo_enable_cfg(const char *name, struct stpmic1_bo_cfg *cfg); int stpmic1_bo_enable_unpg(struct stpmic1_bo_cfg *cfg); int stpmic1_bo_voltage_cfg(const char *name, uint16_t min_millivolt, struct stpmic1_bo_cfg *cfg); int stpmic1_bo_voltage_unpg(struct stpmic1_bo_cfg *cfg); int stpmic1_bo_pull_down_cfg(const char *name, struct stpmic1_bo_cfg *cfg); int stpmic1_bo_pull_down_unpg(struct stpmic1_bo_cfg *cfg); int stpmic1_bo_mask_reset_cfg(const char *name, struct stpmic1_bo_cfg *cfg); int stpmic1_bo_mask_reset_unpg(struct stpmic1_bo_cfg *cfg); bool stpmic1_regu_has_lp_cfg(const char *name); int stpmic1_lp_cfg(const char *name, struct stpmic1_lp_cfg *cfg); int stpmic1_lp_load_unpg(struct stpmic1_lp_cfg *cfg); int stpmic1_lp_on_off_unpg(struct stpmic1_lp_cfg *cfg, int enable); int stpmic1_lp_mode_unpg(struct stpmic1_lp_cfg *cfg, unsigned int mode); int stpmic1_lp_voltage_cfg(const char *name, uint16_t millivolts, struct stpmic1_lp_cfg *cfg); int stpmic1_lp_voltage_unpg(struct stpmic1_lp_cfg *cfg); #endif /*__DRIVERS_STPMIC1_H*/ optee_os-4.3.0/core/include/drivers/stpmic1_regulator.h000066400000000000000000000033161464416617300232200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021-2024, STMicroelectronics */ #ifndef __DRIVERS_STPMIC1_REGULATOR_H #define __DRIVERS_STPMIC1_REGULATOR_H #include #include #include /* * Return true if @name refers to a knwon regulator, return false otherwise */ bool stpmic1_regulator_is_valid(const char *name); /* * Enable STPMIC1 regulator identified by @name. * Return 0 on success and a non-0 value if failing */ int stpmic1_regulator_enable(const char *name); /* * Disable STPMIC1 regulator identified by @name. * Return 0 on success and a non-0 value if failing */ int stpmic1_regulator_disable(const char *name); /* * Return true if regulator identified by @name is enabled and false otherwise. * Return 0 on success and a non-0 value if failing */ bool stpmic1_is_regulator_enabled(const char *name); /* * Retrieve regulator levels array (in millivolts) and/or levels count * @name: regulator identifier * @levels: output reference for an arrays of the supported levels, or NULL * @levels_count: output reference for number of supported levels, or NULL */ void stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, size_t *levels_count); /* * Set voltage level @millivolt for target regulator @name * @name: regulator identifier * @millivot: target voltage level, in mV */ int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); /* * Get current voltage level (in millivolt) for target regulator @name * @name: regulator identifier * Return a positive millivolt level on success or a negative value on error */ int stpmic1_regulator_voltage_get(const char *name); #endif /*__DRIVERS_STPMIC1_REGULATOR_H*/ optee_os-4.3.0/core/include/drivers/tzc380.h000066400000000000000000000171011464416617300206040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2017 NXP * All rights reserved. * * Peng Fan * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_TZC380_H #define __DRIVERS_TZC380_H #include #include #include #include #include #define TZC400_REG_SIZE U(0x1000) #define BUILD_CONFIG_OFF U(0x000) #define ACTION_OFF U(0x004) #define LOCKDOWN_RANGE_OFF U(0x008) #define LOCKDOWN_SELECT_OFF U(0x00C) #define INT_STATUS U(0x010) #define INT_CLEAR U(0x014) #define FAIL_ADDRESS_LOW_OFF U(0x020) #define FAIL_ADDRESS_HIGH_OFF U(0x024) #define FAIL_CONTROL_OFF U(0x028) #define FAIL_ID U(0x02c) #define SPECULATION_CTRL_OFF U(0x030) #define SECURITY_INV_EN_OFF U(0x034) #define REGION_SETUP_LOW_OFF(n) (U(0x100) + (n) * U(0x10)) #define REGION_SETUP_HIGH_OFF(n) (U(0x104) + (n) * U(0x10)) #define REGION_ATTRIBUTES_OFF(n) (U(0x108) + (n) * U(0x10)) /* ID Registers */ #define PID0_OFF U(0xfe0) #define PID1_OFF U(0xfe4) #define PID2_OFF U(0xfe8) #define PID3_OFF U(0xfec) #define PID4_OFF U(0xfd0) #define CID0_OFF U(0xff0) #define CID1_OFF U(0xff4) #define CID2_OFF U(0xff8) #define CID3_OFF U(0xffc) #define BUILD_CONFIG_AW_SHIFT U(8) #define BUILD_CONFIG_AW_MASK U(0x3f) #define BUILD_CONFIG_NR_SHIFT U(0) #define BUILD_CONFIG_NR_MASK U(0xf) #define ACTION_RV_SHIFT U(0) #define ACTION_RV_MASK U(0x3) #define ACTION_RV_LOWOK U(0x0) #define ACTION_RV_LOWERR U(0x1) #define ACTION_RV_HIGHOK U(0x2) #define ACTION_RV_HIGHERR U(0x3) /* Speculation is enabled by default. */ #define SPECULATION_CTRL_WRITE_DISABLE BIT(1) #define SPECULATION_CTRL_READ_DISABLE BIT(0) #define INT_STATUS_OVERRUN_SHIFT U(1) #define INT_STATUS_OVERRUN_MASK U(0x1) #define INT_STATUS_STATUS_SHIFT U(0) #define INT_STATUS_STATUS_MASK U(0x1) #define INT_CLEAR_CLEAR_SHIFT U(0) #define INT_CLEAR_CLEAR_MASK U(0x1) #define TZC380_COMPONENT_ID U(0xb105f00d) #define TZC380_PERIPH_ID_LOW U(0x001bb380) #define TZC380_PERIPH_ID_HIGH U(0x00000004) /******************************************************************************* * Function & variable prototypes ******************************************************************************/ /* * What type of action is expected when an access violation occurs. * The memory requested is zeroed. But we can also raise and event to * let the system know it happened. * We can raise an interrupt(INT) and/or cause an exception(ERR). * TZC_ACTION_NONE - No interrupt, no Exception * TZC_ACTION_ERR - No interrupt, raise exception -> sync external * data abort * TZC_ACTION_INT - Raise interrupt, no exception * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync * external data abort */ enum tzc_action { TZC_ACTION_NONE = 0, TZC_ACTION_ERR = 1, TZC_ACTION_INT = 2, TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT) }; #define TZC_SP_NS_W BIT(0) #define TZC_SP_NS_R BIT(1) #define TZC_SP_S_W BIT(2) #define TZC_SP_S_R BIT(3) #define TZC_ATTR_SP_SHIFT U(28) #define TZC_ATTR_SP_MASK GENMASK_32(31, 28) #define TZC_ATTR_SP_ALL SHIFT_U32(TZC_SP_S_W | TZC_SP_S_R | \ TZC_SP_NS_W | TZC_SP_NS_R, \ TZC_ATTR_SP_SHIFT) #define TZC_ATTR_SP_S_RW SHIFT_U32(TZC_SP_S_W | TZC_SP_S_R, \ TZC_ATTR_SP_SHIFT) #define TZC_ATTR_SP_NS_RW SHIFT_U32(TZC_SP_NS_W | TZC_SP_NS_R, \ TZC_ATTR_SP_SHIFT) #define TZC_REGION_SIZE_32K U(0xe) #define TZC_REGION_SIZE_64K U(0xf) #define TZC_REGION_SIZE_128K U(0x10) #define TZC_REGION_SIZE_256K U(0x11) #define TZC_REGION_SIZE_512K U(0x12) #define TZC_REGION_SIZE_1M U(0x13) #define TZC_REGION_SIZE_2M U(0x14) #define TZC_REGION_SIZE_4M U(0x15) #define TZC_REGION_SIZE_8M U(0x16) #define TZC_REGION_SIZE_16M U(0x17) #define TZC_REGION_SIZE_32M U(0x18) #define TZC_REGION_SIZE_64M U(0x19) #define TZC_REGION_SIZE_128M U(0x1a) #define TZC_REGION_SIZE_256M U(0x1b) #define TZC_REGION_SIZE_512M U(0x1c) #define TZC_REGION_SIZE_1G U(0x1d) #define TZC_REGION_SIZE_2G U(0x1e) #define TZC_REGION_SIZE_4G U(0x1f) #define TZC_REGION_SIZE_8G U(0x20) #define TZC_REGION_SIZE_16G U(0x21) #define TZC_REGION_SIZE_32G U(0x22) #define TZC_REGION_SIZE_64G U(0x23) #define TZC_REGION_SIZE_128G U(0x24) #define TZC_REGION_SIZE_256G U(0x25) #define TZC_REGION_SIZE_512G U(0x26) #define TZC_REGION_SIZE_1T U(0x27) #define TZC_REGION_SIZE_2T U(0x28) #define TZC_REGION_SIZE_4T U(0x29) #define TZC_REGION_SIZE_8T U(0x2a) #define TZC_REGION_SIZE_16T U(0x2b) #define TZC_REGION_SIZE_32T U(0x2c) #define TZC_REGION_SIZE_64T U(0x2d) #define TZC_REGION_SIZE_128T U(0x2e) #define TZC_REGION_SIZE_256T U(0x2f) #define TZC_REGION_SIZE_512T U(0x30) #define TZC_REGION_SIZE_1P U(0x31) #define TZC_REGION_SIZE_2P U(0x32) #define TZC_REGION_SIZE_4P U(0x33) #define TZC_REGION_SIZE_8P U(0x34) #define TZC_REGION_SIZE_16P U(0x35) #define TZC_REGION_SIZE_32P U(0x36) #define TZC_REGION_SIZE_64P U(0x37) #define TZC_REGION_SIZE_128P U(0x38) #define TZC_REGION_SIZE_256P U(0x39) #define TZC_REGION_SIZE_512P U(0x3a) #define TZC_REGION_SIZE_1E U(0x3b) #define TZC_REGION_SIZE_2E U(0x3c) #define TZC_REGION_SIZE_4E U(0x3d) #define TZC_REGION_SIZE_8E U(0x3e) #define TZC_REGION_SIZE_16E U(0x3f) #define TZC_REGION_SIZE_SHIFT U(0x1) #define TZC_REGION_SIZE_MASK GENMASK_32(6, 1) #define TZC_ATTR_REGION_SIZE(s) SHIFT_U32(s, TZC_REGION_SIZE_SHIFT) #define TZC_SUBREGION_DIS_SHIFT U(8) #define TZC_SUBREGION_DIS_MASK GENMASK_32(15, 8) #define TZC_ATTR_SUBREGION_DIS(subreg) \ (BIT((subreg) + TZC_SUBREGION_DIS_SHIFT) & \ TZC_SUBREGION_DIS_MASK) #define TZC_ATTR_REGION_EN_SHIFT U(0x0) #define TZC_ATTR_REGION_EN_MASK U(0x1) #define TZC_ATTR_REGION_EN #define TZC_ATTR_REGION_ENABLE U(0x1) #define TZC_ATTR_REGION_DISABLE U(0x0) #define LOCKDOWN_RANGE_ENABLE BIT(31) #define LOCKDOWN_SELECT_RANGE_ENABLE BIT(0) void tzc_init(vaddr_t base); void tzc_configure_region(uint8_t region, vaddr_t region_base, uint32_t attr); void tzc_region_enable(uint8_t region); void tzc_security_inversion_en(vaddr_t base); void tzc_set_action(enum tzc_action action); uint32_t tzc_get_action(void); void tzc_fail_dump(void); void tzc_int_clear(void); int tzc_auto_configure(vaddr_t addr, vaddr_t rsize, uint32_t attr, uint8_t region); TEE_Result tzc_regions_lockdown(void); #if TRACE_LEVEL >= TRACE_DEBUG void tzc_dump_state(void); #else static inline void tzc_dump_state(void) { } #endif #endif /* __DRIVERS_TZC400_H */ optee_os-4.3.0/core/include/drivers/tzc400.h000066400000000000000000000215761464416617300206100ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ /* * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __DRIVERS_TZC400_H #define __DRIVERS_TZC400_H #include #include #include #include #include #define TZC400_REG_SIZE U(0x1000) #define BUILD_CONFIG_OFF U(0x000) #define ACTION_OFF U(0x004) #define GATE_KEEPER_OFF U(0x008) #define SPECULATION_CTRL_OFF U(0x00c) #define INT_STATUS U(0x010) #define INT_CLEAR U(0x014) #define FAIL_ADDRESS_LOW_OFF U(0x020) #define FAIL_ADDRESS_HIGH_OFF U(0x024) #define FAIL_CONTROL_OFF U(0x028) #define FAIL_ID_OFF U(0x02c) #define FAIL_FILTER_OFF(idx) (U(0x10) * (idx)) #define FAIL_ADDRESS_LOW(idx) (FAIL_ADDRESS_LOW_OFF + FAIL_FILTER_OFF(idx)) #define FAIL_ADDRESS_HIGH(idx) (FAIL_ADDRESS_HIGH_OFF + FAIL_FILTER_OFF(idx)) #define FAIL_CONTROL(idx) (FAIL_CONTROL_OFF + FAIL_FILTER_OFF(idx)) #define FAIL_ID(idx) (FAIL_ID_OFF + FAIL_FILTER_OFF(idx)) #define REGION_BASE_LOW_OFF U(0x100) #define REGION_BASE_HIGH_OFF U(0x104) #define REGION_TOP_LOW_OFF U(0x108) #define REGION_TOP_HIGH_OFF U(0x10c) #define REGION_ATTRIBUTES_OFF U(0x110) #define REGION_ID_ACCESS_OFF U(0x114) #define REGION_NUM_OFF(region) (U(0x20) * (region)) /* ID Registers */ #define PID0_OFF U(0xfe0) #define PID1_OFF U(0xfe4) #define PID2_OFF U(0xfe8) #define PID3_OFF U(0xfec) #define PID4_OFF U(0xfd0) #define PID5_OFF U(0xfd4) #define PID6_OFF U(0xfd8) #define PID7_OFF U(0xfdc) #define CID0_OFF U(0xff0) #define CID1_OFF U(0xff4) #define CID2_OFF U(0xff8) #define CID3_OFF U(0xffc) #define BUILD_CONFIG_NF_SHIFT U(24) #define BUILD_CONFIG_NF_MASK U(0x3) #define BUILD_CONFIG_AW_SHIFT U(8) #define BUILD_CONFIG_AW_MASK U(0x3f) #define BUILD_CONFIG_NR_SHIFT U(0) #define BUILD_CONFIG_NR_MASK U(0x1f) /* Not describing the case where regions 1 to 8 overlap */ #define ACTION_RV_SHIFT U(0) #define ACTION_RV_MASK U(0x3) #define ACTION_RV_LOWOK U(0x0) #define ACTION_RV_LOWERR U(0x1) #define ACTION_RV_HIGHOK U(0x2) #define ACTION_RV_HIGHERR U(0x3) /* * Number of gate keepers is implementation defined. But we know the max for * this device is 4. Get implementation details from BUILD_CONFIG. */ #define GATE_KEEPER_OS_SHIFT U(16) #define GATE_KEEPER_OS_MASK U(0xf) #define GATE_KEEPER_OR_SHIFT U(0) #define GATE_KEEPER_OR_MASK U(0xf) #define GATE_KEEPER_FILTER_MASK U(0x1) /* Speculation is enabled by default. */ #define SPECULATION_CTRL_WRITE_DISABLE BIT(1) #define SPECULATION_CTRL_READ_DISABLE BIT(0) /* Max number of filters allowed is 4. */ #define INT_STATUS_OVERLAP_SHIFT U(16) #define INT_STATUS_OVERLAP_MASK U(0xf) #define INT_STATUS_OVERRUN_SHIFT U(8) #define INT_STATUS_OVERRUN_MASK U(0xf) #define INT_STATUS_STATUS_SHIFT U(0) #define INT_STATUS_STATUS_MASK U(0xf) #define INT_CLEAR_CLEAR_SHIFT U(0) #define INT_CLEAR_CLEAR_MASK U(0xf) /* If set write access, else read access */ #define FAIL_CONTROL_DIRECTION_WRITE BIT(24) /* If set non-secure access, else secure access */ #define FAIL_CONTROL_NONSECURE BIT(21) /* If set privileged access, else unprivileged access */ #define FAIL_CONTROL_PRIVILEGED BIT(20) /* * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific. * Platform should provide the value on initialisation. */ #define FAIL_ID_VNET_SHIFT U(24) #define FAIL_ID_VNET_MASK U(0xf) #define FAIL_ID_ID_SHIFT U(0) /* Used along with 'enum tzc_region_attributes' below */ #define REG_ATTR_SEC_SHIFT U(30) #define REG_ATTR_F_EN_SHIFT U(0) #define REG_ATTR_F_EN_MASK U(0xf) #define REG_ATTR_FILTER_BIT(x) SHIFT_U32(BIT(x), REG_ATTR_F_EN_SHIFT) #define REG_ATTR_FILTER_BIT_ALL SHIFT_U32(REG_ATTR_F_EN_MASK, \ REG_ATTR_F_EN_SHIFT) #define REGION_ID_ACCESS_NSAID_WR_EN_SHIFT U(16) #define REGION_ID_ACCESS_NSAID_RD_EN_SHIFT U(0) #define REGION_ID_ACCESS_NSAID_ID_MASK U(0xf) /* Macros for setting Region ID access permissions based on NSAID */ #define TZC_REGION_ACCESS_RD(id) \ SHIFT_U32(BIT(id & REGION_ID_ACCESS_NSAID_ID_MASK), \ REGION_ID_ACCESS_NSAID_RD_EN_SHIFT) #define TZC_REGION_ACCESS_WR(id) \ SHIFT_U32(BIT(id & REGION_ID_ACCESS_NSAID_ID_MASK), \ REGION_ID_ACCESS_NSAID_WR_EN_SHIFT) #define TZC_REGION_ACCESS_RDWR(id) \ (TZC_REGION_ACCESS_RD(id) | TZC_REGION_ACCESS_WR(id)) /* Filters are bit mapped 0 to 3. */ #define TZC400_COMPONENT_ID U(0xb105f00d) /******************************************************************************* * Function & variable prototypes ******************************************************************************/ /* * What type of action is expected when an access violation occurs. * The memory requested is zeroed. But we can also raise and event to * let the system know it happened. * We can raise an interrupt(INT) and/or cause an exception(ERR). * TZC_ACTION_NONE - No interrupt, no Exception * TZC_ACTION_ERR - No interrupt, raise exception -> sync external * data abort * TZC_ACTION_INT - Raise interrupt, no exception * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync * external data abort */ enum tzc_action { TZC_ACTION_NONE = 0, TZC_ACTION_ERR = 1, TZC_ACTION_INT = 2, TZC_ACTION_ERR_INT = (TZC_ACTION_ERR | TZC_ACTION_INT) }; /* * Controls secure access to a region. If not enabled secure access is not * allowed to region. */ enum tzc_region_attributes { TZC_REGION_S_NONE = 0, TZC_REGION_S_RD = 1, TZC_REGION_S_WR = 2, TZC_REGION_S_RDWR = (TZC_REGION_S_RD | TZC_REGION_S_WR) }; struct tzc_region_config { uint32_t filters; vaddr_t base; vaddr_t top; enum tzc_region_attributes sec_attr; uint32_t ns_device_access; }; void tzc_init(vaddr_t base); void tzc_configure_region(uint8_t region, const struct tzc_region_config *cfg); TEE_Result tzc_get_region_config(uint8_t region, struct tzc_region_config *cfg); void tzc_enable_filters(void); void tzc_disable_filters(void); void tzc_set_action(enum tzc_action action); void tzc_fail_dump(void); void tzc_int_clear(void); #if TRACE_LEVEL >= TRACE_DEBUG void tzc_dump_state(void); #else static inline void tzc_dump_state(void) { } #endif #endif /* __DRIVERS_TZC400_H */ optee_os-4.3.0/core/include/drivers/versal_gpio.h000066400000000000000000000014731464416617300220700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022 Foundries.io Ltd */ #ifndef __DRIVERS_VERSAL_GPIO_H #define __DRIVERS_VERSAL_GPIO_H #include #include #include #include #define VERSAL_GPIO_MAX_BANK 5 struct versal_gpio_platform_data { const char *label; uint16_t ngpio; uint32_t max_bank; uint32_t bank_min[VERSAL_GPIO_MAX_BANK]; uint32_t bank_max[VERSAL_GPIO_MAX_BANK]; }; struct versal_gpio_platdata { paddr_t base; const struct versal_gpio_platform_data *p_data; }; struct versal_gpio_chip { struct gpio_chip chip; struct versal_gpio_platdata plat; vaddr_t base; }; TEE_Result versal_gpio_pmc_init(struct versal_gpio_chip *chip); TEE_Result versal_gpio_ps_init(struct versal_gpio_chip *chip); #endif /* __DRIVERS_VERSAL_GPIO_H */ optee_os-4.3.0/core/include/drivers/versal_mbox.h000066400000000000000000000013561464416617300220770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Foundries.io Ltd */ #ifndef __DRIVERS_VERSAL_MBOX_H #define __DRIVERS_VERSAL_MBOX_H #include #include #include #define VERSAL_MAX_IPI_BUF 7 struct versal_mbox_mem { size_t alloc_len; size_t len; void *buf; }; struct versal_ipi_buf { struct versal_mbox_mem mem; bool only_cache; }; struct versal_ipi_cmd { uint32_t data[8]; struct versal_ipi_buf ibuf[VERSAL_MAX_IPI_BUF]; }; TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd, struct versal_ipi_cmd *rsp, uint32_t *err); TEE_Result versal_mbox_alloc(size_t len, const void *init, struct versal_mbox_mem *mem); #endif /* __DRIVERS_VERSAL_MBOX_H */ optee_os-4.3.0/core/include/drivers/versal_nvm.h000066400000000000000000000164061464416617300217340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022 Foundries.io Ltd */ #ifndef __DRIVERS_VERSAL_NVM_H__ #define __DRIVERS_VERSAL_NVM_H__ #include #include #include #include #include #define PUF_EFUSES_WORDS (128) #define PUF_SYN_DATA_WORDS (127) #define EFUSE_MAX_USER_FUSES (64) #define EFUSE_OFFCHIP_REVOCATION_ID_LEN (4) #define EFUSE_REVOCATION_ID_LEN (4) #define EFUSE_DEC_ONLY_LEN (4) #define EFUSE_DNA_LEN (16) #define EFUSE_PPK_LEN (32) #define EFUSE_IV_LEN (12) enum versal_nvm_iv_type { EFUSE_META_HEADER_IV_RANGE = 0, EFUSE_BLACK_IV, EFUSE_PLM_IV_RANGE, EFUSE_DATA_PARTITION_IV_RANGE, }; enum versal_nvm_ppk_type { EFUSE_PPK0 = 0, EFUSE_PPK1, EFUSE_PPK2 }; enum versal_nvm_revocation_id { EFUSE_REVOCATION_ID_0 = 0, EFUSE_REVOCATION_ID_1, EFUSE_REVOCATION_ID_2, EFUSE_REVOCATION_ID_3, EFUSE_REVOCATION_ID_4, EFUSE_REVOCATION_ID_5, EFUSE_REVOCATION_ID_6, EFUSE_REVOCATION_ID_7 }; enum versal_nvm_offchip_id { EFUSE_INVLD = -1, EFUSE_OFFCHIP_REVOKE_ID_0 = 0, EFUSE_OFFCHIP_REVOKE_ID_1, EFUSE_OFFCHIP_REVOKE_ID_2, EFUSE_OFFCHIP_REVOKE_ID_3, EFUSE_OFFCHIP_REVOKE_ID_4, EFUSE_OFFCHIP_REVOKE_ID_5, EFUSE_OFFCHIP_REVOKE_ID_6, EFUSE_OFFCHIP_REVOKE_ID_7 }; /* * All structures mapped to the PLM processor must be address_and_size aligned * to the cacheline_len. */ struct versal_efuse_glitch_cfg_bits { uint8_t prgm_glitch; uint8_t glitch_det_wr_lk; uint32_t glitch_det_trim; uint8_t gd_rom_monitor_en; uint8_t gd_halt_boot_en; uint8_t pad[53]; }; struct versal_efuse_aes_keys { uint8_t prgm_aes_key; uint8_t prgm_user_key0; uint8_t prgm_user_key1; uint32_t aes_key[8]; uint32_t user_key0[8]; uint32_t user_key1[8]; uint8_t pad[25]; }; struct versal_efuse_ppk_hash { uint8_t prgm_ppk0_hash; uint8_t prgm_ppk1_hash; uint8_t prgm_ppk2_hash; uint32_t ppk0_hash[8]; uint32_t ppk1_hash[8]; uint32_t ppk2_hash[8]; uint8_t pad[89]; }; struct versal_efuse_dec_only { uint8_t prgm_dec_only; uint8_t pad[63]; }; struct versal_efuse_revoke_ids { uint8_t prgm_revoke_id; uint32_t revoke_id[8]; uint8_t pad[89]; }; struct versal_efuse_offchip_ids { uint8_t prgm_offchip_id; uint32_t offchip_id[8]; uint8_t pad[89]; }; struct versal_efuse_user_data { uint32_t start; uint32_t num; uint64_t addr; uint8_t pad[48]; }; struct versal_efuse_puf_fuse { uint8_t env_monitor_dis; uint8_t prgm_puf_fuse; uint32_t start; uint32_t num; uint64_t addr; uint8_t pad[104]; }; struct versal_efuse_ivs { uint8_t prgm_meta_header_iv; uint8_t prgm_blk_obfus_iv; uint8_t prgm_plm_iv; uint8_t prgm_data_partition_iv; uint32_t meta_header_iv[3]; uint32_t blk_obfus_iv[3]; uint32_t plm_iv[3]; uint32_t data_partition_iv[3]; uint8_t pad[12]; }; struct versal_efuse_misc_ctrl_bits { uint8_t glitch_det_halt_boot_en; uint8_t glitch_det_rom_monitor_en; uint8_t halt_boot_error; uint8_t halt_boot_env; uint8_t crypto_kat_en; uint8_t lbist_en; uint8_t safety_mission_en; uint8_t ppk0_invalid; uint8_t ppk1_invalid; uint8_t ppk2_invalid; uint8_t pad[54]; }; struct versal_efuse_puf_sec_ctrl_bits { uint8_t puf_regen_dis; uint8_t puf_hd_invalid; uint8_t puf_test2_dis; uint8_t puf_dis; uint8_t puf_syn_lk; uint8_t pad[59]; }; struct versal_efuse_sec_misc1_bits { uint8_t lpd_mbist_en; uint8_t pmc_mbist_en; uint8_t lpd_noc_sc_en; uint8_t sysmon_volt_mon_en; uint8_t sysmon_temp_mon_en; uint8_t pad[59]; }; struct versal_efuse_boot_env_ctrl_bits { uint8_t prgm_sysmon_temp_hot; uint8_t prgm_sysmon_volt_pmc; uint8_t prgm_sysmon_volt_pslp; uint8_t prgm_sysmon_temp_cold; uint8_t sysmon_temp_en; uint8_t sysmon_volt_en; uint8_t sysmon_volt_soc; uint8_t sysmon_temp_hot; uint8_t sysmon_volt_pmc; uint8_t sysmon_volt_pslp; uint8_t sysmon_temp_cold; uint8_t pad[53]; }; struct versal_efuse_sec_ctrl_bits { uint8_t aes_dis; uint8_t jtag_err_out_dis; uint8_t jtag_dis; uint8_t ppk0_wr_lk; uint8_t ppk1_wr_lk; uint8_t ppk2_wr_lk; uint8_t aes_crc_lk; uint8_t aes_wr_lk; uint8_t user_key0_crc_lk; uint8_t user_key0_wr_lk; uint8_t user_key1_crc_lk; uint8_t user_key1_wr_lk; uint8_t sec_dbg_dis; uint8_t sec_lock_dbg_dis; uint8_t boot_env_wr_lk; uint8_t reg_init_dis; uint8_t pad[48]; }; struct versal_efuse_puf_header { struct versal_efuse_puf_sec_ctrl_bits sec_ctrl; uint8_t prmg_puf_helper_data; uint8_t env_monitor_dis; uint32_t efuse_syn_data[PUF_SYN_DATA_WORDS]; uint32_t chash; uint32_t aux; uint8_t pad[56]; }; struct versal_efuse_puf_user_fuse { uint32_t data_addr[PUF_EFUSES_WORDS]; uint8_t env_monitor_dis; uint8_t prgm_puf_fuse; uint32_t start_row; uint32_t num_rows; }; TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len); TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len, uint32_t first, size_t num); TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len, enum versal_nvm_iv_type type); TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len, enum versal_nvm_ppk_type type); TEE_Result versal_efuse_write_user_data(uint32_t *buf, size_t len, uint32_t first, size_t num); TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys); TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash); TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p); TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p); TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p); TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p); TEE_Result versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits *p); TEE_Result versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits *p); TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p); TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p); TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type); TEE_Result versal_efuse_write_revoke_id(uint32_t id); TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len, enum versal_nvm_revocation_id id); TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf); TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf); TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf); TEE_Result versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf); TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len, enum versal_nvm_offchip_id id); TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len); TEE_Result versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits *buf); TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf); TEE_Result versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p); TEE_Result versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p); TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf); TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len); TEE_Result versal_bbram_zeroize(void); TEE_Result versal_bbram_write_user_data(uint32_t data); TEE_Result versal_bbram_read_user_data(uint32_t *data); TEE_Result versal_bbram_lock_write_user_data(void); #endif /*__DRIVERS_VERSAL_NVM_H__*/ optee_os-4.3.0/core/include/drivers/versal_pm.h000066400000000000000000000005161464416617300215430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022 Foundries.io Ltd */ #ifndef __DRIVERS_VERSAL_PM_H__ #define __DRIVERS_VERSAL_PM_H__ #include #include TEE_Result versal_soc_version(uint8_t *version); TEE_Result versal_write_fpga(paddr_t pa); #endif /*__DRIVERS_VERSAL_PM_H__*/ optee_os-4.3.0/core/include/drivers/versal_puf.h000066400000000000000000000037351464416617300217270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022 Foundries.io Ltd * Jorge Ramirez-Ortiz */ #ifndef __DRIVERS_VERSAL_PUF_H #define __DRIVERS_VERSAL_PUF_H #include #include #include #include #define VERSAL_PUF_REGISTRATION 0x0 #define VERSAL_PUF_REGEN_ON_DEMAND 0x1 #define VERSAL_PUF_REGEN_ID_ONLY 0x2 #define VERSAL_PUF_SHUTTER_VALUE 0x81000100 #define VERSAL_PUF_SYNDROME_MODE_4K 0x0 #define VERSAL_PUF_GLBL_VAR_FLTR_OPTION 1 #define VERSAL_PUF_READ_FROM_RAM 0 #define VERSAL_PUF_READ_FROM_EFUSE_CACHE 1 #define VERSAL_PUF_4K_PUF_SYN_LEN_IN_WORDS 140 #define VERSAL_PUF_EFUSE_SYN_WORDS 127 #define VERSAL_PUF_SYNDROME_WORDS 350 #define VERSAL_PUF_ID_WORDS 8 #define VERSAL_PUF_HASH_LEN 4 #define VERSAL_PUF_AUX_LEN 4 struct versal_puf_data { uint32_t syndrome_data[VERSAL_PUF_SYNDROME_WORDS]; uint32_t chash; uint32_t aux; uint32_t puf_id[VERSAL_PUF_ID_WORDS]; uint32_t efuse_syn_data[VERSAL_PUF_EFUSE_SYN_WORDS]; }; struct versal_puf_cfg { uint8_t reg_mode; uint8_t puf_operation; uint8_t global_var_filter; uint8_t read_option; uint32_t shutter_value; }; struct versal_puf_data_req { uint8_t reg_mode; uint8_t puf_operation; uint8_t global_var_filter; uint8_t read_option; uint32_t shutter_value; uint64_t syndrome_data_addr; uint64_t hash_addr; uint64_t aux_addr; uint64_t puf_id_addr; uint64_t syndrome_addr; uint64_t efuse_syn_data_addr; uint8_t pad[8]; }; enum versal_puf_api { VERSAL_PUF_API_FEATURES = 0U, VERSAL_PUF_REGISTER, VERSAL_PUF_REGENERATE, VERSAL_PUF_CLEAR_ID, }; #define __aligned_puf __aligned(CACHELINE_LEN) TEE_Result versal_puf_regenerate(struct versal_puf_data *buf, struct versal_puf_cfg *cfg); TEE_Result versal_puf_register(struct versal_puf_data *buf, struct versal_puf_cfg *cfg); TEE_Result versal_puf_check_api(enum versal_puf_api id); TEE_Result versal_puf_clear_id(void); #endif /* __DRIVERS_VERSAL_PUF_H */ optee_os-4.3.0/core/include/drivers/versal_sha3_384.h000066400000000000000000000006301464416617300223600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022 Foundries.io Ltd */ #ifndef __DRIVERS_VERSAL_SHA3_384_H__ #define __DRIVERS_VERSAL_SHA3_384_H__ #include #include #include #include TEE_Result versal_sha3_384(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len); #endif /*__DRIVERS_VERSAL_SHA3_384_H__*/ optee_os-4.3.0/core/include/drivers/wdt.h000066400000000000000000000056261464416617300203600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 Broadcom. */ #ifndef __DRIVERS_WDT_H #define __DRIVERS_WDT_H #include #include #include #include #include struct wdt_chip { const struct wdt_ops *ops; struct itr_handler *wdt_itr; }; /* * struct wdt_ops - The watchdog device operations * * @init: The routine to initialized the watchdog resources. * @start: The routine for starting the watchdog device. * @stop: The routine for stopping the watchdog device. * @ping: The routine that sends a keepalive ping to the watchdog device. * @set_timeout:The routine that finds the load value that will reset system in * required timeout (in seconds). * * The wdt_ops structure contains a list of low-level operations * that control a watchdog device. */ struct wdt_ops { TEE_Result (*init)(struct wdt_chip *chip, unsigned long *min_timeout, unsigned long *max_timeout); void (*start)(struct wdt_chip *chip); void (*stop)(struct wdt_chip *chip); void (*ping)(struct wdt_chip *chip); TEE_Result (*set_timeout)(struct wdt_chip *chip, unsigned long timeout); }; #ifdef CFG_WDT extern struct wdt_chip *wdt_chip; /* Register a watchdog as the system watchdog */ TEE_Result watchdog_register(struct wdt_chip *chip); static inline TEE_Result watchdog_init(unsigned long *min_timeout, unsigned long *max_timeout) { if (!wdt_chip) return TEE_ERROR_NOT_SUPPORTED; if (!wdt_chip->ops->init) return TEE_SUCCESS; return wdt_chip->ops->init(wdt_chip, min_timeout, max_timeout); } static inline void watchdog_start(void) { if (wdt_chip) wdt_chip->ops->start(wdt_chip); } static inline void watchdog_stop(void) { if (wdt_chip && wdt_chip->ops->stop) wdt_chip->ops->stop(wdt_chip); } static inline void watchdog_ping(void) { if (wdt_chip) wdt_chip->ops->ping(wdt_chip); } static inline void watchdog_settimeout(unsigned long timeout) { if (wdt_chip) wdt_chip->ops->set_timeout(wdt_chip, timeout); } #else static inline TEE_Result watchdog_register(struct wdt_chip *chip __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result watchdog_init(unsigned long *min_timeout __unused, unsigned long *max_timeout __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void watchdog_start(void) {} static inline void watchdog_stop(void) {} static inline void watchdog_ping(void) {} static inline void watchdog_settimeout(unsigned long timeout __unused) {} #endif #ifdef CFG_WDT_SM_HANDLER enum sm_handler_ret __wdt_sm_handler(struct thread_smc_args *args); static inline enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args) { if (args->a0 != CFG_WDT_SM_HANDLER_ID) return SM_HANDLER_PENDING_SMC; return __wdt_sm_handler(args); } #else static inline enum sm_handler_ret wdt_sm_handler(struct thread_smc_args *args __unused) { return SM_HANDLER_PENDING_SMC; } #endif #endif /* __DRIVERS_WDT_H */ optee_os-4.3.0/core/include/drivers/zynqmp_csu.h000066400000000000000000000023641464416617300217660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2021 * Author: Jorge Ramirez */ #ifndef __DRIVERS_ZYNQMP_CSU_H_ #define __DRIVERS_ZYNQMP_CSU_H_ /* CSU registers */ #define ZYNQMP_CSU_STATUS_OFFSET 0x00 #define ZYNQMP_CSU_CTRL_OFFSET 0x04 #define ZYNQMP_CSU_SSS_CFG_OFFSET 0x08 #define ZYNQMP_CSU_DMA_RESET_OFFSET 0x0c #define ZYNQMP_CSU_MULTI_BOOT_OFFSET 0x10 #define ZYNQMP_CSU_TAMPER_TRIG_OFFSET 0x14 #define ZYNQMP_CSU_FT_STATUS_OFFSET 0x18 #define ZYNQMP_CSU_ISR_OFFSET 0x20 #define ZYNQMP_CSU_STATUS_AUTH BIT(0) #define ZYNQMP_CSU_SSS_DMA0_STREAM_TO_AES 0x5A0 #define ZYNQMP_CSU_DMA_RESET_SET 1 #define ZYNQMP_CSU_DMA_RESET_CLR 0 #define ZYNQMP_CSU_ISR_PUF_ACC_ERROR_MASK BIT(12) /* AES-GCM */ #define ZYNQMP_CSU_AES_BASE (CSU_BASE + 0x1000) #define ZYNQMP_CSU_AES_SIZE 0x1000 /* SHA */ #define ZYNQMP_CSU_SHA_BASE (CSU_BASE + 0x2000) #define ZYNQMP_CSU_SHA_SIZE 0x1000 /* PCAP */ #define ZYNQMP_CSU_PCAP_BASE (CSU_BASE + 0x3000) #define ZYNQMP_CSU_PCAP_SIZE 0x1000 /* PUF */ #define ZYNQMP_CSU_PUF_BASE (CSU_BASE + 0x4000) #define ZYNQMP_CSU_PUF_SIZE 0x1000 /* TAMPER */ #define ZYNQMP_CSU_TAMPER_BASE (CSU_BASE + 0x5000) #define ZYNQMP_CSU_TAMPER_SIZE 0x38 #endif optee_os-4.3.0/core/include/drivers/zynqmp_csu_aes.h000066400000000000000000000020601464416617300226070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2021 * Author: Jorge Ramirez */ #ifndef __DRIVERS_ZYNQMP_CSU_AES_H_ #define __DRIVERS_ZYNQMP_CSU_AES_H_ #include #include #include #define __aligned_csuaes __aligned_csudma #define ZYNQMP_GCM_TAG_SIZE 16 #define ZYNQMP_GCM_IV_SIZE 12 enum zynqmp_csu_key { ZYNQMP_CSU_AES_KEY_SRC_KUP = 0, ZYNQMP_CSU_AES_KEY_SRC_DEV }; #define ZYNQMP_CSU_AES_DST_LEN(x) ((x) + ZYNQMP_GCM_TAG_SIZE) TEE_Result zynqmp_csu_aes_encrypt_data(const void *src, size_t src_len, void *dst, size_t dst_len, void *tag, size_t tag_len, const void *iv, size_t iv_len, enum zynqmp_csu_key key); TEE_Result zynqmp_csu_aes_decrypt_data(const void *src, size_t src_len, void *dst, size_t len, const void *tag, size_t tag_len, const void *iv, size_t iv_len, enum zynqmp_csu_key key); TEE_Result zynqmp_csu_aes_dt_enable_secure_status(void); #endif optee_os-4.3.0/core/include/drivers/zynqmp_csu_puf.h000066400000000000000000000005011464416617300226270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2021 * Author: Jorge Ramirez */ #ifndef __DRIVERS_ZYNQMP_CSU_PUF_H_ #define __DRIVERS_ZYNQMP_CSU_PUF_H_ #include TEE_Result zynqmp_csu_puf_regenerate(void); void zynqmp_csu_puf_reset(void); #endif optee_os-4.3.0/core/include/drivers/zynqmp_csudma.h000066400000000000000000000014611464416617300224450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) Foundries Ltd. 2021 * Author: Jorge Ramirez */ #ifndef __DRIVERS_ZYNQMP_CSUDMA_H_ #define __DRIVERS_ZYNQMP_CSUDMA_H_ #include #include #include #define ZYNQMP_CSUDMA_ALIGN 64 #define __aligned_csudma __aligned(ZYNQMP_CSUDMA_ALIGN) #define ZYNQMP_CSUDMA_MIN_SIZE 16 #define ZYNQMP_CSUDMA_DONE BIT(0) enum zynqmp_csudma_channel { ZYNQMP_CSUDMA_SRC_CHANNEL = 0, ZYNQMP_CSUDMA_DST_CHANNEL }; TEE_Result zynqmp_csudma_transfer(enum zynqmp_csudma_channel channel, void *address, size_t len, uint8_t notify); TEE_Result zynqmp_csudma_sync(enum zynqmp_csudma_channel channel); TEE_Result zynqmp_csudma_prepare(void); void zynqmp_csudma_unprepare(void); #endif optee_os-4.3.0/core/include/drivers/zynqmp_efuse.h000066400000000000000000000030721464416617300223000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2021 Foundries.io Ltd */ #ifndef __DRIVERS_ZYNQMP_EFUSE_H__ #define __DRIVERS_ZYNQMP_EFUSE_H__ #include #define ZYNQMP_EFUSE_DNA_OFFSET 0xc #define ZYNQMP_EFUSE_DNA_LENGTH 12 #define ZYNQMP_EFUSE_IP_DISABLE_OFFSET 0x18 #define ZYNQMP_EFUSE_IP_DISABLE_LENGTH 4 #define ZYNQMP_EFUSE_USER0_OFFSET 0x20 #define ZYNQMP_EFUSE_USER0_LENGTH 4 #define ZYNQMP_EFUSE_USER1_OFFSET 0x24 #define ZYNQMP_EFUSE_USER1_LENGTH 4 #define ZYNQMP_EFUSE_USER2_OFFSET 0x28 #define ZYNQMP_EFUSE_USER2_LENGTH 4 #define ZYNQMP_EFUSE_USER3_OFFSET 0x2c #define ZYNQMP_EFUSE_USER3_LENGTH 4 #define ZYNQMP_EFUSE_USER4_OFFSET 0x30 #define ZYNQMP_EFUSE_USER4_LENGTH 4 #define ZYNQMP_EFUSE_USER5_OFFSET 0x34 #define ZYNQMP_EFUSE_USER5_LENGTH 4 #define ZYNQMP_EFUSE_USER6_OFFSET 0x38 #define ZYNQMP_EFUSE_USER6_LENGTH 4 #define ZYNQMP_EFUSE_USER7_OFFSET 0x3c #define ZYNQMP_EFUSE_USER7_LENGTH 4 #define ZYNQMP_EFUSE_MISC_USER_CTRL_OFFSET 0x40 #define ZYNQMP_EFUSE_MISC_USER_CTRL_LENGTH 4 #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_0 BIT(0) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_1 BIT(1) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_2 BIT(2) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_3 BIT(3) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_4 BIT(4) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_5 BIT(5) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_6 BIT(6) #define ZYNQMP_EFUSE_MISC_USER_CTRL_USR_WRLK_7 BIT(7) #define ZYNQMP_EFUSE_SEC_CTRL_OFFSET 0x58 #define ZYNQMP_EFUSE_SEC_CTRL_LENGTH 4 #endif /*__DRIVERS_ZYNQMP_EFUSE_H__*/ optee_os-4.3.0/core/include/drivers/zynqmp_huk.h000066400000000000000000000016651464416617300217660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022, Vaisala Oyj */ #ifndef __DRIVERS_ZYNQMP_HUK_H__ #define __DRIVERS_ZYNQMP_HUK_H__ /* * Query Device DNA from the device * * Note: configured as weak so that it can be replaced with implementation to * get read only PL Device DNA from FPGA array. This would need custom IP core * for access. * * Both PS and PL Device DNA's have 96 bits. * * Xilinx recommends to use PL Device DNA for device identification. * * ref: * * 71342 - Zynq UltraScale+ Device - PS DNA is not write protected and is a * different value than the PL DNA * * https://support.xilinx.com/s/article/71342 * * @device_dna: Memory buffer to receive value of Device DNA * @size: length of device_dna buffer (requires buffer of 12 bytes) * Return a TEE_Result compliant status */ TEE_Result tee_zynqmp_get_device_dna(uint8_t *device_dna, size_t size); #endif /* __DRIVERS_ZYNQMP_HUK_H__ */ optee_os-4.3.0/core/include/drivers/zynqmp_pm.h000066400000000000000000000036721464416617300216130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2021 Foundries.io Ltd */ #ifndef __DRIVERS_ZYNQMP_PM_H__ #define __DRIVERS_ZYNQMP_PM_H__ #include #include #include #include /* * Information about accessing eFuses and the Physically Uncloneable Function * (PUF) Support can be found at * https://www.xilinx.com/support/documentation/application_notes/xapp1319-zynq-usp-prog-nvm.pdf */ #define ZYNQMP_NONPUF_EFUSE 0 #define ZYNQMP_PUF_EFUSE 1 /* List of eFuse identifiers */ enum zynqmp_efuse_id { DNA = 0, IP_DISABLE, USER0, USER1, USER2, USER3, USER4, USER5, USER6, USER7, MISC_USER_CTRL, SEC_CTRL, }; /* Valid bytes in the eFuse */ #define ZYNQMP_EFUSE_LEN(_id) ZYNQMP_EFUSE_##_id##_LENGTH /* Memory required to access the eFuse */ #define ZYNQMP_EFUSE_MEM(_id) (ROUNDUP(ZYNQMP_EFUSE_LEN(_id), CACHELINE_LEN)) /* Alignment required in the buffers used to read the eFuse */ #define __aligned_efuse __aligned(CACHELINE_LEN) /* * Read eFuse memory * @buf: buffer, where eFuse date will be stored. The data is returned * in LE byte order. * @buf_sz: buffer size in bytes * @id: eFuse identifier. * @puf: is eFuse PUF, ZYNQMP_PUF_EFUSE/ZYNQMP_NONPUF_EFUSE * Return a TEE_Result compliant status */ TEE_Result zynqmp_efuse_read(uint8_t *buf, size_t buf_sz, enum zynqmp_efuse_id id, bool puf); /* * Program eFuse memory * @buf: buffer where eFuse data are stored in LE byte order. * @buf_sz: buffer size in bytes * @id: eFuse identifier. * @puf: is eFuse PUF, ZYNQMP_PUF_EFUSE/ZYNQMP_NONPUF_EFUSE * Return a TEE_Result compliant status */ TEE_Result zynqmp_efuse_write(uint8_t *buf, size_t buf_sz, enum zynqmp_efuse_id id, bool puf); /* * Read the SoC version number: * Different eFuse bitfields carry different meaning depending on this version. */ TEE_Result zynqmp_soc_version(uint32_t *version); #endif /*__DRIVERS_ZYNQMP_PM_H__*/ optee_os-4.3.0/core/include/dt-bindings/000077500000000000000000000000001464416617300201245ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/clock/000077500000000000000000000000001464416617300212175ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/clock/at91.h000066400000000000000000000153501464416617300221520ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0-or-later or BSD-3-Clause */ /* * Copyright (C) 2021 Microchip * * This header provides constants for AT91 pmc status. * * The constants defined in this header are being used in dts. */ #ifndef _DT_BINDINGS_CLK_AT91_H #define _DT_BINDINGS_CLK_AT91_H #define PMC_TYPE_CORE 0 #define PMC_TYPE_SYSTEM 1 #define PMC_TYPE_PERIPHERAL 2 #define PMC_TYPE_GCK 3 #define PMC_TYPE_PROGRAMMABLE 4 #define PMC_SLOW 0 #define PMC_MCK 1 #define PMC_UTMI 2 #define PMC_MAIN 3 #define PMC_MCK2 4 #define PMC_I2S0_MUX 5 #define PMC_I2S1_MUX 6 #define PMC_PLLACK 7 #define PMC_PLLBCK 8 #define PMC_AUDIOPLLCK 9 #define PMC_MCK_PRES 10 #define PMC_AUDIOPLL_FRACCK 11 #define PMC_USBCK 12 #define PMC_SAMA5D2_CORE_CLK_COUNT 13 /* SAMA7G5 */ #define PMC_CPUPLL (PMC_MAIN + 1) #define PMC_SYSPLL (PMC_MAIN + 2) #define PMC_DDRPLL (PMC_MAIN + 3) #define PMC_IMGPLL (PMC_MAIN + 4) #define PMC_BAUDPLL (PMC_MAIN + 5) #define PMC_AUDIOPMCPLL (PMC_MAIN + 6) /* Reserved for PMC_MCK_PRES */ #define PMC_AUDIOIOPLL (PMC_MAIN + 8) #define PMC_ETHPLL (PMC_MAIN + 9) #define PMC_MCK1 (PMC_MAIN + 10) /* Reserved for MCK2, MCK3, MCK4 */ #define PMC_UTMI1 (PMC_MAIN + 14) #define PMC_UTMI2 (PMC_MAIN + 15) #define PMC_UTMI3 (PMC_MAIN + 16) #define PMC_SAMA7G5_CORE_CLK_COUNT (PMC_MAIN + 17) #define AT91_SCMI_CLK_CORE_MCK 0 #define AT91_SCMI_CLK_CORE_UTMI 1 #define AT91_SCMI_CLK_CORE_MAIN 2 #define AT91_SCMI_CLK_CORE_MCK2 3 #define AT91_SCMI_CLK_CORE_I2S0_MUX 4 #define AT91_SCMI_CLK_CORE_I2S1_MUX 5 #define AT91_SCMI_CLK_CORE_PLLACK 6 #define AT91_SCMI_CLK_CORE_PLLBCK 7 #define AT91_SCMI_CLK_CORE_AUDIOPLLCK 8 #define AT91_SCMI_CLK_CORE_MCK_PRES 9 #define AT91_SCMI_CLK_SYSTEM_DDRCK 10 #define AT91_SCMI_CLK_SYSTEM_LCDCK 11 #define AT91_SCMI_CLK_SYSTEM_UHPCK 12 #define AT91_SCMI_CLK_SYSTEM_UDPCK 13 #define AT91_SCMI_CLK_SYSTEM_PCK0 14 #define AT91_SCMI_CLK_SYSTEM_PCK1 15 #define AT91_SCMI_CLK_SYSTEM_PCK2 16 #define AT91_SCMI_CLK_SYSTEM_ISCCK 17 #define AT91_SCMI_CLK_PERIPH_MACB0_CLK 18 #define AT91_SCMI_CLK_PERIPH_TDES_CLK 19 #define AT91_SCMI_CLK_PERIPH_MATRIX1_CLK 20 #define AT91_SCMI_CLK_PERIPH_HSMC_CLK 21 #define AT91_SCMI_CLK_PERIPH_PIOA_CLK 22 #define AT91_SCMI_CLK_PERIPH_FLX0_CLK 23 #define AT91_SCMI_CLK_PERIPH_FLX1_CLK 24 #define AT91_SCMI_CLK_PERIPH_FLX2_CLK 25 #define AT91_SCMI_CLK_PERIPH_FLX3_CLK 26 #define AT91_SCMI_CLK_PERIPH_FLX4_CLK 27 #define AT91_SCMI_CLK_PERIPH_UART0_CLK 28 #define AT91_SCMI_CLK_PERIPH_UART1_CLK 29 #define AT91_SCMI_CLK_PERIPH_UART2_CLK 30 #define AT91_SCMI_CLK_PERIPH_UART3_CLK 31 #define AT91_SCMI_CLK_PERIPH_UART4_CLK 32 #define AT91_SCMI_CLK_PERIPH_TWI0_CLK 33 #define AT91_SCMI_CLK_PERIPH_TWI1_CLK 34 #define AT91_SCMI_CLK_PERIPH_SPI0_CLK 35 #define AT91_SCMI_CLK_PERIPH_SPI1_CLK 36 #define AT91_SCMI_CLK_PERIPH_TCB0_CLK 37 #define AT91_SCMI_CLK_PERIPH_TCB1_CLK 38 #define AT91_SCMI_CLK_PERIPH_PWM_CLK 39 #define AT91_SCMI_CLK_PERIPH_ADC_CLK 40 #define AT91_SCMI_CLK_PERIPH_UHPHS_CLK 41 #define AT91_SCMI_CLK_PERIPH_UDPHS_CLK 42 #define AT91_SCMI_CLK_PERIPH_SSC0_CLK 43 #define AT91_SCMI_CLK_PERIPH_SSC1_CLK 44 #define AT91_SCMI_CLK_PERIPH_TRNG_CLK 45 #define AT91_SCMI_CLK_PERIPH_PDMIC_CLK 46 #define AT91_SCMI_CLK_PERIPH_SECURAM_CLK 47 #define AT91_SCMI_CLK_PERIPH_I2S0_CLK 48 #define AT91_SCMI_CLK_PERIPH_I2S1_CLK 49 #define AT91_SCMI_CLK_PERIPH_CAN0_CLK 50 #define AT91_SCMI_CLK_PERIPH_CAN1_CLK 51 #define AT91_SCMI_CLK_PERIPH_PTC_CLK 52 #define AT91_SCMI_CLK_PERIPH_CLASSD_CLK 53 #define AT91_SCMI_CLK_PERIPH_DMA0_CLK 54 #define AT91_SCMI_CLK_PERIPH_DMA1_CLK 55 #define AT91_SCMI_CLK_PERIPH_AES_CLK 56 #define AT91_SCMI_CLK_PERIPH_AESB_CLK 57 #define AT91_SCMI_CLK_PERIPH_SHA_CLK 58 #define AT91_SCMI_CLK_PERIPH_MPDDR_CLK 59 #define AT91_SCMI_CLK_PERIPH_MATRIX0_CLK 60 #define AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK 61 #define AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK 62 #define AT91_SCMI_CLK_PERIPH_LCDC_CLK 63 #define AT91_SCMI_CLK_PERIPH_ISC_CLK 64 #define AT91_SCMI_CLK_PERIPH_QSPI0_CLK 65 #define AT91_SCMI_CLK_PERIPH_QSPI1_CLK 66 #define AT91_SCMI_CLK_GCK_SDMMC0_GCLK 67 #define AT91_SCMI_CLK_GCK_SDMMC1_GCLK 68 #define AT91_SCMI_CLK_GCK_TCB0_GCLK 69 #define AT91_SCMI_CLK_GCK_TCB1_GCLK 70 #define AT91_SCMI_CLK_GCK_PWM_GCLK 71 #define AT91_SCMI_CLK_GCK_ISC_GCLK 72 #define AT91_SCMI_CLK_GCK_PDMIC_GCLK 73 #define AT91_SCMI_CLK_GCK_I2S0_GCLK 74 #define AT91_SCMI_CLK_GCK_I2S1_GCLK 75 #define AT91_SCMI_CLK_GCK_CAN0_GCLK 76 #define AT91_SCMI_CLK_GCK_CAN1_GCLK 77 #define AT91_SCMI_CLK_GCK_CLASSD_GCLK 78 #define AT91_SCMI_CLK_PROG_PROG0 79 #define AT91_SCMI_CLK_PROG_PROG1 80 #define AT91_SCMI_CLK_PROG_PROG2 81 #define AT91_SCMI_CLK_SCKC_SLOWCK_32K 82 #define AT91_SCMI_CLK_CPU_OPP 101 #ifdef CFG_SAMA7G5 #define AT91_SCMI_CLK_CORE_CPUPLLCK 4 #define AT91_SCMI_CLK_CORE_SYSPLLCK 5 #define AT91_SCMI_CLK_CORE_DDRPLLCK 6 #define AT91_SCMI_CLK_CORE_IMGPLLCK 7 #define AT91_SCMI_CLK_CORE_ETHPLLCK 10 #define AT91_SCMI_CLK_SYSTEM_PCK3 11 #define AT91_SCMI_CLK_SYSTEM_PCK4 12 #define AT91_SCMI_CLK_SYSTEM_PCK5 13 #define AT91_SCMI_CLK_SYSTEM_PCK6 17 #define AT91_SCMI_CLK_SYSTEM_PCK7 20 #define AT91_SCMI_CLK_UTMI1 97 #define AT91_SCMI_CLK_UTMI2 98 #define AT91_SCMI_CLK_UTMI3 99 #define AT91_SCMI_CLK_PERIPH_DMA2_CLK 100 #define AT91_SCMI_CLK_PERIPH_FLX5_CLK 28 #define AT91_SCMI_CLK_PERIPH_FLX6_CLK 29 #define AT91_SCMI_CLK_PERIPH_FLX7_CLK 30 #define AT91_SCMI_CLK_PERIPH_FLX8_CLK 31 #define AT91_SCMI_CLK_PERIPH_FLX9_CLK 32 #define AT91_SCMI_CLK_PERIPH_FLX10_CLK 33 #define AT91_SCMI_CLK_PERIPH_FLX11_CLK 34 #define AT91_SCMI_CLK_PERIPH_UDPHSB_CLK 35 #define AT91_SCMI_CLK_PERIPH_PDMC1_CLK 36 #define AT91_SCMI_CLK_PERIPH_UDPHSA_CLK 42 #define AT91_SCMI_CLK_GCK_ADC_GCLK 40 #define AT91_SCMI_CLK_PERIPH_PDMC0_CLK 46 #define AT91_SCMI_CLK_PERIPH_CAN2_CLK 52 #define AT91_SCMI_CLK_PERIPH_CAN3_CLK 53 #define AT91_SCMI_CLK_PERIPH_CAN4_CLK 59 #define AT91_SCMI_CLK_PERIPH_CAN5_CLK 60 #define AT91_SCMI_CLK_PERIPH_SDMMC2_HCLK 63 #define AT91_SCMI_CLK_GCK_SDMMC2_GCLK 71 #define AT91_SCMI_CLK_GCK_MACB0_GCLK 72 #define AT91_SCMI_CLK_GCK_MACB0_TSU 73 #define AT91_SCMI_CLK_GCK_CAN2_GCLK 78 #define AT91_SCMI_CLK_GCK_CAN3_GCLK 79 #define AT91_SCMI_CLK_GCK_CAN4_GCLK 80 #define AT91_SCMI_CLK_GCK_CAN5_GCLK 81 #define AT91_SCMI_CLK_PERIPH_SPDIFRX_CLK 83 #define AT91_SCMI_CLK_PERIPH_SPDIFTX_CLK 84 #define AT91_SCMI_CLK_GCK_QSPI0_GCLK 85 #define AT91_SCMI_CLK_GCK_QSPI1_GCLK 86 #define AT91_SCMI_CLK_GCK_SPDIFRX_GCLK 87 #define AT91_SCMI_CLK_GCK_SPDIFTX_GCLK 88 #define AT91_SCMI_CLK_GCK_MACB1_GCLK 89 #define AT91_SCMI_CLK_PERIPH_MACB1_CLK 90 #define AT91_SCMI_CLK_GCK_MACB1_TSU 91 #define AT91_SCMI_CLK_PERIPH_CSI_CLK 92 #define AT91_SCMI_CLK_GCK_CSI_GCLK 93 #define AT91_SCMI_CLK_PERIPH_CSI2DC_CLK 94 #define AT91_SCMI_CLK_PERIPH_ASRC_CLK 95 #define AT91_SCMI_CLK_GCK_ASRC_GCLK 96 #endif #endif optee_os-4.3.0/core/include/dt-bindings/clock/st,stm32mp25-rcc.h000066400000000000000000000307101464416617300242350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) STMicroelectronics 2024 - All Rights Reserved */ #ifndef _DT_BINDINGS_CLOCK_ST_STM32MP25_RCC_H_ #define _DT_BINDINGS_CLOCK_ST_STM32MP25_RCC_H_ /* INTERNAL/EXTERNAL OSCILLATORS */ #define HSI_CK 0 #define HSE_CK 1 #define MSI_CK 2 #define LSI_CK 3 #define LSE_CK 4 #define I2S_CK 5 #define RTC_CK 6 #define SPDIF_CK_SYMB 7 /* PLL CLOCKS */ #define PLL1_CK 8 #define PLL2_CK 9 #define PLL3_CK 10 #define PLL4_CK 11 #define PLL5_CK 12 #define PLL6_CK 13 #define PLL7_CK 14 #define PLL8_CK 15 #define CK_CPU1 16 /* APB DIV CLOCKS */ #define CK_ICN_APB1 17 #define CK_ICN_APB2 18 #define CK_ICN_APB3 19 #define CK_ICN_APB4 20 #define CK_ICN_APBDBG 21 /* GLOBAL TIMER */ #define TIMG1_CK 22 #define TIMG2_CK 23 /* FLEXGEN CLOCKS */ #define CK_ICN_HS_MCU 24 #define CK_ICN_SDMMC 25 #define CK_ICN_DDR 26 #define CK_ICN_DISPLAY 27 #define CK_ICN_HSL 28 #define CK_ICN_NIC 29 #define CK_ICN_VID 30 #define CK_FLEXGEN_07 31 #define CK_FLEXGEN_08 32 #define CK_FLEXGEN_09 33 #define CK_FLEXGEN_10 34 #define CK_FLEXGEN_11 35 #define CK_FLEXGEN_12 36 #define CK_FLEXGEN_13 37 #define CK_FLEXGEN_14 38 #define CK_FLEXGEN_15 39 #define CK_FLEXGEN_16 40 #define CK_FLEXGEN_17 41 #define CK_FLEXGEN_18 42 #define CK_FLEXGEN_19 43 #define CK_FLEXGEN_20 44 #define CK_FLEXGEN_21 45 #define CK_FLEXGEN_22 46 #define CK_FLEXGEN_23 47 #define CK_FLEXGEN_24 48 #define CK_FLEXGEN_25 49 #define CK_FLEXGEN_26 50 #define CK_FLEXGEN_27 51 #define CK_FLEXGEN_28 52 #define CK_FLEXGEN_29 53 #define CK_FLEXGEN_30 54 #define CK_FLEXGEN_31 55 #define CK_FLEXGEN_32 56 #define CK_FLEXGEN_33 57 #define CK_FLEXGEN_34 58 #define CK_FLEXGEN_35 59 #define CK_FLEXGEN_36 60 #define CK_FLEXGEN_37 61 #define CK_FLEXGEN_38 62 #define CK_FLEXGEN_39 63 #define CK_FLEXGEN_40 64 #define CK_FLEXGEN_41 65 #define CK_FLEXGEN_42 66 #define CK_FLEXGEN_43 67 #define CK_FLEXGEN_44 68 #define CK_FLEXGEN_45 69 #define CK_FLEXGEN_46 70 #define CK_FLEXGEN_47 71 #define CK_FLEXGEN_48 72 #define CK_FLEXGEN_49 73 #define CK_FLEXGEN_50 74 #define CK_FLEXGEN_51 75 #define CK_FLEXGEN_52 76 #define CK_FLEXGEN_53 77 #define CK_FLEXGEN_54 78 #define CK_FLEXGEN_55 79 #define CK_FLEXGEN_56 80 #define CK_FLEXGEN_57 81 #define CK_FLEXGEN_58 82 #define CK_FLEXGEN_59 83 #define CK_FLEXGEN_60 84 #define CK_FLEXGEN_61 85 #define CK_FLEXGEN_62 86 #define CK_FLEXGEN_63 87 /* LOW SPEED MCU CLOCK */ #define CK_ICN_LS_MCU 88 #define CK_BUS_STM 89 #define CK_BUS_FMC 90 #define CK_BUS_GPU 91 #define CK_BUS_ETH1 92 #define CK_BUS_ETH2 93 #define CK_BUS_PCIE 94 #define CK_BUS_DDRPHYC 95 #define CK_BUS_SYSCPU1 96 #define CK_BUS_ETHSW 97 #define CK_BUS_HPDMA1 98 #define CK_BUS_HPDMA2 99 #define CK_BUS_HPDMA3 100 #define CK_BUS_ADC12 101 #define CK_BUS_ADC3 102 #define CK_BUS_IPCC1 103 #define CK_BUS_CCI 104 #define CK_BUS_CRC 105 #define CK_BUS_MDF1 106 #define CK_BUS_OSPIIOM 107 #define CK_BUS_BKPSRAM 108 #define CK_BUS_HASH 109 #define CK_BUS_RNG 110 #define CK_BUS_CRYP1 111 #define CK_BUS_CRYP2 112 #define CK_BUS_SAES 113 #define CK_BUS_PKA 114 #define CK_BUS_GPIOA 115 #define CK_BUS_GPIOB 116 #define CK_BUS_GPIOC 117 #define CK_BUS_GPIOD 118 #define CK_BUS_GPIOE 119 #define CK_BUS_GPIOF 120 #define CK_BUS_GPIOG 121 #define CK_BUS_GPIOH 122 #define CK_BUS_GPIOI 123 #define CK_BUS_GPIOJ 124 #define CK_BUS_GPIOK 125 #define CK_BUS_LPSRAM1 126 #define CK_BUS_LPSRAM2 127 #define CK_BUS_LPSRAM3 128 #define CK_BUS_GPIOZ 129 #define CK_BUS_LPDMA 130 #define CK_BUS_HSEM 131 #define CK_BUS_IPCC2 132 #define CK_BUS_RTC 133 #define CK_BUS_SPI8 134 #define CK_BUS_LPUART1 135 #define CK_BUS_I2C8 136 #define CK_BUS_LPTIM3 137 #define CK_BUS_LPTIM4 138 #define CK_BUS_LPTIM5 139 #define CK_BUS_IWDG5 140 #define CK_BUS_WWDG2 141 #define CK_BUS_I3C4 142 #define CK_BUS_TIM2 143 #define CK_BUS_TIM3 144 #define CK_BUS_TIM4 145 #define CK_BUS_TIM5 146 #define CK_BUS_TIM6 147 #define CK_BUS_TIM7 148 #define CK_BUS_TIM10 149 #define CK_BUS_TIM11 150 #define CK_BUS_TIM12 151 #define CK_BUS_TIM13 152 #define CK_BUS_TIM14 153 #define CK_BUS_LPTIM1 154 #define CK_BUS_LPTIM2 155 #define CK_BUS_SPI2 156 #define CK_BUS_SPI3 157 #define CK_BUS_SPDIFRX 158 #define CK_BUS_USART2 159 #define CK_BUS_USART3 160 #define CK_BUS_UART4 161 #define CK_BUS_UART5 162 #define CK_BUS_I2C1 163 #define CK_BUS_I2C2 164 #define CK_BUS_I2C3 165 #define CK_BUS_I2C4 166 #define CK_BUS_I2C5 167 #define CK_BUS_I2C6 168 #define CK_BUS_I2C7 169 #define CK_BUS_I3C1 170 #define CK_BUS_I3C2 171 #define CK_BUS_I3C3 172 #define CK_BUS_TIM1 173 #define CK_BUS_TIM8 174 #define CK_BUS_TIM15 175 #define CK_BUS_TIM16 176 #define CK_BUS_TIM17 177 #define CK_BUS_TIM20 178 #define CK_BUS_SAI1 179 #define CK_BUS_SAI2 180 #define CK_BUS_SAI3 181 #define CK_BUS_SAI4 182 #define CK_BUS_USART1 183 #define CK_BUS_USART6 184 #define CK_BUS_UART7 185 #define CK_BUS_UART8 186 #define CK_BUS_UART9 187 #define CK_BUS_FDCAN 188 #define CK_BUS_SPI1 189 #define CK_BUS_SPI4 190 #define CK_BUS_SPI5 191 #define CK_BUS_SPI6 192 #define CK_BUS_SPI7 193 #define CK_BUS_BSEC 194 #define CK_BUS_IWDG1 195 #define CK_BUS_IWDG2 196 #define CK_BUS_IWDG3 197 #define CK_BUS_IWDG4 198 #define CK_BUS_WWDG1 199 #define CK_BUS_VREF 200 #define CK_BUS_DTS 201 #define CK_BUS_SERC 202 #define CK_BUS_HDP 203 #define CK_BUS_IS2M 204 #define CK_BUS_DSI 205 #define CK_BUS_LTDC 206 #define CK_BUS_CSI 207 #define CK_BUS_DCMIPP 208 #define CK_BUS_DDRC 209 #define CK_BUS_DDRCFG 210 #define CK_BUS_GICV2M 211 #define CK_BUS_USBTC 212 #define CK_BUS_USB3PCIEPHY 214 #define CK_BUS_STGEN 215 #define CK_BUS_VDEC 216 #define CK_BUS_VENC 217 #define CK_SYSDBG 218 #define CK_KER_TIM2 219 #define CK_KER_TIM3 220 #define CK_KER_TIM4 221 #define CK_KER_TIM5 222 #define CK_KER_TIM6 223 #define CK_KER_TIM7 224 #define CK_KER_TIM10 225 #define CK_KER_TIM11 226 #define CK_KER_TIM12 227 #define CK_KER_TIM13 228 #define CK_KER_TIM14 229 #define CK_KER_TIM1 230 #define CK_KER_TIM8 231 #define CK_KER_TIM15 232 #define CK_KER_TIM16 233 #define CK_KER_TIM17 234 #define CK_KER_TIM20 235 #define CK_BUS_SYSRAM 236 #define CK_BUS_VDERAM 237 #define CK_BUS_RETRAM 238 #define CK_BUS_OSPI1 239 #define CK_BUS_OSPI2 240 #define CK_BUS_OTFD1 241 #define CK_BUS_OTFD2 242 #define CK_BUS_SRAM1 243 #define CK_BUS_SRAM2 244 #define CK_BUS_SDMMC1 245 #define CK_BUS_SDMMC2 246 #define CK_BUS_SDMMC3 247 #define CK_BUS_DDR 248 #define CK_BUS_RISAF4 249 #define CK_BUS_USB2OHCI 250 #define CK_BUS_USB2EHCI 251 #define CK_BUS_USB3DR 252 #define CK_KER_LPTIM1 253 #define CK_KER_LPTIM2 254 #define CK_KER_USART2 255 #define CK_KER_UART4 256 #define CK_KER_USART3 257 #define CK_KER_UART5 258 #define CK_KER_SPI2 259 #define CK_KER_SPI3 260 #define CK_KER_SPDIFRX 261 #define CK_KER_I2C1 262 #define CK_KER_I2C2 263 #define CK_KER_I3C1 264 #define CK_KER_I3C2 265 #define CK_KER_I2C3 266 #define CK_KER_I2C5 267 #define CK_KER_I3C3 268 #define CK_KER_I2C4 269 #define CK_KER_I2C6 270 #define CK_KER_I2C7 271 #define CK_KER_SPI1 272 #define CK_KER_SPI4 273 #define CK_KER_SPI5 274 #define CK_KER_SPI6 275 #define CK_KER_SPI7 276 #define CK_KER_USART1 277 #define CK_KER_USART6 278 #define CK_KER_UART7 279 #define CK_KER_UART8 280 #define CK_KER_UART9 281 #define CK_KER_MDF1 282 #define CK_KER_SAI1 283 #define CK_KER_SAI2 284 #define CK_KER_SAI3 285 #define CK_KER_SAI4 286 #define CK_KER_FDCAN 287 #define CK_KER_DSIBLANE 288 #define CK_KER_DSIPHY 289 #define CK_KER_CSI 290 #define CK_KER_CSITXESC 291 #define CK_KER_CSIPHY 292 #define CK_KER_LVDSPHY 293 #define CK_KER_STGEN 294 #define CK_KER_USB3PCIEPHY 295 #define CK_KER_USB2PHY2EN 296 #define CK_KER_I3C4 297 #define CK_KER_SPI8 298 #define CK_KER_I2C8 299 #define CK_KER_LPUART1 300 #define CK_KER_LPTIM3 301 #define CK_KER_LPTIM4 302 #define CK_KER_LPTIM5 303 #define CK_KER_TSDBG 304 #define CK_KER_TPIU 305 #define CK_BUS_ETR 306 #define CK_BUS_SYSATB 307 #define CK_KER_ADC12 308 #define CK_KER_ADC3 309 #define CK_KER_OSPI1 310 #define CK_KER_OSPI2 311 #define CK_KER_FMC 312 #define CK_KER_SDMMC1 313 #define CK_KER_SDMMC2 314 #define CK_KER_SDMMC3 315 #define CK_KER_ETH1 316 #define CK_KER_ETH2 317 #define CK_KER_ETH1PTP 318 #define CK_KER_ETH2PTP 319 #define CK_KER_USB2PHY1 320 #define CK_KER_USB2PHY2 321 #define CK_KER_ETHSW 322 #define CK_KER_ETHSWREF 323 #define CK_MCO1 324 #define CK_MCO2 325 #define CK_KER_DTS 326 #define CK_ETH1_RX 327 #define CK_ETH1_TX 328 #define CK_ETH1_MAC 329 #define CK_ETH2_RX 330 #define CK_ETH2_TX 331 #define CK_ETH2_MAC 332 #define CK_ETH1_STP 333 #define CK_ETH2_STP 334 #define CK_KER_USBTC 335 #define CK_BUS_ADF1 336 #define CK_KER_ADF1 337 #define CK_BUS_LVDS 338 #define CK_KER_LTDC 339 #define CK_KER_GPU 340 #define CK_BUS_ETHSWACMCFG 341 #define CK_BUS_ETHSWACMMSG 342 #define HSE_DIV2_CK 343 #define CK_KER_ETR 344 #define CK_KER_STM 345 #define STM32MP25_LAST_CLK 346 #define CK_SCMI_ICN_HS_MCU 0 #define CK_SCMI_ICN_SDMMC 1 #define CK_SCMI_ICN_DDR 2 #define CK_SCMI_ICN_DISPLAY 3 #define CK_SCMI_ICN_HSL 4 #define CK_SCMI_ICN_NIC 5 #define CK_SCMI_ICN_VID 6 #define CK_SCMI_FLEXGEN_07 7 #define CK_SCMI_FLEXGEN_08 8 #define CK_SCMI_FLEXGEN_09 9 #define CK_SCMI_FLEXGEN_10 10 #define CK_SCMI_FLEXGEN_11 11 #define CK_SCMI_FLEXGEN_12 12 #define CK_SCMI_FLEXGEN_13 13 #define CK_SCMI_FLEXGEN_14 14 #define CK_SCMI_FLEXGEN_15 15 #define CK_SCMI_FLEXGEN_16 16 #define CK_SCMI_FLEXGEN_17 17 #define CK_SCMI_FLEXGEN_18 18 #define CK_SCMI_FLEXGEN_19 19 #define CK_SCMI_FLEXGEN_20 20 #define CK_SCMI_FLEXGEN_21 21 #define CK_SCMI_FLEXGEN_22 22 #define CK_SCMI_FLEXGEN_23 23 #define CK_SCMI_FLEXGEN_24 24 #define CK_SCMI_FLEXGEN_25 25 #define CK_SCMI_FLEXGEN_26 26 #define CK_SCMI_FLEXGEN_27 27 #define CK_SCMI_FLEXGEN_28 28 #define CK_SCMI_FLEXGEN_29 29 #define CK_SCMI_FLEXGEN_30 30 #define CK_SCMI_FLEXGEN_31 31 #define CK_SCMI_FLEXGEN_32 32 #define CK_SCMI_FLEXGEN_33 33 #define CK_SCMI_FLEXGEN_34 34 #define CK_SCMI_FLEXGEN_35 35 #define CK_SCMI_FLEXGEN_36 36 #define CK_SCMI_FLEXGEN_37 37 #define CK_SCMI_FLEXGEN_38 38 #define CK_SCMI_FLEXGEN_39 39 #define CK_SCMI_FLEXGEN_40 40 #define CK_SCMI_FLEXGEN_41 41 #define CK_SCMI_FLEXGEN_42 42 #define CK_SCMI_FLEXGEN_43 43 #define CK_SCMI_FLEXGEN_44 44 #define CK_SCMI_FLEXGEN_45 45 #define CK_SCMI_FLEXGEN_46 46 #define CK_SCMI_FLEXGEN_47 47 #define CK_SCMI_FLEXGEN_48 48 #define CK_SCMI_FLEXGEN_49 49 #define CK_SCMI_FLEXGEN_50 50 #define CK_SCMI_FLEXGEN_51 51 #define CK_SCMI_FLEXGEN_52 52 #define CK_SCMI_FLEXGEN_53 53 #define CK_SCMI_FLEXGEN_54 54 #define CK_SCMI_FLEXGEN_55 55 #define CK_SCMI_FLEXGEN_56 56 #define CK_SCMI_FLEXGEN_57 57 #define CK_SCMI_FLEXGEN_58 58 #define CK_SCMI_FLEXGEN_59 59 #define CK_SCMI_FLEXGEN_60 60 #define CK_SCMI_FLEXGEN_61 61 #define CK_SCMI_FLEXGEN_62 62 #define CK_SCMI_FLEXGEN_63 63 #define CK_SCMI_ICN_LS_MCU 64 #define CK_SCMI_HSE 65 #define CK_SCMI_LSE 66 #define CK_SCMI_HSI 67 #define CK_SCMI_LSI 68 #define CK_SCMI_MSI 69 #define CK_SCMI_HSE_DIV2 70 #define CK_SCMI_CPU1 71 #define CK_SCMI_SYSCPU1 72 #define CK_SCMI_PLL2 73 #define CK_SCMI_PLL3 74 #define CK_SCMI_RTC 75 #define CK_SCMI_RTCCK 76 #define CK_SCMI_ICN_APB1 77 #define CK_SCMI_ICN_APB2 78 #define CK_SCMI_ICN_APB3 79 #define CK_SCMI_ICN_APB4 80 #define CK_SCMI_ICN_APBDBG 81 #define CK_SCMI_TIMG1 82 #define CK_SCMI_TIMG2 83 #define CK_SCMI_BKPSRAM 84 #define CK_SCMI_BSEC 85 #define CK_SCMI_BUS_ETR 87 #define CK_SCMI_FMC 88 #define CK_SCMI_GPIOA 89 #define CK_SCMI_GPIOB 90 #define CK_SCMI_GPIOC 91 #define CK_SCMI_GPIOD 92 #define CK_SCMI_GPIOE 93 #define CK_SCMI_GPIOF 94 #define CK_SCMI_GPIOG 95 #define CK_SCMI_GPIOH 96 #define CK_SCMI_GPIOI 97 #define CK_SCMI_GPIOJ 98 #define CK_SCMI_GPIOK 99 #define CK_SCMI_GPIOZ 100 #define CK_SCMI_HPDMA1 101 #define CK_SCMI_HPDMA2 102 #define CK_SCMI_HPDMA3 103 #define CK_SCMI_HSEM 104 #define CK_SCMI_IPCC1 105 #define CK_SCMI_IPCC2 106 #define CK_SCMI_LPDMA 107 #define CK_SCMI_RETRAM 108 #define CK_SCMI_SRAM1 109 #define CK_SCMI_SRAM2 110 #define CK_SCMI_LPSRAM1 111 #define CK_SCMI_LPSRAM2 112 #define CK_SCMI_LPSRAM3 113 #define CK_SCMI_VDERAM 114 #define CK_SCMI_SYSRAM 115 #define CK_SCMI_OSPI1 116 #define CK_SCMI_OSPI2 117 #define CK_SCMI_TPIU 118 #define CK_SCMI_SYSDBG 119 #define CK_SCMI_SYSATB 120 #define CK_SCMI_TSDBG 121 #define CK_SCMI_BUS_STM 122 #define CK_SCMI_KER_STM 123 #define CK_SCMI_KER_ETR 124 #endif /* _DT_BINDINGS_CLOCK_ST_STM32MP25_RCC_H_ */ optee_os-4.3.0/core/include/dt-bindings/clock/stm32mp1-clks.h000066400000000000000000000122311464416617300237070ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) STMicroelectronics 2018 - All Rights Reserved * Author: Gabriel Fernandez for STMicroelectronics. */ #ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ #define _DT_BINDINGS_STM32MP1_CLKS_H_ /* OSCILLATOR clocks */ #define CK_HSE 0 #define CK_CSI 1 #define CK_LSI 2 #define CK_LSE 3 #define CK_HSI 4 #define CK_HSE_DIV2 5 /* Bus clocks */ #define TIM2 6 #define TIM3 7 #define TIM4 8 #define TIM5 9 #define TIM6 10 #define TIM7 11 #define TIM12 12 #define TIM13 13 #define TIM14 14 #define LPTIM1 15 #define SPI2 16 #define SPI3 17 #define USART2 18 #define USART3 19 #define UART4 20 #define UART5 21 #define UART7 22 #define UART8 23 #define I2C1 24 #define I2C2 25 #define I2C3 26 #define I2C5 27 #define SPDIF 28 #define CEC 29 #define DAC12 30 #define MDIO 31 #define TIM1 32 #define TIM8 33 #define TIM15 34 #define TIM16 35 #define TIM17 36 #define SPI1 37 #define SPI4 38 #define SPI5 39 #define USART6 40 #define SAI1 41 #define SAI2 42 #define SAI3 43 #define DFSDM 44 #define FDCAN 45 #define LPTIM2 46 #define LPTIM3 47 #define LPTIM4 48 #define LPTIM5 49 #define SAI4 50 #define SYSCFG 51 #define VREF 52 #define TMPSENS 53 #define PMBCTRL 54 #define HDP 55 #define LTDC 56 #define DSI 57 #define IWDG2 58 #define USBPHY 59 #define STGENRO 60 #define SPI6 61 #define I2C4 62 #define I2C6 63 #define USART1 64 #define RTCAPB 65 #define TZC1 66 #define TZPC 67 #define IWDG1 68 #define BSEC 69 #define STGEN 70 #define DMA1 71 #define DMA2 72 #define DMAMUX 73 #define ADC12 74 #define USBO 75 #define SDMMC3 76 #define DCMI 77 #define CRYP2 78 #define HASH2 79 #define RNG2 80 #define CRC2 81 #define HSEM 82 #define IPCC 83 #define GPIOA 84 #define GPIOB 85 #define GPIOC 86 #define GPIOD 87 #define GPIOE 88 #define GPIOF 89 #define GPIOG 90 #define GPIOH 91 #define GPIOI 92 #define GPIOJ 93 #define GPIOK 94 #define GPIOZ 95 #define CRYP1 96 #define HASH1 97 #define RNG1 98 #define BKPSRAM 99 #define MDMA 100 #define GPU 101 #define ETHCK 102 #define ETHTX 103 #define ETHRX 104 #define ETHMAC 105 #define FMC 106 #define QSPI 107 #define SDMMC1 108 #define SDMMC2 109 #define CRC1 110 #define USBH 111 #define ETHSTP 112 #define TZC2 113 /* Kernel clocks */ #define SDMMC1_K 118 #define SDMMC2_K 119 #define SDMMC3_K 120 #define FMC_K 121 #define QSPI_K 122 #define ETHCK_K 123 #define RNG1_K 124 #define RNG2_K 125 #define GPU_K 126 #define USBPHY_K 127 #define STGEN_K 128 #define SPDIF_K 129 #define SPI1_K 130 #define SPI2_K 131 #define SPI3_K 132 #define SPI4_K 133 #define SPI5_K 134 #define SPI6_K 135 #define CEC_K 136 #define I2C1_K 137 #define I2C2_K 138 #define I2C3_K 139 #define I2C4_K 140 #define I2C5_K 141 #define I2C6_K 142 #define LPTIM1_K 143 #define LPTIM2_K 144 #define LPTIM3_K 145 #define LPTIM4_K 146 #define LPTIM5_K 147 #define USART1_K 148 #define USART2_K 149 #define USART3_K 150 #define UART4_K 151 #define UART5_K 152 #define USART6_K 153 #define UART7_K 154 #define UART8_K 155 #define DFSDM_K 156 #define FDCAN_K 157 #define SAI1_K 158 #define SAI2_K 159 #define SAI3_K 160 #define SAI4_K 161 #define ADC12_K 162 #define DSI_K 163 #define DSI_PX 164 #define ADFSDM_K 165 #define USBO_K 166 #define LTDC_PX 167 #define DAC12_K 168 #define ETHPTP_K 169 /* PLL */ #define PLL1 176 #define PLL2 177 #define PLL3 178 #define PLL4 179 /* ODF */ #define PLL1_P 180 #define PLL1_Q 181 #define PLL1_R 182 #define PLL2_P 183 #define PLL2_Q 184 #define PLL2_R 185 #define PLL3_P 186 #define PLL3_Q 187 #define PLL3_R 188 #define PLL4_P 189 #define PLL4_Q 190 #define PLL4_R 191 /* AUX */ #define RTC 192 /* MCLK */ #define CK_PER 193 #define CK_MPU 194 #define CK_AXI 195 #define CK_MCU 196 /* Time base */ #define TIM2_K 197 #define TIM3_K 198 #define TIM4_K 199 #define TIM5_K 200 #define TIM6_K 201 #define TIM7_K 202 #define TIM12_K 203 #define TIM13_K 204 #define TIM14_K 205 #define TIM1_K 206 #define TIM8_K 207 #define TIM15_K 208 #define TIM16_K 209 #define TIM17_K 210 /* MCO clocks */ #define CK_MCO1 211 #define CK_MCO2 212 /* TRACE & DEBUG clocks */ #define CK_DBG 214 #define CK_TRACE 215 /* DDR */ #define DDRC1 220 #define DDRC1LP 221 #define DDRC2 222 #define DDRC2LP 223 #define DDRPHYC 224 #define DDRPHYCLP 225 #define DDRCAPB 226 #define DDRCAPBLP 227 #define AXIDCG 228 #define DDRPHYCAPB 229 #define DDRPHYCAPBLP 230 #define DDRPERFM 231 #define STM32MP1_LAST_CLK 232 #define LTDC_K LTDC_PX #define ETHMAC_K ETHCK_K /* SCMI clock identifiers */ #define CK_SCMI_HSE 0 #define CK_SCMI_HSI 1 #define CK_SCMI_CSI 2 #define CK_SCMI_LSE 3 #define CK_SCMI_LSI 4 #define CK_SCMI_PLL2_Q 5 #define CK_SCMI_PLL2_R 6 #define CK_SCMI_MPU 7 #define CK_SCMI_AXI 8 #define CK_SCMI_BSEC 9 #define CK_SCMI_CRYP1 10 #define CK_SCMI_GPIOZ 11 #define CK_SCMI_HASH1 12 #define CK_SCMI_I2C4 13 #define CK_SCMI_I2C6 14 #define CK_SCMI_IWDG1 15 #define CK_SCMI_RNG1 16 #define CK_SCMI_RTC 17 #define CK_SCMI_RTCAPB 18 #define CK_SCMI_SPI6 19 #define CK_SCMI_USART1 20 #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ optee_os-4.3.0/core/include/dt-bindings/clock/stm32mp13-clks.h000066400000000000000000000107231464416617300237760ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved * Author: Gabriel Fernandez */ #ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ #define _DT_BINDINGS_STM32MP13_CLKS_H_ /* OSCILLATOR clocks */ #define CK_HSE 0 #define CK_CSI 1 #define CK_LSI 2 #define CK_LSE 3 #define CK_HSI 4 #define CK_HSE_DIV2 5 /* PLL */ #define PLL1 6 #define PLL2 7 #define PLL3 8 #define PLL4 9 /* ODF */ #define PLL1_P 10 #define PLL1_Q 11 #define PLL1_R 12 #define PLL2_P 13 #define PLL2_Q 14 #define PLL2_R 15 #define PLL3_P 16 #define PLL3_Q 17 #define PLL3_R 18 #define PLL4_P 19 #define PLL4_Q 20 #define PLL4_R 21 /* SYSTEM CLOCK */ #define CK_PER 22 #define CK_MPU 23 #define CK_AXI 24 #define CK_MLAHB 25 #define PCLK1 26 #define PCLK2 27 #define PCLK3 28 #define PCLK4 29 #define PCLK5 30 #define PCLK6 31 /* BASE TIMER */ #define CK_TIMG1 32 #define CK_TIMG2 33 #define CK_TIMG3 34 /* AUX */ #define RTC 35 /* TRACE & DEBUG clocks */ #define CK_DBG 36 #define CK_TRACE 37 /* MCO clocks */ #define CK_MCO1 38 #define CK_MCO2 39 /* IP clocks */ #define SYSCFG 40 #define VREF 41 #define TMPSENS 42 #define PMBCTRL 43 #define HDP 44 #define IWDG2 45 #define STGENRO 46 #define USART1 47 #define RTCAPB 48 #define TZC 49 #define TZPC 50 #define IWDG1 51 #define BSEC 52 #define DMA1 53 #define DMA2 54 #define DMAMUX1 55 #define DMAMUX2 56 #define GPIOA 57 #define GPIOB 58 #define GPIOC 59 #define GPIOD 60 #define GPIOE 61 #define GPIOF 62 #define GPIOG 63 #define GPIOH 64 #define GPIOI 65 #define CRYP1 66 #define HASH1 67 #define BKPSRAM 68 #define MDMA 69 #define CRC1 70 #define USBH 71 #define DMA3 72 #define TSC 73 #define PKA 74 #define AXIMC 75 #define MCE 76 #define ETH1TX 77 #define ETH2TX 78 #define ETH1RX 79 #define ETH2RX 80 #define ETH1MAC 81 #define ETH2MAC 82 #define ETH1STP 83 #define ETH2STP 84 /* IP clocks with parents */ #define SDMMC1_K 85 #define SDMMC2_K 86 #define ADC1_K 87 #define ADC2_K 88 #define FMC_K 89 #define QSPI_K 90 #define RNG1_K 91 #define USBPHY_K 92 #define STGEN_K 93 #define SPDIF_K 94 #define SPI1_K 95 #define SPI2_K 96 #define SPI3_K 97 #define SPI4_K 98 #define SPI5_K 99 #define I2C1_K 100 #define I2C2_K 101 #define I2C3_K 102 #define I2C4_K 103 #define I2C5_K 104 #define TIM2_K 105 #define TIM3_K 106 #define TIM4_K 107 #define TIM5_K 108 #define TIM6_K 109 #define TIM7_K 110 #define TIM12_K 111 #define TIM13_K 112 #define TIM14_K 113 #define TIM1_K 114 #define TIM8_K 115 #define TIM15_K 116 #define TIM16_K 117 #define TIM17_K 118 #define LPTIM1_K 119 #define LPTIM2_K 120 #define LPTIM3_K 121 #define LPTIM4_K 122 #define LPTIM5_K 123 #define USART1_K 124 #define USART2_K 125 #define USART3_K 126 #define UART4_K 127 #define UART5_K 128 #define USART6_K 129 #define UART7_K 130 #define UART8_K 131 #define DFSDM_K 132 #define FDCAN_K 133 #define SAI1_K 134 #define SAI2_K 135 #define ADFSDM_K 136 #define USBO_K 137 #define LTDC_PX 138 #define ETH1CK_K 139 #define ETH1PTP_K 140 #define ETH2CK_K 141 #define ETH2PTP_K 142 #define DCMIPP_K 143 #define SAES_K 144 #define DTS_K 145 /* DDR */ #define DDRC1 146 #define DDRC1LP 147 #define DDRC2 148 #define DDRC2LP 149 #define DDRPHYC 150 #define DDRPHYCLP 151 #define DDRCAPB 152 #define DDRCAPBLP 153 #define AXIDCG 154 #define DDRPHYCAPB 155 #define DDRPHYCAPBLP 156 #define DDRPERFM 157 #define ADC1 158 #define ADC2 159 #define SAI1 160 #define SAI2 161 #define SPI1 162 #define SPI2 163 #define SPI3 164 #define SPI4 165 #define SPI5 166 #define STM32MP1_LAST_CLK 167 /* SCMI clock identifiers */ #define CK_SCMI_HSE 0 #define CK_SCMI_HSI 1 #define CK_SCMI_CSI 2 #define CK_SCMI_LSE 3 #define CK_SCMI_LSI 4 #define CK_SCMI_HSE_DIV2 5 #define CK_SCMI_PLL2_Q 6 #define CK_SCMI_PLL2_R 7 #define CK_SCMI_PLL3_P 8 #define CK_SCMI_PLL3_Q 9 #define CK_SCMI_PLL3_R 10 #define CK_SCMI_PLL4_P 11 #define CK_SCMI_PLL4_Q 12 #define CK_SCMI_PLL4_R 13 #define CK_SCMI_MPU 14 #define CK_SCMI_AXI 15 #define CK_SCMI_MLAHB 16 #define CK_SCMI_CKPER 17 #define CK_SCMI_PCLK1 18 #define CK_SCMI_PCLK2 19 #define CK_SCMI_PCLK3 20 #define CK_SCMI_PCLK4 21 #define CK_SCMI_PCLK5 22 #define CK_SCMI_PCLK6 23 #define CK_SCMI_CKTIMG1 24 #define CK_SCMI_CKTIMG2 25 #define CK_SCMI_CKTIMG3 26 #define CK_SCMI_RTC 27 #define CK_SCMI_RTCAPB 28 #define CK_SCMI_BSEC 29 #endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ optee_os-4.3.0/core/include/dt-bindings/clock/stm32mp13-clksrc.h000066400000000000000000000272451464416617300243320ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved * Author: Gabriel Fernandez */ #ifndef _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ #define _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ #define CMD_DIV 0 #define CMD_MUX 1 #define CMD_CLK 2 #define CMD_SHIFT 26 #define CMD_MASK 0xFC000000 #define CMD_DATA_MASK 0x03FFFFFF #define DIV_ID_SHIFT 8 #define DIV_ID_MASK 0x0000FF00 #define DIV_DIVN_SHIFT 0 #define DIV_DIVN_MASK 0x000000FF #define MUX_ID_SHIFT 4 #define MUX_ID_MASK 0x00000FF0 #define MUX_SEL_SHIFT 0 #define MUX_SEL_MASK 0x0000000F #define CLK_ID_MASK GENMASK_32(19, 11) #define CLK_ID_SHIFT 11 #define CLK_ON_MASK 0x00000400 #define CLK_ON_SHIFT 10 #define CLK_DIV_MASK GENMASK_32(9, 4) #define CLK_DIV_SHIFT 4 #define CLK_SEL_MASK GENMASK_32(3, 0) #define CLK_SEL_SHIFT 0 #define DIV_PLL1DIVP 0 #define DIV_PLL2DIVP 1 #define DIV_PLL2DIVQ 2 #define DIV_PLL2DIVR 3 #define DIV_PLL3DIVP 4 #define DIV_PLL3DIVQ 5 #define DIV_PLL3DIVR 6 #define DIV_PLL4DIVP 7 #define DIV_PLL4DIVQ 8 #define DIV_PLL4DIVR 9 #define DIV_MPU 10 #define DIV_AXI 11 #define DIV_MLAHB 12 #define DIV_APB1 13 #define DIV_APB2 14 #define DIV_APB3 15 #define DIV_APB4 16 #define DIV_APB5 17 #define DIV_APB6 18 #define DIV_RTC 19 #define DIV_MCO1 20 #define DIV_MCO2 21 #define DIV_HSI 22 #define DIV_TRACE 23 #define DIV_ETH1PTP 24 #define DIV_ETH2PTP 25 #define DIV_NB 26 #define DIV(div_id, div) ((CMD_DIV << CMD_SHIFT) |\ ((div_id) << DIV_ID_SHIFT) |\ (div)) #define CLKSRC(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\ ((mux_id) << MUX_ID_SHIFT) |\ (sel)) /* CLK output is enable */ #define CLK_SRC(clk_id, sel) ((CMD_CLK << CMD_SHIFT) |\ ((clk_id) << CLK_ID_SHIFT) |\ (sel) | CLK_ON_MASK) #define CLK_DISABLED(clk_id) ((CMD_CLK << CMD_SHIFT) |\ ((clk_id) << CLK_ID_SHIFT)) #define MUX_MPU 0 #define MUX_AXI 1 #define MUX_MLAHB 2 #define MUX_PLL12 3 #define MUX_PLL3 4 #define MUX_PLL4 5 #define MUX_RTC 6 #define MUX_MCO1 7 #define MUX_MCO2 8 #define MUX_CKPER 9 #define MUX_ADC1 10 #define MUX_ADC2 11 #define MUX_DCMIPP 12 #define MUX_ETH1 13 #define MUX_ETH2 14 #define MUX_FDCAN 15 #define MUX_FMC 16 #define MUX_I2C12 17 #define MUX_I2C3 18 #define MUX_I2C4 19 #define MUX_I2C5 20 #define MUX_LPTIM1 21 #define MUX_LPTIM2 22 #define MUX_LPTIM3 23 #define MUX_LPTIM45 24 #define MUX_QSPI 25 #define MUX_RNG1 26 #define MUX_SAES 27 #define MUX_SAI1 28 #define MUX_SAI2 29 #define MUX_SDMMC1 30 #define MUX_SDMMC2 31 #define MUX_SPDIF 32 #define MUX_SPI1 33 #define MUX_SPI23 34 #define MUX_SPI4 35 #define MUX_SPI5 36 #define MUX_STGEN 37 #define MUX_UART1 38 #define MUX_UART2 39 #define MUX_UART35 40 #define MUX_UART4 41 #define MUX_UART6 42 #define MUX_UART78 43 #define MUX_USBO 44 #define MUX_USBPHY 45 #define MUX_NB 46 /* ADC MUX is the first Kernel MUX */ #define MUX_KERNEL_BEGIN MUX_ADC1 #define CLK_MPU_HSI CLKSRC(MUX_MPU, 0) #define CLK_MPU_HSE CLKSRC(MUX_MPU, 1) #define CLK_MPU_PLL1P CLKSRC(MUX_MPU, 2) #define CLK_MPU_PLL1P_DIV CLKSRC(MUX_MPU, 3) #define CLK_AXI_HSI CLKSRC(MUX_AXI, 0) #define CLK_AXI_HSE CLKSRC(MUX_AXI, 1) #define CLK_AXI_PLL2P CLKSRC(MUX_AXI, 2) #define CLK_MLAHBS_HSI CLKSRC(MUX_MLAHB, 0) #define CLK_MLAHBS_HSE CLKSRC(MUX_MLAHB, 1) #define CLK_MLAHBS_CSI CLKSRC(MUX_MLAHB, 2) #define CLK_MLAHBS_PLL3 CLKSRC(MUX_MLAHB, 3) #define CLK_PLL12_HSI CLKSRC(MUX_PLL12, 0) #define CLK_PLL12_HSE CLKSRC(MUX_PLL12, 1) #define CLK_PLL3_HSI CLKSRC(MUX_PLL3, 0) #define CLK_PLL3_HSE CLKSRC(MUX_PLL3, 1) #define CLK_PLL3_CSI CLKSRC(MUX_PLL3, 2) #define CLK_PLL4_HSI CLKSRC(MUX_PLL4, 0) #define CLK_PLL4_HSE CLKSRC(MUX_PLL4, 1) #define CLK_PLL4_CSI CLKSRC(MUX_PLL4, 2) #define CLK_RTC_DISABLED CLKSRC(RTC, 0) #define CLK_RTC_LSE CLKSRC(RTC, 1) #define CLK_RTC_LSI CLKSRC(RTC, 2) #define CLK_RTC_HSE CLKSRC(RTC, 3) #define CLK_MCO1_HSI CLK_SRC(CK_MCO1, 0) #define CLK_MCO1_HSE CLK_SRC(CK_MCO1, 1) #define CLK_MCO1_CSI CLK_SRC(CK_MCO1, 2) #define CLK_MCO1_LSI CLK_SRC(CK_MCO1, 3) #define CLK_MCO1_LSE CLK_SRC(CK_MCO1, 4) #define CLK_MCO1_DISABLED CLK_DISABLED(CK_MCO1) #define CLK_MCO2_MPU CLK_SRC(CK_MCO2, 0) #define CLK_MCO2_AXI CLK_SRC(CK_MCO2, 1) #define CLK_MCO2_MLAHB CLK_SRC(CK_MCO2, 2) #define CLK_MCO2_PLL4 CLK_SRC(CK_MCO2, 3) #define CLK_MCO2_HSE CLK_SRC(CK_MCO2, 4) #define CLK_MCO2_HSI CLK_SRC(CK_MCO2, 5) #define CLK_MCO2_DISABLED CLK_DISABLED(CK_MCO2) #define CLK_CKPER_HSI CLKSRC(MUX_CKPER, 0) #define CLK_CKPER_CSI CLKSRC(MUX_CKPER, 1) #define CLK_CKPER_HSE CLKSRC(MUX_CKPER, 2) #define CLK_CKPER_DISABLED CLKSRC(MUX_CKPER, 3) #define CLK_I2C12_PCLK1 CLKSRC(MUX_I2C12, 0) #define CLK_I2C12_PLL4R CLKSRC(MUX_I2C12, 1) #define CLK_I2C12_HSI CLKSRC(MUX_I2C12, 2) #define CLK_I2C12_CSI CLKSRC(MUX_I2C12, 3) #define CLK_I2C3_PCLK6 CLKSRC(MUX_I2C3, 0) #define CLK_I2C3_PLL4R CLKSRC(MUX_I2C3, 1) #define CLK_I2C3_HSI CLKSRC(MUX_I2C3, 2) #define CLK_I2C3_CSI CLKSRC(MUX_I2C3, 3) #define CLK_I2C4_PCLK6 CLKSRC(MUX_I2C4, 0) #define CLK_I2C4_PLL4R CLKSRC(MUX_I2C4, 1) #define CLK_I2C4_HSI CLKSRC(MUX_I2C4, 2) #define CLK_I2C4_CSI CLKSRC(MUX_I2C4, 3) #define CLK_I2C5_PCLK6 CLKSRC(MUX_I2C5, 0) #define CLK_I2C5_PLL4R CLKSRC(MUX_I2C5, 1) #define CLK_I2C5_HSI CLKSRC(MUX_I2C5, 2) #define CLK_I2C5_CSI CLKSRC(MUX_I2C5, 3) #define CLK_SPI1_PLL4P CLKSRC(MUX_SPI1, 0) #define CLK_SPI1_PLL3Q CLKSRC(MUX_SPI1, 1) #define CLK_SPI1_I2SCKIN CLKSRC(MUX_SPI1, 2) #define CLK_SPI1_CKPER CLKSRC(MUX_SPI1, 3) #define CLK_SPI1_PLL3R CLKSRC(MUX_SPI1, 4) #define CLK_SPI23_PLL4P CLKSRC(MUX_SPI23, 0) #define CLK_SPI23_PLL3Q CLKSRC(MUX_SPI23, 1) #define CLK_SPI23_I2SCKIN CLKSRC(MUX_SPI23, 2) #define CLK_SPI23_CKPER CLKSRC(MUX_SPI23, 3) #define CLK_SPI23_PLL3R CLKSRC(MUX_SPI23, 4) #define CLK_SPI4_PCLK6 CLKSRC(MUX_SPI4, 0) #define CLK_SPI4_PLL4Q CLKSRC(MUX_SPI4, 1) #define CLK_SPI4_HSI CLKSRC(MUX_SPI4, 2) #define CLK_SPI4_CSI CLKSRC(MUX_SPI4, 3) #define CLK_SPI4_HSE CLKSRC(MUX_SPI4, 4) #define CLK_SPI4_I2SCKIN CLKSRC(MUX_SPI4, 5) #define CLK_SPI5_PCLK6 CLKSRC(MUX_SPI5, 0) #define CLK_SPI5_PLL4Q CLKSRC(MUX_SPI5, 1) #define CLK_SPI5_HSI CLKSRC(MUX_SPI5, 2) #define CLK_SPI5_CSI CLKSRC(MUX_SPI5, 3) #define CLK_SPI5_HSE CLKSRC(MUX_SPI5, 4) #define CLK_UART1_PCLK6 CLKSRC(MUX_UART1, 0) #define CLK_UART1_PLL3Q CLKSRC(MUX_UART1, 1) #define CLK_UART1_HSI CLKSRC(MUX_UART1, 2) #define CLK_UART1_CSI CLKSRC(MUX_UART1, 3) #define CLK_UART1_PLL4Q CLKSRC(MUX_UART1, 4) #define CLK_UART1_HSE CLKSRC(MUX_UART1, 5) #define CLK_UART2_PCLK6 CLKSRC(MUX_UART2, 0) #define CLK_UART2_PLL3Q CLKSRC(MUX_UART2, 1) #define CLK_UART2_HSI CLKSRC(MUX_UART2, 2) #define CLK_UART2_CSI CLKSRC(MUX_UART2, 3) #define CLK_UART2_PLL4Q CLKSRC(MUX_UART2, 4) #define CLK_UART2_HSE CLKSRC(MUX_UART2, 5) #define CLK_UART35_PCLK1 CLKSRC(MUX_UART35, 0) #define CLK_UART35_PLL4Q CLKSRC(MUX_UART35, 1) #define CLK_UART35_HSI CLKSRC(MUX_UART35, 2) #define CLK_UART35_CSI CLKSRC(MUX_UART35, 3) #define CLK_UART35_HSE CLKSRC(MUX_UART35, 4) #define CLK_UART4_PCLK1 CLKSRC(MUX_UART4, 0) #define CLK_UART4_PLL4Q CLKSRC(MUX_UART4, 1) #define CLK_UART4_HSI CLKSRC(MUX_UART4, 2) #define CLK_UART4_CSI CLKSRC(MUX_UART4, 3) #define CLK_UART4_HSE CLKSRC(MUX_UART4, 4) #define CLK_UART6_PCLK2 CLKSRC(MUX_UART6, 0) #define CLK_UART6_PLL4Q CLKSRC(MUX_UART6, 1) #define CLK_UART6_HSI CLKSRC(MUX_UART6, 2) #define CLK_UART6_CSI CLKSRC(MUX_UART6, 3) #define CLK_UART6_HSE CLKSRC(MUX_UART6, 4) #define CLK_UART78_PCLK1 CLKSRC(MUX_UART78, 0) #define CLK_UART78_PLL4Q CLKSRC(MUX_UART78, 1) #define CLK_UART78_HSI CLKSRC(MUX_UART78, 2) #define CLK_UART78_CSI CLKSRC(MUX_UART78, 3) #define CLK_UART78_HSE CLKSRC(MUX_UART78, 4) #define CLK_LPTIM1_PCLK1 CLKSRC(MUX_LPTIM1, 0) #define CLK_LPTIM1_PLL4P CLKSRC(MUX_LPTIM1, 1) #define CLK_LPTIM1_PLL3Q CLKSRC(MUX_LPTIM1, 2) #define CLK_LPTIM1_LSE CLKSRC(MUX_LPTIM1, 3) #define CLK_LPTIM1_LSI CLKSRC(MUX_LPTIM1, 4) #define CLK_LPTIM1_CKPER CLKSRC(MUX_LPTIM1, 5) #define CLK_LPTIM2_PCLK3 CLKSRC(MUX_LPTIM2, 0) #define CLK_LPTIM2_PLL4Q CLKSRC(MUX_LPTIM2, 1) #define CLK_LPTIM2_CKPER CLKSRC(MUX_LPTIM2, 2) #define CLK_LPTIM2_LSE CLKSRC(MUX_LPTIM2, 3) #define CLK_LPTIM2_LSI CLKSRC(MUX_LPTIM2, 4) #define CLK_LPTIM3_PCLK3 CLKSRC(MUX_LPTIM3, 0) #define CLK_LPTIM3_PLL4Q CLKSRC(MUX_LPTIM3, 1) #define CLK_LPTIM3_CKPER CLKSRC(MUX_LPTIM3, 2) #define CLK_LPTIM3_LSE CLKSRC(MUX_LPTIM3, 3) #define CLK_LPTIM3_LSI CLKSRC(MUX_LPTIM3, 4) #define CLK_LPTIM45_PCLK3 CLKSRC(MUX_LPTIM45, 0) #define CLK_LPTIM45_PLL4P CLKSRC(MUX_LPTIM45, 1) #define CLK_LPTIM45_PLL3Q CLKSRC(MUX_LPTIM45, 2) #define CLK_LPTIM45_LSE CLKSRC(MUX_LPTIM45, 3) #define CLK_LPTIM45_LSI CLKSRC(MUX_LPTIM45, 4) #define CLK_LPTIM45_CKPER CLKSRC(MUX_LPTIM45, 5) #define CLK_SAI1_PLL4Q CLKSRC(MUX_SAI1, 0) #define CLK_SAI1_PLL3Q CLKSRC(MUX_SAI1, 1) #define CLK_SAI1_I2SCKIN CLKSRC(MUX_SAI1, 2) #define CLK_SAI1_CKPER CLKSRC(MUX_SAI1, 3) #define CLK_SAI1_PLL3R CLKSRC(MUX_SAI1, 4) #define CLK_SAI2_PLL4Q CLKSRC(MUX_SAI2, 0) #define CLK_SAI2_PLL3Q CLKSRC(MUX_SAI2, 1) #define CLK_SAI2_I2SCKIN CLKSRC(MUX_SAI2, 2) #define CLK_SAI2_CKPER CLKSRC(MUX_SAI2, 3) #define CLK_SAI2_SPDIF CLKSRC(MUX_SAI2, 4) #define CLK_SAI2_PLL3R CLKSRC(MUX_SAI2, 5) #define CLK_FDCAN_HSE CLKSRC(MUX_FDCAN, 0) #define CLK_FDCAN_PLL3Q CLKSRC(MUX_FDCAN, 1) #define CLK_FDCAN_PLL4Q CLKSRC(MUX_FDCAN, 2) #define CLK_FDCAN_PLL4R CLKSRC(MUX_FDCAN, 3) #define CLK_SPDIF_PLL4P CLKSRC(MUX_SPDIF, 0) #define CLK_SPDIF_PLL3Q CLKSRC(MUX_SPDIF, 1) #define CLK_SPDIF_HSI CLKSRC(MUX_SPDIF, 2) #define CLK_ADC1_PLL4R CLKSRC(MUX_ADC1, 0) #define CLK_ADC1_CKPER CLKSRC(MUX_ADC1, 1) #define CLK_ADC1_PLL3Q CLKSRC(MUX_ADC1, 2) #define CLK_ADC2_PLL4R CLKSRC(MUX_ADC2, 0) #define CLK_ADC2_CKPER CLKSRC(MUX_ADC2, 1) #define CLK_ADC2_PLL3Q CLKSRC(MUX_ADC2, 2) #define CLK_SDMMC1_HCLK6 CLKSRC(MUX_SDMMC1, 0) #define CLK_SDMMC1_PLL3R CLKSRC(MUX_SDMMC1, 1) #define CLK_SDMMC1_PLL4P CLKSRC(MUX_SDMMC1, 2) #define CLK_SDMMC1_HSI CLKSRC(MUX_SDMMC1, 3) #define CLK_SDMMC2_HCLK6 CLKSRC(MUX_SDMMC2, 0) #define CLK_SDMMC2_PLL3R CLKSRC(MUX_SDMMC2, 1) #define CLK_SDMMC2_PLL4P CLKSRC(MUX_SDMMC2, 2) #define CLK_SDMMC2_HSI CLKSRC(MUX_SDMMC2, 3) #define CLK_ETH1_PLL4P CLKSRC(MUX_ETH1, 0) #define CLK_ETH1_PLL3Q CLKSRC(MUX_ETH1, 1) #define CLK_ETH2_PLL4P CLKSRC(MUX_ETH2, 0) #define CLK_ETH2_PLL3Q CLKSRC(MUX_ETH2, 1) #define CLK_USBPHY_HSE CLKSRC(MUX_USBPHY, 0) #define CLK_USBPHY_PLL4R CLKSRC(MUX_USBPHY, 1) #define CLK_USBPHY_HSE_DIV2 CLKSRC(MUX_USBPHY, 2) #define CLK_USBO_PLL4R CLKSRC(MUX_USBO, 0) #define CLK_USBO_USBPHY CLKSRC(MUX_USBO, 1) #define CLK_QSPI_ACLK CLKSRC(MUX_QSPI, 0) #define CLK_QSPI_PLL3R CLKSRC(MUX_QSPI, 1) #define CLK_QSPI_PLL4P CLKSRC(MUX_QSPI, 2) #define CLK_QSPI_CKPER CLKSRC(MUX_QSPI, 3) #define CLK_FMC_ACLK CLKSRC(MUX_FMC, 0) #define CLK_FMC_PLL3R CLKSRC(MUX_FMC, 1) #define CLK_FMC_PLL4P CLKSRC(MUX_FMC, 2) #define CLK_FMC_CKPER CLKSRC(MUX_FMC, 3) #define CLK_RNG1_CSI CLKSRC(MUX_RNG1, 0) #define CLK_RNG1_PLL4R CLKSRC(MUX_RNG1, 1) #define CLK_RNG1_LSE CLKSRC(MUX_RNG1, 2) #define CLK_RNG1_LSI CLKSRC(MUX_RNG1, 3) #define CLK_STGEN_HSI CLKSRC(MUX_STGEN, 0) #define CLK_STGEN_HSE CLKSRC(MUX_STGEN, 1) #define CLK_DCMIPP_ACLK CLKSRC(MUX_DCMIPP, 0) #define CLK_DCMIPP_PLL2Q CLKSRC(MUX_DCMIPP, 1) #define CLK_DCMIPP_PLL4P CLKSRC(MUX_DCMIPP, 2) #define CLK_DCMIPP_CKPER CLKSRC(MUX_DCMIPP, 3) #define CLK_SAES_AXI CLKSRC(MUX_SAES, 0) #define CLK_SAES_CKPER CLKSRC(MUX_SAES, 1) #define CLK_SAES_PLL4R CLKSRC(MUX_SAES, 2) #define CLK_SAES_LSI CLKSRC(MUX_SAES, 3) /* define for st,pll /csg */ #define SSCG_MODE_CENTER_SPREAD 0 #define SSCG_MODE_DOWN_SPREAD 1 /* define for st,drive */ #define LSEDRV_LOWEST 0 #define LSEDRV_MEDIUM_LOW 1 #define LSEDRV_MEDIUM_HIGH 2 #define LSEDRV_HIGHEST 3 #endif /* _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ */ optee_os-4.3.0/core/include/dt-bindings/clock/stm32mp25-clksrc.h000066400000000000000000000144421464416617300243300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) STMicroelectronics 2024 - All Rights Reserved */ #ifndef _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_ #define _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_ #define CMD_DIV 0 #define CMD_MUX 1 #define CMD_CLK 2 #define CMD_FLEXGEN 3 #define CMD_OBS 4 #define CMD_ADDR_BIT 0x80000000 #define CMD_SHIFT 26 #define CMD_MASK 0xFC000000 #define CMD_DATA_MASK 0x03FFFFFF #define DIV_ID_SHIFT 8 #define DIV_ID_MASK 0x0000FF00 #define DIV_DIVN_SHIFT 0 #define DIV_DIVN_MASK 0x000000FF #define MUX_ID_SHIFT 4 #define MUX_ID_MASK 0x00000FF0 #define MUX_SEL_SHIFT 0 #define MUX_SEL_MASK 0x0000000F /* CLK define */ #define CLK_ON_MASK BIT(21) #define CLK_ON_SHIFT 21 #define CLK_ID_MASK GENMASK_32(20, 12) #define CLK_ID_SHIFT 12 #define CLK_NO_DIV_MASK 0x0000080 #define CLK_DIV_MASK GENMASK_32(10, 5) #define CLK_DIV_SHIFT 5 #define CLK_NO_SEL_MASK 0x00000010 #define CLK_SEL_MASK GENMASK_32(3, 0) #define CLK_SEL_SHIFT 0 #define CLK_CFG(clk_id, sel, div, state) ((CMD_CLK << CMD_SHIFT) |\ ((state) << CLK_ON_SHIFT) |\ ((clk_id) << CLK_ID_SHIFT) |\ ((div) << CLK_DIV_SHIFT) |\ ((sel) << CLK_SEL_SHIFT)) #define CLK_OFF 0 #define CLK_ON 1 #define CLK_NODIV 0x00000040 #define CLK_NOMUX 0x00000010 /* Flexgen define */ #define FLEX_ID_SHIFT 13 #define FLEX_SEL_SHIFT 9 #define FLEX_PDIV_SHIFT 6 #define FLEX_FDIV_SHIFT 0 #define FLEX_ID_MASK GENMASK_32(18, 13) #define FLEX_SEL_MASK GENMASK_32(12, 9) #define FLEX_PDIV_MASK GENMASK_32(8, 6) #define FLEX_FDIV_MASK GENMASK_32(5, 0) #define DIV_CFG(div_id, div) ((CMD_DIV << CMD_SHIFT) |\ ((div_id) << DIV_ID_SHIFT |\ (div))) #define MUX_CFG(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\ ((mux_id) << MUX_ID_SHIFT |\ (sel))) #define CLK_ADDR_SHIFT 16 #define CLK_ADDR_MASK 0x7FFF0000 #define CLK_ADDR_VAL_MASK 0xFFFF #define DIV_LSMCU 0 #define DIV_APB1 1 #define DIV_APB2 2 #define DIV_APB3 3 #define DIV_APB4 4 #define DIV_APBDBG 5 #define DIV_RTC 6 #define DIV_NB 7 #define MUX_MUXSEL0 0 #define MUX_MUXSEL1 1 #define MUX_MUXSEL2 2 #define MUX_MUXSEL3 3 #define MUX_MUXSEL4 4 #define MUX_MUXSEL5 5 #define MUX_MUXSEL6 6 #define MUX_MUXSEL7 7 #define MUX_XBARSEL 8 #define MUX_RTC 9 #define MUX_MCO1 10 #define MUX_MCO2 11 #define MUX_ADC12 12 #define MUX_ADC3 13 #define MUX_USB2PHY1 14 #define MUX_USB2PHY2 15 #define MUX_USB3PCIEPHY 16 #define MUX_DSIBLANE 17 #define MUX_DSIPHY 18 #define MUX_LVDSPHY 19 #define MUX_DTS 20 #define MUX_D3PER 21 #define MUX_NB 22 #define MUXSEL_HSI 0 #define MUXSEL_HSE 1 #define MUXSEL_MSI 2 /* KERNEL source clocks */ #define MUX_RTC_DISABLED 0x0 #define MUX_RTC_LSE 0x1 #define MUX_RTC_LSI 0x2 #define MUX_RTC_HSE 0x3 #define MUX_MCO1_FLEX61 0x0 #define MUX_MCO1_OBSER0 0x1 #define MUX_MCO2_FLEX62 0x0 #define MUX_MCO2_OBSER1 0x1 #define MUX_ADC12_FLEX46 0x0 #define MUX_ADC12_LSMCU 0x1 #define MUX_ADC3_FLEX47 0x0 #define MUX_ADC3_LSMCU 0x1 #define MUX_ADC3_FLEX46 0x2 #define MUX_USB2PHY1_FLEX57 0x0 #define MUX_USB2PHY1_HSE 0x1 #define MUX_USB2PHY2_FLEX58 0x0 #define MUX_USB2PHY2_HSE 0x1 #define MUX_USB3PCIEPHY_FLEX34 0x0 #define MUX_USB3PCIEPHY_HSE 0x1 #define MUX_DSIBLANE_DSIPHY 0x0 #define MUX_DSIBLANE_FLEX27 0x1 #define MUX_DSIPHY_FLEX28 0x0 #define MUX_DSIPHY_HSE 0x1 #define MUX_LVDSPHY_FLEX32 0x0 #define MUX_LVDSPHY_HSE 0x1 #define MUX_DTS_HSI 0x0 #define MUX_DTS_HSE 0x1 #define MUX_DTS_MSI 0x2 #define MUX_D3PER_MSI 0x0 #define MUX_D3PER_LSI 0x1 #define MUX_D3PER_LSE 0x2 /* PLLs source clocks */ #define PLL_SRC_HSI 0x0 #define PLL_SRC_HSE 0x1 #define PLL_SRC_MSI 0x2 #define PLL_SRC_DISABLED 0x3 /* XBAR source clocks */ #define XBAR_SRC_PLL4 0x0 #define XBAR_SRC_PLL5 0x1 #define XBAR_SRC_PLL6 0x2 #define XBAR_SRC_PLL7 0x3 #define XBAR_SRC_PLL8 0x4 #define XBAR_SRC_HSI 0x5 #define XBAR_SRC_HSE 0x6 #define XBAR_SRC_MSI 0x7 #define XBAR_SRC_HSI_KER 0x8 #define XBAR_SRC_HSE_KER 0x9 #define XBAR_SRC_MSI_KER 0xA #define XBAR_SRC_SPDIF_SYMB 0xB #define XBAR_SRC_I2S 0xC #define XBAR_SRC_LSI 0xD #define XBAR_SRC_LSE 0xE /* * Configure a XBAR channel with its clock source * channel_nb: XBAR channel number from 0 to 63 * channel_src: one of the 15 previous XBAR source clocks defines * channel_prediv: value of the PREDIV in channel RCC_PREDIVxCFGR register * can be either 1, 2, 4 or 1024 * channel_findiv: value of the FINDIV in channel RCC_FINDIVxCFGR register * from 1 to 64 */ #define FLEXGEN_CFG(ch, sel, pdiv, fdiv) ((CMD_FLEXGEN << CMD_SHIFT) |\ ((ch) << FLEX_ID_SHIFT) |\ ((sel) << FLEX_SEL_SHIFT) |\ ((pdiv) << FLEX_PDIV_SHIFT) |\ ((fdiv) << FLEX_FDIV_SHIFT)) /* Register addresses of MCO1 & MCO2 */ #define MCO1 0x494 #define MCO2 0x498 #define MCO_OFF 0 #define MCO_ON 1 #define MCO_STATUS_SHIFT 8 #define MCO_CFG(addr, sel, status) (CMD_ADDR_BIT |\ ((addr) << CLK_ADDR_SHIFT) |\ ((status) << MCO_STATUS_SHIFT) |\ (sel)) #define OBS_ID_SHIFT 14 #define OBS_STATUS_SHIFT 13 #define OBS_INTEXT_SHIFT 12 #define OBS_DIV_SHIFT 9 #define OBS_INV_SHIFT 8 #define OBS_SEL_SHIFT 0 #define OBS_ID_MASK GENMASK_32(14, 14) #define OBS_STATUS_MASK GENMASK_32(13, 13) #define OBS_INTEXT_MASK GENMASK_32(12, 12) #define OBS_DIV_MASK GENMASK_32(11, 9) #define OBS_INV_MASK BIT(8) #define OBS_SEL_MASK GENMASK_32(7, 0) #define OBS_CFG(id, status, int_ext, div, inv, sel)\ ((CMD_OBS << CMD_SHIFT) |\ ((id) << OBS_ID_SHIFT) |\ ((status) << OBS_STATUS_SHIFT) |\ ((int_ext) << OBS_INTEXT_SHIFT) |\ ((div) << OBS_DIV_SHIFT) |\ ((inv) << OBS_INV_SHIFT) |\ ((sel) << OBS_SEL_SHIFT)) #define OBS0 0 #define OBS1 1 #define OBS_OFF 0 #define OBS_ON 1 #define OBS_INT 0 #define OBS_EXT 1 #define OBS_DIV1 0 #define OBS_DIV2 1 #define OBS_DIV4 2 #define OBS_DIV8 3 #define OBS_DIV16 4 #define OBS_DIV32 5 #define OBS_DIV64 6 #define OBS_DIV128 7 #define OBS_NO_INV 0 #define OBS_INV 1 #define OBS_INT_CFG(id, status, div, inv, sel)\ OBS_CFG(id, status, OBS_INT, div, inv, sel) #define OBS_EXT_CFG(id, status, div, inv, sel)\ OBS_CFG(id, status, OBS_EXT, div, inv, sel) /* define for st,pll /csg */ #define SSCG_MODE_CENTER_SPREAD 0 #define SSCG_MODE_DOWN_SPREAD 1 /* define for st,drive */ #define LSEDRV_LOWEST 0 #define LSEDRV_MEDIUM_LOW 2 #define LSEDRV_MEDIUM_HIGH 1 #define LSEDRV_HIGHEST 3 #endif /* _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_ */ optee_os-4.3.0/core/include/dt-bindings/dma/000077500000000000000000000000001464416617300206655ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/dma/at91.h000066400000000000000000000036501464416617300216200ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * This header provides macros for at91 dma bindings. * * Copyright (C) 2013 Ludovic Desroches */ #ifndef __DT_BINDINGS_DMA_AT91_H__ #define __DT_BINDINGS_DMA_AT91_H__ /* ---------- HDMAC ---------- */ /* * Source and/or destination peripheral ID */ #define AT91_DMA_CFG_PER_ID_MASK (0xff) #define AT91_DMA_CFG_PER_ID(id) ((id) & AT91_DMA_CFG_PER_ID_MASK) /* * FIFO configuration: it defines when a request is serviced. */ #define AT91_DMA_CFG_FIFOCFG_OFFSET (8) #define AT91_DMA_CFG_FIFOCFG_MASK (0xf << AT91_DMA_CFG_FIFOCFG_OFFSET) /* half FIFO (default behavior) */ #define AT91_DMA_CFG_FIFOCFG_HALF (0x0 << AT91_DMA_CFG_FIFOCFG_OFFSET) /* largest defined AHB burst */ #define AT91_DMA_CFG_FIFOCFG_ALAP (0x1 << AT91_DMA_CFG_FIFOCFG_OFFSET) /* single AHB access */ #define AT91_DMA_CFG_FIFOCFG_ASAP (0x2 << AT91_DMA_CFG_FIFOCFG_OFFSET) /* ---------- XDMAC ---------- */ #define AT91_XDMAC_DT_MEM_IF_MASK (0x1) #define AT91_XDMAC_DT_MEM_IF_OFFSET (13) #define AT91_XDMAC_DT_MEM_IF(mem_if) \ (((mem_if) & AT91_XDMAC_DT_MEM_IF_MASK) \ << AT91_XDMAC_DT_MEM_IF_OFFSET) #define AT91_XDMAC_DT_GET_MEM_IF(cfg) \ (((cfg) >> AT91_XDMAC_DT_MEM_IF_OFFSET) \ & AT91_XDMAC_DT_MEM_IF_MASK) #define AT91_XDMAC_DT_PER_IF_MASK (0x1) #define AT91_XDMAC_DT_PER_IF_OFFSET (14) #define AT91_XDMAC_DT_PER_IF(per_if) \ (((per_if) & AT91_XDMAC_DT_PER_IF_MASK) \ << AT91_XDMAC_DT_PER_IF_OFFSET) #define AT91_XDMAC_DT_GET_PER_IF(cfg) \ (((cfg) >> AT91_XDMAC_DT_PER_IF_OFFSET) \ & AT91_XDMAC_DT_PER_IF_MASK) #define AT91_XDMAC_DT_PERID_MASK (0x7f) #define AT91_XDMAC_DT_PERID_OFFSET (24) #define AT91_XDMAC_DT_PERID(perid) (((perid) & AT91_XDMAC_DT_PERID_MASK) \ << AT91_XDMAC_DT_PERID_OFFSET) #define AT91_XDMAC_DT_GET_PERID(cfg) (((cfg) >> AT91_XDMAC_DT_PERID_OFFSET) \ & AT91_XDMAC_DT_PERID_MASK) #endif /* __DT_BINDINGS_AT91_DMA_H__ */ optee_os-4.3.0/core/include/dt-bindings/firewall/000077500000000000000000000000001464416617300217315ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/firewall/stm32mp25-rif.h000066400000000000000000000054001464416617300243330ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* * Copyright (C) 2020-2024, STMicroelectronics - All Rights Reserved */ #ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H #define _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H /* RIF CIDs */ #define RIF_CID0 0x0 #define RIF_CID1 0x1 #define RIF_CID2 0x2 #define RIF_CID3 0x3 #define RIF_CID4 0x4 #define RIF_CID5 0x5 #define RIF_CID6 0x6 #define RIF_CID7 0x7 /* RIF semaphore list */ #define EMPTY_SEMWL 0x0 #ifdef __ASSEMBLER__ #define RIF_CID0_BF (1 << RIF_CID0) #define RIF_CID1_BF (1 << RIF_CID1) #define RIF_CID2_BF (1 << RIF_CID2) #define RIF_CID3_BF (1 << RIF_CID3) #define RIF_CID4_BF (1 << RIF_CID4) #define RIF_CID5_BF (1 << RIF_CID5) #define RIF_CID6_BF (1 << RIF_CID6) #define RIF_CID7_BF (1 << RIF_CID7) #else /* __ASSEMBLER__ */ #define RIF_CID0_BF BIT(RIF_CID0) #define RIF_CID1_BF BIT(RIF_CID1) #define RIF_CID2_BF BIT(RIF_CID2) #define RIF_CID3_BF BIT(RIF_CID3) #define RIF_CID4_BF BIT(RIF_CID4) #define RIF_CID5_BF BIT(RIF_CID5) #define RIF_CID6_BF BIT(RIF_CID6) #define RIF_CID7_BF BIT(RIF_CID7) #endif /* __ASSEMBLER__ */ /* RIF secure levels */ #define RIF_NSEC 0x0 #define RIF_SEC 0x1 /* RIF privilege levels */ #define RIF_NPRIV 0x0 #define RIF_PRIV 0x1 /* RIF semaphore modes */ #define RIF_SEM_DIS 0x0 #define RIF_SEM_EN 0x1 /* RIF CID filtering modes */ #define RIF_CFDIS 0x0 #define RIF_CFEN 0x1 /* RIF lock states */ #define RIF_UNLOCK 0x0 #define RIF_LOCK 0x1 /* Used when a field in a macro has no impact */ #define RIF_UNUSED 0x0 /* Most below macros aim to ease DTS files readability */ #define RIF_EXTI1_RESOURCE(x) (x) #define RIF_EXTI2_RESOURCE(x) (x) #define RIF_FMC_CTRL(x) (x) #define RIF_IOPORT_PIN(x) (x) #define RIF_HPDMA_CHANNEL(x) (x) #define RIF_IPCC_CPU1_CHANNEL(x) ((x) - 1) #define RIF_IPCC_CPU2_CHANNEL(x) (((x) - 1) + 16) #define RIF_PWR_RESOURCE(x) (x) #define RIF_HSEM_RESOURCE(x) (x) /* Shareable PWR resources, RIF_PWR_RESOURCE_WIO(0) doesn't exist */ #define RIF_PWR_RESOURCE_WIO(x) ((x) + 6) #define RIF_RCC_RESOURCE(x) (x) #define RIF_RTC_RESOURCE(x) (x) #define RIF_TAMP_RESOURCE(x) (x) #define RISC_CFEN_SHIFT 0 #define RISC_SEM_EN_SHIFT 1 #define RISC_SCID_SHIFT 4 #define RISC_SEC_SHIFT 8 #define RISC_PRIV_SHIFT 9 #define RISC_LOCK_SHIFT 10 #define RISC_SEML_SHIFT 16 #define RISC_PER_ID_SHIFT 24 #define RISC_PERx_CID_SHIFT 0 #define RIFPROT(rifid, sem_list, lock, sec, priv, scid, sem_en, cfen) \ (((rifid) << RISC_PER_ID_SHIFT) | \ ((sem_list) << RISC_SEML_SHIFT) | \ ((lock) << RISC_LOCK_SHIFT) | \ ((priv) << RISC_PRIV_SHIFT) | \ ((sec) << RISC_SEC_SHIFT) | \ ((scid) << RISC_SCID_SHIFT) | \ ((sem_en) << RISC_SEM_EN_SHIFT) | \ ((cfen) << RISC_CFEN_SHIFT)) #endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H */ optee_os-4.3.0/core/include/dt-bindings/firewall/stm32mp25-rifsc.h000066400000000000000000000124631464416617300246700ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ /* * Copyright (c) 2020-2024, STMicroelectronics */ #ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H #define _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H /* RIFSC ID */ #define STM32MP25_RIFSC_TIM1_ID 0 #define STM32MP25_RIFSC_TIM2_ID 1 #define STM32MP25_RIFSC_TIM3_ID 2 #define STM32MP25_RIFSC_TIM4_ID 3 #define STM32MP25_RIFSC_TIM5_ID 4 #define STM32MP25_RIFSC_TIM6_ID 5 #define STM32MP25_RIFSC_TIM7_ID 6 #define STM32MP25_RIFSC_TIM8_ID 7 #define STM32MP25_RIFSC_TIM10_ID 8 #define STM32MP25_RIFSC_TIM11_ID 9 #define STM32MP25_RIFSC_TIM12_ID 10 #define STM32MP25_RIFSC_TIM13_ID 11 #define STM32MP25_RIFSC_TIM14_ID 12 #define STM32MP25_RIFSC_TIM15_ID 13 #define STM32MP25_RIFSC_TIM16_ID 14 #define STM32MP25_RIFSC_TIM17_ID 15 #define STM32MP25_RIFSC_TIM20_ID 16 #define STM32MP25_RIFSC_LPTIM1_ID 17 #define STM32MP25_RIFSC_LPTIM2_ID 18 #define STM32MP25_RIFSC_LPTIM3_ID 19 #define STM32MP25_RIFSC_LPTIM4_ID 20 #define STM32MP25_RIFSC_LPTIM5_ID 21 #define STM32MP25_RIFSC_SPI1_ID 22 #define STM32MP25_RIFSC_SPI2_ID 23 #define STM32MP25_RIFSC_SPI3_ID 24 #define STM32MP25_RIFSC_SPI4_ID 25 #define STM32MP25_RIFSC_SPI5_ID 26 #define STM32MP25_RIFSC_SPI6_ID 27 #define STM32MP25_RIFSC_SPI7_ID 28 #define STM32MP25_RIFSC_SPI8_ID 29 #define STM32MP25_RIFSC_SPDIFRX_ID 30 #define STM32MP25_RIFSC_USART1_ID 31 #define STM32MP25_RIFSC_USART2_ID 32 #define STM32MP25_RIFSC_USART3_ID 33 #define STM32MP25_RIFSC_UART4_ID 34 #define STM32MP25_RIFSC_UART5_ID 35 #define STM32MP25_RIFSC_USART6_ID 36 #define STM32MP25_RIFSC_UART7_ID 37 #define STM32MP25_RIFSC_UART8_ID 38 #define STM32MP25_RIFSC_UART9_ID 39 #define STM32MP25_RIFSC_LPUART1_ID 40 #define STM32MP25_RIFSC_I2C1_ID 41 #define STM32MP25_RIFSC_I2C2_ID 42 #define STM32MP25_RIFSC_I2C3_ID 43 #define STM32MP25_RIFSC_I2C4_ID 44 #define STM32MP25_RIFSC_I2C5_ID 45 #define STM32MP25_RIFSC_I2C6_ID 46 #define STM32MP25_RIFSC_I2C7_ID 47 #define STM32MP25_RIFSC_I2C8_ID 48 #define STM32MP25_RIFSC_SAI1_ID 49 #define STM32MP25_RIFSC_SAI2_ID 50 #define STM32MP25_RIFSC_SAI3_ID 51 #define STM32MP25_RIFSC_SAI4_ID 52 #define STM32MP25_RIFSC_MDF1_ID 54 #define STM32MP25_RIFSC_ADF1_ID 55 #define STM32MP25_RIFSC_FDCAN_ID 56 #define STM32MP25_RIFSC_HDP_ID 57 #define STM32MP25_RIFSC_ADC12_ID 58 #define STM32MP25_RIFSC_ADC3_ID 59 #define STM32MP25_RIFSC_ETH1_ID 60 #define STM32MP25_RIFSC_ETH2_ID 61 #define STM32MP25_RIFSC_USBH_ID 63 #define STM32MP25_RIFSC_USB3DR_ID 66 #define STM32MP25_RIFSC_COMBOPHY_ID 67 #define STM32MP25_RIFSC_PCIE_ID 68 #define STM32MP25_RIFSC_UCPD1_ID 69 #define STM32MP25_RIFSC_ETHSW_DEIP_ID 70 #define STM32MP25_RIFSC_ETHSW_ACM_CFG_ID 71 #define STM32MP25_RIFSC_ETHSW_ACM_MSGBUF_ID 72 #define STM32MP25_RIFSC_STGEN_ID 73 #define STM32MP25_RIFSC_OCTOSPI1_ID 74 #define STM32MP25_RIFSC_OCTOSPI2_ID 75 #define STM32MP25_RIFSC_SDMMC1_ID 76 #define STM32MP25_RIFSC_SDMMC2_ID 77 #define STM32MP25_RIFSC_SDMMC3_ID 78 #define STM32MP25_RIFSC_GPU_ID 79 #define STM32MP25_RIFSC_LTDC_CMN_ID 80 #define STM32MP25_RIFSC_DSI_CMN_ID 81 #define STM32MP25_RIFSC_LVDS_ID 84 #define STM32MP25_RIFSC_CSI_ID 86 #define STM32MP25_RIFSC_DCMIPP_ID 87 #define STM32MP25_RIFSC_DCMI_PSSI_ID 88 #define STM32MP25_RIFSC_VDEC_ID 89 #define STM32MP25_RIFSC_VENC_ID 90 #define STM32MP25_RIFSC_RNG_ID 92 #define STM32MP25_RIFSC_PKA_ID 93 #define STM32MP25_RIFSC_SAES_ID 94 #define STM32MP25_RIFSC_HASH_ID 95 #define STM32MP25_RIFSC_CRYP1_ID 96 #define STM32MP25_RIFSC_CRYP2_ID 97 #define STM32MP25_RIFSC_IWDG1_ID 98 #define STM32MP25_RIFSC_IWDG2_ID 99 #define STM32MP25_RIFSC_IWDG3_ID 100 #define STM32MP25_RIFSC_IWDG4_ID 101 #define STM32MP25_RIFSC_IWDG5_ID 102 #define STM32MP25_RIFSC_WWDG1_ID 103 #define STM32MP25_RIFSC_WWDG2_ID 104 #define STM32MP25_RIFSC_VREFBUF_ID 106 #define STM32MP25_RIFSC_DTS_ID 107 #define STM32MP25_RIFSC_RAMCFG_ID 108 #define STM32MP25_RIFSC_CRC_ID 109 #define STM32MP25_RIFSC_SERC_ID 110 #define STM32MP25_RIFSC_OCTOSPIM_ID 111 #define STM32MP25_RIFSC_GICV2M_ID 112 #define STM32MP25_RIFSC_I3C1_ID 114 #define STM32MP25_RIFSC_I3C2_ID 115 #define STM32MP25_RIFSC_I3C3_ID 116 #define STM32MP25_RIFSC_I3C4_ID 117 #define STM32MP25_RIFSC_ICACHE_DCACHE_ID 118 #define STM32MP25_RIFSC_LTDC_L0L1_ID 119 #define STM32MP25_RIFSC_LTDC_L2_ID 120 #define STM32MP25_RIFSC_LTDC_ROT_ID 121 #define STM32MP25_RIFSC_DSI_TRIG_ID 122 #define STM32MP25_RIFSC_DSI_RDFIFO_ID 123 #define STM32MP25_RIFSC_OTFDEC1_ID 125 #define STM32MP25_RIFSC_OTFDEC2_ID 126 #define STM32MP25_RIFSC_IAC_ID 127 /* Global lock bindings */ #define RIFSC_RIMU_GLOCK 1 #define RIFSC_RISUP_GLOCK 2 /* masters ID */ #define RIMU_ID(idx) (idx) /* master configuration modes */ #define RIF_CIDSEL_P 0x0 /* config from RISUP */ #define RIF_CIDSEL_M 0x1 /* config from RIMU */ #define RIFSC_RIMC_MODE_SHIFT 2 #define RIFSC_RIMC_MCID_SHIFT 4 #define RIFSC_RIMC_MSEC_SHIFT 8 #define RIFSC_RIMC_MPRIV_SHIFT 9 #define RIFSC_RIMC_M_ID_SHIFT 16 #define RIFSC_RIMC_ATTRx_SHIFT 0 #define RIMUPROT(rimuid, mcid, msec, mpriv, mode) \ (((rimuid) << RIFSC_RIMC_M_ID_SHIFT) | \ ((mpriv) << RIFSC_RIMC_MPRIV_SHIFT) | \ ((msec) << RIFSC_RIMC_MSEC_SHIFT) | \ ((mcid) << RIFSC_RIMC_MCID_SHIFT) | \ ((mode) << RIFSC_RIMC_MODE_SHIFT)) #endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H */ optee_os-4.3.0/core/include/dt-bindings/gpio/000077500000000000000000000000001464416617300210625ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/gpio/atmel,piobu.h000066400000000000000000000033211464416617300234470ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* * Copyright (C) 2022 Microchip */ #ifndef _DT_BINDINGS_GPIO_ATMEL_PIOBU_H #define _DT_BINDINGS_GPIO_ATMEL_PIOBU_H #define PIOBU_PIN_AFV_SHIFT 0 #define PIOBU_PIN_AFV_MASK 0xF #define PIOBU_PIN_AFV(val) (((val) & PIOBU_PIN_AFV_MASK) >> \ PIOBU_PIN_AFV_SHIFT) #define PIOBU_PIN_RFV_SHIFT 4 #define PIOBU_PIN_RFV_MASK 0xF0 #define PIOBU_PIN_RFV(val) (((val) & PIOBU_PIN_RFV_MASK) >> \ PIOBU_PIN_RFV_SHIFT) #define PIOBU_PIN_PULL_MODE_SHIFT 8 #define PIOBU_PIN_PULL_MODE_MASK (0x3 << PIOBU_PIN_PULL_MODE_SHIFT) #define PIOBU_PIN_PULL_MODE(val) (((val) & PIOBU_PIN_PULL_MODE_MASK) >> \ PIOBU_PIN_PULL_MODE_SHIFT) #define PIOBU_PIN_PULL_NONE 0 #define PIOBU_PIN_PULL_UP 1 #define PIOBU_PIN_PULL_DOWN 2 #define PIOBU_PIN_DEF_LEVEL_SHIFT 10 #define PIOBU_PIN_DEF_LEVEL_MASK (BIT(PIOBU_PIN_DEF_LEVEL_SHIFT)) #define PIOBU_PIN_DEF_LEVEL(val) (((val) & PIOBU_PIN_DEF_LEVEL_MASK) >> \ PIOBU_PIN_DEF_LEVEL_SHIFT) #define PIOBU_PIN_DEF_LEVEL_LOW 0 #define PIOBU_PIN_DEF_LEVEL_HIGH 1 #define PIOBU_PIN_WAKEUP_SHIFT 11 #define PIOBU_PIN_WAKEUP_MASK (BIT(PIOBU_PIN_WAKEUP_SHIFT)) #define PIOBU_PIN_WAKEUP(val) (((val) & PIOBU_PIN_WAKEUP_MASK) >> \ PIOBU_PIN_WAKEUP_SHIFT) #define PIOBU_PIN_WAKEUP_DISABLE 0 #define PIOBU_PIN_WAKEUP_ENABLE 1 #define PIOBU_PIN_INPUT(afv, rfv, pull_mode, def_level, wakeup) \ ((afv) | \ ((rfv) << PIOBU_PIN_RFV_SHIFT) & PIOBU_PIN_RFV_MASK | \ ((pull_mode) << PIOBU_PIN_PULL_MODE_SHIFT) & \ PIOBU_PIN_PULL_MODE_MASK | \ ((def_level) << PIOBU_PIN_DEF_LEVEL_SHIFT) & \ PIOBU_PIN_DEF_LEVEL_MASK | \ ((wakeup) << PIOBU_PIN_WAKEUP_SHIFT) & PIOBU_PIN_WAKEUP_MASK) #endif /* _DT_BINDINGS_GPIO_ATMEL_PIOBU_H */ optee_os-4.3.0/core/include/dt-bindings/gpio/gpio.h000066400000000000000000000022441464416617300221730ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* * This header provides constants for most GPIO bindings. * * Most GPIO bindings include a flags cell as part of the GPIO specifier. * In most cases, the format of the flags cell uses the standard values * defined in this header. */ #ifndef _DT_BINDINGS_GPIO_GPIO_H #define _DT_BINDINGS_GPIO_GPIO_H /* Bit 0 express polarity */ #define GPIO_ACTIVE_HIGH 0 #define GPIO_ACTIVE_LOW 1 /* Bit 1 express single-endedness */ #define GPIO_PUSH_PULL 0 #define GPIO_SINGLE_ENDED 2 /* Bit 2 express Open drain or open source */ #define GPIO_LINE_OPEN_SOURCE 0 #define GPIO_LINE_OPEN_DRAIN 4 /* * Open Drain/Collector is the combination of single-ended open drain interface. * Open Source/Emitter is the combination of single-ended open source interface. */ #define GPIO_OPEN_DRAIN (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_DRAIN) #define GPIO_OPEN_SOURCE (GPIO_SINGLE_ENDED | GPIO_LINE_OPEN_SOURCE) /* Bit 3 express GPIO suspend/resume and reset persistence */ #define GPIO_PERSISTENT 0 #define GPIO_TRANSITORY 8 /* Bit 4 express pull up */ #define GPIO_PULL_UP 16 /* Bit 5 express pull down */ #define GPIO_PULL_DOWN 32 #endif optee_os-4.3.0/core/include/dt-bindings/gpio/stm32mp_gpio.h000066400000000000000000000006361464416617300235630ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ /* * Copyright (C) STMicroelectronics 2023 - All Rights Reserved */ #ifndef _DT_BINDINGS_GPIO_STM32MP_GPIO_H #define _DT_BINDINGS_GPIO_STM32MP_GPIO_H #include /* Macro to define the security for GPIO */ #ifdef __ASSEMBLER__ #define TZPROT(id) (1 << (id)) #else #define TZPROT(id) (UINT32_C(1) << (id)) #endif #endif optee_os-4.3.0/core/include/dt-bindings/iio/000077500000000000000000000000001464416617300207045ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/iio/adc/000077500000000000000000000000001464416617300214335ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/iio/adc/at91-sama5d2_adc.h000066400000000000000000000007641464416617300244320ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) 2021 Microchip * * This header provides constants for configuring the AT91 SAMA5D2 ADC */ #ifndef _DT_BINDINGS_IIO_ADC_AT91_SAMA5D2_ADC_H #define _DT_BINDINGS_IIO_ADC_AT91_SAMA5D2_ADC_H /* X relative position channel index */ #define AT91_SAMA5D2_ADC_X_CHANNEL 24 /* Y relative position channel index */ #define AT91_SAMA5D2_ADC_Y_CHANNEL 25 /* pressure channel index */ #define AT91_SAMA5D2_ADC_P_CHANNEL 26 #endif optee_os-4.3.0/core/include/dt-bindings/interrupt-controller/000077500000000000000000000000001464416617300243415ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/interrupt-controller/arm-gic.h000066400000000000000000000010301464416617300260230ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 OR MIT */ /* * This header provides constants for the ARM GIC. */ #ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H #define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H #include /* interrupt specifier cell 0 */ #define GIC_SPI 0 #define GIC_PPI 1 /* * Interrupt specifier cell 2. * The flags in irq.h are valid, plus those below. */ #define GIC_CPU_MASK_RAW(x) ((x) << 8) #define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) #endif optee_os-4.3.0/core/include/dt-bindings/interrupt-controller/irq.h000066400000000000000000000011431464416617300253040ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 OR MIT */ /* * This header provides constants for most IRQ bindings. * * Most IRQ bindings include a flags cell as part of the IRQ specifier. * In most cases, the format of the flags cell uses the standard values * defined in this header. */ #ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H #define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H #define IRQ_TYPE_NONE 0 #define IRQ_TYPE_EDGE_RISING 1 #define IRQ_TYPE_EDGE_FALLING 2 #define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) #define IRQ_TYPE_LEVEL_HIGH 4 #define IRQ_TYPE_LEVEL_LOW 8 #endif optee_os-4.3.0/core/include/dt-bindings/mfd/000077500000000000000000000000001464416617300206725ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/mfd/atmel-flexcom.h000066400000000000000000000006641464416617300236060ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * This header provides macros for Atmel Flexcom DT bindings. * * Copyright (C) 2015 Cyrille Pitchen */ #ifndef __DT_BINDINGS_MFD_ATMEL_FLEXCOM_H__ #define __DT_BINDINGS_MFD_ATMEL_FLEXCOM_H__ #define ATMEL_FLEXCOM_MODE_USART 1 #define ATMEL_FLEXCOM_MODE_SPI 2 #define ATMEL_FLEXCOM_MODE_TWI 3 #endif /* __DT_BINDINGS_MFD_ATMEL_FLEXCOM_H__ */ optee_os-4.3.0/core/include/dt-bindings/mfd/st,stpmic1.h000066400000000000000000000022611464416617300230470ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ /* * Copyright (C) STMicroelectronics 2018 - All Rights Reserved * Author: Philippe Peurichard , * Pascal Paillet for STMicroelectronics. */ #ifndef __DT_BINDINGS_STPMIC1_H__ #define __DT_BINDINGS_STPMIC1_H__ /* IRQ definitions */ #define IT_PONKEY_F 0 #define IT_PONKEY_R 1 #define IT_WAKEUP_F 2 #define IT_WAKEUP_R 3 #define IT_VBUS_OTG_F 4 #define IT_VBUS_OTG_R 5 #define IT_SWOUT_F 6 #define IT_SWOUT_R 7 #define IT_CURLIM_BUCK1 8 #define IT_CURLIM_BUCK2 9 #define IT_CURLIM_BUCK3 10 #define IT_CURLIM_BUCK4 11 #define IT_OCP_OTG 12 #define IT_OCP_SWOUT 13 #define IT_OCP_BOOST 14 #define IT_OVP_BOOST 15 #define IT_CURLIM_LDO1 16 #define IT_CURLIM_LDO2 17 #define IT_CURLIM_LDO3 18 #define IT_CURLIM_LDO4 19 #define IT_CURLIM_LDO5 20 #define IT_CURLIM_LDO6 21 #define IT_SHORT_SWOTG 22 #define IT_SHORT_SWOUT 23 #define IT_TWARN_F 24 #define IT_TWARN_R 25 #define IT_VINLOW_F 26 #define IT_VINLOW_R 27 #define IT_SWIN_F 30 #define IT_SWIN_R 31 /* BUCK MODES definitions */ #define STPMIC1_BUCK_MODE_NORMAL 0 #define STPMIC1_BUCK_MODE_LP 2 #endif /* __DT_BINDINGS_STPMIC1_H__ */ optee_os-4.3.0/core/include/dt-bindings/pinctrl/000077500000000000000000000000001464416617300215775ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/pinctrl/stm32-pinfunc.h000066400000000000000000000017101464416617300243570ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ /* * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Torgue Alexandre for STMicroelectronics. */ #ifndef _DT_BINDINGS_STM32_PINFUNC_H #define _DT_BINDINGS_STM32_PINFUNC_H /* define PIN modes */ #define GPIO 0x0 #define AF0 0x1 #define AF1 0x2 #define AF2 0x3 #define AF3 0x4 #define AF4 0x5 #define AF5 0x6 #define AF6 0x7 #define AF7 0x8 #define AF8 0x9 #define AF9 0xa #define AF10 0xb #define AF11 0xc #define AF12 0xd #define AF13 0xe #define AF14 0xf #define AF15 0x10 #define ANALOG 0x11 #define RSVD 0x12 /* define Pins number*/ #define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) #define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) /* package information */ #define STM32MP_PKG_AA 0x1 #define STM32MP_PKG_AB 0x2 #define STM32MP_PKG_AC 0x4 #define STM32MP_PKG_AD 0x8 #endif /* _DT_BINDINGS_STM32_PINFUNC_H */ optee_os-4.3.0/core/include/dt-bindings/regulator/000077500000000000000000000000001464416617300221305ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/regulator/active-semi,8945a-regulator.h000066400000000000000000000016501464416617300272620ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (c) 2018 Microchip Technology, Inc. All rights reserved. * * Device Tree binding constants for the ACT8945A PMIC regulators */ #ifndef _DT_BINDINGS_REGULATOR_ACT8945A_H #define _DT_BINDINGS_REGULATOR_ACT8945A_H /* * These constants should be used to specify regulator modes in device tree for * ACT8945A regulators as follows: * ACT8945A_REGULATOR_MODE_FIXED: It is specific to DCDC regulators and it * specifies the usage of fixed-frequency * PWM. * * ACT8945A_REGULATOR_MODE_NORMAL: It is specific to LDO regulators and it * specifies the usage of normal mode. * * ACT8945A_REGULATOR_MODE_LOWPOWER: For DCDC and LDO regulators; it specify * the usage of proprietary power-saving * mode. */ #define ACT8945A_REGULATOR_MODE_FIXED 1 #define ACT8945A_REGULATOR_MODE_NORMAL 2 #define ACT8945A_REGULATOR_MODE_LOWPOWER 3 #endif optee_os-4.3.0/core/include/dt-bindings/regulator/st,stm32mp13-regulator.h000066400000000000000000000024311464416617300263770ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* * Copyright (C) 2020-2022, STMicroelectronics - All Rights Reserved */ #ifndef __DT_BINDINGS_REGULATOR_ST_STM32MP13_REGULATOR_H #define __DT_BINDINGS_REGULATOR_ST_STM32MP13_REGULATOR_H /* SCMI voltage domains identifiers */ /* SOC Internal regulators */ #define VOLTD_SCMI_REG11 0 #define VOLTD_SCMI_REG18 1 #define VOLTD_SCMI_USB33 2 #define VOLTD_SCMI_SDMMC1_IO 3 #define VOLTD_SCMI_SDMMC2_IO 4 #define VOLTD_SCMI_VREFBUF 5 /* STPMIC1 regulators */ #define VOLTD_SCMI_STPMIC1_BUCK1 6 #define VOLTD_SCMI_STPMIC1_BUCK2 7 #define VOLTD_SCMI_STPMIC1_BUCK3 8 #define VOLTD_SCMI_STPMIC1_BUCK4 9 #define VOLTD_SCMI_STPMIC1_LDO1 10 #define VOLTD_SCMI_STPMIC1_LDO2 11 #define VOLTD_SCMI_STPMIC1_LDO3 12 #define VOLTD_SCMI_STPMIC1_LDO4 13 #define VOLTD_SCMI_STPMIC1_LDO5 14 #define VOLTD_SCMI_STPMIC1_LDO6 15 #define VOLTD_SCMI_STPMIC1_VREFDDR 16 #define VOLTD_SCMI_STPMIC1_BOOST 17 #define VOLTD_SCMI_STPMIC1_PWR_SW1 18 #define VOLTD_SCMI_STPMIC1_PWR_SW2 19 /* External regulators */ #define VOLTD_SCMI_REGU0 20 #define VOLTD_SCMI_REGU1 21 #define VOLTD_SCMI_REGU2 22 #define VOLTD_SCMI_REGU3 23 #define VOLTD_SCMI_REGU4 24 #endif /*__DT_BINDINGS_REGULATOR_ST_STM32MP13_REGULATOR_H */ optee_os-4.3.0/core/include/dt-bindings/regulator/st,stm32mp15-regulator.h000066400000000000000000000016361464416617300264070ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */ /* * Copyright (C) 2020, STMicroelectronics - All Rights Reserved */ #ifndef __DT_BINDINGS_REGULATOR_ST_STM32MP15_REGULATOR_H #define __DT_BINDINGS_REGULATOR_ST_STM32MP15_REGULATOR_H /* SCMI voltage domain identifiers */ #define VOLTD_SCMI_REG11 0 #define VOLTD_SCMI_REG18 1 #define VOLTD_SCMI_USB33 2 #define VOLTD_SCMI_STPMIC1_BUCK1 3 #define VOLTD_SCMI_STPMIC1_BUCK2 4 #define VOLTD_SCMI_STPMIC1_BUCK3 5 #define VOLTD_SCMI_STPMIC1_BUCK4 6 #define VOLTD_SCMI_STPMIC1_LDO1 7 #define VOLTD_SCMI_STPMIC1_LDO2 8 #define VOLTD_SCMI_STPMIC1_LDO3 9 #define VOLTD_SCMI_STPMIC1_LDO4 10 #define VOLTD_SCMI_STPMIC1_LDO5 11 #define VOLTD_SCMI_STPMIC1_LDO6 12 #define VOLTD_SCMI_STPMIC1_VREFDDR 13 #define VOLTD_SCMI_STPMIC1_BOOST 14 #define VOLTD_SCMI_STPMIC1_PWR_SW1 15 #define VOLTD_SCMI_STPMIC1_PWR_SW2 16 #endif /*__DT_BINDINGS_REGULATOR_ST_STM32MP15_REGULATOR_H */ optee_os-4.3.0/core/include/dt-bindings/reset/000077500000000000000000000000001464416617300212465ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/reset/st,stm32mp25-rcc.h000066400000000000000000000066731464416617300242770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) STMicroelectronics 2024 - All Rights Reserved */ #ifndef _DT_BINDINGS_RESET_ST_STM32MP25_RCC_H_ #define _DT_BINDINGS_RESET_ST_STM32MP25_RCC_H_ #define TIM1_R 0 #define TIM2_R 1 #define TIM3_R 2 #define TIM4_R 3 #define TIM5_R 4 #define TIM6_R 5 #define TIM7_R 6 #define TIM8_R 7 #define TIM10_R 8 #define TIM11_R 9 #define TIM12_R 10 #define TIM13_R 11 #define TIM14_R 12 #define TIM15_R 13 #define TIM16_R 14 #define TIM17_R 15 #define TIM20_R 16 #define LPTIM1_R 17 #define LPTIM2_R 18 #define LPTIM3_R 19 #define LPTIM4_R 20 #define LPTIM5_R 21 #define SPI1_R 22 #define SPI2_R 23 #define SPI3_R 24 #define SPI4_R 25 #define SPI5_R 26 #define SPI6_R 27 #define SPI7_R 28 #define SPI8_R 29 #define SPDIFRX_R 30 #define USART1_R 31 #define USART2_R 32 #define USART3_R 33 #define UART4_R 34 #define UART5_R 35 #define USART6_R 36 #define UART7_R 37 #define UART8_R 38 #define UART9_R 39 #define LPUART1_R 40 #define IS2M_R 41 #define I2C1_R 42 #define I2C2_R 43 #define I2C3_R 44 #define I2C4_R 45 #define I2C5_R 46 #define I2C6_R 47 #define I2C7_R 48 #define I2C8_R 49 #define SAI1_R 50 #define SAI2_R 51 #define SAI3_R 52 #define SAI4_R 53 #define MDF1_R 54 #define MDF2_R 55 #define FDCAN_R 56 #define HDP_R 57 #define ADC12_R 58 #define ADC3_R 59 #define ETH1_R 60 #define ETH2_R 61 #define USB2_R 62 #define USB2PHY1_R 63 #define USB2PHY2_R 64 #define USB3DR_R 65 #define USB3PCIEPHY_R 66 #define USBTC_R 67 #define ETHSW_R 68 #define SDMMC1_R 69 #define SDMMC1DLL_R 70 #define SDMMC2_R 71 #define SDMMC2DLL_R 72 #define SDMMC3_R 73 #define SDMMC3DLL_R 74 #define GPU_R 75 #define LTDC_R 76 #define DSI_R 77 #define LVDS_R 78 #define CSI_R 79 #define DCMIPP_R 80 #define CCI_R 81 #define VDEC_R 82 #define VENC_R 83 #define WWDG1_R 84 #define WWDG2_R 85 #define VREF_R 86 #define DTS_R 87 #define CRC_R 88 #define SERC_R 89 #define OSPIIOM_R 90 #define I3C1_R 91 #define I3C2_R 92 #define I3C3_R 93 #define I3C4_R 94 #define IWDG2_KER_R 95 #define IWDG4_KER_R 96 #define RNG_R 97 #define PKA_R 98 #define SAES_R 99 #define HASH_R 100 #define CRYP1_R 101 #define CRYP2_R 102 #define PCIE_R 103 #define OSPI1_R 104 #define OSPI1DLL_R 105 #define OSPI2_R 106 #define OSPI2DLL_R 107 #define FMC_R 108 #define DBG_R 109 #define GPIOA_R 110 #define GPIOB_R 111 #define GPIOC_R 112 #define GPIOD_R 113 #define GPIOE_R 114 #define GPIOF_R 115 #define GPIOG_R 116 #define GPIOH_R 117 #define GPIOI_R 118 #define GPIOJ_R 119 #define GPIOK_R 120 #define GPIOZ_R 121 #define HPDMA1_R 122 #define HPDMA2_R 123 #define HPDMA3_R 124 #define LPDMA_R 125 #define HSEM_R 126 #define IPCC1_R 127 #define IPCC2_R 128 #define C2_HOLDBOOT_R 129 #define C1_HOLDBOOT_R 130 #define C1_R 131 #define C1P1POR_R 132 #define C1P1_R 133 #define C2_R 134 #define C3_R 135 #define SYS_R 136 #define VSW_R 137 #define C1MS_R 138 #define DDRCP_R 139 #define DDRCAPB_R 140 #define DDRPHYCAPB_R 141 #define DDRCFG_R 142 #define DDR_R 143 #define IWDG1_SYS_R 144 #define IWDG2_SYS_R 145 #define IWDG3_SYS_R 146 #define IWDG4_SYS_R 147 #define STM32MP25_LAST_RESET 148 #define RST_SCMI_C1_R 0 #define RST_SCMI_C2_R 1 #define RST_SCMI_C1_HOLDBOOT_R 2 #define RST_SCMI_C2_HOLDBOOT_R 3 #define RST_SCMI_FMC 4 #define RST_SCMI_OSPI1 5 #define RST_SCMI_OSPI1DLL 6 #define RST_SCMI_OSPI2 7 #define RST_SCMI_OSPI2DLL 8 #endif /* _DT_BINDINGS_RESET_ST_STM32MP25_RCC_H_ */ optee_os-4.3.0/core/include/dt-bindings/reset/stm32mp1-resets.h000066400000000000000000000055151464416617300243160ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) STMicroelectronics 2018 - All Rights Reserved * Author: Gabriel Fernandez for STMicroelectronics. */ #ifndef _DT_BINDINGS_STM32MP1_RESET_H_ #define _DT_BINDINGS_STM32MP1_RESET_H_ #define MCU_HOLD_BOOT_R 2144 #define LTDC_R 3072 #define DSI_R 3076 #define DDRPERFM_R 3080 #define USBPHY_R 3088 #define SPI6_R 3136 #define I2C4_R 3138 #define I2C6_R 3139 #define USART1_R 3140 #define STGEN_R 3156 #define GPIOZ_R 3200 #define CRYP1_R 3204 #define HASH1_R 3205 #define RNG1_R 3206 #define AXIM_R 3216 #define GPU_R 3269 #define ETHMAC_R 3274 #define FMC_R 3276 #define QSPI_R 3278 #define SDMMC1_R 3280 #define SDMMC2_R 3281 #define CRC1_R 3284 #define USBH_R 3288 #define MDMA_R 3328 #define MPSYST_R 8224 #define MCU_R 8225 #define TIM2_R 19456 #define TIM3_R 19457 #define TIM4_R 19458 #define TIM5_R 19459 #define TIM6_R 19460 #define TIM7_R 19461 #define TIM12_R 16462 #define TIM13_R 16463 #define TIM14_R 16464 #define LPTIM1_R 19465 #define SPI2_R 19467 #define SPI3_R 19468 #define USART2_R 19470 #define USART3_R 19471 #define UART4_R 19472 #define UART5_R 19473 #define UART7_R 19474 #define UART8_R 19475 #define I2C1_R 19477 #define I2C2_R 19478 #define I2C3_R 19479 #define I2C5_R 19480 #define SPDIF_R 19482 #define CEC_R 19483 #define DAC12_R 19485 #define MDIO_R 19847 #define TIM1_R 19520 #define TIM8_R 19521 #define TIM15_R 19522 #define TIM16_R 19523 #define TIM17_R 19524 #define SPI1_R 19528 #define SPI4_R 19529 #define SPI5_R 19530 #define USART6_R 19533 #define SAI1_R 19536 #define SAI2_R 19537 #define SAI3_R 19538 #define DFSDM_R 19540 #define FDCAN_R 19544 #define LPTIM2_R 19584 #define LPTIM3_R 19585 #define LPTIM4_R 19586 #define LPTIM5_R 19587 #define SAI4_R 19592 #define SYSCFG_R 19595 #define VREF_R 19597 #define TMPSENS_R 19600 #define PMBCTRL_R 19601 #define DMA1_R 19648 #define DMA2_R 19649 #define DMAMUX_R 19650 #define ADC12_R 19653 #define USBO_R 19656 #define SDMMC3_R 19664 #define CAMITF_R 19712 #define CRYP2_R 19716 #define HASH2_R 19717 #define RNG2_R 19718 #define CRC2_R 19719 #define HSEM_R 19723 #define MBOX_R 19724 #define GPIOA_R 19776 #define GPIOB_R 19777 #define GPIOC_R 19778 #define GPIOD_R 19779 #define GPIOE_R 19780 #define GPIOF_R 19781 #define GPIOG_R 19782 #define GPIOH_R 19783 #define GPIOI_R 19784 #define GPIOJ_R 19785 #define GPIOK_R 19786 /* SCMI reset domain identifiers */ #define RST_SCMI_SPI6 0 #define RST_SCMI_I2C4 1 #define RST_SCMI_I2C6 2 #define RST_SCMI_USART1 3 #define RST_SCMI_STGEN 4 #define RST_SCMI_GPIOZ 5 #define RST_SCMI_CRYP1 6 #define RST_SCMI_HASH1 7 #define RST_SCMI_RNG1 8 #define RST_SCMI_MDMA 9 #define RST_SCMI_MCU 10 #define RST_SCMI_MCU_HOLD_BOOT 11 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ optee_os-4.3.0/core/include/dt-bindings/reset/stm32mp13-resets.h000066400000000000000000000044451464416617300244020ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) STMicroelectronics 2022 - All Rights Reserved * Author: Gabriel Fernandez */ #ifndef _DT_BINDINGS_STM32MP13_RESET_H_ #define _DT_BINDINGS_STM32MP13_RESET_H_ #define MPSYST_R 2208 #define TIM2_R 13568 #define TIM3_R 13569 #define TIM4_R 13570 #define TIM5_R 13571 #define TIM6_R 13572 #define TIM7_R 13573 #define LPTIM1_R 13577 #define SPI2_R 13579 #define SPI3_R 13580 #define USART3_R 13583 #define UART4_R 13584 #define UART5_R 13585 #define UART7_R 13586 #define UART8_R 13587 #define I2C1_R 13589 #define I2C2_R 13590 #define SPDIF_R 13594 #define TIM1_R 13632 #define TIM8_R 13633 #define SPI1_R 13640 #define USART6_R 13645 #define SAI1_R 13648 #define SAI2_R 13649 #define DFSDM_R 13652 #define FDCAN_R 13656 #define LPTIM2_R 13696 #define LPTIM3_R 13697 #define LPTIM4_R 13698 #define LPTIM5_R 13699 #define SYSCFG_R 13707 #define VREF_R 13709 #define DTS_R 13712 #define PMBCTRL_R 13713 #define LTDC_R 13760 #define DCMIPP_R 13761 #define DDRPERFM_R 13768 #define USBPHY_R 13776 #define STGEN_R 13844 #define USART1_R 13888 #define USART2_R 13889 #define SPI4_R 13890 #define SPI5_R 13891 #define I2C3_R 13892 #define I2C4_R 13893 #define I2C5_R 13894 #define TIM12_R 13895 #define TIM13_R 13896 #define TIM14_R 13897 #define TIM15_R 13898 #define TIM16_R 13899 #define TIM17_R 13900 #define DMA1_R 13952 #define DMA2_R 13953 #define DMAMUX1_R 13954 #define DMA3_R 13955 #define DMAMUX2_R 13956 #define ADC1_R 13957 #define ADC2_R 13958 #define USBO_R 13960 #define GPIOA_R 14080 #define GPIOB_R 14081 #define GPIOC_R 14082 #define GPIOD_R 14083 #define GPIOE_R 14084 #define GPIOF_R 14085 #define GPIOG_R 14086 #define GPIOH_R 14087 #define GPIOI_R 14088 #define TSC_R 14095 #define PKA_R 14146 #define SAES_R 14147 #define CRYP1_R 14148 #define HASH1_R 14149 #define RNG1_R 14150 #define AXIMC_R 14160 #define MDMA_R 14208 #define MCE_R 14209 #define ETH1MAC_R 14218 #define FMC_R 14220 #define QSPI_R 14222 #define SDMMC1_R 14224 #define SDMMC2_R 14225 #define CRC1_R 14228 #define USBH_R 14232 #define ETH2MAC_R 14238 /* SCMI reset domain identifiers */ #define RST_SCMI_LTDC 0 #define RST_SCMI_MDMA 1 #endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ optee_os-4.3.0/core/include/dt-bindings/rtc/000077500000000000000000000000001464416617300207145ustar00rootroot00000000000000optee_os-4.3.0/core/include/dt-bindings/rtc/rtc-stm32.h000066400000000000000000000005421464416617300226240ustar00rootroot00000000000000/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ /* * Copyright (C) STMicroelectronics 2022-2023 - All Rights Reserved * This header provides constants for STM32_RTC bindings. */ #ifndef _DT_BINDINGS_RTC_STM32_H #define _DT_BINDINGS_RTC_STM32_H #define RTC_OUT1 0 #define RTC_OUT2 1 #define RTC_OUT2_RMP 2 #endif /*_DT_BINDINGS_RTC_STM32_H*/ optee_os-4.3.0/core/include/gen-asm-defines.h000066400000000000000000000005141464416617300210350ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ #ifndef __GEN_ASM_DEFINES_H #define __GEN_ASM_DEFINES_H #define DEFINES void __defines(void); void __defines(void) #define DEFINE(def, val) \ asm volatile("\n.ascii \"==>" #def " %c0 " #val "\"" : : "i" (val)); #endif /*__GEN_ASM_DEFINES_H*/ optee_os-4.3.0/core/include/initcall.h000066400000000000000000000133161464416617300176760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __INITCALL_H #define __INITCALL_H #include #include #include struct initcall { TEE_Result (*func)(void); #if TRACE_LEVEL >= TRACE_DEBUG int level; const char *func_name; #endif }; #if TRACE_LEVEL >= TRACE_DEBUG #define __define_initcall(type, lvl, fn) \ SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(type ## call, lvl, \ struct initcall) = \ { .func = (fn), .level = (lvl), .func_name = #fn, } #else #define __define_initcall(type, lvl, fn) \ SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(type ## call, lvl, \ struct initcall) = \ { .func = (fn), } #endif #define preinitcall_begin \ SCATTERED_ARRAY_BEGIN(preinitcall, struct initcall) #define preinitcall_end SCATTERED_ARRAY_END(preinitcall, struct initcall) #define initcall_begin SCATTERED_ARRAY_BEGIN(initcall, struct initcall) #define initcall_end SCATTERED_ARRAY_END(initcall, struct initcall) #define finalcall_begin SCATTERED_ARRAY_BEGIN(finalcall, struct initcall) #define finalcall_end SCATTERED_ARRAY_END(finalcall, struct initcall) /* * The preinit_*(), *_init() and boot_final() macros are used to register * callback functions to be called at different stages during * initialization. * * Functions registered with preinit_*() are always called before functions * registered with *_init(). * * Functions registered with boot_final() are called before exiting to * normal world the first time. * * Without virtualization this happens in the order of the defines below. * * However, with virtualization things are a bit different. boot_final() * functions are called first before exiting to normal world the first * time. Functions registered with boot_final() can only operate on the * nexus. preinit_*() functions are called early before the first yielding * call into the partition, in the newly created partition. *_init() * functions are called at the first yielding call. * * +-------------------------------+-----------------------------------+ * | Without virtualization | With virtualization | * +-------------------------------+-----------------------------------+ * | At the end of boot_init_primary_late() just before the print: | * | "Primary CPU switching to normal world boot" | * +-------------------------------+-----------------------------------+ * | 1. call_preinitcalls() | In the nexus, final calls | * | 2. call_initcalls() +-----------------------------------+ * | 3. call_finalcalls() | 1. boot_final() / nex_*init*() | * +-------------------------------+-----------------------------------+ * | "Primary CPU switching to normal world boot" is printed | * +-------------------------------+-----------------------------------+ * | A guest is created and | * | virt_guest_created() is called. | * | After the partition has been | * | created and activated. | * +-----------------------------------+ * | 2. call_preinitcalls() | * +-----------------------------------+ * | When the partition is receiving | * | the first yielding call | * | virt_on_stdcall() is called. | * +-----------------------------------+ * | 3. call_initcalls() | * +-----------------------------------+ */ #define preinit_early(fn) __define_initcall(preinit, 1, fn) #define preinit(fn) __define_initcall(preinit, 2, fn) #define preinit_late(fn) __define_initcall(preinit, 3, fn) #define early_init(fn) __define_initcall(init, 1, fn) #define early_init_late(fn) __define_initcall(init, 2, fn) #define service_init(fn) __define_initcall(init, 3, fn) #define service_init_late(fn) __define_initcall(init, 4, fn) #define driver_init(fn) __define_initcall(init, 5, fn) #define driver_init_late(fn) __define_initcall(init, 6, fn) #define release_init_resource(fn) __define_initcall(init, 7, fn) #define boot_final(fn) __define_initcall(final, 1, fn) /* * These nex_* init-calls are provided for drivers and services that reside * in the nexus in case of virtualization. The init-calls are performed * before exiting to the non-secure world at the end of boot * initialization. In case of virtualization the init-calls are based on * final calls, while otherwise are the same as the non-nex counterpart. */ #ifdef CFG_NS_VIRTUALIZATION #define nex_early_init(fn) boot_final(fn) #define nex_early_init_late(fn) __define_initcall(final, 2, fn) #define nex_service_init(fn) __define_initcall(final, 3, fn) #define nex_service_init_late(fn) __define_initcall(final, 4, fn) #define nex_driver_init(fn) __define_initcall(final, 5, fn) #define nex_driver_init_late(fn) __define_initcall(final, 6, fn) #define nex_release_init_resource(fn) __define_initcall(final, 7, fn) #else #define nex_early_init(fn) early_init(fn) #define nex_early_init_late(fn) early_init_late(fn) #define nex_service_init(fn) service_init(fn) #define nex_service_init_late(fn) service_init_late(fn) #define nex_driver_init(fn) driver_init(fn) #define nex_driver_init_late(fn) driver_init_late(fn) #define nex_release_init_resource(fn) release_init_resource(fn) #endif void call_preinitcalls(void); void call_initcalls(void); void call_finalcalls(void); #endif optee_os-4.3.0/core/include/io.h000066400000000000000000000155521464416617300165120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2019, Linaro Limited */ #ifndef __IO_H #define __IO_H #include #include #include #include #include #include /* * Make sure that compiler reads/writes given variable only once. This is needed * in cases when we have normal shared memory, and this memory can be changed * at any moment. Compiler does not knows about this, so it can optimize memory * access in any way, including repeated accesses from the same address. * These macro enforce compiler to access memory only once. */ #define READ_ONCE(p) __compiler_atomic_load(&(p)) #define WRITE_ONCE(p, v) __compiler_atomic_store(&(p), (v)) static inline void io_write8(vaddr_t addr, uint8_t val) { *(volatile uint8_t *)addr = val; } static inline void io_write16(vaddr_t addr, uint16_t val) { *(volatile uint16_t *)addr = val; } static inline void io_write32(vaddr_t addr, uint32_t val) { *(volatile uint32_t *)addr = val; } static inline void io_write64(vaddr_t addr, uint64_t val) { *(volatile uint64_t *)addr = val; } static inline uint8_t io_read8(vaddr_t addr) { return *(volatile uint8_t *)addr; } static inline uint16_t io_read16(vaddr_t addr) { return *(volatile uint16_t *)addr; } static inline uint32_t io_read32(vaddr_t addr) { return *(volatile uint32_t *)addr; } static inline uint64_t io_read64(vaddr_t addr) { return *(volatile uint64_t *)addr; } static inline void io_mask8(vaddr_t addr, uint8_t val, uint8_t mask) { io_write8(addr, (io_read8(addr) & ~mask) | (val & mask)); } static inline void io_mask16(vaddr_t addr, uint16_t val, uint16_t mask) { io_write16(addr, (io_read16(addr) & ~mask) | (val & mask)); } static inline void io_mask32(vaddr_t addr, uint32_t val, uint32_t mask) { io_write32(addr, (io_read32(addr) & ~mask) | (val & mask)); } static inline uint64_t get_be64(const void *p) { return TEE_U64_FROM_BIG_ENDIAN(*(const uint64_t *)p); } static inline void put_be64(void *p, uint64_t val) { *(uint64_t *)p = TEE_U64_TO_BIG_ENDIAN(val); } static inline uint32_t get_be32(const void *p) { return TEE_U32_FROM_BIG_ENDIAN(*(const uint32_t *)p); } static inline void put_be32(void *p, uint32_t val) { *(uint32_t *)p = TEE_U32_TO_BIG_ENDIAN(val); } static inline uint16_t get_be16(const void *p) { return TEE_U16_FROM_BIG_ENDIAN(*(const uint16_t *)p); } static inline void put_be16(void *p, uint16_t val) { *(uint16_t *)p = TEE_U16_TO_BIG_ENDIAN(val); } static inline void put_le32(const void *p, uint32_t val) { *(uint32_t *)p = val; } static inline uint32_t get_le32(const void *p) { return *(const uint32_t *)p; } static inline void put_le64(const void *p, uint64_t val) { *(uint64_t *)p = val; } static inline uint64_t get_le64(const void *p) { return *(const uint64_t *)p; } /* Unaligned accesses */ struct __unaligned_u16_t { uint16_t x; } __packed; struct __unaligned_u32_t { uint32_t x; } __packed; struct __unaligned_u64_t { uint64_t x; } __packed; static inline uint64_t get_unaligned_be64(const void *p) { const struct __unaligned_u64_t *tmp = p; return TEE_U64_FROM_BIG_ENDIAN(tmp->x); } static inline void put_unaligned_be64(void *p, uint64_t val) { struct __unaligned_u64_t *tmp = p; tmp->x = TEE_U64_TO_BIG_ENDIAN(val); } static inline uint32_t get_unaligned_be32(const void *p) { const struct __unaligned_u32_t *tmp = p; return TEE_U32_FROM_BIG_ENDIAN(tmp->x); } static inline void put_unaligned_be32(void *p, uint32_t val) { struct __unaligned_u32_t *tmp = p; tmp->x = TEE_U32_TO_BIG_ENDIAN(val); } static inline uint16_t get_unaligned_be16(const void *p) { const struct __unaligned_u16_t *tmp = p; return TEE_U16_FROM_BIG_ENDIAN(tmp->x); } static inline void put_unaligned_be16(void *p, uint16_t val) { struct __unaligned_u16_t *tmp = p; tmp->x = TEE_U16_TO_BIG_ENDIAN(val); } static inline void put_unaligned_le64(void *p, uint64_t val) { struct __unaligned_u64_t *tmp = p; tmp->x = val; } static inline uint64_t get_unaligned_le64(const void *p) { const struct __unaligned_u64_t *tmp = p; return tmp->x; } static inline void put_unaligned_le32(void *p, uint32_t val) { struct __unaligned_u32_t *tmp = p; tmp->x = val; } static inline uint32_t get_unaligned_le32(const void *p) { const struct __unaligned_u32_t *tmp = p; return tmp->x; } static inline void put_unaligned_le16(void *p, uint16_t val) { struct __unaligned_u16_t *tmp = p; tmp->x = val; } static inline uint16_t get_unaligned_le16(const void *p) { const struct __unaligned_u16_t *tmp = p; return tmp->x; } /* * Set and clear bits helpers. * * @addr is the address of the memory cell accessed * @set_mask represents the bit mask of the bit(s) to set, aka set to 1 * @clear_mask represents the bit mask of the bit(s) to clear, aka reset to 0 * * io_clrsetbits32() clears then sets the target bits in this order. If a bit * position is defined by both @set_mask and @clear_mask, the bit will be set. */ static inline void io_setbits32(vaddr_t addr, uint32_t set_mask) { io_write32(addr, io_read32(addr) | set_mask); } static inline void io_clrbits32(vaddr_t addr, uint32_t clear_mask) { io_write32(addr, io_read32(addr) & ~clear_mask); } static inline void io_clrsetbits32(vaddr_t addr, uint32_t clear_mask, uint32_t set_mask) { io_write32(addr, (io_read32(addr) & ~clear_mask) | set_mask); } static inline void io_setbits16(vaddr_t addr, uint16_t set_mask) { io_write16(addr, io_read16(addr) | set_mask); } static inline void io_clrbits16(vaddr_t addr, uint16_t clear_mask) { io_write16(addr, io_read16(addr) & ~clear_mask); } static inline void io_clrsetbits16(vaddr_t addr, uint16_t clear_mask, uint16_t set_mask) { io_write16(addr, (io_read16(addr) & ~clear_mask) | set_mask); } static inline void io_setbits8(vaddr_t addr, uint8_t set_mask) { io_write8(addr, io_read8(addr) | set_mask); } static inline void io_clrbits8(vaddr_t addr, uint8_t clear_mask) { io_write8(addr, io_read8(addr) & ~clear_mask); } static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask, uint8_t set_mask) { io_write8(addr, (io_read8(addr) & ~clear_mask) | set_mask); } /* * Poll on a IO memory content or timeout * * @_addr is the address of the memory cell accessed * @_val represents the val of the memory cell accessed * @_cond represents the condition to get the correct value * @_delay_us represents the read interval in mircorseconds * @_timeout_us represents the timeout period in microseconds * * @return nonzero value means timeout, 0 means got right value */ #define IO_READ32_POLL_TIMEOUT(_addr, _val, _cond, _delay_us, _timeout_us) \ ({ \ uint64_t __timeout = timeout_init_us(_timeout_us); \ uint32_t __delay = (_delay_us); \ \ while (!timeout_elapsed(__timeout)) { \ (_val) = io_read32(_addr); \ if (_cond) \ break; \ udelay(__delay); \ } \ (_val) = io_read32(_addr); \ !(_cond); \ }) #endif /*__IO_H*/ optee_os-4.3.0/core/include/keep.h000066400000000000000000000023751464416617300170260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __KEEP_H #define __KEEP_H #ifdef __ASSEMBLER__ .macro DECLARE_KEEP_PAGER sym .pushsection __keep_meta_vars_pager, "a" .global ____keep_pager_\sym ____keep_pager_\sym: .long \sym .popsection .endm .macro DECLARE_KEEP_INIT sym .pushsection __keep_meta_vars_init, "a" .global ____keep_init_\sym ____keep_init_\sym: .long \sym .popsection .endm #else #include #define __DECLARE_KEEP_PAGER2(sym, file_id) \ extern const unsigned long ____keep_pager_##sym; \ const unsigned long ____keep_pager_##sym##_##file_id \ __section("__keep_meta_vars_pager") = (unsigned long)&(sym) #define __DECLARE_KEEP_PAGER1(sym, file_id) __DECLARE_KEEP_PAGER2(sym, file_id) #define DECLARE_KEEP_PAGER(sym) __DECLARE_KEEP_PAGER1(sym, __FILE_ID__) #define __DECLARE_KEEP_INIT2(sym, file_id) \ extern const unsigned long ____keep_init_##sym##file_id; \ const unsigned long ____keep_init_##sym##_##file_id \ __section("__keep_meta_vars_init") = (unsigned long)&(sym) #define __DECLARE_KEEP_INIT1(sym, file_id) __DECLARE_KEEP_INIT2(sym, file_id) #define DECLARE_KEEP_INIT(sym) __DECLARE_KEEP_INIT1(sym, __FILE_ID__) #endif /* __ASSEMBLER__ */ #endif /*__KEEP_H*/ optee_os-4.3.0/core/include/kernel/000077500000000000000000000000001464416617300172025ustar00rootroot00000000000000optee_os-4.3.0/core/include/kernel/abort.h000066400000000000000000000020251464416617300204610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2021, Linaro Limited */ #ifndef __KERNEL_ABORT_H #define __KERNEL_ABORT_H #define ABORT_TYPE_UNDEF 0 #define ABORT_TYPE_PREFETCH 1 #define ABORT_TYPE_DATA 2 /* Dump stack on user mode panic (not an abort) */ #define ABORT_TYPE_USER_MODE_PANIC 3 #ifndef __ASSEMBLER__ #include #include struct abort_info { uint32_t abort_type; uint32_t fault_descr; /* only valid for data of prefetch abort */ vaddr_t va; uint32_t pc; struct thread_abort_regs *regs; }; /* Print abort info to the console */ void abort_print(struct abort_info *ai); /* Print abort info + stack dump to the console */ void abort_print_error(struct abort_info *ai); void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs); bool abort_is_user_exception(struct abort_info *ai); bool abort_is_write_fault(struct abort_info *ai); /* Called from a normal thread */ void abort_print_current_ts(void); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_ABORT_H*/ optee_os-4.3.0/core/include/kernel/asan.h000066400000000000000000000027151464416617300203020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __KERNEL_ASAN_H #define __KERNEL_ASAN_H #include #define ASAN_DATA_RED_ZONE -1 #define ASAN_HEAP_RED_ZONE -2 #define ASAN_BLOCK_SIZE U(8) #define ASAN_BLOCK_SHIFT U(3) #define ASAN_BLOCK_MASK (ASAN_BLOCK_SIZE - 1) #ifndef __ASSEMBLER__ #include #include #include void asan_set_shadowed(const void *va_begin, const void *va_end); void asan_start(void); #ifdef CFG_CORE_SANITIZE_KADDRESS void asan_tag_no_access(const void *begin, const void *end); void asan_tag_access(const void *begin, const void *end); void asan_tag_heap_free(const void *begin, const void *end); void *asan_memset_unchecked(void *s, int c, size_t n); void *asan_memcpy_unchecked(void *__restrict s1, const void *__restrict s2, size_t n); #else static inline void asan_tag_no_access(const void *begin __unused, const void *end __unused) { } static inline void asan_tag_access(const void *begin __unused, const void *end __unused) { } static inline void asan_tag_heap_free(const void *begin __unused, const void *end __unused) { } static inline void *asan_memset_unchecked(void *s, int c, size_t n) { return memset(s, c, n); } static inline void *asan_memcpy_unchecked(void *__restrict s1, const void *__restrict s2, size_t n) { return memcpy(s1, s2, n); } #endif #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_ASAN_H*/ optee_os-4.3.0/core/include/kernel/boot.h000066400000000000000000000070051464416617300203200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2020, Linaro Limited * Copyright (c) 2021-2023, Arm Limited */ #ifndef __KERNEL_BOOT_H #define __KERNEL_BOOT_H #include #include #include /* * struct boot_embdata - Embedded boot data * @total_len: Total length of the embedded boot data * @num_blobs: Number of blobs in the embedded boot data, always 2 even if * one blob is empty * @hashes_offset: Offset of hashes from start of this struct * @hashes_len: Length of hashes * @reloc_offset: Offset of reloc from start of this struct * @reloc_len: Length of reloc * * This struct is initialized by scripts/gen_tee_bin.py and must be kept * in sync with that script. The struct and the following data is loaded * at different addresses at boot depending on CFG_WITH_PAGER. * * If configured with CFG_WITH_PAGER=y the struct with data is following * init part, this is together with the init part moved by the primary CPU * so it ends up at __init_end. Whatever need to be saved for later need to * be copied to a safe location in init_runtime(). * * If configured with CFG_WITH_PAGER=n following the struct with data is * __data_end, this is moved by the primary CPU so it ends up at __end. */ struct boot_embdata { uint32_t total_len; uint32_t num_blobs; uint32_t hashes_offset; uint32_t hashes_len; uint32_t reloc_offset; uint32_t reloc_len; }; extern const struct core_mmu_config boot_mmu_config; void boot_init_primary_early(void); void boot_init_primary_late(unsigned long fdt, unsigned long manifest); void boot_init_memtag(void); void boot_clear_memtag(void); void boot_save_args(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4); void __panic_at_smc_return(void) __noreturn; #if defined(CFG_WITH_ARM_TRUSTED_FW) unsigned long cpu_on_handler(unsigned long a0, unsigned long a1); unsigned long boot_cpu_on_handler(unsigned long a0, unsigned long a1); #else void boot_init_secondary(unsigned long nsec_entry); #endif void boot_primary_init_intc(void); void boot_secondary_init_intc(void); void init_sec_mon(unsigned long nsec_entry); void init_tee_runtime(void); /* weak routines eventually overridden by platform */ void plat_cpu_reset_early(void); void plat_primary_init_early(void); unsigned long plat_get_aslr_seed(void); unsigned long plat_get_freq(void); #if defined(_CFG_CORE_STACK_PROTECTOR) || defined(CFG_WITH_STACK_CANARIES) /* * plat_get_random_stack_canaries() - Get random values for stack canaries. * @buf: Pointer to the buffer where to store canaries * @ncan: The number of canaries to generate. * @size: The size (in bytes) of each canary. * * This function has a __weak default implementation. */ void plat_get_random_stack_canaries(void *buf, size_t ncan, size_t size); #endif void arm_cl2_config(vaddr_t pl310); void arm_cl2_enable(vaddr_t pl310); #if defined(CFG_BOOT_SECONDARY_REQUEST) void boot_set_core_ns_entry(size_t core_idx, uintptr_t entry, uintptr_t context_id); int boot_core_release(size_t core_idx, paddr_t entry); struct ns_entry_context *boot_core_hpen(void); #endif /* * get_aslr_seed() - return a random seed for core ASLR * * This function has a __weak default implementation. */ unsigned long get_aslr_seed(void); /* Identify non-secure memory regions for dynamic shared memory */ void discover_nsec_memory(void); /* Add reserved memory for static shared memory in the device-tree */ int mark_static_shm_as_reserved(struct dt_descriptor *dt); #endif /* __KERNEL_BOOT_H */ optee_os-4.3.0/core/include/kernel/cache_helpers.h000066400000000000000000000022251464416617300221410ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __KERNEL_CACHE_HELPERS_H #define __KERNEL_CACHE_HELPERS_H #ifndef __ASSEMBLER__ #include #include #endif /* Data Cache set/way op type defines */ #define DCACHE_OP_INV 0x0 #define DCACHE_OP_CLEAN_INV 0x1 #define DCACHE_OP_CLEAN 0x2 #ifndef __ASSEMBLER__ void dcache_cleaninv_range(void *addr, size_t size); void dcache_clean_range(void *addr, size_t size); void dcache_inv_range(void *addr, size_t size); void dcache_clean_range_pou(void *addr, size_t size); void icache_inv_all(void); void icache_inv_range(void *addr, size_t size); void icache_inv_user_range(void *addr, size_t size); void dcache_op_louis(unsigned long op_type); void dcache_op_all(unsigned long op_type); void dcache_op_level1(unsigned long op_type); void dcache_op_level2(unsigned long op_type); void dcache_op_level3(unsigned long op_type); /* * Get system maximum cache line size. */ static inline unsigned int cache_get_max_line_size(void) { return 1 << CFG_MAX_CACHE_LINE_SHIFT; } #endif /*!__ASSEMBLER__*/ #endif /*__KERNEL_CACHE_HELPERS_H*/ optee_os-4.3.0/core/include/kernel/callout.h000066400000000000000000000112601464416617300210160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024, Linaro Limited */ #ifndef __KERNEL_CALLOUT_H #define __KERNEL_CALLOUT_H #include #include #include /* * struct callout - callout reference * @callback: function to be called when a callout expires * @expiry_value: callout expiry time counter value * @period: ticks to next timeout * @link: linked list element * * @callback is called from an interrupt handler so thread resources must * not be used. The main callout service lock is held while @callback is * called so callout_rem() and callout_add() can't be used, but it is safe * to call callout_set_next_timeout() if the call period should be changed. * @callback returns true if it should be called again in @period ticks * or false if the callout should be removed and inactivated. Returning * false from @callback is the equivalent of calling callout_rem() on the * callout reference. */ struct callout { bool (*callback)(struct callout *co); uint64_t expiry_value; uint64_t period; TAILQ_ENTRY(callout) link; }; /* * callout_add() - Add a callout * @co: callout reference * @callback: callback function accociated with the callout * @ms: time to next callout in milliseconds * * Adds a callout to the callout service with an associated callback * function @callback that is to be called in @ms milliseconds. * * If callout_add() is called before callout_service_init() has been called * then it will be called @ms milliseconds after callout_service_init() has * been called. * * The callout structure can reside in global data or on the heap. It's * safe to embed it inside another struct, but it must not be freed until * removed with callout_rem() or equivalent. * * The function takes the main callout service for synchronization so it * can't be called from within a callback function in a callout or there's * deadlock. */ void callout_add(struct callout *co, bool (*callback)(struct callout *co), uint32_t ms); /* * callout_rem() - Remove a callout * @co: callout reference * * Removes a callout previously added to the callout service with * callout_add(). Note that when the callback function in a callout * returns false the callout is also removed. * * It's safe to try to remove a callback even if it isn't active any * longer. Nothing will happen in that case, but it's guaranteed to be * inactive and it's safe to free the memory after callout_rem() has * returned. */ void callout_rem(struct callout *co); /* * callout_set_next_timeout() - set time to next callout * @co: callout reference * @ms: time to next callout in milliseconds * * Updates the @co->ticks field with the new number of ticks based on @ms. * This value is used to when to calculate the time of the next callout * following then one already set. * * Must only be called from @co->callback() when the callout is triggered. */ void callout_set_next_timeout(struct callout *co, uint32_t ms); /* * struct callout_timer_desc - callout timer descriptor * @disable_timeout: disables the timer from triggering an interrupt * @set_next_timeout: sets the next timeout and enables the timer * @ms_to_ticks: converts milliseconds to ticks, the counter value * unit * @get_now: get the current counter value * @is_per_cpu: flag to indicate if this timer is per CPU (true) or * global (false). * * This descriptor provides an abstract timer interface first used by * callout_service_init() and then stored to be used by * callout_service_cb(). * * When @is_per_cpu is true there is one private timer per CPU so * @disable_timeout() and @set_next_timeout() only affects the timer on the * current CPU. If for instance @set_next_timeout() is called on a new CPU * compared to last time the timer on the old CPU will remain unchanged. * Timer interrupts may trigger based on obsolete configuration, the * callout service is expected to handle this gracefully. */ struct callout_timer_desc { void (*disable_timeout)(const struct callout_timer_desc *desc); void (*set_next_timeout)(const struct callout_timer_desc *desc, uint64_t expiry_value); uint64_t (*ms_to_ticks)(const struct callout_timer_desc *desc, uint32_t ms); uint64_t (*get_now)(const struct callout_timer_desc *desc); bool is_per_cpu; }; /* * callout_service_init() - Initialize the callout service * @desc: Pointer to the timer interface * * The callout service is initialized with the supplied timer interface */ void callout_service_init(const struct callout_timer_desc *desc); /* * callout_service_cb() - Callout service callback * * Called from interrupt service function for the timer. */ void callout_service_cb(void); #endif /*__KERNEL_CALLOUT_H*/ optee_os-4.3.0/core/include/kernel/chip_services.h000066400000000000000000000003671464416617300222070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_CHIP_SERVICES_H #define __KERNEL_CHIP_SERVICES_H /* Die ID */ #define FVR_DIE_ID_NUM_REGS 3 #endif optee_os-4.3.0/core/include/kernel/delay.h000066400000000000000000000052301464416617300204510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __KERNEL_DELAY_H #define __KERNEL_DELAY_H #include #include #include #include #ifdef CFG_CORE_HAS_GENERIC_TIMER /* Convert microsecond base delay @us into architecture time tick counts */ static inline uint64_t delay_us2cnt(uint32_t us) { return ((uint64_t)us * (uint64_t)delay_cnt_freq()) / ULL(1000000); } /* Return delay tick counter for a timeout expiration in @us microseconds */ static inline uint64_t timeout_init_us(uint32_t us) { return delay_cnt_read() + delay_us2cnt(us); } /* Check if timeout tick counter @expire from timeout_init_us() has expired */ static inline bool timeout_elapsed(uint64_t expire) { return delay_cnt_read() > expire; } /* * Return the time in microseconds since/until timeout tick counter @expired, * that was initialized with timeout_init_us() or like, has/will expire. * A positive value means the timeout has expired and a negative one it has not. */ int timeout_elapsed_us(uint64_t expire); #endif /*CFG_CORE_HAS_GENERIC_TIMER*/ /* Wait @us microseconds actively polling on architecture timer */ void udelay(uint32_t us); /* Wait @ms milliseconds actively polling on architecture timer */ void mdelay(uint32_t ms); #endif optee_os-4.3.0/core/include/kernel/dt.h000066400000000000000000000313351464416617300177670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2021, Linaro Limited */ #ifndef __KERNEL_DT_H #define __KERNEL_DT_H #include #include #include #include #include #include #include /* * Bitfield to reflect status and secure-status values ("okay", "disabled" * or not present) */ #define DT_STATUS_DISABLED U(0) #define DT_STATUS_OK_NSEC BIT(0) #define DT_STATUS_OK_SEC BIT(1) #define DT_INFO_INVALID_REG ((paddr_t)-1) #define DT_INFO_INVALID_REG_SIZE ((size_t)-1) #define DT_INFO_INVALID_CLOCK -1 #define DT_INFO_INVALID_RESET -1 #define DT_INFO_INVALID_INTERRUPT -1 /* * @status: Bit mask for DT_STATUS_* * @reg: Device register physical base address or DT_INFO_INVALID_REG * @reg_size: Device register size or DT_INFO_INVALID_REG_SIZE * @clock: Device identifier (positive value) or DT_INFO_INVALID_CLOCK * @reset: Device reset identifier (positive value) or DT_INFO_INVALID_CLOCK * @interrupt: Device interrupt identifier (positive value) or * DT_INFO_INVALID_INTERRUPT * @type: IRQ_TYPE_* value parsed from interrupts properties or IRQ_TYPE_NONE if * not present * @prio: interrupt priority parsed from interrupts properties or 0 if not * present */ struct dt_node_info { unsigned int status; paddr_t reg; size_t reg_size; int clock; int reset; int interrupt; uint32_t type; uint32_t prio; }; /* * DT-aware drivers */ struct dt_device_match { const char *compatible; const void *compat_data; }; /* * DT_MAP_AUTO: Uses status properties from device tree to determine mapping. * DT_MAP_SECURE: Force mapping for device to be secure. * DT_MAP_NON_SECURE: Force mapping for device to be non-secure. */ enum dt_map_dev_directive { DT_MAP_AUTO, DT_MAP_SECURE, DT_MAP_NON_SECURE }; /* * struct dt_descriptor - Descriptor of the device tree * @blob: Pointer to the device tree binary * @frag_id: Used ID of fragments for device tree overlay */ struct dt_descriptor { void *blob; #ifdef _CFG_USE_DTB_OVERLAY int frag_id; #endif }; extern uint8_t embedded_secure_dtb[]; #ifdef CFG_DT /* * dt_getprop_as_number() - get a DT property a unsigned number * @fdt: DT base address * @nodeoffset: node offset * @name: property string name * @num: output number read * Return 0 on success and a negative FDT error value on error * * The size of the property determines if it is read as an unsigned 32-bit * or 64-bit integer. */ int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, uint64_t *num); /* * Find a driver that is suitable for the given DT node, that is, with * a matching "compatible" property. * * @fdt: pointer to the device tree * @offs: node offset */ const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs); /* * Map a device into secure or non-secure memory and return the base VA and * the mapping size. The mapping is done with type MEM_AREA_IO_SEC or * MEM_AREA_IO_NSEC, depending on the device status. * If the mapping already exists, the function simply returns the @vbase and * @size information. * * @offs is the offset of the node that describes the device in @fdt. * @base receives the base virtual address corresponding to the base physical * address of the "reg" property * @size receives the size of the mapping * @mapping what kind of mapping is done for memory. * * Returns 0 on success or -1 in case of error. */ int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, enum dt_map_dev_directive mapping); /* * Check whether the node at @offs contains the property with propname or not. * * @offs is the offset of the node that describes the device in @fdt. * @propname is the property that need to check * * Returns true on success or false if no propname. */ bool dt_have_prop(const void *fdt, int offs, const char *propname); /* * Modify or add "status" property to "disabled" * * @fdt reference to the Device Tree * @node is the node offset to modify * * Returns 0 on success or -1 on failure */ int dt_disable_status(void *fdt, int node); /* * Force secure-status = "okay" and status="disabled" for the target node. * * @fdt reference to the Device Tree * @node is the node offset to modify * * Returns 0 on success or -1 on failure */ int dt_enable_secure_status(void *fdt, int node); /* * FDT manipulation functions, not provided by */ /* * Return the base address for the "reg" property of the specified node or * (paddr_t)-1 in case of error */ paddr_t fdt_reg_base_address(const void *fdt, int offs); /* * Return the reg size for the reg property of the specified node or -1 in case * of error */ size_t fdt_reg_size(const void *fdt, int offs); /* * Read the status and secure-status properties into a bitfield. * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled, * otherwise return a combination of DT_STATUS_OK_NSEC and DT_STATUS_OK_SEC. */ int fdt_get_status(const void *fdt, int offs); /* * fdt_fill_device_info - Get generic device info from a node * * This function fills the generic information from a given node. * Currently supports a single base register, a single clock, * a single reset ID line and a single interrupt ID. * Default DT_INFO_* macros are used when the relate property is not found. */ void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, int node); /* * Read cells from a given property of the given node. Any number of 32-bit * cells of the property can be read. Returns 0 on success, or a negative * FDT error value otherwise. */ int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, uint32_t *array, size_t count); /* * Read one cell from a given multi-value property of the given node. * Returns 0 on success, or a negative FDT error value otherwise. */ int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, int index, uint32_t *value); /* * Read one cell from a given property of the given node. * Returns 0 on success, or a negative FDT error value otherwise. */ int fdt_read_uint32(const void *fdt, int node, const char *prop_name, uint32_t *value); /* * Read one cell from a property of a cell or default to a given value * Returns the 32bit cell value or @dflt_value on failure. */ uint32_t fdt_read_uint32_default(const void *fdt, int node, const char *prop_name, uint32_t dflt_value); /* * This function fills reg node info (base & size) with an index. * * Returns 0 on success and a negative FDT error code on failure. */ int fdt_get_reg_props_by_index(const void *fdt, int node, int index, paddr_t *base, size_t *size); /* * This function fills reg node info (base & size) with an index found by * checking the reg-names node. * * Returns 0 on success and a negative FDT error code on failure. */ int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, paddr_t *base, size_t *size); /* * Returns embedded DTB if present, then external DTB if found, * then manifest DTB if found, then NULL. */ void *get_dt(void); /* * get_secure_dt() - returns secure DTB for drivers * * Returns device tree that is considered secure for drivers to use. * * 1. Returns embedded DTB if available, * 2. Secure external DTB if available, * 3. Manifest DTB if available, * 4. If neither then NULL */ void *get_secure_dt(void); /* Returns embedded DTB location if present, otherwise NULL */ void *get_embedded_dt(void); /* Returns true if passed DTB is same as Embedded DTB, otherwise false */ static inline bool is_embedded_dt(void *fdt) { return fdt && fdt == get_embedded_dt(); } /* Returns DTB descriptor of the external DTB if present, otherwise NULL */ struct dt_descriptor *get_external_dt_desc(void); /* * init_external_dt() - Initialize the external DTB located at given address. * @phys_dt: Physical address where the external DTB located. * @dt_sz: Maximum size of the external DTB. * * Initialize the external DTB. * * 1. Add MMU mapping of the external DTB, * 2. Initialize device tree overlay */ void init_external_dt(unsigned long phys_dt, size_t dt_sz); /* Returns external DTB if present, otherwise NULL */ void *get_external_dt(void); /* * add_dt_path_subnode() - Add new child node into a parent node. * @dt: Pointer to a device tree descriptor which has DTB. * @path: Path to the parent node. * @subnode: Name of the child node. * * Returns the offset of the child node in DTB on success or a negative libfdt * error number. */ int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, const char *subnode); /* * add_res_mem_dt_node() - Create "reserved-memory" parent and child nodes. * @dt: Pointer to a device tree descriptor which has DTB. * @name: Name of the child node. * @pa: Physical address of specific reserved memory region. * @size: Size of specific reserved memory region. * * Returns 0 if succeeds, otherwise a negative libfdt error number. */ int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name, paddr_t pa, size_t size); /* * init_manifest_dt() - Initialize the manifest DTB to given address. * @fdt: Physical address where the manifest DTB located. * * Initialize the manifest DTB to physical address */ void init_manifest_dt(void *fdt); /* * reinit_manifest_dt() - Reinitialize the manifest DTB * * Add MMU mapping of the manifest DTB and initialize device tree overlay */ void reinit_manifest_dt(void); /* Returns TOS_FW_CONFIG DTB or SP manifest DTB if present, otherwise NULL */ void *get_manifest_dt(void); #else /* !CFG_DT */ static inline const struct dt_driver *dt_find_compatible_driver( const void *fdt __unused, int offs __unused) { return NULL; } static inline int dt_map_dev(const void *fdt __unused, int offs __unused, vaddr_t *vbase __unused, size_t *size __unused, enum dt_map_dev_directive mapping __unused) { return -1; } static inline paddr_t fdt_reg_base_address(const void *fdt __unused, int offs __unused) { return (paddr_t)-1; } static inline size_t fdt_reg_size(const void *fdt __unused, int offs __unused) { return (size_t)-1; } static inline int fdt_get_status(const void *fdt __unused, int offs __unused) { return -1; } __noreturn static inline void fdt_fill_device_info(const void *fdt __unused, struct dt_node_info *info __unused, int node __unused) { panic(); } static inline int fdt_read_uint32_array(const void *fdt __unused, int node __unused, const char *prop_name __unused, uint32_t *array __unused, size_t count __unused) { return -1; } static inline int fdt_read_uint32(const void *fdt __unused, int node __unused, const char *prop_name __unused, uint32_t *value __unused) { return -1; } static inline uint32_t fdt_read_uint32_default(const void *fdt __unused, int node __unused, const char *prop_name __unused, uint32_t dflt_value __unused) { return dflt_value; } static inline int fdt_read_uint32_index(const void *fdt __unused, int node __unused, const char *prop_name __unused, int index __unused, uint32_t *value __unused) { return -1; } static inline int fdt_get_reg_props_by_index(const void *fdt __unused, int node __unused, int index __unused, paddr_t *base __unused, size_t *size __unused) { return -1; } static inline int fdt_get_reg_props_by_name(const void *fdt __unused, int node __unused, const char *name __unused, paddr_t *base __unused, size_t *size __unused) { return -1; } static inline int dt_getprop_as_number(const void *fdt __unused, int nodeoffset __unused, const char *name __unused, uint64_t *num __unused) { return -1; } static inline void *get_dt(void) { return NULL; } static inline void *get_secure_dt(void) { return NULL; } static inline void *get_embedded_dt(void) { return NULL; } static inline bool is_embedded_dt(void *fdt __unused) { return false; } static inline struct dt_descriptor *get_external_dt_desc(void) { return NULL; } static inline void init_external_dt(unsigned long phys_dt __unused, size_t dt_sz __unused) { } static inline void *get_external_dt(void) { return NULL; } static inline int add_dt_path_subnode(struct dt_descriptor *dt __unused, const char *path __unused, const char *subnode __unused) { return -1; } static inline int add_res_mem_dt_node(struct dt_descriptor *dt __unused, const char *name __unused, paddr_t pa __unused, size_t size __unused) { return -1; } static inline void init_manifest_dt(void *fdt __unused) { } static inline void reinit_manifest_dt(void) { } static inline void *get_manifest_dt(void) { return NULL; } #endif /* !CFG_DT */ #endif /* __KERNEL_DT_H */ optee_os-4.3.0/core/include/kernel/dt_driver.h000066400000000000000000000226331464416617300213430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Linaro Limited * Copyright (c) 2021, Bootlin * Copyright (c) 2021, STMicroelectronics */ #ifndef __KERNEL_DT_DRIVER_H #define __KERNEL_DT_DRIVER_H #include #include #include #include /* * Type indentifiers for registered device drivers consumer can query * * DT_DRIVER_NOTYPE Generic type for when no generic FDT parsing is supported * DT_DRIVER_UART UART driver currently designed for console means * DT_DRIVER_CLK Clock controller using generic clock DT bindings * DT_DRIVER_RSTCTRL Reset controller using generic reset DT bindings * DT_DRIVER_I2C I2C bus controller using generic I2C bus DT bindings * DT_DRIVER_GPIO GPIO controller using generic GPIO DT bindings * DT_DRIVER_PINCTRL Pin controller using generic reset DT bindings * DT_DRIVER_INTERRUPT Interrupt controller using generic DT bindings * DT_DRIVER_REGULATOR Voltage regulator controller using generic DT bindings * DT_DRIVER_NVMEM NVMEM controller using generic NVMEM DT bindings * DT_DRIVER_FIREWALL Firewall controller using generic DT bindings */ enum dt_driver_type { DT_DRIVER_NOTYPE, DT_DRIVER_UART, DT_DRIVER_CLK, DT_DRIVER_RSTCTRL, DT_DRIVER_I2C, DT_DRIVER_GPIO, DT_DRIVER_PINCTRL, DT_DRIVER_INTERRUPT, DT_DRIVER_REGULATOR, DT_DRIVER_NVMEM, DT_DRIVER_FIREWALL, }; /* * dt_driver_probe_func - Callback probe function for a driver. * * @fdt: FDT base address * @nodeoffset: Offset of the node in the FDT * @compat_data: Data registered for the compatible that probed the device * * Return TEE_SUCCESS on successful probe, * TEE_ERROR_DEFER_DRIVER_INIT if probe must be deferred * TEE_ERROR_ITEM_NOT_FOUND when no driver matched node's compatible string * Any other TEE_ERROR_* compliant code. */ typedef TEE_Result (*dt_driver_probe_func)(const void *fdt, int nodeoffset, const void *compat_data); /* * Driver instance registered to be probed on compatible node found in the DT. * * @name: Driver name * @type: Drive type * @match_table: Compatible matching identifiers, null terminated * @driver: Driver private reference or NULL * @probe: Probe callback (see dt_driver_probe_func) or NULL */ struct dt_driver { const char *name; enum dt_driver_type type; const struct dt_device_match *match_table; /* null-terminated */ const void *driver; TEE_Result (*probe)(const void *fdt, int node, const void *compat_data); }; #define DEFINE_DT_DRIVER(name) \ SCATTERED_ARRAY_DEFINE_PG_ITEM(dt_drivers, struct dt_driver) #define for_each_dt_driver(drv) \ for (drv = SCATTERED_ARRAY_BEGIN(dt_drivers, struct dt_driver); \ drv < SCATTERED_ARRAY_END(dt_drivers, struct dt_driver); \ drv++) /* Opaque reference to DT driver device provider instance */ struct dt_driver_provider; /** * struct dt_pargs - Devicetree phandle arguments * @fdt: Device-tree to work on * @phandle_node: Node pointed by the specifier phandle * @args_count: Count of cells for the device * @args: Device consumer specifiers */ struct dt_pargs { const void *fdt; int phandle_node; int args_count; uint32_t args[]; }; /* * get_of_device_func - Callback function for returning a driver private * instance based on a FDT phandle with possible arguments and the * registered dt_driver private data reference. * * @parg: phandle argument(s) referencing the device in the FDT. * @data: driver private data registered in struct dt_driver. * @device_ref: output device reference upon success, e.g. a struct clk * pointer for a clock driver. * * Return code: * TEE_SUCCESS in case of success * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized * Any TEE_Result compliant code in case of error. */ typedef TEE_Result (*get_of_device_func)(struct dt_pargs *parg, void *data, void *device_ref); /** * dt_driver_register_provider - Register a driver provider * * @fdt: Device tree to work on * @nodeoffset: Node offset in the FDT * @get_of_device: Function to match the devicetree with a device instance * @data: Data which will be passed to the @get_of_device callback * @type: Driver type * * @get_of_device returns a void *. Driver provider is expected to * include a shim helper to cast to device reference into provider driver * target structure reference (e.g (struct clk *) for clock devices). */ TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, get_of_device_func get_of_device, void *data, enum dt_driver_type type); /* * dt_driver_device_from_node_idx_prop - Return a device instance based on a * property name and FDT information * * @prop_name: DT property name, e.g. "clocks" for clock resources * @fdt: FDT base address * @nodeoffset: node offset in the FDT * @prop_idx: index of the phandle data in the property * @type: Driver type * @device_ref: output device opaque reference upon support, for example * a struct clk pointer for a clock driver. * Return code: * TEE_SUCCESS in case of success, * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized * TEE_ERROR_ITEM_NOT_FOUND if @prop_name does not match a property's name * or @prop_idx does not match any index in @prop_name phandle list * Any TEE_Result compliant code in case of error. */ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, const void *fdt, int nodeoffset, unsigned int prop_idx, enum dt_driver_type type, void *device_ref); /* * dt_driver_device_from_parent - Return a device instance based on the parent. * This is mainly used for the devices that are children of a controller * such as I2C, SPI and so on. * * @fdt: FDT base address * @nodeoffset: node offset in the FDT * @type: Driver type * @device_ref: output device opaque reference upon success, for example * a struct i2c_dev pointer for a I2C bus driver * * Return code: * TEE_SUCCESS in case of success, * TEE_ERROR_DEFER_DRIVER_INIT if device driver is not yet initialized * Any TEE_Result compliant code in case of error. */ TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, enum dt_driver_type type, void *device_ref); /* * dt_driver_device_from_node_idx_prop_phandle() - Same as * dt_driver_device_from_node_idx_prop() but phandle is not the first * cells in property @prop_name but is passed as an argument. * * This function is used for DT bindings as "interrupts" property where the * property carries the interrupt information but not the interrupt controller * phandle which is found in a specific property (here "interrupt-parent"). */ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, const void *fdt, int nodeoffs, unsigned int prop_index, enum dt_driver_type type, uint32_t phandle, void *device_ref); /* * dt_driver_get_crypto() - Request crypto support for driver initialization * * Return TEE_SUCCESS if cryptography services are initialized, otherwise return * TEE_ERROR_DEFER_DRIVER_INIT. */ TEE_Result dt_driver_get_crypto(void); #ifdef CFG_DT /* Inform DT driver probe sequence that core crypto support is initialized */ void dt_driver_crypt_init_complete(void); #else static inline void dt_driver_crypt_init_complete(void) {} #endif /* * Return driver provider reference from its node offset value in the FDT */ struct dt_driver_provider * dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type); /* * Return driver provider reference from its phandle value in the FDT */ struct dt_driver_provider * dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type); /* * Return number cells used for phandle arguments by a driver provider */ unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv); /* * Return provider private data registered by dt_driver_register_provider() */ void *dt_driver_provider_priv_data(struct dt_driver_provider *prv); /* * dt_driver_probe_device_by_node - Probe matching driver to create a device * from a FDT node * * @fdt: FDT base address * @nodeoffset: Node byte offset from FDT base * @type: Target driver to match or DT_DRIVER_ANY * * Read the dt_driver database. Compatible list is looked up in the order * of the FDT "compatible" property list. @type can be used to probe only * specific drivers. * */ TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, enum dt_driver_type type); /* * Get cells count of a device node given its dt_driver type * * @fdt: FDT base address * @nodeoffset: Node offset on the FDT for the device * @type: One of the supported DT_DRIVER_* value. * * Return a positive cell count value (>= 0) or a negative FDT_ error code */ int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, enum dt_driver_type type); /* * Called by bus like nodes to propose a node for dt_driver probing * * @fdt: FDT base address * @nodeoffset: Node offset on the FDT for the device */ TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int nodeoffset); #ifdef CFG_DT_DRIVER_EMBEDDED_TEST /* * Return TEE_ERROR_NOT_IMPLEMENTED if test are not implemented * otherwise return TEE_ERROR_GENERIC if some test has failed * otherwise return TEE_SUCCESS (tests succeed or skipped) */ TEE_Result dt_driver_test_status(void); #else static inline TEE_Result dt_driver_test_status(void) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #endif /* __KERNEL_DT_DRIVER_H */ optee_os-4.3.0/core/include/kernel/early_ta.h000066400000000000000000000006521464416617300211560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, 2020, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #ifndef __KERNEL_EARLY_TA_H #define __KERNEL_EARLY_TA_H #include #include #include #include #define for_each_early_ta(_ta) \ SCATTERED_ARRAY_FOREACH(_ta, early_tas, struct embedded_ts) #endif /* __KERNEL_EARLY_TA_H */ optee_os-4.3.0/core/include/kernel/embedded_ts.h000066400000000000000000000017761464416617300216250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #ifndef __KERNEL_EMBEDDED_TS_H #define __KERNEL_EMBEDDED_TS_H #include #include #include #include #include struct embedded_ts { uint32_t flags; TEE_UUID uuid; uint32_t size; uint32_t uncompressed_size; /* 0: not compressed */ const uint8_t *ts; /* @size bytes */ }; struct ts_store_handle; TEE_Result emb_ts_read(struct ts_store_handle *h, void *data_core, void *data_user, size_t len); void emb_ts_close(struct ts_store_handle *h); TEE_Result emb_ts_open(const TEE_UUID *uuid, struct ts_store_handle **h, const struct embedded_ts* (*find_ts) (const TEE_UUID *uuid)); TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size); TEE_Result emb_ts_get_tag(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len); #endif /* __KERNEL_EMBEDDED_TS_H */ optee_os-4.3.0/core/include/kernel/handle.h000066400000000000000000000026141464416617300206110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef __KERNEL_HANDLE_H #define __KERNEL_HANDLE_H #include #include struct handle_db { void **ptrs; size_t max_ptrs; }; #define HANDLE_DB_INITIALIZER { NULL, 0 } /* * Frees all internal data structures of the database, but does not free * the db pointer. The database is safe to reuse after it's destroyed, it * will just be empty again. If ptr_destructor is non-null it will be * called for each registered pointer before the database is cleared. */ void handle_db_destroy(struct handle_db *db, void (*ptr_destructor)(void *ptr)); /* Checks if the associated pointers of all handles in the database are NULL. */ bool handle_db_is_empty(struct handle_db *db); /* * Allocates a new handle and assigns the supplied pointer to it, * ptr must not be NULL. * The function returns * >= 0 on success and * -1 on failure */ int handle_get(struct handle_db *db, void *ptr); /* * Deallocates a handle. Returns the assiciated pointer of the handle * if the handle was valid or NULL if it's invalid. */ void *handle_put(struct handle_db *db, int handle); /* * Returns the assiciated pointer of the handle if the handle is a valid * handle. * Returns NULL on failure. */ void *handle_lookup(struct handle_db *db, int handle); #endif /*__KERNEL_HANDLE_H*/ optee_os-4.3.0/core/include/kernel/huk_subkey.h000066400000000000000000000040441464416617300215260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef __KERNEL_HUK_SUBKEY_H #define __KERNEL_HUK_SUBKEY_H #include #include #include /* * enum huk_subkey_usage - subkey usage identifier * @HUK_SUBKEY_RPMB: RPMB key * @HUK_SUBKEY_SSK: Secure Storage key * @HUK_SUBKEY_DIE_ID: Representing the die ID * @HUK_SUBKEY_UNIQUE_TA: TA unique key * @HUK_SUBKEY_TA_ENC: TA encryption key * @HUK_SUBKEY_SE050: SCP03 set of encryption keys * * Add more identifiers as needed, be careful to not change the already * assigned numbers as that will affect the derived subkey. */ enum huk_subkey_usage { /* * All IDs are explicitly assigned to make it easier to keep then * constant. */ HUK_SUBKEY_RPMB = 0, HUK_SUBKEY_SSK = 1, HUK_SUBKEY_DIE_ID = 2, HUK_SUBKEY_UNIQUE_TA = 3, HUK_SUBKEY_TA_ENC = 4, HUK_SUBKEY_SE050 = 5, }; #define HUK_SUBKEY_MAX_LEN TEE_SHA256_HASH_SIZE /* * huk_subkey_derive() - Derive a subkey from the hardware unique key * @usage: Intended usage of the subkey * @const_data: Constant data to generate different subkeys with * the same usage * @const_data_len: Length of constant data * @subkey: Generated subkey * @subkey_len: Required size of the subkey, sizes larger than * HUK_SUBKEY_MAX_LEN are not accepted. * * Returns a subkey derived from the hardware unique key. Given the same * input the same subkey is returned each time. * Function huk_subkey_derive() is __weak to allow platform specific * implementation. * __huk_subkey_derive() implements the default behavior of HUK derivation. * * Return TEE_SUCCESS on success or an error code on failure. */ TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, const void *const_data, size_t const_data_len, uint8_t *subkey, size_t subkey_len); TEE_Result __huk_subkey_derive(enum huk_subkey_usage usage, const void *const_data, size_t const_data_len, uint8_t *subkey, size_t subkey_len); #endif /*__KERNEL_HUK_SUBKEY_H*/ optee_os-4.3.0/core/include/kernel/interrupt.h000066400000000000000000000423751464416617300214220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2019, Linaro Limited */ #ifndef __KERNEL_INTERRUPT_H #define __KERNEL_INTERRUPT_H #include #include #include #include #include #include #include #define ITRF_TRIGGER_LEVEL BIT(0) #define ITRF_SHARED BIT(1) /* Forward the interrupt only to the current CPU */ #define ITR_CPU_MASK_TO_THIS_CPU BIT(31) /* Forward the interrupt to all CPUs except the current CPU */ #define ITR_CPU_MASK_TO_OTHER_CPUS BIT(30) struct itr_handler; /* * struct itr_chip - Interrupt controller * * @ops Operation callback functions * @name Controller name, for debug purpose * @handlers Registered handlers list head * @dt_get_irq Device tree node parsing function */ struct itr_chip { const struct itr_ops *ops; const char *name; SLIST_HEAD(, itr_handler) handlers; /* * dt_get_irq - parse a device tree interrupt property * * @properties raw interrupt property from device tree * @count number of elements in @properties * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) * or IRQ_TYPE_NONE if unknown * @prio If not NULL, output interrupt priority value or 0 if unknown */ int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, uint32_t *prio); }; /* * struct itr_ops - Interrupt controller operations * @add Register and configure an interrupt * @enable Enable an interrupt * @disable Disable an interrupt * @mask Mask an interrupt, may be called from an interrupt context * @unmask Unmask an interrupt, may be called from an interrupt context * @raise_pi Raise per-cpu interrupt or NULL if not applicable * @raise_sgi Raise a SGI or NULL if not applicable to that controller * @set_affinity Set interrupt/cpu affinity or NULL if not applicable * * Handlers @enable, @disable, @mask, @unmask and @add are mandated. Handlers * @mask and @unmask have unpaged memory contrainsts. See itr_chip_is_valid(). */ struct itr_ops { void (*add)(struct itr_chip *chip, size_t it, uint32_t type, uint32_t prio); void (*enable)(struct itr_chip *chip, size_t it); void (*disable)(struct itr_chip *chip, size_t it); void (*mask)(struct itr_chip *chip, size_t it); void (*unmask)(struct itr_chip *chip, size_t it); void (*raise_pi)(struct itr_chip *chip, size_t it); void (*raise_sgi)(struct itr_chip *chip, size_t it, uint32_t cpu_mask); void (*set_affinity)(struct itr_chip *chip, size_t it, uint8_t cpu_mask); }; /* * struct itr_desc - Interrupt description * @chip Interrupt controller reference * @itr_num Interrupt number * * This struct is used for binding interrupt device data between * drivers when using DT_DRIVERS means. See itr_dt_get_func type * definition. */ struct itr_desc { struct itr_chip *chip; size_t itr_num; }; /* Interrupt handler return value */ enum itr_return { ITRR_NONE, ITRR_HANDLED, }; /* Interrupt handler signature */ typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); /* * struct itr_handler - Interrupt handler reference * @it Interrupt number * @flags Property bit flags (ITRF_*) or 0 * @data Private data for that interrupt handler * @chip Interrupt controller chip device * @link Reference in controller handler list */ struct itr_handler { size_t it; uint32_t flags; itr_handler_t handler; void *data; struct itr_chip *chip; SLIST_ENTRY(itr_handler) link; }; #define ITR_HANDLER(_chip, _itr_num, _flags, _fn, _priv) \ ((struct itr_handler){ \ .chip = (_chip), .it = (_itr_num), .flags = (_flags), \ .handler = (_fn), .data = (_priv), \ }) /* * Return true only if interrupt chip provides required handlers * @chip: Interrupt controller reference */ static inline bool itr_chip_is_valid(struct itr_chip *chip) { return chip && is_unpaged(chip) && chip->ops && is_unpaged((void *)chip->ops) && chip->ops->mask && is_unpaged(chip->ops->mask) && chip->ops->unmask && is_unpaged(chip->ops->unmask) && chip->ops->enable && chip->ops->disable && chip->ops->add; } /* * Initialise an interrupt controller handle * @chip Interrupt controller */ TEE_Result itr_chip_init(struct itr_chip *chip); /* * Initialise main interrupt controller driver * @data Main controller main data reference to register */ void interrupt_main_init(struct itr_chip *data); /* Retrieve main interrupt controller reference */ struct itr_chip *interrupt_get_main_chip(void); /* Retrieve main interrupt controller reference, or NULL on failure */ struct itr_chip *interrupt_get_main_chip_may_fail(void); #ifdef CFG_DT /* * Get the DT interrupt property at @node. In the DT an interrupt property can * specify additional information which can be retrieved with @type and @prio. * * @fdt reference to the Device Tree * @node is the node offset to read the interrupt property from * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property * or IRQ_TYPE_NONE if not. Can be NULL if not needed * @prio interrupt priority if specified by interrupt property or 0 if not. Can * be NULL if not needed * * Returns the interrupt number if value >= 0 * otherwise DT_INFO_INVALID_INTERRUPT */ int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, uint32_t *prio); /* * Get the DT interrupt property at @node */ static inline int dt_get_irq(const void *fdt, int node) { return dt_get_irq_type_prio(fdt, node, NULL, NULL); } #endif /* * __weak overridable function which is called when a secure interrupt is * received. The default function calls panic() immediately, platforms which * expects to receive secure interrupts should override this function. */ void interrupt_main_handler(void); /* * Interrupt controller chip API functions */ /* * interrupt_call_handlers() - Call registered handlers for an interrupt * @chip Interrupt controller * @itr_num Interrupt number * * This function is called from an interrupt context by a primary interrupt * handler. This function calls the handlers registered for that interrupt. * If interrupt is not handled, it is masked. */ void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); /* * interrupt_mask() - Mask an interrupt * @chip Interrupt controller * @itr_num Interrupt number * * This function may be called in interrupt context */ static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) { chip->ops->mask(chip, itr_num); } /* * interrupt_unmask() - Unmask an interrupt * @chip Interrupt controller * @itr_num Interrupt number * * This function may be called in interrupt context */ static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) { chip->ops->unmask(chip, itr_num); } /* * interrupt_enable() - Enable an interrupt * @chip Interrupt controller * @itr_num Interrupt number */ static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) { chip->ops->enable(chip, itr_num); } /* * interrupt_disable() - Disable an interrupt * @chip Interrupt controller * @itr_num Interrupt number */ static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) { chip->ops->disable(chip, itr_num); } /* * interrupt_can_raise_pi() - Return whether controller embeds raise_pi * @chip Interrupt controller */ static inline bool interrupt_can_raise_pi(struct itr_chip *chip) { return chip->ops->raise_pi; } /* * interrupt_can_raise_sgi() - Return whether controller embeds raise_sgi * @chip Interrupt controller */ static inline bool interrupt_can_raise_sgi(struct itr_chip *chip) { return chip->ops->raise_sgi; } /* * interrupt_can_set_affinity() - Return whether controller embeds set_affinity * @chip Interrupt controller */ static inline bool interrupt_can_set_affinity(struct itr_chip *chip) { return chip->ops->set_affinity; } /* * interrupt_raise_pi() - Raise a peripheral interrupt of a controller * @chip Interrupt controller * @itr_num Interrupt number to raise */ static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) { assert(interrupt_can_raise_pi(chip)); chip->ops->raise_pi(chip, itr_num); } /* * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller * @chip Interrupt controller * @itr_num Interrupt number to raise * @cpu_mask: A bitfield of CPUs to forward the interrupt to, unless * ITR_CPU_MASK_TO_THIS_CPU or ITR_CPU_MASK_TO_OTHER_CPUS * (mutually exclusive) are set. */ static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, uint32_t cpu_mask) { assert(interrupt_can_raise_sgi(chip)); chip->ops->raise_sgi(chip, itr_num, cpu_mask); } /* * interrupt_set_affinity() - Set CPU affinity for a controller interrupt * @chip Interrupt controller * @itr_num Interrupt number to raise * @cpu_mask Mask of the CPUs targeted by the interrupt */ static inline void interrupt_set_affinity(struct itr_chip *chip, size_t itr_num, uint8_t cpu_mask) { assert(interrupt_can_set_affinity(chip)); chip->ops->set_affinity(chip, itr_num, cpu_mask); } /* * interrupt_configure() - Configure an interrupt in an interrupt controller * @chip Interrupt controller * @itr_num Interrupt number * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE * @prio Interrupt priority or 0 * * Interrupt consumers that get their interrupt from the DT do not need to * call interrupt_configure() since the interrupt configuration has already * been done by interrupt controller based on the DT bidings. */ TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, uint32_t type, uint32_t prio); /* * interrupt_add_and_configure_handler() - Register and configure a handler * @hdl Interrupt handler to register * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE * @prio Interrupt priority or 0 */ TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, uint32_t type, uint32_t prio); /* * interrupt_add_handler() - Register an interrupt handler * @hdl Interrupt handler to register * * This helper function assumes interrupt type is set to IRQ_TYPE_NONE * and interrupt priority to 0. */ static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) { return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); } /* * interrupt_create_handler() - Allocate/register an interrupt callback handler * @itr_chip Interrupt chip obtained from dt_get_interrupt_by_*() * @itr_num Interrupt number obtained from dt_get_interrupt_by_*() * @callback Callback handler function * @priv Private dat to pssa to @callback * @flags INTERRUPT_FLAGS_* or 0 * @out_hdl Output allocated and registered handler or NULL * * This function differs from interrupt_add_handler() in that the * interrupt is not reconfigured. interrupt_create_handler() expects * @itr_desc was obtained from a call to dt_get_interrupt_by_index() * or dt_get_interrupt_by_name(). That call configured the interrupt. */ TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, itr_handler_t callback, void *priv, uint32_t flags, struct itr_handler **out_hdl); /* * interrupt_add_handler_with_chip() - Register an interrupt handler providing * the interrupt chip reference in specific argument @chip. * @chip Interrupt controller * @h Interrupt handler to register */ static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, struct itr_handler *h) { h->chip = chip; return interrupt_add_handler(h); } /* * interrupt_remove_handler() - Remove a registered interrupt handler * @hdl Interrupt handler to remove * * This function is the counterpart of interrupt_add_handler(). * This function may panic on non-NULL invalid @hdl reference. */ void interrupt_remove_handler(struct itr_handler *hdl); /* * interrupt_alloc_add_conf_handler() - Allocate, configure, register a handler * @chip Interrupt controller * @itr_num Interrupt number * @handler Interrupt handler to register * @flags Bitmask flag ITRF_* * @data Private data reference passed to @handler * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE * @prio Interrupt priority or 0 * @out_hdl NULL or output pointer to allocated struct itr_handler */ TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, size_t it_num, itr_handler_t handler, uint32_t flags, void *data, uint32_t type, uint32_t prio, struct itr_handler **out_hdl); /* * interrupt_alloc_add_handler() - Allocate and register an interrupt handler * @chip Interrupt controller * @itr_num Interrupt number * @handler Interrupt handler to register * @flags Bitmask flag ITRF_* * @data Private data reference passed to @handler * @out_hdl NULL or output pointer to allocated struct itr_handler */ static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, size_t it_num, itr_handler_t handler, uint32_t flags, void *data, struct itr_handler **hdl) { return interrupt_alloc_add_conf_handler(chip, it_num, handler, flags, data, IRQ_TYPE_NONE, 0, hdl); } /* * interrupt_remove_free_handler() - Remove/free a registered interrupt handler * @hdl Interrupt handler to remove and free * * This function is the counterpart of interrupt_alloc_add_handler() * and interrupt_alloc_add_conf_handler(). * This function may panic on non-NULL invalid @hdl reference. */ void interrupt_remove_free_handler(struct itr_handler *hdl); /* * itr_dt_get_func - Typedef of function to get an interrupt in DT node * * @args Reference to phandle arguments * @data Pointer to data given at interrupt_register_provider() call * @itr_desc_p Pointer to the struct itr_desc to fill * Return TEE_SUCCESS in case of success. * Return TEE_ERROR_DEFER_DRIVER_INIT if controller is not initialized. * Return another TEE_Result code otherwise. * * Upon success, the interrupt is configured and consumer can add a handler * function to the interrupt. Yet, the interrupt is not enabled until consumer * calls interrupt_enable(). */ typedef TEE_Result (*itr_dt_get_func)(struct dt_pargs *args, void *data, struct itr_desc *itr_desc_p); #ifdef CFG_DT /** * interrupt_register_provider() - Register an interrupt provider * * @fdt Device tree to work on * @node Node offset of the interrupt controller in the DT * @dt_get_itr Callback to match the devicetree interrupt reference with * @data Data which will be passed to the get_dt_its callback */ TEE_Result interrupt_register_provider(const void *fdt, int node, itr_dt_get_func dt_get_itr, void *data); /** * interrupt_dt_get_by_index() - Get an interrupt from DT by interrupt index * * Interrupt index (@index) refers to the index of the target interrupt to be * retrieved as DT binding property "interrupts" may define several * interrupts. * * @fdt Device tree to work on * @node Node offset of the subnode containing interrupt(s) references * @index Index in "interrupts" or "interrupts-extended" property list * @chip Output interrupt controller reference upon success * @itr_num Output interrupt number upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt * Return any other TEE_Result compliant code in case of error */ TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, unsigned int index, struct itr_chip **chip, size_t *itr_num); /** * interrupt_dt_get_by_name() - Get an interrupt from DT by interrupt name * * @fdt Device tree to work on * @node Node offset of the subnode containing interrupt(s) references * @name Name identifier used in "interrupt-names" property * @chip Output interrupt controller reference upon success * @itr_num Output interrupt number upon success * * Return TEE_SUCCESS in case of success * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt * Return any other TEE_Result compliant code in case of error */ TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, struct itr_chip **chip, size_t *itr_num); #else static inline TEE_Result interrupt_register_provider(const void *dt __unused, int node __unused, itr_dt_get_func f __unused, void *data __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result interrupt_dt_get_by_index(const void *fdt __unused, int node __unused, unsigned int index __unused, struct itr_chip **c __unused, size_t *itr_num __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused, int node __unused, const char *name __unused, struct itr_chip **ch __unused, size_t *itr_num __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif /*CFG_DT*/ /* * Helper function for when caller retrieves the first interrupt defined * in "interrupts" or "interrupts-extended" DT binding property list. */ static inline TEE_Result interrupt_dt_get(const void *fdt, int node, struct itr_chip **chip, size_t *itr_num) { return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num); } #endif /*__KERNEL_INTERRUPT_H*/ optee_os-4.3.0/core/include/kernel/ldelf_loader.h000066400000000000000000000014271464416617300217730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Arm Limited */ #include #include #include #ifndef __KERNEL_LDELF_LOADER_H #define __KERNEL_LDELF_LOADER_H TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx); TEE_Result ldelf_init_with_ldelf(struct ts_session *sess, struct user_mode_ctx *uctx); TEE_Result ldelf_dump_state(struct user_mode_ctx *uctx); TEE_Result ldelf_dump_ftrace(struct user_mode_ctx *uctx, void *buf, size_t *blen); TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid, uint32_t flags); TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, const char *sym, size_t symlen, vaddr_t *val); #endif /* __KERNEL_LDELF_LOADER_H */ optee_os-4.3.0/core/include/kernel/ldelf_syscalls.h000066400000000000000000000027231464416617300223620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2019, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #ifndef __KERNEL_LDELF_SYSCALLS_H #define __KERNEL_LDELF_SYSCALLS_H struct system_ctx { struct handle_db db; const struct ts_store_ops *store_op; }; TEE_Result ldelf_syscall_map_zi(vaddr_t *va, size_t num_bytes, size_t pad_begin, size_t pad_end, unsigned long flags); TEE_Result ldelf_syscall_unmap(vaddr_t va, size_t num_bytes); TEE_Result ldelf_syscall_open_bin(const TEE_UUID *uuid, size_t uuid_size, uint32_t *handle); TEE_Result ldelf_syscall_close_bin(unsigned long handle); TEE_Result ldelf_syscall_map_bin(vaddr_t *va, size_t num_bytes, unsigned long handle, size_t offs_bytes, size_t pad_begin, size_t pad_end, unsigned long flags); TEE_Result ldelf_syscall_copy_from_bin(void *dst, size_t offs, size_t num_bytes, unsigned long handle); TEE_Result ldelf_syscall_set_prot(unsigned long va, size_t num_bytes, unsigned long flags); TEE_Result ldelf_syscall_remap(unsigned long old_va, vaddr_t *new_va, size_t num_bytes, size_t pad_begin, size_t pad_end); TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes); void ldelf_sess_cleanup(struct ts_session *sess); #endif /* __KERNEL_LDELF_SYSCALLS_H */ optee_os-4.3.0/core/include/kernel/linker.h000066400000000000000000000077701464416617300206520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __KERNEL_LINKER_H #define __KERNEL_LINKER_H #include #include /* * Symbols exported by the link script. */ #ifdef ARM32 /* * These addresses will be the start or end of the exception binary search * index table (.ARM.exidx section) */ extern const uint8_t __exidx_start[]; extern const uint8_t __exidx_end[]; extern const uint8_t __extab_start[]; extern const uint8_t __extab_end[]; #endif #define VCORE_UNPG_RX_PA ((unsigned long)__vcore_unpg_rx_start) #define VCORE_UNPG_RX_SZ ((size_t)(__vcore_unpg_rx_end - \ __vcore_unpg_rx_start)) #define VCORE_UNPG_RO_PA ((unsigned long)__vcore_unpg_ro_start) #define VCORE_UNPG_RO_SZ ((size_t)(__vcore_unpg_ro_end - \ __vcore_unpg_ro_start)) #define VCORE_UNPG_RW_PA ((unsigned long)__vcore_unpg_rw_start) #define VCORE_UNPG_RW_SZ ((size_t)(__vcore_unpg_rw_end - \ __vcore_unpg_rw_start)) #define VCORE_NEX_RW_PA ((unsigned long)__vcore_nex_rw_start) #define VCORE_NEX_RW_SZ ((size_t)(__vcore_nex_rw_end - \ __vcore_nex_rw_start)) #define VCORE_INIT_RX_PA ((unsigned long)__vcore_init_rx_start) #define VCORE_INIT_RX_SZ ((size_t)(__vcore_init_rx_end - \ __vcore_init_rx_start)) #define VCORE_INIT_RO_PA ((unsigned long)__vcore_init_ro_start) #define VCORE_INIT_RO_SZ ((size_t)(__vcore_init_ro_end - \ __vcore_init_ro_start)) #define VCORE_START_VA ((vaddr_t)__text_start) #define EMIT_SECTION_INFO_SYMBOLS(section_name) \ extern const uint8_t __vcore_ ## section_name ## _start[]; \ extern const uint8_t __vcore_ ## section_name ## _end[]; \ extern const uint8_t __vcore_ ## section_name ## _size[] EMIT_SECTION_INFO_SYMBOLS(unpg_rx); EMIT_SECTION_INFO_SYMBOLS(unpg_ro); EMIT_SECTION_INFO_SYMBOLS(unpg_rw); EMIT_SECTION_INFO_SYMBOLS(nex_rw); EMIT_SECTION_INFO_SYMBOLS(init_ro); EMIT_SECTION_INFO_SYMBOLS(init_rx); #undef EMIT_SECTION_INFO_SYMBOLS extern const uint8_t __text_start[]; extern const uint8_t __text_data_start[]; extern const uint8_t __text_data_end[]; extern const uint8_t __text_end[]; extern const uint8_t __end[]; extern const uint8_t __identity_map_init_start[]; extern const uint8_t __identity_map_init_end[]; extern uint8_t __data_start[]; extern const uint8_t __data_end[]; extern const uint8_t __rodata_start[]; extern const uint8_t __rodata_end[]; extern const uint8_t __bss_start[]; extern const uint8_t __bss_end[]; extern const uint8_t __nozi_start[]; extern const uint8_t __nozi_end[]; extern const uint8_t __nozi_stack_start[]; extern const uint8_t __nozi_stack_end[]; extern const uint8_t __init_start[]; extern const uint8_t __init_end[]; extern uint8_t __heap1_start[]; extern const uint8_t __heap1_end[]; extern uint8_t __heap2_start[]; extern const uint8_t __heap2_end[]; extern uint8_t __nex_heap_start[]; extern const uint8_t __nex_heap_end[]; extern const uint8_t __pageable_part_start[]; extern const uint8_t __pageable_part_end[]; extern const uint8_t __pageable_start[]; extern const uint8_t __pageable_end[]; extern const uint8_t __rodata_init_start[]; extern const uint8_t __rodata_init_end[]; extern const uint8_t __rodata_pageable_start[]; extern const uint8_t __rodata_pageable_end[]; extern const uint8_t __text_init_start[]; extern const uint8_t __text_init_end[]; extern const uint8_t __text_pageable_start[]; extern const uint8_t __text_pageable_end[]; #define ASAN_SHADOW_PA ((paddr_t)(vaddr_t)__asan_shadow_start) #define ASAN_SHADOW_SZ ((size_t)__asan_shadow_size) extern const uint8_t __asan_shadow_start[]; extern const uint8_t __asan_shadow_end[]; extern const uint8_t __asan_shadow_size[]; #define ASAN_MAP_PA ((paddr_t)(vaddr_t)__asan_map_start) #define ASAN_MAP_SZ ((size_t)__asan_map_size) extern const uint8_t __asan_map_start[]; extern const uint8_t __asan_map_end[]; extern const uint8_t __asan_map_size[]; extern const vaddr_t __ctor_list; extern const vaddr_t __ctor_end; /* Generated by core/arch/$(ARCH)/kernel/link.mk */ extern const char core_v_str[]; #endif /*__KERNEL_LINKER_H*/ optee_os-4.3.0/core/include/kernel/lockdep.h000066400000000000000000000102221464416617300207710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __KERNEL_LOCKDEP_H #define __KERNEL_LOCKDEP_H #include #include #include #include #include #include /* * Lock graph. If node A has an edge to node B, then A was locked before B in * the same thread of execution. */ struct lockdep_edge { struct lockdep_node *to; uintptr_t thread_id; vaddr_t *call_stack_from; vaddr_t *call_stack_to; STAILQ_ENTRY(lockdep_edge) link; }; STAILQ_HEAD(lockdep_edge_head, lockdep_edge); struct lockdep_node { uintptr_t lock_id; /* For instance, address of actual lock object */ struct lockdep_edge_head edges; TAILQ_ENTRY(lockdep_node) link; uint8_t flags; /* Used temporarily when walking the graph */ }; TAILQ_HEAD(lockdep_node_head, lockdep_node); /* Per-thread queue of currently owned locks (point to nodes in the graph) */ struct lockdep_lock { struct lockdep_node *node; vaddr_t *call_stack; TAILQ_ENTRY(lockdep_lock) link; }; TAILQ_HEAD(lockdep_lock_head, lockdep_lock); #ifdef CFG_LOCKDEP /* * Functions used internally and for testing the algorithm. Actual locking code * should use the wrappers below (which panic in case of error). */ TEE_Result __lockdep_lock_acquire(struct lockdep_node_head *graph, struct lockdep_lock_head *owned, uintptr_t id); TEE_Result __lockdep_lock_tryacquire(struct lockdep_node_head *graph, struct lockdep_lock_head *owned, uintptr_t id); TEE_Result __lockdep_lock_release(struct lockdep_lock_head *owned, uintptr_t id); /* Delete all elements in @graph */ void lockdep_graph_delete(struct lockdep_node_head *graph); /* Delete all elements in @queue */ void lockdep_queue_delete(struct lockdep_lock_head *queue); /* * Acquire lock @id, while already holding the locks in @owned. * @owned represent the caller; there should be one instance per thread of * execution. @graph is the directed acyclic graph (DAG) to be used for * potential deadlock detection; use the same @graph for all the locks of the * same type as lock @id. * * This function will panic() if the acquire operation would result in a lock * hierarchy violation (potential deadlock). */ static inline void lockdep_lock_acquire(struct lockdep_node_head *graph, struct lockdep_lock_head *owned, uintptr_t id) { TEE_Result res = __lockdep_lock_acquire(graph, owned, id); if (res) { EMSG("lockdep: error %#" PRIx32, res); panic(); } } /* * Non-blocking acquire lock @id, while already holding the locks in @owned. * @owned represent the caller; there should be one instance per thread of * execution. @graph is the directed acyclic graph (DAG) to be used for * potential deadlock detection; use the same @graph for all the locks of the * same type as lock @id. */ static inline void lockdep_lock_tryacquire(struct lockdep_node_head *graph, struct lockdep_lock_head *owned, uintptr_t id) { TEE_Result res = __lockdep_lock_tryacquire(graph, owned, id); if (res) { EMSG("lockdep: error %#" PRIx32, res); panic(); } } /* * Release lock @id. The lock is removed from @owned. * * This function will panic() if the lock is not held by the caller. */ static inline void lockdep_lock_release(struct lockdep_lock_head *owned, uintptr_t id) { TEE_Result res = __lockdep_lock_release(owned, id); if (res) { EMSG("lockdep: error %#" PRIx32, res); panic(); } } /* * Destroy lock @id in @graph. The lock is freed. */ void lockdep_lock_destroy(struct lockdep_node_head *graph, uintptr_t id); /* Initialize lockdep for mutex objects (kernel/mutex.h) */ void mutex_lockdep_init(void); #else /* CFG_LOCKDEP */ static inline void lockdep_lock_acquire(struct lockdep_node_head *g __unused, struct lockdep_lock_head *o __unused, uintptr_t id __unused) {} static inline void lockdep_lock_release(struct lockdep_lock_head *o __unused, uintptr_t id __unused) {} static inline void lockdep_lock_destroy(struct lockdep_node_head *graph __unused, uintptr_t id __unused) {} static inline void mutex_lockdep_init(void) {} #endif /* !CFG_LOCKDEP */ #endif /* !__KERNEL_LOCKDEP_H */ optee_os-4.3.0/core/include/kernel/misc.h000066400000000000000000000011361464416617300203070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_MISC_H #define __KERNEL_MISC_H #include #include #include #include size_t __get_core_pos(void); static inline size_t __noprof get_core_pos(void) { /* * Foreign interrupts must be disabled before playing with current * core since we otherwise may be rescheduled to a different core. */ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); return __get_core_pos(); } #endif /*__KERNEL_MISC_H*/ optee_os-4.3.0/core/include/kernel/msg_param.h000066400000000000000000000052761464416617300213330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, EPAM Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __KERNEL_MSG_PARAM_H #define __KERNEL_MSG_PARAM_H #include #include #include #include #include /** * msg_param_mobj_from_noncontig() - construct mobj from non-contiguous * list of pages. * * @buf_ptr - optee_msg_param.u.tmem.buf_ptr value * @size - optee_msg_param.u.tmem.size value * @shm_ref - optee_msg_param.u.tmem.shm_ref value * @map_buffer - true if buffer needs to be mapped into OP-TEE address space * * return: * mobj or NULL on error */ #ifdef CFG_CORE_DYN_SHM struct mobj *msg_param_mobj_from_noncontig(paddr_t buf_ptr, size_t size, uint64_t shm_ref, bool map_buffer); #else static inline struct mobj * msg_param_mobj_from_noncontig(paddr_t buf_ptr __unused, size_t size __unused, uint64_t shm_ref __unused, bool map_buffer __unused) { return NULL; } #endif /** * msg_param_attr_is_tmem - helper functions that cheks if attribute is tmem * * @attr - attribute to check * * return: * corresponding size field */ static inline bool msg_param_attr_is_tmem(uint64_t attr) { switch (attr & OPTEE_MSG_ATTR_TYPE_MASK) { case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: return true; default: return false; } } #endif /*__KERNEL_MSG_PARAM_H*/ optee_os-4.3.0/core/include/kernel/mutex.h000066400000000000000000000105061464416617300205170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2017, Linaro Limited */ #ifndef __KERNEL_MUTEX_H #define __KERNEL_MUTEX_H #include #include #include #include struct mutex { unsigned spin_lock; /* used when operating on this struct */ struct wait_queue wq; short state; /* -1: write, 0: unlocked, > 0: readers */ }; #define MUTEX_INITIALIZER { .wq = WAIT_QUEUE_INITIALIZER } struct recursive_mutex { struct mutex m; /* used when lock_depth goes 0 -> 1 or 1 -> 0 */ short int owner; struct refcount lock_depth; }; #define RECURSIVE_MUTEX_INITIALIZER { .m = MUTEX_INITIALIZER, \ .owner = THREAD_ID_INVALID } TAILQ_HEAD(mutex_head, mutex); void mutex_init(struct mutex *m); void mutex_destroy(struct mutex *m); void mutex_init_recursive(struct recursive_mutex *m); void mutex_destroy_recursive(struct recursive_mutex *m); unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m); #ifdef CFG_MUTEX_DEBUG void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_unlock(m) mutex_unlock_debug((m), __FILE__, __LINE__) void mutex_lock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_lock(m) mutex_lock_debug((m), __FILE__, __LINE__) bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_trylock(m) mutex_trylock_debug((m), __FILE__, __LINE__) void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_read_unlock(m) mutex_read_unlock_debug((m), __FILE__, __LINE__) void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_read_lock(m) mutex_read_lock_debug((m), __FILE__, __LINE__) bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno); #define mutex_read_trylock(m) mutex_read_trylock_debug((m), __FILE__, __LINE__) void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname, int lineno); #define mutex_unlock_recursive(m) mutex_unlock_recursive_debug((m), __FILE__, \ __LINE__) void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname, int lineno); #define mutex_lock_recursive(m) mutex_lock_recursive_debug((m), __FILE__, \ __LINE__) #else void mutex_unlock(struct mutex *m); void mutex_lock(struct mutex *m); bool mutex_trylock(struct mutex *m); void mutex_read_unlock(struct mutex *m); void mutex_read_lock(struct mutex *m); bool mutex_read_trylock(struct mutex *m); void mutex_unlock_recursive(struct recursive_mutex *m); void mutex_lock_recursive(struct recursive_mutex *m); #endif struct condvar { unsigned int spin_lock; struct mutex *m; }; #define CONDVAR_INITIALIZER { .m = NULL } void condvar_init(struct condvar *cv); void condvar_destroy(struct condvar *cv); #ifdef CFG_MUTEX_DEBUG void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno); #define condvar_signal(cv) condvar_signal_debug((cv), __FILE__, __LINE__) void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno); #define condvar_broadcast(cv) condvar_broadcast_debug((cv), __FILE__, __LINE__) void condvar_wait_debug(struct condvar *cv, struct mutex *m, const char *fname, int lineno); #define condvar_wait(cv, m) condvar_wait_debug((cv), (m), __FILE__, __LINE__) /* * Return TEE_ERROR_TIMEOUT if the normal world returns before * the condvar has been signaled. */ TEE_Result condvar_wait_timeout_debug(struct condvar *cv, struct mutex *m, uint32_t timeout_ms, const char *fname, int lineno); #define condvar_wait_timeout(cv, m, timeout_ms) \ condvar_wait_timeout_debug((cv), (m), (timeout_ms), __FILE__, __LINE__) #else void condvar_signal(struct condvar *cv); void condvar_broadcast(struct condvar *cv); void condvar_wait(struct condvar *cv, struct mutex *m); /* * Return TEE_ERROR_TIMEOUT if the normal world returns before * the condvar has been signaled. */ TEE_Result condvar_wait_timeout(struct condvar *cv, struct mutex *m, uint32_t timeout_ms); #endif /* * Helper for testing that a given mutex is locked for writing. This helper * is to be used with caution since it does not guarantee that the executing * thread is holding the mutex. */ static inline bool mutex_is_locked(struct mutex *m) { return m->state == -1; /* write locked */ } #endif /*__KERNEL_MUTEX_H*/ optee_os-4.3.0/core/include/kernel/mutex_pm_aware.h000066400000000000000000000030601464416617300223670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024, STMicroelectronics */ #ifndef __KERNEL_MUTEX_PM_AWARE_H #define __KERNEL_MUTEX_PM_AWARE_H #include #include /* * struct mutex_pm_aware - Mutex usable in PM atomic sequence * * Some resources need a mutex protection for runtime operations but are * also accessed during specific system power transition (PM power off, * suspend and resume) that operate in atomic execution environment where * non-secure world is not operational, for example in fastcall SMC entries * of the PSCI services. In such case we cannot take a mutex and we expect * the mutex is unlocked. Additionally a spinning lock is attempted to be * locked to check the resource access consistency. * * Core intentionally panics in case of unexpected resource access contention: * - When a thread requests a mutex held by a non-thread context; * - When a non-thread context requests a mutex held by a thread; * - When a non-thread context requests a mutex held by a non-thread context. */ struct mutex_pm_aware { struct mutex mutex; /* access protection in thread context */ unsigned int lock; /* access consistency in PM context */ }; #define MUTEX_PM_AWARE_INITIALIZER { \ .mutex = MUTEX_INITIALIZER, \ .lock = SPINLOCK_UNLOCK, \ } void mutex_pm_aware_init(struct mutex_pm_aware *m); void mutex_pm_aware_destroy(struct mutex_pm_aware *m); void mutex_pm_aware_lock(struct mutex_pm_aware *m); void mutex_pm_aware_unlock(struct mutex_pm_aware *m); #endif /*__KERNEL_MUTEX_PM_AWARE_H*/ optee_os-4.3.0/core/include/kernel/notif.h000066400000000000000000000131651464416617300205000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Linaro Limited */ #ifndef __KERNEL_NOTIF_H #define __KERNEL_NOTIF_H #include #include #include #include #include /* * Notification values are divided into two kinds, asynchronous and * synchronous, where the asynchronous has the lowest values. * They are ordered as: * 0 Do bottom half * 1..NOTIF_ASYNC_MAX Free for signalling in PTAs and should be * allocated with notif_alloc_async_value() * NOTIF_SYNC_VALUE_BASE.. Used as NOTIF_SYNC_VALUE_BASE + thread_id * NOTIF_VALUE_MAX for mutex and condvar wait/wakeup * * Any value can be signalled with notif_send_sync() while only the ones * <= NOTIF_ASYNC_VALUE_MAX can be signalled with notif_send_async(). */ #if defined(CFG_CORE_ASYNC_NOTIF) #define NOTIF_ASYNC_VALUE_MAX U(63) #define NOTIF_SYNC_VALUE_BASE (NOTIF_ASYNC_VALUE_MAX + U(1)) #else #define NOTIF_SYNC_VALUE_BASE 0 #endif #define NOTIF_VALUE_MAX (NOTIF_SYNC_VALUE_BASE + \ CFG_NUM_THREADS) #define NOTIF_VALUE_DO_BOTTOM_HALF 0 /* * enum notif_event - Notification of an event * @NOTIF_EVENT_STARTED: Delivered in an atomic context to inform * drivers that normal world has enabled * asynchronous notifications. * @NOTIF_EVENT_DO_BOTTOM_HALF: Delivered in a yielding context to let a * driver do bottom half processing. * @NOTIF_EVENT_STOPPED: Delivered in a yielding contest to inform * drivers that normal world is about to disable * asynchronous notifications. * * Once a driver has received a @NOTIF_EVENT_STARTED asynchronous notifications * driving the @NOTIF_EVENT_DO_BOTTOM_HALF deliveries is enabled. * * In case a @NOTIF_EVENT_STOPPED is received there will be no more * @NOTIF_EVENT_DO_BOTTOM_HALF events delivered, until @NOTIF_EVENT_STARTED * has been delivered again. * * Note that while a @NOTIF_EVENT_STOPPED is being delivered at the same * time may a @NOTIF_EVENT_STARTED be delivered again so a driver is * required to sychronize accesses to its internal state. */ enum notif_event { NOTIF_EVENT_STARTED, NOTIF_EVENT_DO_BOTTOM_HALF, NOTIF_EVENT_STOPPED, NOTIF_EVENT_SHUTDOWN, }; /* * struct notif_driver - Registration of driver notification * @atomic_cb: A callback called in an atomic context from * notif_deliver_atomic_event(). Currently only used to * signal @NOTIF_EVENT_STARTED. * @yielding_cb: A callback called in a yielding context from * notif_deliver_event(). Currently only used to signal * @NOTIF_EVENT_DO_BOTTOM_HALF and @NOTIF_EVENT_STOPPED. * * A atomic context means that interrupts are masked and a common spinlock * is held. Calls via @atomic_cb are only atomic with regards to each * other, other CPUs may execute yielding calls or even receive interrupts. * If CFG_NS_VIRTUALIZATION=y then code is executing in Nexus context * without a partition activated, the @guest_id triggering the event is * instead supplied as an argument to the callback. The @guest_id should be * ignored if CFG_NS_VIRTUALIZATION isn't enabled. * * A yielding context means that the function is executing in a normal * threaded context allowing RPC and synchronization with other thread * using mutexes and condition variables. If CFG_NS_VIRTUALIZATION=y then * is a partition matching the guest or VM that triggered the event. */ struct notif_driver { void (*atomic_cb)(struct notif_driver *ndrv, enum notif_event ev, uint16_t guest_id); void (*yielding_cb)(struct notif_driver *ndrv, enum notif_event ev); SLIST_ENTRY(notif_driver) link; }; #if defined(CFG_CORE_ASYNC_NOTIF) bool notif_async_is_started(uint16_t guest_id); #else static inline bool notif_async_is_started(uint16_t guest_id __unused) { return false; } #endif TEE_Result notif_alloc_async_value(uint32_t *value); void notif_free_async_value(uint32_t value); /* * Wait in normal world for a value to be sent by notif_send() */ TEE_Result notif_wait(uint32_t value); /* * Wait timeout in normal world for a value to be sent by notif_send() */ TEE_Result notif_wait_timeout(uint32_t value, uint32_t timeout_ms); /* * Send an asynchronous value, note that it must be <= NOTIF_ASYNC_VALUE_MAX */ #if defined(CFG_CORE_ASYNC_NOTIF) void notif_send_async(uint32_t value, uint16_t guest_id); #else static inline void notif_send_async(uint32_t value __unused, uint16_t guest_id __unused) { } #endif /* * Send a sychronous value, note that it must be <= NOTIF_VALUE_MAX. The * notification is synchronous even if the value happens to belong in the * asynchronous range. */ TEE_Result notif_send_sync(uint32_t value); /* * Called by device drivers. */ #if defined(CFG_CORE_ASYNC_NOTIF) void notif_register_driver(struct notif_driver *ndrv); void notif_unregister_driver(struct notif_driver *ndrv); #else static inline void notif_register_driver(struct notif_driver *ndrv __unused) { } static inline void notif_unregister_driver(struct notif_driver *ndrv __unused) { } #endif /* This is called from a fast call */ #if defined(CFG_CORE_ASYNC_NOTIF) uint32_t notif_get_value(bool *value_valid, bool *value_pending); #else static inline uint32_t notif_get_value(bool *value_valid, bool *value_pending) { *value_valid = false; *value_pending = false; return UINT32_MAX; } #endif #if defined(CFG_CORE_ASYNC_NOTIF) void notif_deliver_atomic_event(enum notif_event ev, uint16_t guest_id); void notif_deliver_event(enum notif_event ev); #else static inline void notif_deliver_atomic_event(enum notif_event ev __unused, uint16_t guest_id __unused) { } static inline void notif_deliver_event(enum notif_event ev __unused) { } #endif #endif /*__KERNEL_NOTIF_H*/ optee_os-4.3.0/core/include/kernel/nv_counter.h000066400000000000000000000005251464416617300215370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, Linaro Limited */ #ifndef __KERNEL_NV_COUNTER_H #define __KERNEL_NV_COUNTER_H #include #include TEE_Result nv_counter_get_ree_fs(uint32_t *value); TEE_Result nv_counter_incr_ree_fs_to(uint32_t value); #endif /*__KERNEL_NV_COUNTER_H*/ optee_os-4.3.0/core/include/kernel/panic.h000066400000000000000000000024301464416617300204440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_PANIC_H #define __KERNEL_PANIC_H #include /* debug disabled => __FILE__, ... and panic message are not built. */ #if defined(CFG_TEE_CORE_DEBUG) #define __panic(str) __do_panic(__FILE__, __LINE__, __func__, str) #else #define __panic(str) __do_panic((void *)0, 0, (void *)0, str) #endif void __do_panic(const char *file, const int line, const char *func, const char *msg) __noreturn; /* * Suppress GCC warning on expansion of the panic() macro with no argument: * 'ISO C99 requires at least one argument for the "..." in a variadic macro' * Occurs when '-pedantic' is combined with '-std=gnu99'. * Suppression applies only to this file and the expansion of macros defined in * this file. */ #pragma GCC system_header /* panic() can get a string or no argument */ #define _panic0() __panic((void *)0) #define _panic1(s) __panic(s) #define _panic_fn(a, b, name, ...) name #define panic(...) _panic_fn("", ##__VA_ARGS__, _panic1, _panic0)(__VA_ARGS__) /* * Weak function used in __do_panic() to put the current CPU on hold. * If no arch-specific override is provided, defaults to a busy loop. */ void cpu_idle(void); #endif /*__KERNEL_PANIC_H*/ optee_os-4.3.0/core/include/kernel/pm.h000066400000000000000000000134101464416617300177660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __KERNEL_PM_H #define __KERNEL_PM_H #include #include #include /* * Platform hints on targeted power state. Hints are stored in a 32bit * unsigned value. Lower bits defines generic resource bit flags. Higher * bits stores a platform specific value specific platform driver may * understand. Registered callbacks may choose to use or ignore these hints. * * PM_HINT_CLOCK_STATE - When set clock shall be suspended/restored * PM_HINT_POWER_STATE - When set device power shall be suspended/restored * PM_HINT_IO_STATE - When set IO pins shall be suspended/restored * PM_HINT_CONTEXT_STATE - When set the full context be suspended/restored * PM_HINT_PLATFORM_STATE_MASK - Bit mask reserved for platform specific hints * PM_HINT_PLATFORM_STATE_SHIFT - LSBit position of platform specific hints mask */ #define PM_HINT_CLOCK_STATE BIT(0) #define PM_HINT_POWER_STATE BIT(1) #define PM_HINT_IO_STATE BIT(2) #define PM_HINT_CONTEXT_STATE BIT(3) #define PM_HINT_PLATFORM_STATE_MASK GENMASK_32(31, 16) #define PM_HINT_PLATFORM_STATE_SHIFT U(16) #define PM_HINT_STATE(_x) ((_x) & ~PM_HINT_PLATFORM_STATE_MASK) #define PM_HINT_PLATFORM_STATE(_x) \ (((_x) & PM_HINT_PLATFORM_STATE_MASK) >> PM_HINT_PLATFORM_STATE_SHIFT) #define PM_HINT_IS_STATE(_x, _name) ((_x) & PM_HINT_ ## _name ## _STATE) /* * PM_OP_SUSPEND: platform is suspending to a target low power state * PM_OP_RESUME: platform is resuming from low power state */ enum pm_op { PM_OP_SUSPEND = 0, PM_OP_RESUME = 1, }; /* * Registered callbacks are called the ordering directives specified * by the PM_CB_ORDER_* value. Driver ordered callbacks at suspended * first/resumed last. Core service ordered callbacks are suspended * last/resumed first. */ enum pm_callback_order { PM_CB_ORDER_DRIVER = 0, PM_CB_ORDER_CORE_SERVICE, PM_CB_ORDER_MAX }; #define PM_CALLBACK_HANDLE_INITIALIZER(_callback, _handle, _order, _name)\ ((struct pm_callback_handle){ \ .callback = (_callback), \ .handle = (_handle), \ .order = (_order), \ .name = (_name), \ }) #define PM_CALLBACK_GET_HANDLE(pm_handle) ((pm_handle)->handle) struct pm_callback_handle; typedef TEE_Result (*pm_callback)(enum pm_op op, uint32_t pm_hint, const struct pm_callback_handle *pm_handle); /* * Drivers and services can register a callback function for the platform * suspend and resume sequences. A private address handle can be registered * with the callback and retrieved from the callback. Callback can be * registered with a specific call order as defined per PM_CB_ORDER_*. * * Callback shall return an error if failing to complete target transition. * This information may be used by the platform to resume a platform on * non-fatal failure to suspend. * * Callback implementations should ensure their functions belong to unpaged * memory sections (see DECLARE_KEEP_PAGER()) since the callback is likely to * be called from an unpaged execution context. * * Power Mamagement callback functions API: * * TEE_Result (*callback)(enum pm_op op, * unsigned int pm_hint, * const struct pm_callback_handle *pm_handle); * * @op - Target operation: either PM_SUSPEND or PM_RESUME * @pm_hint - Hints on power state platform suspends to /resumes from. * PM_STATE_HINT_* defines the supported values. * @pm_handle - Reference to the struct pm_callback_handle related to to * registered callback. Callback can retrieve the registered * private handle with PM_CALLBACK_GET_HANDLE(). * * Return a TEE_Result compliant return code */ /* * struct pm_callback_handle store the callback registration directives. * * @callback - Registered callback function * @handle - Registered private handler for the callback * @order - Registered callback call order priority (PM_CB_ORDER_*) * @flags - Flags set by pm core to keep track of execution * @name - Registered callback name */ struct pm_callback_handle { /* Set by the caller when registering a callback */ pm_callback callback; void *handle; uint8_t order; /* Set by the system according to execution context */ uint8_t flags; const char *name; }; /* * Register a callback for suspend/resume sequence * Refer to struct pm_callback_handle for description of the callbacks * API and the registration directives. * * @pm_handle: Reference callback registration directives */ void register_pm_cb(struct pm_callback_handle *pm_handle); /* * Register a driver callback for generic suspend/resume. * Refer to struct pm_callback_handle for description of the callbacks * API. * * @callback: Registered callback function * @handle: Registered private handle argument for the callback * @name: Registered callback name */ static inline void register_pm_driver_cb(pm_callback callback, void *handle, const char *name) { register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, PM_CB_ORDER_DRIVER, name)); } /* * Register a core service callback for generic suspend/resume. * Refer to struct pm_callback_handle for description of the callbacks * API. * * @callback: Registered callback function * @handle: Registered private handle argument for the callback * @name: Registered callback name */ static inline void register_pm_core_service_cb(pm_callback callback, void *handle, const char *name) { register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle, PM_CB_ORDER_CORE_SERVICE, name)); } /* * Request call to registered PM callbacks * * @op: Either PM_OP_SUSPEND or PM_OP_RESUME * @pm_hint: Hint (PM_HINT_*) on state the platform suspends to/resumes from. * * Return a TEE_Result compliant status */ TEE_Result pm_change_state(enum pm_op op, uint32_t pm_hint); #endif /*__KERNEL_PM_H*/ optee_os-4.3.0/core/include/kernel/pseudo_ta.h000066400000000000000000000054331464416617300213430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __KERNEL_PSEUDO_TA_H #define __KERNEL_PSEUDO_TA_H #include #include #include #include #include #include #include #include #include #define PTA_MANDATORY_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ TA_FLAG_MULTI_SESSION | \ TA_FLAG_INSTANCE_KEEP_ALIVE) #define PTA_ALLOWED_FLAGS (PTA_MANDATORY_FLAGS | \ TA_FLAG_SECURE_DATA_PATH | \ TA_FLAG_CONCURRENT | \ TA_FLAG_DEVICE_ENUM) #define PTA_DEFAULT_FLAGS PTA_MANDATORY_FLAGS struct pseudo_ta_head { TEE_UUID uuid; const char *name; uint32_t flags; TEE_Result (*create_entry_point)(void); void (*destroy_entry_point)(void); TEE_Result (*open_session_entry_point)(uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS], void **ppSessionContext); void (*close_session_entry_point)(void *pSessionContext); TEE_Result (*invoke_command_entry_point)(void *pSessionContext, uint32_t nCommandID, uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]); }; #define pseudo_ta_register(...) \ SCATTERED_ARRAY_DEFINE_PG_ITEM(pseudo_tas, struct pseudo_ta_head) = \ { __VA_ARGS__ } struct pseudo_ta_ctx { const struct pseudo_ta_head *pseudo_ta; struct tee_ta_ctx ctx; }; bool is_pseudo_ta_ctx(struct ts_ctx *ctx); static inline struct pseudo_ta_ctx *to_pseudo_ta_ctx(struct ts_ctx *ctx) { assert(is_pseudo_ta_ctx(ctx)); return container_of(ctx, struct pseudo_ta_ctx, ctx.ts_ctx); } /* * Setup session context for a pseudo TA * @uuid: Pseudo TA UUID * @s: Session for which to setup a pseudo TA context * * This function must be called with tee_ta_mutex locked. */ TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, struct tee_ta_session *s); /* * Helper functions for PTAs to support calls from a TA when CFG_PAN=y */ static inline bool is_caller_ta_with_pan(void) { struct ts_session *s = NULL; if (!IS_ENABLED(CFG_PAN)) return false; s = ts_get_calling_session(); return s && is_user_ta_ctx(s->ctx); } /* * If caller is a TA and PAN is enabled, allocate bounce buffers for each * memref in @params and build @bparams, then make *@oparams point to @bparams. * Otherwise just make *@oparams point to @params. */ TEE_Result to_bounce_params(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS], TEE_Param bparams[TEE_NUM_PARAMS], TEE_Param **oparams); /* * If @eparams == @bparams, copy data from @bparams to @params. Otherwise, do * nothing. */ TEE_Result from_bounce_params(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS], TEE_Param bparams[TEE_NUM_PARAMS], TEE_Param *eparams); #endif /* __KERNEL_PSEUDO_TA_H */ optee_os-4.3.0/core/include/kernel/refcount.h000066400000000000000000000034331464416617300212030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __KERNEL_REFCOUNT_H #define __KERNEL_REFCOUNT_H #include /* * Reference counter * * When val is 0, refcount_inc() does not change the value and returns false. * Otherwise, it increments the value and returns true. * * refcount_dec() decrements the value and returns true when the call * caused the value to become 0, false otherwise. * * Since each call to refcount_dec() is supposed to match a call to * refcount_inc(), refcount_dec() called for val == 0 should never happen. * * This behaviour makes this pattern possible: * if (!refcount_inc(r)) { * mutex_lock(m); * // Some other thread may have initialized o by now so check that * // we still need to initialize o. * if (!o) { * o = initialize(); * refcount_set(r, 1); * } * mutex_unlock(m); * } * * or * if (refcount_dec(r)) { * mutex_lock(m); * // Now that we have the mutex o can't be ininialized/uninitialized * // by any other thread, check that the refcount value is still 0 * // to guard against the thread above already having reinitialized o * if (!refcount_val(r) && o) * uninitialize(o) * mutex_unlock(m); * } * * where r if the reference counter, o is the object and m the mutex * protecting the object. */ struct refcount { unsigned int val; }; /* Increases refcount by 1, return true if val > 0 else false */ bool refcount_inc(struct refcount *r); /* Decreases refcount by 1, return true if val == 0 else false */ bool refcount_dec(struct refcount *r); static inline void refcount_set(struct refcount *r, unsigned int val) { atomic_store_uint(&r->val, val); } static inline unsigned int refcount_val(struct refcount *r) { return atomic_load_uint(&r->val); } #endif /*!__KERNEL_REFCOUNT_H*/ optee_os-4.3.0/core/include/kernel/rpc_io_i2c.h000066400000000000000000000021271464416617300213650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020 Foundries Ltd */ #ifndef __KERNEL_RPC_IO_I2C_H #define __KERNEL_RPC_IO_I2C_H #include #include /* I2C master transfer mode */ enum rpc_i2c_mode { RPC_I2C_MODE_WRITE = OPTEE_RPC_I2C_TRANSFER_WR, RPC_I2C_MODE_READ = OPTEE_RPC_I2C_TRANSFER_RD, }; /* I2C master transfer control flags */ #define RPC_I2C_FLAGS_TEN_BIT OPTEE_RPC_I2C_FLAGS_TEN_BIT /* * The bus identifier defines an implicit ABI with the REE. * Using this service to access I2C slaves on REE dynamically assigned buses is * not recommended unless there is a guarantee that the bus identifier will * persist across reboots. */ struct rpc_i2c_request { enum rpc_i2c_mode mode; uint16_t bus; /* bus identifier used by the REE [0..n] */ uint16_t chip; /* slave identifier from its data sheet */ uint16_t flags; /* transfer flags (ie: ten bit chip address) */ uint8_t *buffer; size_t buffer_len; }; TEE_Result rpc_io_i2c_transfer(struct rpc_i2c_request *p, size_t *bytes); #endif /* __KERNEL_RPC_IO_I2C_H */ optee_os-4.3.0/core/include/kernel/scall.h000066400000000000000000000023631464416617300204550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2022, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef __KERNEL_SCALL_H #define __KERNEL_SCALL_H #include /* * Generic "pointer to function" type. Actual syscalls take zero or more * arguments and return TEE_Result. */ typedef void (*syscall_t)(void); struct thread_scall_regs; /* Helper function for scall_handle_user_ta() and scall_handle_ldelf() */ uint32_t scall_do_call(struct thread_scall_regs *regs, syscall_t func); /* Registered as .handle_scall in struct tee_ta_ops for user TAs. */ bool scall_handle_user_ta(struct thread_scall_regs *regs); /* Separate syscall handler for calls from ldelf */ bool scall_handle_ldelf(struct thread_scall_regs *regs); /* * Called from the assembly functions syscall_sys_return() and * syscall_panic() to update the register values in the struct * thread_scall_regs to return back to TEE Core from an earlier call to * thread_enter_user_mode(). */ uint32_t scall_sys_return_helper(uint32_t ret, bool panic, uint32_t panic_code, struct thread_scall_regs *regs); /* Saves TA panic stack, arch-specific implementation */ void scall_save_panic_stack(struct thread_scall_regs *regs); #endif /*__KERNEL_SCALL_H*/ optee_os-4.3.0/core/include/kernel/semihosting.h000066400000000000000000000012451464416617300217060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2024 Andes Technology Corporation */ #ifndef __KERNEL_SEMIHOSTING_H #define __KERNEL_SEMIHOSTING_H #include #include #include #include /* Perform architecture-specific semihosting instructions. */ uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg); char semihosting_sys_readc(void); void semihosting_sys_writec(char c); int semihosting_open(const char *fname, int flags); size_t semihosting_read(int fd, void *ptr, size_t len); size_t semihosting_write(int fd, const void *ptr, size_t len); int semihosting_close(int fd); #endif /* __KERNEL_SEMIHOSTING_H */ optee_os-4.3.0/core/include/kernel/spinlock.h000066400000000000000000000071651464416617300212060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2016, Linaro Limited */ #ifndef __KERNEL_SPINLOCK_H #define __KERNEL_SPINLOCK_H #define SPINLOCK_LOCK 1 #define SPINLOCK_UNLOCK 0 #ifndef __ASSEMBLER__ #include #include #include #include #ifdef CFG_TEE_CORE_DEBUG void spinlock_count_incr(void); void spinlock_count_decr(void); bool have_spinlock(void); static inline void __nostackcheck assert_have_no_spinlock(void) { assert(!have_spinlock()); } #else static inline void spinlock_count_incr(void) { } static inline void spinlock_count_decr(void) { } static inline void __nostackcheck assert_have_no_spinlock(void) { } #endif void __cpu_spin_lock(unsigned int *lock); void __cpu_spin_unlock(unsigned int *lock); /* returns 0 on locking success, non zero on failure */ unsigned int __cpu_spin_trylock(unsigned int *lock); static inline void cpu_spin_lock_no_dldetect(unsigned int *lock) { assert(thread_foreign_intr_disabled()); __cpu_spin_lock(lock); spinlock_count_incr(); } static inline bool thread_spin_trylock(unsigned int *lock) { assert(thread_get_id_may_fail() != THREAD_ID_INVALID); return !__cpu_spin_trylock(lock); } /* * To be used with lot of care: it is not recommended to spin in a thread * context without masking foreign interrupts */ static inline void thread_spin_lock(unsigned int *lock) { assert(thread_get_id_may_fail() != THREAD_ID_INVALID); __cpu_spin_lock(lock); } static inline void thread_spin_unlock(unsigned int *lock) { assert(thread_get_id_may_fail() != THREAD_ID_INVALID); __cpu_spin_unlock(lock); } #ifdef CFG_TEE_CORE_DEBUG #define cpu_spin_lock(lock) \ cpu_spin_lock_dldetect(__func__, __LINE__, lock) static inline void cpu_spin_lock_dldetect(const char *func, const int line, unsigned int *lock) { unsigned int retries = 0; unsigned int reminder = 0; assert(thread_foreign_intr_disabled()); while (__cpu_spin_trylock(lock)) { retries++; if (!retries) { /* wrapped, time to report */ trace_printf(func, line, TRACE_ERROR, true, "possible spinlock deadlock reminder %u", reminder); if (reminder < UINT_MAX) reminder++; } } spinlock_count_incr(); } #else static inline void cpu_spin_lock(unsigned int *lock) { cpu_spin_lock_no_dldetect(lock); } #endif static inline bool cpu_spin_trylock(unsigned int *lock) { unsigned int rc; assert(thread_foreign_intr_disabled()); rc = __cpu_spin_trylock(lock); if (!rc) spinlock_count_incr(); return !rc; } static inline void cpu_spin_unlock(unsigned int *lock) { assert(thread_foreign_intr_disabled()); __cpu_spin_unlock(lock); spinlock_count_decr(); } static inline uint32_t __must_check cpu_spin_lock_xsave_no_dldetect(unsigned int *lock) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); cpu_spin_lock(lock); return exceptions; } #ifdef CFG_TEE_CORE_DEBUG #define cpu_spin_lock_xsave(lock) \ cpu_spin_lock_xsave_dldetect(__func__, __LINE__, lock) static inline uint32_t __must_check cpu_spin_lock_xsave_dldetect(const char *func, const int line, unsigned int *lock) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); cpu_spin_lock_dldetect(func, line, lock); return exceptions; } #else static inline uint32_t __must_check cpu_spin_lock_xsave(unsigned int *lock) { return cpu_spin_lock_xsave_no_dldetect(lock); } #endif static inline void cpu_spin_unlock_xrestore(unsigned int *lock, uint32_t exceptions) { cpu_spin_unlock(lock); thread_unmask_exceptions(exceptions); } #endif /* __ASSEMBLER__ */ #endif /* __KERNEL_SPINLOCK_H */ optee_os-4.3.0/core/include/kernel/tee_common.h000066400000000000000000000017161464416617300215050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TEE_COMMON_H #define __KERNEL_TEE_COMMON_H #include #ifdef MEASURE_TIME /* * Initializes mesaure time. Initializes RTT0 to highest possible * resolution. */ void tee_mtime_init(void); /* * Adds a time stamp together the description. Note that only the pointer * is copied, not the contents to minimize impact. */ void tee_mtime_stamp(const char *descr); /* * Prints a report of measured times and reinitializes clears the table of * saved time stamps. */ void tee_mtime_report(void); void tee_mtime_perftest(void); #else /* Empty macros to not have any impact on code when not meassuring time */ #define tee_mtime_init() do { } while (0) #define tee_mtime_stamp(descr) do { } while (0) #define tee_mtime_report() do { } while (0) #define tee_mtime_perftest() do { } while (0) #endif #endif /* __KERNEL_TEE_COMMON_H */ optee_os-4.3.0/core/include/kernel/tee_common_otp.h000066400000000000000000000011501464416617300223570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TEE_COMMON_OTP_H #define __KERNEL_TEE_COMMON_OTP_H #include #include #include #include #include struct tee_hw_unique_key { uint8_t data[HW_UNIQUE_KEY_LENGTH]; }; TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey); int tee_otp_get_die_id(uint8_t *buffer, size_t len); TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type, uint8_t *buffer, size_t len); #endif /* __KERNEL_TEE_COMMON_OTP_H */ optee_os-4.3.0/core/include/kernel/tee_misc.h000066400000000000000000000043301464416617300211430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TEE_MISC_H #define __KERNEL_TEE_MISC_H #include /* * Macro to derive hex string buffer size from binary buffer size & the * reverse */ #define TEE_B2HS_HSBUF_SIZE(x) ((x) * 2 + 1) #define TEE_HS2B_BBUF_SIZE(x) ((x + 1) >> 1) /* * binary to hex string buffer * Returns the number of data bytes written to the hex string */ uint32_t tee_b2hs(uint8_t *b, uint8_t *hs, uint32_t blen, uint32_t hslen); /* * hex string to binary buffer * Returns the number of data bytes written to the bin buffer */ uint32_t tee_hs2b(uint8_t *hs, uint8_t *b, uint32_t hslen, uint32_t blen); /* * Is buffer 'b' inside/outside/overlapping area 'a'? * * core_is_buffer_inside() - return true if buffer is inside memory area * core_is_buffer_outside() - return true if buffer is outside area * core_is_buffer_intersect() - return true if buffer overlaps area * * Warning: core_is_buffer_inside(x,x,x,x)==false does NOT mean * core_is_buffer_outside(x,x,x,x)==true. * * Arguments use by each of these routines: * @b - buffer start address (handled has an unsigned offset) * @bl - length (in bytes) of the target buffer * @a - memory area start address (handled has an unsigned offset) * @al - memory area length (in byte) */ bool core_is_buffer_inside(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al); bool core_is_buffer_outside(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al); bool core_is_buffer_intersect(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al); /** * Allocate maximum cache line aligned memory buffer. * * Both size and base address of the memory buffer will be maximum cache line * aligned to make it safe to perform cache maintenance operations over the * allocated area. * * This is needed when non-cache coherent peripherals are used and memory area * is shared between CPU and peripheral. * * Allocated memory is zeroed. * * Release memory with free(). * * @size Size in bytes to allocate * @return NULL on failure or a pointer to allocated memory on success. */ void *alloc_cache_aligned(size_t size); #endif /* __KERNEL_TEE_MISC_H */ optee_os-4.3.0/core/include/kernel/tee_ta_manager.h000066400000000000000000000124711464416617300223130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2017, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef __KERNEL_TEE_TA_MANAGER_H #define __KERNEL_TEE_TA_MANAGER_H #include #include #include #include #include #include #include #include #include #include /* Magic TEE identity pointer: set when teecore requests a TA close */ #define KERN_IDENTITY ((TEE_Identity *)-1) /* Operation is initiated by a client (non-secure) app */ #define NSAPP_IDENTITY (NULL) TAILQ_HEAD(tee_ta_session_head, tee_ta_session); TAILQ_HEAD(tee_ta_ctx_head, tee_ta_ctx); struct mobj; struct param_val { uint32_t a; uint32_t b; }; struct param_mem { struct mobj *mobj; size_t size; size_t offs; }; struct tee_ta_param { uint32_t types; union { struct param_val val; struct param_mem mem; } u[TEE_NUM_PARAMS]; }; struct user_ta_ctx; #if defined(CFG_TA_GPROF_SUPPORT) struct sample_buf { uint32_t nsamples; /* Size of @samples array in uint16_t */ uint32_t offset; /* Passed from user mode */ uint32_t scale; /* Passed from user mode */ uint32_t count; /* Number of samples taken */ bool enabled; /* Sampling enabled? */ uint16_t *samples; uint64_t usr; /* Total user CPU time for this session */ uint64_t usr_entered; /* When this session last entered user mode */ uint32_t freq; /* @usr divided by @freq is in seconds */ }; #endif /* Context of a loaded TA */ struct tee_ta_ctx { uint32_t flags; /* TA_FLAGS from TA header */ TAILQ_ENTRY(tee_ta_ctx) link; struct ts_ctx ts_ctx; uint32_t panicked; /* True if TA has panicked, written from asm */ uint32_t panic_code; /* Code supplied for panic */ uint32_t ref_count; /* Reference counter for multi session TA */ bool busy; /* Context is busy and cannot be entered */ bool is_initializing; /* Context initialization is not completed */ bool is_releasing; /* Context is about to be released */ struct condvar busy_cv; /* CV used when context is busy */ }; struct tee_ta_session { TAILQ_ENTRY(tee_ta_session) link; struct ts_session ts_sess; uint32_t id; /* Session handle (0 is invalid) */ TEE_Identity clnt_id; /* Identify of client */ struct tee_ta_param *param; TEE_ErrorOrigin err_origin; bool cancel; /* True if TA invocation is cancelled */ bool cancel_mask; /* True if cancel is masked */ TEE_Time cancel_time; /* Time when to cancel the TA invocation */ uint32_t ref_count; /* reference counter */ struct condvar refc_cv; /* CV used to wait for ref_count to be 0 */ struct condvar lock_cv; /* CV used to wait for lock */ short int lock_thread; /* Id of thread holding the lock */ bool unlink; /* True if session is to be unlinked */ }; /* Registered contexts */ extern struct tee_ta_ctx_head tee_ctxes; extern struct mutex tee_ta_mutex; extern struct condvar tee_ta_init_cv; TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err, struct tee_ta_session **sess, struct tee_ta_session_head *open_sessions, const TEE_UUID *uuid, const TEE_Identity *clnt_id, uint32_t cancel_req_to, struct tee_ta_param *param); TEE_Result tee_ta_invoke_command(TEE_ErrorOrigin *err, struct tee_ta_session *sess, const TEE_Identity *clnt_id, uint32_t cancel_req_to, uint32_t cmd, struct tee_ta_param *param); TEE_Result tee_ta_cancel_command(TEE_ErrorOrigin *err, struct tee_ta_session *sess, const TEE_Identity *clnt_id); bool tee_ta_session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time); /*----------------------------------------------------------------------------- * Function called to close a TA. * Parameters: * id - The session id (in) * Returns: * TEE_Result *---------------------------------------------------------------------------*/ TEE_Result tee_ta_close_session(struct tee_ta_session *sess, struct tee_ta_session_head *open_sessions, const TEE_Identity *clnt_id); struct tee_ta_session *tee_ta_find_session(uint32_t id, struct tee_ta_session_head *open_sessions); struct tee_ta_session *tee_ta_get_session(uint32_t id, bool exclusive, struct tee_ta_session_head *open_sessions); void tee_ta_put_session(struct tee_ta_session *sess); #if defined(CFG_TA_GPROF_SUPPORT) void tee_ta_update_session_utime_suspend(void); void tee_ta_update_session_utime_resume(void); void tee_ta_gprof_sample_pc(vaddr_t pc); #else static inline void tee_ta_update_session_utime_suspend(void) {} static inline void tee_ta_update_session_utime_resume(void) {} static inline void tee_ta_gprof_sample_pc(vaddr_t pc __unused) {} #endif #if defined(CFG_FTRACE_SUPPORT) void tee_ta_ftrace_update_times_suspend(void); void tee_ta_ftrace_update_times_resume(void); #else static inline void tee_ta_ftrace_update_times_suspend(void) {} static inline void tee_ta_ftrace_update_times_resume(void) {} #endif bool is_ta_ctx(struct ts_ctx *ctx); struct tee_ta_session *to_ta_session(struct ts_session *sess); static inline struct tee_ta_ctx *__noprof to_ta_ctx(struct ts_ctx *ctx) { assert(is_ta_ctx(ctx)); return container_of(ctx, struct tee_ta_ctx, ts_ctx); } #if defined(CFG_TA_STATS) TEE_Result tee_ta_instance_stats(void *buff, size_t *buff_size); #endif #endif optee_os-4.3.0/core/include/kernel/tee_time.h000066400000000000000000000012711464416617300211470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_TEE_TIME_H #define __KERNEL_TEE_TIME_H #include "tee_api_types.h" TEE_Result tee_time_get_sys_time(TEE_Time *time); uint32_t tee_time_get_sys_time_protection_level(void); TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time); TEE_Result tee_time_get_ree_time(TEE_Time *time); TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time); /* Releases CPU through OP-TEE RPC which switches to Normal World */ void tee_time_wait(uint32_t milliseconds_delay); /* Busy wait */ void tee_time_busy_wait(uint32_t milliseconds_delay); #endif optee_os-4.3.0/core/include/kernel/thread.h000066400000000000000000000261731464416617300206330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2016-2017, Linaro Limited * Copyright (c) 2020-2021, Arm Limited */ #ifndef __KERNEL_THREAD_H #define __KERNEL_THREAD_H #ifndef __ASSEMBLER__ #include #include #include #endif #include #include #define THREAD_FLAGS_COPY_ARGS_ON_RETURN BIT(0) #define THREAD_FLAGS_FOREIGN_INTR_ENABLE BIT(1) #define THREAD_FLAGS_EXIT_ON_FOREIGN_INTR BIT(2) #define THREAD_FLAGS_FFA_ONLY BIT(3) #define THREAD_ID_0 0 #define THREAD_ID_INVALID -1 #define THREAD_RPC_MAX_NUM_PARAMS U(4) #ifndef __ASSEMBLER__ struct thread_specific_data { TAILQ_HEAD(, ts_session) sess_stack; struct ts_ctx *ctx; #ifdef CFG_CORE_FFA uint32_t rpc_target_info; #endif uint32_t abort_type; uint32_t abort_descr; vaddr_t abort_va; unsigned int abort_core; struct thread_abort_regs abort_regs; #ifdef CFG_CORE_DEBUG_CHECK_STACKS bool stackcheck_recursion; #endif unsigned int syscall_recursion; #ifdef CFG_FAULT_MITIGATION struct ftmn_func_arg *ftmn_arg; #endif }; void thread_init_canaries(void); void thread_init_primary(void); void thread_init_per_cpu(void); #if defined(CFG_WITH_STACK_CANARIES) void thread_update_canaries(void); #else static inline void thread_update_canaries(void) { } #endif struct thread_core_local *thread_get_core_local(void); /* * Sets the stacks to be used by the different threads. Use THREAD_ID_0 for * first stack, THREAD_ID_0 + 1 for the next and so on. * * Returns true on success and false on errors. */ bool thread_init_stack(uint32_t stack_id, vaddr_t sp); /* * Initializes thread contexts. Called in thread_init_boot_thread() if * virtualization is disabled. Virtualization subsystem calls it for * every new guest otherwise. */ void thread_init_threads(void); /* * Called by the init CPU. Sets temporary stack mode for all CPUs * (curr_thread = -1 and THREAD_CLF_TMP) and sets the temporary stack limit for * the init CPU. */ void thread_init_thread_core_local(void); void thread_init_core_local_stacks(void); #if defined(CFG_CORE_PAUTH) void thread_init_thread_pauth_keys(void); void thread_init_core_local_pauth_keys(void); #else static inline void thread_init_thread_pauth_keys(void) { } static inline void thread_init_core_local_pauth_keys(void) { } #endif /* * Initializes a thread to be used during boot */ void thread_init_boot_thread(void); /* * Clears the current thread id * Only supposed to be used during initialization. */ void thread_clr_boot_thread(void); /* * Returns current thread id. */ short int thread_get_id(void); /* * Returns current thread id, return -1 on failure. */ short int thread_get_id_may_fail(void); /* Returns Thread Specific Data (TSD) pointer. */ struct thread_specific_data *thread_get_tsd(void); /* * Sets foreign interrupts status for current thread, must only be called * from an active thread context. * * enable == true -> enable foreign interrupts * enable == false -> disable foreign interrupts */ void thread_set_foreign_intr(bool enable); /* * Restores the foreign interrupts status (in CPSR) for current thread, must * only be called from an active thread context. */ void thread_restore_foreign_intr(void); /* * thread_get_exceptions() - return current exception mask */ uint32_t thread_get_exceptions(void); /* * thread_set_exceptions() - set exception mask * @exceptions: exception mask to set * * Any previous exception mask is replaced by this exception mask, that is, * old bits are cleared and replaced by these. */ void thread_set_exceptions(uint32_t exceptions); /* * thread_mask_exceptions() - Masks (disables) specified asynchronous exceptions * @exceptions exceptions to mask * @returns old exception state */ uint32_t thread_mask_exceptions(uint32_t exceptions); /* * thread_unmask_exceptions() - Unmasks asynchronous exceptions * @state Old asynchronous exception state to restore (returned by * thread_mask_exceptions()) */ void thread_unmask_exceptions(uint32_t state); static inline bool __nostackcheck thread_foreign_intr_disabled(void) { return !!(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); } /* * thread_enter_user_mode() - Enters user mode * @a0: Passed in r/x0 for user_func * @a1: Passed in r/x1 for user_func * @a2: Passed in r/x2 for user_func * @a3: Passed in r/x3 for user_func * @user_sp: Assigned sp value in user mode * @user_func: Function to execute in user mode * @is_32bit: True if TA should execute in Aarch32, false if Aarch64 * @exit_status0: Pointer to opaque exit staus 0 * @exit_status1: Pointer to opaque exit staus 1 * * This functions enters user mode with the argument described above, * @exit_status0 and @exit_status1 are filled in by thread_unwind_user_mode() * when returning back to the caller of this function through an exception * handler. * * @Returns what's passed in "ret" to thread_unwind_user_mode() */ uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, bool is_32bit, uint32_t *exit_status0, uint32_t *exit_status1); /* * thread_unwind_user_mode() - Unwinds kernel stack from user entry * @ret: Value to return from thread_enter_user_mode() * @exit_status0: Exit status 0 * @exit_status1: Exit status 1 * * This is the function that exception handlers can return into * to resume execution in kernel mode instead of user mode. * * This function is closely coupled with thread_enter_user_mode() since it * need to restore registers saved by thread_enter_user_mode() and when it * returns make it look like thread_enter_user_mode() just returned. It is * expected that the stack pointer is where thread_enter_user_mode() left * it. The stack will be unwound and the function will return to where * thread_enter_user_mode() was called from. Exit_status0 and exit_status1 * are filled in the corresponding pointers supplied to * thread_enter_user_mode(). */ void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0, uint32_t exit_status1); /* * Returns the start address (bottom) of the stack for the current thread, * zero if there is no current thread. */ vaddr_t thread_stack_start(void); /* Returns the stack size for the current thread */ size_t thread_stack_size(void); /* * Returns the start (top, lowest address) and end (bottom, highest address) of * the current stack (thread, temporary or abort stack). * When CFG_CORE_DEBUG_CHECK_STACKS=y, the @hard parameter tells if the hard or * soft limits are queried. The difference between soft and hard is that for the * latter, the stack start includes some additional space to let any function * overflow the soft limit and still be able to print a stack dump in this case. */ bool get_stack_limits(vaddr_t *start, vaddr_t *end, bool hard); static inline bool __nostackcheck get_stack_soft_limits(vaddr_t *start, vaddr_t *end) { return get_stack_limits(start, end, false); } static inline bool __nostackcheck get_stack_hard_limits(vaddr_t *start, vaddr_t *end) { return get_stack_limits(start, end, true); } bool thread_is_in_normal_mode(void); /* * Returns true if previous exeception also was in abort mode. * * Note: it's only valid to call this function from an abort exception * handler before interrupts has been re-enabled. */ bool thread_is_from_abort_mode(void); /** * Allocates data for payload buffers. * * @size: size in bytes of payload buffer * * @returns mobj that describes allocated buffer or NULL on error */ struct mobj *thread_rpc_alloc_payload(size_t size); /** * Free physical memory previously allocated with thread_rpc_alloc_payload() * * @mobj: mobj that describes the buffer */ void thread_rpc_free_payload(struct mobj *mobj); /** * Allocate data for payload buffers only shared with the non-secure kernel * * @size: size in bytes of payload buffer * * @returns mobj that describes allocated buffer or NULL on error */ struct mobj *thread_rpc_alloc_kernel_payload(size_t size); /** * Free physical memory previously allocated with * thread_rpc_alloc_kernel_payload() * * @mobj: mobj that describes the buffer */ void thread_rpc_free_kernel_payload(struct mobj *mobj); struct thread_param_memref { size_t offs; size_t size; struct mobj *mobj; }; struct thread_param_value { uint64_t a; uint64_t b; uint64_t c; }; /* * Note that there's some arithmetics done on the value so it's important * to keep in IN, OUT, INOUT order. */ enum thread_param_attr { THREAD_PARAM_ATTR_NONE = 0, THREAD_PARAM_ATTR_VALUE_IN, THREAD_PARAM_ATTR_VALUE_OUT, THREAD_PARAM_ATTR_VALUE_INOUT, THREAD_PARAM_ATTR_MEMREF_IN, THREAD_PARAM_ATTR_MEMREF_OUT, THREAD_PARAM_ATTR_MEMREF_INOUT, }; struct thread_param { enum thread_param_attr attr; union { struct thread_param_memref memref; struct thread_param_value value; } u; }; #define THREAD_PARAM_MEMREF(_direction, _mobj, _offs, _size) \ (struct thread_param){ \ .attr = THREAD_PARAM_ATTR_MEMREF_ ## _direction, .u.memref = { \ .mobj = (_mobj), .offs = (_offs), .size = (_size) } \ } #define THREAD_PARAM_VALUE(_direction, _a, _b, _c) \ (struct thread_param){ \ .attr = THREAD_PARAM_ATTR_VALUE_ ## _direction, .u.value = { \ .a = (_a), .b = (_b), .c = (_c) } \ } /** * Does an RPC using a preallocated argument buffer * @cmd: RPC cmd * @num_params: number of parameters * @params: RPC parameters * @returns RPC return value */ uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params, struct thread_param *params); /** * Allocate data for payload buffers. * Buffer is exported to user mode applications. * * @size: size in bytes of payload buffer * * @returns mobj that describes allocated buffer or NULL on error */ struct mobj *thread_rpc_alloc_global_payload(size_t size); /** * Free physical memory previously allocated with * thread_rpc_alloc_global_payload() * * @mobj: mobj that describes the buffer */ void thread_rpc_free_global_payload(struct mobj *mobj); /* * enum thread_shm_type - type of non-secure shared memory * @THREAD_SHM_TYPE_APPLICATION - user space application shared memory * @THREAD_SHM_TYPE_KERNEL_PRIVATE - kernel private shared memory * @THREAD_SHM_TYPE_GLOBAL - user space and kernel shared memory */ enum thread_shm_type { THREAD_SHM_TYPE_APPLICATION, THREAD_SHM_TYPE_KERNEL_PRIVATE, THREAD_SHM_TYPE_GLOBAL, }; /* * enum thread_shm_cache_user - user of a cache allocation * @THREAD_SHM_CACHE_USER_SOCKET - socket communication * @THREAD_SHM_CACHE_USER_FS - filesystem access * @THREAD_SHM_CACHE_USER_I2C - I2C communication * * To ensure that each user of the shared memory cache doesn't interfere * with each other a unique ID per user is used. */ enum thread_shm_cache_user { THREAD_SHM_CACHE_USER_SOCKET, THREAD_SHM_CACHE_USER_FS, THREAD_SHM_CACHE_USER_I2C, }; /* * Returns a pointer to the cached RPC memory. Each thread and @user tuple * has a unique cache. The pointer is guaranteed to point to a large enough * area or to be NULL. */ void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user, enum thread_shm_type shm_type, size_t size, struct mobj **mobj); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_THREAD_H*/ optee_os-4.3.0/core/include/kernel/thread_private.h000066400000000000000000000045251464416617300223620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __KERNEL_THREAD_PRIVATE_H #define __KERNEL_THREAD_PRIVATE_H #include #ifndef __ASSEMBLER__ #include #include #include #include #include enum thread_state { THREAD_STATE_FREE, THREAD_STATE_SUSPENDED, THREAD_STATE_ACTIVE, }; struct thread_shm_cache_entry { struct mobj *mobj; size_t size; enum thread_shm_type type; enum thread_shm_cache_user user; SLIST_ENTRY(thread_shm_cache_entry) link; }; SLIST_HEAD(thread_shm_cache, thread_shm_cache_entry); struct thread_ctx { struct thread_ctx_regs regs; enum thread_state state; vaddr_t stack_va_end; uint32_t flags; struct core_mmu_user_map user_map; bool have_user_map; #if defined(ARM64) || defined(RV64) vaddr_t kern_sp; /* Saved kernel SP during user TA execution */ #endif #ifdef CFG_CORE_PAUTH struct thread_pauth_keys keys; #endif #ifdef CFG_WITH_VFP struct thread_vfp_state vfp_state; #endif void *rpc_arg; struct mobj *rpc_mobj; struct thread_shm_cache shm_cache; struct thread_specific_data tsd; }; #endif /*__ASSEMBLER__*/ /* Describes the flags field of struct thread_core_local */ #define THREAD_CLF_SAVED_SHIFT 4 #define THREAD_CLF_CURR_SHIFT 0 #define THREAD_CLF_MASK 0xf #define THREAD_CLF_TMP_SHIFT 0 #define THREAD_CLF_ABORT_SHIFT 1 #define THREAD_CLF_IRQ_SHIFT 2 #define THREAD_CLF_FIQ_SHIFT 3 #define THREAD_CLF_TMP BIT(THREAD_CLF_TMP_SHIFT) #define THREAD_CLF_ABORT BIT(THREAD_CLF_ABORT_SHIFT) #define THREAD_CLF_IRQ BIT(THREAD_CLF_IRQ_SHIFT) #define THREAD_CLF_FIQ BIT(THREAD_CLF_FIQ_SHIFT) #ifndef __ASSEMBLER__ extern const void *stack_tmp_export; extern const uint32_t stack_tmp_stride; extern struct thread_ctx threads[]; extern struct thread_core_local thread_core_local[]; #ifdef CFG_WITH_STACK_CANARIES #define STACK_CANARY_SIZE (4 * sizeof(long)) #else #define STACK_CANARY_SIZE 0 #endif /* Checks stack canaries */ void thread_check_canaries(void); void thread_lock_global(void); void thread_unlock_global(void); /* Frees the cache of allocated FS RPC memory */ void thread_rpc_shm_cache_clear(struct thread_shm_cache *cache); #endif /*__ASSEMBLER__*/ #endif /*__KERNEL_THREAD_PRIVATE_H*/ optee_os-4.3.0/core/include/kernel/timer.h000066400000000000000000000021421464416617300204720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2018, 2024, Linaro Limited */ #ifndef __KERNEL_TIMER_H #define __KERNEL_TIMER_H #include #include void generic_timer_start(uint32_t time_ms); void generic_timer_stop(void); /* Handler for timer expiry interrupt */ void generic_timer_handler(uint32_t time_ms); /* * timer_init_callout_service() - Initializes the callout service * @itr_chip: Interrupt chip, typically interrupt_get_main_chip() * @itr_number: Interrupt number in @itr_chip space for the timer. * * This function starts the callout service via interrupts from the timer. * The platform or architecture specific code provides the implementation * of this function. The interrupt callback function for the timer calls * callout_service_cb() to drive the callout service. * * Note that usage of this function is incompatible with usage of the * generic_timer_start(), generic_timer_stop() and generic_timer_handler() * functions. */ void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number); #endif /* __KERNEL_TIMER_H */ optee_os-4.3.0/core/include/kernel/tpm.h000066400000000000000000000022761464416617300201620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 2020-2022, ARM Limited. All rights reserved. */ #ifndef __KERNEL_TPM_H__ #define __KERNEL_TPM_H__ #include #ifdef CFG_CORE_TPM_EVENT_LOG /* * Returns the TPM Event Log information previously retrieved * by @tpm_map_log_area. * * @buf Pointer to a buffer where to store a copy of the TPM Event log. */ TEE_Result tpm_get_event_log(void *buf, size_t *size); TEE_Result tpm_get_event_log_size(size_t *size); /* * Reads the TPM Event log information and store it internally. * If support for DTB is enabled, it will read the parameters there. * Otherwise, it will use the constant parameters hardcoded in conf.mk. * * @fdt Pointer to the DTB blob where the TPM Event log information * is expected to be. */ void tpm_map_log_area(void *fdt); #else static inline TEE_Result tpm_get_event_log(void *buf __unused, size_t *size __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result tpm_get_event_log_size(size_t *size __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void tpm_map_log_area(void *fdt __unused) {} #endif /* CFG_CORE_TPM_EVENT_LOG */ #endif /* __KERNEL_TPM_H__ */ optee_os-4.3.0/core/include/kernel/trace_ta.h000066400000000000000000000006561464416617300211440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __KERNEL_TRACE_TA_H #define __KERNEL_TRACE_TA_H #include /* Macros to trace TA related events, logs, TA crash info etc */ #ifdef CFG_TEE_CORE_TA_TRACE #define TAMSG(...) EMSG(__VA_ARGS__) #define TAMSG_RAW(...) EMSG_RAW(__VA_ARGS__) #else #define TAMSG(...) #define TAMSG_RAW(...) #endif #endif /*__KERNEL_TRACE_TA_H*/ optee_os-4.3.0/core/include/kernel/transfer_list.h000066400000000000000000000104671464416617300222420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, Linaro Limited */ #ifndef __KERNEL_TRANSFER_LIST_H #define __KERNEL_TRANSFER_LIST_H #define TRANSFER_LIST_SIGNATURE U(0x4a0fb10b) #define TRANSFER_LIST_VERSION U(0x0001) /* * Init value of maximum alignment required by any transfer entry data in the TL * specified as a power of two */ #define TRANSFER_LIST_INIT_MAX_ALIGN U(3) /* Alignment required by transfer entry header start address, in bytes */ #define TRANSFER_LIST_GRANULE U(8) /* * Version of the register convention used. * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9 */ #define REG_CONVENTION_VER_MASK BIT(24) #define TL_FLAGS_HAS_CHECKSUM BIT(0) /* Transfer list operation codes */ #define TL_OPS_NONE U(0) /* invalid for any operation */ #define TL_OPS_ALL U(1) /* valid for all operations */ #define TL_OPS_RO U(2) /* valid for read only */ #define TL_OPS_CUS U(3) /* either abort or special code to interpret */ #ifndef __ASSEMBLER__ #include /* Get alignment from a value specified as power of two */ #define TL_ALIGNMENT_FROM_ORDER(a) BIT(a) enum transfer_list_tag_id { TL_TAG_EMPTY = 0, TL_TAG_FDT = 1, TL_TAG_HOB_BLOCK = 2, TL_TAG_HOB_LIST = 3, TL_TAG_ACPI_TABLE_AGGREGATE = 4, TL_TAG_OPTEE_PAGABLE_PART = 0x100, }; struct transfer_list_header { uint32_t signature; uint8_t checksum; uint8_t version; uint8_t hdr_size; uint8_t alignment; /* max alignment of transfer entry data */ uint32_t size; /* TL header + all transfer entries */ uint32_t max_size; uint32_t flags; uint32_t reserved; /* spare bytes */ /* * Commented out element used to visualize dynamic part of the * data structure. * * Note that struct transfer_list_entry also is dynamic in size * so the elements can't be indexed directly but instead must be * traversed in order * * struct transfer_list_entry entries[]; */ }; struct transfer_list_entry { uint16_t tag_id; uint8_t reserved0; /* place holder for tag ID 3rd byte (MSB) */ uint8_t hdr_size; uint32_t data_size; /* * Commented out element used to visualize dynamic part of the * data structure. * * Note that padding is added at the end of @data to make it reach * a 8-byte boundary. * * uint8_t data[ROUNDUP(data_size, 8)]; */ }; struct transfer_list_header *transfer_list_map(paddr_t pa); void transfer_list_unmap_sync(struct transfer_list_header *tl); void transfer_list_unmap_nosync(struct transfer_list_header *tl); void transfer_list_dump(struct transfer_list_header *tl); struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size); struct transfer_list_header * transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa, size_t max_size); #if defined(CFG_TRANSFER_LIST) int transfer_list_check_header(const struct transfer_list_header *tl); struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl, uint16_t tag_id); void *transfer_list_entry_data(struct transfer_list_entry *tl_e); #else /* CFG_TRANSFER_LIST */ static inline int transfer_list_check_header(const struct transfer_list_header *tl __unused) { return TL_OPS_NONE; } static inline struct transfer_list_entry * transfer_list_find(struct transfer_list_header *tl __unused, uint16_t tag_id __unused) { return NULL; } static inline void * transfer_list_entry_data(struct transfer_list_entry *tl_e __unused) { return NULL; } #endif /* CFG_TRANSFER_LIST */ void transfer_list_update_checksum(struct transfer_list_header *tl); bool transfer_list_verify_checksum(const struct transfer_list_header *tl); bool transfer_list_set_data_size(struct transfer_list_header *tl, struct transfer_list_entry *tl_e, uint32_t new_data_size); bool transfer_list_rem(struct transfer_list_header *tl, struct transfer_list_entry *tl_e); struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl, uint16_t tag_id, uint32_t data_size, const void *data); struct transfer_list_entry * transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id, uint32_t data_size, const void *data, uint8_t alignment); struct transfer_list_entry * transfer_list_next(struct transfer_list_header *tl, struct transfer_list_entry *last); #endif /*__ASSEMBLER__*/ #endif /*__TRANSFER_LIST_H*/ optee_os-4.3.0/core/include/kernel/ts_manager.h000066400000000000000000000052141464416617300214750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2017-2020, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef __KERNEL_TS_MANAGER_H #define __KERNEL_TS_MANAGER_H #include #include struct ts_ctx { TEE_UUID uuid; const struct ts_ops *ops; }; struct thread_scall_regs; struct ts_session { TAILQ_ENTRY(ts_session) link_tsd; struct ts_ctx *ctx; /* Generic TS context */ #if defined(CFG_TA_GPROF_SUPPORT) struct sample_buf *sbuf; /* Profiling data (PC sampling) */ #endif #if defined(CFG_FTRACE_SUPPORT) struct ftrace_buf *fbuf; /* ftrace buffer */ #endif /* * Used by PTAs to store session specific information, or used by ldelf * syscalls to store handlers of opened TA/SP binaries. */ void *user_ctx; bool (*handle_scall)(struct thread_scall_regs *regs); }; enum ts_gprof_status { TS_GPROF_SUSPEND, TS_GPROF_RESUME, }; /* * struct ts_ops - Trusted Service operations * The operations below are called when: * @enter_open_session(): opening a session to the service * @enter_invoke_cmd(): invoking a command in the service * @enter_close_session(): closing a session to the service * @dump_mem_stats(): dumping heap state of the service * @dump_state(): dumping active memory mappings * @dump_ftrace(): dumping the ftrace data via RPC * @release_state(): the service has panicked and as much state * as possible need to be released * @destroy(): freeing the struct ts_ctx removing all * trace of the service * @get_instance_id(): a unique ID of the service is needed * @handle_scall(): handling a syscall from the service * @gprof_set_status(): updating the gprof status of the service */ struct ts_ops { TEE_Result (*enter_open_session)(struct ts_session *s); TEE_Result (*enter_invoke_cmd)(struct ts_session *s, uint32_t cmd); void (*enter_close_session)(struct ts_session *s); #if defined(CFG_TA_STATS) TEE_Result (*dump_mem_stats)(struct ts_session *s); #endif void (*dump_state)(struct ts_ctx *ctx); void (*dump_ftrace)(struct ts_ctx *ctx); void (*release_state)(struct ts_ctx *ctx); void (*destroy)(struct ts_ctx *ctx); uint32_t (*get_instance_id)(struct ts_ctx *ctx); bool (*handle_scall)(struct thread_scall_regs *regs); #ifdef CFG_TA_GPROF_SUPPORT void (*gprof_set_status)(enum ts_gprof_status status); #endif }; struct ts_session *ts_get_current_session(void); struct ts_session *ts_get_current_session_may_fail(void); void ts_push_current_session(struct ts_session *sess); struct ts_session *ts_pop_current_session(void); struct ts_session *ts_get_calling_session(void); #endif /*__KERNEL_TS_MANAGER_H*/ optee_os-4.3.0/core/include/kernel/ts_store.h000066400000000000000000000056501464416617300212230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2019, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #ifndef __KERNEL_TS_STORE_H #define __KERNEL_TS_STORE_H #include struct ts_store_handle; struct ts_store_ops { /* * Human-readable string to describe where the TS comes from. * For debug purposes only. */ const char *description; /* * Open a TS. Does not guarantee that the TS is valid or even exists. */ TEE_Result (*open)(const TEE_UUID *uuid, struct ts_store_handle **h); /* * Return the size of the unencrypted TS binary, that is: the TS * header (struct ta_head or sp_head) plus the ELF data. */ TEE_Result (*get_size)(const struct ts_store_handle *h, size_t *size); /* * Return the tag or hash of the TS binary. Used to uniquely * identify the binary also if the binary happens to be updated. */ TEE_Result (*get_tag)(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len); /* * Read the TS sequentially, from the start of the TS header (struct * ta_head or sp_head) up to the end of the ELF. * The TEE core is expected to read *exactly* get_size() bytes in total * unless an error occurs. Therefore, an implementation may rely on the * condition (current offset == total size) to detect the last call to * this function. * @data_core: pointer to secure memory where the TS bytes should be * copied. * @data_user: pointer to user memory where the TS bytes should be * copied. * At least one of @data_core and @data_user are normally NULL, but * both are also permitted to be non-NULL. * If @data_core == NULL and @data_user == NULL and @len != 0, the * function should just skip @len bytes. */ TEE_Result (*read)(struct ts_store_handle *h, void *data_core, void *data_user, size_t len); /* * Close a TS handle. Do nothing if @h == NULL. */ void (*close)(struct ts_store_handle *h); }; /* * Registers a TA storage. * * A TA is loaded from the first TA storage in which the TA can be found. * TA storage is searched in order of priority, where lower values are * tried first. * * Note prio must be unique per storage in order to avoid dependency on * registration order. This is enforced by a deliberate linker error in * case of conflict. * * Also note that TA storage is sorted lexicographically instead of * numerically. */ #define REGISTER_TA_STORE(prio) \ int __tee_ta_store_##prio __unused; \ SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(ta_stores, prio, \ struct ts_store_ops) /* * Registers a SP storage. * * The SP store is separate from the TA store. The user of the stores knows if * it needs to access the TA store or if it needs to access the SP one. */ #define REGISTER_SP_STORE(prio) \ int __tee_sp_store_##prio __unused; \ SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(sp_stores, prio, \ struct ts_store_ops) #endif /*__KERNEL_TS_STORE_H*/ optee_os-4.3.0/core/include/kernel/unwind.h000066400000000000000000000011301464416617300206520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /*- * Copyright (c) 2015-2019 Linaro Limited * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #ifndef __KERNEL_UNWIND #define __KERNEL_UNWIND #include #if defined(CFG_UNWIND) && (TRACE_LEVEL > 0) void print_kernel_stack(void); #else static inline void print_kernel_stack(void) { } #endif #ifdef CFG_UNWIND /* Get current call stack as an array allocated on the heap */ vaddr_t *unw_get_kernel_stack(void); #else static inline void *unw_get_kernel_stack(void) { return NULL; } #endif /* CFG_UNWIND */ #endif /*__KERNEL_UNWIND*/ optee_os-4.3.0/core/include/kernel/user_access.h000066400000000000000000000137221464416617300216570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Linaro Limited */ #ifndef __KERNEL_USER_ACCESS_H #define __KERNEL_USER_ACCESS_H #include #include #include #include #ifdef CFG_WITH_USER_TA TEE_Result check_user_access(uint32_t flags, const void *uaddr, size_t len); TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len); TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len); TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len); TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len); #else static inline TEE_Result check_user_access(uint32_t flags __unused, const void *uaddr __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result copy_from_user_private(void *kaddr __unused, const void *uaddr __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result copy_from_user(void *kaddr __unused, const void *uaddr __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result copy_to_user_private(void *uaddr __unused, const void *kaddr __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result copy_to_user(void *uaddr __unused, const void *kaddr __unused, size_t len __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* * bb_alloc() - Allocate a bounce buffer * @len: Length of bounce buffer * * The bounce buffer is allocated from a per user TA context region reserved * for bounce buffers. Buffers are allocated in a stack like fashion so * only the last buffer can be free. Buffers generally don't have to be * freed, all bounce buffer allocations are reset on each syscall entry. * * Return NULL on failure or a valid pointer on success. */ void *bb_alloc(size_t len); /* * bb_free() - Free a bounce buffer * @bb: Buffer * @len: Length of buffer * * The bounce buffer is only freed if it is last on the stack of allocated * bounce buffers. This function does normally not need to be called, see * description of bb_alloc(). */ void bb_free(void *bb, size_t len); /* * bb_free_wipe() - Wipe and free a bounce buffer * @bb: Buffer * @len: Length of buffer * * The bounce buffer is always wiped if @bb is non-NULL, but only freed if * it is last on the stack of allocated bounce buffers. */ void bb_free_wipe(void *bb, size_t len); /* * bb_reset() - Reset bounce buffer allocation * * Resets the bounce buffer allocatation state, old pointers allocated * with bb_alloc() should not be used any longer. */ void bb_reset(void); TEE_Result clear_user(void *uaddr, size_t n); size_t strnlen_user(const void *s, size_t n); #define __BB_MEMDUP(memdup_func, src, len, p) ({ \ TEE_Result __res = TEE_SUCCESS; \ void *__p = NULL; \ \ __res = memdup_func((src), (len), &__p); \ if (!__res) \ *(p) = __p; \ __res; \ }) /* * bb_memdup_user() - Duplicate a user-space buffer into a bounce buffer * @src: Pointer to the user buffer to be duplicated. * @len: Length of the user buffer to be duplicated. * @p: Holds duplicated bounce buffer on success, or unchanged on failure. * Note that the returned buffer is allocated by bb_alloc() and * normally doesn't have to be freed. * Return TEE_SUCCESS on success. * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error. */ TEE_Result bb_memdup_user(const void *src, size_t len, void **p); #define BB_MEMDUP_USER(src, len, p) \ __BB_MEMDUP(bb_memdup_user, (src), (len), (p)) /* * bb_memdup_user_private() - Duplicate a private user-space buffer * @src: Pointer to the user buffer to be duplicated. The buffer should * be private to current TA (i.e., !TEE_MEMORY_ACCESS_ANY_OWNER). * @len: Length of the user buffer to be duplicated. * @p: Holds duplicated kernel buffer on success, or unchanged on failure. * Note that the returned buffer is allocated by bb_alloc() and * normally doesn't have to be freed. * Return TEE_SUCCESS on success. * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error. */ TEE_Result bb_memdup_user_private(const void *src, size_t len, void **p); #define BB_MEMDUP_USER_PRIVATE(src, len, p) \ __BB_MEMDUP(bb_memdup_user_private, (src), (len), (p)) /* * bb_strndup_user() - Duplicate a user-space string into a bounce buffer * @src: Pointer to the user string to be duplicated. * @maxlen: Maximum length of the user string * @dst: Holds duplicated string on success, or unchanged on failure. * @dstlen: Length of string, excluding the terminating zero, returned in * @dst. * * Note that the returned buffer is allocated by bb_alloc() and normally * doesn't have to be freed. But if it is to be freed the supplied length * to bb_free() should be dstlen + 1. * * Return TEE_SUCCESS on success. * Return TEE_ERROR_OUT_OF_MEMORY or TEE_ERROR_ACCESS_DENIED on error. */ TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst, size_t *dstlen); TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr); uint32_t kaddr_to_uref(void *kaddr); vaddr_t uref_to_vaddr(uint32_t uref); static inline void *uref_to_kaddr(uint32_t uref) { return (void *)uref_to_vaddr(uref); } #define GET_USER_SCALAR(_x, _p) ({ \ TEE_Result __res = TEE_SUCCESS; \ typeof(_p) __p = (_p); \ \ static_assert(sizeof(_x) == sizeof(*__p)); \ \ __res = copy_from_user(&(_x), (const void *)__p, sizeof(*__p)); \ __res; \ }) #define PUT_USER_SCALAR(_x, _p) ({ \ TEE_Result __res = TEE_SUCCESS; \ typeof(_p) __p = (_p); \ \ static_assert(sizeof(_x) == sizeof(*__p)); \ \ __res = copy_to_user((void *)__p, &(_x), sizeof(*__p)); \ __res; \ }) #endif /*__KERNEL_USER_ACCESS_H*/ optee_os-4.3.0/core/include/kernel/user_mode_ctx.h000066400000000000000000000015041464416617300222130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2021, Arm Limited */ #ifndef __KERNEL_USER_MODE_CTX_H #define __KERNEL_USER_MODE_CTX_H #include #include #include #include #include #include static inline bool is_user_mode_ctx(struct ts_ctx *ctx) { return is_user_ta_ctx(ctx) || is_stmm_ctx(ctx) || is_sp_ctx(ctx); } static inline struct user_mode_ctx *to_user_mode_ctx(struct ts_ctx *ctx) { if (is_user_ta_ctx(ctx)) return &to_user_ta_ctx(ctx)->uctx; else if (is_sp_ctx(ctx)) return &to_sp_ctx(ctx)->uctx; else return &to_stmm_ctx(ctx)->uctx; } void user_mode_ctx_print_mappings(struct user_mode_ctx *umctx); #endif /*__KERNEL_USER_MODE_CTX_H*/ optee_os-4.3.0/core/include/kernel/user_mode_ctx_struct.h000066400000000000000000000032661464416617300236260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2021, Linaro Limited * Copyright (c) 2020-2023, Arm Limited */ #ifndef __KERNEL_USER_MODE_CTX_STRUCT_H #define __KERNEL_USER_MODE_CTX_STRUCT_H #include #include #include /* * struct user_mode_ctx - user mode context * @vm_info: Virtual memory map of this context * @regions: Memory regions registered by pager * @vfp: State of VFP registers * @keys: Pointer authentication keys * @ts_ctx: Generic TS context * @entry_func: Entry address in TS * @dump_entry_func: Entry address in TS for dumping address mappings * and stack trace * @ftrace_entry_func: Entry address in ldelf for dumping ftrace data * @dl_entry_func: Entry address in ldelf for dynamic linking * @ldelf_stack_ptr: Stack pointer used for dumping address mappings and * stack trace * @is_32bit: True if 32-bit TS, false if 64-bit TS * @stack_ptr: Stack pointer * @bbuf: Bounce buffer for user buffers * @bbuf_size: Size of bounce buffer * @bbuf_offs: Offset to unused part of bounce buffer */ struct user_mode_ctx { struct vm_info vm_info; struct vm_paged_region_head *regions; struct pgt_cache pgt_cache; #if defined(CFG_WITH_VFP) struct thread_user_vfp_state vfp; #endif #if defined(CFG_TA_PAUTH) struct thread_pauth_keys keys; #endif struct ts_ctx *ts_ctx; uaddr_t entry_func; uaddr_t load_addr; uaddr_t dump_entry_func; #ifdef CFG_FTRACE_SUPPORT uaddr_t ftrace_entry_func; #endif uaddr_t dl_entry_func; uaddr_t ldelf_stack_ptr; bool is_32bit; vaddr_t stack_ptr; uint8_t *bbuf; size_t bbuf_size; size_t bbuf_offs; }; #endif /*__KERNEL_USER_MODE_CTX_STRUCT_H*/ optee_os-4.3.0/core/include/kernel/user_ta.h000066400000000000000000000045151464416617300210220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef __KERNEL_USER_TA_H #define __KERNEL_USER_TA_H #include #include #include #include #include #include #include #include #include #include TAILQ_HEAD(tee_cryp_state_head, tee_cryp_state); TAILQ_HEAD(tee_obj_head, tee_obj); TAILQ_HEAD(tee_storage_enum_head, tee_storage_enum); SLIST_HEAD(load_seg_head, load_seg); /* * struct user_ta_ctx - user TA context * @open_sessions: List of sessions opened by this TA * @cryp_states: List of cryp states created by this TA * @objects: List of storage objects opened by this TA * @storage_enums: List of storage enumerators opened by this TA * @uctx: Generic user mode context * @ctx: Generic TA context */ struct user_ta_ctx { struct tee_ta_session_head open_sessions; struct tee_cryp_state_head cryp_states; struct tee_obj_head objects; struct tee_storage_enum_head storage_enums; struct user_mode_ctx uctx; struct tee_ta_ctx ta_ctx; }; #ifdef CFG_WITH_USER_TA bool is_user_ta_ctx(struct ts_ctx *ctx); #else static inline bool __noprof is_user_ta_ctx(struct ts_ctx *ctx __unused) { return false; } #endif static inline struct user_ta_ctx *to_user_ta_ctx(struct ts_ctx *ctx) { assert(is_user_ta_ctx(ctx)); return container_of(ctx, struct user_ta_ctx, ta_ctx.ts_ctx); } #ifdef CFG_WITH_USER_TA /* * Setup session context for a user TA * @uuid: TA UUID * @s: Session for which to setup a user TA context * * This function must be called with tee_ta_mutex locked. */ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid, struct tee_ta_session *s); /* * Finalize session context initialization for a user TA * @sess: Session for which to finalize user TA context */ TEE_Result tee_ta_complete_user_ta_session(struct tee_ta_session *s); #else static inline TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid __unused, struct tee_ta_session *s __unused) { return TEE_ERROR_ITEM_NOT_FOUND; } static inline TEE_Result tee_ta_complete_user_ta_session(struct tee_ta_session *s __unused) { return TEE_ERROR_GENERIC; } #endif /*CFG_WITH_USER_TA*/ #endif /*__KERNEL_USER_TA_H*/ optee_os-4.3.0/core/include/kernel/virtualization.h000066400000000000000000000212641464416617300224440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, EPAM Systems. All rights reserved. * Copyright (c) 2024, Linaro Limited */ #ifndef __KERNEL_VIRTUALIZATION_H #define __KERNEL_VIRTUALIZATION_H #include #include #include #include #include #define HYP_CLNT_ID 0 struct guest_partition; #if defined(CFG_NS_VIRTUALIZATION) /** * virt_guest_created() - create new VM partition * @guest_id: VM id provided by hypervisor * * This function is called by hypervisor (via fast SMC) * when hypervisor creates new guest VM, so OP-TEE * can prepare partition for that VM */ TEE_Result virt_guest_created(uint16_t guest_id); /** * virt_guest_destroyed() - destroy existing VM partition * @guest_id: VM id provided by hypervisor * * This function is called by hypervisor (via fast SMC) * when hypervisor is ready to destroy guest VM. Hypervisor * must ensure that there are no ongoing calls from this * VM right now. */ TEE_Result virt_guest_destroyed(uint16_t guest_id); /** * virt_set_guest() - set guest VM context for current core * @guest_id: VM id provided by hypervisor * * This function switches memory partitions, so TEE part of * OP-TEE will see memory associated with current guest. * It should be called on entry to OP-TEE */ TEE_Result virt_set_guest(uint16_t guest_id); /** * virt_unset_guest() - set default memory partition * * This function should be called upon leaving OP-TEE, * to switch to default memory partition, so all TEE-specific * memory will be unmapped. This is safety measure to ensure * that TEE memory is untouched when there is no active VM. */ void virt_unset_guest(void); /** * virt_on_stdcall() - std call hook * * This hook is called on every std call, but really is needed * only once: to initialize TEE runtime for current guest VM */ void virt_on_stdcall(void); /* * Next function are needed because virtualization subsystem manages * memory in own way. There is no one static memory map, instead * every guest gets own memory map. */ /** * virt_init_memory() - initialize memory for virtualization subsystem * @memory_map: current OP-TEE memory map * @secmem0_base: base of first secure memory range * @secmem0_size: size of first secure memory range * @secmem1_base: base of an eventual second secure memory range, 0 if unused * @secmem1_size: size of an eventual second secure memory range, 0 if unused */ void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base, paddr_size_t secmem0_size, paddr_t secmem1_base, paddr_size_t secmem1_size); /** * virt_get_memory_map() - get current memory map */ struct tee_mmap_region *virt_get_memory_map(void); /** * virt_get_ta_ram() - get TA RAM mapping for current VM * @start: beginning of TA RAM returned here * @end: end of TA RAM returned here */ void virt_get_ta_ram(vaddr_t *start, vaddr_t *end); /** * virt_get_current_guest_id() - return current guest ID * * Returns current guest ID or 0 if none is set. */ uint16_t virt_get_current_guest_id(void); /** * virt_get_guest_id() - return guest ID of a guest partition * @prtn: Guest partition * * Returns guest ID or 0 if @prtn is NULL */ uint16_t virt_get_guest_id(struct guest_partition *prtn); /* * virt_next_guest() - iterate over guest partitions * @prtn: Guest partition to start from * * Iterates of the guest partitions, if @prtn is NULL the first partition * is returned. If there are none or no next partition NULL is returned. * * The supplied @prtn has its reference counter decreased with * virt_put_guest() before returning the next partition. A returned * partition has its reference counter increased before being returned. * * If virt_next_guest() is called in sequence until it returns NULL, all * reference counters are restored, but if the sequence is stopped earlier * it's the callers responsibility to call virt_put_guest() on the last * returned partition. */ struct guest_partition *virt_next_guest(struct guest_partition *prtn); /** * virt_get_current_guest() - increase reference to current guest partition * * Each successful call to this function must be matched by a call to * virt_put_guest() in order to decrease the reference counter again. * * Return a pointer to the guest partition on success or NULL on failure */ struct guest_partition *virt_get_current_guest(void); /** * virt_get_guest() - increase reference to a guest partition * @guest_id: ID of the guest partition to find * * Each successful call to this function must be matched by a call to * virt_put_guest() in order to decrease the reference counter again. * * Return a pointer to the guest partition on success or NULL on failure */ struct guest_partition *virt_get_guest(uint16_t guest_id); /** * virt_put_guest() - decrease reference to a guest partition * @prtn: Guest partition * * Does nothing if @prtn is NULL. */ void virt_put_guest(struct guest_partition *prtn); /** * virt_add_guest_spec_data() - add guest specific data * @data_id: assigned id for the guest specific data * @data_size: size of the guest specific data * @data_destroy: function to destroy the guest specific data when the * guest is destroyed, does not free the data itself * * Assigns a new data ID returned in @data_id and records the associated * @data_size size and destructor function @data_destroy. * * To keep things simple, this function is only to be called before exiting * to the normal world for the first time, that is, while we're single * threaded and only have one partition. */ TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size, void (*data_destroy)(void *data)); /* * virt_get_guest_spec_data() - get guest specific data * @prtn: guest partition * @data_id: previously assigned ID for the data * * Returns the preallocated guest specific data of the partition with the * ID of @guest_id, will only return NULL for an unrecognized @data_id or * NULL @prtn. */ void *virt_get_guest_spec_data(struct guest_partition *prtn, unsigned int data_id); #else static inline TEE_Result virt_guest_created(uint16_t guest_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result virt_guest_destroyed(uint16_t guest_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline TEE_Result virt_set_guest(uint16_t guest_id __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void virt_unset_guest(void) { } static inline void virt_on_stdcall(void) { } static inline struct tee_mmap_region *virt_get_memory_map(void) { return NULL; } static inline void virt_get_ta_ram(vaddr_t *start __unused, vaddr_t *end __unused) { } static inline void virt_init_memory(struct tee_mmap_region *memory_map __unused, paddr_t secmem0_base __unused, paddr_size_t secmem0_size __unused, paddr_t secmem1_base __unused, paddr_size_t secmem1_size __unused) { } static inline uint16_t virt_get_current_guest_id(void) { return 0; } static inline uint16_t virt_get_guest_id(struct guest_partition *prtn __unused) { return 0; } static inline struct guest_partition *virt_get_current_guest(void) { return NULL; } static inline struct guest_partition *virt_get_guest(uint16_t guest_id __unused) { return NULL; } static inline struct guest_partition * virt_next_guest(struct guest_partition *prtn __unused) { return NULL; } static inline void virt_put_guest(struct guest_partition *prtn __unused) { } static inline TEE_Result virt_add_guest_spec_data(unsigned int *data_id __unused, size_t data_size __unused, void (*data_destroy)(void *data) __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void * virt_get_guest_spec_data(struct guest_partition *prtn __unused, unsigned int data_id __unused) { return NULL; } #endif /*CFG_NS_VIRTUALIZATION*/ #if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_NS_VIRTUALIZATION) TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie); void virt_remove_cookie(uint64_t cookie); uint16_t virt_find_guest_by_cookie(uint64_t cookie); bitstr_t *virt_get_shm_bits(void); TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id, uint64_t cookie); #else static inline TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie __unused) { return TEE_ERROR_NOT_SUPPORTED; } static inline void virt_remove_cookie(uint64_t cookie __unused) { } static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused) { return 0; } static inline bitstr_t *virt_get_shm_bits(void) { return NULL; } static inline TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id __unused, uint64_t cookie __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif #endif /* __KERNEL_VIRTUALIZATION_H */ optee_os-4.3.0/core/include/kernel/wait_queue.h000066400000000000000000000035611464416617300215300ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __KERNEL_WAIT_QUEUE_H #define __KERNEL_WAIT_QUEUE_H #include #include #include struct wait_queue_elem; SLIST_HEAD(wait_queue, wait_queue_elem); #define WAIT_QUEUE_INITIALIZER { .slh_first = NULL } struct condvar; struct wait_queue_elem { short handle; bool done; bool wait_read; struct condvar *cv; SLIST_ENTRY(wait_queue_elem) link; }; /* * Initializes a wait queue */ void wq_init(struct wait_queue *wq); /* * Initializes a wait queue element and adds it to the wait queue. This * function is supposed to be called before the lock that protects the * resource we need to wait for is released. * * One call to this function must be followed by one call to wq_wait_final() * on the same wait queue element. */ void wq_wait_init_condvar(struct wait_queue *wq, struct wait_queue_elem *wqe, struct condvar *cv, bool wait_read); static inline void wq_wait_init(struct wait_queue *wq, struct wait_queue_elem *wqe, bool wait_read) { wq_wait_init_condvar(wq, wqe, NULL, wait_read); } /* Waits for the wait queue element to be awakened or timed out */ TEE_Result wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe, uint32_t timeout_ms, const void *sync_obj, const char *fname, int lineno); /* Wakes up the first wait queue element in the wait queue, if there is one */ void wq_wake_next(struct wait_queue *wq, const void *sync_obj, const char *fname, int lineno); /* Returns true if the wait queue doesn't contain any elements */ bool wq_is_empty(struct wait_queue *wq); void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv, bool only_one, const void *sync_obj, const char *fname, int lineno); bool wq_have_condvar(struct wait_queue *wq, struct condvar *cv); #endif /*__KERNEL_WAIT_QUEUE_H*/ optee_os-4.3.0/core/include/mm/000077500000000000000000000000001464416617300163335ustar00rootroot00000000000000optee_os-4.3.0/core/include/mm/core_memprot.h000066400000000000000000000104071464416617300212010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MM_CORE_MEMPROT_H #define __MM_CORE_MEMPROT_H #include #include /* * "pbuf_is" support. * * core_vbuf_is()/core_pbuf_is() can be used to check if a teecore mapped * virtual address or a physical address is "Secure", "Unsecure", "external * RAM" and some other fancy attributes. * * DO NOT use 'buf_is(Secure, buffer)==false' as a assumption that buffer is * UnSecured ! This is NOT a valid asumption ! A buffer is certified UnSecured * only if 'buf_is(UnSecure, buffer)==true'. */ /* memory atttributes */ enum buf_is_attr { CORE_MEM_CACHED, CORE_MEM_NSEC_SHM, CORE_MEM_NON_SEC, CORE_MEM_SEC, CORE_MEM_TEE_RAM, CORE_MEM_TA_RAM, CORE_MEM_SDP_MEM, CORE_MEM_REG_SHM, }; /* redirect legacy tee_vbuf_is() and tee_pbuf_is() to our routines */ #define tee_pbuf_is core_pbuf_is #define tee_vbuf_is core_vbuf_is /* Convenience macros */ #define tee_pbuf_is_non_sec(buf, len) \ core_pbuf_is(CORE_MEM_NON_SEC, (paddr_t)(buf), (len)) #define tee_pbuf_is_sec(buf, len) \ core_pbuf_is(CORE_MEM_SEC, (paddr_t)(buf), (len)) #define tee_vbuf_is_non_sec(buf, len) \ core_vbuf_is(CORE_MEM_NON_SEC, (void *)(buf), (len)) #define tee_vbuf_is_sec(buf, len) \ core_vbuf_is(CORE_MEM_SEC, (void *)(buf), (len)) /* * This function return true if the buf complies with supplied flags. * If this function returns false buf doesn't comply with supplied flags * or something went wrong. * * Note that returning false doesn't guarantee that buf complies with * the complement of the supplied flags. */ bool core_pbuf_is(uint32_t flags, paddr_t pbuf, size_t len); /* * Translates the supplied virtual address to a physical address and uses * tee_phys_buf_is() to check the compliance of the buffer. */ bool core_vbuf_is(uint32_t flags, const void *vbuf, size_t len); /* * Translate physical address to virtual address using specified mapping. * Also tries to find proper mapping which have counterpart translation * for specified length of data starting from given physical address. * Len parameter can be set to 1 if caller knows that requested (pa + len) * doesn`t cross mapping granule boundary. * Returns NULL on failure or a valid virtual address on success. */ void *phys_to_virt(paddr_t pa, enum teecore_memtypes m, size_t len); /* * Translate physical address to virtual address trying MEM_AREA_IO_SEC * first then MEM_AREA_IO_NSEC if not found. Like phys_to_virt() tries * to find proper mapping relying on length parameter. * Returns NULL on failure or a valid virtual address on success. */ void *phys_to_virt_io(paddr_t pa, size_t len); /* * Translate virtual address to physical address * Returns 0 on failure or a valid physical address on success. */ paddr_t virt_to_phys(void *va); /* * Return runtime usable address, irrespective of whether * the MMU is enabled or not. In case of MMU enabled also will be performed * check for requested amount of data is present in found mapping. */ vaddr_t core_mmu_get_va(paddr_t pa, enum teecore_memtypes type, size_t len); /* * is_unpaged() - report unpaged status of an address * @va: virtual address * * Returns true if the @va is non-NULL and is in the unpaged area if paging * is enabled, else false. */ #ifdef CFG_WITH_PAGER bool is_unpaged(const void *va); #else static inline bool is_unpaged(const void *va) { return va; } #endif /* * is_nexus() - report nexus status of an address * @va: virtual address * * Returns true if the @va is non-NULL and is in the nexus memory area * if ns-virtualization is enabled, else false. */ #ifdef CFG_NS_VIRTUALIZATION bool is_nexus(const void *va); #else static inline bool is_nexus(const void *va) { return va; } #endif struct io_pa_va { paddr_t pa; vaddr_t va; }; /* * Helper function to return a physical or virtual address for a device, * depending on whether the MMU is enabled or not * io_pa_or_va() uses secure mapped IO memory if found or fallback to * non-secure mapped IO memory. */ vaddr_t io_pa_or_va_secure(struct io_pa_va *p, size_t len); vaddr_t io_pa_or_va_nsec(struct io_pa_va *p, size_t len); vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len); #endif /* __MM_CORE_MEMPROT_H */ optee_os-4.3.0/core/include/mm/core_mmu.h000066400000000000000000000556201464416617300203220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MM_CORE_MMU_H #define __MM_CORE_MMU_H #ifndef __ASSEMBLER__ #include #include #include #include #include #include #include #endif #include #include /* A small page is the smallest unit of memory that can be mapped */ #define SMALL_PAGE_SIZE BIT(SMALL_PAGE_SHIFT) #define SMALL_PAGE_MASK ((paddr_t)SMALL_PAGE_SIZE - 1) /* * PGDIR is the translation table above the translation table that holds * the pages. */ #define CORE_MMU_PGDIR_SIZE BIT(CORE_MMU_PGDIR_SHIFT) #define CORE_MMU_PGDIR_MASK ((paddr_t)CORE_MMU_PGDIR_SIZE - 1) /* TA user space code, data, stack and heap are mapped using this granularity */ #define CORE_MMU_USER_CODE_SIZE BIT(CORE_MMU_USER_CODE_SHIFT) #define CORE_MMU_USER_CODE_MASK ((paddr_t)CORE_MMU_USER_CODE_SIZE - 1) /* TA user space parameters are mapped using this granularity */ #define CORE_MMU_USER_PARAM_SIZE BIT(CORE_MMU_USER_PARAM_SHIFT) #define CORE_MMU_USER_PARAM_MASK ((paddr_t)CORE_MMU_USER_PARAM_SIZE - 1) /* * Identify mapping constraint: virtual base address is the physical start addr. * If platform did not set some macros, some get default value. */ #ifndef TEE_RAM_VA_SIZE #define TEE_RAM_VA_SIZE CORE_MMU_PGDIR_SIZE #endif #ifndef TEE_LOAD_ADDR #define TEE_LOAD_ADDR TEE_RAM_START #endif #ifndef STACK_ALIGNMENT #define STACK_ALIGNMENT (sizeof(long) * U(2)) #endif #ifndef __ASSEMBLER__ /* * Memory area type: * MEM_AREA_END: Reserved, marks the end of a table of mapping areas. * MEM_AREA_TEE_RAM: core RAM (read/write/executable, secure, reserved to TEE) * MEM_AREA_TEE_RAM_RX: core private read-only/executable memory (secure) * MEM_AREA_TEE_RAM_RO: core private read-only/non-executable memory (secure) * MEM_AREA_TEE_RAM_RW: core private read/write/non-executable memory (secure) * MEM_AREA_INIT_RAM_RO: init private read-only/non-executable memory (secure) * MEM_AREA_INIT_RAM_RX: init private read-only/executable memory (secure) * MEM_AREA_NEX_RAM_RO: nexus private read-only/non-executable memory (secure) * MEM_AREA_NEX_RAM_RW: nexus private r/w/non-executable memory (secure) * MEM_AREA_TEE_COHERENT: teecore coherent RAM (secure, reserved to TEE) * MEM_AREA_TEE_ASAN: core address sanitizer RAM (secure, reserved to TEE) * MEM_AREA_IDENTITY_MAP_RX: core identity mapped r/o executable memory (secure) * MEM_AREA_TA_RAM: Secure RAM where teecore loads/exec TA instances. * MEM_AREA_NSEC_SHM: NonSecure shared RAM between NSec and TEE. * MEM_AREA_NEX_NSEC_SHM: nexus non-secure shared RAM between NSec and TEE. * MEM_AREA_RAM_NSEC: NonSecure RAM storing data * MEM_AREA_RAM_SEC: Secure RAM storing some secrets * MEM_AREA_ROM_SEC: Secure read only memory storing some secrets * MEM_AREA_IO_NSEC: NonSecure HW mapped registers * MEM_AREA_IO_SEC: Secure HW mapped registers * MEM_AREA_EXT_DT: Memory loads external device tree * MEM_AREA_MANIFEST_DT: Memory loads manifest device tree * MEM_AREA_TRANSFER_LIST: Memory area mapped for Transfer List * MEM_AREA_RES_VASPACE: Reserved virtual memory space * MEM_AREA_SHM_VASPACE: Virtual memory space for dynamic shared memory buffers * MEM_AREA_TS_VASPACE: TS va space, only used with phys_to_virt() * MEM_AREA_DDR_OVERALL: Overall DDR address range, candidate to dynamic shm. * MEM_AREA_SEC_RAM_OVERALL: Whole secure RAM * MEM_AREA_MAXTYPE: lower invalid 'type' value */ enum teecore_memtypes { MEM_AREA_END = 0, MEM_AREA_TEE_RAM, MEM_AREA_TEE_RAM_RX, MEM_AREA_TEE_RAM_RO, MEM_AREA_TEE_RAM_RW, MEM_AREA_INIT_RAM_RO, MEM_AREA_INIT_RAM_RX, MEM_AREA_NEX_RAM_RO, MEM_AREA_NEX_RAM_RW, MEM_AREA_TEE_COHERENT, MEM_AREA_TEE_ASAN, MEM_AREA_IDENTITY_MAP_RX, MEM_AREA_TA_RAM, MEM_AREA_NSEC_SHM, MEM_AREA_NEX_NSEC_SHM, MEM_AREA_RAM_NSEC, MEM_AREA_RAM_SEC, MEM_AREA_ROM_SEC, MEM_AREA_IO_NSEC, MEM_AREA_IO_SEC, MEM_AREA_EXT_DT, MEM_AREA_MANIFEST_DT, MEM_AREA_TRANSFER_LIST, MEM_AREA_RES_VASPACE, MEM_AREA_SHM_VASPACE, MEM_AREA_TS_VASPACE, MEM_AREA_PAGER_VASPACE, MEM_AREA_SDP_MEM, MEM_AREA_DDR_OVERALL, MEM_AREA_SEC_RAM_OVERALL, MEM_AREA_MAXTYPE }; static inline const char *teecore_memtype_name(enum teecore_memtypes type) { static const char * const names[] = { [MEM_AREA_END] = "END", [MEM_AREA_TEE_RAM] = "TEE_RAM_RWX", [MEM_AREA_TEE_RAM_RX] = "TEE_RAM_RX", [MEM_AREA_TEE_RAM_RO] = "TEE_RAM_RO", [MEM_AREA_TEE_RAM_RW] = "TEE_RAM_RW", [MEM_AREA_INIT_RAM_RO] = "INIT_RAM_RO", [MEM_AREA_INIT_RAM_RX] = "INIT_RAM_RX", [MEM_AREA_NEX_RAM_RO] = "NEX_RAM_RO", [MEM_AREA_NEX_RAM_RW] = "NEX_RAM_RW", [MEM_AREA_TEE_ASAN] = "TEE_ASAN", [MEM_AREA_IDENTITY_MAP_RX] = "IDENTITY_MAP_RX", [MEM_AREA_TEE_COHERENT] = "TEE_COHERENT", [MEM_AREA_TA_RAM] = "TA_RAM", [MEM_AREA_NSEC_SHM] = "NSEC_SHM", [MEM_AREA_NEX_NSEC_SHM] = "NEX_NSEC_SHM", [MEM_AREA_RAM_NSEC] = "RAM_NSEC", [MEM_AREA_RAM_SEC] = "RAM_SEC", [MEM_AREA_ROM_SEC] = "ROM_SEC", [MEM_AREA_IO_NSEC] = "IO_NSEC", [MEM_AREA_IO_SEC] = "IO_SEC", [MEM_AREA_EXT_DT] = "EXT_DT", [MEM_AREA_MANIFEST_DT] = "MANIFEST_DT", [MEM_AREA_TRANSFER_LIST] = "TRANSFER_LIST", [MEM_AREA_RES_VASPACE] = "RES_VASPACE", [MEM_AREA_SHM_VASPACE] = "SHM_VASPACE", [MEM_AREA_TS_VASPACE] = "TS_VASPACE", [MEM_AREA_PAGER_VASPACE] = "PAGER_VASPACE", [MEM_AREA_SDP_MEM] = "SDP_MEM", [MEM_AREA_DDR_OVERALL] = "DDR_OVERALL", [MEM_AREA_SEC_RAM_OVERALL] = "SEC_RAM_OVERALL", }; COMPILE_TIME_ASSERT(ARRAY_SIZE(names) == MEM_AREA_MAXTYPE); return names[type]; } #ifdef CFG_CORE_RWDATA_NOEXEC #define MEM_AREA_TEE_RAM_RW_DATA MEM_AREA_TEE_RAM_RW #else #define MEM_AREA_TEE_RAM_RW_DATA MEM_AREA_TEE_RAM #endif struct core_mmu_phys_mem { const char *name; enum teecore_memtypes type; __extension__ union { #if __SIZEOF_LONG__ != __SIZEOF_PADDR__ struct { uint32_t lo_addr; uint32_t hi_addr; }; #endif paddr_t addr; }; __extension__ union { #if __SIZEOF_LONG__ != __SIZEOF_PADDR__ struct { uint32_t lo_size; uint32_t hi_size; }; #endif paddr_size_t size; }; }; #define __register_memory(_name, _type, _addr, _size, _section) \ SCATTERED_ARRAY_DEFINE_ITEM(_section, struct core_mmu_phys_mem) = \ { .name = (_name), .type = (_type), .addr = (_addr), \ .size = (_size) } #if __SIZEOF_LONG__ != __SIZEOF_PADDR__ #define __register_memory_ul(_name, _type, _addr, _size, _section) \ SCATTERED_ARRAY_DEFINE_ITEM(_section, struct core_mmu_phys_mem) = \ { .name = (_name), .type = (_type), .lo_addr = (_addr), \ .lo_size = (_size) } #else #define __register_memory_ul(_name, _type, _addr, _size, _section) \ __register_memory(_name, _type, _addr, _size, _section) #endif #define register_phys_mem(type, addr, size) \ __register_memory(#addr, (type), (addr), (size), \ phys_mem_map) #define register_phys_mem_ul(type, addr, size) \ __register_memory_ul(#addr, (type), (addr), (size), \ phys_mem_map) /* Same as register_phys_mem() but with PGDIR_SIZE granularity */ #define register_phys_mem_pgdir(type, addr, size) \ __register_memory(#addr, type, ROUNDDOWN(addr, CORE_MMU_PGDIR_SIZE), \ ROUNDUP(size + addr - \ ROUNDDOWN(addr, CORE_MMU_PGDIR_SIZE), \ CORE_MMU_PGDIR_SIZE), phys_mem_map) #ifdef CFG_SECURE_DATA_PATH #define register_sdp_mem(addr, size) \ __register_memory(#addr, MEM_AREA_SDP_MEM, (addr), (size), \ phys_sdp_mem) #else #define register_sdp_mem(addr, size) \ static int CONCAT(__register_sdp_mem_unused, __COUNTER__) \ __unused #endif /* register_dynamic_shm() is deprecated, please use register_ddr() instead */ #define register_dynamic_shm(addr, size) \ __register_memory(#addr, MEM_AREA_DDR_OVERALL, (addr), (size), \ phys_ddr_overall_compat) /* * register_ddr() - Define a memory range * @addr: Base address * @size: Length * * This macro can be used multiple times to define disjoint ranges. While * initializing holes are carved out of these ranges where it overlaps with * special memory, for instance memory registered with register_sdp_mem(). * * The memory that remains is accepted as non-secure shared memory when * communicating with normal world. * * This macro is an alternative to supply the memory description with a * devicetree blob. */ #define register_ddr(addr, size) \ __register_memory(#addr, MEM_AREA_DDR_OVERALL, (addr), \ (size), phys_ddr_overall) #define phys_ddr_overall_begin \ SCATTERED_ARRAY_BEGIN(phys_ddr_overall, struct core_mmu_phys_mem) #define phys_ddr_overall_end \ SCATTERED_ARRAY_END(phys_ddr_overall, struct core_mmu_phys_mem) #define phys_ddr_overall_compat_begin \ SCATTERED_ARRAY_BEGIN(phys_ddr_overall_compat, struct core_mmu_phys_mem) #define phys_ddr_overall_compat_end \ SCATTERED_ARRAY_END(phys_ddr_overall_compat, struct core_mmu_phys_mem) #define phys_sdp_mem_begin \ SCATTERED_ARRAY_BEGIN(phys_sdp_mem, struct core_mmu_phys_mem) #define phys_sdp_mem_end \ SCATTERED_ARRAY_END(phys_sdp_mem, struct core_mmu_phys_mem) #define phys_mem_map_begin \ SCATTERED_ARRAY_BEGIN(phys_mem_map, struct core_mmu_phys_mem) #define phys_mem_map_end \ SCATTERED_ARRAY_END(phys_mem_map, struct core_mmu_phys_mem) /* Physical Secure DDR pool */ extern tee_mm_pool_t tee_mm_sec_ddr; /* Virtual memory pool for core mappings */ extern tee_mm_pool_t core_virt_mem_pool; /* Virtual memory pool for shared memory mappings */ extern tee_mm_pool_t core_virt_shm_pool; #ifdef CFG_CORE_RESERVED_SHM /* Default NSec shared memory allocated from NSec world */ extern unsigned long default_nsec_shm_paddr; extern unsigned long default_nsec_shm_size; #endif /* * Physical load address of OP-TEE updated during boot if needed to reflect * the value used. */ #ifdef CFG_CORE_PHYS_RELOCATABLE extern unsigned long core_mmu_tee_load_pa; #else extern const unsigned long core_mmu_tee_load_pa; #endif void core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg); void core_init_mmu_regs(struct core_mmu_config *cfg); /* Arch specific function to help optimizing 1 MMU xlat table */ bool core_mmu_prefer_tee_ram_at_top(paddr_t paddr); /* * struct mmu_partition - stores MMU partition. * * Basically it represent whole MMU mapping. It is possible * to create multiple partitions, and change them in runtime, * effectively changing how OP-TEE sees memory. * This is opaque struct which is defined differently for * v7 and LPAE MMUs * * This structure used mostly when virtualization is enabled. * When CFG_NS_VIRTUALIZATION==n only default partition exists. */ struct mmu_partition; /* * core_mmu_get_user_va_range() - Return range of user va space * @base: Lowest user virtual address * @size: Size in bytes of user address space */ void core_mmu_get_user_va_range(vaddr_t *base, size_t *size); /* * enum core_mmu_fault - different kinds of faults * @CORE_MMU_FAULT_ALIGNMENT: alignment fault * @CORE_MMU_FAULT_DEBUG_EVENT: debug event * @CORE_MMU_FAULT_TRANSLATION: translation fault * @CORE_MMU_FAULT_WRITE_PERMISSION: Permission fault during write * @CORE_MMU_FAULT_READ_PERMISSION: Permission fault during read * @CORE_MMU_FAULT_ASYNC_EXTERNAL: asynchronous external abort * @CORE_MMU_FAULT_ACCESS_BIT: access bit fault * @CORE_MMU_FAULT_TAG_CHECK: tag check fault * @CORE_MMU_FAULT_OTHER: Other/unknown fault */ enum core_mmu_fault { CORE_MMU_FAULT_ALIGNMENT, CORE_MMU_FAULT_DEBUG_EVENT, CORE_MMU_FAULT_TRANSLATION, CORE_MMU_FAULT_WRITE_PERMISSION, CORE_MMU_FAULT_READ_PERMISSION, CORE_MMU_FAULT_ASYNC_EXTERNAL, CORE_MMU_FAULT_ACCESS_BIT, CORE_MMU_FAULT_TAG_CHECK, CORE_MMU_FAULT_OTHER, }; /* * core_mmu_get_fault_type() - get fault type * @fault_descr: Content of fault status or exception syndrome register * @returns an enum describing the content of fault status register. */ enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr); /* * core_mm_type_to_attr() - convert memory type to attribute * @t: memory type * @returns an attribute that can be passed to core_mm_set_entry() and friends */ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t); /* * core_mmu_create_user_map() - Create user mode mapping * @uctx: Pointer to user mode context * @map: MMU configuration to use when activating this VA space */ void core_mmu_create_user_map(struct user_mode_ctx *uctx, struct core_mmu_user_map *map); /* * core_mmu_get_user_map() - Reads current MMU configuration for user VA space * @map: MMU configuration for current user VA space. */ void core_mmu_get_user_map(struct core_mmu_user_map *map); /* * core_mmu_set_user_map() - Set new MMU configuration for user VA space * @map: User context MMU configuration or NULL to set core VA space * * Activate user VA space mapping and set its ASID if @map is not NULL, * otherwise activate core mapping and set ASID to 0. */ void core_mmu_set_user_map(struct core_mmu_user_map *map); /* * struct core_mmu_table_info - Properties for a translation table * @table: Pointer to translation table * @va_base: VA base address of the transaltion table * @level: Translation table level * @next_level: Finer grained translation table level according to @level. * @shift: The shift of each entry in the table * @num_entries: Number of entries in this table. */ struct core_mmu_table_info { void *table; vaddr_t va_base; unsigned num_entries; #ifdef CFG_NS_VIRTUALIZATION struct mmu_partition *prtn; #endif uint8_t level; uint8_t shift; uint8_t next_level; }; /* * core_mmu_find_table() - Locates a translation table * @prtn: MMU partition where search should be performed * @va: Virtual address for the table to cover * @max_level: Don't traverse beyond this level * @tbl_info: Pointer to where to store properties. * @return true if a translation table was found, false on error */ bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va, unsigned max_level, struct core_mmu_table_info *tbl_info); /* * core_mmu_entry_to_finer_grained() - divide mapping at current level into * smaller ones so memory can be mapped with finer granularity * @tbl_info: table where target record located * @idx: index of record for which a pdgir must be setup. * @secure: true/false if pgdir maps secure/non-secure memory (32bit mmu) * @return true on successful, false on error */ bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info, unsigned int idx, bool secure); void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx, paddr_t pa, uint32_t attr); void core_mmu_get_user_pgdir(struct core_mmu_table_info *pgd_info); /* * core_mmu_set_entry() - Set entry in translation table * @tbl_info: Translation table properties * @idx: Index of entry to update * @pa: Physical address to assign entry * @attr: Attributes to assign entry */ void core_mmu_set_entry(struct core_mmu_table_info *tbl_info, unsigned idx, paddr_t pa, uint32_t attr); void core_mmu_get_entry_primitive(const void *table, size_t level, size_t idx, paddr_t *pa, uint32_t *attr); /* * core_mmu_get_entry() - Get entry from translation table * @tbl_info: Translation table properties * @idx: Index of entry to read * @pa: Physical address is returned here if pa is not NULL * @attr: Attributues are returned here if attr is not NULL */ void core_mmu_get_entry(struct core_mmu_table_info *tbl_info, unsigned idx, paddr_t *pa, uint32_t *attr); /* * core_mmu_va2idx() - Translate from virtual address to table index * @tbl_info: Translation table properties * @va: Virtual address to translate * @returns index in transaltion table */ static inline unsigned core_mmu_va2idx(struct core_mmu_table_info *tbl_info, vaddr_t va) { return (va - tbl_info->va_base) >> tbl_info->shift; } /* * core_mmu_idx2va() - Translate from table index to virtual address * @tbl_info: Translation table properties * @idx: Index to translate * @returns Virtual address */ static inline vaddr_t core_mmu_idx2va(struct core_mmu_table_info *tbl_info, unsigned idx) { return (idx << tbl_info->shift) + tbl_info->va_base; } /* * core_mmu_get_block_offset() - Get offset inside a block/page * @tbl_info: Translation table properties * @pa: Physical address * @returns offset within one block of the translation table */ static inline size_t core_mmu_get_block_offset( struct core_mmu_table_info *tbl_info, paddr_t pa) { return pa & ((1 << tbl_info->shift) - 1); } /* * core_mmu_is_dynamic_vaspace() - Check if memory region belongs to * empty virtual address space that is used for dymanic mappings * @mm: memory region to be checked * @returns result of the check */ static inline bool core_mmu_is_dynamic_vaspace(struct tee_mmap_region *mm) { return mm->type == MEM_AREA_RES_VASPACE || mm->type == MEM_AREA_SHM_VASPACE; } /* * core_mmu_map_pages() - map list of pages at given virtual address * @vstart: Virtual address where mapping begins * @pages: Array of page addresses * @num_pages: Number of pages * @memtype: Type of memmory to be mapped * * Note: This function asserts that pages are not mapped executeable for * kernel (privileged) mode. * * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error */ TEE_Result core_mmu_map_pages(vaddr_t vstart, paddr_t *pages, size_t num_pages, enum teecore_memtypes memtype); /* * core_mmu_map_contiguous_pages() - map range of pages at given virtual address * @vstart: Virtual address where mapping begins * @pstart: Physical address of the first page * @num_pages: Number of pages * @memtype: Type of memmory to be mapped * * Note: This function asserts that pages are not mapped executeable for * kernel (privileged) mode. * * @returns: TEE_SUCCESS on success, TEE_ERROR_XXX on error */ TEE_Result core_mmu_map_contiguous_pages(vaddr_t vstart, paddr_t pstart, size_t num_pages, enum teecore_memtypes memtype); /* * core_mmu_unmap_pages() - remove mapping at given virtual address * @vstart: Virtual address where mapping begins * @num_pages: Number of pages to unmap */ void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages); /* * core_mmu_user_mapping_is_active() - Report if user mapping is active * @returns true if a user VA space is active, false if user VA space is * inactive. */ bool core_mmu_user_mapping_is_active(void); /* * core_mmu_mattr_is_ok() - Check that supplied mem attributes can be used * @returns true if the attributes can be used, false if not. */ bool core_mmu_mattr_is_ok(uint32_t mattr); void core_mmu_get_mem_by_type(enum teecore_memtypes type, vaddr_t *s, vaddr_t *e); enum teecore_memtypes core_mmu_get_type_by_pa(paddr_t pa); /* routines to retreive shared mem configuration */ static inline bool core_mmu_is_shm_cached(void) { return mattr_is_cached(core_mmu_type_to_attr(MEM_AREA_NSEC_SHM)); } TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr, size_t len); void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len); /* * core_mmu_find_mapping_exclusive() - Find mapping of specified type and * length. If more than one mapping of * specified type is present, NULL will be * returned. * @type: memory type * @len: length in bytes */ struct tee_mmap_region * core_mmu_find_mapping_exclusive(enum teecore_memtypes type, size_t len); /* * tlbi_va_range() - Invalidate TLB for virtual address range * @va: start virtual address, must be a multiple of @granule * @len: length in bytes of range, must be a multiple of @granule * @granule: granularity of mapping, supported values are * CORE_MMU_PGDIR_SIZE or SMALL_PAGE_SIZE. This value must * match the actual mappings. */ void tlbi_va_range(vaddr_t va, size_t len, size_t granule); /* * tlbi_va_range_asid() - Invalidate TLB for virtual address range for * a specific ASID * @va: start virtual address, must be a multiple of @granule * @len: length in bytes of range, must be a multiple of @granule * @granule: granularity of mapping, supported values are * CORE_MMU_PGDIR_SIZE or SMALL_PAGE_SIZE. This value must * match the actual mappings. * @asid: Address space identifier */ void tlbi_va_range_asid(vaddr_t va, size_t len, size_t granule, uint32_t asid); /* Check cpu mmu enabled or not */ bool cpu_mmu_enabled(void); #ifdef CFG_CORE_DYN_SHM /* * Check if platform defines nsec DDR range(s). * Static SHM (MEM_AREA_NSEC_SHM) is not covered by this API as it is * always present. */ bool core_mmu_nsec_ddr_is_defined(void); void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start, size_t nelems); #endif /* Initialize MMU partition */ void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm); unsigned int asid_alloc(void); void asid_free(unsigned int asid); #ifdef CFG_SECURE_DATA_PATH /* Alloc and fill SDP memory objects table - table is NULL terminated */ struct mobj **core_sdp_mem_create_mobjs(void); #endif #ifdef CFG_NS_VIRTUALIZATION size_t core_mmu_get_total_pages_size(void); struct mmu_partition *core_alloc_mmu_prtn(void *tables); void core_free_mmu_prtn(struct mmu_partition *prtn); void core_mmu_set_prtn(struct mmu_partition *prtn); void core_mmu_set_default_prtn(void); void core_mmu_set_default_prtn_tbl(void); #endif void core_mmu_init_virtualization(void); /* init some allocation pools */ void core_mmu_init_ta_ram(void); void core_init_mmu(struct tee_mmap_region *mm); void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info, unsigned int level, vaddr_t va_base, void *table); void core_mmu_populate_user_map(struct core_mmu_table_info *dir_info, struct user_mode_ctx *uctx); void core_mmu_map_region(struct mmu_partition *prtn, struct tee_mmap_region *mm); bool arch_va2pa_helper(void *va, paddr_t *pa); static inline bool core_mmap_is_end_of_table(const struct tee_mmap_region *mm) { return mm->type == MEM_AREA_END; } static inline bool core_mmu_check_end_pa(paddr_t pa, size_t len) { paddr_t end_pa = 0; if (ADD_OVERFLOW(pa, len - 1, &end_pa)) return false; return core_mmu_check_max_pa(end_pa); } /* * core_mmu_set_secure_memory() - set physical secure memory range * @base: base address of secure memory * @size: size of secure memory * * The physical secure memory range is not known in advance when OP-TEE is * relocatable, this information must be supplied once during boot before * the translation tables can be initialized and the MMU enabled. */ void core_mmu_set_secure_memory(paddr_t base, size_t size); /* * core_mmu_get_secure_memory() - get physical secure memory range * @base: base address of secure memory * @size: size of secure memory * * The physical secure memory range returned covers at least the memory * range used by OP-TEE Core, but may cover more memory depending on the * configuration. */ void core_mmu_get_secure_memory(paddr_t *base, paddr_size_t *size); /* * core_mmu_get_ta_range() - get physical memory range reserved for TAs * @base: [out] range base address ref or NULL * @size: [out] range size ref or NULL */ void core_mmu_get_ta_range(paddr_t *base, size_t *size); #endif /*__ASSEMBLER__*/ #endif /* __MM_CORE_MMU_H */ optee_os-4.3.0/core/include/mm/file.h000066400000000000000000000053361464416617300174320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef __MM_FILE_H #define __MM_FILE_H #include #include #include /* This is supposed to be large enough to hold any hash or tag used */ #define FILE_TAG_SIZE TEE_SHA256_HASH_SIZE /* * struct file_slice - one slice of a file * @fobj: Fobj holding the data of this slice * @page_offset: Offset in pages into the file where the @fobj is * located. */ struct file_slice { struct fobj *fobj; unsigned int page_offset; }; struct file; /* * file_lock() - Lock the file * @f: File pointer * * Waits until the file can be locked and with the file put in locked state. */ void file_lock(struct file *f); /* * file_lock() - Try to lock the file without blocking * @f: File pointer * * Returns false if file cannot be locked without blocking. * Returns true if the file has been put in locked state. */ bool file_trylock(struct file *f); /* * file_unlock() - Unlock the file * @f: File pointer * * File must be in locked state. Releases the previous lock and returns. */ void file_unlock(struct file *f); /* * file_add_slice() - Add a slice to a file * @f: File pointer * @fobj: Fobj holding the data of this slice * @page_offset: Offset in pages into the file (@f) where the @fobj is * located. * * File must be in locked state. * * Returns TEE_SUCCESS on success or a TEE_ERROR_* code on failure. */ TEE_Result file_add_slice(struct file *f, struct fobj *fobj, unsigned int page_offset); /* * file_get() - Increase file reference counter * @f: File pointer * * Returns @f, if @f isn't NULL its reference counter is first increased. */ struct file *file_get(struct file *f); /* * file_get_by_tag() - Finds a file based on tag and increase reference counter * @tag: Tag of the file * @taglen: Length of @tag * * If a file doesn't exist it's created with the supplied tag. * * Returns a file with an increased reference counter, or NULL on failure. */ struct file *file_get_by_tag(const uint8_t *tag, unsigned int taglen); /* * file_put() - Decrease reference counter of file * @f: File pointer * * If reference counter reaches 0, matching the numbers of file_new() + * file_get() + file_get_by_tag(), the file is removed with reference * counters for all contained fobjs decreased. */ void file_put(struct file *f); /* * file_find_slice() - Find a slice covering the @page_offset * @f: File pointer * @page_offset: Offset that must be covered * * File must be in locked state. * * If a matching file slice is found it is returned, else NULL is returned. */ struct file_slice *file_find_slice(struct file *f, unsigned int page_offset); #endif /*__MM_FILE_H*/ optee_os-4.3.0/core/include/mm/fobj.h000066400000000000000000000133331464416617300174270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2021, Linaro Limited */ #ifndef __MM_FOBJ_H #define __MM_FOBJ_H #include #include #include #include #include #include /* * struct fobj - file object storage abstraction * @ops: Operations pointer * @num_pages: Number of pages covered * @refc: Reference counter */ struct fobj { const struct fobj_ops *ops; unsigned int num_pages; struct refcount refc; #ifdef CFG_WITH_PAGER struct vm_paged_region_head regions; #endif }; /* * struct fobj_ops - operations struct for struct fobj * @free: Frees the @fobj * @load_page: Loads page with index @page_idx at address @va * @save_page: Saves page with index @page_idx from address @va * @get_iv_vaddr: Returns virtual address of tag and IV for the page at * @page_idx if tag and IV are paged for this fobj * @get_pa: Returns physical address of page at @page_idx if not paged */ struct fobj_ops { void (*free)(struct fobj *fobj); #ifdef CFG_WITH_PAGER TEE_Result (*load_page)(struct fobj *fobj, unsigned int page_idx, void *va); TEE_Result (*save_page)(struct fobj *fobj, unsigned int page_idx, const void *va); vaddr_t (*get_iv_vaddr)(struct fobj *fobj, unsigned int page_idx); #endif paddr_t (*get_pa)(struct fobj *fobj, unsigned int page_idx); }; #ifdef CFG_WITH_PAGER /* * fobj_locked_paged_alloc() - Allocate storage which is locked in memory * @num_pages: Number of pages covered * * This object only supports loading pages zero initialized. Saving a page * will result in an error. * * Returns a valid pointer on success or NULL on failure. */ struct fobj *fobj_locked_paged_alloc(unsigned int num_pages); /* * fobj_rw_paged_alloc() - Allocate read/write storage * @num_pages: Number of pages covered * * This object supports both load and saving of pages. Pages are zero * initialized the first time they are loaded. * * Returns a valid pointer on success or NULL on failure. */ struct fobj *fobj_rw_paged_alloc(unsigned int num_pages); /* * fobj_ro_paged_alloc() - Allocate initialized read-only storage * @num_pages: Number of pages covered * @hashes: Hashes to verify the pages * @store: Clear text data for all pages * * This object only support loading pages with an already provided content * in @store. When a page is loaded it will be verified against an hash in * @hash. Saving a page will result in an error. * * Returns a valid pointer on success or NULL on failure. */ struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes, void *store); /* * fobj_ro_reloc_paged_alloc() - Allocate initialized read-only storage with * relocation * @num_pages: Number of pages covered * @hashes: Hashes to verify the pages * @reloc_offs: Offset from the base address in the relocations in @reloc * @reloc: Relocation data * @reloc_len: Length of relocation data * @store: Clear text data for all pages * * This object is like fobj_ro_paged_alloc() above, but in addition the * relocation information is applied to a populated page. This makes sure * the offset to which all pages are relocated doesn't leak out to storage. * * Returns a valid pointer on success or NULL on failure. */ struct fobj *fobj_ro_reloc_paged_alloc(unsigned int num_pages, void *hashes, unsigned int reloc_offs, const void *reloc, unsigned int reloc_len, void *store); /* * fobj_load_page() - Load a page into memory * @fobj: Fobj pointer * @page_index: Index of page in @fobj * @va: Address where content should be stored and verified * * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure. */ static inline TEE_Result fobj_load_page(struct fobj *fobj, unsigned int page_idx, void *va) { if (fobj) return fobj->ops->load_page(fobj, page_idx, va); return TEE_ERROR_GENERIC; } /* * fobj_save_page() - Save a page into storage * @fobj: Fobj pointer * @page_index: Index of page in @fobj * @va: Address of the page to store. * * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure. */ static inline TEE_Result fobj_save_page(struct fobj *fobj, unsigned int page_idx, const void *va) { if (fobj) return fobj->ops->save_page(fobj, page_idx, va); return TEE_ERROR_GENERIC; } static inline vaddr_t fobj_get_iv_vaddr(struct fobj *fobj, unsigned int page_idx) { if (fobj && fobj->ops->get_iv_vaddr) return fobj->ops->get_iv_vaddr(fobj, page_idx); return 0; } #endif /* * fobj_ta_mem_alloc() - Allocates TA memory * @num_pages: Number of pages * * If paging of user TAs read/write paged fobj is allocated otherwise a * fobj which uses unpaged secure memory directly. * * Returns a valid pointer on success or NULL on failure. */ #ifdef CFG_PAGED_USER_TA #define fobj_ta_mem_alloc(num_pages) fobj_rw_paged_alloc(num_pages) #else /* * fobj_sec_mem_alloc() - Allocates storage directly in secure memory * @num_pages: Number of pages * * Returns a valid pointer on success or NULL on failure. */ struct fobj *fobj_sec_mem_alloc(unsigned int num_pages); #define fobj_ta_mem_alloc(num_pages) fobj_sec_mem_alloc(num_pages) #endif /* * fobj_get() - Increase fobj reference count * @fobj: Fobj pointer * * Returns @fobj, if @fobj isn't NULL its reference counter is first * increased. */ static inline struct fobj *fobj_get(struct fobj *fobj) { if (fobj && !refcount_inc(&fobj->refc)) panic(); return fobj; } /* * fobj_put() - Decrease reference counter of fobj * @fobj: Fobj pointer * * If reference counter reaches 0, matching the numbers of fobj_alloc_*() + * fobj_get(), the fobj is freed. */ static inline void fobj_put(struct fobj *fobj) { if (fobj && refcount_dec(&fobj->refc)) fobj->ops->free(fobj); } #endif /*__MM_FOBJ_H*/ optee_os-4.3.0/core/include/mm/mobj.h000066400000000000000000000204451464416617300174400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, 2022 Linaro Limited */ #ifndef __MM_MOBJ_H #define __MM_MOBJ_H #include #include #include #include #include #include #include #include #include struct mobj { const struct mobj_ops *ops; size_t size; size_t phys_granule; struct refcount refc; }; struct mobj_ops { void *(*get_va)(struct mobj *mobj, size_t offs, size_t len); TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule, paddr_t *pa); size_t (*get_phys_offs)(struct mobj *mobj, size_t granule); TEE_Result (*get_mem_type)(struct mobj *mobj, uint32_t *mt); bool (*matches)(struct mobj *mobj, enum buf_is_attr attr); void (*free)(struct mobj *mobj); uint64_t (*get_cookie)(struct mobj *mobj); struct fobj *(*get_fobj)(struct mobj *mobj); TEE_Result (*inc_map)(struct mobj *mobj); TEE_Result (*dec_map)(struct mobj *mobj); }; extern struct mobj mobj_virt; extern struct mobj *mobj_sec_ddr; extern struct mobj *mobj_tee_ram_rx; extern struct mobj *mobj_tee_ram_rw; /* * mobj_get_va() - get virtual address of a mapped mobj * @mobj: memory object * @offset: find the va of this offset into @mobj * @len: how many bytes after @offset that must be valid, can be 1 if * the caller knows by other means that the expected buffer is * available. * * return a virtual address on success or NULL on error */ static inline void *mobj_get_va(struct mobj *mobj, size_t offset, size_t len) { if (mobj && mobj->ops && mobj->ops->get_va) return mobj->ops->get_va(mobj, offset, len); return NULL; } static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs, size_t granule, paddr_t *pa) { if (mobj && mobj->ops && mobj->ops->get_pa) return mobj->ops->get_pa(mobj, offs, granule, pa); return TEE_ERROR_GENERIC; } static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule) { if (mobj && mobj->ops && mobj->ops->get_phys_offs) return mobj->ops->get_phys_offs(mobj, granule); return 0; } static inline TEE_Result mobj_get_mem_type(struct mobj *mobj, uint32_t *mt) { if (mobj && mobj->ops && mobj->ops->get_mem_type) return mobj->ops->get_mem_type(mobj, mt); return TEE_ERROR_GENERIC; } static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr) { if (mobj && mobj->ops && mobj->ops->matches) return mobj->ops->matches(mobj, attr); return false; } /** * mobj_inc_map() - increase map count * @mobj: pointer to a MOBJ * * Maps the MOBJ if it isn't mapped already and increases the map count * Each call to mobj_inc_map() is supposed to be matches by a call to * mobj_dec_map(). * * Returns TEE_SUCCESS on success or an error code on failure */ static inline TEE_Result mobj_inc_map(struct mobj *mobj) { if (mobj && mobj->ops) { if (mobj->ops->inc_map) return mobj->ops->inc_map(mobj); return TEE_SUCCESS; } return TEE_ERROR_GENERIC; } /** * mobj_dec_map() - decrease map count * @mobj: pointer to a MOBJ * * Decreases the map count and also unmaps the MOBJ if the map count * reaches 0. Each call to mobj_inc_map() is supposed to be matched by a * call to mobj_dec_map(). * * Returns TEE_SUCCESS on success or an error code on failure */ static inline TEE_Result mobj_dec_map(struct mobj *mobj) { if (mobj && mobj->ops) { if (mobj->ops->dec_map) return mobj->ops->dec_map(mobj); return TEE_SUCCESS; } return TEE_ERROR_GENERIC; } /** * mobj_get() - get a MOBJ * @mobj: Pointer to a MOBJ or NULL * * Increases reference counter of the @mobj * * Returns @mobj with reference counter increased or NULL if @mobj was NULL */ static inline struct mobj *mobj_get(struct mobj *mobj) { if (mobj && !refcount_inc(&mobj->refc)) panic(); return mobj; } /** * mobj_put() - put a MOBJ * @mobj: Pointer to a MOBJ or NULL * * Decreases reference counter of the @mobj and frees it if the counter * reaches 0. */ static inline void mobj_put(struct mobj *mobj) { if (mobj && refcount_dec(&mobj->refc)) mobj->ops->free(mobj); } /** * mobj_put_wipe() - wipe and put a MOBJ * @mobj: Pointer to a MOBJ or NULL * * Clears the memory represented by the mobj and then puts it. */ static inline void mobj_put_wipe(struct mobj *mobj) { if (mobj) { void *buf = mobj_get_va(mobj, 0, mobj->size); if (buf) memzero_explicit(buf, mobj->size); mobj_put(mobj); } } static inline uint64_t mobj_get_cookie(struct mobj *mobj) { if (mobj && mobj->ops && mobj->ops->get_cookie) return mobj->ops->get_cookie(mobj); #if defined(CFG_CORE_FFA) return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID; #else return 0; #endif } static inline struct fobj *mobj_get_fobj(struct mobj *mobj) { if (mobj && mobj->ops && mobj->ops->get_fobj) return mobj->ops->get_fobj(mobj); return NULL; } static inline bool mobj_is_nonsec(struct mobj *mobj) { return mobj_matches(mobj, CORE_MEM_NON_SEC); } static inline bool mobj_is_secure(struct mobj *mobj) { return mobj_matches(mobj, CORE_MEM_SEC); } static inline bool mobj_is_sdp_mem(struct mobj *mobj) { return mobj_matches(mobj, CORE_MEM_SDP_MEM); } static inline size_t mobj_get_phys_granule(struct mobj *mobj) { if (mobj->phys_granule) return mobj->phys_granule; return mobj->size; } static inline bool mobj_check_offset_and_len(struct mobj *mobj, size_t offset, size_t len) { size_t end_offs = 0; return len && !ADD_OVERFLOW(offset, len - 1, &end_offs) && end_offs < mobj->size; } struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr, enum buf_is_attr battr); #if defined(CFG_CORE_FFA) struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs); TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie); /* Functions for SPMC */ #ifdef CFG_CORE_SEL1_SPMC struct mobj_ffa *mobj_ffa_sel1_spmc_new(uint64_t cookie, unsigned int num_pages); void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj); TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie); #else struct mobj_ffa *mobj_ffa_spmc_new(uint64_t cookie, unsigned int num_pages); void mobj_ffa_spmc_delete(struct mobj_ffa *mobj); #endif uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj); TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx, paddr_t pa, unsigned int num_pages); uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj); #elif defined(CFG_CORE_DYN_SHM) /* reg_shm represents TEE shared memory */ struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, paddr_t page_offset, uint64_t cookie); /** * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie * @cookie: Cookie used by normal world when suppling the shared memory * * Searches for a registered shared memory MOBJ and if one with a matching * @cookie is found its reference counter is increased before returning * the MOBJ. * * Returns a valid pointer on success or NULL on failure. */ struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie); TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie); /** * mobj_reg_shm_unguard() - unguards a reg_shm * @mobj: pointer to a registered shared memory mobj * * A registered shared memory mobj is normally guarded against being * released with mobj_reg_shm_try_release_by_cookie(). After this function * has returned the mobj can be released by a call to * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it. */ void mobj_reg_shm_unguard(struct mobj *mobj); /* * mapped_shm represents registered shared buffer * which is mapped into OPTEE va space */ struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, paddr_t page_offset, uint64_t cookie); #endif /*CFG_CORE_DYN_SHM*/ #if !defined(CFG_CORE_DYN_SHM) static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused, size_t num_pages __unused, paddr_t page_offset __unused, uint64_t cookie __unused) { return NULL; } static inline struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie __unused) { return NULL; } #endif struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie); #ifdef CFG_PAGED_USER_TA bool mobj_is_paged(struct mobj *mobj); #else static inline bool mobj_is_paged(struct mobj *mobj __unused) { return false; } #endif struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file, uint32_t mem_type); #endif /*__MM_MOBJ_H*/ optee_os-4.3.0/core/include/mm/pgt_cache.h000066400000000000000000000056361464416617300204330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __MM_PGT_CACHE_H #define __MM_PGT_CACHE_H #include #include #include #include #include #ifdef CFG_WITH_LPAE #define PGT_SIZE (4 * 1024) #define PGT_NUM_PGT_PER_PAGE 1 #else #define PGT_SIZE (1 * 1024) #define PGT_NUM_PGT_PER_PAGE 4 #endif struct ts_ctx; struct pgt { void *tbl; vaddr_t vabase; #if !defined(CFG_CORE_PREALLOC_EL0_TBLS) struct ts_ctx *ctx; #endif bool populated; #if defined(CFG_PAGED_USER_TA) uint16_t num_used_entries; #endif #if defined(CFG_CORE_PREALLOC_EL0_TBLS) || \ (defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE)) struct pgt_parent *parent; #endif SLIST_ENTRY(pgt) link; }; SLIST_HEAD(pgt_cache, pgt); struct user_mode_ctx; bool pgt_check_avail(struct user_mode_ctx *uctx); /* * pgt_get_all() - makes all needed translation tables available * @uctx: the context to own the tables * * Guaranteed to succeed, but may need to sleep for a while to get all the * needed translation tables. */ #if defined(CFG_CORE_PREALLOC_EL0_TBLS) static inline void pgt_get_all(struct user_mode_ctx *uctx __unused) { } #else void pgt_get_all(struct user_mode_ctx *uctx); #endif /* * pgt_put_all() - informs the translation table manager that these tables * will not be needed for a while * @uctx: the context owning the tables to make inactive */ #if defined(CFG_CORE_PREALLOC_EL0_TBLS) static inline void pgt_put_all(struct user_mode_ctx *uctx __unused) { } #else void pgt_put_all(struct user_mode_ctx *uctx); #endif void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end); void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last); #if defined(CFG_CORE_PREALLOC_EL0_TBLS) static inline struct pgt *pgt_pop_from_cache_list(vaddr_t vabase __unused, struct ts_ctx *ctx __unused) { return NULL; } static inline void pgt_push_to_cache_list(struct pgt *pgt __unused) { } #else struct pgt *pgt_pop_from_cache_list(vaddr_t vabase, struct ts_ctx *ctx); void pgt_push_to_cache_list(struct pgt *pgt); #endif #if defined(CFG_CORE_PREALLOC_EL0_TBLS) static inline void pgt_init(void) { } #else void pgt_init(void); #endif void pgt_flush(struct user_mode_ctx *uctx); #if defined(CFG_PAGED_USER_TA) static inline void pgt_inc_used_entries(struct pgt *pgt) { pgt->num_used_entries++; assert(pgt->num_used_entries); } static inline void pgt_dec_used_entries(struct pgt *pgt) { assert(pgt->num_used_entries); pgt->num_used_entries--; } static inline void pgt_set_used_entries(struct pgt *pgt, size_t val) { pgt->num_used_entries = val; } #else static inline void pgt_inc_used_entries(struct pgt *pgt __unused) { } static inline void pgt_dec_used_entries(struct pgt *pgt __unused) { } static inline void pgt_set_used_entries(struct pgt *pgt __unused, size_t val __unused) { } #endif #endif /*__MM_PGT_CACHE_H*/ optee_os-4.3.0/core/include/mm/sp_mem.h000066400000000000000000000046171464416617300177740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021-2022, Arm Limited. */ #ifndef __MM_SP_MEM_H #define __MM_SP_MEM_H #include #include #include struct sp_mem; /* * struct sp_mem_receiver - Memory object instance for a FF-A receiver endpoint * * @perm: Receiver permission on the shared memory * @ref_count: Count retrieve requests from endpoint * @smem: Shared memory reference * @link: Link in related list */ struct sp_mem_receiver { struct ffa_mem_access_perm perm; uint8_t ref_count; struct sp_mem *smem; SLIST_ENTRY(sp_mem_receiver) link; }; /* * sp_mem_map_region represents the memory address when using FF-A shares. * Instead of storing the physical addresses and the size of the region, we use * the mobj's which were already used by the SPs. The offset is used to point * to the specific location inside the mobj memory range. */ struct sp_mem_map_region { struct mobj *mobj; /* * Offset (in pages) inside the mobj which is used to retrieve the * location. */ uint32_t page_offset; uint32_t page_count; SLIST_ENTRY(sp_mem_map_region) link; }; SLIST_HEAD(sp_mem_receiver_head, sp_mem_receiver); SLIST_HEAD(sp_mem_regions_head, sp_mem_map_region); /* * sp_mem is used as the main place to store the FF-A shares information. * For each FFA_SHARE message a new sp_mem object is created. * The receivers field is used to store all receiver specific information. * The regions field is used to store all data needed for retrieving the * shared addresses. */ struct sp_mem { struct sp_mem_regions_head regions; struct sp_mem_receiver_head receivers; /* Data which was passed inside struct ffa_mem_transaction */ uint16_t sender_id; uint8_t mem_reg_attr; uint32_t flags; uint64_t global_handle; uint64_t tag; SLIST_ENTRY(sp_mem) link; }; struct sp_mem *sp_mem_new(void); struct sp_mem_receiver *sp_mem_get_receiver(uint32_t s_id, struct sp_mem *smem); struct sp_mem *sp_mem_get(uint64_t handle); bool sp_mem_is_shared(struct sp_mem_map_region *new_reg); void *sp_mem_get_va(const struct user_mode_ctx *uctx, size_t offset, struct mobj *mobj); void sp_mem_remove(struct sp_mem *s_mem); void sp_mem_add(struct sp_mem *smem); struct mobj *sp_mem_new_mobj(uint64_t pages, uint32_t mem_type, bool is_secure); int sp_mem_add_pages(struct mobj *mobj, unsigned int *idx, paddr_t pa, unsigned int num_pages); #endif /*__MM_SP_MEM_H*/ optee_os-4.3.0/core/include/mm/tee_mm.h000066400000000000000000000060671464416617300177630ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MM_TEE_MM_H #define __MM_TEE_MM_H #include #include #include /* Define to indicate default pool initiation */ #define TEE_MM_POOL_NO_FLAGS 0 /* Flag to indicate that memory is allocated from hi address to low address */ #define TEE_MM_POOL_HI_ALLOC (1u << 0) /* Flag to indicate that pool should use nex_malloc instead of malloc */ #define TEE_MM_POOL_NEX_MALLOC (1u << 1) struct _tee_mm_entry_t { struct _tee_mm_pool_t *pool; struct _tee_mm_entry_t *next; uint32_t offset; /* offset in pages/sections */ uint32_t size; /* size in pages/sections */ }; typedef struct _tee_mm_entry_t tee_mm_entry_t; struct _tee_mm_pool_t { tee_mm_entry_t *entry; paddr_t lo; /* low boundary of the pool */ paddr_size_t size; /* pool size */ uint32_t flags; /* Config flags for the pool */ uint8_t shift; /* size shift */ unsigned int lock; #ifdef CFG_WITH_STATS size_t max_allocated; #endif }; typedef struct _tee_mm_pool_t tee_mm_pool_t; /* * Returns a pointer to the mm covering the supplied address, * if no mm is found NULL is returned. */ tee_mm_entry_t *tee_mm_find(const tee_mm_pool_t *pool, paddr_t addr); /* * Validates that an address (addr) is part of the secure virtual memory * Returns false if not valid, true if valid * NOTE: This function is executed in abort mode. * Please take care of stack usage */ static inline bool tee_mm_validate(const tee_mm_pool_t *pool, paddr_t addr) { return tee_mm_find(pool, addr) != 0; } /* * Returns a virtual address to the start of the allocated memory * for the mm entry. */ uintptr_t tee_mm_get_smem(const tee_mm_entry_t *mm); /* Init managed memory area */ bool tee_mm_init(tee_mm_pool_t *pool, paddr_t lo, paddr_size_t size, uint8_t shift, uint32_t flags); /* Kill managed memory area*/ void tee_mm_final(tee_mm_pool_t *pool); /* * Allocates size number of bytes in the paged virtual address space * Returns a handle to the memory. The handle is used as an input to * the tee_mm_free function. */ tee_mm_entry_t *tee_mm_alloc(tee_mm_pool_t *pool, size_t size); /* Allocate supplied memory range if it's free */ tee_mm_entry_t *tee_mm_alloc2(tee_mm_pool_t *pool, paddr_t base, size_t size); /* * Frees the entry in the paged virtual address space pointed to by the * input parameter p */ void tee_mm_free(tee_mm_entry_t *p); /* Returns size in sections or pages */ static inline size_t tee_mm_get_size(tee_mm_entry_t *p) { return p->size; } /* Returns offset from start of area in sections or pages */ static inline uint32_t tee_mm_get_offset(tee_mm_entry_t *p) { return p->offset; } /* Return size of the mm entry in bytes */ size_t tee_mm_get_bytes(const tee_mm_entry_t *mm); bool tee_mm_addr_is_within_range(const tee_mm_pool_t *pool, paddr_t addr); bool tee_mm_is_empty(tee_mm_pool_t *pool); #ifdef CFG_WITH_STATS void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats, bool reset); #endif #endif optee_os-4.3.0/core/include/mm/tee_mmu_types.h000066400000000000000000000103571464416617300213710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2021, Linaro Limited * Copyright (c) 2022, Arm Limited. */ #ifndef __MM_TEE_MMU_TYPES_H #define __MM_TEE_MMU_TYPES_H #include #include #include #define TEE_MATTR_VALID_BLOCK BIT(0) #define TEE_MATTR_TABLE BIT(3) #define TEE_MATTR_PR BIT(4) #define TEE_MATTR_PW BIT(5) #define TEE_MATTR_PX BIT(6) #define TEE_MATTR_PRW (TEE_MATTR_PR | TEE_MATTR_PW) #define TEE_MATTR_PRX (TEE_MATTR_PR | TEE_MATTR_PX) #define TEE_MATTR_PRWX (TEE_MATTR_PRW | TEE_MATTR_PX) #define TEE_MATTR_UR BIT(7) #define TEE_MATTR_UW BIT(8) #define TEE_MATTR_UX BIT(9) #define TEE_MATTR_URW (TEE_MATTR_UR | TEE_MATTR_UW) #define TEE_MATTR_URX (TEE_MATTR_UR | TEE_MATTR_UX) #define TEE_MATTR_URWX (TEE_MATTR_URW | TEE_MATTR_UX) #define TEE_MATTR_PROT_MASK \ (TEE_MATTR_PRWX | TEE_MATTR_URWX | TEE_MATTR_GUARDED) #define TEE_MATTR_GLOBAL BIT(10) #define TEE_MATTR_SECURE BIT(11) #define TEE_MATTR_MEM_TYPE_MASK U(0x7) #define TEE_MATTR_MEM_TYPE_SHIFT U(12) /* These are shifted TEE_MATTR_MEM_TYPE_SHIFT */ /* * Device-nGnRnE most restrictive (equivalent to Strongly Ordered memory * in the ARMv7 architecture). * https://developer.arm.com/documentation/den0024/a/Memory-Ordering/Memory-types/Device-memory * * If an ARMv7 architecture operating system runs on a Cortex-A53 processor, * the Device memory type matches the nGnRE encoding and the Strongly-Ordered * memory type matches the nGnRnE memory type. * https://developer.arm.com/documentation/den0024/a/Memory-Ordering/Memory-types/Device-memory */ #define TEE_MATTR_MEM_TYPE_DEV U(0) /* Device-nGnRE */ #define TEE_MATTR_MEM_TYPE_CACHED U(1) #define TEE_MATTR_MEM_TYPE_STRONGLY_O U(2) /* Device-nGnRnE */ #define TEE_MATTR_MEM_TYPE_TAGGED U(3) #define TEE_MATTR_GUARDED BIT(15) /* * Tags TA mappings which are only used during a single call (open session * or invoke command parameters). */ #define VM_FLAG_EPHEMERAL BIT(0) /* * Tags TA mappings that must not be removed (kernel mappings while in user * mode). */ #define VM_FLAG_PERMANENT BIT(1) /* Tags TA mappings that may be shared with other TAs. */ #define VM_FLAG_SHAREABLE BIT(2) /* Tags temporary mappings added to load the ldelf binary */ #define VM_FLAG_LDELF BIT(3) /* * The mapping should only be mapped read-only, not enforced by the vm_* * functions. */ #define VM_FLAG_READONLY BIT(4) /* * Set of flags used by tee_mmu_is_vbuf_inside_ta_private() and * tee_mmu_is_vbuf_intersect_ta_private() to tell if a certain region is * mapping TA internal memory or not. */ #define VM_FLAGS_NONPRIV (VM_FLAG_EPHEMERAL | \ VM_FLAG_PERMANENT | \ VM_FLAG_SHAREABLE) struct tee_mmap_region { unsigned int type; /* enum teecore_memtypes */ unsigned int region_size; paddr_t pa; vaddr_t va; size_t size; uint32_t attr; /* TEE_MATTR_* above */ }; struct vm_region { struct mobj *mobj; size_t offset; vaddr_t va; size_t size; uint16_t attr; /* TEE_MATTR_* above */ uint16_t flags; /* VM_FLAGS_* above */ TAILQ_ENTRY(vm_region) link; }; enum vm_paged_region_type { PAGED_REGION_TYPE_RO, PAGED_REGION_TYPE_RW, PAGED_REGION_TYPE_LOCK, }; struct vm_paged_region { struct fobj *fobj; size_t fobj_pgoffs; enum vm_paged_region_type type; uint32_t flags; vaddr_t base; size_t size; struct pgt **pgt_array; TAILQ_ENTRY(vm_paged_region) link; TAILQ_ENTRY(vm_paged_region) fobj_link; }; TAILQ_HEAD(vm_paged_region_head, vm_paged_region); TAILQ_HEAD(vm_region_head, vm_region); struct vm_info { struct vm_region_head regions; unsigned int asid; }; static inline void mattr_perm_to_str(char *str, size_t size, uint32_t attr) { if (size < 7) return; str[0] = (attr & TEE_MATTR_UR) ? 'r' : '-'; str[1] = (attr & TEE_MATTR_UW) ? 'w' : '-'; str[2] = (attr & TEE_MATTR_UX) ? 'x' : '-'; str[3] = (attr & TEE_MATTR_PR) ? 'R' : '-'; str[4] = (attr & TEE_MATTR_PW) ? 'W' : '-'; str[5] = (attr & TEE_MATTR_PX) ? 'X' : '-'; str[6] = '\0'; } static inline bool mattr_is_cached(uint32_t mattr) { uint32_t mem_type = (mattr >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK; return mem_type == TEE_MATTR_MEM_TYPE_CACHED || mem_type == TEE_MATTR_MEM_TYPE_TAGGED; } #endif optee_os-4.3.0/core/include/mm/tee_pager.h000066400000000000000000000174321464416617300204460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2021, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MM_TEE_PAGER_H #define __MM_TEE_PAGER_H #include #include #include #include #include #include #include /* * tee_pager_early_init() - Perform early initialization of pager * * Panics if some error occurs */ void tee_pager_early_init(void); /* * tee_pager_get_table_info() - Fills in table info for address mapped in * translation table managed by the pager. * @va: address to look up * @ti: filled in table info * * Returns true if address is in the pager translation tables else false */ bool tee_pager_get_table_info(vaddr_t va, struct core_mmu_table_info *ti); /* * tee_pager_phys_to_virt() - Translate physical address to virtual address * looking in the pager page tables * @pa: address to translate * @len: check for length is mapped linearly in CORE_MMU_PGDIR_SIZE range * * Returns found virtual address or NULL on error */ void *tee_pager_phys_to_virt(paddr_t pa, size_t len); /* * tee_pager_set_alias_area() - Initialize pager alias area * @mm_alias: The alias area where all physical pages managed by the * pager are aliased * * Panics if called twice or some other error occurs. */ void tee_pager_set_alias_area(tee_mm_entry_t *mm_alias); /* * tee_pager_init_iv_region() - Initialized pager region for tags IVs used by RW * paged fobjs * @fobj: fobj backing the region * * Panics if called twice or some other error occurs. * * Returns virtual address of start of IV region. */ vaddr_t tee_pager_init_iv_region(struct fobj *fobj); /* * tee_pager_generate_authenc_key() - Generates authenc key for r/w paging * * Needs to draw random from RNG, panics if some error occurs. */ #ifdef CFG_WITH_PAGER void tee_pager_generate_authenc_key(void); #else static inline void tee_pager_generate_authenc_key(void) { } #endif /* * tee_pager_add_core_region() - Adds a pageable core region * @base: base of covered memory region * @type: type of memory region * @fobj: fobj backing the region * * Non-page aligned base or size will cause a panic. */ void tee_pager_add_core_region(vaddr_t base, enum vm_paged_region_type type, struct fobj *fobj); /* * tee_pager_add_um_region() - Adds a pageable user TA region * @uctx: user mode context of the region * @base: base of covered memory region * @fobj: fobj of the store backing the memory region * * The mapping is created suitable to initialize the memory content while * loading the TA. Once the TA is properly loaded the regions should be * finalized with tee_pager_set_um_region_attr() to get more strict settings. * * Return TEE_SUCCESS on success, anything else if the region can't be added */ #ifdef CFG_PAGED_USER_TA TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx, vaddr_t base, struct fobj *fobj, uint32_t prot); #else static inline TEE_Result tee_pager_add_um_region(struct user_mode_ctx *uctx __unused, vaddr_t base __unused, struct fobj *fobj __unused, uint32_t prot __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /* * tee_pager_set_um_region_attr() - Set attributes of a initialized memory * region * @uctx: user mode context of the region * @base: base of covered memory region * @size: size of covered memory region * @flags: TEE_MATTR_U* flags describing permissions of the region * * Return true on success of false if the region can't be updated */ #ifdef CFG_PAGED_USER_TA bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx, vaddr_t base, size_t size, uint32_t flags); #else static inline bool tee_pager_set_um_region_attr(struct user_mode_ctx *uctx __unused, vaddr_t base __unused, size_t size __unused, uint32_t flags __unused) { return false; } #endif #ifdef CFG_PAGED_USER_TA void tee_pager_rem_um_region(struct user_mode_ctx *uctx, vaddr_t base, size_t size); #else static inline void tee_pager_rem_um_region(struct user_mode_ctx *uctx __unused, vaddr_t base __unused, size_t size __unused) { } #endif #ifdef CFG_PAGED_USER_TA TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx, vaddr_t va); #else static inline TEE_Result tee_pager_split_um_region(struct user_mode_ctx *uctx __unused, vaddr_t va __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif #ifdef CFG_PAGED_USER_TA void tee_pager_merge_um_region(struct user_mode_ctx *uctx, vaddr_t va, size_t len); #else static inline void tee_pager_merge_um_region(struct user_mode_ctx *uctx __unused, vaddr_t va __unused, size_t len __unused) { } #endif /* * tee_pager_rem_uma_regions() - Remove all user TA regions * @uctx: user mode context * * This function is called when a user mode context is teared down. */ #ifdef CFG_PAGED_USER_TA void tee_pager_rem_um_regions(struct user_mode_ctx *uctx); #else static inline void tee_pager_rem_um_regions(struct user_mode_ctx *uctx __unused) { } #endif /* * tee_pager_assign_um_tables() - Assigns translation table to a user ta * @uctx: user mode context * * This function is called to assign translation tables for the pageable * regions of a user TA. */ #ifdef CFG_PAGED_USER_TA void tee_pager_assign_um_tables(struct user_mode_ctx *uctx); #else static inline void tee_pager_assign_um_tables(struct user_mode_ctx *uctx __unused) { } #endif /* * Adds physical pages to the pager to use. The supplied virtual address range * is searched for mapped physical pages and unmapped pages are ignored. * * vaddr is the first virtual address * npages is the number of pages to add */ void tee_pager_add_pages(vaddr_t vaddr, size_t npages, bool unmap); /* * tee_pager_alloc() - Allocate read-write virtual memory from pager. * @size: size of memory in bytes * * @return NULL on failure or a pointer to the virtual memory on success. */ void *tee_pager_alloc(size_t size); #ifdef CFG_PAGED_USER_TA /* * tee_pager_pgt_save_and_release_entries() - Save dirty pages to backing store * and remove physical page from translation table * @pgt: page table descriptor * * This function is called when a translation table needs to be recycled */ void tee_pager_pgt_save_and_release_entries(struct pgt *pgt); #else static inline void tee_pager_pgt_save_and_release_entries(struct pgt *pgt __unused) { } #endif /* * tee_pager_release_phys() - Release physical pages used for mapping * @addr: virtual address of first page to release * @size: number of bytes to release * * Only pages completely covered by the supplied range are affected. This * function only supplies a hint to the pager that the physical page can be * reused. The caller can't expect a released memory range to hold a * specific bit pattern when used next time. * * Note that the virtual memory allocation is still valid after this * function has returned, it's just the content that may or may not have * changed. */ #ifdef CFG_WITH_PAGER void tee_pager_release_phys(void *addr, size_t size); #else static inline void tee_pager_release_phys(void *addr __unused, size_t size __unused) { } #endif /* * Statistics on the pager */ struct tee_pager_stats { size_t hidden_hits; size_t ro_hits; size_t rw_hits; size_t zi_released; size_t npages; /* number of load pages */ size_t npages_all; /* number of pages */ }; #ifdef CFG_WITH_PAGER void tee_pager_get_stats(struct tee_pager_stats *stats); bool tee_pager_handle_fault(struct abort_info *ai); #else /*CFG_WITH_PAGER*/ static inline bool tee_pager_handle_fault(struct abort_info *ai __unused) { return false; } static inline void tee_pager_get_stats(struct tee_pager_stats *stats) { memset(stats, 0, sizeof(struct tee_pager_stats)); } #endif /*CFG_WITH_PAGER*/ void tee_pager_invalidate_fobj(struct fobj *fobj); #endif /*MM_TEE_PAGER_H*/ optee_os-4.3.0/core/include/mm/vm.h000066400000000000000000000072371464416617300171370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MM_VM_H #define __MM_VM_H #include #include #include /* Allocate context resources like ASID and MMU table information */ TEE_Result vm_info_init(struct user_mode_ctx *uctx, struct ts_ctx *ts_ctx); /* Release context resources like ASID */ void vm_info_final(struct user_mode_ctx *uctx); /* * Creates a memory map of a mobj. * Desired virtual address can be specified in @va otherwise @va must be * initialized to 0 if the next available can be chosen. * * @pad_begin and @pad_end specify how much extra free space should be kept * when establishing the map. This allows mapping the first part of for * instance an ELF file while knowing that the next part which has to be of * a certain offset from the first part also will succeed. */ TEE_Result vm_map_pad(struct user_mode_ctx *uctx, vaddr_t *va, size_t len, uint32_t prot, uint32_t flags, struct mobj *mobj, size_t offs, size_t pad_begin, size_t pad_end, size_t align); /* * Creates a memory map of a mobj. * Desired virtual address can be specified in @va otherwise @va must be * initialized to 0 if the next available can be chosen. */ static inline TEE_Result vm_map(struct user_mode_ctx *uctx, vaddr_t *va, size_t len, uint32_t prot, uint32_t flags, struct mobj *mobj, size_t offs) { return vm_map_pad(uctx, va, len, prot, flags, mobj, offs, 0, 0, 0); } TEE_Result vm_remap(struct user_mode_ctx *uctx, vaddr_t *new_va, vaddr_t old_va, size_t len, size_t pad_begin, size_t pad_end); TEE_Result vm_get_flags(struct user_mode_ctx *uctx, vaddr_t va, size_t len, uint32_t *flags); TEE_Result vm_get_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, uint16_t *prot); TEE_Result vm_set_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, uint32_t prot); TEE_Result vm_unmap(struct user_mode_ctx *uctx, vaddr_t va, size_t len); /* Map parameters for a user TA */ TEE_Result vm_map_param(struct user_mode_ctx *uctx, struct tee_ta_param *param, void *param_va[TEE_NUM_PARAMS]); void vm_clean_param(struct user_mode_ctx *uctx); /* * User mode private memory is defined as user mode image static segment * (code, ro/rw static data, heap, stack). The sole other virtual memory * mapped to user mode are memref parameters. These later are considered * outside user mode private memory as it might be accessed by the user * mode context and its client(s). */ bool vm_buf_is_inside_um_private(const struct user_mode_ctx *uctx, const void *va, size_t size); bool vm_buf_intersects_um_private(const struct user_mode_ctx *uctx, const void *va, size_t size); TEE_Result vm_buf_to_mboj_offs(const struct user_mode_ctx *uctx, const void *va, size_t size, struct mobj **mobj, size_t *offs); /* Helper function for virt_to_phys(), shouldn't be used directly elsewhere */ TEE_Result vm_va2pa(const struct user_mode_ctx *uctx, void *ua, paddr_t *pa); /* Helper function for phys_to_virt(), shouldn't be used directly elsewhere */ void *vm_pa2va(const struct user_mode_ctx *uctx, paddr_t pa, size_t pa_size); /* * Return TEE_SUCCESS or TEE_ERROR_ACCESS_DENIED when buffer exists or return * another TEE_Result code. */ TEE_Result vm_check_access_rights(const struct user_mode_ctx *uctx, uint32_t flags, uaddr_t uaddr, size_t len); /* Set user context @ctx or core privileged context if @ctx is NULL */ void vm_set_ctx(struct ts_ctx *ctx); struct mobj *vm_get_mobj(struct user_mode_ctx *uctx, vaddr_t va, size_t *len, uint16_t *prot, size_t *offs); #endif /*__MM_VM_H*/ optee_os-4.3.0/core/include/optee_msg.h000066400000000000000000000300161464416617300200550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2020, Linaro Limited */ #ifndef __OPTEE_MSG_H #define __OPTEE_MSG_H #include #include #include /* * This file defines the OP-TEE message protocol used to communicate * with an instance of OP-TEE running in secure world. */ /***************************************************************************** * Part 1 - formatting of messages *****************************************************************************/ #define OPTEE_MSG_ATTR_TYPE_NONE U(0x0) #define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT U(0x1) #define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT U(0x2) #define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT U(0x3) #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT U(0x5) #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT U(0x6) #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT U(0x7) #define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT #define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT #define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT U(0x9) #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT U(0xa) #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT U(0xb) #define OPTEE_MSG_ATTR_TYPE_MASK GENMASK_32(7, 0) /* * Meta parameter to be absorbed by the Secure OS and not passed * to the Trusted Application. * * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION. */ #define OPTEE_MSG_ATTR_META BIT(8) /* * Pointer to a list of pages used to register user-defined SHM buffer. * Used with OPTEE_MSG_ATTR_TYPE_TMEM_*. * buf_ptr should point to the beginning of the buffer. Buffer will contain * list of page addresses. OP-TEE core can reconstruct contiguous buffer from * that page addresses list. Page addresses are stored as 64 bit values. * Last entry on a page should point to the next page of buffer. * Every entry in buffer should point to a 4k page beginning (12 least * significant bits must be equal to zero). * * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold * page offset of user buffer. * * So, entries should be placed like members of this structure: * * struct page_data { * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1]; * uint64_t next_page_data; * }; * * Structure is designed to exactly fit into the page size * OPTEE_MSG_NONCONTIG_PAGE_SIZE which is a standard 4KB page. * * The size of 4KB is chosen because this is the smallest page size for ARM * architectures. If REE uses larger pages, it should divide them to 4KB ones. */ #define OPTEE_MSG_ATTR_NONCONTIG BIT(9) /* * Memory attributes for caching passed with temp memrefs. The actual value * used is defined outside the message protocol with the exception of * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already * defined for the memory range should be used. If optee_smc.h is used as * bearer of this protocol OPTEE_SMC_SHM_* is used for values. */ #define OPTEE_MSG_ATTR_CACHE_SHIFT U(16) #define OPTEE_MSG_ATTR_CACHE_MASK GENMASK_32(2, 0) #define OPTEE_MSG_ATTR_CACHE_PREDEFINED U(0) /* * Same values as TEE_LOGIN_* from TEE Internal API */ #define OPTEE_MSG_LOGIN_PUBLIC U(0x00000000) #define OPTEE_MSG_LOGIN_USER U(0x00000001) #define OPTEE_MSG_LOGIN_GROUP U(0x00000002) #define OPTEE_MSG_LOGIN_APPLICATION U(0x00000004) #define OPTEE_MSG_LOGIN_APPLICATION_USER U(0x00000005) #define OPTEE_MSG_LOGIN_APPLICATION_GROUP U(0x00000006) /* * Page size used in non-contiguous buffer entries */ #define OPTEE_MSG_NONCONTIG_PAGE_SIZE U(4096) #define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff #ifndef __ASSEMBLER__ /** * struct optee_msg_param_tmem - temporary memory reference parameter * @buf_ptr: Address of the buffer * @size: Size of the buffer * @shm_ref: Temporary shared memory reference, pointer to a struct tee_shm * * Secure and normal world communicates pointers as physical address * instead of the virtual address. This is because secure and normal world * have completely independent memory mapping. Normal world can even have a * hypervisor which need to translate the guest physical address (AKA IPA * in ARM documentation) to a real physical address before passing the * structure to secure world. */ struct optee_msg_param_tmem { uint64_t buf_ptr; uint64_t size; uint64_t shm_ref; }; /** * struct optee_msg_param_rmem - registered memory reference parameter * @offs: Offset into shared memory reference * @size: Size of the buffer * @shm_ref: Shared memory reference, pointer to a struct tee_shm */ struct optee_msg_param_rmem { uint64_t offs; uint64_t size; uint64_t shm_ref; }; /** * struct optee_msg_param_fmem - FF-A memory reference parameter * @offs_lower: Lower bits of offset into shared memory reference * @offs_upper: Upper bits of offset into shared memory reference * @internal_offs: Internal offset into the first page of shared memory * reference * @size: Size of the buffer * @global_id: Global identifier of the shared memory */ struct optee_msg_param_fmem { uint32_t offs_low; uint16_t offs_high; uint16_t internal_offs; uint64_t size; uint64_t global_id; }; /** * struct optee_msg_param_value - opaque value parameter * * Value parameters are passed unchecked between normal and secure world. */ struct optee_msg_param_value { uint64_t a; uint64_t b; uint64_t c; }; /** * struct optee_msg_param - parameter used together with struct optee_msg_arg * @attr: attributes * @tmem: parameter by temporary memory reference * @rmem: parameter by registered memory reference * @fmem: parameter by FF-A registered memory reference * @value: parameter by opaque value * * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value, * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates * @rmem or @fmem depending on the conduit. * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used. */ struct optee_msg_param { uint64_t attr; union { struct optee_msg_param_tmem tmem; struct optee_msg_param_rmem rmem; struct optee_msg_param_fmem fmem; struct optee_msg_param_value value; } u; }; /** * struct optee_msg_arg - call argument * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_* * @func: Trusted Application function, specific to the Trusted Application, * used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND * @session: In parameter for all OPTEE_MSG_CMD_* except * OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead * @cancel_id: Cancellation id, a unique value to identify this request * @ret: return value * @ret_origin: origin of the return value * @num_params: number of parameters supplied to the OS Command * @params: the parameters supplied to the OS Command * * All normal calls to Trusted OS uses this struct. If cmd requires further * information than what these fields hold it can be passed as a parameter * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding * attrs field). All parameters tagged as meta have to come first. */ struct optee_msg_arg { uint32_t cmd; uint32_t func; uint32_t session; uint32_t cancel_id; uint32_t pad; uint32_t ret; uint32_t ret_origin; uint32_t num_params; /* num_params tells the actual number of element in params */ struct optee_msg_param params[]; }; /** * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg * * @num_params: Number of parameters embedded in the struct optee_msg_arg * * Returns the size of the struct optee_msg_arg together with the number * of embedded parameters. */ #define OPTEE_MSG_GET_ARG_SIZE(num_params) \ (sizeof(struct optee_msg_arg) + \ sizeof(struct optee_msg_param) * (num_params)) /* * Defines the maximum value of @num_params that can be passed to * OPTEE_MSG_GET_ARG_SIZE without a risk of crossing page boundary. */ #define OPTEE_MSG_MAX_NUM_PARAMS \ ((OPTEE_MSG_NONCONTIG_PAGE_SIZE - sizeof(struct optee_msg_arg)) / \ sizeof(struct optee_msg_param)) #endif /*__ASSEMBLER__*/ /***************************************************************************** * Part 2 - requests from normal world *****************************************************************************/ /* * Return the following UID if using API specified in this file without * further extensions: * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b. * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1, * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3. */ #define OPTEE_MSG_UID_0 U(0x384fb3e0) #define OPTEE_MSG_UID_1 U(0xe7f811e3) #define OPTEE_MSG_UID_2 U(0xaf630002) #define OPTEE_MSG_UID_3 U(0xa5d5c51b) #define OPTEE_MSG_FUNCID_CALLS_UID U(0xFF01) /* * Returns 2.0 if using API specified in this file without further * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR * and OPTEE_MSG_REVISION_MINOR */ #define OPTEE_MSG_REVISION_MAJOR U(2) #define OPTEE_MSG_REVISION_MINOR U(0) #define OPTEE_MSG_FUNCID_CALLS_REVISION U(0xFF03) /* * Get UUID of Trusted OS. * * Used by non-secure world to figure out which Trusted OS is installed. * Note that returned UUID is the UUID of the Trusted OS, not of the API. * * Returns UUID in 4 32-bit words in the same way as * OPTEE_MSG_FUNCID_CALLS_UID described above. */ #define OPTEE_MSG_OS_OPTEE_UUID_0 U(0x486178e0) #define OPTEE_MSG_OS_OPTEE_UUID_1 U(0xe7f811e3) #define OPTEE_MSG_OS_OPTEE_UUID_2 U(0xbc5e0002) #define OPTEE_MSG_OS_OPTEE_UUID_3 U(0xa5d5c51b) #define OPTEE_MSG_FUNCID_GET_OS_UUID U(0x0000) /* * Get revision of Trusted OS. * * Used by non-secure world to figure out which version of the Trusted OS * is installed. Note that the returned revision is the revision of the * Trusted OS, not of the API. * * Returns revision in 2 32-bit words in the same way as * OPTEE_MSG_CALLS_REVISION described above. */ #define OPTEE_MSG_FUNCID_GET_OS_REVISION U(0x0001) /* * Do a secure call with struct optee_msg_arg as argument * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd * * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application. * The first two parameters are tagged as meta, holding two value * parameters to pass the following information: * param[0].u.value.a-b uuid of Trusted Application * param[1].u.value.a-b uuid of Client * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_* * * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened * session to a Trusted Application. struct optee_msg_arg::func is Trusted * Application function, specific to the Trusted Application. * * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to * Trusted Application. * * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command. * * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The * information is passed as: * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_TMEM_INPUT * [| OPTEE_MSG_ATTR_NONCONTIG] * [in] param[0].u.tmem.buf_ptr physical address (of first fragment) * [in] param[0].u.tmem.size size (of first fragment) * [in] param[0].u.tmem.shm_ref holds shared memory reference * * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared * memory reference. The information is passed as: * [in] param[0].attr OPTEE_MSG_ATTR_TYPE_RMEM_INPUT * [in] param[0].u.rmem.shm_ref holds shared memory reference * [in] param[0].u.rmem.offs 0 * [in] param[0].u.rmem.size 0 * * OPTEE_MSG_CMD_DO_BOTTOM_HALF does the scheduled bottom half processing * of a driver. * * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF informs secure world that from now is * normal world unable to process asynchronous notifications. Typically * used when the driver is shut down. */ #define OPTEE_MSG_CMD_OPEN_SESSION U(0) #define OPTEE_MSG_CMD_INVOKE_COMMAND U(1) #define OPTEE_MSG_CMD_CLOSE_SESSION U(2) #define OPTEE_MSG_CMD_CANCEL U(3) #define OPTEE_MSG_CMD_REGISTER_SHM U(4) #define OPTEE_MSG_CMD_UNREGISTER_SHM U(5) #define OPTEE_MSG_CMD_DO_BOTTOM_HALF U(6) #define OPTEE_MSG_CMD_STOP_ASYNC_NOTIF U(7) #define OPTEE_MSG_FUNCID_CALL_WITH_ARG U(0x0004) #endif /* __OPTEE_MSG_H */ optee_os-4.3.0/core/include/optee_rpc_cmd.h000066400000000000000000000255541464416617300207110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2021, Linaro Limited */ #ifndef __OPTEE_RPC_CMD_H #define __OPTEE_RPC_CMD_H /* * All RPC is done with a struct optee_msg_arg as bearer of information, * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below. * Only the commands handled by the kernel driver are defined here. * * RPC communication with tee-supplicant is reversed compared to normal * client communication described above. The supplicant receives requests * and sends responses. */ /* * Load a TA into memory * * Since the size of the TA isn't known in advance the size of the TA is * can be queried with a NULL buffer. * * [in] value[0].a-b UUID * [out] memref[1] Buffer with TA */ #define OPTEE_RPC_CMD_LOAD_TA U(0) /* * Replay Protected Memory Block access * * [in] memref[0] Frames to device * [out] memref[1] Frames from device */ #define OPTEE_RPC_CMD_RPMB U(1) /* * File system access, see definition of protocol below */ #define OPTEE_RPC_CMD_FS U(2) /* * Get time * * Returns number of seconds and nano seconds since the Epoch, * 1970-01-01 00:00:00 +0000 (UTC). * * [out] value[0].a Number of seconds * [out] value[0].b Number of nano seconds. */ #define OPTEE_RPC_CMD_GET_TIME U(3) /* * Notification from/to secure world. * * If secure world needs to wait for something, for instance a mutex, it * does a notification wait request instead of spinning in secure world. * Conversely a synchronous notification can be sent when a secure * world mutex with a thread waiting thread is unlocked. * * This interface can also be used to wait for a asynchronous notification * which instead is sent via a non-secure interrupt. * * Waiting on notification * [in] value[0].a OPTEE_RPC_NOTIFICATION_WAIT * [in] value[0].b notification value * [in] value[0].c timeout in millisecond or 0 if no timeout * * Sending a synchronous notification * [in] value[0].a OPTEE_RPC_NOTIFICATION_SEND * [in] value[0].b notification value * [in] value[0].c shall be 0, reserved for future evolution */ #define OPTEE_RPC_CMD_NOTIFICATION U(4) #define OPTEE_RPC_NOTIFICATION_WAIT U(0) #define OPTEE_RPC_NOTIFICATION_SEND U(1) /* * Suspend execution * * [in] value[0].a Number of milliseconds to suspend */ #define OPTEE_RPC_CMD_SUSPEND U(5) /* * Allocate a piece of shared memory * * [in] value[0].a Type of memory one of * OPTEE_RPC_SHM_TYPE_* below * [in] value[0].b Requested size * [in] value[0].c Required alignment * [out] memref[0] Buffer */ #define OPTEE_RPC_CMD_SHM_ALLOC U(6) /* Memory that can be shared with a non-secure user space application */ #define OPTEE_RPC_SHM_TYPE_APPL U(0) /* Memory only shared with non-secure kernel */ #define OPTEE_RPC_SHM_TYPE_KERNEL U(1) /* * Memory shared with non-secure kernel and exported to a non-secure user * space application */ #define OPTEE_RPC_SHM_TYPE_GLOBAL U(2) /* * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC * * [in] value[0].a Type of memory one of * OPTEE_RPC_SHM_TYPE_* above * [in] value[0].b Value of shared memory reference or cookie */ #define OPTEE_RPC_CMD_SHM_FREE U(7) /* Was OPTEE_RPC_CMD_SQL_FS, which isn't supported any longer */ #define OPTEE_RPC_CMD_SQL_FS_RESERVED U(8) /* * Send TA profiling information to normal world * * [in/out] value[0].a File identifier. Must be set to 0 on * first call. A value >= 1 will be * returned on success. Re-use this value * to append data to the same file. * [in] memref[1] TA UUID * [in] memref[2] Profile data */ #define OPTEE_RPC_CMD_GPROF U(9) /* * Socket command, see definition of protocol below */ #define OPTEE_RPC_CMD_SOCKET U(10) /* * Send TA function graph data to normal world * * [in/out] value[0].a File identifier. Must be set to 0 on * first call. A value >= 1 will be * returned on success. Re-use this value * to append data to the same file. * [in] memref[1] TA UUID * [in] memref[2] function graph data */ #define OPTEE_RPC_CMD_FTRACE U(11) /* * tee-supplicant plugin command, see definition of protocol below */ #define OPTEE_RPC_CMD_SUPP_PLUGIN U(12) /* * Register timestamp buffer in the linux kernel optee driver * * [in] value[0].a Subcommand (register buffer, unregister buffer) * [in] value[0].b Physical address of timestamp buffer * [in] value[0].c Size of buffer */ #define OPTEE_RPC_CMD_BENCH_REG U(20) /* * Issue master requests (read and write operations) to an I2C chip. * * [in] value[0].a Transfer mode (OPTEE_RPC_I2C_TRANSFER_*) * [in] value[0].b The I2C bus (a.k.a adapter). * 16 bit field. * [in] value[0].c The I2C chip (a.k.a address). * 16 bit field (either 7 or 10 bit effective). * [in] value[1].a The I2C master control flags (ie, 10 bit address). * 16 bit field. * [in/out] memref[2] Buffer used for data transfers. * [out] value[3].a Number of bytes transferred by the REE. */ #define OPTEE_RPC_CMD_I2C_TRANSFER U(21) /* I2C master transfer modes */ #define OPTEE_RPC_I2C_TRANSFER_RD U(0) #define OPTEE_RPC_I2C_TRANSFER_WR U(1) /* I2C master control flags */ #define OPTEE_RPC_I2C_FLAGS_TEN_BIT BIT(0) /* * Definition of protocol for command OPTEE_RPC_CMD_FS */ /* * Open a file * * [in] value[0].a OPTEE_RPC_FS_OPEN * [in] memref[1] A string holding the file name * [out] value[2].a File descriptor of open file */ #define OPTEE_RPC_FS_OPEN U(0) /* * Create a file * * [in] value[0].a OPTEE_RPC_FS_CREATE * [in] memref[1] A string holding the file name * [out] value[2].a File descriptor of open file */ #define OPTEE_RPC_FS_CREATE U(1) /* * Close a file * * [in] value[0].a OPTEE_RPC_FS_CLOSE * [in] value[0].b File descriptor of open file. */ #define OPTEE_RPC_FS_CLOSE U(2) /* * Read from a file * * [in] value[0].a OPTEE_RPC_FS_READ * [in] value[0].b File descriptor of open file * [in] value[0].c Offset into file * [out] memref[1] Buffer to hold returned data */ #define OPTEE_RPC_FS_READ U(3) /* * Write to a file * * [in] value[0].a OPTEE_RPC_FS_WRITE * [in] value[0].b File descriptor of open file * [in] value[0].c Offset into file * [in] memref[1] Buffer holding data to be written */ #define OPTEE_RPC_FS_WRITE U(4) /* * Truncate a file * * [in] value[0].a OPTEE_RPC_FS_TRUNCATE * [in] value[0].b File descriptor of open file * [in] value[0].c Length of file. */ #define OPTEE_RPC_FS_TRUNCATE U(5) /* * Remove a file * * [in] value[0].a OPTEE_RPC_FS_REMOVE * [in] memref[1] A string holding the file name */ #define OPTEE_RPC_FS_REMOVE U(6) /* * Rename a file * * [in] value[0].a OPTEE_RPC_FS_RENAME * [in] value[0].b True if existing target should be removed * [in] memref[1] A string holding the old file name * [in] memref[2] A string holding the new file name */ #define OPTEE_RPC_FS_RENAME U(7) /* * Opens a directory for file listing * * [in] value[0].a OPTEE_RPC_FS_OPENDIR * [in] memref[1] A string holding the name of the directory * [out] value[2].a Handle to open directory */ #define OPTEE_RPC_FS_OPENDIR U(8) /* * Closes a directory handle * * [in] value[0].a OPTEE_RPC_FS_CLOSEDIR * [in] value[0].b Handle to open directory */ #define OPTEE_RPC_FS_CLOSEDIR U(9) /* * Read next file name of directory * * * [in] value[0].a OPTEE_RPC_FS_READDIR * [in] value[0].b Handle to open directory * [out] memref[1] A string holding the file name */ #define OPTEE_RPC_FS_READDIR U(10) /* End of definition of protocol for command OPTEE_RPC_CMD_FS */ /* * Definition of protocol for command OPTEE_RPC_CMD_SOCKET */ #define OPTEE_RPC_SOCKET_TIMEOUT_NONBLOCKING U(0) #define OPTEE_RPC_SOCKET_TIMEOUT_BLOCKING U(0xffffffff) /* * Open socket * * [in] value[0].a OPTEE_RPC_SOCKET_OPEN * [in] value[0].b TA instance id * [in] value[1].a Server port number * [in] value[1].b Protocol, TEE_ISOCKET_PROTOCOLID_* * [in] value[1].c Ip version TEE_IP_VERSION_* from tee_ipsocket.h * [in] memref[2] Server address * [out] value[3].a Socket handle (32-bit) */ #define OPTEE_RPC_SOCKET_OPEN U(0) /* * Close socket * * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE * [in] value[0].b TA instance id * [in] value[0].c Socket handle */ #define OPTEE_RPC_SOCKET_CLOSE U(1) /* * Close all sockets * * [in] value[0].a OPTEE_RPC_SOCKET_CLOSE_ALL * [in] value[0].b TA instance id */ #define OPTEE_RPC_SOCKET_CLOSE_ALL U(2) /* * Send data on socket * * [in] value[0].a OPTEE_RPC_SOCKET_SEND * [in] value[0].b TA instance id * [in] value[0].c Socket handle * [in] memref[1] Buffer to transmit * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_* * [out] value[2].b Number of transmitted bytes */ #define OPTEE_RPC_SOCKET_SEND U(3) /* * Receive data on socket * * [in] value[0].a OPTEE_RPC_SOCKET_RECV * [in] value[0].b TA instance id * [in] value[0].c Socket handle * [out] memref[1] Buffer to receive * [in] value[2].a Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_* */ #define OPTEE_RPC_SOCKET_RECV U(4) /* * Perform IOCTL on socket * * [in] value[0].a OPTEE_RPC_SOCKET_IOCTL * [in] value[0].b TA instance id * [in] value[0].c Socket handle * [in/out] memref[1] Buffer * [in] value[2].a Ioctl command */ #define OPTEE_RPC_SOCKET_IOCTL U(5) /* End of definition of protocol for command OPTEE_RPC_CMD_SOCKET */ /* * Definition of protocol for command OPTEE_RPC_CMD_SUPP_PLUGIN */ /* * Invoke tee-supplicant's plugin. * * [in] value[0].a OPTEE_RPC_SUPP_PLUGIN_INVOKE * [in] value[0].b uuid.d1 * [in] value[0].c uuid.d2 * [in] value[1].a uuid.d3 * [in] value[1].b uuid.d4 * [in] value[1].c cmd for plugin * [in] value[2].a sub_cmd for plugin * [out] value[2].b length of the outbuf (memref[3]), if out is needed. * [in/out] memref[3] buffer holding data for plugin * * UUID serialized into octets: * b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 b12 b13 b14 b15 * d1 | d2 | d3 | d4 * * The endianness of words d1, d2, d3 and d4 must be little-endian. * d1 word contains [b3 b2 b1 b0] * d2 word contains [b7 b6 b5 b4] * d3 word contains [b11 b10 b9 b8] * d4 word contains [b15 b14 b13 b12] */ #define OPTEE_RPC_SUPP_PLUGIN_INVOKE U(0) /* End of definition of protocol for command OPTEE_RPC_CMD_SUPP_PLUGIN */ #endif /*__OPTEE_RPC_CMD_H*/ optee_os-4.3.0/core/include/rng_support.h000066400000000000000000000004221464416617300204530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __RNG_SUPPORT_H__ #define __RNG_SUPPORT_H__ #include TEE_Result hw_get_random_bytes(void *buf, size_t blen); #endif /* __RNG_SUPPORT_H__ */ optee_os-4.3.0/core/include/scattered_array.h000066400000000000000000000110701464416617300212460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __SCATTERED_ARRAY_H #define __SCATTERED_ARRAY_H #include #include /* * A scattered array is assembled from items declared in different source * files depending on something like "SORT(.scattered_array*)" in the link * script to get everything assembled in the right order. * * Whenever a new scattered array is created with the macros below there's * no need to update the link script. */ #define __SCT_ARRAY_DEF_ITEM3(element_type, element_name, section_name) \ static const element_type element_name; \ DECLARE_KEEP_INIT(element_name); \ static const element_type element_name __used \ __section(section_name) #define __SCT_ARRAY_DEF_PG_ITEM3(element_type, element_name, section_name) \ static const element_type element_name __used \ __section(section_name) #define __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) \ __SCT_ARRAY_DEF_ITEM3(element_type, \ __scattered_array_ ## id ## array_name, \ ".scattered_array_" #array_name "_1_" #order) #define __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) \ __SCT_ARRAY_DEF_PG_ITEM3(element_type, \ __scattered_array_ ## id ## array_name, \ ".scattered_array_" #array_name "_1_" #order) #define __SCT_ARRAY_DEF_ITEM1(array_name, order, id, element_type) \ __SCT_ARRAY_DEF_ITEM2(array_name, order, id, element_type) #define __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, id, element_type) \ __SCT_ARRAY_DEF_PG_ITEM2(array_name, order, id, element_type) /* * Defines an item in a scattered array, sorted based on @order. * @array_name: Name of the scattered array * @order: Tag on which this item is sorted in the array * @element_type: The type of the elemenet */ #define SCATTERED_ARRAY_DEFINE_ITEM_ORDERED(array_name, order, element_type) \ __SCT_ARRAY_DEF_ITEM1(array_name, order, __COUNTER__, element_type) /* * Same as SCATTERED_ARRAY_DEFINE_ITEM_ORDERED except that references * to other objects (for instance null terminated strings) are allowed * to reside in the paged area without residing in the init area */ #define SCATTERED_ARRAY_DEFINE_PG_ITEM_ORDERED(array_name, order, \ element_type) \ __SCT_ARRAY_DEF_PG_ITEM1(array_name, order, __COUNTER__, element_type) /* * Defines an item in a scattered array * @array_name: Name of the scattered array * @element_type: The type of the elemenet */ #define SCATTERED_ARRAY_DEFINE_ITEM(array_name, element_type) \ __SCT_ARRAY_DEF_ITEM1(array_name, 0, __COUNTER__, element_type) /* * Same as SCATTERED_ARRAY_DEFINE_ITEM except that references to other * objects (for instance null terminated strings) are allowed to reside in * the paged area without residing in the init area */ #define SCATTERED_ARRAY_DEFINE_PG_ITEM(array_name, element_type) \ __SCT_ARRAY_DEF_PG_ITEM1(array_name, 0, __COUNTER__, element_type) /* * Returns the first element in a scattered array * @array_name: Name of the scattered array * @element_type: The type of the elemenet */ #define SCATTERED_ARRAY_BEGIN(array_name, element_type) (__extension__({ \ static const element_type __scattered_array_begin[0] __unused \ __section(".scattered_array_" #array_name "_0"); \ \ (const element_type *)scattered_array_relax_ptr( \ __scattered_array_begin); \ })) /* * Returns one entry past the last element in a scattered array * @array_name: Name of the scattered array * @element_type: The type of the elemenet */ #define SCATTERED_ARRAY_END(array_name, element_type) (__extension__({ \ static const element_type __scattered_array_end[0] __unused \ __section(".scattered_array_" #array_name "_2"); \ \ __scattered_array_end; \ })) /* * Loop over all elements in the scattered array * @elem: Iterator * @array_name: Name of the scattered array * @element_type: The type of the elemenet */ #define SCATTERED_ARRAY_FOREACH(elem, array_name, element_type) \ for ((elem) = SCATTERED_ARRAY_BEGIN(array_name, element_type); \ (elem) < SCATTERED_ARRAY_END(array_name, element_type); (elem)++) /* * scattered_array_relax_ptr() - relax pointer attributes * @p pointer to return * * If the pointer returned from the array __scattered_array_begin[] in * SCATTERED_ARRAY_BEGIN() is passed directly the compiler may notice that * it's an empty array and emit warnings. With the address passed via this * function the compiler will have no such knowledge about the pointer. * * Returns supplied pointer. */ const void *scattered_array_relax_ptr(const void *p) __attr_const; #endif /*__SCATTERED_ARRAY_H*/ optee_os-4.3.0/core/include/signed_hdr.h000066400000000000000000000150311464416617300202010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __SIGNED_HDR_H #define __SIGNED_HDR_H #include #include #include #include enum shdr_img_type { SHDR_TA = 0, SHDR_BOOTSTRAP_TA = 1, SHDR_ENCRYPTED_TA = 2, SHDR_SUBKEY = 3, }; #define SHDR_MAGIC 0x4f545348 /** * struct shdr - signed header * @magic: magic number must match SHDR_MAGIC * @img_type: image type, values defined by enum shdr_img_type * @img_size: image size in bytes * @algo: algorithm, defined by public key algorithms TEE_ALG_* * from TEE Internal API specification * @hash_size: size of the signed hash * @sig_size: size of the signature * @hash: hash of an image * @sig: signature of @hash */ struct shdr { uint32_t magic; uint32_t img_type; uint32_t img_size; uint32_t algo; uint16_t hash_size; uint16_t sig_size; /* * Commented out element used to visualize the layout dynamic part * of the struct. * * hash is accessed through the macro SHDR_GET_HASH and * signature is accessed through the macro SHDR_GET_SIG * * uint8_t hash[hash_size]; * uint8_t sig[sig_size]; */ }; static inline size_t shdr_get_size(const struct shdr *shdr) { size_t s = sizeof(*shdr); if (ADD_OVERFLOW(s, shdr->hash_size, &s) || ADD_OVERFLOW(s, shdr->sig_size, &s)) return 0; return s; } #define SHDR_GET_SIZE(x) shdr_get_size((x)) #define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1) #define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size) /** * struct shdr_subkey - subkey header * @uuid: UUID of the subkey * @name_size: The size of a name field that follows right * after this header, before the next signed header. * @subkey_version: Version of the subkey * @max_depth: Maximum depth supported below this subkey * @algo: Algorithm, defined by public key algorithms TEE_ALG_* * from TEE Internal API specification * @attr_count: Number of attributes for the public key matching * @algo. * @attrs: Attributes for the public key matching @algo. * @attrs[].id: Attribute ID TEE_ATTR_* from GlobalPlatform * @attrs[].offs: Offset of the attribute value from start of * struct shdr_subkey * @attrs[].size: Attribute size * * The @uuid defines UUID URN Namespace (RFC4122), the next UUID after this * header (another subkey or a TA) must be in the namespace of this UUID. * This means that further subkeys or TAs have their UUID fixed in the * hierarchy and cannot be moved up or below another subkey. * * If @name_size is non-zero it indicates that a name field of this size * exists and is used to generate the UUID of the following TA or subkey. * If it's zero the following TA or subkey must have a matching UUID. * * The @subkey_version field is used as a rollback measure. The version is * checked against earlier saved values of this subkey. If the latest known * version is less than this the stored value is updated. If the latest * known version is larger than this then the subkey is refused. * * The @max_depth defines how many levels are allowed below this subkey, * the value 0 means only TAs are allowed below. The value 1 means that * eventual subkeys below must have the value 0 in their @max_depth field. * * Each attribute of @attrs must be within range of the image size of this * header defined in the preceding struct shdr. * * The next struct shdr is found right after the indicated end of the * previous struct shdr. Signature verification starts over with the * next struct shdr using this subkey instead of the root key. */ struct shdr_subkey { uint8_t uuid[sizeof(TEE_UUID)]; uint32_t name_size; uint32_t subkey_version; uint32_t max_depth; uint32_t algo; uint32_t attr_count; struct shdr_subkey_attr { uint32_t id; uint32_t offs; uint32_t size; } attrs[]; }; /** * struct shdr_bootstrap_ta - bootstrap TA subheader * @uuid: UUID of the TA * @ta_version: Version of the TA */ struct shdr_bootstrap_ta { uint8_t uuid[sizeof(TEE_UUID)]; uint32_t ta_version; }; /** * struct shdr_encrypted_ta - encrypted TA header * @enc_algo: authenticated encyption algorithm, defined by symmetric key * algorithms TEE_ALG_* from TEE Internal API * specification * @flags: authenticated encyption flags * @iv_size: size of the initialization vector * @tag_size: size of the authentication tag * @iv: initialization vector * @tag: authentication tag */ struct shdr_encrypted_ta { uint32_t enc_algo; uint32_t flags; uint16_t iv_size; uint16_t tag_size; /* * Commented out element used to visualize the layout dynamic part * of the struct. * * iv is accessed through the macro SHDR_ENC_GET_IV and * tag is accessed through the macro SHDR_ENC_GET_TAG * * uint8_t iv[iv_size]; * uint8_t tag[tag_size]; */ }; #define SHDR_ENC_KEY_TYPE_MASK 0x1 enum shdr_enc_key_type { SHDR_ENC_KEY_DEV_SPECIFIC = 0, SHDR_ENC_KEY_CLASS_WIDE = 1, }; static inline size_t shdr_enc_get_size(const struct shdr_encrypted_ta *ehdr) { size_t s = sizeof(*ehdr); if (ADD_OVERFLOW(s, ehdr->iv_size, &s) || ADD_OVERFLOW(s, ehdr->tag_size, &s)) return 0; return s; } #define SHDR_ENC_GET_SIZE(x) shdr_enc_get_size((x)) #define SHDR_ENC_GET_IV(x) ((uint8_t *) \ (((struct shdr_encrypted_ta *)(x)) + 1)) #define SHDR_ENC_GET_TAG(x) ({ typeof(x) _x = (x); \ (SHDR_ENC_GET_IV(_x) + _x->iv_size); }) /* * Allocates a struct shdr large enough to hold the entire header, * excluding a subheader like struct shdr_bootstrap_ta. */ struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size); /* Frees a previously allocated struct shdr */ static inline void shdr_free(struct shdr *shdr) { free(shdr); } struct shdr_pub_key { uint32_t main_algo; uint8_t uuid[sizeof(TEE_UUID)]; uint8_t next_uuid[sizeof(TEE_UUID)]; uint32_t max_depth; uint32_t name_size; uint32_t version; union { struct rsa_public_key *rsa; } pub_key; }; TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs, const uint8_t *ns_img, size_t ns_img_size, const uint8_t next_uuid[sizeof(TEE_UUID)], uint32_t max_depth, struct shdr_pub_key *key); void shdr_free_pub_key(struct shdr_pub_key *key); TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, const struct shdr *shdr); /* * Verifies the signature in the @shdr. * * Note that the static part of struct shdr and payload still need to be * checked against the hash contained in the header. * * Returns TEE_SUCCESS on success or TEE_ERROR_SECURITY on failure */ TEE_Result shdr_verify_signature(const struct shdr *shdr); #endif /*__SIGNED_HDR_H*/ optee_os-4.3.0/core/include/spi.h000066400000000000000000000013631464416617300166710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __SPI_H__ #define __SPI_H__ #include enum spi_mode { SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3 }; enum spi_result { SPI_OK, SPI_ERR_CFG, SPI_ERR_PKTCNT, SPI_ERR_GENERIC }; struct spi_chip { const struct spi_ops *ops; }; struct spi_ops { void (*configure)(struct spi_chip *chip); void (*start)(struct spi_chip *chip); enum spi_result (*txrx8)(struct spi_chip *chip, uint8_t *wdat, uint8_t *rdat, size_t num_pkts); enum spi_result (*txrx16)(struct spi_chip *chip, uint16_t *wdat, uint16_t *rdat, size_t num_pkts); void (*end)(struct spi_chip *chip); void (*flushfifo)(struct spi_chip *chip); }; #endif /* __SPI_H__ */ optee_os-4.3.0/core/include/ta_pub_key.h000066400000000000000000000004771464416617300202250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __TA_PUB_KEY_H #define __TA_PUB_KEY_H #include extern const uint32_t ta_pub_key_exponent; extern const uint8_t ta_pub_key_modulus[]; extern const size_t ta_pub_key_modulus_size; #endif /*__TA_PUB_KEY_H*/ optee_os-4.3.0/core/include/tee/000077500000000000000000000000001464416617300164775ustar00rootroot00000000000000optee_os-4.3.0/core/include/tee/cache.h000066400000000000000000000004131464416617300177110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __TEE_CACHE_H #define __TEE_CACHE_H #include TEE_Result cache_operation(enum utee_cache_operation op, void *va, size_t len); #endif /* __TEE_CACHE_H */ optee_os-4.3.0/core/include/tee/entry_std.h000066400000000000000000000014511464416617300206640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_ENTRY_STD_H #define __TEE_ENTRY_STD_H #include #include #include /* * Standard call entry, __weak, overridable. If overridden should call * __tee_entry_std() at the end in order to handle the standard functions. * * These functions are called in a normal thread context. */ TEE_Result tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params); TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params); /* Get list head for sessions opened from non-secure */ void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions); #endif /* __TEE_ENTRY_STD_H */ optee_os-4.3.0/core/include/tee/fs_dirfile.h000066400000000000000000000114641464416617300207640ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __TEE_FS_DIRFILE_H #define __TEE_FS_DIRFILE_H #include #include struct tee_fs_dirfile_dirh; /** * struct tee_fs_dirfile_fileh - file handle * @file_number: sequence number of a file * @hash: hash of file, to be supplied to tee_fs_htree_open() * @idx: index of the file handle in the dirfile */ struct tee_fs_dirfile_fileh { uint32_t file_number; uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; int idx; }; /** * struct tee_fs_dirfile_operations - file interface supplied by user of this * interface * @open: opens a file * @close: closes a file, changes are discarded unless * @commit_writes is called before * @read: reads from an open file * @write: writes to an open file * @commit_writes: commits changes since the file was opened */ struct tee_fs_dirfile_operations { TEE_Result (*open)(bool create, uint8_t *hash, uint32_t min_counter, const TEE_UUID *uuid, struct tee_fs_dirfile_fileh *dfh, struct tee_file_handle **fh); void (*close)(struct tee_file_handle *fh); TEE_Result (*read)(struct tee_file_handle *fh, size_t pos, void *buf, size_t *len); TEE_Result (*write)(struct tee_file_handle *fh, size_t pos, const void *buf, size_t len); TEE_Result (*commit_writes)(struct tee_file_handle *fh, uint8_t *hash, uint32_t *counter); }; /** * tee_fs_dirfile_open() - opens a dirfile handle * @create: true if a new dirfile is to be created, else the dirfile * is read opened and verified * @hash: hash of underlying file * @min_counter: the smallest accepted value in struct htree_image.counter * @fops: file interface * @dirh: returned dirfile handle */ TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash, uint32_t min_counter, const struct tee_fs_dirfile_operations *fops, struct tee_fs_dirfile_dirh **dirh); /** * tee_fs_dirfile_close() - closes a dirfile handle * @dirh: dirfile handle * * All changes since last call to tee_fs_dirfile_commit_writes() are * discarded. */ void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh); /** * tee_fs_dirfile_commit_writes() - commit updates of dirfile * @dirh: dirfile handle * @hash: hash of underlying file is copied here if not NULL * @counter: version counter of underlying file is copied here if not NULL */ TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh, uint8_t *hash, uint32_t *counter); /** * tee_fs_dirfile_get_tmp() - get a temporary file handle * @dirh: dirfile handle * @dfh: returned temporary file handle * * Note, nothing is queued up as changes to the dirfile with this function. */ TEE_Result tee_fs_dirfile_get_tmp(struct tee_fs_dirfile_dirh *dirh, struct tee_fs_dirfile_fileh *dfh); /** * tee_fs_dirfile_find() - find a file handle * @dirh: dirfile handle * @uuid: uuid of requesting TA * @oid: object id * @oidlen: length of object id * @dfh: returned file handle */ TEE_Result tee_fs_dirfile_find(struct tee_fs_dirfile_dirh *dirh, const TEE_UUID *uuid, const void *oid, size_t oidlen, struct tee_fs_dirfile_fileh *dfh); /** * tee_fs_dirfile_fileh_to_fname() - get string representation of file handle * @dfh: file handle * @fname: buffer * @fnlen: length of buffer, updated to used length */ TEE_Result tee_fs_dirfile_fileh_to_fname(const struct tee_fs_dirfile_fileh *dfh, char *fname, size_t *fnlen); /** * tee_fs_dirfile_rename() - changes/supplies file handle object id * @dirh: dirfile handle * @uuid: uuid of requesting TA * @dfh: file handle * @oid: object id * @oidlen: length of object id * * If the supplied object id already is used by another file is that file * removed from the dirfile. */ TEE_Result tee_fs_dirfile_rename(struct tee_fs_dirfile_dirh *dirh, const TEE_UUID *uuid, struct tee_fs_dirfile_fileh *dfh, const void *oid, size_t oidlen); /** * tee_fs_dirfile_remove() - remove file * @dirh: dirfile handle * @dfh: file handle */ TEE_Result tee_fs_dirfile_remove(struct tee_fs_dirfile_dirh *dirh, const struct tee_fs_dirfile_fileh *dfh); /** * tee_fs_dirfile_update_hash() - update hash of file handle * @dirh: filefile handle * @dfh: file handle */ TEE_Result tee_fs_dirfile_update_hash(struct tee_fs_dirfile_dirh *dirh, const struct tee_fs_dirfile_fileh *dfh); /** * tee_fs_dirfile_get_next() - get object id of next file * @dirh: dirfile handle * @uuid: uuid of requesting TA * @idx: pointer to index * @oid: object id * @oidlen: length of object id * * If @idx contains -1 the first object id is returned, *@idx is updated * with the index of the file. */ TEE_Result tee_fs_dirfile_get_next(struct tee_fs_dirfile_dirh *dirh, const TEE_UUID *uuid, int *idx, void *oid, size_t *oidlen); #endif /*__TEE_FS_DIRFILE_H*/ optee_os-4.3.0/core/include/tee/fs_htree.h000066400000000000000000000132461464416617300204550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __TEE_FS_HTREE_H #define __TEE_FS_HTREE_H /* * The purpose of this API is to provide file integrity and confidentiality * in order to implement secure storage. On-disk data structures are * duplicated to make updates atomic, an update is finalized to disk with * tee_fs_htree_sync_to_storage(). * * This implementation doesn't provide rollback protection, it only * guarantees the integrity and confidentiality of the file. */ #include #include #include #define TEE_FS_HTREE_HASH_SIZE TEE_SHA256_HASH_SIZE #define TEE_FS_HTREE_IV_SIZE U(16) #define TEE_FS_HTREE_FEK_SIZE U(16) #define TEE_FS_HTREE_TAG_SIZE U(16) /* Internal struct provided to let the rpc callbacks know the size if needed */ struct tee_fs_htree_node_image { /* Note that calc_node_hash() depends on hash first in struct */ uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; uint8_t iv[TEE_FS_HTREE_IV_SIZE]; uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; uint16_t flags; }; /* * This struct is not interpreted by the hash tree, it's up to the user of * the interface to update etc if needed. */ struct tee_fs_htree_meta { uint64_t length; }; /* Internal struct needed by struct tee_fs_htree_image */ struct tee_fs_htree_imeta { struct tee_fs_htree_meta meta; uint32_t max_node_id; }; /* Internal struct provided to let the rpc callbacks know the size if needed */ struct tee_fs_htree_image { uint8_t iv[TEE_FS_HTREE_IV_SIZE]; uint8_t tag[TEE_FS_HTREE_TAG_SIZE]; uint8_t enc_fek[TEE_FS_HTREE_FEK_SIZE]; uint8_t imeta[sizeof(struct tee_fs_htree_imeta)]; uint32_t counter; }; /** * enum tee_fs_htree_type - type of hash tree element * @TEE_FS_HTREE_TYPE_HEAD: indicates a struct tee_fs_htree_image * @TEE_FS_HTREE_TYPE_NODE: indicates a struct tee_fs_htree_node_image * @TEE_FS_HTREE_TYPE_BLOCK: indicates a data block */ enum tee_fs_htree_type { TEE_FS_HTREE_TYPE_HEAD, TEE_FS_HTREE_TYPE_NODE, TEE_FS_HTREE_TYPE_BLOCK, }; struct tee_fs_rpc_operation; /** * struct tee_fs_htree_storage - storage description supplied by user of * this interface * @block_size: size of data blocks * @rpc_read_init: initialize a struct tee_fs_rpc_operation for an RPC read * operation * @rpc_write_init: initialize a struct tee_fs_rpc_operation for an RPC * write operation * * The @idx arguments starts counting from 0. The @vers arguments are either * 0 or 1. The @data arguments is a pointer to a buffer in non-secure shared * memory where the encrypted data is stored. */ struct tee_fs_htree_storage { size_t block_size; TEE_Result (*rpc_read_init)(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data); TEE_Result (*rpc_read_final)(struct tee_fs_rpc_operation *op, size_t *bytes); TEE_Result (*rpc_write_init)(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data); TEE_Result (*rpc_write_final)(struct tee_fs_rpc_operation *op); }; struct tee_fs_htree; /** * tee_fs_htree_open() - opens/creates a hash tree * @create: true if a new hash tree is to be created, else the hash tree * is read in and verified * @hash: hash of root node, ignored if NULL * @min_counter: the smallest accepted value in struct htree_image.counter * @uuid: uuid of requesting TA, may be NULL if not from a TA * @stor: storage description * @stor_aux: auxilary pointer supplied to callbacks in struct * tee_fs_htree_storage * @ht: returned hash tree on success */ TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, uint32_t min_counter, const TEE_UUID *uuid, const struct tee_fs_htree_storage *stor, void *stor_aux, struct tee_fs_htree **ht); /** * tee_fs_htree_close() - close a hash tree * @ht: hash tree */ void tee_fs_htree_close(struct tee_fs_htree **ht); /** * tee_fs_htree_get_meta() - get a pointer to associated struct * tee_fs_htree_meta * @ht: hash tree */ struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht); /** * tee_fs_htree_meta_set_dirty() - tell hash tree that meta were modified */ void tee_fs_htree_meta_set_dirty(struct tee_fs_htree *ht); /** * tee_fs_htree_sync_to_storage() - synchronize hash tree to storage * @ht: hash tree * @hash: hash of root node is copied to this if not NULL * @counter: ever increasing version counter is copied to this if not NULL * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht, uint8_t *hash, uint32_t *counter); /** * tee_fs_htree_truncate() - truncate a hash tree * @ht: hash tree * @block_num: the number of nodes to truncate to * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht, size_t block_num); /** * tee_fs_htree_write_block() - encrypt and write a data block to storage * @ht: hash tree * @block_num: block number * @block: pointer to a block of stor->block_size size * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht, size_t block_num, const void *block); /** * tee_fs_htree_write_block() - read and decrypt a data block from storage * @ht: hash tree * @block_num: block number * @block: pointer to a block of stor->block_size size * * Frees the hash tree and sets *ht to NULL on failure and returns an error code */ TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht, size_t block_num, void *block); #endif /*__TEE_FS_HTREE_H*/ optee_os-4.3.0/core/include/tee/svc_cache.h000066400000000000000000000006041464416617300205660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __TEE_SVC_CACHE_H #define __TEE_SVC_CACHE_H #include #include #ifdef CFG_CACHE_API TEE_Result syscall_cache_operation(void *va, size_t len, unsigned long op); #else #define syscall_cache_operation syscall_not_supported #endif #endif /*__TEE_SVC_CACHE_H*/ optee_os-4.3.0/core/include/tee/tadb.h000066400000000000000000000040021464416617300175560ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __TEE_TADB_H #define __TEE_TADB_H #include struct tee_tadb_ta_write; struct tee_tadb_ta_read; /* * struct tee_tadb_property * @uuid: UUID of Trusted Application (TA) or Security Domain (SD) * @version: Version of TA or SD * @custom_size:Size of customized properties, prepended to the encrypted * TA binary * @bin_size: Size of the binary TA */ struct tee_tadb_property { TEE_UUID uuid; uint32_t version; uint32_t custom_size; uint32_t bin_size; }; struct tee_fs_rpc_operation; struct tee_tadb_file_operations { TEE_Result (*open)(uint32_t file_number, int *fd); TEE_Result (*create)(uint32_t file_number, int *fd); void (*close)(int fd); TEE_Result (*remove)(uint32_t file_number); TEE_Result (*read_init)(struct tee_fs_rpc_operation *op, int fd, size_t pos, uint8_t **data, size_t bytes); TEE_Result (*read_final)(struct tee_fs_rpc_operation *op, size_t *bytes); TEE_Result (*write_init)(struct tee_fs_rpc_operation *op, int fd, size_t pos, uint8_t **data, size_t len); TEE_Result (*write_final)(struct tee_fs_rpc_operation *op); }; TEE_Result tee_tadb_ta_create(const struct tee_tadb_property *property, struct tee_tadb_ta_write **ta); TEE_Result tee_tadb_ta_write(struct tee_tadb_ta_write *ta, const void *buf, size_t len); void tee_tadb_ta_close_and_delete(struct tee_tadb_ta_write *ta); TEE_Result tee_tadb_ta_close_and_commit(struct tee_tadb_ta_write *ta); TEE_Result tee_tadb_ta_delete(const TEE_UUID *uuid); TEE_Result tee_tadb_ta_open(const TEE_UUID *uuid, struct tee_tadb_ta_read **ta); const struct tee_tadb_property * tee_tadb_ta_get_property(struct tee_tadb_ta_read *ta); TEE_Result tee_tadb_get_tag(struct tee_tadb_ta_read *ta, uint8_t *tag, unsigned int *tag_len); TEE_Result tee_tadb_ta_read(struct tee_tadb_ta_read *ta, void *buf_core, void *buf_user, size_t *len); void tee_tadb_ta_close(struct tee_tadb_ta_read *ta); #endif /*__TEE_TADB_H*/ optee_os-4.3.0/core/include/tee/tee_cryp_concat_kdf.h000066400000000000000000000007331464416617300226400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __TEE_TEE_CRYP_CONCAT_KDF_H #define __TEE_TEE_CRYP_CONCAT_KDF_H #include TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *other_info, size_t other_info_len, uint8_t *derived_key, size_t derived_key_len); #endif /* __TEE_TEE_CRYP_CONCAT_KDF_H */ optee_os-4.3.0/core/include/tee/tee_cryp_hkdf.h000066400000000000000000000006351464416617300214620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __TEE_TEE_CRYP_HKDF_H #define __TEE_TEE_CRYP_HKDF_H #include TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, size_t salt_len, const uint8_t *info, size_t info_len, uint8_t *okm, size_t okm_len); #endif /* __TEE_TEE_CRYP_HKDF_H */ optee_os-4.3.0/core/include/tee/tee_cryp_pbkdf2.h000066400000000000000000000006711464416617300217160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __TEE_TEE_CRYP_PBKDF2_H #define __TEE_TEE_CRYP_PBKDF2_H #include TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint32_t iteration_count, uint8_t *derived_key, size_t derived_key_len); #endif /* __TEE_TEE_CRYP_PBKDF2_H */ optee_os-4.3.0/core/include/tee/tee_cryp_utl.h000066400000000000000000000021261464416617300213470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, Linaro Limited */ #ifndef __TEE_TEE_CRYP_UTL_H #define __TEE_TEE_CRYP_UTL_H #include #include TEE_Result tee_alg_get_digest_size(uint32_t algo, size_t *size); TEE_Result tee_hash_createdigest(uint32_t algo, const uint8_t *data, size_t datalen, uint8_t *digest, size_t digestlen); TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size); TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo, TEE_OperationMode mode, bool last_block, const uint8_t *data, size_t len, uint8_t *dst); /* * plat_prng_add_jitter_entropy() - Adds jitter to RNG entropy pool * @sid: source ID, normally unique per location of the call * @pnum: pointer where the pool number for this @sid is stored * * Note that the supplied @sid controls (CRYPTO_RNG_SRC_IS_QUICK()) whether * RPC is allowed to be performed or the event just will be queued for later * consumption. */ void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum); void plat_rng_init(void); #endif optee_os-4.3.0/core/include/tee/tee_fs.h000066400000000000000000000053731464416617300201250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_TEE_FS_H #define __TEE_TEE_FS_H #include #include #include #include #define TEE_FS_NAME_MAX U(350) typedef int64_t tee_fs_off_t; typedef uint32_t tee_fs_mode_t; struct tee_fs_dirent { uint8_t oid[TEE_OBJECT_ID_MAX_LEN]; size_t oidlen; }; struct tee_fs_dir; struct tee_file_handle; struct tee_pobj; /* * tee_fs implements a POSIX like secure file system with GP extension */ struct tee_file_operations { TEE_Result (*open)(struct tee_pobj *po, size_t *size, struct tee_file_handle **fh); TEE_Result (*create)(struct tee_pobj *po, bool overwrite, const void *head, size_t head_size, const void *attr, size_t attr_size, const void *data_core, const void *data_user, size_t data_size, struct tee_file_handle **fh); void (*close)(struct tee_file_handle **fh); TEE_Result (*read)(struct tee_file_handle *fh, size_t pos, void *buf_core, void *buf_user, size_t *len); TEE_Result (*write)(struct tee_file_handle *fh, size_t pos, const void *buf_core, const void *buf_user, size_t len); TEE_Result (*rename)(struct tee_pobj *old_po, struct tee_pobj *new_po, bool overwrite); TEE_Result (*remove)(struct tee_pobj *po); TEE_Result (*truncate)(struct tee_file_handle *fh, size_t size); TEE_Result (*opendir)(const TEE_UUID *uuid, struct tee_fs_dir **d); TEE_Result (*readdir)(struct tee_fs_dir *d, struct tee_fs_dirent **ent); void (*closedir)(struct tee_fs_dir *d); }; #ifdef CFG_REE_FS extern const struct tee_file_operations ree_fs_ops; #endif #ifdef CFG_RPMB_FS extern const struct tee_file_operations rpmb_fs_ops; TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create, struct tee_file_handle **fh); /** * Weak function which can be overridden by platforms to indicate that the RPMB * key is ready to be written. Defaults to true, platforms can return false to * prevent a RPMB key write in the wrong state. */ bool plat_rpmb_key_is_ready(void); #endif /* * Returns the appropriate tee_file_operations for the specified storage ID. * The value TEE_STORAGE_PRIVATE will select the REE FS if available, otherwise * RPMB. */ static inline const struct tee_file_operations * tee_svc_storage_file_ops(uint32_t storage_id) { switch (storage_id) { case TEE_STORAGE_PRIVATE: #if defined(CFG_REE_FS) return &ree_fs_ops; #elif defined(CFG_RPMB_FS) return &rpmb_fs_ops; #else return NULL; #endif #ifdef CFG_REE_FS case TEE_STORAGE_PRIVATE_REE: return &ree_fs_ops; #endif #ifdef CFG_RPMB_FS case TEE_STORAGE_PRIVATE_RPMB: return &rpmb_fs_ops; #endif default: return NULL; } } #endif /*__TEE_TEE_FS_H*/ optee_os-4.3.0/core/include/tee/tee_fs_key_manager.h000066400000000000000000000017411464416617300224620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __TEE_TEE_FS_KEY_MANAGER_H #define __TEE_TEE_FS_KEY_MANAGER_H #include #include #define TEE_FS_KM_CHIP_ID_LENGTH U(32) #define TEE_FS_KM_HMAC_ALG TEE_ALG_HMAC_SHA256 #define TEE_FS_KM_ENC_FEK_ALG TEE_ALG_AES_ECB_NOPAD #define TEE_FS_KM_SSK_SIZE TEE_SHA256_HASH_SIZE #define TEE_FS_KM_TSK_SIZE TEE_SHA256_HASH_SIZE #define TEE_FS_KM_FEK_SIZE U(16) /* bytes */ TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *encrypted_fek, size_t fek_size); TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, const uint8_t *in, size_t size, uint16_t blk_idx, const uint8_t *encrypted_fek, TEE_OperationMode mode); TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode, const uint8_t *in_key, size_t size, uint8_t *out_key); #endif optee_os-4.3.0/core/include/tee/tee_fs_rpc.h000066400000000000000000000025561464416617300207710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ /* * Interface with tee-supplicant for file operations */ #ifndef __TEE_TEE_FS_RPC_H #define __TEE_TEE_FS_RPC_H #include #include #include #include #include struct tee_fs_rpc_operation { uint32_t id; struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS]; size_t num_params; }; struct tee_fs_dirfile_fileh; TEE_Result tee_fs_rpc_open_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh, int *fd); TEE_Result tee_fs_rpc_create_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh, int *fd); TEE_Result tee_fs_rpc_close(uint32_t id, int fd); TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, uint32_t id, int fd, tee_fs_off_t offset, size_t data_len, void **out_data); TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, size_t *data_len); TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, uint32_t id, int fd, tee_fs_off_t offset, size_t data_len, void **data); TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op); TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len); TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh); #endif /* __TEE_TEE_FS_RPC_H */ optee_os-4.3.0/core/include/tee/tee_obj.h000066400000000000000000000020211464416617300202520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_TEE_OBJ_H #define __TEE_TEE_OBJ_H #include #include #include #include #define TEE_USAGE_DEFAULT 0xffffffff struct tee_obj { TAILQ_ENTRY(tee_obj) link; TEE_ObjectInfo info; bool busy; /* true if used by an operation */ uint32_t have_attrs; /* bitfield identifying set properties */ void *attr; size_t ds_pos; struct tee_pobj *pobj; /* ptr to persistant object */ struct tee_file_handle *fh; }; void tee_obj_add(struct user_ta_ctx *utc, struct tee_obj *o); TEE_Result tee_obj_get(struct user_ta_ctx *utc, vaddr_t obj_id, struct tee_obj **obj); void tee_obj_close(struct user_ta_ctx *utc, struct tee_obj *o); void tee_obj_close_all(struct user_ta_ctx *utc); TEE_Result tee_obj_verify(struct tee_ta_session *sess, struct tee_obj *o); struct tee_obj *tee_obj_alloc(void); void tee_obj_free(struct tee_obj *o); #endif optee_os-4.3.0/core/include/tee/tee_pobj.h000066400000000000000000000024721464416617300204440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_TEE_POBJ_H #define __TEE_TEE_POBJ_H #include #include #include #include struct tee_pobj { TAILQ_ENTRY(tee_pobj) link; uint32_t refcnt; TEE_UUID uuid; void *obj_id; uint32_t obj_id_len; uint32_t flags; uint32_t obj_info_usage; bool temporary; /* can be changed while creating == true */ bool creating; /* can only be changed with mutex held */ /* Filesystem handling this object */ const struct tee_file_operations *fops; }; enum tee_pobj_usage { TEE_POBJ_USAGE_OPEN, TEE_POBJ_USAGE_RENAME, TEE_POBJ_USAGE_CREATE, TEE_POBJ_USAGE_ENUM, }; TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len, uint32_t flags, enum tee_pobj_usage usage, const struct tee_file_operations *fops, struct tee_pobj **obj); void tee_pobj_create_final(struct tee_pobj *obj); TEE_Result tee_pobj_release(struct tee_pobj *obj); TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id, uint32_t obj_id_len); /* * Locks and unlocks a mutex intended to protect the obj_info_usage field * in struct tee_pobj. */ void tee_pobj_lock_usage(struct tee_pobj *obj); void tee_pobj_unlock_usage(struct tee_pobj *obj); #endif optee_os-4.3.0/core/include/tee/tee_supp_plugin_rpc.h000066400000000000000000000007231464416617300227200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Open Mobile Platform LLC */ #ifndef __TEE_TEE_SUPP_PLUGIN_RPC_H #define __TEE_TEE_SUPP_PLUGIN_RPC_H #include #include #include TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, uint32_t sub_cmd, void *buf_core, void *buf_user, size_t len, size_t *outlen); #endif /* __TEE_TEE_SUPP_PLUGIN_RPC_H */ optee_os-4.3.0/core/include/tee/tee_svc.h000066400000000000000000000041011464416617300202740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_TEE_SVC_H #define __TEE_TEE_SVC_H #include #include #include #include #include struct tee_ta_session; /* TA Properties */ struct tee_props { const char *name; /* prop_type is of type enum user_ta_prop_type*/ const uint32_t prop_type; /* either get_prop_func or both data and len */ TEE_Result (*get_prop_func)(struct ts_session *sess, void *buf, size_t *blen); const void *data; const size_t len; }; struct tee_vendor_props { const struct tee_props *props; size_t len; }; void syscall_sys_return(unsigned long ret); void syscall_log(const void *buf, size_t len); void syscall_panic(unsigned long code); TEE_Result syscall_not_supported(void); /* prop_set defined by enum utee_property */ TEE_Result syscall_get_property(unsigned long prop_set, unsigned long index, void *name, uint32_t *name_len, void *buf, uint32_t *blen, uint32_t *prop_type); TEE_Result syscall_get_property_name_to_index(unsigned long prop_set, void *name, unsigned long name_len, uint32_t *index); TEE_Result syscall_open_ta_session(const TEE_UUID *dest, unsigned long cancel_req_to, struct utee_params *params, uint32_t *sess, uint32_t *ret_orig); TEE_Result syscall_close_ta_session(unsigned long sess); TEE_Result syscall_invoke_ta_command(unsigned long sess, unsigned long cancel_req_to, unsigned long cmd_id, struct utee_params *params, uint32_t *ret_orig); TEE_Result syscall_check_access_rights(unsigned long flags, const void *buf, size_t len); TEE_Result syscall_get_cancellation_flag(uint32_t *cancel); TEE_Result syscall_unmask_cancellation(uint32_t *old_mask); TEE_Result syscall_mask_cancellation(uint32_t *old_mask); TEE_Result syscall_wait(unsigned long timeout); TEE_Result syscall_get_time(unsigned long cat, TEE_Time *time); TEE_Result syscall_set_ta_time(const TEE_Time *time); #endif /* __TEE_TEE_SVC_H */ optee_os-4.3.0/core/include/tee/tee_svc_cryp.h000066400000000000000000000076401464416617300213440ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TEE_TEE_SVC_CRYP_H #define __TEE_TEE_SVC_CRYP_H #include #include #include struct user_ta_ctx; TEE_Result syscall_cryp_obj_get_info(unsigned long obj, struct utee_object_info *info); TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj, unsigned long usage); TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, void *buffer, uint64_t *size); TEE_Result syscall_cryp_obj_alloc(unsigned long obj_type, unsigned long max_key_size, uint32_t *obj); TEE_Result syscall_cryp_obj_close(unsigned long obj); TEE_Result syscall_cryp_obj_reset(unsigned long obj); TEE_Result syscall_cryp_obj_populate(unsigned long obj, struct utee_attribute *attrs, unsigned long attr_count); TEE_Result syscall_cryp_obj_copy(unsigned long dst_obj, unsigned long src_obj); TEE_Result syscall_obj_generate_key(unsigned long obj, unsigned long key_size, const struct utee_attribute *params, unsigned long param_count); TEE_Result syscall_cryp_state_alloc(unsigned long algo, unsigned long op_mode, unsigned long key1, unsigned long key2, uint32_t *state); TEE_Result syscall_cryp_state_copy(unsigned long dst, unsigned long src); TEE_Result syscall_cryp_state_free(unsigned long state); void tee_svc_cryp_free_states(struct user_ta_ctx *utc); /* iv and iv_len are ignored for hash algorithms */ TEE_Result syscall_hash_init(unsigned long state, const void *iv, size_t iv_len); TEE_Result syscall_hash_update(unsigned long state, const void *chunk, size_t chunk_size); TEE_Result syscall_hash_final(unsigned long state, const void *chunk, size_t chunk_size, void *hash, uint64_t *hash_len); TEE_Result syscall_cipher_init(unsigned long state, const void *iv, size_t iv_len); TEE_Result syscall_cipher_update(unsigned long state, const void *src, size_t src_len, void *dest, uint64_t *dest_len); TEE_Result syscall_cipher_final(unsigned long state, const void *src, size_t src_len, void *dest, uint64_t *dest_len); TEE_Result syscall_cryp_derive_key(unsigned long state, const struct utee_attribute *params, unsigned long param_count, unsigned long derived_key); TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen); TEE_Result syscall_authenc_init(unsigned long state, const void *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); TEE_Result syscall_authenc_update_aad(unsigned long state, const void *aad_data, size_t aad_data_len); TEE_Result syscall_authenc_update_payload(unsigned long state, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len); TEE_Result syscall_authenc_enc_final(unsigned long state, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len, void *tag, uint64_t *tag_len); TEE_Result syscall_authenc_dec_final(unsigned long state, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len, const void *tag, size_t tag_len); TEE_Result syscall_asymm_operate(unsigned long state, const struct utee_attribute *usr_params, size_t num_params, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len); TEE_Result syscall_asymm_verify(unsigned long state, const struct utee_attribute *usr_params, size_t num_params, const void *data, size_t data_len, const void *sig, size_t sig_len); TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type, size_t max_key_size); void tee_obj_attr_free(struct tee_obj *o); void tee_obj_attr_clear(struct tee_obj *o); TEE_Result tee_obj_attr_to_binary(struct tee_obj *o, void *data, size_t *data_len); TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data, size_t data_len); TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src); #endif /* __TEE_TEE_SVC_CRYP_H */ optee_os-4.3.0/core/include/tee/tee_svc_storage.h000066400000000000000000000036241464416617300220310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2023, Linaro Limited */ #ifndef __TEE_TEE_SVC_STORAGE_H #define __TEE_TEE_SVC_STORAGE_H #include #include #include #include /* * Persistant Object Functions */ TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, size_t object_id_len, unsigned long flags, uint32_t *obj); TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, size_t object_id_len, unsigned long flags, unsigned long attr, void *data, size_t len, uint32_t *obj); TEE_Result syscall_storage_obj_del(unsigned long obj); TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, size_t object_id_len); /* * Persistent Object Enumeration Functions */ TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum); TEE_Result syscall_storage_free_enum(unsigned long obj_enum); TEE_Result syscall_storage_reset_enum(unsigned long obj_enum); TEE_Result syscall_storage_start_enum(unsigned long obj_enum, unsigned long storage_id); TEE_Result syscall_storage_next_enum(unsigned long obj_enum, struct utee_object_info *info, void *obj_id, uint64_t *len); /* * Data Stream Access Functions */ TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, uint64_t *count); TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len); TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len); TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, unsigned long whence); void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc); TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage); void tee_svc_storage_init(void); #endif /* __TEE_TEE_SVC_STORAGE_H */ optee_os-4.3.0/core/include/tee/tee_ta_enc_manager.h000066400000000000000000000011521464416617300224270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef __TEE_TEE_TA_ENC_MANAGER_H #define __TEE_TEE_TA_ENC_MANAGER_H #include #include #include #define TEE_TA_ENC_KEY_SIZE TEE_SHA256_HASH_SIZE TEE_Result tee_ta_decrypt_init(void **enc_ctx, struct shdr_encrypted_ta *ehdr, size_t len); TEE_Result tee_ta_decrypt_update(void *enc_ctx, uint8_t *dst, uint8_t *src, size_t len); TEE_Result tee_ta_decrypt_final(void *enc_ctx, struct shdr_encrypted_ta *ehdr, uint8_t *dst, uint8_t *src, size_t len); #endif optee_os-4.3.0/core/include/tee/uuid.h000066400000000000000000000011311464416617300176120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __TEE_UUID #define __TEE_UUID #include #include /** * tee_uuid_to_octets() - serialize a TEE_UUID into an octet string * @dst: pointer to octet string * @src: pointer TEE_UUID */ void tee_uuid_to_octets(uint8_t *dst, const TEE_UUID *src); /** * tee_uuid_from_octets() - de-serialize an octet string into a TEE_UUID * @dst: pointer TEE_UUID * @src: pointer to octet string */ void tee_uuid_from_octets(TEE_UUID *dst, const uint8_t *src); #endif /*__TEE_UUID*/ optee_os-4.3.0/core/kernel/000077500000000000000000000000001464416617300155575ustar00rootroot00000000000000optee_os-4.3.0/core/kernel/asan.c000066400000000000000000000143671464416617300166600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #include #include #include #if __GCC_VERSION >= 70000 #define ASAN_ABI_VERSION 7 #else #define ASAN_ABI_VERSION 6 #endif struct asan_source_location { const char *file_name; int line_no; int column_no; }; struct asan_global { uintptr_t beg; uintptr_t size; uintptr_t size_with_redzone; const char *name; const char *module_name; uintptr_t has_dynamic_init; struct asan_source_location *location; #if ASAN_ABI_VERSION >= 7 uintptr_t odr_indicator; #endif }; static vaddr_t asan_va_base; static size_t asan_va_size; static bool asan_active; static int8_t *va_to_shadow(const void *va) { vaddr_t sa = ((vaddr_t)va / ASAN_BLOCK_SIZE) + CFG_ASAN_SHADOW_OFFSET; return (int8_t *)sa; } static size_t va_range_to_shadow_size(const void *begin, const void *end) { return ((vaddr_t)end - (vaddr_t)begin) / ASAN_BLOCK_SIZE; } static bool va_range_inside_shadow(const void *begin, const void *end) { vaddr_t b = (vaddr_t)begin; vaddr_t e = (vaddr_t)end; if (b >= e) return false; return (b >= asan_va_base) && (e <= (asan_va_base + asan_va_size)); } static bool va_range_outside_shadow(const void *begin, const void *end) { vaddr_t b = (vaddr_t)begin; vaddr_t e = (vaddr_t)end; if (b >= e) return false; return (e <= asan_va_base) || (b >= (asan_va_base + asan_va_size)); } static size_t va_misalignment(const void *va) { return (vaddr_t)va & ASAN_BLOCK_MASK; } static bool va_is_well_aligned(const void *va) { return !va_misalignment(va); } void asan_set_shadowed(const void *begin, const void *end) { vaddr_t b = (vaddr_t)begin; vaddr_t e = (vaddr_t)end; assert(!asan_va_base); assert(va_is_well_aligned(begin)); assert(va_is_well_aligned(end)); assert(b < e); asan_va_base = b; asan_va_size = e - b; } void asan_tag_no_access(const void *begin, const void *end) { assert(va_is_well_aligned(begin)); assert(va_is_well_aligned(end)); assert(va_range_inside_shadow(begin, end)); asan_memset_unchecked(va_to_shadow(begin), ASAN_DATA_RED_ZONE, va_range_to_shadow_size(begin, end)); } void asan_tag_access(const void *begin, const void *end) { if (!asan_va_base || (begin == end)) return; assert(va_range_inside_shadow(begin, end)); assert(va_is_well_aligned(begin)); asan_memset_unchecked(va_to_shadow(begin), 0, va_range_to_shadow_size(begin, end)); if (!va_is_well_aligned(end)) *va_to_shadow(end) = ASAN_BLOCK_SIZE - va_misalignment(end); } void asan_tag_heap_free(const void *begin, const void *end) { if (!asan_va_base) return; assert(va_range_inside_shadow(begin, end)); assert(va_is_well_aligned(begin)); assert(va_is_well_aligned(end)); asan_memset_unchecked(va_to_shadow(begin), ASAN_HEAP_RED_ZONE, va_range_to_shadow_size(begin, end)); } __inhibit_loop_to_libcall void *asan_memset_unchecked(void *s, int c, size_t n) { uint8_t *b = s; size_t m; for (m = 0; m < n; m++) b[m] = c; return s; } __inhibit_loop_to_libcall void *asan_memcpy_unchecked(void *__restrict dst, const void *__restrict src, size_t len) { uint8_t *__restrict d = dst; const uint8_t *__restrict s = src; size_t n; for (n = 0; n < len; n++) d[n] = s[n]; return dst; } void asan_start(void) { assert(asan_va_base && !asan_active); asan_active = true; } static void check_access(vaddr_t addr, size_t size) { void *begin = (void *)addr; void *end = (void *)(addr + size); int8_t *a; int8_t *e; if (!asan_active || !size) return; if (va_range_outside_shadow(begin, end)) return; /* * If it isn't outside it has to be completely inside or there's a * problem. */ if (!va_range_inside_shadow(begin, end)) panic(); e = va_to_shadow((void *)(addr + size - 1)); for (a = va_to_shadow(begin); a <= e; a++) if (*a < 0) panic(); if (!va_is_well_aligned(end) && va_misalignment(end) > (size_t)(*e - ASAN_BLOCK_SIZE)) panic(); } static void check_load(vaddr_t addr, size_t size) { check_access(addr, size); } static void check_store(vaddr_t addr, size_t size) { check_access(addr, size); } static void __noreturn report_load(vaddr_t addr __unused, size_t size __unused) { panic(); } static void __noreturn report_store(vaddr_t addr __unused, size_t size __unused) { panic(); } #define DEFINE_ASAN_FUNC(type, size) \ void __asan_##type##size(vaddr_t addr); \ void __asan_##type##size(vaddr_t addr) \ { check_##type(addr, size); } \ void __asan_##type##size##_noabort(vaddr_t addr); \ void __asan_##type##size##_noabort(vaddr_t addr) \ { check_##type(addr, size); } \ void __asan_report_##type##size##_noabort(vaddr_t addr);\ void __noreturn __asan_report_##type##size##_noabort(vaddr_t addr) \ { report_##type(addr, size); } DEFINE_ASAN_FUNC(load, 1) DEFINE_ASAN_FUNC(load, 2) DEFINE_ASAN_FUNC(load, 4) DEFINE_ASAN_FUNC(load, 8) DEFINE_ASAN_FUNC(load, 16) DEFINE_ASAN_FUNC(store, 1) DEFINE_ASAN_FUNC(store, 2) DEFINE_ASAN_FUNC(store, 4) DEFINE_ASAN_FUNC(store, 8) DEFINE_ASAN_FUNC(store, 16) void __asan_loadN_noabort(vaddr_t addr, size_t size); void __asan_loadN_noabort(vaddr_t addr, size_t size) { check_load(addr, size); } void __asan_storeN_noabort(vaddr_t addr, size_t size); void __asan_storeN_noabort(vaddr_t addr, size_t size) { check_store(addr, size); } void __asan_report_load_n_noabort(vaddr_t addr, size_t size); void __noreturn __asan_report_load_n_noabort(vaddr_t addr, size_t size) { report_load(addr, size); } void __asan_report_store_n_noabort(vaddr_t addr, size_t size); void __noreturn __asan_report_store_n_noabort(vaddr_t addr, size_t size) { report_store(addr, size); } void __asan_handle_no_return(void); void __asan_handle_no_return(void) { } void __asan_register_globals(struct asan_global *globals, size_t size); void __asan_register_globals(struct asan_global *globals, size_t size) { size_t n; for (n = 0; n < size; n++) asan_tag_access((void *)globals[n].beg, (void *)(globals[n].beg + globals[n].size)); } DECLARE_KEEP_INIT(__asan_register_globals); void __asan_unregister_globals(struct asan_global *globals, size_t size); void __asan_unregister_globals(struct asan_global *globals __unused, size_t size __unused) { } optee_os-4.3.0/core/kernel/assert.c000066400000000000000000000011651464416617300172270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include /* assert log and break for the optee kernel */ void __nostackcheck _assert_log(const char *expr __maybe_unused, const char *file __maybe_unused, const int line __maybe_unused, const char *func __maybe_unused) { #if defined(CFG_TEE_CORE_DEBUG) EMSG_RAW("assertion '%s' failed at %s:%d <%s>", expr, file, line, func); #else EMSG_RAW("assertion failed"); #endif } void __noreturn _assert_break(void) { panic(); } optee_os-4.3.0/core/kernel/boot.c000066400000000000000000000102261464416617300166670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2023, Linaro Limited * Copyright (c) 2023, Arm Limited */ #include #include #include #include #ifdef CFG_CORE_DYN_SHM static uint64_t get_dt_val_and_advance(const void *data, size_t *offs, uint32_t cell_size) { uint64_t rv = 0; if (cell_size == 1) { uint32_t v; memcpy(&v, (const uint8_t *)data + *offs, sizeof(v)); *offs += sizeof(v); rv = fdt32_to_cpu(v); } else { uint64_t v; memcpy(&v, (const uint8_t *)data + *offs, sizeof(v)); *offs += sizeof(v); rv = fdt64_to_cpu(v); } return rv; } /* * Find all non-secure memory from DT. Memory marked inaccessible by Secure * World is ignored since it could not be mapped to be used as dynamic shared * memory. */ static int __maybe_unused get_nsec_memory_helper(void *fdt, struct core_mmu_phys_mem *mem) { const uint8_t *prop = NULL; uint64_t a = 0; uint64_t l = 0; size_t prop_offs = 0; size_t prop_len = 0; int elems_total = 0; int addr_size = 0; int len_size = 0; int offs = 0; size_t n = 0; int len = 0; addr_size = fdt_address_cells(fdt, 0); if (addr_size < 0) return 0; len_size = fdt_size_cells(fdt, 0); if (len_size < 0) return 0; while (true) { offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type", "memory", sizeof("memory")); if (offs < 0) break; if (fdt_get_status(fdt, offs) != (DT_STATUS_OK_NSEC | DT_STATUS_OK_SEC)) continue; prop = fdt_getprop(fdt, offs, "reg", &len); if (!prop) continue; prop_len = len; for (n = 0, prop_offs = 0; prop_offs < prop_len; n++) { a = get_dt_val_and_advance(prop, &prop_offs, addr_size); if (prop_offs >= prop_len) { n--; break; } l = get_dt_val_and_advance(prop, &prop_offs, len_size); if (mem) { mem->type = MEM_AREA_DDR_OVERALL; mem->addr = a; mem->size = l; mem++; } } elems_total += n; } return elems_total; } #ifdef CFG_DT static struct core_mmu_phys_mem *get_nsec_memory(void *fdt, size_t *nelems) { struct core_mmu_phys_mem *mem = NULL; int elems_total = 0; elems_total = get_nsec_memory_helper(fdt, NULL); if (elems_total <= 0) return NULL; mem = nex_calloc(elems_total, sizeof(*mem)); if (!mem) panic(); elems_total = get_nsec_memory_helper(fdt, mem); assert(elems_total > 0); *nelems = elems_total; return mem; } #else /*CFG_DT*/ static struct core_mmu_phys_mem *get_nsec_memory(void *fdt __unused, size_t *nelems __unused) { return NULL; } #endif /*!CFG_DT*/ void discover_nsec_memory(void) { struct core_mmu_phys_mem *mem; const struct core_mmu_phys_mem *mem_begin = NULL; const struct core_mmu_phys_mem *mem_end = NULL; size_t nelems; void *fdt = get_external_dt(); if (fdt) { mem = get_nsec_memory(fdt, &nelems); if (mem) { core_mmu_set_discovered_nsec_ddr(mem, nelems); return; } DMSG("No non-secure memory found in FDT"); } mem_begin = phys_ddr_overall_begin; mem_end = phys_ddr_overall_end; nelems = mem_end - mem_begin; if (nelems) { /* * Platform cannot use both register_ddr() and the now * deprecated register_dynamic_shm(). */ assert(phys_ddr_overall_compat_begin == phys_ddr_overall_compat_end); } else { mem_begin = phys_ddr_overall_compat_begin; mem_end = phys_ddr_overall_compat_end; nelems = mem_end - mem_begin; if (!nelems) return; DMSG("Warning register_dynamic_shm() is deprecated, " "please use register_ddr() instead"); } mem = nex_calloc(nelems, sizeof(*mem)); if (!mem) panic(); memcpy(mem, phys_ddr_overall_begin, sizeof(*mem) * nelems); core_mmu_set_discovered_nsec_ddr(mem, nelems); } #else /*CFG_CORE_DYN_SHM*/ void discover_nsec_memory(void) { } #endif /*!CFG_CORE_DYN_SHM*/ #ifdef CFG_CORE_RESERVED_SHM int mark_static_shm_as_reserved(struct dt_descriptor *dt) { vaddr_t shm_start; vaddr_t shm_end; core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &shm_start, &shm_end); if (shm_start != shm_end) return add_res_mem_dt_node(dt, "optee_shm", virt_to_phys((void *)shm_start), shm_end - shm_start); DMSG("No SHM configured"); return -1; } #endif /*CFG_CORE_RESERVED_SHM*/ optee_os-4.3.0/core/kernel/callout.c000066400000000000000000000112401464416617300173640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, Linaro Limited */ #include #include #include #include TAILQ_HEAD(callout_head, callout); static unsigned int callout_sched_lock __nex_data = SPINLOCK_UNLOCK; static size_t callout_sched_core __nex_bss; static unsigned int callout_lock __nex_data = SPINLOCK_UNLOCK; static const struct callout_timer_desc *callout_desc __nex_bss; static struct callout_head callout_head __nex_data = TAILQ_HEAD_INITIALIZER(callout_head); static void insert_callout(struct callout *co) { struct callout *co2 = NULL; TAILQ_FOREACH(co2, &callout_head, link) { if (co->expiry_value < co2->expiry_value) { TAILQ_INSERT_BEFORE(co2, co, link); return; } } TAILQ_INSERT_TAIL(&callout_head, co, link); } static void schedule_next_timeout(void) { const struct callout_timer_desc *desc = callout_desc; struct callout *co = TAILQ_FIRST(&callout_head); if (co) desc->set_next_timeout(desc, co->expiry_value); else desc->disable_timeout(desc); if (desc->is_per_cpu) { /* * Remember which core is supposed to receive the next * timer interrupt. This will not disable timers on other * CPUs, instead they will be ignored as a spurious call. */ cpu_spin_lock(&callout_sched_lock); callout_sched_core = get_core_pos(); cpu_spin_unlock(&callout_sched_lock); } } static bool callout_is_active(struct callout *co) { struct callout *co2 = NULL; TAILQ_FOREACH(co2, &callout_head, link) if (co2 == co) return true; return false; } void callout_rem(struct callout *co) { uint32_t state = 0; state = cpu_spin_lock_xsave(&callout_lock); if (callout_is_active(co)) { TAILQ_REMOVE(&callout_head, co, link); schedule_next_timeout(); } cpu_spin_unlock_xrestore(&callout_lock, state); } void callout_add(struct callout *co, bool (*callback)(struct callout *co), uint32_t ms) { const struct callout_timer_desc *desc = callout_desc; uint32_t state = 0; state = cpu_spin_lock_xsave(&callout_lock); assert(is_nexus(co) && !callout_is_active(co) && is_unpaged(callback)); *co = (struct callout){ .callback = callback, }; if (desc) { co->period = desc->ms_to_ticks(desc, ms); co->expiry_value = desc->get_now(desc) + co->period; } else { /* This will be converted to ticks in callout_service_init(). */ co->period = ms; } insert_callout(co); if (desc && co == TAILQ_FIRST(&callout_head)) schedule_next_timeout(); cpu_spin_unlock_xrestore(&callout_lock, state); } void callout_set_next_timeout(struct callout *co, uint32_t ms) { co->period = callout_desc->ms_to_ticks(callout_desc, ms); } void callout_service_init(const struct callout_timer_desc *desc) { struct callout_head tmp_head = TAILQ_HEAD_INITIALIZER(tmp_head); struct callout *co = NULL; uint32_t state = 0; uint64_t now = 0; state = cpu_spin_lock_xsave(&callout_lock); assert(!callout_desc); assert(is_nexus(desc) && is_unpaged(desc->disable_timeout) && is_unpaged(desc->set_next_timeout) && is_unpaged(desc->ms_to_ticks) && is_unpaged(desc->get_now)); callout_desc = desc; now = desc->get_now(desc); TAILQ_CONCAT(&tmp_head, &callout_head, link); while (!TAILQ_EMPTY(&tmp_head)) { co = TAILQ_FIRST(&tmp_head); TAILQ_REMOVE(&tmp_head, co, link); /* * Periods set before the timer descriptor are in * milliseconds since the frequency of the timer isn't * available at that point. So update it to ticks now. */ co->period = desc->ms_to_ticks(desc, co->period); co->expiry_value = now + co->period; insert_callout(co); } schedule_next_timeout(); cpu_spin_unlock_xrestore(&callout_lock, state); } void callout_service_cb(void) { const struct callout_timer_desc *desc = callout_desc; struct callout *co = NULL; uint64_t now = 0; if (desc->is_per_cpu) { bool do_callout = false; /* * schedule_next_timeout() saves the core it was last * called on. If there's a mismatch here it means that * another core has been scheduled for the next callout, so * there's no work to be done for this core and we can * disable the timeout on this CPU. */ cpu_spin_lock(&callout_sched_lock); do_callout = (get_core_pos() == callout_sched_core); if (!do_callout) desc->disable_timeout(desc); cpu_spin_unlock(&callout_sched_lock); if (!do_callout) return; } cpu_spin_lock(&callout_lock); now = desc->get_now(desc); while (!TAILQ_EMPTY(&callout_head)) { co = TAILQ_FIRST(&callout_head); if (co->expiry_value > now) break; TAILQ_REMOVE(&callout_head, co, link); if (co->callback(co)) { co->expiry_value += co->period; insert_callout(co); } } schedule_next_timeout(); cpu_spin_unlock(&callout_lock); } optee_os-4.3.0/core/kernel/console.c000066400000000000000000000072651464416617300173770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include static struct serial_chip *serial_console __nex_bss; /* May be overridden by platform */ __weak void plat_console_init(void) { } void console_init(void) { if (IS_ENABLED(CFG_SEMIHOSTING_CONSOLE)) semihosting_console_init(CFG_SEMIHOSTING_CONSOLE_FILE); else if (IS_ENABLED(CFG_FFA_CONSOLE)) ffa_console_init(); else plat_console_init(); } void __weak console_putc(int ch) { if (!serial_console) return; if (ch == '\n') serial_console->ops->putc(serial_console, '\r'); serial_console->ops->putc(serial_console, ch); } void __weak console_flush(void) { if (!serial_console || !serial_console->ops->flush) return; serial_console->ops->flush(serial_console); } void register_serial_console(struct serial_chip *chip) { serial_console = chip; } #ifdef CFG_DT static int find_chosen_node(void *fdt) { int offset = 0; if (!fdt) return -1; offset = fdt_path_offset(fdt, "/secure-chosen"); if (offset < 0) offset = fdt_path_offset(fdt, "/chosen"); return offset; } TEE_Result get_console_node_from_dt(void *fdt, int *offs_out, char **path_out, char **params_out) { const struct fdt_property *prop; const char *uart; const char *parms = NULL; int offs; char *stdout_data; char *p; TEE_Result rc = TEE_ERROR_GENERIC; /* Probe console from secure DT and fallback to non-secure DT */ offs = find_chosen_node(fdt); if (offs < 0) { DMSG("No console directive from DTB"); return TEE_ERROR_ITEM_NOT_FOUND; } prop = fdt_get_property(fdt, offs, "stdout-path", NULL); if (!prop) { /* * A secure-chosen or chosen node is present but defined * no stdout-path property: no console expected */ IMSG("Switching off console"); register_serial_console(NULL); return TEE_ERROR_ITEM_NOT_FOUND; } stdout_data = nex_strdup(prop->data); if (!stdout_data) panic(); p = strchr(stdout_data, ':'); if (p) { *p = '\0'; parms = p + 1; } /* stdout-path may refer to an alias */ uart = fdt_get_alias(fdt, stdout_data); if (!uart) { /* Not an alias, assume we have a node path */ uart = stdout_data; } offs = fdt_path_offset(fdt, uart); if (offs >= 0) { if (offs_out) *offs_out = offs; if (params_out) *params_out = parms ? nex_strdup(parms) : NULL; if (path_out) *path_out = uart ? nex_strdup(uart) : NULL; rc = TEE_SUCCESS; } nex_free(stdout_data); return rc; } void configure_console_from_dt(void) { const struct dt_driver *dt_drv; const struct serial_driver *sdrv; struct serial_chip *dev; char *uart = NULL; char *parms = NULL; void *fdt; int offs; fdt = get_dt(); if (IS_ENABLED(CFG_CBMEM_CONSOLE) && cbmem_console_init_from_dt(fdt)) return; if (get_console_node_from_dt(fdt, &offs, &uart, &parms)) return; dt_drv = dt_find_compatible_driver(fdt, offs); if (!dt_drv || dt_drv->type != DT_DRIVER_UART) goto out; sdrv = (const struct serial_driver *)dt_drv->driver; if (!sdrv) goto out; dev = sdrv->dev_alloc(); if (!dev) goto out; /* * If the console is the same as the early console, dev_init() might * clear pending data. Flush to avoid that. */ console_flush(); if (sdrv->dev_init(dev, fdt, offs, parms) < 0) { sdrv->dev_free(dev); goto out; } IMSG("Switching console to device: %s", uart); register_serial_console(dev); out: nex_free(uart); nex_free(parms); } #endif /* CFG_DT */ optee_os-4.3.0/core/kernel/delay.c000066400000000000000000000044121464416617300170220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #ifdef CFG_CORE_HAS_GENERIC_TIMER int timeout_elapsed_us(uint64_t expire) { int64_t diff = delay_cnt_read() - expire; if (MUL_OVERFLOW(diff, 1000000, &diff) || diff < INT_MIN || diff > INT_MAX) { if (timeout_elapsed(expire)) return INT_MAX; else return INT_MIN; } return diff / delay_cnt_freq(); } void udelay(uint32_t us) { uint64_t target = timeout_init_us(us); while (!timeout_elapsed(target)) ; } #else void udelay(uint32_t us) { uint64_t cycles = 0; uint32_t cycles_to_wait = 0; cycles = (uint64_t)us * ((uint64_t)plat_get_freq() / 1000000ULL); while (cycles) { cycles_to_wait = MIN(cycles, UINT32_MAX); wait_cycles(cycles_to_wait); cycles -= cycles_to_wait; } } #endif void mdelay(uint32_t ms) { udelay(1000 * ms); } optee_os-4.3.0/core/kernel/dt.c000066400000000000000000000413651464416617300163430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include static struct dt_descriptor external_dt __nex_bss; #if defined(CFG_CORE_FFA) static void *manifest_dt __nex_bss; #endif const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs) { const struct dt_device_match *dm; const struct dt_driver *drv; for_each_dt_driver(drv) { for (dm = drv->match_table; dm; dm++) { if (!dm->compatible) { break; } if (!fdt_node_check_compatible(fdt, offs, dm->compatible)) { return drv; } } } return NULL; } bool dt_have_prop(const void *fdt, int offs, const char *propname) { const void *prop; prop = fdt_getprop(fdt, offs, propname, NULL); return prop; } int dt_disable_status(void *fdt, int node) { const char *prop = NULL; int len = 0; prop = fdt_getprop(fdt, node, "status", &len); if (!prop) { if (fdt_setprop_string(fdt, node, "status", "disabled")) return -1; } else { /* * Status is there, modify it. * Ask to set "disabled" value to the property. The value * will be automatically truncated with "len" size by the * fdt_setprop_inplace function. * Setting a value different from "ok" or "okay" will disable * the property. * Setting a truncated value of "disabled" with the original * property "len" is preferred to not increase the DT size and * losing time in recalculating the overall DT offsets. * If original length of the status property is larger than * "disabled", the property will start with "disabled" and be * completed with the rest of the original property. */ if (fdt_setprop_inplace(fdt, node, "status", "disabled", len)) return -1; } return 0; } int dt_enable_secure_status(void *fdt, int node) { if (dt_disable_status(fdt, node)) { EMSG("Unable to disable Normal Status"); return -1; } if (fdt_setprop_string(fdt, node, "secure-status", "okay")) return -1; return 0; } int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size, enum dt_map_dev_directive mapping) { enum teecore_memtypes mtype; paddr_t pbase; vaddr_t vbase; size_t sz; int st; assert(cpu_mmu_enabled()); st = fdt_get_status(fdt, offs); if (st == DT_STATUS_DISABLED) return -1; pbase = fdt_reg_base_address(fdt, offs); if (pbase == DT_INFO_INVALID_REG) return -1; sz = fdt_reg_size(fdt, offs); if (sz == DT_INFO_INVALID_REG_SIZE) return -1; switch (mapping) { case DT_MAP_AUTO: if ((st & DT_STATUS_OK_SEC) && !(st & DT_STATUS_OK_NSEC)) mtype = MEM_AREA_IO_SEC; else mtype = MEM_AREA_IO_NSEC; break; case DT_MAP_SECURE: mtype = MEM_AREA_IO_SEC; break; case DT_MAP_NON_SECURE: mtype = MEM_AREA_IO_NSEC; break; default: panic("Invalid mapping specified"); break; } /* Check if we have a mapping, create one if needed */ vbase = (vaddr_t)core_mmu_add_mapping(mtype, pbase, sz); if (!vbase) { EMSG("Failed to map %zu bytes at PA 0x%"PRIxPA, (size_t)sz, pbase); return -1; } *base = vbase; *size = sz; return 0; } /* Read a physical address (n=1 or 2 cells) */ static paddr_t fdt_read_paddr(const uint32_t *cell, int n) { paddr_t addr; if (n < 1 || n > 2) goto bad; addr = fdt32_to_cpu(*cell); cell++; if (n == 2) { #ifdef ARM32 if (addr) { /* High order 32 bits can't be nonzero */ goto bad; } addr = fdt32_to_cpu(*cell); #else addr = (addr << 32) | fdt32_to_cpu(*cell); #endif } return addr; bad: return DT_INFO_INVALID_REG; } paddr_t fdt_reg_base_address(const void *fdt, int offs) { const void *reg; int ncells; int len; int parent; parent = fdt_parent_offset(fdt, offs); if (parent < 0) return DT_INFO_INVALID_REG; reg = fdt_getprop(fdt, offs, "reg", &len); if (!reg) return DT_INFO_INVALID_REG; ncells = fdt_address_cells(fdt, parent); if (ncells < 0) return DT_INFO_INVALID_REG; return fdt_read_paddr(reg, ncells); } static size_t fdt_read_size(const uint32_t *cell, int n) { uint32_t sz = 0; sz = fdt32_to_cpu(*cell); if (n == 2) { if (sz) return DT_INFO_INVALID_REG_SIZE; cell++; sz = fdt32_to_cpu(*cell); } return sz; } size_t fdt_reg_size(const void *fdt, int offs) { const uint32_t *reg; int n; int len; int parent; parent = fdt_parent_offset(fdt, offs); if (parent < 0) return DT_INFO_INVALID_REG_SIZE; reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len); if (!reg) return DT_INFO_INVALID_REG_SIZE; n = fdt_address_cells(fdt, parent); if (n < 1 || n > 2) return DT_INFO_INVALID_REG_SIZE; reg += n; n = fdt_size_cells(fdt, parent); if (n < 1 || n > 2) return DT_INFO_INVALID_REG_SIZE; return fdt_read_size(reg, n); } static bool is_okay(const char *st, int len) { return !strncmp(st, "ok", len) || !strncmp(st, "okay", len); } int fdt_get_status(const void *fdt, int offs) { const char *prop; int st = 0; int len; prop = fdt_getprop(fdt, offs, "status", &len); if (!prop || is_okay(prop, len)) { /* If status is not specified, it defaults to "okay" */ st |= DT_STATUS_OK_NSEC; } prop = fdt_getprop(fdt, offs, "secure-status", &len); if (!prop) { /* * When secure-status is not specified it defaults to the same * value as status */ if (st & DT_STATUS_OK_NSEC) st |= DT_STATUS_OK_SEC; } else { if (is_okay(prop, len)) st |= DT_STATUS_OK_SEC; } return st; } void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, int offs) { struct dt_node_info dinfo = { .reg = DT_INFO_INVALID_REG, .reg_size = DT_INFO_INVALID_REG_SIZE, .clock = DT_INFO_INVALID_CLOCK, .reset = DT_INFO_INVALID_RESET, .interrupt = DT_INFO_INVALID_INTERRUPT, }; const fdt32_t *cuint; dinfo.reg = fdt_reg_base_address(fdt, offs); dinfo.reg_size = fdt_reg_size(fdt, offs); cuint = fdt_getprop(fdt, offs, "clocks", NULL); if (cuint) { cuint++; dinfo.clock = (int)fdt32_to_cpu(*cuint); } cuint = fdt_getprop(fdt, offs, "resets", NULL); if (cuint) { cuint++; dinfo.reset = (int)fdt32_to_cpu(*cuint); } dinfo.interrupt = dt_get_irq_type_prio(fdt, offs, &dinfo.type, &dinfo.prio); dinfo.status = fdt_get_status(fdt, offs); *info = dinfo; } int fdt_read_uint32_array(const void *fdt, int node, const char *prop_name, uint32_t *array, size_t count) { const fdt32_t *cuint = NULL; int len = 0; uint32_t i = 0; cuint = fdt_getprop(fdt, node, prop_name, &len); if (!cuint) return len; if ((uint32_t)len != (count * sizeof(uint32_t))) return -FDT_ERR_BADLAYOUT; for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { *array = fdt32_to_cpu(*cuint); array++; cuint++; } return 0; } int fdt_read_uint32_index(const void *fdt, int node, const char *prop_name, int index, uint32_t *value) { const fdt32_t *cuint = NULL; int len = 0; cuint = fdt_getprop(fdt, node, prop_name, &len); if (!cuint) return len; if ((uint32_t)len < (sizeof(uint32_t) * (index + 1))) return -FDT_ERR_BADLAYOUT; *value = fdt32_to_cpu(cuint[index]); return 0; } int fdt_read_uint32(const void *fdt, int node, const char *prop_name, uint32_t *value) { return fdt_read_uint32_array(fdt, node, prop_name, value, 1); } uint32_t fdt_read_uint32_default(const void *fdt, int node, const char *prop_name, uint32_t dflt_value) { uint32_t ret = dflt_value; fdt_read_uint32_index(fdt, node, prop_name, 0, &ret); return ret; } int fdt_get_reg_props_by_index(const void *fdt, int node, int index, paddr_t *base, size_t *size) { const fdt32_t *prop = NULL; int parent = 0; int len = 0; int address_cells = 0; int size_cells = 0; int cell = 0; parent = fdt_parent_offset(fdt, node); if (parent < 0) return parent; address_cells = fdt_address_cells(fdt, parent); if (address_cells < 0) return address_cells; size_cells = fdt_size_cells(fdt, parent); if (size_cells < 0) return size_cells; cell = index * (address_cells + size_cells); prop = fdt_getprop(fdt, node, "reg", &len); if (!prop) return len; if (((cell + address_cells + size_cells) * (int)sizeof(uint32_t)) > len) return -FDT_ERR_BADVALUE; if (base) { *base = fdt_read_paddr(&prop[cell], address_cells); if (*base == DT_INFO_INVALID_REG) return -FDT_ERR_BADVALUE; } if (size) { *size = fdt_read_size(&prop[cell + address_cells], size_cells); if (*size == DT_INFO_INVALID_REG_SIZE) return -FDT_ERR_BADVALUE; } return 0; } int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name, paddr_t *base, size_t *size) { int index = 0; index = fdt_stringlist_search(fdt, node, "reg-names", name); if (index < 0) return index; return fdt_get_reg_props_by_index(fdt, node, index, base, size); } int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name, uint64_t *num) { const void *prop = NULL; int len = 0; prop = fdt_getprop(fdt, nodeoffset, name, &len); if (!prop) return len; switch (len) { case sizeof(uint32_t): *num = fdt32_ld(prop); return 0; case sizeof(uint64_t): *num = fdt64_ld(prop); return 0; default: return -FDT_ERR_BADVALUE; } } void *get_dt(void) { void *fdt = get_embedded_dt(); if (!fdt) fdt = get_external_dt(); if (!fdt) fdt = get_manifest_dt(); return fdt; } void *get_secure_dt(void) { void *fdt = get_embedded_dt(); if (!fdt && IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) fdt = get_external_dt(); if (!fdt) fdt = get_manifest_dt(); return fdt; } #if defined(CFG_EMBED_DTB) void *get_embedded_dt(void) { static bool checked; assert(cpu_mmu_enabled()); if (!checked) { IMSG("Embedded DTB found"); if (fdt_check_header(embedded_secure_dtb)) panic("Invalid embedded DTB"); checked = true; } return embedded_secure_dtb; } #else void *get_embedded_dt(void) { return NULL; } #endif /*CFG_EMBED_DTB*/ #ifdef _CFG_USE_DTB_OVERLAY static int add_dt_overlay_fragment(struct dt_descriptor *dt, int ioffs) { char frag[32] = { }; int offs = 0; int ret = 0; ret = snprintf(frag, sizeof(frag), "fragment@%d", dt->frag_id); if (ret < 0 || (size_t)ret >= sizeof(frag)) return -1; offs = fdt_add_subnode(dt->blob, ioffs, frag); if (offs < 0) return offs; dt->frag_id += 1; ret = fdt_setprop_string(dt->blob, offs, "target-path", "/"); if (ret < 0) return ret; return fdt_add_subnode(dt->blob, offs, "__overlay__"); } static int init_dt_overlay(struct dt_descriptor *dt, int __maybe_unused dt_size) { int fragment = 0; if (IS_ENABLED(CFG_EXTERNAL_DTB_OVERLAY)) { if (!fdt_check_header(dt->blob)) { fdt_for_each_subnode(fragment, dt->blob, 0) dt->frag_id += 1; return 0; } } return fdt_create_empty_tree(dt->blob, dt_size); } #else static int add_dt_overlay_fragment(struct dt_descriptor *dt __unused, int offs) { return offs; } static int init_dt_overlay(struct dt_descriptor *dt __unused, int dt_size __unused) { return 0; } #endif /* _CFG_USE_DTB_OVERLAY */ struct dt_descriptor *get_external_dt_desc(void) { if (!IS_ENABLED(CFG_EXTERNAL_DT)) return NULL; return &external_dt; } void init_external_dt(unsigned long phys_dt, size_t dt_sz) { struct dt_descriptor *dt = &external_dt; int ret = 0; enum teecore_memtypes mtype = MEM_AREA_MAXTYPE; if (!IS_ENABLED(CFG_EXTERNAL_DT)) return; if (!phys_dt || !dt_sz) { /* * No need to panic as we're not using the DT in OP-TEE * yet, we're only adding some nodes for normal world use. * This makes the switch to using DT easier as we can boot * a newer OP-TEE with older boot loaders. Once we start to * initialize devices based on DT we'll likely panic * instead of returning here. */ IMSG("No non-secure external DT"); return; } mtype = core_mmu_get_type_by_pa(phys_dt); if (mtype == MEM_AREA_MAXTYPE) { /* Map the DTB if it is not yet mapped */ dt->blob = core_mmu_add_mapping(MEM_AREA_EXT_DT, phys_dt, dt_sz); if (!dt->blob) panic("Failed to map external DTB"); } else { /* Get the DTB address if already mapped in a memory area */ dt->blob = phys_to_virt(phys_dt, mtype, dt_sz); if (!dt->blob) { EMSG("Failed to get a mapped external DTB for PA %#lx", phys_dt); panic(); } } ret = init_dt_overlay(dt, dt_sz); if (ret < 0) { EMSG("Device Tree Overlay init fail @ %#lx: error %d", phys_dt, ret); panic(); } ret = fdt_open_into(dt->blob, dt->blob, dt_sz); if (ret < 0) { EMSG("Invalid Device Tree at %#lx: error %d", phys_dt, ret); panic(); } IMSG("Non-secure external DT found"); } void *get_external_dt(void) { if (!IS_ENABLED(CFG_EXTERNAL_DT)) return NULL; assert(cpu_mmu_enabled()); return external_dt.blob; } static TEE_Result release_external_dt(void) { int ret = 0; paddr_t pa_dt = 0; if (!IS_ENABLED(CFG_EXTERNAL_DT)) return TEE_SUCCESS; if (!external_dt.blob) return TEE_SUCCESS; pa_dt = virt_to_phys(external_dt.blob); /* * Skip packing and un-mapping operations if the external DTB is mapped * in a different memory area */ if (core_mmu_get_type_by_pa(pa_dt) != MEM_AREA_EXT_DT) return TEE_SUCCESS; ret = fdt_pack(external_dt.blob); if (ret < 0) { EMSG("Failed to pack Device Tree at 0x%" PRIxPA ": error %d", virt_to_phys(external_dt.blob), ret); panic(); } if (core_mmu_remove_mapping(MEM_AREA_EXT_DT, external_dt.blob, CFG_DTB_MAX_SIZE)) panic("Failed to remove temporary Device Tree mapping"); /* External DTB no more reached, reset pointer to invalid */ external_dt.blob = NULL; return TEE_SUCCESS; } boot_final(release_external_dt); int add_dt_path_subnode(struct dt_descriptor *dt, const char *path, const char *subnode) { int offs = 0; offs = fdt_path_offset(dt->blob, path); if (offs < 0) return offs; offs = add_dt_overlay_fragment(dt, offs); if (offs < 0) return offs; return fdt_add_subnode(dt->blob, offs, subnode); } static void set_dt_val(void *data, uint32_t cell_size, uint64_t val) { if (cell_size == 1) { fdt32_t v = cpu_to_fdt32((uint32_t)val); memcpy(data, &v, sizeof(v)); } else { fdt64_t v = cpu_to_fdt64(val); memcpy(data, &v, sizeof(v)); } } int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name, paddr_t pa, size_t size) { int offs = 0; int ret = 0; int addr_size = -1; int len_size = -1; bool found = true; char subnode_name[80] = { }; offs = fdt_path_offset(dt->blob, "/reserved-memory"); if (offs < 0) { found = false; offs = 0; } if (IS_ENABLED2(_CFG_USE_DTB_OVERLAY)) { len_size = sizeof(paddr_t) / sizeof(uint32_t); addr_size = sizeof(paddr_t) / sizeof(uint32_t); } else { len_size = fdt_size_cells(dt->blob, offs); if (len_size < 0) return len_size; addr_size = fdt_address_cells(dt->blob, offs); if (addr_size < 0) return addr_size; } if (!found) { offs = add_dt_path_subnode(dt, "/", "reserved-memory"); if (offs < 0) return offs; ret = fdt_setprop_cell(dt->blob, offs, "#address-cells", addr_size); if (ret < 0) return ret; ret = fdt_setprop_cell(dt->blob, offs, "#size-cells", len_size); if (ret < 0) return ret; ret = fdt_setprop(dt->blob, offs, "ranges", NULL, 0); if (ret < 0) return ret; } ret = snprintf(subnode_name, sizeof(subnode_name), "%s@%" PRIxPA, name, pa); if (ret < 0 || ret >= (int)sizeof(subnode_name)) DMSG("truncated node \"%s@%" PRIxPA"\"", name, pa); offs = fdt_add_subnode(dt->blob, offs, subnode_name); if (offs >= 0) { uint32_t data[FDT_MAX_NCELLS * 2] = { }; set_dt_val(data, addr_size, pa); set_dt_val(data + addr_size, len_size, size); ret = fdt_setprop(dt->blob, offs, "reg", data, sizeof(uint32_t) * (addr_size + len_size)); if (ret < 0) return ret; ret = fdt_setprop(dt->blob, offs, "no-map", NULL, 0); if (ret < 0) return ret; } else { return offs; } return 0; } #if defined(CFG_CORE_FFA) void init_manifest_dt(void *fdt) { manifest_dt = fdt; } void reinit_manifest_dt(void) { paddr_t pa = (unsigned long)manifest_dt; void *fdt = NULL; int ret = 0; if (!pa) { EMSG("No manifest DT found"); return; } fdt = core_mmu_add_mapping(MEM_AREA_MANIFEST_DT, pa, CFG_DTB_MAX_SIZE); if (!fdt) panic("Failed to map manifest DT"); manifest_dt = fdt; ret = fdt_check_full(fdt, CFG_DTB_MAX_SIZE); if (ret < 0) { EMSG("Invalid manifest Device Tree at %#lx: error %d", pa, ret); panic(); } IMSG("manifest DT found"); } void *get_manifest_dt(void) { return manifest_dt; } static TEE_Result release_manifest_dt(void) { if (!manifest_dt) return TEE_SUCCESS; if (core_mmu_remove_mapping(MEM_AREA_MANIFEST_DT, manifest_dt, CFG_DTB_MAX_SIZE)) panic("Failed to remove temporary manifest DT mapping"); manifest_dt = NULL; return TEE_SUCCESS; } boot_final(release_manifest_dt); #else void init_manifest_dt(void *fdt __unused) { } void reinit_manifest_dt(void) { } void *get_manifest_dt(void) { return NULL; } #endif /*CFG_CORE_FFA*/ optee_os-4.3.0/core/kernel/dt_driver.c000066400000000000000000000551371464416617300177200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Linaro Limited * Copyright (c) 2021, Bootlin * Copyright (c) 2021, Linaro Limited * Copyright (c) 2021, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include #include /* * struct dt_driver_probe - Node instance in secure FDT to probe a driver for * * @link: List hook * @nodeoffset: Node offset of device referenced in the FDT * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. * @deferrals: Driver probe deferrals count * @dt_drv: Matching driver to probe if found or NULL * @dm: Matching reference if applicable or NULL */ struct dt_driver_probe { int nodeoffset; enum dt_driver_type type; unsigned int deferrals; const struct dt_driver *dt_drv; const struct dt_device_match *dm; TAILQ_ENTRY(dt_driver_probe) link; }; /* * struct dt_driver_provider - DT related info on probed device * * Saves information on the probed device so that device * drivers can get resources from DT phandle and related arguments. * * @nodeoffset: Node offset of device referenced in the FDT * @type: One of DT_DRIVER_* or DT_DRIVER_NOTYPE. * @provider_cells: Cells count in the FDT used by the driver's references * @get_of_device: Function to get driver's device ref from phandle data * @priv_data: Driver private data passed as @get_of_device argument * @link: Reference in DT driver providers list */ struct dt_driver_provider { int nodeoffset; enum dt_driver_type type; unsigned int provider_cells; uint32_t phandle; get_of_device_func get_of_device; void *priv_data; SLIST_ENTRY(dt_driver_provider) link; }; /* * Device driver providers are able to provide a driver specific instance * related to device phandle arguments found in the secure embedded FDT. */ static SLIST_HEAD(, dt_driver_provider) dt_driver_provider_list = SLIST_HEAD_INITIALIZER(dt_driver_provider_list); /* FDT nodes for which a matching driver is to be probed */ static TAILQ_HEAD(dt_driver_probe_head, dt_driver_probe) dt_driver_probe_list = TAILQ_HEAD_INITIALIZER(dt_driver_probe_list); /* FDT nodes for which a matching driver has been successfully probed */ static TAILQ_HEAD(, dt_driver_probe) dt_driver_ready_list = TAILQ_HEAD_INITIALIZER(dt_driver_ready_list); /* List of the nodes for which a compatible driver but reported a failure */ static TAILQ_HEAD(, dt_driver_probe) dt_driver_failed_list = TAILQ_HEAD_INITIALIZER(dt_driver_failed_list); /* Flag enabled when a new node (possibly typed) is added in the probe list */ static bool added_node; /* Resolve drivers dependencies on core crypto layer */ static bool tee_crypt_is_ready; void dt_driver_crypt_init_complete(void) { assert(!tee_crypt_is_ready); tee_crypt_is_ready = true; } TEE_Result dt_driver_get_crypto(void) { if (tee_crypt_is_ready) return TEE_SUCCESS; else return TEE_ERROR_DEFER_DRIVER_INIT; } static void assert_type_is_valid(enum dt_driver_type type) { switch (type) { case DT_DRIVER_NOTYPE: case DT_DRIVER_CLK: case DT_DRIVER_RSTCTRL: case DT_DRIVER_UART: case DT_DRIVER_GPIO: case DT_DRIVER_I2C: case DT_DRIVER_PINCTRL: case DT_DRIVER_INTERRUPT: case DT_DRIVER_REGULATOR: case DT_DRIVER_NVMEM: case DT_DRIVER_FIREWALL: return; default: assert(0); } } /* * Driver provider registering API functions */ TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset, get_of_device_func get_of_device, void *priv, enum dt_driver_type type) { struct dt_driver_provider *prv = NULL; int provider_cells = 0; uint32_t phandle = 0; assert_type_is_valid(type); provider_cells = fdt_get_dt_driver_cells(fdt, nodeoffset, type); if (provider_cells < 0) { DMSG("Failed to find provider cells: %d", provider_cells); return TEE_ERROR_GENERIC; } phandle = fdt_get_phandle(fdt, nodeoffset); if (phandle == (uint32_t)-1) { DMSG("Failed to find provide phandle"); return TEE_ERROR_GENERIC; } prv = calloc(1, sizeof(*prv)); if (!prv) return TEE_ERROR_OUT_OF_MEMORY; prv->nodeoffset = nodeoffset; prv->type = type; prv->provider_cells = provider_cells; prv->phandle = phandle; prv->get_of_device = get_of_device; prv->priv_data = priv; SLIST_INSERT_HEAD(&dt_driver_provider_list, prv, link); return TEE_SUCCESS; } static bool dt_driver_use_parent_controller(enum dt_driver_type type) { switch (type) { case DT_DRIVER_PINCTRL: case DT_DRIVER_NVMEM: return true; default: return false; } } /* * Helper functions for dt_drivers querying driver provider information */ int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset, enum dt_driver_type type) { const char *cells_name = NULL; const fdt32_t *c = NULL; int len = 0; if (dt_driver_use_parent_controller(type)) return 0; switch (type) { case DT_DRIVER_CLK: cells_name = "#clock-cells"; break; case DT_DRIVER_INTERRUPT: cells_name = "#interrupt-cells"; break; case DT_DRIVER_RSTCTRL: cells_name = "#reset-cells"; break; case DT_DRIVER_GPIO: cells_name = "#gpio-cells"; break; case DT_DRIVER_FIREWALL: cells_name = "#access-controller-cells"; break; case DT_DRIVER_I2C: case DT_DRIVER_REGULATOR: return 0; default: panic(); } c = fdt_getprop(fdt, nodeoffset, cells_name, &len); if (!c) return len; if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; return fdt32_to_cpu(*c); } unsigned int dt_driver_provider_cells(struct dt_driver_provider *prv) { return prv->provider_cells; } void *dt_driver_provider_priv_data(struct dt_driver_provider *prv) { return prv->priv_data; } struct dt_driver_provider * dt_driver_get_provider_by_node(int nodeoffset, enum dt_driver_type type) { struct dt_driver_provider *prv = NULL; SLIST_FOREACH(prv, &dt_driver_provider_list, link) if (prv->nodeoffset == nodeoffset && prv->type == type) return prv; return NULL; } struct dt_driver_provider * dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type) { struct dt_driver_provider *prv = NULL; SLIST_FOREACH(prv, &dt_driver_provider_list, link) if (prv->phandle == phandle && prv->type == type) return prv; return NULL; } static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv, const void *fdt, int phandle_node, const uint32_t *prop, void *device_ref) { TEE_Result res = TEE_ERROR_GENERIC; struct dt_pargs *pargs = NULL; unsigned int n = 0; pargs = calloc(1, prv->provider_cells * sizeof(uint32_t *) + sizeof(*pargs)); if (!pargs) return TEE_ERROR_OUT_OF_MEMORY; pargs->fdt = fdt; pargs->phandle_node = phandle_node; pargs->args_count = prv->provider_cells; for (n = 0; n < prv->provider_cells; n++) { assert(prop); pargs->args[n] = fdt32_to_cpu(prop[n]); } res = prv->get_of_device(pargs, prv->priv_data, device_ref); free(pargs); return res; } TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset, enum dt_driver_type type, void *device_ref) { int parent = -1; struct dt_driver_provider *prv = NULL; assert(fdt == get_secure_dt()); parent = fdt_parent_offset(fdt, nodeoffset); if (parent < 0) return TEE_ERROR_GENERIC; prv = dt_driver_get_provider_by_node(parent, type); if (!prv) { /* No provider registered yet */ return TEE_ERROR_DEFER_DRIVER_INIT; } return device_from_provider_prop(prv, fdt, nodeoffset, NULL, device_ref); } TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name, const void *fdt, int nodeoffs, unsigned int prop_index, enum dt_driver_type type, uint32_t phandle, void *device_ref) { int len = 0; const uint32_t *prop = NULL; int phandle_node_unused = -1; struct dt_driver_provider *prv = NULL; prop = fdt_getprop(fdt, nodeoffs, prop_name, &len); if (!prop) { if (len != -FDT_ERR_NOTFOUND) { DMSG("Corrupted node %s", prop_name); return TEE_ERROR_GENERIC; } else { DMSG("Property %s missing in node %s", prop_name, fdt_get_name(fdt, nodeoffs, NULL)); return TEE_ERROR_ITEM_NOT_FOUND; } } prv = dt_driver_get_provider_by_phandle(phandle, type); if (!prv) return TEE_ERROR_DEFER_DRIVER_INIT; prop_index *= dt_driver_provider_cells(prv); if ((prop_index + 1) * sizeof(*prop) > (size_t)len) return TEE_ERROR_ITEM_NOT_FOUND; return device_from_provider_prop(prv, fdt, phandle_node_unused, prop + prop_index, device_ref); } TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name, const void *fdt, int nodeoffset, unsigned int prop_idx, enum dt_driver_type type, void *device_ref) { int len = 0; int idx = 0; int idx32 = 0; int prv_cells = 0; int phandle_node = -1; uint32_t phandle = 0; const uint32_t *prop = NULL; struct dt_driver_provider *prv = NULL; prop = fdt_getprop(fdt, nodeoffset, prop_name, &len); if (!prop) { DMSG("Property %s missing in node %s", prop_name, fdt_get_name(fdt, nodeoffset, NULL)); return TEE_ERROR_ITEM_NOT_FOUND; } while (idx < len) { idx32 = idx / sizeof(uint32_t); phandle = fdt32_to_cpu(prop[idx32]); if (!phandle) { if (!prop_idx) break; idx += sizeof(phandle); prop_idx--; continue; } /* * In some cases, pinctrl, i2c, nvmem, etc, the consumer phandle * points directly to a subnode of the parent. In such cases, * the provider does not have any "-cells" property and * potentially no "phandle" property. */ if (dt_driver_use_parent_controller(type)) { phandle_node = fdt_node_offset_by_phandle(fdt, phandle); if (phandle_node < 0) return TEE_ERROR_GENERIC; nodeoffset = fdt_parent_offset(fdt, phandle_node); if (nodeoffset < 0) return TEE_ERROR_GENERIC; prv = dt_driver_get_provider_by_node(nodeoffset, type); } else { prv = dt_driver_get_provider_by_phandle(phandle, type); } if (prv) { prv_cells = dt_driver_provider_cells(prv); } else if (prop_idx) { /* * When we need to skip another provider phandle * arguments cells (aka when prop_idx != 0), we don't * really need the skipped provider to be already * registered, we can look straight in its DT node. */ phandle_node = fdt_node_offset_by_phandle(fdt, phandle); if (phandle_node < 0) { DMSG("Can't find node for phandle %"PRIu32, phandle); return TEE_ERROR_GENERIC; } prv_cells = fdt_get_dt_driver_cells(fdt, phandle_node, type); if (prv_cells < 0) { DMSG("Can't find cells count on node %s: %d", fdt_get_name(fdt, phandle_node, NULL), prv_cells); return TEE_ERROR_GENERIC; } } if (prop_idx) { prop_idx--; idx += sizeof(phandle) + prv_cells * sizeof(uint32_t); continue; } if (!prv) return TEE_ERROR_DEFER_DRIVER_INIT; /* Skip property cell with the phandle, already handled */ idx32++; return device_from_provider_prop(prv, fdt, phandle_node, prop + idx32, device_ref); } return TEE_ERROR_ITEM_NOT_FOUND; } static void __maybe_unused print_probe_list(const void *fdt __maybe_unused) { struct dt_driver_probe *elt = NULL; unsigned int count = 0; TAILQ_FOREACH(elt, &dt_driver_probe_list, link) count++; DMSG("Probe list: %u elements", count); TAILQ_FOREACH(elt, &dt_driver_probe_list, link) DMSG("|- Driver %s probes on node %s", elt->dt_drv->name, fdt_get_name(fdt, elt->nodeoffset, NULL)); DMSG("`- Probe list end"); count = 0; TAILQ_FOREACH(elt, &dt_driver_failed_list, link) count++; DMSG("Failed list: %u elements", count); TAILQ_FOREACH(elt, &dt_driver_failed_list, link) EMSG("|- Driver %s on node %s failed", elt->dt_drv->name, fdt_get_name(fdt, elt->nodeoffset, NULL)); DMSG("`- Failed list end"); } /* * Probe element: push to ready list if succeeds, push to probe list if probe * if deferred, panic with an error trace otherwise. */ static TEE_Result probe_driver_node(const void *fdt, struct dt_driver_probe *elt) { TEE_Result res = TEE_ERROR_GENERIC; const char __maybe_unused *drv_name = NULL; const char __maybe_unused *node_name = NULL; node_name = fdt_get_name(fdt, elt->nodeoffset, NULL); drv_name = elt->dt_drv->name; if (!elt->dt_drv->probe) { DMSG("No probe operator for driver %s, skipped", drv_name); return TEE_SUCCESS; } FMSG("Probing %s on node %s", drv_name, node_name); res = elt->dt_drv->probe(fdt, elt->nodeoffset, elt->dm->compat_data); switch (res) { case TEE_SUCCESS: TAILQ_INSERT_HEAD(&dt_driver_ready_list, elt, link); DMSG("element: %s on node %s initialized", drv_name, node_name); break; case TEE_ERROR_DEFER_DRIVER_INIT: elt->deferrals++; TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); DMSG("element: %s on node %s deferred %u time(s)", drv_name, node_name, elt->deferrals); break; case TEE_ERROR_NODE_DISABLED: DMSG("element: %s on node %s is disabled", drv_name, node_name); break; default: TAILQ_INSERT_HEAD(&dt_driver_failed_list, elt, link); EMSG("Failed to probe %s on node %s: %#"PRIx32, drv_name, node_name, res); break; } return res; } static TEE_Result alloc_elt_and_probe(const void *fdt, int node, const struct dt_driver *dt_drv, const struct dt_device_match *dm) { struct dt_driver_probe *elt = NULL; /* Will be freed when lists are released */ elt = calloc(1, sizeof(*elt)); if (!elt) return TEE_ERROR_OUT_OF_MEMORY; elt->nodeoffset = node; elt->dt_drv = dt_drv; elt->dm = dm; elt->type = dt_drv->type; return probe_driver_node(fdt, elt); } /* Lookup a compatible driver, possibly of a specific @type, for the FDT node */ static TEE_Result probe_device_by_compat(const void *fdt, int node, const char *compat, enum dt_driver_type type) { const struct dt_driver *drv = NULL; const struct dt_device_match *dm = NULL; for_each_dt_driver(drv) { if (drv->type != type) continue; for (dm = drv->match_table; dm && dm->compatible; dm++) if (strcmp(dm->compatible, compat) == 0) return alloc_elt_and_probe(fdt, node, drv, dm); } return TEE_ERROR_ITEM_NOT_FOUND; } /* * Lookup the best matching compatible driver, possibly of a specific @type, * for the FDT node. */ TEE_Result dt_driver_probe_device_by_node(const void *fdt, int nodeoffset, enum dt_driver_type type) { int idx = 0; int len = 0; int count = 0; const char *compat = NULL; TEE_Result res = TEE_ERROR_GENERIC; assert_type_is_valid(type); count = fdt_stringlist_count(fdt, nodeoffset, "compatible"); if (count < 0) return TEE_ERROR_ITEM_NOT_FOUND; for (idx = 0; idx < count; idx++) { compat = fdt_stringlist_get(fdt, nodeoffset, "compatible", idx, &len); if (!compat) return TEE_ERROR_GENERIC; res = probe_device_by_compat(fdt, nodeoffset, compat, type); if (res != TEE_ERROR_ITEM_NOT_FOUND) return res; } return TEE_ERROR_ITEM_NOT_FOUND; } static TEE_Result process_probe_list(const void *fdt) { struct dt_driver_probe *elt = NULL; struct dt_driver_probe *prev = NULL; static unsigned int __maybe_unused loop_count; static unsigned int __maybe_unused deferral_loop_count; bool __maybe_unused one_deferred = false; bool one_probed_ok = false; do { loop_count++; FMSG("Probe loop %u after %u for deferral(s)", loop_count, deferral_loop_count); /* Hack here for TRACE_DEBUG messages on probe list elements */ if (TRACE_LEVEL >= TRACE_FLOW) print_probe_list(fdt); if (TAILQ_EMPTY(&dt_driver_probe_list)) return TEE_SUCCESS; /* * Probe from current end to top. Deferred probed node are * pushed back after current tail for the next probe round. * Reset probe result flags and see status after probe round. */ one_deferred = false; one_probed_ok = false; added_node = false; TAILQ_FOREACH_REVERSE_SAFE(elt, &dt_driver_probe_list, dt_driver_probe_head, link, prev) { TAILQ_REMOVE(&dt_driver_probe_list, elt, link); switch (probe_driver_node(fdt, elt)) { case TEE_SUCCESS: one_probed_ok = true; break; case TEE_ERROR_DEFER_DRIVER_INIT: one_deferred = true; break; default: break; } } if (one_deferred) deferral_loop_count++; } while (added_node || one_probed_ok); DMSG("Unresolved dependencies after %u rounds, %u deferred", loop_count, deferral_loop_count); if (one_deferred) return TEE_ERROR_DEFER_DRIVER_INIT; else return TEE_ERROR_GENERIC; } static int driver_probe_compare(struct dt_driver_probe *candidate, struct dt_driver_probe *elt) { if (candidate->nodeoffset != elt->nodeoffset || candidate->type != elt->type) return 1; assert(elt->dt_drv == candidate->dt_drv); return 0; } /* * Return TEE_SUCCESS if compatible found * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted */ static TEE_Result add_node_to_probe(const void *fdt, int node, const struct dt_driver *dt_drv, const struct dt_device_match *dm) { const char __maybe_unused *node_name = fdt_get_name(fdt, node, NULL); const char __maybe_unused *drv_name = dt_drv->name; struct dt_driver_probe *elt = NULL; struct dt_driver_probe elt_new = { .dm = dm, .dt_drv = dt_drv, .nodeoffset = node, .type = dt_drv->type, }; /* If node/type found in probe list or ready list, nothing to do */ TAILQ_FOREACH(elt, &dt_driver_probe_list, link) if (!driver_probe_compare(&elt_new, elt)) return TEE_SUCCESS; TAILQ_FOREACH(elt, &dt_driver_ready_list, link) if (!driver_probe_compare(&elt_new, elt)) return TEE_SUCCESS; elt = malloc(sizeof(*elt)); if (!elt) return TEE_ERROR_OUT_OF_MEMORY; DMSG("element: %s on node %s", drv_name, node_name); memcpy(elt, &elt_new, sizeof(*elt)); added_node = true; TAILQ_INSERT_TAIL(&dt_driver_probe_list, elt, link); /* Hack here for TRACE_DEBUG messages on current probe list elements */ if (TRACE_LEVEL >= TRACE_FLOW) print_probe_list(fdt); return TEE_SUCCESS; } /* * Add a node to the probe list if a dt_driver matches target compatible. * * If @type is DT_DRIVER_ANY, probe list can hold only 1 driver to probe for * the node. A node may probe several drivers if have a unique driver type. * * Return TEE_SUCCESS if compatible found * TEE_ERROR_ITEM_NOT_FOUND if no matching driver * TEE_ERROR_OUT_OF_MEMORY if heap is exhausted */ static TEE_Result add_probe_node_by_compat(const void *fdt, int node, const char *compat) { TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; const struct dt_driver *dt_drv = NULL; const struct dt_device_match *dm = NULL; uint32_t found_types = 0; for_each_dt_driver(dt_drv) { for (dm = dt_drv->match_table; dm && dm->compatible; dm++) { if (strcmp(dm->compatible, compat) == 0) { assert(dt_drv->type < 32); res = add_node_to_probe(fdt, node, dt_drv, dm); if (res) return res; if (found_types & BIT(dt_drv->type)) { EMSG("Driver %s multi hit on type %u", dt_drv->name, dt_drv->type); panic(); } found_types |= BIT(dt_drv->type); /* Matching found for this driver, try next */ break; } } } return res; } /* * Add the node to the probe list if matching compatible drivers are found. * Follow node's compatible property list ordering to find matching driver. */ TEE_Result dt_driver_maybe_add_probe_node(const void *fdt, int node) { int idx = 0; int len = 0; int count = 0; const char *compat = NULL; TEE_Result res = TEE_ERROR_GENERIC; if (fdt_get_status(fdt, node) == DT_STATUS_DISABLED) return TEE_SUCCESS; count = fdt_stringlist_count(fdt, node, "compatible"); if (count < 0) return TEE_SUCCESS; for (idx = 0; idx < count; idx++) { compat = fdt_stringlist_get(fdt, node, "compatible", idx, &len); assert(compat && len > 0); res = add_probe_node_by_compat(fdt, node, compat); /* Stop lookup if something was found */ if (res != TEE_ERROR_ITEM_NOT_FOUND) return res; } return TEE_SUCCESS; } static void parse_node(const void *fdt, int node) { TEE_Result __maybe_unused res = TEE_ERROR_GENERIC; int subnode = 0; fdt_for_each_subnode(subnode, fdt, node) { res = dt_driver_maybe_add_probe_node(fdt, subnode); if (res) { EMSG("Failed on node %s with %#"PRIx32, fdt_get_name(fdt, subnode, NULL), res); panic(); } /* * Rescursively parse the FDT, skipping disabled nodes. * FDT is expected reliable and core shall have sufficient * stack depth to possibly parse all DT nodes. */ if (IS_ENABLED(CFG_DRIVERS_DT_RECURSIVE_PROBE)) { if (fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED) continue; parse_node(fdt, subnode); } } } /* * Parse FDT for nodes and save in probe list the node for which a dt_driver * matches node's compatible property. */ static TEE_Result probe_dt_drivers_early(void) { TEE_Result res = TEE_ERROR_GENERIC; const void *fdt = NULL; fdt = get_secure_dt(); if (!fdt) return TEE_SUCCESS; parse_node(fdt, fdt_path_offset(fdt, "/")); res = process_probe_list(fdt); if (res == TEE_ERROR_DEFER_DRIVER_INIT) { DMSG("Deferred drivers probing"); print_probe_list(fdt); res = TEE_SUCCESS; } return res; } static TEE_Result probe_dt_drivers(void) { TEE_Result res = TEE_ERROR_GENERIC; const void *fdt = NULL; fdt = get_secure_dt(); if (!fdt) return TEE_SUCCESS; res = process_probe_list(fdt); if (res || !TAILQ_EMPTY(&dt_driver_failed_list)) { EMSG("Probe sequence result: %#"PRIx32, res); print_probe_list(fdt); panic(); } return TEE_SUCCESS; } early_init_late(probe_dt_drivers_early); driver_init(probe_dt_drivers); static TEE_Result release_probe_lists(void) { struct dt_driver_probe *elt = NULL; struct dt_driver_probe *next = NULL; struct dt_driver_provider *prov = NULL; struct dt_driver_provider *next_prov = NULL; const void *fdt = NULL; fdt = get_secure_dt(); if (!fdt) return TEE_SUCCESS; assert(fdt && TAILQ_EMPTY(&dt_driver_probe_list)); TAILQ_FOREACH_SAFE(elt, &dt_driver_ready_list, link, next) free(elt); TAILQ_FOREACH_SAFE(elt, &dt_driver_failed_list, link, next) free(elt); SLIST_FOREACH_SAFE(prov, &dt_driver_provider_list, link, next_prov) free(prov); return TEE_SUCCESS; } release_init_resource(release_probe_lists); /* * Simple bus support: handy to parse subnodes */ static TEE_Result simple_bus_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; int subnode = 0; fdt_for_each_subnode(subnode, fdt, node) { res = dt_driver_maybe_add_probe_node(fdt, subnode); if (res) { EMSG("Failed on node %s with %#"PRIx32, fdt_get_name(fdt, subnode, NULL), res); panic(); } } return TEE_SUCCESS; } static const struct dt_device_match simple_bus_match_table[] = { { .compatible = "simple-bus" }, { } }; DEFINE_DT_DRIVER(simple_bus_dt_driver) = { .name = "simple-bus", .match_table = simple_bus_match_table, .probe = simple_bus_probe, }; optee_os-4.3.0/core/kernel/early_ta.c000066400000000000000000000025141464416617300175250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #include #include #include #include #include #include #include #include #include #include #include static const struct embedded_ts *find_early_ta(const TEE_UUID *uuid) { const struct embedded_ts *ta = NULL; for_each_early_ta(ta) if (!memcmp(&ta->uuid, uuid, sizeof(*uuid))) return ta; return NULL; } static TEE_Result early_ta_open(const TEE_UUID *uuid, struct ts_store_handle **h) { return emb_ts_open(uuid, h, find_early_ta); } REGISTER_TA_STORE(2) = { .description = "early TA", .open = early_ta_open, .get_size = emb_ts_get_size, .get_tag = emb_ts_get_tag, .read = emb_ts_read, .close = emb_ts_close, }; static TEE_Result early_ta_init(void) { const struct embedded_ts *ta = NULL; char __maybe_unused msg[60] = { '\0', }; for_each_early_ta(ta) { if (ta->uncompressed_size) snprintf(msg, sizeof(msg), " (compressed, uncompressed %u)", ta->uncompressed_size); else msg[0] = '\0'; DMSG("Early TA %pUl size %u%s", (void *)&ta->uuid, ta->size, msg); } return TEE_SUCCESS; } service_init(early_ta_init); optee_os-4.3.0/core/kernel/embedded_ts.c000066400000000000000000000116771464416617300201760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited * Copyright (c) 2020, Arm Limited. */ #include #include #include #include #include #include #include #include #include #include #include #include #include struct ts_store_handle { const struct embedded_ts *ts; size_t offs; z_stream strm; }; static void *zalloc(void *opaque __unused, unsigned int items, unsigned int size) { return mempool_alloc(mempool_default, items * size); } static void zfree(void *opaque __unused, void *address) { mempool_free(mempool_default, address); } static bool decompression_init(z_stream *strm, const struct embedded_ts *ts) { int st = Z_OK; strm->next_in = ts->ts; strm->avail_in = ts->size; strm->zalloc = zalloc; strm->zfree = zfree; st = inflateInit(strm); if (st != Z_OK) { EMSG("Decompression initialization error (%d)", st); return false; } return true; } TEE_Result emb_ts_open(const TEE_UUID *uuid, struct ts_store_handle **h, const struct embedded_ts* (*find_ts) (const TEE_UUID *uuid)) { struct ts_store_handle *handle = NULL; const struct embedded_ts *ts = NULL; ts = find_ts(uuid); if (!ts) return TEE_ERROR_ITEM_NOT_FOUND; handle = calloc(1, sizeof(*handle)); if (!handle) return TEE_ERROR_OUT_OF_MEMORY; if (ts->uncompressed_size) { if (!decompression_init(&handle->strm, ts)) { free(handle); return TEE_ERROR_BAD_FORMAT; } } handle->ts = ts; *h = handle; return TEE_SUCCESS; } TEE_Result emb_ts_get_size(const struct ts_store_handle *h, size_t *size) { const struct embedded_ts *ts = h->ts; if (ts->uncompressed_size) *size = ts->uncompressed_size; else *size = ts->size; return TEE_SUCCESS; } TEE_Result emb_ts_get_tag(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len) { TEE_Result res = TEE_SUCCESS; void *ctx = NULL; if (!tag || *tag_len < TEE_SHA256_HASH_SIZE) { *tag_len = TEE_SHA256_HASH_SIZE; return TEE_ERROR_SHORT_BUFFER; } *tag_len = TEE_SHA256_HASH_SIZE; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); if (res) return res; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, h->ts->ts, h->ts->size); if (res) goto out; res = crypto_hash_final(ctx, tag, *tag_len); out: crypto_hash_free_ctx(ctx); return res; } static TEE_Result read_uncompressed(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) { TEE_Result res = TEE_SUCCESS; uint8_t *src = (uint8_t *)h->ts->ts + h->offs; size_t next_offs = 0; if (ADD_OVERFLOW(h->offs, len, &next_offs) || next_offs > h->ts->size) return TEE_ERROR_BAD_PARAMETERS; if (data_core) memcpy(data_core, src, len); if (data_user) res = copy_to_user(data_user, src, len); if (!res) h->offs = next_offs; return res; } static TEE_Result read_compressed(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) { TEE_Result res = TEE_SUCCESS; z_stream *strm = &h->strm; size_t total = 0; uint8_t *bb = NULL; size_t bb_len = 0; size_t out = 0; int st = Z_OK; /* Inflate into a 1kB bounce buffer */ bb_len = MIN(len, 1024U); bb = bb_alloc(bb_len); if (!bb) { EMSG("Out of memory"); return TEE_ERROR_OUT_OF_MEMORY; } strm->avail_out = bb_len; strm->next_out = bb; /* * Loop until we get as many bytes as requested, or an error occurs. * inflate() returns: * - Z_OK when progress was made, but neither the end of the input * stream nor the end of the output buffer were met. * - Z_STREAM_END when the end of the intput stream was reached. * - Z_BUF_ERROR when there is still input to process but the output * buffer is full (not a "hard" error, decompression can proceeed * later). */ do { out = strm->total_out; st = inflate(strm, Z_SYNC_FLUSH); out = strm->total_out - out; FMSG("%zu bytes", out); if (data_core) memcpy((uint8_t *)data_core + total, bb, out); if (data_user) { res = copy_to_user((uint8_t *)data_user + total, bb, out); if (res) goto out; } total += out; /* * Reset the pointer since we've just copied out the last * data. */ strm->next_out = bb; strm->avail_out = MIN(len - total, bb_len); } while ((st == Z_OK || st == Z_BUF_ERROR) && (total != len)); if (st != Z_OK && st != Z_STREAM_END) { EMSG("Decompression error (%d)", st); res = TEE_ERROR_GENERIC; goto out; } res = TEE_SUCCESS; out: bb_free(bb, bb_len); return res; } TEE_Result emb_ts_read(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) { if (h->ts->uncompressed_size) return read_compressed(h, data_core, data_user, len); else return read_uncompressed(h, data_core, data_user, len); } void emb_ts_close(struct ts_store_handle *h) { if (h->ts->uncompressed_size) inflateEnd(&h->strm); free(h); } optee_os-4.3.0/core/kernel/handle.c000066400000000000000000000040271464416617300171610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include /* * Define the initial capacity of the database. It should be a low number * multiple of 2 since some databases a likely to only use a few handles. * Since the algorithm is to doubles up when growing it shouldn't cause a * noticable overhead on large databases. */ #define HANDLE_DB_INITIAL_MAX_PTRS 4 void handle_db_destroy(struct handle_db *db, void (*ptr_destructor)(void *ptr)) { if (db) { if (ptr_destructor) { size_t n = 0; for (n = 0; n < db->max_ptrs; n++) if (db->ptrs[n]) ptr_destructor(db->ptrs[n]); } free(db->ptrs); db->ptrs = NULL; db->max_ptrs = 0; } } bool handle_db_is_empty(struct handle_db *db) { size_t n = 0; if (db) { for (n = 0; n < db->max_ptrs; n++) { if (db->ptrs[n]) return false; } } return true; } int handle_get(struct handle_db *db, void *ptr) { size_t n; void *p; size_t new_max_ptrs; if (!db || !ptr) return -1; /* Try to find an empty location */ for (n = 0; n < db->max_ptrs; n++) { if (!db->ptrs[n]) { db->ptrs[n] = ptr; return n; } } /* No location available, grow the ptrs array */ if (db->max_ptrs) new_max_ptrs = db->max_ptrs * 2; else new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; p = realloc(db->ptrs, new_max_ptrs * sizeof(void *)); if (!p) return -1; db->ptrs = p; memset(db->ptrs + db->max_ptrs, 0, (new_max_ptrs - db->max_ptrs) * sizeof(void *)); db->max_ptrs = new_max_ptrs; /* Since n stopped at db->max_ptrs there is an empty location there */ db->ptrs[n] = ptr; return n; } void *handle_put(struct handle_db *db, int handle) { void *p; if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) return NULL; p = db->ptrs[handle]; db->ptrs[handle] = NULL; return p; } void *handle_lookup(struct handle_db *db, int handle) { if (!db || handle < 0 || (size_t)handle >= db->max_ptrs) return NULL; return db->ptrs[handle]; } optee_os-4.3.0/core/kernel/huk_subkey.c000066400000000000000000000052371464416617300201030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include static TEE_Result mac_usage(void *ctx, uint32_t usage) { return crypto_mac_update(ctx, (const void *)&usage, sizeof(usage)); } #ifdef CFG_CORE_HUK_SUBKEY_COMPAT static TEE_Result get_otp_die_id(uint8_t *buffer, size_t len) { static const char pattern[4] = { 'B', 'E', 'E', 'F' }; size_t i; if (IS_ENABLED(CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID)) return tee_otp_get_die_id(buffer, len); for (i = 0; i < len; i++) buffer[i] = pattern[i % 4]; return TEE_SUCCESS; } /* * This does special treatment for RPMB and SSK key derivations to give * the same result as when huk_subkey_derive() wasn't used. */ static TEE_Result huk_compat(void *ctx, enum huk_subkey_usage usage) { TEE_Result res = TEE_SUCCESS; uint8_t chip_id[TEE_FS_KM_CHIP_ID_LENGTH] = { 0 }; static uint8_t ssk_str[] = "ONLY_FOR_tee_fs_ssk"; switch (usage) { case HUK_SUBKEY_RPMB: return TEE_SUCCESS; case HUK_SUBKEY_SSK: res = get_otp_die_id(chip_id, sizeof(chip_id)); if (res) return res; res = crypto_mac_update(ctx, chip_id, sizeof(chip_id)); if (res) return res; return crypto_mac_update(ctx, ssk_str, sizeof(ssk_str)); default: return mac_usage(ctx, usage); } } #endif /*CFG_CORE_HUK_SUBKEY_COMPAT*/ TEE_Result __huk_subkey_derive(enum huk_subkey_usage usage, const void *const_data, size_t const_data_len, uint8_t *subkey, size_t subkey_len) { void *ctx = NULL; struct tee_hw_unique_key huk = { }; TEE_Result res = TEE_SUCCESS; if (subkey_len > HUK_SUBKEY_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; if (!const_data && const_data_len) return TEE_ERROR_BAD_PARAMETERS; res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); if (res) return res; res = tee_otp_get_hw_unique_key(&huk); if (res) goto out; res = crypto_mac_init(ctx, huk.data, sizeof(huk.data)); if (res) goto out; #ifdef CFG_CORE_HUK_SUBKEY_COMPAT res = huk_compat(ctx, usage); #else res = mac_usage(ctx, usage); #endif if (res) goto out; if (const_data) { res = crypto_mac_update(ctx, const_data, const_data_len); if (res) goto out; } res = crypto_mac_final(ctx, subkey, subkey_len); out: if (res) memzero_explicit(subkey, subkey_len); memzero_explicit(&huk, sizeof(huk)); crypto_mac_free_ctx(ctx); return res; } TEE_Result huk_subkey_derive(enum huk_subkey_usage usage, const void *const_data, size_t const_data_len, uint8_t *subkey, size_t subkey_len) __weak __alias("__huk_subkey_derive"); optee_os-4.3.0/core/kernel/initcall.c000066400000000000000000000032131464416617300175210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include /* * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ void __weak call_preinitcalls(void) { const struct initcall *call = NULL; TEE_Result ret = TEE_SUCCESS; for (call = preinitcall_begin; call < preinitcall_end; call++) { DMSG("level %d %s()", call->level, call->func_name); ret = call->func(); if (ret != TEE_SUCCESS) { EMSG("Preinitcall __text_start + 0x%08" PRIxVA " failed", (vaddr_t)call - VCORE_START_VA); } } } /* * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ void __weak call_initcalls(void) { const struct initcall *call = NULL; TEE_Result ret = TEE_SUCCESS; for (call = initcall_begin; call < initcall_end; call++) { DMSG("level %d %s()", call->level, call->func_name); ret = call->func(); if (ret != TEE_SUCCESS) { EMSG("Initcall __text_start + 0x%08" PRIxVA " failed", (vaddr_t)call - VCORE_START_VA); } } } /* * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ void __weak call_finalcalls(void) { const struct initcall *call = NULL; TEE_Result ret = TEE_SUCCESS; for (call = finalcall_begin; call < finalcall_end; call++) { DMSG("level %d %s()", call->level, call->func_name); ret = call->func(); if (ret != TEE_SUCCESS) { EMSG("Finalcall __text_start + 0x%08" PRIxVA " failed", (vaddr_t)call - VCORE_START_VA); } } } optee_os-4.3.0/core/kernel/interrupt.c000066400000000000000000000176771464416617300200010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2019, Linaro Limited */ #include #include #include #include #include #include #include #include /* * NOTE! * * We're assuming that there's no concurrent use of this interface, except * delivery of interrupts in parallel. Synchronization will be needed when * we begin to modify settings after boot initialization. */ static struct itr_chip *itr_main_chip __nex_bss; TEE_Result itr_chip_init(struct itr_chip *chip) { if (!itr_chip_is_valid(chip)) return TEE_ERROR_BAD_PARAMETERS; SLIST_INIT(&chip->handlers); return TEE_SUCCESS; } void interrupt_main_init(struct itr_chip *chip) { if (itr_chip_init(chip)) panic(); itr_main_chip = chip; } struct itr_chip *interrupt_get_main_chip(void) { assert(itr_main_chip); return itr_main_chip; } struct itr_chip *interrupt_get_main_chip_may_fail(void) { return itr_main_chip; } #ifdef CFG_DT int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, uint32_t *prio) { const uint32_t *prop = NULL; int count = 0; int it_num = DT_INFO_INVALID_INTERRUPT; if (!itr_main_chip || !itr_main_chip->dt_get_irq) return it_num; prop = fdt_getprop(fdt, node, "interrupts", &count); if (!prop) return it_num; return itr_main_chip->dt_get_irq(prop, count, type, prio); } #endif /* This function is supposed to be overridden in platform specific code */ void __weak __noreturn interrupt_main_handler(void) { panic("Secure interrupt handler not defined"); } /* * Interrupt controller chip support */ void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num) { struct itr_handler *h = NULL; bool was_handled = false; assert(chip); SLIST_FOREACH(h, &chip->handlers, link) { if (h->it == itr_num) { if (h->handler(h) == ITRR_HANDLED) was_handled = true; else if (!(h->flags & ITRF_SHARED)) break; } } if (!was_handled) { EMSG("Mask unhandled interrupt %s:%zu", chip->name, itr_num); interrupt_mask(chip, itr_num); } } TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, uint32_t type, uint32_t prio) { chip->ops->add(chip, itr_num, type, prio); return TEE_SUCCESS; } static TEE_Result add_configure_handler(struct itr_handler *hdl, uint32_t type, uint32_t prio, bool configure) { struct itr_handler *h = NULL; assert(hdl && hdl->chip->ops && is_unpaged(hdl) && hdl->handler && is_unpaged(hdl->handler)); SLIST_FOREACH(h, &hdl->chip->handlers, link) { if (h->it == hdl->it && (!(hdl->flags & ITRF_SHARED) || !(h->flags & ITRF_SHARED))) { EMSG("Shared and non-shared flags on interrupt %s#%zu", hdl->chip->name, hdl->it); return TEE_ERROR_GENERIC; } } if (configure) interrupt_configure(hdl->chip, hdl->it, type, prio); SLIST_INSERT_HEAD(&hdl->chip->handlers, hdl, link); return TEE_SUCCESS; } TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, uint32_t type, uint32_t prio) { return add_configure_handler(hdl, type, prio, true /* configure */); } TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, itr_handler_t callback, void *priv, uint32_t flags, struct itr_handler **out_hdl) { TEE_Result res = TEE_ERROR_GENERIC; struct itr_handler *itr_hdl = NULL; itr_hdl = calloc(1, sizeof(*itr_hdl)); if (!itr_hdl) return TEE_ERROR_OUT_OF_MEMORY; *itr_hdl = (struct itr_handler){ .chip = itr_chip, .it = itr_num, .flags = flags, .handler = callback, .data = priv, }; res = add_configure_handler(itr_hdl, 0, 0, false /* configure */); if (res) { free(itr_hdl); return res; } if (out_hdl) *out_hdl = itr_hdl; return TEE_SUCCESS; } void interrupt_remove_handler(struct itr_handler *hdl) { struct itr_handler *h = NULL; bool disable_itr = true; if (!hdl) return; SLIST_FOREACH(h, &hdl->chip->handlers, link) if (h == hdl) break; if (!h) { DMSG("Invalid %s:%zu", hdl->chip->name, hdl->it); assert(false); return; } if (hdl->flags & ITRF_SHARED) { SLIST_FOREACH(h, &hdl->chip->handlers, link) { if (h != hdl && h->it == hdl->it) { disable_itr = false; break; } } } if (disable_itr) interrupt_disable(hdl->chip, hdl->it); SLIST_REMOVE(&hdl->chip->handlers, hdl, itr_handler, link); } TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, size_t itr_num, itr_handler_t handler, uint32_t flags, void *data, uint32_t type, uint32_t prio, struct itr_handler **out_hdl) { TEE_Result res = TEE_ERROR_GENERIC; struct itr_handler *hdl = NULL; hdl = calloc(1, sizeof(*hdl)); if (!hdl) return TEE_ERROR_OUT_OF_MEMORY; *hdl = ITR_HANDLER(chip, itr_num, flags, handler, data); res = interrupt_add_configure_handler(hdl, type, prio); if (res) { free(hdl); return res; } if (out_hdl) *out_hdl = hdl; return TEE_SUCCESS; } void interrupt_remove_free_handler(struct itr_handler *hdl) { if (hdl) { interrupt_remove_handler(hdl); free(hdl); } } #ifdef CFG_DT TEE_Result interrupt_register_provider(const void *fdt, int node, itr_dt_get_func dt_get_itr, void *data) { return dt_driver_register_provider(fdt, node, (get_of_device_func)dt_get_itr, data, DT_DRIVER_INTERRUPT); } /* * Fills an itr_desc reference based on "interrupts" property bindings. * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found but * not yet initialized. */ static TEE_Result get_legacy_interrupt_by_index(const void *fdt, int node, unsigned int index, struct itr_desc *itr_desc) { const uint32_t *prop = NULL; uint32_t phandle = 0; int pnode = 0; int len = 0; prop = fdt_getprop(fdt, node, "interrupts", &len); if (!prop) return TEE_ERROR_ITEM_NOT_FOUND; /* Find "interrupt-parent" in node or its parents */ pnode = node; prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len); while (!prop) { pnode = fdt_parent_offset(fdt, pnode); if (pnode < 0) break; prop = fdt_getprop(fdt, pnode, "interrupt-parent", &len); if (!prop && len != -FDT_ERR_NOTFOUND) break; } if (!prop) { DMSG("No interrupt parent for node %s", fdt_get_name(fdt, node, NULL)); return TEE_ERROR_GENERIC; } /* "interrupt-parent" provides interrupt controller phandle */ phandle = fdt32_to_cpu(prop[0]); /* Get interrupt chip/number from phandle and "interrupts" property */ return dt_driver_device_from_node_idx_prop_phandle("interrupts", fdt, node, index, DT_DRIVER_INTERRUPT, phandle, itr_desc); } /* * Fills an itr_desc based on "interrupts-extended" property bindings. * May return TEE_ERROR_DEFER_DRIVER_INIT if parent controller is found * but not yet initialized. */ static TEE_Result get_extended_interrupt_by_index(const void *fdt, int node, unsigned int index, struct itr_desc *itr_desc) { return dt_driver_device_from_node_idx_prop("interrupts-extended", fdt, node, index, DT_DRIVER_INTERRUPT, itr_desc); } TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, unsigned int index, struct itr_chip **chip, size_t *itr_num) { TEE_Result res = TEE_ERROR_GENERIC; struct itr_desc desc = { }; assert(chip && itr_num); /* "interrupts-extended" takes precedence over "interrupts" */ if (fdt_getprop(fdt, node, "interrupts-extended", NULL)) res = get_extended_interrupt_by_index(fdt, node, index, &desc); else res = get_legacy_interrupt_by_index(fdt, node, index, &desc); if (!res) { assert(desc.chip); *chip = desc.chip; *itr_num = desc.itr_num; } return res; } TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, struct itr_chip **chip, size_t *itr_num) { int idx = 0; idx = fdt_stringlist_search(fdt, node, "interrupt-names", name); if (idx < 0) return TEE_ERROR_GENERIC; return interrupt_dt_get_by_index(fdt, node, idx, chip, itr_num); } #endif /*CFG_DT*/ optee_os-4.3.0/core/kernel/ldelf_loader.c000066400000000000000000000304351464416617300203440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015-2020, 2022 Linaro Limited * Copyright (c) 2020-2023, Arm Limited */ #include #include #include #include #include #include #include #include #define BOUNCE_BUFFER_SIZE 4096 extern uint8_t ldelf_data[]; extern const unsigned int ldelf_code_size; extern const unsigned int ldelf_data_size; extern const unsigned int ldelf_entry; /* ldelf has the same architecture/register width as the kernel */ #if defined(ARM32) || defined(RV32) static const bool is_32bit = true; #else static const bool is_32bit; #endif static TEE_Result alloc_and_map_fobj(struct user_mode_ctx *uctx, size_t sz, uint32_t prot, uint32_t flags, vaddr_t *va) { size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; struct fobj *fobj = fobj_ta_mem_alloc(num_pgs); struct mobj *mobj = mobj_with_fobj_alloc(fobj, NULL, TEE_MATTR_MEM_TYPE_TAGGED); TEE_Result res = TEE_SUCCESS; fobj_put(fobj); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map(uctx, va, num_pgs * SMALL_PAGE_SIZE, prot, flags, mobj, 0); mobj_put(mobj); return res; } /* * This function may leave a few mappings behind on error, but that's taken * care of by tee_ta_init_user_ta_session() since the entire context is * removed then. */ TEE_Result ldelf_load_ldelf(struct user_mode_ctx *uctx) { TEE_Result res = TEE_SUCCESS; vaddr_t stack_addr = 0; vaddr_t code_addr = 0; vaddr_t rw_addr = 0; vaddr_t bb_addr = 0; uint32_t prot = 0; uctx->is_32bit = is_32bit; res = alloc_and_map_fobj(uctx, BOUNCE_BUFFER_SIZE, TEE_MATTR_PRW, 0, &bb_addr); if (res) return res; uctx->bbuf = (void *)bb_addr; uctx->bbuf_size = BOUNCE_BUFFER_SIZE; res = alloc_and_map_fobj(uctx, LDELF_STACK_SIZE, TEE_MATTR_URW | TEE_MATTR_PRW, VM_FLAG_LDELF, &stack_addr); if (res) return res; uctx->ldelf_stack_ptr = stack_addr + LDELF_STACK_SIZE; res = alloc_and_map_fobj(uctx, ldelf_code_size, TEE_MATTR_PRW, VM_FLAG_LDELF, &code_addr); if (res) return res; uctx->entry_func = code_addr + ldelf_entry; rw_addr = ROUNDUP(code_addr + ldelf_code_size, SMALL_PAGE_SIZE); res = alloc_and_map_fobj(uctx, ldelf_data_size, TEE_MATTR_URW | TEE_MATTR_PRW, VM_FLAG_LDELF, &rw_addr); if (res) return res; vm_set_ctx(uctx->ts_ctx); memcpy((void *)code_addr, ldelf_data, ldelf_code_size); res = copy_to_user((void *)rw_addr, ldelf_data + ldelf_code_size, ldelf_data_size); if (res) return res; prot = TEE_MATTR_URX; if (IS_ENABLED(CFG_CORE_BTI)) prot |= TEE_MATTR_GUARDED; res = vm_set_prot(uctx, code_addr, ROUNDUP(ldelf_code_size, SMALL_PAGE_SIZE), prot); if (res) return res; DMSG("ldelf load address %#"PRIxVA, code_addr); return TEE_SUCCESS; } TEE_Result ldelf_init_with_ldelf(struct ts_session *sess, struct user_mode_ctx *uctx) { TEE_Result res = TEE_SUCCESS; struct ldelf_arg *arg = NULL; uint32_t panic_code = 0; uint32_t panicked = 0; uaddr_t usr_stack = 0; struct ldelf_arg *arg_bbuf = NULL; usr_stack = uctx->ldelf_stack_ptr; usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); arg = (struct ldelf_arg *)usr_stack; sess->handle_scall = scall_handle_ldelf; res = clear_user(arg, sizeof(*arg)); if (res) return res; res = PUT_USER_SCALAR(uctx->ts_ctx->uuid, &arg->uuid); if (res) return res; res = thread_enter_user_mode((vaddr_t)arg, 0, 0, 0, usr_stack, uctx->entry_func, is_32bit, &panicked, &panic_code); sess->handle_scall = sess->ctx->ops->handle_scall; thread_user_clear_vfp(uctx); ldelf_sess_cleanup(sess); if (panicked) { abort_print_current_ts(); EMSG("ldelf panicked"); return TEE_ERROR_GENERIC; } if (res) { EMSG("ldelf failed with res: %#"PRIx32, res); return res; } res = BB_MEMDUP_USER(arg, sizeof(*arg), &arg_bbuf); if (res) return res; if (is_user_ta_ctx(uctx->ts_ctx)) { /* * This is already checked by the elf loader, but since it runs * in user mode we're not trusting it entirely. */ if (arg_bbuf->flags & ~TA_FLAGS_MASK) return TEE_ERROR_BAD_FORMAT; to_user_ta_ctx(uctx->ts_ctx)->ta_ctx.flags = arg_bbuf->flags; } uctx->is_32bit = arg_bbuf->is_32bit; uctx->entry_func = arg_bbuf->entry_func; uctx->load_addr = arg_bbuf->load_addr; uctx->stack_ptr = arg_bbuf->stack_ptr; uctx->dump_entry_func = arg_bbuf->dump_entry; #ifdef CFG_FTRACE_SUPPORT uctx->ftrace_entry_func = arg_bbuf->ftrace_entry; sess->fbuf = arg_bbuf->fbuf; #endif uctx->dl_entry_func = arg_bbuf->dl_entry; bb_free(arg_bbuf, sizeof(*arg)); return TEE_SUCCESS; } TEE_Result ldelf_dump_state(struct user_mode_ctx *uctx) { TEE_Result res = TEE_SUCCESS; uaddr_t usr_stack = uctx->ldelf_stack_ptr; struct dump_entry_arg *arg = NULL; uint32_t panic_code = 0; uint32_t panicked = 0; struct thread_specific_data *tsd = thread_get_tsd(); struct ts_session *sess = NULL; struct vm_region *r = NULL; size_t arg_size = 0; size_t n = 0; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) if (r->attr & TEE_MATTR_URWX) n++; arg_size = ROUNDUP(sizeof(*arg) + n * sizeof(struct dump_map), STACK_ALIGNMENT); usr_stack = uctx->ldelf_stack_ptr; usr_stack -= arg_size; arg = bb_alloc(arg_size); if (!arg) return TEE_ERROR_OUT_OF_MEMORY; memset(arg, 0, arg_size); arg->num_maps = n; n = 0; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { if (r->attr & TEE_MATTR_URWX) { if (r->mobj) mobj_get_pa(r->mobj, r->offset, 0, &arg->maps[n].pa); arg->maps[n].va = r->va; arg->maps[n].sz = r->size; if (r->attr & TEE_MATTR_UR) arg->maps[n].flags |= DUMP_MAP_READ; if (r->attr & TEE_MATTR_UW) arg->maps[n].flags |= DUMP_MAP_WRITE; if (r->attr & TEE_MATTR_UX) arg->maps[n].flags |= DUMP_MAP_EXEC; if (r->attr & TEE_MATTR_SECURE) arg->maps[n].flags |= DUMP_MAP_SECURE; if (r->flags & VM_FLAG_EPHEMERAL) arg->maps[n].flags |= DUMP_MAP_EPHEM; if (r->flags & VM_FLAG_LDELF) arg->maps[n].flags |= DUMP_MAP_LDELF; n++; } } arg->is_32bit = uctx->is_32bit; #ifdef ARM32 arg->arm32.regs[0] = tsd->abort_regs.r0; arg->arm32.regs[1] = tsd->abort_regs.r1; arg->arm32.regs[2] = tsd->abort_regs.r2; arg->arm32.regs[3] = tsd->abort_regs.r3; arg->arm32.regs[4] = tsd->abort_regs.r4; arg->arm32.regs[5] = tsd->abort_regs.r5; arg->arm32.regs[6] = tsd->abort_regs.r6; arg->arm32.regs[7] = tsd->abort_regs.r7; arg->arm32.regs[8] = tsd->abort_regs.r8; arg->arm32.regs[9] = tsd->abort_regs.r9; arg->arm32.regs[10] = tsd->abort_regs.r10; arg->arm32.regs[11] = tsd->abort_regs.r11; arg->arm32.regs[12] = tsd->abort_regs.ip; arg->arm32.regs[13] = tsd->abort_regs.usr_sp; /*SP*/ arg->arm32.regs[14] = tsd->abort_regs.usr_lr; /*LR*/ arg->arm32.regs[15] = tsd->abort_regs.elr; /*PC*/ #endif /*ARM32*/ #ifdef ARM64 if (uctx->is_32bit) { arg->arm32.regs[0] = tsd->abort_regs.x0; arg->arm32.regs[1] = tsd->abort_regs.x1; arg->arm32.regs[2] = tsd->abort_regs.x2; arg->arm32.regs[3] = tsd->abort_regs.x3; arg->arm32.regs[4] = tsd->abort_regs.x4; arg->arm32.regs[5] = tsd->abort_regs.x5; arg->arm32.regs[6] = tsd->abort_regs.x6; arg->arm32.regs[7] = tsd->abort_regs.x7; arg->arm32.regs[8] = tsd->abort_regs.x8; arg->arm32.regs[9] = tsd->abort_regs.x9; arg->arm32.regs[10] = tsd->abort_regs.x10; arg->arm32.regs[11] = tsd->abort_regs.x11; arg->arm32.regs[12] = tsd->abort_regs.x12; arg->arm32.regs[13] = tsd->abort_regs.x13; /*SP*/ arg->arm32.regs[14] = tsd->abort_regs.x14; /*LR*/ arg->arm32.regs[15] = tsd->abort_regs.elr; /*PC*/ } else { arg->arm64.fp = tsd->abort_regs.x29; arg->arm64.pc = tsd->abort_regs.elr; arg->arm64.sp = tsd->abort_regs.sp_el0; } #endif /*ARM64*/ #if defined(RV64) || defined(RV32) arg->rv.fp = tsd->abort_regs.s0; arg->rv.pc = tsd->abort_regs.epc; arg->rv.sp = tsd->abort_regs.sp; #endif /*RV64||RV32*/ res = copy_to_user((void *)usr_stack, arg, arg_size); if (res) return res; sess = ts_get_current_session(); sess->handle_scall = scall_handle_ldelf; res = thread_enter_user_mode(usr_stack, 0, 0, 0, usr_stack, uctx->dump_entry_func, is_32bit, &panicked, &panic_code); sess->handle_scall = sess->ctx->ops->handle_scall; thread_user_clear_vfp(uctx); ldelf_sess_cleanup(sess); if (panicked) { uctx->dump_entry_func = 0; EMSG("ldelf dump function panicked"); abort_print_current_ts(); res = TEE_ERROR_TARGET_DEAD; } return res; } #ifdef CFG_FTRACE_SUPPORT TEE_Result ldelf_dump_ftrace(struct user_mode_ctx *uctx, void *buf, size_t *blen) { uaddr_t usr_stack = uctx->ldelf_stack_ptr; TEE_Result res = TEE_SUCCESS; uint32_t panic_code = 0; uint32_t panicked = 0; size_t *arg = NULL; struct ts_session *sess = NULL; if (!uctx->ftrace_entry_func) return TEE_ERROR_NOT_SUPPORTED; usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); arg = (size_t *)usr_stack; res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)arg, sizeof(*arg)); if (res) { EMSG("ldelf stack is inaccessible!"); return res; } *arg = *blen; sess = ts_get_current_session(); sess->handle_scall = scall_handle_ldelf; res = thread_enter_user_mode((vaddr_t)buf, (vaddr_t)arg, 0, 0, usr_stack, uctx->ftrace_entry_func, is_32bit, &panicked, &panic_code); sess->handle_scall = sess->ctx->ops->handle_scall; thread_user_clear_vfp(uctx); ldelf_sess_cleanup(sess); if (panicked) { uctx->ftrace_entry_func = 0; EMSG("ldelf ftrace function panicked"); abort_print_current_ts(); res = TEE_ERROR_TARGET_DEAD; } if (!res) { if (*arg > *blen) res = TEE_ERROR_SHORT_BUFFER; *blen = *arg; } return res; } #endif /*CFG_FTRACE_SUPPORT*/ TEE_Result ldelf_dlopen(struct user_mode_ctx *uctx, TEE_UUID *uuid, uint32_t flags) { uaddr_t usr_stack = uctx->ldelf_stack_ptr; TEE_Result res = TEE_ERROR_GENERIC; struct dl_entry_arg *usr_arg = NULL; struct dl_entry_arg *arg = NULL; uint32_t panic_code = 0; uint32_t panicked = 0; struct ts_session *sess = NULL; assert(uuid); arg = bb_alloc(sizeof(*arg)); if (!arg) return TEE_ERROR_OUT_OF_MEMORY; memset(arg, 0, sizeof(*arg)); arg->cmd = LDELF_DL_ENTRY_DLOPEN; arg->dlopen.uuid = *uuid; arg->dlopen.flags = flags; usr_stack -= ROUNDUP(sizeof(*arg), STACK_ALIGNMENT); usr_arg = (void *)usr_stack; res = copy_to_user(usr_arg, arg, sizeof(*arg)); if (res) return res; sess = ts_get_current_session(); sess->handle_scall = scall_handle_ldelf; res = thread_enter_user_mode(usr_stack, 0, 0, 0, usr_stack, uctx->dl_entry_func, is_32bit, &panicked, &panic_code); sess->handle_scall = sess->ctx->ops->handle_scall; ldelf_sess_cleanup(sess); if (panicked) { EMSG("ldelf dl_entry function panicked"); abort_print_current_ts(); res = TEE_ERROR_TARGET_DEAD; } if (!res) { TEE_Result res2 = TEE_SUCCESS; res2 = GET_USER_SCALAR(res, &usr_arg->ret); if (res2) res = res2; } return res; } TEE_Result ldelf_dlsym(struct user_mode_ctx *uctx, TEE_UUID *uuid, const char *sym, size_t symlen, vaddr_t *val) { uaddr_t usr_stack = uctx->ldelf_stack_ptr; TEE_Result res = TEE_ERROR_GENERIC; struct dl_entry_arg *usr_arg = NULL; struct dl_entry_arg *arg = NULL; uint32_t panic_code = 0; uint32_t panicked = 0; struct ts_session *sess = NULL; usr_stack -= ROUNDUP(sizeof(*arg) + symlen + 1, STACK_ALIGNMENT); usr_arg = (void *)usr_stack; arg = bb_alloc(sizeof(*arg)); if (!arg) return TEE_ERROR_OUT_OF_MEMORY; memset(arg, 0, sizeof(*arg)); arg->cmd = LDELF_DL_ENTRY_DLSYM; arg->dlsym.uuid = *uuid; res = copy_to_user(usr_arg, arg, sizeof(*arg)); if (res) return res; res = copy_to_user(usr_arg->dlsym.symbol, sym, symlen + 1); if (res) return res; sess = ts_get_current_session(); sess->handle_scall = scall_handle_ldelf; res = thread_enter_user_mode((vaddr_t)usr_arg, 0, 0, 0, usr_stack, uctx->dl_entry_func, is_32bit, &panicked, &panic_code); sess->handle_scall = sess->ctx->ops->handle_scall; ldelf_sess_cleanup(sess); if (panicked) { EMSG("ldelf dl_entry function panicked"); abort_print_current_ts(); res = TEE_ERROR_TARGET_DEAD; } if (!res) { TEE_Result res2 = TEE_SUCCESS; res2 = GET_USER_SCALAR(res, &usr_arg->ret); if (res2) res = res2; if (!res) res = GET_USER_SCALAR(*val, &usr_arg->dlsym.val); } return res; } optee_os-4.3.0/core/kernel/ldelf_syscalls.c000066400000000000000000000361711464416617300207360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2019, 2022 Linaro Limited * Copyright (c) 2020-2021, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct bin_handle { const struct ts_store_ops *op; struct ts_store_handle *h; struct file *f; size_t offs_bytes; size_t size_bytes; }; static void unmap_or_panic(struct user_mode_ctx *uctx, vaddr_t va, size_t byte_count) { TEE_Result res = vm_unmap(uctx, va, byte_count); if (res) { EMSG("vm_unmap(%#"PRIxVA", %#zx) returned %#"PRIx32, va, byte_count, res); panic("Can't restore memory map"); } } TEE_Result ldelf_syscall_map_zi(vaddr_t *va, size_t num_bytes, size_t pad_begin, size_t pad_end, unsigned long flags) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); struct fobj *f = NULL; struct mobj *mobj = NULL; uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; uint32_t vm_flags = 0; vaddr_t va_copy = 0; if (flags & ~LDELF_MAP_FLAG_SHAREABLE) return TEE_ERROR_BAD_PARAMETERS; res = GET_USER_SCALAR(va_copy, va); if (res) return res; if (flags & LDELF_MAP_FLAG_SHAREABLE) vm_flags |= VM_FLAG_SHAREABLE; f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE)); if (!f) return TEE_ERROR_OUT_OF_MEMORY; mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(f); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map_pad(uctx, &va_copy, num_bytes, prot, vm_flags, mobj, 0, pad_begin, pad_end, 0); mobj_put(mobj); if (!res) { res = PUT_USER_SCALAR(va_copy, va); if (res) unmap_or_panic(uctx, va_copy, num_bytes); } return res; } TEE_Result ldelf_syscall_unmap(vaddr_t va, size_t num_bytes) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); size_t sz = ROUNDUP(num_bytes, SMALL_PAGE_SIZE); uint32_t vm_flags = 0; vaddr_t end_va = 0; /* * The vm_get_flags() and vm_unmap() are supposed to detect or handle * overflow directly or indirectly. However, since this function is an * API function it's worth having an extra guard here. If nothing else, * to increase code clarity. */ if (ADD_OVERFLOW(va, sz, &end_va)) return TEE_ERROR_BAD_PARAMETERS; res = vm_get_flags(uctx, va, sz, &vm_flags); if (res) return res; if (vm_flags & VM_FLAG_PERMANENT) return TEE_ERROR_ACCESS_DENIED; return vm_unmap(uctx, va, sz); } static void bin_close(void *ptr) { struct bin_handle *binh = ptr; if (binh) { if (binh->op && binh->h) binh->op->close(binh->h); file_put(binh->f); } free(binh); } TEE_Result ldelf_syscall_open_bin(const TEE_UUID *uuid, size_t uuid_size, uint32_t *handle) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); struct system_ctx *sys_ctx = sess->user_ctx; struct bin_handle *binh = NULL; uint8_t tag[FILE_TAG_SIZE] = { 0 }; unsigned int tag_len = sizeof(tag); TEE_UUID *bb_uuid = NULL; int h = 0; res = BB_MEMDUP_USER(uuid, sizeof(*uuid), &bb_uuid); if (res) return res; res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)handle, sizeof(uint32_t)); if (res) return res; if (uuid_size != sizeof(*uuid)) return TEE_ERROR_BAD_PARAMETERS; if (!sys_ctx) { sys_ctx = calloc(1, sizeof(*sys_ctx)); if (!sys_ctx) return TEE_ERROR_OUT_OF_MEMORY; sess->user_ctx = sys_ctx; } binh = calloc(1, sizeof(*binh)); if (!binh) return TEE_ERROR_OUT_OF_MEMORY; if (is_user_ta_ctx(sess->ctx) || is_stmm_ctx(sess->ctx)) { SCATTERED_ARRAY_FOREACH(binh->op, ta_stores, struct ts_store_ops) { DMSG("Lookup user TA ELF %pUl (%s)", (void *)bb_uuid, binh->op->description); res = binh->op->open(bb_uuid, &binh->h); DMSG("res=%#"PRIx32, res); if (res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) break; } } else if (is_sp_ctx(sess->ctx)) { SCATTERED_ARRAY_FOREACH(binh->op, sp_stores, struct ts_store_ops) { DMSG("Lookup user SP ELF %pUl (%s)", (void *)bb_uuid, binh->op->description); res = binh->op->open(bb_uuid, &binh->h); DMSG("res=%#"PRIx32, res); if (res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) break; } } else { res = TEE_ERROR_ITEM_NOT_FOUND; } if (res) goto err; res = binh->op->get_size(binh->h, &binh->size_bytes); if (res) goto err; res = binh->op->get_tag(binh->h, tag, &tag_len); if (res) goto err; binh->f = file_get_by_tag(tag, tag_len); if (!binh->f) goto err_oom; h = handle_get(&sys_ctx->db, binh); if (h < 0) goto err_oom; res = PUT_USER_SCALAR(h, handle); if (res) { handle_put(&sys_ctx->db, h); goto err; } return TEE_SUCCESS; err_oom: res = TEE_ERROR_OUT_OF_MEMORY; err: bin_close(binh); return res; } TEE_Result ldelf_syscall_close_bin(unsigned long handle) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct system_ctx *sys_ctx = sess->user_ctx; struct bin_handle *binh = NULL; if (!sys_ctx) return TEE_ERROR_BAD_PARAMETERS; binh = handle_put(&sys_ctx->db, handle); if (!binh) return TEE_ERROR_BAD_PARAMETERS; if (binh->offs_bytes < binh->size_bytes) res = binh->op->read(binh->h, NULL, NULL, binh->size_bytes - binh->offs_bytes); bin_close(binh); if (handle_db_is_empty(&sys_ctx->db)) { handle_db_destroy(&sys_ctx->db, bin_close); free(sys_ctx); sess->user_ctx = NULL; } return res; } static TEE_Result binh_copy_to(struct bin_handle *binh, vaddr_t va_core, vaddr_t va_user, size_t offs_bytes, size_t num_bytes) { TEE_Result res = TEE_SUCCESS; size_t next_offs = 0; if (offs_bytes < binh->offs_bytes) return TEE_ERROR_BAD_STATE; if (ADD_OVERFLOW(offs_bytes, num_bytes, &next_offs)) return TEE_ERROR_BAD_PARAMETERS; if (offs_bytes > binh->offs_bytes) { res = binh->op->read(binh->h, NULL, NULL, offs_bytes - binh->offs_bytes); if (res) return res; binh->offs_bytes = offs_bytes; } if (next_offs > binh->size_bytes) { size_t rb = binh->size_bytes - binh->offs_bytes; res = binh->op->read(binh->h, (void *)va_core, (void *)va_user, rb); if (res) return res; if (va_core) memset((uint8_t *)va_core + rb, 0, num_bytes - rb); if (va_user) { res = clear_user((uint8_t *)va_user + rb, num_bytes - rb); if (res) return res; } binh->offs_bytes = binh->size_bytes; } else { res = binh->op->read(binh->h, (void *)va_core, (void *)va_user, num_bytes); if (res) return res; binh->offs_bytes = next_offs; } return TEE_SUCCESS; } TEE_Result ldelf_syscall_map_bin(vaddr_t *va, size_t num_bytes, unsigned long handle, size_t offs_bytes, size_t pad_begin, size_t pad_end, unsigned long flags) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); struct system_ctx *sys_ctx = sess->user_ctx; struct bin_handle *binh = NULL; uint32_t num_rounded_bytes = 0; struct file_slice *fs = NULL; bool file_is_locked = false; struct mobj *mobj = NULL; uint32_t offs_pages = 0; size_t num_pages = 0; vaddr_t va_copy = 0; uint32_t prot = 0; const uint32_t accept_flags = LDELF_MAP_FLAG_SHAREABLE | LDELF_MAP_FLAG_WRITEABLE | LDELF_MAP_FLAG_BTI | LDELF_MAP_FLAG_EXECUTABLE; res = GET_USER_SCALAR(va_copy, va); if (res) return res; if (!sys_ctx) return TEE_ERROR_BAD_PARAMETERS; binh = handle_lookup(&sys_ctx->db, handle); if (!binh) return TEE_ERROR_BAD_PARAMETERS; if ((flags & accept_flags) != flags) return TEE_ERROR_BAD_PARAMETERS; if ((flags & LDELF_MAP_FLAG_SHAREABLE) && (flags & LDELF_MAP_FLAG_WRITEABLE)) return TEE_ERROR_BAD_PARAMETERS; if ((flags & LDELF_MAP_FLAG_EXECUTABLE) && (flags & LDELF_MAP_FLAG_WRITEABLE)) return TEE_ERROR_BAD_PARAMETERS; if (offs_bytes & SMALL_PAGE_MASK) return TEE_ERROR_BAD_PARAMETERS; prot = TEE_MATTR_UR | TEE_MATTR_PR; if (flags & LDELF_MAP_FLAG_WRITEABLE) prot |= TEE_MATTR_UW | TEE_MATTR_PW; if (flags & LDELF_MAP_FLAG_EXECUTABLE) prot |= TEE_MATTR_UX; if (flags & LDELF_MAP_FLAG_BTI) prot |= TEE_MATTR_GUARDED; offs_pages = offs_bytes >> SMALL_PAGE_SHIFT; if (ROUNDUP_OVERFLOW(num_bytes, SMALL_PAGE_SIZE, &num_rounded_bytes)) return TEE_ERROR_BAD_PARAMETERS; num_pages = num_rounded_bytes / SMALL_PAGE_SIZE; if (!file_trylock(binh->f)) { /* * Before we can block on the file lock we must make all * our page tables available for reclaiming in order to * avoid a dead-lock with the other thread (which already * is holding the file lock) mapping lots of memory below. */ vm_set_ctx(NULL); file_lock(binh->f); vm_set_ctx(uctx->ts_ctx); } file_is_locked = true; fs = file_find_slice(binh->f, offs_pages); if (fs) { /* If there's registered slice it has to match */ if (fs->page_offset != offs_pages || num_pages > fs->fobj->num_pages) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } /* If there's a slice we must be mapping shareable */ if (!(flags & LDELF_MAP_FLAG_SHAREABLE)) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } mobj = mobj_with_fobj_alloc(fs->fobj, binh->f, TEE_MATTR_MEM_TYPE_TAGGED); if (!mobj) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } res = vm_map_pad(uctx, &va_copy, num_rounded_bytes, prot, VM_FLAG_READONLY, mobj, 0, pad_begin, pad_end, 0); mobj_put(mobj); if (res) goto err; } else { struct fobj *f = fobj_ta_mem_alloc(num_pages); struct file *file = NULL; uint32_t vm_flags = 0; if (!f) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } if (!(flags & LDELF_MAP_FLAG_WRITEABLE)) { file = binh->f; vm_flags |= VM_FLAG_READONLY; } mobj = mobj_with_fobj_alloc(f, file, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(f); if (!mobj) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } res = vm_map_pad(uctx, &va_copy, num_rounded_bytes, TEE_MATTR_PRW, vm_flags, mobj, 0, pad_begin, pad_end, 0); mobj_put(mobj); if (res) goto err; res = binh_copy_to(binh, va_copy, 0, offs_bytes, num_bytes); if (res) goto err_unmap_va; res = vm_set_prot(uctx, va_copy, num_rounded_bytes, prot); if (res) goto err_unmap_va; /* * The context currently is active set it again to update * the mapping. */ vm_set_ctx(uctx->ts_ctx); if (!(flags & LDELF_MAP_FLAG_WRITEABLE)) { res = file_add_slice(binh->f, f, offs_pages); if (res) goto err_unmap_va; } } res = PUT_USER_SCALAR(va_copy, va); if (res) goto err_unmap_va; file_unlock(binh->f); return TEE_SUCCESS; err_unmap_va: unmap_or_panic(uctx, va_copy, num_rounded_bytes); /* * The context currently is active set it again to update * the mapping. */ vm_set_ctx(uctx->ts_ctx); err: if (file_is_locked) file_unlock(binh->f); return res; } TEE_Result ldelf_syscall_copy_from_bin(void *dst, size_t offs, size_t num_bytes, unsigned long handle) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); struct system_ctx *sys_ctx = sess->user_ctx; struct bin_handle *binh = NULL; res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)dst, num_bytes); if (res) return res; if (!sys_ctx) return TEE_ERROR_BAD_PARAMETERS; binh = handle_lookup(&sys_ctx->db, handle); if (!binh) return TEE_ERROR_BAD_PARAMETERS; return binh_copy_to(binh, 0, (vaddr_t)dst, offs, num_bytes); } TEE_Result ldelf_syscall_set_prot(unsigned long va, size_t num_bytes, unsigned long flags) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); size_t sz = ROUNDUP(num_bytes, SMALL_PAGE_SIZE); uint32_t prot = TEE_MATTR_UR | TEE_MATTR_PR; uint32_t vm_flags = 0; vaddr_t end_va = 0; const uint32_t accept_flags = LDELF_MAP_FLAG_WRITEABLE | LDELF_MAP_FLAG_BTI | LDELF_MAP_FLAG_EXECUTABLE; if ((flags & accept_flags) != flags) return TEE_ERROR_BAD_PARAMETERS; if (flags & LDELF_MAP_FLAG_WRITEABLE) prot |= TEE_MATTR_UW | TEE_MATTR_PW; if (flags & LDELF_MAP_FLAG_EXECUTABLE) prot |= TEE_MATTR_UX; if (flags & LDELF_MAP_FLAG_BTI) prot |= TEE_MATTR_GUARDED; /* * The vm_get_flags() and vm_unmap() are supposed to detect or handle * overflow directly or indirectly. However, since this function is an * API function it's worth having an extra guard here. If nothing else, * to increase code clarity. */ if (ADD_OVERFLOW(va, sz, &end_va)) return TEE_ERROR_BAD_PARAMETERS; res = vm_get_flags(uctx, va, sz, &vm_flags); if (res) return res; if (vm_flags & VM_FLAG_PERMANENT) return TEE_ERROR_ACCESS_DENIED; /* * If the segment is a mapping of a part of a file (vm_flags & * VM_FLAG_READONLY) it cannot be made writeable as all mapped * files are mapped read-only. */ if ((vm_flags & VM_FLAG_READONLY) && (prot & (TEE_MATTR_UW | TEE_MATTR_PW))) return TEE_ERROR_ACCESS_DENIED; return vm_set_prot(uctx, va, sz, prot); } TEE_Result ldelf_syscall_remap(unsigned long old_va, vaddr_t *new_va, size_t num_bytes, size_t pad_begin, size_t pad_end) { TEE_Result res = TEE_SUCCESS; struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(sess->ctx); uint32_t vm_flags = 0; vaddr_t va_copy = 0; res = GET_USER_SCALAR(va_copy, new_va); if (res) return res; res = vm_get_flags(uctx, old_va, num_bytes, &vm_flags); if (res) return res; if (vm_flags & VM_FLAG_PERMANENT) return TEE_ERROR_ACCESS_DENIED; res = vm_remap(uctx, &va_copy, old_va, num_bytes, pad_begin, pad_end); if (res) return res; res = PUT_USER_SCALAR(va_copy, new_va); if (res) { TEE_Result res2 = TEE_SUCCESS; vaddr_t va = old_va; res2 = vm_remap(uctx, &va, va_copy, num_bytes, 0, 0); if (res2) { EMSG("vm_remap(%#"PRIxVA", %#"PRIxVA", %#zx) returned %#"PRIx32, va, va_copy, num_bytes, res2); panic("Can't restore memory map"); } return res; } return TEE_SUCCESS; } TEE_Result ldelf_syscall_gen_rnd_num(void *buf, size_t num_bytes) { TEE_Result res = TEE_SUCCESS; void *bb = NULL; bb = bb_alloc(num_bytes); if (!bb) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_rng_read(bb, num_bytes); if (res) return res; return copy_to_user(buf, bb, num_bytes); } /* * Should be called after returning from ldelf. If user_ctx is not NULL means * that ldelf crashed or otherwise didn't complete properly. This function will * close the remaining handles and free the context structs allocated by ldelf. */ void ldelf_sess_cleanup(struct ts_session *sess) { struct system_ctx *sys_ctx = sess->user_ctx; if (sys_ctx) { handle_db_destroy(&sys_ctx->db, bin_close); free(sys_ctx); sess->user_ctx = NULL; } } optee_os-4.3.0/core/kernel/lockdep.c000066400000000000000000000265601464416617300173550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include #include #include #include #include #include #include #include /* lockdep_node::flags values */ /* Flags used for depth-first topological sorting */ #define LOCKDEP_NODE_TEMP_MARK BIT(0) #define LOCKDEP_NODE_PERM_MARK BIT(1) /* Flag used during breadth-first search (print shortest cycle) */ #define LOCKDEP_NODE_BFS_VISITED BIT(2) /* Find node in graph or add it */ static struct lockdep_node *lockdep_add_to_graph( struct lockdep_node_head *graph, uintptr_t lock_id) { struct lockdep_node *node = NULL; assert(graph); TAILQ_FOREACH(node, graph, link) if (node->lock_id == lock_id) return node; node = calloc(1, sizeof(*node)); if (!node) return NULL; node->lock_id = lock_id; STAILQ_INIT(&node->edges); TAILQ_INSERT_TAIL(graph, node, link); return node; } static vaddr_t *dup_call_stack(vaddr_t *stack) { vaddr_t *nstack = NULL; int n = 0; if (!stack) return NULL; while (stack[n]) n++; nstack = malloc((n + 1) * sizeof(vaddr_t)); if (!nstack) return NULL; memcpy(nstack, stack, (n + 1) * sizeof(vaddr_t)); return nstack; } static void lockdep_print_call_stack(vaddr_t *stack) { vaddr_t *p = NULL; if (!IS_ENABLED(CFG_LOCKDEP_RECORD_STACK)) return; EMSG_RAW("Call stack:"); for (p = stack; p && *p; p++) EMSG_RAW(" %#" PRIxPTR, *p); } static TEE_Result lockdep_add_edge(struct lockdep_node *from, struct lockdep_node *to, vaddr_t *call_stack_from, vaddr_t *call_stack_to, uintptr_t thread_id) { struct lockdep_edge *edge = NULL; STAILQ_FOREACH(edge, &from->edges, link) if (edge->to == to) return TEE_SUCCESS; edge = calloc(1, sizeof(*edge)); if (!edge) return TEE_ERROR_OUT_OF_MEMORY; edge->to = to; edge->call_stack_from = dup_call_stack(call_stack_from); edge->call_stack_to = dup_call_stack(call_stack_to); edge->thread_id = thread_id; STAILQ_INSERT_TAIL(&from->edges, edge, link); return TEE_SUCCESS; } struct lockdep_bfs { struct lockdep_node *node; uintptr_t *path; int pathlen; TAILQ_ENTRY(lockdep_bfs) link; }; TAILQ_HEAD(lockdep_bfs_head, lockdep_bfs); static void lockdep_bfs_queue_delete(struct lockdep_bfs_head *queue) { struct lockdep_bfs *cur = NULL; struct lockdep_bfs *next = NULL; TAILQ_FOREACH_SAFE(cur, queue, link, next) { TAILQ_REMOVE(queue, cur, link); free(cur->path); free(cur); } } /* * Print shortest cycle in @graph that contains @node. * This function performs an iterative breadth-first search starting from @node, * and stops when it reaches @node again. In each node we're tracking the path * from the start node. */ static uintptr_t *lockdep_graph_get_shortest_cycle(struct lockdep_node *node) { struct lockdep_bfs_head queue; struct lockdep_bfs *qe = NULL; uintptr_t *ret = NULL; TAILQ_INIT(&queue); node->flags |= LOCKDEP_NODE_BFS_VISITED; qe = calloc(1, sizeof(*qe)); if (!qe) goto out; qe->node = node; qe->path = malloc(sizeof(uintptr_t)); if (!qe->path) goto out; qe->path[0] = node->lock_id; qe->pathlen = 1; TAILQ_INSERT_TAIL(&queue, qe, link); while (!TAILQ_EMPTY(&queue)) { struct lockdep_node *n = NULL; struct lockdep_edge *e = NULL; qe = TAILQ_FIRST(&queue); n = qe->node; TAILQ_REMOVE(&queue, qe, link); STAILQ_FOREACH(e, &n->edges, link) { if (e->to->lock_id == node->lock_id) { uintptr_t *tmp = NULL; size_t nlen = qe->pathlen + 1; /* * Cycle found. Terminate cycle path with NULL * and return it. */ tmp = realloc(qe->path, nlen * sizeof(uintptr_t)); if (!tmp) { EMSG("Out of memory"); free(qe->path); ret = NULL; goto out; } qe->path = tmp; qe->path[nlen - 1] = 0; ret = qe->path; goto out; } if (!(e->to->flags & LOCKDEP_NODE_BFS_VISITED)) { size_t nlen = 0; struct lockdep_bfs *nqe = NULL; e->to->flags |= LOCKDEP_NODE_BFS_VISITED; nlen = qe->pathlen + 1; nqe = calloc(1, sizeof(*nqe)); if (!nqe) goto out; nqe->node = e->to; nqe->path = malloc(nlen * sizeof(uintptr_t)); if (!nqe->path) goto out; nqe->pathlen = nlen; memcpy(nqe->path, qe->path, qe->pathlen * sizeof(uintptr_t)); nqe->path[nlen - 1] = e->to->lock_id; TAILQ_INSERT_TAIL(&queue, nqe, link); } } free(qe->path); free(qe); qe = NULL; } out: free(qe); lockdep_bfs_queue_delete(&queue); return ret; } static TEE_Result lockdep_visit(struct lockdep_node *node) { struct lockdep_edge *e = NULL; if (node->flags & LOCKDEP_NODE_PERM_MARK) return TEE_SUCCESS; if (node->flags & LOCKDEP_NODE_TEMP_MARK) return TEE_ERROR_BAD_STATE; /* Not a DAG! */ node->flags |= LOCKDEP_NODE_TEMP_MARK; STAILQ_FOREACH(e, &node->edges, link) { TEE_Result res = lockdep_visit(e->to); if (res) return res; } node->flags |= LOCKDEP_NODE_PERM_MARK; return TEE_SUCCESS; } static TEE_Result lockdep_graph_sort(struct lockdep_node_head *graph) { struct lockdep_node *node = NULL; TAILQ_FOREACH(node, graph, link) { if (!node->flags) { /* Unmarked node */ TEE_Result res = lockdep_visit(node); if (res) return res; } } TAILQ_FOREACH(node, graph, link) node->flags = 0; return TEE_SUCCESS; } static struct lockdep_edge *lockdep_find_edge(struct lockdep_node_head *graph, uintptr_t from, uintptr_t to) { struct lockdep_node *node = NULL; struct lockdep_edge *edge = NULL; TAILQ_FOREACH(node, graph, link) if (node->lock_id == from) STAILQ_FOREACH(edge, &node->edges, link) if (edge->to->lock_id == to) return edge; return NULL; } static void lockdep_print_edge_info(uintptr_t from __maybe_unused, struct lockdep_edge *edge) { uintptr_t __maybe_unused to = edge->to->lock_id; const char __maybe_unused *at_msg = ""; const char __maybe_unused *acq_msg = ""; if (IS_ENABLED(CFG_LOCKDEP_RECORD_STACK)) { at_msg = " at:"; acq_msg = " acquired at:"; } EMSG_RAW("-> Thread %#" PRIxPTR " acquired lock %#" PRIxPTR "%s", edge->thread_id, to, at_msg); lockdep_print_call_stack(edge->call_stack_to); EMSG_RAW("...while holding lock %#" PRIxPTR "%s", from, acq_msg); lockdep_print_call_stack(edge->call_stack_from); } /* * Find cycle containing @node in the lock graph, then print full debug * information about each edge (thread that acquired the locks and call stacks) */ static void lockdep_print_cycle_info(struct lockdep_node_head *graph, struct lockdep_node *node) { struct lockdep_edge *edge = NULL; uintptr_t *cycle = NULL; uintptr_t *p = NULL; uintptr_t from = 0; uintptr_t to = 0; cycle = lockdep_graph_get_shortest_cycle(node); assert(cycle && cycle[0]); EMSG_RAW("-> Shortest cycle:"); for (p = cycle; *p; p++) EMSG_RAW(" Lock %#" PRIxPTR, *p); for (p = cycle; ; p++) { if (!*p) { assert(p != cycle); from = to; to = cycle[0]; edge = lockdep_find_edge(graph, from, to); lockdep_print_edge_info(from, edge); break; } if (p != cycle) from = to; to = *p; if (p != cycle) { edge = lockdep_find_edge(graph, from, to); lockdep_print_edge_info(from, edge); } } free(cycle); } static vaddr_t *lockdep_get_kernel_stack(void) { if (IS_ENABLED(CFG_LOCKDEP_RECORD_STACK)) return unw_get_kernel_stack(); return NULL; } TEE_Result __lockdep_lock_acquire(struct lockdep_node_head *graph, struct lockdep_lock_head *owned, uintptr_t id) { struct lockdep_node *node = lockdep_add_to_graph(graph, id); struct lockdep_lock *lock = NULL; TEE_Result res = TEE_SUCCESS; vaddr_t *acq_stack = NULL; if (!node) return TEE_ERROR_OUT_OF_MEMORY; acq_stack = lockdep_get_kernel_stack(); TAILQ_FOREACH(lock, owned, link) { res = lockdep_add_edge(lock->node, node, lock->call_stack, acq_stack, (uintptr_t)owned); if (res) return res; } res = lockdep_graph_sort(graph); if (res) { EMSG_RAW("Potential deadlock detected!"); EMSG_RAW("When trying to acquire lock %#" PRIxPTR, id); lockdep_print_cycle_info(graph, node); return res; } lock = calloc(1, sizeof(*lock)); if (!lock) return TEE_ERROR_OUT_OF_MEMORY; lock->node = node; lock->call_stack = acq_stack; TAILQ_INSERT_TAIL(owned, lock, link); return TEE_SUCCESS; } /* * Call this when it is known that the thread has been able to acquire the lock. * Similar to __lockdep_lock_acquire(), but since the operation is non-blocking, * no dependency to currently owned locks are created. */ TEE_Result __lockdep_lock_tryacquire(struct lockdep_node_head *graph, struct lockdep_lock_head *owned, uintptr_t id) { struct lockdep_node *node = lockdep_add_to_graph(graph, id); struct lockdep_lock *lock = NULL; vaddr_t *acq_stack = NULL; if (!node) return TEE_ERROR_OUT_OF_MEMORY; acq_stack = lockdep_get_kernel_stack(); lock = calloc(1, sizeof(*lock)); if (!lock) return TEE_ERROR_OUT_OF_MEMORY; lock->node = node; lock->call_stack = acq_stack; TAILQ_INSERT_TAIL(owned, lock, link); return TEE_SUCCESS; } TEE_Result __lockdep_lock_release(struct lockdep_lock_head *owned, uintptr_t id) { struct lockdep_lock *lock = NULL; TAILQ_FOREACH_REVERSE(lock, owned, lockdep_lock_head, link) { if (lock->node->lock_id == id) { TAILQ_REMOVE(owned, lock, link); free(lock->call_stack); free(lock); return TEE_SUCCESS; } } EMSG_RAW("Thread %p does not own lock %#" PRIxPTR, (void *)owned, id); return TEE_ERROR_ITEM_NOT_FOUND; } static void lockdep_free_edge(struct lockdep_edge *edge) { free(edge->call_stack_from); free(edge->call_stack_to); free(edge); } static void lockdep_node_delete(struct lockdep_node *node) { struct lockdep_edge *edge = NULL; struct lockdep_edge *next = NULL; STAILQ_FOREACH_SAFE(edge, &node->edges, link, next) lockdep_free_edge(edge); free(node); } void lockdep_graph_delete(struct lockdep_node_head *graph) { struct lockdep_node *node = NULL; struct lockdep_node *next = NULL; TAILQ_FOREACH_SAFE(node, graph, link, next) { TAILQ_REMOVE(graph, node, link); lockdep_node_delete(node); } } void lockdep_queue_delete(struct lockdep_lock_head *owned) { struct lockdep_lock *lock = NULL; struct lockdep_lock *next = NULL; TAILQ_FOREACH_SAFE(lock, owned, link, next) { TAILQ_REMOVE(owned, lock, link); free(lock); } } static void lockdep_node_destroy(struct lockdep_node_head *graph, struct lockdep_node *node) { struct lockdep_edge *edge = NULL; struct lockdep_edge *next = NULL; struct lockdep_node *from = NULL; TAILQ_REMOVE(graph, node, link); /* * Loop over all nodes in the graph to remove all edges with the * node to remove in the "to" field. */ TAILQ_FOREACH(from, graph, link) { edge = STAILQ_FIRST(&from->edges); while (edge && edge->to == node) { STAILQ_REMOVE_HEAD(&from->edges, link); lockdep_free_edge(edge); edge = STAILQ_FIRST(&from->edges); } if (!edge) continue; next = STAILQ_NEXT(edge, link); while (next) { if (next->to == node) { STAILQ_REMOVE_AFTER(&from->edges, edge, link); lockdep_free_edge(next); } else { edge = next; } next = STAILQ_NEXT(edge, link); } } STAILQ_FOREACH_SAFE(edge, &node->edges, link, next) lockdep_free_edge(edge); free(node); } void lockdep_lock_destroy(struct lockdep_node_head *graph, uintptr_t lock_id) { struct lockdep_node *node = NULL; assert(graph); TAILQ_FOREACH(node, graph, link) { if (node->lock_id == lock_id) { lockdep_node_destroy(graph, node); break; } } } optee_os-4.3.0/core/kernel/msg_param.c000066400000000000000000000102711464416617300176720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, EPAM Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include /** * msg_param_extract_pages() - extract list of pages from * OPTEE_MSG_ATTR_NONCONTIG buffer. * * @buffer: pointer to parameters array * @pages: output array of page addresses * @num_pages: number of pages in array * * return: * true on success, false otherwise * * @buffer points to the physical address of a structure that can be viewed as * * struct page_data { * uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1]; * uint64_t next_page_data; * }; * * So, it is a linked list of arrays, where each element of linked list fits * exactly into one 4K page. * * This function extracts data from arrays into one array pointed by @pages * * @buffer points to data shared with normal world, so some precautions * should be taken. */ static bool msg_param_extract_pages(paddr_t buffer, paddr_t *pages, size_t num_pages) { size_t cnt; struct mobj *mobj; paddr_t page; uint64_t *va; bool ret = false; if (buffer & SMALL_PAGE_MASK) return false; /* * There we map first page of array. * mobj_mapped_shm_alloc() will check if page resides in nonsec ddr */ mobj = mobj_mapped_shm_alloc(&buffer, 1, 0, 0); if (!mobj) return false; va = mobj_get_va(mobj, 0, SMALL_PAGE_SIZE); assert(va); for (cnt = 0; cnt < num_pages; cnt++, va++) { /* * If we about to roll over page boundary, then last entry holds * address of next page of array. Unmap current page and map * next one */ if (!((vaddr_t)(va + 1) & SMALL_PAGE_MASK)) { page = *va; if (page & SMALL_PAGE_MASK) goto out; mobj_put(mobj); mobj = mobj_mapped_shm_alloc(&page, 1, 0, 0); if (!mobj) goto out; va = mobj_get_va(mobj, 0, SMALL_PAGE_SIZE); assert(va); } pages[cnt] = *va; if (pages[cnt] & SMALL_PAGE_MASK) goto out; } ret = true; out: mobj_put(mobj); return ret; } struct mobj *msg_param_mobj_from_noncontig(paddr_t buf_ptr, size_t size, uint64_t shm_ref, bool map_buffer) { struct mobj *mobj = NULL; paddr_t *pages = NULL; paddr_t page_offset = 0; size_t num_pages = 0; size_t size_plus_offs = 0; size_t msize = 0; page_offset = buf_ptr & SMALL_PAGE_MASK; if (ADD_OVERFLOW(size, page_offset, &size_plus_offs)) return NULL; num_pages = (size_plus_offs - 1) / SMALL_PAGE_SIZE + 1; if (MUL_OVERFLOW(num_pages, sizeof(paddr_t), &msize)) return NULL; pages = malloc(msize); if (!pages) return NULL; if (!msg_param_extract_pages(buf_ptr & ~SMALL_PAGE_MASK, pages, num_pages)) goto out; if (map_buffer) mobj = mobj_mapped_shm_alloc(pages, num_pages, page_offset, shm_ref); else mobj = mobj_reg_shm_alloc(pages, num_pages, page_offset, shm_ref); out: free(pages); return mobj; } optee_os-4.3.0/core/kernel/mutex.c000066400000000000000000000256761464416617300171050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2017, Linaro Limited */ #include #include #include #include #include #include #include #include "mutex_lockdep.h" void mutex_init(struct mutex *m) { *m = (struct mutex)MUTEX_INITIALIZER; } void mutex_init_recursive(struct recursive_mutex *m) { *m = (struct recursive_mutex)RECURSIVE_MUTEX_INITIALIZER; } static void __mutex_lock(struct mutex *m, const char *fname, int lineno) { assert_have_no_spinlock(); assert(thread_get_id_may_fail() != THREAD_ID_INVALID); assert(thread_is_in_normal_mode()); mutex_lock_check(m); while (true) { uint32_t old_itr_status; bool can_lock; struct wait_queue_elem wqe; /* * If the mutex is locked we need to initialize the wqe * before releasing the spinlock to guarantee that we don't * miss the wakeup from mutex_unlock(). * * If the mutex is unlocked we don't need to use the wqe at * all. */ old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); can_lock = !m->state; if (!can_lock) { wq_wait_init(&m->wq, &wqe, false /* wait_read */); } else { m->state = -1; /* write locked */ } cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); if (!can_lock) { /* * Someone else is holding the lock, wait in normal * world for the lock to become available. */ wq_wait_final(&m->wq, &wqe, 0, m, fname, lineno); } else return; } } static void __mutex_lock_recursive(struct recursive_mutex *m, const char *fname, int lineno) { short int ct = thread_get_id(); assert_have_no_spinlock(); assert(thread_is_in_normal_mode()); if (atomic_load_short(&m->owner) == ct) { if (!refcount_inc(&m->lock_depth)) panic(); return; } __mutex_lock(&m->m, fname, lineno); assert(m->owner == THREAD_ID_INVALID); atomic_store_short(&m->owner, ct); refcount_set(&m->lock_depth, 1); } static void __mutex_unlock(struct mutex *m, const char *fname, int lineno) { uint32_t old_itr_status; assert_have_no_spinlock(); assert(thread_get_id_may_fail() != THREAD_ID_INVALID); mutex_unlock_check(m); old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); if (!m->state) panic(); m->state = 0; cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); wq_wake_next(&m->wq, m, fname, lineno); } static void __mutex_unlock_recursive(struct recursive_mutex *m, const char *fname, int lineno) { assert_have_no_spinlock(); assert(m->owner == thread_get_id()); if (refcount_dec(&m->lock_depth)) { /* * Do an atomic store to match the atomic load in * __mutex_lock_recursive() */ atomic_store_short(&m->owner, THREAD_ID_INVALID); __mutex_unlock(&m->m, fname, lineno); } } static bool __mutex_trylock(struct mutex *m, const char *fname __unused, int lineno __unused) { uint32_t old_itr_status; bool can_lock_write; assert_have_no_spinlock(); assert(thread_get_id_may_fail() != THREAD_ID_INVALID); old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); can_lock_write = !m->state; if (can_lock_write) m->state = -1; cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); if (can_lock_write) mutex_trylock_check(m); return can_lock_write; } static void __mutex_read_unlock(struct mutex *m, const char *fname, int lineno) { uint32_t old_itr_status; short new_state; assert_have_no_spinlock(); assert(thread_get_id_may_fail() != THREAD_ID_INVALID); old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); if (m->state <= 0) panic(); m->state--; new_state = m->state; cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); /* Wake eventual waiters if the mutex was unlocked */ if (!new_state) wq_wake_next(&m->wq, m, fname, lineno); } static void __mutex_read_lock(struct mutex *m, const char *fname, int lineno) { assert_have_no_spinlock(); assert(thread_get_id_may_fail() != THREAD_ID_INVALID); assert(thread_is_in_normal_mode()); while (true) { uint32_t old_itr_status; bool can_lock; struct wait_queue_elem wqe; /* * If the mutex is locked we need to initialize the wqe * before releasing the spinlock to guarantee that we don't * miss the wakeup from mutex_unlock(). * * If the mutex is unlocked we don't need to use the wqe at * all. */ old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); can_lock = m->state != -1; if (!can_lock) { wq_wait_init(&m->wq, &wqe, true /* wait_read */); } else { m->state++; /* read_locked */ } cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); if (!can_lock) { /* * Someone else is holding the lock, wait in normal * world for the lock to become available. */ wq_wait_final(&m->wq, &wqe, 0, m, fname, lineno); } else return; } } static bool __mutex_read_trylock(struct mutex *m, const char *fname __unused, int lineno __unused) { uint32_t old_itr_status; bool can_lock; assert_have_no_spinlock(); assert(thread_get_id_may_fail() != THREAD_ID_INVALID); assert(thread_is_in_normal_mode()); old_itr_status = cpu_spin_lock_xsave(&m->spin_lock); can_lock = m->state != -1; if (can_lock) m->state++; cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); return can_lock; } #ifdef CFG_MUTEX_DEBUG void mutex_unlock_debug(struct mutex *m, const char *fname, int lineno) { __mutex_unlock(m, fname, lineno); } void mutex_lock_debug(struct mutex *m, const char *fname, int lineno) { __mutex_lock(m, fname, lineno); } bool mutex_trylock_debug(struct mutex *m, const char *fname, int lineno) { return __mutex_trylock(m, fname, lineno); } void mutex_read_unlock_debug(struct mutex *m, const char *fname, int lineno) { __mutex_read_unlock(m, fname, lineno); } void mutex_read_lock_debug(struct mutex *m, const char *fname, int lineno) { __mutex_read_lock(m, fname, lineno); } bool mutex_read_trylock_debug(struct mutex *m, const char *fname, int lineno) { return __mutex_read_trylock(m, fname, lineno); } void mutex_unlock_recursive_debug(struct recursive_mutex *m, const char *fname, int lineno) { __mutex_unlock_recursive(m, fname, lineno); } void mutex_lock_recursive_debug(struct recursive_mutex *m, const char *fname, int lineno) { __mutex_lock_recursive(m, fname, lineno); } #else void mutex_unlock(struct mutex *m) { __mutex_unlock(m, NULL, -1); } void mutex_unlock_recursive(struct recursive_mutex *m) { __mutex_unlock_recursive(m, NULL, -1); } void mutex_lock(struct mutex *m) { __mutex_lock(m, NULL, -1); } void mutex_lock_recursive(struct recursive_mutex *m) { __mutex_lock_recursive(m, NULL, -1); } bool mutex_trylock(struct mutex *m) { return __mutex_trylock(m, NULL, -1); } void mutex_read_unlock(struct mutex *m) { __mutex_read_unlock(m, NULL, -1); } void mutex_read_lock(struct mutex *m) { __mutex_read_lock(m, NULL, -1); } bool mutex_read_trylock(struct mutex *m) { return __mutex_read_trylock(m, NULL, -1); } #endif void mutex_destroy(struct mutex *m) { /* * Caller guarantees that no one will try to take the mutex so * there's no need to take the spinlock before accessing it. */ if (m->state) panic(); if (!wq_is_empty(&m->wq)) panic("waitqueue not empty"); mutex_destroy_check(m); } void mutex_destroy_recursive(struct recursive_mutex *m) { mutex_destroy(&m->m); } unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m) { assert_have_no_spinlock(); assert(m->owner == thread_get_id()); return refcount_val(&m->lock_depth); } void mutex_pm_aware_init(struct mutex_pm_aware *m) { *m = (struct mutex_pm_aware)MUTEX_PM_AWARE_INITIALIZER; } void mutex_pm_aware_destroy(struct mutex_pm_aware *m) { mutex_destroy(&m->mutex); } void mutex_pm_aware_lock(struct mutex_pm_aware *m) { if (thread_get_id_may_fail() == THREAD_ID_INVALID) { if (!cpu_spin_trylock(&m->lock) || m->mutex.state) panic(); } else { mutex_lock(&m->mutex); if (!thread_spin_trylock(&m->lock)) panic(); } } void mutex_pm_aware_unlock(struct mutex_pm_aware *m) { if (thread_get_id_may_fail() == THREAD_ID_INVALID) { assert(!m->mutex.state); cpu_spin_unlock(&m->lock); } else { thread_spin_unlock(&m->lock); mutex_unlock(&m->mutex); } } void condvar_init(struct condvar *cv) { *cv = (struct condvar)CONDVAR_INITIALIZER; } void condvar_destroy(struct condvar *cv) { if (cv->m && wq_have_condvar(&cv->m->wq, cv)) panic(); condvar_init(cv); } static void cv_signal(struct condvar *cv, bool only_one, const char *fname, int lineno) { uint32_t old_itr_status; struct mutex *m; old_itr_status = cpu_spin_lock_xsave(&cv->spin_lock); m = cv->m; cpu_spin_unlock_xrestore(&cv->spin_lock, old_itr_status); if (m) wq_promote_condvar(&m->wq, cv, only_one, m, fname, lineno); } #ifdef CFG_MUTEX_DEBUG void condvar_signal_debug(struct condvar *cv, const char *fname, int lineno) { cv_signal(cv, true /* only one */, fname, lineno); } void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno) { cv_signal(cv, false /* all */, fname, lineno); } #else void condvar_signal(struct condvar *cv) { cv_signal(cv, true /* only one */, NULL, -1); } void condvar_broadcast(struct condvar *cv) { cv_signal(cv, false /* all */, NULL, -1); } #endif /*CFG_MUTEX_DEBUG*/ static TEE_Result __condvar_wait_timeout(struct condvar *cv, struct mutex *m, uint32_t timeout_ms, const char *fname, int lineno) { TEE_Result res = TEE_SUCCESS; uint32_t old_itr_status = 0; struct wait_queue_elem wqe = { }; short old_state = 0; short new_state = 0; mutex_unlock_check(m); /* Link this condvar to this mutex until reinitialized */ old_itr_status = cpu_spin_lock_xsave(&cv->spin_lock); if (cv->m && cv->m != m) panic("invalid mutex"); cv->m = m; cpu_spin_unlock(&cv->spin_lock); cpu_spin_lock(&m->spin_lock); if (!m->state) panic(); old_state = m->state; /* Add to mutex wait queue as a condvar waiter */ wq_wait_init_condvar(&m->wq, &wqe, cv, m->state > 0); if (m->state > 1) { /* Multiple read locks, remove one */ m->state--; } else { /* Only one lock (read or write), unlock the mutex */ m->state = 0; } new_state = m->state; cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status); /* Wake eventual waiters if the mutex was unlocked */ if (!new_state) wq_wake_next(&m->wq, m, fname, lineno); res = wq_wait_final(&m->wq, &wqe, timeout_ms, m, fname, lineno); if (old_state > 0) mutex_read_lock(m); else mutex_lock(m); return res; } #ifdef CFG_MUTEX_DEBUG void condvar_wait_debug(struct condvar *cv, struct mutex *m, const char *fname, int lineno) { __condvar_wait_timeout(cv, m, 0, fname, lineno); } TEE_Result condvar_wait_timeout_debug(struct condvar *cv, struct mutex *m, uint32_t timeout_ms, const char *fname, int lineno) { return __condvar_wait_timeout(cv, m, timeout_ms, fname, lineno); } #else void condvar_wait(struct condvar *cv, struct mutex *m) { __condvar_wait_timeout(cv, m, 0, NULL, -1); } TEE_Result condvar_wait_timeout(struct condvar *cv, struct mutex *m, uint32_t timeout_ms) { return __condvar_wait_timeout(cv, m, timeout_ms, NULL, -1); } #endif optee_os-4.3.0/core/kernel/mutex_lockdep.c000066400000000000000000000033741464416617300205750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include #include #include #include #include #include #include "mutex_lockdep.h" /* Global graph of all mutexes used in the code */ static struct lockdep_node_head graph = TAILQ_HEAD_INITIALIZER(graph); /* Protects @graph */ static unsigned int graph_lock = SPINLOCK_UNLOCK; /* * One queue per thread, contains the mutexes the thread owns at any point in * time (in aquire order) */ static struct lockdep_lock_head owned[CFG_NUM_THREADS]; void mutex_lockdep_init(void) { int n = 0; for (n = 0; n < CFG_NUM_THREADS; n++) TAILQ_INIT(&owned[n]); DMSG("lockdep is enabled for mutexes"); } void mutex_lock_check(struct mutex *m) { short int thread = thread_get_id(); uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&graph_lock); lockdep_lock_acquire(&graph, &owned[thread], (uintptr_t)m); cpu_spin_unlock_xrestore(&graph_lock, exceptions); } void mutex_trylock_check(struct mutex *m) { short int thread = thread_get_id(); uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&graph_lock); lockdep_lock_tryacquire(&graph, &owned[thread], (uintptr_t)m); cpu_spin_unlock_xrestore(&graph_lock, exceptions); } void mutex_unlock_check(struct mutex *m) { short int thread = thread_get_id(); uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&graph_lock); lockdep_lock_release(&owned[thread], (uintptr_t)m); cpu_spin_unlock_xrestore(&graph_lock, exceptions); } void mutex_destroy_check(struct mutex *m) { uint32_t exceptions = cpu_spin_lock_xsave(&graph_lock); lockdep_lock_destroy(&graph, (uintptr_t)m); cpu_spin_unlock_xrestore(&graph_lock, exceptions); } optee_os-4.3.0/core/kernel/mutex_lockdep.h000066400000000000000000000013121464416617300205700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef MUTEX_LOCKDEP_H #define MUTEX_LOCKDEP_H #include #include #ifdef CFG_LOCKDEP void mutex_lock_check(struct mutex *m); void mutex_trylock_check(struct mutex *m); void mutex_unlock_check(struct mutex *m); void mutex_destroy_check(struct mutex *m); #else static inline void mutex_lock_check(struct mutex *m __unused) {} static inline void mutex_trylock_check(struct mutex *m __unused) {} static inline void mutex_unlock_check(struct mutex *m __unused) {} static inline void mutex_destroy_check(struct mutex *m __unused) {} #endif /* !CFG_LOCKDEP */ #endif /* MUTEX_LOCKDEP_H */ optee_os-4.3.0/core/kernel/notif.c000066400000000000000000000110641464416617300170440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2024, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #if defined(CFG_CORE_ASYNC_NOTIF) struct notif_data { bool notif_started; }; static struct mutex notif_mutex = MUTEX_INITIALIZER; static unsigned int notif_lock __nex_data = SPINLOCK_UNLOCK; static struct notif_data default_notif_data; static unsigned int notif_data_id __nex_bss; SLIST_HEAD(notif_driver_head, notif_driver); static struct notif_driver_head notif_driver_head __nex_data = SLIST_HEAD_INITIALIZER(¬if_driver_head); static struct notif_data *get_notif_data(struct guest_partition *prtn) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { assert(prtn); return virt_get_guest_spec_data(prtn, notif_data_id); } return &default_notif_data; } bool notif_async_is_started(uint16_t guest_id) { struct guest_partition *prtn = virt_get_guest(guest_id); uint32_t old_itr_status = 0; bool ret = false; if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || prtn) { struct notif_data *ndata = get_notif_data(prtn); old_itr_status = cpu_spin_lock_xsave(¬if_lock); ret = ndata->notif_started; cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); } virt_put_guest(prtn); return ret; } void notif_register_driver(struct notif_driver *ndrv) { uint32_t old_itr_status = 0; assert(is_nexus(ndrv) && is_unpaged(ndrv->atomic_cb)); old_itr_status = cpu_spin_lock_xsave(¬if_lock); SLIST_INSERT_HEAD(¬if_driver_head, ndrv, link); cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); } void notif_unregister_driver(struct notif_driver *ndrv) { uint32_t old_itr_status = 0; old_itr_status = cpu_spin_lock_xsave(¬if_lock); SLIST_REMOVE(¬if_driver_head, ndrv, notif_driver, link); cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); } void notif_deliver_atomic_event(enum notif_event ev, uint16_t guest_id) { struct guest_partition *prtn = virt_get_guest(guest_id); struct notif_data *ndata = get_notif_data(prtn); struct notif_driver *nd = NULL; uint32_t old_itr_status = 0; old_itr_status = cpu_spin_lock_xsave(¬if_lock); switch (ev) { case NOTIF_EVENT_STARTED: if (ndata->notif_started) { DMSG("Already started"); goto out; } ndata->notif_started = true; break; case NOTIF_EVENT_SHUTDOWN: break; default: EMSG("Unknown event %d", (int)ev); panic(); } SLIST_FOREACH(nd, ¬if_driver_head, link) if (nd->atomic_cb) nd->atomic_cb(nd, ev, guest_id); out: cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); virt_put_guest(prtn); } void notif_deliver_event(enum notif_event ev) { struct guest_partition *prtn = virt_get_current_guest(); struct notif_data *ndata = get_notif_data(prtn); uint32_t old_itr_status = 0; struct notif_driver *nd = NULL; struct notif_driver *nd_tmp = NULL; assert(ev == NOTIF_EVENT_DO_BOTTOM_HALF || ev == NOTIF_EVENT_STOPPED); /* Serialize all yielding notifications */ mutex_lock(¬if_mutex); old_itr_status = cpu_spin_lock_xsave(¬if_lock); if (!ndata || !ndata->notif_started) { DMSG("Not started ev %d", (int)ev); goto out; } if (ev == NOTIF_EVENT_STOPPED) ndata->notif_started = false; SLIST_FOREACH_SAFE(nd, ¬if_driver_head, link, nd_tmp) { cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); if (nd->yielding_cb) nd->yielding_cb(nd, ev); old_itr_status = cpu_spin_lock_xsave(¬if_lock); if (ev == NOTIF_EVENT_STOPPED && ndata->notif_started) { DMSG("Started again while stopping"); goto out; } } out: cpu_spin_unlock_xrestore(¬if_lock, old_itr_status); mutex_unlock(¬if_mutex); virt_put_guest(prtn); } #endif /*CFG_CORE_ASYNC_NOTIF*/ static TEE_Result notif_rpc(uint32_t func, uint32_t value1, uint32_t value2) { struct thread_param params = THREAD_PARAM_VALUE(IN, func, value1, value2); return thread_rpc_cmd(OPTEE_RPC_CMD_NOTIFICATION, 1, ¶ms); } TEE_Result notif_wait(uint32_t value) { return notif_rpc(OPTEE_RPC_NOTIFICATION_WAIT, value, 0); } TEE_Result notif_send_sync(uint32_t value) { return notif_rpc(OPTEE_RPC_NOTIFICATION_SEND, value, 0); } TEE_Result notif_wait_timeout(uint32_t value, uint32_t timeout_ms) { return notif_rpc(OPTEE_RPC_NOTIFICATION_WAIT, value, timeout_ms); } #ifdef CFG_NS_VIRTUALIZATION static TEE_Result nex_init_notif(void) { return virt_add_guest_spec_data(¬if_data_id, sizeof(struct notif_data), NULL); } nex_early_init(nex_init_notif); #endif optee_os-4.3.0/core/kernel/notif_default.c000066400000000000000000000046111464416617300205500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021-2023, Linaro Limited */ #include #include #include #include #include #include #include static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1); static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1); static unsigned int notif_default_lock = SPINLOCK_UNLOCK; TEE_Result notif_alloc_async_value(uint32_t *val) { static bool alloc_values_inited; uint32_t old_itr_status = 0; int bit = 0; assert(interrupt_can_raise_pi(interrupt_get_main_chip())); old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); if (!alloc_values_inited) { bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF); alloc_values_inited = true; } bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); if (bit >= 0) { *val = bit; bit_set(notif_alloc_values, bit); } cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); if (bit < 0) return TEE_ERROR_OUT_OF_MEMORY; return TEE_SUCCESS; } void notif_free_async_value(uint32_t val) { uint32_t old_itr_status = 0; old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); assert(val < NOTIF_ASYNC_VALUE_MAX); assert(bit_test(notif_alloc_values, val)); bit_clear(notif_alloc_values, val); cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); } uint32_t notif_get_value(bool *value_valid, bool *value_pending) { uint32_t old_itr_status = 0; uint32_t res = 0; int bit = 0; old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); *value_valid = (bit >= 0); if (!*value_valid) { *value_pending = false; goto out; } res = bit; bit_clear(notif_values, res); bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); *value_pending = (bit >= 0); out: cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); return res; } void notif_send_async(uint32_t value, uint16_t guest_id __maybe_unused) { uint32_t old_itr_status = 0; struct itr_chip *itr_chip = interrupt_get_main_chip(); assert(value <= NOTIF_ASYNC_VALUE_MAX && !guest_id); old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); bit_set(notif_values, value); interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID); cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); } optee_os-4.3.0/core/kernel/nv_counter.c000066400000000000000000000005431464416617300201070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Linaro Limited */ #include #include TEE_Result __weak nv_counter_get_ree_fs(uint32_t *value __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } TEE_Result __weak nv_counter_incr_ree_fs_to(uint32_t value __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } optee_os-4.3.0/core/kernel/otp_stubs.c000066400000000000000000000025251464416617300177510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, 2019, Linaro Limited */ #include #include #include #include #include #include /* * Override these in your platform code to really fetch device-unique * bits from e-fuses or whatever. * * The default implementation just sets it to a constant. */ __weak TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey) { memset(&hwkey->data[0], 0, sizeof(hwkey->data)); return TEE_SUCCESS; } __weak int tee_otp_get_die_id(uint8_t *buffer, size_t len) { if (huk_subkey_derive(HUK_SUBKEY_DIE_ID, NULL, 0, buffer, len)) return -1; return 0; } #ifdef CFG_WITH_USER_TA /* * Override this API on your platform to provide TA encryption key as * per your security requirements. There can be two options for this key: * * 1) Unique per device encryption key. * 2) Class wide encryption key. * * The default implementation chooses option (1). */ __weak TEE_Result tee_otp_get_ta_enc_key(uint32_t key_type __maybe_unused, uint8_t *buffer, size_t len) { assert(key_type == SHDR_ENC_KEY_DEV_SPECIFIC); if (huk_subkey_derive(HUK_SUBKEY_TA_ENC, ta_pub_key_modulus, ta_pub_key_modulus_size, buffer, len)) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } #endif optee_os-4.3.0/core/kernel/panic.c000066400000000000000000000045011464416617300170150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include /* SGI number chosen to halt other cores must be in the secure SGI range */ static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || (CFG_HALT_CORES_ON_PANIC_SGI >= 8 && CFG_HALT_CORES_ON_PANIC_SGI < 16)); static enum itr_return __noreturn multi_core_panic_it_handler(struct itr_handler *hdl __unused) { IMSG("Halting CPU %zu", get_core_pos()); while (true) cpu_idle(); } static struct itr_handler multi_core_panic_handler __nex_data = { .it = CFG_HALT_CORES_ON_PANIC_SGI, .handler = multi_core_panic_it_handler, }; DECLARE_KEEP_PAGER(multi_core_panic_handler); static void notify_other_cores(void) { struct itr_chip *chip = interrupt_get_main_chip_may_fail(); if (chip) interrupt_raise_sgi(chip, CFG_HALT_CORES_ON_PANIC_SGI, ITR_CPU_MASK_TO_OTHER_CPUS); else EMSG("Can't notify other cores, main interrupt chip not set"); } static TEE_Result init_multi_core_panic_handler(void) { if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1) return TEE_SUCCESS; if (interrupt_add_handler_with_chip(interrupt_get_main_chip(), &multi_core_panic_handler)) panic(); interrupt_enable(interrupt_get_main_chip(), multi_core_panic_handler.it); return TEE_SUCCESS; } nex_driver_init_late(init_multi_core_panic_handler); void __do_panic(const char *file __maybe_unused, const int line __maybe_unused, const char *func __maybe_unused, const char *msg __maybe_unused) { /* disable preemption */ (void)thread_mask_exceptions(THREAD_EXCP_ALL); /* trace: Panic ['panic-string-message' ]at FILE:LINE []" */ if (!file && !func && !msg) EMSG_RAW("Panic"); else EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s", msg ? "'" : "", msg ? msg : "", msg ? "' " : "", file ? file : "?", file ? line : 0, func ? "<" : "", func ? func : "", func ? ">" : ""); print_kernel_stack(); if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1) notify_other_cores(); /* abort current execution */ while (1) cpu_idle(); } void __weak cpu_idle(void) { } optee_os-4.3.0/core/kernel/pm.c000066400000000000000000000060441464416617300163430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include #include #include #include #include #include #include #define PM_FLAG_SUSPENDED BIT(0) static struct pm_callback_handle *pm_cb_ref; static size_t pm_cb_count; static const char no_name[] = "no-name"; DECLARE_KEEP_PAGER(no_name); static void verify_cb_args(struct pm_callback_handle *pm_hdl) { if (is_unpaged((void *)(vaddr_t)pm_change_state) && (!is_unpaged((void *)(vaddr_t)pm_hdl->callback) || (pm_hdl->handle && !is_unpaged(pm_hdl->handle)))) { EMSG("PM callbacks mandates unpaged arguments: %p %p", (void *)(vaddr_t)pm_hdl->callback, pm_hdl->handle); panic(); } } void register_pm_cb(struct pm_callback_handle *pm_hdl) { struct pm_callback_handle *ref = NULL; const char *name = pm_hdl->name; size_t count = pm_cb_count; verify_cb_args(pm_hdl); if (!name) name = no_name; if (!is_unpaged((void *)name)) { name = strdup(name); if (!name) panic(); } ref = realloc(pm_cb_ref, sizeof(*ref) * (count + 1)); if (!ref) panic(); ref[count] = *pm_hdl; ref[count].flags = 0; ref[count].name = name; pm_cb_count = count + 1; pm_cb_ref = ref; } static TEE_Result do_pm_callback(enum pm_op op, uint32_t pm_hint, struct pm_callback_handle *hdl) { TEE_Result res = TEE_ERROR_GENERIC; bool suspending = op == PM_OP_SUSPEND; if (suspending == (bool)(hdl->flags & PM_FLAG_SUSPENDED)) return TEE_SUCCESS; DMSG("%s %s", suspending ? "Suspend" : "Resume", hdl->name); res = hdl->callback(op, pm_hint, hdl); if (res) { EMSG("%s %s (%p) failed: %#"PRIx32, suspending ? "Suspend" : "Resume", hdl->name, (void *)(vaddr_t)hdl->callback, res); return res; } if (suspending) hdl->flags |= PM_FLAG_SUSPENDED; else hdl->flags &= ~PM_FLAG_SUSPENDED; return TEE_SUCCESS; } static TEE_Result call_callbacks(enum pm_op op, uint32_t pm_hint, enum pm_callback_order order) { struct pm_callback_handle *hdl = NULL; TEE_Result res = TEE_ERROR_GENERIC; size_t n = 0; /* * Suspend first the last registered instances. * Resume first the first registered instances. */ if (op == PM_OP_SUSPEND) hdl = pm_cb_ref + pm_cb_count - 1; else hdl = pm_cb_ref; for (n = 0; n < pm_cb_count; n++) { if (hdl->order == order) { res = do_pm_callback(op, pm_hint, hdl); if (res) return res; } if (op == PM_OP_SUSPEND) hdl--; else hdl++; } return TEE_SUCCESS; } TEE_Result pm_change_state(enum pm_op op, uint32_t pm_hint) { enum pm_callback_order cnt = PM_CB_ORDER_DRIVER; TEE_Result res = TEE_ERROR_GENERIC; switch (op) { case PM_OP_SUSPEND: for (cnt = PM_CB_ORDER_DRIVER; cnt < PM_CB_ORDER_MAX; cnt++) { res = call_callbacks(op, pm_hint, cnt); if (res) return res; } break; case PM_OP_RESUME: for (cnt = PM_CB_ORDER_MAX; cnt > PM_CB_ORDER_DRIVER; cnt--) { res = call_callbacks(op, pm_hint, cnt - 1); if (res) return res; } break; default: panic(); } return TEE_SUCCESS; } optee_os-4.3.0/core/kernel/pseudo_ta.c000066400000000000000000000251031464416617300177070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_SECURE_DATA_PATH static bool client_is_secure(struct ts_session *s) { /* rely on core entry to have constrained client IDs */ if (to_ta_session(s)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) return true; return false; } static bool validate_in_param(struct ts_session *s, struct mobj *mobj) { /* Supplying NULL to query buffer size is OK */ if (!mobj) return true; /* for secure clients, core entry always holds valid memref objects */ if (client_is_secure(s)) return true; /* all non-secure memory references are handled by PTAs */ if (mobj_is_nonsec(mobj)) return true; return false; } #else static bool validate_in_param(struct ts_session *s __unused, struct mobj *mobj __unused) { /* At this point, core has filled only valid accessible memref mobj */ return true; } #endif /* Maps pseudo TA params */ static TEE_Result copy_in_param(struct ts_session *s __maybe_unused, struct tee_ta_param *param, TEE_Param tee_param[TEE_NUM_PARAMS], bool did_map[TEE_NUM_PARAMS]) { size_t n; void *va; struct param_mem *mem; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(param->types, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: tee_param[n].value.a = param->u[n].val.a; tee_param[n].value.b = param->u[n].val.b; break; case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: mem = ¶m->u[n].mem; if (!validate_in_param(s, mem->mobj)) return TEE_ERROR_BAD_PARAMETERS; if (mem->size) { TEE_Result res = mobj_inc_map(mem->mobj); if (res) return res; did_map[n] = true; va = mobj_get_va(mem->mobj, mem->offs, mem->size); if (!va) return TEE_ERROR_BAD_PARAMETERS; } else { va = NULL; } tee_param[n].memref.buffer = va; tee_param[n].memref.size = mem->size; break; default: memset(tee_param + n, 0, sizeof(TEE_Param)); break; } } return TEE_SUCCESS; } static void update_out_param(TEE_Param tee_param[TEE_NUM_PARAMS], struct tee_ta_param *param) { size_t n; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(param->types, n)) { case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: param->u[n].val.a = tee_param[n].value.a; param->u[n].val.b = tee_param[n].value.b; break; case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: param->u[n].mem.size = tee_param[n].memref.size; break; default: break; } } } static void unmap_mapped_param(struct tee_ta_param *param, bool did_map[TEE_NUM_PARAMS]) { size_t n; for (n = 0; n < TEE_NUM_PARAMS; n++) { if (did_map[n]) { TEE_Result res __maybe_unused; res = mobj_dec_map(param->u[n].mem.mobj); assert(!res); } } } static TEE_Result pseudo_ta_enter_open_session(struct ts_session *s) { TEE_Result res = TEE_SUCCESS; struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); struct tee_ta_session *ta_sess = to_ta_session(s); TEE_Param tee_param[TEE_NUM_PARAMS] = { }; bool did_map[TEE_NUM_PARAMS] = { false }; ts_push_current_session(s); ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; if (stc->ctx.ref_count == 1 && stc->pseudo_ta->create_entry_point) { res = stc->pseudo_ta->create_entry_point(); if (res != TEE_SUCCESS) goto out; } if (stc->pseudo_ta->open_session_entry_point) { void **user_ctx = &s->user_ctx; uint32_t param_types = 0; if (ta_sess->param) { res = copy_in_param(s, ta_sess->param, tee_param, did_map); if (res != TEE_SUCCESS) { unmap_mapped_param(ta_sess->param, did_map); ta_sess->err_origin = TEE_ORIGIN_TEE; goto out; } param_types = ta_sess->param->types; } res = stc->pseudo_ta->open_session_entry_point(param_types, tee_param, user_ctx); if (ta_sess->param) { update_out_param(tee_param, ta_sess->param); unmap_mapped_param(ta_sess->param, did_map); } } out: ts_pop_current_session(); return res; } static TEE_Result pseudo_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) { TEE_Result res = TEE_SUCCESS; struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); struct tee_ta_session *ta_sess = to_ta_session(s); uint32_t param_types = 0; TEE_Param tee_param[TEE_NUM_PARAMS] = { }; bool did_map[TEE_NUM_PARAMS] = { false }; ts_push_current_session(s); if (ta_sess->param) { res = copy_in_param(s, ta_sess->param, tee_param, did_map); if (res != TEE_SUCCESS) { unmap_mapped_param(ta_sess->param, did_map); ta_sess->err_origin = TEE_ORIGIN_TEE; goto out; } param_types = ta_sess->param->types; } ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; res = stc->pseudo_ta->invoke_command_entry_point(s->user_ctx, cmd, param_types, tee_param); if (ta_sess->param) { update_out_param(tee_param, ta_sess->param); unmap_mapped_param(ta_sess->param, did_map); } out: ts_pop_current_session(); return res; } static void pseudo_ta_enter_close_session(struct ts_session *s) { struct pseudo_ta_ctx *stc = to_pseudo_ta_ctx(s->ctx); void *user_ctx = s->user_ctx; ts_push_current_session(s); if (stc->pseudo_ta->close_session_entry_point) stc->pseudo_ta->close_session_entry_point(user_ctx); if (stc->ctx.ref_count == 1 && stc->pseudo_ta->destroy_entry_point) stc->pseudo_ta->destroy_entry_point(); ts_pop_current_session(); } static void pseudo_ta_destroy(struct ts_ctx *ctx) { free(to_pseudo_ta_ctx(ctx)); } static const struct ts_ops pseudo_ta_ops = { .enter_open_session = pseudo_ta_enter_open_session, .enter_invoke_cmd = pseudo_ta_enter_invoke_cmd, .enter_close_session = pseudo_ta_enter_close_session, .destroy = pseudo_ta_destroy, }; bool __noprof is_pseudo_ta_ctx(struct ts_ctx *ctx) { return ctx->ops == &pseudo_ta_ops; } /* Insures declared pseudo TAs conforms with core expectations */ static TEE_Result verify_pseudo_tas_conformance(void) { const struct pseudo_ta_head *start = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); const struct pseudo_ta_head *end = SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head); const struct pseudo_ta_head *pta; for (pta = start; pta < end; pta++) { const struct pseudo_ta_head *pta2; /* PTAs must all have a specific UUID */ for (pta2 = pta + 1; pta2 < end; pta2++) { if (!memcmp(&pta->uuid, &pta2->uuid, sizeof(TEE_UUID))) goto err; } if (!pta->name || (pta->flags & PTA_MANDATORY_FLAGS) != PTA_MANDATORY_FLAGS || pta->flags & ~PTA_ALLOWED_FLAGS || !pta->invoke_command_entry_point) goto err; } return TEE_SUCCESS; err: DMSG("pseudo TA error at %p", (void *)pta); panic("PTA"); } service_init(verify_pseudo_tas_conformance); /*----------------------------------------------------------------------------- * Initialises a session based on the UUID or ptr to the ta * Returns ptr to the session (ta_session) and a TEE_Result *---------------------------------------------------------------------------*/ TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid, struct tee_ta_session *s) { struct pseudo_ta_ctx *stc = NULL; struct tee_ta_ctx *ctx; const struct pseudo_ta_head *ta; /* * Caller is expected to hold tee_ta_mutex for safe changes * in @s and registering of the context in tee_ctxes list. */ assert(mutex_is_locked(&tee_ta_mutex)); DMSG("Lookup pseudo TA %pUl", (void *)uuid); ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head); while (true) { if (ta >= SCATTERED_ARRAY_END(pseudo_tas, struct pseudo_ta_head)) return TEE_ERROR_ITEM_NOT_FOUND; if (memcmp(&ta->uuid, uuid, sizeof(TEE_UUID)) == 0) break; ta++; } DMSG("Open %s", ta->name); stc = calloc(1, sizeof(struct pseudo_ta_ctx)); if (!stc) return TEE_ERROR_OUT_OF_MEMORY; ctx = &stc->ctx; ctx->ref_count = 1; ctx->flags = ta->flags; stc->pseudo_ta = ta; ctx->ts_ctx.uuid = ta->uuid; ctx->ts_ctx.ops = &pseudo_ta_ops; s->ts_sess.ctx = &ctx->ts_ctx; TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid); return TEE_SUCCESS; } TEE_Result to_bounce_params(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS], TEE_Param bparams[TEE_NUM_PARAMS], TEE_Param **oparams) { TEE_Result res = TEE_ERROR_GENERIC; void *kptr = NULL; void *uptr = NULL; size_t size = 0; int i = 0; if (!is_caller_ta_with_pan()) { *oparams = params; return TEE_SUCCESS; } for (i = 0; i < TEE_NUM_PARAMS; i++) { switch (TEE_PARAM_TYPE_GET(param_types, i)) { case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: size = params[i].memref.size; uptr = params[i].memref.buffer; kptr = bb_alloc(size); if (!kptr) return TEE_ERROR_OUT_OF_MEMORY; bparams[i].memref.buffer = kptr; bparams[i].memref.size = size; break; default: break; } switch (TEE_PARAM_TYPE_GET(param_types, i)) { case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: res = copy_from_user(kptr, uptr, size); if (res) return res; break; case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_INOUT: bparams[i].value.a = params[i].value.a; bparams[i].value.b = params[i].value.b; break; default: break; } } *oparams = bparams; return TEE_SUCCESS; } TEE_Result from_bounce_params(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS], TEE_Param bparams[TEE_NUM_PARAMS], TEE_Param *eparams) { TEE_Result res = TEE_ERROR_GENERIC; void *kptr = NULL; void *uptr = NULL; size_t size = 0; int i = 0; if (eparams == params) return TEE_SUCCESS; for (i = 0; i < TEE_NUM_PARAMS; i++) { switch (TEE_PARAM_TYPE_GET(param_types, i)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: uptr = params[i].memref.buffer; kptr = bparams[i].memref.buffer; size = bparams[i].memref.size; res = copy_to_user(uptr, kptr, size); if (res) return res; params[i].memref.size = size; break; case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: params[i].value.a = bparams[i].value.a; params[i].value.b = bparams[i].value.b; break; default: break; } } return res; } optee_os-4.3.0/core/kernel/ree_fs_ta.c000066400000000000000000000505371464416617300176640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, 2019, Linaro Limited * Copyright (c) 2020, Arm Limited. */ /* * Security properties of REE-FS TAs * ================================= * * Authentication only * ------------------- * * Required security properties: * 1. Authentication and non-repudiation of a TA to Service Provider (SP). * 2. Integrity of a TA. * * To satisfy (1) and (2), SP needs to sign TA and OP-TEE core needs to verify * the signature using SP public key with computed hash of the TA. * * Authentication along with Confidentiality * ----------------------------------------- * * Required security properties: * 1. Authentication and non-repudiation of a TA to Service Provider (SP). * 2. Confidentiality of a TA. * 3. Integrity of an encrypted TA blob. * * To satisfy (1), SP needs to sign plain TA and OP-TEE core needs to verify the * signature using SP public key with computed hash of the TA. * * To satisfy (2) and (3), SP needs to do authenticated encryption of TA and * OP-TEE core needs to do authenticated decryption of TA to retrieve its * contents. Here encryption provides the confidentiality of TA and MAC tag * provides the integrity of encrypted TA blob. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct ree_fs_ta_handle { struct shdr *nw_ta; /* Non-secure (shared memory) */ size_t nw_ta_size; struct mobj *mobj; size_t offs; struct shdr *shdr; /* Verified secure copy of @nw_ta's signed header */ void *hash_ctx; void *enc_ctx; struct shdr_bootstrap_ta *bs_hdr; struct shdr_encrypted_ta *ehdr; }; struct ver_db_entry { uint8_t uuid[sizeof(TEE_UUID)]; uint32_t version; }; struct ver_db_hdr { uint32_t db_version; uint32_t nb_entries; }; static const char ta_ver_db[] = "ta_ver.db"; static const char subkey_ver_db[] = "subkey_ver.db"; static struct mutex ver_db_mutex = MUTEX_INITIALIZER; static TEE_Result check_update_version(const char *db_name, const uint8_t uuid[sizeof(TEE_UUID)], uint32_t version) { struct ver_db_entry db_entry = { }; const struct tee_file_operations *ops = NULL; struct tee_file_handle *fh = NULL; TEE_Result res = TEE_SUCCESS; bool entry_found = false; size_t len = 0; unsigned int i = 0; struct ver_db_hdr db_hdr = { }; struct tee_pobj pobj = { .obj_id = (void *)db_name, .obj_id_len = strlen(db_name) + 1, }; ops = tee_svc_storage_file_ops(TEE_STORAGE_PRIVATE); if (!ops) return TEE_SUCCESS; /* Compiled with no secure storage */ mutex_lock(&ver_db_mutex); res = ops->open(&pobj, NULL, &fh); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) goto out; if (res == TEE_ERROR_ITEM_NOT_FOUND) { res = ops->create(&pobj, false, NULL, 0, NULL, 0, NULL, NULL, 0, &fh); if (res != TEE_SUCCESS) goto out; res = ops->write(fh, 0, &db_hdr, NULL, sizeof(db_hdr)); if (res != TEE_SUCCESS) goto out; } else { len = sizeof(db_hdr); res = ops->read(fh, 0, &db_hdr, NULL, &len); if (res != TEE_SUCCESS) { goto out; } else if (len != sizeof(db_hdr)) { res = TEE_ERROR_BAD_STATE; goto out; } } for (i = 0; i < db_hdr.nb_entries; i++) { len = sizeof(db_entry); res = ops->read(fh, sizeof(db_hdr) + (i * len), &db_entry, NULL, &len); if (res != TEE_SUCCESS) { goto out; } else if (len != sizeof(db_entry)) { res = TEE_ERROR_BAD_STATE; goto out; } if (!memcmp(uuid, db_entry.uuid, sizeof(TEE_UUID))) { entry_found = true; break; } } if (entry_found) { if (db_entry.version > version) { res = TEE_ERROR_ACCESS_CONFLICT; goto out; } else if (db_entry.version < version) { memcpy(db_entry.uuid, uuid, sizeof(TEE_UUID)); db_entry.version = version; len = sizeof(db_entry); res = ops->write(fh, sizeof(db_hdr) + (i * len), &db_entry, NULL, len); if (res != TEE_SUCCESS) goto out; } } else { memcpy(db_entry.uuid, uuid, sizeof(TEE_UUID)); db_entry.version = version; len = sizeof(db_entry); res = ops->write(fh, sizeof(db_hdr) + (db_hdr.nb_entries * len), &db_entry, NULL, len); if (res != TEE_SUCCESS) goto out; db_hdr.nb_entries++; res = ops->write(fh, 0, &db_hdr, NULL, sizeof(db_hdr)); if (res != TEE_SUCCESS) goto out; } out: ops->close(&fh); mutex_unlock(&ver_db_mutex); return res; } /* * Load a TA via RPC with UUID defined by input param @uuid. The virtual * address of the raw TA binary is received in out parameter @ta. */ static TEE_Result rpc_load(const TEE_UUID *uuid, struct shdr **ta, size_t *ta_size, struct mobj **mobj) { TEE_Result res; struct thread_param params[2]; if (!uuid || !ta || !mobj || !ta_size) return TEE_ERROR_BAD_PARAMETERS; memset(params, 0, sizeof(params)); params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); if (res != TEE_SUCCESS) return res; *mobj = thread_rpc_alloc_payload(params[1].u.memref.size); if (!*mobj) return TEE_ERROR_OUT_OF_MEMORY; *ta = mobj_get_va(*mobj, 0, params[1].u.memref.size); if (!*ta) { res = TEE_ERROR_SHORT_BUFFER; goto exit; } /* We don't expect NULL as thread_rpc_alloc_payload() was successful */ assert(*ta); *ta_size = params[1].u.memref.size; params[0].attr = THREAD_PARAM_ATTR_VALUE_IN; tee_uuid_to_octets((void *)¶ms[0].u.value, uuid); params[1].attr = THREAD_PARAM_ATTR_MEMREF_OUT; params[1].u.memref.offs = 0; params[1].u.memref.mobj = *mobj; res = thread_rpc_cmd(OPTEE_RPC_CMD_LOAD_TA, 2, params); exit: if (res != TEE_SUCCESS) thread_rpc_free_payload(*mobj); return res; } static TEE_Result ree_fs_ta_open(const TEE_UUID *uuid, struct ts_store_handle **h) { uint8_t next_uuid[sizeof(TEE_UUID)] = { }; struct ree_fs_ta_handle *handle; uint8_t *next_uuid_ptr = NULL; struct shdr *shdr = NULL; struct mobj *mobj = NULL; void *hash_ctx = NULL; struct shdr *ta = NULL; size_t ta_size = 0; TEE_Result res = TEE_SUCCESS; size_t offs = 0; struct shdr_bootstrap_ta *bs_hdr = NULL; struct shdr_encrypted_ta *ehdr = NULL; size_t shdr_sz = 0; uint32_t max_depth = UINT32_MAX; struct ftmn ftmn = { }; unsigned int incr0_count = 0; handle = calloc(1, sizeof(*handle)); if (!handle) return TEE_ERROR_OUT_OF_MEMORY; /* Request TA from tee-supplicant */ res = rpc_load(uuid, &ta, &ta_size, &mobj); if (res != TEE_SUCCESS) goto error; /* Make secure copy of signed header */ shdr = shdr_alloc_and_copy(0, ta, ta_size); if (!shdr) { res = TEE_ERROR_SECURITY; goto error_free_payload; } /* Validate header signature */ FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, shdr_verify_signature, shdr); incr0_count++; if (res != TEE_SUCCESS) goto error_free_payload; shdr_sz = SHDR_GET_SIZE(shdr); if (!shdr_sz) { res = TEE_ERROR_SECURITY; goto error_free_payload; } offs = shdr_sz; while (shdr->img_type == SHDR_SUBKEY) { struct shdr_pub_key pub_key = { }; if (offs > ta_size) { res = TEE_ERROR_SECURITY; goto error_free_payload; } res = shdr_load_pub_key(shdr, offs, (const void *)ta, ta_size, next_uuid_ptr, max_depth, &pub_key); if (res) goto error_free_payload; if (ADD_OVERFLOW(offs, shdr->img_size, &offs) || ADD_OVERFLOW(offs, pub_key.name_size, &offs) || offs > ta_size) { res = TEE_ERROR_SECURITY; goto error_free_payload; } max_depth = pub_key.max_depth; memcpy(next_uuid, pub_key.next_uuid, sizeof(TEE_UUID)); next_uuid_ptr = next_uuid; res = check_update_version(subkey_ver_db, pub_key.uuid, pub_key.version); if (res) { res = TEE_ERROR_SECURITY; shdr_free_pub_key(&pub_key); goto error_free_payload; } shdr_free(shdr); shdr = shdr_alloc_and_copy(offs, ta, ta_size); res = TEE_ERROR_SECURITY; if (shdr) { FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, shdr_verify_signature2, &pub_key, shdr); incr0_count++; } shdr_free_pub_key(&pub_key); if (res) goto error_free_payload; shdr_sz = SHDR_GET_SIZE(shdr); if (!shdr_sz) { res = TEE_ERROR_SECURITY; goto error_free_payload; } offs += shdr_sz; if (offs > ta_size) { res = TEE_ERROR_SECURITY; goto error_free_payload; } } if (shdr->img_type != SHDR_TA && shdr->img_type != SHDR_BOOTSTRAP_TA && shdr->img_type != SHDR_ENCRYPTED_TA) { res = TEE_ERROR_SECURITY; goto error_free_payload; } /* * If we're verifying this TA using a subkey, make sure that * the UUID of the TA belongs to the namespace defined by the subkey. * The namespace is defined as in RFC4122, that is, valid UUID * is calculated as a V5 UUID SHA-512(subkey UUID, "name string"). */ if (next_uuid_ptr) { TEE_UUID check_uuid = { }; tee_uuid_from_octets(&check_uuid, next_uuid_ptr); if (memcmp(&check_uuid, uuid, sizeof(*uuid))) { res = TEE_ERROR_SECURITY; goto error_free_payload; } } /* * Initialize a hash context and run the algorithm over the signed * header (less the final file hash and its signature of course) */ res = crypto_hash_alloc_ctx(&hash_ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo)); if (res != TEE_SUCCESS) goto error_free_payload; res = crypto_hash_init(hash_ctx); if (res != TEE_SUCCESS) goto error_free_hash; res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr)); if (res != TEE_SUCCESS) goto error_free_hash; if (shdr->img_type == SHDR_BOOTSTRAP_TA || shdr->img_type == SHDR_ENCRYPTED_TA) { TEE_UUID bs_uuid = { }; size_t sz = shdr_sz; if (ADD_OVERFLOW(sz, sizeof(*bs_hdr), &sz) || ta_size < sz) { res = TEE_ERROR_SECURITY; goto error_free_hash; } bs_hdr = malloc(sizeof(*bs_hdr)); if (!bs_hdr) { res = TEE_ERROR_OUT_OF_MEMORY; goto error_free_hash; } memcpy(bs_hdr, (uint8_t *)ta + offs, sizeof(*bs_hdr)); /* * There's a check later that the UUID embedded inside the * ELF is matching, but since we now have easy access to * the expected uuid of the TA we check it a bit earlier * here. */ tee_uuid_from_octets(&bs_uuid, bs_hdr->uuid); if (memcmp(&bs_uuid, uuid, sizeof(TEE_UUID))) { res = TEE_ERROR_SECURITY; goto error_free_hash; } res = crypto_hash_update(hash_ctx, (uint8_t *)bs_hdr, sizeof(*bs_hdr)); if (res != TEE_SUCCESS) goto error_free_hash; offs += sizeof(*bs_hdr); handle->bs_hdr = bs_hdr; } if (shdr->img_type == SHDR_ENCRYPTED_TA) { struct shdr_encrypted_ta img_ehdr = { }; size_t sz = shdr_sz; size_t ehdr_sz = 0; if (ADD_OVERFLOW(sz, sizeof(struct shdr_bootstrap_ta), &sz) || ADD_OVERFLOW(sz, sizeof(img_ehdr), &sz) || ta_size < sz) { res = TEE_ERROR_SECURITY; goto error_free_hash; } memcpy(&img_ehdr, ((uint8_t *)ta + offs), sizeof(img_ehdr)); ehdr_sz = SHDR_ENC_GET_SIZE(&img_ehdr); sz -= sizeof(img_ehdr); if (!ehdr_sz || ADD_OVERFLOW(sz, ehdr_sz, &sz) || ta_size < sz) { res = TEE_ERROR_SECURITY; goto error_free_hash; } /* * This is checked further down too, but we must sanity * check shdr->img_size before it's used below. */ if (ta_size != offs + ehdr_sz + shdr->img_size) { res = TEE_ERROR_SECURITY; goto error_free_hash; } ehdr = malloc(ehdr_sz); if (!ehdr) { res = TEE_ERROR_OUT_OF_MEMORY; goto error_free_hash; } *ehdr = img_ehdr; memcpy((uint8_t *)ehdr + sizeof(img_ehdr), (uint8_t *)ta + offs + sizeof(img_ehdr), ehdr_sz - sizeof(img_ehdr)); res = crypto_hash_update(hash_ctx, (uint8_t *)ehdr, ehdr_sz); if (res != TEE_SUCCESS) goto error_free_hash; res = tee_ta_decrypt_init(&handle->enc_ctx, ehdr, shdr->img_size); if (res != TEE_SUCCESS) goto error_free_hash; offs += ehdr_sz; handle->ehdr = ehdr; } if (ta_size != offs + shdr->img_size) { res = TEE_ERROR_SECURITY; goto error_free_hash; } handle->nw_ta = ta; handle->nw_ta_size = ta_size; handle->offs = offs; handle->hash_ctx = hash_ctx; handle->shdr = shdr; handle->mobj = mobj; *h = (struct ts_store_handle *)handle; FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(incr0_count), TEE_SUCCESS); return TEE_SUCCESS; error_free_hash: crypto_hash_free_ctx(hash_ctx); error_free_payload: thread_rpc_free_payload(mobj); error: free(ehdr); free(bs_hdr); shdr_free(shdr); free(handle); FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR1, res); FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(incr0_count, 1), res); return res; } static TEE_Result ree_fs_ta_get_size(const struct ts_store_handle *h, size_t *size) { struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; *size = handle->shdr->img_size; return TEE_SUCCESS; } static TEE_Result ree_fs_ta_get_tag(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len) { struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; if (!tag || *tag_len < handle->shdr->hash_size) { *tag_len = handle->shdr->hash_size; return TEE_ERROR_SHORT_BUFFER; } *tag_len = handle->shdr->hash_size; memcpy(tag, SHDR_GET_HASH(handle->shdr), handle->shdr->hash_size); return TEE_SUCCESS; } static TEE_Result check_digest(struct ree_fs_ta_handle *h) { void *digest = NULL; TEE_Result res; digest = malloc(h->shdr->hash_size); if (!digest) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_hash_final(h->hash_ctx, digest, h->shdr->hash_size); if (res != TEE_SUCCESS) { res = TEE_ERROR_SECURITY; goto out; } if (FTMN_CALLEE_DONE_MEMCMP(memcmp, digest, SHDR_GET_HASH(h->shdr), h->shdr->hash_size)) res = TEE_ERROR_SECURITY; out: free(digest); return res; } static TEE_Result ree_fs_ta_read(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) { struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; uint8_t *src = (uint8_t *)handle->nw_ta + handle->offs; size_t bb_len = MIN(1024U, len); size_t next_offs = 0; TEE_Result res = TEE_SUCCESS; size_t num_bytes = 0; size_t dst_len = 0; void *dst = NULL; void *bb = NULL; if (ADD_OVERFLOW(handle->offs, len, &next_offs) || next_offs > handle->nw_ta_size) return TEE_ERROR_BAD_PARAMETERS; if (data_core) { dst = data_core; dst_len = len; } else { bb = bb_alloc(bb_len); if (!bb) return TEE_ERROR_OUT_OF_MEMORY; dst = bb; dst_len = bb_len; } /* * This loop will only run once if data_core is non-NULL, but as * many times as needed if the bounce buffer bb is used. That's why * dst doesn't need to be updated in the loop. */ while (num_bytes < len) { size_t n = MIN(dst_len, len - num_bytes); if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { res = tee_ta_decrypt_update(handle->enc_ctx, dst, src + num_bytes, n); if (res) { res = TEE_ERROR_SECURITY; goto out; } } else { memcpy(dst, src + num_bytes, n); } res = crypto_hash_update(handle->hash_ctx, dst, n); if (res) { res = TEE_ERROR_SECURITY; goto out; } if (data_user) { res = copy_to_user((uint8_t *)data_user + num_bytes, dst, n); if (res) { res = TEE_ERROR_SECURITY; goto out; } } num_bytes += n; } handle->offs = next_offs; if (handle->offs == handle->nw_ta_size) { if (handle->shdr->img_type == SHDR_ENCRYPTED_TA) { /* * Last read: time to finalize authenticated * decryption. */ res = tee_ta_decrypt_final(handle->enc_ctx, handle->ehdr, NULL, NULL, 0); if (res != TEE_SUCCESS) { res = TEE_ERROR_SECURITY; goto out; } } /* * Last read: time to check if our digest matches the expected * one (from the signed header) */ res = check_digest(handle); if (res != TEE_SUCCESS) goto out; if (handle->bs_hdr) res = check_update_version(ta_ver_db, handle->bs_hdr->uuid, handle->bs_hdr->ta_version); } out: bb_free(bb, bb_len); return res; } static void ree_fs_ta_close(struct ts_store_handle *h) { struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; if (!handle) return; thread_rpc_free_payload(handle->mobj); crypto_hash_free_ctx(handle->hash_ctx); free(handle->shdr); free(handle->ehdr); free(handle->bs_hdr); free(handle); } #ifndef CFG_REE_FS_TA_BUFFERED REGISTER_TA_STORE(9) = { .description = "REE", .open = ree_fs_ta_open, .get_size = ree_fs_ta_get_size, .get_tag = ree_fs_ta_get_tag, .read = ree_fs_ta_read, .close = ree_fs_ta_close, }; #endif #ifdef CFG_REE_FS_TA_BUFFERED /* * This is a wrapper around the "REE FS" TA store. * The whole TA/library is read into a temporary buffer during .open(). This * allows the binary to be authenticated before any data is read and processed * by the upper layer (ELF loader). */ struct buf_ree_fs_ta_handle { struct ts_store_handle *h; /* Note: a REE FS TA store handle */ size_t ta_size; tee_mm_entry_t *mm; uint8_t *buf; size_t offs; uint8_t *tag; unsigned int tag_len; }; static TEE_Result buf_ta_open(const TEE_UUID *uuid, struct ts_store_handle **h) { struct buf_ree_fs_ta_handle *handle = NULL; struct ftmn ftmn = { }; TEE_Result res = TEE_SUCCESS; handle = calloc(1, sizeof(*handle)); if (!handle) return TEE_ERROR_OUT_OF_MEMORY; FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("ree_fs_ta_open")); res = ree_fs_ta_open(uuid, &handle->h); if (!res) FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res); FTMN_POP_LINKED_CALL(&ftmn); if (res) goto err_free_handle; ftmn_checkpoint(&ftmn, FTMN_INCR1); res = ree_fs_ta_get_size(handle->h, &handle->ta_size); if (res) goto err; res = ree_fs_ta_get_tag(handle->h, NULL, &handle->tag_len); if (res != TEE_ERROR_SHORT_BUFFER) { res = TEE_ERROR_GENERIC; goto err; } handle->tag = malloc(handle->tag_len); if (!handle->tag) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } res = ree_fs_ta_get_tag(handle->h, handle->tag, &handle->tag_len); if (res) goto err; handle->mm = tee_mm_alloc(&tee_mm_sec_ddr, handle->ta_size); if (!handle->mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } handle->buf = phys_to_virt(tee_mm_get_smem(handle->mm), MEM_AREA_TA_RAM, handle->ta_size); if (!handle->buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("check_digest")); res = ree_fs_ta_read(handle->h, handle->buf, NULL, handle->ta_size); if (!res) FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res); FTMN_POP_LINKED_CALL(&ftmn); if (res) goto err; ftmn_checkpoint(&ftmn, FTMN_INCR1); *h = (struct ts_store_handle *)handle; ree_fs_ta_close(handle->h); return ftmn_return_res(&ftmn, FTMN_STEP_COUNT(2, 2), TEE_SUCCESS); err: ree_fs_ta_close(handle->h); tee_mm_free(handle->mm); free(handle->tag); err_free_handle: free(handle); return res; } static TEE_Result buf_ta_get_size(const struct ts_store_handle *h, size_t *size) { struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; *size = handle->ta_size; return TEE_SUCCESS; } static TEE_Result buf_ta_read(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) { struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; uint8_t *src = handle->buf + handle->offs; TEE_Result res = TEE_SUCCESS; size_t next_offs = 0; if (ADD_OVERFLOW(handle->offs, len, &next_offs) || next_offs > handle->ta_size) return TEE_ERROR_BAD_PARAMETERS; if (data_core) memcpy(data_core, src, len); if (data_user) { res = copy_to_user(data_user, src, len); if (res) return res; } handle->offs = next_offs; return TEE_SUCCESS; } static TEE_Result buf_ta_get_tag(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len) { struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; *tag_len = handle->tag_len; if (!tag || *tag_len < handle->tag_len) return TEE_ERROR_SHORT_BUFFER; memcpy(tag, handle->tag, handle->tag_len); return TEE_SUCCESS; } static void buf_ta_close(struct ts_store_handle *h) { struct buf_ree_fs_ta_handle *handle = (struct buf_ree_fs_ta_handle *)h; if (!handle) return; tee_mm_free(handle->mm); free(handle->tag); free(handle); } REGISTER_TA_STORE(9) = { .description = "REE [buffered]", .open = buf_ta_open, .get_size = buf_ta_get_size, .get_tag = buf_ta_get_tag, .read = buf_ta_read, .close = buf_ta_close, }; #endif /* CFG_REE_FS_TA_BUFFERED */ optee_os-4.3.0/core/kernel/refcount.c000066400000000000000000000017111464416617300175500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include bool refcount_inc(struct refcount *r) { unsigned int nval; unsigned int oval = atomic_load_uint(&r->val); while (true) { nval = oval + 1; /* r->val is 0, we can't do anything more. */ if (!oval) return false; if (atomic_cas_uint(&r->val, &oval, nval)) return true; /* * At this point atomic_cas_uint() has updated oval to the * current r->val. */ } } bool refcount_dec(struct refcount *r) { unsigned int nval; unsigned int oval = atomic_load_uint(&r->val); while (true) { assert(oval); nval = oval - 1; if (atomic_cas_uint(&r->val, &oval, nval)) { /* * Value has been updated, if value was set to 0 * return true to indicate that. */ return !nval; } /* * At this point atomic_cas_uint() has updated oval to the * current r->val. */ } } optee_os-4.3.0/core/kernel/scall.c000066400000000000000000000204631464416617300170260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2022, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (TRACE_LEVEL == TRACE_FLOW) && defined(CFG_TEE_CORE_TA_TRACE) #define TRACE_SYSCALLS #endif struct syscall_entry { syscall_t fn; #ifdef TRACE_SYSCALLS const char *name; #endif }; #ifdef TRACE_SYSCALLS #define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn, .name = #_fn } #else #define SYSCALL_ENTRY(_fn) { .fn = (syscall_t)_fn } #endif /* * This array is ordered according to the SYSCALL ids TEE_SCN_xxx */ static const struct syscall_entry tee_syscall_table[] = { SYSCALL_ENTRY(syscall_sys_return), SYSCALL_ENTRY(syscall_log), SYSCALL_ENTRY(syscall_panic), SYSCALL_ENTRY(syscall_get_property), SYSCALL_ENTRY(syscall_get_property_name_to_index), SYSCALL_ENTRY(syscall_open_ta_session), SYSCALL_ENTRY(syscall_close_ta_session), SYSCALL_ENTRY(syscall_invoke_ta_command), SYSCALL_ENTRY(syscall_check_access_rights), SYSCALL_ENTRY(syscall_get_cancellation_flag), SYSCALL_ENTRY(syscall_unmask_cancellation), SYSCALL_ENTRY(syscall_mask_cancellation), SYSCALL_ENTRY(syscall_wait), SYSCALL_ENTRY(syscall_get_time), SYSCALL_ENTRY(syscall_set_ta_time), SYSCALL_ENTRY(syscall_cryp_state_alloc), SYSCALL_ENTRY(syscall_cryp_state_copy), SYSCALL_ENTRY(syscall_cryp_state_free), SYSCALL_ENTRY(syscall_hash_init), SYSCALL_ENTRY(syscall_hash_update), SYSCALL_ENTRY(syscall_hash_final), SYSCALL_ENTRY(syscall_cipher_init), SYSCALL_ENTRY(syscall_cipher_update), SYSCALL_ENTRY(syscall_cipher_final), SYSCALL_ENTRY(syscall_cryp_obj_get_info), SYSCALL_ENTRY(syscall_cryp_obj_restrict_usage), SYSCALL_ENTRY(syscall_cryp_obj_get_attr), SYSCALL_ENTRY(syscall_cryp_obj_alloc), SYSCALL_ENTRY(syscall_cryp_obj_close), SYSCALL_ENTRY(syscall_cryp_obj_reset), SYSCALL_ENTRY(syscall_cryp_obj_populate), SYSCALL_ENTRY(syscall_cryp_obj_copy), SYSCALL_ENTRY(syscall_cryp_derive_key), SYSCALL_ENTRY(syscall_cryp_random_number_generate), SYSCALL_ENTRY(syscall_authenc_init), SYSCALL_ENTRY(syscall_authenc_update_aad), SYSCALL_ENTRY(syscall_authenc_update_payload), SYSCALL_ENTRY(syscall_authenc_enc_final), SYSCALL_ENTRY(syscall_authenc_dec_final), SYSCALL_ENTRY(syscall_asymm_operate), SYSCALL_ENTRY(syscall_asymm_verify), SYSCALL_ENTRY(syscall_storage_obj_open), SYSCALL_ENTRY(syscall_storage_obj_create), SYSCALL_ENTRY(syscall_storage_obj_del), SYSCALL_ENTRY(syscall_storage_obj_rename), SYSCALL_ENTRY(syscall_storage_alloc_enum), SYSCALL_ENTRY(syscall_storage_free_enum), SYSCALL_ENTRY(syscall_storage_reset_enum), SYSCALL_ENTRY(syscall_storage_start_enum), SYSCALL_ENTRY(syscall_storage_next_enum), SYSCALL_ENTRY(syscall_storage_obj_read), SYSCALL_ENTRY(syscall_storage_obj_write), SYSCALL_ENTRY(syscall_storage_obj_trunc), SYSCALL_ENTRY(syscall_storage_obj_seek), SYSCALL_ENTRY(syscall_obj_generate_key), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_not_supported), SYSCALL_ENTRY(syscall_cache_operation), }; /* * The ldelf return, log, panic syscalls have the same functionality and syscall * number as the user TAs'. To avoid unnecessary code duplication, the ldelf SVC * handler doesn't implement separate functions for these. */ static const struct syscall_entry ldelf_syscall_table[] = { SYSCALL_ENTRY(syscall_sys_return), SYSCALL_ENTRY(syscall_log), SYSCALL_ENTRY(syscall_panic), SYSCALL_ENTRY(ldelf_syscall_map_zi), SYSCALL_ENTRY(ldelf_syscall_unmap), SYSCALL_ENTRY(ldelf_syscall_open_bin), SYSCALL_ENTRY(ldelf_syscall_close_bin), SYSCALL_ENTRY(ldelf_syscall_map_bin), SYSCALL_ENTRY(ldelf_syscall_copy_from_bin), SYSCALL_ENTRY(ldelf_syscall_set_prot), SYSCALL_ENTRY(ldelf_syscall_remap), SYSCALL_ENTRY(ldelf_syscall_gen_rnd_num), }; #ifdef TRACE_SYSCALLS static void trace_syscall(size_t num) { if (num == TEE_SCN_RETURN || num == TEE_SCN_LOG || num > TEE_SCN_MAX) return; FMSG("syscall #%zu (%s)", num, tee_syscall_table[num].name); } #else static void trace_syscall(size_t num __unused) { } #endif #ifdef CFG_SYSCALL_FTRACE static void __noprof ftrace_syscall_enter(size_t num) { struct ts_session *s = NULL; /* * Syscalls related to inter-TA communication can't be traced in the * caller TA's ftrace buffer as it involves context switching to callee * TA's context. Moreover, user can enable ftrace for callee TA to dump * function trace in corresponding ftrace buffer. */ if (num == TEE_SCN_OPEN_TA_SESSION || num == TEE_SCN_CLOSE_TA_SESSION || num == TEE_SCN_INVOKE_TA_COMMAND) return; s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); if (s && s->fbuf) s->fbuf->syscall_trace_enabled = true; } static void __noprof ftrace_syscall_leave(void) { struct ts_session *s = TAILQ_FIRST(&thread_get_tsd()->sess_stack); if (s && s->fbuf) s->fbuf->syscall_trace_enabled = false; } #else static void __noprof ftrace_syscall_enter(size_t num __unused) { } static void __noprof ftrace_syscall_leave(void) { } #endif static syscall_t get_tee_syscall_func(size_t num) { /* Cast away const */ struct syscall_entry *sc_table = (void *)tee_syscall_table; static_assert(ARRAY_SIZE(tee_syscall_table) == (TEE_SCN_MAX + 1)); if (num > TEE_SCN_MAX) return (syscall_t)syscall_not_supported; return load_no_speculate(&sc_table[num].fn, &sc_table[0].fn, &sc_table[TEE_SCN_MAX].fn + 1); } bool scall_handle_user_ta(struct thread_scall_regs *regs) { size_t scn = 0; size_t max_args = 0; syscall_t scf = NULL; bb_reset(); scall_get_max_args(regs, &scn, &max_args); trace_syscall(scn); if (max_args > TEE_SVC_MAX_ARGS) { DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args); scall_set_retval(regs, TEE_ERROR_GENERIC); return true; /* return to user mode */ } scf = get_tee_syscall_func(scn); ftrace_syscall_enter(scn); scall_set_retval(regs, scall_do_call(regs, scf)); ftrace_syscall_leave(); /* * Return true if we're to return to user mode, * thread_scall_handler() will take care of the rest. */ return scn != TEE_SCN_RETURN && scn != TEE_SCN_PANIC; } static syscall_t get_ldelf_syscall_func(size_t num) { /* Cast away const */ struct syscall_entry *sc_table = (void *)ldelf_syscall_table; COMPILE_TIME_ASSERT(ARRAY_SIZE(ldelf_syscall_table) == (LDELF_SCN_MAX + 1)); if (num > LDELF_SCN_MAX) return (syscall_t)syscall_not_supported; return load_no_speculate(&sc_table[num].fn, &sc_table[0].fn, &sc_table[LDELF_SCN_MAX].fn + 1); } bool scall_handle_ldelf(struct thread_scall_regs *regs) { size_t scn = 0; size_t max_args = 0; syscall_t scf = NULL; bb_reset(); scall_get_max_args(regs, &scn, &max_args); trace_syscall(scn); if (max_args > TEE_SVC_MAX_ARGS) { DMSG("Too many arguments for SCN %zu (%zu)", scn, max_args); scall_set_retval(regs, TEE_ERROR_GENERIC); return true; /* return to user mode */ } scf = get_ldelf_syscall_func(scn); ftrace_syscall_enter(scn); scall_set_retval(regs, scall_do_call(regs, scf)); ftrace_syscall_leave(); /* * Return true if we're to return to user mode, * thread_scall_handler() will take care of the rest. */ return scn != LDELF_RETURN && scn != LDELF_PANIC; } uint32_t scall_sys_return_helper(uint32_t ret, bool panic, uint32_t panic_code, struct thread_scall_regs *regs) { if (panic) { TAMSG_RAW(""); TAMSG_RAW("TA panicked with code 0x%" PRIx32, panic_code); scall_save_panic_stack(regs); } scall_set_sys_return_regs(regs, panic, panic_code); return ret; } optee_os-4.3.0/core/kernel/scattered_array.c000066400000000000000000000002711464416617300210770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include const void *scattered_array_relax_ptr(const void *p) { return p; } optee_os-4.3.0/core/kernel/secstor_ta.c000066400000000000000000000036361464416617300201010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include static TEE_Result secstor_ta_open(const TEE_UUID *uuid, struct ts_store_handle **handle) { TEE_Result res; struct tee_tadb_ta_read *ta; size_t l; const struct tee_tadb_property *prop; res = tee_tadb_ta_open(uuid, &ta); if (res) return res; prop = tee_tadb_ta_get_property(ta); l = prop->custom_size; res = tee_tadb_ta_read(ta, NULL, NULL, &l); if (res) goto err; if (l != prop->custom_size) { res = TEE_ERROR_CORRUPT_OBJECT; goto err; } *handle = (struct ts_store_handle *)ta; return TEE_SUCCESS; err: tee_tadb_ta_close(ta); return res; } static TEE_Result secstor_ta_get_size(const struct ts_store_handle *h, size_t *size) { struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h; const struct tee_tadb_property *prop = tee_tadb_ta_get_property(ta); *size = prop->bin_size; return TEE_SUCCESS; } static TEE_Result secstor_ta_get_tag(const struct ts_store_handle *h, uint8_t *tag, unsigned int *tag_len) { return tee_tadb_get_tag((struct tee_tadb_ta_read *)h, tag, tag_len); } static TEE_Result secstor_ta_read(struct ts_store_handle *h, void *data_core, void *data_user, size_t len) { struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h; size_t l = len; TEE_Result res = tee_tadb_ta_read(ta, data_core, data_user, &l); if (res) return res; if (l != len) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } static void secstor_ta_close(struct ts_store_handle *h) { struct tee_tadb_ta_read *ta = (struct tee_tadb_ta_read *)h; tee_tadb_ta_close(ta); } REGISTER_TA_STORE(4) = { .description = "Secure Storage TA", .open = secstor_ta_open, .get_size = secstor_ta_get_size, .get_tag = secstor_ta_get_tag, .read = secstor_ta_read, .close = secstor_ta_close, }; optee_os-4.3.0/core/kernel/semihosting.c000066400000000000000000000106371464416617300202630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024 Andes Technology Corporation */ #include #include /* * ARM and RISC-V have defined the standard way to perform * the semihosting operations. * - Operation codes and open modes are identical. * - The implementation of the low-level __do_semihosting() call is * architecture-specific. * - Arm semihosting interface: * https://developer.arm.com/documentation/dui0471/g/Semihosting/The-semihosting-interface * - RISC-V semihosting interface: * https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc */ /* An integer that specifies the file open mode */ enum semihosting_open_mode { SEMIHOSTING_OPEN_R = 0, SEMIHOSTING_OPEN_RB = 1, SEMIHOSTING_OPEN_RX = 2, SEMIHOSTING_OPEN_RXB = 3, SEMIHOSTING_OPEN_W = 4, SEMIHOSTING_OPEN_WB = 5, SEMIHOSTING_OPEN_WX = 6, SEMIHOSTING_OPEN_WXB = 7, SEMIHOSTING_OPEN_A = 8, SEMIHOSTING_OPEN_AB = 9, SEMIHOSTING_OPEN_AX = 10, SEMIHOSTING_OPEN_AXB = 11, }; enum semihosting_sys_ops { /* Regular operations */ SEMIHOSTING_SYS_OPEN = 0x01, SEMIHOSTING_SYS_CLOSE = 0x02, SEMIHOSTING_SYS_WRITEC = 0x03, SEMIHOSTING_SYS_WRITE = 0x05, SEMIHOSTING_SYS_READ = 0x06, SEMIHOSTING_SYS_READC = 0x07, }; struct semihosting_param_t { uintptr_t param0; uintptr_t param1; uintptr_t param2; }; /** * @brief Read one character byte from the semihosting host debug terminal * * @retval the character read from the semihosting host */ char semihosting_sys_readc(void) { return __do_semihosting(SEMIHOSTING_SYS_READC, 0); } /** * @brief Write one character byte to the semihosting host debug terminal * @param c: the character to be written */ void semihosting_sys_writec(char c) { __do_semihosting(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&c); } /** * @brief Request the semihosting host to open a file on the host system * @param fname: the path or name of the file * @param flags: sys/fcntl.h standard flags to open the file with * * @retval nonzero if OK, or -1 if fails */ int semihosting_open(const char *fname, int flags) { int semi_open_flags = 0; const int flags_mask = O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_TRUNC | O_APPEND; struct semihosting_param_t arg = { }; /* Convert the flags to semihosting open. */ switch (flags & flags_mask) { case O_RDONLY: /* 'r' */ semi_open_flags = SEMIHOSTING_OPEN_R; break; case O_WRONLY | O_CREAT | O_TRUNC: /* 'w' */ semi_open_flags = SEMIHOSTING_OPEN_W; break; case O_WRONLY | O_CREAT | O_APPEND: /* 'a' */ semi_open_flags = SEMIHOSTING_OPEN_A; break; case O_RDWR: /* 'r+' */ semi_open_flags = SEMIHOSTING_OPEN_RX; break; case O_RDWR | O_CREAT | O_TRUNC: /* 'w+' */ semi_open_flags = SEMIHOSTING_OPEN_WX; break; case O_RDWR | O_CREAT | O_APPEND: /* 'a+' */ semi_open_flags = SEMIHOSTING_OPEN_AX; break; default: return -1; } arg.param0 = (uintptr_t)fname; arg.param1 = semi_open_flags; arg.param2 = strlen(fname); return (int)__do_semihosting(SEMIHOSTING_SYS_OPEN, (uintptr_t)&arg); } /** * @brief Read data from a file on the semihosting host system * @param fd: a handle for a file previously opened * @param ptr: pointer to a buffer * @param len: the number of bytes to read to the buffer from the file * * @retval zero if OK, the same value as @len if fails, smaller value than @len * for partial success */ size_t semihosting_read(int fd, void *ptr, size_t len) { struct semihosting_param_t arg = { .param0 = fd, .param1 = (uintptr_t)ptr, .param2 = len }; return __do_semihosting(SEMIHOSTING_SYS_READ, (uintptr_t)&arg); } /** * @brief Write data into a file on the semihosting host system * @param fd: a handle for a file previously opened * @param ptr: pointer to a buffer * @param len: the number of bytes to be written from the buffer to the file * * @retval zero if OK, otherwise the number of bytes that are not written */ size_t semihosting_write(int fd, const void *ptr, size_t len) { struct semihosting_param_t arg = { .param0 = fd, .param1 = (uintptr_t)ptr, .param2 = len }; return __do_semihosting(SEMIHOSTING_SYS_WRITE, (uintptr_t)&arg); } /** * @brief Close a file on the semihosting host system * @param fd: a handle for a file previously opened * * @retval zero if OK, -1 if fails */ int semihosting_close(int fd) { struct semihosting_param_t arg = { .param0 = fd, }; return (int)__do_semihosting(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&arg); } optee_os-4.3.0/core/kernel/show_conf.c000066400000000000000000000006041464416617300177100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 1019 Huawei Technologies Co., Ltd */ #include #include extern const char conf_str[]; static TEE_Result show_conf(void) { #if (TRACE_LEVEL >= TRACE_INFO) IMSG("Contents of conf.mk (decode with 'base64 -d | xz -d'):"); trace_ext_puts(conf_str); #endif return TEE_SUCCESS; } service_init(show_conf); optee_os-4.3.0/core/kernel/spin_lock_debug.c000066400000000000000000000014261464416617300210550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include void spinlock_count_incr(void) { struct thread_core_local *l = thread_get_core_local(); l->locked_count++; assert(l->locked_count); } void spinlock_count_decr(void) { struct thread_core_local *l = thread_get_core_local(); assert(l->locked_count); l->locked_count--; } bool __nostackcheck have_spinlock(void) { struct thread_core_local *l; if (!thread_foreign_intr_disabled()) { /* * Normally we can't be holding a spinlock since doing so would * imply foreign interrupts are disabled (or the spinlock * logic is flawed). */ return false; } l = thread_get_core_local(); return !!l->locked_count; } optee_os-4.3.0/core/kernel/sub.mk000066400000000000000000000035411464416617300167040ustar00rootroot00000000000000srcs-$(CFG_CORE_SANITIZE_KADDRESS) += asan.c cflags-remove-asan.c-y += $(cflags_kasan) srcs-$(CFG_TEE_CORE_DEBUG) += spin_lock_debug.c srcs-y += assert.c srcs-y += console.c srcs-$(CFG_DT) += dt.c srcs-$(CFG_DT) += dt_driver.c srcs-y += boot.c srcs-y += pm.c srcs-y += handle.c srcs-y += interrupt.c ifeq ($(CFG_WITH_USER_TA),y) srcs-y += ldelf_loader.c srcs-y += ldelf_syscalls.c srcs-y += scall.c endif srcs-$(CFG_LOCKDEP) += lockdep.c ifneq ($(CFG_CORE_FFA),y) srcs-$(CFG_CORE_DYN_SHM) += msg_param.c endif srcs-y += panic.c srcs-y += trace_ext.c srcs-y += refcount.c srcs-y += delay.c srcs-y += tee_time.c srcs-$(CFG_SECURE_TIME_SOURCE_REE) += tee_time_ree.c srcs-y += otp_stubs.c srcs-y += tee_misc.c srcs-y += tee_ta_manager.c srcs-y += ts_manager.c srcs-$(CFG_CORE_SANITIZE_UNDEFINED) += ubsan.c srcs-y += scattered_array.c srcs-y += huk_subkey.c srcs-$(CFG_SHOW_CONF_ON_BOOT) += show_conf.c srcs-y += user_mode_ctx.c srcs-$(CFG_CORE_TPM_EVENT_LOG) += tpm.c srcs-y += initcall.c srcs-$(CFG_WITH_USER_TA) += user_access.c srcs-y += mutex.c srcs-$(CFG_LOCKDEP) += mutex_lockdep.c srcs-y += wait_queue.c srcs-y += notif.c srcs-$(_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL) += notif_default.c srcs-y += thread.c ifeq ($(CFG_WITH_USER_TA),y) srcs-y += user_ta.c srcs-$(CFG_REE_FS_TA) += ree_fs_ta.c srcs-$(CFG_EARLY_TA) += early_ta.c srcs-$(CFG_SECSTOR_TA) += secstor_ta.c endif srcs-$(CFG_EMBEDDED_TS) += embedded_ts.c srcs-y += pseudo_ta.c srcs-$(CFG_TRANSFER_LIST) += transfer_list.c srcs-$(CFG_SEMIHOSTING) += semihosting.c ifeq ($(CFG_SYSCALL_FTRACE),y) # We would not like to profile spin_lock_debug.c file as it provides # common APIs that are needed for ftrace framework to trace syscalls. # So profiling this file could create an incorrect cyclic behaviour. cflags-remove-spin_lock_debug.c-$(CFG_TEE_CORE_DEBUG) += -pg endif srcs-y += nv_counter.c srcs-$(CFG_CALLOUT) += callout.c optee_os-4.3.0/core/kernel/tee_misc.c000066400000000000000000000056461464416617300175260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include static uint8_t tee_b2hs_add_base(uint8_t in) { if (in > 9) return in + 55; else return in + 48; } static int tee_hs2b_rem_base(uint8_t in, uint8_t *out) { if (in < 48 || in > 70 || (in > 57 && in < 65)) return -1; if (in < 58) *out = in - 48; else *out = in - 55; return 0; } uint32_t tee_b2hs(uint8_t *b, uint8_t *hs, uint32_t blen, uint32_t hslen) { uint32_t i = 0; if (blen * 2 + 1 > hslen) return 0; for (; i < blen; i++) { hs[i * 2 + 1] = tee_b2hs_add_base(b[i] & 0xf); hs[i * 2] = tee_b2hs_add_base(b[i] >> 4); } hs[blen * 2] = 0; return blen * 2; } uint32_t tee_hs2b(uint8_t *hs, uint8_t *b, uint32_t hslen, uint32_t blen) { uint32_t i = 0; uint32_t len = TEE_HS2B_BBUF_SIZE(hslen); uint8_t hi; uint8_t lo; if (len > blen) return 0; for (; i < len; i++) { if (tee_hs2b_rem_base(hs[i * 2], &hi)) return 0; if (tee_hs2b_rem_base(hs[i * 2 + 1], &lo)) return 0; b[i] = (hi << 4) + lo; } return len; } static bool is_valid_conf_and_notnull_size(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al) { /* invalid config return false */ if ((b - 1 + bl < b) || (a - 1 + al < a)) return false; /* null sized areas are never inside / outside / overlap */ if (!bl || !al) return false; return true; } /* Returns true when buffer 'b' is fully contained in area 'a' */ bool core_is_buffer_inside(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al) { /* invalid config or "null size" return false */ if (!is_valid_conf_and_notnull_size(b, bl, a, al)) return false; if ((b >= a) && (b - 1 + bl <= a - 1 + al)) return true; return false; } /* Returns true when buffer 'b' is fully outside area 'a' */ bool core_is_buffer_outside(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al) { /* invalid config or "null size" return false */ if (!is_valid_conf_and_notnull_size(b, bl, a, al)) return false; if ((b + bl - 1 < a) || (b > a + al - 1)) return true; return false; } /* Returns true when buffer 'b' intersects area 'a' */ bool core_is_buffer_intersect(paddr_t b, paddr_size_t bl, paddr_t a, paddr_size_t al) { /* invalid config or "null size" return false */ if (!is_valid_conf_and_notnull_size(b, bl, a, al)) return false; if ((b + bl - 1 < a) || (b > a + al - 1)) return false; return true; } void *alloc_cache_aligned(size_t size) { void *ptr = NULL; size_t alloc_size = 0; uint32_t cacheline_size = 0; cacheline_size = cache_get_max_line_size(); if (ROUNDUP_OVERFLOW(size, cacheline_size, &alloc_size)) return NULL; ptr = memalign(cacheline_size, alloc_size); if (!ptr) return NULL; memset(ptr, 0, size); return ptr; } optee_os-4.3.0/core/kernel/tee_ta_manager.c000066400000000000000000000646541464416617300206750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CFG_TA_STATS) #define MAX_DUMP_SESS_NUM (16) struct tee_ta_dump_ctx { TEE_UUID uuid; uint32_t panicked; bool is_user_ta; uint32_t sess_num; uint32_t sess_id[MAX_DUMP_SESS_NUM]; }; #endif /* This mutex protects the critical section in tee_ta_init_session */ struct mutex tee_ta_mutex = MUTEX_INITIALIZER; /* This condvar is used when waiting for a TA context to become initialized */ struct condvar tee_ta_init_cv = CONDVAR_INITIALIZER; struct tee_ta_ctx_head tee_ctxes = TAILQ_HEAD_INITIALIZER(tee_ctxes); #ifndef CFG_CONCURRENT_SINGLE_INSTANCE_TA static struct condvar tee_ta_cv = CONDVAR_INITIALIZER; static short int tee_ta_single_instance_thread = THREAD_ID_INVALID; static size_t tee_ta_single_instance_count; #endif #ifdef CFG_CONCURRENT_SINGLE_INSTANCE_TA static void lock_single_instance(void) { } static void unlock_single_instance(void) { } static bool has_single_instance_lock(void) { return false; } #else static void lock_single_instance(void) { /* Requires tee_ta_mutex to be held */ if (tee_ta_single_instance_thread != thread_get_id()) { /* Wait until the single-instance lock is available. */ while (tee_ta_single_instance_thread != THREAD_ID_INVALID) condvar_wait(&tee_ta_cv, &tee_ta_mutex); tee_ta_single_instance_thread = thread_get_id(); assert(tee_ta_single_instance_count == 0); } tee_ta_single_instance_count++; } static void unlock_single_instance(void) { /* Requires tee_ta_mutex to be held */ assert(tee_ta_single_instance_thread == thread_get_id()); assert(tee_ta_single_instance_count > 0); tee_ta_single_instance_count--; if (tee_ta_single_instance_count == 0) { tee_ta_single_instance_thread = THREAD_ID_INVALID; condvar_signal(&tee_ta_cv); } } static bool has_single_instance_lock(void) { /* Requires tee_ta_mutex to be held */ return tee_ta_single_instance_thread == thread_get_id(); } #endif struct tee_ta_session *__noprof to_ta_session(struct ts_session *sess) { assert(is_ta_ctx(sess->ctx) || is_stmm_ctx(sess->ctx)); return container_of(sess, struct tee_ta_session, ts_sess); } static struct tee_ta_ctx *ts_to_ta_ctx(struct ts_ctx *ctx) { if (is_ta_ctx(ctx)) return to_ta_ctx(ctx); if (is_stmm_ctx(ctx)) return &(to_stmm_ctx(ctx)->ta_ctx); panic("bad context"); } static bool tee_ta_try_set_busy(struct tee_ta_ctx *ctx) { bool rc = true; if (ctx->flags & TA_FLAG_CONCURRENT) return true; mutex_lock(&tee_ta_mutex); if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) lock_single_instance(); if (has_single_instance_lock()) { if (ctx->busy) { /* * We're holding the single-instance lock and the * TA is busy, as waiting now would only cause a * dead-lock, we release the lock and return false. */ rc = false; if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) unlock_single_instance(); } } else { /* * We're not holding the single-instance lock, we're free to * wait for the TA to become available. */ while (ctx->busy) condvar_wait(&ctx->busy_cv, &tee_ta_mutex); } /* Either it's already true or we should set it to true */ ctx->busy = true; mutex_unlock(&tee_ta_mutex); return rc; } static void tee_ta_set_busy(struct tee_ta_ctx *ctx) { if (!tee_ta_try_set_busy(ctx)) panic(); } static void tee_ta_clear_busy(struct tee_ta_ctx *ctx) { if (ctx->flags & TA_FLAG_CONCURRENT) return; mutex_lock(&tee_ta_mutex); assert(ctx->busy); ctx->busy = false; condvar_signal(&ctx->busy_cv); if (ctx->flags & TA_FLAG_SINGLE_INSTANCE) unlock_single_instance(); mutex_unlock(&tee_ta_mutex); } static void dec_session_ref_count(struct tee_ta_session *s) { assert(s->ref_count > 0); s->ref_count--; if (s->ref_count == 1) condvar_signal(&s->refc_cv); } void tee_ta_put_session(struct tee_ta_session *s) { mutex_lock(&tee_ta_mutex); if (s->lock_thread == thread_get_id()) { s->lock_thread = THREAD_ID_INVALID; condvar_signal(&s->lock_cv); } dec_session_ref_count(s); mutex_unlock(&tee_ta_mutex); } static struct tee_ta_session *tee_ta_find_session_nolock(uint32_t id, struct tee_ta_session_head *open_sessions) { struct tee_ta_session *s = NULL; struct tee_ta_session *found = NULL; TAILQ_FOREACH(s, open_sessions, link) { if (s->id == id) { found = s; break; } } return found; } struct tee_ta_session *tee_ta_find_session(uint32_t id, struct tee_ta_session_head *open_sessions) { struct tee_ta_session *s = NULL; mutex_lock(&tee_ta_mutex); s = tee_ta_find_session_nolock(id, open_sessions); mutex_unlock(&tee_ta_mutex); return s; } struct tee_ta_session *tee_ta_get_session(uint32_t id, bool exclusive, struct tee_ta_session_head *open_sessions) { struct tee_ta_session *s; mutex_lock(&tee_ta_mutex); while (true) { s = tee_ta_find_session_nolock(id, open_sessions); if (!s) break; if (s->unlink) { s = NULL; break; } s->ref_count++; if (!exclusive) break; assert(s->lock_thread != thread_get_id()); while (s->lock_thread != THREAD_ID_INVALID && !s->unlink) condvar_wait(&s->lock_cv, &tee_ta_mutex); if (s->unlink) { dec_session_ref_count(s); s = NULL; break; } s->lock_thread = thread_get_id(); break; } mutex_unlock(&tee_ta_mutex); return s; } static void tee_ta_unlink_session(struct tee_ta_session *s, struct tee_ta_session_head *open_sessions) { mutex_lock(&tee_ta_mutex); assert(s->ref_count >= 1); assert(s->lock_thread == thread_get_id()); assert(!s->unlink); s->unlink = true; condvar_broadcast(&s->lock_cv); while (s->ref_count != 1) condvar_wait(&s->refc_cv, &tee_ta_mutex); TAILQ_REMOVE(open_sessions, s, link); mutex_unlock(&tee_ta_mutex); } static void destroy_session(struct tee_ta_session *s, struct tee_ta_session_head *open_sessions) { #if defined(CFG_FTRACE_SUPPORT) if (s->ts_sess.ctx && s->ts_sess.ctx->ops->dump_ftrace) { ts_push_current_session(&s->ts_sess); s->ts_sess.fbuf = NULL; s->ts_sess.ctx->ops->dump_ftrace(s->ts_sess.ctx); ts_pop_current_session(); } #endif tee_ta_unlink_session(s, open_sessions); #if defined(CFG_TA_GPROF_SUPPORT) free(s->ts_sess.sbuf); #endif free(s); } static void destroy_context(struct tee_ta_ctx *ctx) { DMSG("Destroy TA ctx (0x%" PRIxVA ")", (vaddr_t)ctx); condvar_destroy(&ctx->busy_cv); ctx->ts_ctx.ops->destroy(&ctx->ts_ctx); } /* * tee_ta_context_find - Find TA in session list based on a UUID (input) * Returns a pointer to the session */ static struct tee_ta_ctx *tee_ta_context_find(const TEE_UUID *uuid) { struct tee_ta_ctx *ctx; TAILQ_FOREACH(ctx, &tee_ctxes, link) { if (memcmp(&ctx->ts_ctx.uuid, uuid, sizeof(TEE_UUID)) == 0) return ctx; } return NULL; } /* check if requester (client ID) matches session initial client */ static TEE_Result check_client(struct tee_ta_session *s, const TEE_Identity *id) { if (id == KERN_IDENTITY) return TEE_SUCCESS; if (id == NSAPP_IDENTITY) { if (s->clnt_id.login == TEE_LOGIN_TRUSTED_APP) { DMSG("nsec tries to hijack TA session"); return TEE_ERROR_ACCESS_DENIED; } return TEE_SUCCESS; } if (memcmp(&s->clnt_id, id, sizeof(TEE_Identity)) != 0) { DMSG("client id mismatch"); return TEE_ERROR_ACCESS_DENIED; } return TEE_SUCCESS; } /* * Check if invocation parameters matches TA properties * * @s - current session handle * @param - already identified memory references hold a valid 'mobj'. * * Policy: * - All TAs can access 'non-secure' shared memory. * - All TAs can access TEE private memory (seccpy) * - Only SDP flagged TAs can accept SDP memory references. */ #ifndef CFG_SECURE_DATA_PATH static bool check_params(struct tee_ta_session *sess __unused, struct tee_ta_param *param __unused) { /* * When CFG_SECURE_DATA_PATH is not enabled, SDP memory references * are rejected at OP-TEE core entry. Hence here all TAs have same * permissions regarding memory reference parameters. */ return true; } #else static bool check_params(struct tee_ta_session *sess, struct tee_ta_param *param) { int n; /* * When CFG_SECURE_DATA_PATH is enabled, OP-TEE entry allows SHM and * SDP memory references. Only TAs flagged SDP can access SDP memory. */ if (sess->ts_sess.ctx && ts_to_ta_ctx(sess->ts_sess.ctx)->flags & TA_FLAG_SECURE_DATA_PATH) return true; for (n = 0; n < TEE_NUM_PARAMS; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); struct param_mem *mem = ¶m->u[n].mem; if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; if (!mem->size) continue; if (mobj_is_sdp_mem(mem->mobj)) return false; } return true; } #endif static void set_invoke_timeout(struct tee_ta_session *sess, uint32_t cancel_req_to) { TEE_Time current_time; TEE_Time cancel_time; if (cancel_req_to == TEE_TIMEOUT_INFINITE) goto infinite; if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) goto infinite; if (ADD_OVERFLOW(current_time.seconds, cancel_req_to / 1000, &cancel_time.seconds)) goto infinite; cancel_time.millis = current_time.millis + cancel_req_to % 1000; if (cancel_time.millis > 1000) { if (ADD_OVERFLOW(current_time.seconds, 1, &cancel_time.seconds)) goto infinite; cancel_time.seconds++; cancel_time.millis -= 1000; } sess->cancel_time = cancel_time; return; infinite: sess->cancel_time.seconds = UINT32_MAX; sess->cancel_time.millis = UINT32_MAX; } /*----------------------------------------------------------------------------- * Close a Trusted Application and free available resources *---------------------------------------------------------------------------*/ TEE_Result tee_ta_close_session(struct tee_ta_session *csess, struct tee_ta_session_head *open_sessions, const TEE_Identity *clnt_id) { struct tee_ta_session *sess = NULL; struct tee_ta_ctx *ctx = NULL; struct ts_ctx *ts_ctx = NULL; bool keep_alive = false; DMSG("csess 0x%" PRIxVA " id %u", (vaddr_t)csess, csess ? csess->id : UINT_MAX); if (!csess) return TEE_ERROR_ITEM_NOT_FOUND; sess = tee_ta_get_session(csess->id, true, open_sessions); if (!sess) { EMSG("session 0x%" PRIxVA " to be removed is not found", (vaddr_t)csess); return TEE_ERROR_ITEM_NOT_FOUND; } if (check_client(sess, clnt_id) != TEE_SUCCESS) { tee_ta_put_session(sess); return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ } DMSG("Destroy session"); ts_ctx = sess->ts_sess.ctx; if (!ts_ctx) { destroy_session(sess, open_sessions); return TEE_SUCCESS; } ctx = ts_to_ta_ctx(ts_ctx); if (ctx->panicked) { destroy_session(sess, open_sessions); } else { tee_ta_set_busy(ctx); set_invoke_timeout(sess, TEE_TIMEOUT_INFINITE); ts_ctx->ops->enter_close_session(&sess->ts_sess); destroy_session(sess, open_sessions); tee_ta_clear_busy(ctx); } mutex_lock(&tee_ta_mutex); if (ctx->ref_count <= 0) panic(); ctx->ref_count--; keep_alive = (ctx->flags & TA_FLAG_INSTANCE_KEEP_ALIVE) && (ctx->flags & TA_FLAG_SINGLE_INSTANCE); if (!ctx->ref_count && (ctx->panicked || !keep_alive)) { if (!ctx->is_releasing) { TAILQ_REMOVE(&tee_ctxes, ctx, link); ctx->is_releasing = true; } mutex_unlock(&tee_ta_mutex); destroy_context(ctx); } else mutex_unlock(&tee_ta_mutex); return TEE_SUCCESS; } static TEE_Result tee_ta_init_session_with_context(struct tee_ta_session *s, const TEE_UUID *uuid) { struct tee_ta_ctx *ctx = NULL; while (true) { ctx = tee_ta_context_find(uuid); if (!ctx) return TEE_ERROR_ITEM_NOT_FOUND; if (!ctx->is_initializing) break; /* * Context is still initializing, wait here until it's * fully initialized. Note that we're searching for the * context again since it may have been removed while we * where sleeping. */ condvar_wait(&tee_ta_init_cv, &tee_ta_mutex); } /* * If the trusted service is not a single instance service (e.g. is * a multi-instance TA) it should be loaded as a new instance instead * of doing anything with this instance. So tell the caller that we * didn't find the TA it the caller will load a new instance. */ if ((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) return TEE_ERROR_ITEM_NOT_FOUND; /* * The trusted service is single instance, if it isn't multi session we * can't create another session unless its reference is zero */ if (!(ctx->flags & TA_FLAG_MULTI_SESSION) && ctx->ref_count) return TEE_ERROR_BUSY; DMSG("Re-open trusted service %pUl", (void *)&ctx->ts_ctx.uuid); ctx->ref_count++; s->ts_sess.ctx = &ctx->ts_ctx; s->ts_sess.handle_scall = s->ts_sess.ctx->ops->handle_scall; return TEE_SUCCESS; } static uint32_t new_session_id(struct tee_ta_session_head *open_sessions) { struct tee_ta_session *last = NULL; uint32_t saved = 0; uint32_t id = 1; last = TAILQ_LAST(open_sessions, tee_ta_session_head); if (last) { /* This value is less likely to be already used */ id = last->id + 1; if (!id) id++; /* 0 is not valid */ } saved = id; do { if (!tee_ta_find_session_nolock(id, open_sessions)) return id; id++; if (!id) id++; } while (id != saved); return 0; } static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, struct tee_ta_session_head *open_sessions, const TEE_UUID *uuid, struct tee_ta_session **sess) { TEE_Result res; struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session)); *err = TEE_ORIGIN_TEE; if (!s) return TEE_ERROR_OUT_OF_MEMORY; s->cancel_mask = true; condvar_init(&s->refc_cv); condvar_init(&s->lock_cv); s->lock_thread = THREAD_ID_INVALID; s->ref_count = 1; mutex_lock(&tee_ta_mutex); s->id = new_session_id(open_sessions); if (!s->id) { res = TEE_ERROR_OVERFLOW; goto err_mutex_unlock; } TAILQ_INSERT_TAIL(open_sessions, s, link); /* Look for already loaded TA */ res = tee_ta_init_session_with_context(s, uuid); if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) { mutex_unlock(&tee_ta_mutex); goto out; } /* Look for secure partition */ res = stmm_init_session(uuid, s); if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) { mutex_unlock(&tee_ta_mutex); if (res == TEE_SUCCESS) res = stmm_complete_session(s); goto out; } /* Look for pseudo TA */ res = tee_ta_init_pseudo_ta_session(uuid, s); if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) { mutex_unlock(&tee_ta_mutex); goto out; } /* Look for user TA */ res = tee_ta_init_user_ta_session(uuid, s); mutex_unlock(&tee_ta_mutex); if (res == TEE_SUCCESS) res = tee_ta_complete_user_ta_session(s); out: if (!res) { *sess = s; return TEE_SUCCESS; } mutex_lock(&tee_ta_mutex); TAILQ_REMOVE(open_sessions, s, link); err_mutex_unlock: mutex_unlock(&tee_ta_mutex); free(s); return res; } static void release_ta_ctx(struct tee_ta_ctx *ctx) { bool was_releasing = false; mutex_lock(&tee_ta_mutex); was_releasing = ctx->is_releasing; ctx->is_releasing = true; if (!was_releasing) { DMSG("Releasing panicked TA ctx"); TAILQ_REMOVE(&tee_ctxes, ctx, link); } mutex_unlock(&tee_ta_mutex); if (!was_releasing) ctx->ts_ctx.ops->release_state(&ctx->ts_ctx); } TEE_Result tee_ta_open_session(TEE_ErrorOrigin *err, struct tee_ta_session **sess, struct tee_ta_session_head *open_sessions, const TEE_UUID *uuid, const TEE_Identity *clnt_id, uint32_t cancel_req_to, struct tee_ta_param *param) { TEE_Result res = TEE_SUCCESS; struct tee_ta_session *s = NULL; struct tee_ta_ctx *ctx = NULL; struct ts_ctx *ts_ctx = NULL; bool panicked = false; bool was_busy = false; res = tee_ta_init_session(err, open_sessions, uuid, &s); if (res != TEE_SUCCESS) { DMSG("init session failed 0x%x", res); return res; } if (!check_params(s, param)) return TEE_ERROR_BAD_PARAMETERS; ts_ctx = s->ts_sess.ctx; ctx = ts_to_ta_ctx(ts_ctx); if (tee_ta_try_set_busy(ctx)) { if (!ctx->panicked) { /* Save identity of the owner of the session */ s->clnt_id = *clnt_id; s->param = param; set_invoke_timeout(s, cancel_req_to); res = ts_ctx->ops->enter_open_session(&s->ts_sess); s->param = NULL; } panicked = ctx->panicked; if (panicked) { release_ta_ctx(ctx); res = TEE_ERROR_TARGET_DEAD; } tee_ta_clear_busy(ctx); } else { /* Deadlock avoided */ res = TEE_ERROR_BUSY; was_busy = true; } /* * Origin error equal to TEE_ORIGIN_TRUSTED_APP for "regular" error, * apart from panicking. */ if (panicked || was_busy) *err = TEE_ORIGIN_TEE; else *err = s->err_origin; tee_ta_put_session(s); if (panicked || res != TEE_SUCCESS) tee_ta_close_session(s, open_sessions, KERN_IDENTITY); if (!res) *sess = s; else EMSG("Failed for TA %pUl. Return error %#"PRIx32, uuid, res); return res; } TEE_Result tee_ta_invoke_command(TEE_ErrorOrigin *err, struct tee_ta_session *sess, const TEE_Identity *clnt_id, uint32_t cancel_req_to, uint32_t cmd, struct tee_ta_param *param) { struct tee_ta_ctx *ta_ctx = NULL; struct ts_ctx *ts_ctx = NULL; TEE_Result res = TEE_SUCCESS; bool panicked = false; if (check_client(sess, clnt_id) != TEE_SUCCESS) return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ if (!check_params(sess, param)) return TEE_ERROR_BAD_PARAMETERS; ts_ctx = sess->ts_sess.ctx; ta_ctx = ts_to_ta_ctx(ts_ctx); tee_ta_set_busy(ta_ctx); if (!ta_ctx->panicked) { sess->param = param; set_invoke_timeout(sess, cancel_req_to); res = ts_ctx->ops->enter_invoke_cmd(&sess->ts_sess, cmd); sess->param = NULL; } panicked = ta_ctx->panicked; if (panicked) { release_ta_ctx(ta_ctx); res = TEE_ERROR_TARGET_DEAD; } tee_ta_clear_busy(ta_ctx); /* * Origin error equal to TEE_ORIGIN_TRUSTED_APP for "regular" error, * apart from panicking. */ if (panicked) *err = TEE_ORIGIN_TEE; else *err = sess->err_origin; /* Short buffer is not an effective error case */ if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) DMSG("Error: %x of %d", res, *err); return res; } #if defined(CFG_TA_STATS) static TEE_Result dump_ta_memstats(struct tee_ta_session *s, struct tee_ta_param *param) { TEE_Result res = TEE_SUCCESS; struct tee_ta_ctx *ctx = NULL; struct ts_ctx *ts_ctx = NULL; bool panicked = false; ts_ctx = s->ts_sess.ctx; if (!ts_ctx) return TEE_ERROR_ITEM_NOT_FOUND; ctx = ts_to_ta_ctx(ts_ctx); if (ctx->is_initializing) return TEE_ERROR_BAD_STATE; if (tee_ta_try_set_busy(ctx)) { if (!ctx->panicked) { s->param = param; set_invoke_timeout(s, TEE_TIMEOUT_INFINITE); res = ts_ctx->ops->dump_mem_stats(&s->ts_sess); s->param = NULL; } panicked = ctx->panicked; if (panicked) { release_ta_ctx(ctx); res = TEE_ERROR_TARGET_DEAD; } tee_ta_clear_busy(ctx); } else { /* Deadlock avoided */ res = TEE_ERROR_BUSY; } return res; } static void init_dump_ctx(struct tee_ta_dump_ctx *dump_ctx) { struct tee_ta_session *sess = NULL; struct tee_ta_session_head *open_sessions = NULL; struct tee_ta_ctx *ctx = NULL; unsigned int n = 0; nsec_sessions_list_head(&open_sessions); /* * Scan all sessions opened from secure side by searching through * all available TA instances and for each context, scan all opened * sessions. */ TAILQ_FOREACH(ctx, &tee_ctxes, link) { unsigned int cnt = 0; if (!is_user_ta_ctx(&ctx->ts_ctx)) continue; memcpy(&dump_ctx[n].uuid, &ctx->ts_ctx.uuid, sizeof(ctx->ts_ctx.uuid)); dump_ctx[n].panicked = ctx->panicked; dump_ctx[n].is_user_ta = is_user_ta_ctx(&ctx->ts_ctx); TAILQ_FOREACH(sess, open_sessions, link) { if (sess->ts_sess.ctx == &ctx->ts_ctx) { if (cnt == MAX_DUMP_SESS_NUM) break; dump_ctx[n].sess_id[cnt] = sess->id; cnt++; } } dump_ctx[n].sess_num = cnt; n++; } } static TEE_Result dump_ta_stats(struct tee_ta_dump_ctx *dump_ctx, struct pta_stats_ta *dump_stats, size_t ta_count) { TEE_Result res = TEE_SUCCESS; struct tee_ta_session *sess = NULL; struct tee_ta_session_head *open_sessions = NULL; struct tee_ta_param param = { }; unsigned int i = 0; unsigned int j = 0; nsec_sessions_list_head(&open_sessions); for (i = 0; i < ta_count; i++) { struct pta_stats_ta *stats = &dump_stats[i]; memcpy(&stats->uuid, &dump_ctx[i].uuid, sizeof(dump_ctx[i].uuid)); stats->panicked = dump_ctx[i].panicked; stats->sess_num = dump_ctx[i].sess_num; /* Find a session from dump context */ for (j = 0, sess = NULL; j < dump_ctx[i].sess_num && !sess; j++) sess = tee_ta_get_session(dump_ctx[i].sess_id[j], true, open_sessions); if (!sess) continue; /* If session is existing, get its heap stats */ memset(¶m, 0, sizeof(struct tee_ta_param)); param.types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); res = dump_ta_memstats(sess, ¶m); if (res == TEE_SUCCESS) { stats->heap.allocated = param.u[0].val.a; stats->heap.max_allocated = param.u[0].val.b; stats->heap.size = param.u[1].val.a; stats->heap.num_alloc_fail = param.u[1].val.b; stats->heap.biggest_alloc_fail = param.u[2].val.a; stats->heap.biggest_alloc_fail_used = param.u[2].val.b; } else { memset(&stats->heap, 0, sizeof(stats->heap)); } tee_ta_put_session(sess); } return TEE_SUCCESS; } TEE_Result tee_ta_instance_stats(void *buf, size_t *buf_size) { TEE_Result res = TEE_SUCCESS; struct pta_stats_ta *dump_stats = NULL; struct tee_ta_dump_ctx *dump_ctx = NULL; struct tee_ta_ctx *ctx = NULL; size_t sz = 0; size_t ta_count = 0; if (!buf_size) return TEE_ERROR_BAD_PARAMETERS; mutex_lock(&tee_ta_mutex); /* Go through all available TA and calc out the actual buffer size. */ TAILQ_FOREACH(ctx, &tee_ctxes, link) if (is_user_ta_ctx(&ctx->ts_ctx)) ta_count++; sz = sizeof(struct pta_stats_ta) * ta_count; if (!sz) { /* sz = 0 means there is no UTA, return no item found. */ res = TEE_ERROR_ITEM_NOT_FOUND; } else if (!buf || *buf_size < sz) { /* * buf is null or pass size less than actual size * means caller try to query the buffer size. * update *buf_size. */ *buf_size = sz; res = TEE_ERROR_SHORT_BUFFER; } else if (!IS_ALIGNED_WITH_TYPE(buf, uint32_t)) { DMSG("Data alignment"); res = TEE_ERROR_BAD_PARAMETERS; } else { dump_stats = (struct pta_stats_ta *)buf; dump_ctx = malloc(sizeof(struct tee_ta_dump_ctx) * ta_count); if (!dump_ctx) res = TEE_ERROR_OUT_OF_MEMORY; else init_dump_ctx(dump_ctx); } mutex_unlock(&tee_ta_mutex); if (res != TEE_SUCCESS) return res; /* Dump user ta stats by iterating dump_ctx[] */ res = dump_ta_stats(dump_ctx, dump_stats, ta_count); if (res == TEE_SUCCESS) *buf_size = sz; free(dump_ctx); return res; } #endif TEE_Result tee_ta_cancel_command(TEE_ErrorOrigin *err, struct tee_ta_session *sess, const TEE_Identity *clnt_id) { *err = TEE_ORIGIN_TEE; if (check_client(sess, clnt_id) != TEE_SUCCESS) return TEE_ERROR_BAD_PARAMETERS; /* intentional generic error */ sess->cancel = true; return TEE_SUCCESS; } bool tee_ta_session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time) { TEE_Time current_time; if (s->cancel_mask) return false; if (s->cancel) return true; if (s->cancel_time.seconds == UINT32_MAX) return false; if (curr_time != NULL) current_time = *curr_time; else if (tee_time_get_sys_time(¤t_time) != TEE_SUCCESS) return false; if (current_time.seconds > s->cancel_time.seconds || (current_time.seconds == s->cancel_time.seconds && current_time.millis >= s->cancel_time.millis)) { return true; } return false; } #if defined(CFG_TA_GPROF_SUPPORT) void tee_ta_gprof_sample_pc(vaddr_t pc) { struct ts_session *s = ts_get_current_session(); struct user_ta_ctx *utc = NULL; struct sample_buf *sbuf = NULL; TEE_Result res = 0; size_t idx = 0; sbuf = s->sbuf; if (!sbuf || !sbuf->enabled) return; /* PC sampling is not enabled */ idx = (((uint64_t)pc - sbuf->offset)/2 * sbuf->scale)/65536; if (idx < sbuf->nsamples) { utc = to_user_ta_ctx(s->ctx); res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)&sbuf->samples[idx], sizeof(*sbuf->samples)); if (res != TEE_SUCCESS) return; sbuf->samples[idx]++; } sbuf->count++; } static void gprof_update_session_utime(bool suspend, struct ts_session *s, uint64_t now) { struct sample_buf *sbuf = s->sbuf; if (!sbuf) return; if (suspend) { assert(sbuf->usr_entered); sbuf->usr += now - sbuf->usr_entered; sbuf->usr_entered = 0; } else { assert(!sbuf->usr_entered); if (!now) now++; /* 0 is reserved */ sbuf->usr_entered = now; } } /* * Update user-mode CPU time for the current session * @suspend: true if session is being suspended (leaving user mode), false if * it is resumed (entering user mode) */ static void tee_ta_update_session_utime(bool suspend) { struct ts_session *s = ts_get_current_session(); uint64_t now = barrier_read_counter_timer(); gprof_update_session_utime(suspend, s, now); } void tee_ta_update_session_utime_suspend(void) { tee_ta_update_session_utime(true); } void tee_ta_update_session_utime_resume(void) { tee_ta_update_session_utime(false); } #endif #if defined(CFG_FTRACE_SUPPORT) static void ftrace_update_times(bool suspend) { struct ts_session *s = ts_get_current_session_may_fail(); struct ftrace_buf *fbuf = NULL; uint64_t now = 0; uint32_t i = 0; if (!s) return; now = barrier_read_counter_timer(); fbuf = s->fbuf; if (!fbuf) return; if (suspend) { fbuf->suspend_time = now; } else { for (i = 0; i <= fbuf->ret_idx; i++) fbuf->begin_time[i] += now - fbuf->suspend_time; } } void tee_ta_ftrace_update_times_suspend(void) { ftrace_update_times(true); } void tee_ta_ftrace_update_times_resume(void) { ftrace_update_times(false); } #endif bool __noprof is_ta_ctx(struct ts_ctx *ctx) { return is_user_ta_ctx(ctx) || is_pseudo_ta_ctx(ctx); } optee_os-4.3.0/core/kernel/tee_time.c000066400000000000000000000021171464416617300175170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2020, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include void tee_time_wait(uint32_t milliseconds_delay) { struct thread_param params = THREAD_PARAM_VALUE(IN, milliseconds_delay, 0, 0); thread_rpc_cmd(OPTEE_RPC_CMD_SUSPEND, 1, ¶ms); } /* * tee_time_get_ree_time(): this function implements the GP Internal API * function TEE_GetREETime() * Goal is to get the time of the Rich Execution Environment * This is why this time is provided through the supplicant */ TEE_Result tee_time_get_ree_time(TEE_Time *time) { struct thread_param params = THREAD_PARAM_VALUE(OUT, 0, 0, 0); TEE_Result res = TEE_SUCCESS; if (!time) return TEE_ERROR_BAD_PARAMETERS; res = thread_rpc_cmd(OPTEE_RPC_CMD_GET_TIME, 1, ¶ms); if (res == TEE_SUCCESS) { time->seconds = params.u.value.a; time->millis = params.u.value.b / 1000000; } return res; } optee_os-4.3.0/core/kernel/tee_time_ree.c000066400000000000000000000012371464416617300203540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited */ #include #include static TEE_Time prev; static struct mutex time_mu = MUTEX_INITIALIZER; TEE_Result tee_time_get_sys_time(TEE_Time *time) { TEE_Result res; res = tee_time_get_ree_time(time); if (res != TEE_SUCCESS) return res; mutex_lock(&time_mu); if (time->seconds < prev.seconds || (time->seconds == prev.seconds && time->millis < prev.millis)) *time = prev; /* REE time was rolled back */ else prev = *time; mutex_unlock(&time_mu); return res; } uint32_t tee_time_get_sys_time_protection_level(void) { return 100; } optee_os-4.3.0/core/kernel/thread.c000066400000000000000000000422241464416617300171760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2022, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020-2021, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include struct thread_ctx threads[CFG_NUM_THREADS]; struct thread_core_local thread_core_local[CFG_TEE_CORE_NB_CORE] __nex_bss; /* * Stacks * * [Lower addresses on the left] * * [ STACK_CANARY_SIZE/2 | STACK_CHECK_EXTRA | STACK_XXX_SIZE | STACK_CANARY_SIZE/2 ] * ^ ^ ^ ^ * stack_xxx[n] "hard" top "soft" top bottom */ #ifdef CFG_WITH_STACK_CANARIES static uint32_t start_canary_value = 0xdedede00; static uint32_t end_canary_value = 0xababab00; #define GET_START_CANARY(name, stack_num) name[stack_num][0] #define GET_END_CANARY(name, stack_num) \ name[stack_num][sizeof(name[stack_num]) / sizeof(uint32_t) - 1] #endif #define DECLARE_STACK(name, num_stacks, stack_size, linkage) \ linkage uint32_t name[num_stacks] \ [ROUNDUP(stack_size + STACK_CANARY_SIZE + STACK_CHECK_EXTRA, \ STACK_ALIGNMENT) / sizeof(uint32_t)] \ __attribute__((section(".nozi_stack." # name), \ aligned(STACK_ALIGNMENT))) #define GET_STACK(stack) ((vaddr_t)(stack) + STACK_SIZE(stack)) DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE, /* global linkage */); DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE, static); #ifndef CFG_WITH_PAGER DECLARE_STACK(stack_thread, CFG_NUM_THREADS, STACK_THREAD_SIZE, static); #endif #define GET_STACK_TOP_HARD(stack, n) \ ((vaddr_t)&(stack)[n] + STACK_CANARY_SIZE / 2) #define GET_STACK_TOP_SOFT(stack, n) \ (GET_STACK_TOP_HARD(stack, n) + STACK_CHECK_EXTRA) #define GET_STACK_BOTTOM(stack, n) ((vaddr_t)&(stack)[n] + sizeof(stack[n]) - \ STACK_CANARY_SIZE / 2) const uint32_t stack_tmp_stride __section(".identity_map.stack_tmp_stride") = sizeof(stack_tmp[0]); /* * This stack setup info is required by secondary boot cores before they * each locally enable the pager (the mmu). Hence kept in pager sections. */ DECLARE_KEEP_PAGER(stack_tmp_stride); static unsigned int thread_global_lock __nex_bss = SPINLOCK_UNLOCK; void thread_init_canaries(void) { #ifdef CFG_WITH_STACK_CANARIES size_t n; #define INIT_CANARY(name) \ for (n = 0; n < ARRAY_SIZE(name); n++) { \ uint32_t *start_canary = &GET_START_CANARY(name, n); \ uint32_t *end_canary = &GET_END_CANARY(name, n); \ \ *start_canary = start_canary_value; \ *end_canary = end_canary_value; \ } INIT_CANARY(stack_tmp); INIT_CANARY(stack_abt); #if !defined(CFG_WITH_PAGER) && !defined(CFG_NS_VIRTUALIZATION) INIT_CANARY(stack_thread); #endif #endif/*CFG_WITH_STACK_CANARIES*/ } #if defined(CFG_WITH_STACK_CANARIES) void thread_update_canaries(void) { uint32_t canary[2] = { }; uint32_t exceptions = 0; plat_get_random_stack_canaries(canary, ARRAY_SIZE(canary), sizeof(canary[0])); exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); thread_check_canaries(); start_canary_value = canary[0]; end_canary_value = canary[1]; thread_init_canaries(); thread_unmask_exceptions(exceptions); } #endif #define CANARY_DIED(stack, loc, n, addr) \ do { \ EMSG_RAW("Dead canary at %s of '%s[%zu]' (%p)", #loc, #stack, \ n, (void *)addr); \ panic(); \ } while (0) void thread_check_canaries(void) { #ifdef CFG_WITH_STACK_CANARIES uint32_t *canary = NULL; size_t n = 0; for (n = 0; n < ARRAY_SIZE(stack_tmp); n++) { canary = &GET_START_CANARY(stack_tmp, n); if (*canary != start_canary_value) CANARY_DIED(stack_tmp, start, n, canary); canary = &GET_END_CANARY(stack_tmp, n); if (*canary != end_canary_value) CANARY_DIED(stack_tmp, end, n, canary); } for (n = 0; n < ARRAY_SIZE(stack_abt); n++) { canary = &GET_START_CANARY(stack_abt, n); if (*canary != start_canary_value) CANARY_DIED(stack_abt, start, n, canary); canary = &GET_END_CANARY(stack_abt, n); if (*canary != end_canary_value) CANARY_DIED(stack_abt, end, n, canary); } #if !defined(CFG_WITH_PAGER) && !defined(CFG_NS_VIRTUALIZATION) for (n = 0; n < ARRAY_SIZE(stack_thread); n++) { canary = &GET_START_CANARY(stack_thread, n); if (*canary != start_canary_value) CANARY_DIED(stack_thread, start, n, canary); canary = &GET_END_CANARY(stack_thread, n); if (*canary != end_canary_value) CANARY_DIED(stack_thread, end, n, canary); } #endif #endif/*CFG_WITH_STACK_CANARIES*/ } void thread_lock_global(void) { cpu_spin_lock(&thread_global_lock); } void thread_unlock_global(void) { cpu_spin_unlock(&thread_global_lock); } static struct thread_core_local * __nostackcheck get_core_local(unsigned int pos) { /* * Foreign interrupts must be disabled before playing with core_local * since we otherwise may be rescheduled to a different core in the * middle of this function. */ assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR); assert(pos < CFG_TEE_CORE_NB_CORE); return &thread_core_local[pos]; } struct thread_core_local * __nostackcheck thread_get_core_local(void) { unsigned int pos = get_core_pos(); return get_core_local(pos); } #ifdef CFG_CORE_DEBUG_CHECK_STACKS static void print_stack_limits(void) { size_t n = 0; vaddr_t __maybe_unused start = 0; vaddr_t __maybe_unused end = 0; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { start = GET_STACK_TOP_SOFT(stack_tmp, n); end = GET_STACK_BOTTOM(stack_tmp, n); DMSG("tmp [%zu] 0x%" PRIxVA "..0x%" PRIxVA, n, start, end); } for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { start = GET_STACK_TOP_SOFT(stack_abt, n); end = GET_STACK_BOTTOM(stack_abt, n); DMSG("abt [%zu] 0x%" PRIxVA "..0x%" PRIxVA, n, start, end); } for (n = 0; n < CFG_NUM_THREADS; n++) { end = threads[n].stack_va_end; start = end - STACK_THREAD_SIZE + STACK_CHECK_EXTRA; DMSG("thr [%zu] 0x%" PRIxVA "..0x%" PRIxVA, n, start, end); } } static void check_stack_limits(void) { vaddr_t stack_start = 0; vaddr_t stack_end = 0; /* Any value in the current stack frame will do */ vaddr_t current_sp = (vaddr_t)&stack_start; if (!get_stack_soft_limits(&stack_start, &stack_end)) panic("Unknown stack limits"); if (current_sp < stack_start || current_sp > stack_end) { EMSG("Stack pointer out of range: 0x%" PRIxVA " not in [0x%" PRIxVA " .. 0x%" PRIxVA "]", current_sp, stack_start, stack_end); print_stack_limits(); panic(); } } static bool * __nostackcheck get_stackcheck_recursion_flag(void) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); unsigned int pos = get_core_pos(); struct thread_core_local *l = get_core_local(pos); int ct = l->curr_thread; bool *p = NULL; if (l->flags & (THREAD_CLF_ABORT | THREAD_CLF_TMP)) p = &l->stackcheck_recursion; else if (!l->flags) p = &threads[ct].tsd.stackcheck_recursion; thread_unmask_exceptions(exceptions); return p; } void __cyg_profile_func_enter(void *this_fn, void *call_site); void __nostackcheck __cyg_profile_func_enter(void *this_fn __unused, void *call_site __unused) { bool *p = get_stackcheck_recursion_flag(); assert(p); if (*p) return; *p = true; check_stack_limits(); *p = false; } void __cyg_profile_func_exit(void *this_fn, void *call_site); void __nostackcheck __cyg_profile_func_exit(void *this_fn __unused, void *call_site __unused) { } #else static void print_stack_limits(void) { } #endif void thread_init_boot_thread(void) { struct thread_core_local *l = thread_get_core_local(); thread_init_threads(); l->curr_thread = 0; threads[0].state = THREAD_STATE_ACTIVE; } void __nostackcheck thread_clr_boot_thread(void) { struct thread_core_local *l = thread_get_core_local(); assert(l->curr_thread >= 0 && l->curr_thread < CFG_NUM_THREADS); assert(threads[l->curr_thread].state == THREAD_STATE_ACTIVE); threads[l->curr_thread].state = THREAD_STATE_FREE; l->curr_thread = THREAD_ID_INVALID; } void __nostackcheck *thread_get_tmp_sp(void) { struct thread_core_local *l = thread_get_core_local(); /* * Called from assembly when switching to the temporary stack, so flags * need updating */ l->flags |= THREAD_CLF_TMP; return (void *)l->tmp_stack_va_end; } vaddr_t thread_stack_start(void) { struct thread_ctx *thr; int ct = thread_get_id_may_fail(); if (ct == THREAD_ID_INVALID) return 0; thr = threads + ct; return thr->stack_va_end - STACK_THREAD_SIZE; } size_t thread_stack_size(void) { return STACK_THREAD_SIZE; } bool get_stack_limits(vaddr_t *start, vaddr_t *end, bool hard) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); unsigned int pos = get_core_pos(); struct thread_core_local *l = get_core_local(pos); int ct = l->curr_thread; bool ret = false; if (l->flags & THREAD_CLF_TMP) { if (hard) *start = GET_STACK_TOP_HARD(stack_tmp, pos); else *start = GET_STACK_TOP_SOFT(stack_tmp, pos); *end = GET_STACK_BOTTOM(stack_tmp, pos); ret = true; } else if (l->flags & THREAD_CLF_ABORT) { if (hard) *start = GET_STACK_TOP_HARD(stack_abt, pos); else *start = GET_STACK_TOP_SOFT(stack_abt, pos); *end = GET_STACK_BOTTOM(stack_abt, pos); ret = true; } else if (!l->flags) { if (ct < 0 || ct >= CFG_NUM_THREADS) goto out; *end = threads[ct].stack_va_end; *start = *end - STACK_THREAD_SIZE; if (!hard) *start += STACK_CHECK_EXTRA; ret = true; } out: thread_unmask_exceptions(exceptions); return ret; } bool thread_is_from_abort_mode(void) { struct thread_core_local *l = thread_get_core_local(); return (l->flags >> THREAD_CLF_SAVED_SHIFT) & THREAD_CLF_ABORT; } /* * This function should always be accurate, but it might be possible to * implement a more efficient depending on cpu architecture. */ bool __weak thread_is_in_normal_mode(void) { uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); struct thread_core_local *l = thread_get_core_local(); bool ret; /* * If any bit in l->flags is set aside from THREAD_CLF_TMP we're * handling some exception. */ ret = (l->curr_thread != THREAD_ID_INVALID) && !(l->flags & ~THREAD_CLF_TMP); thread_unmask_exceptions(exceptions); return ret; } short int __noprof thread_get_id_may_fail(void) { /* * thread_get_core_local() requires foreign interrupts to be disabled */ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); struct thread_core_local *l = thread_get_core_local(); short int ct = l->curr_thread; thread_unmask_exceptions(exceptions); return ct; } short int __noprof thread_get_id(void) { short int ct = thread_get_id_may_fail(); /* Thread ID has to fit in a short int */ COMPILE_TIME_ASSERT(CFG_NUM_THREADS <= SHRT_MAX); assert(ct >= 0 && ct < CFG_NUM_THREADS); return ct; } #ifdef CFG_WITH_PAGER static void init_thread_stacks(void) { size_t n = 0; /* * Allocate virtual memory for thread stacks. */ for (n = 0; n < CFG_NUM_THREADS; n++) { tee_mm_entry_t *mm = NULL; vaddr_t sp = 0; size_t num_pages = 0; struct fobj *fobj = NULL; /* Find vmem for thread stack and its protection gap */ mm = tee_mm_alloc(&core_virt_mem_pool, SMALL_PAGE_SIZE + STACK_THREAD_SIZE); assert(mm); /* Claim eventual physical page */ tee_pager_add_pages(tee_mm_get_smem(mm), tee_mm_get_size(mm), true); num_pages = tee_mm_get_bytes(mm) / SMALL_PAGE_SIZE - 1; fobj = fobj_locked_paged_alloc(num_pages); /* Add the region to the pager */ tee_pager_add_core_region(tee_mm_get_smem(mm) + SMALL_PAGE_SIZE, PAGED_REGION_TYPE_LOCK, fobj); fobj_put(fobj); /* init effective stack */ sp = tee_mm_get_smem(mm) + tee_mm_get_bytes(mm); asan_tag_access((void *)tee_mm_get_smem(mm), (void *)sp); if (!thread_init_stack(n, sp)) panic("init stack failed"); } } #else static void init_thread_stacks(void) { size_t n; /* Assign the thread stacks */ for (n = 0; n < CFG_NUM_THREADS; n++) { if (!thread_init_stack(n, GET_STACK_BOTTOM(stack_thread, n))) panic("thread_init_stack failed"); } } #endif /*CFG_WITH_PAGER*/ void thread_init_threads(void) { size_t n = 0; init_thread_stacks(); print_stack_limits(); pgt_init(); mutex_lockdep_init(); for (n = 0; n < CFG_NUM_THREADS; n++) TAILQ_INIT(&threads[n].tsd.sess_stack); } void __nostackcheck thread_init_thread_core_local(void) { size_t n = 0; struct thread_core_local *tcl = thread_core_local; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { tcl[n].curr_thread = THREAD_ID_INVALID; tcl[n].flags = THREAD_CLF_TMP; } tcl[0].tmp_stack_va_end = GET_STACK_BOTTOM(stack_tmp, 0); } void __nostackcheck thread_init_core_local_stacks(void) { size_t n = 0; struct thread_core_local *tcl = thread_core_local; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) { tcl[n].tmp_stack_va_end = GET_STACK_BOTTOM(stack_tmp, n) - STACK_TMP_OFFS; tcl[n].abt_stack_va_end = GET_STACK_BOTTOM(stack_abt, n); } } #if defined(CFG_CORE_PAUTH) void thread_init_thread_pauth_keys(void) { size_t n = 0; for (n = 0; n < CFG_NUM_THREADS; n++) if (crypto_rng_read(&threads[n].keys, sizeof(threads[n].keys))) panic("Failed to init thread pauth keys"); } void thread_init_core_local_pauth_keys(void) { struct thread_core_local *tcl = thread_core_local; size_t n = 0; for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) if (crypto_rng_read(&tcl[n].keys, sizeof(tcl[n].keys))) panic("Failed to init core local pauth keys"); } #endif struct thread_specific_data * __noprof thread_get_tsd(void) { return &threads[thread_get_id()].tsd; } struct thread_ctx_regs * __nostackcheck thread_get_ctx_regs(void) { struct thread_core_local *l = thread_get_core_local(); assert(l->curr_thread != THREAD_ID_INVALID); return &threads[l->curr_thread].regs; } void thread_set_foreign_intr(bool enable) { /* thread_get_core_local() requires foreign interrupts to be disabled */ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); struct thread_core_local *l; l = thread_get_core_local(); assert(l->curr_thread != THREAD_ID_INVALID); if (enable) { threads[l->curr_thread].flags |= THREAD_FLAGS_FOREIGN_INTR_ENABLE; thread_set_exceptions(exceptions & ~THREAD_EXCP_FOREIGN_INTR); } else { /* * No need to disable foreign interrupts here since they're * already disabled above. */ threads[l->curr_thread].flags &= ~THREAD_FLAGS_FOREIGN_INTR_ENABLE; } } void thread_restore_foreign_intr(void) { /* thread_get_core_local() requires foreign interrupts to be disabled */ uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR); struct thread_core_local *l; l = thread_get_core_local(); assert(l->curr_thread != THREAD_ID_INVALID); if (threads[l->curr_thread].flags & THREAD_FLAGS_FOREIGN_INTR_ENABLE) thread_set_exceptions(exceptions & ~THREAD_EXCP_FOREIGN_INTR); } static struct mobj *alloc_shm(enum thread_shm_type shm_type, size_t size) { switch (shm_type) { case THREAD_SHM_TYPE_APPLICATION: return thread_rpc_alloc_payload(size); case THREAD_SHM_TYPE_KERNEL_PRIVATE: return thread_rpc_alloc_kernel_payload(size); case THREAD_SHM_TYPE_GLOBAL: return thread_rpc_alloc_global_payload(size); default: return NULL; } } static void clear_shm_cache_entry(struct thread_shm_cache_entry *ce) { if (ce->mobj) { switch (ce->type) { case THREAD_SHM_TYPE_APPLICATION: thread_rpc_free_payload(ce->mobj); break; case THREAD_SHM_TYPE_KERNEL_PRIVATE: thread_rpc_free_kernel_payload(ce->mobj); break; case THREAD_SHM_TYPE_GLOBAL: thread_rpc_free_global_payload(ce->mobj); break; default: assert(0); /* "can't happen" */ break; } } ce->mobj = NULL; ce->size = 0; } static struct thread_shm_cache_entry * get_shm_cache_entry(enum thread_shm_cache_user user) { struct thread_shm_cache *cache = &threads[thread_get_id()].shm_cache; struct thread_shm_cache_entry *ce = NULL; SLIST_FOREACH(ce, cache, link) if (ce->user == user) return ce; ce = calloc(1, sizeof(*ce)); if (ce) { ce->user = user; SLIST_INSERT_HEAD(cache, ce, link); } return ce; } void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user, enum thread_shm_type shm_type, size_t size, struct mobj **mobj) { struct thread_shm_cache_entry *ce = NULL; size_t sz = size; paddr_t p = 0; void *va = NULL; if (!size) return NULL; ce = get_shm_cache_entry(user); if (!ce) return NULL; /* * Always allocate in page chunks as normal world allocates payload * memory as complete pages. */ sz = ROUNDUP(size, SMALL_PAGE_SIZE); if (ce->type != shm_type || sz > ce->size) { clear_shm_cache_entry(ce); ce->mobj = alloc_shm(shm_type, sz); if (!ce->mobj) return NULL; if (mobj_get_pa(ce->mobj, 0, 0, &p)) goto err; if (!IS_ALIGNED_WITH_TYPE(p, uint64_t)) goto err; va = mobj_get_va(ce->mobj, 0, sz); if (!va) goto err; ce->size = sz; ce->type = shm_type; } else { va = mobj_get_va(ce->mobj, 0, sz); if (!va) goto err; } *mobj = ce->mobj; return va; err: clear_shm_cache_entry(ce); return NULL; } void thread_rpc_shm_cache_clear(struct thread_shm_cache *cache) { while (true) { struct thread_shm_cache_entry *ce = SLIST_FIRST(cache); if (!ce) break; SLIST_REMOVE_HEAD(cache, link); clear_shm_cache_entry(ce); free(ce); } } optee_os-4.3.0/core/kernel/tpm.c000066400000000000000000000064011464416617300165240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 2020-2023, ARM Limited. All rights reserved. */ #include #include #include #include #include #include static void *tpm_log_addr; static size_t tpm_log_size; /* * Check whether the node at @offs contains TPM Event Log information or not. * * @offs is the offset of the node that describes the device in @fdt. * @buf will contain the phy address of the TPM Event log. * @size will contain the size of the mapped area. * * Returns the size of the mapped area or < 0 on failure. */ #ifdef CFG_DT static int read_dt_tpm_log_info(void *fdt, int node, paddr_t *buf, size_t *size) { const uint32_t *property = NULL; const uint64_t zero_addr = 0; int len_prop = 0; paddr_t log_addr = 0; int err = 0; #ifdef CFG_MAP_EXT_DT_SECURE const char *dt_tpm_event_log_addr = "tpm_event_log_addr"; #else const char *dt_tpm_event_log_addr = "tpm_event_log_sm_addr"; #endif /* * Get the TPM Log address. */ property = fdt_getprop(fdt, node, dt_tpm_event_log_addr, &len_prop); if (!property || len_prop != sizeof(uint32_t) * 2) return -1; log_addr = fdt32_to_cpu(property[1]); if (!IS_ENABLED(CFG_CORE_SEL1_SPMC)) { err = fdt_setprop(fdt, node, dt_tpm_event_log_addr, &zero_addr, sizeof(uint32_t) * 2); if (err < 0) { EMSG("Error setting property DTB to zero"); return err; } } /* * Get the TPM Log size. */ property = fdt_getprop(fdt, node, "tpm_event_log_size", &len_prop); if (!property || len_prop != sizeof(uint32_t)) return -1; *size = fdt32_to_cpu(property[0]); *buf = log_addr; return *size; } #endif static void get_tpm_phys_params(void *fdt __maybe_unused, paddr_t *addr, size_t *size) { #ifdef CFG_DT int node = 0; const char *dt_tpm_match_table = { "arm,tpm_event_log", }; if (!fdt) { EMSG("TPM: No DTB found"); return; } node = fdt_node_offset_by_compatible(fdt, -1, dt_tpm_match_table); if (node < 0) { EMSG("TPM: Fail to find TPM node %i", node); return; } if (read_dt_tpm_log_info((void *)fdt, node, addr, size) < 0) { EMSG("TPM: Fail to retrieve DTB properties from node %i", node); return; } #else *size = CFG_TPM_MAX_LOG_SIZE; *addr = CFG_TPM_LOG_BASE_ADDR; #endif /* CFG_DT */ } TEE_Result tpm_get_event_log(void *buf, size_t *size) { const size_t buf_size = *size; *size = tpm_log_size; if (!buf) { EMSG("TPM: Invalid buffer"); return TEE_ERROR_BAD_PARAMETERS; } if (buf_size < tpm_log_size) { EMSG("TPM: Not enough space for the log: %zu, %zu", buf_size, tpm_log_size); return TEE_ERROR_SHORT_BUFFER; } memcpy(buf, tpm_log_addr, tpm_log_size); return TEE_SUCCESS; } TEE_Result tpm_get_event_log_size(size_t *size) { *size = tpm_log_size; return TEE_SUCCESS; } void tpm_map_log_area(void *fdt) { paddr_t log_addr = 0; unsigned int rounded_size = 0; get_tpm_phys_params(fdt, &log_addr, &tpm_log_size); DMSG("TPM Event log PA: %#" PRIxPA, log_addr); DMSG("TPM Event log size: %zu Bytes", tpm_log_size); rounded_size = ROUNDUP(tpm_log_size, SMALL_PAGE_SIZE); tpm_log_addr = core_mmu_add_mapping(MEM_AREA_RAM_SEC, log_addr, rounded_size); if (!tpm_log_addr) { EMSG("TPM: Failed to map TPM log memory"); return; } } optee_os-4.3.0/core/kernel/trace_ext.c000066400000000000000000000025711464416617300177060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited */ #include #include #include #include #include #include #include #include const char trace_ext_prefix[] = "TC"; int trace_level __nex_data = TRACE_LEVEL; static unsigned int puts_lock __nex_bss = SPINLOCK_UNLOCK; void __weak plat_trace_ext_puts(const char *str __unused) { } void trace_ext_puts(const char *str) { uint32_t itr_status = thread_mask_exceptions(THREAD_EXCP_ALL); bool mmu_enabled = cpu_mmu_enabled(); bool was_contended = false; const char *p; if (mmu_enabled && !cpu_spin_trylock(&puts_lock)) { was_contended = true; cpu_spin_lock_no_dldetect(&puts_lock); } plat_trace_ext_puts(str); console_flush(); if (was_contended) console_putc('*'); for (p = str; *p; p++) console_putc(*p); console_flush(); if (mmu_enabled) cpu_spin_unlock(&puts_lock); thread_unmask_exceptions(itr_status); } int trace_ext_get_thread_id(void) { return thread_get_id_may_fail(); } int trace_ext_get_core_id(void) { /* If foreign interrupts aren't masked we report invalid core ID */ if (thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR) return get_core_pos(); else return -1; } int trace_ext_get_guest_id(void) { return virt_get_current_guest_id(); } optee_os-4.3.0/core/kernel/transfer_list.c000066400000000000000000000432311464416617300206050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Linaro Limited */ /******************************************************************************* * Transfer list library compliant with the Firmware Handoff specification at: * https://github.com/FirmwareHandoff/firmware_handoff ******************************************************************************/ #include #include #include #include #include #include #include /******************************************************************************* * Adapt a physical address to match the maximum transfer entry data alignment * required by an existing transfer list. * Compliant with 2.4.6 of Firmware Handoff specification (v0.9). * @pa: Physical address for adapting. * @tl: Pointer to the existing transfer list. * Return the adapted physical address. ******************************************************************************/ static paddr_t get_align_base_addr(paddr_t pa, struct transfer_list_header *tl) { paddr_t align_mask = TL_ALIGNMENT_FROM_ORDER(tl->alignment) - 1; paddr_t align_off = (paddr_t)tl & align_mask; paddr_t new_addr = (pa & ~align_mask) + align_off; if (new_addr < pa) new_addr += TL_ALIGNMENT_FROM_ORDER(tl->alignment); return new_addr; } static void unmap_list(struct transfer_list_header *tl, size_t sz) { if (core_mmu_remove_mapping(MEM_AREA_TRANSFER_LIST, tl, sz)) panic("Failed to remove transfer list mapping"); } struct transfer_list_header *transfer_list_map(paddr_t pa) { struct transfer_list_header *tl = NULL; size_t sz = SMALL_PAGE_SIZE; size_t old_sz = 0; while (true) { tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, sz); if (!tl) { EMSG("Failed to map TL with PA %#"PRIxPA", size %#zx", pa, sz); return NULL; } old_sz = sz; if (transfer_list_check_header(tl) == TL_OPS_NONE) { unmap_list(tl, sz); return NULL; } if (tl->max_size <= sz) return tl; sz = ROUNDUP(tl->max_size, SMALL_PAGE_SIZE); unmap_list(tl, old_sz); } } void transfer_list_unmap_sync(struct transfer_list_header *tl) { size_t sz = tl->max_size; transfer_list_update_checksum(tl); dcache_cleaninv_range(tl, sz); unmap_list(tl, sz); } void transfer_list_unmap_nosync(struct transfer_list_header *tl) { unmap_list(tl, tl->max_size); } void transfer_list_dump(struct transfer_list_header *tl) { struct transfer_list_entry *tl_e = NULL; int i __maybe_unused = 0; if (!tl) return; DMSG("Dump transfer list:"); DMSG("signature %#"PRIx32, tl->signature); DMSG("checksum %#"PRIx8, tl->checksum); DMSG("version %#"PRIx8, tl->version); DMSG("hdr_size %#"PRIx8, tl->hdr_size); DMSG("alignment %#"PRIx8, tl->alignment); DMSG("size %#"PRIx32, tl->size); DMSG("max_size %#"PRIx32, tl->max_size); DMSG("flags %#"PRIx32, tl->flags); while (true) { tl_e = transfer_list_next(tl, tl_e); if (!tl_e) break; DMSG("Entry %d:", i++); DMSG("tag_id %#"PRIx16, tl_e->tag_id); DMSG("hdr_size %#"PRIx8, tl_e->hdr_size); DMSG("data_size %#"PRIx32, tl_e->data_size); DMSG("data_addr %#"PRIxVA, (vaddr_t)transfer_list_entry_data(tl_e)); } } /******************************************************************************* * Creating a transfer list in a specified reserved memory region. * Compliant with 2.4.5 of Firmware Handoff specification (v0.9). * @pa: Physical address for residing the new transfer list. * @max_size: Maximum size of the new transfer list. * Return pointer to the created transfer list or NULL on error. ******************************************************************************/ struct transfer_list_header *transfer_list_init(paddr_t pa, size_t max_size) { struct transfer_list_header *tl = NULL; int align = TL_ALIGNMENT_FROM_ORDER(TRANSFER_LIST_INIT_MAX_ALIGN); if (!pa || !max_size) return NULL; if (!IS_ALIGNED(pa, align) || !IS_ALIGNED(max_size, align) || max_size < sizeof(*tl)) return NULL; tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, pa, max_size); if (!tl) return NULL; memset(tl, 0, max_size); tl->signature = TRANSFER_LIST_SIGNATURE; tl->version = TRANSFER_LIST_VERSION; tl->hdr_size = sizeof(*tl); tl->alignment = TRANSFER_LIST_INIT_MAX_ALIGN; /* initial max align */ tl->size = sizeof(*tl); /* initial size is the size of header */ tl->max_size = max_size; tl->flags = TL_FLAGS_HAS_CHECKSUM; transfer_list_update_checksum(tl); return tl; } /******************************************************************************* * Relocating a transfer list to a specified reserved memory region. * Compliant with 2.4.6 of Firmware Handoff specification (v0.9). * @tl: Pointer to the transfer list for relocating. * @pa: Physical address for relocating the transfer list. * @max_size: Maximum size of the transfer list after relocating * Return pointer to the relocated transfer list or NULL on error. ******************************************************************************/ struct transfer_list_header * transfer_list_relocate(struct transfer_list_header *tl, paddr_t pa, size_t max_size) { paddr_t new_addr = 0; struct transfer_list_header *new_tl = NULL; size_t new_max_size = 0; if (!tl || !pa || !max_size) return NULL; new_addr = get_align_base_addr(pa, tl); new_max_size = max_size - (new_addr - pa); /* The new space is not sufficient for the TL */ if (tl->size > new_max_size) return NULL; new_tl = core_mmu_add_mapping(MEM_AREA_TRANSFER_LIST, new_addr, new_max_size); if (!new_tl) return NULL; memmove(new_tl, tl, tl->size); new_tl->max_size = new_max_size; transfer_list_update_checksum(new_tl); transfer_list_unmap_nosync(tl); return new_tl; } /******************************************************************************* * Verifying the header of a transfer list. * Compliant with 2.4.1 of Firmware Handoff specification (v0.9). * @tl: Pointer to the transfer list. * Return transfer list operation status code. ******************************************************************************/ int transfer_list_check_header(const struct transfer_list_header *tl) { if (!tl) return TL_OPS_NONE; if (tl->signature != TRANSFER_LIST_SIGNATURE) { EMSG("Bad transfer list signature %#"PRIx32, tl->signature); return TL_OPS_NONE; } if (!tl->max_size) { EMSG("Bad transfer list max size %#"PRIx32, tl->max_size); return TL_OPS_NONE; } if (tl->size > tl->max_size) { EMSG("Bad transfer list size %#"PRIx32, tl->size); return TL_OPS_NONE; } if (tl->hdr_size != sizeof(struct transfer_list_header)) { EMSG("Bad transfer list header size %#"PRIx8, tl->hdr_size); return TL_OPS_NONE; } if (!transfer_list_verify_checksum(tl)) { EMSG("Bad transfer list checksum %#"PRIx8, tl->checksum); return TL_OPS_NONE; } if (tl->version == 0) { EMSG("Transfer list version is invalid"); return TL_OPS_NONE; } else if (tl->version == TRANSFER_LIST_VERSION) { DMSG("Transfer list version is valid for all operations"); return TL_OPS_ALL; } else if (tl->version > TRANSFER_LIST_VERSION) { DMSG("Transfer list version is valid for read-only"); return TL_OPS_RO; } DMSG("Old transfer list version is detected"); return TL_OPS_CUS; } /******************************************************************************* * Enumerate the next transfer entry. * @tl: Pointer to the transfer list. * @cur: Pointer to the current transfer entry where we want to search for the * next one. * Return pointer to the next transfer entry or NULL on error or if @cur is the * last entry. ******************************************************************************/ struct transfer_list_entry *transfer_list_next(struct transfer_list_header *tl, struct transfer_list_entry *cur) { struct transfer_list_entry *tl_e = NULL; vaddr_t tl_ev = 0; vaddr_t va = 0; vaddr_t ev = 0; size_t sz = 0; if (!tl) return NULL; tl_ev = (vaddr_t)tl + tl->size; if (cur) { va = (vaddr_t)cur; /* check if the total size overflow */ if (ADD_OVERFLOW(cur->hdr_size, cur->data_size, &sz)) return NULL; /* roundup to the next entry */ if (ADD_OVERFLOW(va, sz, &va) || ROUNDUP_OVERFLOW(va, TRANSFER_LIST_GRANULE, &va)) return NULL; } else { va = (vaddr_t)tl + tl->hdr_size; } tl_e = (struct transfer_list_entry *)va; if (va + sizeof(*tl_e) > tl_ev || tl_e->hdr_size < sizeof(*tl_e) || ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) || ADD_OVERFLOW(va, sz, &ev) || ev > tl_ev) return NULL; return tl_e; } /******************************************************************************* * Calculate the byte sum (modulo 256) of a transfer list. * @tl: Pointer to the transfer list. * Return byte sum of the transfer list. ******************************************************************************/ static uint8_t calc_byte_sum(const struct transfer_list_header *tl) { uint8_t *b = (uint8_t *)tl; uint8_t cs = 0; size_t n = 0; for (n = 0; n < tl->size; n++) cs += b[n]; return cs; } /******************************************************************************* * Update the checksum of a transfer list. * @tl: Pointer to the transfer list. * Return updated checksum of the transfer list. ******************************************************************************/ void transfer_list_update_checksum(struct transfer_list_header *tl) { uint8_t cs = 0; if (!tl || !(tl->flags & TL_FLAGS_HAS_CHECKSUM)) return; cs = calc_byte_sum(tl); cs -= tl->checksum; cs = 256 - cs; tl->checksum = cs; assert(transfer_list_verify_checksum(tl)); } /******************************************************************************* * Verify the checksum of a transfer list. * @tl: Pointer to the transfer list. * Return true if verified or false if not. ******************************************************************************/ bool transfer_list_verify_checksum(const struct transfer_list_header *tl) { if (!tl) return false; if (!(tl->flags & TL_FLAGS_HAS_CHECKSUM)) return true; return !calc_byte_sum(tl); } /******************************************************************************* * Update the data size of a transfer entry. * @tl: Pointer to the transfer list. * @tl_e: Pointer to the transfer entry. * @new_data_size: New data size of the transfer entry. * Return true on success or false on error. ******************************************************************************/ bool transfer_list_set_data_size(struct transfer_list_header *tl, struct transfer_list_entry *tl_e, uint32_t new_data_size) { vaddr_t tl_old_ev = 0; vaddr_t new_ev = 0; vaddr_t old_ev = 0; vaddr_t r_new_ev = 0; struct transfer_list_entry *dummy_te = NULL; size_t gap = 0; size_t mov_dis = 0; size_t sz = 0; if (!tl || !tl_e) return false; tl_old_ev = (vaddr_t)tl + tl->size; /* * Calculate the old and new end of transfer entry * both must be roundup to align with TRANSFER_LIST_GRANULE */ if (ADD_OVERFLOW(tl_e->hdr_size, tl_e->data_size, &sz) || ADD_OVERFLOW((vaddr_t)tl_e, sz, &old_ev) || ROUNDUP_OVERFLOW(old_ev, TRANSFER_LIST_GRANULE, &old_ev)) return false; if (ADD_OVERFLOW(tl_e->hdr_size, new_data_size, &sz) || ADD_OVERFLOW((vaddr_t)tl_e, sz, &new_ev) || ROUNDUP_OVERFLOW(new_ev, TRANSFER_LIST_GRANULE, &new_ev)) return false; if (new_ev > old_ev) { /* * Move distance should be rounded up to match the entry data * alignment. * Ensure that the increased size doesn't exceed the max size * of TL */ mov_dis = new_ev - old_ev; if (ROUNDUP_OVERFLOW(mov_dis, TL_ALIGNMENT_FROM_ORDER(tl->alignment), &mov_dis) || tl->size + mov_dis > tl->max_size) { return false; } r_new_ev = old_ev + mov_dis; tl->size += mov_dis; } else { /* * Move distance should be rounded down to match the entry data * alignment. */ mov_dis = ROUNDDOWN(old_ev - new_ev, TL_ALIGNMENT_FROM_ORDER(tl->alignment)); r_new_ev = old_ev - mov_dis; tl->size -= mov_dis; } /* Move all following entries to fit in the expanded or shrunk space */ memmove((void *)r_new_ev, (void *)old_ev, tl_old_ev - old_ev); /* * Fill the gap due to round up/down with a void entry if the size of * the gap is more than an entry header. */ gap = r_new_ev - new_ev; if (gap >= sizeof(*dummy_te)) { /* Create a dummy transfer entry to fill up the gap */ dummy_te = (struct transfer_list_entry *)new_ev; dummy_te->tag_id = TL_TAG_EMPTY; dummy_te->reserved0 = 0; dummy_te->hdr_size = sizeof(*dummy_te); dummy_te->data_size = gap - sizeof(*dummy_te); } tl_e->data_size = new_data_size; transfer_list_update_checksum(tl); return true; } /******************************************************************************* * Remove a specified transfer entry from a transfer list. * @tl: Pointer to the transfer list. * @tl_e: Pointer to the transfer entry. * Return true on success or false on error. ******************************************************************************/ bool transfer_list_rem(struct transfer_list_header *tl, struct transfer_list_entry *tl_e) { if (!tl || !tl_e || (vaddr_t)tl_e > (vaddr_t)tl + tl->size) return false; tl_e->tag_id = TL_TAG_EMPTY; tl_e->reserved0 = 0; transfer_list_update_checksum(tl); return true; } /******************************************************************************* * Add a new transfer entry into a transfer list. * Compliant with 2.4.3 of Firmware Handoff specification (v0.9). * @tl: Pointer to the transfer list. * @tag_id: Tag ID for the new transfer entry. * @data_size: Data size of the new transfer entry. * @data: Pointer to the data for the new transfer entry. * NULL to skip data copying. * Return pointer to the added transfer entry or NULL on error. ******************************************************************************/ struct transfer_list_entry *transfer_list_add(struct transfer_list_header *tl, uint16_t tag_id, uint32_t data_size, const void *data) { vaddr_t max_tl_ev = 0; vaddr_t tl_ev = 0; vaddr_t ev = 0; struct transfer_list_entry *tl_e = NULL; size_t sz = 0; if (!tl) return NULL; max_tl_ev = (vaddr_t)tl + tl->max_size; tl_ev = (vaddr_t)tl + tl->size; ev = tl_ev; /* * Skip the step 1 (optional step). * New transfer entry will be added into the tail */ if (ADD_OVERFLOW(sizeof(*tl_e), data_size, &sz) || ADD_OVERFLOW(ev, sz, &ev) || ROUNDUP_OVERFLOW(ev, TRANSFER_LIST_GRANULE, &ev) || ev > max_tl_ev) { return NULL; } tl_e = (struct transfer_list_entry *)tl_ev; *tl_e = (struct transfer_list_entry){ .tag_id = tag_id, .hdr_size = sizeof(*tl_e), .data_size = data_size, }; tl->size += ev - tl_ev; if (data) memmove(tl_e + tl_e->hdr_size, data, data_size); transfer_list_update_checksum(tl); return tl_e; } /******************************************************************************* * Add a new transfer entry into a transfer list with specified new data * alignment requirement. * Compliant with 2.4.4 of Firmware Handoff specification (v0.9). * @tl: Pointer to the transfer list. * @tag_id: Tag ID for the new transfer entry. * @data_size: Data size of the new transfer entry. * @data: Pointer to the data for the new transfer entry. * @alignment: New data alignment specified as a power of two. * Return pointer to the added transfer entry or NULL on error. ******************************************************************************/ struct transfer_list_entry * transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id, uint32_t data_size, const void *data, uint8_t alignment) { struct transfer_list_entry *tl_e = NULL; vaddr_t tl_ev = 0; vaddr_t ev = 0; vaddr_t new_tl_ev = 0; size_t dummy_te_data_sz = 0; if (!tl) return NULL; tl_ev = (vaddr_t)tl + tl->size; ev = tl_ev + sizeof(struct transfer_list_entry); if (!IS_ALIGNED(ev, TL_ALIGNMENT_FROM_ORDER(alignment))) { /* * Transfer entry data address is not aligned to the new * alignment. Fill the gap with an empty transfer entry as a * placeholder before adding the desired transfer entry */ new_tl_ev = ROUNDUP(ev, TL_ALIGNMENT_FROM_ORDER(alignment)) - sizeof(struct transfer_list_entry); assert(new_tl_ev - tl_ev > sizeof(struct transfer_list_entry)); dummy_te_data_sz = new_tl_ev - tl_ev - sizeof(struct transfer_list_entry); if (!transfer_list_add(tl, TL_TAG_EMPTY, dummy_te_data_sz, NULL)) { return NULL; } } tl_e = transfer_list_add(tl, tag_id, data_size, data); if (alignment > tl->alignment) { tl->alignment = alignment; transfer_list_update_checksum(tl); } return tl_e; } /******************************************************************************* * Search for an existing transfer entry with the specified tag id from a * transfer list. * @tl: Pointer to the transfer list. * @tag_id: Tag ID to match a transfer entry. * Return pointer to the found transfer entry or NULL if not found. ******************************************************************************/ struct transfer_list_entry *transfer_list_find(struct transfer_list_header *tl, uint16_t tag_id) { struct transfer_list_entry *tl_e = NULL; do { tl_e = transfer_list_next(tl, tl_e); } while (tl_e && tl_e->tag_id != tag_id); return tl_e; } /******************************************************************************* * Retrieve the data pointer of a specified transfer entry. * @tl_e: Pointer to the transfer entry. * Return pointer to the transfer entry data or NULL on error. ******************************************************************************/ void *transfer_list_entry_data(struct transfer_list_entry *tl_e) { if (!tl_e) return NULL; return (uint8_t *)tl_e + tl_e->hdr_size; } optee_os-4.3.0/core/kernel/ts_manager.c000066400000000000000000000032111464416617300200400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include #include #include static void update_current_ctx(struct thread_specific_data *tsd) { struct ts_ctx *ctx = NULL; struct ts_session *s = TAILQ_FIRST(&tsd->sess_stack); if (s) { if (is_pseudo_ta_ctx(s->ctx)) s = TAILQ_NEXT(s, link_tsd); if (s) ctx = s->ctx; } if (tsd->ctx != ctx) vm_set_ctx(ctx); /* * If current context is of user mode, then it has to be active too. */ if (is_user_mode_ctx(ctx) != core_mmu_user_mapping_is_active()) panic("unexpected active mapping"); } void ts_push_current_session(struct ts_session *s) { struct thread_specific_data *tsd = thread_get_tsd(); TAILQ_INSERT_HEAD(&tsd->sess_stack, s, link_tsd); update_current_ctx(tsd); } struct ts_session *ts_pop_current_session(void) { struct thread_specific_data *tsd = thread_get_tsd(); struct ts_session *s = TAILQ_FIRST(&tsd->sess_stack); if (s) { TAILQ_REMOVE(&tsd->sess_stack, s, link_tsd); update_current_ctx(tsd); } return s; } struct ts_session *ts_get_calling_session(void) { return TAILQ_NEXT(ts_get_current_session(), link_tsd); } struct ts_session *ts_get_current_session_may_fail(void) { return TAILQ_FIRST(&thread_get_tsd()->sess_stack); } struct ts_session *ts_get_current_session(void) { struct ts_session *s = ts_get_current_session_may_fail(); if (!s) panic(); return s; } optee_os-4.3.0/core/kernel/ubsan.c000066400000000000000000000135741464416617300170450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include struct source_location { const char *file_name; uint32_t line; uint32_t column; }; struct type_descriptor { uint16_t type_kind; uint16_t type_info; char type_name[1]; }; struct type_mismatch_data { struct source_location loc; struct type_descriptor *type; unsigned long alignment; unsigned char type_check_kind; }; struct overflow_data { struct source_location loc; struct type_descriptor *type; }; struct shift_out_of_bounds_data { struct source_location loc; struct type_descriptor *lhs_type; struct type_descriptor *rhs_type; }; struct out_of_bounds_data { struct source_location loc; struct type_descriptor *array_type; struct type_descriptor *index_type; }; struct unreachable_data { struct source_location loc; }; struct vla_bound_data { struct source_location loc; struct type_descriptor *type; }; struct invalid_value_data { struct source_location loc; struct type_descriptor *type; }; struct nonnull_arg_data { struct source_location loc; }; /* * When compiling with -fsanitize=undefined the compiler expects functions * with the following signatures. The functions are never called directly, * only when undefined behavior is detected in instrumented code. */ void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr); void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data *data, unsigned long ptr); void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_mul_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long old_val); void __ubsan_handle_divrem_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_pointer_overflow(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, unsigned long idx); void __ubsan_handle_unreachable(struct unreachable_data *data); void __ubsan_handle_missing_return(struct unreachable_data *data); void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, unsigned long bound); void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, unsigned long val); void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data #if __GCC_VERSION < 60000 , size_t arg_no #endif ); static void print_loc(const char *func, struct source_location *loc) { const char *f = func; const char func_prefix[] = "__ubsan_handle"; if (!memcmp(f, func_prefix, sizeof(func_prefix) - 1)) f += sizeof(func_prefix); EMSG_RAW("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32, f, loc->file_name, loc->line, loc->column); } static volatile bool ubsan_panic = true; void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, unsigned long ptr __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data *data, unsigned long ptr __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_add_overflow(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_sub_overflow(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_mul_overflow(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_negate_overflow(struct overflow_data *data, unsigned long old_val __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_divrem_overflow(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_pointer_overflow(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data, unsigned long idx __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_unreachable(struct unreachable_data *data) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __noreturn __ubsan_handle_missing_return(struct unreachable_data *data) { print_loc(__func__, &data->loc); panic(); } void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data, unsigned long bound __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_load_invalid_value(struct invalid_value_data *data, unsigned long val __unused) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data #if __GCC_VERSION < 60000 , size_t arg_no __unused #endif ) { print_loc(__func__, &data->loc); if (ubsan_panic) panic(); } optee_os-4.3.0/core/kernel/user_access.c000066400000000000000000000160521464416617300202260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015-2020, 2022 Linaro Limited */ #include #include #include #include #include #include #include #include #include #define BB_ALIGNMENT (sizeof(long) * 2) static struct user_mode_ctx *get_current_uctx(void) { struct ts_session *s = ts_get_current_session(); if (!is_user_mode_ctx(s->ctx)) { /* * We may be called within a PTA session, which doesn't * have a user_mode_ctx. Here, try to retrieve the * user_mode_ctx associated with the calling session. */ s = TAILQ_NEXT(s, link_tsd); if (!s || !is_user_mode_ctx(s->ctx)) return NULL; } return to_user_mode_ctx(s->ctx); } TEE_Result check_user_access(uint32_t flags, const void *uaddr, size_t len) { struct user_mode_ctx *uctx = get_current_uctx(); if (!uctx) return TEE_ERROR_GENERIC; return vm_check_access_rights(uctx, flags, (vaddr_t)uaddr, len); } TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len) { uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; TEE_Result res = TEE_SUCCESS; uaddr = memtag_strip_tag_const(uaddr); res = check_user_access(flags, uaddr, len); if (!res) { enter_user_access(); memcpy(kaddr, uaddr, len); exit_user_access(); } return res; } TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len) { uint32_t flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; TEE_Result res = TEE_SUCCESS; uaddr = memtag_strip_tag(uaddr); res = check_user_access(flags, uaddr, len); if (!res) { enter_user_access(); memcpy(uaddr, kaddr, len); exit_user_access(); } return res; } TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len) { uint32_t flags = TEE_MEMORY_ACCESS_READ; TEE_Result res = TEE_SUCCESS; uaddr = memtag_strip_tag_const(uaddr); res = check_user_access(flags, uaddr, len); if (!res) { enter_user_access(); memcpy(kaddr, uaddr, len); exit_user_access(); } return res; } TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len) { uint32_t flags = TEE_MEMORY_ACCESS_WRITE; TEE_Result res = TEE_SUCCESS; uaddr = memtag_strip_tag(uaddr); res = check_user_access(flags, uaddr, len); if (!res) { enter_user_access(); memcpy(uaddr, kaddr, len); exit_user_access(); } return res; } static void *maybe_tag_bb(void *buf, size_t sz) { static_assert(MEMTAG_GRANULE_SIZE <= BB_ALIGNMENT); if (!MEMTAG_IS_ENABLED) return buf; assert(!((vaddr_t)buf % MEMTAG_GRANULE_SIZE)); return memtag_set_random_tags(buf, ROUNDUP(sz, MEMTAG_GRANULE_SIZE)); } static void maybe_untag_bb(void *buf, size_t sz) { if (MEMTAG_IS_ENABLED) { assert(!((vaddr_t)buf % MEMTAG_GRANULE_SIZE)); memtag_set_tags(buf, ROUNDUP(sz, MEMTAG_GRANULE_SIZE), 0); } } void *bb_alloc(size_t len) { struct user_mode_ctx *uctx = get_current_uctx(); size_t offs = 0; void *bb = NULL; if (uctx && !ADD_OVERFLOW(uctx->bbuf_offs, len, &offs) && offs <= uctx->bbuf_size) { bb = maybe_tag_bb(uctx->bbuf + uctx->bbuf_offs, len); uctx->bbuf_offs = ROUNDUP(offs, BB_ALIGNMENT); } return bb; } static void bb_free_helper(struct user_mode_ctx *uctx, vaddr_t bb, size_t len) { vaddr_t bbuf = (vaddr_t)uctx->bbuf; if (bb >= bbuf && IS_ALIGNED(bb, BB_ALIGNMENT)) { size_t prev_offs = bb - bbuf; /* * Even if we can't update offset we can still invalidate * the memory allocation. */ maybe_untag_bb((void *)bb, len); if (prev_offs + ROUNDUP(len, BB_ALIGNMENT) == uctx->bbuf_offs) uctx->bbuf_offs = prev_offs; } } void bb_free(void *bb, size_t len) { struct user_mode_ctx *uctx = get_current_uctx(); if (uctx) bb_free_helper(uctx, memtag_strip_tag_vaddr(bb), len); } void bb_free_wipe(void *bb, size_t len) { if (bb) memset(bb, 0, len); bb_free(bb, len); } void bb_reset(void) { struct user_mode_ctx *uctx = get_current_uctx(); if (uctx) { /* * Only the part up to the offset have been allocated, so * no need to clear tags beyond that. */ maybe_untag_bb(uctx->bbuf, uctx->bbuf_offs); uctx->bbuf_offs = 0; } } TEE_Result clear_user(void *uaddr, size_t n) { uint32_t flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; TEE_Result res = TEE_SUCCESS; uaddr = memtag_strip_tag(uaddr); res = check_user_access(flags, uaddr, n); if (res) return res; enter_user_access(); memset(uaddr, 0, n); exit_user_access(); return TEE_SUCCESS; } size_t strnlen_user(const void *uaddr, size_t len) { uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; TEE_Result res = TEE_SUCCESS; size_t n = 0; if (!len) return 0; uaddr = memtag_strip_tag_const(uaddr); res = check_user_access(flags, uaddr, len); if (!res) { enter_user_access(); n = strnlen(uaddr, len); exit_user_access(); } return n; } static TEE_Result __bb_memdup_user(TEE_Result (*copy_func)(void *uaddr, const void *kaddr, size_t len), const void *src, size_t len, void **p) { TEE_Result res = TEE_SUCCESS; void *buf = NULL; buf = bb_alloc(len); if (!buf) return TEE_ERROR_OUT_OF_MEMORY; if (len) res = copy_func(buf, src, len); if (res) bb_free(buf, len); else *p = buf; return res; } TEE_Result bb_memdup_user(const void *src, size_t len, void **p) { return __bb_memdup_user(copy_from_user, src, len, p); } TEE_Result bb_memdup_user_private(const void *src, size_t len, void **p) { return __bb_memdup_user(copy_from_user_private, src, len, p); } TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst, size_t *dstlen) { uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; TEE_Result res = TEE_SUCCESS; size_t l = 0; char *d = NULL; src = memtag_strip_tag_const(src); if (maxlen) { res = check_user_access(flags, src, maxlen); if (res) return res; enter_user_access(); l = strnlen(src, maxlen); exit_user_access(); } d = bb_alloc(l + 1); if (!d) return TEE_ERROR_OUT_OF_MEMORY; if (l) { enter_user_access(); memcpy(d, src, l); exit_user_access(); } d[l] = 0; *dst = d; *dstlen = l; return TEE_SUCCESS; } TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr) { uint32_t ref = kaddr_to_uref(kaddr); return copy_to_user_private(uref, &ref, sizeof(ref)); } uint32_t kaddr_to_uref(void *kaddr) { if (MEMTAG_IS_ENABLED) { unsigned int uref_tag_shift = 32 - MEMTAG_TAG_WIDTH; vaddr_t uref = memtag_strip_tag_vaddr(kaddr); uref -= VCORE_START_VA; assert(uref < (UINT32_MAX >> MEMTAG_TAG_WIDTH)); uref |= (vaddr_t)memtag_get_tag(kaddr) << uref_tag_shift; return uref; } assert(((vaddr_t)kaddr - VCORE_START_VA) < UINT32_MAX); return (vaddr_t)kaddr - VCORE_START_VA; } vaddr_t uref_to_vaddr(uint32_t uref) { if (MEMTAG_IS_ENABLED) { vaddr_t u = uref & (UINT32_MAX >> MEMTAG_TAG_WIDTH); unsigned int uref_tag_shift = 32 - MEMTAG_TAG_WIDTH; uint8_t tag = uref >> uref_tag_shift; return memtag_insert_tag_vaddr(VCORE_START_VA + u, tag); } return VCORE_START_VA + uref; } optee_os-4.3.0/core/kernel/user_mode_ctx.c000066400000000000000000000012131464416617300205600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include void user_mode_ctx_print_mappings(struct user_mode_ctx *uctx) { struct vm_region *r = NULL; char flags[7] = { '\0', }; size_t n = 0; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { paddr_t pa = 0; if (r->mobj) mobj_get_pa(r->mobj, r->offset, 0, &pa); mattr_perm_to_str(flags, sizeof(flags), r->attr); EMSG_RAW(" region %2zu: va 0x%0*" PRIxVA " pa 0x%0*" PRIxPA " size 0x%06zx flags %s", n, PRIxVA_WIDTH, r->va, PRIxPA_WIDTH, pa, r->size, flags); n++; } } optee_os-4.3.0/core/kernel/user_ta.c000066400000000000000000000326401464416617300173720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015-2022 Linaro Limited * Copyright (c) 2020, Arm Limited. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static TEE_Result init_utee_param(struct utee_params *up, const struct tee_ta_param *p, void *va[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; size_t n = 0; struct utee_params *up_bbuf = NULL; up_bbuf = bb_alloc(sizeof(struct utee_params)); if (!up_bbuf) return TEE_ERROR_OUT_OF_MEMORY; up_bbuf->types = p->types; for (n = 0; n < TEE_NUM_PARAMS; n++) { uintptr_t a; uintptr_t b; switch (TEE_PARAM_TYPE_GET(p->types, n)) { case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: a = (uintptr_t)va[n]; b = p->u[n].mem.size; break; case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_INOUT: a = p->u[n].val.a; b = p->u[n].val.b; break; default: a = 0; b = 0; break; } /* See comment for struct utee_params in utee_types.h */ up_bbuf->vals[n * 2] = a; up_bbuf->vals[n * 2 + 1] = b; } res = copy_to_user(up, up_bbuf, sizeof(struct utee_params)); bb_free(up_bbuf, sizeof(struct utee_params)); return res; } static void update_from_utee_param(struct tee_ta_param *p, const struct utee_params *up) { TEE_Result res = TEE_SUCCESS; size_t n = 0; struct utee_params *up_bbuf = NULL; res = BB_MEMDUP_USER(up, sizeof(*up), &up_bbuf); if (res) return; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(p->types, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: /* See comment for struct utee_params in utee_types.h */ p->u[n].mem.size = up_bbuf->vals[n * 2 + 1]; break; case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: /* See comment for struct utee_params in utee_types.h */ p->u[n].val.a = up_bbuf->vals[n * 2]; p->u[n].val.b = up_bbuf->vals[n * 2 + 1]; break; default: break; } } bb_free(up_bbuf, sizeof(*up)); } static bool inc_recursion(void) { struct thread_specific_data *tsd = thread_get_tsd(); if (tsd->syscall_recursion >= CFG_CORE_MAX_SYSCALL_RECURSION) { DMSG("Maximum allowed recursion depth reached (%u)", CFG_CORE_MAX_SYSCALL_RECURSION); return false; } tsd->syscall_recursion++; return true; } static void dec_recursion(void) { struct thread_specific_data *tsd = thread_get_tsd(); assert(tsd->syscall_recursion); tsd->syscall_recursion--; } static TEE_Result user_ta_enter(struct ts_session *session, enum utee_entry_func func, uint32_t cmd) { TEE_Result res = TEE_SUCCESS; struct utee_params *usr_params = NULL; uaddr_t usr_stack = 0; struct user_ta_ctx *utc = to_user_ta_ctx(session->ctx); struct tee_ta_session *ta_sess = to_ta_session(session); struct ts_session *ts_sess __maybe_unused = NULL; void *param_va[TEE_NUM_PARAMS] = { NULL }; if (!inc_recursion()) { /* Using this error code since we've run out of resources. */ res = TEE_ERROR_OUT_OF_MEMORY; goto out_clr_cancel; } if (ta_sess->param) { /* Map user space memory */ res = vm_map_param(&utc->uctx, ta_sess->param, param_va); if (res != TEE_SUCCESS) goto out; } /* Switch to user ctx */ ts_push_current_session(session); /* Make room for usr_params at top of stack */ usr_stack = utc->uctx.stack_ptr; usr_stack -= ROUNDUP(sizeof(struct utee_params), STACK_ALIGNMENT); usr_params = (struct utee_params *)usr_stack; if (ta_sess->param) res = init_utee_param(usr_params, ta_sess->param, param_va); else res = clear_user(usr_params, sizeof(*usr_params)); if (res) goto out_pop_session; res = thread_enter_user_mode(func, kaddr_to_uref(session), (vaddr_t)usr_params, cmd, usr_stack, utc->uctx.entry_func, utc->uctx.is_32bit, &utc->ta_ctx.panicked, &utc->ta_ctx.panic_code); thread_user_clear_vfp(&utc->uctx); if (utc->ta_ctx.panicked) { abort_print_current_ts(); DMSG("tee_user_ta_enter: TA panicked with code 0x%x", utc->ta_ctx.panic_code); res = TEE_ERROR_TARGET_DEAD; } else { /* * According to GP spec the origin should allways be set to * the TA after TA execution */ ta_sess->err_origin = TEE_ORIGIN_TRUSTED_APP; } if (ta_sess->param) { /* Copy out value results */ update_from_utee_param(ta_sess->param, usr_params); } out_pop_session: if (ta_sess->param) { /* * Clear out the parameter mappings added with * vm_clean_param() above. */ vm_clean_param(&utc->uctx); } ts_sess = ts_pop_current_session(); assert(ts_sess == session); out: dec_recursion(); out_clr_cancel: /* * Reset the cancel state now that the user TA has returned. The next * time the TA will be invoked will be with a new operation and should * not have an old cancellation pending. */ ta_sess->cancel = false; ta_sess->cancel_mask = true; return res; } static TEE_Result user_ta_enter_open_session(struct ts_session *s) { return user_ta_enter(s, UTEE_ENTRY_FUNC_OPEN_SESSION, 0); } static TEE_Result user_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd) { return user_ta_enter(s, UTEE_ENTRY_FUNC_INVOKE_COMMAND, cmd); } static void user_ta_enter_close_session(struct ts_session *s) { /* Only if the TA was fully initialized by ldelf */ if (!to_user_ta_ctx(s->ctx)->ta_ctx.is_initializing) user_ta_enter(s, UTEE_ENTRY_FUNC_CLOSE_SESSION, 0); } #if defined(CFG_TA_STATS) static TEE_Result user_ta_enter_dump_memstats(struct ts_session *s) { return user_ta_enter(s, UTEE_ENTRY_FUNC_DUMP_MEMSTATS, 0); } #endif static void dump_state_no_ldelf_dbg(struct user_ta_ctx *utc) { user_mode_ctx_print_mappings(&utc->uctx); } static void user_ta_dump_state(struct ts_ctx *ctx) { struct user_ta_ctx *utc = to_user_ta_ctx(ctx); if (utc->uctx.dump_entry_func) { TEE_Result res = ldelf_dump_state(&utc->uctx); if (!res || res == TEE_ERROR_TARGET_DEAD) return; /* * Fall back to dump_state_no_ldelf_dbg() if * ldelf_dump_state() fails for some reason. * * If ldelf_dump_state() failed with panic * we are done since abort_print_current_ts() will be * called which will dump the memory map. */ } dump_state_no_ldelf_dbg(utc); } #ifdef CFG_FTRACE_SUPPORT static void user_ta_dump_ftrace(struct ts_ctx *ctx) { uint32_t prot = TEE_MATTR_URW; struct user_ta_ctx *utc = to_user_ta_ctx(ctx); struct thread_param params[3] = { }; TEE_Result res = TEE_SUCCESS; struct mobj *mobj = NULL; uint8_t *ubuf = NULL; void *buf = NULL; size_t pl_sz = 0; size_t blen = 0, ld_addr_len = 0; vaddr_t va = 0; res = ldelf_dump_ftrace(&utc->uctx, NULL, &blen); if (res != TEE_ERROR_SHORT_BUFFER) return; #define LOAD_ADDR_DUMP_SIZE 64 pl_sz = ROUNDUP(blen + sizeof(TEE_UUID) + LOAD_ADDR_DUMP_SIZE, SMALL_PAGE_SIZE); mobj = thread_rpc_alloc_payload(pl_sz); if (!mobj) { EMSG("Ftrace thread_rpc_alloc_payload failed"); return; } buf = mobj_get_va(mobj, 0, pl_sz); if (!buf) goto out_free_pl; res = vm_map(&utc->uctx, &va, mobj->size, prot, VM_FLAG_EPHEMERAL, mobj, 0); if (res) goto out_free_pl; ubuf = (uint8_t *)va + mobj_get_phys_offs(mobj, mobj->phys_granule); memcpy(ubuf, &ctx->uuid, sizeof(TEE_UUID)); ubuf += sizeof(TEE_UUID); ld_addr_len = snprintk((char *)ubuf, LOAD_ADDR_DUMP_SIZE, "TEE load address @ %#"PRIxVA"\n", VCORE_START_VA); ubuf += ld_addr_len; res = ldelf_dump_ftrace(&utc->uctx, ubuf, &blen); if (res) { EMSG("Ftrace dump failed: %#"PRIx32, res); goto out_unmap_pl; } params[0] = THREAD_PARAM_VALUE(INOUT, 0, 0, 0); params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, sizeof(TEE_UUID)); params[2] = THREAD_PARAM_MEMREF(IN, mobj, sizeof(TEE_UUID), blen + ld_addr_len); res = thread_rpc_cmd(OPTEE_RPC_CMD_FTRACE, 3, params); if (res) EMSG("Ftrace thread_rpc_cmd res: %#"PRIx32, res); out_unmap_pl: res = vm_unmap(&utc->uctx, va, mobj->size); assert(!res); out_free_pl: thread_rpc_free_payload(mobj); } #endif /*CFG_FTRACE_SUPPORT*/ #ifdef CFG_TA_GPROF_SUPPORT static void user_ta_gprof_set_status(enum ts_gprof_status status) { if (status == TS_GPROF_SUSPEND) tee_ta_update_session_utime_suspend(); else tee_ta_update_session_utime_resume(); } #endif /*CFG_TA_GPROF_SUPPORT*/ static void release_utc_state(struct user_ta_ctx *utc) { /* * Close sessions opened by this TA * Note that tee_ta_close_session() removes the item * from the utc->open_sessions list. */ while (!TAILQ_EMPTY(&utc->open_sessions)) { tee_ta_close_session(TAILQ_FIRST(&utc->open_sessions), &utc->open_sessions, KERN_IDENTITY); } vm_info_final(&utc->uctx); /* Free cryp states created by this TA */ tee_svc_cryp_free_states(utc); /* Close cryp objects opened by this TA */ tee_obj_close_all(utc); /* Free emums created by this TA */ tee_svc_storage_close_all_enum(utc); } static void free_utc(struct user_ta_ctx *utc) { release_utc_state(utc); free(utc); } static void user_ta_release_state(struct ts_ctx *ctx) { release_utc_state(to_user_ta_ctx(ctx)); } static void user_ta_ctx_destroy(struct ts_ctx *ctx) { free_utc(to_user_ta_ctx(ctx)); } static uint32_t user_ta_get_instance_id(struct ts_ctx *ctx) { return to_user_ta_ctx(ctx)->uctx.vm_info.asid; } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct ts_ops user_ta_ops __weak __relrodata_unpaged("user_ta_ops") = { .enter_open_session = user_ta_enter_open_session, .enter_invoke_cmd = user_ta_enter_invoke_cmd, .enter_close_session = user_ta_enter_close_session, #if defined(CFG_TA_STATS) .dump_mem_stats = user_ta_enter_dump_memstats, #endif .dump_state = user_ta_dump_state, #ifdef CFG_FTRACE_SUPPORT .dump_ftrace = user_ta_dump_ftrace, #endif .release_state = user_ta_release_state, .destroy = user_ta_ctx_destroy, .get_instance_id = user_ta_get_instance_id, .handle_scall = scall_handle_user_ta, #ifdef CFG_TA_GPROF_SUPPORT .gprof_set_status = user_ta_gprof_set_status, #endif }; static void set_ta_ctx_ops(struct tee_ta_ctx *ctx) { ctx->ts_ctx.ops = &user_ta_ops; } bool __noprof is_user_ta_ctx(struct ts_ctx *ctx) { return ctx && ctx->ops == &user_ta_ops; } static TEE_Result check_ta_store(void) { const struct ts_store_ops *op = NULL; SCATTERED_ARRAY_FOREACH(op, ta_stores, struct ts_store_ops) DMSG("TA store: \"%s\"", op->description); return TEE_SUCCESS; } service_init(check_ta_store); TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid, struct tee_ta_session *s) { TEE_Result res = TEE_SUCCESS; struct user_ta_ctx *utc = NULL; /* * Caller is expected to hold tee_ta_mutex for safe changes * in @s and registering of the context in tee_ctxes list. */ assert(mutex_is_locked(&tee_ta_mutex)); utc = calloc(1, sizeof(struct user_ta_ctx)); if (!utc) return TEE_ERROR_OUT_OF_MEMORY; TAILQ_INIT(&utc->open_sessions); TAILQ_INIT(&utc->cryp_states); TAILQ_INIT(&utc->objects); TAILQ_INIT(&utc->storage_enums); condvar_init(&utc->ta_ctx.busy_cv); utc->ta_ctx.ref_count = 1; /* * Set context TA operation structure. It is required by generic * implementation to identify userland TA versus pseudo TA contexts. */ set_ta_ctx_ops(&utc->ta_ctx); utc->ta_ctx.ts_ctx.uuid = *uuid; res = vm_info_init(&utc->uctx, &utc->ta_ctx.ts_ctx); if (res) { condvar_destroy(&utc->ta_ctx.busy_cv); free_utc(utc); return res; } utc->ta_ctx.is_initializing = true; #ifdef CFG_TA_PAUTH crypto_rng_read(&utc->uctx.keys, sizeof(utc->uctx.keys)); #endif assert(!mutex_trylock(&tee_ta_mutex)); s->ts_sess.ctx = &utc->ta_ctx.ts_ctx; s->ts_sess.handle_scall = s->ts_sess.ctx->ops->handle_scall; /* * Another thread trying to load this same TA may need to wait * until this context is fully initialized. This is needed to * handle single instance TAs. */ TAILQ_INSERT_TAIL(&tee_ctxes, &utc->ta_ctx, link); return TEE_SUCCESS; } TEE_Result tee_ta_complete_user_ta_session(struct tee_ta_session *s) { struct user_ta_ctx *utc = to_user_ta_ctx(s->ts_sess.ctx); TEE_Result res = TEE_SUCCESS; /* * We must not hold tee_ta_mutex while allocating page tables as * that may otherwise lead to a deadlock. */ ts_push_current_session(&s->ts_sess); res = ldelf_load_ldelf(&utc->uctx); if (!res) res = ldelf_init_with_ldelf(&s->ts_sess, &utc->uctx); ts_pop_current_session(); mutex_lock(&tee_ta_mutex); if (!res) { utc->ta_ctx.is_initializing = false; } else { s->ts_sess.ctx = NULL; TAILQ_REMOVE(&tee_ctxes, &utc->ta_ctx, link); condvar_destroy(&utc->ta_ctx.busy_cv); free_utc(utc); } /* The state has changed for the context, notify eventual waiters. */ condvar_broadcast(&tee_ta_init_cv); mutex_unlock(&tee_ta_mutex); return res; } optee_os-4.3.0/core/kernel/wait_queue.c000066400000000000000000000117631464416617300201030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2021, Linaro Limited */ #include #include #include #include #include #include #include #include static unsigned wq_spin_lock; void wq_init(struct wait_queue *wq) { *wq = (struct wait_queue)WAIT_QUEUE_INITIALIZER; } static TEE_Result do_notif(bool wait, int id, uint32_t timeout_ms, const char *cmd_str __maybe_unused, const void *sync_obj __maybe_unused, const char *fname, int lineno __maybe_unused) { TEE_Result res = TEE_SUCCESS; if (fname) DMSG("%s thread %d %p %s:%d", cmd_str, id, sync_obj, fname, lineno); else DMSG("%s thread %d %p", cmd_str, id, sync_obj); if (wait) res = notif_wait_timeout(id + NOTIF_SYNC_VALUE_BASE, timeout_ms); else res = notif_send_sync(id + NOTIF_SYNC_VALUE_BASE); if (res) DMSG("%s thread %d res %#"PRIx32, cmd_str, id, res); return res; } static void slist_add_tail(struct wait_queue *wq, struct wait_queue_elem *wqe) { struct wait_queue_elem *wqe_iter; /* Add elem to end of wait queue */ wqe_iter = SLIST_FIRST(wq); if (wqe_iter) { while (SLIST_NEXT(wqe_iter, link)) wqe_iter = SLIST_NEXT(wqe_iter, link); SLIST_INSERT_AFTER(wqe_iter, wqe, link); } else SLIST_INSERT_HEAD(wq, wqe, link); } void wq_wait_init_condvar(struct wait_queue *wq, struct wait_queue_elem *wqe, struct condvar *cv, bool wait_read) { uint32_t old_itr_status; wqe->handle = thread_get_id(); wqe->done = false; wqe->wait_read = wait_read; wqe->cv = cv; old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); slist_add_tail(wq, wqe); cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); } static TEE_Result wq_wait_final_helper(struct wait_queue *wq, struct wait_queue_elem *wqe, uint32_t timeout_ms, const void *sync_obj, const char *fname, int lineno) { uint32_t old_itr_status = 0; do_notif(true, wqe->handle, timeout_ms, "sleep", sync_obj, fname, lineno); old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); SLIST_REMOVE(wq, wqe, wait_queue_elem, link); cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); if (wqe->done) return TEE_SUCCESS; else return TEE_ERROR_TIMEOUT; } TEE_Result wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe, uint32_t timeout_ms, const void *sync_obj, const char *fname, int lineno) { return wq_wait_final_helper(wq, wqe, timeout_ms, sync_obj, fname, lineno); } void wq_wake_next(struct wait_queue *wq, const void *sync_obj, const char *fname, int lineno) { uint32_t old_itr_status; struct wait_queue_elem *wqe; int handle = -1; bool do_wakeup = false; bool wake_type_assigned = false; bool wake_read = false; /* avoid gcc warning */ /* * If next type is wait_read wakeup all wqe with wait_read true. * If next type isn't wait_read wakeup only the first wqe which isn't * done. */ while (true) { old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); SLIST_FOREACH(wqe, wq, link) { if (wqe->cv) continue; if (wqe->done) continue; if (!wake_type_assigned) { wake_read = wqe->wait_read; wake_type_assigned = true; } if (wqe->wait_read != wake_read) continue; wqe->done = true; handle = wqe->handle; do_wakeup = true; break; } cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); if (do_wakeup) do_notif(false, handle, 0, "wake ", sync_obj, fname, lineno); if (!do_wakeup || !wake_read) break; do_wakeup = false; } } void wq_promote_condvar(struct wait_queue *wq, struct condvar *cv, bool only_one, const void *sync_obj __unused, const char *fname, int lineno __maybe_unused) { uint32_t old_itr_status; struct wait_queue_elem *wqe; if (!cv) return; old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); /* * Find condvar waiter(s) and promote each to an active waiter. * This is a bit unfair to eventual other active waiters as a * condvar waiter is added to the queue when waiting for the * condvar. */ SLIST_FOREACH(wqe, wq, link) { if (wqe->cv == cv) { if (fname) FMSG("promote thread %u %p %s:%d", wqe->handle, (void *)cv->m, fname, lineno); else FMSG("promote thread %u %p", wqe->handle, (void *)cv->m); wqe->cv = NULL; if (only_one) break; } } cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); } bool wq_have_condvar(struct wait_queue *wq, struct condvar *cv) { uint32_t old_itr_status; struct wait_queue_elem *wqe; bool rc = false; old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); SLIST_FOREACH(wqe, wq, link) { if (wqe->cv == cv) { rc = true; break; } } cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); return rc; } bool wq_is_empty(struct wait_queue *wq) { uint32_t old_itr_status; bool ret; old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock); ret = SLIST_EMPTY(wq); cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status); return ret; } optee_os-4.3.0/core/lib/000077500000000000000000000000001464416617300150455ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libfdt/000077500000000000000000000000001464416617300163115ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libfdt/README.license000066400000000000000000000055271464416617300206230ustar00rootroot00000000000000Licensing and contribution policy of dtc and libfdt =================================================== This dtc package contains two pieces of software: dtc itself, and libfdt which comprises the files in the libfdt/ subdirectory. These two pieces of software, although closely related, are quite distinct. dtc does not incorporate or rely on libfdt for its operation, nor vice versa. It is important that these two pieces of software have different license conditions. As SPDX license tags in each source file attest, dtc is licensed under the GNU GPL. The full text of the GPL can be found in the file entitled 'GPL' which should be included in this package. dtc code, therefore, may not be incorporated into works which do not have a GPL compatible license. libfdt, however, is GPL/BSD dual-licensed. That is, it may be used either under the terms of the GPL, or under the terms of the 2-clause BSD license (aka the ISC license). The full terms of that license can be found are in the file entitled 'BSD-2-Clause'. This is, in practice, equivalent to being BSD licensed, since the terms of the BSD license are strictly more permissive than the GPL. I made the decision to license libfdt in this way because I want to encourage widespread and correct usage of flattened device trees, including by proprietary or otherwise GPL-incompatible firmware or tools. Allowing libfdt to be used under the terms of the BSD license makes that it easier for vendors or authors of such software to do so. This does mean that libfdt code could be "stolen" - say, included in a proprietary fimware and extended without contributing those extensions back to the libfdt mainline. While I hope that doesn't happen, I believe the goal of allowing libfdt to be widely used is more important than avoiding that. libfdt is quite small, and hardly rocket science; so the incentive for such impolite behaviour is small, and the inconvenience caused thereby is not dire. Licenses such as the LGPL which would allow code to be used in non-GPL software, but also require contributions to be returned were considered. However, libfdt is designed to be used in firmwares and other environments with unusual technical constraints. It's difficult to anticipate all possible changes which might be needed to meld libfdt into such environments and so difficult to suitably word a license that puts the boundary between what is and isn't permitted in the intended place. Again, I judged encouraging widespread use of libfdt by keeping the license terms simple and familiar to be the more important goal. **IMPORTANT** It's intended that all of libfdt as released remain permissively licensed this way. Therefore only contributions which are released under these terms can be merged into the libfdt mainline. David Gibson (principal original author of dtc and libfdt) 2 November 2007 optee_os-4.3.0/core/lib/libfdt/fdt.c000066400000000000000000000150271464416617300172370ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" /* * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks * that the given buffer contains what appears to be a flattened * device tree with sane information in its header. */ int32_t fdt_ro_probe_(const void *fdt) { uint32_t totalsize = fdt_totalsize(fdt); if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION; if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) return -FDT_ERR_BADVERSION; } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ if (fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE; } else { return -FDT_ERR_BADMAGIC; } if (totalsize < INT32_MAX) return totalsize; else return -FDT_ERR_TRUNCATED; } static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) { return (off >= hdrsize) && (off <= totalsize); } static int check_block_(uint32_t hdrsize, uint32_t totalsize, uint32_t base, uint32_t size) { if (!check_off_(hdrsize, totalsize, base)) return 0; /* block start out of bounds */ if ((base + size) < base) return 0; /* overflow */ if (!check_off_(hdrsize, totalsize, base + size)) return 0; /* block end out of bounds */ return 1; } size_t fdt_header_size_(uint32_t version) { if (version <= 1) return FDT_V1_SIZE; else if (version <= 2) return FDT_V2_SIZE; else if (version <= 3) return FDT_V3_SIZE; else if (version <= 16) return FDT_V16_SIZE; else return FDT_V17_SIZE; } int fdt_check_header(const void *fdt) { size_t hdrsize; if (fdt_magic(fdt) != FDT_MAGIC) return -FDT_ERR_BADMAGIC; hdrsize = fdt_header_size(fdt); if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) return -FDT_ERR_BADVERSION; if (fdt_version(fdt) < fdt_last_comp_version(fdt)) return -FDT_ERR_BADVERSION; if ((fdt_totalsize(fdt) < hdrsize) || (fdt_totalsize(fdt) > INT_MAX)) return -FDT_ERR_TRUNCATED; /* Bounds check memrsv block */ if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) return -FDT_ERR_TRUNCATED; /* Bounds check structure block */ if (fdt_version(fdt) < 17) { if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_dt_struct(fdt))) return -FDT_ERR_TRUNCATED; } else { if (!check_block_(hdrsize, fdt_totalsize(fdt), fdt_off_dt_struct(fdt), fdt_size_dt_struct(fdt))) return -FDT_ERR_TRUNCATED; } /* Bounds check strings block */ if (!check_block_(hdrsize, fdt_totalsize(fdt), fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) return -FDT_ERR_TRUNCATED; return 0; } const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { unsigned absoffset = offset + fdt_off_dt_struct(fdt); if ((absoffset < offset) || ((absoffset + len) < absoffset) || (absoffset + len) > fdt_totalsize(fdt)) return NULL; if (fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; return fdt_offset_ptr_(fdt, offset); } uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) { const fdt32_t *tagp, *lenp; uint32_t tag; int offset = startoffset; const char *p; *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); if (!tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; *nextoffset = -FDT_ERR_BADSTRUCTURE; switch (tag) { case FDT_BEGIN_NODE: /* skip name */ do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); if (!p) return FDT_END; /* premature end */ break; case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); if (!lenp) return FDT_END; /* premature end */ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + fdt32_to_cpu(*lenp); if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) offset += 4; break; case FDT_END: case FDT_END_NODE: case FDT_NOP: break; default: return FDT_END; } if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) return FDT_END; /* premature end */ *nextoffset = FDT_TAGALIGN(offset); return tag; } int fdt_check_node_offset_(const void *fdt, int offset) { if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) return -FDT_ERR_BADOFFSET; return offset; } int fdt_check_prop_offset_(const void *fdt, int offset) { if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) return -FDT_ERR_BADOFFSET; return offset; } int fdt_next_node(const void *fdt, int offset, int *depth) { int nextoffset = 0; uint32_t tag; if (offset >= 0) if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) return nextoffset; do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_PROP: case FDT_NOP: break; case FDT_BEGIN_NODE: if (depth) (*depth)++; break; case FDT_END_NODE: if (depth && ((--(*depth)) < 0)) return nextoffset; break; case FDT_END: if ((nextoffset >= 0) || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) return -FDT_ERR_NOTFOUND; else return nextoffset; } } while (tag != FDT_BEGIN_NODE); return offset; } int fdt_first_subnode(const void *fdt, int offset) { int depth = 0; offset = fdt_next_node(fdt, offset, &depth); if (offset < 0 || depth != 1) return -FDT_ERR_NOTFOUND; return offset; } int fdt_next_subnode(const void *fdt, int offset) { int depth = 1; /* * With respect to the parent, the depth of the next subnode will be * the same as the last. */ do { offset = fdt_next_node(fdt, offset, &depth); if (offset < 0 || depth < 1) return -FDT_ERR_NOTFOUND; } while (depth > 1); return offset; } const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) { int len = strlen(s) + 1; const char *last = strtab + tabsize - len; const char *p; for (p = strtab; p <= last; p++) if (memcmp(p, s, len) == 0) return p; return NULL; } int fdt_move(const void *fdt, void *buf, int bufsize) { FDT_RO_PROBE(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; memmove(buf, fdt, fdt_totalsize(fdt)); return 0; } optee_os-4.3.0/core/lib/libfdt/fdt_addresses.c000066400000000000000000000042061464416617300212710ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2014 David Gibson * Copyright (C) 2018 embedded brains GmbH */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" static int fdt_cells(const void *fdt, int nodeoffset, const char *name) { const fdt32_t *c; uint32_t val; int len; c = fdt_getprop(fdt, nodeoffset, name, &len); if (!c) return len; if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; val = fdt32_to_cpu(*c); if (val > FDT_MAX_NCELLS) return -FDT_ERR_BADNCELLS; return (int)val; } int fdt_address_cells(const void *fdt, int nodeoffset) { int val; val = fdt_cells(fdt, nodeoffset, "#address-cells"); if (val == 0) return -FDT_ERR_BADNCELLS; if (val == -FDT_ERR_NOTFOUND) return 2; return val; } int fdt_size_cells(const void *fdt, int nodeoffset) { int val; val = fdt_cells(fdt, nodeoffset, "#size-cells"); if (val == -FDT_ERR_NOTFOUND) return 1; return val; } /* This function assumes that [address|size]_cells is 1 or 2 */ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, const char *name, uint64_t addr, uint64_t size) { int addr_cells, size_cells, ret; uint8_t data[sizeof(fdt64_t) * 2], *prop; ret = fdt_address_cells(fdt, parent); if (ret < 0) return ret; addr_cells = ret; ret = fdt_size_cells(fdt, parent); if (ret < 0) return ret; size_cells = ret; /* check validity of address */ prop = data; if (addr_cells == 1) { if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) return -FDT_ERR_BADVALUE; fdt32_st(prop, (uint32_t)addr); } else if (addr_cells == 2) { fdt64_st(prop, addr); } else { return -FDT_ERR_BADNCELLS; } /* check validity of size */ prop += addr_cells * sizeof(fdt32_t); if (size_cells == 1) { if (size > UINT32_MAX) return -FDT_ERR_BADVALUE; fdt32_st(prop, (uint32_t)size); } else if (size_cells == 2) { fdt64_st(prop, size); } else { return -FDT_ERR_BADNCELLS; } return fdt_appendprop(fdt, nodeoffset, name, data, (addr_cells + size_cells) * sizeof(fdt32_t)); } optee_os-4.3.0/core/lib/libfdt/fdt_empty_tree.c000066400000000000000000000012011464416617300214610ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2012 David Gibson, IBM Corporation. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" int fdt_create_empty_tree(void *buf, int bufsize) { int err; err = fdt_create(buf, bufsize); if (err) return err; err = fdt_finish_reservemap(buf); if (err) return err; err = fdt_begin_node(buf, ""); if (err) return err; err = fdt_end_node(buf); if (err) return err; err = fdt_finish(buf); if (err) return err; return fdt_open_into(buf, buf, bufsize); } optee_os-4.3.0/core/lib/libfdt/fdt_overlay.c000066400000000000000000000532031464416617300207760ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2016 Free Electrons * Copyright (C) 2016 NextThing Co. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" /** * overlay_get_target_phandle - retrieves the target phandle of a fragment * @fdto: pointer to the device tree overlay blob * @fragment: node offset of the fragment in the overlay * * overlay_get_target_phandle() retrieves the target phandle of an * overlay fragment when that fragment uses a phandle (target * property) instead of a path (target-path property). * * returns: * the phandle pointed by the target property * 0, if the phandle was not found * -1, if the phandle was malformed */ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) { const fdt32_t *val; int len; val = fdt_getprop(fdto, fragment, "target", &len); if (!val) return 0; if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) return (uint32_t)-1; return fdt32_to_cpu(*val); } /** * overlay_get_target - retrieves the offset of a fragment's target * @fdt: Base device tree blob * @fdto: Device tree overlay blob * @fragment: node offset of the fragment in the overlay * @pathp: pointer which receives the path of the target (or NULL) * * overlay_get_target() retrieves the target offset in the base * device tree of a fragment, no matter how the actual targeting is * done (through a phandle or a path) * * returns: * the targeted node offset in the base device tree * Negative error code on error */ static int overlay_get_target(const void *fdt, const void *fdto, int fragment, char const **pathp) { uint32_t phandle; const char *path = NULL; int path_len = 0, ret; /* Try first to do a phandle based lookup */ phandle = overlay_get_target_phandle(fdto, fragment); if (phandle == (uint32_t)-1) return -FDT_ERR_BADPHANDLE; /* no phandle, try path */ if (!phandle) { /* And then a path based lookup */ path = fdt_getprop(fdto, fragment, "target-path", &path_len); if (path) ret = fdt_path_offset(fdt, path); else ret = path_len; } else ret = fdt_node_offset_by_phandle(fdt, phandle); /* * If we haven't found either a target or a * target-path property in a node that contains a * __overlay__ subnode (we wouldn't be called * otherwise), consider it a improperly written * overlay */ if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) ret = -FDT_ERR_BADOVERLAY; /* return on error */ if (ret < 0) return ret; /* return pointer to path (if available) */ if (pathp) *pathp = path ? path : NULL; return ret; } /** * overlay_phandle_add_offset - Increases a phandle by an offset * @fdt: Base device tree blob * @node: Device tree overlay blob * @name: Name of the property to modify (phandle or linux,phandle) * @delta: offset to apply * * overlay_phandle_add_offset() increments a node phandle by a given * offset. * * returns: * 0 on success. * Negative error code on error */ static int overlay_phandle_add_offset(void *fdt, int node, const char *name, uint32_t delta) { const fdt32_t *val; uint32_t adj_val; int len; val = fdt_getprop(fdt, node, name, &len); if (!val) return len; if (len != sizeof(*val)) return -FDT_ERR_BADPHANDLE; adj_val = fdt32_to_cpu(*val); if ((adj_val + delta) < adj_val) return -FDT_ERR_NOPHANDLES; adj_val += delta; if (adj_val == (uint32_t)-1) return -FDT_ERR_NOPHANDLES; return fdt_setprop_inplace_u32(fdt, node, name, adj_val); } /** * overlay_adjust_node_phandles - Offsets the phandles of a node * @fdto: Device tree overlay blob * @node: Offset of the node we want to adjust * @delta: Offset to shift the phandles of * * overlay_adjust_node_phandles() adds a constant to all the phandles * of a given node. This is mainly use as part of the overlay * application process, when we want to update all the overlay * phandles to not conflict with the overlays of the base device tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_adjust_node_phandles(void *fdto, int node, uint32_t delta) { int child; int ret; ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); if (ret && ret != -FDT_ERR_NOTFOUND) return ret; ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); if (ret && ret != -FDT_ERR_NOTFOUND) return ret; fdt_for_each_subnode(child, fdto, node) { ret = overlay_adjust_node_phandles(fdto, child, delta); if (ret) return ret; } return 0; } /** * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay * @fdto: Device tree overlay blob * @delta: Offset to shift the phandles of * * overlay_adjust_local_phandles() adds a constant to all the * phandles of an overlay. This is mainly use as part of the overlay * application process, when we want to update all the overlay * phandles to not conflict with the overlays of the base device tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) { /* * Start adjusting the phandles from the overlay root */ return overlay_adjust_node_phandles(fdto, 0, delta); } /** * overlay_update_local_node_references - Adjust the overlay references * @fdto: Device tree overlay blob * @tree_node: Node offset of the node to operate on * @fixup_node: Node offset of the matching local fixups node * @delta: Offset to shift the phandles of * * overlay_update_local_nodes_references() update the phandles * pointing to a node within the device tree overlay by adding a * constant delta. * * This is mainly used as part of a device tree application process, * where you want the device tree overlays phandles to not conflict * with the ones from the base device tree before merging them. * * returns: * 0 on success * Negative error code on failure */ static int overlay_update_local_node_references(void *fdto, int tree_node, int fixup_node, uint32_t delta) { int fixup_prop; int fixup_child; int ret; fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { const fdt32_t *fixup_val; const char *tree_val; const char *name; int fixup_len; int tree_len; int i; fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, &name, &fixup_len); if (!fixup_val) return fixup_len; if (fixup_len % sizeof(uint32_t)) return -FDT_ERR_BADOVERLAY; tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); if (!tree_val) { if (tree_len == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; return tree_len; } for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { fdt32_t adj_val; uint32_t poffset; poffset = fdt32_to_cpu(fixup_val[i]); /* * phandles to fixup can be unaligned. * * Use a memcpy for the architectures that do * not support unaligned accesses. */ memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); ret = fdt_setprop_inplace_namelen_partial(fdto, tree_node, name, strlen(name), poffset, &adj_val, sizeof(adj_val)); if (ret == -FDT_ERR_NOSPACE) return -FDT_ERR_BADOVERLAY; if (ret) return ret; } } fdt_for_each_subnode(fixup_child, fdto, fixup_node) { const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL); int tree_child; tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name); if (tree_child == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; if (tree_child < 0) return tree_child; ret = overlay_update_local_node_references(fdto, tree_child, fixup_child, delta); if (ret) return ret; } return 0; } /** * overlay_update_local_references - Adjust the overlay references * @fdto: Device tree overlay blob * @delta: Offset to shift the phandles of * * overlay_update_local_references() update all the phandles pointing * to a node within the device tree overlay by adding a constant * delta to not conflict with the base overlay. * * This is mainly used as part of a device tree application process, * where you want the device tree overlays phandles to not conflict * with the ones from the base device tree before merging them. * * returns: * 0 on success * Negative error code on failure */ static int overlay_update_local_references(void *fdto, uint32_t delta) { int fixups; fixups = fdt_path_offset(fdto, "/__local_fixups__"); if (fixups < 0) { /* There's no local phandles to adjust, bail out */ if (fixups == -FDT_ERR_NOTFOUND) return 0; return fixups; } /* * Update our local references from the root of the tree */ return overlay_update_local_node_references(fdto, 0, fixups, delta); } /** * overlay_fixup_one_phandle - Set an overlay phandle to the base one * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * @symbols_off: Node offset of the symbols node in the base device tree * @path: Path to a node holding a phandle in the overlay * @path_len: number of path characters to consider * @name: Name of the property holding the phandle reference in the overlay * @name_len: number of name characters to consider * @poffset: Offset within the overlay property where the phandle is stored * @label: Label of the node referenced by the phandle * * overlay_fixup_one_phandle() resolves an overlay phandle pointing to * a node in the base device tree. * * This is part of the device tree overlay application process, when * you want all the phandles in the overlay to point to the actual * base dt nodes. * * returns: * 0 on success * Negative error code on failure */ static int overlay_fixup_one_phandle(void *fdt, void *fdto, int symbols_off, const char *path, uint32_t path_len, const char *name, uint32_t name_len, int poffset, const char *label) { const char *symbol_path; uint32_t phandle; fdt32_t phandle_prop; int symbol_off, fixup_off; int prop_len; if (symbols_off < 0) return symbols_off; symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len); if (!symbol_path) return prop_len; symbol_off = fdt_path_offset(fdt, symbol_path); if (symbol_off < 0) return symbol_off; phandle = fdt_get_phandle(fdt, symbol_off); if (!phandle) return -FDT_ERR_NOTFOUND; fixup_off = fdt_path_offset_namelen(fdto, path, path_len); if (fixup_off == -FDT_ERR_NOTFOUND) return -FDT_ERR_BADOVERLAY; if (fixup_off < 0) return fixup_off; phandle_prop = cpu_to_fdt32(phandle); return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, name, name_len, poffset, &phandle_prop, sizeof(phandle_prop)); } /** * overlay_fixup_phandle - Set an overlay phandle to the base one * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * @symbols_off: Node offset of the symbols node in the base device tree * @property: Property offset in the overlay holding the list of fixups * * overlay_fixup_phandle() resolves all the overlay phandles pointed * to in a __fixups__ property, and updates them to match the phandles * in use in the base device tree. * * This is part of the device tree overlay application process, when * you want all the phandles in the overlay to point to the actual * base dt nodes. * * returns: * 0 on success * Negative error code on failure */ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, int property) { const char *value; const char *label; int len; value = fdt_getprop_by_offset(fdto, property, &label, &len); if (!value) { if (len == -FDT_ERR_NOTFOUND) return -FDT_ERR_INTERNAL; return len; } do { const char *path, *name, *fixup_end; const char *fixup_str = value; uint32_t path_len, name_len; uint32_t fixup_len; char *sep, *endptr; int poffset, ret; fixup_end = memchr(value, '\0', len); if (!fixup_end) return -FDT_ERR_BADOVERLAY; fixup_len = fixup_end - fixup_str; len -= fixup_len + 1; value += fixup_len + 1; path = fixup_str; sep = memchr(fixup_str, ':', fixup_len); if (!sep || *sep != ':') return -FDT_ERR_BADOVERLAY; path_len = sep - path; if (path_len == (fixup_len - 1)) return -FDT_ERR_BADOVERLAY; fixup_len -= path_len + 1; name = sep + 1; sep = memchr(name, ':', fixup_len); if (!sep || *sep != ':') return -FDT_ERR_BADOVERLAY; name_len = sep - name; if (!name_len) return -FDT_ERR_BADOVERLAY; poffset = strtoul(sep + 1, &endptr, 10); if ((*endptr != '\0') || (endptr <= (sep + 1))) return -FDT_ERR_BADOVERLAY; ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, path, path_len, name, name_len, poffset, label); if (ret) return ret; } while (len > 0); return 0; } /** * overlay_fixup_phandles - Resolve the overlay phandles to the base * device tree * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * * overlay_fixup_phandles() resolves all the overlay phandles pointing * to nodes in the base device tree. * * This is one of the steps of the device tree overlay application * process, when you want all the phandles in the overlay to point to * the actual base dt nodes. * * returns: * 0 on success * Negative error code on failure */ static int overlay_fixup_phandles(void *fdt, void *fdto) { int fixups_off, symbols_off; int property; /* We can have overlays without any fixups */ fixups_off = fdt_path_offset(fdto, "/__fixups__"); if (fixups_off == -FDT_ERR_NOTFOUND) return 0; /* nothing to do */ if (fixups_off < 0) return fixups_off; /* And base DTs without symbols */ symbols_off = fdt_path_offset(fdt, "/__symbols__"); if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) return symbols_off; fdt_for_each_property_offset(property, fdto, fixups_off) { int ret; ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); if (ret) return ret; } return 0; } /** * overlay_apply_node - Merges a node into the base device tree * @fdt: Base Device Tree blob * @target: Node offset in the base device tree to apply the fragment to * @fdto: Device tree overlay blob * @node: Node offset in the overlay holding the changes to merge * * overlay_apply_node() merges a node into a target base device tree * node pointed. * * This is part of the final step in the device tree overlay * application process, when all the phandles have been adjusted and * resolved and you just have to merge overlay into the base device * tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_apply_node(void *fdt, int target, void *fdto, int node) { int property; int subnode; fdt_for_each_property_offset(property, fdto, node) { const char *name; const void *prop; int prop_len; int ret; prop = fdt_getprop_by_offset(fdto, property, &name, &prop_len); if (prop_len == -FDT_ERR_NOTFOUND) return -FDT_ERR_INTERNAL; if (prop_len < 0) return prop_len; ret = fdt_setprop(fdt, target, name, prop, prop_len); if (ret) return ret; } fdt_for_each_subnode(subnode, fdto, node) { const char *name = fdt_get_name(fdto, subnode, NULL); int nnode; int ret; nnode = fdt_add_subnode(fdt, target, name); if (nnode == -FDT_ERR_EXISTS) { nnode = fdt_subnode_offset(fdt, target, name); if (nnode == -FDT_ERR_NOTFOUND) return -FDT_ERR_INTERNAL; } if (nnode < 0) return nnode; ret = overlay_apply_node(fdt, nnode, fdto, subnode); if (ret) return ret; } return 0; } /** * overlay_merge - Merge an overlay into its base device tree * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * * overlay_merge() merges an overlay into its base device tree. * * This is the next to last step in the device tree overlay application * process, when all the phandles have been adjusted and resolved and * you just have to merge overlay into the base device tree. * * returns: * 0 on success * Negative error code on failure */ static int overlay_merge(void *fdt, void *fdto) { int fragment; fdt_for_each_subnode(fragment, fdto, 0) { int overlay; int target; int ret; /* * Each fragments will have an __overlay__ node. If * they don't, it's not supposed to be merged */ overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); if (overlay == -FDT_ERR_NOTFOUND) continue; if (overlay < 0) return overlay; target = overlay_get_target(fdt, fdto, fragment, NULL); if (target < 0) return target; ret = overlay_apply_node(fdt, target, fdto, overlay); if (ret) return ret; } return 0; } static int get_path_len(const void *fdt, int nodeoffset) { int len = 0, namelen; const char *name; FDT_RO_PROBE(fdt); for (;;) { name = fdt_get_name(fdt, nodeoffset, &namelen); if (!name) return namelen; /* root? we're done */ if (namelen == 0) break; nodeoffset = fdt_parent_offset(fdt, nodeoffset); if (nodeoffset < 0) return nodeoffset; len += namelen + 1; } /* in case of root pretend it's "/" */ if (len == 0) len++; return len; } /** * overlay_symbol_update - Update the symbols of base tree after a merge * @fdt: Base Device Tree blob * @fdto: Device tree overlay blob * * overlay_symbol_update() updates the symbols of the base tree with the * symbols of the applied overlay * * This is the last step in the device tree overlay application * process, allowing the reference of overlay symbols by subsequent * overlay operations. * * returns: * 0 on success * Negative error code on failure */ static int overlay_symbol_update(void *fdt, void *fdto) { int root_sym, ov_sym, prop, path_len, fragment, target; int len, frag_name_len, ret, rel_path_len; const char *s, *e; const char *path; const char *name; const char *frag_name; const char *rel_path; const char *target_path; char *buf; void *p; ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); /* if no overlay symbols exist no problem */ if (ov_sym < 0) return 0; root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); /* it no root symbols exist we should create them */ if (root_sym == -FDT_ERR_NOTFOUND) root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); /* any error is fatal now */ if (root_sym < 0) return root_sym; /* iterate over each overlay symbol */ fdt_for_each_property_offset(prop, fdto, ov_sym) { path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); if (!path) return path_len; /* verify it's a string property (terminated by a single \0) */ if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) return -FDT_ERR_BADVALUE; /* keep end marker to avoid strlen() */ e = path + path_len; if (*path != '/') return -FDT_ERR_BADVALUE; /* get fragment name first */ s = strchr(path + 1, '/'); if (!s) { /* Symbol refers to something that won't end * up in the target tree */ continue; } frag_name = path + 1; frag_name_len = s - path - 1; /* verify format; safe since "s" lies in \0 terminated prop */ len = sizeof("/__overlay__/") - 1; if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { /* //__overlay__/ */ rel_path = s + len; rel_path_len = e - rel_path; } else if ((e - s) == len && (memcmp(s, "/__overlay__", len - 1) == 0)) { /* //__overlay__ */ rel_path = ""; rel_path_len = 0; } else { /* Symbol refers to something that won't end * up in the target tree */ continue; } /* find the fragment index in which the symbol lies */ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, frag_name_len); /* not found? */ if (ret < 0) return -FDT_ERR_BADOVERLAY; fragment = ret; /* an __overlay__ subnode must exist */ ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); if (ret < 0) return -FDT_ERR_BADOVERLAY; /* get the target of the fragment */ ret = overlay_get_target(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; /* if we have a target path use */ if (!target_path) { ret = get_path_len(fdt, target); if (ret < 0) return ret; len = ret; } else { len = strlen(target_path); } ret = fdt_setprop_placeholder(fdt, root_sym, name, len + (len > 1) + rel_path_len + 1, &p); if (ret < 0) return ret; if (!target_path) { /* again in case setprop_placeholder changed it */ ret = overlay_get_target(fdt, fdto, fragment, &target_path); if (ret < 0) return ret; target = ret; } buf = p; if (len > 1) { /* target is not root */ if (!target_path) { ret = fdt_get_path(fdt, target, buf, len + 1); if (ret < 0) return ret; } else memcpy(buf, target_path, len + 1); } else len--; buf[len] = '/'; memcpy(buf + len + 1, rel_path, rel_path_len); buf[len + 1 + rel_path_len] = '\0'; } return 0; } int fdt_overlay_apply(void *fdt, void *fdto) { uint32_t delta; int ret; FDT_RO_PROBE(fdt); FDT_RO_PROBE(fdto); ret = fdt_find_max_phandle(fdt, &delta); if (ret) goto err; ret = overlay_adjust_local_phandles(fdto, delta); if (ret) goto err; ret = overlay_update_local_references(fdto, delta); if (ret) goto err; ret = overlay_fixup_phandles(fdt, fdto); if (ret) goto err; ret = overlay_merge(fdt, fdto); if (ret) goto err; ret = overlay_symbol_update(fdt, fdto); if (ret) goto err; /* * The overlay has been damaged, erase its magic. */ fdt_set_magic(fdto, ~0); return 0; err: /* * The overlay might have been damaged, erase its magic. */ fdt_set_magic(fdto, ~0); /* * The base device tree might have been damaged, erase its * magic. */ fdt_set_magic(fdt, ~0); return ret; } optee_os-4.3.0/core/lib/libfdt/fdt_ro.c000066400000000000000000000447331464416617300177450ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" static int fdt_nodename_eq_(const void *fdt, int offset, const char *s, int len) { int olen; const char *p = fdt_get_name(fdt, offset, &olen); if (!p || olen < len) /* short match */ return 0; if (memcmp(p, s, len) != 0) return 0; if (p[len] == '\0') return 1; else if (!memchr(s, '@', len) && (p[len] == '@')) return 1; else return 0; } const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) { int32_t totalsize = fdt_ro_probe_(fdt); uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); size_t len; int err; const char *s, *n; err = totalsize; if (totalsize < 0) goto fail; err = -FDT_ERR_BADOFFSET; if (absoffset >= totalsize) goto fail; len = totalsize - absoffset; if (fdt_magic(fdt) == FDT_MAGIC) { if (stroffset < 0) goto fail; if (fdt_version(fdt) >= 17) { if (stroffset >= fdt_size_dt_strings(fdt)) goto fail; if ((fdt_size_dt_strings(fdt) - stroffset) < len) len = fdt_size_dt_strings(fdt) - stroffset; } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { if ((stroffset >= 0) || (stroffset < -fdt_size_dt_strings(fdt))) goto fail; if ((-stroffset) < len) len = -stroffset; } else { err = -FDT_ERR_INTERNAL; goto fail; } s = (const char *)fdt + absoffset; n = memchr(s, '\0', len); if (!n) { /* missing terminating NULL */ err = -FDT_ERR_TRUNCATED; goto fail; } if (lenp) *lenp = n - s; return s; fail: if (lenp) *lenp = err; return NULL; } const char *fdt_string(const void *fdt, int stroffset) { return fdt_get_string(fdt, stroffset, NULL); } static int fdt_string_eq_(const void *fdt, int stroffset, const char *s, int len) { int slen; const char *p = fdt_get_string(fdt, stroffset, &slen); return p && (slen == len) && (memcmp(p, s, len) == 0); } int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) { uint32_t max = 0; int offset = -1; while (true) { uint32_t value; offset = fdt_next_node(fdt, offset, NULL); if (offset < 0) { if (offset == -FDT_ERR_NOTFOUND) break; return offset; } value = fdt_get_phandle(fdt, offset); if (value > max) max = value; } if (phandle) *phandle = max; return 0; } int fdt_generate_phandle(const void *fdt, uint32_t *phandle) { uint32_t max; int err; err = fdt_find_max_phandle(fdt, &max); if (err < 0) return err; if (max == FDT_MAX_PHANDLE) return -FDT_ERR_NOPHANDLES; if (phandle) *phandle = max + 1; return 0; } static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { int offset = n * sizeof(struct fdt_reserve_entry); int absoffset = fdt_off_mem_rsvmap(fdt) + offset; if (absoffset < fdt_off_mem_rsvmap(fdt)) return NULL; if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) return NULL; return fdt_mem_rsv_(fdt, n); } int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { const struct fdt_reserve_entry *re; FDT_RO_PROBE(fdt); re = fdt_mem_rsv(fdt, n); if (!re) return -FDT_ERR_BADOFFSET; *address = fdt64_ld(&re->address); *size = fdt64_ld(&re->size); return 0; } int fdt_num_mem_rsv(const void *fdt) { int i; const struct fdt_reserve_entry *re; for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { if (fdt64_ld(&re->size) == 0) return i; } return -FDT_ERR_TRUNCATED; } static int nextprop_(const void *fdt, int offset) { uint32_t tag; int nextoffset; do { tag = fdt_next_tag(fdt, offset, &nextoffset); switch (tag) { case FDT_END: if (nextoffset >= 0) return -FDT_ERR_BADSTRUCTURE; else return nextoffset; case FDT_PROP: return offset; } offset = nextoffset; } while (tag == FDT_NOP); return -FDT_ERR_NOTFOUND; } int fdt_subnode_offset_namelen(const void *fdt, int offset, const char *name, int namelen) { int depth; FDT_RO_PROBE(fdt); for (depth = 0; (offset >= 0) && (depth >= 0); offset = fdt_next_node(fdt, offset, &depth)) if ((depth == 1) && fdt_nodename_eq_(fdt, offset, name, namelen)) return offset; if (depth < 0) return -FDT_ERR_NOTFOUND; return offset; /* error */ } int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name) { return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); } int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) { const char *end = path + namelen; const char *p = path; int offset = 0; FDT_RO_PROBE(fdt); /* see if we have an alias */ if (*path != '/') { const char *q = memchr(path, '/', end - p); if (!q) q = end; p = fdt_get_alias_namelen(fdt, p, q - p); if (!p) return -FDT_ERR_BADPATH; offset = fdt_path_offset(fdt, p); p = q; } while (p < end) { const char *q; while (*p == '/') { p++; if (p == end) return offset; } q = memchr(p, '/', end - p); if (! q) q = end; offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); if (offset < 0) return offset; p = q; } return offset; } int fdt_path_offset(const void *fdt, const char *path) { return fdt_path_offset_namelen(fdt, path, strlen(path)); } const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) { const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); const char *nameptr; int err; if (((err = fdt_ro_probe_(fdt)) < 0) || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; nameptr = nh->name; if (fdt_version(fdt) < 0x10) { /* * For old FDT versions, match the naming conventions of V16: * give only the leaf name (after all /). The actual tree * contents are loosely checked. */ const char *leaf; leaf = strrchr(nameptr, '/'); if (leaf == NULL) { err = -FDT_ERR_BADSTRUCTURE; goto fail; } nameptr = leaf+1; } if (len) *len = strlen(nameptr); return nameptr; fail: if (len) *len = err; return NULL; } int fdt_first_property_offset(const void *fdt, int nodeoffset) { int offset; if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return offset; return nextprop_(fdt, offset); } int fdt_next_property_offset(const void *fdt, int offset) { if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) return offset; return nextprop_(fdt, offset); } static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, int offset, int *lenp) { int err; const struct fdt_property *prop; if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; } prop = fdt_offset_ptr_(fdt, offset); if (lenp) *lenp = fdt32_ld(&prop->len); return prop; } const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp) { /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ if (fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; } return fdt_get_property_by_offset_(fdt, offset, lenp); } static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, int offset, const char *name, int namelen, int *lenp, int *poffset) { for (offset = fdt_first_property_offset(fdt, offset); (offset >= 0); (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { offset = -FDT_ERR_INTERNAL; break; } if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), name, namelen)) { if (poffset) *poffset = offset; return prop; } } if (lenp) *lenp = offset; return NULL; } const struct fdt_property *fdt_get_property_namelen(const void *fdt, int offset, const char *name, int namelen, int *lenp) { /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ if (fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; } return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, NULL); } const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp) { return fdt_get_property_namelen(fdt, nodeoffset, name, strlen(name), lenp); } const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) { int poffset; const struct fdt_property *prop; prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, &poffset); if (!prop) return NULL; /* Handle realignment */ if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } const void *fdt_getprop_by_offset(const void *fdt, int offset, const char **namep, int *lenp) { const struct fdt_property *prop; prop = fdt_get_property_by_offset_(fdt, offset, lenp); if (!prop) return NULL; if (namep) { const char *name; int namelen; name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), &namelen); if (!name) { if (lenp) *lenp = namelen; return NULL; } *namep = name; } /* Handle realignment */ if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp) { return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); } uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) { const fdt32_t *php; int len; /* FIXME: This is a bit sub-optimal, since we potentially scan * over all the properties twice. */ php = fdt_getprop(fdt, nodeoffset, "phandle", &len); if (!php || (len != sizeof(*php))) { php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); if (!php || (len != sizeof(*php))) return 0; } return fdt32_ld(php); } const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen) { int aliasoffset; aliasoffset = fdt_path_offset(fdt, "/aliases"); if (aliasoffset < 0) return NULL; return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); } const char *fdt_get_alias(const void *fdt, const char *name) { return fdt_get_alias_namelen(fdt, name, strlen(name)); } int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) { int pdepth = 0, p = 0; int offset, depth, namelen; const char *name; FDT_RO_PROBE(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { while (pdepth > depth) { do { p--; } while (buf[p-1] != '/'); pdepth--; } if (pdepth >= depth) { name = fdt_get_name(fdt, offset, &namelen); if (!name) return namelen; if ((p + namelen + 1) <= buflen) { memcpy(buf + p, name, namelen); p += namelen; buf[p++] = '/'; pdepth++; } } if (offset == nodeoffset) { if (pdepth < (depth + 1)) return -FDT_ERR_NOSPACE; if (p > 1) /* special case so that root path is "/", not "" */ p--; buf[p] = '\0'; return 0; } } if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) return -FDT_ERR_BADOFFSET; else if (offset == -FDT_ERR_BADOFFSET) return -FDT_ERR_BADSTRUCTURE; return offset; /* error from fdt_next_node() */ } int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth) { int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; FDT_RO_PROBE(fdt); if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; for (offset = 0, depth = 0; (offset >= 0) && (offset <= nodeoffset); offset = fdt_next_node(fdt, offset, &depth)) { if (depth == supernodedepth) supernodeoffset = offset; if (offset == nodeoffset) { if (nodedepth) *nodedepth = depth; if (supernodedepth > depth) return -FDT_ERR_NOTFOUND; else return supernodeoffset; } } if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) return -FDT_ERR_BADOFFSET; else if (offset == -FDT_ERR_BADOFFSET) return -FDT_ERR_BADSTRUCTURE; return offset; /* error from fdt_next_node() */ } int fdt_node_depth(const void *fdt, int nodeoffset) { int nodedepth; int err; err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) return (err < 0) ? err : -FDT_ERR_INTERNAL; return nodedepth; } int fdt_parent_offset(const void *fdt, int nodeoffset) { int nodedepth = fdt_node_depth(fdt, nodeoffset); if (nodedepth < 0) return nodedepth; return fdt_supernode_atdepth_offset(fdt, nodeoffset, nodedepth - 1, NULL); } int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen) { int offset; const void *val; int len; FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't * find what we want, we scan over them again making our way * to the next node. Still it's the easiest to implement * approach; performance can come later. */ for (offset = fdt_next_node(fdt, startoffset, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { val = fdt_getprop(fdt, offset, propname, &len); if (val && (len == proplen) && (memcmp(val, propval, len) == 0)) return offset; } return offset; /* error from fdt_next_node() */ } int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { int offset; if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in * fdt_get_phandle(), then if that didn't find what * we want, we scan over them again making our way to the next * node. Still it's the easiest to implement approach; * performance can come later. */ for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { if (fdt_get_phandle(fdt, offset) == phandle) return offset; } return offset; /* error from fdt_next_node() */ } int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) { int len = strlen(str); const char *p; while (listlen >= len) { if (memcmp(str, strlist, len+1) == 0) return 1; p = memchr(strlist, '\0', listlen); if (!p) return 0; /* malformed strlist.. */ listlen -= (p-strlist) + 1; strlist = p + 1; } return 0; } int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) { const char *list, *end; int length, count = 0; list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) return length; end = list + length; while (list < end) { length = strnlen(list, end - list) + 1; /* Abort if the last string isn't properly NUL-terminated. */ if (list + length > end) return -FDT_ERR_BADVALUE; list += length; count++; } return count; } int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, const char *string) { int length, len, idx = 0; const char *list, *end; list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) return length; len = strlen(string) + 1; end = list + length; while (list < end) { length = strnlen(list, end - list) + 1; /* Abort if the last string isn't properly NUL-terminated. */ if (list + length > end) return -FDT_ERR_BADVALUE; if (length == len && memcmp(list, string, length) == 0) return idx; list += length; idx++; } return -FDT_ERR_NOTFOUND; } const char *fdt_stringlist_get(const void *fdt, int nodeoffset, const char *property, int idx, int *lenp) { const char *list, *end; int length; list = fdt_getprop(fdt, nodeoffset, property, &length); if (!list) { if (lenp) *lenp = length; return NULL; } end = list + length; while (list < end) { length = strnlen(list, end - list) + 1; /* Abort if the last string isn't properly NUL-terminated. */ if (list + length > end) { if (lenp) *lenp = -FDT_ERR_BADVALUE; return NULL; } if (idx == 0) { if (lenp) *lenp = length - 1; return list; } list += length; idx--; } if (lenp) *lenp = -FDT_ERR_NOTFOUND; return NULL; } int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible) { const void *prop; int len; prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); if (!prop) return len; return !fdt_stringlist_contains(prop, len, compatible); } int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible) { int offset, err; FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if * that didn't find what we want, we scan over them again * making our way to the next node. Still it's the easiest to * implement approach; performance can come later. */ for (offset = fdt_next_node(fdt, startoffset, NULL); offset >= 0; offset = fdt_next_node(fdt, offset, NULL)) { err = fdt_node_check_compatible(fdt, offset, compatible); if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) return err; else if (err == 0) return offset; } return offset; /* error from fdt_next_node() */ } int fdt_check_full(const void *fdt, size_t bufsize) { int err; int num_memrsv; int offset, nextoffset = 0; uint32_t tag; unsigned depth = 0; const void *prop; const char *propname; if (bufsize < FDT_V1_SIZE) return -FDT_ERR_TRUNCATED; err = fdt_check_header(fdt); if (err != 0) return err; if (bufsize < fdt_totalsize(fdt)) return -FDT_ERR_TRUNCATED; num_memrsv = fdt_num_mem_rsv(fdt); if (num_memrsv < 0) return num_memrsv; while (1) { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); if (nextoffset < 0) return nextoffset; switch (tag) { case FDT_NOP: break; case FDT_END: if (depth != 0) return -FDT_ERR_BADSTRUCTURE; return 0; case FDT_BEGIN_NODE: depth++; if (depth > INT_MAX) return -FDT_ERR_BADSTRUCTURE; break; case FDT_END_NODE: if (depth == 0) return -FDT_ERR_BADSTRUCTURE; depth--; break; case FDT_PROP: prop = fdt_getprop_by_offset(fdt, offset, &propname, &err); if (!prop) return err; break; default: return -FDT_ERR_INTERNAL; } } } optee_os-4.3.0/core/lib/libfdt/fdt_rw.c000066400000000000000000000260431464416617300177470ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" static int fdt_blocks_misordered_(const void *fdt, int mem_rsv_size, int struct_size) { return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) || (fdt_off_dt_struct(fdt) < (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) || (fdt_off_dt_strings(fdt) < (fdt_off_dt_struct(fdt) + struct_size)) || (fdt_totalsize(fdt) < (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); } static int fdt_rw_probe_(void *fdt) { FDT_RO_PROBE(fdt); if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; if (fdt_version(fdt) > 17) fdt_set_version(fdt, 17); return 0; } #define FDT_RW_PROBE(fdt) \ { \ int err_; \ if ((err_ = fdt_rw_probe_(fdt)) != 0) \ return err_; \ } static inline int fdt_data_size_(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; char *end = (char *)fdt + fdt_data_size_(fdt); if (((p + oldlen) < p) || ((p + oldlen) > end)) return -FDT_ERR_BADOFFSET; if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) return -FDT_ERR_BADOFFSET; if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) return -FDT_ERR_NOSPACE; memmove(p + newlen, p + oldlen, end - p - oldlen); return 0; } static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, int oldn, int newn) { int delta = (newn - oldn) * sizeof(*p); int err; err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); if (err) return err; fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); return 0; } static int fdt_splice_struct_(void *fdt, void *p, int oldlen, int newlen) { int delta = newlen - oldlen; int err; if ((err = fdt_splice_(fdt, p, oldlen, newlen))) return err; fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); return 0; } /* Must only be used to roll back in case of error */ static void fdt_del_last_string_(void *fdt, const char *s) { int newlen = strlen(s) + 1; fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); } static int fdt_splice_string_(void *fdt, int newlen) { void *p = (char *)fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); int err; if ((err = fdt_splice_(fdt, p, 0, newlen))) return err; fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); return 0; } static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; char *new; int len = strlen(s) + 1; int err; *allocated = 0; p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) /* found it */ return (p - strtab); new = strtab + fdt_size_dt_strings(fdt); err = fdt_splice_string_(fdt, len); if (err) return err; *allocated = 1; memcpy(new, s, len); return (new - strtab); } int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) { struct fdt_reserve_entry *re; int err; FDT_RW_PROBE(fdt); re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); err = fdt_splice_mem_rsv_(fdt, re, 0, 1); if (err) return err; re->address = cpu_to_fdt64(address); re->size = cpu_to_fdt64(size); return 0; } int fdt_del_mem_rsv(void *fdt, int n) { struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); FDT_RW_PROBE(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; return fdt_splice_mem_rsv_(fdt, re, 1, 0); } static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int oldlen; int err; *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (!*prop) return oldlen; if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(len)))) return err; (*prop)->len = cpu_to_fdt32(len); return 0; } static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int len, struct fdt_property **prop) { int proplen; int nextoffset; int namestroff; int err; int allocated; if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; namestroff = fdt_find_add_string_(fdt, name, &allocated); if (namestroff < 0) return namestroff; *prop = fdt_offset_ptr_w_(fdt, nextoffset); proplen = sizeof(**prop) + FDT_TAGALIGN(len); err = fdt_splice_struct_(fdt, *prop, 0, proplen); if (err) { if (allocated) fdt_del_last_string_(fdt, name); return err; } (*prop)->tag = cpu_to_fdt32(FDT_PROP); (*prop)->nameoff = cpu_to_fdt32(namestroff); (*prop)->len = cpu_to_fdt32(len); return 0; } int fdt_set_name(void *fdt, int nodeoffset, const char *name) { char *namep; int oldlen, newlen; int err; FDT_RW_PROBE(fdt); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) return oldlen; newlen = strlen(name); err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), FDT_TAGALIGN(newlen+1)); if (err) return err; memcpy(namep, name, newlen+1); return 0; } int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, int len, void **prop_data) { struct fdt_property *prop; int err; FDT_RW_PROBE(fdt); err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); if (err) return err; *prop_data = prop->data; return 0; } int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { void *prop_data; int err; err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); if (err) return err; if (len) memcpy(prop_data, val, len); return 0; } int fdt_appendprop(void *fdt, int nodeoffset, const char *name, const void *val, int len) { struct fdt_property *prop; int err, oldlen, newlen; FDT_RW_PROBE(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (prop) { newlen = len + oldlen; err = fdt_splice_struct_(fdt, prop->data, FDT_TAGALIGN(oldlen), FDT_TAGALIGN(newlen)); if (err) return err; prop->len = cpu_to_fdt32(newlen); memcpy(prop->data + oldlen, val, len); } else { err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); if (err) return err; memcpy(prop->data, val, len); } return 0; } int fdt_delprop(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len, proplen; FDT_RW_PROBE(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (!prop) return len; proplen = sizeof(*prop) + FDT_TAGALIGN(len); return fdt_splice_struct_(fdt, prop, proplen, 0); } int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen) { struct fdt_node_header *nh; int offset, nextoffset; int nodelen; int err; uint32_t tag; fdt32_t *endtag; FDT_RW_PROBE(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) return -FDT_ERR_EXISTS; else if (offset != -FDT_ERR_NOTFOUND) return offset; /* Try to place the new node after the parent's properties */ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ do { offset = nextoffset; tag = fdt_next_tag(fdt, offset, &nextoffset); } while ((tag == FDT_PROP) || (tag == FDT_NOP)); nh = fdt_offset_ptr_w_(fdt, offset); nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; err = fdt_splice_struct_(fdt, nh, 0, nodelen); if (err) return err; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); memcpy(nh->name, name, namelen); endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); *endtag = cpu_to_fdt32(FDT_END_NODE); return offset; } int fdt_add_subnode(void *fdt, int parentoffset, const char *name) { return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); } int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; FDT_RW_PROBE(fdt); endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) return endoffset; return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), endoffset - nodeoffset, 0); } static void fdt_packblocks_(const char *old, char *new, int mem_rsv_size, int struct_size) { int mem_rsv_off, struct_off, strings_off; mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); struct_off = mem_rsv_off + mem_rsv_size; strings_off = struct_off + struct_size; memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); fdt_set_off_mem_rsvmap(new, mem_rsv_off); memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); fdt_set_off_dt_struct(new, struct_off); fdt_set_size_dt_struct(new, struct_size); memmove(new + strings_off, old + fdt_off_dt_strings(old), fdt_size_dt_strings(old)); fdt_set_off_dt_strings(new, strings_off); fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); } int fdt_open_into(const void *fdt, void *buf, int bufsize) { int err; int mem_rsv_size, struct_size; int newsize; const char *fdtstart = fdt; const char *fdtend = fdtstart + fdt_totalsize(fdt); char *tmp; FDT_RO_PROBE(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); if (fdt_version(fdt) >= 17) { struct_size = fdt_size_dt_struct(fdt); } else { struct_size = 0; while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) ; if (struct_size < 0) return struct_size; } if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) return err; fdt_set_version(buf, 17); fdt_set_size_dt_struct(buf, struct_size); fdt_set_totalsize(buf, bufsize); return 0; } /* Need to reorder */ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + struct_size + fdt_size_dt_strings(fdt); if (bufsize < newsize) return -FDT_ERR_NOSPACE; /* First attempt to build converted tree at beginning of buffer */ tmp = buf; /* But if that overlaps with the old tree... */ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { /* Try right after the old tree instead */ tmp = (char *)(uintptr_t)fdtend; if ((tmp + newsize) > ((char *)buf + bufsize)) return -FDT_ERR_NOSPACE; } fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); memmove(buf, tmp, newsize); fdt_set_magic(buf, FDT_MAGIC); fdt_set_totalsize(buf, bufsize); fdt_set_version(buf, 17); fdt_set_last_comp_version(buf, 16); fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); return 0; } int fdt_pack(void *fdt) { int mem_rsv_size; FDT_RW_PROBE(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); fdt_set_totalsize(fdt, fdt_data_size_(fdt)); return 0; } optee_os-4.3.0/core/lib/libfdt/fdt_strerror.c000066400000000000000000000026431464416617300212010ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" struct fdt_errtabent { const char *str; }; #define FDT_ERRTABENT(val) \ [(val)] = { .str = #val, } static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_NOTFOUND), FDT_ERRTABENT(FDT_ERR_EXISTS), FDT_ERRTABENT(FDT_ERR_NOSPACE), FDT_ERRTABENT(FDT_ERR_BADOFFSET), FDT_ERRTABENT(FDT_ERR_BADPATH), FDT_ERRTABENT(FDT_ERR_BADPHANDLE), FDT_ERRTABENT(FDT_ERR_BADSTATE), FDT_ERRTABENT(FDT_ERR_TRUNCATED), FDT_ERRTABENT(FDT_ERR_BADMAGIC), FDT_ERRTABENT(FDT_ERR_BADVERSION), FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), FDT_ERRTABENT(FDT_ERR_BADLAYOUT), FDT_ERRTABENT(FDT_ERR_INTERNAL), FDT_ERRTABENT(FDT_ERR_BADNCELLS), FDT_ERRTABENT(FDT_ERR_BADVALUE), FDT_ERRTABENT(FDT_ERR_BADOVERLAY), FDT_ERRTABENT(FDT_ERR_NOPHANDLES), FDT_ERRTABENT(FDT_ERR_BADFLAGS), }; #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) const char *fdt_strerror(int errval) { if (errval > 0) return ""; else if (errval == 0) return ""; else if (errval > -FDT_ERRTABSIZE) { const char *s = fdt_errtable[-errval].str; if (s) return s; } return ""; } optee_os-4.3.0/core/lib/libfdt/fdt_sw.c000066400000000000000000000203651464416617300177510ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" static int fdt_sw_probe_(void *fdt) { if (fdt_magic(fdt) == FDT_MAGIC) return -FDT_ERR_BADSTATE; else if (fdt_magic(fdt) != FDT_SW_MAGIC) return -FDT_ERR_BADMAGIC; return 0; } #define FDT_SW_PROBE(fdt) \ { \ int err; \ if ((err = fdt_sw_probe_(fdt)) != 0) \ return err; \ } /* 'memrsv' state: Initial state after fdt_create() * * Allowed functions: * fdt_add_reservmap_entry() * fdt_finish_reservemap() [moves to 'struct' state] */ static int fdt_sw_probe_memrsv_(void *fdt) { int err = fdt_sw_probe_(fdt); if (err) return err; if (fdt_off_dt_strings(fdt) != 0) return -FDT_ERR_BADSTATE; return 0; } #define FDT_SW_PROBE_MEMRSV(fdt) \ { \ int err; \ if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ return err; \ } /* 'struct' state: Enter this state after fdt_finish_reservemap() * * Allowed functions: * fdt_begin_node() * fdt_end_node() * fdt_property*() * fdt_finish() [moves to 'complete' state] */ static int fdt_sw_probe_struct_(void *fdt) { int err = fdt_sw_probe_(fdt); if (err) return err; if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) return -FDT_ERR_BADSTATE; return 0; } #define FDT_SW_PROBE_STRUCT(fdt) \ { \ int err; \ if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ return err; \ } static inline uint32_t sw_flags(void *fdt) { /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ return fdt_last_comp_version(fdt); } /* 'complete' state: Enter this state after fdt_finish() * * Allowed functions: none */ static void *fdt_grab_space_(void *fdt, size_t len) { int offset = fdt_size_dt_struct(fdt); int spaceleft; spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - fdt_size_dt_strings(fdt); if ((offset + len < offset) || (offset + len > spaceleft)) return NULL; fdt_set_size_dt_struct(fdt, offset + len); return fdt_offset_ptr_w_(fdt, offset); } int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) { const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), sizeof(struct fdt_reserve_entry)); void *fdt = buf; if (bufsize < hdrsize) return -FDT_ERR_NOSPACE; if (flags & ~FDT_CREATE_FLAGS_ALL) return -FDT_ERR_BADFLAGS; memset(buf, 0, bufsize); /* * magic and last_comp_version keep intermediate state during the fdt * creation process, which is replaced with the proper FDT format by * fdt_finish(). * * flags should be accessed with sw_flags(). */ fdt_set_magic(fdt, FDT_SW_MAGIC); fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); fdt_set_last_comp_version(fdt, flags); fdt_set_totalsize(fdt, bufsize); fdt_set_off_mem_rsvmap(fdt, hdrsize); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); fdt_set_off_dt_strings(fdt, 0); return 0; } int fdt_create(void *buf, int bufsize) { return fdt_create_with_flags(buf, bufsize, 0); } int fdt_resize(void *fdt, void *buf, int bufsize) { size_t headsize, tailsize; char *oldtail, *newtail; FDT_SW_PROBE(fdt); headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); if ((headsize + tailsize) > fdt_totalsize(fdt)) return -FDT_ERR_INTERNAL; if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; newtail = (char *)buf + bufsize - tailsize; /* Two cases to avoid clobbering data if the old and new * buffers partially overlap */ if (buf <= fdt) { memmove(buf, fdt, headsize); memmove(newtail, oldtail, tailsize); } else { memmove(newtail, oldtail, tailsize); memmove(buf, fdt, headsize); } fdt_set_totalsize(buf, bufsize); if (fdt_off_dt_strings(buf)) fdt_set_off_dt_strings(buf, bufsize); return 0; } int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) { struct fdt_reserve_entry *re; int offset; FDT_SW_PROBE_MEMRSV(fdt); offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; re = (struct fdt_reserve_entry *)((char *)fdt + offset); re->address = cpu_to_fdt64(addr); re->size = cpu_to_fdt64(size); fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); return 0; } int fdt_finish_reservemap(void *fdt) { int err = fdt_add_reservemap_entry(fdt, 0, 0); if (err) return err; fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); return 0; } int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; int namelen; FDT_SW_PROBE_STRUCT(fdt); namelen = strlen(name) + 1; nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); memcpy(nh->name, name, namelen); return 0; } int fdt_end_node(void *fdt) { fdt32_t *en; FDT_SW_PROBE_STRUCT(fdt); en = fdt_grab_space_(fdt, FDT_TAGSIZE); if (! en) return -FDT_ERR_NOSPACE; *en = cpu_to_fdt32(FDT_END_NODE); return 0; } static int fdt_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); int strtabsize = fdt_size_dt_strings(fdt); int len = strlen(s) + 1; int struct_top, offset; offset = -strtabsize - len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); if (fdt_totalsize(fdt) + offset < struct_top) return 0; /* no more room :( */ memcpy(strtab + offset, s, len); fdt_set_size_dt_strings(fdt, strtabsize + len); return offset; } /* Must only be used to roll back in case of error */ static void fdt_del_last_string_(void *fdt, const char *s) { int strtabsize = fdt_size_dt_strings(fdt); int len = strlen(s) + 1; fdt_set_size_dt_strings(fdt, strtabsize - len); } static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_totalsize(fdt); int strtabsize = fdt_size_dt_strings(fdt); const char *p; *allocated = 0; p = fdt_find_string_(strtab - strtabsize, strtabsize, s); if (p) return p - strtab; *allocated = 1; return fdt_add_string_(fdt, s); } int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) { struct fdt_property *prop; int nameoff; int allocated; FDT_SW_PROBE_STRUCT(fdt); /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { allocated = 1; nameoff = fdt_add_string_(fdt, name); } else { nameoff = fdt_find_add_string_(fdt, name, &allocated); } if (nameoff == 0) return -FDT_ERR_NOSPACE; prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); if (! prop) { if (allocated) fdt_del_last_string_(fdt, name); return -FDT_ERR_NOSPACE; } prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); prop->len = cpu_to_fdt32(len); *valp = prop->data; return 0; } int fdt_property(void *fdt, const char *name, const void *val, int len) { void *ptr; int ret; ret = fdt_property_placeholder(fdt, name, len, &ptr); if (ret) return ret; memcpy(ptr, val, len); return 0; } int fdt_finish(void *fdt) { char *p = (char *)fdt; fdt32_t *end; int oldstroffset, newstroffset; uint32_t tag; int offset, nextoffset; FDT_SW_PROBE_STRUCT(fdt); /* Add terminator */ end = fdt_grab_space_(fdt, sizeof(*end)); if (! end) return -FDT_ERR_NOSPACE; *end = cpu_to_fdt32(FDT_END); /* Relocate the string table */ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); fdt_set_off_dt_strings(fdt, newstroffset); /* Walk the structure, correcting string offsets */ offset = 0; while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { if (tag == FDT_PROP) { struct fdt_property *prop = fdt_offset_ptr_w_(fdt, offset); int nameoff; nameoff = fdt32_to_cpu(prop->nameoff); nameoff += fdt_size_dt_strings(fdt); prop->nameoff = cpu_to_fdt32(nameoff); } offset = nextoffset; } if (nextoffset < 0) return nextoffset; /* Finally, adjust the header */ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); /* And fix up fields that were keeping intermediate state. */ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_magic(fdt, FDT_MAGIC); return 0; } optee_os-4.3.0/core/lib/libfdt/fdt_wip.c000066400000000000000000000035501464416617300201140ustar00rootroot00000000000000// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include "libfdt_env.h" #include #include #include "libfdt_internal.h" int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, const char *name, int namelen, uint32_t idx, const void *val, int len) { void *propval; int proplen; propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, &proplen); if (!propval) return proplen; if (proplen < (len + idx)) return -FDT_ERR_NOSPACE; memcpy((char *)propval + idx, val, len); return 0; } int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len) { const void *propval; int proplen; propval = fdt_getprop(fdt, nodeoffset, name, &proplen); if (!propval) return proplen; if (proplen != len) return -FDT_ERR_NOSPACE; return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, strlen(name), 0, val, len); } static void fdt_nop_region_(void *start, int len) { fdt32_t *p; for (p = start; (char *)p < ((char *)start + len); p++) *p = cpu_to_fdt32(FDT_NOP); } int fdt_nop_property(void *fdt, int nodeoffset, const char *name) { struct fdt_property *prop; int len; prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (!prop) return len; fdt_nop_region_(prop, len + sizeof(*prop)); return 0; } int fdt_node_end_offset_(void *fdt, int offset) { int depth = 0; while ((offset >= 0) && (depth >= 0)) offset = fdt_next_node(fdt, offset, &depth); return offset; } int fdt_nop_node(void *fdt, int nodeoffset) { int endoffset; endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) return endoffset; fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset); return 0; } optee_os-4.3.0/core/lib/libfdt/include/000077500000000000000000000000001464416617300177345ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libfdt/include/fdt.h000066400000000000000000000033371464416617300206700ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef FDT_H #define FDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. */ #ifndef __ASSEMBLY__ struct fdt_header { fdt32_t magic; /* magic word FDT_MAGIC */ fdt32_t totalsize; /* total size of DT block */ fdt32_t off_dt_struct; /* offset to structure */ fdt32_t off_dt_strings; /* offset to strings */ fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ fdt32_t version; /* format version */ fdt32_t last_comp_version; /* last compatible version */ /* version 2 fields below */ fdt32_t boot_cpuid_phys; /* Which physical CPU id we're booting on */ /* version 3 fields below */ fdt32_t size_dt_strings; /* size of the strings block */ /* version 17 fields below */ fdt32_t size_dt_struct; /* size of the structure block */ }; struct fdt_reserve_entry { fdt64_t address; fdt64_t size; }; struct fdt_node_header { fdt32_t tag; char name[]; }; struct fdt_property { fdt32_t tag; fdt32_t len; fdt32_t nameoff; char data[]; }; #endif /* !__ASSEMBLY */ #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ #define FDT_TAGSIZE sizeof(fdt32_t) #define FDT_BEGIN_NODE 0x1 /* Start node: full name */ #define FDT_END_NODE 0x2 /* End node */ #define FDT_PROP 0x3 /* Property: name off, size, content */ #define FDT_NOP 0x4 /* nop */ #define FDT_END 0x9 #define FDT_V1_SIZE (7*sizeof(fdt32_t)) #define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) #define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) #define FDT_V16_SIZE FDT_V3_SIZE #define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) #endif /* FDT_H */ optee_os-4.3.0/core/lib/libfdt/include/libfdt.h000066400000000000000000002177631464416617300213710ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_H #define LIBFDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include #include #define FDT_FIRST_SUPPORTED_VERSION 0x02 #define FDT_LAST_SUPPORTED_VERSION 0x11 /* Error codes: informative error codes */ #define FDT_ERR_NOTFOUND 1 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ #define FDT_ERR_EXISTS 2 /* FDT_ERR_EXISTS: Attempted to create a node or property which * already exists */ #define FDT_ERR_NOSPACE 3 /* FDT_ERR_NOSPACE: Operation needed to expand the device * tree, but its buffer did not have sufficient space to * contain the expanded tree. Use fdt_open_into() to move the * device tree to a buffer with more space. */ /* Error codes: codes for bad parameters */ #define FDT_ERR_BADOFFSET 4 /* FDT_ERR_BADOFFSET: Function was passed a structure block * offset which is out-of-bounds, or which points to an * unsuitable part of the structure for the operation. */ #define FDT_ERR_BADPATH 5 /* FDT_ERR_BADPATH: Function was passed a badly formatted path * (e.g. missing a leading / for a function which requires an * absolute path) */ #define FDT_ERR_BADPHANDLE 6 /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. * This can be caused either by an invalid phandle property * length, or the phandle value was either 0 or -1, which are * not permitted. */ #define FDT_ERR_BADSTATE 7 /* FDT_ERR_BADSTATE: Function was passed an incomplete device * tree created by the sequential-write functions, which is * not sufficiently complete for the requested operation. */ /* Error codes: codes for bad device tree blobs */ #define FDT_ERR_TRUNCATED 8 /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly * terminated (overflows, goes outside allowed bounds, or * isn't properly terminated). */ #define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device * tree magic number. */ #define FDT_ERR_BADVERSION 10 /* FDT_ERR_BADVERSION: Given device tree has a version which * can't be handled by the requested operation. For * read-write functions, this may mean that fdt_open_into() is * required to convert the tree to the expected version. */ #define FDT_ERR_BADSTRUCTURE 11 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt * structure block or other serious error (e.g. misnested * nodes, or subnodes preceding properties). */ #define FDT_ERR_BADLAYOUT 12 /* FDT_ERR_BADLAYOUT: For read-write functions, the given * device tree has it's sub-blocks in an order that the * function can't handle (memory reserve map, then structure, * then strings). Use fdt_open_into() to reorganize the tree * into a form suitable for the read-write operations. */ /* "Can't happen" error indicating a bug in libfdt */ #define FDT_ERR_INTERNAL 13 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. * Should never be returned, if it is, it indicates a bug in * libfdt itself. */ /* Errors in device tree content */ #define FDT_ERR_BADNCELLS 14 /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells * or similar property with a bad format or value */ #define FDT_ERR_BADVALUE 15 /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected * value. For example: a property expected to contain a string list * is not NUL-terminated within the length of its value. */ #define FDT_ERR_BADOVERLAY 16 /* FDT_ERR_BADOVERLAY: The device tree overlay, while * correctly structured, cannot be applied due to some * unexpected or missing value, property or node. */ #define FDT_ERR_NOPHANDLES 17 /* FDT_ERR_NOPHANDLES: The device tree doesn't have any * phandle available anymore without causing an overflow */ #define FDT_ERR_BADFLAGS 18 /* FDT_ERR_BADFLAGS: The function was passed a flags field that * contains invalid flags or an invalid combination of flags. */ #define FDT_ERR_MAX 18 /* constants */ #define FDT_MAX_PHANDLE 0xfffffffe /* Valid values for phandles range from 1 to 2^32-2. */ /**********************************************************************/ /* Low-level functions (you probably don't need these) */ /**********************************************************************/ #ifndef SWIG /* This function is not useful in Python */ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); #endif static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) { return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); } uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); /* * Alignment helpers: * These helpers access words from a device tree blob. They're * built to work even with unaligned pointers on platforms (ike * ARM) that don't like unaligned loads and stores */ static inline uint32_t fdt32_ld(const fdt32_t *p) { const uint8_t *bp = (const uint8_t *)p; return ((uint32_t)bp[0] << 24) | ((uint32_t)bp[1] << 16) | ((uint32_t)bp[2] << 8) | bp[3]; } static inline void fdt32_st(void *property, uint32_t value) { uint8_t *bp = property; bp[0] = value >> 24; bp[1] = (value >> 16) & 0xff; bp[2] = (value >> 8) & 0xff; bp[3] = value & 0xff; } static inline uint64_t fdt64_ld(const fdt64_t *p) { const uint8_t *bp = (const uint8_t *)p; return ((uint64_t)bp[0] << 56) | ((uint64_t)bp[1] << 48) | ((uint64_t)bp[2] << 40) | ((uint64_t)bp[3] << 32) | ((uint64_t)bp[4] << 24) | ((uint64_t)bp[5] << 16) | ((uint64_t)bp[6] << 8) | bp[7]; } static inline void fdt64_st(void *property, uint64_t value) { uint8_t *bp = property; bp[0] = value >> 56; bp[1] = (value >> 48) & 0xff; bp[2] = (value >> 40) & 0xff; bp[3] = (value >> 32) & 0xff; bp[4] = (value >> 24) & 0xff; bp[5] = (value >> 16) & 0xff; bp[6] = (value >> 8) & 0xff; bp[7] = value & 0xff; } /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ int fdt_next_node(const void *fdt, int offset, int *depth); /** * fdt_first_subnode() - get offset of first direct subnode * * @fdt: FDT blob * @offset: Offset of node to check * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none */ int fdt_first_subnode(const void *fdt, int offset); /** * fdt_next_subnode() - get offset of next direct subnode * * After first calling fdt_first_subnode(), call this function repeatedly to * get direct subnodes of a parent node. * * @fdt: FDT blob * @offset: Offset of previous subnode * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more * subnodes */ int fdt_next_subnode(const void *fdt, int offset); /** * fdt_for_each_subnode - iterate over all subnodes of a parent * * @node: child node (int, lvalue) * @fdt: FDT blob (const void *) * @parent: parent node (int) * * This is actually a wrapper around a for loop and would be used like so: * * fdt_for_each_subnode(node, fdt, parent) { * Use node * ... * } * * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { * Error handling * } * * Note that this is implemented as a macro and @node is used as * iterator in the loop. The parent variable be constant or even a * literal. * */ #define fdt_for_each_subnode(node, fdt, parent) \ for (node = fdt_first_subnode(fdt, parent); \ node >= 0; \ node = fdt_next_subnode(fdt, node)) /**********************************************************************/ /* General functions */ /**********************************************************************/ #define fdt_get_header(fdt, field) \ (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) #define fdt_version(fdt) (fdt_get_header(fdt, version)) #define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) #define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) #define fdt_set_hdr_(name) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \ { \ struct fdt_header *fdth = (struct fdt_header *)fdt; \ fdth->name = cpu_to_fdt32(val); \ } fdt_set_hdr_(magic); fdt_set_hdr_(totalsize); fdt_set_hdr_(off_dt_struct); fdt_set_hdr_(off_dt_strings); fdt_set_hdr_(off_mem_rsvmap); fdt_set_hdr_(version); fdt_set_hdr_(last_comp_version); fdt_set_hdr_(boot_cpuid_phys); fdt_set_hdr_(size_dt_strings); fdt_set_hdr_(size_dt_struct); #undef fdt_set_hdr_ /** * fdt_header_size - return the size of the tree's header * @fdt: pointer to a flattened device tree */ size_t fdt_header_size_(uint32_t version); static inline size_t fdt_header_size(const void *fdt) { return fdt_header_size_(fdt_version(fdt)); } /** * fdt_check_header - sanity check a device tree header * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what * appears to be a flattened device tree, and that the header contains * valid information (to the extent that can be determined from the * header alone). * * returns: * 0, if the buffer appears to contain a valid device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_TRUNCATED, standard meanings, as above */ int fdt_check_header(const void *fdt); /** * fdt_move - move a device tree around in memory * @fdt: pointer to the device tree to move * @buf: pointer to memory where the device is to be moved * @bufsize: size of the memory space at buf * * fdt_move() relocates, if possible, the device tree blob located at * fdt to the buffer at buf of size bufsize. The buffer may overlap * with the existing device tree blob at fdt. Therefore, * fdt_move(fdt, fdt, fdt_totalsize(fdt)) * should always succeed. * * returns: * 0, on success * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ int fdt_move(const void *fdt, void *buf, int bufsize); /**********************************************************************/ /* Read-only functions */ /**********************************************************************/ int fdt_check_full(const void *fdt, size_t bufsize); /** * fdt_get_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob * @stroffset: offset of the string within the strings block (native endian) * @lenp: optional pointer to return the string's length * * fdt_get_string() retrieves a pointer to a single string from the * strings block of the device tree blob at fdt, and optionally also * returns the string's length in *lenp. * * returns: * a pointer to the string, on success * NULL, if stroffset is out of bounds, or doesn't point to a valid string */ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); /** * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob * @stroffset: offset of the string within the strings block (native endian) * * fdt_string() retrieves a pointer to a single string from the * strings block of the device tree blob at fdt. * * returns: * a pointer to the string, on success * NULL, if stroffset is out of bounds, or doesn't point to a valid string */ const char *fdt_string(const void *fdt, int stroffset); /** * fdt_find_max_phandle - find and return the highest phandle in a tree * @fdt: pointer to the device tree blob * @phandle: return location for the highest phandle value found in the tree * * fdt_find_max_phandle() finds the highest phandle value in the given device * tree. The value returned in @phandle is only valid if the function returns * success. * * returns: * 0 on success or a negative error code on failure */ int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); /** * fdt_get_max_phandle - retrieves the highest phandle in a tree * @fdt: pointer to the device tree blob * * fdt_get_max_phandle retrieves the highest phandle in the given * device tree. This will ignore badly formatted phandles, or phandles * with a value of 0 or -1. * * This function is deprecated in favour of fdt_find_max_phandle(). * * returns: * the highest phandle on success * 0, if no phandle was found in the device tree * -1, if an error occurred */ static inline uint32_t fdt_get_max_phandle(const void *fdt) { uint32_t phandle; int err; err = fdt_find_max_phandle(fdt, &phandle); if (err < 0) return (uint32_t)-1; return phandle; } /** * fdt_generate_phandle - return a new, unused phandle for a device tree blob * @fdt: pointer to the device tree blob * @phandle: return location for the new phandle * * Walks the device tree blob and looks for the highest phandle value. On * success, the new, unused phandle value (one higher than the previously * highest phandle value in the device tree blob) will be returned in the * @phandle parameter. * * Returns: * 0 on success or a negative error-code on failure */ int fdt_generate_phandle(const void *fdt, uint32_t *phandle); /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries * @fdt: pointer to the device tree blob * * Returns the number of entries in the device tree blob's memory * reservation map. This does not include the terminating 0,0 entry * or any other (0,0) entries reserved for expansion. * * returns: * the number of entries */ int fdt_num_mem_rsv(const void *fdt); /** * fdt_get_mem_rsv - retrieve one memory reserve map entry * @fdt: pointer to the device tree blob * @address, @size: pointers to 64-bit variables * * On success, *address and *size will contain the address and size of * the n-th reserve map entry from the device tree blob, in * native-endian format. * * returns: * 0, on success * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); /** * fdt_subnode_offset_namelen - find a subnode based on substring * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * @namelen: number of characters of name to consider * * Identical to fdt_subnode_offset(), but only examine the first * namelen characters of name for matching the subnode name. This is * useful for finding subnodes based on a portion of a larger string, * such as a full path. */ #ifndef SWIG /* Not available in Python */ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, const char *name, int namelen); #endif /** * fdt_subnode_offset - find a subnode of a given node * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * * fdt_subnode_offset() finds a subnode of the node at structure block * offset parentoffset with the given name. name may include a unit * address, in which case fdt_subnode_offset() will find the subnode * with that unit address, or the unit address may be omitted, in * which case fdt_subnode_offset() will find an arbitrary subnode * whose name excluding unit address matches the given name. * * returns: * structure block offset of the requested subnode (>=0), on success * -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); /** * fdt_path_offset_namelen - find a tree node by its full path * @fdt: pointer to the device tree blob * @path: full path of the node to locate * @namelen: number of characters of path to consider * * Identical to fdt_path_offset(), but only consider the first namelen * characters of path as the path name. */ #ifndef SWIG /* Not available in Python */ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); #endif /** * fdt_path_offset - find a tree node by its full path * @fdt: pointer to the device tree blob * @path: full path of the node to locate * * fdt_path_offset() finds a node of a given path in the device tree. * Each path component may omit the unit address portion, but the * results of this are undefined if any such path component is * ambiguous (that is if there are multiple nodes at the relevant * level matching the given component, differentiated only by unit * address). * * returns: * structure block offset of the node with the requested path (>=0), on * success * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid * -FDT_ERR_NOTFOUND, if the requested node does not exist * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_path_offset(const void *fdt, const char *path); /** * fdt_get_name - retrieve the name of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the starting node * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_name() retrieves the name (including unit address) of the * device tree node at structure block offset nodeoffset. If lenp is * non-NULL, the length of this name is also returned, in the integer * pointed to by lenp. * * returns: * pointer to the node's name, on success * If lenp is non-NULL, *lenp contains the length of that name * (>=0) * NULL, on error * if lenp is non-NULL *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); /** * fdt_first_property_offset - find the offset of a node's first property * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of a node * * fdt_first_property_offset() finds the first property of the node at * the given structure block offset. * * returns: * structure block offset of the property (>=0), on success * -FDT_ERR_NOTFOUND, if the requested node has no properties * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_first_property_offset(const void *fdt, int nodeoffset); /** * fdt_next_property_offset - step through a node's properties * @fdt: pointer to the device tree blob * @offset: structure block offset of a property * * fdt_next_property_offset() finds the property immediately after the * one at the given structure block offset. This will be a property * of the same node as the given property. * * returns: * structure block offset of the next property (>=0), on success * -FDT_ERR_NOTFOUND, if the given property is the last in its node * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_next_property_offset(const void *fdt, int offset); /** * fdt_for_each_property_offset - iterate over all properties of a node * * @property_offset: property offset (int, lvalue) * @fdt: FDT blob (const void *) * @node: node offset (int) * * This is actually a wrapper around a for loop and would be used like so: * * fdt_for_each_property_offset(property, fdt, node) { * Use property * ... * } * * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { * Error handling * } * * Note that this is implemented as a macro and property is used as * iterator in the loop. The node variable can be constant or even a * literal. */ #define fdt_for_each_property_offset(property, fdt, node) \ for (property = fdt_first_property_offset(fdt, node); \ property >= 0; \ property = fdt_next_property_offset(fdt, property)) /** * fdt_get_property_by_offset - retrieve the property at a given offset * @fdt: pointer to the device tree blob * @offset: offset of the property to retrieve * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_property_by_offset() retrieves a pointer to the * fdt_property structure within the device tree blob at the given * offset. If lenp is non-NULL, the length of the property value is * also returned, in the integer pointed to by lenp. * * Note that this code only works on device tree versions >= 16. fdt_getprop() * works on all versions. * * returns: * pointer to the structure representing the property * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, int offset, int *lenp); /** * fdt_get_property_namelen - find a property based on substring * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @namelen: number of characters of name to consider * @lenp: pointer to an integer variable (will be overwritten) or NULL * * Identical to fdt_get_property(), but only examine the first namelen * characters of name for matching the property name. */ #ifndef SWIG /* Not available in Python */ const struct fdt_property *fdt_get_property_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp); #endif /** * fdt_get_property - find a given property in a given node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_get_property() retrieves a pointer to the fdt_property * structure within the device tree blob corresponding to the property * named 'name' of the node at offset nodeoffset. If lenp is * non-NULL, the length of the property value is also returned, in the * integer pointed to by lenp. * * returns: * pointer to the structure representing the property * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_NOTFOUND, node does not have named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, const char *name, int *lenp); static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, const char *name, int *lenp) { return (struct fdt_property *)(uintptr_t) fdt_get_property(fdt, nodeoffset, name, lenp); } /** * fdt_getprop_by_offset - retrieve the value of a property at a given offset * @fdt: pointer to the device tree blob * @offset: offset of the property to read * @namep: pointer to a string variable (will be overwritten) or NULL * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_getprop_by_offset() retrieves a pointer to the value of the * property at structure block offset 'offset' (this will be a pointer * to within the device blob itself, not a copy of the value). If * lenp is non-NULL, the length of the property value is also * returned, in the integer pointed to by lenp. If namep is non-NULL, * the property's namne will also be returned in the char * pointed to * by namep (this will be a pointer to within the device tree's string * block, not a new copy of the name). * * returns: * pointer to the property's value * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * if namep is non-NULL *namep contiains a pointer to the property * name. * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ #ifndef SWIG /* This function is not useful in Python */ const void *fdt_getprop_by_offset(const void *fdt, int offset, const char **namep, int *lenp); #endif /** * fdt_getprop_namelen - get property value based on substring * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @namelen: number of characters of name to consider * @lenp: pointer to an integer variable (will be overwritten) or NULL * * Identical to fdt_getprop(), but only examine the first namelen * characters of name for matching the property name. */ #ifndef SWIG /* Not available in Python */ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const char *name, int namelen, int *lenp); static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, const char *name, int namelen, int *lenp) { return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, namelen, lenp); } #endif /** * fdt_getprop - retrieve the value of a given property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to find * @name: name of the property to find * @lenp: pointer to an integer variable (will be overwritten) or NULL * * fdt_getprop() retrieves a pointer to the value of the property * named 'name' of the node at offset nodeoffset (this will be a * pointer to within the device blob itself, not a copy of the value). * If lenp is non-NULL, the length of the property value is also * returned, in the integer pointed to by lenp. * * returns: * pointer to the property's value * if lenp is non-NULL, *lenp contains the length of the property * value (>=0) * NULL, on error * if lenp is non-NULL, *lenp contains an error code (<0): * -FDT_ERR_NOTFOUND, node does not have named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE * tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ const void *fdt_getprop(const void *fdt, int nodeoffset, const char *name, int *lenp); static inline void *fdt_getprop_w(void *fdt, int nodeoffset, const char *name, int *lenp) { return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); } /** * fdt_get_phandle - retrieve the phandle of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of the node * * fdt_get_phandle() retrieves the phandle of the device tree node at * structure block offset nodeoffset. * * returns: * the phandle of the node at nodeoffset, on success (!= 0, != -1) * 0, if the node has no phandle, or another error occurs */ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); /** * fdt_get_alias_namelen - get alias based on substring * @fdt: pointer to the device tree blob * @name: name of the alias th look up * @namelen: number of characters of name to consider * * Identical to fdt_get_alias(), but only examine the first namelen * characters of name for matching the alias name. */ #ifndef SWIG /* Not available in Python */ const char *fdt_get_alias_namelen(const void *fdt, const char *name, int namelen); #endif /** * fdt_get_alias - retrieve the path referenced by a given alias * @fdt: pointer to the device tree blob * @name: name of the alias th look up * * fdt_get_alias() retrieves the value of a given alias. That is, the * value of the property named 'name' in the node /aliases. * * returns: * a pointer to the expansion of the alias named 'name', if it exists * NULL, if the given alias or the /aliases node does not exist */ const char *fdt_get_alias(const void *fdt, const char *name); /** * fdt_get_path - determine the full path of a node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose path to find * @buf: character buffer to contain the returned path (will be overwritten) * @buflen: size of the character buffer at buf * * fdt_get_path() computes the full path of the node at offset * nodeoffset, and records that path in the buffer at buf. * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset. * * returns: * 0, on success * buf contains the absolute path of the node at * nodeoffset, as a NUL-terminated string. * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) * characters and will not fit in the given buffer. * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); /** * fdt_supernode_atdepth_offset - find a specific ancestor of a node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose parent to find * @supernodedepth: depth of the ancestor to find * @nodedepth: pointer to an integer variable (will be overwritten) or NULL * * fdt_supernode_atdepth_offset() finds an ancestor of the given node * at a specific depth from the root (where the root itself has depth * 0, its immediate subnodes depth 1 and so forth). So * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); * will always return 0, the offset of the root node. If the node at * nodeoffset has depth D, then: * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); * will return nodeoffset itself. * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset. * * returns: * structure block offset of the node at node offset's ancestor * of depth supernodedepth (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of * nodeoffset * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int supernodedepth, int *nodedepth); /** * fdt_node_depth - find the depth of a given node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose parent to find * * fdt_node_depth() finds the depth of a given node. The root node * has depth 0, its immediate subnodes depth 1 and so forth. * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset. * * returns: * depth of the node at nodeoffset (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_depth(const void *fdt, int nodeoffset); /** * fdt_parent_offset - find the parent of a given node * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose parent to find * * fdt_parent_offset() locates the parent node of a given node (that * is, it finds the offset of the node which contains the node at * nodeoffset as a subnode). * * NOTE: This function is expensive, as it must scan the device tree * structure from the start to nodeoffset, *twice*. * * returns: * structure block offset of the parent of the node at nodeoffset * (>=0), on success * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_parent_offset(const void *fdt, int nodeoffset); /** * fdt_node_offset_by_prop_value - find nodes with a given property value * @fdt: pointer to the device tree blob * @startoffset: only find nodes after this offset * @propname: property name to check * @propval: property value to search for * @proplen: length of the value in propval * * fdt_node_offset_by_prop_value() returns the offset of the first * node after startoffset, which has a property named propname whose * value is of length proplen and has value equal to propval; or if * startoffset is -1, the very first such node in the tree. * * To iterate through all nodes matching the criterion, the following * idiom can be used: * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, * propval, proplen); * while (offset != -FDT_ERR_NOTFOUND) { * // other code here * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, * propval, proplen); * } * * Note the -1 in the first call to the function, if 0 is used here * instead, the function will never locate the root node, even if it * matches the criterion. * * returns: * structure block offset of the located node (>= 0, >startoffset), * on success * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * tree after startoffset * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const char *propname, const void *propval, int proplen); /** * fdt_node_offset_by_phandle - find the node with a given phandle * @fdt: pointer to the device tree blob * @phandle: phandle value * * fdt_node_offset_by_phandle() returns the offset of the node * which has the given phandle value. If there is more than one node * in the tree with the given phandle (an invalid tree), results are * undefined. * * returns: * structure block offset of the located node (>= 0), on success * -FDT_ERR_NOTFOUND, no node with that phandle exists * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); /** * fdt_node_check_compatible: check a node's compatible property * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @compatible: string to match against * * * fdt_node_check_compatible() returns 0 if the given node contains a * 'compatible' property with the given string as one of its elements, * it returns non-zero otherwise, or on error. * * returns: * 0, if the node has a 'compatible' property listing the given string * 1, if the node has a 'compatible' property, but it does not list * the given string * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_check_compatible(const void *fdt, int nodeoffset, const char *compatible); /** * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value * @fdt: pointer to the device tree blob * @startoffset: only find nodes after this offset * @compatible: 'compatible' string to match against * * fdt_node_offset_by_compatible() returns the offset of the first * node after startoffset, which has a 'compatible' property which * lists the given compatible string; or if startoffset is -1, the * very first such node in the tree. * * To iterate through all nodes matching the criterion, the following * idiom can be used: * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); * while (offset != -FDT_ERR_NOTFOUND) { * // other code here * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); * } * * Note the -1 in the first call to the function, if 0 is used here * instead, the function will never locate the root node, even if it * matches the criterion. * * returns: * structure block offset of the located node (>= 0, >startoffset), * on success * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * tree after startoffset * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, standard meanings */ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, const char *compatible); /** * fdt_stringlist_contains - check a string list property for a string * @strlist: Property containing a list of strings to check * @listlen: Length of property * @str: String to search for * * This is a utility function provided for convenience. The list contains * one or more strings, each terminated by \0, as is found in a device tree * "compatible" property. * * @return: 1 if the string is found in the list, 0 not found, or invalid list */ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); /** * fdt_stringlist_count - count the number of strings in a string list * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list * @return: * the number of strings in the given property * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist */ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); /** * fdt_stringlist_search - find a string in a string list and return its index * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list * @string: string to look up in the string list * * Note that it is possible for this function to succeed on property values * that are not NUL-terminated. That's because the function will stop after * finding the first occurrence of @string. This can for example happen with * small-valued cell properties, such as #address-cells, when searching for * the empty string. * * @return: * the index of the string in the list of strings * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist or does not contain * the given string */ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, const char *string); /** * fdt_stringlist_get() - obtain the string at a given index in a string list * @fdt: pointer to the device tree blob * @nodeoffset: offset of a tree node * @property: name of the property containing the string list * @index: index of the string to return * @lenp: return location for the string length or an error code on failure * * Note that this will successfully extract strings from properties with * non-NUL-terminated values. For example on small-valued cell properties * this function will return the empty string. * * If non-NULL, the length of the string (on success) or a negative error-code * (on failure) will be stored in the integer pointer to by lenp. * * @return: * A pointer to the string at the given index in the string list or NULL on * failure. On success the length of the string will be stored in the memory * location pointed to by the lenp parameter, if non-NULL. On failure one of * the following negative error codes will be returned in the lenp parameter * (if non-NULL): * -FDT_ERR_BADVALUE if the property value is not NUL-terminated * -FDT_ERR_NOTFOUND if the property does not exist */ const char *fdt_stringlist_get(const void *fdt, int nodeoffset, const char *property, int index, int *lenp); /**********************************************************************/ /* Read-only functions (addressing related) */ /**********************************************************************/ /** * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells * * This is the maximum value for #address-cells, #size-cells and * similar properties that will be processed by libfdt. IEE1275 * requires that OF implementations handle values up to 4. * Implementations may support larger values, but in practice higher * values aren't used. */ #define FDT_MAX_NCELLS 4 /** * fdt_address_cells - retrieve address size for a bus represented in the tree * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to find the address size for * * When the node has a valid #address-cells property, returns its value. * * returns: * 0 <= n < FDT_MAX_NCELLS, on success * 2, if the node has no #address-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #address-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_address_cells(const void *fdt, int nodeoffset); /** * fdt_size_cells - retrieve address range size for a bus represented in the * tree * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to find the address range size for * * When the node has a valid #size-cells property, returns its value. * * returns: * 0 <= n < FDT_MAX_NCELLS, on success * 1, if the node has no #size-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_size_cells(const void *fdt, int nodeoffset); /**********************************************************************/ /* Write-in-place functions */ /**********************************************************************/ /** * fdt_setprop_inplace_namelen_partial - change a property's value, * but not its size * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @namelen: number of characters of name to consider * @idx: index of the property to change in the array * @val: pointer to data to replace the property value with * @len: length of the property value * * Identical to fdt_setprop_inplace(), but modifies the given property * starting from the given index, and using only the first characters * of the name. It is useful when you want to manipulate only one value of * an array and you have a string that doesn't end with \0. */ #ifndef SWIG /* Not available in Python */ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, const char *name, int namelen, uint32_t idx, const void *val, int len); #endif /** * fdt_setprop_inplace - change a property's value, but not its size * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: pointer to data to replace the property value with * @len: length of the property value * * fdt_setprop_inplace() replaces the value of a given property with * the data in val, of length len. This function cannot change the * size of a property, and so will only work if len is equal to the * current length of the property. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part * of the tree. * * returns: * 0, on success * -FDT_ERR_NOSPACE, if len is not equal to the property's current length * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ #ifndef SWIG /* Not available in Python */ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, const void *val, int len); #endif /** * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value to replace the property with * * fdt_setprop_inplace_u32() replaces the value of a given property * with the 32-bit integer value in val, converting val to big-endian * if necessary. This function cannot change the size of a property, * and so will only work if the property already exists and has length * 4. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part * of the tree. * * returns: * 0, on success * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 64-bit integer value to replace the property with * * fdt_setprop_inplace_u64() replaces the value of a given property * with the 64-bit integer value in val, converting val to big-endian * if necessary. This function cannot change the size of a property, * and so will only work if the property already exists and has length * 8. * * This function will alter only the bytes in the blob which contain * the given property value, and will not alter or move any other part * of the tree. * * returns: * 0, on success * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_inplace_cell - change the value of a single-cell property * * This is an alternative name for fdt_setprop_inplace_u32() */ static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); } /** * fdt_nop_property - replace a property with nop tags * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to nop * @name: name of the property to nop * * fdt_nop_property() will replace a given property's representation * in the blob with FDT_NOP tags, effectively removing it from the * tree. * * This function will alter only the bytes in the blob which contain * the property, and will not alter or move any other part of the * tree. * * returns: * 0, on success * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_nop_property(void *fdt, int nodeoffset, const char *name); /** * fdt_nop_node - replace a node (subtree) with nop tags * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to nop * * fdt_nop_node() will replace a given node's representation in the * blob, including all its subnodes, if any, with FDT_NOP tags, * effectively removing it from the tree. * * This function will alter only the bytes in the blob which contain * the node and its properties and subnodes, and will not alter or * move any other part of the tree. * * returns: * 0, on success * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_nop_node(void *fdt, int nodeoffset); /**********************************************************************/ /* Sequential write functions */ /**********************************************************************/ /* fdt_create_with_flags flags */ #define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property * names in the fdt. This can result in faster creation times, but * a larger fdt. */ #define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) /** * fdt_create_with_flags - begin creation of a new fdt * @fdt: pointer to memory allocated where fdt will be created * @bufsize: size of the memory space at fdt * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. * * fdt_create_with_flags() begins the process of creating a new fdt with * the sequential write interface. * * fdt creation process must end with fdt_finished() to produce a valid fdt. * * returns: * 0, on success * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt * -FDT_ERR_BADFLAGS, flags is not valid */ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); /** * fdt_create - begin creation of a new fdt * @fdt: pointer to memory allocated where fdt will be created * @bufsize: size of the memory space at fdt * * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. * * returns: * 0, on success * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt */ int fdt_create(void *buf, int bufsize); int fdt_resize(void *fdt, void *buf, int bufsize); int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); int fdt_begin_node(void *fdt, const char *name); int fdt_property(void *fdt, const char *name, const void *val, int len); static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } #ifndef SWIG /* Not available in Python */ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { return fdt_property_u32(fdt, name, val); } #endif /** * fdt_property_placeholder - add a new property and return a ptr to its value * * @fdt: pointer to the device tree blob * @name: name of property to add * @len: length of property value in bytes * @valp: returns a pointer to where where the value should be placed * * returns: * 0, on success * -FDT_ERR_BADMAGIC, * -FDT_ERR_NOSPACE, standard meanings */ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); #define fdt_property_string(fdt, name, str) \ fdt_property(fdt, name, str, strlen(str)+1) int fdt_end_node(void *fdt); int fdt_finish(void *fdt); /**********************************************************************/ /* Read-write functions */ /**********************************************************************/ int fdt_create_empty_tree(void *buf, int bufsize); int fdt_open_into(const void *fdt, void *buf, int bufsize); int fdt_pack(void *fdt); /** * fdt_add_mem_rsv - add one memory reserve map entry * @fdt: pointer to the device tree blob * @address, @size: 64-bit values (native endian) * * Adds a reserve map entry to the given blob reserving a region at * address address of length size. * * This function will insert data into the reserve map and will * therefore change the indexes of some entries in the table. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new reservation entry * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); /** * fdt_del_mem_rsv - remove a memory reserve map entry * @fdt: pointer to the device tree blob * @n: entry to remove * * fdt_del_mem_rsv() removes the n-th memory reserve map entry from * the blob. * * This function will delete data from the reservation table and will * therefore change the indexes of some entries in the table. * * returns: * 0, on success * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there * are less than n+1 reserve map entries) * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_del_mem_rsv(void *fdt, int n); /** * fdt_set_name - change the name of a given node * @fdt: pointer to the device tree blob * @nodeoffset: structure block offset of a node * @name: name to give the node * * fdt_set_name() replaces the name (including unit address, if any) * of the given node with the given string. NOTE: this function can't * efficiently check if the new name is unique amongst the given * node's siblings; results are undefined if this function is invoked * with a name equal to one of the given node's siblings. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob * to contain the new name * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, standard meanings */ int fdt_set_name(void *fdt, int nodeoffset, const char *name); /** * fdt_setprop - create or change a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: pointer to data to set the property value to * @len: length of the property value * * fdt_setprop() sets the value of the named property in the given * node to the given value and length, creating the property if it * does not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** * fdt_setprop_placeholder - allocate space for a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @len: length of the property value * @prop_data: return pointer to property data * * fdt_setprop_placeholer() allocates the named property in the given node. * If the property exists it is resized. In either case a pointer to the * property data is returned. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, int len, void **prop_data); /** * fdt_setprop_u32 - set a property to a 32-bit integer * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value for the property (native endian) * * fdt_setprop_u32() sets the value of the named property in the given * node to the given 32-bit integer value (converting to big-endian if * necessary), or creates a new property with that value if it does * not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_u64 - set a property to a 64-bit integer * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 64-bit integer value for the property (native endian) * * fdt_setprop_u64() sets the value of the named property in the given * node to the given 64-bit integer value (converting to big-endian if * necessary), or creates a new property with that value if it does * not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_setprop_cell - set a property to a single cell value * * This is an alternative name for fdt_setprop_u32() */ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { return fdt_setprop_u32(fdt, nodeoffset, name, val); } /** * fdt_setprop_string - set a property to a string value * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @str: string value for the property * * fdt_setprop_string() sets the value of the named property in the * given node to the given string value (using the length of the * string to determine the new length of the property), or creates a * new property with that value if it does not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ #define fdt_setprop_string(fdt, nodeoffset, name, str) \ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) /** * fdt_setprop_empty - set a property to an empty value * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * * fdt_setprop_empty() sets the value of the named property in the * given node to an empty (zero length) value, or creates a new empty * property if it does not already exist. * * This function may insert or delete data from the blob, and will * therefore change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ #define fdt_setprop_empty(fdt, nodeoffset, name) \ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) /** * fdt_appendprop - append to or create a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to append to * @val: pointer to data to append to the property value * @len: length of the data to append to the property value * * fdt_appendprop() appends the value to the named property in the * given node, creating the property if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, const void *val, int len); /** * fdt_appendprop_u32 - append a 32-bit integer value to a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 32-bit integer value to append to the property (native endian) * * fdt_appendprop_u32() appends the given 32-bit integer value * (converting to big-endian if necessary) to the value of the named * property in the given node, or creates a new property with that * value if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, const char *name, uint32_t val) { fdt32_t tmp = cpu_to_fdt32(val); return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_appendprop_u64 - append a 64-bit integer value to a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @val: 64-bit integer value to append to the property (native endian) * * fdt_appendprop_u64() appends the given 64-bit integer value * (converting to big-endian if necessary) to the value of the named * property in the given node, or creates a new property with that * value if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, const char *name, uint64_t val) { fdt64_t tmp = cpu_to_fdt64(val); return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); } /** * fdt_appendprop_cell - append a single cell value to a property * * This is an alternative name for fdt_appendprop_u32() */ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, const char *name, uint32_t val) { return fdt_appendprop_u32(fdt, nodeoffset, name, val); } /** * fdt_appendprop_string - append a string to a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change * @name: name of the property to change * @str: string value to append to the property * * fdt_appendprop_string() appends the given string to the value of * the named property in the given node, or creates a new property * with that value if it does not already exist. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain the new property value * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_TRUNCATED, standard meanings */ #define fdt_appendprop_string(fdt, nodeoffset, name, str) \ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) /** * fdt_appendprop_addrrange - append a address range property * @fdt: pointer to the device tree blob * @parent: offset of the parent node * @nodeoffset: offset of the node to add a property at * @name: name of property * @addr: start address of a given range * @size: size of a given range * * fdt_appendprop_addrrange() appends an address range value (start * address and size) to the value of the named property in the given * node, or creates a new property with that value if it does not * already exist. * If "name" is not specified, a default "reg" is used. * Cell sizes are determined by parent's #address-cells and #size-cells. * * This function may insert data into the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #address-cells property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to * contain a new property * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, const char *name, uint64_t addr, uint64_t size); /** * fdt_delprop - delete a property * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to nop * @name: name of the property to nop * * fdt_del_property() will delete the given property. * * This function will delete data from the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_NOTFOUND, node does not have the named property * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_delprop(void *fdt, int nodeoffset, const char *name); /** * fdt_add_subnode_namelen - creates a new node based on substring * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * @namelen: number of characters of name to consider * * Identical to fdt_add_subnode(), but use only the first namelen * characters of name as the name of the new node. This is useful for * creating subnodes based on a portion of a larger string, such as a * full path. */ #ifndef SWIG /* Not available in Python */ int fdt_add_subnode_namelen(void *fdt, int parentoffset, const char *name, int namelen); #endif /** * fdt_add_subnode - creates a new node * @fdt: pointer to the device tree blob * @parentoffset: structure block offset of a node * @name: name of the subnode to locate * * fdt_add_subnode() creates a new node as a subnode of the node at * structure block offset parentoffset, with the given name (which * should include the unit address, if any). * * This function will insert data into the blob, and will therefore * change the offsets of some existing nodes. * returns: * structure block offset of the created nodeequested subnode (>=0), on * success * -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE * tag * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of * the given name * -FDT_ERR_NOSPACE, if there is insufficient free space in the * blob to contain the new node * -FDT_ERR_NOSPACE * -FDT_ERR_BADLAYOUT * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings. */ int fdt_add_subnode(void *fdt, int parentoffset, const char *name); /** * fdt_del_node - delete a node (subtree) * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node to nop * * fdt_del_node() will remove the given node, including all its * subnodes if any, from the blob. * * This function will delete data from the blob, and will therefore * change the offsets of some existing nodes. * * returns: * 0, on success * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_del_node(void *fdt, int nodeoffset); /** * fdt_overlay_apply - Applies a DT overlay on a base DT * @fdt: pointer to the base device tree blob * @fdto: pointer to the device tree overlay blob * * fdt_overlay_apply() will apply the given device tree overlay on the * given base device tree. * * Expect the base device tree to be modified, even if the function * returns an error. * * returns: * 0, on success * -FDT_ERR_NOSPACE, there's not enough space in the base device tree * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or * properties in the base DT * -FDT_ERR_BADPHANDLE, * -FDT_ERR_BADOVERLAY, * -FDT_ERR_NOPHANDLES, * -FDT_ERR_INTERNAL, * -FDT_ERR_BADLAYOUT, * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADOFFSET, * -FDT_ERR_BADPATH, * -FDT_ERR_BADVERSION, * -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTATE, * -FDT_ERR_TRUNCATED, standard meanings */ int fdt_overlay_apply(void *fdt, void *fdto); /**********************************************************************/ /* Debugging / informational functions */ /**********************************************************************/ const char *fdt_strerror(int errval); #endif /* LIBFDT_H */ optee_os-4.3.0/core/lib/libfdt/include/libfdt_env.h000066400000000000000000000053011464416617300222200ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_ENV_H #define LIBFDT_ENV_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. */ #include #include #include #include #include #include #ifdef __CHECKER__ #define FDT_FORCE __attribute__((force)) #define FDT_BITWISE __attribute__((bitwise)) #else #define FDT_FORCE #define FDT_BITWISE #endif typedef uint16_t FDT_BITWISE fdt16_t; typedef uint32_t FDT_BITWISE fdt32_t; typedef uint64_t FDT_BITWISE fdt64_t; #define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) #define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) #define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) static inline uint16_t fdt16_to_cpu(fdt16_t x) { return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); } static inline fdt16_t cpu_to_fdt16(uint16_t x) { return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); } static inline uint32_t fdt32_to_cpu(fdt32_t x) { return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); } static inline fdt32_t cpu_to_fdt32(uint32_t x) { return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); } static inline uint64_t fdt64_to_cpu(fdt64_t x) { return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); } static inline fdt64_t cpu_to_fdt64(uint64_t x) { return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); } #undef CPU_TO_FDT64 #undef CPU_TO_FDT32 #undef CPU_TO_FDT16 #undef EXTRACT_BYTE #ifdef __APPLE__ #include /* strnlen() is not available on Mac OS < 10.7 */ # if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ MAC_OS_X_VERSION_10_7) #define strnlen fdt_strnlen /* * fdt_strnlen: returns the length of a string or max_count - which ever is * smallest. * Input 1 string: the string whose size is to be determined * Input 2 max_count: the maximum value returned by this function * Output: length of the string or max_count (the smallest of the two) */ static inline size_t fdt_strnlen(const char *string, size_t max_count) { const char *p = memchr(string, 0, max_count); return p ? p - string : max_count; } #endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7) */ #endif /* __APPLE__ */ #endif /* LIBFDT_ENV_H */ optee_os-4.3.0/core/lib/libfdt/libfdt_internal.h000066400000000000000000000027001464416617300216210ustar00rootroot00000000000000/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_INTERNAL_H #define LIBFDT_INTERNAL_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. */ #include #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) int fdt_ro_probe_(const void *fdt); #define FDT_RO_PROBE(fdt) \ { \ int totalsize_; \ if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ return totalsize_; \ } int fdt_check_node_offset_(const void *fdt, int offset); int fdt_check_prop_offset_(const void *fdt, int offset); const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); int fdt_node_end_offset_(void *fdt, int nodeoffset); static inline const void *fdt_offset_ptr_(const void *fdt, int offset) { return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; } static inline void *fdt_offset_ptr_w_(void *fdt, int offset) { return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); } static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) { const struct fdt_reserve_entry *rsv_table = (const struct fdt_reserve_entry *) ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); return rsv_table + n; } static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) { return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); } #define FDT_SW_MAGIC (~FDT_MAGIC) #endif /* LIBFDT_INTERNAL_H */ optee_os-4.3.0/core/lib/libfdt/sub.mk000066400000000000000000000003631464416617300174350ustar00rootroot00000000000000global-incdirs-y += include cflags-y += -Wno-cast-align cflags-y += -Wno-sign-compare cflags-y += -Wno-switch-default srcs-y += fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c srcs-y += fdt_empty_tree.c fdt_addresses.c fdt_overlay.c optee_os-4.3.0/core/lib/libtomcrypt/000077500000000000000000000000001464416617300174155ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/acipher_helpers.h000066400000000000000000000057321464416617300227320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2019, Linaro Limited */ #ifndef ACIPHER_HELPERS_H #define ACIPHER_HELPERS_H #include #include #include #include #include static inline bool bn_alloc_max(struct bignum **s) { *s = crypto_bignum_allocate(_CFG_CORE_LTC_BIGNUM_MAX_BITS); return *s; } static inline TEE_Result convert_ltc_verify_status(int ltc_res, int ltc_stat) { switch (ltc_res) { case CRYPT_OK: if (ltc_stat == 1) return TEE_SUCCESS; else return TEE_ERROR_SIGNATURE_INVALID; case CRYPT_INVALID_PACKET: case CRYPT_PK_INVALID_SIZE: return TEE_ERROR_SIGNATURE_INVALID; default: return TEE_ERROR_GENERIC; } } #ifdef _CFG_CORE_LTC_ECC TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key, struct ecc_keypair *key, uint32_t algo, size_t *key_size_bytes); TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key, struct ecc_public_key *key, uint32_t algo, size_t *key_size_bytes); #endif /* Write bignum to fixed size buffer in big endian order */ #define mp_to_unsigned_bin2(a, b, c) \ do { \ void *_a = (a); \ mp_to_unsigned_bin(_a, (b) + (c) - mp_unsigned_bin_size(_a)); \ } while(0) #ifdef _CFG_CORE_LTC_SM2_DSA TEE_Result sm2_ltc_dsa_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result sm2_ltc_dsa_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); #else static inline TEE_Result sm2_ltc_dsa_sign(uint32_t algo __unused, struct ecc_keypair *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, uint8_t *sig __unused, size_t *sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result sm2_ltc_dsa_verify(uint32_t algo __unused, struct ecc_public_key *key __unused, const uint8_t *msg __unused, size_t msg_len __unused, const uint8_t *sig __unused, size_t sig_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #ifdef _CFG_CORE_LTC_SM2_PKE TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); #else static inline TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key __unused, const uint8_t *src __unused, size_t src_len __unused, uint8_t *dst __unused, size_t *dst_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } static inline TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key __unused, const uint8_t *src __unused, size_t src_len __unused, uint8_t *dst __unused, size_t *dst_len __unused) { return TEE_ERROR_NOT_IMPLEMENTED; } #endif #endif /* ACIPHER_HELPERS_H */ optee_os-4.3.0/core/lib/libtomcrypt/aes.c000066400000000000000000000025311464416617300203320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #define AES_ENC_KEY_LEN (sizeof(ulong32) * 60) TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len, void *enc_key, size_t enc_keylen, unsigned int *rounds) { #ifdef _CFG_CORE_LTC_AES_ACCEL return crypto_accel_aes_expand_keys(key, key_len, enc_key, NULL, enc_keylen, rounds); #else symmetric_key skey; if (enc_keylen < AES_ENC_KEY_LEN) return TEE_ERROR_BAD_PARAMETERS; if (aes_setup(key, key_len, 0, &skey)) return TEE_ERROR_BAD_PARAMETERS; memcpy(enc_key, skey.rijndael.eK, AES_ENC_KEY_LEN); *rounds = skey.rijndael.Nr; #endif return TEE_SUCCESS; } void crypto_aes_enc_block(const void *enc_key, size_t enc_keylen __maybe_unused, unsigned int rounds, const void *src, void *dst) { #ifdef _CFG_CORE_LTC_AES_ACCEL crypto_accel_aes_ecb_enc(dst, src, enc_key, rounds, 1); #else symmetric_key skey = { }; assert(enc_keylen >= AES_ENC_KEY_LEN); skey.rijndael.eK = LTC_ALIGN_BUF(skey.rijndael.K, 16); memcpy(skey.rijndael.eK, enc_key, AES_ENC_KEY_LEN); skey.rijndael.Nr = rounds; if (aes_ecb_encrypt(src, dst, &skey)) panic(); #endif } optee_os-4.3.0/core/lib/libtomcrypt/aes_accel.c000066400000000000000000000154031464416617300214630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited * All rights reserved. * Copyright (c) 2001-2007, Tom St Denis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ /* * AES cipher for ARMv8 with Crypto Extensions * * Copyright (C) 2013 Linaro Ltd */ #include #include #include #define EXPANDED_AES_KEY_WORD_COUNT 60 #define EXPANDED_AES_KEY_LEN (EXPANDED_AES_KEY_WORD_COUNT * \ sizeof(uint32_t)) int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { unsigned int round_count = 0; LTC_ARGCHK(key); LTC_ARGCHK(skey); if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE; skey->rijndael.eK = LTC_ALIGN_BUF(skey->rijndael.K, 16); skey->rijndael.dK = skey->rijndael.eK + EXPANDED_AES_KEY_WORD_COUNT; if (crypto_accel_aes_expand_keys(key, keylen, skey->rijndael.eK, skey->rijndael.dK, EXPANDED_AES_KEY_LEN, &round_count)) return CRYPT_INVALID_ARG; if (num_rounds && (unsigned int)num_rounds != round_count) return CRYPT_INVALID_ROUNDS; skey->rijndael.Nr = round_count; return CRYPT_OK; } void rijndael_done(symmetric_key *skey __unused) { } int rijndael_keysize(int *keysize) { LTC_ARGCHK(keysize); if (*keysize < 16) return CRYPT_INVALID_KEYSIZE; else if (*keysize < 24) *keysize = 16; else if (*keysize < 32) *keysize = 24; else *keysize = 32; return CRYPT_OK; } static int aes_ecb_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, unsigned long blocks, const symmetric_key *skey) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(skey); crypto_accel_aes_ecb_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr, blocks); return CRYPT_OK; } static int aes_ecb_decrypt_nblocks(const unsigned char *ct, unsigned char *pt, unsigned long blocks, const symmetric_key *skey) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(skey); crypto_accel_aes_ecb_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr, blocks); return CRYPT_OK; } int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { return aes_ecb_encrypt_nblocks(pt, ct, 1, skey); } int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { return aes_ecb_decrypt_nblocks(ct, pt, 1, skey); } static int aes_cbc_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(IV); LTC_ARGCHK(skey); crypto_accel_aes_cbc_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr, blocks, IV); return CRYPT_OK; } static int aes_cbc_decrypt_nblocks(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(IV); LTC_ARGCHK(skey); crypto_accel_aes_cbc_dec(pt, ct, skey->rijndael.dK, skey->rijndael.Nr, blocks, IV); return CRYPT_OK; } #ifdef LTC_CTR_MODE static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(IV); LTC_ARGCHK(skey); if (mode == CTR_COUNTER_LITTLE_ENDIAN) { /* Accelerated algorithm supports big endian only */ return CRYPT_ERROR; } crypto_accel_aes_ctr_be_enc(ct, pt, skey->rijndael.eK, skey->rijndael.Nr, blocks, IV); return CRYPT_OK; } #endif static int aes_xts_encrypt_nblocks(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(tweak); LTC_ARGCHK(skey1); LTC_ARGCHK(skey2); LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr); crypto_accel_aes_xts_enc(ct, pt, skey1->rijndael.eK, skey1->rijndael.Nr, blocks, skey2->rijndael.eK, tweak); return CRYPT_OK; } static int aes_xts_decrypt_nblocks(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) { LTC_ARGCHK(pt); LTC_ARGCHK(ct); LTC_ARGCHK(tweak); LTC_ARGCHK(skey1); LTC_ARGCHK(skey2); LTC_ARGCHK(skey1->rijndael.Nr == skey2->rijndael.Nr); crypto_accel_aes_xts_dec(pt, ct, skey1->rijndael.dK, skey1->rijndael.Nr, blocks, skey2->rijndael.eK, tweak); return CRYPT_OK; } const struct ltc_cipher_descriptor aes_desc = { .name = "aes", .ID = 6, .min_key_length = 16, .max_key_length = 32, .block_length = 16, .default_rounds = 10, .setup = rijndael_setup, .ecb_encrypt = rijndael_ecb_encrypt, .ecb_decrypt = rijndael_ecb_decrypt, .done = rijndael_done, .keysize = rijndael_keysize, .accel_ecb_encrypt = aes_ecb_encrypt_nblocks, .accel_ecb_decrypt = aes_ecb_decrypt_nblocks, .accel_cbc_encrypt = aes_cbc_encrypt_nblocks, .accel_cbc_decrypt = aes_cbc_decrypt_nblocks, #ifdef LTC_CTR_MODE .accel_ctr_encrypt = aes_ctr_encrypt_nblocks, #endif .accel_xts_encrypt = aes_xts_encrypt_nblocks, .accel_xts_decrypt = aes_xts_decrypt_nblocks, }; optee_os-4.3.0/core/lib/libtomcrypt/cbc.c000066400000000000000000000064271464416617300203210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include "des2_key.h" struct ltc_cbc_ctx { struct crypto_cipher_ctx ctx; int cipher_idx; bool des3; int (*update)(const unsigned char *src, unsigned char *dst, unsigned long len, symmetric_CBC *cbc); symmetric_CBC state; }; static const struct crypto_cipher_ops ltc_cbc_ops; static struct ltc_cbc_ctx *to_cbc_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == <c_cbc_ops); return container_of(ctx, struct ltc_cbc_ctx, ctx); } static TEE_Result ltc_cbc_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv, size_t iv_len) { struct ltc_cbc_ctx *c = to_cbc_ctx(ctx); uint8_t tmp[24] = { 0 }; const uint8_t *k = key1; size_t kl = key1_len; if ((int)iv_len != cipher_descriptor[c->cipher_idx]->block_length) return TEE_ERROR_BAD_PARAMETERS; if (mode == TEE_MODE_ENCRYPT) c->update = cbc_encrypt; else c->update = cbc_decrypt; if (c->des3) get_des2_key(&k, &kl, tmp); if (cbc_start(c->cipher_idx, iv, k, kl, 0, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_cbc_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct ltc_cbc_ctx *c = to_cbc_ctx(ctx); if (c->update && c->update(data, dst, len, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static void ltc_cbc_final(struct crypto_cipher_ctx *ctx) { cbc_done(&to_cbc_ctx(ctx)->state); } static void ltc_cbc_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_cbc_ctx(ctx)); } static void ltc_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct ltc_cbc_ctx *src = to_cbc_ctx(src_ctx); struct ltc_cbc_ctx *dst = to_cbc_ctx(dst_ctx); assert(src->cipher_idx == dst->cipher_idx); dst->update = src->update; dst->state = src->state; } static const struct crypto_cipher_ops ltc_cbc_ops = { .init = ltc_cbc_init, .update = ltc_cbc_update, .final = ltc_cbc_final, .free_ctx = ltc_cbc_free_ctx, .copy_state = ltc_cbc_copy_state, }; static TEE_Result ltc_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret, int cipher_idx, bool des3) { struct ltc_cbc_ctx *c = NULL; if (cipher_idx < 0) return TEE_ERROR_NOT_SUPPORTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = <c_cbc_ops; c->cipher_idx = cipher_idx; c->des3 = des3; *ctx_ret = &c->ctx; return TEE_SUCCESS; } #if defined(_CFG_CORE_LTC_AES) TEE_Result crypto_aes_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx) { return ltc_cbc_alloc_ctx(ctx, find_cipher("aes"), false); } #endif #if defined(_CFG_CORE_LTC_DES) TEE_Result crypto_des_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx) { return ltc_cbc_alloc_ctx(ctx, find_cipher("des"), false); } TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx) { return ltc_cbc_alloc_ctx(ctx, find_cipher("3des"), true); } #endif optee_os-4.3.0/core/lib/libtomcrypt/ccm.c000066400000000000000000000140411464416617300203230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #define TEE_CCM_KEY_MAX_LENGTH 32 #define TEE_CCM_NONCE_MAX_LENGTH 13 #define TEE_CCM_TAG_MAX_LENGTH 16 struct tee_ccm_state { struct crypto_authenc_ctx aectx; ccm_state ctx; /* the ccm state as defined by LTC */ size_t tag_len; /* tag length */ }; static const struct crypto_authenc_ops aes_ccm_ops; TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) { struct tee_ccm_state *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->aectx.ops = &aes_ccm_ops; *ctx_ret = &ctx->aectx; return TEE_SUCCESS; } static struct tee_ccm_state *to_tee_ccm_state(struct crypto_authenc_ctx *aectx) { assert(aectx && aectx->ops == &aes_ccm_ops); return container_of(aectx, struct tee_ccm_state, aectx); } static void crypto_aes_ccm_free_ctx(struct crypto_authenc_ctx *aectx) { free(to_tee_ccm_state(aectx)); } static void crypto_aes_ccm_copy_state(struct crypto_authenc_ctx *dst_aectx, struct crypto_authenc_ctx *src_aectx) { struct tee_ccm_state *dst_ctx = to_tee_ccm_state(dst_aectx); struct tee_ccm_state *src_ctx = to_tee_ccm_state(src_aectx); dst_ctx->ctx = src_ctx->ctx; dst_ctx->tag_len = src_ctx->tag_len; } static TEE_Result crypto_aes_ccm_init(struct crypto_authenc_ctx *aectx, TEE_OperationMode mode __unused, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len) { int ltc_res = 0; int ltc_cipherindex = find_cipher("aes"); struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); if (ltc_cipherindex < 0) return TEE_ERROR_NOT_SUPPORTED; /* reset the state */ memset(&ccm->ctx, 0, sizeof(ccm->ctx)); ccm->tag_len = tag_len; /* Check the key length */ if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH)) return TEE_ERROR_BAD_PARAMETERS; /* check the nonce */ if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH) return TEE_ERROR_BAD_PARAMETERS; /* Check that payload_len and aad_len will fit into ints */ if (payload_len > INT_MAX || aad_len > INT_MAX) return TEE_ERROR_BAD_PARAMETERS; /* check the tag len */ if ((tag_len < 4) || (tag_len > TEE_CCM_TAG_MAX_LENGTH) || (tag_len % 2 != 0)) return TEE_ERROR_NOT_SUPPORTED; ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len, payload_len, tag_len, aad_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; /* Add the IV */ ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_ccm_update_aad(struct crypto_authenc_ctx *aectx, const uint8_t *data, size_t len) { struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); int ltc_res = 0; /* Add the AAD (note: aad can be NULL if aadlen == 0) */ ltc_res = ccm_add_aad(&ccm->ctx, data, len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_ccm_update_payload(struct crypto_authenc_ctx *aectx, TEE_OperationMode mode, const uint8_t *src_data, size_t len, uint8_t *dst_data) { int ltc_res = 0; int dir = 0; struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); unsigned char *pt = NULL; unsigned char *ct = NULL; if (mode == TEE_MODE_ENCRYPT) { pt = (unsigned char *)src_data; ct = dst_data; dir = CCM_ENCRYPT; } else { pt = dst_data; ct = (unsigned char *)src_data; dir = CCM_DECRYPT; } ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_ccm_enc_final(struct crypto_authenc_ctx *aectx, const uint8_t *src_data, size_t len, uint8_t *dst_data, uint8_t *dst_tag, size_t *dst_tag_len) { TEE_Result res = TEE_SUCCESS; struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); int ltc_res = 0; /* Finalize the remaining buffer */ res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data, len, dst_data); if (res != TEE_SUCCESS) return res; /* Check the tag length */ if (*dst_tag_len < ccm->tag_len) { *dst_tag_len = ccm->tag_len; return TEE_ERROR_SHORT_BUFFER; } *dst_tag_len = ccm->tag_len; /* Compute the tag */ ltc_res = ccm_done(&ccm->ctx, dst_tag, (unsigned long *)dst_tag_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_ccm_dec_final(struct crypto_authenc_ctx *aectx, const uint8_t *src_data, size_t len, uint8_t *dst_data, const uint8_t *tag, size_t tag_len) { TEE_Result res = TEE_ERROR_BAD_STATE; struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); int ltc_res = 0; uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH] = { 0 }; unsigned long ltc_tag_len = tag_len; if (tag_len == 0) return TEE_ERROR_SHORT_BUFFER; if (tag_len > TEE_CCM_TAG_MAX_LENGTH) return TEE_ERROR_BAD_STATE; /* Process the last buffer, if any */ res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_DECRYPT, src_data, len, dst_data); if (res != TEE_SUCCESS) return res; /* Finalize the authentication */ ltc_res = ccm_done(&ccm->ctx, dst_tag, <c_tag_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; if (consttime_memcmp(dst_tag, tag, tag_len) != 0) res = TEE_ERROR_MAC_INVALID; else res = TEE_SUCCESS; return res; } static void crypto_aes_ccm_final(struct crypto_authenc_ctx *aectx) { ccm_reset(&to_tee_ccm_state(aectx)->ctx); } static const struct crypto_authenc_ops aes_ccm_ops = { .init = crypto_aes_ccm_init, .update_aad = crypto_aes_ccm_update_aad, .update_payload = crypto_aes_ccm_update_payload, .enc_final = crypto_aes_ccm_enc_final, .dec_final = crypto_aes_ccm_dec_final, .final = crypto_aes_ccm_final, .free_ctx = crypto_aes_ccm_free_ctx, .copy_state = crypto_aes_ccm_copy_state, }; optee_os-4.3.0/core/lib/libtomcrypt/cmac.c000066400000000000000000000052351464416617300204710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited * Copyright (c) 2021, SumUp Services GmbH */ #include #include #include #include #include #include #include #include #include struct ltc_omac_ctx { struct crypto_mac_ctx ctx; int cipher_idx; omac_state state; }; static const struct crypto_mac_ops ltc_omac_ops; static struct ltc_omac_ctx *to_omac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == <c_omac_ops); return container_of(ctx, struct ltc_omac_ctx, ctx); } static TEE_Result ltc_omac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { struct ltc_omac_ctx *hc = to_omac_ctx(ctx); if (omac_init(&hc->state, hc->cipher_idx, key, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_omac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { if (omac_process(&to_omac_ctx(ctx)->state, data, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_omac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { unsigned long l = len; if (omac_done(&to_omac_ctx(ctx)->state, digest, &l) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static void ltc_omac_free_ctx(struct crypto_mac_ctx *ctx) { free(to_omac_ctx(ctx)); } static void ltc_omac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct ltc_omac_ctx *src = to_omac_ctx(src_ctx); struct ltc_omac_ctx *dst = to_omac_ctx(dst_ctx); assert(src->cipher_idx == dst->cipher_idx); dst->state = src->state; } static const struct crypto_mac_ops ltc_omac_ops = { .init = ltc_omac_init, .update = ltc_omac_update, .final = ltc_omac_final, .free_ctx = ltc_omac_free_ctx, .copy_state = ltc_omac_copy_state, }; static TEE_Result crypto_common_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, const char *cipher) { struct ltc_omac_ctx *ctx = NULL; int cipher_idx = find_cipher(cipher); if (!ctx_ret) return TEE_ERROR_BAD_PARAMETERS; if (cipher_idx < 0) return TEE_ERROR_NOT_SUPPORTED; ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->ctx.ops = <c_omac_ops; ctx->cipher_idx = cipher_idx; *ctx_ret = &ctx->ctx; return TEE_SUCCESS; } TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) { return crypto_common_cmac_alloc_ctx(ctx_ret, "aes"); } TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) { return crypto_common_cmac_alloc_ctx(ctx_ret, "3des"); } optee_os-4.3.0/core/lib/libtomcrypt/ctr.c000066400000000000000000000053321464416617300203540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include struct ltc_ctr_ctx { struct crypto_cipher_ctx ctx; int cipher_idx; int (*update)(const unsigned char *src, unsigned char *dst, unsigned long len, symmetric_CTR *ctr); symmetric_CTR state; }; static const struct crypto_cipher_ops ltc_ctr_ops; static struct ltc_ctr_ctx *to_ctr_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == <c_ctr_ops); return container_of(ctx, struct ltc_ctr_ctx, ctx); } static TEE_Result ltc_ctr_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct ltc_ctr_ctx *c = to_ctr_ctx(ctx); if ((int)iv_len != cipher_descriptor[c->cipher_idx]->block_length) return TEE_ERROR_BAD_PARAMETERS; if (mode == TEE_MODE_ENCRYPT) c->update = ctr_encrypt; else c->update = ctr_decrypt; if (ctr_start(c->cipher_idx, iv, key1, key1_len, 0, CTR_COUNTER_BIG_ENDIAN, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_ctr_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct ltc_ctr_ctx *c = to_ctr_ctx(ctx); if (c->update && c->update(data, dst, len, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static void ltc_ctr_final(struct crypto_cipher_ctx *ctx) { ctr_done(&to_ctr_ctx(ctx)->state); } static void ltc_ctr_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_ctr_ctx(ctx)); } static void ltc_ctr_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct ltc_ctr_ctx *src = to_ctr_ctx(src_ctx); struct ltc_ctr_ctx *dst = to_ctr_ctx(dst_ctx); assert(src->cipher_idx == dst->cipher_idx); dst->update = src->update; dst->state = src->state; } static const struct crypto_cipher_ops ltc_ctr_ops = { .init = ltc_ctr_init, .update = ltc_ctr_update, .final = ltc_ctr_final, .free_ctx = ltc_ctr_free_ctx, .copy_state = ltc_ctr_copy_state, }; TEE_Result crypto_aes_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct ltc_ctr_ctx *c = NULL; int cipher_idx = find_cipher("aes"); if (cipher_idx < 0) return TEE_ERROR_NOT_SUPPORTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = <c_ctr_ops; c->cipher_idx = cipher_idx; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/lib/libtomcrypt/des2_key.h000066400000000000000000000011121464416617300212660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2019, Linaro Limited */ static inline void get_des2_key(const uint8_t **key, size_t *key_len, uint8_t *tmp) { if (*key_len == 16) { /* * This corresponds to a 2DES key. The 2DES encryption * algorithm is similar to 3DES. Both perform and * encryption step, then a decryption step, followed * by another encryption step (EDE). However 2DES uses * the same key for both of the encryption (E) steps. */ memcpy(tmp, *key, 16); memcpy(tmp + 16, *key, 8); *key = tmp; *key_len = 24; } } optee_os-4.3.0/core/lib/libtomcrypt/dh.c000066400000000000000000000037101464416617300201550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include "acipher_helpers.h" TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->g)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->p)) goto err; if (!bn_alloc_max(&s->y)) goto err; if (!bn_alloc_max(&s->x)) goto err; if (!bn_alloc_max(&s->q)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->g); crypto_bignum_free(&s->p); crypto_bignum_free(&s->y); crypto_bignum_free(&s->x); return TEE_ERROR_OUT_OF_MEMORY; } TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q, size_t xbits, size_t key_size) { TEE_Result res = TEE_ERROR_GENERIC; dh_key ltc_tmp_key = { }; int ltc_res = 0; if (key_size != 8 * mp_unsigned_bin_size(key->p)) return TEE_ERROR_BAD_PARAMETERS; ltc_res = mp_init_multi(<c_tmp_key.base, <c_tmp_key.prime, NULL); if (ltc_res != CRYPT_OK) return TEE_ERROR_OUT_OF_MEMORY; /* Generate the DH key */ mp_copy(key->g, ltc_tmp_key.base); mp_copy(key->p, ltc_tmp_key.prime); ltc_res = dh_make_key(NULL, find_prng("prng_crypto"), q, xbits, <c_tmp_key); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; } else { ltc_mp.copy(ltc_tmp_key.y, key->y); ltc_mp.copy(ltc_tmp_key.x, key->x); res = TEE_SUCCESS; } dh_free(<c_tmp_key); return res; } TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, struct bignum *public_key, struct bignum *secret) { int err; if (!private_key || !public_key || !secret) return TEE_ERROR_BAD_PARAMETERS; err = mp_exptmod(public_key, private_key->x, private_key->p, secret); return ((err == CRYPT_OK) ? TEE_SUCCESS : TEE_ERROR_BAD_PARAMETERS); } optee_os-4.3.0/core/lib/libtomcrypt/dsa.c000066400000000000000000000110621464416617300203300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include "acipher_helpers.h" TEE_Result crypto_acipher_alloc_dsa_keypair(struct dsa_keypair *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->g)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->p)) goto err; if (!bn_alloc_max(&s->q)) goto err; if (!bn_alloc_max(&s->y)) goto err; if (!bn_alloc_max(&s->x)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->g); crypto_bignum_free(&s->p); crypto_bignum_free(&s->q); crypto_bignum_free(&s->y); return TEE_ERROR_OUT_OF_MEMORY; } TEE_Result crypto_acipher_alloc_dsa_public_key(struct dsa_public_key *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->g)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->p)) goto err; if (!bn_alloc_max(&s->q)) goto err; if (!bn_alloc_max(&s->y)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->g); crypto_bignum_free(&s->p); crypto_bignum_free(&s->q); return TEE_ERROR_OUT_OF_MEMORY; } TEE_Result crypto_acipher_gen_dsa_key(struct dsa_keypair *key, size_t key_size) { dsa_key ltc_tmp_key = { }; int ltc_res = 0; if (key_size != 8 * mp_unsigned_bin_size(key->p)) return TEE_ERROR_BAD_PARAMETERS; ltc_res = mp_init_multi(<c_tmp_key.g, <c_tmp_key.p, <c_tmp_key.q, <c_tmp_key.x, <c_tmp_key.y, NULL); if (ltc_res) return TEE_ERROR_OUT_OF_MEMORY; /* Copy the key parameters */ mp_copy(key->g, ltc_tmp_key.g); mp_copy(key->p, ltc_tmp_key.p); mp_copy(key->q, ltc_tmp_key.q); /* Generate the DSA key */ ltc_res = dsa_generate_key(NULL, find_prng("prng_crypto"), <c_tmp_key); if (ltc_res) return TEE_ERROR_BAD_PARAMETERS; /* Copy the key */ mp_copy(ltc_tmp_key.y, key->y); mp_copy(ltc_tmp_key.x, key->x); /* Free the temporary key */ dsa_free(<c_tmp_key); return TEE_SUCCESS; } TEE_Result crypto_acipher_dsa_sign(uint32_t algo, struct dsa_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res; size_t hash_size; int ltc_res; void *r, *s; dsa_key ltc_key = { .type = PK_PRIVATE, .qord = mp_unsigned_bin_size(key->q), .g = key->g, .p = key->p, .q = key->q, .y = key->y, .x = key->x, }; if (algo != TEE_ALG_DSA_SHA1 && algo != TEE_ALG_DSA_SHA224 && algo != TEE_ALG_DSA_SHA256) { res = TEE_ERROR_NOT_IMPLEMENTED; goto err; } res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &hash_size); if (res != TEE_SUCCESS) goto err; if (mp_unsigned_bin_size(ltc_key.q) < hash_size) hash_size = mp_unsigned_bin_size(ltc_key.q); if (msg_len != hash_size) { res = TEE_ERROR_SECURITY; goto err; } if (*sig_len < 2 * mp_unsigned_bin_size(ltc_key.q)) { *sig_len = 2 * mp_unsigned_bin_size(ltc_key.q); res = TEE_ERROR_SHORT_BUFFER; goto err; } ltc_res = mp_init_multi(&r, &s, NULL); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } ltc_res = dsa_sign_hash_raw(msg, msg_len, r, s, NULL, find_prng("prng_crypto"), <c_key); if (ltc_res == CRYPT_OK) { *sig_len = 2 * mp_unsigned_bin_size(ltc_key.q); memset(sig, 0, *sig_len); mp_to_unsigned_bin(r, (uint8_t *)sig + *sig_len/2 - mp_unsigned_bin_size(r)); mp_to_unsigned_bin(s, (uint8_t *)sig + *sig_len - mp_unsigned_bin_size(s)); res = TEE_SUCCESS; } else { res = TEE_ERROR_GENERIC; } mp_clear_multi(r, s, NULL); err: return res; } TEE_Result crypto_acipher_dsa_verify(uint32_t algo, struct dsa_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res; int ltc_stat, ltc_res; void *r, *s; dsa_key ltc_key = { .type = PK_PUBLIC, .qord = mp_unsigned_bin_size(key->q), .g = key->g, .p = key->p, .q = key->q, .y = key->y }; if (algo != TEE_ALG_DSA_SHA1 && algo != TEE_ALG_DSA_SHA224 && algo != TEE_ALG_DSA_SHA256) { res = TEE_ERROR_NOT_IMPLEMENTED; goto err; } ltc_res = mp_init_multi(&r, &s, NULL); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } mp_read_unsigned_bin(r, (uint8_t *)sig, sig_len/2); mp_read_unsigned_bin(s, (uint8_t *)sig + sig_len/2, sig_len/2); ltc_res = dsa_verify_hash_raw(r, s, msg, msg_len, <c_stat, <c_key); mp_clear_multi(r, s, NULL); res = convert_ltc_verify_status(ltc_res, ltc_stat); err: return res; } optee_os-4.3.0/core/lib/libtomcrypt/ecb.c000066400000000000000000000063071464416617300203200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include "des2_key.h" struct ltc_ecb_ctx { struct crypto_cipher_ctx ctx; int cipher_idx; bool des3; int (*update)(const unsigned char *src, unsigned char *dst, unsigned long len, symmetric_ECB *ecb); symmetric_ECB state; }; static const struct crypto_cipher_ops ltc_ecb_ops; static struct ltc_ecb_ctx *to_ecb_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == <c_ecb_ops); return container_of(ctx, struct ltc_ecb_ctx, ctx); } static TEE_Result ltc_ecb_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct ltc_ecb_ctx *c = to_ecb_ctx(ctx); uint8_t tmp[24] = { 0 }; const uint8_t *k = key1; size_t kl = key1_len; if (mode == TEE_MODE_ENCRYPT) c->update = ecb_encrypt; else c->update = ecb_decrypt; if (c->des3) get_des2_key(&k, &kl, tmp); if (ecb_start(c->cipher_idx, k, kl, 0, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_ecb_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct ltc_ecb_ctx *c = to_ecb_ctx(ctx); if (c->update && c->update(data, dst, len, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static void ltc_ecb_final(struct crypto_cipher_ctx *ctx) { ecb_done(&to_ecb_ctx(ctx)->state); } static void ltc_ecb_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_ecb_ctx(ctx)); } static void ltc_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct ltc_ecb_ctx *src = to_ecb_ctx(src_ctx); struct ltc_ecb_ctx *dst = to_ecb_ctx(dst_ctx); assert(src->cipher_idx == dst->cipher_idx); dst->update = src->update; dst->state = src->state; } static const struct crypto_cipher_ops ltc_ecb_ops = { .init = ltc_ecb_init, .update = ltc_ecb_update, .final = ltc_ecb_final, .free_ctx = ltc_ecb_free_ctx, .copy_state = ltc_ecb_copy_state, }; static TEE_Result ltc_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret, int cipher_idx, bool des3) { struct ltc_ecb_ctx *c = NULL; if (cipher_idx < 0) return TEE_ERROR_NOT_SUPPORTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = <c_ecb_ops; c->cipher_idx = cipher_idx; c->des3 = des3; *ctx_ret = &c->ctx; return TEE_SUCCESS; } #if defined(_CFG_CORE_LTC_AES) TEE_Result crypto_aes_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx) { return ltc_ecb_alloc_ctx(ctx, find_cipher("aes"), false); } #endif #if defined(_CFG_CORE_LTC_DES) TEE_Result crypto_des_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx) { return ltc_ecb_alloc_ctx(ctx, find_cipher("des"), false); } TEE_Result crypto_des3_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx) { return ltc_ecb_alloc_ctx(ctx, find_cipher("3des"), true); } #endif optee_os-4.3.0/core/lib/libtomcrypt/ecc.c000066400000000000000000000317731464416617300203260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include "acipher_helpers.h" static void _ltc_ecc_free_public_key(struct ecc_public_key *s) { if (!s) return; crypto_bignum_free(&s->x); crypto_bignum_free(&s->y); } /* * For a given TEE @curve, return key size and LTC curve name. Also check that * @algo is compatible with this curve. * @curve: TEE_ECC_CURVE_NIST_P192, ... * @algo: TEE_ALG_ECDSA_SHA1, ... */ static TEE_Result ecc_get_curve_info(uint32_t curve, uint32_t algo, size_t *key_size_bytes, size_t *key_size_bits, const char **curve_name) { size_t size_bytes = 0; size_t size_bits = 0; const char *name = NULL; /* * Excerpt of libtomcrypt documentation: * ecc_make_key(... key_size ...): The keysize is the size of the * modulus in bytes desired. Currently directly supported values * are 12, 16, 20, 24, 28, 32, 48, and 65 bytes which correspond * to key sizes of 112, 128, 160, 192, 224, 256, 384, and 521 bits * respectively. */ switch (curve) { case TEE_ECC_CURVE_NIST_P192: size_bits = 192; size_bytes = 24; name = "NISTP192"; if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA1) && (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) return TEE_ERROR_BAD_PARAMETERS; break; case TEE_ECC_CURVE_NIST_P224: size_bits = 224; size_bytes = 28; name = "NISTP224"; if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA224) && (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) return TEE_ERROR_BAD_PARAMETERS; break; case TEE_ECC_CURVE_NIST_P256: size_bits = 256; size_bytes = 32; name = "NISTP256"; if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA256) && (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) return TEE_ERROR_BAD_PARAMETERS; break; case TEE_ECC_CURVE_NIST_P384: size_bits = 384; size_bytes = 48; name = "NISTP384"; if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA384) && (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) return TEE_ERROR_BAD_PARAMETERS; break; case TEE_ECC_CURVE_NIST_P521: size_bits = 521; size_bytes = 66; name = "NISTP521"; if ((algo != 0) && (algo != TEE_ALG_ECDSA_SHA512) && (algo != TEE_ALG_ECDH_DERIVE_SHARED_SECRET)) return TEE_ERROR_BAD_PARAMETERS; break; case TEE_ECC_CURVE_SM2: size_bits = 256; size_bytes = 32; name = "SM2"; if ((algo != 0) && (algo != TEE_ALG_SM2_PKE) && (algo != TEE_ALG_SM2_DSA_SM3) && (algo != TEE_ALG_SM2_KEP)) return TEE_ERROR_BAD_PARAMETERS; break; default: return TEE_ERROR_NOT_SUPPORTED; } if (key_size_bytes) *key_size_bytes = size_bytes; if (key_size_bits) *key_size_bits = size_bits; if (curve_name) *curve_name = name; return TEE_SUCCESS; } /* Note: this function clears the key before setting the curve */ static TEE_Result ecc_set_curve_from_name(ecc_key *ltc_key, const char *curve_name) { const ltc_ecc_curve *curve = NULL; int ltc_res = 0; ltc_res = ecc_find_curve(curve_name, &curve); if (ltc_res != CRYPT_OK) return TEE_ERROR_NOT_SUPPORTED; ltc_res = ecc_set_curve(curve, ltc_key); if (ltc_res != CRYPT_OK) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result _ltc_ecc_generate_keypair(struct ecc_keypair *key, size_t key_size) { TEE_Result res; ecc_key ltc_tmp_key; int ltc_res; size_t key_size_bytes = 0; size_t key_size_bits = 0; const char *name = NULL; res = ecc_get_curve_info(key->curve, 0, &key_size_bytes, &key_size_bits, &name); if (res != TEE_SUCCESS) return res; if (key_size != key_size_bits) return TEE_ERROR_BAD_PARAMETERS; res = ecc_set_curve_from_name(<c_tmp_key, name); if (res) return res; /* Generate the ECC key */ ltc_res = ecc_generate_key(NULL, find_prng("prng_crypto"), <c_tmp_key); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; /* check the size of the keys */ if (((size_t)mp_count_bits(ltc_tmp_key.pubkey.x) > key_size_bits) || ((size_t)mp_count_bits(ltc_tmp_key.pubkey.y) > key_size_bits) || ((size_t)mp_count_bits(ltc_tmp_key.k) > key_size_bits)) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } /* check LTC is returning z==1 */ if (mp_count_bits(ltc_tmp_key.pubkey.z) != 1) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } /* Copy the key */ ltc_mp.copy(ltc_tmp_key.k, key->d); ltc_mp.copy(ltc_tmp_key.pubkey.x, key->x); ltc_mp.copy(ltc_tmp_key.pubkey.y, key->y); res = TEE_SUCCESS; exit: ecc_free(<c_tmp_key); /* Free the temporary key */ return res; } /* * Given a keypair "key", populate the Libtomcrypt private key "ltc_key" * It also returns the key size, in bytes */ TEE_Result ecc_populate_ltc_private_key(ecc_key *ltc_key, struct ecc_keypair *key, uint32_t algo, size_t *key_size_bytes) { TEE_Result res = TEE_ERROR_GENERIC; const char *name = NULL; res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name); if (res) return res; memset(ltc_key, 0, sizeof(*ltc_key)); res = ecc_set_curve_from_name(ltc_key, name); if (res) return res; ltc_key->type = PK_PRIVATE; mp_copy(key->d, ltc_key->k); mp_copy(key->x, ltc_key->pubkey.x); mp_copy(key->y, ltc_key->pubkey.y); mp_set_int(ltc_key->pubkey.z, 1); return TEE_SUCCESS; } /* * Given a public "key", populate the Libtomcrypt public key "ltc_key" * It also returns the key size, in bytes */ TEE_Result ecc_populate_ltc_public_key(ecc_key *ltc_key, struct ecc_public_key *key, uint32_t algo, size_t *key_size_bytes) { TEE_Result res = TEE_ERROR_GENERIC; const char *name = NULL; uint8_t one[1] = { 1 }; res = ecc_get_curve_info(key->curve, algo, key_size_bytes, NULL, &name); if (res) return res; memset(ltc_key, 0, sizeof(*ltc_key)); res = ecc_set_curve_from_name(ltc_key, name); if (res) return res; ltc_key->type = PK_PUBLIC; mp_copy(key->x, ltc_key->pubkey.x); mp_copy(key->y, ltc_key->pubkey.y); mp_read_unsigned_bin(ltc_key->pubkey.z, one, sizeof(one)); return TEE_SUCCESS; } static TEE_Result _ltc_ecc_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res = TEE_ERROR_GENERIC; int ltc_res = 0; size_t key_size_bytes = 0; ecc_key ltc_key = { }; unsigned long ltc_sig_len = 0; if (algo == 0) return TEE_ERROR_BAD_PARAMETERS; res = ecc_populate_ltc_private_key(<c_key, key, algo, &key_size_bytes); if (res != TEE_SUCCESS) return res; if (*sig_len < 2 * key_size_bytes) { *sig_len = 2 * key_size_bytes; res = TEE_ERROR_SHORT_BUFFER; goto out; } ltc_sig_len = *sig_len; ltc_res = ecc_sign_hash_rfc7518(msg, msg_len, sig, <c_sig_len, NULL, find_prng("prng_crypto"), <c_key); if (ltc_res == CRYPT_OK) { res = TEE_SUCCESS; } else { res = TEE_ERROR_GENERIC; } *sig_len = ltc_sig_len; out: ecc_free(<c_key); return res; } static TEE_Result _ltc_ecc_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res = TEE_ERROR_GENERIC; int ltc_stat = 0; int ltc_res = 0; size_t key_size_bytes = 0; ecc_key ltc_key = { }; if (algo == 0) return TEE_ERROR_BAD_PARAMETERS; res = ecc_populate_ltc_public_key(<c_key, key, algo, &key_size_bytes); if (res != TEE_SUCCESS) goto out; /* check keysize vs sig_len */ if ((key_size_bytes * 2) != sig_len) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } ltc_res = ecc_verify_hash_rfc7518(sig, sig_len, msg, msg_len, <c_stat, <c_key); res = convert_ltc_verify_status(ltc_res, ltc_stat); out: ecc_free(<c_key); return res; } static TEE_Result _ltc_ecc_shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len) { TEE_Result res = TEE_ERROR_GENERIC; int ltc_res = 0; ecc_key ltc_private_key = { }; ecc_key ltc_public_key = { }; size_t key_size_bytes = 0; /* Check the curves are the same */ if (private_key->curve != public_key->curve) return TEE_ERROR_BAD_PARAMETERS; res = ecc_populate_ltc_private_key(<c_private_key, private_key, 0, &key_size_bytes); if (res != TEE_SUCCESS) goto out; res = ecc_populate_ltc_public_key(<c_public_key, public_key, 0, &key_size_bytes); if (res != TEE_SUCCESS) goto out; ltc_res = ecc_shared_secret(<c_private_key, <c_public_key, secret, secret_len); if (ltc_res == CRYPT_OK) res = TEE_SUCCESS; else res = TEE_ERROR_BAD_PARAMETERS; out: ecc_free(<c_private_key); ecc_free(<c_public_key); return res; } static const struct crypto_ecc_keypair_ops ecc_keypair_ops = { .generate = _ltc_ecc_generate_keypair, .sign = _ltc_ecc_sign, .shared_secret = _ltc_ecc_shared_secret, }; static const struct crypto_ecc_public_ops ecc_public_key_ops = { .free = _ltc_ecc_free_public_key, .verify = _ltc_ecc_verify, }; static const struct crypto_ecc_keypair_ops sm2_dsa_keypair_ops = { .generate = _ltc_ecc_generate_keypair, .sign = sm2_ltc_dsa_sign, }; static const struct crypto_ecc_public_ops sm2_dsa_public_key_ops = { .free = _ltc_ecc_free_public_key, .verify = sm2_ltc_dsa_verify, }; static const struct crypto_ecc_keypair_ops sm2_pke_keypair_ops = { .generate = _ltc_ecc_generate_keypair, .decrypt = sm2_ltc_pke_decrypt, }; static const struct crypto_ecc_public_ops sm2_pke_public_key_ops = { .free = _ltc_ecc_free_public_key, .encrypt = sm2_ltc_pke_encrypt, }; static const struct crypto_ecc_keypair_ops sm2_kep_keypair_ops = { .generate = _ltc_ecc_generate_keypair, }; static const struct crypto_ecc_public_ops sm2_kep_public_key_ops = { .free = _ltc_ecc_free_public_key, }; const struct crypto_ecc_keypair_ops * crypto_asym_get_ecc_keypair_ops( uint32_t key_type) { switch (key_type) { case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: return &ecc_keypair_ops; case TEE_TYPE_SM2_DSA_KEYPAIR: if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA)) return NULL; return &sm2_dsa_keypair_ops; case TEE_TYPE_SM2_PKE_KEYPAIR: if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE)) return NULL; return &sm2_pke_keypair_ops; case TEE_TYPE_SM2_KEP_KEYPAIR: if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP)) return NULL; return &sm2_kep_keypair_ops; default: return NULL; } } TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s, uint32_t key_type, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); switch (key_type) { case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: s->ops = &ecc_keypair_ops; break; case TEE_TYPE_SM2_DSA_KEYPAIR: if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_DSA)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_dsa_keypair_ops; break; case TEE_TYPE_SM2_PKE_KEYPAIR: if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_PKE)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_pke_keypair_ops; break; case TEE_TYPE_SM2_KEP_KEYPAIR: if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_KEP)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_kep_keypair_ops; break; default: return TEE_ERROR_NOT_IMPLEMENTED; } if (!bn_alloc_max(&s->d)) goto err; if (!bn_alloc_max(&s->x)) goto err; if (!bn_alloc_max(&s->y)) goto err; return TEE_SUCCESS; err: s->ops = NULL; crypto_bignum_free(&s->d); crypto_bignum_free(&s->x); return TEE_ERROR_OUT_OF_MEMORY; } const struct crypto_ecc_public_ops* crypto_asym_get_ecc_public_ops(uint32_t key_type) { switch (key_type) { case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDH_PUBLIC_KEY: return &ecc_public_key_ops; case TEE_TYPE_SM2_DSA_PUBLIC_KEY: if (!IS_ENABLED(_CFG_CORE_LTC_SM2_DSA)) return NULL; return &sm2_dsa_public_key_ops; case TEE_TYPE_SM2_PKE_PUBLIC_KEY: if (!IS_ENABLED(_CFG_CORE_LTC_SM2_PKE)) return NULL; return &sm2_pke_public_key_ops; case TEE_TYPE_SM2_KEP_PUBLIC_KEY: if (!IS_ENABLED(_CFG_CORE_LTC_SM2_KEP)) return NULL; return &sm2_kep_public_key_ops; default: return NULL; } } TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s, uint32_t key_type, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); switch (key_type) { case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDH_PUBLIC_KEY: s->ops = &ecc_public_key_ops; break; case TEE_TYPE_SM2_DSA_PUBLIC_KEY: if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_DSA)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_dsa_public_key_ops; break; case TEE_TYPE_SM2_PKE_PUBLIC_KEY: if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_PKE)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_pke_public_key_ops; break; case TEE_TYPE_SM2_KEP_PUBLIC_KEY: if (!IS_ENABLED2(_CFG_CORE_LTC_SM2_KEP)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_kep_public_key_ops; break; default: return TEE_ERROR_NOT_IMPLEMENTED; } if (!bn_alloc_max(&s->x)) goto err; if (!bn_alloc_max(&s->y)) goto err; return TEE_SUCCESS; err: s->ops = NULL; crypto_bignum_free(&s->x); return TEE_ERROR_OUT_OF_MEMORY; } optee_os-4.3.0/core/lib/libtomcrypt/ed25519.c000066400000000000000000000112661464416617300205650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Technology Innovation Institute (TII) * Copyright (c) 2022, EPAM Systems */ #include #include #include #include #include #include #include #include "acipher_helpers.h" #define ED25519_KEY_SIZE UL(256) TEE_Result crypto_acipher_alloc_ed25519_keypair(struct ed25519_keypair *key, size_t key_size) { if (!key || key_size != ED25519_KEY_SIZE) return TEE_ERROR_BAD_PARAMETERS; memset(key, 0, sizeof(*key)); key->priv = calloc(1, key_size >> 3); key->pub = calloc(1, key_size >> 3); if (!key->priv || !key->pub) { free(key->priv); free(key->pub); return TEE_ERROR_OUT_OF_MEMORY; } return TEE_SUCCESS; } TEE_Result crypto_acipher_alloc_ed25519_public_key(struct ed25519_public_key *key, size_t key_size) { if (!key || key_size != ED25519_KEY_SIZE) return TEE_ERROR_BAD_PARAMETERS; memset(key, 0, sizeof(*key)); key->pub = calloc(1, key_size >> 3); if (!key->pub) return TEE_ERROR_OUT_OF_MEMORY; return TEE_SUCCESS; } TEE_Result crypto_acipher_gen_ed25519_key(struct ed25519_keypair *key, size_t key_size) { curve25519_key ltc_tmp_key = { }; if (key_size != ED25519_KEY_SIZE) return TEE_ERROR_BAD_PARAMETERS; if (ed25519_make_key(NULL, find_prng("prng_crypto"), <c_tmp_key) != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; assert(key_size >= sizeof(ltc_tmp_key.pub) && key_size >= sizeof(ltc_tmp_key.priv)); memcpy(key->pub, ltc_tmp_key.pub, sizeof(ltc_tmp_key.pub)); memcpy(key->priv, ltc_tmp_key.priv, sizeof(ltc_tmp_key.priv)); memzero_explicit(<c_tmp_key, sizeof(ltc_tmp_key)); return TEE_SUCCESS; } TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { int err; unsigned long siglen = 0; curve25519_key private_key = { .type = PK_PRIVATE, .algo = LTC_OID_ED25519, }; if (!key || !sig_len) return TEE_ERROR_BAD_PARAMETERS; siglen = *sig_len; memcpy(private_key.priv, key->priv, sizeof(private_key.priv)); memcpy(private_key.pub, key->pub, sizeof(private_key.pub)); err = ed25519_sign(msg, msg_len, sig, &siglen, &private_key); memzero_explicit(&private_key, sizeof(private_key)); if (err != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; *sig_len = siglen; return TEE_SUCCESS; } TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len, bool ph_flag, const uint8_t *ctx, size_t ctxlen) { int err = CRYPT_ERROR; unsigned long siglen = 0; curve25519_key private_key = { .type = PK_PRIVATE, .algo = LTC_OID_ED25519, }; if (!key || !sig_len) return TEE_ERROR_BAD_PARAMETERS; siglen = *sig_len; memcpy(private_key.priv, key->priv, sizeof(private_key.priv)); memcpy(private_key.pub, key->pub, sizeof(private_key.pub)); if (ph_flag) { err = ed25519ph_sign(msg, msg_len, sig, &siglen, ctx, ctxlen, &private_key); } else { err = ed25519ctx_sign(msg, msg_len, sig, &siglen, ctx, ctxlen, &private_key); } memzero_explicit(&private_key, sizeof(private_key)); if (err != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; *sig_len = siglen; return TEE_SUCCESS; } TEE_Result crypto_acipher_ed25519_verify(struct ed25519_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { int stat = 0; curve25519_key public_key = { .type = PK_PUBLIC, .algo = LTC_OID_ED25519, }; if (!key) return TEE_ERROR_BAD_PARAMETERS; memcpy(public_key.pub, key->pub, sizeof(public_key.pub)); if (ed25519_verify(msg, msg_len, sig, sig_len, &stat, &public_key) != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; if (stat != 1) return TEE_ERROR_SIGNATURE_INVALID; return TEE_SUCCESS; } TEE_Result crypto_acipher_ed25519ctx_verify(struct ed25519_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, bool ph_flag, const uint8_t *ctx, size_t ctxlen) { int stat = 0; curve25519_key public_key = { .type = PK_PUBLIC, .algo = LTC_OID_ED25519, }; if (!key) return TEE_ERROR_BAD_PARAMETERS; memcpy(public_key.pub, key->pub, sizeof(public_key.pub)); if (ph_flag) { if (ed25519ph_verify(msg, msg_len, sig, sig_len, ctx, ctxlen, &stat, &public_key) != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; } else { if (ed25519ctx_verify(msg, msg_len, sig, sig_len, ctx, ctxlen, &stat, &public_key) != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; } if (stat != 1) return TEE_ERROR_SIGNATURE_INVALID; return TEE_SUCCESS; } optee_os-4.3.0/core/lib/libtomcrypt/gcm.c000066400000000000000000000132561464416617300203360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #define TEE_GCM_TAG_MAX_LENGTH 16 struct tee_gcm_state { struct crypto_authenc_ctx aectx; gcm_state ctx; /* the gcm state as defined by LTC */ size_t tag_len; /* tag length */ }; static const struct crypto_authenc_ops aes_gcm_ops; static struct tee_gcm_state *to_tee_gcm_state(struct crypto_authenc_ctx *aectx) { assert(aectx && aectx->ops == &aes_gcm_ops); return container_of(aectx, struct tee_gcm_state, aectx); } TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) { struct tee_gcm_state *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->aectx.ops = &aes_gcm_ops; *ctx_ret = &ctx->aectx; return TEE_SUCCESS; } static void crypto_aes_gcm_free_ctx(struct crypto_authenc_ctx *aectx) { free(to_tee_gcm_state(aectx)); } static void crypto_aes_gcm_copy_state(struct crypto_authenc_ctx *dst_aectx, struct crypto_authenc_ctx *src_aectx) { struct tee_gcm_state *dst_ctx = to_tee_gcm_state(dst_aectx); struct tee_gcm_state *src_ctx = to_tee_gcm_state(src_aectx); dst_ctx->ctx = src_ctx->ctx; dst_ctx->tag_len = src_ctx->tag_len; } static TEE_Result crypto_aes_gcm_init(struct crypto_authenc_ctx *aectx, TEE_OperationMode mode __unused, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, size_t tag_len, size_t aad_len __unused, size_t payload_len __unused) { int ltc_res = 0; int ltc_cipherindex = find_cipher("aes"); struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); if (ltc_cipherindex < 0) return TEE_ERROR_NOT_SUPPORTED; /* reset the state */ memset(&gcm->ctx, 0, sizeof(gcm->ctx)); gcm->tag_len = tag_len; ltc_res = gcm_init(&gcm->ctx, ltc_cipherindex, key, key_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; /* Add the IV */ ltc_res = gcm_add_iv(&gcm->ctx, nonce, nonce_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_gcm_update_aad(struct crypto_authenc_ctx *aectx, const uint8_t *data, size_t len) { struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); int ltc_res = 0; /* Add the AAD (note: aad can be NULL if aadlen == 0) */ ltc_res = gcm_add_aad(&gcm->ctx, data, len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_gcm_update_payload(struct crypto_authenc_ctx *aectx, TEE_OperationMode mode, const uint8_t *src_data, size_t len, uint8_t *dst_data) { TEE_Result res = TEE_SUCCESS; int ltc_res = 0; int dir = 0; struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); unsigned char *pt = NULL; unsigned char *ct = NULL; if (mode == TEE_MODE_ENCRYPT) { pt = (unsigned char *)src_data; ct = dst_data; dir = GCM_ENCRYPT; } else { pt = dst_data; ct = (unsigned char *)src_data; dir = GCM_DECRYPT; } /* aad is optional ==> add one without length */ if (gcm->ctx.mode == LTC_GCM_MODE_IV) { res = crypto_aes_gcm_update_aad(aectx, NULL, 0); if (res != TEE_SUCCESS) return res; } /* process the data */ ltc_res = gcm_process(&gcm->ctx, pt, len, ct, dir); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_gcm_enc_final(struct crypto_authenc_ctx *aectx, const uint8_t *src_data, size_t len, uint8_t *dst_data, uint8_t *dst_tag, size_t *dst_tag_len) { TEE_Result res = TEE_SUCCESS; struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); int ltc_res = 0; /* Finalize the remaining buffer */ res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data, len, dst_data); if (res != TEE_SUCCESS) return res; /* Check the tag length */ if (*dst_tag_len < gcm->tag_len) { *dst_tag_len = gcm->tag_len; return TEE_ERROR_SHORT_BUFFER; } *dst_tag_len = gcm->tag_len; /* Compute the tag */ ltc_res = gcm_done(&gcm->ctx, dst_tag, (unsigned long *)dst_tag_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result crypto_aes_gcm_dec_final(struct crypto_authenc_ctx *aectx, const uint8_t *src_data, size_t len, uint8_t *dst_data, const uint8_t *tag, size_t tag_len) { TEE_Result res = TEE_ERROR_BAD_STATE; struct tee_gcm_state *gcm = to_tee_gcm_state(aectx); int ltc_res = 0; uint8_t dst_tag[TEE_GCM_TAG_MAX_LENGTH] = { 0 }; unsigned long ltc_tag_len = tag_len; if (tag_len == 0) return TEE_ERROR_SHORT_BUFFER; if (tag_len > TEE_GCM_TAG_MAX_LENGTH) return TEE_ERROR_BAD_STATE; /* Process the last buffer, if any */ res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_DECRYPT, src_data, len, dst_data); if (res != TEE_SUCCESS) return res; /* Finalize the authentication */ ltc_res = gcm_done(&gcm->ctx, dst_tag, <c_tag_len); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_STATE; if (consttime_memcmp(dst_tag, tag, tag_len) != 0) res = TEE_ERROR_MAC_INVALID; else res = TEE_SUCCESS; return res; } static void crypto_aes_gcm_final(struct crypto_authenc_ctx *aectx) { gcm_reset(&to_tee_gcm_state(aectx)->ctx); } static const struct crypto_authenc_ops aes_gcm_ops = { .init = crypto_aes_gcm_init, .update_aad = crypto_aes_gcm_update_aad, .update_payload = crypto_aes_gcm_update_payload, .enc_final = crypto_aes_gcm_enc_final, .dec_final = crypto_aes_gcm_dec_final, .final = crypto_aes_gcm_final, .free_ctx = crypto_aes_gcm_free_ctx, .copy_state = crypto_aes_gcm_copy_state, }; optee_os-4.3.0/core/lib/libtomcrypt/hash.c000066400000000000000000000127221464416617300205100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include /****************************************************************************** * Message digest functions ******************************************************************************/ struct ltc_hash_ctx { struct crypto_hash_ctx ctx; const struct ltc_hash_descriptor *descr; hash_state state; }; static const struct crypto_hash_ops ltc_hash_ops; static struct ltc_hash_ctx *to_hash_ctx(struct crypto_hash_ctx *ctx) { assert(ctx && ctx->ops == <c_hash_ops); return container_of(ctx, struct ltc_hash_ctx, ctx); } static TEE_Result ltc_hash_init(struct crypto_hash_ctx *ctx) { struct ltc_hash_ctx *hc = to_hash_ctx(ctx); if (hc->descr->init(&hc->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_hash_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { struct ltc_hash_ctx *hc = to_hash_ctx(ctx); if (hc->descr->process(&hc->state, data, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { struct ltc_hash_ctx *hc = to_hash_ctx(ctx); size_t hash_size = hc->descr->hashsize; uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; uint8_t *tmp_digest = NULL; if (len == 0) return TEE_ERROR_BAD_PARAMETERS; if (hash_size > len) { if (hash_size > sizeof(block_digest)) return TEE_ERROR_BAD_STATE; tmp_digest = block_digest; /* use a tempory buffer */ } else { tmp_digest = digest; } if (hc->descr->done(&hc->state, tmp_digest) == CRYPT_OK) { if (hash_size > len) memcpy(digest, tmp_digest, len); } else { return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static void ltc_hash_free_ctx(struct crypto_hash_ctx *ctx) { free(to_hash_ctx(ctx)); } static void ltc_hash_copy_state(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx) { struct ltc_hash_ctx *src = to_hash_ctx(src_ctx); struct ltc_hash_ctx *dst = to_hash_ctx(dst_ctx); assert(src->descr == dst->descr); dst->state = src->state; } static const struct crypto_hash_ops ltc_hash_ops = { .init = ltc_hash_init, .update = ltc_hash_update, .final = ltc_hash_final, .free_ctx = ltc_hash_free_ctx, .copy_state = ltc_hash_copy_state, }; static TEE_Result ltc_hash_alloc_ctx(struct crypto_hash_ctx **ctx_ret, int ltc_hash_idx) { struct ltc_hash_ctx *ctx = NULL; if (ltc_hash_idx < 0) return TEE_ERROR_NOT_SUPPORTED; ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->ctx.ops = <c_hash_ops; ctx->descr = hash_descriptor[ltc_hash_idx]; *ctx_ret = &ctx->ctx; return TEE_SUCCESS; } #if defined(_CFG_CORE_LTC_MD5) TEE_Result crypto_md5_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("md5")); } #endif #if defined(_CFG_CORE_LTC_SHA1) TEE_Result crypto_sha1_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha1")); } #endif #if defined(_CFG_CORE_LTC_SHA224) TEE_Result crypto_sha224_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha224")); } #endif #if defined(_CFG_CORE_LTC_SHA256) TEE_Result crypto_sha256_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha256")); } #endif #if defined(_CFG_CORE_LTC_SHA384) TEE_Result crypto_sha384_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha384")); } #endif #if defined(_CFG_CORE_LTC_SHA512) TEE_Result crypto_sha512_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha512")); } #endif #if defined(_CFG_CORE_LTC_SHA256) TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, size_t data_size) { hash_state hs; uint8_t digest[TEE_SHA256_HASH_SIZE]; if (sha256_init(&hs) != CRYPT_OK) return TEE_ERROR_GENERIC; if (sha256_process(&hs, data, data_size) != CRYPT_OK) return TEE_ERROR_GENERIC; if (sha256_done(&hs, digest) != CRYPT_OK) return TEE_ERROR_GENERIC; if (consttime_memcmp(digest, hash, sizeof(digest)) != 0) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } #endif #if defined(_CFG_CORE_LTC_SHA512_256) TEE_Result hash_sha512_256_compute(uint8_t *digest, const uint8_t *data, size_t data_size) { hash_state hs; if (sha512_256_init(&hs) != CRYPT_OK) return TEE_ERROR_GENERIC; if (sha512_256_process(&hs, data, data_size) != CRYPT_OK) return TEE_ERROR_GENERIC; if (sha512_256_done(&hs, digest) != CRYPT_OK) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } #endif #if defined(_CFG_CORE_LTC_SHA3_224) TEE_Result crypto_sha3_224_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha3-224")); } #endif #if defined(_CFG_CORE_LTC_SHA3_256) TEE_Result crypto_sha3_256_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha3-256")); } #endif #if defined(_CFG_CORE_LTC_SHA3_384) TEE_Result crypto_sha3_384_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha3-384")); } #endif #if defined(_CFG_CORE_LTC_SHA3_512) TEE_Result crypto_sha3_512_alloc_ctx(struct crypto_hash_ctx **ctx) { return ltc_hash_alloc_ctx(ctx, find_hash("sha3-512")); } #endif optee_os-4.3.0/core/lib/libtomcrypt/hmac.c000066400000000000000000000076401464416617300205000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include struct ltc_hmac_ctx { struct crypto_mac_ctx ctx; int hash_idx; hmac_state state; }; static const struct crypto_mac_ops ltc_hmac_ops; static struct ltc_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == <c_hmac_ops); return container_of(ctx, struct ltc_hmac_ctx, ctx); } static TEE_Result ltc_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { struct ltc_hmac_ctx *hc = to_hmac_ctx(ctx); if (hmac_init(&hc->state, hc->hash_idx, key, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_hmac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { if (hmac_process(&to_hmac_ctx(ctx)->state, data, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { unsigned long l = len; if (hmac_done(&to_hmac_ctx(ctx)->state, digest, &l) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static void ltc_hmac_free_ctx(struct crypto_mac_ctx *ctx) { free(to_hmac_ctx(ctx)); } static void ltc_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct ltc_hmac_ctx *src = to_hmac_ctx(src_ctx); struct ltc_hmac_ctx *dst = to_hmac_ctx(dst_ctx); assert(src->hash_idx == dst->hash_idx); dst->state = src->state; } static const struct crypto_mac_ops ltc_hmac_ops = { .init = ltc_hmac_init, .update = ltc_hmac_update, .final = ltc_hmac_final, .free_ctx = ltc_hmac_free_ctx, .copy_state = ltc_hmac_copy_state, }; static TEE_Result ltc_hmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, int hash_idx) { struct ltc_hmac_ctx *ctx = NULL; if (hash_idx < 0) return TEE_ERROR_NOT_SUPPORTED; ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->ctx.ops = <c_hmac_ops; ctx->hash_idx = hash_idx; *ctx_ret = &ctx->ctx; return TEE_SUCCESS; } #if defined(_CFG_CORE_LTC_MD5) TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("md5")); } #endif #if defined(_CFG_CORE_LTC_SHA1) TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha1")); } #endif #if defined(_CFG_CORE_LTC_SHA224) TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha224")); } #endif #if defined(_CFG_CORE_LTC_SHA256) TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha256")); } #endif #if defined(_CFG_CORE_LTC_SHA384) TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha384")); } #endif #if defined(_CFG_CORE_LTC_SHA512) TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha512")); } #endif #if defined(_CFG_CORE_LTC_SHA3_224) TEE_Result crypto_hmac_sha3_224_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-224")); } #endif #if defined(_CFG_CORE_LTC_SHA3_256) TEE_Result crypto_hmac_sha3_256_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-256")); } #endif #if defined(_CFG_CORE_LTC_SHA3_384) TEE_Result crypto_hmac_sha3_384_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-384")); } #endif #if defined(_CFG_CORE_LTC_SHA3_512) TEE_Result crypto_hmac_sha3_512_alloc_ctx(struct crypto_mac_ctx **ctx) { return ltc_hmac_alloc_ctx(ctx, find_hash("sha3-512")); } #endif optee_os-4.3.0/core/lib/libtomcrypt/include/000077500000000000000000000000001464416617300210405ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/include/tomcrypt_init.h000066400000000000000000000003071464416617300241150ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef __TOMCRYPT_INIT_H #define __TOMCRYPT_INIT_H void tomcrypt_init(void); #endif /*__TOMCRYPT_INIT_H*/ optee_os-4.3.0/core/lib/libtomcrypt/include/tomcrypt_mp.h000066400000000000000000000004701464416617300235670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef TOMCRYPT_MP_H_ #define TOMCRYPT_MP_H_ #if defined(_CFG_CORE_LTC_ACIPHER) void init_mp_tomcrypt(void); #else static inline void init_mp_tomcrypt(void) { } #endif #endif /* TOMCRYPT_MP_H_ */ optee_os-4.3.0/core/lib/libtomcrypt/mpi_desc.c000066400000000000000000000332611464416617300213510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include #include #include #include #include #include #include #include #include #if defined(_CFG_CORE_LTC_PAGER) #include #include #endif /* Size needed for xtest to pass reliably on both ARM32 and ARM64 */ #define MPI_MEMPOOL_SIZE (46 * 1024) /* From mbedtls/library/bignum.c */ #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ #define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) #if defined(_CFG_CORE_LTC_PAGER) /* allocate pageable_zi vmem for mp scratch memory pool */ static struct mempool *get_mp_scratch_memory_pool(void) { size_t size; void *data; size = ROUNDUP(MPI_MEMPOOL_SIZE, SMALL_PAGE_SIZE); data = tee_pager_alloc(size); if (!data) panic(); return mempool_alloc_pool(data, size, tee_pager_release_phys); } #else /* _CFG_CORE_LTC_PAGER */ static struct mempool *get_mp_scratch_memory_pool(void) { static uint8_t data[MPI_MEMPOOL_SIZE] __aligned(MEMPOOL_ALIGN); return mempool_alloc_pool(data, sizeof(data), NULL); } #endif void init_mp_tomcrypt(void) { struct mempool *p = get_mp_scratch_memory_pool(); if (!p) panic(); mbedtls_mpi_mempool = p; assert(!mempool_default); mempool_default = p; } static int init(void **a) { mbedtls_mpi *bn = mempool_alloc(mbedtls_mpi_mempool, sizeof(*bn)); if (!bn) return CRYPT_MEM; mbedtls_mpi_init_mempool(bn); *a = bn; return CRYPT_OK; } static int init_size(int size_bits __unused, void **a) { return init(a); } static void deinit(void *a) { mbedtls_mpi_free((mbedtls_mpi *)a); mempool_free(mbedtls_mpi_mempool, a); } static int neg(void *a, void *b) { if (mbedtls_mpi_copy(b, a)) return CRYPT_MEM; ((mbedtls_mpi *)b)->s *= -1; return CRYPT_OK; } static int copy(void *a, void *b) { if (mbedtls_mpi_copy(b, a)) return CRYPT_MEM; return CRYPT_OK; } static int init_copy(void **a, void *b) { if (init(a) != CRYPT_OK) { return CRYPT_MEM; } return copy(b, *a); } /* ---- trivial ---- */ static int set_int(void *a, ltc_mp_digit b) { uint32_t b32 = b; if (b32 != b) return CRYPT_INVALID_ARG; mbedtls_mpi_uint p = b32; mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p }; if (mbedtls_mpi_copy(a, &bn)) return CRYPT_MEM; return CRYPT_OK; } static unsigned long get_int(void *a) { mbedtls_mpi *bn = a; if (!bn->n) return 0; return bn->p[bn->n - 1]; } static ltc_mp_digit get_digit(void *a, int n) { mbedtls_mpi *bn = a; COMPILE_TIME_ASSERT(sizeof(ltc_mp_digit) >= sizeof(mbedtls_mpi_uint)); if (n < 0 || (size_t)n >= bn->n) return 0; return bn->p[n]; } static int get_digit_count(void *a) { return ROUNDUP(mbedtls_mpi_size(a), sizeof(mbedtls_mpi_uint)) / sizeof(mbedtls_mpi_uint); } static int compare(void *a, void *b) { int ret = mbedtls_mpi_cmp_mpi(a, b); if (ret < 0) return LTC_MP_LT; if (ret > 0) return LTC_MP_GT; return LTC_MP_EQ; } static int compare_d(void *a, ltc_mp_digit b) { unsigned long v = b; unsigned int shift = 31; uint32_t mask = BIT(shift) - 1; mbedtls_mpi bn; mbedtls_mpi_init_mempool(&bn); while (true) { mbedtls_mpi_add_int(&bn, &bn, v & mask); v >>= shift; if (!v) break; mbedtls_mpi_shift_l(&bn, shift); } int ret = compare(a, &bn); mbedtls_mpi_free(&bn); return ret; } static int count_bits(void *a) { return mbedtls_mpi_bitlen(a); } static int count_lsb_bits(void *a) { return mbedtls_mpi_lsb(a); } static int twoexpt(void *a, int n) { if (mbedtls_mpi_set_bit(a, n, 1)) return CRYPT_MEM; return CRYPT_OK; } /* ---- conversions ---- */ /* read ascii string */ static int read_radix(void *a, const char *b, int radix) { int res = mbedtls_mpi_read_string(a, radix, b); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } /* write one */ static int write_radix(void *a, char *b, int radix) { size_t ol = SIZE_MAX; int res = mbedtls_mpi_write_string(a, radix, b, ol, &ol); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } /* get size as unsigned char string */ static unsigned long unsigned_size(void *a) { return mbedtls_mpi_size(a); } /* store */ static int unsigned_write(void *a, unsigned char *b) { int res = mbedtls_mpi_write_binary(a, b, unsigned_size(a)); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } /* read */ static int unsigned_read(void *a, unsigned char *b, unsigned long len) { int res = mbedtls_mpi_read_binary(a, b, len); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } /* add */ static int add(void *a, void *b, void *c) { if (mbedtls_mpi_add_mpi(c, a, b)) return CRYPT_MEM; return CRYPT_OK; } static int addi(void *a, ltc_mp_digit b, void *c) { uint32_t b32 = b; if (b32 != b) return CRYPT_INVALID_ARG; mbedtls_mpi_uint p = b32; mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p }; return add(a, &bn, c); } /* sub */ static int sub(void *a, void *b, void *c) { if (mbedtls_mpi_sub_mpi(c, a, b)) return CRYPT_MEM; return CRYPT_OK; } static int subi(void *a, ltc_mp_digit b, void *c) { uint32_t b32 = b; if (b32 != b) return CRYPT_INVALID_ARG; mbedtls_mpi_uint p = b32; mbedtls_mpi bn = { .s = 1, .n = 1, .p = &p }; return sub(a, &bn, c); } /* mul */ static int mul(void *a, void *b, void *c) { if (mbedtls_mpi_mul_mpi(c, a, b)) return CRYPT_MEM; return CRYPT_OK; } static int muli(void *a, ltc_mp_digit b, void *c) { if (b > (unsigned long) UINT32_MAX) return CRYPT_INVALID_ARG; if (mbedtls_mpi_mul_int(c, a, b)) return CRYPT_MEM; return CRYPT_OK; } /* sqr */ static int sqr(void *a, void *b) { return mul(a, a, b); } /* div */ static int divide(void *a, void *b, void *c, void *d) { int res = mbedtls_mpi_div_mpi(c, d, a, b); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } static int div_2(void *a, void *b) { if (mbedtls_mpi_copy(b, a)) return CRYPT_MEM; if (mbedtls_mpi_shift_r(b, 1)) return CRYPT_MEM; return CRYPT_OK; } /* modi */ static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) { mbedtls_mpi bn_b; mbedtls_mpi bn_c; int res = 0; mbedtls_mpi_init_mempool(&bn_b); mbedtls_mpi_init_mempool(&bn_c); res = set_int(&bn_b, b); if (res) return res; res = mbedtls_mpi_mod_mpi(&bn_c, &bn_b, a); if (!res) *c = get_int(&bn_c); mbedtls_mpi_free(&bn_b); mbedtls_mpi_free(&bn_c); if (res) return CRYPT_MEM; return CRYPT_OK; } /* gcd */ static int gcd(void *a, void *b, void *c) { if (mbedtls_mpi_gcd(c, a, b)) return CRYPT_MEM; return CRYPT_OK; } /* lcm */ static int lcm(void *a, void *b, void *c) { int res = CRYPT_MEM; mbedtls_mpi tmp; mbedtls_mpi_init_mempool(&tmp); if (mbedtls_mpi_mul_mpi(&tmp, a, b)) goto out; if (mbedtls_mpi_gcd(c, a, b)) goto out; /* We use the following equality: gcd(a, b) * lcm(a, b) = a * b */ res = divide(&tmp, c, c, NULL); out: mbedtls_mpi_free(&tmp); return res; } static int mod(void *a, void *b, void *c) { int res = mbedtls_mpi_mod_mpi(c, a, b); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } static int addmod(void *a, void *b, void *c, void *d) { int res = add(a, b, d); if (res) return res; return mod(d, c, d); } static int submod(void *a, void *b, void *c, void *d) { int res = sub(a, b, d); if (res) return res; return mod(d, c, d); } static int mulmod(void *a, void *b, void *c, void *d) { int res; mbedtls_mpi ta; mbedtls_mpi tb; mbedtls_mpi_init_mempool(&ta); mbedtls_mpi_init_mempool(&tb); res = mod(a, c, &ta); if (res) goto out; res = mod(b, c, &tb); if (res) goto out; res = mul(&ta, &tb, d); if (res) goto out; res = mod(d, c, d); out: mbedtls_mpi_free(&ta); mbedtls_mpi_free(&tb); return res; } static int sqrmod(void *a, void *b, void *c) { return mulmod(a, a, b, c); } /* invmod */ static int invmod(void *a, void *b, void *c) { int res = mbedtls_mpi_inv_mod(c, a, b); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) return CRYPT_ERROR; return CRYPT_OK; } /* setup */ static int montgomery_setup(void *a, void **b) { *b = mempool_alloc(mbedtls_mpi_mempool, sizeof(mbedtls_mpi_uint)); if (!*b) return CRYPT_MEM; mbedtls_mpi_montg_init(*b, a); return CRYPT_OK; } /* get normalization value */ static int montgomery_normalization(void *a, void *b) { size_t c = ROUNDUP(mbedtls_mpi_size(b), sizeof(mbedtls_mpi_uint)) * 8; if (mbedtls_mpi_lset(a, 1)) return CRYPT_MEM; if (mbedtls_mpi_shift_l(a, c)) return CRYPT_MEM; if (mbedtls_mpi_mod_mpi(a, a, b)) return CRYPT_MEM; return CRYPT_OK; } /* reduce */ static int montgomery_reduce(void *a, void *b, void *c) { mbedtls_mpi A; mbedtls_mpi *N = b; mbedtls_mpi_uint *mm = c; mbedtls_mpi T; int ret = CRYPT_MEM; mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A); if (mbedtls_mpi_grow(&T, (N->n + 1) * 2)) goto out; if (mbedtls_mpi_cmp_mpi(a, N) > 0) { if (mbedtls_mpi_mod_mpi(&A, a, N)) goto out; } else { if (mbedtls_mpi_copy(&A, a)) goto out; } if (mbedtls_mpi_grow(&A, N->n + 1)) goto out; mbedtls_mpi_montred(&A, N, *mm, &T); if (mbedtls_mpi_copy(a, &A)) goto out; ret = CRYPT_OK; out: mbedtls_mpi_free(&A); mbedtls_mpi_free(&T); return ret; } /* clean up */ static void montgomery_deinit(void *a) { mempool_free(mbedtls_mpi_mempool, a); } /* * This function calculates: * d = a^b mod c * * @a: base * @b: exponent * @c: modulus * @d: destination */ static int exptmod(void *a, void *b, void *c, void *d) { int res; if (d == a || d == b || d == c) { mbedtls_mpi dest; mbedtls_mpi_init_mempool(&dest); res = mbedtls_mpi_exp_mod(&dest, a, b, c, NULL); if (!res) res = mbedtls_mpi_copy(d, &dest); mbedtls_mpi_free(&dest); } else { res = mbedtls_mpi_exp_mod(d, a, b, c, NULL); } if (res) return CRYPT_MEM; else return CRYPT_OK; } static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen) { if (crypto_rng_read(buf, blen)) return MBEDTLS_ERR_MPI_FILE_IO_ERROR; return 0; } static int isprime(void *a, int b, int *c) { int res = mbedtls_mpi_is_prime_ext(a, b, rng_read, NULL); if (res == MBEDTLS_ERR_MPI_ALLOC_FAILED) return CRYPT_MEM; if (res) *c = LTC_MP_NO; else *c = LTC_MP_YES; return CRYPT_OK; } static int mpi_rand(void *a, int size) { if (mbedtls_mpi_fill_random(a, size, rng_read, NULL)) return CRYPT_MEM; return CRYPT_OK; } ltc_math_descriptor ltc_mp = { .name = "MPI", .bits_per_digit = sizeof(mbedtls_mpi_uint) * 8, .init = init, .init_size = init_size, .init_copy = init_copy, .deinit = deinit, .neg = neg, .copy = copy, .set_int = set_int, .get_int = get_int, .get_digit = get_digit, .get_digit_count = get_digit_count, .compare = compare, .compare_d = compare_d, .count_bits = count_bits, .count_lsb_bits = count_lsb_bits, .twoexpt = twoexpt, .read_radix = read_radix, .write_radix = write_radix, .unsigned_size = unsigned_size, .unsigned_write = unsigned_write, .unsigned_read = unsigned_read, .add = add, .addi = addi, .sub = sub, .subi = subi, .mul = mul, .muli = muli, .sqr = sqr, .mpdiv = divide, .div_2 = div_2, .modi = modi, .gcd = gcd, .lcm = lcm, .mulmod = mulmod, .sqrmod = sqrmod, .invmod = invmod, .montgomery_setup = montgomery_setup, .montgomery_normalization = montgomery_normalization, .montgomery_reduce = montgomery_reduce, .montgomery_deinit = montgomery_deinit, .exptmod = exptmod, .isprime = isprime, #ifdef LTC_MECC #ifdef LTC_MECC_FP .ecc_ptmul = ltc_ecc_fp_mulmod, #else .ecc_ptmul = ltc_ecc_mulmod, #endif /* LTC_MECC_FP */ .ecc_ptadd = ltc_ecc_projective_add_point, .ecc_ptdbl = ltc_ecc_projective_dbl_point, .ecc_map = ltc_ecc_map, #ifdef LTC_ECC_SHAMIR #ifdef LTC_MECC_FP .ecc_mul2add = ltc_ecc_fp_mul2add, #else .ecc_mul2add = ltc_ecc_mul2add, #endif /* LTC_MECC_FP */ #endif /* LTC_ECC_SHAMIR */ #endif /* LTC_MECC */ #ifdef LTC_MRSA .rsa_keygen = rsa_make_key, .rsa_me = rsa_exptmod, #endif .addmod = addmod, .submod = submod, .rand = mpi_rand, }; size_t crypto_bignum_num_bytes(struct bignum *a) { return mbedtls_mpi_size((mbedtls_mpi *)a); } size_t crypto_bignum_num_bits(struct bignum *a) { return mbedtls_mpi_bitlen((mbedtls_mpi *)a); } int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b) { return mbedtls_mpi_cmp_mpi((mbedtls_mpi *)a, (mbedtls_mpi *)b); } void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to) { const mbedtls_mpi *f = (const mbedtls_mpi *)from; int rc __maybe_unused = 0; rc = mbedtls_mpi_write_binary(f, (void *)to, mbedtls_mpi_size(f)); assert(!rc); } TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, struct bignum *to) { if (mbedtls_mpi_read_binary((mbedtls_mpi *)to, (const void *)from, fromsize)) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } void crypto_bignum_copy(struct bignum *to, const struct bignum *from) { int rc __maybe_unused = 0; rc = mbedtls_mpi_copy((mbedtls_mpi *)to, (const mbedtls_mpi *)from); assert(!rc); } struct bignum *crypto_bignum_allocate(size_t size_bits) { mbedtls_mpi *bn = malloc(sizeof(*bn)); if (!bn) return NULL; mbedtls_mpi_init(bn); if (mbedtls_mpi_grow(bn, BITS_TO_LIMBS(size_bits))) { free(bn); return NULL; } return (struct bignum *)bn; } void crypto_bignum_free(struct bignum **s) { assert(s); mbedtls_mpi_free((mbedtls_mpi *)*s); free(*s); *s = NULL; } void crypto_bignum_clear(struct bignum *s) { mbedtls_mpi *bn = (mbedtls_mpi *)s; bn->s = 1; if (bn->p) memset(bn->p, 0, sizeof(*bn->p) * bn->n); } optee_os-4.3.0/core/lib/libtomcrypt/rsa.c000066400000000000000000000436071464416617300203600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, 2022 Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include "acipher_helpers.h" /* * Compute the LibTomCrypt "hashindex" given a TEE Algorithm "algo" * Return * - TEE_SUCCESS in case of success, * - TEE_ERROR_BAD_PARAMETERS in case algo is not a valid algo * - TEE_ERROR_NOT_SUPPORTED in case algo is not supported by LTC * Return -1 in case of error */ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex) { switch (algo) { #if defined(_CFG_CORE_LTC_SHA1_DESC) case TEE_ALG_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: *ltc_hashindex = find_hash("sha1"); break; #endif #if defined(_CFG_CORE_LTC_MD5_DESC) case TEE_ALG_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: *ltc_hashindex = find_hash("md5"); break; #endif #if defined(_CFG_CORE_LTC_SHA224_DESC) case TEE_ALG_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: *ltc_hashindex = find_hash("sha224"); break; #endif #if defined(_CFG_CORE_LTC_SHA256_DESC) case TEE_ALG_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: *ltc_hashindex = find_hash("sha256"); break; #endif #if defined(_CFG_CORE_LTC_SHA384_DESC) case TEE_ALG_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: *ltc_hashindex = find_hash("sha384"); break; #endif #if defined(_CFG_CORE_LTC_SHA512_DESC) case TEE_ALG_SHA512: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: *ltc_hashindex = find_hash("sha512"); break; #endif case TEE_ALG_RSASSA_PKCS1_V1_5: case TEE_ALG_RSAES_PKCS1_V1_5: /* invalid one. but it should not be used anyway */ *ltc_hashindex = -1; return TEE_SUCCESS; default: return TEE_ERROR_BAD_PARAMETERS; } if (*ltc_hashindex < 0) return TEE_ERROR_NOT_SUPPORTED; else return TEE_SUCCESS; } TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, size_t key_size_bits __unused) __weak __alias("sw_crypto_acipher_alloc_rsa_keypair"); TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->e)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->d)) goto err; if (!bn_alloc_max(&s->n)) goto err; if (!bn_alloc_max(&s->p)) goto err; if (!bn_alloc_max(&s->q)) goto err; if (!bn_alloc_max(&s->qp)) goto err; if (!bn_alloc_max(&s->dp)) goto err; if (!bn_alloc_max(&s->dq)) goto err; return TEE_SUCCESS; err: crypto_acipher_free_rsa_keypair(s); return TEE_ERROR_OUT_OF_MEMORY; } TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, size_t key_size_bits __unused) __weak __alias("sw_crypto_acipher_alloc_rsa_public_key"); TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, size_t key_size_bits __unused) { memset(s, 0, sizeof(*s)); if (!bn_alloc_max(&s->e)) return TEE_ERROR_OUT_OF_MEMORY; if (!bn_alloc_max(&s->n)) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->e); return TEE_ERROR_OUT_OF_MEMORY; } void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) __weak __alias("sw_crypto_acipher_free_rsa_public_key"); void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) { if (!s) return; crypto_bignum_free(&s->n); crypto_bignum_free(&s->e); } void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) __weak __alias("sw_crypto_acipher_free_rsa_keypair"); void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) { if (!s) return; crypto_bignum_free(&s->e); crypto_bignum_free(&s->d); crypto_bignum_free(&s->n); crypto_bignum_free(&s->p); crypto_bignum_free(&s->q); crypto_bignum_free(&s->qp); crypto_bignum_free(&s->dp); crypto_bignum_free(&s->dq); } TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) __weak __alias("sw_crypto_acipher_gen_rsa_key"); TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) { TEE_Result res; rsa_key ltc_tmp_key; int ltc_res; /* Generate a temporary RSA key */ ltc_res = rsa_make_key_bn_e(NULL, find_prng("prng_crypto"), key_size / 8, key->e, <c_tmp_key); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; } else if ((size_t)mp_count_bits(ltc_tmp_key.N) != key_size) { rsa_free(<c_tmp_key); res = TEE_ERROR_BAD_PARAMETERS; } else { /* Copy the key */ ltc_mp.copy(ltc_tmp_key.d, key->d); ltc_mp.copy(ltc_tmp_key.N, key->n); ltc_mp.copy(ltc_tmp_key.p, key->p); ltc_mp.copy(ltc_tmp_key.q, key->q); ltc_mp.copy(ltc_tmp_key.qP, key->qp); ltc_mp.copy(ltc_tmp_key.dP, key->dp); ltc_mp.copy(ltc_tmp_key.dQ, key->dq); /* Free the temporary key */ rsa_free(<c_tmp_key); res = TEE_SUCCESS; } return res; } static TEE_Result rsadorep(rsa_key *ltc_key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; uint8_t *buf = NULL; unsigned long blen, offset; int ltc_res; /* * Use a temporary buffer since we don't know exactly how large the * required size of the out buffer without doing a partial decrypt. * We know the upper bound though. */ blen = _CFG_CORE_LTC_BIGNUM_MAX_BITS / sizeof(uint8_t); buf = mempool_alloc(mempool_default, blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = rsa_exptmod(src, src_len, buf, &blen, ltc_key->type, ltc_key); switch (ltc_res) { case CRYPT_PK_NOT_PRIVATE: case CRYPT_PK_INVALID_TYPE: case CRYPT_PK_INVALID_SIZE: case CRYPT_INVALID_PACKET: EMSG("rsa_exptmod() returned %d", ltc_res); res = TEE_ERROR_BAD_PARAMETERS; goto out; case CRYPT_OK: break; default: /* This will result in a panic */ EMSG("rsa_exptmod() returned %d", ltc_res); res = TEE_ERROR_GENERIC; goto out; } /* Remove the zero-padding (leave one zero if buff is all zeroes) */ offset = 0; while ((offset < blen - 1) && (buf[offset] == 0)) offset++; if (*dst_len < blen - offset) { *dst_len = blen - offset; res = TEE_ERROR_SHORT_BUFFER; goto out; } res = TEE_SUCCESS; *dst_len = blen - offset; memcpy(dst, (char *)buf + offset, *dst_len); out: mempool_free(mempool_default, buf); return res; } TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsanopad_encrypt"); TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res; rsa_key ltc_key = { 0, }; ltc_key.type = PK_PUBLIC; ltc_key.e = key->e; ltc_key.N = key->n; res = rsadorep(<c_key, src, src_len, dst, dst_len); return res; } TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsanopad_decrypt"); TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res; rsa_key ltc_key = { 0, }; ltc_key.type = PK_PRIVATE; ltc_key.e = key->e; ltc_key.N = key->n; ltc_key.d = key->d; if (key->p && crypto_bignum_num_bytes(key->p)) { ltc_key.p = key->p; ltc_key.q = key->q; ltc_key.qP = key->qp; ltc_key.dP = key->dp; ltc_key.dQ = key->dq; } res = rsadorep(<c_key, src, src_len, dst, dst_len); return res; } TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsaes_decrypt"); TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; void *buf = NULL; unsigned long blen; int ltc_hashindex, ltc_mgfindex, ltc_res, ltc_stat, ltc_rsa_algo; size_t mod_size; rsa_key ltc_key = { 0, }; ltc_key.type = PK_PRIVATE; ltc_key.e = key->e; ltc_key.d = key->d; ltc_key.N = key->n; if (key->p && crypto_bignum_num_bytes(key->p)) { ltc_key.p = key->p; ltc_key.q = key->q; ltc_key.qP = key->qp; ltc_key.dP = key->dp; ltc_key.dQ = key->dq; } /* Get the algorithm */ res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); if (res != TEE_SUCCESS) { EMSG("tee_algo_to_ltc_hashindex() returned %#"PRIx32, res); goto out; } if (algo != TEE_ALG_RSAES_PKCS1_V1_5) { res = tee_algo_to_ltc_hashindex(mgf_algo, <c_mgfindex); if (res != TEE_SUCCESS) { EMSG("tee_algo_to_ltc_hashindex() returned %#"PRIx32"for mgf algo %#"PRIx32, res, mgf_algo); goto out; } } else { ltc_mgfindex = -1; } /* * Use a temporary buffer since we don't know exactly how large * the required size of the out buffer without doing a partial * decrypt. We know the upper bound though. */ if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); blen = mod_size - 11; ltc_rsa_algo = LTC_PKCS_1_V1_5; } else { /* Decoded message is always shorter than encrypted message */ blen = src_len; ltc_rsa_algo = LTC_PKCS_1_OAEP; } buf = mempool_alloc(mempool_default, blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen, ((label_len == 0) ? 0 : label), label_len, ltc_mgfindex, ltc_hashindex, ltc_rsa_algo, <c_stat, <c_key); switch (ltc_res) { case CRYPT_PK_INVALID_PADDING: case CRYPT_INVALID_PACKET: case CRYPT_PK_INVALID_SIZE: EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); res = TEE_ERROR_BAD_PARAMETERS; goto out; case CRYPT_OK: break; default: /* This will result in a panic */ EMSG("rsa_decrypt_key_ex() returned %d", ltc_res); res = TEE_ERROR_GENERIC; goto out; } if (ltc_stat != 1) { /* This will result in a panic */ EMSG("rsa_decrypt_key_ex() returned %d and %d", ltc_res, ltc_stat); res = TEE_ERROR_GENERIC; goto out; } if (*dst_len < blen) { *dst_len = blen; res = TEE_ERROR_SHORT_BUFFER; goto out; } res = TEE_SUCCESS; *dst_len = blen; memcpy(dst, buf, blen); out: mempool_free(mempool_default, buf); return res; } TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsaes_encrypt"); TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label, size_t label_len, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res; uint32_t mod_size; int ltc_hashindex, ltc_mgfindex, ltc_res, ltc_rsa_algo; rsa_key ltc_key = { .type = PK_PUBLIC, .e = key->e, .N = key->n }; mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); if (*dst_len < mod_size) { *dst_len = mod_size; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = mod_size; /* Get the algorithm */ res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); if (res != TEE_SUCCESS) goto out; if (algo != TEE_ALG_RSAES_PKCS1_V1_5) { res = tee_algo_to_ltc_hashindex(mgf_algo, <c_mgfindex); if (res != TEE_SUCCESS) goto out; } else { ltc_mgfindex = -1; } if (algo == TEE_ALG_RSAES_PKCS1_V1_5) ltc_rsa_algo = LTC_PKCS_1_V1_5; else ltc_rsa_algo = LTC_PKCS_1_OAEP; ltc_res = rsa_encrypt_key_ex(src, src_len, dst, (unsigned long *)(dst_len), label, label_len, NULL, find_prng("prng_crypto"), ltc_mgfindex, ltc_hashindex, ltc_rsa_algo, <c_key); switch (ltc_res) { case CRYPT_PK_INVALID_PADDING: case CRYPT_INVALID_PACKET: case CRYPT_PK_INVALID_SIZE: EMSG("rsa_encrypt_key_ex() returned %d", ltc_res); res = TEE_ERROR_BAD_PARAMETERS; goto out; case CRYPT_OK: break; default: /* This will result in a panic */ res = TEE_ERROR_GENERIC; goto out; } res = TEE_SUCCESS; out: return res; } TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) __weak __alias("sw_crypto_acipher_rsassa_sign"); TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res; size_t hash_size, mod_size; int ltc_res, ltc_rsa_algo, ltc_hashindex; unsigned long ltc_sig_len; rsa_key ltc_key = { 0, }; ltc_key.type = PK_PRIVATE; ltc_key.e = key->e; ltc_key.N = key->n; ltc_key.d = key->d; if (key->p && crypto_bignum_num_bytes(key->p)) { ltc_key.p = key->p; ltc_key.q = key->q; ltc_key.qP = key->qp; ltc_key.dP = key->dp; ltc_key.dQ = key->dq; } switch (algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; break; case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: ltc_rsa_algo = LTC_PKCS_1_V1_5; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: ltc_rsa_algo = LTC_PKCS_1_PSS; break; default: res = TEE_ERROR_BAD_PARAMETERS; goto err; } if (ltc_rsa_algo != LTC_PKCS_1_V1_5_NA1) { ltc_res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &hash_size); if (res != TEE_SUCCESS) goto err; if (msg_len != hash_size) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } } mod_size = ltc_mp.unsigned_size((void *)(ltc_key.N)); if (*sig_len < mod_size) { *sig_len = mod_size; res = TEE_ERROR_SHORT_BUFFER; goto err; } ltc_sig_len = mod_size; ltc_res = rsa_sign_hash_ex(msg, msg_len, sig, <c_sig_len, ltc_rsa_algo, NULL, find_prng("prng_crypto"), ltc_hashindex, salt_len, <c_key); *sig_len = ltc_sig_len; if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } res = TEE_SUCCESS; err: return res; } TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) __weak __alias("sw_crypto_acipher_rsassa_verify"); TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res; uint32_t bigint_size; size_t hash_size; int stat, ltc_hashindex, ltc_res, ltc_rsa_algo; rsa_key ltc_key = { .type = PK_PUBLIC, .e = key->e, .N = key->n }; struct ftmn ftmn = { }; /* * The caller expects to call crypto_acipher_rsassa_verify(), * update the hash as needed. */ FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify")); if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &hash_size); if (res != TEE_SUCCESS) goto err; if (msg_len != hash_size) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } } bigint_size = ltc_mp.unsigned_size(ltc_key.N); if (sig_len < bigint_size) { res = TEE_ERROR_SIGNATURE_INVALID; goto err; } /* Get the algorithm */ if (algo != TEE_ALG_RSASSA_PKCS1_V1_5) { res = tee_algo_to_ltc_hashindex(algo, <c_hashindex); if (res != TEE_SUCCESS) goto err; } switch (algo) { case TEE_ALG_RSASSA_PKCS1_V1_5: ltc_rsa_algo = LTC_PKCS_1_V1_5_NA1; break; case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: ltc_rsa_algo = LTC_PKCS_1_V1_5; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: ltc_rsa_algo = LTC_PKCS_1_PSS; break; default: res = TEE_ERROR_BAD_PARAMETERS; goto err; } FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("rsa_verify_hash_ex")); ltc_res = rsa_verify_hash_ex(sig, sig_len, msg, msg_len, ltc_rsa_algo, ltc_hashindex, salt_len, &stat, <c_key); res = convert_ltc_verify_status(ltc_res, stat); if (res) FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res); else FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, 0); FTMN_POP_LINKED_CALL(&ftmn); FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res); return res; err: FTMN_CALLEE_DONE_NOT_ZERO(res); return res; } optee_os-4.3.0/core/lib/libtomcrypt/sha1_accel.c000066400000000000000000000130541464416617300215470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, 2020, Linaro Limited * Copyright (c) 2001-2007, Tom St Denis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include #include /** @file sha1.c LTC_SHA1 code by Tom St Denis */ const struct ltc_hash_descriptor sha1_desc = { "sha1", 2, 20, 64, /* OID */ { 1, 3, 14, 3, 2, 26, }, 6, &sha1_init, &sha1_process, &sha1_done, &sha1_test, NULL }; static int sha1_compress_nblocks(hash_state *md, const unsigned char *buf, int blocks) { void *state = md->sha1.state; COMPILE_TIME_ASSERT(sizeof(md->sha1.state[0]) == sizeof(uint32_t)); crypto_accel_sha1_compress(state, buf, blocks); return CRYPT_OK; } static int sha1_compress(hash_state *md, const unsigned char *buf) { return sha1_compress_nblocks(md, buf, 1); } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS_NBLOCKS(sha1_process, sha1_compress_nblocks, sha1, 64) /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha1_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha1.state[0] = 0x67452301UL; md->sha1.state[1] = 0xefcdab89UL; md->sha1.state[2] = 0x98badcfeUL; md->sha1.state[3] = 0x10325476UL; md->sha1.state[4] = 0xc3d2e1f0UL; md->sha1.curlen = 0; md->sha1.length = 0; return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (20 bytes) @return CRYPT_OK if successful */ int sha1_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha1.curlen >= sizeof(md->sha1.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->sha1.length += md->sha1.curlen * 8; /* append the '1' bit */ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha1.curlen > 56) { while (md->sha1.curlen < 64) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } sha1_compress(md, md->sha1.buf); md->sha1.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->sha1.curlen < 56) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha1.length, md->sha1.buf+56); sha1_compress(md, md->sha1.buf); /* copy output */ for (i = 0; i < 5; i++) { STORE32H(md->sha1.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha1_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[20]; } tests[] = { { "abc", { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 } } }; int i; unsigned char tmp[20]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha1_init(&md); sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); sha1_done(&md, tmp); if (XMEMCMP(tmp, tests[i].hash, 20) != 0) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } optee_os-4.3.0/core/lib/libtomcrypt/sha256_accel.c000066400000000000000000000140641464416617300217250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited * All rights reserved. * Copyright (c) 2001-2007, Tom St Denis * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include #include #ifdef LTC_SHA256 const struct ltc_hash_descriptor sha256_desc = { "sha256", 0, 32, 64, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, 9, &sha256_init, &sha256_process, &sha256_done, &sha256_test, NULL }; /* Implemented in assembly */ int sha256_ce_transform(ulong32 *state, const unsigned char *buf, int blocks); static int sha256_compress_nblocks(hash_state *md, const unsigned char *buf, int blocks) { void *state = md->sha256.state; COMPILE_TIME_ASSERT(sizeof(md->sha256.state[0]) == sizeof(uint32_t)); crypto_accel_sha256_compress(state, buf, blocks); return CRYPT_OK; } static int sha256_compress(hash_state *md, const unsigned char *buf) { return sha256_compress_nblocks(md, buf, 1); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha256_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha256.curlen = 0; md->sha256.length = 0; md->sha256.state[0] = 0x6A09E667UL; md->sha256.state[1] = 0xBB67AE85UL; md->sha256.state[2] = 0x3C6EF372UL; md->sha256.state[3] = 0xA54FF53AUL; md->sha256.state[4] = 0x510E527FUL; md->sha256.state[5] = 0x9B05688CUL; md->sha256.state[6] = 0x1F83D9ABUL; md->sha256.state[7] = 0x5BE0CD19UL; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS_NBLOCKS(sha256_process, sha256_compress_nblocks, sha256, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (32 bytes) @return CRYPT_OK if successful */ int sha256_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha256.curlen >= sizeof(md->sha256.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->sha256.length += md->sha256.curlen * 8; /* append the '1' bit */ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha256.curlen > 56) { while (md->sha256.curlen < 64) { md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; } sha256_compress(md, md->sha256.buf); md->sha256.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->sha256.curlen < 56) { md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha256.length, md->sha256.buf+56); sha256_compress(md, md->sha256.buf); /* copy output */ for (i = 0; i < 8; i++) { STORE32H(md->sha256.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[32]; } tests[] = { { "abc", { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }, }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha256_init(&md); sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); sha256_done(&md, tmp); if (XMEMCMP(tmp, tests[i].hash, 32) != 0) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif /*LTC_SHA256*/ optee_os-4.3.0/core/lib/libtomcrypt/sha3_accel.c000066400000000000000000000142551464416617300215550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* * Copyright (c) 2023, Linaro Limited */ /* based on https://github.com/brainhub/SHA3IUF (public domain) */ #include #include #include #ifdef LTC_SHA3 const struct ltc_hash_descriptor sha3_224_desc = { "sha3-224", /* name of hash */ 17, /* internal ID */ 28, /* Size of digest in octets */ 144, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_224_init, &sha3_process, &sha3_done, &sha3_224_test, NULL }; const struct ltc_hash_descriptor sha3_256_desc = { "sha3-256", /* name of hash */ 18, /* internal ID */ 32, /* Size of digest in octets */ 136, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_256_init, &sha3_process, &sha3_done, &sha3_256_test, NULL }; const struct ltc_hash_descriptor sha3_384_desc = { "sha3-384", /* name of hash */ 19, /* internal ID */ 48, /* Size of digest in octets */ 104, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_384_init, &sha3_process, &sha3_done, &sha3_384_test, NULL }; const struct ltc_hash_descriptor sha3_512_desc = { "sha3-512", /* name of hash */ 20, /* internal ID */ 64, /* Size of digest in octets */ 72, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_512_init, &sha3_process, &sha3_done, &sha3_512_test, NULL }; /* Public Inteface */ int sha3_224_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_256_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_384_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_512_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_shake_init(hash_state *md, int num) { LTC_ARGCHK(md != NULL); if (num != 128 && num != 256) return CRYPT_INVALID_ARG; XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64))); return CRYPT_OK; } int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen) { unsigned int digest_size = 0; unsigned int block_count = 0; unsigned int block_size = 0; void *state = NULL; unsigned int l = 0; if (!inlen) return CRYPT_OK; LTC_ARGCHK(md); LTC_ARGCHK(in); block_size = 200 - md->sha3.capacity_words * 8; digest_size = md->sha3.capacity_words * 8 / 2; state = md->sha3.s; if (md->sha3.byte_index) { l = MIN(block_size - md->sha3.byte_index, inlen); memcpy(md->sha3.sb + md->sha3.byte_index, in, l); in += l; inlen -= l; md->sha3.byte_index += l; if (md->sha3.byte_index == block_size) { crypto_accel_sha3_compress(state, md->sha3.sb, 1, digest_size); md->sha3.byte_index = 0; } if (!inlen) return CRYPT_OK; } if (inlen > block_size) { block_count = inlen / block_size; crypto_accel_sha3_compress(state, in, block_count, digest_size); in += block_count * block_size; inlen -= block_count * block_size; } memcpy(md->sha3.sb + md->sha3.byte_index, in, inlen); md->sha3.byte_index += inlen; return CRYPT_OK; } static void copy_out_digest(ulong64 *s, unsigned int digest_size, unsigned char *out) { unsigned int n = 0; for (n = 0; n < digest_size / sizeof(uint64_t); n++) { put_unaligned_le64(out, s[n]); out += sizeof(uint64_t); } if (digest_size % sizeof(uint64_t)) put_unaligned_le32(out, s[n]); } int sha3_done(hash_state *md, unsigned char *out) { unsigned int digest_size = 0; unsigned int block_size = 0; void *state = NULL; uint8_t *buf = NULL; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); block_size = 200 - md->sha3.capacity_words * 8; digest_size = md->sha3.capacity_words * 8 / 2; state = md->sha3.s; buf = md->sha3.sb; buf[md->sha3.byte_index++] = 0x06; memset(buf + md->sha3.byte_index, 0, block_size - md->sha3.byte_index); buf[block_size - 1] |= 0x80; crypto_accel_sha3_compress(state, buf, 1, digest_size); copy_out_digest(state, digest_size, out); return CRYPT_OK; } int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen) { unsigned int digest_size = 0; unsigned int block_size = 0; void *state = NULL; uint8_t *buf = NULL; unsigned int n = 0; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); block_size = 200 - md->sha3.capacity_words * 8; digest_size = md->sha3.capacity_words * 8 / 2; state = md->sha3.s; buf = md->sha3.sb; if (!md->sha3.xof_flag) { buf[md->sha3.byte_index++] = 0x1f; memset(buf + md->sha3.byte_index, 0, block_size - md->sha3.byte_index); buf[block_size - 1] |= 0x80; crypto_accel_sha3_compress(state, buf, 1, digest_size); md->sha3.byte_index = 0; copy_out_digest(state, block_size, buf); md->sha3.xof_flag = 1; } for (n = 0; n < outlen; n++) { if (md->sha3.byte_index >= block_size) { memset(buf, 0, block_size); crypto_accel_sha3_compress(state, buf, 1, digest_size); md->sha3.byte_index = 0; copy_out_digest(state, block_size, buf); } out[n] = buf[md->sha3.byte_index]; md->sha3.byte_index++; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/sha512_accel.c000066400000000000000000000121341464416617300217140ustar00rootroot00000000000000// SPDX-License-Identifier: Unlicense AND BSD-2-Clause /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* Copyright (c) 2023 Linaro Limited */ #include #include /** @param sha512.c LTC_SHA512 by Tom St Denis */ #ifdef LTC_SHA512 const struct ltc_hash_descriptor sha512_desc = { "sha512", 5, 64, 128, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, 9, &sha512_init, &sha512_process, &sha512_done, &sha512_test, NULL }; /* Implemented in assembly */ int sha512_ce_transform(ulong64 *state, const unsigned char *buf, int blocks); static int sha512_compress_nblocks(hash_state *md, const unsigned char *buf, int blocks) { void *state = md->sha512.state; COMPILE_TIME_ASSERT(sizeof(md->sha512.state[0]) == sizeof(uint64_t)); crypto_accel_sha512_compress(state, buf, blocks); return CRYPT_OK; } static int sha512_compress(hash_state *md, const unsigned char *buf) { return sha512_compress_nblocks(md, buf, 1); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha512_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha512.curlen = 0; md->sha512.length = 0; md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); md->sha512.state[4] = CONST64(0x510e527fade682d1); md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); md->sha512.state[7] = CONST64(0x5be0cd19137e2179); return CRYPT_OK; } HASH_PROCESS_NBLOCKS(sha512_process, sha512_compress_nblocks, sha512, 128) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (64 bytes) @return CRYPT_OK if successful */ int sha512_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha512.curlen >= sizeof(md->sha512.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->sha512.length += md->sha512.curlen * CONST64(8); /* append the '1' bit */ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; /* if the length is currently above 112 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha512.curlen > 112) { while (md->sha512.curlen < 128) { md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; } sha512_compress(md, md->sha512.buf); md->sha512.curlen = 0; } /* pad upto 120 bytes of zeroes * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash * > 2^64 bits of data... :-) */ while (md->sha512.curlen < 120) { md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha512.length, md->sha512.buf+120); sha512_compress(md, md->sha512.buf); /* copy output */ for (i = 0; i < 8; i++) { STORE64H(md->sha512.state[i], out+(8*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha512_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[64]; } tests[] = { { "abc", { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } }, }; int i; unsigned char tmp[64]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha512_init(&md); sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha512_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif /*LTC_SHA512*/ optee_os-4.3.0/core/lib/libtomcrypt/shake.c000066400000000000000000000053771464416617300206700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #include #include #include #include struct shake_ctx { struct crypto_hash_ctx ctx; struct sha3_state sha3; }; static struct shake_ctx *to_shake_ctx(struct crypto_hash_ctx *ctx) { return container_of(ctx, struct shake_ctx, ctx); } static TEE_Result do_shake_init(struct crypto_hash_ctx *ctx, unsigned int num) { struct shake_ctx *c = to_shake_ctx(ctx); if (sha3_shake_init((void *)&c->sha3, num) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result do_sha3_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { struct shake_ctx *c = to_shake_ctx(ctx); if (sha3_process((void *)&c->sha3, data, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result do_shake_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { struct shake_ctx *c = to_shake_ctx(ctx); if (sha3_shake_done((void *)&c->sha3, digest, len) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result do_shake_alloc_ctx(struct crypto_hash_ctx **ctx_ret, const struct crypto_hash_ops *ops) { struct shake_ctx *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; ctx->ctx.ops = ops; *ctx_ret = &ctx->ctx; return TEE_SUCCESS; } static void do_sha3_free_ctx(struct crypto_hash_ctx *ctx) { struct shake_ctx *c = to_shake_ctx(ctx); free(c); } static void do_sha3_copy_state(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx) { struct shake_ctx *dc = to_shake_ctx(dst_ctx); struct shake_ctx *sc = to_shake_ctx(src_ctx); assert(sc->ctx.ops == dc->ctx.ops); dc->sha3 = sc->sha3; } #if defined(_CFG_CORE_LTC_SHAKE128) static TEE_Result do_shake128_init(struct crypto_hash_ctx *ctx) { return do_shake_init(ctx, 128); } static const struct crypto_hash_ops shake128_ops = { .init = do_shake128_init, .update = do_sha3_update, .final = do_shake_final, .free_ctx = do_sha3_free_ctx, .copy_state = do_sha3_copy_state, }; TEE_Result crypto_shake128_alloc_ctx(struct crypto_hash_ctx **ctx) { return do_shake_alloc_ctx(ctx, &shake128_ops); } #endif #if defined(_CFG_CORE_LTC_SHAKE256) static TEE_Result do_shake256_init(struct crypto_hash_ctx *ctx) { return do_shake_init(ctx, 256); } static const struct crypto_hash_ops shake256_ops = { .init = do_shake256_init, .update = do_sha3_update, .final = do_shake_final, .free_ctx = do_sha3_free_ctx, .copy_state = do_sha3_copy_state, }; TEE_Result crypto_shake256_alloc_ctx(struct crypto_hash_ctx **ctx) { return do_shake_alloc_ctx(ctx, &shake256_ops); } #endif optee_os-4.3.0/core/lib/libtomcrypt/sm2-dsa.c000066400000000000000000000136551464416617300210410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include "acipher_helpers.h" /* SM2 uses 256 bit unsigned integers in big endian format */ #define SM2_INT_SIZE_BYTES 32 /* * GM/T 0003.1‒2012 Part1 2 Section 6.1 */ TEE_Result sm2_ltc_dsa_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res = TEE_SUCCESS; ecc_point *x1y1p = NULL; ecc_key ltc_key = { }; int ltc_res = 0; void *k = NULL; void *e = NULL; void *r = NULL; void *s = NULL; void *tmp = NULL; if (*sig_len < 2 * SM2_INT_SIZE_BYTES) { *sig_len = 64; return TEE_ERROR_SHORT_BUFFER; } ltc_res = mp_init_multi(&k, &e, &r, &s, &tmp, NULL); if (ltc_res != CRYPT_OK) return TEE_ERROR_OUT_OF_MEMORY; x1y1p = ltc_ecc_new_point(); if (!x1y1p) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = ecc_populate_ltc_private_key(<c_key, key, algo, NULL); if (res) goto out; /* * Steps A1 and A2 are the generation of the hash value e from user * information (ZA) and the message to be signed (M). There are not done * here since @msg is expected to be the hash value e already. */ /* Step A3: generate random number 1 <= k < n */ A3: ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, find_prng("prng_crypto")); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A4: compute (x1, y1) = [k]G */ ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, x1y1p, ltc_key.dp.A, ltc_key.dp.prime, 1); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A5: compute r = (e + x1) mod n */ mp_read_unsigned_bin(e, (unsigned char *)msg, msg_len); ltc_res = mp_addmod(e, x1y1p->x, ltc_key.dp.order, r); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_add(r, k, tmp); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } if (mp_cmp_d(r, 0) == LTC_MP_EQ || mp_cmp(tmp, ltc_key.dp.order) == LTC_MP_EQ) goto A3; /* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */ ltc_res = mp_add_d(ltc_key.k, 1, s); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_invmod(s, ltc_key.dp.order, s); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_mul(r, ltc_key.k, tmp); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_sub(k, tmp, tmp); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_mulmod(s, tmp, ltc_key.dp.order, s); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A7: convert (r, s) to binary for output */ *sig_len = 2 * SM2_INT_SIZE_BYTES; memset(sig, 0, *sig_len); mp_to_unsigned_bin2(r, sig, SM2_INT_SIZE_BYTES); mp_to_unsigned_bin2(s, sig + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); out: ecc_free(<c_key); ltc_ecc_del_point(x1y1p); mp_clear_multi(k, e, r, s, tmp, NULL); return res; } /* * GM/T 0003.1‒2012 Part1 2 Section 7.1 */ TEE_Result sm2_ltc_dsa_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res = TEE_SUCCESS; ecc_key ltc_key = { }; int ltc_res = 0; void *rprime = NULL; void *sprime = NULL; void *t = NULL; void *mp = NULL; void *mu = NULL; void *ma = NULL; void *eprime = NULL; void *R = NULL; ecc_point *x1y1p = NULL; if (sig_len != 64) return TEE_ERROR_BAD_PARAMETERS; ltc_res = mp_init_multi(&rprime, &sprime, &t, &mu, &ma, &eprime, &R, NULL); if (ltc_res != CRYPT_OK) return TEE_ERROR_OUT_OF_MEMORY; mp_read_unsigned_bin(rprime, (unsigned char *)sig, 32); mp_read_unsigned_bin(sprime, (unsigned char *)sig + 32, 32); res = ecc_populate_ltc_public_key(<c_key, key, algo, NULL); if (res) goto out; /* Step B1: verify r' in [1, n - 1] */ if (mp_cmp_d(rprime, 1) == LTC_MP_LT || mp_cmp(rprime, ltc_key.dp.order) != LTC_MP_LT) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } /* Step B2: verify s' in [1, n - 1] */ if (mp_cmp_d(sprime, 1) == LTC_MP_LT || mp_cmp(sprime, ltc_key.dp.order) != LTC_MP_LT) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } /* * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here * because @msg is supposed to contain the hash value e' already. */ /* Step B5: t = (r' + s') mod n and check t != 0 */ ltc_res = mp_addmod(rprime, sprime, ltc_key.dp.order, t); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } if (mp_cmp_d(t, 0) == LTC_MP_EQ) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } /* Step B6: (x1', y1') = [s']G + [t]PA */ x1y1p = ltc_ecc_new_point(); if (!x1y1p) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = mp_montgomery_setup(ltc_key.dp.prime, &mp); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_montgomery_normalization(mu, ltc_key.dp.prime); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = mp_mulmod(ltc_key.dp.A, mu, ltc_key.dp.prime, ma); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = ltc_ecc_mul2add(<c_key.dp.base, sprime, <c_key.pubkey, t, x1y1p, ma, ltc_key.dp.prime); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step B7: compute R = (e' + x1') mod n and verify R == r' */ mp_read_unsigned_bin(eprime, (unsigned char *)msg, msg_len); ltc_res = mp_addmod(eprime, x1y1p->x, ltc_key.dp.order, R); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } if (mp_cmp(R, rprime) != LTC_MP_EQ) res = TEE_ERROR_SIGNATURE_INVALID; out: mp_montgomery_free(mp); ltc_ecc_del_point(x1y1p); ecc_free(<c_key); mp_clear_multi(rprime, sprime, t, mu, ma, eprime, R, NULL); return res; } optee_os-4.3.0/core/lib/libtomcrypt/sm2-kep.c000066400000000000000000000251461464416617300210470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include "acipher_helpers.h" /* SM2 uses 256 bit unsigned integers in big endian format */ #define SM2_INT_SIZE_BYTES 32 /* * Compute a hash of a user's identity and public key * For user A: ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */ static TEE_Result sm2_kep_compute_Z(uint8_t *Z, size_t Zlen, const uint8_t *id, size_t idlen, const ecc_key *key) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t ENTLEN[2] = { }; uint8_t buf[SM2_INT_SIZE_BYTES]; void *ctx = NULL; if (Zlen < TEE_SM3_HASH_SIZE) return TEE_ERROR_SHORT_BUFFER; /* * ENTLEN is the length in bits if the user's distinguished identifier * encoded over 16 bits in big endian format. */ ENTLEN[0] = (idlen * 8) >> 8; ENTLEN[1] = idlen * 8; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, ENTLEN, sizeof(ENTLEN)); if (res) goto out; res = crypto_hash_update(ctx, id, idlen); if (res) goto out; mp_to_unsigned_bin2(key->dp.A, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mp_to_unsigned_bin2(key->dp.B, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mp_to_unsigned_bin2(key->dp.base.x, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mp_to_unsigned_bin2(key->dp.base.y, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mp_to_unsigned_bin2(key->pubkey.x, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mp_to_unsigned_bin2(key->pubkey.y, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; res = crypto_hash_final(ctx, Z, TEE_SM3_HASH_SIZE); out: crypto_hash_free_ctx(ctx); return res; } /* * Compute a verification value, to be checked against the value sent by the * peer. * On the initiator's side: * S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)) * On the responder's side: * S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)) */ static TEE_Result sm2_kep_compute_S(uint8_t *S, size_t S_len, uint8_t flag, ecc_point *UV, const uint8_t *ZAZB, size_t ZAZB_len, ecc_key *initiator_eph_key, ecc_key *responder_eph_key) { uint8_t hash[TEE_SM3_HASH_SIZE] = { }; TEE_Result res = TEE_ERROR_GENERIC; uint8_t buf[SM2_INT_SIZE_BYTES]; void *ctx = NULL; if (S_len < TEE_SM3_HASH_SIZE) return TEE_ERROR_SHORT_BUFFER; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; /* Compute the inner hash */ res = crypto_hash_init(ctx); if (res) goto out; /* xU or xV */ mp_to_unsigned_bin2(UV->x, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* ZA || ZB */ res = crypto_hash_update(ctx, ZAZB, ZAZB_len); if (res) goto out; /* x1 */ mp_to_unsigned_bin2(initiator_eph_key->pubkey.x, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* y1 */ mp_to_unsigned_bin2(initiator_eph_key->pubkey.y, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* x2 */ mp_to_unsigned_bin2(responder_eph_key->pubkey.x, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* y2 */ mp_to_unsigned_bin2(responder_eph_key->pubkey.y, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; res = crypto_hash_final(ctx, hash, sizeof(hash)); if (res) goto out; /* Now compute S */ res = crypto_hash_init(ctx); if (res) goto out; /* 0x02 or 0x03 */ res = crypto_hash_update(ctx, &flag, sizeof(flag)); if (res) goto out; /* yU or yV */ mp_to_unsigned_bin2(UV->y, buf, SM2_INT_SIZE_BYTES); res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* Inner SM3(...) */ res = crypto_hash_update(ctx, hash, sizeof(hash)); if (res) goto out; res = crypto_hash_final(ctx, S, TEE_SM3_HASH_SIZE); out: crypto_hash_free_ctx(ctx); return res; } /* * GM/T 0003.1‒2012 Part 3 Section 6.1 * Key exchange protocol */ static TEE_Result sm2_kep_derive(ecc_key *my_key, ecc_key *my_eph_key, ecc_key *peer_key, ecc_key *peer_eph_key, struct sm2_kep_parms *p) { /* * Variable names and documented steps reflect the initator side (user A * in the spec), but the other side is quite similar hence only one * function. */ uint8_t xUyUZAZB[2 * SM2_INT_SIZE_BYTES + 2 * TEE_SM3_HASH_SIZE] = { }; ecc_key *initiator_eph_key = p->is_initiator ? my_eph_key : peer_eph_key; ecc_key *responder_eph_key = p->is_initiator ? peer_eph_key : my_eph_key; ecc_key *initiator_key = p->is_initiator ? my_key : peer_key; ecc_key *responder_key = p->is_initiator ? peer_key : my_key; TEE_Result res = TEE_ERROR_BAD_STATE; uint8_t tmp[SM2_INT_SIZE_BYTES]; void *n = my_key->dp.order; ecc_point *U = NULL; void *x1bar = NULL; void *x2bar = NULL; void *tA = NULL; void *h = NULL; void *htA = NULL; void *mp = NULL; void *mu = NULL; void *ma = NULL; void *one = NULL; int ltc_res = 0; int inf = 0; ltc_res = mp_init_multi(&x1bar, &x2bar, &tA, &h, &htA, &mu, &ma, &one, NULL); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } U = ltc_ecc_new_point(); if (!U) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* * Steps A1-A3 are supposedly done already (generate ephemeral key, send * it to peer). * Step A4: (x1, y1) = RA; x1bar = 2^w + (x1 & (2^w - 1)) */ mp_to_unsigned_bin2(my_eph_key->pubkey.x, tmp, SM2_INT_SIZE_BYTES); tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; mp_read_unsigned_bin(x1bar, tmp + SM2_INT_SIZE_BYTES / 2, SM2_INT_SIZE_BYTES / 2); /* Step A5: tA = (dA + x1bar * rA) mod n */ ltc_res = mp_mulmod(x1bar, my_eph_key->k, n, tA); if (ltc_res != CRYPT_OK) goto out; ltc_res = mp_addmod(tA, my_key->k, n, tA); if (ltc_res != CRYPT_OK) goto out; /* Step A6: verify whether RB verifies the curve equation */ ltc_res = ltc_ecc_is_point(&peer_eph_key->dp, peer_eph_key->pubkey.x, peer_eph_key->pubkey.y); if (ltc_res != CRYPT_OK) goto out; /* Step A6 (continued): (x2, y2) = RB; x2bar = 2^w + (x2 & (2^w - 1)) */ mp_to_unsigned_bin2(peer_eph_key->pubkey.x, tmp, SM2_INT_SIZE_BYTES); tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; mp_read_unsigned_bin(x2bar, tmp + SM2_INT_SIZE_BYTES / 2, SM2_INT_SIZE_BYTES / 2); /* Step A7: compute U = [h.tA](PB + [x2bar]RB) and check for infinity */ ltc_res = mp_montgomery_setup(peer_key->dp.prime, &mp); if (ltc_res != CRYPT_OK) goto out; ltc_res = mp_montgomery_normalization(mu, peer_key->dp.prime); if (ltc_res != CRYPT_OK) goto out; ltc_res = mp_mulmod(peer_key->dp.A, mu, peer_key->dp.prime, ma); if (ltc_res != CRYPT_OK) goto out; ltc_res = mp_set_int(one, 1); if (ltc_res != CRYPT_OK) goto out; ltc_res = ltc_ecc_mul2add(&peer_key->pubkey, one, &peer_eph_key->pubkey, x2bar, U, ma, peer_key->dp.prime); if (ltc_res != CRYPT_OK) goto out; ltc_res = mp_set_int(h, peer_key->dp.cofactor); if (ltc_res != CRYPT_OK) goto out; ltc_res = mp_mul(h, tA, htA); if (ltc_res != CRYPT_OK) goto out; ltc_res = ltc_ecc_mulmod(htA, U, U, peer_key->dp.A, peer_key->dp.prime, 1); if (ltc_res != CRYPT_OK) goto out; ltc_res = ltc_ecc_is_point_at_infinity(U, peer_key->dp.prime, &inf); if (ltc_res != CRYPT_OK) goto out; if (inf) goto out; /* Step A8: compute KA = KDF(xU || yU || ZA || ZB, klen) */ /* xU */ mp_to_unsigned_bin2(U->x, xUyUZAZB, SM2_INT_SIZE_BYTES); /* yU */ mp_to_unsigned_bin2(U->y, xUyUZAZB + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); /* ZA */ res = sm2_kep_compute_Z(xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, TEE_SM3_HASH_SIZE, p->initiator_id, p->initiator_id_len, initiator_key); if (res) goto out; /* ZB */ res = sm2_kep_compute_Z(xUyUZAZB + 2 * SM2_INT_SIZE_BYTES + TEE_SM3_HASH_SIZE, TEE_SM3_HASH_SIZE, p->responder_id, p->responder_id_len, responder_key); if (res) goto out; res = sm2_kdf(xUyUZAZB, sizeof(xUyUZAZB), p->out, p->out_len); if (res) goto out; /* Step A9: compute S1 and check S1 == SB */ if (p->conf_in) { uint8_t S1[TEE_SM3_HASH_SIZE]; uint8_t flag = p->is_initiator ? 0x02 : 0x03; if (p->conf_in_len < TEE_SM3_HASH_SIZE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = sm2_kep_compute_S(S1, sizeof(S1), flag, U, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, 2 * SM2_INT_SIZE_BYTES, initiator_eph_key, responder_eph_key); if (res) goto out; if (consttime_memcmp(S1, p->conf_in, sizeof(S1))) { /* Verification failed */ res = TEE_ERROR_BAD_STATE; goto out; } } /* Step A10: compute SA */ if (p->conf_out) { uint8_t flag = p->is_initiator ? 0x03 : 0x02; if (p->conf_out_len < TEE_SM3_HASH_SIZE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = sm2_kep_compute_S(p->conf_out, TEE_SM3_HASH_SIZE, flag, U, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, 2 * SM2_INT_SIZE_BYTES, initiator_eph_key, responder_eph_key); if (res) goto out; } out: mp_montgomery_free(mp); ltc_ecc_del_point(U); mp_clear_multi(x1bar, x2bar, tA, h, htA, mu, ma, one, NULL); return res; } TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key, struct ecc_keypair *my_eph_key, struct ecc_public_key *peer_key, struct ecc_public_key *peer_eph_key, struct sm2_kep_parms *p) { TEE_Result res = TEE_SUCCESS; ecc_key ltc_my_key = { }; ecc_key ltc_my_eph_key = { }; ecc_key ltc_peer_key = { }; ecc_key ltc_peer_eph_key = { }; res = ecc_populate_ltc_private_key(<c_my_key, my_key, TEE_ALG_SM2_KEP, NULL); if (res) goto out; res = ecc_populate_ltc_private_key(<c_my_eph_key, my_eph_key, TEE_ALG_SM2_KEP, NULL); if (res) goto out; res = ecc_populate_ltc_public_key(<c_peer_key, peer_key, TEE_ALG_SM2_KEP, NULL); if (res) goto out; res = ecc_populate_ltc_public_key(<c_peer_eph_key, peer_eph_key, TEE_ALG_SM2_KEP, NULL); if (res) goto out; res = sm2_kep_derive(<c_my_key, <c_my_eph_key, <c_peer_key, <c_peer_eph_key, p); out: ecc_free(<c_peer_eph_key); ecc_free(<c_peer_key); ecc_free(<c_my_eph_key); ecc_free(<c_my_key); return res; } optee_os-4.3.0/core/lib/libtomcrypt/sm2-pke.c000066400000000000000000000264551464416617300210530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include #include "acipher_helpers.h" /* SM2 uses 256 bit unsigned integers in big endian format */ #define SM2_INT_SIZE_BYTES 32 static TEE_Result sm2_uncompressed_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp, const uint8_t *x1y1, size_t max_size, size_t *consumed) { uint8_t *ptr = (uint8_t *)x1y1; uint8_t one[] = { 1 }; int ltc_res = 0; if (max_size < (size_t)(2 * SM2_INT_SIZE_BYTES)) return TEE_ERROR_BAD_PARAMETERS; ltc_res = mp_read_unsigned_bin(p->x, ptr, SM2_INT_SIZE_BYTES); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; ptr += SM2_INT_SIZE_BYTES; ltc_res = mp_read_unsigned_bin(p->y, ptr, SM2_INT_SIZE_BYTES); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; ltc_res = ltc_ecc_is_point(dp, p->x, p->y); if (ltc_res != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; mp_read_unsigned_bin(p->z, one, sizeof(one)); *consumed = 2 * SM2_INT_SIZE_BYTES + 1; /* PC */ return TEE_SUCCESS; } /* * GM/T 0003.1‒2012 Part 1 Section 4.2.9 * Conversion of a byte string @buf to a point @p. Makes sure @p is on the curve * defined by domain parameters @dp. * Note: only the uncompressed form is supported. Uncompressed and hybrid forms * are TBD. */ static TEE_Result sm2_bytes_to_point(ecc_point *p, const ltc_ecc_dp *dp, const uint8_t *buf, size_t max_size, size_t *consumed) { uint8_t PC = 0; if (!max_size) return TEE_ERROR_BAD_PARAMETERS; PC = buf[0]; switch (PC) { case 0x02: case 0x03: /* Compressed form */ return TEE_ERROR_NOT_SUPPORTED; case 0x04: /* UNcompressed form */ return sm2_uncompressed_bytes_to_point(p, dp, buf + 1, max_size - 1, consumed); case 0x06: case 0x07: /* Hybrid form */ return TEE_ERROR_NOT_SUPPORTED; default: return TEE_ERROR_BAD_PARAMETERS; } return TEE_ERROR_GENERIC; } static bool is_zero(const uint8_t *buf, size_t size) { uint8_t v = 0; size_t i = 0; for (i = 0; i < size; i++) v |= buf[i]; return !v; } /* * GM/T 0003.1‒2012 Part 4 Section 7.1 * Decryption algorithm */ TEE_Result sm2_ltc_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; uint8_t x2y2[64] = { }; ecc_key ltc_key = { }; ecc_point *C1 = NULL; size_t C1_len = 0; ecc_point *S = NULL; ecc_point *x2y2p = NULL; void *ctx = NULL; int ltc_res = 0; void *h = NULL; int inf = 0; uint8_t *t = NULL; size_t C2_len = 0; size_t i = 0; size_t out_len = 0; uint8_t *eom = NULL; uint8_t u[TEE_SM3_HASH_SIZE] = { }; /* * Input buffer src is (C1 || C2 || C3) * - C1 represents a point (should be on the curve) * - C2 is the encrypted message * - C3 is a SM3 hash */ res = ecc_populate_ltc_private_key(<c_key, key, TEE_ALG_SM2_PKE, NULL); if (res) goto out; /* Step B1: read and validate point C1 from encrypted message */ C1 = ltc_ecc_new_point(); if (!C1) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = sm2_bytes_to_point(C1, <c_key.dp, src, src_len, &C1_len); if (res) goto out; /* Step B2: S = [h]C1 */ if (ltc_key.dp.cofactor != 1) { S = ltc_ecc_new_point(); if (!S) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = mp_init_multi(&h, NULL); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = mp_set_int(h, ltc_key.dp.cofactor); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = ltc_ecc_mulmod(h, C1, S, ltc_key.dp.A, ltc_key.dp.prime, 1); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, &inf); } else { ltc_res = ltc_ecc_is_point_at_infinity(C1, ltc_key.dp.prime, &inf); } if (ltc_res != CRYPT_OK || inf) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step B3: (x2, y2) = [dB]C1 */ x2y2p = ltc_ecc_new_point(); if (!x2y2p) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = ltc_ecc_mulmod(ltc_key.k, C1, x2y2p, ltc_key.dp.A, ltc_key.dp.prime, 1); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { res = TEE_ERROR_BAD_STATE; goto out; } mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); /* Step B4: t = KDF(x2 || y2, klen) */ /* C = C1 || C2 || C3 */ if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; t = calloc(1, C2_len); if (!t) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); if (res) goto out; if (is_zero(t, C2_len)) { res = TEE_ERROR_CIPHERTEXT_INVALID; goto out; } /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ out_len = MIN(*dst_len, C2_len); for (i = 0; i < out_len; i++) dst[i] = src[C1_len + i] ^ t[i]; *dst_len = out_len; if (out_len < C2_len) { eom = calloc(1, C2_len - out_len); if (!eom) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } for (i = out_len; i < C2_len; i++) eom[i - out_len] = src[C1_len + i] ^ t[i]; } /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_update(ctx, dst, out_len); if (res) goto out; if (out_len < C2_len) { res = crypto_hash_update(ctx, eom, C2_len - out_len); if (res) goto out; } res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_final(ctx, u, sizeof(u)); if (res) goto out; if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { res = TEE_ERROR_CIPHERTEXT_INVALID; goto out; } out: free(eom); free(t); crypto_hash_free_ctx(ctx); ltc_ecc_del_point(x2y2p); ltc_ecc_del_point(S); ltc_ecc_del_point(C1); mp_clear_multi(h, NULL); ecc_free(<c_key); return res; } /* * GM/T 0003.1‒2012 Part 1 Section 4.2.8 * Conversion of point @p to a byte string @buf (uncompressed form). */ static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, const ecc_point *p) { size_t xsize = mp_unsigned_bin_size(p->x); size_t ysize = mp_unsigned_bin_size(p->y); size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || *size < sz) return TEE_ERROR_BAD_STATE; memset(buf, 0, sz); buf[0] = 0x04; /* Uncompressed form indicator */ mp_to_unsigned_bin2(p->x, buf + 1, SM2_INT_SIZE_BYTES); mp_to_unsigned_bin2(p->y, buf + 1 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); *size = sz; return TEE_SUCCESS; } /* * GM/T 0003.1‒2012 Part 4 Section 6.1 * Encryption algorithm */ TEE_Result sm2_ltc_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; ecc_key ltc_key = { }; ecc_point *x2y2p = NULL; ecc_point *C1 = NULL; ecc_point *S = NULL; uint8_t x2y2[64] = { }; uint8_t *t = NULL; int ltc_res = 0; void *k = NULL; void *h = NULL; int inf = 0; size_t C1_len = 0; void *ctx = NULL; size_t i = 0; ltc_res = mp_init_multi(&k, &h, NULL); if (ltc_res != CRYPT_OK) return TEE_ERROR_OUT_OF_MEMORY; res = ecc_populate_ltc_public_key(<c_key, key, TEE_ALG_SM2_PKE, NULL); if (res) goto out; /* Step A1: generate random number 1 <= k < n */ ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL, find_prng("prng_crypto")); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A2: compute C1 = [k]G */ C1 = ltc_ecc_new_point(); if (!C1) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = ltc_ecc_mulmod(k, <c_key.dp.base, C1, ltc_key.dp.A, ltc_key.dp.prime, 1); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A3: compute S = [h]PB and check for infinity */ if (ltc_key.dp.cofactor != 1) { S = ltc_ecc_new_point(); if (!S) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = mp_set_int(h, ltc_key.dp.cofactor); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = ltc_ecc_mulmod(h, <c_key.pubkey, S, ltc_key.dp.A, ltc_key.dp.prime, 1); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } ltc_res = ltc_ecc_is_point_at_infinity(S, ltc_key.dp.prime, &inf); } else { ltc_res = ltc_ecc_is_point_at_infinity(<c_key.pubkey, ltc_key.dp.prime, &inf); } if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } if (inf) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A4: compute (x2, y2) = [k]PB */ x2y2p = ltc_ecc_new_point(); if (!x2y2p) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } ltc_res = ltc_ecc_mulmod(k, <c_key.pubkey, x2y2p, ltc_key.dp.A, ltc_key.dp.prime, 1); if (ltc_res != CRYPT_OK) { res = TEE_ERROR_BAD_STATE; goto out; } if (mp_unsigned_bin_size(x2y2p->x) > SM2_INT_SIZE_BYTES || mp_unsigned_bin_size(x2y2p->y) > SM2_INT_SIZE_BYTES) { res = TEE_ERROR_BAD_STATE; goto out; } mp_to_unsigned_bin2(x2y2p->x, x2y2, SM2_INT_SIZE_BYTES); mp_to_unsigned_bin2(x2y2p->y, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); /* Step A5: compute t = KDF(x2 || y2, klen) */ t = calloc(1, src_len); if (!t) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); if (res) goto out; if (is_zero(t, src_len)) { res = TEE_ERROR_CIPHERTEXT_INVALID; goto out; } /* * Steps A6, A7, A8: * Compute C2 = M (+) t * Compute C3 = Hash(x2 || M || y2) * Output C = C1 || C2 || C3 */ /* C1 */ C1_len = *dst_len; res = sm2_point_to_bytes(dst, &C1_len, C1); if (res) goto out; if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; res = TEE_ERROR_SHORT_BUFFER; goto out; } /* C2 */ for (i = 0; i < src_len; i++) dst[i + C1_len] = src[i] ^ t[i]; /* C3 */ res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_update(ctx, src, src_len); if (res) goto out; res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); if (res) goto out; *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; out: crypto_hash_free_ctx(ctx); free(t); ltc_ecc_del_point(x2y2p); ltc_ecc_del_point(S); ltc_ecc_del_point(C1); ecc_free(<c_key); mp_clear_multi(k, h, NULL); return res; } optee_os-4.3.0/core/lib/libtomcrypt/src/000077500000000000000000000000001464416617300202045ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/000077500000000000000000000000001464416617300216415ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/aes/000077500000000000000000000000001464416617300224115ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/aes/aes.c000066400000000000000000000453061464416617300233350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* AES implementation by Tom St Denis * * Derived from the Public Domain source code by --- * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto --- */ /** @file aes.c Implementation of AES */ #include "tomcrypt_private.h" #ifdef LTC_RIJNDAEL #ifndef ENCRYPT_ONLY #define SETUP rijndael_setup #define ECB_ENC rijndael_ecb_encrypt #define ECB_DEC rijndael_ecb_decrypt #define ECB_DONE rijndael_done #define ECB_TEST rijndael_test #define ECB_KS rijndael_keysize const struct ltc_cipher_descriptor rijndael_desc = { "rijndael", 6, 16, 32, 16, 10, SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #else #define SETUP rijndael_enc_setup #define ECB_ENC rijndael_enc_ecb_encrypt #define ECB_KS rijndael_enc_keysize #define ECB_DONE rijndael_enc_done const struct ltc_cipher_descriptor rijndael_enc_desc = { "rijndael", 6, 16, 32, 16, 10, SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #endif #define LTC_AES_TAB_C #include "aes_tab.c" static ulong32 setup_mix(ulong32 temp) { return (Te4_3[LTC_BYTE(temp, 2)]) ^ (Te4_2[LTC_BYTE(temp, 1)]) ^ (Te4_1[LTC_BYTE(temp, 0)]) ^ (Te4_0[LTC_BYTE(temp, 3)]); } #ifndef ENCRYPT_ONLY #ifdef LTC_SMALL_CODE static ulong32 setup_mix2(ulong32 temp) { return Td0(255 & Te4[LTC_BYTE(temp, 3)]) ^ Td1(255 & Te4[LTC_BYTE(temp, 2)]) ^ Td2(255 & Te4[LTC_BYTE(temp, 1)]) ^ Td3(255 & Te4[LTC_BYTE(temp, 0)]); } #endif #endif /** Initialize the AES (Rijndael) block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int i; ulong32 temp, *rk, *K; #ifndef ENCRYPT_ONLY ulong32 *rrk; #endif LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 16 && keylen != 24 && keylen != 32) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) { return CRYPT_INVALID_ROUNDS; } skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; K = LTC_ALIGN_BUF(skey->rijndael.K, 16); skey->rijndael.eK = K; K += 60; skey->rijndael.dK = K; /* setup the forward key */ i = 0; rk = skey->rijndael.eK; LOAD32H(rk[0], key ); LOAD32H(rk[1], key + 4); LOAD32H(rk[2], key + 8); LOAD32H(rk[3], key + 12); if (keylen == 16) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { break; } rk += 4; } } else if (keylen == 24) { LOAD32H(rk[4], key + 16); LOAD32H(rk[5], key + 20); for (;;) { #ifdef _MSC_VER temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; #else temp = rk[5]; #endif rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { break; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } else if (keylen == 32) { LOAD32H(rk[4], key + 16); LOAD32H(rk[5], key + 20); LOAD32H(rk[6], key + 24); LOAD32H(rk[7], key + 28); for (;;) { #ifdef _MSC_VER temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; #else temp = rk[7]; #endif rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { break; } temp = rk[11]; rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8)); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } else { /* this can't happen */ /* coverity[dead_error_line] */ return CRYPT_ERROR; } #ifndef ENCRYPT_ONLY /* setup the inverse key now */ rk = skey->rijndael.dK; rrk = skey->rijndael.eK + (28 + keylen) - 4; /* apply the inverse MixColumn transform to all round keys but the first and the last: */ /* copy first */ *rk++ = *rrk++; *rk++ = *rrk++; *rk++ = *rrk++; *rk = *rrk; rk -= 3; rrk -= 3; for (i = 1; i < skey->rijndael.Nr; i++) { rrk -= 4; rk += 4; #ifdef LTC_SMALL_CODE temp = rrk[0]; rk[0] = setup_mix2(temp); temp = rrk[1]; rk[1] = setup_mix2(temp); temp = rrk[2]; rk[2] = setup_mix2(temp); temp = rrk[3]; rk[3] = setup_mix2(temp); #else temp = rrk[0]; rk[0] = Tks0[LTC_BYTE(temp, 3)] ^ Tks1[LTC_BYTE(temp, 2)] ^ Tks2[LTC_BYTE(temp, 1)] ^ Tks3[LTC_BYTE(temp, 0)]; temp = rrk[1]; rk[1] = Tks0[LTC_BYTE(temp, 3)] ^ Tks1[LTC_BYTE(temp, 2)] ^ Tks2[LTC_BYTE(temp, 1)] ^ Tks3[LTC_BYTE(temp, 0)]; temp = rrk[2]; rk[2] = Tks0[LTC_BYTE(temp, 3)] ^ Tks1[LTC_BYTE(temp, 2)] ^ Tks2[LTC_BYTE(temp, 1)] ^ Tks3[LTC_BYTE(temp, 0)]; temp = rrk[3]; rk[3] = Tks0[LTC_BYTE(temp, 3)] ^ Tks1[LTC_BYTE(temp, 2)] ^ Tks2[LTC_BYTE(temp, 1)] ^ Tks3[LTC_BYTE(temp, 0)]; #endif } /* copy last */ rrk -= 4; rk += 4; *rk++ = *rrk++; *rk++ = *rrk++; *rk++ = *rrk++; *rk = *rrk; #endif /* ENCRYPT_ONLY */ return CRYPT_OK; } /** Encrypts a block of text with AES @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 s0, s1, s2, s3, t0, t1, t2, t3; const ulong32 *rk; int Nr, r; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); Nr = skey->rijndael.Nr; if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; rk = skey->rijndael.eK; /* * map byte array block to cipher state * and add initial round key: */ LOAD32H(s0, pt ); s0 ^= rk[0]; LOAD32H(s1, pt + 4); s1 ^= rk[1]; LOAD32H(s2, pt + 8); s2 ^= rk[2]; LOAD32H(s3, pt + 12); s3 ^= rk[3]; #ifdef LTC_SMALL_CODE for (r = 0; ; r++) { rk += 4; t0 = Te0(LTC_BYTE(s0, 3)) ^ Te1(LTC_BYTE(s1, 2)) ^ Te2(LTC_BYTE(s2, 1)) ^ Te3(LTC_BYTE(s3, 0)) ^ rk[0]; t1 = Te0(LTC_BYTE(s1, 3)) ^ Te1(LTC_BYTE(s2, 2)) ^ Te2(LTC_BYTE(s3, 1)) ^ Te3(LTC_BYTE(s0, 0)) ^ rk[1]; t2 = Te0(LTC_BYTE(s2, 3)) ^ Te1(LTC_BYTE(s3, 2)) ^ Te2(LTC_BYTE(s0, 1)) ^ Te3(LTC_BYTE(s1, 0)) ^ rk[2]; t3 = Te0(LTC_BYTE(s3, 3)) ^ Te1(LTC_BYTE(s0, 2)) ^ Te2(LTC_BYTE(s1, 1)) ^ Te3(LTC_BYTE(s2, 0)) ^ rk[3]; if (r == Nr-2) { break; } s0 = t0; s1 = t1; s2 = t2; s3 = t3; } rk += 4; #else /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0(LTC_BYTE(s0, 3)) ^ Te1(LTC_BYTE(s1, 2)) ^ Te2(LTC_BYTE(s2, 1)) ^ Te3(LTC_BYTE(s3, 0)) ^ rk[4]; t1 = Te0(LTC_BYTE(s1, 3)) ^ Te1(LTC_BYTE(s2, 2)) ^ Te2(LTC_BYTE(s3, 1)) ^ Te3(LTC_BYTE(s0, 0)) ^ rk[5]; t2 = Te0(LTC_BYTE(s2, 3)) ^ Te1(LTC_BYTE(s3, 2)) ^ Te2(LTC_BYTE(s0, 1)) ^ Te3(LTC_BYTE(s1, 0)) ^ rk[6]; t3 = Te0(LTC_BYTE(s3, 3)) ^ Te1(LTC_BYTE(s0, 2)) ^ Te2(LTC_BYTE(s1, 1)) ^ Te3(LTC_BYTE(s2, 0)) ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0(LTC_BYTE(t0, 3)) ^ Te1(LTC_BYTE(t1, 2)) ^ Te2(LTC_BYTE(t2, 1)) ^ Te3(LTC_BYTE(t3, 0)) ^ rk[0]; s1 = Te0(LTC_BYTE(t1, 3)) ^ Te1(LTC_BYTE(t2, 2)) ^ Te2(LTC_BYTE(t3, 1)) ^ Te3(LTC_BYTE(t0, 0)) ^ rk[1]; s2 = Te0(LTC_BYTE(t2, 3)) ^ Te1(LTC_BYTE(t3, 2)) ^ Te2(LTC_BYTE(t0, 1)) ^ Te3(LTC_BYTE(t1, 0)) ^ rk[2]; s3 = Te0(LTC_BYTE(t3, 3)) ^ Te1(LTC_BYTE(t0, 2)) ^ Te2(LTC_BYTE(t1, 1)) ^ Te3(LTC_BYTE(t2, 0)) ^ rk[3]; } #endif /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4_3[LTC_BYTE(t0, 3)]) ^ (Te4_2[LTC_BYTE(t1, 2)]) ^ (Te4_1[LTC_BYTE(t2, 1)]) ^ (Te4_0[LTC_BYTE(t3, 0)]) ^ rk[0]; STORE32H(s0, ct); s1 = (Te4_3[LTC_BYTE(t1, 3)]) ^ (Te4_2[LTC_BYTE(t2, 2)]) ^ (Te4_1[LTC_BYTE(t3, 1)]) ^ (Te4_0[LTC_BYTE(t0, 0)]) ^ rk[1]; STORE32H(s1, ct+4); s2 = (Te4_3[LTC_BYTE(t2, 3)]) ^ (Te4_2[LTC_BYTE(t3, 2)]) ^ (Te4_1[LTC_BYTE(t0, 1)]) ^ (Te4_0[LTC_BYTE(t1, 0)]) ^ rk[2]; STORE32H(s2, ct+8); s3 = (Te4_3[LTC_BYTE(t3, 3)]) ^ (Te4_2[LTC_BYTE(t0, 2)]) ^ (Te4_1[LTC_BYTE(t1, 1)]) ^ (Te4_0[LTC_BYTE(t2, 0)]) ^ rk[3]; STORE32H(s3, ct+12); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_rijndael_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); return err; } #endif #ifndef ENCRYPT_ONLY /** Decrypts a block of text with AES @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 s0, s1, s2, s3, t0, t1, t2, t3; const ulong32 *rk; int Nr, r; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); Nr = skey->rijndael.Nr; if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; rk = skey->rijndael.dK; /* * map byte array block to cipher state * and add initial round key: */ LOAD32H(s0, ct ); s0 ^= rk[0]; LOAD32H(s1, ct + 4); s1 ^= rk[1]; LOAD32H(s2, ct + 8); s2 ^= rk[2]; LOAD32H(s3, ct + 12); s3 ^= rk[3]; #ifdef LTC_SMALL_CODE for (r = 0; ; r++) { rk += 4; t0 = Td0(LTC_BYTE(s0, 3)) ^ Td1(LTC_BYTE(s3, 2)) ^ Td2(LTC_BYTE(s2, 1)) ^ Td3(LTC_BYTE(s1, 0)) ^ rk[0]; t1 = Td0(LTC_BYTE(s1, 3)) ^ Td1(LTC_BYTE(s0, 2)) ^ Td2(LTC_BYTE(s3, 1)) ^ Td3(LTC_BYTE(s2, 0)) ^ rk[1]; t2 = Td0(LTC_BYTE(s2, 3)) ^ Td1(LTC_BYTE(s1, 2)) ^ Td2(LTC_BYTE(s0, 1)) ^ Td3(LTC_BYTE(s3, 0)) ^ rk[2]; t3 = Td0(LTC_BYTE(s3, 3)) ^ Td1(LTC_BYTE(s2, 2)) ^ Td2(LTC_BYTE(s1, 1)) ^ Td3(LTC_BYTE(s0, 0)) ^ rk[3]; if (r == Nr-2) { break; } s0 = t0; s1 = t1; s2 = t2; s3 = t3; } rk += 4; #else /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0(LTC_BYTE(s0, 3)) ^ Td1(LTC_BYTE(s3, 2)) ^ Td2(LTC_BYTE(s2, 1)) ^ Td3(LTC_BYTE(s1, 0)) ^ rk[4]; t1 = Td0(LTC_BYTE(s1, 3)) ^ Td1(LTC_BYTE(s0, 2)) ^ Td2(LTC_BYTE(s3, 1)) ^ Td3(LTC_BYTE(s2, 0)) ^ rk[5]; t2 = Td0(LTC_BYTE(s2, 3)) ^ Td1(LTC_BYTE(s1, 2)) ^ Td2(LTC_BYTE(s0, 1)) ^ Td3(LTC_BYTE(s3, 0)) ^ rk[6]; t3 = Td0(LTC_BYTE(s3, 3)) ^ Td1(LTC_BYTE(s2, 2)) ^ Td2(LTC_BYTE(s1, 1)) ^ Td3(LTC_BYTE(s0, 0)) ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0(LTC_BYTE(t0, 3)) ^ Td1(LTC_BYTE(t3, 2)) ^ Td2(LTC_BYTE(t2, 1)) ^ Td3(LTC_BYTE(t1, 0)) ^ rk[0]; s1 = Td0(LTC_BYTE(t1, 3)) ^ Td1(LTC_BYTE(t0, 2)) ^ Td2(LTC_BYTE(t3, 1)) ^ Td3(LTC_BYTE(t2, 0)) ^ rk[1]; s2 = Td0(LTC_BYTE(t2, 3)) ^ Td1(LTC_BYTE(t1, 2)) ^ Td2(LTC_BYTE(t0, 1)) ^ Td3(LTC_BYTE(t3, 0)) ^ rk[2]; s3 = Td0(LTC_BYTE(t3, 3)) ^ Td1(LTC_BYTE(t2, 2)) ^ Td2(LTC_BYTE(t1, 1)) ^ Td3(LTC_BYTE(t0, 0)) ^ rk[3]; } #endif /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[LTC_BYTE(t0, 3)] & 0xff000000) ^ (Td4[LTC_BYTE(t3, 2)] & 0x00ff0000) ^ (Td4[LTC_BYTE(t2, 1)] & 0x0000ff00) ^ (Td4[LTC_BYTE(t1, 0)] & 0x000000ff) ^ rk[0]; STORE32H(s0, pt); s1 = (Td4[LTC_BYTE(t1, 3)] & 0xff000000) ^ (Td4[LTC_BYTE(t0, 2)] & 0x00ff0000) ^ (Td4[LTC_BYTE(t3, 1)] & 0x0000ff00) ^ (Td4[LTC_BYTE(t2, 0)] & 0x000000ff) ^ rk[1]; STORE32H(s1, pt+4); s2 = (Td4[LTC_BYTE(t2, 3)] & 0xff000000) ^ (Td4[LTC_BYTE(t1, 2)] & 0x00ff0000) ^ (Td4[LTC_BYTE(t0, 1)] & 0x0000ff00) ^ (Td4[LTC_BYTE(t3, 0)] & 0x000000ff) ^ rk[2]; STORE32H(s2, pt+8); s3 = (Td4[LTC_BYTE(t3, 3)] & 0xff000000) ^ (Td4[LTC_BYTE(t2, 2)] & 0x00ff0000) ^ (Td4[LTC_BYTE(t1, 1)] & 0x0000ff00) ^ (Td4[LTC_BYTE(t0, 0)] & 0x000000ff) ^ rk[3]; STORE32H(s3, pt+12); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_rijndael_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); return err; } #endif /** Performs a self-test of the AES block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int ECB_TEST(void) { #ifndef LTC_TEST return CRYPT_NOP; #else int err; static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } }, { 24, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } }, { 32, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } } }; symmetric_key key; unsigned char tmp[2][16]; int i, y; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { zeromem(&key, sizeof(key)); if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key); rijndael_ecb_decrypt(tmp[0], tmp[1], &key); if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) || compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif /* ENCRYPT_ONLY */ /** Terminate the context @param skey The scheduled key */ void ECB_DONE(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int ECB_KS(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } if (*keysize < 24) { *keysize = 16; return CRYPT_OK; } if (*keysize < 32) { *keysize = 24; return CRYPT_OK; } *keysize = 32; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/aes/aes_desc.c000066400000000000000000000150531464416617300243270ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* Auto-detection of AES implementation by Steffen Jaeckel */ /** @file aes_desc.c Run-time detection of correct AES implementation */ #include "tomcrypt_private.h" #if defined(LTC_RIJNDAEL) #ifndef ENCRYPT_ONLY #define AES_SETUP aes_setup #define AES_ENC aes_ecb_encrypt #define AES_DEC aes_ecb_decrypt #define AES_DONE aes_done #define AES_TEST aes_test #define AES_KS aes_keysize const struct ltc_cipher_descriptor aes_desc = { "aes", 6, 16, 32, 16, 10, AES_SETUP, AES_ENC, AES_DEC, AES_TEST, AES_DONE, AES_KS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #else #define AES_SETUP aes_enc_setup #define AES_ENC aes_enc_ecb_encrypt #define AES_DONE aes_enc_done #define AES_TEST aes_enc_test #define AES_KS aes_enc_keysize const struct ltc_cipher_descriptor aes_enc_desc = { "aes", 6, 16, 32, 16, 10, AES_SETUP, AES_ENC, NULL, NULL, AES_DONE, AES_KS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #endif /* Code partially borrowed from https://software.intel.com/content/www/us/en/develop/articles/intel-sha-extensions.html */ #if defined(LTC_HAS_AES_NI) static LTC_INLINE int s_aesni_is_supported(void) { static int initialized = 0, is_supported = 0; if (initialized == 0) { int a, b, c, d; /* Look for CPUID.1.0.ECX[25] * EAX = 1, ECX = 0 */ a = 1; c = 0; asm volatile ("cpuid" :"=a"(a), "=b"(b), "=c"(c), "=d"(d) :"a"(a), "c"(c) ); is_supported = ((c >> 25) & 1); initialized = 1; } return is_supported; } #ifndef ENCRYPT_ONLY int aesni_is_supported(void) { return s_aesni_is_supported(); } #endif #endif /** Initialize the AES (Rijndael) block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int AES_SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { #ifdef LTC_HAS_AES_NI if (s_aesni_is_supported()) { return aesni_setup(key, keylen, num_rounds, skey); } #endif /* Last resort, software AES */ return rijndael_setup(key, keylen, num_rounds, skey); } /** Encrypts a block of text with AES @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int AES_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { #ifdef LTC_HAS_AES_NI if (s_aesni_is_supported()) { return aesni_ecb_encrypt(pt, ct, skey); } #endif return rijndael_ecb_encrypt(pt, ct, skey); } #ifndef ENCRYPT_ONLY /** Decrypts a block of text with AES @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int AES_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { #ifdef LTC_HAS_AES_NI if (s_aesni_is_supported()) { return aesni_ecb_decrypt(ct, pt, skey); } #endif return rijndael_ecb_decrypt(ct, pt, skey); } #endif /* ENCRYPT_ONLY */ /** Performs a self-test of the AES block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int AES_TEST(void) { #ifndef LTC_TEST return CRYPT_NOP; #else int err; static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } }, { 24, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } }, { 32, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } } }; symmetric_key key; unsigned char tmp[2][16]; int i; #ifndef ENCRYPT_ONLY int y; #endif for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { zeromem(&key, sizeof(key)); if ((err = AES_SETUP(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } AES_ENC(tests[i].pt, tmp[0], &key); if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } #ifndef ENCRYPT_ONLY AES_DEC(tmp[0], tmp[1], &key); if (compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) AES_ENC(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) AES_DEC(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; #endif } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void AES_DONE(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int AES_KS(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } if (*keysize < 24) { *keysize = 16; return CRYPT_OK; } if (*keysize < 32) { *keysize = 24; return CRYPT_OK; } *keysize = 32; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/aes/aes_tab.c000066400000000000000000002073731464416617300241670ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The precomputed tables for AES */ /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ #ifdef LTC_AES_TAB_C /** @file aes_tab.c AES tables */ static const ulong32 TE0[256] = { 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, }; #if !defined(PELI_TAB) && defined(LTC_SMALL_CODE) static const ulong32 Te4[256] = { 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, }; #endif #ifndef ENCRYPT_ONLY static const ulong32 TD0[256] = { 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, }; static const ulong32 Td4[256] = { 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, }; #endif /* ENCRYPT_ONLY */ #ifdef LTC_SMALL_CODE #define Te0(x) TE0[x] #define Te1(x) RORc(TE0[x], 8) #define Te2(x) RORc(TE0[x], 16) #define Te3(x) RORc(TE0[x], 24) #define Td0(x) TD0[x] #define Td1(x) RORc(TD0[x], 8) #define Td2(x) RORc(TD0[x], 16) #define Td3(x) RORc(TD0[x], 24) #define Te4_0 0x000000FF & Te4 #define Te4_1 0x0000FF00 & Te4 #define Te4_2 0x00FF0000 & Te4 #define Te4_3 0xFF000000 & Te4 #else #define Te0(x) TE0[x] #define Te1(x) TE1[x] #define Te2(x) TE2[x] #define Te3(x) TE3[x] #define Td0(x) TD0[x] #define Td1(x) TD1[x] #define Td2(x) TD2[x] #define Td3(x) TD3[x] static const ulong32 TE1[256] = { 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, }; static const ulong32 TE2[256] = { 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, }; static const ulong32 TE3[256] = { 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, }; #ifndef PELI_TAB static const ulong32 Te4_0[] = { 0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, 0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, 0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, 0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, 0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, 0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, 0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, 0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, 0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, 0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, 0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, 0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, 0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, 0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, 0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, 0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, 0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, 0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, 0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, 0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, 0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, 0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, 0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, 0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, 0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, 0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, 0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, 0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, 0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, 0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, 0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL }; static const ulong32 Te4_1[] = { 0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, 0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, 0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, 0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, 0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, 0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, 0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, 0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, 0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, 0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, 0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, 0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, 0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, 0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, 0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, 0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, 0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, 0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, 0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, 0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, 0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, 0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, 0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, 0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, 0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, 0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, 0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, 0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, 0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, 0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, 0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, 0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL }; static const ulong32 Te4_2[] = { 0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, 0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, 0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, 0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, 0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, 0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, 0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, 0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, 0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, 0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, 0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, 0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, 0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, 0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, 0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, 0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, 0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, 0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, 0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, 0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, 0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, 0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, 0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, 0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, 0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, 0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, 0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, 0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, 0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, 0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, 0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, 0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL }; static const ulong32 Te4_3[] = { 0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, 0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, 0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, 0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, 0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, 0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, 0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, 0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, 0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, 0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, 0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, 0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, 0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, 0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, 0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, 0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, 0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, 0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, 0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, 0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, 0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, 0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, 0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, 0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, 0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, 0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, 0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, 0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, 0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, 0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, 0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, 0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL }; #endif /* pelimac */ #ifndef ENCRYPT_ONLY static const ulong32 TD1[256] = { 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, }; static const ulong32 TD2[256] = { 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, }; static const ulong32 TD3[256] = { 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, }; static const ulong32 Tks0[] = { 0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, 0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, 0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, 0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, 0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, 0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, 0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, 0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, 0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, 0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, 0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, 0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, 0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, 0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, 0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, 0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, 0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, 0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, 0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, 0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, 0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, 0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, 0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, 0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, 0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, 0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, 0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, 0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, 0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, 0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, 0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, 0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL }; static const ulong32 Tks1[] = { 0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, 0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, 0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, 0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, 0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, 0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, 0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, 0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, 0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, 0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, 0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, 0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, 0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, 0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, 0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, 0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, 0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, 0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, 0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, 0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, 0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, 0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, 0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, 0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, 0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, 0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, 0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, 0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, 0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, 0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, 0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, 0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL }; static const ulong32 Tks2[] = { 0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, 0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, 0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, 0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, 0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, 0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, 0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, 0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, 0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, 0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, 0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, 0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, 0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, 0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, 0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, 0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, 0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, 0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, 0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, 0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, 0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, 0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, 0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, 0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, 0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, 0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, 0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, 0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, 0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, 0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, 0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, 0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL }; static const ulong32 Tks3[] = { 0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, 0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, 0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, 0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, 0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, 0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, 0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, 0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, 0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, 0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, 0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, 0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, 0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, 0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, 0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, 0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, 0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, 0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, 0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, 0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, 0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, 0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, 0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, 0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, 0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, 0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, 0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, 0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, 0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, 0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, 0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, 0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL }; #endif /* ENCRYPT_ONLY */ #endif /* SMALL CODE */ #ifndef PELI_TAB static const ulong32 rcon[] = { 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #endif #endif /* LTC_AES_TAB_C */ optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/aes/aesni.c000066400000000000000000000240371464416617300236620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* AES-NI implementation by Steffen Jaeckel */ /** @file aesni.c Implementation of AES via the AES-NI instruction on x86_64 */ #include "tomcrypt_private.h" #if defined(LTC_HAS_AES_NI) const struct ltc_cipher_descriptor aesni_desc = { "aes", 6, 16, 32, 16, 10, aesni_setup, aesni_ecb_encrypt, aesni_ecb_decrypt, aesni_test, aesni_done, aesni_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #include #include #include #define setup_mix(t, c) _mm_extract_epi32(_mm_aeskeygenassist_si128(t, 0), c) #define temp_load(k) _mm_loadu_si128((__m128i*)(k)) #define temp_update(t, k) _mm_insert_epi32(t, k, 3) #define temp_invert(k) _mm_aesimc_si128(*((__m128i*)(k))) static const ulong32 rcon[] = { 0x01UL, 0x02UL, 0x04UL, 0x08UL, 0x10UL, 0x20UL, 0x40UL, 0x80UL, 0x1BUL, 0x36UL }; /** Initialize the AES (Rijndael) block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int i; __m128i temp; ulong32 *rk, *K; ulong32 *rrk; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 16 && keylen != 24 && keylen != 32) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 0 && num_rounds != (keylen / 4 + 6)) { return CRYPT_INVALID_ROUNDS; } skey->rijndael.Nr = keylen / 4 + 6; K = LTC_ALIGN_BUF(skey->rijndael.K, 16); skey->rijndael.eK = K; K += 60; skey->rijndael.dK = K; /* setup the forward key */ i = 0; rk = skey->rijndael.eK; LOAD32L(rk[0], key); LOAD32L(rk[1], key + 4); LOAD32L(rk[2], key + 8); LOAD32L(rk[3], key + 12); if (keylen == 16) { temp = temp_load(key); for (;;) { rk[4] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { break; } temp = temp_update(temp, rk[7]); rk += 4; } } else if (keylen == 24) { LOAD32L(rk[4], key + 16); LOAD32L(rk[5], key + 20); temp = temp_load(key + 8); for (;;) { rk[6] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; rk[7] = rk[1] ^ rk[6]; rk[8] = rk[2] ^ rk[7]; rk[9] = rk[3] ^ rk[8]; if (++i == 8) { break; } rk[10] = rk[4] ^ rk[9]; rk[11] = rk[5] ^ rk[10]; temp = temp_update(temp, rk[11]); rk += 6; } } else if (keylen == 32) { LOAD32L(rk[4], key + 16); LOAD32L(rk[5], key + 20); LOAD32L(rk[6], key + 24); LOAD32L(rk[7], key + 28); temp = temp_load(key + 16); for (;;) { rk[8] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; rk[9] = rk[1] ^ rk[8]; rk[10] = rk[2] ^ rk[9]; rk[11] = rk[3] ^ rk[10]; if (++i == 7) { break; } temp = temp_update(temp, rk[11]); rk[12] = rk[4] ^ setup_mix(temp, 2); rk[13] = rk[5] ^ rk[12]; rk[14] = rk[6] ^ rk[13]; rk[15] = rk[7] ^ rk[14]; temp = temp_update(temp, rk[15]); rk += 8; } } else { /* this can't happen */ /* coverity[dead_error_line] */ return CRYPT_ERROR; } /* setup the inverse key now */ rk = skey->rijndael.dK; rrk = skey->rijndael.eK + skey->rijndael.Nr * 4; /* apply the inverse MixColumn transform to all round keys but the first and the last: */ /* copy first */ *rk++ = *rrk++; *rk++ = *rrk++; *rk++ = *rrk++; *rk = *rrk; rk -= 3; rrk -= 3; for (i = 1; i < skey->rijndael.Nr; i++) { rrk -= 4; rk += 4; temp = temp_invert(rk); *((__m128i*) rk) = temp_invert(rrk); } /* copy last */ rrk -= 4; rk += 4; *rk++ = *rrk++; *rk++ = *rrk++; *rk++ = *rrk++; *rk = *rrk; return CRYPT_OK; } /** Encrypts a block of text with AES @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { int Nr, r; const __m128i *skeys; __m128i block; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); Nr = skey->rijndael.Nr; if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; skeys = (__m128i*) skey->rijndael.eK; block = _mm_loadu_si128((const __m128i*) (pt)); block = _mm_xor_si128(block, skeys[0]); for (r = 1; r < Nr - 1; r += 2) { block = _mm_aesenc_si128(block, skeys[r]); block = _mm_aesenc_si128(block, skeys[r + 1]); } block = _mm_aesenc_si128(block, skeys[Nr - 1]); block = _mm_aesenclast_si128(block, skeys[Nr]); _mm_storeu_si128((__m128i*) ct, block); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_aesni_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); return err; } #endif /** Decrypts a block of text with AES @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { int Nr, r; const __m128i *skeys; __m128i block; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); Nr = skey->rijndael.Nr; if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; skeys = (__m128i*) skey->rijndael.dK; block = _mm_loadu_si128((const __m128i*) (ct)); block = _mm_xor_si128(block, skeys[0]); for (r = 1; r < Nr - 1; r += 2) { block = _mm_aesdec_si128(block, skeys[r]); block = _mm_aesdec_si128(block, skeys[r + 1]); } block = _mm_aesdec_si128(block, skeys[Nr - 1]); block = _mm_aesdeclast_si128(block, skeys[Nr]); _mm_storeu_si128((__m128i*) pt, block); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_aesni_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); return err; } #endif /** Performs a self-test of the AES block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int aesni_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else int err; static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } }, { 24, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } }, { 32, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } } }; symmetric_key key; unsigned char tmp[2][16]; int i, y; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { zeromem(&key, sizeof(key)); if ((err = aesni_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } aesni_ecb_encrypt(tests[i].pt, tmp[0], &key); aesni_ecb_decrypt(tmp[0], tmp[1], &key); if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES-NI Encrypt", i) || compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES-NI Decrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) aesni_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) aesni_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void aesni_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int aesni_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } if (*keysize < 24) { *keysize = 16; return CRYPT_OK; } if (*keysize < 32) { *keysize = 24; return CRYPT_OK; } *keysize = 32; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/anubis.c000066400000000000000000002050451464416617300232740ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file anubis.c Anubis implementation derived from public domain source Authors: Paulo S.L.M. Barreto and Vincent Rijmen. */ #include "tomcrypt_private.h" #ifdef LTC_ANUBIS const struct ltc_cipher_descriptor anubis_desc = { "anubis", 19, 16, 40, 16, 12, &anubis_setup, &anubis_ecb_encrypt, &anubis_ecb_decrypt, &anubis_test, &anubis_done, &anubis_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #define MAX_N 10 /* * Though Anubis is endianness-neutral, the encryption tables are listed * in BIG-ENDIAN format, which is adopted throughout this implementation * (but little-endian notation would be equally suitable if consistently * employed). */ #if defined(LTC_ANUBIS_TWEAK) static const ulong32 T0[256] = { 0xba69d2bbU, 0x54a84de5U, 0x2f5ebce2U, 0x74e8cd25U, 0x53a651f7U, 0xd3bb6bd0U, 0xd2b96fd6U, 0x4d9a29b3U, 0x50a05dfdU, 0xac458acfU, 0x8d070e09U, 0xbf63c6a5U, 0x70e0dd3dU, 0x52a455f1U, 0x9a29527bU, 0x4c982db5U, 0xeac98f46U, 0xd5b773c4U, 0x97336655U, 0xd1bf63dcU, 0x3366ccaaU, 0x51a259fbU, 0x5bb671c7U, 0xa651a2f3U, 0xdea15ffeU, 0x48903dadU, 0xa84d9ad7U, 0x992f5e71U, 0xdbab4be0U, 0x3264c8acU, 0xb773e695U, 0xfce5d732U, 0xe3dbab70U, 0x9e214263U, 0x913f7e41U, 0x9b2b567dU, 0xe2d9af76U, 0xbb6bd6bdU, 0x4182199bU, 0x6edca579U, 0xa557aef9U, 0xcb8b0b80U, 0x6bd6b167U, 0x95376e59U, 0xa15fbee1U, 0xf3fbeb10U, 0xb17ffe81U, 0x0204080cU, 0xcc851792U, 0xc49537a2U, 0x1d3a744eU, 0x14285078U, 0xc39b2bb0U, 0x63c69157U, 0xdaa94fe6U, 0x5dba69d3U, 0x5fbe61dfU, 0xdca557f2U, 0x7dfae913U, 0xcd871394U, 0x7ffee11fU, 0x5ab475c1U, 0x6cd8ad75U, 0x5cb86dd5U, 0xf7f3fb08U, 0x264c98d4U, 0xffe3db38U, 0xedc79354U, 0xe8cd874aU, 0x9d274e69U, 0x6fdea17fU, 0x8e010203U, 0x19326456U, 0xa05dbae7U, 0xf0fde71aU, 0x890f1e11U, 0x0f1e3c22U, 0x070e1c12U, 0xaf4386c5U, 0xfbebcb20U, 0x08102030U, 0x152a547eU, 0x0d1a342eU, 0x04081018U, 0x01020406U, 0x64c88d45U, 0xdfa35bf8U, 0x76ecc529U, 0x79f2f90bU, 0xdda753f4U, 0x3d7af48eU, 0x162c5874U, 0x3f7efc82U, 0x376edcb2U, 0x6ddaa973U, 0x3870e090U, 0xb96fdeb1U, 0x73e6d137U, 0xe9cf834cU, 0x356ad4beU, 0x55aa49e3U, 0x71e2d93bU, 0x7bf6f107U, 0x8c050a0fU, 0x72e4d531U, 0x880d1a17U, 0xf6f1ff0eU, 0x2a54a8fcU, 0x3e7cf884U, 0x5ebc65d9U, 0x274e9cd2U, 0x468c0589U, 0x0c183028U, 0x65ca8943U, 0x68d0bd6dU, 0x61c2995bU, 0x03060c0aU, 0xc19f23bcU, 0x57ae41efU, 0xd6b17fceU, 0xd9af43ecU, 0x58b07dcdU, 0xd8ad47eaU, 0x66cc8549U, 0xd7b37bc8U, 0x3a74e89cU, 0xc88d078aU, 0x3c78f088U, 0xfae9cf26U, 0x96316253U, 0xa753a6f5U, 0x982d5a77U, 0xecc59752U, 0xb86ddab7U, 0xc7933ba8U, 0xae4182c3U, 0x69d2b96bU, 0x4b9631a7U, 0xab4b96ddU, 0xa94f9ed1U, 0x67ce814fU, 0x0a14283cU, 0x478e018fU, 0xf2f9ef16U, 0xb577ee99U, 0x224488ccU, 0xe5d7b364U, 0xeec19f5eU, 0xbe61c2a3U, 0x2b56acfaU, 0x811f3e21U, 0x1224486cU, 0x831b362dU, 0x1b366c5aU, 0x0e1c3824U, 0x23468ccaU, 0xf5f7f304U, 0x458a0983U, 0x214284c6U, 0xce811f9eU, 0x499239abU, 0x2c58b0e8U, 0xf9efc32cU, 0xe6d1bf6eU, 0xb671e293U, 0x2850a0f0U, 0x172e5c72U, 0x8219322bU, 0x1a34685cU, 0x8b0b161dU, 0xfee1df3eU, 0x8a09121bU, 0x09122436U, 0xc98f038cU, 0x87132635U, 0x4e9c25b9U, 0xe1dfa37cU, 0x2e5cb8e4U, 0xe4d5b762U, 0xe0dda77aU, 0xebcb8b40U, 0x903d7a47U, 0xa455aaffU, 0x1e3c7844U, 0x85172e39U, 0x60c09d5dU, 0x00000000U, 0x254a94deU, 0xf4f5f702U, 0xf1ffe31cU, 0x94356a5fU, 0x0b162c3aU, 0xe7d3bb68U, 0x75eac923U, 0xefc39b58U, 0x3468d0b8U, 0x3162c4a6U, 0xd4b577c2U, 0xd0bd67daU, 0x86112233U, 0x7efce519U, 0xad478ec9U, 0xfde7d334U, 0x2952a4f6U, 0x3060c0a0U, 0x3b76ec9aU, 0x9f234665U, 0xf8edc72aU, 0xc6913faeU, 0x13264c6aU, 0x060c1814U, 0x050a141eU, 0xc59733a4U, 0x11224466U, 0x77eec12fU, 0x7cf8ed15U, 0x7af4f501U, 0x78f0fd0dU, 0x366cd8b4U, 0x1c387048U, 0x3972e496U, 0x59b279cbU, 0x18306050U, 0x56ac45e9U, 0xb37bf68dU, 0xb07dfa87U, 0x244890d8U, 0x204080c0U, 0xb279f28bU, 0x9239724bU, 0xa35bb6edU, 0xc09d27baU, 0x44880d85U, 0x62c49551U, 0x10204060U, 0xb475ea9fU, 0x84152a3fU, 0x43861197U, 0x933b764dU, 0xc2992fb6U, 0x4a9435a1U, 0xbd67cea9U, 0x8f030605U, 0x2d5ab4eeU, 0xbc65caafU, 0x9c254a6fU, 0x6ad4b561U, 0x40801d9dU, 0xcf831b98U, 0xa259b2ebU, 0x801d3a27U, 0x4f9e21bfU, 0x1f3e7c42U, 0xca890f86U, 0xaa4992dbU, 0x42841591U, }; static const ulong32 T1[256] = { 0x69babbd2U, 0xa854e54dU, 0x5e2fe2bcU, 0xe87425cdU, 0xa653f751U, 0xbbd3d06bU, 0xb9d2d66fU, 0x9a4db329U, 0xa050fd5dU, 0x45accf8aU, 0x078d090eU, 0x63bfa5c6U, 0xe0703dddU, 0xa452f155U, 0x299a7b52U, 0x984cb52dU, 0xc9ea468fU, 0xb7d5c473U, 0x33975566U, 0xbfd1dc63U, 0x6633aaccU, 0xa251fb59U, 0xb65bc771U, 0x51a6f3a2U, 0xa1defe5fU, 0x9048ad3dU, 0x4da8d79aU, 0x2f99715eU, 0xabdbe04bU, 0x6432acc8U, 0x73b795e6U, 0xe5fc32d7U, 0xdbe370abU, 0x219e6342U, 0x3f91417eU, 0x2b9b7d56U, 0xd9e276afU, 0x6bbbbdd6U, 0x82419b19U, 0xdc6e79a5U, 0x57a5f9aeU, 0x8bcb800bU, 0xd66b67b1U, 0x3795596eU, 0x5fa1e1beU, 0xfbf310ebU, 0x7fb181feU, 0x04020c08U, 0x85cc9217U, 0x95c4a237U, 0x3a1d4e74U, 0x28147850U, 0x9bc3b02bU, 0xc6635791U, 0xa9dae64fU, 0xba5dd369U, 0xbe5fdf61U, 0xa5dcf257U, 0xfa7d13e9U, 0x87cd9413U, 0xfe7f1fe1U, 0xb45ac175U, 0xd86c75adU, 0xb85cd56dU, 0xf3f708fbU, 0x4c26d498U, 0xe3ff38dbU, 0xc7ed5493U, 0xcde84a87U, 0x279d694eU, 0xde6f7fa1U, 0x018e0302U, 0x32195664U, 0x5da0e7baU, 0xfdf01ae7U, 0x0f89111eU, 0x1e0f223cU, 0x0e07121cU, 0x43afc586U, 0xebfb20cbU, 0x10083020U, 0x2a157e54U, 0x1a0d2e34U, 0x08041810U, 0x02010604U, 0xc864458dU, 0xa3dff85bU, 0xec7629c5U, 0xf2790bf9U, 0xa7ddf453U, 0x7a3d8ef4U, 0x2c167458U, 0x7e3f82fcU, 0x6e37b2dcU, 0xda6d73a9U, 0x703890e0U, 0x6fb9b1deU, 0xe67337d1U, 0xcfe94c83U, 0x6a35bed4U, 0xaa55e349U, 0xe2713bd9U, 0xf67b07f1U, 0x058c0f0aU, 0xe47231d5U, 0x0d88171aU, 0xf1f60effU, 0x542afca8U, 0x7c3e84f8U, 0xbc5ed965U, 0x4e27d29cU, 0x8c468905U, 0x180c2830U, 0xca654389U, 0xd0686dbdU, 0xc2615b99U, 0x06030a0cU, 0x9fc1bc23U, 0xae57ef41U, 0xb1d6ce7fU, 0xafd9ec43U, 0xb058cd7dU, 0xadd8ea47U, 0xcc664985U, 0xb3d7c87bU, 0x743a9ce8U, 0x8dc88a07U, 0x783c88f0U, 0xe9fa26cfU, 0x31965362U, 0x53a7f5a6U, 0x2d98775aU, 0xc5ec5297U, 0x6db8b7daU, 0x93c7a83bU, 0x41aec382U, 0xd2696bb9U, 0x964ba731U, 0x4babdd96U, 0x4fa9d19eU, 0xce674f81U, 0x140a3c28U, 0x8e478f01U, 0xf9f216efU, 0x77b599eeU, 0x4422cc88U, 0xd7e564b3U, 0xc1ee5e9fU, 0x61bea3c2U, 0x562bfaacU, 0x1f81213eU, 0x24126c48U, 0x1b832d36U, 0x361b5a6cU, 0x1c0e2438U, 0x4623ca8cU, 0xf7f504f3U, 0x8a458309U, 0x4221c684U, 0x81ce9e1fU, 0x9249ab39U, 0x582ce8b0U, 0xeff92cc3U, 0xd1e66ebfU, 0x71b693e2U, 0x5028f0a0U, 0x2e17725cU, 0x19822b32U, 0x341a5c68U, 0x0b8b1d16U, 0xe1fe3edfU, 0x098a1b12U, 0x12093624U, 0x8fc98c03U, 0x13873526U, 0x9c4eb925U, 0xdfe17ca3U, 0x5c2ee4b8U, 0xd5e462b7U, 0xdde07aa7U, 0xcbeb408bU, 0x3d90477aU, 0x55a4ffaaU, 0x3c1e4478U, 0x1785392eU, 0xc0605d9dU, 0x00000000U, 0x4a25de94U, 0xf5f402f7U, 0xfff11ce3U, 0x35945f6aU, 0x160b3a2cU, 0xd3e768bbU, 0xea7523c9U, 0xc3ef589bU, 0x6834b8d0U, 0x6231a6c4U, 0xb5d4c277U, 0xbdd0da67U, 0x11863322U, 0xfc7e19e5U, 0x47adc98eU, 0xe7fd34d3U, 0x5229f6a4U, 0x6030a0c0U, 0x763b9aecU, 0x239f6546U, 0xedf82ac7U, 0x91c6ae3fU, 0x26136a4cU, 0x0c061418U, 0x0a051e14U, 0x97c5a433U, 0x22116644U, 0xee772fc1U, 0xf87c15edU, 0xf47a01f5U, 0xf0780dfdU, 0x6c36b4d8U, 0x381c4870U, 0x723996e4U, 0xb259cb79U, 0x30185060U, 0xac56e945U, 0x7bb38df6U, 0x7db087faU, 0x4824d890U, 0x4020c080U, 0x79b28bf2U, 0x39924b72U, 0x5ba3edb6U, 0x9dc0ba27U, 0x8844850dU, 0xc4625195U, 0x20106040U, 0x75b49feaU, 0x15843f2aU, 0x86439711U, 0x3b934d76U, 0x99c2b62fU, 0x944aa135U, 0x67bda9ceU, 0x038f0506U, 0x5a2deeb4U, 0x65bcafcaU, 0x259c6f4aU, 0xd46a61b5U, 0x80409d1dU, 0x83cf981bU, 0x59a2ebb2U, 0x1d80273aU, 0x9e4fbf21U, 0x3e1f427cU, 0x89ca860fU, 0x49aadb92U, 0x84429115U, }; static const ulong32 T2[256] = { 0xd2bbba69U, 0x4de554a8U, 0xbce22f5eU, 0xcd2574e8U, 0x51f753a6U, 0x6bd0d3bbU, 0x6fd6d2b9U, 0x29b34d9aU, 0x5dfd50a0U, 0x8acfac45U, 0x0e098d07U, 0xc6a5bf63U, 0xdd3d70e0U, 0x55f152a4U, 0x527b9a29U, 0x2db54c98U, 0x8f46eac9U, 0x73c4d5b7U, 0x66559733U, 0x63dcd1bfU, 0xccaa3366U, 0x59fb51a2U, 0x71c75bb6U, 0xa2f3a651U, 0x5ffedea1U, 0x3dad4890U, 0x9ad7a84dU, 0x5e71992fU, 0x4be0dbabU, 0xc8ac3264U, 0xe695b773U, 0xd732fce5U, 0xab70e3dbU, 0x42639e21U, 0x7e41913fU, 0x567d9b2bU, 0xaf76e2d9U, 0xd6bdbb6bU, 0x199b4182U, 0xa5796edcU, 0xaef9a557U, 0x0b80cb8bU, 0xb1676bd6U, 0x6e599537U, 0xbee1a15fU, 0xeb10f3fbU, 0xfe81b17fU, 0x080c0204U, 0x1792cc85U, 0x37a2c495U, 0x744e1d3aU, 0x50781428U, 0x2bb0c39bU, 0x915763c6U, 0x4fe6daa9U, 0x69d35dbaU, 0x61df5fbeU, 0x57f2dca5U, 0xe9137dfaU, 0x1394cd87U, 0xe11f7ffeU, 0x75c15ab4U, 0xad756cd8U, 0x6dd55cb8U, 0xfb08f7f3U, 0x98d4264cU, 0xdb38ffe3U, 0x9354edc7U, 0x874ae8cdU, 0x4e699d27U, 0xa17f6fdeU, 0x02038e01U, 0x64561932U, 0xbae7a05dU, 0xe71af0fdU, 0x1e11890fU, 0x3c220f1eU, 0x1c12070eU, 0x86c5af43U, 0xcb20fbebU, 0x20300810U, 0x547e152aU, 0x342e0d1aU, 0x10180408U, 0x04060102U, 0x8d4564c8U, 0x5bf8dfa3U, 0xc52976ecU, 0xf90b79f2U, 0x53f4dda7U, 0xf48e3d7aU, 0x5874162cU, 0xfc823f7eU, 0xdcb2376eU, 0xa9736ddaU, 0xe0903870U, 0xdeb1b96fU, 0xd13773e6U, 0x834ce9cfU, 0xd4be356aU, 0x49e355aaU, 0xd93b71e2U, 0xf1077bf6U, 0x0a0f8c05U, 0xd53172e4U, 0x1a17880dU, 0xff0ef6f1U, 0xa8fc2a54U, 0xf8843e7cU, 0x65d95ebcU, 0x9cd2274eU, 0x0589468cU, 0x30280c18U, 0x894365caU, 0xbd6d68d0U, 0x995b61c2U, 0x0c0a0306U, 0x23bcc19fU, 0x41ef57aeU, 0x7fced6b1U, 0x43ecd9afU, 0x7dcd58b0U, 0x47ead8adU, 0x854966ccU, 0x7bc8d7b3U, 0xe89c3a74U, 0x078ac88dU, 0xf0883c78U, 0xcf26fae9U, 0x62539631U, 0xa6f5a753U, 0x5a77982dU, 0x9752ecc5U, 0xdab7b86dU, 0x3ba8c793U, 0x82c3ae41U, 0xb96b69d2U, 0x31a74b96U, 0x96ddab4bU, 0x9ed1a94fU, 0x814f67ceU, 0x283c0a14U, 0x018f478eU, 0xef16f2f9U, 0xee99b577U, 0x88cc2244U, 0xb364e5d7U, 0x9f5eeec1U, 0xc2a3be61U, 0xacfa2b56U, 0x3e21811fU, 0x486c1224U, 0x362d831bU, 0x6c5a1b36U, 0x38240e1cU, 0x8cca2346U, 0xf304f5f7U, 0x0983458aU, 0x84c62142U, 0x1f9ece81U, 0x39ab4992U, 0xb0e82c58U, 0xc32cf9efU, 0xbf6ee6d1U, 0xe293b671U, 0xa0f02850U, 0x5c72172eU, 0x322b8219U, 0x685c1a34U, 0x161d8b0bU, 0xdf3efee1U, 0x121b8a09U, 0x24360912U, 0x038cc98fU, 0x26358713U, 0x25b94e9cU, 0xa37ce1dfU, 0xb8e42e5cU, 0xb762e4d5U, 0xa77ae0ddU, 0x8b40ebcbU, 0x7a47903dU, 0xaaffa455U, 0x78441e3cU, 0x2e398517U, 0x9d5d60c0U, 0x00000000U, 0x94de254aU, 0xf702f4f5U, 0xe31cf1ffU, 0x6a5f9435U, 0x2c3a0b16U, 0xbb68e7d3U, 0xc92375eaU, 0x9b58efc3U, 0xd0b83468U, 0xc4a63162U, 0x77c2d4b5U, 0x67dad0bdU, 0x22338611U, 0xe5197efcU, 0x8ec9ad47U, 0xd334fde7U, 0xa4f62952U, 0xc0a03060U, 0xec9a3b76U, 0x46659f23U, 0xc72af8edU, 0x3faec691U, 0x4c6a1326U, 0x1814060cU, 0x141e050aU, 0x33a4c597U, 0x44661122U, 0xc12f77eeU, 0xed157cf8U, 0xf5017af4U, 0xfd0d78f0U, 0xd8b4366cU, 0x70481c38U, 0xe4963972U, 0x79cb59b2U, 0x60501830U, 0x45e956acU, 0xf68db37bU, 0xfa87b07dU, 0x90d82448U, 0x80c02040U, 0xf28bb279U, 0x724b9239U, 0xb6eda35bU, 0x27bac09dU, 0x0d854488U, 0x955162c4U, 0x40601020U, 0xea9fb475U, 0x2a3f8415U, 0x11974386U, 0x764d933bU, 0x2fb6c299U, 0x35a14a94U, 0xcea9bd67U, 0x06058f03U, 0xb4ee2d5aU, 0xcaafbc65U, 0x4a6f9c25U, 0xb5616ad4U, 0x1d9d4080U, 0x1b98cf83U, 0xb2eba259U, 0x3a27801dU, 0x21bf4f9eU, 0x7c421f3eU, 0x0f86ca89U, 0x92dbaa49U, 0x15914284U, }; static const ulong32 T3[256] = { 0xbbd269baU, 0xe54da854U, 0xe2bc5e2fU, 0x25cde874U, 0xf751a653U, 0xd06bbbd3U, 0xd66fb9d2U, 0xb3299a4dU, 0xfd5da050U, 0xcf8a45acU, 0x090e078dU, 0xa5c663bfU, 0x3ddde070U, 0xf155a452U, 0x7b52299aU, 0xb52d984cU, 0x468fc9eaU, 0xc473b7d5U, 0x55663397U, 0xdc63bfd1U, 0xaacc6633U, 0xfb59a251U, 0xc771b65bU, 0xf3a251a6U, 0xfe5fa1deU, 0xad3d9048U, 0xd79a4da8U, 0x715e2f99U, 0xe04babdbU, 0xacc86432U, 0x95e673b7U, 0x32d7e5fcU, 0x70abdbe3U, 0x6342219eU, 0x417e3f91U, 0x7d562b9bU, 0x76afd9e2U, 0xbdd66bbbU, 0x9b198241U, 0x79a5dc6eU, 0xf9ae57a5U, 0x800b8bcbU, 0x67b1d66bU, 0x596e3795U, 0xe1be5fa1U, 0x10ebfbf3U, 0x81fe7fb1U, 0x0c080402U, 0x921785ccU, 0xa23795c4U, 0x4e743a1dU, 0x78502814U, 0xb02b9bc3U, 0x5791c663U, 0xe64fa9daU, 0xd369ba5dU, 0xdf61be5fU, 0xf257a5dcU, 0x13e9fa7dU, 0x941387cdU, 0x1fe1fe7fU, 0xc175b45aU, 0x75add86cU, 0xd56db85cU, 0x08fbf3f7U, 0xd4984c26U, 0x38dbe3ffU, 0x5493c7edU, 0x4a87cde8U, 0x694e279dU, 0x7fa1de6fU, 0x0302018eU, 0x56643219U, 0xe7ba5da0U, 0x1ae7fdf0U, 0x111e0f89U, 0x223c1e0fU, 0x121c0e07U, 0xc58643afU, 0x20cbebfbU, 0x30201008U, 0x7e542a15U, 0x2e341a0dU, 0x18100804U, 0x06040201U, 0x458dc864U, 0xf85ba3dfU, 0x29c5ec76U, 0x0bf9f279U, 0xf453a7ddU, 0x8ef47a3dU, 0x74582c16U, 0x82fc7e3fU, 0xb2dc6e37U, 0x73a9da6dU, 0x90e07038U, 0xb1de6fb9U, 0x37d1e673U, 0x4c83cfe9U, 0xbed46a35U, 0xe349aa55U, 0x3bd9e271U, 0x07f1f67bU, 0x0f0a058cU, 0x31d5e472U, 0x171a0d88U, 0x0efff1f6U, 0xfca8542aU, 0x84f87c3eU, 0xd965bc5eU, 0xd29c4e27U, 0x89058c46U, 0x2830180cU, 0x4389ca65U, 0x6dbdd068U, 0x5b99c261U, 0x0a0c0603U, 0xbc239fc1U, 0xef41ae57U, 0xce7fb1d6U, 0xec43afd9U, 0xcd7db058U, 0xea47add8U, 0x4985cc66U, 0xc87bb3d7U, 0x9ce8743aU, 0x8a078dc8U, 0x88f0783cU, 0x26cfe9faU, 0x53623196U, 0xf5a653a7U, 0x775a2d98U, 0x5297c5ecU, 0xb7da6db8U, 0xa83b93c7U, 0xc38241aeU, 0x6bb9d269U, 0xa731964bU, 0xdd964babU, 0xd19e4fa9U, 0x4f81ce67U, 0x3c28140aU, 0x8f018e47U, 0x16eff9f2U, 0x99ee77b5U, 0xcc884422U, 0x64b3d7e5U, 0x5e9fc1eeU, 0xa3c261beU, 0xfaac562bU, 0x213e1f81U, 0x6c482412U, 0x2d361b83U, 0x5a6c361bU, 0x24381c0eU, 0xca8c4623U, 0x04f3f7f5U, 0x83098a45U, 0xc6844221U, 0x9e1f81ceU, 0xab399249U, 0xe8b0582cU, 0x2cc3eff9U, 0x6ebfd1e6U, 0x93e271b6U, 0xf0a05028U, 0x725c2e17U, 0x2b321982U, 0x5c68341aU, 0x1d160b8bU, 0x3edfe1feU, 0x1b12098aU, 0x36241209U, 0x8c038fc9U, 0x35261387U, 0xb9259c4eU, 0x7ca3dfe1U, 0xe4b85c2eU, 0x62b7d5e4U, 0x7aa7dde0U, 0x408bcbebU, 0x477a3d90U, 0xffaa55a4U, 0x44783c1eU, 0x392e1785U, 0x5d9dc060U, 0x00000000U, 0xde944a25U, 0x02f7f5f4U, 0x1ce3fff1U, 0x5f6a3594U, 0x3a2c160bU, 0x68bbd3e7U, 0x23c9ea75U, 0x589bc3efU, 0xb8d06834U, 0xa6c46231U, 0xc277b5d4U, 0xda67bdd0U, 0x33221186U, 0x19e5fc7eU, 0xc98e47adU, 0x34d3e7fdU, 0xf6a45229U, 0xa0c06030U, 0x9aec763bU, 0x6546239fU, 0x2ac7edf8U, 0xae3f91c6U, 0x6a4c2613U, 0x14180c06U, 0x1e140a05U, 0xa43397c5U, 0x66442211U, 0x2fc1ee77U, 0x15edf87cU, 0x01f5f47aU, 0x0dfdf078U, 0xb4d86c36U, 0x4870381cU, 0x96e47239U, 0xcb79b259U, 0x50603018U, 0xe945ac56U, 0x8df67bb3U, 0x87fa7db0U, 0xd8904824U, 0xc0804020U, 0x8bf279b2U, 0x4b723992U, 0xedb65ba3U, 0xba279dc0U, 0x850d8844U, 0x5195c462U, 0x60402010U, 0x9fea75b4U, 0x3f2a1584U, 0x97118643U, 0x4d763b93U, 0xb62f99c2U, 0xa135944aU, 0xa9ce67bdU, 0x0506038fU, 0xeeb45a2dU, 0xafca65bcU, 0x6f4a259cU, 0x61b5d46aU, 0x9d1d8040U, 0x981b83cfU, 0xebb259a2U, 0x273a1d80U, 0xbf219e4fU, 0x427c3e1fU, 0x860f89caU, 0xdb9249aaU, 0x91158442U, }; static const ulong32 T4[256] = { 0xbabababaU, 0x54545454U, 0x2f2f2f2fU, 0x74747474U, 0x53535353U, 0xd3d3d3d3U, 0xd2d2d2d2U, 0x4d4d4d4dU, 0x50505050U, 0xacacacacU, 0x8d8d8d8dU, 0xbfbfbfbfU, 0x70707070U, 0x52525252U, 0x9a9a9a9aU, 0x4c4c4c4cU, 0xeaeaeaeaU, 0xd5d5d5d5U, 0x97979797U, 0xd1d1d1d1U, 0x33333333U, 0x51515151U, 0x5b5b5b5bU, 0xa6a6a6a6U, 0xdedededeU, 0x48484848U, 0xa8a8a8a8U, 0x99999999U, 0xdbdbdbdbU, 0x32323232U, 0xb7b7b7b7U, 0xfcfcfcfcU, 0xe3e3e3e3U, 0x9e9e9e9eU, 0x91919191U, 0x9b9b9b9bU, 0xe2e2e2e2U, 0xbbbbbbbbU, 0x41414141U, 0x6e6e6e6eU, 0xa5a5a5a5U, 0xcbcbcbcbU, 0x6b6b6b6bU, 0x95959595U, 0xa1a1a1a1U, 0xf3f3f3f3U, 0xb1b1b1b1U, 0x02020202U, 0xccccccccU, 0xc4c4c4c4U, 0x1d1d1d1dU, 0x14141414U, 0xc3c3c3c3U, 0x63636363U, 0xdadadadaU, 0x5d5d5d5dU, 0x5f5f5f5fU, 0xdcdcdcdcU, 0x7d7d7d7dU, 0xcdcdcdcdU, 0x7f7f7f7fU, 0x5a5a5a5aU, 0x6c6c6c6cU, 0x5c5c5c5cU, 0xf7f7f7f7U, 0x26262626U, 0xffffffffU, 0xededededU, 0xe8e8e8e8U, 0x9d9d9d9dU, 0x6f6f6f6fU, 0x8e8e8e8eU, 0x19191919U, 0xa0a0a0a0U, 0xf0f0f0f0U, 0x89898989U, 0x0f0f0f0fU, 0x07070707U, 0xafafafafU, 0xfbfbfbfbU, 0x08080808U, 0x15151515U, 0x0d0d0d0dU, 0x04040404U, 0x01010101U, 0x64646464U, 0xdfdfdfdfU, 0x76767676U, 0x79797979U, 0xddddddddU, 0x3d3d3d3dU, 0x16161616U, 0x3f3f3f3fU, 0x37373737U, 0x6d6d6d6dU, 0x38383838U, 0xb9b9b9b9U, 0x73737373U, 0xe9e9e9e9U, 0x35353535U, 0x55555555U, 0x71717171U, 0x7b7b7b7bU, 0x8c8c8c8cU, 0x72727272U, 0x88888888U, 0xf6f6f6f6U, 0x2a2a2a2aU, 0x3e3e3e3eU, 0x5e5e5e5eU, 0x27272727U, 0x46464646U, 0x0c0c0c0cU, 0x65656565U, 0x68686868U, 0x61616161U, 0x03030303U, 0xc1c1c1c1U, 0x57575757U, 0xd6d6d6d6U, 0xd9d9d9d9U, 0x58585858U, 0xd8d8d8d8U, 0x66666666U, 0xd7d7d7d7U, 0x3a3a3a3aU, 0xc8c8c8c8U, 0x3c3c3c3cU, 0xfafafafaU, 0x96969696U, 0xa7a7a7a7U, 0x98989898U, 0xececececU, 0xb8b8b8b8U, 0xc7c7c7c7U, 0xaeaeaeaeU, 0x69696969U, 0x4b4b4b4bU, 0xababababU, 0xa9a9a9a9U, 0x67676767U, 0x0a0a0a0aU, 0x47474747U, 0xf2f2f2f2U, 0xb5b5b5b5U, 0x22222222U, 0xe5e5e5e5U, 0xeeeeeeeeU, 0xbebebebeU, 0x2b2b2b2bU, 0x81818181U, 0x12121212U, 0x83838383U, 0x1b1b1b1bU, 0x0e0e0e0eU, 0x23232323U, 0xf5f5f5f5U, 0x45454545U, 0x21212121U, 0xcecececeU, 0x49494949U, 0x2c2c2c2cU, 0xf9f9f9f9U, 0xe6e6e6e6U, 0xb6b6b6b6U, 0x28282828U, 0x17171717U, 0x82828282U, 0x1a1a1a1aU, 0x8b8b8b8bU, 0xfefefefeU, 0x8a8a8a8aU, 0x09090909U, 0xc9c9c9c9U, 0x87878787U, 0x4e4e4e4eU, 0xe1e1e1e1U, 0x2e2e2e2eU, 0xe4e4e4e4U, 0xe0e0e0e0U, 0xebebebebU, 0x90909090U, 0xa4a4a4a4U, 0x1e1e1e1eU, 0x85858585U, 0x60606060U, 0x00000000U, 0x25252525U, 0xf4f4f4f4U, 0xf1f1f1f1U, 0x94949494U, 0x0b0b0b0bU, 0xe7e7e7e7U, 0x75757575U, 0xefefefefU, 0x34343434U, 0x31313131U, 0xd4d4d4d4U, 0xd0d0d0d0U, 0x86868686U, 0x7e7e7e7eU, 0xadadadadU, 0xfdfdfdfdU, 0x29292929U, 0x30303030U, 0x3b3b3b3bU, 0x9f9f9f9fU, 0xf8f8f8f8U, 0xc6c6c6c6U, 0x13131313U, 0x06060606U, 0x05050505U, 0xc5c5c5c5U, 0x11111111U, 0x77777777U, 0x7c7c7c7cU, 0x7a7a7a7aU, 0x78787878U, 0x36363636U, 0x1c1c1c1cU, 0x39393939U, 0x59595959U, 0x18181818U, 0x56565656U, 0xb3b3b3b3U, 0xb0b0b0b0U, 0x24242424U, 0x20202020U, 0xb2b2b2b2U, 0x92929292U, 0xa3a3a3a3U, 0xc0c0c0c0U, 0x44444444U, 0x62626262U, 0x10101010U, 0xb4b4b4b4U, 0x84848484U, 0x43434343U, 0x93939393U, 0xc2c2c2c2U, 0x4a4a4a4aU, 0xbdbdbdbdU, 0x8f8f8f8fU, 0x2d2d2d2dU, 0xbcbcbcbcU, 0x9c9c9c9cU, 0x6a6a6a6aU, 0x40404040U, 0xcfcfcfcfU, 0xa2a2a2a2U, 0x80808080U, 0x4f4f4f4fU, 0x1f1f1f1fU, 0xcacacacaU, 0xaaaaaaaaU, 0x42424242U, }; static const ulong32 T5[256] = { 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, }; /** * The round constants. */ static const ulong32 rc[] = { 0xba542f74U, 0x53d3d24dU, 0x50ac8dbfU, 0x70529a4cU, 0xead597d1U, 0x33515ba6U, 0xde48a899U, 0xdb32b7fcU, 0xe39e919bU, 0xe2bb416eU, 0xa5cb6b95U, 0xa1f3b102U, 0xccc41d14U, 0xc363da5dU, 0x5fdc7dcdU, 0x7f5a6c5cU, 0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U, }; #else static const ulong32 T0[256] = { 0xa753a6f5U, 0xd3bb6bd0U, 0xe6d1bf6eU, 0x71e2d93bU, 0xd0bd67daU, 0xac458acfU, 0x4d9a29b3U, 0x79f2f90bU, 0x3a74e89cU, 0xc98f038cU, 0x913f7e41U, 0xfce5d732U, 0x1e3c7844U, 0x478e018fU, 0x54a84de5U, 0xbd67cea9U, 0x8c050a0fU, 0xa557aef9U, 0x7af4f501U, 0xfbebcb20U, 0x63c69157U, 0xb86ddab7U, 0xdda753f4U, 0xd4b577c2U, 0xe5d7b364U, 0xb37bf68dU, 0xc59733a4U, 0xbe61c2a3U, 0xa94f9ed1U, 0x880d1a17U, 0x0c183028U, 0xa259b2ebU, 0x3972e496U, 0xdfa35bf8U, 0x2952a4f6U, 0xdaa94fe6U, 0x2b56acfaU, 0xa84d9ad7U, 0xcb8b0b80U, 0x4c982db5U, 0x4b9631a7U, 0x224488ccU, 0xaa4992dbU, 0x244890d8U, 0x4182199bU, 0x70e0dd3dU, 0xa651a2f3U, 0xf9efc32cU, 0x5ab475c1U, 0xe2d9af76U, 0xb07dfa87U, 0x366cd8b4U, 0x7dfae913U, 0xe4d5b762U, 0x3366ccaaU, 0xffe3db38U, 0x60c09d5dU, 0x204080c0U, 0x08102030U, 0x8b0b161dU, 0x5ebc65d9U, 0xab4b96ddU, 0x7ffee11fU, 0x78f0fd0dU, 0x7cf8ed15U, 0x2c58b0e8U, 0x57ae41efU, 0xd2b96fd6U, 0xdca557f2U, 0x6ddaa973U, 0x7efce519U, 0x0d1a342eU, 0x53a651f7U, 0x94356a5fU, 0xc39b2bb0U, 0x2850a0f0U, 0x274e9cd2U, 0x060c1814U, 0x5fbe61dfU, 0xad478ec9U, 0x67ce814fU, 0x5cb86dd5U, 0x55aa49e3U, 0x48903dadU, 0x0e1c3824U, 0x52a455f1U, 0xeac98f46U, 0x42841591U, 0x5bb671c7U, 0x5dba69d3U, 0x3060c0a0U, 0x58b07dcdU, 0x51a259fbU, 0x59b279cbU, 0x3c78f088U, 0x4e9c25b9U, 0x3870e090U, 0x8a09121bU, 0x72e4d531U, 0x14285078U, 0xe7d3bb68U, 0xc6913faeU, 0xdea15ffeU, 0x50a05dfdU, 0x8e010203U, 0x9239724bU, 0xd1bf63dcU, 0x77eec12fU, 0x933b764dU, 0x458a0983U, 0x9a29527bU, 0xce811f9eU, 0x2d5ab4eeU, 0x03060c0aU, 0x62c49551U, 0xb671e293U, 0xb96fdeb1U, 0xbf63c6a5U, 0x96316253U, 0x6bd6b167U, 0x3f7efc82U, 0x070e1c12U, 0x1224486cU, 0xae4182c3U, 0x40801d9dU, 0x3468d0b8U, 0x468c0589U, 0x3e7cf884U, 0xdbab4be0U, 0xcf831b98U, 0xecc59752U, 0xcc851792U, 0xc19f23bcU, 0xa15fbee1U, 0xc09d27baU, 0xd6b17fceU, 0x1d3a744eU, 0xf4f5f702U, 0x61c2995bU, 0x3b76ec9aU, 0x10204060U, 0xd8ad47eaU, 0x68d0bd6dU, 0xa05dbae7U, 0xb17ffe81U, 0x0a14283cU, 0x69d2b96bU, 0x6cd8ad75U, 0x499239abU, 0xfae9cf26U, 0x76ecc529U, 0xc49537a2U, 0x9e214263U, 0x9b2b567dU, 0x6edca579U, 0x992f5e71U, 0xc2992fb6U, 0xb773e695U, 0x982d5a77U, 0xbc65caafU, 0x8f030605U, 0x85172e39U, 0x1f3e7c42U, 0xb475ea9fU, 0xf8edc72aU, 0x11224466U, 0x2e5cb8e4U, 0x00000000U, 0x254a94deU, 0x1c387048U, 0x2a54a8fcU, 0x3d7af48eU, 0x050a141eU, 0x4f9e21bfU, 0x7bf6f107U, 0xb279f28bU, 0x3264c8acU, 0x903d7a47U, 0xaf4386c5U, 0x19326456U, 0xa35bb6edU, 0xf7f3fb08U, 0x73e6d137U, 0x9d274e69U, 0x152a547eU, 0x74e8cd25U, 0xeec19f5eU, 0xca890f86U, 0x9f234665U, 0x0f1e3c22U, 0x1b366c5aU, 0x75eac923U, 0x86112233U, 0x84152a3fU, 0x9c254a6fU, 0x4a9435a1U, 0x97336655U, 0x1a34685cU, 0x65ca8943U, 0xf6f1ff0eU, 0xedc79354U, 0x09122436U, 0xbb6bd6bdU, 0x264c98d4U, 0x831b362dU, 0xebcb8b40U, 0x6fdea17fU, 0x811f3e21U, 0x04081018U, 0x6ad4b561U, 0x43861197U, 0x01020406U, 0x172e5c72U, 0xe1dfa37cU, 0x87132635U, 0xf5f7f304U, 0x8d070e09U, 0xe3dbab70U, 0x23468ccaU, 0x801d3a27U, 0x44880d85U, 0x162c5874U, 0x66cc8549U, 0x214284c6U, 0xfee1df3eU, 0xd5b773c4U, 0x3162c4a6U, 0xd9af43ecU, 0x356ad4beU, 0x18306050U, 0x0204080cU, 0x64c88d45U, 0xf2f9ef16U, 0xf1ffe31cU, 0x56ac45e9U, 0xcd871394U, 0x8219322bU, 0xc88d078aU, 0xba69d2bbU, 0xf0fde71aU, 0xefc39b58U, 0xe9cf834cU, 0xe8cd874aU, 0xfde7d334U, 0x890f1e11U, 0xd7b37bc8U, 0xc7933ba8U, 0xb577ee99U, 0xa455aaffU, 0x2f5ebce2U, 0x95376e59U, 0x13264c6aU, 0x0b162c3aU, 0xf3fbeb10U, 0xe0dda77aU, 0x376edcb2U, }; static const ulong32 T1[256] = { 0x53a7f5a6U, 0xbbd3d06bU, 0xd1e66ebfU, 0xe2713bd9U, 0xbdd0da67U, 0x45accf8aU, 0x9a4db329U, 0xf2790bf9U, 0x743a9ce8U, 0x8fc98c03U, 0x3f91417eU, 0xe5fc32d7U, 0x3c1e4478U, 0x8e478f01U, 0xa854e54dU, 0x67bda9ceU, 0x058c0f0aU, 0x57a5f9aeU, 0xf47a01f5U, 0xebfb20cbU, 0xc6635791U, 0x6db8b7daU, 0xa7ddf453U, 0xb5d4c277U, 0xd7e564b3U, 0x7bb38df6U, 0x97c5a433U, 0x61bea3c2U, 0x4fa9d19eU, 0x0d88171aU, 0x180c2830U, 0x59a2ebb2U, 0x723996e4U, 0xa3dff85bU, 0x5229f6a4U, 0xa9dae64fU, 0x562bfaacU, 0x4da8d79aU, 0x8bcb800bU, 0x984cb52dU, 0x964ba731U, 0x4422cc88U, 0x49aadb92U, 0x4824d890U, 0x82419b19U, 0xe0703dddU, 0x51a6f3a2U, 0xeff92cc3U, 0xb45ac175U, 0xd9e276afU, 0x7db087faU, 0x6c36b4d8U, 0xfa7d13e9U, 0xd5e462b7U, 0x6633aaccU, 0xe3ff38dbU, 0xc0605d9dU, 0x4020c080U, 0x10083020U, 0x0b8b1d16U, 0xbc5ed965U, 0x4babdd96U, 0xfe7f1fe1U, 0xf0780dfdU, 0xf87c15edU, 0x582ce8b0U, 0xae57ef41U, 0xb9d2d66fU, 0xa5dcf257U, 0xda6d73a9U, 0xfc7e19e5U, 0x1a0d2e34U, 0xa653f751U, 0x35945f6aU, 0x9bc3b02bU, 0x5028f0a0U, 0x4e27d29cU, 0x0c061418U, 0xbe5fdf61U, 0x47adc98eU, 0xce674f81U, 0xb85cd56dU, 0xaa55e349U, 0x9048ad3dU, 0x1c0e2438U, 0xa452f155U, 0xc9ea468fU, 0x84429115U, 0xb65bc771U, 0xba5dd369U, 0x6030a0c0U, 0xb058cd7dU, 0xa251fb59U, 0xb259cb79U, 0x783c88f0U, 0x9c4eb925U, 0x703890e0U, 0x098a1b12U, 0xe47231d5U, 0x28147850U, 0xd3e768bbU, 0x91c6ae3fU, 0xa1defe5fU, 0xa050fd5dU, 0x018e0302U, 0x39924b72U, 0xbfd1dc63U, 0xee772fc1U, 0x3b934d76U, 0x8a458309U, 0x299a7b52U, 0x81ce9e1fU, 0x5a2deeb4U, 0x06030a0cU, 0xc4625195U, 0x71b693e2U, 0x6fb9b1deU, 0x63bfa5c6U, 0x31965362U, 0xd66b67b1U, 0x7e3f82fcU, 0x0e07121cU, 0x24126c48U, 0x41aec382U, 0x80409d1dU, 0x6834b8d0U, 0x8c468905U, 0x7c3e84f8U, 0xabdbe04bU, 0x83cf981bU, 0xc5ec5297U, 0x85cc9217U, 0x9fc1bc23U, 0x5fa1e1beU, 0x9dc0ba27U, 0xb1d6ce7fU, 0x3a1d4e74U, 0xf5f402f7U, 0xc2615b99U, 0x763b9aecU, 0x20106040U, 0xadd8ea47U, 0xd0686dbdU, 0x5da0e7baU, 0x7fb181feU, 0x140a3c28U, 0xd2696bb9U, 0xd86c75adU, 0x9249ab39U, 0xe9fa26cfU, 0xec7629c5U, 0x95c4a237U, 0x219e6342U, 0x2b9b7d56U, 0xdc6e79a5U, 0x2f99715eU, 0x99c2b62fU, 0x73b795e6U, 0x2d98775aU, 0x65bcafcaU, 0x038f0506U, 0x1785392eU, 0x3e1f427cU, 0x75b49feaU, 0xedf82ac7U, 0x22116644U, 0x5c2ee4b8U, 0x00000000U, 0x4a25de94U, 0x381c4870U, 0x542afca8U, 0x7a3d8ef4U, 0x0a051e14U, 0x9e4fbf21U, 0xf67b07f1U, 0x79b28bf2U, 0x6432acc8U, 0x3d90477aU, 0x43afc586U, 0x32195664U, 0x5ba3edb6U, 0xf3f708fbU, 0xe67337d1U, 0x279d694eU, 0x2a157e54U, 0xe87425cdU, 0xc1ee5e9fU, 0x89ca860fU, 0x239f6546U, 0x1e0f223cU, 0x361b5a6cU, 0xea7523c9U, 0x11863322U, 0x15843f2aU, 0x259c6f4aU, 0x944aa135U, 0x33975566U, 0x341a5c68U, 0xca654389U, 0xf1f60effU, 0xc7ed5493U, 0x12093624U, 0x6bbbbdd6U, 0x4c26d498U, 0x1b832d36U, 0xcbeb408bU, 0xde6f7fa1U, 0x1f81213eU, 0x08041810U, 0xd46a61b5U, 0x86439711U, 0x02010604U, 0x2e17725cU, 0xdfe17ca3U, 0x13873526U, 0xf7f504f3U, 0x078d090eU, 0xdbe370abU, 0x4623ca8cU, 0x1d80273aU, 0x8844850dU, 0x2c167458U, 0xcc664985U, 0x4221c684U, 0xe1fe3edfU, 0xb7d5c473U, 0x6231a6c4U, 0xafd9ec43U, 0x6a35bed4U, 0x30185060U, 0x04020c08U, 0xc864458dU, 0xf9f216efU, 0xfff11ce3U, 0xac56e945U, 0x87cd9413U, 0x19822b32U, 0x8dc88a07U, 0x69babbd2U, 0xfdf01ae7U, 0xc3ef589bU, 0xcfe94c83U, 0xcde84a87U, 0xe7fd34d3U, 0x0f89111eU, 0xb3d7c87bU, 0x93c7a83bU, 0x77b599eeU, 0x55a4ffaaU, 0x5e2fe2bcU, 0x3795596eU, 0x26136a4cU, 0x160b3a2cU, 0xfbf310ebU, 0xdde07aa7U, 0x6e37b2dcU, }; static const ulong32 T2[256] = { 0xa6f5a753U, 0x6bd0d3bbU, 0xbf6ee6d1U, 0xd93b71e2U, 0x67dad0bdU, 0x8acfac45U, 0x29b34d9aU, 0xf90b79f2U, 0xe89c3a74U, 0x038cc98fU, 0x7e41913fU, 0xd732fce5U, 0x78441e3cU, 0x018f478eU, 0x4de554a8U, 0xcea9bd67U, 0x0a0f8c05U, 0xaef9a557U, 0xf5017af4U, 0xcb20fbebU, 0x915763c6U, 0xdab7b86dU, 0x53f4dda7U, 0x77c2d4b5U, 0xb364e5d7U, 0xf68db37bU, 0x33a4c597U, 0xc2a3be61U, 0x9ed1a94fU, 0x1a17880dU, 0x30280c18U, 0xb2eba259U, 0xe4963972U, 0x5bf8dfa3U, 0xa4f62952U, 0x4fe6daa9U, 0xacfa2b56U, 0x9ad7a84dU, 0x0b80cb8bU, 0x2db54c98U, 0x31a74b96U, 0x88cc2244U, 0x92dbaa49U, 0x90d82448U, 0x199b4182U, 0xdd3d70e0U, 0xa2f3a651U, 0xc32cf9efU, 0x75c15ab4U, 0xaf76e2d9U, 0xfa87b07dU, 0xd8b4366cU, 0xe9137dfaU, 0xb762e4d5U, 0xccaa3366U, 0xdb38ffe3U, 0x9d5d60c0U, 0x80c02040U, 0x20300810U, 0x161d8b0bU, 0x65d95ebcU, 0x96ddab4bU, 0xe11f7ffeU, 0xfd0d78f0U, 0xed157cf8U, 0xb0e82c58U, 0x41ef57aeU, 0x6fd6d2b9U, 0x57f2dca5U, 0xa9736ddaU, 0xe5197efcU, 0x342e0d1aU, 0x51f753a6U, 0x6a5f9435U, 0x2bb0c39bU, 0xa0f02850U, 0x9cd2274eU, 0x1814060cU, 0x61df5fbeU, 0x8ec9ad47U, 0x814f67ceU, 0x6dd55cb8U, 0x49e355aaU, 0x3dad4890U, 0x38240e1cU, 0x55f152a4U, 0x8f46eac9U, 0x15914284U, 0x71c75bb6U, 0x69d35dbaU, 0xc0a03060U, 0x7dcd58b0U, 0x59fb51a2U, 0x79cb59b2U, 0xf0883c78U, 0x25b94e9cU, 0xe0903870U, 0x121b8a09U, 0xd53172e4U, 0x50781428U, 0xbb68e7d3U, 0x3faec691U, 0x5ffedea1U, 0x5dfd50a0U, 0x02038e01U, 0x724b9239U, 0x63dcd1bfU, 0xc12f77eeU, 0x764d933bU, 0x0983458aU, 0x527b9a29U, 0x1f9ece81U, 0xb4ee2d5aU, 0x0c0a0306U, 0x955162c4U, 0xe293b671U, 0xdeb1b96fU, 0xc6a5bf63U, 0x62539631U, 0xb1676bd6U, 0xfc823f7eU, 0x1c12070eU, 0x486c1224U, 0x82c3ae41U, 0x1d9d4080U, 0xd0b83468U, 0x0589468cU, 0xf8843e7cU, 0x4be0dbabU, 0x1b98cf83U, 0x9752ecc5U, 0x1792cc85U, 0x23bcc19fU, 0xbee1a15fU, 0x27bac09dU, 0x7fced6b1U, 0x744e1d3aU, 0xf702f4f5U, 0x995b61c2U, 0xec9a3b76U, 0x40601020U, 0x47ead8adU, 0xbd6d68d0U, 0xbae7a05dU, 0xfe81b17fU, 0x283c0a14U, 0xb96b69d2U, 0xad756cd8U, 0x39ab4992U, 0xcf26fae9U, 0xc52976ecU, 0x37a2c495U, 0x42639e21U, 0x567d9b2bU, 0xa5796edcU, 0x5e71992fU, 0x2fb6c299U, 0xe695b773U, 0x5a77982dU, 0xcaafbc65U, 0x06058f03U, 0x2e398517U, 0x7c421f3eU, 0xea9fb475U, 0xc72af8edU, 0x44661122U, 0xb8e42e5cU, 0x00000000U, 0x94de254aU, 0x70481c38U, 0xa8fc2a54U, 0xf48e3d7aU, 0x141e050aU, 0x21bf4f9eU, 0xf1077bf6U, 0xf28bb279U, 0xc8ac3264U, 0x7a47903dU, 0x86c5af43U, 0x64561932U, 0xb6eda35bU, 0xfb08f7f3U, 0xd13773e6U, 0x4e699d27U, 0x547e152aU, 0xcd2574e8U, 0x9f5eeec1U, 0x0f86ca89U, 0x46659f23U, 0x3c220f1eU, 0x6c5a1b36U, 0xc92375eaU, 0x22338611U, 0x2a3f8415U, 0x4a6f9c25U, 0x35a14a94U, 0x66559733U, 0x685c1a34U, 0x894365caU, 0xff0ef6f1U, 0x9354edc7U, 0x24360912U, 0xd6bdbb6bU, 0x98d4264cU, 0x362d831bU, 0x8b40ebcbU, 0xa17f6fdeU, 0x3e21811fU, 0x10180408U, 0xb5616ad4U, 0x11974386U, 0x04060102U, 0x5c72172eU, 0xa37ce1dfU, 0x26358713U, 0xf304f5f7U, 0x0e098d07U, 0xab70e3dbU, 0x8cca2346U, 0x3a27801dU, 0x0d854488U, 0x5874162cU, 0x854966ccU, 0x84c62142U, 0xdf3efee1U, 0x73c4d5b7U, 0xc4a63162U, 0x43ecd9afU, 0xd4be356aU, 0x60501830U, 0x080c0204U, 0x8d4564c8U, 0xef16f2f9U, 0xe31cf1ffU, 0x45e956acU, 0x1394cd87U, 0x322b8219U, 0x078ac88dU, 0xd2bbba69U, 0xe71af0fdU, 0x9b58efc3U, 0x834ce9cfU, 0x874ae8cdU, 0xd334fde7U, 0x1e11890fU, 0x7bc8d7b3U, 0x3ba8c793U, 0xee99b577U, 0xaaffa455U, 0xbce22f5eU, 0x6e599537U, 0x4c6a1326U, 0x2c3a0b16U, 0xeb10f3fbU, 0xa77ae0ddU, 0xdcb2376eU, }; static const ulong32 T3[256] = { 0xf5a653a7U, 0xd06bbbd3U, 0x6ebfd1e6U, 0x3bd9e271U, 0xda67bdd0U, 0xcf8a45acU, 0xb3299a4dU, 0x0bf9f279U, 0x9ce8743aU, 0x8c038fc9U, 0x417e3f91U, 0x32d7e5fcU, 0x44783c1eU, 0x8f018e47U, 0xe54da854U, 0xa9ce67bdU, 0x0f0a058cU, 0xf9ae57a5U, 0x01f5f47aU, 0x20cbebfbU, 0x5791c663U, 0xb7da6db8U, 0xf453a7ddU, 0xc277b5d4U, 0x64b3d7e5U, 0x8df67bb3U, 0xa43397c5U, 0xa3c261beU, 0xd19e4fa9U, 0x171a0d88U, 0x2830180cU, 0xebb259a2U, 0x96e47239U, 0xf85ba3dfU, 0xf6a45229U, 0xe64fa9daU, 0xfaac562bU, 0xd79a4da8U, 0x800b8bcbU, 0xb52d984cU, 0xa731964bU, 0xcc884422U, 0xdb9249aaU, 0xd8904824U, 0x9b198241U, 0x3ddde070U, 0xf3a251a6U, 0x2cc3eff9U, 0xc175b45aU, 0x76afd9e2U, 0x87fa7db0U, 0xb4d86c36U, 0x13e9fa7dU, 0x62b7d5e4U, 0xaacc6633U, 0x38dbe3ffU, 0x5d9dc060U, 0xc0804020U, 0x30201008U, 0x1d160b8bU, 0xd965bc5eU, 0xdd964babU, 0x1fe1fe7fU, 0x0dfdf078U, 0x15edf87cU, 0xe8b0582cU, 0xef41ae57U, 0xd66fb9d2U, 0xf257a5dcU, 0x73a9da6dU, 0x19e5fc7eU, 0x2e341a0dU, 0xf751a653U, 0x5f6a3594U, 0xb02b9bc3U, 0xf0a05028U, 0xd29c4e27U, 0x14180c06U, 0xdf61be5fU, 0xc98e47adU, 0x4f81ce67U, 0xd56db85cU, 0xe349aa55U, 0xad3d9048U, 0x24381c0eU, 0xf155a452U, 0x468fc9eaU, 0x91158442U, 0xc771b65bU, 0xd369ba5dU, 0xa0c06030U, 0xcd7db058U, 0xfb59a251U, 0xcb79b259U, 0x88f0783cU, 0xb9259c4eU, 0x90e07038U, 0x1b12098aU, 0x31d5e472U, 0x78502814U, 0x68bbd3e7U, 0xae3f91c6U, 0xfe5fa1deU, 0xfd5da050U, 0x0302018eU, 0x4b723992U, 0xdc63bfd1U, 0x2fc1ee77U, 0x4d763b93U, 0x83098a45U, 0x7b52299aU, 0x9e1f81ceU, 0xeeb45a2dU, 0x0a0c0603U, 0x5195c462U, 0x93e271b6U, 0xb1de6fb9U, 0xa5c663bfU, 0x53623196U, 0x67b1d66bU, 0x82fc7e3fU, 0x121c0e07U, 0x6c482412U, 0xc38241aeU, 0x9d1d8040U, 0xb8d06834U, 0x89058c46U, 0x84f87c3eU, 0xe04babdbU, 0x981b83cfU, 0x5297c5ecU, 0x921785ccU, 0xbc239fc1U, 0xe1be5fa1U, 0xba279dc0U, 0xce7fb1d6U, 0x4e743a1dU, 0x02f7f5f4U, 0x5b99c261U, 0x9aec763bU, 0x60402010U, 0xea47add8U, 0x6dbdd068U, 0xe7ba5da0U, 0x81fe7fb1U, 0x3c28140aU, 0x6bb9d269U, 0x75add86cU, 0xab399249U, 0x26cfe9faU, 0x29c5ec76U, 0xa23795c4U, 0x6342219eU, 0x7d562b9bU, 0x79a5dc6eU, 0x715e2f99U, 0xb62f99c2U, 0x95e673b7U, 0x775a2d98U, 0xafca65bcU, 0x0506038fU, 0x392e1785U, 0x427c3e1fU, 0x9fea75b4U, 0x2ac7edf8U, 0x66442211U, 0xe4b85c2eU, 0x00000000U, 0xde944a25U, 0x4870381cU, 0xfca8542aU, 0x8ef47a3dU, 0x1e140a05U, 0xbf219e4fU, 0x07f1f67bU, 0x8bf279b2U, 0xacc86432U, 0x477a3d90U, 0xc58643afU, 0x56643219U, 0xedb65ba3U, 0x08fbf3f7U, 0x37d1e673U, 0x694e279dU, 0x7e542a15U, 0x25cde874U, 0x5e9fc1eeU, 0x860f89caU, 0x6546239fU, 0x223c1e0fU, 0x5a6c361bU, 0x23c9ea75U, 0x33221186U, 0x3f2a1584U, 0x6f4a259cU, 0xa135944aU, 0x55663397U, 0x5c68341aU, 0x4389ca65U, 0x0efff1f6U, 0x5493c7edU, 0x36241209U, 0xbdd66bbbU, 0xd4984c26U, 0x2d361b83U, 0x408bcbebU, 0x7fa1de6fU, 0x213e1f81U, 0x18100804U, 0x61b5d46aU, 0x97118643U, 0x06040201U, 0x725c2e17U, 0x7ca3dfe1U, 0x35261387U, 0x04f3f7f5U, 0x090e078dU, 0x70abdbe3U, 0xca8c4623U, 0x273a1d80U, 0x850d8844U, 0x74582c16U, 0x4985cc66U, 0xc6844221U, 0x3edfe1feU, 0xc473b7d5U, 0xa6c46231U, 0xec43afd9U, 0xbed46a35U, 0x50603018U, 0x0c080402U, 0x458dc864U, 0x16eff9f2U, 0x1ce3fff1U, 0xe945ac56U, 0x941387cdU, 0x2b321982U, 0x8a078dc8U, 0xbbd269baU, 0x1ae7fdf0U, 0x589bc3efU, 0x4c83cfe9U, 0x4a87cde8U, 0x34d3e7fdU, 0x111e0f89U, 0xc87bb3d7U, 0xa83b93c7U, 0x99ee77b5U, 0xffaa55a4U, 0xe2bc5e2fU, 0x596e3795U, 0x6a4c2613U, 0x3a2c160bU, 0x10ebfbf3U, 0x7aa7dde0U, 0xb2dc6e37U, }; static const ulong32 T4[256] = { 0xa7a7a7a7U, 0xd3d3d3d3U, 0xe6e6e6e6U, 0x71717171U, 0xd0d0d0d0U, 0xacacacacU, 0x4d4d4d4dU, 0x79797979U, 0x3a3a3a3aU, 0xc9c9c9c9U, 0x91919191U, 0xfcfcfcfcU, 0x1e1e1e1eU, 0x47474747U, 0x54545454U, 0xbdbdbdbdU, 0x8c8c8c8cU, 0xa5a5a5a5U, 0x7a7a7a7aU, 0xfbfbfbfbU, 0x63636363U, 0xb8b8b8b8U, 0xddddddddU, 0xd4d4d4d4U, 0xe5e5e5e5U, 0xb3b3b3b3U, 0xc5c5c5c5U, 0xbebebebeU, 0xa9a9a9a9U, 0x88888888U, 0x0c0c0c0cU, 0xa2a2a2a2U, 0x39393939U, 0xdfdfdfdfU, 0x29292929U, 0xdadadadaU, 0x2b2b2b2bU, 0xa8a8a8a8U, 0xcbcbcbcbU, 0x4c4c4c4cU, 0x4b4b4b4bU, 0x22222222U, 0xaaaaaaaaU, 0x24242424U, 0x41414141U, 0x70707070U, 0xa6a6a6a6U, 0xf9f9f9f9U, 0x5a5a5a5aU, 0xe2e2e2e2U, 0xb0b0b0b0U, 0x36363636U, 0x7d7d7d7dU, 0xe4e4e4e4U, 0x33333333U, 0xffffffffU, 0x60606060U, 0x20202020U, 0x08080808U, 0x8b8b8b8bU, 0x5e5e5e5eU, 0xababababU, 0x7f7f7f7fU, 0x78787878U, 0x7c7c7c7cU, 0x2c2c2c2cU, 0x57575757U, 0xd2d2d2d2U, 0xdcdcdcdcU, 0x6d6d6d6dU, 0x7e7e7e7eU, 0x0d0d0d0dU, 0x53535353U, 0x94949494U, 0xc3c3c3c3U, 0x28282828U, 0x27272727U, 0x06060606U, 0x5f5f5f5fU, 0xadadadadU, 0x67676767U, 0x5c5c5c5cU, 0x55555555U, 0x48484848U, 0x0e0e0e0eU, 0x52525252U, 0xeaeaeaeaU, 0x42424242U, 0x5b5b5b5bU, 0x5d5d5d5dU, 0x30303030U, 0x58585858U, 0x51515151U, 0x59595959U, 0x3c3c3c3cU, 0x4e4e4e4eU, 0x38383838U, 0x8a8a8a8aU, 0x72727272U, 0x14141414U, 0xe7e7e7e7U, 0xc6c6c6c6U, 0xdedededeU, 0x50505050U, 0x8e8e8e8eU, 0x92929292U, 0xd1d1d1d1U, 0x77777777U, 0x93939393U, 0x45454545U, 0x9a9a9a9aU, 0xcecececeU, 0x2d2d2d2dU, 0x03030303U, 0x62626262U, 0xb6b6b6b6U, 0xb9b9b9b9U, 0xbfbfbfbfU, 0x96969696U, 0x6b6b6b6bU, 0x3f3f3f3fU, 0x07070707U, 0x12121212U, 0xaeaeaeaeU, 0x40404040U, 0x34343434U, 0x46464646U, 0x3e3e3e3eU, 0xdbdbdbdbU, 0xcfcfcfcfU, 0xececececU, 0xccccccccU, 0xc1c1c1c1U, 0xa1a1a1a1U, 0xc0c0c0c0U, 0xd6d6d6d6U, 0x1d1d1d1dU, 0xf4f4f4f4U, 0x61616161U, 0x3b3b3b3bU, 0x10101010U, 0xd8d8d8d8U, 0x68686868U, 0xa0a0a0a0U, 0xb1b1b1b1U, 0x0a0a0a0aU, 0x69696969U, 0x6c6c6c6cU, 0x49494949U, 0xfafafafaU, 0x76767676U, 0xc4c4c4c4U, 0x9e9e9e9eU, 0x9b9b9b9bU, 0x6e6e6e6eU, 0x99999999U, 0xc2c2c2c2U, 0xb7b7b7b7U, 0x98989898U, 0xbcbcbcbcU, 0x8f8f8f8fU, 0x85858585U, 0x1f1f1f1fU, 0xb4b4b4b4U, 0xf8f8f8f8U, 0x11111111U, 0x2e2e2e2eU, 0x00000000U, 0x25252525U, 0x1c1c1c1cU, 0x2a2a2a2aU, 0x3d3d3d3dU, 0x05050505U, 0x4f4f4f4fU, 0x7b7b7b7bU, 0xb2b2b2b2U, 0x32323232U, 0x90909090U, 0xafafafafU, 0x19191919U, 0xa3a3a3a3U, 0xf7f7f7f7U, 0x73737373U, 0x9d9d9d9dU, 0x15151515U, 0x74747474U, 0xeeeeeeeeU, 0xcacacacaU, 0x9f9f9f9fU, 0x0f0f0f0fU, 0x1b1b1b1bU, 0x75757575U, 0x86868686U, 0x84848484U, 0x9c9c9c9cU, 0x4a4a4a4aU, 0x97979797U, 0x1a1a1a1aU, 0x65656565U, 0xf6f6f6f6U, 0xededededU, 0x09090909U, 0xbbbbbbbbU, 0x26262626U, 0x83838383U, 0xebebebebU, 0x6f6f6f6fU, 0x81818181U, 0x04040404U, 0x6a6a6a6aU, 0x43434343U, 0x01010101U, 0x17171717U, 0xe1e1e1e1U, 0x87878787U, 0xf5f5f5f5U, 0x8d8d8d8dU, 0xe3e3e3e3U, 0x23232323U, 0x80808080U, 0x44444444U, 0x16161616U, 0x66666666U, 0x21212121U, 0xfefefefeU, 0xd5d5d5d5U, 0x31313131U, 0xd9d9d9d9U, 0x35353535U, 0x18181818U, 0x02020202U, 0x64646464U, 0xf2f2f2f2U, 0xf1f1f1f1U, 0x56565656U, 0xcdcdcdcdU, 0x82828282U, 0xc8c8c8c8U, 0xbabababaU, 0xf0f0f0f0U, 0xefefefefU, 0xe9e9e9e9U, 0xe8e8e8e8U, 0xfdfdfdfdU, 0x89898989U, 0xd7d7d7d7U, 0xc7c7c7c7U, 0xb5b5b5b5U, 0xa4a4a4a4U, 0x2f2f2f2fU, 0x95959595U, 0x13131313U, 0x0b0b0b0bU, 0xf3f3f3f3U, 0xe0e0e0e0U, 0x37373737U, }; static const ulong32 T5[256] = { 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, }; /** * The round constants. */ static const ulong32 rc[] = { 0xa7d3e671U, 0xd0ac4d79U, 0x3ac991fcU, 0x1e4754bdU, 0x8ca57afbU, 0x63b8ddd4U, 0xe5b3c5beU, 0xa9880ca2U, 0x39df29daU, 0x2ba8cb4cU, 0x4b22aa24U, 0x4170a6f9U, 0x5ae2b036U, 0x7de433ffU, 0x6020088bU, 0x5eab7f78U, 0x7c2c57d2U, 0xdc6d7e0dU, 0x5394c328U, }; #endif /** Initialize the Anubis block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #else int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #endif { int N, R, i, pos, r; ulong32 kappa[MAX_N]; ulong32 inter[MAX_N] = { 0 }; /* initialize as all zeroes */ ulong32 v, K0, K1, K2, K3; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* Valid sizes (in bytes) are 16, 20, 24, 28, 32, 36, and 40. */ if ((keylen & 3) || (keylen < 16) || (keylen > 40)) { return CRYPT_INVALID_KEYSIZE; } skey->anubis.keyBits = keylen*8; /* * determine the N length parameter: * (N.B. it is assumed that the key length is valid!) */ N = skey->anubis.keyBits >> 5; /* * determine number of rounds from key size: */ skey->anubis.R = R = 8 + N; if (num_rounds != 0 && num_rounds != skey->anubis.R) { return CRYPT_INVALID_ROUNDS; } /* * map cipher key to initial key state (mu): */ for (i = 0, pos = 0; i < N; i++, pos += 4) { kappa[i] = (((ulong32)key[pos ]) << 24) ^ (((ulong32)key[pos + 1]) << 16) ^ (((ulong32)key[pos + 2]) << 8) ^ (((ulong32)key[pos + 3]) ); } /* * generate R + 1 round keys: */ for (r = 0; r <= R; r++) { /* * generate r-th round key K^r: */ K0 = T4[(kappa[N - 1] >> 24) & 0xff]; K1 = T4[(kappa[N - 1] >> 16) & 0xff]; K2 = T4[(kappa[N - 1] >> 8) & 0xff]; K3 = T4[(kappa[N - 1] ) & 0xff]; for (i = N - 2; i >= 0; i--) { K0 = T4[(kappa[i] >> 24) & 0xff] ^ (T5[(K0 >> 24) & 0xff] & 0xff000000U) ^ (T5[(K0 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K0 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K0 ) & 0xff] & 0x000000ffU); K1 = T4[(kappa[i] >> 16) & 0xff] ^ (T5[(K1 >> 24) & 0xff] & 0xff000000U) ^ (T5[(K1 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K1 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K1 ) & 0xff] & 0x000000ffU); K2 = T4[(kappa[i] >> 8) & 0xff] ^ (T5[(K2 >> 24) & 0xff] & 0xff000000U) ^ (T5[(K2 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K2 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K2 ) & 0xff] & 0x000000ffU); K3 = T4[(kappa[i] ) & 0xff] ^ (T5[(K3 >> 24) & 0xff] & 0xff000000U) ^ (T5[(K3 >> 16) & 0xff] & 0x00ff0000U) ^ (T5[(K3 >> 8) & 0xff] & 0x0000ff00U) ^ (T5[(K3 ) & 0xff] & 0x000000ffU); } /* -- this is the code to use with the large U tables: K0 = K1 = K2 = K3 = 0; for (i = 0; i < N; i++) { K0 ^= U[i][(kappa[i] >> 24) & 0xff]; K1 ^= U[i][(kappa[i] >> 16) & 0xff]; K2 ^= U[i][(kappa[i] >> 8) & 0xff]; K3 ^= U[i][(kappa[i] ) & 0xff]; } */ skey->anubis.roundKeyEnc[r][0] = K0; skey->anubis.roundKeyEnc[r][1] = K1; skey->anubis.roundKeyEnc[r][2] = K2; skey->anubis.roundKeyEnc[r][3] = K3; /* * compute kappa^{r+1} from kappa^r: */ if (r == R) { break; } for (i = 0; i < N; i++) { int j = i; inter[i] = T0[(kappa[j--] >> 24) & 0xff]; if (j < 0) j = N - 1; inter[i] ^= T1[(kappa[j--] >> 16) & 0xff]; if (j < 0) j = N - 1; inter[i] ^= T2[(kappa[j--] >> 8) & 0xff]; if (j < 0) j = N - 1; inter[i] ^= T3[(kappa[j ] ) & 0xff]; } kappa[0] = inter[0] ^ rc[r]; for (i = 1; i < N; i++) { kappa[i] = inter[i]; } } /* * generate inverse key schedule: K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}): */ for (i = 0; i < 4; i++) { skey->anubis.roundKeyDec[0][i] = skey->anubis.roundKeyEnc[R][i]; skey->anubis.roundKeyDec[R][i] = skey->anubis.roundKeyEnc[0][i]; } for (r = 1; r < R; r++) { for (i = 0; i < 4; i++) { v = skey->anubis.roundKeyEnc[R - r][i]; skey->anubis.roundKeyDec[r][i] = T0[T4[(v >> 24) & 0xff] & 0xff] ^ T1[T4[(v >> 16) & 0xff] & 0xff] ^ T2[T4[(v >> 8) & 0xff] & 0xff] ^ T3[T4[(v ) & 0xff] & 0xff]; } } return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int err; err = s_anubis_setup(key, keylen, num_rounds, skey); burn_stack(sizeof(int) * 5 + sizeof(ulong32) * (MAX_N + MAX_N + 5)); return err; } #endif static void anubis_crypt(const unsigned char *plaintext, unsigned char *ciphertext, const ulong32 roundKey[18 + 1][4], int R) { int i, pos, r; ulong32 state[4]; ulong32 inter[4]; /* * map plaintext block to cipher state (mu) * and add initial round key (sigma[K^0]): */ for (i = 0, pos = 0; i < 4; i++, pos += 4) { state[i] = (((ulong32)plaintext[pos ]) << 24) ^ (((ulong32)plaintext[pos + 1]) << 16) ^ (((ulong32)plaintext[pos + 2]) << 8) ^ (((ulong32)plaintext[pos + 3]) ) ^ roundKey[0][i]; } /* * R - 1 full rounds: */ for (r = 1; r < R; r++) { inter[0] = T0[(state[0] >> 24) & 0xff] ^ T1[(state[1] >> 24) & 0xff] ^ T2[(state[2] >> 24) & 0xff] ^ T3[(state[3] >> 24) & 0xff] ^ roundKey[r][0]; inter[1] = T0[(state[0] >> 16) & 0xff] ^ T1[(state[1] >> 16) & 0xff] ^ T2[(state[2] >> 16) & 0xff] ^ T3[(state[3] >> 16) & 0xff] ^ roundKey[r][1]; inter[2] = T0[(state[0] >> 8) & 0xff] ^ T1[(state[1] >> 8) & 0xff] ^ T2[(state[2] >> 8) & 0xff] ^ T3[(state[3] >> 8) & 0xff] ^ roundKey[r][2]; inter[3] = T0[(state[0] ) & 0xff] ^ T1[(state[1] ) & 0xff] ^ T2[(state[2] ) & 0xff] ^ T3[(state[3] ) & 0xff] ^ roundKey[r][3]; state[0] = inter[0]; state[1] = inter[1]; state[2] = inter[2]; state[3] = inter[3]; } /* * last round: */ inter[0] = (T0[(state[0] >> 24) & 0xff] & 0xff000000U) ^ (T1[(state[1] >> 24) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] >> 24) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] >> 24) & 0xff] & 0x000000ffU) ^ roundKey[R][0]; inter[1] = (T0[(state[0] >> 16) & 0xff] & 0xff000000U) ^ (T1[(state[1] >> 16) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] >> 16) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] >> 16) & 0xff] & 0x000000ffU) ^ roundKey[R][1]; inter[2] = (T0[(state[0] >> 8) & 0xff] & 0xff000000U) ^ (T1[(state[1] >> 8) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] >> 8) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] >> 8) & 0xff] & 0x000000ffU) ^ roundKey[R][2]; inter[3] = (T0[(state[0] ) & 0xff] & 0xff000000U) ^ (T1[(state[1] ) & 0xff] & 0x00ff0000U) ^ (T2[(state[2] ) & 0xff] & 0x0000ff00U) ^ (T3[(state[3] ) & 0xff] & 0x000000ffU) ^ roundKey[R][3]; /* * map cipher state to ciphertext block (mu^{-1}): */ for (i = 0, pos = 0; i < 4; i++, pos += 4) { ulong32 w = inter[i]; ciphertext[pos ] = (unsigned char)(w >> 24); ciphertext[pos + 1] = (unsigned char)(w >> 16); ciphertext[pos + 2] = (unsigned char)(w >> 8); ciphertext[pos + 3] = (unsigned char)(w ); } } /** Encrypts a block of text with Anubis @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); if (skey->anubis.R < 12 || skey->anubis.R > 18) { return CRYPT_INVALID_ROUNDS; } anubis_crypt(pt, ct, skey->anubis.roundKeyEnc, skey->anubis.R); return CRYPT_OK; } /** Decrypts a block of text with Anubis @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); if (skey->anubis.R < 12 || skey->anubis.R > 18) { return CRYPT_INVALID_ROUNDS; } anubis_crypt(ct, pt, skey->anubis.roundKeyDec, skey->anubis.R); return CRYPT_OK; } /** Performs a self-test of the Anubis block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int anubis_test(void) { #if !defined(LTC_TEST) return CRYPT_NOP; #else static const struct test { int keylen; unsigned char pt[16], ct[16], key[40]; } tests[] = { #ifndef LTC_ANUBIS_TWEAK /**** ORIGINAL LTC_ANUBIS ****/ /* 128 bit keys */ { 16, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xF0, 0x68, 0x60, 0xFC, 0x67, 0x30, 0xE8, 0x18, 0xF1, 0x32, 0xC7, 0x8A, 0xF4, 0x13, 0x2A, 0xFE }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 16, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xA8, 0x66, 0x84, 0x80, 0x07, 0x74, 0x5C, 0x89, 0xFC, 0x5E, 0xB5, 0xBA, 0xD4, 0xFE, 0x32, 0x6D }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 160-bit keys */ { 20, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xBD, 0x5E, 0x32, 0xBE, 0x51, 0x67, 0xA8, 0xE2, 0x72, 0xD7, 0x95, 0x0F, 0x83, 0xC6, 0x8C, 0x31 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 20, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x4C, 0x1F, 0x86, 0x2E, 0x11, 0xEB, 0xCE, 0xEB, 0xFE, 0xB9, 0x73, 0xC9, 0xDF, 0xEF, 0x7A, 0xDB }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 192-bit keys */ { 24, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x17, 0xAC, 0x57, 0x44, 0x9D, 0x59, 0x61, 0x66, 0xD0, 0xC7, 0x9E, 0x04, 0x7C, 0xC7, 0x58, 0xF0 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 24, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x71, 0x52, 0xB4, 0xEB, 0x1D, 0xAA, 0x36, 0xFD, 0x57, 0x14, 0x5F, 0x57, 0x04, 0x9F, 0x70, 0x74 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 224-bit keys */ { 28, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xA2, 0xF0, 0xA6, 0xB9, 0x17, 0x93, 0x2A, 0x3B, 0xEF, 0x08, 0xE8, 0x7A, 0x58, 0xD6, 0xF8, 0x53 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 28, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xF0, 0xCA, 0xFC, 0x78, 0x8B, 0x4B, 0x4E, 0x53, 0x8B, 0xC4, 0x32, 0x6A, 0xF5, 0xB9, 0x1B, 0x5F }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 256-bit keys */ { 32, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xE0, 0x86, 0xAC, 0x45, 0x6B, 0x3C, 0xE5, 0x13, 0xED, 0xF5, 0xDF, 0xDD, 0xD6, 0x3B, 0x71, 0x93 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 32, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x50, 0x01, 0xB9, 0xF5, 0x21, 0xC1, 0xC1, 0x29, 0x00, 0xD5, 0xEC, 0x98, 0x2B, 0x9E, 0xE8, 0x21 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 288-bit keys */ { 36, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xE8, 0xF4, 0xAF, 0x2B, 0x21, 0xA0, 0x87, 0x9B, 0x41, 0x95, 0xB9, 0x71, 0x75, 0x79, 0x04, 0x7C }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 36, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xE6, 0xA6, 0xA5, 0xBC, 0x8B, 0x63, 0x6F, 0xE2, 0xBD, 0xA7, 0xA7, 0x53, 0xAB, 0x40, 0x22, 0xE0 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 320-bit keys */ { 40, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x17, 0x04, 0xD7, 0x2C, 0xC6, 0x85, 0x76, 0x02, 0x4B, 0xCC, 0x39, 0x80, 0xD8, 0x22, 0xEA, 0xA4 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 40, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x7A, 0x41, 0xE6, 0x7D, 0x4F, 0xD8, 0x64, 0xF0, 0x44, 0xA8, 0x3C, 0x73, 0x81, 0x7E, 0x53, 0xD8 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } #else /**** Tweaked LTC_ANUBIS ****/ /* 128 bit keys */ { 16, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB8, 0x35, 0xBD, 0xC3, 0x34, 0x82, 0x9D, 0x83, 0x71, 0xBF, 0xA3, 0x71, 0xE4, 0xB3, 0xC4, 0xFD }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 16, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xE6, 0x14, 0x1E, 0xAF, 0xEB, 0xE0, 0x59, 0x3C, 0x48, 0xE1, 0xCD, 0xF2, 0x1B, 0xBA, 0xA1, 0x89 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 160-bit keys */ { 20, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x97, 0x59, 0x79, 0x4B, 0x5C, 0xA0, 0x70, 0x73, 0x24, 0xEF, 0xB3, 0x58, 0x67, 0xCA, 0xD4, 0xB3 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 20, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB8, 0x0D, 0xFB, 0x9B, 0xE4, 0xA1, 0x58, 0x87, 0xB3, 0x76, 0xD5, 0x02, 0x18, 0x95, 0xC1, 0x2E }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 192-bit keys */ { 24, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x7D, 0x62, 0x3B, 0x52, 0xC7, 0x4C, 0x64, 0xD8, 0xEB, 0xC7, 0x2D, 0x57, 0x97, 0x85, 0x43, 0x8F }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 24, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB1, 0x0A, 0x59, 0xDD, 0x5D, 0x5D, 0x8D, 0x67, 0xEC, 0xEE, 0x4A, 0xC4, 0xBE, 0x4F, 0xA8, 0x4F }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 224-bit keys */ { 28, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x68, 0x9E, 0x05, 0x94, 0x6A, 0x94, 0x43, 0x8F, 0xE7, 0x8E, 0x37, 0x3D, 0x24, 0x97, 0x92, 0xF5 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 28, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xDD, 0xB7, 0xB0, 0xB4, 0xE9, 0xB4, 0x9B, 0x9C, 0x38, 0x20, 0x25, 0x0B, 0x47, 0xC2, 0x1F, 0x89 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 256-bit keys */ { 32, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x96, 0x00, 0xF0, 0x76, 0x91, 0x69, 0x29, 0x87, 0xF5, 0xE5, 0x97, 0xDB, 0xDB, 0xAF, 0x1B, 0x0A }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 32, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x69, 0x9C, 0xAF, 0xDD, 0x94, 0xC7, 0xBC, 0x60, 0x44, 0xFE, 0x02, 0x05, 0x8A, 0x6E, 0xEF, 0xBD }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 288-bit keys */ { 36, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x0F, 0xC7, 0xA2, 0xC0, 0x11, 0x17, 0xAC, 0x43, 0x52, 0x5E, 0xDF, 0x6C, 0xF3, 0x96, 0x33, 0x6C }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 36, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xAD, 0x08, 0x4F, 0xED, 0x55, 0xA6, 0x94, 0x3E, 0x7E, 0x5E, 0xED, 0x05, 0xA1, 0x9D, 0x41, 0xB4 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, /* 320-bit keys */ { 40, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xFE, 0xE2, 0x0E, 0x2A, 0x9D, 0xC5, 0x83, 0xBA, 0xA3, 0xA6, 0xD6, 0xA6, 0xF2, 0xE8, 0x06, 0xA5 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { 40, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x86, 0x3D, 0xCC, 0x4A, 0x60, 0x34, 0x9C, 0x28, 0xA7, 0xDA, 0xA4, 0x3B, 0x0A, 0xD7, 0xFD, 0xC7 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } } #endif }; int x, y; unsigned char buf[2][16]; symmetric_key skey; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { anubis_setup(tests[x].key, tests[x].keylen, 0, &skey); anubis_ecb_encrypt(tests[x].pt, buf[0], &skey); anubis_ecb_decrypt(buf[0], buf[1], &skey); if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis Encrypt", x) || compare_testvector(buf[1], 16, tests[x].pt, 16, "Anubis Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } for (y = 0; y < 1000; y++) anubis_ecb_encrypt(buf[0], buf[0], &skey); for (y = 0; y < 1000; y++) anubis_ecb_decrypt(buf[0], buf[0], &skey); if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis 1000", 1000)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void anubis_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int anubis_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize >= 40) { *keysize = 40; } else if (*keysize >= 36) { *keysize = 36; } else if (*keysize >= 32) { *keysize = 32; } else if (*keysize >= 28) { *keysize = 28; } else if (*keysize >= 24) { *keysize = 24; } else if (*keysize >= 20) { *keysize = 20; } else if (*keysize >= 16) { *keysize = 16; } else { return CRYPT_INVALID_KEYSIZE; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/blowfish.c000066400000000000000000000650531464416617300236330ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file blowfish.c Implementation of the Blowfish block cipher, Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_BLOWFISH const struct ltc_cipher_descriptor blowfish_desc = { "blowfish", 0, 8, 56, 8, 16, &blowfish_setup, &blowfish_ecb_encrypt, &blowfish_ecb_decrypt, &blowfish_test, &blowfish_done, &blowfish_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 ORIG_P[16 + 2] = { 0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL, 0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL, 0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL, 0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL, 0x9216D5D9UL, 0x8979FB1BUL }; static const ulong32 ORIG_S[4][256] = { { 0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL, 0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL, 0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL, 0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL, 0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL, 0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL, 0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL, 0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL, 0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL, 0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL, 0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL, 0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL, 0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL, 0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL, 0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL, 0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL, 0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL, 0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL, 0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL, 0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL, 0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL, 0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL, 0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL, 0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL, 0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL, 0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL, 0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL, 0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL, 0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL, 0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL, 0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL, 0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL, 0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL, 0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL, 0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL, 0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL, 0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL, 0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL, 0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL, 0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL, 0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL, 0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL, 0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL, 0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL, 0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL, 0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL, 0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL, 0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL, 0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL, 0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL, 0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL, 0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL, 0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL, 0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL, 0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL, 0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL, 0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL, 0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL, 0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL, 0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL, 0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL, 0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL, 0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL, 0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL }, { 0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL, 0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL, 0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL, 0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL, 0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL, 0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL, 0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL, 0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL, 0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL, 0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL, 0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL, 0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL, 0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL, 0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL, 0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL, 0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL, 0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL, 0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL, 0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL, 0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL, 0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL, 0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL, 0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL, 0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL, 0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL, 0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL, 0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL, 0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL, 0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL, 0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL, 0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL, 0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL, 0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL, 0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL, 0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL, 0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL, 0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL, 0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL, 0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL, 0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL, 0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL, 0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL, 0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL, 0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL, 0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL, 0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL, 0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL, 0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL, 0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL, 0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL, 0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL, 0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL, 0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL, 0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL, 0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL, 0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL, 0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL, 0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL, 0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL, 0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL, 0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL, 0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL, 0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL, 0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL }, { 0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL, 0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL, 0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL, 0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL, 0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL, 0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL, 0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL, 0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL, 0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL, 0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL, 0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL, 0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL, 0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL, 0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL, 0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL, 0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL, 0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL, 0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL, 0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL, 0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL, 0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL, 0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL, 0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL, 0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL, 0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL, 0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL, 0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL, 0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL, 0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL, 0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL, 0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL, 0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL, 0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL, 0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL, 0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL, 0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL, 0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL, 0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL, 0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL, 0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL, 0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL, 0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL, 0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL, 0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL, 0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL, 0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL, 0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL, 0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL, 0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL, 0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL, 0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL, 0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL, 0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL, 0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL, 0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL, 0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL, 0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL, 0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL, 0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL, 0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL, 0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL, 0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL, 0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL, 0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL }, { 0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL, 0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL, 0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL, 0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL, 0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL, 0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL, 0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL, 0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL, 0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL, 0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL, 0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL, 0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL, 0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL, 0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL, 0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL, 0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL, 0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL, 0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL, 0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL, 0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL, 0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL, 0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL, 0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL, 0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL, 0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL, 0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL, 0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL, 0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL, 0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL, 0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL, 0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL, 0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL, 0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL, 0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL, 0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL, 0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL, 0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL, 0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL, 0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL, 0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL, 0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL, 0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL, 0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL, 0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL, 0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL, 0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL, 0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL, 0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL, 0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL, 0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL, 0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL, 0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL, 0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL, 0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL, 0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL, 0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL, 0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL, 0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL, 0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL, 0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL, 0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL, 0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL, 0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL, 0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL } }; #ifndef __GNUC__ #define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)] #else #define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)] #endif static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *skey) { int rounds; ulong32 l, r; #ifndef __GNUC__ const ulong32 *S1, *S2, *S3, *S4; S1 = skey->blowfish.S[0]; S2 = skey->blowfish.S[1]; S3 = skey->blowfish.S[2]; S4 = skey->blowfish.S[3]; #endif l = *L; r = *R; /* do 16 rounds */ for (rounds = 0; rounds < 16; ) { l ^= skey->blowfish.K[rounds++]; r ^= F(l); r ^= skey->blowfish.K[rounds++]; l ^= F(r); l ^= skey->blowfish.K[rounds++]; r ^= F(l); r ^= skey->blowfish.K[rounds++]; l ^= F(r); } /* last keying */ l ^= skey->blowfish.K[16]; r ^= skey->blowfish.K[17]; *L = r; *R = l; } void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey) { unsigned long i; ulong32 *d = data; for (i = 0; i < blocks; ++i) { s_blowfish_encipher(d, d + 1, skey); d += 2; } } static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur) { unsigned int z; int y = *cur; ulong32 ret = 0; for (z = 0; z < 4; z++) { ret = (ret << 8) | ((ulong32)d[y++] & 255); if (y == dlen) { y = 0; } } *cur = y; return ret; } /** Expand the Blowfish internal state @param key The symmetric key you wish to pass @param keylen The key length in bytes @param data The additional data you wish to pass (can be NULL) @param datalen The additional data length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int blowfish_expand(const unsigned char *key, int keylen, const unsigned char *data, int datalen, symmetric_key *skey) { ulong32 x, y, A, B[2]; int i; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* load in key bytes (Supplied by David Hopwood) */ i = 0; for (x = 0; x < 18; x++) { A = s_blowfish_stream2word(key, keylen, &i); skey->blowfish.K[x] ^= A; } i = 0; B[0] = 0; B[1] = 0; for (x = 0; x < 18; x += 2) { if (data != NULL) { B[0] ^= s_blowfish_stream2word(data, datalen, &i); B[1] ^= s_blowfish_stream2word(data, datalen, &i); } /* encrypt it */ s_blowfish_encipher(&B[0], &B[1], skey); /* copy it */ skey->blowfish.K[x] = B[0]; skey->blowfish.K[x+1] = B[1]; } /* encrypt S array */ for (x = 0; x < 4; x++) { for (y = 0; y < 256; y += 2) { if (data != NULL) { B[0] ^= s_blowfish_stream2word(data, datalen, &i); B[1] ^= s_blowfish_stream2word(data, datalen, &i); } /* encrypt it */ s_blowfish_encipher(&B[0], &B[1], skey); /* copy it */ skey->blowfish.S[x][y] = B[0]; skey->blowfish.S[x][y+1] = B[1]; } } #ifdef LTC_CLEAN_STACK zeromem(B, sizeof(B)); #endif return CRYPT_OK; } /** Initialize the Blowfish block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { /* check key length */ if (keylen < 8 || keylen > 56) { return CRYPT_INVALID_KEYSIZE; } /* check rounds */ if (num_rounds != 0 && num_rounds != 16) { return CRYPT_INVALID_ROUNDS; } return blowfish_setup_with_data(key, keylen, NULL, 0, skey); } /** Alternative initialize of the Blowfish block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param data The additional data you wish to pass (can be NULL) @param datalen The additional data length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int blowfish_setup_with_data(const unsigned char *key, int keylen, const unsigned char *data, int datalen, symmetric_key *skey) { XMEMCPY(skey->blowfish.K, ORIG_P, sizeof(ORIG_P)); XMEMCPY(skey->blowfish.S, ORIG_S, sizeof(ORIG_S)); return blowfish_expand(key, keylen, data, datalen, skey); } /** Encrypts a block of text with Blowfish @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 L, R; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); /* load it */ LOAD32H(L, &pt[0]); LOAD32H(R, &pt[4]); s_blowfish_encipher(&L, &R, skey); /* store */ STORE32H(L, &ct[0]); STORE32H(R, &ct[4]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_blowfish_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(ulong32) * 2 + sizeof(int)); return err; } #endif /** Decrypts a block of text with Blowfish @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 L, R; int r; #ifndef __GNUC__ const ulong32 *S1, *S2, *S3, *S4; #endif LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); #ifndef __GNUC__ S1 = skey->blowfish.S[0]; S2 = skey->blowfish.S[1]; S3 = skey->blowfish.S[2]; S4 = skey->blowfish.S[3]; #endif /* load it */ LOAD32H(R, &ct[0]); LOAD32H(L, &ct[4]); /* undo last keying */ R ^= skey->blowfish.K[17]; L ^= skey->blowfish.K[16]; /* do 16 rounds */ for (r = 15; r > 0; ) { L ^= F(R); R ^= skey->blowfish.K[r--]; R ^= F(L); L ^= skey->blowfish.K[r--]; L ^= F(R); R ^= skey->blowfish.K[r--]; R ^= F(L); L ^= skey->blowfish.K[r--]; } /* store */ STORE32H(L, &pt[0]); STORE32H(R, &pt[4]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_blowfish_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(ulong32) * 2 + sizeof(int)); return err; } #endif /** Performs a self-test of the Blowfish block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int blowfish_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else int err; symmetric_key key; static const struct { unsigned char key[8], pt[8], ct[8]; } tests[] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78} }, { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, { 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A} }, { { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, { 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2} } }; unsigned char tmp[2][8]; int x, y; for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { /* setup key */ if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) { return err; } /* encrypt and decrypt */ blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key); blowfish_ecb_decrypt(tmp[0], tmp[1], &key); /* compare */ if ((compare_testvector(tmp[0], 8, tests[x].ct, 8, "Blowfish Encrypt", x) != 0) || (compare_testvector(tmp[1], 8, tests[x].pt, 8, "Blowfish Decrypt", x) != 0)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void blowfish_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int blowfish_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 8) { return CRYPT_INVALID_KEYSIZE; } if (*keysize > 56) { *keysize = 56; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/camellia.c000066400000000000000000000701251464416617300235610ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file camellia.c Implementation by Tom St Denis of Elliptic Semiconductor */ #include "tomcrypt_private.h" #ifdef LTC_CAMELLIA const struct ltc_cipher_descriptor camellia_desc = { "camellia", 23, 16, 32, 16, 18, &camellia_setup, &camellia_ecb_encrypt, &camellia_ecb_decrypt, &camellia_test, &camellia_done, &camellia_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 SP1110[] = { 0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100, 0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00, 0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00, 0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700, 0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100, 0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200, 0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300, 0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00, 0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00, 0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400, 0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00, }; static const ulong32 SP0222[] = { 0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242, 0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434, 0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a, 0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf, 0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323, 0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5, 0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666, 0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c, 0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575, 0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949, 0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393, 0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d, }; static const ulong32 SP3033[] = { 0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090, 0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d, 0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696, 0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb, 0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8, 0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969, 0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999, 0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717, 0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d, 0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252, 0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f, }; static const ulong32 SP4404[] = { 0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b, 0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004, 0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064, 0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063, 0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1, 0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad, 0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093, 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd, 0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099, 0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050, 0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2, 0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa, 0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068, 0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e, }; static const ulong64 key_sigma[] = { CONST64(0xA09E667F3BCC908B), CONST64(0xB67AE8584CAA73B2), CONST64(0xC6EF372FE94F82BE), CONST64(0x54FF53A5F1D36F1C), CONST64(0x10E527FADE682D1D), CONST64(0xB05688C2B3E6C1FD) }; static ulong64 F(ulong64 x) { ulong32 D, U; #define loc(i) ((8-i)*8) D = SP1110[(x >> loc(8)) & 0xFF] ^ SP0222[(x >> loc(5)) & 0xFF] ^ SP3033[(x >> loc(6)) & 0xFF] ^ SP4404[(x >> loc(7)) & 0xFF]; U = SP1110[(x >> loc(1)) & 0xFF] ^ SP0222[(x >> loc(2)) & 0xFF] ^ SP3033[(x >> loc(3)) & 0xFF] ^ SP4404[(x >> loc(4)) & 0xFF]; D ^= U; U = D ^ RORc(U, 8); return ((ulong64)U) | (((ulong64)D) << CONST64(32)); } static void rot_128(const unsigned char *in, unsigned count, unsigned char *out) { unsigned x, w, b; w = count >> 3; b = count & 7; for (x = 0; x < 16; x++) { out[x] = (in[(x+w)&15] << b) | (in[(x+w+1)&15] >> (8 - b)); } } int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { unsigned char T[48], kA[16], kB[16], kR[16], kL[16]; int x; ulong64 A, B; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* Valid sizes (in bytes) are 16, 24, 32 */ if (keylen != 16 && keylen != 24 && keylen != 32) { return CRYPT_INVALID_KEYSIZE; } /* number of rounds */ skey->camellia.R = (keylen == 16) ? 18 : 24; if (num_rounds != 0 && num_rounds != skey->camellia.R) { return CRYPT_INVALID_ROUNDS; } /* expand key */ if (keylen == 16) { for (x = 0; x < 16; x++) { T[x] = key[x]; T[x + 16] = 0; } } else if (keylen == 24) { for (x = 0; x < 24; x++) { T[x] = key[x]; } for (x = 24; x < 32; x++) { T[x] = key[x-8] ^ 0xFF; } } else { for (x = 0; x < 32; x++) { T[x] = key[x]; } } for (x = 0; x < 16; x++) { kL[x] = T[x]; kR[x] = T[x + 16]; } for (x = 32; x < 48; x++) { T[x] = T[x - 32] ^ T[x - 16]; } /* first two rounds */ LOAD64H(A, T+32); LOAD64H(B, T+40); B ^= F(A ^ key_sigma[0]); A ^= F(B ^ key_sigma[1]); STORE64H(A, T+32); STORE64H(B, T+40); /* xor kL in */ for (x = 0; x < 16; x++) { T[x+32] ^= kL[x]; } /* next two rounds */ LOAD64H(A, T+32); LOAD64H(B, T+40); B ^= F(A ^ key_sigma[2]); A ^= F(B ^ key_sigma[3]); STORE64H(A, T+32); STORE64H(B, T+40); /* grab KA */ for (x = 0; x < 16; x++) { kA[x] = T[x+32]; } /* xor kR in */ for (x = 0; x < 16; x++) { T[x+32] ^= kR[x]; } if (keylen == 16) { /* grab whitening keys kw1 and kw2 */ LOAD64H(skey->camellia.kw[0], kL); LOAD64H(skey->camellia.kw[1], kL+8); /* k1-k2 */ LOAD64H(skey->camellia.k[0], kA); LOAD64H(skey->camellia.k[1], kA+8); /* rotate kL by 15, k3/k4 */ rot_128(kL, 15, T+32); LOAD64H(skey->camellia.k[2], T+32); LOAD64H(skey->camellia.k[3], T+40); /* rotate kA by 15, k5/k6 */ rot_128(kA, 15, T+32); LOAD64H(skey->camellia.k[4], T+32); LOAD64H(skey->camellia.k[5], T+40); /* rotate kA by 30, kl1, kl2 */ rot_128(kA, 30, T+32); LOAD64H(skey->camellia.kl[0], T+32); LOAD64H(skey->camellia.kl[1], T+40); /* rotate kL by 45, k7/k8 */ rot_128(kL, 45, T+32); LOAD64H(skey->camellia.k[6], T+32); LOAD64H(skey->camellia.k[7], T+40); /* rotate kA by 45, k9/k10 */ rot_128(kA, 45, T+32); LOAD64H(skey->camellia.k[8], T+32); rot_128(kL, 60, T+32); LOAD64H(skey->camellia.k[9], T+40); /* rotate kA by 60, k11/k12 */ rot_128(kA, 60, T+32); LOAD64H(skey->camellia.k[10], T+32); LOAD64H(skey->camellia.k[11], T+40); /* rotate kL by 77, kl3, kl4 */ rot_128(kL, 77, T+32); LOAD64H(skey->camellia.kl[2], T+32); LOAD64H(skey->camellia.kl[3], T+40); /* rotate kL by 94, k13/k14 */ rot_128(kL, 94, T+32); LOAD64H(skey->camellia.k[12], T+32); LOAD64H(skey->camellia.k[13], T+40); /* rotate kA by 94, k15/k16 */ rot_128(kA, 94, T+32); LOAD64H(skey->camellia.k[14], T+32); LOAD64H(skey->camellia.k[15], T+40); /* rotate kL by 111, k17/k18 */ rot_128(kL, 111, T+32); LOAD64H(skey->camellia.k[16], T+32); LOAD64H(skey->camellia.k[17], T+40); /* rotate kA by 111, kw3/kw4 */ rot_128(kA, 111, T+32); LOAD64H(skey->camellia.kw[2], T+32); LOAD64H(skey->camellia.kw[3], T+40); } else { /* last two rounds */ LOAD64H(A, T+32); LOAD64H(B, T+40); B ^= F(A ^ key_sigma[4]); A ^= F(B ^ key_sigma[5]); STORE64H(A, T+32); STORE64H(B, T+40); /* grab kB */ for (x = 0; x < 16; x++) { kB[x] = T[x+32]; } /* kw1/2 from kL*/ LOAD64H(skey->camellia.kw[0], kL); LOAD64H(skey->camellia.kw[1], kL+8); /* k1/k2 = kB */ LOAD64H(skey->camellia.k[0], kB); LOAD64H(skey->camellia.k[1], kB+8); /* k3/k4 = kR by 15 */ rot_128(kR, 15, T+32); LOAD64H(skey->camellia.k[2], T+32); LOAD64H(skey->camellia.k[3], T+40); /* k5/k7 = kA by 15 */ rot_128(kA, 15, T+32); LOAD64H(skey->camellia.k[4], T+32); LOAD64H(skey->camellia.k[5], T+40); /* kl1/2 = kR by 30 */ rot_128(kR, 30, T+32); LOAD64H(skey->camellia.kl[0], T+32); LOAD64H(skey->camellia.kl[1], T+40); /* k7/k8 = kB by 30 */ rot_128(kB, 30, T+32); LOAD64H(skey->camellia.k[6], T+32); LOAD64H(skey->camellia.k[7], T+40); /* k9/k10 = kL by 45 */ rot_128(kL, 45, T+32); LOAD64H(skey->camellia.k[8], T+32); LOAD64H(skey->camellia.k[9], T+40); /* k11/k12 = kA by 45 */ rot_128(kA, 45, T+32); LOAD64H(skey->camellia.k[10], T+32); LOAD64H(skey->camellia.k[11], T+40); /* kl3/4 = kL by 60 */ rot_128(kL, 60, T+32); LOAD64H(skey->camellia.kl[2], T+32); LOAD64H(skey->camellia.kl[3], T+40); /* k13/k14 = kR by 60 */ rot_128(kR, 60, T+32); LOAD64H(skey->camellia.k[12], T+32); LOAD64H(skey->camellia.k[13], T+40); /* k15/k16 = kB by 15 */ rot_128(kB, 60, T+32); LOAD64H(skey->camellia.k[14], T+32); LOAD64H(skey->camellia.k[15], T+40); /* k17/k18 = kL by 77 */ rot_128(kL, 77, T+32); LOAD64H(skey->camellia.k[16], T+32); LOAD64H(skey->camellia.k[17], T+40); /* kl5/6 = kA by 77 */ rot_128(kA, 77, T+32); LOAD64H(skey->camellia.kl[4], T+32); LOAD64H(skey->camellia.kl[5], T+40); /* k19/k20 = kR by 94 */ rot_128(kR, 94, T+32); LOAD64H(skey->camellia.k[18], T+32); LOAD64H(skey->camellia.k[19], T+40); /* k21/k22 = kA by 94 */ rot_128(kA, 94, T+32); LOAD64H(skey->camellia.k[20], T+32); LOAD64H(skey->camellia.k[21], T+40); /* k23/k24 = kL by 111 */ rot_128(kL, 111, T+32); LOAD64H(skey->camellia.k[22], T+32); LOAD64H(skey->camellia.k[23], T+40); /* kw2/kw3 = kB by 111 */ rot_128(kB, 111, T+32); LOAD64H(skey->camellia.kw[2], T+32); LOAD64H(skey->camellia.kw[3], T+40); } return CRYPT_OK; } int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong64 L, R; ulong32 a, b; LOAD64H(L, pt+0); LOAD64H(R, pt+8); L ^= skey->camellia.kw[0]; R ^= skey->camellia.kw[1]; /* first 6 rounds */ R ^= F(L ^ skey->camellia.k[0]); L ^= F(R ^ skey->camellia.k[1]); R ^= F(L ^ skey->camellia.k[2]); L ^= F(R ^ skey->camellia.k[3]); R ^= F(L ^ skey->camellia.k[4]); L ^= F(R ^ skey->camellia.k[5]); /* FL */ a = (ulong32)(L >> 32); b = (ulong32)(L & 0xFFFFFFFFUL); b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); L = (((ulong64)a) << 32) | b; /* FL^-1 */ a = (ulong32)(R >> 32); b = (ulong32)(R & 0xFFFFFFFFUL); a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); R = (((ulong64)a) << 32) | b; /* second 6 rounds */ R ^= F(L ^ skey->camellia.k[6]); L ^= F(R ^ skey->camellia.k[7]); R ^= F(L ^ skey->camellia.k[8]); L ^= F(R ^ skey->camellia.k[9]); R ^= F(L ^ skey->camellia.k[10]); L ^= F(R ^ skey->camellia.k[11]); /* FL */ a = (ulong32)(L >> 32); b = (ulong32)(L & 0xFFFFFFFFUL); b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); L = (((ulong64)a) << 32) | b; /* FL^-1 */ a = (ulong32)(R >> 32); b = (ulong32)(R & 0xFFFFFFFFUL); a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); R = (((ulong64)a) << 32) | b; /* third 6 rounds */ R ^= F(L ^ skey->camellia.k[12]); L ^= F(R ^ skey->camellia.k[13]); R ^= F(L ^ skey->camellia.k[14]); L ^= F(R ^ skey->camellia.k[15]); R ^= F(L ^ skey->camellia.k[16]); L ^= F(R ^ skey->camellia.k[17]); /* next FL */ if (skey->camellia.R == 24) { /* FL */ a = (ulong32)(L >> 32); b = (ulong32)(L & 0xFFFFFFFFUL); b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); L = (((ulong64)a) << 32) | b; /* FL^-1 */ a = (ulong32)(R >> 32); b = (ulong32)(R & 0xFFFFFFFFUL); a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); R = (((ulong64)a) << 32) | b; /* fourth 6 rounds */ R ^= F(L ^ skey->camellia.k[18]); L ^= F(R ^ skey->camellia.k[19]); R ^= F(L ^ skey->camellia.k[20]); L ^= F(R ^ skey->camellia.k[21]); R ^= F(L ^ skey->camellia.k[22]); L ^= F(R ^ skey->camellia.k[23]); } L ^= skey->camellia.kw[3]; R ^= skey->camellia.kw[2]; STORE64H(R, ct+0); STORE64H(L, ct+8); return CRYPT_OK; } int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong64 L, R; ulong32 a, b; LOAD64H(R, ct+0); LOAD64H(L, ct+8); L ^= skey->camellia.kw[3]; R ^= skey->camellia.kw[2]; /* next FL */ if (skey->camellia.R == 24) { /* fourth 6 rounds */ L ^= F(R ^ skey->camellia.k[23]); R ^= F(L ^ skey->camellia.k[22]); L ^= F(R ^ skey->camellia.k[21]); R ^= F(L ^ skey->camellia.k[20]); L ^= F(R ^ skey->camellia.k[19]); R ^= F(L ^ skey->camellia.k[18]); /* FL */ a = (ulong32)(L >> 32); b = (ulong32)(L & 0xFFFFFFFFUL); a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); L = (((ulong64)a) << 32) | b; /* FL^-1 */ a = (ulong32)(R >> 32); b = (ulong32)(R & 0xFFFFFFFFUL); b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); R = (((ulong64)a) << 32) | b; } /* third 6 rounds */ L ^= F(R ^ skey->camellia.k[17]); R ^= F(L ^ skey->camellia.k[16]); L ^= F(R ^ skey->camellia.k[15]); R ^= F(L ^ skey->camellia.k[14]); L ^= F(R ^ skey->camellia.k[13]); R ^= F(L ^ skey->camellia.k[12]); /* FL */ a = (ulong32)(L >> 32); b = (ulong32)(L & 0xFFFFFFFFUL); a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); L = (((ulong64)a) << 32) | b; /* FL^-1 */ a = (ulong32)(R >> 32); b = (ulong32)(R & 0xFFFFFFFFUL); b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); R = (((ulong64)a) << 32) | b; /* second 6 rounds */ L ^= F(R ^ skey->camellia.k[11]); R ^= F(L ^ skey->camellia.k[10]); L ^= F(R ^ skey->camellia.k[9]); R ^= F(L ^ skey->camellia.k[8]); L ^= F(R ^ skey->camellia.k[7]); R ^= F(L ^ skey->camellia.k[6]); /* FL */ a = (ulong32)(L >> 32); b = (ulong32)(L & 0xFFFFFFFFUL); a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); L = (((ulong64)a) << 32) | b; /* FL^-1 */ a = (ulong32)(R >> 32); b = (ulong32)(R & 0xFFFFFFFFUL); b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); R = (((ulong64)a) << 32) | b; /* first 6 rounds */ L ^= F(R ^ skey->camellia.k[5]); R ^= F(L ^ skey->camellia.k[4]); L ^= F(R ^ skey->camellia.k[3]); R ^= F(L ^ skey->camellia.k[2]); L ^= F(R ^ skey->camellia.k[1]); R ^= F(L ^ skey->camellia.k[0]); R ^= skey->camellia.kw[1]; L ^= skey->camellia.kw[0]; STORE64H(R, pt+8); STORE64H(L, pt+0); return CRYPT_OK; } int camellia_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 } }, { 24, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 } }, { 32, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 } }, { 32, { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }, { 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }, { 0x79, 0x60, 0x10, 0x9F, 0xB6, 0xDC, 0x42, 0x94, 0x7F, 0xCF, 0xE5, 0x9E, 0xA3, 0xC5, 0xEB, 0x6B } } }; unsigned char buf[2][16]; symmetric_key skey; int err; unsigned int x; for (x = 0; x < sizeof(tests)/sizeof(tests[0]); x++) { zeromem(&skey, sizeof(skey)); if ((err = camellia_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { return err; } if ((err = camellia_ecb_encrypt(tests[x].pt, buf[0], &skey)) != CRYPT_OK) { camellia_done(&skey); return err; } if ((err = camellia_ecb_decrypt(tests[x].ct, buf[1], &skey)) != CRYPT_OK) { camellia_done(&skey); return err; } camellia_done(&skey); if (compare_testvector(tests[x].ct, 16, buf[0], 16, "Camellia Encrypt", x) || compare_testvector(tests[x].pt, 16, buf[1], 16, "Camellia Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } void camellia_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } int camellia_keysize(int *keysize) { if (*keysize >= 32) { *keysize = 32; } else if (*keysize >= 24) { *keysize = 24; } else if (*keysize >= 16) { *keysize = 16; } else return CRYPT_INVALID_KEYSIZE; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/cast5.c000066400000000000000000001212211464416617300230230ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file cast5.c Implementation of LTC_CAST5 (RFC 2144) by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_CAST5 const struct ltc_cipher_descriptor cast5_desc = { "cast5", 15, 5, 16, 8, 16, &cast5_setup, &cast5_ecb_encrypt, &cast5_ecb_decrypt, &cast5_test, &cast5_done, &cast5_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 S1[256] = { 0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL, 0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL, 0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL, 0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL, 0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL, 0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL, 0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL, 0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL, 0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL, 0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL, 0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL, 0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL, 0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL, 0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL, 0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL, 0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL, 0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL, 0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL, 0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL, 0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL, 0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL, 0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL, 0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL, 0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL, 0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL, 0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL, 0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL, 0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL, 0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL, 0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL, 0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL, 0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL, 0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL, 0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL, 0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL, 0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL, 0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL, 0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL, 0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL, 0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL, 0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL, 0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL, 0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL}; static const ulong32 S2[256] = { 0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL, 0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL, 0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL, 0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL, 0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL, 0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL, 0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL, 0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL, 0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL, 0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL, 0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL, 0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL, 0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL, 0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL, 0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL, 0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL, 0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL, 0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL, 0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL, 0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL, 0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL, 0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL, 0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL, 0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL, 0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL, 0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL, 0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL, 0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL, 0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL, 0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL, 0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL, 0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL, 0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL, 0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL, 0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL, 0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL, 0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL, 0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL, 0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL, 0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL, 0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL, 0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL, 0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL}; static const ulong32 S3[256] = { 0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL, 0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL, 0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL, 0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL, 0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL, 0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL, 0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL, 0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL, 0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL, 0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL, 0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL, 0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL, 0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL, 0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL, 0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL, 0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL, 0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL, 0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL, 0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL, 0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL, 0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL, 0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL, 0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL, 0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL, 0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL, 0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL, 0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL, 0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL, 0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL, 0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL, 0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL, 0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL, 0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL, 0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL, 0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL, 0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL, 0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL, 0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL, 0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL, 0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL, 0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL, 0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL, 0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL}; static const ulong32 S4[256] = { 0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL, 0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL, 0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL, 0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL, 0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL, 0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL, 0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL, 0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL, 0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL, 0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL, 0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL, 0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL, 0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL, 0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL, 0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL, 0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL, 0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL, 0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL, 0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL, 0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL, 0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL, 0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL, 0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL, 0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL, 0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL, 0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL, 0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL, 0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL, 0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL, 0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL, 0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL, 0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL, 0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL, 0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL, 0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL, 0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL, 0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL, 0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL, 0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL, 0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL, 0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL, 0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL, 0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL}; static const ulong32 S5[256] = { 0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL, 0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL, 0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL, 0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL, 0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL, 0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL, 0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL, 0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL, 0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL, 0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL, 0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL, 0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL, 0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL, 0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL, 0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL, 0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL, 0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL, 0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL, 0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL, 0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL, 0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL, 0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL, 0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL, 0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL, 0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL, 0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL, 0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL, 0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL, 0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL, 0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL, 0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL, 0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL, 0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL, 0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL, 0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL, 0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL, 0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL, 0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL, 0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL, 0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL, 0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL, 0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL, 0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL}; static const ulong32 S6[256] = { 0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL, 0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL, 0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL, 0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL, 0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL, 0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL, 0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL, 0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL, 0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL, 0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL, 0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL, 0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL, 0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL, 0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL, 0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL, 0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL, 0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL, 0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL, 0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL, 0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL, 0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL, 0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL, 0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL, 0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL, 0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL, 0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL, 0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL, 0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL, 0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL, 0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL, 0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL, 0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL, 0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL, 0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL, 0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL, 0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL, 0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL, 0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL, 0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL, 0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL, 0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL, 0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL, 0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL}; static const ulong32 S7[256] = { 0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL, 0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL, 0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL, 0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL, 0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL, 0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL, 0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL, 0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL, 0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL, 0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL, 0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL, 0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL, 0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL, 0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL, 0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL, 0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL, 0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL, 0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL, 0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL, 0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL, 0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL, 0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL, 0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL, 0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL, 0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL, 0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL, 0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL, 0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL, 0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL, 0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL, 0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL, 0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL, 0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL, 0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL, 0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL, 0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL, 0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL, 0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL, 0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL, 0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL, 0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL, 0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL, 0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL}; static const ulong32 S8[256] = { 0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL, 0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL, 0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL, 0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL, 0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL, 0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL, 0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL, 0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL, 0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL, 0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL, 0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL, 0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL, 0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL, 0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL, 0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL, 0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL, 0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL, 0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL, 0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL, 0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL, 0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL, 0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL, 0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL, 0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL, 0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL, 0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL, 0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL, 0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL, 0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL, 0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL, 0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL, 0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL, 0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL, 0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL, 0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL, 0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL, 0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL, 0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL, 0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL, 0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL, 0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL, 0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL, 0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL}; /* returns the i'th byte of a variable */ #ifdef _MSC_VER #define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))) #else #define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255) #endif /** Initialize the LTC_CAST5 block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #else int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #endif { ulong32 x[4], z[4]; unsigned char buf[16]; int y, i; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) { return CRYPT_INVALID_ROUNDS; } if (num_rounds == 12 && keylen > 10) { return CRYPT_INVALID_ROUNDS; } if (keylen < 5 || keylen > 16) { return CRYPT_INVALID_KEYSIZE; } /* extend the key as required */ zeromem(buf, sizeof(buf)); XMEMCPY(buf, key, (size_t)keylen); /* load and start the awful looking network */ for (y = 0; y < 4; y++) { LOAD32H(x[3-y],buf+4*y); } for (i = y = 0; y < 2; y++) { z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)]; skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)]; skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)]; skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)]; x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)]; skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)]; skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)]; skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)]; /* second half */ z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)]; skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)]; skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)]; skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)]; x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)]; skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)]; skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)]; skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)]; } skey->cast5.keylen = keylen; #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); zeromem(x, sizeof(x)); zeromem(z, sizeof(z)); #endif return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int z; z = s_cast5_setup(key, keylen, num_rounds, skey); burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2); return z; } #endif LTC_INLINE static ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr) { ulong32 I; I = (Km + R); I = ROL(I, Kr); return ((S1[LTC_BYTE(I, 3)] ^ S2[LTC_BYTE(I,2)]) - S3[LTC_BYTE(I,1)]) + S4[LTC_BYTE(I,0)]; } LTC_INLINE static ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr) { ulong32 I; I = (Km ^ R); I = ROL(I, Kr); return ((S1[LTC_BYTE(I, 3)] - S2[LTC_BYTE(I,2)]) + S3[LTC_BYTE(I,1)]) ^ S4[LTC_BYTE(I,0)]; } LTC_INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr) { ulong32 I; I = (Km - R); I = ROL(I, Kr); return ((S1[LTC_BYTE(I, 3)] + S2[LTC_BYTE(I,2)]) ^ S3[LTC_BYTE(I,1)]) - S4[LTC_BYTE(I,0)]; } /** Encrypts a block of text with LTC_CAST5 @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled */ #ifdef LTC_CLEAN_STACK static int s_cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 R, L; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(L,&pt[0]); LOAD32H(R,&pt[4]); L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); if (skey->cast5.keylen > 10) { L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); } STORE32H(R,&ct[0]); STORE32H(L,&ct[4]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_cast5_ecb_encrypt(pt,ct,skey); burn_stack(sizeof(ulong32)*3); return err; } #endif /** Decrypts a block of text with LTC_CAST5 @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled */ #ifdef LTC_CLEAN_STACK static int s_cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 R, L; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(R,&ct[0]); LOAD32H(L,&ct[4]); if (skey->cast5.keylen > 10) { R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); } R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); STORE32H(L,&pt[0]); STORE32H(R,&pt[4]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_cast5_ecb_decrypt(ct,pt,skey); burn_stack(sizeof(ulong32)*3); return err; } #endif /** Performs a self-test of the LTC_CAST5 block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int cast5_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key[16]; unsigned char pt[8]; unsigned char ct[8]; } tests[] = { { 16, {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2} }, { 10, {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B}, }, { 5, {0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E} } }; int i, y, err; symmetric_key key; unsigned char tmp[2][8]; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } cast5_ecb_encrypt(tests[i].pt, tmp[0], &key); cast5_ecb_decrypt(tmp[0], tmp[1], &key); if ((compare_testvector(tmp[0], 8, tests[i].ct, 8, "CAST5 Encrypt", i) != 0) || (compare_testvector(tmp[1], 8, tests[i].pt, 8, "CAST5 Decrypt", i) != 0)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void cast5_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int cast5_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 5) { return CRYPT_INVALID_KEYSIZE; } if (*keysize > 16) { *keysize = 16; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/des.c000066400000000000000000004735711464416617300226010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file des.c DES code submitted by Dobes Vandermeer */ #ifdef LTC_DES #define EN0 0 #define DE1 1 const struct ltc_cipher_descriptor des_desc = { "des", 13, 8, 8, 8, 16, &des_setup, &des_ecb_encrypt, &des_ecb_decrypt, &des_test, &des_done, &des_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; const struct ltc_cipher_descriptor des3_desc = { "3des", 14, 16, 24, 8, 16, &des3_setup, &des3_ecb_encrypt, &des3_ecb_decrypt, &des3_test, &des3_done, &des3_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 bytebit[8] = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; static const ulong32 bigbyte[24] = { 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, 0x800UL, 0x400UL, 0x200UL, 0x100UL, 0x80UL, 0x40UL, 0x20UL, 0x10UL, 0x8UL, 0x4UL, 0x2UL, 0x1L }; /* Use the key schedule specific in the standard (ANSI X3.92-1981) */ static const unsigned char pc1[56] = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; static const unsigned char totrot[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; static const unsigned char pc2[48] = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; static const ulong32 SP1[64] = { 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL }; static const ulong32 SP2[64] = { 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL }; static const ulong32 SP3[64] = { 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL }; static const ulong32 SP4[64] = { 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL }; static const ulong32 SP5[64] = { 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL }; static const ulong32 SP6[64] = { 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL }; static const ulong32 SP7[64] = { 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL }; static const ulong32 SP8[64] = { 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL }; #ifndef LTC_SMALL_CODE static const ulong64 des_ip[8][256] = { { CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010), CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010), CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010), CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010), CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010), CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010), CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010), CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010), CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010), CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010), CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010), CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010), CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010), CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010), CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010), CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010), CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010), CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010), CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010), CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010), CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010), CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010), CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010), CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010), CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010), CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010), CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010), CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010), CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010), CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010), CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010), CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010), CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010), CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010), CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010), CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010), CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010), CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010), CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010), CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010), CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010), CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010), CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010), CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010), CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010), CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010), CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010), CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010), CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010), CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010), CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010), CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010), CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010), CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010), CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010), CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010), CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010), CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010), CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010), CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010), CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010), CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010), CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010), CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010) }, { CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008), CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008), CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808), CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808), CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008), CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008), CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808), CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808), CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008), CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008), CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808), CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808), CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008), CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008), CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808), CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808), CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008), CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008), CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808), CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808), CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008), CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008), CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808), CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808), CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008), CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008), CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808), CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808), CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008), CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008), CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808), CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808), CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008), CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008), CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808), CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808), CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008), CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008), CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808), CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808), CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008), CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008), CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808), CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808), CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008), CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008), CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808), CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808), CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008), CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008), CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808), CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808), CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008), CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008), CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808), CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808), CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008), CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008), CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808), CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808), CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008), CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008), CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808), CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808) }, { CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004), CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004), CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404), CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404), CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004), CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004), CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404), CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404), CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004), CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004), CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404), CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404), CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004), CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004), CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404), CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404), CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004), CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004), CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404), CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404), CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004), CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004), CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404), CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404), CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004), CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004), CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404), CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404), CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004), CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004), CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404), CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404), CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004), CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004), CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404), CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404), CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004), CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004), CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404), CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404), CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004), CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004), CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404), CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404), CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004), CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004), CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404), CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404), CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004), CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004), CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404), CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404), CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004), CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004), CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404), CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404), CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004), CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004), CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404), CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404), CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004), CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004), CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404), CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404) }, { CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002), CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002), CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202), CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202), CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002), CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002), CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202), CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202), CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002), CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002), CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202), CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202), CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002), CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002), CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202), CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202), CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002), CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002), CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202), CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202), CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002), CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002), CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202), CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202), CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002), CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002), CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202), CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202), CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002), CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002), CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202), CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202), CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002), CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002), CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202), CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202), CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002), CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002), CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202), CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202), CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002), CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002), CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202), CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202), CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002), CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002), CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202), CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202), CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002), CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002), CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202), CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202), CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002), CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002), CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202), CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202), CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002), CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002), CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202), CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202), CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002), CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002), CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202), CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202) }, { CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100), CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100), CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100), CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100), CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100), CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100), CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100), CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100), CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100), CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100), CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100), CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100), CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100), CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100), CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100), CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100), CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100), CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100), CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100), CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100), CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100), CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100), CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100), CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100), CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100), CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100), CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100), CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100), CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100), CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100), CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100), CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100), CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101), CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101), CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101), CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101), CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101), CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101), CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101), CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101), CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101), CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101), CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101), CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101), CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101), CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101), CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101), CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101), CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101), CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101), CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101), CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101), CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101), CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101), CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101), CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101), CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101), CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101), CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101), CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101), CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101), CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101), CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101), CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101) }, { CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080), CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080), CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080), CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080), CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080), CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080), CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080), CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080), CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080), CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080), CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080), CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080), CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080), CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080), CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080), CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080), CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080), CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080), CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080), CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080), CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080), CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080), CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080), CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080), CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080), CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080), CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080), CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080), CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080), CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080), CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080), CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080), CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080), CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080), CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080), CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080), CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080), CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080), CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080), CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080), CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080), CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080), CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080), CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080), CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080), CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080), CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080), CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080), CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080), CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080), CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080), CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080), CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080), CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080), CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080), CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080), CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080), CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080), CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080), CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080), CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080), CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080), CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080), CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080) }, { CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040), CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040), CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040), CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040), CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040), CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040), CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040), CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040), CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040), CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040), CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040), CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040), CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040), CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040), CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040), CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040), CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040), CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040), CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040), CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040), CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040), CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040), CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040), CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040), CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040), CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040), CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040), CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040), CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040), CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040), CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040), CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040), CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040), CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040), CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040), CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040), CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040), CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040), CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040), CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040), CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040), CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040), CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040), CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040), CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040), CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040), CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040), CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040), CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040), CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040), CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040), CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040), CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040), CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040), CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040), CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040), CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040), CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040), CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040), CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040), CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040), CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040), CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040), CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040) }, { CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020), CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020), CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020), CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020), CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020), CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020), CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020), CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020), CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020), CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020), CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020), CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020), CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020), CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020), CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020), CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020), CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020), CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020), CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020), CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020), CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020), CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020), CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020), CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020), CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020), CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020), CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020), CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020), CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020), CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020), CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020), CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020), CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020), CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020), CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020), CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020), CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020), CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020), CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020), CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020), CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020), CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020), CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020), CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020), CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020), CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020), CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020), CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020), CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020), CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020), CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020), CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020), CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020), CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020), CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020), CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020), CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020), CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020), CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020), CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020), CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020), CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020), CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020), CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020) }}; static const ulong64 des_fp[8][256] = { { CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000), CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000), CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200), CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200), CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002), CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002), CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202), CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202), CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000), CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000), CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200), CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200), CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002), CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002), CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202), CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202), CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000), CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000), CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200), CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200), CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002), CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002), CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202), CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202), CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000), CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000), CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200), CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200), CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002), CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002), CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202), CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202), CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000), CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000), CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200), CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200), CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002), CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002), CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202), CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202), CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000), CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000), CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200), CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200), CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002), CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002), CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202), CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202), CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000), CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000), CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200), CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200), CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002), CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002), CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202), CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202), CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000), CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000), CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200), CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200), CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002), CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002), CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202), CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202) }, { CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000), CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000), CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800), CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800), CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008), CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008), CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808), CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808), CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000), CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000), CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800), CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800), CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008), CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008), CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808), CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808), CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000), CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000), CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800), CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800), CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008), CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008), CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808), CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808), CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000), CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000), CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800), CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800), CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008), CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008), CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808), CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808), CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000), CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000), CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800), CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800), CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008), CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008), CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808), CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808), CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000), CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000), CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800), CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800), CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008), CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008), CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808), CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808), CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000), CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000), CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800), CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800), CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008), CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008), CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808), CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808), CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000), CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000), CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800), CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800), CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008), CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008), CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808), CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808) }, { CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000), CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000), CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000), CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000), CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020), CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020), CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020), CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020), CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000), CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000), CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000), CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000), CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020), CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020), CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020), CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020), CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000), CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000), CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000), CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000), CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020), CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020), CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020), CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020), CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000), CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000), CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000), CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000), CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020), CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020), CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020), CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020), CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000), CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000), CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000), CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000), CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020), CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020), CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020), CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020), CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000), CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000), CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000), CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000), CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020), CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020), CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020), CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020), CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000), CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000), CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000), CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000), CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020), CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020), CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020), CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020), CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000), CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000), CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000), CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000), CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020), CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020), CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020), CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020) }, { CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000), CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000), CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000), CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000), CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080), CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080), CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080), CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080), CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000), CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000), CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000), CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000), CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080), CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080), CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080), CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080), CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000), CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000), CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000), CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000), CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080), CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080), CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080), CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080), CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000), CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000), CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000), CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000), CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080), CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080), CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080), CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080), CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000), CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000), CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000), CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000), CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080), CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080), CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080), CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080), CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000), CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000), CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000), CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000), CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080), CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080), CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080), CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080), CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000), CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000), CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000), CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000), CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080), CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080), CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080), CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080), CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000), CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000), CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000), CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000), CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080), CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080), CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080), CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080) }, { CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000), CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000), CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100), CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100), CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001), CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001), CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101), CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101), CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000), CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000), CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100), CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100), CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001), CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001), CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101), CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101), CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000), CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000), CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100), CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100), CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001), CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001), CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101), CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101), CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000), CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000), CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100), CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100), CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001), CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001), CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101), CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101), CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000), CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000), CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100), CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100), CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001), CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001), CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101), CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101), CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000), CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000), CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100), CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100), CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001), CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001), CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101), CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101), CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000), CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000), CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100), CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100), CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001), CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001), CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101), CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101), CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000), CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000), CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100), CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100), CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001), CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001), CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101), CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101) }, { CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000), CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000), CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400), CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400), CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004), CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004), CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404), CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404), CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000), CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000), CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400), CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400), CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004), CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004), CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404), CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404), CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000), CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000), CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400), CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400), CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004), CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004), CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404), CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404), CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000), CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000), CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400), CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400), CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004), CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004), CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404), CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404), CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000), CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000), CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400), CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400), CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004), CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004), CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404), CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404), CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000), CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000), CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400), CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400), CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004), CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004), CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404), CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404), CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000), CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000), CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400), CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400), CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004), CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004), CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404), CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404), CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000), CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000), CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400), CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400), CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004), CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004), CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404), CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404) }, { CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000), CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000), CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000), CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000), CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010), CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010), CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010), CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010), CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000), CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000), CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000), CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000), CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010), CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010), CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010), CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010), CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000), CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000), CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000), CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000), CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010), CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010), CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010), CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010), CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000), CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000), CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000), CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000), CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010), CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010), CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010), CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010), CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000), CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000), CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000), CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000), CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010), CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010), CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010), CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010), CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000), CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000), CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000), CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000), CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010), CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010), CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010), CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010), CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000), CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000), CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000), CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000), CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010), CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010), CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010), CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010), CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000), CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000), CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000), CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000), CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010), CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010), CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010), CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010) }, { CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000), CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000), CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000), CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000), CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040), CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040), CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040), CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040), CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000), CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000), CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000), CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000), CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040), CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040), CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040), CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040), CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000), CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000), CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000), CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000), CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040), CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040), CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040), CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040), CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000), CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000), CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000), CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000), CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040), CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040), CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040), CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040), CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000), CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000), CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000), CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000), CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040), CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040), CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040), CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040), CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000), CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000), CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000), CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000), CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040), CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040), CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040), CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040), CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000), CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000), CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000), CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000), CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040), CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040), CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040), CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040), CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000), CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000), CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000), CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000), CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040), CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040), CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040), CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040) }}; #endif static void cookey(const ulong32 *raw1, ulong32 *keyout); #ifdef LTC_CLEAN_STACK static void s_deskey(const unsigned char *key, short edf, ulong32 *keyout) #else static void deskey(const unsigned char *key, short edf, ulong32 *keyout) #endif { ulong32 i, j, l, m, n, kn[32]; unsigned char pc1m[56], pcr[56]; for (j=0; j < 56; j++) { l = (ulong32)pc1[j]; m = l & 7; pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); } for (i=0; i < 16; i++) { if (edf == DE1) { m = (15 - i) << 1; } else { m = i << 1; } n = m + 1; kn[m] = kn[n] = 0L; for (j=0; j < 28; j++) { l = j + (ulong32)totrot[i]; if (l < 28) { pcr[j] = pc1m[l]; } else { pcr[j] = pc1m[l - 28]; } } for (/*j = 28*/; j < 56; j++) { l = j + (ulong32)totrot[i]; if (l < 56) { pcr[j] = pc1m[l]; } else { pcr[j] = pc1m[l - 28]; } } for (j=0; j < 24; j++) { if ((int)pcr[(int)pc2[j]] != 0) { kn[m] |= bigbyte[j]; } if ((int)pcr[(int)pc2[j+24]] != 0) { kn[n] |= bigbyte[j]; } } } cookey(kn, keyout); } #ifdef LTC_CLEAN_STACK static void deskey(const unsigned char *key, short edf, ulong32 *keyout) { s_deskey(key, edf, keyout); burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112); } #endif #ifdef LTC_CLEAN_STACK static void s_cookey(const ulong32 *raw1, ulong32 *keyout) #else static void cookey(const ulong32 *raw1, ulong32 *keyout) #endif { ulong32 *cook; const ulong32 *raw0; ulong32 dough[32]; int i; cook = dough; for(i=0; i < 16; i++, raw1++) { raw0 = raw1++; *cook = (*raw0 & 0x00fc0000L) << 6; *cook |= (*raw0 & 0x00000fc0L) << 10; *cook |= (*raw1 & 0x00fc0000L) >> 10; *cook++ |= (*raw1 & 0x00000fc0L) >> 6; *cook = (*raw0 & 0x0003f000L) << 12; *cook |= (*raw0 & 0x0000003fL) << 16; *cook |= (*raw1 & 0x0003f000L) >> 4; *cook++ |= (*raw1 & 0x0000003fL); } XMEMCPY(keyout, dough, sizeof(dough)); } #ifdef LTC_CLEAN_STACK static void cookey(const ulong32 *raw1, ulong32 *keyout) { s_cookey(raw1, keyout); burn_stack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int)); } #endif #ifndef LTC_CLEAN_STACK static void desfunc(ulong32 *block, const ulong32 *keys) #else static void s_desfunc(ulong32 *block, const ulong32 *keys) #endif { ulong32 work, right, leftt; int cur_round; leftt = block[0]; right = block[1]; #ifdef LTC_SMALL_CODE work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; right ^= work; leftt ^= (work << 4); work = ((leftt >> 16) ^ right) & 0x0000ffffL; right ^= work; leftt ^= (work << 16); work = ((right >> 2) ^ leftt) & 0x33333333L; leftt ^= work; right ^= (work << 2); work = ((right >> 8) ^ leftt) & 0x00ff00ffL; leftt ^= work; right ^= (work << 8); right = ROLc(right, 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = ROLc(leftt, 1); #else { ulong64 tmp; tmp = des_ip[0][LTC_BYTE(leftt, 0)] ^ des_ip[1][LTC_BYTE(leftt, 1)] ^ des_ip[2][LTC_BYTE(leftt, 2)] ^ des_ip[3][LTC_BYTE(leftt, 3)] ^ des_ip[4][LTC_BYTE(right, 0)] ^ des_ip[5][LTC_BYTE(right, 1)] ^ des_ip[6][LTC_BYTE(right, 2)] ^ des_ip[7][LTC_BYTE(right, 3)]; leftt = (ulong32)(tmp >> 32); right = (ulong32)(tmp & 0xFFFFFFFFUL); } #endif for (cur_round = 0; cur_round < 8; cur_round++) { work = RORc(right, 4) ^ *keys++; leftt ^= SP7[work & 0x3fL] ^ SP5[(work >> 8) & 0x3fL] ^ SP3[(work >> 16) & 0x3fL] ^ SP1[(work >> 24) & 0x3fL]; work = right ^ *keys++; leftt ^= SP8[ work & 0x3fL] ^ SP6[(work >> 8) & 0x3fL] ^ SP4[(work >> 16) & 0x3fL] ^ SP2[(work >> 24) & 0x3fL]; work = RORc(leftt, 4) ^ *keys++; right ^= SP7[ work & 0x3fL] ^ SP5[(work >> 8) & 0x3fL] ^ SP3[(work >> 16) & 0x3fL] ^ SP1[(work >> 24) & 0x3fL]; work = leftt ^ *keys++; right ^= SP8[ work & 0x3fL] ^ SP6[(work >> 8) & 0x3fL] ^ SP4[(work >> 16) & 0x3fL] ^ SP2[(work >> 24) & 0x3fL]; } #ifdef LTC_SMALL_CODE right = RORc(right, 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = RORc(leftt, 1); work = ((leftt >> 8) ^ right) & 0x00ff00ffL; right ^= work; leftt ^= (work << 8); /* -- */ work = ((leftt >> 2) ^ right) & 0x33333333L; right ^= work; leftt ^= (work << 2); work = ((right >> 16) ^ leftt) & 0x0000ffffL; leftt ^= work; right ^= (work << 16); work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; leftt ^= work; right ^= (work << 4); #else { ulong64 tmp; tmp = des_fp[0][LTC_BYTE(leftt, 0)] ^ des_fp[1][LTC_BYTE(leftt, 1)] ^ des_fp[2][LTC_BYTE(leftt, 2)] ^ des_fp[3][LTC_BYTE(leftt, 3)] ^ des_fp[4][LTC_BYTE(right, 0)] ^ des_fp[5][LTC_BYTE(right, 1)] ^ des_fp[6][LTC_BYTE(right, 2)] ^ des_fp[7][LTC_BYTE(right, 3)]; leftt = (ulong32)(tmp >> 32); right = (ulong32)(tmp & 0xFFFFFFFFUL); } #endif block[0] = right; block[1] = leftt; } #ifdef LTC_CLEAN_STACK static void desfunc(ulong32 *block, const ulong32 *keys) { s_desfunc(block, keys); burn_stack(sizeof(ulong32) * 4 + sizeof(int)); } #endif /** Initialize the LTC_DES block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && num_rounds != 16) { return CRYPT_INVALID_ROUNDS; } if (keylen != 8) { return CRYPT_INVALID_KEYSIZE; } deskey(key, EN0, skey->des.ek); deskey(key, DE1, skey->des.dk); return CRYPT_OK; } /** Initialize the 3LTC_DES-EDE block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if(num_rounds != 0 && num_rounds != 16) { return CRYPT_INVALID_ROUNDS; } if (keylen != 24 && keylen != 16) { return CRYPT_INVALID_KEYSIZE; } deskey(key, EN0, skey->des3.ek[0]); deskey(key+8, DE1, skey->des3.ek[1]); if (keylen == 24) { deskey(key+16, EN0, skey->des3.ek[2]); } else { /* two-key 3DES: K3=K1 */ deskey(key, EN0, skey->des3.ek[2]); } deskey(key, DE1, skey->des3.dk[2]); deskey(key+8, EN0, skey->des3.dk[1]); if (keylen == 24) { deskey(key+16, DE1, skey->des3.dk[0]); } else { /* two-key 3DES: K3=K1 */ deskey(key, DE1, skey->des3.dk[0]); } return CRYPT_OK; } /** Encrypts a block of text with LTC_DES @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 work[2]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(work[0], pt+0); LOAD32H(work[1], pt+4); desfunc(work, skey->des.ek); STORE32H(work[0],ct+0); STORE32H(work[1],ct+4); return CRYPT_OK; } /** Decrypts a block of text with LTC_DES @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 work[2]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(work[0], ct+0); LOAD32H(work[1], ct+4); desfunc(work, skey->des.dk); STORE32H(work[0],pt+0); STORE32H(work[1],pt+4); return CRYPT_OK; } /** Encrypts a block of text with 3LTC_DES-EDE @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 work[2]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(work[0], pt+0); LOAD32H(work[1], pt+4); desfunc(work, skey->des3.ek[0]); desfunc(work, skey->des3.ek[1]); desfunc(work, skey->des3.ek[2]); STORE32H(work[0],ct+0); STORE32H(work[1],ct+4); return CRYPT_OK; } /** Decrypts a block of text with 3LTC_DES-EDE @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 work[2]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(work[0], ct+0); LOAD32H(work[1], ct+4); desfunc(work, skey->des3.dk[0]); desfunc(work, skey->des3.dk[1]); desfunc(work, skey->des3.dk[2]); STORE32H(work[0],pt+0); STORE32H(work[1],pt+4); return CRYPT_OK; } /** Performs a self-test of the LTC_DES block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int des_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct des_test_case { unsigned char key[8], txt[8], out[8]; } cases[] = { { { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } }, { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } }, { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } }, { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } }, { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } }, { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } }, { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } }, { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } }, { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } }, { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } }, { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } }, { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } }, { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } }, { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } }, { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } }, { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } }, { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } }, { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } }, { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } }, { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } }, { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } }, { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } }, { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } }, { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } }, { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } }, { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } }, { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } }, { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } }, { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } }, { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } }, { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } }, { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } }, { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } }, { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } }, { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } }, { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } }, /*** more test cases you could add if you are not convinced (the above test cases aren't really too good): key plaintext ciphertext 0000000000000000 0000000000000000 8CA64DE9C1B123A7 FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58 3000000000000000 1000000000000001 958E6E627A05557B 1111111111111111 1111111111111111 F40379AB9E0EC533 0123456789ABCDEF 1111111111111111 17668DFC7292532D 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD 0000000000000000 0000000000000000 8CA64DE9C1B123A7 FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 025816164629B007 480D39006EE762F2 A1F9915541020B56 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606 E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451 FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2 http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt ***/ }; unsigned char key[8], pt[8], ct[8], tmp[8]; symmetric_key skey; int i, err; for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) { if ((err = des_setup(cases[i].key, 8, 0, &skey)) != CRYPT_OK) { return err; } des_ecb_encrypt(cases[i].txt, ct, &skey); if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "DES Encrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } des_ecb_decrypt(ct, pt, &skey); if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "DES Decrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } } /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ for (i = 0; i < 8; i++) key[i] = i; if ((err = des_setup(key, 8, 0, &skey)) != CRYPT_OK) { return err; } for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; for (i = 0; i < 1000; i++) des_ecb_encrypt(tmp, tmp, &skey); for (i = 0; i < 1000; i++) des_ecb_decrypt(tmp, tmp, &skey); if (compare_testvector(tmp, 8, pt, 8, "DES", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int des3_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct des3_test_case { unsigned char key[16], txt[8], out[8]; } cases[] = { /* https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/des/Triple-Des-2-Key-128-64.unverified.test-vectors */ { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xFA, 0xFD, 0x50, 0x84, 0x37, 0x4F, 0xCE, 0x34 } }, { { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x60, 0xCC, 0x37, 0xB7, 0xB5, 0x37, 0xA1, 0xDC } }, { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xBE, 0x3E, 0x73, 0x04, 0xFE, 0x92, 0xC2, 0xBC } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, { 0xE5, 0xA9, 0xE3, 0x80, 0x03, 0xA5, 0xA0, 0xFD }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0xE4, 0xFC, 0x19, 0xD6, 0x94, 0x63, 0xB7, 0x83 }, { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } }, }; unsigned char key[24], pt[8], ct[8], tmp[8]; symmetric_key skey; int i, err; if ((err = des_test()) != CRYPT_OK) { return err; } for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) { if ((err = des3_setup(cases[i].key, 16, 0, &skey)) != CRYPT_OK) { return err; } des3_ecb_encrypt(cases[i].txt, ct, &skey); if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "3DES Encrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } des3_ecb_decrypt(ct, pt, &skey); if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "3DES Decrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } } /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ for (i = 0; i < 24; i++) key[i] = i; if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) { return err; } for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; for (i = 0; i < 1000; i++) des3_ecb_encrypt(tmp, tmp, &skey); for (i = 0; i < 1000; i++) des3_ecb_decrypt(tmp, tmp, &skey); if (compare_testvector(tmp, 8, pt, 8, "3DES", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void des_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Terminate the context @param skey The scheduled key */ void des3_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int des_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if(*keysize < 8) { return CRYPT_INVALID_KEYSIZE; } *keysize = 8; return CRYPT_OK; } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int des3_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } if (*keysize < 24) { *keysize = 16; return CRYPT_OK; } *keysize = 24; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/idea.c000066400000000000000000000176011464416617300227140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* Based on idea.cpp - originally written and placed in the public domain by Wei Dai https://github.com/weidai11/cryptopp/blob/master/idea.cpp Patents should be expired. On 2017-10-16 wikipedia says: https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990, then an international patent application was filed under the Patent Cooperation Treaty on May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands, Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011), the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012) and Japan (JP 3225440) (expired May 16, 2011). */ #include "tomcrypt_private.h" #ifdef LTC_IDEA const struct ltc_cipher_descriptor idea_desc = { "idea", 24, /* cipher_ID */ 16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */ &idea_setup, &idea_ecb_encrypt, &idea_ecb_decrypt, &idea_test, &idea_done, &idea_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; typedef unsigned short int ushort16; #define LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */ #define HIGH16(x) ((x)>>16) #define MUL(a,b) { \ ulong32 p = (ulong32)LOW16(a) * b; \ if (p) { \ p = LOW16(p) - HIGH16(p); \ a = (ushort16)p - (ushort16)HIGH16(p); \ } \ else \ a = 1 - a - b; \ } #define STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); } #define LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); } static ushort16 s_mul_inv(ushort16 x) { ushort16 y = x; unsigned i; for (i = 0; i < 15; i++) { MUL(y, LOW16(y)); MUL(y, x); } return LOW16(y); } static ushort16 s_add_inv(ushort16 x) { return LOW16(0 - x); } static int s_setup_key(const unsigned char *key, symmetric_key *skey) { int i, j; ushort16 *e_key = skey->idea.ek; ushort16 *d_key = skey->idea.dk; /* prepare enc key */ for (i = 0; i < 8; i++) { LOAD16(e_key[i], key + 2 * i); } for (; i < LTC_IDEA_KEYLEN; i++) { j = (i - i % 8) - 8; e_key[i] = LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7)); } /* prepare dec key */ for (i = 0; i < LTC_IDEA_ROUNDS; i++) { d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]); d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]); d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4]; d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5]; } d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]); d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]); d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); return CRYPT_OK; } static int s_process_block(const unsigned char *in, unsigned char *out, const ushort16 *m_key) { int i; ushort16 x0, x1, x2, x3, t0, t1; LOAD16(x0, in + 0); LOAD16(x1, in + 2); LOAD16(x2, in + 4); LOAD16(x3, in + 6); for (i = 0; i < LTC_IDEA_ROUNDS; i++) { MUL(x0, m_key[i*6+0]); x1 += m_key[i*6+1]; x2 += m_key[i*6+2]; MUL(x3, m_key[i*6+3]); t0 = x0^x2; MUL(t0, m_key[i*6+4]); t1 = t0 + (x1^x3); MUL(t1, m_key[i*6+5]); t0 += t1; x0 ^= t1; x3 ^= t0; t0 ^= x1; x1 = x2^t1; x2 = t0; } MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]); x2 += m_key[LTC_IDEA_ROUNDS*6+1]; x1 += m_key[LTC_IDEA_ROUNDS*6+2]; MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]); STORE16(x0, out + 0); STORE16(x2, out + 2); STORE16(x1, out + 4); STORE16(x3, out + 6); return CRYPT_OK; } int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && num_rounds != 8) return CRYPT_INVALID_ROUNDS; if (keylen != 16) return CRYPT_INVALID_KEYSIZE; return s_setup_key(key, skey); } int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_process_block(pt, ct, skey->idea.ek); #ifdef LTC_CLEAN_STACK burn_stack(sizeof(ushort16) * 6 + sizeof(int)); #endif return err; } int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_process_block(ct, pt, skey->idea.dk); #ifdef LTC_CLEAN_STACK burn_stack(sizeof(ushort16) * 6 + sizeof(int)); #endif return err; } void idea_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } int idea_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } *keysize = 16; return CRYPT_OK; } int idea_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[16], pt[8], ct[8]; } tests[] = { { /* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F } }, { /* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 } }, { /* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 } }, { /* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA } }, { /* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C } }, }; unsigned char buf[2][8]; symmetric_key key; int err, x; if (sizeof(ushort16) != 2) { return CRYPT_FAIL_TESTVECTOR; } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) { return err; } if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { return err; } if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { return err; } if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/kasumi.c000066400000000000000000000230371464416617300233030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file kasumi.c Implementation of the 3GPP Kasumi block cipher Derived from the 3GPP standard source code */ #include "tomcrypt_private.h" #ifdef LTC_KASUMI typedef unsigned u16; #define ROL16(x, y) ((((x)<<(y)) | ((x)>>(16-(y)))) & 0xFFFF) const struct ltc_cipher_descriptor kasumi_desc = { "kasumi", 21, 16, 16, 8, 8, &kasumi_setup, &kasumi_ecb_encrypt, &kasumi_ecb_decrypt, &kasumi_test, &kasumi_done, &kasumi_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static u16 FI( u16 in, u16 subkey ) { u16 nine, seven; static const u16 S7[128] = { 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,123, 33, 55,113, 39,114, 21, 67, 65, 12, 47, 73, 46, 27, 25,111,124, 81, 53, 9,121, 79, 52, 60, 58, 48,101,127, 40,120,104, 70, 71, 43, 20,122, 72, 61, 23,109, 13,100, 77, 1, 16, 7, 82, 10,105, 98, 117,116, 76, 11, 89,106, 0,125,118, 99, 86, 69, 30, 57,126, 87, 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66, 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29,115, 44, 64,107,108, 24,110, 83, 36, 78, 42, 19, 15, 41, 88,119, 59, 3 }; static const u16 S9[512] = { 167,239,161,379,391,334, 9,338, 38,226, 48,358,452,385, 90,397, 183,253,147,331,415,340, 51,362,306,500,262, 82,216,159,356,177, 175,241,489, 37,206, 17, 0,333, 44,254,378, 58,143,220, 81,400, 95, 3,315,245, 54,235,218,405,472,264,172,494,371,290,399, 76, 165,197,395,121,257,480,423,212,240, 28,462,176,406,507,288,223, 501,407,249,265, 89,186,221,428,164, 74,440,196,458,421,350,163, 232,158,134,354, 13,250,491,142,191, 69,193,425,152,227,366,135, 344,300,276,242,437,320,113,278, 11,243, 87,317, 36, 93,496, 27, 487,446,482, 41, 68,156,457,131,326,403,339, 20, 39,115,442,124, 475,384,508, 53,112,170,479,151,126,169, 73,268,279,321,168,364, 363,292, 46,499,393,327,324, 24,456,267,157,460,488,426,309,229, 439,506,208,271,349,401,434,236, 16,209,359, 52, 56,120,199,277, 465,416,252,287,246, 6, 83,305,420,345,153,502, 65, 61,244,282, 173,222,418, 67,386,368,261,101,476,291,195,430, 49, 79,166,330, 280,383,373,128,382,408,155,495,367,388,274,107,459,417, 62,454, 132,225,203,316,234, 14,301, 91,503,286,424,211,347,307,140,374, 35,103,125,427, 19,214,453,146,498,314,444,230,256,329,198,285, 50,116, 78,410, 10,205,510,171,231, 45,139,467, 29, 86,505, 32, 72, 26,342,150,313,490,431,238,411,325,149,473, 40,119,174,355, 185,233,389, 71,448,273,372, 55,110,178,322, 12,469,392,369,190, 1,109,375,137,181, 88, 75,308,260,484, 98,272,370,275,412,111, 336,318, 4,504,492,259,304, 77,337,435, 21,357,303,332,483, 18, 47, 85, 25,497,474,289,100,269,296,478,270,106, 31,104,433, 84, 414,486,394, 96, 99,154,511,148,413,361,409,255,162,215,302,201, 266,351,343,144,441,365,108,298,251, 34,182,509,138,210,335,133, 311,352,328,141,396,346,123,319,450,281,429,228,443,481, 92,404, 485,422,248,297, 23,213,130,466, 22,217,283, 70,294,360,419,127, 312,377, 7,468,194, 2,117,295,463,258,224,447,247,187, 80,398, 284,353,105,390,299,471,470,184, 57,200,348, 63,204,188, 33,451, 97, 30,310,219, 94,160,129,493, 64,179,263,102,189,207,114,402, 438,477,387,122,192, 42,381, 5,145,118,180,449,293,323,136,380, 43, 66, 60,455,341,445,202,432, 8,237, 15,376,436,464, 59,461}; /* The sixteen bit input is split into two unequal halves, * * nine bits and seven bits - as is the subkey */ nine = (u16)(in>>7)&0x1FF; seven = (u16)(in&0x7F); /* Now run the various operations */ nine = (u16)(S9[nine] ^ seven); seven = (u16)(S7[seven] ^ (nine & 0x7F)); seven ^= (subkey>>9); nine ^= (subkey&0x1FF); nine = (u16)(S9[nine] ^ seven); seven = (u16)(S7[seven] ^ (nine & 0x7F)); return (u16)(seven<<9) + nine; } static ulong32 FO( ulong32 in, int round_no, const symmetric_key *key) { u16 left, right; /* Split the input into two 16-bit words */ left = (u16)(in>>16); right = (u16) in&0xFFFF; /* Now apply the same basic transformation three times */ left ^= key->kasumi.KOi1[round_no]; left = FI( left, key->kasumi.KIi1[round_no] ); left ^= right; right ^= key->kasumi.KOi2[round_no]; right = FI( right, key->kasumi.KIi2[round_no] ); right ^= left; left ^= key->kasumi.KOi3[round_no]; left = FI( left, key->kasumi.KIi3[round_no] ); left ^= right; return (((ulong32)right)<<16)+left; } static ulong32 FL( ulong32 in, int round_no, const symmetric_key *key ) { u16 l, r, a, b; /* split out the left and right halves */ l = (u16)(in>>16); r = (u16)(in)&0xFFFF; /* do the FL() operations */ a = (u16) (l & key->kasumi.KLi1[round_no]); r ^= ROL16(a,1); b = (u16)(r | key->kasumi.KLi2[round_no]); l ^= ROL16(b,1); /* put the two halves back together */ return (((ulong32)l)<<16) + r; } int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 left, right, temp; int n; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(left, pt); LOAD32H(right, pt+4); for (n = 0; n <= 7; ) { temp = FL(left, n, skey); temp = FO(temp, n++, skey); right ^= temp; temp = FO(right, n, skey); temp = FL(temp, n++, skey); left ^= temp; } STORE32H(left, ct); STORE32H(right, ct+4); return CRYPT_OK; } int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 left, right, temp; int n; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(left, ct); LOAD32H(right, ct+4); for (n = 7; n >= 0; ) { temp = FO(right, n, skey); temp = FL(temp, n--, skey); left ^= temp; temp = FL(left, n, skey); temp = FO(temp, n--, skey); right ^= temp; } STORE32H(left, pt); STORE32H(right, pt+4); return CRYPT_OK; } int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { static const u16 C[8] = { 0x0123,0x4567,0x89AB,0xCDEF, 0xFEDC,0xBA98,0x7654,0x3210 }; u16 ukey[8], Kprime[8]; int n; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 0 && num_rounds != 8) { return CRYPT_INVALID_ROUNDS; } /* Start by ensuring the subkeys are endian correct on a 16-bit basis */ for (n = 0; n < 8; n++ ) { ukey[n] = (((u16)key[2*n]) << 8) | key[2*n+1]; } /* Now build the K'[] keys */ for (n = 0; n < 8; n++) { Kprime[n] = ukey[n] ^ C[n]; } /* Finally construct the various sub keys */ for(n = 0; n < 8; n++) { skey->kasumi.KLi1[n] = ROL16(ukey[n],1); skey->kasumi.KLi2[n] = Kprime[(n+2)&0x7]; skey->kasumi.KOi1[n] = ROL16(ukey[(n+1)&0x7],5); skey->kasumi.KOi2[n] = ROL16(ukey[(n+5)&0x7],8); skey->kasumi.KOi3[n] = ROL16(ukey[(n+6)&0x7],13); skey->kasumi.KIi1[n] = Kprime[(n+4)&0x7]; skey->kasumi.KIi2[n] = Kprime[(n+3)&0x7]; skey->kasumi.KIi3[n] = Kprime[(n+7)&0x7]; } return CRYPT_OK; } void kasumi_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } int kasumi_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize >= 16) { *keysize = 16; return CRYPT_OK; } return CRYPT_INVALID_KEYSIZE; } int kasumi_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[16], pt[8], ct[8]; } tests[] = { { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x4B, 0x58, 0xA7, 0x71, 0xAF, 0xC7, 0xE5, 0xE8 } }, { { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x7E, 0xEF, 0x11, 0x3C, 0x95, 0xBB, 0x5A, 0x77 } }, { { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x5F, 0x14, 0x06, 0x86, 0xD7, 0xAD, 0x5A, 0x39 }, }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x2E, 0x14, 0x91, 0xCF, 0x70, 0xAA, 0x46, 0x5D } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xB5, 0x45, 0x86, 0xF4, 0xAB, 0x9A, 0xE5, 0x46 } }, }; unsigned char buf[2][8]; symmetric_key key; int err, x; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = kasumi_setup(tests[x].key, 16, 0, &key)) != CRYPT_OK) { return err; } if ((err = kasumi_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { return err; } if ((err = kasumi_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { return err; } if (compare_testvector(buf[1], 8, tests[x].pt, 8, "Kasumi Decrypt", x) || compare_testvector(buf[0], 8, tests[x].ct, 8, "Kasumi Encrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/khazad.c000066400000000000000000002124401464416617300232520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file khazad.c Khazad implementation derived from public domain source Authors: Paulo S.L.M. Barreto and Vincent Rijmen. */ #ifdef LTC_KHAZAD const struct ltc_cipher_descriptor khazad_desc = { "khazad", 18, 16, 16, 8, 8, &khazad_setup, &khazad_ecb_encrypt, &khazad_ecb_decrypt, &khazad_test, &khazad_done, &khazad_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #define R 8 static const ulong64 T0[256] = { CONST64(0xbad3d268bbb96a01), CONST64(0x54fc4d19e59a66b1), CONST64(0x2f71bc93e26514cd), CONST64(0x749ccdb925871b51), CONST64(0x53f55102f7a257a4), CONST64(0xd3686bb8d0d6be03), CONST64(0xd26b6fbdd6deb504), CONST64(0x4dd72964b35285fe), CONST64(0x50f05d0dfdba4aad), CONST64(0xace98a26cf09e063), CONST64(0x8d8a0e83091c9684), CONST64(0xbfdcc679a5914d1a), CONST64(0x7090ddad3da7374d), CONST64(0x52f65507f1aa5ca3), CONST64(0x9ab352c87ba417e1), CONST64(0x4cd42d61b55a8ef9), CONST64(0xea238f65460320ac), CONST64(0xd56273a6c4e68411), CONST64(0x97a466f155cc68c2), CONST64(0xd16e63b2dcc6a80d), CONST64(0x3355ccffaa85d099), CONST64(0x51f35908fbb241aa), CONST64(0x5bed712ac7e20f9c), CONST64(0xa6f7a204f359ae55), CONST64(0xde7f5f81febec120), CONST64(0x48d83d75ad7aa2e5), CONST64(0xa8e59a32d729cc7f), CONST64(0x99b65ec771bc0ae8), CONST64(0xdb704b90e096e63b), CONST64(0x3256c8faac8ddb9e), CONST64(0xb7c4e65195d11522), CONST64(0xfc19d72b32b3aace), CONST64(0xe338ab48704b7393), CONST64(0x9ebf42dc63843bfd), CONST64(0x91ae7eef41fc52d0), CONST64(0x9bb056cd7dac1ce6), CONST64(0xe23baf4d76437894), CONST64(0xbbd0d66dbdb16106), CONST64(0x41c319589b32f1da), CONST64(0x6eb2a5cb7957e517), CONST64(0xa5f2ae0bf941b35c), CONST64(0xcb400bc08016564b), CONST64(0x6bbdb1da677fc20c), CONST64(0x95a26efb59dc7ecc), CONST64(0xa1febe1fe1619f40), CONST64(0xf308eb1810cbc3e3), CONST64(0xb1cefe4f81e12f30), CONST64(0x0206080a0c10160e), CONST64(0xcc4917db922e675e), CONST64(0xc45137f3a26e3f66), CONST64(0x1d2774694ee8cf53), CONST64(0x143c504478a09c6c), CONST64(0xc3582be8b0560e73), CONST64(0x63a591f2573f9a34), CONST64(0xda734f95e69eed3c), CONST64(0x5de76934d3d2358e), CONST64(0x5fe1613edfc22380), CONST64(0xdc79578bf2aed72e), CONST64(0x7d87e99413cf486e), CONST64(0xcd4a13de94266c59), CONST64(0x7f81e19e1fdf5e60), CONST64(0x5aee752fc1ea049b), CONST64(0x6cb4adc17547f319), CONST64(0x5ce46d31d5da3e89), CONST64(0xf704fb0c08ebefff), CONST64(0x266a98bed42d47f2), CONST64(0xff1cdb2438abb7c7), CONST64(0xed2a937e543b11b9), CONST64(0xe825876f4a1336a2), CONST64(0x9dba4ed3699c26f4), CONST64(0x6fb1a1ce7f5fee10), CONST64(0x8e8f028c03048b8d), CONST64(0x192b647d56c8e34f), CONST64(0xa0fdba1ae7699447), CONST64(0xf00de7171ad3deea), CONST64(0x89861e97113cba98), CONST64(0x0f113c332278692d), CONST64(0x07091c1b12383115), CONST64(0xafec8629c511fd6a), CONST64(0xfb10cb30208b9bdb), CONST64(0x0818202830405838), CONST64(0x153f54417ea8976b), CONST64(0x0d1734392e687f23), CONST64(0x040c101418202c1c), CONST64(0x0103040506080b07), CONST64(0x64ac8de94507ab21), CONST64(0xdf7c5b84f8b6ca27), CONST64(0x769ac5b329970d5f), CONST64(0x798bf9800bef6472), CONST64(0xdd7a538ef4a6dc29), CONST64(0x3d47f4c98ef5b2b3), CONST64(0x163a584e74b08a62), CONST64(0x3f41fcc382e5a4bd), CONST64(0x3759dcebb2a5fc85), CONST64(0x6db7a9c4734ff81e), CONST64(0x3848e0d890dd95a8), CONST64(0xb9d6de67b1a17708), CONST64(0x7395d1a237bf2a44), CONST64(0xe926836a4c1b3da5), CONST64(0x355fd4e1beb5ea8b), CONST64(0x55ff491ce3926db6), CONST64(0x7193d9a83baf3c4a), CONST64(0x7b8df18a07ff727c), CONST64(0x8c890a860f149d83), CONST64(0x7296d5a731b72143), CONST64(0x88851a921734b19f), CONST64(0xf607ff090ee3e4f8), CONST64(0x2a7ea882fc4d33d6), CONST64(0x3e42f8c684edafba), CONST64(0x5ee2653bd9ca2887), CONST64(0x27699cbbd2254cf5), CONST64(0x46ca0543890ac0cf), CONST64(0x0c14303c28607424), CONST64(0x65af89ec430fa026), CONST64(0x68b8bdd56d67df05), CONST64(0x61a399f85b2f8c3a), CONST64(0x03050c0f0a181d09), CONST64(0xc15e23e2bc46187d), CONST64(0x57f94116ef827bb8), CONST64(0xd6677fa9cefe9918), CONST64(0xd976439aec86f035), CONST64(0x58e87d25cdfa1295), CONST64(0xd875479fea8efb32), CONST64(0x66aa85e34917bd2f), CONST64(0xd7647bacc8f6921f), CONST64(0x3a4ee8d29ccd83a6), CONST64(0xc84507cf8a0e4b42), CONST64(0x3c44f0cc88fdb9b4), CONST64(0xfa13cf35268390dc), CONST64(0x96a762f453c463c5), CONST64(0xa7f4a601f551a552), CONST64(0x98b55ac277b401ef), CONST64(0xec29977b52331abe), CONST64(0xb8d5da62b7a97c0f), CONST64(0xc7543bfca876226f), CONST64(0xaeef822cc319f66d), CONST64(0x69bbb9d06b6fd402), CONST64(0x4bdd317aa762bfec), CONST64(0xabe0963ddd31d176), CONST64(0xa9e69e37d121c778), CONST64(0x67a981e64f1fb628), CONST64(0x0a1e28223c504e36), CONST64(0x47c901468f02cbc8), CONST64(0xf20bef1d16c3c8e4), CONST64(0xb5c2ee5b99c1032c), CONST64(0x226688aacc0d6bee), CONST64(0xe532b356647b4981), CONST64(0xee2f9f715e230cb0), CONST64(0xbedfc27ca399461d), CONST64(0x2b7dac87fa4538d1), CONST64(0x819e3ebf217ce2a0), CONST64(0x1236485a6c90a67e), CONST64(0x839836b52d6cf4ae), CONST64(0x1b2d6c775ad8f541), CONST64(0x0e1238362470622a), CONST64(0x23658cafca0560e9), CONST64(0xf502f30604fbf9f1), CONST64(0x45cf094c8312ddc6), CONST64(0x216384a5c61576e7), CONST64(0xce4f1fd19e3e7150), CONST64(0x49db3970ab72a9e2), CONST64(0x2c74b09ce87d09c4), CONST64(0xf916c33a2c9b8dd5), CONST64(0xe637bf596e635488), CONST64(0xb6c7e25493d91e25), CONST64(0x2878a088f05d25d8), CONST64(0x17395c4b72b88165), CONST64(0x829b32b02b64ffa9), CONST64(0x1a2e68725cd0fe46), CONST64(0x8b80169d1d2cac96), CONST64(0xfe1fdf213ea3bcc0), CONST64(0x8a8312981b24a791), CONST64(0x091b242d3648533f), CONST64(0xc94603ca8c064045), CONST64(0x879426a1354cd8b2), CONST64(0x4ed2256bb94a98f7), CONST64(0xe13ea3427c5b659d), CONST64(0x2e72b896e46d1fca), CONST64(0xe431b75362734286), CONST64(0xe03da7477a536e9a), CONST64(0xeb208b60400b2bab), CONST64(0x90ad7aea47f459d7), CONST64(0xa4f1aa0eff49b85b), CONST64(0x1e22786644f0d25a), CONST64(0x85922eab395ccebc), CONST64(0x60a09dfd5d27873d), CONST64(0x0000000000000000), CONST64(0x256f94b1de355afb), CONST64(0xf401f70302f3f2f6), CONST64(0xf10ee3121cdbd5ed), CONST64(0x94a16afe5fd475cb), CONST64(0x0b1d2c273a584531), CONST64(0xe734bb5c686b5f8f), CONST64(0x759fc9bc238f1056), CONST64(0xef2c9b74582b07b7), CONST64(0x345cd0e4b8bde18c), CONST64(0x3153c4f5a695c697), CONST64(0xd46177a3c2ee8f16), CONST64(0xd06d67b7dacea30a), CONST64(0x869722a43344d3b5), CONST64(0x7e82e59b19d75567), CONST64(0xadea8e23c901eb64), CONST64(0xfd1ad32e34bba1c9), CONST64(0x297ba48df6552edf), CONST64(0x3050c0f0a09dcd90), CONST64(0x3b4decd79ac588a1), CONST64(0x9fbc46d9658c30fa), CONST64(0xf815c73f2a9386d2), CONST64(0xc6573ff9ae7e2968), CONST64(0x13354c5f6a98ad79), CONST64(0x060a181e14303a12), CONST64(0x050f14111e28271b), CONST64(0xc55233f6a4663461), CONST64(0x113344556688bb77), CONST64(0x7799c1b62f9f0658), CONST64(0x7c84ed9115c74369), CONST64(0x7a8ef58f01f7797b), CONST64(0x7888fd850de76f75), CONST64(0x365ad8eeb4adf782), CONST64(0x1c24706c48e0c454), CONST64(0x394be4dd96d59eaf), CONST64(0x59eb7920cbf21992), CONST64(0x1828607850c0e848), CONST64(0x56fa4513e98a70bf), CONST64(0xb3c8f6458df1393e), CONST64(0xb0cdfa4a87e92437), CONST64(0x246c90b4d83d51fc), CONST64(0x206080a0c01d7de0), CONST64(0xb2cbf2408bf93239), CONST64(0x92ab72e04be44fd9), CONST64(0xa3f8b615ed71894e), CONST64(0xc05d27e7ba4e137a), CONST64(0x44cc0d49851ad6c1), CONST64(0x62a695f751379133), CONST64(0x103040506080b070), CONST64(0xb4c1ea5e9fc9082b), CONST64(0x84912aae3f54c5bb), CONST64(0x43c511529722e7d4), CONST64(0x93a876e54dec44de), CONST64(0xc25b2fedb65e0574), CONST64(0x4ade357fa16ab4eb), CONST64(0xbddace73a9815b14), CONST64(0x8f8c0689050c808a), CONST64(0x2d77b499ee7502c3), CONST64(0xbcd9ca76af895013), CONST64(0x9cb94ad66f942df3), CONST64(0x6abeb5df6177c90b), CONST64(0x40c01d5d9d3afadd), CONST64(0xcf4c1bd498367a57), CONST64(0xa2fbb210eb798249), CONST64(0x809d3aba2774e9a7), CONST64(0x4fd1216ebf4293f0), CONST64(0x1f217c6342f8d95d), CONST64(0xca430fc5861e5d4c), CONST64(0xaae39238db39da71), CONST64(0x42c61557912aecd3), }; static const ulong64 T1[256] = { CONST64(0xd3ba68d2b9bb016a), CONST64(0xfc54194d9ae5b166), CONST64(0x712f93bc65e2cd14), CONST64(0x9c74b9cd8725511b), CONST64(0xf5530251a2f7a457), CONST64(0x68d3b86bd6d003be), CONST64(0x6bd2bd6fded604b5), CONST64(0xd74d642952b3fe85), CONST64(0xf0500d5dbafdad4a), CONST64(0xe9ac268a09cf63e0), CONST64(0x8a8d830e1c098496), CONST64(0xdcbf79c691a51a4d), CONST64(0x9070addda73d4d37), CONST64(0xf6520755aaf1a35c), CONST64(0xb39ac852a47be117), CONST64(0xd44c612d5ab5f98e), CONST64(0x23ea658f0346ac20), CONST64(0x62d5a673e6c41184), CONST64(0xa497f166cc55c268), CONST64(0x6ed1b263c6dc0da8), CONST64(0x5533ffcc85aa99d0), CONST64(0xf3510859b2fbaa41), CONST64(0xed5b2a71e2c79c0f), CONST64(0xf7a604a259f355ae), CONST64(0x7fde815fbefe20c1), CONST64(0xd848753d7aade5a2), CONST64(0xe5a8329a29d77fcc), CONST64(0xb699c75ebc71e80a), CONST64(0x70db904b96e03be6), CONST64(0x5632fac88dac9edb), CONST64(0xc4b751e6d1952215), CONST64(0x19fc2bd7b332ceaa), CONST64(0x38e348ab4b709373), CONST64(0xbf9edc428463fd3b), CONST64(0xae91ef7efc41d052), CONST64(0xb09bcd56ac7de61c), CONST64(0x3be24daf43769478), CONST64(0xd0bb6dd6b1bd0661), CONST64(0xc3415819329bdaf1), CONST64(0xb26ecba5577917e5), CONST64(0xf2a50bae41f95cb3), CONST64(0x40cbc00b16804b56), CONST64(0xbd6bdab17f670cc2), CONST64(0xa295fb6edc59cc7e), CONST64(0xfea11fbe61e1409f), CONST64(0x08f318ebcb10e3c3), CONST64(0xceb14ffee181302f), CONST64(0x06020a08100c0e16), CONST64(0x49ccdb172e925e67), CONST64(0x51c4f3376ea2663f), CONST64(0x271d6974e84e53cf), CONST64(0x3c144450a0786c9c), CONST64(0x58c3e82b56b0730e), CONST64(0xa563f2913f57349a), CONST64(0x73da954f9ee63ced), CONST64(0xe75d3469d2d38e35), CONST64(0xe15f3e61c2df8023), CONST64(0x79dc8b57aef22ed7), CONST64(0x877d94e9cf136e48), CONST64(0x4acdde132694596c), CONST64(0x817f9ee1df1f605e), CONST64(0xee5a2f75eac19b04), CONST64(0xb46cc1ad477519f3), CONST64(0xe45c316ddad5893e), CONST64(0x04f70cfbeb08ffef), CONST64(0x6a26be982dd4f247), CONST64(0x1cff24dbab38c7b7), CONST64(0x2aed7e933b54b911), CONST64(0x25e86f87134aa236), CONST64(0xba9dd34e9c69f426), CONST64(0xb16fcea15f7f10ee), CONST64(0x8f8e8c0204038d8b), CONST64(0x2b197d64c8564fe3), CONST64(0xfda01aba69e74794), CONST64(0x0df017e7d31aeade), CONST64(0x8689971e3c1198ba), CONST64(0x110f333c78222d69), CONST64(0x09071b1c38121531), CONST64(0xecaf298611c56afd), CONST64(0x10fb30cb8b20db9b), CONST64(0x1808282040303858), CONST64(0x3f154154a87e6b97), CONST64(0x170d3934682e237f), CONST64(0x0c04141020181c2c), CONST64(0x030105040806070b), CONST64(0xac64e98d074521ab), CONST64(0x7cdf845bb6f827ca), CONST64(0x9a76b3c597295f0d), CONST64(0x8b7980f9ef0b7264), CONST64(0x7add8e53a6f429dc), CONST64(0x473dc9f4f58eb3b2), CONST64(0x3a164e58b074628a), CONST64(0x413fc3fce582bda4), CONST64(0x5937ebdca5b285fc), CONST64(0xb76dc4a94f731ef8), CONST64(0x4838d8e0dd90a895), CONST64(0xd6b967dea1b10877), CONST64(0x9573a2d1bf37442a), CONST64(0x26e96a831b4ca53d), CONST64(0x5f35e1d4b5be8bea), CONST64(0xff551c4992e3b66d), CONST64(0x9371a8d9af3b4a3c), CONST64(0x8d7b8af1ff077c72), CONST64(0x898c860a140f839d), CONST64(0x9672a7d5b7314321), CONST64(0x8588921a34179fb1), CONST64(0x07f609ffe30ef8e4), CONST64(0x7e2a82a84dfcd633), CONST64(0x423ec6f8ed84baaf), CONST64(0xe25e3b65cad98728), CONST64(0x6927bb9c25d2f54c), CONST64(0xca4643050a89cfc0), CONST64(0x140c3c3060282474), CONST64(0xaf65ec890f4326a0), CONST64(0xb868d5bd676d05df), CONST64(0xa361f8992f5b3a8c), CONST64(0x05030f0c180a091d), CONST64(0x5ec1e22346bc7d18), CONST64(0xf957164182efb87b), CONST64(0x67d6a97ffece1899), CONST64(0x76d99a4386ec35f0), CONST64(0xe858257dfacd9512), CONST64(0x75d89f478eea32fb), CONST64(0xaa66e38517492fbd), CONST64(0x64d7ac7bf6c81f92), CONST64(0x4e3ad2e8cd9ca683), CONST64(0x45c8cf070e8a424b), CONST64(0x443cccf0fd88b4b9), CONST64(0x13fa35cf8326dc90), CONST64(0xa796f462c453c563), CONST64(0xf4a701a651f552a5), CONST64(0xb598c25ab477ef01), CONST64(0x29ec7b973352be1a), CONST64(0xd5b862daa9b70f7c), CONST64(0x54c7fc3b76a86f22), CONST64(0xefae2c8219c36df6), CONST64(0xbb69d0b96f6b02d4), CONST64(0xdd4b7a3162a7ecbf), CONST64(0xe0ab3d9631dd76d1), CONST64(0xe6a9379e21d178c7), CONST64(0xa967e6811f4f28b6), CONST64(0x1e0a2228503c364e), CONST64(0xc9474601028fc8cb), CONST64(0x0bf21defc316e4c8), CONST64(0xc2b55beec1992c03), CONST64(0x6622aa880dccee6b), CONST64(0x32e556b37b648149), CONST64(0x2fee719f235eb00c), CONST64(0xdfbe7cc299a31d46), CONST64(0x7d2b87ac45fad138), CONST64(0x9e81bf3e7c21a0e2), CONST64(0x36125a48906c7ea6), CONST64(0x9883b5366c2daef4), CONST64(0x2d1b776cd85a41f5), CONST64(0x120e363870242a62), CONST64(0x6523af8c05cae960), CONST64(0x02f506f3fb04f1f9), CONST64(0xcf454c091283c6dd), CONST64(0x6321a58415c6e776), CONST64(0x4fced11f3e9e5071), CONST64(0xdb49703972abe2a9), CONST64(0x742c9cb07de8c409), CONST64(0x16f93ac39b2cd58d), CONST64(0x37e659bf636e8854), CONST64(0xc7b654e2d993251e), CONST64(0x782888a05df0d825), CONST64(0x39174b5cb8726581), CONST64(0x9b82b032642ba9ff), CONST64(0x2e1a7268d05c46fe), CONST64(0x808b9d162c1d96ac), CONST64(0x1ffe21dfa33ec0bc), CONST64(0x838a9812241b91a7), CONST64(0x1b092d2448363f53), CONST64(0x46c9ca03068c4540), CONST64(0x9487a1264c35b2d8), CONST64(0xd24e6b254ab9f798), CONST64(0x3ee142a35b7c9d65), CONST64(0x722e96b86de4ca1f), CONST64(0x31e453b773628642), CONST64(0x3de047a7537a9a6e), CONST64(0x20eb608b0b40ab2b), CONST64(0xad90ea7af447d759), CONST64(0xf1a40eaa49ff5bb8), CONST64(0x221e6678f0445ad2), CONST64(0x9285ab2e5c39bcce), CONST64(0xa060fd9d275d3d87), CONST64(0x0000000000000000), CONST64(0x6f25b19435defb5a), CONST64(0x01f403f7f302f6f2), CONST64(0x0ef112e3db1cedd5), CONST64(0xa194fe6ad45fcb75), CONST64(0x1d0b272c583a3145), CONST64(0x34e75cbb6b688f5f), CONST64(0x9f75bcc98f235610), CONST64(0x2cef749b2b58b707), CONST64(0x5c34e4d0bdb88ce1), CONST64(0x5331f5c495a697c6), CONST64(0x61d4a377eec2168f), CONST64(0x6dd0b767ceda0aa3), CONST64(0x9786a4224433b5d3), CONST64(0x827e9be5d7196755), CONST64(0xeaad238e01c964eb), CONST64(0x1afd2ed3bb34c9a1), CONST64(0x7b298da455f6df2e), CONST64(0x5030f0c09da090cd), CONST64(0x4d3bd7ecc59aa188), CONST64(0xbc9fd9468c65fa30), CONST64(0x15f83fc7932ad286), CONST64(0x57c6f93f7eae6829), CONST64(0x35135f4c986a79ad), CONST64(0x0a061e183014123a), CONST64(0x0f051114281e1b27), CONST64(0x52c5f63366a46134), CONST64(0x33115544886677bb), CONST64(0x9977b6c19f2f5806), CONST64(0x847c91edc7156943), CONST64(0x8e7a8ff5f7017b79), CONST64(0x887885fde70d756f), CONST64(0x5a36eed8adb482f7), CONST64(0x241c6c70e04854c4), CONST64(0x4b39dde4d596af9e), CONST64(0xeb592079f2cb9219), CONST64(0x28187860c05048e8), CONST64(0xfa5613458ae9bf70), CONST64(0xc8b345f6f18d3e39), CONST64(0xcdb04afae9873724), CONST64(0x6c24b4903dd8fc51), CONST64(0x6020a0801dc0e07d), CONST64(0xcbb240f2f98b3932), CONST64(0xab92e072e44bd94f), CONST64(0xf8a315b671ed4e89), CONST64(0x5dc0e7274eba7a13), CONST64(0xcc44490d1a85c1d6), CONST64(0xa662f79537513391), CONST64(0x30105040806070b0), CONST64(0xc1b45eeac99f2b08), CONST64(0x9184ae2a543fbbc5), CONST64(0xc54352112297d4e7), CONST64(0xa893e576ec4dde44), CONST64(0x5bc2ed2f5eb67405), CONST64(0xde4a7f356aa1ebb4), CONST64(0xdabd73ce81a9145b), CONST64(0x8c8f89060c058a80), CONST64(0x772d99b475eec302), CONST64(0xd9bc76ca89af1350), CONST64(0xb99cd64a946ff32d), CONST64(0xbe6adfb577610bc9), CONST64(0xc0405d1d3a9dddfa), CONST64(0x4ccfd41b3698577a), CONST64(0xfba210b279eb4982), CONST64(0x9d80ba3a7427a7e9), CONST64(0xd14f6e2142bff093), CONST64(0x211f637cf8425dd9), CONST64(0x43cac50f1e864c5d), CONST64(0xe3aa389239db71da), CONST64(0xc64257152a91d3ec), }; static const ulong64 T2[256] = { CONST64(0xd268bad36a01bbb9), CONST64(0x4d1954fc66b1e59a), CONST64(0xbc932f7114cde265), CONST64(0xcdb9749c1b512587), CONST64(0x510253f557a4f7a2), CONST64(0x6bb8d368be03d0d6), CONST64(0x6fbdd26bb504d6de), CONST64(0x29644dd785feb352), CONST64(0x5d0d50f04aadfdba), CONST64(0x8a26ace9e063cf09), CONST64(0x0e838d8a9684091c), CONST64(0xc679bfdc4d1aa591), CONST64(0xddad7090374d3da7), CONST64(0x550752f65ca3f1aa), CONST64(0x52c89ab317e17ba4), CONST64(0x2d614cd48ef9b55a), CONST64(0x8f65ea2320ac4603), CONST64(0x73a6d5628411c4e6), CONST64(0x66f197a468c255cc), CONST64(0x63b2d16ea80ddcc6), CONST64(0xccff3355d099aa85), CONST64(0x590851f341aafbb2), CONST64(0x712a5bed0f9cc7e2), CONST64(0xa204a6f7ae55f359), CONST64(0x5f81de7fc120febe), CONST64(0x3d7548d8a2e5ad7a), CONST64(0x9a32a8e5cc7fd729), CONST64(0x5ec799b60ae871bc), CONST64(0x4b90db70e63be096), CONST64(0xc8fa3256db9eac8d), CONST64(0xe651b7c4152295d1), CONST64(0xd72bfc19aace32b3), CONST64(0xab48e3387393704b), CONST64(0x42dc9ebf3bfd6384), CONST64(0x7eef91ae52d041fc), CONST64(0x56cd9bb01ce67dac), CONST64(0xaf4de23b78947643), CONST64(0xd66dbbd06106bdb1), CONST64(0x195841c3f1da9b32), CONST64(0xa5cb6eb2e5177957), CONST64(0xae0ba5f2b35cf941), CONST64(0x0bc0cb40564b8016), CONST64(0xb1da6bbdc20c677f), CONST64(0x6efb95a27ecc59dc), CONST64(0xbe1fa1fe9f40e161), CONST64(0xeb18f308c3e310cb), CONST64(0xfe4fb1ce2f3081e1), CONST64(0x080a0206160e0c10), CONST64(0x17dbcc49675e922e), CONST64(0x37f3c4513f66a26e), CONST64(0x74691d27cf534ee8), CONST64(0x5044143c9c6c78a0), CONST64(0x2be8c3580e73b056), CONST64(0x91f263a59a34573f), CONST64(0x4f95da73ed3ce69e), CONST64(0x69345de7358ed3d2), CONST64(0x613e5fe12380dfc2), CONST64(0x578bdc79d72ef2ae), CONST64(0xe9947d87486e13cf), CONST64(0x13decd4a6c599426), CONST64(0xe19e7f815e601fdf), CONST64(0x752f5aee049bc1ea), CONST64(0xadc16cb4f3197547), CONST64(0x6d315ce43e89d5da), CONST64(0xfb0cf704efff08eb), CONST64(0x98be266a47f2d42d), CONST64(0xdb24ff1cb7c738ab), CONST64(0x937eed2a11b9543b), CONST64(0x876fe82536a24a13), CONST64(0x4ed39dba26f4699c), CONST64(0xa1ce6fb1ee107f5f), CONST64(0x028c8e8f8b8d0304), CONST64(0x647d192be34f56c8), CONST64(0xba1aa0fd9447e769), CONST64(0xe717f00ddeea1ad3), CONST64(0x1e978986ba98113c), CONST64(0x3c330f11692d2278), CONST64(0x1c1b070931151238), CONST64(0x8629afecfd6ac511), CONST64(0xcb30fb109bdb208b), CONST64(0x2028081858383040), CONST64(0x5441153f976b7ea8), CONST64(0x34390d177f232e68), CONST64(0x1014040c2c1c1820), CONST64(0x040501030b070608), CONST64(0x8de964acab214507), CONST64(0x5b84df7cca27f8b6), CONST64(0xc5b3769a0d5f2997), CONST64(0xf980798b64720bef), CONST64(0x538edd7adc29f4a6), CONST64(0xf4c93d47b2b38ef5), CONST64(0x584e163a8a6274b0), CONST64(0xfcc33f41a4bd82e5), CONST64(0xdceb3759fc85b2a5), CONST64(0xa9c46db7f81e734f), CONST64(0xe0d8384895a890dd), CONST64(0xde67b9d67708b1a1), CONST64(0xd1a273952a4437bf), CONST64(0x836ae9263da54c1b), CONST64(0xd4e1355fea8bbeb5), CONST64(0x491c55ff6db6e392), CONST64(0xd9a871933c4a3baf), CONST64(0xf18a7b8d727c07ff), CONST64(0x0a868c899d830f14), CONST64(0xd5a77296214331b7), CONST64(0x1a928885b19f1734), CONST64(0xff09f607e4f80ee3), CONST64(0xa8822a7e33d6fc4d), CONST64(0xf8c63e42afba84ed), CONST64(0x653b5ee22887d9ca), CONST64(0x9cbb27694cf5d225), CONST64(0x054346cac0cf890a), CONST64(0x303c0c1474242860), CONST64(0x89ec65afa026430f), CONST64(0xbdd568b8df056d67), CONST64(0x99f861a38c3a5b2f), CONST64(0x0c0f03051d090a18), CONST64(0x23e2c15e187dbc46), CONST64(0x411657f97bb8ef82), CONST64(0x7fa9d6679918cefe), CONST64(0x439ad976f035ec86), CONST64(0x7d2558e81295cdfa), CONST64(0x479fd875fb32ea8e), CONST64(0x85e366aabd2f4917), CONST64(0x7bacd764921fc8f6), CONST64(0xe8d23a4e83a69ccd), CONST64(0x07cfc8454b428a0e), CONST64(0xf0cc3c44b9b488fd), CONST64(0xcf35fa1390dc2683), CONST64(0x62f496a763c553c4), CONST64(0xa601a7f4a552f551), CONST64(0x5ac298b501ef77b4), CONST64(0x977bec291abe5233), CONST64(0xda62b8d57c0fb7a9), CONST64(0x3bfcc754226fa876), CONST64(0x822caeeff66dc319), CONST64(0xb9d069bbd4026b6f), CONST64(0x317a4bddbfeca762), CONST64(0x963dabe0d176dd31), CONST64(0x9e37a9e6c778d121), CONST64(0x81e667a9b6284f1f), CONST64(0x28220a1e4e363c50), CONST64(0x014647c9cbc88f02), CONST64(0xef1df20bc8e416c3), CONST64(0xee5bb5c2032c99c1), CONST64(0x88aa22666beecc0d), CONST64(0xb356e5324981647b), CONST64(0x9f71ee2f0cb05e23), CONST64(0xc27cbedf461da399), CONST64(0xac872b7d38d1fa45), CONST64(0x3ebf819ee2a0217c), CONST64(0x485a1236a67e6c90), CONST64(0x36b58398f4ae2d6c), CONST64(0x6c771b2df5415ad8), CONST64(0x38360e12622a2470), CONST64(0x8caf236560e9ca05), CONST64(0xf306f502f9f104fb), CONST64(0x094c45cfddc68312), CONST64(0x84a5216376e7c615), CONST64(0x1fd1ce4f71509e3e), CONST64(0x397049dba9e2ab72), CONST64(0xb09c2c7409c4e87d), CONST64(0xc33af9168dd52c9b), CONST64(0xbf59e63754886e63), CONST64(0xe254b6c71e2593d9), CONST64(0xa088287825d8f05d), CONST64(0x5c4b1739816572b8), CONST64(0x32b0829bffa92b64), CONST64(0x68721a2efe465cd0), CONST64(0x169d8b80ac961d2c), CONST64(0xdf21fe1fbcc03ea3), CONST64(0x12988a83a7911b24), CONST64(0x242d091b533f3648), CONST64(0x03cac94640458c06), CONST64(0x26a18794d8b2354c), CONST64(0x256b4ed298f7b94a), CONST64(0xa342e13e659d7c5b), CONST64(0xb8962e721fcae46d), CONST64(0xb753e43142866273), CONST64(0xa747e03d6e9a7a53), CONST64(0x8b60eb202bab400b), CONST64(0x7aea90ad59d747f4), CONST64(0xaa0ea4f1b85bff49), CONST64(0x78661e22d25a44f0), CONST64(0x2eab8592cebc395c), CONST64(0x9dfd60a0873d5d27), CONST64(0x0000000000000000), CONST64(0x94b1256f5afbde35), CONST64(0xf703f401f2f602f3), CONST64(0xe312f10ed5ed1cdb), CONST64(0x6afe94a175cb5fd4), CONST64(0x2c270b1d45313a58), CONST64(0xbb5ce7345f8f686b), CONST64(0xc9bc759f1056238f), CONST64(0x9b74ef2c07b7582b), CONST64(0xd0e4345ce18cb8bd), CONST64(0xc4f53153c697a695), CONST64(0x77a3d4618f16c2ee), CONST64(0x67b7d06da30adace), CONST64(0x22a48697d3b53344), CONST64(0xe59b7e82556719d7), CONST64(0x8e23adeaeb64c901), CONST64(0xd32efd1aa1c934bb), CONST64(0xa48d297b2edff655), CONST64(0xc0f03050cd90a09d), CONST64(0xecd73b4d88a19ac5), CONST64(0x46d99fbc30fa658c), CONST64(0xc73ff81586d22a93), CONST64(0x3ff9c6572968ae7e), CONST64(0x4c5f1335ad796a98), CONST64(0x181e060a3a121430), CONST64(0x1411050f271b1e28), CONST64(0x33f6c5523461a466), CONST64(0x44551133bb776688), CONST64(0xc1b6779906582f9f), CONST64(0xed917c84436915c7), CONST64(0xf58f7a8e797b01f7), CONST64(0xfd8578886f750de7), CONST64(0xd8ee365af782b4ad), CONST64(0x706c1c24c45448e0), CONST64(0xe4dd394b9eaf96d5), CONST64(0x792059eb1992cbf2), CONST64(0x60781828e84850c0), CONST64(0x451356fa70bfe98a), CONST64(0xf645b3c8393e8df1), CONST64(0xfa4ab0cd243787e9), CONST64(0x90b4246c51fcd83d), CONST64(0x80a020607de0c01d), CONST64(0xf240b2cb32398bf9), CONST64(0x72e092ab4fd94be4), CONST64(0xb615a3f8894eed71), CONST64(0x27e7c05d137aba4e), CONST64(0x0d4944ccd6c1851a), CONST64(0x95f762a691335137), CONST64(0x40501030b0706080), CONST64(0xea5eb4c1082b9fc9), CONST64(0x2aae8491c5bb3f54), CONST64(0x115243c5e7d49722), CONST64(0x76e593a844de4dec), CONST64(0x2fedc25b0574b65e), CONST64(0x357f4adeb4eba16a), CONST64(0xce73bdda5b14a981), CONST64(0x06898f8c808a050c), CONST64(0xb4992d7702c3ee75), CONST64(0xca76bcd95013af89), CONST64(0x4ad69cb92df36f94), CONST64(0xb5df6abec90b6177), CONST64(0x1d5d40c0fadd9d3a), CONST64(0x1bd4cf4c7a579836), CONST64(0xb210a2fb8249eb79), CONST64(0x3aba809de9a72774), CONST64(0x216e4fd193f0bf42), CONST64(0x7c631f21d95d42f8), CONST64(0x0fc5ca435d4c861e), CONST64(0x9238aae3da71db39), CONST64(0x155742c6ecd3912a), }; static const ulong64 T3[256] = { CONST64(0x68d2d3ba016ab9bb), CONST64(0x194dfc54b1669ae5), CONST64(0x93bc712fcd1465e2), CONST64(0xb9cd9c74511b8725), CONST64(0x0251f553a457a2f7), CONST64(0xb86b68d303bed6d0), CONST64(0xbd6f6bd204b5ded6), CONST64(0x6429d74dfe8552b3), CONST64(0x0d5df050ad4abafd), CONST64(0x268ae9ac63e009cf), CONST64(0x830e8a8d84961c09), CONST64(0x79c6dcbf1a4d91a5), CONST64(0xaddd90704d37a73d), CONST64(0x0755f652a35caaf1), CONST64(0xc852b39ae117a47b), CONST64(0x612dd44cf98e5ab5), CONST64(0x658f23eaac200346), CONST64(0xa67362d51184e6c4), CONST64(0xf166a497c268cc55), CONST64(0xb2636ed10da8c6dc), CONST64(0xffcc553399d085aa), CONST64(0x0859f351aa41b2fb), CONST64(0x2a71ed5b9c0fe2c7), CONST64(0x04a2f7a655ae59f3), CONST64(0x815f7fde20c1befe), CONST64(0x753dd848e5a27aad), CONST64(0x329ae5a87fcc29d7), CONST64(0xc75eb699e80abc71), CONST64(0x904b70db3be696e0), CONST64(0xfac856329edb8dac), CONST64(0x51e6c4b72215d195), CONST64(0x2bd719fcceaab332), CONST64(0x48ab38e393734b70), CONST64(0xdc42bf9efd3b8463), CONST64(0xef7eae91d052fc41), CONST64(0xcd56b09be61cac7d), CONST64(0x4daf3be294784376), CONST64(0x6dd6d0bb0661b1bd), CONST64(0x5819c341daf1329b), CONST64(0xcba5b26e17e55779), CONST64(0x0baef2a55cb341f9), CONST64(0xc00b40cb4b561680), CONST64(0xdab1bd6b0cc27f67), CONST64(0xfb6ea295cc7edc59), CONST64(0x1fbefea1409f61e1), CONST64(0x18eb08f3e3c3cb10), CONST64(0x4ffeceb1302fe181), CONST64(0x0a0806020e16100c), CONST64(0xdb1749cc5e672e92), CONST64(0xf33751c4663f6ea2), CONST64(0x6974271d53cfe84e), CONST64(0x44503c146c9ca078), CONST64(0xe82b58c3730e56b0), CONST64(0xf291a563349a3f57), CONST64(0x954f73da3ced9ee6), CONST64(0x3469e75d8e35d2d3), CONST64(0x3e61e15f8023c2df), CONST64(0x8b5779dc2ed7aef2), CONST64(0x94e9877d6e48cf13), CONST64(0xde134acd596c2694), CONST64(0x9ee1817f605edf1f), CONST64(0x2f75ee5a9b04eac1), CONST64(0xc1adb46c19f34775), CONST64(0x316de45c893edad5), CONST64(0x0cfb04f7ffefeb08), CONST64(0xbe986a26f2472dd4), CONST64(0x24db1cffc7b7ab38), CONST64(0x7e932aedb9113b54), CONST64(0x6f8725e8a236134a), CONST64(0xd34eba9df4269c69), CONST64(0xcea1b16f10ee5f7f), CONST64(0x8c028f8e8d8b0403), CONST64(0x7d642b194fe3c856), CONST64(0x1abafda0479469e7), CONST64(0x17e70df0eaded31a), CONST64(0x971e868998ba3c11), CONST64(0x333c110f2d697822), CONST64(0x1b1c090715313812), CONST64(0x2986ecaf6afd11c5), CONST64(0x30cb10fbdb9b8b20), CONST64(0x2820180838584030), CONST64(0x41543f156b97a87e), CONST64(0x3934170d237f682e), CONST64(0x14100c041c2c2018), CONST64(0x05040301070b0806), CONST64(0xe98dac6421ab0745), CONST64(0x845b7cdf27cab6f8), CONST64(0xb3c59a765f0d9729), CONST64(0x80f98b797264ef0b), CONST64(0x8e537add29dca6f4), CONST64(0xc9f4473db3b2f58e), CONST64(0x4e583a16628ab074), CONST64(0xc3fc413fbda4e582), CONST64(0xebdc593785fca5b2), CONST64(0xc4a9b76d1ef84f73), CONST64(0xd8e04838a895dd90), CONST64(0x67ded6b90877a1b1), CONST64(0xa2d19573442abf37), CONST64(0x6a8326e9a53d1b4c), CONST64(0xe1d45f358beab5be), CONST64(0x1c49ff55b66d92e3), CONST64(0xa8d993714a3caf3b), CONST64(0x8af18d7b7c72ff07), CONST64(0x860a898c839d140f), CONST64(0xa7d596724321b731), CONST64(0x921a85889fb13417), CONST64(0x09ff07f6f8e4e30e), CONST64(0x82a87e2ad6334dfc), CONST64(0xc6f8423ebaafed84), CONST64(0x3b65e25e8728cad9), CONST64(0xbb9c6927f54c25d2), CONST64(0x4305ca46cfc00a89), CONST64(0x3c30140c24746028), CONST64(0xec89af6526a00f43), CONST64(0xd5bdb86805df676d), CONST64(0xf899a3613a8c2f5b), CONST64(0x0f0c0503091d180a), CONST64(0xe2235ec17d1846bc), CONST64(0x1641f957b87b82ef), CONST64(0xa97f67d61899fece), CONST64(0x9a4376d935f086ec), CONST64(0x257de8589512facd), CONST64(0x9f4775d832fb8eea), CONST64(0xe385aa662fbd1749), CONST64(0xac7b64d71f92f6c8), CONST64(0xd2e84e3aa683cd9c), CONST64(0xcf0745c8424b0e8a), CONST64(0xccf0443cb4b9fd88), CONST64(0x35cf13fadc908326), CONST64(0xf462a796c563c453), CONST64(0x01a6f4a752a551f5), CONST64(0xc25ab598ef01b477), CONST64(0x7b9729ecbe1a3352), CONST64(0x62dad5b80f7ca9b7), CONST64(0xfc3b54c76f2276a8), CONST64(0x2c82efae6df619c3), CONST64(0xd0b9bb6902d46f6b), CONST64(0x7a31dd4becbf62a7), CONST64(0x3d96e0ab76d131dd), CONST64(0x379ee6a978c721d1), CONST64(0xe681a96728b61f4f), CONST64(0x22281e0a364e503c), CONST64(0x4601c947c8cb028f), CONST64(0x1def0bf2e4c8c316), CONST64(0x5beec2b52c03c199), CONST64(0xaa886622ee6b0dcc), CONST64(0x56b332e581497b64), CONST64(0x719f2feeb00c235e), CONST64(0x7cc2dfbe1d4699a3), CONST64(0x87ac7d2bd13845fa), CONST64(0xbf3e9e81a0e27c21), CONST64(0x5a4836127ea6906c), CONST64(0xb5369883aef46c2d), CONST64(0x776c2d1b41f5d85a), CONST64(0x3638120e2a627024), CONST64(0xaf8c6523e96005ca), CONST64(0x06f302f5f1f9fb04), CONST64(0x4c09cf45c6dd1283), CONST64(0xa5846321e77615c6), CONST64(0xd11f4fce50713e9e), CONST64(0x7039db49e2a972ab), CONST64(0x9cb0742cc4097de8), CONST64(0x3ac316f9d58d9b2c), CONST64(0x59bf37e68854636e), CONST64(0x54e2c7b6251ed993), CONST64(0x88a07828d8255df0), CONST64(0x4b5c39176581b872), CONST64(0xb0329b82a9ff642b), CONST64(0x72682e1a46fed05c), CONST64(0x9d16808b96ac2c1d), CONST64(0x21df1ffec0bca33e), CONST64(0x9812838a91a7241b), CONST64(0x2d241b093f534836), CONST64(0xca0346c94540068c), CONST64(0xa1269487b2d84c35), CONST64(0x6b25d24ef7984ab9), CONST64(0x42a33ee19d655b7c), CONST64(0x96b8722eca1f6de4), CONST64(0x53b731e486427362), CONST64(0x47a73de09a6e537a), CONST64(0x608b20ebab2b0b40), CONST64(0xea7aad90d759f447), CONST64(0x0eaaf1a45bb849ff), CONST64(0x6678221e5ad2f044), CONST64(0xab2e9285bcce5c39), CONST64(0xfd9da0603d87275d), CONST64(0x0000000000000000), CONST64(0xb1946f25fb5a35de), CONST64(0x03f701f4f6f2f302), CONST64(0x12e30ef1edd5db1c), CONST64(0xfe6aa194cb75d45f), CONST64(0x272c1d0b3145583a), CONST64(0x5cbb34e78f5f6b68), CONST64(0xbcc99f7556108f23), CONST64(0x749b2cefb7072b58), CONST64(0xe4d05c348ce1bdb8), CONST64(0xf5c4533197c695a6), CONST64(0xa37761d4168feec2), CONST64(0xb7676dd00aa3ceda), CONST64(0xa4229786b5d34433), CONST64(0x9be5827e6755d719), CONST64(0x238eeaad64eb01c9), CONST64(0x2ed31afdc9a1bb34), CONST64(0x8da47b29df2e55f6), CONST64(0xf0c0503090cd9da0), CONST64(0xd7ec4d3ba188c59a), CONST64(0xd946bc9ffa308c65), CONST64(0x3fc715f8d286932a), CONST64(0xf93f57c668297eae), CONST64(0x5f4c351379ad986a), CONST64(0x1e180a06123a3014), CONST64(0x11140f051b27281e), CONST64(0xf63352c5613466a4), CONST64(0x5544331177bb8866), CONST64(0xb6c1997758069f2f), CONST64(0x91ed847c6943c715), CONST64(0x8ff58e7a7b79f701), CONST64(0x85fd8878756fe70d), CONST64(0xeed85a3682f7adb4), CONST64(0x6c70241c54c4e048), CONST64(0xdde44b39af9ed596), CONST64(0x2079eb599219f2cb), CONST64(0x7860281848e8c050), CONST64(0x1345fa56bf708ae9), CONST64(0x45f6c8b33e39f18d), CONST64(0x4afacdb03724e987), CONST64(0xb4906c24fc513dd8), CONST64(0xa0806020e07d1dc0), CONST64(0x40f2cbb23932f98b), CONST64(0xe072ab92d94fe44b), CONST64(0x15b6f8a34e8971ed), CONST64(0xe7275dc07a134eba), CONST64(0x490dcc44c1d61a85), CONST64(0xf795a66233913751), CONST64(0x5040301070b08060), CONST64(0x5eeac1b42b08c99f), CONST64(0xae2a9184bbc5543f), CONST64(0x5211c543d4e72297), CONST64(0xe576a893de44ec4d), CONST64(0xed2f5bc274055eb6), CONST64(0x7f35de4aebb46aa1), CONST64(0x73cedabd145b81a9), CONST64(0x89068c8f8a800c05), CONST64(0x99b4772dc30275ee), CONST64(0x76cad9bc135089af), CONST64(0xd64ab99cf32d946f), CONST64(0xdfb5be6a0bc97761), CONST64(0x5d1dc040ddfa3a9d), CONST64(0xd41b4ccf577a3698), CONST64(0x10b2fba2498279eb), CONST64(0xba3a9d80a7e97427), CONST64(0x6e21d14ff09342bf), CONST64(0x637c211f5dd9f842), CONST64(0xc50f43ca4c5d1e86), CONST64(0x3892e3aa71da39db), CONST64(0x5715c642d3ec2a91), }; static const ulong64 T4[256] = { CONST64(0xbbb96a01bad3d268), CONST64(0xe59a66b154fc4d19), CONST64(0xe26514cd2f71bc93), CONST64(0x25871b51749ccdb9), CONST64(0xf7a257a453f55102), CONST64(0xd0d6be03d3686bb8), CONST64(0xd6deb504d26b6fbd), CONST64(0xb35285fe4dd72964), CONST64(0xfdba4aad50f05d0d), CONST64(0xcf09e063ace98a26), CONST64(0x091c96848d8a0e83), CONST64(0xa5914d1abfdcc679), CONST64(0x3da7374d7090ddad), CONST64(0xf1aa5ca352f65507), CONST64(0x7ba417e19ab352c8), CONST64(0xb55a8ef94cd42d61), CONST64(0x460320acea238f65), CONST64(0xc4e68411d56273a6), CONST64(0x55cc68c297a466f1), CONST64(0xdcc6a80dd16e63b2), CONST64(0xaa85d0993355ccff), CONST64(0xfbb241aa51f35908), CONST64(0xc7e20f9c5bed712a), CONST64(0xf359ae55a6f7a204), CONST64(0xfebec120de7f5f81), CONST64(0xad7aa2e548d83d75), CONST64(0xd729cc7fa8e59a32), CONST64(0x71bc0ae899b65ec7), CONST64(0xe096e63bdb704b90), CONST64(0xac8ddb9e3256c8fa), CONST64(0x95d11522b7c4e651), CONST64(0x32b3aacefc19d72b), CONST64(0x704b7393e338ab48), CONST64(0x63843bfd9ebf42dc), CONST64(0x41fc52d091ae7eef), CONST64(0x7dac1ce69bb056cd), CONST64(0x76437894e23baf4d), CONST64(0xbdb16106bbd0d66d), CONST64(0x9b32f1da41c31958), CONST64(0x7957e5176eb2a5cb), CONST64(0xf941b35ca5f2ae0b), CONST64(0x8016564bcb400bc0), CONST64(0x677fc20c6bbdb1da), CONST64(0x59dc7ecc95a26efb), CONST64(0xe1619f40a1febe1f), CONST64(0x10cbc3e3f308eb18), CONST64(0x81e12f30b1cefe4f), CONST64(0x0c10160e0206080a), CONST64(0x922e675ecc4917db), CONST64(0xa26e3f66c45137f3), CONST64(0x4ee8cf531d277469), CONST64(0x78a09c6c143c5044), CONST64(0xb0560e73c3582be8), CONST64(0x573f9a3463a591f2), CONST64(0xe69eed3cda734f95), CONST64(0xd3d2358e5de76934), CONST64(0xdfc223805fe1613e), CONST64(0xf2aed72edc79578b), CONST64(0x13cf486e7d87e994), CONST64(0x94266c59cd4a13de), CONST64(0x1fdf5e607f81e19e), CONST64(0xc1ea049b5aee752f), CONST64(0x7547f3196cb4adc1), CONST64(0xd5da3e895ce46d31), CONST64(0x08ebeffff704fb0c), CONST64(0xd42d47f2266a98be), CONST64(0x38abb7c7ff1cdb24), CONST64(0x543b11b9ed2a937e), CONST64(0x4a1336a2e825876f), CONST64(0x699c26f49dba4ed3), CONST64(0x7f5fee106fb1a1ce), CONST64(0x03048b8d8e8f028c), CONST64(0x56c8e34f192b647d), CONST64(0xe7699447a0fdba1a), CONST64(0x1ad3deeaf00de717), CONST64(0x113cba9889861e97), CONST64(0x2278692d0f113c33), CONST64(0x1238311507091c1b), CONST64(0xc511fd6aafec8629), CONST64(0x208b9bdbfb10cb30), CONST64(0x3040583808182028), CONST64(0x7ea8976b153f5441), CONST64(0x2e687f230d173439), CONST64(0x18202c1c040c1014), CONST64(0x06080b0701030405), CONST64(0x4507ab2164ac8de9), CONST64(0xf8b6ca27df7c5b84), CONST64(0x29970d5f769ac5b3), CONST64(0x0bef6472798bf980), CONST64(0xf4a6dc29dd7a538e), CONST64(0x8ef5b2b33d47f4c9), CONST64(0x74b08a62163a584e), CONST64(0x82e5a4bd3f41fcc3), CONST64(0xb2a5fc853759dceb), CONST64(0x734ff81e6db7a9c4), CONST64(0x90dd95a83848e0d8), CONST64(0xb1a17708b9d6de67), CONST64(0x37bf2a447395d1a2), CONST64(0x4c1b3da5e926836a), CONST64(0xbeb5ea8b355fd4e1), CONST64(0xe3926db655ff491c), CONST64(0x3baf3c4a7193d9a8), CONST64(0x07ff727c7b8df18a), CONST64(0x0f149d838c890a86), CONST64(0x31b721437296d5a7), CONST64(0x1734b19f88851a92), CONST64(0x0ee3e4f8f607ff09), CONST64(0xfc4d33d62a7ea882), CONST64(0x84edafba3e42f8c6), CONST64(0xd9ca28875ee2653b), CONST64(0xd2254cf527699cbb), CONST64(0x890ac0cf46ca0543), CONST64(0x286074240c14303c), CONST64(0x430fa02665af89ec), CONST64(0x6d67df0568b8bdd5), CONST64(0x5b2f8c3a61a399f8), CONST64(0x0a181d0903050c0f), CONST64(0xbc46187dc15e23e2), CONST64(0xef827bb857f94116), CONST64(0xcefe9918d6677fa9), CONST64(0xec86f035d976439a), CONST64(0xcdfa129558e87d25), CONST64(0xea8efb32d875479f), CONST64(0x4917bd2f66aa85e3), CONST64(0xc8f6921fd7647bac), CONST64(0x9ccd83a63a4ee8d2), CONST64(0x8a0e4b42c84507cf), CONST64(0x88fdb9b43c44f0cc), CONST64(0x268390dcfa13cf35), CONST64(0x53c463c596a762f4), CONST64(0xf551a552a7f4a601), CONST64(0x77b401ef98b55ac2), CONST64(0x52331abeec29977b), CONST64(0xb7a97c0fb8d5da62), CONST64(0xa876226fc7543bfc), CONST64(0xc319f66daeef822c), CONST64(0x6b6fd40269bbb9d0), CONST64(0xa762bfec4bdd317a), CONST64(0xdd31d176abe0963d), CONST64(0xd121c778a9e69e37), CONST64(0x4f1fb62867a981e6), CONST64(0x3c504e360a1e2822), CONST64(0x8f02cbc847c90146), CONST64(0x16c3c8e4f20bef1d), CONST64(0x99c1032cb5c2ee5b), CONST64(0xcc0d6bee226688aa), CONST64(0x647b4981e532b356), CONST64(0x5e230cb0ee2f9f71), CONST64(0xa399461dbedfc27c), CONST64(0xfa4538d12b7dac87), CONST64(0x217ce2a0819e3ebf), CONST64(0x6c90a67e1236485a), CONST64(0x2d6cf4ae839836b5), CONST64(0x5ad8f5411b2d6c77), CONST64(0x2470622a0e123836), CONST64(0xca0560e923658caf), CONST64(0x04fbf9f1f502f306), CONST64(0x8312ddc645cf094c), CONST64(0xc61576e7216384a5), CONST64(0x9e3e7150ce4f1fd1), CONST64(0xab72a9e249db3970), CONST64(0xe87d09c42c74b09c), CONST64(0x2c9b8dd5f916c33a), CONST64(0x6e635488e637bf59), CONST64(0x93d91e25b6c7e254), CONST64(0xf05d25d82878a088), CONST64(0x72b8816517395c4b), CONST64(0x2b64ffa9829b32b0), CONST64(0x5cd0fe461a2e6872), CONST64(0x1d2cac968b80169d), CONST64(0x3ea3bcc0fe1fdf21), CONST64(0x1b24a7918a831298), CONST64(0x3648533f091b242d), CONST64(0x8c064045c94603ca), CONST64(0x354cd8b2879426a1), CONST64(0xb94a98f74ed2256b), CONST64(0x7c5b659de13ea342), CONST64(0xe46d1fca2e72b896), CONST64(0x62734286e431b753), CONST64(0x7a536e9ae03da747), CONST64(0x400b2babeb208b60), CONST64(0x47f459d790ad7aea), CONST64(0xff49b85ba4f1aa0e), CONST64(0x44f0d25a1e227866), CONST64(0x395ccebc85922eab), CONST64(0x5d27873d60a09dfd), CONST64(0x0000000000000000), CONST64(0xde355afb256f94b1), CONST64(0x02f3f2f6f401f703), CONST64(0x1cdbd5edf10ee312), CONST64(0x5fd475cb94a16afe), CONST64(0x3a5845310b1d2c27), CONST64(0x686b5f8fe734bb5c), CONST64(0x238f1056759fc9bc), CONST64(0x582b07b7ef2c9b74), CONST64(0xb8bde18c345cd0e4), CONST64(0xa695c6973153c4f5), CONST64(0xc2ee8f16d46177a3), CONST64(0xdacea30ad06d67b7), CONST64(0x3344d3b5869722a4), CONST64(0x19d755677e82e59b), CONST64(0xc901eb64adea8e23), CONST64(0x34bba1c9fd1ad32e), CONST64(0xf6552edf297ba48d), CONST64(0xa09dcd903050c0f0), CONST64(0x9ac588a13b4decd7), CONST64(0x658c30fa9fbc46d9), CONST64(0x2a9386d2f815c73f), CONST64(0xae7e2968c6573ff9), CONST64(0x6a98ad7913354c5f), CONST64(0x14303a12060a181e), CONST64(0x1e28271b050f1411), CONST64(0xa4663461c55233f6), CONST64(0x6688bb7711334455), CONST64(0x2f9f06587799c1b6), CONST64(0x15c743697c84ed91), CONST64(0x01f7797b7a8ef58f), CONST64(0x0de76f757888fd85), CONST64(0xb4adf782365ad8ee), CONST64(0x48e0c4541c24706c), CONST64(0x96d59eaf394be4dd), CONST64(0xcbf2199259eb7920), CONST64(0x50c0e84818286078), CONST64(0xe98a70bf56fa4513), CONST64(0x8df1393eb3c8f645), CONST64(0x87e92437b0cdfa4a), CONST64(0xd83d51fc246c90b4), CONST64(0xc01d7de0206080a0), CONST64(0x8bf93239b2cbf240), CONST64(0x4be44fd992ab72e0), CONST64(0xed71894ea3f8b615), CONST64(0xba4e137ac05d27e7), CONST64(0x851ad6c144cc0d49), CONST64(0x5137913362a695f7), CONST64(0x6080b07010304050), CONST64(0x9fc9082bb4c1ea5e), CONST64(0x3f54c5bb84912aae), CONST64(0x9722e7d443c51152), CONST64(0x4dec44de93a876e5), CONST64(0xb65e0574c25b2fed), CONST64(0xa16ab4eb4ade357f), CONST64(0xa9815b14bddace73), CONST64(0x050c808a8f8c0689), CONST64(0xee7502c32d77b499), CONST64(0xaf895013bcd9ca76), CONST64(0x6f942df39cb94ad6), CONST64(0x6177c90b6abeb5df), CONST64(0x9d3afadd40c01d5d), CONST64(0x98367a57cf4c1bd4), CONST64(0xeb798249a2fbb210), CONST64(0x2774e9a7809d3aba), CONST64(0xbf4293f04fd1216e), CONST64(0x42f8d95d1f217c63), CONST64(0x861e5d4cca430fc5), CONST64(0xdb39da71aae39238), CONST64(0x912aecd342c61557), }; static const ulong64 T5[256] = { CONST64(0xb9bb016ad3ba68d2), CONST64(0x9ae5b166fc54194d), CONST64(0x65e2cd14712f93bc), CONST64(0x8725511b9c74b9cd), CONST64(0xa2f7a457f5530251), CONST64(0xd6d003be68d3b86b), CONST64(0xded604b56bd2bd6f), CONST64(0x52b3fe85d74d6429), CONST64(0xbafdad4af0500d5d), CONST64(0x09cf63e0e9ac268a), CONST64(0x1c0984968a8d830e), CONST64(0x91a51a4ddcbf79c6), CONST64(0xa73d4d379070addd), CONST64(0xaaf1a35cf6520755), CONST64(0xa47be117b39ac852), CONST64(0x5ab5f98ed44c612d), CONST64(0x0346ac2023ea658f), CONST64(0xe6c4118462d5a673), CONST64(0xcc55c268a497f166), CONST64(0xc6dc0da86ed1b263), CONST64(0x85aa99d05533ffcc), CONST64(0xb2fbaa41f3510859), CONST64(0xe2c79c0fed5b2a71), CONST64(0x59f355aef7a604a2), CONST64(0xbefe20c17fde815f), CONST64(0x7aade5a2d848753d), CONST64(0x29d77fcce5a8329a), CONST64(0xbc71e80ab699c75e), CONST64(0x96e03be670db904b), CONST64(0x8dac9edb5632fac8), CONST64(0xd1952215c4b751e6), CONST64(0xb332ceaa19fc2bd7), CONST64(0x4b70937338e348ab), CONST64(0x8463fd3bbf9edc42), CONST64(0xfc41d052ae91ef7e), CONST64(0xac7de61cb09bcd56), CONST64(0x437694783be24daf), CONST64(0xb1bd0661d0bb6dd6), CONST64(0x329bdaf1c3415819), CONST64(0x577917e5b26ecba5), CONST64(0x41f95cb3f2a50bae), CONST64(0x16804b5640cbc00b), CONST64(0x7f670cc2bd6bdab1), CONST64(0xdc59cc7ea295fb6e), CONST64(0x61e1409ffea11fbe), CONST64(0xcb10e3c308f318eb), CONST64(0xe181302fceb14ffe), CONST64(0x100c0e1606020a08), CONST64(0x2e925e6749ccdb17), CONST64(0x6ea2663f51c4f337), CONST64(0xe84e53cf271d6974), CONST64(0xa0786c9c3c144450), CONST64(0x56b0730e58c3e82b), CONST64(0x3f57349aa563f291), CONST64(0x9ee63ced73da954f), CONST64(0xd2d38e35e75d3469), CONST64(0xc2df8023e15f3e61), CONST64(0xaef22ed779dc8b57), CONST64(0xcf136e48877d94e9), CONST64(0x2694596c4acdde13), CONST64(0xdf1f605e817f9ee1), CONST64(0xeac19b04ee5a2f75), CONST64(0x477519f3b46cc1ad), CONST64(0xdad5893ee45c316d), CONST64(0xeb08ffef04f70cfb), CONST64(0x2dd4f2476a26be98), CONST64(0xab38c7b71cff24db), CONST64(0x3b54b9112aed7e93), CONST64(0x134aa23625e86f87), CONST64(0x9c69f426ba9dd34e), CONST64(0x5f7f10eeb16fcea1), CONST64(0x04038d8b8f8e8c02), CONST64(0xc8564fe32b197d64), CONST64(0x69e74794fda01aba), CONST64(0xd31aeade0df017e7), CONST64(0x3c1198ba8689971e), CONST64(0x78222d69110f333c), CONST64(0x3812153109071b1c), CONST64(0x11c56afdecaf2986), CONST64(0x8b20db9b10fb30cb), CONST64(0x4030385818082820), CONST64(0xa87e6b973f154154), CONST64(0x682e237f170d3934), CONST64(0x20181c2c0c041410), CONST64(0x0806070b03010504), CONST64(0x074521abac64e98d), CONST64(0xb6f827ca7cdf845b), CONST64(0x97295f0d9a76b3c5), CONST64(0xef0b72648b7980f9), CONST64(0xa6f429dc7add8e53), CONST64(0xf58eb3b2473dc9f4), CONST64(0xb074628a3a164e58), CONST64(0xe582bda4413fc3fc), CONST64(0xa5b285fc5937ebdc), CONST64(0x4f731ef8b76dc4a9), CONST64(0xdd90a8954838d8e0), CONST64(0xa1b10877d6b967de), CONST64(0xbf37442a9573a2d1), CONST64(0x1b4ca53d26e96a83), CONST64(0xb5be8bea5f35e1d4), CONST64(0x92e3b66dff551c49), CONST64(0xaf3b4a3c9371a8d9), CONST64(0xff077c728d7b8af1), CONST64(0x140f839d898c860a), CONST64(0xb73143219672a7d5), CONST64(0x34179fb18588921a), CONST64(0xe30ef8e407f609ff), CONST64(0x4dfcd6337e2a82a8), CONST64(0xed84baaf423ec6f8), CONST64(0xcad98728e25e3b65), CONST64(0x25d2f54c6927bb9c), CONST64(0x0a89cfc0ca464305), CONST64(0x60282474140c3c30), CONST64(0x0f4326a0af65ec89), CONST64(0x676d05dfb868d5bd), CONST64(0x2f5b3a8ca361f899), CONST64(0x180a091d05030f0c), CONST64(0x46bc7d185ec1e223), CONST64(0x82efb87bf9571641), CONST64(0xfece189967d6a97f), CONST64(0x86ec35f076d99a43), CONST64(0xfacd9512e858257d), CONST64(0x8eea32fb75d89f47), CONST64(0x17492fbdaa66e385), CONST64(0xf6c81f9264d7ac7b), CONST64(0xcd9ca6834e3ad2e8), CONST64(0x0e8a424b45c8cf07), CONST64(0xfd88b4b9443cccf0), CONST64(0x8326dc9013fa35cf), CONST64(0xc453c563a796f462), CONST64(0x51f552a5f4a701a6), CONST64(0xb477ef01b598c25a), CONST64(0x3352be1a29ec7b97), CONST64(0xa9b70f7cd5b862da), CONST64(0x76a86f2254c7fc3b), CONST64(0x19c36df6efae2c82), CONST64(0x6f6b02d4bb69d0b9), CONST64(0x62a7ecbfdd4b7a31), CONST64(0x31dd76d1e0ab3d96), CONST64(0x21d178c7e6a9379e), CONST64(0x1f4f28b6a967e681), CONST64(0x503c364e1e0a2228), CONST64(0x028fc8cbc9474601), CONST64(0xc316e4c80bf21def), CONST64(0xc1992c03c2b55bee), CONST64(0x0dccee6b6622aa88), CONST64(0x7b64814932e556b3), CONST64(0x235eb00c2fee719f), CONST64(0x99a31d46dfbe7cc2), CONST64(0x45fad1387d2b87ac), CONST64(0x7c21a0e29e81bf3e), CONST64(0x906c7ea636125a48), CONST64(0x6c2daef49883b536), CONST64(0xd85a41f52d1b776c), CONST64(0x70242a62120e3638), CONST64(0x05cae9606523af8c), CONST64(0xfb04f1f902f506f3), CONST64(0x1283c6ddcf454c09), CONST64(0x15c6e7766321a584), CONST64(0x3e9e50714fced11f), CONST64(0x72abe2a9db497039), CONST64(0x7de8c409742c9cb0), CONST64(0x9b2cd58d16f93ac3), CONST64(0x636e885437e659bf), CONST64(0xd993251ec7b654e2), CONST64(0x5df0d825782888a0), CONST64(0xb872658139174b5c), CONST64(0x642ba9ff9b82b032), CONST64(0xd05c46fe2e1a7268), CONST64(0x2c1d96ac808b9d16), CONST64(0xa33ec0bc1ffe21df), CONST64(0x241b91a7838a9812), CONST64(0x48363f531b092d24), CONST64(0x068c454046c9ca03), CONST64(0x4c35b2d89487a126), CONST64(0x4ab9f798d24e6b25), CONST64(0x5b7c9d653ee142a3), CONST64(0x6de4ca1f722e96b8), CONST64(0x7362864231e453b7), CONST64(0x537a9a6e3de047a7), CONST64(0x0b40ab2b20eb608b), CONST64(0xf447d759ad90ea7a), CONST64(0x49ff5bb8f1a40eaa), CONST64(0xf0445ad2221e6678), CONST64(0x5c39bcce9285ab2e), CONST64(0x275d3d87a060fd9d), CONST64(0x0000000000000000), CONST64(0x35defb5a6f25b194), CONST64(0xf302f6f201f403f7), CONST64(0xdb1cedd50ef112e3), CONST64(0xd45fcb75a194fe6a), CONST64(0x583a31451d0b272c), CONST64(0x6b688f5f34e75cbb), CONST64(0x8f2356109f75bcc9), CONST64(0x2b58b7072cef749b), CONST64(0xbdb88ce15c34e4d0), CONST64(0x95a697c65331f5c4), CONST64(0xeec2168f61d4a377), CONST64(0xceda0aa36dd0b767), CONST64(0x4433b5d39786a422), CONST64(0xd7196755827e9be5), CONST64(0x01c964ebeaad238e), CONST64(0xbb34c9a11afd2ed3), CONST64(0x55f6df2e7b298da4), CONST64(0x9da090cd5030f0c0), CONST64(0xc59aa1884d3bd7ec), CONST64(0x8c65fa30bc9fd946), CONST64(0x932ad28615f83fc7), CONST64(0x7eae682957c6f93f), CONST64(0x986a79ad35135f4c), CONST64(0x3014123a0a061e18), CONST64(0x281e1b270f051114), CONST64(0x66a4613452c5f633), CONST64(0x886677bb33115544), CONST64(0x9f2f58069977b6c1), CONST64(0xc7156943847c91ed), CONST64(0xf7017b798e7a8ff5), CONST64(0xe70d756f887885fd), CONST64(0xadb482f75a36eed8), CONST64(0xe04854c4241c6c70), CONST64(0xd596af9e4b39dde4), CONST64(0xf2cb9219eb592079), CONST64(0xc05048e828187860), CONST64(0x8ae9bf70fa561345), CONST64(0xf18d3e39c8b345f6), CONST64(0xe9873724cdb04afa), CONST64(0x3dd8fc516c24b490), CONST64(0x1dc0e07d6020a080), CONST64(0xf98b3932cbb240f2), CONST64(0xe44bd94fab92e072), CONST64(0x71ed4e89f8a315b6), CONST64(0x4eba7a135dc0e727), CONST64(0x1a85c1d6cc44490d), CONST64(0x37513391a662f795), CONST64(0x806070b030105040), CONST64(0xc99f2b08c1b45eea), CONST64(0x543fbbc59184ae2a), CONST64(0x2297d4e7c5435211), CONST64(0xec4dde44a893e576), CONST64(0x5eb674055bc2ed2f), CONST64(0x6aa1ebb4de4a7f35), CONST64(0x81a9145bdabd73ce), CONST64(0x0c058a808c8f8906), CONST64(0x75eec302772d99b4), CONST64(0x89af1350d9bc76ca), CONST64(0x946ff32db99cd64a), CONST64(0x77610bc9be6adfb5), CONST64(0x3a9dddfac0405d1d), CONST64(0x3698577a4ccfd41b), CONST64(0x79eb4982fba210b2), CONST64(0x7427a7e99d80ba3a), CONST64(0x42bff093d14f6e21), CONST64(0xf8425dd9211f637c), CONST64(0x1e864c5d43cac50f), CONST64(0x39db71dae3aa3892), CONST64(0x2a91d3ecc6425715), }; static const ulong64 T6[256] = { CONST64(0x6a01bbb9d268bad3), CONST64(0x66b1e59a4d1954fc), CONST64(0x14cde265bc932f71), CONST64(0x1b512587cdb9749c), CONST64(0x57a4f7a2510253f5), CONST64(0xbe03d0d66bb8d368), CONST64(0xb504d6de6fbdd26b), CONST64(0x85feb35229644dd7), CONST64(0x4aadfdba5d0d50f0), CONST64(0xe063cf098a26ace9), CONST64(0x9684091c0e838d8a), CONST64(0x4d1aa591c679bfdc), CONST64(0x374d3da7ddad7090), CONST64(0x5ca3f1aa550752f6), CONST64(0x17e17ba452c89ab3), CONST64(0x8ef9b55a2d614cd4), CONST64(0x20ac46038f65ea23), CONST64(0x8411c4e673a6d562), CONST64(0x68c255cc66f197a4), CONST64(0xa80ddcc663b2d16e), CONST64(0xd099aa85ccff3355), CONST64(0x41aafbb2590851f3), CONST64(0x0f9cc7e2712a5bed), CONST64(0xae55f359a204a6f7), CONST64(0xc120febe5f81de7f), CONST64(0xa2e5ad7a3d7548d8), CONST64(0xcc7fd7299a32a8e5), CONST64(0x0ae871bc5ec799b6), CONST64(0xe63be0964b90db70), CONST64(0xdb9eac8dc8fa3256), CONST64(0x152295d1e651b7c4), CONST64(0xaace32b3d72bfc19), CONST64(0x7393704bab48e338), CONST64(0x3bfd638442dc9ebf), CONST64(0x52d041fc7eef91ae), CONST64(0x1ce67dac56cd9bb0), CONST64(0x78947643af4de23b), CONST64(0x6106bdb1d66dbbd0), CONST64(0xf1da9b32195841c3), CONST64(0xe5177957a5cb6eb2), CONST64(0xb35cf941ae0ba5f2), CONST64(0x564b80160bc0cb40), CONST64(0xc20c677fb1da6bbd), CONST64(0x7ecc59dc6efb95a2), CONST64(0x9f40e161be1fa1fe), CONST64(0xc3e310cbeb18f308), CONST64(0x2f3081e1fe4fb1ce), CONST64(0x160e0c10080a0206), CONST64(0x675e922e17dbcc49), CONST64(0x3f66a26e37f3c451), CONST64(0xcf534ee874691d27), CONST64(0x9c6c78a05044143c), CONST64(0x0e73b0562be8c358), CONST64(0x9a34573f91f263a5), CONST64(0xed3ce69e4f95da73), CONST64(0x358ed3d269345de7), CONST64(0x2380dfc2613e5fe1), CONST64(0xd72ef2ae578bdc79), CONST64(0x486e13cfe9947d87), CONST64(0x6c59942613decd4a), CONST64(0x5e601fdfe19e7f81), CONST64(0x049bc1ea752f5aee), CONST64(0xf3197547adc16cb4), CONST64(0x3e89d5da6d315ce4), CONST64(0xefff08ebfb0cf704), CONST64(0x47f2d42d98be266a), CONST64(0xb7c738abdb24ff1c), CONST64(0x11b9543b937eed2a), CONST64(0x36a24a13876fe825), CONST64(0x26f4699c4ed39dba), CONST64(0xee107f5fa1ce6fb1), CONST64(0x8b8d0304028c8e8f), CONST64(0xe34f56c8647d192b), CONST64(0x9447e769ba1aa0fd), CONST64(0xdeea1ad3e717f00d), CONST64(0xba98113c1e978986), CONST64(0x692d22783c330f11), CONST64(0x311512381c1b0709), CONST64(0xfd6ac5118629afec), CONST64(0x9bdb208bcb30fb10), CONST64(0x5838304020280818), CONST64(0x976b7ea85441153f), CONST64(0x7f232e6834390d17), CONST64(0x2c1c18201014040c), CONST64(0x0b07060804050103), CONST64(0xab2145078de964ac), CONST64(0xca27f8b65b84df7c), CONST64(0x0d5f2997c5b3769a), CONST64(0x64720beff980798b), CONST64(0xdc29f4a6538edd7a), CONST64(0xb2b38ef5f4c93d47), CONST64(0x8a6274b0584e163a), CONST64(0xa4bd82e5fcc33f41), CONST64(0xfc85b2a5dceb3759), CONST64(0xf81e734fa9c46db7), CONST64(0x95a890dde0d83848), CONST64(0x7708b1a1de67b9d6), CONST64(0x2a4437bfd1a27395), CONST64(0x3da54c1b836ae926), CONST64(0xea8bbeb5d4e1355f), CONST64(0x6db6e392491c55ff), CONST64(0x3c4a3bafd9a87193), CONST64(0x727c07fff18a7b8d), CONST64(0x9d830f140a868c89), CONST64(0x214331b7d5a77296), CONST64(0xb19f17341a928885), CONST64(0xe4f80ee3ff09f607), CONST64(0x33d6fc4da8822a7e), CONST64(0xafba84edf8c63e42), CONST64(0x2887d9ca653b5ee2), CONST64(0x4cf5d2259cbb2769), CONST64(0xc0cf890a054346ca), CONST64(0x74242860303c0c14), CONST64(0xa026430f89ec65af), CONST64(0xdf056d67bdd568b8), CONST64(0x8c3a5b2f99f861a3), CONST64(0x1d090a180c0f0305), CONST64(0x187dbc4623e2c15e), CONST64(0x7bb8ef82411657f9), CONST64(0x9918cefe7fa9d667), CONST64(0xf035ec86439ad976), CONST64(0x1295cdfa7d2558e8), CONST64(0xfb32ea8e479fd875), CONST64(0xbd2f491785e366aa), CONST64(0x921fc8f67bacd764), CONST64(0x83a69ccde8d23a4e), CONST64(0x4b428a0e07cfc845), CONST64(0xb9b488fdf0cc3c44), CONST64(0x90dc2683cf35fa13), CONST64(0x63c553c462f496a7), CONST64(0xa552f551a601a7f4), CONST64(0x01ef77b45ac298b5), CONST64(0x1abe5233977bec29), CONST64(0x7c0fb7a9da62b8d5), CONST64(0x226fa8763bfcc754), CONST64(0xf66dc319822caeef), CONST64(0xd4026b6fb9d069bb), CONST64(0xbfeca762317a4bdd), CONST64(0xd176dd31963dabe0), CONST64(0xc778d1219e37a9e6), CONST64(0xb6284f1f81e667a9), CONST64(0x4e363c5028220a1e), CONST64(0xcbc88f02014647c9), CONST64(0xc8e416c3ef1df20b), CONST64(0x032c99c1ee5bb5c2), CONST64(0x6beecc0d88aa2266), CONST64(0x4981647bb356e532), CONST64(0x0cb05e239f71ee2f), CONST64(0x461da399c27cbedf), CONST64(0x38d1fa45ac872b7d), CONST64(0xe2a0217c3ebf819e), CONST64(0xa67e6c90485a1236), CONST64(0xf4ae2d6c36b58398), CONST64(0xf5415ad86c771b2d), CONST64(0x622a247038360e12), CONST64(0x60e9ca058caf2365), CONST64(0xf9f104fbf306f502), CONST64(0xddc68312094c45cf), CONST64(0x76e7c61584a52163), CONST64(0x71509e3e1fd1ce4f), CONST64(0xa9e2ab72397049db), CONST64(0x09c4e87db09c2c74), CONST64(0x8dd52c9bc33af916), CONST64(0x54886e63bf59e637), CONST64(0x1e2593d9e254b6c7), CONST64(0x25d8f05da0882878), CONST64(0x816572b85c4b1739), CONST64(0xffa92b6432b0829b), CONST64(0xfe465cd068721a2e), CONST64(0xac961d2c169d8b80), CONST64(0xbcc03ea3df21fe1f), CONST64(0xa7911b2412988a83), CONST64(0x533f3648242d091b), CONST64(0x40458c0603cac946), CONST64(0xd8b2354c26a18794), CONST64(0x98f7b94a256b4ed2), CONST64(0x659d7c5ba342e13e), CONST64(0x1fcae46db8962e72), CONST64(0x42866273b753e431), CONST64(0x6e9a7a53a747e03d), CONST64(0x2bab400b8b60eb20), CONST64(0x59d747f47aea90ad), CONST64(0xb85bff49aa0ea4f1), CONST64(0xd25a44f078661e22), CONST64(0xcebc395c2eab8592), CONST64(0x873d5d279dfd60a0), CONST64(0x0000000000000000), CONST64(0x5afbde3594b1256f), CONST64(0xf2f602f3f703f401), CONST64(0xd5ed1cdbe312f10e), CONST64(0x75cb5fd46afe94a1), CONST64(0x45313a582c270b1d), CONST64(0x5f8f686bbb5ce734), CONST64(0x1056238fc9bc759f), CONST64(0x07b7582b9b74ef2c), CONST64(0xe18cb8bdd0e4345c), CONST64(0xc697a695c4f53153), CONST64(0x8f16c2ee77a3d461), CONST64(0xa30adace67b7d06d), CONST64(0xd3b5334422a48697), CONST64(0x556719d7e59b7e82), CONST64(0xeb64c9018e23adea), CONST64(0xa1c934bbd32efd1a), CONST64(0x2edff655a48d297b), CONST64(0xcd90a09dc0f03050), CONST64(0x88a19ac5ecd73b4d), CONST64(0x30fa658c46d99fbc), CONST64(0x86d22a93c73ff815), CONST64(0x2968ae7e3ff9c657), CONST64(0xad796a984c5f1335), CONST64(0x3a121430181e060a), CONST64(0x271b1e281411050f), CONST64(0x3461a46633f6c552), CONST64(0xbb77668844551133), CONST64(0x06582f9fc1b67799), CONST64(0x436915c7ed917c84), CONST64(0x797b01f7f58f7a8e), CONST64(0x6f750de7fd857888), CONST64(0xf782b4add8ee365a), CONST64(0xc45448e0706c1c24), CONST64(0x9eaf96d5e4dd394b), CONST64(0x1992cbf2792059eb), CONST64(0xe84850c060781828), CONST64(0x70bfe98a451356fa), CONST64(0x393e8df1f645b3c8), CONST64(0x243787e9fa4ab0cd), CONST64(0x51fcd83d90b4246c), CONST64(0x7de0c01d80a02060), CONST64(0x32398bf9f240b2cb), CONST64(0x4fd94be472e092ab), CONST64(0x894eed71b615a3f8), CONST64(0x137aba4e27e7c05d), CONST64(0xd6c1851a0d4944cc), CONST64(0x9133513795f762a6), CONST64(0xb070608040501030), CONST64(0x082b9fc9ea5eb4c1), CONST64(0xc5bb3f542aae8491), CONST64(0xe7d49722115243c5), CONST64(0x44de4dec76e593a8), CONST64(0x0574b65e2fedc25b), CONST64(0xb4eba16a357f4ade), CONST64(0x5b14a981ce73bdda), CONST64(0x808a050c06898f8c), CONST64(0x02c3ee75b4992d77), CONST64(0x5013af89ca76bcd9), CONST64(0x2df36f944ad69cb9), CONST64(0xc90b6177b5df6abe), CONST64(0xfadd9d3a1d5d40c0), CONST64(0x7a5798361bd4cf4c), CONST64(0x8249eb79b210a2fb), CONST64(0xe9a727743aba809d), CONST64(0x93f0bf42216e4fd1), CONST64(0xd95d42f87c631f21), CONST64(0x5d4c861e0fc5ca43), CONST64(0xda71db399238aae3), CONST64(0xecd3912a155742c6), }; static const ulong64 T7[256] = { CONST64(0x016ab9bb68d2d3ba), CONST64(0xb1669ae5194dfc54), CONST64(0xcd1465e293bc712f), CONST64(0x511b8725b9cd9c74), CONST64(0xa457a2f70251f553), CONST64(0x03bed6d0b86b68d3), CONST64(0x04b5ded6bd6f6bd2), CONST64(0xfe8552b36429d74d), CONST64(0xad4abafd0d5df050), CONST64(0x63e009cf268ae9ac), CONST64(0x84961c09830e8a8d), CONST64(0x1a4d91a579c6dcbf), CONST64(0x4d37a73daddd9070), CONST64(0xa35caaf10755f652), CONST64(0xe117a47bc852b39a), CONST64(0xf98e5ab5612dd44c), CONST64(0xac200346658f23ea), CONST64(0x1184e6c4a67362d5), CONST64(0xc268cc55f166a497), CONST64(0x0da8c6dcb2636ed1), CONST64(0x99d085aaffcc5533), CONST64(0xaa41b2fb0859f351), CONST64(0x9c0fe2c72a71ed5b), CONST64(0x55ae59f304a2f7a6), CONST64(0x20c1befe815f7fde), CONST64(0xe5a27aad753dd848), CONST64(0x7fcc29d7329ae5a8), CONST64(0xe80abc71c75eb699), CONST64(0x3be696e0904b70db), CONST64(0x9edb8dacfac85632), CONST64(0x2215d19551e6c4b7), CONST64(0xceaab3322bd719fc), CONST64(0x93734b7048ab38e3), CONST64(0xfd3b8463dc42bf9e), CONST64(0xd052fc41ef7eae91), CONST64(0xe61cac7dcd56b09b), CONST64(0x947843764daf3be2), CONST64(0x0661b1bd6dd6d0bb), CONST64(0xdaf1329b5819c341), CONST64(0x17e55779cba5b26e), CONST64(0x5cb341f90baef2a5), CONST64(0x4b561680c00b40cb), CONST64(0x0cc27f67dab1bd6b), CONST64(0xcc7edc59fb6ea295), CONST64(0x409f61e11fbefea1), CONST64(0xe3c3cb1018eb08f3), CONST64(0x302fe1814ffeceb1), CONST64(0x0e16100c0a080602), CONST64(0x5e672e92db1749cc), CONST64(0x663f6ea2f33751c4), CONST64(0x53cfe84e6974271d), CONST64(0x6c9ca07844503c14), CONST64(0x730e56b0e82b58c3), CONST64(0x349a3f57f291a563), CONST64(0x3ced9ee6954f73da), CONST64(0x8e35d2d33469e75d), CONST64(0x8023c2df3e61e15f), CONST64(0x2ed7aef28b5779dc), CONST64(0x6e48cf1394e9877d), CONST64(0x596c2694de134acd), CONST64(0x605edf1f9ee1817f), CONST64(0x9b04eac12f75ee5a), CONST64(0x19f34775c1adb46c), CONST64(0x893edad5316de45c), CONST64(0xffefeb080cfb04f7), CONST64(0xf2472dd4be986a26), CONST64(0xc7b7ab3824db1cff), CONST64(0xb9113b547e932aed), CONST64(0xa236134a6f8725e8), CONST64(0xf4269c69d34eba9d), CONST64(0x10ee5f7fcea1b16f), CONST64(0x8d8b04038c028f8e), CONST64(0x4fe3c8567d642b19), CONST64(0x479469e71abafda0), CONST64(0xeaded31a17e70df0), CONST64(0x98ba3c11971e8689), CONST64(0x2d697822333c110f), CONST64(0x153138121b1c0907), CONST64(0x6afd11c52986ecaf), CONST64(0xdb9b8b2030cb10fb), CONST64(0x3858403028201808), CONST64(0x6b97a87e41543f15), CONST64(0x237f682e3934170d), CONST64(0x1c2c201814100c04), CONST64(0x070b080605040301), CONST64(0x21ab0745e98dac64), CONST64(0x27cab6f8845b7cdf), CONST64(0x5f0d9729b3c59a76), CONST64(0x7264ef0b80f98b79), CONST64(0x29dca6f48e537add), CONST64(0xb3b2f58ec9f4473d), CONST64(0x628ab0744e583a16), CONST64(0xbda4e582c3fc413f), CONST64(0x85fca5b2ebdc5937), CONST64(0x1ef84f73c4a9b76d), CONST64(0xa895dd90d8e04838), CONST64(0x0877a1b167ded6b9), CONST64(0x442abf37a2d19573), CONST64(0xa53d1b4c6a8326e9), CONST64(0x8beab5bee1d45f35), CONST64(0xb66d92e31c49ff55), CONST64(0x4a3caf3ba8d99371), CONST64(0x7c72ff078af18d7b), CONST64(0x839d140f860a898c), CONST64(0x4321b731a7d59672), CONST64(0x9fb13417921a8588), CONST64(0xf8e4e30e09ff07f6), CONST64(0xd6334dfc82a87e2a), CONST64(0xbaafed84c6f8423e), CONST64(0x8728cad93b65e25e), CONST64(0xf54c25d2bb9c6927), CONST64(0xcfc00a894305ca46), CONST64(0x247460283c30140c), CONST64(0x26a00f43ec89af65), CONST64(0x05df676dd5bdb868), CONST64(0x3a8c2f5bf899a361), CONST64(0x091d180a0f0c0503), CONST64(0x7d1846bce2235ec1), CONST64(0xb87b82ef1641f957), CONST64(0x1899fecea97f67d6), CONST64(0x35f086ec9a4376d9), CONST64(0x9512facd257de858), CONST64(0x32fb8eea9f4775d8), CONST64(0x2fbd1749e385aa66), CONST64(0x1f92f6c8ac7b64d7), CONST64(0xa683cd9cd2e84e3a), CONST64(0x424b0e8acf0745c8), CONST64(0xb4b9fd88ccf0443c), CONST64(0xdc90832635cf13fa), CONST64(0xc563c453f462a796), CONST64(0x52a551f501a6f4a7), CONST64(0xef01b477c25ab598), CONST64(0xbe1a33527b9729ec), CONST64(0x0f7ca9b762dad5b8), CONST64(0x6f2276a8fc3b54c7), CONST64(0x6df619c32c82efae), CONST64(0x02d46f6bd0b9bb69), CONST64(0xecbf62a77a31dd4b), CONST64(0x76d131dd3d96e0ab), CONST64(0x78c721d1379ee6a9), CONST64(0x28b61f4fe681a967), CONST64(0x364e503c22281e0a), CONST64(0xc8cb028f4601c947), CONST64(0xe4c8c3161def0bf2), CONST64(0x2c03c1995beec2b5), CONST64(0xee6b0dccaa886622), CONST64(0x81497b6456b332e5), CONST64(0xb00c235e719f2fee), CONST64(0x1d4699a37cc2dfbe), CONST64(0xd13845fa87ac7d2b), CONST64(0xa0e27c21bf3e9e81), CONST64(0x7ea6906c5a483612), CONST64(0xaef46c2db5369883), CONST64(0x41f5d85a776c2d1b), CONST64(0x2a6270243638120e), CONST64(0xe96005caaf8c6523), CONST64(0xf1f9fb0406f302f5), CONST64(0xc6dd12834c09cf45), CONST64(0xe77615c6a5846321), CONST64(0x50713e9ed11f4fce), CONST64(0xe2a972ab7039db49), CONST64(0xc4097de89cb0742c), CONST64(0xd58d9b2c3ac316f9), CONST64(0x8854636e59bf37e6), CONST64(0x251ed99354e2c7b6), CONST64(0xd8255df088a07828), CONST64(0x6581b8724b5c3917), CONST64(0xa9ff642bb0329b82), CONST64(0x46fed05c72682e1a), CONST64(0x96ac2c1d9d16808b), CONST64(0xc0bca33e21df1ffe), CONST64(0x91a7241b9812838a), CONST64(0x3f5348362d241b09), CONST64(0x4540068cca0346c9), CONST64(0xb2d84c35a1269487), CONST64(0xf7984ab96b25d24e), CONST64(0x9d655b7c42a33ee1), CONST64(0xca1f6de496b8722e), CONST64(0x8642736253b731e4), CONST64(0x9a6e537a47a73de0), CONST64(0xab2b0b40608b20eb), CONST64(0xd759f447ea7aad90), CONST64(0x5bb849ff0eaaf1a4), CONST64(0x5ad2f0446678221e), CONST64(0xbcce5c39ab2e9285), CONST64(0x3d87275dfd9da060), CONST64(0x0000000000000000), CONST64(0xfb5a35deb1946f25), CONST64(0xf6f2f30203f701f4), CONST64(0xedd5db1c12e30ef1), CONST64(0xcb75d45ffe6aa194), CONST64(0x3145583a272c1d0b), CONST64(0x8f5f6b685cbb34e7), CONST64(0x56108f23bcc99f75), CONST64(0xb7072b58749b2cef), CONST64(0x8ce1bdb8e4d05c34), CONST64(0x97c695a6f5c45331), CONST64(0x168feec2a37761d4), CONST64(0x0aa3cedab7676dd0), CONST64(0xb5d34433a4229786), CONST64(0x6755d7199be5827e), CONST64(0x64eb01c9238eeaad), CONST64(0xc9a1bb342ed31afd), CONST64(0xdf2e55f68da47b29), CONST64(0x90cd9da0f0c05030), CONST64(0xa188c59ad7ec4d3b), CONST64(0xfa308c65d946bc9f), CONST64(0xd286932a3fc715f8), CONST64(0x68297eaef93f57c6), CONST64(0x79ad986a5f4c3513), CONST64(0x123a30141e180a06), CONST64(0x1b27281e11140f05), CONST64(0x613466a4f63352c5), CONST64(0x77bb886655443311), CONST64(0x58069f2fb6c19977), CONST64(0x6943c71591ed847c), CONST64(0x7b79f7018ff58e7a), CONST64(0x756fe70d85fd8878), CONST64(0x82f7adb4eed85a36), CONST64(0x54c4e0486c70241c), CONST64(0xaf9ed596dde44b39), CONST64(0x9219f2cb2079eb59), CONST64(0x48e8c05078602818), CONST64(0xbf708ae91345fa56), CONST64(0x3e39f18d45f6c8b3), CONST64(0x3724e9874afacdb0), CONST64(0xfc513dd8b4906c24), CONST64(0xe07d1dc0a0806020), CONST64(0x3932f98b40f2cbb2), CONST64(0xd94fe44be072ab92), CONST64(0x4e8971ed15b6f8a3), CONST64(0x7a134ebae7275dc0), CONST64(0xc1d61a85490dcc44), CONST64(0x33913751f795a662), CONST64(0x70b0806050403010), CONST64(0x2b08c99f5eeac1b4), CONST64(0xbbc5543fae2a9184), CONST64(0xd4e722975211c543), CONST64(0xde44ec4de576a893), CONST64(0x74055eb6ed2f5bc2), CONST64(0xebb46aa17f35de4a), CONST64(0x145b81a973cedabd), CONST64(0x8a800c0589068c8f), CONST64(0xc30275ee99b4772d), CONST64(0x135089af76cad9bc), CONST64(0xf32d946fd64ab99c), CONST64(0x0bc97761dfb5be6a), CONST64(0xddfa3a9d5d1dc040), CONST64(0x577a3698d41b4ccf), CONST64(0x498279eb10b2fba2), CONST64(0xa7e97427ba3a9d80), CONST64(0xf09342bf6e21d14f), CONST64(0x5dd9f842637c211f), CONST64(0x4c5d1e86c50f43ca), CONST64(0x71da39db3892e3aa), CONST64(0xd3ec2a915715c642), }; static const ulong64 c[R + 1] = { CONST64(0xba542f7453d3d24d), CONST64(0x50ac8dbf70529a4c), CONST64(0xead597d133515ba6), CONST64(0xde48a899db32b7fc), CONST64(0xe39e919be2bb416e), CONST64(0xa5cb6b95a1f3b102), CONST64(0xccc41d14c363da5d), CONST64(0x5fdc7dcd7f5a6c5c), CONST64(0xf726ffede89d6f8e), }; /** Initialize the Khazad block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int r; const ulong64 *S; ulong64 K2, K1; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 8 && num_rounds != 0) { return CRYPT_INVALID_ROUNDS; } /* use 7th table */ S = T7; /* * map unsigned char array cipher key to initial key state (mu): */ K2 = ((ulong64)key[ 0] << 56) ^ ((ulong64)key[ 1] << 48) ^ ((ulong64)key[ 2] << 40) ^ ((ulong64)key[ 3] << 32) ^ ((ulong64)key[ 4] << 24) ^ ((ulong64)key[ 5] << 16) ^ ((ulong64)key[ 6] << 8) ^ ((ulong64)key[ 7] ); K1 = ((ulong64)key[ 8] << 56) ^ ((ulong64)key[ 9] << 48) ^ ((ulong64)key[10] << 40) ^ ((ulong64)key[11] << 32) ^ ((ulong64)key[12] << 24) ^ ((ulong64)key[13] << 16) ^ ((ulong64)key[14] << 8) ^ ((ulong64)key[15] ); /* * compute the round keys: */ for (r = 0; r <= R; r++) { /* * K[r] = rho(c[r], K1) ^ K2; */ skey->khazad.roundKeyEnc[r] = T0[(int)(K1 >> 56) ] ^ T1[(int)(K1 >> 48) & 0xff] ^ T2[(int)(K1 >> 40) & 0xff] ^ T3[(int)(K1 >> 32) & 0xff] ^ T4[(int)(K1 >> 24) & 0xff] ^ T5[(int)(K1 >> 16) & 0xff] ^ T6[(int)(K1 >> 8) & 0xff] ^ T7[(int)(K1 ) & 0xff] ^ c[r] ^ K2; K2 = K1; K1 = skey->khazad.roundKeyEnc[r]; } /* * compute the inverse key schedule: * K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}) */ skey->khazad.roundKeyDec[0] = skey->khazad.roundKeyEnc[R]; for (r = 1; r < R; r++) { K1 = skey->khazad.roundKeyEnc[R - r]; skey->khazad.roundKeyDec[r] = T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^ T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^ T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^ T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^ T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^ T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^ T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^ T7[(int)S[(int)(K1 ) & 0xff] & 0xff]; } skey->khazad.roundKeyDec[R] = skey->khazad.roundKeyEnc[0]; return CRYPT_OK; } static void khazad_crypt(const unsigned char *plaintext, unsigned char *ciphertext, const ulong64 *roundKey) { int r; ulong64 state; /* * map plaintext block to cipher state (mu) * and add initial round key (sigma[K^0]): */ state = ((ulong64)plaintext[0] << 56) ^ ((ulong64)plaintext[1] << 48) ^ ((ulong64)plaintext[2] << 40) ^ ((ulong64)plaintext[3] << 32) ^ ((ulong64)plaintext[4] << 24) ^ ((ulong64)plaintext[5] << 16) ^ ((ulong64)plaintext[6] << 8) ^ ((ulong64)plaintext[7] ) ^ roundKey[0]; /* * R - 1 full rounds: */ for (r = 1; r < R; r++) { state = T0[(int)(state >> 56) ] ^ T1[(int)(state >> 48) & 0xff] ^ T2[(int)(state >> 40) & 0xff] ^ T3[(int)(state >> 32) & 0xff] ^ T4[(int)(state >> 24) & 0xff] ^ T5[(int)(state >> 16) & 0xff] ^ T6[(int)(state >> 8) & 0xff] ^ T7[(int)(state ) & 0xff] ^ roundKey[r]; } /* * last round: */ state = (T0[(int)(state >> 56) ] & CONST64(0xff00000000000000)) ^ (T1[(int)(state >> 48) & 0xff] & CONST64(0x00ff000000000000)) ^ (T2[(int)(state >> 40) & 0xff] & CONST64(0x0000ff0000000000)) ^ (T3[(int)(state >> 32) & 0xff] & CONST64(0x000000ff00000000)) ^ (T4[(int)(state >> 24) & 0xff] & CONST64(0x00000000ff000000)) ^ (T5[(int)(state >> 16) & 0xff] & CONST64(0x0000000000ff0000)) ^ (T6[(int)(state >> 8) & 0xff] & CONST64(0x000000000000ff00)) ^ (T7[(int)(state ) & 0xff] & CONST64(0x00000000000000ff)) ^ roundKey[R]; /* * map cipher state to ciphertext block (mu^{-1}): */ ciphertext[0] = (unsigned char)(state >> 56); ciphertext[1] = (unsigned char)(state >> 48); ciphertext[2] = (unsigned char)(state >> 40); ciphertext[3] = (unsigned char)(state >> 32); ciphertext[4] = (unsigned char)(state >> 24); ciphertext[5] = (unsigned char)(state >> 16); ciphertext[6] = (unsigned char)(state >> 8); ciphertext[7] = (unsigned char)(state ); } /** Encrypts a block of text with Khazad @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); khazad_crypt(pt, ct, skey->khazad.roundKeyEnc); return CRYPT_OK; } /** Decrypts a block of text with Khazad @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); khazad_crypt(ct, pt, skey->khazad.roundKeyDec); return CRYPT_OK; } /** Performs a self-test of the Khazad block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int khazad_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct test { unsigned char pt[8], ct[8], key[16]; } tests[] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x49, 0xA4, 0xCE, 0x32, 0xAC, 0x19, 0x0E, 0x3F }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x64, 0x5D, 0x77, 0x3E, 0x40, 0xAB, 0xDD, 0x53 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }, { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x9E, 0x39, 0x98, 0x64, 0xF7, 0x8E, 0xCA, 0x02 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0xA9, 0xDF, 0x3D, 0x2C, 0x64, 0xD3, 0xEA, 0x28 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } } }; int x, y; unsigned char buf[2][8]; symmetric_key skey; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { khazad_setup(tests[x].key, 16, 0, &skey); khazad_ecb_encrypt(tests[x].pt, buf[0], &skey); khazad_ecb_decrypt(buf[0], buf[1], &skey); if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad Encrypt", x) || compare_testvector(buf[1], 8, tests[x].pt, 8, "Khazad Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } for (y = 0; y < 1000; y++) khazad_ecb_encrypt(buf[0], buf[0], &skey); for (y = 0; y < 1000; y++) khazad_ecb_decrypt(buf[0], buf[0], &skey); if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad 1000", 1000)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void khazad_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int khazad_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize >= 16) { *keysize = 16; return CRYPT_OK; } return CRYPT_INVALID_KEYSIZE; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/kseed.c000066400000000000000000000461111464416617300231030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file kseed.c seed implementation of SEED derived from RFC4269 Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_KSEED const struct ltc_cipher_descriptor kseed_desc = { "seed", 20, 16, 16, 16, 16, &kseed_setup, &kseed_ecb_encrypt, &kseed_ecb_decrypt, &kseed_test, &kseed_done, &kseed_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 SS0[256] = { 0x2989A1A8UL,0x05858184UL,0x16C6D2D4UL,0x13C3D3D0UL,0x14445054UL,0x1D0D111CUL,0x2C8CA0ACUL,0x25052124UL, 0x1D4D515CUL,0x03434340UL,0x18081018UL,0x1E0E121CUL,0x11415150UL,0x3CCCF0FCUL,0x0ACAC2C8UL,0x23436360UL, 0x28082028UL,0x04444044UL,0x20002020UL,0x1D8D919CUL,0x20C0E0E0UL,0x22C2E2E0UL,0x08C8C0C8UL,0x17071314UL, 0x2585A1A4UL,0x0F8F838CUL,0x03030300UL,0x3B4B7378UL,0x3B8BB3B8UL,0x13031310UL,0x12C2D2D0UL,0x2ECEE2ECUL, 0x30407070UL,0x0C8C808CUL,0x3F0F333CUL,0x2888A0A8UL,0x32023230UL,0x1DCDD1DCUL,0x36C6F2F4UL,0x34447074UL, 0x2CCCE0ECUL,0x15859194UL,0x0B0B0308UL,0x17475354UL,0x1C4C505CUL,0x1B4B5358UL,0x3D8DB1BCUL,0x01010100UL, 0x24042024UL,0x1C0C101CUL,0x33437370UL,0x18889098UL,0x10001010UL,0x0CCCC0CCUL,0x32C2F2F0UL,0x19C9D1D8UL, 0x2C0C202CUL,0x27C7E3E4UL,0x32427270UL,0x03838380UL,0x1B8B9398UL,0x11C1D1D0UL,0x06868284UL,0x09C9C1C8UL, 0x20406060UL,0x10405050UL,0x2383A3A0UL,0x2BCBE3E8UL,0x0D0D010CUL,0x3686B2B4UL,0x1E8E929CUL,0x0F4F434CUL, 0x3787B3B4UL,0x1A4A5258UL,0x06C6C2C4UL,0x38487078UL,0x2686A2A4UL,0x12021210UL,0x2F8FA3ACUL,0x15C5D1D4UL, 0x21416160UL,0x03C3C3C0UL,0x3484B0B4UL,0x01414140UL,0x12425250UL,0x3D4D717CUL,0x0D8D818CUL,0x08080008UL, 0x1F0F131CUL,0x19899198UL,0x00000000UL,0x19091118UL,0x04040004UL,0x13435350UL,0x37C7F3F4UL,0x21C1E1E0UL, 0x3DCDF1FCUL,0x36467274UL,0x2F0F232CUL,0x27072324UL,0x3080B0B0UL,0x0B8B8388UL,0x0E0E020CUL,0x2B8BA3A8UL, 0x2282A2A0UL,0x2E4E626CUL,0x13839390UL,0x0D4D414CUL,0x29496168UL,0x3C4C707CUL,0x09090108UL,0x0A0A0208UL, 0x3F8FB3BCUL,0x2FCFE3ECUL,0x33C3F3F0UL,0x05C5C1C4UL,0x07878384UL,0x14041014UL,0x3ECEF2FCUL,0x24446064UL, 0x1ECED2DCUL,0x2E0E222CUL,0x0B4B4348UL,0x1A0A1218UL,0x06060204UL,0x21012120UL,0x2B4B6368UL,0x26466264UL, 0x02020200UL,0x35C5F1F4UL,0x12829290UL,0x0A8A8288UL,0x0C0C000CUL,0x3383B3B0UL,0x3E4E727CUL,0x10C0D0D0UL, 0x3A4A7278UL,0x07474344UL,0x16869294UL,0x25C5E1E4UL,0x26062224UL,0x00808080UL,0x2D8DA1ACUL,0x1FCFD3DCUL, 0x2181A1A0UL,0x30003030UL,0x37073334UL,0x2E8EA2ACUL,0x36063234UL,0x15051114UL,0x22022220UL,0x38083038UL, 0x34C4F0F4UL,0x2787A3A4UL,0x05454144UL,0x0C4C404CUL,0x01818180UL,0x29C9E1E8UL,0x04848084UL,0x17879394UL, 0x35053134UL,0x0BCBC3C8UL,0x0ECEC2CCUL,0x3C0C303CUL,0x31417170UL,0x11011110UL,0x07C7C3C4UL,0x09898188UL, 0x35457174UL,0x3BCBF3F8UL,0x1ACAD2D8UL,0x38C8F0F8UL,0x14849094UL,0x19495158UL,0x02828280UL,0x04C4C0C4UL, 0x3FCFF3FCUL,0x09494148UL,0x39093138UL,0x27476364UL,0x00C0C0C0UL,0x0FCFC3CCUL,0x17C7D3D4UL,0x3888B0B8UL, 0x0F0F030CUL,0x0E8E828CUL,0x02424240UL,0x23032320UL,0x11819190UL,0x2C4C606CUL,0x1BCBD3D8UL,0x2484A0A4UL, 0x34043034UL,0x31C1F1F0UL,0x08484048UL,0x02C2C2C0UL,0x2F4F636CUL,0x3D0D313CUL,0x2D0D212CUL,0x00404040UL, 0x3E8EB2BCUL,0x3E0E323CUL,0x3C8CB0BCUL,0x01C1C1C0UL,0x2A8AA2A8UL,0x3A8AB2B8UL,0x0E4E424CUL,0x15455154UL, 0x3B0B3338UL,0x1CCCD0DCUL,0x28486068UL,0x3F4F737CUL,0x1C8C909CUL,0x18C8D0D8UL,0x0A4A4248UL,0x16465254UL, 0x37477374UL,0x2080A0A0UL,0x2DCDE1ECUL,0x06464244UL,0x3585B1B4UL,0x2B0B2328UL,0x25456164UL,0x3ACAF2F8UL, 0x23C3E3E0UL,0x3989B1B8UL,0x3181B1B0UL,0x1F8F939CUL,0x1E4E525CUL,0x39C9F1F8UL,0x26C6E2E4UL,0x3282B2B0UL, 0x31013130UL,0x2ACAE2E8UL,0x2D4D616CUL,0x1F4F535CUL,0x24C4E0E4UL,0x30C0F0F0UL,0x0DCDC1CCUL,0x08888088UL, 0x16061214UL,0x3A0A3238UL,0x18485058UL,0x14C4D0D4UL,0x22426260UL,0x29092128UL,0x07070304UL,0x33033330UL, 0x28C8E0E8UL,0x1B0B1318UL,0x05050104UL,0x39497178UL,0x10809090UL,0x2A4A6268UL,0x2A0A2228UL,0x1A8A9298UL }; static const ulong32 SS1[256] = { 0x38380830UL,0xE828C8E0UL,0x2C2D0D21UL,0xA42686A2UL,0xCC0FCFC3UL,0xDC1ECED2UL,0xB03383B3UL,0xB83888B0UL, 0xAC2F8FA3UL,0x60204060UL,0x54154551UL,0xC407C7C3UL,0x44044440UL,0x6C2F4F63UL,0x682B4B63UL,0x581B4B53UL, 0xC003C3C3UL,0x60224262UL,0x30330333UL,0xB43585B1UL,0x28290921UL,0xA02080A0UL,0xE022C2E2UL,0xA42787A3UL, 0xD013C3D3UL,0x90118191UL,0x10110111UL,0x04060602UL,0x1C1C0C10UL,0xBC3C8CB0UL,0x34360632UL,0x480B4B43UL, 0xEC2FCFE3UL,0x88088880UL,0x6C2C4C60UL,0xA82888A0UL,0x14170713UL,0xC404C4C0UL,0x14160612UL,0xF434C4F0UL, 0xC002C2C2UL,0x44054541UL,0xE021C1E1UL,0xD416C6D2UL,0x3C3F0F33UL,0x3C3D0D31UL,0x8C0E8E82UL,0x98188890UL, 0x28280820UL,0x4C0E4E42UL,0xF436C6F2UL,0x3C3E0E32UL,0xA42585A1UL,0xF839C9F1UL,0x0C0D0D01UL,0xDC1FCFD3UL, 0xD818C8D0UL,0x282B0B23UL,0x64264662UL,0x783A4A72UL,0x24270723UL,0x2C2F0F23UL,0xF031C1F1UL,0x70324272UL, 0x40024242UL,0xD414C4D0UL,0x40014141UL,0xC000C0C0UL,0x70334373UL,0x64274763UL,0xAC2C8CA0UL,0x880B8B83UL, 0xF437C7F3UL,0xAC2D8DA1UL,0x80008080UL,0x1C1F0F13UL,0xC80ACAC2UL,0x2C2C0C20UL,0xA82A8AA2UL,0x34340430UL, 0xD012C2D2UL,0x080B0B03UL,0xEC2ECEE2UL,0xE829C9E1UL,0x5C1D4D51UL,0x94148490UL,0x18180810UL,0xF838C8F0UL, 0x54174753UL,0xAC2E8EA2UL,0x08080800UL,0xC405C5C1UL,0x10130313UL,0xCC0DCDC1UL,0x84068682UL,0xB83989B1UL, 0xFC3FCFF3UL,0x7C3D4D71UL,0xC001C1C1UL,0x30310131UL,0xF435C5F1UL,0x880A8A82UL,0x682A4A62UL,0xB03181B1UL, 0xD011C1D1UL,0x20200020UL,0xD417C7D3UL,0x00020202UL,0x20220222UL,0x04040400UL,0x68284860UL,0x70314171UL, 0x04070703UL,0xD81BCBD3UL,0x9C1D8D91UL,0x98198991UL,0x60214161UL,0xBC3E8EB2UL,0xE426C6E2UL,0x58194951UL, 0xDC1DCDD1UL,0x50114151UL,0x90108090UL,0xDC1CCCD0UL,0x981A8A92UL,0xA02383A3UL,0xA82B8BA3UL,0xD010C0D0UL, 0x80018181UL,0x0C0F0F03UL,0x44074743UL,0x181A0A12UL,0xE023C3E3UL,0xEC2CCCE0UL,0x8C0D8D81UL,0xBC3F8FB3UL, 0x94168692UL,0x783B4B73UL,0x5C1C4C50UL,0xA02282A2UL,0xA02181A1UL,0x60234363UL,0x20230323UL,0x4C0D4D41UL, 0xC808C8C0UL,0x9C1E8E92UL,0x9C1C8C90UL,0x383A0A32UL,0x0C0C0C00UL,0x2C2E0E22UL,0xB83A8AB2UL,0x6C2E4E62UL, 0x9C1F8F93UL,0x581A4A52UL,0xF032C2F2UL,0x90128292UL,0xF033C3F3UL,0x48094941UL,0x78384870UL,0xCC0CCCC0UL, 0x14150511UL,0xF83BCBF3UL,0x70304070UL,0x74354571UL,0x7C3F4F73UL,0x34350531UL,0x10100010UL,0x00030303UL, 0x64244460UL,0x6C2D4D61UL,0xC406C6C2UL,0x74344470UL,0xD415C5D1UL,0xB43484B0UL,0xE82ACAE2UL,0x08090901UL, 0x74364672UL,0x18190911UL,0xFC3ECEF2UL,0x40004040UL,0x10120212UL,0xE020C0E0UL,0xBC3D8DB1UL,0x04050501UL, 0xF83ACAF2UL,0x00010101UL,0xF030C0F0UL,0x282A0A22UL,0x5C1E4E52UL,0xA82989A1UL,0x54164652UL,0x40034343UL, 0x84058581UL,0x14140410UL,0x88098981UL,0x981B8B93UL,0xB03080B0UL,0xE425C5E1UL,0x48084840UL,0x78394971UL, 0x94178793UL,0xFC3CCCF0UL,0x1C1E0E12UL,0x80028282UL,0x20210121UL,0x8C0C8C80UL,0x181B0B13UL,0x5C1F4F53UL, 0x74374773UL,0x54144450UL,0xB03282B2UL,0x1C1D0D11UL,0x24250521UL,0x4C0F4F43UL,0x00000000UL,0x44064642UL, 0xEC2DCDE1UL,0x58184850UL,0x50124252UL,0xE82BCBE3UL,0x7C3E4E72UL,0xD81ACAD2UL,0xC809C9C1UL,0xFC3DCDF1UL, 0x30300030UL,0x94158591UL,0x64254561UL,0x3C3C0C30UL,0xB43686B2UL,0xE424C4E0UL,0xB83B8BB3UL,0x7C3C4C70UL, 0x0C0E0E02UL,0x50104050UL,0x38390931UL,0x24260622UL,0x30320232UL,0x84048480UL,0x68294961UL,0x90138393UL, 0x34370733UL,0xE427C7E3UL,0x24240420UL,0xA42484A0UL,0xC80BCBC3UL,0x50134353UL,0x080A0A02UL,0x84078783UL, 0xD819C9D1UL,0x4C0C4C40UL,0x80038383UL,0x8C0F8F83UL,0xCC0ECEC2UL,0x383B0B33UL,0x480A4A42UL,0xB43787B3UL }; static const ulong32 SS2[256] = { 0xA1A82989UL,0x81840585UL,0xD2D416C6UL,0xD3D013C3UL,0x50541444UL,0x111C1D0DUL,0xA0AC2C8CUL,0x21242505UL, 0x515C1D4DUL,0x43400343UL,0x10181808UL,0x121C1E0EUL,0x51501141UL,0xF0FC3CCCUL,0xC2C80ACAUL,0x63602343UL, 0x20282808UL,0x40440444UL,0x20202000UL,0x919C1D8DUL,0xE0E020C0UL,0xE2E022C2UL,0xC0C808C8UL,0x13141707UL, 0xA1A42585UL,0x838C0F8FUL,0x03000303UL,0x73783B4BUL,0xB3B83B8BUL,0x13101303UL,0xD2D012C2UL,0xE2EC2ECEUL, 0x70703040UL,0x808C0C8CUL,0x333C3F0FUL,0xA0A82888UL,0x32303202UL,0xD1DC1DCDUL,0xF2F436C6UL,0x70743444UL, 0xE0EC2CCCUL,0x91941585UL,0x03080B0BUL,0x53541747UL,0x505C1C4CUL,0x53581B4BUL,0xB1BC3D8DUL,0x01000101UL, 0x20242404UL,0x101C1C0CUL,0x73703343UL,0x90981888UL,0x10101000UL,0xC0CC0CCCUL,0xF2F032C2UL,0xD1D819C9UL, 0x202C2C0CUL,0xE3E427C7UL,0x72703242UL,0x83800383UL,0x93981B8BUL,0xD1D011C1UL,0x82840686UL,0xC1C809C9UL, 0x60602040UL,0x50501040UL,0xA3A02383UL,0xE3E82BCBUL,0x010C0D0DUL,0xB2B43686UL,0x929C1E8EUL,0x434C0F4FUL, 0xB3B43787UL,0x52581A4AUL,0xC2C406C6UL,0x70783848UL,0xA2A42686UL,0x12101202UL,0xA3AC2F8FUL,0xD1D415C5UL, 0x61602141UL,0xC3C003C3UL,0xB0B43484UL,0x41400141UL,0x52501242UL,0x717C3D4DUL,0x818C0D8DUL,0x00080808UL, 0x131C1F0FUL,0x91981989UL,0x00000000UL,0x11181909UL,0x00040404UL,0x53501343UL,0xF3F437C7UL,0xE1E021C1UL, 0xF1FC3DCDUL,0x72743646UL,0x232C2F0FUL,0x23242707UL,0xB0B03080UL,0x83880B8BUL,0x020C0E0EUL,0xA3A82B8BUL, 0xA2A02282UL,0x626C2E4EUL,0x93901383UL,0x414C0D4DUL,0x61682949UL,0x707C3C4CUL,0x01080909UL,0x02080A0AUL, 0xB3BC3F8FUL,0xE3EC2FCFUL,0xF3F033C3UL,0xC1C405C5UL,0x83840787UL,0x10141404UL,0xF2FC3ECEUL,0x60642444UL, 0xD2DC1ECEUL,0x222C2E0EUL,0x43480B4BUL,0x12181A0AUL,0x02040606UL,0x21202101UL,0x63682B4BUL,0x62642646UL, 0x02000202UL,0xF1F435C5UL,0x92901282UL,0x82880A8AUL,0x000C0C0CUL,0xB3B03383UL,0x727C3E4EUL,0xD0D010C0UL, 0x72783A4AUL,0x43440747UL,0x92941686UL,0xE1E425C5UL,0x22242606UL,0x80800080UL,0xA1AC2D8DUL,0xD3DC1FCFUL, 0xA1A02181UL,0x30303000UL,0x33343707UL,0xA2AC2E8EUL,0x32343606UL,0x11141505UL,0x22202202UL,0x30383808UL, 0xF0F434C4UL,0xA3A42787UL,0x41440545UL,0x404C0C4CUL,0x81800181UL,0xE1E829C9UL,0x80840484UL,0x93941787UL, 0x31343505UL,0xC3C80BCBUL,0xC2CC0ECEUL,0x303C3C0CUL,0x71703141UL,0x11101101UL,0xC3C407C7UL,0x81880989UL, 0x71743545UL,0xF3F83BCBUL,0xD2D81ACAUL,0xF0F838C8UL,0x90941484UL,0x51581949UL,0x82800282UL,0xC0C404C4UL, 0xF3FC3FCFUL,0x41480949UL,0x31383909UL,0x63642747UL,0xC0C000C0UL,0xC3CC0FCFUL,0xD3D417C7UL,0xB0B83888UL, 0x030C0F0FUL,0x828C0E8EUL,0x42400242UL,0x23202303UL,0x91901181UL,0x606C2C4CUL,0xD3D81BCBUL,0xA0A42484UL, 0x30343404UL,0xF1F031C1UL,0x40480848UL,0xC2C002C2UL,0x636C2F4FUL,0x313C3D0DUL,0x212C2D0DUL,0x40400040UL, 0xB2BC3E8EUL,0x323C3E0EUL,0xB0BC3C8CUL,0xC1C001C1UL,0xA2A82A8AUL,0xB2B83A8AUL,0x424C0E4EUL,0x51541545UL, 0x33383B0BUL,0xD0DC1CCCUL,0x60682848UL,0x737C3F4FUL,0x909C1C8CUL,0xD0D818C8UL,0x42480A4AUL,0x52541646UL, 0x73743747UL,0xA0A02080UL,0xE1EC2DCDUL,0x42440646UL,0xB1B43585UL,0x23282B0BUL,0x61642545UL,0xF2F83ACAUL, 0xE3E023C3UL,0xB1B83989UL,0xB1B03181UL,0x939C1F8FUL,0x525C1E4EUL,0xF1F839C9UL,0xE2E426C6UL,0xB2B03282UL, 0x31303101UL,0xE2E82ACAUL,0x616C2D4DUL,0x535C1F4FUL,0xE0E424C4UL,0xF0F030C0UL,0xC1CC0DCDUL,0x80880888UL, 0x12141606UL,0x32383A0AUL,0x50581848UL,0xD0D414C4UL,0x62602242UL,0x21282909UL,0x03040707UL,0x33303303UL, 0xE0E828C8UL,0x13181B0BUL,0x01040505UL,0x71783949UL,0x90901080UL,0x62682A4AUL,0x22282A0AUL,0x92981A8AUL }; static const ulong32 SS3[256] = { 0x08303838UL,0xC8E0E828UL,0x0D212C2DUL,0x86A2A426UL,0xCFC3CC0FUL,0xCED2DC1EUL,0x83B3B033UL,0x88B0B838UL, 0x8FA3AC2FUL,0x40606020UL,0x45515415UL,0xC7C3C407UL,0x44404404UL,0x4F636C2FUL,0x4B63682BUL,0x4B53581BUL, 0xC3C3C003UL,0x42626022UL,0x03333033UL,0x85B1B435UL,0x09212829UL,0x80A0A020UL,0xC2E2E022UL,0x87A3A427UL, 0xC3D3D013UL,0x81919011UL,0x01111011UL,0x06020406UL,0x0C101C1CUL,0x8CB0BC3CUL,0x06323436UL,0x4B43480BUL, 0xCFE3EC2FUL,0x88808808UL,0x4C606C2CUL,0x88A0A828UL,0x07131417UL,0xC4C0C404UL,0x06121416UL,0xC4F0F434UL, 0xC2C2C002UL,0x45414405UL,0xC1E1E021UL,0xC6D2D416UL,0x0F333C3FUL,0x0D313C3DUL,0x8E828C0EUL,0x88909818UL, 0x08202828UL,0x4E424C0EUL,0xC6F2F436UL,0x0E323C3EUL,0x85A1A425UL,0xC9F1F839UL,0x0D010C0DUL,0xCFD3DC1FUL, 0xC8D0D818UL,0x0B23282BUL,0x46626426UL,0x4A72783AUL,0x07232427UL,0x0F232C2FUL,0xC1F1F031UL,0x42727032UL, 0x42424002UL,0xC4D0D414UL,0x41414001UL,0xC0C0C000UL,0x43737033UL,0x47636427UL,0x8CA0AC2CUL,0x8B83880BUL, 0xC7F3F437UL,0x8DA1AC2DUL,0x80808000UL,0x0F131C1FUL,0xCAC2C80AUL,0x0C202C2CUL,0x8AA2A82AUL,0x04303434UL, 0xC2D2D012UL,0x0B03080BUL,0xCEE2EC2EUL,0xC9E1E829UL,0x4D515C1DUL,0x84909414UL,0x08101818UL,0xC8F0F838UL, 0x47535417UL,0x8EA2AC2EUL,0x08000808UL,0xC5C1C405UL,0x03131013UL,0xCDC1CC0DUL,0x86828406UL,0x89B1B839UL, 0xCFF3FC3FUL,0x4D717C3DUL,0xC1C1C001UL,0x01313031UL,0xC5F1F435UL,0x8A82880AUL,0x4A62682AUL,0x81B1B031UL, 0xC1D1D011UL,0x00202020UL,0xC7D3D417UL,0x02020002UL,0x02222022UL,0x04000404UL,0x48606828UL,0x41717031UL, 0x07030407UL,0xCBD3D81BUL,0x8D919C1DUL,0x89919819UL,0x41616021UL,0x8EB2BC3EUL,0xC6E2E426UL,0x49515819UL, 0xCDD1DC1DUL,0x41515011UL,0x80909010UL,0xCCD0DC1CUL,0x8A92981AUL,0x83A3A023UL,0x8BA3A82BUL,0xC0D0D010UL, 0x81818001UL,0x0F030C0FUL,0x47434407UL,0x0A12181AUL,0xC3E3E023UL,0xCCE0EC2CUL,0x8D818C0DUL,0x8FB3BC3FUL, 0x86929416UL,0x4B73783BUL,0x4C505C1CUL,0x82A2A022UL,0x81A1A021UL,0x43636023UL,0x03232023UL,0x4D414C0DUL, 0xC8C0C808UL,0x8E929C1EUL,0x8C909C1CUL,0x0A32383AUL,0x0C000C0CUL,0x0E222C2EUL,0x8AB2B83AUL,0x4E626C2EUL, 0x8F939C1FUL,0x4A52581AUL,0xC2F2F032UL,0x82929012UL,0xC3F3F033UL,0x49414809UL,0x48707838UL,0xCCC0CC0CUL, 0x05111415UL,0xCBF3F83BUL,0x40707030UL,0x45717435UL,0x4F737C3FUL,0x05313435UL,0x00101010UL,0x03030003UL, 0x44606424UL,0x4D616C2DUL,0xC6C2C406UL,0x44707434UL,0xC5D1D415UL,0x84B0B434UL,0xCAE2E82AUL,0x09010809UL, 0x46727436UL,0x09111819UL,0xCEF2FC3EUL,0x40404000UL,0x02121012UL,0xC0E0E020UL,0x8DB1BC3DUL,0x05010405UL, 0xCAF2F83AUL,0x01010001UL,0xC0F0F030UL,0x0A22282AUL,0x4E525C1EUL,0x89A1A829UL,0x46525416UL,0x43434003UL, 0x85818405UL,0x04101414UL,0x89818809UL,0x8B93981BUL,0x80B0B030UL,0xC5E1E425UL,0x48404808UL,0x49717839UL, 0x87939417UL,0xCCF0FC3CUL,0x0E121C1EUL,0x82828002UL,0x01212021UL,0x8C808C0CUL,0x0B13181BUL,0x4F535C1FUL, 0x47737437UL,0x44505414UL,0x82B2B032UL,0x0D111C1DUL,0x05212425UL,0x4F434C0FUL,0x00000000UL,0x46424406UL, 0xCDE1EC2DUL,0x48505818UL,0x42525012UL,0xCBE3E82BUL,0x4E727C3EUL,0xCAD2D81AUL,0xC9C1C809UL,0xCDF1FC3DUL, 0x00303030UL,0x85919415UL,0x45616425UL,0x0C303C3CUL,0x86B2B436UL,0xC4E0E424UL,0x8BB3B83BUL,0x4C707C3CUL, 0x0E020C0EUL,0x40505010UL,0x09313839UL,0x06222426UL,0x02323032UL,0x84808404UL,0x49616829UL,0x83939013UL, 0x07333437UL,0xC7E3E427UL,0x04202424UL,0x84A0A424UL,0xCBC3C80BUL,0x43535013UL,0x0A02080AUL,0x87838407UL, 0xC9D1D819UL,0x4C404C0CUL,0x83838003UL,0x8F838C0FUL,0xCEC2CC0EUL,0x0B33383BUL,0x4A42480AUL,0x87B3B437UL }; static const ulong32 KCi[16] = { 0x9E3779B9,0x3C6EF373, 0x78DDE6E6,0xF1BBCDCC, 0xE3779B99,0xC6EF3733, 0x8DDE6E67,0x1BBCDCCF, 0x3779B99E,0x6EF3733C, 0xDDE6E678,0xBBCDCCF1, 0x779B99E3,0xEF3733C6, 0xDE6E678D,0xBCDCCF1B }; #define G(x) (SS3[((x)>>24)&255] ^ SS2[((x)>>16)&255] ^ SS1[((x)>>8)&255] ^ SS0[(x)&255]) #define F(L1, L2, R1, R2, K1, K2) \ T2 = G((R1 ^ K1) ^ (R2 ^ K2)); \ T = G( G(T2 + (R1 ^ K1)) + T2); \ L2 ^= T; \ L1 ^= (T + G(T2 + (R1 ^ K1))); \ /** Initialize the SEED block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int i; ulong32 tmp, k1, k2, k3, k4; if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 16 && num_rounds != 0) { return CRYPT_INVALID_ROUNDS; } /* load key */ LOAD32H(k1, key); LOAD32H(k2, key+4); LOAD32H(k3, key+8); LOAD32H(k4, key+12); for (i = 0; i < 16; i++) { skey->kseed.K[2*i+0] = G(k1 + k3 - KCi[i]); skey->kseed.K[2*i+1] = G(k2 - k4 + KCi[i]); if (i&1) { tmp = k3; k3 = ((k3 << 8) | (k4 >> 24)) & 0xFFFFFFFF; k4 = ((k4 << 8) | (tmp >> 24)) & 0xFFFFFFFF; } else { tmp = k1; k1 = ((k1 >> 8) | (k2 << 24)) & 0xFFFFFFFF; k2 = ((k2 >> 8) | (tmp << 24)) & 0xFFFFFFFF; } /* reverse keys for decrypt */ skey->kseed.dK[2*(15-i)+0] = skey->kseed.K[2*i+0]; skey->kseed.dK[2*(15-i)+1] = skey->kseed.K[2*i+1]; } return CRYPT_OK; } static void rounds(ulong32 *P, const ulong32 *K) { ulong32 T, T2; int i; for (i = 0; i < 16; i += 2) { F(P[0], P[1], P[2], P[3], K[0], K[1]); F(P[2], P[3], P[0], P[1], K[2], K[3]); K += 4; } } /** Encrypts a block of text with SEED @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 P[4]; LOAD32H(P[0], pt); LOAD32H(P[1], pt+4); LOAD32H(P[2], pt+8); LOAD32H(P[3], pt+12); rounds(P, skey->kseed.K); STORE32H(P[2], ct); STORE32H(P[3], ct+4); STORE32H(P[0], ct+8); STORE32H(P[1], ct+12); return CRYPT_OK; } /** Decrypts a block of text with SEED @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 P[4]; LOAD32H(P[0], ct); LOAD32H(P[1], ct+4); LOAD32H(P[2], ct+8); LOAD32H(P[3], ct+12); rounds(P, skey->kseed.dK); STORE32H(P[2], pt); STORE32H(P[3], pt+4); STORE32H(P[0], pt+8); STORE32H(P[1], pt+12); return CRYPT_OK; } /** Terminate the context @param skey The scheduled key */ void kseed_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Performs a self-test of the SEED block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int kseed_test(void) { #if !defined(LTC_TEST) return CRYPT_NOP; #else static const struct test { unsigned char pt[16], ct[16], key[16]; } tests[] = { { { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, { 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB }, { 0 }, }, { { 0 }, { 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 }, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, }, { { 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D }, { 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A }, { 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 }, }, { { 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 }, { 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 }, { 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 }, } }; int x; unsigned char buf[2][16]; symmetric_key skey; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { kseed_setup(tests[x].key, 16, 0, &skey); kseed_ecb_encrypt(tests[x].pt, buf[0], &skey); kseed_ecb_decrypt(buf[0], buf[1], &skey); if (compare_testvector(buf[0], 16, tests[x].ct, 16, "KSEED Encrypt", x) || compare_testvector(buf[1], 16, tests[x].pt, 16, "KSEED Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int kseed_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize >= 16) { *keysize = 16; } else { return CRYPT_INVALID_KEYSIZE; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/multi2.c000066400000000000000000000160641464416617300232300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file multi2.c Multi-2 implementation (not public domain, hence the default disable) */ #include "tomcrypt_private.h" #ifdef LTC_MULTI2 static void s_pi1(ulong32 *p) { p[1] ^= p[0]; } static void s_pi2(ulong32 *p, const ulong32 *k) { ulong32 t; t = (p[1] + k[0]) & 0xFFFFFFFFUL; t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL; t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL; p[0] ^= t; } static void s_pi3(ulong32 *p, const ulong32 *k) { ulong32 t; t = p[0] + k[1]; t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; t = (ROL(t, 8) ^ t) & 0xFFFFFFFFUL; t = (t + k[2]) & 0xFFFFFFFFUL; t = (ROL(t, 1) - t) & 0xFFFFFFFFUL; t = ROL(t, 16) ^ (p[0] | t); p[1] ^= t; } static void s_pi4(ulong32 *p, const ulong32 *k) { ulong32 t; t = (p[1] + k[3]) & 0xFFFFFFFFUL; t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; p[0] ^= t; } static void s_setup(const ulong32 *dk, const ulong32 *k, ulong32 *uk) { int n, t; ulong32 p[2]; p[0] = dk[0]; p[1] = dk[1]; t = 4; n = 0; s_pi1(p); s_pi2(p, k); uk[n++] = p[0]; s_pi3(p, k); uk[n++] = p[1]; s_pi4(p, k); uk[n++] = p[0]; s_pi1(p); uk[n++] = p[1]; s_pi2(p, k+t); uk[n++] = p[0]; s_pi3(p, k+t); uk[n++] = p[1]; s_pi4(p, k+t); uk[n++] = p[0]; s_pi1(p); uk[n++] = p[1]; } static void s_encrypt(ulong32 *p, int N, const ulong32 *uk) { int n, t; for (t = n = 0; ; ) { s_pi1(p); if (++n == N) break; s_pi2(p, uk+t); if (++n == N) break; s_pi3(p, uk+t); if (++n == N) break; s_pi4(p, uk+t); if (++n == N) break; t ^= 4; } } static void s_decrypt(ulong32 *p, int N, const ulong32 *uk) { int n, t; for (t = 4*(((N-1)>>2)&1), n = N; ; ) { switch (n<=4 ? n : ((n-1)%4)+1) { case 4: s_pi4(p, uk+t); --n; /* FALLTHROUGH */ case 3: s_pi3(p, uk+t); --n; /* FALLTHROUGH */ case 2: s_pi2(p, uk+t); --n; /* FALLTHROUGH */ case 1: s_pi1(p); --n; break; case 0: return; } t ^= 4; } } const struct ltc_cipher_descriptor multi2_desc = { "multi2", 22, 40, 40, 8, 128, &multi2_setup, &multi2_ecb_encrypt, &multi2_ecb_decrypt, &multi2_test, &multi2_done, &multi2_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { ulong32 sk[8], dk[2]; int x; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 40) return CRYPT_INVALID_KEYSIZE; if (num_rounds == 0) num_rounds = 128; skey->multi2.N = num_rounds; for (x = 0; x < 8; x++) { LOAD32H(sk[x], key + x*4); } LOAD32H(dk[0], key + 32); LOAD32H(dk[1], key + 36); s_setup(dk, sk, skey->multi2.uk); zeromem(sk, sizeof(sk)); zeromem(dk, sizeof(dk)); return CRYPT_OK; } /** Encrypts a block of text with multi2 @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 p[2]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(p[0], pt); LOAD32H(p[1], pt+4); s_encrypt(p, skey->multi2.N, skey->multi2.uk); STORE32H(p[0], ct); STORE32H(p[1], ct+4); return CRYPT_OK; } /** Decrypts a block of text with multi2 @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 p[2]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(p[0], ct); LOAD32H(p[1], ct+4); s_decrypt(p, skey->multi2.N, skey->multi2.uk); STORE32H(p[0], pt); STORE32H(p[1], pt+4); return CRYPT_OK; } /** Performs a self-test of the multi2 block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int multi2_test(void) { static const struct { unsigned char key[40]; unsigned char pt[8], ct[8]; int rounds; } tests[] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }, { 0xf8, 0x94, 0x40, 0x84, 0x5e, 0x11, 0xcf, 0x89 }, 128, }, { { 0x35, 0x91, 0x9d, 0x96, 0x07, 0x02, 0xe2, 0xce, 0x8d, 0x0b, 0x58, 0x3c, 0xc9, 0xc8, 0x9d, 0x59, 0xa2, 0xae, 0x96, 0x4e, 0x87, 0x82, 0x45, 0xed, 0x3f, 0x2e, 0x62, 0xd6, 0x36, 0x35, 0xd0, 0x67, 0xb1, 0x27, 0xb9, 0x06, 0xe7, 0x56, 0x22, 0x38, }, { 0x1f, 0xb4, 0x60, 0x60, 0xd0, 0xb3, 0x4f, 0xa5 }, { 0xca, 0x84, 0xa9, 0x34, 0x75, 0xc8, 0x60, 0xe5 }, 216, } }; unsigned char buf[8]; symmetric_key skey; int err, x; for (x = 1; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = multi2_setup(tests[x].key, 40, tests[x].rounds, &skey)) != CRYPT_OK) { return err; } if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) { return err; } if (compare_testvector(buf, 8, tests[x].ct, 8, "Multi2 Encrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) { return err; } if (compare_testvector(buf, 8, tests[x].pt, 8, "Multi2 Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } } for (x = 128; x < 256; ++x) { unsigned char ct[8]; if ((err = multi2_setup(tests[0].key, 40, x, &skey)) != CRYPT_OK) { return err; } if ((err = multi2_ecb_encrypt(tests[0].pt, ct, &skey)) != CRYPT_OK) { return err; } if ((err = multi2_ecb_decrypt(ct, buf, &skey)) != CRYPT_OK) { return err; } if (compare_testvector(buf, 8, tests[0].pt, 8, "Multi2 Rounds", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; } /** Terminate the context @param skey The scheduled key */ void multi2_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int multi2_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize >= 40) { *keysize = 40; } else { return CRYPT_INVALID_KEYSIZE; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/noekeon.c000066400000000000000000000233311464416617300234450ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file noekeon.c Implementation of the Noekeon block cipher by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_NOEKEON const struct ltc_cipher_descriptor noekeon_desc = { "noekeon", 16, 16, 16, 16, 16, &noekeon_setup, &noekeon_ecb_encrypt, &noekeon_ecb_decrypt, &noekeon_test, &noekeon_done, &noekeon_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 RC[] = { 0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL, 0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL, 0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL, 0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL, 0x000000d4UL }; #define kTHETA(a, b, c, d) \ temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ b ^= temp; d ^= temp; \ temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ a ^= temp; c ^= temp; #define THETA(k, a, b, c, d) \ temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ b ^= temp ^ k[1]; d ^= temp ^ k[3]; \ temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ a ^= temp ^ k[0]; c ^= temp ^ k[2]; #define GAMMA(a, b, c, d) \ b ^= ~(d|c); \ a ^= c&b; \ temp = d; d = a; a = temp;\ c ^= a ^ b ^ d; \ b ^= ~(d|c); \ a ^= c&b; #define PI1(a, b, c, d) \ b = ROLc(b, 1); c = ROLc(c, 5); d = ROLc(d, 2); #define PI2(a, b, c, d) \ b = RORc(b, 1); c = RORc(c, 5); d = RORc(d, 2); /** Initialize the Noekeon block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { ulong32 temp; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 16 && num_rounds != 0) { return CRYPT_INVALID_ROUNDS; } LOAD32H(skey->noekeon.K[0],&key[0]); LOAD32H(skey->noekeon.K[1],&key[4]); LOAD32H(skey->noekeon.K[2],&key[8]); LOAD32H(skey->noekeon.K[3],&key[12]); LOAD32H(skey->noekeon.dK[0],&key[0]); LOAD32H(skey->noekeon.dK[1],&key[4]); LOAD32H(skey->noekeon.dK[2],&key[8]); LOAD32H(skey->noekeon.dK[3],&key[12]); kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]); return CRYPT_OK; } /** Encrypts a block of text with Noekeon @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 a,b,c,d,temp; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]); LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]); #define ROUND(i) \ a ^= RC[i]; \ THETA(skey->noekeon.K, a,b,c,d); \ PI1(a,b,c,d); \ GAMMA(a,b,c,d); \ PI2(a,b,c,d); for (r = 0; r < 16; ++r) { ROUND(r); } #undef ROUND a ^= RC[16]; THETA(skey->noekeon.K, a, b, c, d); STORE32H(a,&ct[0]); STORE32H(b,&ct[4]); STORE32H(c,&ct[8]); STORE32H(d,&ct[12]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_noekeon_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(ulong32) * 5 + sizeof(int)); return err; } #endif /** Decrypts a block of text with Noekeon @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 a,b,c,d, temp; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]); LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]); #define ROUND(i) \ THETA(skey->noekeon.dK, a,b,c,d); \ a ^= RC[i]; \ PI1(a,b,c,d); \ GAMMA(a,b,c,d); \ PI2(a,b,c,d); for (r = 16; r > 0; --r) { ROUND(r); } #undef ROUND THETA(skey->noekeon.dK, a,b,c,d); a ^= RC[0]; STORE32H(a,&pt[0]); STORE32H(b, &pt[4]); STORE32H(c,&pt[8]); STORE32H(d, &pt[12]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_noekeon_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(ulong32) * 5 + sizeof(int)); return err; } #endif /** Performs a self-test of the Noekeon block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int noekeon_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key[16], pt[16], ct[16]; } tests[] = { { 16, { 0xAA, 0x3C, 0x8C, 0x86, 0xD9, 0x8B, 0xF8, 0xBE, 0x21, 0xE0, 0x36, 0x09, 0x78, 0xFB, 0xE4, 0x90 }, { 0xE4, 0x96, 0x6C, 0xD3, 0x13, 0xA0, 0x6C, 0xAF, 0xD0, 0x23, 0xC9, 0xFD, 0x45, 0x32, 0x23, 0x16 }, { 0xA6, 0xEC, 0xB8, 0xA8, 0x61, 0xFD, 0x62, 0xD9, 0x13, 0x02, 0xFE, 0x9E, 0x47, 0x01, 0x3F, 0xC3 } }, { 16, { 0xED, 0x43, 0xD1, 0x87, 0x21, 0x7E, 0xE0, 0x97, 0x3D, 0x76, 0xC3, 0x37, 0x2E, 0x7D, 0xAE, 0xD3 }, { 0xE3, 0x38, 0x32, 0xCC, 0xF2, 0x2F, 0x2F, 0x0A, 0x4A, 0x8B, 0x8F, 0x18, 0x12, 0x20, 0x17, 0xD3 }, { 0x94, 0xA5, 0xDF, 0xF5, 0xAE, 0x1C, 0xBB, 0x22, 0xAD, 0xEB, 0xA7, 0x0D, 0xB7, 0x82, 0x90, 0xA0 } }, { 16, { 0x6F, 0xDC, 0x23, 0x38, 0xF2, 0x10, 0xFB, 0xD3, 0xC1, 0x8C, 0x02, 0xF6, 0xB4, 0x6A, 0xD5, 0xA8 }, { 0xDB, 0x29, 0xED, 0xB5, 0x5F, 0xB3, 0x60, 0x3A, 0x92, 0xA8, 0xEB, 0x9C, 0x6D, 0x9D, 0x3E, 0x8F }, { 0x78, 0xF3, 0x6F, 0xF8, 0x9E, 0xBB, 0x8C, 0x6A, 0xE8, 0x10, 0xF7, 0x00, 0x22, 0x15, 0x30, 0x3D } }, { 16, { 0x2C, 0x0C, 0x02, 0xEF, 0x6B, 0xC4, 0xF2, 0x0B, 0x2E, 0xB9, 0xE0, 0xBF, 0xD9, 0x36, 0xC2, 0x4E }, { 0x84, 0xE2, 0xFE, 0x64, 0xB1, 0xB9, 0xFE, 0x76, 0xA8, 0x3F, 0x45, 0xC7, 0x40, 0x7A, 0xAF, 0xEE }, { 0x2A, 0x08, 0xD6, 0xA2, 0x1C, 0x63, 0x08, 0xB0, 0xF8, 0xBC, 0xB3, 0xA1, 0x66, 0xF7, 0xAE, 0xCF } }, { 16, { 0x6F, 0x30, 0xF8, 0x9F, 0xDA, 0x6E, 0xA0, 0x91, 0x04, 0x0F, 0x6C, 0x8B, 0x7D, 0xF7, 0x2A, 0x4B }, { 0x65, 0xB6, 0xA6, 0xD0, 0x42, 0x14, 0x08, 0x60, 0x34, 0x8D, 0x37, 0x2F, 0x01, 0xF0, 0x46, 0xBE }, { 0x66, 0xAC, 0x0B, 0x62, 0x1D, 0x68, 0x11, 0xF5, 0x27, 0xB1, 0x13, 0x5D, 0xF3, 0x2A, 0xE9, 0x18 } }, { 16, { 0xCA, 0xA4, 0x16, 0xB7, 0x1C, 0x92, 0x2E, 0xAD, 0xEB, 0xA7, 0xDB, 0x69, 0x92, 0xCB, 0x35, 0xEF }, { 0x81, 0x6F, 0x8E, 0x4D, 0x96, 0xC6, 0xB3, 0x67, 0x83, 0xF5, 0x63, 0xC7, 0x20, 0x6D, 0x40, 0x23 }, { 0x44, 0xF7, 0x63, 0x62, 0xF0, 0x43, 0xBB, 0x67, 0x4A, 0x75, 0x12, 0x42, 0x46, 0x29, 0x28, 0x19 } }, { 16, { 0x6B, 0xCF, 0x22, 0x2F, 0xE0, 0x1B, 0xB0, 0xAA, 0xD8, 0x3C, 0x91, 0x99, 0x18, 0xB2, 0x28, 0xE8 }, { 0x7C, 0x37, 0xC7, 0xD0, 0xAC, 0x92, 0x29, 0xF1, 0x60, 0x82, 0x93, 0x89, 0xAA, 0x61, 0xAA, 0xA9 }, { 0xE5, 0x89, 0x1B, 0xB3, 0xFE, 0x8B, 0x0C, 0xA1, 0xA6, 0xC7, 0xBE, 0x12, 0x73, 0x0F, 0xC1, 0x19 } }, { 16, { 0xE6, 0xD0, 0xF1, 0x03, 0x2E, 0xDE, 0x70, 0x8D, 0xD8, 0x9E, 0x36, 0x5C, 0x05, 0x52, 0xE7, 0x0D }, { 0xE2, 0x42, 0xE7, 0x92, 0x0E, 0xF7, 0x82, 0xA2, 0xB8, 0x21, 0x8D, 0x26, 0xBA, 0x2D, 0xE6, 0x32 }, { 0x1E, 0xDD, 0x75, 0x22, 0xB9, 0x36, 0x8A, 0x0F, 0x32, 0xFD, 0xD4, 0x48, 0x65, 0x12, 0x5A, 0x2F } } }; symmetric_key key; unsigned char tmp[2][16]; int err, i, y; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { zeromem(&key, sizeof(key)); if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key); noekeon_ecb_decrypt(tmp[0], tmp[1], &key); if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Noekeon Encrypt", i) || compare_testvector(tmp[1], 16, tests[i].pt, 16, "Noekeon Decrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) noekeon_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void noekeon_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int noekeon_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } *keysize = 16; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/rc2.c000066400000000000000000000323441464416617300225010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /**********************************************************************\ * To commemorate the 1996 RSA Data Security Conference, the following * * code is released into the public domain by its author. Prost! * * * * This cipher uses 16-bit words and little-endian byte ordering. * * I wonder which processor it was optimized for? * * * * Thanks to CodeView, SoftIce, and D86 for helping bring this code to * * the public. * \**********************************************************************/ #include "tomcrypt_private.h" /** @file rc2.c Implementation of RC2 with fixed effective key length of 64bits */ #ifdef LTC_RC2 const struct ltc_cipher_descriptor rc2_desc = { "rc2", 12, 8, 128, 8, 16, &rc2_setup, &rc2_ecb_encrypt, &rc2_ecb_decrypt, &rc2_test, &rc2_done, &rc2_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* 256-entry permutation table, probably derived somehow from pi */ static const unsigned char permute[256] = { 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 }; /** Initialize the RC2 block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param bits The effective key length in bits @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey) { unsigned *xkey = skey->rc2.xkey; unsigned char tmp[128]; unsigned T8, TM; int i; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen == 0 || keylen > 128 || bits > 1024) { return CRYPT_INVALID_KEYSIZE; } if (bits == 0) { bits = 1024; } if (num_rounds != 0 && num_rounds != 16) { return CRYPT_INVALID_ROUNDS; } for (i = 0; i < keylen; i++) { tmp[i] = key[i] & 255; } /* Phase 1: Expand input key to 128 bytes */ if (keylen < 128) { for (i = keylen; i < 128; i++) { tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255]; } } /* Phase 2 - reduce effective key size to "bits" */ T8 = (unsigned)(bits+7)>>3; TM = (255 >> (unsigned)(7 & -bits)); tmp[128 - T8] = permute[tmp[128 - T8] & TM]; for (i = 127 - T8; i >= 0; i--) { tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]]; } /* Phase 3 - copy to xkey in little-endian order */ for (i = 0; i < 64; i++) { xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8); } #ifdef LTC_CLEAN_STACK zeromem(tmp, sizeof(tmp)); #endif return CRYPT_OK; } /** Initialize the RC2 block cipher The effective key length is here always keylen * 8 @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { return rc2_setup_ex(key, keylen, keylen * 8, num_rounds, skey); } /**********************************************************************\ * Encrypt an 8-byte block of plaintext using the given key. * \**********************************************************************/ /** Encrypts a block of text with RC2 @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rc2_ecb_encrypt( const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int rc2_ecb_encrypt( const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { const unsigned *xkey; unsigned x76, x54, x32, x10, i; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); xkey = skey->rc2.xkey; x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6]; x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4]; x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2]; x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0]; for (i = 0; i < 16; i++) { x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF; x10 = ((x10 << 1) | (x10 >> 15)); x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF; x32 = ((x32 << 2) | (x32 >> 14)); x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF; x54 = ((x54 << 3) | (x54 >> 13)); x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF; x76 = ((x76 << 5) | (x76 >> 11)); if (i == 4 || i == 10) { x10 = (x10 + xkey[x76 & 63]) & 0xFFFF; x32 = (x32 + xkey[x10 & 63]) & 0xFFFF; x54 = (x54 + xkey[x32 & 63]) & 0xFFFF; x76 = (x76 + xkey[x54 & 63]) & 0xFFFF; } } ct[0] = (unsigned char)x10; ct[1] = (unsigned char)(x10 >> 8); ct[2] = (unsigned char)x32; ct[3] = (unsigned char)(x32 >> 8); ct[4] = (unsigned char)x54; ct[5] = (unsigned char)(x54 >> 8); ct[6] = (unsigned char)x76; ct[7] = (unsigned char)(x76 >> 8); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc2_ecb_encrypt( const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_rc2_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5); return err; } #endif /**********************************************************************\ * Decrypt an 8-byte block of ciphertext using the given key. * \**********************************************************************/ /** Decrypts a block of text with RC2 @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rc2_ecb_decrypt( const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int rc2_ecb_decrypt( const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { unsigned x76, x54, x32, x10; const unsigned *xkey; int i; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); xkey = skey->rc2.xkey; x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6]; x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4]; x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2]; x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0]; for (i = 15; i >= 0; i--) { if (i == 4 || i == 10) { x76 = (x76 - xkey[x54 & 63]) & 0xFFFF; x54 = (x54 - xkey[x32 & 63]) & 0xFFFF; x32 = (x32 - xkey[x10 & 63]) & 0xFFFF; x10 = (x10 - xkey[x76 & 63]) & 0xFFFF; } x76 = ((x76 << 11) | (x76 >> 5)); x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF; x54 = ((x54 << 13) | (x54 >> 3)); x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF; x32 = ((x32 << 14) | (x32 >> 2)); x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF; x10 = ((x10 << 15) | (x10 >> 1)); x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF; } pt[0] = (unsigned char)x10; pt[1] = (unsigned char)(x10 >> 8); pt[2] = (unsigned char)x32; pt[3] = (unsigned char)(x32 >> 8); pt[4] = (unsigned char)x54; pt[5] = (unsigned char)(x54 >> 8); pt[6] = (unsigned char)x76; pt[7] = (unsigned char)(x76 >> 8); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc2_ecb_decrypt( const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_rc2_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int)); return err; } #endif /** Performs a self-test of the RC2 block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int rc2_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen, bits; unsigned char key[16], pt[8], ct[8]; } tests[] = { { 8, 63, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff } }, { 8, 64, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, { 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49 } }, { 8, 64, { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 } }, { 1, 64, { 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0 } }, { 7, 64, { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f } }, { 16, 64, { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1 } }, { 16, 128, { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 } } }; int x, y, err; symmetric_key skey; unsigned char tmp[2][8]; for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { zeromem(tmp, sizeof(tmp)); if (tests[x].bits == (tests[x].keylen * 8)) { if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { return err; } } else { if ((err = rc2_setup_ex(tests[x].key, tests[x].keylen, tests[x].bits, 0, &skey)) != CRYPT_OK) { return err; } } rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey); rc2_ecb_decrypt(tmp[0], tmp[1], &skey); if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC2 CT", x) || compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC2 PT", x)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void rc2_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int rc2_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 1) { return CRYPT_INVALID_KEYSIZE; } if (*keysize > 128) { *keysize = 128; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/rc5.c000066400000000000000000000213441464416617300225020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file rc5.c LTC_RC5 code by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_RC5 const struct ltc_cipher_descriptor rc5_desc = { "rc5", 2, 8, 128, 8, 12, &rc5_setup, &rc5_ecb_encrypt, &rc5_ecb_decrypt, &rc5_test, &rc5_done, &rc5_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 stab[50] = { 0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, 0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, 0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, 0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, 0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, 0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL, 0x62482413UL, 0x007f9dccUL }; /** Initialize the LTC_RC5 block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #else int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #endif { ulong32 L[64], *S, A, B, i, j, v, s, t, l; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(key != NULL); /* test parameters */ if (num_rounds == 0) { num_rounds = rc5_desc.default_rounds; } if (num_rounds < 12 || num_rounds > 24) { return CRYPT_INVALID_ROUNDS; } /* key must be between 64 and 1024 bits */ if (keylen < 8 || keylen > 128) { return CRYPT_INVALID_KEYSIZE; } skey->rc5.rounds = num_rounds; S = skey->rc5.K; /* copy the key into the L array */ for (A = i = j = 0; i < (ulong32)keylen; ) { A = (A << 8) | ((ulong32)(key[i++] & 255)); if ((i & 3) == 0) { L[j++] = BSWAP(A); A = 0; } } if ((keylen & 3) != 0) { A <<= (ulong32)((8 * (4 - (keylen&3)))); L[j++] = BSWAP(A); } /* setup the S array */ t = (ulong32)(2 * (num_rounds + 1)); XMEMCPY(S, stab, t * sizeof(*S)); /* mix buffer */ s = 3 * MAX(t, j); l = j; for (A = B = i = j = v = 0; v < s; v++) { A = S[i] = ROLc(S[i] + A + B, 3); B = L[j] = ROL(L[j] + A + B, (A+B)); if (++i == t) { i = 0; } if (++j == l) { j = 0; } } return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int x; x = s_rc5_setup(key, keylen, num_rounds, skey); burn_stack(sizeof(ulong32) * 122 + sizeof(int)); return x; } #endif /** Encrypts a block of text with LTC_RC5 @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 A, B; const ulong32 *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { return CRYPT_INVALID_ROUNDS; } LOAD32L(A, &pt[0]); LOAD32L(B, &pt[4]); A += skey->rc5.K[0]; B += skey->rc5.K[1]; K = skey->rc5.K + 2; if ((skey->rc5.rounds & 1) == 0) { for (r = 0; r < skey->rc5.rounds; r += 2) { A = ROL(A ^ B, B) + K[0]; B = ROL(B ^ A, A) + K[1]; A = ROL(A ^ B, B) + K[2]; B = ROL(B ^ A, A) + K[3]; K += 4; } } else { for (r = 0; r < skey->rc5.rounds; r++) { A = ROL(A ^ B, B) + K[0]; B = ROL(B ^ A, A) + K[1]; K += 2; } } STORE32L(A, &ct[0]); STORE32L(B, &ct[4]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_rc5_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(ulong32) * 2 + sizeof(int)); return err; } #endif /** Decrypts a block of text with LTC_RC5 @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 A, B; const ulong32 *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { return CRYPT_INVALID_ROUNDS; } LOAD32L(A, &ct[0]); LOAD32L(B, &ct[4]); K = skey->rc5.K + (skey->rc5.rounds << 1); if ((skey->rc5.rounds & 1) == 0) { K -= 2; for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) { B = ROR(B - K[3], A) ^ A; A = ROR(A - K[2], B) ^ B; B = ROR(B - K[1], A) ^ A; A = ROR(A - K[0], B) ^ B; K -= 4; } } else { for (r = skey->rc5.rounds - 1; r >= 0; r--) { B = ROR(B - K[1], A) ^ A; A = ROR(A - K[0], B) ^ B; K -= 2; } } A -= skey->rc5.K[0]; B -= skey->rc5.K[1]; STORE32L(A, &pt[0]); STORE32L(B, &pt[4]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_rc5_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(ulong32) * 2 + sizeof(int)); return err; } #endif /** Performs a self-test of the LTC_RC5 block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int rc5_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[16], pt[8], ct[8]; } tests[] = { { { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51, 0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 }, { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d }, { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 } }, { { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f, 0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 }, { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 }, { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 } }, { { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f, 0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf }, { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }, { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc } } }; unsigned char tmp[2][8]; int x, y, err; symmetric_key key; for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { /* setup key */ if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) { return err; } /* encrypt and decrypt */ rc5_ecb_encrypt(tests[x].pt, tmp[0], &key); rc5_ecb_decrypt(tmp[0], tmp[1], &key); /* compare */ if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC5 Encrypt", x) != 0 || compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC5 Decrypt", x) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void rc5_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int rc5_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 8) { return CRYPT_INVALID_KEYSIZE; } if (*keysize > 128) { *keysize = 128; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/rc6.c000066400000000000000000000221151464416617300225000ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file rc6.c LTC_RC6 code by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_RC6 const struct ltc_cipher_descriptor rc6_desc = { "rc6", 3, 8, 128, 16, 20, &rc6_setup, &rc6_ecb_encrypt, &rc6_ecb_decrypt, &rc6_test, &rc6_done, &rc6_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const ulong32 stab[44] = { 0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, 0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, 0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, 0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, 0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, 0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL }; /** Initialize the LTC_RC6 block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #else int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #endif { ulong32 L[64], S[50], A, B, i, j, v, s, l; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* test parameters */ if (num_rounds != 0 && num_rounds != 20) { return CRYPT_INVALID_ROUNDS; } /* key must be between 64 and 1024 bits */ if (keylen < 8 || keylen > 128) { return CRYPT_INVALID_KEYSIZE; } /* copy the key into the L array */ for (A = i = j = 0; i < (ulong32)keylen; ) { A = (A << 8) | ((ulong32)(key[i++] & 255)); if (!(i & 3)) { L[j++] = BSWAP(A); A = 0; } } /* handle odd sized keys */ if (keylen & 3) { A <<= (8 * (4 - (keylen&3))); L[j++] = BSWAP(A); } /* setup the S array */ XMEMCPY(S, stab, 44 * sizeof(stab[0])); /* mix buffer */ s = 3 * MAX(44, j); l = j; for (A = B = i = j = v = 0; v < s; v++) { A = S[i] = ROLc(S[i] + A + B, 3); B = L[j] = ROL(L[j] + A + B, (A+B)); if (++i == 44) { i = 0; } if (++j == l) { j = 0; } } /* copy to key */ for (i = 0; i < 44; i++) { skey->rc6.K[i] = S[i]; } return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int x; x = s_rc6_setup(key, keylen, num_rounds, skey); burn_stack(sizeof(ulong32) * 122); return x; } #endif /** Encrypts a block of text with LTC_RC6 @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled */ #ifdef LTC_CLEAN_STACK static int s_rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 a,b,c,d,t,u; const ulong32 *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]); b += skey->rc6.K[0]; d += skey->rc6.K[1]; #define RND(a,b,c,d) \ t = (b * (b + b + 1)); t = ROLc(t, 5); \ u = (d * (d + d + 1)); u = ROLc(u, 5); \ a = ROL(a^t,u) + K[0]; \ c = ROL(c^u,t) + K[1]; K += 2; K = skey->rc6.K + 2; for (r = 0; r < 20; r += 4) { RND(a,b,c,d); RND(b,c,d,a); RND(c,d,a,b); RND(d,a,b,c); } #undef RND a += skey->rc6.K[42]; c += skey->rc6.K[43]; STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_rc6_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(ulong32) * 6 + sizeof(int)); return err; } #endif /** Decrypts a block of text with LTC_RC6 @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled */ #ifdef LTC_CLEAN_STACK static int s_rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 a,b,c,d,t,u; const ulong32 *K; int r; LTC_ARGCHK(skey != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]); a -= skey->rc6.K[42]; c -= skey->rc6.K[43]; #define RND(a,b,c,d) \ t = (b * (b + b + 1)); t = ROLc(t, 5); \ u = (d * (d + d + 1)); u = ROLc(u, 5); \ c = ROR(c - K[1], t) ^ u; \ a = ROR(a - K[0], u) ^ t; K -= 2; K = skey->rc6.K + 40; for (r = 0; r < 20; r += 4) { RND(d,a,b,c); RND(c,d,a,b); RND(b,c,d,a); RND(a,b,c,d); } #undef RND b -= skey->rc6.K[0]; d -= skey->rc6.K[1]; STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_rc6_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(ulong32) * 6 + sizeof(int)); return err; } #endif /** Performs a self-test of the LTC_RC6 block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int rc6_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, { 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23, 0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 } }, { 24, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, { 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04, 0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 } }, { 32, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }, { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, { 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89, 0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 } } }; unsigned char tmp[2][16]; int x, y, err; symmetric_key key; for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { /* setup key */ if ((err = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { return err; } /* encrypt and decrypt */ rc6_ecb_encrypt(tests[x].pt, tmp[0], &key); rc6_ecb_decrypt(tmp[0], tmp[1], &key); /* compare */ if (compare_testvector(tmp[0], 16, tests[x].ct, 16, "RC6 Encrypt", x) || compare_testvector(tmp[1], 16, tests[x].pt, 16, "RC6 Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) rc6_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) rc6_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void rc6_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int rc6_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 8) { return CRYPT_INVALID_KEYSIZE; } if (*keysize > 128) { *keysize = 128; } return CRYPT_OK; } #endif /*LTC_RC6*/ optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/safer/000077500000000000000000000000001464416617300227415ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/safer/safer.c000066400000000000000000000365471464416617300242240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /******************************************************************************* * * FILE: safer.c * * LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption * Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128, * LTC_SAFER SK-64 and LTC_SAFER SK-128. * * AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch) * Signal and Information Processing Laboratory * Swiss Federal Institute of Technology * CH-8092 Zuerich, Switzerland * * DATE: September 9, 1995 * * CHANGE HISTORY: * *******************************************************************************/ #include "tomcrypt_private.h" #ifdef LTC_SAFER #define LTC_SAFER_TAB_C #include "safer_tab.c" const struct ltc_cipher_descriptor safer_k64_desc = { "safer-k64", 8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS, &safer_k64_setup, &safer_ecb_encrypt, &safer_ecb_decrypt, &safer_k64_test, &safer_done, &safer_64_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, safer_sk64_desc = { "safer-sk64", 9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS, &safer_sk64_setup, &safer_ecb_encrypt, &safer_ecb_decrypt, &safer_sk64_test, &safer_done, &safer_64_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, safer_k128_desc = { "safer-k128", 10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS, &safer_k128_setup, &safer_ecb_encrypt, &safer_ecb_decrypt, &safer_sk128_test, &safer_done, &safer_128_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, safer_sk128_desc = { "safer-sk128", 11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS, &safer_sk128_setup, &safer_ecb_encrypt, &safer_ecb_decrypt, &safer_sk128_test, &safer_done, &safer_128_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /******************* Constants ************************************************/ /* #define TAB_LEN 256 */ /******************* Assertions ***********************************************/ /******************* Macros ***************************************************/ #define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\ |(unsigned int)((x) & 0xFF) >> (8 - (n)))) #define EXP(x) safer_ebox[(x) & 0xFF] #define LOG(x) safer_lbox[(x) & 0xFF] #define PHT(x, y) { y += x; x += y; } #define IPHT(x, y) { x -= y; y -= x; } /******************* Types ****************************************************/ #ifdef LTC_CLEAN_STACK static void s_safer_expand_userkey(const unsigned char *userkey_1, const unsigned char *userkey_2, unsigned int nof_rounds, int strengthened, safer_key_t key) #else static void safer_expand_userkey(const unsigned char *userkey_1, const unsigned char *userkey_2, unsigned int nof_rounds, int strengthened, safer_key_t key) #endif { unsigned int i, j, k; unsigned char ka[LTC_SAFER_BLOCK_LEN + 1]; unsigned char kb[LTC_SAFER_BLOCK_LEN + 1]; if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds) { nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS; } *key++ = (unsigned char)nof_rounds; ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; k = 0; for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { ka[j] = ROL8(userkey_1[j], 5); ka[LTC_SAFER_BLOCK_LEN] ^= ka[j]; kb[j] = *key++ = userkey_2[j]; kb[LTC_SAFER_BLOCK_LEN] ^= kb[j]; } for (i = 1; i <= nof_rounds; i++) { for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) { ka[j] = ROL8(ka[j], 6); kb[j] = ROL8(kb[j], 6); } if (strengthened) { k = 2 * i - 1; while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } } for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { if (strengthened) { *key++ = (ka[k] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } } else { *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; } } if (strengthened) { k = 2 * i; while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } } for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { if (strengthened) { *key++ = (kb[k] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } } else { *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; } } } #ifdef LTC_CLEAN_STACK zeromem(ka, sizeof(ka)); zeromem(kb, sizeof(kb)); #endif } #ifdef LTC_CLEAN_STACK static void safer_expand_userkey(const unsigned char *userkey_1, const unsigned char *userkey_2, unsigned int nof_rounds, int strengthened, safer_key_t key) { s_safer_expand_userkey(userkey_1, userkey_2, nof_rounds, strengthened, key); burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2); } #endif int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { return CRYPT_INVALID_ROUNDS; } if (keylen != 8) { return CRYPT_INVALID_KEYSIZE; } safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); return CRYPT_OK; } int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { return CRYPT_INVALID_ROUNDS; } if (keylen != 8) { return CRYPT_INVALID_KEYSIZE; } safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); return CRYPT_OK; } int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { return CRYPT_INVALID_ROUNDS; } if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); return CRYPT_OK; } int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { return CRYPT_INVALID_ROUNDS; } if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0?num_rounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { unsigned char a, b, c, d, e, f, g, h, t; unsigned int round; const unsigned char *key; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); key = skey->safer.key; a = pt[0]; b = pt[1]; c = pt[2]; d = pt[3]; e = pt[4]; f = pt[5]; g = pt[6]; h = pt[7]; if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; while(round-- > 0) { a ^= *++key; b += *++key; c += *++key; d ^= *++key; e ^= *++key; f += *++key; g += *++key; h ^= *++key; a = EXP(a) + *++key; b = LOG(b) ^ *++key; c = LOG(c) ^ *++key; d = EXP(d) + *++key; e = EXP(e) + *++key; f = LOG(f) ^ *++key; g = LOG(g) ^ *++key; h = EXP(h) + *++key; PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h); PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h); PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h); t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; } a ^= *++key; b += *++key; c += *++key; d ^= *++key; e ^= *++key; f += *++key; g += *++key; h ^= *++key; ct[0] = a & 0xFF; ct[1] = b & 0xFF; ct[2] = c & 0xFF; ct[3] = d & 0xFF; ct[4] = e & 0xFF; ct[5] = f & 0xFF; ct[6] = g & 0xFF; ct[7] = h & 0xFF; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_safer_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); return err; } #endif #ifdef LTC_CLEAN_STACK static int s_safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { unsigned char a, b, c, d, e, f, g, h, t; unsigned int round; const unsigned char *key; LTC_ARGCHK(ct != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(skey != NULL); key = skey->safer.key; a = ct[0]; b = ct[1]; c = ct[2]; d = ct[3]; e = ct[4]; f = ct[5]; g = ct[6]; h = ct[7]; if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round); h ^= *key; g -= *--key; f -= *--key; e ^= *--key; d ^= *--key; c -= *--key; b -= *--key; a ^= *--key; while (round--) { t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h); IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h); IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h); h -= *--key; g ^= *--key; f ^= *--key; e -= *--key; d -= *--key; c ^= *--key; b ^= *--key; a -= *--key; h = LOG(h) ^ *--key; g = EXP(g) - *--key; f = EXP(f) - *--key; e = LOG(e) ^ *--key; d = LOG(d) ^ *--key; c = EXP(c) - *--key; b = EXP(b) - *--key; a = LOG(a) ^ *--key; } pt[0] = a & 0xFF; pt[1] = b & 0xFF; pt[2] = c & 0xFF; pt[3] = d & 0xFF; pt[4] = e & 0xFF; pt[5] = f & 0xFF; pt[6] = g & 0xFF; pt[7] = h & 0xFF; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_safer_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); return err; } #endif int safer_64_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 8) { return CRYPT_INVALID_KEYSIZE; } *keysize = 8; return CRYPT_OK; } int safer_128_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } *keysize = 16; return CRYPT_OK; } int safer_k64_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 }, k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 }; symmetric_key skey; unsigned char buf[2][8]; int err; /* test K64 */ if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) { return err; } safer_ecb_encrypt(k64_pt, buf[0], &skey); safer_ecb_decrypt(buf[0], buf[1], &skey); if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 || compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int safer_sk64_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 }; symmetric_key skey; unsigned char buf[2][8]; int err, y; /* test SK64 */ if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) { return err; } safer_ecb_encrypt(sk64_pt, buf[0], &skey); safer_ecb_decrypt(buf[0], buf[1], &skey); if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 || compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) buf[0][y] = 0; for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void safer_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } int safer_sk128_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0 }, sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 }; symmetric_key skey; unsigned char buf[2][8]; int err, y; /* test SK128 */ if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) { return err; } safer_ecb_encrypt(sk128_pt, buf[0], &skey); safer_ecb_decrypt(buf[0], buf[1], &skey); if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 || compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) buf[0][y] = 0; for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/safer/safer_tab.c000066400000000000000000000057641464416617300250470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file safer_tab.c Tables for LTC_SAFER block ciphers */ #ifdef LTC_SAFER_TAB_C /* This is the box defined by ebox[x] = 45^x mod 257. * Its assumed that the value "256" corresponds to zero. */ static const unsigned char safer_ebox[256] = { 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63, 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247, 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40 }; /* This is the inverse of ebox or the base 45 logarithm */ static const unsigned char safer_lbox[256] = { 128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248, 192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130, 112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37, 201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15, 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198, 175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84, 121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188, 189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217, 208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158, 210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42, 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219, 164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29, 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14, 122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104, 109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66, 184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48 }; #endif /* LTC_SAFER_TAB_C */ optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/safer/saferp.c000066400000000000000000000520661464416617300243760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file saferp.c LTC_SAFER+ Implementation by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_SAFERP #define LTC_SAFER_TAB_C #include "safer_tab.c" const struct ltc_cipher_descriptor saferp_desc = { "safer+", 4, 16, 32, 16, 8, &saferp_setup, &saferp_ecb_encrypt, &saferp_ecb_decrypt, &saferp_test, &saferp_done, &saferp_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* ROUND(b,i) * * This is one forward key application. Note the basic form is * key addition, substitution, key addition. The safer_ebox and safer_lbox * are the exponentiation box and logarithm boxes respectively. * The value of 'i' is the current round number which allows this * function to be unrolled massively. Most of LTC_SAFER+'s speed * comes from not having to compute indirect accesses into the * array of 16 bytes b[0..15] which is the block of data */ #define ROUND(b, i) do { \ b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \ b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \ b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \ b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \ b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \ b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \ b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \ b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \ b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \ b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \ b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \ b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \ b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \ b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \ b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \ b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; \ } while (0) /* This is one inverse key application */ #define iROUND(b, i) do { \ b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \ b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \ b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \ b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \ b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \ b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \ b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \ b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \ b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \ b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \ b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \ b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \ b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \ b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \ b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \ b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; \ } while (0) /* This is a forward single layer PHT transform. */ #define PHT(b) do { \ b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \ b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \ b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \ b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \ b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \ b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \ b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \ b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; \ } while (0) /* This is an inverse single layer PHT transform */ #define iPHT(b) do { \ b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \ b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \ b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \ b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \ b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \ b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \ b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \ b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \ } while (0) /* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */ #define SHUF(b, b2) do { \ b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \ b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \ b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \ b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; \ } while (0) /* This is the inverse shuffle. It takes from b and gives to b2 */ #define iSHUF(b, b2) do { \ b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \ b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \ b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \ b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; \ } while (0) /* The complete forward Linear Transform layer. * Note that alternating usage of b and b2. * Each round of LT starts in 'b' and ends in 'b2'. */ #define LT(b, b2) do { \ PHT(b); SHUF(b, b2); \ PHT(b2); SHUF(b2, b); \ PHT(b); SHUF(b, b2); \ PHT(b2); \ } while (0) /* This is the inverse linear transform layer. */ #define iLT(b, b2) do { \ iPHT(b); \ iSHUF(b, b2); iPHT(b2); \ iSHUF(b2, b); iPHT(b); \ iSHUF(b, b2); iPHT(b2); \ } while (0) #ifdef LTC_SMALL_CODE static void s_round(unsigned char *b, int i, const symmetric_key *skey) { ROUND(b, i); } static void s_iround(unsigned char *b, int i, const symmetric_key *skey) { iROUND(b, i); } static void s_lt(unsigned char *b, unsigned char *b2) { LT(b, b2); } static void s_ilt(unsigned char *b, unsigned char *b2) { iLT(b, b2); } #undef ROUND #define ROUND(b, i) s_round(b, i, skey) #undef iROUND #define iROUND(b, i) s_iround(b, i, skey) #undef LT #define LT(b, b2) s_lt(b, b2) #undef iLT #define iLT(b, b2) s_ilt(b, b2) #endif /* These are the 33, 128-bit bias words for the key schedule */ static const unsigned char safer_bias[33][16] = { { 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100}, { 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61}, { 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160}, { 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148}, { 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143}, { 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202}, { 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44}, { 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51}, { 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56}, { 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215}, { 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210}, { 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53}, { 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244}, { 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131}, { 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241}, { 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172}, { 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239}, { 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202}, { 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246}, { 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152}, { 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236}, { 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150}, { 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30}, { 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6}, { 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104}, { 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175}, { 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35}, { 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7}, { 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207}, { 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247}, { 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255}, { 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}}; /** Initialize the LTC_SAFER+ block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { unsigned x, y, z; unsigned char t[33]; static const int rounds[3] = { 8, 12, 16 }; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* check arguments */ if (keylen != 16 && keylen != 24 && keylen != 32) { return CRYPT_INVALID_KEYSIZE; } /* Is the number of rounds valid? Either use zero for default or * 8,12,16 rounds for 16,24,32 byte keys */ if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) { return CRYPT_INVALID_ROUNDS; } /* 128 bit key version */ if (keylen == 16) { /* copy key into t */ for (x = y = 0; x < 16; x++) { t[x] = key[x]; y ^= key[x]; } t[16] = y; /* make round keys */ for (x = 0; x < 16; x++) { skey->saferp.K[0][x] = t[x]; } /* make the 16 other keys as a transformation of the first key */ for (x = 1; x < 17; x++) { /* rotate 3 bits each */ for (y = 0; y < 17; y++) { t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; } /* select and add */ z = x; for (y = 0; y < 16; y++) { skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; if (++z == 17) { z = 0; } } } skey->saferp.rounds = 8; } else if (keylen == 24) { /* copy key into t */ for (x = y = 0; x < 24; x++) { t[x] = key[x]; y ^= key[x]; } t[24] = y; /* make round keys */ for (x = 0; x < 16; x++) { skey->saferp.K[0][x] = t[x]; } for (x = 1; x < 25; x++) { /* rotate 3 bits each */ for (y = 0; y < 25; y++) { t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; } /* select and add */ z = x; for (y = 0; y < 16; y++) { skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; if (++z == 25) { z = 0; } } } skey->saferp.rounds = 12; } else { /* copy key into t */ for (x = y = 0; x < 32; x++) { t[x] = key[x]; y ^= key[x]; } t[32] = y; /* make round keys */ for (x = 0; x < 16; x++) { skey->saferp.K[0][x] = t[x]; } for (x = 1; x < 33; x++) { /* rotate 3 bits each */ for (y = 0; y < 33; y++) { t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; } /* select and add */ z = x; for (y = 0; y < 16; y++) { skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; if (++z == 33) { z = 0; } } } skey->saferp.rounds = 16; } #ifdef LTC_CLEAN_STACK zeromem(t, sizeof(t)); #endif return CRYPT_OK; } /** Encrypts a block of text with LTC_SAFER+ @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { unsigned char b[16]; int x; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { return CRYPT_INVALID_ROUNDS; } /* do eight rounds */ for (x = 0; x < 16; x++) { b[x] = pt[x]; } ROUND(b, 0); LT(b, ct); ROUND(ct, 2); LT(ct, b); ROUND(b, 4); LT(b, ct); ROUND(ct, 6); LT(ct, b); ROUND(b, 8); LT(b, ct); ROUND(ct, 10); LT(ct, b); ROUND(b, 12); LT(b, ct); ROUND(ct, 14); LT(ct, b); /* 192-bit key? */ if (skey->saferp.rounds > 8) { ROUND(b, 16); LT(b, ct); ROUND(ct, 18); LT(ct, b); ROUND(b, 20); LT(b, ct); ROUND(ct, 22); LT(ct, b); } /* 256-bit key? */ if (skey->saferp.rounds > 12) { ROUND(b, 24); LT(b, ct); ROUND(ct, 26); LT(ct, b); ROUND(b, 28); LT(b, ct); ROUND(ct, 30); LT(ct, b); } ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255; ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255; ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255; ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255; ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255; ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255; ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255; ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255; ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; #ifdef LTC_CLEAN_STACK zeromem(b, sizeof(b)); #endif return CRYPT_OK; } /** Decrypts a block of text with LTC_SAFER+ @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { unsigned char b[16]; int x; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { return CRYPT_INVALID_ROUNDS; } /* do eight rounds */ b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255; b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255; b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255; b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255; b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255; b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255; b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255; b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255; b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; /* 256-bit key? */ if (skey->saferp.rounds > 12) { iLT(b, pt); iROUND(pt, 30); iLT(pt, b); iROUND(b, 28); iLT(b, pt); iROUND(pt, 26); iLT(pt, b); iROUND(b, 24); } /* 192-bit key? */ if (skey->saferp.rounds > 8) { iLT(b, pt); iROUND(pt, 22); iLT(pt, b); iROUND(b, 20); iLT(b, pt); iROUND(pt, 18); iLT(pt, b); iROUND(b, 16); } iLT(b, pt); iROUND(pt, 14); iLT(pt, b); iROUND(b, 12); iLT(b, pt); iROUND(pt,10); iLT(pt, b); iROUND(b, 8); iLT(b, pt); iROUND(pt,6); iLT(pt, b); iROUND(b, 4); iLT(b, pt); iROUND(pt,2); iLT(pt, b); iROUND(b, 0); for (x = 0; x < 16; x++) { pt[x] = b[x]; } #ifdef LTC_CLEAN_STACK zeromem(b, sizeof(b)); #endif return CRYPT_OK; } /** Performs a self-test of the LTC_SAFER+ block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int saferp_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 41, 35, 190, 132, 225, 108, 214, 174, 82, 144, 73, 241, 241, 187, 233, 235 }, { 179, 166, 219, 60, 135, 12, 62, 153, 36, 94, 13, 28, 6, 183, 71, 222 }, { 224, 31, 182, 10, 12, 255, 84, 70, 127, 13, 89, 249, 9, 57, 165, 220 } }, { 24, { 72, 211, 143, 117, 230, 217, 29, 42, 229, 192, 247, 43, 120, 129, 135, 68, 14, 95, 80, 0, 212, 97, 141, 190 }, { 123, 5, 21, 7, 59, 51, 130, 31, 24, 112, 146, 218, 100, 84, 206, 177 }, { 92, 136, 4, 63, 57, 95, 100, 0, 150, 130, 130, 16, 193, 111, 219, 133 } }, { 32, { 243, 168, 141, 254, 190, 242, 235, 113, 255, 160, 208, 59, 117, 6, 140, 126, 135, 120, 115, 77, 208, 190, 130, 190, 219, 194, 70, 65, 43, 140, 250, 48 }, { 127, 112, 240, 167, 84, 134, 50, 149, 170, 91, 104, 19, 11, 230, 252, 245 }, { 88, 11, 25, 36, 172, 229, 202, 213, 170, 65, 105, 153, 220, 104, 153, 138 } } }; unsigned char tmp[2][16]; symmetric_key skey; int err, i, y; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) { return err; } saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey); saferp_ecb_decrypt(tmp[0], tmp[1], &skey); /* compare */ if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Safer+ Encrypt", i) || compare_testvector(tmp[1], 16, tests[i].pt, 16, "Safer+ Decrypt", i)) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void saferp_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int saferp_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } if (*keysize < 24) { *keysize = 16; } else if (*keysize < 32) { *keysize = 24; } else { *keysize = 32; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/serpent.c000066400000000000000000000435471464416617300235020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* Based on serpent.cpp - originally written and placed in the public domain by Wei Dai https://github.com/weidai11/cryptopp/blob/master/serpent.cpp On 2017-10-16 wikipedia says: "The Serpent cipher algorithm is in the public domain and has not been patented." https://en.wikipedia.org/wiki/Serpent_(cipher) */ #include "tomcrypt_private.h" #ifdef LTC_SERPENT const struct ltc_cipher_descriptor serpent_desc = { "serpent", 25, /* cipher_ID */ 16, 32, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */ &serpent_setup, &serpent_ecb_encrypt, &serpent_ecb_decrypt, &serpent_test, &serpent_done, &serpent_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* linear transformation */ #define s_lt(i,a,b,c,d,e) { \ a = ROLc(a, 13); \ c = ROLc(c, 3); \ d = ROLc(d ^ c ^ (a << 3), 7); \ b = ROLc(b ^ a ^ c, 1); \ a = ROLc(a ^ b ^ d, 5); \ c = ROLc(c ^ d ^ (b << 7), 22); \ } /* inverse linear transformation */ #define s_ilt(i,a,b,c,d,e) { \ c = RORc(c, 22); \ a = RORc(a, 5); \ c ^= d ^ (b << 7); \ a ^= b ^ d; \ b = RORc(b, 1); \ d = RORc(d, 7) ^ c ^ (a << 3); \ b ^= a ^ c; \ c = RORc(c, 3); \ a = RORc(a, 13); \ } /* order of output from S-box functions */ #define s_beforeS0(f) f(0,a,b,c,d,e) #define s_afterS0(f) f(1,b,e,c,a,d) #define s_afterS1(f) f(2,c,b,a,e,d) #define s_afterS2(f) f(3,a,e,b,d,c) #define s_afterS3(f) f(4,e,b,d,c,a) #define s_afterS4(f) f(5,b,a,e,c,d) #define s_afterS5(f) f(6,a,c,b,e,d) #define s_afterS6(f) f(7,a,c,d,b,e) #define s_afterS7(f) f(8,d,e,b,a,c) /* order of output from inverse S-box functions */ #define s_beforeI7(f) f(8,a,b,c,d,e) #define s_afterI7(f) f(7,d,a,b,e,c) #define s_afterI6(f) f(6,a,b,c,e,d) #define s_afterI5(f) f(5,b,d,e,c,a) #define s_afterI4(f) f(4,b,c,e,a,d) #define s_afterI3(f) f(3,a,b,e,c,d) #define s_afterI2(f) f(2,b,d,e,c,a) #define s_afterI1(f) f(1,a,b,c,e,d) #define s_afterI0(f) f(0,a,d,b,e,c) /* The instruction sequences for the S-box functions * come from Dag Arne Osvik's paper "Speeding up Serpent". */ #define s_s0(i, r0, r1, r2, r3, r4) { \ r3 ^= r0; \ r4 = r1; \ r1 &= r3; \ r4 ^= r2; \ r1 ^= r0; \ r0 |= r3; \ r0 ^= r4; \ r4 ^= r3; \ r3 ^= r2; \ r2 |= r1; \ r2 ^= r4; \ r4 = ~r4; \ r4 |= r1; \ r1 ^= r3; \ r1 ^= r4; \ r3 |= r0; \ r1 ^= r3; \ r4 ^= r3; \ } #define s_i0(i, r0, r1, r2, r3, r4) { \ r2 = ~r2; \ r4 = r1; \ r1 |= r0; \ r4 = ~r4; \ r1 ^= r2; \ r2 |= r4; \ r1 ^= r3; \ r0 ^= r4; \ r2 ^= r0; \ r0 &= r3; \ r4 ^= r0; \ r0 |= r1; \ r0 ^= r2; \ r3 ^= r4; \ r2 ^= r1; \ r3 ^= r0; \ r3 ^= r1; \ r2 &= r3; \ r4 ^= r2; \ } #define s_s1(i, r0, r1, r2, r3, r4) { \ r0 = ~r0; \ r2 = ~r2; \ r4 = r0; \ r0 &= r1; \ r2 ^= r0; \ r0 |= r3; \ r3 ^= r2; \ r1 ^= r0; \ r0 ^= r4; \ r4 |= r1; \ r1 ^= r3; \ r2 |= r0; \ r2 &= r4; \ r0 ^= r1; \ r1 &= r2; \ r1 ^= r0; \ r0 &= r2; \ r0 ^= r4; \ } #define s_i1(i, r0, r1, r2, r3, r4) { \ r4 = r1; \ r1 ^= r3; \ r3 &= r1; \ r4 ^= r2; \ r3 ^= r0; \ r0 |= r1; \ r2 ^= r3; \ r0 ^= r4; \ r0 |= r2; \ r1 ^= r3; \ r0 ^= r1; \ r1 |= r3; \ r1 ^= r0; \ r4 = ~r4; \ r4 ^= r1; \ r1 |= r0; \ r1 ^= r0; \ r1 |= r4; \ r3 ^= r1; \ } #define s_s2(i, r0, r1, r2, r3, r4) { \ r4 = r0; \ r0 &= r2; \ r0 ^= r3; \ r2 ^= r1; \ r2 ^= r0; \ r3 |= r4; \ r3 ^= r1; \ r4 ^= r2; \ r1 = r3; \ r3 |= r4; \ r3 ^= r0; \ r0 &= r1; \ r4 ^= r0; \ r1 ^= r3; \ r1 ^= r4; \ r4 = ~r4; \ } #define s_i2(i, r0, r1, r2, r3, r4) { \ r2 ^= r3; \ r3 ^= r0; \ r4 = r3; \ r3 &= r2; \ r3 ^= r1; \ r1 |= r2; \ r1 ^= r4; \ r4 &= r3; \ r2 ^= r3; \ r4 &= r0; \ r4 ^= r2; \ r2 &= r1; \ r2 |= r0; \ r3 = ~r3; \ r2 ^= r3; \ r0 ^= r3; \ r0 &= r1; \ r3 ^= r4; \ r3 ^= r0; \ } #define s_s3(i, r0, r1, r2, r3, r4) { \ r4 = r0; \ r0 |= r3; \ r3 ^= r1; \ r1 &= r4; \ r4 ^= r2; \ r2 ^= r3; \ r3 &= r0; \ r4 |= r1; \ r3 ^= r4; \ r0 ^= r1; \ r4 &= r0; \ r1 ^= r3; \ r4 ^= r2; \ r1 |= r0; \ r1 ^= r2; \ r0 ^= r3; \ r2 = r1; \ r1 |= r3; \ r1 ^= r0; \ } #define s_i3(i, r0, r1, r2, r3, r4) { \ r4 = r2; \ r2 ^= r1; \ r1 &= r2; \ r1 ^= r0; \ r0 &= r4; \ r4 ^= r3; \ r3 |= r1; \ r3 ^= r2; \ r0 ^= r4; \ r2 ^= r0; \ r0 |= r3; \ r0 ^= r1; \ r4 ^= r2; \ r2 &= r3; \ r1 |= r3; \ r1 ^= r2; \ r4 ^= r0; \ r2 ^= r4; \ } #define s_s4(i, r0, r1, r2, r3, r4) { \ r1 ^= r3; \ r3 = ~r3; \ r2 ^= r3; \ r3 ^= r0; \ r4 = r1; \ r1 &= r3; \ r1 ^= r2; \ r4 ^= r3; \ r0 ^= r4; \ r2 &= r4; \ r2 ^= r0; \ r0 &= r1; \ r3 ^= r0; \ r4 |= r1; \ r4 ^= r0; \ r0 |= r3; \ r0 ^= r2; \ r2 &= r3; \ r0 = ~r0; \ r4 ^= r2; \ } #define s_i4(i, r0, r1, r2, r3, r4) { \ r4 = r2; \ r2 &= r3; \ r2 ^= r1; \ r1 |= r3; \ r1 &= r0; \ r4 ^= r2; \ r4 ^= r1; \ r1 &= r2; \ r0 = ~r0; \ r3 ^= r4; \ r1 ^= r3; \ r3 &= r0; \ r3 ^= r2; \ r0 ^= r1; \ r2 &= r0; \ r3 ^= r0; \ r2 ^= r4; \ r2 |= r3; \ r3 ^= r0; \ r2 ^= r1; \ } #define s_s5(i, r0, r1, r2, r3, r4) { \ r0 ^= r1; \ r1 ^= r3; \ r3 = ~r3; \ r4 = r1; \ r1 &= r0; \ r2 ^= r3; \ r1 ^= r2; \ r2 |= r4; \ r4 ^= r3; \ r3 &= r1; \ r3 ^= r0; \ r4 ^= r1; \ r4 ^= r2; \ r2 ^= r0; \ r0 &= r3; \ r2 = ~r2; \ r0 ^= r4; \ r4 |= r3; \ r2 ^= r4; \ } #define s_i5(i, r0, r1, r2, r3, r4) { \ r1 = ~r1; \ r4 = r3; \ r2 ^= r1; \ r3 |= r0; \ r3 ^= r2; \ r2 |= r1; \ r2 &= r0; \ r4 ^= r3; \ r2 ^= r4; \ r4 |= r0; \ r4 ^= r1; \ r1 &= r2; \ r1 ^= r3; \ r4 ^= r2; \ r3 &= r4; \ r4 ^= r1; \ r3 ^= r0; \ r3 ^= r4; \ r4 = ~r4; \ } #define s_s6(i, r0, r1, r2, r3, r4) { \ r2 = ~r2; \ r4 = r3; \ r3 &= r0; \ r0 ^= r4; \ r3 ^= r2; \ r2 |= r4; \ r1 ^= r3; \ r2 ^= r0; \ r0 |= r1; \ r2 ^= r1; \ r4 ^= r0; \ r0 |= r3; \ r0 ^= r2; \ r4 ^= r3; \ r4 ^= r0; \ r3 = ~r3; \ r2 &= r4; \ r2 ^= r3; \ } #define s_i6(i, r0, r1, r2, r3, r4) { \ r0 ^= r2; \ r4 = r2; \ r2 &= r0; \ r4 ^= r3; \ r2 = ~r2; \ r3 ^= r1; \ r2 ^= r3; \ r4 |= r0; \ r0 ^= r2; \ r3 ^= r4; \ r4 ^= r1; \ r1 &= r3; \ r1 ^= r0; \ r0 ^= r3; \ r0 |= r2; \ r3 ^= r1; \ r4 ^= r0; \ } #define s_s7(i, r0, r1, r2, r3, r4) { \ r4 = r2; \ r2 &= r1; \ r2 ^= r3; \ r3 &= r1; \ r4 ^= r2; \ r2 ^= r1; \ r1 ^= r0; \ r0 |= r4; \ r0 ^= r2; \ r3 ^= r1; \ r2 ^= r3; \ r3 &= r0; \ r3 ^= r4; \ r4 ^= r2; \ r2 &= r0; \ r4 = ~r4; \ r2 ^= r4; \ r4 &= r0; \ r1 ^= r3; \ r4 ^= r1; \ } #define s_i7(i, r0, r1, r2, r3, r4) { \ r4 = r2; \ r2 ^= r0; \ r0 &= r3; \ r2 = ~r2; \ r4 |= r3; \ r3 ^= r1; \ r1 |= r0; \ r0 ^= r2; \ r2 &= r4; \ r1 ^= r2; \ r2 ^= r0; \ r0 |= r2; \ r3 &= r4; \ r0 ^= r3; \ r4 ^= r1; \ r3 ^= r4; \ r4 |= r0; \ r3 ^= r2; \ r4 ^= r2; \ } /* key xor */ #define s_kx(r, a, b, c, d, e) { \ a ^= k[4 * r + 0]; \ b ^= k[4 * r + 1]; \ c ^= k[4 * r + 2]; \ d ^= k[4 * r + 3]; \ } #define s_lk(r, a, b, c, d, e) { \ a = k[(8-r)*4 + 0]; \ b = k[(8-r)*4 + 1]; \ c = k[(8-r)*4 + 2]; \ d = k[(8-r)*4 + 3]; \ } #define s_sk(r, a, b, c, d, e) { \ k[(8-r)*4 + 4] = a; \ k[(8-r)*4 + 5] = b; \ k[(8-r)*4 + 6] = c; \ k[(8-r)*4 + 7] = d; \ } static int s_setup_key(const unsigned char *key, int keylen, int rounds, ulong32 *k) { int i; ulong32 t; ulong32 k0[8] = { 0 }; /* zero-initialize */ ulong32 a, b, c, d, e; for (i = 0; i < 8 && i < keylen/4; ++i) { LOAD32L(k0[i], key + i * 4); } if (keylen < 32) { k0[keylen/4] |= (ulong32)1 << ((keylen%4)*8); } t = k0[7]; for (i = 0; i < 8; ++i) { k[i] = k0[i] = t = ROLc(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); } for (i = 8; i < 4*(rounds+1); ++i) { k[i] = t = ROLc(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); } k -= 20; for (i = 0; i < rounds/8; i++) { s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); s_afterS1(s_lk); s_afterS1(s_s2); s_afterS2(s_sk); s_afterS0(s_lk); s_afterS0(s_s1); s_afterS1(s_sk); s_beforeS0(s_lk); s_beforeS0(s_s0); s_afterS0(s_sk); k += 8*4; s_afterS6(s_lk); s_afterS6(s_s7); s_afterS7(s_sk); s_afterS5(s_lk); s_afterS5(s_s6); s_afterS6(s_sk); s_afterS4(s_lk); s_afterS4(s_s5); s_afterS5(s_sk); s_afterS3(s_lk); s_afterS3(s_s4); s_afterS4(s_sk); } s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); return CRYPT_OK; } static int s_enc_block(const unsigned char *in, unsigned char *out, const ulong32 *k) { ulong32 a, b, c, d, e; unsigned int i = 1; LOAD32L(a, in + 0); LOAD32L(b, in + 4); LOAD32L(c, in + 8); LOAD32L(d, in + 12); do { s_beforeS0(s_kx); s_beforeS0(s_s0); s_afterS0(s_lt); s_afterS0(s_kx); s_afterS0(s_s1); s_afterS1(s_lt); s_afterS1(s_kx); s_afterS1(s_s2); s_afterS2(s_lt); s_afterS2(s_kx); s_afterS2(s_s3); s_afterS3(s_lt); s_afterS3(s_kx); s_afterS3(s_s4); s_afterS4(s_lt); s_afterS4(s_kx); s_afterS4(s_s5); s_afterS5(s_lt); s_afterS5(s_kx); s_afterS5(s_s6); s_afterS6(s_lt); s_afterS6(s_kx); s_afterS6(s_s7); if (i == 4) break; ++i; c = b; b = e; e = d; d = a; a = e; k += 32; s_beforeS0(s_lt); } while (1); s_afterS7(s_kx); STORE32L(d, out + 0); STORE32L(e, out + 4); STORE32L(b, out + 8); STORE32L(a, out + 12); return CRYPT_OK; } static int s_dec_block(const unsigned char *in, unsigned char *out, const ulong32 *k) { ulong32 a, b, c, d, e; unsigned int i; LOAD32L(a, in + 0); LOAD32L(b, in + 4); LOAD32L(c, in + 8); LOAD32L(d, in + 12); e = 0; LTC_UNUSED_PARAM(e); /* avoid scan-build warning */ i = 4; k += 96; s_beforeI7(s_kx); goto start; do { c = b; b = d; d = e; k -= 32; s_beforeI7(s_ilt); start: s_beforeI7(s_i7); s_afterI7(s_kx); s_afterI7(s_ilt); s_afterI7(s_i6); s_afterI6(s_kx); s_afterI6(s_ilt); s_afterI6(s_i5); s_afterI5(s_kx); s_afterI5(s_ilt); s_afterI5(s_i4); s_afterI4(s_kx); s_afterI4(s_ilt); s_afterI4(s_i3); s_afterI3(s_kx); s_afterI3(s_ilt); s_afterI3(s_i2); s_afterI2(s_kx); s_afterI2(s_ilt); s_afterI2(s_i1); s_afterI1(s_kx); s_afterI1(s_ilt); s_afterI1(s_i0); s_afterI0(s_kx); } while (--i != 0); STORE32L(a, out + 0); STORE32L(d, out + 4); STORE32L(b, out + 8); STORE32L(e, out + 12); return CRYPT_OK; } int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (num_rounds != 0 && num_rounds != 32) return CRYPT_INVALID_ROUNDS; if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE; err = s_setup_key(key, keylen, 32, skey->serpent.k); #ifdef LTC_CLEAN_STACK burn_stack(sizeof(ulong32) * 14 + sizeof(int)); #endif return err; } int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_enc_block(pt, ct, skey->serpent.k); #ifdef LTC_CLEAN_STACK burn_stack(sizeof(ulong32) * 5 + sizeof(int)); #endif return err; } int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_dec_block(ct, pt, skey->serpent.k); #ifdef LTC_CLEAN_STACK burn_stack(sizeof(ulong32) * 5 + sizeof(int)); #endif return err; } void serpent_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } int serpent_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize >= 32) { *keysize = 32; } else if (*keysize >= 24) { *keysize = 24; } else if (*keysize >= 16) { *keysize = 16; } else return CRYPT_INVALID_KEYSIZE; return CRYPT_OK; } int serpent_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[32]; int keylen; unsigned char pt[16], ct[16]; } tests[] = { { /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 32, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0xA2,0x23,0xAA,0x12,0x88,0x46,0x3C,0x0E,0x2B,0xE3,0x8E,0xBD,0x82,0x56,0x16,0xC0} }, { /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 32, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0xEA,0xE1,0xD4,0x05,0x57,0x01,0x74,0xDF,0x7D,0xF2,0xF9,0x96,0x6D,0x50,0x91,0x59} }, { /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 32, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0x65,0xF3,0x76,0x84,0x47,0x1E,0x92,0x1D,0xC8,0xA3,0x0F,0x45,0xB4,0x3C,0x44,0x99} }, { /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 24, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0x9E,0x27,0x4E,0xAD,0x9B,0x73,0x7B,0xB2,0x1E,0xFC,0xFC,0xA5,0x48,0x60,0x26,0x89} }, { /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 24, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0x92,0xFC,0x8E,0x51,0x03,0x99,0xE4,0x6A,0x04,0x1B,0xF3,0x65,0xE7,0xB3,0xAE,0x82} }, { /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 24, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0x5E,0x0D,0xA3,0x86,0xC4,0x6A,0xD4,0x93,0xDE,0xA2,0x03,0xFD,0xC6,0xF5,0x7D,0x70} }, { /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 16, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0x26,0x4E,0x54,0x81,0xEF,0xF4,0x2A,0x46,0x06,0xAB,0xDA,0x06,0xC0,0xBF,0xDA,0x3D} }, { /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 16, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0x4A,0x23,0x1B,0x3B,0xC7,0x27,0x99,0x34,0x07,0xAC,0x6E,0xC8,0x35,0x0E,0x85,0x24} }, { /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* keylen */ 16, /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* ct */ {0xE0,0x32,0x69,0xF9,0xE9,0xFD,0x85,0x3C,0x7D,0x81,0x56,0xDF,0x14,0xB9,0x8D,0x56} } }; unsigned char buf[2][16]; symmetric_key key; int err, x; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { return err; } if ((err = serpent_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { return err; } if (compare_testvector(buf[0], 16, tests[x].ct, 16, "SERPENT Encrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } if ((err = serpent_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { return err; } if (compare_testvector(buf[1], 16, tests[x].pt, 16, "SERPENT Decrypt", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/skipjack.c000066400000000000000000000227101464416617300236060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file skipjack.c Skipjack Implementation by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_SKIPJACK const struct ltc_cipher_descriptor skipjack_desc = { "skipjack", 17, 10, 10, 8, 32, &skipjack_setup, &skipjack_ecb_encrypt, &skipjack_ecb_decrypt, &skipjack_test, &skipjack_done, &skipjack_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static const unsigned char sbox[256] = { 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 }; /* simple x + 1 (mod 10) in one step. */ static const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; /* simple x - 1 (mod 10) in one step */ static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /** Initialize the Skipjack block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int x; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); if (keylen != 10) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 32 && num_rounds != 0) { return CRYPT_INVALID_ROUNDS; } /* make sure the key is in range for platforms where CHAR_BIT != 8 */ for (x = 0; x < 10; x++) { skey->skipjack.key[x] = key[x] & 255; } return CRYPT_OK; } #define RULE_A \ tmp = g_func(w1, &kp, skey->skipjack.key); \ w1 = tmp ^ w4 ^ x; \ w4 = w3; w3 = w2; \ w2 = tmp; #define RULE_B \ tmp = g_func(w1, &kp, skey->skipjack.key); \ tmp1 = w4; w4 = w3; \ w3 = w1 ^ w2 ^ x; \ w1 = tmp1; w2 = tmp; #define RULE_A1 \ tmp = w1 ^ w2 ^ x; \ w1 = ig_func(w2, &kp, skey->skipjack.key); \ w2 = w3; w3 = w4; w4 = tmp; #define RULE_B1 \ tmp = ig_func(w2, &kp, skey->skipjack.key); \ w2 = tmp ^ w3 ^ x; \ w3 = w4; w4 = w1; w1 = tmp; static unsigned g_func(unsigned w, int *kp, const unsigned char *key) { unsigned char g1,g2; g1 = (w >> 8) & 255; g2 = w & 255; g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; return ((unsigned)g1<<8)|(unsigned)g2; } static unsigned ig_func(unsigned w, int *kp, const unsigned char *key) { unsigned char g1,g2; g1 = (w >> 8) & 255; g2 = w & 255; *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; return ((unsigned)g1<<8)|(unsigned)g2; } /** Encrypts a block of text with Skipjack @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { unsigned w1,w2,w3,w4,tmp,tmp1; int x, kp; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); /* load block */ w1 = ((unsigned)pt[0]<<8)|pt[1]; w2 = ((unsigned)pt[2]<<8)|pt[3]; w3 = ((unsigned)pt[4]<<8)|pt[5]; w4 = ((unsigned)pt[6]<<8)|pt[7]; /* 8 rounds of RULE A */ for (x = 1, kp = 0; x < 9; x++) { RULE_A; } /* 8 rounds of RULE B */ for (; x < 17; x++) { RULE_B; } /* 8 rounds of RULE A */ for (; x < 25; x++) { RULE_A; } /* 8 rounds of RULE B */ for (; x < 33; x++) { RULE_B; } /* store block */ ct[0] = (w1>>8)&255; ct[1] = w1&255; ct[2] = (w2>>8)&255; ct[3] = w2&255; ct[4] = (w3>>8)&255; ct[5] = w3&255; ct[6] = (w4>>8)&255; ct[7] = w4&255; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_skipjack_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2); return err; } #endif /** Decrypts a block of text with Skipjack @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { unsigned w1,w2,w3,w4,tmp; int x, kp; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); /* load block */ w1 = ((unsigned)ct[0]<<8)|ct[1]; w2 = ((unsigned)ct[2]<<8)|ct[3]; w3 = ((unsigned)ct[4]<<8)|ct[5]; w4 = ((unsigned)ct[6]<<8)|ct[7]; /* 8 rounds of RULE B^-1 Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8 */ for (x = 32, kp = 8; x > 24; x--) { RULE_B1; } /* 8 rounds of RULE A^-1 */ for (; x > 16; x--) { RULE_A1; } /* 8 rounds of RULE B^-1 */ for (; x > 8; x--) { RULE_B1; } /* 8 rounds of RULE A^-1 */ for (; x > 0; x--) { RULE_A1; } /* store block */ pt[0] = (w1>>8)&255; pt[1] = w1&255; pt[2] = (w2>>8)&255; pt[3] = w2&255; pt[4] = (w3>>8)&255; pt[5] = w3&255; pt[6] = (w4>>8)&255; pt[7] = w4&255; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_skipjack_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2); return err; } #endif /** Performs a self-test of the Skipjack block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int skipjack_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[10], pt[8], ct[8]; } tests[] = { { { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa }, { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 } } }; unsigned char buf[2][8]; int x, y, err; symmetric_key key; for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { /* setup key */ if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) { return err; } /* encrypt and decrypt */ skipjack_ecb_encrypt(tests[x].pt, buf[0], &key); skipjack_ecb_decrypt(buf[0], buf[1], &key); /* compare */ if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Skipjack Encrypt", x) != 0 || compare_testvector(buf[1], 8, tests[x].pt, 8, "Skipjack Decrypt", x) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) buf[0][y] = 0; for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key); for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key); for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void skipjack_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int skipjack_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 10) { return CRYPT_INVALID_KEYSIZE; } if (*keysize > 10) { *keysize = 10; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/tea.c000066400000000000000000000125741464416617300225670ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file tea.c Implementation of TEA, Steffen Jaeckel */ #include "tomcrypt_private.h" #ifdef LTC_TEA const struct ltc_cipher_descriptor tea_desc = { "tea", 26, 16, 16, 8, 32, &tea_setup, &tea_ecb_encrypt, &tea_ecb_decrypt, &tea_test, &tea_done, &tea_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; #define DELTA 0x9E3779B9uL #define SUM 0xC6EF3720uL int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* check arguments */ if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 0 && num_rounds != 32) { return CRYPT_INVALID_ROUNDS; } /* load key */ LOAD32H(skey->tea.k[0], key+0); LOAD32H(skey->tea.k[1], key+4); LOAD32H(skey->tea.k[2], key+8); LOAD32H(skey->tea.k[3], key+12); return CRYPT_OK; } /** Encrypts a block of text with TEA @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 y, z, sum = 0; const ulong32 delta = DELTA; int r; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(y, &pt[0]); LOAD32H(z, &pt[4]); for (r = 0; r < 32; r++) { sum += delta; y += ((z<<4) + skey->tea.k[0]) ^ (z + sum) ^ ((z>>5) + skey->tea.k[1]); z += ((y<<4) + skey->tea.k[2]) ^ (y + sum) ^ ((y>>5) + skey->tea.k[3]); } STORE32H(y, &ct[0]); STORE32H(z, &ct[4]); return CRYPT_OK; } /** Decrypts a block of text with TEA @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 v0, v1, sum = SUM; const ulong32 delta = DELTA; int r; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(v0, &ct[0]); LOAD32H(v1, &ct[4]); for (r = 0; r < 32; r++) { v1 -= ((v0 << 4) + skey->tea.k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + skey->tea.k[3]); v0 -= ((v1 << 4) + skey->tea.k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + skey->tea.k[1]); sum -= delta; } STORE32H(v0, &pt[0]); STORE32H(v1, &pt[4]); return CRYPT_OK; } /** Performs a self-test of the TEA block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int tea_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *key, *pt, *ct; } tests[] = { { "00000000000000000000000000000000", "0000000000000000", "41ea3a0a94baa940" }, { "32a1e65408b63bb9214105744ec5d2e2", "5ada1d89a9c3801a", "dd46249e28aa0b4b" }, { "60388adadf70a1f5d9cb4e097d2c6c57", "7a6adb4d69c53e0f", "44b71215cf25368a" }, { "4368d2249bd0321eb7c56d5b63a1bfac", "5a5d7ca2e186c41a", "91f56dff7281794f" }, { "5c60bff27072d01c4513c5eb8f3a38ab", "80d9c4adcf899635", "2bb0f1b3c023ed11" } }; unsigned char ptct[2][8]; unsigned char tmp[2][8]; unsigned char key[16]; unsigned long l; symmetric_key skey; size_t i; int err, y; for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { zeromem(&skey, sizeof(skey)); l = sizeof(key); if ((err = base16_decode(tests[i].key, XSTRLEN(tests[i].key), key, &l)) != CRYPT_OK) return err; l = sizeof(ptct[0]); if ((err = base16_decode(tests[i].pt, XSTRLEN(tests[i].pt), ptct[0], &l)) != CRYPT_OK) return err; l = sizeof(ptct[1]); if ((err = base16_decode(tests[i].ct, XSTRLEN(tests[i].ct), ptct[1], &l)) != CRYPT_OK) return err; if ((err = tea_setup(key, 16, 0, &skey)) != CRYPT_OK) { return err; } tea_ecb_encrypt(ptct[0], tmp[0], &skey); tea_ecb_decrypt(tmp[0], tmp[1], &skey); if (compare_testvector(tmp[0], 8, ptct[1], 8, "TEA Encrypt", i) != 0 || compare_testvector(tmp[1], 8, ptct[0], 8, "TEA Decrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) tea_ecb_encrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 1000; y++) tea_ecb_decrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } /* for */ return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void tea_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int tea_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } *keysize = 16; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/twofish/000077500000000000000000000000001464416617300233245ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/twofish/twofish.c000066400000000000000000000504061464416617300251600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file twofish.c Implementation of Twofish by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_TWOFISH /* first LTC_TWOFISH_ALL_TABLES must ensure LTC_TWOFISH_TABLES is defined */ #ifdef LTC_TWOFISH_ALL_TABLES #ifndef LTC_TWOFISH_TABLES #define LTC_TWOFISH_TABLES #endif #endif const struct ltc_cipher_descriptor twofish_desc = { "twofish", 7, 16, 32, 16, 16, &twofish_setup, &twofish_ecb_encrypt, &twofish_ecb_decrypt, &twofish_test, &twofish_done, &twofish_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* the two polynomials */ #ifndef LTC_TWOFISH_TABLES #define MDS_POLY 0x169 #endif #ifndef LTC_TWOFISH_ALL_TABLES #define RS_POLY 0x14D #endif /* The 4x8 RS Linear Transform */ static const unsigned char RS[4][8] = { { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E }, { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 }, { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 }, { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 } }; #ifdef LTC_TWOFISH_SMALL /* sbox usage orderings */ static const unsigned char qord[4][5] = { { 1, 1, 0, 0, 1 }, { 0, 1, 1, 0, 0 }, { 0, 0, 0, 1, 1 }, { 1, 0, 1, 1, 0 } }; #endif /* LTC_TWOFISH_SMALL */ #ifdef LTC_TWOFISH_TABLES #define LTC_TWOFISH_TAB_C #include "twofish_tab.c" #define sbox(i, x) ((ulong32)SBOX[i][(x)&255]) #else /* The Q-box tables */ static const unsigned char qbox[2][4][16] = { { { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 }, { 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD }, { 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 }, { 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA } }, { { 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 }, { 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 }, { 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF }, { 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA } } }; /* computes S_i[x] */ #ifdef LTC_CLEAN_STACK static ulong32 s_sbox(int i, ulong32 x) #else static ulong32 sbox(int i, ulong32 x) #endif { unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y; /* a0,b0 = [x/16], x mod 16 */ a0 = (unsigned char)((x>>4)&15); b0 = (unsigned char)((x)&15); /* a1 = a0 ^ b0 */ a1 = a0 ^ b0; /* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */ b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15; /* a2,b2 = t0[a1], t1[b1] */ a2 = qbox[i][0][(int)a1]; b2 = qbox[i][1][(int)b1]; /* a3 = a2 ^ b2 */ a3 = a2 ^ b2; /* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */ b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15; /* a4,b4 = t2[a3], t3[b3] */ a4 = qbox[i][2][(int)a3]; b4 = qbox[i][3][(int)b3]; /* y = 16b4 + a4 */ y = (b4 << 4) + a4; /* return result */ return (ulong32)y; } #ifdef LTC_CLEAN_STACK static ulong32 sbox(int i, ulong32 x) { ulong32 y; y = s_sbox(i, x); burn_stack(sizeof(unsigned char) * 11); return y; } #endif /* LTC_CLEAN_STACK */ #endif /* LTC_TWOFISH_TABLES */ /* computes ab mod p */ static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p) { ulong32 result, B[2], P[2]; P[1] = p; B[1] = b; result = P[0] = B[0] = 0; /* unrolled branchless GF multiplier */ result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); result ^= B[a&1]; return result; } /* computes [y0 y1 y2 y3] = MDS . [x0] */ #ifndef LTC_TWOFISH_TABLES static ulong32 mds_column_mult(unsigned char in, int col) { ulong32 x01, x5B, xEF; x01 = in; x5B = gf_mult(in, 0x5B, MDS_POLY); xEF = gf_mult(in, 0xEF, MDS_POLY); switch (col) { case 0: return (x01 << 0 ) | (x5B << 8 ) | (xEF << 16) | (xEF << 24); case 1: return (xEF << 0 ) | (xEF << 8 ) | (x5B << 16) | (x01 << 24); case 2: return (x5B << 0 ) | (xEF << 8 ) | (x01 << 16) | (xEF << 24); case 3: return (x5B << 0 ) | (x01 << 8 ) | (xEF << 16) | (x5B << 24); } /* avoid warnings, we'd never get here normally but just to calm compiler warnings... */ return 0; } #else /* !LTC_TWOFISH_TABLES */ #define mds_column_mult(x, i) mds_tab[i][x] #endif /* LTC_TWOFISH_TABLES */ /* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */ static void mds_mult(const unsigned char *in, unsigned char *out) { int x; ulong32 tmp; for (tmp = x = 0; x < 4; x++) { tmp ^= mds_column_mult(in[x], x); } STORE32L(tmp, out); } #ifdef LTC_TWOFISH_ALL_TABLES /* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ static void rs_mult(const unsigned char *in, unsigned char *out) { ulong32 tmp; tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^ rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]]; STORE32L(tmp, out); } #else /* !LTC_TWOFISH_ALL_TABLES */ /* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ static void rs_mult(const unsigned char *in, unsigned char *out) { int x, y; for (x = 0; x < 4; x++) { out[x] = 0; for (y = 0; y < 8; y++) { out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY); } } } #endif /* computes h(x) */ static void h_func(const unsigned char *in, unsigned char *out, const unsigned char *M, int k, int offset) { int x; unsigned char y[4]; for (x = 0; x < 4; x++) { y[x] = in[x]; } switch (k) { case 4: y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]); y[1] = (unsigned char)(sbox(0, (ulong32)y[1]) ^ M[4 * (6 + offset) + 1]); y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (6 + offset) + 2]); y[3] = (unsigned char)(sbox(1, (ulong32)y[3]) ^ M[4 * (6 + offset) + 3]); /* FALLTHROUGH */ case 3: y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (4 + offset) + 0]); y[1] = (unsigned char)(sbox(1, (ulong32)y[1]) ^ M[4 * (4 + offset) + 1]); y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (4 + offset) + 2]); y[3] = (unsigned char)(sbox(0, (ulong32)y[3]) ^ M[4 * (4 + offset) + 3]); /* FALLTHROUGH */ case 2: y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (ulong32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0])); y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (ulong32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1])); y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (ulong32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2])); y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (ulong32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3])); /* FALLTHROUGH */ } mds_mult(y, out); } #ifndef LTC_TWOFISH_SMALL /* for GCC we don't use pointer aliases */ #if defined(__GNUC__) #define S1 skey->twofish.S[0] #define S2 skey->twofish.S[1] #define S3 skey->twofish.S[2] #define S4 skey->twofish.S[3] #endif /* the G function */ #define g_func(x, dum) (S1[LTC_BYTE(x,0)] ^ S2[LTC_BYTE(x,1)] ^ S3[LTC_BYTE(x,2)] ^ S4[LTC_BYTE(x,3)]) #define g1_func(x, dum) (S2[LTC_BYTE(x,0)] ^ S3[LTC_BYTE(x,1)] ^ S4[LTC_BYTE(x,2)] ^ S1[LTC_BYTE(x,3)]) #else #ifdef LTC_CLEAN_STACK static ulong32 s_g_func(ulong32 x, const symmetric_key *key) #else static ulong32 g_func(ulong32 x, const symmetric_key *key) #endif { unsigned char g, i, y, z; ulong32 res; res = 0; for (y = 0; y < 4; y++) { z = key->twofish.start; /* do unkeyed substitution */ g = sbox(qord[y][z++], (x >> (8*y)) & 255); /* first subkey */ i = 0; /* do key mixing+sbox until z==5 */ while (z != 5) { g = g ^ key->twofish.S[4*i++ + y]; g = sbox(qord[y][z++], g); } /* multiply g by a column of the MDS */ res ^= mds_column_mult(g, y); } return res; } #define g1_func(x, key) g_func(ROLc(x, 8), key) #ifdef LTC_CLEAN_STACK static ulong32 g_func(ulong32 x, const symmetric_key *key) { ulong32 y; y = s_g_func(x, key); burn_stack(sizeof(unsigned char) * 4 + sizeof(ulong32)); return y; } #endif /* LTC_CLEAN_STACK */ #endif /* LTC_TWOFISH_SMALL */ /** Initialize the Twofish block cipher @param key The symmetric key you wish to pass @param keylen The key length in bytes @param num_rounds The number of rounds desired (0 for default) @param skey The key in as scheduled by this function. @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #else int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) #endif { #ifndef LTC_TWOFISH_SMALL unsigned char S[4*4], tmpx0, tmpx1; #endif int k, x, y; unsigned char tmp[4], tmp2[4], M[8*4]; ulong32 A, B; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* invalid arguments? */ if (num_rounds != 16 && num_rounds != 0) { return CRYPT_INVALID_ROUNDS; } if (keylen != 16 && keylen != 24 && keylen != 32) { return CRYPT_INVALID_KEYSIZE; } /* k = keysize/64 [but since our keysize is in bytes...] */ k = keylen / 8; /* copy the key into M */ for (x = 0; x < keylen; x++) { M[x] = key[x] & 255; } /* create the S[..] words */ #ifndef LTC_TWOFISH_SMALL for (x = 0; x < k; x++) { rs_mult(M+(x*8), S+(x*4)); } #else for (x = 0; x < k; x++) { rs_mult(M+(x*8), skey->twofish.S+(x*4)); } #endif /* make subkeys */ for (x = 0; x < 20; x++) { /* A = h(p * 2x, Me) */ for (y = 0; y < 4; y++) { tmp[y] = x+x; } h_func(tmp, tmp2, M, k, 0); LOAD32L(A, tmp2); /* B = ROL(h(p * (2x + 1), Mo), 8) */ for (y = 0; y < 4; y++) { tmp[y] = (unsigned char)(x+x+1); } h_func(tmp, tmp2, M, k, 1); LOAD32L(B, tmp2); B = ROLc(B, 8); /* K[2i] = A + B */ skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL; /* K[2i+1] = (A + 2B) <<< 9 */ skey->twofish.K[x+x+1] = ROLc(B + B + A, 9); } #ifndef LTC_TWOFISH_SMALL /* make the sboxes (large ram variant) */ if (k == 2) { for (x = 0; x < 256; x++) { tmpx0 = (unsigned char)sbox(0, x); tmpx1 = (unsigned char)sbox(1, x); skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0); skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1); skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2); skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3); } } else if (k == 3) { for (x = 0; x < 256; x++) { tmpx0 = (unsigned char)sbox(0, x); tmpx1 = (unsigned char)sbox(1, x); skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0); skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1); skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2); skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3); } } else { for (x = 0; x < 256; x++) { tmpx0 = (unsigned char)sbox(0, x); tmpx1 = (unsigned char)sbox(1, x); skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0); skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1); skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2); skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3); } } #else /* where to start in the sbox layers */ /* small ram variant */ switch (k) { case 4 : skey->twofish.start = 0; break; case 3 : skey->twofish.start = 1; break; default: skey->twofish.start = 2; break; } #endif return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int x; x = s_twofish_setup(key, keylen, num_rounds, skey); burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(ulong32) * 2); return x; } #endif /** Encrypts a block of text with Twofish @param pt The input plaintext (16 bytes) @param ct The output ciphertext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #else int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) #endif { ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; const ulong32 *k; int r; #if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) const ulong32 *S1, *S2, *S3, *S4; #endif LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); #if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) S1 = skey->twofish.S[0]; S2 = skey->twofish.S[1]; S3 = skey->twofish.S[2]; S4 = skey->twofish.S[3]; #endif LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]); LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]); a ^= skey->twofish.K[0]; b ^= skey->twofish.K[1]; c ^= skey->twofish.K[2]; d ^= skey->twofish.K[3]; k = skey->twofish.K + 8; for (r = 8; r != 0; --r) { t2 = g1_func(b, skey); t1 = g_func(a, skey) + t2; c = RORc(c ^ (t1 + k[0]), 1); d = ROLc(d, 1) ^ (t2 + t1 + k[1]); t2 = g1_func(d, skey); t1 = g_func(c, skey) + t2; a = RORc(a ^ (t1 + k[2]), 1); b = ROLc(b, 1) ^ (t2 + t1 + k[3]); k += 4; } /* output with "undo last swap" */ ta = c ^ skey->twofish.K[4]; tb = d ^ skey->twofish.K[5]; tc = a ^ skey->twofish.K[6]; td = b ^ skey->twofish.K[7]; /* store output */ STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]); STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { int err = s_twofish_ecb_encrypt(pt, ct, skey); burn_stack(sizeof(ulong32) * 10 + sizeof(int)); return err; } #endif /** Decrypts a block of text with Twofish @param ct The input ciphertext (16 bytes) @param pt The output plaintext (16 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ #ifdef LTC_CLEAN_STACK static int s_twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #else int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) #endif { ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; const ulong32 *k; int r; #if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) const ulong32 *S1, *S2, *S3, *S4; #endif LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); #if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) S1 = skey->twofish.S[0]; S2 = skey->twofish.S[1]; S3 = skey->twofish.S[2]; S4 = skey->twofish.S[3]; #endif /* load input */ LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]); LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]); /* undo undo final swap */ a = tc ^ skey->twofish.K[6]; b = td ^ skey->twofish.K[7]; c = ta ^ skey->twofish.K[4]; d = tb ^ skey->twofish.K[5]; k = skey->twofish.K + 36; for (r = 8; r != 0; --r) { t2 = g1_func(d, skey); t1 = g_func(c, skey) + t2; a = ROLc(a, 1) ^ (t1 + k[2]); b = RORc(b ^ (t2 + t1 + k[3]), 1); t2 = g1_func(b, skey); t1 = g_func(a, skey) + t2; c = ROLc(c, 1) ^ (t1 + k[0]); d = RORc(d ^ (t2 + t1 + k[1]), 1); k -= 4; } /* pre-white */ a ^= skey->twofish.K[0]; b ^= skey->twofish.K[1]; c ^= skey->twofish.K[2]; d ^= skey->twofish.K[3]; /* store */ STORE32L(a, &pt[0]); STORE32L(b, &pt[4]); STORE32L(c, &pt[8]); STORE32L(d, &pt[12]); return CRYPT_OK; } #ifdef LTC_CLEAN_STACK int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { int err = s_twofish_ecb_decrypt(ct, pt, skey); burn_stack(sizeof(ulong32) * 10 + sizeof(int)); return err; } #endif /** Performs a self-test of the Twofish block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int twofish_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; } tests[] = { { 16, { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }, { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }, { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 } }, { 24, { 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 }, { 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 }, { 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 } }, { 32, { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }, { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }, { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA } } }; symmetric_key key; unsigned char tmp[2][16]; int err, i, y; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { return err; } twofish_ecb_encrypt(tests[i].pt, tmp[0], &key); twofish_ecb_decrypt(tmp[0], tmp[1], &key); if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Twofish Encrypt", i) != 0 || compare_testvector(tmp[1], 16, tests[i].pt, 16, "Twofish Decrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 16; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key); for (y = 0; y < 1000; y++) twofish_ecb_decrypt(tmp[0], tmp[0], &key); for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void twofish_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int twofish_keysize(int *keysize) { LTC_ARGCHK(keysize); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } if (*keysize < 24) { *keysize = 16; return CRYPT_OK; } if (*keysize < 32) { *keysize = 24; return CRYPT_OK; } *keysize = 32; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/twofish/twofish_tab.c000066400000000000000000001336501464416617300260110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file twofish_tab.c Twofish tables, Tom St Denis */ #ifdef LTC_TWOFISH_TABLES #ifdef LTC_TWOFISH_TAB_C /* pre generated 8x8 tables from the four 4x4s */ static const unsigned char SBOX[2][256] = { { 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d, 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0}, { 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91} }; /* the 4x4 MDS in a nicer format */ static const ulong32 mds_tab[4][256] = { { 0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL, 0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL, 0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL, 0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL, 0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL, 0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL, 0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL, 0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL, 0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL, 0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL, 0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL, 0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL, 0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL, 0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL, 0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL, 0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL, 0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL, 0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL, 0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL, 0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL, 0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL, 0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL, 0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL, 0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL, 0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL, 0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL, 0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL, 0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL, 0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL, 0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL, 0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL, 0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL }, { 0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL, 0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL, 0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL, 0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL, 0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL, 0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL, 0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL, 0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL, 0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL, 0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL, 0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL, 0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL, 0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL, 0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL, 0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL, 0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL, 0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL, 0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL, 0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL, 0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL, 0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL, 0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL, 0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL, 0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL, 0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL, 0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL, 0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL, 0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL, 0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL, 0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL, 0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL, 0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL }, { 0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL, 0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL, 0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL, 0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL, 0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL, 0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL, 0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL, 0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL, 0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL, 0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL, 0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL, 0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL, 0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL, 0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL, 0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL, 0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL, 0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL, 0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL, 0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL, 0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL, 0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL, 0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL, 0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL, 0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL, 0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL, 0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL, 0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL, 0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL, 0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL, 0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL, 0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL, 0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL }, { 0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL, 0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL, 0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL, 0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL, 0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL, 0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL, 0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL, 0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL, 0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL, 0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL, 0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL, 0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL, 0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL, 0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL, 0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL, 0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL, 0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL, 0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL, 0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL, 0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL, 0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL, 0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL, 0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL, 0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL, 0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL, 0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL, 0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL, 0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL, 0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL, 0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL, 0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL, 0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL }}; #ifdef LTC_TWOFISH_ALL_TABLES /* the 4x8 RS transform */ static const ulong32 rs_tab0[256] = { 0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU, 0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU, 0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU, 0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU, 0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU, 0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU, 0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU, 0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU, 0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU, 0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU, 0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU, 0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU, 0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU, 0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU, 0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU, 0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU, 0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU, 0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU, 0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU, 0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU, 0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU, 0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU, 0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU, 0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU, 0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU, 0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU, 0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU, 0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU, 0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU, 0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU, 0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU, 0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU }; static const ulong32 rs_tab1[256] = { 0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU, 0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU, 0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU, 0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU, 0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU, 0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU, 0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU, 0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU, 0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU, 0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU, 0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU, 0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU, 0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU, 0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU, 0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU, 0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU, 0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU, 0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU, 0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU, 0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU, 0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU, 0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU, 0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU, 0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU, 0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU, 0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU, 0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU, 0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU, 0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU, 0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU, 0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU, 0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU }; static const ulong32 rs_tab2[256] = { 0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU, 0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU, 0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU, 0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU, 0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU, 0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU, 0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU, 0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU, 0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU, 0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU, 0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU, 0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU, 0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU, 0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU, 0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU, 0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU, 0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU, 0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU, 0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU, 0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU, 0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU, 0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU, 0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU, 0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU, 0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU, 0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU, 0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU, 0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU, 0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU, 0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU, 0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU, 0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU }; static const ulong32 rs_tab3[256] = { 0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU, 0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU, 0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU, 0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU, 0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU, 0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU, 0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU, 0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU, 0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU, 0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU, 0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU, 0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU, 0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU, 0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU, 0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU, 0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU, 0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU, 0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU, 0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU, 0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU, 0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU, 0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU, 0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU, 0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU, 0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU, 0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU, 0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU, 0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU, 0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU, 0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU, 0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU, 0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU }; static const ulong32 rs_tab4[256] = { 0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU, 0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU, 0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU, 0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU, 0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU, 0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU, 0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU, 0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU, 0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU, 0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU, 0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU, 0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU, 0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU, 0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU, 0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU, 0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU, 0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU, 0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU, 0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU, 0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU, 0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU, 0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU, 0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU, 0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU, 0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU, 0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU, 0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU, 0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU, 0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU, 0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU, 0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU, 0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU }; static const ulong32 rs_tab5[256] = { 0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU, 0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU, 0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU, 0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU, 0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU, 0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU, 0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU, 0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU, 0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU, 0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU, 0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU, 0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU, 0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU, 0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU, 0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU, 0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU, 0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU, 0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU, 0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU, 0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU, 0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU, 0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU, 0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU, 0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU, 0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU, 0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU, 0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU, 0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU, 0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU, 0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU, 0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU, 0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU }; static const ulong32 rs_tab6[256] = { 0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU, 0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU, 0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU, 0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU, 0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU, 0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU, 0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU, 0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU, 0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU, 0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU, 0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU, 0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU, 0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU, 0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU, 0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU, 0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU, 0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU, 0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU, 0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU, 0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU, 0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU, 0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU, 0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU, 0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU, 0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU, 0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU, 0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU, 0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU, 0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU, 0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU, 0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU, 0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU }; static const ulong32 rs_tab7[256] = { 0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU, 0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU, 0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU, 0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU, 0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU, 0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU, 0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU, 0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU, 0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU, 0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU, 0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU, 0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU, 0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU, 0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU, 0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU, 0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU, 0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU, 0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU, 0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU, 0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU, 0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU, 0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU, 0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU, 0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU, 0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU, 0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU, 0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU, 0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU, 0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU, 0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU, 0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU, 0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU }; #endif /* LTC_TWOFISH_ALL_TABLES */ #endif /* LTC_TWOFISH_TAB_C */ #endif optee_os-4.3.0/core/lib/libtomcrypt/src/ciphers/xtea.c000066400000000000000000000175571464416617300227650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file xtea.c Implementation of eXtended TEA, Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_XTEA const struct ltc_cipher_descriptor xtea_desc = { "xtea", 1, 16, 16, 8, 32, &xtea_setup, &xtea_ecb_encrypt, &xtea_ecb_decrypt, &xtea_test, &xtea_done, &xtea_keysize, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { ulong32 x, sum, K[4]; LTC_ARGCHK(key != NULL); LTC_ARGCHK(skey != NULL); /* check arguments */ if (keylen != 16) { return CRYPT_INVALID_KEYSIZE; } if (num_rounds != 0 && num_rounds != 32) { return CRYPT_INVALID_ROUNDS; } /* load key */ LOAD32H(K[0], key+0); LOAD32H(K[1], key+4); LOAD32H(K[2], key+8); LOAD32H(K[3], key+12); for (x = sum = 0; x < 32; x++) { skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL; sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL; skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL; } #ifdef LTC_CLEAN_STACK zeromem(&K, sizeof(K)); #endif return CRYPT_OK; } /** Encrypts a block of text with LTC_XTEA @param pt The input plaintext (8 bytes) @param ct The output ciphertext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) { ulong32 y, z; int r; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(y, &pt[0]); LOAD32H(z, &pt[4]); for (r = 0; r < 32; r += 4) { y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL; z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL; y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL; z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL; y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL; z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL; } STORE32H(y, &ct[0]); STORE32H(z, &ct[4]); return CRYPT_OK; } /** Decrypts a block of text with LTC_XTEA @param ct The input ciphertext (8 bytes) @param pt The output plaintext (8 bytes) @param skey The key as scheduled @return CRYPT_OK if successful */ int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) { ulong32 y, z; int r; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(skey != NULL); LOAD32H(y, &ct[0]); LOAD32H(z, &ct[4]); for (r = 31; r >= 0; r -= 4) { z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL; y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL; z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL; y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL; z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL; y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL; } STORE32H(y, &pt[0]); STORE32H(z, &pt[4]); return CRYPT_OK; } /** Performs a self-test of the LTC_XTEA block cipher @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled */ int xtea_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[16], pt[8], ct[8]; } tests[] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xde, 0xe9, 0xd4, 0xd8, 0xf7, 0x13, 0x1e, 0xd9 } }, { { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xa5, 0x97, 0xab, 0x41, 0x76, 0x01, 0x4d, 0x72 } }, { { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06 }, { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 }, { 0xb1, 0xfd, 0x5d, 0xa9, 0xcc, 0x6d, 0xc9, 0xdc } }, { { 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, { 0x70, 0x4b, 0x31, 0x34, 0x47, 0x44, 0xdf, 0xab } }, { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 } }, { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 } }, { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d } }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }, { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } } }; unsigned char tmp[2][8]; symmetric_key skey; int i, err, y; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { zeromem(&skey, sizeof(skey)); if ((err = xtea_setup(tests[i].key, 16, 0, &skey)) != CRYPT_OK) { return err; } xtea_ecb_encrypt(tests[i].pt, tmp[0], &skey); xtea_ecb_decrypt(tmp[0], tmp[1], &skey); if (compare_testvector(tmp[0], 8, tests[i].ct, 8, "XTEA Encrypt", i) != 0 || compare_testvector(tmp[1], 8, tests[i].pt, 8, "XTEA Decrypt", i) != 0) { return CRYPT_FAIL_TESTVECTOR; } /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ for (y = 0; y < 8; y++) tmp[0][y] = 0; for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey); for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; } /* for */ return CRYPT_OK; #endif } /** Terminate the context @param skey The scheduled key */ void xtea_done(symmetric_key *skey) { LTC_UNUSED_PARAM(skey); } /** Gets suitable key size @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. @return CRYPT_OK if the input key size is acceptable. */ int xtea_keysize(int *keysize) { LTC_ARGCHK(keysize != NULL); if (*keysize < 16) { return CRYPT_INVALID_KEYSIZE; } *keysize = 16; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/000077500000000000000000000000001464416617300216335ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/000077500000000000000000000000001464416617300223755ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_aad.c000066400000000000000000000025251464416617300247240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CCM_MODE /** Add AAD to the CCM state @param ccm The CCM state @param adata The additional authentication data to add to the CCM state @param adatalen The length of the AAD data. @return CRYPT_OK on success */ int ccm_add_aad(ccm_state *ccm, const unsigned char *adata, unsigned long adatalen) { unsigned long y; int err; LTC_ARGCHK(ccm != NULL); LTC_ARGCHK(adata != NULL); if (ccm->aadlen < ccm->current_aadlen + adatalen) { return CRYPT_INVALID_ARG; } ccm->current_aadlen += adatalen; /* now add the data */ for (y = 0; y < adatalen; y++) { if (ccm->x == 16) { /* full block so let's encrypt it */ if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { return err; } ccm->x = 0; } ccm->PAD[ccm->x++] ^= adata[y]; } /* remainder? */ if (ccm->aadlen == ccm->current_aadlen) { if (ccm->x != 0) { if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { return err; } } ccm->x = 0; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c000066400000000000000000000051451464416617300253020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CCM_MODE /** Add nonce data to the CCM state @param ccm The CCM state @param nonce The nonce data to add @param noncelen The length of the nonce @return CRYPT_OK on success */ int ccm_add_nonce(ccm_state *ccm, const unsigned char *nonce, unsigned long noncelen) { unsigned long x, y, len; int err; LTC_ARGCHK(ccm != NULL); LTC_ARGCHK(nonce != NULL); /* increase L to match the nonce len */ ccm->noncelen = (noncelen > 13) ? 13 : noncelen; if ((15 - ccm->noncelen) > ccm->L) { ccm->L = 15 - ccm->noncelen; } if (ccm->L > 8) { return CRYPT_INVALID_ARG; } /* decrease noncelen to match L */ if ((ccm->noncelen + ccm->L) > 15) { ccm->noncelen = 15 - ccm->L; } /* form B_0 == flags | Nonce N | l(m) */ x = 0; ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) | (((ccm->taglen - 2)>>1)<<3) | (ccm->L-1)); /* nonce */ for (y = 0; y < 15 - ccm->L; y++) { ccm->PAD[x++] = nonce[y]; } /* store len */ len = ccm->ptlen; /* shift len so the upper bytes of len are the contents of the length */ for (y = ccm->L; y < 4; y++) { len <<= 8; } /* store l(m) (only store 32-bits) */ for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) { ccm->PAD[x++] = 0; } for (; y < ccm->L; y++) { ccm->PAD[x++] = (unsigned char)((len >> 24) & 255); len <<= 8; } /* encrypt PAD */ if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { return err; } /* handle header */ ccm->x = 0; if (ccm->aadlen > 0) { /* store length */ if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) { ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; } else { ccm->PAD[ccm->x++] ^= 0xFF; ccm->PAD[ccm->x++] ^= 0xFE; ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255; ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255; ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; } } /* setup the ctr counter */ x = 0; /* flags */ ccm->ctr[x++] = (unsigned char)ccm->L-1; /* nonce */ for (y = 0; y < (16 - (ccm->L+1)); ++y) { ccm->ctr[x++] = nonce[y]; } /* offset */ while (x < 16) { ccm->ctr[x++] = 0; } ccm->CTRlen = 16; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_done.c000066400000000000000000000024701464416617300243130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CCM_MODE /** Terminate a CCM stream @param ccm The CCM state @param tag [out] The destination for the MAC tag @param taglen [in/out] The length of the MAC tag @return CRYPT_OK on success */ int ccm_done(ccm_state *ccm, unsigned char *tag, unsigned long *taglen) { unsigned long x, y; int err; LTC_ARGCHK(ccm != NULL); /* Check all data have been processed */ if (ccm->ptlen != ccm->current_ptlen) { return CRYPT_ERROR; } LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); if (ccm->x != 0) { if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { return err; } } /* setup CTR for the TAG (zero the count) */ for (y = 15; y > 15 - ccm->L; y--) { ccm->ctr[y] = 0x00; } if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { return err; } cipher_descriptor[ccm->cipher]->done(&ccm->K); /* store the TAG */ for (x = 0; x < 16 && x < *taglen; x++) { tag[x] = ccm->PAD[x] ^ ccm->CTRPAD[x]; } *taglen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_init.c000066400000000000000000000030651464416617300243320ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CCM_MODE /** Initialize a CCM state @param ccm The CCM state to initialize @param cipher The index of the cipher to use @param key The secret key @param keylen The length of the secret key @param ptlen The length of the plain/cipher text that will be processed @param taglen The max length of the MAC tag @param aadlen The length of the AAD @return CRYPT_OK on success */ int ccm_init(ccm_state *ccm, int cipher, const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen) { int err; LTC_ARGCHK(ccm != NULL); LTC_ARGCHK(key != NULL); XMEMSET(ccm, 0, sizeof(ccm_state)); /* check cipher input */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher]->block_length != 16) { return CRYPT_INVALID_CIPHER; } /* make sure the taglen is valid */ if (taglen < 4 || taglen > 16 || (taglen % 2) == 1 || aadlen < 0 || ptlen < 0) { return CRYPT_INVALID_ARG; } ccm->taglen = taglen; /* schedule key */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &ccm->K)) != CRYPT_OK) { return err; } ccm->cipher = cipher; /* let's get the L value */ ccm->ptlen = ptlen; ccm->L = 0; while (ptlen) { ++ccm->L; ptlen >>= 8; } if (ccm->L <= 1) { ccm->L = 2; } ccm->aadlen = aadlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c000066400000000000000000000245501464416617300247010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ccm_memory.c CCM support, process a block of memory, Tom St Denis */ #ifdef LTC_CCM_MODE /** CCM encrypt/decrypt and produce an authentication tag *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction' @param cipher The index of the cipher desired @param key The secret key to use @param keylen The length of the secret key (octets) @param uskey A previously scheduled key [optional can be NULL] @param nonce The session nonce [use once] @param noncelen The length of the nonce @param header The header for the session @param headerlen The length of the header (octets) @param pt [*1] The plaintext @param ptlen The length of the plaintext (octets) @param ct [*1] The ciphertext @param tag [*1] The destination tag @param taglen The max size and resulting size of the authentication tag @param direction Encrypt or Decrypt direction (0 or 1) @return CRYPT_OK if successful */ int ccm_memory(int cipher, const unsigned char *key, unsigned long keylen, symmetric_key *uskey, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction) { unsigned char PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real; unsigned char *pt_work = NULL; symmetric_key *skey; int err; unsigned long len, L, x, y, z, CTRlen; if (uskey == NULL) { LTC_ARGCHK(key != NULL); } LTC_ARGCHK(nonce != NULL); if (headerlen > 0) { LTC_ARGCHK(header != NULL); } LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); pt_real = pt; #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* check cipher input */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher]->block_length != 16) { return CRYPT_INVALID_CIPHER; } /* make sure the taglen is valid */ if (*taglen < 4 || *taglen > 16 || (*taglen % 2) == 1 || headerlen > 0x7fffffffu) { return CRYPT_INVALID_ARG; } /* is there an accelerator? */ if (cipher_descriptor[cipher]->accel_ccm_memory != NULL) { return cipher_descriptor[cipher]->accel_ccm_memory( key, keylen, uskey, nonce, noncelen, header, headerlen, pt, ptlen, ct, tag, taglen, direction); } /* let's get the L value */ len = ptlen; L = 0; while (len) { ++L; len >>= 8; } if (L <= 1) { L = 2; } /* increase L to match the nonce len */ noncelen = (noncelen > 13) ? 13 : noncelen; if ((15 - noncelen) > L) { L = 15 - noncelen; } if (L > 8) { return CRYPT_INVALID_ARG; } /* allocate mem for the symmetric key */ if (uskey == NULL) { skey = XMALLOC(sizeof(*skey)); if (skey == NULL) { return CRYPT_MEM; } /* initialize the cipher */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, skey)) != CRYPT_OK) { XFREE(skey); return err; } } else { skey = uskey; } /* initialize buffer for pt */ if (direction == CCM_DECRYPT && ptlen > 0) { pt_work = XMALLOC(ptlen); if (pt_work == NULL) { goto error; } pt = pt_work; } /* form B_0 == flags | Nonce N | l(m) */ x = 0; PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | (((*taglen - 2)>>1)<<3) | (L-1)); /* nonce */ for (y = 0; y < 15 - L; y++) { PAD[x++] = nonce[y]; } /* store len */ len = ptlen; /* shift len so the upper bytes of len are the contents of the length */ for (y = L; y < 4; y++) { len <<= 8; } /* store l(m) (only store 32-bits) */ for (y = 0; L > 4 && (L-y)>4; y++) { PAD[x++] = 0; } for (; y < L; y++) { if (x >= sizeof(PAD)) { err = CRYPT_INVALID_ARG; goto error; } PAD[x++] = (unsigned char)((len >> 24) & 255); len <<= 8; } /* encrypt PAD */ if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } /* handle header */ if (headerlen > 0) { x = 0; /* store length */ if (headerlen < ((1UL<<16) - (1UL<<8))) { PAD[x++] ^= (headerlen>>8) & 255; PAD[x++] ^= headerlen & 255; } else { PAD[x++] ^= 0xFF; PAD[x++] ^= 0xFE; PAD[x++] ^= (headerlen>>24) & 255; PAD[x++] ^= (headerlen>>16) & 255; PAD[x++] ^= (headerlen>>8) & 255; PAD[x++] ^= headerlen & 255; } /* now add the data */ for (y = 0; y < headerlen; y++) { if (x == 16) { /* full block so let's encrypt it */ if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } x = 0; } PAD[x++] ^= header[y]; } /* remainder */ if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } } /* setup the ctr counter */ x = 0; /* flags */ ctr[x++] = (unsigned char)L-1; /* nonce */ for (y = 0; y < (16 - (L+1)); ++y) { ctr[x++] = nonce[y]; } /* offset */ while (x < 16) { ctr[x++] = 0; } x = 0; CTRlen = 16; /* now handle the PT */ if (ptlen > 0) { y = 0; #ifdef LTC_FAST if (ptlen & ~15) { if (direction == CCM_ENCRYPT) { for (; y < (ptlen & ~15); y += 16) { /* increment the ctr? */ for (z = 15; z > 15-L; z--) { ctr[z] = (ctr[z] + 1) & 255; if (ctr[z]) break; } if ((err = cipher_descriptor[cipher]->ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { goto error; } /* xor the PT against the pad first */ for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); } if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } } } else { /* direction == CCM_DECRYPT */ for (; y < (ptlen & ~15); y += 16) { /* increment the ctr? */ for (z = 15; z > 15-L; z--) { ctr[z] = (ctr[z] + 1) & 255; if (ctr[z]) break; } if ((err = cipher_descriptor[cipher]->ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { goto error; } /* xor the PT against the pad last */ for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); } if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } } } } #endif for (; y < ptlen; y++) { /* increment the ctr? */ if (CTRlen == 16) { for (z = 15; z > 15-L; z--) { ctr[z] = (ctr[z] + 1) & 255; if (ctr[z]) break; } if ((err = cipher_descriptor[cipher]->ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { goto error; } CTRlen = 0; } /* if we encrypt we add the bytes to the MAC first */ if (direction == CCM_ENCRYPT) { b = pt[y]; ct[y] = b ^ CTRPAD[CTRlen++]; } else { b = ct[y] ^ CTRPAD[CTRlen++]; pt[y] = b; } if (x == 16) { if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } x = 0; } PAD[x++] ^= b; } if (x != 0) { if ((err = cipher_descriptor[cipher]->ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { goto error; } } } /* setup CTR for the TAG (zero the count) */ for (y = 15; y > 15 - L; y--) { ctr[y] = 0x00; } if ((err = cipher_descriptor[cipher]->ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { goto error; } if (skey != uskey) { cipher_descriptor[cipher]->done(skey); #ifdef LTC_CLEAN_STACK zeromem(skey, sizeof(*skey)); #endif } if (direction == CCM_ENCRYPT) { /* store the TAG */ for (x = 0; x < 16 && x < *taglen; x++) { tag[x] = PAD[x] ^ CTRPAD[x]; } *taglen = x; } else { /* direction == CCM_DECRYPT */ /* decrypt the tag */ for (x = 0; x < 16 && x < *taglen; x++) { ptTag[x] = tag[x] ^ CTRPAD[x]; } *taglen = x; /* check validity of the decrypted tag against the computed PAD (in constant time) */ /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR). * there should be a better way of setting the correct error code in constant * time. */ err = XMEM_NEQ(ptTag, PAD, *taglen); /* Zero the plaintext if the tag was invalid (in constant time) */ if (ptlen > 0) { copy_or_zeromem(pt, pt_real, ptlen, err); } } #ifdef LTC_CLEAN_STACK zeromem(PAD, sizeof(PAD)); zeromem(CTRPAD, sizeof(CTRPAD)); if (pt_work != NULL) { zeromem(pt_work, ptlen); } #endif error: if (pt_work) { XFREE(pt_work); } if (skey != uskey) { XFREE(skey); } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_process.c000066400000000000000000000041601464416617300250420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CCM_MODE /** Process plaintext/ciphertext through CCM @param ccm The CCM state @param pt The plaintext @param ptlen The plaintext length (ciphertext length is the same) @param ct The ciphertext @param direction Encrypt or Decrypt mode (CCM_ENCRYPT or CCM_DECRYPT) @return CRYPT_OK on success */ int ccm_process(ccm_state *ccm, unsigned char *pt, unsigned long ptlen, unsigned char *ct, int direction) { unsigned char z, b; unsigned long y; int err; LTC_ARGCHK(ccm != NULL); /* Check aad has been correctly added */ if (ccm->aadlen != ccm->current_aadlen) { return CRYPT_ERROR; } /* Check we do not process too much data */ if (ccm->ptlen < ccm->current_ptlen + ptlen) { return CRYPT_ERROR; } ccm->current_ptlen += ptlen; /* now handle the PT */ if (ptlen > 0) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); for (y = 0; y < ptlen; y++) { /* increment the ctr? */ if (ccm->CTRlen == 16) { for (z = 15; z > 15-ccm->L; z--) { ccm->ctr[z] = (ccm->ctr[z] + 1) & 255; if (ccm->ctr[z]) break; } if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { return err; } ccm->CTRlen = 0; } /* if we encrypt we add the bytes to the MAC first */ if (direction == CCM_ENCRYPT) { b = pt[y]; ct[y] = b ^ ccm->CTRPAD[ccm->CTRlen++]; } else { b = ct[y] ^ ccm->CTRPAD[ccm->CTRlen++]; pt[y] = b; } if (ccm->x == 16) { if ((err = cipher_descriptor[ccm->cipher]->ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { return err; } ccm->x = 0; } ccm->PAD[ccm->x++] ^= b; } } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_reset.c000066400000000000000000000011531464416617300245050ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CCM_MODE /** Reset a CCM state to as if you just called ccm_init(). This saves the initialization time. @param ccm The CCM state to reset @return CRYPT_OK on success */ int ccm_reset(ccm_state *ccm) { LTC_ARGCHK(ccm != NULL); zeromem(ccm->PAD, sizeof(ccm->PAD)); zeromem(ccm->ctr, sizeof(ccm->ctr)); zeromem(ccm->CTRPAD, sizeof(ccm->CTRPAD)); ccm->CTRlen = 0; ccm->current_ptlen = 0; ccm->current_aadlen = 0; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c000066400000000000000000000232271464416617300243500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ccm_test.c CCM support, process a block of memory, Tom St Denis */ #ifdef LTC_CCM_MODE int ccm_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[16]; unsigned char nonce[16]; int noncelen; unsigned char header[64]; int headerlen; unsigned char pt[64]; int ptlen; unsigned char ct[64]; unsigned char tag[16]; unsigned long taglen; } tests[] = { /* 13 byte nonce, 8 byte auth, 23 byte pt */ { { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, { 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, 13, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 8, { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E }, 23, { 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2, 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80, 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84 }, { 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 }, 8 }, /* 13 byte nonce, 12 byte header, 19 byte pt */ { { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, { 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, 13, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B }, 12, { 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E }, 19, { 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79, 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91, 0xCD, 0xAC, 0x8C }, { 0x96, 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1 }, 8 }, /* supplied by Brian Gladman */ { { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }, { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, 7, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, 8, { 0x20, 0x21, 0x22, 0x23 }, 4, { 0x71, 0x62, 0x01, 0x5b }, { 0x4d, 0xac, 0x25, 0x5d }, 4 }, { { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f }, { 0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5, 0x03, 0x97, 0x76, 0xe7, 0x0c }, 13, { 0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae, 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00 }, 22, { 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, 0x7e, 0x78, 0xa0, 0x50 }, 20, { 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, 0x3c, 0x04, 0xd0, 0x19 }, { 0x78, 0x45, 0xce, 0x0b, 0x16, 0xf9, 0x76, 0x23 }, 8 }, }; unsigned long taglen, x, y; unsigned char buf[64], buf2[64], tag[16], tag2[16], tag3[16], zero[64]; int err, idx; symmetric_key skey; ccm_state ccm; zeromem(zero, 64); idx = find_cipher("aes"); if (idx == -1) { idx = find_cipher("rijndael"); if (idx == -1) { return CRYPT_NOP; } } for (x = 0; x < (sizeof(tests)/sizeof(tests[0])); x++) { for (y = 0; y < 2; y++) { taglen = tests[x].taglen; if (y == 0) { if ((err = cipher_descriptor[idx]->setup(tests[x].key, 16, 0, &skey)) != CRYPT_OK) { return err; } if ((err = ccm_memory(idx, tests[x].key, 16, &skey, tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, tag, &taglen, 0)) != CRYPT_OK) { return err; } /* run a second time to make sure skey is not touched */ if ((err = ccm_memory(idx, tests[x].key, 16, &skey, tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, tag, &taglen, 0)) != CRYPT_OK) { return err; } } else { if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { return err; } if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { return err; } if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { return err; } if ((err = ccm_process(&ccm, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, CCM_ENCRYPT)) != CRYPT_OK) { return err; } if ((err = ccm_done(&ccm, tag, &taglen)) != CRYPT_OK) { return err; } } if (compare_testvector(buf, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "CCM encrypt data", x)) { return CRYPT_FAIL_TESTVECTOR; } if (compare_testvector(tag, taglen, tests[x].tag, tests[x].taglen, "CCM encrypt tag", x)) { return CRYPT_FAIL_TESTVECTOR; } if (y == 0) { XMEMCPY(tag3, tests[x].tag, tests[x].taglen); taglen = tests[x].taglen; if ((err = ccm_memory(idx, tests[x].key, 16, NULL, tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, buf2, tests[x].ptlen, buf, tag3, &taglen, 1 )) != CRYPT_OK) { return err; } } else { if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { return err; } if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { return err; } if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { return err; } if ((err = ccm_process(&ccm, buf2, tests[x].ptlen, buf, CCM_DECRYPT)) != CRYPT_OK) { return err; } if ((err = ccm_done(&ccm, tag2, &taglen)) != CRYPT_OK) { return err; } } if (compare_testvector(buf2, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "CCM decrypt data", x)) { return CRYPT_FAIL_TESTVECTOR; } if (y == 0) { /* check if decryption with the wrong tag does not reveal the plaintext */ XMEMCPY(tag3, tests[x].tag, tests[x].taglen); tag3[0] ^= 0xff; /* set the tag to the wrong value */ taglen = tests[x].taglen; if (ccm_memory(idx, tests[x].key, 16, NULL, tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, buf2, tests[x].ptlen, buf, tag3, &taglen, 1 ) != CRYPT_ERROR) { return CRYPT_FAIL_TESTVECTOR; } if (compare_testvector(buf2, tests[x].ptlen, zero, tests[x].ptlen, "CCM decrypt wrong tag", x)) { return CRYPT_FAIL_TESTVECTOR; } } else { if (compare_testvector(tag2, taglen, tests[x].tag, tests[x].taglen, "CCM decrypt tag", x)) { return CRYPT_FAIL_TESTVECTOR; } } if (y == 0) { cipher_descriptor[idx]->done(&skey); } } } /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/452 */ { unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; unsigned char iv[] = { 0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51 }; unsigned char valid_tag[] = { 0x23,0x1a,0x2d,0x8f }; unsigned char invalid_tag[] = { 0x23,0x1a,0x2d,0x8f,0x6a }; unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; unsigned char ct[] = { 0xd3,0xda,0xb1,0xee,0x49,0x4c,0xc2,0x29,0x09,0x9d,0x6c,0xac,0x7d,0xf1,0x4a,0xdd }; unsigned char pt[20] = { 0 }; /* VALID tag */ taglen = sizeof(valid_tag); err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, pt, sizeof(ct), ct, valid_tag, &taglen, CCM_DECRYPT); if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { return CRYPT_FAIL_TESTVECTOR; } /* INVALID tag */ taglen = sizeof(invalid_tag); err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, pt, sizeof(ct), ct, invalid_tag, &taglen, CCM_DECRYPT); if (err == CRYPT_OK) { return CRYPT_FAIL_TESTVECTOR; /* should fail */ } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/000077500000000000000000000000001464416617300237465ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c000066400000000000000000000014721464416617300303210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Add AAD to the ChaCha20Poly1305 state @param st The ChaCha20Poly1305 state @param in The additional authentication data to add to the ChaCha20Poly1305 state @param inlen The length of the ChaCha20Poly1305 data. @return CRYPT_OK on success */ int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen) { int err; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); if (st->aadflg == 0) return CRYPT_ERROR; if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; st->aadlen += (ulong64)inlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c000066400000000000000000000022711464416617300304340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Decrypt bytes of ciphertext with ChaCha20Poly1305 @param st The ChaCha20Poly1305 state @param in The ciphertext @param inlen The length of the input (octets) @param out [out] The plaintext (length inlen) @return CRYPT_OK if successful */ int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { unsigned char padzero[16] = { 0 }; unsigned long padlen; int err; LTC_ARGCHK(st != NULL); if (st->aadflg) { padlen = 16 - (unsigned long)(st->aadlen % 16); if (padlen < 16) { if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; } st->aadflg = 0; /* no more AAD */ } if (st->aadflg) st->aadflg = 0; /* no more AAD */ if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; st->ctlen += (ulong64)inlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c000066400000000000000000000021731464416617300277100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Terminate a ChaCha20Poly1305 stream @param st The ChaCha20Poly1305 state @param tag [out] The destination for the MAC tag @param taglen [in/out] The length of the MAC tag @return CRYPT_OK on success */ int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen) { unsigned char padzero[16] = { 0 }; unsigned long padlen; unsigned char buf[16]; int err; LTC_ARGCHK(st != NULL); padlen = 16 - (unsigned long)(st->ctlen % 16); if (padlen < 16) { if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; } STORE64L(st->aadlen, buf); STORE64L(st->ctlen, buf + 8); if ((err = poly1305_process(&st->poly, buf, 16)) != CRYPT_OK) return err; if ((err = poly1305_done(&st->poly, tag, taglen)) != CRYPT_OK) return err; if ((err = chacha_done(&st->chacha)) != CRYPT_OK) return err; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c000066400000000000000000000022121464416617300304410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Encrypt bytes of ciphertext with ChaCha20Poly1305 @param st The ChaCha20Poly1305 state @param in The plaintext @param inlen The length of the input (octets) @param out [out] The ciphertext (length inlen) @return CRYPT_OK if successful */ int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { unsigned char padzero[16] = { 0 }; unsigned long padlen; int err; LTC_ARGCHK(st != NULL); if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; if (st->aadflg) { padlen = 16 - (unsigned long)(st->aadlen % 16); if (padlen < 16) { if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; } st->aadflg = 0; /* no more AAD */ } if ((err = poly1305_process(&st->poly, out, inlen)) != CRYPT_OK) return err; st->ctlen += (ulong64)inlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c000066400000000000000000000011331464416617300277210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Initialize an ChaCha20Poly1305 context (only the key) @param st [out] The destination of the ChaCha20Poly1305 state @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen) { return chacha_setup(&st->chacha, key, keylen, 20); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c000066400000000000000000000054471464416617300303020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Process an entire GCM packet in one call. @param key The secret key @param keylen The length of the secret key @param iv The initialization vector @param ivlen The length of the initialization vector @param aad The additional authentication data (header) @param aadlen The length of the aad @param in The plaintext @param inlen The length of the plaintext (ciphertext length is the same) @param out The ciphertext @param tag [out] The MAC tag @param taglen [in/out] The MAC tag length @param direction Encrypt or Decrypt mode (CHACHA20POLY1305_ENCRYPT or CHACHA20POLY1305_DECRYPT) @return CRYPT_OK on success */ int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *aad, unsigned long aadlen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned char *tag, unsigned long *taglen, int direction) { chacha20poly1305_state st; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(iv != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); if ((err = chacha20poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = chacha20poly1305_setiv(&st, iv, ivlen)) != CRYPT_OK) { goto LBL_ERR; } if (aad && aadlen > 0) { if ((err = chacha20poly1305_add_aad(&st, aad, aadlen)) != CRYPT_OK) { goto LBL_ERR; } } if (direction == CHACHA20POLY1305_ENCRYPT) { if ((err = chacha20poly1305_encrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } if ((err = chacha20poly1305_done(&st, tag, taglen)) != CRYPT_OK) { goto LBL_ERR; } } else if (direction == CHACHA20POLY1305_DECRYPT) { unsigned char buf[MAXBLOCKSIZE]; unsigned long buflen = sizeof(buf); if ((err = chacha20poly1305_decrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } if ((err = chacha20poly1305_done(&st, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; } if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { err = CRYPT_ERROR; goto LBL_ERR; } } else { err = CRYPT_INVALID_ARG; goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(chacha20poly1305_state)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c000066400000000000000000000032271464416617300301160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Set IV + counter data to the ChaCha20Poly1305 state and reset the context @param st The ChaCha20Poly1305 state @param iv The IV data to add @param ivlen The length of the IV (must be 12 or 8) @return CRYPT_OK on success */ int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen) { chacha_state tmp_st; int i, err; unsigned char polykey[32]; LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL); LTC_ARGCHK(ivlen == 12 || ivlen == 8); /* set IV for chacha20 */ if (ivlen == 12) { /* IV 96bit */ if ((err = chacha_ivctr32(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; } else { /* IV 64bit */ if ((err = chacha_ivctr64(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; } /* copy chacha20 key to temporary state */ for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i]; tmp_st.rounds = 20; /* set IV */ if (ivlen == 12) { /* IV 32bit */ if ((err = chacha_ivctr32(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; } else { /* IV 64bit */ if ((err = chacha_ivctr64(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; } /* (re)generate new poly1305 key */ if ((err = chacha_keystream(&tmp_st, polykey, 32)) != CRYPT_OK) return err; /* (re)initialise poly1305 */ if ((err = poly1305_init(&st->poly, polykey, 32)) != CRYPT_OK) return err; st->ctlen = 0; st->aadlen = 0; st->aadflg = 1; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c000066400000000000000000000017441464416617300312770ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE /** Set IV + counter data (with RFC7905-magic) to the ChaCha20Poly1305 state and reset the context @param st The ChaCha20Poly1305 state @param iv The IV data to add @param ivlen The length of the IV (must be 12 or 8) @param sequence_number 64bit sequence number which is incorporated into IV as described in RFC7905 @return CRYPT_OK on success */ int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number) { int i; unsigned char combined_iv[12] = { 0 }; LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL); LTC_ARGCHK(ivlen == 12); STORE64L(sequence_number, combined_iv + 4); for (i = 0; i < 12; i++) combined_iv[i] = iv[i] ^ combined_iv[i]; return chacha20poly1305_setiv(st, combined_iv, 12); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c000066400000000000000000000234151464416617300277440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20POLY1305_MODE int chacha20poly1305_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else chacha20poly1305_state st1, st2; unsigned char k[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }; unsigned char i12[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }; unsigned char i8[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43 }; unsigned char aad[] = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }; unsigned char enc[] = { 0xD3, 0x1A, 0x8D, 0x34, 0x64, 0x8E, 0x60, 0xDB, 0x7B, 0x86, 0xAF, 0xBC, 0x53, 0xEF, 0x7E, 0xC2, 0xA4, 0xAD, 0xED, 0x51, 0x29, 0x6E, 0x08, 0xFE, 0xA9, 0xE2, 0xB5, 0xA7, 0x36, 0xEE, 0x62, 0xD6, 0x3D, 0xBE, 0xA4, 0x5E, 0x8C, 0xA9, 0x67, 0x12, 0x82, 0xFA, 0xFB, 0x69, 0xDA, 0x92, 0x72, 0x8B, 0x1A, 0x71, 0xDE, 0x0A, 0x9E, 0x06, 0x0B, 0x29, 0x05, 0xD6, 0xA5, 0xB6, 0x7E, 0xCD, 0x3B, 0x36, 0x92, 0xDD, 0xBD, 0x7F, 0x2D, 0x77, 0x8B, 0x8C, 0x98, 0x03, 0xAE, 0xE3, 0x28, 0x09, 0x1B, 0x58, 0xFA, 0xB3, 0x24, 0xE4, 0xFA, 0xD6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8B, 0x48, 0x31, 0xD7, 0xBC, 0x3F, 0xF4, 0xDE, 0xF0, 0x8E, 0x4B, 0x7A, 0x9D, 0xE5, 0x76, 0xD2, 0x65, 0x86, 0xCE, 0xC6, 0x4B, 0x61, 0x16 }; unsigned char tag[] = { 0x1A, 0xE1, 0x0B, 0x59, 0x4F, 0x09, 0xE2, 0x6A, 0x7E, 0x90, 0x2E, 0xCB, 0xD0, 0x60, 0x06, 0x91 }; char m[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; unsigned long mlen = XSTRLEN(m); unsigned long len; unsigned char rfc7905_pt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; unsigned char rfc7905_enc[] = { 0xE4, 0x62, 0x85, 0xB4, 0x29, 0x95, 0x34, 0x96, 0xAB, 0xFB, 0x67, 0xCD, 0xAE, 0xAC, 0x94, 0x1E }; unsigned char rfc7905_tag[] = { 0x16, 0x2C, 0x92, 0x48, 0x2A, 0xDB, 0xD3, 0x5D, 0x48, 0xBE, 0xC6, 0xFF, 0x10, 0x9C, 0xBA, 0xE4 }; unsigned char ct[1000], pt[1000], emac[16], dmac[16]; int err; /* encrypt IV 96bit */ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; if ((err = chacha20poly1305_setiv(&st1, i12, sizeof(i12))) != CRYPT_OK) return err; if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; /* encrypt piece by piece */ if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, 25, ct)) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 25, 10, ct + 25)) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 35, 35, ct + 35)) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 70, 5, ct + 70)) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 75, 5, ct + 75)) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 80, mlen - 80, ct + 80)) != CRYPT_OK) return err; len = sizeof(emac); if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT", 1) != 0) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; /* decrypt IV 96bit */ if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; if ((err = chacha20poly1305_setiv(&st2, i12, sizeof(i12))) != CRYPT_OK) return err; if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; if ((err = chacha20poly1305_decrypt(&st2, ct, 21, pt)) != CRYPT_OK) return err; if ((err = chacha20poly1305_decrypt(&st2, ct + 21, mlen - 21, pt + 21)) != CRYPT_OK) return err; len = sizeof(dmac); if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; if (compare_testvector(pt, mlen, m, mlen, "DEC-PT", 3) != 0) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(dmac, len, tag, sizeof(tag), "DEC-TAG", 4) != 0) return CRYPT_FAIL_TESTVECTOR; /* chacha20poly1305_memory - encrypt */ len = sizeof(emac); if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), (unsigned char *)m, mlen, ct, emac, &len, CHACHA20POLY1305_ENCRYPT)) != CRYPT_OK) return err; if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG2", 2) != 0) return CRYPT_FAIL_TESTVECTOR; /* chacha20poly1305_memory - decrypt */ len = sizeof(dmac); XMEMCPY(dmac, tag, sizeof(tag)); if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), ct, mlen, pt, dmac, &len, CHACHA20POLY1305_DECRYPT)) != CRYPT_OK) return err; if (compare_testvector(pt, mlen, m, mlen, "DEC-PT2", 3) != 0) return CRYPT_FAIL_TESTVECTOR; /* encrypt - rfc7905 */ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, rfc7905_pt, 16, ct)) != CRYPT_OK) return err; len = sizeof(emac); if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; if (compare_testvector(ct, 16, rfc7905_enc, 16, "ENC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(emac, len, rfc7905_tag, 16, "ENC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; /* decrypt - rfc7905 */ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; if ((err = chacha20poly1305_decrypt(&st1, ct, 16, pt)) != CRYPT_OK) return err; len = sizeof(dmac); if ((err = chacha20poly1305_done(&st1, dmac, &len)) != CRYPT_OK) return err; if (compare_testvector(pt, 16, rfc7905_pt, 16, "DEC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(dmac, len, rfc7905_tag, 16, "DEC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; /* encrypt IV 64bit */ if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; if ((err = chacha20poly1305_setiv(&st1, i8, sizeof(i8))) != CRYPT_OK) return err; if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, mlen, ct)) != CRYPT_OK) return err; len = sizeof(emac); if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; /* decrypt IV 64bit */ if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; if ((err = chacha20poly1305_setiv(&st2, i8, sizeof(i8))) != CRYPT_OK) return err; if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; if ((err = chacha20poly1305_decrypt(&st2, ct, mlen, pt)) != CRYPT_OK) return err; len = sizeof(dmac); if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; if (compare_testvector(pt, mlen, m, mlen, "DEC-PT4", 1) != 0) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(dmac, len, emac, len, "DEC-TAG4", 2) != 0) return CRYPT_FAIL_TESTVECTOR; /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ { unsigned char key[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff, 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; unsigned char iv[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b }; unsigned char valid_tag[] = { 0xa3,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; unsigned char invalid_tag[] = { 0xa2,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; unsigned char waad[] = { 0x61,0x61,0x64 }; unsigned char wct[] = { 0x00 }; unsigned char wpt[20] = { 0 }; unsigned char wtag[20] = { 0 }; unsigned long taglen; /* encrypt */ taglen = sizeof(wtag); err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), wpt, 0, wct, wtag, &taglen, CHACHA20POLY1305_ENCRYPT); if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(wtag, taglen, valid_tag, sizeof(valid_tag), "WYCH", 1) != 0) return CRYPT_FAIL_TESTVECTOR; /* VALID tag */ taglen = sizeof(valid_tag); err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), wpt, 0, wct, valid_tag, &taglen, CHACHA20POLY1305_DECRYPT); if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; /* INVALID tag */ taglen = sizeof(invalid_tag); err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), wpt, 0, wct, invalid_tag, &taglen, CHACHA20POLY1305_DECRYPT); if (err == CRYPT_OK) { return CRYPT_FAIL_TESTVECTOR; /* should fail */ } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/000077500000000000000000000000001464416617300224105ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_addheader.c000066400000000000000000000013261464416617300253140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_addheader.c EAX implementation, add meta-data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** add header (metadata) to the stream @param eax The current EAX state @param header The header (meta-data) data you wish to add to the state @param length The length of the header data @return CRYPT_OK if successful */ int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length) { LTC_ARGCHK(eax != NULL); LTC_ARGCHK(header != NULL); return omac_process(&eax->headeromac, header, length); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt.c000066400000000000000000000015751464416617300250730ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_decrypt.c EAX implementation, decrypt block, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** Decrypt data with the EAX protocol @param eax The EAX state @param ct The ciphertext @param pt [out] The plaintext @param length The length (octets) of the ciphertext @return CRYPT_OK if successful */ int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length) { int err; LTC_ARGCHK(eax != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); /* omac ciphertext */ if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) { return err; } /* decrypt */ return ctr_decrypt(ct, pt, length, &eax->ctr); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c000066400000000000000000000052211464416617300300370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_decrypt_verify_memory.c EAX implementation, decrypt block of memory, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** Decrypt a block of memory and verify the provided MAC tag with EAX @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the key (octets) @param nonce The nonce data (use once) for the session @param noncelen The length of the nonce data. @param header The session header data @param headerlen The length of the header (octets) @param ct The ciphertext @param ctlen The length of the ciphertext (octets) @param pt [out] The plaintext @param tag The authentication tag provided by the encoder @param taglen [in/out] The length of the tag (octets) @param stat [out] The result of the decryption (1==valid tag, 0==invalid) @return CRYPT_OK if successful regardless of the resulting tag comparison */ int eax_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat) { int err; eax_state *eax; unsigned char *buf; unsigned long buflen; LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); /* default to zero */ *stat = 0; /* limit taglen */ taglen = MIN(taglen, MAXBLOCKSIZE); /* allocate ram */ buf = XMALLOC(taglen); eax = XMALLOC(sizeof(*eax)); if (eax == NULL || buf == NULL) { if (eax != NULL) { XFREE(eax); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = eax_decrypt(eax, ct, pt, ctlen)) != CRYPT_OK) { goto LBL_ERR; } buflen = taglen; if ((err = eax_done(eax, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; } /* compare tags */ if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { *stat = 1; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, taglen); zeromem(eax, sizeof(*eax)); #endif XFREE(eax); XFREE(buf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_done.c000066400000000000000000000035701464416617300243430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_done.c EAX implementation, terminate session, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** Terminate an EAX session and get the tag. @param eax The EAX state @param tag [out] The destination of the authentication tag @param taglen [in/out] The max length and resulting length of the authentication tag @return CRYPT_OK if successful */ int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) { int err; unsigned char *headermac, *ctmac; unsigned long x, len; LTC_ARGCHK(eax != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); /* allocate ram */ headermac = XMALLOC(MAXBLOCKSIZE); ctmac = XMALLOC(MAXBLOCKSIZE); if (headermac == NULL || ctmac == NULL) { if (headermac != NULL) { XFREE(headermac); } if (ctmac != NULL) { XFREE(ctmac); } return CRYPT_MEM; } /* finish ctomac */ len = MAXBLOCKSIZE; if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { goto LBL_ERR; } /* finish headeromac */ /* note we specifically don't reset len so the two lens are minimal */ if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { goto LBL_ERR; } /* terminate the CTR chain */ if ((err = ctr_done(&eax->ctr)) != CRYPT_OK) { goto LBL_ERR; } /* compute N xor H xor C */ for (x = 0; x < len && x < *taglen; x++) { tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; } *taglen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ctmac, MAXBLOCKSIZE); zeromem(headermac, MAXBLOCKSIZE); zeromem(eax, sizeof(*eax)); #endif XFREE(ctmac); XFREE(headermac); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt.c000066400000000000000000000016341464416617300251010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_encrypt.c EAX implementation, encrypt block by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** Encrypt with EAX a block of data. @param eax The EAX state @param pt The plaintext to encrypt @param ct [out] The ciphertext as encrypted @param length The length of the plaintext (octets) @return CRYPT_OK if successful */ int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length) { int err; LTC_ARGCHK(eax != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); /* encrypt */ if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) { return err; } /* omac ciphertext */ return omac_process(&eax->ctomac, ct, length); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c000066400000000000000000000037131464416617300312270ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_encrypt_authenticate_memory.c EAX implementation, encrypt a block of memory, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** EAX encrypt and produce an authentication tag @param cipher The index of the cipher desired @param key The secret key to use @param keylen The length of the secret key (octets) @param nonce The session nonce [use once] @param noncelen The length of the nonce @param header The header for the session @param headerlen The length of the header (octets) @param pt The plaintext @param ptlen The length of the plaintext (octets) @param ct [out] The ciphertext @param tag [out] The destination tag @param taglen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful */ int eax_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen) { int err; eax_state *eax; LTC_ARGCHK(key != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); eax = XMALLOC(sizeof(*eax)); if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = eax_encrypt(eax, pt, ct, ptlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = eax_done(eax, tag, taglen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(eax, sizeof(*eax)); #endif XFREE(eax); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_init.c000066400000000000000000000064431464416617300243630ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_init.c EAX implementation, initialized EAX state, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** Initialized an EAX state @param eax [out] The EAX state to initialize @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param nonce The use-once nonce for the session @param noncelen The length of the nonce (octets) @param header The header for the EAX state @param headerlen The header length (octets) @return CRYPT_OK if successful */ int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen) { unsigned char *buf; int err, blklen; omac_state *omac; unsigned long len; LTC_ARGCHK(eax != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(nonce != NULL); if (headerlen > 0) { LTC_ARGCHK(header != NULL); } if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } blklen = cipher_descriptor[cipher]->block_length; /* allocate ram */ buf = XMALLOC(MAXBLOCKSIZE); omac = XMALLOC(sizeof(*omac)); if (buf == NULL || omac == NULL) { if (buf != NULL) { XFREE(buf); } if (omac != NULL) { XFREE(omac); } return CRYPT_MEM; } /* N = LTC_OMAC_0K(nonce) */ zeromem(buf, MAXBLOCKSIZE); if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } /* omac the [0]_n */ if ((err = omac_process(omac, buf, blklen)) != CRYPT_OK) { goto LBL_ERR; } /* omac the nonce */ if ((err = omac_process(omac, nonce, noncelen)) != CRYPT_OK) { goto LBL_ERR; } /* store result */ len = sizeof(eax->N); if ((err = omac_done(omac, eax->N, &len)) != CRYPT_OK) { goto LBL_ERR; } /* H = LTC_OMAC_1K(header) */ zeromem(buf, MAXBLOCKSIZE); buf[blklen - 1] = 1; if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } /* omac the [1]_n */ if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) { goto LBL_ERR; } /* omac the header */ if (headerlen != 0) { if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) { goto LBL_ERR; } } /* note we don't finish the headeromac, this allows us to add more header later */ /* setup the CTR mode */ if ((err = ctr_start(cipher, eax->N, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &eax->ctr)) != CRYPT_OK) { goto LBL_ERR; } /* setup the LTC_OMAC for the ciphertext */ if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } /* omac [2]_n */ zeromem(buf, MAXBLOCKSIZE); buf[blklen-1] = 2; if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, MAXBLOCKSIZE); zeromem(omac, sizeof(*omac)); #endif XFREE(omac); XFREE(buf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/eax/eax_test.c000066400000000000000000000164761464416617300244060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file eax_test.c EAX implementation, self-test, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_EAX_MODE /** Test the EAX implementation @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int eax_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int keylen, noncelen, headerlen, msglen; unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE], header[MAXBLOCKSIZE], plaintext[MAXBLOCKSIZE], ciphertext[MAXBLOCKSIZE], tag[MAXBLOCKSIZE]; } tests[] = { /* NULL message */ { 16, 0, 0, 0, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0 }, /* header */ { 0 }, /* plaintext */ { 0 }, /* ciphertext */ { 0 }, /* tag */ { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5, 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff } }, /* test with nonce */ { 16, 16, 0, 0, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* header */ { 0 }, /* plaintext */ { 0 }, /* ciphertext */ { 0 }, /* tag */ { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb, 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec } }, /* test with header [no nonce] */ { 16, 0, 16, 0, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0 }, /* header */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* plaintext */ { 0 }, /* ciphertext */ { 0 }, /* tag */ { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0, 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff } }, /* test with header + nonce + plaintext */ { 16, 16, 16, 32, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* header */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* plaintext */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, /* ciphertext */ { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b, 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78, 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f, 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc }, /* tag */ { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e, 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 } }, /* test with header + nonce + plaintext [not even sizes!] */ { 16, 15, 14, 29, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }, /* header */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, /* plaintext */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c }, /* ciphertext */ { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59, 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8, 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c, 0x8a, 0x24, 0xdb, 0x86, 0x8b }, /* tag */ { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2, 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda } }, /* Vectors from Brian Gladman */ { 16, 16, 8, 0, /* key */ { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f, 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 }, /* nonce */ { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07, 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 }, /* header */ { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b }, /* PT */ { 0x00 }, /* CT */ { 0x00 }, /* tag */ { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b, 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 } }, { 16, 16, 8, 2, /* key */ { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b, 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 }, /* nonce */ { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84, 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd }, /* header */ { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa }, /* PT */ { 0xf7, 0xfb }, /* CT */ { 0x19, 0xdd }, /* tag */ { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda, 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 } }, { 16, 16, 8, 5, /* key */ { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7, 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 }, /* nonce */ { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84, 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e }, /* header */ { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 }, /* PT */ { 0x1a, 0x47, 0xcb, 0x49, 0x33 }, /* CT */ { 0xd8, 0x51, 0xd5, 0xba, 0xe0 }, /* Tag */ { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19, 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 } } }; int err, x, idx, res; unsigned long len; unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { len = sizeof(outtag); if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen, tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) { return err; } if (compare_testvector(outtag, len, tests[x].tag, len, "EAX Tag", x) || compare_testvector(outct, tests[x].msglen, tests[x].ciphertext, tests[x].msglen, "EAX CT", x)) { return CRYPT_FAIL_TESTVECTOR; } /* test decrypt */ if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen, tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) { return err; } if ((res != 1) || compare_testvector(outct, tests[x].msglen, tests[x].plaintext, tests[x].msglen, "EAX", x)) { #ifdef LTC_TEST_DBG printf("\n\nEAX: Failure-decrypt - res = %d\n", res); #endif return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif /* LTC_TEST */ } #endif /* LTC_EAX_MODE */ optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/000077500000000000000000000000001464416617300224015ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_aad.c000066400000000000000000000054521464416617300247360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_add_aad.c GCM implementation, Add AAD data to the stream, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Add AAD to the GCM state @param gcm The GCM state @param adata The additional authentication data to add to the GCM state @param adatalen The length of the AAD data. @return CRYPT_OK on success */ int gcm_add_aad(gcm_state *gcm, const unsigned char *adata, unsigned long adatalen) { unsigned long x; int err; #ifdef LTC_FAST unsigned long y; #endif LTC_ARGCHK(gcm != NULL); if (adatalen > 0) { LTC_ARGCHK(adata != NULL); } if (gcm->buflen > 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } /* in IV mode? */ if (gcm->mode == LTC_GCM_MODE_IV) { /* IV length must be > 0 */ if (gcm->buflen == 0 && gcm->totlen == 0) return CRYPT_ERROR; /* let's process the IV */ if (gcm->ivmode || gcm->buflen != 12) { for (x = 0; x < (unsigned long)gcm->buflen; x++) { gcm->X[x] ^= gcm->buf[x]; } if (gcm->buflen) { gcm->totlen += gcm->buflen * CONST64(8); gcm_mult_h(gcm, gcm->X); } /* mix in the length */ zeromem(gcm->buf, 8); STORE64H(gcm->totlen, gcm->buf+8); for (x = 0; x < 16; x++) { gcm->X[x] ^= gcm->buf[x]; } gcm_mult_h(gcm, gcm->X); /* copy counter out */ XMEMCPY(gcm->Y, gcm->X, 16); zeromem(gcm->X, 16); } else { XMEMCPY(gcm->Y, gcm->buf, 12); gcm->Y[12] = 0; gcm->Y[13] = 0; gcm->Y[14] = 0; gcm->Y[15] = 1; } XMEMCPY(gcm->Y_0, gcm->Y, 16); zeromem(gcm->buf, 16); gcm->buflen = 0; gcm->totlen = 0; gcm->mode = LTC_GCM_MODE_AAD; } if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) { return CRYPT_INVALID_ARG; } x = 0; #ifdef LTC_FAST if (gcm->buflen == 0 && adatalen > 15) { for (x = 0; x < (adatalen & ~15); x += 16) { for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y])); } gcm_mult_h(gcm, gcm->X); gcm->totlen += 128; } adata += x; } #endif /* start adding AAD data to the state */ for (; x < adatalen; x++) { gcm->X[gcm->buflen++] ^= *adata++; if (gcm->buflen == 16) { /* GF mult it */ gcm_mult_h(gcm, gcm->X); gcm->buflen = 0; gcm->totlen += 128; } } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_add_iv.c000066400000000000000000000033761464416617300246320ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_add_iv.c GCM implementation, add IV data to the state, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Add IV data to the GCM state @param gcm The GCM state @param IV The initial value data to add @param IVlen The length of the IV @return CRYPT_OK on success */ int gcm_add_iv(gcm_state *gcm, const unsigned char *IV, unsigned long IVlen) { unsigned long x, y; int err; LTC_ARGCHK(gcm != NULL); if (IVlen > 0) { LTC_ARGCHK(IV != NULL); } /* must be in IV mode */ if (gcm->mode != LTC_GCM_MODE_IV) { return CRYPT_INVALID_ARG; } if (gcm->buflen >= 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } /* trip the ivmode flag */ if (IVlen + gcm->buflen > 12) { gcm->ivmode |= 1; } x = 0; #ifdef LTC_FAST if (gcm->buflen == 0) { for (x = 0; x < (IVlen & ~15); x += 16) { for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&IV[x + y])); } gcm_mult_h(gcm, gcm->X); gcm->totlen += 128; } IV += x; } #endif /* start adding IV data to the state */ for (; x < IVlen; x++) { gcm->buf[gcm->buflen++] = *IV++; if (gcm->buflen == 16) { /* GF mult it */ for (y = 0; y < 16; y++) { gcm->X[y] ^= gcm->buf[y]; } gcm_mult_h(gcm, gcm->X); gcm->buflen = 0; gcm->totlen += 128; } } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_done.c000066400000000000000000000035701464416617300243250ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_done.c GCM implementation, Terminate the stream, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Terminate a GCM stream @param gcm The GCM state @param tag [out] The destination for the MAC tag @param taglen [in/out] The length of the MAC tag @return CRYPT_OK on success */ int gcm_done(gcm_state *gcm, unsigned char *tag, unsigned long *taglen) { unsigned long x; int err; LTC_ARGCHK(gcm != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); if (gcm->buflen > 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } if (gcm->mode == LTC_GCM_MODE_IV) { /* let's process the IV */ if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; } if (gcm->mode == LTC_GCM_MODE_AAD) { /* let's process the AAD */ if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err; } if (gcm->mode != LTC_GCM_MODE_TEXT) { return CRYPT_INVALID_ARG; } /* handle remaining ciphertext */ if (gcm->buflen) { gcm->pttotlen += gcm->buflen * CONST64(8); gcm_mult_h(gcm, gcm->X); } /* length */ STORE64H(gcm->totlen, gcm->buf); STORE64H(gcm->pttotlen, gcm->buf+8); for (x = 0; x < 16; x++) { gcm->X[x] ^= gcm->buf[x]; } gcm_mult_h(gcm, gcm->X); /* encrypt original counter */ if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) { return err; } for (x = 0; x < 16 && x < *taglen; x++) { tag[x] = gcm->buf[x] ^ gcm->X[x]; } *taglen = x; cipher_descriptor[gcm->cipher]->done(&gcm->K); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c000066400000000000000000000175111464416617300250350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_gf_mult.c GCM implementation, do the GF mult, by Tom St Denis */ #include "tomcrypt_private.h" #if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || (defined(LTC_GCM_MODE) && defined(LTC_FAST)) /* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the * lower 16 bits are not zero'ed I removed the upper 14 bytes */ const unsigned char gcm_shift_table[256*2] = { 0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e, 0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e, 0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e, 0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e, 0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e, 0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e, 0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e, 0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e, 0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce, 0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde, 0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee, 0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe, 0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e, 0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e, 0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae, 0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe, 0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e, 0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e, 0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e, 0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e, 0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e, 0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e, 0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e, 0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e, 0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce, 0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde, 0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee, 0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe, 0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e, 0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e, 0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae, 0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe }; #endif #if defined(LTC_GCM_MODE) || defined(LRW_MODE) #ifndef LTC_FAST /* right shift */ static void s_gcm_rightshift(unsigned char *a) { int x; for (x = 15; x > 0; x--) { a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80); } a[0] >>= 1; } /* c = b*a */ static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; static const unsigned char poly[] = { 0x00, 0xE1 }; /** GCM GF multiplier (internal use only) bitserial @param a First value @param b Second value @param c Destination for a * b */ void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) { unsigned char Z[16], V[16]; unsigned char x, y, z; zeromem(Z, 16); XMEMCPY(V, a, 16); for (x = 0; x < 128; x++) { if (b[x>>3] & mask[x&7]) { for (y = 0; y < 16; y++) { Z[y] ^= V[y]; } } z = V[15] & 0x01; s_gcm_rightshift(V); V[0] ^= poly[z]; } XMEMCPY(c, Z, 16); } #else /* map normal numbers to "ieee" way ... e.g. bit reversed */ #define M(x) ( ((x&8)>>3) | ((x&4)>>1) | ((x&2)<<1) | ((x&1)<<3) ) #define BPD (sizeof(LTC_FAST_TYPE) * 8) #define WPV (1 + (16 / sizeof(LTC_FAST_TYPE))) /** GCM GF multiplier (internal use only) word oriented @param a First value @param b Second value @param c Destination for a * b */ void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) { int i, j, k, u; LTC_FAST_TYPE B[16][WPV], tmp[32 / sizeof(LTC_FAST_TYPE)], pB[16 / sizeof(LTC_FAST_TYPE)], zz, z; unsigned char pTmp[32]; /* create simple tables */ zeromem(B[0], sizeof(B[0])); zeromem(B[M(1)], sizeof(B[M(1)])); #ifdef ENDIAN_32BITWORD for (i = 0; i < 4; i++) { LOAD32H(B[M(1)][i], a + (i<<2)); LOAD32L(pB[i], b + (i<<2)); } #else for (i = 0; i < 2; i++) { LOAD64H(B[M(1)][i], a + (i<<3)); LOAD64L(pB[i], b + (i<<3)); } #endif /* now create 2, 4 and 8 */ B[M(2)][0] = B[M(1)][0] >> 1; B[M(4)][0] = B[M(1)][0] >> 2; B[M(8)][0] = B[M(1)][0] >> 3; for (i = 1; i < (int)WPV; i++) { B[M(2)][i] = (B[M(1)][i-1] << (BPD-1)) | (B[M(1)][i] >> 1); B[M(4)][i] = (B[M(1)][i-1] << (BPD-2)) | (B[M(1)][i] >> 2); B[M(8)][i] = (B[M(1)][i-1] << (BPD-3)) | (B[M(1)][i] >> 3); } /* now all values with two bits which are 3, 5, 6, 9, 10, 12 */ for (i = 0; i < (int)WPV; i++) { B[M(3)][i] = B[M(1)][i] ^ B[M(2)][i]; B[M(5)][i] = B[M(1)][i] ^ B[M(4)][i]; B[M(6)][i] = B[M(2)][i] ^ B[M(4)][i]; B[M(9)][i] = B[M(1)][i] ^ B[M(8)][i]; B[M(10)][i] = B[M(2)][i] ^ B[M(8)][i]; B[M(12)][i] = B[M(8)][i] ^ B[M(4)][i]; /* now all 3 bit values and the only 4 bit value: 7, 11, 13, 14, 15 */ B[M(7)][i] = B[M(3)][i] ^ B[M(4)][i]; B[M(11)][i] = B[M(3)][i] ^ B[M(8)][i]; B[M(13)][i] = B[M(1)][i] ^ B[M(12)][i]; B[M(14)][i] = B[M(6)][i] ^ B[M(8)][i]; B[M(15)][i] = B[M(7)][i] ^ B[M(8)][i]; } zeromem(tmp, sizeof(tmp)); /* compute product four bits of each word at a time */ /* for each nibble */ for (i = (BPD/4)-1; i >= 0; i--) { /* for each word */ for (j = 0; j < (int)(WPV-1); j++) { /* grab the 4 bits recall the nibbles are backwards so it's a shift by (i^1)*4 */ u = (pB[j] >> ((i^1)<<2)) & 15; /* add offset by the word count the table looked up value to the result */ for (k = 0; k < (int)WPV; k++) { tmp[k+j] ^= B[u][k]; } } /* shift result up by 4 bits */ if (i != 0) { for (z = j = 0; j < (int)(32 / sizeof(LTC_FAST_TYPE)); j++) { zz = tmp[j] << (BPD-4); tmp[j] = (tmp[j] >> 4) | z; z = zz; } } } /* store product */ #ifdef ENDIAN_32BITWORD for (i = 0; i < 8; i++) { STORE32H(tmp[i], pTmp + (i<<2)); } #else for (i = 0; i < 4; i++) { STORE64H(tmp[i], pTmp + (i<<3)); } #endif /* reduce by taking most significant byte and adding the appropriate two byte sequence 16 bytes down */ for (i = 31; i >= 16; i--) { pTmp[i-16] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)]; pTmp[i-15] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)+1]; } for (i = 0; i < 16; i++) { c[i] = pTmp[i]; } } #endif #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_init.c000066400000000000000000000043771464416617300243510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_init.c GCM implementation, initialize state, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Initialize a GCM state @param gcm The GCM state to initialize @param cipher The index of the cipher to use @param key The secret key @param keylen The length of the secret key @return CRYPT_OK on success */ int gcm_init(gcm_state *gcm, int cipher, const unsigned char *key, int keylen) { int err; unsigned char B[16]; #ifdef LTC_GCM_TABLES int x, y, z, t; #endif LTC_ARGCHK(gcm != NULL); LTC_ARGCHK(key != NULL); #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* is cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher]->block_length != 16) { return CRYPT_INVALID_CIPHER; } /* schedule key */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) { return err; } /* H = E(0) */ zeromem(B, 16); if ((err = cipher_descriptor[cipher]->ecb_encrypt(B, gcm->H, &gcm->K)) != CRYPT_OK) { return err; } /* setup state */ zeromem(gcm->buf, sizeof(gcm->buf)); zeromem(gcm->X, sizeof(gcm->X)); gcm->cipher = cipher; gcm->mode = LTC_GCM_MODE_IV; gcm->ivmode = 0; gcm->buflen = 0; gcm->totlen = 0; gcm->pttotlen = 0; #ifdef LTC_GCM_TABLES /* setup tables */ /* generate the first table as it has no shifting (from which we make the other tables) */ zeromem(B, 16); for (y = 0; y < 256; y++) { B[0] = y; gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]); } /* now generate the rest of the tables based the previous table */ for (x = 1; x < 16; x++) { for (y = 0; y < 256; y++) { /* now shift it right by 8 bits */ t = gcm->PC[x-1][y][15]; for (z = 15; z > 0; z--) { gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; } gcm->PC[x][y][0] = gcm_shift_table[t<<1]; gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; } } #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c000066400000000000000000000070601464416617300247060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_memory.c GCM implementation, process a packet, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Process an entire GCM packet in one call. @param cipher Index of cipher to use @param key The secret key @param keylen The length of the secret key @param IV The initialization vector @param IVlen The length of the initialization vector @param adata The additional authentication data (header) @param adatalen The length of the adata @param pt The plaintext @param ptlen The length of the plaintext (ciphertext length is the same) @param ct The ciphertext @param tag [out] The MAC tag @param taglen [in/out] The MAC tag length @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) @return CRYPT_OK on success */ int gcm_memory( int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *IV, unsigned long IVlen, const unsigned char *adata, unsigned long adatalen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction) { void *orig; gcm_state *gcm; int err; if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher]->accel_gcm_memory != NULL) { return cipher_descriptor[cipher]->accel_gcm_memory (key, keylen, IV, IVlen, adata, adatalen, pt, ptlen, ct, tag, taglen, direction); } #ifndef LTC_GCM_TABLES_SSE2 orig = gcm = XMALLOC(sizeof(*gcm)); #else orig = gcm = XMALLOC(sizeof(*gcm) + 16); #endif if (gcm == NULL) { return CRYPT_MEM; } /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations * note that we only modify gcm and keep orig intact. This code is not portable * but again it's only for SSE2 anyways, so who cares? */ #ifdef LTC_GCM_TABLES_SSE2 gcm = LTC_ALIGN_BUF(gcm, 16); #endif if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { goto LTC_ERR; } if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) { goto LTC_ERR; } if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) { goto LTC_ERR; } if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) { goto LTC_ERR; } if (direction == GCM_ENCRYPT) { if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) { goto LTC_ERR; } } else if (direction == GCM_DECRYPT) { unsigned char buf[MAXBLOCKSIZE]; unsigned long buflen = sizeof(buf); if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) { goto LTC_ERR; } if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { err = CRYPT_ERROR; } } else { err = CRYPT_INVALID_ARG; } LTC_ERR: gcm_reset(gcm); XFREE(orig); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h.c000066400000000000000000000022451464416617300246660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_mult_h.c GCM implementation, do the GF mult, by Tom St Denis */ #include "tomcrypt_private.h" #if defined(LTC_GCM_MODE) /** GCM multiply by H @param gcm The GCM state which holds the H value @param I The value to multiply H by */ void gcm_mult_h(const gcm_state *gcm, unsigned char *I) { unsigned char T[16]; #ifdef LTC_GCM_TABLES int x; #ifdef LTC_GCM_TABLES_SSE2 asm("movdqa (%0),%%xmm0"::"r"(&gcm->PC[0][I[0]][0])); for (x = 1; x < 16; x++) { asm("pxor (%0),%%xmm0"::"r"(&gcm->PC[x][I[x]][0])); } asm("movdqa %%xmm0,(%0)"::"r"(&T)); #else int y; XMEMCPY(T, &gcm->PC[0][I[0]][0], 16); for (x = 1; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&gcm->PC[x][I[x]][y])); } #else for (y = 0; y < 16; y++) { T[y] ^= gcm->PC[x][I[x]][y]; } #endif /* LTC_FAST */ } #endif /* LTC_GCM_TABLES_SSE2 */ #else gcm_gf_mult(gcm->H, I, T); #endif XMEMCPY(I, T, 16); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_mult_h_arm_ce.c000066400000000000000000000017661464416617300262030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include /** GCM multiply by H @param gcm The GCM state which holds the H value @param I The value to multiply H by */ void gcm_mult_h(gcm_state *gcm, unsigned char *I) { struct tomcrypt_arm_neon_state state; const uint8_t zeroes[TEE_AES_BLOCK_SIZE] = { 0 }; uint64_t k[2]; uint64_t a; uint64_t b; uint64_t dg[2]; b = get_be64(gcm->H); a = get_be64(gcm->H + 8); k[0] = (a << 1) | (b >> 63); k[1] = (b << 1) | (a >> 63); if (b >> 63) k[1] ^= 0xc200000000000000UL; dg[1] = get_be64(I); dg[0] = get_be64(I + 8); tomcrypt_arm_neon_enable(&state); #ifdef _CFG_CORE_LTC_HWSUPP_PMULL pmull_ghash_update_p64(1, dg, zeroes, k, NULL); #else pmull_ghash_update_p8(1, dg, zeroes, k, NULL); #endif tomcrypt_arm_neon_disable(&state); put_be64(I, dg[1]); put_be64(I + 8, dg[0]); } optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_process.c000066400000000000000000000106361464416617300250570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_process.c GCM implementation, process message data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Process plaintext/ciphertext through GCM @param gcm The GCM state @param pt The plaintext @param ptlen The plaintext length (ciphertext length is the same) @param ct The ciphertext @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) @return CRYPT_OK on success */ int gcm_process(gcm_state *gcm, unsigned char *pt, unsigned long ptlen, unsigned char *ct, int direction) { unsigned long x; int y, err; unsigned char b; LTC_ARGCHK(gcm != NULL); if (ptlen > 0) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); } if (gcm->buflen > 16 || gcm->buflen < 0) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { return err; } /* 0xFFFFFFFE0 = ((2^39)-256)/8 */ if (gcm->pttotlen / 8 + (ulong64)gcm->buflen + (ulong64)ptlen >= CONST64(0xFFFFFFFE0)) { return CRYPT_INVALID_ARG; } if (gcm->mode == LTC_GCM_MODE_IV) { /* let's process the IV */ if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; } /* in AAD mode? */ if (gcm->mode == LTC_GCM_MODE_AAD) { /* let's process the AAD */ if (gcm->buflen) { gcm->totlen += gcm->buflen * CONST64(8); gcm_mult_h(gcm, gcm->X); } /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y] & 255) { break; } } /* encrypt the counter */ if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { return err; } gcm->buflen = 0; gcm->mode = LTC_GCM_MODE_TEXT; } if (gcm->mode != LTC_GCM_MODE_TEXT) { return CRYPT_INVALID_ARG; } x = 0; #ifdef LTC_FAST if (gcm->buflen == 0) { if (direction == GCM_ENCRYPT) { for (x = 0; x < (ptlen & ~15); x += 16) { /* ctr encrypt */ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&ct[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); } /* GMAC it */ gcm->pttotlen += 128; gcm_mult_h(gcm, gcm->X); /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y] & 255) { break; } } if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { return err; } } } else { for (x = 0; x < (ptlen & ~15); x += 16) { /* ctr encrypt */ for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); *(LTC_FAST_TYPE_PTR_CAST(&pt[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); } /* GMAC it */ gcm->pttotlen += 128; gcm_mult_h(gcm, gcm->X); /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y] & 255) { break; } } if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { return err; } } } } #endif /* process text */ for (; x < ptlen; x++) { if (gcm->buflen == 16) { gcm->pttotlen += 128; gcm_mult_h(gcm, gcm->X); /* increment counter */ for (y = 15; y >= 12; y--) { if (++gcm->Y[y] & 255) { break; } } if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { return err; } gcm->buflen = 0; } if (direction == GCM_ENCRYPT) { b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen]; } else { b = ct[x]; pt[x] = ct[x] ^ gcm->buf[gcm->buflen]; } gcm->X[gcm->buflen++] ^= b; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_reset.c000066400000000000000000000013361464416617300245200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_reset.c GCM implementation, reset a used state so it can accept IV data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Reset a GCM state to as if you just called gcm_init(). This saves the initialization time. @param gcm The GCM state to reset @return CRYPT_OK on success */ int gcm_reset(gcm_state *gcm) { LTC_ARGCHK(gcm != NULL); zeromem(gcm->buf, sizeof(gcm->buf)); zeromem(gcm->X, sizeof(gcm->X)); gcm->mode = LTC_GCM_MODE_IV; gcm->ivmode = 0; gcm->buflen = 0; gcm->totlen = 0; gcm->pttotlen = 0; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/gcm/gcm_test.c000066400000000000000000000305431464416617300243570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file gcm_test.c GCM implementation, testing, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_GCM_MODE /** Test the GCM code @return CRYPT_OK on success */ int gcm_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char K[32]; int keylen; unsigned char P[128]; unsigned long ptlen; unsigned char A[128]; unsigned long alen; unsigned char IV[128]; unsigned long IVlen; unsigned char C[128]; unsigned char T[16]; } tests[] = { /* test case #1 */ { /* key */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* plaintext */ { 0 }, 0, /* AAD data */ { 0 }, 0, /* IV */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 12, /* ciphertext */ { 0 }, /* tag */ { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a } }, /* test case #2 */ { /* key */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* PT */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* ADATA */ { 0 }, 0, /* IV */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 12, /* CT */ { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, /* TAG */ { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf } }, /* test case #3 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, }, 64, /* ADATA */ { 0 }, 0, /* IV */ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }, 12, /* CT */ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, }, /* TAG */ { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, } }, /* test case #4 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, }, 60, /* ADATA */ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2, }, 20, /* IV */ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }, 12, /* CT */ { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, }, /* TAG */ { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, } }, /* test case #5 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, }, 60, /* ADATA */ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2, }, 20, /* IV */ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, }, 8, /* CT */ { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 0xc2, 0x3f, 0x45, 0x98, }, /* TAG */ { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, } }, /* test case #6 */ { /* key */ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, 16, /* PT */ { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, }, 60, /* ADATA */ { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2, }, 20, /* IV */ { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 0xa6, 0x37, 0xb3, 0x9b, }, 60, /* CT */ { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5, }, /* TAG */ { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, } }, /* test case #46 from BG (catches the LTC bug of v1.15) */ { /* key */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 16, /* PT */ { 0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd, 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7, 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7, 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53, 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7, 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29, 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4, 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd, 0x75, 0x8d, 0x2c }, 67, /* ADATA */ { 0x68, 0x8e, 0x1a, 0xa9, 0x84, 0xde, 0x92, 0x6d, 0xc7, 0xb4, 0xc4, 0x7f, 0x44 }, 13, /* IV */ { 0xb7, 0x21, 0x38, 0xb5, 0xa0, 0x5f, 0xf5, 0x07, 0x0e, 0x8c, 0xd9, 0x41, 0x83, 0xf7, 0x61, 0xd8 }, 16, /* CT */ { 0xcb, 0xc8, 0xd2, 0xf1, 0x54, 0x81, 0xa4, 0xcc, 0x7d, 0xd1, 0xe1, 0x9a, 0xaa, 0x83, 0xde, 0x56, 0x78, 0x48, 0x3e, 0xc3, 0x59, 0xae, 0x7d, 0xec, 0x2a, 0xb8, 0xd5, 0x34, 0xe0, 0x90, 0x6f, 0x4b, 0x46, 0x63, 0xfa, 0xff, 0x58, 0xa8, 0xb2, 0xd7, 0x33, 0xb8, 0x45, 0xee, 0xf7, 0xc9, 0xb3, 0x31, 0xe9, 0xe1, 0x0e, 0xb2, 0x61, 0x2c, 0x99, 0x5f, 0xeb, 0x1a, 0xc1, 0x5a, 0x62, 0x86, 0xcc, 0xe8, 0xb2, 0x97, 0xa8 }, /* TAG */ { 0x8d, 0x2d, 0x2a, 0x93, 0x72, 0x62, 0x6f, 0x6b, 0xee, 0x85, 0x80, 0x27, 0x6a, 0x63, 0x66, 0xbf } } /* rest of test cases are the same except AES key size changes... ignored... */ }; int idx, err; unsigned long x, y; unsigned char out[2][128], T[2][16]; gcm_state gcm; /* find aes */ idx = find_cipher("aes"); if (idx == -1) { idx = find_cipher("rijndael"); if (idx == -1) { return CRYPT_NOP; } } /* Special test case for empty AAD + empty PT */ y = sizeof(T[0]); if ((err = gcm_init(&gcm, idx, tests[0].K, tests[0].keylen)) != CRYPT_OK) return err; if ((err = gcm_add_iv(&gcm, tests[0].IV, tests[0].IVlen)) != CRYPT_OK) return err; /* intentionally skip gcm_add_aad + gcm_process */ if ((err = gcm_done(&gcm, T[0], &y)) != CRYPT_OK) return err; if (compare_testvector(T[0], y, tests[0].T, 16, "GCM Encrypt Tag-special", 0)) return CRYPT_FAIL_TESTVECTOR; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { y = sizeof(T[0]); if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, tests[x].IV, tests[x].IVlen, tests[x].A, tests[x].alen, (unsigned char*)tests[x].P, tests[x].ptlen, out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) { return err; } if (compare_testvector(out[0], tests[x].ptlen, tests[x].C, tests[x].ptlen, "GCM CT", x)) { return CRYPT_FAIL_TESTVECTOR; } if (compare_testvector(T[0], y, tests[x].T, 16, "GCM Encrypt Tag", x)) { return CRYPT_FAIL_TESTVECTOR; } y = sizeof(T[1]); XMEMCPY(T[1], tests[x].T, 16); if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, tests[x].IV, tests[x].IVlen, tests[x].A, tests[x].alen, out[1], tests[x].ptlen, out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) { return err; } if (compare_testvector(out[1], tests[x].ptlen, tests[x].P, tests[x].ptlen, "GCM PT", x)) { return CRYPT_FAIL_TESTVECTOR; } } /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ { unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; unsigned char iv[] = { 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b }; unsigned char valid_tag[] = { 0xd8,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; unsigned char invalid_tag[] = { 0xd9,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; unsigned char ct[] = { 0xeb,0x15,0x6d,0x08,0x1e,0xd6,0xb6,0xb5,0x5f,0x46,0x12,0xf0,0x21,0xd8,0x7b,0x39 }; unsigned char pt[20] = { 0 }; unsigned long taglen; /* VALID tag */ taglen = sizeof(valid_tag); err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, pt, sizeof(ct), ct, valid_tag, &taglen, GCM_DECRYPT); if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { return CRYPT_FAIL_TESTVECTOR; } /* INVALID tag */ taglen = sizeof(invalid_tag); err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, pt, sizeof(ct), ct, invalid_tag, &taglen, GCM_DECRYPT); if (err == CRYPT_OK) { return CRYPT_FAIL_TESTVECTOR; /* should fail */ } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/000077500000000000000000000000001464416617300223765ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt.c000066400000000000000000000030741464416617300250430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_decrypt.c OCB implementation, decrypt data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Decrypt a block with OCB. @param ocb The OCB state @param ct The ciphertext (length of the block size of the block cipher) @param pt [out] The plaintext (length of ct) @return CRYPT_OK if successful */ int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) { unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; int err, x; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); /* check if valid cipher */ if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { return err; } LTC_ARGCHK(cipher_descriptor[ocb->cipher]->ecb_decrypt != NULL); /* check length */ if (ocb->block_len != cipher_descriptor[ocb->cipher]->block_length) { return CRYPT_INVALID_ARG; } /* Get Z[i] value */ ocb_shift_xor(ocb, Z); /* xor ct in, encrypt, xor Z out */ for (x = 0; x < ocb->block_len; x++) { tmp[x] = ct[x] ^ Z[x]; } if ((err = cipher_descriptor[ocb->cipher]->ecb_decrypt(tmp, pt, &ocb->key)) != CRYPT_OK) { return err; } for (x = 0; x < ocb->block_len; x++) { pt[x] ^= Z[x]; } /* compute checksum */ for (x = 0; x < ocb->block_len; x++) { ocb->checksum[x] ^= pt[x]; } #ifdef LTC_CLEAN_STACK zeromem(Z, sizeof(Z)); zeromem(tmp, sizeof(tmp)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c000066400000000000000000000041041464416617300300120ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_decrypt_verify_memory.c OCB implementation, helper to decrypt block of memory, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Decrypt and compare the tag with OCB. @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param nonce The session nonce (length of the block size of the block cipher) @param ct The ciphertext @param ctlen The length of the ciphertext (octets) @param pt [out] The plaintext @param tag The tag to compare against @param taglen The length of the tag (octets) @param stat [out] The result of the tag comparison (1==valid, 0==invalid) @return CRYPT_OK if successful regardless of the tag comparison */ int ocb_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat) { int err; ocb_state *ocb; LTC_ARGCHK(key != NULL); LTC_ARGCHK(nonce != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(stat != NULL); /* allocate memory */ ocb = XMALLOC(sizeof(ocb_state)); if (ocb == NULL) { return CRYPT_MEM; } if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { goto LBL_ERR; } while (ctlen > (unsigned long)ocb->block_len) { if ((err = ocb_decrypt(ocb, ct, pt)) != CRYPT_OK) { goto LBL_ERR; } ctlen -= ocb->block_len; pt += ocb->block_len; ct += ocb->block_len; } err = ocb_done_decrypt(ocb, ct, ctlen, pt, tag, taglen, stat); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ocb, sizeof(ocb_state)); #endif XFREE(ocb); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c000066400000000000000000000032371464416617300260510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_done_decrypt.c OCB implementation, terminate decryption, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Terminate a decrypting OCB state @param ocb The OCB state @param ct The ciphertext (if any) @param ctlen The length of the ciphertext (octets) @param pt [out] The plaintext @param tag The authentication tag (to compare against) @param taglen The length of the authentication tag provided @param stat [out] The result of the tag comparison @return CRYPT_OK if the process was successful regardless if the tag is valid */ int ocb_done_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat) { int err; unsigned char *tagbuf; unsigned long tagbuflen; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(stat != NULL); /* default to failed */ *stat = 0; /* allocate memory */ tagbuf = XMALLOC(MAXBLOCKSIZE); if (tagbuf == NULL) { return CRYPT_MEM; } tagbuflen = MAXBLOCKSIZE; if ((err = s_ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) { goto LBL_ERR; } if (taglen <= tagbuflen && XMEM_NEQ(tagbuf, tag, taglen) == 0) { *stat = 1; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(tagbuf, MAXBLOCKSIZE); #endif XFREE(tagbuf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c000066400000000000000000000020201464416617300260500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_done_encrypt.c OCB implementation, terminate encryption, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Terminate an encryption OCB state @param ocb The OCB state @param pt Remaining plaintext (if any) @param ptlen The length of the plaintext (octets) @param ct [out] The ciphertext (if any) @param tag [out] The tag for the OCB stream @param taglen [in/out] The max size and resulting size of the tag @return CRYPT_OK if successful */ int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen) { LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); return s_ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt.c000066400000000000000000000027241464416617300250560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_encrypt.c OCB implementation, encrypt data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Encrypt a block of data with OCB. @param ocb The OCB state @param pt The plaintext (length of the block size of the block cipher) @param ct [out] The ciphertext (same size as the pt) @return CRYPT_OK if successful */ int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) { unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; int err, x; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { return err; } if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { return CRYPT_INVALID_ARG; } /* compute checksum */ for (x = 0; x < ocb->block_len; x++) { ocb->checksum[x] ^= pt[x]; } /* Get Z[i] value */ ocb_shift_xor(ocb, Z); /* xor pt in, encrypt, xor Z out */ for (x = 0; x < ocb->block_len; x++) { tmp[x] = pt[x] ^ Z[x]; } if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key)) != CRYPT_OK) { return err; } for (x = 0; x < ocb->block_len; x++) { ct[x] ^= Z[x]; } #ifdef LTC_CLEAN_STACK zeromem(Z, sizeof(Z)); zeromem(tmp, sizeof(tmp)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c000066400000000000000000000037451464416617300312100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_encrypt_authenticate_memory.c OCB implementation, encrypt block of memory, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Encrypt and generate an authentication code for a buffer of memory @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param nonce The session nonce (length of the block ciphers block size) @param pt The plaintext @param ptlen The length of the plaintext (octets) @param ct [out] The ciphertext @param tag [out] The authentication tag @param taglen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful */ int ocb_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen) { int err; ocb_state *ocb; LTC_ARGCHK(key != NULL); LTC_ARGCHK(nonce != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); /* allocate ram */ ocb = XMALLOC(sizeof(ocb_state)); if (ocb == NULL) { return CRYPT_MEM; } if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { goto LBL_ERR; } while (ptlen > (unsigned long)ocb->block_len) { if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) { goto LBL_ERR; } ptlen -= ocb->block_len; pt += ocb->block_len; ct += ocb->block_len; } err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ocb, sizeof(ocb_state)); #endif XFREE(ocb); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_init.c000066400000000000000000000067271464416617300243440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_init.c OCB implementation, initialize state, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE static const struct { int len; unsigned char poly_div[MAXBLOCKSIZE], poly_mul[MAXBLOCKSIZE]; } polys[] = { { 8, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } }, { 16, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } } }; /** Initialize an OCB context. @param ocb [out] The destination of the OCB state @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param nonce The session nonce (length of the block size of the cipher) @return CRYPT_OK if successful */ int ocb_init(ocb_state *ocb, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce) { int poly, x, y, m, err; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(nonce != NULL); /* valid cipher? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* determine which polys to use */ ocb->block_len = cipher_descriptor[cipher]->block_length; x = (int)(sizeof(polys)/sizeof(polys[0])); for (poly = 0; poly < x; poly++) { if (polys[poly].len == ocb->block_len) { break; } } if (poly == x) { return CRYPT_INVALID_ARG; /* block_len not found in polys */ } if (polys[poly].len != ocb->block_len) { return CRYPT_INVALID_ARG; } /* schedule the key */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { return err; } /* find L = E[0] */ zeromem(ocb->L, ocb->block_len); if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) { return err; } /* find R = E[N xor L] */ for (x = 0; x < ocb->block_len; x++) { ocb->R[x] = ocb->L[x] ^ nonce[x]; } if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) { return err; } /* find Ls[i] = L << i for i == 0..31 */ XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len); for (x = 1; x < 32; x++) { m = ocb->Ls[x-1][0] >> 7; for (y = 0; y < ocb->block_len-1; y++) { ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; } ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; if (m == 1) { for (y = 0; y < ocb->block_len; y++) { ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; } } } /* find Lr = L / x */ m = ocb->L[ocb->block_len-1] & 1; /* shift right */ for (x = ocb->block_len - 1; x > 0; x--) { ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; } ocb->Lr[0] = ocb->L[0] >> 1; if (m == 1) { for (x = 0; x < ocb->block_len; x++) { ocb->Lr[x] ^= polys[poly].poly_div[x]; } } /* set Li, checksum */ zeromem(ocb->Li, ocb->block_len); zeromem(ocb->checksum, ocb->block_len); /* set other params */ ocb->block_index = 1; ocb->cipher = cipher; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_ntz.c000066400000000000000000000010661464416617300242030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_ntz.c OCB implementation, internal function, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Returns the number of leading zero bits [from lsb up] @param x The 32-bit value to observe @return The number of bits [from the lsb up] that are zero */ int ocb_ntz(unsigned long x) { int c; x &= 0xFFFFFFFFUL; c = 0; while ((x & 1) == 0) { ++c; x >>= 1; } return c; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c000066400000000000000000000011601464416617300253700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_shift_xor.c OCB implementation, internal function, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Compute the shift/xor for OCB (internal function) @param ocb The OCB state @param Z The destination of the shift */ void ocb_shift_xor(ocb_state *ocb, unsigned char *Z) { int x, y; y = ocb_ntz(ocb->block_index++); for (x = 0; x < ocb->block_len; x++) { ocb->Li[x] ^= ocb->Ls[y][x]; Z[x] = ocb->Li[x] ^ ocb->R[x]; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/ocb_test.c000066400000000000000000000136541464416617300243550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb_test.c OCB implementation, self-test by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /** Test the OCB protocol @return CRYPT_OK if successful */ int ocb_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int ptlen; unsigned char key[16], nonce[16], pt[34], ct[34], tag[16]; } tests[] = { /* OCB-AES-128-0B */ { 0, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, /* pt */ { 0 }, /* ct */ { 0 }, /* tag */ { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6, 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee }, }, /* OCB-AES-128-3B */ { 3, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, /* pt */ { 0x00, 0x01, 0x02 }, /* ct */ { 0xfc, 0xd3, 0x7d }, /* tag */ { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a, 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba }, }, /* OCB-AES-128-16B */ { 16, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, /* pt */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* ct */ { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3, 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 }, /* tag */ { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71, 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf }, }, /* OCB-AES-128-20B */ { 20, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, /* pt */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 }, /* ct */ { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, 0x70, 0x03, 0xeb, 0x55}, /* tag */ { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77, 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb }, }, /* OCB-AES-128-32B */ { 32, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, /* pt */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, /* ct */ { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8, 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa }, /* tag */ { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c, 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf }, }, /* OCB-AES-128-34B */ { 34, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* nonce */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, /* pt */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21 }, /* ct */ { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa, 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f, 0xa9, 0x5d }, /* tag */ { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf, 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab }, }, }; int err, x, idx, res; unsigned long len; unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { len = sizeof(outtag); if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16, tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) { return err; } if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB Tag", x) || compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB CT", x)) { return CRYPT_FAIL_TESTVECTOR; } if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen, outct, tests[x].tag, len, &res)) != CRYPT_OK) { return err; } if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB", x)) { #ifdef LTC_TEST_DBG printf("\n\nOCB: Failure-decrypt - res = %d\n", res); #endif return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif /* LTC_TEST */ } #endif /* LTC_OCB_MODE */ /* some comments -- it's hard to seek -- hard to stream [you can't emit ciphertext until full block] -- The setup is somewhat complicated... */ optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb/s_ocb_done.c000066400000000000000000000070321464416617300246360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file s_ocb_done.c OCB implementation, internal helper, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB_MODE /* Since the last block is encrypted in CTR mode the same code can * be used to finish a decrypt or encrypt stream. The only difference * is we XOR the final ciphertext into the checksum so we have to xor it * before we CTR [decrypt] or after [encrypt] * * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... */ /** Shared code to finish an OCB stream @param ocb The OCB state @param pt The remaining plaintext [or input] @param ptlen The length of the input (octets) @param ct [out] The output buffer @param tag [out] The destination for the authentication tag @param taglen [in/out] The max size and resulting size of the authentication tag @param mode The mode we are terminating, 0==encrypt, 1==decrypt @return CRYPT_OK if successful */ int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) { unsigned char *Z, *Y, *X; int err, x; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { return err; } if (ocb->block_len != cipher_descriptor[ocb->cipher]->block_length || (int)ptlen > ocb->block_len || (int)ptlen < 0) { return CRYPT_INVALID_ARG; } /* allocate ram */ Z = XMALLOC(MAXBLOCKSIZE); Y = XMALLOC(MAXBLOCKSIZE); X = XMALLOC(MAXBLOCKSIZE); if (X == NULL || Y == NULL || Z == NULL) { if (X != NULL) { XFREE(X); } if (Y != NULL) { XFREE(Y); } if (Z != NULL) { XFREE(Z); } return CRYPT_MEM; } /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ ocb_shift_xor(ocb, X); XMEMCPY(Z, X, ocb->block_len); X[ocb->block_len-1] ^= (ptlen*8)&255; X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; for (x = 0; x < ocb->block_len; x++) { X[x] ^= ocb->Lr[x]; } /* Y[m] = E(X[m])) */ if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(X, Y, &ocb->key)) != CRYPT_OK) { goto error; } if (mode == 1) { /* decrypt mode, so let's xor it first */ /* xor C[m] into checksum */ for (x = 0; x < (int)ptlen; x++) { ocb->checksum[x] ^= ct[x]; } } /* C[m] = P[m] xor Y[m] */ for (x = 0; x < (int)ptlen; x++) { ct[x] = pt[x] ^ Y[x]; } if (mode == 0) { /* encrypt mode */ /* xor C[m] into checksum */ for (x = 0; x < (int)ptlen; x++) { ocb->checksum[x] ^= ct[x]; } } /* xor Y[m] and Z[m] into checksum */ for (x = 0; x < ocb->block_len; x++) { ocb->checksum[x] ^= Y[x] ^ Z[x]; } /* encrypt checksum, er... tag!! */ if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->checksum, X, &ocb->key)) != CRYPT_OK) { goto error; } cipher_descriptor[ocb->cipher]->done(&ocb->key); /* now store it */ for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { tag[x] = X[x]; } *taglen = x; #ifdef LTC_CLEAN_STACK zeromem(X, MAXBLOCKSIZE); zeromem(Y, MAXBLOCKSIZE); zeromem(Z, MAXBLOCKSIZE); zeromem(ocb, sizeof(*ocb)); #endif error: XFREE(X); XFREE(Y); XFREE(Z); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/000077500000000000000000000000001464416617300224615ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c000066400000000000000000000052121464416617300250700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_add_aad.c OCB implementation, add AAD data, by Karel Miko */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Add one block of AAD data (internal function) @param ocb The OCB state @param aad_block [in] AAD data (block_len size) @return CRYPT_OK if successful */ static int s_ocb3_int_aad_add_block(ocb3_state *ocb, const unsigned char *aad_block) { unsigned char tmp[MAXBLOCKSIZE]; int err; /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_[ocb3_int_ntz(ocb->ablock_index)], ocb->block_len); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ ocb3_int_xor_blocks(tmp, aad_block, ocb->aOffset_current, ocb->block_len); if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { return err; } ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); ocb->ablock_index++; return CRYPT_OK; } /** Add AAD - additional associated data @param ocb The OCB state @param aad The AAD data @param aadlen The size of AAD data (octets) @return CRYPT_OK if successful */ int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen) { int err, x, full_blocks, full_blocks_len, last_block_len; unsigned char *data; unsigned long datalen, l; LTC_ARGCHK(ocb != NULL); if (aadlen == 0) return CRYPT_OK; LTC_ARGCHK(aad != NULL); if (ocb->adata_buffer_bytes > 0) { l = ocb->block_len - ocb->adata_buffer_bytes; if (l > aadlen) l = aadlen; XMEMCPY(ocb->adata_buffer+ocb->adata_buffer_bytes, aad, l); ocb->adata_buffer_bytes += l; if (ocb->adata_buffer_bytes == ocb->block_len) { if ((err = s_ocb3_int_aad_add_block(ocb, ocb->adata_buffer)) != CRYPT_OK) { return err; } ocb->adata_buffer_bytes = 0; } data = (unsigned char *)aad + l; datalen = aadlen - l; } else { data = (unsigned char *)aad; datalen = aadlen; } if (datalen == 0) return CRYPT_OK; full_blocks = datalen/ocb->block_len; full_blocks_len = full_blocks * ocb->block_len; last_block_len = datalen - full_blocks_len; for (x=0; xblock_len)) != CRYPT_OK) { return err; } } if (last_block_len>0) { XMEMCPY(ocb->adata_buffer, data+full_blocks_len, last_block_len); ocb->adata_buffer_bytes = last_block_len; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c000066400000000000000000000043271464416617300252130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_decrypt.c OCB implementation, decrypt data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Decrypt blocks of ciphertext with OCB @param ocb The OCB state @param ct The ciphertext (length multiple of the block size of the block cipher) @param ctlen The length of the input (octets) @param pt [out] The plaintext (length of ct) @return CRYPT_OK if successful */ int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) { unsigned char tmp[MAXBLOCKSIZE]; int err, i, full_blocks; unsigned char *pt_b, *ct_b; LTC_ARGCHK(ocb != NULL); if (ctlen == 0) return CRYPT_OK; /* no data, nothing to do */ LTC_ARGCHK(ct != NULL); LTC_ARGCHK(pt != NULL); if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { return err; } if (ocb->block_len != cipher_descriptor[ocb->cipher]->block_length) { return CRYPT_INVALID_ARG; } if (ctlen % ocb->block_len) { /* ctlen has to bu multiple of block_len */ return CRYPT_INVALID_ARG; } full_blocks = ctlen/ocb->block_len; for(i=0; iblock_len; ct_b = (unsigned char *)ct+i*ocb->block_len; /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); /* tmp[] = ct[] XOR ocb->Offset_current[] */ ocb3_int_xor_blocks(tmp, ct_b, ocb->Offset_current, ocb->block_len); /* decrypt */ if ((err = cipher_descriptor[ocb->cipher]->ecb_decrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } /* pt[] = tmp[] XOR ocb->Offset_current[] */ ocb3_int_xor_blocks(pt_b, tmp, ocb->Offset_current, ocb->block_len); /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); ocb->block_index++; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(tmp, sizeof(tmp)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c000066400000000000000000000062311464416617300262320ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_decrypt_last.c OCB implementation, internal helper, by Karel Miko */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Finish an OCB (decryption) stream @param ocb The OCB state @param ct The remaining ciphertext @param ctlen The length of the ciphertext (octets) @param pt [out] The output buffer @return CRYPT_OK if successful */ int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) { unsigned char iOffset_star[MAXBLOCKSIZE]; unsigned char iPad[MAXBLOCKSIZE]; int err, x, full_blocks, full_blocks_len, last_block_len; LTC_ARGCHK(ocb != NULL); if (ct == NULL) LTC_ARGCHK(ctlen == 0); if (ctlen != 0) { LTC_ARGCHK(ct != NULL); LTC_ARGCHK(pt != NULL); } if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { goto LBL_ERR; } full_blocks = ctlen/ocb->block_len; full_blocks_len = full_blocks * ocb->block_len; last_block_len = ctlen - full_blocks_len; /* process full blocks first */ if (full_blocks>0) { if ((err = ocb3_decrypt(ocb, ct, full_blocks_len, pt)) != CRYPT_OK) { goto LBL_ERR; } } if (last_block_len>0) { /* Offset_* = Offset_m xor L_* */ ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); /* Pad = ENCIPHER(K, Offset_*) */ if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } /* P_* = C_* xor Pad[1..bitlen(C_*)] */ ocb3_int_xor_blocks(pt+full_blocks_len, (unsigned char *)ct+full_blocks_len, iPad, last_block_len); /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); for(x=last_block_len; xblock_len; x++) { if (x == last_block_len) { ocb->checksum[x] ^= 0x80; } else { ocb->checksum[x] ^= 0x00; } } /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ for(x=0; xblock_len; x++) { ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; } if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } } else { /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ for(x=0; xblock_len; x++) { ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; } if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(iOffset_star, MAXBLOCKSIZE); zeromem(iPad, MAXBLOCKSIZE); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c000066400000000000000000000052201464416617300301600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_decrypt_verify_memory.c OCB implementation, helper to decrypt block of memory, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Decrypt and compare the tag with OCB @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param nonce The session nonce (length of the block size of the block cipher) @param noncelen The length of the nonce (octets) @param adata The AAD - additional associated data @param adatalen The length of AAD (octets) @param ct The ciphertext @param ctlen The length of the ciphertext (octets) @param pt [out] The plaintext @param tag The tag to compare against @param taglen The length of the tag (octets) @param stat [out] The result of the tag comparison (1==valid, 0==invalid) @return CRYPT_OK if successful regardless of the tag comparison */ int ocb3_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *adata, unsigned long adatalen, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat) { int err; ocb3_state *ocb; unsigned char *buf; unsigned long buflen; LTC_ARGCHK(stat != NULL); /* default to zero */ *stat = 0; /* limit taglen */ taglen = MIN(taglen, MAXBLOCKSIZE); /* allocate memory */ buf = XMALLOC(taglen); ocb = XMALLOC(sizeof(ocb3_state)); if (ocb == NULL || buf == NULL) { if (ocb != NULL) { XFREE(ocb); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, taglen)) != CRYPT_OK) { goto LBL_ERR; } if (adata != NULL || adatalen != 0) { if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { goto LBL_ERR; } } if ((err = ocb3_decrypt_last(ocb, ct, ctlen, pt)) != CRYPT_OK) { goto LBL_ERR; } buflen = taglen; if ((err = ocb3_done(ocb, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; } /* compare tags */ if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { *stat = 1; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ocb, sizeof(ocb3_state)); #endif XFREE(ocb); XFREE(buf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_done.c000066400000000000000000000044341464416617300244650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_done.c OCB implementation, INTERNAL ONLY helper, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Finish OCB processing and compute the tag @param ocb The OCB state @param tag [out] The destination for the authentication tag @param taglen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful */ int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen) { unsigned char tmp[MAXBLOCKSIZE]; int err, x; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { goto LBL_ERR; } /* check taglen */ if ((int)*taglen < ocb->tag_len) { *taglen = (unsigned long)ocb->tag_len; return CRYPT_BUFFER_OVERFLOW; } /* finalize AAD processing */ if (ocb->adata_buffer_bytes>0) { /* Offset_* = Offset_m xor L_* */ ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_star, ocb->block_len); /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ ocb3_int_xor_blocks(tmp, ocb->adata_buffer, ocb->aOffset_current, ocb->adata_buffer_bytes); for(x=ocb->adata_buffer_bytes; xblock_len; x++) { if (x == ocb->adata_buffer_bytes) { tmp[x] = 0x80 ^ ocb->aOffset_current[x]; } else { tmp[x] = 0x00 ^ ocb->aOffset_current[x]; } } /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); } /* finalize TAG computing */ /* at this point ocb->aSum_current = HASH(K, A) */ /* tag = tag ^ HASH(K, A) */ ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len); /* copy tag bytes */ for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x]; *taglen = (unsigned long)ocb->tag_len; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(tmp, MAXBLOCKSIZE); zeromem(ocb, sizeof(*ocb)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c000066400000000000000000000043301464416617300252170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_encrypt.c OCB implementation, encrypt data, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Encrypt blocks of data with OCB @param ocb The OCB state @param pt The plaintext (length multiple of the block size of the block cipher) @param ptlen The length of the input (octets) @param ct [out] The ciphertext (same size as the pt) @return CRYPT_OK if successful */ int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) { unsigned char tmp[MAXBLOCKSIZE]; int err, i, full_blocks; unsigned char *pt_b, *ct_b; LTC_ARGCHK(ocb != NULL); if (ptlen == 0) return CRYPT_OK; /* no data, nothing to do */ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { return err; } if (ocb->block_len != cipher_descriptor[ocb->cipher]->block_length) { return CRYPT_INVALID_ARG; } if (ptlen % ocb->block_len) { /* ptlen has to bu multiple of block_len */ return CRYPT_INVALID_ARG; } full_blocks = ptlen/ocb->block_len; for(i=0; iblock_len; ct_b = (unsigned char *)ct+i*ocb->block_len; /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); /* tmp[] = pt[] XOR ocb->Offset_current[] */ ocb3_int_xor_blocks(tmp, pt_b, ocb->Offset_current, ocb->block_len); /* encrypt */ if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } /* ct[] = tmp[] XOR ocb->Offset_current[] */ ocb3_int_xor_blocks(ct_b, tmp, ocb->Offset_current, ocb->block_len); /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); ocb->block_index++; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(tmp, sizeof(tmp)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c000066400000000000000000000040621464416617300313470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_encrypt_authenticate_memory.c OCB implementation, encrypt block of memory, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Encrypt and generate an authentication code for a buffer of memory @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param nonce The session nonce (length of the block ciphers block size) @param noncelen The length of the nonce (octets) @param adata The AAD - additional associated data @param adatalen The length of AAD (octets) @param pt The plaintext @param ptlen The length of the plaintext (octets) @param ct [out] The ciphertext @param tag [out] The authentication tag @param taglen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful */ int ocb3_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *adata, unsigned long adatalen, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen) { int err; ocb3_state *ocb; LTC_ARGCHK(taglen != NULL); /* allocate memory */ ocb = XMALLOC(sizeof(ocb3_state)); if (ocb == NULL) { return CRYPT_MEM; } if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, *taglen)) != CRYPT_OK) { goto LBL_ERR; } if (adata != NULL || adatalen != 0) { if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { goto LBL_ERR; } } if ((err = ocb3_encrypt_last(ocb, pt, ptlen, ct)) != CRYPT_OK) { goto LBL_ERR; } err = ocb3_done(ocb, tag, taglen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ocb, sizeof(ocb3_state)); #endif XFREE(ocb); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c000066400000000000000000000063441464416617300262510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_encrypt_last.c OCB implementation, internal helper, by Karel Miko */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Finish an OCB (encryption) stream @param ocb The OCB state @param pt The remaining plaintext @param ptlen The length of the plaintext (octets) @param ct [out] The output buffer @return CRYPT_OK if successful */ int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) { unsigned char iOffset_star[MAXBLOCKSIZE]; unsigned char iPad[MAXBLOCKSIZE]; int err, x, full_blocks, full_blocks_len, last_block_len; LTC_ARGCHK(ocb != NULL); if (pt == NULL) LTC_ARGCHK(ptlen == 0); if (ptlen != 0) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); } if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { goto LBL_ERR; } full_blocks = ptlen/ocb->block_len; full_blocks_len = full_blocks * ocb->block_len; last_block_len = ptlen - full_blocks_len; /* process full blocks first */ if (full_blocks>0) { if ((err = ocb3_encrypt(ocb, pt, full_blocks_len, ct)) != CRYPT_OK) { goto LBL_ERR; } } /* at this point: m = ocb->block_index (last block index), Offset_m = ocb->Offset_current */ if (last_block_len>0) { /* Offset_* = Offset_m xor L_* */ ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); /* Pad = ENCIPHER(K, Offset_*) */ if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } /* C_* = P_* xor Pad[1..bitlen(P_*)] */ ocb3_int_xor_blocks(ct+full_blocks_len, pt+full_blocks_len, iPad, last_block_len); /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); for(x=last_block_len; xblock_len; x++) { if (x == last_block_len) { ocb->checksum[x] ^= 0x80; } else { ocb->checksum[x] ^= 0x00; } } /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ for(x=0; xblock_len; x++) { ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; } if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } } else { /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ for(x=0; xblock_len; x++) { ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; } if ((err = cipher_descriptor[ocb->cipher]->ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { goto LBL_ERR; } } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(iOffset_star, MAXBLOCKSIZE); zeromem(iPad, MAXBLOCKSIZE); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_init.c000066400000000000000000000127251464416617300245050ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_init.c OCB implementation, initialize state, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE static void s_ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen) { int x, y, bottom; int idx, shift; unsigned char iNonce[MAXBLOCKSIZE]; unsigned char iKtop[MAXBLOCKSIZE]; unsigned char iStretch[MAXBLOCKSIZE+8]; /* Nonce = zeros(127-bitlen(N)) || 1 || N */ zeromem(iNonce, sizeof(iNonce)); for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) { iNonce[x] = nonce[noncelen-y-1]; } iNonce[x] = 0x01; iNonce[0] |= ((taglen*8) % 128) << 1; /* bottom = str2num(Nonce[123..128]) */ bottom = iNonce[ocb->block_len-1] & 0x3F; /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */ iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0; if ((cipher_descriptor[ocb->cipher]->ecb_encrypt(iNonce, iKtop, &ocb->key)) != CRYPT_OK) { zeromem(ocb->Offset_current, ocb->block_len); return; } /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ for (x = 0; x < ocb->block_len; x++) { iStretch[x] = iKtop[x]; } for (y = 0; y < 8; y++) { iStretch[x+y] = iKtop[y] ^ iKtop[y+1]; } /* Offset_0 = Stretch[1+bottom..128+bottom] */ idx = bottom / 8; shift = (bottom % 8); for (x = 0; x < ocb->block_len; x++) { ocb->Offset_current[x] = iStretch[idx+x] << shift; if (shift > 0) { ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift); } } } static const struct { int len; unsigned char poly_mul[MAXBLOCKSIZE]; } polys[] = { { 8, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } }, { 16, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } } }; /** Initialize an OCB context @param ocb [out] The destination of the OCB state @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param nonce The session nonce @param noncelen The length of the session nonce (octets, up to 15) @param taglen The length of the tag (octets, up to 16) @return CRYPT_OK if successful */ int ocb3_init(ocb3_state *ocb, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen) { int poly, x, y, m, err; unsigned char *previous, *current; LTC_ARGCHK(ocb != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(nonce != NULL); /* valid cipher? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } ocb->cipher = cipher; /* Valid Nonce? * As of RFC7253: "string of no more than 120 bits" */ if (noncelen > (120/8)) { return CRYPT_INVALID_ARG; } /* The blockcipher must have a 128-bit blocksize */ if (cipher_descriptor[cipher]->block_length != 16) { return CRYPT_INVALID_ARG; } /* The TAGLEN may be any value up to 128 (bits) */ if (taglen > 16) { return CRYPT_INVALID_ARG; } ocb->tag_len = taglen; /* determine which polys to use */ ocb->block_len = cipher_descriptor[cipher]->block_length; x = (int)(sizeof(polys)/sizeof(polys[0])); for (poly = 0; poly < x; poly++) { if (polys[poly].len == ocb->block_len) { break; } } if (poly == x) { return CRYPT_INVALID_ARG; /* block_len not found in polys */ } if (polys[poly].len != ocb->block_len) { return CRYPT_INVALID_ARG; } /* schedule the key */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { return err; } /* L_* = ENCIPHER(K, zeros(128)) */ zeromem(ocb->L_star, ocb->block_len); if ((err = cipher_descriptor[cipher]->ecb_encrypt(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) { return err; } /* compute L_$, L_0, L_1, ... */ for (x = -1; x < 32; x++) { if (x == -1) { /* gonna compute: L_$ = double(L_*) */ current = ocb->L_dollar; previous = ocb->L_star; } else if (x == 0) { /* gonna compute: L_0 = double(L_$) */ current = ocb->L_[0]; previous = ocb->L_dollar; } else { /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */ current = ocb->L_[x]; previous = ocb->L_[x-1]; } m = previous[0] >> 7; for (y = 0; y < ocb->block_len-1; y++) { current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255; } current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255; if (m == 1) { /* current[] = current[] XOR polys[poly].poly_mul[]*/ ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len); } } /* initialize ocb->Offset_current = Offset_0 */ s_ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen); /* initialize checksum to all zeros */ zeromem(ocb->checksum, ocb->block_len); /* set block index */ ocb->block_index = 1; /* initialize AAD related stuff */ ocb->ablock_index = 1; ocb->adata_buffer_bytes = 0; zeromem(ocb->aOffset_current, ocb->block_len); zeromem(ocb->aSum_current, ocb->block_len); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c000066400000000000000000000011251464416617300252170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_int_ntz.c OCB implementation, INTERNAL ONLY helper, by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Returns the number of leading zero bits [from lsb up] (internal function) @param x The 32-bit value to observe @return The number of bits [from the lsb up] that are zero */ int ocb3_int_ntz(unsigned long x) { int c; x &= 0xFFFFFFFFUL; c = 0; while ((x & 1) == 0) { ++c; x >>= 1; } return c; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c000066400000000000000000000015701464416617300265550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_int_xor_blocks.c OCB implementation, INTERNAL ONLY helper, by Karel Miko */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Compute xor for two blocks of bytes 'out = block_a XOR block_b' (internal function) @param out The block of bytes (output) @param block_a The block of bytes (input) @param block_b The block of bytes (input) @param block_len The size of block_a, block_b, out */ void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len) { int x; if (out == block_a) { for (x = 0; x < (int)block_len; x++) out[x] ^= block_b[x]; } else { for (x = 0; x < (int)block_len; x++) out[x] = block_a[x] ^ block_b[x]; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/encauth/ocb3/ocb3_test.c000066400000000000000000000365251464416617300245250ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file ocb3_test.c OCB implementation, self-test by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_OCB3_MODE /** Test the OCB protocol @return CRYPT_OK if successful */ int ocb3_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else /* test vectors from: http://tools.ietf.org/html/draft-krovetz-ocb-03 */ unsigned char key[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; unsigned char nonce[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B }; const struct { int ptlen; int aadlen; unsigned char pt[64], aad[64], ct[64], tag[16]; } tests[] = { { /* index:0 */ 0, /* PLAINTEXT length */ 0, /* AAD length */ { 0 }, /* PLAINTEXT */ { 0 }, /* AAD */ { 0 }, /* CIPHERTEXT */ { 0x19,0x7b,0x9c,0x3c,0x44,0x1d,0x3c,0x83,0xea,0xfb,0x2b,0xef,0x63,0x3b,0x91,0x82 }, /* TAG */ }, { /* index:1 */ 8, /* PLAINTEXT length */ 8, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ { 0x16,0xdc,0x76,0xa4,0x6d,0x47,0xe1,0xea,0xd5,0x37,0x20,0x9e,0x8a,0x96,0xd1,0x4e }, /* TAG */ }, { /* index:2 */ 0, /* PLAINTEXT length */ 8, /* AAD length */ { 0 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ { 0 }, /* CIPHERTEXT */ { 0x98,0xb9,0x15,0x52,0xc8,0xc0,0x09,0x18,0x50,0x44,0xe3,0x0a,0x6e,0xb2,0xfe,0x21 }, /* TAG */ }, { /* index:3 */ 8, /* PLAINTEXT length */ 0, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ { 0 }, /* AAD */ { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ { 0x97,0x1e,0xff,0xca,0xe1,0x9a,0xd4,0x71,0x6f,0x88,0xe8,0x7b,0x87,0x1f,0xbe,0xed }, /* TAG */ }, { /* index:4 */ 16, /* PLAINTEXT length */ 16, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ { 0x77,0x6c,0x99,0x24,0xd6,0x72,0x3a,0x1f,0xc4,0x52,0x45,0x32,0xac,0x3e,0x5b,0xeb }, /* TAG */ }, { /* index:5 */ 0, /* PLAINTEXT length */ 16, /* AAD length */ { 0 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ { 0 }, /* CIPHERTEXT */ { 0x7d,0xdb,0x8e,0x6c,0xea,0x68,0x14,0x86,0x62,0x12,0x50,0x96,0x19,0xb1,0x9c,0xc6 }, /* TAG */ }, { /* index:6 */ 16, /* PLAINTEXT length */ 0, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ { 0 }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ { 0x13,0xcc,0x8b,0x74,0x78,0x07,0x12,0x1a,0x4c,0xbb,0x3e,0x4b,0xd6,0xb4,0x56,0xaf }, /* TAG */ }, { /* index:7 */ 24, /* PLAINTEXT length */ 24, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ { 0x5f,0xa9,0x4f,0xc3,0xf3,0x88,0x20,0xf1,0xdc,0x3f,0x3d,0x1f,0xd4,0xe5,0x5e,0x1c }, /* TAG */ }, { /* index:8 */ 0, /* PLAINTEXT length */ 24, /* AAD length */ { 0 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */ { 0 }, /* CIPHERTEXT */ { 0x28,0x20,0x26,0xda,0x30,0x68,0xbc,0x9f,0xa1,0x18,0x68,0x1d,0x55,0x9f,0x10,0xf6 }, /* TAG */ }, { /* index:9 */ 24, /* PLAINTEXT length */ 0, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ { 0 }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ { 0x6e,0xf2,0xf5,0x25,0x87,0xfd,0xa0,0xed,0x97,0xdc,0x7e,0xed,0xe2,0x41,0xdf,0x68 }, /* TAG */ }, { /* index:10 */ 32, /* PLAINTEXT length */ 32, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ { 0xb2,0xa0,0x40,0xdd,0x3b,0xd5,0x16,0x43,0x72,0xd7,0x6d,0x7b,0xb6,0x82,0x42,0x40 }, /* TAG */ }, { /* index:11 */ 0, /* PLAINTEXT length */ 32, /* AAD length */ { 0 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* AAD */ { 0 }, /* CIPHERTEXT */ { 0xe1,0xe0,0x72,0x63,0x3b,0xad,0xe5,0x1a,0x60,0xe8,0x59,0x51,0xd9,0xc4,0x2a,0x1b }, /* TAG */ }, { /* index:12 */ 32, /* PLAINTEXT length */ 0, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* PLAINTEXT */ { 0 }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ { 0x4a,0x3b,0xae,0x82,0x44,0x65,0xcf,0xda,0xf8,0xc4,0x1f,0xc5,0x0c,0x7d,0xf9,0xd9 }, /* TAG */ }, { /* index:13 */ 40, /* PLAINTEXT length */ 40, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ { 0x65,0x9c,0x62,0x32,0x11,0xde,0xea,0x0d,0xe3,0x0d,0x2c,0x38,0x18,0x79,0xf4,0xc8 }, /* TAG */ }, { /* index:14 */ 0, /* PLAINTEXT length */ 40, /* AAD length */ { 0 }, /* PLAINTEXT */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ { 0 }, /* CIPHERTEXT */ { 0x7a,0xeb,0x7a,0x69,0xa1,0x68,0x7d,0xd0,0x82,0xca,0x27,0xb0,0xd9,0xa3,0x70,0x96 }, /* TAG */ }, { /* index:15 */ 40, /* PLAINTEXT length */ 0, /* AAD length */ { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */ { 0 }, /* AAD */ { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ { 0x06,0x0c,0x84,0x67,0xf4,0xab,0xab,0x5e,0x8b,0x3c,0x20,0x67,0xa2,0xe1,0x15,0xdc }, /* TAG */ }, }; /* As of RFC 7253 - 'Appendix A. Sample Results' * The next tuple shows a result with a tag length of 96 bits and a different key. K: 0F0E0D0C0B0A09080706050403020100 N: BBAA9988776655443322110D A: 000102030405060708090A0B0C0D0E0F1011121314151617 18191A1B1C1D1E1F2021222324252627 P: 000102030405060708090A0B0C0D0E0F1011121314151617 18191A1B1C1D1E1F2021222324252627 C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1 A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD AC4F02AA The C has been split up in C and T (tag) */ const unsigned char K[] = { 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08, 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 }; const unsigned char N[] = { 0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44, 0x33,0x22,0x11,0x0D }; const unsigned char A[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }; const unsigned char P[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }; const unsigned char C[] = { 0x17,0x92,0xA4,0xE3,0x1E,0x07,0x55,0xFB, 0x03,0xE3,0x1B,0x22,0x11,0x6E,0x6C,0x2D, 0xDF,0x9E,0xFD,0x6E,0x33,0xD5,0x36,0xF1, 0xA0,0x12,0x4B,0x0A,0x55,0xBA,0xE8,0x84, 0xED,0x93,0x48,0x15,0x29,0xC7,0x6B,0x6A }; const unsigned char T[] = { 0xD0,0xC5,0x15,0xF4,0xD1,0xCD,0xD4,0xFD, 0xAC,0x4F,0x02,0xAA }; int err, x, idx, res; unsigned long len; unsigned char outct[MAXBLOCKSIZE] = { 0 }; unsigned char outtag[MAXBLOCKSIZE] = { 0 }; ocb3_state ocb; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { len = 16; /* must be the same as the required taglen */ if ((err = ocb3_encrypt_authenticate_memory(idx, key, sizeof(key), nonce, sizeof(nonce), tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, tests[x].ptlen != 0 ? tests[x].pt : NULL, tests[x].ptlen, tests[x].ptlen != 0 ? outct : NULL, outtag, &len)) != CRYPT_OK) { return err; } if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB3 Tag", x) || compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB3 CT", x)) { return CRYPT_FAIL_TESTVECTOR; } if ((err = ocb3_decrypt_verify_memory(idx, key, sizeof(key), nonce, sizeof(nonce), tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, tests[x].ptlen != 0 ? outct : NULL, tests[x].ptlen, tests[x].ptlen != 0 ? outct : NULL, tests[x].tag, len, &res)) != CRYPT_OK) { return err; } if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB3", x)) { #ifdef LTC_TEST_DBG printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); #endif return CRYPT_FAIL_TESTVECTOR; } } /* RFC 7253 - test vector with a tag length of 96 bits - part 1 */ x = 99; len = 12; if ((err = ocb3_encrypt_authenticate_memory(idx, K, sizeof(K), N, sizeof(N), A, sizeof(A), P, sizeof(P), outct, outtag, &len)) != CRYPT_OK) { return err; } if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag", x) || compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) { return CRYPT_FAIL_TESTVECTOR; } if ((err = ocb3_decrypt_verify_memory(idx, K, sizeof(K), N, sizeof(N), A, sizeof(A), C, sizeof(C), outct, T, sizeof(T), &res)) != CRYPT_OK) { return err; } if ((res != 1) || compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3", x)) { #ifdef LTC_TEST_DBG printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); #endif return CRYPT_FAIL_TESTVECTOR; } /* RFC 7253 - test vector with a tag length of 96 bits - part 2 */ x = 100; if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; if ((err = ocb3_encrypt(&ocb, P, 32, outct)) != CRYPT_OK) return err; if ((err = ocb3_encrypt_last(&ocb, P+32, sizeof(P)-32, outct+32)) != CRYPT_OK) return err; len = sizeof(outtag); /* intentionally more than 12 */ if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; if (compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.enc", x)) return CRYPT_FAIL_TESTVECTOR; if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; if ((err = ocb3_decrypt(&ocb, C, 32, outct)) != CRYPT_OK) return err; if ((err = ocb3_decrypt_last(&ocb, C+32, sizeof(C)-32, outct+32)) != CRYPT_OK) return err; len = sizeof(outtag); /* intentionally more than 12 */ if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; if (compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3 PT", x)) return CRYPT_FAIL_TESTVECTOR; if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.dec", x)) return CRYPT_FAIL_TESTVECTOR; return CRYPT_OK; #endif /* LTC_TEST */ } #endif /* LTC_OCB3_MODE */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/000077500000000000000000000000001464416617300214575ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/blake2b.c000066400000000000000000000451761464416617300231420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* BLAKE2 reference source code package - reference C implementations Copyright 2012, Samuel Neves . You may use this under the terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at your option. The terms of these licenses can be found at: - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - OpenSSL license : https://www.openssl.org/source/license.html - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 More information about the BLAKE2 hash function can be found at https://blake2.net. */ /* see also https://www.ietf.org/rfc/rfc7693.txt */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2B enum blake2b_constant { BLAKE2B_BLOCKBYTES = 128, BLAKE2B_OUTBYTES = 64, BLAKE2B_KEYBYTES = 64, BLAKE2B_SALTBYTES = 16, BLAKE2B_PERSONALBYTES = 16, BLAKE2B_PARAM_SIZE = 64 }; /* param offsets */ enum { O_DIGEST_LENGTH = 0, O_KEY_LENGTH = 1, O_FANOUT = 2, O_DEPTH = 3, O_LEAF_LENGTH = 4, O_NODE_OFFSET = 8, O_XOF_LENGTH = 12, O_NODE_DEPTH = 16, O_INNER_LENGTH = 17, O_RESERVED = 18, O_SALT = 32, O_PERSONAL = 48 }; /* struct blake2b_param { unsigned char digest_length; unsigned char key_length; unsigned char fanout; unsigned char depth; ulong32 leaf_length; ulong32 node_offset; ulong32 xof_length; unsigned char node_depth; unsigned char inner_length; unsigned char reserved[14]; unsigned char salt[BLAKE2B_SALTBYTES]; unsigned char personal[BLAKE2B_PERSONALBYTES]; }; */ const struct ltc_hash_descriptor blake2b_160_desc = { "blake2b-160", 25, 20, 128, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 }, 11, &blake2b_160_init, &blake2b_process, &blake2b_done, &blake2b_160_test, NULL }; const struct ltc_hash_descriptor blake2b_256_desc = { "blake2b-256", 26, 32, 128, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 }, 11, &blake2b_256_init, &blake2b_process, &blake2b_done, &blake2b_256_test, NULL }; const struct ltc_hash_descriptor blake2b_384_desc = { "blake2b-384", 27, 48, 128, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 }, 11, &blake2b_384_init, &blake2b_process, &blake2b_done, &blake2b_384_test, NULL }; const struct ltc_hash_descriptor blake2b_512_desc = { "blake2b-512", 28, 64, 128, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 }, 11, &blake2b_512_init, &blake2b_process, &blake2b_done, &blake2b_512_test, NULL }; static const ulong64 blake2b_IV[8] = { CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b), CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1), CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f), CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179) }; static const unsigned char blake2b_sigma[12][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } }; static void s_blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); } /* Some helper functions, not necessarily useful */ static int s_blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; } static void s_blake2b_set_lastblock(hash_state *md) { if (md->blake2b.last_node) { s_blake2b_set_lastnode(md); } md->blake2b.f[0] = CONST64(0xffffffffffffffff); } static void s_blake2b_increment_counter(hash_state *md, ulong64 inc) { md->blake2b.t[0] += inc; if (md->blake2b.t[0] < inc) md->blake2b.t[1]++; } static void s_blake2b_init0(hash_state *md) { unsigned long i; XMEMSET(&md->blake2b, 0, sizeof(md->blake2b)); for (i = 0; i < 8; ++i) { md->blake2b.h[i] = blake2b_IV[i]; } } /* init xors IV with input parameter block */ static int s_blake2b_init_param(hash_state *md, const unsigned char *P) { unsigned long i; s_blake2b_init0(md); /* IV XOR ParamBlock */ for (i = 0; i < 8; ++i) { ulong64 tmp; LOAD64L(tmp, P + i * 8); md->blake2b.h[i] ^= tmp; } md->blake2b.outlen = P[O_DIGEST_LENGTH]; return CRYPT_OK; } /** Initialize the hash/MAC state Use this function to init for arbitrary sizes. Give a key and keylen to init for MAC mode. @param md The hash state you wish to initialize @param outlen The desired output-length @param key The key of the MAC @param keylen The length of the key @return CRYPT_OK if successful */ int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) { unsigned char P[BLAKE2B_PARAM_SIZE]; int err; LTC_ARGCHK(md != NULL); if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { return CRYPT_INVALID_ARG; } if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) { return CRYPT_INVALID_ARG; } XMEMSET(P, 0, sizeof(P)); P[O_DIGEST_LENGTH] = (unsigned char)outlen; P[O_KEY_LENGTH] = (unsigned char)keylen; P[O_FANOUT] = 1; P[O_DEPTH] = 1; err = s_blake2b_init_param(md, P); if (err != CRYPT_OK) return err; if (key) { unsigned char block[BLAKE2B_BLOCKBYTES]; XMEMSET(block, 0, BLAKE2B_BLOCKBYTES); XMEMCPY(block, key, keylen); blake2b_process(md, block, BLAKE2B_BLOCKBYTES); #ifdef LTC_CLEAN_STACK zeromem(block, sizeof(block)); #endif } return CRYPT_OK; } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, NULL, 0); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); } #define G(r, i, a, b, c, d) \ do { \ a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ d = ROR64(d ^ a, 32); \ c = c + d; \ b = ROR64(b ^ c, 24); \ a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ d = ROR64(d ^ a, 16); \ c = c + d; \ b = ROR64(b ^ c, 63); \ } while (0) #define ROUND(r) \ do { \ G(r, 0, v[0], v[4], v[8], v[12]); \ G(r, 1, v[1], v[5], v[9], v[13]); \ G(r, 2, v[2], v[6], v[10], v[14]); \ G(r, 3, v[3], v[7], v[11], v[15]); \ G(r, 4, v[0], v[5], v[10], v[15]); \ G(r, 5, v[1], v[6], v[11], v[12]); \ G(r, 6, v[2], v[7], v[8], v[13]); \ G(r, 7, v[3], v[4], v[9], v[14]); \ } while (0) #ifdef LTC_CLEAN_STACK static int ss_blake2b_compress(hash_state *md, const unsigned char *buf) #else static int s_blake2b_compress(hash_state *md, const unsigned char *buf) #endif { ulong64 m[16]; ulong64 v[16]; unsigned long i; for (i = 0; i < 16; ++i) { LOAD64L(m[i], buf + i * sizeof(m[i])); } for (i = 0; i < 8; ++i) { v[i] = md->blake2b.h[i]; } v[8] = blake2b_IV[0]; v[9] = blake2b_IV[1]; v[10] = blake2b_IV[2]; v[11] = blake2b_IV[3]; v[12] = blake2b_IV[4] ^ md->blake2b.t[0]; v[13] = blake2b_IV[5] ^ md->blake2b.t[1]; v[14] = blake2b_IV[6] ^ md->blake2b.f[0]; v[15] = blake2b_IV[7] ^ md->blake2b.f[1]; ROUND(0); ROUND(1); ROUND(2); ROUND(3); ROUND(4); ROUND(5); ROUND(6); ROUND(7); ROUND(8); ROUND(9); ROUND(10); ROUND(11); for (i = 0; i < 8; ++i) { md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8]; } return CRYPT_OK; } #undef G #undef ROUND #ifdef LTC_CLEAN_STACK static int s_blake2b_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_blake2b_compress(md, buf); burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long)); return err; } #endif /** Process a block of memory through the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen) { LTC_ARGCHK(md != NULL); LTC_ARGCHK(in != NULL); if (md->blake2b.curlen > sizeof(md->blake2b.buf)) { return CRYPT_INVALID_ARG; } if (inlen > 0) { unsigned long left = md->blake2b.curlen; unsigned long fill = BLAKE2B_BLOCKBYTES - left; if (inlen > fill) { md->blake2b.curlen = 0; XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */ s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); s_blake2b_compress(md, md->blake2b.buf); /* Compress */ in += fill; inlen -= fill; while (inlen > BLAKE2B_BLOCKBYTES) { s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); s_blake2b_compress(md, in); in += BLAKE2B_BLOCKBYTES; inlen -= BLAKE2B_BLOCKBYTES; } } XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen); md->blake2b.curlen += inlen; } return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (size depending on the length used on init) @return CRYPT_OK if successful */ int blake2b_done(hash_state *md, unsigned char *out) { unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 }; unsigned long i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */ if (s_blake2b_is_lastblock(md)) { return CRYPT_ERROR; } s_blake2b_increment_counter(md, md->blake2b.curlen); s_blake2b_set_lastblock(md); XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */ s_blake2b_compress(md, md->blake2b.buf); for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ STORE64L(md->blake2b.h[i], buffer + i * 8); } XMEMCPY(out, buffer, md->blake2b.outlen); zeromem(md, sizeof(hash_state)); #ifdef LTC_CLEAN_STACK zeromem(buffer, sizeof(buffer)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2b_512_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[64]; } tests[] = { { "", { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72, 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61, 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19, 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b, 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } }, { "abc", { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9, 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7, 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95, 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a, 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } }, { NULL, { 0 } } }; int i; unsigned char tmp[64]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2b_512_init(&md); blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2b_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2b_384_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[48]; } tests[] = { { "", { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d, 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5, 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a, 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24, 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73, 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } }, { "abc", { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26, 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb, 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd, 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6, 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d, 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } }, { NULL, { 0 } } }; int i; unsigned char tmp[48]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2b_384_init(&md); blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2b_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2b_256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[32]; } tests[] = { { "", { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2, 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1, 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87, 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } }, { "abc", { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72, 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b, 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42, 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } }, { "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890", { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08, 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41, 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3, 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } }, { NULL, { 0 } } }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2b_256_init(&md); blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2b_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2b_160_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[20]; } tests[] = { { "", { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18, 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41, 0x79, 0x0b, 0x6c, 0xf2 } }, { "abc", { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36, 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc, 0x68, 0xb6, 0x84, 0x6b } }, { NULL, { 0 } } }; int i; unsigned char tmp[20]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2b_160_init(&md); blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2b_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/blake2s.c000066400000000000000000000424251464416617300231550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* BLAKE2 reference source code package - reference C implementations Copyright 2012, Samuel Neves . You may use this under the terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at your option. The terms of these licenses can be found at: - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 - OpenSSL license : https://www.openssl.org/source/license.html - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 More information about the BLAKE2 hash function can be found at https://blake2.net. */ /* see also https://www.ietf.org/rfc/rfc7693.txt */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2S enum blake2s_constant { BLAKE2S_BLOCKBYTES = 64, BLAKE2S_OUTBYTES = 32, BLAKE2S_KEYBYTES = 32, BLAKE2S_SALTBYTES = 8, BLAKE2S_PERSONALBYTES = 8, BLAKE2S_PARAM_SIZE = 32 }; /* param offsets */ enum { O_DIGEST_LENGTH = 0, O_KEY_LENGTH = 1, O_FANOUT = 2, O_DEPTH = 3, O_LEAF_LENGTH = 4, O_NODE_OFFSET = 8, O_XOF_LENGTH = 12, O_NODE_DEPTH = 14, O_INNER_LENGTH = 15, O_SALT = 16, O_PERSONAL = 24 }; /* struct blake2s_param { unsigned char digest_length; unsigned char key_length; unsigned char fanout; unsigned char depth; ulong32 leaf_length; ulong32 node_offset; ushort16 xof_length; unsigned char node_depth; unsigned char inner_length; unsigned char salt[BLAKE2S_SALTBYTES]; unsigned char personal[BLAKE2S_PERSONALBYTES]; }; */ const struct ltc_hash_descriptor blake2s_128_desc = { "blake2s-128", 21, 16, 64, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 }, 11, &blake2s_128_init, &blake2s_process, &blake2s_done, &blake2s_128_test, NULL }; const struct ltc_hash_descriptor blake2s_160_desc = { "blake2s-160", 22, 20, 64, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 }, 11, &blake2s_160_init, &blake2s_process, &blake2s_done, &blake2s_160_test, NULL }; const struct ltc_hash_descriptor blake2s_224_desc = { "blake2s-224", 23, 28, 64, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 }, 11, &blake2s_224_init, &blake2s_process, &blake2s_done, &blake2s_224_test, NULL }; const struct ltc_hash_descriptor blake2s_256_desc = { "blake2s-256", 24, 32, 64, { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 }, 11, &blake2s_256_init, &blake2s_process, &blake2s_done, &blake2s_256_test, NULL }; static const ulong32 blake2s_IV[8] = { 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL }; static const unsigned char blake2s_sigma[10][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, }; static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; } /* Some helper functions, not necessarily useful */ static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; } static void s_blake2s_set_lastblock(hash_state *md) { if (md->blake2s.last_node) { s_blake2s_set_lastnode(md); } md->blake2s.f[0] = 0xffffffffUL; } static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc) { md->blake2s.t[0] += inc; if (md->blake2s.t[0] < inc) md->blake2s.t[1]++; } static int s_blake2s_init0(hash_state *md) { int i; XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state)); for (i = 0; i < 8; ++i) { md->blake2s.h[i] = blake2s_IV[i]; } return CRYPT_OK; } /* init2 xors IV with input parameter block */ static int s_blake2s_init_param(hash_state *md, const unsigned char *P) { unsigned long i; s_blake2s_init0(md); /* IV XOR ParamBlock */ for (i = 0; i < 8; ++i) { ulong32 tmp; LOAD32L(tmp, P + i * 4); md->blake2s.h[i] ^= tmp; } md->blake2s.outlen = P[O_DIGEST_LENGTH]; return CRYPT_OK; } /** Initialize the hash/MAC state Use this function to init for arbitrary sizes. Give a key and keylen to init for MAC mode. @param md The hash state you wish to initialize @param outlen The desired output-length @param key The key of the MAC @param keylen The length of the key @return CRYPT_OK if successful */ int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) { unsigned char P[BLAKE2S_PARAM_SIZE]; int err; LTC_ARGCHK(md != NULL); if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) { return CRYPT_INVALID_ARG; } if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) { return CRYPT_INVALID_ARG; } XMEMSET(P, 0, sizeof(P)); P[O_DIGEST_LENGTH] = (unsigned char)outlen; P[O_KEY_LENGTH] = (unsigned char)keylen; P[O_FANOUT] = 1; P[O_DEPTH] = 1; err = s_blake2s_init_param(md, P); if (err != CRYPT_OK) return err; if (key) { unsigned char block[BLAKE2S_BLOCKBYTES]; XMEMSET(block, 0, BLAKE2S_BLOCKBYTES); XMEMCPY(block, key, keylen); blake2s_process(md, block, BLAKE2S_BLOCKBYTES); #ifdef LTC_CLEAN_STACK zeromem(block, sizeof(block)); #endif } return CRYPT_OK; } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); } #define G(r, i, a, b, c, d) \ do { \ a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \ d = ROR(d ^ a, 16); \ c = c + d; \ b = ROR(b ^ c, 12); \ a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \ d = ROR(d ^ a, 8); \ c = c + d; \ b = ROR(b ^ c, 7); \ } while (0) #define ROUND(r) \ do { \ G(r, 0, v[0], v[4], v[8], v[12]); \ G(r, 1, v[1], v[5], v[9], v[13]); \ G(r, 2, v[2], v[6], v[10], v[14]); \ G(r, 3, v[3], v[7], v[11], v[15]); \ G(r, 4, v[0], v[5], v[10], v[15]); \ G(r, 5, v[1], v[6], v[11], v[12]); \ G(r, 6, v[2], v[7], v[8], v[13]); \ G(r, 7, v[3], v[4], v[9], v[14]); \ } while (0) #ifdef LTC_CLEAN_STACK static int ss_blake2s_compress(hash_state *md, const unsigned char *buf) #else static int s_blake2s_compress(hash_state *md, const unsigned char *buf) #endif { unsigned long i; ulong32 m[16]; ulong32 v[16]; for (i = 0; i < 16; ++i) { LOAD32L(m[i], buf + i * sizeof(m[i])); } for (i = 0; i < 8; ++i) { v[i] = md->blake2s.h[i]; } v[8] = blake2s_IV[0]; v[9] = blake2s_IV[1]; v[10] = blake2s_IV[2]; v[11] = blake2s_IV[3]; v[12] = md->blake2s.t[0] ^ blake2s_IV[4]; v[13] = md->blake2s.t[1] ^ blake2s_IV[5]; v[14] = md->blake2s.f[0] ^ blake2s_IV[6]; v[15] = md->blake2s.f[1] ^ blake2s_IV[7]; ROUND(0); ROUND(1); ROUND(2); ROUND(3); ROUND(4); ROUND(5); ROUND(6); ROUND(7); ROUND(8); ROUND(9); for (i = 0; i < 8; ++i) { md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8]; } return CRYPT_OK; } #undef G #undef ROUND #ifdef LTC_CLEAN_STACK static int s_blake2s_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_blake2s_compress(md, buf); burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long)); return err; } #endif /** Process a block of memory through the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen) { LTC_ARGCHK(md != NULL); LTC_ARGCHK(in != NULL); if (md->blake2s.curlen > sizeof(md->blake2s.buf)) { return CRYPT_INVALID_ARG; } if (inlen > 0) { unsigned long left = md->blake2s.curlen; unsigned long fill = BLAKE2S_BLOCKBYTES - left; if (inlen > fill) { md->blake2s.curlen = 0; XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */ s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); s_blake2s_compress(md, md->blake2s.buf); /* Compress */ in += fill; inlen -= fill; while (inlen > BLAKE2S_BLOCKBYTES) { s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); s_blake2s_compress(md, in); in += BLAKE2S_BLOCKBYTES; inlen -= BLAKE2S_BLOCKBYTES; } } XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen); md->blake2s.curlen += inlen; } return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (size depending on the length used on init) @return CRYPT_OK if successful */ int blake2s_done(hash_state *md, unsigned char *out) { unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 }; unsigned long i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */ if (s_blake2s_is_lastblock(md)) { return CRYPT_ERROR; } s_blake2s_increment_counter(md, md->blake2s.curlen); s_blake2s_set_lastblock(md); XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */ s_blake2s_compress(md, md->blake2s.buf); for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ STORE32L(md->blake2s.h[i], buffer + i * 4); } XMEMCPY(out, buffer, md->blake2s.outlen); zeromem(md, sizeof(hash_state)); #ifdef LTC_CLEAN_STACK zeromem(buffer, sizeof(buffer)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2s_256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[32]; } tests[] = { { "", { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94, 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c, 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e, 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } }, { "abc", { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2, 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f, 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29, 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } }, { "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890" "12345678901234567890123456789012345678901234567890", { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41, 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41, 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70, 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } }, { NULL, { 0 } } }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2s_256_init(&md); blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2s_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2s_224_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[28]; } tests[] = { { "", { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37, 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63, 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34, 0xe7, 0xbc, 0x1e, 0xf4 } }, { "abc", { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd, 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c, 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87, 0x40, 0x7f, 0xbd, 0x55 } }, { NULL, { 0 } } }; int i; unsigned char tmp[28]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2s_224_init(&md); blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2s_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2s_160_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[20]; } tests[] = { { "", { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24, 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42, 0x9c, 0x34, 0x91, 0x6f} }, { "abc", { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83, 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04, 0x38, 0xf8, 0xde, 0x17 } }, { NULL, { 0 } } }; int i; unsigned char tmp[20]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2s_160_init(&md); blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2s_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int blake2s_128_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[16]; } tests[] = { { "", { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01, 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } }, { "abc", { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8, 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } }, { NULL, { 0 } } }; int i; unsigned char tmp[16]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { blake2s_128_init(&md); blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); blake2s_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/chc/000077500000000000000000000000001464416617300222145ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/chc/chc.c000066400000000000000000000171041464416617300231200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file chc.c CHC support. (Tom St Denis) */ #ifdef LTC_CHC_HASH #define UNDEFED_HASH -17 /* chc settings */ static int cipher_idx=UNDEFED_HASH, /* which cipher */ cipher_blocksize; /* blocksize of cipher */ const struct ltc_hash_descriptor chc_desc = { "chc_hash", 12, 0, 0, { 0 }, 0, &chc_init, &chc_process, &chc_done, &chc_test, NULL }; /** Initialize the CHC state with a given cipher @param cipher The index of the cipher you wish to bind @return CRYPT_OK if successful */ int chc_register(int cipher) { int err, kl, idx; if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* will it be valid? */ kl = cipher_descriptor[cipher]->block_length; /* must be >64 bit block */ if (kl <= 8) { return CRYPT_INVALID_CIPHER; } /* can we use the ideal keysize? */ if ((err = cipher_descriptor[cipher]->keysize(&kl)) != CRYPT_OK) { return err; } /* we require that key size == block size be a valid choice */ if (kl != cipher_descriptor[cipher]->block_length) { return CRYPT_INVALID_CIPHER; } /* determine if chc_hash has been register_hash'ed already */ if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) { return err; } /* store into descriptor */ hash_descriptor[idx]->hashsize = hash_descriptor[idx]->blocksize = cipher_descriptor[cipher]->block_length; /* store the idx and block size */ cipher_idx = cipher; cipher_blocksize = cipher_descriptor[cipher]->block_length; return CRYPT_OK; } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int chc_init(hash_state *md) { symmetric_key *key; unsigned char buf[MAXBLOCKSIZE]; int err; LTC_ARGCHK(md != NULL); /* is the cipher valid? */ if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { return err; } if (cipher_blocksize != cipher_descriptor[cipher_idx]->block_length) { return CRYPT_INVALID_CIPHER; } if ((key = XMALLOC(sizeof(*key))) == NULL) { return CRYPT_MEM; } /* zero key and what not */ zeromem(buf, cipher_blocksize); if ((err = cipher_descriptor[cipher_idx]->setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) { XFREE(key); return err; } /* encrypt zero block */ cipher_descriptor[cipher_idx]->ecb_encrypt(buf, md->chc.state, key); /* zero other members */ md->chc.length = 0; md->chc.curlen = 0; zeromem(md->chc.buf, sizeof(md->chc.buf)); XFREE(key); return CRYPT_OK; } /* key <= state T0,T1 <= block T0 <= encrypt T0 state <= state xor T0 xor T1 */ static int s_chc_compress(hash_state *md, const unsigned char *buf) { unsigned char T[2][MAXBLOCKSIZE]; symmetric_key *key; int err, x; if ((key = XMALLOC(sizeof(*key))) == NULL) { return CRYPT_MEM; } if ((err = cipher_descriptor[cipher_idx]->setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) { XFREE(key); return err; } XMEMCPY(T[1], buf, cipher_blocksize); cipher_descriptor[cipher_idx]->ecb_encrypt(buf, T[0], key); for (x = 0; x < cipher_blocksize; x++) { md->chc.state[x] ^= T[0][x] ^ T[1][x]; } #ifdef LTC_CLEAN_STACK zeromem(T, sizeof(T)); zeromem(key, sizeof(*key)); #endif XFREE(key); return CRYPT_OK; } /** Function for processing blocks @param md The hash state @param buf The data to hash @param len The length of the data (octets) @return CRYPT_OK if successful */ static int ss_chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); static HASH_PROCESS(ss_chc_process, s_chc_compress, chc, (unsigned long)cipher_blocksize) /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen) { int err; LTC_ARGCHK(md != NULL); LTC_ARGCHK(in != NULL); /* is the cipher valid? */ if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { return err; } if (cipher_blocksize != cipher_descriptor[cipher_idx]->block_length) { return CRYPT_INVALID_CIPHER; } return ss_chc_process(md, in, inlen); } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (length of the block size of the block cipher) @return CRYPT_OK if successful */ int chc_done(hash_state *md, unsigned char *out) { int err; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); /* is the cipher valid? */ if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { return err; } if (cipher_blocksize != cipher_descriptor[cipher_idx]->block_length) { return CRYPT_INVALID_CIPHER; } if (md->chc.curlen >= sizeof(md->chc.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->chc.length += md->chc.curlen * 8; /* append the '1' bit */ md->chc.buf[md->chc.curlen++] = (unsigned char)0x80; /* if the length is currently above l-8 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) { while (md->chc.curlen < (unsigned long)cipher_blocksize) { md->chc.buf[md->chc.curlen++] = (unsigned char)0; } s_chc_compress(md, md->chc.buf); md->chc.curlen = 0; } /* pad upto l-8 bytes of zeroes */ while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) { md->chc.buf[md->chc.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8)); s_chc_compress(md, md->chc.buf); /* copy output */ XMEMCPY(out, md->chc.state, cipher_blocksize); #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int chc_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char *msg, hash[MAXBLOCKSIZE]; int len; } tests[] = { { (unsigned char *)"hello world", { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61, 0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e }, 16 } }; int i, oldhashidx, idx, err; unsigned char tmp[MAXBLOCKSIZE]; hash_state md; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } oldhashidx = cipher_idx; chc_register(idx); for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { if ((err = chc_init(&md)) != CRYPT_OK) { return err; } if ((err = chc_process(&md, tests[i].msg, XSTRLEN((char *)tests[i].msg))) != CRYPT_OK) { return err; } if ((err = chc_done(&md, tmp)) != CRYPT_OK) { return err; } if (compare_testvector(tmp, tests[i].len, tests[i].hash, tests[i].len, "CHC", i)) { return CRYPT_FAIL_TESTVECTOR; } } if (oldhashidx != UNDEFED_HASH) { chc_register(oldhashidx); } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/helper/000077500000000000000000000000001464416617300227365ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/helper/hash_file.c000066400000000000000000000020061464416617300250220ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifndef LTC_NO_FILE /** @file hash_file.c Hash a file, Tom St Denis */ /** @param hash The index of the hash desired @param fname The name of the file you wish to hash @param out [out] The destination of the digest @param outlen [in/out] The max size and resulting size of the message digest @result CRYPT_OK if successful */ int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) { FILE *in; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } in = fopen(fname, "rb"); if (in == NULL) { return CRYPT_FILE_NOTFOUND; } err = hash_filehandle(hash, in, out, outlen); if (fclose(in) != 0) { return CRYPT_ERROR; } return err; } #endif /* #ifndef LTC_NO_FILE */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/helper/hash_filehandle.c000066400000000000000000000032711464416617300262030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifndef LTC_NO_FILE /** @file hash_filehandle.c Hash open files, Tom St Denis */ /** Hash data from an open file handle. @param hash The index of the hash you want to use @param in The FILE* handle of the file you want to hash @param out [out] The destination of the digest @param outlen [in/out] The max size and resulting size of the digest @result CRYPT_OK if successful */ int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) { hash_state md; unsigned char *buf; size_t x; int err; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(in != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = hash_is_valid(hash)) != CRYPT_OK) { goto LBL_ERR; } if (*outlen < hash_descriptor[hash]->hashsize) { *outlen = hash_descriptor[hash]->hashsize; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } if ((err = hash_descriptor[hash]->init(&md)) != CRYPT_OK) { goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = hash_descriptor[hash]->process(&md, buf, (unsigned long)x)) != CRYPT_OK) { goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if ((err = hash_descriptor[hash]->done(&md, out)) == CRYPT_OK) { *outlen = hash_descriptor[hash]->hashsize; } LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: XFREE(buf); return err; } #endif /* #ifndef LTC_NO_FILE */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/helper/hash_memory.c000066400000000000000000000030551464416617300254200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_HASH_HELPERS /** @file hash_memory.c Hash memory helper, Tom St Denis */ /** Hash a block of memory and store the digest. @param hash The index of the hash you wish to use @param in The data you wish to hash @param inlen The length of the data to hash (octets) @param out [out] Where to store the digest @param outlen [in/out] Max size and resulting size of the digest @return CRYPT_OK if successful */ int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { hash_state *md; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (*outlen < hash_descriptor[hash]->hashsize) { *outlen = hash_descriptor[hash]->hashsize; return CRYPT_BUFFER_OVERFLOW; } md = XMALLOC(sizeof(hash_state)); if (md == NULL) { return CRYPT_MEM; } if ((err = hash_descriptor[hash]->init(md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash]->process(md, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } err = hash_descriptor[hash]->done(md, out); *outlen = hash_descriptor[hash]->hashsize; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif XFREE(md); return err; } #endif /* #ifdef LTC_HASH_HELPERS */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/helper/hash_memory_multi.c000066400000000000000000000042361464416617300266340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include #ifdef LTC_HASH_HELPERS /** @file hash_memory_multi.c Hash (multiple buffers) memory helper, Tom St Denis */ /** Hash multiple (non-adjacent) blocks of memory at once. @param hash The index of the hash you wish to use @param out [out] Where to store the digest @param outlen [in/out] Max size and resulting size of the digest @param in The data you wish to hash @param inlen The length of the data to hash (octets) @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { hash_state *md; int err; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (*outlen < hash_descriptor[hash]->hashsize) { *outlen = hash_descriptor[hash]->hashsize; return CRYPT_BUFFER_OVERFLOW; } md = XMALLOC(sizeof(hash_state)); if (md == NULL) { return CRYPT_MEM; } if ((err = hash_descriptor[hash]->init(md)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = hash_descriptor[hash]->process(md, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } err = hash_descriptor[hash]->done(md, out); *outlen = hash_descriptor[hash]->hashsize; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif XFREE(md); va_end(args); return err; } #endif /* #ifdef LTC_HASH_HELPERS */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/md2.c000066400000000000000000000144341464416617300223130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @param md2.c LTC_MD2 (RFC 1319) hash function implementation by Tom St Denis */ #ifdef LTC_MD2 const struct ltc_hash_descriptor md2_desc = { "md2", 7, 16, 16, /* OID */ { 1, 2, 840, 113549, 2, 2, }, 6, &md2_init, &md2_process, &md2_done, &md2_test, NULL }; static const unsigned char PI_SUBST[256] = { 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 }; /* adds 16 bytes to the checksum */ static void s_md2_update_chksum(hash_state *md) { int j; unsigned char L; L = md->md2.chksum[15]; for (j = 0; j < 16; j++) { /* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say otherwise. */ L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255); } } static void s_md2_compress(hash_state *md) { int j, k; unsigned char t; /* copy block */ for (j = 0; j < 16; j++) { md->md2.X[16+j] = md->md2.buf[j]; md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j]; } t = (unsigned char)0; /* do 18 rounds */ for (j = 0; j < 18; j++) { for (k = 0; k < 48; k++) { t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]); } t = (t + (unsigned char)j) & 255; } } /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int md2_init(hash_state *md) { LTC_ARGCHK(md != NULL); /* LTC_MD2 uses a zero'ed state... */ zeromem(md->md2.X, sizeof(md->md2.X)); zeromem(md->md2.chksum, sizeof(md->md2.chksum)); zeromem(md->md2.buf, sizeof(md->md2.buf)); md->md2.curlen = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen) { unsigned long n; LTC_ARGCHK(md != NULL); LTC_ARGCHK(in != NULL); if (md-> md2 .curlen > sizeof(md-> md2 .buf)) { return CRYPT_INVALID_ARG; } while (inlen > 0) { n = MIN(inlen, (16 - md->md2.curlen)); XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n); md->md2.curlen += n; in += n; inlen -= n; /* is 16 bytes full? */ if (md->md2.curlen == 16) { s_md2_compress(md); s_md2_update_chksum(md); md->md2.curlen = 0; } } return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int md2_done(hash_state * md, unsigned char *out) { unsigned long i, k; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->md2.curlen >= sizeof(md->md2.buf)) { return CRYPT_INVALID_ARG; } /* pad the message */ k = 16 - md->md2.curlen; for (i = md->md2.curlen; i < 16; i++) { md->md2.buf[i] = (unsigned char)k; } /* hash and update */ s_md2_compress(md); s_md2_update_chksum(md); /* hash checksum */ XMEMCPY(md->md2.buf, md->md2.chksum, 16); s_md2_compress(md); /* output is lower 16 bytes of X */ XMEMCPY(out, md->md2.X, 16); #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int md2_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[16]; } tests[] = { { "", {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d, 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73 } }, { "a", {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72, 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1 } }, { "message digest", {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b, 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0 } }, { "abcdefghijklmnopqrstuvwxyz", {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab, 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39, 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd } }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d, 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8 } } }; int i; unsigned char tmp[16]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { md2_init(&md); md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); md2_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/md4.c000066400000000000000000000201331464416617300223060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @param md4.c Submitted by Dobes Vandermeer (dobes@smartt.com) */ #ifdef LTC_MD4 const struct ltc_hash_descriptor md4_desc = { "md4", 6, 16, 64, /* OID */ { 1, 2, 840, 113549, 2, 4, }, 6, &md4_init, &md4_process, &md4_done, &md4_test, NULL }; #define S11 3 #define S12 7 #define S13 11 #define S14 19 #define S21 3 #define S22 5 #define S23 9 #define S24 13 #define S31 3 #define S32 9 #define S33 11 #define S34 15 /* F, G and H are basic LTC_MD4 functions. */ #define F(x, y, z) (z ^ (x & (y ^ z))) #define G(x, y, z) ((x & y) | (z & (x | y))) #define H(x, y, z) ((x) ^ (y) ^ (z)) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) ROLc(x, n) /* FF, GG and HH are transformations for rounds 1, 2 and 3 */ /* Rotation is separate from addition to prevent recomputation */ #define FF(a, b, c, d, x, s) { \ (a) += F ((b), (c), (d)) + (x); \ (a) = ROTATE_LEFT ((a), (s)); \ } #define GG(a, b, c, d, x, s) { \ (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \ (a) = ROTATE_LEFT ((a), (s)); \ } #define HH(a, b, c, d, x, s) { \ (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \ (a) = ROTATE_LEFT ((a), (s)); \ } #ifdef LTC_CLEAN_STACK static int ss_md4_compress(hash_state *md, const unsigned char *buf) #else static int s_md4_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 x[16], a, b, c, d; int i; /* copy state */ a = md->md4.state[0]; b = md->md4.state[1]; c = md->md4.state[2]; d = md->md4.state[3]; /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32L(x[i], buf + (4*i)); } /* Round 1 */ FF (a, b, c, d, x[ 0], S11); /* 1 */ FF (d, a, b, c, x[ 1], S12); /* 2 */ FF (c, d, a, b, x[ 2], S13); /* 3 */ FF (b, c, d, a, x[ 3], S14); /* 4 */ FF (a, b, c, d, x[ 4], S11); /* 5 */ FF (d, a, b, c, x[ 5], S12); /* 6 */ FF (c, d, a, b, x[ 6], S13); /* 7 */ FF (b, c, d, a, x[ 7], S14); /* 8 */ FF (a, b, c, d, x[ 8], S11); /* 9 */ FF (d, a, b, c, x[ 9], S12); /* 10 */ FF (c, d, a, b, x[10], S13); /* 11 */ FF (b, c, d, a, x[11], S14); /* 12 */ FF (a, b, c, d, x[12], S11); /* 13 */ FF (d, a, b, c, x[13], S12); /* 14 */ FF (c, d, a, b, x[14], S13); /* 15 */ FF (b, c, d, a, x[15], S14); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 0], S21); /* 17 */ GG (d, a, b, c, x[ 4], S22); /* 18 */ GG (c, d, a, b, x[ 8], S23); /* 19 */ GG (b, c, d, a, x[12], S24); /* 20 */ GG (a, b, c, d, x[ 1], S21); /* 21 */ GG (d, a, b, c, x[ 5], S22); /* 22 */ GG (c, d, a, b, x[ 9], S23); /* 23 */ GG (b, c, d, a, x[13], S24); /* 24 */ GG (a, b, c, d, x[ 2], S21); /* 25 */ GG (d, a, b, c, x[ 6], S22); /* 26 */ GG (c, d, a, b, x[10], S23); /* 27 */ GG (b, c, d, a, x[14], S24); /* 28 */ GG (a, b, c, d, x[ 3], S21); /* 29 */ GG (d, a, b, c, x[ 7], S22); /* 30 */ GG (c, d, a, b, x[11], S23); /* 31 */ GG (b, c, d, a, x[15], S24); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 0], S31); /* 33 */ HH (d, a, b, c, x[ 8], S32); /* 34 */ HH (c, d, a, b, x[ 4], S33); /* 35 */ HH (b, c, d, a, x[12], S34); /* 36 */ HH (a, b, c, d, x[ 2], S31); /* 37 */ HH (d, a, b, c, x[10], S32); /* 38 */ HH (c, d, a, b, x[ 6], S33); /* 39 */ HH (b, c, d, a, x[14], S34); /* 40 */ HH (a, b, c, d, x[ 1], S31); /* 41 */ HH (d, a, b, c, x[ 9], S32); /* 42 */ HH (c, d, a, b, x[ 5], S33); /* 43 */ HH (b, c, d, a, x[13], S34); /* 44 */ HH (a, b, c, d, x[ 3], S31); /* 45 */ HH (d, a, b, c, x[11], S32); /* 46 */ HH (c, d, a, b, x[ 7], S33); /* 47 */ HH (b, c, d, a, x[15], S34); /* 48 */ /* Update our state */ md->md4.state[0] = md->md4.state[0] + a; md->md4.state[1] = md->md4.state[1] + b; md->md4.state[2] = md->md4.state[2] + c; md->md4.state[3] = md->md4.state[3] + d; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_md4_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_md4_compress(md, buf); burn_stack(sizeof(ulong32) * 20 + sizeof(int)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int md4_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->md4.state[0] = 0x67452301UL; md->md4.state[1] = 0xefcdab89UL; md->md4.state[2] = 0x98badcfeUL; md->md4.state[3] = 0x10325476UL; md->md4.length = 0; md->md4.curlen = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(md4_process, s_md4_compress, md4, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int md4_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->md4.curlen >= sizeof(md->md4.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->md4.length += md->md4.curlen * 8; /* append the '1' bit */ md->md4.buf[md->md4.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->md4.curlen > 56) { while (md->md4.curlen < 64) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } s_md4_compress(md, md->md4.buf); md->md4.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->md4.curlen < 56) { md->md4.buf[md->md4.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->md4.length, md->md4.buf+56); s_md4_compress(md, md->md4.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->md4.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int md4_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct md4_test_case { const char *input; unsigned char hash[16]; } tests[] = { { "", {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} }, { "a", {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} }, { "abc", {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} }, { "message digest", {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} }, { "abcdefghijklmnopqrstuvwxyz", {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} }, }; int i; unsigned char tmp[16]; hash_state md; for(i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { md4_init(&md); md4_process(&md, (unsigned char *)tests[i].input, (unsigned long)XSTRLEN(tests[i].input)); md4_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD4", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/md5.c000066400000000000000000000240651464416617300223170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file md5.c LTC_MD5 hash function by Tom St Denis */ #ifdef LTC_MD5 const struct ltc_hash_descriptor md5_desc = { "md5", 3, 16, 64, /* OID */ { 1, 2, 840, 113549, 2, 5, }, 6, &md5_init, &md5_process, &md5_done, &md5_test, NULL }; #define F(x,y,z) (z ^ (x & (y ^ z))) #define G(x,y,z) (y ^ (z & (y ^ x))) #define H(x,y,z) (x^y^z) #define I(x,y,z) (y^(x|(~z))) #ifdef LTC_SMALL_CODE #define FF(a,b,c,d,M,s,t) \ a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; #define GG(a,b,c,d,M,s,t) \ a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; #define HH(a,b,c,d,M,s,t) \ a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; #define II(a,b,c,d,M,s,t) \ a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; static const unsigned char Worder[64] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 }; static const unsigned char Rorder[64] = { 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 }; static const ulong32 Korder[64] = { 0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, 0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, 0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, 0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, 0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, 0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, 0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, 0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL }; #else #define FF(a,b,c,d,M,s,t) \ a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; #define GG(a,b,c,d,M,s,t) \ a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; #define HH(a,b,c,d,M,s,t) \ a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; #define II(a,b,c,d,M,s,t) \ a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; #endif #ifdef LTC_CLEAN_STACK static int ss_md5_compress(hash_state *md, const unsigned char *buf) #else static int s_md5_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 i, W[16], a, b, c, d; #ifdef LTC_SMALL_CODE ulong32 t; #endif /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32L(W[i], buf + (4*i)); } /* copy state */ a = md->md5.state[0]; b = md->md5.state[1]; c = md->md5.state[2]; d = md->md5.state[3]; #ifdef LTC_SMALL_CODE for (i = 0; i < 16; ++i) { FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); t = d; d = c; c = b; b = a; a = t; } for (; i < 32; ++i) { GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); t = d; d = c; c = b; b = a; a = t; } for (; i < 48; ++i) { HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); t = d; d = c; c = b; b = a; a = t; } for (; i < 64; ++i) { II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); t = d; d = c; c = b; b = a; a = t; } #else FF(a,b,c,d,W[0],7,0xd76aa478UL) FF(d,a,b,c,W[1],12,0xe8c7b756UL) FF(c,d,a,b,W[2],17,0x242070dbUL) FF(b,c,d,a,W[3],22,0xc1bdceeeUL) FF(a,b,c,d,W[4],7,0xf57c0fafUL) FF(d,a,b,c,W[5],12,0x4787c62aUL) FF(c,d,a,b,W[6],17,0xa8304613UL) FF(b,c,d,a,W[7],22,0xfd469501UL) FF(a,b,c,d,W[8],7,0x698098d8UL) FF(d,a,b,c,W[9],12,0x8b44f7afUL) FF(c,d,a,b,W[10],17,0xffff5bb1UL) FF(b,c,d,a,W[11],22,0x895cd7beUL) FF(a,b,c,d,W[12],7,0x6b901122UL) FF(d,a,b,c,W[13],12,0xfd987193UL) FF(c,d,a,b,W[14],17,0xa679438eUL) FF(b,c,d,a,W[15],22,0x49b40821UL) GG(a,b,c,d,W[1],5,0xf61e2562UL) GG(d,a,b,c,W[6],9,0xc040b340UL) GG(c,d,a,b,W[11],14,0x265e5a51UL) GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) GG(a,b,c,d,W[5],5,0xd62f105dUL) GG(d,a,b,c,W[10],9,0x02441453UL) GG(c,d,a,b,W[15],14,0xd8a1e681UL) GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) GG(a,b,c,d,W[9],5,0x21e1cde6UL) GG(d,a,b,c,W[14],9,0xc33707d6UL) GG(c,d,a,b,W[3],14,0xf4d50d87UL) GG(b,c,d,a,W[8],20,0x455a14edUL) GG(a,b,c,d,W[13],5,0xa9e3e905UL) GG(d,a,b,c,W[2],9,0xfcefa3f8UL) GG(c,d,a,b,W[7],14,0x676f02d9UL) GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) HH(a,b,c,d,W[5],4,0xfffa3942UL) HH(d,a,b,c,W[8],11,0x8771f681UL) HH(c,d,a,b,W[11],16,0x6d9d6122UL) HH(b,c,d,a,W[14],23,0xfde5380cUL) HH(a,b,c,d,W[1],4,0xa4beea44UL) HH(d,a,b,c,W[4],11,0x4bdecfa9UL) HH(c,d,a,b,W[7],16,0xf6bb4b60UL) HH(b,c,d,a,W[10],23,0xbebfbc70UL) HH(a,b,c,d,W[13],4,0x289b7ec6UL) HH(d,a,b,c,W[0],11,0xeaa127faUL) HH(c,d,a,b,W[3],16,0xd4ef3085UL) HH(b,c,d,a,W[6],23,0x04881d05UL) HH(a,b,c,d,W[9],4,0xd9d4d039UL) HH(d,a,b,c,W[12],11,0xe6db99e5UL) HH(c,d,a,b,W[15],16,0x1fa27cf8UL) HH(b,c,d,a,W[2],23,0xc4ac5665UL) II(a,b,c,d,W[0],6,0xf4292244UL) II(d,a,b,c,W[7],10,0x432aff97UL) II(c,d,a,b,W[14],15,0xab9423a7UL) II(b,c,d,a,W[5],21,0xfc93a039UL) II(a,b,c,d,W[12],6,0x655b59c3UL) II(d,a,b,c,W[3],10,0x8f0ccc92UL) II(c,d,a,b,W[10],15,0xffeff47dUL) II(b,c,d,a,W[1],21,0x85845dd1UL) II(a,b,c,d,W[8],6,0x6fa87e4fUL) II(d,a,b,c,W[15],10,0xfe2ce6e0UL) II(c,d,a,b,W[6],15,0xa3014314UL) II(b,c,d,a,W[13],21,0x4e0811a1UL) II(a,b,c,d,W[4],6,0xf7537e82UL) II(d,a,b,c,W[11],10,0xbd3af235UL) II(c,d,a,b,W[2],15,0x2ad7d2bbUL) II(b,c,d,a,W[9],21,0xeb86d391UL) #endif md->md5.state[0] = md->md5.state[0] + a; md->md5.state[1] = md->md5.state[1] + b; md->md5.state[2] = md->md5.state[2] + c; md->md5.state[3] = md->md5.state[3] + d; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_md5_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_md5_compress(md, buf); burn_stack(sizeof(ulong32) * 21); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int md5_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->md5.state[0] = 0x67452301UL; md->md5.state[1] = 0xefcdab89UL; md->md5.state[2] = 0x98badcfeUL; md->md5.state[3] = 0x10325476UL; md->md5.curlen = 0; md->md5.length = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(md5_process, s_md5_compress, md5, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int md5_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->md5.curlen >= sizeof(md->md5.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->md5.length += md->md5.curlen * 8; /* append the '1' bit */ md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->md5.curlen > 56) { while (md->md5.curlen < 64) { md->md5.buf[md->md5.curlen++] = (unsigned char)0; } s_md5_compress(md, md->md5.buf); md->md5.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->md5.curlen < 56) { md->md5.buf[md->md5.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->md5.length, md->md5.buf+56); s_md5_compress(md, md->md5.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->md5.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int md5_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[16]; } tests[] = { { "", { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, { "a", {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, { "abc", { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, { "message digest", { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, { "abcdefghijklmnopqrstuvwxyz", { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, { NULL, { 0 } } }; int i; unsigned char tmp[16]; hash_state md; for (i = 0; tests[i].msg != NULL; i++) { md5_init(&md); md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); md5_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD5", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/rmd128.c000066400000000000000000000263711464416617300226510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @param rmd128.c RMD128 Hash function */ /* Implementation of LTC_RIPEMD-128 based on the source by Antoon Bosselaers, ESAT-COSIC * * This source has been radically overhauled to be portable and work within * the LibTomCrypt API by Tom St Denis */ #ifdef LTC_RIPEMD128 const struct ltc_hash_descriptor rmd128_desc = { "rmd128", 8, 16, 64, /* OID */ { 1, 0, 10118, 3, 0, 50 }, 6, &rmd128_init, &rmd128_process, &rmd128_done, &rmd128_test, NULL }; /* the four basic functions F(), G() and H() */ #define F(x, y, z) ((x) ^ (y) ^ (z)) #define G(x, y, z) (((x) & (y)) | (~(x) & (z))) #define H(x, y, z) (((x) | ~(y)) ^ (z)) #define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) /* the eight basic operations FF() through III() */ #define FF(a, b, c, d, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)); #define GG(a, b, c, d, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ (a) = ROLc((a), (s)); #define HH(a, b, c, d, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ (a) = ROLc((a), (s)); #define II(a, b, c, d, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ (a) = ROLc((a), (s)); #define FFF(a, b, c, d, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)); #define GGG(a, b, c, d, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ (a) = ROLc((a), (s)); #define HHH(a, b, c, d, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ (a) = ROLc((a), (s)); #define III(a, b, c, d, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ (a) = ROLc((a), (s)); #ifdef LTC_CLEAN_STACK static int ss_rmd128_compress(hash_state *md, const unsigned char *buf) #else static int s_rmd128_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16]; int i; /* load words X */ for (i = 0; i < 16; i++){ LOAD32L(X[i], buf + (4 * i)); } /* load state */ aa = aaa = md->rmd128.state[0]; bb = bbb = md->rmd128.state[1]; cc = ccc = md->rmd128.state[2]; dd = ddd = md->rmd128.state[3]; /* round 1 */ FF(aa, bb, cc, dd, X[ 0], 11); FF(dd, aa, bb, cc, X[ 1], 14); FF(cc, dd, aa, bb, X[ 2], 15); FF(bb, cc, dd, aa, X[ 3], 12); FF(aa, bb, cc, dd, X[ 4], 5); FF(dd, aa, bb, cc, X[ 5], 8); FF(cc, dd, aa, bb, X[ 6], 7); FF(bb, cc, dd, aa, X[ 7], 9); FF(aa, bb, cc, dd, X[ 8], 11); FF(dd, aa, bb, cc, X[ 9], 13); FF(cc, dd, aa, bb, X[10], 14); FF(bb, cc, dd, aa, X[11], 15); FF(aa, bb, cc, dd, X[12], 6); FF(dd, aa, bb, cc, X[13], 7); FF(cc, dd, aa, bb, X[14], 9); FF(bb, cc, dd, aa, X[15], 8); /* round 2 */ GG(aa, bb, cc, dd, X[ 7], 7); GG(dd, aa, bb, cc, X[ 4], 6); GG(cc, dd, aa, bb, X[13], 8); GG(bb, cc, dd, aa, X[ 1], 13); GG(aa, bb, cc, dd, X[10], 11); GG(dd, aa, bb, cc, X[ 6], 9); GG(cc, dd, aa, bb, X[15], 7); GG(bb, cc, dd, aa, X[ 3], 15); GG(aa, bb, cc, dd, X[12], 7); GG(dd, aa, bb, cc, X[ 0], 12); GG(cc, dd, aa, bb, X[ 9], 15); GG(bb, cc, dd, aa, X[ 5], 9); GG(aa, bb, cc, dd, X[ 2], 11); GG(dd, aa, bb, cc, X[14], 7); GG(cc, dd, aa, bb, X[11], 13); GG(bb, cc, dd, aa, X[ 8], 12); /* round 3 */ HH(aa, bb, cc, dd, X[ 3], 11); HH(dd, aa, bb, cc, X[10], 13); HH(cc, dd, aa, bb, X[14], 6); HH(bb, cc, dd, aa, X[ 4], 7); HH(aa, bb, cc, dd, X[ 9], 14); HH(dd, aa, bb, cc, X[15], 9); HH(cc, dd, aa, bb, X[ 8], 13); HH(bb, cc, dd, aa, X[ 1], 15); HH(aa, bb, cc, dd, X[ 2], 14); HH(dd, aa, bb, cc, X[ 7], 8); HH(cc, dd, aa, bb, X[ 0], 13); HH(bb, cc, dd, aa, X[ 6], 6); HH(aa, bb, cc, dd, X[13], 5); HH(dd, aa, bb, cc, X[11], 12); HH(cc, dd, aa, bb, X[ 5], 7); HH(bb, cc, dd, aa, X[12], 5); /* round 4 */ II(aa, bb, cc, dd, X[ 1], 11); II(dd, aa, bb, cc, X[ 9], 12); II(cc, dd, aa, bb, X[11], 14); II(bb, cc, dd, aa, X[10], 15); II(aa, bb, cc, dd, X[ 0], 14); II(dd, aa, bb, cc, X[ 8], 15); II(cc, dd, aa, bb, X[12], 9); II(bb, cc, dd, aa, X[ 4], 8); II(aa, bb, cc, dd, X[13], 9); II(dd, aa, bb, cc, X[ 3], 14); II(cc, dd, aa, bb, X[ 7], 5); II(bb, cc, dd, aa, X[15], 6); II(aa, bb, cc, dd, X[14], 8); II(dd, aa, bb, cc, X[ 5], 6); II(cc, dd, aa, bb, X[ 6], 5); II(bb, cc, dd, aa, X[ 2], 12); /* parallel round 1 */ III(aaa, bbb, ccc, ddd, X[ 5], 8); III(ddd, aaa, bbb, ccc, X[14], 9); III(ccc, ddd, aaa, bbb, X[ 7], 9); III(bbb, ccc, ddd, aaa, X[ 0], 11); III(aaa, bbb, ccc, ddd, X[ 9], 13); III(ddd, aaa, bbb, ccc, X[ 2], 15); III(ccc, ddd, aaa, bbb, X[11], 15); III(bbb, ccc, ddd, aaa, X[ 4], 5); III(aaa, bbb, ccc, ddd, X[13], 7); III(ddd, aaa, bbb, ccc, X[ 6], 7); III(ccc, ddd, aaa, bbb, X[15], 8); III(bbb, ccc, ddd, aaa, X[ 8], 11); III(aaa, bbb, ccc, ddd, X[ 1], 14); III(ddd, aaa, bbb, ccc, X[10], 14); III(ccc, ddd, aaa, bbb, X[ 3], 12); III(bbb, ccc, ddd, aaa, X[12], 6); /* parallel round 2 */ HHH(aaa, bbb, ccc, ddd, X[ 6], 9); HHH(ddd, aaa, bbb, ccc, X[11], 13); HHH(ccc, ddd, aaa, bbb, X[ 3], 15); HHH(bbb, ccc, ddd, aaa, X[ 7], 7); HHH(aaa, bbb, ccc, ddd, X[ 0], 12); HHH(ddd, aaa, bbb, ccc, X[13], 8); HHH(ccc, ddd, aaa, bbb, X[ 5], 9); HHH(bbb, ccc, ddd, aaa, X[10], 11); HHH(aaa, bbb, ccc, ddd, X[14], 7); HHH(ddd, aaa, bbb, ccc, X[15], 7); HHH(ccc, ddd, aaa, bbb, X[ 8], 12); HHH(bbb, ccc, ddd, aaa, X[12], 7); HHH(aaa, bbb, ccc, ddd, X[ 4], 6); HHH(ddd, aaa, bbb, ccc, X[ 9], 15); HHH(ccc, ddd, aaa, bbb, X[ 1], 13); HHH(bbb, ccc, ddd, aaa, X[ 2], 11); /* parallel round 3 */ GGG(aaa, bbb, ccc, ddd, X[15], 9); GGG(ddd, aaa, bbb, ccc, X[ 5], 7); GGG(ccc, ddd, aaa, bbb, X[ 1], 15); GGG(bbb, ccc, ddd, aaa, X[ 3], 11); GGG(aaa, bbb, ccc, ddd, X[ 7], 8); GGG(ddd, aaa, bbb, ccc, X[14], 6); GGG(ccc, ddd, aaa, bbb, X[ 6], 6); GGG(bbb, ccc, ddd, aaa, X[ 9], 14); GGG(aaa, bbb, ccc, ddd, X[11], 12); GGG(ddd, aaa, bbb, ccc, X[ 8], 13); GGG(ccc, ddd, aaa, bbb, X[12], 5); GGG(bbb, ccc, ddd, aaa, X[ 2], 14); GGG(aaa, bbb, ccc, ddd, X[10], 13); GGG(ddd, aaa, bbb, ccc, X[ 0], 13); GGG(ccc, ddd, aaa, bbb, X[ 4], 7); GGG(bbb, ccc, ddd, aaa, X[13], 5); /* parallel round 4 */ FFF(aaa, bbb, ccc, ddd, X[ 8], 15); FFF(ddd, aaa, bbb, ccc, X[ 6], 5); FFF(ccc, ddd, aaa, bbb, X[ 4], 8); FFF(bbb, ccc, ddd, aaa, X[ 1], 11); FFF(aaa, bbb, ccc, ddd, X[ 3], 14); FFF(ddd, aaa, bbb, ccc, X[11], 14); FFF(ccc, ddd, aaa, bbb, X[15], 6); FFF(bbb, ccc, ddd, aaa, X[ 0], 14); FFF(aaa, bbb, ccc, ddd, X[ 5], 6); FFF(ddd, aaa, bbb, ccc, X[12], 9); FFF(ccc, ddd, aaa, bbb, X[ 2], 12); FFF(bbb, ccc, ddd, aaa, X[13], 9); FFF(aaa, bbb, ccc, ddd, X[ 9], 12); FFF(ddd, aaa, bbb, ccc, X[ 7], 5); FFF(ccc, ddd, aaa, bbb, X[10], 15); FFF(bbb, ccc, ddd, aaa, X[14], 8); /* combine results */ ddd += cc + md->rmd128.state[1]; /* final result for MDbuf[0] */ md->rmd128.state[1] = md->rmd128.state[2] + dd + aaa; md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb; md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc; md->rmd128.state[0] = ddd; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_rmd128_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_rmd128_compress(md, buf); burn_stack(sizeof(ulong32) * 24 + sizeof(int)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int rmd128_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->rmd128.state[0] = 0x67452301UL; md->rmd128.state[1] = 0xefcdab89UL; md->rmd128.state[2] = 0x98badcfeUL; md->rmd128.state[3] = 0x10325476UL; md->rmd128.curlen = 0; md->rmd128.length = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(rmd128_process, s_rmd128_compress, rmd128, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int rmd128_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->rmd128.length += md->rmd128.curlen * 8; /* append the '1' bit */ md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->rmd128.curlen > 56) { while (md->rmd128.curlen < 64) { md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; } s_rmd128_compress(md, md->rmd128.buf); md->rmd128.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->rmd128.curlen < 56) { md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->rmd128.length, md->rmd128.buf+56); s_rmd128_compress(md, md->rmd128.buf); /* copy output */ for (i = 0; i < 4; i++) { STORE32L(md->rmd128.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int rmd128_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[16]; } tests[] = { { "", { 0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e, 0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46 } }, { "a", { 0x86, 0xbe, 0x7a, 0xfa, 0x33, 0x9d, 0x0f, 0xc7, 0xcf, 0xc7, 0x85, 0xe7, 0x2f, 0x57, 0x8d, 0x33 } }, { "abc", { 0xc1, 0x4a, 0x12, 0x19, 0x9c, 0x66, 0xe4, 0xba, 0x84, 0x63, 0x6b, 0x0f, 0x69, 0x14, 0x4c, 0x77 } }, { "message digest", { 0x9e, 0x32, 0x7b, 0x3d, 0x6e, 0x52, 0x30, 0x62, 0xaf, 0xc1, 0x13, 0x2d, 0x7d, 0xf9, 0xd1, 0xb8 } }, { "abcdefghijklmnopqrstuvwxyz", { 0xfd, 0x2a, 0xa6, 0x07, 0xf7, 0x1d, 0xc8, 0xf5, 0x10, 0x71, 0x49, 0x22, 0xb3, 0x71, 0x83, 0x4e } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { 0xd1, 0xe9, 0x59, 0xeb, 0x17, 0x9c, 0x91, 0x1f, 0xae, 0xa4, 0x62, 0x4c, 0x60, 0xc5, 0xc7, 0x02 } } }; int i; unsigned char tmp[16]; hash_state md; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { rmd128_init(&md); rmd128_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); rmd128_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD128", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/rmd160.c000066400000000000000000000341041464416617300226360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rmd160.c RMD160 hash function */ /* Implementation of LTC_RIPEMD-160 based on the source by Antoon Bosselaers, ESAT-COSIC * * This source has been radically overhauled to be portable and work within * the LibTomCrypt API by Tom St Denis */ #ifdef LTC_RIPEMD160 const struct ltc_hash_descriptor rmd160_desc = { "rmd160", 9, 20, 64, /* OID */ { 1, 3, 36, 3, 2, 1, }, 6, &rmd160_init, &rmd160_process, &rmd160_done, &rmd160_test, NULL }; /* the five basic functions F(), G() and H() */ #define F(x, y, z) ((x) ^ (y) ^ (z)) #define G(x, y, z) (((x) & (y)) | (~(x) & (z))) #define H(x, y, z) (((x) | ~(y)) ^ (z)) #define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define J(x, y, z) ((x) ^ ((y) | ~(z))) /* the ten basic operations FF() through III() */ #define FF(a, b, c, d, e, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define GG(a, b, c, d, e, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define HH(a, b, c, d, e, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define II(a, b, c, d, e, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define JJ(a, b, c, d, e, x, s) \ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define FFF(a, b, c, d, e, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define GGG(a, b, c, d, e, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define HHH(a, b, c, d, e, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define III(a, b, c, d, e, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define JJJ(a, b, c, d, e, x, s) \ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #ifdef LTC_CLEAN_STACK static int ss_rmd160_compress(hash_state *md, const unsigned char *buf) #else static int s_rmd160_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; int i; /* load words X */ for (i = 0; i < 16; i++){ LOAD32L(X[i], buf + (4 * i)); } /* load state */ aa = aaa = md->rmd160.state[0]; bb = bbb = md->rmd160.state[1]; cc = ccc = md->rmd160.state[2]; dd = ddd = md->rmd160.state[3]; ee = eee = md->rmd160.state[4]; /* round 1 */ FF(aa, bb, cc, dd, ee, X[ 0], 11); FF(ee, aa, bb, cc, dd, X[ 1], 14); FF(dd, ee, aa, bb, cc, X[ 2], 15); FF(cc, dd, ee, aa, bb, X[ 3], 12); FF(bb, cc, dd, ee, aa, X[ 4], 5); FF(aa, bb, cc, dd, ee, X[ 5], 8); FF(ee, aa, bb, cc, dd, X[ 6], 7); FF(dd, ee, aa, bb, cc, X[ 7], 9); FF(cc, dd, ee, aa, bb, X[ 8], 11); FF(bb, cc, dd, ee, aa, X[ 9], 13); FF(aa, bb, cc, dd, ee, X[10], 14); FF(ee, aa, bb, cc, dd, X[11], 15); FF(dd, ee, aa, bb, cc, X[12], 6); FF(cc, dd, ee, aa, bb, X[13], 7); FF(bb, cc, dd, ee, aa, X[14], 9); FF(aa, bb, cc, dd, ee, X[15], 8); /* round 2 */ GG(ee, aa, bb, cc, dd, X[ 7], 7); GG(dd, ee, aa, bb, cc, X[ 4], 6); GG(cc, dd, ee, aa, bb, X[13], 8); GG(bb, cc, dd, ee, aa, X[ 1], 13); GG(aa, bb, cc, dd, ee, X[10], 11); GG(ee, aa, bb, cc, dd, X[ 6], 9); GG(dd, ee, aa, bb, cc, X[15], 7); GG(cc, dd, ee, aa, bb, X[ 3], 15); GG(bb, cc, dd, ee, aa, X[12], 7); GG(aa, bb, cc, dd, ee, X[ 0], 12); GG(ee, aa, bb, cc, dd, X[ 9], 15); GG(dd, ee, aa, bb, cc, X[ 5], 9); GG(cc, dd, ee, aa, bb, X[ 2], 11); GG(bb, cc, dd, ee, aa, X[14], 7); GG(aa, bb, cc, dd, ee, X[11], 13); GG(ee, aa, bb, cc, dd, X[ 8], 12); /* round 3 */ HH(dd, ee, aa, bb, cc, X[ 3], 11); HH(cc, dd, ee, aa, bb, X[10], 13); HH(bb, cc, dd, ee, aa, X[14], 6); HH(aa, bb, cc, dd, ee, X[ 4], 7); HH(ee, aa, bb, cc, dd, X[ 9], 14); HH(dd, ee, aa, bb, cc, X[15], 9); HH(cc, dd, ee, aa, bb, X[ 8], 13); HH(bb, cc, dd, ee, aa, X[ 1], 15); HH(aa, bb, cc, dd, ee, X[ 2], 14); HH(ee, aa, bb, cc, dd, X[ 7], 8); HH(dd, ee, aa, bb, cc, X[ 0], 13); HH(cc, dd, ee, aa, bb, X[ 6], 6); HH(bb, cc, dd, ee, aa, X[13], 5); HH(aa, bb, cc, dd, ee, X[11], 12); HH(ee, aa, bb, cc, dd, X[ 5], 7); HH(dd, ee, aa, bb, cc, X[12], 5); /* round 4 */ II(cc, dd, ee, aa, bb, X[ 1], 11); II(bb, cc, dd, ee, aa, X[ 9], 12); II(aa, bb, cc, dd, ee, X[11], 14); II(ee, aa, bb, cc, dd, X[10], 15); II(dd, ee, aa, bb, cc, X[ 0], 14); II(cc, dd, ee, aa, bb, X[ 8], 15); II(bb, cc, dd, ee, aa, X[12], 9); II(aa, bb, cc, dd, ee, X[ 4], 8); II(ee, aa, bb, cc, dd, X[13], 9); II(dd, ee, aa, bb, cc, X[ 3], 14); II(cc, dd, ee, aa, bb, X[ 7], 5); II(bb, cc, dd, ee, aa, X[15], 6); II(aa, bb, cc, dd, ee, X[14], 8); II(ee, aa, bb, cc, dd, X[ 5], 6); II(dd, ee, aa, bb, cc, X[ 6], 5); II(cc, dd, ee, aa, bb, X[ 2], 12); /* round 5 */ JJ(bb, cc, dd, ee, aa, X[ 4], 9); JJ(aa, bb, cc, dd, ee, X[ 0], 15); JJ(ee, aa, bb, cc, dd, X[ 5], 5); JJ(dd, ee, aa, bb, cc, X[ 9], 11); JJ(cc, dd, ee, aa, bb, X[ 7], 6); JJ(bb, cc, dd, ee, aa, X[12], 8); JJ(aa, bb, cc, dd, ee, X[ 2], 13); JJ(ee, aa, bb, cc, dd, X[10], 12); JJ(dd, ee, aa, bb, cc, X[14], 5); JJ(cc, dd, ee, aa, bb, X[ 1], 12); JJ(bb, cc, dd, ee, aa, X[ 3], 13); JJ(aa, bb, cc, dd, ee, X[ 8], 14); JJ(ee, aa, bb, cc, dd, X[11], 11); JJ(dd, ee, aa, bb, cc, X[ 6], 8); JJ(cc, dd, ee, aa, bb, X[15], 5); JJ(bb, cc, dd, ee, aa, X[13], 6); /* parallel round 1 */ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); /* parallel round 2 */ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); III(ddd, eee, aaa, bbb, ccc, X[11], 13); III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); III(eee, aaa, bbb, ccc, ddd, X[13], 8); III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); III(ccc, ddd, eee, aaa, bbb, X[10], 11); III(bbb, ccc, ddd, eee, aaa, X[14], 7); III(aaa, bbb, ccc, ddd, eee, X[15], 7); III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); III(ddd, eee, aaa, bbb, ccc, X[12], 7); III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); /* parallel round 3 */ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); /* parallel round 4 */ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); /* parallel round 5 */ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); /* combine results */ ddd += cc + md->rmd160.state[1]; /* final result for md->rmd160.state[0] */ md->rmd160.state[1] = md->rmd160.state[2] + dd + eee; md->rmd160.state[2] = md->rmd160.state[3] + ee + aaa; md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb; md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc; md->rmd160.state[0] = ddd; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_rmd160_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_rmd160_compress(md, buf); burn_stack(sizeof(ulong32) * 26 + sizeof(int)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int rmd160_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->rmd160.state[0] = 0x67452301UL; md->rmd160.state[1] = 0xefcdab89UL; md->rmd160.state[2] = 0x98badcfeUL; md->rmd160.state[3] = 0x10325476UL; md->rmd160.state[4] = 0xc3d2e1f0UL; md->rmd160.curlen = 0; md->rmd160.length = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(rmd160_process, s_rmd160_compress, rmd160, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (20 bytes) @return CRYPT_OK if successful */ int rmd160_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->rmd160.length += md->rmd160.curlen * 8; /* append the '1' bit */ md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->rmd160.curlen > 56) { while (md->rmd160.curlen < 64) { md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; } s_rmd160_compress(md, md->rmd160.buf); md->rmd160.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->rmd160.curlen < 56) { md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->rmd160.length, md->rmd160.buf+56); s_rmd160_compress(md, md->rmd160.buf); /* copy output */ for (i = 0; i < 5; i++) { STORE32L(md->rmd160.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int rmd160_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[20]; } tests[] = { { "", { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 } }, { "a", { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe } }, { "abc", { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc } }, { "message digest", { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 } }, { "abcdefghijklmnopqrstuvwxyz", { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b } } }; int i; unsigned char tmp[20]; hash_state md; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { rmd160_init(&md); rmd160_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); rmd160_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD160", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/rmd256.c000066400000000000000000000300361464416617300226440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @param rmd256.c RLTC_MD256 Hash function */ #ifdef LTC_RIPEMD256 const struct ltc_hash_descriptor rmd256_desc = { "rmd256", 13, 32, 64, /* OID */ { 1, 3, 36, 3, 2, 3 }, 6, &rmd256_init, &rmd256_process, &rmd256_done, &rmd256_test, NULL }; /* the four basic functions F(), G() and H() */ #define F(x, y, z) ((x) ^ (y) ^ (z)) #define G(x, y, z) (((x) & (y)) | (~(x) & (z))) #define H(x, y, z) (((x) | ~(y)) ^ (z)) #define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) /* the eight basic operations FF() through III() */ #define FF(a, b, c, d, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)); #define GG(a, b, c, d, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ (a) = ROLc((a), (s)); #define HH(a, b, c, d, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ (a) = ROLc((a), (s)); #define II(a, b, c, d, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ (a) = ROLc((a), (s)); #define FFF(a, b, c, d, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)); #define GGG(a, b, c, d, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ (a) = ROLc((a), (s)); #define HHH(a, b, c, d, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ (a) = ROLc((a), (s)); #define III(a, b, c, d, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ (a) = ROLc((a), (s)); #ifdef LTC_CLEAN_STACK static int ss_rmd256_compress(hash_state *md, const unsigned char *buf) #else static int s_rmd256_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,tmp,X[16]; int i; /* load words X */ for (i = 0; i < 16; i++){ LOAD32L(X[i], buf + (4 * i)); } /* load state */ aa = md->rmd256.state[0]; bb = md->rmd256.state[1]; cc = md->rmd256.state[2]; dd = md->rmd256.state[3]; aaa = md->rmd256.state[4]; bbb = md->rmd256.state[5]; ccc = md->rmd256.state[6]; ddd = md->rmd256.state[7]; /* round 1 */ FF(aa, bb, cc, dd, X[ 0], 11); FF(dd, aa, bb, cc, X[ 1], 14); FF(cc, dd, aa, bb, X[ 2], 15); FF(bb, cc, dd, aa, X[ 3], 12); FF(aa, bb, cc, dd, X[ 4], 5); FF(dd, aa, bb, cc, X[ 5], 8); FF(cc, dd, aa, bb, X[ 6], 7); FF(bb, cc, dd, aa, X[ 7], 9); FF(aa, bb, cc, dd, X[ 8], 11); FF(dd, aa, bb, cc, X[ 9], 13); FF(cc, dd, aa, bb, X[10], 14); FF(bb, cc, dd, aa, X[11], 15); FF(aa, bb, cc, dd, X[12], 6); FF(dd, aa, bb, cc, X[13], 7); FF(cc, dd, aa, bb, X[14], 9); FF(bb, cc, dd, aa, X[15], 8); /* parallel round 1 */ III(aaa, bbb, ccc, ddd, X[ 5], 8); III(ddd, aaa, bbb, ccc, X[14], 9); III(ccc, ddd, aaa, bbb, X[ 7], 9); III(bbb, ccc, ddd, aaa, X[ 0], 11); III(aaa, bbb, ccc, ddd, X[ 9], 13); III(ddd, aaa, bbb, ccc, X[ 2], 15); III(ccc, ddd, aaa, bbb, X[11], 15); III(bbb, ccc, ddd, aaa, X[ 4], 5); III(aaa, bbb, ccc, ddd, X[13], 7); III(ddd, aaa, bbb, ccc, X[ 6], 7); III(ccc, ddd, aaa, bbb, X[15], 8); III(bbb, ccc, ddd, aaa, X[ 8], 11); III(aaa, bbb, ccc, ddd, X[ 1], 14); III(ddd, aaa, bbb, ccc, X[10], 14); III(ccc, ddd, aaa, bbb, X[ 3], 12); III(bbb, ccc, ddd, aaa, X[12], 6); tmp = aa; aa = aaa; aaa = tmp; /* round 2 */ GG(aa, bb, cc, dd, X[ 7], 7); GG(dd, aa, bb, cc, X[ 4], 6); GG(cc, dd, aa, bb, X[13], 8); GG(bb, cc, dd, aa, X[ 1], 13); GG(aa, bb, cc, dd, X[10], 11); GG(dd, aa, bb, cc, X[ 6], 9); GG(cc, dd, aa, bb, X[15], 7); GG(bb, cc, dd, aa, X[ 3], 15); GG(aa, bb, cc, dd, X[12], 7); GG(dd, aa, bb, cc, X[ 0], 12); GG(cc, dd, aa, bb, X[ 9], 15); GG(bb, cc, dd, aa, X[ 5], 9); GG(aa, bb, cc, dd, X[ 2], 11); GG(dd, aa, bb, cc, X[14], 7); GG(cc, dd, aa, bb, X[11], 13); GG(bb, cc, dd, aa, X[ 8], 12); /* parallel round 2 */ HHH(aaa, bbb, ccc, ddd, X[ 6], 9); HHH(ddd, aaa, bbb, ccc, X[11], 13); HHH(ccc, ddd, aaa, bbb, X[ 3], 15); HHH(bbb, ccc, ddd, aaa, X[ 7], 7); HHH(aaa, bbb, ccc, ddd, X[ 0], 12); HHH(ddd, aaa, bbb, ccc, X[13], 8); HHH(ccc, ddd, aaa, bbb, X[ 5], 9); HHH(bbb, ccc, ddd, aaa, X[10], 11); HHH(aaa, bbb, ccc, ddd, X[14], 7); HHH(ddd, aaa, bbb, ccc, X[15], 7); HHH(ccc, ddd, aaa, bbb, X[ 8], 12); HHH(bbb, ccc, ddd, aaa, X[12], 7); HHH(aaa, bbb, ccc, ddd, X[ 4], 6); HHH(ddd, aaa, bbb, ccc, X[ 9], 15); HHH(ccc, ddd, aaa, bbb, X[ 1], 13); HHH(bbb, ccc, ddd, aaa, X[ 2], 11); tmp = bb; bb = bbb; bbb = tmp; /* round 3 */ HH(aa, bb, cc, dd, X[ 3], 11); HH(dd, aa, bb, cc, X[10], 13); HH(cc, dd, aa, bb, X[14], 6); HH(bb, cc, dd, aa, X[ 4], 7); HH(aa, bb, cc, dd, X[ 9], 14); HH(dd, aa, bb, cc, X[15], 9); HH(cc, dd, aa, bb, X[ 8], 13); HH(bb, cc, dd, aa, X[ 1], 15); HH(aa, bb, cc, dd, X[ 2], 14); HH(dd, aa, bb, cc, X[ 7], 8); HH(cc, dd, aa, bb, X[ 0], 13); HH(bb, cc, dd, aa, X[ 6], 6); HH(aa, bb, cc, dd, X[13], 5); HH(dd, aa, bb, cc, X[11], 12); HH(cc, dd, aa, bb, X[ 5], 7); HH(bb, cc, dd, aa, X[12], 5); /* parallel round 3 */ GGG(aaa, bbb, ccc, ddd, X[15], 9); GGG(ddd, aaa, bbb, ccc, X[ 5], 7); GGG(ccc, ddd, aaa, bbb, X[ 1], 15); GGG(bbb, ccc, ddd, aaa, X[ 3], 11); GGG(aaa, bbb, ccc, ddd, X[ 7], 8); GGG(ddd, aaa, bbb, ccc, X[14], 6); GGG(ccc, ddd, aaa, bbb, X[ 6], 6); GGG(bbb, ccc, ddd, aaa, X[ 9], 14); GGG(aaa, bbb, ccc, ddd, X[11], 12); GGG(ddd, aaa, bbb, ccc, X[ 8], 13); GGG(ccc, ddd, aaa, bbb, X[12], 5); GGG(bbb, ccc, ddd, aaa, X[ 2], 14); GGG(aaa, bbb, ccc, ddd, X[10], 13); GGG(ddd, aaa, bbb, ccc, X[ 0], 13); GGG(ccc, ddd, aaa, bbb, X[ 4], 7); GGG(bbb, ccc, ddd, aaa, X[13], 5); tmp = cc; cc = ccc; ccc = tmp; /* round 4 */ II(aa, bb, cc, dd, X[ 1], 11); II(dd, aa, bb, cc, X[ 9], 12); II(cc, dd, aa, bb, X[11], 14); II(bb, cc, dd, aa, X[10], 15); II(aa, bb, cc, dd, X[ 0], 14); II(dd, aa, bb, cc, X[ 8], 15); II(cc, dd, aa, bb, X[12], 9); II(bb, cc, dd, aa, X[ 4], 8); II(aa, bb, cc, dd, X[13], 9); II(dd, aa, bb, cc, X[ 3], 14); II(cc, dd, aa, bb, X[ 7], 5); II(bb, cc, dd, aa, X[15], 6); II(aa, bb, cc, dd, X[14], 8); II(dd, aa, bb, cc, X[ 5], 6); II(cc, dd, aa, bb, X[ 6], 5); II(bb, cc, dd, aa, X[ 2], 12); /* parallel round 4 */ FFF(aaa, bbb, ccc, ddd, X[ 8], 15); FFF(ddd, aaa, bbb, ccc, X[ 6], 5); FFF(ccc, ddd, aaa, bbb, X[ 4], 8); FFF(bbb, ccc, ddd, aaa, X[ 1], 11); FFF(aaa, bbb, ccc, ddd, X[ 3], 14); FFF(ddd, aaa, bbb, ccc, X[11], 14); FFF(ccc, ddd, aaa, bbb, X[15], 6); FFF(bbb, ccc, ddd, aaa, X[ 0], 14); FFF(aaa, bbb, ccc, ddd, X[ 5], 6); FFF(ddd, aaa, bbb, ccc, X[12], 9); FFF(ccc, ddd, aaa, bbb, X[ 2], 12); FFF(bbb, ccc, ddd, aaa, X[13], 9); FFF(aaa, bbb, ccc, ddd, X[ 9], 12); FFF(ddd, aaa, bbb, ccc, X[ 7], 5); FFF(ccc, ddd, aaa, bbb, X[10], 15); FFF(bbb, ccc, ddd, aaa, X[14], 8); tmp = dd; dd = ddd; ddd = tmp; /* combine results */ md->rmd256.state[0] += aa; md->rmd256.state[1] += bb; md->rmd256.state[2] += cc; md->rmd256.state[3] += dd; md->rmd256.state[4] += aaa; md->rmd256.state[5] += bbb; md->rmd256.state[6] += ccc; md->rmd256.state[7] += ddd; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_rmd256_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_rmd256_compress(md, buf); burn_stack(sizeof(ulong32) * 25 + sizeof(int)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int rmd256_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->rmd256.state[0] = 0x67452301UL; md->rmd256.state[1] = 0xefcdab89UL; md->rmd256.state[2] = 0x98badcfeUL; md->rmd256.state[3] = 0x10325476UL; md->rmd256.state[4] = 0x76543210UL; md->rmd256.state[5] = 0xfedcba98UL; md->rmd256.state[6] = 0x89abcdefUL; md->rmd256.state[7] = 0x01234567UL; md->rmd256.curlen = 0; md->rmd256.length = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(rmd256_process, s_rmd256_compress, rmd256, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (16 bytes) @return CRYPT_OK if successful */ int rmd256_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->rmd256.curlen >= sizeof(md->rmd256.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->rmd256.length += md->rmd256.curlen * 8; /* append the '1' bit */ md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->rmd256.curlen > 56) { while (md->rmd256.curlen < 64) { md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; } s_rmd256_compress(md, md->rmd256.buf); md->rmd256.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->rmd256.curlen < 56) { md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->rmd256.length, md->rmd256.buf+56); s_rmd256_compress(md, md->rmd256.buf); /* copy output */ for (i = 0; i < 8; i++) { STORE32L(md->rmd256.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int rmd256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[32]; } tests[] = { { "", { 0x02, 0xba, 0x4c, 0x4e, 0x5f, 0x8e, 0xcd, 0x18, 0x77, 0xfc, 0x52, 0xd6, 0x4d, 0x30, 0xe3, 0x7a, 0x2d, 0x97, 0x74, 0xfb, 0x1e, 0x5d, 0x02, 0x63, 0x80, 0xae, 0x01, 0x68, 0xe3, 0xc5, 0x52, 0x2d } }, { "a", { 0xf9, 0x33, 0x3e, 0x45, 0xd8, 0x57, 0xf5, 0xd9, 0x0a, 0x91, 0xba, 0xb7, 0x0a, 0x1e, 0xba, 0x0c, 0xfb, 0x1b, 0xe4, 0xb0, 0x78, 0x3c, 0x9a, 0xcf, 0xcd, 0x88, 0x3a, 0x91, 0x34, 0x69, 0x29, 0x25 } }, { "abc", { 0xaf, 0xbd, 0x6e, 0x22, 0x8b, 0x9d, 0x8c, 0xbb, 0xce, 0xf5, 0xca, 0x2d, 0x03, 0xe6, 0xdb, 0xa1, 0x0a, 0xc0, 0xbc, 0x7d, 0xcb, 0xe4, 0x68, 0x0e, 0x1e, 0x42, 0xd2, 0xe9, 0x75, 0x45, 0x9b, 0x65 } }, { "message digest", { 0x87, 0xe9, 0x71, 0x75, 0x9a, 0x1c, 0xe4, 0x7a, 0x51, 0x4d, 0x5c, 0x91, 0x4c, 0x39, 0x2c, 0x90, 0x18, 0xc7, 0xc4, 0x6b, 0xc1, 0x44, 0x65, 0x55, 0x4a, 0xfc, 0xdf, 0x54, 0xa5, 0x07, 0x0c, 0x0e } }, { "abcdefghijklmnopqrstuvwxyz", { 0x64, 0x9d, 0x30, 0x34, 0x75, 0x1e, 0xa2, 0x16, 0x77, 0x6b, 0xf9, 0xa1, 0x8a, 0xcc, 0x81, 0xbc, 0x78, 0x96, 0x11, 0x8a, 0x51, 0x97, 0x96, 0x87, 0x82, 0xdd, 0x1f, 0xd9, 0x7d, 0x8d, 0x51, 0x33 } }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { 0x57, 0x40, 0xa4, 0x08, 0xac, 0x16, 0xb7, 0x20, 0xb8, 0x44, 0x24, 0xae, 0x93, 0x1c, 0xbb, 0x1f, 0xe3, 0x63, 0xd1, 0xd0, 0xbf, 0x40, 0x17, 0xf1, 0xa8, 0x9f, 0x7e, 0xa6, 0xde, 0x77, 0xa0, 0xb8 } } }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { rmd256_init(&md); rmd256_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); rmd256_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD256", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/rmd320.c000066400000000000000000000362001464416617300226330ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rmd320.c RMD320 hash function */ #ifdef LTC_RIPEMD320 const struct ltc_hash_descriptor rmd320_desc = { "rmd320", 14, 40, 64, /* OID ... does not exist * http://oid-info.com/get/1.3.36.3.2 */ { 0 }, 0, &rmd320_init, &rmd320_process, &rmd320_done, &rmd320_test, NULL }; /* the five basic functions F(), G() and H() */ #define F(x, y, z) ((x) ^ (y) ^ (z)) #define G(x, y, z) (((x) & (y)) | (~(x) & (z))) #define H(x, y, z) (((x) | ~(y)) ^ (z)) #define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define J(x, y, z) ((x) ^ ((y) | ~(z))) /* the ten basic operations FF() through III() */ #define FF(a, b, c, d, e, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define GG(a, b, c, d, e, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define HH(a, b, c, d, e, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define II(a, b, c, d, e, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define JJ(a, b, c, d, e, x, s) \ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define FFF(a, b, c, d, e, x, s) \ (a) += F((b), (c), (d)) + (x);\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define GGG(a, b, c, d, e, x, s) \ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define HHH(a, b, c, d, e, x, s) \ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define III(a, b, c, d, e, x, s) \ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #define JJJ(a, b, c, d, e, x, s) \ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ (a) = ROLc((a), (s)) + (e);\ (c) = ROLc((c), 10); #ifdef LTC_CLEAN_STACK static int ss_rmd320_compress(hash_state *md, const unsigned char *buf) #else static int s_rmd320_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,tmp,X[16]; int i; /* load words X */ for (i = 0; i < 16; i++){ LOAD32L(X[i], buf + (4 * i)); } /* load state */ aa = md->rmd320.state[0]; bb = md->rmd320.state[1]; cc = md->rmd320.state[2]; dd = md->rmd320.state[3]; ee = md->rmd320.state[4]; aaa = md->rmd320.state[5]; bbb = md->rmd320.state[6]; ccc = md->rmd320.state[7]; ddd = md->rmd320.state[8]; eee = md->rmd320.state[9]; /* round 1 */ FF(aa, bb, cc, dd, ee, X[ 0], 11); FF(ee, aa, bb, cc, dd, X[ 1], 14); FF(dd, ee, aa, bb, cc, X[ 2], 15); FF(cc, dd, ee, aa, bb, X[ 3], 12); FF(bb, cc, dd, ee, aa, X[ 4], 5); FF(aa, bb, cc, dd, ee, X[ 5], 8); FF(ee, aa, bb, cc, dd, X[ 6], 7); FF(dd, ee, aa, bb, cc, X[ 7], 9); FF(cc, dd, ee, aa, bb, X[ 8], 11); FF(bb, cc, dd, ee, aa, X[ 9], 13); FF(aa, bb, cc, dd, ee, X[10], 14); FF(ee, aa, bb, cc, dd, X[11], 15); FF(dd, ee, aa, bb, cc, X[12], 6); FF(cc, dd, ee, aa, bb, X[13], 7); FF(bb, cc, dd, ee, aa, X[14], 9); FF(aa, bb, cc, dd, ee, X[15], 8); /* parallel round 1 */ JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); tmp = aa; aa = aaa; aaa = tmp; /* round 2 */ GG(ee, aa, bb, cc, dd, X[ 7], 7); GG(dd, ee, aa, bb, cc, X[ 4], 6); GG(cc, dd, ee, aa, bb, X[13], 8); GG(bb, cc, dd, ee, aa, X[ 1], 13); GG(aa, bb, cc, dd, ee, X[10], 11); GG(ee, aa, bb, cc, dd, X[ 6], 9); GG(dd, ee, aa, bb, cc, X[15], 7); GG(cc, dd, ee, aa, bb, X[ 3], 15); GG(bb, cc, dd, ee, aa, X[12], 7); GG(aa, bb, cc, dd, ee, X[ 0], 12); GG(ee, aa, bb, cc, dd, X[ 9], 15); GG(dd, ee, aa, bb, cc, X[ 5], 9); GG(cc, dd, ee, aa, bb, X[ 2], 11); GG(bb, cc, dd, ee, aa, X[14], 7); GG(aa, bb, cc, dd, ee, X[11], 13); GG(ee, aa, bb, cc, dd, X[ 8], 12); /* parallel round 2 */ III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); III(ddd, eee, aaa, bbb, ccc, X[11], 13); III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); III(eee, aaa, bbb, ccc, ddd, X[13], 8); III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); III(ccc, ddd, eee, aaa, bbb, X[10], 11); III(bbb, ccc, ddd, eee, aaa, X[14], 7); III(aaa, bbb, ccc, ddd, eee, X[15], 7); III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); III(ddd, eee, aaa, bbb, ccc, X[12], 7); III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); tmp = bb; bb = bbb; bbb = tmp; /* round 3 */ HH(dd, ee, aa, bb, cc, X[ 3], 11); HH(cc, dd, ee, aa, bb, X[10], 13); HH(bb, cc, dd, ee, aa, X[14], 6); HH(aa, bb, cc, dd, ee, X[ 4], 7); HH(ee, aa, bb, cc, dd, X[ 9], 14); HH(dd, ee, aa, bb, cc, X[15], 9); HH(cc, dd, ee, aa, bb, X[ 8], 13); HH(bb, cc, dd, ee, aa, X[ 1], 15); HH(aa, bb, cc, dd, ee, X[ 2], 14); HH(ee, aa, bb, cc, dd, X[ 7], 8); HH(dd, ee, aa, bb, cc, X[ 0], 13); HH(cc, dd, ee, aa, bb, X[ 6], 6); HH(bb, cc, dd, ee, aa, X[13], 5); HH(aa, bb, cc, dd, ee, X[11], 12); HH(ee, aa, bb, cc, dd, X[ 5], 7); HH(dd, ee, aa, bb, cc, X[12], 5); /* parallel round 3 */ HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); tmp = cc; cc = ccc; ccc = tmp; /* round 4 */ II(cc, dd, ee, aa, bb, X[ 1], 11); II(bb, cc, dd, ee, aa, X[ 9], 12); II(aa, bb, cc, dd, ee, X[11], 14); II(ee, aa, bb, cc, dd, X[10], 15); II(dd, ee, aa, bb, cc, X[ 0], 14); II(cc, dd, ee, aa, bb, X[ 8], 15); II(bb, cc, dd, ee, aa, X[12], 9); II(aa, bb, cc, dd, ee, X[ 4], 8); II(ee, aa, bb, cc, dd, X[13], 9); II(dd, ee, aa, bb, cc, X[ 3], 14); II(cc, dd, ee, aa, bb, X[ 7], 5); II(bb, cc, dd, ee, aa, X[15], 6); II(aa, bb, cc, dd, ee, X[14], 8); II(ee, aa, bb, cc, dd, X[ 5], 6); II(dd, ee, aa, bb, cc, X[ 6], 5); II(cc, dd, ee, aa, bb, X[ 2], 12); /* parallel round 4 */ GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); tmp = dd; dd = ddd; ddd = tmp; /* round 5 */ JJ(bb, cc, dd, ee, aa, X[ 4], 9); JJ(aa, bb, cc, dd, ee, X[ 0], 15); JJ(ee, aa, bb, cc, dd, X[ 5], 5); JJ(dd, ee, aa, bb, cc, X[ 9], 11); JJ(cc, dd, ee, aa, bb, X[ 7], 6); JJ(bb, cc, dd, ee, aa, X[12], 8); JJ(aa, bb, cc, dd, ee, X[ 2], 13); JJ(ee, aa, bb, cc, dd, X[10], 12); JJ(dd, ee, aa, bb, cc, X[14], 5); JJ(cc, dd, ee, aa, bb, X[ 1], 12); JJ(bb, cc, dd, ee, aa, X[ 3], 13); JJ(aa, bb, cc, dd, ee, X[ 8], 14); JJ(ee, aa, bb, cc, dd, X[11], 11); JJ(dd, ee, aa, bb, cc, X[ 6], 8); JJ(cc, dd, ee, aa, bb, X[15], 5); JJ(bb, cc, dd, ee, aa, X[13], 6); /* parallel round 5 */ FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); tmp = ee; ee = eee; eee = tmp; /* combine results */ md->rmd320.state[0] += aa; md->rmd320.state[1] += bb; md->rmd320.state[2] += cc; md->rmd320.state[3] += dd; md->rmd320.state[4] += ee; md->rmd320.state[5] += aaa; md->rmd320.state[6] += bbb; md->rmd320.state[7] += ccc; md->rmd320.state[8] += ddd; md->rmd320.state[9] += eee; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_rmd320_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_rmd320_compress(md, buf); burn_stack(sizeof(ulong32) * 27 + sizeof(int)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int rmd320_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->rmd320.state[0] = 0x67452301UL; md->rmd320.state[1] = 0xefcdab89UL; md->rmd320.state[2] = 0x98badcfeUL; md->rmd320.state[3] = 0x10325476UL; md->rmd320.state[4] = 0xc3d2e1f0UL; md->rmd320.state[5] = 0x76543210UL; md->rmd320.state[6] = 0xfedcba98UL; md->rmd320.state[7] = 0x89abcdefUL; md->rmd320.state[8] = 0x01234567UL; md->rmd320.state[9] = 0x3c2d1e0fUL; md->rmd320.curlen = 0; md->rmd320.length = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(rmd320_process, s_rmd320_compress, rmd320, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (20 bytes) @return CRYPT_OK if successful */ int rmd320_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->rmd320.curlen >= sizeof(md->rmd320.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->rmd320.length += md->rmd320.curlen * 8; /* append the '1' bit */ md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->rmd320.curlen > 56) { while (md->rmd320.curlen < 64) { md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; } s_rmd320_compress(md, md->rmd320.buf); md->rmd320.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->rmd320.curlen < 56) { md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->rmd320.length, md->rmd320.buf+56); s_rmd320_compress(md, md->rmd320.buf); /* copy output */ for (i = 0; i < 10; i++) { STORE32L(md->rmd320.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int rmd320_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[40]; } tests[] = { { "", { 0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc, 0x75, 0xc1, 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41, 0xb9, 0xf2, 0x73, 0x25, 0xeb, 0xc6, 0x1e, 0x85, 0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e, 0xc8, 0x80, 0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8 } }, { "a", { 0xce, 0x78, 0x85, 0x06, 0x38, 0xf9, 0x26, 0x58, 0xa5, 0xa5, 0x85, 0x09, 0x75, 0x79, 0x92, 0x6d, 0xda, 0x66, 0x7a, 0x57, 0x16, 0x56, 0x2c, 0xfc, 0xf6, 0xfb, 0xe7, 0x7f, 0x63, 0x54, 0x2f, 0x99, 0xb0, 0x47, 0x05, 0xd6, 0x97, 0x0d, 0xff, 0x5d } }, { "abc", { 0xde, 0x4c, 0x01, 0xb3, 0x05, 0x4f, 0x89, 0x30, 0xa7, 0x9d, 0x09, 0xae, 0x73, 0x8e, 0x92, 0x30, 0x1e, 0x5a, 0x17, 0x08, 0x5b, 0xef, 0xfd, 0xc1, 0xb8, 0xd1, 0x16, 0x71, 0x3e, 0x74, 0xf8, 0x2f, 0xa9, 0x42, 0xd6, 0x4c, 0xdb, 0xc4, 0x68, 0x2d } }, { "message digest", { 0x3a, 0x8e, 0x28, 0x50, 0x2e, 0xd4, 0x5d, 0x42, 0x2f, 0x68, 0x84, 0x4f, 0x9d, 0xd3, 0x16, 0xe7, 0xb9, 0x85, 0x33, 0xfa, 0x3f, 0x2a, 0x91, 0xd2, 0x9f, 0x84, 0xd4, 0x25, 0xc8, 0x8d, 0x6b, 0x4e, 0xff, 0x72, 0x7d, 0xf6, 0x6a, 0x7c, 0x01, 0x97 } }, { "abcdefghijklmnopqrstuvwxyz", { 0xca, 0xbd, 0xb1, 0x81, 0x0b, 0x92, 0x47, 0x0a, 0x20, 0x93, 0xaa, 0x6b, 0xce, 0x05, 0x95, 0x2c, 0x28, 0x34, 0x8c, 0xf4, 0x3f, 0xf6, 0x08, 0x41, 0x97, 0x51, 0x66, 0xbb, 0x40, 0xed, 0x23, 0x40, 0x04, 0xb8, 0x82, 0x44, 0x63, 0xe6, 0xb0, 0x09 } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0xd0, 0x34, 0xa7, 0x95, 0x0c, 0xf7, 0x22, 0x02, 0x1b, 0xa4, 0xb8, 0x4d, 0xf7, 0x69, 0xa5, 0xde, 0x20, 0x60, 0xe2, 0x59, 0xdf, 0x4c, 0x9b, 0xb4, 0xa4, 0x26, 0x8c, 0x0e, 0x93, 0x5b, 0xbc, 0x74, 0x70, 0xa9, 0x69, 0xc9, 0xd0, 0x72, 0xa1, 0xac } } }; int i; unsigned char tmp[40]; hash_state md; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { rmd320_init(&md); rmd320_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); rmd320_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD320", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha1.c000066400000000000000000000147051464416617300224660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file sha1.c LTC_SHA1 code by Tom St Denis */ #ifdef LTC_SHA1 const struct ltc_hash_descriptor sha1_desc = { "sha1", 2, 20, 64, /* OID */ { 1, 3, 14, 3, 2, 26, }, 6, &sha1_init, &sha1_process, &sha1_done, &sha1_test, NULL }; #define F0(x,y,z) (z ^ (x & (y ^ z))) #define F1(x,y,z) (x ^ y ^ z) #define F2(x,y,z) ((x & y) | (z & (x | y))) #define F3(x,y,z) (x ^ y ^ z) #ifdef LTC_CLEAN_STACK static int ss_sha1_compress(hash_state *md, const unsigned char *buf) #else static int s_sha1_compress(hash_state *md, const unsigned char *buf) #endif { ulong32 a,b,c,d,e,W[80],i; #ifdef LTC_SMALL_CODE ulong32 t; #endif /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32H(W[i], buf + (4*i)); } /* copy state */ a = md->sha1.state[0]; b = md->sha1.state[1]; c = md->sha1.state[2]; d = md->sha1.state[3]; e = md->sha1.state[4]; /* expand it */ for (i = 16; i < 80; i++) { W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); } /* compress */ /* round one */ #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); #ifdef LTC_SMALL_CODE for (i = 0; i < 20; ) { FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; } for (; i < 40; ) { FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; } for (; i < 60; ) { FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; } for (; i < 80; ) { FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; } #else for (i = 0; i < 20; ) { FF0(a,b,c,d,e,i++); FF0(e,a,b,c,d,i++); FF0(d,e,a,b,c,i++); FF0(c,d,e,a,b,i++); FF0(b,c,d,e,a,i++); } /* round two */ for (; i < 40; ) { FF1(a,b,c,d,e,i++); FF1(e,a,b,c,d,i++); FF1(d,e,a,b,c,i++); FF1(c,d,e,a,b,i++); FF1(b,c,d,e,a,i++); } /* round three */ for (; i < 60; ) { FF2(a,b,c,d,e,i++); FF2(e,a,b,c,d,i++); FF2(d,e,a,b,c,i++); FF2(c,d,e,a,b,i++); FF2(b,c,d,e,a,i++); } /* round four */ for (; i < 80; ) { FF3(a,b,c,d,e,i++); FF3(e,a,b,c,d,i++); FF3(d,e,a,b,c,i++); FF3(c,d,e,a,b,i++); FF3(b,c,d,e,a,i++); } #endif #undef FF0 #undef FF1 #undef FF2 #undef FF3 /* store */ md->sha1.state[0] = md->sha1.state[0] + a; md->sha1.state[1] = md->sha1.state[1] + b; md->sha1.state[2] = md->sha1.state[2] + c; md->sha1.state[3] = md->sha1.state[3] + d; md->sha1.state[4] = md->sha1.state[4] + e; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_sha1_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_sha1_compress(md, buf); burn_stack(sizeof(ulong32) * 87); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha1_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha1.state[0] = 0x67452301UL; md->sha1.state[1] = 0xefcdab89UL; md->sha1.state[2] = 0x98badcfeUL; md->sha1.state[3] = 0x10325476UL; md->sha1.state[4] = 0xc3d2e1f0UL; md->sha1.curlen = 0; md->sha1.length = 0; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (20 bytes) @return CRYPT_OK if successful */ int sha1_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha1.curlen >= sizeof(md->sha1.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->sha1.length += md->sha1.curlen * 8; /* append the '1' bit */ md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha1.curlen > 56) { while (md->sha1.curlen < 64) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } s_sha1_compress(md, md->sha1.buf); md->sha1.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->sha1.curlen < 56) { md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha1.length, md->sha1.buf+56); s_sha1_compress(md, md->sha1.buf); /* copy output */ for (i = 0; i < 5; i++) { STORE32H(md->sha1.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha1_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[20]; } tests[] = { { "abc", { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 } } }; int i; unsigned char tmp[20]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha1_init(&md); sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha1_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/000077500000000000000000000000001464416617300223145ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/sha224.c000066400000000000000000000055421464416617300234710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @param sha224.c LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis) */ #include "tomcrypt_private.h" #if defined(LTC_SHA224) && defined(LTC_SHA256) const struct ltc_hash_descriptor sha224_desc = { "sha224", 10, 28, 64, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 4, }, 9, &sha224_init, &sha256_process, &sha224_done, &sha224_test, NULL }; /* init the sha256 er... sha224 state ;-) */ /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha224_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha256.curlen = 0; md->sha256.length = 0; md->sha256.state[0] = 0xc1059ed8UL; md->sha256.state[1] = 0x367cd507UL; md->sha256.state[2] = 0x3070dd17UL; md->sha256.state[3] = 0xf70e5939UL; md->sha256.state[4] = 0xffc00b31UL; md->sha256.state[5] = 0x68581511UL; md->sha256.state[6] = 0x64f98fa7UL; md->sha256.state[7] = 0xbefa4fa4UL; return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (28 bytes) @return CRYPT_OK if successful */ int sha224_done(hash_state * md, unsigned char *out) { unsigned char buf[32]; int err; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); err = sha256_done(md, buf); XMEMCPY(out, buf, 28); #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return err; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha224_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[28]; } tests[] = { { "abc", { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 } }, }; int i; unsigned char tmp[28]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha224_init(&md); sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha224_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA224", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/sha256.c000066400000000000000000000261531464416617300234770ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file sha256.c LTC_SHA256 by Tom St Denis */ #ifdef LTC_SHA256 const struct ltc_hash_descriptor sha256_desc = { "sha256", 0, 32, 64, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, 9, &sha256_init, &sha256_process, &sha256_done, &sha256_test, NULL }; #ifdef LTC_SMALL_CODE /* the K array */ static const ulong32 K[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; #endif /* Various logical functions */ #define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) RORc((x),(n)) #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) /* compress 512-bits */ #ifdef LTC_CLEAN_STACK static int ss_sha256_compress(hash_state * md, const unsigned char *buf) #else static int s_sha256_compress(hash_state * md, const unsigned char *buf) #endif { ulong32 S[8], W[64], t0, t1; #ifdef LTC_SMALL_CODE ulong32 t; #endif int i; /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->sha256.state[i]; } /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD32H(W[i], buf + (4*i)); } /* fill W[16..63] */ for (i = 16; i < 64; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ #ifdef LTC_SMALL_CODE #define RND(a,b,c,d,e,f,g,h,i) \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; for (i = 0; i < 64; ++i) { RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; } #else #define RND(a,b,c,d,e,f,g,h,i,ki) \ t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); #endif #undef RND /* feedback */ for (i = 0; i < 8; i++) { md->sha256.state[i] = md->sha256.state[i] + S[i]; } return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_sha256_compress(hash_state * md, const unsigned char *buf) { int err; err = ss_sha256_compress(md, buf); burn_stack(sizeof(ulong32) * 74); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha256_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha256.curlen = 0; md->sha256.length = 0; md->sha256.state[0] = 0x6A09E667UL; md->sha256.state[1] = 0xBB67AE85UL; md->sha256.state[2] = 0x3C6EF372UL; md->sha256.state[3] = 0xA54FF53AUL; md->sha256.state[4] = 0x510E527FUL; md->sha256.state[5] = 0x9B05688CUL; md->sha256.state[6] = 0x1F83D9ABUL; md->sha256.state[7] = 0x5BE0CD19UL; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (32 bytes) @return CRYPT_OK if successful */ int sha256_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha256.curlen >= sizeof(md->sha256.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->sha256.length += md->sha256.curlen * 8; /* append the '1' bit */ md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha256.curlen > 56) { while (md->sha256.curlen < 64) { md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; } s_sha256_compress(md, md->sha256.buf); md->sha256.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->sha256.curlen < 56) { md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha256.length, md->sha256.buf+56); s_sha256_compress(md, md->sha256.buf); /* copy output */ for (i = 0; i < 8; i++) { STORE32H(md->sha256.state[i], out+(4*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[32]; } tests[] = { { "abc", { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }, }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha256_init(&md); sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha256_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA256", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/sha384.c000066400000000000000000000064251464416617300235010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @param sha384.c LTC_SHA384 hash included in sha512.c, Tom St Denis */ #include "tomcrypt_private.h" #if defined(LTC_SHA384) && defined(LTC_SHA512) const struct ltc_hash_descriptor sha384_desc = { "sha384", 4, 48, 128, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 2, }, 9, &sha384_init, &sha512_process, &sha384_done, &sha384_test, NULL }; /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha384_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha512.curlen = 0; md->sha512.length = 0; md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8); md->sha512.state[1] = CONST64(0x629a292a367cd507); md->sha512.state[2] = CONST64(0x9159015a3070dd17); md->sha512.state[3] = CONST64(0x152fecd8f70e5939); md->sha512.state[4] = CONST64(0x67332667ffc00b31); md->sha512.state[5] = CONST64(0x8eb44a8768581511); md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7); md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4); return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (48 bytes) @return CRYPT_OK if successful */ int sha384_done(hash_state * md, unsigned char *out) { unsigned char buf[64]; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha512.curlen >= sizeof(md->sha512.buf)) { return CRYPT_INVALID_ARG; } sha512_done(md, buf); XMEMCPY(out, buf, 48); #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha384_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[48]; } tests[] = { { "abc", { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } }, }; int i; unsigned char tmp[48]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha384_init(&md); sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha384_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA384", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/sha512.c000066400000000000000000000230501464416617300234630ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @param sha512.c LTC_SHA512 by Tom St Denis */ #ifdef LTC_SHA512 const struct ltc_hash_descriptor sha512_desc = { "sha512", 5, 64, 128, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, 9, &sha512_init, &sha512_process, &sha512_done, &sha512_test, NULL }; /* the K array */ static const ulong64 K[80] = { CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) }; /* Various logical functions */ #define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) ROR64c(x, n) #define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n)) #define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) #define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) #define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) #define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) /* compress 1024-bits */ #ifdef LTC_CLEAN_STACK static int ss_sha512_compress(hash_state * md, const unsigned char *buf) #else static int s_sha512_compress(hash_state * md, const unsigned char *buf) #endif { ulong64 S[8], W[80], t0, t1; int i; /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->sha512.state[i]; } /* copy the state into 1024-bits into W[0..15] */ for (i = 0; i < 16; i++) { LOAD64H(W[i], buf + (8*i)); } /* fill W[16..79] */ for (i = 16; i < 80; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ #ifdef LTC_SMALL_CODE for (i = 0; i < 80; i++) { t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; S[4] = S[3] + t0; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t0 + t1; } #else #define RND(a,b,c,d,e,f,g,h,i) \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; for (i = 0; i < 80; i += 8) { RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); } #endif /* feedback */ for (i = 0; i < 8; i++) { md->sha512.state[i] = md->sha512.state[i] + S[i]; } return CRYPT_OK; } /* compress 1024-bits */ #ifdef LTC_CLEAN_STACK static int s_sha512_compress(hash_state * md, const unsigned char *buf) { int err; err = ss_sha512_compress(md, buf); burn_stack(sizeof(ulong64) * 90 + sizeof(int)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha512_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha512.curlen = 0; md->sha512.length = 0; md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); md->sha512.state[4] = CONST64(0x510e527fade682d1); md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); md->sha512.state[7] = CONST64(0x5be0cd19137e2179); return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(sha512_process, s_sha512_compress, sha512, 128) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (64 bytes) @return CRYPT_OK if successful */ int sha512_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha512.curlen >= sizeof(md->sha512.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->sha512.length += md->sha512.curlen * CONST64(8); /* append the '1' bit */ md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; /* if the length is currently above 112 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->sha512.curlen > 112) { while (md->sha512.curlen < 128) { md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; } s_sha512_compress(md, md->sha512.buf); md->sha512.curlen = 0; } /* pad upto 120 bytes of zeroes * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash * > 2^64 bits of data... :-) */ while (md->sha512.curlen < 120) { md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->sha512.length, md->sha512.buf+120); s_sha512_compress(md, md->sha512.buf); /* copy output */ for (i = 0; i < 8; i++) { STORE64H(md->sha512.state[i], out+(8*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha512_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[64]; } tests[] = { { "abc", { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } }, }; int i; unsigned char tmp[64]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha512_init(&md); sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha512_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/sha512_224.c000066400000000000000000000060601464416617300240540ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @param sha512_224.c SHA512/224 hash included in sha512.c */ #include "tomcrypt_private.h" #if defined(LTC_SHA512_224) && defined(LTC_SHA512) const struct ltc_hash_descriptor sha512_224_desc = { "sha512-224", 15, 28, 128, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 5, }, 9, &sha512_224_init, &sha512_process, &sha512_224_done, &sha512_224_test, NULL }; /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha512_224_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha512.curlen = 0; md->sha512.length = 0; md->sha512.state[0] = CONST64(0x8C3D37C819544DA2); md->sha512.state[1] = CONST64(0x73E1996689DCD4D6); md->sha512.state[2] = CONST64(0x1DFAB7AE32FF9C82); md->sha512.state[3] = CONST64(0x679DD514582F9FCF); md->sha512.state[4] = CONST64(0x0F6D2B697BD44DA8); md->sha512.state[5] = CONST64(0x77E36F7304C48942); md->sha512.state[6] = CONST64(0x3F9D85A86A1D36C8); md->sha512.state[7] = CONST64(0x1112E6AD91D692A1); return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (48 bytes) @return CRYPT_OK if successful */ int sha512_224_done(hash_state * md, unsigned char *out) { unsigned char buf[64]; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha512.curlen >= sizeof(md->sha512.buf)) { return CRYPT_INVALID_ARG; } sha512_done(md, buf); XMEMCPY(out, buf, 28); #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha512_224_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[28]; } tests[] = { { "abc", { 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, 0x3E, 0x89, 0x24, 0xAA } }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", { 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, 0x68, 0x67, 0x4A, 0xF9 } }, }; int i; unsigned char tmp[28]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha512_224_init(&md); sha512_224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha512_224_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-224", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha2/sha512_256.c000066400000000000000000000061401464416617300240600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @param sha512_256.c SHA512/256 hash included in sha512.c */ #include "tomcrypt_private.h" #if defined(LTC_SHA512_256) && defined(LTC_SHA512) const struct ltc_hash_descriptor sha512_256_desc = { "sha512-256", 16, 32, 128, /* OID */ { 2, 16, 840, 1, 101, 3, 4, 2, 6, }, 9, &sha512_256_init, &sha512_process, &sha512_256_done, &sha512_256_test, NULL }; /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int sha512_256_init(hash_state * md) { LTC_ARGCHK(md != NULL); md->sha512.curlen = 0; md->sha512.length = 0; md->sha512.state[0] = CONST64(0x22312194FC2BF72C); md->sha512.state[1] = CONST64(0x9F555FA3C84C64C2); md->sha512.state[2] = CONST64(0x2393B86B6F53B151); md->sha512.state[3] = CONST64(0x963877195940EABD); md->sha512.state[4] = CONST64(0x96283EE2A88EFFE3); md->sha512.state[5] = CONST64(0xBE5E1E2553863992); md->sha512.state[6] = CONST64(0x2B0199FC2C85B8AA); md->sha512.state[7] = CONST64(0x0EB72DDC81C52CA2); return CRYPT_OK; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (48 bytes) @return CRYPT_OK if successful */ int sha512_256_done(hash_state * md, unsigned char *out) { unsigned char buf[64]; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->sha512.curlen >= sizeof(md->sha512.buf)) { return CRYPT_INVALID_ARG; } sha512_done(md, buf); XMEMCPY(out, buf, 32); #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha512_256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[32]; } tests[] = { { "abc", { 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 } }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", { 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A } }, }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha512_256_init(&md); sha512_256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); sha512_256_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-265", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha3.c000066400000000000000000000263211464416617300224650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* based on https://github.com/brainhub/SHA3IUF (public domain) */ #include "tomcrypt_private.h" #ifdef LTC_SHA3 const struct ltc_hash_descriptor sha3_224_desc = { "sha3-224", /* name of hash */ 17, /* internal ID */ 28, /* Size of digest in octets */ 144, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_224_init, &sha3_process, &sha3_done, &sha3_224_test, NULL }; const struct ltc_hash_descriptor sha3_256_desc = { "sha3-256", /* name of hash */ 18, /* internal ID */ 32, /* Size of digest in octets */ 136, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_256_init, &sha3_process, &sha3_done, &sha3_256_test, NULL }; const struct ltc_hash_descriptor sha3_384_desc = { "sha3-384", /* name of hash */ 19, /* internal ID */ 48, /* Size of digest in octets */ 104, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_384_init, &sha3_process, &sha3_done, &sha3_384_test, NULL }; const struct ltc_hash_descriptor sha3_512_desc = { "sha3-512", /* name of hash */ 20, /* internal ID */ 64, /* Size of digest in octets */ 72, /* Input block size in octets */ { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */ 9, /* Length OID */ &sha3_512_init, &sha3_process, &sha3_done, &sha3_512_test, NULL }; #endif #ifdef LTC_KECCAK const struct ltc_hash_descriptor keccak_224_desc = { "keccak224", /* name of hash */ 29, /* internal ID */ 28, /* Size of digest in octets */ 144, /* Input block size in octets */ { 0 }, 0, /* no ASN.1 OID */ &sha3_224_init, &sha3_process, &keccak_done, &keccak_224_test, NULL }; const struct ltc_hash_descriptor keccak_256_desc = { "keccak256", /* name of hash */ 30, /* internal ID */ 32, /* Size of digest in octets */ 136, /* Input block size in octets */ { 0 }, 0, /* no ASN.1 OID */ &sha3_256_init, &sha3_process, &keccak_done, &keccak_256_test, NULL }; const struct ltc_hash_descriptor keccak_384_desc = { "keccak384", /* name of hash */ 31, /* internal ID */ 48, /* Size of digest in octets */ 104, /* Input block size in octets */ { 0 }, 0, /* no ASN.1 OID */ &sha3_384_init, &sha3_process, &keccak_done, &keccak_384_test, NULL }; const struct ltc_hash_descriptor keccak_512_desc = { "keccak512", /* name of hash */ 32, /* internal ID */ 64, /* Size of digest in octets */ 72, /* Input block size in octets */ { 0 }, 0, /* no ASN.1 OID */ &sha3_512_init, &sha3_process, &keccak_done, &keccak_512_test, NULL }; #endif #if defined(LTC_SHA3) || defined(LTC_KECCAK) #define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */ #define SHA3_KECCAK_ROUNDS 24 static const ulong64 s_keccakf_rndc[24] = { CONST64(0x0000000000000001), CONST64(0x0000000000008082), CONST64(0x800000000000808a), CONST64(0x8000000080008000), CONST64(0x000000000000808b), CONST64(0x0000000080000001), CONST64(0x8000000080008081), CONST64(0x8000000000008009), CONST64(0x000000000000008a), CONST64(0x0000000000000088), CONST64(0x0000000080008009), CONST64(0x000000008000000a), CONST64(0x000000008000808b), CONST64(0x800000000000008b), CONST64(0x8000000000008089), CONST64(0x8000000000008003), CONST64(0x8000000000008002), CONST64(0x8000000000000080), CONST64(0x000000000000800a), CONST64(0x800000008000000a), CONST64(0x8000000080008081), CONST64(0x8000000000008080), CONST64(0x0000000080000001), CONST64(0x8000000080008008) }; static const unsigned s_keccakf_rotc[24] = { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 }; static const unsigned s_keccakf_piln[24] = { 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 }; static void s_keccakf(ulong64 s[25]) { int i, j, round; ulong64 t, bc[5]; for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) { /* Theta */ for(i = 0; i < 5; i++) { bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; } for(i = 0; i < 5; i++) { t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1); for(j = 0; j < 25; j += 5) { s[j + i] ^= t; } } /* Rho Pi */ t = s[1]; for(i = 0; i < 24; i++) { j = s_keccakf_piln[i]; bc[0] = s[j]; s[j] = ROL64(t, s_keccakf_rotc[i]); t = bc[0]; } /* Chi */ for(j = 0; j < 25; j += 5) { for(i = 0; i < 5; i++) { bc[i] = s[j + i]; } for(i = 0; i < 5; i++) { s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; } } /* Iota */ s[0] ^= s_keccakf_rndc[round]; } } static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad) { unsigned i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(hash != NULL); md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8))); md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); s_keccakf(md->sha3.s); /* store sha3.s[] as little-endian bytes into sha3.sb */ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); } XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4); return CRYPT_OK; } /* Public Inteface */ int sha3_224_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_256_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_384_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64)); return CRYPT_OK; } int sha3_512_init(hash_state *md) { LTC_ARGCHK(md != NULL); XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64)); return CRYPT_OK; } #ifdef LTC_SHA3 int sha3_shake_init(hash_state *md, int num) { LTC_ARGCHK(md != NULL); if (num != 128 && num != 256) return CRYPT_INVALID_ARG; XMEMSET(&md->sha3, 0, sizeof(md->sha3)); md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64))); return CRYPT_OK; } #endif int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen) { /* 0...7 -- how much is needed to have a word */ unsigned old_tail = (8 - md->sha3.byte_index) & 7; unsigned long words; unsigned tail; unsigned long i; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(md != NULL); LTC_ARGCHK(in != NULL); if(inlen < old_tail) { /* have no complete word or haven't started the word yet */ while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); return CRYPT_OK; } if(old_tail) { /* will have one word to process */ inlen -= old_tail; while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); /* now ready to add saved to the sponge */ md->sha3.s[md->sha3.word_index] ^= md->sha3.saved; md->sha3.byte_index = 0; md->sha3.saved = 0; if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { s_keccakf(md->sha3.s); md->sha3.word_index = 0; } } /* now work in full words directly from input */ words = inlen / sizeof(ulong64); tail = inlen - words * sizeof(ulong64); for(i = 0; i < words; i++, in += sizeof(ulong64)) { ulong64 t; LOAD64L(t, in); md->sha3.s[md->sha3.word_index] ^= t; if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { s_keccakf(md->sha3.s); md->sha3.word_index = 0; } } /* finally, save the partial word */ while (tail--) { md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); } return CRYPT_OK; } #ifdef LTC_SHA3 int sha3_done(hash_state *md, unsigned char *out) { return ss_done(md, out, CONST64(0x06)); } #endif #ifdef LTC_KECCAK int keccak_done(hash_state *md, unsigned char *out) { return ss_done(md, out, CONST64(0x01)); } #endif #ifdef LTC_SHA3 int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen) { /* IMPORTANT NOTE: sha3_shake_done can be called many times */ unsigned long idx; unsigned i; if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (!md->sha3.xof_flag) { /* shake_xof operation must be done only once */ md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8))); md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); s_keccakf(md->sha3.s); /* store sha3.s[] as little-endian bytes into sha3.sb */ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); } md->sha3.byte_index = 0; md->sha3.xof_flag = 1; } for (idx = 0; idx < outlen; idx++) { if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) { s_keccakf(md->sha3.s); /* store sha3.s[] as little-endian bytes into sha3.sb */ for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); } md->sha3.byte_index = 0; } out[idx] = md->sha3.sb[md->sha3.byte_index++]; } return CRYPT_OK; } int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen) { hash_state md; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err; if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err; if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err; return CRYPT_OK; } #endif #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/sha3_test.c000066400000000000000000000637311464416617300235320ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* based on https://github.com/brainhub/SHA3IUF (public domain) */ #include "tomcrypt_private.h" #ifdef LTC_SHA3 int sha3_224_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char buf[200], hash[224 / 8]; int i; hash_state c; const unsigned char c1 = 0xa3; const unsigned char sha3_224_empty[224 / 8] = { 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, 0x5b, 0x5a, 0x6b, 0xc7 }; const unsigned char sha3_224_0xa3_200_times[224 / 8] = { 0x93, 0x76, 0x81, 0x6a, 0xba, 0x50, 0x3f, 0x72, 0xf9, 0x6c, 0xe7, 0xeb, 0x65, 0xac, 0x09, 0x5d, 0xee, 0xe3, 0xbe, 0x4b, 0xf9, 0xbb, 0xc2, 0xa1, 0xcb, 0x7e, 0x11, 0xe0 }; XMEMSET(buf, c1, sizeof(buf)); /* SHA3-224 on an empty buffer */ sha3_224_init(&c); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_224_empty, sizeof(sha3_224_empty), "SHA3-224", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-224 in two steps. [FIPS 202] */ sha3_224_init(&c); sha3_process(&c, buf, sizeof(buf) / 2); sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 1)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-224 byte-by-byte: 200 steps. [FIPS 202] */ i = 200; sha3_224_init(&c); while (i--) { sha3_process(&c, &c1, 1); } sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 2)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int sha3_256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char buf[200], hash[256 / 8]; int i; hash_state c; const unsigned char c1 = 0xa3; const unsigned char sha3_256_empty[256 / 8] = { 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a }; const unsigned char sha3_256_0xa3_200_times[256 / 8] = { 0x79, 0xf3, 0x8a, 0xde, 0xc5, 0xc2, 0x03, 0x07, 0xa9, 0x8e, 0xf7, 0x6e, 0x83, 0x24, 0xaf, 0xbf, 0xd4, 0x6c, 0xfd, 0x81, 0xb2, 0x2e, 0x39, 0x73, 0xc6, 0x5f, 0xa1, 0xbd, 0x9d, 0xe3, 0x17, 0x87 }; XMEMSET(buf, c1, sizeof(buf)); /* SHA3-256 on an empty buffer */ sha3_256_init(&c); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_256_empty, sizeof(sha3_256_empty), "SHA3-256", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-256 as a single buffer. [FIPS 202] */ sha3_256_init(&c); sha3_process(&c, buf, sizeof(buf)); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 1)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-256 in two steps. [FIPS 202] */ sha3_256_init(&c); sha3_process(&c, buf, sizeof(buf) / 2); sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 2)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */ i = 200; sha3_256_init(&c); while (i--) { sha3_process(&c, &c1, 1); } sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 3)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output * matched with sha3sum. */ sha3_256_init(&c); sha3_process(&c, (unsigned char*) "\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a" "\x93\xd1\x56\x43\xd7\x18\x1d\x2a" "\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f" "\x20\xed\x21\xf1\x47\xbe\xf7\x32" "\xbf\x3a\x60\xef\x40\x67\xc3\x73" "\x4b\x85\xbc\x8c\xd4\x71\x78\x0f" "\x10\xdc\x9e\x82\x91\xb5\x83\x39" "\xa6\x77\xb9\x60\x21\x8f\x71\xe7" "\x93\xf2\x79\x7a\xea\x34\x94\x06" "\x51\x28\x29\x06\x5d\x37\xbb\x55" "\xea\x79\x6f\xa4\xf5\x6f\xd8\x89" "\x6b\x49\xb2\xcd\x19\xb4\x32\x15" "\xad\x96\x7c\x71\x2b\x24\xe5\x03" "\x2d\x06\x52\x32\xe0\x2c\x12\x74" "\x09\xd2\xed\x41\x46\xb9\xd7\x5d" "\x76\x3d\x52\xdb\x98\xd9\x49\xd3" "\xb0\xfe\xd6\xa8\x05\x2f\xbb", 1080 / 8); sha3_done(&c, hash); if(compare_testvector(hash, sizeof(hash), "\xa1\x9e\xee\x92\xbb\x20\x97\xb6" "\x4e\x82\x3d\x59\x77\x98\xaa\x18" "\xbe\x9b\x7c\x73\x6b\x80\x59\xab" "\xfd\x67\x79\xac\x35\xac\x81\xb5", 256 / 8, "SHA3-256", 4)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int sha3_384_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char buf[200], hash[384 / 8]; int i; hash_state c; const unsigned char c1 = 0xa3; const unsigned char sha3_384_0xa3_200_times[384 / 8] = { 0x18, 0x81, 0xde, 0x2c, 0xa7, 0xe4, 0x1e, 0xf9, 0x5d, 0xc4, 0x73, 0x2b, 0x8f, 0x5f, 0x00, 0x2b, 0x18, 0x9c, 0xc1, 0xe4, 0x2b, 0x74, 0x16, 0x8e, 0xd1, 0x73, 0x26, 0x49, 0xce, 0x1d, 0xbc, 0xdd, 0x76, 0x19, 0x7a, 0x31, 0xfd, 0x55, 0xee, 0x98, 0x9f, 0x2d, 0x70, 0x50, 0xdd, 0x47, 0x3e, 0x8f }; XMEMSET(buf, c1, sizeof(buf)); /* SHA3-384 as a single buffer. [FIPS 202] */ sha3_384_init(&c); sha3_process(&c, buf, sizeof(buf)); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-384 in two steps. [FIPS 202] */ sha3_384_init(&c); sha3_process(&c, buf, sizeof(buf) / 2); sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 1)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */ i = 200; sha3_384_init(&c); while (i--) { sha3_process(&c, &c1, 1); } sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 2)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int sha3_512_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char buf[200], hash[512 / 8]; int i; hash_state c; const unsigned char c1 = 0xa3; const unsigned char sha3_512_0xa3_200_times[512 / 8] = { 0xe7, 0x6d, 0xfa, 0xd2, 0x20, 0x84, 0xa8, 0xb1, 0x46, 0x7f, 0xcf, 0x2f, 0xfa, 0x58, 0x36, 0x1b, 0xec, 0x76, 0x28, 0xed, 0xf5, 0xf3, 0xfd, 0xc0, 0xe4, 0x80, 0x5d, 0xc4, 0x8c, 0xae, 0xec, 0xa8, 0x1b, 0x7c, 0x13, 0xc3, 0x0a, 0xdf, 0x52, 0xa3, 0x65, 0x95, 0x84, 0x73, 0x9a, 0x2d, 0xf4, 0x6b, 0xe5, 0x89, 0xc5, 0x1c, 0xa1, 0xa4, 0xa8, 0x41, 0x6d, 0xf6, 0x54, 0x5a, 0x1c, 0xe8, 0xba, 0x00 }; XMEMSET(buf, c1, sizeof(buf)); /* SHA3-512 as a single buffer. [FIPS 202] */ sha3_512_init(&c); sha3_process(&c, buf, sizeof(buf)); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-512 in two steps. [FIPS 202] */ sha3_512_init(&c); sha3_process(&c, buf, sizeof(buf) / 2); sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 1)) { return CRYPT_FAIL_TESTVECTOR; } /* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */ i = 200; sha3_512_init(&c); while (i--) { sha3_process(&c, &c1, 1); } sha3_done(&c, hash); if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 2)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int sha3_shake_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char buf[200], hash[512]; int i; hash_state c; const unsigned char c1 = 0xa3; unsigned long len; const unsigned char shake256_empty[32] = { 0xab, 0x0b, 0xae, 0x31, 0x63, 0x39, 0x89, 0x43, 0x04, 0xe3, 0x58, 0x77, 0xb0, 0xc2, 0x8a, 0x9b, 0x1f, 0xd1, 0x66, 0xc7, 0x96, 0xb9, 0xcc, 0x25, 0x8a, 0x06, 0x4a, 0x8f, 0x57, 0xe2, 0x7f, 0x2a }; const unsigned char shake256_0xa3_200_times[32] = { 0x6a, 0x1a, 0x9d, 0x78, 0x46, 0x43, 0x6e, 0x4d, 0xca, 0x57, 0x28, 0xb6, 0xf7, 0x60, 0xee, 0xf0, 0xca, 0x92, 0xbf, 0x0b, 0xe5, 0x61, 0x5e, 0x96, 0x95, 0x9d, 0x76, 0x71, 0x97, 0xa0, 0xbe, 0xeb }; const unsigned char shake128_empty[32] = { 0x43, 0xe4, 0x1b, 0x45, 0xa6, 0x53, 0xf2, 0xa5, 0xc4, 0x49, 0x2c, 0x1a, 0xdd, 0x54, 0x45, 0x12, 0xdd, 0xa2, 0x52, 0x98, 0x33, 0x46, 0x2b, 0x71, 0xa4, 0x1a, 0x45, 0xbe, 0x97, 0x29, 0x0b, 0x6f }; const unsigned char shake128_0xa3_200_times[32] = { 0x44, 0xc9, 0xfb, 0x35, 0x9f, 0xd5, 0x6a, 0xc0, 0xa9, 0xa7, 0x5a, 0x74, 0x3c, 0xff, 0x68, 0x62, 0xf1, 0x7d, 0x72, 0x59, 0xab, 0x07, 0x52, 0x16, 0xc0, 0x69, 0x95, 0x11, 0x64, 0x3b, 0x64, 0x39 }; XMEMSET(buf, c1, sizeof(buf)); /* SHAKE256 on an empty buffer */ sha3_shake_init(&c, 256); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake256_empty), shake256_empty, sizeof(shake256_empty), "SHAKE256", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE256 via sha3_shake_memory [FIPS 202] */ len = 512; sha3_shake_memory(256, buf, sizeof(buf), hash, &len); if (compare_testvector(hash + 480, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 1)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE256 as a single buffer. [FIPS 202] */ sha3_shake_init(&c, 256); sha3_shake_process(&c, buf, sizeof(buf)); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 2)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE256 in two steps. [FIPS 202] */ sha3_shake_init(&c, 256); sha3_shake_process(&c, buf, sizeof(buf) / 2); sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 3)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE256 byte-by-byte: 200 steps. [FIPS 202] */ i = 200; sha3_shake_init(&c, 256); while (i--) sha3_shake_process(&c, &c1, 1); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 4)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE128 on an empty buffer */ sha3_shake_init(&c, 128); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake128_empty), shake128_empty, sizeof(shake128_empty), "SHAKE128", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE128 via sha3_shake_memory [FIPS 202] */ len = 512; sha3_shake_memory(128, buf, sizeof(buf), hash, &len); if (compare_testvector(hash + 480, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 1)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE128 as a single buffer. [FIPS 202] */ sha3_shake_init(&c, 128); sha3_shake_process(&c, buf, sizeof(buf)); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 2)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE128 in two steps. [FIPS 202] */ sha3_shake_init(&c, 128); sha3_shake_process(&c, buf, sizeof(buf) / 2); sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 3)) { return CRYPT_FAIL_TESTVECTOR; } /* SHAKE128 byte-by-byte: 200 steps. [FIPS 202] */ i = 200; sha3_shake_init(&c, 128); while (i--) sha3_shake_process(&c, &c1, 1); for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 4)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif #ifdef LTC_KECCAK int keccak_224_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else hash_state c; unsigned char hash[MAXBLOCKSIZE]; keccak_224_init(&c); keccak_process(&c, (unsigned char*) "\xcc", 1); keccak_done(&c, hash); if(compare_testvector(hash, 28, "\xa9\xca\xb5\x9e\xb4\x0a\x10\xb2" "\x46\x29\x0f\x2d\x60\x86\xe3\x2e" "\x36\x89\xfa\xf1\xd2\x6b\x47\x0c" "\x89\x9f\x28\x02", 28, "KECCAK-224", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_224_init(&c); keccak_process(&c, (unsigned char*)"\x41\xfb", 2); keccak_done(&c, hash); if(compare_testvector(hash, 28, "\x61\x5b\xa3\x67\xaf\xdc\x35\xaa" "\xc3\x97\xbc\x7e\xb5\xd5\x8d\x10" "\x6a\x73\x4b\x24\x98\x6d\x5d\x97" "\x8f\xef\xd6\x2c", 28, "KECCAK-224", 1) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_224_init(&c); keccak_process(&c, (unsigned char*) "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); keccak_done(&c, hash); if(compare_testvector(hash, 28, "\x56\x79\xcd\x50\x9c\x51\x20\xaf" "\x54\x79\x5c\xf4\x77\x14\x96\x41" "\xcf\x27\xb2\xeb\xb6\xa5\xf9\x03" "\x40\x70\x4e\x57", 28, "KECCAK-224", 2) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_224_init(&c); keccak_process(&c, (unsigned char*) "\x43\x3c\x53\x03\x13\x16\x24\xc0" "\x02\x1d\x86\x8a\x30\x82\x54\x75" "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" "\x03\x98\xf4\xca\x44\x23\xb9\x82" "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" "\x92\xcc\x1b\x06\xce\xdf\x32\x24" "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" "\x6d\xcb\xb4\xce", 100); keccak_done(&c, hash); if(compare_testvector(hash, 28, "\x62\xb1\x0f\x1b\x62\x36\xeb\xc2" "\xda\x72\x95\x77\x42\xa8\xd4\xe4" "\x8e\x21\x3b\x5f\x89\x34\x60\x4b" "\xfd\x4d\x2c\x3a", 28, "KECCAK-224", 3) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int keccak_256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else hash_state c; unsigned char hash[MAXBLOCKSIZE]; keccak_256_init(&c); keccak_process(&c, (unsigned char*) "\xcc", 1); keccak_done(&c, hash); if(compare_testvector(hash, 32, "\xee\xad\x6d\xbf\xc7\x34\x0a\x56" "\xca\xed\xc0\x44\x69\x6a\x16\x88" "\x70\x54\x9a\x6a\x7f\x6f\x56\x96" "\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 32, "KECCAK-256", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_256_init(&c); keccak_process(&c, (unsigned char*)"\x41\xfb", 2); keccak_done(&c, hash); if(compare_testvector(hash, 32, "\xa8\xea\xce\xda\x4d\x47\xb3\x28" "\x1a\x79\x5a\xd9\xe1\xea\x21\x22" "\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1" "\x8b\x57\x17\xb7\x87\x35\x37\xd2", 32, "KECCAK-256", 1) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_256_init(&c); keccak_process(&c, (unsigned char*) "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); keccak_done(&c, hash); if(compare_testvector(hash, 32, "\x0e\x32\xde\xfa\x20\x71\xf0\xb5" "\xac\x0e\x6a\x10\x8b\x84\x2e\xd0" "\xf1\xd3\x24\x97\x12\xf5\x8e\xe0" "\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 32, "KECCAK-256", 2) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_256_init(&c); keccak_process(&c, (unsigned char*) "\x43\x3c\x53\x03\x13\x16\x24\xc0" "\x02\x1d\x86\x8a\x30\x82\x54\x75" "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" "\x03\x98\xf4\xca\x44\x23\xb9\x82" "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" "\x92\xcc\x1b\x06\xce\xdf\x32\x24" "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" "\x6d\xcb\xb4\xce", 100); keccak_done(&c, hash); if(compare_testvector(hash, 32, "\xce\x87\xa5\x17\x3b\xff\xd9\x23" "\x99\x22\x16\x58\xf8\x01\xd4\x5c" "\x29\x4d\x90\x06\xee\x9f\x3f\x9d" "\x41\x9c\x8d\x42\x77\x48\xdc\x41", 32, "KECCAK-256", 3) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int keccak_384_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else hash_state c; unsigned char hash[MAXBLOCKSIZE]; keccak_384_init(&c); keccak_process(&c, (unsigned char*) "\xcc", 1); keccak_done(&c, hash); if(compare_testvector(hash, 48, "\x1b\x84\xe6\x2a\x46\xe5\xa2\x01" "\x86\x17\x54\xaf\x5d\xc9\x5c\x4a" "\x1a\x69\xca\xf4\xa7\x96\xae\x40" "\x56\x80\x16\x1e\x29\x57\x26\x41" "\xf5\xfa\x1e\x86\x41\xd7\x95\x83" "\x36\xee\x7b\x11\xc5\x8f\x73\xe9", 48, "KECCAK-384", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_384_init(&c); keccak_process(&c, (unsigned char*)"\x41\xfb", 2); keccak_done(&c, hash); if(compare_testvector(hash, 48, "\x49\x5c\xce\x27\x14\xcd\x72\xc8" "\xc5\x3c\x33\x63\xd2\x2c\x58\xb5" "\x59\x60\xfe\x26\xbe\x0b\xf3\xbb" "\xc7\xa3\x31\x6d\xd5\x63\xad\x1d" "\xb8\x41\x0e\x75\xee\xfe\xa6\x55" "\xe3\x9d\x46\x70\xec\x0b\x17\x92", 48, "KECCAK-384", 1) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_384_init(&c); keccak_process(&c, (unsigned char*) "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); keccak_done(&c, hash); if(compare_testvector(hash, 48, "\x18\x42\x2a\xc1\xd3\xa1\xe5\x4b" "\xad\x87\x68\x83\xd2\xd6\xdd\x65" "\xf6\x5c\x1d\x5f\x33\xa7\x12\x5c" "\xc4\xc1\x86\x40\x5a\x12\xed\x64" "\xba\x96\x67\x2e\xed\xda\x8c\x5a" "\x63\x31\xd2\x86\x83\xf4\x88\xeb", 48, "KECCAK-384", 2) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_384_init(&c); keccak_process(&c, (unsigned char*) "\x43\x3c\x53\x03\x13\x16\x24\xc0" "\x02\x1d\x86\x8a\x30\x82\x54\x75" "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" "\x03\x98\xf4\xca\x44\x23\xb9\x82" "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" "\x92\xcc\x1b\x06\xce\xdf\x32\x24" "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" "\x6d\xcb\xb4\xce", 100); keccak_done(&c, hash); if(compare_testvector(hash, 48, "\x13\x51\x14\x50\x8d\xd6\x3e\x27" "\x9e\x70\x9c\x26\xf7\x81\x7c\x04" "\x82\x76\x6c\xde\x49\x13\x2e\x3e" "\xdf\x2e\xed\xd8\x99\x6f\x4e\x35" "\x96\xd1\x84\x10\x0b\x38\x48\x68" "\x24\x9f\x1d\x8b\x8f\xda\xa2\xc9", 48, "KECCAK-384", 3) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } int keccak_512_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else hash_state c; unsigned char hash[MAXBLOCKSIZE]; keccak_512_init(&c); keccak_process(&c, (unsigned char*) "\xcc", 1); keccak_done(&c, hash); if(compare_testvector(hash, 64, "\x86\x30\xc1\x3c\xbd\x06\x6e\xa7" "\x4b\xbe\x7f\xe4\x68\xfe\xc1\xde" "\xe1\x0e\xdc\x12\x54\xfb\x4c\x1b" "\x7c\x5f\xd6\x9b\x64\x6e\x44\x16" "\x0b\x8c\xe0\x1d\x05\xa0\x90\x8c" "\xa7\x90\xdf\xb0\x80\xf4\xb5\x13" "\xbc\x3b\x62\x25\xec\xe7\xa8\x10" "\x37\x14\x41\xa5\xac\x66\x6e\xb9", 64, "KECCAK-512", 0) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_512_init(&c); keccak_process(&c, (unsigned char*)"\x41\xfb", 2); keccak_done(&c, hash); if(compare_testvector(hash, 64, "\x55\x1d\xa6\x23\x6f\x8b\x96\xfc" "\xe9\xf9\x7f\x11\x90\xe9\x01\x32" "\x4f\x0b\x45\xe0\x6d\xbb\xb5\xcd" "\xb8\x35\x5d\x6e\xd1\xdc\x34\xb3" "\xf0\xea\xe7\xdc\xb6\x86\x22\xff" "\x23\x2f\xa3\xce\xce\x0d\x46\x16" "\xcd\xeb\x39\x31\xf9\x38\x03\x66" "\x2a\x28\xdf\x1c\xd5\x35\xb7\x31", 64, "KECCAK-512", 1) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_512_init(&c); keccak_process(&c, (unsigned char*) "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); keccak_done(&c, hash); if(compare_testvector(hash, 64, "\x4b\x39\xd3\xda\x5b\xcd\xf4\xd9" "\xb7\x69\x01\x59\x95\x64\x43\x11" "\xc1\x4c\x43\x5b\xf7\x2b\x10\x09" "\xd6\xdd\x71\xb0\x1a\x63\xb9\x7c" "\xfb\x59\x64\x18\xe8\xe4\x23\x42" "\xd1\x17\xe0\x74\x71\xa8\x91\x43" "\x14\xba\x7b\x0e\x26\x4d\xad\xf0" "\xce\xa3\x81\x86\x8c\xbd\x43\xd1", 64, "KECCAK-512", 2) != 0) { return CRYPT_FAIL_TESTVECTOR; } keccak_512_init(&c); keccak_process(&c, (unsigned char*) "\x43\x3c\x53\x03\x13\x16\x24\xc0" "\x02\x1d\x86\x8a\x30\x82\x54\x75" "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" "\x03\x98\xf4\xca\x44\x23\xb9\x82" "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" "\x92\xcc\x1b\x06\xce\xdf\x32\x24" "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" "\x6d\xcb\xb4\xce", 100); keccak_done(&c, hash); if(compare_testvector(hash, 64, "\x52\x7d\x28\xe3\x41\xe6\xb1\x4f" "\x46\x84\xad\xb4\xb8\x24\xc4\x96" "\xc6\x48\x2e\x51\x14\x95\x65\xd3" "\xd1\x72\x26\x82\x88\x84\x30\x6b" "\x51\xd6\x14\x8a\x72\x62\x2c\x2b" "\x75\xf5\xd3\x51\x0b\x79\x9d\x8b" "\xdc\x03\xea\xed\xe4\x53\x67\x6a" "\x6e\xc8\xfe\x03\xa1\xad\x0e\xab", 64, "KECCAK-512", 3) != 0) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/tiger.c000066400000000000000000001517641464416617300227530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file tiger.c Tiger hash function, Tom St Denis */ #ifdef LTC_TIGER const struct ltc_hash_descriptor tiger_desc = { "tiger", 1, 24, 64, /* OID */ { 1, 3, 6, 1, 4, 1, 11591, 12, 2, }, 9, &tiger_init, &tiger_process, &tiger_done, &tiger_test, NULL }; const struct ltc_hash_descriptor tiger2_desc = { "tiger2", 33, 24, 64, /* OID ... does not exist */ { 0 }, 0, &tiger2_init, &tiger_process, &tiger_done, &tiger2_test, NULL }; #define t1 (table) #define t2 (table+256) #define t3 (table+256*2) #define t4 (table+256*3) static const ulong64 table[4*256] = { CONST64(0x02AAB17CF7E90C5E) /* 0 */, CONST64(0xAC424B03E243A8EC) /* 1 */, CONST64(0x72CD5BE30DD5FCD3) /* 2 */, CONST64(0x6D019B93F6F97F3A) /* 3 */, CONST64(0xCD9978FFD21F9193) /* 4 */, CONST64(0x7573A1C9708029E2) /* 5 */, CONST64(0xB164326B922A83C3) /* 6 */, CONST64(0x46883EEE04915870) /* 7 */, CONST64(0xEAACE3057103ECE6) /* 8 */, CONST64(0xC54169B808A3535C) /* 9 */, CONST64(0x4CE754918DDEC47C) /* 10 */, CONST64(0x0AA2F4DFDC0DF40C) /* 11 */, CONST64(0x10B76F18A74DBEFA) /* 12 */, CONST64(0xC6CCB6235AD1AB6A) /* 13 */, CONST64(0x13726121572FE2FF) /* 14 */, CONST64(0x1A488C6F199D921E) /* 15 */, CONST64(0x4BC9F9F4DA0007CA) /* 16 */, CONST64(0x26F5E6F6E85241C7) /* 17 */, CONST64(0x859079DBEA5947B6) /* 18 */, CONST64(0x4F1885C5C99E8C92) /* 19 */, CONST64(0xD78E761EA96F864B) /* 20 */, CONST64(0x8E36428C52B5C17D) /* 21 */, CONST64(0x69CF6827373063C1) /* 22 */, CONST64(0xB607C93D9BB4C56E) /* 23 */, CONST64(0x7D820E760E76B5EA) /* 24 */, CONST64(0x645C9CC6F07FDC42) /* 25 */, CONST64(0xBF38A078243342E0) /* 26 */, CONST64(0x5F6B343C9D2E7D04) /* 27 */, CONST64(0xF2C28AEB600B0EC6) /* 28 */, CONST64(0x6C0ED85F7254BCAC) /* 29 */, CONST64(0x71592281A4DB4FE5) /* 30 */, CONST64(0x1967FA69CE0FED9F) /* 31 */, CONST64(0xFD5293F8B96545DB) /* 32 */, CONST64(0xC879E9D7F2A7600B) /* 33 */, CONST64(0x860248920193194E) /* 34 */, CONST64(0xA4F9533B2D9CC0B3) /* 35 */, CONST64(0x9053836C15957613) /* 36 */, CONST64(0xDB6DCF8AFC357BF1) /* 37 */, CONST64(0x18BEEA7A7A370F57) /* 38 */, CONST64(0x037117CA50B99066) /* 39 */, CONST64(0x6AB30A9774424A35) /* 40 */, CONST64(0xF4E92F02E325249B) /* 41 */, CONST64(0x7739DB07061CCAE1) /* 42 */, CONST64(0xD8F3B49CECA42A05) /* 43 */, CONST64(0xBD56BE3F51382F73) /* 44 */, CONST64(0x45FAED5843B0BB28) /* 45 */, CONST64(0x1C813D5C11BF1F83) /* 46 */, CONST64(0x8AF0E4B6D75FA169) /* 47 */, CONST64(0x33EE18A487AD9999) /* 48 */, CONST64(0x3C26E8EAB1C94410) /* 49 */, CONST64(0xB510102BC0A822F9) /* 50 */, CONST64(0x141EEF310CE6123B) /* 51 */, CONST64(0xFC65B90059DDB154) /* 52 */, CONST64(0xE0158640C5E0E607) /* 53 */, CONST64(0x884E079826C3A3CF) /* 54 */, CONST64(0x930D0D9523C535FD) /* 55 */, CONST64(0x35638D754E9A2B00) /* 56 */, CONST64(0x4085FCCF40469DD5) /* 57 */, CONST64(0xC4B17AD28BE23A4C) /* 58 */, CONST64(0xCAB2F0FC6A3E6A2E) /* 59 */, CONST64(0x2860971A6B943FCD) /* 60 */, CONST64(0x3DDE6EE212E30446) /* 61 */, CONST64(0x6222F32AE01765AE) /* 62 */, CONST64(0x5D550BB5478308FE) /* 63 */, CONST64(0xA9EFA98DA0EDA22A) /* 64 */, CONST64(0xC351A71686C40DA7) /* 65 */, CONST64(0x1105586D9C867C84) /* 66 */, CONST64(0xDCFFEE85FDA22853) /* 67 */, CONST64(0xCCFBD0262C5EEF76) /* 68 */, CONST64(0xBAF294CB8990D201) /* 69 */, CONST64(0xE69464F52AFAD975) /* 70 */, CONST64(0x94B013AFDF133E14) /* 71 */, CONST64(0x06A7D1A32823C958) /* 72 */, CONST64(0x6F95FE5130F61119) /* 73 */, CONST64(0xD92AB34E462C06C0) /* 74 */, CONST64(0xED7BDE33887C71D2) /* 75 */, CONST64(0x79746D6E6518393E) /* 76 */, CONST64(0x5BA419385D713329) /* 77 */, CONST64(0x7C1BA6B948A97564) /* 78 */, CONST64(0x31987C197BFDAC67) /* 79 */, CONST64(0xDE6C23C44B053D02) /* 80 */, CONST64(0x581C49FED002D64D) /* 81 */, CONST64(0xDD474D6338261571) /* 82 */, CONST64(0xAA4546C3E473D062) /* 83 */, CONST64(0x928FCE349455F860) /* 84 */, CONST64(0x48161BBACAAB94D9) /* 85 */, CONST64(0x63912430770E6F68) /* 86 */, CONST64(0x6EC8A5E602C6641C) /* 87 */, CONST64(0x87282515337DDD2B) /* 88 */, CONST64(0x2CDA6B42034B701B) /* 89 */, CONST64(0xB03D37C181CB096D) /* 90 */, CONST64(0xE108438266C71C6F) /* 91 */, CONST64(0x2B3180C7EB51B255) /* 92 */, CONST64(0xDF92B82F96C08BBC) /* 93 */, CONST64(0x5C68C8C0A632F3BA) /* 94 */, CONST64(0x5504CC861C3D0556) /* 95 */, CONST64(0xABBFA4E55FB26B8F) /* 96 */, CONST64(0x41848B0AB3BACEB4) /* 97 */, CONST64(0xB334A273AA445D32) /* 98 */, CONST64(0xBCA696F0A85AD881) /* 99 */, CONST64(0x24F6EC65B528D56C) /* 100 */, CONST64(0x0CE1512E90F4524A) /* 101 */, CONST64(0x4E9DD79D5506D35A) /* 102 */, CONST64(0x258905FAC6CE9779) /* 103 */, CONST64(0x2019295B3E109B33) /* 104 */, CONST64(0xF8A9478B73A054CC) /* 105 */, CONST64(0x2924F2F934417EB0) /* 106 */, CONST64(0x3993357D536D1BC4) /* 107 */, CONST64(0x38A81AC21DB6FF8B) /* 108 */, CONST64(0x47C4FBF17D6016BF) /* 109 */, CONST64(0x1E0FAADD7667E3F5) /* 110 */, CONST64(0x7ABCFF62938BEB96) /* 111 */, CONST64(0xA78DAD948FC179C9) /* 112 */, CONST64(0x8F1F98B72911E50D) /* 113 */, CONST64(0x61E48EAE27121A91) /* 114 */, CONST64(0x4D62F7AD31859808) /* 115 */, CONST64(0xECEBA345EF5CEAEB) /* 116 */, CONST64(0xF5CEB25EBC9684CE) /* 117 */, CONST64(0xF633E20CB7F76221) /* 118 */, CONST64(0xA32CDF06AB8293E4) /* 119 */, CONST64(0x985A202CA5EE2CA4) /* 120 */, CONST64(0xCF0B8447CC8A8FB1) /* 121 */, CONST64(0x9F765244979859A3) /* 122 */, CONST64(0xA8D516B1A1240017) /* 123 */, CONST64(0x0BD7BA3EBB5DC726) /* 124 */, CONST64(0xE54BCA55B86ADB39) /* 125 */, CONST64(0x1D7A3AFD6C478063) /* 126 */, CONST64(0x519EC608E7669EDD) /* 127 */, CONST64(0x0E5715A2D149AA23) /* 128 */, CONST64(0x177D4571848FF194) /* 129 */, CONST64(0xEEB55F3241014C22) /* 130 */, CONST64(0x0F5E5CA13A6E2EC2) /* 131 */, CONST64(0x8029927B75F5C361) /* 132 */, CONST64(0xAD139FABC3D6E436) /* 133 */, CONST64(0x0D5DF1A94CCF402F) /* 134 */, CONST64(0x3E8BD948BEA5DFC8) /* 135 */, CONST64(0xA5A0D357BD3FF77E) /* 136 */, CONST64(0xA2D12E251F74F645) /* 137 */, CONST64(0x66FD9E525E81A082) /* 138 */, CONST64(0x2E0C90CE7F687A49) /* 139 */, CONST64(0xC2E8BCBEBA973BC5) /* 140 */, CONST64(0x000001BCE509745F) /* 141 */, CONST64(0x423777BBE6DAB3D6) /* 142 */, CONST64(0xD1661C7EAEF06EB5) /* 143 */, CONST64(0xA1781F354DAACFD8) /* 144 */, CONST64(0x2D11284A2B16AFFC) /* 145 */, CONST64(0xF1FC4F67FA891D1F) /* 146 */, CONST64(0x73ECC25DCB920ADA) /* 147 */, CONST64(0xAE610C22C2A12651) /* 148 */, CONST64(0x96E0A810D356B78A) /* 149 */, CONST64(0x5A9A381F2FE7870F) /* 150 */, CONST64(0xD5AD62EDE94E5530) /* 151 */, CONST64(0xD225E5E8368D1427) /* 152 */, CONST64(0x65977B70C7AF4631) /* 153 */, CONST64(0x99F889B2DE39D74F) /* 154 */, CONST64(0x233F30BF54E1D143) /* 155 */, CONST64(0x9A9675D3D9A63C97) /* 156 */, CONST64(0x5470554FF334F9A8) /* 157 */, CONST64(0x166ACB744A4F5688) /* 158 */, CONST64(0x70C74CAAB2E4AEAD) /* 159 */, CONST64(0xF0D091646F294D12) /* 160 */, CONST64(0x57B82A89684031D1) /* 161 */, CONST64(0xEFD95A5A61BE0B6B) /* 162 */, CONST64(0x2FBD12E969F2F29A) /* 163 */, CONST64(0x9BD37013FEFF9FE8) /* 164 */, CONST64(0x3F9B0404D6085A06) /* 165 */, CONST64(0x4940C1F3166CFE15) /* 166 */, CONST64(0x09542C4DCDF3DEFB) /* 167 */, CONST64(0xB4C5218385CD5CE3) /* 168 */, CONST64(0xC935B7DC4462A641) /* 169 */, CONST64(0x3417F8A68ED3B63F) /* 170 */, CONST64(0xB80959295B215B40) /* 171 */, CONST64(0xF99CDAEF3B8C8572) /* 172 */, CONST64(0x018C0614F8FCB95D) /* 173 */, CONST64(0x1B14ACCD1A3ACDF3) /* 174 */, CONST64(0x84D471F200BB732D) /* 175 */, CONST64(0xC1A3110E95E8DA16) /* 176 */, CONST64(0x430A7220BF1A82B8) /* 177 */, CONST64(0xB77E090D39DF210E) /* 178 */, CONST64(0x5EF4BD9F3CD05E9D) /* 179 */, CONST64(0x9D4FF6DA7E57A444) /* 180 */, CONST64(0xDA1D60E183D4A5F8) /* 181 */, CONST64(0xB287C38417998E47) /* 182 */, CONST64(0xFE3EDC121BB31886) /* 183 */, CONST64(0xC7FE3CCC980CCBEF) /* 184 */, CONST64(0xE46FB590189BFD03) /* 185 */, CONST64(0x3732FD469A4C57DC) /* 186 */, CONST64(0x7EF700A07CF1AD65) /* 187 */, CONST64(0x59C64468A31D8859) /* 188 */, CONST64(0x762FB0B4D45B61F6) /* 189 */, CONST64(0x155BAED099047718) /* 190 */, CONST64(0x68755E4C3D50BAA6) /* 191 */, CONST64(0xE9214E7F22D8B4DF) /* 192 */, CONST64(0x2ADDBF532EAC95F4) /* 193 */, CONST64(0x32AE3909B4BD0109) /* 194 */, CONST64(0x834DF537B08E3450) /* 195 */, CONST64(0xFA209DA84220728D) /* 196 */, CONST64(0x9E691D9B9EFE23F7) /* 197 */, CONST64(0x0446D288C4AE8D7F) /* 198 */, CONST64(0x7B4CC524E169785B) /* 199 */, CONST64(0x21D87F0135CA1385) /* 200 */, CONST64(0xCEBB400F137B8AA5) /* 201 */, CONST64(0x272E2B66580796BE) /* 202 */, CONST64(0x3612264125C2B0DE) /* 203 */, CONST64(0x057702BDAD1EFBB2) /* 204 */, CONST64(0xD4BABB8EACF84BE9) /* 205 */, CONST64(0x91583139641BC67B) /* 206 */, CONST64(0x8BDC2DE08036E024) /* 207 */, CONST64(0x603C8156F49F68ED) /* 208 */, CONST64(0xF7D236F7DBEF5111) /* 209 */, CONST64(0x9727C4598AD21E80) /* 210 */, CONST64(0xA08A0896670A5FD7) /* 211 */, CONST64(0xCB4A8F4309EBA9CB) /* 212 */, CONST64(0x81AF564B0F7036A1) /* 213 */, CONST64(0xC0B99AA778199ABD) /* 214 */, CONST64(0x959F1EC83FC8E952) /* 215 */, CONST64(0x8C505077794A81B9) /* 216 */, CONST64(0x3ACAAF8F056338F0) /* 217 */, CONST64(0x07B43F50627A6778) /* 218 */, CONST64(0x4A44AB49F5ECCC77) /* 219 */, CONST64(0x3BC3D6E4B679EE98) /* 220 */, CONST64(0x9CC0D4D1CF14108C) /* 221 */, CONST64(0x4406C00B206BC8A0) /* 222 */, CONST64(0x82A18854C8D72D89) /* 223 */, CONST64(0x67E366B35C3C432C) /* 224 */, CONST64(0xB923DD61102B37F2) /* 225 */, CONST64(0x56AB2779D884271D) /* 226 */, CONST64(0xBE83E1B0FF1525AF) /* 227 */, CONST64(0xFB7C65D4217E49A9) /* 228 */, CONST64(0x6BDBE0E76D48E7D4) /* 229 */, CONST64(0x08DF828745D9179E) /* 230 */, CONST64(0x22EA6A9ADD53BD34) /* 231 */, CONST64(0xE36E141C5622200A) /* 232 */, CONST64(0x7F805D1B8CB750EE) /* 233 */, CONST64(0xAFE5C7A59F58E837) /* 234 */, CONST64(0xE27F996A4FB1C23C) /* 235 */, CONST64(0xD3867DFB0775F0D0) /* 236 */, CONST64(0xD0E673DE6E88891A) /* 237 */, CONST64(0x123AEB9EAFB86C25) /* 238 */, CONST64(0x30F1D5D5C145B895) /* 239 */, CONST64(0xBB434A2DEE7269E7) /* 240 */, CONST64(0x78CB67ECF931FA38) /* 241 */, CONST64(0xF33B0372323BBF9C) /* 242 */, CONST64(0x52D66336FB279C74) /* 243 */, CONST64(0x505F33AC0AFB4EAA) /* 244 */, CONST64(0xE8A5CD99A2CCE187) /* 245 */, CONST64(0x534974801E2D30BB) /* 246 */, CONST64(0x8D2D5711D5876D90) /* 247 */, CONST64(0x1F1A412891BC038E) /* 248 */, CONST64(0xD6E2E71D82E56648) /* 249 */, CONST64(0x74036C3A497732B7) /* 250 */, CONST64(0x89B67ED96361F5AB) /* 251 */, CONST64(0xFFED95D8F1EA02A2) /* 252 */, CONST64(0xE72B3BD61464D43D) /* 253 */, CONST64(0xA6300F170BDC4820) /* 254 */, CONST64(0xEBC18760ED78A77A) /* 255 */, CONST64(0xE6A6BE5A05A12138) /* 256 */, CONST64(0xB5A122A5B4F87C98) /* 257 */, CONST64(0x563C6089140B6990) /* 258 */, CONST64(0x4C46CB2E391F5DD5) /* 259 */, CONST64(0xD932ADDBC9B79434) /* 260 */, CONST64(0x08EA70E42015AFF5) /* 261 */, CONST64(0xD765A6673E478CF1) /* 262 */, CONST64(0xC4FB757EAB278D99) /* 263 */, CONST64(0xDF11C6862D6E0692) /* 264 */, CONST64(0xDDEB84F10D7F3B16) /* 265 */, CONST64(0x6F2EF604A665EA04) /* 266 */, CONST64(0x4A8E0F0FF0E0DFB3) /* 267 */, CONST64(0xA5EDEEF83DBCBA51) /* 268 */, CONST64(0xFC4F0A2A0EA4371E) /* 269 */, CONST64(0xE83E1DA85CB38429) /* 270 */, CONST64(0xDC8FF882BA1B1CE2) /* 271 */, CONST64(0xCD45505E8353E80D) /* 272 */, CONST64(0x18D19A00D4DB0717) /* 273 */, CONST64(0x34A0CFEDA5F38101) /* 274 */, CONST64(0x0BE77E518887CAF2) /* 275 */, CONST64(0x1E341438B3C45136) /* 276 */, CONST64(0xE05797F49089CCF9) /* 277 */, CONST64(0xFFD23F9DF2591D14) /* 278 */, CONST64(0x543DDA228595C5CD) /* 279 */, CONST64(0x661F81FD99052A33) /* 280 */, CONST64(0x8736E641DB0F7B76) /* 281 */, CONST64(0x15227725418E5307) /* 282 */, CONST64(0xE25F7F46162EB2FA) /* 283 */, CONST64(0x48A8B2126C13D9FE) /* 284 */, CONST64(0xAFDC541792E76EEA) /* 285 */, CONST64(0x03D912BFC6D1898F) /* 286 */, CONST64(0x31B1AAFA1B83F51B) /* 287 */, CONST64(0xF1AC2796E42AB7D9) /* 288 */, CONST64(0x40A3A7D7FCD2EBAC) /* 289 */, CONST64(0x1056136D0AFBBCC5) /* 290 */, CONST64(0x7889E1DD9A6D0C85) /* 291 */, CONST64(0xD33525782A7974AA) /* 292 */, CONST64(0xA7E25D09078AC09B) /* 293 */, CONST64(0xBD4138B3EAC6EDD0) /* 294 */, CONST64(0x920ABFBE71EB9E70) /* 295 */, CONST64(0xA2A5D0F54FC2625C) /* 296 */, CONST64(0xC054E36B0B1290A3) /* 297 */, CONST64(0xF6DD59FF62FE932B) /* 298 */, CONST64(0x3537354511A8AC7D) /* 299 */, CONST64(0xCA845E9172FADCD4) /* 300 */, CONST64(0x84F82B60329D20DC) /* 301 */, CONST64(0x79C62CE1CD672F18) /* 302 */, CONST64(0x8B09A2ADD124642C) /* 303 */, CONST64(0xD0C1E96A19D9E726) /* 304 */, CONST64(0x5A786A9B4BA9500C) /* 305 */, CONST64(0x0E020336634C43F3) /* 306 */, CONST64(0xC17B474AEB66D822) /* 307 */, CONST64(0x6A731AE3EC9BAAC2) /* 308 */, CONST64(0x8226667AE0840258) /* 309 */, CONST64(0x67D4567691CAECA5) /* 310 */, CONST64(0x1D94155C4875ADB5) /* 311 */, CONST64(0x6D00FD985B813FDF) /* 312 */, CONST64(0x51286EFCB774CD06) /* 313 */, CONST64(0x5E8834471FA744AF) /* 314 */, CONST64(0xF72CA0AEE761AE2E) /* 315 */, CONST64(0xBE40E4CDAEE8E09A) /* 316 */, CONST64(0xE9970BBB5118F665) /* 317 */, CONST64(0x726E4BEB33DF1964) /* 318 */, CONST64(0x703B000729199762) /* 319 */, CONST64(0x4631D816F5EF30A7) /* 320 */, CONST64(0xB880B5B51504A6BE) /* 321 */, CONST64(0x641793C37ED84B6C) /* 322 */, CONST64(0x7B21ED77F6E97D96) /* 323 */, CONST64(0x776306312EF96B73) /* 324 */, CONST64(0xAE528948E86FF3F4) /* 325 */, CONST64(0x53DBD7F286A3F8F8) /* 326 */, CONST64(0x16CADCE74CFC1063) /* 327 */, CONST64(0x005C19BDFA52C6DD) /* 328 */, CONST64(0x68868F5D64D46AD3) /* 329 */, CONST64(0x3A9D512CCF1E186A) /* 330 */, CONST64(0x367E62C2385660AE) /* 331 */, CONST64(0xE359E7EA77DCB1D7) /* 332 */, CONST64(0x526C0773749ABE6E) /* 333 */, CONST64(0x735AE5F9D09F734B) /* 334 */, CONST64(0x493FC7CC8A558BA8) /* 335 */, CONST64(0xB0B9C1533041AB45) /* 336 */, CONST64(0x321958BA470A59BD) /* 337 */, CONST64(0x852DB00B5F46C393) /* 338 */, CONST64(0x91209B2BD336B0E5) /* 339 */, CONST64(0x6E604F7D659EF19F) /* 340 */, CONST64(0xB99A8AE2782CCB24) /* 341 */, CONST64(0xCCF52AB6C814C4C7) /* 342 */, CONST64(0x4727D9AFBE11727B) /* 343 */, CONST64(0x7E950D0C0121B34D) /* 344 */, CONST64(0x756F435670AD471F) /* 345 */, CONST64(0xF5ADD442615A6849) /* 346 */, CONST64(0x4E87E09980B9957A) /* 347 */, CONST64(0x2ACFA1DF50AEE355) /* 348 */, CONST64(0xD898263AFD2FD556) /* 349 */, CONST64(0xC8F4924DD80C8FD6) /* 350 */, CONST64(0xCF99CA3D754A173A) /* 351 */, CONST64(0xFE477BACAF91BF3C) /* 352 */, CONST64(0xED5371F6D690C12D) /* 353 */, CONST64(0x831A5C285E687094) /* 354 */, CONST64(0xC5D3C90A3708A0A4) /* 355 */, CONST64(0x0F7F903717D06580) /* 356 */, CONST64(0x19F9BB13B8FDF27F) /* 357 */, CONST64(0xB1BD6F1B4D502843) /* 358 */, CONST64(0x1C761BA38FFF4012) /* 359 */, CONST64(0x0D1530C4E2E21F3B) /* 360 */, CONST64(0x8943CE69A7372C8A) /* 361 */, CONST64(0xE5184E11FEB5CE66) /* 362 */, CONST64(0x618BDB80BD736621) /* 363 */, CONST64(0x7D29BAD68B574D0B) /* 364 */, CONST64(0x81BB613E25E6FE5B) /* 365 */, CONST64(0x071C9C10BC07913F) /* 366 */, CONST64(0xC7BEEB7909AC2D97) /* 367 */, CONST64(0xC3E58D353BC5D757) /* 368 */, CONST64(0xEB017892F38F61E8) /* 369 */, CONST64(0xD4EFFB9C9B1CC21A) /* 370 */, CONST64(0x99727D26F494F7AB) /* 371 */, CONST64(0xA3E063A2956B3E03) /* 372 */, CONST64(0x9D4A8B9A4AA09C30) /* 373 */, CONST64(0x3F6AB7D500090FB4) /* 374 */, CONST64(0x9CC0F2A057268AC0) /* 375 */, CONST64(0x3DEE9D2DEDBF42D1) /* 376 */, CONST64(0x330F49C87960A972) /* 377 */, CONST64(0xC6B2720287421B41) /* 378 */, CONST64(0x0AC59EC07C00369C) /* 379 */, CONST64(0xEF4EAC49CB353425) /* 380 */, CONST64(0xF450244EEF0129D8) /* 381 */, CONST64(0x8ACC46E5CAF4DEB6) /* 382 */, CONST64(0x2FFEAB63989263F7) /* 383 */, CONST64(0x8F7CB9FE5D7A4578) /* 384 */, CONST64(0x5BD8F7644E634635) /* 385 */, CONST64(0x427A7315BF2DC900) /* 386 */, CONST64(0x17D0C4AA2125261C) /* 387 */, CONST64(0x3992486C93518E50) /* 388 */, CONST64(0xB4CBFEE0A2D7D4C3) /* 389 */, CONST64(0x7C75D6202C5DDD8D) /* 390 */, CONST64(0xDBC295D8E35B6C61) /* 391 */, CONST64(0x60B369D302032B19) /* 392 */, CONST64(0xCE42685FDCE44132) /* 393 */, CONST64(0x06F3DDB9DDF65610) /* 394 */, CONST64(0x8EA4D21DB5E148F0) /* 395 */, CONST64(0x20B0FCE62FCD496F) /* 396 */, CONST64(0x2C1B912358B0EE31) /* 397 */, CONST64(0xB28317B818F5A308) /* 398 */, CONST64(0xA89C1E189CA6D2CF) /* 399 */, CONST64(0x0C6B18576AAADBC8) /* 400 */, CONST64(0xB65DEAA91299FAE3) /* 401 */, CONST64(0xFB2B794B7F1027E7) /* 402 */, CONST64(0x04E4317F443B5BEB) /* 403 */, CONST64(0x4B852D325939D0A6) /* 404 */, CONST64(0xD5AE6BEEFB207FFC) /* 405 */, CONST64(0x309682B281C7D374) /* 406 */, CONST64(0xBAE309A194C3B475) /* 407 */, CONST64(0x8CC3F97B13B49F05) /* 408 */, CONST64(0x98A9422FF8293967) /* 409 */, CONST64(0x244B16B01076FF7C) /* 410 */, CONST64(0xF8BF571C663D67EE) /* 411 */, CONST64(0x1F0D6758EEE30DA1) /* 412 */, CONST64(0xC9B611D97ADEB9B7) /* 413 */, CONST64(0xB7AFD5887B6C57A2) /* 414 */, CONST64(0x6290AE846B984FE1) /* 415 */, CONST64(0x94DF4CDEACC1A5FD) /* 416 */, CONST64(0x058A5BD1C5483AFF) /* 417 */, CONST64(0x63166CC142BA3C37) /* 418 */, CONST64(0x8DB8526EB2F76F40) /* 419 */, CONST64(0xE10880036F0D6D4E) /* 420 */, CONST64(0x9E0523C9971D311D) /* 421 */, CONST64(0x45EC2824CC7CD691) /* 422 */, CONST64(0x575B8359E62382C9) /* 423 */, CONST64(0xFA9E400DC4889995) /* 424 */, CONST64(0xD1823ECB45721568) /* 425 */, CONST64(0xDAFD983B8206082F) /* 426 */, CONST64(0xAA7D29082386A8CB) /* 427 */, CONST64(0x269FCD4403B87588) /* 428 */, CONST64(0x1B91F5F728BDD1E0) /* 429 */, CONST64(0xE4669F39040201F6) /* 430 */, CONST64(0x7A1D7C218CF04ADE) /* 431 */, CONST64(0x65623C29D79CE5CE) /* 432 */, CONST64(0x2368449096C00BB1) /* 433 */, CONST64(0xAB9BF1879DA503BA) /* 434 */, CONST64(0xBC23ECB1A458058E) /* 435 */, CONST64(0x9A58DF01BB401ECC) /* 436 */, CONST64(0xA070E868A85F143D) /* 437 */, CONST64(0x4FF188307DF2239E) /* 438 */, CONST64(0x14D565B41A641183) /* 439 */, CONST64(0xEE13337452701602) /* 440 */, CONST64(0x950E3DCF3F285E09) /* 441 */, CONST64(0x59930254B9C80953) /* 442 */, CONST64(0x3BF299408930DA6D) /* 443 */, CONST64(0xA955943F53691387) /* 444 */, CONST64(0xA15EDECAA9CB8784) /* 445 */, CONST64(0x29142127352BE9A0) /* 446 */, CONST64(0x76F0371FFF4E7AFB) /* 447 */, CONST64(0x0239F450274F2228) /* 448 */, CONST64(0xBB073AF01D5E868B) /* 449 */, CONST64(0xBFC80571C10E96C1) /* 450 */, CONST64(0xD267088568222E23) /* 451 */, CONST64(0x9671A3D48E80B5B0) /* 452 */, CONST64(0x55B5D38AE193BB81) /* 453 */, CONST64(0x693AE2D0A18B04B8) /* 454 */, CONST64(0x5C48B4ECADD5335F) /* 455 */, CONST64(0xFD743B194916A1CA) /* 456 */, CONST64(0x2577018134BE98C4) /* 457 */, CONST64(0xE77987E83C54A4AD) /* 458 */, CONST64(0x28E11014DA33E1B9) /* 459 */, CONST64(0x270CC59E226AA213) /* 460 */, CONST64(0x71495F756D1A5F60) /* 461 */, CONST64(0x9BE853FB60AFEF77) /* 462 */, CONST64(0xADC786A7F7443DBF) /* 463 */, CONST64(0x0904456173B29A82) /* 464 */, CONST64(0x58BC7A66C232BD5E) /* 465 */, CONST64(0xF306558C673AC8B2) /* 466 */, CONST64(0x41F639C6B6C9772A) /* 467 */, CONST64(0x216DEFE99FDA35DA) /* 468 */, CONST64(0x11640CC71C7BE615) /* 469 */, CONST64(0x93C43694565C5527) /* 470 */, CONST64(0xEA038E6246777839) /* 471 */, CONST64(0xF9ABF3CE5A3E2469) /* 472 */, CONST64(0x741E768D0FD312D2) /* 473 */, CONST64(0x0144B883CED652C6) /* 474 */, CONST64(0xC20B5A5BA33F8552) /* 475 */, CONST64(0x1AE69633C3435A9D) /* 476 */, CONST64(0x97A28CA4088CFDEC) /* 477 */, CONST64(0x8824A43C1E96F420) /* 478 */, CONST64(0x37612FA66EEEA746) /* 479 */, CONST64(0x6B4CB165F9CF0E5A) /* 480 */, CONST64(0x43AA1C06A0ABFB4A) /* 481 */, CONST64(0x7F4DC26FF162796B) /* 482 */, CONST64(0x6CBACC8E54ED9B0F) /* 483 */, CONST64(0xA6B7FFEFD2BB253E) /* 484 */, CONST64(0x2E25BC95B0A29D4F) /* 485 */, CONST64(0x86D6A58BDEF1388C) /* 486 */, CONST64(0xDED74AC576B6F054) /* 487 */, CONST64(0x8030BDBC2B45805D) /* 488 */, CONST64(0x3C81AF70E94D9289) /* 489 */, CONST64(0x3EFF6DDA9E3100DB) /* 490 */, CONST64(0xB38DC39FDFCC8847) /* 491 */, CONST64(0x123885528D17B87E) /* 492 */, CONST64(0xF2DA0ED240B1B642) /* 493 */, CONST64(0x44CEFADCD54BF9A9) /* 494 */, CONST64(0x1312200E433C7EE6) /* 495 */, CONST64(0x9FFCC84F3A78C748) /* 496 */, CONST64(0xF0CD1F72248576BB) /* 497 */, CONST64(0xEC6974053638CFE4) /* 498 */, CONST64(0x2BA7B67C0CEC4E4C) /* 499 */, CONST64(0xAC2F4DF3E5CE32ED) /* 500 */, CONST64(0xCB33D14326EA4C11) /* 501 */, CONST64(0xA4E9044CC77E58BC) /* 502 */, CONST64(0x5F513293D934FCEF) /* 503 */, CONST64(0x5DC9645506E55444) /* 504 */, CONST64(0x50DE418F317DE40A) /* 505 */, CONST64(0x388CB31A69DDE259) /* 506 */, CONST64(0x2DB4A83455820A86) /* 507 */, CONST64(0x9010A91E84711AE9) /* 508 */, CONST64(0x4DF7F0B7B1498371) /* 509 */, CONST64(0xD62A2EABC0977179) /* 510 */, CONST64(0x22FAC097AA8D5C0E) /* 511 */, CONST64(0xF49FCC2FF1DAF39B) /* 512 */, CONST64(0x487FD5C66FF29281) /* 513 */, CONST64(0xE8A30667FCDCA83F) /* 514 */, CONST64(0x2C9B4BE3D2FCCE63) /* 515 */, CONST64(0xDA3FF74B93FBBBC2) /* 516 */, CONST64(0x2FA165D2FE70BA66) /* 517 */, CONST64(0xA103E279970E93D4) /* 518 */, CONST64(0xBECDEC77B0E45E71) /* 519 */, CONST64(0xCFB41E723985E497) /* 520 */, CONST64(0xB70AAA025EF75017) /* 521 */, CONST64(0xD42309F03840B8E0) /* 522 */, CONST64(0x8EFC1AD035898579) /* 523 */, CONST64(0x96C6920BE2B2ABC5) /* 524 */, CONST64(0x66AF4163375A9172) /* 525 */, CONST64(0x2174ABDCCA7127FB) /* 526 */, CONST64(0xB33CCEA64A72FF41) /* 527 */, CONST64(0xF04A4933083066A5) /* 528 */, CONST64(0x8D970ACDD7289AF5) /* 529 */, CONST64(0x8F96E8E031C8C25E) /* 530 */, CONST64(0xF3FEC02276875D47) /* 531 */, CONST64(0xEC7BF310056190DD) /* 532 */, CONST64(0xF5ADB0AEBB0F1491) /* 533 */, CONST64(0x9B50F8850FD58892) /* 534 */, CONST64(0x4975488358B74DE8) /* 535 */, CONST64(0xA3354FF691531C61) /* 536 */, CONST64(0x0702BBE481D2C6EE) /* 537 */, CONST64(0x89FB24057DEDED98) /* 538 */, CONST64(0xAC3075138596E902) /* 539 */, CONST64(0x1D2D3580172772ED) /* 540 */, CONST64(0xEB738FC28E6BC30D) /* 541 */, CONST64(0x5854EF8F63044326) /* 542 */, CONST64(0x9E5C52325ADD3BBE) /* 543 */, CONST64(0x90AA53CF325C4623) /* 544 */, CONST64(0xC1D24D51349DD067) /* 545 */, CONST64(0x2051CFEEA69EA624) /* 546 */, CONST64(0x13220F0A862E7E4F) /* 547 */, CONST64(0xCE39399404E04864) /* 548 */, CONST64(0xD9C42CA47086FCB7) /* 549 */, CONST64(0x685AD2238A03E7CC) /* 550 */, CONST64(0x066484B2AB2FF1DB) /* 551 */, CONST64(0xFE9D5D70EFBF79EC) /* 552 */, CONST64(0x5B13B9DD9C481854) /* 553 */, CONST64(0x15F0D475ED1509AD) /* 554 */, CONST64(0x0BEBCD060EC79851) /* 555 */, CONST64(0xD58C6791183AB7F8) /* 556 */, CONST64(0xD1187C5052F3EEE4) /* 557 */, CONST64(0xC95D1192E54E82FF) /* 558 */, CONST64(0x86EEA14CB9AC6CA2) /* 559 */, CONST64(0x3485BEB153677D5D) /* 560 */, CONST64(0xDD191D781F8C492A) /* 561 */, CONST64(0xF60866BAA784EBF9) /* 562 */, CONST64(0x518F643BA2D08C74) /* 563 */, CONST64(0x8852E956E1087C22) /* 564 */, CONST64(0xA768CB8DC410AE8D) /* 565 */, CONST64(0x38047726BFEC8E1A) /* 566 */, CONST64(0xA67738B4CD3B45AA) /* 567 */, CONST64(0xAD16691CEC0DDE19) /* 568 */, CONST64(0xC6D4319380462E07) /* 569 */, CONST64(0xC5A5876D0BA61938) /* 570 */, CONST64(0x16B9FA1FA58FD840) /* 571 */, CONST64(0x188AB1173CA74F18) /* 572 */, CONST64(0xABDA2F98C99C021F) /* 573 */, CONST64(0x3E0580AB134AE816) /* 574 */, CONST64(0x5F3B05B773645ABB) /* 575 */, CONST64(0x2501A2BE5575F2F6) /* 576 */, CONST64(0x1B2F74004E7E8BA9) /* 577 */, CONST64(0x1CD7580371E8D953) /* 578 */, CONST64(0x7F6ED89562764E30) /* 579 */, CONST64(0xB15926FF596F003D) /* 580 */, CONST64(0x9F65293DA8C5D6B9) /* 581 */, CONST64(0x6ECEF04DD690F84C) /* 582 */, CONST64(0x4782275FFF33AF88) /* 583 */, CONST64(0xE41433083F820801) /* 584 */, CONST64(0xFD0DFE409A1AF9B5) /* 585 */, CONST64(0x4325A3342CDB396B) /* 586 */, CONST64(0x8AE77E62B301B252) /* 587 */, CONST64(0xC36F9E9F6655615A) /* 588 */, CONST64(0x85455A2D92D32C09) /* 589 */, CONST64(0xF2C7DEA949477485) /* 590 */, CONST64(0x63CFB4C133A39EBA) /* 591 */, CONST64(0x83B040CC6EBC5462) /* 592 */, CONST64(0x3B9454C8FDB326B0) /* 593 */, CONST64(0x56F56A9E87FFD78C) /* 594 */, CONST64(0x2DC2940D99F42BC6) /* 595 */, CONST64(0x98F7DF096B096E2D) /* 596 */, CONST64(0x19A6E01E3AD852BF) /* 597 */, CONST64(0x42A99CCBDBD4B40B) /* 598 */, CONST64(0xA59998AF45E9C559) /* 599 */, CONST64(0x366295E807D93186) /* 600 */, CONST64(0x6B48181BFAA1F773) /* 601 */, CONST64(0x1FEC57E2157A0A1D) /* 602 */, CONST64(0x4667446AF6201AD5) /* 603 */, CONST64(0xE615EBCACFB0F075) /* 604 */, CONST64(0xB8F31F4F68290778) /* 605 */, CONST64(0x22713ED6CE22D11E) /* 606 */, CONST64(0x3057C1A72EC3C93B) /* 607 */, CONST64(0xCB46ACC37C3F1F2F) /* 608 */, CONST64(0xDBB893FD02AAF50E) /* 609 */, CONST64(0x331FD92E600B9FCF) /* 610 */, CONST64(0xA498F96148EA3AD6) /* 611 */, CONST64(0xA8D8426E8B6A83EA) /* 612 */, CONST64(0xA089B274B7735CDC) /* 613 */, CONST64(0x87F6B3731E524A11) /* 614 */, CONST64(0x118808E5CBC96749) /* 615 */, CONST64(0x9906E4C7B19BD394) /* 616 */, CONST64(0xAFED7F7E9B24A20C) /* 617 */, CONST64(0x6509EADEEB3644A7) /* 618 */, CONST64(0x6C1EF1D3E8EF0EDE) /* 619 */, CONST64(0xB9C97D43E9798FB4) /* 620 */, CONST64(0xA2F2D784740C28A3) /* 621 */, CONST64(0x7B8496476197566F) /* 622 */, CONST64(0x7A5BE3E6B65F069D) /* 623 */, CONST64(0xF96330ED78BE6F10) /* 624 */, CONST64(0xEEE60DE77A076A15) /* 625 */, CONST64(0x2B4BEE4AA08B9BD0) /* 626 */, CONST64(0x6A56A63EC7B8894E) /* 627 */, CONST64(0x02121359BA34FEF4) /* 628 */, CONST64(0x4CBF99F8283703FC) /* 629 */, CONST64(0x398071350CAF30C8) /* 630 */, CONST64(0xD0A77A89F017687A) /* 631 */, CONST64(0xF1C1A9EB9E423569) /* 632 */, CONST64(0x8C7976282DEE8199) /* 633 */, CONST64(0x5D1737A5DD1F7ABD) /* 634 */, CONST64(0x4F53433C09A9FA80) /* 635 */, CONST64(0xFA8B0C53DF7CA1D9) /* 636 */, CONST64(0x3FD9DCBC886CCB77) /* 637 */, CONST64(0xC040917CA91B4720) /* 638 */, CONST64(0x7DD00142F9D1DCDF) /* 639 */, CONST64(0x8476FC1D4F387B58) /* 640 */, CONST64(0x23F8E7C5F3316503) /* 641 */, CONST64(0x032A2244E7E37339) /* 642 */, CONST64(0x5C87A5D750F5A74B) /* 643 */, CONST64(0x082B4CC43698992E) /* 644 */, CONST64(0xDF917BECB858F63C) /* 645 */, CONST64(0x3270B8FC5BF86DDA) /* 646 */, CONST64(0x10AE72BB29B5DD76) /* 647 */, CONST64(0x576AC94E7700362B) /* 648 */, CONST64(0x1AD112DAC61EFB8F) /* 649 */, CONST64(0x691BC30EC5FAA427) /* 650 */, CONST64(0xFF246311CC327143) /* 651 */, CONST64(0x3142368E30E53206) /* 652 */, CONST64(0x71380E31E02CA396) /* 653 */, CONST64(0x958D5C960AAD76F1) /* 654 */, CONST64(0xF8D6F430C16DA536) /* 655 */, CONST64(0xC8FFD13F1BE7E1D2) /* 656 */, CONST64(0x7578AE66004DDBE1) /* 657 */, CONST64(0x05833F01067BE646) /* 658 */, CONST64(0xBB34B5AD3BFE586D) /* 659 */, CONST64(0x095F34C9A12B97F0) /* 660 */, CONST64(0x247AB64525D60CA8) /* 661 */, CONST64(0xDCDBC6F3017477D1) /* 662 */, CONST64(0x4A2E14D4DECAD24D) /* 663 */, CONST64(0xBDB5E6D9BE0A1EEB) /* 664 */, CONST64(0x2A7E70F7794301AB) /* 665 */, CONST64(0xDEF42D8A270540FD) /* 666 */, CONST64(0x01078EC0A34C22C1) /* 667 */, CONST64(0xE5DE511AF4C16387) /* 668 */, CONST64(0x7EBB3A52BD9A330A) /* 669 */, CONST64(0x77697857AA7D6435) /* 670 */, CONST64(0x004E831603AE4C32) /* 671 */, CONST64(0xE7A21020AD78E312) /* 672 */, CONST64(0x9D41A70C6AB420F2) /* 673 */, CONST64(0x28E06C18EA1141E6) /* 674 */, CONST64(0xD2B28CBD984F6B28) /* 675 */, CONST64(0x26B75F6C446E9D83) /* 676 */, CONST64(0xBA47568C4D418D7F) /* 677 */, CONST64(0xD80BADBFE6183D8E) /* 678 */, CONST64(0x0E206D7F5F166044) /* 679 */, CONST64(0xE258A43911CBCA3E) /* 680 */, CONST64(0x723A1746B21DC0BC) /* 681 */, CONST64(0xC7CAA854F5D7CDD3) /* 682 */, CONST64(0x7CAC32883D261D9C) /* 683 */, CONST64(0x7690C26423BA942C) /* 684 */, CONST64(0x17E55524478042B8) /* 685 */, CONST64(0xE0BE477656A2389F) /* 686 */, CONST64(0x4D289B5E67AB2DA0) /* 687 */, CONST64(0x44862B9C8FBBFD31) /* 688 */, CONST64(0xB47CC8049D141365) /* 689 */, CONST64(0x822C1B362B91C793) /* 690 */, CONST64(0x4EB14655FB13DFD8) /* 691 */, CONST64(0x1ECBBA0714E2A97B) /* 692 */, CONST64(0x6143459D5CDE5F14) /* 693 */, CONST64(0x53A8FBF1D5F0AC89) /* 694 */, CONST64(0x97EA04D81C5E5B00) /* 695 */, CONST64(0x622181A8D4FDB3F3) /* 696 */, CONST64(0xE9BCD341572A1208) /* 697 */, CONST64(0x1411258643CCE58A) /* 698 */, CONST64(0x9144C5FEA4C6E0A4) /* 699 */, CONST64(0x0D33D06565CF620F) /* 700 */, CONST64(0x54A48D489F219CA1) /* 701 */, CONST64(0xC43E5EAC6D63C821) /* 702 */, CONST64(0xA9728B3A72770DAF) /* 703 */, CONST64(0xD7934E7B20DF87EF) /* 704 */, CONST64(0xE35503B61A3E86E5) /* 705 */, CONST64(0xCAE321FBC819D504) /* 706 */, CONST64(0x129A50B3AC60BFA6) /* 707 */, CONST64(0xCD5E68EA7E9FB6C3) /* 708 */, CONST64(0xB01C90199483B1C7) /* 709 */, CONST64(0x3DE93CD5C295376C) /* 710 */, CONST64(0xAED52EDF2AB9AD13) /* 711 */, CONST64(0x2E60F512C0A07884) /* 712 */, CONST64(0xBC3D86A3E36210C9) /* 713 */, CONST64(0x35269D9B163951CE) /* 714 */, CONST64(0x0C7D6E2AD0CDB5FA) /* 715 */, CONST64(0x59E86297D87F5733) /* 716 */, CONST64(0x298EF221898DB0E7) /* 717 */, CONST64(0x55000029D1A5AA7E) /* 718 */, CONST64(0x8BC08AE1B5061B45) /* 719 */, CONST64(0xC2C31C2B6C92703A) /* 720 */, CONST64(0x94CC596BAF25EF42) /* 721 */, CONST64(0x0A1D73DB22540456) /* 722 */, CONST64(0x04B6A0F9D9C4179A) /* 723 */, CONST64(0xEFFDAFA2AE3D3C60) /* 724 */, CONST64(0xF7C8075BB49496C4) /* 725 */, CONST64(0x9CC5C7141D1CD4E3) /* 726 */, CONST64(0x78BD1638218E5534) /* 727 */, CONST64(0xB2F11568F850246A) /* 728 */, CONST64(0xEDFABCFA9502BC29) /* 729 */, CONST64(0x796CE5F2DA23051B) /* 730 */, CONST64(0xAAE128B0DC93537C) /* 731 */, CONST64(0x3A493DA0EE4B29AE) /* 732 */, CONST64(0xB5DF6B2C416895D7) /* 733 */, CONST64(0xFCABBD25122D7F37) /* 734 */, CONST64(0x70810B58105DC4B1) /* 735 */, CONST64(0xE10FDD37F7882A90) /* 736 */, CONST64(0x524DCAB5518A3F5C) /* 737 */, CONST64(0x3C9E85878451255B) /* 738 */, CONST64(0x4029828119BD34E2) /* 739 */, CONST64(0x74A05B6F5D3CECCB) /* 740 */, CONST64(0xB610021542E13ECA) /* 741 */, CONST64(0x0FF979D12F59E2AC) /* 742 */, CONST64(0x6037DA27E4F9CC50) /* 743 */, CONST64(0x5E92975A0DF1847D) /* 744 */, CONST64(0xD66DE190D3E623FE) /* 745 */, CONST64(0x5032D6B87B568048) /* 746 */, CONST64(0x9A36B7CE8235216E) /* 747 */, CONST64(0x80272A7A24F64B4A) /* 748 */, CONST64(0x93EFED8B8C6916F7) /* 749 */, CONST64(0x37DDBFF44CCE1555) /* 750 */, CONST64(0x4B95DB5D4B99BD25) /* 751 */, CONST64(0x92D3FDA169812FC0) /* 752 */, CONST64(0xFB1A4A9A90660BB6) /* 753 */, CONST64(0x730C196946A4B9B2) /* 754 */, CONST64(0x81E289AA7F49DA68) /* 755 */, CONST64(0x64669A0F83B1A05F) /* 756 */, CONST64(0x27B3FF7D9644F48B) /* 757 */, CONST64(0xCC6B615C8DB675B3) /* 758 */, CONST64(0x674F20B9BCEBBE95) /* 759 */, CONST64(0x6F31238275655982) /* 760 */, CONST64(0x5AE488713E45CF05) /* 761 */, CONST64(0xBF619F9954C21157) /* 762 */, CONST64(0xEABAC46040A8EAE9) /* 763 */, CONST64(0x454C6FE9F2C0C1CD) /* 764 */, CONST64(0x419CF6496412691C) /* 765 */, CONST64(0xD3DC3BEF265B0F70) /* 766 */, CONST64(0x6D0E60F5C3578A9E) /* 767 */, CONST64(0x5B0E608526323C55) /* 768 */, CONST64(0x1A46C1A9FA1B59F5) /* 769 */, CONST64(0xA9E245A17C4C8FFA) /* 770 */, CONST64(0x65CA5159DB2955D7) /* 771 */, CONST64(0x05DB0A76CE35AFC2) /* 772 */, CONST64(0x81EAC77EA9113D45) /* 773 */, CONST64(0x528EF88AB6AC0A0D) /* 774 */, CONST64(0xA09EA253597BE3FF) /* 775 */, CONST64(0x430DDFB3AC48CD56) /* 776 */, CONST64(0xC4B3A67AF45CE46F) /* 777 */, CONST64(0x4ECECFD8FBE2D05E) /* 778 */, CONST64(0x3EF56F10B39935F0) /* 779 */, CONST64(0x0B22D6829CD619C6) /* 780 */, CONST64(0x17FD460A74DF2069) /* 781 */, CONST64(0x6CF8CC8E8510ED40) /* 782 */, CONST64(0xD6C824BF3A6ECAA7) /* 783 */, CONST64(0x61243D581A817049) /* 784 */, CONST64(0x048BACB6BBC163A2) /* 785 */, CONST64(0xD9A38AC27D44CC32) /* 786 */, CONST64(0x7FDDFF5BAAF410AB) /* 787 */, CONST64(0xAD6D495AA804824B) /* 788 */, CONST64(0xE1A6A74F2D8C9F94) /* 789 */, CONST64(0xD4F7851235DEE8E3) /* 790 */, CONST64(0xFD4B7F886540D893) /* 791 */, CONST64(0x247C20042AA4BFDA) /* 792 */, CONST64(0x096EA1C517D1327C) /* 793 */, CONST64(0xD56966B4361A6685) /* 794 */, CONST64(0x277DA5C31221057D) /* 795 */, CONST64(0x94D59893A43ACFF7) /* 796 */, CONST64(0x64F0C51CCDC02281) /* 797 */, CONST64(0x3D33BCC4FF6189DB) /* 798 */, CONST64(0xE005CB184CE66AF1) /* 799 */, CONST64(0xFF5CCD1D1DB99BEA) /* 800 */, CONST64(0xB0B854A7FE42980F) /* 801 */, CONST64(0x7BD46A6A718D4B9F) /* 802 */, CONST64(0xD10FA8CC22A5FD8C) /* 803 */, CONST64(0xD31484952BE4BD31) /* 804 */, CONST64(0xC7FA975FCB243847) /* 805 */, CONST64(0x4886ED1E5846C407) /* 806 */, CONST64(0x28CDDB791EB70B04) /* 807 */, CONST64(0xC2B00BE2F573417F) /* 808 */, CONST64(0x5C9590452180F877) /* 809 */, CONST64(0x7A6BDDFFF370EB00) /* 810 */, CONST64(0xCE509E38D6D9D6A4) /* 811 */, CONST64(0xEBEB0F00647FA702) /* 812 */, CONST64(0x1DCC06CF76606F06) /* 813 */, CONST64(0xE4D9F28BA286FF0A) /* 814 */, CONST64(0xD85A305DC918C262) /* 815 */, CONST64(0x475B1D8732225F54) /* 816 */, CONST64(0x2D4FB51668CCB5FE) /* 817 */, CONST64(0xA679B9D9D72BBA20) /* 818 */, CONST64(0x53841C0D912D43A5) /* 819 */, CONST64(0x3B7EAA48BF12A4E8) /* 820 */, CONST64(0x781E0E47F22F1DDF) /* 821 */, CONST64(0xEFF20CE60AB50973) /* 822 */, CONST64(0x20D261D19DFFB742) /* 823 */, CONST64(0x16A12B03062A2E39) /* 824 */, CONST64(0x1960EB2239650495) /* 825 */, CONST64(0x251C16FED50EB8B8) /* 826 */, CONST64(0x9AC0C330F826016E) /* 827 */, CONST64(0xED152665953E7671) /* 828 */, CONST64(0x02D63194A6369570) /* 829 */, CONST64(0x5074F08394B1C987) /* 830 */, CONST64(0x70BA598C90B25CE1) /* 831 */, CONST64(0x794A15810B9742F6) /* 832 */, CONST64(0x0D5925E9FCAF8C6C) /* 833 */, CONST64(0x3067716CD868744E) /* 834 */, CONST64(0x910AB077E8D7731B) /* 835 */, CONST64(0x6A61BBDB5AC42F61) /* 836 */, CONST64(0x93513EFBF0851567) /* 837 */, CONST64(0xF494724B9E83E9D5) /* 838 */, CONST64(0xE887E1985C09648D) /* 839 */, CONST64(0x34B1D3C675370CFD) /* 840 */, CONST64(0xDC35E433BC0D255D) /* 841 */, CONST64(0xD0AAB84234131BE0) /* 842 */, CONST64(0x08042A50B48B7EAF) /* 843 */, CONST64(0x9997C4EE44A3AB35) /* 844 */, CONST64(0x829A7B49201799D0) /* 845 */, CONST64(0x263B8307B7C54441) /* 846 */, CONST64(0x752F95F4FD6A6CA6) /* 847 */, CONST64(0x927217402C08C6E5) /* 848 */, CONST64(0x2A8AB754A795D9EE) /* 849 */, CONST64(0xA442F7552F72943D) /* 850 */, CONST64(0x2C31334E19781208) /* 851 */, CONST64(0x4FA98D7CEAEE6291) /* 852 */, CONST64(0x55C3862F665DB309) /* 853 */, CONST64(0xBD0610175D53B1F3) /* 854 */, CONST64(0x46FE6CB840413F27) /* 855 */, CONST64(0x3FE03792DF0CFA59) /* 856 */, CONST64(0xCFE700372EB85E8F) /* 857 */, CONST64(0xA7BE29E7ADBCE118) /* 858 */, CONST64(0xE544EE5CDE8431DD) /* 859 */, CONST64(0x8A781B1B41F1873E) /* 860 */, CONST64(0xA5C94C78A0D2F0E7) /* 861 */, CONST64(0x39412E2877B60728) /* 862 */, CONST64(0xA1265EF3AFC9A62C) /* 863 */, CONST64(0xBCC2770C6A2506C5) /* 864 */, CONST64(0x3AB66DD5DCE1CE12) /* 865 */, CONST64(0xE65499D04A675B37) /* 866 */, CONST64(0x7D8F523481BFD216) /* 867 */, CONST64(0x0F6F64FCEC15F389) /* 868 */, CONST64(0x74EFBE618B5B13C8) /* 869 */, CONST64(0xACDC82B714273E1D) /* 870 */, CONST64(0xDD40BFE003199D17) /* 871 */, CONST64(0x37E99257E7E061F8) /* 872 */, CONST64(0xFA52626904775AAA) /* 873 */, CONST64(0x8BBBF63A463D56F9) /* 874 */, CONST64(0xF0013F1543A26E64) /* 875 */, CONST64(0xA8307E9F879EC898) /* 876 */, CONST64(0xCC4C27A4150177CC) /* 877 */, CONST64(0x1B432F2CCA1D3348) /* 878 */, CONST64(0xDE1D1F8F9F6FA013) /* 879 */, CONST64(0x606602A047A7DDD6) /* 880 */, CONST64(0xD237AB64CC1CB2C7) /* 881 */, CONST64(0x9B938E7225FCD1D3) /* 882 */, CONST64(0xEC4E03708E0FF476) /* 883 */, CONST64(0xFEB2FBDA3D03C12D) /* 884 */, CONST64(0xAE0BCED2EE43889A) /* 885 */, CONST64(0x22CB8923EBFB4F43) /* 886 */, CONST64(0x69360D013CF7396D) /* 887 */, CONST64(0x855E3602D2D4E022) /* 888 */, CONST64(0x073805BAD01F784C) /* 889 */, CONST64(0x33E17A133852F546) /* 890 */, CONST64(0xDF4874058AC7B638) /* 891 */, CONST64(0xBA92B29C678AA14A) /* 892 */, CONST64(0x0CE89FC76CFAADCD) /* 893 */, CONST64(0x5F9D4E0908339E34) /* 894 */, CONST64(0xF1AFE9291F5923B9) /* 895 */, CONST64(0x6E3480F60F4A265F) /* 896 */, CONST64(0xEEBF3A2AB29B841C) /* 897 */, CONST64(0xE21938A88F91B4AD) /* 898 */, CONST64(0x57DFEFF845C6D3C3) /* 899 */, CONST64(0x2F006B0BF62CAAF2) /* 900 */, CONST64(0x62F479EF6F75EE78) /* 901 */, CONST64(0x11A55AD41C8916A9) /* 902 */, CONST64(0xF229D29084FED453) /* 903 */, CONST64(0x42F1C27B16B000E6) /* 904 */, CONST64(0x2B1F76749823C074) /* 905 */, CONST64(0x4B76ECA3C2745360) /* 906 */, CONST64(0x8C98F463B91691BD) /* 907 */, CONST64(0x14BCC93CF1ADE66A) /* 908 */, CONST64(0x8885213E6D458397) /* 909 */, CONST64(0x8E177DF0274D4711) /* 910 */, CONST64(0xB49B73B5503F2951) /* 911 */, CONST64(0x10168168C3F96B6B) /* 912 */, CONST64(0x0E3D963B63CAB0AE) /* 913 */, CONST64(0x8DFC4B5655A1DB14) /* 914 */, CONST64(0xF789F1356E14DE5C) /* 915 */, CONST64(0x683E68AF4E51DAC1) /* 916 */, CONST64(0xC9A84F9D8D4B0FD9) /* 917 */, CONST64(0x3691E03F52A0F9D1) /* 918 */, CONST64(0x5ED86E46E1878E80) /* 919 */, CONST64(0x3C711A0E99D07150) /* 920 */, CONST64(0x5A0865B20C4E9310) /* 921 */, CONST64(0x56FBFC1FE4F0682E) /* 922 */, CONST64(0xEA8D5DE3105EDF9B) /* 923 */, CONST64(0x71ABFDB12379187A) /* 924 */, CONST64(0x2EB99DE1BEE77B9C) /* 925 */, CONST64(0x21ECC0EA33CF4523) /* 926 */, CONST64(0x59A4D7521805C7A1) /* 927 */, CONST64(0x3896F5EB56AE7C72) /* 928 */, CONST64(0xAA638F3DB18F75DC) /* 929 */, CONST64(0x9F39358DABE9808E) /* 930 */, CONST64(0xB7DEFA91C00B72AC) /* 931 */, CONST64(0x6B5541FD62492D92) /* 932 */, CONST64(0x6DC6DEE8F92E4D5B) /* 933 */, CONST64(0x353F57ABC4BEEA7E) /* 934 */, CONST64(0x735769D6DA5690CE) /* 935 */, CONST64(0x0A234AA642391484) /* 936 */, CONST64(0xF6F9508028F80D9D) /* 937 */, CONST64(0xB8E319A27AB3F215) /* 938 */, CONST64(0x31AD9C1151341A4D) /* 939 */, CONST64(0x773C22A57BEF5805) /* 940 */, CONST64(0x45C7561A07968633) /* 941 */, CONST64(0xF913DA9E249DBE36) /* 942 */, CONST64(0xDA652D9B78A64C68) /* 943 */, CONST64(0x4C27A97F3BC334EF) /* 944 */, CONST64(0x76621220E66B17F4) /* 945 */, CONST64(0x967743899ACD7D0B) /* 946 */, CONST64(0xF3EE5BCAE0ED6782) /* 947 */, CONST64(0x409F753600C879FC) /* 948 */, CONST64(0x06D09A39B5926DB6) /* 949 */, CONST64(0x6F83AEB0317AC588) /* 950 */, CONST64(0x01E6CA4A86381F21) /* 951 */, CONST64(0x66FF3462D19F3025) /* 952 */, CONST64(0x72207C24DDFD3BFB) /* 953 */, CONST64(0x4AF6B6D3E2ECE2EB) /* 954 */, CONST64(0x9C994DBEC7EA08DE) /* 955 */, CONST64(0x49ACE597B09A8BC4) /* 956 */, CONST64(0xB38C4766CF0797BA) /* 957 */, CONST64(0x131B9373C57C2A75) /* 958 */, CONST64(0xB1822CCE61931E58) /* 959 */, CONST64(0x9D7555B909BA1C0C) /* 960 */, CONST64(0x127FAFDD937D11D2) /* 961 */, CONST64(0x29DA3BADC66D92E4) /* 962 */, CONST64(0xA2C1D57154C2ECBC) /* 963 */, CONST64(0x58C5134D82F6FE24) /* 964 */, CONST64(0x1C3AE3515B62274F) /* 965 */, CONST64(0xE907C82E01CB8126) /* 966 */, CONST64(0xF8ED091913E37FCB) /* 967 */, CONST64(0x3249D8F9C80046C9) /* 968 */, CONST64(0x80CF9BEDE388FB63) /* 969 */, CONST64(0x1881539A116CF19E) /* 970 */, CONST64(0x5103F3F76BD52457) /* 971 */, CONST64(0x15B7E6F5AE47F7A8) /* 972 */, CONST64(0xDBD7C6DED47E9CCF) /* 973 */, CONST64(0x44E55C410228BB1A) /* 974 */, CONST64(0xB647D4255EDB4E99) /* 975 */, CONST64(0x5D11882BB8AAFC30) /* 976 */, CONST64(0xF5098BBB29D3212A) /* 977 */, CONST64(0x8FB5EA14E90296B3) /* 978 */, CONST64(0x677B942157DD025A) /* 979 */, CONST64(0xFB58E7C0A390ACB5) /* 980 */, CONST64(0x89D3674C83BD4A01) /* 981 */, CONST64(0x9E2DA4DF4BF3B93B) /* 982 */, CONST64(0xFCC41E328CAB4829) /* 983 */, CONST64(0x03F38C96BA582C52) /* 984 */, CONST64(0xCAD1BDBD7FD85DB2) /* 985 */, CONST64(0xBBB442C16082AE83) /* 986 */, CONST64(0xB95FE86BA5DA9AB0) /* 987 */, CONST64(0xB22E04673771A93F) /* 988 */, CONST64(0x845358C9493152D8) /* 989 */, CONST64(0xBE2A488697B4541E) /* 990 */, CONST64(0x95A2DC2DD38E6966) /* 991 */, CONST64(0xC02C11AC923C852B) /* 992 */, CONST64(0x2388B1990DF2A87B) /* 993 */, CONST64(0x7C8008FA1B4F37BE) /* 994 */, CONST64(0x1F70D0C84D54E503) /* 995 */, CONST64(0x5490ADEC7ECE57D4) /* 996 */, CONST64(0x002B3C27D9063A3A) /* 997 */, CONST64(0x7EAEA3848030A2BF) /* 998 */, CONST64(0xC602326DED2003C0) /* 999 */, CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */, CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */, CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */, CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */, CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */, CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */, CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */, CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */, CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */, CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */, CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */, CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */}; /* one round of the hash function */ LTC_INLINE static void tiger_round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul) { ulong64 tmp; tmp = (*c ^= x); *a -= t1[LTC_BYTE(tmp, 0)] ^ t2[LTC_BYTE(tmp, 2)] ^ t3[LTC_BYTE(tmp, 4)] ^ t4[LTC_BYTE(tmp, 6)]; tmp = (*b += t4[LTC_BYTE(tmp, 1)] ^ t3[LTC_BYTE(tmp, 3)] ^ t2[LTC_BYTE(tmp,5)] ^ t1[LTC_BYTE(tmp,7)]); switch (mul) { case 5: *b = (tmp << 2) + tmp; break; case 7: *b = (tmp << 3) - tmp; break; case 9: *b = (tmp << 3) + tmp; break; } } /* one complete pass */ static void s_pass(ulong64 *a, ulong64 *b, ulong64 *c, const ulong64 *x, int mul) { tiger_round(a,b,c,x[0],mul); tiger_round(b,c,a,x[1],mul); tiger_round(c,a,b,x[2],mul); tiger_round(a,b,c,x[3],mul); tiger_round(b,c,a,x[4],mul); tiger_round(c,a,b,x[5],mul); tiger_round(a,b,c,x[6],mul); tiger_round(b,c,a,x[7],mul); } /* The key mixing schedule */ static void s_key_schedule(ulong64 *x) { x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5); x[1] ^= x[0]; x[2] += x[1]; x[3] -= x[2] ^ ((~x[1])<<19); x[4] ^= x[3]; x[5] += x[4]; x[6] -= x[5] ^ ((~x[4])>>23); x[7] ^= x[6]; x[0] += x[7]; x[1] -= x[0] ^ ((~x[7])<<19); x[2] ^= x[1]; x[3] += x[2]; x[4] -= x[3] ^ ((~x[2])>>23); x[5] ^= x[4]; x[6] += x[5]; x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF); } #ifdef LTC_CLEAN_STACK static int ss_tiger_compress(hash_state *md, const unsigned char *buf) #else static int s_tiger_compress(hash_state *md, const unsigned char *buf) #endif { ulong64 a, b, c, x[8], t; unsigned long i; /* load words */ for (i = 0; i < 8; i++) { LOAD64L(x[i],&buf[8*i]); } a = md->tiger.state[0]; b = md->tiger.state[1]; c = md->tiger.state[2]; s_pass(&a,&b,&c,x,5); s_key_schedule(x); s_pass(&c,&a,&b,x,7); s_key_schedule(x); s_pass(&b,&c,&a,x,9); for (i = 3; i < md->tiger.passes; ++i) { s_key_schedule(x); s_pass(&a,&b,&c,x,9); t = a; a = c; c = b; b = t; } /* store state */ md->tiger.state[0] = a ^ md->tiger.state[0]; md->tiger.state[1] = b - md->tiger.state[1]; md->tiger.state[2] = c + md->tiger.state[2]; return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_tiger_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_tiger_compress(md, buf); burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long)); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int tiger_init(hash_state *md) { LTC_ARGCHK(md != NULL); md->tiger.state[0] = CONST64(0x0123456789ABCDEF); md->tiger.state[1] = CONST64(0xFEDCBA9876543210); md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187); md->tiger.curlen = 0; md->tiger.length = 0; md->tiger.passes = 3; md->tiger.pad = 0x01u; return CRYPT_OK; } /** Initialize the hash state (extended version) @param md The hash state you wish to initialize @param passes The number of passes that should be executed when the compress function is called. @return CRYPT_OK if successful */ int tiger_init_ex(hash_state *md, unsigned long passes) { int err; if ((err = tiger_init(md) != CRYPT_OK)) { return err; } md->tiger.passes = passes; return CRYPT_OK; } /** Initialize the hash state (extended version) @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int tiger2_init(hash_state *md) { int err; if ((err = tiger_init(md) != CRYPT_OK)) { return err; } md->tiger.pad = 0x80u; return CRYPT_OK; } /** Initialize the hash state (extended version) @param md The hash state you wish to initialize @param passes The number of passes that should be executed when the compress function is called. @return CRYPT_OK if successful */ int tiger2_init_ex(hash_state *md, unsigned long passes) { int err; if ((err = tiger2_init(md) != CRYPT_OK)) { return err; } md->tiger.passes = passes; return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(tiger_process, s_tiger_compress, tiger, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (24 bytes) @return CRYPT_OK if successful */ int tiger_done(hash_state * md, unsigned char *out) { LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->tiger.curlen >= sizeof(md->tiger.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->tiger.length += md->tiger.curlen * 8; /* append the padding bit */ md->tiger.buf[md->tiger.curlen++] = md->tiger.pad; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->tiger.curlen > 56) { while (md->tiger.curlen < 64) { md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; } s_tiger_compress(md, md->tiger.buf); md->tiger.curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->tiger.curlen < 56) { md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; } /* store length */ STORE64L(md->tiger.length, md->tiger.buf+56); s_tiger_compress(md, md->tiger.buf); /* copy output */ STORE64L(md->tiger.state[0], &out[0]); STORE64L(md->tiger.state[1], &out[8]); STORE64L(md->tiger.state[2], &out[16]); #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(hash_state)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int s_tiger_test(unsigned int idx) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { const char *msg; unsigned char hash[2][24]; } tests[] = { { "", { { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24, 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16, 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 }, { 0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73, 0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92, 0x4a, 0xa8, 0x31, 0x3f, 0xef, 0x91, 0x9f, 0x41 }, }, }, { "abc", { { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2, 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52, 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 }, { 0xf6, 0x8d, 0x7b, 0xc5, 0xaf, 0x4b, 0x43, 0xa0, 0x6e, 0x04, 0x8d, 0x78, 0x29, 0x56, 0x0d, 0x4a, 0x94, 0x15, 0x65, 0x8b, 0xb0, 0xb1, 0xf3, 0xbf }, }, }, { "Tiger", { { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f, 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27, 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 }, { 0xfe, 0x40, 0x79, 0x8b, 0x8e, 0xb9, 0x37, 0xfd, 0x97, 0x76, 0x08, 0x93, 0x05, 0x48, 0xd6, 0xa8, 0x94, 0xc2, 0x0b, 0x04, 0xcb, 0xef, 0x7a, 0x42 }, }, }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", { { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87, 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47, 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 }, { 0x15, 0x9b, 0x38, 0x0a, 0xb7, 0x92, 0x94, 0xe0, 0xda, 0x19, 0xf1, 0x62, 0x82, 0xce, 0x6d, 0xce, 0x0f, 0x84, 0xd3, 0x4f, 0x72, 0x9d, 0xbe, 0xa3 }, }, }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", { { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00, 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76, 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 }, { 0x01, 0xef, 0x91, 0x0b, 0x9b, 0xb2, 0xcb, 0x4c, 0x6c, 0x47, 0x49, 0x5c, 0x86, 0xb3, 0x64, 0x1a, 0xff, 0x14, 0xfb, 0xf7, 0x79, 0x40, 0x9c, 0x0e }, }, }, }; int (*init[2])(hash_state *hash) = { tiger_init, tiger2_init }; int i; unsigned char tmp[24]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { init[idx](&md); tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); tiger_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash[idx], sizeof(tests[i].hash[idx]), !idx ? "TIGER": "TIGER2", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int tiger_test(void) { return s_tiger_test(0); } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int tiger2_test(void) { return s_tiger_test(1); } #endif /* Hash of "": 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A Hash of "abc": F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 Hash of "Tiger": 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789": 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham": 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.": EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.": 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 */ optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/whirl/000077500000000000000000000000001464416617300226045ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/whirl/whirl.c000066400000000000000000000222761464416617300241060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file whirl.c LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis */ #include "tomcrypt_private.h" #ifdef LTC_WHIRLPOOL const struct ltc_hash_descriptor whirlpool_desc = { "whirlpool", 11, 64, 64, /* OID */ { 1, 0, 10118, 3, 0, 55 }, 6, &whirlpool_init, &whirlpool_process, &whirlpool_done, &whirlpool_test, NULL }; /* the sboxes */ #define LTC_WHIRLTAB_C #include "whirltab.c" /* get a_{i,j} */ #define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255) /* shortcut macro to perform three functions at once */ #define theta_pi_gamma(a, i) \ (SB0(GB(a, i-0, 7)) ^ \ SB1(GB(a, i-1, 6)) ^ \ SB2(GB(a, i-2, 5)) ^ \ SB3(GB(a, i-3, 4)) ^ \ SB4(GB(a, i-4, 3)) ^ \ SB5(GB(a, i-5, 2)) ^ \ SB6(GB(a, i-6, 1)) ^ \ SB7(GB(a, i-7, 0))) #ifdef LTC_CLEAN_STACK static int ss_whirlpool_compress(hash_state *md, const unsigned char *buf) #else static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) #endif { ulong64 K[2][8], T[3][8]; int x, y; /* load the block/state */ for (x = 0; x < 8; x++) { K[0][x] = md->whirlpool.state[x]; LOAD64H(T[0][x], buf + (8 * x)); T[2][x] = T[0][x]; T[0][x] ^= K[0][x]; } /* do rounds 1..10 */ for (x = 0; x < 10; x += 2) { /* odd round */ /* apply main transform to K[0] into K[1] */ for (y = 0; y < 8; y++) { K[1][y] = theta_pi_gamma(K[0], y); } /* xor the constant */ K[1][0] ^= cont[x]; /* apply main transform to T[0] into T[1] */ for (y = 0; y < 8; y++) { T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y]; } /* even round */ /* apply main transform to K[1] into K[0] */ for (y = 0; y < 8; y++) { K[0][y] = theta_pi_gamma(K[1], y); } /* xor the constant */ K[0][0] ^= cont[x+1]; /* apply main transform to T[1] into T[0] */ for (y = 0; y < 8; y++) { T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y]; } } /* store state */ for (x = 0; x < 8; x++) { md->whirlpool.state[x] ^= T[0][x] ^ T[2][x]; } return CRYPT_OK; } #ifdef LTC_CLEAN_STACK static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) { int err; err = ss_whirlpool_compress(md, buf); burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int))); return err; } #endif /** Initialize the hash state @param md The hash state you wish to initialize @return CRYPT_OK if successful */ int whirlpool_init(hash_state * md) { LTC_ARGCHK(md != NULL); zeromem(&md->whirlpool, sizeof(md->whirlpool)); return CRYPT_OK; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ HASH_PROCESS(whirlpool_process, s_whirlpool_compress, whirlpool, 64) /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (64 bytes) @return CRYPT_OK if successful */ int whirlpool_done(hash_state * md, unsigned char *out) { int i; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) { return CRYPT_INVALID_ARG; } /* increase the length of the message */ md->whirlpool.length += md->whirlpool.curlen * 8; /* append the '1' bit */ md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80; /* if the length is currently above 32 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->whirlpool.curlen > 32) { while (md->whirlpool.curlen < 64) { md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; } s_whirlpool_compress(md, md->whirlpool.buf); md->whirlpool.curlen = 0; } /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */ while (md->whirlpool.curlen < 56) { md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; } /* store length */ STORE64H(md->whirlpool.length, md->whirlpool.buf+56); s_whirlpool_compress(md, md->whirlpool.buf); /* copy output */ for (i = 0; i < 8; i++) { STORE64H(md->whirlpool.state[i], out+(8*i)); } #ifdef LTC_CLEAN_STACK zeromem(md, sizeof(*md)); #endif return CRYPT_OK; } /** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int whirlpool_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { int len; unsigned char msg[128], hash[64]; } tests[] = { /* NULL Message */ { 0, { 0x00 }, { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 } }, /* 448-bits of 0 bits */ { 56, { 0x00 }, { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03, 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70, 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61, 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 } }, /* 520-bits of 0 bits */ { 65, { 0x00 }, { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D, 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4, 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF, 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 } }, /* 512-bits, leading set */ { 64, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A, 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94, 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6, 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB } }, /* 512-bits, leading set of second byte */ { 64, { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E, 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F, 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35, 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 } }, /* 512-bits, leading set of last byte */ { 64, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6, 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F, 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B, 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 } }, }; int i; unsigned char tmp[64]; hash_state md; for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { whirlpool_init(&md); whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len); whirlpool_done(&md, tmp); if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/hashes/whirl/whirltab.c000066400000000000000000001665371464416617300246060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file whirltab.c LTC_WHIRLPOOL tables, Tom St Denis */ #ifdef LTC_WHIRLTAB_C static const ulong64 sbox0[] = { CONST64(0x18186018c07830d8), CONST64(0x23238c2305af4626), CONST64(0xc6c63fc67ef991b8), CONST64(0xe8e887e8136fcdfb), CONST64(0x878726874ca113cb), CONST64(0xb8b8dab8a9626d11), CONST64(0x0101040108050209), CONST64(0x4f4f214f426e9e0d), CONST64(0x3636d836adee6c9b), CONST64(0xa6a6a2a6590451ff), CONST64(0xd2d26fd2debdb90c), CONST64(0xf5f5f3f5fb06f70e), CONST64(0x7979f979ef80f296), CONST64(0x6f6fa16f5fcede30), CONST64(0x91917e91fcef3f6d), CONST64(0x52525552aa07a4f8), CONST64(0x60609d6027fdc047), CONST64(0xbcbccabc89766535), CONST64(0x9b9b569baccd2b37), CONST64(0x8e8e028e048c018a), CONST64(0xa3a3b6a371155bd2), CONST64(0x0c0c300c603c186c), CONST64(0x7b7bf17bff8af684), CONST64(0x3535d435b5e16a80), CONST64(0x1d1d741de8693af5), CONST64(0xe0e0a7e05347ddb3), CONST64(0xd7d77bd7f6acb321), CONST64(0xc2c22fc25eed999c), CONST64(0x2e2eb82e6d965c43), CONST64(0x4b4b314b627a9629), CONST64(0xfefedffea321e15d), CONST64(0x575741578216aed5), CONST64(0x15155415a8412abd), CONST64(0x7777c1779fb6eee8), CONST64(0x3737dc37a5eb6e92), CONST64(0xe5e5b3e57b56d79e), CONST64(0x9f9f469f8cd92313), CONST64(0xf0f0e7f0d317fd23), CONST64(0x4a4a354a6a7f9420), CONST64(0xdada4fda9e95a944), CONST64(0x58587d58fa25b0a2), CONST64(0xc9c903c906ca8fcf), CONST64(0x2929a429558d527c), CONST64(0x0a0a280a5022145a), CONST64(0xb1b1feb1e14f7f50), CONST64(0xa0a0baa0691a5dc9), CONST64(0x6b6bb16b7fdad614), CONST64(0x85852e855cab17d9), CONST64(0xbdbdcebd8173673c), CONST64(0x5d5d695dd234ba8f), CONST64(0x1010401080502090), CONST64(0xf4f4f7f4f303f507), CONST64(0xcbcb0bcb16c08bdd), CONST64(0x3e3ef83eedc67cd3), CONST64(0x0505140528110a2d), CONST64(0x676781671fe6ce78), CONST64(0xe4e4b7e47353d597), CONST64(0x27279c2725bb4e02), CONST64(0x4141194132588273), CONST64(0x8b8b168b2c9d0ba7), CONST64(0xa7a7a6a7510153f6), CONST64(0x7d7de97dcf94fab2), CONST64(0x95956e95dcfb3749), CONST64(0xd8d847d88e9fad56), CONST64(0xfbfbcbfb8b30eb70), CONST64(0xeeee9fee2371c1cd), CONST64(0x7c7ced7cc791f8bb), CONST64(0x6666856617e3cc71), CONST64(0xdddd53dda68ea77b), CONST64(0x17175c17b84b2eaf), CONST64(0x4747014702468e45), CONST64(0x9e9e429e84dc211a), CONST64(0xcaca0fca1ec589d4), CONST64(0x2d2db42d75995a58), CONST64(0xbfbfc6bf9179632e), CONST64(0x07071c07381b0e3f), CONST64(0xadad8ead012347ac), CONST64(0x5a5a755aea2fb4b0), CONST64(0x838336836cb51bef), CONST64(0x3333cc3385ff66b6), CONST64(0x636391633ff2c65c), CONST64(0x02020802100a0412), CONST64(0xaaaa92aa39384993), CONST64(0x7171d971afa8e2de), CONST64(0xc8c807c80ecf8dc6), CONST64(0x19196419c87d32d1), CONST64(0x494939497270923b), CONST64(0xd9d943d9869aaf5f), CONST64(0xf2f2eff2c31df931), CONST64(0xe3e3abe34b48dba8), CONST64(0x5b5b715be22ab6b9), CONST64(0x88881a8834920dbc), CONST64(0x9a9a529aa4c8293e), CONST64(0x262698262dbe4c0b), CONST64(0x3232c8328dfa64bf), CONST64(0xb0b0fab0e94a7d59), CONST64(0xe9e983e91b6acff2), CONST64(0x0f0f3c0f78331e77), CONST64(0xd5d573d5e6a6b733), CONST64(0x80803a8074ba1df4), CONST64(0xbebec2be997c6127), CONST64(0xcdcd13cd26de87eb), CONST64(0x3434d034bde46889), CONST64(0x48483d487a759032), CONST64(0xffffdbffab24e354), CONST64(0x7a7af57af78ff48d), CONST64(0x90907a90f4ea3d64), CONST64(0x5f5f615fc23ebe9d), CONST64(0x202080201da0403d), CONST64(0x6868bd6867d5d00f), CONST64(0x1a1a681ad07234ca), CONST64(0xaeae82ae192c41b7), CONST64(0xb4b4eab4c95e757d), CONST64(0x54544d549a19a8ce), CONST64(0x93937693ece53b7f), CONST64(0x222288220daa442f), CONST64(0x64648d6407e9c863), CONST64(0xf1f1e3f1db12ff2a), CONST64(0x7373d173bfa2e6cc), CONST64(0x12124812905a2482), CONST64(0x40401d403a5d807a), CONST64(0x0808200840281048), CONST64(0xc3c32bc356e89b95), CONST64(0xecec97ec337bc5df), CONST64(0xdbdb4bdb9690ab4d), CONST64(0xa1a1bea1611f5fc0), CONST64(0x8d8d0e8d1c830791), CONST64(0x3d3df43df5c97ac8), CONST64(0x97976697ccf1335b), CONST64(0x0000000000000000), CONST64(0xcfcf1bcf36d483f9), CONST64(0x2b2bac2b4587566e), CONST64(0x7676c57697b3ece1), CONST64(0x8282328264b019e6), CONST64(0xd6d67fd6fea9b128), CONST64(0x1b1b6c1bd87736c3), CONST64(0xb5b5eeb5c15b7774), CONST64(0xafaf86af112943be), CONST64(0x6a6ab56a77dfd41d), CONST64(0x50505d50ba0da0ea), CONST64(0x45450945124c8a57), CONST64(0xf3f3ebf3cb18fb38), CONST64(0x3030c0309df060ad), CONST64(0xefef9bef2b74c3c4), CONST64(0x3f3ffc3fe5c37eda), CONST64(0x55554955921caac7), CONST64(0xa2a2b2a2791059db), CONST64(0xeaea8fea0365c9e9), CONST64(0x656589650fecca6a), CONST64(0xbabad2bab9686903), CONST64(0x2f2fbc2f65935e4a), CONST64(0xc0c027c04ee79d8e), CONST64(0xdede5fdebe81a160), CONST64(0x1c1c701ce06c38fc), CONST64(0xfdfdd3fdbb2ee746), CONST64(0x4d4d294d52649a1f), CONST64(0x92927292e4e03976), CONST64(0x7575c9758fbceafa), CONST64(0x06061806301e0c36), CONST64(0x8a8a128a249809ae), CONST64(0xb2b2f2b2f940794b), CONST64(0xe6e6bfe66359d185), CONST64(0x0e0e380e70361c7e), CONST64(0x1f1f7c1ff8633ee7), CONST64(0x6262956237f7c455), CONST64(0xd4d477d4eea3b53a), CONST64(0xa8a89aa829324d81), CONST64(0x96966296c4f43152), CONST64(0xf9f9c3f99b3aef62), CONST64(0xc5c533c566f697a3), CONST64(0x2525942535b14a10), CONST64(0x59597959f220b2ab), CONST64(0x84842a8454ae15d0), CONST64(0x7272d572b7a7e4c5), CONST64(0x3939e439d5dd72ec), CONST64(0x4c4c2d4c5a619816), CONST64(0x5e5e655eca3bbc94), CONST64(0x7878fd78e785f09f), CONST64(0x3838e038ddd870e5), CONST64(0x8c8c0a8c14860598), CONST64(0xd1d163d1c6b2bf17), CONST64(0xa5a5aea5410b57e4), CONST64(0xe2e2afe2434dd9a1), CONST64(0x616199612ff8c24e), CONST64(0xb3b3f6b3f1457b42), CONST64(0x2121842115a54234), CONST64(0x9c9c4a9c94d62508), CONST64(0x1e1e781ef0663cee), CONST64(0x4343114322528661), CONST64(0xc7c73bc776fc93b1), CONST64(0xfcfcd7fcb32be54f), CONST64(0x0404100420140824), CONST64(0x51515951b208a2e3), CONST64(0x99995e99bcc72f25), CONST64(0x6d6da96d4fc4da22), CONST64(0x0d0d340d68391a65), CONST64(0xfafacffa8335e979), CONST64(0xdfdf5bdfb684a369), CONST64(0x7e7ee57ed79bfca9), CONST64(0x242490243db44819), CONST64(0x3b3bec3bc5d776fe), CONST64(0xabab96ab313d4b9a), CONST64(0xcece1fce3ed181f0), CONST64(0x1111441188552299), CONST64(0x8f8f068f0c890383), CONST64(0x4e4e254e4a6b9c04), CONST64(0xb7b7e6b7d1517366), CONST64(0xebeb8beb0b60cbe0), CONST64(0x3c3cf03cfdcc78c1), CONST64(0x81813e817cbf1ffd), CONST64(0x94946a94d4fe3540), CONST64(0xf7f7fbf7eb0cf31c), CONST64(0xb9b9deb9a1676f18), CONST64(0x13134c13985f268b), CONST64(0x2c2cb02c7d9c5851), CONST64(0xd3d36bd3d6b8bb05), CONST64(0xe7e7bbe76b5cd38c), CONST64(0x6e6ea56e57cbdc39), CONST64(0xc4c437c46ef395aa), CONST64(0x03030c03180f061b), CONST64(0x565645568a13acdc), CONST64(0x44440d441a49885e), CONST64(0x7f7fe17fdf9efea0), CONST64(0xa9a99ea921374f88), CONST64(0x2a2aa82a4d825467), CONST64(0xbbbbd6bbb16d6b0a), CONST64(0xc1c123c146e29f87), CONST64(0x53535153a202a6f1), CONST64(0xdcdc57dcae8ba572), CONST64(0x0b0b2c0b58271653), CONST64(0x9d9d4e9d9cd32701), CONST64(0x6c6cad6c47c1d82b), CONST64(0x3131c43195f562a4), CONST64(0x7474cd7487b9e8f3), CONST64(0xf6f6fff6e309f115), CONST64(0x464605460a438c4c), CONST64(0xacac8aac092645a5), CONST64(0x89891e893c970fb5), CONST64(0x14145014a04428b4), CONST64(0xe1e1a3e15b42dfba), CONST64(0x16165816b04e2ca6), CONST64(0x3a3ae83acdd274f7), CONST64(0x6969b9696fd0d206), CONST64(0x09092409482d1241), CONST64(0x7070dd70a7ade0d7), CONST64(0xb6b6e2b6d954716f), CONST64(0xd0d067d0ceb7bd1e), CONST64(0xeded93ed3b7ec7d6), CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c22d2c), CONST64(0xa4a4aaa4490e55ed), CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2) }; #ifdef LTC_SMALL_CODE #define SB0(x) sbox0[x] #define SB1(x) ROR64c(sbox0[x], 8) #define SB2(x) ROR64c(sbox0[x], 16) #define SB3(x) ROR64c(sbox0[x], 24) #define SB4(x) ROR64c(sbox0[x], 32) #define SB5(x) ROR64c(sbox0[x], 40) #define SB6(x) ROR64c(sbox0[x], 48) #define SB7(x) ROR64c(sbox0[x], 56) #else #define SB0(x) sbox0[x] #define SB1(x) sbox1[x] #define SB2(x) sbox2[x] #define SB3(x) sbox3[x] #define SB4(x) sbox4[x] #define SB5(x) sbox5[x] #define SB6(x) sbox6[x] #define SB7(x) sbox7[x] static const ulong64 sbox1[] = { CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd), CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e), CONST64(0x9b3636d836adee6c), CONST64(0xffa6a6a2a6590451), CONST64(0x0cd2d26fd2debdb9), CONST64(0x0ef5f5f3f5fb06f7), CONST64(0x967979f979ef80f2), CONST64(0x306f6fa16f5fcede), CONST64(0x6d91917e91fcef3f), CONST64(0xf852525552aa07a4), CONST64(0x4760609d6027fdc0), CONST64(0x35bcbccabc897665), CONST64(0x379b9b569baccd2b), CONST64(0x8a8e8e028e048c01), CONST64(0xd2a3a3b6a371155b), CONST64(0x6c0c0c300c603c18), CONST64(0x847b7bf17bff8af6), CONST64(0x803535d435b5e16a), CONST64(0xf51d1d741de8693a), CONST64(0xb3e0e0a7e05347dd), CONST64(0x21d7d77bd7f6acb3), CONST64(0x9cc2c22fc25eed99), CONST64(0x432e2eb82e6d965c), CONST64(0x294b4b314b627a96), CONST64(0x5dfefedffea321e1), CONST64(0xd5575741578216ae), CONST64(0xbd15155415a8412a), CONST64(0xe87777c1779fb6ee), CONST64(0x923737dc37a5eb6e), CONST64(0x9ee5e5b3e57b56d7), CONST64(0x139f9f469f8cd923), CONST64(0x23f0f0e7f0d317fd), CONST64(0x204a4a354a6a7f94), CONST64(0x44dada4fda9e95a9), CONST64(0xa258587d58fa25b0), CONST64(0xcfc9c903c906ca8f), CONST64(0x7c2929a429558d52), CONST64(0x5a0a0a280a502214), CONST64(0x50b1b1feb1e14f7f), CONST64(0xc9a0a0baa0691a5d), CONST64(0x146b6bb16b7fdad6), CONST64(0xd985852e855cab17), CONST64(0x3cbdbdcebd817367), CONST64(0x8f5d5d695dd234ba), CONST64(0x9010104010805020), CONST64(0x07f4f4f7f4f303f5), CONST64(0xddcbcb0bcb16c08b), CONST64(0xd33e3ef83eedc67c), CONST64(0x2d0505140528110a), CONST64(0x78676781671fe6ce), CONST64(0x97e4e4b7e47353d5), CONST64(0x0227279c2725bb4e), CONST64(0x7341411941325882), CONST64(0xa78b8b168b2c9d0b), CONST64(0xf6a7a7a6a7510153), CONST64(0xb27d7de97dcf94fa), CONST64(0x4995956e95dcfb37), CONST64(0x56d8d847d88e9fad), CONST64(0x70fbfbcbfb8b30eb), CONST64(0xcdeeee9fee2371c1), CONST64(0xbb7c7ced7cc791f8), CONST64(0x716666856617e3cc), CONST64(0x7bdddd53dda68ea7), CONST64(0xaf17175c17b84b2e), CONST64(0x454747014702468e), CONST64(0x1a9e9e429e84dc21), CONST64(0xd4caca0fca1ec589), CONST64(0x582d2db42d75995a), CONST64(0x2ebfbfc6bf917963), CONST64(0x3f07071c07381b0e), CONST64(0xacadad8ead012347), CONST64(0xb05a5a755aea2fb4), CONST64(0xef838336836cb51b), CONST64(0xb63333cc3385ff66), CONST64(0x5c636391633ff2c6), CONST64(0x1202020802100a04), CONST64(0x93aaaa92aa393849), CONST64(0xde7171d971afa8e2), CONST64(0xc6c8c807c80ecf8d), CONST64(0xd119196419c87d32), CONST64(0x3b49493949727092), CONST64(0x5fd9d943d9869aaf), CONST64(0x31f2f2eff2c31df9), CONST64(0xa8e3e3abe34b48db), CONST64(0xb95b5b715be22ab6), CONST64(0xbc88881a8834920d), CONST64(0x3e9a9a529aa4c829), CONST64(0x0b262698262dbe4c), CONST64(0xbf3232c8328dfa64), CONST64(0x59b0b0fab0e94a7d), CONST64(0xf2e9e983e91b6acf), CONST64(0x770f0f3c0f78331e), CONST64(0x33d5d573d5e6a6b7), CONST64(0xf480803a8074ba1d), CONST64(0x27bebec2be997c61), CONST64(0xebcdcd13cd26de87), CONST64(0x893434d034bde468), CONST64(0x3248483d487a7590), CONST64(0x54ffffdbffab24e3), CONST64(0x8d7a7af57af78ff4), CONST64(0x6490907a90f4ea3d), CONST64(0x9d5f5f615fc23ebe), CONST64(0x3d202080201da040), CONST64(0x0f6868bd6867d5d0), CONST64(0xca1a1a681ad07234), CONST64(0xb7aeae82ae192c41), CONST64(0x7db4b4eab4c95e75), CONST64(0xce54544d549a19a8), CONST64(0x7f93937693ece53b), CONST64(0x2f222288220daa44), CONST64(0x6364648d6407e9c8), CONST64(0x2af1f1e3f1db12ff), CONST64(0xcc7373d173bfa2e6), CONST64(0x8212124812905a24), CONST64(0x7a40401d403a5d80), CONST64(0x4808082008402810), CONST64(0x95c3c32bc356e89b), CONST64(0xdfecec97ec337bc5), CONST64(0x4ddbdb4bdb9690ab), CONST64(0xc0a1a1bea1611f5f), CONST64(0x918d8d0e8d1c8307), CONST64(0xc83d3df43df5c97a), CONST64(0x5b97976697ccf133), CONST64(0x0000000000000000), CONST64(0xf9cfcf1bcf36d483), CONST64(0x6e2b2bac2b458756), CONST64(0xe17676c57697b3ec), CONST64(0xe68282328264b019), CONST64(0x28d6d67fd6fea9b1), CONST64(0xc31b1b6c1bd87736), CONST64(0x74b5b5eeb5c15b77), CONST64(0xbeafaf86af112943), CONST64(0x1d6a6ab56a77dfd4), CONST64(0xea50505d50ba0da0), CONST64(0x5745450945124c8a), CONST64(0x38f3f3ebf3cb18fb), CONST64(0xad3030c0309df060), CONST64(0xc4efef9bef2b74c3), CONST64(0xda3f3ffc3fe5c37e), CONST64(0xc755554955921caa), CONST64(0xdba2a2b2a2791059), CONST64(0xe9eaea8fea0365c9), CONST64(0x6a656589650fecca), CONST64(0x03babad2bab96869), CONST64(0x4a2f2fbc2f65935e), CONST64(0x8ec0c027c04ee79d), CONST64(0x60dede5fdebe81a1), CONST64(0xfc1c1c701ce06c38), CONST64(0x46fdfdd3fdbb2ee7), CONST64(0x1f4d4d294d52649a), CONST64(0x7692927292e4e039), CONST64(0xfa7575c9758fbcea), CONST64(0x3606061806301e0c), CONST64(0xae8a8a128a249809), CONST64(0x4bb2b2f2b2f94079), CONST64(0x85e6e6bfe66359d1), CONST64(0x7e0e0e380e70361c), CONST64(0xe71f1f7c1ff8633e), CONST64(0x556262956237f7c4), CONST64(0x3ad4d477d4eea3b5), CONST64(0x81a8a89aa829324d), CONST64(0x5296966296c4f431), CONST64(0x62f9f9c3f99b3aef), CONST64(0xa3c5c533c566f697), CONST64(0x102525942535b14a), CONST64(0xab59597959f220b2), CONST64(0xd084842a8454ae15), CONST64(0xc57272d572b7a7e4), CONST64(0xec3939e439d5dd72), CONST64(0x164c4c2d4c5a6198), CONST64(0x945e5e655eca3bbc), CONST64(0x9f7878fd78e785f0), CONST64(0xe53838e038ddd870), CONST64(0x988c8c0a8c148605), CONST64(0x17d1d163d1c6b2bf), CONST64(0xe4a5a5aea5410b57), CONST64(0xa1e2e2afe2434dd9), CONST64(0x4e616199612ff8c2), CONST64(0x42b3b3f6b3f1457b), CONST64(0x342121842115a542), CONST64(0x089c9c4a9c94d625), CONST64(0xee1e1e781ef0663c), CONST64(0x6143431143225286), CONST64(0xb1c7c73bc776fc93), CONST64(0x4ffcfcd7fcb32be5), CONST64(0x2404041004201408), CONST64(0xe351515951b208a2), CONST64(0x2599995e99bcc72f), CONST64(0x226d6da96d4fc4da), CONST64(0x650d0d340d68391a), CONST64(0x79fafacffa8335e9), CONST64(0x69dfdf5bdfb684a3), CONST64(0xa97e7ee57ed79bfc), CONST64(0x19242490243db448), CONST64(0xfe3b3bec3bc5d776), CONST64(0x9aabab96ab313d4b), CONST64(0xf0cece1fce3ed181), CONST64(0x9911114411885522), CONST64(0x838f8f068f0c8903), CONST64(0x044e4e254e4a6b9c), CONST64(0x66b7b7e6b7d15173), CONST64(0xe0ebeb8beb0b60cb), CONST64(0xc13c3cf03cfdcc78), CONST64(0xfd81813e817cbf1f), CONST64(0x4094946a94d4fe35), CONST64(0x1cf7f7fbf7eb0cf3), CONST64(0x18b9b9deb9a1676f), CONST64(0x8b13134c13985f26), CONST64(0x512c2cb02c7d9c58), CONST64(0x05d3d36bd3d6b8bb), CONST64(0x8ce7e7bbe76b5cd3), CONST64(0x396e6ea56e57cbdc), CONST64(0xaac4c437c46ef395), CONST64(0x1b03030c03180f06), CONST64(0xdc565645568a13ac), CONST64(0x5e44440d441a4988), CONST64(0xa07f7fe17fdf9efe), CONST64(0x88a9a99ea921374f), CONST64(0x672a2aa82a4d8254), CONST64(0x0abbbbd6bbb16d6b), CONST64(0x87c1c123c146e29f), CONST64(0xf153535153a202a6), CONST64(0x72dcdc57dcae8ba5), CONST64(0x530b0b2c0b582716), CONST64(0x019d9d4e9d9cd327), CONST64(0x2b6c6cad6c47c1d8), CONST64(0xa43131c43195f562), CONST64(0xf37474cd7487b9e8), CONST64(0x15f6f6fff6e309f1), CONST64(0x4c464605460a438c), CONST64(0xa5acac8aac092645), CONST64(0xb589891e893c970f), CONST64(0xb414145014a04428), CONST64(0xbae1e1a3e15b42df), CONST64(0xa616165816b04e2c), CONST64(0xf73a3ae83acdd274), CONST64(0x066969b9696fd0d2), CONST64(0x4109092409482d12), CONST64(0xd77070dd70a7ade0), CONST64(0x6fb6b6e2b6d95471), CONST64(0x1ed0d067d0ceb7bd), CONST64(0xd6eded93ed3b7ec7), CONST64(0xe2cccc17cc2edb85), CONST64(0x68424215422a5784), CONST64(0x2c98985a98b4c22d), CONST64(0xeda4a4aaa4490e55), CONST64(0x752828a0285d8850), CONST64(0x865c5c6d5cda31b8), CONST64(0x6bf8f8c7f8933fed), CONST64(0xc28686228644a411) }; static const ulong64 sbox2[] = { CONST64(0x30d818186018c078), CONST64(0x462623238c2305af), CONST64(0x91b8c6c63fc67ef9), CONST64(0xcdfbe8e887e8136f), CONST64(0x13cb878726874ca1), CONST64(0x6d11b8b8dab8a962), CONST64(0x0209010104010805), CONST64(0x9e0d4f4f214f426e), CONST64(0x6c9b3636d836adee), CONST64(0x51ffa6a6a2a65904), CONST64(0xb90cd2d26fd2debd), CONST64(0xf70ef5f5f3f5fb06), CONST64(0xf2967979f979ef80), CONST64(0xde306f6fa16f5fce), CONST64(0x3f6d91917e91fcef), CONST64(0xa4f852525552aa07), CONST64(0xc04760609d6027fd), CONST64(0x6535bcbccabc8976), CONST64(0x2b379b9b569baccd), CONST64(0x018a8e8e028e048c), CONST64(0x5bd2a3a3b6a37115), CONST64(0x186c0c0c300c603c), CONST64(0xf6847b7bf17bff8a), CONST64(0x6a803535d435b5e1), CONST64(0x3af51d1d741de869), CONST64(0xddb3e0e0a7e05347), CONST64(0xb321d7d77bd7f6ac), CONST64(0x999cc2c22fc25eed), CONST64(0x5c432e2eb82e6d96), CONST64(0x96294b4b314b627a), CONST64(0xe15dfefedffea321), CONST64(0xaed5575741578216), CONST64(0x2abd15155415a841), CONST64(0xeee87777c1779fb6), CONST64(0x6e923737dc37a5eb), CONST64(0xd79ee5e5b3e57b56), CONST64(0x23139f9f469f8cd9), CONST64(0xfd23f0f0e7f0d317), CONST64(0x94204a4a354a6a7f), CONST64(0xa944dada4fda9e95), CONST64(0xb0a258587d58fa25), CONST64(0x8fcfc9c903c906ca), CONST64(0x527c2929a429558d), CONST64(0x145a0a0a280a5022), CONST64(0x7f50b1b1feb1e14f), CONST64(0x5dc9a0a0baa0691a), CONST64(0xd6146b6bb16b7fda), CONST64(0x17d985852e855cab), CONST64(0x673cbdbdcebd8173), CONST64(0xba8f5d5d695dd234), CONST64(0x2090101040108050), CONST64(0xf507f4f4f7f4f303), CONST64(0x8bddcbcb0bcb16c0), CONST64(0x7cd33e3ef83eedc6), CONST64(0x0a2d050514052811), CONST64(0xce78676781671fe6), CONST64(0xd597e4e4b7e47353), CONST64(0x4e0227279c2725bb), CONST64(0x8273414119413258), CONST64(0x0ba78b8b168b2c9d), CONST64(0x53f6a7a7a6a75101), CONST64(0xfab27d7de97dcf94), CONST64(0x374995956e95dcfb), CONST64(0xad56d8d847d88e9f), CONST64(0xeb70fbfbcbfb8b30), CONST64(0xc1cdeeee9fee2371), CONST64(0xf8bb7c7ced7cc791), CONST64(0xcc716666856617e3), CONST64(0xa77bdddd53dda68e), CONST64(0x2eaf17175c17b84b), CONST64(0x8e45474701470246), CONST64(0x211a9e9e429e84dc), CONST64(0x89d4caca0fca1ec5), CONST64(0x5a582d2db42d7599), CONST64(0x632ebfbfc6bf9179), CONST64(0x0e3f07071c07381b), CONST64(0x47acadad8ead0123), CONST64(0xb4b05a5a755aea2f), CONST64(0x1bef838336836cb5), CONST64(0x66b63333cc3385ff), CONST64(0xc65c636391633ff2), CONST64(0x041202020802100a), CONST64(0x4993aaaa92aa3938), CONST64(0xe2de7171d971afa8), CONST64(0x8dc6c8c807c80ecf), CONST64(0x32d119196419c87d), CONST64(0x923b494939497270), CONST64(0xaf5fd9d943d9869a), CONST64(0xf931f2f2eff2c31d), CONST64(0xdba8e3e3abe34b48), CONST64(0xb6b95b5b715be22a), CONST64(0x0dbc88881a883492), CONST64(0x293e9a9a529aa4c8), CONST64(0x4c0b262698262dbe), CONST64(0x64bf3232c8328dfa), CONST64(0x7d59b0b0fab0e94a), CONST64(0xcff2e9e983e91b6a), CONST64(0x1e770f0f3c0f7833), CONST64(0xb733d5d573d5e6a6), CONST64(0x1df480803a8074ba), CONST64(0x6127bebec2be997c), CONST64(0x87ebcdcd13cd26de), CONST64(0x68893434d034bde4), CONST64(0x903248483d487a75), CONST64(0xe354ffffdbffab24), CONST64(0xf48d7a7af57af78f), CONST64(0x3d6490907a90f4ea), CONST64(0xbe9d5f5f615fc23e), CONST64(0x403d202080201da0), CONST64(0xd00f6868bd6867d5), CONST64(0x34ca1a1a681ad072), CONST64(0x41b7aeae82ae192c), CONST64(0x757db4b4eab4c95e), CONST64(0xa8ce54544d549a19), CONST64(0x3b7f93937693ece5), CONST64(0x442f222288220daa), CONST64(0xc86364648d6407e9), CONST64(0xff2af1f1e3f1db12), CONST64(0xe6cc7373d173bfa2), CONST64(0x248212124812905a), CONST64(0x807a40401d403a5d), CONST64(0x1048080820084028), CONST64(0x9b95c3c32bc356e8), CONST64(0xc5dfecec97ec337b), CONST64(0xab4ddbdb4bdb9690), CONST64(0x5fc0a1a1bea1611f), CONST64(0x07918d8d0e8d1c83), CONST64(0x7ac83d3df43df5c9), CONST64(0x335b97976697ccf1), CONST64(0x0000000000000000), CONST64(0x83f9cfcf1bcf36d4), CONST64(0x566e2b2bac2b4587), CONST64(0xece17676c57697b3), CONST64(0x19e68282328264b0), CONST64(0xb128d6d67fd6fea9), CONST64(0x36c31b1b6c1bd877), CONST64(0x7774b5b5eeb5c15b), CONST64(0x43beafaf86af1129), CONST64(0xd41d6a6ab56a77df), CONST64(0xa0ea50505d50ba0d), CONST64(0x8a5745450945124c), CONST64(0xfb38f3f3ebf3cb18), CONST64(0x60ad3030c0309df0), CONST64(0xc3c4efef9bef2b74), CONST64(0x7eda3f3ffc3fe5c3), CONST64(0xaac755554955921c), CONST64(0x59dba2a2b2a27910), CONST64(0xc9e9eaea8fea0365), CONST64(0xca6a656589650fec), CONST64(0x6903babad2bab968), CONST64(0x5e4a2f2fbc2f6593), CONST64(0x9d8ec0c027c04ee7), CONST64(0xa160dede5fdebe81), CONST64(0x38fc1c1c701ce06c), CONST64(0xe746fdfdd3fdbb2e), CONST64(0x9a1f4d4d294d5264), CONST64(0x397692927292e4e0), CONST64(0xeafa7575c9758fbc), CONST64(0x0c3606061806301e), CONST64(0x09ae8a8a128a2498), CONST64(0x794bb2b2f2b2f940), CONST64(0xd185e6e6bfe66359), CONST64(0x1c7e0e0e380e7036), CONST64(0x3ee71f1f7c1ff863), CONST64(0xc4556262956237f7), CONST64(0xb53ad4d477d4eea3), CONST64(0x4d81a8a89aa82932), CONST64(0x315296966296c4f4), CONST64(0xef62f9f9c3f99b3a), CONST64(0x97a3c5c533c566f6), CONST64(0x4a102525942535b1), CONST64(0xb2ab59597959f220), CONST64(0x15d084842a8454ae), CONST64(0xe4c57272d572b7a7), CONST64(0x72ec3939e439d5dd), CONST64(0x98164c4c2d4c5a61), CONST64(0xbc945e5e655eca3b), CONST64(0xf09f7878fd78e785), CONST64(0x70e53838e038ddd8), CONST64(0x05988c8c0a8c1486), CONST64(0xbf17d1d163d1c6b2), CONST64(0x57e4a5a5aea5410b), CONST64(0xd9a1e2e2afe2434d), CONST64(0xc24e616199612ff8), CONST64(0x7b42b3b3f6b3f145), CONST64(0x42342121842115a5), CONST64(0x25089c9c4a9c94d6), CONST64(0x3cee1e1e781ef066), CONST64(0x8661434311432252), CONST64(0x93b1c7c73bc776fc), CONST64(0xe54ffcfcd7fcb32b), CONST64(0x0824040410042014), CONST64(0xa2e351515951b208), CONST64(0x2f2599995e99bcc7), CONST64(0xda226d6da96d4fc4), CONST64(0x1a650d0d340d6839), CONST64(0xe979fafacffa8335), CONST64(0xa369dfdf5bdfb684), CONST64(0xfca97e7ee57ed79b), CONST64(0x4819242490243db4), CONST64(0x76fe3b3bec3bc5d7), CONST64(0x4b9aabab96ab313d), CONST64(0x81f0cece1fce3ed1), CONST64(0x2299111144118855), CONST64(0x03838f8f068f0c89), CONST64(0x9c044e4e254e4a6b), CONST64(0x7366b7b7e6b7d151), CONST64(0xcbe0ebeb8beb0b60), CONST64(0x78c13c3cf03cfdcc), CONST64(0x1ffd81813e817cbf), CONST64(0x354094946a94d4fe), CONST64(0xf31cf7f7fbf7eb0c), CONST64(0x6f18b9b9deb9a167), CONST64(0x268b13134c13985f), CONST64(0x58512c2cb02c7d9c), CONST64(0xbb05d3d36bd3d6b8), CONST64(0xd38ce7e7bbe76b5c), CONST64(0xdc396e6ea56e57cb), CONST64(0x95aac4c437c46ef3), CONST64(0x061b03030c03180f), CONST64(0xacdc565645568a13), CONST64(0x885e44440d441a49), CONST64(0xfea07f7fe17fdf9e), CONST64(0x4f88a9a99ea92137), CONST64(0x54672a2aa82a4d82), CONST64(0x6b0abbbbd6bbb16d), CONST64(0x9f87c1c123c146e2), CONST64(0xa6f153535153a202), CONST64(0xa572dcdc57dcae8b), CONST64(0x16530b0b2c0b5827), CONST64(0x27019d9d4e9d9cd3), CONST64(0xd82b6c6cad6c47c1), CONST64(0x62a43131c43195f5), CONST64(0xe8f37474cd7487b9), CONST64(0xf115f6f6fff6e309), CONST64(0x8c4c464605460a43), CONST64(0x45a5acac8aac0926), CONST64(0x0fb589891e893c97), CONST64(0x28b414145014a044), CONST64(0xdfbae1e1a3e15b42), CONST64(0x2ca616165816b04e), CONST64(0x74f73a3ae83acdd2), CONST64(0xd2066969b9696fd0), CONST64(0x124109092409482d), CONST64(0xe0d77070dd70a7ad), CONST64(0x716fb6b6e2b6d954), CONST64(0xbd1ed0d067d0ceb7), CONST64(0xc7d6eded93ed3b7e), CONST64(0x85e2cccc17cc2edb), CONST64(0x8468424215422a57), CONST64(0x2d2c98985a98b4c2), CONST64(0x55eda4a4aaa4490e), CONST64(0x50752828a0285d88), CONST64(0xb8865c5c6d5cda31), CONST64(0xed6bf8f8c7f8933f), CONST64(0x11c28686228644a4) }; static const ulong64 sbox3[] = { CONST64(0x7830d818186018c0), CONST64(0xaf462623238c2305), CONST64(0xf991b8c6c63fc67e), CONST64(0x6fcdfbe8e887e813), CONST64(0xa113cb878726874c), CONST64(0x626d11b8b8dab8a9), CONST64(0x0502090101040108), CONST64(0x6e9e0d4f4f214f42), CONST64(0xee6c9b3636d836ad), CONST64(0x0451ffa6a6a2a659), CONST64(0xbdb90cd2d26fd2de), CONST64(0x06f70ef5f5f3f5fb), CONST64(0x80f2967979f979ef), CONST64(0xcede306f6fa16f5f), CONST64(0xef3f6d91917e91fc), CONST64(0x07a4f852525552aa), CONST64(0xfdc04760609d6027), CONST64(0x766535bcbccabc89), CONST64(0xcd2b379b9b569bac), CONST64(0x8c018a8e8e028e04), CONST64(0x155bd2a3a3b6a371), CONST64(0x3c186c0c0c300c60), CONST64(0x8af6847b7bf17bff), CONST64(0xe16a803535d435b5), CONST64(0x693af51d1d741de8), CONST64(0x47ddb3e0e0a7e053), CONST64(0xacb321d7d77bd7f6), CONST64(0xed999cc2c22fc25e), CONST64(0x965c432e2eb82e6d), CONST64(0x7a96294b4b314b62), CONST64(0x21e15dfefedffea3), CONST64(0x16aed55757415782), CONST64(0x412abd15155415a8), CONST64(0xb6eee87777c1779f), CONST64(0xeb6e923737dc37a5), CONST64(0x56d79ee5e5b3e57b), CONST64(0xd923139f9f469f8c), CONST64(0x17fd23f0f0e7f0d3), CONST64(0x7f94204a4a354a6a), CONST64(0x95a944dada4fda9e), CONST64(0x25b0a258587d58fa), CONST64(0xca8fcfc9c903c906), CONST64(0x8d527c2929a42955), CONST64(0x22145a0a0a280a50), CONST64(0x4f7f50b1b1feb1e1), CONST64(0x1a5dc9a0a0baa069), CONST64(0xdad6146b6bb16b7f), CONST64(0xab17d985852e855c), CONST64(0x73673cbdbdcebd81), CONST64(0x34ba8f5d5d695dd2), CONST64(0x5020901010401080), CONST64(0x03f507f4f4f7f4f3), CONST64(0xc08bddcbcb0bcb16), CONST64(0xc67cd33e3ef83eed), CONST64(0x110a2d0505140528), CONST64(0xe6ce78676781671f), CONST64(0x53d597e4e4b7e473), CONST64(0xbb4e0227279c2725), CONST64(0x5882734141194132), CONST64(0x9d0ba78b8b168b2c), CONST64(0x0153f6a7a7a6a751), CONST64(0x94fab27d7de97dcf), CONST64(0xfb374995956e95dc), CONST64(0x9fad56d8d847d88e), CONST64(0x30eb70fbfbcbfb8b), CONST64(0x71c1cdeeee9fee23), CONST64(0x91f8bb7c7ced7cc7), CONST64(0xe3cc716666856617), CONST64(0x8ea77bdddd53dda6), CONST64(0x4b2eaf17175c17b8), CONST64(0x468e454747014702), CONST64(0xdc211a9e9e429e84), CONST64(0xc589d4caca0fca1e), CONST64(0x995a582d2db42d75), CONST64(0x79632ebfbfc6bf91), CONST64(0x1b0e3f07071c0738), CONST64(0x2347acadad8ead01), CONST64(0x2fb4b05a5a755aea), CONST64(0xb51bef838336836c), CONST64(0xff66b63333cc3385), CONST64(0xf2c65c636391633f), CONST64(0x0a04120202080210), CONST64(0x384993aaaa92aa39), CONST64(0xa8e2de7171d971af), CONST64(0xcf8dc6c8c807c80e), CONST64(0x7d32d119196419c8), CONST64(0x70923b4949394972), CONST64(0x9aaf5fd9d943d986), CONST64(0x1df931f2f2eff2c3), CONST64(0x48dba8e3e3abe34b), CONST64(0x2ab6b95b5b715be2), CONST64(0x920dbc88881a8834), CONST64(0xc8293e9a9a529aa4), CONST64(0xbe4c0b262698262d), CONST64(0xfa64bf3232c8328d), CONST64(0x4a7d59b0b0fab0e9), CONST64(0x6acff2e9e983e91b), CONST64(0x331e770f0f3c0f78), CONST64(0xa6b733d5d573d5e6), CONST64(0xba1df480803a8074), CONST64(0x7c6127bebec2be99), CONST64(0xde87ebcdcd13cd26), CONST64(0xe468893434d034bd), CONST64(0x75903248483d487a), CONST64(0x24e354ffffdbffab), CONST64(0x8ff48d7a7af57af7), CONST64(0xea3d6490907a90f4), CONST64(0x3ebe9d5f5f615fc2), CONST64(0xa0403d202080201d), CONST64(0xd5d00f6868bd6867), CONST64(0x7234ca1a1a681ad0), CONST64(0x2c41b7aeae82ae19), CONST64(0x5e757db4b4eab4c9), CONST64(0x19a8ce54544d549a), CONST64(0xe53b7f93937693ec), CONST64(0xaa442f222288220d), CONST64(0xe9c86364648d6407), CONST64(0x12ff2af1f1e3f1db), CONST64(0xa2e6cc7373d173bf), CONST64(0x5a24821212481290), CONST64(0x5d807a40401d403a), CONST64(0x2810480808200840), CONST64(0xe89b95c3c32bc356), CONST64(0x7bc5dfecec97ec33), CONST64(0x90ab4ddbdb4bdb96), CONST64(0x1f5fc0a1a1bea161), CONST64(0x8307918d8d0e8d1c), CONST64(0xc97ac83d3df43df5), CONST64(0xf1335b97976697cc), CONST64(0x0000000000000000), CONST64(0xd483f9cfcf1bcf36), CONST64(0x87566e2b2bac2b45), CONST64(0xb3ece17676c57697), CONST64(0xb019e68282328264), CONST64(0xa9b128d6d67fd6fe), CONST64(0x7736c31b1b6c1bd8), CONST64(0x5b7774b5b5eeb5c1), CONST64(0x2943beafaf86af11), CONST64(0xdfd41d6a6ab56a77), CONST64(0x0da0ea50505d50ba), CONST64(0x4c8a574545094512), CONST64(0x18fb38f3f3ebf3cb), CONST64(0xf060ad3030c0309d), CONST64(0x74c3c4efef9bef2b), CONST64(0xc37eda3f3ffc3fe5), CONST64(0x1caac75555495592), CONST64(0x1059dba2a2b2a279), CONST64(0x65c9e9eaea8fea03), CONST64(0xecca6a656589650f), CONST64(0x686903babad2bab9), CONST64(0x935e4a2f2fbc2f65), CONST64(0xe79d8ec0c027c04e), CONST64(0x81a160dede5fdebe), CONST64(0x6c38fc1c1c701ce0), CONST64(0x2ee746fdfdd3fdbb), CONST64(0x649a1f4d4d294d52), CONST64(0xe0397692927292e4), CONST64(0xbceafa7575c9758f), CONST64(0x1e0c360606180630), CONST64(0x9809ae8a8a128a24), CONST64(0x40794bb2b2f2b2f9), CONST64(0x59d185e6e6bfe663), CONST64(0x361c7e0e0e380e70), CONST64(0x633ee71f1f7c1ff8), CONST64(0xf7c4556262956237), CONST64(0xa3b53ad4d477d4ee), CONST64(0x324d81a8a89aa829), CONST64(0xf4315296966296c4), CONST64(0x3aef62f9f9c3f99b), CONST64(0xf697a3c5c533c566), CONST64(0xb14a102525942535), CONST64(0x20b2ab59597959f2), CONST64(0xae15d084842a8454), CONST64(0xa7e4c57272d572b7), CONST64(0xdd72ec3939e439d5), CONST64(0x6198164c4c2d4c5a), CONST64(0x3bbc945e5e655eca), CONST64(0x85f09f7878fd78e7), CONST64(0xd870e53838e038dd), CONST64(0x8605988c8c0a8c14), CONST64(0xb2bf17d1d163d1c6), CONST64(0x0b57e4a5a5aea541), CONST64(0x4dd9a1e2e2afe243), CONST64(0xf8c24e616199612f), CONST64(0x457b42b3b3f6b3f1), CONST64(0xa542342121842115), CONST64(0xd625089c9c4a9c94), CONST64(0x663cee1e1e781ef0), CONST64(0x5286614343114322), CONST64(0xfc93b1c7c73bc776), CONST64(0x2be54ffcfcd7fcb3), CONST64(0x1408240404100420), CONST64(0x08a2e351515951b2), CONST64(0xc72f2599995e99bc), CONST64(0xc4da226d6da96d4f), CONST64(0x391a650d0d340d68), CONST64(0x35e979fafacffa83), CONST64(0x84a369dfdf5bdfb6), CONST64(0x9bfca97e7ee57ed7), CONST64(0xb44819242490243d), CONST64(0xd776fe3b3bec3bc5), CONST64(0x3d4b9aabab96ab31), CONST64(0xd181f0cece1fce3e), CONST64(0x5522991111441188), CONST64(0x8903838f8f068f0c), CONST64(0x6b9c044e4e254e4a), CONST64(0x517366b7b7e6b7d1), CONST64(0x60cbe0ebeb8beb0b), CONST64(0xcc78c13c3cf03cfd), CONST64(0xbf1ffd81813e817c), CONST64(0xfe354094946a94d4), CONST64(0x0cf31cf7f7fbf7eb), CONST64(0x676f18b9b9deb9a1), CONST64(0x5f268b13134c1398), CONST64(0x9c58512c2cb02c7d), CONST64(0xb8bb05d3d36bd3d6), CONST64(0x5cd38ce7e7bbe76b), CONST64(0xcbdc396e6ea56e57), CONST64(0xf395aac4c437c46e), CONST64(0x0f061b03030c0318), CONST64(0x13acdc565645568a), CONST64(0x49885e44440d441a), CONST64(0x9efea07f7fe17fdf), CONST64(0x374f88a9a99ea921), CONST64(0x8254672a2aa82a4d), CONST64(0x6d6b0abbbbd6bbb1), CONST64(0xe29f87c1c123c146), CONST64(0x02a6f153535153a2), CONST64(0x8ba572dcdc57dcae), CONST64(0x2716530b0b2c0b58), CONST64(0xd327019d9d4e9d9c), CONST64(0xc1d82b6c6cad6c47), CONST64(0xf562a43131c43195), CONST64(0xb9e8f37474cd7487), CONST64(0x09f115f6f6fff6e3), CONST64(0x438c4c464605460a), CONST64(0x2645a5acac8aac09), CONST64(0x970fb589891e893c), CONST64(0x4428b414145014a0), CONST64(0x42dfbae1e1a3e15b), CONST64(0x4e2ca616165816b0), CONST64(0xd274f73a3ae83acd), CONST64(0xd0d2066969b9696f), CONST64(0x2d12410909240948), CONST64(0xade0d77070dd70a7), CONST64(0x54716fb6b6e2b6d9), CONST64(0xb7bd1ed0d067d0ce), CONST64(0x7ec7d6eded93ed3b), CONST64(0xdb85e2cccc17cc2e), CONST64(0x578468424215422a), CONST64(0xc22d2c98985a98b4), CONST64(0x0e55eda4a4aaa449), CONST64(0x8850752828a0285d), CONST64(0x31b8865c5c6d5cda), CONST64(0x3fed6bf8f8c7f893), CONST64(0xa411c28686228644) }; static const ulong64 sbox4[] = { CONST64(0xc07830d818186018), CONST64(0x05af462623238c23), CONST64(0x7ef991b8c6c63fc6), CONST64(0x136fcdfbe8e887e8), CONST64(0x4ca113cb87872687), CONST64(0xa9626d11b8b8dab8), CONST64(0x0805020901010401), CONST64(0x426e9e0d4f4f214f), CONST64(0xadee6c9b3636d836), CONST64(0x590451ffa6a6a2a6), CONST64(0xdebdb90cd2d26fd2), CONST64(0xfb06f70ef5f5f3f5), CONST64(0xef80f2967979f979), CONST64(0x5fcede306f6fa16f), CONST64(0xfcef3f6d91917e91), CONST64(0xaa07a4f852525552), CONST64(0x27fdc04760609d60), CONST64(0x89766535bcbccabc), CONST64(0xaccd2b379b9b569b), CONST64(0x048c018a8e8e028e), CONST64(0x71155bd2a3a3b6a3), CONST64(0x603c186c0c0c300c), CONST64(0xff8af6847b7bf17b), CONST64(0xb5e16a803535d435), CONST64(0xe8693af51d1d741d), CONST64(0x5347ddb3e0e0a7e0), CONST64(0xf6acb321d7d77bd7), CONST64(0x5eed999cc2c22fc2), CONST64(0x6d965c432e2eb82e), CONST64(0x627a96294b4b314b), CONST64(0xa321e15dfefedffe), CONST64(0x8216aed557574157), CONST64(0xa8412abd15155415), CONST64(0x9fb6eee87777c177), CONST64(0xa5eb6e923737dc37), CONST64(0x7b56d79ee5e5b3e5), CONST64(0x8cd923139f9f469f), CONST64(0xd317fd23f0f0e7f0), CONST64(0x6a7f94204a4a354a), CONST64(0x9e95a944dada4fda), CONST64(0xfa25b0a258587d58), CONST64(0x06ca8fcfc9c903c9), CONST64(0x558d527c2929a429), CONST64(0x5022145a0a0a280a), CONST64(0xe14f7f50b1b1feb1), CONST64(0x691a5dc9a0a0baa0), CONST64(0x7fdad6146b6bb16b), CONST64(0x5cab17d985852e85), CONST64(0x8173673cbdbdcebd), CONST64(0xd234ba8f5d5d695d), CONST64(0x8050209010104010), CONST64(0xf303f507f4f4f7f4), CONST64(0x16c08bddcbcb0bcb), CONST64(0xedc67cd33e3ef83e), CONST64(0x28110a2d05051405), CONST64(0x1fe6ce7867678167), CONST64(0x7353d597e4e4b7e4), CONST64(0x25bb4e0227279c27), CONST64(0x3258827341411941), CONST64(0x2c9d0ba78b8b168b), CONST64(0x510153f6a7a7a6a7), CONST64(0xcf94fab27d7de97d), CONST64(0xdcfb374995956e95), CONST64(0x8e9fad56d8d847d8), CONST64(0x8b30eb70fbfbcbfb), CONST64(0x2371c1cdeeee9fee), CONST64(0xc791f8bb7c7ced7c), CONST64(0x17e3cc7166668566), CONST64(0xa68ea77bdddd53dd), CONST64(0xb84b2eaf17175c17), CONST64(0x02468e4547470147), CONST64(0x84dc211a9e9e429e), CONST64(0x1ec589d4caca0fca), CONST64(0x75995a582d2db42d), CONST64(0x9179632ebfbfc6bf), CONST64(0x381b0e3f07071c07), CONST64(0x012347acadad8ead), CONST64(0xea2fb4b05a5a755a), CONST64(0x6cb51bef83833683), CONST64(0x85ff66b63333cc33), CONST64(0x3ff2c65c63639163), CONST64(0x100a041202020802), CONST64(0x39384993aaaa92aa), CONST64(0xafa8e2de7171d971), CONST64(0x0ecf8dc6c8c807c8), CONST64(0xc87d32d119196419), CONST64(0x7270923b49493949), CONST64(0x869aaf5fd9d943d9), CONST64(0xc31df931f2f2eff2), CONST64(0x4b48dba8e3e3abe3), CONST64(0xe22ab6b95b5b715b), CONST64(0x34920dbc88881a88), CONST64(0xa4c8293e9a9a529a), CONST64(0x2dbe4c0b26269826), CONST64(0x8dfa64bf3232c832), CONST64(0xe94a7d59b0b0fab0), CONST64(0x1b6acff2e9e983e9), CONST64(0x78331e770f0f3c0f), CONST64(0xe6a6b733d5d573d5), CONST64(0x74ba1df480803a80), CONST64(0x997c6127bebec2be), CONST64(0x26de87ebcdcd13cd), CONST64(0xbde468893434d034), CONST64(0x7a75903248483d48), CONST64(0xab24e354ffffdbff), CONST64(0xf78ff48d7a7af57a), CONST64(0xf4ea3d6490907a90), CONST64(0xc23ebe9d5f5f615f), CONST64(0x1da0403d20208020), CONST64(0x67d5d00f6868bd68), CONST64(0xd07234ca1a1a681a), CONST64(0x192c41b7aeae82ae), CONST64(0xc95e757db4b4eab4), CONST64(0x9a19a8ce54544d54), CONST64(0xece53b7f93937693), CONST64(0x0daa442f22228822), CONST64(0x07e9c86364648d64), CONST64(0xdb12ff2af1f1e3f1), CONST64(0xbfa2e6cc7373d173), CONST64(0x905a248212124812), CONST64(0x3a5d807a40401d40), CONST64(0x4028104808082008), CONST64(0x56e89b95c3c32bc3), CONST64(0x337bc5dfecec97ec), CONST64(0x9690ab4ddbdb4bdb), CONST64(0x611f5fc0a1a1bea1), CONST64(0x1c8307918d8d0e8d), CONST64(0xf5c97ac83d3df43d), CONST64(0xccf1335b97976697), CONST64(0x0000000000000000), CONST64(0x36d483f9cfcf1bcf), CONST64(0x4587566e2b2bac2b), CONST64(0x97b3ece17676c576), CONST64(0x64b019e682823282), CONST64(0xfea9b128d6d67fd6), CONST64(0xd87736c31b1b6c1b), CONST64(0xc15b7774b5b5eeb5), CONST64(0x112943beafaf86af), CONST64(0x77dfd41d6a6ab56a), CONST64(0xba0da0ea50505d50), CONST64(0x124c8a5745450945), CONST64(0xcb18fb38f3f3ebf3), CONST64(0x9df060ad3030c030), CONST64(0x2b74c3c4efef9bef), CONST64(0xe5c37eda3f3ffc3f), CONST64(0x921caac755554955), CONST64(0x791059dba2a2b2a2), CONST64(0x0365c9e9eaea8fea), CONST64(0x0fecca6a65658965), CONST64(0xb9686903babad2ba), CONST64(0x65935e4a2f2fbc2f), CONST64(0x4ee79d8ec0c027c0), CONST64(0xbe81a160dede5fde), CONST64(0xe06c38fc1c1c701c), CONST64(0xbb2ee746fdfdd3fd), CONST64(0x52649a1f4d4d294d), CONST64(0xe4e0397692927292), CONST64(0x8fbceafa7575c975), CONST64(0x301e0c3606061806), CONST64(0x249809ae8a8a128a), CONST64(0xf940794bb2b2f2b2), CONST64(0x6359d185e6e6bfe6), CONST64(0x70361c7e0e0e380e), CONST64(0xf8633ee71f1f7c1f), CONST64(0x37f7c45562629562), CONST64(0xeea3b53ad4d477d4), CONST64(0x29324d81a8a89aa8), CONST64(0xc4f4315296966296), CONST64(0x9b3aef62f9f9c3f9), CONST64(0x66f697a3c5c533c5), CONST64(0x35b14a1025259425), CONST64(0xf220b2ab59597959), CONST64(0x54ae15d084842a84), CONST64(0xb7a7e4c57272d572), CONST64(0xd5dd72ec3939e439), CONST64(0x5a6198164c4c2d4c), CONST64(0xca3bbc945e5e655e), CONST64(0xe785f09f7878fd78), CONST64(0xddd870e53838e038), CONST64(0x148605988c8c0a8c), CONST64(0xc6b2bf17d1d163d1), CONST64(0x410b57e4a5a5aea5), CONST64(0x434dd9a1e2e2afe2), CONST64(0x2ff8c24e61619961), CONST64(0xf1457b42b3b3f6b3), CONST64(0x15a5423421218421), CONST64(0x94d625089c9c4a9c), CONST64(0xf0663cee1e1e781e), CONST64(0x2252866143431143), CONST64(0x76fc93b1c7c73bc7), CONST64(0xb32be54ffcfcd7fc), CONST64(0x2014082404041004), CONST64(0xb208a2e351515951), CONST64(0xbcc72f2599995e99), CONST64(0x4fc4da226d6da96d), CONST64(0x68391a650d0d340d), CONST64(0x8335e979fafacffa), CONST64(0xb684a369dfdf5bdf), CONST64(0xd79bfca97e7ee57e), CONST64(0x3db4481924249024), CONST64(0xc5d776fe3b3bec3b), CONST64(0x313d4b9aabab96ab), CONST64(0x3ed181f0cece1fce), CONST64(0x8855229911114411), CONST64(0x0c8903838f8f068f), CONST64(0x4a6b9c044e4e254e), CONST64(0xd1517366b7b7e6b7), CONST64(0x0b60cbe0ebeb8beb), CONST64(0xfdcc78c13c3cf03c), CONST64(0x7cbf1ffd81813e81), CONST64(0xd4fe354094946a94), CONST64(0xeb0cf31cf7f7fbf7), CONST64(0xa1676f18b9b9deb9), CONST64(0x985f268b13134c13), CONST64(0x7d9c58512c2cb02c), CONST64(0xd6b8bb05d3d36bd3), CONST64(0x6b5cd38ce7e7bbe7), CONST64(0x57cbdc396e6ea56e), CONST64(0x6ef395aac4c437c4), CONST64(0x180f061b03030c03), CONST64(0x8a13acdc56564556), CONST64(0x1a49885e44440d44), CONST64(0xdf9efea07f7fe17f), CONST64(0x21374f88a9a99ea9), CONST64(0x4d8254672a2aa82a), CONST64(0xb16d6b0abbbbd6bb), CONST64(0x46e29f87c1c123c1), CONST64(0xa202a6f153535153), CONST64(0xae8ba572dcdc57dc), CONST64(0x582716530b0b2c0b), CONST64(0x9cd327019d9d4e9d), CONST64(0x47c1d82b6c6cad6c), CONST64(0x95f562a43131c431), CONST64(0x87b9e8f37474cd74), CONST64(0xe309f115f6f6fff6), CONST64(0x0a438c4c46460546), CONST64(0x092645a5acac8aac), CONST64(0x3c970fb589891e89), CONST64(0xa04428b414145014), CONST64(0x5b42dfbae1e1a3e1), CONST64(0xb04e2ca616165816), CONST64(0xcdd274f73a3ae83a), CONST64(0x6fd0d2066969b969), CONST64(0x482d124109092409), CONST64(0xa7ade0d77070dd70), CONST64(0xd954716fb6b6e2b6), CONST64(0xceb7bd1ed0d067d0), CONST64(0x3b7ec7d6eded93ed), CONST64(0x2edb85e2cccc17cc), CONST64(0x2a57846842421542), CONST64(0xb4c22d2c98985a98), CONST64(0x490e55eda4a4aaa4), CONST64(0x5d8850752828a028), CONST64(0xda31b8865c5c6d5c), CONST64(0x933fed6bf8f8c7f8), CONST64(0x44a411c286862286) }; static const ulong64 sbox5[] = { CONST64(0x18c07830d8181860), CONST64(0x2305af462623238c), CONST64(0xc67ef991b8c6c63f), CONST64(0xe8136fcdfbe8e887), CONST64(0x874ca113cb878726), CONST64(0xb8a9626d11b8b8da), CONST64(0x0108050209010104), CONST64(0x4f426e9e0d4f4f21), CONST64(0x36adee6c9b3636d8), CONST64(0xa6590451ffa6a6a2), CONST64(0xd2debdb90cd2d26f), CONST64(0xf5fb06f70ef5f5f3), CONST64(0x79ef80f2967979f9), CONST64(0x6f5fcede306f6fa1), CONST64(0x91fcef3f6d91917e), CONST64(0x52aa07a4f8525255), CONST64(0x6027fdc04760609d), CONST64(0xbc89766535bcbcca), CONST64(0x9baccd2b379b9b56), CONST64(0x8e048c018a8e8e02), CONST64(0xa371155bd2a3a3b6), CONST64(0x0c603c186c0c0c30), CONST64(0x7bff8af6847b7bf1), CONST64(0x35b5e16a803535d4), CONST64(0x1de8693af51d1d74), CONST64(0xe05347ddb3e0e0a7), CONST64(0xd7f6acb321d7d77b), CONST64(0xc25eed999cc2c22f), CONST64(0x2e6d965c432e2eb8), CONST64(0x4b627a96294b4b31), CONST64(0xfea321e15dfefedf), CONST64(0x578216aed5575741), CONST64(0x15a8412abd151554), CONST64(0x779fb6eee87777c1), CONST64(0x37a5eb6e923737dc), CONST64(0xe57b56d79ee5e5b3), CONST64(0x9f8cd923139f9f46), CONST64(0xf0d317fd23f0f0e7), CONST64(0x4a6a7f94204a4a35), CONST64(0xda9e95a944dada4f), CONST64(0x58fa25b0a258587d), CONST64(0xc906ca8fcfc9c903), CONST64(0x29558d527c2929a4), CONST64(0x0a5022145a0a0a28), CONST64(0xb1e14f7f50b1b1fe), CONST64(0xa0691a5dc9a0a0ba), CONST64(0x6b7fdad6146b6bb1), CONST64(0x855cab17d985852e), CONST64(0xbd8173673cbdbdce), CONST64(0x5dd234ba8f5d5d69), CONST64(0x1080502090101040), CONST64(0xf4f303f507f4f4f7), CONST64(0xcb16c08bddcbcb0b), CONST64(0x3eedc67cd33e3ef8), CONST64(0x0528110a2d050514), CONST64(0x671fe6ce78676781), CONST64(0xe47353d597e4e4b7), CONST64(0x2725bb4e0227279c), CONST64(0x4132588273414119), CONST64(0x8b2c9d0ba78b8b16), CONST64(0xa7510153f6a7a7a6), CONST64(0x7dcf94fab27d7de9), CONST64(0x95dcfb374995956e), CONST64(0xd88e9fad56d8d847), CONST64(0xfb8b30eb70fbfbcb), CONST64(0xee2371c1cdeeee9f), CONST64(0x7cc791f8bb7c7ced), CONST64(0x6617e3cc71666685), CONST64(0xdda68ea77bdddd53), CONST64(0x17b84b2eaf17175c), CONST64(0x4702468e45474701), CONST64(0x9e84dc211a9e9e42), CONST64(0xca1ec589d4caca0f), CONST64(0x2d75995a582d2db4), CONST64(0xbf9179632ebfbfc6), CONST64(0x07381b0e3f07071c), CONST64(0xad012347acadad8e), CONST64(0x5aea2fb4b05a5a75), CONST64(0x836cb51bef838336), CONST64(0x3385ff66b63333cc), CONST64(0x633ff2c65c636391), CONST64(0x02100a0412020208), CONST64(0xaa39384993aaaa92), CONST64(0x71afa8e2de7171d9), CONST64(0xc80ecf8dc6c8c807), CONST64(0x19c87d32d1191964), CONST64(0x497270923b494939), CONST64(0xd9869aaf5fd9d943), CONST64(0xf2c31df931f2f2ef), CONST64(0xe34b48dba8e3e3ab), CONST64(0x5be22ab6b95b5b71), CONST64(0x8834920dbc88881a), CONST64(0x9aa4c8293e9a9a52), CONST64(0x262dbe4c0b262698), CONST64(0x328dfa64bf3232c8), CONST64(0xb0e94a7d59b0b0fa), CONST64(0xe91b6acff2e9e983), CONST64(0x0f78331e770f0f3c), CONST64(0xd5e6a6b733d5d573), CONST64(0x8074ba1df480803a), CONST64(0xbe997c6127bebec2), CONST64(0xcd26de87ebcdcd13), CONST64(0x34bde468893434d0), CONST64(0x487a75903248483d), CONST64(0xffab24e354ffffdb), CONST64(0x7af78ff48d7a7af5), CONST64(0x90f4ea3d6490907a), CONST64(0x5fc23ebe9d5f5f61), CONST64(0x201da0403d202080), CONST64(0x6867d5d00f6868bd), CONST64(0x1ad07234ca1a1a68), CONST64(0xae192c41b7aeae82), CONST64(0xb4c95e757db4b4ea), CONST64(0x549a19a8ce54544d), CONST64(0x93ece53b7f939376), CONST64(0x220daa442f222288), CONST64(0x6407e9c86364648d), CONST64(0xf1db12ff2af1f1e3), CONST64(0x73bfa2e6cc7373d1), CONST64(0x12905a2482121248), CONST64(0x403a5d807a40401d), CONST64(0x0840281048080820), CONST64(0xc356e89b95c3c32b), CONST64(0xec337bc5dfecec97), CONST64(0xdb9690ab4ddbdb4b), CONST64(0xa1611f5fc0a1a1be), CONST64(0x8d1c8307918d8d0e), CONST64(0x3df5c97ac83d3df4), CONST64(0x97ccf1335b979766), CONST64(0x0000000000000000), CONST64(0xcf36d483f9cfcf1b), CONST64(0x2b4587566e2b2bac), CONST64(0x7697b3ece17676c5), CONST64(0x8264b019e6828232), CONST64(0xd6fea9b128d6d67f), CONST64(0x1bd87736c31b1b6c), CONST64(0xb5c15b7774b5b5ee), CONST64(0xaf112943beafaf86), CONST64(0x6a77dfd41d6a6ab5), CONST64(0x50ba0da0ea50505d), CONST64(0x45124c8a57454509), CONST64(0xf3cb18fb38f3f3eb), CONST64(0x309df060ad3030c0), CONST64(0xef2b74c3c4efef9b), CONST64(0x3fe5c37eda3f3ffc), CONST64(0x55921caac7555549), CONST64(0xa2791059dba2a2b2), CONST64(0xea0365c9e9eaea8f), CONST64(0x650fecca6a656589), CONST64(0xbab9686903babad2), CONST64(0x2f65935e4a2f2fbc), CONST64(0xc04ee79d8ec0c027), CONST64(0xdebe81a160dede5f), CONST64(0x1ce06c38fc1c1c70), CONST64(0xfdbb2ee746fdfdd3), CONST64(0x4d52649a1f4d4d29), CONST64(0x92e4e03976929272), CONST64(0x758fbceafa7575c9), CONST64(0x06301e0c36060618), CONST64(0x8a249809ae8a8a12), CONST64(0xb2f940794bb2b2f2), CONST64(0xe66359d185e6e6bf), CONST64(0x0e70361c7e0e0e38), CONST64(0x1ff8633ee71f1f7c), CONST64(0x6237f7c455626295), CONST64(0xd4eea3b53ad4d477), CONST64(0xa829324d81a8a89a), CONST64(0x96c4f43152969662), CONST64(0xf99b3aef62f9f9c3), CONST64(0xc566f697a3c5c533), CONST64(0x2535b14a10252594), CONST64(0x59f220b2ab595979), CONST64(0x8454ae15d084842a), CONST64(0x72b7a7e4c57272d5), CONST64(0x39d5dd72ec3939e4), CONST64(0x4c5a6198164c4c2d), CONST64(0x5eca3bbc945e5e65), CONST64(0x78e785f09f7878fd), CONST64(0x38ddd870e53838e0), CONST64(0x8c148605988c8c0a), CONST64(0xd1c6b2bf17d1d163), CONST64(0xa5410b57e4a5a5ae), CONST64(0xe2434dd9a1e2e2af), CONST64(0x612ff8c24e616199), CONST64(0xb3f1457b42b3b3f6), CONST64(0x2115a54234212184), CONST64(0x9c94d625089c9c4a), CONST64(0x1ef0663cee1e1e78), CONST64(0x4322528661434311), CONST64(0xc776fc93b1c7c73b), CONST64(0xfcb32be54ffcfcd7), CONST64(0x0420140824040410), CONST64(0x51b208a2e3515159), CONST64(0x99bcc72f2599995e), CONST64(0x6d4fc4da226d6da9), CONST64(0x0d68391a650d0d34), CONST64(0xfa8335e979fafacf), CONST64(0xdfb684a369dfdf5b), CONST64(0x7ed79bfca97e7ee5), CONST64(0x243db44819242490), CONST64(0x3bc5d776fe3b3bec), CONST64(0xab313d4b9aabab96), CONST64(0xce3ed181f0cece1f), CONST64(0x1188552299111144), CONST64(0x8f0c8903838f8f06), CONST64(0x4e4a6b9c044e4e25), CONST64(0xb7d1517366b7b7e6), CONST64(0xeb0b60cbe0ebeb8b), CONST64(0x3cfdcc78c13c3cf0), CONST64(0x817cbf1ffd81813e), CONST64(0x94d4fe354094946a), CONST64(0xf7eb0cf31cf7f7fb), CONST64(0xb9a1676f18b9b9de), CONST64(0x13985f268b13134c), CONST64(0x2c7d9c58512c2cb0), CONST64(0xd3d6b8bb05d3d36b), CONST64(0xe76b5cd38ce7e7bb), CONST64(0x6e57cbdc396e6ea5), CONST64(0xc46ef395aac4c437), CONST64(0x03180f061b03030c), CONST64(0x568a13acdc565645), CONST64(0x441a49885e44440d), CONST64(0x7fdf9efea07f7fe1), CONST64(0xa921374f88a9a99e), CONST64(0x2a4d8254672a2aa8), CONST64(0xbbb16d6b0abbbbd6), CONST64(0xc146e29f87c1c123), CONST64(0x53a202a6f1535351), CONST64(0xdcae8ba572dcdc57), CONST64(0x0b582716530b0b2c), CONST64(0x9d9cd327019d9d4e), CONST64(0x6c47c1d82b6c6cad), CONST64(0x3195f562a43131c4), CONST64(0x7487b9e8f37474cd), CONST64(0xf6e309f115f6f6ff), CONST64(0x460a438c4c464605), CONST64(0xac092645a5acac8a), CONST64(0x893c970fb589891e), CONST64(0x14a04428b4141450), CONST64(0xe15b42dfbae1e1a3), CONST64(0x16b04e2ca6161658), CONST64(0x3acdd274f73a3ae8), CONST64(0x696fd0d2066969b9), CONST64(0x09482d1241090924), CONST64(0x70a7ade0d77070dd), CONST64(0xb6d954716fb6b6e2), CONST64(0xd0ceb7bd1ed0d067), CONST64(0xed3b7ec7d6eded93), CONST64(0xcc2edb85e2cccc17), CONST64(0x422a578468424215), CONST64(0x98b4c22d2c98985a), CONST64(0xa4490e55eda4a4aa), CONST64(0x285d8850752828a0), CONST64(0x5cda31b8865c5c6d), CONST64(0xf8933fed6bf8f8c7), CONST64(0x8644a411c2868622) }; static const ulong64 sbox6[] = { CONST64(0x6018c07830d81818), CONST64(0x8c2305af46262323), CONST64(0x3fc67ef991b8c6c6), CONST64(0x87e8136fcdfbe8e8), CONST64(0x26874ca113cb8787), CONST64(0xdab8a9626d11b8b8), CONST64(0x0401080502090101), CONST64(0x214f426e9e0d4f4f), CONST64(0xd836adee6c9b3636), CONST64(0xa2a6590451ffa6a6), CONST64(0x6fd2debdb90cd2d2), CONST64(0xf3f5fb06f70ef5f5), CONST64(0xf979ef80f2967979), CONST64(0xa16f5fcede306f6f), CONST64(0x7e91fcef3f6d9191), CONST64(0x5552aa07a4f85252), CONST64(0x9d6027fdc0476060), CONST64(0xcabc89766535bcbc), CONST64(0x569baccd2b379b9b), CONST64(0x028e048c018a8e8e), CONST64(0xb6a371155bd2a3a3), CONST64(0x300c603c186c0c0c), CONST64(0xf17bff8af6847b7b), CONST64(0xd435b5e16a803535), CONST64(0x741de8693af51d1d), CONST64(0xa7e05347ddb3e0e0), CONST64(0x7bd7f6acb321d7d7), CONST64(0x2fc25eed999cc2c2), CONST64(0xb82e6d965c432e2e), CONST64(0x314b627a96294b4b), CONST64(0xdffea321e15dfefe), CONST64(0x41578216aed55757), CONST64(0x5415a8412abd1515), CONST64(0xc1779fb6eee87777), CONST64(0xdc37a5eb6e923737), CONST64(0xb3e57b56d79ee5e5), CONST64(0x469f8cd923139f9f), CONST64(0xe7f0d317fd23f0f0), CONST64(0x354a6a7f94204a4a), CONST64(0x4fda9e95a944dada), CONST64(0x7d58fa25b0a25858), CONST64(0x03c906ca8fcfc9c9), CONST64(0xa429558d527c2929), CONST64(0x280a5022145a0a0a), CONST64(0xfeb1e14f7f50b1b1), CONST64(0xbaa0691a5dc9a0a0), CONST64(0xb16b7fdad6146b6b), CONST64(0x2e855cab17d98585), CONST64(0xcebd8173673cbdbd), CONST64(0x695dd234ba8f5d5d), CONST64(0x4010805020901010), CONST64(0xf7f4f303f507f4f4), CONST64(0x0bcb16c08bddcbcb), CONST64(0xf83eedc67cd33e3e), CONST64(0x140528110a2d0505), CONST64(0x81671fe6ce786767), CONST64(0xb7e47353d597e4e4), CONST64(0x9c2725bb4e022727), CONST64(0x1941325882734141), CONST64(0x168b2c9d0ba78b8b), CONST64(0xa6a7510153f6a7a7), CONST64(0xe97dcf94fab27d7d), CONST64(0x6e95dcfb37499595), CONST64(0x47d88e9fad56d8d8), CONST64(0xcbfb8b30eb70fbfb), CONST64(0x9fee2371c1cdeeee), CONST64(0xed7cc791f8bb7c7c), CONST64(0x856617e3cc716666), CONST64(0x53dda68ea77bdddd), CONST64(0x5c17b84b2eaf1717), CONST64(0x014702468e454747), CONST64(0x429e84dc211a9e9e), CONST64(0x0fca1ec589d4caca), CONST64(0xb42d75995a582d2d), CONST64(0xc6bf9179632ebfbf), CONST64(0x1c07381b0e3f0707), CONST64(0x8ead012347acadad), CONST64(0x755aea2fb4b05a5a), CONST64(0x36836cb51bef8383), CONST64(0xcc3385ff66b63333), CONST64(0x91633ff2c65c6363), CONST64(0x0802100a04120202), CONST64(0x92aa39384993aaaa), CONST64(0xd971afa8e2de7171), CONST64(0x07c80ecf8dc6c8c8), CONST64(0x6419c87d32d11919), CONST64(0x39497270923b4949), CONST64(0x43d9869aaf5fd9d9), CONST64(0xeff2c31df931f2f2), CONST64(0xabe34b48dba8e3e3), CONST64(0x715be22ab6b95b5b), CONST64(0x1a8834920dbc8888), CONST64(0x529aa4c8293e9a9a), CONST64(0x98262dbe4c0b2626), CONST64(0xc8328dfa64bf3232), CONST64(0xfab0e94a7d59b0b0), CONST64(0x83e91b6acff2e9e9), CONST64(0x3c0f78331e770f0f), CONST64(0x73d5e6a6b733d5d5), CONST64(0x3a8074ba1df48080), CONST64(0xc2be997c6127bebe), CONST64(0x13cd26de87ebcdcd), CONST64(0xd034bde468893434), CONST64(0x3d487a7590324848), CONST64(0xdbffab24e354ffff), CONST64(0xf57af78ff48d7a7a), CONST64(0x7a90f4ea3d649090), CONST64(0x615fc23ebe9d5f5f), CONST64(0x80201da0403d2020), CONST64(0xbd6867d5d00f6868), CONST64(0x681ad07234ca1a1a), CONST64(0x82ae192c41b7aeae), CONST64(0xeab4c95e757db4b4), CONST64(0x4d549a19a8ce5454), CONST64(0x7693ece53b7f9393), CONST64(0x88220daa442f2222), CONST64(0x8d6407e9c8636464), CONST64(0xe3f1db12ff2af1f1), CONST64(0xd173bfa2e6cc7373), CONST64(0x4812905a24821212), CONST64(0x1d403a5d807a4040), CONST64(0x2008402810480808), CONST64(0x2bc356e89b95c3c3), CONST64(0x97ec337bc5dfecec), CONST64(0x4bdb9690ab4ddbdb), CONST64(0xbea1611f5fc0a1a1), CONST64(0x0e8d1c8307918d8d), CONST64(0xf43df5c97ac83d3d), CONST64(0x6697ccf1335b9797), CONST64(0x0000000000000000), CONST64(0x1bcf36d483f9cfcf), CONST64(0xac2b4587566e2b2b), CONST64(0xc57697b3ece17676), CONST64(0x328264b019e68282), CONST64(0x7fd6fea9b128d6d6), CONST64(0x6c1bd87736c31b1b), CONST64(0xeeb5c15b7774b5b5), CONST64(0x86af112943beafaf), CONST64(0xb56a77dfd41d6a6a), CONST64(0x5d50ba0da0ea5050), CONST64(0x0945124c8a574545), CONST64(0xebf3cb18fb38f3f3), CONST64(0xc0309df060ad3030), CONST64(0x9bef2b74c3c4efef), CONST64(0xfc3fe5c37eda3f3f), CONST64(0x4955921caac75555), CONST64(0xb2a2791059dba2a2), CONST64(0x8fea0365c9e9eaea), CONST64(0x89650fecca6a6565), CONST64(0xd2bab9686903baba), CONST64(0xbc2f65935e4a2f2f), CONST64(0x27c04ee79d8ec0c0), CONST64(0x5fdebe81a160dede), CONST64(0x701ce06c38fc1c1c), CONST64(0xd3fdbb2ee746fdfd), CONST64(0x294d52649a1f4d4d), CONST64(0x7292e4e039769292), CONST64(0xc9758fbceafa7575), CONST64(0x1806301e0c360606), CONST64(0x128a249809ae8a8a), CONST64(0xf2b2f940794bb2b2), CONST64(0xbfe66359d185e6e6), CONST64(0x380e70361c7e0e0e), CONST64(0x7c1ff8633ee71f1f), CONST64(0x956237f7c4556262), CONST64(0x77d4eea3b53ad4d4), CONST64(0x9aa829324d81a8a8), CONST64(0x6296c4f431529696), CONST64(0xc3f99b3aef62f9f9), CONST64(0x33c566f697a3c5c5), CONST64(0x942535b14a102525), CONST64(0x7959f220b2ab5959), CONST64(0x2a8454ae15d08484), CONST64(0xd572b7a7e4c57272), CONST64(0xe439d5dd72ec3939), CONST64(0x2d4c5a6198164c4c), CONST64(0x655eca3bbc945e5e), CONST64(0xfd78e785f09f7878), CONST64(0xe038ddd870e53838), CONST64(0x0a8c148605988c8c), CONST64(0x63d1c6b2bf17d1d1), CONST64(0xaea5410b57e4a5a5), CONST64(0xafe2434dd9a1e2e2), CONST64(0x99612ff8c24e6161), CONST64(0xf6b3f1457b42b3b3), CONST64(0x842115a542342121), CONST64(0x4a9c94d625089c9c), CONST64(0x781ef0663cee1e1e), CONST64(0x1143225286614343), CONST64(0x3bc776fc93b1c7c7), CONST64(0xd7fcb32be54ffcfc), CONST64(0x1004201408240404), CONST64(0x5951b208a2e35151), CONST64(0x5e99bcc72f259999), CONST64(0xa96d4fc4da226d6d), CONST64(0x340d68391a650d0d), CONST64(0xcffa8335e979fafa), CONST64(0x5bdfb684a369dfdf), CONST64(0xe57ed79bfca97e7e), CONST64(0x90243db448192424), CONST64(0xec3bc5d776fe3b3b), CONST64(0x96ab313d4b9aabab), CONST64(0x1fce3ed181f0cece), CONST64(0x4411885522991111), CONST64(0x068f0c8903838f8f), CONST64(0x254e4a6b9c044e4e), CONST64(0xe6b7d1517366b7b7), CONST64(0x8beb0b60cbe0ebeb), CONST64(0xf03cfdcc78c13c3c), CONST64(0x3e817cbf1ffd8181), CONST64(0x6a94d4fe35409494), CONST64(0xfbf7eb0cf31cf7f7), CONST64(0xdeb9a1676f18b9b9), CONST64(0x4c13985f268b1313), CONST64(0xb02c7d9c58512c2c), CONST64(0x6bd3d6b8bb05d3d3), CONST64(0xbbe76b5cd38ce7e7), CONST64(0xa56e57cbdc396e6e), CONST64(0x37c46ef395aac4c4), CONST64(0x0c03180f061b0303), CONST64(0x45568a13acdc5656), CONST64(0x0d441a49885e4444), CONST64(0xe17fdf9efea07f7f), CONST64(0x9ea921374f88a9a9), CONST64(0xa82a4d8254672a2a), CONST64(0xd6bbb16d6b0abbbb), CONST64(0x23c146e29f87c1c1), CONST64(0x5153a202a6f15353), CONST64(0x57dcae8ba572dcdc), CONST64(0x2c0b582716530b0b), CONST64(0x4e9d9cd327019d9d), CONST64(0xad6c47c1d82b6c6c), CONST64(0xc43195f562a43131), CONST64(0xcd7487b9e8f37474), CONST64(0xfff6e309f115f6f6), CONST64(0x05460a438c4c4646), CONST64(0x8aac092645a5acac), CONST64(0x1e893c970fb58989), CONST64(0x5014a04428b41414), CONST64(0xa3e15b42dfbae1e1), CONST64(0x5816b04e2ca61616), CONST64(0xe83acdd274f73a3a), CONST64(0xb9696fd0d2066969), CONST64(0x2409482d12410909), CONST64(0xdd70a7ade0d77070), CONST64(0xe2b6d954716fb6b6), CONST64(0x67d0ceb7bd1ed0d0), CONST64(0x93ed3b7ec7d6eded), CONST64(0x17cc2edb85e2cccc), CONST64(0x15422a5784684242), CONST64(0x5a98b4c22d2c9898), CONST64(0xaaa4490e55eda4a4), CONST64(0xa0285d8850752828), CONST64(0x6d5cda31b8865c5c), CONST64(0xc7f8933fed6bf8f8), CONST64(0x228644a411c28686) }; static const ulong64 sbox7[] = { CONST64(0x186018c07830d818), CONST64(0x238c2305af462623), CONST64(0xc63fc67ef991b8c6), CONST64(0xe887e8136fcdfbe8), CONST64(0x8726874ca113cb87), CONST64(0xb8dab8a9626d11b8), CONST64(0x0104010805020901), CONST64(0x4f214f426e9e0d4f), CONST64(0x36d836adee6c9b36), CONST64(0xa6a2a6590451ffa6), CONST64(0xd26fd2debdb90cd2), CONST64(0xf5f3f5fb06f70ef5), CONST64(0x79f979ef80f29679), CONST64(0x6fa16f5fcede306f), CONST64(0x917e91fcef3f6d91), CONST64(0x525552aa07a4f852), CONST64(0x609d6027fdc04760), CONST64(0xbccabc89766535bc), CONST64(0x9b569baccd2b379b), CONST64(0x8e028e048c018a8e), CONST64(0xa3b6a371155bd2a3), CONST64(0x0c300c603c186c0c), CONST64(0x7bf17bff8af6847b), CONST64(0x35d435b5e16a8035), CONST64(0x1d741de8693af51d), CONST64(0xe0a7e05347ddb3e0), CONST64(0xd77bd7f6acb321d7), CONST64(0xc22fc25eed999cc2), CONST64(0x2eb82e6d965c432e), CONST64(0x4b314b627a96294b), CONST64(0xfedffea321e15dfe), CONST64(0x5741578216aed557), CONST64(0x155415a8412abd15), CONST64(0x77c1779fb6eee877), CONST64(0x37dc37a5eb6e9237), CONST64(0xe5b3e57b56d79ee5), CONST64(0x9f469f8cd923139f), CONST64(0xf0e7f0d317fd23f0), CONST64(0x4a354a6a7f94204a), CONST64(0xda4fda9e95a944da), CONST64(0x587d58fa25b0a258), CONST64(0xc903c906ca8fcfc9), CONST64(0x29a429558d527c29), CONST64(0x0a280a5022145a0a), CONST64(0xb1feb1e14f7f50b1), CONST64(0xa0baa0691a5dc9a0), CONST64(0x6bb16b7fdad6146b), CONST64(0x852e855cab17d985), CONST64(0xbdcebd8173673cbd), CONST64(0x5d695dd234ba8f5d), CONST64(0x1040108050209010), CONST64(0xf4f7f4f303f507f4), CONST64(0xcb0bcb16c08bddcb), CONST64(0x3ef83eedc67cd33e), CONST64(0x05140528110a2d05), CONST64(0x6781671fe6ce7867), CONST64(0xe4b7e47353d597e4), CONST64(0x279c2725bb4e0227), CONST64(0x4119413258827341), CONST64(0x8b168b2c9d0ba78b), CONST64(0xa7a6a7510153f6a7), CONST64(0x7de97dcf94fab27d), CONST64(0x956e95dcfb374995), CONST64(0xd847d88e9fad56d8), CONST64(0xfbcbfb8b30eb70fb), CONST64(0xee9fee2371c1cdee), CONST64(0x7ced7cc791f8bb7c), CONST64(0x66856617e3cc7166), CONST64(0xdd53dda68ea77bdd), CONST64(0x175c17b84b2eaf17), CONST64(0x47014702468e4547), CONST64(0x9e429e84dc211a9e), CONST64(0xca0fca1ec589d4ca), CONST64(0x2db42d75995a582d), CONST64(0xbfc6bf9179632ebf), CONST64(0x071c07381b0e3f07), CONST64(0xad8ead012347acad), CONST64(0x5a755aea2fb4b05a), CONST64(0x8336836cb51bef83), CONST64(0x33cc3385ff66b633), CONST64(0x6391633ff2c65c63), CONST64(0x020802100a041202), CONST64(0xaa92aa39384993aa), CONST64(0x71d971afa8e2de71), CONST64(0xc807c80ecf8dc6c8), CONST64(0x196419c87d32d119), CONST64(0x4939497270923b49), CONST64(0xd943d9869aaf5fd9), CONST64(0xf2eff2c31df931f2), CONST64(0xe3abe34b48dba8e3), CONST64(0x5b715be22ab6b95b), CONST64(0x881a8834920dbc88), CONST64(0x9a529aa4c8293e9a), CONST64(0x2698262dbe4c0b26), CONST64(0x32c8328dfa64bf32), CONST64(0xb0fab0e94a7d59b0), CONST64(0xe983e91b6acff2e9), CONST64(0x0f3c0f78331e770f), CONST64(0xd573d5e6a6b733d5), CONST64(0x803a8074ba1df480), CONST64(0xbec2be997c6127be), CONST64(0xcd13cd26de87ebcd), CONST64(0x34d034bde4688934), CONST64(0x483d487a75903248), CONST64(0xffdbffab24e354ff), CONST64(0x7af57af78ff48d7a), CONST64(0x907a90f4ea3d6490), CONST64(0x5f615fc23ebe9d5f), CONST64(0x2080201da0403d20), CONST64(0x68bd6867d5d00f68), CONST64(0x1a681ad07234ca1a), CONST64(0xae82ae192c41b7ae), CONST64(0xb4eab4c95e757db4), CONST64(0x544d549a19a8ce54), CONST64(0x937693ece53b7f93), CONST64(0x2288220daa442f22), CONST64(0x648d6407e9c86364), CONST64(0xf1e3f1db12ff2af1), CONST64(0x73d173bfa2e6cc73), CONST64(0x124812905a248212), CONST64(0x401d403a5d807a40), CONST64(0x0820084028104808), CONST64(0xc32bc356e89b95c3), CONST64(0xec97ec337bc5dfec), CONST64(0xdb4bdb9690ab4ddb), CONST64(0xa1bea1611f5fc0a1), CONST64(0x8d0e8d1c8307918d), CONST64(0x3df43df5c97ac83d), CONST64(0x976697ccf1335b97), CONST64(0x0000000000000000), CONST64(0xcf1bcf36d483f9cf), CONST64(0x2bac2b4587566e2b), CONST64(0x76c57697b3ece176), CONST64(0x82328264b019e682), CONST64(0xd67fd6fea9b128d6), CONST64(0x1b6c1bd87736c31b), CONST64(0xb5eeb5c15b7774b5), CONST64(0xaf86af112943beaf), CONST64(0x6ab56a77dfd41d6a), CONST64(0x505d50ba0da0ea50), CONST64(0x450945124c8a5745), CONST64(0xf3ebf3cb18fb38f3), CONST64(0x30c0309df060ad30), CONST64(0xef9bef2b74c3c4ef), CONST64(0x3ffc3fe5c37eda3f), CONST64(0x554955921caac755), CONST64(0xa2b2a2791059dba2), CONST64(0xea8fea0365c9e9ea), CONST64(0x6589650fecca6a65), CONST64(0xbad2bab9686903ba), CONST64(0x2fbc2f65935e4a2f), CONST64(0xc027c04ee79d8ec0), CONST64(0xde5fdebe81a160de), CONST64(0x1c701ce06c38fc1c), CONST64(0xfdd3fdbb2ee746fd), CONST64(0x4d294d52649a1f4d), CONST64(0x927292e4e0397692), CONST64(0x75c9758fbceafa75), CONST64(0x061806301e0c3606), CONST64(0x8a128a249809ae8a), CONST64(0xb2f2b2f940794bb2), CONST64(0xe6bfe66359d185e6), CONST64(0x0e380e70361c7e0e), CONST64(0x1f7c1ff8633ee71f), CONST64(0x62956237f7c45562), CONST64(0xd477d4eea3b53ad4), CONST64(0xa89aa829324d81a8), CONST64(0x966296c4f4315296), CONST64(0xf9c3f99b3aef62f9), CONST64(0xc533c566f697a3c5), CONST64(0x25942535b14a1025), CONST64(0x597959f220b2ab59), CONST64(0x842a8454ae15d084), CONST64(0x72d572b7a7e4c572), CONST64(0x39e439d5dd72ec39), CONST64(0x4c2d4c5a6198164c), CONST64(0x5e655eca3bbc945e), CONST64(0x78fd78e785f09f78), CONST64(0x38e038ddd870e538), CONST64(0x8c0a8c148605988c), CONST64(0xd163d1c6b2bf17d1), CONST64(0xa5aea5410b57e4a5), CONST64(0xe2afe2434dd9a1e2), CONST64(0x6199612ff8c24e61), CONST64(0xb3f6b3f1457b42b3), CONST64(0x21842115a5423421), CONST64(0x9c4a9c94d625089c), CONST64(0x1e781ef0663cee1e), CONST64(0x4311432252866143), CONST64(0xc73bc776fc93b1c7), CONST64(0xfcd7fcb32be54ffc), CONST64(0x0410042014082404), CONST64(0x515951b208a2e351), CONST64(0x995e99bcc72f2599), CONST64(0x6da96d4fc4da226d), CONST64(0x0d340d68391a650d), CONST64(0xfacffa8335e979fa), CONST64(0xdf5bdfb684a369df), CONST64(0x7ee57ed79bfca97e), CONST64(0x2490243db4481924), CONST64(0x3bec3bc5d776fe3b), CONST64(0xab96ab313d4b9aab), CONST64(0xce1fce3ed181f0ce), CONST64(0x1144118855229911), CONST64(0x8f068f0c8903838f), CONST64(0x4e254e4a6b9c044e), CONST64(0xb7e6b7d1517366b7), CONST64(0xeb8beb0b60cbe0eb), CONST64(0x3cf03cfdcc78c13c), CONST64(0x813e817cbf1ffd81), CONST64(0x946a94d4fe354094), CONST64(0xf7fbf7eb0cf31cf7), CONST64(0xb9deb9a1676f18b9), CONST64(0x134c13985f268b13), CONST64(0x2cb02c7d9c58512c), CONST64(0xd36bd3d6b8bb05d3), CONST64(0xe7bbe76b5cd38ce7), CONST64(0x6ea56e57cbdc396e), CONST64(0xc437c46ef395aac4), CONST64(0x030c03180f061b03), CONST64(0x5645568a13acdc56), CONST64(0x440d441a49885e44), CONST64(0x7fe17fdf9efea07f), CONST64(0xa99ea921374f88a9), CONST64(0x2aa82a4d8254672a), CONST64(0xbbd6bbb16d6b0abb), CONST64(0xc123c146e29f87c1), CONST64(0x535153a202a6f153), CONST64(0xdc57dcae8ba572dc), CONST64(0x0b2c0b582716530b), CONST64(0x9d4e9d9cd327019d), CONST64(0x6cad6c47c1d82b6c), CONST64(0x31c43195f562a431), CONST64(0x74cd7487b9e8f374), CONST64(0xf6fff6e309f115f6), CONST64(0x4605460a438c4c46), CONST64(0xac8aac092645a5ac), CONST64(0x891e893c970fb589), CONST64(0x145014a04428b414), CONST64(0xe1a3e15b42dfbae1), CONST64(0x165816b04e2ca616), CONST64(0x3ae83acdd274f73a), CONST64(0x69b9696fd0d20669), CONST64(0x092409482d124109), CONST64(0x70dd70a7ade0d770), CONST64(0xb6e2b6d954716fb6), CONST64(0xd067d0ceb7bd1ed0), CONST64(0xed93ed3b7ec7d6ed), CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d2c98), CONST64(0xa4aaa4490e55eda4), CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286) }; #endif static const ulong64 cont[] = { CONST64(0x1823c6e887b8014f), CONST64(0x36a6d2f5796f9152), CONST64(0x60bc9b8ea30c7b35), CONST64(0x1de0d7c22e4bfe57), CONST64(0x157737e59ff04ada), CONST64(0x58c9290ab1a06b85), CONST64(0xbd5d10f4cb3e0567), CONST64(0xe427418ba77d95d8), CONST64(0xfbee7c66dd17479e), CONST64(0xca2dbf07ad5a8333), CONST64(0x6302aa71c81949d9), }; #endif /* LTC_WHIRLTAB_C */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/000077500000000000000000000000001464416617300216175ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt.h000066400000000000000000000052061464416617300236540ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #ifndef TOMCRYPT_H_ #define TOMCRYPT_H_ #include #include #include #include #include #include #include #include /* use configuration data */ #include "tomcrypt_custom.h" #ifdef __cplusplus extern "C" { #endif /* version */ #define CRYPT 0x0118 #define SCRYPT "1.18.2-develop" /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 144 #ifndef TAB_SIZE /* descriptor table size */ #define TAB_SIZE 48 #endif /* error codes [will be expanded in future releases] */ enum { CRYPT_OK=0, /* Result OK */ CRYPT_ERROR, /* Generic Error */ CRYPT_NOP, /* Not a failure but no operation was performed */ CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ CRYPT_INVALID_PACKET, /* Invalid input packet given */ CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ CRYPT_INVALID_HASH, /* Invalid hash specified */ CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ CRYPT_MEM, /* Out of memory */ CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ CRYPT_INVALID_ARG, /* Generic invalid argument */ CRYPT_FILE_NOTFOUND, /* File Not Found */ CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */ CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */ }; #include "tomcrypt_cfg.h" #include "tomcrypt_macros.h" #include "tomcrypt_cipher.h" #include "tomcrypt_hash.h" #include "tomcrypt_mac.h" #include "tomcrypt_prng.h" #include "tomcrypt_pk.h" #include "tomcrypt_math.h" #include "tomcrypt_misc.h" #include "tomcrypt_argchk.h" #include "tomcrypt_pkcs.h" #ifdef __cplusplus } #endif #endif /* TOMCRYPT_H_ */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_argchk.h000066400000000000000000000020501464416617300251650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* Defines the LTC_ARGCHK macro used within the library */ /* ARGTYPE is defined in tomcrypt_cfg.h */ /* ARGTYPE is per default defined to 0 */ #if ARGTYPE == 0 #include LTC_NORETURN void crypt_argchk(const char *v, const char *s, int d); #define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) #define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) #elif ARGTYPE == 1 /* fatal type of error */ #define LTC_ARGCHK(x) assert((x)) #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) #elif ARGTYPE == 2 #define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) #elif ARGTYPE == 3 #define LTC_ARGCHK(x) LTC_UNUSED_PARAM(x) #define LTC_ARGCHKVD(x) LTC_ARGCHK(x) #elif ARGTYPE == 4 #define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; #define LTC_ARGCHKVD(x) if (!(x)) return; #endif optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_arm_neon.h000066400000000000000000000010121464416617300255210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #ifndef TOMCRYPT_ARM_NEON_H #define TOMCRYPT_ARM_NEON_H #include struct tomcrypt_arm_neon_state { ulong32 state; }; /* Temporarily enables neon instructions */ void tomcrypt_arm_neon_enable(struct tomcrypt_arm_neon_state *state); /* Disables neon instructions after a call to tomcrypt_arm_neon_enable() */ void tomcrypt_arm_neon_disable(struct tomcrypt_arm_neon_state *state); #endif /*TOMCRYPT_ARM_NEON_H*/ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h000066400000000000000000000253751464416617300245040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* This is the build config file. * * With this you can setup what to include/exclude automatically during any build. Just comment * out the line that #define's the word for the thing you want to remove. phew! */ #ifndef TOMCRYPT_CFG_H #define TOMCRYPT_CFG_H #if defined(_WIN32) || defined(_MSC_VER) #define LTC_CALL __cdecl #elif !defined(LTC_CALL) #define LTC_CALL #endif #ifndef LTC_EXPORT #define LTC_EXPORT #endif /* certain platforms use macros for these, making the prototypes broken */ #ifndef LTC_NO_PROTOTYPES /* you can change how memory allocation works ... */ LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); LTC_EXPORT void LTC_CALL XFREE(void *p); LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); /* change the clock function too */ LTC_EXPORT clock_t LTC_CALL XCLOCK(void); /* various other functions */ LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); #endif /* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */ #if defined(__GNUC__) || defined(__xlc__) #define LTC_INLINE __inline__ #elif defined(_MSC_VER) || defined(__HP_cc) #define LTC_INLINE __inline #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define LTC_INLINE inline #else #define LTC_INLINE #endif #if defined(__clang__) || defined(__GNUC_MINOR__) #define LTC_NORETURN __attribute__ ((noreturn)) #elif defined(_MSC_VER) #define LTC_NORETURN __declspec(noreturn) #else #define LTC_NORETURN #endif /* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ #ifndef ARGTYPE #define ARGTYPE 0 #endif #undef LTC_ENCRYPT #define LTC_ENCRYPT 0 #undef LTC_DECRYPT #define LTC_DECRYPT 1 /* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code * * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** * use the portable [slower] macros. */ /* detect x86/i386/ARM 32bit */ #if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_ARM) #define ENDIAN_LITTLE #define ENDIAN_32BITWORD #define LTC_FAST #endif /* detect amd64/x64/arm64 */ #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64) #define ENDIAN_LITTLE #define ENDIAN_64BITWORD #define LTC_FAST #if defined(__SSE4_1__) #if __SSE4_1__ == 1 #define LTC_AMD64_SSE4_1 #endif #endif #endif /* detect PPC32 */ #if defined(LTC_PPC32) #define ENDIAN_BIG #define ENDIAN_32BITWORD #define LTC_FAST #endif /* detects MIPS R5900 processors (PS2) */ #if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) #define ENDIAN_64BITWORD #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) #define ENDIAN_BIG #else #define ENDIAN_LITTLE #endif #endif /* detect AIX */ #if defined(_AIX) && defined(_BIG_ENDIAN) #define ENDIAN_BIG #if defined(__LP64__) || defined(_ARCH_PPC64) #define ENDIAN_64BITWORD #else #define ENDIAN_32BITWORD #endif #endif /* detect HP-UX */ #if defined(__hpux) || defined(__hpux__) #define ENDIAN_BIG #if defined(__ia64) || defined(__ia64__) || defined(__LP64__) #define ENDIAN_64BITWORD #else #define ENDIAN_32BITWORD #endif #endif /* detect Apple OS X */ #if defined(__APPLE__) && defined(__MACH__) #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__) #define ENDIAN_LITTLE #else #define ENDIAN_BIG #endif #if defined(__LP64__) || defined(__x86_64__) #define ENDIAN_64BITWORD #else #define ENDIAN_32BITWORD #endif #endif /* detect SPARC and SPARC64 */ #if defined(__sparc__) || defined(__sparc) #define ENDIAN_BIG #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) #define ENDIAN_64BITWORD #else #define ENDIAN_32BITWORD #endif #endif /* detect IBM S390(x) */ #if defined(__s390x__) || defined(__s390__) #define ENDIAN_BIG #if defined(__s390x__) #define ENDIAN_64BITWORD #else #define ENDIAN_32BITWORD #endif #endif /* detect PPC64 */ #if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) #define ENDIAN_64BITWORD #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define ENDIAN_BIG #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define ENDIAN_LITTLE #endif #define LTC_FAST #endif /* endianness fallback */ #if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \ defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ defined(__BIG_ENDIAN__) || \ defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ defined(__m68k__) #define ENDIAN_BIG #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \ defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ defined(__LITTLE_ENDIAN__) || \ defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \ defined(_M_ARM) || defined(_M_ARM64) #define ENDIAN_LITTLE #else #error Cannot detect endianness #endif #endif /* ulong64: 64-bit data type */ #ifdef _MSC_VER #define CONST64(n) n ## ui64 typedef unsigned __int64 ulong64; typedef __int64 long64; #else #define CONST64(n) n ## uLL typedef unsigned long long ulong64; typedef long long long64; #endif /* ulong32: "32-bit at least" data type */ #if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ defined(__LP64__) || defined(_LP64) || defined(__64BIT__) || defined(_M_ARM64) typedef unsigned ulong32; #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) #define ENDIAN_64BITWORD #endif #else typedef unsigned long ulong32; #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) #define ENDIAN_32BITWORD #endif #endif #if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER) typedef unsigned long long ltc_mp_digit; #else typedef unsigned long ltc_mp_digit; #endif /* No asm is a quick way to disable anything "not portable" */ #ifdef LTC_NO_ASM #define ENDIAN_NEUTRAL #undef ENDIAN_32BITWORD #undef ENDIAN_64BITWORD #undef LTC_FAST #define LTC_NO_BSWAP #define LTC_NO_ROLC #define LTC_NO_ROTATE #endif /* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */ #if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__) #undef LTC_FAST #endif #ifdef LTC_FAST #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x)) #ifdef ENDIAN_64BITWORD typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE; #else typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE; #endif #endif #if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) #error You must specify a word size as well as endianess in tomcrypt_cfg.h #endif #if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) #define ENDIAN_NEUTRAL #endif #if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD)) #error Cannot be 32 and 64 bit words... #endif /* gcc 4.3 and up has a bswap builtin; detect it by gcc version. * clang also supports the bswap builtin, and although clang pretends * to be gcc (macro-wise, anyway), clang pretends to be a version * prior to gcc 4.3, so we can't detect bswap that way. Instead, * clang has a __has_builtin mechanism that can be used to check * for builtins: * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */ #ifndef __has_builtin #define __has_builtin(x) 0 #endif #if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \ ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \ (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64))) #define LTC_HAVE_BSWAP_BUILTIN #endif #if !defined(LTC_NO_ROTATE) && (__has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateright32)) #define LTC_HAVE_ROTATE_BUILTIN #endif #if defined(__GNUC__) #define LTC_ALIGN(n) __attribute__((aligned(n))) #else #define LTC_ALIGN(n) #endif /* Choose Windows Vista as minimum Version if we're compiling with at least VS2019 * This is done in order to test the bcrypt RNG and can still be overridden by the user. */ #if defined(_MSC_VER) && _MSC_VER >= 1920 # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0600 # endif # ifndef WINVER # define WINVER 0x0600 # endif #endif #if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && !defined(LTC_WIN32_BCRYPT) # define LTC_WIN32_BCRYPT #endif /* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code * before including `tomcrypt.h` to disable this functionality. */ #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK) # define LTC_NULL_TERMINATED __attribute__((sentinel)) #else # define LTC_NULL_TERMINATED #endif #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) # define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s))) # define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s) # define LTC_DEPRECATED_PRAGMA(s) PRIVATE_LTC_DEPRECATED_PRAGMA(GCC warning s) #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) # define LTC_DEPRECATED(s) __attribute__((deprecated)) # define LTC_DEPRECATED_PRAGMA(s) #elif defined(_MSC_VER) && _MSC_VER >= 1500 /* supported since Visual Studio 2008 */ # define LTC_DEPRECATED(s) __declspec(deprecated("replaced by " #s)) # define LTC_DEPRECATED_PRAGMA(s) __pragma(message(s)) #else # define LTC_DEPRECATED(s) # define LTC_DEPRECATED_PRAGMA(s) #endif #endif /* TOMCRYPT_CFG_H */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h000066400000000000000000001244441464416617300252140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* ---- SYMMETRIC KEY STUFF ----- * * We put each of the ciphers scheduled keys in their own structs then we put all of * the key formats in one union. This makes the function prototypes easier to use. */ #ifdef LTC_BLOWFISH struct blowfish_key { ulong32 S[4][256]; ulong32 K[18]; }; #endif #ifdef LTC_RC5 struct rc5_key { int rounds; ulong32 K[50]; }; #endif #ifdef LTC_RC6 struct rc6_key { ulong32 K[44]; }; #endif #ifdef LTC_SAFERP struct saferp_key { unsigned char K[33][16]; long rounds; }; #endif #ifdef LTC_RIJNDAEL struct rijndael_key { unsigned char K[(60 + 60 + 4) * sizeof(ulong32)]; ulong32 *eK; ulong32 *dK; int Nr; }; #endif #ifdef LTC_KSEED struct kseed_key { ulong32 K[32], dK[32]; }; #endif #ifdef LTC_KASUMI struct kasumi_key { ulong32 KLi1[8], KLi2[8], KOi1[8], KOi2[8], KOi3[8], KIi1[8], KIi2[8], KIi3[8]; }; #endif #ifdef LTC_XTEA struct xtea_key { unsigned long A[32], B[32]; }; #endif #ifdef LTC_TWOFISH #ifndef LTC_TWOFISH_SMALL struct twofish_key { ulong32 S[4][256], K[40]; }; #else struct twofish_key { ulong32 K[40]; unsigned char S[32], start; }; #endif #endif #ifdef LTC_SAFER #define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6 #define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10 #define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8 #define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10 #define LTC_SAFER_MAX_NOF_ROUNDS 13 #define LTC_SAFER_BLOCK_LEN 8 #define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS)) typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN]; typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN]; struct safer_key { safer_key_t key; }; #endif #ifdef LTC_RC2 struct rc2_key { unsigned xkey[64]; }; #endif #ifdef LTC_DES struct des_key { ulong32 ek[32], dk[32]; }; struct des3_key { ulong32 ek[3][32], dk[3][32]; }; #endif #ifdef LTC_CAST5 struct cast5_key { ulong32 K[32], keylen; }; #endif #ifdef LTC_NOEKEON struct noekeon_key { ulong32 K[4], dK[4]; }; #endif #ifdef LTC_SKIPJACK struct skipjack_key { unsigned char key[10]; }; #endif #ifdef LTC_KHAZAD struct khazad_key { ulong64 roundKeyEnc[8 + 1]; ulong64 roundKeyDec[8 + 1]; }; #endif #ifdef LTC_ANUBIS struct anubis_key { ulong32 roundKeyEnc[18 + 1][4]; ulong32 roundKeyDec[18 + 1][4]; int keyBits; int R; }; #endif #ifdef LTC_MULTI2 struct multi2_key { ulong32 uk[8]; int N; }; #endif #ifdef LTC_CAMELLIA struct camellia_key { ulong64 kw[4], k[24], kl[6]; int R; }; #endif #ifdef LTC_IDEA /* rounds */ #define LTC_IDEA_ROUNDS 8 /* key schedule length in # of unsigned shorts */ #define LTC_IDEA_KEYLEN 6*LTC_IDEA_ROUNDS+4 struct idea_key { unsigned short int ek[LTC_IDEA_KEYLEN]; /* enc key */ unsigned short int dk[LTC_IDEA_KEYLEN]; /* dec key */ }; #endif #ifdef LTC_SERPENT struct serpent_key { ulong32 k[33*4]; }; #endif #ifdef LTC_TEA struct tea_key { ulong32 k[4]; }; #endif typedef union Symmetric_key { #ifdef LTC_DES struct des_key des; struct des3_key des3; #endif #ifdef LTC_RC2 struct rc2_key rc2; #endif #ifdef LTC_SAFER struct safer_key safer; #endif #ifdef LTC_TWOFISH struct twofish_key twofish; #endif #ifdef LTC_BLOWFISH struct blowfish_key blowfish; #endif #ifdef LTC_RC5 struct rc5_key rc5; #endif #ifdef LTC_RC6 struct rc6_key rc6; #endif #ifdef LTC_SAFERP struct saferp_key saferp; #endif #ifdef LTC_RIJNDAEL struct rijndael_key rijndael; #endif #ifdef LTC_XTEA struct xtea_key xtea; #endif #ifdef LTC_CAST5 struct cast5_key cast5; #endif #ifdef LTC_NOEKEON struct noekeon_key noekeon; #endif #ifdef LTC_SKIPJACK struct skipjack_key skipjack; #endif #ifdef LTC_KHAZAD struct khazad_key khazad; #endif #ifdef LTC_ANUBIS struct anubis_key anubis; #endif #ifdef LTC_KSEED struct kseed_key kseed; #endif #ifdef LTC_KASUMI struct kasumi_key kasumi; #endif #ifdef LTC_MULTI2 struct multi2_key multi2; #endif #ifdef LTC_CAMELLIA struct camellia_key camellia; #endif #ifdef LTC_IDEA struct idea_key idea; #endif #ifdef LTC_SERPENT struct serpent_key serpent; #endif #ifdef LTC_TEA struct tea_key tea; #endif void *data; } symmetric_key; #ifdef LTC_ECB_MODE /** A block cipher ECB structure */ typedef struct { /** The scheduled key */ symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen; } symmetric_ECB; #endif #ifdef LTC_CFB_MODE /** A block cipher CFB structure */ typedef struct { /** The current IV */ unsigned char IV[MAXBLOCKSIZE], /** The pad used to encrypt/decrypt */ pad[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen, /** The padding offset */ padlen; } symmetric_CFB; #endif #ifdef LTC_OFB_MODE /** A block cipher OFB structure */ typedef struct { /** The current IV */ unsigned char IV[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen, /** The padding offset */ padlen; } symmetric_OFB; #endif #ifdef LTC_CBC_MODE /** A block cipher CBC structure */ typedef struct { /** The current IV */ unsigned char IV[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen; } symmetric_CBC; #endif #ifdef LTC_CTR_MODE /** A block cipher CTR structure */ typedef struct { /** The counter */ unsigned char ctr[MAXBLOCKSIZE]; /** The pad used to encrypt/decrypt */ unsigned char pad[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen, /** The padding offset */ padlen, /** The mode (endianess) of the CTR, 0==little, 1==big */ mode, /** counter width */ ctrlen; } symmetric_CTR; #endif #ifdef LTC_LRW_MODE /** A LRW structure */ typedef struct { /** The current IV */ unsigned char IV[16], /** the tweak key */ tweak[16], /** The current pad, it's the product of the first 15 bytes against the tweak key */ pad[16]; /** The scheduled symmetric key */ symmetric_key key; #ifdef LTC_LRW_TABLES /** The pre-computed multiplication table */ unsigned char PC[16][256][16]; #endif /** The index of the cipher chosen (must be a 128-bit block cipher) */ int cipher; } symmetric_LRW; #endif #ifdef LTC_F8_MODE /** A block cipher F8 structure */ typedef struct { /** The current IV */ unsigned char IV[MAXBLOCKSIZE], MIV[MAXBLOCKSIZE]; /** The scheduled key */ symmetric_key key; /** The index of the cipher chosen */ int cipher, /** The block size of the given cipher */ blocklen, /** The padding offset */ padlen; /** Current block count */ ulong32 blockcnt; } symmetric_F8; #endif /** cipher descriptor table, last entry has "name == NULL" to mark the end of table */ extern const struct ltc_cipher_descriptor { /** name of cipher */ const char *name; /** internal ID */ unsigned char ID; /** min keysize (octets) */ int min_key_length, /** max keysize (octets) */ max_key_length, /** block size (octets) */ block_length, /** default number of rounds */ default_rounds; /** Setup the cipher @param key The input symmetric key @param keylen The length of the input key (octets) @param num_rounds The requested number of rounds (0==default) @param skey [out] The destination of the scheduled key @return CRYPT_OK if successful */ int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); /** Encrypt a block @param pt The plaintext @param ct [out] The ciphertext @param skey The scheduled key @return CRYPT_OK if successful */ int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); /** Decrypt a block @param ct The ciphertext @param pt [out] The plaintext @param skey The scheduled key @return CRYPT_OK if successful */ int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); /** Test the block cipher @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int (*test)(void); /** Terminate the context @param skey The scheduled key */ void (*done)(symmetric_key *skey); /** Determine a key size @param keysize [in/out] The size of the key desired and the suggested size @return CRYPT_OK if successful */ int (*keysize)(int *keysize); /** Accelerators **/ /** Accelerated ECB encryption @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, const symmetric_key *skey); /** Accelerated ECB decryption @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, const symmetric_key *skey); /** Accelerated CBC encryption @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param IV The initial value (input/output) @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey); /** Accelerated CBC decryption @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param IV The initial value (input/output) @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey); /** Accelerated CTR encryption @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param IV The initial value (input/output) @param mode little or big endian counter (mode=0 or mode=1) @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey); /** Accelerated LRW @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param IV The initial value (input/output) @param tweak The LRW tweak @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); /** Accelerated LRW @param ct Ciphertext @param pt Plaintext @param blocks The number of complete blocks to process @param IV The initial value (input/output) @param tweak The LRW tweak @param skey The scheduled key context @return CRYPT_OK if successful */ int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); /** Accelerated CCM packet (one-shot) @param key The secret key to use @param keylen The length of the secret key (octets) @param uskey A previously scheduled key [optional can be NULL] @param nonce The session nonce [use once] @param noncelen The length of the nonce @param header The header for the session @param headerlen The length of the header (octets) @param pt [out] The plaintext @param ptlen The length of the plaintext (octets) @param ct [out] The ciphertext @param tag [out] The destination tag @param taglen [in/out] The max size and resulting size of the authentication tag @param direction Encrypt or Decrypt direction (0 or 1) @return CRYPT_OK if successful */ int (*accel_ccm_memory)( const unsigned char *key, unsigned long keylen, symmetric_key *uskey, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction); /** Accelerated GCM packet (one shot) @param key The secret key @param keylen The length of the secret key @param IV The initialization vector @param IVlen The length of the initialization vector @param adata The additional authentication data (header) @param adatalen The length of the adata @param pt The plaintext @param ptlen The length of the plaintext (ciphertext length is the same) @param ct The ciphertext @param tag [out] The MAC tag @param taglen [in/out] The MAC tag length @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) @return CRYPT_OK on success */ int (*accel_gcm_memory)( const unsigned char *key, unsigned long keylen, const unsigned char *IV, unsigned long IVlen, const unsigned char *adata, unsigned long adatalen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction); /** Accelerated one shot LTC_OMAC @param key The secret key @param keylen The key length (octets) @param in The message @param inlen Length of message (octets) @param out [out] Destination for tag @param outlen [in/out] Initial and final size of out @return CRYPT_OK on success */ int (*omac_memory)( const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); /** Accelerated one shot XCBC @param key The secret key @param keylen The key length (octets) @param in The message @param inlen Length of message (octets) @param out [out] Destination for tag @param outlen [in/out] Initial and final size of out @return CRYPT_OK on success */ int (*xcbc_memory)( const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); /** Accelerated one shot F9 @param key The secret key @param keylen The key length (octets) @param in The message @param inlen Length of message (octets) @param out [out] Destination for tag @param outlen [in/out] Initial and final size of out @return CRYPT_OK on success @remark Requires manual padding */ int (*f9_memory)( const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); /** Accelerated XTS encryption @param pt Plaintext @param ct Ciphertext @param blocks The number of complete blocks to process @param tweak The 128-bit encryption tweak (input/output). The tweak should not be encrypted on input, but next tweak will be copied encrypted on output. @param skey1 The first scheduled key context @param skey2 The second scheduled key context @return CRYPT_OK if successful */ int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2); /** Accelerated XTS decryption @param ct Ciphertext @param pt Plaintext @param blocks The number of complete blocks to process @param tweak The 128-bit encryption tweak (input/output). The tweak should not be encrypted on input, but next tweak will be copied encrypted on output. @param skey1 The first scheduled key context @param skey2 The second scheduled key context @return CRYPT_OK if successful */ int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2); } *cipher_descriptor[]; #ifdef LTC_BLOWFISH int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int blowfish_test(void); void blowfish_done(symmetric_key *skey); int blowfish_keysize(int *keysize); extern const struct ltc_cipher_descriptor blowfish_desc; #endif #ifdef LTC_RC5 int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int rc5_test(void); void rc5_done(symmetric_key *skey); int rc5_keysize(int *keysize); extern const struct ltc_cipher_descriptor rc5_desc; #endif #ifdef LTC_RC6 int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int rc6_test(void); void rc6_done(symmetric_key *skey); int rc6_keysize(int *keysize); extern const struct ltc_cipher_descriptor rc6_desc; #endif #ifdef LTC_RC2 int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey); int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int rc2_test(void); void rc2_done(symmetric_key *skey); int rc2_keysize(int *keysize); extern const struct ltc_cipher_descriptor rc2_desc; #endif #ifdef LTC_SAFERP int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int saferp_test(void); void saferp_done(symmetric_key *skey); int saferp_keysize(int *keysize); extern const struct ltc_cipher_descriptor saferp_desc; #endif #ifdef LTC_SAFER int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int safer_k64_test(void); int safer_sk64_test(void); int safer_sk128_test(void); void safer_done(symmetric_key *skey); int safer_64_keysize(int *keysize); int safer_128_keysize(int *keysize); extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc; #endif #ifdef LTC_RIJNDAEL /* declare aes properly now */ int aes_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int aes_test(void); void aes_done(symmetric_key *skey); int aes_keysize(int *keysize); int aes_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int aes_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int aes_enc_test(void); void aes_enc_done(symmetric_key *skey); int aes_enc_keysize(int *keysize); extern const struct ltc_cipher_descriptor aes_desc; extern const struct ltc_cipher_descriptor aes_enc_desc; int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int rijndael_test(void); void rijndael_done(symmetric_key *skey); int rijndael_keysize(int *keysize); int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); void rijndael_enc_done(symmetric_key *skey); int rijndael_enc_keysize(int *keysize); extern const struct ltc_cipher_descriptor rijndael_desc; extern const struct ltc_cipher_descriptor rijndael_enc_desc; #endif #if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1) int aesni_is_supported(void); int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int aesni_test(void); void aesni_done(symmetric_key *skey); int aesni_keysize(int *keysize); extern const struct ltc_cipher_descriptor aesni_desc; #endif #ifdef LTC_XTEA int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int xtea_test(void); void xtea_done(symmetric_key *skey); int xtea_keysize(int *keysize); extern const struct ltc_cipher_descriptor xtea_desc; #endif #ifdef LTC_TWOFISH int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int twofish_test(void); void twofish_done(symmetric_key *skey); int twofish_keysize(int *keysize); extern const struct ltc_cipher_descriptor twofish_desc; #endif #ifdef LTC_DES int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int des_test(void); void des_done(symmetric_key *skey); int des_keysize(int *keysize); int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int des3_test(void); void des3_done(symmetric_key *skey); int des3_keysize(int *keysize); extern const struct ltc_cipher_descriptor des_desc, des3_desc; #endif #ifdef LTC_CAST5 int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int cast5_test(void); void cast5_done(symmetric_key *skey); int cast5_keysize(int *keysize); extern const struct ltc_cipher_descriptor cast5_desc; #endif #ifdef LTC_NOEKEON int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int noekeon_test(void); void noekeon_done(symmetric_key *skey); int noekeon_keysize(int *keysize); extern const struct ltc_cipher_descriptor noekeon_desc; #endif #ifdef LTC_SKIPJACK int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int skipjack_test(void); void skipjack_done(symmetric_key *skey); int skipjack_keysize(int *keysize); extern const struct ltc_cipher_descriptor skipjack_desc; #endif #ifdef LTC_KHAZAD int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int khazad_test(void); void khazad_done(symmetric_key *skey); int khazad_keysize(int *keysize); extern const struct ltc_cipher_descriptor khazad_desc; #endif #ifdef LTC_ANUBIS int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int anubis_test(void); void anubis_done(symmetric_key *skey); int anubis_keysize(int *keysize); extern const struct ltc_cipher_descriptor anubis_desc; #endif #ifdef LTC_KSEED int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int kseed_test(void); void kseed_done(symmetric_key *skey); int kseed_keysize(int *keysize); extern const struct ltc_cipher_descriptor kseed_desc; #endif #ifdef LTC_KASUMI int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int kasumi_test(void); void kasumi_done(symmetric_key *skey); int kasumi_keysize(int *keysize); extern const struct ltc_cipher_descriptor kasumi_desc; #endif #ifdef LTC_MULTI2 int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int multi2_test(void); void multi2_done(symmetric_key *skey); int multi2_keysize(int *keysize); extern const struct ltc_cipher_descriptor multi2_desc; #endif #ifdef LTC_CAMELLIA int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int camellia_test(void); void camellia_done(symmetric_key *skey); int camellia_keysize(int *keysize); extern const struct ltc_cipher_descriptor camellia_desc; #endif #ifdef LTC_IDEA int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int idea_test(void); void idea_done(symmetric_key *skey); int idea_keysize(int *keysize); extern const struct ltc_cipher_descriptor idea_desc; #endif #ifdef LTC_SERPENT int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int serpent_test(void); void serpent_done(symmetric_key *skey); int serpent_keysize(int *keysize); extern const struct ltc_cipher_descriptor serpent_desc; #endif #ifdef LTC_TEA int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); int tea_test(void); void tea_done(symmetric_key *skey); int tea_keysize(int *keysize); extern const struct ltc_cipher_descriptor tea_desc; #endif #ifdef LTC_ECB_MODE int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb); int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb); int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb); int ecb_done(symmetric_ECB *ecb); #endif #ifdef LTC_CFB_MODE int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_CFB *cfb); int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb); int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb); int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb); int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb); int cfb_done(symmetric_CFB *cfb); #endif #ifdef LTC_OFB_MODE int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_OFB *ofb); int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb); int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb); int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb); int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb); int ofb_done(symmetric_OFB *ofb); #endif #ifdef LTC_CBC_MODE int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_CBC *cbc); int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc); int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc); int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc); int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc); int cbc_done(symmetric_CBC *cbc); #endif #ifdef LTC_CTR_MODE #define CTR_COUNTER_LITTLE_ENDIAN 0x0000 #define CTR_COUNTER_BIG_ENDIAN 0x1000 #define LTC_CTR_RFC3686 0x2000 int ctr_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, int ctr_mode, symmetric_CTR *ctr); int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr); int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr); int ctr_done(symmetric_CTR *ctr); int ctr_test(void); #endif #ifdef LTC_LRW_MODE #define LRW_ENCRYPT LTC_ENCRYPT #define LRW_DECRYPT LTC_DECRYPT int lrw_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *tweak, int num_rounds, symmetric_LRW *lrw); int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw); int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw); int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw); int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw); int lrw_done(symmetric_LRW *lrw); int lrw_test(void); /* don't call */ int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw); #endif #ifdef LTC_F8_MODE int f8_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *salt_key, int skeylen, int num_rounds, symmetric_F8 *f8); int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8); int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8); int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8); int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8); int f8_done(symmetric_F8 *f8); int f8_test_mode(void); #endif #ifdef LTC_XTS_MODE typedef struct { symmetric_key key1, key2; int cipher; } symmetric_xts; int xts_start( int cipher, const unsigned char *key1, const unsigned char *key2, unsigned long keylen, int num_rounds, symmetric_xts *xts); int xts_encrypt( const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak, const symmetric_xts *xts); int xts_decrypt( const unsigned char *ct, unsigned long ptlen, unsigned char *pt, unsigned char *tweak, const symmetric_xts *xts); void xts_done(symmetric_xts *xts); int xts_test(void); void xts_mult_x(unsigned char *I); #endif int find_cipher(const char *name); int find_cipher_any(const char *name, int blocklen, int keylen); int find_cipher_id(unsigned char ID); int register_cipher(const struct ltc_cipher_descriptor *cipher); int unregister_cipher(const struct ltc_cipher_descriptor *cipher); int register_all_ciphers(void); int cipher_is_valid(int idx); LTC_MUTEX_PROTO(ltc_cipher_mutex) /* ---- stream ciphers ---- */ #ifdef LTC_CHACHA typedef struct { ulong32 input[16]; unsigned char kstream[64]; unsigned long ksleft; unsigned long ivlen; int rounds; } chacha_state; int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds); int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter); int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen); int chacha_done(chacha_state *st); int chacha_test(void); int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, const unsigned char *iv, unsigned long ivlen, ulong64 counter, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_CHACHA */ #ifdef LTC_SALSA20 typedef struct { ulong32 input[16]; unsigned char kstream[64]; unsigned long ksleft; unsigned long ivlen; int rounds; } salsa20_state; int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds); int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen); int salsa20_done(salsa20_state *st); int salsa20_test(void); int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, const unsigned char *iv, unsigned long ivlen, ulong64 counter, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_SALSA20 */ #ifdef LTC_XSALSA20 int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, int rounds); int xsalsa20_test(void); int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, const unsigned char *nonce, unsigned long noncelen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_XSALSA20 */ #ifdef LTC_SOSEMANUK typedef struct { ulong32 kc[100]; /* key_context */ ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09; ulong32 r1, r2; /* * Buffering: the stream cipher produces output data by * blocks of 640 bits. buf[] contains such a block, and * "ptr" is the index of the next output byte. */ unsigned char buf[80]; unsigned ptr; } sosemanuk_state; int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen); int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen); int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen); int sosemanuk_done(sosemanuk_state *st); int sosemanuk_test(void); int sosemanuk_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_SOSEMANUK */ #ifdef LTC_RABBIT typedef struct { ulong32 x[8]; ulong32 c[8]; ulong32 carry; } rabbit_ctx; typedef struct { rabbit_ctx master_ctx; rabbit_ctx work_ctx; unsigned char block[16]; /* last keystream block containing unused bytes */ ulong32 unused; /* count fm right */ } rabbit_state; int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen); int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen); int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out); int rabbit_keystream(rabbit_state* st, unsigned char *out, unsigned long outlen); int rabbit_done(rabbit_state *st); int rabbit_test(void); int rabbit_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_RABBIT */ #ifdef LTC_RC4_STREAM typedef struct { unsigned int x, y; unsigned char buf[256]; } rc4_state; int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen); int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen); int rc4_stream_done(rc4_state *st); int rc4_stream_test(void); int rc4_stream_memory(const unsigned char *key, unsigned long keylen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_RC4_STREAM */ #ifdef LTC_SOBER128_STREAM typedef struct { ulong32 R[17], /* Working storage for the shift register */ initR[17], /* saved register contents */ konst, /* key dependent constant */ sbuf; /* partial word encryption buffer */ int nbuf; /* number of part-word stream bits buffered */ } sober128_state; int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen); int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen); int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen); int sober128_stream_done(sober128_state *st); int sober128_stream_test(void); int sober128_stream_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout); #endif /* LTC_SOBER128_STREAM */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h000066400000000000000000000426351464416617300252550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #ifndef TOMCRYPT_CUSTOM_H_ #define TOMCRYPT_CUSTOM_H_ /* macros for various libc functions you can change for embedded targets */ #ifndef XMALLOC #define XMALLOC malloc #endif #ifndef XREALLOC #define XREALLOC realloc #endif #ifndef XCALLOC #define XCALLOC calloc #endif #ifndef XFREE #define XFREE free #endif #ifndef XMEMSET #define XMEMSET memset #endif #ifndef XMEMCPY #define XMEMCPY memcpy #endif #ifndef XMEMMOVE #define XMEMMOVE memmove #endif #ifndef XMEMCMP #define XMEMCMP memcmp #endif /* A memory compare function that has to run in constant time, * c.f. mem_neq() API summary. */ #ifndef XMEM_NEQ #define XMEM_NEQ mem_neq #endif #ifndef XSTRCMP #define XSTRCMP strcmp #endif #ifndef XSTRLEN #define XSTRLEN strlen #endif #ifndef XSTRNCPY #define XSTRNCPY strncpy #endif #ifndef XCLOCK #define XCLOCK clock #endif #ifndef XQSORT #define XQSORT qsort #endif #if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \ defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \ defined(strlen) || defined(strncpy) || defined(clock) || defined(qsort) ) \ && !defined(LTC_NO_PROTOTYPES) #define LTC_NO_PROTOTYPES #endif /* shortcut to disable automatic inclusion */ #if defined LTC_NOTHING && !defined LTC_EASY #define LTC_NO_CIPHERS #define LTC_NO_MODES #define LTC_NO_HASHES #define LTC_NO_MACS #define LTC_NO_PRNGS #define LTC_NO_PK #define LTC_NO_PKCS #define LTC_NO_MISC #endif /* LTC_NOTHING */ /* Easy button? */ #ifdef LTC_EASY #define LTC_NO_CIPHERS #define LTC_RIJNDAEL #define LTC_BLOWFISH #define LTC_DES #define LTC_CAST5 #define LTC_NO_MODES #define LTC_ECB_MODE #define LTC_CBC_MODE #define LTC_CTR_MODE #define LTC_NO_HASHES #define LTC_SHA1 #define LTC_SHA3 #define LTC_SHA512 #define LTC_SHA384 #define LTC_SHA256 #define LTC_SHA224 #define LTC_HASH_HELPERS #define LTC_NO_MACS #define LTC_HMAC #define LTC_OMAC #define LTC_CCM_MODE #define LTC_NO_PRNGS #define LTC_SPRNG #define LTC_YARROW #define LTC_DEVRANDOM #define LTC_TRY_URANDOM_FIRST #define LTC_RNG_GET_BYTES #define LTC_RNG_MAKE_PRNG #define LTC_NO_PK #define LTC_MRSA #define LTC_MECC #define LTC_NO_MISC #define LTC_BASE64 #endif /* LTC_EASY */ /* The minimal set of functionality to run the tests */ #ifdef LTC_MINIMAL #define LTC_RIJNDAEL #define LTC_SHA256 #define LTC_YARROW #define LTC_CTR_MODE #define LTC_RNG_MAKE_PRNG #define LTC_RNG_GET_BYTES #define LTC_DEVRANDOM #define LTC_TRY_URANDOM_FIRST #undef LTC_NO_FILE #endif /* LTC_MINIMAL */ /* Enable self-test test vector checking */ #ifndef LTC_NO_TEST #define LTC_TEST #endif /* Enable extended self-tests */ /* #define LTC_TEST_EXT */ /* Use small code where possible */ /* #define LTC_SMALL_CODE */ /* clean the stack of functions which put private information on stack */ /* #define LTC_CLEAN_STACK */ /* disable all file related functions */ /* #define LTC_NO_FILE */ /* disable all forms of ASM */ /* #define LTC_NO_ASM */ /* disable FAST mode */ /* #define LTC_NO_FAST */ /* disable BSWAP on x86 */ /* #define LTC_NO_BSWAP */ /* ---> math provider? <--- */ #ifndef LTC_NO_MATH /* LibTomMath */ /* #define LTM_DESC */ /* TomsFastMath */ /* #define TFM_DESC */ /* GNU Multiple Precision Arithmetic Library */ /* #define GMP_DESC */ #endif /* LTC_NO_MATH */ /* ---> Symmetric Block Ciphers <--- */ #ifndef LTC_NO_CIPHERS #define LTC_BLOWFISH #define LTC_RC2 #define LTC_RC5 #define LTC_RC6 #define LTC_SAFERP #define LTC_RIJNDAEL #ifndef LTC_NO_AES_NI #define LTC_AES_NI #endif #define LTC_XTEA /* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ #define LTC_TWOFISH #ifndef LTC_NO_TABLES #define LTC_TWOFISH_TABLES /* #define LTC_TWOFISH_ALL_TABLES */ #else #define LTC_TWOFISH_SMALL #endif /* #define LTC_TWOFISH_SMALL */ /* LTC_DES includes EDE triple-DES */ #define LTC_DES #define LTC_CAST5 #define LTC_NOEKEON #define LTC_SKIPJACK #define LTC_SAFER #define LTC_KHAZAD #define LTC_ANUBIS #define LTC_ANUBIS_TWEAK #define LTC_KSEED #define LTC_KASUMI #define LTC_MULTI2 #define LTC_CAMELLIA #define LTC_IDEA #define LTC_SERPENT #define LTC_TEA /* stream ciphers */ #define LTC_CHACHA #define LTC_SALSA20 #define LTC_XSALSA20 #define LTC_SOSEMANUK #define LTC_RABBIT #define LTC_RC4_STREAM #define LTC_SOBER128_STREAM #endif /* LTC_NO_CIPHERS */ /* ---> Block Cipher Modes of Operation <--- */ #ifndef LTC_NO_MODES #define LTC_CFB_MODE #define LTC_OFB_MODE #define LTC_ECB_MODE #define LTC_CBC_MODE #define LTC_CTR_MODE /* F8 chaining mode */ #define LTC_F8_MODE /* LRW mode */ #define LTC_LRW_MODE #ifndef LTC_NO_TABLES /* like GCM mode this will enable 16 8x128 tables [64KB] that make * seeking very fast. */ #define LTC_LRW_TABLES #endif /* XTS mode */ #define LTC_XTS_MODE #endif /* LTC_NO_MODES */ /* ---> One-Way Hash Functions <--- */ #ifndef LTC_NO_HASHES #define LTC_CHC_HASH #define LTC_WHIRLPOOL #define LTC_SHA3 #define LTC_KECCAK #define LTC_SHA512 #define LTC_SHA512_256 #define LTC_SHA512_224 #define LTC_SHA384 #define LTC_SHA256 #define LTC_SHA224 #define LTC_TIGER #define LTC_SHA1 #define LTC_MD5 #define LTC_MD4 #define LTC_MD2 #define LTC_RIPEMD128 #define LTC_RIPEMD160 #define LTC_RIPEMD256 #define LTC_RIPEMD320 #define LTC_BLAKE2S #define LTC_BLAKE2B #define LTC_HASH_HELPERS #endif /* LTC_NO_HASHES */ /* ---> MAC functions <--- */ #ifndef LTC_NO_MACS #define LTC_HMAC #define LTC_OMAC #define LTC_PMAC #define LTC_XCBC #define LTC_F9_MODE #define LTC_PELICAN #define LTC_POLY1305 #define LTC_BLAKE2SMAC #define LTC_BLAKE2BMAC /* ---> Encrypt + Authenticate Modes <--- */ #define LTC_EAX_MODE #define LTC_OCB_MODE #define LTC_OCB3_MODE #define LTC_CCM_MODE #define LTC_GCM_MODE #define LTC_CHACHA20POLY1305_MODE /* Use 64KiB tables */ #ifndef LTC_NO_TABLES #define LTC_GCM_TABLES #endif /* USE SSE2? requires GCC works on x86_32 and x86_64*/ #ifdef LTC_GCM_TABLES /* #define LTC_GCM_TABLES_SSE2 */ #endif #endif /* LTC_NO_MACS */ /* --> Pseudo Random Number Generators <--- */ #ifndef LTC_NO_PRNGS /* Yarrow */ #define LTC_YARROW /* a PRNG that simply reads from an available system source */ #define LTC_SPRNG /* The RC4 stream cipher based PRNG */ #define LTC_RC4 /* The ChaCha20 stream cipher based PRNG */ #define LTC_CHACHA20_PRNG /* Fortuna PRNG */ #define LTC_FORTUNA /* Greg's SOBER128 stream cipher based PRNG */ #define LTC_SOBER128 #if !defined(_WIN32) && !defined(_WIN32_WCE) /* the *nix style /dev/random device */ #define LTC_DEVRANDOM /* try /dev/urandom before trying /dev/random * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */ #define LTC_TRY_URANDOM_FIRST #endif /* not Windows */ /* rng_get_bytes() */ #define LTC_RNG_GET_BYTES /* rng_make_prng() */ #define LTC_RNG_MAKE_PRNG /* enable the ltc_rng hook to integrate e.g. embedded hardware RNG's easily */ /* #define LTC_PRNG_ENABLE_LTC_RNG */ #endif /* LTC_NO_PRNGS */ #ifdef LTC_YARROW /* which descriptor of AES to use? */ /* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ #ifdef ENCRYPT_ONLY #define LTC_YARROW_AES 0 #else #define LTC_YARROW_AES 2 #endif #endif /* LTC_YARROW */ #ifdef LTC_FORTUNA #if !defined(LTC_FORTUNA_RESEED_RATELIMIT_STATIC) && \ ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(_WIN32)) /* time-based rate limit of the reseeding */ #define LTC_FORTUNA_RESEED_RATELIMIT_TIMED /* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */ #if defined(__GLIBC__) && defined(__GLIBC_PREREQ) #if __GLIBC_PREREQ(2, 17) #define LTC_CLOCK_GETTIME #endif #elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L #define LTC_CLOCK_GETTIME #endif #else #ifndef LTC_FORTUNA_WD /* reseed every N calls to the read function */ #define LTC_FORTUNA_WD 10 #endif #ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED /* make sure only one of * LTC_FORTUNA_RESEED_RATELIMIT_STATIC * and * LTC_FORTUNA_RESEED_RATELIMIT_TIMED * is defined. */ #undef LTC_FORTUNA_RESEED_RATELIMIT_TIMED #warning "undef'ed LTC_FORTUNA_RESEED_RATELIMIT_TIMED, looks like your architecture doesn't support it" #endif #endif #ifndef LTC_FORTUNA_POOLS /* number of pools (4..32) can save a bit of ram by lowering the count */ #define LTC_FORTUNA_POOLS 32 #endif /* at compile time you can decide whether fortuna uses the regular AES APIs * or whether it will use the 'encrypt_only' variants. * This is useful for custom builds of libtomcrypt for size-constrained targets. */ /* #define LTC_FORTUNA_USE_ENCRYPT_ONLY */ #endif /* LTC_FORTUNA */ /* ---> Public Key Crypto <--- */ #ifndef LTC_NO_PK /* Include RSA support */ #define LTC_MRSA /* Include Diffie-Hellman support */ /* is_prime fails for GMP */ #define LTC_MDH /* Supported Key Sizes */ #define LTC_DH768 #define LTC_DH1024 #define LTC_DH1536 #define LTC_DH2048 #if defined(LTM_DESC) || defined(GMP_DESC) /* tfm has a problem in fp_isprime for larger key sizes */ #define LTC_DH3072 #define LTC_DH4096 #define LTC_DH6144 #define LTC_DH8192 #endif /* Digital Signature Algorithm */ #define LTC_MDSA /* Ed25519 & X25519 */ #define LTC_CURVE25519 /* ECC */ #define LTC_MECC /* use Shamir's trick for point mul (speeds up signature verification) */ #define LTC_ECC_SHAMIR #if defined(TFM_DESC) && defined(LTC_MECC) #define LTC_MECC_ACCEL #endif /* do we want fixed point ECC */ /* #define LTC_MECC_FP */ #endif /* LTC_NO_PK */ #if defined(LTC_MRSA) && !defined(LTC_NO_RSA_BLINDING) /* Enable RSA blinding when doing private key operations by default */ #define LTC_RSA_BLINDING #endif /* LTC_NO_RSA_BLINDING */ #if defined(LTC_MRSA) && !defined(LTC_NO_RSA_CRT_HARDENING) /* Enable RSA CRT hardening when doing private key operations by default */ #define LTC_RSA_CRT_HARDENING #endif /* LTC_NO_RSA_CRT_HARDENING */ #if defined(LTC_MECC) && !defined(LTC_NO_ECC_TIMING_RESISTANT) /* Enable ECC timing resistant version by default */ #define LTC_ECC_TIMING_RESISTANT #endif /* PKCS #1 (RSA) and #5 (Password Handling) stuff */ #ifndef LTC_NO_PKCS #define LTC_PKCS_1 #define LTC_PKCS_5 #define LTC_PKCS_8 #define LTC_PKCS_12 /* Include ASN.1 DER (required by DSA/RSA) */ #define LTC_DER #define LTC_MPI #endif /* LTC_NO_PKCS */ /* misc stuff */ #ifndef LTC_NO_MISC /* Various tidbits of modern neatoness */ #define LTC_BASE64 /* ... and it's URL safe version */ #define LTC_BASE64_URL /* Base32 encoding/decoding */ #define LTC_BASE32 /* Base16/hex encoding/decoding */ #define LTC_BASE16 #define LTC_BCRYPT #ifndef LTC_BCRYPT_DEFAULT_ROUNDS #define LTC_BCRYPT_DEFAULT_ROUNDS 10 #endif /* Keep LTC_NO_HKDF for compatibility reasons * superseeded by LTC_NO_MISC*/ #ifndef LTC_NO_HKDF /* HKDF Key Derivation/Expansion stuff */ #define LTC_HKDF #endif /* LTC_NO_HKDF */ #define LTC_ADLER32 #define LTC_CRC32 #define LTC_SSH #define LTC_PADDING #define LTC_PBES #endif /* LTC_NO_MISC */ /* cleanup */ #ifdef LTC_MECC /* Supported ECC Key Sizes */ #ifndef LTC_NO_CURVES #define LTC_ECC_BRAINPOOLP160R1 #define LTC_ECC_BRAINPOOLP160T1 #define LTC_ECC_BRAINPOOLP192R1 #define LTC_ECC_BRAINPOOLP192T1 #define LTC_ECC_BRAINPOOLP224R1 #define LTC_ECC_BRAINPOOLP224T1 #define LTC_ECC_BRAINPOOLP256R1 #define LTC_ECC_BRAINPOOLP256T1 #define LTC_ECC_BRAINPOOLP320R1 #define LTC_ECC_BRAINPOOLP320T1 #define LTC_ECC_BRAINPOOLP384R1 #define LTC_ECC_BRAINPOOLP384T1 #define LTC_ECC_BRAINPOOLP512R1 #define LTC_ECC_BRAINPOOLP512T1 #define LTC_ECC_PRIME192V2 #define LTC_ECC_PRIME192V3 #define LTC_ECC_PRIME239V1 #define LTC_ECC_PRIME239V2 #define LTC_ECC_PRIME239V3 #define LTC_ECC_SECP112R1 #define LTC_ECC_SECP112R2 #define LTC_ECC_SECP128R1 #define LTC_ECC_SECP128R2 #define LTC_ECC_SECP160K1 #define LTC_ECC_SECP160R1 #define LTC_ECC_SECP160R2 #define LTC_ECC_SECP192K1 #define LTC_ECC_SECP192R1 #define LTC_ECC_SECP224K1 #define LTC_ECC_SECP224R1 #define LTC_ECC_SECP256K1 #define LTC_ECC_SECP256R1 #define LTC_ECC_SECP384R1 #define LTC_ECC_SECP521R1 #endif #endif /* LTC_MECC */ #if defined(LTC_DER) #ifndef LTC_DER_MAX_RECURSION /* Maximum recursion limit when processing nested ASN.1 types. */ #define LTC_DER_MAX_RECURSION 30 #endif #endif #if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH) #ifndef LTC_PK_MAX_RETRIES /* iterations limit for retry-loops */ #define LTC_PK_MAX_RETRIES 20 #endif #endif #ifdef LTC_MRSA #define LTC_PKCS_1 #endif #if defined(LTC_MRSA) || defined(LTC_MECC) #define LTC_PKCS_8 #endif #ifdef LTC_PKCS_8 #define LTC_PADDING #define LTC_PBES #endif #if defined(LTC_CLEAN_STACK) /* if you're sure that you want to use it, remove the line below */ #error LTC_CLEAN_STACK is considered as broken #endif #if defined(LTC_PBES) && !defined(LTC_PKCS_5) #error LTC_PBES requires LTC_PKCS_5 #endif #if defined(LTC_PBES) && !defined(LTC_PKCS_12) #error LTC_PBES requires LTC_PKCS_12 #endif #if defined(LTC_PKCS_5) && !defined(LTC_HMAC) #error LTC_PKCS_5 requires LTC_HMAC #endif #if defined(LTC_PKCS_5) && !defined(LTC_HASH_HELPERS) #error LTC_PKCS_5 requires LTC_HASH_HELPERS #endif #if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL) #error Pelican-MAC requires LTC_RIJNDAEL #endif #if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) #error LTC_EAX_MODE requires CTR and LTC_OMAC mode #endif #if defined(LTC_YARROW) && !defined(LTC_CTR_MODE) #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined! #endif #if defined(LTC_DER) && !defined(LTC_MPI) #error ASN.1 DER requires MPI functionality #endif #if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC)) && !defined(LTC_DER) #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled #endif #if defined(LTC_BCRYPT) && !defined(LTC_BLOWFISH) #error LTC_BCRYPT requires LTC_BLOWFISH #endif #if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305)) #error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305 #endif #if defined(LTC_CHACHA20_PRNG) && !defined(LTC_CHACHA) #error LTC_CHACHA20_PRNG requires LTC_CHACHA #endif #if defined(LTC_XSALSA20) && !defined(LTC_SALSA20) #error LTC_XSALSA20 requires LTC_SALSA20 #endif #if defined(LTC_RC4) && !defined(LTC_RC4_STREAM) #error LTC_RC4 requires LTC_RC4_STREAM #endif #if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM) #error LTC_SOBER128 requires LTC_SOBER128_STREAM #endif #if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S) #error LTC_BLAKE2SMAC requires LTC_BLAKE2S #endif #if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B) #error LTC_BLAKE2BMAC requires LTC_BLAKE2B #endif #if defined(LTC_SPRNG) && !defined(LTC_RNG_GET_BYTES) #error LTC_SPRNG requires LTC_RNG_GET_BYTES #endif #if defined(LTC_NO_MATH) && (defined(LTM_DESC) || defined(TFM_DESC) || defined(GMP_DESC)) #error LTC_NO_MATH defined, but also a math descriptor #endif /* THREAD management */ #if defined(_CFG_CORE_LTC_OPTEE_THREAD) #include #define LTC_MUTEX_GLOBAL(x) struct mutex x = MUTEX_INITIALIZER; #define LTC_MUTEX_PROTO(x) extern struct mutex x; #define LTC_MUTEX_TYPE(x) struct mutex x; #define LTC_MUTEX_INIT(x) mutex_init(x); #define LTC_MUTEX_LOCK(x) mutex_lock(x); #define LTC_MUTEX_UNLOCK(x) mutex_unlock(x); #elif defined(LTC_PTHREAD) #include #define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; #define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x; #define LTC_MUTEX_TYPE(x) pthread_mutex_t x; #define LTC_MUTEX_INIT(x) LTC_ARGCHK(pthread_mutex_init(x, NULL) == 0); #define LTC_MUTEX_LOCK(x) LTC_ARGCHK(pthread_mutex_lock(x) == 0); #define LTC_MUTEX_UNLOCK(x) LTC_ARGCHK(pthread_mutex_unlock(x) == 0); #define LTC_MUTEX_DESTROY(x) LTC_ARGCHK(pthread_mutex_destroy(x) == 0); #else /* default no functions */ #define LTC_MUTEX_GLOBAL(x) #define LTC_MUTEX_PROTO(x) #define LTC_MUTEX_TYPE(x) #define LTC_MUTEX_INIT(x) #define LTC_MUTEX_LOCK(x) #define LTC_MUTEX_UNLOCK(x) #define LTC_MUTEX_DESTROY(x) #endif /* LTC_PTHREAD */ /* Debuggers */ /* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */ /* #define LTC_VALGRIND */ #ifndef LTC_NO_FILE /* buffer size for reading from a file via fread(..) */ #ifndef LTC_FILE_READ_BUFSIZE #define LTC_FILE_READ_BUFSIZE 8192 #endif #endif /* ECC backwards compatibility */ #if !defined(LTC_ECC_SECP112R1) && defined(LTC_ECC112) #define LTC_ECC_SECP112R1 #undef LTC_ECC112 #endif #if !defined(LTC_ECC_SECP128R1) && defined(LTC_ECC128) #define LTC_ECC_SECP128R1 #undef LTC_ECC128 #endif #if !defined(LTC_ECC_SECP160R1) && defined(LTC_ECC160) #define LTC_ECC_SECP160R1 #undef LTC_ECC160 #endif #if !defined(LTC_ECC_SECP192R1) && defined(LTC_ECC192) #define LTC_ECC_SECP192R1 #undef LTC_ECC192 #endif #if !defined(LTC_ECC_SECP224R1) && defined(LTC_ECC224) #define LTC_ECC_SECP224R1 #undef LTC_ECC224 #endif #if !defined(LTC_ECC_SECP256R1) && defined(LTC_ECC256) #define LTC_ECC_SECP256R1 #undef LTC_ECC256 #endif #if !defined(LTC_ECC_SECP384R1) && defined(LTC_ECC384) #define LTC_ECC_SECP384R1 #undef LTC_ECC384 #endif #if !defined(LTC_ECC_SECP512R1) && defined(LTC_ECC521) #define LTC_ECC_SECP521R1 #undef LTC_ECC521 #endif #endif /* TOMCRYPT_CUSTOM_H_ */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h000066400000000000000000000350221464416617300246560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* ---- HASH FUNCTIONS ---- */ #if defined(LTC_SHA3) || defined(LTC_KECCAK) struct sha3_state { ulong64 saved; /* the portion of the input message that we didn't consume yet */ ulong64 s[25]; unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */ unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */ unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */ unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */ unsigned short xof_flag; }; #endif #ifdef LTC_SHA512 struct sha512_state { ulong64 length, state[8]; unsigned long curlen; unsigned char buf[128]; }; #endif #ifdef LTC_SHA256 struct sha256_state { ulong64 length; ulong32 state[8], curlen; unsigned char buf[64]; }; #endif #ifdef LTC_SHA1 struct sha1_state { ulong64 length; ulong32 state[5], curlen; unsigned char buf[64]; }; #endif #ifdef LTC_MD5 struct md5_state { ulong64 length; ulong32 state[4], curlen; unsigned char buf[64]; }; #endif #ifdef LTC_MD4 struct md4_state { ulong64 length; ulong32 state[4], curlen; unsigned char buf[64]; }; #endif #ifdef LTC_TIGER struct tiger_state { ulong64 state[3], length; unsigned long curlen, passes; unsigned char buf[64], pad; }; #endif #ifdef LTC_MD2 struct md2_state { unsigned char chksum[16], X[48], buf[16]; unsigned long curlen; }; #endif #ifdef LTC_RIPEMD128 struct rmd128_state { ulong64 length; unsigned char buf[64]; ulong32 curlen, state[4]; }; #endif #ifdef LTC_RIPEMD160 struct rmd160_state { ulong64 length; unsigned char buf[64]; ulong32 curlen, state[5]; }; #endif #ifdef LTC_RIPEMD256 struct rmd256_state { ulong64 length; unsigned char buf[64]; ulong32 curlen, state[8]; }; #endif #ifdef LTC_RIPEMD320 struct rmd320_state { ulong64 length; unsigned char buf[64]; ulong32 curlen, state[10]; }; #endif #ifdef LTC_WHIRLPOOL struct whirlpool_state { ulong64 length, state[8]; unsigned char buf[64]; ulong32 curlen; }; #endif #ifdef LTC_CHC_HASH struct chc_state { ulong64 length; unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE]; ulong32 curlen; }; #endif #ifdef LTC_BLAKE2S struct blake2s_state { ulong32 h[8]; ulong32 t[2]; ulong32 f[2]; unsigned char buf[64]; unsigned long curlen; unsigned long outlen; unsigned char last_node; }; #endif #ifdef LTC_BLAKE2B struct blake2b_state { ulong64 h[8]; ulong64 t[2]; ulong64 f[2]; unsigned char buf[128]; unsigned long curlen; unsigned long outlen; unsigned char last_node; }; #endif typedef union Hash_state { char dummy[1]; #ifdef LTC_CHC_HASH struct chc_state chc; #endif #ifdef LTC_WHIRLPOOL struct whirlpool_state whirlpool; #endif #if defined(LTC_SHA3) || defined(LTC_KECCAK) struct sha3_state sha3; #endif #ifdef LTC_SHA512 struct sha512_state sha512; #endif #ifdef LTC_SHA256 struct sha256_state sha256; #endif #ifdef LTC_SHA1 struct sha1_state sha1; #endif #ifdef LTC_MD5 struct md5_state md5; #endif #ifdef LTC_MD4 struct md4_state md4; #endif #ifdef LTC_MD2 struct md2_state md2; #endif #ifdef LTC_TIGER struct tiger_state tiger; #endif #ifdef LTC_RIPEMD128 struct rmd128_state rmd128; #endif #ifdef LTC_RIPEMD160 struct rmd160_state rmd160; #endif #ifdef LTC_RIPEMD256 struct rmd256_state rmd256; #endif #ifdef LTC_RIPEMD320 struct rmd320_state rmd320; #endif #ifdef LTC_BLAKE2S struct blake2s_state blake2s; #endif #ifdef LTC_BLAKE2B struct blake2b_state blake2b; #endif void *data; } hash_state; /** hash descriptor */ extern const struct ltc_hash_descriptor { /** name of hash */ const char *name; /** internal ID */ unsigned char ID; /** Size of digest in octets */ unsigned long hashsize; /** Input block size in octets */ unsigned long blocksize; /** ASN.1 OID */ unsigned long OID[16]; /** Length of DER encoding */ unsigned long OIDlen; /** Init a hash state @param hash The hash to initialize @return CRYPT_OK if successful */ int (*init)(hash_state *hash); /** Process a block of data @param hash The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); /** Produce the digest and store it @param hash The hash state @param out [out] The destination of the digest @return CRYPT_OK if successful */ int (*done)(hash_state *hash, unsigned char *out); /** Self-test @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int (*test)(void); /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ int (*hmac_block)(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); } *hash_descriptor[]; #ifdef LTC_CHC_HASH int chc_register(int cipher); int chc_init(hash_state * md); int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); int chc_done(hash_state * md, unsigned char *out); int chc_test(void); extern const struct ltc_hash_descriptor chc_desc; #endif #ifdef LTC_WHIRLPOOL int whirlpool_init(hash_state * md); int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen); int whirlpool_done(hash_state * md, unsigned char *out); int whirlpool_test(void); extern const struct ltc_hash_descriptor whirlpool_desc; #endif #if defined(LTC_SHA3) || defined(LTC_KECCAK) /* sha3_NNN_init are shared by SHA3 and KECCAK */ int sha3_512_init(hash_state * md); int sha3_384_init(hash_state * md); int sha3_256_init(hash_state * md); int sha3_224_init(hash_state * md); /* sha3_process is the same for all variants of SHA3 + KECCAK */ int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen); #endif #ifdef LTC_SHA3 int sha3_512_test(void); extern const struct ltc_hash_descriptor sha3_512_desc; int sha3_384_test(void); extern const struct ltc_hash_descriptor sha3_384_desc; int sha3_256_test(void); extern const struct ltc_hash_descriptor sha3_256_desc; int sha3_224_test(void); extern const struct ltc_hash_descriptor sha3_224_desc; int sha3_done(hash_state *md, unsigned char *out); /* SHAKE128 + SHAKE256 */ int sha3_shake_init(hash_state *md, int num); #define sha3_shake_process(a,b,c) sha3_process(a,b,c) int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen); int sha3_shake_test(void); int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen); #endif #ifdef LTC_KECCAK #define keccak_512_init(a) sha3_512_init(a) #define keccak_384_init(a) sha3_384_init(a) #define keccak_256_init(a) sha3_256_init(a) #define keccak_224_init(a) sha3_224_init(a) #define keccak_process(a,b,c) sha3_process(a,b,c) extern const struct ltc_hash_descriptor keccak_512_desc; int keccak_512_test(void); extern const struct ltc_hash_descriptor keccak_384_desc; int keccak_384_test(void); extern const struct ltc_hash_descriptor keccak_256_desc; int keccak_256_test(void); extern const struct ltc_hash_descriptor keccak_224_desc; int keccak_224_test(void); int keccak_done(hash_state *md, unsigned char *out); #endif #ifdef LTC_SHA512 int sha512_init(hash_state * md); int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen); int sha512_done(hash_state * md, unsigned char *out); int sha512_test(void); extern const struct ltc_hash_descriptor sha512_desc; #endif #ifdef LTC_SHA384 #ifndef LTC_SHA512 #error LTC_SHA512 is required for LTC_SHA384 #endif int sha384_init(hash_state * md); #define sha384_process sha512_process int sha384_done(hash_state * md, unsigned char *out); int sha384_test(void); extern const struct ltc_hash_descriptor sha384_desc; #endif #ifdef LTC_SHA512_256 #ifndef LTC_SHA512 #error LTC_SHA512 is required for LTC_SHA512_256 #endif int sha512_256_init(hash_state * md); #define sha512_256_process sha512_process int sha512_256_done(hash_state * md, unsigned char *out); int sha512_256_test(void); extern const struct ltc_hash_descriptor sha512_256_desc; #endif #ifdef LTC_SHA512_224 #ifndef LTC_SHA512 #error LTC_SHA512 is required for LTC_SHA512_224 #endif int sha512_224_init(hash_state * md); #define sha512_224_process sha512_process int sha512_224_done(hash_state * md, unsigned char *out); int sha512_224_test(void); extern const struct ltc_hash_descriptor sha512_224_desc; #endif #ifdef LTC_SHA256 int sha256_init(hash_state * md); int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); int sha256_done(hash_state * md, unsigned char *out); int sha256_test(void); extern const struct ltc_hash_descriptor sha256_desc; #ifdef LTC_SHA224 #ifndef LTC_SHA256 #error LTC_SHA256 is required for LTC_SHA224 #endif int sha224_init(hash_state * md); #define sha224_process sha256_process int sha224_done(hash_state * md, unsigned char *out); int sha224_test(void); extern const struct ltc_hash_descriptor sha224_desc; #endif #endif #ifdef LTC_SHA1 int sha1_init(hash_state * md); int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen); int sha1_done(hash_state * md, unsigned char *out); int sha1_test(void); extern const struct ltc_hash_descriptor sha1_desc; #endif #ifdef LTC_BLAKE2S extern const struct ltc_hash_descriptor blake2s_256_desc; int blake2s_256_init(hash_state * md); int blake2s_256_test(void); extern const struct ltc_hash_descriptor blake2s_224_desc; int blake2s_224_init(hash_state * md); int blake2s_224_test(void); extern const struct ltc_hash_descriptor blake2s_160_desc; int blake2s_160_init(hash_state * md); int blake2s_160_test(void); extern const struct ltc_hash_descriptor blake2s_128_desc; int blake2s_128_init(hash_state * md); int blake2s_128_test(void); int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen); int blake2s_done(hash_state * md, unsigned char *out); #endif #ifdef LTC_BLAKE2B extern const struct ltc_hash_descriptor blake2b_512_desc; int blake2b_512_init(hash_state * md); int blake2b_512_test(void); extern const struct ltc_hash_descriptor blake2b_384_desc; int blake2b_384_init(hash_state * md); int blake2b_384_test(void); extern const struct ltc_hash_descriptor blake2b_256_desc; int blake2b_256_init(hash_state * md); int blake2b_256_test(void); extern const struct ltc_hash_descriptor blake2b_160_desc; int blake2b_160_init(hash_state * md); int blake2b_160_test(void); int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen); int blake2b_done(hash_state * md, unsigned char *out); #endif #ifdef LTC_MD5 int md5_init(hash_state * md); int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); int md5_done(hash_state * md, unsigned char *out); int md5_test(void); extern const struct ltc_hash_descriptor md5_desc; #endif #ifdef LTC_MD4 int md4_init(hash_state * md); int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen); int md4_done(hash_state * md, unsigned char *out); int md4_test(void); extern const struct ltc_hash_descriptor md4_desc; #endif #ifdef LTC_MD2 int md2_init(hash_state * md); int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen); int md2_done(hash_state * md, unsigned char *out); int md2_test(void); extern const struct ltc_hash_descriptor md2_desc; #endif #ifdef LTC_TIGER int tiger_init(hash_state * md); int tiger_init_ex(hash_state *md, unsigned long passes); int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); int tiger_done(hash_state * md, unsigned char *out); int tiger_test(void); int tiger2_init(hash_state *md); int tiger2_init_ex(hash_state *md, unsigned long passes); #define tiger2_process(m, i, l) tiger_process(m, i, l) #define tiger2_done(m, o) tiger_done(m, o) int tiger2_test(void); extern const struct ltc_hash_descriptor tiger_desc, tiger2_desc; #endif #ifdef LTC_RIPEMD128 int rmd128_init(hash_state * md); int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen); int rmd128_done(hash_state * md, unsigned char *out); int rmd128_test(void); extern const struct ltc_hash_descriptor rmd128_desc; #endif #ifdef LTC_RIPEMD160 int rmd160_init(hash_state * md); int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen); int rmd160_done(hash_state * md, unsigned char *out); int rmd160_test(void); extern const struct ltc_hash_descriptor rmd160_desc; #endif #ifdef LTC_RIPEMD256 int rmd256_init(hash_state * md); int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen); int rmd256_done(hash_state * md, unsigned char *out); int rmd256_test(void); extern const struct ltc_hash_descriptor rmd256_desc; #endif #ifdef LTC_RIPEMD320 int rmd320_init(hash_state * md); int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen); int rmd320_done(hash_state * md, unsigned char *out); int rmd320_test(void); extern const struct ltc_hash_descriptor rmd320_desc; #endif int find_hash(const char *name); int find_hash_id(unsigned char ID); int find_hash_oid(const unsigned long *ID, unsigned long IDlen); int find_hash_any(const char *name, int digestlen); int register_hash(const struct ltc_hash_descriptor *hash); int unregister_hash(const struct ltc_hash_descriptor *hash); int register_all_hashes(void); int hash_is_valid(int idx); LTC_MUTEX_PROTO(ltc_hash_mutex) int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; #ifndef LTC_NO_FILE int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); #endif optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h000066400000000000000000000562101464416617300244750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #ifdef LTC_HMAC typedef struct Hmac_state { hash_state md; int hash; unsigned char key[MAXBLOCKSIZE]; } hmac_state; int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen); int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen); int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen); int hmac_test(void); int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int hmac_memory_multi(int hash, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int hmac_file(int hash, const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen); #endif #ifdef LTC_OMAC typedef struct { int cipher_idx, buflen, blklen; unsigned char block[MAXBLOCKSIZE], prev[MAXBLOCKSIZE], Lu[2][MAXBLOCKSIZE]; symmetric_key key; } omac_state; int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen); int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen); int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen); int omac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int omac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen); int omac_test(void); #endif /* LTC_OMAC */ #ifdef LTC_PMAC typedef struct { unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ Lr[MAXBLOCKSIZE], /* L * x^-1 */ block[MAXBLOCKSIZE], /* currently accumulated block */ checksum[MAXBLOCKSIZE]; /* current checksum */ symmetric_key key; /* scheduled key for cipher */ unsigned long block_index; /* index # for current block */ int cipher_idx, /* cipher idx */ block_len, /* length of block */ buflen; /* number of bytes in the buffer */ } pmac_state; int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen); int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen); int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen); int pmac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int pmac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int pmac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen); int pmac_test(void); /* internal functions */ int pmac_ntz(unsigned long x); void pmac_shift_xor(pmac_state *pmac); #endif /* PMAC */ #ifdef LTC_POLY1305 typedef struct { ulong32 r[5]; ulong32 h[5]; ulong32 pad[4]; unsigned long leftover; unsigned char buffer[16]; int final; } poly1305_state; int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen); int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen); int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen); int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); int poly1305_test(void); #endif /* LTC_POLY1305 */ #ifdef LTC_BLAKE2SMAC typedef hash_state blake2smac_state; int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen); int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen); int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); int blake2smac_test(void); #endif /* LTC_BLAKE2SMAC */ #ifdef LTC_BLAKE2BMAC typedef hash_state blake2bmac_state; int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen); int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen); int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); int blake2bmac_test(void); #endif /* LTC_BLAKE2BMAC */ #ifdef LTC_PELICAN typedef struct pelican_state { symmetric_key K; unsigned char state[16]; int buflen; } pelican_state; int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen); int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen); int pelican_done(pelican_state *pelmac, unsigned char *out); int pelican_test(void); int pelican_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out); #endif #ifdef LTC_XCBC /* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */ #define LTC_XCBC_PURE 0x8000UL typedef struct { unsigned char K[3][MAXBLOCKSIZE], IV[MAXBLOCKSIZE]; symmetric_key key; int cipher, buflen, blocksize; } xcbc_state; int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen); int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen); int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen); int xcbc_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int xcbc_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int xcbc_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen); int xcbc_test(void); #endif #ifdef LTC_F9_MODE typedef struct { unsigned char akey[MAXBLOCKSIZE], ACC[MAXBLOCKSIZE], IV[MAXBLOCKSIZE]; symmetric_key key; int cipher, buflen, keylen, blocksize; } f9_state; int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen); int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen); int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen); int f9_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int f9_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; int f9_file(int cipher, const unsigned char *key, unsigned long keylen, const char *fname, unsigned char *out, unsigned long *outlen); int f9_test(void); #endif /* * ENC+AUTH modes */ #ifdef LTC_EAX_MODE #if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE)) #error LTC_EAX_MODE requires LTC_OMAC and CTR #endif typedef struct { unsigned char N[MAXBLOCKSIZE]; symmetric_CTR ctr; omac_state headeromac, ctomac; } eax_state; int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen); int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length); int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length); int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length); int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen); int eax_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen); int eax_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat); int eax_test(void); #endif /* EAX MODE */ #ifdef LTC_OCB_MODE typedef struct { unsigned char L[MAXBLOCKSIZE], /* L value */ Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ Lr[MAXBLOCKSIZE], /* L * x^-1 */ R[MAXBLOCKSIZE], /* R value */ checksum[MAXBLOCKSIZE]; /* current checksum */ symmetric_key key; /* scheduled key for cipher */ unsigned long block_index; /* index # for current block */ int cipher, /* cipher idx */ block_len; /* length of block */ } ocb_state; int ocb_init(ocb_state *ocb, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce); int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen); int ocb_done_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat); int ocb_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen); int ocb_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat); int ocb_test(void); /* internal functions */ void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); int ocb_ntz(unsigned long x); int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); #endif /* LTC_OCB_MODE */ #ifdef LTC_OCB3_MODE typedef struct { unsigned char Offset_0[MAXBLOCKSIZE], /* Offset_0 value */ Offset_current[MAXBLOCKSIZE], /* Offset_{current_block_index} value */ L_dollar[MAXBLOCKSIZE], /* L_$ value */ L_star[MAXBLOCKSIZE], /* L_* value */ L_[32][MAXBLOCKSIZE], /* L_{i} values */ tag_part[MAXBLOCKSIZE], /* intermediate result of tag calculation */ checksum[MAXBLOCKSIZE]; /* current checksum */ /* AAD related members */ unsigned char aSum_current[MAXBLOCKSIZE], /* AAD related helper variable */ aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */ adata_buffer[MAXBLOCKSIZE]; /* AAD buffer */ symmetric_key key; /* scheduled key for cipher */ int adata_buffer_bytes; /* bytes in AAD buffer */ unsigned long ablock_index; /* index # for current adata (AAD) block */ unsigned long block_index; /* index # for current data block */ int cipher, /* cipher idx */ tag_len, /* length of tag */ block_len; /* length of block */ } ocb3_state; int ocb3_init(ocb3_state *ocb, int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen); int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen); int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen); int ocb3_encrypt_authenticate_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *adata, unsigned long adatalen, const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen); int ocb3_decrypt_verify_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, const unsigned char *adata, unsigned long adatalen, const unsigned char *ct, unsigned long ctlen, unsigned char *pt, const unsigned char *tag, unsigned long taglen, int *stat); int ocb3_test(void); #endif /* LTC_OCB3_MODE */ #ifdef LTC_CCM_MODE #define CCM_ENCRYPT LTC_ENCRYPT #define CCM_DECRYPT LTC_DECRYPT typedef struct { unsigned char PAD[16], /* flags | Nonce N | l(m) */ ctr[16], CTRPAD[16]; symmetric_key K; int cipher, /* which cipher */ taglen, /* length of the tag (encoded in M value) */ x; /* index in PAD */ unsigned long L, /* L value */ ptlen, /* length that will be enc / dec */ current_ptlen, /* current processed length */ aadlen, /* length of the aad */ current_aadlen, /* length of the currently provided add */ noncelen; /* length of the nonce */ unsigned char CTRlen; } ccm_state; int ccm_init(ccm_state *ccm, int cipher, const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen); int ccm_reset(ccm_state *ccm); int ccm_add_nonce(ccm_state *ccm, const unsigned char *nonce, unsigned long noncelen); int ccm_add_aad(ccm_state *ccm, const unsigned char *adata, unsigned long adatalen); int ccm_process(ccm_state *ccm, unsigned char *pt, unsigned long ptlen, unsigned char *ct, int direction); int ccm_done(ccm_state *ccm, unsigned char *tag, unsigned long *taglen); int ccm_memory(int cipher, const unsigned char *key, unsigned long keylen, symmetric_key *uskey, const unsigned char *nonce, unsigned long noncelen, const unsigned char *header, unsigned long headerlen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction); int ccm_test(void); #endif /* LTC_CCM_MODE */ #if defined(LRW_MODE) || defined(LTC_GCM_MODE) void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c); #endif /* table shared between GCM and LRW */ #if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST)) extern const unsigned char gcm_shift_table[]; #endif #ifdef LTC_GCM_MODE #define GCM_ENCRYPT LTC_ENCRYPT #define GCM_DECRYPT LTC_DECRYPT #define LTC_GCM_MODE_IV 0 #define LTC_GCM_MODE_AAD 1 #define LTC_GCM_MODE_TEXT 2 typedef struct { unsigned char H[16], /* multiplier */ X[16], /* accumulator */ Y[16], /* counter */ Y_0[16], /* initial counter */ buf[16]; /* buffer for stuff */ #ifdef LTC_GCM_TABLES unsigned char PC[16][256][16]; /* 16 tables of 8x128 */ #endif symmetric_key K; int cipher, /* which cipher */ ivmode, /* Which mode is the IV in? */ mode, /* mode the GCM code is in */ buflen; /* length of data in buf */ ulong64 totlen, /* 64-bit counter used for IV and AAD */ pttotlen; /* 64-bit counter for the PT */ } gcm_state; void gcm_mult_h(const gcm_state *gcm, unsigned char *I); int gcm_init(gcm_state *gcm, int cipher, const unsigned char *key, int keylen); int gcm_reset(gcm_state *gcm); int gcm_add_iv(gcm_state *gcm, const unsigned char *IV, unsigned long IVlen); int gcm_add_aad(gcm_state *gcm, const unsigned char *adata, unsigned long adatalen); int gcm_process(gcm_state *gcm, unsigned char *pt, unsigned long ptlen, unsigned char *ct, int direction); int gcm_done(gcm_state *gcm, unsigned char *tag, unsigned long *taglen); int gcm_memory( int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *IV, unsigned long IVlen, const unsigned char *adata, unsigned long adatalen, unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tag, unsigned long *taglen, int direction); int gcm_test(void); #endif /* LTC_GCM_MODE */ #ifdef LTC_CHACHA20POLY1305_MODE typedef struct { poly1305_state poly; chacha_state chacha; ulong64 aadlen; ulong64 ctlen; int aadflg; } chacha20poly1305_state; #define CHACHA20POLY1305_ENCRYPT LTC_ENCRYPT #define CHACHA20POLY1305_DECRYPT LTC_DECRYPT int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen); int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen); int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number); int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen); int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen); int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *aad, unsigned long aadlen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned char *tag, unsigned long *taglen, int direction); int chacha20poly1305_test(void); #endif /* LTC_CHACHA20POLY1305_MODE */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h000066400000000000000000000367541464416617300252340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #define LTC_TMPVAR__(n, l) n ## l #define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l) #define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__) /* ---- HELPER MACROS ---- */ #ifdef ENDIAN_NEUTRAL #define STORE32L(x, y) \ do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) #define LOAD32L(x, y) \ do { x = ((ulong32)((y)[3] & 255)<<24) | \ ((ulong32)((y)[2] & 255)<<16) | \ ((ulong32)((y)[1] & 255)<<8) | \ ((ulong32)((y)[0] & 255)); } while(0) #define STORE64L(x, y) \ do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) #define LOAD64L(x, y) \ do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) #define STORE32H(x, y) \ do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) #define LOAD32H(x, y) \ do { x = ((ulong32)((y)[0] & 255)<<24) | \ ((ulong32)((y)[1] & 255)<<16) | \ ((ulong32)((y)[2] & 255)<<8) | \ ((ulong32)((y)[3] & 255)); } while(0) #define STORE64H(x, y) \ do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) #define LOAD64H(x, y) \ do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0) #elif defined(ENDIAN_LITTLE) #ifdef LTC_HAVE_BSWAP_BUILTIN #define STORE32H(x, y) \ do { ulong32 ttt = __builtin_bswap32 ((x)); \ XMEMCPY ((y), &ttt, 4); } while(0) #define LOAD32H(x, y) \ do { XMEMCPY (&(x), (y), 4); \ (x) = __builtin_bswap32 ((x)); } while(0) #elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__)))) #define STORE32H(x, y) \ asm __volatile__ ( \ "bswapl %0 \n\t" \ "movl %0,(%1)\n\t" \ "bswapl %0 \n\t" \ ::"r"(x), "r"(y): "memory"); #define LOAD32H(x, y) \ asm __volatile__ ( \ "movl (%1),%0\n\t" \ "bswapl %0\n\t" \ :"=r"(x): "r"(y): "memory"); #else #define STORE32H(x, y) \ do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) #define LOAD32H(x, y) \ do { x = ((ulong32)((y)[0] & 255)<<24) | \ ((ulong32)((y)[1] & 255)<<16) | \ ((ulong32)((y)[2] & 255)<<8) | \ ((ulong32)((y)[3] & 255)); } while(0) #endif #ifdef LTC_HAVE_BSWAP_BUILTIN #define STORE64H(x, y) \ do { ulong64 ttt = __builtin_bswap64 ((x)); \ XMEMCPY ((y), &ttt, 8); } while(0) #define LOAD64H(x, y) \ do { XMEMCPY (&(x), (y), 8); \ (x) = __builtin_bswap64 ((x)); } while(0) /* x86_64 processor */ #elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) #define STORE64H(x, y) \ asm __volatile__ ( \ "bswapq %0 \n\t" \ "movq %0,(%1)\n\t" \ "bswapq %0 \n\t" \ ::"r"(x), "r"(y): "memory"); #define LOAD64H(x, y) \ asm __volatile__ ( \ "movq (%1),%0\n\t" \ "bswapq %0\n\t" \ :"=r"(x): "r"(y): "memory"); #else #define STORE64H(x, y) \ do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) #define LOAD64H(x, y) \ do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0) #endif #ifdef ENDIAN_32BITWORD #define STORE32L(x, y) \ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) #define LOAD32L(x, y) \ do { XMEMCPY(&(x), y, 4); } while(0) #define STORE64L(x, y) \ do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) #define LOAD64L(x, y) \ do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) #else /* 64-bit words then */ #define STORE32L(x, y) \ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) #define LOAD32L(x, y) \ do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) #define STORE64L(x, y) \ do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) #define LOAD64L(x, y) \ do { XMEMCPY(&(x), y, 8); } while(0) #endif /* ENDIAN_64BITWORD */ #elif defined(ENDIAN_BIG) #define STORE32L(x, y) \ do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) #define LOAD32L(x, y) \ do { x = ((ulong32)((y)[3] & 255)<<24) | \ ((ulong32)((y)[2] & 255)<<16) | \ ((ulong32)((y)[1] & 255)<<8) | \ ((ulong32)((y)[0] & 255)); } while(0) #define STORE64L(x, y) \ do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) #define LOAD64L(x, y) \ do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) #ifdef ENDIAN_32BITWORD #define STORE32H(x, y) \ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) #define LOAD32H(x, y) \ do { XMEMCPY(&(x), y, 4); } while(0) #define STORE64H(x, y) \ do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) #define LOAD64H(x, y) \ do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0) #else /* 64-bit words then */ #define STORE32H(x, y) \ do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) #define LOAD32H(x, y) \ do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) #define STORE64H(x, y) \ do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) #define LOAD64H(x, y) \ do { XMEMCPY(&(x), y, 8); } while(0) #endif /* ENDIAN_64BITWORD */ #endif /* ENDIAN_BIG */ #define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) /* 32-bit Rotates */ #if defined(_MSC_VER) #define LTC_ROx_BUILTIN /* instrinsic rotate */ #include #pragma intrinsic(_rotr,_rotl) #define ROR(x,n) _rotr(x,n) #define ROL(x,n) _rotl(x,n) #define RORc(x,n) ROR(x,n) #define ROLc(x,n) ROL(x,n) #elif defined(LTC_HAVE_ROTATE_BUILTIN) #define LTC_ROx_BUILTIN #define ROR(x,n) __builtin_rotateright32(x,n) #define ROL(x,n) __builtin_rotateleft32(x,n) #define ROLc(x,n) ROL(x,n) #define RORc(x,n) ROR(x,n) #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) #define LTC_ROx_ASM static inline ulong32 ROL(ulong32 word, int i) { asm ("roll %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } static inline ulong32 ROR(ulong32 word, int i) { asm ("rorl %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } #ifndef LTC_NO_ROLC #define ROLc(word,i) ({ \ ulong32 LTC_TMPVAR(ROLc) = (word); \ __asm__ ("roll %2, %0" : \ "=r" (LTC_TMPVAR(ROLc)) : \ "0" (LTC_TMPVAR(ROLc)), \ "I" (i)); \ LTC_TMPVAR(ROLc); \ }) #define RORc(word,i) ({ \ ulong32 LTC_TMPVAR(RORc) = (word); \ __asm__ ("rorl %2, %0" : \ "=r" (LTC_TMPVAR(RORc)) : \ "0" (LTC_TMPVAR(RORc)), \ "I" (i)); \ LTC_TMPVAR(RORc); \ }) #else #define ROLc ROL #define RORc ROR #endif #elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) #define LTC_ROx_ASM static inline ulong32 ROL(ulong32 word, int i) { asm ("rotlw %0,%0,%2" :"=r" (word) :"0" (word),"r" (i)); return word; } static inline ulong32 ROR(ulong32 word, int i) { asm ("rotlw %0,%0,%2" :"=r" (word) :"0" (word),"r" (32-i)); return word; } #ifndef LTC_NO_ROLC static inline ulong32 ROLc(ulong32 word, const int i) { asm ("rotlwi %0,%0,%2" :"=r" (word) :"0" (word),"I" (i)); return word; } static inline ulong32 RORc(ulong32 word, const int i) { asm ("rotrwi %0,%0,%2" :"=r" (word) :"0" (word),"I" (i)); return word; } #else #define ROLc ROL #define RORc ROR #endif #else /* rotates the hard way */ #define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) #define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) #define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) #define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) #endif /* 64-bit Rotates */ #if defined(_MSC_VER) /* instrinsic rotate */ #include #pragma intrinsic(_rotr64,_rotr64) #define ROR64(x,n) _rotr64(x,n) #define ROL64(x,n) _rotl64(x,n) #define ROR64c(x,n) ROR64(x,n) #define ROL64c(x,n) ROL64(x,n) #elif defined(LTC_HAVE_ROTATE_BUILTIN) #define ROR64(x,n) __builtin_rotateright64(x,n) #define ROL64(x,n) __builtin_rotateleft64(x,n) #define ROR64c(x,n) ROR64(x,n) #define ROL64c(x,n) ROL64(x,n) #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) static inline ulong64 ROL64(ulong64 word, int i) { asm("rolq %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } static inline ulong64 ROR64(ulong64 word, int i) { asm("rorq %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; } #ifndef LTC_NO_ROLC #define ROL64c(word,i) ({ \ ulong64 LTC_TMPVAR(ROL64c) = word; \ __asm__ ("rolq %2, %0" : \ "=r" (LTC_TMPVAR(ROL64c)) : \ "0" (LTC_TMPVAR(ROL64c)), \ "J" (i)); \ LTC_TMPVAR(ROL64c); \ }) #define ROR64c(word,i) ({ \ ulong64 LTC_TMPVAR(ROR64c) = word; \ __asm__ ("rorq %2, %0" : \ "=r" (LTC_TMPVAR(ROR64c)) : \ "0" (LTC_TMPVAR(ROR64c)), \ "J" (i)); \ LTC_TMPVAR(ROR64c); \ }) #else /* LTC_NO_ROLC */ #define ROL64c ROL64 #define ROR64c ROR64 #endif #else /* Not x86_64 */ #define ROL64(x, y) \ ( (((x)<<((ulong64)(y)&63)) | \ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) #define ROR64(x, y) \ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) #define ROL64c(x, y) \ ( (((x)<<((ulong64)(y)&63)) | \ (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) #define ROR64c(x, y) \ ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) #endif #ifndef MAX #define MAX(x, y) ( ((x)>(y))?(x):(y) ) #endif #ifndef MIN #define MIN(x, y) ( ((x)<(y))?(x):(y) ) #endif #ifndef LTC_UNUSED_PARAM #define LTC_UNUSED_PARAM(x) (void)(x) #endif /* there is no snprintf before Visual C++ 2015 */ #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_math.h000066400000000000000000000410051464416617300246620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** math functions **/ #define LTC_MP_LT -1 #define LTC_MP_EQ 0 #define LTC_MP_GT 1 #define LTC_MP_NO 0 #define LTC_MP_YES 1 #ifndef LTC_MECC typedef void ecc_point; #endif #ifndef LTC_MRSA typedef void rsa_key; #endif #ifndef LTC_MILLER_RABIN_REPS /* Number of rounds of the Miller-Rabin test * "Reasonable values of reps are between 15 and 50." c.f. gmp doc of mpz_probab_prime_p() * As of https://security.stackexchange.com/a/4546 we should use 40 rounds */ #define LTC_MILLER_RABIN_REPS 40 #endif int radix_to_bin(const void *in, int radix, void *out, unsigned long *len); /** math descriptor */ typedef struct { /** Name of the math provider */ const char *name; /** Bits per digit, amount of bits must fit in an unsigned long */ int bits_per_digit; /* ---- init/deinit functions ---- */ /** initialize a bignum @param a The number to initialize @return CRYPT_OK on success */ int (*init)(void **a); /** initialize a bignum @param size_bits The size of the number we compute on @param a The number to initialize @return CRYPT_OK on success */ int (*init_size)(int size_bits, void **a); /** init copy @param dst The number to initialize and write to @param src The number to copy from @return CRYPT_OK on success */ int (*init_copy)(void **dst, void *src); /** deinit @param a The number to free @return CRYPT_OK on success */ void (*deinit)(void *a); /* ---- data movement ---- */ /** negate @param src The number to negate @param dst The destination @return CRYPT_OK on success */ int (*neg)(void *src, void *dst); /** copy @param src The number to copy from @param dst The number to write to @return CRYPT_OK on success */ int (*copy)(void *src, void *dst); /* ---- trivial low level functions ---- */ /** set small constant @param a Number to write to @param n Source upto bits_per_digit (actually meant for very small constants) @return CRYPT_OK on success */ int (*set_int)(void *a, ltc_mp_digit n); /** get small constant @param a Small number to read, only fetches up to bits_per_digit from the number @return The lower bits_per_digit of the integer (unsigned) */ unsigned long (*get_int)(void *a); /** get digit n @param a The number to read from @param n The number of the digit to fetch @return The bits_per_digit sized n'th digit of a */ ltc_mp_digit (*get_digit)(void *a, int n); /** Get the number of digits that represent the number @param a The number to count @return The number of digits used to represent the number */ int (*get_digit_count)(void *a); /** compare two integers @param a The left side integer @param b The right side integer @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) */ int (*compare)(void *a, void *b); /** compare against int @param a The left side integer @param b The right side integer (upto bits_per_digit) @return LTC_MP_LT if a < b, LTC_MP_GT if a > b and LTC_MP_EQ otherwise. (signed comparison) */ int (*compare_d)(void *a, ltc_mp_digit n); /** Count the number of bits used to represent the integer @param a The integer to count @return The number of bits required to represent the integer */ int (*count_bits)(void * a); /** Count the number of LSB bits which are zero @param a The integer to count @return The number of contiguous zero LSB bits */ int (*count_lsb_bits)(void *a); /** Compute a power of two @param a The integer to store the power in @param n The power of two you want to store (a = 2^n) @return CRYPT_OK on success */ int (*twoexpt)(void *a , int n); /* ---- radix conversions ---- */ /** read ascii string @param a The integer to store into @param str The string to read @param radix The radix the integer has been represented in (2-64) @return CRYPT_OK on success */ int (*read_radix)(void *a, const char *str, int radix); /** write number to string @param a The integer to store @param str The destination for the string @param radix The radix the integer is to be represented in (2-64) @return CRYPT_OK on success */ int (*write_radix)(void *a, char *str, int radix); /** get size as unsigned char string @param a The integer to get the size (when stored in array of octets) @return The length of the integer in octets */ unsigned long (*unsigned_size)(void *a); /** store an integer as an array of octets @param src The integer to store @param dst The buffer to store the integer in @return CRYPT_OK on success */ int (*unsigned_write)(void *src, unsigned char *dst); /** read an array of octets and store as integer @param dst The integer to load @param src The array of octets @param len The number of octets @return CRYPT_OK on success */ int (*unsigned_read)( void *dst, unsigned char *src, unsigned long len); /* ---- basic math ---- */ /** add two integers @param a The first source integer @param b The second source integer @param c The destination of "a + b" @return CRYPT_OK on success */ int (*add)(void *a, void *b, void *c); /** add two integers @param a The first source integer @param b The second source integer (single digit of upto bits_per_digit in length) @param c The destination of "a + b" @return CRYPT_OK on success */ int (*addi)(void *a, ltc_mp_digit b, void *c); /** subtract two integers @param a The first source integer @param b The second source integer @param c The destination of "a - b" @return CRYPT_OK on success */ int (*sub)(void *a, void *b, void *c); /** subtract two integers @param a The first source integer @param b The second source integer (single digit of upto bits_per_digit in length) @param c The destination of "a - b" @return CRYPT_OK on success */ int (*subi)(void *a, ltc_mp_digit b, void *c); /** multiply two integers @param a The first source integer @param b The second source integer (single digit of upto bits_per_digit in length) @param c The destination of "a * b" @return CRYPT_OK on success */ int (*mul)(void *a, void *b, void *c); /** multiply two integers @param a The first source integer @param b The second source integer (single digit of upto bits_per_digit in length) @param c The destination of "a * b" @return CRYPT_OK on success */ int (*muli)(void *a, ltc_mp_digit b, void *c); /** Square an integer @param a The integer to square @param b The destination @return CRYPT_OK on success */ int (*sqr)(void *a, void *b); /** Square root (mod prime) @param a The integer to compute square root mod prime from @param b The prime @param c The destination @return CRYPT_OK on success */ int (*sqrtmod_prime)(void *a, void *b, void *c); /** Divide an integer @param a The dividend @param b The divisor @param c The quotient (can be NULL to signify don't care) @param d The remainder (can be NULL to signify don't care) @return CRYPT_OK on success */ int (*mpdiv)(void *a, void *b, void *c, void *d); /** divide by two @param a The integer to divide (shift right) @param b The destination @return CRYPT_OK on success */ int (*div_2)(void *a, void *b); /** Get remainder (small value) @param a The integer to reduce @param b The modulus (upto bits_per_digit in length) @param c The destination for the residue @return CRYPT_OK on success */ int (*modi)(void *a, ltc_mp_digit b, ltc_mp_digit *c); /** gcd @param a The first integer @param b The second integer @param c The destination for (a, b) @return CRYPT_OK on success */ int (*gcd)(void *a, void *b, void *c); /** lcm @param a The first integer @param b The second integer @param c The destination for [a, b] @return CRYPT_OK on success */ int (*lcm)(void *a, void *b, void *c); /** Modular multiplication @param a The first source @param b The second source @param c The modulus @param d The destination (a*b mod c) @return CRYPT_OK on success */ int (*mulmod)(void *a, void *b, void *c, void *d); /** Modular squaring @param a The first source @param b The modulus @param c The destination (a*a mod b) @return CRYPT_OK on success */ int (*sqrmod)(void *a, void *b, void *c); /** Modular inversion @param a The value to invert @param b The modulus @param c The destination (1/a mod b) @return CRYPT_OK on success */ int (*invmod)(void *, void *, void *); /* ---- reduction ---- */ /** setup Montgomery @param a The modulus @param b The destination for the reduction digit @return CRYPT_OK on success */ int (*montgomery_setup)(void *a, void **b); /** get normalization value @param a The destination for the normalization value @param b The modulus @return CRYPT_OK on success */ int (*montgomery_normalization)(void *a, void *b); /** reduce a number @param a The number [and dest] to reduce @param b The modulus @param c The value "b" from montgomery_setup() @return CRYPT_OK on success */ int (*montgomery_reduce)(void *a, void *b, void *c); /** clean up (frees memory) @param a The value "b" from montgomery_setup() @return CRYPT_OK on success */ void (*montgomery_deinit)(void *a); /* ---- exponentiation ---- */ /** Modular exponentiation @param a The base integer @param b The power (can be negative) integer @param c The modulus integer @param d The destination @return CRYPT_OK on success */ int (*exptmod)(void *a, void *b, void *c, void *d); /** Primality testing @param a The integer to test @param b The number of Miller-Rabin tests that shall be executed @param c The destination of the result (FP_YES if prime) @return CRYPT_OK on success */ int (*isprime)(void *a, int b, int *c); /* ---- (optional) ecc point math ---- */ /** ECC GF(p) point multiplication (from the NIST curves) @param k The integer to multiply the point by @param G The point to multiply @param R The destination for kG @param a ECC curve parameter a @param modulus The modulus for the field @param map Boolean indicated whether to map back to affine or not (can be ignored if you work in affine only) @return CRYPT_OK on success */ int (*ecc_ptmul)( void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map); /** ECC GF(p) point addition @param P The first point @param Q The second point @param R The destination of P + Q @param ma The curve parameter "a" in montgomery form @param modulus The modulus @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ int (*ecc_ptadd)(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp); /** ECC GF(p) point double @param P The first point @param R The destination of 2P @param ma The curve parameter "a" in montgomery form @param modulus The modulus @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ int (*ecc_ptdbl)(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp); /** ECC mapping from projective to affine, currently uses (x,y,z) => (x/z^2, y/z^3, 1) @param P The point to map @param modulus The modulus @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success @remark The mapping can be different but keep in mind a ecc_point only has three integers (x,y,z) so if you use a different mapping you have to make it fit. */ int (*ecc_map)(ecc_point *P, void *modulus, void *mp); /** Computes kA*A + kB*B = C using Shamir's Trick @param A First point to multiply @param kA What to multiple A by @param B Second point to multiply @param kB What to multiple B by @param C [out] Destination point (can overlap with A or B) @param ma The curve parameter "a" in montgomery form @param modulus Modulus for curve @return CRYPT_OK on success */ int (*ecc_mul2add)(const ecc_point *A, void *kA, const ecc_point *B, void *kB, ecc_point *C, void *ma, void *modulus); /* ---- (optional) rsa optimized math (for internal CRT) ---- */ /** RSA Key Generation @param prng An active PRNG state @param wprng The index of the PRNG desired @param size The size of the key in octets @param e The "e" value (public key). e==65537 is a good choice @param key [out] Destination of a newly created private key pair @return CRYPT_OK if successful, upon error all allocated ram is freed */ int (*rsa_keygen)(prng_state *prng, int wprng, int size, long e, rsa_key *key); /** RSA exponentiation @param in The octet array representing the base @param inlen The length of the input @param out The destination (to be stored in an octet array format) @param outlen The length of the output buffer and the resulting size (zero padded to the size of the modulus) @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA @param key The RSA key to use @return CRYPT_OK on success */ int (*rsa_me)(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int which, const rsa_key *key); /* ---- basic math continued ---- */ /** Modular addition @param a The first source @param b The second source @param c The modulus @param d The destination (a + b mod c) @return CRYPT_OK on success */ int (*addmod)(void *a, void *b, void *c, void *d); /** Modular substraction @param a The first source @param b The second source @param c The modulus @param d The destination (a - b mod c) @return CRYPT_OK on success */ int (*submod)(void *a, void *b, void *c, void *d); /* ---- misc stuff ---- */ /** Make a pseudo-random mpi @param a The mpi to make random @param size The desired length @return CRYPT_OK on success */ int (*rand)(void *a, int size); } ltc_math_descriptor; extern ltc_math_descriptor ltc_mp; int ltc_init_multi(void **a, ...) LTC_NULL_TERMINATED; int ltc_init_multi_size(int size_bits, void **a, ...) LTC_NULL_TERMINATED; void ltc_deinit_multi(void *a, ...) LTC_NULL_TERMINATED; void ltc_cleanup_multi(void **a, ...) LTC_NULL_TERMINATED; #ifdef LTM_DESC extern const ltc_math_descriptor ltm_desc; #endif #ifdef TFM_DESC extern const ltc_math_descriptor tfm_desc; #endif #ifdef GMP_DESC extern const ltc_math_descriptor gmp_desc; #endif optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_misc.h000066400000000000000000000143611464416617300246710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* ---- LTC_BASE64 Routines ---- */ #ifdef LTC_BASE64 int base64_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen); int base64_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int base64_strict_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int base64_sane_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); #endif #ifdef LTC_BASE64_URL int base64url_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen); int base64url_strict_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen); int base64url_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int base64url_strict_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int base64url_sane_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); #endif /* ---- BASE32 Routines ---- */ #ifdef LTC_BASE32 typedef enum { BASE32_RFC4648 = 0, BASE32_BASE32HEX = 1, BASE32_ZBASE32 = 2, BASE32_CROCKFORD = 3 } base32_alphabet; int base32_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, base32_alphabet id); int base32_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, base32_alphabet id); #endif /* ---- BASE16 Routines ---- */ #ifdef LTC_BASE16 int base16_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, unsigned int options); int base16_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); #endif #ifdef LTC_BCRYPT int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, const unsigned char *salt, unsigned long salt_len, unsigned int rounds, int hash_idx, unsigned char *out, unsigned long *outlen); #endif /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ #ifdef LTC_HKDF int hkdf_test(void); int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen); int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen); #endif /* LTC_HKDF */ /* ---- MEM routines ---- */ int mem_neq(const void *a, const void *b, size_t len); void zeromem(volatile void *out, size_t outlen); void burn_stack(unsigned long len); const char *error_to_string(int err); extern const char *crypt_build_settings; /* ---- HMM ---- */ int crypt_fsa(void *mp, ...) LTC_NULL_TERMINATED; /* ---- Dynamic language support ---- */ int crypt_get_constant(const char* namein, int *valueout); int crypt_list_all_constants(char *names_list, unsigned int *names_list_size); int crypt_get_size(const char* namein, unsigned int *sizeout); int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size); #ifdef LTM_DESC LTC_DEPRECATED(crypt_mp_init) void init_LTM(void); #endif #ifdef TFM_DESC LTC_DEPRECATED(crypt_mp_init) void init_TFM(void); #endif #ifdef GMP_DESC LTC_DEPRECATED(crypt_mp_init) void init_GMP(void); #endif int crypt_mp_init(const char* mpi); #ifdef LTC_ADLER32 typedef struct adler32_state_s { unsigned short s[2]; } adler32_state; void adler32_init(adler32_state *ctx); void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length); void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size); int adler32_test(void); #endif #ifdef LTC_CRC32 typedef struct crc32_state_s { ulong32 crc; } crc32_state; void crc32_init(crc32_state *ctx); void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length); void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size); int crc32_test(void); #endif #ifdef LTC_PADDING enum padding_type { LTC_PAD_PKCS7 = 0x0000U, #ifdef LTC_RNG_GET_BYTES LTC_PAD_ISO_10126 = 0x1000U, #endif LTC_PAD_ANSI_X923 = 0x2000U, LTC_PAD_SSH = 0x3000U, /* The following padding modes don't contain the padding * length as last byte of the padding. */ LTC_PAD_ONE_AND_ZERO = 0x8000U, LTC_PAD_ZERO = 0x9000U, LTC_PAD_ZERO_ALWAYS = 0xA000U, }; int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode); int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode); #endif /* LTC_PADDING */ #ifdef LTC_SSH typedef enum ssh_data_type_ { LTC_SSHDATA_EOL, LTC_SSHDATA_BYTE, LTC_SSHDATA_BOOLEAN, LTC_SSHDATA_UINT32, LTC_SSHDATA_UINT64, LTC_SSHDATA_STRING, LTC_SSHDATA_MPINT, LTC_SSHDATA_NAMELIST, } ssh_data_type; /* VA list handy helpers with tuples of */ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED; #endif /* LTC_SSH */ int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h000066400000000000000000001011531464416617300243440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* ---- NUMBER THEORY ---- */ enum public_key_type { /* Refers to the public key */ PK_PUBLIC = 0x0000, /* Refers to the private key */ PK_PRIVATE = 0x0001, /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */ PK_STD = 0x1000, /* Indicates compressed public ECC key */ PK_COMPRESSED = 0x2000, /* Indicates ECC key with the curve specified by OID */ PK_CURVEOID = 0x4000 }; int rand_prime(void *N, long len, prng_state *prng, int wprng); /* ---- RSA ---- */ #ifdef LTC_MRSA /** RSA PKCS style key */ typedef struct Rsa_key { /** Type of key, PK_PRIVATE or PK_PUBLIC */ int type; /** The public exponent */ void *e; /** The private exponent */ void *d; /** The modulus */ void *N; /** The p factor of N */ void *p; /** The q factor of N */ void *q; /** The 1/q mod p CRT param */ void *qP; /** The d mod (p - 1) CRT param */ void *dP; /** The d mod (q - 1) CRT param */ void *dQ; } rsa_key; int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size, const unsigned char *e, unsigned long elen, rsa_key *key); int rsa_get_size(const rsa_key *key); int rsa_exptmod(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int which, const rsa_key *key); void rsa_free(rsa_key *key); /* These use PKCS #1 v2.0 padding */ #define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \ rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key) #define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \ rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key) #define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \ rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) #define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \ rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key) #define rsa_sign_saltlen_get_max(hash_idx, key) \ rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) /* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, prng_state *prng, int prng_idx, int mgf_hash, int lparam_hash, int padding, const rsa_key *key); int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, int mgf_hash, int lparam_hash, int padding, int *stat, const rsa_key *key); int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, prng_state *prng, int prng_idx, int hash_idx, unsigned long saltlen, const rsa_key *key); int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, int hash_idx, unsigned long saltlen, int *stat, const rsa_key *key); int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); /* PKCS #1 import/export */ int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key); int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key); int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *passwd, unsigned long passwdlen, rsa_key *key); int rsa_set_key(const unsigned char *N, unsigned long Nlen, const unsigned char *e, unsigned long elen, const unsigned char *d, unsigned long dlen, rsa_key *key); int rsa_set_factors(const unsigned char *p, unsigned long plen, const unsigned char *q, unsigned long qlen, rsa_key *key); int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, const unsigned char *dQ, unsigned long dQlen, const unsigned char *qP, unsigned long qPlen, rsa_key *key); #endif /* ---- DH Routines ---- */ #ifdef LTC_MDH typedef struct { int type; void *x; void *y; void *base; void *prime; } dh_key; int dh_get_groupsize(const dh_key *key); int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key); int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); int dh_set_pg(const unsigned char *p, unsigned long plen, const unsigned char *g, unsigned long glen, dh_key *key); int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key); int dh_set_pg_groupsize(int groupsize, dh_key *key); int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key); int dh_generate_key(prng_state *prng, int wprng, dh_key *key); int dh_make_key(prng_state *prng, int wprng, void *q, int xbits, dh_key *key); /* OP-TEE */ int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, unsigned char *out, unsigned long *outlen); void dh_free(dh_key *key); int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key); #endif /* LTC_MDH */ /* ---- ECC Routines ---- */ #ifdef LTC_MECC /* size of our temp buffers for exported keys */ #define ECC_BUF_SIZE 256 /* max private key size */ #define ECC_MAXSIZE 66 /** Structure defines a GF(p) curve */ typedef struct { /** The prime that defines the field the curve is in (encoded in hex) */ const char *prime; /** The fields A param (hex) */ const char *A; /** The fields B param (hex) */ const char *B; /** The order of the curve (hex) */ const char *order; /** The x co-ordinate of the base point on the curve (hex) */ const char *Gx; /** The y co-ordinate of the base point on the curve (hex) */ const char *Gy; /** The co-factor */ unsigned long cofactor; /** The OID */ const char *OID; } ltc_ecc_curve; /** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ typedef struct { /** The x co-ordinate */ void *x; /** The y co-ordinate */ void *y; /** The z co-ordinate */ void *z; } ecc_point; /** ECC key's domain parameters */ typedef struct { /** The size of the curve in octets */ int size; /** The prime that defines the field the curve is in */ void *prime; /** The fields A param */ void *A; /** The fields B param */ void *B; /** The order of the curve */ void *order; /** The base point G on the curve */ ecc_point base; /** The co-factor */ unsigned long cofactor; /** The OID */ unsigned long oid[16]; unsigned long oidlen; } ltc_ecc_dp; /** An ECC key */ typedef struct { /** Type of key, PK_PRIVATE or PK_PUBLIC */ int type; /** Structure with domain parameters */ ltc_ecc_dp dp; /** Structure with the public key */ ecc_point pubkey; /** The private key */ void *k; } ecc_key; /** Formats of ECC signatures */ typedef enum ecc_signature_type_ { /* ASN.1 encoded, ANSI X9.62 */ LTC_ECCSIG_ANSIX962 = 0x0, /* raw R, S values */ LTC_ECCSIG_RFC7518 = 0x1, /* raw R, S, V (+27) values */ LTC_ECCSIG_ETH27 = 0x2, /* SSH + ECDSA signature format defined by RFC5656 */ LTC_ECCSIG_RFC5656 = 0x3, } ecc_signature_type; /** the ECC params provided */ extern const ltc_ecc_curve ltc_ecc_curves[]; void ecc_sizes(int *low, int *high); int ecc_get_size(const ecc_key *key); int ecc_find_curve(const char* name_or_oid, const ltc_ecc_curve** cu); int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key); int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key); int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key); int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu); void ecc_free(ecc_key *key); int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu); int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen); int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu); int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key); int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key); int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key); int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, unsigned char *out, unsigned long *outlen); int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, const ecc_key *key); int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const ecc_key *key); #define ecc_sign_hash_rfc7518(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \ ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_RFC7518, NULL, key_) #define ecc_sign_hash(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \ ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_ANSIX962, NULL, key_) #define ecc_verify_hash_rfc7518(sig_, siglen_, hash_, hashlen_, stat_, key_) \ ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_RFC7518, stat_, key_) #define ecc_verify_hash(sig_, siglen_, hash_, hashlen_, stat_, key_) \ ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_ANSIX962, stat_, key_) int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, ecc_signature_type sigformat, int *recid, const ecc_key *key); int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, ecc_signature_type sigformat, int *stat, const ecc_key *key); int ecc_recover_key(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int recid, ecc_signature_type sigformat, ecc_key *key); #endif #ifdef LTC_CURVE25519 typedef struct { /** The key type, PK_PRIVATE or PK_PUBLIC */ enum public_key_type type; /** The PK-algorithm, PKA_ED25519 or PKA_X25519 */ /** This was supposed to be: * enum public_key_algorithms algo; * but that enum is now in tomcrypt_private.h */ int algo; /** The private key */ unsigned char priv[32]; /** The public key */ unsigned char pub[32]; } curve25519_key; /** Ed25519 Signature API */ int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key); int ed25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key); int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key); int ed25519_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const curve25519_key *private_key); int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const unsigned char *ctx, unsigned long ctxlen, const curve25519_key *private_key); int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const unsigned char *ctx, unsigned long ctxlen, const curve25519_key *private_key); int ed25519_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, int *stat, const curve25519_key *public_key); int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, const unsigned char *ctx, unsigned long ctxlen, int *stat, const curve25519_key *public_key); int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, const unsigned char *ctx, unsigned long ctxlen, int *stat, const curve25519_key *public_key); /** X25519 Key-Exchange API */ int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); int x25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key); int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key); int x25519_shared_secret(const curve25519_key *private_key, const curve25519_key *public_key, unsigned char *out, unsigned long *outlen); #endif /* LTC_CURVE25519 */ #ifdef LTC_MDSA /* Max diff between group and modulus size in bytes (max case: L=8192bits, N=256bits) */ #define LTC_MDSA_DELTA 992 /* Max DSA group size in bytes */ #define LTC_MDSA_MAX_GROUP 64 /* Max DSA modulus size in bytes (the actual DSA size, max 8192 bits) */ #define LTC_MDSA_MAX_MODULUS 1024 /** DSA key structure */ typedef struct { /** The key type, PK_PRIVATE or PK_PUBLIC */ int type; /** The order of the sub-group used in octets */ int qord; /** The generator */ void *g; /** The prime used to generate the sub-group */ void *q; /** The large prime that generats the field the contains the sub-group */ void *p; /** The private key */ void *x; /** The public key */ void *y; } dsa_key; int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); int dsa_set_pqg(const unsigned char *p, unsigned long plen, const unsigned char *q, unsigned long qlen, const unsigned char *g, unsigned long glen, dsa_key *key); int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key); int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key); int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key); void dsa_free(dsa_key *key); int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, void *r, void *s, prng_state *prng, int wprng, const dsa_key *key); int dsa_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, const dsa_key *key); int dsa_verify_hash_raw( void *r, void *s, const unsigned char *hash, unsigned long hashlen, int *stat, const dsa_key *key); int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, const dsa_key *key); int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, const dsa_key *key); int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const dsa_key *key); int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key); int dsa_verify_key(const dsa_key *key, int *stat); int dsa_shared_secret(void *private_key, void *base, const dsa_key *public_key, unsigned char *out, unsigned long *outlen); #endif /* LTC_MDSA */ #ifdef LTC_DER /* DER handling */ typedef enum ltc_asn1_type_ { /* 0 */ LTC_ASN1_EOL, LTC_ASN1_BOOLEAN, LTC_ASN1_INTEGER, LTC_ASN1_SHORT_INTEGER, LTC_ASN1_BIT_STRING, /* 5 */ LTC_ASN1_OCTET_STRING, LTC_ASN1_NULL, LTC_ASN1_OBJECT_IDENTIFIER, LTC_ASN1_IA5_STRING, LTC_ASN1_PRINTABLE_STRING, /* 10 */ LTC_ASN1_UTF8_STRING, LTC_ASN1_UTCTIME, LTC_ASN1_CHOICE, LTC_ASN1_SEQUENCE, LTC_ASN1_SET, /* 15 */ LTC_ASN1_SETOF, LTC_ASN1_RAW_BIT_STRING, LTC_ASN1_TELETEX_STRING, LTC_ASN1_GENERALIZEDTIME, LTC_ASN1_CUSTOM_TYPE, } ltc_asn1_type; typedef enum { LTC_ASN1_CL_UNIVERSAL = 0x0, LTC_ASN1_CL_APPLICATION = 0x1, LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2, LTC_ASN1_CL_PRIVATE = 0x3, } ltc_asn1_class; typedef enum { LTC_ASN1_PC_PRIMITIVE = 0x0, LTC_ASN1_PC_CONSTRUCTED = 0x1, } ltc_asn1_pc; /** A LTC ASN.1 list type */ typedef struct ltc_asn1_list_ { /** The LTC ASN.1 enumerated type identifier */ ltc_asn1_type type; /** The data to encode or place for decoding */ void *data; /** The size of the input or resulting output */ unsigned long size; /** The used flag * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made * 2. This is used by the ASN.1 decoder to indicate if an element is used * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */ int used; /** Flag used to indicate optional items in ASN.1 sequences */ int optional; /** ASN.1 identifier */ ltc_asn1_class klass; ltc_asn1_pc pc; ulong64 tag; /** prev/next entry in the list */ struct ltc_asn1_list_ *prev, *next, *child, *parent; } ltc_asn1_list; #define LTC_SET_ASN1(list, index, Type, Data, Size) \ do { \ int LTC_TMPVAR(SA) = (index); \ ltc_asn1_list *LTC_TMPVAR(SA_list) = (list); \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].type = (Type); \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].data = (void*)(Data); \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].size = (Size); \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].used = 0; \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].optional = 0; \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].klass = 0; \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].pc = 0; \ LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].tag = 0; \ } while (0) #define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ do { \ int LTC_TMPVAR(SAI) = (index); \ ltc_asn1_list *LTC_TMPVAR(SAI_list) = (list); \ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].type = LTC_ASN1_CUSTOM_TYPE; \ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].klass = (Class); \ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].pc = (Pc); \ LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].tag = (Tag); \ } while (0) #define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ do { \ int LTC_TMPVAR(SACC) = (index); \ LTC_SET_ASN1(list, LTC_TMPVAR(SACC), LTC_ASN1_CUSTOM_TYPE, Data, 1); \ LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACC), Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ } while (0) #define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ do { \ int LTC_TMPVAR(SACP) = (index); \ LTC_SET_ASN1(list, LTC_TMPVAR(SACP), LTC_ASN1_CUSTOM_TYPE, Data, Size); \ LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACP), Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ list[LTC_TMPVAR(SACP)].used = (int)(Type); \ } while (0) extern const char* der_asn1_class_to_string_map[]; extern const unsigned long der_asn1_class_to_string_map_sz; extern const char* der_asn1_pc_to_string_map[]; extern const unsigned long der_asn1_pc_to_string_map_sz; extern const char* der_asn1_tag_to_string_map[]; extern const unsigned long der_asn1_tag_to_string_map_sz; /* SEQUENCE */ int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen, int type_of); #define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) /** The supported bitmap for all the * decoders with a `flags` argument. */ enum ltc_der_seq { LTC_DER_SEQ_ZERO = 0x0u, /** Bit0 - [0]=Unordered (SET or SETOF) * [1]=Ordered (SEQUENCE) */ LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO, LTC_DER_SEQ_ORDERED = 0x1u, /** Bit1 - [0]=Relaxed * [1]=Strict */ LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO, LTC_DER_SEQ_STRICT = 0x2u, /** Alternative naming */ LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED, LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED, }; int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, ltc_asn1_list *list, unsigned long outlen, unsigned int flags); #define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED) #define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT) int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, unsigned long *outlen); /* Custom-types */ int der_encode_custom_type(const ltc_asn1_list *root, unsigned char *out, unsigned long *outlen); int der_decode_custom_type(const unsigned char *in, unsigned long inlen, ltc_asn1_list *root); int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen); /* SET */ #define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET) #define der_length_set der_length_sequence int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen); /* VA list handy helpers with triplets of */ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; /* FLEXI DECODER handle unknown list decoder */ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); #define der_free_sequence_flexi der_sequence_free void der_sequence_free(ltc_asn1_list *in); void der_sequence_shrink(ltc_asn1_list *in); /* BOOLEAN */ int der_length_boolean(unsigned long *outlen); int der_encode_boolean(int in, unsigned char *out, unsigned long *outlen); int der_decode_boolean(const unsigned char *in, unsigned long inlen, int *out); /* INTEGER */ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen); int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num); int der_length_integer(void *num, unsigned long *outlen); /* INTEGER -- handy for 0..2^32-1 values */ int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); int der_length_short_integer(unsigned long num, unsigned long *outlen); /* BIT STRING */ int der_encode_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_decode_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_length_bit_string(unsigned long nbits, unsigned long *outlen); /* OCTET STRING */ int der_encode_octet_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_decode_octet_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_length_octet_string(unsigned long noctets, unsigned long *outlen); /* OBJECT IDENTIFIER */ int der_encode_object_identifier(const unsigned long *words, unsigned long nwords, unsigned char *out, unsigned long *outlen); int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, unsigned long *words, unsigned long *outlen); int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen); unsigned long der_object_identifier_bits(unsigned long x); /* IA5 STRING */ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); int der_ia5_char_encode(int c); int der_ia5_value_decode(int v); /* TELETEX STRING */ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); /* PRINTABLE STRING */ int der_encode_printable_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_decode_printable_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); int der_printable_char_encode(int c); int der_printable_value_decode(int v); /* UTF-8 */ #if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(__WCHAR_MAX__) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR) #if defined(__WCHAR_MAX__) #define LTC_WCHAR_MAX __WCHAR_MAX__ #else #include #define LTC_WCHAR_MAX WCHAR_MAX #endif /* please note that it might happen that LTC_WCHAR_MAX is undefined */ #else typedef ulong32 wchar_t; #define LTC_WCHAR_MAX 0xFFFFFFFF #endif int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, wchar_t *out, unsigned long *outlen); unsigned long der_utf8_charsize(const wchar_t c); int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen); /* CHOICE */ int der_decode_choice(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *list, unsigned long outlen); /* UTCTime */ typedef struct { unsigned YY, /* year */ MM, /* month */ DD, /* day */ hh, /* hour */ mm, /* minute */ ss, /* second */ off_dir, /* timezone offset direction 0 == +, 1 == - */ off_hh, /* timezone offset hours */ off_mm; /* timezone offset minutes */ } ltc_utctime; int der_encode_utctime(const ltc_utctime *utctime, unsigned char *out, unsigned long *outlen); int der_decode_utctime(const unsigned char *in, unsigned long *inlen, ltc_utctime *out); int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen); /* GeneralizedTime */ typedef struct { unsigned YYYY, /* year */ MM, /* month */ DD, /* day */ hh, /* hour */ mm, /* minute */ ss, /* second */ fs, /* fractional seconds */ off_dir, /* timezone offset direction 0 == +, 1 == - */ off_hh, /* timezone offset hours */ off_mm; /* timezone offset minutes */ } ltc_generalizedtime; int der_encode_generalizedtime(const ltc_generalizedtime *gtime, unsigned char *out, unsigned long *outlen); int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, ltc_generalizedtime *out); int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen); #endif optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h000066400000000000000000000107201464416617300246710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* PKCS Header Info */ /* ===> PKCS #1 -- RSA Cryptography <=== */ #ifdef LTC_PKCS_1 enum ltc_pkcs_1_v1_5_blocks { LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */ LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */ }; enum ltc_pkcs_1_paddings { LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */ LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */ LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */ }; int pkcs_1_mgf1( int hash_idx, const unsigned char *seed, unsigned long seedlen, unsigned char *mask, unsigned long masklen); int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); /* *** v1.5 padding */ int pkcs_1_v1_5_encode(const unsigned char *msg, unsigned long msglen, int block_type, unsigned long modulus_bitlen, prng_state *prng, int prng_idx, unsigned char *out, unsigned long *outlen); int pkcs_1_v1_5_decode(const unsigned char *msg, unsigned long msglen, int block_type, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen, int *is_valid); /* *** v2.1 padding */ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, prng_state *prng, int prng_idx, int mgf_hash, int lparam_hash, unsigned char *out, unsigned long *outlen); int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, int mgf_hash, int lparam_hash, unsigned char *out, unsigned long *outlen, int *res); int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, unsigned long saltlen, prng_state *prng, int prng_idx, int hash_idx, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen); int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, unsigned long saltlen, int hash_idx, unsigned long modulus_bitlen, int *res); #endif /* LTC_PKCS_1 */ /* ===> PKCS #5 -- Password Based Cryptography <=== */ #ifdef LTC_PKCS_5 /* Algorithm #1 (PBKDF1) */ int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, const unsigned char *salt, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen); /* Algorithm #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys. Compatible with EVP_BytesToKey() */ int pkcs_5_alg1_openssl(const unsigned char *password, unsigned long password_len, const unsigned char *salt, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen); /* Algorithm #2 (PBKDF2) */ int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, const unsigned char *salt, unsigned long salt_len, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen); int pkcs_5_test (void); #endif /* LTC_PKCS_5 */ optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_private.h000066400000000000000000000567231464416617300254200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt.h" /* * Internal Macros */ /* Static assertion */ #define LTC_STATIC_ASSERT(msg, cond) typedef char ltc_static_assert_##msg[(cond) ? 1 : -1]; #define LTC_PAD_MASK (0xF000U) #if defined(ENDIAN_64BITWORD) #define CONSTPTR(n) CONST64(n) #else #define CONSTPTR(n) n ## uL #endif LTC_STATIC_ASSERT(correct_CONSTPTR_size, sizeof(CONSTPTR(1)) == sizeof(void*)) /* Poor-man's `uintptr_t` since we can't use stdint.h * c.f. https://github.com/DCIT/perl-CryptX/issues/95#issuecomment-1745280962 */ typedef size_t ltc_uintptr; LTC_STATIC_ASSERT(correct_ltc_uintptr_size, sizeof(ltc_uintptr) == sizeof(void*)) /* Aligns a `unsigned char` buffer `buf` to `n` bytes and returns that aligned address. * Make sure that the buffer that is passed is huge enough. */ #define LTC_ALIGN_BUF(buf, n) ((void*)((ltc_uintptr)&((unsigned char*)(buf))[n - 1] & (~(CONSTPTR(n) - CONSTPTR(1))))) /* `NULL` as defined by the standard is not guaranteed to be of a pointer * type. In order to make sure that in vararg API's a pointer type is used, * define our own version and use that one internally. */ #ifndef LTC_NULL #define LTC_NULL ((void *)0) #endif /* * Internal Enums */ enum ltc_oid_id { LTC_OID_RSA, LTC_OID_DSA, LTC_OID_EC, LTC_OID_EC_PRIMEF, LTC_OID_X25519, LTC_OID_ED25519, }; /* * Internal Types */ typedef struct { int size; const char *name, *base, *prime; } ltc_dh_set_type; typedef int (*fn_kdf_t)(const unsigned char *password, unsigned long password_len, const unsigned char *salt, unsigned long salt_len, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen); typedef struct { /* KDF */ fn_kdf_t kdf; /* Hash or HMAC */ const char* h; /* cipher */ const char* c; unsigned long keylen; /* not used for pbkdf2 */ unsigned long blocklen; } pbes_properties; typedef struct { pbes_properties type; const void *pwd; unsigned long pwdlen; ltc_asn1_list *enc_data; ltc_asn1_list *salt; ltc_asn1_list *iv; unsigned long iterations; /* only used for RC2 */ unsigned long key_bits; } pbes_arg; /* * Internal functions */ /* tomcrypt_cipher.h */ #if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1) #define LTC_HAS_AES_NI #endif void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey); int blowfish_expand(const unsigned char *key, int keylen, const unsigned char *data, int datalen, symmetric_key *skey); int blowfish_setup_with_data(const unsigned char *key, int keylen, const unsigned char *data, int datalen, symmetric_key *skey); /* tomcrypt_hash.h */ /* a macro for making hash "process" functions */ #define HASH_PROCESS_(func_name, compress_name, compress_n_name, state_var, block_size) \ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ { \ unsigned long n, blocks; \ int err; \ int (*compress)(hash_state *, const unsigned char *) = compress_name; \ int (*compress_n)(hash_state *, const unsigned char *, int) = compress_n_name;\ LTC_ARGCHK(md != NULL); \ LTC_ARGCHK(in != NULL); \ if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ return CRYPT_INVALID_ARG; \ } \ if (((md-> state_var .length + inlen * 8) < md-> state_var .length) \ || ((inlen * 8) < inlen)) { \ return CRYPT_HASH_OVERFLOW; \ } \ while (inlen > 0) { \ if (md-> state_var .curlen == 0 && inlen >= block_size) { \ if (compress_n) { \ blocks = inlen / block_size; \ err = compress_n (md, in, blocks); \ } else { \ blocks = 1; \ err = compress (md, in); \ } \ if (err != CRYPT_OK) \ return err; \ md-> state_var .length += blocks * block_size * 8; \ in += blocks * block_size; \ inlen -= blocks * block_size; \ } else { \ n = MIN(inlen, (block_size - md-> state_var .curlen)); \ XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ md-> state_var .curlen += n; \ in += n; \ inlen -= n; \ if (md-> state_var .curlen == block_size) { \ if (compress_n) { \ err = compress_n (md, md-> state_var .buf, 1); \ } else { \ err = compress (md, md-> state_var .buf); \ } \ if (err != CRYPT_OK) { \ return err; \ } \ md-> state_var .length += 8*block_size; \ md-> state_var .curlen = 0; \ } \ } \ } \ return CRYPT_OK; \ } /* define a hash "process" function based on a 1-block compress function */ #define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ HASH_PROCESS_(func_name, compress_name, NULL, state_var, block_size) /* define a hash "process" function based on a n-block compress function */ #define HASH_PROCESS_NBLOCKS(func_name, compress_n_name, state_var, block_size) \ HASH_PROCESS_(func_name, NULL, compress_n_name, state_var, block_size) /* tomcrypt_mac.h */ int ocb3_int_ntz(unsigned long x); void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len); /* tomcrypt_math.h */ #if !defined(DESC_DEF_ONLY) #define MP_DIGIT_BIT ltc_mp.bits_per_digit /* some handy macros */ #define mp_init(a) ltc_mp.init(a) #define mp_init_multi ltc_init_multi #define mp_init_size(a, b) ltc_mp.init_size(a, b) #define mp_init_multi_size ltc_init_multi_size #define mp_clear(a) ltc_mp.deinit(a) #define mp_clear_multi ltc_deinit_multi #define mp_cleanup_multi ltc_cleanup_multi #define mp_init_copy(a, b) ltc_mp.init_copy(a, b) #define mp_neg(a, b) ltc_mp.neg(a, b) #define mp_copy(a, b) ltc_mp.copy(a, b) #define mp_set(a, b) ltc_mp.set_int(a, b) #define mp_set_int(a, b) ltc_mp.set_int(a, b) #define mp_get_int(a) ltc_mp.get_int(a) #define mp_get_digit(a, n) ltc_mp.get_digit(a, n) #define mp_get_digit_count(a) ltc_mp.get_digit_count(a) #define mp_cmp(a, b) ltc_mp.compare(a, b) #define mp_cmp_d(a, b) ltc_mp.compare_d(a, b) #define mp_count_bits(a) ltc_mp.count_bits(a) #define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a) #define mp_2expt(a, b) ltc_mp.twoexpt(a, b) #define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c) #define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c) #define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) #define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) #define mp_add(a, b, c) ltc_mp.add(a, b, c) #define mp_add_d(a, b, c) ltc_mp.addi(a, b, c) #define mp_sub(a, b, c) ltc_mp.sub(a, b, c) #define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c) #define mp_mul(a, b, c) ltc_mp.mul(a, b, c) #define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) #define mp_sqr(a, b) ltc_mp.sqr(a, b) #define mp_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c) #define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) #define mp_div_2(a, b) ltc_mp.div_2(a, b) #define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c) #define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c) #define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c) #define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c) #define mp_addmod(a, b, c, d) ltc_mp.addmod(a, b, c, d) #define mp_submod(a, b, c, d) ltc_mp.submod(a, b, c, d) #define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d) #define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c) #define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c) #define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b) #define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b) #define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c) #define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a) #define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) #define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, b, c) #define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO) #define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO) #define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0) #define mp_tohex(a, b) mp_toradix(a, b, 16) #define mp_rand(a, b) ltc_mp.rand(a, b) #endif /* tomcrypt_misc.h */ typedef enum { /** Use `\r\n` as line separator */ BASE64_PEM_CRLF = 1, /** Create output with 72 chars line length */ BASE64_PEM_SSH = 2, } base64_pem_flags; int base64_encode_pem(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, unsigned int flags); void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz); int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size); int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res); int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res); /* tomcrypt_pk.h */ int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng); int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng); int pk_get_oid(enum ltc_oid_id id, const char **st); int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen); int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen); /* ---- DH Routines ---- */ #ifdef LTC_MRSA int rsa_init(rsa_key *key); void rsa_shrink_key(rsa_key *key); int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key); /* used by op-tee */ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); #endif /* LTC_MRSA */ /* ---- DH Routines ---- */ #ifdef LTC_MDH extern const ltc_dh_set_type ltc_dh_sets[]; int dh_check_pubkey(const dh_key *key); #endif /* LTC_MDH */ /* ---- ECC Routines ---- */ #ifdef LTC_MECC int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key); int ecc_copy_curve(const ecc_key *srckey, ecc_key *key); int ecc_set_curve_by_size(int size, ecc_key *key); int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key); #ifdef LTC_SSH int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key); #endif /* low level functions */ ecc_point *ltc_ecc_new_point(void); void ltc_ecc_del_point(ecc_point *p); int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p); int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst); int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y); int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval); int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y); int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed); int ltc_ecc_verify_key(const ecc_key *key); /* point ops (mp == montgomery digit) */ #if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) /* R = 2P */ int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp); /* R = P + Q */ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp); #endif #if defined(LTC_MECC_FP) /* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); /* functions for saving/loading/freeing/adding to fixed point cache */ int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); void ltc_ecc_fp_free(void); int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock); /* lock/unlock all points currently in fixed point cache */ void ltc_ecc_fp_tablelock(int lock); #endif /* R = kG */ int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map); #ifdef LTC_ECC_SHAMIR /* kA*A + kB*B = C */ int ltc_ecc_mul2add(const ecc_point *A, void *kA, const ecc_point *B, void *kB, ecc_point *C, void *ma, void *modulus); #ifdef LTC_MECC_FP /* Shamir's trick with optimized point multiplication using fixed point cache */ int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA, const ecc_point *B, void *kB, ecc_point *C, void *ma, void *modulus); #endif #endif /* map P to affine from projective */ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); #endif /* LTC_MECC */ #ifdef LTC_MDSA int dsa_int_validate_xy(const dsa_key *key, int *stat); int dsa_int_validate_pqg(const dsa_key *key, int *stat); int dsa_int_validate_primes(const dsa_key *key, int *stat); #endif /* LTC_MDSA */ #ifdef LTC_CURVE25519 int tweetnacl_crypto_sign( unsigned char *sm,unsigned long long *smlen, const unsigned char *m,unsigned long long mlen, const unsigned char *sk,const unsigned char *pk, const unsigned char *ctx,unsigned long long cs); int tweetnacl_crypto_sign_open( int *stat, unsigned char *m,unsigned long long *mlen, const unsigned char *sm,unsigned long long smlen, const unsigned char *ctx, unsigned long long cs, const unsigned char *pk); int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, unsigned char *pk,unsigned char *sk); int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk); int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n); int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long long msglen); typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk); int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, enum ltc_oid_id id, sk_to_pk fp, curve25519_key *key); int ec25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key); int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen); #endif /* LTC_CURVE25519 */ #ifdef LTC_DER #define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t))) /* DER handling */ int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, ltc_asn1_list *root, ltc_asn1_list *list, unsigned long outlen, unsigned int flags); int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen); int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id); int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen); int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen); int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen); int der_length_asn1_length(unsigned long len, unsigned long *outlen); int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, unsigned long *outlen, unsigned long *payloadlen); extern const ltc_asn1_type der_asn1_tag_to_type_map[]; extern const unsigned long der_asn1_tag_to_type_map_sz; extern const int der_asn1_type_to_identifier_map[]; extern const unsigned long der_asn1_type_to_identifier_map_sz; int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) LTC_NULL_TERMINATED; int der_teletex_char_encode(int c); int der_teletex_value_decode(int v); int der_utf8_valid_char(const wchar_t c); typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx); int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, public_key_decode_cb callback, void *ctx); /* SUBJECT PUBLIC KEY INFO */ int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, unsigned int algorithm, const void* public_key, unsigned long public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len); int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, unsigned int algorithm, void* public_key, unsigned long* public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size); int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); #endif /* LTC_DER */ /* tomcrypt_pkcs.h */ #ifdef LTC_PKCS_8 int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ltc_asn1_list **decoded_list); #endif /* LTC_PKCS_8 */ #ifdef LTC_PKCS_12 int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int pkcs12_kdf( int hash_id, const unsigned char *pw, unsigned long pwlen, const unsigned char *salt, unsigned long saltlen, unsigned int iterations, unsigned char purpose, unsigned char *out, unsigned long outlen); #endif /* LTC_PKCS_12 */ /* tomcrypt_prng.h */ #define LTC_PRNG_EXPORT(which) \ int which ## _export(unsigned char *out, unsigned long *outlen, prng_state *prng) \ { \ unsigned long len = which ## _desc.export_size; \ \ LTC_ARGCHK(prng != NULL); \ LTC_ARGCHK(out != NULL); \ LTC_ARGCHK(outlen != NULL); \ \ if (*outlen < len) { \ *outlen = len; \ return CRYPT_BUFFER_OVERFLOW; \ } \ \ if (which ## _read(out, len, prng) != len) { \ return CRYPT_ERROR_READPRNG; \ } \ \ *outlen = len; \ return CRYPT_OK; \ } /* extract a byte portably */ #ifdef _MSC_VER #define LTC_BYTE(x, n) ((unsigned char)((x) >> (8 * (n)))) #else #define LTC_BYTE(x, n) (((x) >> (8 * (n))) & 255) #endif optee_os-4.3.0/core/lib/libtomcrypt/src/headers/tomcrypt_prng.h000066400000000000000000000177171464416617300247140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* ---- PRNG Stuff ---- */ #ifdef LTC_YARROW struct yarrow_prng { int cipher, hash; unsigned char pool[MAXBLOCKSIZE]; symmetric_CTR ctr; }; #endif #ifdef LTC_RC4 struct rc4_prng { rc4_state s; }; #endif #ifdef LTC_CHACHA20_PRNG struct chacha20_prng { chacha_state s; /* chacha state */ unsigned char ent[40]; /* entropy buffer */ unsigned long idx; /* entropy counter */ }; #endif #ifdef LTC_FORTUNA struct fortuna_prng { hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */ symmetric_key skey; unsigned char K[32], /* the current key */ IV[16]; /* IV for CTR mode */ unsigned long pool_idx, /* current pool we will add to */ pool0_len; /* length of 0'th pool */ ulong64 wd; ulong64 reset_cnt; /* number of times we have reseeded */ }; #endif #ifdef LTC_SOBER128 struct sober128_prng { sober128_state s; /* sober128 state */ unsigned char ent[40]; /* entropy buffer */ unsigned long idx; /* entropy counter */ }; #endif typedef struct { union { char dummy[1]; #ifdef LTC_YARROW struct yarrow_prng yarrow; #endif #ifdef LTC_RC4 struct rc4_prng rc4; #endif #ifdef LTC_CHACHA20_PRNG struct chacha20_prng chacha; #endif #ifdef LTC_FORTUNA struct fortuna_prng fortuna; #endif #ifdef LTC_SOBER128 struct sober128_prng sober128; #endif } u; short ready; /* ready flag 0-1 */ LTC_MUTEX_TYPE(lock) /* lock */ } prng_state; /** PRNG descriptor */ extern const struct ltc_prng_descriptor { /** Name of the PRNG */ const char *name; /** size in bytes of exported state */ int export_size; /** Start a PRNG state @param prng [out] The state to initialize @return CRYPT_OK if successful */ int (*start)(prng_state *prng); /** Add entropy to the PRNG @param in The entropy @param inlen Length of the entropy (octets)\ @param prng The PRNG state @return CRYPT_OK if successful */ int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng); /** Ready a PRNG state to read from @param prng The PRNG state to ready @return CRYPT_OK if successful */ int (*ready)(prng_state *prng); /** Read from the PRNG @param out [out] Where to store the data @param outlen Length of data desired (octets) @param prng The PRNG state to read from @return Number of octets read */ unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng); /** Terminate a PRNG state @param prng The PRNG state to terminate @return CRYPT_OK if successful */ int (*done)(prng_state *prng); /** Export a PRNG state @param out [out] The destination for the state @param outlen [in/out] The max size and resulting size of the PRNG state @param prng The PRNG to export @return CRYPT_OK if successful */ int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng); /** Import a PRNG state @param in The data to import @param inlen The length of the data to import (octets) @param prng The PRNG to initialize/import @return CRYPT_OK if successful */ int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng); /** Self-test the PRNG @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int (*test)(void); } *prng_descriptor[]; #ifdef LTC_YARROW int yarrow_start(prng_state *prng); int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); int yarrow_ready(prng_state *prng); unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng); int yarrow_done(prng_state *prng); int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng); int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng); int yarrow_test(void); extern const struct ltc_prng_descriptor yarrow_desc; #endif #ifdef LTC_FORTUNA int fortuna_start(prng_state *prng); int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng); int fortuna_ready(prng_state *prng); unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng); int fortuna_done(prng_state *prng); int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng); int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng); int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng); int fortuna_test(void); extern const struct ltc_prng_descriptor fortuna_desc; #endif #ifdef LTC_RC4 int rc4_start(prng_state *prng); int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); int rc4_ready(prng_state *prng); unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); int rc4_done(prng_state *prng); int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); int rc4_test(void); extern const struct ltc_prng_descriptor rc4_desc; #endif #ifdef LTC_CHACHA20_PRNG int chacha20_prng_start(prng_state *prng); int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); int chacha20_prng_ready(prng_state *prng); unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng); int chacha20_prng_done(prng_state *prng); int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); int chacha20_prng_test(void); extern const struct ltc_prng_descriptor chacha20_prng_desc; #endif #ifdef LTC_SPRNG int sprng_start(prng_state *prng); int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); int sprng_ready(prng_state *prng); unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng); int sprng_done(prng_state *prng); int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); int sprng_test(void); extern const struct ltc_prng_descriptor sprng_desc; #endif #ifdef LTC_SOBER128 int sober128_start(prng_state *prng); int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); int sober128_ready(prng_state *prng); unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); int sober128_done(prng_state *prng); int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); int sober128_test(void); extern const struct ltc_prng_descriptor sober128_desc; #endif int find_prng(const char *name); int register_prng(const struct ltc_prng_descriptor *prng); int unregister_prng(const struct ltc_prng_descriptor *prng); int register_all_prngs(void); int prng_is_valid(int idx); LTC_MUTEX_PROTO(ltc_prng_mutex) /* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this * might not work on all platforms as planned */ unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, void (*callback)(void)); int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); #ifdef LTC_PRNG_ENABLE_LTC_RNG extern unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/000077500000000000000000000000001464416617300207445ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/000077500000000000000000000000001464416617300221045ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2bmac.c000066400000000000000000000032561464416617300242410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2BMAC /** Initialize an BLAKE2B MAC context. @param st The BLAKE2B MAC state @param outlen The size of the MAC output (octets) @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); return blake2b_init(st, outlen, key, keylen); } /** Process data through BLAKE2B MAC @param st The BLAKE2B MAC state @param in The data to send through HMAC @param inlen The length of the data to HMAC (octets) @return CRYPT_OK if successful */ int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen) { if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); return blake2b_process(st, in, inlen); } /** Terminate a BLAKE2B MAC session @param st The BLAKE2B MAC state @param mac [out] The destination of the BLAKE2B MAC authentication tag @param maclen [in/out] The max size and resulting size of the BLAKE2B MAC authentication tag @return CRYPT_OK if successful */ int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); LTC_ARGCHK(*maclen >= st->blake2b.outlen); *maclen = st->blake2b.outlen; return blake2b_done(st, mac); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_file.c000066400000000000000000000036051464416617300252360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2BMAC /** BLAKE2B MAC a file @param fname The name of the file you wish to BLAKE2B MAC @param key The secret key @param keylen The length of the secret key @param mac [out] The BLAKE2B MAC authentication tag @param maclen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(fname); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(mac); LTC_UNUSED_PARAM(maclen); return CRYPT_NOP; #else blake2bmac_state st; FILE *in; unsigned char *buf; size_t x; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(fname, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = blake2bmac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = blake2bmac_done(&st, mac, maclen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(blake2bmac_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory.c000066400000000000000000000023551464416617300256300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2BMAC /** BLAKE2B MAC a block of memory to produce the authentication tag @param key The secret key @param keylen The length of the secret key (octets) @param in The data to BLAKE2B MAC @param inlen The length of the data to BLAKE2B MAC (octets) @param mac [out] Destination of the authentication tag @param maclen [in/out] Max size and resulting size of authentication tag @return CRYPT_OK if successful */ int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) { blake2bmac_state st; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = blake2bmac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } err = blake2bmac_done(&st, mac, maclen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(blake2bmac_state)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c000066400000000000000000000032711464416617300270400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include #ifdef LTC_BLAKE2BMAC /** BLAKE2B MAC multiple blocks of memory to produce the authentication tag @param key The secret key @param keylen The length of the secret key (octets) @param mac [out] Destination of the authentication tag @param maclen [in/out] Max size and resulting size of authentication tag @param in The data to BLAKE2B MAC @param inlen The length of the data to BLAKE2B MAC (octets) @param ... tuples of (data,len) pairs to BLAKE2B MAC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) { blake2bmac_state st; int err; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); va_start(args, inlen); curptr = in; curlen = inlen; if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } for (;;) { if ((err = blake2bmac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } curptr = va_arg(args, const unsigned char*); if (curptr == NULL) break; curlen = va_arg(args, unsigned long); } err = blake2bmac_done(&st, mac, maclen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(blake2bmac_state)); #endif va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2bmac_test.c000066400000000000000000003110441464416617300252750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2BMAC int blake2bmac_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const unsigned char tests[256][64] = { /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */ { 0x10, 0xeb, 0xb6, 0x77, 0x00, 0xb1, 0x86, 0x8e, 0xfb, 0x44, 0x17, 0x98, 0x7a, 0xcf, 0x46, 0x90, 0xae, 0x9d, 0x97, 0x2f, 0xb7, 0xa5, 0x90, 0xc2, 0xf0, 0x28, 0x71, 0x79, 0x9a, 0xaa, 0x47, 0x86, 0xb5, 0xe9, 0x96, 0xe8, 0xf0, 0xf4, 0xeb, 0x98, 0x1f, 0xc2, 0x14, 0xb0, 0x05, 0xf4, 0x2d, 0x2f, 0xf4, 0x23, 0x34, 0x99, 0x39, 0x16, 0x53, 0xdf, 0x7a, 0xef, 0xcb, 0xc1, 0x3f, 0xc5, 0x15, 0x68 }, { 0x96, 0x1f, 0x6d, 0xd1, 0xe4, 0xdd, 0x30, 0xf6, 0x39, 0x01, 0x69, 0x0c, 0x51, 0x2e, 0x78, 0xe4, 0xb4, 0x5e, 0x47, 0x42, 0xed, 0x19, 0x7c, 0x3c, 0x5e, 0x45, 0xc5, 0x49, 0xfd, 0x25, 0xf2, 0xe4, 0x18, 0x7b, 0x0b, 0xc9, 0xfe, 0x30, 0x49, 0x2b, 0x16, 0xb0, 0xd0, 0xbc, 0x4e, 0xf9, 0xb0, 0xf3, 0x4c, 0x70, 0x03, 0xfa, 0xc0, 0x9a, 0x5e, 0xf1, 0x53, 0x2e, 0x69, 0x43, 0x02, 0x34, 0xce, 0xbd }, { 0xda, 0x2c, 0xfb, 0xe2, 0xd8, 0x40, 0x9a, 0x0f, 0x38, 0x02, 0x61, 0x13, 0x88, 0x4f, 0x84, 0xb5, 0x01, 0x56, 0x37, 0x1a, 0xe3, 0x04, 0xc4, 0x43, 0x01, 0x73, 0xd0, 0x8a, 0x99, 0xd9, 0xfb, 0x1b, 0x98, 0x31, 0x64, 0xa3, 0x77, 0x07, 0x06, 0xd5, 0x37, 0xf4, 0x9e, 0x0c, 0x91, 0x6d, 0x9f, 0x32, 0xb9, 0x5c, 0xc3, 0x7a, 0x95, 0xb9, 0x9d, 0x85, 0x74, 0x36, 0xf0, 0x23, 0x2c, 0x88, 0xa9, 0x65 }, { 0x33, 0xd0, 0x82, 0x5d, 0xdd, 0xf7, 0xad, 0xa9, 0x9b, 0x0e, 0x7e, 0x30, 0x71, 0x04, 0xad, 0x07, 0xca, 0x9c, 0xfd, 0x96, 0x92, 0x21, 0x4f, 0x15, 0x61, 0x35, 0x63, 0x15, 0xe7, 0x84, 0xf3, 0xe5, 0xa1, 0x7e, 0x36, 0x4a, 0xe9, 0xdb, 0xb1, 0x4c, 0xb2, 0x03, 0x6d, 0xf9, 0x32, 0xb7, 0x7f, 0x4b, 0x29, 0x27, 0x61, 0x36, 0x5f, 0xb3, 0x28, 0xde, 0x7a, 0xfd, 0xc6, 0xd8, 0x99, 0x8f, 0x5f, 0xc1 }, { 0xbe, 0xaa, 0x5a, 0x3d, 0x08, 0xf3, 0x80, 0x71, 0x43, 0xcf, 0x62, 0x1d, 0x95, 0xcd, 0x69, 0x05, 0x14, 0xd0, 0xb4, 0x9e, 0xff, 0xf9, 0xc9, 0x1d, 0x24, 0xb5, 0x92, 0x41, 0xec, 0x0e, 0xef, 0xa5, 0xf6, 0x01, 0x96, 0xd4, 0x07, 0x04, 0x8b, 0xba, 0x8d, 0x21, 0x46, 0x82, 0x8e, 0xbc, 0xb0, 0x48, 0x8d, 0x88, 0x42, 0xfd, 0x56, 0xbb, 0x4f, 0x6d, 0xf8, 0xe1, 0x9c, 0x4b, 0x4d, 0xaa, 0xb8, 0xac }, { 0x09, 0x80, 0x84, 0xb5, 0x1f, 0xd1, 0x3d, 0xea, 0xe5, 0xf4, 0x32, 0x0d, 0xe9, 0x4a, 0x68, 0x8e, 0xe0, 0x7b, 0xae, 0xa2, 0x80, 0x04, 0x86, 0x68, 0x9a, 0x86, 0x36, 0x11, 0x7b, 0x46, 0xc1, 0xf4, 0xc1, 0xf6, 0xaf, 0x7f, 0x74, 0xae, 0x7c, 0x85, 0x76, 0x00, 0x45, 0x6a, 0x58, 0xa3, 0xaf, 0x25, 0x1d, 0xc4, 0x72, 0x3a, 0x64, 0xcc, 0x7c, 0x0a, 0x5a, 0xb6, 0xd9, 0xca, 0xc9, 0x1c, 0x20, 0xbb }, { 0x60, 0x44, 0x54, 0x0d, 0x56, 0x08, 0x53, 0xeb, 0x1c, 0x57, 0xdf, 0x00, 0x77, 0xdd, 0x38, 0x10, 0x94, 0x78, 0x1c, 0xdb, 0x90, 0x73, 0xe5, 0xb1, 0xb3, 0xd3, 0xf6, 0xc7, 0x82, 0x9e, 0x12, 0x06, 0x6b, 0xba, 0xca, 0x96, 0xd9, 0x89, 0xa6, 0x90, 0xde, 0x72, 0xca, 0x31, 0x33, 0xa8, 0x36, 0x52, 0xba, 0x28, 0x4a, 0x6d, 0x62, 0x94, 0x2b, 0x27, 0x1f, 0xfa, 0x26, 0x20, 0xc9, 0xe7, 0x5b, 0x1f }, { 0x7a, 0x8c, 0xfe, 0x9b, 0x90, 0xf7, 0x5f, 0x7e, 0xcb, 0x3a, 0xcc, 0x05, 0x3a, 0xae, 0xd6, 0x19, 0x31, 0x12, 0xb6, 0xf6, 0xa4, 0xae, 0xeb, 0x3f, 0x65, 0xd3, 0xde, 0x54, 0x19, 0x42, 0xde, 0xb9, 0xe2, 0x22, 0x81, 0x52, 0xa3, 0xc4, 0xbb, 0xbe, 0x72, 0xfc, 0x3b, 0x12, 0x62, 0x95, 0x28, 0xcf, 0xbb, 0x09, 0xfe, 0x63, 0x0f, 0x04, 0x74, 0x33, 0x9f, 0x54, 0xab, 0xf4, 0x53, 0xe2, 0xed, 0x52 }, { 0x38, 0x0b, 0xea, 0xf6, 0xea, 0x7c, 0xc9, 0x36, 0x5e, 0x27, 0x0e, 0xf0, 0xe6, 0xf3, 0xa6, 0x4f, 0xb9, 0x02, 0xac, 0xae, 0x51, 0xdd, 0x55, 0x12, 0xf8, 0x42, 0x59, 0xad, 0x2c, 0x91, 0xf4, 0xbc, 0x41, 0x08, 0xdb, 0x73, 0x19, 0x2a, 0x5b, 0xbf, 0xb0, 0xcb, 0xcf, 0x71, 0xe4, 0x6c, 0x3e, 0x21, 0xae, 0xe1, 0xc5, 0xe8, 0x60, 0xdc, 0x96, 0xe8, 0xeb, 0x0b, 0x7b, 0x84, 0x26, 0xe6, 0xab, 0xe9 }, { 0x60, 0xfe, 0x3c, 0x45, 0x35, 0xe1, 0xb5, 0x9d, 0x9a, 0x61, 0xea, 0x85, 0x00, 0xbf, 0xac, 0x41, 0xa6, 0x9d, 0xff, 0xb1, 0xce, 0xad, 0xd9, 0xac, 0xa3, 0x23, 0xe9, 0xa6, 0x25, 0xb6, 0x4d, 0xa5, 0x76, 0x3b, 0xad, 0x72, 0x26, 0xda, 0x02, 0xb9, 0xc8, 0xc4, 0xf1, 0xa5, 0xde, 0x14, 0x0a, 0xc5, 0xa6, 0xc1, 0x12, 0x4e, 0x4f, 0x71, 0x8c, 0xe0, 0xb2, 0x8e, 0xa4, 0x73, 0x93, 0xaa, 0x66, 0x37 }, { 0x4f, 0xe1, 0x81, 0xf5, 0x4a, 0xd6, 0x3a, 0x29, 0x83, 0xfe, 0xaa, 0xf7, 0x7d, 0x1e, 0x72, 0x35, 0xc2, 0xbe, 0xb1, 0x7f, 0xa3, 0x28, 0xb6, 0xd9, 0x50, 0x5b, 0xda, 0x32, 0x7d, 0xf1, 0x9f, 0xc3, 0x7f, 0x02, 0xc4, 0xb6, 0xf0, 0x36, 0x8c, 0xe2, 0x31, 0x47, 0x31, 0x3a, 0x8e, 0x57, 0x38, 0xb5, 0xfa, 0x2a, 0x95, 0xb2, 0x9d, 0xe1, 0xc7, 0xf8, 0x26, 0x4e, 0xb7, 0x7b, 0x69, 0xf5, 0x85, 0xcd }, { 0xf2, 0x28, 0x77, 0x3c, 0xe3, 0xf3, 0xa4, 0x2b, 0x5f, 0x14, 0x4d, 0x63, 0x23, 0x7a, 0x72, 0xd9, 0x96, 0x93, 0xad, 0xb8, 0x83, 0x7d, 0x0e, 0x11, 0x2a, 0x8a, 0x0f, 0x8f, 0xff, 0xf2, 0xc3, 0x62, 0x85, 0x7a, 0xc4, 0x9c, 0x11, 0xec, 0x74, 0x0d, 0x15, 0x00, 0x74, 0x9d, 0xac, 0x9b, 0x1f, 0x45, 0x48, 0x10, 0x8b, 0xf3, 0x15, 0x57, 0x94, 0xdc, 0xc9, 0xe4, 0x08, 0x28, 0x49, 0xe2, 0xb8, 0x5b }, { 0x96, 0x24, 0x52, 0xa8, 0x45, 0x5c, 0xc5, 0x6c, 0x85, 0x11, 0x31, 0x7e, 0x3b, 0x1f, 0x3b, 0x2c, 0x37, 0xdf, 0x75, 0xf5, 0x88, 0xe9, 0x43, 0x25, 0xfd, 0xd7, 0x70, 0x70, 0x35, 0x9c, 0xf6, 0x3a, 0x9a, 0xe6, 0xe9, 0x30, 0x93, 0x6f, 0xdf, 0x8e, 0x1e, 0x08, 0xff, 0xca, 0x44, 0x0c, 0xfb, 0x72, 0xc2, 0x8f, 0x06, 0xd8, 0x9a, 0x21, 0x51, 0xd1, 0xc4, 0x6c, 0xd5, 0xb2, 0x68, 0xef, 0x85, 0x63 }, { 0x43, 0xd4, 0x4b, 0xfa, 0x18, 0x76, 0x8c, 0x59, 0x89, 0x6b, 0xf7, 0xed, 0x17, 0x65, 0xcb, 0x2d, 0x14, 0xaf, 0x8c, 0x26, 0x02, 0x66, 0x03, 0x90, 0x99, 0xb2, 0x5a, 0x60, 0x3e, 0x4d, 0xdc, 0x50, 0x39, 0xd6, 0xef, 0x3a, 0x91, 0x84, 0x7d, 0x10, 0x88, 0xd4, 0x01, 0xc0, 0xc7, 0xe8, 0x47, 0x78, 0x1a, 0x8a, 0x59, 0x0d, 0x33, 0xa3, 0xc6, 0xcb, 0x4d, 0xf0, 0xfa, 0xb1, 0xc2, 0xf2, 0x23, 0x55 }, { 0xdc, 0xff, 0xa9, 0xd5, 0x8c, 0x2a, 0x4c, 0xa2, 0xcd, 0xbb, 0x0c, 0x7a, 0xa4, 0xc4, 0xc1, 0xd4, 0x51, 0x65, 0x19, 0x00, 0x89, 0xf4, 0xe9, 0x83, 0xbb, 0x1c, 0x2c, 0xab, 0x4a, 0xae, 0xff, 0x1f, 0xa2, 0xb5, 0xee, 0x51, 0x6f, 0xec, 0xd7, 0x80, 0x54, 0x02, 0x40, 0xbf, 0x37, 0xe5, 0x6c, 0x8b, 0xcc, 0xa7, 0xfa, 0xb9, 0x80, 0xe1, 0xe6, 0x1c, 0x94, 0x00, 0xd8, 0xa9, 0xa5, 0xb1, 0x4a, 0xc6 }, { 0x6f, 0xbf, 0x31, 0xb4, 0x5a, 0xb0, 0xc0, 0xb8, 0xda, 0xd1, 0xc0, 0xf5, 0xf4, 0x06, 0x13, 0x79, 0x91, 0x2d, 0xde, 0x5a, 0xa9, 0x22, 0x09, 0x9a, 0x03, 0x0b, 0x72, 0x5c, 0x73, 0x34, 0x6c, 0x52, 0x42, 0x91, 0xad, 0xef, 0x89, 0xd2, 0xf6, 0xfd, 0x8d, 0xfc, 0xda, 0x6d, 0x07, 0xda, 0xd8, 0x11, 0xa9, 0x31, 0x45, 0x36, 0xc2, 0x91, 0x5e, 0xd4, 0x5d, 0xa3, 0x49, 0x47, 0xe8, 0x3d, 0xe3, 0x4e }, { 0xa0, 0xc6, 0x5b, 0xdd, 0xde, 0x8a, 0xde, 0xf5, 0x72, 0x82, 0xb0, 0x4b, 0x11, 0xe7, 0xbc, 0x8a, 0xab, 0x10, 0x5b, 0x99, 0x23, 0x1b, 0x75, 0x0c, 0x02, 0x1f, 0x4a, 0x73, 0x5c, 0xb1, 0xbc, 0xfa, 0xb8, 0x75, 0x53, 0xbb, 0xa3, 0xab, 0xb0, 0xc3, 0xe6, 0x4a, 0x0b, 0x69, 0x55, 0x28, 0x51, 0x85, 0xa0, 0xbd, 0x35, 0xfb, 0x8c, 0xfd, 0xe5, 0x57, 0x32, 0x9b, 0xeb, 0xb1, 0xf6, 0x29, 0xee, 0x93 }, { 0xf9, 0x9d, 0x81, 0x55, 0x50, 0x55, 0x8e, 0x81, 0xec, 0xa2, 0xf9, 0x67, 0x18, 0xae, 0xd1, 0x0d, 0x86, 0xf3, 0xf1, 0xcf, 0xb6, 0x75, 0xcc, 0xe0, 0x6b, 0x0e, 0xff, 0x02, 0xf6, 0x17, 0xc5, 0xa4, 0x2c, 0x5a, 0xa7, 0x60, 0x27, 0x0f, 0x26, 0x79, 0xda, 0x26, 0x77, 0xc5, 0xae, 0xb9, 0x4f, 0x11, 0x42, 0x27, 0x7f, 0x21, 0xc7, 0xf7, 0x9f, 0x3c, 0x4f, 0x0c, 0xce, 0x4e, 0xd8, 0xee, 0x62, 0xb1 }, { 0x95, 0x39, 0x1d, 0xa8, 0xfc, 0x7b, 0x91, 0x7a, 0x20, 0x44, 0xb3, 0xd6, 0xf5, 0x37, 0x4e, 0x1c, 0xa0, 0x72, 0xb4, 0x14, 0x54, 0xd5, 0x72, 0xc7, 0x35, 0x6c, 0x05, 0xfd, 0x4b, 0xc1, 0xe0, 0xf4, 0x0b, 0x8b, 0xb8, 0xb4, 0xa9, 0xf6, 0xbc, 0xe9, 0xbe, 0x2c, 0x46, 0x23, 0xc3, 0x99, 0xb0, 0xdc, 0xa0, 0xda, 0xb0, 0x5c, 0xb7, 0x28, 0x1b, 0x71, 0xa2, 0x1b, 0x0e, 0xbc, 0xd9, 0xe5, 0x56, 0x70 }, { 0x04, 0xb9, 0xcd, 0x3d, 0x20, 0xd2, 0x21, 0xc0, 0x9a, 0xc8, 0x69, 0x13, 0xd3, 0xdc, 0x63, 0x04, 0x19, 0x89, 0xa9, 0xa1, 0xe6, 0x94, 0xf1, 0xe6, 0x39, 0xa3, 0xba, 0x7e, 0x45, 0x18, 0x40, 0xf7, 0x50, 0xc2, 0xfc, 0x19, 0x1d, 0x56, 0xad, 0x61, 0xf2, 0xe7, 0x93, 0x6b, 0xc0, 0xac, 0x8e, 0x09, 0x4b, 0x60, 0xca, 0xee, 0xd8, 0x78, 0xc1, 0x87, 0x99, 0x04, 0x54, 0x02, 0xd6, 0x1c, 0xea, 0xf9 }, { 0xec, 0x0e, 0x0e, 0xf7, 0x07, 0xe4, 0xed, 0x6c, 0x0c, 0x66, 0xf9, 0xe0, 0x89, 0xe4, 0x95, 0x4b, 0x05, 0x80, 0x30, 0xd2, 0xdd, 0x86, 0x39, 0x8f, 0xe8, 0x40, 0x59, 0x63, 0x1f, 0x9e, 0xe5, 0x91, 0xd9, 0xd7, 0x73, 0x75, 0x35, 0x51, 0x49, 0x17, 0x8c, 0x0c, 0xf8, 0xf8, 0xe7, 0xc4, 0x9e, 0xd2, 0xa5, 0xe4, 0xf9, 0x54, 0x88, 0xa2, 0x24, 0x70, 0x67, 0xc2, 0x08, 0x51, 0x0f, 0xad, 0xc4, 0x4c }, { 0x9a, 0x37, 0xcc, 0xe2, 0x73, 0xb7, 0x9c, 0x09, 0x91, 0x36, 0x77, 0x51, 0x0e, 0xaf, 0x76, 0x88, 0xe8, 0x9b, 0x33, 0x14, 0xd3, 0x53, 0x2f, 0xd2, 0x76, 0x4c, 0x39, 0xde, 0x02, 0x2a, 0x29, 0x45, 0xb5, 0x71, 0x0d, 0x13, 0x51, 0x7a, 0xf8, 0xdd, 0xc0, 0x31, 0x66, 0x24, 0xe7, 0x3b, 0xec, 0x1c, 0xe6, 0x7d, 0xf1, 0x52, 0x28, 0x30, 0x20, 0x36, 0xf3, 0x30, 0xab, 0x0c, 0xb4, 0xd2, 0x18, 0xdd }, { 0x4c, 0xf9, 0xbb, 0x8f, 0xb3, 0xd4, 0xde, 0x8b, 0x38, 0xb2, 0xf2, 0x62, 0xd3, 0xc4, 0x0f, 0x46, 0xdf, 0xe7, 0x47, 0xe8, 0xfc, 0x0a, 0x41, 0x4c, 0x19, 0x3d, 0x9f, 0xcf, 0x75, 0x31, 0x06, 0xce, 0x47, 0xa1, 0x8f, 0x17, 0x2f, 0x12, 0xe8, 0xa2, 0xf1, 0xc2, 0x67, 0x26, 0x54, 0x53, 0x58, 0xe5, 0xee, 0x28, 0xc9, 0xe2, 0x21, 0x3a, 0x87, 0x87, 0xaa, 0xfb, 0xc5, 0x16, 0xd2, 0x34, 0x31, 0x52 }, { 0x64, 0xe0, 0xc6, 0x3a, 0xf9, 0xc8, 0x08, 0xfd, 0x89, 0x31, 0x37, 0x12, 0x98, 0x67, 0xfd, 0x91, 0x93, 0x9d, 0x53, 0xf2, 0xaf, 0x04, 0xbe, 0x4f, 0xa2, 0x68, 0x00, 0x61, 0x00, 0x06, 0x9b, 0x2d, 0x69, 0xda, 0xa5, 0xc5, 0xd8, 0xed, 0x7f, 0xdd, 0xcb, 0x2a, 0x70, 0xee, 0xec, 0xdf, 0x2b, 0x10, 0x5d, 0xd4, 0x6a, 0x1e, 0x3b, 0x73, 0x11, 0x72, 0x8f, 0x63, 0x9a, 0xb4, 0x89, 0x32, 0x6b, 0xc9 }, { 0x5e, 0x9c, 0x93, 0x15, 0x8d, 0x65, 0x9b, 0x2d, 0xef, 0x06, 0xb0, 0xc3, 0xc7, 0x56, 0x50, 0x45, 0x54, 0x26, 0x62, 0xd6, 0xee, 0xe8, 0xa9, 0x6a, 0x89, 0xb7, 0x8a, 0xde, 0x09, 0xfe, 0x8b, 0x3d, 0xcc, 0x09, 0x6d, 0x4f, 0xe4, 0x88, 0x15, 0xd8, 0x8d, 0x8f, 0x82, 0x62, 0x01, 0x56, 0x60, 0x2a, 0xf5, 0x41, 0x95, 0x5e, 0x1f, 0x6c, 0xa3, 0x0d, 0xce, 0x14, 0xe2, 0x54, 0xc3, 0x26, 0xb8, 0x8f }, { 0x77, 0x75, 0xdf, 0xf8, 0x89, 0x45, 0x8d, 0xd1, 0x1a, 0xef, 0x41, 0x72, 0x76, 0x85, 0x3e, 0x21, 0x33, 0x5e, 0xb8, 0x8e, 0x4d, 0xec, 0x9c, 0xfb, 0x4e, 0x9e, 0xdb, 0x49, 0x82, 0x00, 0x88, 0x55, 0x1a, 0x2c, 0xa6, 0x03, 0x39, 0xf1, 0x20, 0x66, 0x10, 0x11, 0x69, 0xf0, 0xdf, 0xe8, 0x4b, 0x09, 0x8f, 0xdd, 0xb1, 0x48, 0xd9, 0xda, 0x6b, 0x3d, 0x61, 0x3d, 0xf2, 0x63, 0x88, 0x9a, 0xd6, 0x4b }, { 0xf0, 0xd2, 0x80, 0x5a, 0xfb, 0xb9, 0x1f, 0x74, 0x39, 0x51, 0x35, 0x1a, 0x6d, 0x02, 0x4f, 0x93, 0x53, 0xa2, 0x3c, 0x7c, 0xe1, 0xfc, 0x2b, 0x05, 0x1b, 0x3a, 0x8b, 0x96, 0x8c, 0x23, 0x3f, 0x46, 0xf5, 0x0f, 0x80, 0x6e, 0xcb, 0x15, 0x68, 0xff, 0xaa, 0x0b, 0x60, 0x66, 0x1e, 0x33, 0x4b, 0x21, 0xdd, 0xe0, 0x4f, 0x8f, 0xa1, 0x55, 0xac, 0x74, 0x0e, 0xeb, 0x42, 0xe2, 0x0b, 0x60, 0xd7, 0x64 }, { 0x86, 0xa2, 0xaf, 0x31, 0x6e, 0x7d, 0x77, 0x54, 0x20, 0x1b, 0x94, 0x2e, 0x27, 0x53, 0x64, 0xac, 0x12, 0xea, 0x89, 0x62, 0xab, 0x5b, 0xd8, 0xd7, 0xfb, 0x27, 0x6d, 0xc5, 0xfb, 0xff, 0xc8, 0xf9, 0xa2, 0x8c, 0xae, 0x4e, 0x48, 0x67, 0xdf, 0x67, 0x80, 0xd9, 0xb7, 0x25, 0x24, 0x16, 0x09, 0x27, 0xc8, 0x55, 0xda, 0x5b, 0x60, 0x78, 0xe0, 0xb5, 0x54, 0xaa, 0x91, 0xe3, 0x1c, 0xb9, 0xca, 0x1d }, { 0x10, 0xbd, 0xf0, 0xca, 0xa0, 0x80, 0x27, 0x05, 0xe7, 0x06, 0x36, 0x9b, 0xaf, 0x8a, 0x3f, 0x79, 0xd7, 0x2c, 0x0a, 0x03, 0xa8, 0x06, 0x75, 0xa7, 0xbb, 0xb0, 0x0b, 0xe3, 0xa4, 0x5e, 0x51, 0x64, 0x24, 0xd1, 0xee, 0x88, 0xef, 0xb5, 0x6f, 0x6d, 0x57, 0x77, 0x54, 0x5a, 0xe6, 0xe2, 0x77, 0x65, 0xc3, 0xa8, 0xf5, 0xe4, 0x93, 0xfc, 0x30, 0x89, 0x15, 0x63, 0x89, 0x33, 0xa1, 0xdf, 0xee, 0x55 }, { 0xb0, 0x17, 0x81, 0x09, 0x2b, 0x17, 0x48, 0x45, 0x9e, 0x2e, 0x4e, 0xc1, 0x78, 0x69, 0x66, 0x27, 0xbf, 0x4e, 0xba, 0xfe, 0xbb, 0xa7, 0x74, 0xec, 0xf0, 0x18, 0xb7, 0x9a, 0x68, 0xae, 0xb8, 0x49, 0x17, 0xbf, 0x0b, 0x84, 0xbb, 0x79, 0xd1, 0x7b, 0x74, 0x31, 0x51, 0x14, 0x4c, 0xd6, 0x6b, 0x7b, 0x33, 0xa4, 0xb9, 0xe5, 0x2c, 0x76, 0xc4, 0xe1, 0x12, 0x05, 0x0f, 0xf5, 0x38, 0x5b, 0x7f, 0x0b }, { 0xc6, 0xdb, 0xc6, 0x1d, 0xec, 0x6e, 0xae, 0xac, 0x81, 0xe3, 0xd5, 0xf7, 0x55, 0x20, 0x3c, 0x8e, 0x22, 0x05, 0x51, 0x53, 0x4a, 0x0b, 0x2f, 0xd1, 0x05, 0xa9, 0x18, 0x89, 0x94, 0x5a, 0x63, 0x85, 0x50, 0x20, 0x4f, 0x44, 0x09, 0x3d, 0xd9, 0x98, 0xc0, 0x76, 0x20, 0x5d, 0xff, 0xad, 0x70, 0x3a, 0x0e, 0x5c, 0xd3, 0xc7, 0xf4, 0x38, 0xa7, 0xe6, 0x34, 0xcd, 0x59, 0xfe, 0xde, 0xdb, 0x53, 0x9e }, { 0xeb, 0xa5, 0x1a, 0xcf, 0xfb, 0x4c, 0xea, 0x31, 0xdb, 0x4b, 0x8d, 0x87, 0xe9, 0xbf, 0x7d, 0xd4, 0x8f, 0xe9, 0x7b, 0x02, 0x53, 0xae, 0x67, 0xaa, 0x58, 0x0f, 0x9a, 0xc4, 0xa9, 0xd9, 0x41, 0xf2, 0xbe, 0xa5, 0x18, 0xee, 0x28, 0x68, 0x18, 0xcc, 0x9f, 0x63, 0x3f, 0x2a, 0x3b, 0x9f, 0xb6, 0x8e, 0x59, 0x4b, 0x48, 0xcd, 0xd6, 0xd5, 0x15, 0xbf, 0x1d, 0x52, 0xba, 0x6c, 0x85, 0xa2, 0x03, 0xa7 }, { 0x86, 0x22, 0x1f, 0x3a, 0xda, 0x52, 0x03, 0x7b, 0x72, 0x22, 0x4f, 0x10, 0x5d, 0x79, 0x99, 0x23, 0x1c, 0x5e, 0x55, 0x34, 0xd0, 0x3d, 0xa9, 0xd9, 0xc0, 0xa1, 0x2a, 0xcb, 0x68, 0x46, 0x0c, 0xd3, 0x75, 0xda, 0xf8, 0xe2, 0x43, 0x86, 0x28, 0x6f, 0x96, 0x68, 0xf7, 0x23, 0x26, 0xdb, 0xf9, 0x9b, 0xa0, 0x94, 0x39, 0x24, 0x37, 0xd3, 0x98, 0xe9, 0x5b, 0xb8, 0x16, 0x1d, 0x71, 0x7f, 0x89, 0x91 }, { 0x55, 0x95, 0xe0, 0x5c, 0x13, 0xa7, 0xec, 0x4d, 0xc8, 0xf4, 0x1f, 0xb7, 0x0c, 0xb5, 0x0a, 0x71, 0xbc, 0xe1, 0x7c, 0x02, 0x4f, 0xf6, 0xde, 0x7a, 0xf6, 0x18, 0xd0, 0xcc, 0x4e, 0x9c, 0x32, 0xd9, 0x57, 0x0d, 0x6d, 0x3e, 0xa4, 0x5b, 0x86, 0x52, 0x54, 0x91, 0x03, 0x0c, 0x0d, 0x8f, 0x2b, 0x18, 0x36, 0xd5, 0x77, 0x8c, 0x1c, 0xe7, 0x35, 0xc1, 0x77, 0x07, 0xdf, 0x36, 0x4d, 0x05, 0x43, 0x47 }, { 0xce, 0x0f, 0x4f, 0x6a, 0xca, 0x89, 0x59, 0x0a, 0x37, 0xfe, 0x03, 0x4d, 0xd7, 0x4d, 0xd5, 0xfa, 0x65, 0xeb, 0x1c, 0xbd, 0x0a, 0x41, 0x50, 0x8a, 0xad, 0xdc, 0x09, 0x35, 0x1a, 0x3c, 0xea, 0x6d, 0x18, 0xcb, 0x21, 0x89, 0xc5, 0x4b, 0x70, 0x0c, 0x00, 0x9f, 0x4c, 0xbf, 0x05, 0x21, 0xc7, 0xea, 0x01, 0xbe, 0x61, 0xc5, 0xae, 0x09, 0xcb, 0x54, 0xf2, 0x7b, 0xc1, 0xb4, 0x4d, 0x65, 0x8c, 0x82 }, { 0x7e, 0xe8, 0x0b, 0x06, 0xa2, 0x15, 0xa3, 0xbc, 0xa9, 0x70, 0xc7, 0x7c, 0xda, 0x87, 0x61, 0x82, 0x2b, 0xc1, 0x03, 0xd4, 0x4f, 0xa4, 0xb3, 0x3f, 0x4d, 0x07, 0xdc, 0xb9, 0x97, 0xe3, 0x6d, 0x55, 0x29, 0x8b, 0xce, 0xae, 0x12, 0x24, 0x1b, 0x3f, 0xa0, 0x7f, 0xa6, 0x3b, 0xe5, 0x57, 0x60, 0x68, 0xda, 0x38, 0x7b, 0x8d, 0x58, 0x59, 0xae, 0xab, 0x70, 0x13, 0x69, 0x84, 0x8b, 0x17, 0x6d, 0x42 }, { 0x94, 0x0a, 0x84, 0xb6, 0xa8, 0x4d, 0x10, 0x9a, 0xab, 0x20, 0x8c, 0x02, 0x4c, 0x6c, 0xe9, 0x64, 0x76, 0x76, 0xba, 0x0a, 0xaa, 0x11, 0xf8, 0x6d, 0xbb, 0x70, 0x18, 0xf9, 0xfd, 0x22, 0x20, 0xa6, 0xd9, 0x01, 0xa9, 0x02, 0x7f, 0x9a, 0xbc, 0xf9, 0x35, 0x37, 0x27, 0x27, 0xcb, 0xf0, 0x9e, 0xbd, 0x61, 0xa2, 0xa2, 0xee, 0xb8, 0x76, 0x53, 0xe8, 0xec, 0xad, 0x1b, 0xab, 0x85, 0xdc, 0x83, 0x27 }, { 0x20, 0x20, 0xb7, 0x82, 0x64, 0xa8, 0x2d, 0x9f, 0x41, 0x51, 0x14, 0x1a, 0xdb, 0xa8, 0xd4, 0x4b, 0xf2, 0x0c, 0x5e, 0xc0, 0x62, 0xee, 0xe9, 0xb5, 0x95, 0xa1, 0x1f, 0x9e, 0x84, 0x90, 0x1b, 0xf1, 0x48, 0xf2, 0x98, 0xe0, 0xc9, 0xf8, 0x77, 0x7d, 0xcd, 0xbc, 0x7c, 0xc4, 0x67, 0x0a, 0xac, 0x35, 0x6c, 0xc2, 0xad, 0x8c, 0xcb, 0x16, 0x29, 0xf1, 0x6f, 0x6a, 0x76, 0xbc, 0xef, 0xbe, 0xe7, 0x60 }, { 0xd1, 0xb8, 0x97, 0xb0, 0xe0, 0x75, 0xba, 0x68, 0xab, 0x57, 0x2a, 0xdf, 0x9d, 0x9c, 0x43, 0x66, 0x63, 0xe4, 0x3e, 0xb3, 0xd8, 0xe6, 0x2d, 0x92, 0xfc, 0x49, 0xc9, 0xbe, 0x21, 0x4e, 0x6f, 0x27, 0x87, 0x3f, 0xe2, 0x15, 0xa6, 0x51, 0x70, 0xe6, 0xbe, 0xa9, 0x02, 0x40, 0x8a, 0x25, 0xb4, 0x95, 0x06, 0xf4, 0x7b, 0xab, 0xd0, 0x7c, 0xec, 0xf7, 0x11, 0x3e, 0xc1, 0x0c, 0x5d, 0xd3, 0x12, 0x52 }, { 0xb1, 0x4d, 0x0c, 0x62, 0xab, 0xfa, 0x46, 0x9a, 0x35, 0x71, 0x77, 0xe5, 0x94, 0xc1, 0x0c, 0x19, 0x42, 0x43, 0xed, 0x20, 0x25, 0xab, 0x8a, 0xa5, 0xad, 0x2f, 0xa4, 0x1a, 0xd3, 0x18, 0xe0, 0xff, 0x48, 0xcd, 0x5e, 0x60, 0xbe, 0xc0, 0x7b, 0x13, 0x63, 0x4a, 0x71, 0x1d, 0x23, 0x26, 0xe4, 0x88, 0xa9, 0x85, 0xf3, 0x1e, 0x31, 0x15, 0x33, 0x99, 0xe7, 0x30, 0x88, 0xef, 0xc8, 0x6a, 0x5c, 0x55 }, { 0x41, 0x69, 0xc5, 0xcc, 0x80, 0x8d, 0x26, 0x97, 0xdc, 0x2a, 0x82, 0x43, 0x0d, 0xc2, 0x3e, 0x3c, 0xd3, 0x56, 0xdc, 0x70, 0xa9, 0x45, 0x66, 0x81, 0x05, 0x02, 0xb8, 0xd6, 0x55, 0xb3, 0x9a, 0xbf, 0x9e, 0x7f, 0x90, 0x2f, 0xe7, 0x17, 0xe0, 0x38, 0x92, 0x19, 0x85, 0x9e, 0x19, 0x45, 0xdf, 0x1a, 0xf6, 0xad, 0xa4, 0x2e, 0x4c, 0xcd, 0xa5, 0x5a, 0x19, 0x7b, 0x71, 0x00, 0xa3, 0x0c, 0x30, 0xa1 }, { 0x25, 0x8a, 0x4e, 0xdb, 0x11, 0x3d, 0x66, 0xc8, 0x39, 0xc8, 0xb1, 0xc9, 0x1f, 0x15, 0xf3, 0x5a, 0xde, 0x60, 0x9f, 0x11, 0xcd, 0x7f, 0x86, 0x81, 0xa4, 0x04, 0x5b, 0x9f, 0xef, 0x7b, 0x0b, 0x24, 0xc8, 0x2c, 0xda, 0x06, 0xa5, 0xf2, 0x06, 0x7b, 0x36, 0x88, 0x25, 0xe3, 0x91, 0x4e, 0x53, 0xd6, 0x94, 0x8e, 0xde, 0x92, 0xef, 0xd6, 0xe8, 0x38, 0x7f, 0xa2, 0xe5, 0x37, 0x23, 0x9b, 0x5b, 0xee }, { 0x79, 0xd2, 0xd8, 0x69, 0x6d, 0x30, 0xf3, 0x0f, 0xb3, 0x46, 0x57, 0x76, 0x11, 0x71, 0xa1, 0x1e, 0x6c, 0x3f, 0x1e, 0x64, 0xcb, 0xe7, 0xbe, 0xbe, 0xe1, 0x59, 0xcb, 0x95, 0xbf, 0xaf, 0x81, 0x2b, 0x4f, 0x41, 0x1e, 0x2f, 0x26, 0xd9, 0xc4, 0x21, 0xdc, 0x2c, 0x28, 0x4a, 0x33, 0x42, 0xd8, 0x23, 0xec, 0x29, 0x38, 0x49, 0xe4, 0x2d, 0x1e, 0x46, 0xb0, 0xa4, 0xac, 0x1e, 0x3c, 0x86, 0xab, 0xaa }, { 0x8b, 0x94, 0x36, 0x01, 0x0d, 0xc5, 0xde, 0xe9, 0x92, 0xae, 0x38, 0xae, 0xa9, 0x7f, 0x2c, 0xd6, 0x3b, 0x94, 0x6d, 0x94, 0xfe, 0xdd, 0x2e, 0xc9, 0x67, 0x1d, 0xcd, 0xe3, 0xbd, 0x4c, 0xe9, 0x56, 0x4d, 0x55, 0x5c, 0x66, 0xc1, 0x5b, 0xb2, 0xb9, 0x00, 0xdf, 0x72, 0xed, 0xb6, 0xb8, 0x91, 0xeb, 0xca, 0xdf, 0xef, 0xf6, 0x3c, 0x9e, 0xa4, 0x03, 0x6a, 0x99, 0x8b, 0xe7, 0x97, 0x39, 0x81, 0xe7 }, { 0xc8, 0xf6, 0x8e, 0x69, 0x6e, 0xd2, 0x82, 0x42, 0xbf, 0x99, 0x7f, 0x5b, 0x3b, 0x34, 0x95, 0x95, 0x08, 0xe4, 0x2d, 0x61, 0x38, 0x10, 0xf1, 0xe2, 0xa4, 0x35, 0xc9, 0x6e, 0xd2, 0xff, 0x56, 0x0c, 0x70, 0x22, 0xf3, 0x61, 0xa9, 0x23, 0x4b, 0x98, 0x37, 0xfe, 0xee, 0x90, 0xbf, 0x47, 0x92, 0x2e, 0xe0, 0xfd, 0x5f, 0x8d, 0xdf, 0x82, 0x37, 0x18, 0xd8, 0x6d, 0x1e, 0x16, 0xc6, 0x09, 0x00, 0x71 }, { 0xb0, 0x2d, 0x3e, 0xee, 0x48, 0x60, 0xd5, 0x86, 0x8b, 0x2c, 0x39, 0xce, 0x39, 0xbf, 0xe8, 0x10, 0x11, 0x29, 0x05, 0x64, 0xdd, 0x67, 0x8c, 0x85, 0xe8, 0x78, 0x3f, 0x29, 0x30, 0x2d, 0xfc, 0x13, 0x99, 0xba, 0x95, 0xb6, 0xb5, 0x3c, 0xd9, 0xeb, 0xbf, 0x40, 0x0c, 0xca, 0x1d, 0xb0, 0xab, 0x67, 0xe1, 0x9a, 0x32, 0x5f, 0x2d, 0x11, 0x58, 0x12, 0xd2, 0x5d, 0x00, 0x97, 0x8a, 0xd1, 0xbc, 0xa4 }, { 0x76, 0x93, 0xea, 0x73, 0xaf, 0x3a, 0xc4, 0xda, 0xd2, 0x1c, 0xa0, 0xd8, 0xda, 0x85, 0xb3, 0x11, 0x8a, 0x7d, 0x1c, 0x60, 0x24, 0xcf, 0xaf, 0x55, 0x76, 0x99, 0x86, 0x82, 0x17, 0xbc, 0x0c, 0x2f, 0x44, 0xa1, 0x99, 0xbc, 0x6c, 0x0e, 0xdd, 0x51, 0x97, 0x98, 0xba, 0x05, 0xbd, 0x5b, 0x1b, 0x44, 0x84, 0x34, 0x6a, 0x47, 0xc2, 0xca, 0xdf, 0x6b, 0xf3, 0x0b, 0x78, 0x5c, 0xc8, 0x8b, 0x2b, 0xaf }, { 0xa0, 0xe5, 0xc1, 0xc0, 0x03, 0x1c, 0x02, 0xe4, 0x8b, 0x7f, 0x09, 0xa5, 0xe8, 0x96, 0xee, 0x9a, 0xef, 0x2f, 0x17, 0xfc, 0x9e, 0x18, 0xe9, 0x97, 0xd7, 0xf6, 0xca, 0xc7, 0xae, 0x31, 0x64, 0x22, 0xc2, 0xb1, 0xe7, 0x79, 0x84, 0xe5, 0xf3, 0xa7, 0x3c, 0xb4, 0x5d, 0xee, 0xd5, 0xd3, 0xf8, 0x46, 0x00, 0x10, 0x5e, 0x6e, 0xe3, 0x8f, 0x2d, 0x09, 0x0c, 0x7d, 0x04, 0x42, 0xea, 0x34, 0xc4, 0x6d }, { 0x41, 0xda, 0xa6, 0xad, 0xcf, 0xdb, 0x69, 0xf1, 0x44, 0x0c, 0x37, 0xb5, 0x96, 0x44, 0x01, 0x65, 0xc1, 0x5a, 0xda, 0x59, 0x68, 0x13, 0xe2, 0xe2, 0x2f, 0x06, 0x0f, 0xcd, 0x55, 0x1f, 0x24, 0xde, 0xe8, 0xe0, 0x4b, 0xa6, 0x89, 0x03, 0x87, 0x88, 0x6c, 0xee, 0xc4, 0xa7, 0xa0, 0xd7, 0xfc, 0x6b, 0x44, 0x50, 0x63, 0x92, 0xec, 0x38, 0x22, 0xc0, 0xd8, 0xc1, 0xac, 0xfc, 0x7d, 0x5a, 0xeb, 0xe8 }, { 0x14, 0xd4, 0xd4, 0x0d, 0x59, 0x84, 0xd8, 0x4c, 0x5c, 0xf7, 0x52, 0x3b, 0x77, 0x98, 0xb2, 0x54, 0xe2, 0x75, 0xa3, 0xa8, 0xcc, 0x0a, 0x1b, 0xd0, 0x6e, 0xbc, 0x0b, 0xee, 0x72, 0x68, 0x56, 0xac, 0xc3, 0xcb, 0xf5, 0x16, 0xff, 0x66, 0x7c, 0xda, 0x20, 0x58, 0xad, 0x5c, 0x34, 0x12, 0x25, 0x44, 0x60, 0xa8, 0x2c, 0x92, 0x18, 0x70, 0x41, 0x36, 0x3c, 0xc7, 0x7a, 0x4d, 0xc2, 0x15, 0xe4, 0x87 }, { 0xd0, 0xe7, 0xa1, 0xe2, 0xb9, 0xa4, 0x47, 0xfe, 0xe8, 0x3e, 0x22, 0x77, 0xe9, 0xff, 0x80, 0x10, 0xc2, 0xf3, 0x75, 0xae, 0x12, 0xfa, 0x7a, 0xaa, 0x8c, 0xa5, 0xa6, 0x31, 0x78, 0x68, 0xa2, 0x6a, 0x36, 0x7a, 0x0b, 0x69, 0xfb, 0xc1, 0xcf, 0x32, 0xa5, 0x5d, 0x34, 0xeb, 0x37, 0x06, 0x63, 0x01, 0x6f, 0x3d, 0x21, 0x10, 0x23, 0x0e, 0xba, 0x75, 0x40, 0x28, 0xa5, 0x6f, 0x54, 0xac, 0xf5, 0x7c }, { 0xe7, 0x71, 0xaa, 0x8d, 0xb5, 0xa3, 0xe0, 0x43, 0xe8, 0x17, 0x8f, 0x39, 0xa0, 0x85, 0x7b, 0xa0, 0x4a, 0x3f, 0x18, 0xe4, 0xaa, 0x05, 0x74, 0x3c, 0xf8, 0xd2, 0x22, 0xb0, 0xb0, 0x95, 0x82, 0x53, 0x50, 0xba, 0x42, 0x2f, 0x63, 0x38, 0x2a, 0x23, 0xd9, 0x2e, 0x41, 0x49, 0x07, 0x4e, 0x81, 0x6a, 0x36, 0xc1, 0xcd, 0x28, 0x28, 0x4d, 0x14, 0x62, 0x67, 0x94, 0x0b, 0x31, 0xf8, 0x81, 0x8e, 0xa2 }, { 0xfe, 0xb4, 0xfd, 0x6f, 0x9e, 0x87, 0xa5, 0x6b, 0xef, 0x39, 0x8b, 0x32, 0x84, 0xd2, 0xbd, 0xa5, 0xb5, 0xb0, 0xe1, 0x66, 0x58, 0x3a, 0x66, 0xb6, 0x1e, 0x53, 0x84, 0x57, 0xff, 0x05, 0x84, 0x87, 0x2c, 0x21, 0xa3, 0x29, 0x62, 0xb9, 0x92, 0x8f, 0xfa, 0xb5, 0x8d, 0xe4, 0xaf, 0x2e, 0xdd, 0x4e, 0x15, 0xd8, 0xb3, 0x55, 0x70, 0x52, 0x32, 0x07, 0xff, 0x4e, 0x2a, 0x5a, 0xa7, 0x75, 0x4c, 0xaa }, { 0x46, 0x2f, 0x17, 0xbf, 0x00, 0x5f, 0xb1, 0xc1, 0xb9, 0xe6, 0x71, 0x77, 0x9f, 0x66, 0x52, 0x09, 0xec, 0x28, 0x73, 0xe3, 0xe4, 0x11, 0xf9, 0x8d, 0xab, 0xf2, 0x40, 0xa1, 0xd5, 0xec, 0x3f, 0x95, 0xce, 0x67, 0x96, 0xb6, 0xfc, 0x23, 0xfe, 0x17, 0x19, 0x03, 0xb5, 0x02, 0x02, 0x34, 0x67, 0xde, 0xc7, 0x27, 0x3f, 0xf7, 0x48, 0x79, 0xb9, 0x29, 0x67, 0xa2, 0xa4, 0x3a, 0x5a, 0x18, 0x3d, 0x33 }, { 0xd3, 0x33, 0x81, 0x93, 0xb6, 0x45, 0x53, 0xdb, 0xd3, 0x8d, 0x14, 0x4b, 0xea, 0x71, 0xc5, 0x91, 0x5b, 0xb1, 0x10, 0xe2, 0xd8, 0x81, 0x80, 0xdb, 0xc5, 0xdb, 0x36, 0x4f, 0xd6, 0x17, 0x1d, 0xf3, 0x17, 0xfc, 0x72, 0x68, 0x83, 0x1b, 0x5a, 0xef, 0x75, 0xe4, 0x34, 0x2b, 0x2f, 0xad, 0x87, 0x97, 0xba, 0x39, 0xed, 0xdc, 0xef, 0x80, 0xe6, 0xec, 0x08, 0x15, 0x93, 0x50, 0xb1, 0xad, 0x69, 0x6d }, { 0xe1, 0x59, 0x0d, 0x58, 0x5a, 0x3d, 0x39, 0xf7, 0xcb, 0x59, 0x9a, 0xbd, 0x47, 0x90, 0x70, 0x96, 0x64, 0x09, 0xa6, 0x84, 0x6d, 0x43, 0x77, 0xac, 0xf4, 0x47, 0x1d, 0x06, 0x5d, 0x5d, 0xb9, 0x41, 0x29, 0xcc, 0x9b, 0xe9, 0x25, 0x73, 0xb0, 0x5e, 0xd2, 0x26, 0xbe, 0x1e, 0x9b, 0x7c, 0xb0, 0xca, 0xbe, 0x87, 0x91, 0x85, 0x89, 0xf8, 0x0d, 0xad, 0xd4, 0xef, 0x5e, 0xf2, 0x5a, 0x93, 0xd2, 0x8e }, { 0xf8, 0xf3, 0x72, 0x6a, 0xc5, 0xa2, 0x6c, 0xc8, 0x01, 0x32, 0x49, 0x3a, 0x6f, 0xed, 0xcb, 0x0e, 0x60, 0x76, 0x0c, 0x09, 0xcf, 0xc8, 0x4c, 0xad, 0x17, 0x81, 0x75, 0x98, 0x68, 0x19, 0x66, 0x5e, 0x76, 0x84, 0x2d, 0x7b, 0x9f, 0xed, 0xf7, 0x6d, 0xdd, 0xeb, 0xf5, 0xd3, 0xf5, 0x6f, 0xaa, 0xad, 0x44, 0x77, 0x58, 0x7a, 0xf2, 0x16, 0x06, 0xd3, 0x96, 0xae, 0x57, 0x0d, 0x8e, 0x71, 0x9a, 0xf2 }, { 0x30, 0x18, 0x60, 0x55, 0xc0, 0x79, 0x49, 0x94, 0x81, 0x83, 0xc8, 0x50, 0xe9, 0xa7, 0x56, 0xcc, 0x09, 0x93, 0x7e, 0x24, 0x7d, 0x9d, 0x92, 0x8e, 0x86, 0x9e, 0x20, 0xba, 0xfc, 0x3c, 0xd9, 0x72, 0x17, 0x19, 0xd3, 0x4e, 0x04, 0xa0, 0x89, 0x9b, 0x92, 0xc7, 0x36, 0x08, 0x45, 0x50, 0x18, 0x68, 0x86, 0xef, 0xba, 0x2e, 0x79, 0x0d, 0x8b, 0xe6, 0xeb, 0xf0, 0x40, 0xb2, 0x09, 0xc4, 0x39, 0xa4 }, { 0xf3, 0xc4, 0x27, 0x6c, 0xb8, 0x63, 0x63, 0x77, 0x12, 0xc2, 0x41, 0xc4, 0x44, 0xc5, 0xcc, 0x1e, 0x35, 0x54, 0xe0, 0xfd, 0xdb, 0x17, 0x4d, 0x03, 0x58, 0x19, 0xdd, 0x83, 0xeb, 0x70, 0x0b, 0x4c, 0xe8, 0x8d, 0xf3, 0xab, 0x38, 0x41, 0xba, 0x02, 0x08, 0x5e, 0x1a, 0x99, 0xb4, 0xe1, 0x73, 0x10, 0xc5, 0x34, 0x10, 0x75, 0xc0, 0x45, 0x8b, 0xa3, 0x76, 0xc9, 0x5a, 0x68, 0x18, 0xfb, 0xb3, 0xe2 }, { 0x0a, 0xa0, 0x07, 0xc4, 0xdd, 0x9d, 0x58, 0x32, 0x39, 0x30, 0x40, 0xa1, 0x58, 0x3c, 0x93, 0x0b, 0xca, 0x7d, 0xc5, 0xe7, 0x7e, 0xa5, 0x3a, 0xdd, 0x7e, 0x2b, 0x3f, 0x7c, 0x8e, 0x23, 0x13, 0x68, 0x04, 0x35, 0x20, 0xd4, 0xa3, 0xef, 0x53, 0xc9, 0x69, 0xb6, 0xbb, 0xfd, 0x02, 0x59, 0x46, 0xf6, 0x32, 0xbd, 0x7f, 0x76, 0x5d, 0x53, 0xc2, 0x10, 0x03, 0xb8, 0xf9, 0x83, 0xf7, 0x5e, 0x2a, 0x6a }, { 0x08, 0xe9, 0x46, 0x47, 0x20, 0x53, 0x3b, 0x23, 0xa0, 0x4e, 0xc2, 0x4f, 0x7a, 0xe8, 0xc1, 0x03, 0x14, 0x5f, 0x76, 0x53, 0x87, 0xd7, 0x38, 0x77, 0x7d, 0x3d, 0x34, 0x34, 0x77, 0xfd, 0x1c, 0x58, 0xdb, 0x05, 0x21, 0x42, 0xca, 0xb7, 0x54, 0xea, 0x67, 0x43, 0x78, 0xe1, 0x87, 0x66, 0xc5, 0x35, 0x42, 0xf7, 0x19, 0x70, 0x17, 0x1c, 0xc4, 0xf8, 0x16, 0x94, 0x24, 0x6b, 0x71, 0x7d, 0x75, 0x64 }, { 0xd3, 0x7f, 0xf7, 0xad, 0x29, 0x79, 0x93, 0xe7, 0xec, 0x21, 0xe0, 0xf1, 0xb4, 0xb5, 0xae, 0x71, 0x9c, 0xdc, 0x83, 0xc5, 0xdb, 0x68, 0x75, 0x27, 0xf2, 0x75, 0x16, 0xcb, 0xff, 0xa8, 0x22, 0x88, 0x8a, 0x68, 0x10, 0xee, 0x5c, 0x1c, 0xa7, 0xbf, 0xe3, 0x32, 0x11, 0x19, 0xbe, 0x1a, 0xb7, 0xbf, 0xa0, 0xa5, 0x02, 0x67, 0x1c, 0x83, 0x29, 0x49, 0x4d, 0xf7, 0xad, 0x6f, 0x52, 0x2d, 0x44, 0x0f }, { 0xdd, 0x90, 0x42, 0xf6, 0xe4, 0x64, 0xdc, 0xf8, 0x6b, 0x12, 0x62, 0xf6, 0xac, 0xcf, 0xaf, 0xbd, 0x8c, 0xfd, 0x90, 0x2e, 0xd3, 0xed, 0x89, 0xab, 0xf7, 0x8f, 0xfa, 0x48, 0x2d, 0xbd, 0xee, 0xb6, 0x96, 0x98, 0x42, 0x39, 0x4c, 0x9a, 0x11, 0x68, 0xae, 0x3d, 0x48, 0x1a, 0x01, 0x78, 0x42, 0xf6, 0x60, 0x00, 0x2d, 0x42, 0x44, 0x7c, 0x6b, 0x22, 0xf7, 0xb7, 0x2f, 0x21, 0xaa, 0xe0, 0x21, 0xc9 }, { 0xbd, 0x96, 0x5b, 0xf3, 0x1e, 0x87, 0xd7, 0x03, 0x27, 0x53, 0x6f, 0x2a, 0x34, 0x1c, 0xeb, 0xc4, 0x76, 0x8e, 0xca, 0x27, 0x5f, 0xa0, 0x5e, 0xf9, 0x8f, 0x7f, 0x1b, 0x71, 0xa0, 0x35, 0x12, 0x98, 0xde, 0x00, 0x6f, 0xba, 0x73, 0xfe, 0x67, 0x33, 0xed, 0x01, 0xd7, 0x58, 0x01, 0xb4, 0xa9, 0x28, 0xe5, 0x42, 0x31, 0xb3, 0x8e, 0x38, 0xc5, 0x62, 0xb2, 0xe3, 0x3e, 0xa1, 0x28, 0x49, 0x92, 0xfa }, { 0x65, 0x67, 0x6d, 0x80, 0x06, 0x17, 0x97, 0x2f, 0xbd, 0x87, 0xe4, 0xb9, 0x51, 0x4e, 0x1c, 0x67, 0x40, 0x2b, 0x7a, 0x33, 0x10, 0x96, 0xd3, 0xbf, 0xac, 0x22, 0xf1, 0xab, 0xb9, 0x53, 0x74, 0xab, 0xc9, 0x42, 0xf1, 0x6e, 0x9a, 0xb0, 0xea, 0xd3, 0x3b, 0x87, 0xc9, 0x19, 0x68, 0xa6, 0xe5, 0x09, 0xe1, 0x19, 0xff, 0x07, 0x78, 0x7b, 0x3e, 0xf4, 0x83, 0xe1, 0xdc, 0xdc, 0xcf, 0x6e, 0x30, 0x22 }, { 0x93, 0x9f, 0xa1, 0x89, 0x69, 0x9c, 0x5d, 0x2c, 0x81, 0xdd, 0xd1, 0xff, 0xc1, 0xfa, 0x20, 0x7c, 0x97, 0x0b, 0x6a, 0x36, 0x85, 0xbb, 0x29, 0xce, 0x1d, 0x3e, 0x99, 0xd4, 0x2f, 0x2f, 0x74, 0x42, 0xda, 0x53, 0xe9, 0x5a, 0x72, 0x90, 0x73, 0x14, 0xf4, 0x58, 0x83, 0x99, 0xa3, 0xff, 0x5b, 0x0a, 0x92, 0xbe, 0xb3, 0xf6, 0xbe, 0x26, 0x94, 0xf9, 0xf8, 0x6e, 0xcf, 0x29, 0x52, 0xd5, 0xb4, 0x1c }, { 0xc5, 0x16, 0x54, 0x17, 0x01, 0x86, 0x3f, 0x91, 0x00, 0x5f, 0x31, 0x41, 0x08, 0xce, 0xec, 0xe3, 0xc6, 0x43, 0xe0, 0x4f, 0xc8, 0xc4, 0x2f, 0xd2, 0xff, 0x55, 0x62, 0x20, 0xe6, 0x16, 0xaa, 0xa6, 0xa4, 0x8a, 0xeb, 0x97, 0xa8, 0x4b, 0xad, 0x74, 0x78, 0x2e, 0x8d, 0xff, 0x96, 0xa1, 0xa2, 0xfa, 0x94, 0x93, 0x39, 0xd7, 0x22, 0xed, 0xca, 0xa3, 0x2b, 0x57, 0x06, 0x70, 0x41, 0xdf, 0x88, 0xcc }, { 0x98, 0x7f, 0xd6, 0xe0, 0xd6, 0x85, 0x7c, 0x55, 0x3e, 0xae, 0xbb, 0x3d, 0x34, 0x97, 0x0a, 0x2c, 0x2f, 0x6e, 0x89, 0xa3, 0x54, 0x8f, 0x49, 0x25, 0x21, 0x72, 0x2b, 0x80, 0xa1, 0xc2, 0x1a, 0x15, 0x38, 0x92, 0x34, 0x6d, 0x2c, 0xba, 0x64, 0x44, 0x21, 0x2d, 0x56, 0xda, 0x9a, 0x26, 0xe3, 0x24, 0xdc, 0xcb, 0xc0, 0xdc, 0xde, 0x85, 0xd4, 0xd2, 0xee, 0x43, 0x99, 0xee, 0xc5, 0xa6, 0x4e, 0x8f }, { 0xae, 0x56, 0xde, 0xb1, 0xc2, 0x32, 0x8d, 0x9c, 0x40, 0x17, 0x70, 0x6b, 0xce, 0x6e, 0x99, 0xd4, 0x13, 0x49, 0x05, 0x3b, 0xa9, 0xd3, 0x36, 0xd6, 0x77, 0xc4, 0xc2, 0x7d, 0x9f, 0xd5, 0x0a, 0xe6, 0xae, 0xe1, 0x7e, 0x85, 0x31, 0x54, 0xe1, 0xf4, 0xfe, 0x76, 0x72, 0x34, 0x6d, 0xa2, 0xea, 0xa3, 0x1e, 0xea, 0x53, 0xfc, 0xf2, 0x4a, 0x22, 0x80, 0x4f, 0x11, 0xd0, 0x3d, 0xa6, 0xab, 0xfc, 0x2b }, { 0x49, 0xd6, 0xa6, 0x08, 0xc9, 0xbd, 0xe4, 0x49, 0x18, 0x70, 0x49, 0x85, 0x72, 0xac, 0x31, 0xaa, 0xc3, 0xfa, 0x40, 0x93, 0x8b, 0x38, 0xa7, 0x81, 0x8f, 0x72, 0x38, 0x3e, 0xb0, 0x40, 0xad, 0x39, 0x53, 0x2b, 0xc0, 0x65, 0x71, 0xe1, 0x3d, 0x76, 0x7e, 0x69, 0x45, 0xab, 0x77, 0xc0, 0xbd, 0xc3, 0xb0, 0x28, 0x42, 0x53, 0x34, 0x3f, 0x9f, 0x6c, 0x12, 0x44, 0xeb, 0xf2, 0xff, 0x0d, 0xf8, 0x66 }, { 0xda, 0x58, 0x2a, 0xd8, 0xc5, 0x37, 0x0b, 0x44, 0x69, 0xaf, 0x86, 0x2a, 0xa6, 0x46, 0x7a, 0x22, 0x93, 0xb2, 0xb2, 0x8b, 0xd8, 0x0a, 0xe0, 0xe9, 0x1f, 0x42, 0x5a, 0xd3, 0xd4, 0x72, 0x49, 0xfd, 0xf9, 0x88, 0x25, 0xcc, 0x86, 0xf1, 0x40, 0x28, 0xc3, 0x30, 0x8c, 0x98, 0x04, 0xc7, 0x8b, 0xfe, 0xee, 0xee, 0x46, 0x14, 0x44, 0xce, 0x24, 0x36, 0x87, 0xe1, 0xa5, 0x05, 0x22, 0x45, 0x6a, 0x1d }, { 0xd5, 0x26, 0x6a, 0xa3, 0x33, 0x11, 0x94, 0xae, 0xf8, 0x52, 0xee, 0xd8, 0x6d, 0x7b, 0x5b, 0x26, 0x33, 0xa0, 0xaf, 0x1c, 0x73, 0x59, 0x06, 0xf2, 0xe1, 0x32, 0x79, 0xf1, 0x49, 0x31, 0xa9, 0xfc, 0x3b, 0x0e, 0xac, 0x5c, 0xe9, 0x24, 0x52, 0x73, 0xbd, 0x1a, 0xa9, 0x29, 0x05, 0xab, 0xe1, 0x62, 0x78, 0xef, 0x7e, 0xfd, 0x47, 0x69, 0x47, 0x89, 0xa7, 0x28, 0x3b, 0x77, 0xda, 0x3c, 0x70, 0xf8 }, { 0x29, 0x62, 0x73, 0x4c, 0x28, 0x25, 0x21, 0x86, 0xa9, 0xa1, 0x11, 0x1c, 0x73, 0x2a, 0xd4, 0xde, 0x45, 0x06, 0xd4, 0xb4, 0x48, 0x09, 0x16, 0x30, 0x3e, 0xb7, 0x99, 0x1d, 0x65, 0x9c, 0xcd, 0xa0, 0x7a, 0x99, 0x11, 0x91, 0x4b, 0xc7, 0x5c, 0x41, 0x8a, 0xb7, 0xa4, 0x54, 0x17, 0x57, 0xad, 0x05, 0x47, 0x96, 0xe2, 0x67, 0x97, 0xfe, 0xaf, 0x36, 0xe9, 0xf6, 0xad, 0x43, 0xf1, 0x4b, 0x35, 0xa4 }, { 0xe8, 0xb7, 0x9e, 0xc5, 0xd0, 0x6e, 0x11, 0x1b, 0xdf, 0xaf, 0xd7, 0x1e, 0x9f, 0x57, 0x60, 0xf0, 0x0a, 0xc8, 0xac, 0x5d, 0x8b, 0xf7, 0x68, 0xf9, 0xff, 0x6f, 0x08, 0xb8, 0xf0, 0x26, 0x09, 0x6b, 0x1c, 0xc3, 0xa4, 0xc9, 0x73, 0x33, 0x30, 0x19, 0xf1, 0xe3, 0x55, 0x3e, 0x77, 0xda, 0x3f, 0x98, 0xcb, 0x9f, 0x54, 0x2e, 0x0a, 0x90, 0xe5, 0xf8, 0xa9, 0x40, 0xcc, 0x58, 0xe5, 0x98, 0x44, 0xb3 }, { 0xdf, 0xb3, 0x20, 0xc4, 0x4f, 0x9d, 0x41, 0xd1, 0xef, 0xdc, 0xc0, 0x15, 0xf0, 0x8d, 0xd5, 0x53, 0x9e, 0x52, 0x6e, 0x39, 0xc8, 0x7d, 0x50, 0x9a, 0xe6, 0x81, 0x2a, 0x96, 0x9e, 0x54, 0x31, 0xbf, 0x4f, 0xa7, 0xd9, 0x1f, 0xfd, 0x03, 0xb9, 0x81, 0xe0, 0xd5, 0x44, 0xcf, 0x72, 0xd7, 0xb1, 0xc0, 0x37, 0x4f, 0x88, 0x01, 0x48, 0x2e, 0x6d, 0xea, 0x2e, 0xf9, 0x03, 0x87, 0x7e, 0xba, 0x67, 0x5e }, { 0xd8, 0x86, 0x75, 0x11, 0x8f, 0xdb, 0x55, 0xa5, 0xfb, 0x36, 0x5a, 0xc2, 0xaf, 0x1d, 0x21, 0x7b, 0xf5, 0x26, 0xce, 0x1e, 0xe9, 0xc9, 0x4b, 0x2f, 0x00, 0x90, 0xb2, 0xc5, 0x8a, 0x06, 0xca, 0x58, 0x18, 0x7d, 0x7f, 0xe5, 0x7c, 0x7b, 0xed, 0x9d, 0x26, 0xfc, 0xa0, 0x67, 0xb4, 0x11, 0x0e, 0xef, 0xcd, 0x9a, 0x0a, 0x34, 0x5d, 0xe8, 0x72, 0xab, 0xe2, 0x0d, 0xe3, 0x68, 0x00, 0x1b, 0x07, 0x45 }, { 0xb8, 0x93, 0xf2, 0xfc, 0x41, 0xf7, 0xb0, 0xdd, 0x6e, 0x2f, 0x6a, 0xa2, 0xe0, 0x37, 0x0c, 0x0c, 0xff, 0x7d, 0xf0, 0x9e, 0x3a, 0xcf, 0xcc, 0x0e, 0x92, 0x0b, 0x6e, 0x6f, 0xad, 0x0e, 0xf7, 0x47, 0xc4, 0x06, 0x68, 0x41, 0x7d, 0x34, 0x2b, 0x80, 0xd2, 0x35, 0x1e, 0x8c, 0x17, 0x5f, 0x20, 0x89, 0x7a, 0x06, 0x2e, 0x97, 0x65, 0xe6, 0xc6, 0x7b, 0x53, 0x9b, 0x6b, 0xa8, 0xb9, 0x17, 0x05, 0x45 }, { 0x6c, 0x67, 0xec, 0x56, 0x97, 0xac, 0xcd, 0x23, 0x5c, 0x59, 0xb4, 0x86, 0xd7, 0xb7, 0x0b, 0xae, 0xed, 0xcb, 0xd4, 0xaa, 0x64, 0xeb, 0xd4, 0xee, 0xf3, 0xc7, 0xea, 0xc1, 0x89, 0x56, 0x1a, 0x72, 0x62, 0x50, 0xae, 0xc4, 0xd4, 0x8c, 0xad, 0xca, 0xfb, 0xbe, 0x2c, 0xe3, 0xc1, 0x6c, 0xe2, 0xd6, 0x91, 0xa8, 0xcc, 0xe0, 0x6e, 0x88, 0x79, 0x55, 0x6d, 0x44, 0x83, 0xed, 0x71, 0x65, 0xc0, 0x63 }, { 0xf1, 0xaa, 0x2b, 0x04, 0x4f, 0x8f, 0x0c, 0x63, 0x8a, 0x3f, 0x36, 0x2e, 0x67, 0x7b, 0x5d, 0x89, 0x1d, 0x6f, 0xd2, 0xab, 0x07, 0x65, 0xf6, 0xee, 0x1e, 0x49, 0x87, 0xde, 0x05, 0x7e, 0xad, 0x35, 0x78, 0x83, 0xd9, 0xb4, 0x05, 0xb9, 0xd6, 0x09, 0xee, 0xa1, 0xb8, 0x69, 0xd9, 0x7f, 0xb1, 0x6d, 0x9b, 0x51, 0x01, 0x7c, 0x55, 0x3f, 0x3b, 0x93, 0xc0, 0xa1, 0xe0, 0xf1, 0x29, 0x6f, 0xed, 0xcd }, { 0xcb, 0xaa, 0x25, 0x95, 0x72, 0xd4, 0xae, 0xbf, 0xc1, 0x91, 0x7a, 0xcd, 0xdc, 0x58, 0x2b, 0x9f, 0x8d, 0xfa, 0xa9, 0x28, 0xa1, 0x98, 0xca, 0x7a, 0xcd, 0x0f, 0x2a, 0xa7, 0x6a, 0x13, 0x4a, 0x90, 0x25, 0x2e, 0x62, 0x98, 0xa6, 0x5b, 0x08, 0x18, 0x6a, 0x35, 0x0d, 0x5b, 0x76, 0x26, 0x69, 0x9f, 0x8c, 0xb7, 0x21, 0xa3, 0xea, 0x59, 0x21, 0xb7, 0x53, 0xae, 0x3a, 0x2d, 0xce, 0x24, 0xba, 0x3a }, { 0xfa, 0x15, 0x49, 0xc9, 0x79, 0x6c, 0xd4, 0xd3, 0x03, 0xdc, 0xf4, 0x52, 0xc1, 0xfb, 0xd5, 0x74, 0x4f, 0xd9, 0xb9, 0xb4, 0x70, 0x03, 0xd9, 0x20, 0xb9, 0x2d, 0xe3, 0x48, 0x39, 0xd0, 0x7e, 0xf2, 0xa2, 0x9d, 0xed, 0x68, 0xf6, 0xfc, 0x9e, 0x6c, 0x45, 0xe0, 0x71, 0xa2, 0xe4, 0x8b, 0xd5, 0x0c, 0x50, 0x84, 0xe9, 0x6b, 0x65, 0x7d, 0xd0, 0x40, 0x40, 0x45, 0xa1, 0xdd, 0xef, 0xe2, 0x82, 0xed }, { 0x5c, 0xf2, 0xac, 0x89, 0x7a, 0xb4, 0x44, 0xdc, 0xb5, 0xc8, 0xd8, 0x7c, 0x49, 0x5d, 0xbd, 0xb3, 0x4e, 0x18, 0x38, 0xb6, 0xb6, 0x29, 0x42, 0x7c, 0xaa, 0x51, 0x70, 0x2a, 0xd0, 0xf9, 0x68, 0x85, 0x25, 0xf1, 0x3b, 0xec, 0x50, 0x3a, 0x3c, 0x3a, 0x2c, 0x80, 0xa6, 0x5e, 0x0b, 0x57, 0x15, 0xe8, 0xaf, 0xab, 0x00, 0xff, 0xa5, 0x6e, 0xc4, 0x55, 0xa4, 0x9a, 0x1a, 0xd3, 0x0a, 0xa2, 0x4f, 0xcd }, { 0x9a, 0xaf, 0x80, 0x20, 0x7b, 0xac, 0xe1, 0x7b, 0xb7, 0xab, 0x14, 0x57, 0x57, 0xd5, 0x69, 0x6b, 0xde, 0x32, 0x40, 0x6e, 0xf2, 0x2b, 0x44, 0x29, 0x2e, 0xf6, 0x5d, 0x45, 0x19, 0xc3, 0xbb, 0x2a, 0xd4, 0x1a, 0x59, 0xb6, 0x2c, 0xc3, 0xe9, 0x4b, 0x6f, 0xa9, 0x6d, 0x32, 0xa7, 0xfa, 0xad, 0xae, 0x28, 0xaf, 0x7d, 0x35, 0x09, 0x72, 0x19, 0xaa, 0x3f, 0xd8, 0xcd, 0xa3, 0x1e, 0x40, 0xc2, 0x75 }, { 0xaf, 0x88, 0xb1, 0x63, 0x40, 0x2c, 0x86, 0x74, 0x5c, 0xb6, 0x50, 0xc2, 0x98, 0x8f, 0xb9, 0x52, 0x11, 0xb9, 0x4b, 0x03, 0xef, 0x29, 0x0e, 0xed, 0x96, 0x62, 0x03, 0x42, 0x41, 0xfd, 0x51, 0xcf, 0x39, 0x8f, 0x80, 0x73, 0xe3, 0x69, 0x35, 0x4c, 0x43, 0xea, 0xe1, 0x05, 0x2f, 0x9b, 0x63, 0xb0, 0x81, 0x91, 0xca, 0xa1, 0x38, 0xaa, 0x54, 0xfe, 0xa8, 0x89, 0xcc, 0x70, 0x24, 0x23, 0x68, 0x97 }, { 0x48, 0xfa, 0x7d, 0x64, 0xe1, 0xce, 0xee, 0x27, 0xb9, 0x86, 0x4d, 0xb5, 0xad, 0xa4, 0xb5, 0x3d, 0x00, 0xc9, 0xbc, 0x76, 0x26, 0x55, 0x58, 0x13, 0xd3, 0xcd, 0x67, 0x30, 0xab, 0x3c, 0xc0, 0x6f, 0xf3, 0x42, 0xd7, 0x27, 0x90, 0x5e, 0x33, 0x17, 0x1b, 0xde, 0x6e, 0x84, 0x76, 0xe7, 0x7f, 0xb1, 0x72, 0x08, 0x61, 0xe9, 0x4b, 0x73, 0xa2, 0xc5, 0x38, 0xd2, 0x54, 0x74, 0x62, 0x85, 0xf4, 0x30 }, { 0x0e, 0x6f, 0xd9, 0x7a, 0x85, 0xe9, 0x04, 0xf8, 0x7b, 0xfe, 0x85, 0xbb, 0xeb, 0x34, 0xf6, 0x9e, 0x1f, 0x18, 0x10, 0x5c, 0xf4, 0xed, 0x4f, 0x87, 0xae, 0xc3, 0x6c, 0x6e, 0x8b, 0x5f, 0x68, 0xbd, 0x2a, 0x6f, 0x3d, 0xc8, 0xa9, 0xec, 0xb2, 0xb6, 0x1d, 0xb4, 0xee, 0xdb, 0x6b, 0x2e, 0xa1, 0x0b, 0xf9, 0xcb, 0x02, 0x51, 0xfb, 0x0f, 0x8b, 0x34, 0x4a, 0xbf, 0x7f, 0x36, 0x6b, 0x6d, 0xe5, 0xab }, { 0x06, 0x62, 0x2d, 0xa5, 0x78, 0x71, 0x76, 0x28, 0x7f, 0xdc, 0x8f, 0xed, 0x44, 0x0b, 0xad, 0x18, 0x7d, 0x83, 0x00, 0x99, 0xc9, 0x4e, 0x6d, 0x04, 0xc8, 0xe9, 0xc9, 0x54, 0xcd, 0xa7, 0x0c, 0x8b, 0xb9, 0xe1, 0xfc, 0x4a, 0x6d, 0x0b, 0xaa, 0x83, 0x1b, 0x9b, 0x78, 0xef, 0x66, 0x48, 0x68, 0x1a, 0x48, 0x67, 0xa1, 0x1d, 0xa9, 0x3e, 0xe3, 0x6e, 0x5e, 0x6a, 0x37, 0xd8, 0x7f, 0xc6, 0x3f, 0x6f }, { 0x1d, 0xa6, 0x77, 0x2b, 0x58, 0xfa, 0xbf, 0x9c, 0x61, 0xf6, 0x8d, 0x41, 0x2c, 0x82, 0xf1, 0x82, 0xc0, 0x23, 0x6d, 0x7d, 0x57, 0x5e, 0xf0, 0xb5, 0x8d, 0xd2, 0x24, 0x58, 0xd6, 0x43, 0xcd, 0x1d, 0xfc, 0x93, 0xb0, 0x38, 0x71, 0xc3, 0x16, 0xd8, 0x43, 0x0d, 0x31, 0x29, 0x95, 0xd4, 0x19, 0x7f, 0x08, 0x74, 0xc9, 0x91, 0x72, 0xba, 0x00, 0x4a, 0x01, 0xee, 0x29, 0x5a, 0xba, 0xc2, 0x4e, 0x46 }, { 0x3c, 0xd2, 0xd9, 0x32, 0x0b, 0x7b, 0x1d, 0x5f, 0xb9, 0xaa, 0xb9, 0x51, 0xa7, 0x60, 0x23, 0xfa, 0x66, 0x7b, 0xe1, 0x4a, 0x91, 0x24, 0xe3, 0x94, 0x51, 0x39, 0x18, 0xa3, 0xf4, 0x40, 0x96, 0xae, 0x49, 0x04, 0xba, 0x0f, 0xfc, 0x15, 0x0b, 0x63, 0xbc, 0x7a, 0xb1, 0xee, 0xb9, 0xa6, 0xe2, 0x57, 0xe5, 0xc8, 0xf0, 0x00, 0xa7, 0x03, 0x94, 0xa5, 0xaf, 0xd8, 0x42, 0x71, 0x5d, 0xe1, 0x5f, 0x29 }, { 0x04, 0xcd, 0xc1, 0x4f, 0x74, 0x34, 0xe0, 0xb4, 0xbe, 0x70, 0xcb, 0x41, 0xdb, 0x4c, 0x77, 0x9a, 0x88, 0xea, 0xef, 0x6a, 0xcc, 0xeb, 0xcb, 0x41, 0xf2, 0xd4, 0x2f, 0xff, 0xe7, 0xf3, 0x2a, 0x8e, 0x28, 0x1b, 0x5c, 0x10, 0x3a, 0x27, 0x02, 0x1d, 0x0d, 0x08, 0x36, 0x22, 0x50, 0x75, 0x3c, 0xdf, 0x70, 0x29, 0x21, 0x95, 0xa5, 0x3a, 0x48, 0x72, 0x8c, 0xeb, 0x58, 0x44, 0xc2, 0xd9, 0x8b, 0xab }, { 0x90, 0x71, 0xb7, 0xa8, 0xa0, 0x75, 0xd0, 0x09, 0x5b, 0x8f, 0xb3, 0xae, 0x51, 0x13, 0x78, 0x57, 0x35, 0xab, 0x98, 0xe2, 0xb5, 0x2f, 0xaf, 0x91, 0xd5, 0xb8, 0x9e, 0x44, 0xaa, 0xc5, 0xb5, 0xd4, 0xeb, 0xbf, 0x91, 0x22, 0x3b, 0x0f, 0xf4, 0xc7, 0x19, 0x05, 0xda, 0x55, 0x34, 0x2e, 0x64, 0x65, 0x5d, 0x6e, 0xf8, 0xc8, 0x9a, 0x47, 0x68, 0xc3, 0xf9, 0x3a, 0x6d, 0xc0, 0x36, 0x6b, 0x5b, 0xc8 }, { 0xeb, 0xb3, 0x02, 0x40, 0xdd, 0x96, 0xc7, 0xbc, 0x8d, 0x0a, 0xbe, 0x49, 0xaa, 0x4e, 0xdc, 0xbb, 0x4a, 0xfd, 0xc5, 0x1f, 0xf9, 0xaa, 0xf7, 0x20, 0xd3, 0xf9, 0xe7, 0xfb, 0xb0, 0xf9, 0xc6, 0xd6, 0x57, 0x13, 0x50, 0x50, 0x17, 0x69, 0xfc, 0x4e, 0xbd, 0x0b, 0x21, 0x41, 0x24, 0x7f, 0xf4, 0x00, 0xd4, 0xfd, 0x4b, 0xe4, 0x14, 0xed, 0xf3, 0x77, 0x57, 0xbb, 0x90, 0xa3, 0x2a, 0xc5, 0xc6, 0x5a }, { 0x85, 0x32, 0xc5, 0x8b, 0xf3, 0xc8, 0x01, 0x5d, 0x9d, 0x1c, 0xbe, 0x00, 0xee, 0xf1, 0xf5, 0x08, 0x2f, 0x8f, 0x36, 0x32, 0xfb, 0xe9, 0xf1, 0xed, 0x4f, 0x9d, 0xfb, 0x1f, 0xa7, 0x9e, 0x82, 0x83, 0x06, 0x6d, 0x77, 0xc4, 0x4c, 0x4a, 0xf9, 0x43, 0xd7, 0x6b, 0x30, 0x03, 0x64, 0xae, 0xcb, 0xd0, 0x64, 0x8c, 0x8a, 0x89, 0x39, 0xbd, 0x20, 0x41, 0x23, 0xf4, 0xb5, 0x62, 0x60, 0x42, 0x2d, 0xec }, { 0xfe, 0x98, 0x46, 0xd6, 0x4f, 0x7c, 0x77, 0x08, 0x69, 0x6f, 0x84, 0x0e, 0x2d, 0x76, 0xcb, 0x44, 0x08, 0xb6, 0x59, 0x5c, 0x2f, 0x81, 0xec, 0x6a, 0x28, 0xa7, 0xf2, 0xf2, 0x0c, 0xb8, 0x8c, 0xfe, 0x6a, 0xc0, 0xb9, 0xe9, 0xb8, 0x24, 0x4f, 0x08, 0xbd, 0x70, 0x95, 0xc3, 0x50, 0xc1, 0xd0, 0x84, 0x2f, 0x64, 0xfb, 0x01, 0xbb, 0x7f, 0x53, 0x2d, 0xfc, 0xd4, 0x73, 0x71, 0xb0, 0xae, 0xeb, 0x79 }, { 0x28, 0xf1, 0x7e, 0xa6, 0xfb, 0x6c, 0x42, 0x09, 0x2d, 0xc2, 0x64, 0x25, 0x7e, 0x29, 0x74, 0x63, 0x21, 0xfb, 0x5b, 0xda, 0xea, 0x98, 0x73, 0xc2, 0xa7, 0xfa, 0x9d, 0x8f, 0x53, 0x81, 0x8e, 0x89, 0x9e, 0x16, 0x1b, 0xc7, 0x7d, 0xfe, 0x80, 0x90, 0xaf, 0xd8, 0x2b, 0xf2, 0x26, 0x6c, 0x5c, 0x1b, 0xc9, 0x30, 0xa8, 0xd1, 0x54, 0x76, 0x24, 0x43, 0x9e, 0x66, 0x2e, 0xf6, 0x95, 0xf2, 0x6f, 0x24 }, { 0xec, 0x6b, 0x7d, 0x7f, 0x03, 0x0d, 0x48, 0x50, 0xac, 0xae, 0x3c, 0xb6, 0x15, 0xc2, 0x1d, 0xd2, 0x52, 0x06, 0xd6, 0x3e, 0x84, 0xd1, 0xdb, 0x8d, 0x95, 0x73, 0x70, 0x73, 0x7b, 0xa0, 0xe9, 0x84, 0x67, 0xea, 0x0c, 0xe2, 0x74, 0xc6, 0x61, 0x99, 0x90, 0x1e, 0xae, 0xc1, 0x8a, 0x08, 0x52, 0x57, 0x15, 0xf5, 0x3b, 0xfd, 0xb0, 0xaa, 0xcb, 0x61, 0x3d, 0x34, 0x2e, 0xbd, 0xce, 0xed, 0xdc, 0x3b }, { 0xb4, 0x03, 0xd3, 0x69, 0x1c, 0x03, 0xb0, 0xd3, 0x41, 0x8d, 0xf3, 0x27, 0xd5, 0x86, 0x0d, 0x34, 0xbb, 0xfc, 0xc4, 0x51, 0x9b, 0xfb, 0xce, 0x36, 0xbf, 0x33, 0xb2, 0x08, 0x38, 0x5f, 0xad, 0xb9, 0x18, 0x6b, 0xc7, 0x8a, 0x76, 0xc4, 0x89, 0xd8, 0x9f, 0xd5, 0x7e, 0x7d, 0xc7, 0x54, 0x12, 0xd2, 0x3b, 0xcd, 0x1d, 0xae, 0x84, 0x70, 0xce, 0x92, 0x74, 0x75, 0x4b, 0xb8, 0x58, 0x5b, 0x13, 0xc5 }, { 0x31, 0xfc, 0x79, 0x73, 0x8b, 0x87, 0x72, 0xb3, 0xf5, 0x5c, 0xd8, 0x17, 0x88, 0x13, 0xb3, 0xb5, 0x2d, 0x0d, 0xb5, 0xa4, 0x19, 0xd3, 0x0b, 0xa9, 0x49, 0x5c, 0x4b, 0x9d, 0xa0, 0x21, 0x9f, 0xac, 0x6d, 0xf8, 0xe7, 0xc2, 0x3a, 0x81, 0x15, 0x51, 0xa6, 0x2b, 0x82, 0x7f, 0x25, 0x6e, 0xcd, 0xb8, 0x12, 0x4a, 0xc8, 0xa6, 0x79, 0x2c, 0xcf, 0xec, 0xc3, 0xb3, 0x01, 0x27, 0x22, 0xe9, 0x44, 0x63 }, { 0xbb, 0x20, 0x39, 0xec, 0x28, 0x70, 0x91, 0xbc, 0xc9, 0x64, 0x2f, 0xc9, 0x00, 0x49, 0xe7, 0x37, 0x32, 0xe0, 0x2e, 0x57, 0x7e, 0x28, 0x62, 0xb3, 0x22, 0x16, 0xae, 0x9b, 0xed, 0xcd, 0x73, 0x0c, 0x4c, 0x28, 0x4e, 0xf3, 0x96, 0x8c, 0x36, 0x8b, 0x7d, 0x37, 0x58, 0x4f, 0x97, 0xbd, 0x4b, 0x4d, 0xc6, 0xef, 0x61, 0x27, 0xac, 0xfe, 0x2e, 0x6a, 0xe2, 0x50, 0x91, 0x24, 0xe6, 0x6c, 0x8a, 0xf4 }, { 0xf5, 0x3d, 0x68, 0xd1, 0x3f, 0x45, 0xed, 0xfc, 0xb9, 0xbd, 0x41, 0x5e, 0x28, 0x31, 0xe9, 0x38, 0x35, 0x0d, 0x53, 0x80, 0xd3, 0x43, 0x22, 0x78, 0xfc, 0x1c, 0x0c, 0x38, 0x1f, 0xcb, 0x7c, 0x65, 0xc8, 0x2d, 0xaf, 0xe0, 0x51, 0xd8, 0xc8, 0xb0, 0xd4, 0x4e, 0x09, 0x74, 0xa0, 0xe5, 0x9e, 0xc7, 0xbf, 0x7e, 0xd0, 0x45, 0x9f, 0x86, 0xe9, 0x6f, 0x32, 0x9f, 0xc7, 0x97, 0x52, 0x51, 0x0f, 0xd3 }, { 0x8d, 0x56, 0x8c, 0x79, 0x84, 0xf0, 0xec, 0xdf, 0x76, 0x40, 0xfb, 0xc4, 0x83, 0xb5, 0xd8, 0xc9, 0xf8, 0x66, 0x34, 0xf6, 0xf4, 0x32, 0x91, 0x84, 0x1b, 0x30, 0x9a, 0x35, 0x0a, 0xb9, 0xc1, 0x13, 0x7d, 0x24, 0x06, 0x6b, 0x09, 0xda, 0x99, 0x44, 0xba, 0xc5, 0x4d, 0x5b, 0xb6, 0x58, 0x0d, 0x83, 0x60, 0x47, 0xaa, 0xc7, 0x4a, 0xb7, 0x24, 0xb8, 0x87, 0xeb, 0xf9, 0x3d, 0x4b, 0x32, 0xec, 0xa9 }, { 0xc0, 0xb6, 0x5c, 0xe5, 0xa9, 0x6f, 0xf7, 0x74, 0xc4, 0x56, 0xca, 0xc3, 0xb5, 0xf2, 0xc4, 0xcd, 0x35, 0x9b, 0x4f, 0xf5, 0x3e, 0xf9, 0x3a, 0x3d, 0xa0, 0x77, 0x8b, 0xe4, 0x90, 0x0d, 0x1e, 0x8d, 0xa1, 0x60, 0x1e, 0x76, 0x9e, 0x8f, 0x1b, 0x02, 0xd2, 0xa2, 0xf8, 0xc5, 0xb9, 0xfa, 0x10, 0xb4, 0x4f, 0x1c, 0x18, 0x69, 0x85, 0x46, 0x8f, 0xee, 0xb0, 0x08, 0x73, 0x02, 0x83, 0xa6, 0x65, 0x7d }, { 0x49, 0x00, 0xbb, 0xa6, 0xf5, 0xfb, 0x10, 0x3e, 0xce, 0x8e, 0xc9, 0x6a, 0xda, 0x13, 0xa5, 0xc3, 0xc8, 0x54, 0x88, 0xe0, 0x55, 0x51, 0xda, 0x6b, 0x6b, 0x33, 0xd9, 0x88, 0xe6, 0x11, 0xec, 0x0f, 0xe2, 0xe3, 0xc2, 0xaa, 0x48, 0xea, 0x6a, 0xe8, 0x98, 0x6a, 0x3a, 0x23, 0x1b, 0x22, 0x3c, 0x5d, 0x27, 0xce, 0xc2, 0xea, 0xdd, 0xe9, 0x1c, 0xe0, 0x79, 0x81, 0xee, 0x65, 0x28, 0x62, 0xd1, 0xe4 }, { 0xc7, 0xf5, 0xc3, 0x7c, 0x72, 0x85, 0xf9, 0x27, 0xf7, 0x64, 0x43, 0x41, 0x4d, 0x43, 0x57, 0xff, 0x78, 0x96, 0x47, 0xd7, 0xa0, 0x05, 0xa5, 0xa7, 0x87, 0xe0, 0x3c, 0x34, 0x6b, 0x57, 0xf4, 0x9f, 0x21, 0xb6, 0x4f, 0xa9, 0xcf, 0x4b, 0x7e, 0x45, 0x57, 0x3e, 0x23, 0x04, 0x90, 0x17, 0x56, 0x71, 0x21, 0xa9, 0xc3, 0xd4, 0xb2, 0xb7, 0x3e, 0xc5, 0xe9, 0x41, 0x35, 0x77, 0x52, 0x5d, 0xb4, 0x5a }, { 0xec, 0x70, 0x96, 0x33, 0x07, 0x36, 0xfd, 0xb2, 0xd6, 0x4b, 0x56, 0x53, 0xe7, 0x47, 0x5d, 0xa7, 0x46, 0xc2, 0x3a, 0x46, 0x13, 0xa8, 0x26, 0x87, 0xa2, 0x80, 0x62, 0xd3, 0x23, 0x63, 0x64, 0x28, 0x4a, 0xc0, 0x17, 0x20, 0xff, 0xb4, 0x06, 0xcf, 0xe2, 0x65, 0xc0, 0xdf, 0x62, 0x6a, 0x18, 0x8c, 0x9e, 0x59, 0x63, 0xac, 0xe5, 0xd3, 0xd5, 0xbb, 0x36, 0x3e, 0x32, 0xc3, 0x8c, 0x21, 0x90, 0xa6 }, { 0x82, 0xe7, 0x44, 0xc7, 0x5f, 0x46, 0x49, 0xec, 0x52, 0xb8, 0x07, 0x71, 0xa7, 0x7d, 0x47, 0x5a, 0x3b, 0xc0, 0x91, 0x98, 0x95, 0x56, 0x96, 0x0e, 0x27, 0x6a, 0x5f, 0x9e, 0xad, 0x92, 0xa0, 0x3f, 0x71, 0x87, 0x42, 0xcd, 0xcf, 0xea, 0xee, 0x5c, 0xb8, 0x5c, 0x44, 0xaf, 0x19, 0x8a, 0xdc, 0x43, 0xa4, 0xa4, 0x28, 0xf5, 0xf0, 0xc2, 0xdd, 0xb0, 0xbe, 0x36, 0x05, 0x9f, 0x06, 0xd7, 0xdf, 0x73 }, { 0x28, 0x34, 0xb7, 0xa7, 0x17, 0x0f, 0x1f, 0x5b, 0x68, 0x55, 0x9a, 0xb7, 0x8c, 0x10, 0x50, 0xec, 0x21, 0xc9, 0x19, 0x74, 0x0b, 0x78, 0x4a, 0x90, 0x72, 0xf6, 0xe5, 0xd6, 0x9f, 0x82, 0x8d, 0x70, 0xc9, 0x19, 0xc5, 0x03, 0x9f, 0xb1, 0x48, 0xe3, 0x9e, 0x2c, 0x8a, 0x52, 0x11, 0x83, 0x78, 0xb0, 0x64, 0xca, 0x8d, 0x50, 0x01, 0xcd, 0x10, 0xa5, 0x47, 0x83, 0x87, 0xb9, 0x66, 0x71, 0x5e, 0xd6 }, { 0x16, 0xb4, 0xad, 0xa8, 0x83, 0xf7, 0x2f, 0x85, 0x3b, 0xb7, 0xef, 0x25, 0x3e, 0xfc, 0xab, 0x0c, 0x3e, 0x21, 0x61, 0x68, 0x7a, 0xd6, 0x15, 0x43, 0xa0, 0xd2, 0x82, 0x4f, 0x91, 0xc1, 0xf8, 0x13, 0x47, 0xd8, 0x6b, 0xe7, 0x09, 0xb1, 0x69, 0x96, 0xe1, 0x7f, 0x2d, 0xd4, 0x86, 0x92, 0x7b, 0x02, 0x88, 0xad, 0x38, 0xd1, 0x30, 0x63, 0xc4, 0xa9, 0x67, 0x2c, 0x39, 0x39, 0x7d, 0x37, 0x89, 0xb6 }, { 0x78, 0xd0, 0x48, 0xf3, 0xa6, 0x9d, 0x8b, 0x54, 0xae, 0x0e, 0xd6, 0x3a, 0x57, 0x3a, 0xe3, 0x50, 0xd8, 0x9f, 0x7c, 0x6c, 0xf1, 0xf3, 0x68, 0x89, 0x30, 0xde, 0x89, 0x9a, 0xfa, 0x03, 0x76, 0x97, 0x62, 0x9b, 0x31, 0x4e, 0x5c, 0xd3, 0x03, 0xaa, 0x62, 0xfe, 0xea, 0x72, 0xa2, 0x5b, 0xf4, 0x2b, 0x30, 0x4b, 0x6c, 0x6b, 0xcb, 0x27, 0xfa, 0xe2, 0x1c, 0x16, 0xd9, 0x25, 0xe1, 0xfb, 0xda, 0xc3 }, { 0x0f, 0x74, 0x6a, 0x48, 0x74, 0x92, 0x87, 0xad, 0xa7, 0x7a, 0x82, 0x96, 0x1f, 0x05, 0xa4, 0xda, 0x4a, 0xbd, 0xb7, 0xd7, 0x7b, 0x12, 0x20, 0xf8, 0x36, 0xd0, 0x9e, 0xc8, 0x14, 0x35, 0x9c, 0x0e, 0xc0, 0x23, 0x9b, 0x8c, 0x7b, 0x9f, 0xf9, 0xe0, 0x2f, 0x56, 0x9d, 0x1b, 0x30, 0x1e, 0xf6, 0x7c, 0x46, 0x12, 0xd1, 0xde, 0x4f, 0x73, 0x0f, 0x81, 0xc1, 0x2c, 0x40, 0xcc, 0x06, 0x3c, 0x5c, 0xaa }, { 0xf0, 0xfc, 0x85, 0x9d, 0x3b, 0xd1, 0x95, 0xfb, 0xdc, 0x2d, 0x59, 0x1e, 0x4c, 0xda, 0xc1, 0x51, 0x79, 0xec, 0x0f, 0x1d, 0xc8, 0x21, 0xc1, 0x1d, 0xf1, 0xf0, 0xc1, 0xd2, 0x6e, 0x62, 0x60, 0xaa, 0xa6, 0x5b, 0x79, 0xfa, 0xfa, 0xca, 0xfd, 0x7d, 0x3a, 0xd6, 0x1e, 0x60, 0x0f, 0x25, 0x09, 0x05, 0xf5, 0x87, 0x8c, 0x87, 0x45, 0x28, 0x97, 0x64, 0x7a, 0x35, 0xb9, 0x95, 0xbc, 0xad, 0xc3, 0xa3 }, { 0x26, 0x20, 0xf6, 0x87, 0xe8, 0x62, 0x5f, 0x6a, 0x41, 0x24, 0x60, 0xb4, 0x2e, 0x2c, 0xef, 0x67, 0x63, 0x42, 0x08, 0xce, 0x10, 0xa0, 0xcb, 0xd4, 0xdf, 0xf7, 0x04, 0x4a, 0x41, 0xb7, 0x88, 0x00, 0x77, 0xe9, 0xf8, 0xdc, 0x3b, 0x8d, 0x12, 0x16, 0xd3, 0x37, 0x6a, 0x21, 0xe0, 0x15, 0xb5, 0x8f, 0xb2, 0x79, 0xb5, 0x21, 0xd8, 0x3f, 0x93, 0x88, 0xc7, 0x38, 0x2c, 0x85, 0x05, 0x59, 0x0b, 0x9b }, { 0x22, 0x7e, 0x3a, 0xed, 0x8d, 0x2c, 0xb1, 0x0b, 0x91, 0x8f, 0xcb, 0x04, 0xf9, 0xde, 0x3e, 0x6d, 0x0a, 0x57, 0xe0, 0x84, 0x76, 0xd9, 0x37, 0x59, 0xcd, 0x7b, 0x2e, 0xd5, 0x4a, 0x1c, 0xbf, 0x02, 0x39, 0xc5, 0x28, 0xfb, 0x04, 0xbb, 0xf2, 0x88, 0x25, 0x3e, 0x60, 0x1d, 0x3b, 0xc3, 0x8b, 0x21, 0x79, 0x4a, 0xfe, 0xf9, 0x0b, 0x17, 0x09, 0x4a, 0x18, 0x2c, 0xac, 0x55, 0x77, 0x45, 0xe7, 0x5f }, { 0x1a, 0x92, 0x99, 0x01, 0xb0, 0x9c, 0x25, 0xf2, 0x7d, 0x6b, 0x35, 0xbe, 0x7b, 0x2f, 0x1c, 0x47, 0x45, 0x13, 0x1f, 0xde, 0xbc, 0xa7, 0xf3, 0xe2, 0x45, 0x19, 0x26, 0x72, 0x04, 0x34, 0xe0, 0xdb, 0x6e, 0x74, 0xfd, 0x69, 0x3a, 0xd2, 0x9b, 0x77, 0x7d, 0xc3, 0x35, 0x5c, 0x59, 0x2a, 0x36, 0x1c, 0x48, 0x73, 0xb0, 0x11, 0x33, 0xa5, 0x7c, 0x2e, 0x3b, 0x70, 0x75, 0xcb, 0xdb, 0x86, 0xf4, 0xfc }, { 0x5f, 0xd7, 0x96, 0x8b, 0xc2, 0xfe, 0x34, 0xf2, 0x20, 0xb5, 0xe3, 0xdc, 0x5a, 0xf9, 0x57, 0x17, 0x42, 0xd7, 0x3b, 0x7d, 0x60, 0x81, 0x9f, 0x28, 0x88, 0xb6, 0x29, 0x07, 0x2b, 0x96, 0xa9, 0xd8, 0xab, 0x2d, 0x91, 0xb8, 0x2d, 0x0a, 0x9a, 0xab, 0xa6, 0x1b, 0xbd, 0x39, 0x95, 0x81, 0x32, 0xfc, 0xc4, 0x25, 0x70, 0x23, 0xd1, 0xec, 0xa5, 0x91, 0xb3, 0x05, 0x4e, 0x2d, 0xc8, 0x1c, 0x82, 0x00 }, { 0xdf, 0xcc, 0xe8, 0xcf, 0x32, 0x87, 0x0c, 0xc6, 0xa5, 0x03, 0xea, 0xda, 0xfc, 0x87, 0xfd, 0x6f, 0x78, 0x91, 0x8b, 0x9b, 0x4d, 0x07, 0x37, 0xdb, 0x68, 0x10, 0xbe, 0x99, 0x6b, 0x54, 0x97, 0xe7, 0xe5, 0xcc, 0x80, 0xe3, 0x12, 0xf6, 0x1e, 0x71, 0xff, 0x3e, 0x96, 0x24, 0x43, 0x60, 0x73, 0x15, 0x64, 0x03, 0xf7, 0x35, 0xf5, 0x6b, 0x0b, 0x01, 0x84, 0x5c, 0x18, 0xf6, 0xca, 0xf7, 0x72, 0xe6 }, { 0x02, 0xf7, 0xef, 0x3a, 0x9c, 0xe0, 0xff, 0xf9, 0x60, 0xf6, 0x70, 0x32, 0xb2, 0x96, 0xef, 0xca, 0x30, 0x61, 0xf4, 0x93, 0x4d, 0x69, 0x07, 0x49, 0xf2, 0xd0, 0x1c, 0x35, 0xc8, 0x1c, 0x14, 0xf3, 0x9a, 0x67, 0xfa, 0x35, 0x0b, 0xc8, 0xa0, 0x35, 0x9b, 0xf1, 0x72, 0x4b, 0xff, 0xc3, 0xbc, 0xa6, 0xd7, 0xc7, 0xbb, 0xa4, 0x79, 0x1f, 0xd5, 0x22, 0xa3, 0xad, 0x35, 0x3c, 0x02, 0xec, 0x5a, 0xa8 }, { 0x64, 0xbe, 0x5c, 0x6a, 0xba, 0x65, 0xd5, 0x94, 0x84, 0x4a, 0xe7, 0x8b, 0xb0, 0x22, 0xe5, 0xbe, 0xbe, 0x12, 0x7f, 0xd6, 0xb6, 0xff, 0xa5, 0xa1, 0x37, 0x03, 0x85, 0x5a, 0xb6, 0x3b, 0x62, 0x4d, 0xcd, 0x1a, 0x36, 0x3f, 0x99, 0x20, 0x3f, 0x63, 0x2e, 0xc3, 0x86, 0xf3, 0xea, 0x76, 0x7f, 0xc9, 0x92, 0xe8, 0xed, 0x96, 0x86, 0x58, 0x6a, 0xa2, 0x75, 0x55, 0xa8, 0x59, 0x9d, 0x5b, 0x80, 0x8f }, { 0xf7, 0x85, 0x85, 0x50, 0x5c, 0x4e, 0xaa, 0x54, 0xa8, 0xb5, 0xbe, 0x70, 0xa6, 0x1e, 0x73, 0x5e, 0x0f, 0xf9, 0x7a, 0xf9, 0x44, 0xdd, 0xb3, 0x00, 0x1e, 0x35, 0xd8, 0x6c, 0x4e, 0x21, 0x99, 0xd9, 0x76, 0x10, 0x4b, 0x6a, 0xe3, 0x17, 0x50, 0xa3, 0x6a, 0x72, 0x6e, 0xd2, 0x85, 0x06, 0x4f, 0x59, 0x81, 0xb5, 0x03, 0x88, 0x9f, 0xef, 0x82, 0x2f, 0xcd, 0xc2, 0x89, 0x8d, 0xdd, 0xb7, 0x88, 0x9a }, { 0xe4, 0xb5, 0x56, 0x60, 0x33, 0x86, 0x95, 0x72, 0xed, 0xfd, 0x87, 0x47, 0x9a, 0x5b, 0xb7, 0x3c, 0x80, 0xe8, 0x75, 0x9b, 0x91, 0x23, 0x28, 0x79, 0xd9, 0x6b, 0x1d, 0xda, 0x36, 0xc0, 0x12, 0x07, 0x6e, 0xe5, 0xa2, 0xed, 0x7a, 0xe2, 0xde, 0x63, 0xef, 0x84, 0x06, 0xa0, 0x6a, 0xea, 0x82, 0xc1, 0x88, 0x03, 0x1b, 0x56, 0x0b, 0xea, 0xfb, 0x58, 0x3f, 0xb3, 0xde, 0x9e, 0x57, 0x95, 0x2a, 0x7e }, { 0xe1, 0xb3, 0xe7, 0xed, 0x86, 0x7f, 0x6c, 0x94, 0x84, 0xa2, 0xa9, 0x7f, 0x77, 0x15, 0xf2, 0x5e, 0x25, 0x29, 0x4e, 0x99, 0x2e, 0x41, 0xf6, 0xa7, 0xc1, 0x61, 0xff, 0xc2, 0xad, 0xc6, 0xda, 0xae, 0xb7, 0x11, 0x31, 0x02, 0xd5, 0xe6, 0x09, 0x02, 0x87, 0xfe, 0x6a, 0xd9, 0x4c, 0xe5, 0xd6, 0xb7, 0x39, 0xc6, 0xca, 0x24, 0x0b, 0x05, 0xc7, 0x6f, 0xb7, 0x3f, 0x25, 0xdd, 0x02, 0x4b, 0xf9, 0x35 }, { 0x85, 0xfd, 0x08, 0x5f, 0xdc, 0x12, 0xa0, 0x80, 0x98, 0x3d, 0xf0, 0x7b, 0xd7, 0x01, 0x2b, 0x0d, 0x40, 0x2a, 0x0f, 0x40, 0x43, 0xfc, 0xb2, 0x77, 0x5a, 0xdf, 0x0b, 0xad, 0x17, 0x4f, 0x9b, 0x08, 0xd1, 0x67, 0x6e, 0x47, 0x69, 0x85, 0x78, 0x5c, 0x0a, 0x5d, 0xcc, 0x41, 0xdb, 0xff, 0x6d, 0x95, 0xef, 0x4d, 0x66, 0xa3, 0xfb, 0xdc, 0x4a, 0x74, 0xb8, 0x2b, 0xa5, 0x2d, 0xa0, 0x51, 0x2b, 0x74 }, { 0xae, 0xd8, 0xfa, 0x76, 0x4b, 0x0f, 0xbf, 0xf8, 0x21, 0xe0, 0x52, 0x33, 0xd2, 0xf7, 0xb0, 0x90, 0x0e, 0xc4, 0x4d, 0x82, 0x6f, 0x95, 0xe9, 0x3c, 0x34, 0x3c, 0x1b, 0xc3, 0xba, 0x5a, 0x24, 0x37, 0x4b, 0x1d, 0x61, 0x6e, 0x7e, 0x7a, 0xba, 0x45, 0x3a, 0x0a, 0xda, 0x5e, 0x4f, 0xab, 0x53, 0x82, 0x40, 0x9e, 0x0d, 0x42, 0xce, 0x9c, 0x2b, 0xc7, 0xfb, 0x39, 0xa9, 0x9c, 0x34, 0x0c, 0x20, 0xf0 }, { 0x7b, 0xa3, 0xb2, 0xe2, 0x97, 0x23, 0x35, 0x22, 0xee, 0xb3, 0x43, 0xbd, 0x3e, 0xbc, 0xfd, 0x83, 0x5a, 0x04, 0x00, 0x77, 0x35, 0xe8, 0x7f, 0x0c, 0xa3, 0x00, 0xcb, 0xee, 0x6d, 0x41, 0x65, 0x65, 0x16, 0x21, 0x71, 0x58, 0x1e, 0x40, 0x20, 0xff, 0x4c, 0xf1, 0x76, 0x45, 0x0f, 0x12, 0x91, 0xea, 0x22, 0x85, 0xcb, 0x9e, 0xbf, 0xfe, 0x4c, 0x56, 0x66, 0x06, 0x27, 0x68, 0x51, 0x45, 0x05, 0x1c }, { 0xde, 0x74, 0x8b, 0xcf, 0x89, 0xec, 0x88, 0x08, 0x47, 0x21, 0xe1, 0x6b, 0x85, 0xf3, 0x0a, 0xdb, 0x1a, 0x61, 0x34, 0xd6, 0x64, 0xb5, 0x84, 0x35, 0x69, 0xba, 0xbc, 0x5b, 0xbd, 0x1a, 0x15, 0xca, 0x9b, 0x61, 0x80, 0x3c, 0x90, 0x1a, 0x4f, 0xef, 0x32, 0x96, 0x5a, 0x17, 0x49, 0xc9, 0xf3, 0xa4, 0xe2, 0x43, 0xe1, 0x73, 0x93, 0x9d, 0xc5, 0xa8, 0xdc, 0x49, 0x5c, 0x67, 0x1a, 0xb5, 0x21, 0x45 }, { 0xaa, 0xf4, 0xd2, 0xbd, 0xf2, 0x00, 0xa9, 0x19, 0x70, 0x6d, 0x98, 0x42, 0xdc, 0xe1, 0x6c, 0x98, 0x14, 0x0d, 0x34, 0xbc, 0x43, 0x3d, 0xf3, 0x20, 0xab, 0xa9, 0xbd, 0x42, 0x9e, 0x54, 0x9a, 0xa7, 0xa3, 0x39, 0x76, 0x52, 0xa4, 0xd7, 0x68, 0x27, 0x77, 0x86, 0xcf, 0x99, 0x3c, 0xde, 0x23, 0x38, 0x67, 0x3e, 0xd2, 0xe6, 0xb6, 0x6c, 0x96, 0x1f, 0xef, 0xb8, 0x2c, 0xd2, 0x0c, 0x93, 0x33, 0x8f }, { 0xc4, 0x08, 0x21, 0x89, 0x68, 0xb7, 0x88, 0xbf, 0x86, 0x4f, 0x09, 0x97, 0xe6, 0xbc, 0x4c, 0x3d, 0xba, 0x68, 0xb2, 0x76, 0xe2, 0x12, 0x5a, 0x48, 0x43, 0x29, 0x60, 0x52, 0xff, 0x93, 0xbf, 0x57, 0x67, 0xb8, 0xcd, 0xce, 0x71, 0x31, 0xf0, 0x87, 0x64, 0x30, 0xc1, 0x16, 0x5f, 0xec, 0x6c, 0x4f, 0x47, 0xad, 0xaa, 0x4f, 0xd8, 0xbc, 0xfa, 0xce, 0xf4, 0x63, 0xb5, 0xd3, 0xd0, 0xfa, 0x61, 0xa0 }, { 0x76, 0xd2, 0xd8, 0x19, 0xc9, 0x2b, 0xce, 0x55, 0xfa, 0x8e, 0x09, 0x2a, 0xb1, 0xbf, 0x9b, 0x9e, 0xab, 0x23, 0x7a, 0x25, 0x26, 0x79, 0x86, 0xca, 0xcf, 0x2b, 0x8e, 0xe1, 0x4d, 0x21, 0x4d, 0x73, 0x0d, 0xc9, 0xa5, 0xaa, 0x2d, 0x7b, 0x59, 0x6e, 0x86, 0xa1, 0xfd, 0x8f, 0xa0, 0x80, 0x4c, 0x77, 0x40, 0x2d, 0x2f, 0xcd, 0x45, 0x08, 0x36, 0x88, 0xb2, 0x18, 0xb1, 0xcd, 0xfa, 0x0d, 0xcb, 0xcb }, { 0x72, 0x06, 0x5e, 0xe4, 0xdd, 0x91, 0xc2, 0xd8, 0x50, 0x9f, 0xa1, 0xfc, 0x28, 0xa3, 0x7c, 0x7f, 0xc9, 0xfa, 0x7d, 0x5b, 0x3f, 0x8a, 0xd3, 0xd0, 0xd7, 0xa2, 0x56, 0x26, 0xb5, 0x7b, 0x1b, 0x44, 0x78, 0x8d, 0x4c, 0xaf, 0x80, 0x62, 0x90, 0x42, 0x5f, 0x98, 0x90, 0xa3, 0xa2, 0xa3, 0x5a, 0x90, 0x5a, 0xb4, 0xb3, 0x7a, 0xcf, 0xd0, 0xda, 0x6e, 0x45, 0x17, 0xb2, 0x52, 0x5c, 0x96, 0x51, 0xe4 }, { 0x64, 0x47, 0x5d, 0xfe, 0x76, 0x00, 0xd7, 0x17, 0x1b, 0xea, 0x0b, 0x39, 0x4e, 0x27, 0xc9, 0xb0, 0x0d, 0x8e, 0x74, 0xdd, 0x1e, 0x41, 0x6a, 0x79, 0x47, 0x36, 0x82, 0xad, 0x3d, 0xfd, 0xbb, 0x70, 0x66, 0x31, 0x55, 0x80, 0x55, 0xcf, 0xc8, 0xa4, 0x0e, 0x07, 0xbd, 0x01, 0x5a, 0x45, 0x40, 0xdc, 0xde, 0xa1, 0x58, 0x83, 0xcb, 0xbf, 0x31, 0x41, 0x2d, 0xf1, 0xde, 0x1c, 0xd4, 0x15, 0x2b, 0x91 }, { 0x12, 0xcd, 0x16, 0x74, 0xa4, 0x48, 0x8a, 0x5d, 0x7c, 0x2b, 0x31, 0x60, 0xd2, 0xe2, 0xc4, 0xb5, 0x83, 0x71, 0xbe, 0xda, 0xd7, 0x93, 0x41, 0x8d, 0x6f, 0x19, 0xc6, 0xee, 0x38, 0x5d, 0x70, 0xb3, 0xe0, 0x67, 0x39, 0x36, 0x9d, 0x4d, 0xf9, 0x10, 0xed, 0xb0, 0xb0, 0xa5, 0x4c, 0xbf, 0xf4, 0x3d, 0x54, 0x54, 0x4c, 0xd3, 0x7a, 0xb3, 0xa0, 0x6c, 0xfa, 0x0a, 0x3d, 0xda, 0xc8, 0xb6, 0x6c, 0x89 }, { 0x60, 0x75, 0x69, 0x66, 0x47, 0x9d, 0xed, 0xc6, 0xdd, 0x4b, 0xcf, 0xf8, 0xea, 0x7d, 0x1d, 0x4c, 0xe4, 0xd4, 0xaf, 0x2e, 0x7b, 0x09, 0x7e, 0x32, 0xe3, 0x76, 0x35, 0x18, 0x44, 0x11, 0x47, 0xcc, 0x12, 0xb3, 0xc0, 0xee, 0x6d, 0x2e, 0xca, 0xbf, 0x11, 0x98, 0xce, 0xc9, 0x2e, 0x86, 0xa3, 0x61, 0x6f, 0xba, 0x4f, 0x4e, 0x87, 0x2f, 0x58, 0x25, 0x33, 0x0a, 0xdb, 0xb4, 0xc1, 0xde, 0xe4, 0x44 }, { 0xa7, 0x80, 0x3b, 0xcb, 0x71, 0xbc, 0x1d, 0x0f, 0x43, 0x83, 0xdd, 0xe1, 0xe0, 0x61, 0x2e, 0x04, 0xf8, 0x72, 0xb7, 0x15, 0xad, 0x30, 0x81, 0x5c, 0x22, 0x49, 0xcf, 0x34, 0xab, 0xb8, 0xb0, 0x24, 0x91, 0x5c, 0xb2, 0xfc, 0x9f, 0x4e, 0x7c, 0xc4, 0xc8, 0xcf, 0xd4, 0x5b, 0xe2, 0xd5, 0xa9, 0x1e, 0xab, 0x09, 0x41, 0xc7, 0xd2, 0x70, 0xe2, 0xda, 0x4c, 0xa4, 0xa9, 0xf7, 0xac, 0x68, 0x66, 0x3a }, { 0xb8, 0x4e, 0xf6, 0xa7, 0x22, 0x9a, 0x34, 0xa7, 0x50, 0xd9, 0xa9, 0x8e, 0xe2, 0x52, 0x98, 0x71, 0x81, 0x6b, 0x87, 0xfb, 0xe3, 0xbc, 0x45, 0xb4, 0x5f, 0xa5, 0xae, 0x82, 0xd5, 0x14, 0x15, 0x40, 0x21, 0x11, 0x65, 0xc3, 0xc5, 0xd7, 0xa7, 0x47, 0x6b, 0xa5, 0xa4, 0xaa, 0x06, 0xd6, 0x64, 0x76, 0xf0, 0xd9, 0xdc, 0x49, 0xa3, 0xf1, 0xee, 0x72, 0xc3, 0xac, 0xab, 0xd4, 0x98, 0x96, 0x74, 0x14 }, { 0xfa, 0xe4, 0xb6, 0xd8, 0xef, 0xc3, 0xf8, 0xc8, 0xe6, 0x4d, 0x00, 0x1d, 0xab, 0xec, 0x3a, 0x21, 0xf5, 0x44, 0xe8, 0x27, 0x14, 0x74, 0x52, 0x51, 0xb2, 0xb4, 0xb3, 0x93, 0xf2, 0xf4, 0x3e, 0x0d, 0xa3, 0xd4, 0x03, 0xc6, 0x4d, 0xb9, 0x5a, 0x2c, 0xb6, 0xe2, 0x3e, 0xbb, 0x7b, 0x9e, 0x94, 0xcd, 0xd5, 0xdd, 0xac, 0x54, 0xf0, 0x7c, 0x4a, 0x61, 0xbd, 0x3c, 0xb1, 0x0a, 0xa6, 0xf9, 0x3b, 0x49 }, { 0x34, 0xf7, 0x28, 0x66, 0x05, 0xa1, 0x22, 0x36, 0x95, 0x40, 0x14, 0x1d, 0xed, 0x79, 0xb8, 0x95, 0x72, 0x55, 0xda, 0x2d, 0x41, 0x55, 0xab, 0xbf, 0x5a, 0x8d, 0xbb, 0x89, 0xc8, 0xeb, 0x7e, 0xde, 0x8e, 0xee, 0xf1, 0xda, 0xa4, 0x6d, 0xc2, 0x9d, 0x75, 0x1d, 0x04, 0x5d, 0xc3, 0xb1, 0xd6, 0x58, 0xbb, 0x64, 0xb8, 0x0f, 0xf8, 0x58, 0x9e, 0xdd, 0xb3, 0x82, 0x4b, 0x13, 0xda, 0x23, 0x5a, 0x6b }, { 0x3b, 0x3b, 0x48, 0x43, 0x4b, 0xe2, 0x7b, 0x9e, 0xab, 0xab, 0xba, 0x43, 0xbf, 0x6b, 0x35, 0xf1, 0x4b, 0x30, 0xf6, 0xa8, 0x8d, 0xc2, 0xe7, 0x50, 0xc3, 0x58, 0x47, 0x0d, 0x6b, 0x3a, 0xa3, 0xc1, 0x8e, 0x47, 0xdb, 0x40, 0x17, 0xfa, 0x55, 0x10, 0x6d, 0x82, 0x52, 0xf0, 0x16, 0x37, 0x1a, 0x00, 0xf5, 0xf8, 0xb0, 0x70, 0xb7, 0x4b, 0xa5, 0xf2, 0x3c, 0xff, 0xc5, 0x51, 0x1c, 0x9f, 0x09, 0xf0 }, { 0xba, 0x28, 0x9e, 0xbd, 0x65, 0x62, 0xc4, 0x8c, 0x3e, 0x10, 0xa8, 0xad, 0x6c, 0xe0, 0x2e, 0x73, 0x43, 0x3d, 0x1e, 0x93, 0xd7, 0xc9, 0x27, 0x9d, 0x4d, 0x60, 0xa7, 0xe8, 0x79, 0xee, 0x11, 0xf4, 0x41, 0xa0, 0x00, 0xf4, 0x8e, 0xd9, 0xf7, 0xc4, 0xed, 0x87, 0xa4, 0x51, 0x36, 0xd7, 0xdc, 0xcd, 0xca, 0x48, 0x21, 0x09, 0xc7, 0x8a, 0x51, 0x06, 0x2b, 0x3b, 0xa4, 0x04, 0x4a, 0xda, 0x24, 0x69 }, { 0x02, 0x29, 0x39, 0xe2, 0x38, 0x6c, 0x5a, 0x37, 0x04, 0x98, 0x56, 0xc8, 0x50, 0xa2, 0xbb, 0x10, 0xa1, 0x3d, 0xfe, 0xa4, 0x21, 0x2b, 0x4c, 0x73, 0x2a, 0x88, 0x40, 0xa9, 0xff, 0xa5, 0xfa, 0xf5, 0x48, 0x75, 0xc5, 0x44, 0x88, 0x16, 0xb2, 0x78, 0x5a, 0x00, 0x7d, 0xa8, 0xa8, 0xd2, 0xbc, 0x7d, 0x71, 0xa5, 0x4e, 0x4e, 0x65, 0x71, 0xf1, 0x0b, 0x60, 0x0c, 0xbd, 0xb2, 0x5d, 0x13, 0xed, 0xe3 }, { 0xe6, 0xfe, 0xc1, 0x9d, 0x89, 0xce, 0x87, 0x17, 0xb1, 0xa0, 0x87, 0x02, 0x46, 0x70, 0xfe, 0x02, 0x6f, 0x6c, 0x7c, 0xbd, 0xa1, 0x1c, 0xae, 0xf9, 0x59, 0xbb, 0x2d, 0x35, 0x1b, 0xf8, 0x56, 0xf8, 0x05, 0x5d, 0x1c, 0x0e, 0xbd, 0xaa, 0xa9, 0xd1, 0xb1, 0x78, 0x86, 0xfc, 0x2c, 0x56, 0x2b, 0x5e, 0x99, 0x64, 0x2f, 0xc0, 0x64, 0x71, 0x0c, 0x0d, 0x34, 0x88, 0xa0, 0x2b, 0x5e, 0xd7, 0xf6, 0xfd }, { 0x94, 0xc9, 0x6f, 0x02, 0xa8, 0xf5, 0x76, 0xac, 0xa3, 0x2b, 0xa6, 0x1c, 0x2b, 0x20, 0x6f, 0x90, 0x72, 0x85, 0xd9, 0x29, 0x9b, 0x83, 0xac, 0x17, 0x5c, 0x20, 0x9a, 0x8d, 0x43, 0xd5, 0x3b, 0xfe, 0x68, 0x3d, 0xd1, 0xd8, 0x3e, 0x75, 0x49, 0xcb, 0x90, 0x6c, 0x28, 0xf5, 0x9a, 0xb7, 0xc4, 0x6f, 0x87, 0x51, 0x36, 0x6a, 0x28, 0xc3, 0x9d, 0xd5, 0xfe, 0x26, 0x93, 0xc9, 0x01, 0x96, 0x66, 0xc8 }, { 0x31, 0xa0, 0xcd, 0x21, 0x5e, 0xbd, 0x2c, 0xb6, 0x1d, 0xe5, 0xb9, 0xed, 0xc9, 0x1e, 0x61, 0x95, 0xe3, 0x1c, 0x59, 0xa5, 0x64, 0x8d, 0x5c, 0x9f, 0x73, 0x7e, 0x12, 0x5b, 0x26, 0x05, 0x70, 0x8f, 0x2e, 0x32, 0x5a, 0xb3, 0x38, 0x1c, 0x8d, 0xce, 0x1a, 0x3e, 0x95, 0x88, 0x86, 0xf1, 0xec, 0xdc, 0x60, 0x31, 0x8f, 0x88, 0x2c, 0xfe, 0x20, 0xa2, 0x41, 0x91, 0x35, 0x2e, 0x61, 0x7b, 0x0f, 0x21 }, { 0x91, 0xab, 0x50, 0x4a, 0x52, 0x2d, 0xce, 0x78, 0x77, 0x9f, 0x4c, 0x6c, 0x6b, 0xa2, 0xe6, 0xb6, 0xdb, 0x55, 0x65, 0xc7, 0x6d, 0x3e, 0x7e, 0x7c, 0x92, 0x0c, 0xaf, 0x7f, 0x75, 0x7e, 0xf9, 0xdb, 0x7c, 0x8f, 0xcf, 0x10, 0xe5, 0x7f, 0x03, 0x37, 0x9e, 0xa9, 0xbf, 0x75, 0xeb, 0x59, 0x89, 0x5d, 0x96, 0xe1, 0x49, 0x80, 0x0b, 0x6a, 0xae, 0x01, 0xdb, 0x77, 0x8b, 0xb9, 0x0a, 0xfb, 0xc9, 0x89 }, { 0xd8, 0x5c, 0xab, 0xc6, 0xbd, 0x5b, 0x1a, 0x01, 0xa5, 0xaf, 0xd8, 0xc6, 0x73, 0x47, 0x40, 0xda, 0x9f, 0xd1, 0xc1, 0xac, 0xc6, 0xdb, 0x29, 0xbf, 0xc8, 0xa2, 0xe5, 0xb6, 0x68, 0xb0, 0x28, 0xb6, 0xb3, 0x15, 0x4b, 0xfb, 0x87, 0x03, 0xfa, 0x31, 0x80, 0x25, 0x1d, 0x58, 0x9a, 0xd3, 0x80, 0x40, 0xce, 0xb7, 0x07, 0xc4, 0xba, 0xd1, 0xb5, 0x34, 0x3c, 0xb4, 0x26, 0xb6, 0x1e, 0xaa, 0x49, 0xc1 }, { 0xd6, 0x2e, 0xfb, 0xec, 0x2c, 0xa9, 0xc1, 0xf8, 0xbd, 0x66, 0xce, 0x8b, 0x3f, 0x6a, 0x89, 0x8c, 0xb3, 0xf7, 0x56, 0x6b, 0xa6, 0x56, 0x8c, 0x61, 0x8a, 0xd1, 0xfe, 0xb2, 0xb6, 0x5b, 0x76, 0xc3, 0xce, 0x1d, 0xd2, 0x0f, 0x73, 0x95, 0x37, 0x2f, 0xaf, 0x28, 0x42, 0x7f, 0x61, 0xc9, 0x27, 0x80, 0x49, 0xcf, 0x01, 0x40, 0xdf, 0x43, 0x4f, 0x56, 0x33, 0x04, 0x8c, 0x86, 0xb8, 0x1e, 0x03, 0x99 }, { 0x7c, 0x8f, 0xdc, 0x61, 0x75, 0x43, 0x9e, 0x2c, 0x3d, 0xb1, 0x5b, 0xaf, 0xa7, 0xfb, 0x06, 0x14, 0x3a, 0x6a, 0x23, 0xbc, 0x90, 0xf4, 0x49, 0xe7, 0x9d, 0xee, 0xf7, 0x3c, 0x3d, 0x49, 0x2a, 0x67, 0x17, 0x15, 0xc1, 0x93, 0xb6, 0xfe, 0xa9, 0xf0, 0x36, 0x05, 0x0b, 0x94, 0x60, 0x69, 0x85, 0x6b, 0x89, 0x7e, 0x08, 0xc0, 0x07, 0x68, 0xf5, 0xee, 0x5d, 0xdc, 0xf7, 0x0b, 0x7c, 0xd6, 0xd0, 0xe0 }, { 0x58, 0x60, 0x2e, 0xe7, 0x46, 0x8e, 0x6b, 0xc9, 0xdf, 0x21, 0xbd, 0x51, 0xb2, 0x3c, 0x00, 0x5f, 0x72, 0xd6, 0xcb, 0x01, 0x3f, 0x0a, 0x1b, 0x48, 0xcb, 0xec, 0x5e, 0xca, 0x29, 0x92, 0x99, 0xf9, 0x7f, 0x09, 0xf5, 0x4a, 0x9a, 0x01, 0x48, 0x3e, 0xae, 0xb3, 0x15, 0xa6, 0x47, 0x8b, 0xad, 0x37, 0xba, 0x47, 0xca, 0x13, 0x47, 0xc7, 0xc8, 0xfc, 0x9e, 0x66, 0x95, 0x59, 0x2c, 0x91, 0xd7, 0x23 }, { 0x27, 0xf5, 0xb7, 0x9e, 0xd2, 0x56, 0xb0, 0x50, 0x99, 0x3d, 0x79, 0x34, 0x96, 0xed, 0xf4, 0x80, 0x7c, 0x1d, 0x85, 0xa7, 0xb0, 0xa6, 0x7c, 0x9c, 0x4f, 0xa9, 0x98, 0x60, 0x75, 0x0b, 0x0a, 0xe6, 0x69, 0x89, 0x67, 0x0a, 0x8f, 0xfd, 0x78, 0x56, 0xd7, 0xce, 0x41, 0x15, 0x99, 0xe5, 0x8c, 0x4d, 0x77, 0xb2, 0x32, 0xa6, 0x2b, 0xef, 0x64, 0xd1, 0x52, 0x75, 0xbe, 0x46, 0xa6, 0x82, 0x35, 0xff }, { 0x39, 0x57, 0xa9, 0x76, 0xb9, 0xf1, 0x88, 0x7b, 0xf0, 0x04, 0xa8, 0xdc, 0xa9, 0x42, 0xc9, 0x2d, 0x2b, 0x37, 0xea, 0x52, 0x60, 0x0f, 0x25, 0xe0, 0xc9, 0xbc, 0x57, 0x07, 0xd0, 0x27, 0x9c, 0x00, 0xc6, 0xe8, 0x5a, 0x83, 0x9b, 0x0d, 0x2d, 0x8e, 0xb5, 0x9c, 0x51, 0xd9, 0x47, 0x88, 0xeb, 0xe6, 0x24, 0x74, 0xa7, 0x91, 0xca, 0xdf, 0x52, 0xcc, 0xcf, 0x20, 0xf5, 0x07, 0x0b, 0x65, 0x73, 0xfc }, { 0xea, 0xa2, 0x37, 0x6d, 0x55, 0x38, 0x0b, 0xf7, 0x72, 0xec, 0xca, 0x9c, 0xb0, 0xaa, 0x46, 0x68, 0xc9, 0x5c, 0x70, 0x71, 0x62, 0xfa, 0x86, 0xd5, 0x18, 0xc8, 0xce, 0x0c, 0xa9, 0xbf, 0x73, 0x62, 0xb9, 0xf2, 0xa0, 0xad, 0xc3, 0xff, 0x59, 0x92, 0x2d, 0xf9, 0x21, 0xb9, 0x45, 0x67, 0xe8, 0x1e, 0x45, 0x2f, 0x6c, 0x1a, 0x07, 0xfc, 0x81, 0x7c, 0xeb, 0xe9, 0x96, 0x04, 0xb3, 0x50, 0x5d, 0x38 }, { 0xc1, 0xe2, 0xc7, 0x8b, 0x6b, 0x27, 0x34, 0xe2, 0x48, 0x0e, 0xc5, 0x50, 0x43, 0x4c, 0xb5, 0xd6, 0x13, 0x11, 0x1a, 0xdc, 0xc2, 0x1d, 0x47, 0x55, 0x45, 0xc3, 0xb1, 0xb7, 0xe6, 0xff, 0x12, 0x44, 0x44, 0x76, 0xe5, 0xc0, 0x55, 0x13, 0x2e, 0x22, 0x29, 0xdc, 0x0f, 0x80, 0x70, 0x44, 0xbb, 0x91, 0x9b, 0x1a, 0x56, 0x62, 0xdd, 0x38, 0xa9, 0xee, 0x65, 0xe2, 0x43, 0xa3, 0x91, 0x1a, 0xed, 0x1a }, { 0x8a, 0xb4, 0x87, 0x13, 0x38, 0x9d, 0xd0, 0xfc, 0xf9, 0xf9, 0x65, 0xd3, 0xce, 0x66, 0xb1, 0xe5, 0x59, 0xa1, 0xf8, 0xc5, 0x87, 0x41, 0xd6, 0x76, 0x83, 0xcd, 0x97, 0x13, 0x54, 0xf4, 0x52, 0xe6, 0x2d, 0x02, 0x07, 0xa6, 0x5e, 0x43, 0x6c, 0x5d, 0x5d, 0x8f, 0x8e, 0xe7, 0x1c, 0x6a, 0xbf, 0xe5, 0x0e, 0x66, 0x90, 0x04, 0xc3, 0x02, 0xb3, 0x1a, 0x7e, 0xa8, 0x31, 0x1d, 0x4a, 0x91, 0x60, 0x51 }, { 0x24, 0xce, 0x0a, 0xdd, 0xaa, 0x4c, 0x65, 0x03, 0x8b, 0xd1, 0xb1, 0xc0, 0xf1, 0x45, 0x2a, 0x0b, 0x12, 0x87, 0x77, 0xaa, 0xbc, 0x94, 0xa2, 0x9d, 0xf2, 0xfd, 0x6c, 0x7e, 0x2f, 0x85, 0xf8, 0xab, 0x9a, 0xc7, 0xef, 0xf5, 0x16, 0xb0, 0xe0, 0xa8, 0x25, 0xc8, 0x4a, 0x24, 0xcf, 0xe4, 0x92, 0xea, 0xad, 0x0a, 0x63, 0x08, 0xe4, 0x6d, 0xd4, 0x2f, 0xe8, 0x33, 0x3a, 0xb9, 0x71, 0xbb, 0x30, 0xca }, { 0x51, 0x54, 0xf9, 0x29, 0xee, 0x03, 0x04, 0x5b, 0x6b, 0x0c, 0x00, 0x04, 0xfa, 0x77, 0x8e, 0xde, 0xe1, 0xd1, 0x39, 0x89, 0x32, 0x67, 0xcc, 0x84, 0x82, 0x5a, 0xd7, 0xb3, 0x6c, 0x63, 0xde, 0x32, 0x79, 0x8e, 0x4a, 0x16, 0x6d, 0x24, 0x68, 0x65, 0x61, 0x35, 0x4f, 0x63, 0xb0, 0x07, 0x09, 0xa1, 0x36, 0x4b, 0x3c, 0x24, 0x1d, 0xe3, 0xfe, 0xbf, 0x07, 0x54, 0x04, 0x58, 0x97, 0x46, 0x7c, 0xd4 }, { 0xe7, 0x4e, 0x90, 0x79, 0x20, 0xfd, 0x87, 0xbd, 0x5a, 0xd6, 0x36, 0xdd, 0x11, 0x08, 0x5e, 0x50, 0xee, 0x70, 0x45, 0x9c, 0x44, 0x3e, 0x1c, 0xe5, 0x80, 0x9a, 0xf2, 0xbc, 0x2e, 0xba, 0x39, 0xf9, 0xe6, 0xd7, 0x12, 0x8e, 0x0e, 0x37, 0x12, 0xc3, 0x16, 0xda, 0x06, 0xf4, 0x70, 0x5d, 0x78, 0xa4, 0x83, 0x8e, 0x28, 0x12, 0x1d, 0x43, 0x44, 0xa2, 0xc7, 0x9c, 0x5e, 0x0d, 0xb3, 0x07, 0xa6, 0x77 }, { 0xbf, 0x91, 0xa2, 0x23, 0x34, 0xba, 0xc2, 0x0f, 0x3f, 0xd8, 0x06, 0x63, 0xb3, 0xcd, 0x06, 0xc4, 0xe8, 0x80, 0x2f, 0x30, 0xe6, 0xb5, 0x9f, 0x90, 0xd3, 0x03, 0x5c, 0xc9, 0x79, 0x8a, 0x21, 0x7e, 0xd5, 0xa3, 0x1a, 0xbb, 0xda, 0x7f, 0xa6, 0x84, 0x28, 0x27, 0xbd, 0xf2, 0xa7, 0xa1, 0xc2, 0x1f, 0x6f, 0xcf, 0xcc, 0xbb, 0x54, 0xc6, 0xc5, 0x29, 0x26, 0xf3, 0x2d, 0xa8, 0x16, 0x26, 0x9b, 0xe1 }, { 0xd9, 0xd5, 0xc7, 0x4b, 0xe5, 0x12, 0x1b, 0x0b, 0xd7, 0x42, 0xf2, 0x6b, 0xff, 0xb8, 0xc8, 0x9f, 0x89, 0x17, 0x1f, 0x3f, 0x93, 0x49, 0x13, 0x49, 0x2b, 0x09, 0x03, 0xc2, 0x71, 0xbb, 0xe2, 0xb3, 0x39, 0x5e, 0xf2, 0x59, 0x66, 0x9b, 0xef, 0x43, 0xb5, 0x7f, 0x7f, 0xcc, 0x30, 0x27, 0xdb, 0x01, 0x82, 0x3f, 0x6b, 0xae, 0xe6, 0x6e, 0x4f, 0x9f, 0xea, 0xd4, 0xd6, 0x72, 0x6c, 0x74, 0x1f, 0xce }, { 0x50, 0xc8, 0xb8, 0xcf, 0x34, 0xcd, 0x87, 0x9f, 0x80, 0xe2, 0xfa, 0xab, 0x32, 0x30, 0xb0, 0xc0, 0xe1, 0xcc, 0x3e, 0x9d, 0xca, 0xde, 0xb1, 0xb9, 0xd9, 0x7a, 0xb9, 0x23, 0x41, 0x5d, 0xd9, 0xa1, 0xfe, 0x38, 0xad, 0xdd, 0x5c, 0x11, 0x75, 0x6c, 0x67, 0x99, 0x0b, 0x25, 0x6e, 0x95, 0xad, 0x6d, 0x8f, 0x9f, 0xed, 0xce, 0x10, 0xbf, 0x1c, 0x90, 0x67, 0x9c, 0xde, 0x0e, 0xcf, 0x1b, 0xe3, 0x47 }, { 0x0a, 0x38, 0x6e, 0x7c, 0xd5, 0xdd, 0x9b, 0x77, 0xa0, 0x35, 0xe0, 0x9f, 0xe6, 0xfe, 0xe2, 0xc8, 0xce, 0x61, 0xb5, 0x38, 0x3c, 0x87, 0xea, 0x43, 0x20, 0x50, 0x59, 0xc5, 0xe4, 0xcd, 0x4f, 0x44, 0x08, 0x31, 0x9b, 0xb0, 0xa8, 0x23, 0x60, 0xf6, 0xa5, 0x8e, 0x6c, 0x9c, 0xe3, 0xf4, 0x87, 0xc4, 0x46, 0x06, 0x3b, 0xf8, 0x13, 0xbc, 0x6b, 0xa5, 0x35, 0xe1, 0x7f, 0xc1, 0x82, 0x6c, 0xfc, 0x91 }, { 0x1f, 0x14, 0x59, 0xcb, 0x6b, 0x61, 0xcb, 0xac, 0x5f, 0x0e, 0xfe, 0x8f, 0xc4, 0x87, 0x53, 0x8f, 0x42, 0x54, 0x89, 0x87, 0xfc, 0xd5, 0x62, 0x21, 0xcf, 0xa7, 0xbe, 0xb2, 0x25, 0x04, 0x76, 0x9e, 0x79, 0x2c, 0x45, 0xad, 0xfb, 0x1d, 0x6b, 0x3d, 0x60, 0xd7, 0xb7, 0x49, 0xc8, 0xa7, 0x5b, 0x0b, 0xdf, 0x14, 0xe8, 0xea, 0x72, 0x1b, 0x95, 0xdc, 0xa5, 0x38, 0xca, 0x6e, 0x25, 0x71, 0x12, 0x09 }, { 0xe5, 0x8b, 0x38, 0x36, 0xb7, 0xd8, 0xfe, 0xdb, 0xb5, 0x0c, 0xa5, 0x72, 0x5c, 0x65, 0x71, 0xe7, 0x4c, 0x07, 0x85, 0xe9, 0x78, 0x21, 0xda, 0xb8, 0xb6, 0x29, 0x8c, 0x10, 0xe4, 0xc0, 0x79, 0xd4, 0xa6, 0xcd, 0xf2, 0x2f, 0x0f, 0xed, 0xb5, 0x50, 0x32, 0x92, 0x5c, 0x16, 0x74, 0x81, 0x15, 0xf0, 0x1a, 0x10, 0x5e, 0x77, 0xe0, 0x0c, 0xee, 0x3d, 0x07, 0x92, 0x4d, 0xc0, 0xd8, 0xf9, 0x06, 0x59 }, { 0xb9, 0x29, 0xcc, 0x65, 0x05, 0xf0, 0x20, 0x15, 0x86, 0x72, 0xde, 0xda, 0x56, 0xd0, 0xdb, 0x08, 0x1a, 0x2e, 0xe3, 0x4c, 0x00, 0xc1, 0x10, 0x00, 0x29, 0xbd, 0xf8, 0xea, 0x98, 0x03, 0x4f, 0xa4, 0xbf, 0x3e, 0x86, 0x55, 0xec, 0x69, 0x7f, 0xe3, 0x6f, 0x40, 0x55, 0x3c, 0x5b, 0xb4, 0x68, 0x01, 0x64, 0x4a, 0x62, 0x7d, 0x33, 0x42, 0xf4, 0xfc, 0x92, 0xb6, 0x1f, 0x03, 0x29, 0x0f, 0xb3, 0x81 }, { 0x72, 0xd3, 0x53, 0x99, 0x4b, 0x49, 0xd3, 0xe0, 0x31, 0x53, 0x92, 0x9a, 0x1e, 0x4d, 0x4f, 0x18, 0x8e, 0xe5, 0x8a, 0xb9, 0xe7, 0x2e, 0xe8, 0xe5, 0x12, 0xf2, 0x9b, 0xc7, 0x73, 0x91, 0x38, 0x19, 0xce, 0x05, 0x7d, 0xdd, 0x70, 0x02, 0xc0, 0x43, 0x3e, 0xe0, 0xa1, 0x61, 0x14, 0xe3, 0xd1, 0x56, 0xdd, 0x2c, 0x4a, 0x7e, 0x80, 0xee, 0x53, 0x37, 0x8b, 0x86, 0x70, 0xf2, 0x3e, 0x33, 0xef, 0x56 }, { 0xc7, 0x0e, 0xf9, 0xbf, 0xd7, 0x75, 0xd4, 0x08, 0x17, 0x67, 0x37, 0xa0, 0x73, 0x6d, 0x68, 0x51, 0x7c, 0xe1, 0xaa, 0xad, 0x7e, 0x81, 0xa9, 0x3c, 0x8c, 0x1e, 0xd9, 0x67, 0xea, 0x21, 0x4f, 0x56, 0xc8, 0xa3, 0x77, 0xb1, 0x76, 0x3e, 0x67, 0x66, 0x15, 0xb6, 0x0f, 0x39, 0x88, 0x24, 0x1e, 0xae, 0x6e, 0xab, 0x96, 0x85, 0xa5, 0x12, 0x49, 0x29, 0xd2, 0x81, 0x88, 0xf2, 0x9e, 0xab, 0x06, 0xf7 }, { 0xc2, 0x30, 0xf0, 0x80, 0x26, 0x79, 0xcb, 0x33, 0x82, 0x2e, 0xf8, 0xb3, 0xb2, 0x1b, 0xf7, 0xa9, 0xa2, 0x89, 0x42, 0x09, 0x29, 0x01, 0xd7, 0xda, 0xc3, 0x76, 0x03, 0x00, 0x83, 0x10, 0x26, 0xcf, 0x35, 0x4c, 0x92, 0x32, 0xdf, 0x3e, 0x08, 0x4d, 0x99, 0x03, 0x13, 0x0c, 0x60, 0x1f, 0x63, 0xc1, 0xf4, 0xa4, 0xa4, 0xb8, 0x10, 0x6e, 0x46, 0x8c, 0xd4, 0x43, 0xbb, 0xe5, 0xa7, 0x34, 0xf4, 0x5f }, { 0x6f, 0x43, 0x09, 0x4c, 0xaf, 0xb5, 0xeb, 0xf1, 0xf7, 0xa4, 0x93, 0x7e, 0xc5, 0x0f, 0x56, 0xa4, 0xc9, 0xda, 0x30, 0x3c, 0xbb, 0x55, 0xac, 0x1f, 0x27, 0xf1, 0xf1, 0x97, 0x6c, 0xd9, 0x6b, 0xed, 0xa9, 0x46, 0x4f, 0x0e, 0x7b, 0x9c, 0x54, 0x62, 0x0b, 0x8a, 0x9f, 0xba, 0x98, 0x31, 0x64, 0xb8, 0xbe, 0x35, 0x78, 0x42, 0x5a, 0x02, 0x4f, 0x5f, 0xe1, 0x99, 0xc3, 0x63, 0x56, 0xb8, 0x89, 0x72 }, { 0x37, 0x45, 0x27, 0x3f, 0x4c, 0x38, 0x22, 0x5d, 0xb2, 0x33, 0x73, 0x81, 0x87, 0x1a, 0x0c, 0x6a, 0xaf, 0xd3, 0xaf, 0x9b, 0x01, 0x8c, 0x88, 0xaa, 0x02, 0x02, 0x58, 0x50, 0xa5, 0xdc, 0x3a, 0x42, 0xa1, 0xa3, 0xe0, 0x3e, 0x56, 0xcb, 0xf1, 0xb0, 0x87, 0x6d, 0x63, 0xa4, 0x41, 0xf1, 0xd2, 0x85, 0x6a, 0x39, 0xb8, 0x80, 0x1e, 0xb5, 0xaf, 0x32, 0x52, 0x01, 0xc4, 0x15, 0xd6, 0x5e, 0x97, 0xfe }, { 0xc5, 0x0c, 0x44, 0xcc, 0xa3, 0xec, 0x3e, 0xda, 0xae, 0x77, 0x9a, 0x7e, 0x17, 0x94, 0x50, 0xeb, 0xdd, 0xa2, 0xf9, 0x70, 0x67, 0xc6, 0x90, 0xaa, 0x6c, 0x5a, 0x4a, 0xc7, 0xc3, 0x01, 0x39, 0xbb, 0x27, 0xc0, 0xdf, 0x4d, 0xb3, 0x22, 0x0e, 0x63, 0xcb, 0x11, 0x0d, 0x64, 0xf3, 0x7f, 0xfe, 0x07, 0x8d, 0xb7, 0x26, 0x53, 0xe2, 0xda, 0xac, 0xf9, 0x3a, 0xe3, 0xf0, 0xa2, 0xd1, 0xa7, 0xeb, 0x2e }, { 0x8a, 0xef, 0x26, 0x3e, 0x38, 0x5c, 0xbc, 0x61, 0xe1, 0x9b, 0x28, 0x91, 0x42, 0x43, 0x26, 0x2a, 0xf5, 0xaf, 0xe8, 0x72, 0x6a, 0xf3, 0xce, 0x39, 0xa7, 0x9c, 0x27, 0x02, 0x8c, 0xf3, 0xec, 0xd3, 0xf8, 0xd2, 0xdf, 0xd9, 0xcf, 0xc9, 0xad, 0x91, 0xb5, 0x8f, 0x6f, 0x20, 0x77, 0x8f, 0xd5, 0xf0, 0x28, 0x94, 0xa3, 0xd9, 0x1c, 0x7d, 0x57, 0xd1, 0xe4, 0xb8, 0x66, 0xa7, 0xf3, 0x64, 0xb6, 0xbe }, { 0x28, 0x69, 0x61, 0x41, 0xde, 0x6e, 0x2d, 0x9b, 0xcb, 0x32, 0x35, 0x57, 0x8a, 0x66, 0x16, 0x6c, 0x14, 0x48, 0xd3, 0xe9, 0x05, 0xa1, 0xb4, 0x82, 0xd4, 0x23, 0xbe, 0x4b, 0xc5, 0x36, 0x9b, 0xc8, 0xc7, 0x4d, 0xae, 0x0a, 0xcc, 0x9c, 0xc1, 0x23, 0xe1, 0xd8, 0xdd, 0xce, 0x9f, 0x97, 0x91, 0x7e, 0x8c, 0x01, 0x9c, 0x55, 0x2d, 0xa3, 0x2d, 0x39, 0xd2, 0x21, 0x9b, 0x9a, 0xbf, 0x0f, 0xa8, 0xc8 }, { 0x2f, 0xb9, 0xeb, 0x20, 0x85, 0x83, 0x01, 0x81, 0x90, 0x3a, 0x9d, 0xaf, 0xe3, 0xdb, 0x42, 0x8e, 0xe1, 0x5b, 0xe7, 0x66, 0x22, 0x24, 0xef, 0xd6, 0x43, 0x37, 0x1f, 0xb2, 0x56, 0x46, 0xae, 0xe7, 0x16, 0xe5, 0x31, 0xec, 0xa6, 0x9b, 0x2b, 0xdc, 0x82, 0x33, 0xf1, 0xa8, 0x08, 0x1f, 0xa4, 0x3d, 0xa1, 0x50, 0x03, 0x02, 0x97, 0x5a, 0x77, 0xf4, 0x2f, 0xa5, 0x92, 0x13, 0x67, 0x10, 0xe9, 0xdc }, { 0x66, 0xf9, 0xa7, 0x14, 0x3f, 0x7a, 0x33, 0x14, 0xa6, 0x69, 0xbf, 0x2e, 0x24, 0xbb, 0xb3, 0x50, 0x14, 0x26, 0x1d, 0x63, 0x9f, 0x49, 0x5b, 0x6c, 0x9c, 0x1f, 0x10, 0x4f, 0xe8, 0xe3, 0x20, 0xac, 0xa6, 0x0d, 0x45, 0x50, 0xd6, 0x9d, 0x52, 0xed, 0xbd, 0x5a, 0x3c, 0xde, 0xb4, 0x01, 0x4a, 0xe6, 0x5b, 0x1d, 0x87, 0xaa, 0x77, 0x0b, 0x69, 0xae, 0x5c, 0x15, 0xf4, 0x33, 0x0b, 0x0b, 0x0a, 0xd8 }, { 0xf4, 0xc4, 0xdd, 0x1d, 0x59, 0x4c, 0x35, 0x65, 0xe3, 0xe2, 0x5c, 0xa4, 0x3d, 0xad, 0x82, 0xf6, 0x2a, 0xbe, 0xa4, 0x83, 0x5e, 0xd4, 0xcd, 0x81, 0x1b, 0xcd, 0x97, 0x5e, 0x46, 0x27, 0x98, 0x28, 0xd4, 0x4d, 0x4c, 0x62, 0xc3, 0x67, 0x9f, 0x1b, 0x7f, 0x7b, 0x9d, 0xd4, 0x57, 0x1d, 0x7b, 0x49, 0x55, 0x73, 0x47, 0xb8, 0xc5, 0x46, 0x0c, 0xbd, 0xc1, 0xbe, 0xf6, 0x90, 0xfb, 0x2a, 0x08, 0xc0 }, { 0x8f, 0x1d, 0xc9, 0x64, 0x9c, 0x3a, 0x84, 0x55, 0x1f, 0x8f, 0x6e, 0x91, 0xca, 0xc6, 0x82, 0x42, 0xa4, 0x3b, 0x1f, 0x8f, 0x32, 0x8e, 0xe9, 0x22, 0x80, 0x25, 0x73, 0x87, 0xfa, 0x75, 0x59, 0xaa, 0x6d, 0xb1, 0x2e, 0x4a, 0xea, 0xdc, 0x2d, 0x26, 0x09, 0x91, 0x78, 0x74, 0x9c, 0x68, 0x64, 0xb3, 0x57, 0xf3, 0xf8, 0x3b, 0x2f, 0xb3, 0xef, 0xa8, 0xd2, 0xa8, 0xdb, 0x05, 0x6b, 0xed, 0x6b, 0xcc }, { 0x31, 0x39, 0xc1, 0xa7, 0xf9, 0x7a, 0xfd, 0x16, 0x75, 0xd4, 0x60, 0xeb, 0xbc, 0x07, 0xf2, 0x72, 0x8a, 0xa1, 0x50, 0xdf, 0x84, 0x96, 0x24, 0x51, 0x1e, 0xe0, 0x4b, 0x74, 0x3b, 0xa0, 0xa8, 0x33, 0x09, 0x2f, 0x18, 0xc1, 0x2d, 0xc9, 0x1b, 0x4d, 0xd2, 0x43, 0xf3, 0x33, 0x40, 0x2f, 0x59, 0xfe, 0x28, 0xab, 0xdb, 0xbb, 0xae, 0x30, 0x1e, 0x7b, 0x65, 0x9c, 0x7a, 0x26, 0xd5, 0xc0, 0xf9, 0x79 }, { 0x06, 0xf9, 0x4a, 0x29, 0x96, 0x15, 0x8a, 0x81, 0x9f, 0xe3, 0x4c, 0x40, 0xde, 0x3c, 0xf0, 0x37, 0x9f, 0xd9, 0xfb, 0x85, 0xb3, 0xe3, 0x63, 0xba, 0x39, 0x26, 0xa0, 0xe7, 0xd9, 0x60, 0xe3, 0xf4, 0xc2, 0xe0, 0xc7, 0x0c, 0x7c, 0xe0, 0xcc, 0xb2, 0xa6, 0x4f, 0xc2, 0x98, 0x69, 0xf6, 0xe7, 0xab, 0x12, 0xbd, 0x4d, 0x3f, 0x14, 0xfc, 0xe9, 0x43, 0x27, 0x90, 0x27, 0xe7, 0x85, 0xfb, 0x5c, 0x29 }, { 0xc2, 0x9c, 0x39, 0x9e, 0xf3, 0xee, 0xe8, 0x96, 0x1e, 0x87, 0x56, 0x5c, 0x1c, 0xe2, 0x63, 0x92, 0x5f, 0xc3, 0xd0, 0xce, 0x26, 0x7d, 0x13, 0xe4, 0x8d, 0xd9, 0xe7, 0x32, 0xee, 0x67, 0xb0, 0xf6, 0x9f, 0xad, 0x56, 0x40, 0x1b, 0x0f, 0x10, 0xfc, 0xaa, 0xc1, 0x19, 0x20, 0x10, 0x46, 0xcc, 0xa2, 0x8c, 0x5b, 0x14, 0xab, 0xde, 0xa3, 0x21, 0x2a, 0xe6, 0x55, 0x62, 0xf7, 0xf1, 0x38, 0xdb, 0x3d }, { 0x4c, 0xec, 0x4c, 0x9d, 0xf5, 0x2e, 0xef, 0x05, 0xc3, 0xf6, 0xfa, 0xaa, 0x97, 0x91, 0xbc, 0x74, 0x45, 0x93, 0x71, 0x83, 0x22, 0x4e, 0xcc, 0x37, 0xa1, 0xe5, 0x8d, 0x01, 0x32, 0xd3, 0x56, 0x17, 0x53, 0x1d, 0x7e, 0x79, 0x5f, 0x52, 0xaf, 0x7b, 0x1e, 0xb9, 0xd1, 0x47, 0xde, 0x12, 0x92, 0xd3, 0x45, 0xfe, 0x34, 0x18, 0x23, 0xf8, 0xe6, 0xbc, 0x1e, 0x5b, 0xad, 0xca, 0x5c, 0x65, 0x61, 0x08 }, { 0x89, 0x8b, 0xfb, 0xae, 0x93, 0xb3, 0xe1, 0x8d, 0x00, 0x69, 0x7e, 0xab, 0x7d, 0x97, 0x04, 0xfa, 0x36, 0xec, 0x33, 0x9d, 0x07, 0x61, 0x31, 0xce, 0xfd, 0xf3, 0x0e, 0xdb, 0xe8, 0xd9, 0xcc, 0x81, 0xc3, 0xa8, 0x0b, 0x12, 0x96, 0x59, 0xb1, 0x63, 0xa3, 0x23, 0xba, 0xb9, 0x79, 0x3d, 0x4f, 0xee, 0xd9, 0x2d, 0x54, 0xda, 0xe9, 0x66, 0xc7, 0x75, 0x29, 0x76, 0x4a, 0x09, 0xbe, 0x88, 0xdb, 0x45 }, { 0xee, 0x9b, 0xd0, 0x46, 0x9d, 0x3a, 0xaf, 0x4f, 0x14, 0x03, 0x5b, 0xe4, 0x8a, 0x2c, 0x3b, 0x84, 0xd9, 0xb4, 0xb1, 0xff, 0xf1, 0xd9, 0x45, 0xe1, 0xf1, 0xc1, 0xd3, 0x89, 0x80, 0xa9, 0x51, 0xbe, 0x19, 0x7b, 0x25, 0xfe, 0x22, 0xc7, 0x31, 0xf2, 0x0a, 0xea, 0xcc, 0x93, 0x0b, 0xa9, 0xc4, 0xa1, 0xf4, 0x76, 0x22, 0x27, 0x61, 0x7a, 0xd3, 0x50, 0xfd, 0xab, 0xb4, 0xe8, 0x02, 0x73, 0xa0, 0xf4 }, { 0x3d, 0x4d, 0x31, 0x13, 0x30, 0x05, 0x81, 0xcd, 0x96, 0xac, 0xbf, 0x09, 0x1c, 0x3d, 0x0f, 0x3c, 0x31, 0x01, 0x38, 0xcd, 0x69, 0x79, 0xe6, 0x02, 0x6c, 0xde, 0x62, 0x3e, 0x2d, 0xd1, 0xb2, 0x4d, 0x4a, 0x86, 0x38, 0xbe, 0xd1, 0x07, 0x33, 0x44, 0x78, 0x3a, 0xd0, 0x64, 0x9c, 0xc6, 0x30, 0x5c, 0xce, 0xc0, 0x4b, 0xeb, 0x49, 0xf3, 0x1c, 0x63, 0x30, 0x88, 0xa9, 0x9b, 0x65, 0x13, 0x02, 0x67 }, { 0x95, 0xc0, 0x59, 0x1a, 0xd9, 0x1f, 0x92, 0x1a, 0xc7, 0xbe, 0x6d, 0x9c, 0xe3, 0x7e, 0x06, 0x63, 0xed, 0x80, 0x11, 0xc1, 0xcf, 0xd6, 0xd0, 0x16, 0x2a, 0x55, 0x72, 0xe9, 0x43, 0x68, 0xba, 0xc0, 0x20, 0x24, 0x48, 0x5e, 0x6a, 0x39, 0x85, 0x4a, 0xa4, 0x6f, 0xe3, 0x8e, 0x97, 0xd6, 0xc6, 0xb1, 0x94, 0x7c, 0xd2, 0x72, 0xd8, 0x6b, 0x06, 0xbb, 0x5b, 0x2f, 0x78, 0xb9, 0xb6, 0x8d, 0x55, 0x9d }, { 0x22, 0x7b, 0x79, 0xde, 0xd3, 0x68, 0x15, 0x3b, 0xf4, 0x6c, 0x0a, 0x3c, 0xa9, 0x78, 0xbf, 0xdb, 0xef, 0x31, 0xf3, 0x02, 0x4a, 0x56, 0x65, 0x84, 0x24, 0x68, 0x49, 0x0b, 0x0f, 0xf7, 0x48, 0xae, 0x04, 0xe7, 0x83, 0x2e, 0xd4, 0xc9, 0xf4, 0x9d, 0xe9, 0xb1, 0x70, 0x67, 0x09, 0xd6, 0x23, 0xe5, 0xc8, 0xc1, 0x5e, 0x3c, 0xae, 0xca, 0xe8, 0xd5, 0xe4, 0x33, 0x43, 0x0f, 0xf7, 0x2f, 0x20, 0xeb }, { 0x5d, 0x34, 0xf3, 0x95, 0x2f, 0x01, 0x05, 0xee, 0xf8, 0x8a, 0xe8, 0xb6, 0x4c, 0x6c, 0xe9, 0x5e, 0xbf, 0xad, 0xe0, 0xe0, 0x2c, 0x69, 0xb0, 0x87, 0x62, 0xa8, 0x71, 0x2d, 0x2e, 0x49, 0x11, 0xad, 0x3f, 0x94, 0x1f, 0xc4, 0x03, 0x4d, 0xc9, 0xb2, 0xe4, 0x79, 0xfd, 0xbc, 0xd2, 0x79, 0xb9, 0x02, 0xfa, 0xf5, 0xd8, 0x38, 0xbb, 0x2e, 0x0c, 0x64, 0x95, 0xd3, 0x72, 0xb5, 0xb7, 0x02, 0x98, 0x13 }, { 0x7f, 0x93, 0x9b, 0xf8, 0x35, 0x3a, 0xbc, 0xe4, 0x9e, 0x77, 0xf1, 0x4f, 0x37, 0x50, 0xaf, 0x20, 0xb7, 0xb0, 0x39, 0x02, 0xe1, 0xa1, 0xe7, 0xfb, 0x6a, 0xaf, 0x76, 0xd0, 0x25, 0x9c, 0xd4, 0x01, 0xa8, 0x31, 0x90, 0xf1, 0x56, 0x40, 0xe7, 0x4f, 0x3e, 0x6c, 0x5a, 0x90, 0xe8, 0x39, 0xc7, 0x82, 0x1f, 0x64, 0x74, 0x75, 0x7f, 0x75, 0xc7, 0xbf, 0x90, 0x02, 0x08, 0x4d, 0xdc, 0x7a, 0x62, 0xdc }, { 0x06, 0x2b, 0x61, 0xa2, 0xf9, 0xa3, 0x3a, 0x71, 0xd7, 0xd0, 0xa0, 0x61, 0x19, 0x64, 0x4c, 0x70, 0xb0, 0x71, 0x6a, 0x50, 0x4d, 0xe7, 0xe5, 0xe1, 0xbe, 0x49, 0xbd, 0x7b, 0x86, 0xe7, 0xed, 0x68, 0x17, 0x71, 0x4f, 0x9f, 0x0f, 0xc3, 0x13, 0xd0, 0x61, 0x29, 0x59, 0x7e, 0x9a, 0x22, 0x35, 0xec, 0x85, 0x21, 0xde, 0x36, 0xf7, 0x29, 0x0a, 0x90, 0xcc, 0xfc, 0x1f, 0xfa, 0x6d, 0x0a, 0xee, 0x29 }, { 0xf2, 0x9e, 0x01, 0xee, 0xae, 0x64, 0x31, 0x1e, 0xb7, 0xf1, 0xc6, 0x42, 0x2f, 0x94, 0x6b, 0xf7, 0xbe, 0xa3, 0x63, 0x79, 0x52, 0x3e, 0x7b, 0x2b, 0xba, 0xba, 0x7d, 0x1d, 0x34, 0xa2, 0x2d, 0x5e, 0xa5, 0xf1, 0xc5, 0xa0, 0x9d, 0x5c, 0xe1, 0xfe, 0x68, 0x2c, 0xce, 0xd9, 0xa4, 0x79, 0x8d, 0x1a, 0x05, 0xb4, 0x6c, 0xd7, 0x2d, 0xff, 0x5c, 0x1b, 0x35, 0x54, 0x40, 0xb2, 0xa2, 0xd4, 0x76, 0xbc }, { 0xec, 0x38, 0xcd, 0x3b, 0xba, 0xb3, 0xef, 0x35, 0xd7, 0xcb, 0x6d, 0x5c, 0x91, 0x42, 0x98, 0x35, 0x1d, 0x8a, 0x9d, 0xc9, 0x7f, 0xce, 0xe0, 0x51, 0xa8, 0xa0, 0x2f, 0x58, 0xe3, 0xed, 0x61, 0x84, 0xd0, 0xb7, 0x81, 0x0a, 0x56, 0x15, 0x41, 0x1a, 0xb1, 0xb9, 0x52, 0x09, 0xc3, 0xc8, 0x10, 0x11, 0x4f, 0xde, 0xb2, 0x24, 0x52, 0x08, 0x4e, 0x77, 0xf3, 0xf8, 0x47, 0xc6, 0xdb, 0xaa, 0xfe, 0x16 }, { 0xc2, 0xae, 0xf5, 0xe0, 0xca, 0x43, 0xe8, 0x26, 0x41, 0x56, 0x5b, 0x8c, 0xb9, 0x43, 0xaa, 0x8b, 0xa5, 0x35, 0x50, 0xca, 0xef, 0x79, 0x3b, 0x65, 0x32, 0xfa, 0xfa, 0xd9, 0x4b, 0x81, 0x60, 0x82, 0xf0, 0x11, 0x3a, 0x3e, 0xa2, 0xf6, 0x36, 0x08, 0xab, 0x40, 0x43, 0x7e, 0xcc, 0x0f, 0x02, 0x29, 0xcb, 0x8f, 0xa2, 0x24, 0xdc, 0xf1, 0xc4, 0x78, 0xa6, 0x7d, 0x9b, 0x64, 0x16, 0x2b, 0x92, 0xd1 }, { 0x15, 0xf5, 0x34, 0xef, 0xff, 0x71, 0x05, 0xcd, 0x1c, 0x25, 0x4d, 0x07, 0x4e, 0x27, 0xd5, 0x89, 0x8b, 0x89, 0x31, 0x3b, 0x7d, 0x36, 0x6d, 0xc2, 0xd7, 0xd8, 0x71, 0x13, 0xfa, 0x7d, 0x53, 0xaa, 0xe1, 0x3f, 0x6d, 0xba, 0x48, 0x7a, 0xd8, 0x10, 0x3d, 0x5e, 0x85, 0x4c, 0x91, 0xfd, 0xb6, 0xe1, 0xe7, 0x4b, 0x2e, 0xf6, 0xd1, 0x43, 0x17, 0x69, 0xc3, 0x07, 0x67, 0xdd, 0xe0, 0x67, 0xa3, 0x5c }, { 0x89, 0xac, 0xbc, 0xa0, 0xb1, 0x69, 0x89, 0x7a, 0x0a, 0x27, 0x14, 0xc2, 0xdf, 0x8c, 0x95, 0xb5, 0xb7, 0x9c, 0xb6, 0x93, 0x90, 0x14, 0x2b, 0x7d, 0x60, 0x18, 0xbb, 0x3e, 0x30, 0x76, 0xb0, 0x99, 0xb7, 0x9a, 0x96, 0x41, 0x52, 0xa9, 0xd9, 0x12, 0xb1, 0xb8, 0x64, 0x12, 0xb7, 0xe3, 0x72, 0xe9, 0xce, 0xca, 0xd7, 0xf2, 0x5d, 0x4c, 0xba, 0xb8, 0xa3, 0x17, 0xbe, 0x36, 0x49, 0x2a, 0x67, 0xd7 }, { 0xe3, 0xc0, 0x73, 0x91, 0x90, 0xed, 0x84, 0x9c, 0x9c, 0x96, 0x2f, 0xd9, 0xdb, 0xb5, 0x5e, 0x20, 0x7e, 0x62, 0x4f, 0xca, 0xc1, 0xeb, 0x41, 0x76, 0x91, 0x51, 0x54, 0x99, 0xee, 0xa8, 0xd8, 0x26, 0x7b, 0x7e, 0x8f, 0x12, 0x87, 0xa6, 0x36, 0x33, 0xaf, 0x50, 0x11, 0xfd, 0xe8, 0xc4, 0xdd, 0xf5, 0x5b, 0xfd, 0xf7, 0x22, 0xed, 0xf8, 0x88, 0x31, 0x41, 0x4f, 0x2c, 0xfa, 0xed, 0x59, 0xcb, 0x9a }, { 0x8d, 0x6c, 0xf8, 0x7c, 0x08, 0x38, 0x0d, 0x2d, 0x15, 0x06, 0xee, 0xe4, 0x6f, 0xd4, 0x22, 0x2d, 0x21, 0xd8, 0xc0, 0x4e, 0x58, 0x5f, 0xbf, 0xd0, 0x82, 0x69, 0xc9, 0x8f, 0x70, 0x28, 0x33, 0xa1, 0x56, 0x32, 0x6a, 0x07, 0x24, 0x65, 0x64, 0x00, 0xee, 0x09, 0x35, 0x1d, 0x57, 0xb4, 0x40, 0x17, 0x5e, 0x2a, 0x5d, 0xe9, 0x3c, 0xc5, 0xf8, 0x0d, 0xb6, 0xda, 0xf8, 0x35, 0x76, 0xcf, 0x75, 0xfa }, { 0xda, 0x24, 0xbe, 0xde, 0x38, 0x36, 0x66, 0xd5, 0x63, 0xee, 0xed, 0x37, 0xf6, 0x31, 0x9b, 0xaf, 0x20, 0xd5, 0xc7, 0x5d, 0x16, 0x35, 0xa6, 0xba, 0x5e, 0xf4, 0xcf, 0xa1, 0xac, 0x95, 0x48, 0x7e, 0x96, 0xf8, 0xc0, 0x8a, 0xf6, 0x00, 0xaa, 0xb8, 0x7c, 0x98, 0x6e, 0xba, 0xd4, 0x9f, 0xc7, 0x0a, 0x58, 0xb4, 0x89, 0x0b, 0x9c, 0x87, 0x6e, 0x09, 0x10, 0x16, 0xda, 0xf4, 0x9e, 0x1d, 0x32, 0x2e }, { 0xf9, 0xd1, 0xd1, 0xb1, 0xe8, 0x7e, 0xa7, 0xae, 0x75, 0x3a, 0x02, 0x97, 0x50, 0xcc, 0x1c, 0xf3, 0xd0, 0x15, 0x7d, 0x41, 0x80, 0x5e, 0x24, 0x5c, 0x56, 0x17, 0xbb, 0x93, 0x4e, 0x73, 0x2f, 0x0a, 0xe3, 0x18, 0x0b, 0x78, 0xe0, 0x5b, 0xfe, 0x76, 0xc7, 0xc3, 0x05, 0x1e, 0x3e, 0x3a, 0xc7, 0x8b, 0x9b, 0x50, 0xc0, 0x51, 0x42, 0x65, 0x7e, 0x1e, 0x03, 0x21, 0x5d, 0x6e, 0xc7, 0xbf, 0xd0, 0xfc }, { 0x11, 0xb7, 0xbc, 0x16, 0x68, 0x03, 0x20, 0x48, 0xaa, 0x43, 0x34, 0x3d, 0xe4, 0x76, 0x39, 0x5e, 0x81, 0x4b, 0xbb, 0xc2, 0x23, 0x67, 0x8d, 0xb9, 0x51, 0xa1, 0xb0, 0x3a, 0x02, 0x1e, 0xfa, 0xc9, 0x48, 0xcf, 0xbe, 0x21, 0x5f, 0x97, 0xfe, 0x9a, 0x72, 0xa2, 0xf6, 0xbc, 0x03, 0x9e, 0x39, 0x56, 0xbf, 0xa4, 0x17, 0xc1, 0xa9, 0xf1, 0x0d, 0x6d, 0x7b, 0xa5, 0xd3, 0xd3, 0x2f, 0xf3, 0x23, 0xe5 }, { 0xb8, 0xd9, 0x00, 0x0e, 0x4f, 0xc2, 0xb0, 0x66, 0xed, 0xb9, 0x1a, 0xfe, 0xe8, 0xe7, 0xeb, 0x0f, 0x24, 0xe3, 0xa2, 0x01, 0xdb, 0x8b, 0x67, 0x93, 0xc0, 0x60, 0x85, 0x81, 0xe6, 0x28, 0xed, 0x0b, 0xcc, 0x4e, 0x5a, 0xa6, 0x78, 0x79, 0x92, 0xa4, 0xbc, 0xc4, 0x4e, 0x28, 0x80, 0x93, 0xe6, 0x3e, 0xe8, 0x3a, 0xbd, 0x0b, 0xc3, 0xec, 0x6d, 0x09, 0x34, 0xa6, 0x74, 0xa4, 0xda, 0x13, 0x83, 0x8a }, { 0xce, 0x32, 0x5e, 0x29, 0x4f, 0x9b, 0x67, 0x19, 0xd6, 0xb6, 0x12, 0x78, 0x27, 0x6a, 0xe0, 0x6a, 0x25, 0x64, 0xc0, 0x3b, 0xb0, 0xb7, 0x83, 0xfa, 0xfe, 0x78, 0x5b, 0xdf, 0x89, 0xc7, 0xd5, 0xac, 0xd8, 0x3e, 0x78, 0x75, 0x6d, 0x30, 0x1b, 0x44, 0x56, 0x99, 0x02, 0x4e, 0xae, 0xb7, 0x7b, 0x54, 0xd4, 0x77, 0x33, 0x6e, 0xc2, 0xa4, 0xf3, 0x32, 0xf2, 0xb3, 0xf8, 0x87, 0x65, 0xdd, 0xb0, 0xc3 }, { 0x29, 0xac, 0xc3, 0x0e, 0x96, 0x03, 0xae, 0x2f, 0xcc, 0xf9, 0x0b, 0xf9, 0x7e, 0x6c, 0xc4, 0x63, 0xeb, 0xe2, 0x8c, 0x1b, 0x2f, 0x9b, 0x4b, 0x76, 0x5e, 0x70, 0x53, 0x7c, 0x25, 0xc7, 0x02, 0xa2, 0x9d, 0xcb, 0xfb, 0xf1, 0x4c, 0x99, 0xc5, 0x43, 0x45, 0xba, 0x2b, 0x51, 0xf1, 0x7b, 0x77, 0xb5, 0xf1, 0x5d, 0xb9, 0x2b, 0xba, 0xd8, 0xfa, 0x95, 0xc4, 0x71, 0xf5, 0xd0, 0x70, 0xa1, 0x37, 0xcc }, { 0x33, 0x79, 0xcb, 0xaa, 0xe5, 0x62, 0xa8, 0x7b, 0x4c, 0x04, 0x25, 0x55, 0x0f, 0xfd, 0xd6, 0xbf, 0xe1, 0x20, 0x3f, 0x0d, 0x66, 0x6c, 0xc7, 0xea, 0x09, 0x5b, 0xe4, 0x07, 0xa5, 0xdf, 0xe6, 0x1e, 0xe9, 0x14, 0x41, 0xcd, 0x51, 0x54, 0xb3, 0xe5, 0x3b, 0x4f, 0x5f, 0xb3, 0x1a, 0xd4, 0xc7, 0xa9, 0xad, 0x5c, 0x7a, 0xf4, 0xae, 0x67, 0x9a, 0xa5, 0x1a, 0x54, 0x00, 0x3a, 0x54, 0xca, 0x6b, 0x2d }, { 0x30, 0x95, 0xa3, 0x49, 0xd2, 0x45, 0x70, 0x8c, 0x7c, 0xf5, 0x50, 0x11, 0x87, 0x03, 0xd7, 0x30, 0x2c, 0x27, 0xb6, 0x0a, 0xf5, 0xd4, 0xe6, 0x7f, 0xc9, 0x78, 0xf8, 0xa4, 0xe6, 0x09, 0x53, 0xc7, 0xa0, 0x4f, 0x92, 0xfc, 0xf4, 0x1a, 0xee, 0x64, 0x32, 0x1c, 0xcb, 0x70, 0x7a, 0x89, 0x58, 0x51, 0x55, 0x2b, 0x1e, 0x37, 0xb0, 0x0b, 0xc5, 0xe6, 0xb7, 0x2f, 0xa5, 0xbc, 0xef, 0x9e, 0x3f, 0xff }, { 0x07, 0x26, 0x2d, 0x73, 0x8b, 0x09, 0x32, 0x1f, 0x4d, 0xbc, 0xce, 0xc4, 0xbb, 0x26, 0xf4, 0x8c, 0xb0, 0xf0, 0xed, 0x24, 0x6c, 0xe0, 0xb3, 0x1b, 0x9a, 0x6e, 0x7b, 0xc6, 0x83, 0x04, 0x9f, 0x1f, 0x3e, 0x55, 0x45, 0xf2, 0x8c, 0xe9, 0x32, 0xdd, 0x98, 0x5c, 0x5a, 0xb0, 0xf4, 0x3b, 0xd6, 0xde, 0x07, 0x70, 0x56, 0x0a, 0xf3, 0x29, 0x06, 0x5e, 0xd2, 0xe4, 0x9d, 0x34, 0x62, 0x4c, 0x2c, 0xbb }, { 0xb6, 0x40, 0x5e, 0xca, 0x8e, 0xe3, 0x31, 0x6c, 0x87, 0x06, 0x1c, 0xc6, 0xec, 0x18, 0xdb, 0xa5, 0x3e, 0x6c, 0x25, 0x0c, 0x63, 0xba, 0x1f, 0x3b, 0xae, 0x9e, 0x55, 0xdd, 0x34, 0x98, 0x03, 0x6a, 0xf0, 0x8c, 0xd2, 0x72, 0xaa, 0x24, 0xd7, 0x13, 0xc6, 0x02, 0x0d, 0x77, 0xab, 0x2f, 0x39, 0x19, 0xaf, 0x1a, 0x32, 0xf3, 0x07, 0x42, 0x06, 0x18, 0xab, 0x97, 0xe7, 0x39, 0x53, 0x99, 0x4f, 0xb4 }, { 0x7e, 0xe6, 0x82, 0xf6, 0x31, 0x48, 0xee, 0x45, 0xf6, 0xe5, 0x31, 0x5d, 0xa8, 0x1e, 0x5c, 0x6e, 0x55, 0x7c, 0x2c, 0x34, 0x64, 0x1f, 0xc5, 0x09, 0xc7, 0xa5, 0x70, 0x10, 0x88, 0xc3, 0x8a, 0x74, 0x75, 0x61, 0x68, 0xe2, 0xcd, 0x8d, 0x35, 0x1e, 0x88, 0xfd, 0x1a, 0x45, 0x1f, 0x36, 0x0a, 0x01, 0xf5, 0xb2, 0x58, 0x0f, 0x9b, 0x5a, 0x2e, 0x8c, 0xfc, 0x13, 0x8f, 0x3d, 0xd5, 0x9a, 0x3f, 0xfc }, { 0x1d, 0x26, 0x3c, 0x17, 0x9d, 0x6b, 0x26, 0x8f, 0x6f, 0xa0, 0x16, 0xf3, 0xa4, 0xf2, 0x9e, 0x94, 0x38, 0x91, 0x12, 0x5e, 0xd8, 0x59, 0x3c, 0x81, 0x25, 0x60, 0x59, 0xf5, 0xa7, 0xb4, 0x4a, 0xf2, 0xdc, 0xb2, 0x03, 0x0d, 0x17, 0x5c, 0x00, 0xe6, 0x2e, 0xca, 0xf7, 0xee, 0x96, 0x68, 0x2a, 0xa0, 0x7a, 0xb2, 0x0a, 0x61, 0x10, 0x24, 0xa2, 0x85, 0x32, 0xb1, 0xc2, 0x5b, 0x86, 0x65, 0x79, 0x02 }, { 0x10, 0x6d, 0x13, 0x2c, 0xbd, 0xb4, 0xcd, 0x25, 0x97, 0x81, 0x28, 0x46, 0xe2, 0xbc, 0x1b, 0xf7, 0x32, 0xfe, 0xc5, 0xf0, 0xa5, 0xf6, 0x5d, 0xbb, 0x39, 0xec, 0x4e, 0x6d, 0xc6, 0x4a, 0xb2, 0xce, 0x6d, 0x24, 0x63, 0x0d, 0x0f, 0x15, 0xa8, 0x05, 0xc3, 0x54, 0x00, 0x25, 0xd8, 0x4a, 0xfa, 0x98, 0xe3, 0x67, 0x03, 0xc3, 0xdb, 0xee, 0x71, 0x3e, 0x72, 0xdd, 0xe8, 0x46, 0x5b, 0xc1, 0xbe, 0x7e }, { 0x0e, 0x79, 0x96, 0x82, 0x26, 0x65, 0x06, 0x67, 0xa8, 0xd8, 0x62, 0xea, 0x8d, 0xa4, 0x89, 0x1a, 0xf5, 0x6a, 0x4e, 0x3a, 0x8b, 0x6d, 0x17, 0x50, 0xe3, 0x94, 0xf0, 0xde, 0xa7, 0x6d, 0x64, 0x0d, 0x85, 0x07, 0x7b, 0xce, 0xc2, 0xcc, 0x86, 0x88, 0x6e, 0x50, 0x67, 0x51, 0xb4, 0xf6, 0xa5, 0x83, 0x8f, 0x7f, 0x0b, 0x5f, 0xef, 0x76, 0x5d, 0x9d, 0xc9, 0x0d, 0xcd, 0xcb, 0xaf, 0x07, 0x9f, 0x08 }, { 0x52, 0x11, 0x56, 0xa8, 0x2a, 0xb0, 0xc4, 0xe5, 0x66, 0xe5, 0x84, 0x4d, 0x5e, 0x31, 0xad, 0x9a, 0xaf, 0x14, 0x4b, 0xbd, 0x5a, 0x46, 0x4f, 0xdc, 0xa3, 0x4d, 0xbd, 0x57, 0x17, 0xe8, 0xff, 0x71, 0x1d, 0x3f, 0xfe, 0xbb, 0xfa, 0x08, 0x5d, 0x67, 0xfe, 0x99, 0x6a, 0x34, 0xf6, 0xd3, 0xe4, 0xe6, 0x0b, 0x13, 0x96, 0xbf, 0x4b, 0x16, 0x10, 0xc2, 0x63, 0xbd, 0xbb, 0x83, 0x4d, 0x56, 0x08, 0x16 }, { 0x1a, 0xba, 0x88, 0xbe, 0xfc, 0x55, 0xbc, 0x25, 0xef, 0xbc, 0xe0, 0x2d, 0xb8, 0xb9, 0x93, 0x3e, 0x46, 0xf5, 0x76, 0x61, 0xba, 0xea, 0xbe, 0xb2, 0x1c, 0xc2, 0x57, 0x4d, 0x2a, 0x51, 0x8a, 0x3c, 0xba, 0x5d, 0xc5, 0xa3, 0x8e, 0x49, 0x71, 0x34, 0x40, 0xb2, 0x5f, 0x9c, 0x74, 0x4e, 0x75, 0xf6, 0xb8, 0x5c, 0x9d, 0x8f, 0x46, 0x81, 0xf6, 0x76, 0x16, 0x0f, 0x61, 0x05, 0x35, 0x7b, 0x84, 0x06 }, { 0x5a, 0x99, 0x49, 0xfc, 0xb2, 0xc4, 0x73, 0xcd, 0xa9, 0x68, 0xac, 0x1b, 0x5d, 0x08, 0x56, 0x6d, 0xc2, 0xd8, 0x16, 0xd9, 0x60, 0xf5, 0x7e, 0x63, 0xb8, 0x98, 0xfa, 0x70, 0x1c, 0xf8, 0xeb, 0xd3, 0xf5, 0x9b, 0x12, 0x4d, 0x95, 0xbf, 0xbb, 0xed, 0xc5, 0xf1, 0xcf, 0x0e, 0x17, 0xd5, 0xea, 0xed, 0x0c, 0x02, 0xc5, 0x0b, 0x69, 0xd8, 0xa4, 0x02, 0xca, 0xbc, 0xca, 0x44, 0x33, 0xb5, 0x1f, 0xd4 }, { 0xb0, 0xce, 0xad, 0x09, 0x80, 0x7c, 0x67, 0x2a, 0xf2, 0xeb, 0x2b, 0x0f, 0x06, 0xdd, 0xe4, 0x6c, 0xf5, 0x37, 0x0e, 0x15, 0xa4, 0x09, 0x6b, 0x1a, 0x7d, 0x7c, 0xbb, 0x36, 0xec, 0x31, 0xc2, 0x05, 0xfb, 0xef, 0xca, 0x00, 0xb7, 0xa4, 0x16, 0x2f, 0xa8, 0x9f, 0xb4, 0xfb, 0x3e, 0xb7, 0x8d, 0x79, 0x77, 0x0c, 0x23, 0xf4, 0x4e, 0x72, 0x06, 0x66, 0x4c, 0xe3, 0xcd, 0x93, 0x1c, 0x29, 0x1e, 0x5d }, { 0xbb, 0x66, 0x64, 0x93, 0x1e, 0xc9, 0x70, 0x44, 0xe4, 0x5b, 0x2a, 0xe4, 0x20, 0xae, 0x1c, 0x55, 0x1a, 0x88, 0x74, 0xbc, 0x93, 0x7d, 0x08, 0xe9, 0x69, 0x39, 0x9c, 0x39, 0x64, 0xeb, 0xdb, 0xa8, 0x34, 0x6c, 0xdd, 0x5d, 0x09, 0xca, 0xaf, 0xe4, 0xc2, 0x8b, 0xa7, 0xec, 0x78, 0x81, 0x91, 0xce, 0xca, 0x65, 0xdd, 0xd6, 0xf9, 0x5f, 0x18, 0x58, 0x3e, 0x04, 0x0d, 0x0f, 0x30, 0xd0, 0x36, 0x4d }, { 0x65, 0xbc, 0x77, 0x0a, 0x5f, 0xaa, 0x37, 0x92, 0x36, 0x98, 0x03, 0x68, 0x3e, 0x84, 0x4b, 0x0b, 0xe7, 0xee, 0x96, 0xf2, 0x9f, 0x6d, 0x6a, 0x35, 0x56, 0x80, 0x06, 0xbd, 0x55, 0x90, 0xf9, 0xa4, 0xef, 0x63, 0x9b, 0x7a, 0x80, 0x61, 0xc7, 0xb0, 0x42, 0x4b, 0x66, 0xb6, 0x0a, 0xc3, 0x4a, 0xf3, 0x11, 0x99, 0x05, 0xf3, 0x3a, 0x9d, 0x8c, 0x3a, 0xe1, 0x83, 0x82, 0xca, 0x9b, 0x68, 0x99, 0x00 }, { 0xea, 0x9b, 0x4d, 0xca, 0x33, 0x33, 0x36, 0xaa, 0xf8, 0x39, 0xa4, 0x5c, 0x6e, 0xaa, 0x48, 0xb8, 0xcb, 0x4c, 0x7d, 0xda, 0xbf, 0xfe, 0xa4, 0xf6, 0x43, 0xd6, 0x35, 0x7e, 0xa6, 0x62, 0x8a, 0x48, 0x0a, 0x5b, 0x45, 0xf2, 0xb0, 0x52, 0xc1, 0xb0, 0x7d, 0x1f, 0xed, 0xca, 0x91, 0x8b, 0x6f, 0x11, 0x39, 0xd8, 0x0f, 0x74, 0xc2, 0x45, 0x10, 0xdc, 0xba, 0xa4, 0xbe, 0x70, 0xea, 0xcc, 0x1b, 0x06 }, { 0xe6, 0x34, 0x2f, 0xb4, 0xa7, 0x80, 0xad, 0x97, 0x5d, 0x0e, 0x24, 0xbc, 0xe1, 0x49, 0x98, 0x9b, 0x91, 0xd3, 0x60, 0x55, 0x7e, 0x87, 0x99, 0x4f, 0x6b, 0x45, 0x7b, 0x89, 0x55, 0x75, 0xcc, 0x02, 0xd0, 0xc1, 0x5b, 0xad, 0x3c, 0xe7, 0x57, 0x7f, 0x4c, 0x63, 0x92, 0x7f, 0xf1, 0x3f, 0x3e, 0x38, 0x1f, 0xf7, 0xe7, 0x2b, 0xdb, 0xe7, 0x45, 0x32, 0x48, 0x44, 0xa9, 0xd2, 0x7e, 0x3f, 0x1c, 0x01 }, { 0x3e, 0x20, 0x9c, 0x9b, 0x33, 0xe8, 0xe4, 0x61, 0x17, 0x8a, 0xb4, 0x6b, 0x1c, 0x64, 0xb4, 0x9a, 0x07, 0xfb, 0x74, 0x5f, 0x1c, 0x8b, 0xc9, 0x5f, 0xbf, 0xb9, 0x4c, 0x6b, 0x87, 0xc6, 0x95, 0x16, 0x65, 0x1b, 0x26, 0x4e, 0xf9, 0x80, 0x93, 0x7f, 0xad, 0x41, 0x23, 0x8b, 0x91, 0xdd, 0xc0, 0x11, 0xa5, 0xdd, 0x77, 0x7c, 0x7e, 0xfd, 0x44, 0x94, 0xb4, 0xb6, 0xec, 0xd3, 0xa9, 0xc2, 0x2a, 0xc0 }, { 0xfd, 0x6a, 0x3d, 0x5b, 0x18, 0x75, 0xd8, 0x04, 0x86, 0xd6, 0xe6, 0x96, 0x94, 0xa5, 0x6d, 0xbb, 0x04, 0xa9, 0x9a, 0x4d, 0x05, 0x1f, 0x15, 0xdb, 0x26, 0x89, 0x77, 0x6b, 0xa1, 0xc4, 0x88, 0x2e, 0x6d, 0x46, 0x2a, 0x60, 0x3b, 0x70, 0x15, 0xdc, 0x9f, 0x4b, 0x74, 0x50, 0xf0, 0x53, 0x94, 0x30, 0x3b, 0x86, 0x52, 0xcf, 0xb4, 0x04, 0xa2, 0x66, 0x96, 0x2c, 0x41, 0xba, 0xe6, 0xe1, 0x8a, 0x94 }, { 0x95, 0x1e, 0x27, 0x51, 0x7e, 0x6b, 0xad, 0x9e, 0x41, 0x95, 0xfc, 0x86, 0x71, 0xde, 0xe3, 0xe7, 0xe9, 0xbe, 0x69, 0xce, 0xe1, 0x42, 0x2c, 0xb9, 0xfe, 0xcf, 0xce, 0x0d, 0xba, 0x87, 0x5f, 0x7b, 0x31, 0x0b, 0x93, 0xee, 0x3a, 0x3d, 0x55, 0x8f, 0x94, 0x1f, 0x63, 0x5f, 0x66, 0x8f, 0xf8, 0x32, 0xd2, 0xc1, 0xd0, 0x33, 0xc5, 0xe2, 0xf0, 0x99, 0x7e, 0x4c, 0x66, 0xf1, 0x47, 0x34, 0x4e, 0x02 }, { 0x8e, 0xba, 0x2f, 0x87, 0x4f, 0x1a, 0xe8, 0x40, 0x41, 0x90, 0x3c, 0x7c, 0x42, 0x53, 0xc8, 0x22, 0x92, 0x53, 0x0f, 0xc8, 0x50, 0x95, 0x50, 0xbf, 0xdc, 0x34, 0xc9, 0x5c, 0x7e, 0x28, 0x89, 0xd5, 0x65, 0x0b, 0x0a, 0xd8, 0xcb, 0x98, 0x8e, 0x5c, 0x48, 0x94, 0xcb, 0x87, 0xfb, 0xfb, 0xb1, 0x96, 0x12, 0xea, 0x93, 0xcc, 0xc4, 0xc5, 0xca, 0xd1, 0x71, 0x58, 0xb9, 0x76, 0x34, 0x64, 0xb4, 0x92 }, { 0x16, 0xf7, 0x12, 0xea, 0xa1, 0xb7, 0xc6, 0x35, 0x47, 0x19, 0xa8, 0xe7, 0xdb, 0xdf, 0xaf, 0x55, 0xe4, 0x06, 0x3a, 0x4d, 0x27, 0x7d, 0x94, 0x75, 0x50, 0x01, 0x9b, 0x38, 0xdf, 0xb5, 0x64, 0x83, 0x09, 0x11, 0x05, 0x7d, 0x50, 0x50, 0x61, 0x36, 0xe2, 0x39, 0x4c, 0x3b, 0x28, 0x94, 0x5c, 0xc9, 0x64, 0x96, 0x7d, 0x54, 0xe3, 0x00, 0x0c, 0x21, 0x81, 0x62, 0x6c, 0xfb, 0x9b, 0x73, 0xef, 0xd2 }, { 0xc3, 0x96, 0x39, 0xe7, 0xd5, 0xc7, 0xfb, 0x8c, 0xdd, 0x0f, 0xd3, 0xe6, 0xa5, 0x20, 0x96, 0x03, 0x94, 0x37, 0x12, 0x2f, 0x21, 0xc7, 0x8f, 0x16, 0x79, 0xce, 0xa9, 0xd7, 0x8a, 0x73, 0x4c, 0x56, 0xec, 0xbe, 0xb2, 0x86, 0x54, 0xb4, 0xf1, 0x8e, 0x34, 0x2c, 0x33, 0x1f, 0x6f, 0x72, 0x29, 0xec, 0x4b, 0x4b, 0xc2, 0x81, 0xb2, 0xd8, 0x0a, 0x6e, 0xb5, 0x00, 0x43, 0xf3, 0x17, 0x96, 0xc8, 0x8c }, { 0x72, 0xd0, 0x81, 0xaf, 0x99, 0xf8, 0xa1, 0x73, 0xdc, 0xc9, 0xa0, 0xac, 0x4e, 0xb3, 0x55, 0x74, 0x05, 0x63, 0x9a, 0x29, 0x08, 0x4b, 0x54, 0xa4, 0x01, 0x72, 0x91, 0x2a, 0x2f, 0x8a, 0x39, 0x51, 0x29, 0xd5, 0x53, 0x6f, 0x09, 0x18, 0xe9, 0x02, 0xf9, 0xe8, 0xfa, 0x60, 0x00, 0x99, 0x5f, 0x41, 0x68, 0xdd, 0xc5, 0xf8, 0x93, 0x01, 0x1b, 0xe6, 0xa0, 0xdb, 0xc9, 0xb8, 0xa1, 0xa3, 0xf5, 0xbb }, { 0xc1, 0x1a, 0xa8, 0x1e, 0x5e, 0xfd, 0x24, 0xd5, 0xfc, 0x27, 0xee, 0x58, 0x6c, 0xfd, 0x88, 0x47, 0xfb, 0xb0, 0xe2, 0x76, 0x01, 0xcc, 0xec, 0xe5, 0xec, 0xca, 0x01, 0x98, 0xe3, 0xc7, 0x76, 0x53, 0x93, 0xbb, 0x74, 0x45, 0x7c, 0x7e, 0x7a, 0x27, 0xeb, 0x91, 0x70, 0x35, 0x0e, 0x1f, 0xb5, 0x38, 0x57, 0x17, 0x75, 0x06, 0xbe, 0x3e, 0x76, 0x2c, 0xc0, 0xf1, 0x4d, 0x8c, 0x3a, 0xfe, 0x90, 0x77 }, { 0xc2, 0x8f, 0x21, 0x50, 0xb4, 0x52, 0xe6, 0xc0, 0xc4, 0x24, 0xbc, 0xde, 0x6f, 0x8d, 0x72, 0x00, 0x7f, 0x93, 0x10, 0xfe, 0xd7, 0xf2, 0xf8, 0x7d, 0xe0, 0xdb, 0xb6, 0x4f, 0x44, 0x79, 0xd6, 0xc1, 0x44, 0x1b, 0xa6, 0x6f, 0x44, 0xb2, 0xac, 0xce, 0xe6, 0x16, 0x09, 0x17, 0x7e, 0xd3, 0x40, 0x12, 0x8b, 0x40, 0x7e, 0xce, 0xc7, 0xc6, 0x4b, 0xbe, 0x50, 0xd6, 0x3d, 0x22, 0xd8, 0x62, 0x77, 0x27 }, { 0xf6, 0x3d, 0x88, 0x12, 0x28, 0x77, 0xec, 0x30, 0xb8, 0xc8, 0xb0, 0x0d, 0x22, 0xe8, 0x90, 0x00, 0xa9, 0x66, 0x42, 0x61, 0x12, 0xbd, 0x44, 0x16, 0x6e, 0x2f, 0x52, 0x5b, 0x76, 0x9c, 0xcb, 0xe9, 0xb2, 0x86, 0xd4, 0x37, 0xa0, 0x12, 0x91, 0x30, 0xdd, 0xe1, 0xa8, 0x6c, 0x43, 0xe0, 0x4b, 0xed, 0xb5, 0x94, 0xe6, 0x71, 0xd9, 0x82, 0x83, 0xaf, 0xe6, 0x4c, 0xe3, 0x31, 0xde, 0x98, 0x28, 0xfd }, { 0x34, 0x8b, 0x05, 0x32, 0x88, 0x0b, 0x88, 0xa6, 0x61, 0x4a, 0x8d, 0x74, 0x08, 0xc3, 0xf9, 0x13, 0x35, 0x7f, 0xbb, 0x60, 0xe9, 0x95, 0xc6, 0x02, 0x05, 0xbe, 0x91, 0x39, 0xe7, 0x49, 0x98, 0xae, 0xde, 0x7f, 0x45, 0x81, 0xe4, 0x2f, 0x6b, 0x52, 0x69, 0x8f, 0x7f, 0xa1, 0x21, 0x97, 0x08, 0xc1, 0x44, 0x98, 0x06, 0x7f, 0xd1, 0xe0, 0x95, 0x02, 0xde, 0x83, 0xa7, 0x7d, 0xd2, 0x81, 0x15, 0x0c }, { 0x51, 0x33, 0xdc, 0x8b, 0xef, 0x72, 0x53, 0x59, 0xdf, 0xf5, 0x97, 0x92, 0xd8, 0x5e, 0xaf, 0x75, 0xb7, 0xe1, 0xdc, 0xd1, 0x97, 0x8b, 0x01, 0xc3, 0x5b, 0x1b, 0x85, 0xfc, 0xeb, 0xc6, 0x33, 0x88, 0xad, 0x99, 0xa1, 0x7b, 0x63, 0x46, 0xa2, 0x17, 0xdc, 0x1a, 0x96, 0x22, 0xeb, 0xd1, 0x22, 0xec, 0xf6, 0x91, 0x3c, 0x4d, 0x31, 0xa6, 0xb5, 0x2a, 0x69, 0x5b, 0x86, 0xaf, 0x00, 0xd7, 0x41, 0xa0 }, { 0x27, 0x53, 0xc4, 0xc0, 0xe9, 0x8e, 0xca, 0xd8, 0x06, 0xe8, 0x87, 0x80, 0xec, 0x27, 0xfc, 0xcd, 0x0f, 0x5c, 0x1a, 0xb5, 0x47, 0xf9, 0xe4, 0xbf, 0x16, 0x59, 0xd1, 0x92, 0xc2, 0x3a, 0xa2, 0xcc, 0x97, 0x1b, 0x58, 0xb6, 0x80, 0x25, 0x80, 0xba, 0xef, 0x8a, 0xdc, 0x3b, 0x77, 0x6e, 0xf7, 0x08, 0x6b, 0x25, 0x45, 0xc2, 0x98, 0x7f, 0x34, 0x8e, 0xe3, 0x71, 0x9c, 0xde, 0xf2, 0x58, 0xc4, 0x03 }, { 0xb1, 0x66, 0x35, 0x73, 0xce, 0x4b, 0x9d, 0x8c, 0xae, 0xfc, 0x86, 0x50, 0x12, 0xf3, 0xe3, 0x97, 0x14, 0xb9, 0x89, 0x8a, 0x5d, 0xa6, 0xce, 0x17, 0xc2, 0x5a, 0x6a, 0x47, 0x93, 0x1a, 0x9d, 0xdb, 0x9b, 0xbe, 0x98, 0xad, 0xaa, 0x55, 0x3b, 0xee, 0xd4, 0x36, 0xe8, 0x95, 0x78, 0x45, 0x54, 0x16, 0xc2, 0xa5, 0x2a, 0x52, 0x5c, 0xf2, 0x86, 0x2b, 0x8d, 0x1d, 0x49, 0xa2, 0x53, 0x1b, 0x73, 0x91 }, { 0x64, 0xf5, 0x8b, 0xd6, 0xbf, 0xc8, 0x56, 0xf5, 0xe8, 0x73, 0xb2, 0xa2, 0x95, 0x6e, 0xa0, 0xed, 0xa0, 0xd6, 0xdb, 0x0d, 0xa3, 0x9c, 0x8c, 0x7f, 0xc6, 0x7c, 0x9f, 0x9f, 0xee, 0xfc, 0xff, 0x30, 0x72, 0xcd, 0xf9, 0xe6, 0xea, 0x37, 0xf6, 0x9a, 0x44, 0xf0, 0xc6, 0x1a, 0xa0, 0xda, 0x36, 0x93, 0xc2, 0xdb, 0x5b, 0x54, 0x96, 0x0c, 0x02, 0x81, 0xa0, 0x88, 0x15, 0x1d, 0xb4, 0x2b, 0x11, 0xe8 }, { 0x07, 0x64, 0xc7, 0xbe, 0x28, 0x12, 0x5d, 0x90, 0x65, 0xc4, 0xb9, 0x8a, 0x69, 0xd6, 0x0a, 0xed, 0xe7, 0x03, 0x54, 0x7c, 0x66, 0xa1, 0x2e, 0x17, 0xe1, 0xc6, 0x18, 0x99, 0x41, 0x32, 0xf5, 0xef, 0x82, 0x48, 0x2c, 0x1e, 0x3f, 0xe3, 0x14, 0x6c, 0xc6, 0x53, 0x76, 0xcc, 0x10, 0x9f, 0x01, 0x38, 0xed, 0x9a, 0x80, 0xe4, 0x9f, 0x1f, 0x3c, 0x7d, 0x61, 0x0d, 0x2f, 0x24, 0x32, 0xf2, 0x06, 0x05 }, { 0xf7, 0x48, 0x78, 0x43, 0x98, 0xa2, 0xff, 0x03, 0xeb, 0xeb, 0x07, 0xe1, 0x55, 0xe6, 0x61, 0x16, 0xa8, 0x39, 0x74, 0x1a, 0x33, 0x6e, 0x32, 0xda, 0x71, 0xec, 0x69, 0x60, 0x01, 0xf0, 0xad, 0x1b, 0x25, 0xcd, 0x48, 0xc6, 0x9c, 0xfc, 0xa7, 0x26, 0x5e, 0xca, 0x1d, 0xd7, 0x19, 0x04, 0xa0, 0xce, 0x74, 0x8a, 0xc4, 0x12, 0x4f, 0x35, 0x71, 0x07, 0x6d, 0xfa, 0x71, 0x16, 0xa9, 0xcf, 0x00, 0xe9 }, { 0x3f, 0x0d, 0xbc, 0x01, 0x86, 0xbc, 0xeb, 0x6b, 0x78, 0x5b, 0xa7, 0x8d, 0x2a, 0x2a, 0x01, 0x3c, 0x91, 0x0b, 0xe1, 0x57, 0xbd, 0xaf, 0xfa, 0xe8, 0x1b, 0xb6, 0x66, 0x3b, 0x1a, 0x73, 0x72, 0x2f, 0x7f, 0x12, 0x28, 0x79, 0x5f, 0x3e, 0xca, 0xda, 0x87, 0xcf, 0x6e, 0xf0, 0x07, 0x84, 0x74, 0xaf, 0x73, 0xf3, 0x1e, 0xca, 0x0c, 0xc2, 0x00, 0xed, 0x97, 0x5b, 0x68, 0x93, 0xf7, 0x61, 0xcb, 0x6d }, { 0xd4, 0x76, 0x2c, 0xd4, 0x59, 0x98, 0x76, 0xca, 0x75, 0xb2, 0xb8, 0xfe, 0x24, 0x99, 0x44, 0xdb, 0xd2, 0x7a, 0xce, 0x74, 0x1f, 0xda, 0xb9, 0x36, 0x16, 0xcb, 0xc6, 0xe4, 0x25, 0x46, 0x0f, 0xeb, 0x51, 0xd4, 0xe7, 0xad, 0xcc, 0x38, 0x18, 0x0e, 0x7f, 0xc4, 0x7c, 0x89, 0x02, 0x4a, 0x7f, 0x56, 0x19, 0x1a, 0xdb, 0x87, 0x8d, 0xfd, 0xe4, 0xea, 0xd6, 0x22, 0x23, 0xf5, 0xa2, 0x61, 0x0e, 0xfe }, { 0xcd, 0x36, 0xb3, 0xd5, 0xb4, 0xc9, 0x1b, 0x90, 0xfc, 0xbb, 0xa7, 0x95, 0x13, 0xcf, 0xee, 0x19, 0x07, 0xd8, 0x64, 0x5a, 0x16, 0x2a, 0xfd, 0x0c, 0xd4, 0xcf, 0x41, 0x92, 0xd4, 0xa5, 0xf4, 0xc8, 0x92, 0x18, 0x3a, 0x8e, 0xac, 0xdb, 0x2b, 0x6b, 0x6a, 0x9d, 0x9a, 0xa8, 0xc1, 0x1a, 0xc1, 0xb2, 0x61, 0xb3, 0x80, 0xdb, 0xee, 0x24, 0xca, 0x46, 0x8f, 0x1b, 0xfd, 0x04, 0x3c, 0x58, 0xee, 0xfe }, { 0x98, 0x59, 0x34, 0x52, 0x28, 0x16, 0x61, 0xa5, 0x3c, 0x48, 0xa9, 0xd8, 0xcd, 0x79, 0x08, 0x26, 0xc1, 0xa1, 0xce, 0x56, 0x77, 0x38, 0x05, 0x3d, 0x0b, 0xee, 0x4a, 0x91, 0xa3, 0xd5, 0xbd, 0x92, 0xee, 0xfd, 0xba, 0xbe, 0xbe, 0x32, 0x04, 0xf2, 0x03, 0x1c, 0xa5, 0xf7, 0x81, 0xbd, 0xa9, 0x9e, 0xf5, 0xd8, 0xae, 0x56, 0xe5, 0xb0, 0x4a, 0x9e, 0x1e, 0xcd, 0x21, 0xb0, 0xeb, 0x05, 0xd3, 0xe1 }, { 0x77, 0x1f, 0x57, 0xdd, 0x27, 0x75, 0xcc, 0xda, 0xb5, 0x59, 0x21, 0xd3, 0xe8, 0xe3, 0x0c, 0xcf, 0x48, 0x4d, 0x61, 0xfe, 0x1c, 0x1b, 0x9c, 0x2a, 0xe8, 0x19, 0xd0, 0xfb, 0x2a, 0x12, 0xfa, 0xb9, 0xbe, 0x70, 0xc4, 0xa7, 0xa1, 0x38, 0xda, 0x84, 0xe8, 0x28, 0x04, 0x35, 0xda, 0xad, 0xe5, 0xbb, 0xe6, 0x6a, 0xf0, 0x83, 0x6a, 0x15, 0x4f, 0x81, 0x7f, 0xb1, 0x7f, 0x33, 0x97, 0xe7, 0x25, 0xa3 }, { 0xc6, 0x08, 0x97, 0xc6, 0xf8, 0x28, 0xe2, 0x1f, 0x16, 0xfb, 0xb5, 0xf1, 0x5b, 0x32, 0x3f, 0x87, 0xb6, 0xc8, 0x95, 0x5e, 0xab, 0xf1, 0xd3, 0x80, 0x61, 0xf7, 0x07, 0xf6, 0x08, 0xab, 0xdd, 0x99, 0x3f, 0xac, 0x30, 0x70, 0x63, 0x3e, 0x28, 0x6c, 0xf8, 0x33, 0x9c, 0xe2, 0x95, 0xdd, 0x35, 0x2d, 0xf4, 0xb4, 0xb4, 0x0b, 0x2f, 0x29, 0xda, 0x1d, 0xd5, 0x0b, 0x3a, 0x05, 0xd0, 0x79, 0xe6, 0xbb }, { 0x82, 0x10, 0xcd, 0x2c, 0x2d, 0x3b, 0x13, 0x5c, 0x2c, 0xf0, 0x7f, 0xa0, 0xd1, 0x43, 0x3c, 0xd7, 0x71, 0xf3, 0x25, 0xd0, 0x75, 0xc6, 0x46, 0x9d, 0x9c, 0x7f, 0x1b, 0xa0, 0x94, 0x3c, 0xd4, 0xab, 0x09, 0x80, 0x8c, 0xab, 0xf4, 0xac, 0xb9, 0xce, 0x5b, 0xb8, 0x8b, 0x49, 0x89, 0x29, 0xb4, 0xb8, 0x47, 0xf6, 0x81, 0xad, 0x2c, 0x49, 0x0d, 0x04, 0x2d, 0xb2, 0xae, 0xc9, 0x42, 0x14, 0xb0, 0x6b }, { 0x1d, 0x4e, 0xdf, 0xff, 0xd8, 0xfd, 0x80, 0xf7, 0xe4, 0x10, 0x78, 0x40, 0xfa, 0x3a, 0xa3, 0x1e, 0x32, 0x59, 0x84, 0x91, 0xe4, 0xaf, 0x70, 0x13, 0xc1, 0x97, 0xa6, 0x5b, 0x7f, 0x36, 0xdd, 0x3a, 0xc4, 0xb4, 0x78, 0x45, 0x61, 0x11, 0xcd, 0x43, 0x09, 0xd9, 0x24, 0x35, 0x10, 0x78, 0x2f, 0xa3, 0x1b, 0x7c, 0x4c, 0x95, 0xfa, 0x95, 0x15, 0x20, 0xd0, 0x20, 0xeb, 0x7e, 0x5c, 0x36, 0xe4, 0xef }, { 0xaf, 0x8e, 0x6e, 0x91, 0xfa, 0xb4, 0x6c, 0xe4, 0x87, 0x3e, 0x1a, 0x50, 0xa8, 0xef, 0x44, 0x8c, 0xc2, 0x91, 0x21, 0xf7, 0xf7, 0x4d, 0xee, 0xf3, 0x4a, 0x71, 0xef, 0x89, 0xcc, 0x00, 0xd9, 0x27, 0x4b, 0xc6, 0xc2, 0x45, 0x4b, 0xbb, 0x32, 0x30, 0xd8, 0xb2, 0xec, 0x94, 0xc6, 0x2b, 0x1d, 0xec, 0x85, 0xf3, 0x59, 0x3b, 0xfa, 0x30, 0xea, 0x6f, 0x7a, 0x44, 0xd7, 0xc0, 0x94, 0x65, 0xa2, 0x53 }, { 0x29, 0xfd, 0x38, 0x4e, 0xd4, 0x90, 0x6f, 0x2d, 0x13, 0xaa, 0x9f, 0xe7, 0xaf, 0x90, 0x59, 0x90, 0x93, 0x8b, 0xed, 0x80, 0x7f, 0x18, 0x32, 0x45, 0x4a, 0x37, 0x2a, 0xb4, 0x12, 0xee, 0xa1, 0xf5, 0x62, 0x5a, 0x1f, 0xcc, 0x9a, 0xc8, 0x34, 0x3b, 0x7c, 0x67, 0xc5, 0xab, 0xa6, 0xe0, 0xb1, 0xcc, 0x46, 0x44, 0x65, 0x49, 0x13, 0x69, 0x2c, 0x6b, 0x39, 0xeb, 0x91, 0x87, 0xce, 0xac, 0xd3, 0xec }, { 0xa2, 0x68, 0xc7, 0x88, 0x5d, 0x98, 0x74, 0xa5, 0x1c, 0x44, 0xdf, 0xfe, 0xd8, 0xea, 0x53, 0xe9, 0x4f, 0x78, 0x45, 0x6e, 0x0b, 0x2e, 0xd9, 0x9f, 0xf5, 0xa3, 0x92, 0x47, 0x60, 0x81, 0x38, 0x26, 0xd9, 0x60, 0xa1, 0x5e, 0xdb, 0xed, 0xbb, 0x5d, 0xe5, 0x22, 0x6b, 0xa4, 0xb0, 0x74, 0xe7, 0x1b, 0x05, 0xc5, 0x5b, 0x97, 0x56, 0xbb, 0x79, 0xe5, 0x5c, 0x02, 0x75, 0x4c, 0x2c, 0x7b, 0x6c, 0x8a }, { 0x0c, 0xf8, 0x54, 0x54, 0x88, 0xd5, 0x6a, 0x86, 0x81, 0x7c, 0xd7, 0xec, 0xb1, 0x0f, 0x71, 0x16, 0xb7, 0xea, 0x53, 0x0a, 0x45, 0xb6, 0xea, 0x49, 0x7b, 0x6c, 0x72, 0xc9, 0x97, 0xe0, 0x9e, 0x3d, 0x0d, 0xa8, 0x69, 0x8f, 0x46, 0xbb, 0x00, 0x6f, 0xc9, 0x77, 0xc2, 0xcd, 0x3d, 0x11, 0x77, 0x46, 0x3a, 0xc9, 0x05, 0x7f, 0xdd, 0x16, 0x62, 0xc8, 0x5d, 0x0c, 0x12, 0x64, 0x43, 0xc1, 0x04, 0x73 }, { 0xb3, 0x96, 0x14, 0x26, 0x8f, 0xdd, 0x87, 0x81, 0x51, 0x5e, 0x2c, 0xfe, 0xbf, 0x89, 0xb4, 0xd5, 0x40, 0x2b, 0xab, 0x10, 0xc2, 0x26, 0xe6, 0x34, 0x4e, 0x6b, 0x9a, 0xe0, 0x00, 0xfb, 0x0d, 0x6c, 0x79, 0xcb, 0x2f, 0x3e, 0xc8, 0x0e, 0x80, 0xea, 0xeb, 0x19, 0x80, 0xd2, 0xf8, 0x69, 0x89, 0x16, 0xbd, 0x2e, 0x9f, 0x74, 0x72, 0x36, 0x65, 0x51, 0x16, 0x64, 0x9c, 0xd3, 0xca, 0x23, 0xa8, 0x37 }, { 0x74, 0xbe, 0xf0, 0x92, 0xfc, 0x6f, 0x1e, 0x5d, 0xba, 0x36, 0x63, 0xa3, 0xfb, 0x00, 0x3b, 0x2a, 0x5b, 0xa2, 0x57, 0x49, 0x65, 0x36, 0xd9, 0x9f, 0x62, 0xb9, 0xd7, 0x3f, 0x8f, 0x9e, 0xb3, 0xce, 0x9f, 0xf3, 0xee, 0xc7, 0x09, 0xeb, 0x88, 0x36, 0x55, 0xec, 0x9e, 0xb8, 0x96, 0xb9, 0x12, 0x8f, 0x2a, 0xfc, 0x89, 0xcf, 0x7d, 0x1a, 0xb5, 0x8a, 0x72, 0xf4, 0xa3, 0xbf, 0x03, 0x4d, 0x2b, 0x4a }, { 0x3a, 0x98, 0x8d, 0x38, 0xd7, 0x56, 0x11, 0xf3, 0xef, 0x38, 0xb8, 0x77, 0x49, 0x80, 0xb3, 0x3e, 0x57, 0x3b, 0x6c, 0x57, 0xbe, 0xe0, 0x46, 0x9b, 0xa5, 0xee, 0xd9, 0xb4, 0x4f, 0x29, 0x94, 0x5e, 0x73, 0x47, 0x96, 0x7f, 0xba, 0x2c, 0x16, 0x2e, 0x1c, 0x3b, 0xe7, 0xf3, 0x10, 0xf2, 0xf7, 0x5e, 0xe2, 0x38, 0x1e, 0x7b, 0xfd, 0x6b, 0x3f, 0x0b, 0xae, 0xa8, 0xd9, 0x5d, 0xfb, 0x1d, 0xaf, 0xb1 }, { 0x58, 0xae, 0xdf, 0xce, 0x6f, 0x67, 0xdd, 0xc8, 0x5a, 0x28, 0xc9, 0x92, 0xf1, 0xc0, 0xbd, 0x09, 0x69, 0xf0, 0x41, 0xe6, 0x6f, 0x1e, 0xe8, 0x80, 0x20, 0xa1, 0x25, 0xcb, 0xfc, 0xfe, 0xbc, 0xd6, 0x17, 0x09, 0xc9, 0xc4, 0xeb, 0xa1, 0x92, 0xc1, 0x5e, 0x69, 0xf0, 0x20, 0xd4, 0x62, 0x48, 0x60, 0x19, 0xfa, 0x8d, 0xea, 0x0c, 0xd7, 0xa4, 0x29, 0x21, 0xa1, 0x9d, 0x2f, 0xe5, 0x46, 0xd4, 0x3d }, { 0x93, 0x47, 0xbd, 0x29, 0x14, 0x73, 0xe6, 0xb4, 0xe3, 0x68, 0x43, 0x7b, 0x8e, 0x56, 0x1e, 0x06, 0x5f, 0x64, 0x9a, 0x6d, 0x8a, 0xda, 0x47, 0x9a, 0xd0, 0x9b, 0x19, 0x99, 0xa8, 0xf2, 0x6b, 0x91, 0xcf, 0x61, 0x20, 0xfd, 0x3b, 0xfe, 0x01, 0x4e, 0x83, 0xf2, 0x3a, 0xcf, 0xa4, 0xc0, 0xad, 0x7b, 0x37, 0x12, 0xb2, 0xc3, 0xc0, 0x73, 0x32, 0x70, 0x66, 0x31, 0x12, 0xcc, 0xd9, 0x28, 0x5c, 0xd9 }, { 0xb3, 0x21, 0x63, 0xe7, 0xc5, 0xdb, 0xb5, 0xf5, 0x1f, 0xdc, 0x11, 0xd2, 0xea, 0xc8, 0x75, 0xef, 0xbb, 0xcb, 0x7e, 0x76, 0x99, 0x09, 0x0a, 0x7e, 0x7f, 0xf8, 0xa8, 0xd5, 0x07, 0x95, 0xaf, 0x5d, 0x74, 0xd9, 0xff, 0x98, 0x54, 0x3e, 0xf8, 0xcd, 0xf8, 0x9a, 0xc1, 0x3d, 0x04, 0x85, 0x27, 0x87, 0x56, 0xe0, 0xef, 0x00, 0xc8, 0x17, 0x74, 0x56, 0x61, 0xe1, 0xd5, 0x9f, 0xe3, 0x8e, 0x75, 0x37 }, { 0x10, 0x85, 0xd7, 0x83, 0x07, 0xb1, 0xc4, 0xb0, 0x08, 0xc5, 0x7a, 0x2e, 0x7e, 0x5b, 0x23, 0x46, 0x58, 0xa0, 0xa8, 0x2e, 0x4f, 0xf1, 0xe4, 0xaa, 0xac, 0x72, 0xb3, 0x12, 0xfd, 0xa0, 0xfe, 0x27, 0xd2, 0x33, 0xbc, 0x5b, 0x10, 0xe9, 0xcc, 0x17, 0xfd, 0xc7, 0x69, 0x7b, 0x54, 0x0c, 0x7d, 0x95, 0xeb, 0x21, 0x5a, 0x19, 0xa1, 0xa0, 0xe2, 0x0e, 0x1a, 0xbf, 0xa1, 0x26, 0xef, 0xd5, 0x68, 0xc7 }, { 0x4e, 0x5c, 0x73, 0x4c, 0x7d, 0xde, 0x01, 0x1d, 0x83, 0xea, 0xc2, 0xb7, 0x34, 0x7b, 0x37, 0x35, 0x94, 0xf9, 0x2d, 0x70, 0x91, 0xb9, 0xca, 0x34, 0xcb, 0x9c, 0x6f, 0x39, 0xbd, 0xf5, 0xa8, 0xd2, 0xf1, 0x34, 0x37, 0x9e, 0x16, 0xd8, 0x22, 0xf6, 0x52, 0x21, 0x70, 0xcc, 0xf2, 0xdd, 0xd5, 0x5c, 0x84, 0xb9, 0xe6, 0xc6, 0x4f, 0xc9, 0x27, 0xac, 0x4c, 0xf8, 0xdf, 0xb2, 0xa1, 0x77, 0x01, 0xf2 }, { 0x69, 0x5d, 0x83, 0xbd, 0x99, 0x0a, 0x11, 0x17, 0xb3, 0xd0, 0xce, 0x06, 0xcc, 0x88, 0x80, 0x27, 0xd1, 0x2a, 0x05, 0x4c, 0x26, 0x77, 0xfd, 0x82, 0xf0, 0xd4, 0xfb, 0xfc, 0x93, 0x57, 0x55, 0x23, 0xe7, 0x99, 0x1a, 0x5e, 0x35, 0xa3, 0x75, 0x2e, 0x9b, 0x70, 0xce, 0x62, 0x99, 0x2e, 0x26, 0x8a, 0x87, 0x77, 0x44, 0xcd, 0xd4, 0x35, 0xf5, 0xf1, 0x30, 0x86, 0x9c, 0x9a, 0x20, 0x74, 0xb3, 0x38 }, { 0xa6, 0x21, 0x37, 0x43, 0x56, 0x8e, 0x3b, 0x31, 0x58, 0xb9, 0x18, 0x43, 0x01, 0xf3, 0x69, 0x08, 0x47, 0x55, 0x4c, 0x68, 0x45, 0x7c, 0xb4, 0x0f, 0xc9, 0xa4, 0xb8, 0xcf, 0xd8, 0xd4, 0xa1, 0x18, 0xc3, 0x01, 0xa0, 0x77, 0x37, 0xae, 0xda, 0x0f, 0x92, 0x9c, 0x68, 0x91, 0x3c, 0x5f, 0x51, 0xc8, 0x03, 0x94, 0xf5, 0x3b, 0xff, 0x1c, 0x3e, 0x83, 0xb2, 0xe4, 0x0c, 0xa9, 0x7e, 0xba, 0x9e, 0x15 }, { 0xd4, 0x44, 0xbf, 0xa2, 0x36, 0x2a, 0x96, 0xdf, 0x21, 0x3d, 0x07, 0x0e, 0x33, 0xfa, 0x84, 0x1f, 0x51, 0x33, 0x4e, 0x4e, 0x76, 0x86, 0x6b, 0x81, 0x39, 0xe8, 0xaf, 0x3b, 0xb3, 0x39, 0x8b, 0xe2, 0xdf, 0xad, 0xdc, 0xbc, 0x56, 0xb9, 0x14, 0x6d, 0xe9, 0xf6, 0x81, 0x18, 0xdc, 0x58, 0x29, 0xe7, 0x4b, 0x0c, 0x28, 0xd7, 0x71, 0x19, 0x07, 0xb1, 0x21, 0xf9, 0x16, 0x1c, 0xb9, 0x2b, 0x69, 0xa9 }, { 0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97, 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5, 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b, 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d, 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d, 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61 }, }; unsigned char inp[1000], out[1000]; unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f }; unsigned long ilen, klen = sizeof(key), mlen = 64; blake2bmac_state st; for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; for (ilen = 0; ilen < 256; ilen++) { const unsigned char *mac = tests[ilen]; unsigned long olen = mlen; /* process piece by piece */ if (ilen > 15) { blake2bmac_init(&st, olen, key, klen); blake2bmac_process(&st, (unsigned char*)inp, 5); blake2bmac_process(&st, (unsigned char*)inp + 5, 4); blake2bmac_process(&st, (unsigned char*)inp + 9, 3); blake2bmac_process(&st, (unsigned char*)inp + 12, 2); blake2bmac_process(&st, (unsigned char*)inp + 14, 1); blake2bmac_process(&st, (unsigned char*)inp + 15, ilen - 15); blake2bmac_done(&st, out, &olen); if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; } /* process in one go */ blake2bmac_init(&st, olen, key, klen); blake2bmac_process(&st, (unsigned char*)inp, ilen); blake2bmac_done(&st, out, &olen); if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2smac.c000066400000000000000000000032561464416617300242620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2SMAC /** Initialize an BLAKE2S MAC context. @param st The BLAKE2S MAC state @param outlen The size of the MAC output (octets) @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); return blake2s_init(st, outlen, key, keylen); } /** Process data through BLAKE2S MAC @param st The BLAKE2S MAC state @param in The data to send through HMAC @param inlen The length of the data to HMAC (octets) @return CRYPT_OK if successful */ int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen) { if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); return blake2s_process(st, in, inlen); } /** Terminate a BLAKE2S MAC session @param st The BLAKE2S MAC state @param mac [out] The destination of the BLAKE2S MAC authentication tag @param maclen [in/out] The max size and resulting size of the BLAKE2S MAC authentication tag @return CRYPT_OK if successful */ int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); LTC_ARGCHK(*maclen >= st->blake2s.outlen); *maclen = st->blake2s.outlen; return blake2s_done(st, mac); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2smac_file.c000066400000000000000000000036051464416617300252570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2SMAC /** BLAKE2S MAC a file @param fname The name of the file you wish to BLAKE2S MAC @param key The secret key @param keylen The length of the secret key @param mac [out] The BLAKE2S MAC authentication tag @param maclen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(fname); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(mac); LTC_UNUSED_PARAM(maclen); return CRYPT_NOP; #else blake2smac_state st; FILE *in; unsigned char *buf; size_t x; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(fname, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = blake2smac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = blake2smac_done(&st, mac, maclen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(blake2smac_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory.c000066400000000000000000000023551464416617300256510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2SMAC /** BLAKE2S MAC a block of memory to produce the authentication tag @param key The secret key @param keylen The length of the secret key (octets) @param in The data to BLAKE2S MAC @param inlen The length of the data to BLAKE2S MAC (octets) @param mac [out] Destination of the authentication tag @param maclen [in/out] Max size and resulting size of authentication tag @return CRYPT_OK if successful */ int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) { blake2smac_state st; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = blake2smac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } err = blake2smac_done(&st, mac, maclen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(blake2smac_state)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c000066400000000000000000000032711464416617300270610ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include #ifdef LTC_BLAKE2SMAC /** BLAKE2S MAC multiple blocks of memory to produce the authentication tag @param key The secret key @param keylen The length of the secret key (octets) @param mac [out] Destination of the authentication tag @param maclen [in/out] Max size and resulting size of authentication tag @param in The data to BLAKE2S MAC @param inlen The length of the data to BLAKE2S MAC (octets) @param ... tuples of (data,len) pairs to BLAKE2S MAC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) { blake2smac_state st; int err; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); va_start(args, inlen); curptr = in; curlen = inlen; if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } for (;;) { if ((err = blake2smac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } curptr = va_arg(args, const unsigned char*); if (curptr == NULL) break; curlen = va_arg(args, unsigned long); } err = blake2smac_done(&st, mac, maclen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(blake2smac_state)); #endif va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/blake2/blake2smac_test.c000066400000000000000000001505441464416617300253240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BLAKE2SMAC int blake2smac_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const unsigned char tests[256][32] = { /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-kat.txt */ { 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b, 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b, 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a, 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49 }, { 0x40, 0xd1, 0x5f, 0xee, 0x7c, 0x32, 0x88, 0x30, 0x16, 0x6a, 0xc3, 0xf9, 0x18, 0x65, 0x0f, 0x80, 0x7e, 0x7e, 0x01, 0xe1, 0x77, 0x25, 0x8c, 0xdc, 0x0a, 0x39, 0xb1, 0x1f, 0x59, 0x80, 0x66, 0xf1 }, { 0x6b, 0xb7, 0x13, 0x00, 0x64, 0x4c, 0xd3, 0x99, 0x1b, 0x26, 0xcc, 0xd4, 0xd2, 0x74, 0xac, 0xd1, 0xad, 0xea, 0xb8, 0xb1, 0xd7, 0x91, 0x45, 0x46, 0xc1, 0x19, 0x8b, 0xbe, 0x9f, 0xc9, 0xd8, 0x03 }, { 0x1d, 0x22, 0x0d, 0xbe, 0x2e, 0xe1, 0x34, 0x66, 0x1f, 0xdf, 0x6d, 0x9e, 0x74, 0xb4, 0x17, 0x04, 0x71, 0x05, 0x56, 0xf2, 0xf6, 0xe5, 0xa0, 0x91, 0xb2, 0x27, 0x69, 0x74, 0x45, 0xdb, 0xea, 0x6b }, { 0xf6, 0xc3, 0xfb, 0xad, 0xb4, 0xcc, 0x68, 0x7a, 0x00, 0x64, 0xa5, 0xbe, 0x6e, 0x79, 0x1b, 0xec, 0x63, 0xb8, 0x68, 0xad, 0x62, 0xfb, 0xa6, 0x1b, 0x37, 0x57, 0xef, 0x9c, 0xa5, 0x2e, 0x05, 0xb2 }, { 0x49, 0xc1, 0xf2, 0x11, 0x88, 0xdf, 0xd7, 0x69, 0xae, 0xa0, 0xe9, 0x11, 0xdd, 0x6b, 0x41, 0xf1, 0x4d, 0xab, 0x10, 0x9d, 0x2b, 0x85, 0x97, 0x7a, 0xa3, 0x08, 0x8b, 0x5c, 0x70, 0x7e, 0x85, 0x98 }, { 0xfd, 0xd8, 0x99, 0x3d, 0xcd, 0x43, 0xf6, 0x96, 0xd4, 0x4f, 0x3c, 0xea, 0x0f, 0xf3, 0x53, 0x45, 0x23, 0x4e, 0xc8, 0xee, 0x08, 0x3e, 0xb3, 0xca, 0xda, 0x01, 0x7c, 0x7f, 0x78, 0xc1, 0x71, 0x43 }, { 0xe6, 0xc8, 0x12, 0x56, 0x37, 0x43, 0x8d, 0x09, 0x05, 0xb7, 0x49, 0xf4, 0x65, 0x60, 0xac, 0x89, 0xfd, 0x47, 0x1c, 0xf8, 0x69, 0x2e, 0x28, 0xfa, 0xb9, 0x82, 0xf7, 0x3f, 0x01, 0x9b, 0x83, 0xa9 }, { 0x19, 0xfc, 0x8c, 0xa6, 0x97, 0x9d, 0x60, 0xe6, 0xed, 0xd3, 0xb4, 0x54, 0x1e, 0x2f, 0x96, 0x7c, 0xed, 0x74, 0x0d, 0xf6, 0xec, 0x1e, 0xae, 0xbb, 0xfe, 0x81, 0x38, 0x32, 0xe9, 0x6b, 0x29, 0x74 }, { 0xa6, 0xad, 0x77, 0x7c, 0xe8, 0x81, 0xb5, 0x2b, 0xb5, 0xa4, 0x42, 0x1a, 0xb6, 0xcd, 0xd2, 0xdf, 0xba, 0x13, 0xe9, 0x63, 0x65, 0x2d, 0x4d, 0x6d, 0x12, 0x2a, 0xee, 0x46, 0x54, 0x8c, 0x14, 0xa7 }, { 0xf5, 0xc4, 0xb2, 0xba, 0x1a, 0x00, 0x78, 0x1b, 0x13, 0xab, 0xa0, 0x42, 0x52, 0x42, 0xc6, 0x9c, 0xb1, 0x55, 0x2f, 0x3f, 0x71, 0xa9, 0xa3, 0xbb, 0x22, 0xb4, 0xa6, 0xb4, 0x27, 0x7b, 0x46, 0xdd }, { 0xe3, 0x3c, 0x4c, 0x9b, 0xd0, 0xcc, 0x7e, 0x45, 0xc8, 0x0e, 0x65, 0xc7, 0x7f, 0xa5, 0x99, 0x7f, 0xec, 0x70, 0x02, 0x73, 0x85, 0x41, 0x50, 0x9e, 0x68, 0xa9, 0x42, 0x38, 0x91, 0xe8, 0x22, 0xa3 }, { 0xfb, 0xa1, 0x61, 0x69, 0xb2, 0xc3, 0xee, 0x10, 0x5b, 0xe6, 0xe1, 0xe6, 0x50, 0xe5, 0xcb, 0xf4, 0x07, 0x46, 0xb6, 0x75, 0x3d, 0x03, 0x6a, 0xb5, 0x51, 0x79, 0x01, 0x4a, 0xd7, 0xef, 0x66, 0x51 }, { 0xf5, 0xc4, 0xbe, 0xc6, 0xd6, 0x2f, 0xc6, 0x08, 0xbf, 0x41, 0xcc, 0x11, 0x5f, 0x16, 0xd6, 0x1c, 0x7e, 0xfd, 0x3f, 0xf6, 0xc6, 0x56, 0x92, 0xbb, 0xe0, 0xaf, 0xff, 0xb1, 0xfe, 0xde, 0x74, 0x75 }, { 0xa4, 0x86, 0x2e, 0x76, 0xdb, 0x84, 0x7f, 0x05, 0xba, 0x17, 0xed, 0xe5, 0xda, 0x4e, 0x7f, 0x91, 0xb5, 0x92, 0x5c, 0xf1, 0xad, 0x4b, 0xa1, 0x27, 0x32, 0xc3, 0x99, 0x57, 0x42, 0xa5, 0xcd, 0x6e }, { 0x65, 0xf4, 0xb8, 0x60, 0xcd, 0x15, 0xb3, 0x8e, 0xf8, 0x14, 0xa1, 0xa8, 0x04, 0x31, 0x4a, 0x55, 0xbe, 0x95, 0x3c, 0xaa, 0x65, 0xfd, 0x75, 0x8a, 0xd9, 0x89, 0xff, 0x34, 0xa4, 0x1c, 0x1e, 0xea }, { 0x19, 0xba, 0x23, 0x4f, 0x0a, 0x4f, 0x38, 0x63, 0x7d, 0x18, 0x39, 0xf9, 0xd9, 0xf7, 0x6a, 0xd9, 0x1c, 0x85, 0x22, 0x30, 0x71, 0x43, 0xc9, 0x7d, 0x5f, 0x93, 0xf6, 0x92, 0x74, 0xce, 0xc9, 0xa7 }, { 0x1a, 0x67, 0x18, 0x6c, 0xa4, 0xa5, 0xcb, 0x8e, 0x65, 0xfc, 0xa0, 0xe2, 0xec, 0xbc, 0x5d, 0xdc, 0x14, 0xae, 0x38, 0x1b, 0xb8, 0xbf, 0xfe, 0xb9, 0xe0, 0xa1, 0x03, 0x44, 0x9e, 0x3e, 0xf0, 0x3c }, { 0xaf, 0xbe, 0xa3, 0x17, 0xb5, 0xa2, 0xe8, 0x9c, 0x0b, 0xd9, 0x0c, 0xcf, 0x5d, 0x7f, 0xd0, 0xed, 0x57, 0xfe, 0x58, 0x5e, 0x4b, 0xe3, 0x27, 0x1b, 0x0a, 0x6b, 0xf0, 0xf5, 0x78, 0x6b, 0x0f, 0x26 }, { 0xf1, 0xb0, 0x15, 0x58, 0xce, 0x54, 0x12, 0x62, 0xf5, 0xec, 0x34, 0x29, 0x9d, 0x6f, 0xb4, 0x09, 0x00, 0x09, 0xe3, 0x43, 0x4b, 0xe2, 0xf4, 0x91, 0x05, 0xcf, 0x46, 0xaf, 0x4d, 0x2d, 0x41, 0x24 }, { 0x13, 0xa0, 0xa0, 0xc8, 0x63, 0x35, 0x63, 0x5e, 0xaa, 0x74, 0xca, 0x2d, 0x5d, 0x48, 0x8c, 0x79, 0x7b, 0xbb, 0x4f, 0x47, 0xdc, 0x07, 0x10, 0x50, 0x15, 0xed, 0x6a, 0x1f, 0x33, 0x09, 0xef, 0xce }, { 0x15, 0x80, 0xaf, 0xee, 0xbe, 0xbb, 0x34, 0x6f, 0x94, 0xd5, 0x9f, 0xe6, 0x2d, 0xa0, 0xb7, 0x92, 0x37, 0xea, 0xd7, 0xb1, 0x49, 0x1f, 0x56, 0x67, 0xa9, 0x0e, 0x45, 0xed, 0xf6, 0xca, 0x8b, 0x03 }, { 0x20, 0xbe, 0x1a, 0x87, 0x5b, 0x38, 0xc5, 0x73, 0xdd, 0x7f, 0xaa, 0xa0, 0xde, 0x48, 0x9d, 0x65, 0x5c, 0x11, 0xef, 0xb6, 0xa5, 0x52, 0x69, 0x8e, 0x07, 0xa2, 0xd3, 0x31, 0xb5, 0xf6, 0x55, 0xc3 }, { 0xbe, 0x1f, 0xe3, 0xc4, 0xc0, 0x40, 0x18, 0xc5, 0x4c, 0x4a, 0x0f, 0x6b, 0x9a, 0x2e, 0xd3, 0xc5, 0x3a, 0xbe, 0x3a, 0x9f, 0x76, 0xb4, 0xd2, 0x6d, 0xe5, 0x6f, 0xc9, 0xae, 0x95, 0x05, 0x9a, 0x99 }, { 0xe3, 0xe3, 0xac, 0xe5, 0x37, 0xeb, 0x3e, 0xdd, 0x84, 0x63, 0xd9, 0xad, 0x35, 0x82, 0xe1, 0x3c, 0xf8, 0x65, 0x33, 0xff, 0xde, 0x43, 0xd6, 0x68, 0xdd, 0x2e, 0x93, 0xbb, 0xdb, 0xd7, 0x19, 0x5a }, { 0x11, 0x0c, 0x50, 0xc0, 0xbf, 0x2c, 0x6e, 0x7a, 0xeb, 0x7e, 0x43, 0x5d, 0x92, 0xd1, 0x32, 0xab, 0x66, 0x55, 0x16, 0x8e, 0x78, 0xa2, 0xde, 0xcd, 0xec, 0x33, 0x30, 0x77, 0x76, 0x84, 0xd9, 0xc1 }, { 0xe9, 0xba, 0x8f, 0x50, 0x5c, 0x9c, 0x80, 0xc0, 0x86, 0x66, 0xa7, 0x01, 0xf3, 0x36, 0x7e, 0x6c, 0xc6, 0x65, 0xf3, 0x4b, 0x22, 0xe7, 0x3c, 0x3c, 0x04, 0x17, 0xeb, 0x1c, 0x22, 0x06, 0x08, 0x2f }, { 0x26, 0xcd, 0x66, 0xfc, 0xa0, 0x23, 0x79, 0xc7, 0x6d, 0xf1, 0x23, 0x17, 0x05, 0x2b, 0xca, 0xfd, 0x6c, 0xd8, 0xc3, 0xa7, 0xb8, 0x90, 0xd8, 0x05, 0xf3, 0x6c, 0x49, 0x98, 0x97, 0x82, 0x43, 0x3a }, { 0x21, 0x3f, 0x35, 0x96, 0xd6, 0xe3, 0xa5, 0xd0, 0xe9, 0x93, 0x2c, 0xd2, 0x15, 0x91, 0x46, 0x01, 0x5e, 0x2a, 0xbc, 0x94, 0x9f, 0x47, 0x29, 0xee, 0x26, 0x32, 0xfe, 0x1e, 0xdb, 0x78, 0xd3, 0x37 }, { 0x10, 0x15, 0xd7, 0x01, 0x08, 0xe0, 0x3b, 0xe1, 0xc7, 0x02, 0xfe, 0x97, 0x25, 0x36, 0x07, 0xd1, 0x4a, 0xee, 0x59, 0x1f, 0x24, 0x13, 0xea, 0x67, 0x87, 0x42, 0x7b, 0x64, 0x59, 0xff, 0x21, 0x9a }, { 0x3c, 0xa9, 0x89, 0xde, 0x10, 0xcf, 0xe6, 0x09, 0x90, 0x94, 0x72, 0xc8, 0xd3, 0x56, 0x10, 0x80, 0x5b, 0x2f, 0x97, 0x77, 0x34, 0xcf, 0x65, 0x2c, 0xc6, 0x4b, 0x3b, 0xfc, 0x88, 0x2d, 0x5d, 0x89 }, { 0xb6, 0x15, 0x6f, 0x72, 0xd3, 0x80, 0xee, 0x9e, 0xa6, 0xac, 0xd1, 0x90, 0x46, 0x4f, 0x23, 0x07, 0xa5, 0xc1, 0x79, 0xef, 0x01, 0xfd, 0x71, 0xf9, 0x9f, 0x2d, 0x0f, 0x7a, 0x57, 0x36, 0x0a, 0xea }, { 0xc0, 0x3b, 0xc6, 0x42, 0xb2, 0x09, 0x59, 0xcb, 0xe1, 0x33, 0xa0, 0x30, 0x3e, 0x0c, 0x1a, 0xbf, 0xf3, 0xe3, 0x1e, 0xc8, 0xe1, 0xa3, 0x28, 0xec, 0x85, 0x65, 0xc3, 0x6d, 0xec, 0xff, 0x52, 0x65 }, { 0x2c, 0x3e, 0x08, 0x17, 0x6f, 0x76, 0x0c, 0x62, 0x64, 0xc3, 0xa2, 0xcd, 0x66, 0xfe, 0xc6, 0xc3, 0xd7, 0x8d, 0xe4, 0x3f, 0xc1, 0x92, 0x45, 0x7b, 0x2a, 0x4a, 0x66, 0x0a, 0x1e, 0x0e, 0xb2, 0x2b }, { 0xf7, 0x38, 0xc0, 0x2f, 0x3c, 0x1b, 0x19, 0x0c, 0x51, 0x2b, 0x1a, 0x32, 0xde, 0xab, 0xf3, 0x53, 0x72, 0x8e, 0x0e, 0x9a, 0xb0, 0x34, 0x49, 0x0e, 0x3c, 0x34, 0x09, 0x94, 0x6a, 0x97, 0xae, 0xec }, { 0x8b, 0x18, 0x80, 0xdf, 0x30, 0x1c, 0xc9, 0x63, 0x41, 0x88, 0x11, 0x08, 0x89, 0x64, 0x83, 0x92, 0x87, 0xff, 0x7f, 0xe3, 0x1c, 0x49, 0xea, 0x6e, 0xbd, 0x9e, 0x48, 0xbd, 0xee, 0xe4, 0x97, 0xc5 }, { 0x1e, 0x75, 0xcb, 0x21, 0xc6, 0x09, 0x89, 0x02, 0x03, 0x75, 0xf1, 0xa7, 0xa2, 0x42, 0x83, 0x9f, 0x0b, 0x0b, 0x68, 0x97, 0x3a, 0x4c, 0x2a, 0x05, 0xcf, 0x75, 0x55, 0xed, 0x5a, 0xae, 0xc4, 0xc1 }, { 0x62, 0xbf, 0x8a, 0x9c, 0x32, 0xa5, 0xbc, 0xcf, 0x29, 0x0b, 0x6c, 0x47, 0x4d, 0x75, 0xb2, 0xa2, 0xa4, 0x09, 0x3f, 0x1a, 0x9e, 0x27, 0x13, 0x94, 0x33, 0xa8, 0xf2, 0xb3, 0xbc, 0xe7, 0xb8, 0xd7 }, { 0x16, 0x6c, 0x83, 0x50, 0xd3, 0x17, 0x3b, 0x5e, 0x70, 0x2b, 0x78, 0x3d, 0xfd, 0x33, 0xc6, 0x6e, 0xe0, 0x43, 0x27, 0x42, 0xe9, 0xb9, 0x2b, 0x99, 0x7f, 0xd2, 0x3c, 0x60, 0xdc, 0x67, 0x56, 0xca }, { 0x04, 0x4a, 0x14, 0xd8, 0x22, 0xa9, 0x0c, 0xac, 0xf2, 0xf5, 0xa1, 0x01, 0x42, 0x8a, 0xdc, 0x8f, 0x41, 0x09, 0x38, 0x6c, 0xcb, 0x15, 0x8b, 0xf9, 0x05, 0xc8, 0x61, 0x8b, 0x8e, 0xe2, 0x4e, 0xc3 }, { 0x38, 0x7d, 0x39, 0x7e, 0xa4, 0x3a, 0x99, 0x4b, 0xe8, 0x4d, 0x2d, 0x54, 0x4a, 0xfb, 0xe4, 0x81, 0xa2, 0x00, 0x0f, 0x55, 0x25, 0x26, 0x96, 0xbb, 0xa2, 0xc5, 0x0c, 0x8e, 0xbd, 0x10, 0x13, 0x47 }, { 0x56, 0xf8, 0xcc, 0xf1, 0xf8, 0x64, 0x09, 0xb4, 0x6c, 0xe3, 0x61, 0x66, 0xae, 0x91, 0x65, 0x13, 0x84, 0x41, 0x57, 0x75, 0x89, 0xdb, 0x08, 0xcb, 0xc5, 0xf6, 0x6c, 0xa2, 0x97, 0x43, 0xb9, 0xfd }, { 0x97, 0x06, 0xc0, 0x92, 0xb0, 0x4d, 0x91, 0xf5, 0x3d, 0xff, 0x91, 0xfa, 0x37, 0xb7, 0x49, 0x3d, 0x28, 0xb5, 0x76, 0xb5, 0xd7, 0x10, 0x46, 0x9d, 0xf7, 0x94, 0x01, 0x66, 0x22, 0x36, 0xfc, 0x03 }, { 0x87, 0x79, 0x68, 0x68, 0x6c, 0x06, 0x8c, 0xe2, 0xf7, 0xe2, 0xad, 0xcf, 0xf6, 0x8b, 0xf8, 0x74, 0x8e, 0xdf, 0x3c, 0xf8, 0x62, 0xcf, 0xb4, 0xd3, 0x94, 0x7a, 0x31, 0x06, 0x95, 0x80, 0x54, 0xe3 }, { 0x88, 0x17, 0xe5, 0x71, 0x98, 0x79, 0xac, 0xf7, 0x02, 0x47, 0x87, 0xec, 0xcd, 0xb2, 0x71, 0x03, 0x55, 0x66, 0xcf, 0xa3, 0x33, 0xe0, 0x49, 0x40, 0x7c, 0x01, 0x78, 0xcc, 0xc5, 0x7a, 0x5b, 0x9f }, { 0x89, 0x38, 0x24, 0x9e, 0x4b, 0x50, 0xca, 0xda, 0xcc, 0xdf, 0x5b, 0x18, 0x62, 0x13, 0x26, 0xcb, 0xb1, 0x52, 0x53, 0xe3, 0x3a, 0x20, 0xf5, 0x63, 0x6e, 0x99, 0x5d, 0x72, 0x47, 0x8d, 0xe4, 0x72 }, { 0xf1, 0x64, 0xab, 0xba, 0x49, 0x63, 0xa4, 0x4d, 0x10, 0x72, 0x57, 0xe3, 0x23, 0x2d, 0x90, 0xac, 0xa5, 0xe6, 0x6a, 0x14, 0x08, 0x24, 0x8c, 0x51, 0x74, 0x1e, 0x99, 0x1d, 0xb5, 0x22, 0x77, 0x56 }, { 0xd0, 0x55, 0x63, 0xe2, 0xb1, 0xcb, 0xa0, 0xc4, 0xa2, 0xa1, 0xe8, 0xbd, 0xe3, 0xa1, 0xa0, 0xd9, 0xf5, 0xb4, 0x0c, 0x85, 0xa0, 0x70, 0xd6, 0xf5, 0xfb, 0x21, 0x06, 0x6e, 0xad, 0x5d, 0x06, 0x01 }, { 0x03, 0xfb, 0xb1, 0x63, 0x84, 0xf0, 0xa3, 0x86, 0x6f, 0x4c, 0x31, 0x17, 0x87, 0x76, 0x66, 0xef, 0xbf, 0x12, 0x45, 0x97, 0x56, 0x4b, 0x29, 0x3d, 0x4a, 0xab, 0x0d, 0x26, 0x9f, 0xab, 0xdd, 0xfa }, { 0x5f, 0xa8, 0x48, 0x6a, 0xc0, 0xe5, 0x29, 0x64, 0xd1, 0x88, 0x1b, 0xbe, 0x33, 0x8e, 0xb5, 0x4b, 0xe2, 0xf7, 0x19, 0x54, 0x92, 0x24, 0x89, 0x20, 0x57, 0xb4, 0xda, 0x04, 0xba, 0x8b, 0x34, 0x75 }, { 0xcd, 0xfa, 0xbc, 0xee, 0x46, 0x91, 0x11, 0x11, 0x23, 0x6a, 0x31, 0x70, 0x8b, 0x25, 0x39, 0xd7, 0x1f, 0xc2, 0x11, 0xd9, 0xb0, 0x9c, 0x0d, 0x85, 0x30, 0xa1, 0x1e, 0x1d, 0xbf, 0x6e, 0xed, 0x01 }, { 0x4f, 0x82, 0xde, 0x03, 0xb9, 0x50, 0x47, 0x93, 0xb8, 0x2a, 0x07, 0xa0, 0xbd, 0xcd, 0xff, 0x31, 0x4d, 0x75, 0x9e, 0x7b, 0x62, 0xd2, 0x6b, 0x78, 0x49, 0x46, 0xb0, 0xd3, 0x6f, 0x91, 0x6f, 0x52 }, { 0x25, 0x9e, 0xc7, 0xf1, 0x73, 0xbc, 0xc7, 0x6a, 0x09, 0x94, 0xc9, 0x67, 0xb4, 0xf5, 0xf0, 0x24, 0xc5, 0x60, 0x57, 0xfb, 0x79, 0xc9, 0x65, 0xc4, 0xfa, 0xe4, 0x18, 0x75, 0xf0, 0x6a, 0x0e, 0x4c }, { 0x19, 0x3c, 0xc8, 0xe7, 0xc3, 0xe0, 0x8b, 0xb3, 0x0f, 0x54, 0x37, 0xaa, 0x27, 0xad, 0xe1, 0xf1, 0x42, 0x36, 0x9b, 0x24, 0x6a, 0x67, 0x5b, 0x23, 0x83, 0xe6, 0xda, 0x9b, 0x49, 0xa9, 0x80, 0x9e }, { 0x5c, 0x10, 0x89, 0x6f, 0x0e, 0x28, 0x56, 0xb2, 0xa2, 0xee, 0xe0, 0xfe, 0x4a, 0x2c, 0x16, 0x33, 0x56, 0x5d, 0x18, 0xf0, 0xe9, 0x3e, 0x1f, 0xab, 0x26, 0xc3, 0x73, 0xe8, 0xf8, 0x29, 0x65, 0x4d }, { 0xf1, 0x60, 0x12, 0xd9, 0x3f, 0x28, 0x85, 0x1a, 0x1e, 0xb9, 0x89, 0xf5, 0xd0, 0xb4, 0x3f, 0x3f, 0x39, 0xca, 0x73, 0xc9, 0xa6, 0x2d, 0x51, 0x81, 0xbf, 0xf2, 0x37, 0x53, 0x6b, 0xd3, 0x48, 0xc3 }, { 0x29, 0x66, 0xb3, 0xcf, 0xae, 0x1e, 0x44, 0xea, 0x99, 0x6d, 0xc5, 0xd6, 0x86, 0xcf, 0x25, 0xfa, 0x05, 0x3f, 0xb6, 0xf6, 0x72, 0x01, 0xb9, 0xe4, 0x6e, 0xad, 0xe8, 0x5d, 0x0a, 0xd6, 0xb8, 0x06 }, { 0xdd, 0xb8, 0x78, 0x24, 0x85, 0xe9, 0x00, 0xbc, 0x60, 0xbc, 0xf4, 0xc3, 0x3a, 0x6f, 0xd5, 0x85, 0x68, 0x0c, 0xc6, 0x83, 0xd5, 0x16, 0xef, 0xa0, 0x3e, 0xb9, 0x98, 0x5f, 0xad, 0x87, 0x15, 0xfb }, { 0x4c, 0x4d, 0x6e, 0x71, 0xae, 0xa0, 0x57, 0x86, 0x41, 0x31, 0x48, 0xfc, 0x7a, 0x78, 0x6b, 0x0e, 0xca, 0xf5, 0x82, 0xcf, 0xf1, 0x20, 0x9f, 0x5a, 0x80, 0x9f, 0xba, 0x85, 0x04, 0xce, 0x66, 0x2c }, { 0xfb, 0x4c, 0x5e, 0x86, 0xd7, 0xb2, 0x22, 0x9b, 0x99, 0xb8, 0xba, 0x6d, 0x94, 0xc2, 0x47, 0xef, 0x96, 0x4a, 0xa3, 0xa2, 0xba, 0xe8, 0xed, 0xc7, 0x75, 0x69, 0xf2, 0x8d, 0xbb, 0xff, 0x2d, 0x4e }, { 0xe9, 0x4f, 0x52, 0x6d, 0xe9, 0x01, 0x96, 0x33, 0xec, 0xd5, 0x4a, 0xc6, 0x12, 0x0f, 0x23, 0x95, 0x8d, 0x77, 0x18, 0xf1, 0xe7, 0x71, 0x7b, 0xf3, 0x29, 0x21, 0x1a, 0x4f, 0xae, 0xed, 0x4e, 0x6d }, { 0xcb, 0xd6, 0x66, 0x0a, 0x10, 0xdb, 0x3f, 0x23, 0xf7, 0xa0, 0x3d, 0x4b, 0x9d, 0x40, 0x44, 0xc7, 0x93, 0x2b, 0x28, 0x01, 0xac, 0x89, 0xd6, 0x0b, 0xc9, 0xeb, 0x92, 0xd6, 0x5a, 0x46, 0xc2, 0xa0 }, { 0x88, 0x18, 0xbb, 0xd3, 0xdb, 0x4d, 0xc1, 0x23, 0xb2, 0x5c, 0xbb, 0xa5, 0xf5, 0x4c, 0x2b, 0xc4, 0xb3, 0xfc, 0xf9, 0xbf, 0x7d, 0x7a, 0x77, 0x09, 0xf4, 0xae, 0x58, 0x8b, 0x26, 0x7c, 0x4e, 0xce }, { 0xc6, 0x53, 0x82, 0x51, 0x3f, 0x07, 0x46, 0x0d, 0xa3, 0x98, 0x33, 0xcb, 0x66, 0x6c, 0x5e, 0xd8, 0x2e, 0x61, 0xb9, 0xe9, 0x98, 0xf4, 0xb0, 0xc4, 0x28, 0x7c, 0xee, 0x56, 0xc3, 0xcc, 0x9b, 0xcd }, { 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66, 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26, 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab, 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4 }, { 0x21, 0xfe, 0x0c, 0xeb, 0x00, 0x52, 0xbe, 0x7f, 0xb0, 0xf0, 0x04, 0x18, 0x7c, 0xac, 0xd7, 0xde, 0x67, 0xfa, 0x6e, 0xb0, 0x93, 0x8d, 0x92, 0x76, 0x77, 0xf2, 0x39, 0x8c, 0x13, 0x23, 0x17, 0xa8 }, { 0x2e, 0xf7, 0x3f, 0x3c, 0x26, 0xf1, 0x2d, 0x93, 0x88, 0x9f, 0x3c, 0x78, 0xb6, 0xa6, 0x6c, 0x1d, 0x52, 0xb6, 0x49, 0xdc, 0x9e, 0x85, 0x6e, 0x2c, 0x17, 0x2e, 0xa7, 0xc5, 0x8a, 0xc2, 0xb5, 0xe3 }, { 0x38, 0x8a, 0x3c, 0xd5, 0x6d, 0x73, 0x86, 0x7a, 0xbb, 0x5f, 0x84, 0x01, 0x49, 0x2b, 0x6e, 0x26, 0x81, 0xeb, 0x69, 0x85, 0x1e, 0x76, 0x7f, 0xd8, 0x42, 0x10, 0xa5, 0x60, 0x76, 0xfb, 0x3d, 0xd3 }, { 0xaf, 0x53, 0x3e, 0x02, 0x2f, 0xc9, 0x43, 0x9e, 0x4e, 0x3c, 0xb8, 0x38, 0xec, 0xd1, 0x86, 0x92, 0x23, 0x2a, 0xdf, 0x6f, 0xe9, 0x83, 0x95, 0x26, 0xd3, 0xc3, 0xdd, 0x1b, 0x71, 0x91, 0x0b, 0x1a }, { 0x75, 0x1c, 0x09, 0xd4, 0x1a, 0x93, 0x43, 0x88, 0x2a, 0x81, 0xcd, 0x13, 0xee, 0x40, 0x81, 0x8d, 0x12, 0xeb, 0x44, 0xc6, 0xc7, 0xf4, 0x0d, 0xf1, 0x6e, 0x4a, 0xea, 0x8f, 0xab, 0x91, 0x97, 0x2a }, { 0x5b, 0x73, 0xdd, 0xb6, 0x8d, 0x9d, 0x2b, 0x0a, 0xa2, 0x65, 0xa0, 0x79, 0x88, 0xd6, 0xb8, 0x8a, 0xe9, 0xaa, 0xc5, 0x82, 0xaf, 0x83, 0x03, 0x2f, 0x8a, 0x9b, 0x21, 0xa2, 0xe1, 0xb7, 0xbf, 0x18 }, { 0x3d, 0xa2, 0x91, 0x26, 0xc7, 0xc5, 0xd7, 0xf4, 0x3e, 0x64, 0x24, 0x2a, 0x79, 0xfe, 0xaa, 0x4e, 0xf3, 0x45, 0x9c, 0xde, 0xcc, 0xc8, 0x98, 0xed, 0x59, 0xa9, 0x7f, 0x6e, 0xc9, 0x3b, 0x9d, 0xab }, { 0x56, 0x6d, 0xc9, 0x20, 0x29, 0x3d, 0xa5, 0xcb, 0x4f, 0xe0, 0xaa, 0x8a, 0xbd, 0xa8, 0xbb, 0xf5, 0x6f, 0x55, 0x23, 0x13, 0xbf, 0xf1, 0x90, 0x46, 0x64, 0x1e, 0x36, 0x15, 0xc1, 0xe3, 0xed, 0x3f }, { 0x41, 0x15, 0xbe, 0xa0, 0x2f, 0x73, 0xf9, 0x7f, 0x62, 0x9e, 0x5c, 0x55, 0x90, 0x72, 0x0c, 0x01, 0xe7, 0xe4, 0x49, 0xae, 0x2a, 0x66, 0x97, 0xd4, 0xd2, 0x78, 0x33, 0x21, 0x30, 0x36, 0x92, 0xf9 }, { 0x4c, 0xe0, 0x8f, 0x47, 0x62, 0x46, 0x8a, 0x76, 0x70, 0x01, 0x21, 0x64, 0x87, 0x8d, 0x68, 0x34, 0x0c, 0x52, 0xa3, 0x5e, 0x66, 0xc1, 0x88, 0x4d, 0x5c, 0x86, 0x48, 0x89, 0xab, 0xc9, 0x66, 0x77 }, { 0x81, 0xea, 0x0b, 0x78, 0x04, 0x12, 0x4e, 0x0c, 0x22, 0xea, 0x5f, 0xc7, 0x11, 0x04, 0xa2, 0xaf, 0xcb, 0x52, 0xa1, 0xfa, 0x81, 0x6f, 0x3e, 0xcb, 0x7d, 0xcb, 0x5d, 0x9d, 0xea, 0x17, 0x86, 0xd0 }, { 0xfe, 0x36, 0x27, 0x33, 0xb0, 0x5f, 0x6b, 0xed, 0xaf, 0x93, 0x79, 0xd7, 0xf7, 0x93, 0x6e, 0xde, 0x20, 0x9b, 0x1f, 0x83, 0x23, 0xc3, 0x92, 0x25, 0x49, 0xd9, 0xe7, 0x36, 0x81, 0xb5, 0xdb, 0x7b }, { 0xef, 0xf3, 0x7d, 0x30, 0xdf, 0xd2, 0x03, 0x59, 0xbe, 0x4e, 0x73, 0xfd, 0xf4, 0x0d, 0x27, 0x73, 0x4b, 0x3d, 0xf9, 0x0a, 0x97, 0xa5, 0x5e, 0xd7, 0x45, 0x29, 0x72, 0x94, 0xca, 0x85, 0xd0, 0x9f }, { 0x17, 0x2f, 0xfc, 0x67, 0x15, 0x3d, 0x12, 0xe0, 0xca, 0x76, 0xa8, 0xb6, 0xcd, 0x5d, 0x47, 0x31, 0x88, 0x5b, 0x39, 0xce, 0x0c, 0xac, 0x93, 0xa8, 0x97, 0x2a, 0x18, 0x00, 0x6c, 0x8b, 0x8b, 0xaf }, { 0xc4, 0x79, 0x57, 0xf1, 0xcc, 0x88, 0xe8, 0x3e, 0xf9, 0x44, 0x58, 0x39, 0x70, 0x9a, 0x48, 0x0a, 0x03, 0x6b, 0xed, 0x5f, 0x88, 0xac, 0x0f, 0xcc, 0x8e, 0x1e, 0x70, 0x3f, 0xfa, 0xac, 0x13, 0x2c }, { 0x30, 0xf3, 0x54, 0x83, 0x70, 0xcf, 0xdc, 0xed, 0xa5, 0xc3, 0x7b, 0x56, 0x9b, 0x61, 0x75, 0xe7, 0x99, 0xee, 0xf1, 0xa6, 0x2a, 0xaa, 0x94, 0x32, 0x45, 0xae, 0x76, 0x69, 0xc2, 0x27, 0xa7, 0xb5 }, { 0xc9, 0x5d, 0xcb, 0x3c, 0xf1, 0xf2, 0x7d, 0x0e, 0xef, 0x2f, 0x25, 0xd2, 0x41, 0x38, 0x70, 0x90, 0x4a, 0x87, 0x7c, 0x4a, 0x56, 0xc2, 0xde, 0x1e, 0x83, 0xe2, 0xbc, 0x2a, 0xe2, 0xe4, 0x68, 0x21 }, { 0xd5, 0xd0, 0xb5, 0xd7, 0x05, 0x43, 0x4c, 0xd4, 0x6b, 0x18, 0x57, 0x49, 0xf6, 0x6b, 0xfb, 0x58, 0x36, 0xdc, 0xdf, 0x6e, 0xe5, 0x49, 0xa2, 0xb7, 0xa4, 0xae, 0xe7, 0xf5, 0x80, 0x07, 0xca, 0xaf }, { 0xbb, 0xc1, 0x24, 0xa7, 0x12, 0xf1, 0x5d, 0x07, 0xc3, 0x00, 0xe0, 0x5b, 0x66, 0x83, 0x89, 0xa4, 0x39, 0xc9, 0x17, 0x77, 0xf7, 0x21, 0xf8, 0x32, 0x0c, 0x1c, 0x90, 0x78, 0x06, 0x6d, 0x2c, 0x7e }, { 0xa4, 0x51, 0xb4, 0x8c, 0x35, 0xa6, 0xc7, 0x85, 0x4c, 0xfa, 0xae, 0x60, 0x26, 0x2e, 0x76, 0x99, 0x08, 0x16, 0x38, 0x2a, 0xc0, 0x66, 0x7e, 0x5a, 0x5c, 0x9e, 0x1b, 0x46, 0xc4, 0x34, 0x2d, 0xdf }, { 0xb0, 0xd1, 0x50, 0xfb, 0x55, 0xe7, 0x78, 0xd0, 0x11, 0x47, 0xf0, 0xb5, 0xd8, 0x9d, 0x99, 0xec, 0xb2, 0x0f, 0xf0, 0x7e, 0x5e, 0x67, 0x60, 0xd6, 0xb6, 0x45, 0xeb, 0x5b, 0x65, 0x4c, 0x62, 0x2b }, { 0x34, 0xf7, 0x37, 0xc0, 0xab, 0x21, 0x99, 0x51, 0xee, 0xe8, 0x9a, 0x9f, 0x8d, 0xac, 0x29, 0x9c, 0x9d, 0x4c, 0x38, 0xf3, 0x3f, 0xa4, 0x94, 0xc5, 0xc6, 0xee, 0xfc, 0x92, 0xb6, 0xdb, 0x08, 0xbc }, { 0x1a, 0x62, 0xcc, 0x3a, 0x00, 0x80, 0x0d, 0xcb, 0xd9, 0x98, 0x91, 0x08, 0x0c, 0x1e, 0x09, 0x84, 0x58, 0x19, 0x3a, 0x8c, 0xc9, 0xf9, 0x70, 0xea, 0x99, 0xfb, 0xef, 0xf0, 0x03, 0x18, 0xc2, 0x89 }, { 0xcf, 0xce, 0x55, 0xeb, 0xaf, 0xc8, 0x40, 0xd7, 0xae, 0x48, 0x28, 0x1c, 0x7f, 0xd5, 0x7e, 0xc8, 0xb4, 0x82, 0xd4, 0xb7, 0x04, 0x43, 0x74, 0x95, 0x49, 0x5a, 0xc4, 0x14, 0xcf, 0x4a, 0x37, 0x4b }, { 0x67, 0x46, 0xfa, 0xcf, 0x71, 0x14, 0x6d, 0x99, 0x9d, 0xab, 0xd0, 0x5d, 0x09, 0x3a, 0xe5, 0x86, 0x64, 0x8d, 0x1e, 0xe2, 0x8e, 0x72, 0x61, 0x7b, 0x99, 0xd0, 0xf0, 0x08, 0x6e, 0x1e, 0x45, 0xbf }, { 0x57, 0x1c, 0xed, 0x28, 0x3b, 0x3f, 0x23, 0xb4, 0xe7, 0x50, 0xbf, 0x12, 0xa2, 0xca, 0xf1, 0x78, 0x18, 0x47, 0xbd, 0x89, 0x0e, 0x43, 0x60, 0x3c, 0xdc, 0x59, 0x76, 0x10, 0x2b, 0x7b, 0xb1, 0x1b }, { 0xcf, 0xcb, 0x76, 0x5b, 0x04, 0x8e, 0x35, 0x02, 0x2c, 0x5d, 0x08, 0x9d, 0x26, 0xe8, 0x5a, 0x36, 0xb0, 0x05, 0xa2, 0xb8, 0x04, 0x93, 0xd0, 0x3a, 0x14, 0x4e, 0x09, 0xf4, 0x09, 0xb6, 0xaf, 0xd1 }, { 0x40, 0x50, 0xc7, 0xa2, 0x77, 0x05, 0xbb, 0x27, 0xf4, 0x20, 0x89, 0xb2, 0x99, 0xf3, 0xcb, 0xe5, 0x05, 0x4e, 0xad, 0x68, 0x72, 0x7e, 0x8e, 0xf9, 0x31, 0x8c, 0xe6, 0xf2, 0x5c, 0xd6, 0xf3, 0x1d }, { 0x18, 0x40, 0x70, 0xbd, 0x5d, 0x26, 0x5f, 0xbd, 0xc1, 0x42, 0xcd, 0x1c, 0x5c, 0xd0, 0xd7, 0xe4, 0x14, 0xe7, 0x03, 0x69, 0xa2, 0x66, 0xd6, 0x27, 0xc8, 0xfb, 0xa8, 0x4f, 0xa5, 0xe8, 0x4c, 0x34 }, { 0x9e, 0xdd, 0xa9, 0xa4, 0x44, 0x39, 0x02, 0xa9, 0x58, 0x8c, 0x0d, 0x0c, 0xcc, 0x62, 0xb9, 0x30, 0x21, 0x84, 0x79, 0xa6, 0x84, 0x1e, 0x6f, 0xe7, 0xd4, 0x30, 0x03, 0xf0, 0x4b, 0x1f, 0xd6, 0x43 }, { 0xe4, 0x12, 0xfe, 0xef, 0x79, 0x08, 0x32, 0x4a, 0x6d, 0xa1, 0x84, 0x16, 0x29, 0xf3, 0x5d, 0x3d, 0x35, 0x86, 0x42, 0x01, 0x93, 0x10, 0xec, 0x57, 0xc6, 0x14, 0x83, 0x6b, 0x63, 0xd3, 0x07, 0x63 }, { 0x1a, 0x2b, 0x8e, 0xdf, 0xf3, 0xf9, 0xac, 0xc1, 0x55, 0x4f, 0xcb, 0xae, 0x3c, 0xf1, 0xd6, 0x29, 0x8c, 0x64, 0x62, 0xe2, 0x2e, 0x5e, 0xb0, 0x25, 0x96, 0x84, 0xf8, 0x35, 0x01, 0x2b, 0xd1, 0x3f }, { 0x28, 0x8c, 0x4a, 0xd9, 0xb9, 0x40, 0x97, 0x62, 0xea, 0x07, 0xc2, 0x4a, 0x41, 0xf0, 0x4f, 0x69, 0xa7, 0xd7, 0x4b, 0xee, 0x2d, 0x95, 0x43, 0x53, 0x74, 0xbd, 0xe9, 0x46, 0xd7, 0x24, 0x1c, 0x7b }, { 0x80, 0x56, 0x91, 0xbb, 0x28, 0x67, 0x48, 0xcf, 0xb5, 0x91, 0xd3, 0xae, 0xbe, 0x7e, 0x6f, 0x4e, 0x4d, 0xc6, 0xe2, 0x80, 0x8c, 0x65, 0x14, 0x3c, 0xc0, 0x04, 0xe4, 0xeb, 0x6f, 0xd0, 0x9d, 0x43 }, { 0xd4, 0xac, 0x8d, 0x3a, 0x0a, 0xfc, 0x6c, 0xfa, 0x7b, 0x46, 0x0a, 0xe3, 0x00, 0x1b, 0xae, 0xb3, 0x6d, 0xad, 0xb3, 0x7d, 0xa0, 0x7d, 0x2e, 0x8a, 0xc9, 0x18, 0x22, 0xdf, 0x34, 0x8a, 0xed, 0x3d }, { 0xc3, 0x76, 0x61, 0x70, 0x14, 0xd2, 0x01, 0x58, 0xbc, 0xed, 0x3d, 0x3b, 0xa5, 0x52, 0xb6, 0xec, 0xcf, 0x84, 0xe6, 0x2a, 0xa3, 0xeb, 0x65, 0x0e, 0x90, 0x02, 0x9c, 0x84, 0xd1, 0x3e, 0xea, 0x69 }, { 0xc4, 0x1f, 0x09, 0xf4, 0x3c, 0xec, 0xae, 0x72, 0x93, 0xd6, 0x00, 0x7c, 0xa0, 0xa3, 0x57, 0x08, 0x7d, 0x5a, 0xe5, 0x9b, 0xe5, 0x00, 0xc1, 0xcd, 0x5b, 0x28, 0x9e, 0xe8, 0x10, 0xc7, 0xb0, 0x82 }, { 0x03, 0xd1, 0xce, 0xd1, 0xfb, 0xa5, 0xc3, 0x91, 0x55, 0xc4, 0x4b, 0x77, 0x65, 0xcb, 0x76, 0x0c, 0x78, 0x70, 0x8d, 0xcf, 0xc8, 0x0b, 0x0b, 0xd8, 0xad, 0xe3, 0xa5, 0x6d, 0xa8, 0x83, 0x0b, 0x29 }, { 0x09, 0xbd, 0xe6, 0xf1, 0x52, 0x21, 0x8d, 0xc9, 0x2c, 0x41, 0xd7, 0xf4, 0x53, 0x87, 0xe6, 0x3e, 0x58, 0x69, 0xd8, 0x07, 0xec, 0x70, 0xb8, 0x21, 0x40, 0x5d, 0xbd, 0x88, 0x4b, 0x7f, 0xcf, 0x4b }, { 0x71, 0xc9, 0x03, 0x6e, 0x18, 0x17, 0x9b, 0x90, 0xb3, 0x7d, 0x39, 0xe9, 0xf0, 0x5e, 0xb8, 0x9c, 0xc5, 0xfc, 0x34, 0x1f, 0xd7, 0xc4, 0x77, 0xd0, 0xd7, 0x49, 0x32, 0x85, 0xfa, 0xca, 0x08, 0xa4 }, { 0x59, 0x16, 0x83, 0x3e, 0xbb, 0x05, 0xcd, 0x91, 0x9c, 0xa7, 0xfe, 0x83, 0xb6, 0x92, 0xd3, 0x20, 0x5b, 0xef, 0x72, 0x39, 0x2b, 0x2c, 0xf6, 0xbb, 0x0a, 0x6d, 0x43, 0xf9, 0x94, 0xf9, 0x5f, 0x11 }, { 0xf6, 0x3a, 0xab, 0x3e, 0xc6, 0x41, 0xb3, 0xb0, 0x24, 0x96, 0x4c, 0x2b, 0x43, 0x7c, 0x04, 0xf6, 0x04, 0x3c, 0x4c, 0x7e, 0x02, 0x79, 0x23, 0x99, 0x95, 0x40, 0x19, 0x58, 0xf8, 0x6b, 0xbe, 0x54 }, { 0xf1, 0x72, 0xb1, 0x80, 0xbf, 0xb0, 0x97, 0x40, 0x49, 0x31, 0x20, 0xb6, 0x32, 0x6c, 0xbd, 0xc5, 0x61, 0xe4, 0x77, 0xde, 0xf9, 0xbb, 0xcf, 0xd2, 0x8c, 0xc8, 0xc1, 0xc5, 0xe3, 0x37, 0x9a, 0x31 }, { 0xcb, 0x9b, 0x89, 0xcc, 0x18, 0x38, 0x1d, 0xd9, 0x14, 0x1a, 0xde, 0x58, 0x86, 0x54, 0xd4, 0xe6, 0xa2, 0x31, 0xd5, 0xbf, 0x49, 0xd4, 0xd5, 0x9a, 0xc2, 0x7d, 0x86, 0x9c, 0xbe, 0x10, 0x0c, 0xf3 }, { 0x7b, 0xd8, 0x81, 0x50, 0x46, 0xfd, 0xd8, 0x10, 0xa9, 0x23, 0xe1, 0x98, 0x4a, 0xae, 0xbd, 0xcd, 0xf8, 0x4d, 0x87, 0xc8, 0x99, 0x2d, 0x68, 0xb5, 0xee, 0xb4, 0x60, 0xf9, 0x3e, 0xb3, 0xc8, 0xd7 }, { 0x60, 0x7b, 0xe6, 0x68, 0x62, 0xfd, 0x08, 0xee, 0x5b, 0x19, 0xfa, 0xca, 0xc0, 0x9d, 0xfd, 0xbc, 0xd4, 0x0c, 0x31, 0x21, 0x01, 0xd6, 0x6e, 0x6e, 0xbd, 0x2b, 0x84, 0x1f, 0x1b, 0x9a, 0x93, 0x25 }, { 0x9f, 0xe0, 0x3b, 0xbe, 0x69, 0xab, 0x18, 0x34, 0xf5, 0x21, 0x9b, 0x0d, 0xa8, 0x8a, 0x08, 0xb3, 0x0a, 0x66, 0xc5, 0x91, 0x3f, 0x01, 0x51, 0x96, 0x3c, 0x36, 0x05, 0x60, 0xdb, 0x03, 0x87, 0xb3 }, { 0x90, 0xa8, 0x35, 0x85, 0x71, 0x7b, 0x75, 0xf0, 0xe9, 0xb7, 0x25, 0xe0, 0x55, 0xee, 0xee, 0xb9, 0xe7, 0xa0, 0x28, 0xea, 0x7e, 0x6c, 0xbc, 0x07, 0xb2, 0x09, 0x17, 0xec, 0x03, 0x63, 0xe3, 0x8c }, { 0x33, 0x6e, 0xa0, 0x53, 0x0f, 0x4a, 0x74, 0x69, 0x12, 0x6e, 0x02, 0x18, 0x58, 0x7e, 0xbb, 0xde, 0x33, 0x58, 0xa0, 0xb3, 0x1c, 0x29, 0xd2, 0x00, 0xf7, 0xdc, 0x7e, 0xb1, 0x5c, 0x6a, 0xad, 0xd8 }, { 0xa7, 0x9e, 0x76, 0xdc, 0x0a, 0xbc, 0xa4, 0x39, 0x6f, 0x07, 0x47, 0xcd, 0x7b, 0x74, 0x8d, 0xf9, 0x13, 0x00, 0x76, 0x26, 0xb1, 0xd6, 0x59, 0xda, 0x0c, 0x1f, 0x78, 0xb9, 0x30, 0x3d, 0x01, 0xa3 }, { 0x44, 0xe7, 0x8a, 0x77, 0x37, 0x56, 0xe0, 0x95, 0x15, 0x19, 0x50, 0x4d, 0x70, 0x38, 0xd2, 0x8d, 0x02, 0x13, 0xa3, 0x7e, 0x0c, 0xe3, 0x75, 0x37, 0x17, 0x57, 0xbc, 0x99, 0x63, 0x11, 0xe3, 0xb8 }, { 0x77, 0xac, 0x01, 0x2a, 0x3f, 0x75, 0x4d, 0xcf, 0xea, 0xb5, 0xeb, 0x99, 0x6b, 0xe9, 0xcd, 0x2d, 0x1f, 0x96, 0x11, 0x1b, 0x6e, 0x49, 0xf3, 0x99, 0x4d, 0xf1, 0x81, 0xf2, 0x85, 0x69, 0xd8, 0x25 }, { 0xce, 0x5a, 0x10, 0xdb, 0x6f, 0xcc, 0xda, 0xf1, 0x40, 0xaa, 0xa4, 0xde, 0xd6, 0x25, 0x0a, 0x9c, 0x06, 0xe9, 0x22, 0x2b, 0xc9, 0xf9, 0xf3, 0x65, 0x8a, 0x4a, 0xff, 0x93, 0x5f, 0x2b, 0x9f, 0x3a }, { 0xec, 0xc2, 0x03, 0xa7, 0xfe, 0x2b, 0xe4, 0xab, 0xd5, 0x5b, 0xb5, 0x3e, 0x6e, 0x67, 0x35, 0x72, 0xe0, 0x07, 0x8d, 0xa8, 0xcd, 0x37, 0x5e, 0xf4, 0x30, 0xcc, 0x97, 0xf9, 0xf8, 0x00, 0x83, 0xaf }, { 0x14, 0xa5, 0x18, 0x6d, 0xe9, 0xd7, 0xa1, 0x8b, 0x04, 0x12, 0xb8, 0x56, 0x3e, 0x51, 0xcc, 0x54, 0x33, 0x84, 0x0b, 0x4a, 0x12, 0x9a, 0x8f, 0xf9, 0x63, 0xb3, 0x3a, 0x3c, 0x4a, 0xfe, 0x8e, 0xbb }, { 0x13, 0xf8, 0xef, 0x95, 0xcb, 0x86, 0xe6, 0xa6, 0x38, 0x93, 0x1c, 0x8e, 0x10, 0x76, 0x73, 0xeb, 0x76, 0xba, 0x10, 0xd7, 0xc2, 0xcd, 0x70, 0xb9, 0xd9, 0x92, 0x0b, 0xbe, 0xed, 0x92, 0x94, 0x09 }, { 0x0b, 0x33, 0x8f, 0x4e, 0xe1, 0x2f, 0x2d, 0xfc, 0xb7, 0x87, 0x13, 0x37, 0x79, 0x41, 0xe0, 0xb0, 0x63, 0x21, 0x52, 0x58, 0x1d, 0x13, 0x32, 0x51, 0x6e, 0x4a, 0x2c, 0xab, 0x19, 0x42, 0xcc, 0xa4 }, { 0xea, 0xab, 0x0e, 0xc3, 0x7b, 0x3b, 0x8a, 0xb7, 0x96, 0xe9, 0xf5, 0x72, 0x38, 0xde, 0x14, 0xa2, 0x64, 0xa0, 0x76, 0xf3, 0x88, 0x7d, 0x86, 0xe2, 0x9b, 0xb5, 0x90, 0x6d, 0xb5, 0xa0, 0x0e, 0x02 }, { 0x23, 0xcb, 0x68, 0xb8, 0xc0, 0xe6, 0xdc, 0x26, 0xdc, 0x27, 0x76, 0x6d, 0xdc, 0x0a, 0x13, 0xa9, 0x94, 0x38, 0xfd, 0x55, 0x61, 0x7a, 0xa4, 0x09, 0x5d, 0x8f, 0x96, 0x97, 0x20, 0xc8, 0x72, 0xdf }, { 0x09, 0x1d, 0x8e, 0xe3, 0x0d, 0x6f, 0x29, 0x68, 0xd4, 0x6b, 0x68, 0x7d, 0xd6, 0x52, 0x92, 0x66, 0x57, 0x42, 0xde, 0x0b, 0xb8, 0x3d, 0xcc, 0x00, 0x04, 0xc7, 0x2c, 0xe1, 0x00, 0x07, 0xa5, 0x49 }, { 0x7f, 0x50, 0x7a, 0xbc, 0x6d, 0x19, 0xba, 0x00, 0xc0, 0x65, 0xa8, 0x76, 0xec, 0x56, 0x57, 0x86, 0x88, 0x82, 0xd1, 0x8a, 0x22, 0x1b, 0xc4, 0x6c, 0x7a, 0x69, 0x12, 0x54, 0x1f, 0x5b, 0xc7, 0xba }, { 0xa0, 0x60, 0x7c, 0x24, 0xe1, 0x4e, 0x8c, 0x22, 0x3d, 0xb0, 0xd7, 0x0b, 0x4d, 0x30, 0xee, 0x88, 0x01, 0x4d, 0x60, 0x3f, 0x43, 0x7e, 0x9e, 0x02, 0xaa, 0x7d, 0xaf, 0xa3, 0xcd, 0xfb, 0xad, 0x94 }, { 0xdd, 0xbf, 0xea, 0x75, 0xcc, 0x46, 0x78, 0x82, 0xeb, 0x34, 0x83, 0xce, 0x5e, 0x2e, 0x75, 0x6a, 0x4f, 0x47, 0x01, 0xb7, 0x6b, 0x44, 0x55, 0x19, 0xe8, 0x9f, 0x22, 0xd6, 0x0f, 0xa8, 0x6e, 0x06 }, { 0x0c, 0x31, 0x1f, 0x38, 0xc3, 0x5a, 0x4f, 0xb9, 0x0d, 0x65, 0x1c, 0x28, 0x9d, 0x48, 0x68, 0x56, 0xcd, 0x14, 0x13, 0xdf, 0x9b, 0x06, 0x77, 0xf5, 0x3e, 0xce, 0x2c, 0xd9, 0xe4, 0x77, 0xc6, 0x0a }, { 0x46, 0xa7, 0x3a, 0x8d, 0xd3, 0xe7, 0x0f, 0x59, 0xd3, 0x94, 0x2c, 0x01, 0xdf, 0x59, 0x9d, 0xef, 0x78, 0x3c, 0x9d, 0xa8, 0x2f, 0xd8, 0x32, 0x22, 0xcd, 0x66, 0x2b, 0x53, 0xdc, 0xe7, 0xdb, 0xdf }, { 0xad, 0x03, 0x8f, 0xf9, 0xb1, 0x4d, 0xe8, 0x4a, 0x80, 0x1e, 0x4e, 0x62, 0x1c, 0xe5, 0xdf, 0x02, 0x9d, 0xd9, 0x35, 0x20, 0xd0, 0xc2, 0xfa, 0x38, 0xbf, 0xf1, 0x76, 0xa8, 0xb1, 0xd1, 0x69, 0x8c }, { 0xab, 0x70, 0xc5, 0xdf, 0xbd, 0x1e, 0xa8, 0x17, 0xfe, 0xd0, 0xcd, 0x06, 0x72, 0x93, 0xab, 0xf3, 0x19, 0xe5, 0xd7, 0x90, 0x1c, 0x21, 0x41, 0xd5, 0xd9, 0x9b, 0x23, 0xf0, 0x3a, 0x38, 0xe7, 0x48 }, { 0x1f, 0xff, 0xda, 0x67, 0x93, 0x2b, 0x73, 0xc8, 0xec, 0xaf, 0x00, 0x9a, 0x34, 0x91, 0xa0, 0x26, 0x95, 0x3b, 0xab, 0xfe, 0x1f, 0x66, 0x3b, 0x06, 0x97, 0xc3, 0xc4, 0xae, 0x8b, 0x2e, 0x7d, 0xcb }, { 0xb0, 0xd2, 0xcc, 0x19, 0x47, 0x2d, 0xd5, 0x7f, 0x2b, 0x17, 0xef, 0xc0, 0x3c, 0x8d, 0x58, 0xc2, 0x28, 0x3d, 0xbb, 0x19, 0xda, 0x57, 0x2f, 0x77, 0x55, 0x85, 0x5a, 0xa9, 0x79, 0x43, 0x17, 0xa0 }, { 0xa0, 0xd1, 0x9a, 0x6e, 0xe3, 0x39, 0x79, 0xc3, 0x25, 0x51, 0x0e, 0x27, 0x66, 0x22, 0xdf, 0x41, 0xf7, 0x15, 0x83, 0xd0, 0x75, 0x01, 0xb8, 0x70, 0x71, 0x12, 0x9a, 0x0a, 0xd9, 0x47, 0x32, 0xa5 }, { 0x72, 0x46, 0x42, 0xa7, 0x03, 0x2d, 0x10, 0x62, 0xb8, 0x9e, 0x52, 0xbe, 0xa3, 0x4b, 0x75, 0xdf, 0x7d, 0x8f, 0xe7, 0x72, 0xd9, 0xfe, 0x3c, 0x93, 0xdd, 0xf3, 0xc4, 0x54, 0x5a, 0xb5, 0xa9, 0x9b }, { 0xad, 0xe5, 0xea, 0xa7, 0xe6, 0x1f, 0x67, 0x2d, 0x58, 0x7e, 0xa0, 0x3d, 0xae, 0x7d, 0x7b, 0x55, 0x22, 0x9c, 0x01, 0xd0, 0x6b, 0xc0, 0xa5, 0x70, 0x14, 0x36, 0xcb, 0xd1, 0x83, 0x66, 0xa6, 0x26 }, { 0x01, 0x3b, 0x31, 0xeb, 0xd2, 0x28, 0xfc, 0xdd, 0xa5, 0x1f, 0xab, 0xb0, 0x3b, 0xb0, 0x2d, 0x60, 0xac, 0x20, 0xca, 0x21, 0x5a, 0xaf, 0xa8, 0x3b, 0xdd, 0x85, 0x5e, 0x37, 0x55, 0xa3, 0x5f, 0x0b }, { 0x33, 0x2e, 0xd4, 0x0b, 0xb1, 0x0d, 0xde, 0x3c, 0x95, 0x4a, 0x75, 0xd7, 0xb8, 0x99, 0x9d, 0x4b, 0x26, 0xa1, 0xc0, 0x63, 0xc1, 0xdc, 0x6e, 0x32, 0xc1, 0xd9, 0x1b, 0xab, 0x7b, 0xbb, 0x7d, 0x16 }, { 0xc7, 0xa1, 0x97, 0xb3, 0xa0, 0x5b, 0x56, 0x6b, 0xcc, 0x9f, 0xac, 0xd2, 0x0e, 0x44, 0x1d, 0x6f, 0x6c, 0x28, 0x60, 0xac, 0x96, 0x51, 0xcd, 0x51, 0xd6, 0xb9, 0xd2, 0xcd, 0xee, 0xea, 0x03, 0x90 }, { 0xbd, 0x9c, 0xf6, 0x4e, 0xa8, 0x95, 0x3c, 0x03, 0x71, 0x08, 0xe6, 0xf6, 0x54, 0x91, 0x4f, 0x39, 0x58, 0xb6, 0x8e, 0x29, 0xc1, 0x67, 0x00, 0xdc, 0x18, 0x4d, 0x94, 0xa2, 0x17, 0x08, 0xff, 0x60 }, { 0x88, 0x35, 0xb0, 0xac, 0x02, 0x11, 0x51, 0xdf, 0x71, 0x64, 0x74, 0xce, 0x27, 0xce, 0x4d, 0x3c, 0x15, 0xf0, 0xb2, 0xda, 0xb4, 0x80, 0x03, 0xcf, 0x3f, 0x3e, 0xfd, 0x09, 0x45, 0x10, 0x6b, 0x9a }, { 0x3b, 0xfe, 0xfa, 0x33, 0x01, 0xaa, 0x55, 0xc0, 0x80, 0x19, 0x0c, 0xff, 0xda, 0x8e, 0xae, 0x51, 0xd9, 0xaf, 0x48, 0x8b, 0x4c, 0x1f, 0x24, 0xc3, 0xd9, 0xa7, 0x52, 0x42, 0xfd, 0x8e, 0xa0, 0x1d }, { 0x08, 0x28, 0x4d, 0x14, 0x99, 0x3c, 0xd4, 0x7d, 0x53, 0xeb, 0xae, 0xcf, 0x0d, 0xf0, 0x47, 0x8c, 0xc1, 0x82, 0xc8, 0x9c, 0x00, 0xe1, 0x85, 0x9c, 0x84, 0x85, 0x16, 0x86, 0xdd, 0xf2, 0xc1, 0xb7 }, { 0x1e, 0xd7, 0xef, 0x9f, 0x04, 0xc2, 0xac, 0x8d, 0xb6, 0xa8, 0x64, 0xdb, 0x13, 0x10, 0x87, 0xf2, 0x70, 0x65, 0x09, 0x8e, 0x69, 0xc3, 0xfe, 0x78, 0x71, 0x8d, 0x9b, 0x94, 0x7f, 0x4a, 0x39, 0xd0 }, { 0xc1, 0x61, 0xf2, 0xdc, 0xd5, 0x7e, 0x9c, 0x14, 0x39, 0xb3, 0x1a, 0x9d, 0xd4, 0x3d, 0x8f, 0x3d, 0x7d, 0xd8, 0xf0, 0xeb, 0x7c, 0xfa, 0xc6, 0xfb, 0x25, 0xa0, 0xf2, 0x8e, 0x30, 0x6f, 0x06, 0x61 }, { 0xc0, 0x19, 0x69, 0xad, 0x34, 0xc5, 0x2c, 0xaf, 0x3d, 0xc4, 0xd8, 0x0d, 0x19, 0x73, 0x5c, 0x29, 0x73, 0x1a, 0xc6, 0xe7, 0xa9, 0x20, 0x85, 0xab, 0x92, 0x50, 0xc4, 0x8d, 0xea, 0x48, 0xa3, 0xfc }, { 0x17, 0x20, 0xb3, 0x65, 0x56, 0x19, 0xd2, 0xa5, 0x2b, 0x35, 0x21, 0xae, 0x0e, 0x49, 0xe3, 0x45, 0xcb, 0x33, 0x89, 0xeb, 0xd6, 0x20, 0x8a, 0xca, 0xf9, 0xf1, 0x3f, 0xda, 0xcc, 0xa8, 0xbe, 0x49 }, { 0x75, 0x62, 0x88, 0x36, 0x1c, 0x83, 0xe2, 0x4c, 0x61, 0x7c, 0xf9, 0x5c, 0x90, 0x5b, 0x22, 0xd0, 0x17, 0xcd, 0xc8, 0x6f, 0x0b, 0xf1, 0xd6, 0x58, 0xf4, 0x75, 0x6c, 0x73, 0x79, 0x87, 0x3b, 0x7f }, { 0xe7, 0xd0, 0xed, 0xa3, 0x45, 0x26, 0x93, 0xb7, 0x52, 0xab, 0xcd, 0xa1, 0xb5, 0x5e, 0x27, 0x6f, 0x82, 0x69, 0x8f, 0x5f, 0x16, 0x05, 0x40, 0x3e, 0xff, 0x83, 0x0b, 0xea, 0x00, 0x71, 0xa3, 0x94 }, { 0x2c, 0x82, 0xec, 0xaa, 0x6b, 0x84, 0x80, 0x3e, 0x04, 0x4a, 0xf6, 0x31, 0x18, 0xaf, 0xe5, 0x44, 0x68, 0x7c, 0xb6, 0xe6, 0xc7, 0xdf, 0x49, 0xed, 0x76, 0x2d, 0xfd, 0x7c, 0x86, 0x93, 0xa1, 0xbc }, { 0x61, 0x36, 0xcb, 0xf4, 0xb4, 0x41, 0x05, 0x6f, 0xa1, 0xe2, 0x72, 0x24, 0x98, 0x12, 0x5d, 0x6d, 0xed, 0x45, 0xe1, 0x7b, 0x52, 0x14, 0x39, 0x59, 0xc7, 0xf4, 0xd4, 0xe3, 0x95, 0x21, 0x8a, 0xc2 }, { 0x72, 0x1d, 0x32, 0x45, 0xaa, 0xfe, 0xf2, 0x7f, 0x6a, 0x62, 0x4f, 0x47, 0x95, 0x4b, 0x6c, 0x25, 0x50, 0x79, 0x52, 0x6f, 0xfa, 0x25, 0xe9, 0xff, 0x77, 0xe5, 0xdc, 0xff, 0x47, 0x3b, 0x15, 0x97 }, { 0x9d, 0xd2, 0xfb, 0xd8, 0xce, 0xf1, 0x6c, 0x35, 0x3c, 0x0a, 0xc2, 0x11, 0x91, 0xd5, 0x09, 0xeb, 0x28, 0xdd, 0x9e, 0x3e, 0x0d, 0x8c, 0xea, 0x5d, 0x26, 0xca, 0x83, 0x93, 0x93, 0x85, 0x1c, 0x3a }, { 0xb2, 0x39, 0x4c, 0xea, 0xcd, 0xeb, 0xf2, 0x1b, 0xf9, 0xdf, 0x2c, 0xed, 0x98, 0xe5, 0x8f, 0x1c, 0x3a, 0x4b, 0xbb, 0xff, 0x66, 0x0d, 0xd9, 0x00, 0xf6, 0x22, 0x02, 0xd6, 0x78, 0x5c, 0xc4, 0x6e }, { 0x57, 0x08, 0x9f, 0x22, 0x27, 0x49, 0xad, 0x78, 0x71, 0x76, 0x5f, 0x06, 0x2b, 0x11, 0x4f, 0x43, 0xba, 0x20, 0xec, 0x56, 0x42, 0x2a, 0x8b, 0x1e, 0x3f, 0x87, 0x19, 0x2c, 0x0e, 0xa7, 0x18, 0xc6 }, { 0xe4, 0x9a, 0x94, 0x59, 0x96, 0x1c, 0xd3, 0x3c, 0xdf, 0x4a, 0xae, 0x1b, 0x10, 0x78, 0xa5, 0xde, 0xa7, 0xc0, 0x40, 0xe0, 0xfe, 0xa3, 0x40, 0xc9, 0x3a, 0x72, 0x48, 0x72, 0xfc, 0x4a, 0xf8, 0x06 }, { 0xed, 0xe6, 0x7f, 0x72, 0x0e, 0xff, 0xd2, 0xca, 0x9c, 0x88, 0x99, 0x41, 0x52, 0xd0, 0x20, 0x1d, 0xee, 0x6b, 0x0a, 0x2d, 0x2c, 0x07, 0x7a, 0xca, 0x6d, 0xae, 0x29, 0xf7, 0x3f, 0x8b, 0x63, 0x09 }, { 0xe0, 0xf4, 0x34, 0xbf, 0x22, 0xe3, 0x08, 0x80, 0x39, 0xc2, 0x1f, 0x71, 0x9f, 0xfc, 0x67, 0xf0, 0xf2, 0xcb, 0x5e, 0x98, 0xa7, 0xa0, 0x19, 0x4c, 0x76, 0xe9, 0x6b, 0xf4, 0xe8, 0xe1, 0x7e, 0x61 }, { 0x27, 0x7c, 0x04, 0xe2, 0x85, 0x34, 0x84, 0xa4, 0xeb, 0xa9, 0x10, 0xad, 0x33, 0x6d, 0x01, 0xb4, 0x77, 0xb6, 0x7c, 0xc2, 0x00, 0xc5, 0x9f, 0x3c, 0x8d, 0x77, 0xee, 0xf8, 0x49, 0x4f, 0x29, 0xcd }, { 0x15, 0x6d, 0x57, 0x47, 0xd0, 0xc9, 0x9c, 0x7f, 0x27, 0x09, 0x7d, 0x7b, 0x7e, 0x00, 0x2b, 0x2e, 0x18, 0x5c, 0xb7, 0x2d, 0x8d, 0xd7, 0xeb, 0x42, 0x4a, 0x03, 0x21, 0x52, 0x81, 0x61, 0x21, 0x9f }, { 0x20, 0xdd, 0xd1, 0xed, 0x9b, 0x1c, 0xa8, 0x03, 0x94, 0x6d, 0x64, 0xa8, 0x3a, 0xe4, 0x65, 0x9d, 0xa6, 0x7f, 0xba, 0x7a, 0x1a, 0x3e, 0xdd, 0xb1, 0xe1, 0x03, 0xc0, 0xf5, 0xe0, 0x3e, 0x3a, 0x2c }, { 0xf0, 0xaf, 0x60, 0x4d, 0x3d, 0xab, 0xbf, 0x9a, 0x0f, 0x2a, 0x7d, 0x3d, 0xda, 0x6b, 0xd3, 0x8b, 0xba, 0x72, 0xc6, 0xd0, 0x9b, 0xe4, 0x94, 0xfc, 0xef, 0x71, 0x3f, 0xf1, 0x01, 0x89, 0xb6, 0xe6 }, { 0x98, 0x02, 0xbb, 0x87, 0xde, 0xf4, 0xcc, 0x10, 0xc4, 0xa5, 0xfd, 0x49, 0xaa, 0x58, 0xdf, 0xe2, 0xf3, 0xfd, 0xdb, 0x46, 0xb4, 0x70, 0x88, 0x14, 0xea, 0xd8, 0x1d, 0x23, 0xba, 0x95, 0x13, 0x9b }, { 0x4f, 0x8c, 0xe1, 0xe5, 0x1d, 0x2f, 0xe7, 0xf2, 0x40, 0x43, 0xa9, 0x04, 0xd8, 0x98, 0xeb, 0xfc, 0x91, 0x97, 0x54, 0x18, 0x75, 0x34, 0x13, 0xaa, 0x09, 0x9b, 0x79, 0x5e, 0xcb, 0x35, 0xce, 0xdb }, { 0xbd, 0xdc, 0x65, 0x14, 0xd7, 0xee, 0x6a, 0xce, 0x0a, 0x4a, 0xc1, 0xd0, 0xe0, 0x68, 0x11, 0x22, 0x88, 0xcb, 0xcf, 0x56, 0x04, 0x54, 0x64, 0x27, 0x05, 0x63, 0x01, 0x77, 0xcb, 0xa6, 0x08, 0xbd }, { 0xd6, 0x35, 0x99, 0x4f, 0x62, 0x91, 0x51, 0x7b, 0x02, 0x81, 0xff, 0xdd, 0x49, 0x6a, 0xfa, 0x86, 0x27, 0x12, 0xe5, 0xb3, 0xc4, 0xe5, 0x2e, 0x4c, 0xd5, 0xfd, 0xae, 0x8c, 0x0e, 0x72, 0xfb, 0x08 }, { 0x87, 0x8d, 0x9c, 0xa6, 0x00, 0xcf, 0x87, 0xe7, 0x69, 0xcc, 0x30, 0x5c, 0x1b, 0x35, 0x25, 0x51, 0x86, 0x61, 0x5a, 0x73, 0xa0, 0xda, 0x61, 0x3b, 0x5f, 0x1c, 0x98, 0xdb, 0xf8, 0x12, 0x83, 0xea }, { 0xa6, 0x4e, 0xbe, 0x5d, 0xc1, 0x85, 0xde, 0x9f, 0xdd, 0xe7, 0x60, 0x7b, 0x69, 0x98, 0x70, 0x2e, 0xb2, 0x34, 0x56, 0x18, 0x49, 0x57, 0x30, 0x7d, 0x2f, 0xa7, 0x2e, 0x87, 0xa4, 0x77, 0x02, 0xd6 }, { 0xce, 0x50, 0xea, 0xb7, 0xb5, 0xeb, 0x52, 0xbd, 0xc9, 0xad, 0x8e, 0x5a, 0x48, 0x0a, 0xb7, 0x80, 0xca, 0x93, 0x20, 0xe4, 0x43, 0x60, 0xb1, 0xfe, 0x37, 0xe0, 0x3f, 0x2f, 0x7a, 0xd7, 0xde, 0x01 }, { 0xee, 0xdd, 0xb7, 0xc0, 0xdb, 0x6e, 0x30, 0xab, 0xe6, 0x6d, 0x79, 0xe3, 0x27, 0x51, 0x1e, 0x61, 0xfc, 0xeb, 0xbc, 0x29, 0xf1, 0x59, 0xb4, 0x0a, 0x86, 0xb0, 0x46, 0xec, 0xf0, 0x51, 0x38, 0x23 }, { 0x78, 0x7f, 0xc9, 0x34, 0x40, 0xc1, 0xec, 0x96, 0xb5, 0xad, 0x01, 0xc1, 0x6c, 0xf7, 0x79, 0x16, 0xa1, 0x40, 0x5f, 0x94, 0x26, 0x35, 0x6e, 0xc9, 0x21, 0xd8, 0xdf, 0xf3, 0xea, 0x63, 0xb7, 0xe0 }, { 0x7f, 0x0d, 0x5e, 0xab, 0x47, 0xee, 0xfd, 0xa6, 0x96, 0xc0, 0xbf, 0x0f, 0xbf, 0x86, 0xab, 0x21, 0x6f, 0xce, 0x46, 0x1e, 0x93, 0x03, 0xab, 0xa6, 0xac, 0x37, 0x41, 0x20, 0xe8, 0x90, 0xe8, 0xdf }, { 0xb6, 0x80, 0x04, 0xb4, 0x2f, 0x14, 0xad, 0x02, 0x9f, 0x4c, 0x2e, 0x03, 0xb1, 0xd5, 0xeb, 0x76, 0xd5, 0x71, 0x60, 0xe2, 0x64, 0x76, 0xd2, 0x11, 0x31, 0xbe, 0xf2, 0x0a, 0xda, 0x7d, 0x27, 0xf4 }, { 0xb0, 0xc4, 0xeb, 0x18, 0xae, 0x25, 0x0b, 0x51, 0xa4, 0x13, 0x82, 0xea, 0xd9, 0x2d, 0x0d, 0xc7, 0x45, 0x5f, 0x93, 0x79, 0xfc, 0x98, 0x84, 0x42, 0x8e, 0x47, 0x70, 0x60, 0x8d, 0xb0, 0xfa, 0xec }, { 0xf9, 0x2b, 0x7a, 0x87, 0x0c, 0x05, 0x9f, 0x4d, 0x46, 0x46, 0x4c, 0x82, 0x4e, 0xc9, 0x63, 0x55, 0x14, 0x0b, 0xdc, 0xe6, 0x81, 0x32, 0x2c, 0xc3, 0xa9, 0x92, 0xff, 0x10, 0x3e, 0x3f, 0xea, 0x52 }, { 0x53, 0x64, 0x31, 0x26, 0x14, 0x81, 0x33, 0x98, 0xcc, 0x52, 0x5d, 0x4c, 0x4e, 0x14, 0x6e, 0xde, 0xb3, 0x71, 0x26, 0x5f, 0xba, 0x19, 0x13, 0x3a, 0x2c, 0x3d, 0x21, 0x59, 0x29, 0x8a, 0x17, 0x42 }, { 0xf6, 0x62, 0x0e, 0x68, 0xd3, 0x7f, 0xb2, 0xaf, 0x50, 0x00, 0xfc, 0x28, 0xe2, 0x3b, 0x83, 0x22, 0x97, 0xec, 0xd8, 0xbc, 0xe9, 0x9e, 0x8b, 0xe4, 0xd0, 0x4e, 0x85, 0x30, 0x9e, 0x3d, 0x33, 0x74 }, { 0x53, 0x16, 0xa2, 0x79, 0x69, 0xd7, 0xfe, 0x04, 0xff, 0x27, 0xb2, 0x83, 0x96, 0x1b, 0xff, 0xc3, 0xbf, 0x5d, 0xfb, 0x32, 0xfb, 0x6a, 0x89, 0xd1, 0x01, 0xc6, 0xc3, 0xb1, 0x93, 0x7c, 0x28, 0x71 }, { 0x81, 0xd1, 0x66, 0x4f, 0xdf, 0x3c, 0xb3, 0x3c, 0x24, 0xee, 0xba, 0xc0, 0xbd, 0x64, 0x24, 0x4b, 0x77, 0xc4, 0xab, 0xea, 0x90, 0xbb, 0xe8, 0xb5, 0xee, 0x0b, 0x2a, 0xaf, 0xcf, 0x2d, 0x6a, 0x53 }, { 0x34, 0x57, 0x82, 0xf2, 0x95, 0xb0, 0x88, 0x03, 0x52, 0xe9, 0x24, 0xa0, 0x46, 0x7b, 0x5f, 0xbc, 0x3e, 0x8f, 0x3b, 0xfb, 0xc3, 0xc7, 0xe4, 0x8b, 0x67, 0x09, 0x1f, 0xb5, 0xe8, 0x0a, 0x94, 0x42 }, { 0x79, 0x41, 0x11, 0xea, 0x6c, 0xd6, 0x5e, 0x31, 0x1f, 0x74, 0xee, 0x41, 0xd4, 0x76, 0xcb, 0x63, 0x2c, 0xe1, 0xe4, 0xb0, 0x51, 0xdc, 0x1d, 0x9e, 0x9d, 0x06, 0x1a, 0x19, 0xe1, 0xd0, 0xbb, 0x49 }, { 0x2a, 0x85, 0xda, 0xf6, 0x13, 0x88, 0x16, 0xb9, 0x9b, 0xf8, 0xd0, 0x8b, 0xa2, 0x11, 0x4b, 0x7a, 0xb0, 0x79, 0x75, 0xa7, 0x84, 0x20, 0xc1, 0xa3, 0xb0, 0x6a, 0x77, 0x7c, 0x22, 0xdd, 0x8b, 0xcb }, { 0x89, 0xb0, 0xd5, 0xf2, 0x89, 0xec, 0x16, 0x40, 0x1a, 0x06, 0x9a, 0x96, 0x0d, 0x0b, 0x09, 0x3e, 0x62, 0x5d, 0xa3, 0xcf, 0x41, 0xee, 0x29, 0xb5, 0x9b, 0x93, 0x0c, 0x58, 0x20, 0x14, 0x54, 0x55 }, { 0xd0, 0xfd, 0xcb, 0x54, 0x39, 0x43, 0xfc, 0x27, 0xd2, 0x08, 0x64, 0xf5, 0x21, 0x81, 0x47, 0x1b, 0x94, 0x2c, 0xc7, 0x7c, 0xa6, 0x75, 0xbc, 0xb3, 0x0d, 0xf3, 0x1d, 0x35, 0x8e, 0xf7, 0xb1, 0xeb }, { 0xb1, 0x7e, 0xa8, 0xd7, 0x70, 0x63, 0xc7, 0x09, 0xd4, 0xdc, 0x6b, 0x87, 0x94, 0x13, 0xc3, 0x43, 0xe3, 0x79, 0x0e, 0x9e, 0x62, 0xca, 0x85, 0xb7, 0x90, 0x0b, 0x08, 0x6f, 0x6b, 0x75, 0xc6, 0x72 }, { 0xe7, 0x1a, 0x3e, 0x2c, 0x27, 0x4d, 0xb8, 0x42, 0xd9, 0x21, 0x14, 0xf2, 0x17, 0xe2, 0xc0, 0xea, 0xc8, 0xb4, 0x50, 0x93, 0xfd, 0xfd, 0x9d, 0xf4, 0xca, 0x71, 0x62, 0x39, 0x48, 0x62, 0xd5, 0x01 }, { 0xc0, 0x47, 0x67, 0x59, 0xab, 0x7a, 0xa3, 0x33, 0x23, 0x4f, 0x6b, 0x44, 0xf5, 0xfd, 0x85, 0x83, 0x90, 0xec, 0x23, 0x69, 0x4c, 0x62, 0x2c, 0xb9, 0x86, 0xe7, 0x69, 0xc7, 0x8e, 0xdd, 0x73, 0x3e }, { 0x9a, 0xb8, 0xea, 0xbb, 0x14, 0x16, 0x43, 0x4d, 0x85, 0x39, 0x13, 0x41, 0xd5, 0x69, 0x93, 0xc5, 0x54, 0x58, 0x16, 0x7d, 0x44, 0x18, 0xb1, 0x9a, 0x0f, 0x2a, 0xd8, 0xb7, 0x9a, 0x83, 0xa7, 0x5b }, { 0x79, 0x92, 0xd0, 0xbb, 0xb1, 0x5e, 0x23, 0x82, 0x6f, 0x44, 0x3e, 0x00, 0x50, 0x5d, 0x68, 0xd3, 0xed, 0x73, 0x72, 0x99, 0x5a, 0x5c, 0x3e, 0x49, 0x86, 0x54, 0x10, 0x2f, 0xbc, 0xd0, 0x96, 0x4e }, { 0xc0, 0x21, 0xb3, 0x00, 0x85, 0x15, 0x14, 0x35, 0xdf, 0x33, 0xb0, 0x07, 0xcc, 0xec, 0xc6, 0x9d, 0xf1, 0x26, 0x9f, 0x39, 0xba, 0x25, 0x09, 0x2b, 0xed, 0x59, 0xd9, 0x32, 0xac, 0x0f, 0xdc, 0x28 }, { 0x91, 0xa2, 0x5e, 0xc0, 0xec, 0x0d, 0x9a, 0x56, 0x7f, 0x89, 0xc4, 0xbf, 0xe1, 0xa6, 0x5a, 0x0e, 0x43, 0x2d, 0x07, 0x06, 0x4b, 0x41, 0x90, 0xe2, 0x7d, 0xfb, 0x81, 0x90, 0x1f, 0xd3, 0x13, 0x9b }, { 0x59, 0x50, 0xd3, 0x9a, 0x23, 0xe1, 0x54, 0x5f, 0x30, 0x12, 0x70, 0xaa, 0x1a, 0x12, 0xf2, 0xe6, 0xc4, 0x53, 0x77, 0x6e, 0x4d, 0x63, 0x55, 0xde, 0x42, 0x5c, 0xc1, 0x53, 0xf9, 0x81, 0x88, 0x67 }, { 0xd7, 0x9f, 0x14, 0x72, 0x0c, 0x61, 0x0a, 0xf1, 0x79, 0xa3, 0x76, 0x5d, 0x4b, 0x7c, 0x09, 0x68, 0xf9, 0x77, 0x96, 0x2d, 0xbf, 0x65, 0x5b, 0x52, 0x12, 0x72, 0xb6, 0xf1, 0xe1, 0x94, 0x48, 0x8e }, { 0xe9, 0x53, 0x1b, 0xfc, 0x8b, 0x02, 0x99, 0x5a, 0xea, 0xa7, 0x5b, 0xa2, 0x70, 0x31, 0xfa, 0xdb, 0xcb, 0xf4, 0xa0, 0xda, 0xb8, 0x96, 0x1d, 0x92, 0x96, 0xcd, 0x7e, 0x84, 0xd2, 0x5d, 0x60, 0x06 }, { 0x34, 0xe9, 0xc2, 0x6a, 0x01, 0xd7, 0xf1, 0x61, 0x81, 0xb4, 0x54, 0xa9, 0xd1, 0x62, 0x3c, 0x23, 0x3c, 0xb9, 0x9d, 0x31, 0xc6, 0x94, 0x65, 0x6e, 0x94, 0x13, 0xac, 0xa3, 0xe9, 0x18, 0x69, 0x2f }, { 0xd9, 0xd7, 0x42, 0x2f, 0x43, 0x7b, 0xd4, 0x39, 0xdd, 0xd4, 0xd8, 0x83, 0xda, 0xe2, 0xa0, 0x83, 0x50, 0x17, 0x34, 0x14, 0xbe, 0x78, 0x15, 0x51, 0x33, 0xff, 0xf1, 0x96, 0x4c, 0x3d, 0x79, 0x72 }, { 0x4a, 0xee, 0x0c, 0x7a, 0xaf, 0x07, 0x54, 0x14, 0xff, 0x17, 0x93, 0xea, 0xd7, 0xea, 0xca, 0x60, 0x17, 0x75, 0xc6, 0x15, 0xdb, 0xd6, 0x0b, 0x64, 0x0b, 0x0a, 0x9f, 0x0c, 0xe5, 0x05, 0xd4, 0x35 }, { 0x6b, 0xfd, 0xd1, 0x54, 0x59, 0xc8, 0x3b, 0x99, 0xf0, 0x96, 0xbf, 0xb4, 0x9e, 0xe8, 0x7b, 0x06, 0x3d, 0x69, 0xc1, 0x97, 0x4c, 0x69, 0x28, 0xac, 0xfc, 0xfb, 0x40, 0x99, 0xf8, 0xc4, 0xef, 0x67 }, { 0x9f, 0xd1, 0xc4, 0x08, 0xfd, 0x75, 0xc3, 0x36, 0x19, 0x3a, 0x2a, 0x14, 0xd9, 0x4f, 0x6a, 0xf5, 0xad, 0xf0, 0x50, 0xb8, 0x03, 0x87, 0xb4, 0xb0, 0x10, 0xfb, 0x29, 0xf4, 0xcc, 0x72, 0x70, 0x7c }, { 0x13, 0xc8, 0x84, 0x80, 0xa5, 0xd0, 0x0d, 0x6c, 0x8c, 0x7a, 0xd2, 0x11, 0x0d, 0x76, 0xa8, 0x2d, 0x9b, 0x70, 0xf4, 0xfa, 0x66, 0x96, 0xd4, 0xe5, 0xdd, 0x42, 0xa0, 0x66, 0xdc, 0xaf, 0x99, 0x20 }, { 0x82, 0x0e, 0x72, 0x5e, 0xe2, 0x5f, 0xe8, 0xfd, 0x3a, 0x8d, 0x5a, 0xbe, 0x4c, 0x46, 0xc3, 0xba, 0x88, 0x9d, 0xe6, 0xfa, 0x91, 0x91, 0xaa, 0x22, 0xba, 0x67, 0xd5, 0x70, 0x54, 0x21, 0x54, 0x2b }, { 0x32, 0xd9, 0x3a, 0x0e, 0xb0, 0x2f, 0x42, 0xfb, 0xbc, 0xaf, 0x2b, 0xad, 0x00, 0x85, 0xb2, 0x82, 0xe4, 0x60, 0x46, 0xa4, 0xdf, 0x7a, 0xd1, 0x06, 0x57, 0xc9, 0xd6, 0x47, 0x63, 0x75, 0xb9, 0x3e }, { 0xad, 0xc5, 0x18, 0x79, 0x05, 0xb1, 0x66, 0x9c, 0xd8, 0xec, 0x9c, 0x72, 0x1e, 0x19, 0x53, 0x78, 0x6b, 0x9d, 0x89, 0xa9, 0xba, 0xe3, 0x07, 0x80, 0xf1, 0xe1, 0xea, 0xb2, 0x4a, 0x00, 0x52, 0x3c }, { 0xe9, 0x07, 0x56, 0xff, 0x7f, 0x9a, 0xd8, 0x10, 0xb2, 0x39, 0xa1, 0x0c, 0xed, 0x2c, 0xf9, 0xb2, 0x28, 0x43, 0x54, 0xc1, 0xf8, 0xc7, 0xe0, 0xac, 0xcc, 0x24, 0x61, 0xdc, 0x79, 0x6d, 0x6e, 0x89 }, { 0x12, 0x51, 0xf7, 0x6e, 0x56, 0x97, 0x84, 0x81, 0x87, 0x53, 0x59, 0x80, 0x1d, 0xb5, 0x89, 0xa0, 0xb2, 0x2f, 0x86, 0xd8, 0xd6, 0x34, 0xdc, 0x04, 0x50, 0x6f, 0x32, 0x2e, 0xd7, 0x8f, 0x17, 0xe8 }, { 0x3a, 0xfa, 0x89, 0x9f, 0xd9, 0x80, 0xe7, 0x3e, 0xcb, 0x7f, 0x4d, 0x8b, 0x8f, 0x29, 0x1d, 0xc9, 0xaf, 0x79, 0x6b, 0xc6, 0x5d, 0x27, 0xf9, 0x74, 0xc6, 0xf1, 0x93, 0xc9, 0x19, 0x1a, 0x09, 0xfd }, { 0xaa, 0x30, 0x5b, 0xe2, 0x6e, 0x5d, 0xed, 0xdc, 0x3c, 0x10, 0x10, 0xcb, 0xc2, 0x13, 0xf9, 0x5f, 0x05, 0x1c, 0x78, 0x5c, 0x5b, 0x43, 0x1e, 0x6a, 0x7c, 0xd0, 0x48, 0xf1, 0x61, 0x78, 0x75, 0x28 }, { 0x8e, 0xa1, 0x88, 0x4f, 0xf3, 0x2e, 0x9d, 0x10, 0xf0, 0x39, 0xb4, 0x07, 0xd0, 0xd4, 0x4e, 0x7e, 0x67, 0x0a, 0xbd, 0x88, 0x4a, 0xee, 0xe0, 0xfb, 0x75, 0x7a, 0xe9, 0x4e, 0xaa, 0x97, 0x37, 0x3d }, { 0xd4, 0x82, 0xb2, 0x15, 0x5d, 0x4d, 0xec, 0x6b, 0x47, 0x36, 0xa1, 0xf1, 0x61, 0x7b, 0x53, 0xaa, 0xa3, 0x73, 0x10, 0x27, 0x7d, 0x3f, 0xef, 0x0c, 0x37, 0xad, 0x41, 0x76, 0x8f, 0xc2, 0x35, 0xb4 }, { 0x4d, 0x41, 0x39, 0x71, 0x38, 0x7e, 0x7a, 0x88, 0x98, 0xa8, 0xdc, 0x2a, 0x27, 0x50, 0x07, 0x78, 0x53, 0x9e, 0xa2, 0x14, 0xa2, 0xdf, 0xe9, 0xb3, 0xd7, 0xe8, 0xeb, 0xdc, 0xe5, 0xcf, 0x3d, 0xb3 }, { 0x69, 0x6e, 0x5d, 0x46, 0xe6, 0xc5, 0x7e, 0x87, 0x96, 0xe4, 0x73, 0x5d, 0x08, 0x91, 0x6e, 0x0b, 0x79, 0x29, 0xb3, 0xcf, 0x29, 0x8c, 0x29, 0x6d, 0x22, 0xe9, 0xd3, 0x01, 0x96, 0x53, 0x37, 0x1c }, { 0x1f, 0x56, 0x47, 0xc1, 0xd3, 0xb0, 0x88, 0x22, 0x88, 0x85, 0x86, 0x5c, 0x89, 0x40, 0x90, 0x8b, 0xf4, 0x0d, 0x1a, 0x82, 0x72, 0x82, 0x19, 0x73, 0xb1, 0x60, 0x00, 0x8e, 0x7a, 0x3c, 0xe2, 0xeb }, { 0xb6, 0xe7, 0x6c, 0x33, 0x0f, 0x02, 0x1a, 0x5b, 0xda, 0x65, 0x87, 0x50, 0x10, 0xb0, 0xed, 0xf0, 0x91, 0x26, 0xc0, 0xf5, 0x10, 0xea, 0x84, 0x90, 0x48, 0x19, 0x20, 0x03, 0xae, 0xf4, 0xc6, 0x1c }, { 0x3c, 0xd9, 0x52, 0xa0, 0xbe, 0xad, 0xa4, 0x1a, 0xbb, 0x42, 0x4c, 0xe4, 0x7f, 0x94, 0xb4, 0x2b, 0xe6, 0x4e, 0x1f, 0xfb, 0x0f, 0xd0, 0x78, 0x22, 0x76, 0x80, 0x79, 0x46, 0xd0, 0xd0, 0xbc, 0x55 }, { 0x98, 0xd9, 0x26, 0x77, 0x43, 0x9b, 0x41, 0xb7, 0xbb, 0x51, 0x33, 0x12, 0xaf, 0xb9, 0x2b, 0xcc, 0x8e, 0xe9, 0x68, 0xb2, 0xe3, 0xb2, 0x38, 0xce, 0xcb, 0x9b, 0x0f, 0x34, 0xc9, 0xbb, 0x63, 0xd0 }, { 0xec, 0xbc, 0xa2, 0xcf, 0x08, 0xae, 0x57, 0xd5, 0x17, 0xad, 0x16, 0x15, 0x8a, 0x32, 0xbf, 0xa7, 0xdc, 0x03, 0x82, 0xea, 0xed, 0xa1, 0x28, 0xe9, 0x18, 0x86, 0x73, 0x4c, 0x24, 0xa0, 0xb2, 0x9d }, { 0x94, 0x2c, 0xc7, 0xc0, 0xb5, 0x2e, 0x2b, 0x16, 0xa4, 0xb8, 0x9f, 0xa4, 0xfc, 0x7e, 0x0b, 0xf6, 0x09, 0xe2, 0x9a, 0x08, 0xc1, 0xa8, 0x54, 0x34, 0x52, 0xb7, 0x7c, 0x7b, 0xfd, 0x11, 0xbb, 0x28 }, { 0x8a, 0x06, 0x5d, 0x8b, 0x61, 0xa0, 0xdf, 0xfb, 0x17, 0x0d, 0x56, 0x27, 0x73, 0x5a, 0x76, 0xb0, 0xe9, 0x50, 0x60, 0x37, 0x80, 0x8c, 0xba, 0x16, 0xc3, 0x45, 0x00, 0x7c, 0x9f, 0x79, 0xcf, 0x8f }, { 0x1b, 0x9f, 0xa1, 0x97, 0x14, 0x65, 0x9c, 0x78, 0xff, 0x41, 0x38, 0x71, 0x84, 0x92, 0x15, 0x36, 0x10, 0x29, 0xac, 0x80, 0x2b, 0x1c, 0xbc, 0xd5, 0x4e, 0x40, 0x8b, 0xd8, 0x72, 0x87, 0xf8, 0x1f }, { 0x8d, 0xab, 0x07, 0x1b, 0xcd, 0x6c, 0x72, 0x92, 0xa9, 0xef, 0x72, 0x7b, 0x4a, 0xe0, 0xd8, 0x67, 0x13, 0x30, 0x1d, 0xa8, 0x61, 0x8d, 0x9a, 0x48, 0xad, 0xce, 0x55, 0xf3, 0x03, 0xa8, 0x69, 0xa1 }, { 0x82, 0x53, 0xe3, 0xe7, 0xc7, 0xb6, 0x84, 0xb9, 0xcb, 0x2b, 0xeb, 0x01, 0x4c, 0xe3, 0x30, 0xff, 0x3d, 0x99, 0xd1, 0x7a, 0xbb, 0xdb, 0xab, 0xe4, 0xf4, 0xd6, 0x74, 0xde, 0xd5, 0x3f, 0xfc, 0x6b }, { 0xf1, 0x95, 0xf3, 0x21, 0xe9, 0xe3, 0xd6, 0xbd, 0x7d, 0x07, 0x45, 0x04, 0xdd, 0x2a, 0xb0, 0xe6, 0x24, 0x1f, 0x92, 0xe7, 0x84, 0xb1, 0xaa, 0x27, 0x1f, 0xf6, 0x48, 0xb1, 0xca, 0xb6, 0xd7, 0xf6 }, { 0x27, 0xe4, 0xcc, 0x72, 0x09, 0x0f, 0x24, 0x12, 0x66, 0x47, 0x6a, 0x7c, 0x09, 0x49, 0x5f, 0x2d, 0xb1, 0x53, 0xd5, 0xbc, 0xbd, 0x76, 0x19, 0x03, 0xef, 0x79, 0x27, 0x5e, 0xc5, 0x6b, 0x2e, 0xd8 }, { 0x89, 0x9c, 0x24, 0x05, 0x78, 0x8e, 0x25, 0xb9, 0x9a, 0x18, 0x46, 0x35, 0x5e, 0x64, 0x6d, 0x77, 0xcf, 0x40, 0x00, 0x83, 0x41, 0x5f, 0x7d, 0xc5, 0xaf, 0xe6, 0x9d, 0x6e, 0x17, 0xc0, 0x00, 0x23 }, { 0xa5, 0x9b, 0x78, 0xc4, 0x90, 0x57, 0x44, 0x07, 0x6b, 0xfe, 0xe8, 0x94, 0xde, 0x70, 0x7d, 0x4f, 0x12, 0x0b, 0x5c, 0x68, 0x93, 0xea, 0x04, 0x00, 0x29, 0x7d, 0x0b, 0xb8, 0x34, 0x72, 0x76, 0x32 }, { 0x59, 0xdc, 0x78, 0xb1, 0x05, 0x64, 0x97, 0x07, 0xa2, 0xbb, 0x44, 0x19, 0xc4, 0x8f, 0x00, 0x54, 0x00, 0xd3, 0x97, 0x3d, 0xe3, 0x73, 0x66, 0x10, 0x23, 0x04, 0x35, 0xb1, 0x04, 0x24, 0xb2, 0x4f }, { 0xc0, 0x14, 0x9d, 0x1d, 0x7e, 0x7a, 0x63, 0x53, 0xa6, 0xd9, 0x06, 0xef, 0xe7, 0x28, 0xf2, 0xf3, 0x29, 0xfe, 0x14, 0xa4, 0x14, 0x9a, 0x3e, 0xa7, 0x76, 0x09, 0xbc, 0x42, 0xb9, 0x75, 0xdd, 0xfa }, { 0xa3, 0x2f, 0x24, 0x14, 0x74, 0xa6, 0xc1, 0x69, 0x32, 0xe9, 0x24, 0x3b, 0xe0, 0xcf, 0x09, 0xbc, 0xdc, 0x7e, 0x0c, 0xa0, 0xe7, 0xa6, 0xa1, 0xb9, 0xb1, 0xa0, 0xf0, 0x1e, 0x41, 0x50, 0x23, 0x77 }, { 0xb2, 0x39, 0xb2, 0xe4, 0xf8, 0x18, 0x41, 0x36, 0x1c, 0x13, 0x39, 0xf6, 0x8e, 0x2c, 0x35, 0x9f, 0x92, 0x9a, 0xf9, 0xad, 0x9f, 0x34, 0xe0, 0x1a, 0xab, 0x46, 0x31, 0xad, 0x6d, 0x55, 0x00, 0xb0 }, { 0x85, 0xfb, 0x41, 0x9c, 0x70, 0x02, 0xa3, 0xe0, 0xb4, 0xb6, 0xea, 0x09, 0x3b, 0x4c, 0x1a, 0xc6, 0x93, 0x66, 0x45, 0xb6, 0x5d, 0xac, 0x5a, 0xc1, 0x5a, 0x85, 0x28, 0xb7, 0xb9, 0x4c, 0x17, 0x54 }, { 0x96, 0x19, 0x72, 0x06, 0x25, 0xf1, 0x90, 0xb9, 0x3a, 0x3f, 0xad, 0x18, 0x6a, 0xb3, 0x14, 0x18, 0x96, 0x33, 0xc0, 0xd3, 0xa0, 0x1e, 0x6f, 0x9b, 0xc8, 0xc4, 0xa8, 0xf8, 0x2f, 0x38, 0x3d, 0xbf }, { 0x7d, 0x62, 0x0d, 0x90, 0xfe, 0x69, 0xfa, 0x46, 0x9a, 0x65, 0x38, 0x38, 0x89, 0x70, 0xa1, 0xaa, 0x09, 0xbb, 0x48, 0xa2, 0xd5, 0x9b, 0x34, 0x7b, 0x97, 0xe8, 0xce, 0x71, 0xf4, 0x8c, 0x7f, 0x46 }, { 0x29, 0x43, 0x83, 0x56, 0x85, 0x96, 0xfb, 0x37, 0xc7, 0x5b, 0xba, 0xcd, 0x97, 0x9c, 0x5f, 0xf6, 0xf2, 0x0a, 0x55, 0x6b, 0xf8, 0x87, 0x9c, 0xc7, 0x29, 0x24, 0x85, 0x5d, 0xf9, 0xb8, 0x24, 0x0e }, { 0x16, 0xb1, 0x8a, 0xb3, 0x14, 0x35, 0x9c, 0x2b, 0x83, 0x3c, 0x1c, 0x69, 0x86, 0xd4, 0x8c, 0x55, 0xa9, 0xfc, 0x97, 0xcd, 0xe9, 0xa3, 0xc1, 0xf1, 0x0a, 0x31, 0x77, 0x14, 0x0f, 0x73, 0xf7, 0x38 }, { 0x8c, 0xbb, 0xdd, 0x14, 0xbc, 0x33, 0xf0, 0x4c, 0xf4, 0x58, 0x13, 0xe4, 0xa1, 0x53, 0xa2, 0x73, 0xd3, 0x6a, 0xda, 0xd5, 0xce, 0x71, 0xf4, 0x99, 0xee, 0xb8, 0x7f, 0xb8, 0xac, 0x63, 0xb7, 0x29 }, { 0x69, 0xc9, 0xa4, 0x98, 0xdb, 0x17, 0x4e, 0xca, 0xef, 0xcc, 0x5a, 0x3a, 0xc9, 0xfd, 0xed, 0xf0, 0xf8, 0x13, 0xa5, 0xbe, 0xc7, 0x27, 0xf1, 0xe7, 0x75, 0xba, 0xbd, 0xec, 0x77, 0x18, 0x81, 0x6e }, { 0xb4, 0x62, 0xc3, 0xbe, 0x40, 0x44, 0x8f, 0x1d, 0x4f, 0x80, 0x62, 0x62, 0x54, 0xe5, 0x35, 0xb0, 0x8b, 0xc9, 0xcd, 0xcf, 0xf5, 0x99, 0xa7, 0x68, 0x57, 0x8d, 0x4b, 0x28, 0x81, 0xa8, 0xe3, 0xf0 }, { 0x55, 0x3e, 0x9d, 0x9c, 0x5f, 0x36, 0x0a, 0xc0, 0xb7, 0x4a, 0x7d, 0x44, 0xe5, 0xa3, 0x91, 0xda, 0xd4, 0xce, 0xd0, 0x3e, 0x0c, 0x24, 0x18, 0x3b, 0x7e, 0x8e, 0xca, 0xbd, 0xf1, 0x71, 0x5a, 0x64 }, { 0x7a, 0x7c, 0x55, 0xa5, 0x6f, 0xa9, 0xae, 0x51, 0xe6, 0x55, 0xe0, 0x19, 0x75, 0xd8, 0xa6, 0xff, 0x4a, 0xe9, 0xe4, 0xb4, 0x86, 0xfc, 0xbe, 0x4e, 0xac, 0x04, 0x45, 0x88, 0xf2, 0x45, 0xeb, 0xea }, { 0x2a, 0xfd, 0xf3, 0xc8, 0x2a, 0xbc, 0x48, 0x67, 0xf5, 0xde, 0x11, 0x12, 0x86, 0xc2, 0xb3, 0xbe, 0x7d, 0x6e, 0x48, 0x65, 0x7b, 0xa9, 0x23, 0xcf, 0xbf, 0x10, 0x1a, 0x6d, 0xfc, 0xf9, 0xdb, 0x9a }, { 0x41, 0x03, 0x7d, 0x2e, 0xdc, 0xdc, 0xe0, 0xc4, 0x9b, 0x7f, 0xb4, 0xa6, 0xaa, 0x09, 0x99, 0xca, 0x66, 0x97, 0x6c, 0x74, 0x83, 0xaf, 0xe6, 0x31, 0xd4, 0xed, 0xa2, 0x83, 0x14, 0x4f, 0x6d, 0xfc }, { 0xc4, 0x46, 0x6f, 0x84, 0x97, 0xca, 0x2e, 0xeb, 0x45, 0x83, 0xa0, 0xb0, 0x8e, 0x9d, 0x9a, 0xc7, 0x43, 0x95, 0x70, 0x9f, 0xda, 0x10, 0x9d, 0x24, 0xf2, 0xe4, 0x46, 0x21, 0x96, 0x77, 0x9c, 0x5d }, { 0x75, 0xf6, 0x09, 0x33, 0x8a, 0xa6, 0x7d, 0x96, 0x9a, 0x2a, 0xe2, 0xa2, 0x36, 0x2b, 0x2d, 0xa9, 0xd7, 0x7c, 0x69, 0x5d, 0xfd, 0x1d, 0xf7, 0x22, 0x4a, 0x69, 0x01, 0xdb, 0x93, 0x2c, 0x33, 0x64 }, { 0x68, 0x60, 0x6c, 0xeb, 0x98, 0x9d, 0x54, 0x88, 0xfc, 0x7c, 0xf6, 0x49, 0xf3, 0xd7, 0xc2, 0x72, 0xef, 0x05, 0x5d, 0xa1, 0xa9, 0x3f, 0xae, 0xcd, 0x55, 0xfe, 0x06, 0xf6, 0x96, 0x70, 0x98, 0xca }, { 0x44, 0x34, 0x6b, 0xde, 0xb7, 0xe0, 0x52, 0xf6, 0x25, 0x50, 0x48, 0xf0, 0xd9, 0xb4, 0x2c, 0x42, 0x5b, 0xab, 0x9c, 0x3d, 0xd2, 0x41, 0x68, 0x21, 0x2c, 0x3e, 0xcf, 0x1e, 0xbf, 0x34, 0xe6, 0xae }, { 0x8e, 0x9c, 0xf6, 0xe1, 0xf3, 0x66, 0x47, 0x1f, 0x2a, 0xc7, 0xd2, 0xee, 0x9b, 0x5e, 0x62, 0x66, 0xfd, 0xa7, 0x1f, 0x8f, 0x2e, 0x41, 0x09, 0xf2, 0x23, 0x7e, 0xd5, 0xf8, 0x81, 0x3f, 0xc7, 0x18 }, { 0x84, 0xbb, 0xeb, 0x84, 0x06, 0xd2, 0x50, 0x95, 0x1f, 0x8c, 0x1b, 0x3e, 0x86, 0xa7, 0xc0, 0x10, 0x08, 0x29, 0x21, 0x83, 0x3d, 0xfd, 0x95, 0x55, 0xa2, 0xf9, 0x09, 0xb1, 0x08, 0x6e, 0xb4, 0xb8 }, { 0xee, 0x66, 0x6f, 0x3e, 0xef, 0x0f, 0x7e, 0x2a, 0x9c, 0x22, 0x29, 0x58, 0xc9, 0x7e, 0xaf, 0x35, 0xf5, 0x1c, 0xed, 0x39, 0x3d, 0x71, 0x44, 0x85, 0xab, 0x09, 0xa0, 0x69, 0x34, 0x0f, 0xdf, 0x88 }, { 0xc1, 0x53, 0xd3, 0x4a, 0x65, 0xc4, 0x7b, 0x4a, 0x62, 0xc5, 0xca, 0xcf, 0x24, 0x01, 0x09, 0x75, 0xd0, 0x35, 0x6b, 0x2f, 0x32, 0xc8, 0xf5, 0xda, 0x53, 0x0d, 0x33, 0x88, 0x16, 0xad, 0x5d, 0xe6 }, { 0x9f, 0xc5, 0x45, 0x01, 0x09, 0xe1, 0xb7, 0x79, 0xf6, 0xc7, 0xae, 0x79, 0xd5, 0x6c, 0x27, 0x63, 0x5c, 0x8d, 0xd4, 0x26, 0xc5, 0xa9, 0xd5, 0x4e, 0x25, 0x78, 0xdb, 0x98, 0x9b, 0x8c, 0x3b, 0x4e }, { 0xd1, 0x2b, 0xf3, 0x73, 0x2e, 0xf4, 0xaf, 0x5c, 0x22, 0xfa, 0x90, 0x35, 0x6a, 0xf8, 0xfc, 0x50, 0xfc, 0xb4, 0x0f, 0x8f, 0x2e, 0xa5, 0xc8, 0x59, 0x47, 0x37, 0xa3, 0xb3, 0xd5, 0xab, 0xdb, 0xd7 }, { 0x11, 0x03, 0x0b, 0x92, 0x89, 0xbb, 0xa5, 0xaf, 0x65, 0x26, 0x06, 0x72, 0xab, 0x6f, 0xee, 0x88, 0xb8, 0x74, 0x20, 0xac, 0xef, 0x4a, 0x17, 0x89, 0xa2, 0x07, 0x3b, 0x7e, 0xc2, 0xf2, 0xa0, 0x9e }, { 0x69, 0xcb, 0x19, 0x2b, 0x84, 0x44, 0x00, 0x5c, 0x8c, 0x0c, 0xeb, 0x12, 0xc8, 0x46, 0x86, 0x07, 0x68, 0x18, 0x8c, 0xda, 0x0a, 0xec, 0x27, 0xa9, 0xc8, 0xa5, 0x5c, 0xde, 0xe2, 0x12, 0x36, 0x32 }, { 0xdb, 0x44, 0x4c, 0x15, 0x59, 0x7b, 0x5f, 0x1a, 0x03, 0xd1, 0xf9, 0xed, 0xd1, 0x6e, 0x4a, 0x9f, 0x43, 0xa6, 0x67, 0xcc, 0x27, 0x51, 0x75, 0xdf, 0xa2, 0xb7, 0x04, 0xe3, 0xbb, 0x1a, 0x9b, 0x83 }, { 0x3f, 0xb7, 0x35, 0x06, 0x1a, 0xbc, 0x51, 0x9d, 0xfe, 0x97, 0x9e, 0x54, 0xc1, 0xee, 0x5b, 0xfa, 0xd0, 0xa9, 0xd8, 0x58, 0xb3, 0x31, 0x5b, 0xad, 0x34, 0xbd, 0xe9, 0x99, 0xef, 0xd7, 0x24, 0xdd }, }; unsigned char inp[1000], out[1000]; unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; unsigned long ilen, klen = sizeof(key), mlen = 32; blake2smac_state st; for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; for (ilen = 0; ilen < 256; ilen++) { const unsigned char *mac = tests[ilen]; unsigned long olen = mlen; /* process piece by piece */ if (ilen > 15) { blake2smac_init(&st, olen, key, klen); blake2smac_process(&st, (unsigned char*)inp, 5); blake2smac_process(&st, (unsigned char*)inp + 5, 4); blake2smac_process(&st, (unsigned char*)inp + 9, 3); blake2smac_process(&st, (unsigned char*)inp + 12, 2); blake2smac_process(&st, (unsigned char*)inp + 14, 1); blake2smac_process(&st, (unsigned char*)inp + 15, ilen - 15); blake2smac_done(&st, out, &olen); if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; } /* process in one go */ blake2smac_init(&st, olen, key, klen); blake2smac_process(&st, (unsigned char*)inp, ilen); blake2smac_done(&st, out, &olen); if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/000077500000000000000000000000001464416617300212625ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_done.c000066400000000000000000000031621464416617300227530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f9_done.c f9 Support, terminate the state */ #ifdef LTC_F9_MODE /** Terminate the f9-MAC state @param f9 f9 state to terminate @param out [out] Destination for the MAC tag @param outlen [in/out] Destination size and final tag size Return CRYPT_OK on success */ int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen) { int err, x; LTC_ARGCHK(f9 != NULL); LTC_ARGCHK(out != NULL); /* check structure */ if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { return err; } if ((f9->blocksize > cipher_descriptor[f9->cipher]->block_length) || (f9->blocksize < 0) || (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { return CRYPT_INVALID_ARG; } if (f9->buflen != 0) { /* encrypt */ cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key); f9->buflen = 0; for (x = 0; x < f9->blocksize; x++) { f9->ACC[x] ^= f9->IV[x]; } } /* schedule modified key */ if ((err = cipher_descriptor[f9->cipher]->setup(f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) { return err; } /* encrypt the ACC */ cipher_descriptor[f9->cipher]->ecb_encrypt(f9->ACC, f9->ACC, &f9->key); cipher_descriptor[f9->cipher]->done(&f9->key); /* extract tag */ for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) { out[x] = f9->ACC[x]; } *outlen = x; #ifdef LTC_CLEAN_STACK zeromem(f9, sizeof(*f9)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_file.c000066400000000000000000000040501464416617300227420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f9_file.c f9 support, process a file, Tom St Denis */ #ifdef LTC_F9_MODE /** f9 a file @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param fname The name of the file you wish to f9 @param out [out] Where the authentication tag is to be stored @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int f9_file(int cipher, const unsigned char *key, unsigned long keylen, const char *fname, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(cipher); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(fname); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; int err; f9_state f9; FILE *in; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(fname != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(fname, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = f9_done(&f9, out, outlen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&f9, sizeof(f9_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_init.c000066400000000000000000000025631464416617300227750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f9_init.c F9 Support, start an F9 state */ #ifdef LTC_F9_MODE /** Initialize F9-MAC state @param f9 [out] f9 state to initialize @param cipher Index of cipher to use @param key [in] Secret key @param keylen Length of secret key in octets Return CRYPT_OK on success */ int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen) { int x, err; LTC_ARGCHK(f9 != NULL); LTC_ARGCHK(key != NULL); /* schedule the key */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } #ifdef LTC_FAST if (cipher_descriptor[cipher]->block_length % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &f9->key)) != CRYPT_OK) { goto done; } /* make the second key */ for (x = 0; (unsigned)x < keylen; x++) { f9->akey[x] = key[x] ^ 0xAA; } /* setup struct */ zeromem(f9->IV, cipher_descriptor[cipher]->block_length); zeromem(f9->ACC, cipher_descriptor[cipher]->block_length); f9->blocksize = cipher_descriptor[cipher]->block_length; f9->cipher = cipher; f9->buflen = 0; f9->keylen = keylen; done: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_memory.c000066400000000000000000000027231464416617300233400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f9_process.c f9 Support, Process a block through F9-MAC */ #ifdef LTC_F9_MODE /** f9-MAC a block of memory @param cipher Index of cipher to use @param key [in] Secret key @param keylen Length of key in octets @param in [in] Message to MAC @param inlen Length of input in octets @param out [out] Destination for the MAC tag @param outlen [in/out] Output size and final tag size Return CRYPT_OK on success. */ int f9_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { f9_state *f9; int err; /* is the cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* Use accelerator if found */ if (cipher_descriptor[cipher]->f9_memory != NULL) { return cipher_descriptor[cipher]->f9_memory(key, keylen, in, inlen, out, outlen); } f9 = XCALLOC(1, sizeof(*f9)); if (f9 == NULL) { return CRYPT_MEM; } if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { goto done; } if ((err = f9_process(f9, in, inlen)) != CRYPT_OK) { goto done; } err = f9_done(f9, out, outlen); done: XFREE(f9); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_memory_multi.c000066400000000000000000000042261464416617300245520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file f9_memory_multi.c f9 support, process multiple blocks of memory, Tom St Denis */ #ifdef LTC_F9_MODE /** f9 multiple blocks of memory @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param out [out] The destination of the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag (octets) @param in The data to send through f9 @param inlen The length of the data to send through f9 (octets) @param ... tuples of (data,len) pairs to f9, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int f9_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { int err; f9_state *f9; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for f9 state */ f9 = XMALLOC(sizeof(f9_state)); if (f9 == NULL) { return CRYPT_MEM; } /* f9 process the message */ if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = f9_process(f9, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } if ((err = f9_done(f9, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(f9, sizeof(f9_state)); #endif XFREE(f9); va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_process.c000066400000000000000000000034631464416617300235100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f9_process.c f9 Support, process blocks with f9 */ #ifdef LTC_F9_MODE /** Process data through f9-MAC @param f9 The f9-MAC state @param in Input data to process @param inlen Length of input in octets Return CRYPT_OK on success */ int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen) { int err, x; LTC_ARGCHK(f9 != NULL); LTC_ARGCHK(in != NULL); /* check structure */ if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { return err; } if ((f9->blocksize > cipher_descriptor[f9->cipher]->block_length) || (f9->blocksize < 0) || (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (f9->buflen == 0) { while (inlen >= (unsigned long)f9->blocksize) { for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); } cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key); for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&(f9->ACC[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))); } in += f9->blocksize; inlen -= f9->blocksize; } } #endif while (inlen) { if (f9->buflen == f9->blocksize) { cipher_descriptor[f9->cipher]->ecb_encrypt(f9->IV, f9->IV, &f9->key); for (x = 0; x < f9->blocksize; x++) { f9->ACC[x] ^= f9->IV[x]; } f9->buflen = 0; } f9->IV[f9->buflen++] ^= *in++; --inlen; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/f9/f9_test.c000066400000000000000000000037711464416617300230130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f9_test.c f9 Support, Test F9 mode */ #ifdef LTC_F9_MODE /** Test f9-MAC mode Return CRYPT_OK on success */ int f9_test(void) { #ifdef LTC_NO_TEST return CRYPT_NOP; #else static const struct { int msglen; unsigned char K[16], M[128], T[4]; } tests[] = { { 20, { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }, { 0x38, 0xA6, 0xF0, 0x56, 0xB8, 0xAE, 0xFD, 0xA9, 0x33, 0x32, 0x34, 0x62, 0x63, 0x39, 0x38, 0x61, 0x37, 0x34, 0x79, 0x40 }, { 0x46, 0xE0, 0x0D, 0x4B } }, { 105, { 0x83, 0xFD, 0x23, 0xA2, 0x44, 0xA7, 0x4C, 0xF3, 0x58, 0xDA, 0x30, 0x19, 0xF1, 0x72, 0x26, 0x35 }, { 0x36, 0xAF, 0x61, 0x44, 0x4F, 0x30, 0x2A, 0xD2, 0x35, 0xC6, 0x87, 0x16, 0x63, 0x3C, 0x66, 0xFB, 0x75, 0x0C, 0x26, 0x68, 0x65, 0xD5, 0x3C, 0x11, 0xEA, 0x05, 0xB1, 0xE9, 0xFA, 0x49, 0xC8, 0x39, 0x8D, 0x48, 0xE1, 0xEF, 0xA5, 0x90, 0x9D, 0x39, 0x47, 0x90, 0x28, 0x37, 0xF5, 0xAE, 0x96, 0xD5, 0xA0, 0x5B, 0xC8, 0xD6, 0x1C, 0xA8, 0xDB, 0xEF, 0x1B, 0x13, 0xA4, 0xB4, 0xAB, 0xFE, 0x4F, 0xB1, 0x00, 0x60, 0x45, 0xB6, 0x74, 0xBB, 0x54, 0x72, 0x93, 0x04, 0xC3, 0x82, 0xBE, 0x53, 0xA5, 0xAF, 0x05, 0x55, 0x61, 0x76, 0xF6, 0xEA, 0xA2, 0xEF, 0x1D, 0x05, 0xE4, 0xB0, 0x83, 0x18, 0x1E, 0xE6, 0x74, 0xCD, 0xA5, 0xA4, 0x85, 0xF7, 0x4D, 0x7A, 0x40|0x80 }, { 0x95, 0xAE, 0x41, 0xBA }, } }; unsigned char T[16]; unsigned long taglen; int err, x, idx; /* find kasumi */ if ((idx = find_cipher("kasumi")) == -1) { return CRYPT_NOP; } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { taglen = 4; if ((err = f9_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { return err; } if (compare_testvector(T, taglen, tests[x].T, 4, "F9", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/000077500000000000000000000000001464416617300216545ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_done.c000066400000000000000000000046251464416617300237440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hmac_done.c HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer */ #ifdef LTC_HMAC #define LTC_HMAC_BLOCKSIZE hash_descriptor[hash]->blocksize /** Terminate an HMAC session @param hmac The HMAC state @param out [out] The destination of the HMAC authentication tag @param outlen [in/out] The max size and resulting size of the HMAC authentication tag @return CRYPT_OK if successful */ int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) { unsigned char *buf, *isha; unsigned long hashsize, i; int hash, err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(out != NULL); /* test hash */ hash = hmac->hash; if((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* get the hash message digest size */ hashsize = hash_descriptor[hash]->hashsize; /* allocate buffers */ buf = XMALLOC(LTC_HMAC_BLOCKSIZE); isha = XMALLOC(hashsize); if (buf == NULL || isha == NULL) { if (buf != NULL) { XFREE(buf); } if (isha != NULL) { XFREE(isha); } return CRYPT_MEM; } /* Get the hash of the first HMAC vector plus the data */ if ((err = hash_descriptor[hash]->done(&hmac->md, isha)) != CRYPT_OK) { goto LBL_ERR; } /* Create the second HMAC vector vector for step (3) */ for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { buf[i] = hmac->key[i] ^ 0x5C; } /* Now calculate the "outer" hash for step (5), (6), and (7) */ if ((err = hash_descriptor[hash]->init(&hmac->md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash]->process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash]->process(&hmac->md, isha, hashsize)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash]->done(&hmac->md, buf)) != CRYPT_OK) { goto LBL_ERR; } /* copy to output */ for (i = 0; i < hashsize && i < *outlen; i++) { out[i] = buf[i]; } *outlen = i; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(isha, hashsize); zeromem(buf, hashsize); zeromem(hmac, sizeof(*hmac)); #endif XFREE(isha); XFREE(buf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_file.c000066400000000000000000000042711464416617300237330ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hmac_file.c HMAC support, process a file, Tom St Denis/Dobes Vandermeer */ #ifdef LTC_HMAC /** HMAC a file @param hash The index of the hash you wish to use @param fname The name of the file you wish to HMAC @param key The secret key @param keylen The length of the secret key @param out [out] The HMAC authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int hmac_file(int hash, const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(hash); LTC_UNUSED_PARAM(fname); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else hmac_state hmac; FILE *in; unsigned char *buf; size_t x; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = hash_is_valid(hash)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(fname, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); /* we don't trap this error since we're already returning an error! */ goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = hmac_done(&hmac, out, outlen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&hmac, sizeof(hmac_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_init.c000066400000000000000000000044311464416617300237550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hmac_init.c HMAC support, initialize state, Tom St Denis/Dobes Vandermeer */ #ifdef LTC_HMAC #define LTC_HMAC_BLOCKSIZE hash_descriptor[hash]->blocksize /** Initialize an HMAC context. @param hmac The HMAC state @param hash The index of the hash you want to use @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) { unsigned char *buf; unsigned long hashsize; unsigned long i, z; int err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(key != NULL); /* valid hash? */ if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } hmac->hash = hash; hashsize = hash_descriptor[hash]->hashsize; /* valid key length? */ if (keylen == 0) { return CRYPT_INVALID_KEYSIZE; } /* allocate ram for buf */ buf = XMALLOC(LTC_HMAC_BLOCKSIZE); if (buf == NULL) { return CRYPT_MEM; } /* check hash block fits */ if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* (1) make sure we have a large enough key */ if(keylen > LTC_HMAC_BLOCKSIZE) { z = LTC_HMAC_BLOCKSIZE; if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { goto LBL_ERR; } keylen = hashsize; } else { XMEMCPY(hmac->key, key, (size_t)keylen); } if(keylen < LTC_HMAC_BLOCKSIZE) { zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen)); } /* Create the initialization vector for step (3) */ for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { buf[i] = hmac->key[i] ^ 0x36; } /* Pre-pend that to the hash data */ if ((err = hash_descriptor[hash]->init(&hmac->md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash]->process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, LTC_HMAC_BLOCKSIZE); #endif XFREE(buf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_memory.c000066400000000000000000000037511464416617300243260ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hmac_memory.c HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer */ #ifdef LTC_HMAC /** HMAC a block of memory to produce the authentication tag @param hash The index of the hash to use @param key The secret key @param keylen The length of the secret key (octets) @param in The data to HMAC @param inlen The length of the data to HMAC (octets) @param out [out] Destination of the authentication tag @param outlen [in/out] Max size and resulting size of authentication tag @return CRYPT_OK if successful */ int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { hmac_state *hmac; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* is there a descriptor? */ if (hash_descriptor[hash]->hmac_block != NULL) { return hash_descriptor[hash]->hmac_block(key, keylen, in, inlen, out, outlen); } /* nope, so call the hmac functions */ /* allocate ram for hmac state */ hmac = XMALLOC(sizeof(hmac_state)); if (hmac == NULL) { return CRYPT_MEM; } if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(hmac, sizeof(hmac_state)); #endif XFREE(hmac); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_memory_multi.c000066400000000000000000000043041464416617300255330ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file hmac_memory_multi.c HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer */ #ifdef LTC_HMAC /** HMAC multiple blocks of memory to produce the authentication tag @param hash The index of the hash to use @param key The secret key @param keylen The length of the secret key (octets) @param out [out] Destination of the authentication tag @param outlen [in/out] Max size and resulting size of authentication tag @param in The data to HMAC @param inlen The length of the data to HMAC (octets) @param ... tuples of (data,len) pairs to HMAC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int hmac_memory_multi(int hash, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { hmac_state *hmac; int err; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for hmac state */ hmac = XMALLOC(sizeof(hmac_state)); if (hmac == NULL) { return CRYPT_MEM; } if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(hmac, sizeof(hmac_state)); #endif XFREE(hmac); va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_process.c000066400000000000000000000014001464416617300244610ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hmac_process.c HMAC support, process data, Tom St Denis/Dobes Vandermeer */ #ifdef LTC_HMAC /** Process data through HMAC @param hmac The hmac state @param in The data to send through HMAC @param inlen The length of the data to HMAC (octets) @return CRYPT_OK if successful */ int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) { int err; LTC_ARGCHK(hmac != NULL); LTC_ARGCHK(in != NULL); if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { return err; } return hash_descriptor[hmac->hash]->process(&hmac->md, in, inlen); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/hmac/hmac_test.c000066400000000000000000000604201464416617300237710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hmac_test.c HMAC support, self-test, Tom St Denis/Dobes Vandermeer/Steffen Jaeckel */ #ifdef LTC_HMAC /* TEST CASES SOURCE: Network Working Group P. Cheng Request for Comments: 2202 IBM Category: Informational R. Glenn NIST September 1997 Test Cases for HMAC-MD5 and HMAC-SHA-1 ******************************************************************************* Network Working Group J. Kapp Request for Comments: 2286 Reaper Technologies Category: Informational February 1998 Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128 ******************************************************************************* Network Working Group M. Nystrom Request for Comments: 4231 RSA Security Category: Standards Track December 2005 Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 */ /** HMAC self-test @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. */ int hmac_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char digest[MAXBLOCKSIZE]; int i; static const unsigned char hmac_test_case_keys[][136] = { { /* 1 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }, #ifdef LTC_TEST_EXT { /* 2 */ 0x4a, 0x65, 0x66, 0x65 }, { /* 4 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }, { /* 5 */ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, { /* 3, 6, 7 */ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa } #endif /* LTC_TEST_EXT */ }; static const unsigned char hmac_test_case_data[][153] = { { "Hi There" }, #ifdef LTC_TEST_EXT { "what do ya want for nothing?" }, { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }, { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd }, { "Test With Truncation" }, { "Test Using Larger Than Block-Size Key - Hash Key First" }, { "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" }, { "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." } #endif /* LTC_TEST_EXT */ }; static const struct hmac_test_case { const char *num; const char *algo; const unsigned char *key; unsigned long keylen; const unsigned char *data; unsigned long datalen; unsigned char digest[MAXBLOCKSIZE]; } cases[] = { /* RFC 2202 3. Test Cases for HMAC-SHA-1 */ { "rfc2202 3.1", "sha1", hmac_test_case_keys[0], 20, hmac_test_case_data[0], 8, {0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00} }, #ifdef LTC_TEST_EXT { "rfc2202 3.2", "sha1", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79} }, { "rfc2202 3.3", "sha1", hmac_test_case_keys[4], 20, hmac_test_case_data[2], 50, {0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3} }, { "rfc2202 3.4", "sha1", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda} }, { "rfc2202 3.5", "sha1", hmac_test_case_keys[3], 20, hmac_test_case_data[4], 20, {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, { "rfc2202 3.6", "sha1", hmac_test_case_keys[4], 80, hmac_test_case_data[5], 54, {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12} }, { "rfc2202 3.7", "sha1", hmac_test_case_keys[4], 80, hmac_test_case_data[6], 73, {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, #endif /* LTC_TEST_EXT */ /* RFC 2202 2. Test Cases for HMAC-MD5 */ { "rfc2202 2.1", "md5", hmac_test_case_keys[0], 16, hmac_test_case_data[0], 8, {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, #ifdef LTC_TEST_EXT { "rfc2202 2.2", "md5", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, { "rfc2202 2.3", "md5", hmac_test_case_keys[4], 16, hmac_test_case_data[2], 50, {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, { "rfc2202 2.4", "md5", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, { "rfc2202 2.5", "md5", hmac_test_case_keys[3], 16, hmac_test_case_data[4], 20, {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, { "rfc2202 2.6", "md5", hmac_test_case_keys[4], 80, hmac_test_case_data[5], 54, {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, { "rfc2202 2.7", "md5", hmac_test_case_keys[4], 80, hmac_test_case_data[6], 73, {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }, #endif /* LTC_TEST_EXT */ /* RFC 2286 2. Test Cases for HMAC-RIPEMD160 */ { "rfc2286 2.1", "rmd160", hmac_test_case_keys[0], 20, hmac_test_case_data[0], 8, {0x24, 0xcb, 0x4b, 0xd6, 0x7d, 0x20, 0xfc, 0x1a, 0x5d, 0x2e, 0xd7, 0x73, 0x2d, 0xcc, 0x39, 0x37, 0x7f, 0x0a, 0x56, 0x68} }, #ifdef LTC_TEST_EXT { "rfc2286 2.2", "rmd160", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0xdd, 0xa6, 0xc0, 0x21, 0x3a, 0x48, 0x5a, 0x9e, 0x24, 0xf4, 0x74, 0x20, 0x64, 0xa7, 0xf0, 0x33, 0xb4, 0x3c, 0x40, 0x69} }, { "rfc2286 2.3", "rmd160", hmac_test_case_keys[4], 20, hmac_test_case_data[2], 50, {0xb0, 0xb1, 0x05, 0x36, 0x0d, 0xe7, 0x59, 0x96, 0x0a, 0xb4, 0xf3, 0x52, 0x98, 0xe1, 0x16, 0xe2, 0x95, 0xd8, 0xe7, 0xc1} }, { "rfc2286 2.4", "rmd160", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0xd5, 0xca, 0x86, 0x2f, 0x4d, 0x21, 0xd5, 0xe6, 0x10, 0xe1, 0x8b, 0x4c, 0xf1, 0xbe, 0xb9, 0x7a, 0x43, 0x65, 0xec, 0xf4} }, { "rfc2286 2.5", "rmd160", hmac_test_case_keys[3], 20, hmac_test_case_data[4], 20, {0x76, 0x19, 0x69, 0x39, 0x78, 0xf9, 0x1d, 0x90, 0x53, 0x9a, 0xe7, 0x86, 0x50, 0x0f, 0xf3, 0xd8, 0xe0, 0x51, 0x8e, 0x39} }, { "rfc2286 2.6", "rmd160", hmac_test_case_keys[4], 80, hmac_test_case_data[5], 54, {0x64, 0x66, 0xca, 0x07, 0xac, 0x5e, 0xac, 0x29, 0xe1, 0xbd, 0x52, 0x3e, 0x5a, 0xda, 0x76, 0x05, 0xb7, 0x91, 0xfd, 0x8b} }, { "rfc2286 2.7", "rmd160", hmac_test_case_keys[4], 80, hmac_test_case_data[6], 73, {0x69, 0xea, 0x60, 0x79, 0x8d, 0x71, 0x61, 0x6c, 0xce, 0x5f, 0xd0, 0x87, 0x1e, 0x23, 0x75, 0x4c, 0xd7, 0x5d, 0x5a, 0x0a} }, #endif /* LTC_TEST_EXT */ /* RFC 2286 3. Test Cases for HMAC-RIPEMD128 */ { "rfc2286 3.1", "rmd128", hmac_test_case_keys[0], 16, hmac_test_case_data[0], 8, {0xfb, 0xf6, 0x1f, 0x94, 0x92, 0xaa, 0x4b, 0xbf, 0x81, 0xc1, 0x72, 0xe8, 0x4e, 0x07, 0x34, 0xdb} }, #ifdef LTC_TEST_EXT { "rfc2286 3.2", "rmd128", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0x87, 0x5f, 0x82, 0x88, 0x62, 0xb6, 0xb3, 0x34, 0xb4, 0x27, 0xc5, 0x5f, 0x9f, 0x7f, 0xf0, 0x9b} }, { "rfc2286 3.3", "rmd128", hmac_test_case_keys[4], 16, hmac_test_case_data[2], 50, {0x09, 0xf0, 0xb2, 0x84, 0x6d, 0x2f, 0x54, 0x3d, 0xa3, 0x63, 0xcb, 0xec, 0x8d, 0x62, 0xa3, 0x8d} }, { "rfc2286 3.4", "rmd128", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0xbd, 0xbb, 0xd7, 0xcf, 0x03, 0xe4, 0x4b, 0x5a, 0xa6, 0x0a, 0xf8, 0x15, 0xbe, 0x4d, 0x22, 0x94} }, { "rfc2286 3.5", "rmd128", hmac_test_case_keys[3], 16, hmac_test_case_data[4], 20, {0xe7, 0x98, 0x08, 0xf2, 0x4b, 0x25, 0xfd, 0x03, 0x1c, 0x15, 0x5f, 0x0d, 0x55, 0x1d, 0x9a, 0x3a} }, { "rfc2286 3.6", "rmd128", hmac_test_case_keys[4], 80, hmac_test_case_data[5], 54, {0xdc, 0x73, 0x29, 0x28, 0xde, 0x98, 0x10, 0x4a, 0x1f, 0x59, 0xd3, 0x73, 0xc1, 0x50, 0xac, 0xbb} }, { "rfc2286 3.7", "rmd128", hmac_test_case_keys[4], 80, hmac_test_case_data[6], 73, {0x5c, 0x6b, 0xec, 0x96, 0x79, 0x3e, 0x16, 0xd4, 0x06, 0x90, 0xc2, 0x37, 0x63, 0x5f, 0x30, 0xc5} }, #endif /* LTC_TEST_EXT */ /* RFC 4231 4. Test Vectors Ch. 4.6 with truncated output left out to simplify tests */ { "rfc4231 4.2", "sha224", hmac_test_case_keys[0], 20, hmac_test_case_data[0], 8, {0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22} }, #ifdef LTC_TEST_EXT { "rfc4231 4.3", "sha224", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44} }, { "rfc4231 4.4", "sha224", hmac_test_case_keys[4], 20, hmac_test_case_data[2], 50, {0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea} }, { "rfc4231 4.5", "sha224", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, 0xe7, 0xaf, 0xec, 0x5a} }, { "rfc4231 4.7", "sha224", hmac_test_case_keys[4], 131, hmac_test_case_data[5], 54, {0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e} }, { "rfc4231 4.8", "sha224", hmac_test_case_keys[4], 131, hmac_test_case_data[7], 152, {0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, 0xf6, 0xf5, 0x65, 0xd1} }, #endif /* LTC_TEST_EXT */ { "rfc4231 4.2", "sha256", hmac_test_case_keys[0], 20, hmac_test_case_data[0], 8, {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7} }, #ifdef LTC_TEST_EXT { "rfc4231 4.3", "sha256", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43} }, { "rfc4231 4.4", "sha256", hmac_test_case_keys[4], 20, hmac_test_case_data[2], 50, {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe} }, { "rfc4231 4.5", "sha256", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b} }, { "rfc4231 4.7", "sha256", hmac_test_case_keys[4], 131, hmac_test_case_data[5], 54, {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54} }, { "rfc4231 4.8", "sha256", hmac_test_case_keys[4], 131, hmac_test_case_data[7], 152, {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }, #endif /* LTC_TEST_EXT */ { "rfc4231 4.2", "sha384", hmac_test_case_keys[0], 20, hmac_test_case_data[0], 8, {0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6} }, #ifdef LTC_TEST_EXT { "rfc4231 4.3", "sha384", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49} }, { "rfc4231 4.4", "sha384", hmac_test_case_keys[4], 20, hmac_test_case_data[2], 50, {0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27} }, { "rfc4231 4.5", "sha384", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb} }, { "rfc4231 4.7", "sha384", hmac_test_case_keys[4], 131, hmac_test_case_data[5], 54, {0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52} }, { "rfc4231 4.8", "sha384", hmac_test_case_keys[4], 131, hmac_test_case_data[7], 152, {0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e} }, #endif /* LTC_TEST_EXT */ { "rfc4231 4.2", "sha512", hmac_test_case_keys[0], 20, hmac_test_case_data[0], 8, {0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54} }, #ifdef LTC_TEST_EXT { "rfc4231 4.3", "sha512", hmac_test_case_keys[1], 4, hmac_test_case_data[1], 28, {0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37} }, { "rfc4231 4.4", "sha512", hmac_test_case_keys[4], 20, hmac_test_case_data[2], 50, {0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb} }, { "rfc4231 4.5", "sha512", hmac_test_case_keys[2], 25, hmac_test_case_data[3], 50, {0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd} }, { "rfc4231 4.7", "sha512", hmac_test_case_keys[4], 131, hmac_test_case_data[5], 54, {0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98} }, { "rfc4231 4.8", "sha512", hmac_test_case_keys[4], 131, hmac_test_case_data[7], 152, {0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58} }, #endif /* LTC_TEST_EXT */ }; unsigned long outlen; int err; int tested=0,failed=0; for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { int hash = find_hash(cases[i].algo); if (hash == -1) continue; ++tested; outlen = sizeof(digest); if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) { #ifdef LTC_TEST_DBG printf("HMAC-%s test %s, %s\n", cases[i].algo, cases[i].num, error_to_string(err)); #endif return err; } if(compare_testvector(digest, outlen, cases[i].digest, (size_t)hash_descriptor[hash]->hashsize, cases[i].num, i)) { failed++; } } if (failed != 0) { return CRYPT_FAIL_TESTVECTOR; } if (tested == 0) { return CRYPT_NOP; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/000077500000000000000000000000001464416617300216635ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_done.c000066400000000000000000000035311464416617300237550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file omac_done.c OMAC1 support, terminate a stream, Tom St Denis */ #ifdef LTC_OMAC /** Terminate an OMAC stream @param omac The OMAC state @param out [out] Destination for the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful */ int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen) { int err, mode; unsigned x; LTC_ARGCHK(omac != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) { return err; } if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { return CRYPT_INVALID_ARG; } /* figure out mode */ if (omac->buflen != omac->blklen) { /* add the 0x80 byte */ omac->block[omac->buflen++] = 0x80; /* pad with 0x00 */ while (omac->buflen < omac->blklen) { omac->block[omac->buflen++] = 0x00; } mode = 1; } else { mode = 0; } /* now xor prev + Lu[mode] */ for (x = 0; x < (unsigned)omac->blklen; x++) { omac->block[x] ^= omac->prev[x] ^ omac->Lu[mode][x]; } /* encrypt it */ if ((err = cipher_descriptor[omac->cipher_idx]->ecb_encrypt(omac->block, omac->block, &omac->key)) != CRYPT_OK) { return err; } cipher_descriptor[omac->cipher_idx]->done(&omac->key); /* output it */ for (x = 0; x < (unsigned)omac->blklen && x < *outlen; x++) { out[x] = omac->block[x]; } *outlen = x; #ifdef LTC_CLEAN_STACK zeromem(omac, sizeof(*omac)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_file.c000066400000000000000000000041251464416617300237470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file omac_file.c OMAC1 support, process a file, Tom St Denis */ #ifdef LTC_OMAC /** OMAC a file @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param filename The name of the file you wish to OMAC @param out [out] Where the authentication tag is to be stored @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(cipher); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(filename); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; int err; omac_state omac; FILE *in; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(filename != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(filename, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = omac_process(&omac, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = omac_done(&omac, out, outlen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&omac, sizeof(omac_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_init.c000066400000000000000000000045561464416617300240030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file omac_init.c OMAC1 support, initialize state, by Tom St Denis */ #ifdef LTC_OMAC /** Initialize an OMAC state @param omac The OMAC state to initialize @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen) { int err, x, y, mask, msb, len; LTC_ARGCHK(omac != NULL); LTC_ARGCHK(key != NULL); /* schedule the key */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } #ifdef LTC_FAST if (cipher_descriptor[cipher]->block_length % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* now setup the system */ switch (cipher_descriptor[cipher]->block_length) { case 8: mask = 0x1B; len = 8; break; case 16: mask = 0x87; len = 16; break; default: return CRYPT_INVALID_ARG; } if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &omac->key)) != CRYPT_OK) { return err; } /* ok now we need Lu and Lu^2 [calc one from the other] */ /* first calc L which is Ek(0) */ zeromem(omac->Lu[0], cipher_descriptor[cipher]->block_length); if ((err = cipher_descriptor[cipher]->ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key)) != CRYPT_OK) { return err; } /* now do the mults, whoopy! */ for (x = 0; x < 2; x++) { /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ msb = omac->Lu[x][0] >> 7; /* shift left */ for (y = 0; y < (len - 1); y++) { omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255; } omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255; /* copy up as require */ if (x == 0) { XMEMCPY(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0])); } } /* setup state */ omac->cipher_idx = cipher; omac->buflen = 0; omac->blklen = len; zeromem(omac->prev, sizeof(omac->prev)); zeromem(omac->block, sizeof(omac->block)); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_memory.c000066400000000000000000000036741464416617300243500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file omac_memory.c OMAC1 support, process a block of memory, Tom St Denis */ #ifdef LTC_OMAC /** OMAC a block of memory @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param in The data to send through OMAC @param inlen The length of the data to send through OMAC (octets) @param out [out] The destination of the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag (octets) @return CRYPT_OK if successful */ int omac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { int err; omac_state *omac; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* is the cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* Use accelerator if found */ if (cipher_descriptor[cipher]->omac_memory != NULL) { return cipher_descriptor[cipher]->omac_memory(key, keylen, in, inlen, out, outlen); } /* allocate ram for omac state */ omac = XMALLOC(sizeof(omac_state)); if (omac == NULL) { return CRYPT_MEM; } /* omac process the message */ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(omac, sizeof(omac_state)); #endif XFREE(omac); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_memory_multi.c000066400000000000000000000043021464416617300255470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file omac_memory_multi.c OMAC1 support, process multiple blocks of memory, Tom St Denis */ #ifdef LTC_OMAC /** OMAC multiple blocks of memory @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param out [out] The destination of the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag (octets) @param in The data to send through OMAC @param inlen The length of the data to send through OMAC (octets) @param ... tuples of (data,len) pairs to OMAC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int omac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { int err; omac_state *omac; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for omac state */ omac = XMALLOC(sizeof(omac_state)); if (omac == NULL) { return CRYPT_MEM; } /* omac process the message */ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = omac_process(omac, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(omac, sizeof(omac_state)); #endif XFREE(omac); va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_process.c000066400000000000000000000043601464416617300245070ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file omac_process.c OMAC1 support, process data, Tom St Denis */ #ifdef LTC_OMAC /** Process data through OMAC @param omac The OMAC state @param in The input data to send through OMAC @param inlen The length of the input (octets) @return CRYPT_OK if successful */ int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) { unsigned long n, x; int err; LTC_ARGCHK(omac != NULL); LTC_ARGCHK(in != NULL); if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) { return err; } if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST { unsigned long blklen = cipher_descriptor[omac->cipher_idx]->block_length; if (omac->buflen == 0 && inlen > blklen) { unsigned long y; for (x = 0; x < (inlen - blklen); x += blklen) { for (y = 0; y < blklen; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&omac->prev[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&in[y])); } in += blklen; if ((err = cipher_descriptor[omac->cipher_idx]->ecb_encrypt(omac->prev, omac->prev, &omac->key)) != CRYPT_OK) { return err; } } inlen -= x; } } #endif while (inlen != 0) { /* ok if the block is full we xor in prev, encrypt and replace prev */ if (omac->buflen == omac->blklen) { for (x = 0; x < (unsigned long)omac->blklen; x++) { omac->block[x] ^= omac->prev[x]; } if ((err = cipher_descriptor[omac->cipher_idx]->ecb_encrypt(omac->block, omac->prev, &omac->key)) != CRYPT_OK) { return err; } omac->buflen = 0; } /* add bytes */ n = MIN(inlen, (unsigned long)(omac->blklen - omac->buflen)); XMEMCPY(omac->block + omac->buflen, in, n); omac->buflen += n; inlen -= n; in += n; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/omac/omac_test.c000066400000000000000000000060231464416617300240060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file omac_test.c OMAC1 support, self-test, by Tom St Denis */ #ifdef LTC_OMAC /** Test the OMAC setup @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled */ int omac_test(void) { #if !defined(LTC_TEST) return CRYPT_NOP; #else static const struct { int keylen, msglen; unsigned char key[16], msg[64], tag[16]; } tests[] = { { 16, 0, { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, { 0x00 }, { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } }, { 16, 16, { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } }, { 16, 40, { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } }, { 16, 64, { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } } }; unsigned char out[16]; int x, err, idx; unsigned long len; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { len = sizeof(out); if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) { return err; } if (compare_testvector(out, len, tests[x].tag, sizeof(tests[x].tag), "OMAC", x) != 0) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pelican/000077500000000000000000000000001464416617300223575ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pelican/pelican.c000066400000000000000000000074111464416617300241410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pelican.c Pelican MAC, initialize state, by Tom St Denis */ #ifdef LTC_PELICAN #define LTC_AES_TAB_C #define ENCRYPT_ONLY #define PELI_TAB #include "../../ciphers/aes/aes_tab.c" /** Initialize a Pelican state @param pelmac The Pelican state to initialize @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen) { int err; LTC_ARGCHK(pelmac != NULL); LTC_ARGCHK(key != NULL); #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif if ((err = aes_setup(key, keylen, 0, &pelmac->K)) != CRYPT_OK) { return err; } zeromem(pelmac->state, 16); aes_ecb_encrypt(pelmac->state, pelmac->state, &pelmac->K); pelmac->buflen = 0; return CRYPT_OK; } static void s_four_rounds(pelican_state *pelmac) { ulong32 s0, s1, s2, s3, t0, t1, t2, t3; int r; LOAD32H(s0, pelmac->state ); LOAD32H(s1, pelmac->state + 4); LOAD32H(s2, pelmac->state + 8); LOAD32H(s3, pelmac->state + 12); for (r = 0; r < 4; r++) { t0 = Te0(LTC_BYTE(s0, 3)) ^ Te1(LTC_BYTE(s1, 2)) ^ Te2(LTC_BYTE(s2, 1)) ^ Te3(LTC_BYTE(s3, 0)); t1 = Te0(LTC_BYTE(s1, 3)) ^ Te1(LTC_BYTE(s2, 2)) ^ Te2(LTC_BYTE(s3, 1)) ^ Te3(LTC_BYTE(s0, 0)); t2 = Te0(LTC_BYTE(s2, 3)) ^ Te1(LTC_BYTE(s3, 2)) ^ Te2(LTC_BYTE(s0, 1)) ^ Te3(LTC_BYTE(s1, 0)); t3 = Te0(LTC_BYTE(s3, 3)) ^ Te1(LTC_BYTE(s0, 2)) ^ Te2(LTC_BYTE(s1, 1)) ^ Te3(LTC_BYTE(s2, 0)); s0 = t0; s1 = t1; s2 = t2; s3 = t3; } STORE32H(s0, pelmac->state ); STORE32H(s1, pelmac->state + 4); STORE32H(s2, pelmac->state + 8); STORE32H(s3, pelmac->state + 12); } /** Process a block of text through Pelican @param pelmac The Pelican MAC state @param in The input @param inlen The length input (octets) @return CRYPT_OK on success */ int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen) { LTC_ARGCHK(pelmac != NULL); LTC_ARGCHK(in != NULL); /* check range */ if (pelmac->buflen < 0 || pelmac->buflen > 15) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (pelmac->buflen == 0) { while (inlen & ~15) { int x; for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pelmac->state + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)in + x)); } s_four_rounds(pelmac); in += 16; inlen -= 16; } } #endif while (inlen--) { pelmac->state[pelmac->buflen++] ^= *in++; if (pelmac->buflen == 16) { s_four_rounds(pelmac); pelmac->buflen = 0; } } return CRYPT_OK; } /** Terminate Pelican MAC @param pelmac The Pelican MAC state @param out [out] The TAG @return CRYPT_OK on sucess */ int pelican_done(pelican_state *pelmac, unsigned char *out) { LTC_ARGCHK(pelmac != NULL); LTC_ARGCHK(out != NULL); /* check range */ if (pelmac->buflen < 0 || pelmac->buflen > 16) { return CRYPT_INVALID_ARG; } if (pelmac->buflen == 16) { s_four_rounds(pelmac); pelmac->buflen = 0; } pelmac->state[pelmac->buflen++] ^= 0x80; aes_ecb_encrypt(pelmac->state, out, &pelmac->K); aes_done(&pelmac->K); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pelican/pelican_memory.c000066400000000000000000000021141464416617300255240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pelican_memory.c Pelican MAC, MAC a block of memory, by Tom St Denis */ #ifdef LTC_PELICAN /** Pelican block of memory @param key The key for the MAC @param keylen The length of the key (octets) @param in The input to MAC @param inlen The length of the input (octets) @param out [out] The output TAG @return CRYPT_OK on success */ int pelican_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out) { pelican_state *pel; int err; pel = XMALLOC(sizeof(*pel)); if (pel == NULL) { return CRYPT_MEM; } if ((err = pelican_init(pel, key, keylen)) != CRYPT_OK) { XFREE(pel); return err; } if ((err = pelican_process(pel, in ,inlen)) != CRYPT_OK) { XFREE(pel); return err; } err = pelican_done(pel, out); XFREE(pel); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pelican/pelican_test.c000066400000000000000000000054551464416617300252060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pelican_test.c Pelican MAC, test, by Tom St Denis */ #ifdef LTC_PELICAN int pelican_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char K[32], MSG[64], T[16]; int keylen, ptlen; } tests[] = { /* K=16, M=0 */ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0 }, { 0xeb, 0x58, 0x37, 0x15, 0xf8, 0x34, 0xde, 0xe5, 0xa4, 0xd1, 0x6e, 0xe4, 0xb9, 0xd7, 0x76, 0x0e, }, 16, 0 }, /* K=16, M=3 */ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0x00, 0x01, 0x02 }, { 0x1c, 0x97, 0x40, 0x60, 0x6c, 0x58, 0x17, 0x2d, 0x03, 0x94, 0x19, 0x70, 0x81, 0xc4, 0x38, 0x54, }, 16, 3 }, /* K=16, M=16 */ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0x03, 0xcc, 0x46, 0xb8, 0xac, 0xa7, 0x9c, 0x36, 0x1e, 0x8c, 0x6e, 0xa6, 0x7b, 0x89, 0x32, 0x49, }, 16, 16 }, /* K=16, M=32 */ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, { 0x89, 0xcc, 0x36, 0x58, 0x1b, 0xdd, 0x4d, 0xb5, 0x78, 0xbb, 0xac, 0xf0, 0xff, 0x8b, 0x08, 0x15, }, 16, 32 }, /* K=16, M=35 */ { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x23 }, { 0x4a, 0x7d, 0x45, 0x4d, 0xcd, 0xb5, 0xda, 0x8d, 0x48, 0x78, 0x16, 0x48, 0x5d, 0x45, 0x95, 0x99, }, 16, 35 }, }; int x, err; unsigned char out[16]; pelican_state pel; for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = pelican_init(&pel, tests[x].K, tests[x].keylen)) != CRYPT_OK) { return err; } if ((err = pelican_process(&pel, tests[x].MSG, tests[x].ptlen)) != CRYPT_OK) { return err; } if ((err = pelican_done(&pel, out)) != CRYPT_OK) { return err; } if (compare_testvector(out, 16, tests[x].T, 16, "PELICAN", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/000077500000000000000000000000001464416617300216645ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_done.c000066400000000000000000000030751464416617300237620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_done.c PMAC implementation, terminate a session, by Tom St Denis */ #ifdef LTC_PMAC int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen) { int err, x; LTC_ARGCHK(pmac != NULL); LTC_ARGCHK(out != NULL); if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) { return err; } if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { return CRYPT_INVALID_ARG; } /* handle padding. If multiple xor in L/x */ if (pmac->buflen == pmac->block_len) { /* xor Lr against the checksum */ for (x = 0; x < pmac->block_len; x++) { pmac->checksum[x] ^= pmac->block[x] ^ pmac->Lr[x]; } } else { /* otherwise xor message bytes then the 0x80 byte */ for (x = 0; x < pmac->buflen; x++) { pmac->checksum[x] ^= pmac->block[x]; } pmac->checksum[x] ^= 0x80; } /* encrypt it */ if ((err = cipher_descriptor[pmac->cipher_idx]->ecb_encrypt(pmac->checksum, pmac->checksum, &pmac->key)) != CRYPT_OK) { return err; } cipher_descriptor[pmac->cipher_idx]->done(&pmac->key); /* store it */ for (x = 0; x < pmac->block_len && x < (int)*outlen; x++) { out[x] = pmac->checksum[x]; } *outlen = x; #ifdef LTC_CLEAN_STACK zeromem(pmac, sizeof(*pmac)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_file.c000066400000000000000000000041631464416617300237530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_file.c PMAC implementation, process a file, by Tom St Denis */ #ifdef LTC_PMAC /** PMAC a file @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param filename The name of the file to send through PMAC @param out [out] Destination for the authentication tag @param outlen [in/out] Max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int pmac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(cipher); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(filename); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; int err; pmac_state pmac; FILE *in; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(filename != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(filename, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = pmac_process(&pmac, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = pmac_done(&pmac, out, outlen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&pmac, sizeof(pmac_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_init.c000066400000000000000000000067331464416617300240040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_init.c PMAC implementation, initialize state, by Tom St Denis */ #ifdef LTC_PMAC static const struct { int len; unsigned char poly_div[MAXBLOCKSIZE], poly_mul[MAXBLOCKSIZE]; } polys[] = { { 8, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } }, { 16, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } } }; /** Initialize a PMAC state @param pmac The PMAC state to initialize @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) { int poly, x, y, m, err; unsigned char *L; LTC_ARGCHK(pmac != NULL); LTC_ARGCHK(key != NULL); /* valid cipher? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* determine which polys to use */ pmac->block_len = cipher_descriptor[cipher]->block_length; for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { if (polys[poly].len == pmac->block_len) { break; } } if (poly >= (int)(sizeof(polys)/sizeof(polys[0]))) { return CRYPT_INVALID_ARG; } if (polys[poly].len != pmac->block_len) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (pmac->block_len % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* schedule the key */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) { return err; } /* allocate L */ L = XMALLOC(pmac->block_len); if (L == NULL) { return CRYPT_MEM; } /* find L = E[0] */ zeromem(L, pmac->block_len); if ((err = cipher_descriptor[cipher]->ecb_encrypt(L, L, &pmac->key)) != CRYPT_OK) { goto error; } /* find Ls[i] = L << i for i == 0..31 */ XMEMCPY(pmac->Ls[0], L, pmac->block_len); for (x = 1; x < 32; x++) { m = pmac->Ls[x-1][0] >> 7; for (y = 0; y < pmac->block_len-1; y++) { pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; } pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; if (m == 1) { for (y = 0; y < pmac->block_len; y++) { pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; } } } /* find Lr = L / x */ m = L[pmac->block_len-1] & 1; /* shift right */ for (x = pmac->block_len - 1; x > 0; x--) { pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; } pmac->Lr[0] = L[0] >> 1; if (m == 1) { for (x = 0; x < pmac->block_len; x++) { pmac->Lr[x] ^= polys[poly].poly_div[x]; } } /* zero buffer, counters, etc... */ pmac->block_index = 1; pmac->cipher_idx = cipher; pmac->buflen = 0; zeromem(pmac->block, sizeof(pmac->block)); zeromem(pmac->Li, sizeof(pmac->Li)); zeromem(pmac->checksum, sizeof(pmac->checksum)); err = CRYPT_OK; error: #ifdef LTC_CLEAN_STACK zeromem(L, pmac->block_len); #endif XFREE(L); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_memory.c000066400000000000000000000031661464416617300243460ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_memory.c PMAC implementation, process a block of memory, by Tom St Denis */ #ifdef LTC_PMAC /** PMAC a block of memory @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param in The data you wish to send through PMAC @param inlen The length of data you wish to send through PMAC (octets) @param out [out] Destination for the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful */ int pmac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { int err; pmac_state *pmac; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for pmac state */ pmac = XMALLOC(sizeof(pmac_state)); if (pmac == NULL) { return CRYPT_MEM; } if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = pmac_process(pmac, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(pmac, sizeof(pmac_state)); #endif XFREE(pmac); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_memory_multi.c000066400000000000000000000042461464416617300255600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file pmac_memory_multi.c PMAC implementation, process multiple blocks of memory, by Tom St Denis */ #ifdef LTC_PMAC /** PMAC multiple blocks of memory @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param out [out] Destination for the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag @param in The data you wish to send through PMAC @param inlen The length of data you wish to send through PMAC (octets) @param ... tuples of (data,len) pairs to PMAC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int pmac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { int err; pmac_state *pmac; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for pmac state */ pmac = XMALLOC(sizeof(pmac_state)); if (pmac == NULL) { return CRYPT_MEM; } if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = pmac_process(pmac, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(pmac, sizeof(pmac_state)); #endif XFREE(pmac); va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_ntz.c000066400000000000000000000006531464416617300236470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_ntz.c PMAC implementation, internal function, by Tom St Denis */ #ifdef LTC_PMAC /** Internal PMAC function */ int pmac_ntz(unsigned long x) { int c; x &= 0xFFFFFFFFUL; c = 0; while ((x & 1) == 0) { ++c; x >>= 1; } return c; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_process.c000066400000000000000000000050641464416617300245130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_process.c PMAC implementation, process data, by Tom St Denis */ #ifdef LTC_PMAC /** Process data in a PMAC stream @param pmac The PMAC state @param in The data to send through PMAC @param inlen The length of the data to send through PMAC @return CRYPT_OK if successful */ int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen) { int err, n; unsigned long x; unsigned char Z[MAXBLOCKSIZE]; LTC_ARGCHK(pmac != NULL); LTC_ARGCHK(in != NULL); if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) { return err; } if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (pmac->buflen == 0 && inlen > 16) { unsigned long y; for (x = 0; x < (inlen - 16); x += 16) { pmac_shift_xor(pmac); for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&Z[y])) = *(LTC_FAST_TYPE_PTR_CAST(&in[y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&pmac->Li[y])); } if ((err = cipher_descriptor[pmac->cipher_idx]->ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) { return err; } for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&pmac->checksum[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&Z[y])); } in += 16; } inlen -= x; } #endif while (inlen != 0) { /* ok if the block is full we xor in prev, encrypt and replace prev */ if (pmac->buflen == pmac->block_len) { pmac_shift_xor(pmac); for (x = 0; x < (unsigned long)pmac->block_len; x++) { Z[x] = pmac->Li[x] ^ pmac->block[x]; } if ((err = cipher_descriptor[pmac->cipher_idx]->ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) { return err; } for (x = 0; x < (unsigned long)pmac->block_len; x++) { pmac->checksum[x] ^= Z[x]; } pmac->buflen = 0; } /* add bytes */ n = MIN(inlen, (unsigned long)(pmac->block_len - pmac->buflen)); XMEMCPY(pmac->block + pmac->buflen, in, n); pmac->buflen += n; inlen -= n; in += n; } #ifdef LTC_CLEAN_STACK zeromem(Z, sizeof(Z)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_shift_xor.c000066400000000000000000000014161464416617300250370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_shift_xor.c PMAC implementation, internal function, by Tom St Denis */ #ifdef LTC_PMAC /** Internal function. Performs the state update (adding correct multiple) @param pmac The PMAC state. */ void pmac_shift_xor(pmac_state *pmac) { int x, y; y = pmac_ntz(pmac->block_index++); #ifdef LTC_FAST for (x = 0; x < pmac->block_len; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Li + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Ls[y] + x)); } #else for (x = 0; x < pmac->block_len; x++) { pmac->Li[x] ^= pmac->Ls[y][x]; } #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/pmac/pmac_test.c000066400000000000000000000072761464416617300240230ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pmac_test.c PMAC implementation, self-test, by Tom St Denis */ #ifdef LTC_PMAC /** Test the LTC_OMAC implementation @return CRYPT_OK if successful, CRYPT_NOP if testing has been disabled */ int pmac_test(void) { #if !defined(LTC_TEST) return CRYPT_NOP; #else static const struct { int msglen; unsigned char key[16], msg[34], tag[16]; } tests[] = { /* PMAC-AES-128-0B */ { 0, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* msg */ { 0x00 }, /* tag */ { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41, 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 } }, /* PMAC-AES-128-3B */ { 3, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* msg */ { 0x00, 0x01, 0x02 }, /* tag */ { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b, 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 } }, /* PMAC-AES-128-16B */ { 16, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* msg */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* tag */ { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6, 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 } }, /* PMAC-AES-128-20B */ { 20, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* msg */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 }, /* tag */ { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05, 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 } }, /* PMAC-AES-128-32B */ { 32, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* msg */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, /* tag */ { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99, 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 } }, /* PMAC-AES-128-34B */ { 34, /* key */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* msg */ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21 }, /* tag */ { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86, 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 } } }; int err, x, idx; unsigned long len; unsigned char outtag[MAXBLOCKSIZE]; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { len = sizeof(outtag); if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) { return err; } if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "PMAC", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif /* LTC_TEST */ } #endif /* PMAC_MODE */ optee_os-4.3.0/core/lib/libtomcrypt/src/mac/poly1305/000077500000000000000000000000001464416617300222405ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/poly1305/poly1305.c000066400000000000000000000163351464416617300237100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * Public Domain poly1305 from Andrew Moon * https://github.com/floodyberry/poly1305-donna */ #include "tomcrypt_private.h" #ifdef LTC_POLY1305 /* internal only */ static void s_poly1305_block(poly1305_state *st, const unsigned char *in, unsigned long inlen) { const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ ulong32 r0,r1,r2,r3,r4; ulong32 s1,s2,s3,s4; ulong32 h0,h1,h2,h3,h4; ulong32 tmp; ulong64 d0,d1,d2,d3,d4; ulong32 c; r0 = st->r[0]; r1 = st->r[1]; r2 = st->r[2]; r3 = st->r[3]; r4 = st->r[4]; s1 = r1 * 5; s2 = r2 * 5; s3 = r3 * 5; s4 = r4 * 5; h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; h3 = st->h[3]; h4 = st->h[4]; while (inlen >= 16) { /* h += in[i] */ LOAD32L(tmp, in+ 0); h0 += (tmp ) & 0x3ffffff; LOAD32L(tmp, in+ 3); h1 += (tmp >> 2) & 0x3ffffff; LOAD32L(tmp, in+ 6); h2 += (tmp >> 4) & 0x3ffffff; LOAD32L(tmp, in+ 9); h3 += (tmp >> 6) & 0x3ffffff; LOAD32L(tmp, in+12); h4 += (tmp >> 8) | hibit; /* h *= r */ d0 = ((ulong64)h0 * r0) + ((ulong64)h1 * s4) + ((ulong64)h2 * s3) + ((ulong64)h3 * s2) + ((ulong64)h4 * s1); d1 = ((ulong64)h0 * r1) + ((ulong64)h1 * r0) + ((ulong64)h2 * s4) + ((ulong64)h3 * s3) + ((ulong64)h4 * s2); d2 = ((ulong64)h0 * r2) + ((ulong64)h1 * r1) + ((ulong64)h2 * r0) + ((ulong64)h3 * s4) + ((ulong64)h4 * s3); d3 = ((ulong64)h0 * r3) + ((ulong64)h1 * r2) + ((ulong64)h2 * r1) + ((ulong64)h3 * r0) + ((ulong64)h4 * s4); d4 = ((ulong64)h0 * r4) + ((ulong64)h1 * r3) + ((ulong64)h2 * r2) + ((ulong64)h3 * r1) + ((ulong64)h4 * r0); /* (partial) h %= p */ c = (ulong32)(d0 >> 26); h0 = (ulong32)d0 & 0x3ffffff; d1 += c; c = (ulong32)(d1 >> 26); h1 = (ulong32)d1 & 0x3ffffff; d2 += c; c = (ulong32)(d2 >> 26); h2 = (ulong32)d2 & 0x3ffffff; d3 += c; c = (ulong32)(d3 >> 26); h3 = (ulong32)d3 & 0x3ffffff; d4 += c; c = (ulong32)(d4 >> 26); h4 = (ulong32)d4 & 0x3ffffff; h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; h1 += c; in += 16; inlen -= 16; } st->h[0] = h0; st->h[1] = h1; st->h[2] = h2; st->h[3] = h3; st->h[4] = h4; } /** Initialize an POLY1305 context. @param st The POLY1305 state @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen == 32); /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ LOAD32L(st->r[0], key + 0); st->r[0] = (st->r[0] ) & 0x3ffffff; LOAD32L(st->r[1], key + 3); st->r[1] = (st->r[1] >> 2) & 0x3ffff03; LOAD32L(st->r[2], key + 6); st->r[2] = (st->r[2] >> 4) & 0x3ffc0ff; LOAD32L(st->r[3], key + 9); st->r[3] = (st->r[3] >> 6) & 0x3f03fff; LOAD32L(st->r[4], key + 12); st->r[4] = (st->r[4] >> 8) & 0x00fffff; /* h = 0 */ st->h[0] = 0; st->h[1] = 0; st->h[2] = 0; st->h[3] = 0; st->h[4] = 0; /* save pad for later */ LOAD32L(st->pad[0], key + 16); LOAD32L(st->pad[1], key + 20); LOAD32L(st->pad[2], key + 24); LOAD32L(st->pad[3], key + 28); st->leftover = 0; st->final = 0; return CRYPT_OK; } /** Process data through POLY1305 @param st The POLY1305 state @param in The data to send through HMAC @param inlen The length of the data to HMAC (octets) @return CRYPT_OK if successful */ int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen) { unsigned long i; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); /* handle leftover */ if (st->leftover) { unsigned long want = (16 - st->leftover); if (want > inlen) want = inlen; for (i = 0; i < want; i++) st->buffer[st->leftover + i] = in[i]; inlen -= want; in += want; st->leftover += want; if (st->leftover < 16) return CRYPT_OK; s_poly1305_block(st, st->buffer, 16); st->leftover = 0; } /* process full blocks */ if (inlen >= 16) { unsigned long want = (inlen & ~(16 - 1)); s_poly1305_block(st, in, want); in += want; inlen -= want; } /* store leftover */ if (inlen) { for (i = 0; i < inlen; i++) st->buffer[st->leftover + i] = in[i]; st->leftover += inlen; } return CRYPT_OK; } /** Terminate a POLY1305 session @param st The POLY1305 state @param mac [out] The destination of the POLY1305 authentication tag @param maclen [in/out] The max size and resulting size of the POLY1305 authentication tag @return CRYPT_OK if successful */ int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen) { ulong32 h0,h1,h2,h3,h4,c; ulong32 g0,g1,g2,g3,g4; ulong64 f; ulong32 mask; LTC_ARGCHK(st != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); LTC_ARGCHK(*maclen >= 16); /* process the remaining block */ if (st->leftover) { unsigned long i = st->leftover; st->buffer[i++] = 1; for (; i < 16; i++) st->buffer[i] = 0; st->final = 1; s_poly1305_block(st, st->buffer, 16); } /* fully carry h */ h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; h3 = st->h[3]; h4 = st->h[4]; c = h1 >> 26; h1 = h1 & 0x3ffffff; h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += c; /* compute h + -p */ g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; g4 = h4 + c - (1UL << 26); /* select h if h < p, or h + -p if h >= p */ mask = (g4 >> 31) - 1; g0 &= mask; g1 &= mask; g2 &= mask; g3 &= mask; g4 &= mask; mask = ~mask; h0 = (h0 & mask) | g0; h1 = (h1 & mask) | g1; h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3; h4 = (h4 & mask) | g4; /* h = h % (2^128) */ h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; /* mac = (h + pad) % (2^128) */ f = (ulong64)h0 + st->pad[0] ; h0 = (ulong32)f; f = (ulong64)h1 + st->pad[1] + (f >> 32); h1 = (ulong32)f; f = (ulong64)h2 + st->pad[2] + (f >> 32); h2 = (ulong32)f; f = (ulong64)h3 + st->pad[3] + (f >> 32); h3 = (ulong32)f; STORE32L(h0, mac + 0); STORE32L(h1, mac + 4); STORE32L(h2, mac + 8); STORE32L(h3, mac + 12); /* zero out the state */ st->h[0] = 0; st->h[1] = 0; st->h[2] = 0; st->h[3] = 0; st->h[4] = 0; st->r[0] = 0; st->r[1] = 0; st->r[2] = 0; st->r[3] = 0; st->r[4] = 0; st->pad[0] = 0; st->pad[1] = 0; st->pad[2] = 0; st->pad[3] = 0; *maclen = 16; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/poly1305/poly1305_file.c000066400000000000000000000037511464416617300247050ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * Public Domain poly1305 from Andrew Moon * https://github.com/floodyberry/poly1305-donna */ #include "tomcrypt_private.h" #ifdef LTC_POLY1305 /** POLY1305 a file @param fname The name of the file you wish to POLY1305 @param key The secret key @param keylen The length of the secret key @param mac [out] The POLY1305 authentication tag @param maclen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(fname); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(mac); LTC_UNUSED_PARAM(maclen); return CRYPT_NOP; #else poly1305_state st; FILE *in; unsigned char *buf; size_t x; int err; LTC_ARGCHK(fname != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(fname, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = poly1305_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = poly1305_done(&st, mac, maclen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(poly1305_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory.c000066400000000000000000000025211464416617300252700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * Public Domain poly1305 from Andrew Moon * https://github.com/floodyberry/poly1305-donna */ #include "tomcrypt_private.h" #ifdef LTC_POLY1305 /** POLY1305 a block of memory to produce the authentication tag @param key The secret key @param keylen The length of the secret key (octets) @param in The data to POLY1305 @param inlen The length of the data to POLY1305 (octets) @param mac [out] Destination of the authentication tag @param maclen [in/out] Max size and resulting size of authentication tag @return CRYPT_OK if successful */ int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) { poly1305_state st; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = poly1305_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } err = poly1305_done(&st, mac, maclen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(poly1305_state)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c000066400000000000000000000034321464416617300265040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * Public Domain poly1305 from Andrew Moon * https://github.com/floodyberry/poly1305-donna */ #include "tomcrypt_private.h" #include #ifdef LTC_POLY1305 /** POLY1305 multiple blocks of memory to produce the authentication tag @param key The secret key @param keylen The length of the secret key (octets) @param mac [out] Destination of the authentication tag @param maclen [in/out] Max size and resulting size of authentication tag @param in The data to POLY1305 @param inlen The length of the data to POLY1305 (octets) @param ... tuples of (data,len) pairs to POLY1305, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) { poly1305_state st; int err; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(mac != NULL); LTC_ARGCHK(maclen != NULL); va_start(args, inlen); curptr = in; curlen = inlen; if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } for (;;) { if ((err = poly1305_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } curptr = va_arg(args, const unsigned char*); if (curptr == NULL) break; curlen = va_arg(args, unsigned long); } err = poly1305_done(&st, mac, maclen); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&st, sizeof(poly1305_state)); #endif va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/poly1305/poly1305_test.c000066400000000000000000000044201464416617300247370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * Public Domain poly1305 from Andrew Moon * https://github.com/floodyberry/poly1305-donna */ #include "tomcrypt_private.h" #ifdef LTC_POLY1305 int poly1305_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else /* https://tools.ietf.org/html/rfc7539#section-2.5.2 */ unsigned char k[] = { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b }; unsigned char tag[] = { 0xA8, 0x06, 0x1D, 0xC1, 0x30, 0x51, 0x36, 0xC6, 0xC2, 0x2B, 0x8B, 0xAF, 0x0C, 0x01, 0x27, 0xA9 }; char m[] = "Cryptographic Forum Research Group"; unsigned long len = 16, mlen = XSTRLEN(m); unsigned char out[1000]; poly1305_state st; int err; /* process piece by piece */ if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m, 5)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m + 5, 4)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m + 9, 3)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m + 12, 2)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m + 14, 1)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m + 15, mlen - 15)) != CRYPT_OK) return err; if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR; /* process in one go */ if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; if ((err = poly1305_process(&st, (unsigned char*)m, mlen)) != CRYPT_OK) return err; if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/000077500000000000000000000000001464416617300216635ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_done.c000066400000000000000000000031471464416617300237600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file xcbc_done.c XCBC Support, terminate the state */ #ifdef LTC_XCBC /** Terminate the XCBC-MAC state @param xcbc XCBC state to terminate @param out [out] Destination for the MAC tag @param outlen [in/out] Destination size and final tag size Return CRYPT_OK on success */ int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen) { int err, x; LTC_ARGCHK(xcbc != NULL); LTC_ARGCHK(out != NULL); /* check structure */ if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) { return err; } if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher]->block_length) || (xcbc->blocksize < 0) || (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { return CRYPT_INVALID_ARG; } /* which key do we use? */ if (xcbc->buflen == xcbc->blocksize) { /* k2 */ for (x = 0; x < xcbc->blocksize; x++) { xcbc->IV[x] ^= xcbc->K[1][x]; } } else { xcbc->IV[xcbc->buflen] ^= 0x80; /* k3 */ for (x = 0; x < xcbc->blocksize; x++) { xcbc->IV[x] ^= xcbc->K[2][x]; } } /* encrypt */ cipher_descriptor[xcbc->cipher]->ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); cipher_descriptor[xcbc->cipher]->done(&xcbc->key); /* extract tag */ for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) { out[x] = xcbc->IV[x]; } *outlen = x; #ifdef LTC_CLEAN_STACK zeromem(xcbc, sizeof(*xcbc)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_file.c000066400000000000000000000041241464416617300237460ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file xcbc_file.c XCBC support, process a file, Tom St Denis */ #ifdef LTC_XCBC /** XCBC a file @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param filename The name of the file you wish to XCBC @param out [out] Where the authentication tag is to be stored @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int xcbc_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(cipher); LTC_UNUSED_PARAM(key); LTC_UNUSED_PARAM(keylen); LTC_UNUSED_PARAM(filename); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(outlen); return CRYPT_NOP; #else size_t x; int err; xcbc_state xcbc; FILE *in; unsigned char *buf; LTC_ARGCHK(key != NULL); LTC_ARGCHK(filename != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { return CRYPT_MEM; } if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } in = fopen(filename, "rb"); if (in == NULL) { err = CRYPT_FILE_NOTFOUND; goto LBL_ERR; } do { x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); if ((err = xcbc_process(&xcbc, buf, (unsigned long)x)) != CRYPT_OK) { fclose(in); goto LBL_CLEANBUF; } } while (x == LTC_FILE_READ_BUFSIZE); if (fclose(in) != 0) { err = CRYPT_ERROR; goto LBL_CLEANBUF; } err = xcbc_done(&xcbc, out, outlen); LBL_CLEANBUF: zeromem(buf, LTC_FILE_READ_BUFSIZE); LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(&xcbc, sizeof(xcbc_state)); #endif XFREE(buf); return err; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_init.c000066400000000000000000000050121464416617300237670ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file xcbc_init.c XCBC Support, start an XCBC state */ #ifdef LTC_XCBC /** Initialize XCBC-MAC state @param xcbc [out] XCBC state to initialize @param cipher Index of cipher to use @param key [in] Secret key @param keylen Length of secret key in octets Return CRYPT_OK on success */ int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen) { int x, y, err; symmetric_key *skey; unsigned long k1; LTC_ARGCHK(xcbc != NULL); LTC_ARGCHK(key != NULL); /* schedule the key */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } #ifdef LTC_FAST if (cipher_descriptor[cipher]->block_length % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif skey = NULL; /* are we in pure XCBC mode with three keys? */ if (keylen & LTC_XCBC_PURE) { keylen &= ~LTC_XCBC_PURE; if (keylen < 2UL*cipher_descriptor[cipher]->block_length) { return CRYPT_INVALID_ARG; } k1 = keylen - 2*cipher_descriptor[cipher]->block_length; XMEMCPY(xcbc->K[0], key, k1); XMEMCPY(xcbc->K[1], key+k1, cipher_descriptor[cipher]->block_length); XMEMCPY(xcbc->K[2], key+k1 + cipher_descriptor[cipher]->block_length, cipher_descriptor[cipher]->block_length); } else { /* use the key expansion */ k1 = cipher_descriptor[cipher]->block_length; /* schedule the user key */ skey = XCALLOC(1, sizeof(*skey)); if (skey == NULL) { return CRYPT_MEM; } if ((err = cipher_descriptor[cipher]->setup(key, keylen, 0, skey)) != CRYPT_OK) { goto done; } /* make the three keys */ for (y = 0; y < 3; y++) { for (x = 0; x < cipher_descriptor[cipher]->block_length; x++) { xcbc->K[y][x] = y + 1; } cipher_descriptor[cipher]->ecb_encrypt(xcbc->K[y], xcbc->K[y], skey); } } /* setup K1 */ err = cipher_descriptor[cipher]->setup(xcbc->K[0], k1, 0, &xcbc->key); /* setup struct */ zeromem(xcbc->IV, cipher_descriptor[cipher]->block_length); xcbc->blocksize = cipher_descriptor[cipher]->block_length; xcbc->cipher = cipher; xcbc->buflen = 0; done: cipher_descriptor[cipher]->done(skey); if (skey != NULL) { #ifdef LTC_CLEAN_STACK zeromem(skey, sizeof(*skey)); #endif XFREE(skey); } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory.c000066400000000000000000000027601464416617300243430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file xcbc_process.c XCBC Support, XCBC-MAC a block of memory */ #ifdef LTC_XCBC /** XCBC-MAC a block of memory @param cipher Index of cipher to use @param key [in] Secret key @param keylen Length of key in octets @param in [in] Message to MAC @param inlen Length of input in octets @param out [out] Destination for the MAC tag @param outlen [in/out] Output size and final tag size Return CRYPT_OK on success. */ int xcbc_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { xcbc_state *xcbc; int err; /* is the cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* Use accelerator if found */ if (cipher_descriptor[cipher]->xcbc_memory != NULL) { return cipher_descriptor[cipher]->xcbc_memory(key, keylen, in, inlen, out, outlen); } xcbc = XCALLOC(1, sizeof(*xcbc)); if (xcbc == NULL) { return CRYPT_MEM; } if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { goto done; } if ((err = xcbc_process(xcbc, in, inlen)) != CRYPT_OK) { goto done; } err = xcbc_done(xcbc, out, outlen); done: XFREE(xcbc); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c000066400000000000000000000043011464416617300255460ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file xcbc_memory_multi.c XCBC support, process multiple blocks of memory, Tom St Denis */ #ifdef LTC_XCBC /** XCBC multiple blocks of memory @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param out [out] The destination of the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag (octets) @param in The data to send through XCBC @param inlen The length of the data to send through XCBC (octets) @param ... tuples of (data,len) pairs to XCBC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int xcbc_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { int err; xcbc_state *xcbc; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for xcbc state */ xcbc = XMALLOC(sizeof(xcbc_state)); if (xcbc == NULL) { return CRYPT_MEM; } /* xcbc process the message */ if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = xcbc_process(xcbc, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } if ((err = xcbc_done(xcbc, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(xcbc, sizeof(xcbc_state)); #endif XFREE(xcbc); va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_process.c000066400000000000000000000031741464416617300245110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file xcbc_process.c XCBC Support, process blocks with XCBC */ #ifdef LTC_XCBC /** Process data through XCBC-MAC @param xcbc The XCBC-MAC state @param in Input data to process @param inlen Length of input in octets Return CRYPT_OK on success */ int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen) { int err; #ifdef LTC_FAST int x; #endif LTC_ARGCHK(xcbc != NULL); LTC_ARGCHK(in != NULL); /* check structure */ if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) { return err; } if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher]->block_length) || (xcbc->blocksize < 0) || (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (xcbc->buflen == 0) { while (inlen > (unsigned long)xcbc->blocksize) { for (x = 0; x < xcbc->blocksize; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&(xcbc->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); } cipher_descriptor[xcbc->cipher]->ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); in += xcbc->blocksize; inlen -= xcbc->blocksize; } } #endif while (inlen) { if (xcbc->buflen == xcbc->blocksize) { cipher_descriptor[xcbc->cipher]->ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); xcbc->buflen = 0; } xcbc->IV[xcbc->buflen++] ^= *in++; --inlen; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/mac/xcbc/xcbc_test.c000066400000000000000000000053741464416617300240160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file xcbc_test.c XCBC Support, Test XCBC-MAC mode */ #ifdef LTC_XCBC /** Test XCBC-MAC mode Return CRYPT_OK on success */ int xcbc_test(void) { #ifdef LTC_NO_TEST return CRYPT_NOP; #else static const struct { int msglen; unsigned char K[16], M[34], T[16]; } tests[] = { { 0, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0 }, { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c, 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 } }, { 3, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x01, 0x02 }, { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf, 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f } }, { 16, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7, 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 } }, { 32, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3, 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 } }, { 34, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21 }, { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3, 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 }, }, }; unsigned char T[16]; unsigned long taglen; int err, x, idx; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { taglen = 16; if ((err = xcbc_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { return err; } if (compare_testvector(T, taglen, tests[x].T, 16, "XCBC", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/math/000077500000000000000000000000001464416617300211355ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/math/fp/000077500000000000000000000000001464416617300215425ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c000066400000000000000000003166041464416617300253560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_fp_mulmod.c ECC Crypto, Tom St Denis */ #if defined(LTC_MECC) && defined(LTC_MECC_FP) #include /* number of entries in the cache */ #ifndef FP_ENTRIES #define FP_ENTRIES 16 #endif /* number of bits in LUT */ #ifndef FP_LUT #define FP_LUT 8U #endif #if (FP_LUT > 12) || (FP_LUT < 2) #error FP_LUT must be between 2 and 12 inclusively #endif /** Our FP cache */ static struct { ecc_point *g, /* cached COPY of base point */ *LUT[1U< 6 { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, #if FP_LUT > 7 { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, #if FP_LUT > 8 { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, #if FP_LUT > 9 { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, #if FP_LUT > 10 { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, #if FP_LUT > 11 { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, #endif #endif #endif #endif #endif #endif }; /* find a hole and free as required, return -1 if no hole found */ static int s_find_hole(void) { unsigned x; int y, z; for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) { if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) { z = x; y = fp_cache[x].lru_count; } } /* decrease all */ for (x = 0; x < FP_ENTRIES; x++) { if (fp_cache[x].lru_count > 3) { --(fp_cache[x].lru_count); } } /* free entry z */ if (z >= 0 && fp_cache[z].g) { if (fp_cache[z].mu != NULL) { mp_clear(fp_cache[z].mu); fp_cache[z].mu = NULL; } ltc_ecc_del_point(fp_cache[z].g); fp_cache[z].g = NULL; for (x = 0; x < (1U<x, g->x) == LTC_MP_EQ && mp_cmp(fp_cache[x].g->y, g->y) == LTC_MP_EQ && mp_cmp(fp_cache[x].g->z, g->z) == LTC_MP_EQ) { break; } } if (x == FP_ENTRIES) { x = -1; } return x; } /* add a new base to the cache */ static int s_add_entry(int idx, ecc_point *g) { unsigned x, y; /* allocate base and LUT */ fp_cache[idx].g = ltc_ecc_new_point(); if (fp_cache[idx].g == NULL) { return CRYPT_MEM; } /* copy x and y */ if ((mp_copy(g->x, fp_cache[idx].g->x) != CRYPT_OK) || (mp_copy(g->y, fp_cache[idx].g->y) != CRYPT_OK) || (mp_copy(g->z, fp_cache[idx].g->z) != CRYPT_OK)) { ltc_ecc_del_point(fp_cache[idx].g); fp_cache[idx].g = NULL; return CRYPT_MEM; } for (x = 0; x < (1U<x, mu, modulus, fp_cache[idx].LUT[1]->x) != CRYPT_OK) || (mp_mulmod(fp_cache[idx].g->y, mu, modulus, fp_cache[idx].LUT[1]->y) != CRYPT_OK) || (mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { goto ERR; } /* make all single bit entries */ for (x = 1; x < FP_LUT; x++) { if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, fp_cache[idx].LUT[1<x) != CRYPT_OK) || (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, fp_cache[idx].LUT[1<y) != CRYPT_OK) || (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { goto ERR; } /* now double it bitlen/FP_LUT times */ for (y = 0; y < lut_gap; y++) { if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<z, modulus, mp)) != CRYPT_OK) { goto ERR; } /* invert it */ if ((err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto ERR; } /* now square it */ if ((err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } /* fix x */ if ((err = mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto ERR; } /* get 1/z^3 */ if ((err = mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } /* fix y */ if ((err = mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto ERR; } /* free z */ mp_clear(fp_cache[idx].LUT[x]->z); fp_cache[idx].LUT[x]->z = NULL; } mp_clear(tmp); return CRYPT_OK; ERR: err = CRYPT_MEM; DONE: for (y = 0; y < (1U< mp_unsigned_bin_size(modulus)) { /* find order */ y = mp_unsigned_bin_size(modulus); for (x = 0; ltc_ecc_sets[x].size; x++) { if (y <= (unsigned)ltc_ecc_sets[x].size) break; } /* back off if we are on the 521 bit curve */ if (y == 66) --x; if ((err = mp_init(&order)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { mp_clear(&order); return err; } /* k must be less than modulus */ if (mp_cmp(k, order) != LTC_MP_LT) { if ((err = mp_init(&tk)) != CRYPT_OK) { mp_clear(order); return err; } if ((err = mp_mod(k, order, tk)) != CRYPT_OK) { mp_clear(tk); mp_clear(order); return err; } } else { tk = k; } mp_clear(order); } else { tk = k; } /* get bitlen and round up to next multiple of FP_LUT */ bitlen = mp_unsigned_bin_size(modulus) << 3; x = bitlen % FP_LUT; if (x) { bitlen += FP_LUT - x; } lut_gap = bitlen / FP_LUT; /* get the k value */ if (mp_unsigned_bin_size(tk) > (sizeof(kb) - 2)) { if (tk != k) { mp_clear(tk); } return CRYPT_BUFFER_OVERFLOW; } /* store k */ zeromem(kb, sizeof(kb)); if ((err = mp_to_unsigned_bin(tk, kb)) != CRYPT_OK) { if (tk != k) { mp_clear(tk); } return err; } /* let's reverse kb so it's little endian */ x = 0; y = mp_unsigned_bin_size(tk) - 1; if (tk != k) { mp_clear(tk); } while ((unsigned)x < y) { z = kb[x]; kb[x] = kb[y]; kb[y] = z; ++x; --y; } /* at this point we can start, yipee */ first = 1; for (x = lut_gap-1; x >= 0; x--) { /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ bitpos = x; for (y = z = 0; y < FP_LUT; y++) { z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y; bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ } /* double if not first */ if (!first) { if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { return err; } } /* add if not first, otherwise copy */ if (!first && z) { if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) { return err; } } else if (z) { if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != CRYPT_OK) || (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != CRYPT_OK) || (mp_copy(fp_cache[idx].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } first = 0; } } z = 0; zeromem(kb, sizeof(kb)); /* map R back from projective space */ if (map) { err = ltc_ecc_map(R, modulus, mp); } else { err = CRYPT_OK; } return err; } #ifdef LTC_ECC_SHAMIR /* perform a fixed point ECC mulmod */ static int ss_accel_fp_mul2add(int idx1, int idx2, void *kA, void *kB, ecc_point *R, void *a, void *modulus, void *mp) { unsigned char kb[2][128]; int x; unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; void *tka, *tkb, *order; /* if it's smaller than modulus we fine */ if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) { /* find order */ y = mp_unsigned_bin_size(modulus); for (x = 0; ltc_ecc_sets[x].size; x++) { if (y <= (unsigned)ltc_ecc_sets[x].size) break; } /* back off if we are on the 521 bit curve */ if (y == 66) --x; if ((err = mp_init(&order)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { mp_clear(&order); return err; } /* kA must be less than modulus */ if (mp_cmp(kA, order) != LTC_MP_LT) { if ((err = mp_init(&tka)) != CRYPT_OK) { mp_clear(order); return err; } if ((err = mp_mod(kA, order, tka)) != CRYPT_OK) { mp_clear(tka); mp_clear(order); return err; } } else { tka = kA; } mp_clear(order); } else { tka = kA; } /* if it's smaller than modulus we fine */ if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) { /* find order */ y = mp_unsigned_bin_size(modulus); for (x = 0; ltc_ecc_sets[x].size; x++) { if (y <= (unsigned)ltc_ecc_sets[x].size) break; } /* back off if we are on the 521 bit curve */ if (y == 66) --x; if ((err = mp_init(&order)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { mp_clear(&order); return err; } /* kB must be less than modulus */ if (mp_cmp(kB, order) != LTC_MP_LT) { if ((err = mp_init(&tkb)) != CRYPT_OK) { mp_clear(order); return err; } if ((err = mp_mod(kB, order, tkb)) != CRYPT_OK) { mp_clear(tkb); mp_clear(order); return err; } } else { tkb = kB; } mp_clear(order); } else { tkb = kB; } /* get bitlen and round up to next multiple of FP_LUT */ bitlen = mp_unsigned_bin_size(modulus) << 3; x = bitlen % FP_LUT; if (x) { bitlen += FP_LUT - x; } lut_gap = bitlen / FP_LUT; /* get the k value */ if ((mp_unsigned_bin_size(tka) > (sizeof(kb[0]) - 2)) || (mp_unsigned_bin_size(tkb) > (sizeof(kb[0]) - 2)) ) { if (tka != kA) { mp_clear(tka); } if (tkb != kB) { mp_clear(tkb); } return CRYPT_BUFFER_OVERFLOW; } /* store k */ zeromem(kb, sizeof(kb)); if ((err = mp_to_unsigned_bin(tka, kb[0])) != CRYPT_OK) { if (tka != kA) { mp_clear(tka); } if (tkb != kB) { mp_clear(tkb); } return err; } /* let's reverse kb so it's little endian */ x = 0; y = mp_unsigned_bin_size(tka) - 1; if (tka != kA) { mp_clear(tka); } while ((unsigned)x < y) { z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z; ++x; --y; } /* store b */ if ((err = mp_to_unsigned_bin(tkb, kb[1])) != CRYPT_OK) { if (tkb != kB) { mp_clear(tkb); } return err; } x = 0; y = mp_unsigned_bin_size(tkb) - 1; if (tkb != kB) { mp_clear(tkb); } while ((unsigned)x < y) { z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z; ++x; --y; } /* at this point we can start, yipee */ first = 1; for (x = lut_gap-1; x >= 0; x--) { /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ bitpos = x; for (y = zA = zB = 0; y < FP_LUT; y++) { zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y; zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y; bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ } /* double if not first */ if (!first) { if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { return err; } } /* add if not first, otherwise copy */ if (!first) { if (zA) { if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { return err; } } if (zB) { if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { return err; } } } else { if (zA) { if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) || (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) || (mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } first = 0; } if (zB && first == 0) { if (zB) { if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { return err; } } } else if (zB && first == 1) { if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) || (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) || (mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } first = 0; } } } zeromem(kb, sizeof(kb)); return ltc_ecc_map(R, modulus, mp); } /** ECC Fixed Point mulmod global Computes kA*A + kB*B = C using Shamir's Trick @param A First point to multiply @param kA What to multiple A by @param B Second point to multiply @param kB What to multiple B by @param C [out] Destination point (can overlap with A or B) @param modulus Modulus for curve @return CRYPT_OK on success */ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, ecc_point *B, void *kB, ecc_point *C, void *a, void *modulus) { int idx1, idx2, err; void *mp, *mu; mp = NULL; mu = NULL; LTC_MUTEX_LOCK(<c_ecc_fp_lock); /* find point */ idx1 = s_find_base(A); /* no entry? */ if (idx1 == -1) { /* find hole and add it */ if ((idx1 = s_find_hole()) >= 0) { if ((err = s_add_entry(idx1, A)) != CRYPT_OK) { goto LBL_ERR; } } } if (idx1 != -1) { /* increment LRU */ ++(fp_cache[idx1].lru_count); } /* find point */ idx2 = s_find_base(B); /* no entry? */ if (idx2 == -1) { /* find hole and add it */ if ((idx2 = s_find_hole()) >= 0) { if ((err = s_add_entry(idx2, B)) != CRYPT_OK) { goto LBL_ERR; } } } if (idx2 != -1) { /* increment LRU */ ++(fp_cache[idx2].lru_count); } /* if it's 2 build the LUT, if it's higher just use the LUT */ if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) { /* compute mp */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } /* compute mu */ if ((err = mp_init(&mu)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto LBL_ERR; } /* build the LUT */ if ((err = s_build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) { goto LBL_ERR;; } } /* if it's 2 build the LUT, if it's higher just use the LUT */ if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) { if (mp == NULL) { /* compute mp */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } /* compute mu */ if ((err = mp_init(&mu)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto LBL_ERR; } } /* build the LUT */ if ((err = s_build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) { goto LBL_ERR;; } } if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 && fp_cache[idx2].lru_count >= 2) { if (mp == NULL) { /* compute mp */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } } err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); } else { err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus); } LBL_ERR: LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); if (mp != NULL) { mp_montgomery_free(mp); } if (mu != NULL) { mp_clear(mu); } return err; } #endif /** ECC Fixed Point mulmod global @param k The multiplicand @param G Base point to multiply @param R [out] Destination of product @param a ECC curve parameter a @param modulus The modulus for the curve @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form @return CRYPT_OK if successful */ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) { int idx, err; void *mp, *mu; mp = NULL; mu = NULL; LTC_MUTEX_LOCK(<c_ecc_fp_lock); /* find point */ idx = s_find_base(G); /* no entry? */ if (idx == -1) { /* find hole and add it */ idx = s_find_hole(); if (idx >= 0) { if ((err = s_add_entry(idx, G)) != CRYPT_OK) { goto LBL_ERR; } } } if (idx != -1) { /* increment LRU */ ++(fp_cache[idx].lru_count); } /* if it's 2 build the LUT, if it's higher just use the LUT */ if (idx >= 0 && fp_cache[idx].lru_count == 2) { /* compute mp */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } /* compute mu */ if ((err = mp_init(&mu)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto LBL_ERR; } /* build the LUT */ if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { goto LBL_ERR;; } } if (idx >= 0 && fp_cache[idx].lru_count >= 2) { if (mp == NULL) { /* compute mp */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } } err = s_accel_fp_mul(idx, k, R, a, modulus, mp, map); } else { err = ltc_ecc_mulmod(k, G, R, a, modulus, map); } LBL_ERR: LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); if (mp != NULL) { mp_montgomery_free(mp); } if (mu != NULL) { mp_clear(mu); } return err; } /* helper function for freeing the cache ... must be called with the cache mutex locked */ static void s_ltc_ecc_fp_free_cache(void) { unsigned x, y; for (x = 0; x < FP_ENTRIES; x++) { if (fp_cache[x].g != NULL) { for (y = 0; y < (1U<= 0) { /* it is already in the cache ... just check that the LUT is initialized */ if(fp_cache[idx].lru_count >= 2) { LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); return CRYPT_OK; } } if(idx == -1 && (idx = s_find_hole()) == -1) { err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } if ((err = s_add_entry(idx, g)) != CRYPT_OK) { goto LBL_ERR; } /* compute mp */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } /* compute mu */ if ((err = mp_init(&mu)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto LBL_ERR; } /* build the LUT */ if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { goto LBL_ERR; } fp_cache[idx].lru_count = 2; fp_cache[idx].lock = lock; LBL_ERR: LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); if (mp != NULL) { mp_montgomery_free(mp); } if (mu != NULL) { mp_clear(mu); } return err; } /** Prevent/permit the FP cache from being updated @param flag If flag is 0, remove cache lock (unlock), otherwise lock it */ void ltc_ecc_fp_tablelock(int lock) { int i; LTC_MUTEX_LOCK(<c_ecc_fp_lock); for (i = 0; i < FP_ENTRIES; i++) { fp_cache[i].lock = lock; } LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); } /** Export the current cache as a binary packet @param out [out] pointer to malloc'ed space containing the packet @param outlen [out] size of exported packet @return CRYPT_OK if successful */ int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen) { ltc_asn1_list *cache_entry; unsigned int i, j, k; unsigned long fp_entries, fp_lut, num_entries; int err; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); fp_entries = FP_ENTRIES; fp_lut = FP_LUT; num_entries = 0; LTC_MUTEX_LOCK(<c_ecc_fp_lock); /* * build the list; Cache DEFINITIONS ::= BEGIN CacheDump ::= SEQUENCE { numEntries SHORTINTEGER, maxEntries SHORTINTEGER, numLUT SHORTINTEGER, cache SEQUENCE OF INTEGER } END * */ /* * The cache itself is a point (3 INTEGERS), * the LUT as pairs of INTEGERS (2 * 1<x, 1); LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); for (k = 0; k < (1U<x, 1); LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].LUT[k]->y, 1); } LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); } LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_EOL, 0, 0); LTC_SET_ASN1(cache_entry, 0, LTC_ASN1_SHORT_INTEGER, &num_entries, 1); if ((err = der_length_sequence(cache_entry, j, outlen)) != CRYPT_OK) { goto save_err; } if ((*out = XMALLOC(*outlen)) == NULL) { err = CRYPT_MEM; goto save_err; } err = der_encode_sequence(cache_entry, j, *out, outlen); save_err: XFREE(cache_entry); LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); return err; } /** Import a binary packet into the current cache @param in [in] pointer to packet @param inlen [in] size of packet (bytes) @return CRYPT_OK if successful */ int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) { int err; ltc_asn1_list *asn1_list; unsigned long num_entries, fp_entries, fp_lut; unsigned long i, j; unsigned int x; LTC_ARGCHK(in != NULL); if (inlen == 0) { return CRYPT_INVALID_ARG; } /* zero indecies */ i = 0; j = 0; asn1_list = NULL; LTC_MUTEX_LOCK(<c_ecc_fp_lock); /* * start with an empty cache */ s_ltc_ecc_fp_free_cache(); /* * decode the input packet: It consists of a sequence with a few * integers (including the FP_ENTRIES and FP_LUT sizes), followed by a * SEQUENCE which is the cache itself. * * use standard decoding for the first part, then flexible for the second */ if((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1, &num_entries, LTC_ASN1_SHORT_INTEGER, 1, &fp_entries, LTC_ASN1_SHORT_INTEGER, 1, &fp_lut, LTC_ASN1_EOL, 0, 0)) != CRYPT_OK) { goto ERR_OUT; } if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) { err = CRYPT_INVALID_PACKET; goto ERR_OUT; } if ((asn1_list = XCALLOC(3+num_entries*(4+2*(1<x, 1); LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); for (x = 0; x < (1U<x, &p->y, LTC_NULL)) != CRYPT_OK) { goto ERR_OUT; } p->z = NULL; LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->x, 1); LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->y, 1); } if((err = mp_init(&fp_cache[i].mu)) != CRYPT_OK) { goto ERR_OUT; } LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); fp_cache[i].lru_count = 3; fp_cache[i].lock = 1; } if ((err = der_decode_sequence(in, inlen, asn1_list, j)) != CRYPT_OK) { goto ERR_OUT; } XFREE(asn1_list); LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); return CRYPT_OK; ERR_OUT: if(asn1_list) XFREE(asn1_list); s_ltc_ecc_fp_free_cache(); LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/math/gmp_desc.c000066400000000000000000000317051464416617300230700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #define DESC_DEF_ONLY #include "tomcrypt_private.h" #ifdef GMP_DESC #include #include static int init(void **a) { LTC_ARGCHK(a != NULL); *a = XCALLOC(1, sizeof(__mpz_struct)); if (*a == NULL) { return CRYPT_MEM; } mpz_init(((__mpz_struct *)*a)); return CRYPT_OK; } static void deinit(void *a) { LTC_ARGCHKVD(a != NULL); mpz_clear(a); XFREE(a); } static int neg(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_neg(b, a); return CRYPT_OK; } static int copy(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_set(b, a); return CRYPT_OK; } static int init_copy(void **a, void *b) { if (init(a) != CRYPT_OK) { return CRYPT_MEM; } return copy(b, *a); } /* ---- trivial ---- */ static int set_int(void *a, ltc_mp_digit b) { LTC_ARGCHK(a != NULL); mpz_set_ui(((__mpz_struct *)a), b); return CRYPT_OK; } static unsigned long get_int(void *a) { LTC_ARGCHK(a != NULL); return mpz_get_ui(a); } static ltc_mp_digit get_digit(void *a, int n) { LTC_ARGCHK(a != NULL); return mpz_getlimbn(a, n); } static int get_digit_count(void *a) { LTC_ARGCHK(a != NULL); return mpz_size(a); } static int compare(void *a, void *b) { int ret; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); ret = mpz_cmp(a, b); if (ret < 0) { return LTC_MP_LT; } else if (ret > 0) { return LTC_MP_GT; } else { return LTC_MP_EQ; } } static int compare_d(void *a, ltc_mp_digit b) { int ret; LTC_ARGCHK(a != NULL); ret = mpz_cmp_ui(((__mpz_struct *)a), b); if (ret < 0) { return LTC_MP_LT; } else if (ret > 0) { return LTC_MP_GT; } else { return LTC_MP_EQ; } } static int count_bits(void *a) { LTC_ARGCHK(a != NULL); return mpz_sizeinbase(a, 2); } static int count_lsb_bits(void *a) { LTC_ARGCHK(a != NULL); return mpz_scan1(a, 0); } static int twoexpt(void *a, int n) { LTC_ARGCHK(a != NULL); mpz_set_ui(a, 0); mpz_setbit(a, n); return CRYPT_OK; } /* ---- conversions ---- */ static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; /* read ascii string */ static int read_radix(void *a, const char *b, int radix) { int ret; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); if (radix == 64) { /* Sadly, GMP only supports radixes up to 62, but we need 64. * So, although this is not the most elegant or efficient way, * let's just convert the base 64 string (6 bits per digit) to * an octal string (3 bits per digit) that's twice as long. */ char c, *tmp, *q; const char *p; int i; tmp = XMALLOC (1 + 2 * XSTRLEN (b)); if (tmp == NULL) { return CRYPT_MEM; } p = b; q = tmp; while ((c = *p++) != 0) { for (i = 0; i < 64; i++) { if (c == rmap[i]) break; } if (i == 64) { XFREE (tmp); /* printf ("c = '%c'\n", c); */ return CRYPT_ERROR; } *q++ = '0' + (i / 8); *q++ = '0' + (i % 8); } *q = 0; ret = mpz_set_str(a, tmp, 8); /* printf ("ret = %d for '%s'\n", ret, tmp); */ XFREE (tmp); } else { ret = mpz_set_str(a, b, radix); } return (ret == 0 ? CRYPT_OK : CRYPT_ERROR); } /* write one */ static int write_radix(void *a, char *b, int radix) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); if (radix >= 11 && radix <= 36) /* If radix is positive, GMP uses lowercase, and if negative, uppercase. * We want it to use uppercase, to match the test vectors (presumably * generated with LibTomMath). */ radix = -radix; mpz_get_str(b, radix, a); return CRYPT_OK; } /* get size as unsigned char string */ static unsigned long unsigned_size(void *a) { unsigned long t; LTC_ARGCHK(a != NULL); t = mpz_sizeinbase(a, 2); if (mpz_cmp_ui(((__mpz_struct *)a), 0) == 0) return 0; return (t>>3) + ((t&7)?1:0); } /* store */ static int unsigned_write(void *a, unsigned char *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_export(b, NULL, 1, 1, 1, 0, ((__mpz_struct*)a)); return CRYPT_OK; } /* read */ static int unsigned_read(void *a, unsigned char *b, unsigned long len) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_import(a, len, 1, 1, 1, 0, b); return CRYPT_OK; } /* add */ static int add(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_add(c, a, b); return CRYPT_OK; } static int addi(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); mpz_add_ui(c, a, b); return CRYPT_OK; } /* sub */ static int sub(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_sub(c, a, b); return CRYPT_OK; } static int subi(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); mpz_sub_ui(c, a, b); return CRYPT_OK; } /* mul */ static int mul(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_mul(c, a, b); return CRYPT_OK; } static int muli(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); mpz_mul_ui(c, a, b); return CRYPT_OK; } /* sqr */ static int sqr(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_mul(b, a, a); return CRYPT_OK; } /* sqrtmod_prime */ static int sqrtmod_prime(void *n, void *prime, void *ret) { int res, legendre, i; mpz_t t1, C, Q, S, Z, M, T, R, two; LTC_ARGCHK(n != NULL); LTC_ARGCHK(prime != NULL); LTC_ARGCHK(ret != NULL); /* first handle the simple cases */ if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) { mpz_set_ui(ret, 0); return CRYPT_OK; } if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0) return CRYPT_ERROR; /* prime must be odd */ legendre = mpz_legendre(n, prime); if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */ mpz_init(t1); mpz_init(C); mpz_init(Q); mpz_init(S); mpz_init(Z); mpz_init(M); mpz_init(T); mpz_init(R); mpz_init(two); /* SPECIAL CASE: if prime mod 4 == 3 * compute directly: res = n^(prime+1)/4 mod prime * Handbook of Applied Cryptography algorithm 3.36 */ i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */ if (i == 3) { mpz_add_ui(t1, prime, 1); mpz_fdiv_q_2exp(t1, t1, 2); mpz_powm(ret, n, t1, prime); res = CRYPT_OK; goto cleanup; } /* NOW: Tonelli-Shanks algorithm */ /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ mpz_set(Q, prime); mpz_sub_ui(Q, Q, 1); /* Q = prime - 1 */ mpz_set_ui(S, 0); /* S = 0 */ while (mpz_even_p(Q)) { mpz_fdiv_q_2exp(Q, Q, 1); /* Q = Q / 2 */ mpz_add_ui(S, S, 1); /* S = S + 1 */ } /* find a Z such that the Legendre symbol (Z|prime) == -1 */ mpz_set_ui(Z, 2); /* Z = 2 */ while(1) { legendre = mpz_legendre(Z, prime); if (legendre == -1) break; mpz_add_ui(Z, Z, 1); /* Z = Z + 1 */ } mpz_powm(C, Z, Q, prime); /* C = Z ^ Q mod prime */ mpz_add_ui(t1, Q, 1); mpz_fdiv_q_2exp(t1, t1, 1); /* t1 = (Q + 1) / 2 */ mpz_powm(R, n, t1, prime); /* R = n ^ ((Q + 1) / 2) mod prime */ mpz_powm(T, n, Q, prime); /* T = n ^ Q mod prime */ mpz_set(M, S); /* M = S */ mpz_set_ui(two, 2); while (1) { mpz_set(t1, T); i = 0; while (1) { if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break; mpz_powm(t1, t1, two, prime); i++; } if (i == 0) { mpz_set(ret, R); res = CRYPT_OK; goto cleanup; } mpz_sub_ui(t1, M, i); mpz_sub_ui(t1, t1, 1); mpz_powm(t1, two, t1, prime); /* t1 = 2 ^ (M - i - 1) */ mpz_powm(t1, C, t1, prime); /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ mpz_mul(C, t1, t1); mpz_mod(C, C, prime); /* C = (t1 * t1) mod prime */ mpz_mul(R, R, t1); mpz_mod(R, R, prime); /* R = (R * t1) mod prime */ mpz_mul(T, T, C); mpz_mod(T, T, prime); /* T = (T * C) mod prime */ mpz_set_ui(M, i); /* M = i */ } cleanup: mpz_clear(t1); mpz_clear(C); mpz_clear(Q); mpz_clear(S); mpz_clear(Z); mpz_clear(M); mpz_clear(T); mpz_clear(R); mpz_clear(two); return res; } /* div */ static int divide(void *a, void *b, void *c, void *d) { mpz_t tmp; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); if (c != NULL) { mpz_init(tmp); mpz_divexact(tmp, a, b); } if (d != NULL) { mpz_mod(d, a, b); } if (c != NULL) { mpz_set(c, tmp); mpz_clear(tmp); } return CRYPT_OK; } static int div_2(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_divexact_ui(b, a, 2); return CRYPT_OK; } /* modi */ static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); *c = mpz_fdiv_ui(a, b); return CRYPT_OK; } /* gcd */ static int gcd(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_gcd(c, a, b); return CRYPT_OK; } /* lcm */ static int lcm(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_lcm(c, a, b); return CRYPT_OK; } static int addmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); mpz_add(d, a, b); mpz_mod(d, d, c); return CRYPT_OK; } static int submod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); mpz_sub(d, a, b); mpz_mod(d, d, c); return CRYPT_OK; } static int mulmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); mpz_mul(d, a, b); mpz_mod(d, d, c); return CRYPT_OK; } static int sqrmod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_mul(c, a, a); mpz_mod(c, c, b); return CRYPT_OK; } /* invmod */ static int invmod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_invert(c, a, b); return CRYPT_OK; } /* setup */ static int montgomery_setup(void *a, void **b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); *b = (void *)1; return CRYPT_OK; } /* get normalization value */ static int montgomery_normalization(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); mpz_set_ui(a, 1); return CRYPT_OK; } /* reduce */ static int montgomery_reduce(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); mpz_mod(a, a, b); return CRYPT_OK; } /* clean up */ static void montgomery_deinit(void *a) { LTC_UNUSED_PARAM(a); } static int exptmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); mpz_powm(d, a, b, c); return CRYPT_OK; } static int isprime(void *a, int b, int *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); if (b == 0) { b = LTC_MILLER_RABIN_REPS; } /* if */ *c = mpz_probab_prime_p(a, b) > 0 ? LTC_MP_YES : LTC_MP_NO; return CRYPT_OK; } static int set_rand(void *a, int size) { LTC_ARGCHK(a != NULL); mpz_random(a, size); return CRYPT_OK; } const ltc_math_descriptor gmp_desc = { "GNU MP", sizeof(mp_limb_t) * CHAR_BIT - GMP_NAIL_BITS, &init, &init_copy, &deinit, &neg, ©, &set_int, &get_int, &get_digit, &get_digit_count, &compare, &compare_d, &count_bits, &count_lsb_bits, &twoexpt, &read_radix, &write_radix, &unsigned_size, &unsigned_write, &unsigned_read, &add, &addi, &sub, &subi, &mul, &muli, &sqr, &sqrtmod_prime, ÷, &div_2, &modi, &gcd, &lcm, &mulmod, &sqrmod, &invmod, &montgomery_setup, &montgomery_normalization, &montgomery_reduce, &montgomery_deinit, &exptmod, &isprime, #ifdef LTC_MECC #ifdef LTC_MECC_FP <c_ecc_fp_mulmod, #else <c_ecc_mulmod, #endif /* LTC_MECC_FP */ <c_ecc_projective_add_point, <c_ecc_projective_dbl_point, <c_ecc_map, #ifdef LTC_ECC_SHAMIR #ifdef LTC_MECC_FP <c_ecc_fp_mul2add, #else <c_ecc_mul2add, #endif /* LTC_MECC_FP */ #else NULL, #endif /* LTC_ECC_SHAMIR */ #else NULL, NULL, NULL, NULL, NULL, #endif /* LTC_MECC */ #ifdef LTC_MRSA &rsa_make_key, &rsa_exptmod, #else NULL, NULL, #endif &addmod, &submod, &set_rand, }; #endif optee_os-4.3.0/core/lib/libtomcrypt/src/math/ltm_desc.c000066400000000000000000000253261464416617300231030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #define DESC_DEF_ONLY #include "tomcrypt_private.h" #ifdef LTM_DESC #include #if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C) #include #endif static const struct { mp_err mpi_code; int ltc_code; } mpi_to_ltc_codes[] = { { MP_OKAY , CRYPT_OK}, { MP_MEM , CRYPT_MEM}, { MP_VAL , CRYPT_INVALID_ARG}, #if defined(MP_BUF) || defined(MP_USE_ENUMS) { MP_ITER , CRYPT_INVALID_PACKET}, { MP_BUF , CRYPT_BUFFER_OVERFLOW}, #endif }; /** Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) @param err The error to convert @return The equivalent LTC error code or CRYPT_ERROR if none found */ static int mpi_to_ltc_error(mp_err err) { size_t x; for (x = 0; x < sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0]); x++) { if (err == mpi_to_ltc_codes[x].mpi_code) { return mpi_to_ltc_codes[x].ltc_code; } } return CRYPT_ERROR; } static int init_mpi(void **a) { LTC_ARGCHK(a != NULL); *a = XCALLOC(1, sizeof(mp_int)); if (*a == NULL) { return CRYPT_MEM; } else { return CRYPT_OK; } } static int init(void **a) { int err; LTC_ARGCHK(a != NULL); if ((err = init_mpi(a)) != CRYPT_OK) { return err; } if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) { XFREE(*a); } return err; } static void deinit(void *a) { LTC_ARGCHKVD(a != NULL); mp_clear(a); XFREE(a); } static int neg(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_neg(a, b)); } static int copy(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_copy(a, b)); } static int init_copy(void **a, void *b) { int err; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); if ((err = init_mpi(a)) != CRYPT_OK) return err; return mpi_to_ltc_error(mp_init_copy(*a, b)); } /* ---- trivial ---- */ static int set_int(void *a, ltc_mp_digit b) { LTC_ARGCHK(a != NULL); #ifdef BN_MP_SET_INT_C return mpi_to_ltc_error(mp_set_int(a, b)); #else mp_set_u32(a, b); return CRYPT_OK; #endif } static unsigned long get_int(void *a) { LTC_ARGCHK(a != NULL); #ifdef BN_MP_GET_INT_C return mp_get_int(a); #else return mp_get_ul(a); #endif } static ltc_mp_digit get_digit(void *a, int n) { mp_int *A; LTC_ARGCHK(a != NULL); A = a; return (n >= A->used || n < 0) ? 0 : A->dp[n]; } static int get_digit_count(void *a) { mp_int *A; LTC_ARGCHK(a != NULL); A = a; return A->used; } static int compare(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); switch (mp_cmp(a, b)) { case MP_LT: return LTC_MP_LT; case MP_EQ: return LTC_MP_EQ; case MP_GT: return LTC_MP_GT; default: return 0; } } static int compare_d(void *a, ltc_mp_digit b) { LTC_ARGCHK(a != NULL); switch (mp_cmp_d(a, b)) { case MP_LT: return LTC_MP_LT; case MP_EQ: return LTC_MP_EQ; case MP_GT: return LTC_MP_GT; default: return 0; } } static int count_bits(void *a) { LTC_ARGCHK(a != NULL); return mp_count_bits(a); } static int count_lsb_bits(void *a) { LTC_ARGCHK(a != NULL); return mp_cnt_lsb(a); } static int twoexpt(void *a, int n) { LTC_ARGCHK(a != NULL); return mpi_to_ltc_error(mp_2expt(a, n)); } /* ---- conversions ---- */ /* read ascii string */ static int read_radix(void *a, const char *b, int radix) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_read_radix(a, b, radix)); } /* write one */ static int write_radix(void *a, char *b, int radix) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); #ifdef BN_MP_TORADIX_C return mpi_to_ltc_error(mp_toradix(a, b, radix)); #else return mpi_to_ltc_error(mp_to_radix(a, b, SIZE_MAX, NULL, radix)); #endif } /* get size as unsigned char string */ static unsigned long unsigned_size(void *a) { LTC_ARGCHK(a != NULL); #ifdef BN_MP_UNSIGNED_BIN_SIZE_C return mp_unsigned_bin_size(a); #else return (unsigned long)mp_ubin_size(a); #endif } /* store */ static int unsigned_write(void *a, unsigned char *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); #ifdef BN_MP_TO_UNSIGNED_BIN_C return mpi_to_ltc_error(mp_to_unsigned_bin(a, b)); #else return mpi_to_ltc_error(mp_to_ubin(a, b, SIZE_MAX, NULL)); #endif } /* read */ static int unsigned_read(void *a, unsigned char *b, unsigned long len) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); #ifdef BN_MP_READ_UNSIGNED_BIN_C return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len)); #else return mpi_to_ltc_error(mp_from_ubin(a, b, (size_t)len)); #endif } /* add */ static int add(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_add(a, b, c)); } static int addi(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_add_d(a, b, c)); } /* sub */ static int sub(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_sub(a, b, c)); } static int subi(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_sub_d(a, b, c)); } /* mul */ static int mul(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_mul(a, b, c)); } static int muli(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_mul_d(a, b, c)); } /* sqr */ static int sqr(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_sqr(a, b)); } /* sqrtmod_prime */ static int sqrtmod_prime(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c)); } /* div */ static int divide(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_div(a, b, c, d)); } static int div_2(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_div_2(a, b)); } /* modi */ static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) { mp_digit tmp; int err; LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) { return err; } *c = tmp; return CRYPT_OK; } /* gcd */ static int gcd(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_gcd(a, b, c)); } /* lcm */ static int lcm(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_lcm(a, b, c)); } static int addmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return mpi_to_ltc_error(mp_addmod(a,b,c,d)); } static int submod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return mpi_to_ltc_error(mp_submod(a,b,c,d)); } static int mulmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return mpi_to_ltc_error(mp_mulmod(a,b,c,d)); } static int sqrmod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_sqrmod(a,b,c)); } /* invmod */ static int invmod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_invmod(a, b, c)); } /* setup */ static int montgomery_setup(void *a, void **b) { int err; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); *b = XCALLOC(1, sizeof(mp_digit)); if (*b == NULL) { return CRYPT_MEM; } if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) { XFREE(*b); } return err; } /* get normalization value */ static int montgomery_normalization(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b)); } /* reduce */ static int montgomery_reduce(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c))); } /* clean up */ static void montgomery_deinit(void *a) { XFREE(a); } static int exptmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return mpi_to_ltc_error(mp_exptmod(a,b,c,d)); } static int isprime(void *a, int b, int *c) { int err; #if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C) int res; #else bool res; #endif LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); b = mp_prime_rabin_miller_trials(mp_count_bits(a)); err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res)); *c = res ? LTC_MP_YES : LTC_MP_NO; return err; } static int set_rand(void *a, int size) { LTC_ARGCHK(a != NULL); return mpi_to_ltc_error(mp_rand(a, size)); } #ifndef MP_DIGIT_BIT #define MP_DIGIT_BIT DIGIT_BIT #endif const ltc_math_descriptor ltm_desc = { "LibTomMath", (int)MP_DIGIT_BIT, &init, &init_copy, &deinit, &neg, ©, &set_int, &get_int, &get_digit, &get_digit_count, &compare, &compare_d, &count_bits, &count_lsb_bits, &twoexpt, &read_radix, &write_radix, &unsigned_size, &unsigned_write, &unsigned_read, &add, &addi, &sub, &subi, &mul, &muli, &sqr, &sqrtmod_prime, ÷, &div_2, &modi, &gcd, &lcm, &mulmod, &sqrmod, &invmod, &montgomery_setup, &montgomery_normalization, &montgomery_reduce, &montgomery_deinit, &exptmod, &isprime, #ifdef LTC_MECC #ifdef LTC_MECC_FP <c_ecc_fp_mulmod, #else <c_ecc_mulmod, #endif <c_ecc_projective_add_point, <c_ecc_projective_dbl_point, <c_ecc_map, #ifdef LTC_ECC_SHAMIR #ifdef LTC_MECC_FP <c_ecc_fp_mul2add, #else <c_ecc_mul2add, #endif /* LTC_MECC_FP */ #else NULL, #endif /* LTC_ECC_SHAMIR */ #else NULL, NULL, NULL, NULL, NULL, #endif /* LTC_MECC */ #ifdef LTC_MRSA &rsa_make_key, &rsa_exptmod, #else NULL, NULL, #endif &addmod, &submod, &set_rand, }; #endif optee_os-4.3.0/core/lib/libtomcrypt/src/math/multi.c000066400000000000000000000034731464416617300224420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MPI #include int ltc_init_multi(void **a, ...) { void **cur = a; int np = 0; va_list args; va_start(args, a); while (cur != NULL) { if (mp_init(cur) != CRYPT_OK) { /* failed */ va_list clean_list; va_start(clean_list, a); cur = a; while (np--) { mp_clear(*cur); cur = va_arg(clean_list, void**); } va_end(clean_list); va_end(args); return CRYPT_MEM; } ++np; cur = va_arg(args, void**); } va_end(args); return CRYPT_OK; } int ltc_init_multi_size(int size_bits, void **a, ...) { void **cur = a; int np = 0; va_list args; va_start(args, a); while (cur != NULL) { if (mp_init_size(size_bits, cur) != CRYPT_OK) { /* failed */ va_list clean_list; va_start(clean_list, a); cur = a; while (np--) { mp_clear(*cur); cur = va_arg(clean_list, void**); } va_end(clean_list); return CRYPT_MEM; } ++np; cur = va_arg(args, void**); } va_end(args); return CRYPT_OK; } void ltc_deinit_multi(void *a, ...) { void *cur = a; va_list args; va_start(args, a); while (cur != NULL) { mp_clear(cur); cur = va_arg(args, void *); } va_end(args); } void ltc_cleanup_multi(void **a, ...) { void **cur = a; va_list args; va_start(args, a); while (cur != NULL) { if (*cur != NULL) { mp_clear(*cur); *cur = NULL; } cur = va_arg(args, void**); } va_end(args); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/math/radix_to_bin.c000066400000000000000000000023311464416617300237410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file radix_to_bin.c Convert data from a specific radix to binary. Steffen Jaeckel */ /** Convert data from a specific radix to binary The default MPI descriptors #ltm_desc, #tfm_desc and #gmp_desc have the following restrictions on parameters: \p in - NUL-terminated char buffer \p radix - 2..64 @param in The input @param radix The radix of the input @param out The output buffer @param len [in/out] The length of the output buffer @return CRYPT_OK on success. */ int radix_to_bin(const void *in, int radix, void *out, unsigned long *len) { unsigned long l; void* mpi; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(len != NULL); if ((err = mp_init(&mpi)) != CRYPT_OK) return err; if ((err = mp_read_radix(mpi, in, radix)) != CRYPT_OK) goto LBL_ERR; if ((l = mp_unsigned_bin_size(mpi)) > *len) { *len = l; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } *len = l; if ((err = mp_to_unsigned_bin(mpi, out)) != CRYPT_OK) goto LBL_ERR; LBL_ERR: mp_clear(mpi); return err; } optee_os-4.3.0/core/lib/libtomcrypt/src/math/rand_bn.c000066400000000000000000000030031464416617300227000ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #if defined(LTC_MDSA) || defined(LTC_MECC) /** Generate a random number N with given bitlength (note: MSB can be 0) */ int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng) { int res, bytes; unsigned char *buf, mask; LTC_ARGCHK(N != NULL); LTC_ARGCHK(bits > 1); /* check PRNG */ if ((res = prng_is_valid(wprng)) != CRYPT_OK) return res; bytes = (bits+7) >> 3; mask = 0xff >> (bits % 8 == 0 ? 0 : 8 - bits % 8); /* allocate buffer */ if ((buf = XCALLOC(1, bytes)) == NULL) return CRYPT_MEM; /* generate random bytes */ if (prng_descriptor[wprng]->read(buf, bytes, prng) != (unsigned long)bytes) { res = CRYPT_ERROR_READPRNG; goto cleanup; } /* mask bits */ buf[0] &= mask; /* load value */ if ((res = mp_read_unsigned_bin(N, buf, bytes)) != CRYPT_OK) goto cleanup; res = CRYPT_OK; cleanup: #ifdef LTC_CLEAN_STACK zeromem(buf, bytes); #endif XFREE(buf); return res; } /** Generate a random number N in a range: 1 <= N < limit */ int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng) { int res, bits; LTC_ARGCHK(N != NULL); LTC_ARGCHK(limit != NULL); bits = mp_count_bits(limit); do { res = rand_bn_bits(N, bits, prng, wprng); if (res != CRYPT_OK) return res; } while (mp_cmp_d(N, 0) != LTC_MP_GT || mp_cmp(N, limit) != LTC_MP_LT); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/math/rand_prime.c000066400000000000000000000032001464416617300234140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #if defined(LTC_MRSA) || (!defined(LTC_NO_MATH) && !defined(LTC_NO_PRNGS)) /** @file rand_prime.c Generate a random prime, Tom St Denis */ #define USE_BBS 1 int rand_prime(void *N, long len, prng_state *prng, int wprng) { int err, res, type; unsigned char *buf; LTC_ARGCHK(N != NULL); /* get type */ if (len < 0) { type = USE_BBS; len = -len; } else { type = 0; } /* allow sizes between 2 and 512 bytes for a prime size */ if (len < 2 || len > 512) { return CRYPT_INVALID_PRIME_SIZE; } /* valid PRNG? Better be! */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } /* allocate buffer to work with */ buf = XCALLOC(1, len); if (buf == NULL) { return CRYPT_MEM; } do { /* generate value */ if (prng_descriptor[wprng]->read(buf, len, prng) != (unsigned long)len) { XFREE(buf); return CRYPT_ERROR_READPRNG; } /* munge bits */ buf[0] |= 0x80 | 0x40; buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); /* load value */ if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) { XFREE(buf); return err; } /* test */ if ((err = mp_prime_is_prime(N, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { XFREE(buf); return err; } } while (res == LTC_MP_NO); #ifdef LTC_CLEAN_STACK zeromem(buf, len); #endif XFREE(buf); return CRYPT_OK; } #endif /* LTC_NO_MATH */ optee_os-4.3.0/core/lib/libtomcrypt/src/math/tfm_desc.c000066400000000000000000000432201464416617300230660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #define DESC_DEF_ONLY #include "tomcrypt_private.h" #ifdef TFM_DESC #include static const struct { int tfm_code, ltc_code; } tfm_to_ltc_codes[] = { { FP_OKAY , CRYPT_OK}, { FP_MEM , CRYPT_MEM}, { FP_VAL , CRYPT_INVALID_ARG}, }; /** Convert a tfm error to a LTC error (Possibly the most powerful function ever! Oh wait... no) @param err The error to convert @return The equivalent LTC error code or CRYPT_ERROR if none found */ static int tfm_to_ltc_error(int err) { int x; for (x = 0; x < (int)(sizeof(tfm_to_ltc_codes)/sizeof(tfm_to_ltc_codes[0])); x++) { if (err == tfm_to_ltc_codes[x].tfm_code) { return tfm_to_ltc_codes[x].ltc_code; } } return CRYPT_ERROR; } static int init(void **a) { LTC_ARGCHK(a != NULL); *a = XCALLOC(1, sizeof(fp_int)); if (*a == NULL) { return CRYPT_MEM; } fp_init(*a); return CRYPT_OK; } static void deinit(void *a) { LTC_ARGCHKVD(a != NULL); XFREE(a); } static int neg(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_neg(((fp_int*)a), ((fp_int*)b)); return CRYPT_OK; } static int copy(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_copy(a, b); return CRYPT_OK; } static int init_copy(void **a, void *b) { if (init(a) != CRYPT_OK) { return CRYPT_MEM; } return copy(b, *a); } /* ---- trivial ---- */ static int set_int(void *a, ltc_mp_digit b) { LTC_ARGCHK(a != NULL); fp_set(a, b); return CRYPT_OK; } static unsigned long get_int(void *a) { fp_int *A; LTC_ARGCHK(a != NULL); A = a; return A->used > 0 ? A->dp[0] : 0; } static ltc_mp_digit get_digit(void *a, int n) { fp_int *A; LTC_ARGCHK(a != NULL); A = a; return (n >= A->used || n < 0) ? 0 : A->dp[n]; } static int get_digit_count(void *a) { fp_int *A; LTC_ARGCHK(a != NULL); A = a; return A->used; } static int compare(void *a, void *b) { int ret; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); ret = fp_cmp(a, b); switch (ret) { case FP_LT: return LTC_MP_LT; case FP_EQ: return LTC_MP_EQ; case FP_GT: return LTC_MP_GT; } return 0; } static int compare_d(void *a, ltc_mp_digit b) { int ret; LTC_ARGCHK(a != NULL); ret = fp_cmp_d(a, b); switch (ret) { case FP_LT: return LTC_MP_LT; case FP_EQ: return LTC_MP_EQ; case FP_GT: return LTC_MP_GT; } return 0; } static int count_bits(void *a) { LTC_ARGCHK(a != NULL); return fp_count_bits(a); } static int count_lsb_bits(void *a) { LTC_ARGCHK(a != NULL); return fp_cnt_lsb(a); } static int twoexpt(void *a, int n) { LTC_ARGCHK(a != NULL); fp_2expt(a, n); return CRYPT_OK; } /* ---- conversions ---- */ /* read ascii string */ static int read_radix(void *a, const char *b, int radix) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return tfm_to_ltc_error(fp_read_radix(a, (char *)b, radix)); } /* write one */ static int write_radix(void *a, char *b, int radix) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return tfm_to_ltc_error(fp_toradix(a, b, radix)); } /* get size as unsigned char string */ static unsigned long unsigned_size(void *a) { LTC_ARGCHK(a != NULL); return fp_unsigned_bin_size(a); } /* store */ static int unsigned_write(void *a, unsigned char *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_to_unsigned_bin(a, b); return CRYPT_OK; } /* read */ static int unsigned_read(void *a, unsigned char *b, unsigned long len) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_read_unsigned_bin(a, b, len); return CRYPT_OK; } /* add */ static int add(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); fp_add(a, b, c); return CRYPT_OK; } static int addi(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); fp_add_d(a, b, c); return CRYPT_OK; } /* sub */ static int sub(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); fp_sub(a, b, c); return CRYPT_OK; } static int subi(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); fp_sub_d(a, b, c); return CRYPT_OK; } /* mul */ static int mul(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); fp_mul(a, b, c); return CRYPT_OK; } static int muli(void *a, ltc_mp_digit b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); fp_mul_d(a, b, c); return CRYPT_OK; } /* sqr */ static int sqr(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_sqr(a, b); return CRYPT_OK; } /* sqrtmod_prime - NOT SUPPORTED */ /* div */ static int divide(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); return tfm_to_ltc_error(fp_div(a, b, c, d)); } static int div_2(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_div_2(a, b); return CRYPT_OK; } /* modi */ static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) { fp_digit tmp; int err; LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); if ((err = tfm_to_ltc_error(fp_mod_d(a, b, &tmp))) != CRYPT_OK) { return err; } *c = tmp; return CRYPT_OK; } /* gcd */ static int gcd(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); fp_gcd(a, b, c); return CRYPT_OK; } /* lcm */ static int lcm(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); fp_lcm(a, b, c); return CRYPT_OK; } static int addmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return tfm_to_ltc_error(fp_addmod(a,b,c,d)); } static int submod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return tfm_to_ltc_error(fp_submod(a,b,c,d)); } static int mulmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return tfm_to_ltc_error(fp_mulmod(a,b,c,d)); } static int sqrmod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return tfm_to_ltc_error(fp_sqrmod(a,b,c)); } /* invmod */ static int invmod(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return tfm_to_ltc_error(fp_invmod(a, b, c)); } /* setup */ static int montgomery_setup(void *a, void **b) { int err; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); *b = XCALLOC(1, sizeof(fp_digit)); if (*b == NULL) { return CRYPT_MEM; } if ((err = tfm_to_ltc_error(fp_montgomery_setup(a, (fp_digit *)*b))) != CRYPT_OK) { XFREE(*b); } return err; } /* get normalization value */ static int montgomery_normalization(void *a, void *b) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); fp_montgomery_calc_normalization(a, b); return CRYPT_OK; } /* reduce */ static int montgomery_reduce(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); fp_montgomery_reduce(a, b, *((fp_digit *)c)); return CRYPT_OK; } /* clean up */ static void montgomery_deinit(void *a) { XFREE(a); } static int exptmod(void *a, void *b, void *c, void *d) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); LTC_ARGCHK(d != NULL); return tfm_to_ltc_error(fp_exptmod(a,b,c,d)); } static int isprime(void *a, int b, int *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(c != NULL); if (b == 0) { b = LTC_MILLER_RABIN_REPS; } /* if */ *c = (fp_isprime_ex(a, b) == FP_YES) ? LTC_MP_YES : LTC_MP_NO; return CRYPT_OK; } #if defined(LTC_MECC) && defined(LTC_MECC_ACCEL) static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp) { fp_int t1, t2; fp_digit mp; int err, inf; LTC_ARGCHK(P != NULL); LTC_ARGCHK(R != NULL); LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(Mp != NULL); mp = *((fp_digit*)Mp); fp_init(&t1); fp_init(&t2); if (P != R) { fp_copy(P->x, R->x); fp_copy(P->y, R->y); fp_copy(P->z, R->z); } if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* if P is point at infinity >> Result = point at infinity */ ltc_mp.set_int(R->x, 1); ltc_mp.set_int(R->y, 1); ltc_mp.set_int(R->z, 0); return CRYPT_OK; } /* t1 = Z * Z */ fp_sqr(R->z, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* Z = Y * Z */ fp_mul(R->z, R->y, R->z); fp_montgomery_reduce(R->z, modulus, mp); /* Z = 2Z */ fp_add(R->z, R->z, R->z); if (fp_cmp(R->z, modulus) != FP_LT) { fp_sub(R->z, modulus, R->z); } if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ /* T2 = X - T1 */ fp_sub(R->x, &t1, &t2); if (fp_cmp_d(&t2, 0) == LTC_MP_LT) { fp_add(&t2, modulus, &t2); } /* T1 = X + T1 */ fp_add(&t1, R->x, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } /* T2 = T1 * T2 */ fp_mul(&t1, &t2, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* T1 = 2T2 */ fp_add(&t2, &t2, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } /* T1 = T1 + T2 */ fp_add(&t1, &t2, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } } else { /* T2 = T1 * T1 */ fp_sqr(&t1, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* T1 = T2 * a */ fp_mul(&t2, ma, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* T2 = X * X */ fp_sqr(R->x, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* T1 = T1 + T2 */ fp_add(&t1, &t2, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } /* T1 = T1 + T2 */ fp_add(&t1, &t2, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } /* T1 = T1 + T2 */ fp_add(&t1, &t2, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } } /* Y = 2Y */ fp_add(R->y, R->y, R->y); if (fp_cmp(R->y, modulus) != FP_LT) { fp_sub(R->y, modulus, R->y); } /* Y = Y * Y */ fp_sqr(R->y, R->y); fp_montgomery_reduce(R->y, modulus, mp); /* T2 = Y * Y */ fp_sqr(R->y, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* T2 = T2/2 */ if (fp_isodd(&t2)) { fp_add(&t2, modulus, &t2); } fp_div_2(&t2, &t2); /* Y = Y * X */ fp_mul(R->y, R->x, R->y); fp_montgomery_reduce(R->y, modulus, mp); /* X = T1 * T1 */ fp_sqr(&t1, R->x); fp_montgomery_reduce(R->x, modulus, mp); /* X = X - Y */ fp_sub(R->x, R->y, R->x); if (fp_cmp_d(R->x, 0) == FP_LT) { fp_add(R->x, modulus, R->x); } /* X = X - Y */ fp_sub(R->x, R->y, R->x); if (fp_cmp_d(R->x, 0) == FP_LT) { fp_add(R->x, modulus, R->x); } /* Y = Y - X */ fp_sub(R->y, R->x, R->y); if (fp_cmp_d(R->y, 0) == FP_LT) { fp_add(R->y, modulus, R->y); } /* Y = Y * T1 */ fp_mul(R->y, &t1, R->y); fp_montgomery_reduce(R->y, modulus, mp); /* Y = Y - T2 */ fp_sub(R->y, &t2, R->y); if (fp_cmp_d(R->y, 0) == FP_LT) { fp_add(R->y, modulus, R->y); } return CRYPT_OK; } /** Add two ECC points @param P The point to add @param Q The point to add @param R [out] The destination of the double @param modulus The modulus of the field the ECC curve is in @param Mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp) { fp_int t1, t2, x, y, z; fp_digit mp; int err, inf; LTC_ARGCHK(P != NULL); LTC_ARGCHK(Q != NULL); LTC_ARGCHK(R != NULL); LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(Mp != NULL); mp = *((fp_digit*)Mp); fp_init(&t1); fp_init(&t2); fp_init(&x); fp_init(&y); fp_init(&z); if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* P is point at infinity >> Result = Q */ ltc_mp.copy(Q->x, R->x); ltc_mp.copy(Q->y, R->y); ltc_mp.copy(Q->z, R->z); return CRYPT_OK; } if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* Q is point at infinity >> Result = P */ ltc_mp.copy(P->x, R->x); ltc_mp.copy(P->y, R->y); ltc_mp.copy(P->z, R->z); return CRYPT_OK; } /* should we dbl instead? */ fp_sub(modulus, Q->y, &t1); if ( (fp_cmp(P->x, Q->x) == FP_EQ) && (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) && (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) { return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp); } fp_copy(P->x, &x); fp_copy(P->y, &y); fp_copy(P->z, &z); /* if Z is one then these are no-operations */ if (Q->z != NULL) { /* T1 = Z' * Z' */ fp_sqr(Q->z, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* X = X * T1 */ fp_mul(&t1, &x, &x); fp_montgomery_reduce(&x, modulus, mp); /* T1 = Z' * T1 */ fp_mul(Q->z, &t1, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* Y = Y * T1 */ fp_mul(&t1, &y, &y); fp_montgomery_reduce(&y, modulus, mp); } /* T1 = Z*Z */ fp_sqr(&z, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* T2 = X' * T1 */ fp_mul(Q->x, &t1, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* T1 = Z * T1 */ fp_mul(&z, &t1, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* T1 = Y' * T1 */ fp_mul(Q->y, &t1, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* Y = Y - T1 */ fp_sub(&y, &t1, &y); if (fp_cmp_d(&y, 0) == FP_LT) { fp_add(&y, modulus, &y); } /* T1 = 2T1 */ fp_add(&t1, &t1, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } /* T1 = Y + T1 */ fp_add(&t1, &y, &t1); if (fp_cmp(&t1, modulus) != FP_LT) { fp_sub(&t1, modulus, &t1); } /* X = X - T2 */ fp_sub(&x, &t2, &x); if (fp_cmp_d(&x, 0) == FP_LT) { fp_add(&x, modulus, &x); } /* T2 = 2T2 */ fp_add(&t2, &t2, &t2); if (fp_cmp(&t2, modulus) != FP_LT) { fp_sub(&t2, modulus, &t2); } /* T2 = X + T2 */ fp_add(&t2, &x, &t2); if (fp_cmp(&t2, modulus) != FP_LT) { fp_sub(&t2, modulus, &t2); } /* if Z' != 1 */ if (Q->z != NULL) { /* Z = Z * Z' */ fp_mul(&z, Q->z, &z); fp_montgomery_reduce(&z, modulus, mp); } /* Z = Z * X */ fp_mul(&z, &x, &z); fp_montgomery_reduce(&z, modulus, mp); /* T1 = T1 * X */ fp_mul(&t1, &x, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* X = X * X */ fp_sqr(&x, &x); fp_montgomery_reduce(&x, modulus, mp); /* T2 = T2 * x */ fp_mul(&t2, &x, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* T1 = T1 * X */ fp_mul(&t1, &x, &t1); fp_montgomery_reduce(&t1, modulus, mp); /* X = Y*Y */ fp_sqr(&y, &x); fp_montgomery_reduce(&x, modulus, mp); /* X = X - T2 */ fp_sub(&x, &t2, &x); if (fp_cmp_d(&x, 0) == FP_LT) { fp_add(&x, modulus, &x); } /* T2 = T2 - X */ fp_sub(&t2, &x, &t2); if (fp_cmp_d(&t2, 0) == FP_LT) { fp_add(&t2, modulus, &t2); } /* T2 = T2 - X */ fp_sub(&t2, &x, &t2); if (fp_cmp_d(&t2, 0) == FP_LT) { fp_add(&t2, modulus, &t2); } /* T2 = T2 * Y */ fp_mul(&t2, &y, &t2); fp_montgomery_reduce(&t2, modulus, mp); /* Y = T2 - T1 */ fp_sub(&t2, &t1, &y); if (fp_cmp_d(&y, 0) == FP_LT) { fp_add(&y, modulus, &y); } /* Y = Y/2 */ if (fp_isodd(&y)) { fp_add(&y, modulus, &y); } fp_div_2(&y, &y); fp_copy(&x, R->x); fp_copy(&y, R->y); fp_copy(&z, R->z); return CRYPT_OK; } #endif static int set_rand(void *a, int size) { LTC_ARGCHK(a != NULL); fp_rand(a, size); return CRYPT_OK; } const ltc_math_descriptor tfm_desc = { "TomsFastMath", (int)DIGIT_BIT, &init, &init_copy, &deinit, &neg, ©, &set_int, &get_int, &get_digit, &get_digit_count, &compare, &compare_d, &count_bits, &count_lsb_bits, &twoexpt, &read_radix, &write_radix, &unsigned_size, &unsigned_write, &unsigned_read, &add, &addi, &sub, &subi, &mul, &muli, &sqr, NULL, /* TODO: &sqrtmod_prime */ ÷, &div_2, &modi, &gcd, &lcm, &mulmod, &sqrmod, &invmod, &montgomery_setup, &montgomery_normalization, &montgomery_reduce, &montgomery_deinit, &exptmod, &isprime, #ifdef LTC_MECC #ifdef LTC_MECC_FP <c_ecc_fp_mulmod, #else <c_ecc_mulmod, #endif /* LTC_MECC_FP */ #ifdef LTC_MECC_ACCEL &tfm_ecc_projective_add_point, &tfm_ecc_projective_dbl_point, #else <c_ecc_projective_add_point, <c_ecc_projective_dbl_point, #endif /* LTC_MECC_ACCEL */ <c_ecc_map, #ifdef LTC_ECC_SHAMIR #ifdef LTC_MECC_FP <c_ecc_fp_mul2add, #else <c_ecc_mul2add, #endif /* LTC_MECC_FP */ #else NULL, #endif /* LTC_ECC_SHAMIR */ #else NULL, NULL, NULL, NULL, NULL, #endif /* LTC_MECC */ #ifdef LTC_MRSA &rsa_make_key, &rsa_exptmod, #else NULL, NULL, #endif &addmod, &submod, set_rand, }; #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/000077500000000000000000000000001464416617300211375ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/adler32.c000066400000000000000000000050001464416617300225320ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file adler32.c Adler-32 checksum algorithm Written and placed in the public domain by Wei Dai Adapted for libtomcrypt by Steffen Jaeckel */ #ifdef LTC_ADLER32 static const unsigned long s_adler32_base = 65521; void adler32_init(adler32_state *ctx) { LTC_ARGCHKVD(ctx != NULL); ctx->s[0] = 1; ctx->s[1] = 0; } void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length) { unsigned long s1, s2; LTC_ARGCHKVD(ctx != NULL); LTC_ARGCHKVD(input != NULL); s1 = ctx->s[0]; s2 = ctx->s[1]; if (length % 8 != 0) { do { s1 += *input++; s2 += s1; length--; } while (length % 8 != 0); if (s1 >= s_adler32_base) { s1 -= s_adler32_base; } s2 %= s_adler32_base; } while (length > 0) { s1 += input[0]; s2 += s1; s1 += input[1]; s2 += s1; s1 += input[2]; s2 += s1; s1 += input[3]; s2 += s1; s1 += input[4]; s2 += s1; s1 += input[5]; s2 += s1; s1 += input[6]; s2 += s1; s1 += input[7]; s2 += s1; length -= 8; input += 8; if (s1 >= s_adler32_base) { s1 -= s_adler32_base; } s2 %= s_adler32_base; } LTC_ARGCHKVD(s1 < s_adler32_base); LTC_ARGCHKVD(s2 < s_adler32_base); ctx->s[0] = (unsigned short)s1; ctx->s[1] = (unsigned short)s2; } void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size) { unsigned char* h; LTC_ARGCHKVD(ctx != NULL); LTC_ARGCHKVD(hash != NULL); h = hash; switch (size) { default: h[3] = ctx->s[0] & 0x0ff; /* FALLTHROUGH */ case 3: h[2] = (ctx->s[0] >> 8) & 0x0ff; /* FALLTHROUGH */ case 2: h[1] = ctx->s[1] & 0x0ff; /* FALLTHROUGH */ case 1: h[0] = (ctx->s[1] >> 8) & 0x0ff; /* FALLTHROUGH */ case 0: ; } } int adler32_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else const void* in = "libtomcrypt"; const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba }; unsigned char out[4]; adler32_state ctx; adler32_init(&ctx); adler32_update(&ctx, in, XSTRLEN(in)); adler32_finish(&ctx, out, 4); if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base16/000077500000000000000000000000001464416617300222205ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base16/base16_decode.c000066400000000000000000000042041464416617300247500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file base16_decode.c Base16/Hex decode a string. Based on https://stackoverflow.com/a/23898449 Adapted for libtomcrypt by Steffen Jaeckel */ #ifdef LTC_BASE16 /** Base16 decode a string @param in The Base16 string to decode @param inlen The length of the Base16 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base16_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long pos, out_len; unsigned char idx0, idx1; char in0, in1; const unsigned char hashmap[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */ 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */ }; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET; out_len = *outlen * 2; for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) { in0 = in[pos + 0]; in1 = in[pos + 1]; if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET; if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET; idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10; idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10; if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET; if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET; out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1]; } *outlen = pos / 2; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base16/base16_encode.c000066400000000000000000000030201464416617300247550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file base16_encode.c Base16/Hex encode a string, Steffen Jaeckel */ #ifdef LTC_BASE16 /** Base16 encode a buffer @param in The input buffer to encode @param inlen The length of the input buffer @param out [out] The destination of the Base16 encoded data @param outlen [in/out] The max size and resulting size of the encoded data @param options Output 'a-f' on 0 and 'A-F' otherwise. @return CRYPT_OK if successful */ int base16_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, unsigned int options) { unsigned long i, x; const char *alphabet; const char *alphabets[2] = { "0123456789abcdef", "0123456789ABCDEF", }; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* check the sizes */ x = inlen * 2 + 1; if (x < inlen) return CRYPT_OVERFLOW; if (*outlen < x) { *outlen = x; return CRYPT_BUFFER_OVERFLOW; } x--; *outlen = x; /* returning the length without terminating NUL */ if (options == 0) { alphabet = alphabets[0]; } else { alphabet = alphabets[1]; } for (i = 0; i < x; i += 2) { out[i] = alphabet[(in[i/2] >> 4) & 0x0f]; out[i+1] = alphabet[in[i/2] & 0x0f]; } out[x] = '\0'; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base32/000077500000000000000000000000001464416617300222165ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base32/base32_decode.c000066400000000000000000000103371464416617300247500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BASE32 /** Base32 decode a buffer @param in The Base32 data to decode @param inlen The length of the Base32 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD @return CRYPT_OK if successful */ int base32_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, base32_alphabet id) { unsigned long x; int y = 0; ulong64 t = 0; char c; const unsigned char *map; const unsigned char tables[4][43] = { { /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */ 99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/, 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/, 13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/ }, { /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */ 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/, 23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/ }, { /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */ 99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/, 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, 24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/, 2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/ }, { /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */ 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/, 21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/ } }; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(id >= BASE32_RFC4648); LTC_ARGCHK(id <= BASE32_CROCKFORD); /* ignore all trailing = */ while (inlen > 0 && in[inlen-1] == '=') inlen--; /* no input, nothing to do */ if (inlen == 0) { *outlen = 0; return CRYPT_OK; } /* check the size of output buffer */ x = (inlen * 5) / 8; if (*outlen < x) { *outlen = x; return CRYPT_BUFFER_OVERFLOW; } *outlen = x; /* check input data length */ x = inlen % 8; if (x == 1 || x == 3 || x == 6) { return CRYPT_INVALID_PACKET; } map = tables[id]; for (x = 0; x < inlen; x++) { c = in[x]; /* convert to upper case */ if ((c >= 'a') && (c <= 'z')) c -= 32; if (c < '0' || c > 'Z' || map[c-'0'] > 31) { return CRYPT_INVALID_PACKET; } t = (t<<5) | map[c-'0']; if (++y == 8) { *out++ = (unsigned char)((t>>32) & 255); *out++ = (unsigned char)((t>>24) & 255); *out++ = (unsigned char)((t>>16) & 255); *out++ = (unsigned char)((t>> 8) & 255); *out++ = (unsigned char)( t & 255); y = 0; t = 0; } } if (y > 0) { t = t << (5 * (8 - y)); if (y >= 2) *out++ = (unsigned char)((t>>32) & 255); if (y >= 4) *out++ = (unsigned char)((t>>24) & 255); if (y >= 5) *out++ = (unsigned char)((t>>16) & 255); if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255); } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base32/base32_encode.c000066400000000000000000000055071464416617300247650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_BASE32 /** Base32 encode a buffer @param in The input buffer to encode @param inlen The length of the input buffer @param out [out] The destination of the Base32 encoded data @param outlen [in/out] The max size and resulting size of the encoded data @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD @return CRYPT_OK if successful */ int base32_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, base32_alphabet id) { unsigned long i, x; const char *codes; const char *alphabet[4] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */ "0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */ "ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */ "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */ }; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(id >= BASE32_RFC4648); LTC_ARGCHK(id <= BASE32_CROCKFORD); /* check the size of output buffer +1 byte for terminating NUL */ x = (8 * inlen + 4) / 5 + 1; if (*outlen < x) { *outlen = x; return CRYPT_BUFFER_OVERFLOW; } *outlen = x - 1; /* returning the length without terminating NUL */ /* no input, nothing to do */ if (inlen == 0) { *out = '\0'; return CRYPT_OK; } codes = alphabet[id]; x = 5 * (inlen / 5); for (i = 0; i < x; i += 5) { *out++ = codes[(in[0] >> 3) & 0x1F]; *out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F]; *out++ = codes[(in[1] >> 1) & 0x1F]; *out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F]; *out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F]; *out++ = codes[(in[3] >> 2) & 0x1F]; *out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F]; *out++ = codes[in[4] & 0x1F]; in += 5; } if (i < inlen) { unsigned a = in[0]; unsigned b = (i+1 < inlen) ? in[1] : 0; unsigned c = (i+2 < inlen) ? in[2] : 0; unsigned d = (i+3 < inlen) ? in[3] : 0; *out++ = codes[(a >> 3) & 0x1F]; *out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F]; if (i+1 < inlen) { *out++ = codes[(b >> 1) & 0x1F]; *out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F]; } if (i+2 < inlen) { *out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F]; } if (i+3 < inlen) { *out++ = codes[(d >> 2) & 0x1F]; *out++ = codes[((d & 0x3) << 3) & 0x1F]; } } *out = '\0'; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base64/000077500000000000000000000000001464416617300222235ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base64/base64_decode.c000066400000000000000000000212101464416617300247520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file base64_decode.c Compliant base64 code donated by Wayne Scott (wscott@bitmover.com) base64 URL Safe variant (RFC 4648 section 5) by Karel Miko */ #if defined(LTC_BASE64) || defined (LTC_BASE64_URL) /* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32) * 254 - padding character '=' (allowed only at the end) * 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode */ #if defined(LTC_BASE64) static const unsigned char map_base64[256] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; #endif /* LTC_BASE64 */ static const unsigned char map_base64url[] = { #if defined(LTC_BASE64_URL) 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 #endif /* LTC_BASE64_URL */ }; enum { insane = 0, strict = 1, relaxed = 2 }; static int s_base64_decode_internal(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *map, int mode) { unsigned long t, x, y, z; unsigned char c; int g; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); g = 0; /* '=' counter */ for (x = y = z = t = 0; x < inlen; x++) { if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) { continue; /* allow the last byte to be NUL (relaxed+insane) */ } c = map[(unsigned char)in[x]&0xFF]; if (c == 254) { g++; continue; } if (c == 253) { if (mode == strict) { return CRYPT_INVALID_PACKET; } continue; /* allow to ignore white-spaces (relaxed+insane) */ } if (c == 255) { if (mode == insane) { continue; /* allow to ignore invalid garbage (insane) */ } return CRYPT_INVALID_PACKET; } if ((g > 0) && (mode != insane)) { /* we only allow '=' to be at the end (strict+relaxed) */ return CRYPT_INVALID_PACKET; } t = (t<<6)|c; if (++y == 4) { if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW; out[z++] = (unsigned char)((t>>16)&255); out[z++] = (unsigned char)((t>>8)&255); out[z++] = (unsigned char)(t&255); y = t = 0; } } if (y != 0) { if (y == 1) return CRYPT_INVALID_PACKET; if (((y + g) != 4) && (mode == strict) && (map != map_base64url)) return CRYPT_INVALID_PACKET; t = t << (6 * (4 - y)); if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW; if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255); if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255); } *outlen = z; return CRYPT_OK; } #if defined(LTC_BASE64) /** Dangerously relaxed base64 decode a block of memory @param in The base64 data to decode @param inlen The length of the base64 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base64_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { return s_base64_decode_internal(in, inlen, out, outlen, map_base64, insane); } /** Strict base64 decode a block of memory @param in The base64 data to decode @param inlen The length of the base64 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base64_strict_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { return s_base64_decode_internal(in, inlen, out, outlen, map_base64, strict); } /** Sane base64 decode a block of memory @param in The base64 data to decode @param inlen The length of the base64 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base64_sane_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { return s_base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed); } #endif /* LTC_BASE64 */ #if defined(LTC_BASE64_URL) /** Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) decode a block of memory @param in The base64 data to decode @param inlen The length of the base64 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base64url_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, insane); } /** Strict base64 (URL Safe, RFC 4648 section 5) decode a block of memory @param in The base64 data to decode @param inlen The length of the base64 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base64url_strict_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, strict); } /** Sane base64 (URL Safe, RFC 4648 section 5) decode a block of memory @param in The base64 data to decode @param inlen The length of the base64 data @param out [out] The destination of the binary decoded data @param outlen [in/out] The max size and resulting size of the decoded data @return CRYPT_OK if successful */ int base64url_sane_decode(const char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed); } #endif /* LTC_BASE64_URL */ #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/base64/base64_encode.c000066400000000000000000000114041464416617300247700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file base64_encode.c Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com) base64 URL Safe variant (RFC 4648 section 5) by Karel Miko */ #if defined(LTC_BASE64) || defined (LTC_BASE64_URL) #if defined(LTC_BASE64) static const char * const codes_base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #endif /* LTC_BASE64 */ #if defined(LTC_BASE64_URL) static const char * const codes_base64url = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; #endif /* LTC_BASE64_URL */ enum mode { nopad = 0, pad = 1, lf = 2, cr = 4, ssh = 8, crlf = lf | cr, }; static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, const char *codes, unsigned int mode) { unsigned long i, len2, leven, linelen; char *p; LTC_ARGCHK(outlen != NULL); linelen = (mode & ssh) ? 72 : 64; /* valid output size ? */ len2 = 4 * ((inlen + 2) / 3); if ((mode & crlf) == lf) { len2 += len2 / linelen; } else if ((mode & crlf) == crlf) { len2 += (len2 / linelen) * 2; } if (*outlen < len2 + 1) { *outlen = len2 + 1; return CRYPT_BUFFER_OVERFLOW; } LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); if ((void*)in == out) { return CRYPT_INVALID_ARG; } p = out; leven = 3*(inlen / 3); for (i = 0; i < leven; i += 3) { *p++ = codes[(in[0] >> 2) & 0x3F]; *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F]; *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F]; *p++ = codes[in[2] & 0x3F]; in += 3; if ((p - out) % linelen == 0) { if (mode & cr) *p++ = '\r'; if (mode & lf) *p++ = '\n'; } } /* Pad it if necessary... */ if (i < inlen) { unsigned a = in[0]; unsigned b = (i+1 < inlen) ? in[1] : 0; *p++ = codes[(a >> 2) & 0x3F]; *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]; if (mode & pad) { *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; *p++ = '='; } else { if (i+1 < inlen) *p++ = codes[(((b & 0xf) << 2)) & 0x3F]; } } /* append a NULL byte */ *p = '\0'; /* return ok */ *outlen = (unsigned long)(p - out); /* the length without terminating NUL */ return CRYPT_OK; } #if defined(LTC_BASE64) /** base64 Encode a buffer (NUL terminated) @param in The input buffer to encode @param inlen The length of the input buffer @param out [out] The destination of the base64 encoded data @param outlen [in/out] The max size and resulting size @return CRYPT_OK if successful */ int base64_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen) { return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad); } /** base64 Encode a buffer for PEM output (NUL terminated with line-break at 64 chars) @param in The input buffer to encode @param inlen The length of the input buffer @param out [out] The destination of the base64 encoded data @param outlen [in/out] The max size and resulting size @param flags \ref base64_pem_flags @return CRYPT_OK if successful */ int base64_encode_pem(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen, unsigned int flags) { int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf; int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0; return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf); } #endif /* LTC_BASE64 */ #if defined(LTC_BASE64_URL) /** base64 (URL Safe, RFC 4648 section 5) Encode a buffer (NUL terminated) @param in The input buffer to encode @param inlen The length of the input buffer @param out [out] The destination of the base64 encoded data @param outlen [in/out] The max size and resulting size @return CRYPT_OK if successful */ int base64url_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen) { return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad); } int base64url_strict_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen) { return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad); } #endif /* LTC_BASE64_URL */ #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/bcrypt/000077500000000000000000000000001464416617300224425ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/bcrypt/bcrypt.c000066400000000000000000000132631464416617300241160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file bcrypt.c bcrypt pbkdf, Steffen Jaeckel */ #ifdef LTC_BCRYPT #define BCRYPT_WORDS 8 #define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) static int s_bcrypt_hash(const unsigned char *pt, const unsigned char *pass, unsigned long passlen, const unsigned char *salt, unsigned long saltlen, unsigned char *out, unsigned long *outlen) { symmetric_key key; int err, n; ulong32 ct[BCRYPT_WORDS]; if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) { return err; } for (n = 0; n < 64; ++n) { if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) { return err; } if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) { return err; } } for (n = 0; n < BCRYPT_WORDS; ++n) { LOAD32H(ct[n], &pt[n*4]); } for (n = 0; n < 64; ++n) { blowfish_enc(ct, BCRYPT_WORDS/2, &key); } for (n = 0; n < BCRYPT_WORDS; ++n) { STORE32L(ct[n], &out[4 * n]); } *outlen = sizeof(ct); #ifdef LTC_CLEAN_STACK zeromem(&key, sizeof(key)); zeromem(ct, sizeof(ct)); #endif return CRYPT_OK; } static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen, const unsigned char *salt, unsigned long saltlen, unsigned char *out, unsigned long *outlen) { const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite"; return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen); } /** Compatible to bcrypt_pbkdf() as provided in OpenBSD @param password The input password (or key) @param password_len The length of the password (octets) @param salt The salt (or nonce) @param salt_len The length of the salt (octets) @param rounds # of iterations desired [read specs for more] @param hash_idx The index of the hash desired @param out [out] The destination for this algorithm @param outlen [in/out] The desired size of the algorithm output @return CRYPT_OK if successful */ int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, const unsigned char *salt, unsigned long salt_len, unsigned int rounds, int hash_idx, unsigned char *out, unsigned long *outlen) { int err; ulong32 blkno; unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds; unsigned char *buf[3], blkbuf[4]; unsigned char *hashed_pass; LTC_ARGCHK(secret != NULL); LTC_ARGCHK(salt != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) { return CRYPT_INVALID_ARG; } /* test hash IDX */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* set default value for rounds if not given */ if (rounds == 0) { used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS; } else { used_rounds = rounds; } buf[0] = XMALLOC(MAXBLOCKSIZE * 3); hashed_pass = XMALLOC(MAXBLOCKSIZE); if (buf[0] == NULL || hashed_pass == NULL) { if (hashed_pass != NULL) { XFREE(hashed_pass); } if (buf[0] != NULL) { XFREE(buf[0]); } return CRYPT_MEM; } /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ buf[1] = buf[0] + MAXBLOCKSIZE; buf[2] = buf[1] + MAXBLOCKSIZE; step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE; steps = (*outlen + step_size - 1) / step_size; hashed_pass_len = MAXBLOCKSIZE; if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) { goto LBL_ERR; } left = *outlen; blkno = 0; while (left != 0) { /* increment and store current block number */ ++blkno; STORE32H(blkno, blkbuf); /* process block number blkno */ zeromem(buf[0], MAXBLOCKSIZE*2); x = MAXBLOCKSIZE; if ((err = hash_memory_multi(hash_idx, buf[0], &x, salt, salt_len, blkbuf, 4uL, LTC_NULL)) != CRYPT_OK) { goto LBL_ERR; } y = MAXBLOCKSIZE; if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { goto LBL_ERR; } XMEMCPY(buf[2], buf[1], y); /* now compute repeated and XOR it in buf[2] */ for (itts = 1; itts < used_rounds; ++itts) { x = MAXBLOCKSIZE; if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) { goto LBL_ERR; } y = MAXBLOCKSIZE; if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { goto LBL_ERR; } for (x = 0; x < y; x++) { buf[2][x] ^= buf[1][x]; } } /* now emit upto `steps` bytes of buf[2] to output */ steps = MIN(steps, left); for (y = 0; y < steps; ++y) { dest = y * step_size + (blkno - 1); if (dest >= *outlen) break; out[dest] = buf[2][y]; } left -= y; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf[0], MAXBLOCKSIZE*3); zeromem(hashed_pass, MAXBLOCKSIZE); #endif XFREE(hashed_pass); XFREE(buf[0]); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/burn_stack.c000066400000000000000000000007111464416617300234350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file burn_stack.c Burn stack, Tom St Denis */ /** Burn some stack memory @param len amount of stack to burn in bytes */ void burn_stack(unsigned long len) { unsigned char buf[32]; zeromem(buf, sizeof(buf)); if (len > (unsigned long)sizeof(buf)) { burn_stack(len - sizeof(buf)); } } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/compare_testvector.c000066400000000000000000000044071464416617300252200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file compare_testvector.c Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel */ #if defined(LTC_TEST) && defined(LTC_TEST_DBG) static void s_print_hex(const char* what, const void* v, const unsigned long l) { const unsigned char* p = v; unsigned long x, y = 0, z; fprintf(stderr, "%s contents: \n", what); for (x = 0; x < l; ) { fprintf(stderr, "%02X ", p[x]); if (!(++x % 16) || x == l) { if((x % 16) != 0) { z = 16 - (x % 16); if(z >= 8) fprintf(stderr, " "); for (; z != 0; --z) { fprintf(stderr, " "); } } fprintf(stderr, " | "); for(; y < x; y++) { if((y % 8) == 0) fprintf(stderr, " "); if(isgraph(p[y])) fprintf(stderr, "%c", p[y]); else fprintf(stderr, "."); } fprintf(stderr, "\n"); } else if((x % 8) == 0) { fprintf(stderr, " "); } } } #endif /** Compare two test-vectors @param is The data as it is @param is_len The length of is @param should The data as it should @param should_len The length of should @param what The type of the data @param which The iteration count @return 0 on equality, -1 or 1 on difference */ int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which) { int res = 0; if(is_len != should_len) { res = is_len > should_len ? -1 : 1; } else { res = XMEMCMP(is, should, is_len); } #if defined(LTC_TEST) && defined(LTC_TEST_DBG) if (res != 0) { fprintf(stderr, "Testvector #%i(0x%x) of %s failed:\n", which, which, what); s_print_hex("SHOULD", should, should_len); s_print_hex("IS ", is, is_len); #if LTC_TEST_DBG > 1 } else { fprintf(stderr, "Testvector #%i(0x%x) of %s passed!\n", which, which, what); #endif } #else LTC_UNUSED_PARAM(which); LTC_UNUSED_PARAM(what); #endif return res; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/copy_or_zeromem.c000066400000000000000000000026021464416617300245130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file copy_or_zeromem.c Either copy or zero a block of memory in constant time, Steffen Jaeckel */ /** Either copy or zero a block of memory in constant time @param src The source where to read from @param dest The destination where to write to @param len The length of the area to process (octets) @param coz Copy (on 0) Or Zero (> 0) */ void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz) { unsigned long y; #ifdef LTC_FAST unsigned long z; LTC_FAST_TYPE fastMask = ~(LTC_FAST_TYPE)0; /* initialize fastMask at all ones */ #endif unsigned char mask = 0xff; /* initialize mask at all ones */ LTC_ARGCHKVD(src != NULL); LTC_ARGCHKVD(dest != NULL); if (coz != 0) coz = 1; y = 0; mask *= 1 - coz; /* mask = ( coz ? 0 : 0xff ) */ #ifdef LTC_FAST fastMask *= 1 - coz; if (len & ~15) { for (; y < (len & ~15); y += 16) { for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&dest[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&src[y+z])) & fastMask; } } } #endif for (; y < len; y++) { dest[y] = src[y] & mask; } #ifdef LTC_CLEAN_STACK #ifdef LTC_FAST fastMask = 0; #endif mask = 0; #endif } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crc32.c000066400000000000000000000221401464416617300222160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crc32.c CRC-32 checksum algorithm Written and placed in the public domain by Wei Dai Adapted for libtomcrypt by Steffen Jaeckel */ #ifdef LTC_CRC32 static const ulong32 CRC32_NEGL = 0xffffffffUL; #if defined(ENDIAN_LITTLE) #define CRC32_INDEX(c) (c & 0xff) #define CRC32_SHIFTED(c) (c >> 8) #elif defined(ENDIAN_BIG) #define CRC32_INDEX(c) (c >> 24) #define CRC32_SHIFTED(c) (c << 8) #else #error The existing CRC32 implementation only works properly when the endianness of the target platform is known. #endif /* Table of CRC-32's of all single byte values (made by makecrc.c) */ static const ulong32 crc32_m_tab[] = { #if defined(ENDIAN_LITTLE) 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL #else 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, 0x8def022dL #endif }; void crc32_init(crc32_state *ctx) { LTC_ARGCHKVD(ctx != NULL); ctx->crc = CRC32_NEGL; } void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length) { ulong32 crc; LTC_ARGCHKVD(ctx != NULL); LTC_ARGCHKVD(input != NULL); crc = ctx->crc; while (length--) { crc = crc32_m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc); } ctx->crc = crc; } void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size) { unsigned long i; unsigned char* h; ulong32 crc; LTC_ARGCHKVD(ctx != NULL); LTC_ARGCHKVD(hash != NULL); h = hash; crc = ctx->crc; crc ^= CRC32_NEGL; if (size > 4) size = 4; for (i = 0; i < size; i++) { h[i] = ((unsigned char*)&(crc))[size-i-1]; } } int crc32_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else const void* in = "libtomcrypt"; const unsigned char crc32[] = { 0xb3, 0x73, 0x76, 0xef }; unsigned char out[4]; crc32_state ctx; crc32_init(&ctx); crc32_update(&ctx, in, XSTRLEN(in)); crc32_finish(&ctx, out, 4); if (compare_testvector(crc32, 4, out, 4, "CRC32", 0)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/000077500000000000000000000000001464416617300223005ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt.c000066400000000000000000000245321464416617300236130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt.c Build strings, Tom St Denis */ #define NAME_VALUE(s) #s"="NAME(s) #define NAME(s) #s const char *crypt_build_settings = "LibTomCrypt " SCRYPT " (www.libtom.net)\n" "LibTomCrypt is public domain software.\n" #if defined(INCLUDE_BUILD_DATE) "Built on " __DATE__ " at " __TIME__ "\n" #endif "\n\nEndianness: " #if defined(ENDIAN_NEUTRAL) "neutral/" #endif #if defined(ENDIAN_LITTLE) "little" #elif defined(ENDIAN_BIG) "big" #endif #if defined(ENDIAN_32BITWORD) " (32-bit words)\n" #elif defined(ENDIAN_64BITWORD) " (64-bit words)\n" #else " (no wordsize defined)\n" #endif "Clean stack: " #if defined(LTC_CLEAN_STACK) "enabled\n" #else "disabled\n" #endif "\nCiphers built-in:\n" #if defined(LTC_BLOWFISH) " Blowfish\n" #endif #if defined(LTC_RC2) " RC2\n" #endif #if defined(LTC_RC5) " RC5\n" #endif #if defined(LTC_RC6) " RC6\n" #endif #if defined(LTC_SAFERP) " Safer+\n" #endif #if defined(LTC_SAFER) " Safer\n" #endif #if defined(LTC_RIJNDAEL) " Rijndael\n" #endif #if defined(LTC_XTEA) " XTEA\n" #endif #if defined(LTC_TWOFISH) " Twofish " #if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) "(small, tables, all_tables)\n" #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) "(small, tables)\n" #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES) "(small, all_tables)\n" #elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) "(tables, all_tables)\n" #elif defined(LTC_TWOFISH_SMALL) "(small)\n" #elif defined(LTC_TWOFISH_TABLES) "(tables)\n" #elif defined(LTC_TWOFISH_ALL_TABLES) "(all_tables)\n" #else "\n" #endif #endif #if defined(LTC_DES) " DES\n" #endif #if defined(LTC_CAST5) " CAST5\n" #endif #if defined(LTC_NOEKEON) " Noekeon\n" #endif #if defined(LTC_SKIPJACK) " Skipjack\n" #endif #if defined(LTC_KHAZAD) " Khazad\n" #endif #if defined(LTC_ANUBIS) " Anubis " #endif #if defined(LTC_ANUBIS_TWEAK) " (tweaked)" #endif "\n" #if defined(LTC_KSEED) " KSEED\n" #endif #if defined(LTC_KASUMI) " KASUMI\n" #endif #if defined(LTC_MULTI2) " MULTI2\n" #endif #if defined(LTC_CAMELLIA) " Camellia\n" #endif #if defined(LTC_IDEA) " IDEA\n" #endif #if defined(LTC_SERPENT) " Serpent\n" #endif #if defined(LTC_TEA) " TEA\n" #endif "Stream ciphers built-in:\n" #if defined(LTC_CHACHA) " ChaCha\n" #endif #if defined(LTC_SALSA20) " Salsa20\n" #endif #if defined(LTC_XSALSA20) " XSalsa20\n" #endif #if defined(LTC_SOSEMANUK) " Sosemanuk\n" #endif #if defined(LTC_RABBIT) " Rabbit\n" #endif #if defined(LTC_RC4_STREAM) " RC4\n" #endif #if defined(LTC_SOBER128_STREAM) " SOBER128\n" #endif "\nHashes built-in:\n" #if defined(LTC_SHA3) " SHA3\n" #endif #if defined(LTC_KECCAK) " KECCAK\n" #endif #if defined(LTC_SHA512) " SHA-512\n" #endif #if defined(LTC_SHA384) " SHA-384\n" #endif #if defined(LTC_SHA512_256) " SHA-512/256\n" #endif #if defined(LTC_SHA256) " SHA-256\n" #endif #if defined(LTC_SHA512_224) " SHA-512/224\n" #endif #if defined(LTC_SHA224) " SHA-224\n" #endif #if defined(LTC_TIGER) " TIGER\n" #endif #if defined(LTC_SHA1) " SHA1\n" #endif #if defined(LTC_MD5) " MD5\n" #endif #if defined(LTC_MD4) " MD4\n" #endif #if defined(LTC_MD2) " MD2\n" #endif #if defined(LTC_RIPEMD128) " RIPEMD128\n" #endif #if defined(LTC_RIPEMD160) " RIPEMD160\n" #endif #if defined(LTC_RIPEMD256) " RIPEMD256\n" #endif #if defined(LTC_RIPEMD320) " RIPEMD320\n" #endif #if defined(LTC_WHIRLPOOL) " WHIRLPOOL\n" #endif #if defined(LTC_BLAKE2S) " BLAKE2S\n" #endif #if defined(LTC_BLAKE2B) " BLAKE2B\n" #endif #if defined(LTC_CHC_HASH) " CHC_HASH\n" #endif "\nBlock Chaining Modes:\n" #if defined(LTC_CFB_MODE) " CFB\n" #endif #if defined(LTC_OFB_MODE) " OFB\n" #endif #if defined(LTC_ECB_MODE) " ECB\n" #endif #if defined(LTC_CBC_MODE) " CBC\n" #endif #if defined(LTC_CTR_MODE) " CTR\n" #endif #if defined(LTC_LRW_MODE) " LRW" #if defined(LTC_LRW_TABLES) " (tables) " #endif "\n" #endif #if defined(LTC_F8_MODE) " F8\n" #endif #if defined(LTC_XTS_MODE) " XTS\n" #endif "\nMACs:\n" #if defined(LTC_HMAC) " HMAC\n" #endif #if defined(LTC_OMAC) " OMAC\n" #endif #if defined(LTC_PMAC) " PMAC\n" #endif #if defined(LTC_PELICAN) " PELICAN\n" #endif #if defined(LTC_XCBC) " XCBC\n" #endif #if defined(LTC_F9_MODE) " F9\n" #endif #if defined(LTC_POLY1305) " POLY1305\n" #endif #if defined(LTC_BLAKE2SMAC) " BLAKE2S MAC\n" #endif #if defined(LTC_BLAKE2BMAC) " BLAKE2B MAC\n" #endif "\nENC + AUTH modes:\n" #if defined(LTC_EAX_MODE) " EAX\n" #endif #if defined(LTC_OCB_MODE) " OCB\n" #endif #if defined(LTC_OCB3_MODE) " OCB3\n" #endif #if defined(LTC_CCM_MODE) " CCM\n" #endif #if defined(LTC_GCM_MODE) " GCM" #if defined(LTC_GCM_TABLES) " (tables) " #endif #if defined(LTC_GCM_TABLES_SSE2) " (SSE2) " #endif "\n" #endif #if defined(LTC_CHACHA20POLY1305_MODE) " CHACHA20POLY1305\n" #endif "\nPRNG:\n" #if defined(LTC_YARROW) " Yarrow ("NAME_VALUE(LTC_YARROW_AES)")\n" #endif #if defined(LTC_SPRNG) " SPRNG\n" #endif #if defined(LTC_RC4) " RC4\n" #endif #if defined(LTC_CHACHA20_PRNG) " ChaCha20\n" #endif #if defined(LTC_FORTUNA) " Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", " #if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED) "LTC_FORTUNA_RESEED_RATELIMIT_TIMED" #else "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD) #endif #if defined(LTC_FORTUNA_USE_ENCRYPT_ONLY) ", LTC_FORTUNA_USE_ENCRYPT_ONLY" #endif ")\n" #endif #if defined(LTC_SOBER128) " SOBER128\n" #endif #if defined(LTC_WIN32_BCRYPT) " WIN32_BCRYPT\n" #endif "\nPK Crypto:\n" #if defined(LTC_MRSA) " RSA" #if defined(LTC_RSA_BLINDING) && defined(LTC_RSA_CRT_HARDENING) " (with blinding and CRT hardening)" #elif defined(LTC_RSA_BLINDING) " (with blinding)" #elif defined(LTC_RSA_CRT_HARDENING) " (with CRT hardening)" #endif "\n" #endif #if defined(LTC_MDH) " DH\n" #endif #if defined(LTC_MECC) " ECC" #if defined(LTC_ECC_TIMING_RESISTANT) " (with blinding)" #endif "\n" #endif #if defined(LTC_MDSA) " DSA\n" #endif #if defined(LTC_CURVE25519) #if defined(LTC_CURVE25519) " Ed25519\n" #endif #if defined(LTC_CURVE25519) " X25519\n" #endif #endif #if defined(LTC_PK_MAX_RETRIES) " "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n" #endif "\nMPI (Math):\n" #if defined(LTC_MPI) " LTC_MPI\n" #endif #if defined(LTM_DESC) " LTM_DESC\n" #endif #if defined(TFM_DESC) " TFM_DESC\n" #endif #if defined(GMP_DESC) " GMP_DESC\n" #endif #if defined(LTC_MILLER_RABIN_REPS) " "NAME_VALUE(LTC_MILLER_RABIN_REPS)"\n" #endif "\nCompiler:\n" #if defined(_WIN64) " WIN64 platform detected.\n" #elif defined(_WIN32) " WIN32 platform detected.\n" #endif #if defined(__CYGWIN__) " CYGWIN Detected.\n" #endif #if defined(__DJGPP__) " DJGPP Detected.\n" #endif #if defined(_MSC_VER) " MSVC compiler detected.\n" #endif #if defined(__clang_version__) " Clang compiler " __clang_version__ ".\n" #elif defined(INTEL_CC) " Intel C Compiler " __VERSION__ ".\n" #elif defined(__GNUC__) /* clang and icc also define __GNUC__ */ " GCC compiler " __VERSION__ ".\n" #endif #if defined(__x86_64__) " x86-64 detected.\n" #endif #if defined(LTC_PPC32) " PPC32 detected.\n" #endif "\nVarious others: " #if defined(ARGTYPE) " " NAME_VALUE(ARGTYPE) " " #endif #if defined(LTC_ADLER32) " ADLER32 " #endif #if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1) " AES-NI " #endif #if defined(LTC_BASE64) " BASE64 " #endif #if defined(LTC_BASE64_URL) " BASE64-URL-SAFE " #endif #if defined(LTC_BASE32) " BASE32 " #endif #if defined(LTC_BASE16) " BASE16 " #endif #if defined(LTC_BCRYPT) " BCRYPT " " " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " " #endif #if defined(LTC_CRC32) " CRC32 " #endif #if defined(LTC_DER) " DER " " " NAME_VALUE(LTC_DER_MAX_RECURSION) " " #endif #if defined(LTC_PKCS_1) " PKCS#1 " #endif #if defined(LTC_PKCS_5) " PKCS#5 " #endif #if defined(LTC_PKCS_8) " PKCS#8 " #endif #if defined(LTC_PKCS_12) " PKCS#12 " #endif #if defined(LTC_PADDING) " PADDING " #endif #if defined(LTC_HKDF) " HKDF " #endif #if defined(LTC_PBES) " PBES1 " " PBES2 " #endif #if defined(LTC_SSH) " SSH " #endif #if defined(LTC_DEVRANDOM) " LTC_DEVRANDOM " #endif #if defined(LTC_TRY_URANDOM_FIRST) " LTC_TRY_URANDOM_FIRST " #endif #if defined(LTC_RNG_GET_BYTES) " LTC_RNG_GET_BYTES " #endif #if defined(LTC_RNG_MAKE_PRNG) " LTC_RNG_MAKE_PRNG " #endif #if defined(LTC_PRNG_ENABLE_LTC_RNG) " LTC_PRNG_ENABLE_LTC_RNG " #endif #if defined(LTC_HASH_HELPERS) " LTC_HASH_HELPERS " #endif #if defined(LTC_VALGRIND) " LTC_VALGRIND " #endif #if defined(LTC_TEST) " LTC_TEST " #endif #if defined(LTC_TEST_DBG) " " NAME_VALUE(LTC_TEST_DBG) " " #endif #if defined(LTC_TEST_EXT) " LTC_TEST_EXT " #endif #if defined(LTC_SMALL_CODE) " LTC_SMALL_CODE " #endif #if defined(LTC_NO_FILE) " LTC_NO_FILE " #endif #if defined(LTC_FILE_READ_BUFSIZE) " " NAME_VALUE(LTC_FILE_READ_BUFSIZE) " " #endif #if defined(LTC_FAST) " LTC_FAST " #endif #if defined(LTC_NO_FAST) " LTC_NO_FAST " #endif #if defined(LTC_NO_BSWAP) " LTC_NO_BSWAP " #endif #if defined(LTC_NO_ASM) " LTC_NO_ASM " #endif #if defined(LTC_ROx_BUILTIN) " LTC_ROx_BUILTIN " #elif defined(LTC_ROx_ASM) " LTC_ROx_ASM " #if defined(LTC_NO_ROLC) " LTC_NO_ROLC " #endif #endif #if defined(LTC_NO_TEST) " LTC_NO_TEST " #endif #if defined(LTC_NO_TABLES) " LTC_NO_TABLES " #endif #if defined(LTC_PTHREAD) " LTC_PTHREAD " #endif #if defined(LTC_EASY) " LTC_EASY " #endif #if defined(LTC_MECC_ACCEL) " LTC_MECC_ACCEL " #endif #if defined(LTC_MECC_FP) " LTC_MECC_FP " #endif #if defined(LTC_ECC_SHAMIR) " LTC_ECC_SHAMIR " #endif #if defined(LTC_CLOCK_GETTIME) " LTC_CLOCK_GETTIME " #endif "\n" ; optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_argchk.c000066400000000000000000000006101464416617300251210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_argchk.c Perform argument checking, Tom St Denis */ #if (ARGTYPE == 0) void crypt_argchk(const char *v, const char *s, int d) { fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n", v, d, s); abort(); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c000066400000000000000000000005141464416617300273750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_cipher_descriptor.c Stores the cipher descriptor table, Tom St Denis */ const struct ltc_cipher_descriptor *cipher_descriptor[TAB_SIZE]; LTC_MUTEX_GLOBAL(ltc_cipher_mutex) optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c000066400000000000000000000011671464416617300270160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_cipher_is_valid.c Determine if cipher is valid, Tom St Denis */ /* Test if a cipher index is valid @param idx The index of the cipher to search for @return CRYPT_OK if valid */ int cipher_is_valid(int idx) { LTC_MUTEX_LOCK(<c_cipher_mutex); if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx] == NULL) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_INVALID_CIPHER; } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_constants.c000066400000000000000000000161521464416617300257060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_constants.c Make various constants available to dynamic languages like Python - Larry Bugbee, February 2013 LB - Dec 2013 - revised to include compiler define options LB - Mar 2014 - added endianness and word size */ typedef struct { const char *name; const int value; } crypt_constant; #define C_STRINGIFY(s) { #s, s } static const crypt_constant s_crypt_constants[] = { C_STRINGIFY(CRYPT_OK), C_STRINGIFY(CRYPT_ERROR), C_STRINGIFY(CRYPT_NOP), C_STRINGIFY(CRYPT_INVALID_KEYSIZE), C_STRINGIFY(CRYPT_INVALID_ROUNDS), C_STRINGIFY(CRYPT_FAIL_TESTVECTOR), C_STRINGIFY(CRYPT_BUFFER_OVERFLOW), C_STRINGIFY(CRYPT_INVALID_PACKET), C_STRINGIFY(CRYPT_INVALID_PRNGSIZE), C_STRINGIFY(CRYPT_ERROR_READPRNG), C_STRINGIFY(CRYPT_INVALID_CIPHER), C_STRINGIFY(CRYPT_INVALID_HASH), C_STRINGIFY(CRYPT_INVALID_PRNG), C_STRINGIFY(CRYPT_MEM), C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH), C_STRINGIFY(CRYPT_PK_NOT_PRIVATE), C_STRINGIFY(CRYPT_INVALID_ARG), C_STRINGIFY(CRYPT_FILE_NOTFOUND), C_STRINGIFY(CRYPT_PK_INVALID_TYPE), C_STRINGIFY(CRYPT_OVERFLOW), C_STRINGIFY(CRYPT_PK_ASN1_ERROR), C_STRINGIFY(CRYPT_INPUT_TOO_LONG), C_STRINGIFY(CRYPT_PK_INVALID_SIZE), C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE), C_STRINGIFY(CRYPT_PK_INVALID_PADDING), C_STRINGIFY(CRYPT_HASH_OVERFLOW), C_STRINGIFY(PK_PUBLIC), C_STRINGIFY(PK_PRIVATE), C_STRINGIFY(LTC_ENCRYPT), C_STRINGIFY(LTC_DECRYPT), #ifdef LTC_PKCS_1 {"LTC_PKCS_1", 1}, /* Block types */ C_STRINGIFY(LTC_PKCS_1_EMSA), C_STRINGIFY(LTC_PKCS_1_EME), /* Padding types */ C_STRINGIFY(LTC_PKCS_1_V1_5), C_STRINGIFY(LTC_PKCS_1_OAEP), C_STRINGIFY(LTC_PKCS_1_PSS), C_STRINGIFY(LTC_PKCS_1_V1_5_NA1), #else {"LTC_PKCS_1", 0}, #endif #ifdef LTC_PADDING {"LTC_PADDING", 1}, C_STRINGIFY(LTC_PAD_PKCS7), #ifdef LTC_RNG_GET_BYTES C_STRINGIFY(LTC_PAD_ISO_10126), #endif C_STRINGIFY(LTC_PAD_ANSI_X923), C_STRINGIFY(LTC_PAD_ONE_AND_ZERO), C_STRINGIFY(LTC_PAD_ZERO), C_STRINGIFY(LTC_PAD_ZERO_ALWAYS), #else {"LTC_PADDING", 0}, #endif #ifdef LTC_MRSA {"LTC_MRSA", 1}, #else {"LTC_MRSA", 0}, #endif #ifdef LTC_MECC {"LTC_MECC", 1}, C_STRINGIFY(ECC_BUF_SIZE), C_STRINGIFY(ECC_MAXSIZE), #else {"LTC_MECC", 0}, #endif #ifdef LTC_MDSA {"LTC_MDSA", 1}, C_STRINGIFY(LTC_MDSA_DELTA), C_STRINGIFY(LTC_MDSA_MAX_GROUP), C_STRINGIFY(LTC_MDSA_MAX_MODULUS), #else {"LTC_MDSA", 0}, #endif #ifdef LTC_MILLER_RABIN_REPS C_STRINGIFY(LTC_MILLER_RABIN_REPS), #endif #ifdef LTC_DER /* DER handling */ {"LTC_DER", 1}, C_STRINGIFY(LTC_ASN1_EOL), C_STRINGIFY(LTC_ASN1_BOOLEAN), C_STRINGIFY(LTC_ASN1_INTEGER), C_STRINGIFY(LTC_ASN1_SHORT_INTEGER), C_STRINGIFY(LTC_ASN1_BIT_STRING), C_STRINGIFY(LTC_ASN1_OCTET_STRING), C_STRINGIFY(LTC_ASN1_NULL), C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER), C_STRINGIFY(LTC_ASN1_IA5_STRING), C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING), C_STRINGIFY(LTC_ASN1_UTF8_STRING), C_STRINGIFY(LTC_ASN1_UTCTIME), C_STRINGIFY(LTC_ASN1_CHOICE), C_STRINGIFY(LTC_ASN1_SEQUENCE), C_STRINGIFY(LTC_ASN1_SET), C_STRINGIFY(LTC_ASN1_SETOF), C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING), C_STRINGIFY(LTC_ASN1_TELETEX_STRING), C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME), C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE), C_STRINGIFY(LTC_DER_MAX_RECURSION), #else {"LTC_DER", 0}, #endif #ifdef LTC_CTR_MODE {"LTC_CTR_MODE", 1}, C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN), C_STRINGIFY(CTR_COUNTER_BIG_ENDIAN), C_STRINGIFY(LTC_CTR_RFC3686), #else {"LTC_CTR_MODE", 0}, #endif #ifdef LTC_GCM_MODE C_STRINGIFY(LTC_GCM_MODE_IV), C_STRINGIFY(LTC_GCM_MODE_AAD), C_STRINGIFY(LTC_GCM_MODE_TEXT), #endif C_STRINGIFY(LTC_MP_LT), C_STRINGIFY(LTC_MP_EQ), C_STRINGIFY(LTC_MP_GT), C_STRINGIFY(LTC_MP_NO), C_STRINGIFY(LTC_MP_YES), C_STRINGIFY(MAXBLOCKSIZE), C_STRINGIFY(TAB_SIZE), C_STRINGIFY(ARGTYPE), #ifdef LTM_DESC {"LTM_DESC", 1}, #else {"LTM_DESC", 0}, #endif #ifdef TFM_DESC {"TFM_DESC", 1}, #else {"TFM_DESC", 0}, #endif #ifdef GMP_DESC {"GMP_DESC", 1}, #else {"GMP_DESC", 0}, #endif #ifdef LTC_FAST {"LTC_FAST", 1}, #else {"LTC_FAST", 0}, #endif #ifdef LTC_NO_FILE {"LTC_NO_FILE", 1}, #else {"LTC_NO_FILE", 0}, #endif #ifdef ENDIAN_LITTLE {"ENDIAN_LITTLE", 1}, #else {"ENDIAN_LITTLE", 0}, #endif #ifdef ENDIAN_BIG {"ENDIAN_BIG", 1}, #else {"ENDIAN_BIG", 0}, #endif #ifdef ENDIAN_32BITWORD {"ENDIAN_32BITWORD", 1}, #else {"ENDIAN_32BITWORD", 0}, #endif #ifdef ENDIAN_64BITWORD {"ENDIAN_64BITWORD", 1}, #else {"ENDIAN_64BITWORD", 0}, #endif #ifdef ENDIAN_NEUTRAL {"ENDIAN_NEUTRAL", 1}, #else {"ENDIAN_NEUTRAL", 0}, #endif }; /* crypt_get_constant() * valueout will be the value of the named constant * return -1 if named item not found */ int crypt_get_constant(const char* namein, int *valueout) { int i; int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]); for (i=0; i *names_list_size) { return -1; } /* build the names list */ ptr = names_list; for (i=0; i total_len) return -1; total_len -= number_len; ptr += number_len; } /* to remove the trailing new-line */ ptr -= 1; *ptr = 0; } return 0; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher.c000066400000000000000000000013471464416617300261440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_cipher.c Find a cipher in the descriptor tables, Tom St Denis */ /** Find a registered cipher by name @param name The name of the cipher to look for @return >= 0 if found, -1 if not present */ int find_cipher(const char *name) { int x; LTC_ARGCHK(name != NULL); LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x] != NULL && !XSTRCMP(cipher_descriptor[x]->name, name)) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c000066400000000000000000000021631464416617300270100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_cipher_any.c Find a cipher in the descriptor tables, Tom St Denis */ /** Find a cipher flexibly. First by name then if not present by block and key size @param name The name of the cipher desired @param blocklen The minimum length of the block cipher desired (octets) @param keylen The minimum length of the key size desired (octets) @return >= 0 if found, -1 if not present */ int find_cipher_any(const char *name, int blocklen, int keylen) { int x; if(name != NULL) { x = find_cipher(name); if (x != -1) return x; } LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x] == NULL) { continue; } if (blocklen <= (int)cipher_descriptor[x]->block_length && keylen <= (int)cipher_descriptor[x]->max_key_length) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c000066400000000000000000000012651464416617300266170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_cipher_id.c Find cipher by ID, Tom St Denis */ /** Find a cipher by ID number @param ID The ID (not same as index) of the cipher to find @return >= 0 if found, -1 if not present */ int find_cipher_id(unsigned char ID) { int x; LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE && cipher_descriptor[x] != NULL; x++) { if (cipher_descriptor[x]->ID == ID) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash.c000066400000000000000000000012751464416617300256150ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_hash.c Find a hash, Tom St Denis */ /** Find a registered hash by name @param name The name of the hash to look for @return >= 0 if found, -1 if not present */ int find_hash(const char *name) { int x; LTC_ARGCHK(name != NULL); LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] != NULL && XSTRCMP(hash_descriptor[x]->name, name) == 0) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c000066400000000000000000000017541464416617300264660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_hash_any.c Find a hash, Tom St Denis */ /** Find a hash flexibly. First by name then if not present by digest size @param name The name of the hash desired @param digestlen The minimum length of the digest size (octets) @return >= 0 if found, -1 if not present */int find_hash_any(const char *name, int digestlen) { int x, y, z; LTC_ARGCHK(name != NULL); x = find_hash(name); if (x != -1) return x; LTC_MUTEX_LOCK(<c_hash_mutex); y = MAXBLOCKSIZE+1; z = -1; for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] == NULL) { continue; } if ((int)hash_descriptor[x]->hashsize >= digestlen && (int)hash_descriptor[x]->hashsize < y) { z = x; y = hash_descriptor[x]->hashsize; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return z; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c000066400000000000000000000012271464416617300262660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_hash_id.c Find hash by ID, Tom St Denis */ /** Find a hash by ID number @param ID The ID (not same as index) of the hash to find @return >= 0 if found, -1 if not present */ int find_hash_id(unsigned char ID) { int x; LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] && hash_descriptor[x]->ID == ID) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c000066400000000000000000000012271464416617300264450ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_hash_oid.c Find a hash, Tom St Denis */ int find_hash_oid(const unsigned long *ID, unsigned long IDlen) { int x; LTC_ARGCHK(ID != NULL); LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] != NULL && hash_descriptor[x]->OIDlen == IDlen && !XMEMCMP(hash_descriptor[x]->OID, ID, sizeof(unsigned long) * IDlen)) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_find_prng.c000066400000000000000000000013001464416617300256250ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_find_prng.c Find a PRNG, Tom St Denis */ /** Find a registered PRNG by name @param name The name of the PRNG to look for @return >= 0 if found, -1 if not present */ int find_prng(const char *name) { int x; LTC_ARGCHK(name != NULL); LTC_MUTEX_LOCK(<c_prng_mutex); for (x = 0; x < TAB_SIZE; x++) { if ((prng_descriptor[x] != NULL) && XSTRCMP(prng_descriptor[x]->name, name) == 0) { LTC_MUTEX_UNLOCK(<c_prng_mutex); return x; } } LTC_MUTEX_UNLOCK(<c_prng_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_fsa.c000066400000000000000000000017741464416617300244470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file crypt_fsa.c LibTomCrypt FULL SPEED AHEAD!, Tom St Denis */ /* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */ int crypt_fsa(void *mp, ...) { va_list args; void *p; va_start(args, mp); if (mp != NULL) { XMEMCPY(<c_mp, mp, sizeof(ltc_mp)); } while ((p = va_arg(args, void*)) != NULL) { if (register_cipher(p) == -1) { va_end(args); return CRYPT_INVALID_CIPHER; } } while ((p = va_arg(args, void*)) != NULL) { if (register_hash(p) == -1) { va_end(args); return CRYPT_INVALID_HASH; } } while ((p = va_arg(args, void*)) != NULL) { if (register_prng(p) == -1) { va_end(args); return CRYPT_INVALID_PRNG; } } va_end(args); return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c000066400000000000000000000005021464416617300270430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_hash_descriptor.c Stores the hash descriptor table, Tom St Denis */ const struct ltc_hash_descriptor *hash_descriptor[TAB_SIZE]; LTC_MUTEX_GLOBAL(ltc_hash_mutex) optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c000066400000000000000000000011431464416617300264610ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_hash_is_valid.c Determine if hash is valid, Tom St Denis */ /* Test if a hash index is valid @param idx The index of the hash to search for @return CRYPT_OK if valid */ int hash_is_valid(int idx) { LTC_MUTEX_LOCK(<c_hash_mutex); if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx] == NULL) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_INVALID_HASH; } LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_inits.c000066400000000000000000000026271464416617300250220ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_inits.c Provide math library functions for dynamic languages like Python - Larry Bugbee, February 2013 */ #ifdef LTM_DESC void init_LTM(void) { ltc_mp = ltm_desc; } #endif #ifdef TFM_DESC void init_TFM(void) { ltc_mp = tfm_desc; } #endif #ifdef GMP_DESC void init_GMP(void) { ltc_mp = gmp_desc; } #endif int crypt_mp_init(const char* mpi) { if (mpi == NULL) return CRYPT_ERROR; switch (mpi[0]) { #ifdef LTM_DESC case 'l': case 'L': ltc_mp = ltm_desc; return CRYPT_OK; #endif #ifdef TFM_DESC case 't': case 'T': ltc_mp = tfm_desc; return CRYPT_OK; #endif #ifdef GMP_DESC case 'g': case 'G': ltc_mp = gmp_desc; return CRYPT_OK; #endif #ifdef EXT_MATH_LIB case 'e': case 'E': { extern ltc_math_descriptor EXT_MATH_LIB; ltc_mp = EXT_MATH_LIB; } #if defined(LTC_TEST_DBG) #define NAME_VALUE(s) #s"="NAME(s) #define NAME(s) #s printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB)); #undef NAME_VALUE #undef NAME #endif return CRYPT_OK; #endif default: #if defined(LTC_TEST_DBG) printf("Unknown/Invalid MPI provider: %s\n", mpi); #endif return CRYPT_ERROR; } } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c000066400000000000000000000004061464416617300274010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */ ltc_math_descriptor ltc_mp = { 0 }; optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c000066400000000000000000000004741464416617300270760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_prng_descriptor.c Stores the PRNG descriptors, Tom St Denis */ const struct ltc_prng_descriptor *prng_descriptor[TAB_SIZE]; LTC_MUTEX_GLOBAL(ltc_prng_mutex) optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c000066400000000000000000000011431464416617300265040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_prng_is_valid.c Determine if PRNG is valid, Tom St Denis */ /* Test if a PRNG index is valid @param idx The index of the PRNG to search for @return CRYPT_OK if valid */ int prng_is_valid(int idx) { LTC_MUTEX_LOCK(<c_prng_mutex); if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx] == NULL) { LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_INVALID_PRNG; } LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c000066400000000000000000000004131464416617300277350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PRNG_ENABLE_LTC_RNG unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c000066400000000000000000000040441464416617300300600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_register_all_ciphers.c Steffen Jaeckel */ #define REGISTER_CIPHER(h) do {\ LTC_ARGCHK(register_cipher(h) != -1); \ } while(0) int register_all_ciphers(void) { #ifdef LTC_RIJNDAEL /* `aesni_desc` is explicitely not registered, since it's handled from within the `aes_desc` */ #ifdef ENCRYPT_ONLY /* alternative would be * register_cipher(&rijndael_enc_desc); */ REGISTER_CIPHER(&aes_enc_desc); #else /* alternative would be * register_cipher(&rijndael_desc); */ REGISTER_CIPHER(&aes_desc); #endif #endif #ifdef LTC_BLOWFISH REGISTER_CIPHER(&blowfish_desc); #endif #ifdef LTC_XTEA REGISTER_CIPHER(&xtea_desc); #endif #ifdef LTC_RC5 REGISTER_CIPHER(&rc5_desc); #endif #ifdef LTC_RC6 REGISTER_CIPHER(&rc6_desc); #endif #ifdef LTC_SAFERP REGISTER_CIPHER(&saferp_desc); #endif #ifdef LTC_TWOFISH REGISTER_CIPHER(&twofish_desc); #endif #ifdef LTC_SAFER REGISTER_CIPHER(&safer_k64_desc); REGISTER_CIPHER(&safer_sk64_desc); REGISTER_CIPHER(&safer_k128_desc); REGISTER_CIPHER(&safer_sk128_desc); #endif #ifdef LTC_RC2 REGISTER_CIPHER(&rc2_desc); #endif #ifdef LTC_DES REGISTER_CIPHER(&des_desc); REGISTER_CIPHER(&des3_desc); #endif #ifdef LTC_CAST5 REGISTER_CIPHER(&cast5_desc); #endif #ifdef LTC_NOEKEON REGISTER_CIPHER(&noekeon_desc); #endif #ifdef LTC_SKIPJACK REGISTER_CIPHER(&skipjack_desc); #endif #ifdef LTC_ANUBIS REGISTER_CIPHER(&anubis_desc); #endif #ifdef LTC_KHAZAD REGISTER_CIPHER(&khazad_desc); #endif #ifdef LTC_KSEED REGISTER_CIPHER(&kseed_desc); #endif #ifdef LTC_KASUMI REGISTER_CIPHER(&kasumi_desc); #endif #ifdef LTC_MULTI2 REGISTER_CIPHER(&multi2_desc); #endif #ifdef LTC_CAMELLIA REGISTER_CIPHER(&camellia_desc); #endif #ifdef LTC_IDEA REGISTER_CIPHER(&idea_desc); #endif #ifdef LTC_SERPENT REGISTER_CIPHER(&serpent_desc); #endif #ifdef LTC_TEA REGISTER_CIPHER(&tea_desc); #endif return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c000066400000000000000000000040611464416617300276750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_register_all_hashes.c Steffen Jaeckel */ #define REGISTER_HASH(h) do {\ LTC_ARGCHK(register_hash(h) != -1); \ } while(0) int register_all_hashes(void) { #ifdef LTC_TIGER REGISTER_HASH(&tiger_desc); REGISTER_HASH(&tiger2_desc); #endif #ifdef LTC_MD2 REGISTER_HASH(&md2_desc); #endif #ifdef LTC_MD4 REGISTER_HASH(&md4_desc); #endif #ifdef LTC_MD5 REGISTER_HASH(&md5_desc); #endif #ifdef LTC_SHA1 REGISTER_HASH(&sha1_desc); #endif #ifdef LTC_SHA224 REGISTER_HASH(&sha224_desc); #endif #ifdef LTC_SHA256 REGISTER_HASH(&sha256_desc); #endif #ifdef LTC_SHA384 REGISTER_HASH(&sha384_desc); #endif #ifdef LTC_SHA512 REGISTER_HASH(&sha512_desc); #endif #ifdef LTC_SHA512_224 REGISTER_HASH(&sha512_224_desc); #endif #ifdef LTC_SHA512_256 REGISTER_HASH(&sha512_256_desc); #endif #ifdef LTC_SHA3 REGISTER_HASH(&sha3_224_desc); REGISTER_HASH(&sha3_256_desc); REGISTER_HASH(&sha3_384_desc); REGISTER_HASH(&sha3_512_desc); #endif #ifdef LTC_KECCAK REGISTER_HASH(&keccak_224_desc); REGISTER_HASH(&keccak_256_desc); REGISTER_HASH(&keccak_384_desc); REGISTER_HASH(&keccak_512_desc); #endif #ifdef LTC_RIPEMD128 REGISTER_HASH(&rmd128_desc); #endif #ifdef LTC_RIPEMD160 REGISTER_HASH(&rmd160_desc); #endif #ifdef LTC_RIPEMD256 REGISTER_HASH(&rmd256_desc); #endif #ifdef LTC_RIPEMD320 REGISTER_HASH(&rmd320_desc); #endif #ifdef LTC_WHIRLPOOL REGISTER_HASH(&whirlpool_desc); #endif #ifdef LTC_BLAKE2S REGISTER_HASH(&blake2s_128_desc); REGISTER_HASH(&blake2s_160_desc); REGISTER_HASH(&blake2s_224_desc); REGISTER_HASH(&blake2s_256_desc); #endif #ifdef LTC_BLAKE2S REGISTER_HASH(&blake2b_160_desc); REGISTER_HASH(&blake2b_256_desc); REGISTER_HASH(&blake2b_384_desc); REGISTER_HASH(&blake2b_512_desc); #endif #ifdef LTC_CHC_HASH REGISTER_HASH(&chc_desc); LTC_ARGCHK(chc_register(find_cipher_any("aes", 8, 16)) == CRYPT_OK); #endif return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c000066400000000000000000000012641464416617300275550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_register_all_prngs.c Steffen Jaeckel */ #define REGISTER_PRNG(h) do {\ LTC_ARGCHK(register_prng(h) != -1); \ } while(0) int register_all_prngs(void) { #ifdef LTC_YARROW REGISTER_PRNG(&yarrow_desc); #endif #ifdef LTC_FORTUNA REGISTER_PRNG(&fortuna_desc); #endif #ifdef LTC_RC4 REGISTER_PRNG(&rc4_desc); #endif #ifdef LTC_CHACHA20_PRNG REGISTER_PRNG(&chacha20_prng_desc); #endif #ifdef LTC_SOBER128 REGISTER_PRNG(&sober128_desc); #endif #ifdef LTC_SPRNG REGISTER_PRNG(&sprng_desc); #endif return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_register_cipher.c000066400000000000000000000021001464416617300270340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_register_cipher.c Register a cipher, Tom St Denis */ /** Register a cipher with the descriptor table @param cipher The cipher you wish to register @return value >= 0 if successfully added (or already present), -1 if unsuccessful */ int register_cipher(const struct ltc_cipher_descriptor *cipher) { int x; LTC_ARGCHK(cipher != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x] != NULL && cipher_descriptor[x]->ID == cipher->ID) { LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } /* find a blank spot */ for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x] == NULL) { cipher_descriptor[x] = cipher; LTC_MUTEX_UNLOCK(<c_cipher_mutex); return x; } } /* no spot */ LTC_MUTEX_UNLOCK(<c_cipher_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_register_hash.c000066400000000000000000000017641464416617300265240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_register_hash.c Register a HASH, Tom St Denis */ /** Register a hash with the descriptor table @param hash The hash you wish to register @return value >= 0 if successfully added (or already present), -1 if unsuccessful */ int register_hash(const struct ltc_hash_descriptor *hash) { int x; LTC_ARGCHK(hash != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] == hash) { LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } /* find a blank spot */ for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] == NULL) { hash_descriptor[x] = hash; LTC_MUTEX_UNLOCK(<c_hash_mutex); return x; } } /* no spot */ LTC_MUTEX_UNLOCK(<c_hash_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_register_prng.c000066400000000000000000000017551464416617300265470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_register_prng.c Register a PRNG, Tom St Denis */ /** Register a PRNG with the descriptor table @param prng The PRNG you wish to register @return value >= 0 if successfully added (or already present), -1 if unsuccessful */ int register_prng(const struct ltc_prng_descriptor *prng) { int x; LTC_ARGCHK(prng != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_prng_mutex); for (x = 0; x < TAB_SIZE; x++) { if (prng_descriptor[x] == prng) { LTC_MUTEX_UNLOCK(<c_prng_mutex); return x; } } /* find a blank spot */ for (x = 0; x < TAB_SIZE; x++) { if (prng_descriptor[x] == NULL) { prng_descriptor[x] = prng; LTC_MUTEX_UNLOCK(<c_prng_mutex); return x; } } /* no spot */ LTC_MUTEX_UNLOCK(<c_prng_mutex); return -1; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_sizes.c000066400000000000000000000175471464416617300250400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_sizes.c Make various struct sizes available to dynamic languages like Python - Larry Bugbee, February 2013 LB - Dec 2013 - revised to include compiler define options */ typedef struct { const char *name; const unsigned int size; } crypt_size; #define SZ_STRINGIFY_S(s) { #s, sizeof(struct s) } #define SZ_STRINGIFY_T(s) { #s, sizeof(s) } static const crypt_size s_crypt_sizes[] = { /* hash state sizes */ SZ_STRINGIFY_S(ltc_hash_descriptor), SZ_STRINGIFY_T(hash_state), #ifdef LTC_CHC_HASH SZ_STRINGIFY_S(chc_state), #endif #ifdef LTC_WHIRLPOOL SZ_STRINGIFY_S(whirlpool_state), #endif #ifdef LTC_SHA3 SZ_STRINGIFY_S(sha3_state), #endif #ifdef LTC_SHA512 SZ_STRINGIFY_S(sha512_state), #endif #ifdef LTC_SHA256 SZ_STRINGIFY_S(sha256_state), #endif #ifdef LTC_SHA1 SZ_STRINGIFY_S(sha1_state), #endif #ifdef LTC_MD5 SZ_STRINGIFY_S(md5_state), #endif #ifdef LTC_MD4 SZ_STRINGIFY_S(md4_state), #endif #ifdef LTC_MD2 SZ_STRINGIFY_S(md2_state), #endif #ifdef LTC_TIGER SZ_STRINGIFY_S(tiger_state), #endif #ifdef LTC_RIPEMD128 SZ_STRINGIFY_S(rmd128_state), #endif #ifdef LTC_RIPEMD160 SZ_STRINGIFY_S(rmd160_state), #endif #ifdef LTC_RIPEMD256 SZ_STRINGIFY_S(rmd256_state), #endif #ifdef LTC_RIPEMD320 SZ_STRINGIFY_S(rmd320_state), #endif #ifdef LTC_BLAKE2S SZ_STRINGIFY_S(blake2s_state), #endif #ifdef LTC_BLAKE2B SZ_STRINGIFY_S(blake2b_state), #endif /* block cipher key sizes */ SZ_STRINGIFY_S(ltc_cipher_descriptor), SZ_STRINGIFY_T(symmetric_key), #ifdef LTC_ANUBIS SZ_STRINGIFY_S(anubis_key), #endif #ifdef LTC_CAMELLIA SZ_STRINGIFY_S(camellia_key), #endif #ifdef LTC_BLOWFISH SZ_STRINGIFY_S(blowfish_key), #endif #ifdef LTC_CAST5 SZ_STRINGIFY_S(cast5_key), #endif #ifdef LTC_DES SZ_STRINGIFY_S(des_key), SZ_STRINGIFY_S(des3_key), #endif #ifdef LTC_IDEA SZ_STRINGIFY_S(idea_key), #endif #ifdef LTC_KASUMI SZ_STRINGIFY_S(kasumi_key), #endif #ifdef LTC_KHAZAD SZ_STRINGIFY_S(khazad_key), #endif #ifdef LTC_KSEED SZ_STRINGIFY_S(kseed_key), #endif #ifdef LTC_MULTI2 SZ_STRINGIFY_S(multi2_key), #endif #ifdef LTC_NOEKEON SZ_STRINGIFY_S(noekeon_key), #endif #ifdef LTC_RC2 SZ_STRINGIFY_S(rc2_key), #endif #ifdef LTC_RC5 SZ_STRINGIFY_S(rc5_key), #endif #ifdef LTC_RC6 SZ_STRINGIFY_S(rc6_key), #endif #ifdef LTC_SERPENT SZ_STRINGIFY_S(serpent_key), #endif #ifdef LTC_SKIPJACK SZ_STRINGIFY_S(skipjack_key), #endif #ifdef LTC_XTEA SZ_STRINGIFY_S(xtea_key), #endif #ifdef LTC_RIJNDAEL SZ_STRINGIFY_S(rijndael_key), #endif #ifdef LTC_SAFER SZ_STRINGIFY_S(safer_key), #endif #ifdef LTC_SAFERP SZ_STRINGIFY_S(saferp_key), #endif #ifdef LTC_TWOFISH SZ_STRINGIFY_S(twofish_key), #endif /* mode sizes */ #ifdef LTC_ECB_MODE SZ_STRINGIFY_T(symmetric_ECB), #endif #ifdef LTC_CFB_MODE SZ_STRINGIFY_T(symmetric_CFB), #endif #ifdef LTC_OFB_MODE SZ_STRINGIFY_T(symmetric_OFB), #endif #ifdef LTC_CBC_MODE SZ_STRINGIFY_T(symmetric_CBC), #endif #ifdef LTC_CTR_MODE SZ_STRINGIFY_T(symmetric_CTR), #endif #ifdef LTC_LRW_MODE SZ_STRINGIFY_T(symmetric_LRW), #endif #ifdef LTC_F8_MODE SZ_STRINGIFY_T(symmetric_F8), #endif #ifdef LTC_XTS_MODE SZ_STRINGIFY_T(symmetric_xts), #endif /* stream cipher sizes */ #ifdef LTC_CHACHA SZ_STRINGIFY_T(chacha_state), #endif #ifdef LTC_SALSA20 SZ_STRINGIFY_T(salsa20_state), #endif #ifdef LTC_SOSEMANUK SZ_STRINGIFY_T(sosemanuk_state), #endif #ifdef LTC_RABBIT SZ_STRINGIFY_T(rabbit_state), #endif #ifdef LTC_RC4_STREAM SZ_STRINGIFY_T(rc4_state), #endif #ifdef LTC_SOBER128_STREAM SZ_STRINGIFY_T(sober128_state), #endif /* MAC sizes -- no states for ccm, lrw */ #ifdef LTC_HMAC SZ_STRINGIFY_T(hmac_state), #endif #ifdef LTC_OMAC SZ_STRINGIFY_T(omac_state), #endif #ifdef LTC_PMAC SZ_STRINGIFY_T(pmac_state), #endif #ifdef LTC_POLY1305 SZ_STRINGIFY_T(poly1305_state), #endif #ifdef LTC_EAX_MODE SZ_STRINGIFY_T(eax_state), #endif #ifdef LTC_OCB_MODE SZ_STRINGIFY_T(ocb_state), #endif #ifdef LTC_OCB3_MODE SZ_STRINGIFY_T(ocb3_state), #endif #ifdef LTC_CCM_MODE SZ_STRINGIFY_T(ccm_state), #endif #ifdef LTC_GCM_MODE SZ_STRINGIFY_T(gcm_state), #endif #ifdef LTC_PELICAN SZ_STRINGIFY_T(pelican_state), #endif #ifdef LTC_XCBC SZ_STRINGIFY_T(xcbc_state), #endif #ifdef LTC_F9_MODE SZ_STRINGIFY_T(f9_state), #endif #ifdef LTC_CHACHA20POLY1305_MODE SZ_STRINGIFY_T(chacha20poly1305_state), #endif /* asymmetric keys */ #ifdef LTC_MRSA SZ_STRINGIFY_T(rsa_key), #endif #ifdef LTC_MDSA SZ_STRINGIFY_T(dsa_key), #endif #ifdef LTC_MDH SZ_STRINGIFY_T(dh_key), #endif #ifdef LTC_MECC SZ_STRINGIFY_T(ltc_ecc_curve), SZ_STRINGIFY_T(ecc_point), SZ_STRINGIFY_T(ecc_key), #endif /* DER handling */ #ifdef LTC_DER SZ_STRINGIFY_T(ltc_asn1_list), /* a list entry */ SZ_STRINGIFY_T(ltc_utctime), SZ_STRINGIFY_T(ltc_generalizedtime), #endif /* prng state sizes */ SZ_STRINGIFY_S(ltc_prng_descriptor), SZ_STRINGIFY_T(prng_state), #ifdef LTC_FORTUNA SZ_STRINGIFY_S(fortuna_prng), #endif #ifdef LTC_CHACHA20_PRNG SZ_STRINGIFY_S(chacha20_prng), #endif #ifdef LTC_RC4 SZ_STRINGIFY_S(rc4_prng), #endif #ifdef LTC_SOBER128 SZ_STRINGIFY_S(sober128_prng), #endif #ifdef LTC_YARROW SZ_STRINGIFY_S(yarrow_prng), #endif /* sprng has no state as it uses other potentially available sources */ /* like /dev/random. See Developers Guide for more info. */ #ifdef LTC_ADLER32 SZ_STRINGIFY_T(adler32_state), #endif #ifdef LTC_CRC32 SZ_STRINGIFY_T(crc32_state), #endif SZ_STRINGIFY_T(ltc_mp_digit), SZ_STRINGIFY_T(ltc_math_descriptor) }; /* crypt_get_size() * sizeout will be the size (bytes) of the named struct or union * return -1 if named item not found */ int crypt_get_size(const char* namein, unsigned int *sizeout) { int i; int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]); for (i=0; i *names_list_size) { return -1; } /* build the names list */ ptr = names_list; for (i=0; i total_len) return -1; total_len -= number_len; ptr += number_len; } /* to remove the trailing new-line */ ptr -= 1; *ptr = 0; } return 0; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c000066400000000000000000000014471464416617300274140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_unregister_cipher.c Unregister a cipher, Tom St Denis */ /** Unregister a cipher from the descriptor table @param cipher The cipher descriptor to remove @return CRYPT_OK on success */ int unregister_cipher(const struct ltc_cipher_descriptor *cipher) { int x; LTC_ARGCHK(cipher != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_cipher_mutex); for (x = 0; x < TAB_SIZE; x++) { if (cipher_descriptor[x] == cipher) { cipher_descriptor[x] = NULL; LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_OK; } } LTC_MUTEX_UNLOCK(<c_cipher_mutex); return CRYPT_ERROR; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c000066400000000000000000000014111464416617300270540ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_unregister_hash.c Unregister a hash, Tom St Denis */ /** Unregister a hash from the descriptor table @param hash The hash descriptor to remove @return CRYPT_OK on success */ int unregister_hash(const struct ltc_hash_descriptor *hash) { int x; LTC_ARGCHK(hash != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_hash_mutex); for (x = 0; x < TAB_SIZE; x++) { if (hash_descriptor[x] == hash) { hash_descriptor[x] = NULL; LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_OK; } } LTC_MUTEX_UNLOCK(<c_hash_mutex); return CRYPT_ERROR; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c000066400000000000000000000014111464416617300270770ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file crypt_unregister_prng.c Unregister a PRNG, Tom St Denis */ /** Unregister a PRNG from the descriptor table @param prng The PRNG descriptor to remove @return CRYPT_OK on success */ int unregister_prng(const struct ltc_prng_descriptor *prng) { int x; LTC_ARGCHK(prng != NULL); /* is it already registered? */ LTC_MUTEX_LOCK(<c_prng_mutex); for (x = 0; x < TAB_SIZE; x++) { if (prng_descriptor[x] == prng) { prng_descriptor[x] = NULL; LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_OK; } } LTC_MUTEX_UNLOCK(<c_prng_mutex); return CRYPT_ERROR; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/error_to_string.c000066400000000000000000000027561464416617300245360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file error_to_string.c Convert error codes to ASCII strings, Tom St Denis */ static const char * const err_2_str[] = { "CRYPT_OK", "CRYPT_ERROR", "Non-fatal 'no-operation' requested.", "Invalid key size.", "Invalid number of rounds for block cipher.", "Algorithm failed test vectors.", "Buffer overflow.", "Invalid input packet.", "Invalid number of bits for a PRNG.", "Error reading the PRNG.", "Invalid cipher specified.", "Invalid hash specified.", "Invalid PRNG specified.", "Out of memory.", "Invalid PK key or key type specified for function.", "A private PK key is required.", "Invalid argument provided.", "File Not Found", "Invalid PK type.", "An overflow of a value was detected/prevented.", "An ASN.1 decoding error occurred.", "The input was longer than expected.", "Invalid sized parameter.", "Invalid size for prime.", "Invalid padding.", "Hash applied to too many bits.", }; /** Convert an LTC error code to ASCII @param err The error code @return A pointer to the ASCII NUL terminated string for the error or "Invalid error code." if the err code was not valid. */ const char *error_to_string(int err) { if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) { return "Invalid error code."; } return err_2_str[err]; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/hkdf/000077500000000000000000000000001464416617300220535ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/hkdf/hkdf.c000066400000000000000000000102501464416617300231310ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include #include #include #include "tomcrypt_private.h" #ifdef LTC_HKDF /* This is mostly just a wrapper around hmac_memory */ int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { /* libtomcrypt chokes on a zero length HMAC key, so we need to check for that. HMAC specifies that keys shorter than the hash's blocksize are 0 padded to the block size. HKDF specifies that a NULL salt is to be substituted with a salt comprised of hashLen 0 bytes. HMAC's padding means that in either case the HMAC is actually using a blocksize long zero filled key. Unless blocksize < hashLen (which wouldn't make any sense), we can use a single 0 byte as the HMAC key and still generate valid results for HKDF. */ if (salt == NULL || saltlen == 0) { return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen); } return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); } int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { unsigned long hashsize; int err; unsigned char N; unsigned long Noutlen, outoff; unsigned char *T, *dat; unsigned long Tlen, datlen; /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hashsize = hash_descriptor[hash_idx]->hashsize; /* RFC5869 parameter restrictions */ if (inlen < hashsize || outlen > hashsize * 255) { return CRYPT_INVALID_ARG; } if (info == NULL && infolen != 0) { return CRYPT_INVALID_ARG; } LTC_ARGCHK(out != NULL); Tlen = hashsize + infolen + 1; T = XMALLOC(Tlen); /* Replace with static buffer? */ if (T == NULL) { return CRYPT_MEM; } if (info != NULL) { XMEMCPY(T + hashsize, info, infolen); } /* HMAC data T(1) doesn't include a previous hash value */ dat = T + hashsize; datlen = Tlen - hashsize; N = 0; outoff = 0; /* offset in out to write to */ while (1) { /* an exit condition breaks mid-loop */ Noutlen = MIN(hashsize, outlen - outoff); T[Tlen - 1] = ++N; if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen, out + outoff, &Noutlen)) != CRYPT_OK) { zeromem(T, Tlen); XFREE(T); return err; } outoff += Noutlen; if (outoff >= outlen) { /* loop exit condition */ break; } /* All subsequent HMAC data T(N) DOES include the previous hash value */ XMEMCPY(T, out + hashsize * (N-1), hashsize); if (N == 1) { dat = T; datlen = Tlen; } } zeromem(T, Tlen); XFREE(T); return CRYPT_OK; } /* all in one step */ int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { unsigned long hashsize; int err; unsigned char *extracted; /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hashsize = hash_descriptor[hash_idx]->hashsize; extracted = XMALLOC(hashsize); /* replace with static buffer? */ if (extracted == NULL) { return CRYPT_MEM; } if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { zeromem(extracted, hashsize); XFREE(extracted); return err; } err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); zeromem(extracted, hashsize); XFREE(extracted); return err; } #endif /* LTC_HKDF */ /* vim: set ts=2 sw=2 et ai si: */ optee_os-4.3.0/core/lib/libtomcrypt/src/misc/hkdf/hkdf_test.c000066400000000000000000000311321464416617300241720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hkdf_test.c LTC_HKDF support, self-test, Steffen Jaeckel */ #ifdef LTC_HKDF /* TEST CASES SOURCE: Internet Engineering Task Force (IETF) H. Krawczyk Request for Comments: 5869 IBM Research Category: Informational P. Eronen ISSN: 2070-1721 Nokia May 2010 Appendix A. Test Vectors */ /** LTC_HKDF self-test @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. */ int hkdf_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char OKM[82]; int i; static const struct hkdf_test_case { int num; const char* Hash; unsigned char IKM[80]; unsigned long IKM_l; unsigned char salt[80]; unsigned long salt_l; unsigned char info[80]; unsigned long info_l; unsigned char PRK[32]; unsigned long PRK_l; unsigned char OKM[82]; unsigned long OKM_l; } cases[] = { #ifdef LTC_SHA256 /* Basic test case with SHA-256 Hash = SHA-256 IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) salt = 0x000102030405060708090a0b0c (13 octets) info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) L = 42 PRK = 0x077709362c2e32df0ddc3f0dc47bba63 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) OKM = 0x3cb25f25faacd57a90434f64d0362f2a 2d2d0a90cf1a5a4c5db02d56ecc4c5bf 34007208d5b887185865 (42 octets) */ {1, "sha256", {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}, 10, {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32, {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65}, 42}, #ifdef LTC_TEST_EXT /* Test with SHA-256 and longer inputs/outputs */ {2, "sha256", {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, {0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32, {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87}, 82}, /* Test with SHA-256 and zero length salt/info */ {3, "sha256", {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, {0}, 0, {0}, 0, {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32, {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8}, 42}, #endif /* LTC_TEST_EXT */ #endif /* LTC_SHA256 */ #ifdef LTC_SHA1 /* Basic test case with SHA-1 */ {4, "sha1", {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 11, {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}, 10, {0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43}, 20, {0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96}, 42}, #ifdef LTC_TEST_EXT /* Test with SHA-1 and longer inputs/outputs */ {5, "sha1", {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, {0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6}, 20, {0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4}, 82}, /* Test with SHA-1 and zero-length salt/info */ {6, "sha1", {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, {0}, 0, {0}, 0, {0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01}, 20, {0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18}, 42}, /* Test with SHA-1, salt not provided (defaults to HashLen zero octets), zero-length info */ {7, "sha1", {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22, {0}, 0, /* pass a null pointer */ {0}, 0, {0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd}, 20, {0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48}, 42}, #endif /* LTC_TEST_EXT */ #endif /* LTC_SHA1 */ }; int err; int tested=0,failed=0; for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { int hash = find_hash(cases[i].Hash); if (hash == -1) continue; ++tested; if((err = hkdf(hash, cases[i].salt, cases[i].salt_l, cases[i].info, cases[i].info_l, cases[i].IKM, cases[i].IKM_l, OKM, cases[i].OKM_l)) != CRYPT_OK) { #if defined(LTC_TEST_DBG) && (LTC_TEST_DBG > 1) printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err)); #endif return err; } if(compare_testvector(OKM, cases[i].OKM_l, cases[i].OKM, (size_t)cases[i].OKM_l, "HKDF", cases[i].num)) { failed++; } } if (failed != 0) { return CRYPT_FAIL_TESTVECTOR; } if (tested == 0) { return CRYPT_NOP; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/mem_neq.c000066400000000000000000000024731464416617300227320ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file mem_neq.c Compare two blocks of memory for inequality in constant time. Steffen Jaeckel */ /** Compare two blocks of memory for inequality in constant time. The usage is similar to that of standard memcmp, but you can only test if the memory is equal or not - you can not determine by how much the first different byte differs. This function shall be used to compare results of cryptographic operations where inequality means most likely usage of a wrong key. The execution time has therefore to be constant as otherwise timing attacks could be possible. @param a The first memory region @param b The second memory region @param len The length of the area to compare (octets) @return 0 when a and b are equal for len bytes, 1 they are not equal. */ int mem_neq(const void *a, const void *b, size_t len) { unsigned char ret = 0; const unsigned char* pa; const unsigned char* pb; LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); pa = a; pb = b; while (len-- > 0) { ret |= *pa ^ *pb; ++pa; ++pb; } ret |= ret >> 4; ret |= ret >> 2; ret |= ret >> 1; ret &= 1; return ret; } optee_os-4.3.0/core/lib/libtomcrypt/src/misc/padding/000077500000000000000000000000001464416617300225455ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/padding/padding_depad.c000066400000000000000000000047561464416617300254700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PADDING /** Remove padding from your data This depads your data. @param data The data to depad @param length [in/out] The size of the data before/after (removing padding) @param mode One of the LTC_PAD_xx flags @return CRYPT_OK on success */ int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode) { unsigned long padded_length, unpadded_length, n; unsigned char pad; enum padding_type type; LTC_ARGCHK(data != NULL); LTC_ARGCHK(length != NULL); padded_length = *length; type = mode & LTC_PAD_MASK; if (type < LTC_PAD_ONE_AND_ZERO) { pad = data[padded_length - 1]; if (pad > padded_length || pad == 0) return CRYPT_INVALID_ARG; unpadded_length = padded_length - pad; } else { /* init pad to calm old compilers */ pad = 0x0; unpadded_length = padded_length; } switch (type) { case LTC_PAD_ANSI_X923: pad = 0x0; /* FALLTHROUGH */ case LTC_PAD_PKCS7: for (n = unpadded_length; n < padded_length - 1; ++n) { if (data[n] != pad) return CRYPT_INVALID_PACKET; } break; #ifdef LTC_RNG_GET_BYTES case LTC_PAD_ISO_10126: /* nop */ break; #endif case LTC_PAD_SSH: pad = 0x1; for (n = unpadded_length; n < padded_length; ++n) { if (data[n] != pad++) return CRYPT_INVALID_PACKET; } break; case LTC_PAD_ONE_AND_ZERO: while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) { if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET; unpadded_length--; } if (unpadded_length == 0) return CRYPT_INVALID_PACKET; unpadded_length--; if (data[unpadded_length] != 0x80) return CRYPT_INVALID_PACKET; break; case LTC_PAD_ZERO: case LTC_PAD_ZERO_ALWAYS: while (unpadded_length > 0 && data[unpadded_length - 1] == 0x0) { unpadded_length--; } if (type == LTC_PAD_ZERO_ALWAYS) { if (unpadded_length == padded_length) return CRYPT_INVALID_PACKET; if (data[unpadded_length] != 0x0) return CRYPT_INVALID_PACKET; } break; default: return CRYPT_INVALID_ARG; } *length = unpadded_length; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/padding/padding_pad.c000066400000000000000000000070441464416617300251500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PADDING /** Determine the to-be-padded length. @param length [in/out] The size of the data before/after padding @param mode Mask of (LTC_PAD_xxx | block_length) @return CRYPT_OK on success */ static int s_padding_padded_length(unsigned long *length, unsigned long mode) { enum padding_type padding; unsigned char pad, block_length, r, t; LTC_ARGCHK(length != NULL); block_length = mode & 0xff; padding = mode & LTC_PAD_MASK; r = *length % block_length; switch (padding) { case LTC_PAD_ZERO: if (r == 0) { t = 0; break; } /* FALLTHROUGH */ case LTC_PAD_PKCS7: case LTC_PAD_ONE_AND_ZERO: case LTC_PAD_ZERO_ALWAYS: case LTC_PAD_SSH: t = 1; break; #ifdef LTC_RNG_GET_BYTES case LTC_PAD_ISO_10126: do { if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) { return CRYPT_ERROR_READPRNG; } t %= (256 / block_length); } while (t == 0); break; #endif case LTC_PAD_ANSI_X923: if (block_length != 16) { return CRYPT_INVALID_ARG; } t = 1; break; default: return CRYPT_INVALID_ARG; } pad = (t * block_length) - r; if ((pad == 0) && (padding != LTC_PAD_ZERO)) { pad = block_length; } *length += pad; return CRYPT_OK; } /** Add padding to data. This pads your data. @param data The data to depad @param length The size of the data before padding @param padded_length [in/out] The size of the data available/after padding @param mode One of the LTC_PAD_xx flags @return CRYPT_OK on success */ int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode) { unsigned long l, n; enum padding_type type; int err; unsigned char diff, pad; LTC_ARGCHK(data != NULL); LTC_ARGCHK(padded_length != NULL); l = length; if ((err = s_padding_padded_length(&l, mode)) != CRYPT_OK) { return err; } type = mode & LTC_PAD_MASK; if (*padded_length < l) { #ifdef LTC_RNG_GET_BYTES if (type != LTC_PAD_ISO_10126) { *padded_length = l; } else { *padded_length = length + 256; } #else *padded_length = l; #endif return CRYPT_BUFFER_OVERFLOW; } if (l - length > 255) return CRYPT_INVALID_ARG; diff = (unsigned char)(l - length); switch (type) { case LTC_PAD_PKCS7: XMEMSET(&data[length], diff, diff); break; #ifdef LTC_RNG_GET_BYTES case LTC_PAD_ISO_10126: if (rng_get_bytes(&data[length], diff-1u, NULL) != diff-1u) { return CRYPT_ERROR_READPRNG; } data[l-1] = diff; break; #endif case LTC_PAD_ANSI_X923: XMEMSET(&data[length], 0, diff-1); data[l-1] = diff; break; case LTC_PAD_SSH: pad = 0x1; for (n = length; n < l; ++n) { data[n] = pad++; } break; case LTC_PAD_ONE_AND_ZERO: XMEMSET(&data[length + 1], 0, diff); data[length] = 0x80; break; case LTC_PAD_ZERO: case LTC_PAD_ZERO_ALWAYS: XMEMSET(&data[length], 0, diff); break; default: return CRYPT_INVALID_ARG; } *padded_length = l; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pbes/000077500000000000000000000000001464416617300220705ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pbes/pbes.c000066400000000000000000000043471464416617300231750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PBES /** Decrypt Data encrypted via either PBES1 or PBES2 @param arg The according PBES parameters @param dec_data [out] The decrypted data @param dec_size [in/out] The length of the encrypted resp. decrypted data @return CRYPT_OK on success */ int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size) { int err, hid, cid; unsigned char k[32], *iv; unsigned long klen, keylen, dlen; long diff; symmetric_CBC cbc; LTC_ARGCHK(arg != NULL); LTC_ARGCHK(arg->type.kdf != NULL); LTC_ARGCHK(dec_data != NULL); LTC_ARGCHK(dec_size != NULL); hid = find_hash(arg->type.h); if (hid == -1) return CRYPT_INVALID_HASH; cid = find_cipher(arg->type.c); if (cid == -1) return CRYPT_INVALID_CIPHER; klen = arg->type.keylen; /* RC2 special case */ if (arg->key_bits != 0) { /* We can't handle odd lengths of Key Bits */ if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE; /* Internally we use bytes, not bits */ klen = arg->key_bits / 8; } keylen = klen; if (arg->iv != NULL) { iv = arg->iv->data; } else { iv = k + klen; klen += arg->type.blocklen; } if (klen > sizeof(k)) return CRYPT_INVALID_ARG; if ((err = arg->type.kdf(arg->pwd, arg->pwdlen, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR; if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR; if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR; if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR; dlen = arg->enc_data->size; if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR; diff = (long)arg->enc_data->size - (long)dlen; if ((diff <= 0) || (diff > cipher_descriptor[cid]->block_length)) { err = CRYPT_PK_INVALID_PADDING; goto LBL_ERROR; } *dec_size = dlen; return CRYPT_OK; LBL_ERROR: zeromem(k, sizeof(k)); zeromem(dec_data, *dec_size); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pbes/pbes1.c000066400000000000000000000113621464416617300232510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PBES static int s_pkcs_5_alg1_wrap(const unsigned char *password, unsigned long password_len, const unsigned char *salt, unsigned long salt_len, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { LTC_UNUSED_PARAM(salt_len); return pkcs_5_alg1(password, password_len, salt, iteration_count, hash_idx, out, outlen); } static int s_pkcs_12_wrap(const unsigned char *password, unsigned long password_len, const unsigned char *salt, unsigned long salt_len, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { int err; /* convert password to unicode/utf16-be */ unsigned long pwlen = password_len * 2; unsigned char* pw; if (*outlen < 32) return CRYPT_INVALID_ARG; pw = XMALLOC(pwlen + 2); if (pw == NULL) return CRYPT_MEM; if ((err = pkcs12_utf8_to_utf16(password, password_len, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR; pw[pwlen++] = 0; pw[pwlen++] = 0; /* derive KEY */ if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR; /* derive IV */ if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR; *outlen = 32; LBL_ERROR: zeromem(pw, pwlen); XFREE(pw); return err; } static const pbes_properties s_pbes1_types[] = { { s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 }, { s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 }, { s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 }, { s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 }, { s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 }, { s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 }, { s_pkcs_12_wrap, "sha1", "3des", 24, 8 }, }; typedef struct { const pbes_properties *data; const char *oid; } oid_to_pbes; static const oid_to_pbes s_pbes1_list[] = { { &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */ { &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */ { &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */ { &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */ { &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */ { &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */ { &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */ { 0 }, }; static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res) { unsigned int i; for (i = 0; s_pbes1_list[i].data != NULL; ++i) { if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) { if (res != NULL) *res = *s_pbes1_list[i].data; return CRYPT_OK; } } return CRYPT_INVALID_ARG; } /** Extract PBES1 parameters @param s The start of the sequence with potential PBES1 parameters @param res Pointer to where the extracted parameters should be stored @return CRYPT_OK on success */ int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res) { int err; LTC_ARGCHK(s != NULL); LTC_ARGCHK(res != NULL); if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err; if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) || !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) { return CRYPT_INVALID_PACKET; } /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC: * 0:d=0 hl=4 l= 329 cons: SEQUENCE * 4:d=1 hl=2 l= 27 cons: SEQUENCE * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s) * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam) * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt) * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations) * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) */ res->salt = s->next->child; res->iterations = mp_get_int(s->next->child->next->data); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pbes/pbes2.c000066400000000000000000000167111464416617300232550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PBES static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13"; static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12"; typedef struct { const char *oid; const char *id; } oid_id_st; static const oid_id_st s_hmac_oid_names[] = { { "1.2.840.113549.2.7", "sha1" }, { "1.2.840.113549.2.8", "sha224" }, { "1.2.840.113549.2.9", "sha256" }, { "1.2.840.113549.2.10", "sha384" }, { "1.2.840.113549.2.11", "sha512" }, { "1.2.840.113549.2.12", "sha512-224" }, { "1.2.840.113549.2.13", "sha512-256" }, }; static const pbes_properties s_pbes2_default_types[] = { { pkcs_5_alg2, "sha1", "des", 8, 0 }, { pkcs_5_alg2, "sha1", "rc2", 4, 0 }, { pkcs_5_alg2, "sha1", "3des", 24, 0 }, { pkcs_5_alg2, "sha1", "aes", 16, 0 }, { pkcs_5_alg2, "sha1", "aes", 24, 0 }, { pkcs_5_alg2, "sha1", "aes", 32, 0 }, }; typedef struct { const pbes_properties *data; const char* oid; } oid_to_pbes; static const oid_to_pbes s_pbes2_list[] = { { &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */ { &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */ { &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */ { &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */ { &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */ { &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */ }; static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res) { unsigned int i; for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) { if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) { *res = *s_pbes2_list[i].data; break; } } if (res->c == NULL) return CRYPT_INVALID_CIPHER; if (hmac_oid != NULL) { for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) { if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) { res->h = s_hmac_oid_names[i].id; return CRYPT_OK; } } return CRYPT_INVALID_HASH; } return CRYPT_OK; } /** Extract PBES2 parameters @param s The start of the sequence with potential PBES2 parameters @param res Pointer to where the extracted parameters should be stored @return CRYPT_OK on success */ int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res) { unsigned long klen; ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac; int err; LTC_ARGCHK(s != NULL); LTC_ARGCHK(res != NULL); if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err; if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) || !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) || !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) || !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) || !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) { return CRYPT_INVALID_PACKET; } /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc: * 0:d=0 hl=4 l= 380 cons: SEQUENCE * 4:d=1 hl=2 l= 78 cons: SEQUENCE * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s) * 17:d=2 hl=2 l= 65 cons: SEQUENCE * 19:d=3 hl=2 l= 41 cons: SEQUENCE * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf) * 32:d=4 hl=2 l= 28 cons: SEQUENCE * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt) * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter) * 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing) * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac) * 60:d=6 hl=2 l= 0 prim: NULL * 62:d=3 hl=2 l= 20 cons: SEQUENCE * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc) * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) */ lkdf = s->next->child->child; lenc = s->next->child->next->child; if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err; if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) || !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) || !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) { return CRYPT_INVALID_PACKET; } liter = lkdf->next->child->next; loptseq = liter->next; res->salt = lkdf->next->child; res->iterations = mp_get_int(liter->data); /* There's an optional INTEGER keyLength after the iterations, skip that if it's there. * c.f. RFC 2898 A.2 PBKDF2 */ if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) { loptseq = loptseq->next; } /* this sequence is optional */ lhmac = NULL; if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) && LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) { lhmac = loptseq->child; } if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err; if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) { /* 'NON-RC2'-CBC */ res->iv = lenc->next; } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) { /* RC2-CBC is a bit special ... * * RC2-CBC-Parameter ::= SEQUENCE { * rc2ParameterVersion INTEGER OPTIONAL, * iv OCTET STRING (SIZE(8)) } */ if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) && LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) { klen = mp_get_int(lenc->next->child->data); res->iv = lenc->next->child->next; /* * Effective Key Bits Encoding * 40 160 * 64 120 * 128 58 * b >= 256 b */ switch (klen) { case 160: res->key_bits = 40; break; case 120: res->key_bits = 64; break; case 58: res->key_bits = 128; break; default: /* We don't handle undefined Key Bits */ if (klen < 256) return CRYPT_INVALID_KEYSIZE; res->key_bits = klen; break; } } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) { res->iv = lenc->next->child; /* * If the rc2ParameterVersion field is omitted, the "effective key bits" * defaults to 32. */ res->key_bits = 32; } else { return CRYPT_INVALID_PACKET; } } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs12/000077500000000000000000000000001464416617300222425ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c000066400000000000000000000050071464416617300243370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PKCS_12 int pkcs12_kdf( int hash_id, const unsigned char *pw, unsigned long pwlen, const unsigned char *salt, unsigned long saltlen, unsigned int iterations, unsigned char purpose, unsigned char *out, unsigned long outlen) { unsigned long u = hash_descriptor[hash_id]->hashsize; unsigned long v = hash_descriptor[hash_id]->blocksize; unsigned long c = (outlen + u - 1) / u; unsigned long Slen = ((saltlen + v - 1) / v) * v; unsigned long Plen = ((pwlen + v - 1) / v) * v; unsigned long k = (Plen + Slen) / v; unsigned long Alen, keylen = 0; unsigned int tmp, i, j, n; unsigned char ch; unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE]; unsigned char *I, *key; int err = CRYPT_ERROR; LTC_ARGCHK(pw != NULL); LTC_ARGCHK(salt != NULL); LTC_ARGCHK(out != NULL); key = XMALLOC(u * c); I = XMALLOC(Plen + Slen); if (key == NULL || I == NULL) goto DONE; zeromem(key, u * c); for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */ for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen]; for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */ for (i = 0; i < c; i++) { Alen = sizeof(A); err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */ if (err != CRYPT_OK) goto DONE; for (j = 1; j < iterations; j++) { err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */ if (err != CRYPT_OK) goto DONE; } /* fill buffer B with A */ for (j = 0; j < v; j++) B[j] = A[j % Alen]; /* B += 1 */ for (j = v; j > 0; j--) { if (++B[j - 1] != 0) break; } /* I_n += B */ for (n = 0; n < k; n++) { ch = 0; for (j = v; j > 0; j--) { tmp = I[n * v + j - 1] + B[j - 1] + ch; ch = (unsigned char)((tmp >> 8) & 0xFF); I[n * v + j - 1] = (unsigned char)(tmp & 0xFF); } } /* store derived key block */ XMEMCPY(&key[keylen], A, Alen); keylen += Alen; } XMEMCPY(out, key, outlen); err = CRYPT_OK; DONE: if (I) { zeromem(I, Plen + Slen); XFREE(I); } if (key) { zeromem(key, u * c); XFREE(key); } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c000066400000000000000000000032741464416617300262140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PKCS_12 int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long len = 0; const unsigned char* in_end = in + inlen; const ulong32 offset[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; int err = CRYPT_ERROR; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); while (in < in_end) { ulong32 ch = 0; unsigned short extra = 0; /* 0 */ if (*in >= 192) extra++; /* 1 */ if (*in >= 224) extra++; /* 2 */ if (*in >= 240) extra++; /* 3 */ if (*in >= 248) extra++; /* 4 */ if (*in >= 252) extra++; /* 5 */ if (in + extra >= in_end) goto ERROR; switch (extra) { case 5: ch += *in++; ch <<= 6; /* FALLTHROUGH */ case 4: ch += *in++; ch <<= 6; /* FALLTHROUGH */ case 3: ch += *in++; ch <<= 6; /* FALLTHROUGH */ case 2: ch += *in++; ch <<= 6; /* FALLTHROUGH */ case 1: ch += *in++; ch <<= 6; /* FALLTHROUGH */ case 0: ch += *in++; default: break; } ch -= offset[extra]; if (ch > 0xFFFF) goto ERROR; if (*outlen >= len + 2) { out[len] = (unsigned short)((ch >> 8) & 0xFF); out[len + 1] = (unsigned char)(ch & 0xFF); } len += 2; } err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK; *outlen = len; ERROR: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs5/000077500000000000000000000000001464416617300221645ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c000066400000000000000000000147151464416617300237440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_5_1.c PKCS #5, Algorithm #1, Tom St Denis */ #ifdef LTC_PKCS_5 /** Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode. PKCS#5 v1 specifies that the output key length can be no larger than the hash output length. OpenSSL unilaterally extended that by repeating the hash process on a block-by-block basis for as long as needed to make bigger keys. If you want to be compatible with KDF for e.g. "openssl enc", you'll want that. If you want strict PKCS behavior, turn openssl_compat off. Or (more likely), use one of the convenience functions below. @param password The password (or key) @param password_len The length of the password (octet) @param salt The salt (or nonce) which is 8 octets long @param iteration_count The PKCS #5 v1 iteration count @param hash_idx The index of the hash desired @param out [out] The destination for this algorithm @param outlen [in/out] The max size and resulting size of the algorithm output @param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL @return CRYPT_OK if successful */ static int s_pkcs_5_alg1_common(const unsigned char *password, unsigned long password_len, const unsigned char *salt, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen, int openssl_compat) { int err; unsigned long x; hash_state *md; unsigned char *buf; /* Storage vars in case we need to support > hashsize (OpenSSL compat) */ unsigned long block = 0, iter; /* How many bytes to put in the outbut buffer (convenience calc) */ unsigned long outidx = 0, nb = 0; LTC_ARGCHK(password != NULL); LTC_ARGCHK(salt != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if (iteration_count <= 0) { return CRYPT_INVALID_ARG; } /* test hash IDX */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* allocate memory */ md = XMALLOC(sizeof(hash_state)); buf = XMALLOC(MAXBLOCKSIZE); if (md == NULL || buf == NULL) { if (md != NULL) { XFREE(md); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } while(block * hash_descriptor[hash_idx]->hashsize < *outlen) { /* hash initial (maybe previous hash) + password + salt */ if ((err = hash_descriptor[hash_idx]->init(md)) != CRYPT_OK) { goto LBL_ERR; } /* in OpenSSL mode, we first hash the previous result for blocks 2-n */ if (openssl_compat && block) { if ((err = hash_descriptor[hash_idx]->process(md, buf, hash_descriptor[hash_idx]->hashsize)) != CRYPT_OK) { goto LBL_ERR; } } if ((err = hash_descriptor[hash_idx]->process(md, password, password_len)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(md, salt, 8)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->done(md, buf)) != CRYPT_OK) { goto LBL_ERR; } iter = iteration_count; while (--iter) { /* code goes here. */ x = MAXBLOCKSIZE; if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx]->hashsize, buf, &x)) != CRYPT_OK) { goto LBL_ERR; } } /* limit the size of the copy to however many bytes we have left in the output buffer (and how many bytes we have to copy) */ outidx = block*hash_descriptor[hash_idx]->hashsize; nb = hash_descriptor[hash_idx]->hashsize; if(outidx+nb > *outlen) { nb = *outlen - outidx; } if(nb > 0) { XMEMCPY(out+outidx, buf, nb); } block++; if (!openssl_compat) { break; } } /* In strict mode, we always return the hashsize, in compat we filled it as much as was requested, so we leave it alone. */ if(!openssl_compat) { *outlen = hash_descriptor[hash_idx]->hashsize; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, MAXBLOCKSIZE); zeromem(md, sizeof(hash_state)); #endif XFREE(buf); XFREE(md); return err; } /** Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension) @param password The password (or key) @param password_len The length of the password (octet) @param salt The salt (or nonce) which is 8 octets long @param iteration_count The PKCS #5 v1 iteration count @param hash_idx The index of the hash desired @param out [out] The destination for this algorithm @param outlen [in/out] The max size and resulting size of the algorithm output @return CRYPT_OK if successful */ int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, const unsigned char *salt, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, hash_idx, out, outlen, 0); } /** Execute PKCS #5 v1 - OpenSSL-extension-compatible mode Use this one if you need to derive keys as "openssl enc" does by default. OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1. @param password The password (or key) @param password_len The length of the password (octet) @param salt The salt (or nonce) which is 8 octets long @param iteration_count The PKCS #5 v1 iteration count @param hash_idx The index of the hash desired @param out [out] The destination for this algorithm @param outlen [in/out] The max size and resulting size of the algorithm output @return CRYPT_OK if successful */ int pkcs_5_alg1_openssl(const unsigned char *password, unsigned long password_len, const unsigned char *salt, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, hash_idx, out, outlen, 1); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c000066400000000000000000000065411464416617300237430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_5_2.c PKCS #5, Algorithm #2, Tom St Denis */ #ifdef LTC_PKCS_5 /** Execute PKCS #5 v2 @param password The input password (or key) @param password_len The length of the password (octets) @param salt The salt (or nonce) @param salt_len The length of the salt (octets) @param iteration_count # of iterations desired for PKCS #5 v2 [read specs for more] @param hash_idx The index of the hash desired @param out [out] The destination for this algorithm @param outlen [in/out] The max size and resulting size of the algorithm output @return CRYPT_OK if successful */ int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, const unsigned char *salt, unsigned long salt_len, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { int err, itts; ulong32 blkno; unsigned long stored, left, x, y; unsigned char *buf[2]; hmac_state *hmac; LTC_ARGCHK(password != NULL); LTC_ARGCHK(salt != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if (iteration_count <= 0) { return CRYPT_INVALID_ARG; } /* test hash IDX */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } buf[0] = XMALLOC(MAXBLOCKSIZE * 2); hmac = XMALLOC(sizeof(hmac_state)); if (hmac == NULL || buf[0] == NULL) { if (hmac != NULL) { XFREE(hmac); } if (buf[0] != NULL) { XFREE(buf[0]); } return CRYPT_MEM; } /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ buf[1] = buf[0] + MAXBLOCKSIZE; left = *outlen; blkno = 1; stored = 0; while (left != 0) { /* process block number blkno */ zeromem(buf[0], MAXBLOCKSIZE*2); /* store current block number and increment for next pass */ STORE32H(blkno, buf[1]); ++blkno; /* get PRF(P, S||int(blkno)) */ if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { goto LBL_ERR; } x = MAXBLOCKSIZE; if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { goto LBL_ERR; } /* now compute repeated and XOR it in buf[1] */ XMEMCPY(buf[1], buf[0], x); for (itts = 1; itts < iteration_count; ++itts) { if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { goto LBL_ERR; } for (y = 0; y < x; y++) { buf[1][y] ^= buf[0][y]; } } /* now emit upto x bytes of buf[1] to output */ for (y = 0; y < x && left != 0; ++y) { out[stored++] = buf[1][y]; --left; } } *outlen = stored; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf[0], MAXBLOCKSIZE*2); zeromem(hmac, sizeof(hmac_state)); #endif XFREE(hmac); XFREE(buf[0]); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c000066400000000000000000000146711464416617300245640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file hkdf_test.c PKCS #5 support, self-test, Steffen Jaeckel */ #ifdef LTC_PKCS_5 /* TEST CASES SOURCE: Internet Engineering Task Force (IETF) S. Josefsson Request for Comments: 6070 SJD AB Category: Informational January 2011 ISSN: 2070-1721 */ /** PKCS #5 self-test @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. */ int pkcs_5_test (void) { #ifndef LTC_TEST return CRYPT_NOP; #else typedef struct { const char* P; unsigned long P_len; const char* S; unsigned long S_len; int c; unsigned long dkLen; unsigned char DK[40]; } case_item; static const case_item cases_5_2[] = { { "password", 8, "salt", 4, 1, 20, { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6 } }, { "password", 8, "salt", 4, 2, 20, { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57 } }, #ifdef LTC_TEST_EXT { "password", 8, "salt", 4, 4096, 20, { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1 } }, { "password", 8, "salt", 4, 16777216, 20, { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, 0x26, 0x34, 0xe9, 0x84 } }, { "passwordPASSWORDpassword", 25, "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, 25, { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 0x38 } }, { "pass\0word", 9, "sa\0lt", 5, 4096, 16, { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 } }, #endif /* LTC_TEST_EXT */ }; static const case_item cases_5_1[] = { { "password", 8, "saltsalt", /* must be 8 octects */ 8, /* ignored by alg1 */ 1, 20, { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } }, }; static const case_item cases_5_1o[] = { { "password", 8, "saltsalt", /* must be 8 octects */ 8, /* ignored by alg1_openssl */ 1, 20, { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } }, { "password", 8, "saltsalt", /* must be 8 octects */ 8, /* ignored by alg1_openssl */ 1, 30, { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44, 0xf0, 0xbf, 0xf4, 0xc1, 0x2c, 0xf3, 0x59, 0x6f, 0xc0, 0x0b } } }; unsigned char DK[40]; unsigned long dkLen; int i, err; int tested=0, failed=0; int hash = find_hash("sha1"); if (hash == -1) { #ifdef LTC_TEST_DBG printf("PKCS#5 test failed: 'sha1' hash not found\n"); #endif return CRYPT_ERROR; } /* testing alg 2 */ for(i=0; i < (int)(sizeof(cases_5_2) / sizeof(cases_5_2[0])); i++) { ++tested; dkLen = cases_5_2[i].dkLen; if((err = pkcs_5_alg2((unsigned char*)cases_5_2[i].P, cases_5_2[i].P_len, (unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len, cases_5_2[i].c, hash, DK, &dkLen)) != CRYPT_OK) { LTC_UNUSED_PARAM(err); #ifdef LTC_TEST_DBG printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err)); #endif ++failed; } else if (compare_testvector(DK, dkLen, cases_5_2[i].DK, cases_5_2[i].dkLen, "PKCS#5_2", i)) { ++failed; } } /* testing alg 1 */ for(i=0; i < (int)(sizeof(cases_5_1) / sizeof(case_item)); i++, tested++) { dkLen = cases_5_1[i].dkLen; if((err = pkcs_5_alg1((unsigned char*)cases_5_1[i].P, cases_5_1[i].P_len, (unsigned char*)cases_5_1[i].S, cases_5_1[i].c, hash, DK, &dkLen)) != CRYPT_OK) { LTC_UNUSED_PARAM(err); #ifdef LTC_TEST_DBG printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err)); #endif ++failed; } else if (compare_testvector(DK, dkLen, cases_5_1[i].DK, cases_5_1[i].dkLen, "PKCS#5_1", i)) { ++failed; } } /* testing alg 1_openssl */ for(i = 0; i < (int)(sizeof(cases_5_1o) / sizeof(cases_5_1o[0])); i++, tested++) { dkLen = cases_5_1o[i].dkLen; if ((err = pkcs_5_alg1_openssl((unsigned char*)cases_5_1o[i].P, cases_5_1o[i].P_len, (unsigned char*)cases_5_1o[i].S, cases_5_1o[i].c, hash, DK, &dkLen)) != CRYPT_OK) { LTC_UNUSED_PARAM(err); #ifdef LTC_TEST_DBG printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err)); #endif ++failed; } else if (compare_testvector(DK, dkLen, cases_5_1o[i].DK, cases_5_1o[i].dkLen, "PKCS#5_1o", i)) { ++failed; } } return (failed != 0) ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/ssh/000077500000000000000000000000001464416617300217345ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c000066400000000000000000000112151464416617300273020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file ssh_decode_sequence_multi.c SSH data type representation as per RFC4251, Russ Williams */ #ifdef LTC_SSH /** Decode a SSH sequence using a VA list @param in The input buffer @param inlen [in/out] The length of the input buffer and on output the amount of decoded data @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long*) @return CRYPT_OK on success */ int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) { int err; va_list args; ssh_data_type type; void *vdata; unsigned char *cdata; char *sdata; ulong32 *u32data; ulong64 *u64data; unsigned long *bufsize; ulong32 size; unsigned long remaining; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); remaining = *inlen; /* Decode values from buffer */ va_start(args, inlen); while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { /* Size of length field */ if (type == LTC_SSHDATA_STRING || type == LTC_SSHDATA_NAMELIST || type == LTC_SSHDATA_MPINT) { /* Check we'll not read too far */ if (remaining < 4) { err = CRYPT_BUFFER_OVERFLOW; goto error; } } /* Calculate (or read) length of data */ size = 0xFFFFFFFFU; switch (type) { case LTC_SSHDATA_BYTE: case LTC_SSHDATA_BOOLEAN: size = 1; break; case LTC_SSHDATA_UINT32: size = 4; break; case LTC_SSHDATA_UINT64: size = 8; break; case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: case LTC_SSHDATA_MPINT: LOAD32H(size, in); in += 4; remaining -= 4; break; case LTC_SSHDATA_EOL: default: /* Should never get here */ err = CRYPT_INVALID_ARG; goto error; } /* Check we'll not read too far */ if (remaining < size) { err = CRYPT_BUFFER_OVERFLOW; goto error; } else { remaining -= size; } vdata = va_arg(args, void*); if (vdata == NULL) { err = CRYPT_INVALID_ARG; goto error; } /* Read data */ switch (type) { case LTC_SSHDATA_BYTE: cdata = vdata; *cdata = *in++; break; case LTC_SSHDATA_BOOLEAN: cdata = vdata; /* The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. */ *cdata = (*in++)?1:0; break; case LTC_SSHDATA_UINT32: u32data = vdata; LOAD32H(*u32data, in); in += 4; break; case LTC_SSHDATA_UINT64: u64data = vdata; LOAD64H(*u64data, in); in += 8; break; case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: sdata = vdata; bufsize = va_arg(args, unsigned long*); if (bufsize == NULL) { err = CRYPT_INVALID_ARG; goto error; } if (size + 1 >= *bufsize) { err = CRYPT_BUFFER_OVERFLOW; goto error; } if (size > 0) { XMEMCPY(sdata, (const char *)in, size); } sdata[size] = '\0'; *bufsize = size; in += size; break; case LTC_SSHDATA_MPINT: if (size == 0) { if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; } } else if ((in[0] & 0x80) != 0) { /* Negative number - not supported */ err = CRYPT_INVALID_PACKET; goto error; } else { if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; } } in += size; break; case LTC_SSHDATA_EOL: default: /* Should never get here */ err = CRYPT_INVALID_ARG; goto error; } } err = CRYPT_OK; *inlen -= remaining; error: va_end(args); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c000066400000000000000000000113011464416617300273100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file ssh_encode_sequence_multi.c SSH data type representation as per RFC4251, Russ Williams */ #ifdef LTC_SSH /** Encode a SSH sequence using a VA list @param out [out] Destination for data @param outlen [in/out] Length of buffer and resulting length of output @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long) @return CRYPT_OK on success */ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) { int err; va_list args; ulong32 size; ssh_data_type type; void *vdata; const char *sdata; int idata; ulong32 u32data; ulong64 u64data; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* Check values and calculate output size */ size = 0; va_start(args, outlen); while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { switch (type) { case LTC_SSHDATA_BYTE: case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */ LTC_UNUSED_PARAM( va_arg(args, int) ); size++; break; case LTC_SSHDATA_UINT32: LTC_UNUSED_PARAM( va_arg(args, ulong32) ); size += 4; break; case LTC_SSHDATA_UINT64: LTC_UNUSED_PARAM( va_arg(args, ulong64) ); size += 8; break; case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: LTC_UNUSED_PARAM( va_arg(args, char*) ); size += va_arg(args, unsigned long); size += 4; break; case LTC_SSHDATA_MPINT: vdata = va_arg(args, void*); /* Calculate size */ size += 4; if (mp_iszero(vdata) != LTC_MP_YES) { size += mp_unsigned_bin_size(vdata); if ((mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */ } break; case LTC_SSHDATA_EOL: /* Should never get here */ default: err = CRYPT_INVALID_ARG; goto error; } } va_end(args); /* Check we have sufficient space */ if (*outlen < size) { *outlen = size; err = CRYPT_BUFFER_OVERFLOW; goto errornoargs; } *outlen = size; /* Encode values into buffer */ va_start(args, outlen); while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { switch (type) { case LTC_SSHDATA_BYTE: idata = va_arg(args, int); *out++ = (unsigned char)(idata & 255); break; case LTC_SSHDATA_BOOLEAN: idata = va_arg(args, int); /* The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. */ *out++ = (idata)?1:0; break; case LTC_SSHDATA_UINT32: u32data = va_arg(args, ulong32); STORE32H(u32data, out); out += 4; break; case LTC_SSHDATA_UINT64: u64data = va_arg(args, ulong64); STORE64H(u64data, out); out += 8; break; case LTC_SSHDATA_STRING: case LTC_SSHDATA_NAMELIST: sdata = va_arg(args, char*); size = va_arg(args, unsigned long); STORE32H(size, out); out += 4; XMEMCPY(out, sdata, size); out += size; break; case LTC_SSHDATA_MPINT: vdata = va_arg(args, void*); if (mp_iszero(vdata) == LTC_MP_YES) { STORE32H(0, out); out += 4; } else { size = mp_unsigned_bin_size(vdata); if ((mp_count_bits(vdata) & 7) == 0) { /* Zero padding if high bit set */ STORE32H(size+1, out); out += 4; *out++ = 0; } else { STORE32H(size, out); out += 4; } if (mp_to_unsigned_bin(vdata, out) != CRYPT_OK) { err = CRYPT_ERROR; goto error; } out += size; } break; case LTC_SSHDATA_EOL: /* Should never get here */ default: err = CRYPT_INVALID_ARG; goto error; } } err = CRYPT_OK; error: va_end(args); errornoargs: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/misc/zeromem.c000066400000000000000000000007571464416617300227720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file zeromem.c Zero a block of memory, Tom St Denis */ /** Zero a block of memory @param out The destination of the area to zero @param outlen The length of the area to zero (octets) */ void zeromem(volatile void *out, size_t outlen) { LTC_ARGCHKVD(out != NULL); memzero_explicit((void *)out, outlen); } optee_os-4.3.0/core/lib/libtomcrypt/src/modes/000077500000000000000000000000001464416617300213135ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/000077500000000000000000000000001464416617300220425ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/cbc_decrypt.c000066400000000000000000000043461464416617300244760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cbc_decrypt.c CBC implementation, encrypt block, Tom St Denis */ #ifdef LTC_CBC_MODE /** CBC decrypt @param ct Ciphertext @param pt [out] Plaintext @param len The number of bytes to process (must be multiple of block length) @param cbc CBC state @return CRYPT_OK if successful */ int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc) { int x, err; unsigned char tmp[16]; #ifdef LTC_FAST LTC_FAST_TYPE tmpy; #else unsigned char tmpy; #endif LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(cbc != NULL); if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { return err; } /* is blocklen valid? */ if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) { return CRYPT_INVALID_ARG; } if (len % cbc->blocklen) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif if (cipher_descriptor[cbc->cipher]->accel_cbc_decrypt != NULL) { return cipher_descriptor[cbc->cipher]->accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key); } while (len) { /* decrypt */ if ((err = cipher_descriptor[cbc->cipher]->ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) { return err; } /* xor IV against plaintext */ #if defined(LTC_FAST) for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { tmpy = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x)); *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) = tmpy; } #else for (x = 0; x < cbc->blocklen; x++) { tmpy = tmp[x] ^ cbc->IV[x]; cbc->IV[x] = ct[x]; pt[x] = tmpy; } #endif ct += cbc->blocklen; pt += cbc->blocklen; len -= cbc->blocklen; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/cbc_done.c000066400000000000000000000011021464416617300237340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cbc_done.c CBC implementation, finish chain, Tom St Denis */ #ifdef LTC_CBC_MODE /** Terminate the chain @param cbc The CBC chain to terminate @return CRYPT_OK on success */ int cbc_done(symmetric_CBC *cbc) { int err; LTC_ARGCHK(cbc != NULL); if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[cbc->cipher]->done(&cbc->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/cbc_encrypt.c000066400000000000000000000043031464416617300245010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cbc_encrypt.c CBC implementation, encrypt block, Tom St Denis */ #ifdef LTC_CBC_MODE /** CBC encrypt @param pt Plaintext @param ct [out] Ciphertext @param len The number of bytes to process (must be multiple of block length) @param cbc CBC state @return CRYPT_OK if successful */ int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc) { int x, err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(cbc != NULL); if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { return err; } /* is blocklen valid? */ if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) { return CRYPT_INVALID_ARG; } if (len % cbc->blocklen) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif if (cipher_descriptor[cbc->cipher]->accel_cbc_encrypt != NULL) { return cipher_descriptor[cbc->cipher]->accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key); } while (len) { /* xor IV against plaintext */ #if defined(LTC_FAST) for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)); } #else for (x = 0; x < cbc->blocklen; x++) { cbc->IV[x] ^= pt[x]; } #endif /* encrypt */ if ((err = cipher_descriptor[cbc->cipher]->ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) { return err; } /* store IV [ciphertext] for a future block */ #if defined(LTC_FAST) for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); } #else for (x = 0; x < cbc->blocklen; x++) { cbc->IV[x] = ct[x]; } #endif ct += cbc->blocklen; pt += cbc->blocklen; len -= cbc->blocklen; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/cbc_getiv.c000066400000000000000000000015461464416617300241410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cbc_getiv.c CBC implementation, get IV, Tom St Denis */ #ifdef LTC_CBC_MODE /** Get the current initialization vector @param IV [out] The destination of the initialization vector @param len [in/out] The max size and resulting size of the initialization vector @param cbc The CBC state @return CRYPT_OK if successful */ int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(len != NULL); LTC_ARGCHK(cbc != NULL); if ((unsigned long)cbc->blocklen > *len) { *len = cbc->blocklen; return CRYPT_BUFFER_OVERFLOW; } XMEMCPY(IV, cbc->IV, cbc->blocklen); *len = cbc->blocklen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/cbc_setiv.c000066400000000000000000000013031464416617300241440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cbc_setiv.c CBC implementation, set IV, Tom St Denis */ #ifdef LTC_CBC_MODE /** Set an initialization vector @param IV The initialization vector @param len The length of the vector (in octets) @param cbc The CBC state @return CRYPT_OK if successful */ int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(cbc != NULL); if (len != (unsigned long)cbc->blocklen) { return CRYPT_INVALID_ARG; } XMEMCPY(cbc->IV, IV, len); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cbc/cbc_start.c000066400000000000000000000024521464416617300241550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cbc_start.c CBC implementation, start chain, Tom St Denis */ #ifdef LTC_CBC_MODE /** Initialize a CBC context @param cipher The index of the cipher desired @param IV The initialization vector @param key The secret key @param keylen The length of the secret key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) @param cbc The CBC state to initialize @return CRYPT_OK if successful */ int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_CBC *cbc) { int x, err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(cbc != NULL); /* bad param? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* setup cipher */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { return err; } /* copy IV */ cbc->blocklen = cipher_descriptor[cipher]->block_length; cbc->cipher = cipher; for (x = 0; x < cbc->blocklen; x++) { cbc->IV[x] = IV[x]; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/000077500000000000000000000000001464416617300220455ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/cfb_decrypt.c000066400000000000000000000024701464416617300245000ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cfb_decrypt.c CFB implementation, decrypt data, Tom St Denis */ #ifdef LTC_CFB_MODE /** CFB decrypt @param ct Ciphertext @param pt [out] Plaintext @param len Length of ciphertext (octets) @param cfb CFB state @return CRYPT_OK if successful */ int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(cfb != NULL); if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { return err; } /* is blocklen/padlen valid? */ if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { return CRYPT_INVALID_ARG; } while (len-- > 0) { if (cfb->padlen == cfb->blocklen) { if ((err = cipher_descriptor[cfb->cipher]->ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) { return err; } cfb->padlen = 0; } cfb->pad[cfb->padlen] = *ct; *pt = *ct ^ cfb->IV[cfb->padlen]; ++pt; ++ct; ++(cfb->padlen); } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/cfb_done.c000066400000000000000000000011021464416617300237420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cfb_done.c CFB implementation, finish chain, Tom St Denis */ #ifdef LTC_CFB_MODE /** Terminate the chain @param cfb The CFB chain to terminate @return CRYPT_OK on success */ int cfb_done(symmetric_CFB *cfb) { int err; LTC_ARGCHK(cfb != NULL); if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[cfb->cipher]->done(&cfb->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/cfb_encrypt.c000066400000000000000000000024421464416617300245110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cfb_encrypt.c CFB implementation, encrypt data, Tom St Denis */ #ifdef LTC_CFB_MODE /** CFB encrypt @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param cfb CFB state @return CRYPT_OK if successful */ int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(cfb != NULL); if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { return err; } /* is blocklen/padlen valid? */ if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { return CRYPT_INVALID_ARG; } while (len-- > 0) { if (cfb->padlen == cfb->blocklen) { if ((err = cipher_descriptor[cfb->cipher]->ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) { return err; } cfb->padlen = 0; } cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]); ++pt; ++ct; ++(cfb->padlen); } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/cfb_getiv.c000066400000000000000000000015461464416617300241470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cfb_getiv.c CFB implementation, get IV, Tom St Denis */ #ifdef LTC_CFB_MODE /** Get the current initialization vector @param IV [out] The destination of the initialization vector @param len [in/out] The max size and resulting size of the initialization vector @param cfb The CFB state @return CRYPT_OK if successful */ int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(len != NULL); LTC_ARGCHK(cfb != NULL); if ((unsigned long)cfb->blocklen > *len) { *len = cfb->blocklen; return CRYPT_BUFFER_OVERFLOW; } XMEMCPY(IV, cfb->IV, cfb->blocklen); *len = cfb->blocklen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/cfb_setiv.c000066400000000000000000000015561464416617300241640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cfb_setiv.c CFB implementation, set IV, Tom St Denis */ #ifdef LTC_CFB_MODE /** Set an initialization vector @param IV The initialization vector @param len The length of the vector (in octets) @param cfb The CFB state @return CRYPT_OK if successful */ int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb) { int err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(cfb != NULL); if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { return err; } if (len != (unsigned long)cfb->blocklen) { return CRYPT_INVALID_ARG; } /* force next block */ cfb->padlen = 0; return cipher_descriptor[cfb->cipher]->ecb_encrypt(IV, cfb->IV, &cfb->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/cfb/cfb_start.c000066400000000000000000000026101464416617300241570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file cfb_start.c CFB implementation, start chain, Tom St Denis */ #ifdef LTC_CFB_MODE /** Initialize a CFB context @param cipher The index of the cipher desired @param IV The initialization vector @param key The secret key @param keylen The length of the secret key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) @param cfb The CFB state to initialize @return CRYPT_OK if successful */ int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_CFB *cfb) { int x, err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(cfb != NULL); if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* copy data */ cfb->cipher = cipher; cfb->blocklen = cipher_descriptor[cipher]->block_length; for (x = 0; x < cfb->blocklen; x++) { cfb->IV[x] = IV[x]; } /* init the cipher */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) { return err; } /* encrypt the IV */ cfb->padlen = 0; return cipher_descriptor[cfb->cipher]->ecb_encrypt(cfb->IV, cfb->IV, &cfb->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/000077500000000000000000000000001464416617300221035ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_decrypt.c000066400000000000000000000012341464416617300245710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_decrypt.c CTR implementation, decrypt data, Tom St Denis */ #ifdef LTC_CTR_MODE /** CTR decrypt @param ct Ciphertext @param pt [out] Plaintext @param len Length of ciphertext (octets) @param ctr CTR state @return CRYPT_OK if successful */ int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(ctr != NULL); return ctr_encrypt(ct, pt, len, ctr); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_done.c000066400000000000000000000011021464416617300240360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_done.c CTR implementation, finish chain, Tom St Denis */ #ifdef LTC_CTR_MODE /** Terminate the chain @param ctr The CTR chain to terminate @return CRYPT_OK on success */ int ctr_done(symmetric_CTR *ctr) { int err; LTC_ARGCHK(ctr != NULL); if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[ctr->cipher]->done(&ctr->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_encrypt.c000066400000000000000000000100161464416617300246010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_encrypt.c CTR implementation, encrypt data, Tom St Denis */ #ifdef LTC_CTR_MODE static void s_ctr_increment_counter(symmetric_CTR *ctr) { int x; if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { for (x = 0; x < ctr->ctrlen; x++) { ctr->ctr[x] = (ctr->ctr[x] + 1) & 0xff; if (ctr->ctr[x]) return; } } else { for (x = ctr->blocklen - 1; x >= ctr->ctrlen; x--) { ctr->ctr[x] = (ctr->ctr[x] + 1) & 0xff; if (ctr->ctr[x]) { return; } } } } /** CTR encrypt software implementation @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param ctr CTR state @return CRYPT_OK if successful */ static int s_ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) { int err; while (len) { /* is the pad empty? */ if (ctr->padlen == ctr->blocklen) { /* encrypt counter into pad */ if ((err = cipher_descriptor[ctr->cipher]->ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) { return err; } ctr->padlen = 0; } #ifdef LTC_FAST if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) { for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x)); } pt += ctr->blocklen; ct += ctr->blocklen; len -= ctr->blocklen; ctr->padlen = ctr->blocklen; continue; } #endif *ct++ = *pt++ ^ ctr->pad[ctr->padlen++]; --len; /* done with one full block? if so, set counter for next block. */ if (ctr->padlen == ctr->blocklen) { s_ctr_increment_counter(ctr); } } return CRYPT_OK; } /** CTR encrypt @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param ctr CTR state @return CRYPT_OK if successful */ int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) { unsigned long incr; int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(ctr != NULL); if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { return err; } /* is blocklen/padlen valid? */ if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) || (ctr->padlen < 0) || (ctr->padlen > (int)sizeof(ctr->pad))) { return CRYPT_INVALID_ARG; } #ifdef LTC_FAST if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif if (cipher_descriptor[ctr->cipher]->accel_ctr_encrypt != NULL ) { /* handle acceleration only if not in the middle of a block, accelerator is present and length is >= a block size */ if ((ctr->padlen == 0 || ctr->padlen == ctr->blocklen) && len >= (unsigned long)ctr->blocklen) { if ((err = cipher_descriptor[ctr->cipher]->accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { return err; } pt += (len / ctr->blocklen) * ctr->blocklen; ct += (len / ctr->blocklen) * ctr->blocklen; len %= ctr->blocklen; /* counter was changed by accelerator so mark pad empty (will need updating in s_ctr_encrypt()) */ ctr->padlen = ctr->blocklen; } /* try to re-synchronize on a block boundary for maximum use of acceleration */ incr = ctr->blocklen - ctr->padlen; if (len >= incr + (unsigned long)ctr->blocklen) { if ((err = s_ctr_encrypt(pt, ct, incr, ctr)) != CRYPT_OK) { return err; } pt += incr; ct += incr; len -= incr; return ctr_encrypt(pt, ct, len, ctr); } } return s_ctr_encrypt(pt, ct, len, ctr); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_getiv.c000066400000000000000000000015471464416617300242440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_getiv.c CTR implementation, get IV, Tom St Denis */ #ifdef LTC_CTR_MODE /** Get the current initialization vector @param IV [out] The destination of the initialization vector @param len [in/out] The max size and resulting size of the initialization vector @param ctr The CTR state @return CRYPT_OK if successful */ int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(len != NULL); LTC_ARGCHK(ctr != NULL); if ((unsigned long)ctr->blocklen > *len) { *len = ctr->blocklen; return CRYPT_BUFFER_OVERFLOW; } XMEMCPY(IV, ctr->ctr, ctr->blocklen); *len = ctr->blocklen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_setiv.c000066400000000000000000000016621464416617300242560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_setiv.c CTR implementation, set IV, Tom St Denis */ #ifdef LTC_CTR_MODE /** Set an initialization vector @param IV The initialization vector @param len The length of the vector (in octets) @param ctr The CTR state @return CRYPT_OK if successful */ int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr) { int err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(ctr != NULL); /* bad param? */ if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { return err; } if (len != (unsigned long)ctr->blocklen) { return CRYPT_INVALID_ARG; } /* set IV */ XMEMCPY(ctr->ctr, IV, len); /* force next block */ ctr->padlen = 0; return cipher_descriptor[ctr->cipher]->ecb_encrypt(IV, ctr->pad, &ctr->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_start.c000066400000000000000000000052211464416617300242540ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_start.c CTR implementation, start chain, Tom St Denis */ #ifdef LTC_CTR_MODE /** Initialize a CTR context @param cipher The index of the cipher desired @param IV The initialization vector @param key The secret key @param keylen The length of the secret key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN) @param ctr The CTR state to initialize @return CRYPT_OK if successful */ int ctr_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, int ctr_mode, symmetric_CTR *ctr) { int x, err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ctr != NULL); /* bad param? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* ctrlen == counter width */ ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher]->block_length; if (ctr->ctrlen > cipher_descriptor[cipher]->block_length) { return CRYPT_INVALID_ARG; } if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) { ctr->ctrlen = cipher_descriptor[cipher]->block_length - ctr->ctrlen; } /* setup cipher */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) { return err; } /* copy ctr */ ctr->blocklen = cipher_descriptor[cipher]->block_length; ctr->cipher = cipher; ctr->padlen = 0; ctr->mode = ctr_mode & 0x1000; for (x = 0; x < ctr->blocklen; x++) { ctr->ctr[x] = IV[x]; } if (ctr_mode & LTC_CTR_RFC3686) { /* increment the IV as per RFC 3686 */ if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { /* little-endian */ for (x = 0; x < ctr->ctrlen; x++) { ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; if (ctr->ctr[x] != (unsigned char)0) { break; } } } else { /* big-endian */ for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) { ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; if (ctr->ctr[x] != (unsigned char)0) { break; } } } } return cipher_descriptor[ctr->cipher]->ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ctr/ctr_test.c000066400000000000000000000043011464416617300240740ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ctr_test.c CTR implementation, Tests again RFC 3686, Tom St Denis */ #ifdef LTC_CTR_MODE int ctr_test(void) { #ifdef LTC_NO_TEST return CRYPT_NOP; #else static const struct { int keylen, msglen; unsigned char key[32], IV[16], pt[64], ct[64]; } tests[] = { /* 128-bit key, 16-byte pt */ { 16, 16, {0xAE,0x68,0x52,0xF8,0x12,0x10,0x67,0xCC,0x4B,0xF7,0xA5,0x76,0x55,0x77,0xF3,0x9E }, {0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, {0x53,0x69,0x6E,0x67,0x6C,0x65,0x20,0x62,0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x73,0x67 }, {0xE4,0x09,0x5D,0x4F,0xB7,0xA7,0xB3,0x79,0x2D,0x61,0x75,0xA3,0x26,0x13,0x11,0xB8 }, }, /* 128-bit key, 36-byte pt */ { 16, 36, {0x76,0x91,0xBE,0x03,0x5E,0x50,0x20,0xA8,0xAC,0x6E,0x61,0x85,0x29,0xF9,0xA0,0xDC }, {0x00,0xE0,0x01,0x7B,0x27,0x77,0x7F,0x3F,0x4A,0x17,0x86,0xF0,0x00,0x00,0x00,0x00 }, {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, 0x20,0x21,0x22,0x23}, {0xC1,0xCF,0x48,0xA8,0x9F,0x2F,0xFD,0xD9,0xCF,0x46,0x52,0xE9,0xEF,0xDB,0x72,0xD7, 0x45,0x40,0xA4,0x2B,0xDE,0x6D,0x78,0x36,0xD5,0x9A,0x5C,0xEA,0xAE,0xF3,0x10,0x53, 0x25,0xB2,0x07,0x2F }, }, }; int idx, err, x; unsigned char buf[64]; symmetric_CTR ctr; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { if ((err = ctr_start(idx, tests[x].IV, tests[x].key, tests[x].keylen, 0, CTR_COUNTER_BIG_ENDIAN|LTC_CTR_RFC3686, &ctr)) != CRYPT_OK) { return err; } if ((err = ctr_encrypt(tests[x].pt, buf, tests[x].msglen, &ctr)) != CRYPT_OK) { return err; } ctr_done(&ctr); if (compare_testvector(buf, tests[x].msglen, tests[x].ct, tests[x].msglen, "CTR", x)) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ecb/000077500000000000000000000000001464416617300220445ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ecb/ecb_decrypt.c000066400000000000000000000026331464416617300244770ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecb_decrypt.c ECB implementation, decrypt a block, Tom St Denis */ #ifdef LTC_ECB_MODE /** ECB decrypt @param ct Ciphertext @param pt [out] Plaintext @param len The number of octets to process (must be multiple of the cipher block size) @param ecb ECB state @return CRYPT_OK if successful */ int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(ecb != NULL); if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { return err; } if (len % cipher_descriptor[ecb->cipher]->block_length) { return CRYPT_INVALID_ARG; } /* check for accel */ if (cipher_descriptor[ecb->cipher]->accel_ecb_decrypt != NULL) { return cipher_descriptor[ecb->cipher]->accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher]->block_length, &ecb->key); } while (len) { if ((err = cipher_descriptor[ecb->cipher]->ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) { return err; } pt += cipher_descriptor[ecb->cipher]->block_length; ct += cipher_descriptor[ecb->cipher]->block_length; len -= cipher_descriptor[ecb->cipher]->block_length; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ecb/ecb_done.c000066400000000000000000000011021464416617300237400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecb_done.c ECB implementation, finish chain, Tom St Denis */ #ifdef LTC_ECB_MODE /** Terminate the chain @param ecb The ECB chain to terminate @return CRYPT_OK on success */ int ecb_done(symmetric_ECB *ecb) { int err; LTC_ARGCHK(ecb != NULL); if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[ecb->cipher]->done(&ecb->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ecb/ecb_encrypt.c000066400000000000000000000026331464416617300245110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecb_encrypt.c ECB implementation, encrypt a block, Tom St Denis */ #ifdef LTC_ECB_MODE /** ECB encrypt @param pt Plaintext @param ct [out] Ciphertext @param len The number of octets to process (must be multiple of the cipher block size) @param ecb ECB state @return CRYPT_OK if successful */ int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(ecb != NULL); if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { return err; } if (len % cipher_descriptor[ecb->cipher]->block_length) { return CRYPT_INVALID_ARG; } /* check for accel */ if (cipher_descriptor[ecb->cipher]->accel_ecb_encrypt != NULL) { return cipher_descriptor[ecb->cipher]->accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher]->block_length, &ecb->key); } while (len) { if ((err = cipher_descriptor[ecb->cipher]->ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) { return err; } pt += cipher_descriptor[ecb->cipher]->block_length; ct += cipher_descriptor[ecb->cipher]->block_length; len -= cipher_descriptor[ecb->cipher]->block_length; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ecb/ecb_start.c000066400000000000000000000017571464416617300241700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecb_start.c ECB implementation, start chain, Tom St Denis */ #ifdef LTC_ECB_MODE /** Initialize a ECB context @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) @param ecb The ECB state to initialize @return CRYPT_OK if successful */ int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ecb != NULL); if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } ecb->cipher = cipher; ecb->blocklen = cipher_descriptor[cipher]->block_length; return cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &ecb->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/000077500000000000000000000000001464416617300216305ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_decrypt.c000066400000000000000000000012221464416617300240400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f8_decrypt.c F8 implementation, decrypt data, Tom St Denis */ #ifdef LTC_F8_MODE /** F8 decrypt @param ct Ciphertext @param pt [out] Plaintext @param len Length of ciphertext (octets) @param f8 F8 state @return CRYPT_OK if successful */ int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(f8 != NULL); return f8_encrypt(ct, pt, len, f8); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_done.c000066400000000000000000000010661464416617300233210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f8_done.c F8 implementation, finish chain, Tom St Denis */ #ifdef LTC_F8_MODE /** Terminate the chain @param f8 The F8 chain to terminate @return CRYPT_OK on success */ int f8_done(symmetric_F8 *f8) { int err; LTC_ARGCHK(f8 != NULL); if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[f8->cipher]->done(&f8->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_encrypt.c000066400000000000000000000053211464416617300240560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f8_encrypt.c F8 implementation, encrypt data, Tom St Denis */ #ifdef LTC_F8_MODE /** F8 encrypt @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param f8 F8 state @return CRYPT_OK if successful */ int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8) { int err, x; unsigned char buf[MAXBLOCKSIZE]; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(f8 != NULL); if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { return err; } /* is blocklen/padlen valid? */ if (f8->blocklen < 0 || f8->blocklen > (int)sizeof(f8->IV) || f8->padlen < 0 || f8->padlen > (int)sizeof(f8->IV)) { return CRYPT_INVALID_ARG; } zeromem(buf, sizeof(buf)); /* make sure the pad is empty */ if (f8->padlen == f8->blocklen) { /* xor of IV, MIV and blockcnt == what goes into cipher */ STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); ++(f8->blockcnt); for (x = 0; x < f8->blocklen; x++) { f8->IV[x] ^= f8->MIV[x] ^ buf[x]; } if ((err = cipher_descriptor[f8->cipher]->ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { return err; } f8->padlen = 0; } #ifdef LTC_FAST if (f8->padlen == 0) { while (len >= (unsigned long)f8->blocklen) { STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); ++(f8->blockcnt); for (x = 0; x < f8->blocklen; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&ct[x])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])); *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&f8->MIV[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&buf[x])); } if ((err = cipher_descriptor[f8->cipher]->ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { return err; } len -= x; pt += x; ct += x; } } #endif while (len > 0) { if (f8->padlen == f8->blocklen) { /* xor of IV, MIV and blockcnt == what goes into cipher */ STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); ++(f8->blockcnt); for (x = 0; x < f8->blocklen; x++) { f8->IV[x] ^= f8->MIV[x] ^ buf[x]; } if ((err = cipher_descriptor[f8->cipher]->ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { return err; } f8->padlen = 0; } *ct++ = *pt++ ^ f8->IV[f8->padlen++]; --len; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_getiv.c000066400000000000000000000015331464416617300235110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_getiv.c F8 implementation, get IV, Tom St Denis */ #ifdef LTC_F8_MODE /** Get the current initialization vector @param IV [out] The destination of the initialization vector @param len [in/out] The max size and resulting size of the initialization vector @param f8 The F8 state @return CRYPT_OK if successful */ int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(len != NULL); LTC_ARGCHK(f8 != NULL); if ((unsigned long)f8->blocklen > *len) { *len = f8->blocklen; return CRYPT_BUFFER_OVERFLOW; } XMEMCPY(IV, f8->IV, f8->blocklen); *len = f8->blocklen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_setiv.c000066400000000000000000000015411464416617300235240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f8_setiv.c F8 implementation, set IV, Tom St Denis */ #ifdef LTC_F8_MODE /** Set an initialization vector @param IV The initialization vector @param len The length of the vector (in octets) @param f8 The F8 state @return CRYPT_OK if successful */ int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8) { int err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(f8 != NULL); if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { return err; } if (len != (unsigned long)f8->blocklen) { return CRYPT_INVALID_ARG; } /* force next block */ f8->padlen = 0; return cipher_descriptor[f8->cipher]->ecb_encrypt(IV, f8->IV, &f8->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_start.c000066400000000000000000000051061464416617300235300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f8_start.c F8 implementation, start chain, Tom St Denis */ #ifdef LTC_F8_MODE /** Initialize an F8 context @param cipher The index of the cipher desired @param IV The initialization vector @param key The secret key @param keylen The length of the secret key (octets) @param salt_key The salting key for the IV @param skeylen The length of the salting key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) @param f8 The F8 state to initialize @return CRYPT_OK if successful */ int f8_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *salt_key, int skeylen, int num_rounds, symmetric_F8 *f8) { int x, err; unsigned char tkey[MAXBLOCKSIZE]; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(salt_key != NULL); LTC_ARGCHK(f8 != NULL); if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } #ifdef LTC_FAST if (cipher_descriptor[cipher]->block_length % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* copy details */ f8->blockcnt = 0; f8->cipher = cipher; f8->blocklen = cipher_descriptor[cipher]->block_length; f8->padlen = f8->blocklen; /* now get key ^ salt_key [extend salt_ket with 0x55 as required to match length] */ zeromem(tkey, sizeof(tkey)); for (x = 0; x < keylen && x < (int)sizeof(tkey); x++) { tkey[x] = key[x]; } for (x = 0; x < skeylen && x < (int)sizeof(tkey); x++) { tkey[x] ^= salt_key[x]; } for (; x < keylen && x < (int)sizeof(tkey); x++) { tkey[x] ^= 0x55; } /* now encrypt with tkey[0..keylen-1] the IV and use that as the IV */ if ((err = cipher_descriptor[cipher]->setup(tkey, keylen, num_rounds, &f8->key)) != CRYPT_OK) { return err; } /* encrypt IV */ if ((err = cipher_descriptor[f8->cipher]->ecb_encrypt(IV, f8->MIV, &f8->key)) != CRYPT_OK) { cipher_descriptor[f8->cipher]->done(&f8->key); return err; } zeromem(tkey, sizeof(tkey)); zeromem(f8->IV, sizeof(f8->IV)); /* terminate this cipher */ cipher_descriptor[f8->cipher]->done(&f8->key); /* init the cipher */ return cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &f8->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/f8/f8_test_mode.c000066400000000000000000000044061464416617300243600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file f8_test_mode.c F8 implementation, test, Tom St Denis */ #ifdef LTC_F8_MODE int f8_test_mode(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const unsigned char key[16] = { 0x23, 0x48, 0x29, 0x00, 0x84, 0x67, 0xbe, 0x18, 0x6c, 0x3d, 0xe1, 0x4a, 0xae, 0x72, 0xd6, 0x2c }; static const unsigned char salt[4] = { 0x32, 0xf2, 0x87, 0x0d }; static const unsigned char IV[16] = { 0x00, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5, 0x5c, 0x62, 0x15, 0x99, 0xd4, 0x62, 0x56, 0x4a }; static const unsigned char pt[39] = { 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67 }; static const unsigned char ct[39] = { 0x01, 0x9c, 0xe7, 0xa2, 0x6e, 0x78, 0x54, 0x01, 0x4a, 0x63, 0x66, 0xaa, 0x95, 0xd4, 0xee, 0xfd, 0x1a, 0xd4, 0x17, 0x2a, 0x14, 0xf9, 0xfa, 0xf4, 0x55, 0xb7, 0xf1, 0xd4, 0xb6, 0x2b, 0xd0, 0x8f, 0x56, 0x2c, 0x0e, 0xef, 0x7c, 0x48, 0x02 }; unsigned char buf[39]; symmetric_F8 f8; int err, idx; idx = find_cipher("aes"); if (idx == -1) { idx = find_cipher("rijndael"); if (idx == -1) return CRYPT_NOP; } /* initialize the context */ if ((err = f8_start(idx, IV, key, sizeof(key), salt, sizeof(salt), 0, &f8)) != CRYPT_OK) { return err; } /* encrypt block */ if ((err = f8_encrypt(pt, buf, sizeof(pt), &f8)) != CRYPT_OK) { f8_done(&f8); return err; } f8_done(&f8); /* compare */ if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "f8", 0)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/000077500000000000000000000000001464416617300221175ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_decrypt.c000066400000000000000000000017041464416617300246230ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_decrypt.c LRW_MODE implementation, Decrypt blocks, Tom St Denis */ #ifdef LTC_LRW_MODE /** LRW decrypt blocks @param ct The ciphertext @param pt [out] The plaintext @param len The length in octets, must be a multiple of 16 @param lrw The LRW state */ int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(lrw != NULL); if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[lrw->cipher]->accel_lrw_decrypt != NULL) { return cipher_descriptor[lrw->cipher]->accel_lrw_decrypt(ct, pt, len, lrw->IV, lrw->tweak, &lrw->key); } return lrw_process(ct, pt, len, LRW_DECRYPT, lrw); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_done.c000066400000000000000000000011131464416617300240700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_done.c LRW_MODE implementation, Free resources, Tom St Denis */ #ifdef LTC_LRW_MODE /** Terminate a LRW state @param lrw The state to terminate @return CRYPT_OK if successful */ int lrw_done(symmetric_LRW *lrw) { int err; LTC_ARGCHK(lrw != NULL); if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[lrw->cipher]->done(&lrw->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_encrypt.c000066400000000000000000000017041464416617300246350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_encrypt.c LRW_MODE implementation, Encrypt blocks, Tom St Denis */ #ifdef LTC_LRW_MODE /** LRW encrypt blocks @param pt The plaintext @param ct [out] The ciphertext @param len The length in octets, must be a multiple of 16 @param lrw The LRW state */ int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(lrw != NULL); if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[lrw->cipher]->accel_lrw_encrypt != NULL) { return cipher_descriptor[lrw->cipher]->accel_lrw_encrypt(pt, ct, len, lrw->IV, lrw->tweak, &lrw->key); } return lrw_process(pt, ct, len, LRW_ENCRYPT, lrw); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_getiv.c000066400000000000000000000014041464416617300242640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_getiv.c LRW_MODE implementation, Retrieve the current IV, Tom St Denis */ #ifdef LTC_LRW_MODE /** Get the IV for LRW @param IV [out] The IV, must be 16 octets @param len Length ... must be at least 16 :-) @param lrw The LRW state to read @return CRYPT_OK if successful */ int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(len != NULL); LTC_ARGCHK(lrw != NULL); if (*len < 16) { *len = 16; return CRYPT_BUFFER_OVERFLOW; } XMEMCPY(IV, lrw->IV, 16); *len = 16; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_process.c000066400000000000000000000056431464416617300246350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_process.c LRW_MODE implementation, Encrypt/decrypt blocks, Tom St Denis */ #ifdef LTC_LRW_MODE /** Process blocks with LRW, since decrypt/encrypt are largely the same they share this code. @param pt The "input" data @param ct [out] The "output" data @param len The length of the input, must be a multiple of 128-bits (16 octets) @param mode LRW_ENCRYPT or LRW_DECRYPT @param lrw The LRW state @return CRYPT_OK if successful */ int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw) { unsigned char prod[16]; int x, err; #ifdef LTC_LRW_TABLES int y; #endif LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(lrw != NULL); if (len & 15) { return CRYPT_INVALID_ARG; } while (len) { /* copy pad */ XMEMCPY(prod, lrw->pad, 16); /* increment IV */ for (x = 15; x >= 0; x--) { lrw->IV[x] = (lrw->IV[x] + 1) & 255; if (lrw->IV[x]) { break; } } /* update pad */ #ifdef LTC_LRW_TABLES /* for each byte changed we undo it's affect on the pad then add the new product */ for (; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(lrw->pad + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][lrw->IV[x]][y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][(lrw->IV[x]-1)&255][y])); } #else for (y = 0; y < 16; y++) { lrw->pad[y] ^= lrw->PC[x][lrw->IV[x]][y] ^ lrw->PC[x][(lrw->IV[x]-1)&255][y]; } #endif } #else gcm_gf_mult(lrw->tweak, lrw->IV, lrw->pad); #endif /* xor prod */ #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x)); } #else for (x = 0; x < 16; x++) { ct[x] = pt[x] ^ prod[x]; } #endif /* send through cipher */ if (mode == LRW_ENCRYPT) { if ((err = cipher_descriptor[lrw->cipher]->ecb_encrypt(ct, ct, &lrw->key)) != CRYPT_OK) { return err; } } else { if ((err = cipher_descriptor[lrw->cipher]->ecb_decrypt(ct, ct, &lrw->key)) != CRYPT_OK) { return err; } } /* xor prod */ #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(ct + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x)); } #else for (x = 0; x < 16; x++) { ct[x] = ct[x] ^ prod[x]; } #endif /* move to next */ pt += 16; ct += 16; len -= 16; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_setiv.c000066400000000000000000000031521464416617300243020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_setiv.c LRW_MODE implementation, Set the current IV, Tom St Denis */ #ifdef LTC_LRW_MODE /** Set the IV for LRW @param IV The IV, must be 16 octets @param len Length ... must be 16 :-) @param lrw The LRW state to update @return CRYPT_OK if successful */ int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw) { int err; #ifdef LTC_LRW_TABLES unsigned char T[16]; int x, y; #endif LTC_ARGCHK(IV != NULL); LTC_ARGCHK(lrw != NULL); if (len != 16) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { return err; } /* copy the IV */ XMEMCPY(lrw->IV, IV, 16); /* check if we have to actually do work */ if (cipher_descriptor[lrw->cipher]->accel_lrw_encrypt != NULL && cipher_descriptor[lrw->cipher]->accel_lrw_decrypt != NULL) { /* we have accelerators, let's bail since they don't use lrw->pad anyways */ return CRYPT_OK; } #ifdef LTC_LRW_TABLES XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16); for (x = 1; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][IV[x]][y])); } #else for (y = 0; y < 16; y++) { T[y] ^= lrw->PC[x][IV[x]][y]; } #endif } XMEMCPY(lrw->pad, T, 16); #else gcm_gf_mult(lrw->tweak, IV, lrw->pad); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_start.c000066400000000000000000000047441464416617300243150ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_start.c LRW_MODE implementation, start mode, Tom St Denis */ #ifdef LTC_LRW_MODE /** Initialize the LRW context @param cipher The cipher desired, must be a 128-bit block cipher @param IV The index value, must be 128-bits @param key The cipher key @param keylen The length of the cipher key in octets @param tweak The tweak value (second key), must be 128-bits @param num_rounds The number of rounds for the cipher (0 == default) @param lrw [out] The LRW state @return CRYPT_OK on success. */ int lrw_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *tweak, int num_rounds, symmetric_LRW *lrw) { int err; #ifdef LTC_LRW_TABLES unsigned char B[16]; int x, y, z, t; #endif LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(tweak != NULL); LTC_ARGCHK(lrw != NULL); #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* is cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher]->block_length != 16) { return CRYPT_INVALID_CIPHER; } /* schedule key */ if ((err = cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &lrw->key)) != CRYPT_OK) { return err; } lrw->cipher = cipher; /* copy the IV and tweak */ XMEMCPY(lrw->tweak, tweak, 16); #ifdef LTC_LRW_TABLES /* setup tables */ /* generate the first table as it has no shifting (from which we make the other tables) */ zeromem(B, 16); for (y = 0; y < 256; y++) { B[0] = y; gcm_gf_mult(tweak, B, &lrw->PC[0][y][0]); } /* now generate the rest of the tables based the previous table */ for (x = 1; x < 16; x++) { for (y = 0; y < 256; y++) { /* now shift it right by 8 bits */ t = lrw->PC[x-1][y][15]; for (z = 15; z > 0; z--) { lrw->PC[x][y][z] = lrw->PC[x-1][y][z-1]; } lrw->PC[x][y][0] = gcm_shift_table[t<<1]; lrw->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; } } #endif /* generate first pad */ return lrw_setiv(IV, 16, lrw); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/lrw/lrw_test.c000066400000000000000000000104251464416617300241300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file lrw_test.c LRW_MODE implementation, test LRW, Tom St Denis */ #ifdef LTC_LRW_MODE /** Test LRW against specs @return CRYPT_OK if goodly */ int lrw_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { unsigned char key[16], tweak[16], IV[16], P[16], expected_tweak[16], C[16]; } tests[] = { { { 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85 }, { 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, { 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, { 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 } }, { { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, { 0x35, 0x23, 0xc2, 0xde, 0xc5, 0x69, 0x4f, 0xa8, 0x72, 0xa9, 0xac, 0xa7, 0x0b, 0x2b, 0xee, 0xbc }, { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, { 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, }, { { 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, { 0x67, 0x53, 0xc9, 0x0c, 0xb7, 0xd8, 0xcd, 0xe5, 0x06, 0xa0, 0x47, 0x78, 0x1a, 0xad, 0x85, 0x11 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, { 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, { 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, }, { { 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47 }, { 0x4e, 0xb5, 0x5d, 0x31, 0x05, 0x97, 0x3a, 0x3f, 0x5e, 0x23, 0xda, 0xfb, 0x5a, 0x45, 0xd6, 0xc0 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, { 0x18, 0xc9, 0x1f, 0x6d, 0x60, 0x1a, 0x1a, 0x37, 0x5d, 0x0b, 0x0e, 0xf7, 0x3a, 0xd5, 0x74, 0xc4 }, { 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 }, } }; int idx, err, x; symmetric_LRW lrw; unsigned char buf[2][16]; idx = find_cipher("aes"); if (idx == -1) { idx = find_cipher("rijndael"); if (idx == -1) { return CRYPT_NOP; } } for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { /* schedule it */ if ((err = lrw_start(idx, tests[x].IV, tests[x].key, 16, tests[x].tweak, 0, &lrw)) != CRYPT_OK) { return err; } /* check pad against expected tweak */ if (compare_testvector(tests[x].expected_tweak, 16, lrw.pad, 16, "LRW Tweak", x)) { lrw_done(&lrw); return CRYPT_FAIL_TESTVECTOR; } /* process block */ if ((err = lrw_encrypt(tests[x].P, buf[0], 16, &lrw)) != CRYPT_OK) { lrw_done(&lrw); return err; } if (compare_testvector(buf[0], 16, tests[x].C, 16, "LRW Encrypt", x)) { lrw_done(&lrw); return CRYPT_FAIL_TESTVECTOR; } /* process block */ if ((err = lrw_setiv(tests[x].IV, 16, &lrw)) != CRYPT_OK) { lrw_done(&lrw); return err; } if ((err = lrw_decrypt(buf[0], buf[1], 16, &lrw)) != CRYPT_OK) { lrw_done(&lrw); return err; } if (compare_testvector(buf[1], 16, tests[x].P, 16, "LRW Decrypt", x)) { lrw_done(&lrw); return CRYPT_FAIL_TESTVECTOR; } if ((err = lrw_done(&lrw)) != CRYPT_OK) { return err; } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/000077500000000000000000000000001464416617300220615ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/ofb_decrypt.c000066400000000000000000000012351464416617300245260ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_decrypt.c OFB implementation, decrypt data, Tom St Denis */ #ifdef LTC_OFB_MODE /** OFB decrypt @param ct Ciphertext @param pt [out] Plaintext @param len Length of ciphertext (octets) @param ofb OFB state @return CRYPT_OK if successful */ int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb) { LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(ofb != NULL); return ofb_encrypt(ct, pt, len, ofb); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/ofb_done.c000066400000000000000000000011021464416617300237720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_done.c OFB implementation, finish chain, Tom St Denis */ #ifdef LTC_OFB_MODE /** Terminate the chain @param ofb The OFB chain to terminate @return CRYPT_OK on success */ int ofb_done(symmetric_OFB *ofb) { int err; LTC_ARGCHK(ofb != NULL); if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { return err; } cipher_descriptor[ofb->cipher]->done(&ofb->key); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/ofb_encrypt.c000066400000000000000000000023321464416617300245370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_encrypt.c OFB implementation, encrypt data, Tom St Denis */ #ifdef LTC_OFB_MODE /** OFB encrypt @param pt Plaintext @param ct [out] Ciphertext @param len Length of plaintext (octets) @param ofb OFB state @return CRYPT_OK if successful */ int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb) { int err; LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(ofb != NULL); if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { return err; } /* is blocklen/padlen valid? */ if (ofb->blocklen < 0 || ofb->blocklen > (int)sizeof(ofb->IV) || ofb->padlen < 0 || ofb->padlen > (int)sizeof(ofb->IV)) { return CRYPT_INVALID_ARG; } while (len-- > 0) { if (ofb->padlen == ofb->blocklen) { if ((err = cipher_descriptor[ofb->cipher]->ecb_encrypt(ofb->IV, ofb->IV, &ofb->key)) != CRYPT_OK) { return err; } ofb->padlen = 0; } *ct++ = *pt++ ^ ofb->IV[(ofb->padlen)++]; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/ofb_getiv.c000066400000000000000000000015461464416617300241770ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_getiv.c OFB implementation, get IV, Tom St Denis */ #ifdef LTC_OFB_MODE /** Get the current initialization vector @param IV [out] The destination of the initialization vector @param len [in/out] The max size and resulting size of the initialization vector @param ofb The OFB state @return CRYPT_OK if successful */ int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb) { LTC_ARGCHK(IV != NULL); LTC_ARGCHK(len != NULL); LTC_ARGCHK(ofb != NULL); if ((unsigned long)ofb->blocklen > *len) { *len = ofb->blocklen; return CRYPT_BUFFER_OVERFLOW; } XMEMCPY(IV, ofb->IV, ofb->blocklen); *len = ofb->blocklen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/ofb_setiv.c000066400000000000000000000015601464416617300242070ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_setiv.c OFB implementation, set IV, Tom St Denis */ #ifdef LTC_OFB_MODE /** Set an initialization vector @param IV The initialization vector @param len The length of the vector (in octets) @param ofb The OFB state @return CRYPT_OK if successful */ int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb) { int err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(ofb != NULL); if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { return err; } if (len != (unsigned long)ofb->blocklen) { return CRYPT_INVALID_ARG; } /* force next block */ ofb->padlen = 0; return cipher_descriptor[ofb->cipher]->ecb_encrypt(IV, ofb->IV, &ofb->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/ofb/ofb_start.c000066400000000000000000000023771464416617300242210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ofb_start.c OFB implementation, start chain, Tom St Denis */ #ifdef LTC_OFB_MODE /** Initialize a OFB context @param cipher The index of the cipher desired @param IV The initialization vector @param key The secret key @param keylen The length of the secret key (octets) @param num_rounds Number of rounds in the cipher desired (0 for default) @param ofb The OFB state to initialize @return CRYPT_OK if successful */ int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, int keylen, int num_rounds, symmetric_OFB *ofb) { int x, err; LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ofb != NULL); if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* copy details */ ofb->cipher = cipher; ofb->blocklen = cipher_descriptor[cipher]->block_length; for (x = 0; x < ofb->blocklen; x++) { ofb->IV[x] = IV[x]; } /* init the cipher */ ofb->padlen = ofb->blocklen; return cipher_descriptor[cipher]->setup(key, keylen, num_rounds, &ofb->key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/000077500000000000000000000000001464416617300221315ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/xts_decrypt.c000066400000000000000000000070041464416617300246460ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects */ #ifdef LTC_XTS_MODE static int s_tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char *T, const symmetric_xts *xts) { unsigned long x; int err; /* tweak encrypt block i */ #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&P[x])) = *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x])); } #else for (x = 0; x < 16; x++) { P[x] = C[x] ^ T[x]; } #endif err = cipher_descriptor[xts->cipher]->ecb_decrypt(P, P, &xts->key1); #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x])); } #else for (x = 0; x < 16; x++) { P[x] = P[x] ^ T[x]; } #endif /* LFSR the tweak */ xts_mult_x(T); return err; } /** XTS Decryption @param ct [in] Ciphertext @param ptlen Length of plaintext (and ciphertext) @param pt [out] Plaintext @param tweak [in] The 128--bit encryption tweak (e.g. sector number) @param xts The XTS structure Returns CRYPT_OK upon success */ int xts_decrypt(const unsigned char *ct, unsigned long ptlen, unsigned char *pt, unsigned char *tweak, const symmetric_xts *xts) { unsigned char PP[16], CC[16], T[16]; unsigned long i, m, mo, lim; int err; /* check inputs */ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tweak != NULL); LTC_ARGCHK(xts != NULL); /* check if valid */ if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { return err; } /* get number of blocks */ m = ptlen >> 4; mo = ptlen & 15; /* must have at least one full block */ if (m == 0) { return CRYPT_INVALID_ARG; } if (mo == 0) { lim = m; } else { lim = m - 1; } if (cipher_descriptor[xts->cipher]->accel_xts_decrypt && lim > 0) { /* use accelerated decryption for whole blocks */ if ((err = cipher_descriptor[xts->cipher]->accel_xts_decrypt(ct, pt, lim, tweak, &xts->key1, &xts->key2)) != CRYPT_OK) { return err; } ct += lim * 16; pt += lim * 16; /* tweak is encrypted on output */ XMEMCPY(T, tweak, sizeof(T)); } else { /* encrypt the tweak */ if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { return err; } for (i = 0; i < lim; i++) { if ((err = s_tweak_uncrypt(ct, pt, T, xts)) != CRYPT_OK) { return err; } ct += 16; pt += 16; } } /* if ptlen not divide 16 then */ if (mo > 0) { XMEMCPY(CC, T, 16); xts_mult_x(CC); /* PP = tweak decrypt block m-1 */ if ((err = s_tweak_uncrypt(ct, PP, CC, xts)) != CRYPT_OK) { return err; } /* Pm = first ptlen % 16 bytes of PP */ for (i = 0; i < mo; i++) { CC[i] = ct[16 + i]; pt[16 + i] = PP[i]; } for (; i < 16; i++) { CC[i] = PP[i]; } /* Pm-1 = Tweak uncrypt CC */ if ((err = s_tweak_uncrypt(CC, pt, T, xts)) != CRYPT_OK) { return err; } } /* Decrypt the tweak back */ if ((err = cipher_descriptor[xts->cipher]->ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { return err; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/xts_done.c000066400000000000000000000007741464416617300241300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects */ #ifdef LTC_XTS_MODE /** Terminate XTS state @param xts The state to terminate */ void xts_done(symmetric_xts *xts) { LTC_ARGCHKVD(xts != NULL); cipher_descriptor[xts->cipher]->done(&xts->key1); cipher_descriptor[xts->cipher]->done(&xts->key2); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/xts_encrypt.c000066400000000000000000000067671464416617300246770ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects */ #ifdef LTC_XTS_MODE static int s_tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, const symmetric_xts *xts) { unsigned long x; int err; /* tweak encrypt block i */ #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&C[x])) = *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x])); } #else for (x = 0; x < 16; x++) { C[x] = P[x] ^ T[x]; } #endif if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(C, C, &xts->key1)) != CRYPT_OK) { return err; } #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x])); } #else for (x = 0; x < 16; x++) { C[x] = C[x] ^ T[x]; } #endif /* LFSR the tweak */ xts_mult_x(T); return CRYPT_OK; } /** XTS Encryption @param pt [in] Plaintext @param ptlen Length of plaintext (and ciphertext) @param ct [out] Ciphertext @param tweak [in] The 128--bit encryption tweak (e.g. sector number) @param xts The XTS structure Returns CRYPT_OK upon success */ int xts_encrypt(const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak, const symmetric_xts *xts) { unsigned char PP[16], CC[16], T[16]; unsigned long i, m, mo, lim; int err; /* check inputs */ LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(tweak != NULL); LTC_ARGCHK(xts != NULL); /* check if valid */ if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { return err; } /* get number of blocks */ m = ptlen >> 4; mo = ptlen & 15; /* must have at least one full block */ if (m == 0) { return CRYPT_INVALID_ARG; } if (mo == 0) { lim = m; } else { lim = m - 1; } if (cipher_descriptor[xts->cipher]->accel_xts_encrypt && lim > 0) { /* use accelerated encryption for whole blocks */ if ((err = cipher_descriptor[xts->cipher]->accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1, &xts->key2)) != CRYPT_OK) { return err; } ct += lim * 16; pt += lim * 16; /* tweak is encrypted on output */ XMEMCPY(T, tweak, sizeof(T)); } else { /* encrypt the tweak */ if ((err = cipher_descriptor[xts->cipher]->ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { return err; } for (i = 0; i < lim; i++) { if ((err = s_tweak_crypt(pt, ct, T, xts)) != CRYPT_OK) { return err; } ct += 16; pt += 16; } } /* if ptlen not divide 16 then */ if (mo > 0) { /* CC = tweak encrypt block m-1 */ if ((err = s_tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) { return err; } /* Cm = first ptlen % 16 bytes of CC */ for (i = 0; i < mo; i++) { PP[i] = pt[16 + i]; ct[16 + i] = CC[i]; } for (; i < 16; i++) { PP[i] = CC[i]; } /* Cm-1 = Tweak encrypt PP */ if ((err = s_tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { return err; } } /* Decrypt the tweak back */ if ((err = cipher_descriptor[xts->cipher]->ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { return err; } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/xts_init.c000066400000000000000000000026301464416617300241370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects */ #ifdef LTC_XTS_MODE /** Start XTS mode @param cipher The index of the cipher to use @param key1 The encrypt key @param key2 The tweak encrypt key @param keylen The length of the keys (each) in octets @param num_rounds The number of rounds for the cipher (0 == default) @param xts [out] XTS structure Returns CRYPT_OK upon success. */ int xts_start(int cipher, const unsigned char *key1, const unsigned char *key2, unsigned long keylen, int num_rounds, symmetric_xts *xts) { int err; /* check inputs */ LTC_ARGCHK(key1 != NULL); LTC_ARGCHK(key2 != NULL); LTC_ARGCHK(xts != NULL); /* check if valid */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher]->block_length != 16) { return CRYPT_INVALID_ARG; } /* schedule the two ciphers */ if ((err = cipher_descriptor[cipher]->setup(key1, keylen, num_rounds, &xts->key1)) != CRYPT_OK) { return err; } if ((err = cipher_descriptor[cipher]->setup(key2, keylen, num_rounds, &xts->key2)) != CRYPT_OK) { return err; } xts->cipher = cipher; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/xts_mult_x.c000066400000000000000000000010711464416617300245020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects */ #ifdef LTC_XTS_MODE /** multiply by x @param I The value to multiply by x (LFSR shift) */ void xts_mult_x(unsigned char *I) { int x; unsigned char t, tt; for (x = t = 0; x < 16; x++) { tt = I[x] >> 7; I[x] = ((I[x] << 1) | t) & 0xFF; t = tt; } if (tt) { I[0] ^= 0x87; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/modes/xts/xts_test.c000066400000000000000000000344651464416617300241660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_XTS_MODE #ifndef LTC_NO_TEST static int s_xts_test_accel_xts_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) { int ret; symmetric_xts xts; int (*orig)(const unsigned char *, unsigned char *, unsigned long , unsigned char *, const symmetric_key *, const symmetric_key *); /* AES can be under rijndael or aes... try to find it */ if ((xts.cipher = find_cipher("aes")) == -1) { if ((xts.cipher = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } orig = cipher_descriptor[xts.cipher]->accel_xts_encrypt; cipher_descriptor[xts.cipher]->accel_xts_encrypt = NULL; XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key)); XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key)); ret = xts_encrypt(pt, blocks << 4, ct, tweak, &xts); cipher_descriptor[xts.cipher]->accel_xts_encrypt = orig; return ret; } static int s_xts_test_accel_xts_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) { int ret; symmetric_xts xts; int (*orig)(const unsigned char *, unsigned char *, unsigned long , unsigned char *, const symmetric_key *, const symmetric_key *); /* AES can be under rijndael or aes... try to find it */ if ((xts.cipher = find_cipher("aes")) == -1) { if ((xts.cipher = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } orig = cipher_descriptor[xts.cipher]->accel_xts_decrypt; cipher_descriptor[xts.cipher]->accel_xts_decrypt = NULL; XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key)); XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key)); ret = xts_decrypt(ct, blocks << 4, pt, tweak, &xts); cipher_descriptor[xts.cipher]->accel_xts_decrypt = orig; return ret; } #endif /** Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects Returns CRYPT_OK upon success. */ int xts_test(void) { #ifdef LTC_NO_TEST return CRYPT_NOP; #else static const struct { int keylen; unsigned char key1[32]; unsigned char key2[32]; ulong64 seqnum; unsigned long PTLEN; unsigned char PTX[512], CTX[512]; } tests[] = { /* #1 32 byte key, 32 byte PTX */ { 32, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, 32, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x91,0x7c,0xf6,0x9e,0xbd,0x68,0xb2,0xec,0x9b,0x9f,0xe9,0xa3,0xea,0xdd,0xa6,0x92,0xcd,0x43,0xd2,0xf5,0x95,0x98,0xed,0x85,0x8c,0x02,0xc2,0x65,0x2f,0xbf,0x92,0x2e }, }, /* #2, 32 byte key, 32 byte PTX */ { 32, { 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 }, { 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22 }, CONST64(0x3333333333), 32, { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, { 0xc4,0x54,0x18,0x5e,0x6a,0x16,0x93,0x6e,0x39,0x33,0x40,0x38,0xac,0xef,0x83,0x8b,0xfb,0x18,0x6f,0xff,0x74,0x80,0xad,0xc4,0x28,0x93,0x82,0xec,0xd6,0xd3,0x94,0xf0 }, }, /* #5 from xts.7, 32 byte key, 32 byte PTX */ { 32, { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, CONST64(0x123456789a), 32, { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, { 0xb0,0x1f,0x86,0xf8,0xed,0xc1,0x86,0x37,0x06,0xfa,0x8a,0x42,0x53,0xe3,0x4f,0x28,0xaf,0x31,0x9d,0xe3,0x83,0x34,0x87,0x0f,0x4d,0xd1,0xf9,0x4c,0xbe,0x98,0x32,0xf1 }, }, /* #4, 32 byte key, 512 byte PTX */ { 32, { 0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26 }, { 0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95 }, 0, 512, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, }, { 0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c, 0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12, 0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce, 0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65, 0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,0xa1,0x0c,0x42,0x11,0x10,0xe6,0xd8,0x15,0x88,0xed,0xe8,0x21,0x03,0xa2,0x52,0xd8, 0xa7,0x50,0xe8,0x76,0x8d,0xef,0xff,0xed,0x91,0x22,0x81,0x0a,0xae,0xb9,0x9f,0x91,0x72,0xaf,0x82,0xb6,0x04,0xdc,0x4b,0x8e,0x51,0xbc,0xb0,0x82,0x35,0xa6,0xf4,0x34, 0x13,0x32,0xe4,0xca,0x60,0x48,0x2a,0x4b,0xa1,0xa0,0x3b,0x3e,0x65,0x00,0x8f,0xc5,0xda,0x76,0xb7,0x0b,0xf1,0x69,0x0d,0xb4,0xea,0xe2,0x9c,0x5f,0x1b,0xad,0xd0,0x3c, 0x5c,0xcf,0x2a,0x55,0xd7,0x05,0xdd,0xcd,0x86,0xd4,0x49,0x51,0x1c,0xeb,0x7e,0xc3,0x0b,0xf1,0x2b,0x1f,0xa3,0x5b,0x91,0x3f,0x9f,0x74,0x7a,0x8a,0xfd,0x1b,0x13,0x0e, 0x94,0xbf,0xf9,0x4e,0xff,0xd0,0x1a,0x91,0x73,0x5c,0xa1,0x72,0x6a,0xcd,0x0b,0x19,0x7c,0x4e,0x5b,0x03,0x39,0x36,0x97,0xe1,0x26,0x82,0x6f,0xb6,0xbb,0xde,0x8e,0xcc, 0x1e,0x08,0x29,0x85,0x16,0xe2,0xc9,0xed,0x03,0xff,0x3c,0x1b,0x78,0x60,0xf6,0xde,0x76,0xd4,0xce,0xcd,0x94,0xc8,0x11,0x98,0x55,0xef,0x52,0x97,0xca,0x67,0xe9,0xf3, 0xe7,0xff,0x72,0xb1,0xe9,0x97,0x85,0xca,0x0a,0x7e,0x77,0x20,0xc5,0xb3,0x6d,0xc6,0xd7,0x2c,0xac,0x95,0x74,0xc8,0xcb,0xbc,0x2f,0x80,0x1e,0x23,0xe5,0x6f,0xd3,0x44, 0xb0,0x7f,0x22,0x15,0x4b,0xeb,0xa0,0xf0,0x8c,0xe8,0x89,0x1e,0x64,0x3e,0xd9,0x95,0xc9,0x4d,0x9a,0x69,0xc9,0xf1,0xb5,0xf4,0x99,0x02,0x7a,0x78,0x57,0x2a,0xee,0xbd, 0x74,0xd2,0x0c,0xc3,0x98,0x81,0xc2,0x13,0xee,0x77,0x0b,0x10,0x10,0xe4,0xbe,0xa7,0x18,0x84,0x69,0x77,0xae,0x11,0x9f,0x7a,0x02,0x3a,0xb5,0x8c,0xca,0x0a,0xd7,0x52, 0xaf,0xe6,0x56,0xbb,0x3c,0x17,0x25,0x6a,0x9f,0x6e,0x9b,0xf1,0x9f,0xdd,0x5a,0x38,0xfc,0x82,0xbb,0xe8,0x72,0xc5,0x53,0x9e,0xdb,0x60,0x9e,0xf4,0xf7,0x9c,0x20,0x3e, 0xbb,0x14,0x0f,0x2e,0x58,0x3c,0xb2,0xad,0x15,0xb4,0xaa,0x5b,0x65,0x50,0x16,0xa8,0x44,0x92,0x77,0xdb,0xd4,0x77,0xef,0x2c,0x8d,0x6c,0x01,0x7d,0xb7,0x38,0xb1,0x8d, 0xeb,0x4a,0x42,0x7d,0x19,0x23,0xce,0x3f,0xf2,0x62,0x73,0x57,0x79,0xa4,0x18,0xf2,0x0a,0x28,0x2d,0xf9,0x20,0x14,0x7b,0xea,0xbe,0x42,0x1e,0xe5,0x31,0x9d,0x05,0x68, } }, /* #7, 32 byte key, 17 byte PTX */ { 32, { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, CONST64(0x123456789a), 17, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10 }, { 0x6c,0x16,0x25,0xdb,0x46,0x71,0x52,0x2d,0x3d,0x75,0x99,0x60,0x1d,0xe7,0xca,0x09,0xed }, }, /* #15, 32 byte key, 25 byte PTX */ { 32, { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, CONST64(0x123456789a), 25, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 }, { 0x8f,0x4d,0xcb,0xad,0x55,0x55,0x8d,0x7b,0x4e,0x01,0xd9,0x37,0x9c,0xd4,0xea,0x22,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73 }, }, /* #21, 32 byte key, 31 byte PTX */ { 32, { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, CONST64(0x123456789a), 31, { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e }, { 0xd0,0x5b,0xc0,0x90,0xa8,0xe0,0x4f,0x1b,0x3d,0x3e,0xcd,0xd5,0xba,0xec,0x0f,0xd4,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73,0x06,0xe6,0x4b,0xe5,0xdd,0x82 }, }, }; unsigned char OUT[512], Torg[16], T[16]; ulong64 seq; symmetric_xts xts; int i, j, k, err, idx; unsigned long len; /* AES can be under rijndael or aes... try to find it */ if ((idx = find_cipher("aes")) == -1) { if ((idx = find_cipher("rijndael")) == -1) { return CRYPT_NOP; } } for (k = 0; k < 4; ++k) { cipher_descriptor[idx]->accel_xts_encrypt = NULL; cipher_descriptor[idx]->accel_xts_decrypt = NULL; if (k & 0x1) { cipher_descriptor[idx]->accel_xts_encrypt = s_xts_test_accel_xts_encrypt; } if (k & 0x2) { cipher_descriptor[idx]->accel_xts_decrypt = s_xts_test_accel_xts_decrypt; } for (j = 0; j < 2; j++) { for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { /* skip the cases where * the length is smaller than 2*blocklen * or the length is not a multiple of 32 */ if ((j == 1) && ((tests[i].PTLEN < 32) || (tests[i].PTLEN % 32))) { continue; } if ((k > 0) && (j == 1)) { continue; } len = tests[i].PTLEN / 2; err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen / 2, 0, &xts); if (err != CRYPT_OK) { return err; } seq = tests[i].seqnum; STORE64L(seq, Torg); XMEMSET(Torg + 8, 0, 8); XMEMCPY(T, Torg, sizeof(T)); if (j == 0) { err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); if (err != CRYPT_OK) { xts_done(&xts); return err; } } else { err = xts_encrypt(tests[i].PTX, len, OUT, T, &xts); if (err != CRYPT_OK) { xts_done(&xts); return err; } err = xts_encrypt(&tests[i].PTX[len], len, &OUT[len], T, &xts); if (err != CRYPT_OK) { xts_done(&xts); return err; } } if (compare_testvector(OUT, tests[i].PTLEN, tests[i].CTX, tests[i].PTLEN, "XTS encrypt", i)) { xts_done(&xts); return CRYPT_FAIL_TESTVECTOR; } XMEMCPY(T, Torg, sizeof(T)); if (j == 0) { err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); if (err != CRYPT_OK) { xts_done(&xts); return err; } } else { err = xts_decrypt(tests[i].CTX, len, OUT, T, &xts); if (err != CRYPT_OK) { xts_done(&xts); return err; } err = xts_decrypt(&tests[i].CTX[len], len, &OUT[len], T, &xts); if (err != CRYPT_OK) { xts_done(&xts); return err; } } if (compare_testvector(OUT, tests[i].PTLEN, tests[i].PTX, tests[i].PTLEN, "XTS decrypt", i)) { xts_done(&xts); return CRYPT_FAIL_TESTVECTOR; } xts_done(&xts); } } } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/000077500000000000000000000000001464416617300206165ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/000077500000000000000000000000001464416617300214605ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/000077500000000000000000000000001464416617300222325ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/bit/000077500000000000000000000000001464416617300230105ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c000066400000000000000000000033401464416617300274550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_bit_string.c ASN.1 DER, encode a BIT STRING, Tom St Denis */ #ifdef LTC_DER /** Store a BIT STRING @param in The DER encoded BIT STRING @param inlen The size of the DER BIT STRING @param out [out] The array of bits stored (one per char) @param outlen [in/out] The number of bits stored @return CRYPT_OK if successful */ int der_decode_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long dlen, blen, x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* packet must be at least 4 bytes */ if (inlen < 4) { return CRYPT_INVALID_ARG; } /* check for 0x03 */ if ((in[0]&0x1F) != 0x03) { return CRYPT_INVALID_PACKET; } /* offset in the data */ x = 1; /* get the length of the data */ y = inlen - 1; if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { return err; } x += y; /* is the data len too long or too short? */ if ((dlen == 0) || (dlen > (inlen - x))) { return CRYPT_INVALID_PACKET; } /* get padding count */ blen = ((dlen - 1) << 3) - (in[x++] & 7); /* too many bits? */ if (blen > *outlen) { *outlen = blen; return CRYPT_BUFFER_OVERFLOW; } /* decode/store the bits */ for (y = 0; y < blen; y++) { out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0; if ((y & 7) == 7) { ++x; } } /* we done */ *outlen = blen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c000066400000000000000000000037161464416617300303350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_bit_string.c ASN.1 DER, encode a BIT STRING, Tom St Denis */ #ifdef LTC_DER #define SETBIT(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n)))) #define CLRBIT(v, n) (v=((unsigned char)(v) & ~(1U << (unsigned char)(n)))) /** Store a BIT STRING @param in The DER encoded BIT STRING @param inlen The size of the DER BIT STRING @param out [out] The array of bits stored (8 per char) @param outlen [in/out] The number of bits stored @return CRYPT_OK if successful */ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long dlen, blen, x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* packet must be at least 4 bytes */ if (inlen < 4) { return CRYPT_INVALID_ARG; } /* check for 0x03 */ if ((in[0]&0x1F) != 0x03) { return CRYPT_INVALID_PACKET; } /* offset in the data */ x = 1; /* get the length of the data */ y = inlen - 1; if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { return err; } x += y; /* is the data len too long or too short? */ if ((dlen == 0) || (dlen > (inlen - x))) { return CRYPT_INVALID_PACKET; } /* get padding count */ blen = ((dlen - 1) << 3) - (in[x++] & 7); /* too many bits? */ if (blen > *outlen) { *outlen = blen; return CRYPT_BUFFER_OVERFLOW; } /* decode/store the bits */ for (y = 0; y < blen; y++) { if (in[x] & (1 << (7 - (y & 7)))) { SETBIT(out[y/8], 7-(y%8)); } else { CLRBIT(out[y/8], 7-(y%8)); } if ((y & 7) == 7) { ++x; } } /* we done */ *outlen = blen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c000066400000000000000000000033411464416617300274700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_bit_string.c ASN.1 DER, encode a BIT STRING, Tom St Denis */ #ifdef LTC_DER /** Store a BIT STRING @param in The array of bits to store (one per char) @param inlen The number of bits tostore @param out [out] The destination for the DER encoded BIT STRING @param outlen [in/out] The max size and resulting size of the DER BIT STRING @return CRYPT_OK if successful */ int der_encode_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long len, x, y; unsigned char buf; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* avoid overflows */ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { return err; } if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } /* store header (include bit padding count in length) */ x = 0; y = ((inlen + 7) >> 3) + 1; out[x++] = 0x03; len = *outlen - x; if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { return err; } x += len; /* store number of zero padding bits */ out[x++] = (unsigned char)((8 - inlen) & 7); /* store the bits in big endian format */ for (y = buf = 0; y < inlen; y++) { buf |= (in[y] ? 1 : 0) << (7 - (y & 7)); if ((y & 7) == 7) { out[x++] = buf; buf = 0; } } /* store last byte */ if (inlen & 7) { out[x++] = buf; } *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c000066400000000000000000000034401464416617300303410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_bit_string.c ASN.1 DER, encode a BIT STRING, Tom St Denis */ #ifdef LTC_DER #define getbit(n, k) (((n) & ( 1 << (k) )) >> (k)) /** Store a BIT STRING @param in The array of bits to store (8 per char) @param inlen The number of bits to store @param out [out] The destination for the DER encoded BIT STRING @param outlen [in/out] The max size and resulting size of the DER BIT STRING @return CRYPT_OK if successful */ int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long len, x, y; unsigned char buf; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* avoid overflows */ if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { return err; } if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } /* store header (include bit padding count in length) */ x = 0; y = ((inlen + 7) >> 3) + 1; out[x++] = 0x03; len = *outlen - x; if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { return err; } x += len; /* store number of zero padding bits */ out[x++] = (unsigned char)((8 - inlen) & 7); /* store the bits in big endian format */ for (y = buf = 0; y < inlen; y++) { buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7)); if ((y & 7) == 7) { out[x++] = buf; buf = 0; } } /* store last byte */ if (inlen & 7) { out[x++] = buf; } *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c000066400000000000000000000015171464416617300275170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_bit_string.c ASN.1 DER, get length of BIT STRING, Tom St Denis */ #ifdef LTC_DER /** Gets length of DER encoding of BIT STRING @param nbits The number of bits in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_bit_string(unsigned long nbits, unsigned long *outlen) { unsigned long nbytes, x; int err; LTC_ARGCHK(outlen != NULL); /* get the number of the bytes */ nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1; if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) { return err; } *outlen = 1 + x + nbytes; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/boolean/000077500000000000000000000000001464416617300236515ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c000066400000000000000000000014551464416617300275760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_boolean.c ASN.1 DER, decode a BOOLEAN, Tom St Denis */ #ifdef LTC_DER /** Read a BOOLEAN @param in The destination for the DER encoded BOOLEAN @param inlen The size of the DER BOOLEAN @param out [out] The boolean to decode @return CRYPT_OK if successful */ int der_decode_boolean(const unsigned char *in, unsigned long inlen, int *out) { LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); if (inlen < 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) { return CRYPT_INVALID_ARG; } *out = (in[2]==0xFF) ? 1 : 0; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c000066400000000000000000000015071464416617300276060ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_boolean.c ASN.1 DER, encode a BOOLEAN, Tom St Denis */ #ifdef LTC_DER /** Store a BOOLEAN @param in The boolean to encode @param out [out] The destination for the DER encoded BOOLEAN @param outlen [in/out] The max size and resulting size of the DER BOOLEAN @return CRYPT_OK if successful */ int der_encode_boolean(int in, unsigned char *out, unsigned long *outlen) { LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(out != NULL); if (*outlen < 3) { *outlen = 3; return CRYPT_BUFFER_OVERFLOW; } *outlen = 3; out[0] = 0x01; out[1] = 0x01; out[2] = in ? 0xFF : 0x00; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c000066400000000000000000000007651464416617300276370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_boolean.c ASN.1 DER, get length of a BOOLEAN, Tom St Denis */ #ifdef LTC_DER /** Gets length of DER encoding of a BOOLEAN @param outlen [out] The length of the DER encoding @return CRYPT_OK if successful */ int der_length_boolean(unsigned long *outlen) { LTC_ARGCHK(outlen != NULL); *outlen = 3; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/choice/000077500000000000000000000000001464416617300234645ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c000066400000000000000000000163021464416617300272210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_choice.c ASN.1 DER, decode a CHOICE, Tom St Denis */ #ifdef LTC_DER /** Decode a CHOICE @param in The DER encoded input @param inlen [in/out] The size of the input and resulting size of read type @param list The list of items to decode @param outlen The number of items in the list @return CRYPT_OK on success */ int der_decode_choice(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *list, unsigned long outlen) { unsigned long size, x, z; void *data; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); LTC_ARGCHK(list != NULL); /* get blk size */ if (*inlen < 2) { return CRYPT_INVALID_PACKET; } /* set all of the "used" flags to zero */ for (x = 0; x < outlen; x++) { list[x].used = 0; } /* now scan until we have a winner */ for (x = 0; x < outlen; x++) { size = list[x].size; data = list[x].data; switch (list[x].type) { case LTC_ASN1_BOOLEAN: if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) { if (der_length_boolean(&z) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_INTEGER: if (der_decode_integer(in, *inlen, data) == CRYPT_OK) { if (der_length_integer(data, &z) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_SHORT_INTEGER: if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) { if (der_length_short_integer(*(unsigned long*)data, &z) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_BIT_STRING: if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_bit_string(size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_RAW_BIT_STRING: if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_bit_string(size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_OCTET_STRING: if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_octet_string(size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_NULL: if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) { *inlen = 2; list[x].used = 1; return CRYPT_OK; } break; case LTC_ASN1_OBJECT_IDENTIFIER: if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_object_identifier(data, size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_TELETEX_STRING: if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_teletex_string(data, size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_IA5_STRING: if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_ia5_string(data, size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_PRINTABLE_STRING: if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_printable_string(data, size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_UTF8_STRING: if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) { if (der_length_utf8_string(data, size, &z) == CRYPT_OK) { list[x].used = 1; list[x].size = size; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_UTCTIME: z = *inlen; if (der_decode_utctime(in, &z, data) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } break; case LTC_ASN1_GENERALIZEDTIME: z = *inlen; if (der_decode_generalizedtime(in, &z, data) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } break; case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) { if (der_length_sequence(data, size, &z) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_CUSTOM_TYPE: if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) { if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) { list[x].used = 1; *inlen = z; return CRYPT_OK; } } break; case LTC_ASN1_CHOICE: case LTC_ASN1_EOL: default: return CRYPT_INVALID_ARG; } } return CRYPT_INVALID_PACKET; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/000077500000000000000000000000001464416617300246055ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c000066400000000000000000000330441464416617300314650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_custom_type.c ASN.1 DER, decode a Custom type, Steffen Jaeckel */ #ifdef LTC_DER /** Decode a Custom type @param in The DER encoded input @param inlen The size of the input @param root The item that defines the custom type to decode @return CRYPT_OK on success */ int der_decode_custom_type(const unsigned char *in, unsigned long inlen, ltc_asn1_list *root) { LTC_ARGCHK(root != NULL); return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED); } /** Extended-decode a Custom type This function is used to decode custom types and sequences/sets For custom types root is used For sequences/sets list and outlen are used @param in The DER encoded input @param inlen The size of the input @param root The item that defines the custom type to decode @param list The list of items to decode @param outlen The number of items in the list @param flags c.f. enum ltc_der_seq @return CRYPT_OK on success */ int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, ltc_asn1_list *root, ltc_asn1_list *list, unsigned long outlen, unsigned int flags) { int err, seq_err, i, ordered; ltc_asn1_type type; ltc_asn1_list ident; unsigned long size, x, y, z, blksize; unsigned char* in_new = NULL; void *data; LTC_ARGCHK(in != NULL); /* get blk size */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } x = 0; if (root == NULL) { LTC_ARGCHK(list != NULL); /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */ if (in[x] != 0x30 && in[x] != 0x31) { return CRYPT_INVALID_PACKET; } ++x; } else { if (root->type != LTC_ASN1_CUSTOM_TYPE) { return CRYPT_INVALID_PACKET; } /* Alloc a copy of the data for primitive handling. */ if (root->pc == LTC_ASN1_PC_PRIMITIVE) { in_new = XMALLOC(inlen); if (in_new == NULL) { return CRYPT_MEM; } XMEMCPY(in_new, in, inlen); in = in_new; } y = inlen; if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) { goto LBL_ERR; } if ((ident.type != root->type) || (ident.klass != root->klass) || (ident.pc != root->pc) || (ident.tag != root->tag)) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } x += y; list = root->data; outlen = root->size; } if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) { if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) || (der_asn1_type_to_identifier_map[root->used] == -1)) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } root->type = (ltc_asn1_type)root->used; list = root; outlen = 1; x -= 1; in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type]; blksize = inlen - x; } else { y = inlen - x; if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) { goto LBL_ERR; } x += y; } /* would this blksize overflow? */ if (blksize > (inlen - x)) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* mark all as unused */ for (i = 0; i < (int)outlen; i++) { list[i].used = 0; } ordered = flags & LTC_DER_SEQ_ORDERED; /* ok read data */ seq_err = CRYPT_OK; blksize += x; inlen -= x; for (i = 0; i < (int)outlen; i++) { z = 0; type = list[i].type; size = list[i].size; data = list[i].data; if (!ordered && list[i].used == 1) { continue; } if (type == LTC_ASN1_EOL) { break; } if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) { err = CRYPT_PK_ASN1_ERROR; goto LBL_ERR; } switch (type) { case LTC_ASN1_CUSTOM_TYPE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: break; default: /* Verify that all basic types are indeed UNIVERSAL&PRIMITIVE */ if (((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT) && (inlen > 0)) { if (in[x] & 0xE0u) { err = CRYPT_PK_ASN1_ERROR; goto LBL_ERR; } } } switch (type) { case LTC_ASN1_BOOLEAN: z = inlen; if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } if ((err = der_length_boolean(&z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_INTEGER: z = inlen; if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } if ((err = der_length_integer(data, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SHORT_INTEGER: z = inlen; if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_BIT_STRING: z = inlen; if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_RAW_BIT_STRING: z = inlen; if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_OCTET_STRING: z = inlen; if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_NULL: if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { if (!ordered || list[i].optional) { continue; } err = CRYPT_INVALID_PACKET; goto LBL_ERR; } z = 2; break; case LTC_ASN1_OBJECT_IDENTIFIER: z = inlen; if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_TELETEX_STRING: z = inlen; if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_IA5_STRING: z = inlen; if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_PRINTABLE_STRING: z = inlen; if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_UTF8_STRING: z = inlen; if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_UTCTIME: z = inlen; if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } break; case LTC_ASN1_GENERALIZEDTIME: z = inlen; if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } break; case LTC_ASN1_SET: z = inlen; if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: /* detect if we have the right type */ if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } z = inlen; err = der_decode_sequence_ex(in + x, z, data, size, flags); if (err == CRYPT_INPUT_TOO_LONG) { seq_err = CRYPT_INPUT_TOO_LONG; err = CRYPT_OK; } if (err != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_CUSTOM_TYPE: z = inlen; err = der_decode_custom_type(in + x, z, &list[i]); if (err == CRYPT_INPUT_TOO_LONG) { seq_err = CRYPT_INPUT_TOO_LONG; err = CRYPT_OK; } if (err != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_CHOICE: z = inlen; if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) { if (!ordered || list[i].optional) { continue; } goto LBL_ERR; } break; case LTC_ASN1_EOL: default: err = CRYPT_INVALID_ARG; goto LBL_ERR; } x += z; inlen -= z; list[i].used = 1; if (!ordered) { /* restart the decoder */ i = -1; } } for (i = 0; i < (int)outlen; i++) { if (list[i].used == 0 && list[i].optional == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } } if (blksize == x && seq_err == CRYPT_OK && inlen == 0) { /* everything decoded and no errors in nested sequences */ err = CRYPT_OK; } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) { /* a sequence reported too-long input, but now we've decoded everything */ err = CRYPT_OK; } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_INPUT_TOO_LONG; } LBL_ERR: if (in_new != NULL) { XFREE(in_new); } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c000066400000000000000000000146201464416617300314760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_custom_type.c ASN.1 DER, encode a Custom Type, Steffen Jaeckel */ #ifdef LTC_DER /** Encode a Custom Type This function is a bit special compared to the others, as it requires the root-ltc_asn1_list where the type is defined. @param root The root of the list of items to encode @param out [out] The destination @param outlen [in/out] The size of the output @return CRYPT_OK on success */ int der_encode_custom_type(const ltc_asn1_list *root, unsigned char *out, unsigned long *outlen) { int err; ltc_asn1_type type; const ltc_asn1_list *list; unsigned long size, x, y, z, i, inlen, id_len; void *data; LTC_ARGCHK(root != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get size of output that will be required */ y = 0; z = 0; if (der_length_custom_type(root, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG; /* too big ? */ if (*outlen < y) { *outlen = y; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* get length of the identifier, so we know the offset where to start writing */ if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG; x = id_len; if (root->pc == LTC_ASN1_PC_PRIMITIVE) { list = root; inlen = 1; /* In case it's a PRIMITIVE type we encode directly to the output * but leave space for a potentially longer identifier as it will * simply be replaced afterwards. */ x -= 1; } else { list = root->data; inlen = root->size; /* store length, identifier will be added later */ y = *outlen - x; if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { goto LBL_ERR; } x += y; } /* store data */ *outlen -= x; for (i = 0; i < inlen; i++) { if (root->pc == LTC_ASN1_PC_PRIMITIVE) { type = (ltc_asn1_type)list[i].used; } else { type = list[i].type; } size = list[i].size; data = list[i].data; if (type == LTC_ASN1_EOL) { break; } switch (type) { case LTC_ASN1_BOOLEAN: z = *outlen; if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_INTEGER: z = *outlen; if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SHORT_INTEGER: z = *outlen; if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_BIT_STRING: z = *outlen; if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_RAW_BIT_STRING: z = *outlen; if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_OCTET_STRING: z = *outlen; if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_NULL: out[x] = 0x05; out[x+1] = 0x00; z = 2; break; case LTC_ASN1_OBJECT_IDENTIFIER: z = *outlen; if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_IA5_STRING: z = *outlen; if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_PRINTABLE_STRING: z = *outlen; if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_UTF8_STRING: z = *outlen; if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_UTCTIME: z = *outlen; if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_GENERALIZEDTIME: z = *outlen; if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SET: z = *outlen; if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SETOF: z = *outlen; if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SEQUENCE: z = *outlen; if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_CUSTOM_TYPE: z = *outlen; if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_CHOICE: case LTC_ASN1_EOL: case LTC_ASN1_TELETEX_STRING: default: err = CRYPT_INVALID_ARG; goto LBL_ERR; } x += z; *outlen -= z; } if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) { goto LBL_ERR; } *outlen = x; err = CRYPT_OK; LBL_ERR: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c000066400000000000000000000130071464416617300315200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_custom_type.c ASN.1 DER, length of a custom type, Steffen Jaeckel */ #ifdef LTC_DER /** Get the length of a DER custom type This function is a bit special compared to the others, as it requires the root-ltc_asn1_list where the type is defined. @param root The root of the struct to encode @param outlen [out] The length required in octets to store it @param payloadlen [out] The length of the payload in octets @return CRYPT_OK on success */ int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen) { int err; const ltc_asn1_list *list; ltc_asn1_type type; unsigned long size, x, y, i, inlen, id_len; void *data; LTC_ARGCHK(root != NULL); LTC_ARGCHK(outlen != NULL); /* get size of output that will be required */ if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) { return err; } y = id_len; if (root->pc == LTC_ASN1_PC_PRIMITIVE) { list = root; inlen = 1; } else { list = root->data; inlen = root->size; } for (i = 0; i < inlen; i++) { if (root->pc == LTC_ASN1_PC_PRIMITIVE) { type = (ltc_asn1_type)list[i].used; } else { type = list[i].type; } size = list[i].size; data = list[i].data; if (type == LTC_ASN1_EOL) { break; } /* some items may be optional during import */ if (!list[i].used && list[i].optional) continue; switch (type) { case LTC_ASN1_BOOLEAN: if ((err = der_length_boolean(&x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_INTEGER: if ((err = der_length_integer(data, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_SHORT_INTEGER: if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_BIT_STRING: case LTC_ASN1_RAW_BIT_STRING: if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_OCTET_STRING: if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_NULL: y += 2; break; case LTC_ASN1_OBJECT_IDENTIFIER: if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_IA5_STRING: if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_TELETEX_STRING: if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_PRINTABLE_STRING: if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_UTCTIME: if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_GENERALIZEDTIME: if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_UTF8_STRING: if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_CUSTOM_TYPE: if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_CHOICE: case LTC_ASN1_EOL: default: err = CRYPT_INVALID_ARG; goto LBL_ERR; } } if (root->pc == LTC_ASN1_PC_PRIMITIVE) { /* In case it's a PRIMITIVE element we're going * to only replace the identifier of the one element * by the custom identifier. */ y -= 1; if (payloadlen != NULL) { *payloadlen = y - id_len; } } else { /* calc length of length */ if ((err = der_length_asn1_length(y - id_len, &x)) != CRYPT_OK) { goto LBL_ERR; } if (payloadlen != NULL) { *payloadlen = y - id_len; } y += x; } /* store size */ *outlen = y; LBL_ERR: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/000077500000000000000000000000001464416617300236475ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c000066400000000000000000000121001464416617300265210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_asn1_maps.c ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel */ #ifdef LTC_DER /** A Map from ltc_asn1_type to the regularly used ASN.1 identifier */ const int der_asn1_type_to_identifier_map[] = { /* 0 */ -1, /* LTC_ASN1_EOL, */ 1, /* LTC_ASN1_BOOLEAN, */ 2, /* LTC_ASN1_INTEGER, */ 2, /* LTC_ASN1_SHORT_INTEGER, */ 3, /* LTC_ASN1_BIT_STRING, */ /* 5 */ 4, /* LTC_ASN1_OCTET_STRING, */ 5, /* LTC_ASN1_NULL, */ 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */ 22, /* LTC_ASN1_IA5_STRING, */ 19, /* LTC_ASN1_PRINTABLE_STRING, */ /* 10 */ 12, /* LTC_ASN1_UTF8_STRING, */ 23, /* LTC_ASN1_UTCTIME, */ -1, /* LTC_ASN1_CHOICE, */ 48, /* LTC_ASN1_SEQUENCE, */ 49, /* LTC_ASN1_SET, */ /* 15 */ 49, /* LTC_ASN1_SETOF, */ 3, /* LTC_ASN1_RAW_BIT_STRING, */ 20, /* LTC_ASN1_TELETEX_STRING, */ 24, /* LTC_ASN1_GENERALIZEDTIME, */ -1, /* LTC_ASN1_CUSTOM_TYPE, */ }; const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]); /** A Map from the ASN.1 Class to its string */ const char* der_asn1_class_to_string_map[] = { "UNIVERSAL", "APPLICATION", "CONTEXT-SPECIFIC", "PRIVATE", }; const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]); /** A Map from the ASN.1 P/C-bit to its string */ const char* der_asn1_pc_to_string_map[] = { "PRIMITIVE", "CONSTRUCTED", }; const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]); /** A Map from the ASN.1 tag to its string */ const char* der_asn1_tag_to_string_map[] = { "Reserved for use by the encoding rules", "Boolean type", "Integer type", "Bitstring type", "Octetstring type", "Null type", "Object identifier type", "Object descriptor type", "External type and Instance-of type", "Real type", "Enumerated type", "Embedded-pdv type", "UTF8String type", "Relative object identifier type", "The time type", "Reserved for future editions of this Recommendation | International Standard", "Sequence and Sequence-of types", "Set and Set-of types", "NumericString type", "PrintableString type", "TeletexString (T61String) type", "VideotexString type", "IA5String type", "UTCTime type", "GeneralizedTime type", "GraphicString type", "VisibleString (ISO646String) type", "GeneralString type", "UniversalString type", "UnrestrictedCharacterString type", "BMPString type", "Date type", "TimeOfDay type", "DateTime type", "Duration type", "OID internationalized resource identifier type", "Relative OID internationalized resource identifier type", }; const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]); /** A Map from ASN.1 Tags to ltc_asn1_type */ const ltc_asn1_type der_asn1_tag_to_type_map[] = { /* 0 */ LTC_ASN1_EOL, /* Reserved for use by the encoding rules */ LTC_ASN1_BOOLEAN, /* Boolean type */ LTC_ASN1_INTEGER, /* Integer type */ LTC_ASN1_BIT_STRING, /* Bitstring type */ LTC_ASN1_OCTET_STRING, /* Octetstring type */ /* 5 */ LTC_ASN1_NULL, /* Null type */ LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */ LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */ LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */ LTC_ASN1_CUSTOM_TYPE, /* Real type */ /* 10 */ LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */ LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */ LTC_ASN1_UTF8_STRING, /* UTF8String type */ LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */ LTC_ASN1_CUSTOM_TYPE, /* The time type */ /* 15 */ LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */ LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */ LTC_ASN1_SET, /* Set and Set-of types */ LTC_ASN1_CUSTOM_TYPE, /* NumericString types */ LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */ /* 20 */ LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */ LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */ LTC_ASN1_IA5_STRING, /* IA5String types */ LTC_ASN1_UTCTIME, /* UTCTime types */ LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */ /* 25 */ LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */ LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */ LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */ LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */ LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */ /* 30 */ LTC_ASN1_CUSTOM_TYPE, /* BMPString types */ }; const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]); #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c000066400000000000000000000057211464416617300312210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_asn1_identifier.c ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel */ #ifdef LTC_DER /* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */ static const unsigned char tag_constructed_map[] = { /* 0 */ 255, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, /* 5 */ LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, /* 10 */ LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, /* 15 */ 255, LTC_ASN1_PC_CONSTRUCTED, LTC_ASN1_PC_CONSTRUCTED, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, /* 20 */ LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, /* 25 */ LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, LTC_ASN1_PC_PRIMITIVE, }; static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]); /** Decode the ASN.1 Identifier @param id Where to store the decoded Identifier @param in Where to read the Identifier from @param inlen [in/out] The size of in available/read @return CRYPT_OK if successful */ int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id) { ulong64 tmp; unsigned long tag_len; int err; LTC_ARGCHK(id != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); if (*inlen == 0) { return CRYPT_BUFFER_OVERFLOW; } tag_len = 1; id->klass = (in[0] >> 6) & 0x3; id->pc = (in[0] >> 5) & 0x1; id->tag = in[0] & 0x1f; err = CRYPT_OK; if (id->tag == 0x1f) { id->tag = 0; do { if (*inlen < tag_len) { /* break the loop and trigger the BOF error-code */ tmp = 0xff; break; } id->tag <<= 7; id->tag |= in[tag_len] & 0x7f; tmp = in[tag_len] & 0x80; tag_len++; } while ((tmp != 0) && (tag_len < 10)); if (tmp != 0) { err = CRYPT_BUFFER_OVERFLOW; } else if (id->tag < 0x1f) { err = CRYPT_PK_ASN1_ERROR; } } if (err != CRYPT_OK) { id->pc = 0; id->klass = 0; id->tag = 0; } else { *inlen = tag_len; if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag < der_asn1_tag_to_type_map_sz) && (id->tag < tag_constructed_map_sz) && (id->pc == tag_constructed_map[id->tag])) { id->type = der_asn1_tag_to_type_map[id->tag]; } else { if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) { id->type = LTC_ASN1_EOL; } else { id->type = LTC_ASN1_CUSTOM_TYPE; } } } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c000066400000000000000000000026531464416617300303610ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_asn1_length.c ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel */ #ifdef LTC_DER /** Decode the ASN.1 Length field @param in Where to read the length field from @param inlen [in/out] The size of in available/read @param outlen [out] The decoded ASN.1 length @return CRYPT_OK if successful */ int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen) { unsigned long real_len, decoded_len, offset, i; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); if (*inlen < 1) { return CRYPT_BUFFER_OVERFLOW; } real_len = in[0]; if (real_len < 128) { decoded_len = real_len; offset = 1; } else { real_len &= 0x7F; if (real_len == 0) { return CRYPT_PK_ASN1_ERROR; } if (real_len > sizeof(decoded_len)) { return CRYPT_OVERFLOW; } if (real_len > (*inlen - 1)) { return CRYPT_BUFFER_OVERFLOW; } decoded_len = 0; offset = 1 + real_len; for (i = 0; i < real_len; i++) { decoded_len = (decoded_len << 8) | in[1 + i]; } } if (outlen != NULL) *outlen = decoded_len; if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW; *inlen = offset; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c000066400000000000000000000041621464416617300312310ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_asn1_identifier.c ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel */ #ifdef LTC_DER /** Encode the ASN.1 Identifier @param id The ASN.1 Identifer to encode @param out Where to write the identifier to @param outlen [in/out] The size of out available/written @return CRYPT_OK if successful */ int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen) { ulong64 tmp; unsigned long tag_len; LTC_ARGCHK(id != NULL); LTC_ARGCHK(outlen != NULL); if (id->type != LTC_ASN1_CUSTOM_TYPE) { if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) { return CRYPT_INVALID_ARG; } if (der_asn1_type_to_identifier_map[id->type] == -1) { return CRYPT_INVALID_ARG; } if (out != NULL) { *out = der_asn1_type_to_identifier_map[id->type]; } *outlen = 1; return CRYPT_OK; } if (id->klass < LTC_ASN1_CL_UNIVERSAL || id->klass > LTC_ASN1_CL_PRIVATE) { return CRYPT_INVALID_ARG; } if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) { return CRYPT_INVALID_ARG; } if (id->tag > (ULONG_MAX >> (8 + 7))) { return CRYPT_INVALID_ARG; } if (out != NULL) { if (*outlen < 1) { return CRYPT_BUFFER_OVERFLOW; } out[0] = id->klass << 6 | id->pc << 5; } if (id->tag < 0x1f) { if (out != NULL) { out[0] |= id->tag & 0x1f; } *outlen = 1; } else { tag_len = 0; tmp = id->tag; do { tag_len++; tmp >>= 7; } while (tmp); if (out != NULL) { if (*outlen < tag_len + 1) { return CRYPT_BUFFER_OVERFLOW; } out[0] |= 0x1f; for (tmp = 1; tmp <= tag_len; ++tmp) { out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80; } out[tag_len] &= ~0x80; } *outlen = tag_len + 1; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c000066400000000000000000000073151464416617300303730ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_asn1_length.c ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel */ #ifdef LTC_DER /** Encode the ASN.1 length field @param len The length to encode @param out Where to write the length field to @param outlen [in/out] The size of out available/written @return CRYPT_OK if successful */ int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen) { unsigned long x, y; LTC_ARGCHK(outlen != NULL); x = len; y = 0; while(x != 0) { y++; x >>= 8; } if (y == 0) { return CRYPT_PK_ASN1_ERROR; } if (out == NULL) { if (len < 128) { x = y; } else { x = y + 1; } } else { if (*outlen < y) { return CRYPT_BUFFER_OVERFLOW; } x = 0; if (len < 128) { out[x++] = (unsigned char)len; } else if (len <= 0xffUL) { out[x++] = 0x81; out[x++] = (unsigned char)len; } else if (len <= 0xffffUL) { out[x++] = 0x82; out[x++] = (unsigned char)((len>>8UL)&255); out[x++] = (unsigned char)(len&255); } else if (len <= 0xffffffUL) { out[x++] = 0x83; out[x++] = (unsigned char)((len>>16UL)&255); out[x++] = (unsigned char)((len>>8UL)&255); out[x++] = (unsigned char)(len&255); #if ULONG_MAX != ULLONG_MAX } else { out[x++] = 0x84; out[x++] = (unsigned char)((len>>24UL)&255); out[x++] = (unsigned char)((len>>16UL)&255); out[x++] = (unsigned char)((len>>8UL)&255); out[x++] = (unsigned char)(len&255); } #else } else if (len <= 0xffffffffUL) { out[x++] = 0x84; out[x++] = (unsigned char)((len>>24UL)&255); out[x++] = (unsigned char)((len>>16UL)&255); out[x++] = (unsigned char)((len>>8UL)&255); out[x++] = (unsigned char)(len&255); } else if (len <= 0xffffffffffULL) { out[x++] = 0x85; out[x++] = (unsigned char)((len>>32ULL)&255); out[x++] = (unsigned char)((len>>24ULL)&255); out[x++] = (unsigned char)((len>>16ULL)&255); out[x++] = (unsigned char)((len>>8ULL)&255); out[x++] = (unsigned char)(len&255); } else if (len <= 0xffffffffffffULL) { out[x++] = 0x86; out[x++] = (unsigned char)((len>>40ULL)&255); out[x++] = (unsigned char)((len>>32ULL)&255); out[x++] = (unsigned char)((len>>24ULL)&255); out[x++] = (unsigned char)((len>>16ULL)&255); out[x++] = (unsigned char)((len>>8ULL)&255); out[x++] = (unsigned char)(len&255); } else if (len <= 0xffffffffffffffULL) { out[x++] = 0x87; out[x++] = (unsigned char)((len>>48ULL)&255); out[x++] = (unsigned char)((len>>40ULL)&255); out[x++] = (unsigned char)((len>>32ULL)&255); out[x++] = (unsigned char)((len>>24ULL)&255); out[x++] = (unsigned char)((len>>16ULL)&255); out[x++] = (unsigned char)((len>>8ULL)&255); out[x++] = (unsigned char)(len&255); } else { out[x++] = 0x88; out[x++] = (unsigned char)((len>>56ULL)&255); out[x++] = (unsigned char)((len>>48ULL)&255); out[x++] = (unsigned char)((len>>40ULL)&255); out[x++] = (unsigned char)((len>>32ULL)&255); out[x++] = (unsigned char)((len>>24ULL)&255); out[x++] = (unsigned char)((len>>16ULL)&255); out[x++] = (unsigned char)((len>>8ULL)&255); out[x++] = (unsigned char)(len&255); } #endif } *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c000066400000000000000000000011761464416617300312570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_asn1_identifier.c ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel */ #ifdef LTC_DER /** Determine the length required when encoding the ASN.1 Identifier @param id The ASN.1 identifier to encode @param idlen [out] The required length to encode list @return CRYPT_OK if successful */ int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen) { return der_encode_asn1_identifier(id, NULL, idlen); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c000066400000000000000000000011531464416617300304110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_asn1_length.c ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel */ #ifdef LTC_DER /** Determine the length required to encode len in the ASN.1 length field @param len The length to encode @param outlen [out] The length that's required to store len @return CRYPT_OK if successful */ int der_length_asn1_length(unsigned long len, unsigned long *outlen) { return der_encode_asn1_length(len, NULL, outlen); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/000077500000000000000000000000001464416617300254025ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c000066400000000000000000000064551464416617300330650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_generalizedtime.c ASN.1 DER, decode a GeneralizedTime, Steffen Jaeckel Based on der_decode_utctime.c */ #ifdef LTC_DER static int s_char_to_int(unsigned char x) { switch (x) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; default: return 100; } } #define DECODE_V(y, max) do {\ y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ if (y >= max) return CRYPT_INVALID_PACKET; \ x += 2; \ } while(0) #define DECODE_V4(y, max) do {\ y = s_char_to_int(buf[x])*1000 + s_char_to_int(buf[x+1])*100 + s_char_to_int(buf[x+2])*10 + s_char_to_int(buf[x+3]); \ if (y >= max) return CRYPT_INVALID_PACKET; \ x += 4; \ } while(0) /** Decodes a Generalized time structure in DER format (reads all 6 valid encoding formats) @param in Input buffer @param inlen Length of input buffer in octets @param out [out] Destination of Generalized time structure @return CRYPT_OK if successful */ int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, ltc_generalizedtime *out) { unsigned char buf[32]; unsigned long x; int y; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); LTC_ARGCHK(out != NULL); /* check header */ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { return CRYPT_INVALID_PACKET; } /* decode the string */ for (x = 0; x < in[1]; x++) { y = der_ia5_value_decode(in[x+2]); if (y == -1) { return CRYPT_INVALID_PACKET; } if (!((y >= '0' && y <= '9') || y == 'Z' || y == '.' || y == '+' || y == '-')) { return CRYPT_INVALID_PACKET; } buf[x] = y; } *inlen = 2 + x; if (x < 15) { return CRYPT_INVALID_PACKET; } /* possible encodings are YYYYMMDDhhmmssZ YYYYMMDDhhmmss+hh'mm' YYYYMMDDhhmmss-hh'mm' YYYYMMDDhhmmss.fsZ YYYYMMDDhhmmss.fs+hh'mm' YYYYMMDDhhmmss.fs-hh'mm' So let's do a trivial decode upto [including] ss */ x = 0; DECODE_V4(out->YYYY, 10000); DECODE_V(out->MM, 13); DECODE_V(out->DD, 32); DECODE_V(out->hh, 24); DECODE_V(out->mm, 60); DECODE_V(out->ss, 60); /* clear fractional seconds info */ out->fs = 0; /* now is it Z or . */ if (buf[x] == 'Z') { return CRYPT_OK; } if (buf[x] == '.') { x++; while (buf[x] >= '0' && buf[x] <= '9') { unsigned fs = out->fs; if (x >= sizeof(buf)) return CRYPT_INVALID_PACKET; out->fs *= 10; out->fs += s_char_to_int(buf[x]); if (fs > out->fs) return CRYPT_OVERFLOW; x++; } } /* now is it Z, +, - */ if (buf[x] == 'Z') { return CRYPT_OK; } if (buf[x] == '+' || buf[x] == '-') { out->off_dir = (buf[x++] == '+') ? 0 : 1; DECODE_V(out->off_hh, 24); DECODE_V(out->off_mm, 60); return CRYPT_OK; } return CRYPT_INVALID_PACKET; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c000066400000000000000000000051271464416617300330720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_utctime.c ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel Based on der_encode_utctime.c */ #ifdef LTC_DER static const char * const baseten = "0123456789"; #define STORE_V(y) do {\ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ out[x++] = der_ia5_char_encode(baseten[y % 10]); \ } while(0) #define STORE_V4(y) do {\ out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \ out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ out[x++] = der_ia5_char_encode(baseten[y % 10]); \ } while(0) /** Encodes a Generalized time structure in DER format @param gtime The GeneralizedTime structure to encode @param out The destination of the DER encoding of the GeneralizedTime structure @param outlen [in/out] The length of the DER encoding @return CRYPT_OK if successful */ int der_encode_generalizedtime(const ltc_generalizedtime *gtime, unsigned char *out, unsigned long *outlen) { unsigned long x, tmplen; int err; LTC_ARGCHK(gtime != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) { return err; } if (tmplen > *outlen) { *outlen = tmplen; return CRYPT_BUFFER_OVERFLOW; } /* store header */ out[0] = 0x18; /* store values */ x = 2; STORE_V4(gtime->YYYY); STORE_V(gtime->MM); STORE_V(gtime->DD); STORE_V(gtime->hh); STORE_V(gtime->mm); STORE_V(gtime->ss); if (gtime->fs) { unsigned long divisor; unsigned fs = gtime->fs; unsigned len = 0; out[x++] = der_ia5_char_encode('.'); divisor = 1; do { fs /= 10; divisor *= 10; len++; } while(fs != 0); while (len-- > 1) { divisor /= 10; out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]); } out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]); } if (gtime->off_mm || gtime->off_hh) { out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+'); STORE_V(gtime->off_hh); STORE_V(gtime->off_mm); } else { out[x++] = der_ia5_char_encode('Z'); } /* store length */ out[1] = (unsigned char)(x - 2); /* all good let's return */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c000066400000000000000000000022271464416617300331140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_utctime.c ASN.1 DER, get length of GeneralizedTime, Steffen Jaeckel Based on der_length_utctime.c */ #ifdef LTC_DER /** Gets length of DER encoding of GeneralizedTime @param gtime The GeneralizedTime structure to get the size of @param outlen [out] The length of the DER encoding @return CRYPT_OK if successful */ int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen) { LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(gtime != NULL); if (gtime->fs == 0) { /* we encode as YYYYMMDDhhmmssZ */ *outlen = 2 + 14 + 1; } else { unsigned long len = 2 + 14 + 1; unsigned fs = gtime->fs; do { fs /= 10; len++; } while(fs != 0); if (gtime->off_hh == 0 && gtime->off_mm == 0) { /* we encode as YYYYMMDDhhmmss.fsZ */ len += 1; } else { /* we encode as YYYYMMDDhhmmss.fs{+|-}hh'mm' */ len += 5; } *outlen = len; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/ia5/000077500000000000000000000000001464416617300227105ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c000066400000000000000000000030671464416617300272630ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_ia5_string.c ASN.1 DER, encode a IA5 STRING, Tom St Denis */ #ifdef LTC_DER /** Store a IA5 STRING @param in The DER encoded IA5 STRING @param inlen The size of the DER IA5 STRING @param out [out] The array of octets stored (one per char) @param outlen [in/out] The number of octets stored @return CRYPT_OK if successful */ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int t, err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* must have header at least */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* check for 0x16 */ if ((in[0] & 0x1F) != 0x16) { return CRYPT_INVALID_PACKET; } x = 1; /* get the length of the data */ y = inlen - x; if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { return err; } x += y; /* is it too long? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } if (len > (inlen - x)) { return CRYPT_INVALID_PACKET; } /* read the data */ for (y = 0; y < len; y++) { t = der_ia5_value_decode(in[x++]); if (t == -1) { return CRYPT_INVALID_ARG; } out[y] = t; } *outlen = y; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c000066400000000000000000000026431464416617300272740ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_ia5_string.c ASN.1 DER, encode a IA5 STRING, Tom St Denis */ #ifdef LTC_DER /** Store an IA5 STRING @param in The array of IA5 to store (one per char) @param inlen The number of IA5 to store @param out [out] The destination for the DER encoded IA5 STRING @param outlen [in/out] The max size and resulting size of the DER IA5 STRING @return CRYPT_OK if successful */ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get the size */ if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) { return err; } /* too big? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } /* encode the header+len */ x = 0; out[x++] = 0x16; len = *outlen - x; if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { return err; } x += len; /* store octets */ for (y = 0; y < inlen; y++) { out[x++] = der_ia5_char_encode(in[y]); } /* retun length */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c000066400000000000000000000055251464416617300273220ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_ia5_string.c ASN.1 DER, get length of IA5 STRING, Tom St Denis */ #ifdef LTC_DER static const struct { int code, value; } ia5_table[] = { { '\0', 0 }, { '\a', 7 }, { '\b', 8 }, { '\t', 9 }, { '\n', 10 }, { '\f', 12 }, { '\r', 13 }, { ' ', 32 }, { '!', 33 }, { '"', 34 }, { '#', 35 }, { '$', 36 }, { '%', 37 }, { '&', 38 }, { '\'', 39 }, { '(', 40 }, { ')', 41 }, { '*', 42 }, { '+', 43 }, { ',', 44 }, { '-', 45 }, { '.', 46 }, { '/', 47 }, { '0', 48 }, { '1', 49 }, { '2', 50 }, { '3', 51 }, { '4', 52 }, { '5', 53 }, { '6', 54 }, { '7', 55 }, { '8', 56 }, { '9', 57 }, { ':', 58 }, { ';', 59 }, { '<', 60 }, { '=', 61 }, { '>', 62 }, { '?', 63 }, { '@', 64 }, { 'A', 65 }, { 'B', 66 }, { 'C', 67 }, { 'D', 68 }, { 'E', 69 }, { 'F', 70 }, { 'G', 71 }, { 'H', 72 }, { 'I', 73 }, { 'J', 74 }, { 'K', 75 }, { 'L', 76 }, { 'M', 77 }, { 'N', 78 }, { 'O', 79 }, { 'P', 80 }, { 'Q', 81 }, { 'R', 82 }, { 'S', 83 }, { 'T', 84 }, { 'U', 85 }, { 'V', 86 }, { 'W', 87 }, { 'X', 88 }, { 'Y', 89 }, { 'Z', 90 }, { '[', 91 }, { '\\', 92 }, { ']', 93 }, { '^', 94 }, { '_', 95 }, { '`', 96 }, { 'a', 97 }, { 'b', 98 }, { 'c', 99 }, { 'd', 100 }, { 'e', 101 }, { 'f', 102 }, { 'g', 103 }, { 'h', 104 }, { 'i', 105 }, { 'j', 106 }, { 'k', 107 }, { 'l', 108 }, { 'm', 109 }, { 'n', 110 }, { 'o', 111 }, { 'p', 112 }, { 'q', 113 }, { 'r', 114 }, { 's', 115 }, { 't', 116 }, { 'u', 117 }, { 'v', 118 }, { 'w', 119 }, { 'x', 120 }, { 'y', 121 }, { 'z', 122 }, { '{', 123 }, { '|', 124 }, { '}', 125 }, { '~', 126 } }; int der_ia5_char_encode(int c) { int x; for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { if (ia5_table[x].code == c) { return ia5_table[x].value; } } return -1; } int der_ia5_value_decode(int v) { int x; for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { if (ia5_table[x].value == v) { return ia5_table[x].code; } } return -1; } /** Gets length of DER encoding of IA5 STRING @param octets The values you want to encode @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) { unsigned long x; int err; LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(octets != NULL); /* scan string for validity */ for (x = 0; x < noctets; x++) { if (der_ia5_char_encode(octets[x]) == -1) { return CRYPT_INVALID_ARG; } } if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { return err; } *outlen = 1 + x + noctets; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/integer/000077500000000000000000000000001464416617300236675ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c000066400000000000000000000027401464416617300276300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_integer.c ASN.1 DER, decode an integer, Tom St Denis */ #ifdef LTC_DER /** Read a mp_int integer @param in The DER encoded data @param inlen Size of DER encoded data @param num The first mp_int to decode @return CRYPT_OK if successful */ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) { unsigned long x, y; int err; LTC_ARGCHK(num != NULL); LTC_ARGCHK(in != NULL); /* min DER INTEGER is 0x02 01 00 == 0 */ if (inlen < (1 + 1 + 1)) { return CRYPT_INVALID_PACKET; } /* ok expect 0x02 when we AND with 0001 1111 [1F] */ x = 0; if ((in[x++] & 0x1F) != 0x02) { return CRYPT_INVALID_PACKET; } /* get the length of the data */ inlen -= x; if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) { return err; } x += inlen; if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) { return err; } /* see if it's negative */ if (in[x] & 0x80) { void *tmp; if (mp_init(&tmp) != CRYPT_OK) { return CRYPT_MEM; } if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) { mp_clear(tmp); return CRYPT_MEM; } mp_clear(tmp); } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c000066400000000000000000000054641464416617300276500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_integer.c ASN.1 DER, encode an integer, Tom St Denis */ #ifdef LTC_DER /* Exports a positive bignum as DER format (upto 2^32 bytes in size) */ /** Store a mp_int integer @param num The first mp_int to encode @param out [out] The destination for the DER encoded integers @param outlen [in/out] The max size and resulting size of the DER encoded integers @return CRYPT_OK if successful */ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) { unsigned long tmplen, y, len; int err, leading_zero; LTC_ARGCHK(num != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* find out how big this will be */ if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) { return err; } if (*outlen < tmplen) { *outlen = tmplen; return CRYPT_BUFFER_OVERFLOW; } if (mp_cmp_d(num, 0) != LTC_MP_LT) { /* we only need a leading zero if the msb of the first byte is one */ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { leading_zero = 1; } else { leading_zero = 0; } /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ y = mp_unsigned_bin_size(num) + leading_zero; } else { leading_zero = 0; y = mp_count_bits(num); y = y + (8 - (y & 7)); y = y >> 3; if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y; } /* now store initial data */ *out++ = 0x02; len = *outlen - 1; if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) { return err; } out += len; /* now store msbyte of zero if num is non-zero */ if (leading_zero) { *out++ = 0x00; } /* if it's not zero store it as big endian */ if (mp_cmp_d(num, 0) == LTC_MP_GT) { /* now store the mpint */ if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) { return err; } } else if (mp_iszero(num) != LTC_MP_YES) { void *tmp; /* negative */ if (mp_init(&tmp) != CRYPT_OK) { return CRYPT_MEM; } /* 2^roundup and subtract */ y = mp_count_bits(num); y = y + (8 - (y & 7)); if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8; if (mp_2expt(tmp, y) != CRYPT_OK || mp_add(tmp, num, tmp) != CRYPT_OK) { mp_clear(tmp); return CRYPT_MEM; } if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { mp_clear(tmp); return err; } mp_clear(tmp); } /* we good */ *outlen = tmplen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c000066400000000000000000000026301464416617300276640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_integer.c ASN.1 DER, get length of encoding, Tom St Denis */ #ifdef LTC_DER /** Gets length of DER encoding of num @param num The int to get the size of @param outlen [out] The length of the DER encoding for the given integer @return CRYPT_OK if successful */ int der_length_integer(void *num, unsigned long *outlen) { unsigned long z, len; int leading_zero, err; LTC_ARGCHK(num != NULL); LTC_ARGCHK(outlen != NULL); if (mp_cmp_d(num, 0) != LTC_MP_LT) { /* positive */ /* we only need a leading zero if the msb of the first byte is one */ if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { leading_zero = 1; } else { leading_zero = 0; } /* size for bignum */ len = leading_zero + mp_unsigned_bin_size(num); } else { /* it's negative */ /* find power of 2 that is a multiple of eight and greater than count bits */ z = mp_count_bits(num); z = z + (8 - (z & 7)); if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z; len = z >> 3; } if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) { return err; } *outlen = 1 + z + len; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/000077500000000000000000000000001464416617300257025ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c000066400000000000000000000041641464416617300336600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_object_identifier.c ASN.1 DER, Decode Object Identifier, Tom St Denis */ #ifdef LTC_DER /** Decode OID data and store the array of integers in words @param in The OID DER encoded data @param inlen The length of the OID data @param words [out] The destination of the OID words @param outlen [in/out] The number of OID words @return CRYPT_OK if successful */ int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, unsigned long *words, unsigned long *outlen) { unsigned long x, y, t, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(words != NULL); LTC_ARGCHK(outlen != NULL); /* header is at least 3 bytes */ if (inlen < 3) { return CRYPT_INVALID_PACKET; } /* must be room for at least two words */ if (*outlen < 2) { *outlen = 2; return CRYPT_BUFFER_OVERFLOW; } /* decode the packet header */ x = 0; if ((in[x++] & 0x1F) != 0x06) { return CRYPT_INVALID_PACKET; } /* get the length of the data */ y = inlen - x; if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { return err; } x += y; if ((len == 0) || (len > (inlen - x))) { return CRYPT_INVALID_PACKET; } /* decode words */ y = 0; t = 0; while (len--) { t = (t << 7) | (in[x] & 0x7F); if (!(in[x++] & 0x80)) { /* store t */ if (y >= *outlen) { y++; } else { if (y == 0) { if (t <= 79) { words[0] = t / 40; words[1] = t % 40; } else { words[0] = 2; words[1] = t - 80; } y = 2; } else { words[y++] = t; } } t = 0; } } if (y > *outlen) { err = CRYPT_BUFFER_OVERFLOW; } else { err = CRYPT_OK; } *outlen = y; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c000066400000000000000000000045111464416617300336660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_object_identifier.c ASN.1 DER, Encode Object Identifier, Tom St Denis */ #ifdef LTC_DER /** Encode an OID @param words The words to encode (upto 32-bits each) @param nwords The number of words in the OID @param out [out] Destination of OID data @param outlen [in/out] The max and resulting size of the OID @return CRYPT_OK if successful */ int der_encode_object_identifier(const unsigned long *words, unsigned long nwords, unsigned char *out, unsigned long *outlen) { unsigned long i, x, y, z, t, mask, wordbuf; int err; LTC_ARGCHK(words != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* check length */ if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) { return err; } if (x > *outlen) { *outlen = x; return CRYPT_BUFFER_OVERFLOW; } /* compute length to store OID data */ z = 0; wordbuf = words[0] * 40 + words[1]; for (y = 1; y < nwords; y++) { t = der_object_identifier_bits(wordbuf); z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); if (y < nwords - 1) { wordbuf = words[y + 1]; } } /* store header + length */ x = 0; out[x++] = 0x06; y = *outlen - x; if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) { return err; } x += y; /* store first byte */ wordbuf = words[0] * 40 + words[1]; for (i = 1; i < nwords; i++) { /* store 7 bit words in little endian */ t = wordbuf & 0xFFFFFFFF; if (t) { y = x; mask = 0; while (t) { out[x++] = (unsigned char)((t & 0x7F) | mask); t >>= 7; mask |= 0x80; /* upper bit is set on all but the last byte */ } /* now swap bytes y...x-1 */ z = x - 1; while (y < z) { t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t; ++y; --z; } } else { /* zero word */ out[x++] = 0x00; } if (i < nwords - 1) { wordbuf = words[i + 1]; } } *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c000066400000000000000000000033141464416617300337120ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_object_identifier.c ASN.1 DER, get length of Object Identifier, Tom St Denis */ #ifdef LTC_DER unsigned long der_object_identifier_bits(unsigned long x) { unsigned long c; x &= 0xFFFFFFFF; c = 0; while (x) { ++c; x >>= 1; } return c; } /** Gets length of DER encoding of Object Identifier @param nwords The number of OID words @param words The actual OID words to get the size of @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen) { unsigned long y, z, t, wordbuf; LTC_ARGCHK(words != NULL); LTC_ARGCHK(outlen != NULL); /* must be >= 2 words */ if (nwords < 2) { return CRYPT_INVALID_ARG; } /* word1 = 0,1,2 and word2 0..39 */ if (words[0] > 2 || (words[0] < 2 && words[1] > 39)) { return CRYPT_INVALID_ARG; } /* leading word is the first two */ z = 0; wordbuf = words[0] * 40 + words[1]; for (y = 1; y < nwords; y++) { t = der_object_identifier_bits(wordbuf); z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); if (y < nwords - 1) { /* grab next word */ wordbuf = words[y+1]; } } /* now depending on the length our length encoding changes */ if (z < 128) { z += 2; } else if (z < 256) { z += 3; } else if (z < 65536UL) { z += 4; } else { return CRYPT_INVALID_ARG; } *outlen = z; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/octet/000077500000000000000000000000001464416617300233505ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c000066400000000000000000000027201464416617300303560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_octet_string.c ASN.1 DER, encode a OCTET STRING, Tom St Denis */ #ifdef LTC_DER /** Store a OCTET STRING @param in The DER encoded OCTET STRING @param inlen The size of the DER OCTET STRING @param out [out] The array of octets stored (one per char) @param outlen [in/out] The number of octets stored @return CRYPT_OK if successful */ int der_decode_octet_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* must have header at least */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* check for 0x04 */ if ((in[0] & 0x1F) != 0x04) { return CRYPT_INVALID_PACKET; } x = 1; /* get the length of the data */ y = inlen - x; if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { return err; } x += y; /* is it too long? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } if (len > (inlen - x)) { return CRYPT_INVALID_PACKET; } /* read the data */ for (y = 0; y < len; y++) { out[y] = in[x++]; } *outlen = y; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c000066400000000000000000000026411464416617300303720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_octet_string.c ASN.1 DER, encode a OCTET STRING, Tom St Denis */ #ifdef LTC_DER /** Store an OCTET STRING @param in The array of OCTETS to store (one per char) @param inlen The number of OCTETS to store @param out [out] The destination for the DER encoded OCTET STRING @param outlen [in/out] The max size and resulting size of the DER OCTET STRING @return CRYPT_OK if successful */ int der_encode_octet_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get the size */ if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) { return err; } /* too big? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } /* encode the header+len */ x = 0; out[x++] = 0x04; len = *outlen - x; if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { return err; } x += len; /* store octets */ for (y = 0; y < inlen; y++) { out[x++] = in[y]; } /* retun length */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c000066400000000000000000000013751464416617300304210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_octet_string.c ASN.1 DER, get length of OCTET STRING, Tom St Denis */ #ifdef LTC_DER /** Gets length of DER encoding of OCTET STRING @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_octet_string(unsigned long noctets, unsigned long *outlen) { unsigned long x; int err; LTC_ARGCHK(outlen != NULL); if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { return err; } *outlen = 1 + x + noctets; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/000077500000000000000000000000001464416617300256005ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c000066400000000000000000000031411464416617300334460ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_printable_string.c ASN.1 DER, encode a printable STRING, Tom St Denis */ #ifdef LTC_DER /** Store a printable STRING @param in The DER encoded printable STRING @param inlen The size of the DER printable STRING @param out [out] The array of octets stored (one per char) @param outlen [in/out] The number of octets stored @return CRYPT_OK if successful */ int der_decode_printable_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int t, err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* must have header at least */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* check for 0x13 */ if ((in[0] & 0x1F) != 0x13) { return CRYPT_INVALID_PACKET; } x = 1; /* get the length of the data */ y = inlen - x; if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { return err; } x += y; /* is it too long? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } if (len > (inlen - x)) { return CRYPT_INVALID_PACKET; } /* read the data */ for (y = 0; y < len; y++) { t = der_printable_value_decode(in[x++]); if (t == -1) { return CRYPT_INVALID_ARG; } out[y] = t; } *outlen = y; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c000066400000000000000000000027371464416617300334720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_printable_string.c ASN.1 DER, encode a printable STRING, Tom St Denis */ #ifdef LTC_DER /** Store an printable STRING @param in The array of printable to store (one per char) @param inlen The number of printable to store @param out [out] The destination for the DER encoded printable STRING @param outlen [in/out] The max size and resulting size of the DER printable STRING @return CRYPT_OK if successful */ int der_encode_printable_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get the size */ if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) { return err; } /* too big? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } /* encode the header+len */ x = 0; out[x++] = 0x13; len = *outlen - x; if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { return err; } x += len; /* store octets */ for (y = 0; y < inlen; y++) { out[x++] = der_printable_char_encode(in[y]); } /* retun length */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c000066400000000000000000000051021464416617300335030ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_printable_string.c ASN.1 DER, get length of Printable STRING, Tom St Denis */ #ifdef LTC_DER static const struct { int code, value; } printable_table[] = { { ' ', 32 }, { '\'', 39 }, { '(', 40 }, { ')', 41 }, { '+', 43 }, { ',', 44 }, { '-', 45 }, { '.', 46 }, { '/', 47 }, { '0', 48 }, { '1', 49 }, { '2', 50 }, { '3', 51 }, { '4', 52 }, { '5', 53 }, { '6', 54 }, { '7', 55 }, { '8', 56 }, { '9', 57 }, { ':', 58 }, { '=', 61 }, { '?', 63 }, { 'A', 65 }, { 'B', 66 }, { 'C', 67 }, { 'D', 68 }, { 'E', 69 }, { 'F', 70 }, { 'G', 71 }, { 'H', 72 }, { 'I', 73 }, { 'J', 74 }, { 'K', 75 }, { 'L', 76 }, { 'M', 77 }, { 'N', 78 }, { 'O', 79 }, { 'P', 80 }, { 'Q', 81 }, { 'R', 82 }, { 'S', 83 }, { 'T', 84 }, { 'U', 85 }, { 'V', 86 }, { 'W', 87 }, { 'X', 88 }, { 'Y', 89 }, { 'Z', 90 }, { 'a', 97 }, { 'b', 98 }, { 'c', 99 }, { 'd', 100 }, { 'e', 101 }, { 'f', 102 }, { 'g', 103 }, { 'h', 104 }, { 'i', 105 }, { 'j', 106 }, { 'k', 107 }, { 'l', 108 }, { 'm', 109 }, { 'n', 110 }, { 'o', 111 }, { 'p', 112 }, { 'q', 113 }, { 'r', 114 }, { 's', 115 }, { 't', 116 }, { 'u', 117 }, { 'v', 118 }, { 'w', 119 }, { 'x', 120 }, { 'y', 121 }, { 'z', 122 }, }; int der_printable_char_encode(int c) { int x; for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { if (printable_table[x].code == c) { return printable_table[x].value; } } return -1; } int der_printable_value_decode(int v) { int x; for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { if (printable_table[x].value == v) { return printable_table[x].code; } } return -1; } /** Gets length of DER encoding of Printable STRING @param octets The values you want to encode @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) { unsigned long x; int err; LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(octets != NULL); /* scan string for validity */ for (x = 0; x < noctets; x++) { if (der_printable_char_encode(octets[x]) == -1) { return CRYPT_INVALID_ARG; } } if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { return err; } *outlen = 1 + x + noctets; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/000077500000000000000000000000001464416617300240425ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c000066400000000000000000000014101464416617300306430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_sequence_ex.c ASN.1 DER, decode a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Decode a SEQUENCE @param in The DER encoded input @param inlen The size of the input @param list The list of items to decode @param outlen The number of items in the list @param flags c.f. enum ltc_der_seq @return CRYPT_OK on success */ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, ltc_asn1_list *list, unsigned long outlen, unsigned int flags) { return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c000066400000000000000000000365511464416617300313540ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_sequence_flexi.c ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis */ #ifdef LTC_DER static int s_new_element(ltc_asn1_list **l) { /* alloc new link */ if (*l == NULL) { *l = XCALLOC(1, sizeof(ltc_asn1_list)); if (*l == NULL) { return CRYPT_MEM; } } else { (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list)); if ((*l)->next == NULL) { return CRYPT_MEM; } (*l)->next->prev = *l; *l = (*l)->next; } return CRYPT_OK; } /** ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. @param in The input buffer @param inlen [in/out] The length of the input buffer and on output the amount of decoded data @param out [out] A pointer to the linked list @param depth The depth/level of decoding recursion we've already reached @return CRYPT_OK on success. */ static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth) { ltc_asn1_list *l; unsigned long err, identifier, len, totlen, data_offset, id_len, len_len; void *realloc_tmp; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); LTC_ARGCHK(out != NULL); l = NULL; totlen = 0; if (*inlen == 0) { /* alloc new link */ if ((err = s_new_element(&l)) != CRYPT_OK) { goto error; } } /* scan the input and and get lengths and what not */ while (*inlen) { /* alloc new link */ if ((err = s_new_element(&l)) != CRYPT_OK) { goto error; } id_len = *inlen; if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) { goto error; } /* read the type byte */ identifier = *in; if (l->type != LTC_ASN1_EOL) { /* fetch length */ len_len = *inlen - id_len; #if defined(LTC_TEST_DBG) data_offset = 666; len = 0; #endif if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) { #if defined(LTC_TEST_DBG) fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); #endif goto error; } else if (len > (*inlen - id_len - len_len)) { err = CRYPT_INVALID_PACKET; #if defined(LTC_TEST_DBG) fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); #endif goto error; } data_offset = id_len + len_len; #if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 if (l->type == LTC_ASN1_CUSTOM_TYPE && l->klass == LTC_ASN1_CL_CONTEXT_SPECIFIC) { fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag); } else { fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]); } #endif len += data_offset; if (l->type == LTC_ASN1_CUSTOM_TYPE) { /* Custom type, use the 'used' field to store the original identifier */ l->used = identifier; if (l->pc == LTC_ASN1_PC_CONSTRUCTED) { /* treat constructed elements like SEQUENCEs */ identifier = 0x20; } else { /* primitive elements are treated as opaque data */ identifier = 0x80; } } } else { /* Init this so gcc won't complain, * as this case will only be hit when we * can't decode the identifier so the * switch-case should go to default anyway... */ data_offset = 0; len = 0; } /* now switch on type */ switch (identifier) { case 0x01: /* BOOLEAN */ if (l->type != LTC_ASN1_BOOLEAN) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = 1; l->data = XCALLOC(1, sizeof(int)); if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { goto error; } if ((err = der_length_boolean(&len)) != CRYPT_OK) { goto error; } break; case 0x02: /* INTEGER */ if (l->type != LTC_ASN1_INTEGER) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = 1; if ((err = mp_init(&l->data)) != CRYPT_OK) { goto error; } /* decode field */ if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { goto error; } /* calc length of object */ if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { goto error; } break; case 0x03: /* BIT */ if (l->type != LTC_ASN1_BIT_STRING) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */ if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x04: /* OCTET */ if (l->type != LTC_ASN1_OCTET_STRING) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x05: /* NULL */ if (l->type != LTC_ASN1_NULL) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* valid NULL is 0x05 0x00 */ if (in[0] != 0x05 || in[1] != 0x00) { err = CRYPT_INVALID_PACKET; goto error; } /* simple to store ;-) */ l->data = NULL; l->size = 0; len = 2; break; case 0x06: /* OID */ if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len; if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { goto error; } /* resize it to save a bunch of mem */ if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { /* out of heap but this is not an error */ break; } l->data = realloc_tmp; break; case 0x0C: /* UTF8 */ /* init field */ if (l->type != LTC_ASN1_UTF8_STRING) { err = CRYPT_PK_ASN1_ERROR; goto error; } l->size = len; if ((l->data = XCALLOC(l->size, sizeof(wchar_t))) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x13: /* PRINTABLE */ if (l->type != LTC_ASN1_PRINTABLE_STRING) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x14: /* TELETEXT */ if (l->type != LTC_ASN1_TELETEX_STRING) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x16: /* IA5 */ if (l->type != LTC_ASN1_IA5_STRING) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len; if ((l->data = XCALLOC(1, l->size)) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { goto error; } if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { goto error; } break; case 0x17: /* UTC TIME */ if (l->type != LTC_ASN1_UTCTIME) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = 1; if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { err = CRYPT_MEM; goto error; } len = *inlen; if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { goto error; } if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { goto error; } break; case 0x18: if (l->type != LTC_ASN1_GENERALIZEDTIME) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* init field */ l->size = len; if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { err = CRYPT_MEM; goto error; } if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { goto error; } if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { goto error; } break; case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ case 0x30: /* SEQUENCE */ case 0x31: /* SET */ /* init field */ if (identifier == 0x20) { if (l->type != LTC_ASN1_CUSTOM_TYPE) { err = CRYPT_PK_ASN1_ERROR; goto error; } } else if (identifier == 0x30) { if (l->type != LTC_ASN1_SEQUENCE) { err = CRYPT_PK_ASN1_ERROR; goto error; } } else { if (l->type != LTC_ASN1_SET) { err = CRYPT_PK_ASN1_ERROR; goto error; } } /* check that we don't go over the recursion limit */ if (depth > LTC_DER_MAX_RECURSION) { err = CRYPT_PK_ASN1_ERROR; goto error; } if ((l->data = XMALLOC(len)) == NULL) { err = CRYPT_MEM; goto error; } XMEMCPY(l->data, in, len); l->size = len; /* jump to the start of the data */ in += data_offset; *inlen -= data_offset; len -= data_offset; /* save the decoded ASN.1 len */ len_len = len; /* Sequence elements go as child */ if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) { goto error; } if (len_len != len) { err = CRYPT_PK_ASN1_ERROR; goto error; } /* len update */ totlen += data_offset; /* the flexi decoder can also do nothing, so make sure a child has been allocated */ if (l->child) { /* link them up y0 */ l->child->parent = l; } break; case 0x80: /* Context-specific */ if (l->type != LTC_ASN1_CUSTOM_TYPE) { err = CRYPT_PK_ASN1_ERROR; goto error; } if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { err = CRYPT_MEM; goto error; } XMEMCPY(l->data, in + data_offset, len - data_offset); l->size = len - data_offset; break; default: /* invalid byte ... this is a soft error */ /* remove link */ if (l->prev) { l = l->prev; XFREE(l->next); l->next = NULL; } goto outside; } /* advance pointers */ totlen += len; in += len; *inlen -= len; } outside: /* in case we processed anything */ if (totlen) { /* rewind l please */ while (l->prev != NULL || l->parent != NULL) { if (l->parent != NULL) { l = l->parent; } else { l = l->prev; } } } /* return */ *out = l; *inlen = totlen; return CRYPT_OK; error: /* free list */ der_sequence_free(l); return err; } /** ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. @param in The input buffer @param inlen [in/out] The length of the input buffer and on output the amount of decoded data @param out [out] A pointer to the linked list @return CRYPT_OK on success. */ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) { return s_der_decode_sequence_flexi(in, inlen, out, 0); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c000066400000000000000000000110611464416617300313640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file der_decode_sequence_multi.c ASN.1 DER, decode a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Decode a SEQUENCE type using a VA list @param in Input buffer @param inlen Length of input in octets @param a1 Initialized argument list #1 @param a2 Initialized argument list #2 (copy of #1) @param flags c.f. enum ltc_der_seq @return CRYPT_OK on success */ static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags) { int err; ltc_asn1_type type; unsigned long size, x; void *data; ltc_asn1_list *list; LTC_ARGCHK(in != NULL); /* get size of output that will be required */ x = 0; for (;;) { type = (ltc_asn1_type)va_arg(a1, int); if (type == LTC_ASN1_EOL) { break; } size = va_arg(a1, unsigned long); data = va_arg(a1, void*); LTC_UNUSED_PARAM(size); LTC_UNUSED_PARAM(data); switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: case LTC_ASN1_BIT_STRING: case LTC_ASN1_OCTET_STRING: case LTC_ASN1_NULL: case LTC_ASN1_OBJECT_IDENTIFIER: case LTC_ASN1_IA5_STRING: case LTC_ASN1_PRINTABLE_STRING: case LTC_ASN1_UTF8_STRING: case LTC_ASN1_UTCTIME: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: case LTC_ASN1_CHOICE: case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_TELETEX_STRING: case LTC_ASN1_GENERALIZEDTIME: ++x; break; case LTC_ASN1_EOL: case LTC_ASN1_CUSTOM_TYPE: default: return CRYPT_INVALID_ARG; } } /* allocate structure for x elements */ if (x == 0) { return CRYPT_NOP; } list = XCALLOC(x, sizeof(*list)); if (list == NULL) { return CRYPT_MEM; } /* fill in the structure */ x = 0; for (;;) { type = (ltc_asn1_type)va_arg(a2, int); size = va_arg(a2, unsigned long); data = va_arg(a2, void*); if (type == LTC_ASN1_EOL) { break; } switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: case LTC_ASN1_BIT_STRING: case LTC_ASN1_OCTET_STRING: case LTC_ASN1_NULL: case LTC_ASN1_OBJECT_IDENTIFIER: case LTC_ASN1_IA5_STRING: case LTC_ASN1_PRINTABLE_STRING: case LTC_ASN1_UTF8_STRING: case LTC_ASN1_UTCTIME: case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_CHOICE: case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_TELETEX_STRING: case LTC_ASN1_GENERALIZEDTIME: LTC_SET_ASN1(list, x++, type, data, size); break; /* coverity[dead_error_line] */ case LTC_ASN1_EOL: case LTC_ASN1_CUSTOM_TYPE: default: break; } } err = der_decode_sequence_ex(in, inlen, list, x, flags); XFREE(list); return err; } /** Decode a SEQUENCE type using a VA list @param in Input buffer @param inlen Length of input in octets @remark <...> is of the form (int, unsigned long, void*) @return CRYPT_OK on success */ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) { va_list a1, a2; int err; LTC_ARGCHK(in != NULL); va_start(a1, inlen); va_start(a2, inlen); err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED); va_end(a2); va_end(a1); return err; } /** Decode a SEQUENCE type using a VA list @param in Input buffer @param inlen Length of input in octets @param flags c.f. enum ltc_der_seq @remark <...> is of the form (int, unsigned long, void*) @return CRYPT_OK on success */ int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) { va_list a1, a2; int err; LTC_ARGCHK(in != NULL); va_start(a1, flags); va_start(a2, flags); err = s_der_decode_sequence_va(in, inlen, a1, a2, flags); va_end(a2); va_end(a1); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c000066400000000000000000000132021464416617300306570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_sequence_ex.c ASN.1 DER, encode a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Encode a SEQUENCE @param list The list of items to encode @param inlen The number of items in the list @param out [out] The destination @param outlen [in/out] The size of the output @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF @return CRYPT_OK on success */ int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen, int type_of) { int err; ltc_asn1_type type; unsigned long size, x, y, z, i; void *data; LTC_ARGCHK(list != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get size of output that will be required */ y = 0; z = 0; if (der_length_sequence_ex(list, inlen, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG; /* too big ? */ if (*outlen < y) { *outlen = y; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* store header */ x = 0; out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31; y = *outlen - x; if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { goto LBL_ERR; } x += y; /* store data */ *outlen -= x; for (i = 0; i < inlen; i++) { type = list[i].type; size = list[i].size; data = list[i].data; if (type == LTC_ASN1_EOL) { break; } switch (type) { case LTC_ASN1_BOOLEAN: z = *outlen; if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_INTEGER: z = *outlen; if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SHORT_INTEGER: z = *outlen; if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_BIT_STRING: z = *outlen; if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_RAW_BIT_STRING: z = *outlen; if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_OCTET_STRING: z = *outlen; if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_NULL: out[x] = 0x05; out[x+1] = 0x00; z = 2; break; case LTC_ASN1_OBJECT_IDENTIFIER: z = *outlen; if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_IA5_STRING: z = *outlen; if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_PRINTABLE_STRING: z = *outlen; if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_UTF8_STRING: z = *outlen; if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_UTCTIME: z = *outlen; if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_GENERALIZEDTIME: z = *outlen; if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SET: z = *outlen; if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SETOF: z = *outlen; if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SEQUENCE: z = *outlen; if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_CUSTOM_TYPE: z = *outlen; if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_CHOICE: case LTC_ASN1_EOL: case LTC_ASN1_TELETEX_STRING: default: err = CRYPT_INVALID_ARG; goto LBL_ERR; } x += z; *outlen -= z; } *outlen = x; err = CRYPT_OK; LBL_ERR: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c000066400000000000000000000070711464416617300314040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #include /** @file der_encode_sequence_multi.c ASN.1 DER, encode a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Encode a SEQUENCE type using a VA list @param out [out] Destination for data @param outlen [in/out] Length of buffer and resulting length of output @remark <...> is of the form (int, unsigned long, void*) @return CRYPT_OK on success */ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) { int err; ltc_asn1_type type; unsigned long size, x; void *data; va_list args; ltc_asn1_list *list; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get size of output that will be required */ va_start(args, outlen); x = 0; for (;;) { type = (ltc_asn1_type)va_arg(args, int); if (type == LTC_ASN1_EOL) { break; } size = va_arg(args, unsigned long); data = va_arg(args, void*); LTC_UNUSED_PARAM(size); LTC_UNUSED_PARAM(data); switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: case LTC_ASN1_BIT_STRING: case LTC_ASN1_OCTET_STRING: case LTC_ASN1_NULL: case LTC_ASN1_OBJECT_IDENTIFIER: case LTC_ASN1_IA5_STRING: case LTC_ASN1_PRINTABLE_STRING: case LTC_ASN1_UTF8_STRING: case LTC_ASN1_UTCTIME: case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_GENERALIZEDTIME: ++x; break; case LTC_ASN1_CHOICE: case LTC_ASN1_CUSTOM_TYPE: case LTC_ASN1_EOL: case LTC_ASN1_TELETEX_STRING: default: va_end(args); return CRYPT_INVALID_ARG; } } va_end(args); /* allocate structure for x elements */ if (x == 0) { return CRYPT_NOP; } list = XCALLOC(x, sizeof(*list)); if (list == NULL) { return CRYPT_MEM; } /* fill in the structure */ va_start(args, outlen); x = 0; for (;;) { type = (ltc_asn1_type)va_arg(args, int); if (type == LTC_ASN1_EOL) { break; } size = va_arg(args, unsigned long); data = va_arg(args, void*); switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: case LTC_ASN1_BIT_STRING: case LTC_ASN1_OCTET_STRING: case LTC_ASN1_NULL: case LTC_ASN1_OBJECT_IDENTIFIER: case LTC_ASN1_IA5_STRING: case LTC_ASN1_PRINTABLE_STRING: case LTC_ASN1_UTF8_STRING: case LTC_ASN1_UTCTIME: case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_GENERALIZEDTIME: LTC_SET_ASN1(list, x++, type, data, size); break; case LTC_ASN1_CHOICE: case LTC_ASN1_CUSTOM_TYPE: case LTC_ASN1_EOL: case LTC_ASN1_TELETEX_STRING: default: va_end(args); err = CRYPT_INVALID_ARG; goto LBL_ERR; } } va_end(args); err = der_encode_sequence(list, x, out, outlen); LBL_ERR: XFREE(list); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c000066400000000000000000000114641464416617300302170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_sequence.c ASN.1 DER, length a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Get the length of a DER sequence @param list The sequences of items in the SEQUENCE @param inlen The number of items @param outlen [out] The length required in octets to store it @return CRYPT_OK on success */ int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, unsigned long *outlen) { return der_length_sequence_ex(list, inlen, outlen, NULL); } int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, unsigned long *outlen, unsigned long *payloadlen) { int err; ltc_asn1_type type; unsigned long size, x, y, i; void *data; LTC_ARGCHK(list != NULL); LTC_ARGCHK(outlen != NULL); /* get size of output that will be required */ y = 0; for (i = 0; i < inlen; i++) { type = list[i].type; size = list[i].size; data = list[i].data; if (type == LTC_ASN1_EOL) { break; } /* some items may be optional during import */ if (!list[i].used && list[i].optional) continue; switch (type) { case LTC_ASN1_BOOLEAN: if ((err = der_length_boolean(&x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_INTEGER: if ((err = der_length_integer(data, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_SHORT_INTEGER: if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_BIT_STRING: case LTC_ASN1_RAW_BIT_STRING: if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_OCTET_STRING: if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_NULL: y += 2; break; case LTC_ASN1_OBJECT_IDENTIFIER: if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_IA5_STRING: if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_TELETEX_STRING: if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_PRINTABLE_STRING: if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_UTCTIME: if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_GENERALIZEDTIME: if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_UTF8_STRING: if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_CUSTOM_TYPE: if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { goto LBL_ERR; } y += x; break; case LTC_ASN1_CHOICE: case LTC_ASN1_EOL: default: err = CRYPT_INVALID_ARG; goto LBL_ERR; } } if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) { goto LBL_ERR; } if (payloadlen != NULL) { *payloadlen = y; } /* store size */ *outlen = y + x + 1; err = CRYPT_OK; LBL_ERR: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c000066400000000000000000000023241464416617300276520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_sequence_free.c ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis */ #ifdef LTC_DER /** Free memory allocated by der_decode_sequence_flexi() @param in The list to free */ void der_sequence_free(ltc_asn1_list *in) { ltc_asn1_list *l; if (!in) return; /* walk to the start of the chain */ while (in->prev != NULL || in->parent != NULL) { if (in->parent != NULL) { in = in->parent; } else { in = in->prev; } } /* now walk the list and free stuff */ while (in != NULL) { /* is there a child? */ if (in->child) { /* disconnect */ in->child->parent = NULL; der_sequence_free(in->child); } switch (in->type) { case LTC_ASN1_SETOF: break; case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); } break; default : if (in->data != NULL) { XFREE(in->data); } } /* move to next and free current */ l = in->next; XFREE(in); in = l; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c000066400000000000000000000017311464416617300302300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_sequence_shrink.c Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel */ #ifdef LTC_DER /** Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi() @param in The list to shrink */ void der_sequence_shrink(ltc_asn1_list *in) { if (!in) return; /* now walk the list and free stuff */ while (in != NULL) { /* is there a child? */ if (in->child) { der_sequence_shrink(in->child); } switch (in->type) { case LTC_ASN1_CUSTOM_TYPE: case LTC_ASN1_SET: case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break; default: break; } /* move to next and free current */ in = in->next; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/set/000077500000000000000000000000001464416617300230255ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c000066400000000000000000000034511464416617300261360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_set.c ASN.1 DER, Encode a SET, Tom St Denis */ #ifdef LTC_DER /* LTC define to ASN.1 TAG */ static int s_ltc_to_asn1(ltc_asn1_type v) { return der_asn1_type_to_identifier_map[v]; } static int s_qsort_helper(const void *a, const void *b) { ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b; int r; r = s_ltc_to_asn1(A->type) - s_ltc_to_asn1(B->type); /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */ if (r == 0) { /* their order in the original list now determines the position */ return A->used - B->used; } return r; } /* Encode a SET type @param list The list of items to encode @param inlen The number of items in the list @param out [out] The destination @param outlen [in/out] The size of the output @return CRYPT_OK on success */ int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen) { ltc_asn1_list *copy; unsigned long x; int err; /* make copy of list */ copy = XCALLOC(inlen, sizeof(*copy)); if (copy == NULL) { return CRYPT_MEM; } /* fill in used member with index so we can fully sort it */ for (x = 0; x < inlen; x++) { copy[x] = list[x]; copy[x].used = x; } /* sort it by the "type" field */ XQSORT(copy, inlen, sizeof(*copy), &s_qsort_helper); /* call der_encode_sequence_ex() */ err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET); /* free list */ XFREE(copy); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c000066400000000000000000000063511464416617300264650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_setof.c ASN.1 DER, Encode SET OF, Tom St Denis */ #ifdef LTC_DER struct edge { unsigned char *start; unsigned long size; }; static int s_qsort_helper(const void *a, const void *b) { struct edge *A = (struct edge *)a, *B = (struct edge *)b; int r; unsigned long x; /* compare min length */ r = XMEMCMP(A->start, B->start, MIN(A->size, B->size)); if (r == 0 && A->size != B->size) { if (A->size > B->size) { for (x = B->size; x < A->size; x++) { if (A->start[x]) { return 1; } } } else { for (x = A->size; x < B->size; x++) { if (B->start[x]) { return -1; } } } } return r; } /** Encode a SETOF stucture @param list The list of items to encode @param inlen The number of items in the list @param out [out] The destination @param outlen [in/out] The size of the output @return CRYPT_OK on success */ int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, z; ptrdiff_t hdrlen; int err; struct edge *edges; unsigned char *ptr, *buf; /* check that they're all the same type */ for (x = 1; x < inlen; x++) { if (list[x].type != list[x-1].type) { return CRYPT_INVALID_ARG; } } /* alloc buffer to store copy of output */ buf = XCALLOC(1, *outlen); if (buf == NULL) { return CRYPT_MEM; } /* encode list */ if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) { XFREE(buf); return err; } /* allocate edges */ edges = XCALLOC(inlen, sizeof(*edges)); if (edges == NULL) { XFREE(buf); return CRYPT_MEM; } /* skip header */ ptr = buf + 1; /* now skip length data */ x = *ptr++; if (x >= 0x80) { ptr += (x & 0x7F); } /* get the size of the static header */ hdrlen = ptr - buf; /* scan for edges */ x = 0; while (ptr < (buf + *outlen)) { /* store start */ edges[x].start = ptr; /* skip type */ z = 1; /* parse length */ y = ptr[z++]; if (y < 128) { edges[x].size = y; } else { y &= 0x7F; edges[x].size = 0; while (y--) { edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]); } } /* skip content */ edges[x].size += z; ptr += edges[x].size; ++x; } /* sort based on contents (using edges) */ XQSORT(edges, inlen, sizeof(*edges), &s_qsort_helper); /* copy static header */ XMEMCPY(out, buf, hdrlen); /* copy+sort using edges+indecies to output from buffer */ for (y = (unsigned long)hdrlen, x = 0; x < inlen; x++) { XMEMCPY(out+y, edges[x].start, edges[x].size); y += edges[x].size; } #ifdef LTC_CLEAN_STACK zeromem(buf, *outlen); #endif /* free buffers */ XFREE(edges); XFREE(buf); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/000077500000000000000000000000001464416617300251065ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c000066400000000000000000000021531464416617300322640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_short_integer.c ASN.1 DER, decode an integer, Tom St Denis */ #ifdef LTC_DER /** Read a short integer @param in The DER encoded data @param inlen Size of data @param num [out] The integer to decode @return CRYPT_OK if successful */ int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num) { unsigned long len, x, y; LTC_ARGCHK(num != NULL); LTC_ARGCHK(in != NULL); /* check length */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* check header */ x = 0; if ((in[x++] & 0x1F) != 0x02) { return CRYPT_INVALID_PACKET; } /* get the packet len */ len = in[x++]; if (x + len > inlen) { return CRYPT_INVALID_PACKET; } if (len > sizeof(unsigned long)) { return CRYPT_OVERFLOW; } /* read number */ y = 0; while (len--) { y = (y<<8) | (unsigned long)in[x++]; } *num = y; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c000066400000000000000000000033271464416617300323020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_short_integer.c ASN.1 DER, encode an integer, Tom St Denis */ #ifdef LTC_DER /** Store a short integer in the range (0,2^32-1) @param num The integer to encode @param out [out] The destination for the DER encoded integers @param outlen [in/out] The max size and resulting size of the DER encoded integers @return CRYPT_OK if successful */ int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) { unsigned long len, x, y, z; int err; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* force to 32 bits */ num &= 0xFFFFFFFFUL; /* find out how big this will be */ if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) { return err; } if (*outlen < len) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } /* get len of output */ z = 0; y = num; while (y) { ++z; y >>= 8; } /* handle zero */ if (z == 0) { z = 1; } /* see if msb is set */ z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; /* adjust the number so the msB is non-zero */ for (x = 0; (z <= 4) && (x < (4 - z)); x++) { num <<= 8; } /* store header */ x = 0; out[x++] = 0x02; out[x++] = (unsigned char)z; /* if 31st bit is set output a leading zero and decrement count */ if (z == 5) { out[x++] = 0; --z; } /* store values */ for (y = 0; y < z; y++) { out[x++] = (unsigned char)((num >> 24) & 0xFF); num <<= 8; } /* we good */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c000066400000000000000000000017771464416617300323350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_short_integer.c ASN.1 DER, get length of encoding, Tom St Denis */ #ifdef LTC_DER /** Gets length of DER encoding of num @param num The integer to get the size of @param outlen [out] The length of the DER encoding for the given integer @return CRYPT_OK if successful */ int der_length_short_integer(unsigned long num, unsigned long *outlen) { unsigned long z, y; int err; LTC_ARGCHK(outlen != NULL); /* force to 32 bits */ num &= 0xFFFFFFFFUL; /* get the number of bytes */ z = 0; y = num; while (y) { ++z; y >>= 8; } /* handle zero */ if (z == 0) { z = 1; } else if ((num&(1UL<<((z<<3) - 1))) != 0) { /* in case msb is set */ ++z; } if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) { return err; } *outlen = 1 + y + z; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/000077500000000000000000000000001464416617300252725ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c000066400000000000000000000031041464416617300326310ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_teletex_string.c ASN.1 DER, encode a teletex STRING */ #ifdef LTC_DER /** Store a teletex STRING @param in The DER encoded teletex STRING @param inlen The size of the DER teletex STRING @param out [out] The array of octets stored (one per char) @param outlen [in/out] The number of octets stored @return CRYPT_OK if successful */ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int t, err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* must have header at least */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* check for 0x14 */ if ((in[0] & 0x1F) != 0x14) { return CRYPT_INVALID_PACKET; } x = 1; /* get the length of the data */ y = inlen - x; if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { return err; } x += y; /* is it too long? */ if (len > *outlen) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } if (len > (inlen - x)) { return CRYPT_INVALID_PACKET; } /* read the data */ for (y = 0; y < len; y++) { t = der_teletex_value_decode(in[x++]); if (t == -1) { return CRYPT_INVALID_ARG; } out[y] = t; } *outlen = y; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c000066400000000000000000000063361464416617300327010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_teletex_string.c ASN.1 DER, get length of teletex STRING */ #ifdef LTC_DER static const struct { int code, value; } teletex_table[] = { { '\0', 0 }, { '\a', 7 }, { '\b', 8 }, { '\t', 9 }, { '\n', 10 }, { '\v', 11 }, { '\f', 12 }, { '\r', 13 }, { ' ', 32 }, { '!', 33 }, { '"', 34 }, { '%', 37 }, { '&', 38 }, { '\'', 39 }, { '(', 40 }, { ')', 41 }, { '+', 43 }, { ',', 44 }, { '-', 45 }, { '.', 46 }, { '/', 47 }, { '0', 48 }, { '1', 49 }, { '2', 50 }, { '3', 51 }, { '4', 52 }, { '5', 53 }, { '6', 54 }, { '7', 55 }, { '8', 56 }, { '9', 57 }, { ':', 58 }, { ';', 59 }, { '<', 60 }, { '=', 61 }, { '>', 62 }, { '?', 63 }, { '@', 64 }, { 'A', 65 }, { 'B', 66 }, { 'C', 67 }, { 'D', 68 }, { 'E', 69 }, { 'F', 70 }, { 'G', 71 }, { 'H', 72 }, { 'I', 73 }, { 'J', 74 }, { 'K', 75 }, { 'L', 76 }, { 'M', 77 }, { 'N', 78 }, { 'O', 79 }, { 'P', 80 }, { 'Q', 81 }, { 'R', 82 }, { 'S', 83 }, { 'T', 84 }, { 'U', 85 }, { 'V', 86 }, { 'W', 87 }, { 'X', 88 }, { 'Y', 89 }, { 'Z', 90 }, { '[', 91 }, { ']', 93 }, { '_', 95 }, { 'a', 97 }, { 'b', 98 }, { 'c', 99 }, { 'd', 100 }, { 'e', 101 }, { 'f', 102 }, { 'g', 103 }, { 'h', 104 }, { 'i', 105 }, { 'j', 106 }, { 'k', 107 }, { 'l', 108 }, { 'm', 109 }, { 'n', 110 }, { 'o', 111 }, { 'p', 112 }, { 'q', 113 }, { 'r', 114 }, { 's', 115 }, { 't', 116 }, { 'u', 117 }, { 'v', 118 }, { 'w', 119 }, { 'x', 120 }, { 'y', 121 }, { 'z', 122 }, { '|', 124 }, { ' ', 160 }, { 0xa1, 161 }, { 0xa2, 162 }, { 0xa3, 163 }, { '$', 164 }, { 0xa5, 165 }, { '#', 166 }, { 0xa7, 167 }, { 0xa4, 168 }, { 0xab, 171 }, { 0xb0, 176 }, { 0xb1, 177 }, { 0xb2, 178 }, { 0xb3, 179 }, { 0xd7, 180 }, { 0xb5, 181 }, { 0xb6, 182 }, { 0xb7, 183 }, { 0xf7, 184 }, { 0xbb, 187 }, { 0xbc, 188 }, { 0xbd, 189 }, { 0xbe, 190 }, { 0xbf, 191 }, }; int der_teletex_char_encode(int c) { int x; for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { if (teletex_table[x].code == c) { return teletex_table[x].value; } } return -1; } int der_teletex_value_decode(int v) { int x; for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { if (teletex_table[x].value == v) { return teletex_table[x].code; } } return -1; } /** Gets length of DER encoding of teletex STRING @param octets The values you want to encode @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) { unsigned long x; int err; LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(octets != NULL); /* scan string for validity */ for (x = 0; x < noctets; x++) { if (der_teletex_char_encode(octets[x]) == -1) { return CRYPT_INVALID_ARG; } } if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { return err; } *outlen = 1 + x + noctets; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utctime/000077500000000000000000000000001464416617300237045ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c000066400000000000000000000053271464416617300276660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_utctime.c ASN.1 DER, decode a UTCTIME, Tom St Denis */ #ifdef LTC_DER static int s_char_to_int(unsigned char x) { switch (x) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; default: return 100; } } #define DECODE_V(y, max) \ y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ if (y >= max) return CRYPT_INVALID_PACKET; \ x += 2; /** Decodes a UTC time structure in DER format (reads all 6 valid encoding formats) @param in Input buffer @param inlen Length of input buffer in octets @param out [out] Destination of UTC time structure @return CRYPT_OK if successful */ int der_decode_utctime(const unsigned char *in, unsigned long *inlen, ltc_utctime *out) { unsigned char buf[32] = { 0 }; /* initialize as all zeroes */ unsigned long x; int y; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != NULL); LTC_ARGCHK(out != NULL); /* check header */ if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { return CRYPT_INVALID_PACKET; } /* decode the string */ for (x = 0; x < in[1]; x++) { y = der_ia5_value_decode(in[x+2]); if (y == -1) { return CRYPT_INVALID_PACKET; } buf[x] = y; } *inlen = 2 + x; /* possible encodings are YYMMDDhhmmZ YYMMDDhhmm+hh'mm' YYMMDDhhmm-hh'mm' YYMMDDhhmmssZ YYMMDDhhmmss+hh'mm' YYMMDDhhmmss-hh'mm' So let's do a trivial decode upto [including] mm */ x = 0; DECODE_V(out->YY, 100); DECODE_V(out->MM, 13); DECODE_V(out->DD, 32); DECODE_V(out->hh, 24); DECODE_V(out->mm, 60); /* clear timezone and seconds info */ out->off_dir = out->off_hh = out->off_mm = out->ss = 0; /* now is it Z, +, - or 0-9 */ if (buf[x] == 'Z') { return CRYPT_OK; } if (buf[x] == '+' || buf[x] == '-') { out->off_dir = (buf[x++] == '+') ? 0 : 1; DECODE_V(out->off_hh, 24); DECODE_V(out->off_mm, 60); return CRYPT_OK; } /* decode seconds */ DECODE_V(out->ss, 60); /* now is it Z, +, - */ if (buf[x] == 'Z') { return CRYPT_OK; } if (buf[x] == '+' || buf[x] == '-') { out->off_dir = (buf[x++] == '+') ? 0 : 1; DECODE_V(out->off_hh, 24); DECODE_V(out->off_mm, 60); return CRYPT_OK; } return CRYPT_INVALID_PACKET; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c000066400000000000000000000034111464416617300276700ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_utctime.c ASN.1 DER, encode a UTCTIME, Tom St Denis */ #ifdef LTC_DER static const char * const baseten = "0123456789"; #define STORE_V(y) \ out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ out[x++] = der_ia5_char_encode(baseten[y % 10]); /** Encodes a UTC time structure in DER format @param utctime The UTC time structure to encode @param out The destination of the DER encoding of the UTC time structure @param outlen [in/out] The length of the DER encoding @return CRYPT_OK if successful */ int der_encode_utctime(const ltc_utctime *utctime, unsigned char *out, unsigned long *outlen) { unsigned long x, tmplen; int err; LTC_ARGCHK(utctime != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) { return err; } if (tmplen > *outlen) { *outlen = tmplen; return CRYPT_BUFFER_OVERFLOW; } /* store header */ out[0] = 0x17; /* store values */ x = 2; STORE_V(utctime->YY); STORE_V(utctime->MM); STORE_V(utctime->DD); STORE_V(utctime->hh); STORE_V(utctime->mm); STORE_V(utctime->ss); if (utctime->off_mm || utctime->off_hh) { out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+'); STORE_V(utctime->off_hh); STORE_V(utctime->off_mm); } else { out[x++] = der_ia5_char_encode('Z'); } /* store length */ out[1] = (unsigned char)(x - 2); /* all good let's return */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c000066400000000000000000000014611464416617300277170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_utctime.c ASN.1 DER, get length of UTCTIME, Tom St Denis */ #ifdef LTC_DER /** Gets length of DER encoding of UTCTIME @param utctime The UTC time structure to get the size of @param outlen [out] The length of the DER encoding @return CRYPT_OK if successful */ int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen) { LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(utctime != NULL); if (utctime->off_hh == 0 && utctime->off_mm == 0) { /* we encode as YYMMDDhhmmssZ */ *outlen = 2 + 13; } else { /* we encode as YYMMDDhhmmss{+|-}hh'mm' */ *outlen = 2 + 17; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utf8/000077500000000000000000000000001464416617300231205ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c000066400000000000000000000056721464416617300277070ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_utf8_string.c ASN.1 DER, encode a UTF8 STRING, Tom St Denis */ #ifdef LTC_DER /** Decode a UTF8 STRING and recover an array of unicode characters. @param in The DER encoded UTF8 STRING @param inlen The size of the DER UTF8 STRING @param out [out] The array of unicode characters (wchar_t*) @param outlen [in/out] The number of unicode characters in the array @return CRYPT_OK if successful */ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, wchar_t *out, unsigned long *outlen) { wchar_t tmp; unsigned long x, y, z, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* must have header at least */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* check for 0x0C */ if ((in[0] & 0x1F) != 0x0C) { return CRYPT_INVALID_PACKET; } x = 1; /* get the length of the data */ y = inlen - x; if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { return err; } x += y; if (len > (inlen - x)) { return CRYPT_INVALID_PACKET; } /* proceed to recover unicode characters from utf8 data. for reference see Section 3 of RFC 3629: https://tools.ietf.org/html/rfc3629#section-3 */ len += x; for (y = 0; x < len; ) { /* read first byte */ tmp = in[x++]; /* a unicode character is recovered from a sequence of 1 to 4 utf8 bytes. the form of those bytes must match a row in the following table: 0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx the number of leading ones in the first byte (0,2,3,4) determines the number of remaining bytes to read (0,1,2,3) */ /* determine z, the number of leading ones. this is done by left-shifting tmp, which clears the ms-bits */ for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF); /* z should be in {0,2,3,4} */ if (z == 1 || z > 4) { return CRYPT_INVALID_PACKET; } /* right-shift tmp to restore least-sig bits */ tmp >>= z; /* now update z so it equals the number of additional bytes to read */ if (z > 0) { --z; } if (x + z > len) { return CRYPT_INVALID_PACKET; } /* read remaining bytes */ while (z-- != 0) { if ((in[x] & 0xC0) != 0x80) { return CRYPT_INVALID_PACKET; } tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F); } if (y < *outlen) { out[y] = tmp; } y++; } if (y > *outlen) { err = CRYPT_BUFFER_OVERFLOW; } else { err = CRYPT_OK; } *outlen = y; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c000066400000000000000000000041611464416617300277110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_encode_utf8_string.c ASN.1 DER, encode a UTF8 STRING, Tom St Denis */ #ifdef LTC_DER /** Store an UTF8 STRING @param in The array of UTF8 to store (one per wchar_t) @param inlen The number of UTF8 to store @param out [out] The destination for the DER encoded UTF8 STRING @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING @return CRYPT_OK if successful */ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* get the size */ for (x = len = 0; x < inlen; x++) { if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; len += der_utf8_charsize(in[x]); } if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { return err; } x += len + 1; /* too big? */ if (x > *outlen) { *outlen = x; return CRYPT_BUFFER_OVERFLOW; } /* encode the header+len */ x = 0; out[x++] = 0x0C; y = *outlen - x; if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) { return err; } x += y; /* store UTF8 */ for (y = 0; y < inlen; y++) { switch (der_utf8_charsize(in[y])) { case 1: out[x++] = (unsigned char)in[y]; break; case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break; case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; #if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; #endif default: break; } } /* return length */ *outlen = x; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c000066400000000000000000000034131464416617300277340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_length_utf8_string.c ASN.1 DER, get length of UTF8 STRING, Tom St Denis */ #ifdef LTC_DER /** Return the size in bytes of a UTF-8 character @param c The UTF-8 character to measure @return The size in bytes */ unsigned long der_utf8_charsize(const wchar_t c) { if (c <= 0x7F) { return 1; } if (c <= 0x7FF) { return 2; } #if LTC_WCHAR_MAX == 0xFFFF return 3; #else if (c <= 0xFFFF) { return 3; } return 4; #endif } /** Test whether the given code point is valid character @param c The UTF-8 character to test @return 1 - valid, 0 - invalid */ int der_utf8_valid_char(const wchar_t c) { LTC_UNUSED_PARAM(c); #if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF if (c > 0x10FFFF) return 0; #endif #if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF if (c < 0) return 0; #endif return 1; } /** Gets length of DER encoding of UTF8 STRING @param in The characters to measure the length of @param noctets The number of octets in the string to encode @param outlen [out] The length of the DER encoding for the given string @return CRYPT_OK if successful */ int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen) { unsigned long x, len; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(outlen != NULL); len = 0; for (x = 0; x < noctets; x++) { if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; len += der_utf8_charsize(in[x]); } if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { return err; } *outlen = 1 + x + len; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/oid/000077500000000000000000000000001464416617300222335ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c000066400000000000000000000022401464416617300245010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_DER typedef struct { enum ltc_oid_id id; const char* oid; } oid_table_entry; static const oid_table_entry pka_oids[] = { { LTC_OID_RSA, "1.2.840.113549.1.1.1" }, { LTC_OID_DSA, "1.2.840.10040.4.1" }, { LTC_OID_EC, "1.2.840.10045.2.1" }, { LTC_OID_EC_PRIMEF, "1.2.840.10045.1.1" }, { LTC_OID_X25519, "1.3.101.110" }, { LTC_OID_ED25519, "1.3.101.112" }, }; /* Returns the OID requested. @return CRYPT_OK if valid */ int pk_get_oid(enum ltc_oid_id id, const char **st) { unsigned int i; LTC_ARGCHK(st != NULL); for (i = 0; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) { if (pka_oids[i].id == id) { *st = pka_oids[i].oid; return CRYPT_OK; } } return CRYPT_INVALID_ARG; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c000066400000000000000000000017741464416617300245140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_DER /* Compare an OID string to an array of `unsigned long`. @return CRYPT_OK if equal */ int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size) { unsigned long i; char tmp[256] = { 0 }; int err; if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; i = sizeof(tmp); if ((err = pk_oid_num_to_str(o2, o2size, tmp, &i)) != CRYPT_OK) { return err; } if (XSTRCMP(o1, tmp) != 0) { return CRYPT_PK_INVALID_TYPE; } return CRYPT_OK; } /* Compare an OID string to an OID element decoded from ASN.1. @return CRYPT_OK if equal */ int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2) { if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; if (o2->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG; return pk_oid_cmp_with_ulong(o1, o2->data, o2->size); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c000066400000000000000000000040531464416617300245360ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen) { unsigned long i, j, limit, oid_j; size_t OID_len; LTC_ARGCHK(oidlen != NULL); limit = *oidlen; *oidlen = 0; /* make sure that we return zero oidlen on error */ for (i = 0; i < limit; i++) oid[i] = 0; if (OID == NULL) return CRYPT_OK; OID_len = XSTRLEN(OID); if (OID_len == 0) return CRYPT_OK; for (i = 0, j = 0; i < OID_len; i++) { if (OID[i] == '.') { if (++j >= limit) continue; } else if ((OID[i] >= '0') && (OID[i] <= '9')) { if ((j >= limit) || (oid == NULL)) continue; oid_j = oid[j]; oid[j] = oid[j] * 10 + (OID[i] - '0'); if (oid[j] < oid_j) return CRYPT_OVERFLOW; } else { return CRYPT_ERROR; } } if (j == 0) return CRYPT_ERROR; if (j >= limit) { *oidlen = j; return CRYPT_BUFFER_OVERFLOW; } *oidlen = j + 1; return CRYPT_OK; } int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen) { int i; unsigned long j, k; char tmp[256] = { 0 }; LTC_ARGCHK(oid != NULL); LTC_ARGCHK(oidlen < INT_MAX); LTC_ARGCHK(outlen != NULL); for (i = oidlen - 1, k = 0; i >= 0; i--) { j = oid[i]; if (j == 0) { tmp[k] = '0'; if (++k >= sizeof(tmp)) return CRYPT_ERROR; } else { while (j > 0) { tmp[k] = '0' + (j % 10); if (++k >= sizeof(tmp)) return CRYPT_ERROR; j /= 10; } } if (i > 0) { tmp[k] = '.'; if (++k >= sizeof(tmp)) return CRYPT_ERROR; } } if (*outlen < k + 1) { *outlen = k + 1; return CRYPT_BUFFER_OVERFLOW; } LTC_ARGCHK(OID != NULL); for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1]; OID[k] = '\0'; *outlen = k; /* the length without terminating NUL byte */ return CRYPT_OK; } optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/pkcs8/000077500000000000000000000000001464416617300225105ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c000066400000000000000000000062711464416617300264040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_PKCS_8 /** PKCS#8 decrypt if necessary & flexi-decode @param in Pointer to the ASN.1 encoded input data @param inlen Length of the input data @param pwd Pointer to the password that was used when encrypting @param pwdlen Length of the password @param decoded_list Pointer to a pointer for the flexi-decoded list @return CRYPT_OK on success */ int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ltc_asn1_list **decoded_list) { unsigned long len = inlen; unsigned long dec_size; unsigned char *dec_data = NULL; ltc_asn1_list *l = NULL; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(decoded_list != NULL); *decoded_list = NULL; if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) { /* the following "if" detects whether it is encrypted or not */ /* PKCS8 Setup * 0:d=0 hl=4 l= 380 cons: SEQUENCE * 4:d=1 hl=2 l= 78 cons: SEQUENCE * 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid) * 17:d=2 hl=2 l= 65 cons: SEQUENCE * Stuff in between is dependent on whether it's PBES1 or PBES2 * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) */ if (l->type == LTC_ASN1_SEQUENCE && LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) && LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) && LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) && LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) { ltc_asn1_list *lalgoid = l->child->child; pbes_arg pbes; XMEMSET(&pbes, 0, sizeof(pbes)); if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) { /* Successfully extracted PBES1 parameters */ } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) { /* Successfully extracted PBES2 parameters */ } else { /* unsupported encryption */ err = CRYPT_INVALID_PACKET; goto LBL_DONE; } pbes.enc_data = l->child->next; pbes.pwd = pwd; pbes.pwdlen = pwdlen; dec_size = pbes.enc_data->size; if ((dec_data = XMALLOC(dec_size)) == NULL) { err = CRYPT_MEM; goto LBL_DONE; } if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE; der_free_sequence_flexi(l); l = NULL; err = der_decode_sequence_flexi(dec_data, &dec_size, &l); if (err != CRYPT_OK) goto LBL_DONE; *decoded_list = l; } else { /* not encrypted */ err = CRYPT_OK; *decoded_list = l; } /* Set l to NULL so it won't be free'd */ l = NULL; } LBL_DONE: if (l) der_free_sequence_flexi(l); if (dec_data) { zeromem(dec_data, dec_size); XFREE(dec_data); } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/x509/000077500000000000000000000000001464416617300221655ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c000066400000000000000000000074731464416617300321470ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x509_decode_public_key_from_certificate.c ASN.1 DER/X.509, decode a certificate */ #ifdef LTC_DER /* Check if it looks like a SubjectPublicKeyInfo */ #define LOOKS_LIKE_SPKI(l) ((l) != NULL) \ && ((l)->type == LTC_ASN1_SEQUENCE) \ && ((l)->child != NULL) \ && ((l)->child->type == LTC_ASN1_OBJECT_IDENTIFIER) \ && ((l)->next != NULL) \ && ((l)->next->type == LTC_ASN1_BIT_STRING) /** Try to decode the public key from a X.509 certificate @param in The input buffer @param inlen The length of the input buffer @param algorithm One out of the enum #public_key_algorithms @param param_type The parameters' type out of the enum ltc_asn1_type @param parameters The parameters to include @param parameters_len [in/out] The number of parameters to include @param callback The callback @param ctx The context passed to the callback @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found */ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, public_key_decode_cb callback, void *ctx) { int err; unsigned char *tmpbuf; unsigned long tmpbuf_len, tmp_inlen; ltc_asn1_list *decoded_list = NULL, *l; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != 0); LTC_ARGCHK(callback != NULL); tmpbuf_len = inlen; tmpbuf = XCALLOC(1, tmpbuf_len); if (tmpbuf == NULL) { err = CRYPT_MEM; goto LBL_OUT; } tmp_inlen = inlen; if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) { l = decoded_list; err = CRYPT_NOP; /* Move 2 levels up in the tree SEQUENCE SEQUENCE ... */ if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { l = l->child; if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { l = l->child; /* Move forward in the tree until we find this combination ... SEQUENCE SEQUENCE OBJECT IDENTIFIER NULL BIT STRING */ do { /* The additional check for l->data is there to make sure * we won't try to decode a list that has been 'shrunk' */ if ((l->type == LTC_ASN1_SEQUENCE) && (l->data != NULL) && LOOKS_LIKE_SPKI(l->child)) { if (algorithm == LTC_OID_EC) { err = callback(l->data, l->size, ctx); } else { err = x509_decode_subject_public_key_info(l->data, l->size, algorithm, tmpbuf, &tmpbuf_len, param_type, parameters, parameters_len); if (err == CRYPT_OK) { err = callback(tmpbuf, tmpbuf_len, ctx); goto LBL_OUT; } } } l = l->next; } while(l); } } } LBL_OUT: if (decoded_list) der_free_sequence_flexi(decoded_list); if (tmpbuf != NULL) XFREE(tmpbuf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c000066400000000000000000000067611464416617300313130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x509_decode_subject_public_key_info.c ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav */ #ifdef LTC_DER /* AlgorithmIdentifier := SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm * } * * SubjectPublicKeyInfo := SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING * } */ /** Decode a SubjectPublicKeyInfo @param in The input buffer @param inlen The length of the input buffer @param algorithm One out of the enum #public_key_algorithms @param public_key The buffer for the public key @param public_key_len [in/out] The length of the public key buffer and the written length @param parameters_type The parameters' type out of the enum ltc_asn1_type @param parameters The parameters to include @param parameters_len [in/out] The number of parameters to include @return CRYPT_OK on success */ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, unsigned int algorithm, void* public_key, unsigned long* public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len) { int err; unsigned long len, alg_id_num, tmplen; const char* oid; unsigned char *tmpbuf; unsigned long tmpoid[16]; unsigned long *_parameters_len; ltc_asn1_list alg_id[2]; ltc_asn1_list subject_pubkey[2]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen != 0); LTC_ARGCHK(public_key_len != NULL); if (parameters_type != LTC_ASN1_EOL) { if ((parameters == NULL) || (parameters_len == NULL)) { tmplen = 0; _parameters_len = &tmplen; } else { _parameters_len = parameters_len; } } err = pk_get_oid(algorithm, &oid); if (err != CRYPT_OK) { return err; } /* see if the OpenSSL DER format RSA public key will work */ tmpbuf = XCALLOC(1, inlen); if (tmpbuf == NULL) { err = CRYPT_MEM; goto LBL_ERR; } /* this includes the internal hash ID and optional params (NULL in this case) */ LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); if (parameters_type == LTC_ASN1_EOL) { alg_id_num = 1; } else { LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len); alg_id_num = 2; } /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet */ LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num); LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U); err=der_decode_sequence(in, inlen, subject_pubkey, 2UL); if (err != CRYPT_OK) { goto LBL_ERR; } if (parameters_type != LTC_ASN1_EOL) { *_parameters_len = alg_id[1].size; } if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { /* OID mismatch */ goto LBL_ERR; } len = subject_pubkey[1].size/8; if (*public_key_len >= len) { XMEMCPY(public_key, subject_pubkey[1].data, len); *public_key_len = len; } else { *public_key_len = len; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: XFREE(tmpbuf); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c000066400000000000000000000042021464416617300313110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x509_encode_subject_public_key_info.c ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav */ #ifdef LTC_DER /* AlgorithmIdentifier := SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm * } * * SubjectPublicKeyInfo := SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING * } */ /** Encode a SubjectPublicKeyInfo @param out The output buffer @param outlen [in/out] Length of buffer and resulting length of output @param algorithm One out of the enum #public_key_algorithms @param public_key The buffer for the public key @param public_key_len The length of the public key buffer @param parameters_type The parameters' type out of the enum ltc_asn1_type @param parameters The parameters to include @param parameters_len The number of parameters to include @return CRYPT_OK on success */ int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, unsigned int algorithm, const void* public_key, unsigned long public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) { int err; ltc_asn1_list alg_id[2]; const char *OID; unsigned long oid[16], oidlen; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if ((err = pk_get_oid(algorithm, &OID)) != CRYPT_OK) { return err; } oidlen = sizeof(oid)/sizeof(oid[0]); if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { return err; } LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len); return der_encode_sequence_multi(out, outlen, LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id, LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key, LTC_ASN1_EOL, 0UL, NULL); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/000077500000000000000000000000001464416617300212115ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh.c000066400000000000000000000221201464416617300217450ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ const ltc_dh_set_type ltc_dh_sets[] = { #ifdef LTC_DH768 { /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */ 96, "DH-768", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH1024 { /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */ 128, "DH-1024", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" "FFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH1536 { /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */ 192, "DH-1536", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH2048 { /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */ 256, "DH-2048", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" "15728E5A8AACAA68FFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH3072 { /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */ 384, "DH-3072", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH4096 { /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */ 512, "DH-4096", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" "FFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH6144 { /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */ 768, "DH-6144", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" }, #endif #ifdef LTC_DH8192 { /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */ 1024, "DH-8192", "2", "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" }, #endif { 0, NULL, NULL, NULL } }; /** Returns the DH group size (octets) for given key @param key The DH key to get the size of @return The group size in octets (0 on error) */ int dh_get_groupsize(const dh_key *key) { if (key == NULL) return 0; return mp_unsigned_bin_size(key->prime); } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_check_pubkey.c000066400000000000000000000023301464416617300244620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Check DH public key (INTERNAL ONLY, not part of public API) @param key The key you wish to test @return CRYPT_OK if successful */ int dh_check_pubkey(const dh_key *key) { void *p_minus1; ltc_mp_digit digit; int i, digit_count, bits_set = 0, err; LTC_ARGCHK(key != NULL); if ((err = mp_init(&p_minus1)) != CRYPT_OK) { return err; } /* avoid: y <= 1 OR y >= p-1 */ if ((err = mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) { goto error; } if (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT) { err = CRYPT_INVALID_ARG; goto error; } /* public key must have more than one bit set */ digit_count = mp_get_digit_count(key->y); for (i = 0; i < digit_count && bits_set < 2; i++) { digit = mp_get_digit(key->y, i); while (digit > 0) { if (digit & 1) bits_set++; digit >>= 1; } } if (bits_set > 1) { err = CRYPT_OK; } else { err = CRYPT_INVALID_ARG; } error: mp_clear(p_minus1); return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_export.c000066400000000000000000000034711464416617300233560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Export a DH key to a binary packet @param out [out] The destination for the key @param outlen [in/out] The max size and resulting size of the DH key @param type Which type of key (PK_PRIVATE or PK_PUBLIC) @param key The key you wish to export @return CRYPT_OK if successful */ int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key) { unsigned char flags[1]; int err; unsigned long version = 0; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); if (type == PK_PRIVATE) { /* export x - private key */ flags[0] = 1; err = der_encode_sequence_multi(out, outlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->prime, LTC_ASN1_INTEGER, 1UL, key->base, LTC_ASN1_INTEGER, 1UL, key->x, LTC_ASN1_EOL, 0UL, NULL); } else { /* export y - public key */ flags[0] = 0; err = der_encode_sequence_multi(out, outlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->prime, LTC_ASN1_INTEGER, 1UL, key->base, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_EOL, 0UL, NULL); } return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_export_key.c000066400000000000000000000016241464416617300242240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Binary export a DH key to a buffer @param out [out] The destination for the key @param outlen [in/out] The max size and resulting size of the DH key @param type Which type of key (PK_PRIVATE or PK_PUBLIC) @param key The key you wish to export @return CRYPT_OK if successful */ int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key) { unsigned long len; void *k; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); k = (type == PK_PRIVATE) ? key->x : key->y; len = mp_unsigned_bin_size(k); if (*outlen < len) { *outlen = len; return CRYPT_BUFFER_OVERFLOW; } *outlen = len; return mp_to_unsigned_bin(k, out); } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_free.c000066400000000000000000000006211464416617300227500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Free the allocated ram for a DH key @param key The key which you wish to free */ void dh_free(dh_key *key) { LTC_ARGCHKVD(key != NULL); mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, LTC_NULL); } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_generate_key.c000066400000000000000000000044111464416617300244720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH static int s_dh_groupsize_to_keysize(int groupsize) { /* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8 * We use "Estimate 2" to get an appropriate private key (exponent) size. */ if (groupsize <= 0) { return 0; } if (groupsize <= 192) { return 30; /* 1536-bit => key size 240-bit */ } if (groupsize <= 256) { return 40; /* 2048-bit => key size 320-bit */ } if (groupsize <= 384) { return 52; /* 3072-bit => key size 416-bit */ } if (groupsize <= 512) { return 60; /* 4096-bit => key size 480-bit */ } if (groupsize <= 768) { return 67; /* 6144-bit => key size 536-bit */ } if (groupsize <= 1024) { return 77; /* 8192-bit => key size 616-bit */ } return 0; } int dh_generate_key(prng_state *prng, int wprng, dh_key *key) { unsigned char *buf; unsigned long keysize; int err, max_iterations = LTC_PK_MAX_RETRIES; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* good prng? */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } keysize = s_dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime)); if (keysize == 0) { err = CRYPT_INVALID_KEYSIZE; goto freemp; } /* allocate buffer */ buf = XMALLOC(keysize); if (buf == NULL) { err = CRYPT_MEM; goto freemp; } key->type = PK_PRIVATE; do { /* make up random buf */ if (prng_descriptor[wprng]->read(buf, keysize, prng) != keysize) { err = CRYPT_ERROR_READPRNG; goto freebuf; } /* load the x value - private key */ if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { goto freebuf; } /* compute the y value - public key */ if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto freebuf; } err = dh_check_pubkey(key); } while (err != CRYPT_OK && max_iterations-- > 0); freebuf: zeromem(buf, keysize); XFREE(buf); freemp: if (err != CRYPT_OK) dh_free(key); return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_import.c000066400000000000000000000057241464416617300233520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Import a DH key from a binary packet @param in The packet to read @param inlen The length of the input packet @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) { unsigned char flags[1]; int err; unsigned long version; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); /* init */ if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } /* find out what type of key it is */ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_BIT_STRING, 1UL, &flags, LTC_ASN1_EOL, 0UL, NULL); if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { goto error; } if (version == 0) { if (flags[0] == 1) { key->type = PK_PRIVATE; if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->prime, LTC_ASN1_INTEGER, 1UL, key->base, LTC_ASN1_INTEGER, 1UL, key->x, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } /* compute public key: y = (base ^ x) mod prime */ if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto error; } } else if (flags[0] == 0) { key->type = PK_PUBLIC; if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->prime, LTC_ASN1_INTEGER, 1UL, key->base, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } } else { err = CRYPT_INVALID_PACKET; goto error; } } else { err = CRYPT_INVALID_PACKET; goto error; } /* check public key */ if ((err = dh_check_pubkey(key)) != CRYPT_OK) { goto error; } return CRYPT_OK; error: dh_free(key); return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c000066400000000000000000000104521464416617300236170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2001-2007, Tom St Denis * Copyright (c) 2014, STMicroelectronics International N.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "tomcrypt_private.h" #include /* * Make a DH key [private key pair] * @param prng An active PRNG state * @param wprng The index for the PRNG you desire to use * @param keysize The key size (octets) desired of the private key * @param q If not null, then the private key is in the range * [2, q-2] where q is called the subprime * @param xbits If not 0, then the private key has 'xbits' bits * @note The private key must always be less than p-1 * @param key [in/out] Where the newly created DH key will be stored * g and p are provided as input in the key * type, x and y are output of this function * @return CRYPT_OK if successful, note: on error all allocated memory will be * freed automatically. */ int dh_make_key(prng_state *prng, int wprng, void *q, int xbits, dh_key *key) { int err = 0; int key_size = 0; /* max key size, in bytes */ int key_size_p = 0; /* key size of p */ int key_size_q = 0; /* key size of p */ void *arg_mod = 0; uint8_t *buf = 0; /* intermediate buffer to have a raw random */ /* * Check the arguments */ LTC_ARGCHK(key != NULL); LTC_ARGCHK(key->base != NULL); LTC_ARGCHK(key->prime != NULL); err = prng_is_valid(wprng); if (err != CRYPT_OK) return err; /* * Set the key size and check constraints */ if (xbits) { LTC_ARGCHK((xbits % 8) == 0); key_size = xbits / 8; } key_size_p = mp_unsigned_bin_size(key->prime); if (q) key_size_q = mp_unsigned_bin_size(q); if (key_size) { /* check the constraints */ LTC_ARGCHK(key_size <= key_size_p); LTC_ARGCHK((q == NULL) || (key_size <= key_size_q)); } else { if (q) key_size = MIN(key_size_p, key_size_q); else key_size =key_size_p; } /* Set the argument we will make the modulo against to */ if ((q != NULL) && (key_size_q < key_size_p)) arg_mod = q; else arg_mod = key->prime; /* initialize the key */ key->x = NULL; key->y = NULL; err = mp_init_multi(&key->x, &key->y, NULL); if (err != CRYPT_OK) goto error; /* Initialize the buffer used to store the random number */ buf = XMALLOC(key_size); if (buf == NULL) { err = CRYPT_MEM; goto error; } /* generate the private key in a raw-buffer */ if (prng_descriptor[wprng]->read(buf, key_size, prng) != (unsigned long)key_size) { err = CRYPT_ERROR_READPRNG; goto error; } /* * Transform it as a Big Number compatible with p and q */ err = mp_read_unsigned_bin(key->y, buf, key_size); if (err != CRYPT_OK) goto error; err = mp_mod(key->y, arg_mod, key->x); if (err != CRYPT_OK) goto error; /* generate the public key key->y */ err = mp_exptmod(key->base, key->x, key->prime, key->y); if (err != CRYPT_OK) goto error; /* no error */ err = CRYPT_OK; error: if (err != CRYPT_OK) mp_clear_multi(key->x, key->y, NULL); if (buf) XFREE(buf); return err; } optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_set.c000066400000000000000000000063231464416617300226270ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Import DH key parts p and g from raw numbers @param p DH's p (prime) @param plen DH's p's length @param g DH's g (group) @param glen DH's g's length @param key [out] the destination for the imported key @return CRYPT_OK if successful */ int dh_set_pg(const unsigned char *p, unsigned long plen, const unsigned char *g, unsigned long glen, dh_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(p != NULL); LTC_ARGCHK(g != NULL); LTC_ARGCHK(ltc_mp.name != NULL); if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK) { goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dh_free(key); return err; } /** Import DH key parts p and g from built-in DH groups @param groupsize The size of the DH group to use @param key [out] Where the newly created DH key will be stored @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. */ int dh_set_pg_groupsize(int groupsize, dh_key *key) { int err, i; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); LTC_ARGCHK(groupsize > 0); for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++); if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE; if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dh_free(key); return err; } /** Import DH public or private key part from raw numbers NB: The p & g parts must be set beforehand @param in The key-part to import, either public or private. @param inlen The key-part's length @param type Which type of key (PK_PRIVATE or PK_PUBLIC) @param key [out] the destination for the imported key @return CRYPT_OK if successful */ int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); if (type == PK_PRIVATE) { key->type = PK_PRIVATE; if ((err = mp_read_unsigned_bin(key->x, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto LBL_ERR; } } else { key->type = PK_PUBLIC; if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } } /* check public key */ if ((err = dh_check_pubkey(key)) != CRYPT_OK) { goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dh_free(key); return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c000066400000000000000000000024471464416617300250140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Import DH key parts p and g from dhparam dhparam data: openssl dhparam -outform DER -out dhparam.der 2048 @param dhparam The DH param DER encoded data @param dhparamlen The length of dhparam data @param key [out] Where the newly created DH key will be stored @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. */ int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); LTC_ARGCHK(dhparam != NULL); LTC_ARGCHK(dhparamlen > 0); if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } if ((err = der_decode_sequence_multi(dhparam, dhparamlen, LTC_ASN1_INTEGER, 1UL, key->prime, LTC_ASN1_INTEGER, 1UL, key->base, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dh_free(key); return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dh/dh_shared_secret.c000066400000000000000000000035271464416617300246520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDH /** Create a DH shared secret. @param private_key The private DH key in the pair @param public_key The public DH key in the pair @param out [out] The destination of the shared data @param outlen [in/out] The max size and resulting size of the shared data. @return CRYPT_OK if successful */ int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, unsigned char *out, unsigned long *outlen) { void *tmp; unsigned long x; int err; LTC_ARGCHK(private_key != NULL); LTC_ARGCHK(public_key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* types valid? */ if (private_key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* same DH group? */ if (mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } if (mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } /* init big numbers */ if ((err = mp_init(&tmp)) != CRYPT_OK) { return err; } /* check public key */ if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) { goto error; } /* compute tmp = y^x mod p */ if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) { goto error; } /* enough space for output? */ x = (unsigned long)mp_unsigned_bin_size(tmp); if (*outlen < x) { *outlen = x; err = CRYPT_BUFFER_OVERFLOW; goto error; } if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { goto error; } *outlen = x; err = CRYPT_OK; error: mp_clear(tmp); return err; } #endif /* LTC_MDH */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/000077500000000000000000000000001464416617300213655ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c000066400000000000000000000062701464416617300247070ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_decrypt_key.c DSA Crypto, Tom St Denis */ #ifdef LTC_MDSA /** Decrypt an DSA encrypted key @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext @param key The corresponding private DSA key @return CRYPT_OK if successful */ int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const dsa_key *key) { unsigned char *skey, *expt; void *g_pub; unsigned long x, y; unsigned long hashOID[32] = { 0 }; int hash, err; ltc_asn1_list decode[3]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* right key type? */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* decode to find out hash */ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); err = der_decode_sequence(in, inlen, decode, 1); if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { return err; } hash = find_hash_oid(hashOID, decode[0].size); if (hash_is_valid(hash) != CRYPT_OK) { return CRYPT_INVALID_PACKET; } /* we now have the hash! */ if ((err = mp_init(&g_pub)) != CRYPT_OK) { return err; } /* allocate memory */ expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); skey = XMALLOC(MAXBLOCKSIZE); if (expt == NULL || skey == NULL) { if (expt != NULL) { XFREE(expt); } if (skey != NULL) { XFREE(skey); } mp_clear(g_pub); return CRYPT_MEM; } LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL); LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); /* read the structure in now */ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { goto LBL_ERR; } /* make shared key */ x = mp_unsigned_bin_size(key->p) + 1; if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) { goto LBL_ERR; } y = mp_unsigned_bin_size(key->p) + 1; y = MIN(y, MAXBLOCKSIZE); if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) { goto LBL_ERR; } /* ensure the hash of the shared secret is at least as big as the encrypt itself */ if (decode[2].size > y) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* avoid buffer overflow */ if (*outlen < decode[2].size) { *outlen = decode[2].size; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* Decrypt the key */ for (x = 0; x < decode[2].size; x++) { out[x] = expt[x] ^ skey[x]; } *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(expt, mp_unsigned_bin_size(key->p) + 1); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(expt); XFREE(skey); mp_clear(g_pub); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c000066400000000000000000000067271464416617300247300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_encrypt_key.c DSA Crypto, Tom St Denis */ #ifdef LTC_MDSA /** Encrypt a symmetric key with DSA @param in The symmetric key you want to encrypt @param inlen The length of the key to encrypt (octets) @param out [out] The destination for the ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param prng An active PRNG state @param wprng The index of the PRNG you wish to use @param hash The index of the hash you want to use @param key The DSA key you want to encrypt to @return CRYPT_OK if successful */ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, const dsa_key *key) { unsigned char *expt, *skey; void *g_pub, *g_priv; unsigned long x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* check that wprng/cipher/hash are not invalid */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (inlen > hash_descriptor[hash]->hashsize) { return CRYPT_INVALID_HASH; } /* make a random key and export the public copy */ if ((err = mp_init_multi(&g_pub, &g_priv, LTC_NULL)) != CRYPT_OK) { return err; } expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); skey = XMALLOC(MAXBLOCKSIZE); if (expt == NULL || skey == NULL) { if (expt != NULL) { XFREE(expt); } if (skey != NULL) { XFREE(skey); } mp_clear_multi(g_pub, g_priv, LTC_NULL); return CRYPT_MEM; } /* make a random g_priv, g_pub = g^x pair private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) { goto LBL_ERR; } /* compute y */ if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) { goto LBL_ERR; } /* make random key */ x = mp_unsigned_bin_size(key->p) + 1; if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) { goto LBL_ERR; } y = MAXBLOCKSIZE; if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) { goto LBL_ERR; } /* Encrypt key */ for (x = 0; x < inlen; x++) { skey[x] ^= in[x]; } err = der_encode_sequence_multi(out, outlen, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash]->OIDlen, hash_descriptor[hash]->OID, LTC_ASN1_INTEGER, 1UL, g_pub, LTC_ASN1_OCTET_STRING, inlen, skey, LTC_ASN1_EOL, 0UL, NULL); LBL_ERR: #ifdef LTC_CLEAN_STACK /* clean up */ zeromem(expt, mp_unsigned_bin_size(key->p) + 1); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(skey); XFREE(expt); mp_clear_multi(g_pub, g_priv, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_export.c000066400000000000000000000070401464416617300237020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_export.c DSA implementation, export key, Tom St Denis */ #ifdef LTC_MDSA /** Export a DSA key to a binary packet @param out [out] Where to store the packet @param outlen [in/out] The max size and resulting size of the packet @param type The type of key to export (PK_PRIVATE or PK_PUBLIC) @param key The key to export @return CRYPT_OK if successful */ int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key) { unsigned long zero=0; unsigned char flags[1]; int err, std; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); std = type & PK_STD; type &= ~PK_STD; if (type == PK_PRIVATE && key->type != PK_PRIVATE) { return CRYPT_PK_TYPE_MISMATCH; } if (type == PK_PRIVATE) { if (std) { return der_encode_sequence_multi(out, outlen, LTC_ASN1_SHORT_INTEGER, 1UL, &zero, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_INTEGER, 1UL, key->x, LTC_ASN1_EOL, 0UL, NULL); } flags[0] = 1; return der_encode_sequence_multi(out, outlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_INTEGER, 1UL, key->x, LTC_ASN1_EOL, 0UL, NULL); } if (type == PK_PUBLIC) { if (std) { unsigned long tmplen = (unsigned long)(mp_count_bits(key->y) / 8) + 8; unsigned char* tmp = XMALLOC(tmplen); ltc_asn1_list int_list[3]; if (tmp == NULL) { return CRYPT_MEM; } err = der_encode_integer(key->y, tmp, &tmplen); if (err != CRYPT_OK) { goto error; } LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL); LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL); LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL); err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp, tmplen, LTC_ASN1_SEQUENCE, int_list, sizeof(int_list) / sizeof(int_list[0])); error: XFREE(tmp); return err; } flags[0] = 0; return der_encode_sequence_multi(out, outlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_EOL, 0UL, NULL); } return CRYPT_INVALID_ARG; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_free.c000066400000000000000000000007371464416617300233100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_free.c DSA implementation, free a DSA key, Tom St Denis */ #ifdef LTC_MDSA /** Free a DSA key @param key The key to free from memory */ void dsa_free(dsa_key *key) { LTC_ARGCHKVD(key != NULL); mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, LTC_NULL); key->type = key->qord = 0; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_key.c000066400000000000000000000020551464416617300250240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_make_key.c DSA implementation, generate a DSA key */ #ifdef LTC_MDSA /** Create a DSA key @param prng An active PRNG state @param wprng The index of the PRNG desired @param key [in/out] Where to store the created key @return CRYPT_OK if successful. */ int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* so now we have our DH structure, generator g, order q, modulus p Now we need a random exponent [mod q] and it's power g^x mod p */ /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; } if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; } key->type = PK_PRIVATE; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c000066400000000000000000000236541464416617300250330ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_generate_pqg.c DSA implementation - generate DSA parameters p, q & g */ #ifdef LTC_MDSA /** Create DSA parameters (INTERNAL ONLY, not part of public API) @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param p [out] bignum where generated 'p' is stored (must be initialized by caller) @param q [out] bignum where generated 'q' is stored (must be initialized by caller) @param g [out] bignum where generated 'g' is stored (must be initialized by caller) @return CRYPT_OK if successful, upon error this function will free all allocated memory */ static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) { unsigned long L, N, n, outbytes, seedbytes, counter, j, i; int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; const char *accepted_hashes[] = { "sha3-512", "sha512", "sha3-384", "sha384", "sha3-256", "sha256" }; /* check size */ if (group_size > LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size || modulus_size > LTC_MDSA_MAX_MODULUS) { return CRYPT_INVALID_ARG; } /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function * * L = The desired length of the prime p (in bits e.g. L = 1024) * N = The desired length of the prime q (in bits e.g. N = 160) * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N * outlen = The bit length of Hash function * * 1. Check that the (L, N) * 2. If (seedlen = 2^(L-1)) { * Test whether or not p is prime as specified in Appendix C.3. * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter * } * offset = offset + n + 1 Comment: Increment offset * } */ seedbytes = group_size; L = (unsigned long)modulus_size * 8; N = (unsigned long)group_size * 8; /* XXX-TODO no Lucas test */ #ifdef LTC_MPI_HAS_LUCAS_TEST /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ mr_tests_p = (L <= 2048) ? 3 : 2; if (N <= 160) { mr_tests_q = 19; } else if (N <= 224) { mr_tests_q = 24; } else { mr_tests_q = 27; } #else /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ if (L <= 1024) { mr_tests_p = 40; } else if (L <= 2048) { mr_tests_p = 56; } else { mr_tests_p = 64; } if (N <= 160) { mr_tests_q = 40; } else if (N <= 224) { mr_tests_q = 56; } else { mr_tests_q = 64; } #endif hash = -1; for (i = 0; i < sizeof(accepted_hashes)/sizeof(accepted_hashes[0]); ++i) { hash = find_hash(accepted_hashes[i]); if (hash != -1) break; } if (hash == -1) { return CRYPT_INVALID_ARG; /* no appropriate hash function found */ } if (N > hash_descriptor[hash]->hashsize * 8) { return CRYPT_INVALID_ARG; /* group_size too big */ } if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } outbytes = hash_descriptor[hash]->hashsize; n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, LTC_NULL); if (err != CRYPT_OK) { goto cleanup1; } if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } /* t2L1 = 2^(L-1) */ if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } /* t2N1 = 2^(N-1) */ if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } /* t2seedlen = 2^seedlen */ for(found_p=0; !found_p;) { /* q */ for(found_q=0; !found_q;) { if (prng_descriptor[wprng]->read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } i = outbytes; if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } if (!mp_isodd(q)) mp_add_d(q, 1, q); if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } if (res == LTC_MP_YES) found_q = 1; } /* p */ if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } for(counter=0; counter < 4*L && !found_p; counter++) { for(j=0; j<=n; j++) { if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } /* seedinc = (seedinc+1) % 2^seed_bitlen */ if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } zeromem(sbuf, seedbytes); if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } i = outbytes; err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); if (err != CRYPT_OK) { goto cleanup; } } if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } if (mp_cmp(p, t2L1) != LTC_MP_LT) { /* p >= 2^(L-1) */ if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } if (res == LTC_MP_YES) { found_p = 1; } } } } /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g * 1. e = (p - 1)/q * 2. h = any integer satisfying: 1 < h < (p - 1) * h could be obtained from a random number generator or from a counter that changes after each use * 3. g = h^e mod p * 4. if (g == 1), then go to step 2. * */ if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } /* e = (p - 1)/q */ i = mp_count_bits(p); do { do { if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } /* h is randon and 1 < h < (p-1) */ if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } } while (mp_cmp_d(g, 1) == LTC_MP_EQ); err = CRYPT_OK; cleanup: mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, LTC_NULL); cleanup1: XFREE(sbuf); cleanup2: XFREE(wbuf); cleanup3: return err; } /** Generate DSA parameters p, q & g @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param key [out] Where to store the created key @return CRYPT_OK if successful. */ int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init mp_ints */ if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL)) != CRYPT_OK) { return err; } /* generate params */ err = s_dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); if (err != CRYPT_OK) { goto cleanup; } key->qord = group_size; return CRYPT_OK; cleanup: dsa_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c000066400000000000000000000112431464416617300236730ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_import.c DSA implementation, import a DSA key, Tom St Denis */ #ifdef LTC_MDSA /** Import a DSA key @param in The binary packet to import from @param inlen The length of the binary packet @param key [out] Where to store the imported key @return CRYPT_OK if successful, upon error this function will free all allocated memory */ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) { int err, stat; unsigned long zero = 0, len; unsigned char* tmpbuf = NULL; unsigned char flags[1]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL) != CRYPT_OK) { return CRYPT_MEM; } /* try to match the old libtomcrypt format */ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_EOL, 0UL, NULL); if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) { /* private key */ if (flags[0] == 1) { if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_INTEGER, 1UL, key->x, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PRIVATE; goto LBL_OK; } /* public key */ else if (flags[0] == 0) { if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PUBLIC; goto LBL_OK; } else { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } } /* get key type */ if (der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &zero, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_INTEGER, 1UL, key->y, LTC_ASN1_INTEGER, 1UL, key->x, LTC_ASN1_EOL, 0UL, NULL) == CRYPT_OK) { key->type = PK_PRIVATE; } else { /* public */ ltc_asn1_list params[3]; unsigned long tmpbuf_len = inlen; LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); tmpbuf = XCALLOC(1, tmpbuf_len); if (tmpbuf == NULL) { err = CRYPT_MEM; goto LBL_ERR; } len = 3; err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_DSA, tmpbuf, &tmpbuf_len, LTC_ASN1_SEQUENCE, params, &len); if (err != CRYPT_OK) { XFREE(tmpbuf); goto LBL_ERR; } if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { XFREE(tmpbuf); goto LBL_ERR; } XFREE(tmpbuf); key->type = PK_PUBLIC; } LBL_OK: key->qord = mp_unsigned_bin_size(key->q); /* quick p, q, g validation, without primality testing */ if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } if (stat == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* validate x, y */ if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } if (stat == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dsa_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_make_key.c000066400000000000000000000016011464416617300241430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_make_key.c DSA implementation, generate a DSA key */ #ifdef LTC_MDSA /** Old-style creation of a DSA key @param prng An active PRNG state @param wprng The index of the PRNG desired @param group_size Size of the multiplicative group (octets) @param modulus_size Size of the modulus (octets) @param key [out] Where to store the created key @return CRYPT_OK if successful. */ int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) { int err; if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; } if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_set.c000066400000000000000000000061661464416617300231640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDSA /** Import DSA's p, q & g from raw numbers @param p DSA's p in binary representation @param plen The length of p @param q DSA's q in binary representation @param qlen The length of q @param g DSA's g in binary representation @param glen The length of g @param key [out] the destination for the imported key @return CRYPT_OK if successful. */ int dsa_set_pqg(const unsigned char *p, unsigned long plen, const unsigned char *q, unsigned long qlen, const unsigned char *g, unsigned long glen, dsa_key *key) { int err, stat; LTC_ARGCHK(p != NULL); LTC_ARGCHK(q != NULL); LTC_ARGCHK(g != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); if (err != CRYPT_OK) return err; if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } key->qord = mp_unsigned_bin_size(key->q); /* do only a quick validation, without primality testing */ if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } if (stat == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dsa_free(key); return err; } /** Import DSA public or private key-part from raw numbers NB: The p, q & g parts must be set beforehand @param in The key-part to import, either public or private. @param inlen The key-part's length @param type Which type of key (PK_PRIVATE or PK_PUBLIC) @param key [out] the destination for the imported key @return CRYPT_OK if successful. */ int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key) { int err, stat = 0; LTC_ARGCHK(key != NULL); LTC_ARGCHK(key->x != NULL); LTC_ARGCHK(key->y != NULL); LTC_ARGCHK(key->p != NULL); LTC_ARGCHK(key->g != NULL); LTC_ARGCHK(key->q != NULL); LTC_ARGCHK(ltc_mp.name != NULL); if (type == PK_PRIVATE) { key->type = PK_PRIVATE; if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; } } else { key->type = PK_PUBLIC; if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } } if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } if (stat == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dsa_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c000066400000000000000000000030731464416617300256750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MDSA /** Import DSA's p, q & g from dsaparam dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048 @param dsaparam The DSA param DER encoded data @param dsaparamlen The length of dhparam data @param key [out] the destination for the imported key @return CRYPT_OK if successful. */ int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key) { int err, stat; LTC_ARGCHK(dsaparam != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); if (err != CRYPT_OK) return err; if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->g, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } key->qord = mp_unsigned_bin_size(key->q); /* quick p, q, g validation, without primality testing */ if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } if (stat == 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } return CRYPT_OK; LBL_ERR: dsa_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_shared_secret.c000066400000000000000000000031721464416617300251760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_shared_secret.c DSA Crypto, Tom St Denis */ #ifdef LTC_MDSA /** Create a DSA shared secret between two keys @param private_key The private DSA key (the exponent) @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt) @param public_key The public key @param out [out] Destination of the shared secret @param outlen [in/out] The max size and resulting size of the shared secret @return CRYPT_OK if successful */ int dsa_shared_secret(void *private_key, void *base, const dsa_key *public_key, unsigned char *out, unsigned long *outlen) { unsigned long x; void *res; int err; LTC_ARGCHK(private_key != NULL); LTC_ARGCHK(public_key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* make new point */ if ((err = mp_init(&res)) != CRYPT_OK) { return err; } if ((err = mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) { mp_clear(res); return err; } x = (unsigned long)mp_unsigned_bin_size(res); if (*outlen < x) { *outlen = x; err = CRYPT_BUFFER_OVERFLOW; goto done; } zeromem(out, x); if ((err = mp_to_unsigned_bin(res, out + (x - mp_unsigned_bin_size(res)))) != CRYPT_OK) { goto done; } err = CRYPT_OK; *outlen = x; done: mp_clear(res); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_sign_hash.c000066400000000000000000000111601464416617300243220ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_sign_hash.c DSA implementation, sign a hash, Tom St Denis */ #ifdef LTC_MDSA /** Sign a hash with DSA @param in The hash to sign @param inlen The length of the hash to sign @param r The "r" integer of the signature (caller must initialize with mp_init() first) @param s The "s" integer of the signature (caller must initialize with mp_init() first) @param prng An active PRNG state @param wprng The index of the PRNG desired @param key A private DSA key @return CRYPT_OK if successful */ int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, void *r, void *s, prng_state *prng, int wprng, const dsa_key *key) { void *k, *kinv, *tmp; unsigned char *buf; int err, qbits; LTC_ARGCHK(in != NULL); LTC_ARGCHK(r != NULL); LTC_ARGCHK(s != NULL); LTC_ARGCHK(key != NULL); if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* check group order size */ if (key->qord >= LTC_MDSA_MAX_GROUP) { return CRYPT_INVALID_ARG; } buf = XMALLOC(LTC_MDSA_MAX_GROUP); if (buf == NULL) { return CRYPT_MEM; } /* Init our temps */ if ((err = mp_init_multi(&k, &kinv, &tmp, LTC_NULL)) != CRYPT_OK) { goto ERRBUF; } qbits = mp_count_bits(key->q); retry: do { /* gen random k */ if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; } /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */ if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; } /* test gcd */ if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; } } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ); /* now find 1/k mod q */ if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; } /* now find r = g^k mod p mod q */ if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; } if ((err = mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; } if (mp_iszero(r) == LTC_MP_YES) { goto retry; } /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/ inlen = MIN(inlen, (unsigned long)(key->qord)); /* now find s = (in + xr)/k mod q */ if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; } if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; } if ((err = mp_add(s, tmp, s)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; } if (mp_iszero(s) == LTC_MP_YES) { goto retry; } err = CRYPT_OK; error: mp_clear_multi(k, kinv, tmp, LTC_NULL); ERRBUF: #ifdef LTC_CLEAN_STACK zeromem(buf, LTC_MDSA_MAX_GROUP); #endif XFREE(buf); return err; } /** Sign a hash with DSA @param in The hash to sign @param inlen The length of the hash to sign @param out [out] Where to store the signature @param outlen [in/out] The max size and resulting size of the signature @param prng An active PRNG state @param wprng The index of the PRNG desired @param key A private DSA key @return CRYPT_OK if successful */ int dsa_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, const dsa_key *key) { void *r, *s; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); if (mp_init_multi(&r, &s, LTC_NULL) != CRYPT_OK) { return CRYPT_MEM; } if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) { goto error; } err = der_encode_sequence_multi(out, outlen, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, NULL); error: mp_clear_multi(r, s, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_hash.c000066400000000000000000000100621464416617300246660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_verify_hash.c DSA implementation, verify a signature, Tom St Denis */ #ifdef LTC_MDSA /** Verify a DSA signature @param r DSA "r" parameter @param s DSA "s" parameter @param hash The hash that was signed @param hashlen The length of the hash that was signed @param stat [out] The result of the signature verification, 1==valid, 0==invalid @param key The corresponding public DSA key @return CRYPT_OK if successful (even if the signature is invalid) */ int dsa_verify_hash_raw( void *r, void *s, const unsigned char *hash, unsigned long hashlen, int *stat, const dsa_key *key) { void *w, *v, *u1, *u2; int err; LTC_ARGCHK(r != NULL); LTC_ARGCHK(s != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); /* default to invalid signature */ *stat = 0; /* init our variables */ if ((err = mp_init_multi(&w, &v, &u1, &u2, LTC_NULL)) != CRYPT_OK) { return err; } /* neither r or s can be null or >q*/ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) { err = CRYPT_INVALID_PACKET; goto error; } /* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */ hashlen = MIN(hashlen, (unsigned long)(key->qord)); /* w = 1/s mod q */ if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; } /* u1 = m * w mod q */ if ((err = mp_read_unsigned_bin(u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; } /* u2 = r*w mod q */ if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; } /* v = g^u1 * y^u2 mod p mod q */ if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; } if ((err = mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK) { goto error; } if ((err = mp_mod(v, key->q, v)) != CRYPT_OK) { goto error; } /* if r = v then we're set */ if (mp_cmp(r, v) == LTC_MP_EQ) { *stat = 1; } err = CRYPT_OK; error: mp_clear_multi(w, v, u1, u2, LTC_NULL); return err; } /** Verify a DSA signature @param sig The signature @param siglen The length of the signature (octets) @param hash The hash that was signed @param hashlen The length of the hash that was signed @param stat [out] The result of the signature verification, 1==valid, 0==invalid @param key The corresponding public DSA key @return CRYPT_OK if successful (even if the signature is invalid) */ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, const dsa_key *key) { int err; void *r, *s; ltc_asn1_list sig_seq[2]; unsigned long reallen = 0; LTC_ARGCHK(stat != NULL); *stat = 0; /* must be set before the first return */ if ((err = mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) { return err; } LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL); LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL); err = der_decode_sequence_strict(sig, siglen, sig_seq, 2); if (err != CRYPT_OK) { goto LBL_ERR; } err = der_length_sequence(sig_seq, 2, &reallen); if (err != CRYPT_OK || reallen != siglen) { goto LBL_ERR; } /* do the op */ err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key); LBL_ERR: mp_clear_multi(r, s, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/dsa/dsa_verify_key.c000066400000000000000000000112701464416617300245350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file dsa_verify_key.c DSA implementation, verify a key, Tom St Denis */ #ifdef LTC_MDSA /** Validate a DSA key Yeah, this function should've been called dsa_validate_key() in the first place and for compat-reasons we keep it as it was (for now). @param key The key to validate @param stat [out] Result of test, 1==valid, 0==invalid @return CRYPT_OK if successful */ int dsa_verify_key(const dsa_key *key, int *stat) { int err; err = dsa_int_validate_primes(key, stat); if (err != CRYPT_OK || *stat == 0) return err; err = dsa_int_validate_pqg(key, stat); if (err != CRYPT_OK || *stat == 0) return err; return dsa_int_validate_xy(key, stat); } /** Non-complex part (no primality testing) of the validation of DSA params (p, q, g) @param key The key to validate @param stat [out] Result of test, 1==valid, 0==invalid @return CRYPT_OK if successful */ int dsa_int_validate_pqg(const dsa_key *key, int *stat) { void *tmp1, *tmp2; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); *stat = 0; /* check q-order */ if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) { return CRYPT_OK; } /* FIPS 186-4 chapter 4.1: 1 < g < p */ if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) { return CRYPT_OK; } if ((err = mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */ if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; } if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; } if (mp_iszero(tmp2) != LTC_MP_YES) { err = CRYPT_OK; goto error; } /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1 */ if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; } if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) { err = CRYPT_OK; goto error; } err = CRYPT_OK; *stat = 1; error: mp_clear_multi(tmp2, tmp1, LTC_NULL); return err; } /** Primality testing of DSA params p and q @param key The key to validate @param stat [out] Result of test, 1==valid, 0==invalid @return CRYPT_OK if successful */ int dsa_int_validate_primes(const dsa_key *key, int *stat) { int err, res; *stat = 0; LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); /* key->q prime? */ if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { return err; } if (res == LTC_MP_NO) { return CRYPT_OK; } /* key->p prime? */ if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { return err; } if (res == LTC_MP_NO) { return CRYPT_OK; } *stat = 1; return CRYPT_OK; } /** Validation of a DSA key (x and y values) @param key The key to validate @param stat [out] Result of test, 1==valid, 0==invalid @return CRYPT_OK if successful */ int dsa_int_validate_xy(const dsa_key *key, int *stat) { void *tmp; int err; *stat = 0; LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); /* 1 < y < p-1 */ if ((err = mp_init(&tmp)) != CRYPT_OK) { return err; } if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { goto error; } if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) { err = CRYPT_OK; goto error; } if (key->type == PK_PRIVATE) { /* FIPS 186-4 chapter 4.1: 0 < x < q */ if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) { err = CRYPT_OK; goto error; } /* FIPS 186-4 chapter 4.1: y = g^x mod p */ if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) { goto error; } if (mp_cmp(tmp, key->y) != LTC_MP_EQ) { err = CRYPT_OK; goto error; } } else { /* with just a public key we cannot test y = g^x mod p therefore we * only test that y^q mod p = 1, which makes sure y is in g^x mod p */ if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { goto error; } if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { err = CRYPT_OK; goto error; } } err = CRYPT_OK; *stat = 1; error: mp_clear(tmp); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ec25519/000077500000000000000000000000001464416617300216135ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c000066400000000000000000000017161464416617300252370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ec25519_crypto_ctx.c curve25519 crypto context helper */ #ifdef LTC_CURVE25519 int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen) { unsigned char *buf = out; const char *prefix = "SigEd25519 no Ed25519 collisions"; const unsigned long prefix_len = XSTRLEN(prefix); const unsigned char ctxlen8 = (unsigned char)ctxlen; if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG; if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW; XMEMCPY(buf, prefix, prefix_len); buf += prefix_len; XMEMCPY(buf, &flag, 1); buf++; XMEMCPY(buf, &ctxlen8, 1); buf++; if (ctxlen > 0u) { LTC_ARGCHK(ctx != NULL); XMEMCPY(buf, ctx, ctxlen); buf += ctxlen; } *outlen = buf-out; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ec25519/ec25519_export.c000066400000000000000000000056011464416617300243570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ec25519_export.c Generic export of a Curve/Ed25519 key to a binary packet, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Generic export of a Curve/Ed25519 key to a binary packet @param out [out] The destination for the key @param outlen [in/out] The max size and resulting size of the Ed25519 key @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) @param key The key you wish to export @return CRYPT_OK if successful */ int ec25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key) { int err, std; const char* OID; unsigned long oid[16], oidlen; ltc_asn1_list alg_id[1]; unsigned char private_key[34]; unsigned long version, private_key_len = sizeof(private_key); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); std = which & PK_STD; which &= ~PK_STD; if (which == PK_PRIVATE) { if(key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; if (std == PK_STD) { if ((err = pk_get_oid(key->algo, &OID)) != CRYPT_OK) { return err; } oidlen = sizeof(oid)/sizeof(oid[0]); if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { return err; } LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); /* encode private key as PKCS#8 */ if ((err = der_encode_octet_string(key->priv, 32uL, private_key, &private_key_len)) != CRYPT_OK) { return err; } version = 0; err = der_encode_sequence_multi(out, outlen, LTC_ASN1_SHORT_INTEGER, 1uL, &version, LTC_ASN1_SEQUENCE, 1uL, alg_id, LTC_ASN1_OCTET_STRING, private_key_len, private_key, LTC_ASN1_EOL, 0uL, NULL); } else { if (*outlen < sizeof(key->priv)) { err = CRYPT_BUFFER_OVERFLOW; } else { XMEMCPY(out, key->priv, sizeof(key->priv)); err = CRYPT_OK; } *outlen = sizeof(key->priv); } } else { if (std == PK_STD) { /* encode public key as SubjectPublicKeyInfo */ err = x509_encode_subject_public_key_info(out, outlen, key->algo, key->pub, 32uL, LTC_ASN1_EOL, NULL, 0); } else { if (*outlen < sizeof(key->pub)) { err = CRYPT_BUFFER_OVERFLOW; } else { XMEMCPY(out, key->pub, sizeof(key->pub)); err = CRYPT_OK; } *outlen = sizeof(key->pub); } } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c000066400000000000000000000055741464416617300254710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ec25519_import_pkcs8.c Generic import of a Curve/Ed25519 private key in PKCS#8 format, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Generic import of a Curve/Ed25519 private key in PKCS#8 format @param in The DER-encoded PKCS#8-formatted private key @param inlen The length of the input data @param passwd The password to decrypt the private key @param passwdlen Password's length (octets) @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, enum ltc_oid_id id, sk_to_pk fp, curve25519_key *key) { int err; ltc_asn1_list *l = NULL; const char *oid; ltc_asn1_list alg_id[1]; unsigned char private_key[34]; unsigned long version, key_len; unsigned long tmpoid[16]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(fp != NULL); if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) { LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0])); key_len = sizeof(private_key); if ((err = der_decode_sequence_multi(l->data, l->size, LTC_ASN1_SHORT_INTEGER, 1uL, &version, LTC_ASN1_SEQUENCE, 1uL, alg_id, LTC_ASN1_OCTET_STRING, key_len, private_key, LTC_ASN1_EOL, 0uL, NULL)) != CRYPT_OK) { /* If there are attributes added after the private_key it is tagged with version 1 and * we get an 'input too long' error but the rest is already decoded and can be * handled the same as for version 0 */ if ((err == CRYPT_INPUT_TOO_LONG) && (version == 1)) { version = 0; } else { goto out; } } if ((err = pk_get_oid(id, &oid)) != CRYPT_OK) { goto out; } if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { goto out; } if (version == 0) { key_len = sizeof(key->priv); if ((err = der_decode_octet_string(private_key, sizeof(private_key), key->priv, &key_len)) == CRYPT_OK) { fp(key->pub, key->priv); key->type = PK_PRIVATE; key->algo = id; } } else { err = CRYPT_PK_INVALID_TYPE; } } out: if (l) der_free_sequence_flexi(l); #ifdef LTC_CLEAN_STACK zeromem(private_key, sizeof(private_key)); #endif return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c000066400000000000000000000217631464416617300237560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /* automatically generated file, do not edit */ #define FOR(i,n) for (i = 0;i < n;++i) #define sv static void typedef unsigned char u8; typedef ulong32 u32; typedef ulong64 u64; typedef long64 i64; typedef i64 gf[16]; static const u8 nine[32] = {9}; static const gf gf0, gf1 = {1}, gf121665 = {0xDB41,1}, D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; static int vn(const u8 *x,const u8 *y,int n) { int i; u32 d = 0; FOR(i,n) d |= x[i]^y[i]; return (1 & ((d - 1) >> 8)) - 1; } static int tweetnacl_crypto_verify_32(const u8 *x,const u8 *y) { return vn(x,y,32); } sv set25519(gf r, const gf a) { int i; FOR(i,16) r[i]=a[i]; } sv car25519(gf o) { int i; i64 c; FOR(i,16) { o[i]+=(1LL<<16); c=o[i]>>16; o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); o[i]-=c<<16; } } sv sel25519(gf p,gf q,int b) { i64 t,i,c=~(b-1); FOR(i,16) { t= c&(p[i]^q[i]); p[i]^=t; q[i]^=t; } } sv pack25519(u8 *o,const gf n) { int i,j,b; gf m,t; FOR(i,16) t[i]=n[i]; car25519(t); car25519(t); car25519(t); FOR(j,2) { m[0]=t[0]-0xffed; for(i=1;i<15;i++) { m[i]=t[i]-0xffff-((m[i-1]>>16)&1); m[i-1]&=0xffff; } m[15]=t[15]-0x7fff-((m[14]>>16)&1); b=(m[15]>>16)&1; m[14]&=0xffff; sel25519(t,m,1-b); } FOR(i,16) { o[2*i]=t[i]&0xff; o[2*i+1]=t[i]>>8; } } static int neq25519(const gf a, const gf b) { u8 c[32],d[32]; pack25519(c,a); pack25519(d,b); return tweetnacl_crypto_verify_32(c,d); } static u8 par25519(const gf a) { u8 d[32]; pack25519(d,a); return d[0]&1; } sv unpack25519(gf o, const u8 *n) { int i; FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); o[15]&=0x7fff; } sv A(gf o,const gf a,const gf b) { int i; FOR(i,16) o[i]=a[i]+b[i]; } sv Z(gf o,const gf a,const gf b) { int i; FOR(i,16) o[i]=a[i]-b[i]; } sv M(gf o,const gf a,const gf b) { i64 i,j,t[31]; FOR(i,31) t[i]=0; FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; FOR(i,15) t[i]+=38*t[i+16]; FOR(i,16) o[i]=t[i]; car25519(o); car25519(o); } sv S(gf o,const gf a) { M(o,a,a); } sv inv25519(gf o,const gf i) { gf c; int a; FOR(a,16) c[a]=i[a]; for(a=253;a>=0;a--) { S(c,c); if(a!=2&&a!=4) M(c,c,i); } FOR(a,16) o[a]=c[a]; } sv pow2523(gf o,const gf i) { gf c; int a; FOR(a,16) c[a]=i[a]; for(a=250;a>=0;a--) { S(c,c); if(a!=1) M(c,c,i); } FOR(a,16) o[a]=c[a]; } int tweetnacl_crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) { u8 z[32]; i64 x[80],r,i; gf a,b,c,d,e,f; FOR(i,31) z[i]=n[i]; z[31]=(n[31]&127)|64; z[0]&=248; unpack25519(x,p); FOR(i,16) { b[i]=x[i]; d[i]=a[i]=c[i]=0; } a[0]=d[0]=1; for(i=254;i>=0;--i) { r=(z[i>>3]>>(i&7))&1; sel25519(a,b,r); sel25519(c,d,r); A(e,a,c); Z(a,a,c); A(c,b,d); Z(b,b,d); S(d,e); S(f,a); M(a,c,a); M(c,b,e); A(e,a,c); Z(a,a,c); S(b,a); Z(c,d,f); M(a,c,gf121665); A(a,a,d); M(c,c,a); M(a,d,f); M(d,b,x); S(b,e); sel25519(a,b,r); sel25519(c,d,r); } FOR(i,16) { x[i+16]=a[i]; x[i+32]=c[i]; x[i+48]=b[i]; x[i+64]=d[i]; } inv25519(x+32,x+32); M(x+16,x+16,x+32); pack25519(q,x+16); return 0; } int tweetnacl_crypto_scalarmult_base(u8 *q,const u8 *n) { return tweetnacl_crypto_scalarmult(q,n,nine); } static LTC_INLINE int tweetnacl_crypto_hash_ctx(u8 *out,const u8 *m,u64 n,const u8 *ctx,u32 cs) { unsigned long len = 64; int hash_idx = find_hash("sha512"); if (n > ULONG_MAX) return CRYPT_OVERFLOW; if(cs == 0) return hash_memory(hash_idx, m, n, out, &len); return hash_memory_multi(hash_idx, out, &len, ctx, cs, m, n, LTC_NULL); } static LTC_INLINE int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n) { return tweetnacl_crypto_hash_ctx(out, m, n, NULL, 0); } sv add(gf p[4],gf q[4]) { gf a,b,c,d,t,e,f,g,h; Z(a, p[1], p[0]); Z(t, q[1], q[0]); M(a, a, t); A(b, p[0], p[1]); A(t, q[0], q[1]); M(b, b, t); M(c, p[3], q[3]); M(c, c, D2); M(d, p[2], q[2]); A(d, d, d); Z(e, b, a); Z(f, d, c); A(g, d, c); A(h, b, a); M(p[0], e, f); M(p[1], h, g); M(p[2], g, f); M(p[3], e, h); } sv cswap(gf p[4],gf q[4],u8 b) { int i; FOR(i,4) sel25519(p[i],q[i],b); } sv pack(u8 *r,gf p[4]) { gf tx, ty, zi; inv25519(zi, p[2]); M(tx, p[0], zi); M(ty, p[1], zi); pack25519(r, ty); r[31] ^= par25519(tx) << 7; } sv scalarmult(gf p[4],gf q[4],const u8 *s) { int i; set25519(p[0],gf0); set25519(p[1],gf1); set25519(p[2],gf1); set25519(p[3],gf0); for (i = 255;i >= 0;--i) { u8 b = (s[i/8]>>(i&7))&1; cswap(p,q,b); add(q,p); add(p,p); cswap(p,q,b); } } sv scalarbase(gf p[4],const u8 *s) { gf q[4]; set25519(q[0],X); set25519(q[1],Y); set25519(q[2],gf1); M(q[3],X,Y); scalarmult(p,q,s); } int tweetnacl_crypto_sk_to_pk(u8 *pk, const u8 *sk) { u8 d[64]; gf p[4]; tweetnacl_crypto_hash(d, sk, 32); d[0] &= 248; d[31] &= 127; d[31] |= 64; scalarbase(p,d); pack(pk,p); return 0; } int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, u8 *pk, u8 *sk) { int err; /* randombytes(sk,32); */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (prng_descriptor[wprng]->read(sk,32, prng) != 32) { return CRYPT_ERROR_READPRNG; } if ((err = tweetnacl_crypto_sk_to_pk(pk, sk)) != CRYPT_OK) { return err; } /* FOR(i,32) sk[32 + i] = pk[i]; * we don't copy the pk in the sk */ return CRYPT_OK; } static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; sv modL(u8 *r,i64 x[64]) { i64 carry,i,j; for (i = 63;i >= 32;--i) { carry = 0; for (j = i - 32;j < i - 12;++j) { x[j] += carry - 16 * x[i] * L[j - (i - 32)]; carry = (x[j] + 128) >> 8; x[j] -= carry << 8; } x[j] += carry; x[i] = 0; } carry = 0; FOR(j,32) { x[j] += carry - (x[31] >> 4) * L[j]; carry = x[j] >> 8; x[j] &= 255; } FOR(j,32) x[j] -= carry * L[j]; FOR(i,32) { x[i+1] += x[i] >> 8; r[i] = x[i] & 255; } } sv reduce(u8 *r) { i64 x[64],i; FOR(i,64) x[i] = (u64) r[i]; FOR(i,64) r[i] = 0; modL(r,x); } int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk, const u8 *ctx, u64 cs) { u8 d[64],h[64],r[64]; i64 i,j,x[64]; gf p[4]; tweetnacl_crypto_hash(d, sk, 32); d[0] &= 248; d[31] &= 127; d[31] |= 64; *smlen = mlen+64; FOR(i,(i64)mlen) sm[64 + i] = m[i]; FOR(i,32) sm[32 + i] = d[32 + i]; tweetnacl_crypto_hash_ctx(r, sm+32, mlen+32,ctx,cs); reduce(r); scalarbase(p,r); pack(sm,p); FOR(i,32) sm[i+32] = pk[i]; tweetnacl_crypto_hash_ctx(h,sm,mlen + 64,ctx,cs); reduce(h); FOR(i,64) x[i] = 0; FOR(i,32) x[i] = (u64) r[i]; FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; modL(sm + 32,x); return 0; } static int unpackneg(gf r[4],const u8 p[32]) { gf t, chk, num, den, den2, den4, den6; set25519(r[2],gf1); unpack25519(r[1],p); S(num,r[1]); M(den,num,D); Z(num,num,r[2]); A(den,r[2],den); S(den2,den); S(den4,den2); M(den6,den4,den2); M(t,den6,num); M(t,t,den); pow2523(t,t); M(t,t,num); M(t,t,den); M(t,t,den); M(r[0],t,den); S(chk,r[0]); M(chk,chk,den); if (neq25519(chk, num)) M(r[0],r[0],I); S(chk,r[0]); M(chk,chk,den); if (neq25519(chk, num)) return -1; if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); M(r[3],r[0],r[1]); return 0; } int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *ctx,u64 cs,const u8 *pk) { u64 i; u8 s[32],t[32],h[64]; gf p[4],q[4]; *stat = 0; if (*mlen < smlen) return CRYPT_BUFFER_OVERFLOW; *mlen = -1; if (smlen < 64) return CRYPT_INVALID_ARG; if (unpackneg(q,pk)) return CRYPT_ERROR; XMEMMOVE(m,sm,smlen); XMEMMOVE(s,m + 32,32); XMEMMOVE(m + 32,pk,32); tweetnacl_crypto_hash_ctx(h,m,smlen,ctx,cs); reduce(h); scalarmult(p,q,h); scalarbase(q,s); add(p,q); pack(t,p); smlen -= 64; if (tweetnacl_crypto_verify_32(sm, t)) { FOR(i,smlen) m[i] = 0; zeromem(m, smlen); return CRYPT_OK; } *stat = 1; XMEMMOVE(m,m + 64,smlen); *mlen = smlen; return CRYPT_OK; } int tweetnacl_crypto_ph(u8 *out,const u8 *msg,u64 msglen) { return tweetnacl_crypto_hash(out, msg, msglen); } optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/000077500000000000000000000000001464416617300213505ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc.c000066400000000000000000000523571464416617300222620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /* This array holds the curve parameters. * Curves (prime field only) are taken from: * - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*) * - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*) * - ANS X9.62 (named: PRIMEP*) * - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*) */ const ltc_ecc_curve ltc_ecc_curves[] = { #ifdef LTC_ECC_SECP112R1 { /* prime */ "DB7C2ABF62E35E668076BEAD208B", /* A */ "DB7C2ABF62E35E668076BEAD2088", /* B */ "659EF8BA043916EEDE8911702B22", /* order */ "DB7C2ABF62E35E7628DFAC6561C5", /* Gx */ "09487239995A5EE76B55F9C2F098", /* Gy */ "A89CE5AF8724C0A23E0E0FF77500", /* cofactor */ 1, /* OID */ "1.3.132.0.6" }, #endif #ifdef LTC_ECC_SECP112R2 { /* prime */ "DB7C2ABF62E35E668076BEAD208B", /* A */ "6127C24C05F38A0AAAF65C0EF02C", /* B */ "51DEF1815DB5ED74FCC34C85D709", /* order */ "36DF0AAFD8B8D7597CA10520D04B", /* Gx */ "4BA30AB5E892B4E1649DD0928643", /* Gy */ "ADCD46F5882E3747DEF36E956E97", /* cofactor */ 4, /* OID */ "1.3.132.0.7" }, #endif #ifdef LTC_ECC_SECP128R1 { /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", /* B */ "E87579C11079F43DD824993C2CEE5ED3", /* order */ "FFFFFFFE0000000075A30D1B9038A115", /* Gx */ "161FF7528B899B2D0C28607CA52C5B86", /* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83", /* cofactor */ 1, /* OID */ "1.3.132.0.28" }, #endif #ifdef LTC_ECC_SECP128R2 { /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", /* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D", /* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3", /* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140", /* Gy */ "27B6916A894D3AEE7106FE805FC34B44", /* cofactor */ 4, /* OID */ "1.3.132.0.29" }, #endif #ifdef LTC_ECC_SECP160R1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", /* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", /* order */ "0100000000000000000001F4C8F927AED3CA752257", /* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82", /* Gy */ "23A628553168947D59DCC912042351377AC5FB32", /* cofactor */ 1, /* OID */ "1.3.132.0.8" }, #endif #ifdef LTC_ECC_SECP160R2 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", /* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", /* order */ "0100000000000000000000351EE786A818F3A1A16B", /* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", /* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", /* cofactor */ 1, /* OID */ "1.3.132.0.30" }, #endif #ifdef LTC_ECC_SECP160K1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* A */ "0000000000000000000000000000000000000000", /* B */ "0000000000000000000000000000000000000007", /* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3", /* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", /* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE", /* cofactor */ 1, /* OID */ "1.3.132.0.9" }, #endif #ifdef LTC_ECC_SECP192R1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.1" }, #endif #ifdef LTC_ECC_PRIME192V2 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", /* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", /* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.2" }, #endif #ifdef LTC_ECC_PRIME192V3 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", /* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", /* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.3" }, #endif #ifdef LTC_ECC_SECP192K1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", /* A */ "000000000000000000000000000000000000000000000000", /* B */ "000000000000000000000000000000000000000000000003", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", /* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", /* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", /* cofactor */ 1, /* OID */ "1.3.132.0.31" }, #endif #ifdef LTC_ECC_SECP224R1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* cofactor */ 1, /* OID */ "1.3.132.0.33" }, #endif #ifdef LTC_ECC_SECP224K1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* A */ "00000000000000000000000000000000000000000000000000000000", /* B */ "00000000000000000000000000000000000000000000000000000005", /* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", /* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", /* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* cofactor */ 1, /* OID */ "1.3.132.0.32" }, #endif #ifdef LTC_ECC_SECP256R1 { /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.7" }, #endif #ifdef LTC_ECC_SECP256K1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* A */ "0000000000000000000000000000000000000000000000000000000000000000", /* B */ "0000000000000000000000000000000000000000000000000000000000000007", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* cofactor */ 1, /* OID */ "1.3.132.0.10" }, #endif #ifdef LTC_ECC_SECP384R1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* cofactor */ 1, /* OID */ "1.3.132.0.34" }, #endif #ifdef LTC_ECC_SECP521R1 { /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* cofactor */ 1, /* OID */ "1.3.132.0.35" }, #endif #ifdef LTC_ECC_PRIME239V1 { /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", /* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", /* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.4" }, #endif #ifdef LTC_ECC_PRIME239V2 { /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", /* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", /* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.5" }, #endif #ifdef LTC_ECC_PRIME239V3 { /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", /* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", /* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", /* cofactor */ 1, /* OID */ "1.2.840.10045.3.1.6" }, #endif #ifdef LTC_ECC_BRAINPOOLP160R1 { /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58", /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.1" }, #endif #ifdef LTC_ECC_BRAINPOOLP192R1 { /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.3" }, #endif #ifdef LTC_ECC_BRAINPOOLP224R1 { /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.5" }, #endif #ifdef LTC_ECC_BRAINPOOLP256R1 { /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.7" }, #endif #ifdef LTC_ECC_BRAINPOOLP320R1 { /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", /* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", /* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", /* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", /* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.9" }, #endif #ifdef LTC_ECC_BRAINPOOLP384R1 { /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", /* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.11" }, #endif #ifdef LTC_ECC_BRAINPOOLP512R1 { /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", /* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.13" }, #endif #ifdef LTC_ECC_BRAINPOOLP160T1 { /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C", /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378", /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.2" }, #endif #ifdef LTC_ECC_BRAINPOOLP192T1 { /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129", /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.4" }, #endif #ifdef LTC_ECC_BRAINPOOLP224T1 { /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580", /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.6" }, #endif #ifdef LTC_ECC_BRAINPOOLP256T1 { /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.8" }, #endif #ifdef LTC_ECC_BRAINPOOLP320T1 { /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52", /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.10" }, #endif #ifdef LTC_ECC_BRAINPOOLP384T1 { /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.12" }, #endif #ifdef LTC_ECC_BRAINPOOLP512T1 { /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", /* cofactor */ 1, /* OID */ "1.3.36.3.3.2.8.1.1.14" }, #endif #ifdef LTC_ECC_SM2 { /* prime */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", /* A */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", /* B */ "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", /* order */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", /* Gx */ "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", /* Gy */ "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", /* cofactor */ 1, /* OID */ "1.2.156.10197.1.301" }, #endif { NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL } }; #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c000066400000000000000000000011271464416617300254530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_ansi_x963_export.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** ECC X9.63 (Sec. 4.3.6) uncompressed export @param key Key to export @param out [out] destination of export @param outlen [in/out] Length of destination and final output size Return CRYPT_OK on success */ int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen) { return ecc_get_key(out, outlen, PK_PUBLIC, key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c000066400000000000000000000026011464416617300254420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_ansi_x963_import.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Import an ANSI X9.63 format public key @param in The input data to read @param inlen The length of the input data @param key [out] destination to store imported key \ */ int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key) { return ecc_ansi_x963_import_ex(in, inlen, key, NULL); } int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); /* must be odd */ if ((inlen & 1) == 0) { return CRYPT_INVALID_ARG; } /* initialize key->dp */ if (cu == NULL) { /* this case works only for uncompressed public keys */ if ((err = ecc_set_curve_by_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; } } else { /* this one works for both compressed / uncompressed pubkeys */ if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } } /* load public key */ if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; } /* we're done */ return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c000066400000000000000000000070011464416617300246460ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_decrypt_key.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Decrypt an ECC encrypted key @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext @param key The corresponding private ECC key @return CRYPT_OK if successful */ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const ecc_key *key) { unsigned char *ecc_shared, *skey, *pub_expt; unsigned long x, y; unsigned long hashOID[32] = { 0 }; int hash, err; ecc_key pubkey; ltc_asn1_list decode[3]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* right key type? */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* decode to find out hash */ LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); err = der_decode_sequence(in, inlen, decode, 1); if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { return err; } hash = find_hash_oid(hashOID, decode[0].size); if (hash_is_valid(hash) != CRYPT_OK) { return CRYPT_INVALID_PACKET; } /* we now have the hash! */ /* allocate memory */ pub_expt = XMALLOC(ECC_BUF_SIZE); ecc_shared = XMALLOC(ECC_BUF_SIZE); skey = XMALLOC(MAXBLOCKSIZE); if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { if (pub_expt != NULL) { XFREE(pub_expt); } if (ecc_shared != NULL) { XFREE(ecc_shared); } if (skey != NULL) { XFREE(skey); } return CRYPT_MEM; } LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); /* read the structure in now */ if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { goto LBL_ERR; } /* import ECC key from packet */ if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } /* make shared key */ x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE); if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { goto LBL_ERR; } /* ensure the hash of the shared secret is at least as big as the encrypt itself */ if (decode[2].size > y) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* avoid buffer overflow */ if (*outlen < decode[2].size) { *outlen = decode[2].size; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* Decrypt the key */ for (x = 0; x < decode[2].size; x++) { out[x] = skey[x] ^ ecc_shared[x]; } *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(pub_expt, ECC_BUF_SIZE); zeromem(ecc_shared, ECC_BUF_SIZE); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(pub_expt); XFREE(ecc_shared); XFREE(skey); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c000066400000000000000000000071151464416617300246660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_encrypt_key.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Encrypt a symmetric key with ECC @param in The symmetric key you want to encrypt @param inlen The length of the key to encrypt (octets) @param out [out] The destination for the ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param prng An active PRNG state @param wprng The index of the PRNG you wish to use @param hash The index of the hash you want to use @param key The ECC key you want to encrypt to @return CRYPT_OK if successful */ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, int hash, const ecc_key *key) { unsigned char *pub_expt, *ecc_shared, *skey; ecc_key pubkey; unsigned long x, y, pubkeysize; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } if (inlen > hash_descriptor[hash]->hashsize) { return CRYPT_INVALID_HASH; } /* make a random key and export the public copy */ if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { return err; } if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; } pub_expt = XMALLOC(ECC_BUF_SIZE); ecc_shared = XMALLOC(ECC_BUF_SIZE); skey = XMALLOC(MAXBLOCKSIZE); if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { if (pub_expt != NULL) { XFREE(pub_expt); } if (ecc_shared != NULL) { XFREE(ecc_shared); } if (skey != NULL) { XFREE(skey); } ecc_free(&pubkey); return CRYPT_MEM; } pubkeysize = ECC_BUF_SIZE; if (ltc_mp.sqrtmod_prime != NULL) { /* PK_COMPRESSED requires sqrtmod_prime */ err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey); } else { err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey); } if (err != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } /* make random key */ x = ECC_BUF_SIZE; if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { ecc_free(&pubkey); goto LBL_ERR; } ecc_free(&pubkey); y = MAXBLOCKSIZE; if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { goto LBL_ERR; } /* Encrypt key */ for (x = 0; x < inlen; x++) { skey[x] ^= in[x]; } err = der_encode_sequence_multi(out, outlen, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash]->OIDlen, hash_descriptor[hash]->OID, LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt, LTC_ASN1_OCTET_STRING, inlen, skey, LTC_ASN1_EOL, 0UL, NULL); LBL_ERR: #ifdef LTC_CLEAN_STACK /* clean up */ zeromem(pub_expt, ECC_BUF_SIZE); zeromem(ecc_shared, ECC_BUF_SIZE); zeromem(skey, MAXBLOCKSIZE); #endif XFREE(skey); XFREE(ecc_shared); XFREE(pub_expt); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_export.c000066400000000000000000000037331464416617300236550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_export.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Export an ECC key as a binary packet @param out [out] Destination for the key @param outlen [in/out] Max size and resulting size of the exported key @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) @param key The key to export @return CRYPT_OK if successful */ int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) { int err; unsigned char flags[1]; unsigned long key_size; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* type valid? */ if (key->type != PK_PRIVATE && type == PK_PRIVATE) { return CRYPT_PK_TYPE_MISMATCH; } /* we store the NIST byte size */ key_size = key->dp.size; if (type == PK_PRIVATE) { flags[0] = 1; err = der_encode_sequence_multi(out, outlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, LTC_ASN1_INTEGER, 1UL, key->pubkey.x, LTC_ASN1_INTEGER, 1UL, key->pubkey.y, LTC_ASN1_INTEGER, 1UL, key->k, LTC_ASN1_EOL, 0UL, NULL); } else { flags[0] = 0; err = der_encode_sequence_multi(out, outlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, LTC_ASN1_INTEGER, 1UL, key->pubkey.x, LTC_ASN1_INTEGER, 1UL, key->pubkey.y, LTC_ASN1_EOL, 0UL, NULL); } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_export_openssl.c000066400000000000000000000165101464416617300254150ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /** Export an ECC key as a binary packet @param out [out] Destination for the key @param outlen [in/out] Max size and resulting size of the exported key @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) @param key The key to export @return CRYPT_OK if successful */ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) { int err; void *prime, *order, *a, *b, *gx, *gy; unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512]; unsigned long len_a, len_b, len_k, len_g, len_xy; unsigned long cofactor, one = 1; const char *OID; unsigned long oid[16], oidlen; ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams; int flag_oid = type & PK_CURVEOID ? 1 : 0; int flag_com = type & PK_COMPRESSED ? 1 : 0; int flag_pri = type & PK_PRIVATE ? 1 : 0; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH; if (flag_oid) { /* http://tools.ietf.org/html/rfc5912 ECParameters ::= CHOICE { namedCurve CURVE.&id({NamedCurve}) # OBJECT } */ if (key->dp.oidlen == 0) { err = CRYPT_INVALID_ARG; goto error; } LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen); } else { prime = key->dp.prime; order = key->dp.order; a = key->dp.A; b = key->dp.B; gx = key->dp.base.x; gy = key->dp.base.y; cofactor = key->dp.cofactor; /* curve param a */ len_a = mp_unsigned_bin_size(a); if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; } if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */ /* curve param b */ len_b = mp_unsigned_bin_size(b); if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; } if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */ /* base point - (un)compressed based on flag_com */ len_g = sizeof(bin_g); err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com); if (err != CRYPT_OK) { goto error; } /* we support only prime-field EC */ if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; } /* http://tools.ietf.org/html/rfc3279 ECParameters ::= SEQUENCE { # SEQUENCE version INTEGER { ecpVer1(1) } (ecpVer1) # INTEGER :01 FieldID ::= SEQUENCE { # SEQUENCE fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER } Curve ::= SEQUENCE { # SEQUENCE a FieldElement ::= OCTET STRING # OCTET STRING b FieldElement ::= OCTET STRING # OCTET STRING seed BIT STRING OPTIONAL } base ECPoint ::= OCTET STRING # OCTET STRING order INTEGER, # INTEGER cofactor INTEGER OPTIONAL # INTEGER } */ oidlen = sizeof(oid)/sizeof(oid[0]); if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { goto error; } /* FieldID SEQUENCE */ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); /* Curve SEQUENCE */ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a); LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b); /* ECParameters SEQUENCE */ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL); LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL); LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g); LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */ LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); } /* public key - (un)compressed based on flag_com */ len_xy = sizeof(bin_xy); err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com); if (err != CRYPT_OK) { goto error; } if (flag_pri) { /* http://tools.ietf.org/html/rfc5915 ECPrivateKey ::= SEQUENCE { # SEQUENCE version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1) # INTEGER :01 privateKey OCTET STRING, # OCTET STRING [0] ECParameters # see above [1] publicKey # BIT STRING } */ /* private key */ len_k = mp_unsigned_bin_size(key->k); if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) { goto error; } LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy); LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1); LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k); LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */ err = der_encode_sequence(seq_priv, 4, out, outlen); } else { /* http://tools.ietf.org/html/rfc5480 SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey ECParameters # see above } subjectPublicKey BIT STRING # BIT STRING } */ err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy, ecparams.type, ecparams.data, ecparams.size ); } error: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_find_curve.c000066400000000000000000000124311464416617300244530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC static const struct { const char *OID; const char *names[6]; } s_curve_names[] = { #ifdef LTC_ECC_SECP112R1 { "1.3.132.0.6", { "SECP112R1", "ECC-112", NULL } }, #endif #ifdef LTC_ECC_SECP112R2 { "1.3.132.0.7", { "SECP112R2", NULL } }, #endif #ifdef LTC_ECC_SECP128R1 { "1.3.132.0.28", { "SECP128R1", "ECC-128", NULL } }, #endif #ifdef LTC_ECC_SECP128R2 { "1.3.132.0.29", { "SECP128R2", NULL } }, #endif #ifdef LTC_ECC_SECP160R1 { "1.3.132.0.8", { "SECP160R1", "ECC-160", NULL } }, #endif #ifdef LTC_ECC_SECP160R2 { "1.3.132.0.30", { "SECP160R2", NULL } }, #endif #ifdef LTC_ECC_SECP160K1 { "1.3.132.0.9", { "SECP160K1", NULL } }, #endif #ifdef LTC_ECC_SECP192R1 { "1.2.840.10045.3.1.1", { "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", NULL } }, #endif #ifdef LTC_ECC_PRIME192V2 { "1.2.840.10045.3.1.2", { "PRIME192V2", NULL } }, #endif #ifdef LTC_ECC_PRIME192V3 { "1.2.840.10045.3.1.3", { "PRIME192V3", NULL } }, #endif #ifdef LTC_ECC_SECP192K1 { "1.3.132.0.31", { "SECP192K1", NULL } }, #endif #ifdef LTC_ECC_SECP224R1 { "1.3.132.0.33", { "SECP224R1", "NISTP224", "ECC-224", "P-224", NULL } }, #endif #ifdef LTC_ECC_SECP224K1 { "1.3.132.0.32", { "SECP224K1", NULL } }, #endif #ifdef LTC_ECC_SECP256R1 { "1.2.840.10045.3.1.7", { "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", NULL } }, #endif #ifdef LTC_ECC_SECP256K1 { "1.3.132.0.10", { "SECP256K1", NULL } }, #endif #ifdef LTC_ECC_SECP384R1 { "1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL } }, #endif #ifdef LTC_ECC_SECP521R1 { "1.3.132.0.35", { "SECP521R1", "NISTP521", "ECC-521", "P-521", NULL } }, #endif #ifdef LTC_ECC_PRIME239V1 { "1.2.840.10045.3.1.4", { "PRIME239V1", NULL } }, #endif #ifdef LTC_ECC_PRIME239V2 { "1.2.840.10045.3.1.5", { "PRIME239V2", NULL } }, #endif #ifdef LTC_ECC_PRIME239V3 { "1.2.840.10045.3.1.6", { "PRIME239V3", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP160R1 { "1.3.36.3.3.2.8.1.1.1", { "BRAINPOOLP160R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP192R1 { "1.3.36.3.3.2.8.1.1.3", { "BRAINPOOLP192R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP224R1 { "1.3.36.3.3.2.8.1.1.5", { "BRAINPOOLP224R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP256R1 { "1.3.36.3.3.2.8.1.1.7", { "BRAINPOOLP256R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP320R1 { "1.3.36.3.3.2.8.1.1.9", { "BRAINPOOLP320R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP384R1 { "1.3.36.3.3.2.8.1.1.11", { "BRAINPOOLP384R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP512R1 { "1.3.36.3.3.2.8.1.1.13", { "BRAINPOOLP512R1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP160T1 { "1.3.36.3.3.2.8.1.1.2", { "BRAINPOOLP160T1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP192T1 { "1.3.36.3.3.2.8.1.1.4", { "BRAINPOOLP192T1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP224T1 { "1.3.36.3.3.2.8.1.1.6", { "BRAINPOOLP224T1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP256T1 { "1.3.36.3.3.2.8.1.1.8", { "BRAINPOOLP256T1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP320T1 { "1.3.36.3.3.2.8.1.1.10", { "BRAINPOOLP320T1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP384T1 { "1.3.36.3.3.2.8.1.1.12", { "BRAINPOOLP384T1", NULL } }, #endif #ifdef LTC_ECC_BRAINPOOLP512T1 { "1.3.36.3.3.2.8.1.1.14", { "BRAINPOOLP512T1", NULL } }, #endif #ifdef LTC_ECC_SM2 { "1.2.156.10197.1.301", { "SM2", NULL } }, #endif { NULL, { NULL } } }; /* case-insensitive match + ignore '-', '_', ' ' */ static int s_name_match(const char *left, const char *right) { char lc_r, lc_l; while ((*left != '\0') && (*right != '\0')) { while ((*left == ' ') || (*left == '-') || (*left == '_')) left++; while ((*right == ' ') || (*right == '-') || (*right == '_')) right++; if (*left == '\0' || *right == '\0') break; lc_r = *right; lc_l = *left; if ((lc_r >= 'A') && (lc_r <= 'Z')) lc_r += 32; if ((lc_l >= 'A') && (lc_l <= 'Z')) lc_l += 32; if (lc_l != lc_r) return 0; left++; right++; } if ((*left == '\0') && (*right == '\0')) return 1; return 0; } int ecc_find_curve(const char *name_or_oid, const ltc_ecc_curve **cu) { int i, j; const char *OID = NULL; LTC_ARGCHK(cu != NULL); LTC_ARGCHK(name_or_oid != NULL); *cu = NULL; for (i = 0; s_curve_names[i].OID != NULL && !OID; i++) { if (XSTRCMP(s_curve_names[i].OID, name_or_oid) == 0) { OID = s_curve_names[i].OID; } for (j = 0; s_curve_names[i].names[j] != NULL && !OID; j++) { if (s_name_match(s_curve_names[i].names[j], name_or_oid)) { OID = s_curve_names[i].OID; } } } if (OID != NULL) { for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { if (XSTRCMP(ltc_ecc_curves[i].OID, OID) == 0) { *cu = <c_ecc_curves[i]; return CRYPT_OK; } } } return CRYPT_INVALID_ARG; /* not found */ } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_free.c000066400000000000000000000011641464416617300232510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_free.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Free an ECC key from memory @param key The key you wish to free */ void ecc_free(ecc_key *key) { LTC_ARGCHKVD(key != NULL); mp_cleanup_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c000066400000000000000000000031671464416617300237640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes) @param out [out] destination of export @param outlen [in/out] Length of destination and final output size @param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC|PK_COMPRESSED @param key Key to export Return CRYPT_OK on success */ int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) { unsigned long size, ksize; int err, compressed; LTC_ARGCHK(key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); size = key->dp.size; compressed = type & PK_COMPRESSED ? 1 : 0; type &= ~PK_COMPRESSED; if (type == PK_PUBLIC) { if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) { return err; } } else if (type == PK_PRIVATE) { if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; if (size > *outlen) { *outlen = size; return CRYPT_BUFFER_OVERFLOW; } *outlen = size; if ((ksize = mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW; /* pad and store k */ if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err; zeromem(out, size - ksize); } else { return CRYPT_INVALID_ARG; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c000066400000000000000000000011261464416617300246300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /** Extract OID as a string from ECC key @param out [out] destination buffer @param outlen [in/out] Length of destination buffer and final output size (without terminating NUL byte) @param key The ECC key Return CRYPT_OK on success */ int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key) { LTC_ARGCHK(key != NULL); return pk_oid_num_to_str(key->dp.oid, key->dp.oidlen, out, outlen); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_get_size.c000066400000000000000000000007311464416617300241400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_get_size.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Get the size of an ECC key @param key The key to get the size of @return The size (octets) of the key or INT_MAX on error */ int ecc_get_size(const ecc_key *key) { if (key == NULL) { return INT_MAX; } return key->dp.size; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_import.c000066400000000000000000000066521464416617300236510ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_import.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Import an ECC key from a binary packet @param in The packet to import @param inlen The length of the packet @param key [out] The destination of the import @return CRYPT_OK if successful, upon error all allocated memory will be freed */ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) { return ecc_import_ex(in, inlen, key, NULL); } /** Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones @param in The packet to import @param inlen The length of the packet @param key [out] The destination of the import @param cu pointer to user supplied params; must be the same as the params used when exporting @return CRYPT_OK if successful, upon error all allocated memory will be freed */ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu) { unsigned long key_size; unsigned char flags[1]; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* find out what type of key it is */ err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, LTC_ASN1_EOL, 0UL, NULL); if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { return err; } /* allocate & initialize the key */ if (cu == NULL) { if ((err = ecc_set_curve_by_size(key_size, key)) != CRYPT_OK) { goto done; } } else { if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { goto done; } } if (flags[0] == 1) { /* private key */ key->type = PK_PRIVATE; if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, LTC_ASN1_INTEGER, 1UL, key->pubkey.x, LTC_ASN1_INTEGER, 1UL, key->pubkey.y, LTC_ASN1_INTEGER, 1UL, key->k, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto done; } } else if (flags[0] == 0) { /* public key */ key->type = PK_PUBLIC; if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, LTC_ASN1_INTEGER, 1UL, key->pubkey.x, LTC_ASN1_INTEGER, 1UL, key->pubkey.y, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto done; } } else { err = CRYPT_INVALID_PACKET; goto done; } /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; } /* point on the curve + other checks */ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; } /* we're good */ return CRYPT_OK; done: ecc_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_import_openssl.c000066400000000000000000000124471464416617300254130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) { ltc_asn1_list seq_priv[4], custom[2]; unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE]; unsigned long len, pkver = 0, curveoid[16]; char OID[256]; const ltc_ecc_curve *curve; int err; /* ### try to load private key - no curve parameters just curve OID */ /* ECPrivateKey SEQUENCE */ LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL); LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ /* try to load private key */ err = der_decode_sequence(in, inlen, seq_priv, 4); if (err == CRYPT_OK) { /* load curve parameters for given curve OID */ len = sizeof(OID); if ((err = pk_oid_num_to_str(curveoid, custom[0].size, OID, &len)) != CRYPT_OK) { goto error; } if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } /* load private+public key */ err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key); } error: return err; } static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) { void *prime, *order, *a, *b, *gx, *gy; ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2]; unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE]; unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; unsigned long len_a, len_b, len_k, len_g; unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; int err; if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { return err; } /* ### try to load private key - curve parameters included */ /* ECPrivateKey SEQUENCE */ LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ /* ECParameters SEQUENCE */ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); seq_ecparams[5].optional = 1; /* FieldID SEQUENCE */ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); /* Curve SEQUENCE */ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8UL*sizeof(bin_seed)); seq_curve[2].optional = 1; /* try to load private key */ err = der_decode_sequence(in, inlen, seq_priv, 4); if (err == CRYPT_OK) { len_k = seq_priv[1].size; len_a = seq_curve[0].size; len_b = seq_curve[1].size; len_g = seq_ecparams[3].size; /* create bignums */ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } /* load curve parameters */ if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } /* load private+public key */ err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key); } error: mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); return err; } int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key) { int err; if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) { goto success; } if ((err = s_ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) { goto success; } err = s_ecc_import_private_with_curve(in, inlen, key); success: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c000066400000000000000000000173421464416617300247570ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC typedef struct { ltc_asn1_type t; ltc_asn1_list **pp; } der_flexi_check; #define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \ do { \ int LTC_SDFC_temp##__LINE__ = (index); \ list[LTC_SDFC_temp##__LINE__].t = Type; \ list[LTC_SDFC_temp##__LINE__].pp = P; \ } while (0) static int s_der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check) { const ltc_asn1_list *cur; if (flexi->type != LTC_ASN1_SEQUENCE) { return CRYPT_INVALID_PACKET; } cur = flexi->child; while(check->t != LTC_ASN1_EOL) { if (!LTC_ASN1_IS_TYPE(cur, check->t)) { return CRYPT_INVALID_PACKET; } if (check->pp != NULL) *check->pp = (ltc_asn1_list*)cur; cur = cur->next; check++; } return CRYPT_OK; } /* NOTE: s_der_decode_pkcs8_flexi & related stuff can be shared with rsa_import_pkcs8() */ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key) { void *a, *b, *gx, *gy; unsigned long len, cofactor, n; const char *pka_ec_oid; int err; char OID[256]; const ltc_ecc_curve *curve; ltc_asn1_list *p = NULL, *l = NULL; der_flexi_check flexi_should[7]; ltc_asn1_list *seq, *priv_key; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* get EC alg oid */ err = pk_get_oid(LTC_OID_EC, &pka_ec_oid); if (err != CRYPT_OK) return err; /* init key */ err = mp_init_multi(&a, &b, &gx, &gy, LTC_NULL); if (err != CRYPT_OK) return err; if (pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l) == CRYPT_OK) { /* Setup for basic structure */ n=0; LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, NULL); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seq); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &priv_key); LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); if ((s_der_flexi_sequence_cmp(l, flexi_should) == CRYPT_OK) && (pk_oid_cmp_with_asn1(pka_ec_oid, seq->child) == CRYPT_OK)) { ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor; /* Setup for CASE 2 */ n=0; LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &version); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &field); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &point); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &point_g); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &order); LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &p_cofactor); LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); if (LTC_ASN1_IS_TYPE(seq->child->next, LTC_ASN1_OBJECT_IDENTIFIER)) { /* CASE 1: curve by OID (AKA short variant): * 0:d=0 hl=2 l= 100 cons: SEQUENCE * 2:d=1 hl=2 l= 1 prim: INTEGER :00 * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *seq) * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey * 16:d=2 hl=2 l= 5 prim: OBJECT :(== *curve_oid (e.g. secp256k1 (== 1.3.132.0.10))) * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) */ ltc_asn1_list *curve_oid = seq->child->next; len = sizeof(OID); if ((err = pk_oid_num_to_str(curve_oid->data, curve_oid->size, OID, &len)) != CRYPT_OK) { goto LBL_DONE; } if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto LBL_DONE; } if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto LBL_DONE; } } else if ((err = s_der_flexi_sequence_cmp(seq->child->next, flexi_should)) == CRYPT_OK) { /* CASE 2: explicit curve parameters (AKA long variant): * 0:d=0 hl=3 l= 227 cons: SEQUENCE * 3:d=1 hl=2 l= 1 prim: INTEGER :00 * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *seq) * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey * 18:d=2 hl=3 l= 130 cons: SEQUENCE * 21:d=3 hl=2 l= 1 prim: INTEGER :01 * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *field) * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field * 35:d=4 hl=2 l= 33 prim: INTEGER :(== *prime / curve.prime) * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *point) * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A) * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B) * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== *g_point / curve.G-point) * 113:d=3 hl=2 l= 33 prim: INTEGER :(== *order / curve.order) * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor) * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) */ if (mp_get_int(version->data) != 1) { goto LBL_DONE; } cofactor = mp_get_int(p_cofactor->data); if (LTC_ASN1_IS_TYPE(field->child, LTC_ASN1_OBJECT_IDENTIFIER) && LTC_ASN1_IS_TYPE(field->child->next, LTC_ASN1_INTEGER) && LTC_ASN1_IS_TYPE(point->child, LTC_ASN1_OCTET_STRING) && LTC_ASN1_IS_TYPE(point->child->next, LTC_ASN1_OCTET_STRING)) { ltc_asn1_list *prime = field->child->next; if ((err = mp_read_unsigned_bin(a, point->child->data, point->child->size)) != CRYPT_OK) { goto LBL_DONE; } if ((err = mp_read_unsigned_bin(b, point->child->next->data, point->child->next->size)) != CRYPT_OK) { goto LBL_DONE; } if ((err = ltc_ecc_import_point(point_g->data, point_g->size, prime->data, a, b, gx, gy)) != CRYPT_OK) { goto LBL_DONE; } if ((err = ecc_set_curve_from_mpis(a, b, prime->data, order->data, gx, gy, cofactor, key)) != CRYPT_OK) { goto LBL_DONE; } } } else { err = CRYPT_INVALID_PACKET; goto LBL_DONE; } /* load private key value 'k' */ len = priv_key->size; if (der_decode_sequence_flexi(priv_key->data, &len, &p) == CRYPT_OK) { if (p->type == LTC_ASN1_SEQUENCE && LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) && LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) { ltc_asn1_list *lk = p->child->next; if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; goto LBL_ECCFREE; } if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) { goto LBL_ECCFREE; } goto LBL_DONE; /* success */ } } } } err = CRYPT_INVALID_PACKET; goto LBL_DONE; LBL_ECCFREE: ecc_free(key); LBL_DONE: mp_clear_multi(a, b, gx, gy, LTC_NULL); if (l) der_free_sequence_flexi(l); if (p) der_free_sequence_flexi(p); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_import_x509.c000066400000000000000000000112751464416617300244330ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) { unsigned char bin_xy[2*ECC_MAXSIZE+2]; unsigned long curveoid[16]; unsigned long len_xy, len_oid, len; char OID[256]; const ltc_ecc_curve *curve; int err; len_xy = sizeof(bin_xy); len_oid = 16; err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); if (err == CRYPT_OK) { /* load curve parameters for given curve OID */ len = sizeof(OID); if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; } if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } /* load public key */ err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); } error: return err; } static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) { void *prime, *order, *a, *b, *gx, *gy; ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6]; unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE]; unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; unsigned long len_a, len_b, len_g, len_xy, len; unsigned long cofactor = 0, ecver = 0, tmpoid[16]; int err; if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { return err; } /* ECParameters SEQUENCE */ LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); seq_ecparams[5].optional = 1; /* FieldID SEQUENCE */ LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); /* Curve SEQUENCE */ LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8u*sizeof(bin_seed)); seq_curve[2].optional = 1; /* try to load public key */ len_xy = sizeof(bin_xy); len = 6; err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); if (err == CRYPT_OK) { len_a = seq_curve[0].size; len_b = seq_curve[1].size; len_g = seq_ecparams[3].size; /* create bignums */ if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } /* load curve parameters */ if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } /* load public key */ err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); } error: mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); return err; } int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key) { int err; if ((err = s_ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) { goto success; } err = s_ecc_import_x509_with_curve(in, inlen, key); success: return err; } /** Import an ECC key from a X.509 certificate @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @return CRYPT_OK if successful, upon error allocated memory is freed */ int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key) { return x509_decode_public_key_from_certificate(in, inlen, LTC_OID_EC, LTC_ASN1_EOL, NULL, NULL, (public_key_decode_cb)ecc_import_subject_public_key_info, key); } #endif /* LTC_MECC */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_make_key.c000066400000000000000000000040241464416617300241130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_make_key.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Make a new ECC key @param prng An active PRNG state @param wprng The index of the PRNG you wish to use @param keysize The keysize for the new key (in octets from 20 to 65 bytes) @param key [out] Destination of the newly created key @return CRYPT_OK if successful, upon error all allocated memory will be freed */ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) { int err; if ((err = ecc_set_curve_by_size(keysize, key)) != CRYPT_OK) { return err; } if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } return CRYPT_OK; } int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu) { int err; if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } return CRYPT_OK; } int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key) { int err; LTC_ARGCHK(ltc_mp.name != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(key->dp.size > 0); /* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates): * the generated private key k should be the range [1, order-1] * a/ N = bitlen(order) * b/ generate N random bits and convert them into big integer k * c/ if k not in [1, order-1] go to b/ * e/ Q = k*G */ if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) { goto error; } /* make the public key */ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) { goto error; } key->type = PK_PRIVATE; /* success */ err = CRYPT_OK; goto cleanup; error: ecc_free(key); cleanup: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_recover_key.c000066400000000000000000000260541464416617300246520ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC #ifdef LTC_ECC_SHAMIR /** @file ecc_recover_key.c ECC Crypto, Russ Williams */ /** Recover ECC public key from signature and hash @param sig The signature to verify @param siglen The length of the signature (octets) @param hash The hash (message digest) that was signed @param hashlen The length of the hash (octets) @param recid The recovery ID ("v"), can be -1 if signature contains it @param sigformat The format of the signature (ecc_signature_type) @param key The recovered public ECC key @return CRYPT_OK if successful (even if the signature is not valid) */ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int recid, ecc_signature_type sigformat, ecc_key *key) { ecc_point *mG = NULL, *mQ = NULL, *mR = NULL; void *p, *m, *a, *b; void *r, *s, *v, *w, *t1, *t2, *u1, *u2, *v1, *v2, *e, *x, *y, *a_plus3; void *mu = NULL, *ma = NULL; void *mp = NULL; int err; unsigned long pbits, pbytes, i, shift_right; unsigned char ch, buf[MAXBLOCKSIZE]; LTC_ARGCHK(sig != NULL); LTC_ARGCHK(hash != NULL); LTC_ARGCHK(key != NULL); /* BEWARE: requires sqrtmod_prime */ if (ltc_mp.sqrtmod_prime == NULL) { return CRYPT_ERROR; } /* allocate ints */ if ((err = mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, LTC_NULL)) != CRYPT_OK) { return err; } p = key->dp.order; m = key->dp.prime; a = key->dp.A; b = key->dp.B; if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } /* allocate points */ mG = ltc_ecc_new_point(); mQ = ltc_ecc_new_point(); mR = ltc_ecc_new_point(); if (mR == NULL || mQ == NULL || mG == NULL) { err = CRYPT_MEM; goto error; } if (sigformat == LTC_ECCSIG_ANSIX962) { /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } } else if (sigformat == LTC_ECCSIG_RFC7518) { /* RFC7518 format - raw (r,s) */ i = mp_unsigned_bin_size(key->dp.order); if (siglen != (2*i)) { err = CRYPT_INVALID_PACKET; goto error; } if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } } else if (sigformat == LTC_ECCSIG_ETH27) { /* Ethereum (v,r,s) format */ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { /* Only valid for secp256k1 - OID 1.3.132.0.10 */ err = CRYPT_ERROR; goto error; } if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ err = CRYPT_INVALID_PACKET; goto error; } i = (unsigned long)sig[64]; if ((i>=27) && (i<31)) i -= 27; /* Ethereum adds 27 to recovery ID */ if (recid >= 0 && ((unsigned long)recid != i)) { /* Recovery ID specified, but doesn't match signature */ err = CRYPT_INVALID_PACKET; goto error; } recid = i; if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } } #ifdef LTC_SSH else if (sigformat == LTC_ECCSIG_RFC5656) { char name[64], name2[64]; unsigned long namelen = sizeof(name); unsigned long name2len = sizeof(name2); /* Decode as SSH data sequence, per RFC4251 */ if ((err = ssh_decode_sequence_multi(sig, &siglen, LTC_SSHDATA_STRING, name, &namelen, LTC_SSHDATA_MPINT, r, LTC_SSHDATA_MPINT, s, LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } /* Check curve matches identifier string */ if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { err = CRYPT_INVALID_ARG; goto error; } } #endif else { /* Unknown signature format */ err = CRYPT_ERROR; goto error; } if (recid < 0 || (unsigned long)recid >= 2*(key->dp.cofactor+1)) { /* Recovery ID is out of range, reject it */ err = CRYPT_INVALID_ARG; goto error; } /* check for zero */ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { err = CRYPT_INVALID_PACKET; goto error; } /* read hash - truncate if needed */ pbits = mp_count_bits(p); pbytes = (pbits+7) >> 3; if (pbits > hashlen*8) { if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } } else if (pbits % 8 == 0) { if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } } else { shift_right = 8 - pbits % 8; for (i=0, ch=0; i> shift_right); } if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } } /* decompress point from r=(x mod p) - BEWARE: requires sqrtmod_prime */ /* x = r + p*(recid/2) */ if ((err = mp_set(x, recid/2)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(p, x, m, x)) != CRYPT_OK) { goto error; } if ((err = mp_add(x, r, x)) != CRYPT_OK) { goto error; } /* compute x^3 */ if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(t1, x, m, t1)) != CRYPT_OK) { goto error; } /* compute x^3 + a*x */ if ((err = mp_mulmod(a, x, m, t2)) != CRYPT_OK) { goto error; } if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto error; } /* compute x^3 + a*x + b */ if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto error; } /* compute sqrt(x^3 + a*x + b) */ if ((err = mp_sqrtmod_prime(t1, m, t2)) != CRYPT_OK) { goto error; } /* fill in mR */ if ((err = mp_copy(x, mR->x)) != CRYPT_OK) { goto error; } if ((mp_isodd(t2) && (recid%2)) || (!mp_isodd(t2) && !(recid%2))) { if ((err = mp_mod(t2, m, mR->y)) != CRYPT_OK) { goto error; } } else { if ((err = mp_submod(m, t2, m, mR->y)) != CRYPT_OK) { goto error; } } if ((err = mp_set(mR->z, 1)) != CRYPT_OK) { goto error; } /* w = r^-1 mod n */ if ((err = mp_invmod(r, p, w)) != CRYPT_OK) { goto error; } /* v1 = sw */ if ((err = mp_mulmod(s, w, p, v1)) != CRYPT_OK) { goto error; } /* v2 = -ew */ if ((err = mp_mulmod(e, w, p, v2)) != CRYPT_OK) { goto error; } if ((err = mp_submod(p, v2, p, v2)) != CRYPT_OK) { goto error; } /* w = s^-1 mod n */ if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } /* u1 = ew */ if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } /* u2 = rw */ if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } /* find mG */ if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } /* find the montgomery mp */ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } /* for curves with a == -3 keep ma == NULL */ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } } /* recover mQ from mR */ /* compute v1*mR + v2*mG = mQ using Shamir's trick */ if ((err = ltc_mp.ecc_mul2add(mR, v1, mG, v2, mQ, ma, m)) != CRYPT_OK) { goto error; } /* compute u1*mG + u2*mQ = mG using Shamir's trick */ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } /* v = X_x1 mod n */ if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } /* does v == r */ if (mp_cmp(v, r) == LTC_MP_EQ) { /* found public key which verifies signature */ if ((err = ltc_ecc_copy_point(mQ, &key->pubkey)) != CRYPT_OK) { goto error; } /* point on the curve + other checks */ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto error; } key->type = PK_PUBLIC; err = CRYPT_OK; } else { /* not found - recid is wrong or we're unable to calculate public key for some other reason */ err = CRYPT_INVALID_ARG; } error: if (ma != NULL) mp_clear(ma); if (mu != NULL) mp_clear(mu); if (mp != NULL) mp_montgomery_free(mp); if (mR != NULL) ltc_ecc_del_point(mR); if (mQ != NULL) ltc_ecc_del_point(mQ); if (mG != NULL) ltc_ecc_del_point(mG); mp_clear_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, LTC_NULL); return err; } #endif #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve.c000066400000000000000000000050041464416617300243240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(cu != NULL); if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL)) != CRYPT_OK) { return err; } /* A, B, order, prime, Gx, Gy */ if ((err = mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(key->dp.A, cu->A, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(key->dp.B, cu->B, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(key->dp.base.x, cu->Gx, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(key->dp.base.y, cu->Gy, 16)) != CRYPT_OK) { goto error; } if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } /* cofactor & size */ key->dp.cofactor = cu->cofactor; key->dp.size = mp_unsigned_bin_size(key->dp.prime); /* OID string >> unsigned long oid[16] + oidlen */ key->dp.oidlen = 16; if ((err = pk_oid_str_to_num(cu->OID, key->dp.oid, &key->dp.oidlen)) != CRYPT_OK) { goto error; } /* success */ return CRYPT_OK; error: ecc_free(key); return err; } int ecc_set_curve_by_size(int size, ecc_key *key) { const ltc_ecc_curve *cu = NULL; int err = CRYPT_ERROR; /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */ if (size <= 14) { err = ecc_find_curve("SECP112R1", &cu); } else if (size <= 16) { err = ecc_find_curve("SECP128R1", &cu); } else if (size <= 20) { err = ecc_find_curve("SECP160R1", &cu); } else if (size <= 24) { err = ecc_find_curve("SECP192R1", &cu); } else if (size <= 28) { err = ecc_find_curve("SECP224R1", &cu); } else if (size <= 32) { err = ecc_find_curve("SECP256R1", &cu); } else if (size <= 48) { err = ecc_find_curve("SECP384R1", &cu); } else if (size <= 66) { err = ecc_find_curve("SECP521R1", &cu); } if (err == CRYPT_OK && cu != NULL) return ecc_set_curve(cu, key); return CRYPT_INVALID_ARG; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c000066400000000000000000000102271464416617300262230ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC static int s_ecc_cmp_hex_bn(const char *left_hex, void *right_bn, void *tmp_bn) { if (mp_read_radix(tmp_bn, left_hex, 16) != CRYPT_OK) return 0; if (mp_cmp(tmp_bn, right_bn) != LTC_MP_EQ) return 0; return 1; } static void s_ecc_oid_lookup(ecc_key *key) { void *bn; const ltc_ecc_curve *curve; key->dp.oidlen = 0; if (mp_init(&bn) != CRYPT_OK) return; for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) { if (s_ecc_cmp_hex_bn(curve->prime, key->dp.prime, bn) != 1) continue; if (s_ecc_cmp_hex_bn(curve->order, key->dp.order, bn) != 1) continue; if (s_ecc_cmp_hex_bn(curve->A, key->dp.A, bn) != 1) continue; if (s_ecc_cmp_hex_bn(curve->B, key->dp.B, bn) != 1) continue; if (s_ecc_cmp_hex_bn(curve->Gx, key->dp.base.x, bn) != 1) continue; if (s_ecc_cmp_hex_bn(curve->Gy, key->dp.base.y, bn) != 1) continue; if (key->dp.cofactor != curve->cofactor) continue; break; /* found */ } mp_clear(bn); if (curve->prime && curve->OID) { key->dp.oidlen = 16; /* size of key->dp.oid */ pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen); } } int ecc_copy_curve(const ecc_key *srckey, ecc_key *key) { unsigned long i; int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(srckey != NULL); if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL)) != CRYPT_OK) { return err; } /* A, B, order, prime, Gx, Gy */ if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; } if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; } if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; } if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; } if ((err = ltc_ecc_copy_point(&srckey->dp.base, &key->dp.base)) != CRYPT_OK) { goto error; } /* cofactor & size */ key->dp.cofactor = srckey->dp.cofactor; key->dp.size = srckey->dp.size; /* OID */ if (srckey->dp.oidlen > 0) { key->dp.oidlen = srckey->dp.oidlen; for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i]; } else { s_ecc_oid_lookup(key); /* try to find OID in ltc_ecc_curves */ } /* success */ return CRYPT_OK; error: ecc_free(key); return err; } int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(prime != NULL); LTC_ARGCHK(order != NULL); LTC_ARGCHK(gx != NULL); LTC_ARGCHK(gy != NULL); if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL)) != CRYPT_OK) { return err; } /* A, B, order, prime, Gx, Gy */ if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; } if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; } if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; } if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; } if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; } if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; } if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } /* cofactor & size */ key->dp.cofactor = cofactor; key->dp.size = mp_unsigned_bin_size(prime); /* try to find OID in ltc_ecc_curves */ s_ecc_oid_lookup(key); /* success */ return CRYPT_OK; error: ecc_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_set_key.c000066400000000000000000000027401464416617300237740ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key) { int err; void *prime, *a, *b; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); prime = key->dp.prime; a = key->dp.A; b = key->dp.B; if (type == PK_PRIVATE) { /* load private key */ if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; } if (mp_iszero(key->k) || (mp_cmp(key->k, key->dp.order) != LTC_MP_LT)) { err = CRYPT_INVALID_PACKET; goto error; } /* compute public key */ if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; } } else if (type == PK_PUBLIC) { /* load public key */ if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; } if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; } } else { err = CRYPT_INVALID_PACKET; goto error; } /* point on the curve + other checks */ if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto error; } key->type = type; return CRYPT_OK; error: ecc_free(key); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_shared_secret.c000066400000000000000000000033421464416617300251430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_shared_secret.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Create an ECC shared secret between two keys @param private_key The private ECC key @param public_key The public key @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63) @param outlen [in/out] The max size and resulting size of the shared secret @return CRYPT_OK if successful */ int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, unsigned char *out, unsigned long *outlen) { unsigned long x; ecc_point *result; void *prime, *a; int err; LTC_ARGCHK(private_key != NULL); LTC_ARGCHK(public_key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* type valid? */ if (private_key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* make new point */ result = ltc_ecc_new_point(); if (result == NULL) { return CRYPT_MEM; } prime = private_key->dp.prime; a = private_key->dp.A; if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; } x = (unsigned long)mp_unsigned_bin_size(prime); if (*outlen < x) { *outlen = x; err = CRYPT_BUFFER_OVERFLOW; goto done; } zeromem(out, x); if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; } err = CRYPT_OK; *outlen = x; done: ltc_ecc_del_point(result); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_sign_hash.c000066400000000000000000000154221464416617300242750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /** @file ecc_sign_hash.c ECC Crypto, Tom St Denis */ /** Sign a message digest @param in The message digest to sign @param inlen The length of the digest @param out [out] The destination for the signature @param outlen [in/out] The max size and resulting size of the signature @param prng An active PRNG state @param wprng The index of the PRNG you wish to use @param sigformat The format of the signature to generate (ecc_signature_type) @param recid [out] The recovery ID for this signature (optional) @param key A private ECC key @return CRYPT_OK if successful */ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, ecc_signature_type sigformat, int *recid, const ecc_key *key) { ecc_key pubkey; void *r, *s, *e, *p, *b; int v = 0; int err, max_iterations = LTC_PK_MAX_RETRIES; unsigned long pbits, pbytes, i, shift_right; unsigned char ch, buf[MAXBLOCKSIZE]; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* is this a private key? */ if (key->type != PK_PRIVATE) { return CRYPT_PK_NOT_PRIVATE; } /* init the bignums */ if ((err = mp_init_multi(&r, &s, &e, &b, LTC_NULL)) != CRYPT_OK) { return err; } /* get the hash and load it as a bignum into 'e' */ p = key->dp.order; pbits = mp_count_bits(p); pbytes = (pbits+7) >> 3; if (pbits > inlen*8) { if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } } else if (pbits % 8 == 0) { if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } } else { shift_right = 8 - pbits % 8; for (i=0, ch=0; i> shift_right); } if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } } /* make up a key and export the public copy */ do { if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; } if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } /* find r = x1 mod n */ if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } if (recid || sigformat==LTC_ECCSIG_ETH27) { /* find recovery ID (if needed) */ v = 0; if (mp_copy(pubkey.pubkey.x, s) != CRYPT_OK) { goto error; } while (mp_cmp_d(s, 0) == LTC_MP_GT && mp_cmp(s, p) != LTC_MP_LT) { /* Compute x1 div n... this will almost never be reached for curves with order 1 */ v += 2; if ((err = mp_sub(s, p, s)) != CRYPT_OK) { goto error; } } if (mp_isodd(pubkey.pubkey.y)) v += 1; } if (mp_iszero(r) == LTC_MP_YES) { ecc_free(&pubkey); } else { if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ /* find s = (e + xr)/k */ if ((err = mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */ if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */ if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */ if ((err = mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */ ecc_free(&pubkey); if (mp_iszero(s) == LTC_MP_NO) { break; } } } while (--max_iterations > 0); if (max_iterations == 0) { goto errnokey; } if (recid) *recid = v; if (sigformat == LTC_ECCSIG_ANSIX962) { /* store as ASN.1 SEQUENCE { r, s -- integer } */ err = der_encode_sequence_multi(out, outlen, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, NULL); } else if (sigformat == LTC_ECCSIG_RFC7518) { /* RFC7518 format - raw (r,s) */ if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; } zeromem(out, 2*pbytes); i = mp_unsigned_bin_size(r); if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) { goto errnokey; } i = mp_unsigned_bin_size(s); if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) { goto errnokey; } *outlen = 2*pbytes; err = CRYPT_OK; } else if (sigformat == LTC_ECCSIG_ETH27) { /* Ethereum (v,r,s) format */ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { /* Only valid for secp256k1 - OID 1.3.132.0.10 */ err = CRYPT_ERROR; goto errnokey; } if (*outlen < 65) { err = CRYPT_MEM; goto errnokey; } zeromem(out, 65); i = mp_unsigned_bin_size(r); if ((err = mp_to_unsigned_bin(r, out + 32 - i)) != CRYPT_OK) { goto errnokey; } i = mp_unsigned_bin_size(s); if ((err = mp_to_unsigned_bin(s, out + 64 - i)) != CRYPT_OK) { goto errnokey; } out[64] = (unsigned char)(v + 27); /* Recovery ID is 27/28 for Ethereum */ *outlen = 65; err = CRYPT_OK; } #ifdef LTC_SSH else if (sigformat == LTC_ECCSIG_RFC5656) { /* Get identifier string */ char name[64]; unsigned long namelen = sizeof(name); if ((err = ecc_ssh_ecdsa_encode_name(name, &namelen, key)) != CRYPT_OK) { goto errnokey; } /* Store as SSH data sequence, per RFC4251 */ err = ssh_encode_sequence_multi(out, outlen, LTC_SSHDATA_STRING, name, namelen, LTC_SSHDATA_MPINT, r, LTC_SSHDATA_MPINT, s, LTC_SSHDATA_EOL, NULL); } #endif else { /* Unknown signature format */ err = CRYPT_ERROR; goto error; } goto errnokey; error: ecc_free(&pubkey); errnokey: mp_clear_multi(r, s, e, b, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_sizes.c000066400000000000000000000013161464416617300234640ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_sizes.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC void ecc_sizes(int *low, int *high) { int i, size; void *prime; LTC_ARGCHKVD(low != NULL); LTC_ARGCHKVD(high != NULL); *low = INT_MAX; *high = 0; if (mp_init(&prime) == CRYPT_OK) { for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { if (mp_read_radix(prime, ltc_ecc_curves[i].prime, 16) == CRYPT_OK) { size = mp_unsigned_bin_size(prime); if (size < *low) *low = size; if (size > *high) *high = size; } } mp_clear(prime); } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c000066400000000000000000000037761464416617300266140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ecc_ssh_ecdsa_encode_name.c Curve/OID to SSH+ECDSA name string mapping per RFC5656 Russ Williams */ #ifdef LTC_SSH /** Curve/OID to SSH+ECDSA name string mapping @param buffer [out] The destination for the name @param buflen [in/out] The max size and resulting size (including terminator) of the name @param key A public or private ECC key @return CRYPT_OK if successful */ int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key) { char oidstr[64] = {0}; unsigned long oidlen = sizeof(oidstr); int err, size = 0; LTC_ARGCHK(buffer != NULL); LTC_ARGCHK(buflen != NULL); LTC_ARGCHK(key != NULL); /* Get the OID of the curve */ if ((err = ecc_get_oid_str(oidstr, &oidlen, key)) != CRYPT_OK) goto error; /* Check for three named curves: nistp256, nistp384, nistp521 */ if (XSTRCMP("1.2.840.10045.3.1.7", oidstr) == 0) { /* nistp256 - secp256r1 - OID 1.2.840.10045.3.1.7 */ size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp256"); } else if (XSTRCMP("1.3.132.0.34", oidstr) == 0) { /* nistp384 - secp384r1 - OID 1.3.132.0.34 */ size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp384"); } else if (XSTRCMP("1.3.132.0.35", oidstr) == 0) { /* nistp521 - secp521r1 - OID 1.3.132.0.35 */ size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp521"); } else { /* Otherwise we use the OID... */ size = snprintf(buffer, *buflen, "ecdsa-sha2-%s", oidstr); } /* snprintf returns a negative value on error * or the size that would have been written, but limits to buflen-1 chars plus terminator */ if (size < 0) { err = CRYPT_ERROR; } else if ((unsigned)size >= *buflen) { err = CRYPT_BUFFER_OVERFLOW; } else { err = CRYPT_OK; } *buflen = size + 1; /* the string length + NUL byte */ error: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ecc_verify_hash.c000066400000000000000000000200011464416617300246260ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /** @file ecc_verify_hash.c ECC Crypto, Tom St Denis */ /** Verify an ECC signature in RFC7518 format @param sig The signature to verify @param siglen The length of the signature (octets) @param hash The hash (message digest) that was signed @param hashlen The length of the hash (octets) @param sigformat The format of the signature (ecc_signature_type) @param stat Result of signature, 1==valid, 0==invalid @param key The corresponding public ECC key @return CRYPT_OK if successful (even if the signature is not valid) */ int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, ecc_signature_type sigformat, int *stat, const ecc_key *key) { ecc_point *mG = NULL, *mQ = NULL; void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3; void *mu = NULL, *ma = NULL; void *mp = NULL; int err; unsigned long pbits, pbytes, i, shift_right; unsigned char ch, buf[MAXBLOCKSIZE]; LTC_ARGCHK(sig != NULL); LTC_ARGCHK(hash != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); /* default to invalid signature */ *stat = 0; /* allocate ints */ if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) { return err; } p = key->dp.order; m = key->dp.prime; a = key->dp.A; if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } /* allocate points */ mG = ltc_ecc_new_point(); mQ = ltc_ecc_new_point(); if (mQ == NULL || mG == NULL) { err = CRYPT_MEM; goto error; } if (sigformat == LTC_ECCSIG_ANSIX962) { /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } } else if (sigformat == LTC_ECCSIG_RFC7518) { /* RFC7518 format - raw (r,s) */ i = mp_unsigned_bin_size(key->dp.order); if (siglen != (2 * i)) { err = CRYPT_INVALID_PACKET; goto error; } if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } } else if (sigformat == LTC_ECCSIG_ETH27) { /* Ethereum (v,r,s) format */ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { /* Only valid for secp256k1 - OID 1.3.132.0.10 */ err = CRYPT_ERROR; goto error; } if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ err = CRYPT_INVALID_PACKET; goto error; } if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } } #ifdef LTC_SSH else if (sigformat == LTC_ECCSIG_RFC5656) { char name[64], name2[64]; unsigned long namelen = sizeof(name); unsigned long name2len = sizeof(name2); /* Decode as SSH data sequence, per RFC4251 */ if ((err = ssh_decode_sequence_multi(sig, &siglen, LTC_SSHDATA_STRING, name, &namelen, LTC_SSHDATA_MPINT, r, LTC_SSHDATA_MPINT, s, LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } /* Check curve matches identifier string */ if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { err = CRYPT_INVALID_ARG; goto error; } } #endif else { /* Unknown signature format */ err = CRYPT_ERROR; goto error; } /* check for zero */ if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { err = CRYPT_INVALID_PACKET; goto error; } /* read hash - truncate if needed */ pbits = mp_count_bits(p); pbytes = (pbits+7) >> 3; if (pbits > hashlen*8) { if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } } else if (pbits % 8 == 0) { if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } } else { shift_right = 8 - pbits % 8; for (i=0, ch=0; i> shift_right); } if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } } /* w = s^-1 mod n */ if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } /* u1 = ew */ if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } /* u2 = rw */ if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } /* find mG and mQ */ if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; } /* find the montgomery mp */ if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } /* for curves with a == -3 keep ma == NULL */ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } } /* compute u1*mG + u2*mQ = mG */ if (ltc_mp.ecc_mul2add == NULL) { if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } /* add them */ if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; } /* reduce */ if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; } } else { /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } } /* v = X_x1 mod n */ if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } /* does v == r */ if (mp_cmp(v, r) == LTC_MP_EQ) { *stat = 1; } /* clear up and return */ err = CRYPT_OK; error: if (mG != NULL) ltc_ecc_del_point(mG); if (mQ != NULL) ltc_ecc_del_point(mQ); if (mu != NULL) mp_clear(mu); if (ma != NULL) mp_clear(ma); mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, LTC_NULL); if (mp != NULL) mp_montgomery_free(mp); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c000066400000000000000000000031531464416617300257240ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed) { int err; unsigned char buf[ECC_BUF_SIZE]; unsigned long xsize, ysize; if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW; if ((xsize = mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW; if ((ysize = mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW; if(compressed) { if (*outlen < (1 + size)) { *outlen = 1 + size; return CRYPT_BUFFER_OVERFLOW; } /* store first byte */ out[0] = mp_isodd(y) ? 0x03 : 0x02; /* pad and store x */ zeromem(buf, sizeof(buf)); if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; XMEMCPY(out+1, buf, size); /* adjust outlen */ *outlen = 1 + size; } else { if (*outlen < (1 + 2*size)) { *outlen = 1 + 2*size; return CRYPT_BUFFER_OVERFLOW; } /* store byte 0x04 */ out[0] = 0x04; /* pad and store x */ zeromem(buf, sizeof(buf)); if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; XMEMCPY(out+1, buf, size); /* pad and store y */ zeromem(buf, sizeof(buf)); if ((err = mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err; XMEMCPY(out+1+size, buf, size); /* adjust outlen */ *outlen = 1 + 2*size; } return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c000066400000000000000000000045711464416617300257220ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y) { int err; unsigned long size; void *t1, *t2; /* init key + temporary numbers */ if (mp_init_multi(&t1, &t2, LTC_NULL) != CRYPT_OK) { return CRYPT_MEM; } size = mp_unsigned_bin_size(prime); if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) { /* read uncompressed point */ /* load x */ if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; } /* load y */ if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { goto cleanup; } } else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size && ltc_mp.sqrtmod_prime != NULL) { /* read compressed point - BEWARE: requires sqrtmod_prime */ /* load x */ if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; } /* compute x^3 */ if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; } if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; } /* compute x^3 + a*x */ if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; } if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } /* compute x^3 + a*x + b */ if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } /* compute sqrt(x^3 + a*x + b) */ if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } /* adjust y */ if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) { if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; } } else { if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; } } } else { err = CRYPT_INVALID_PACKET; goto cleanup; } err = CRYPT_OK; cleanup: mp_clear_multi(t1, t2, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c000066400000000000000000000033041464416617300250140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /** Returns whether [x,y] is a point on curve defined by dp @param dp curve parameters @param x x point coordinate @param y y point coordinate @return CRYPT_OK if valid */ int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y) { void *prime, *a, *b, *t1, *t2; int err; prime = dp->prime; b = dp->B; a = dp->A; if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) return err; /* compute y^2 */ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; /* compute x^3 */ if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; /* compute y^2 - x^3 - a*x */ if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; /* adjust range (0, prime) */ while (mp_cmp_d(t1, 0) == LTC_MP_LT) { if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; } while (mp_cmp(t1, prime) != LTC_MP_LT) { if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; } /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } cleanup: mp_clear_multi(t1, t2, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c000066400000000000000000000024171464416617300274150ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MECC /* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates * a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0) */ int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval) { int err; void *x3, *y2; /* trivial case */ if (!mp_iszero(P->z)) { *retval = 0; return CRYPT_OK; } /* point (0,0,0) is not at infinity */ if (mp_iszero(P->x) && mp_iszero(P->y)) { *retval = 0; return CRYPT_OK; } /* initialize */ if ((err = mp_init_multi(&x3, &y2, LTC_NULL)) != CRYPT_OK) goto done; /* compute y^2 */ if ((err = mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup; /* compute x^3 */ if ((err = mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK) goto cleanup; if ((err = mp_mulmod(P->x, x3, modulus, x3)) != CRYPT_OK) goto cleanup; /* test y^2 == x^3 */ err = CRYPT_OK; if ((mp_cmp(x3, y2) == LTC_MP_EQ) && !mp_iszero(y2)) { *retval = 1; } else { *retval = 0; } cleanup: mp_clear_multi(x3, y2, LTC_NULL); done: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_map.c000066400000000000000000000040021464416617300237410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_map.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Map a projective jacbobian point back to affine space @param P [in/out] The point to map @param modulus The modulus of the field the ECC curve is in @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) { void *t1, *t2; int err; LTC_ARGCHK(P != NULL); LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(mp != NULL); if (mp_iszero(P->z)) { return ltc_ecc_set_point_xyz(0, 0, 1, P); } if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { return err; } /* first map z back to normal */ if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; } /* get 1/z */ if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; } /* get 1/z^2 and 1/z^3 */ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; } if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; } if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; } /* multiply against x/y */ if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; } err = CRYPT_OK; done: mp_clear_multi(t1, t2, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c000066400000000000000000000133411464416617300245220ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_mul2add.c ECC Crypto, Shamir's Trick, Tom St Denis */ #ifdef LTC_MECC #ifdef LTC_ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @param A First point to multiply @param kA What to multiple A by @param B Second point to multiply @param kB What to multiple B by @param C [out] Destination point (can overlap with A or B) @param ma ECC curve parameter a in montgomery form @param modulus Modulus for curve @return CRYPT_OK on success */ int ltc_ecc_mul2add(const ecc_point *A, void *kA, const ecc_point *B, void *kB, ecc_point *C, void *ma, void *modulus) { ecc_point *precomp[16]; unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; unsigned x, y; unsigned char *tA, *tB; int err, first; void *mp, *mu; /* argchks */ LTC_ARGCHK(A != NULL); LTC_ARGCHK(B != NULL); LTC_ARGCHK(C != NULL); LTC_ARGCHK(kA != NULL); LTC_ARGCHK(kB != NULL); LTC_ARGCHK(modulus != NULL); /* allocate memory */ tA = XCALLOC(1, ECC_BUF_SIZE); if (tA == NULL) { return CRYPT_MEM; } tB = XCALLOC(1, ECC_BUF_SIZE); if (tB == NULL) { XFREE(tA); return CRYPT_MEM; } /* get sizes */ lenA = mp_unsigned_bin_size(kA); lenB = mp_unsigned_bin_size(kB); len = MAX(lenA, lenB); /* sanity check */ if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) { err = CRYPT_INVALID_ARG; goto ERR_T; } /* extract and justify kA */ mp_to_unsigned_bin(kA, (len - lenA) + tA); /* extract and justify kB */ mp_to_unsigned_bin(kB, (len - lenB) + tB); /* allocate the table */ for (x = 0; x < 16; x++) { precomp[x] = ltc_ecc_new_point(); if (precomp[x] == NULL) { for (y = 0; y < x; ++y) { ltc_ecc_del_point(precomp[y]); } err = CRYPT_MEM; goto ERR_T; } } /* init montgomery reduction */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto ERR_P; } if ((err = mp_init(&mu)) != CRYPT_OK) { goto ERR_MP; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto ERR_MU; } /* copy ones ... */ if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; } if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; } if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; } if ((err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; } if ((err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; } if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; } /* precomp [i,0](A + B) table */ if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } /* precomp [0,i](A + B) table */ if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } /* precomp [i,j](A + B) table (i != 0, j != 0) */ for (x = 1; x < 4; x++) { for (y = 1; y < 4; y++) { if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } } } nibble = 3; first = 1; bitbufA = tA[0]; bitbufB = tB[0]; /* for every byte of the multiplicands */ for (x = 0;; ) { /* grab a nibble */ if (++nibble == 4) { if (x == len) break; bitbufA = tA[x]; bitbufB = tB[x]; nibble = 0; ++x; } /* extract two bits from both, shift/update */ nA = (bitbufA >> 6) & 0x03; nB = (bitbufB >> 6) & 0x03; bitbufA = (bitbufA << 2) & 0xFF; bitbufB = (bitbufB << 2) & 0xFF; /* if both zero, if first, continue */ if ((nA == 0) && (nB == 0) && (first == 1)) { continue; } /* double twice, only if this isn't the first */ if (first == 0) { /* double twice */ if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } } /* if not both zero */ if ((nA != 0) || (nB != 0)) { if (first == 1) { /* if first, copy from table */ first = 0; if ((err = ltc_ecc_copy_point(precomp[nA + (nB<<2)], C)) != CRYPT_OK) { goto ERR_MU; } } else { /* if not first, add from table */ if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } } } } /* reduce to affine */ err = ltc_ecc_map(C, modulus, mp); /* clean up */ ERR_MU: mp_clear(mu); ERR_MP: mp_montgomery_free(mp); ERR_P: for (x = 0; x < 16; x++) { ltc_ecc_del_point(precomp[x]); } ERR_T: #ifdef LTC_CLEAN_STACK zeromem(tA, ECC_BUF_SIZE); zeromem(tB, ECC_BUF_SIZE); #endif XFREE(tA); XFREE(tB); return err; } #endif #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c000066400000000000000000000146231464416617300244730ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_mulmod.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC #ifndef LTC_ECC_TIMING_RESISTANT /* size of sliding window, don't change this! */ #define WINSIZE 4 /** Perform a point multiplication @param k The scalar to multiply by @param G The base point @param R [out] Destination for kG @param modulus The modulus of the field the ECC curve is in @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) @return CRYPT_OK on success */ int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map) { ecc_point *tG, *M[8]; int i, j, err, inf; void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; ltc_mp_digit buf; int first, bitbuf, bitcpy, bitcnt, mode, digidx; LTC_ARGCHK(k != NULL); LTC_ARGCHK(G != NULL); LTC_ARGCHK(R != NULL); LTC_ARGCHK(modulus != NULL); if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* return the point at infinity */ return ltc_ecc_set_point_xyz(1, 1, 0, R); } /* init montgomery reduction */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } /* for curves with a == -3 keep ma == NULL */ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; } if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } } /* alloc ram for window temps */ for (i = 0; i < 8; i++) { M[i] = ltc_ecc_new_point(); if (M[i] == NULL) { for (j = 0; j < i; j++) { ltc_ecc_del_point(M[j]); } err = CRYPT_MEM; goto error; } } /* make a copy of G incase R==G */ tG = ltc_ecc_new_point(); if (tG == NULL) { err = CRYPT_MEM; goto done; } /* tG = G and convert to montgomery */ if (mp_cmp_d(mu, 1) == LTC_MP_EQ) { if ((err = ltc_ecc_copy_point(G, tG)) != CRYPT_OK) { goto done; } } else { if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } } mp_clear(mu); mu = NULL; /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ if ((err = ltc_mp.ecc_ptdbl(tG, M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } /* now find (8+k)G for k=1..7 */ for (j = 9; j < 16; j++) { if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], ma, modulus, mp)) != CRYPT_OK) { goto done; } } /* setup sliding window */ mode = 0; bitcnt = 1; buf = 0; digidx = mp_get_digit_count(k) - 1; bitcpy = bitbuf = 0; first = 1; /* perform ops */ for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { if (digidx == -1) { break; } buf = mp_get_digit(k, digidx); bitcnt = (int) ltc_mp.bits_per_digit; --digidx; } /* grab the next msb from the ltiplicand */ i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1; buf <<= 1; /* skip leading zero bits */ if (mode == 0 && i == 0) { continue; } /* if the bit is zero and mode == 1 then we double */ if (mode == 1 && i == 0) { if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } continue; } /* else we add it to the window */ bitbuf |= (i << (WINSIZE - ++bitcpy)); mode = 2; if (bitcpy == WINSIZE) { /* if this is the first window we do a simple copy */ if (first == 1) { /* R = kG [k = first window] */ if ((err = ltc_ecc_copy_point(M[bitbuf-8], R)) != CRYPT_OK) { goto done; } first = 0; } else { /* normal window */ /* ok window is filled so double as required and add */ /* double first */ for (j = 0; j < WINSIZE; j++) { if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } } /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, ma, modulus, mp)) != CRYPT_OK) { goto done; } } /* empty window and reset */ bitcpy = bitbuf = 0; mode = 1; } } /* if bits remain then double/add */ if (mode == 2 && bitcpy > 0) { /* double then add */ for (j = 0; j < bitcpy; j++) { /* only double if we have had at least one add first */ if (first == 0) { if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } } bitbuf <<= 1; if ((bitbuf & (1 << WINSIZE)) != 0) { if (first == 1){ /* first add, so copy */ if ((err = ltc_ecc_copy_point(tG, R)) != CRYPT_OK) { goto done; } first = 0; } else { /* then add */ if ((err = ltc_mp.ecc_ptadd(R, tG, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } } } } } /* map R back from projective space */ if (map) { err = ltc_ecc_map(R, modulus, mp); } else { err = CRYPT_OK; } done: ltc_ecc_del_point(tG); for (i = 0; i < 8; i++) { ltc_ecc_del_point(M[i]); } error: if (ma != NULL) mp_clear(ma); if (a_plus3 != NULL) mp_clear(a_plus3); if (mu != NULL) mp_clear(mu); if (mp != NULL) mp_montgomery_free(mp); return err; } #endif #undef WINSIZE #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c000066400000000000000000000116021464416617300260340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_mulmod_timing.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC #ifdef LTC_ECC_TIMING_RESISTANT /** Perform a point multiplication (timing resistant) @param k The scalar to multiply by @param G The base point @param R [out] Destination for kG @param a ECC curve parameter a @param modulus The modulus of the field the ECC curve is in @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) @return CRYPT_OK on success */ int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map) { ecc_point *tG, *M[3]; int i, j, err, inf; void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; ltc_mp_digit buf; int bitcnt, mode, digidx; LTC_ARGCHK(k != NULL); LTC_ARGCHK(G != NULL); LTC_ARGCHK(R != NULL); LTC_ARGCHK(modulus != NULL); if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* return the point at infinity */ return ltc_ecc_set_point_xyz(1, 1, 0, R); } /* init montgomery reduction */ if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; } if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } /* for curves with a == -3 keep ma == NULL */ if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; } if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } } /* alloc ram for window temps */ for (i = 0; i < 3; i++) { M[i] = ltc_ecc_new_point(); if (M[i] == NULL) { for (j = 0; j < i; j++) { ltc_ecc_del_point(M[j]); } mp_clear(mu); mp_montgomery_free(mp); return CRYPT_MEM; } } /* make a copy of G incase R==G */ tG = ltc_ecc_new_point(); if (tG == NULL) { err = CRYPT_MEM; goto done; } /* tG = G and convert to montgomery */ if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } mp_clear(mu); mu = NULL; /* calc the M tab */ /* M[0] == G */ if ((err = ltc_ecc_copy_point(tG, M[0])) != CRYPT_OK) { goto done; } /* M[1] == 2G */ if ((err = ltc_mp.ecc_ptdbl(tG, M[1], ma, modulus, mp)) != CRYPT_OK) { goto done; } /* setup sliding window */ mode = 0; bitcnt = 1; buf = 0; digidx = mp_get_digit_count(k) - 1; /* perform ops */ for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { if (digidx == -1) { break; } buf = mp_get_digit(k, digidx); bitcnt = (int) MP_DIGIT_BIT; --digidx; } /* grab the next msb from the ltiplicand */ i = (int)((buf >> (MP_DIGIT_BIT - 1)) & 1); buf <<= 1; if (mode == 0 && i == 0) { /* dummy operations */ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } continue; } if (mode == 0 && i == 1) { mode = 1; /* dummy operations */ if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } continue; } if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], ma, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], ma, modulus, mp)) != CRYPT_OK) { goto done; } } /* copy result out */ if ((err = ltc_ecc_copy_point(M[0], R)) != CRYPT_OK) { goto done; } /* map R back from projective space */ if (map) { err = ltc_ecc_map(R, modulus, mp); } else { err = CRYPT_OK; } done: ltc_ecc_del_point(tG); for (i = 0; i < 3; i++) { ltc_ecc_del_point(M[i]); } error: if (ma != NULL) mp_clear(ma); if (a_plus3 != NULL) mp_clear(a_plus3); if (mu != NULL) mp_clear(mu); if (mp != NULL) mp_montgomery_free(mp); return err; } #endif #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_points.c000066400000000000000000000027601464416617300245110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_points.c ECC Crypto, Tom St Denis */ #ifdef LTC_MECC /** Allocate a new ECC point @return A newly allocated point or NULL on error */ ecc_point *ltc_ecc_new_point(void) { ecc_point *p; p = XCALLOC(1, sizeof(*p)); if (p == NULL) { return NULL; } if (mp_init_multi_size(LTC_MAX_ECC * 2, &p->x, &p->y, &p->z, LTC_NULL) != CRYPT_OK) { XFREE(p); return NULL; } return p; } /** Free an ECC point from memory @param p The point to free */ void ltc_ecc_del_point(ecc_point *p) { /* prevents free'ing null arguments */ if (p != NULL) { mp_clear_multi(p->x, p->y, p->z, LTC_NULL); /* note: p->z may be NULL but that's ok with this function anyways */ XFREE(p); } } int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p) { int err; if ((err = ltc_mp.set_int(p->x, x)) != CRYPT_OK) return err; if ((err = ltc_mp.set_int(p->y, y)) != CRYPT_OK) return err; if ((err = ltc_mp.set_int(p->z, z)) != CRYPT_OK) return err; return CRYPT_OK; } int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst) { int err; if ((err = ltc_mp.copy(src->x, dst->x)) != CRYPT_OK) return err; if ((err = ltc_mp.copy(src->y, dst->y)) != CRYPT_OK) return err; if ((err = ltc_mp.copy(src->z, dst->z)) != CRYPT_OK) return err; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c000066400000000000000000000214771464416617300273760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ltc_ecc_projective_add_point.c ECC Crypto, Tom St Denis */ #if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) /** Add two ECC points @param P The point to add @param Q The point to add @param R [out] The destination of the double @param ma ECC curve parameter a in montgomery form @param modulus The modulus of the field the ECC curve is in @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp) { void *t1, *t2, *x, *y, *z; int err, inf; LTC_ARGCHK(P != NULL); LTC_ARGCHK(Q != NULL); LTC_ARGCHK(R != NULL); LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(mp != NULL); if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, LTC_NULL)) != CRYPT_OK) { return err; } if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* P is point at infinity >> Result = Q */ err = ltc_ecc_copy_point(Q, R); goto done; } if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* Q is point at infinity >> Result = P */ err = ltc_ecc_copy_point(P, R); goto done; } if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) { if (mp_cmp(P->y, Q->y) == LTC_MP_EQ) { /* here P = Q >> Result = 2 * P (use doubling) */ mp_clear_multi(t1, t2, x, y, z, LTC_NULL); return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp); } if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(P->y, t1) == LTC_MP_EQ) { /* here Q = -P >>> Result = the point at infinity */ err = ltc_ecc_set_point_xyz(1, 1, 0, R); goto done; } } if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; } if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; } if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; } /* if Z is one then these are no-operations */ if (Q->z != NULL) { /* T1 = Z' * Z' */ if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* X = X * T1 */ if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = Z' * T1 */ if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* Y = Y * T1 */ if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; } } /* T1 = Z*Z */ if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* T2 = X' * T1 */ if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = Z * T1 */ if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = Y' * T1 */ if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* Y = Y - T1 */ if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; } if (mp_cmp_d(y, 0) == LTC_MP_LT) { if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } } /* T1 = 2T1 */ if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } /* T1 = Y + T1 */ if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } /* X = X - T2 */ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } if (mp_cmp_d(x, 0) == LTC_MP_LT) { if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } } /* T2 = 2T2 */ if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; } if (mp_cmp(t2, modulus) != LTC_MP_LT) { if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } } /* T2 = X + T2 */ if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; } if (mp_cmp(t2, modulus) != LTC_MP_LT) { if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } } /* if Z' != 1 */ if (Q->z != NULL) { /* Z = Z * Z' */ if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } } /* Z = Z * X */ if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = T1 * X */ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* X = X * X */ if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } /* T2 = T2 * x */ if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = T1 * X */ if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* X = Y*Y */ if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } /* X = X - T2 */ if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } if (mp_cmp_d(x, 0) == LTC_MP_LT) { if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } } /* T2 = T2 - X */ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } if (mp_cmp_d(t2, 0) == LTC_MP_LT) { if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } } /* T2 = T2 - X */ if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } if (mp_cmp_d(t2, 0) == LTC_MP_LT) { if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } } /* T2 = T2 * Y */ if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* Y = T2 - T1 */ if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; } if (mp_cmp_d(y, 0) == LTC_MP_LT) { if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } } /* Y = Y/2 */ if (mp_isodd(y)) { if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } } if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; } if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; } if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; } if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; } err = CRYPT_OK; done: mp_clear_multi(t1, t2, x, y, z, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c000066400000000000000000000176471464416617300274130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /* ### Point doubling in Jacobian coordinate system ### * * let us have a curve: y^2 = x^3 + a*x + b * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 * * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: * Xr = M^2 - 2*S * Yr = M * (S - Xr) - 8*T * Zr = 2 * Yp * Zp * * M = 3 * Xp^2 + a*Zp^4 * T = Yp^4 * S = 4 * Xp * Yp^2 * * SPECIAL CASE: when a == -3 we can compute M as * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) */ /** @file ltc_ecc_projective_dbl_point.c ECC Crypto, Tom St Denis */ #if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) /** Double an ECC point @param P The point to double @param R [out] The destination of the double @param ma ECC curve parameter a in montgomery form @param modulus The modulus of the field the ECC curve is in @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp) { void *t1, *t2; int err, inf; LTC_ARGCHK(P != NULL); LTC_ARGCHK(R != NULL); LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(mp != NULL); if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { return err; } if (P != R) { if ((err = ltc_ecc_copy_point(P, R)) != CRYPT_OK) { goto done; } } if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; if (inf) { /* if P is point at infinity >> Result = point at infinity */ err = ltc_ecc_set_point_xyz(1, 1, 0, R); goto done; } /* t1 = Z * Z */ if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* Z = Y * Z */ if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; } /* Z = 2Z */ if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; } if (mp_cmp(R->z, modulus) != LTC_MP_LT) { if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; } } if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ /* T2 = X - T1 */ if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } if (mp_cmp_d(t2, 0) == LTC_MP_LT) { if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } } /* T1 = X + T1 */ if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } /* T2 = T1 * T2 */ if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = 2T2 */ if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } /* T1 = T1 + T2 */ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } } else { /* T2 = T1 * T1 */ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = T2 * a */ if ((err = mp_mul(t2, ma, t1)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } /* T2 = X * X */ if ((err = mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* T1 = T2 + T1 */ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } /* T1 = T2 + T1 */ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } /* T1 = T2 + T1 */ if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } if (mp_cmp(t1, modulus) != LTC_MP_LT) { if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } } } /* Y = 2Y */ if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; } if (mp_cmp(R->y, modulus) != LTC_MP_LT) { if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } } /* Y = Y * Y */ if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } /* T2 = Y * Y */ if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } /* T2 = T2/2 */ if (mp_isodd(t2)) { if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } } if ((err = mp_div_2(t2, t2)) != CRYPT_OK) { goto done; } /* Y = Y * X */ if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } /* X = T1 * T1 */ if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; } /* X = X - Y */ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } if (mp_cmp_d(R->x, 0) == LTC_MP_LT) { if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } } /* X = X - Y */ if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } if (mp_cmp_d(R->x, 0) == LTC_MP_LT) { if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } } /* Y = Y - X */ if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } } /* Y = Y * T1 */ if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } /* Y = Y - T2 */ if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; } if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } } err = CRYPT_OK; done: mp_clear_multi(t2, t1, LTC_NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c000066400000000000000000000031331464416617300253440ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /* origin of this code - OLPC */ #ifdef LTC_MECC /** Verify a key according to ANSI spec @param key The key to validate @return CRYPT_OK if successful */ int ltc_ecc_verify_key(const ecc_key *key) { int err, inf; ecc_point *point; void *prime = key->dp.prime; void *order = key->dp.order; void *a = key->dp.A; /* Test 1: Are the x and y points of the public key in the field? */ if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) { if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) || (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) || (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) || (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) || (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y)) ) { err = CRYPT_INVALID_PACKET; goto done2; } } /* Test 2: is the public key on the curve? */ if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; } /* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */ point = ltc_ecc_new_point(); if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; } err = ltc_ecc_is_point_at_infinity(point, prime, &inf); if (err != CRYPT_OK || inf) { err = CRYPT_ERROR; } else { err = CRYPT_OK; } done1: ltc_ecc_del_point(point); done2: return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/000077500000000000000000000000001464416617300216145ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_export.c000066400000000000000000000016201464416617300243560ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_export.c Export an Ed25519 key to a binary packet, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Export an Ed25519 key to a binary packet @param out [out] The destination for the key @param outlen [in/out] The max size and resulting size of the Ed25519 key @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) @param key The key you wish to export @return CRYPT_OK if successful */ int ed25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key) { LTC_ARGCHK(key != NULL); if (key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; return ec25519_export(out, outlen, which, key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import.c000066400000000000000000000017051464416617300243530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_import.c Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Import an Ed25519 public key @param in The packet to read @param inlen The length of the input packet @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) { int err; unsigned long key_len; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); key_len = sizeof(key->pub); if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { key->type = PK_PUBLIC; key->algo = LTC_OID_ED25519; } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c000066400000000000000000000017251464416617300254650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_import_pkcs8.c Import an Ed25519 key in PKCS#8 format, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Import an Ed25519 private key in PKCS#8 format @param in The DER-encoded PKCS#8-formatted private key @param inlen The length of the input data @param passwd The password to decrypt the private key @param passwdlen Password's length (octets) @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key) { return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_ED25519, tweetnacl_crypto_sk_to_pk, key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c000066400000000000000000000020401464416617300252150ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_import_raw.c Set the parameters of an Ed25519 key, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Set the parameters of an Ed25519 key @param in The key @param inlen The length of the key @param which Which type of key (PK_PRIVATE or PK_PUBLIC) @param key [out] Destination of the key @return CRYPT_OK if successful */ int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) { LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen == 32uL); LTC_ARGCHK(key != NULL); if (which == PK_PRIVATE) { XMEMCPY(key->priv, in, sizeof(key->priv)); tweetnacl_crypto_sk_to_pk(key->pub, key->priv); } else if (which == PK_PUBLIC) { XMEMCPY(key->pub, in, sizeof(key->pub)); } else { return CRYPT_INVALID_ARG; } key->algo = LTC_OID_ED25519; key->type = which; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c000066400000000000000000000025541464416617300251430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_import_x509.c Import an Ed25519 key from a X.509 certificate, Steffen Jaeckel */ #ifdef LTC_CURVE25519 static int s_ed25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) { if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; XMEMCPY(key->pub, in, sizeof(key->pub)); return CRYPT_OK; } /** Import an Ed25519 public key from a X.509 certificate @param in The DER encoded X.509 certificate @param inlen The length of the certificate @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); if ((err = x509_decode_public_key_from_certificate(in, inlen, LTC_OID_ED25519, LTC_ASN1_EOL, NULL, NULL, (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) { return err; } key->type = PK_PUBLIC; key->algo = LTC_OID_ED25519; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_make_key.c000066400000000000000000000014171464416617300246260ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_make_key.c Create an Ed25519 key, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Create an Ed25519 key @param prng An active PRNG state @param wprng The index of the PRNG desired @param key [out] Destination of a newly created private key pair @return CRYPT_OK if successful */ int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key) { int err; LTC_ARGCHK(key != NULL); if ((err = tweetnacl_crypto_sign_keypair(prng, wprng, key->pub, key->priv)) != CRYPT_OK) { return err; } key->type = PK_PRIVATE; key->algo = LTC_OID_ED25519; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_sign.c000066400000000000000000000104021464416617300237730ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_shared_secret.c Create an Ed25519 signature, Steffen Jaeckel */ #ifdef LTC_CURVE25519 static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const unsigned char *ctx, unsigned long ctxlen, const curve25519_key *private_key) { unsigned char *s; unsigned long long smlen; int err; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(sig != NULL); LTC_ARGCHK(siglen != NULL); LTC_ARGCHK(private_key != NULL); if (private_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; if (*siglen < 64uL) { *siglen = 64uL; return CRYPT_BUFFER_OVERFLOW; } smlen = msglen + 64; s = XMALLOC(smlen); if (s == NULL) return CRYPT_MEM; err = tweetnacl_crypto_sign(s, &smlen, msg, msglen, private_key->priv, private_key->pub, ctx, ctxlen); XMEMCPY(sig, s, 64uL); *siglen = 64uL; #ifdef LTC_CLEAN_STACK zeromem(s, smlen); #endif XFREE(s); return err; } /** Create an Ed25519ctx signature. @param msg The data to be signed @param msglen [in] The size of the date to be signed @param sig [out] The destination of the shared data @param siglen [in/out] The max size and resulting size of the shared data. @param ctx [in] The context is a constant null terminated string @param private_key The private Ed25519 key in the pair @return CRYPT_OK if successful */ int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const unsigned char *ctx, unsigned long ctxlen, const curve25519_key *private_key) { int err; unsigned char ctx_prefix[292]; unsigned long ctx_prefix_size = sizeof(ctx_prefix); LTC_ARGCHK(ctx != NULL); if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK) return err; return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key); } /** Create an Ed25519ph signature. @param msg The data to be signed @param msglen [in] The size of the date to be signed @param sig [out] The destination of the shared data @param siglen [in/out] The max size and resulting size of the shared data. @param ctx [in] The context is a constant null terminated string @param private_key The private Ed25519 key in the pair @return CRYPT_OK if successful */ int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const unsigned char *ctx, unsigned long ctxlen, const curve25519_key *private_key) { int err; unsigned char msg_hash[64]; unsigned char ctx_prefix[292]; unsigned long ctx_prefix_size = sizeof(ctx_prefix); if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) return err; if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) return err; return s_ed25519_sign(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, private_key); } /** Create an Ed25519 signature. @param msg The data to be signed @param msglen [in] The size of the date to be signed @param sig [out] The destination of the shared data @param siglen [in/out] The max size and resulting size of the shared data. @param private_key The private Ed25519 key in the pair @return CRYPT_OK if successful */ int ed25519_sign(const unsigned char *msg, unsigned long msglen, unsigned char *sig, unsigned long *siglen, const curve25519_key *private_key) { return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/ed25519/ed25519_verify.c000066400000000000000000000114551464416617300243500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file ed25519_verify.c Verify an Ed25519 signature, Steffen Jaeckel */ #ifdef LTC_CURVE25519 static int s_ed25519_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, const unsigned char *ctx, unsigned long ctxlen, int *stat, const curve25519_key *public_key) { unsigned char* m; unsigned long long mlen; int err; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(sig != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(public_key != NULL); *stat = 0; if (siglen != 64uL) return CRYPT_INVALID_ARG; if (public_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; mlen = msglen + siglen; if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW; m = XMALLOC(mlen); if (m == NULL) return CRYPT_MEM; XMEMCPY(m, sig, siglen); XMEMCPY(m + siglen, msg, msglen); err = tweetnacl_crypto_sign_open(stat, m, &mlen, m, mlen, ctx, ctxlen, public_key->pub); #ifdef LTC_CLEAN_STACK zeromem(m, msglen + siglen); #endif XFREE(m); return err; } /** Verify an Ed25519ctx signature. @param msg [in] The data to be verified @param msglen [in] The size of the data to be verified @param sig [in] The signature to be verified @param siglen [in] The size of the signature to be verified @param ctx [in] The context @param ctxlen [in] The size of the context @param stat [out] The result of the signature verification, 1==valid, 0==invalid @param public_key [in] The public Ed25519 key in the pair @return CRYPT_OK if successful */ int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, const unsigned char *ctx, unsigned long ctxlen, int *stat, const curve25519_key *public_key) { unsigned char ctx_prefix[292]; unsigned long ctx_prefix_size = sizeof(ctx_prefix); LTC_ARGCHK(ctx != NULL); if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK) return CRYPT_INVALID_ARG; return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); } /** Verify an Ed25519ph signature. @param msg [in] The data to be verified @param msglen [in] The size of the data to be verified @param sig [in] The signature to be verified @param siglen [in] The size of the signature to be verified @param ctx [in] The context @param ctxlen [in] The size of the context @param stat [out] The result of the signature verification, 1==valid, 0==invalid @param public_key [in] The public Ed25519 key in the pair @return CRYPT_OK if successful */ int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, const unsigned char *ctx, unsigned long ctxlen, int *stat, const curve25519_key *public_key) { int err; unsigned char msg_hash[64]; unsigned char ctx_prefix[292]; unsigned long ctx_prefix_size = sizeof(ctx_prefix); if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) return err; if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) return err; return s_ed25519_verify(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); } /** Verify an Ed25519 signature. @param msg [in] The data to be verified @param msglen [in] The size of the data to be verified @param sig [in] The signature to be verified @param siglen [in] The size of the signature to be verified @param stat [out] The result of the signature verification, 1==valid, 0==invalid @param public_key [in] The public Ed25519 key in the pair @return CRYPT_OK if successful */ int ed25519_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, int *stat, const curve25519_key *public_key) { return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/000077500000000000000000000000001464416617300216375ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c000066400000000000000000000015631464416617300243040ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_i2osp.c Integer to Octet I2OSP, Tom St Denis */ #ifdef LTC_PKCS_1 /* always stores the same # of bytes, pads with leading zero bytes as required */ /** PKCS #1 Integer to binary @param n The integer to store @param modulus_len The length of the RSA modulus @param out [out] The destination for the integer @return CRYPT_OK if successful */ int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) { unsigned long size; size = mp_unsigned_bin_size(n); if (size > modulus_len) { return CRYPT_BUFFER_OVERFLOW; } /* store it */ zeromem(out, modulus_len); return mp_to_unsigned_bin(n, out+(modulus_len-size)); } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c000066400000000000000000000044071464416617300241020ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_mgf1.c The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis */ #ifdef LTC_PKCS_1 /** Perform PKCS #1 MGF1 (internal) @param hash_idx The index of the hash desired @param seed The seed for MGF1 @param seedlen The length of the seed @param mask [out] The destination @param masklen The length of the mask desired @return CRYPT_OK if successful */ int pkcs_1_mgf1(int hash_idx, const unsigned char *seed, unsigned long seedlen, unsigned char *mask, unsigned long masklen) { unsigned long hLen, x; ulong32 counter; int err; hash_state *md; unsigned char *buf; LTC_ARGCHK(seed != NULL); LTC_ARGCHK(mask != NULL); /* ensure valid hash */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } /* get hash output size */ hLen = hash_descriptor[hash_idx]->hashsize; /* allocate memory */ md = XMALLOC(sizeof(hash_state)); buf = XMALLOC(hLen); if (md == NULL || buf == NULL) { if (md != NULL) { XFREE(md); } if (buf != NULL) { XFREE(buf); } return CRYPT_MEM; } /* start counter */ counter = 0; while (masklen > 0) { /* handle counter */ STORE32H(counter, buf); ++counter; /* get hash of seed || counter */ if ((err = hash_descriptor[hash_idx]->init(md)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(md, seed, seedlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(md, buf, 4)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->done(md, buf)) != CRYPT_OK) { goto LBL_ERR; } /* store it */ for (x = 0; x < hLen && masklen > 0; x++, masklen--) { *mask++ = buf[x]; } } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, hLen); zeromem(md, sizeof(hash_state)); #endif XFREE(buf); XFREE(md); return err; } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c000066400000000000000000000117121464416617300254740ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_oaep_decode.c OAEP Padding for PKCS #1, Tom St Denis */ #ifdef LTC_PKCS_1 /** PKCS #1 v2.00 OAEP decode @param msg The encoded data to decode @param msglen The length of the encoded data (octets) @param lparam The session or system data (can be NULL) @param lparamlen The length of the lparam @param modulus_bitlen The bit length of the RSA modulus @param mgf_hash The hash algorithm used for the MGF @param lparam_hash The hash algorithm used when hashing the lparam (can be -1) @param out [out] Destination of decoding @param outlen [in/out] The max size and resulting size of the decoding @param res [out] Result of decoding, 1==valid, 0==invalid @return CRYPT_OK if successful */ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, int mgf_hash, int lparam_hash, unsigned char *out, unsigned long *outlen, int *res) { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; int err, ret, lparam_hash_used; LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(res != NULL); /* default to invalid packet */ *res = 0; /* test valid hash */ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { return err; } if (lparam_hash != -1) { if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) { return err; } lparam_hash_used = lparam_hash; } else { lparam_hash_used = mgf_hash; } hLen = hash_descriptor[lparam_hash_used]->hashsize; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test hash/message size */ if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); seed = XMALLOC(hLen); if (DB == NULL || mask == NULL || seed == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (seed != NULL) { XFREE(seed); } return CRYPT_MEM; } /* ok so it's now in the form 0x00 || maskedseed || maskedDB 1 || hLen || modulus_len - hLen - 1 */ ret = CRYPT_OK; /* must have leading 0x00 byte */ if (msg[0] != 0x00) { ret = CRYPT_INVALID_PACKET; } /* now read the masked seed */ x = 1; XMEMCPY(seed, msg + x, hLen); x += hLen; /* now read the masked DB */ XMEMCPY(DB, msg + x, modulus_len - hLen - 1); x += modulus_len - hLen - 1; /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } /* XOR against seed */ for (y = 0; y < hLen; y++) { seed[y] ^= mask[y]; } /* compute MGF1 of seed (k - hlen - 1) */ if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ /* compute lhash and store it in seed [reuse temps!] */ x = modulus_len; if (lparam != NULL) { if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ if ((err = hash_memory(lparam_hash_used, DB, 0, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } /* compare the lhash'es */ if (XMEM_NEQ(seed, DB, hLen) != 0) { ret = CRYPT_INVALID_PACKET; } /* now zeroes before a 0x01 */ for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { /* step... */ } /* error if wasn't 0x01 */ if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { ret = CRYPT_INVALID_PACKET; } /* rest is the message (and skip 0x01) */ if ((modulus_len - hLen - 1 - ++x) > *outlen) { ret = CRYPT_INVALID_PACKET; } if (ret == CRYPT_OK) { /* copy message */ *outlen = modulus_len - hLen - 1 - x; XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); /* valid packet */ *res = 1; } err = ret; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(seed, hLen); zeromem(mask, modulus_len); #endif XFREE(seed); XFREE(mask); XFREE(DB); return err; } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c000066400000000000000000000111531464416617300255050ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_oaep_encode.c OAEP Padding for PKCS #1, Tom St Denis */ #ifdef LTC_PKCS_1 /** PKCS #1 v2.00 OAEP encode @param msg The data to encode @param msglen The length of the data to encode (octets) @param lparam A session or system parameter (can be NULL) @param lparamlen The length of the lparam data @param modulus_bitlen The bit length of the RSA modulus @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param out [out] The destination for the encoded data @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, prng_state *prng, int prng_idx, int mgf_hash, int lparam_hash, unsigned char *out, unsigned long *outlen) { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; int err, lparam_hash_used; LTC_ARGCHK((msglen == 0) || (msg != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* test valid hash */ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { return err; } if (lparam_hash != -1) { if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) { return err; } lparam_hash_used = lparam_hash; } else { lparam_hash_used = mgf_hash; } /* valid prng */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[lparam_hash_used]->hashsize; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test message size */ if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); seed = XMALLOC(hLen); if (DB == NULL || mask == NULL || seed == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (seed != NULL) { XFREE(seed); } return CRYPT_MEM; } /* get lhash */ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ x = modulus_len; if (lparam != NULL) { if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ if ((err = hash_memory(lparam_hash_used, DB, 0, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } /* append PS then 0x01 (to lhash) */ x = hLen; y = modulus_len - msglen - 2*hLen - 2; XMEMSET(DB+x, 0, y); x += y; /* 0x01 byte */ DB[x++] = 0x01; if (msglen != 0) { /* message (length = msglen) */ XMEMCPY(DB+x, msg, msglen); x += msglen; } /* now choose a random seed */ if (prng_descriptor[prng_idx]->read(seed, hLen, prng) != hLen) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } /* compute MGF1 of seed (k - hlen - 1) */ if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* compute MGF1 of maskedDB (hLen) */ if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } /* XOR against seed */ for (y = 0; y < hLen; y++) { seed[y] ^= mask[y]; } /* create string of length modulus_len */ if (*outlen < modulus_len) { *outlen = modulus_len; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* start output which is 0x00 || maskedSeed || maskedDB */ x = 0; out[x++] = 0x00; XMEMCPY(out+x, seed, hLen); x += hLen; XMEMCPY(out+x, DB, modulus_len - hLen - 1); x += modulus_len - hLen - 1; *outlen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(seed, hLen); zeromem(mask, modulus_len); #endif XFREE(seed); XFREE(mask); XFREE(DB); return err; } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c000066400000000000000000000011201464416617300242710ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_os2ip.c Octet to Integer OS2IP, Tom St Denis */ #ifdef LTC_PKCS_1 /** Read a binary string into an mp_int @param n [out] The mp_int destination @param in The binary string to read @param inlen The length of the binary string @return CRYPT_OK if successful */ int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen) { return mp_read_unsigned_bin(n, in, inlen); } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c000066400000000000000000000110261464416617300253530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include #include "tomcrypt_private.h" /** @file pkcs_1_pss_decode.c PKCS #1 PSS Signature Padding, Tom St Denis */ #ifdef LTC_PKCS_1 /** PKCS #1 v2.00 PSS decode @param msghash The hash to verify @param msghashlen The length of the hash (octets) @param sig The signature data (encoded data) @param siglen The length of the signature data (octets) @param saltlen The length of the salt used (octets) @param hash_idx The index of the hash desired @param modulus_bitlen The bit length of the RSA modulus @param res [out] The result of the comparison, 1==valid, 0==invalid @return CRYPT_OK if successful (even if the comparison failed) */ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, unsigned long saltlen, int hash_idx, unsigned long modulus_bitlen, int *res) { unsigned char *DB, *mask, *salt, *hash; unsigned long x, y, hLen, modulus_len; int err; hash_state md; LTC_ARGCHK(msghash != NULL); LTC_ARGCHK(res != NULL); /* default to invalid */ *res = 0; /* ensure hash is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx]->hashsize; modulus_bitlen--; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt/hash of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); salt = XMALLOC(modulus_len); hash = XMALLOC(modulus_len); if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (salt != NULL) { XFREE(salt); } if (hash != NULL) { XFREE(hash); } return CRYPT_MEM; } /* ensure the 0xBC byte */ if (sig[siglen-1] != 0xBC) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* copy out the DB */ x = 0; XMEMCPY(DB, sig + x, modulus_len - hLen - 1); x += modulus_len - hLen - 1; /* copy out the hash */ XMEMCPY(hash, sig + x, hLen); /* x += hLen; */ /* check the MSB */ if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen)))) != 0) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* generate mask of length modulus_len - hLen - 1 from hash */ if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* now clear the first byte [make sure smaller than modulus] */ DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen)); /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ /* check for zeroes and 0x01 */ for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { if (DB[x] != 0x00) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } } /* check for the 0x01 */ if (DB[x++] != 0x01) { err = CRYPT_INVALID_PACKET; goto LBL_ERR; } /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ if ((err = hash_descriptor[hash_idx]->init(&md)) != CRYPT_OK) { goto LBL_ERR; } zeromem(mask, 8); if ((err = hash_descriptor[hash_idx]->process(&md, mask, 8)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(&md, msghash, msghashlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(&md, DB+x, saltlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->done(&md, mask)) != CRYPT_OK) { goto LBL_ERR; } /* mask == hash means valid signature */ if (FTMN_CALLEE_DONE_MEMCMP(XMEM_NEQ, mask, hash, hLen) == 0) { *res = 1; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(mask, modulus_len); zeromem(salt, modulus_len); zeromem(hash, modulus_len); #endif XFREE(hash); XFREE(salt); XFREE(mask); XFREE(DB); return err; } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c000066400000000000000000000111021464416617300253600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_pss_encode.c PKCS #1 PSS Signature Padding, Tom St Denis */ #ifdef LTC_PKCS_1 /** PKCS #1 v2.00 Signature Encoding @param msghash The hash to encode @param msghashlen The length of the hash (octets) @param saltlen The length of the salt desired (octets) @param prng An active PRNG context @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param modulus_bitlen The bit length of the RSA modulus @param out [out] The destination of the encoding @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, unsigned long saltlen, prng_state *prng, int prng_idx, int hash_idx, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen) { unsigned char *DB, *mask, *salt, *hash; unsigned long x, y, hLen, modulus_len; int err; hash_state md; LTC_ARGCHK(msghash != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* ensure hash and PRNG are valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } hLen = hash_descriptor[hash_idx]->hashsize; modulus_bitlen--; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { return CRYPT_PK_INVALID_SIZE; } /* allocate ram for DB/mask/salt/hash of size modulus_len */ DB = XMALLOC(modulus_len); mask = XMALLOC(modulus_len); salt = XMALLOC(modulus_len); hash = XMALLOC(modulus_len); if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { if (DB != NULL) { XFREE(DB); } if (mask != NULL) { XFREE(mask); } if (salt != NULL) { XFREE(salt); } if (hash != NULL) { XFREE(hash); } return CRYPT_MEM; } /* generate random salt */ if (saltlen > 0) { if (prng_descriptor[prng_idx]->read(salt, saltlen, prng) != saltlen) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } } /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ if ((err = hash_descriptor[hash_idx]->init(&md)) != CRYPT_OK) { goto LBL_ERR; } zeromem(DB, 8); if ((err = hash_descriptor[hash_idx]->process(&md, DB, 8)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(&md, msghash, msghashlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->process(&md, salt, saltlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hash_descriptor[hash_idx]->done(&md, hash)) != CRYPT_OK) { goto LBL_ERR; } /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ x = 0; XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2); x += modulus_len - saltlen - hLen - 2; DB[x++] = 0x01; XMEMCPY(DB + x, salt, saltlen); /* x += saltlen; */ /* generate mask of length modulus_len - hLen - 1 from hash */ if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } /* xor against DB */ for (y = 0; y < (modulus_len - hLen - 1); y++) { DB[y] ^= mask[y]; } /* output is DB || hash || 0xBC */ if (*outlen < modulus_len) { *outlen = modulus_len; err = CRYPT_BUFFER_OVERFLOW; goto LBL_ERR; } /* DB len = modulus_len - hLen - 1 */ y = 0; XMEMCPY(out + y, DB, modulus_len - hLen - 1); y += modulus_len - hLen - 1; /* hash */ XMEMCPY(out + y, hash, hLen); y += hLen; /* 0xBC */ out[y] = 0xBC; /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen); /* store output size */ *outlen = modulus_len; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(DB, modulus_len); zeromem(mask, modulus_len); zeromem(salt, modulus_len); zeromem(hash, modulus_len); #endif XFREE(hash); XFREE(salt); XFREE(mask); XFREE(DB); return err; } #endif /* LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c000066400000000000000000000052301464416617300253200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file pkcs_1_v1_5_decode.c * * PKCS #1 v1.5 Padding. (Andreas Lange) */ #ifdef LTC_PKCS_1 /** @brief PKCS #1 v1.5 decode. * * @param msg The encoded data to decode * @param msglen The length of the encoded data (octets) * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) * @param modulus_bitlen The bit length of the RSA modulus * @param out [out] Destination of decoding * @param outlen [in/out] The max size and resulting size of the decoding * @param is_valid [out] Boolean whether the padding was valid * * @return CRYPT_OK if successful */ int pkcs_1_v1_5_decode(const unsigned char *msg, unsigned long msglen, int block_type, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen, int *is_valid) { unsigned long modulus_len, ps_len, i; int result; /* default to invalid packet */ *is_valid = 0; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test message size */ if ((msglen > modulus_len) || (modulus_len < 11)) { return CRYPT_PK_INVALID_SIZE; } result = CRYPT_OK; /* separate encoded message */ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) { result = CRYPT_INVALID_PACKET; } if (block_type == LTC_PKCS_1_EME) { for (i = 2; i < modulus_len; i++) { /* separator */ if (msg[i] == 0x00) { break; } } ps_len = i++ - 2; if (i > modulus_len) { /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ result = CRYPT_INVALID_PACKET; } } else { for (i = 2; i < modulus_len - 1; i++) { if (msg[i] != 0xFF) { break; } } /* separator check */ if (msg[i] != 0) { /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ result = CRYPT_INVALID_PACKET; } ps_len = i - 2; } if (ps_len < 8) { /* The length of ps is less than 8 octets. */ result = CRYPT_INVALID_PACKET; } if (*outlen < (msglen - (2 + ps_len + 1))) { result = CRYPT_INVALID_PACKET; } if (result == CRYPT_OK) { *outlen = (msglen - (2 + ps_len + 1)); XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); /* valid packet */ *is_valid = 1; } return result; } /* pkcs_1_v1_5_decode */ #endif /* #ifdef LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c000066400000000000000000000060521464416617300253350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /*! \file pkcs_1_v1_5_encode.c * * PKCS #1 v1.5 Padding (Andreas Lange) */ #ifdef LTC_PKCS_1 /*! \brief PKCS #1 v1.5 encode. * * \param msg The data to encode * \param msglen The length of the data to encode (octets) * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) * \param modulus_bitlen The bit length of the RSA modulus * \param prng An active PRNG state (only for LTC_PKCS_1_EME) * \param prng_idx The index of the PRNG desired (only for LTC_PKCS_1_EME) * \param out [out] The destination for the encoded data * \param outlen [in/out] The max size and resulting size of the encoded data * * \return CRYPT_OK if successful */ int pkcs_1_v1_5_encode(const unsigned char *msg, unsigned long msglen, int block_type, unsigned long modulus_bitlen, prng_state *prng, int prng_idx, unsigned char *out, unsigned long *outlen) { unsigned long modulus_len, ps_len, i; unsigned char *ps; int result; LTC_ARGCHK((msglen == 0) || (msg != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* valid block_type? */ if ((block_type != LTC_PKCS_1_EMSA) && (block_type != LTC_PKCS_1_EME)) { return CRYPT_PK_INVALID_PADDING; } if (block_type == LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */ if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) { return result; } } modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test message size */ if ((msglen + 11) > modulus_len) { return CRYPT_PK_INVALID_SIZE; } if (*outlen < modulus_len) { *outlen = modulus_len; result = CRYPT_BUFFER_OVERFLOW; goto bail; } /* generate an octets string PS */ ps = &out[2]; ps_len = modulus_len - msglen - 3; if (block_type == LTC_PKCS_1_EME) { /* now choose a random ps */ if (prng_descriptor[prng_idx]->read(ps, ps_len, prng) != ps_len) { result = CRYPT_ERROR_READPRNG; goto bail; } /* transform zero bytes (if any) to non-zero random bytes */ for (i = 0; i < ps_len; i++) { while (ps[i] == 0) { if (prng_descriptor[prng_idx]->read(&ps[i], 1, prng) != 1) { result = CRYPT_ERROR_READPRNG; goto bail; } } } } else { XMEMSET(ps, 0xFF, ps_len); } /* create string of length modulus_len */ out[0] = 0x00; out[1] = (unsigned char)block_type; /* block_type 1 or 2 */ out[2 + ps_len] = 0x00; if (msglen != 0) { XMEMCPY(&out[2 + ps_len + 1], msg, msglen); } *outlen = modulus_len; result = CRYPT_OK; bail: return result; } /* pkcs_1_v1_5_encode */ #endif /* #ifdef LTC_PKCS_1 */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/000077500000000000000000000000001464416617300214035ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c000066400000000000000000000057051464416617300247450ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_decrypt_key.c RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** PKCS #1 decrypt then v1.5 or OAEP depad @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext (octets) @param lparam The system "lparam" value @param lparamlen The length of the lparam value (octets) @param mgf_hash The hash algorithm used for the MGF @param lparam_hash The hash algorithm used when hashing the lparam (can be -1) @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) @param stat [out] Result of the decryption, 1==valid, 0==invalid @param key The corresponding private RSA key @return CRYPT_OK if succcessul (even if invalid) */ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, int mgf_hash, int lparam_hash, int padding, int *stat, const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmp; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); /* default to invalid */ *stat = 0; /* valid padding? */ if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_OAEP)) { return CRYPT_PK_INVALID_PADDING; } if (padding == LTC_PKCS_1_OAEP) { /* valid hash ? */ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { return err; } } /* get modulus len in bits */ modulus_bitlen = mp_count_bits( (key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size( (key->N)); if (modulus_bytelen != inlen) { return CRYPT_INVALID_PACKET; } /* allocate ram */ tmp = XMALLOC(inlen); if (tmp == NULL) { return CRYPT_MEM; } /* rsa decode the packet */ x = inlen; if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { XFREE(tmp); return err; } if (padding == LTC_PKCS_1_OAEP) { /* now OAEP decode the packet */ err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash, lparam_hash, out, outlen, stat); } else { /* now PKCS #1 v1.5 depad the packet */ err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); } XFREE(tmp); return err; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c000066400000000000000000000057451464416617300247630ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_encrypt_key.c RSA PKCS #1 encryption, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** (PKCS #1 v2.0) OAEP pad then encrypt @param in The plaintext @param inlen The length of the plaintext (octets) @param out [out] The ciphertext @param outlen [in/out] The max size and resulting size of the ciphertext @param lparam The system "lparam" for the encryption @param lparamlen The length of lparam (octets) @param prng An active PRNG @param prng_idx The index of the desired prng @param hash_idx The index of the desired hash @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) @param key The RSA key to encrypt to @return CRYPT_OK if successful */ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, prng_state *prng, int prng_idx, int mgf_hash, int lparam_hash, int padding, const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; LTC_ARGCHK((inlen == 0) || (in != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* valid padding? */ if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_OAEP)) { return CRYPT_PK_INVALID_PADDING; } /* valid prng? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } if (padding == LTC_PKCS_1_OAEP) { /* valid hash? */ if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { return err; } } /* get modulus len in bits */ modulus_bitlen = mp_count_bits( (key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size( (key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; return CRYPT_BUFFER_OVERFLOW; } if (padding == LTC_PKCS_1_OAEP) { /* OAEP pad the key */ x = *outlen; if ((err = pkcs_1_oaep_encode(in, inlen, lparam, lparamlen, modulus_bitlen, prng, prng_idx, mgf_hash, lparam_hash, out, &x)) != CRYPT_OK) { return err; } } else { /* PKCS #1 v1.5 pad the key */ x = *outlen; if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME, modulus_bitlen, prng, prng_idx, out, &x)) != CRYPT_OK) { return err; } } /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */ return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key); } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_export.c000066400000000000000000000052711464416617300237420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_export.c Export RSA PKCS keys, Tom St Denis */ #ifdef LTC_MRSA /** This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1] @param out [out] Destination of the packet @param outlen [in/out] The max size and resulting size of the packet @param type The type of exported key (PK_PRIVATE or PK_PUBLIC) @param key The RSA key to export @return CRYPT_OK if successful */ int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key) { unsigned long zero=0; int err, std; LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); std = type & PK_STD; type &= ~PK_STD; if (type == PK_PRIVATE && key->type != PK_PRIVATE) { return CRYPT_PK_TYPE_MISMATCH; } if (type == PK_PRIVATE) { /* private key */ /* output is Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p */ return der_encode_sequence_multi(out, outlen, LTC_ASN1_SHORT_INTEGER, 1UL, &zero, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_INTEGER, 1UL, key->d, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->dP, LTC_ASN1_INTEGER, 1UL, key->dQ, LTC_ASN1_INTEGER, 1UL, key->qP, LTC_ASN1_EOL, 0UL, NULL); } if (type == PK_PUBLIC) { /* public key */ unsigned long tmplen, *ptmplen; unsigned char* tmp = NULL; if (std) { tmplen = (unsigned long)(mp_count_bits(key->N) / 8) * 2 + 8; tmp = XMALLOC(tmplen); ptmplen = &tmplen; if (tmp == NULL) { return CRYPT_MEM; } } else { tmp = out; ptmplen = outlen; } err = der_encode_sequence_multi(tmp, ptmplen, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL); if ((err != CRYPT_OK) || !std) { goto finish; } err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); finish: if (tmp != out) XFREE(tmp); return err; } return CRYPT_INVALID_ARG; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_exptmod.c000066400000000000000000000133441464416617300241010ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_exptmod.c RSA PKCS exptmod, Tom St Denis Added RSA blinding --nmav */ #ifdef LTC_MRSA /** Compute an RSA modular exponentiation @param in The input data to send into RSA @param inlen The length of the input (octets) @param out [out] The destination @param outlen [in/out] The max size and resulting size of the output @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC @param key The RSA key to use @return CRYPT_OK if successful */ int rsa_exptmod(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int which, const rsa_key *key) { void *tmp, *tmpa, *tmpb; #ifdef LTC_RSA_BLINDING void *rnd, *rndi /* inverse of rnd */; #endif unsigned long x; int err, has_crt_parameters; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* is the key of the right type for the operation? */ if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { return CRYPT_PK_NOT_PRIVATE; } /* must be a private or public operation */ if (which != PK_PRIVATE && which != PK_PUBLIC) { return CRYPT_PK_INVALID_TYPE; } /* init and copy into tmp */ if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, #ifdef LTC_RSA_BLINDING &rnd, &rndi, #endif /* LTC_RSA_BLINDING */ NULL)) != CRYPT_OK) { return err; } if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } /* sanity check on the input */ if (mp_cmp(key->N, tmp) == LTC_MP_LT) { err = CRYPT_PK_INVALID_SIZE; goto error; } /* are we using the private exponent and is the key optimized? */ if (which == PK_PRIVATE) { #ifdef LTC_RSA_BLINDING /* do blinding */ err = mp_rand(rnd, mp_get_digit_count(key->N)); if (err != CRYPT_OK) { goto error; } /* rndi = 1/rnd mod N */ err = mp_invmod(rnd, key->N, rndi); if (err != CRYPT_OK) { goto error; } /* rnd = rnd^e */ err = mp_exptmod( rnd, key->e, key->N, rnd); if (err != CRYPT_OK) { goto error; } /* tmp = tmp*rnd mod N */ err = mp_mulmod( tmp, rnd, key->N, tmp); if (err != CRYPT_OK) { goto error; } #endif /* LTC_RSA_BLINDING */ has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) && (key->q != NULL) && (mp_get_digit_count(key->q) != 0) && (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) && (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) && (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0); if (!has_crt_parameters) { /* * In case CRT optimization parameters are not provided, * the private key is directly used to exptmod it */ if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; } } else { /* tmpa = tmp^dP mod p */ if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; } /* tmpb = tmp^dQ mod q */ if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; } /* tmp = (tmpa - tmpb) * qInv (mod p) */ if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; } /* tmp = tmpb + q * tmp */ if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; } if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; } } #ifdef LTC_RSA_BLINDING /* unblind */ err = mp_mulmod( tmp, rndi, key->N, tmp); if (err != CRYPT_OK) { goto error; } #endif #ifdef LTC_RSA_CRT_HARDENING if (has_crt_parameters) { if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; } if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; } } #endif } else { /* exptmod it */ if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; } } /* read it back */ x = (unsigned long)mp_unsigned_bin_size(key->N); if (x > *outlen) { *outlen = x; err = CRYPT_BUFFER_OVERFLOW; goto error; } /* this should never happen ... */ if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) { err = CRYPT_ERROR; goto error; } *outlen = x; /* convert it */ zeromem(out, x); if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; } /* clean up and return */ err = CRYPT_OK; error: mp_clear_multi( #ifdef LTC_RSA_BLINDING rndi, rnd, #endif /* LTC_RSA_BLINDING */ tmpb, tmpa, tmp, NULL); return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_get_size.c000066400000000000000000000010631464416617300242250ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_get_size.c Retrieve the size of an RSA key, Steffen Jaeckel. */ #ifdef LTC_MRSA /** Retrieve the size in bytes of an RSA key. @param key The RSA key @return The size in bytes of the RSA key or INT_MAX on error. */ int rsa_get_size(const rsa_key *key) { int ret = INT_MAX; LTC_ARGCHK(key != NULL); if (key) { ret = mp_unsigned_bin_size(key->N); } /* if */ return ret; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_import.c000066400000000000000000000104141464416617300237260ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_import.c Import a PKCS RSA key, Tom St Denis */ #ifdef LTC_MRSA /** Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] The `key` passed into this function has to be already initialized and will NOT be free'd on error! @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @return CRYPT_OK if successful */ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; unsigned long version = -1; err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_EOL, 0UL, NULL); if (err == CRYPT_OVERFLOW) { /* the version would fit into an LTC_ASN1_SHORT_INTEGER * so we try to decode as a public key */ if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { key->type = PK_PUBLIC; } goto LBL_OUT; } else if (err != CRYPT_INPUT_TOO_LONG) { /* couldn't decode the version, so error out */ goto LBL_OUT; } if (version == 0) { /* it's a private key */ if ((err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_INTEGER, 1UL, key->d, LTC_ASN1_INTEGER, 1UL, key->p, LTC_ASN1_INTEGER, 1UL, key->q, LTC_ASN1_INTEGER, 1UL, key->dP, LTC_ASN1_INTEGER, 1UL, key->dQ, LTC_ASN1_INTEGER, 1UL, key->qP, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_OUT; } key->type = PK_PRIVATE; } else if (version == 1) { /* we don't support multi-prime RSA */ err = CRYPT_PK_INVALID_TYPE; goto LBL_OUT; } err = CRYPT_OK; LBL_OUT: return err; } /** Import multiple formats of RSA public and private keys. RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] SubjectPublicKeyInfo formatted public keys @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @return CRYPT_OK if successful, upon error allocated memory is freed */ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; unsigned char *tmpbuf=NULL; unsigned long tmpbuf_len, len; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ if ((err = rsa_init(key)) != CRYPT_OK) { return err; } /* see if the OpenSSL DER format RSA public key will work */ tmpbuf_len = inlen; tmpbuf = XCALLOC(1, tmpbuf_len); if (tmpbuf == NULL) { err = CRYPT_MEM; goto LBL_ERR; } len = 0; err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_RSA, tmpbuf, &tmpbuf_len, LTC_ASN1_NULL, NULL, &len); if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ /* now it should be SEQUENCE { INTEGER, INTEGER } */ if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PUBLIC; err = CRYPT_OK; goto LBL_FREE; } /* not SSL public key, try to match against PKCS #1 standards */ if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) { goto LBL_FREE; } LBL_ERR: rsa_free(key); LBL_FREE: if (tmpbuf != NULL) { XFREE(tmpbuf); } return err; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c000066400000000000000000000070021464416617300250350ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_import_pkcs8.c Import a PKCS RSA key */ #ifdef LTC_MRSA /* Public-Key Cryptography Standards (PKCS) #8: * Private-Key Information Syntax Specification Version 1.2 * https://tools.ietf.org/html/rfc5208 * * PrivateKeyInfo ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL } * where: * - Version ::= INTEGER * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier * - PrivateKey ::= OCTET STRING * - Attributes ::= SET OF Attribute * * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData } * where: * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * - EncryptedData ::= OCTET STRING */ /** Import an RSAPrivateKey in PKCS#8 format @param in The packet to import from @param inlen It's length (octets) @param passwd The password for decrypting privkey @param passwdlen Password's length (octets) @param key [out] Destination for newly imported key @return CRYPT_OK if successful, upon error allocated memory is freed */ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *passwd, unsigned long passwdlen, rsa_key *key) { int err; unsigned char *buf1 = NULL, *buf2 = NULL; unsigned long buf1len, buf2len; unsigned long oid[16], version; const char *rsaoid; ltc_asn1_list alg_seq[2], top_seq[3]; ltc_asn1_list *l = NULL; unsigned char *decrypted = NULL; unsigned long decryptedlen; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* get RSA alg oid */ err = pk_get_oid(LTC_OID_RSA, &rsaoid); if (err != CRYPT_OK) { goto LBL_NOFREE; } /* alloc buffers */ buf1len = inlen; /* approx. */ buf1 = XMALLOC(buf1len); if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; } buf2len = inlen; /* approx. */ buf2 = XMALLOC(buf2len); if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; } /* init key */ if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; } /* try to decode encrypted priv key */ if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) { goto LBL_ERR; } decrypted = l->data; decryptedlen = l->size; /* try to decode unencrypted priv key */ LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL); LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL); LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL); LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL); LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len); err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL); if (err != CRYPT_OK) { goto LBL_ERR; } /* check alg oid */ if ((err = pk_oid_cmp_with_asn1(rsaoid, &alg_seq[0])) != CRYPT_OK) { goto LBL_ERR; } if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PRIVATE; err = CRYPT_OK; goto LBL_FREE2; LBL_ERR: rsa_free(key); LBL_FREE2: if (l) der_free_sequence_flexi(l); XFREE(buf2); LBL_FREE1: XFREE(buf1); LBL_NOFREE: return err; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_import_x509.c000066400000000000000000000031541464416617300245160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_import.c Import an RSA key from a X.509 certificate, Steffen Jaeckel */ #ifdef LTC_MRSA static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key) { /* now it should be SEQUENCE { INTEGER, INTEGER } */ return der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N, LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL); } /** Import an RSA key from a X.509 certificate @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @return CRYPT_OK if successful, upon error allocated memory is freed */ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ if ((err = rsa_init(key)) != CRYPT_OK) { return err; } if ((err = x509_decode_public_key_from_certificate(in, inlen, LTC_OID_RSA, LTC_ASN1_NULL, NULL, NULL, (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { rsa_free(key); } else { key->type = PK_PUBLIC; } return err; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_key.c000066400000000000000000000047371464416617300232170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_key.c Free an RSA key, Tom St Denis Basic operations on an RSA key, Steffen Jaeckel */ #ifdef LTC_MRSA #include static void s_mpi_shrink_multi(void **a, ...) { void **cur; unsigned n; int err; va_list args; void *tmp[10] = { 0 }; void **arg[10] = { 0 }; /* We re-allocate in the order that we received the varargs */ n = 0; err = CRYPT_ERROR; cur = a; va_start(args, a); while (cur != NULL) { if (n >= sizeof(tmp)/sizeof(tmp[0])) { goto out; } if (*cur != NULL) { arg[n] = cur; if ((err = mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) { goto out; } n++; } cur = va_arg(args, void**); } va_end(args); /* but we clear the old values in the reverse order */ while (n != 0 && arg[--n] != NULL) { mp_clear(*arg[n]); *arg[n] = tmp[n]; } out: va_end(args); /* clean-up after an error * or after this was called with too many args */ if ((err != CRYPT_OK) || (n >= sizeof(tmp)/sizeof(tmp[0]))) { for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) { if (tmp[n] != NULL) { mp_clear(tmp[n]); } } } } /** This shrinks the allocated memory of a RSA key It will use up some more memory temporarily, but then it will free-up the entire sequence that was once allocated when the key was created/populated. This only works with libtommath >= 1.2.0 in earlier versions it has the inverse effect due to the way it worked internally. Also works for GNU MP, tomsfastmath naturally shows no effect. @param key The RSA key to shrink */ void rsa_shrink_key(rsa_key *key) { LTC_ARGCHKVD(key != NULL); s_mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); } /** Init an RSA key @param key The RSA key to free @return CRYPT_OK if successful */ int rsa_init(rsa_key *key) { LTC_ARGCHK(key != NULL); return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL); } /** Free an RSA key from memory @param key The RSA key to free */ void rsa_free(rsa_key *key) { LTC_ARGCHKVD(key != NULL); mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_make_key.c000066400000000000000000000135611464416617300242070ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_make_key.c RSA key generation, Tom St Denis */ #ifdef LTC_MRSA static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_key *key) { void *p, *q, *tmp1, *tmp2; int err; LTC_ARGCHK(ltc_mp.name != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(size > 0); if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } /* make primes p and q (optimization provided by Wayne Scott) */ /* make prime "p" */ do { if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */ if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */ /* make prime "q" */ do { if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */ if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */ } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */ /* tmp1 = lcm(p-1, q-1) */ if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */ /* tmp1 = q-1 (previous do/while loop) */ if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */ /* make key */ if ((err = rsa_init(key)) != CRYPT_OK) { goto errkey; } if ((err = mp_copy( e, key->e)) != CRYPT_OK) { goto errkey; } /* key->e = e */ if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */ if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */ /* optimize for CRT now */ /* find d mod q-1 and d mod p-1 */ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */ if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = q-1 */ if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */ if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */ if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */ if ((err = mp_copy( p, key->p)) != CRYPT_OK) { goto errkey; } if ((err = mp_copy( q, key->q)) != CRYPT_OK) { goto errkey; } /* set key type (in this case it's CRT optimized) */ key->type = PK_PRIVATE; /* return ok and free temps */ err = CRYPT_OK; goto cleanup; errkey: rsa_free(key); cleanup: mp_clear_multi(tmp2, tmp1, q, p, LTC_NULL); return err; } /** Create an RSA key based on a long public exponent type @param prng An active PRNG state @param wprng The index of the PRNG desired @param size The size of the modulus (key size) desired (octets) @param e The "e" value (public key). e==65537 is a good choice @param key [out] Destination of a newly created private key pair @return CRYPT_OK if successful, upon error all allocated ram is freed */ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) { void *tmp_e; int err; if ((e < 3) || ((e & 1) == 0)) { return CRYPT_INVALID_ARG; } if ((err = mp_init(&tmp_e)) != CRYPT_OK) { return err; } if ((err = mp_set_int(tmp_e, e)) == CRYPT_OK) err = s_rsa_make_key(prng, wprng, size, tmp_e, key); mp_clear(tmp_e); return err; } /** Create an RSA key based on a hexadecimal public exponent type @param prng An active PRNG state @param wprng The index of the PRNG desired @param size The size of the modulus (key size) desired (octets) @param e The "e" value (public key). e==65537 is a good choice @param elen The length of e (octets) @param key [out] Destination of a newly created private key pair @return CRYPT_OK if successful, upon error all allocated ram is freed */ int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size, const unsigned char *e, unsigned long elen, rsa_key *key) { int err; void *tmp_e; if ((err = mp_init(&tmp_e)) != CRYPT_OK) { return err; } if ((err = mp_read_unsigned_bin(tmp_e, (unsigned char *)e, elen)) == CRYPT_OK) err = rsa_make_key_bn_e(prng, wprng, size, tmp_e, key); mp_clear(tmp_e); return err; } /** Create an RSA key based on a bignumber public exponent type @param prng An active PRNG state @param wprng The index of the PRNG desired @param size The size of the modulus (key size) desired (octets) @param e The "e" value (public key). e==65537 is a good choice @param key [out] Destination of a newly created private key pair @return CRYPT_OK if successful, upon error all allocated ram is freed */ int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key) { int err; int e_bits; e_bits = mp_count_bits(e); if ((e_bits > 1 && e_bits < 256) && (mp_get_digit(e, 0) & 1)) { err = s_rsa_make_key(prng, wprng, size, e, key); } else { err = CRYPT_INVALID_ARG; } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_set.c000066400000000000000000000070711464416617300232140ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_MRSA /** Import RSA key from raw numbers @param N RSA's N @param Nlen RSA's N's length @param e RSA's e @param elen RSA's e's length @param d RSA's d (only private key, NULL for public key) @param dlen RSA's d's length @param key [out] the destination for the imported key @return CRYPT_OK if successful */ int rsa_set_key(const unsigned char *N, unsigned long Nlen, const unsigned char *e, unsigned long elen, const unsigned char *d, unsigned long dlen, rsa_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(N != NULL); LTC_ARGCHK(e != NULL); LTC_ARGCHK(ltc_mp.name != NULL); if ((err = rsa_init(key)) != CRYPT_OK) return err; if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; } if (d && dlen) { if ((err = mp_read_unsigned_bin(key->d , (unsigned char *)d , dlen)) != CRYPT_OK) { goto LBL_ERR; } key->type = PK_PRIVATE; } else { key->type = PK_PUBLIC; } return CRYPT_OK; LBL_ERR: rsa_free(key); return err; } /** Import factors of an RSA key from raw numbers Only for private keys. @param p RSA's p @param plen RSA's p's length @param q RSA's q @param qlen RSA's q's length @param key [out] the destination for the imported key @return CRYPT_OK if successful */ int rsa_set_factors(const unsigned char *p, unsigned long plen, const unsigned char *q, unsigned long qlen, rsa_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(p != NULL); LTC_ARGCHK(q != NULL); LTC_ARGCHK(ltc_mp.name != NULL); if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; if ((err = mp_read_unsigned_bin(key->p , (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->q , (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } return CRYPT_OK; LBL_ERR: rsa_free(key); return err; } /** Import CRT parameters of an RSA key from raw numbers Only for private keys. @param dP RSA's dP @param dPlen RSA's dP's length @param dQ RSA's dQ @param dQlen RSA's dQ's length @param qP RSA's qP @param qPlen RSA's qP's length @param key [out] the destination for the imported key @return CRYPT_OK if successful */ int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, const unsigned char *dQ, unsigned long dQlen, const unsigned char *qP, unsigned long qPlen, rsa_key *key) { int err; LTC_ARGCHK(key != NULL); LTC_ARGCHK(dP != NULL); LTC_ARGCHK(dQ != NULL); LTC_ARGCHK(qP != NULL); LTC_ARGCHK(ltc_mp.name != NULL); if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; if ((err = mp_read_unsigned_bin(key->dP, (unsigned char *)dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->dQ, (unsigned char *)dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = mp_read_unsigned_bin(key->qP, (unsigned char *)qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; } return CRYPT_OK; LBL_ERR: rsa_free(key); return err; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_hash.c000066400000000000000000000101471464416617300243620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_sign_hash.c RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** PKCS #1 pad then sign @param in The hash to sign @param inlen The length of the hash to sign (octets) @param out [out] The signature @param outlen [in/out] The max size and resulting size of the signature @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) @param prng An active PRNG state @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired @param saltlen The length of the salt desired (octets) @param key The private RSA key to use @return CRYPT_OK if successful */ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, prng_state *prng, int prng_idx, int hash_idx, unsigned long saltlen, const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x, y; int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); /* valid padding? */ if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_PSS) && (padding != LTC_PKCS_1_V1_5_NA1)) { return CRYPT_PK_INVALID_PADDING; } if (padding == LTC_PKCS_1_PSS) { /* valid prng ? */ if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } } if (padding != LTC_PKCS_1_V1_5_NA1) { /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } } /* get modulus len in bits */ modulus_bitlen = mp_count_bits((key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; return CRYPT_BUFFER_OVERFLOW; } if (padding == LTC_PKCS_1_PSS) { /* PSS pad the key */ x = *outlen; if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { return err; } } else { /* PKCS #1 v1.5 pad the hash */ unsigned char *tmpin; if (padding == LTC_PKCS_1_V1_5) { ltc_asn1_list digestinfo[2], siginfo[2]; /* not all hashes have OIDs... so sad */ if (hash_descriptor[hash_idx]->OIDlen == 0) { return CRYPT_INVALID_ARG; } /* construct the SEQUENCE SEQUENCE { SEQUENCE {hashoid OID blah NULL } hash OCTET STRING } */ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx]->OID, hash_descriptor[hash_idx]->OIDlen); LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); /* allocate memory for the encoding */ y = mp_unsigned_bin_size(key->N); tmpin = XMALLOC(y); if (tmpin == NULL) { return CRYPT_MEM; } if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { XFREE(tmpin); return err; } } else { /* set the pointer and data-length to the input values */ tmpin = (unsigned char *)in; y = inlen; } x = *outlen; err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); if (padding == LTC_PKCS_1_V1_5) { XFREE(tmpin); } if (err != CRYPT_OK) { return err; } } /* RSA encode it */ return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c000066400000000000000000000016441464416617300257420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file rsa_sign_saltlen_get.c Retrieve the maximum size of the salt, Steffen Jaeckel. */ #ifdef LTC_MRSA /** Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature. @param padding Type of padding (LTC_PKCS_1_PSS only) @param hash_idx The index of the desired hash @param key The RSA key @return The maximum salt length in bytes or INT_MAX on error. */ int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key) { int ret = INT_MAX; LTC_ARGCHK(key != NULL); if ((hash_is_valid(hash_idx) == CRYPT_OK) && (padding == LTC_PKCS_1_PSS)) { ret = rsa_get_size(key); if (ret < INT_MAX) { ret -= (hash_descriptor[hash_idx]->hashsize + 2); } /* if */ } /* if */ return ret; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c000066400000000000000000000147651464416617300247400ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include #include "tomcrypt_private.h" /** @file rsa_verify_hash.c RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange */ #ifdef LTC_MRSA /** PKCS #1 de-sign then v1.5 or PSS depad @param sig The signature data @param siglen The length of the signature data (octets) @param hash The hash of the message that was signed @param hashlen The length of the hash of the message that was signed (octets) @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) @param hash_idx The index of the desired hash @param saltlen The length of the salt used during signature @param stat [out] The result of the signature comparison, 1==valid, 0==invalid @param key The public RSA key corresponding to the key that performed the signature @return CRYPT_OK on success (even if the signature is invalid) */ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, int hash_idx, unsigned long saltlen, int *stat, const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned int inc1 = 0; unsigned char *tmpbuf; struct ftmn ftmn = { }; LTC_ARGCHK(hash != NULL); LTC_ARGCHK(sig != NULL); LTC_ARGCHK(stat != NULL); LTC_ARGCHK(key != NULL); /* default to invalid */ *stat = 0; FTMN_SET_CHECK_RES(&ftmn, FTMN_INCR0, 1); /* valid padding? */ if ((padding != LTC_PKCS_1_V1_5) && (padding != LTC_PKCS_1_PSS) && (padding != LTC_PKCS_1_V1_5_NA1)) { return CRYPT_PK_INVALID_PADDING; } if (padding != LTC_PKCS_1_V1_5_NA1) { /* valid hash ? */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } } /* get modulus len in bits */ modulus_bitlen = mp_count_bits( (key->N)); /* outlen must be at least the size of the modulus */ modulus_bytelen = mp_unsigned_bin_size( (key->N)); if (modulus_bytelen != siglen) { return CRYPT_INVALID_PACKET; } /* allocate temp buffer for decoded sig */ tmpbuf = XMALLOC(siglen); if (tmpbuf == NULL) { return CRYPT_MEM; } /* RSA decode it */ x = siglen; if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { XFREE(tmpbuf); return err; } /* make sure the output is the right size */ if (x != siglen) { XFREE(tmpbuf); return CRYPT_INVALID_PACKET; } if (padding == LTC_PKCS_1_PSS) { /* PSS decode and verify it */ FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("pkcs_1_pss_decode")); if(modulus_bitlen%8 == 1){ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat); } else{ err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); } if (*stat) { FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR1, 0); inc1 = 1; } FTMN_POP_LINKED_CALL(&ftmn); } else { /* PKCS #1 v1.5 decode it */ unsigned char *out; unsigned long outlen; int decoded; /* allocate temp buffer for decoded hash */ outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3; out = XMALLOC(outlen); if (out == NULL) { err = CRYPT_MEM; goto bail_2; } if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { XFREE(out); goto bail_2; } if (padding == LTC_PKCS_1_V1_5) { unsigned long loid[16], reallen; ltc_asn1_list digestinfo[2], siginfo[2]; /* not all hashes have OIDs... so sad */ if (hash_descriptor[hash_idx]->OIDlen == 0) { err = CRYPT_INVALID_ARG; goto bail_2; } /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ /* construct the SEQUENCE SEQUENCE { SEQUENCE {hashoid OID blah NULL } hash OCTET STRING } */ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0])); LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); if (der_decode_sequence_strict(out, outlen, siginfo, 2) != CRYPT_OK) { /* fallback to Legacy:missing NULL */ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { XFREE(out); goto bail_2; } } if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) { XFREE(out); goto bail_2; } /* test OID */ if ((reallen == outlen) && (digestinfo[0].size == hash_descriptor[hash_idx]->OIDlen) && (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx]->OID, sizeof(unsigned long) * hash_descriptor[hash_idx]->OIDlen) == 0) && (siginfo[1].size == hashlen) && (ftmn_set_check_res_memcmp(&ftmn, FTMN_INCR1, XMEMCMP, siginfo[1].data, hash, hashlen) == 0)) { *stat = 1; } inc1 = 1; } else { /* only check if the hash is equal */ if ((hashlen == outlen) && (ftmn_set_check_res_memcmp(&ftmn, FTMN_INCR1, XMEMCMP, out, hash, hashlen) == 0)) { *stat = 1; } inc1 = 1; } if (!*stat) { /* * The call to ftmn_set_check_res_memcmp() above might have failed, * since memcmp() may set any non-zero result force it 1 to match the * check with FTMN_CALLEE_DONE_CHECK() below. */ FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR1, 1); inc1++; } #ifdef LTC_CLEAN_STACK zeromem(out, outlen); #endif XFREE(out); } bail_2: #ifdef LTC_CLEAN_STACK zeromem(tmpbuf, siglen); #endif XFREE(tmpbuf); FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1, inc1), !*stat); return err; } #endif /* LTC_MRSA */ optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/000077500000000000000000000000001464416617300214735ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_export.c000066400000000000000000000016071464416617300241210ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_export.c Export a X25519 key to a binary packet, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Export a X25519 key to a binary packet @param out [out] The destination for the key @param outlen [in/out] The max size and resulting size of the X25519 key @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) @param key The key you wish to export @return CRYPT_OK if successful */ int x25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key) { LTC_ARGCHK(key != NULL); if (key->algo != LTC_OID_X25519) return CRYPT_PK_INVALID_TYPE; return ec25519_export(out, outlen, which, key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_import.c000066400000000000000000000016671464416617300241200ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_import.c Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Import a X25519 key @param in The packet to read @param inlen The length of the input packet @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) { int err; unsigned long key_len; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); key_len = sizeof(key->pub); if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { key->type = PK_PUBLIC; key->algo = LTC_OID_X25519; } return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c000066400000000000000000000017031464416617300252170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_import_pkcs8.c Import a X25519 key in PKCS#8 format, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Import a X25519 private key in PKCS#8 format @param in The DER-encoded PKCS#8-formatted private key @param inlen The length of the input data @param passwd The password to decrypt the private key @param passwdlen Password's length (octets) @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key) { return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_X25519, tweetnacl_crypto_scalarmult_base, key); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_import_raw.c000066400000000000000000000020401464416617300247530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_import_raw.c Set the parameters of a X25519 key, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Set the parameters of a X25519 key @param in The key @param inlen The length of the key @param which Which type of key (PK_PRIVATE or PK_PUBLIC) @param key [out] Destination of the key @return CRYPT_OK if successful */ int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) { LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen == 32uL); LTC_ARGCHK(key != NULL); if (which == PK_PRIVATE) { XMEMCPY(key->priv, in, sizeof(key->priv)); tweetnacl_crypto_scalarmult_base(key->pub, key->priv); } else if (which == PK_PUBLIC) { XMEMCPY(key->pub, in, sizeof(key->pub)); } else { return CRYPT_INVALID_ARG; } key->algo = LTC_OID_X25519; key->type = which; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_import_x509.c000066400000000000000000000025421464416617300246760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_import_x509.c Import a X25519 key from a X.509 certificate, Steffen Jaeckel */ #ifdef LTC_CURVE25519 static int s_x25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) { if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; XMEMCPY(key->pub, in, sizeof(key->pub)); return CRYPT_OK; } /** Import a X25519 public key from a X.509 certificate @param in The DER encoded X.509 certificate @param inlen The length of the certificate @param key [out] Where to import the key to @return CRYPT_OK if successful, on error all allocated memory is freed automatically */ int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); if ((err = x509_decode_public_key_from_certificate(in, inlen, LTC_OID_X25519, LTC_ASN1_EOL, NULL, NULL, (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) { return err; } key->type = PK_PUBLIC; key->algo = LTC_OID_X25519; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_make_key.c000066400000000000000000000016411464416617300243630ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_make_key.c Create a X25519 key, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Create a X25519 key @param prng An active PRNG state @param wprng The index of the PRNG desired @param key [out] Destination of a newly created private key pair @return CRYPT_OK if successful */ int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key) { int err; LTC_ARGCHK(key != NULL); if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (prng_descriptor[wprng]->read(key->priv, sizeof(key->priv), prng) != sizeof(key->priv)) { return CRYPT_ERROR_READPRNG; } tweetnacl_crypto_scalarmult_base(key->pub, key->priv); key->type = PK_PRIVATE; key->algo = LTC_OID_X25519; return err; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/pk/x25519/x25519_shared_secret.c000066400000000000000000000023451464416617300254130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file x25519_shared_secret.c Create a X25519 shared secret, Steffen Jaeckel */ #ifdef LTC_CURVE25519 /** Create a X25519 shared secret. @param private_key The private X25519 key in the pair @param public_key The public X25519 key in the pair @param out [out] The destination of the shared data @param outlen [in/out] The max size and resulting size of the shared data. @return CRYPT_OK if successful */ int x25519_shared_secret(const curve25519_key *private_key, const curve25519_key *public_key, unsigned char *out, unsigned long *outlen) { LTC_ARGCHK(private_key != NULL); LTC_ARGCHK(public_key != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); if(private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; if(*outlen < 32uL) { *outlen = 32uL; return CRYPT_BUFFER_OVERFLOW; } tweetnacl_crypto_scalarmult(out, private_key->priv, public_key->pub); *outlen = 32uL; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/000077500000000000000000000000001464416617300213355ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/chacha20.c000066400000000000000000000173531464416617300230630ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* the idea of re-keying loosely follows the approach used in: * http://bxr.su/OpenBSD/lib/libc/crypt/arc4random.c */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA20_PRNG const struct ltc_prng_descriptor chacha20_prng_desc = { "chacha20", 40, &chacha20_prng_start, &chacha20_prng_add_entropy, &chacha20_prng_ready, &chacha20_prng_read, &chacha20_prng_done, &chacha20_prng_export, &chacha20_prng_import, &chacha20_prng_test }; /** Start the PRNG @param prng The PRNG state to initialize @return CRYPT_OK if successful */ int chacha20_prng_start(prng_state *prng) { LTC_ARGCHK(prng != NULL); prng->ready = 0; XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); prng->u.chacha.idx = 0; LTC_MUTEX_INIT(&prng->lock) return CRYPT_OK; } /** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { unsigned char buf[40]; unsigned long i; int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { /* chacha20_prng_ready() was already called, do "rekey" operation */ if ((err = chacha_keystream(&prng->u.chacha.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; /* key 32 bytes, 20 rounds */ if ((err = chacha_setup(&prng->u.chacha.s, buf, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; /* iv 8 bytes */ if ((err = chacha_ivctr64(&prng->u.chacha.s, buf + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; /* clear KEY + IV */ zeromem(buf, sizeof(buf)); } else { /* chacha20_prng_ready() was not called yet, add entropy to ent buffer */ while (inlen--) prng->u.chacha.ent[prng->u.chacha.idx++ % sizeof(prng->u.chacha.ent)] ^= *in++; } err = CRYPT_OK; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int chacha20_prng_ready(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } /* key 32 bytes, 20 rounds */ if ((err = chacha_setup(&prng->u.chacha.s, prng->u.chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; /* iv 8 bytes */ if ((err = chacha_ivctr64(&prng->u.chacha.s, prng->u.chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); prng->u.chacha.idx = 0; prng->ready = 1; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) { if (outlen == 0 || prng == NULL || out == NULL) return 0; LTC_MUTEX_LOCK(&prng->lock); if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } if (chacha_keystream(&prng->u.chacha.s, out, outlen) != CRYPT_OK) outlen = 0; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return outlen; } /** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int chacha20_prng_done(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); prng->ready = 0; err = chacha_done(&prng->u.chacha.s); LTC_MUTEX_UNLOCK(&prng->lock); LTC_MUTEX_DESTROY(&prng->lock); return err; } /** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ LTC_PRNG_EXPORT(chacha20_prng) /** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); if (inlen < (unsigned long)chacha20_prng_desc.export_size) return CRYPT_INVALID_ARG; if ((err = chacha20_prng_start(prng)) != CRYPT_OK) return err; if ((err = chacha20_prng_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; return CRYPT_OK; } /** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int chacha20_prng_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else prng_state st; unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; unsigned char dmp[300]; unsigned long dmplen = sizeof(dmp); unsigned char out[500]; unsigned char t1[] = { 0x59, 0xB2, 0x26, 0x95, 0x2B, 0x01, 0x8F, 0x05, 0xBE, 0xD8 }; unsigned char t2[] = { 0x47, 0xC9, 0x0D, 0x03, 0xE4, 0x75, 0x34, 0x27, 0xBD, 0xDE }; unsigned char t3[] = { 0xBC, 0xFA, 0xEF, 0x59, 0x37, 0x7F, 0x1A, 0x91, 0x1A, 0xA6 }; int err; if ((err = chacha20_prng_start(&st)) != CRYPT_OK) return err; /* add entropy to uninitialized prng */ if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ /* add entropy to already initialized prng */ if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if ((err = chacha20_prng_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; if ((err = chacha20_prng_import(dmp, dmplen, &st)) != CRYPT_OK) return err; if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t3, sizeof(t3), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/fortuna.c000066400000000000000000000317601464416617300231660ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED #if defined(_WIN32) #include #elif defined(LTC_CLOCK_GETTIME) #include /* struct timespec + clock_gettime */ #else #include /* struct timeval + gettimeofday */ #endif #endif /** @file fortuna.c Fortuna PRNG, Tom St Denis */ /* Implementation of Fortuna by Tom St Denis We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" in the AddEntropy function are fixed to 0. Second since no reliable timer is provided we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */ #ifdef LTC_FORTUNA /* requries LTC_SHA256 and AES */ #if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256)) #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES) #endif #ifndef LTC_FORTUNA_POOLS #warning LTC_FORTUNA_POOLS was not previously defined (old headers?) #define LTC_FORTUNA_POOLS 32 #endif #if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32 #error LTC_FORTUNA_POOLS must be in [4..32] #endif #ifdef LTC_FORTUNA_USE_ENCRYPT_ONLY #define AES_SETUP aes_enc_setup #define AES_ENC aes_enc_ecb_encrypt #define AES_DONE aes_enc_done #define AES_TEST aes_enc_test #else #define AES_SETUP aes_setup #define AES_ENC aes_ecb_encrypt #define AES_DONE aes_done #define AES_TEST aes_test #endif const struct ltc_prng_descriptor fortuna_desc = { "fortuna", 64, &fortuna_start, &fortuna_add_entropy, &fortuna_ready, &fortuna_read, &fortuna_done, &fortuna_export, &fortuna_import, &fortuna_test }; /* update the IV */ static void s_fortuna_update_iv(prng_state *prng) { int x; unsigned char *IV; /* update IV */ IV = prng->u.fortuna.IV; for (x = 0; x < 16; x++) { IV[x] = (IV[x] + 1) & 255; if (IV[x] != 0) break; } } #ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED /* get the current time in 100ms steps */ static ulong64 s_fortuna_current_time(void) { ulong64 cur_time; #if defined(_WIN32) FILETIME CurrentTime; ULARGE_INTEGER ul; GetSystemTimeAsFileTime(&CurrentTime); ul.LowPart = CurrentTime.dwLowDateTime; ul.HighPart = CurrentTime.dwHighDateTime; cur_time = ul.QuadPart; /* now we have 100ns intervals since 1 January 1601 */ cur_time -= CONST64(116444736000000000); /* subtract 100ns intervals between 1601-1970 */ cur_time /= 10; /* 100ns intervals > microseconds */ #elif defined(LTC_CLOCK_GETTIME) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); cur_time = (ulong64)(ts.tv_sec) * 1000000 + (ulong64)(ts.tv_nsec) / 1000; /* get microseconds */ #else struct timeval tv; gettimeofday(&tv, NULL); cur_time = (ulong64)(tv.tv_sec) * 1000000 + (ulong64)(tv.tv_usec); /* get microseconds */ #endif return cur_time / 100; } #endif /* reseed the PRNG */ static int s_fortuna_reseed(prng_state *prng) { unsigned char tmp[MAXBLOCKSIZE]; hash_state md; ulong64 reset_cnt; int err, x; #ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED ulong64 now = s_fortuna_current_time(); if (now == prng->u.fortuna.wd) { return CRYPT_OK; } #else if (++prng->u.fortuna.wd < LTC_FORTUNA_WD) { return CRYPT_OK; } #endif /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */ sha256_init(&md); if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { sha256_done(&md, tmp); return err; } reset_cnt = prng->u.fortuna.reset_cnt + 1; for (x = 0; x < LTC_FORTUNA_POOLS; x++) { if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) { /* terminate this hash */ if ((err = sha256_done(&prng->u.fortuna.pool[x], tmp)) != CRYPT_OK) { sha256_done(&md, tmp); return err; } /* add it to the string */ if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { sha256_done(&md, tmp); return err; } /* reset this pool */ if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { sha256_done(&md, tmp); return err; } } else { break; } } /* finish key */ if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { return err; } if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { return err; } s_fortuna_update_iv(prng); /* reset/update internals */ prng->u.fortuna.pool0_len = 0; #ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED prng->u.fortuna.wd = now; #else prng->u.fortuna.wd = 0; #endif prng->u.fortuna.reset_cnt = reset_cnt; #ifdef LTC_CLEAN_STACK zeromem(&md, sizeof(md)); zeromem(tmp, sizeof(tmp)); #endif return CRYPT_OK; } /** "Update Seed File"-compliant update of K @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; unsigned char tmp[MAXBLOCKSIZE]; hash_state md; LTC_MUTEX_LOCK(&prng->lock); /* new K = LTC_SHA256(K || in) */ sha256_init(&md); if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { sha256_done(&md, tmp); goto LBL_UNLOCK; } if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) { sha256_done(&md, tmp); goto LBL_UNLOCK; } /* finish key */ if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { goto LBL_UNLOCK; } s_fortuna_update_iv(prng); LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); #ifdef LTC_CLEAN_STACK zeromem(&md, sizeof(md)); #endif return err; } /** Start the PRNG @param prng [out] The PRNG state to initialize @return CRYPT_OK if successful */ int fortuna_start(prng_state *prng) { int err, x, y; unsigned char tmp[MAXBLOCKSIZE]; LTC_ARGCHK(prng != NULL); prng->ready = 0; /* initialize the pools */ for (x = 0; x < LTC_FORTUNA_POOLS; x++) { if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { for (y = 0; y < x; y++) { sha256_done(&prng->u.fortuna.pool[y], tmp); } return err; } } prng->u.fortuna.pool_idx = prng->u.fortuna.pool0_len = 0; prng->u.fortuna.reset_cnt = prng->u.fortuna.wd = 0; /* reset bufs */ zeromem(prng->u.fortuna.K, 32); if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { for (x = 0; x < LTC_FORTUNA_POOLS; x++) { sha256_done(&prng->u.fortuna.pool[x], tmp); } return err; } zeromem(prng->u.fortuna.IV, 16); LTC_MUTEX_INIT(&prng->lock) return CRYPT_OK; } static int s_fortuna_add(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) { unsigned char tmp[2]; int err; /* ensure inlen <= 32 */ if (inlen > 32) { inlen = 32; } /* add s || length(in) || in to pool[pool_idx] */ tmp[0] = (unsigned char)source; tmp[1] = (unsigned char)inlen; if ((err = sha256_process(&prng->u.fortuna.pool[pool], tmp, 2)) != CRYPT_OK) { return err; } if ((err = sha256_process(&prng->u.fortuna.pool[pool], in, inlen)) != CRYPT_OK) { return err; } if (pool == 0) { prng->u.fortuna.pool0_len += inlen; } return CRYPT_OK; /* success */ } /** Add random event to the PRNG state as proposed by the original paper. @param source The source this random event comes from (0 .. 255) @param pool The pool where to add the data to (0 .. LTC_FORTUNA_POOLS) @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); LTC_ARGCHK(source <= 255); LTC_ARGCHK(pool < LTC_FORTUNA_POOLS); LTC_MUTEX_LOCK(&prng->lock); err = s_fortuna_add(source, pool, in, inlen, prng); LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); LTC_MUTEX_LOCK(&prng->lock); err = s_fortuna_add(0, prng->u.fortuna.pool_idx, in, inlen, prng); if (err == CRYPT_OK) { ++(prng->u.fortuna.pool_idx); prng->u.fortuna.pool_idx %= LTC_FORTUNA_POOLS; } LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int fortuna_ready(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); /* make sure the reseed doesn't fail because * of the chosen rate limit */ #ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED prng->u.fortuna.wd = s_fortuna_current_time() - 1; #else prng->u.fortuna.wd = LTC_FORTUNA_WD; #endif err = s_fortuna_reseed(prng); prng->ready = (err == CRYPT_OK) ? 1 : 0; LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) { unsigned char tmp[16]; unsigned long tlen = 0; if (outlen == 0 || prng == NULL || out == NULL) return 0; LTC_MUTEX_LOCK(&prng->lock); if (!prng->ready) { goto LBL_UNLOCK; } /* do we have to reseed? */ if (prng->u.fortuna.pool0_len >= 64) { if (s_fortuna_reseed(prng) != CRYPT_OK) { goto LBL_UNLOCK; } } /* ensure that one reseed happened before allowing to read */ if (prng->u.fortuna.reset_cnt == 0) { goto LBL_UNLOCK; } /* now generate the blocks required */ tlen = outlen; /* handle whole blocks without the extra XMEMCPY */ while (outlen >= 16) { /* encrypt the IV and store it */ AES_ENC(prng->u.fortuna.IV, out, &prng->u.fortuna.skey); out += 16; outlen -= 16; s_fortuna_update_iv(prng); } /* left over bytes? */ if (outlen > 0) { AES_ENC(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey); XMEMCPY(out, tmp, outlen); s_fortuna_update_iv(prng); } /* generate new key */ AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey); s_fortuna_update_iv(prng); AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey); s_fortuna_update_iv(prng); if (AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) { tlen = 0; } LBL_UNLOCK: #ifdef LTC_CLEAN_STACK zeromem(tmp, sizeof(tmp)); #endif LTC_MUTEX_UNLOCK(&prng->lock); return tlen; } /** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int fortuna_done(prng_state *prng) { int err, x; unsigned char tmp[32]; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); prng->ready = 0; /* terminate all the hashes */ for (x = 0; x < LTC_FORTUNA_POOLS; x++) { if ((err = sha256_done(&(prng->u.fortuna.pool[x]), tmp)) != CRYPT_OK) { goto LBL_UNLOCK; } } /* call cipher done when we invent one ;-) */ err = CRYPT_OK; /* success */ LBL_UNLOCK: #ifdef LTC_CLEAN_STACK zeromem(tmp, sizeof(tmp)); #endif LTC_MUTEX_UNLOCK(&prng->lock); LTC_MUTEX_DESTROY(&prng->lock); return err; } /** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ LTC_PRNG_EXPORT(fortuna) /** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(prng != NULL); if (inlen < (unsigned long)fortuna_desc.export_size) { return CRYPT_INVALID_ARG; } if ((err = fortuna_start(prng)) != CRYPT_OK) { return err; } if ((err = fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) { return err; } return err; } /** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int fortuna_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else int err; if ((err = sha256_test()) != CRYPT_OK) { return err; } return AES_TEST(); #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/rc4.c000066400000000000000000000167471464416617300222100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file prngs/rc4.c RC4 PRNG, Tom St Denis */ #ifdef LTC_RC4 const struct ltc_prng_descriptor rc4_desc = { "rc4", 32, &rc4_start, &rc4_add_entropy, &rc4_ready, &rc4_read, &rc4_done, &rc4_export, &rc4_import, &rc4_test }; /** Start the PRNG @param prng [out] The PRNG state to initialize @return CRYPT_OK if successful */ int rc4_start(prng_state *prng) { LTC_ARGCHK(prng != NULL); prng->ready = 0; /* set entropy (key) size to zero */ prng->u.rc4.s.x = 0; /* clear entropy (key) buffer */ XMEMSET(&prng->u.rc4.s.buf, 0, sizeof(prng->u.rc4.s.buf)); LTC_MUTEX_INIT(&prng->lock) return CRYPT_OK; } /** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { unsigned char buf[256]; unsigned long i; int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { /* rc4_ready() was already called, do "rekey" operation */ if ((err = rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; /* initialize RC4 */ if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); zeromem(buf, sizeof(buf)); } else { /* rc4_ready() was not called yet, add entropy to the buffer */ while (inlen--) prng->u.rc4.s.buf[prng->u.rc4.s.x++ % sizeof(prng->u.rc4.s.buf)] ^= *in++; } err = CRYPT_OK; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int rc4_ready(prng_state *prng) { unsigned char buf[256] = { 0 }; unsigned long len; int err, i; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } XMEMCPY(buf, prng->u.rc4.s.buf, sizeof(buf)); /* initialize RC4 */ len = MIN(prng->u.rc4.s.x, 256); /* TODO: we can perhaps always use all 256 bytes */ if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, len)) != CRYPT_OK) goto LBL_UNLOCK; /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); prng->ready = 1; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) { if (outlen == 0 || prng == NULL || out == NULL) return 0; LTC_MUTEX_LOCK(&prng->lock); if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } if (rc4_stream_keystream(&prng->u.rc4.s, out, outlen) != CRYPT_OK) outlen = 0; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return outlen; } /** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int rc4_done(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); prng->ready = 0; err = rc4_stream_done(&prng->u.rc4.s); LTC_MUTEX_UNLOCK(&prng->lock); LTC_MUTEX_DESTROY(&prng->lock); return err; } /** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ LTC_PRNG_EXPORT(rc4) /** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); if (inlen < (unsigned long)rc4_desc.export_size) return CRYPT_INVALID_ARG; if ((err = rc4_start(prng)) != CRYPT_OK) return err; if ((err = rc4_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; return CRYPT_OK; } /** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int rc4_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else prng_state st; unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; unsigned char dmp[500]; unsigned long dmplen = sizeof(dmp); unsigned char out[1000]; unsigned char t1[] = { 0xE0, 0x4D, 0x9A, 0xF6, 0xA8, 0x9D, 0x77, 0x53, 0xAE, 0x09 }; unsigned char t2[] = { 0xEF, 0x80, 0xA2, 0xE6, 0x50, 0x91, 0xF3, 0x17, 0x4A, 0x8A }; unsigned char t3[] = { 0x4B, 0xD6, 0x5C, 0x67, 0x99, 0x03, 0x56, 0x12, 0x80, 0x48 }; int err; if ((err = rc4_start(&st)) != CRYPT_OK) return err; /* add entropy to uninitialized prng */ if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if ((err = rc4_ready(&st)) != CRYPT_OK) return err; if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ /* add entropy to already initialized prng */ if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if ((err = rc4_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; if ((err = rc4_done(&st)) != CRYPT_OK) return err; if ((err = rc4_import(dmp, dmplen, &st)) != CRYPT_OK) return err; if ((err = rc4_ready(&st)) != CRYPT_OK) return err; if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t3, sizeof(t3), "RC4-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; if ((err = rc4_done(&st)) != CRYPT_OK) return err; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c000066400000000000000000000100141464416617300243300ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_RNG_GET_BYTES /** @file rng_get_bytes.c portable way to get secure random bits to feed a PRNG (Tom St Denis) */ #if defined(LTC_DEVRANDOM) && !defined(_WIN32) /* on *NIX read /dev/random */ static unsigned long s_rng_nix(unsigned char *buf, unsigned long len, void (*callback)(void)) { #ifdef LTC_NO_FILE LTC_UNUSED_PARAM(callback); LTC_UNUSED_PARAM(buf); LTC_UNUSED_PARAM(len); return 0; #else FILE *f; unsigned long x; LTC_UNUSED_PARAM(callback); #ifdef LTC_TRY_URANDOM_FIRST f = fopen("/dev/urandom", "rb"); if (f == NULL) { f = fopen("/dev/random", "rb"); } #else f = fopen("/dev/random", "rb"); #endif /* LTC_TRY_URANDOM_FIRST */ if (f == NULL) { return 0; } /* disable buffering */ if (setvbuf(f, NULL, _IONBF, 0) != 0) { fclose(f); return 0; } x = (unsigned long)fread(buf, 1, (size_t)len, f); fclose(f); return x; #endif /* LTC_NO_FILE */ } #endif /* LTC_DEVRANDOM */ #if !defined(_WIN32_WCE) #define ANSI_RNG static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len, void (*callback)(void)) { clock_t t1; int l, acc, bits, a, b; l = len; bits = 8; acc = a = b = 0; while (len--) { if (callback != NULL) callback(); while (bits--) { do { t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; } while (a == b); acc = (acc << 1) | a; } *buf++ = acc; acc = 0; bits = 8; } return l; } #endif /* Try the Microsoft CSP */ #if defined(_WIN32) || defined(_WIN32_WCE) #if defined(LTC_WIN32_BCRYPT) #include #include #pragma comment(lib, "bcrypt.lib") static unsigned long s_rng_win32(unsigned char *buf, unsigned long len, void (*callback)(void)) { LTC_UNUSED_PARAM(callback); return BCRYPT_SUCCESS(BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) ? len : 0; } #else #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif #ifndef WINVER #define WINVER 0x0501 #endif #define WIN32_LEAN_AND_MEAN #include #include static unsigned long s_rng_win32(unsigned char *buf, unsigned long len, void (*callback)(void)) { LTC_UNUSED_PARAM(callback); static HCRYPTPROV hProv = 0; if (hProv == 0) { HCRYPTPROV h = 0; if (!CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && !CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { return 0; } hProv = h; } return CryptGenRandom(hProv, (DWORD)len, (BYTE *)buf) == TRUE ? len : 0; } #endif /* Old WIN32 versions */ #endif /* WIN32 */ /** Read the system RNG @param out Destination @param outlen Length desired (octets) @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL @return Number of octets read */ unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, void (*callback)(void)) { unsigned long x; LTC_ARGCHK(out != NULL); #ifdef LTC_PRNG_ENABLE_LTC_RNG if (ltc_rng) { x = ltc_rng(out, outlen, callback); if (x != 0) { return x; } } #endif #if defined(_WIN32) || defined(_WIN32_WCE) x = s_rng_win32(out, outlen, callback); if (x != 0) { return x; } #elif defined(LTC_DEVRANDOM) x = s_rng_nix(out, outlen, callback); if (x != 0) { return x; } #endif #ifdef ANSI_RNG x = s_rng_ansic(out, outlen, callback); if (x != 0) { return x; } #endif return 0; } #endif /* #ifdef LTC_RNG_GET_BYTES */ optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/rng_make_prng.c000066400000000000000000000040101464416617300243050ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_RNG_MAKE_PRNG /** @file rng_make_prng.c portable way to get secure random bits to feed a PRNG (Tom St Denis) */ /** Create a PRNG from a RNG In case you pass bits as '-1' the PRNG will be setup as if the export/import functionality has been used, but the imported data comes directly from the RNG. @param bits Number of bits of entropy desired (-1 or 64 ... 1024) @param wprng Index of which PRNG to setup @param prng [out] PRNG state to initialize @param callback A pointer to a void function for when the RNG is slow, this can be NULL @return CRYPT_OK if successful */ int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)) { unsigned char* buf; unsigned long bytes; int err; LTC_ARGCHK(prng != NULL); /* check parameter */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } if (bits == -1) { bytes = prng_descriptor[wprng]->export_size; } else if (bits < 64 || bits > 1024) { return CRYPT_INVALID_PRNGSIZE; } else { bytes = (unsigned long)((bits+7)/8) * 2; } if ((err = prng_descriptor[wprng]->start(prng)) != CRYPT_OK) { return err; } buf = XMALLOC(bytes); if (buf == NULL) { return CRYPT_MEM; } if (rng_get_bytes(buf, bytes, callback) != bytes) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } if (bits == -1) { if ((err = prng_descriptor[wprng]->pimport(buf, bytes, prng)) != CRYPT_OK) { goto LBL_ERR; } } else { if ((err = prng_descriptor[wprng]->add_entropy(buf, bytes, prng)) != CRYPT_OK) { goto LBL_ERR; } } if ((err = prng_descriptor[wprng]->ready(prng)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf, bytes); #endif XFREE(buf); return err; } #endif /* #ifdef LTC_RNG_MAKE_PRNG */ optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/sober128.c000066400000000000000000000172501464416617300230530ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file prngs/sober128.c Implementation of SOBER-128 by Tom St Denis. Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. */ #ifdef LTC_SOBER128 const struct ltc_prng_descriptor sober128_desc = { "sober128", 40, &sober128_start, &sober128_add_entropy, &sober128_ready, &sober128_read, &sober128_done, &sober128_export, &sober128_import, &sober128_test }; /** Start the PRNG @param prng [out] The PRNG state to initialize @return CRYPT_OK if successful */ int sober128_start(prng_state *prng) { LTC_ARGCHK(prng != NULL); prng->ready = 0; XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); prng->u.sober128.idx = 0; LTC_MUTEX_INIT(&prng->lock) return CRYPT_OK; } /** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { unsigned char buf[40]; unsigned long i; int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { /* sober128_ready() was already called, do "rekey" operation */ if ((err = sober128_stream_keystream(&prng->u.sober128.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; /* key 32 bytes, 20 rounds */ if ((err = sober128_stream_setup(&prng->u.sober128.s, buf, 32)) != CRYPT_OK) goto LBL_UNLOCK; /* iv 8 bytes */ if ((err = sober128_stream_setiv(&prng->u.sober128.s, buf + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; /* clear KEY + IV */ zeromem(buf, sizeof(buf)); } else { /* sober128_ready() was not called yet, add entropy to ent buffer */ while (inlen--) prng->u.sober128.ent[prng->u.sober128.idx++ % sizeof(prng->u.sober128.ent)] ^= *in++; } err = CRYPT_OK; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int sober128_ready(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } /* key 32 bytes, 20 rounds */ if ((err = sober128_stream_setup(&prng->u.sober128.s, prng->u.sober128.ent, 32)) != CRYPT_OK) goto LBL_UNLOCK; /* iv 8 bytes */ if ((err = sober128_stream_setiv(&prng->u.sober128.s, prng->u.sober128.ent + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); prng->u.sober128.idx = 0; prng->ready = 1; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) { if (outlen == 0 || prng == NULL || out == NULL) return 0; LTC_MUTEX_LOCK(&prng->lock); if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } if (sober128_stream_keystream(&prng->u.sober128.s, out, outlen) != CRYPT_OK) outlen = 0; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return outlen; } /** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int sober128_done(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); prng->ready = 0; err = sober128_stream_done(&prng->u.sober128.s); LTC_MUTEX_UNLOCK(&prng->lock); LTC_MUTEX_DESTROY(&prng->lock); return err; } /** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ LTC_PRNG_EXPORT(sober128) /** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); if (inlen < (unsigned long)sober128_desc.export_size) return CRYPT_INVALID_ARG; if ((err = sober128_start(prng)) != CRYPT_OK) return err; if ((err = sober128_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; return CRYPT_OK; } /** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int sober128_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else prng_state st; unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; unsigned char dmp[300]; unsigned long dmplen = sizeof(dmp); unsigned char out[500]; unsigned char t1[] = { 0x31, 0x82, 0xA7, 0xA5, 0x8B, 0xD7, 0xCB, 0x39, 0x86, 0x1A }; unsigned char t2[] = { 0x6B, 0x43, 0x9E, 0xBC, 0xE7, 0x62, 0x9B, 0xE6, 0x9B, 0x83 }; unsigned char t3[] = { 0x4A, 0x0E, 0x6C, 0xC1, 0xCF, 0xB4, 0x73, 0x49, 0x99, 0x05 }; int err; if ((err = sober128_start(&st)) != CRYPT_OK) return err; /* add entropy to uninitialized prng */ if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if ((err = sober128_ready(&st)) != CRYPT_OK) return err; if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ /* add entropy to already initialized prng */ if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if ((err = sober128_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; if ((err = sober128_done(&st)) != CRYPT_OK) return err; if ((err = sober128_import(dmp, dmplen, &st)) != CRYPT_OK) return err; if ((err = sober128_ready(&st)) != CRYPT_OK) return err; if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ if (compare_testvector(out, 10, t3, sizeof(t3), "SOBER128-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; if ((err = sober128_done(&st)) != CRYPT_OK) return err; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/sprng.c000066400000000000000000000066751464416617300226500ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file sprng.c Secure PRNG, Tom St Denis */ /* A secure PRNG using the RNG functions. Basically this is a * wrapper that allows you to use a secure RNG as a PRNG * in the various other functions. */ #ifdef LTC_SPRNG const struct ltc_prng_descriptor sprng_desc = { "sprng", 0, &sprng_start, &sprng_add_entropy, &sprng_ready, &sprng_read, &sprng_done, &sprng_export, &sprng_import, &sprng_test }; /** Start the PRNG @param prng [out] The PRNG state to initialize @return CRYPT_OK if successful */ int sprng_start(prng_state *prng) { LTC_UNUSED_PARAM(prng); return CRYPT_OK; } /** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { LTC_UNUSED_PARAM(in); LTC_UNUSED_PARAM(inlen); LTC_UNUSED_PARAM(prng); return CRYPT_OK; } /** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int sprng_ready(prng_state *prng) { LTC_UNUSED_PARAM(prng); return CRYPT_OK; } /** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) { LTC_ARGCHK(out != NULL); LTC_UNUSED_PARAM(prng); return rng_get_bytes(out, outlen, NULL); } /** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int sprng_done(prng_state *prng) { LTC_UNUSED_PARAM(prng); return CRYPT_OK; } /** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ /* NOLINTNEXTLINE(readability-non-const-parameter) - silence clang-tidy warning */ int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) { LTC_ARGCHK(outlen != NULL); LTC_UNUSED_PARAM(out); LTC_UNUSED_PARAM(prng); *outlen = 0; return CRYPT_OK; } /** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { LTC_UNUSED_PARAM(in); LTC_UNUSED_PARAM(inlen); LTC_UNUSED_PARAM(prng); return CRYPT_OK; } /** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int sprng_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else prng_state st; unsigned char en[] = { 0x01, 0x02, 0x03, 0x04 }; unsigned char out[1000]; int err; if ((err = sprng_start(&st)) != CRYPT_OK) return err; if ((err = sprng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; if ((err = sprng_ready(&st)) != CRYPT_OK) return err; if (sprng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ if ((err = sprng_done(&st)) != CRYPT_OK) return err; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/prngs/yarrow.c000066400000000000000000000207361464416617300230340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file yarrow.c Yarrow PRNG, Tom St Denis */ #ifdef LTC_YARROW const struct ltc_prng_descriptor yarrow_desc = { "yarrow", 64, &yarrow_start, &yarrow_add_entropy, &yarrow_ready, &yarrow_read, &yarrow_done, &yarrow_export, &yarrow_import, &yarrow_test }; /** Start the PRNG @param prng [out] The PRNG state to initialize @return CRYPT_OK if successful */ int yarrow_start(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); prng->ready = 0; /* these are the default hash/cipher combo used */ #ifdef LTC_RIJNDAEL #if LTC_YARROW_AES==0 prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc); #elif LTC_YARROW_AES==1 prng->u.yarrow.cipher = register_cipher(&aes_enc_desc); #elif LTC_YARROW_AES==2 prng->u.yarrow.cipher = register_cipher(&rijndael_desc); #elif LTC_YARROW_AES==3 prng->u.yarrow.cipher = register_cipher(&aes_desc); #endif #elif defined(LTC_BLOWFISH) prng->u.yarrow.cipher = register_cipher(&blowfish_desc); #elif defined(LTC_TWOFISH) prng->u.yarrow.cipher = register_cipher(&twofish_desc); #elif defined(LTC_RC6) prng->u.yarrow.cipher = register_cipher(&rc6_desc); #elif defined(LTC_RC5) prng->u.yarrow.cipher = register_cipher(&rc5_desc); #elif defined(LTC_SAFERP) prng->u.yarrow.cipher = register_cipher(&saferp_desc); #elif defined(LTC_RC2) prng->u.yarrow.cipher = register_cipher(&rc2_desc); #elif defined(LTC_NOEKEON) prng->u.yarrow.cipher = register_cipher(&noekeon_desc); #elif defined(LTC_ANUBIS) prng->u.yarrow.cipher = register_cipher(&anubis_desc); #elif defined(LTC_KSEED) prng->u.yarrow.cipher = register_cipher(&kseed_desc); #elif defined(LTC_KHAZAD) prng->u.yarrow.cipher = register_cipher(&khazad_desc); #elif defined(LTC_CAST5) prng->u.yarrow.cipher = register_cipher(&cast5_desc); #elif defined(LTC_XTEA) prng->u.yarrow.cipher = register_cipher(&xtea_desc); #elif defined(LTC_SAFER) prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc); #elif defined(LTC_DES) prng->u.yarrow.cipher = register_cipher(&des3_desc); #else #error LTC_YARROW needs at least one CIPHER #endif if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { return err; } #ifdef LTC_SHA256 prng->u.yarrow.hash = register_hash(&sha256_desc); #elif defined(LTC_SHA512) prng->u.yarrow.hash = register_hash(&sha512_desc); #elif defined(LTC_TIGER) prng->u.yarrow.hash = register_hash(&tiger_desc); #elif defined(LTC_SHA1) prng->u.yarrow.hash = register_hash(&sha1_desc); #elif defined(LTC_RIPEMD320) prng->u.yarrow.hash = register_hash(&rmd320_desc); #elif defined(LTC_RIPEMD256) prng->u.yarrow.hash = register_hash(&rmd256_desc); #elif defined(LTC_RIPEMD160) prng->u.yarrow.hash = register_hash(&rmd160_desc); #elif defined(LTC_RIPEMD128) prng->u.yarrow.hash = register_hash(&rmd128_desc); #elif defined(LTC_MD5) prng->u.yarrow.hash = register_hash(&md5_desc); #elif defined(LTC_MD4) prng->u.yarrow.hash = register_hash(&md4_desc); #elif defined(LTC_MD2) prng->u.yarrow.hash = register_hash(&md2_desc); #elif defined(LTC_WHIRLPOOL) prng->u.yarrow.hash = register_hash(&whirlpool_desc); #else #error LTC_YARROW needs at least one HASH #endif if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { return err; } /* zero the memory used */ zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool)); LTC_MUTEX_INIT(&prng->lock) return CRYPT_OK; } /** Add entropy to the PRNG state @param in The data to add @param inlen Length of the data to add @param prng PRNG state to update @return CRYPT_OK if successful */ int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) { hash_state md; int err; LTC_ARGCHK(prng != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(inlen > 0); LTC_MUTEX_LOCK(&prng->lock); if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { goto LBL_UNLOCK; } /* start the hash */ if ((err = hash_descriptor[prng->u.yarrow.hash]->init(&md)) != CRYPT_OK) { goto LBL_UNLOCK; } /* hash the current pool */ if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, prng->u.yarrow.pool, hash_descriptor[prng->u.yarrow.hash]->hashsize)) != CRYPT_OK) { goto LBL_UNLOCK; } /* add the new entropy */ if ((err = hash_descriptor[prng->u.yarrow.hash]->process(&md, in, inlen)) != CRYPT_OK) { goto LBL_UNLOCK; } /* store result */ err = hash_descriptor[prng->u.yarrow.hash]->done(&md, prng->u.yarrow.pool); LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Make the PRNG ready to read from @param prng The PRNG to make active @return CRYPT_OK if successful */ int yarrow_ready(prng_state *prng) { int ks, err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { goto LBL_UNLOCK; } if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { goto LBL_UNLOCK; } /* setup CTR mode using the "pool" as the key */ ks = (int)hash_descriptor[prng->u.yarrow.hash]->hashsize; if ((err = cipher_descriptor[prng->u.yarrow.cipher]->keysize(&ks)) != CRYPT_OK) { goto LBL_UNLOCK; } if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */ prng->u.yarrow.pool, /* IV */ prng->u.yarrow.pool, ks, /* KEY and key size */ 0, /* number of rounds */ CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ &prng->u.yarrow.ctr)) != CRYPT_OK) { goto LBL_UNLOCK; } prng->ready = 1; LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return err; } /** Read from the PRNG @param out Destination @param outlen Length of output @param prng The active PRNG to read from @return Number of octets read */ unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) { if (outlen == 0 || prng == NULL || out == NULL) return 0; LTC_MUTEX_LOCK(&prng->lock); if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } /* put out in predictable state first */ zeromem(out, outlen); /* now randomize it */ if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) { outlen = 0; } LBL_UNLOCK: LTC_MUTEX_UNLOCK(&prng->lock); return outlen; } /** Terminate the PRNG @param prng The PRNG to terminate @return CRYPT_OK if successful */ int yarrow_done(prng_state *prng) { int err; LTC_ARGCHK(prng != NULL); LTC_MUTEX_LOCK(&prng->lock); prng->ready = 0; /* call cipher done when we invent one ;-) */ /* we invented one */ err = ctr_done(&prng->u.yarrow.ctr); LTC_MUTEX_UNLOCK(&prng->lock); LTC_MUTEX_DESTROY(&prng->lock); return err; } /** Export the PRNG state @param out [out] Destination @param outlen [in/out] Max size and resulting size of the state @param prng The PRNG to export @return CRYPT_OK if successful */ LTC_PRNG_EXPORT(yarrow) /** Import a PRNG state @param in The PRNG state @param inlen Size of the state @param prng The PRNG to import @return CRYPT_OK if successful */ int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) { int err; LTC_ARGCHK(in != NULL); LTC_ARGCHK(prng != NULL); if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG; if ((err = yarrow_start(prng)) != CRYPT_OK) return err; if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; return CRYPT_OK; } /** PRNG self-test @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled */ int yarrow_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else int err; prng_state prng; if ((err = yarrow_start(&prng)) != CRYPT_OK) { return err; } /* now let's test the hash/cipher that was chosen */ if (cipher_descriptor[prng.u.yarrow.cipher]->test && ((err = cipher_descriptor[prng.u.yarrow.cipher]->test()) != CRYPT_OK)) { return err; } if (hash_descriptor[prng.u.yarrow.hash]->test && ((err = hash_descriptor[prng.u.yarrow.hash]->test()) != CRYPT_OK)) { return err; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/000077500000000000000000000000001464416617300214775ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/000077500000000000000000000000001464416617300227065ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_crypt.c000066400000000000000000000050461464416617300255070ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA #define QUARTERROUND(a,b,c,d) \ x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 16); \ x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 12); \ x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 8); \ x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 7); static void s_chacha_block(unsigned char *output, const ulong32 *input, int rounds) { ulong32 x[16]; int i; XMEMCPY(x, input, sizeof(x)); for (i = rounds; i > 0; i -= 2) { QUARTERROUND(0, 4, 8,12) QUARTERROUND(1, 5, 9,13) QUARTERROUND(2, 6,10,14) QUARTERROUND(3, 7,11,15) QUARTERROUND(0, 5,10,15) QUARTERROUND(1, 6,11,12) QUARTERROUND(2, 7, 8,13) QUARTERROUND(3, 4, 9,14) } for (i = 0; i < 16; ++i) { x[i] += input[i]; STORE32L(x[i], output + 4 * i); } } /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha @param st The ChaCha state @param in The plaintext (or ciphertext) @param inlen The length of the input (octets) @param out [out] The ciphertext (or plaintext), length inlen @return CRYPT_OK if successful */ int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { unsigned char buf[64]; unsigned long i, j; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(st->ivlen != 0); if (st->ksleft > 0) { j = MIN(st->ksleft, inlen); for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; inlen -= j; if (inlen == 0) return CRYPT_OK; out += j; in += j; } for (;;) { s_chacha_block(buf, st->input, st->rounds); if (st->ivlen == 8) { /* IV-64bit, increment 64bit counter */ if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW; } else { /* IV-96bit, increment 32bit counter */ if (0 == ++st->input[12]) return CRYPT_OVERFLOW; } if (inlen <= 64) { for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; st->ksleft = 64 - inlen; for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; return CRYPT_OK; } for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; inlen -= 64; out += 64; in += 64; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_done.c000066400000000000000000000006121464416617300252650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA /** Terminate and clear ChaCha state @param st The ChaCha state @return CRYPT_OK on success */ int chacha_done(chacha_state *st) { LTC_ARGCHK(st != NULL); zeromem(st, sizeof(chacha_state)); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr32.c000066400000000000000000000016701464416617300256410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA /** Set IV + counter data to the ChaCha state @param st The ChaCha20 state @param iv The IV data to add @param ivlen The length of the IV (must be 12) @param counter 32bit (unsigned) initial counter value @return CRYPT_OK on success */ int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL); /* 96bit IV + 32bit counter */ LTC_ARGCHK(ivlen == 12); st->input[12] = counter; LOAD32L(st->input[13], iv + 0); LOAD32L(st->input[14], iv + 4); LOAD32L(st->input[15], iv + 8); st->ksleft = 0; st->ivlen = ivlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_ivctr64.c000066400000000000000000000017301464416617300256430ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA /** Set IV + counter data to the ChaCha state @param st The ChaCha20 state @param iv The IV data to add @param ivlen The length of the IV (must be 8) @param counter 64bit (unsigned) initial counter value @return CRYPT_OK on success */ int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL); /* 64bit IV + 64bit counter */ LTC_ARGCHK(ivlen == 8); st->input[12] = (ulong32)(counter & 0xFFFFFFFF); st->input[13] = (ulong32)(counter >> 32); LOAD32L(st->input[14], iv + 0); LOAD32L(st->input[15], iv + 4); st->ksleft = 0; st->ivlen = ivlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_keystream.c000066400000000000000000000013151464416617300263450ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA /** Generate a stream of random bytes via ChaCha @param st The ChaCha20 state @param out [out] The output buffer @param outlen The output length @return CRYPT_OK on success */ int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen) { if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); XMEMSET(out, 0, outlen); return chacha_crypt(st, out, outlen, out); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_memory.c000066400000000000000000000026231464416617300256540ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha @param key The key @param keylen The key length @param iv The initial vector @param ivlen The initial vector length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param rounds The number of rounds @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, const unsigned char *iv, unsigned long ivlen, ulong64 counter, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { chacha_state st; int err; LTC_ARGCHK(ivlen <= 8 || counter < 4294967296); /* 2**32 */ if ((err = chacha_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; if (ivlen > 8) { if ((err = chacha_ivctr32(&st, iv, ivlen, (ulong32)counter)) != CRYPT_OK) goto WIPE_KEY; } else { if ((err = chacha_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; } err = chacha_crypt(&st, datain, datalen, dataout); WIPE_KEY: chacha_done(&st); return err; } #endif /* LTC_CHACHA */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_setup.c000066400000000000000000000032101464416617300254750ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA static const char * const sigma = "expand 32-byte k"; static const char * const tau = "expand 16-byte k"; /** Initialize an ChaCha context (only the key) @param st [out] The destination of the ChaCha state @param key The secret key @param keylen The length of the secret key (octets) @param rounds Number of rounds (e.g. 20 for ChaCha20) @return CRYPT_OK if successful */ int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds) { const char *constants; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen == 32 || keylen == 16); if (rounds == 0) rounds = 20; LOAD32L(st->input[4], key + 0); LOAD32L(st->input[5], key + 4); LOAD32L(st->input[6], key + 8); LOAD32L(st->input[7], key + 12); if (keylen == 32) { /* 256bit */ key += 16; constants = sigma; } else { /* 128bit */ constants = tau; } LOAD32L(st->input[8], key + 0); LOAD32L(st->input[9], key + 4); LOAD32L(st->input[10], key + 8); LOAD32L(st->input[11], key + 12); LOAD32L(st->input[0], constants + 0); LOAD32L(st->input[1], constants + 4); LOAD32L(st->input[2], constants + 8); LOAD32L(st->input[3], constants + 12); st->rounds = rounds; /* e.g. 20 for chacha20 */ st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */ return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/chacha/chacha_test.c000066400000000000000000000105561464416617300253270ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_CHACHA int chacha_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned long len; unsigned char out[1000]; /* https://tools.ietf.org/html/rfc7539#section-2.4.2 */ unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 }; unsigned char ct[] = { 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80, 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81, 0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2, 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B, 0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB, 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57, 0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB, 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8, 0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61, 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E, 0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06, 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36, 0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6, 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42, 0x87, 0x4D }; char pt[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; chacha_state st; int err; len = XSTRLEN(pt); /* crypt piece by piece - using chacha_ivctr32() */ if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt, 35, out )) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt + 35, 35, out + 35)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt + 70, 5, out + 70)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt + 75, 5, out + 75)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt + 80, len - 80, out + 80)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in one go - using chacha_ivctr32() */ if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in one go - using chacha_ivctr64() */ if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; if ((err = chacha_ivctr64(&st, n + 4, sizeof(n) - 4, 1)) != CRYPT_OK) return err; if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in a single call using 32-bit counter with a value of 1 */ if ((err = chacha_memory(k, sizeof(k), 20, n, sizeof(n), 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in a single call using 64-bit counter with a value of 1 */ if ((err = chacha_memory(k, sizeof(k), 20, n + 4, sizeof(n) - 4, 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rabbit/000077500000000000000000000000001464416617300227425ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rabbit/rabbit.c000066400000000000000000000435731464416617300243650ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /****************************************************************************** * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission * and should run on any conforming C implementation (C90 or later). * * This implementation supports any key length up to 128 bits (16 bytes) and * works in increments of 8-bit bytes. Keys must be submitted as whole bytes * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv * may be any length up to 8 bytes and will be padded out to 8 bytes. * * The eSTREAM submission was rather picky about the calling sequence of * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed * calling ECRYPT_process_blocks() multiple times for a multiple of whole * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls * were supported correctly. This implementation handles the keystream * differently and rabbit_crypt() may be called as many times as desired, * crypting any number of bytes each time. * * http://www.ecrypt.eu.org/stream/e2-rabbit.html * * NB: One of the test vectors distributed by the eSTREAM site in the file * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" * in that ZIP file, the 3rd line in "out1" should be * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". * * Here is the original legal notice accompanying the Rabbit submission * to the EU eSTREAM competition. *--------------------------------------------------------------------------- * Copyright (C) Cryptico A/S. All rights reserved. * * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. * * This software is developed by Cryptico A/S and/or its suppliers. * All title and intellectual property rights in and to the software, * including but not limited to patent rights and copyrights, are owned * by Cryptico A/S and/or its suppliers. * * The software may be used solely for non-commercial purposes * without the prior written consent of Cryptico A/S. For further * information on licensing terms and conditions please contact * Cryptico A/S at info@cryptico.com * * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" * are either trademarks or registered trademarks of Cryptico A/S. * * Cryptico A/S shall not in any way be liable for any use of this * software. The software is provided "as is" without any express or * implied warranty. *--------------------------------------------------------------------------- * On October 6, 2008, Rabbit was "released into the public domain and * may be used freely for any purpose." * http://www.ecrypt.eu.org/stream/rabbitpf.html * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 ******************************************************************************/ #include "tomcrypt_private.h" #ifdef LTC_RABBIT /* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */ static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x); static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance); static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out); /* -------------------------------------------------------------------------- */ /* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ /* the upper 32 bits XOR the lower 32 bits */ static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x) { ulong32 a, b, h, l; /* Construct high and low argument for squaring */ a = x & 0xFFFF; b = x >> 16; /* Calculate high and low result of squaring */ h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b; l = x * x; /* Return high XOR low */ return (ulong32)(h^l); } /* -------------------------------------------------------------------------- */ /* Calculate the next internal state */ static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance) { ulong32 g[8], c_old[8], i; /* Save old counter values */ for (i=0; i<8; i++) { c_old[i] = p_instance->c[i]; } /* Calculate new counter values */ p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry); p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0])); p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1])); p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2])); p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3])); p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4])); p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5])); p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6])); p_instance->carry = (p_instance->c[7] < c_old[7]); /* Calculate the g-values */ for (i=0;i<8;i++) { g[i] = ss_rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i])); } /* Calculate new state values */ p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16)); p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]); p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16)); p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]); p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16)); p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]); p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16)); p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]); } /* ------------------------------------------------------------------------- */ static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out) { ulong32 *ptr; /* Iterate the work context once */ ss_rabbit_next_state(&(st->work_ctx)); /* Generate 16 bytes of pseudo-random data */ ptr = (ulong32*)&(st->work_ctx.x); STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0); STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4); STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8); STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12); } /* -------------------------------------------------------------------------- */ /* Key setup */ int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen) { ulong32 k0, k1, k2, k3, i; unsigned char tmpkey[16] = {0}; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen <= 16); /* init state */ XMEMSET(st, 0, sizeof(rabbit_state)); /* pad key in tmpkey */ XMEMCPY(tmpkey, key, keylen); /* Generate four subkeys */ LOAD32L(k0, tmpkey+ 0); LOAD32L(k1, tmpkey+ 4); LOAD32L(k2, tmpkey+ 8); LOAD32L(k3, tmpkey+12); #ifdef LTC_CLEAN_STACK /* done with tmpkey, wipe it */ zeromem(tmpkey, sizeof(tmpkey)); #endif /* Generate initial state variables */ st->master_ctx.x[0] = k0; st->master_ctx.x[2] = k1; st->master_ctx.x[4] = k2; st->master_ctx.x[6] = k3; st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16); st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16); st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16); st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16); /* Generate initial counter values */ st->master_ctx.c[0] = ROLc(k2, 16); st->master_ctx.c[2] = ROLc(k3, 16); st->master_ctx.c[4] = ROLc(k0, 16); st->master_ctx.c[6] = ROLc(k1, 16); st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); /* Clear carry bit */ st->master_ctx.carry = 0; /* Iterate the master context four times */ for (i=0; i<4; i++) { ss_rabbit_next_state(&(st->master_ctx)); } /* Modify the counters */ for (i=0; i<8; i++) { st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7]; } /* Copy master instance to work instance */ for (i=0; i<8; i++) { st->work_ctx.x[i] = st->master_ctx.x[i]; st->work_ctx.c[i] = st->master_ctx.c[i]; } st->work_ctx.carry = st->master_ctx.carry; /* ...and prepare block for crypt() */ XMEMSET(&(st->block), 0, sizeof(st->block)); st->unused = 0; return CRYPT_OK; } /* -------------------------------------------------------------------------- */ /* IV setup */ int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen) { ulong32 i0, i1, i2, i3, i; unsigned char tmpiv[8] = {0}; LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL || ivlen == 0); LTC_ARGCHK(ivlen <= 8); /* pad iv in tmpiv */ if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen); /* Generate four subvectors */ LOAD32L(i0, tmpiv+0); LOAD32L(i2, tmpiv+4); i1 = (i0>>16) | (i2&0xFFFF0000); i3 = (i2<<16) | (i0&0x0000FFFF); /* Modify counter values */ st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0; st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1; st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2; st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3; st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0; st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1; st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2; st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3; /* Copy state variables */ for (i=0; i<8; i++) { st->work_ctx.x[i] = st->master_ctx.x[i]; } st->work_ctx.carry = st->master_ctx.carry; /* Iterate the work context four times */ for (i=0; i<4; i++) { ss_rabbit_next_state(&(st->work_ctx)); } /* reset keystream buffer and unused count */ XMEMSET(&(st->block), 0, sizeof(st->block)); st->unused = 0; return CRYPT_OK; } /* ------------------------------------------------------------------------- */ /* Crypt a chunk of any size (encrypt/decrypt) */ int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out) { unsigned char buf[16]; unsigned long i, j; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); if (st->unused > 0) { j = MIN(st->unused, inlen); for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused]; inlen -= j; if (inlen == 0) return CRYPT_OK; out += j; in += j; } for (;;) { /* gen a block for buf */ ss_rabbit_gen_1_block(st, buf); if (inlen <= 16) { /* XOR and send to out */ for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; st->unused = 16 - inlen; /* copy remainder to block */ for (i = inlen; i < 16; ++i) st->block[i] = buf[i]; return CRYPT_OK; } /* XOR entire buf and send to out */ for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i]; inlen -= 16; out += 16; in += 16; } } /* ------------------------------------------------------------------------- */ int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen) { if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); XMEMSET(out, 0, outlen); return rabbit_crypt(st, out, outlen, out); } /* -------------------------------------------------------------------------- */ int rabbit_done(rabbit_state *st) { LTC_ARGCHK(st != NULL); zeromem(st, sizeof(rabbit_state)); return CRYPT_OK; } /* -------------------------------------------------------------------------- */ int rabbit_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else rabbit_state st; int err; unsigned char out[1000] = { 0 }; { /* all 3 tests use key and iv fm set 6, vector 3, the last vector in: http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log */ /* --- Test 1 (generate whole blocks) --------------------------------- */ { unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; char pt[64] = { 0 }; unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C, 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39, 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D, 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F }; unsigned long ptlen = sizeof(pt); /* crypt 64 nulls */ if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err; if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; } /* --- Test 2 (generate unusual number of bytes each time) ------------ */ { unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; char pt[39] = { 0 }; unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D }; unsigned long ptlen = sizeof(pt); /* crypt piece by piece (hit at least one 16-byte boundary) */ if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err; if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; } /* --- Test 3 (use non-null data) ------------------------------------- */ { unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; char pt[] = "Kilroy was here, there, and everywhere!"; unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd, 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54, 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60, 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87, 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac }; unsigned long ptlen = XSTRLEN(pt); unsigned char out2[1000] = { 0 }; unsigned char nulls[1000] = { 0 }; /* crypt piece by piece */ if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err; if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; /* --- Test 4 (crypt in a single call) ------------------------------------ */ if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv), (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err; if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; /* use 'out' (ciphertext) in the next decryption test */ /* --- Test 5 (decrypt ciphertext) ------------------------------------ */ /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */ if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err; if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; /* --- Test 6 (wipe state, incl key) ---------------------------------- */ if ((err = rabbit_done(&st)) != CRYPT_OK) return err; if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; } #endif } /* -------------------------------------------------------------------------- */ #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rabbit/rabbit_memory.c000066400000000000000000000023331464416617300257420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * chacha-ref.c version 20080118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_RABBIT /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Rabbit @param key The key @param keylen The key length @param iv The initial vector @param ivlen The initial vector length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int rabbit_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { rabbit_state st; int err; if ((err = rabbit_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; if ((err = rabbit_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; err = rabbit_crypt(&st, datain, datalen, dataout); WIPE_KEY: rabbit_done(&st); return err; } #endif /* LTC_RABBIT */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rc4/000077500000000000000000000000001464416617300221675ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rc4/rc4_stream.c000066400000000000000000000046001464416617300243760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_RC4_STREAM /** Initialize an RC4 context (only the key) @param st [out] The destination of the RC4 state @param key The secret key @param keylen The length of the secret key (8 - 256 bytes) @return CRYPT_OK if successful */ int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) { unsigned char tmp, *s; int x, y; unsigned long j; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */ s = st->buf; for (x = 0; x < 256; x++) { s[x] = x; } for (j = x = y = 0; x < 256; x++) { y = (y + s[x] + key[j++]) & 255; if (j == keylen) { j = 0; } tmp = s[x]; s[x] = s[y]; s[y] = tmp; } st->x = 0; st->y = 0; return CRYPT_OK; } /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 @param st The RC4 state @param in The plaintext (or ciphertext) @param inlen The length of the input (octets) @param out [out] The ciphertext (or plaintext), length inlen @return CRYPT_OK if successful */ int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { unsigned char x, y, *s, tmp; LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); x = st->x; y = st->y; s = st->buf; while (inlen--) { x = (x + 1) & 255; y = (y + s[x]) & 255; tmp = s[x]; s[x] = s[y]; s[y] = tmp; tmp = (s[x] + s[y]) & 255; *out++ = *in++ ^ s[tmp]; } st->x = x; st->y = y; return CRYPT_OK; } /** Generate a stream of random bytes via RC4 @param st The RC420 state @param out [out] The output buffer @param outlen The output length @return CRYPT_OK on success */ int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) { if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); XMEMSET(out, 0, outlen); return rc4_stream_crypt(st, out, outlen, out); } /** Terminate and clear RC4 state @param st The RC4 state @return CRYPT_OK on success */ int rc4_stream_done(rc4_state *st) { LTC_ARGCHK(st != NULL); zeromem(st, sizeof(rc4_state)); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rc4/rc4_stream_memory.c000066400000000000000000000016471464416617300257760ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_RC4_STREAM /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 @param key The key @param keylen The key length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int rc4_stream_memory(const unsigned char *key, unsigned long keylen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { rc4_state st; int err; if ((err = rc4_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; err = rc4_stream_crypt(&st, datain, datalen, dataout); WIPE_KEY: rc4_stream_done(&st); return err; } #endif /* LTC_RC4_STREAM */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/rc4/rc4_test.c000066400000000000000000000022151464416617300240620ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_RC4_STREAM int rc4_stream_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else rc4_state st; int err; const unsigned char key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; const unsigned char pt[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; const unsigned char ct[] = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }; unsigned char buf[10]; if ((err = rc4_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; if ((err = rc4_stream_crypt(&st, pt, sizeof(pt), buf)) != CRYPT_OK) return err; if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV1", 0)) return CRYPT_FAIL_TESTVECTOR; if ((err = rc4_stream_done(&st)) != CRYPT_OK) return err; /* crypt in a single call */ if ((err = rc4_stream_memory(key, sizeof(key), pt, sizeof(pt), buf)) != CRYPT_OK) return err; if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV2", 0)) return CRYPT_FAIL_TESTVECTOR; return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/000077500000000000000000000000001464416617300227445ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_crypt.c000066400000000000000000000047271464416617300256100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 #define QUARTERROUND(a,b,c,d) \ x[b] ^= (ROL((x[a] + x[d]), 7)); \ x[c] ^= (ROL((x[b] + x[a]), 9)); \ x[d] ^= (ROL((x[c] + x[b]), 13)); \ x[a] ^= (ROL((x[d] + x[c]), 18)); static void s_salsa20_block(unsigned char *output, const ulong32 *input, int rounds) { ulong32 x[16]; int i; XMEMCPY(x, input, sizeof(x)); for (i = rounds; i > 0; i -= 2) { QUARTERROUND( 0, 4, 8,12) QUARTERROUND( 5, 9,13, 1) QUARTERROUND(10,14, 2, 6) QUARTERROUND(15, 3, 7,11) QUARTERROUND( 0, 1, 2, 3) QUARTERROUND( 5, 6, 7, 4) QUARTERROUND(10,11, 8, 9) QUARTERROUND(15,12,13,14) } for (i = 0; i < 16; ++i) { x[i] += input[i]; STORE32L(x[i], output + 4 * i); } } /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 @param st The Salsa20 state @param in The plaintext (or ciphertext) @param inlen The length of the input (octets) @param out [out] The ciphertext (or plaintext), length inlen @return CRYPT_OK if successful */ int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { unsigned char buf[64]; unsigned long i, j; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24); if (st->ksleft > 0) { j = MIN(st->ksleft, inlen); for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; inlen -= j; if (inlen == 0) return CRYPT_OK; out += j; in += j; } for (;;) { s_salsa20_block(buf, st->input, st->rounds); /* Salsa20: 64-bit IV, increment 64-bit counter */ if (0 == ++st->input[8] && 0 == ++st->input[9]) return CRYPT_OVERFLOW; if (inlen <= 64) { for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; st->ksleft = 64 - inlen; for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; return CRYPT_OK; } for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; inlen -= 64; out += 64; in += 64; } } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_done.c000066400000000000000000000006201464416617300253600ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 /** Terminate and clear Salsa20 state @param st The Salsa20 state @return CRYPT_OK on success */ int salsa20_done(salsa20_state *st) { LTC_ARGCHK(st != NULL); zeromem(st, sizeof(salsa20_state)); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c000066400000000000000000000020541464416617300257370ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 /** Set IV + counter data to the Salsa20 state @param st The Salsa20 state @param iv The IV data to add @param ivlen The length of the IV (must be 8) @param counter 64bit (unsigned) initial counter value @return CRYPT_OK on success */ int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL); /* Salsa20: 64-bit IV (nonce) + 64-bit counter */ LTC_ARGCHK(ivlen == 8); LOAD32L(st->input[6], iv + 0); LOAD32L(st->input[7], iv + 4); st->input[8] = (ulong32)(counter & 0xFFFFFFFF); st->input[9] = (ulong32)(counter >> 32); st->ksleft = 0; st->ivlen = ivlen; return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_keystream.c000066400000000000000000000014231464416617300264410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 /** Generate a stream of random bytes via Salsa20 @param st The Salsa20 state @param out [out] The output buffer @param outlen The output length @return CRYPT_OK on success */ int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen) { if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); XMEMSET(out, 0, outlen); return salsa20_crypt(st, out, outlen, out); } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_memory.c000066400000000000000000000023101464416617300257410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 @param key The key @param keylen The key length @param iv The initial vector @param ivlen The initial vector length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param rounds The number of rounds @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, const unsigned char *iv, unsigned long ivlen, ulong64 counter, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { salsa20_state st; int err; if ((err = salsa20_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; if ((err = salsa20_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; err = salsa20_crypt(&st, datain, datalen, dataout); WIPE_KEY: salsa20_done(&st); return err; } #endif /* LTC_SALSA20 */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_setup.c000066400000000000000000000034771464416617300256100ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 static const char * const sigma = "expand 32-byte k"; static const char * const tau = "expand 16-byte k"; /** Initialize an Salsa20 context (only the key) @param st [out] The destination of the Salsa20 state @param key The secret key @param keylen The length of the secret key (octets) @param rounds Number of rounds (e.g. 20 for Salsa20) @return CRYPT_OK if successful */ int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds) { const char *constants; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen == 32 || keylen == 16); if (rounds == 0) rounds = 20; LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ LOAD32L(st->input[1], key + 0); LOAD32L(st->input[2], key + 4); LOAD32L(st->input[3], key + 8); LOAD32L(st->input[4], key + 12); if (keylen == 32) { /* 256bit */ key += 16; constants = sigma; } else { /* 128bit */ constants = tau; } LOAD32L(st->input[11], key + 0); LOAD32L(st->input[12], key + 4); LOAD32L(st->input[13], key + 8); LOAD32L(st->input[14], key + 12); LOAD32L(st->input[ 0], constants + 0); LOAD32L(st->input[ 5], constants + 4); LOAD32L(st->input[10], constants + 8); LOAD32L(st->input[15], constants + 12); st->rounds = rounds; /* default is 20 for salsa20 */ st->ivlen = 0; /* will be set later by salsa20_ivctr(32|64) */ return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/salsa20_test.c000066400000000000000000000114211464416617300254130ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt_private.h" #ifdef LTC_SALSA20 int salsa20_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else salsa20_state st; unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a }; unsigned char ct[] = { 0x37, 0x37, 0x2e, 0x60, 0xb8, 0xae, 0x88, 0x1f, 0xf8, 0xdf, 0x00, 0x26, 0x6c, 0x30, 0x34, 0x2d, 0xa1, 0xd7, 0x79, 0x60, 0x67, 0x72, 0xe0, 0x67, 0x26, 0x22, 0xad, 0x00, 0x9e, 0xd5, 0x59, 0x44, 0x51, 0xd9, 0xe6, 0xaa, 0xc9, 0x59, 0x9e, 0x60, 0xff, 0x87, 0x90, 0xc1, 0xc9, 0x1e }; unsigned char ct2[] = { 0xec, 0x06, 0x32, 0xb3, 0x83, 0x5c, 0xae, 0x91, 0x01, 0x82, 0x7a, 0x71, 0xd9, 0x7d, 0x45, 0xd7, 0xa6, 0x5b, 0xa0, 0x89, 0x9d, 0xd2, 0x6c, 0xaa, 0xbb, 0x2f, 0x5f, 0x30, 0x89, 0x54, 0xff, 0x3e, 0x83, 0xc3, 0x34, 0x10, 0xb6, 0xe1, 0xab, 0xe7, 0xf5, 0xab, 0xab, 0xed, 0xa4, 0xff }; char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ unsigned long len; unsigned char out[1000]; int counter; int rounds; int err; len = XSTRLEN(pt); /* crypt piece by piece */ counter = 0; rounds = 12; if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "SALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in one go - using salsa20_ivctr64() */ counter = 0; rounds = 20; if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in a single call */ if ((err = salsa20_memory(k, sizeof(k), rounds, n, sizeof(n), counter, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; { /* keystream * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup * Set 6, vector 0 */ unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE }; unsigned char ct3[] = { 0xF5, 0xFA, 0xD5, 0x3F, 0x79, 0xF9, 0xDF, 0x58, 0xC4, 0xAE, 0xA0, 0xD0, 0xED, 0x9A, 0x96, 0x01, 0xF2, 0x78, 0x11, 0x2C, 0xA7, 0x18, 0x0D, 0x56, 0x5B, 0x42, 0x0A, 0x48, 0x01, 0x96, 0x70, 0xEA, 0xF2, 0x4C, 0xE4, 0x93, 0xA8, 0x62, 0x63, 0xF6, 0x77, 0xB4, 0x6A, 0xCE, 0x19, 0x24, 0x77, 0x3D, 0x2B, 0xB2, 0x55, 0x71, 0xE1, 0xAA, 0x85, 0x93, 0x75, 0x8F, 0xC3, 0x82, 0xB1, 0x28, 0x0B, 0x71 }; int counter3 = 0; int rounds3 = 20; if ((err = salsa20_setup(&st, k3, sizeof(k3), rounds3)) != CRYPT_OK) return err; if ((err = salsa20_ivctr64(&st, n3, sizeof(n3), counter3)) != CRYPT_OK) return err; if ((err = salsa20_keystream(&st, out, 64)) != CRYPT_OK) return err; if ((err = salsa20_done(&st)) != CRYPT_OK) return err; if (compare_testvector(out, 64, ct3, sizeof(ct3), "SALSA20-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c000066400000000000000000000022051464416617300261340ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_XSALSA20 /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with XSalsa20 @param key The key @param keylen The key length @param nonce The initial vector @param noncelen The initial vector length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param rounds The number of rounds @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, const unsigned char *nonce, unsigned long noncelen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { salsa20_state st; int err; if ((err = xsalsa20_setup(&st, key, keylen, nonce, noncelen, rounds)) != CRYPT_OK) goto WIPE_KEY; err = salsa20_crypt(&st, datain, datalen, dataout); WIPE_KEY: salsa20_done(&st); return err; } #endif /* LTC_XSALSA20 */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c000066400000000000000000000076201464416617300257720ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt.h" #ifdef LTC_XSALSA20 static const char * const constants = "expand 32-byte k"; #define QUARTERROUND(a,b,c,d) \ x[b] ^= (ROL((x[a] + x[d]), 7)); \ x[c] ^= (ROL((x[b] + x[a]), 9)); \ x[d] ^= (ROL((x[c] + x[b]), 13)); \ x[a] ^= (ROL((x[d] + x[c]), 18)); /* use modified salsa20 doubleround (no final addition as in salsa20) */ static void s_xsalsa20_doubleround(ulong32 *x, int rounds) { int i; for (i = rounds; i > 0; i -= 2) { /* columnround */ QUARTERROUND( 0, 4, 8,12) QUARTERROUND( 5, 9,13, 1) QUARTERROUND(10,14, 2, 6) QUARTERROUND(15, 3, 7,11) /* rowround */ QUARTERROUND( 0, 1, 2, 3) QUARTERROUND( 5, 6, 7, 4) QUARTERROUND(10,11, 8, 9) QUARTERROUND(15,12,13,14) } } #undef QUARTERROUND /** Initialize an XSalsa20 context @param st [out] The destination of the XSalsa20 state @param key The secret key @param keylen The length of the secret key, must be 32 (octets) @param nonce The nonce @param noncelen The length of the nonce, must be 24 (octets) @param rounds Number of rounds (must be evenly divisible by 2, default is 20) @return CRYPT_OK if successful */ int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, const unsigned char *nonce, unsigned long noncelen, int rounds) { const int sti[] = {0, 5, 10, 15, 6, 7, 8, 9}; /* indices used to build subkey fm x */ ulong32 x[64]; /* input to & output fm doubleround */ unsigned char subkey[32]; int i; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen == 32); LTC_ARGCHK(nonce != NULL); LTC_ARGCHK(noncelen == 24); if (rounds == 0) rounds = 20; LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ /* load the state to "hash" the key */ LOAD32L(x[ 0], constants + 0); LOAD32L(x[ 5], constants + 4); LOAD32L(x[10], constants + 8); LOAD32L(x[15], constants + 12); LOAD32L(x[ 1], key + 0); LOAD32L(x[ 2], key + 4); LOAD32L(x[ 3], key + 8); LOAD32L(x[ 4], key + 12); LOAD32L(x[11], key + 16); LOAD32L(x[12], key + 20); LOAD32L(x[13], key + 24); LOAD32L(x[14], key + 28); LOAD32L(x[ 6], nonce + 0); LOAD32L(x[ 7], nonce + 4); LOAD32L(x[ 8], nonce + 8); LOAD32L(x[ 9], nonce + 12); /* use modified salsa20 doubleround (no final addition) */ s_xsalsa20_doubleround(x, rounds); /* extract the subkey */ for (i = 0; i < 8; ++i) { STORE32L(x[sti[i]], subkey + 4 * i); } /* load the final initial state */ LOAD32L(st->input[ 0], constants + 0); LOAD32L(st->input[ 5], constants + 4); LOAD32L(st->input[10], constants + 8); LOAD32L(st->input[15], constants + 12); LOAD32L(st->input[ 1], subkey + 0); LOAD32L(st->input[ 2], subkey + 4); LOAD32L(st->input[ 3], subkey + 8); LOAD32L(st->input[ 4], subkey + 12); LOAD32L(st->input[11], subkey + 16); LOAD32L(st->input[12], subkey + 20); LOAD32L(st->input[13], subkey + 24); LOAD32L(st->input[14], subkey + 28); LOAD32L(st->input[ 6], &(nonce[16]) + 0); LOAD32L(st->input[ 7], &(nonce[16]) + 4); st->input[ 8] = 0; st->input[ 9] = 0; st->rounds = rounds; st->ksleft = 0; st->ivlen = 24; /* set switch to say nonce/IV has been loaded */ #ifdef LTC_CLEAN_STACK zeromem(x, sizeof(x)); zeromem(subkey, sizeof(subkey)); #endif return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/salsa20/xsalsa20_test.c000066400000000000000000000100411464416617300256000ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* The implementation is based on: * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf * and salsa20-ref.c version 20051118 * Public domain from D. J. Bernstein */ #include "tomcrypt.h" #ifdef LTC_XSALSA20 #if defined(LTC_SHA256) && defined(LTC_TEST) static int s_sha256(unsigned char *hash, const unsigned char *data, const int datalen) { hash_state md; sha256_init(&md); sha256_process(&md, data, datalen); sha256_done(&md, hash); return CRYPT_OK; } #endif int xsalsa20_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else /*************************************************************************** * verify a round trip: */ { const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; const void *msg = "Kilroy was here!"; unsigned char msglen = 17; /* includes trailing NULL */ int rounds = 20; unsigned char ciphertext[17]; unsigned char msg2[17]; salsa20_state st; int err; if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, msg, msglen, ciphertext)) != CRYPT_OK) return err; if ((err = salsa20_done(&st)) != CRYPT_OK) return err; if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; if ((err = salsa20_crypt(&st, ciphertext, msglen, msg2)) != CRYPT_OK) return err; if ((err = salsa20_done(&st)) != CRYPT_OK) return err; if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; /* round trip with two single function calls */ if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), msg, msglen, ciphertext)) != CRYPT_OK) return err; if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), ciphertext, msglen, msg2)) != CRYPT_OK) return err; if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; } #ifdef LTC_SHA256 /*************************************************************************** * verify correct generation of a keystream */ { const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; const unsigned char expecthash[] = {0x6a,0x60,0x57,0x65,0x27,0xe0,0x00,0x51,0x6d,0xb0,0xda,0x60,0x46,0x20,0xf6,0xd0,0x95,0x65,0x45,0x39,0xf4,0x86,0x83,0x43,0x64,0xdf,0xd9,0x5a,0x6f,0x3f,0xbe,0xb7}; int rounds = 20; unsigned char keystream[91101]; unsigned long keystreamlen = 91101; unsigned char hash[32]; salsa20_state st; int err; if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; if ((err = salsa20_keystream(&st, keystream, keystreamlen)) != CRYPT_OK) return err; if ((err = salsa20_done(&st)) != CRYPT_OK) return err; if ((err = s_sha256(hash, keystream, keystreamlen)) != CRYPT_OK) return err; if (compare_testvector(hash, sizeof(hash), expecthash, sizeof(expecthash), "XSALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; } #endif return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sober128/000077500000000000000000000000001464416617300230445ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sober128/sober128_stream.c000066400000000000000000000164271464416617300261420ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file sober128_stream.c Implementation of SOBER-128 by Tom St Denis. Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. */ #ifdef LTC_SOBER128 #define LTC_SOBER128TAB_C #include "sober128tab.c" /* don't change these... */ #define N 17 #define INITKONST 0x6996c53a /* value of KONST to use during key loading */ #define KEYP 15 /* where to insert key words */ #define FOLDP 4 /* where to insert non-linear feedback */ static ulong32 BYTE2WORD(const unsigned char *b) { ulong32 t; LOAD32L(t, b); return t; } static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) { ulong32 t; LOAD32L(t, in); t ^= w; STORE32L(t, out); } /* give correct offset for the current position of the register, * where logically R[0] is at position "zero". */ #define OFF(zero, i) (((zero)+(i)) % N) /* step the LFSR */ /* After stepping, "zero" moves right one place */ #define STEP(R,z) \ R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; static void cycle(ulong32 *R) { ulong32 t; int i; STEP(R,0); t = R[0]; for (i = 1; i < N; ++i) { R[i-1] = R[i]; } R[N-1] = t; } /* Return a non-linear function of some parts of the register. */ #define NLFUNC(st,z) \ { \ t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \ t ^= Sbox[(t >> 24) & 0xFF]; \ t = RORc(t, 8); \ t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \ t ^= Sbox[(t >> 24) & 0xFF]; \ t = t + st->R[OFF(z,13)]; \ } static ulong32 nltap(const sober128_state *st) { ulong32 t; NLFUNC(st, 0); return t; } /* Save the current register state */ static void s128_savestate(sober128_state *st) { int i; for (i = 0; i < N; ++i) { st->initR[i] = st->R[i]; } } /* initialise to previously saved register state */ static void s128_reloadstate(sober128_state *st) { int i; for (i = 0; i < N; ++i) { st->R[i] = st->initR[i]; } } /* Initialise "konst" */ static void s128_genkonst(sober128_state *st) { ulong32 newkonst; do { cycle(st->R); newkonst = nltap(st); } while ((newkonst & 0xFF000000) == 0); st->konst = newkonst; } /* Load key material into the register */ #define ADDKEY(k) \ st->R[KEYP] += (k); #define XORNL(nl) \ st->R[FOLDP] ^= (nl); /* nonlinear diffusion of register for key */ #define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t; static void s128_diffuse(sober128_state *st) { ulong32 t; /* relies on FOLD == N == 17! */ DROUND(0); DROUND(1); DROUND(2); DROUND(3); DROUND(4); DROUND(5); DROUND(6); DROUND(7); DROUND(8); DROUND(9); DROUND(10); DROUND(11); DROUND(12); DROUND(13); DROUND(14); DROUND(15); DROUND(16); } /** Initialize an Sober128 context (only the key) @param st [out] The destination of the Sober128 state @param key The secret key @param keylen The length of the secret key (octets) @return CRYPT_OK if successful */ int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen) { ulong32 i, k; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen > 0); /* keylen must be multiple of 4 bytes */ if ((keylen & 3) != 0) { return CRYPT_INVALID_KEYSIZE; } /* Register initialised to Fibonacci numbers */ st->R[0] = 1; st->R[1] = 1; for (i = 2; i < N; ++i) { st->R[i] = st->R[i-1] + st->R[i-2]; } st->konst = INITKONST; for (i = 0; i < keylen; i += 4) { k = BYTE2WORD((unsigned char *)&key[i]); ADDKEY(k); cycle(st->R); XORNL(nltap(st)); } /* also fold in the length of the key */ ADDKEY(keylen); /* now diffuse */ s128_diffuse(st); s128_genkonst(st); s128_savestate(st); st->nbuf = 0; return CRYPT_OK; } /** Set IV to the Sober128 state @param st The Sober12820 state @param iv The IV data to add @param ivlen The length of the IV (must be 12) @return CRYPT_OK on success */ int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen) { ulong32 i, k; LTC_ARGCHK(st != NULL); LTC_ARGCHK(iv != NULL); LTC_ARGCHK(ivlen > 0); /* ok we are adding an IV then... */ s128_reloadstate(st); /* ivlen must be multiple of 4 bytes */ if ((ivlen & 3) != 0) { return CRYPT_INVALID_KEYSIZE; } for (i = 0; i < ivlen; i += 4) { k = BYTE2WORD((unsigned char *)&iv[i]); ADDKEY(k); cycle(st->R); XORNL(nltap(st)); } /* also fold in the length of the key */ ADDKEY(ivlen); /* now diffuse */ s128_diffuse(st); st->nbuf = 0; return CRYPT_OK; } /* XOR pseudo-random bytes into buffer */ #define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 @param st The Sober128 state @param in The plaintext (or ciphertext) @param inlen The length of the input (octets) @param out [out] The ciphertext (or plaintext), length inlen @return CRYPT_OK if successful */ int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { ulong32 t; if (inlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); LTC_ARGCHK(st != NULL); /* handle any previously buffered bytes */ while (st->nbuf != 0 && inlen != 0) { *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); st->sbuf >>= 8; st->nbuf -= 8; --inlen; } #ifndef LTC_SMALL_CODE /* do lots at a time, if there's enough to do */ while (inlen >= N*4) { SROUND(0); SROUND(1); SROUND(2); SROUND(3); SROUND(4); SROUND(5); SROUND(6); SROUND(7); SROUND(8); SROUND(9); SROUND(10); SROUND(11); SROUND(12); SROUND(13); SROUND(14); SROUND(15); SROUND(16); out += 4*N; in += 4*N; inlen -= 4*N; } #endif /* do small or odd size buffers the slow way */ while (4 <= inlen) { cycle(st->R); t = nltap(st); XORWORD(t, in, out); out += 4; in += 4; inlen -= 4; } /* handle any trailing bytes */ if (inlen != 0) { cycle(st->R); st->sbuf = nltap(st); st->nbuf = 32; while (st->nbuf != 0 && inlen != 0) { *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); st->sbuf >>= 8; st->nbuf -= 8; --inlen; } } return CRYPT_OK; } int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen) { if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); XMEMSET(out, 0, outlen); return sober128_stream_crypt(st, out, outlen, out); } /** Terminate and clear Sober128 state @param st The Sober128 state @return CRYPT_OK on success */ int sober128_stream_done(sober128_state *st) { LTC_ARGCHK(st != NULL); zeromem(st, sizeof(sober128_state)); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sober128/sober128_stream_memory.c000066400000000000000000000023121464416617300275160ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_SOBER128_STREAM /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with SOBER128 @param key The key @param keylen The key length @param iv The initial vector @param ivlen The initial vector length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int sober128_stream_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { sober128_state st; int err; if ((err = sober128_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; if ((err = sober128_stream_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; err = sober128_stream_crypt(&st, datain, datalen, dataout); WIPE_KEY: sober128_stream_done(&st); return err; } #endif /* LTC_SOBER128_STREAM */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sober128/sober128_test.c000066400000000000000000000030311464416617300256110ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_SOBER128 int sober128_stream_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char key[16] = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 }; unsigned char iv[4] = { 0x00, 0x00, 0x00, 0x00 }; unsigned char out[20] = { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d, 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, 0x40, 0x37, 0x8b, 0xbb }; int err, len = 20; unsigned char src[20], dst[20]; sober128_state st; XMEMSET(src, 0, len); /* input */ if ((err = sober128_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; if ((err = sober128_stream_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; if ((err = sober128_stream_crypt(&st, src, len, dst)) != CRYPT_OK) return err; if ((err = sober128_stream_done(&st)) != CRYPT_OK) return err; if (compare_testvector(dst, len, out, len, "SOBER-128-TV1", 0)) { return CRYPT_FAIL_TESTVECTOR; } /* crypt in a single call */ if ((err = sober128_stream_memory(key, sizeof(key), iv, sizeof(iv), src, len, dst)) != CRYPT_OK) return err; if (compare_testvector(dst, len, out, len, "SOBER-128-TV2", 0)) { return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sober128/sober128tab.c000066400000000000000000000172631464416617300252550ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /** @file sober128tab.c SOBER-128 Tables */ #ifdef LTC_SOBER128TAB_C /* $ID$ */ /* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ /* Multiplication table for Turing using 0xD02B4367 */ static const ulong32 Multab[256] = { 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, }; /* $ID$ */ /* Sbox for SOBER-128 */ /* * This is really the combination of two SBoxes; the least significant * 24 bits comes from: * 8->32 Sbox generated by Millan et. al. at Queensland University of * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, * "On the Design of 8*32 S-boxes". Unpublished report, by the * Information Systems Research Centre, * Queensland University of Technology, 1999. * * The most significant 8 bits are the Skipjack "F table", which can be * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . * In this optimised table, though, the intent is to XOR the word from * the table selected by the high byte with the input word. Thus, the * high byte is actually the Skipjack F-table entry XORED with its * table index. */ static const ulong32 Sbox[256] = { 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, }; #endif /* LTC_SOBER128TAB_C */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sosemanuk/000077500000000000000000000000001464416617300235045ustar00rootroot00000000000000optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk.c000066400000000000000000000643751464416617300256740ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ /* * This LTC implementation was adapted from: * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html */ /* * SOSEMANUK reference implementation. * * This code is supposed to run on any conforming C implementation (C90 * or later). * * (c) 2005 X-CRYPT project. This software is provided 'as-is', without * any express or implied warranty. In no event will the authors be held * liable for any damages arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to no restriction. * * Technical remarks and questions can be addressed to * */ #include "tomcrypt_private.h" #ifdef LTC_SOSEMANUK /* ======================================================================== */ /* * We want (and sometimes need) to perform explicit truncations to 32 bits. */ #define T32(x) ((x) & (ulong32)0xFFFFFFFF) /* * Some of our functions will be tagged as "inline" to help the compiler * optimize things. We use "inline" only if the compiler is advanced * enough to understand it; C99 compilers, and pre-C99 versions of gcc, * understand enough "inline" for our purposes. */ /* ======================================================================== */ /* * Serpent S-boxes, implemented in bitslice mode. These circuits have * been published by Dag Arne Osvik ("Speeding up Serpent", published in * the 3rd AES Candidate Conference) and work on five 32-bit registers: * the four inputs, and a fifth scratch register. There are meant to be * quite fast on Pentium-class processors. These are not the fastest * published, but they are "fast enough" and they are unencumbered as * far as intellectual property is concerned (note: these are rewritten * from the article itself, and hence are not covered by the GPL on * Dag's code, which was not used here). * * The output bits are permuted. Here is the correspondance: * S0: 1420 * S1: 2031 * S2: 2314 * S3: 1234 * S4: 1403 * S5: 1302 * S6: 0142 * S7: 4310 * (for instance, the output of S0 is in "r1, r4, r2, r0"). */ #define S0(r0, r1, r2, r3, r4) do { \ r3 ^= r0; r4 = r1; \ r1 &= r3; r4 ^= r2; \ r1 ^= r0; r0 |= r3; \ r0 ^= r4; r4 ^= r3; \ r3 ^= r2; r2 |= r1; \ r2 ^= r4; r4 = ~r4; \ r4 |= r1; r1 ^= r3; \ r1 ^= r4; r3 |= r0; \ r1 ^= r3; r4 ^= r3; \ } while (0) #define S1(r0, r1, r2, r3, r4) do { \ r0 = ~r0; r2 = ~r2; \ r4 = r0; r0 &= r1; \ r2 ^= r0; r0 |= r3; \ r3 ^= r2; r1 ^= r0; \ r0 ^= r4; r4 |= r1; \ r1 ^= r3; r2 |= r0; \ r2 &= r4; r0 ^= r1; \ r1 &= r2; \ r1 ^= r0; r0 &= r2; \ r0 ^= r4; \ } while (0) #define S2(r0, r1, r2, r3, r4) do { \ r4 = r0; r0 &= r2; \ r0 ^= r3; r2 ^= r1; \ r2 ^= r0; r3 |= r4; \ r3 ^= r1; r4 ^= r2; \ r1 = r3; r3 |= r4; \ r3 ^= r0; r0 &= r1; \ r4 ^= r0; r1 ^= r3; \ r1 ^= r4; r4 = ~r4; \ } while (0) #define S3(r0, r1, r2, r3, r4) do { \ r4 = r0; r0 |= r3; \ r3 ^= r1; r1 &= r4; \ r4 ^= r2; r2 ^= r3; \ r3 &= r0; r4 |= r1; \ r3 ^= r4; r0 ^= r1; \ r4 &= r0; r1 ^= r3; \ r4 ^= r2; r1 |= r0; \ r1 ^= r2; r0 ^= r3; \ r2 = r1; r1 |= r3; \ r1 ^= r0; \ } while (0) #define S4(r0, r1, r2, r3, r4) do { \ r1 ^= r3; r3 = ~r3; \ r2 ^= r3; r3 ^= r0; \ r4 = r1; r1 &= r3; \ r1 ^= r2; r4 ^= r3; \ r0 ^= r4; r2 &= r4; \ r2 ^= r0; r0 &= r1; \ r3 ^= r0; r4 |= r1; \ r4 ^= r0; r0 |= r3; \ r0 ^= r2; r2 &= r3; \ r0 = ~r0; r4 ^= r2; \ } while (0) #define S5(r0, r1, r2, r3, r4) do { \ r0 ^= r1; r1 ^= r3; \ r3 = ~r3; r4 = r1; \ r1 &= r0; r2 ^= r3; \ r1 ^= r2; r2 |= r4; \ r4 ^= r3; r3 &= r1; \ r3 ^= r0; r4 ^= r1; \ r4 ^= r2; r2 ^= r0; \ r0 &= r3; r2 = ~r2; \ r0 ^= r4; r4 |= r3; \ r2 ^= r4; \ } while (0) #define S6(r0, r1, r2, r3, r4) do { \ r2 = ~r2; r4 = r3; \ r3 &= r0; r0 ^= r4; \ r3 ^= r2; r2 |= r4; \ r1 ^= r3; r2 ^= r0; \ r0 |= r1; r2 ^= r1; \ r4 ^= r0; r0 |= r3; \ r0 ^= r2; r4 ^= r3; \ r4 ^= r0; r3 = ~r3; \ r2 &= r4; \ r2 ^= r3; \ } while (0) #define S7(r0, r1, r2, r3, r4) do { \ r4 = r1; r1 |= r2; \ r1 ^= r3; r4 ^= r2; \ r2 ^= r1; r3 |= r4; \ r3 &= r0; r4 ^= r2; \ r3 ^= r1; r1 |= r4; \ r1 ^= r0; r0 |= r4; \ r0 ^= r2; r1 ^= r4; \ r2 ^= r1; r1 &= r0; \ r1 ^= r4; r2 = ~r2; \ r2 |= r0; \ r4 ^= r2; \ } while (0) /* * The Serpent linear transform. */ #define SERPENT_LT(x0, x1, x2, x3) do { \ x0 = ROLc(x0, 13); \ x2 = ROLc(x2, 3); \ x1 = x1 ^ x0 ^ x2; \ x3 = x3 ^ x2 ^ T32(x0 << 3); \ x1 = ROLc(x1, 1); \ x3 = ROLc(x3, 7); \ x0 = x0 ^ x1 ^ x3; \ x2 = x2 ^ x3 ^ T32(x1 << 7); \ x0 = ROLc(x0, 5); \ x2 = ROLc(x2, 22); \ } while (0) /* ======================================================================== */ /* * Initialize Sosemanuk's state by providing a key. The key is an array of * 1 to 32 bytes. * @param st The Sosemanuk state * @param key Key * @param keylen Length of key in bytes * @return CRYPT_OK on success */ int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen) { /* * This key schedule is actually a truncated Serpent key schedule. * The key-derived words (w_i) are computed within the eight * local variables w0 to w7, which are reused again and again. */ #define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \ ulong32 r0, r1, r2, r3, r4; \ r0 = w ## o0; \ r1 = w ## o1; \ r2 = w ## o2; \ r3 = w ## o3; \ S(r0, r1, r2, r3, r4); \ st->kc[i ++] = r ## d0; \ st->kc[i ++] = r ## d1; \ st->kc[i ++] = r ## d2; \ st->kc[i ++] = r ## d3; \ } while (0) #define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0) #define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1) #define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4) #define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4) #define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3) #define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2) #define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2) #define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0) #define WUP(wi, wi5, wi3, wi1, cc) do { \ ulong32 tt = (wi) ^ (wi5) ^ (wi3) \ ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \ (wi) = ROLc(tt, 11); \ } while (0) #define WUP0(cc) do { \ WUP(w0, w3, w5, w7, cc); \ WUP(w1, w4, w6, w0, cc + 1); \ WUP(w2, w5, w7, w1, cc + 2); \ WUP(w3, w6, w0, w2, cc + 3); \ } while (0) #define WUP1(cc) do { \ WUP(w4, w7, w1, w3, cc); \ WUP(w5, w0, w2, w4, cc + 1); \ WUP(w6, w1, w3, w5, cc + 2); \ WUP(w7, w2, w4, w6, cc + 3); \ } while (0) unsigned char wbuf[32]; ulong32 w0, w1, w2, w3, w4, w5, w6, w7; int i = 0; LTC_ARGCHK(st != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(keylen > 0 && keylen <= 32); /* * The key is copied into the wbuf[] buffer and padded to 256 bits * as described in the Serpent specification. */ XMEMCPY(wbuf, key, keylen); if (keylen < 32) { wbuf[keylen] = 0x01; if (keylen < 31) { XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); } } LOAD32L(w0, wbuf); LOAD32L(w1, wbuf + 4); LOAD32L(w2, wbuf + 8); LOAD32L(w3, wbuf + 12); LOAD32L(w4, wbuf + 16); LOAD32L(w5, wbuf + 20); LOAD32L(w6, wbuf + 24); LOAD32L(w7, wbuf + 28); WUP0(0); SKS3; WUP1(4); SKS2; WUP0(8); SKS1; WUP1(12); SKS0; WUP0(16); SKS7; WUP1(20); SKS6; WUP0(24); SKS5; WUP1(28); SKS4; WUP0(32); SKS3; WUP1(36); SKS2; WUP0(40); SKS1; WUP1(44); SKS0; WUP0(48); SKS7; WUP1(52); SKS6; WUP0(56); SKS5; WUP1(60); SKS4; WUP0(64); SKS3; WUP1(68); SKS2; WUP0(72); SKS1; WUP1(76); SKS0; WUP0(80); SKS7; WUP1(84); SKS6; WUP0(88); SKS5; WUP1(92); SKS4; WUP0(96); SKS3; #undef SKS #undef SKS0 #undef SKS1 #undef SKS2 #undef SKS3 #undef SKS4 #undef SKS5 #undef SKS6 #undef SKS7 #undef WUP #undef WUP0 #undef WUP1 return CRYPT_OK; } /* * Initialization continues by setting the IV. The IV length is up to 16 bytes. * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple * encryptions/decryptions are to be performed with the same key and * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called * to set the state. * @param st The Sosemanuk state * @param iv Initialization vector * @param ivlen Length of iv in bytes * @return CRYPT_OK on success */ int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen) { /* * The Serpent key addition step. */ #define KA(zc, x0, x1, x2, x3) do { \ x0 ^= st->kc[(zc)]; \ x1 ^= st->kc[(zc) + 1]; \ x2 ^= st->kc[(zc) + 2]; \ x3 ^= st->kc[(zc) + 3]; \ } while (0) /* * One Serpent round. * zc = current subkey counter * S = S-box macro for this round * i0 to i4 = input register numbers (the fifth is a scratch register) * o0 to o3 = output register numbers */ #define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ } while (0) /* * Last Serpent round. Contrary to the "true" Serpent, we keep * the linear transformation for that last round. */ #define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \ } while (0) ulong32 r0, r1, r2, r3, r4; unsigned char ivtmp[16] = {0}; LTC_ARGCHK(st != NULL); LTC_ARGCHK(ivlen <= 16); LTC_ARGCHK(iv != NULL || ivlen == 0); if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); /* * Decode IV into four 32-bit words (little-endian). */ LOAD32L(r0, ivtmp); LOAD32L(r1, ivtmp + 4); LOAD32L(r2, ivtmp + 8); LOAD32L(r3, ivtmp + 12); /* * Encrypt IV with Serpent24. Some values are extracted from the * output of the twelfth, eighteenth and twenty-fourth rounds. */ FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0); FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4); FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3); FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2); FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2); FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4); FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1); FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0); FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4); FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3); FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0); FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2); st->s09 = r3; st->s08 = r1; st->s07 = r0; st->s06 = r2; FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2); FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3); FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1); FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4); FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3); FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0); st->r1 = r2; st->s04 = r1; st->r2 = r3; st->s05 = r0; FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4); FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2); FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2); FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0); FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1); FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3); st->s03 = r0; st->s02 = r1; st->s01 = r2; st->s00 = r3; st->ptr = sizeof(st->buf); #undef KA #undef FSS #undef FSF return CRYPT_OK; } /* * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24] */ static const ulong32 mul_a[] = { 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB }; /* * Multiplication by 1/alpha: 1/alpha * x = (x >> 8) ^ mul_ia[x & 0xFF] */ static const ulong32 mul_ia[] = { 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 }; /* * Compute the next block of bits of output stream. This is equivalent * to one full rotation of the shift register. */ static LTC_INLINE void s_sosemanuk_internal(sosemanuk_state *st) { /* * MUL_A(x) computes alpha * x (in F_{2^32}). * MUL_G(x) computes 1/alpha * x (in F_{2^32}). */ #define MUL_A(x) (T32((x) << 8) ^ mul_a[(x) >> 24]) #define MUL_G(x) (((x) >> 8) ^ mul_ia[(x) & 0xFF]) /* * This macro computes the special multiplexer, which chooses * between "x" and "x xor y", depending on the least significant * bit of the control word. We use the C "?:" selection operator * (which most compilers know how to optimise) except for Alpha, * where the manual sign extension seems to perform equally well * with DEC/Compaq/HP compiler, and much better with gcc. */ #ifdef __alpha #define XMUX(c, x, y) ((((signed int)((c) << 31) >> 31) & (y)) ^ (x)) #else #define XMUX(c, x, y) (((c) & 0x1) ? ((x) ^ (y)) : (x)) #endif /* * FSM() updates the finite state machine. */ #define FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) do { \ ulong32 tt, or1; \ tt = XMUX(r1, s ## x1, s ## x8); \ or1 = r1; \ r1 = T32(r2 + tt); \ tt = T32(or1 * 0x54655307); \ r2 = ROLc(tt, 7); \ } while (0) /* * LRU updates the shift register; the dropped value is stored * in variable "dd". */ #define LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd) do { \ dd = s ## x0; \ s ## x0 = MUL_A(s ## x0) ^ MUL_G(s ## x3) ^ s ## x9; \ } while (0) /* * CC1 stores into variable "ee" the next intermediate word * (combination of the new states of the LFSR and the FSM). */ #define CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee) do { \ ee = T32(s ## x9 + r1) ^ r2; \ } while (0) /* * STEP computes one internal round. "dd" receives the "s_t" * value (dropped from the LFSR) and "ee" gets the value computed * from the LFSR and FSM. */ #define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd, ee) do { \ FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9); \ LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd); \ CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee); \ } while (0) /* * Apply one Serpent round (with the provided S-box macro), XOR * the result with the "v" values, and encode the result into * the destination buffer, at the provided offset. The "x*" * arguments encode the output permutation of the "S" macro. */ #define SRD(S, x0, x1, x2, x3, ooff) do { \ S(u0, u1, u2, u3, u4); \ STORE32L(u ## x0 ^ v0, st->buf + ooff); \ STORE32L(u ## x1 ^ v1, st->buf + ooff + 4); \ STORE32L(u ## x2 ^ v2, st->buf + ooff + 8); \ STORE32L(u ## x3 ^ v3, st->buf + ooff + 12); \ } while (0) ulong32 s00 = st->s00; ulong32 s01 = st->s01; ulong32 s02 = st->s02; ulong32 s03 = st->s03; ulong32 s04 = st->s04; ulong32 s05 = st->s05; ulong32 s06 = st->s06; ulong32 s07 = st->s07; ulong32 s08 = st->s08; ulong32 s09 = st->s09; ulong32 r1 = st->r1; ulong32 r2 = st->r2; ulong32 u0, u1, u2, u3, u4; ulong32 v0, v1, v2, v3; STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v0, u0); STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v1, u1); STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v2, u2); STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v3, u3); SRD(S2, 2, 3, 1, 4, 0); STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v0, u0); STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v1, u1); STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v2, u2); STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v3, u3); SRD(S2, 2, 3, 1, 4, 16); STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v0, u0); STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v1, u1); STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v2, u2); STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v3, u3); SRD(S2, 2, 3, 1, 4, 32); STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v0, u0); STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v1, u1); STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v2, u2); STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v3, u3); SRD(S2, 2, 3, 1, 4, 48); STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v0, u0); STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v1, u1); STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v2, u2); STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v3, u3); SRD(S2, 2, 3, 1, 4, 64); st->s00 = s00; st->s01 = s01; st->s02 = s02; st->s03 = s03; st->s04 = s04; st->s05 = s05; st->s06 = s06; st->s07 = s07; st->s08 = s08; st->s09 = s09; st->r1 = r1; st->r2 = r2; } /* * Combine buffers in1[] and in2[] by XOR, result in out[]. The length * is "datalen" (in bytes). Partial overlap of out[] with either in1[] * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) * is allowed. */ static LTC_INLINE void s_xorbuf(const unsigned char *in1, const unsigned char *in2, unsigned char *out, unsigned long datalen) { while (datalen -- > 0) { *out ++ = *in1 ++ ^ *in2 ++; } } /* * Cipher operation, as a stream cipher: data is read from the "in" * buffer, combined by XOR with the stream, and the result is written * in the "out" buffer. "in" and "out" must be either equal, or * reference distinct buffers (no partial overlap is allowed). * @param st The Sosemanuk state * @param in Data in * @param inlen Length of data in bytes * @param out Data out * @return CRYPT_OK on success */ int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) { LTC_ARGCHK(st != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); if (st->ptr < (sizeof(st->buf))) { unsigned long rlen = (sizeof(st->buf)) - st->ptr; if (rlen > inlen) { rlen = inlen; } s_xorbuf(st->buf + st->ptr, in, out, rlen); in += rlen; out += rlen; inlen -= rlen; st->ptr += rlen; } while (inlen > 0) { s_sosemanuk_internal(st); if (inlen >= sizeof(st->buf)) { s_xorbuf(st->buf, in, out, sizeof(st->buf)); in += sizeof(st->buf); out += sizeof(st->buf); inlen -= sizeof(st->buf); } else { s_xorbuf(st->buf, in, out, inlen); st->ptr = inlen; inlen = 0; } } return CRYPT_OK; } /* * Cipher operation, as a PRNG: the provided output buffer is filled with * pseudo-random bytes as output from the stream cipher. * @param st The Sosemanuk state * @param out Data out * @param outlen Length of output in bytes * @return CRYPT_OK on success */ int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen) { if (outlen == 0) return CRYPT_OK; /* nothing to do */ LTC_ARGCHK(out != NULL); XMEMSET(out, 0, outlen); return sosemanuk_crypt(st, out, outlen, out); } /* * Terminate and clear Sosemanuk key context * @param st The Sosemanuk state * @return CRYPT_OK on success */ int sosemanuk_done(sosemanuk_state *st) { LTC_ARGCHK(st != NULL); zeromem(st, sizeof(sosemanuk_state)); return CRYPT_OK; } #endif optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c000066400000000000000000000022201464416617300272410ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_SOSEMANUK /** Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sosemanuk @param key The key @param keylen The key length @param iv The initial vector @param ivlen The initial vector length @param datain The plaintext (or ciphertext) @param datalen The length of the input and output (octets) @param dataout [out] The ciphertext (or plaintext) @return CRYPT_OK if successful */ int sosemanuk_memory(const unsigned char *key, unsigned long keylen, const unsigned char *iv, unsigned long ivlen, const unsigned char *datain, unsigned long datalen, unsigned char *dataout) { sosemanuk_state st; int err; if ((err = sosemanuk_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; if ((err = sosemanuk_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; err = sosemanuk_crypt(&st, datain, datalen, dataout); WIPE_KEY: sosemanuk_done(&st); return err; } #endif /* LTC_SOSEMANUK */ optee_os-4.3.0/core/lib/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c000066400000000000000000000113711464416617300267170ustar00rootroot00000000000000/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" #ifdef LTC_SOSEMANUK int sosemanuk_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else sosemanuk_state st; int err; unsigned char out[1000]; { unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char ct[] = { 0x7e, 0xfe, 0x2e, 0x6f, 0x8f, 0x77, 0x15, 0x72, 0x6a, 0x88, 0x14, 0xa6, 0x56, 0x88, 0x29, 0x9a, 0x86, 0x32, 0x7f, 0x14, 0xd6, 0xb1, 0x94, 0x90, 0x25, 0xbc, 0x73, 0xfd, 0x02, 0x6c, 0x6a, 0xb8, 0xda, 0x8e, 0x7f, 0x61, 0x70, 0x81, 0xe3, 0xbb, 0x99, 0xaf, 0x19, 0x9f, 0x20, 0x45 }; char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ unsigned long len; len = XSTRLEN(pt); /* crypt piece by piece */ if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in one go - using sosemanuk_ivctr64() */ if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; /* crypt in a single call */ if ((err = sosemanuk_memory(k, sizeof(k), n, sizeof(n), (unsigned char*)pt, len, out)) != CRYPT_OK) return err; if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; } { /* keystream * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=210&view=auto * Set 6, vector 0 * key = 0053A6F94C9FF24598EB3E91E4378ADD * 3083D6297CCF2275C81B6EC11467BA0D * IV = 0D74DB42A91077DE45AC137AE148AF16 * stream[0..63] = 55EB8D174C2E0351E5A53C90E84740EB * 0F5A24AAFEC8E0C9F9D2CE48B2ADB0A3 * 4D2E8C4E016102607368FFA43A0F9155 * 0706E3548AD9E5EA15A53EB6F0EDE9DC * */ unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC, 0x13, 0x7A, 0xE1, 0x48, 0xAF, 0x16 }; unsigned char ct3[] = { 0x55, 0xEB, 0x8D, 0x17, 0x4C, 0x2E, 0x03, 0x51, 0xE5, 0xA5, 0x3C, 0x90, 0xE8, 0x47, 0x40, 0xEB, 0x0F, 0x5A, 0x24, 0xAA, 0xFE, 0xC8, 0xE0, 0xC9, 0xF9, 0xD2, 0xCE, 0x48, 0xB2, 0xAD, 0xB0, 0xA3, 0x4D, 0x2E, 0x8C, 0x4E, 0x01, 0x61, 0x02, 0x60, 0x73, 0x68, 0xFF, 0xA4, 0x3A, 0x0F, 0x91, 0x55, 0x07, 0x06, 0xE3, 0x54, 0x8A, 0xD9, 0xE5, 0xEA, 0x15, 0xA5, 0x3E, 0xB6, 0xF0, 0xED, 0xE9, 0xDC }; if ((err = sosemanuk_setup(&st, k3, sizeof(k3))) != CRYPT_OK) return err; if ((err = sosemanuk_setiv(&st, n3, sizeof(n3))) != CRYPT_OK) return err; if ((err = sosemanuk_keystream(&st, out, 64)) != CRYPT_OK) return err; if ((err = sosemanuk_done(&st)) != CRYPT_OK) return err; if (compare_testvector(out, 64, ct3, sizeof(ct3), "SOSEMANUK-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; } return CRYPT_OK; #endif } #endif optee_os-4.3.0/core/lib/libtomcrypt/sub.mk000066400000000000000000000415231464416617300205440ustar00rootroot00000000000000global-incdirs-y += include global-incdirs-y += src/headers cppflags-lib-y += -DARGTYPE=4 # Make LTC_ARGCHK() return on error cppflags-lib-y += -DLTC_NO_TEST -DLTC_NO_PROTOTYPES cppflags-lib-y += -DLTC_NO_TABLES -DLTC_HASH_HELPERS cppflags-lib-y += -DLTC_NO_MISC cppflags-lib-y += -DLTC_HMAC cppflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -DLTC_SMALL_CODE cppflags-lib-y += -DLTC_NO_CIPHERS cppflags-lib-y += -DLTC_NO_MODES cppflags-lib-y += -DLTC_NO_HASHES cppflags-lib-y += -DLTC_NO_MACS cppflags-lib-y += -DLTC_NO_PK cppflags-lib-y += -DLTC_NO_PRNGS -DLTC_FORTUNA cflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -Os srcs-y += tomcrypt.c srcs-y += src/misc/burn_stack.c srcs-y += src/misc/error_to_string.c srcs-y += src/misc/mem_neq.c srcs-y += src/misc/zeromem.c srcs-y += src/misc/base64/base64_decode.c srcs-y += src/misc/base64/base64_encode.c srcs-y += src/misc/crypt/crypt.c srcs-y += src/misc/crypt/crypt_cipher_descriptor.c srcs-y += src/misc/crypt/crypt_cipher_is_valid.c srcs-y += src/misc/crypt/crypt_find_cipher_any.c srcs-y += src/misc/crypt/crypt_find_cipher.c srcs-y += src/misc/crypt/crypt_find_cipher_id.c srcs-y += src/misc/crypt/crypt_find_hash_any.c srcs-y += src/misc/crypt/crypt_find_hash.c srcs-y += src/misc/crypt/crypt_find_hash_id.c srcs-y += src/misc/crypt/crypt_find_hash_oid.c srcs-y += src/misc/crypt/crypt_find_prng.c srcs-y += src/misc/crypt/crypt_fsa.c srcs-y += src/misc/crypt/crypt_hash_descriptor.c srcs-y += src/misc/crypt/crypt_hash_is_valid.c srcs-y += src/misc/crypt/crypt_prng_descriptor.c srcs-y += src/misc/crypt/crypt_prng_is_valid.c srcs-y += src/misc/crypt/crypt_register_cipher.c srcs-y += src/misc/crypt/crypt_register_hash.c srcs-y += src/misc/crypt/crypt_register_prng.c srcs-y += src/misc/crypt/crypt_unregister_cipher.c srcs-y += src/misc/crypt/crypt_unregister_hash.c srcs-y += src/misc/crypt/crypt_unregister_prng.c srcs-y += src/misc/pkcs12/pkcs12_kdf.c srcs-y += src/misc/pkcs12/pkcs12_utf8_to_utf16.c srcs-y += src/misc/pkcs5/pkcs_5_1.c srcs-y += src/misc/pkcs5/pkcs_5_2.c srcs-y += src/misc/ssh/ssh_decode_sequence_multi.c srcs-y += src/misc/ssh/ssh_encode_sequence_multi.c cppflags-lib-$(_CFG_CORE_LTC_AES_DESC) += -DLTC_RIJNDAEL srcs-$(_CFG_CORE_LTC_AES) += aes.c ifeq ($(_CFG_CORE_LTC_AES_ACCEL),y) srcs-$(_CFG_CORE_LTC_AES_DESC) += aes_accel.c else srcs-$(_CFG_CORE_LTC_AES_DESC) += src/ciphers/aes/aes.c srcs-$(_CFG_CORE_LTC_AES_DESC) += src/ciphers/aes/aes_desc.c endif cppflags-lib-$(_CFG_CORE_LTC_DES) += -DLTC_DES srcs-$(_CFG_CORE_LTC_DES) += src/ciphers/des.c cppflags-lib-$(_CFG_CORE_LTC_CCM) += -DLTC_CCM_MODE srcs-$(_CFG_CORE_LTC_CCM) += ccm.c srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_init.c srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_add_nonce.c srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_add_aad.c srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_process.c srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_done.c srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_reset.c cppflags-lib-$(_CFG_CORE_LTC_GCM) += -DLTC_GCM_MODE srcs-$(_CFG_CORE_LTC_GCM) += gcm.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_add_aad.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_add_iv.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_done.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_gf_mult.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_init.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_memory.c ifeq ($(_CFG_CORE_LTC_CE),y) srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_mult_h_arm_ce.c else srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_mult_h.c endif srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_process.c srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_reset.c srcs-$(_CFG_CORE_LTC_HASH) += hash.c srcs-$(_CFG_CORE_LTC_HASH) += src/hashes/helper/hash_memory.c srcs-$(_CFG_CORE_LTC_HASH) += src/hashes/helper/hash_memory_multi.c cppflags-lib-$(_CFG_CORE_LTC_MD5_DESC) += -DLTC_MD5 srcs-$(_CFG_CORE_LTC_MD5_DESC) += src/hashes/md5.c cppflags-lib-$(_CFG_CORE_LTC_SHA1_DESC) += -DLTC_SHA1 ifeq ($(_CFG_CORE_LTC_SHA1_ACCEL),y) srcs-$(_CFG_CORE_LTC_SHA1_DESC) += sha1_accel.c else srcs-$(_CFG_CORE_LTC_SHA1_DESC) += src/hashes/sha1.c endif cppflags-lib-$(_CFG_CORE_LTC_SHA3_DESC) += -DLTC_SHA3 ifeq ($(_CFG_CORE_LTC_SHA3_ACCEL),y) srcs-$(_CFG_CORE_LTC_SHA3_DESC) += sha3_accel.c else srcs-$(_CFG_CORE_LTC_SHA3_DESC) += src/hashes/sha3.c endif srcs-$(_CFG_CORE_LTC_SHA3_DESC) += src/hashes/sha3_test.c srcs-$(_CFG_CORE_LTC_SHA3_DESC) += shake.c cppflags-lib-$(_CFG_CORE_LTC_SHA224_DESC) += -DLTC_SHA224 srcs-$(_CFG_CORE_LTC_SHA224_DESC) += src/hashes/sha2/sha224.c cppflags-lib-$(_CFG_CORE_LTC_SHA256_DESC) += -DLTC_SHA256 ifeq ($(_CFG_CORE_LTC_SHA256_ACCEL),y) srcs-$(_CFG_CORE_LTC_SHA256_DESC) += sha256_accel.c else srcs-$(_CFG_CORE_LTC_SHA256_DESC) += src/hashes/sha2/sha256.c endif cppflags-lib-$(_CFG_CORE_LTC_SHA384_DESC) += -DLTC_SHA384 srcs-$(_CFG_CORE_LTC_SHA384_DESC) += src/hashes/sha2/sha384.c cppflags-lib-$(_CFG_CORE_LTC_SHA512_DESC) += -DLTC_SHA512 ifeq ($(_CFG_CORE_LTC_SHA512_ACCEL),y) srcs-$(_CFG_CORE_LTC_SHA512_DESC) += sha512_accel.c else srcs-$(_CFG_CORE_LTC_SHA512_DESC) += src/hashes/sha2/sha512.c endif cppflags-lib-$(_CFG_CORE_LTC_SHA512_256) += -DLTC_SHA512_256 srcs-$(_CFG_CORE_LTC_SHA512_256) += src/hashes/sha2/sha512_256.c cppflags-lib-$(_CFG_CORE_LTC_HMAC) += -DLTC_HMAC srcs-$(_CFG_CORE_LTC_HMAC) += hmac.c srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_done.c srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_init.c srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_memory.c srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_memory_multi.c srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_process.c cppflags-lib-$(_CFG_CORE_LTC_CMAC) += -DLTC_OMAC srcs-$(_CFG_CORE_LTC_CMAC) += cmac.c srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_done.c srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_init.c srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_memory.c srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_memory_multi.c srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_process.c srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/multi.c srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/rand_prime.c srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/rand_bn.c ifeq ($(_CFG_CORE_LTC_ECC),y) srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/fp/ltc_ecc_fp_mulmod.c endif cppflags-lib-$(_CFG_CORE_LTC_CBC) += -DLTC_CBC_MODE srcs-$(_CFG_CORE_LTC_CBC) += cbc.c srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_decrypt.c srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_done.c srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_encrypt.c srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_getiv.c srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_setiv.c srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_start.c cppflags-lib-$(_CFG_CORE_LTC_CTR) += -DLTC_CTR_MODE srcs-$(_CFG_CORE_LTC_CTR) += ctr.c srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_decrypt.c srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_done.c srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_encrypt.c srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_getiv.c srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_setiv.c srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_start.c cppflags-lib-$(_CFG_CORE_LTC_ECB) += -DLTC_ECB_MODE srcs-$(_CFG_CORE_LTC_ECB) += ecb.c srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_decrypt.c srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_done.c srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_encrypt.c srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_start.c cppflags-lib-$(_CFG_CORE_LTC_XTS) += -DLTC_XTS_MODE srcs-$(_CFG_CORE_LTC_XTS) += xts.c srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_decrypt.c srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_done.c srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_encrypt.c srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_init.c srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_mult_x.c srcs-$(_CFG_CORE_LTC_ACIPHER) += mpi_desc.c cflags-mpi_desc.c-y += -Wno-declaration-after-statement cppflags-mpi_desc.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS ifeq ($(_CFG_CORE_LTC_ASN1),y) srcs-y += src/pk/asn1/der/bit/der_decode_bit_string.c srcs-y += src/pk/asn1/der/bit/der_encode_bit_string.c srcs-y += src/pk/asn1/der/bit/der_length_bit_string.c srcs-y += src/pk/asn1/der/bit/der_decode_raw_bit_string.c srcs-y += src/pk/asn1/der/bit/der_encode_raw_bit_string.c srcs-y += src/pk/asn1/der/boolean/der_decode_boolean.c srcs-y += src/pk/asn1/der/boolean/der_encode_boolean.c srcs-y += src/pk/asn1/der/boolean/der_length_boolean.c srcs-y += src/pk/asn1/der/choice/der_decode_choice.c srcs-y += src/pk/asn1/der/custom_type/der_decode_custom_type.c srcs-y += src/pk/asn1/der/custom_type/der_encode_custom_type.c srcs-y += src/pk/asn1/der/custom_type/der_length_custom_type.c srcs-y += src/pk/asn1/der/general/der_asn1_maps.c srcs-y += src/pk/asn1/der/general/der_decode_asn1_length.c srcs-y += src/pk/asn1/der/general/der_decode_asn1_identifier.c srcs-y += src/pk/asn1/der/general/der_encode_asn1_identifier.c srcs-y += src/pk/asn1/der/general/der_encode_asn1_length.c srcs-y += src/pk/asn1/der/general/der_length_asn1_identifier.c srcs-y += src/pk/asn1/der/general/der_length_asn1_length.c srcs-y += src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c srcs-y += src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c srcs-y += src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c srcs-y += src/pk/asn1/der/ia5/der_decode_ia5_string.c srcs-y += src/pk/asn1/der/ia5/der_encode_ia5_string.c srcs-y += src/pk/asn1/der/ia5/der_length_ia5_string.c srcs-y += src/pk/asn1/der/integer/der_decode_integer.c srcs-y += src/pk/asn1/der/integer/der_encode_integer.c srcs-y += src/pk/asn1/der/integer/der_length_integer.c srcs-y += src/pk/asn1/der/object_identifier/der_decode_object_identifier.c srcs-y += src/pk/asn1/der/object_identifier/der_encode_object_identifier.c srcs-y += src/pk/asn1/der/object_identifier/der_length_object_identifier.c srcs-y += src/pk/asn1/der/octet/der_decode_octet_string.c srcs-y += src/pk/asn1/der/octet/der_encode_octet_string.c srcs-y += src/pk/asn1/der/octet/der_length_octet_string.c srcs-y += src/pk/asn1/der/printable_string/der_decode_printable_string.c srcs-y += src/pk/asn1/der/printable_string/der_encode_printable_string.c srcs-y += src/pk/asn1/der/printable_string/der_length_printable_string.c srcs-y += src/pk/asn1/der/sequence/der_decode_sequence_ex.c srcs-y += src/pk/asn1/der/sequence/der_decode_sequence_flexi.c srcs-y += src/pk/asn1/der/sequence/der_decode_sequence_multi.c srcs-y += src/pk/asn1/der/sequence/der_encode_sequence_ex.c srcs-y += src/pk/asn1/der/sequence/der_encode_sequence_multi.c srcs-y += src/pk/asn1/der/sequence/der_length_sequence.c srcs-y += src/pk/asn1/der/sequence/der_sequence_free.c srcs-y += src/pk/asn1/der/set/der_encode_set.c srcs-y += src/pk/asn1/der/set/der_encode_setof.c srcs-y += src/pk/asn1/der/short_integer/der_decode_short_integer.c srcs-y += src/pk/asn1/der/short_integer/der_encode_short_integer.c srcs-y += src/pk/asn1/der/short_integer/der_length_short_integer.c srcs-y += src/pk/asn1/der/utctime/der_decode_utctime.c srcs-y += src/pk/asn1/der/utctime/der_encode_utctime.c srcs-y += src/pk/asn1/der/utctime/der_length_utctime.c srcs-y += src/pk/asn1/der/utf8/der_decode_utf8_string.c srcs-y += src/pk/asn1/der/utf8/der_encode_utf8_string.c srcs-y += src/pk/asn1/der/utf8/der_length_utf8_string.c srcs-y += src/pk/asn1/der/teletex_string/der_decode_teletex_string.c srcs-y += src/pk/asn1/der/teletex_string/der_length_teletex_string.c srcs-y += src/pk/asn1/oid/pk_oid_cmp.c srcs-y += src/pk/asn1/oid/pk_oid_str.c endif cppflags-lib-$(_CFG_CORE_LTC_DSA) += -DLTC_MDSA srcs-$(_CFG_CORE_LTC_DSA) += dsa.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_decrypt_key.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_encrypt_key.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_export.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_free.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_generate_key.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_generate_pqg.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_import.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_make_key.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_shared_secret.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_sign_hash.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_verify_hash.c srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_verify_key.c cppflags-lib-$(_CFG_CORE_LTC_RSA) += -DLTC_MRSA srcs-$(_CFG_CORE_LTC_RSA) += rsa.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_i2osp.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_mgf1.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_oaep_decode.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_oaep_encode.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_os2ip.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_pss_decode.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_pss_encode.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_v1_5_decode.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_v1_5_encode.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_decrypt_key.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_encrypt_key.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_export.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_exptmod.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_import.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_key.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_make_key.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_sign_hash.c srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_verify_hash.c cppflags-lib-$(_CFG_CORE_LTC_DH) += -DLTC_MDH srcs-$(_CFG_CORE_LTC_DH) += dh.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_check_pubkey.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_export.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_export_key.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_free.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_generate_key.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_import.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_make_key.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_set.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_set_pg_dhparam.c srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_shared_secret.c cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_MECC # use Shamir's trick for point mul (speeds up signature verification) cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC_SHAMIR cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC192 cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC224 cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC256 cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC384 cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC521 cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_CURVE25519 # ECC 521 bits is the max supported key size cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_MAX_ECC=521 srcs-$(_CFG_CORE_LTC_ECC) += ecc.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_find_curve.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_free.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_get_oid_str.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_make_key.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_set_curve.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_set_curve_internal.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_shared_secret.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_sign_hash.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_ssh_ecdsa_encode_name.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_verify_hash.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_is_point.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_is_point_at_infinity.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_map.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_mulmod.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_mulmod_timing.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_mul2add.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_points.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_projective_add_point.c srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_projective_dbl_point.c ifneq (,$(filter y,$(_CFG_CORE_LTC_SM2_DSA) $(_CFG_CORE_LTC_SM2_PKE))) cppflags-lib-y += -DLTC_ECC_SM2 endif srcs-$(_CFG_CORE_LTC_SM2_DSA) += sm2-dsa.c srcs-$(_CFG_CORE_LTC_SM2_PKE) += sm2-pke.c srcs-$(_CFG_CORE_LTC_SM2_KEP) += sm2-kep.c cppflags-lib-$(_CFG_CORE_LTC_EC25519) += -DLTC_CURVE25519 srcs-$(_CFG_CORE_LTC_EC25519) += src/pk/ec25519/ec25519_crypto_ctx.c srcs-$(_CFG_CORE_LTC_EC25519) += src/pk/ec25519/ec25519_export.c srcs-$(_CFG_CORE_LTC_EC25519) += src/pk/ec25519/tweetnacl.c srcs-$(_CFG_CORE_LTC_ED25519) += ed25519.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_export.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_import.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_import_pkcs8.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_import_x509.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_make_key.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_sign.c srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_verify.c srcs-$(_CFG_CORE_LTC_X25519) += x25519.c cflags-x25519.c-y += -Wno-declaration-after-statement srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_export.c srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_import.c srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_make_key.c srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_shared_secret.c optee_os-4.3.0/core/lib/libtomcrypt/tomcrypt.c000066400000000000000000000075141464416617300214510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2023, Linaro Limited */ #include #include #include #include #include #include "tomcrypt_mp.h" #include #if defined(_CFG_CORE_LTC_VFP) #include #include #endif #if defined(_CFG_CORE_LTC_ACIPHER) || defined(_CFG_CORE_LTC_EC25519) /* Random generator */ static int prng_crypto_start(prng_state *prng __unused) { return CRYPT_OK; } static int prng_crypto_add_entropy(const unsigned char *in __unused, unsigned long inlen __unused, prng_state *prng __unused) { /* No entropy is required */ return CRYPT_OK; } static int prng_crypto_ready(prng_state *prng __unused) { return CRYPT_OK; } static unsigned long prng_crypto_read(unsigned char *out, unsigned long outlen, prng_state *prng __unused) { if (crypto_rng_read(out, outlen)) return 0; return outlen; } static int prng_crypto_done(prng_state *prng __unused) { return CRYPT_OK; } static int prng_crypto_export(unsigned char *out __unused, unsigned long *outlen __unused, prng_state *prng __unused) { return CRYPT_OK; } static int prng_crypto_import(const unsigned char *in __unused, unsigned long inlen __unused, prng_state *prng __unused) { return CRYPT_OK; } static int prng_crypto_test(void) { return CRYPT_OK; } static const struct ltc_prng_descriptor prng_crypto_desc = { .name = "prng_crypto", .export_size = 64, .start = prng_crypto_start, .add_entropy = prng_crypto_add_entropy, .ready = prng_crypto_ready, .read = prng_crypto_read, .done = prng_crypto_done, .pexport = prng_crypto_export, .pimport = prng_crypto_import, .test = prng_crypto_test, }; #endif /*_CFG_CORE_LTC_ACIPHER*/ /* * tee_ltc_reg_algs(): Registers * - algorithms * - hash * - prng (pseudo random generator) */ static void tee_ltc_reg_algs(void) { #if defined(_CFG_CORE_LTC_AES) || defined(_CFG_CORE_LTC_AES_DESC) register_cipher(&aes_desc); #endif #if defined(_CFG_CORE_LTC_DES) register_cipher(&des_desc); register_cipher(&des3_desc); #endif #if defined(_CFG_CORE_LTC_MD5_DESC) register_hash(&md5_desc); #endif #if defined(_CFG_CORE_LTC_SHA1) || defined(_CFG_CORE_LTC_SHA1_DESC) register_hash(&sha1_desc); #endif #if defined(_CFG_CORE_LTC_SHA224) || defined(_CFG_CORE_LTC_SHA224_DESC) register_hash(&sha224_desc); #endif #if defined(_CFG_CORE_LTC_SHA256) || defined(_CFG_CORE_LTC_SHA256_DESC) register_hash(&sha256_desc); #endif #if defined(_CFG_CORE_LTC_SHA384) || defined(_CFG_CORE_LTC_SHA384_DESC) register_hash(&sha384_desc); #endif #if defined(_CFG_CORE_LTC_SHA512) || defined(_CFG_CORE_LTC_SHA512_DESC) register_hash(&sha512_desc); #endif #if defined(_CFG_CORE_LTC_SHA3_224) || defined(_CFG_CORE_LTC_SHA3_224_DESC) register_hash(&sha3_224_desc); #endif #if defined(_CFG_CORE_LTC_SHA3_256) || defined(_CFG_CORE_LTC_SHA3_256_DESC) register_hash(&sha3_256_desc); #endif #if defined(_CFG_CORE_LTC_SHA3_384) || defined(_CFG_CORE_LTC_SHA3_384_DESC) register_hash(&sha3_384_desc); #endif #if defined(_CFG_CORE_LTC_SHA3_512) || defined(_CFG_CORE_LTC_SHA3_512_DESC) register_hash(&sha3_512_desc); #endif #if defined(_CFG_CORE_LTC_ACIPHER) || defined(_CFG_CORE_LTC_EC25519) register_prng(&prng_crypto_desc); #endif } static void ltc_init(void) { #if defined(_CFG_CORE_LTC_ACIPHER) init_mp_tomcrypt(); #endif tee_ltc_reg_algs(); } #if defined(CFG_CRYPTOLIB_NAME_tomcrypt) TEE_Result crypto_init(void) { ltc_init(); return TEE_SUCCESS; } #else void tomcrypt_init(void) { ltc_init(); } #endif #if defined(CFG_WITH_VFP) void tomcrypt_arm_neon_enable(struct tomcrypt_arm_neon_state *state) { state->state = thread_kernel_enable_vfp(); } void tomcrypt_arm_neon_disable(struct tomcrypt_arm_neon_state *state) { thread_kernel_disable_vfp(state->state); } #endif optee_os-4.3.0/core/lib/libtomcrypt/x25519.c000066400000000000000000000055231464416617300204430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Technology Innovation Institute (TII) */ #include #include #include #include #include #include #include #include "acipher_helpers.h" /* X25519 key is an octet string of 32 bytes */ #define X25519_KEY_SIZE_BYTES UL(32) TEE_Result crypto_acipher_alloc_x25519_keypair(struct montgomery_keypair *key, size_t key_size) { size_t key_size_bytes = key_size / 8; if (!key) return TEE_ERROR_BAD_PARAMETERS; memset(key, 0, sizeof(*key)); if (key_size_bytes != X25519_KEY_SIZE_BYTES) return TEE_ERROR_BAD_PARAMETERS; key->priv = calloc(1, key_size_bytes); key->pub = calloc(1, key_size_bytes); if (!key->priv || !key->pub) { free(key->priv); free(key->pub); return TEE_ERROR_OUT_OF_MEMORY; } return TEE_SUCCESS; } TEE_Result crypto_acipher_gen_x25519_key(struct montgomery_keypair *key, size_t key_size) { curve25519_key ltc_tmp_key = { }; size_t key_size_bytes = key_size / 8; if (key_size_bytes != X25519_KEY_SIZE_BYTES) return TEE_ERROR_BAD_PARAMETERS; if (x25519_make_key(NULL, find_prng("prng_crypto"), <c_tmp_key) != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; if (key_size_bytes < sizeof(ltc_tmp_key.pub) || key_size_bytes < sizeof(ltc_tmp_key.priv)) return TEE_ERROR_BAD_PARAMETERS; memcpy(key->pub, ltc_tmp_key.pub, sizeof(ltc_tmp_key.pub)); memcpy(key->priv, ltc_tmp_key.priv, sizeof(ltc_tmp_key.priv)); memzero_explicit(<c_tmp_key, sizeof(ltc_tmp_key)); return TEE_SUCCESS; } TEE_Result crypto_acipher_x25519_shared_secret(struct montgomery_keypair *private_key, void *public_key, void *secret, unsigned long *secret_len) { curve25519_key ltc_private_key = { .type = PK_PRIVATE, .algo = LTC_OID_X25519, }; curve25519_key ltc_public_key = { .type = PK_PUBLIC, .algo = LTC_OID_X25519, }; if (!private_key || !public_key || !secret || !secret_len) return TEE_ERROR_BAD_PARAMETERS; static_assert(sizeof(ltc_public_key.pub) == X25519_KEY_SIZE_BYTES && sizeof(ltc_public_key.priv) == X25519_KEY_SIZE_BYTES); memcpy(ltc_public_key.pub, public_key, X25519_KEY_SIZE_BYTES); memcpy(ltc_private_key.priv, private_key->priv, X25519_KEY_SIZE_BYTES); if (x25519_shared_secret(<c_private_key, <c_public_key, secret, secret_len) != CRYPT_OK) return TEE_ERROR_BAD_PARAMETERS; /* Clear private key from the stack */ memzero_explicit(<c_private_key, sizeof(ltc_private_key)); /* * RFC 7748, sec 6.1, check for all zero shared secret output to reject * input points of low order. */ if (*secret_len != X25519_KEY_SIZE_BYTES || !consttime_memcmp(secret, ltc_private_key.pub, X25519_KEY_SIZE_BYTES)) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } optee_os-4.3.0/core/lib/libtomcrypt/xts.c000066400000000000000000000061611464416617300204030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include struct ltc_xts_ctx { struct crypto_cipher_ctx ctx; int cipher_idx; int (*update)(const unsigned char *src, unsigned long len, unsigned char *dst, unsigned char *tweak, const symmetric_xts *xts); symmetric_xts state; uint8_t tweak[TEE_AES_BLOCK_SIZE]; }; static const struct crypto_cipher_ops ltc_xts_ops; static struct ltc_xts_ctx *to_xts_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == <c_xts_ops); return container_of(ctx, struct ltc_xts_ctx, ctx); } static TEE_Result ltc_xts_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct ltc_xts_ctx *c = to_xts_ctx(ctx); if (key1_len != key2_len) return TEE_ERROR_BAD_PARAMETERS; if (iv) { if (iv_len != sizeof(c->tweak)) return TEE_ERROR_BAD_PARAMETERS; memcpy(c->tweak, iv, sizeof(c->tweak)); } else { memset(c->tweak, 0, sizeof(c->tweak)); } if ((int)iv_len != cipher_descriptor[c->cipher_idx]->block_length) return TEE_ERROR_BAD_PARAMETERS; if (mode == TEE_MODE_ENCRYPT) c->update = xts_encrypt; else c->update = xts_decrypt; if (xts_start(c->cipher_idx, key1, key2, key1_len, 0, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static TEE_Result ltc_xts_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct ltc_xts_ctx *c = to_xts_ctx(ctx); if (c->update && c->update(data, len, dst, c->tweak, &c->state) == CRYPT_OK) return TEE_SUCCESS; else return TEE_ERROR_BAD_STATE; } static void ltc_xts_final(struct crypto_cipher_ctx *ctx) { xts_done(&to_xts_ctx(ctx)->state); } static void ltc_xts_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_xts_ctx(ctx)); } static void ltc_xts_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct ltc_xts_ctx *src = to_xts_ctx(src_ctx); struct ltc_xts_ctx *dst = to_xts_ctx(dst_ctx); assert(src->cipher_idx == dst->cipher_idx); dst->update = src->update; memcpy(dst->tweak, src->tweak, sizeof(src->tweak)); dst->state = src->state; } static const struct crypto_cipher_ops ltc_xts_ops = { .init = ltc_xts_init, .update = ltc_xts_update, .final = ltc_xts_final, .free_ctx = ltc_xts_free_ctx, .copy_state = ltc_xts_copy_state, }; TEE_Result crypto_aes_xts_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct ltc_xts_ctx *c = NULL; int cipher_idx = find_cipher("aes"); if (cipher_idx < 0) return TEE_ERROR_NOT_SUPPORTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = <c_xts_ops; c->cipher_idx = cipher_idx; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/core/lib/scmi-server/000077500000000000000000000000001464416617300173045ustar00rootroot00000000000000optee_os-4.3.0/core/lib/scmi-server/conf-optee-fvp.mk000066400000000000000000000015561464416617300224740ustar00rootroot00000000000000$(call force,CFG_SCPFW_MOD_CLOCK,y) $(call force,CFG_SCPFW_MOD_DVFS,y) $(call force,CFG_SCPFW_MOD_MSG_SMT,y) $(call force,CFG_SCPFW_MOD_MOCK_CLOCK,y) $(call force,CFG_SCPFW_MOD_MOCK_PPU,y) $(call force,CFG_SCPFW_MOD_MOCK_PSU,y) $(call force,CFG_SCPFW_MOD_OPTEE_MBX,y) $(call force,CFG_SCPFW_MOD_POWER_DOMAIN,y) $(call force,CFG_SCPFW_MOD_PSU,y) $(call force,CFG_SCPFW_MOD_REG_SENSOR,y) $(call force,CFG_SCPFW_MOD_SCMI,y) $(call force,CFG_SCPFW_MOD_SCMI_CLOCK,y) $(call force,CFG_SCPFW_MOD_SCMI_PERF,y) $(call force,CFG_SCPFW_SCMI_PERF_PROTOCOL_OPS,y) $(call force,CFG_SCPFW_MOD_SCMI_POWER_DOMAIN,y) $(call force,CFG_SCPFW_MOD_SCMI_SENSOR,y) $(call force,CFG_SCPFW_MOD_SYSTEM_PLL,y) $(call force,CFG_SCPFW_MOD_SENSOR,y) $(call force,CFG_SCPFW_MOD_VPLL,y) $(call force,CFG_SCPFW_NOTIFICATION,y) $(call force,CFG_SCPFW_SCMI_SENSOR_EVENTS,y) $(call force,CFG_SCPFW_FAST_CHANNEL,n) optee_os-4.3.0/core/lib/scmi-server/conf-optee-stm32mp1.mk000066400000000000000000000014141464416617300232600ustar00rootroot00000000000000$(call force,CFG_SCPFW_MOD_RESET_DOMAIN,y) $(call force,CFG_SCPFW_MOD_CLOCK,y) $(call force,CFG_SCPFW_MOD_OPTEE_CLOCK,y) $(call force,CFG_SCPFW_MOD_OPTEE_CONSOLE,y) $(call force,CFG_SCPFW_MOD_OPTEE_MBX,y) $(call force,CFG_SCPFW_MOD_OPTEE_RESET,y) ifeq ($(CFG_STM32MP1_SCMI_SHM_SYSRAM),y) $(call force,CFG_SCPFW_MOD_OPTEE_SMT,y) else $(call force,CFG_SCPFW_MOD_MSG_SMT,y) endif $(call force,CFG_SCPFW_MOD_SCMI,y) $(call force,CFG_SCPFW_MOD_SCMI_CLOCK,y) $(call force,CFG_SCPFW_MOD_SCMI_RESET_DOMAIN,y) $(call force,CFG_SCPFW_MOD_SCMI_VOLTAGE_DOMAIN,y) $(call force,CFG_SCPFW_MOD_VOLTAGE_DOMAIN,y) $(call force,CFG_SCPFW_MOD_STM32_PMIC_REGU,$(CFG_STPMIC1)) $(call force,CFG_SCPFW_MOD_STM32_PWR_REGU,y) $(call force,CFG_SCPFW_NOTIFICATION,n) $(call force,CFG_SCPFW_FAST_CHANNEL,n) optee_os-4.3.0/core/lib/scmi-server/conf.mk000066400000000000000000000046211464416617300205650ustar00rootroot00000000000000# Configuration switches for SCP-firmware: # # CFG_SCMI_SCPFW Boolean switch, embeds SCP-firmware SCMI stack when enabled. # CFG_SCMI_SCPFW_PRODUCT Name of the SCP-firmware product to build. # CFG_SCP_FIRMWARE Directory path to SCP-firmware source tree # CFG_SCPFW_LOG_LEVEL SCP-firmware log level # CFG_SCPFW_MOD_x Boolean switch, embeds SCP-firmware module x when enabled # CFG_SCPFW_NOTIFICATION Boolean switch, embeds SCMI notification when enabled. # CFG_SCPFW_FAST_CHANNELS Boolean switch, embeds SCMI fast channel when enabled. # # Boolean y|n switches for module features # CFG_SCPFW_CLOCK_TREE_MGMT # CFG_SCPFW_SCMI_PERF_FAST_CHANNELS # CFG_SCPFW_SCMI_SENSOR_EVENTS # CFG_SCPFW_SCMI_SENSOR_V2 # CFG_SCPFW_SENSOR_TIMESTAMP # CFG_SCPFW_SENSOR_MULTI_AXIS # CFG_SCPFW_SENSOR_EXT_ATTRIBS # CFG_SCPFW_SENSOR_SIGNED_VALUE include core/lib/scmi-server/conf-optee-$(CFG_SCMI_SCPFW_PRODUCT).mk # SCP-fmw log level: 0 trace/verbose, 1 info, 2 warning, 3 error, 4 critical ifeq ($(CFG_TEE_CORE_LOG_LEVEL),0) CFG_SCPFW_LOG_LEVEL ?= 3 else ifeq ($(CFG_TEE_CORE_LOG_LEVEL),1) CFG_SCPFW_LOG_LEVEL ?= 3 else ifeq ($(CFG_TEE_CORE_LOG_LEVEL),2) CFG_SCPFW_LOG_LEVEL ?= 1 else CFG_SCPFW_LOG_LEVEL ?= 0 endif CFG_SCPFW_MOD_DVFS ?= n CFG_SCPFW_MOD_RESET_DOMAIN ?= n CFG_SCPFW_MOD_CLOCK ?= n CFG_SCPFW_MOD_MSG_SMT ?= n CFG_SCPFW_MOD_MOCK_CLOCK ?= n CFG_SCPFW_MOD_MOCK_PPU ?= n CFG_SCPFW_MOD_MOCK_PSU ?= n CFG_SCPFW_MOD_OPTEE_CLOCK ?= n CFG_SCPFW_MOD_OPTEE_CONSOLE ?= y CFG_SCPFW_MOD_OPTEE_MBX ?= n CFG_SCPFW_MOD_OPTEE_RESET ?= n CFG_SCPFW_MOD_OPTEE_SMT ?= n CFG_SCPFW_MOD_POWER_DOMAIN ?= n CFG_SCPFW_MOD_PSU ?= n CFG_SCPFW_MOD_REG_SENSOR ?= n CFG_SCPFW_MOD_SENSOR ?= n CFG_SCPFW_MOD_SCMI ?= y CFG_SCPFW_MOD_SCMI_APCORE ?= n CFG_SCPFW_MOD_SCMI_CLOCK ?= n CFG_SCPFW_MOD_SCMI_PERF ?= n CFG_SCPFW_MOD_SCMI_POWER_DOMAIN ?= n CFG_SCPFW_MOD_SCMI_RESET_DOMAIN ?= n CFG_SCPFW_MOD_SCMI_SENSOR ?= n CFG_SCPFW_MOD_SCMI_VOLTAGE_DOMAIN ?= n CFG_SCPFW_MOD_SYSTEM_PLL ?= n CFG_SCPFW_MOD_VOLTAGE_DOMAIN ?= n CFG_SCPFW_NOTIFICATION ?= n CFG_SCPFW_FAST_CHANNELS ?= n CFG_SCPFW_CLOCK_TREE_MGMT ?= n CFG_SCPFW_SCMI_PERF_FAST_CHANNELS ?= n CFG_SCPFW_SCMI_SENSOR_EVENTS ?= n CFG_SCPFW_SCMI_SENSOR_V2 ?= n CFG_SCPFW_SENSOR_TIMESTAMP ?= n CFG_SCPFW_SENSOR_MULTI_AXIS ?= n CFG_SCPFW_SENSOR_EXT_ATTRIBS ?= n CFG_SCPFW_SENSOR_SIGNED_VALUE ?= n ifeq ($(CFG_SCPFW_MOD_OPTEE_SMT),y) _CFG_SCMI_PTA_SMT_HEADER := y endif ifeq ($(CFG_SCPFW_MOD_MSG_SMT),y) _CFG_SCMI_PTA_MSG_HEADER := y endif optee_os-4.3.0/core/lib/scmi-server/include/000077500000000000000000000000001464416617300207275ustar00rootroot00000000000000optee_os-4.3.0/core/lib/scmi-server/include/optee_scmi.h000066400000000000000000000011021464416617300232210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2022, Linaro Limited */ #ifndef OPTEE_SCMI_H #define OPTEE_SCMI_H #include #include /* * Return virtual address mapped for target SMT IOMEM address range * * @pa: Target address range base physical address * @sz: Target address range byte size * @shmem_is_secure: True if memory is secure, false otherwise * Return a virtual address or 0 is memory is not mapped */ uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure); #endif /* OPTEE_SCMI_H */ optee_os-4.3.0/core/lib/scmi-server/scmi_server.c000066400000000000000000000032741464416617300217770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2022, Linaro Limited */ #include #include #include #include #include #include #include /* * OP-TEE helper function exported to SCP-firmware */ uintptr_t smt_phys_to_virt(uintptr_t pa, size_t sz, bool shmem_is_secure) { if (shmem_is_secure) return (uintptr_t)phys_to_virt(pa, MEM_AREA_IO_SEC, sz); else return (uintptr_t)phys_to_virt(pa, MEM_AREA_IO_NSEC, sz); } /* * SCMI server APIs exported to OP-TEE core */ int scmi_server_get_channels_count(void) { return scmi_get_devices_count(); } TEE_Result scmi_server_get_channel(unsigned int channel_id, int *handle) { int fwk_id = 0; fwk_id = scmi_get_device(channel_id); if (fwk_id < 0) return TEE_ERROR_BAD_PARAMETERS; if (handle) *handle = fwk_id; return TEE_SUCCESS; } TEE_Result scmi_server_smt_process_thread(unsigned int channel_id) { TEE_Result res = TEE_ERROR_GENERIC; int fwk_id = 0; res = scmi_server_get_channel(channel_id, &fwk_id); if (!res) scmi_process_mbx_smt(fwk_id); return res; } TEE_Result scmi_server_msg_process_thread(unsigned int channel_id, void *in_buf, size_t in_sz, void *out_buf, size_t *out_sz) { TEE_Result res = TEE_ERROR_GENERIC; int fwk_id = 0; res = scmi_server_get_channel(channel_id, &fwk_id); if (!res) scmi_process_mbx_msg(fwk_id, in_buf, in_sz, out_buf, out_sz); return res; } static TEE_Result scmi_server_initialize(void) { int rc = 0; rc = scmi_arch_init(); if (rc < 0) { EMSG("SCMI server init failed: %d", rc); panic(); } return TEE_SUCCESS; } boot_final(scmi_server_initialize); optee_os-4.3.0/core/lib/scmi-server/sub.mk000066400000000000000000000104521464416617300204300ustar00rootroot00000000000000# SCMI server library is built from SCP-firmware source tree. # The firmware is made of a framework, a product and modules. # Only modules used by firmware must be built, as stated by # CFG_SCPFW_MOD_* switches. SCP-firmware needs a C source and # a header file to be generated to describe embedded modules. # This is done through cmake configuration of the package. # The toolchain build directive must also match the list of # embedded modules. scpfw-path = $(CFG_SCP_FIRMWARE) scpfw-product = optee/$(CFG_SCMI_SCPFW_PRODUCT) scpfw-out-path := $(out-dir)/$(libdir) scpfw-integ-version-maj = 2 scpfw-integ-version-min = 14 scpfw-integ-version-pat = 0 scpfw-integ-version = $(scpfw-integ-version-maj).$(scpfw-integ-version-min).$(scpfw-integ-version-pat) srcs-y += scmi_server.c incdirs-y += include # SCP-firmware cmake configuration generates header fwk_module_idx.h and # source files fwk_module_list.c needed for scp-firmware compilation. scpfw-cmake-flags-y = -DSCP_FIRMWARE_SOURCE_DIR:PATH=$(scpfw-product)/fw \ -DSCP_LOG_LEVEL="TRACE" \ -DDISABLE_CPPCHECK=1 \ -DCFG_NUM_THREADS=$(CFG_NUM_THREADS) \ -DSCP_OPTEE_DIR:PATH=$(CURDIR) # CMake does not need to check the cross compilation toolchain since we do not # compile any source file with CMake, we only generate some SCP-firmware # files. scpfw-cmake-flags-y += -DCMAKE_C_COMPILER_WORKS=1 ifeq ($(cmd-echo-silent),true) scpfw-cmake-redirect = >/dev/null endif gensrcs-y += fwk_module_list force-gensrc-fwk_module_list := y produce-fwk_module_list = build/framework/src/fwk_module_list.c recipe-fwk_module_list = cmake -S $(scpfw-path) -B $(scpfw-out-path)/build \ $(scpfw-cmake-flags-y) --log-level=WARNING $(scpfw-cmake-redirect) depends-fwk_module_list = $(scpfw-path)/product/$(scpfw-product)/fw/Firmware.cmake $(conf-file) # Include path of generated header file fwk_module_idx.h incdirs_ext-y += $(scpfw-out-path)/build/framework/include cppflags-lib-y += -DBUILD_VERSION_MAJOR=$(scpfw-integ-version-maj) \ -DBUILD_VERSION_MINOR=$(scpfw-integ-version-min) \ -DBUILD_VERSION_PATCH=$(scpfw-integ-version-pat) scpfw-impl-version := $(shell git -C $(scpfw-path) describe --tags --always --dirty=-dev 2>/dev/null || \ echo Unknown_$(scpfw-integ-version)) cppflags-lib-y += -DBUILD_VERSION_DESCRIBE_STRING=\"$(scpfw-impl-version)\" cppflags-lib-y += -DFWK_LOG_LEVEL=$(CFG_SCPFW_LOG_LEVEL) ifneq ($(CFG_SCPFW_LOG_LEVEL),0) cppflags-lib-y += -DFMW_LOG_MINIMAL_BANNER=1 endif cflags-lib-y += -Wno-cast-align \ -Wno-nonnull-compare \ -Wno-unused-parameter \ -Wno-suggest-attribute=format \ -Wno-declaration-after-statement # The below directives will be removed once SCP-firmware pull requests # 728 and 732 are merged. cflags-lib-y += -Wno-undef \ -Wno-missing-prototypes \ -Wno-missing-declarations \ -Wno-unused-but-set-variable \ -Wno-suggest-attribute=format # Notification implementation has strict aliasing issues cflags-lib-$(CFG_SCPFW_NOTIFICATION) += -Wno-strict-aliasing cppflags-lib-y += -DBUILD_HAS_SUB_SYSTEM_MODE=1 \ -DBUILD_HAS_BASE_PROTOCOL cppflags-lib-$(CFG_SCPFW_NOTIFICATION) += -DBUILD_HAS_NOTIFICATION \ -DBUILD_HAS_SCMI_NOTIFICATIONS cppflags-lib-$(CFG_SCPFW_FAST_CHANNELS) += -DBUILD_HAS_FAST_CHANNELS \ -DBUILD_HAS_SCMI_FAST_CHANNELS cppflags-lib-$(CFG_SCPFW_CLOCK_TREE_MGMT) += -DBUILD_HAS_CLOCK_TREE_MGMT cppflags-lib-$(CFG_SCPFW_SCMI_PERF_FAST_CHANNELS) += -DBUILD_HAS_SCMI_PERF_FAST_CHANNELS cppflags-lib-$(CFG_SCPFW_SCMI_PERF_PROTOCOL_OPS) \ += -DBUILD_HAS_SCMI_PERF_PROTOCOL_OPS cppflags-lib-$(CFG_SCPFW_SCMI_SENSOR_EVENTS) += -DBUILD_HAS_SCMI_SENSOR_EVENTS cppflags-lib-$(CFG_SCPFW_SCMI_SENSOR_V2) += -DBUILD_HAS_SCMI_SENSOR_V2 \ -DBUILD_HAS_SENSOR_TIMESTAMP \ -DBUILD_HAS_SENSOR_MULTI_AXIS \ -DBUILD_HAS_SENSOR_EXT_ATTRIBS \ -DBUILD_HAS_SENSOR_SIGNED_VALUE cppflags-lib-$(CFG_SCPFW_SENSOR_TIMESTAMP) += -DBUILD_HAS_SENSOR_TIMESTAMP cppflags-lib-$(CFG_SCPFW_SENSOR_MULTI_AXIS) += -DBUILD_HAS_SENSOR_MULTI_AXI cppflags-lib-$(CFG_SCPFW_SENSOR_EXT_ATTRIBS) += -DBUILD_HAS_SENSOR_EXT_ATTRIBS cppflags-lib-$(CFG_SCPFW_SENSOR_SIGNED_VALUE) += -DBUILD_HAS_SENSOR_SIGNED_VALUE cppflags-lib-$(CFG_SCPFW_INBAND_MSG_SUPPORT) += -DBUILD_HAS_INBAND_MSG_SUPPORT # Include SCP-firmware make files include $(scpfw-path)/product/optee/sub.mk optee_os-4.3.0/core/lib/zlib/000077500000000000000000000000001464416617300160055ustar00rootroot00000000000000optee_os-4.3.0/core/lib/zlib/adler32.c000066400000000000000000000121651464416617300174120ustar00rootroot00000000000000// SPDX-License-Identifier: Zlib /* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware -- try it both ways to see which is faster */ #ifdef NO_DIVIDE /* note that this assumes BASE is 65521, where 65536 % 65521 == 15 (thank you to John Reiser for pointing this out) */ # define CHOP(a) \ do { \ unsigned long tmp = a >> 16; \ a &= 0xffffUL; \ a += (tmp << 4) - tmp; \ } while (0) # define MOD28(a) \ do { \ CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD(a) \ do { \ CHOP(a); \ MOD28(a); \ } while (0) # define MOD63(a) \ do { /* this assumes a is not negative */ \ z_off64_t tmp = a >> 32; \ a &= 0xffffffffL; \ a += (tmp << 8) - (tmp << 5) + tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD28(a) a %= BASE # define MOD63(a) a %= BASE #endif /* ========================================================================= */ uLong ZEXPORT adler32_z(adler, buf, len) uLong adler; const Bytef *buf; z_size_t len; { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32(adler, buf, len) uLong adler; const Bytef *buf; uInt len; { return adler32_z(adler, buf, len); } /* ========================================================================= */ local uLong adler32_combine_(adler1, adler2, len2) uLong adler1; uLong adler2; z_off64_t len2; { unsigned long sum1; unsigned long sum2; unsigned rem; /* for negative len, return invalid adler32 as a clue for debugging */ if (len2 < 0) return 0xffffffffUL; /* the derivation of this formula is left as an exercise for the reader */ MOD63(len2); /* assumes len2 >= 0 */ rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong ZEXPORT adler32_combine(adler1, adler2, len2) uLong adler1; uLong adler2; z_off_t len2; { return adler32_combine_(adler1, adler2, len2); } uLong ZEXPORT adler32_combine64(adler1, adler2, len2) uLong adler1; uLong adler2; z_off64_t len2; { return adler32_combine_(adler1, adler2, len2); } optee_os-4.3.0/core/lib/zlib/gzguts.h000066400000000000000000000153371464416617300175120ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* gzguts.h -- zlib internal header definitions for gz* operations * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef _LARGEFILE64_SOURCE # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif # ifdef _FILE_OFFSET_BITS # undef _FILE_OFFSET_BITS # endif #endif #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include #include "zlib.h" #ifdef STDC # include # include # include #endif #ifndef _POSIX_SOURCE # define _POSIX_SOURCE #endif #include #ifdef _WIN32 # include #endif #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif #if defined(_WIN32) # define WIDECHAR #endif #ifdef WINAPI_FAMILY # define open _open # define read _read # define write _write # define close _close #endif #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif #if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(__CYGWIN__) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) # ifndef HAVE_VSNPRINTF # define HAVE_VSNPRINTF # endif #endif #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ # define NO_vsnprintf # endif # ifdef WIN32 /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) # define vsnprintf _vsnprintf # endif # endif # endif # ifdef __SASC # define NO_vsnprintf # endif # ifdef VMS # define NO_vsnprintf # endif # ifdef __OS400__ # define NO_vsnprintf # endif # ifdef __MVS__ # define NO_vsnprintf # endif #endif /* unlike snprintf (which is required in C99), _snprintf does not guarantee null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ #if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif #ifndef local # define local static #endif /* since "static" is used to mean two completely different things in C, we define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC extern voidp malloc OF((uInt size)); extern void free OF((voidpf ptr)); #endif /* get errno and strerror definition */ #if defined UNDER_CE # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else # ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else # define zstrerror() "stdio error (consult errno)" # endif #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); #endif /* default memLevel */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default i/o buffer size -- double this for output when reading (this and twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ #define GZ_NONE 0 #define GZ_READ 7247 #define GZ_WRITE 31153 #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ /* values for gz_state how */ #define LOOK 0 /* look for a gzip header */ #define COPY 1 /* copy input directly */ #define GZIP 2 /* decompress a gzip stream */ /* internal gzip file state data structure */ typedef struct { /* exposed contents for gzgetc() macro */ struct gzFile_s x; /* "x" for exposed */ /* x.have: number of bytes available at x.next */ /* x.next: next output data to deliver or write */ /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ int how; /* 0: get header, 1: copy, 2: decompress */ z_off64_t start; /* where the gzip data started, for rewinding */ int eof; /* true if end of input file reached */ int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ int reset; /* true if a reset is pending after a Z_FINISH */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ /* zlib inflate or deflate stream */ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state FAR *gz_statep; /* shared functions */ void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); #if defined UNDER_CE char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); #endif /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ #ifdef INT_MAX # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #else unsigned ZLIB_INTERNAL gz_intmax OF((void)); # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) #endif optee_os-4.3.0/core/lib/zlib/inffast.c000066400000000000000000000313471464416617300176130ustar00rootroot00000000000000// SPDX-License-Identifier: Zlib /* inffast.c -- fast decoding * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef ASMINF # pragma message("Assembler code may have bugs -- use at your own risk") #else /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void ZLIB_INTERNAL inflate_fast(strm, start) z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const FAR *lcode; /* local strm->lencode */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code const *here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char FAR *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; in = strm->next_in; last = in + (strm->avail_in - 5); out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } here = lcode + (hold & lmask); dolen: op = (unsigned)(here->bits); hold >>= op; bits -= op; op = (unsigned)(here->op); if (op == 0) { /* literal */ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here->val)); *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(*in++) << bits; bits += 8; hold += (unsigned long)(*in++) << bits; bits += 8; } here = dcode + (hold & dmask); dodist: op = (unsigned)(here->bits); hold >>= op; bits -= op; op = (unsigned)(here->op); if (op & 16) { /* distance base */ dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(*in++) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { *out++ = 0; } while (--len); continue; } len -= op - whave; do { *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { *out++ = *from++; } while (--len); continue; } #endif } from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } else if (wnext < op) { /* wrap around window */ from += wsize + wnext - op; op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { *out++ = *from++; } while (--op); from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { *out++ = *from++; *out++ = *from++; *out++ = *from++; len -= 3; } if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ *out++ = *from++; *out++ = *from++; *out++ = *from++; len -= 3; } while (len > 2); if (len) { *out++ = *from++; if (len > 1) *out++ = *from++; } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in; strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ #endif /* !ASMINF */ optee_os-4.3.0/core/lib/zlib/inffast.h000066400000000000000000000007171464416617300176150ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); optee_os-4.3.0/core/lib/zlib/inffixed.h000066400000000000000000000142741464416617300177620ustar00rootroot00000000000000 /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of this library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, {0,9,255} }; static const code distfix[32] = { {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, {22,5,193},{64,5,0} }; optee_os-4.3.0/core/lib/zlib/inflate.c000066400000000000000000001553001464416617300175770ustar00rootroot00000000000000// SPDX-License-Identifier: Zlib /* inflate.c -- zlib decompression * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common wnext == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif /* function prototypes */ local int inflateStateCheck OF((z_streamp strm)); local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, unsigned copy)); #ifdef BUILDFIXED void makefixed OF((void)); #endif local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); local int inflateStateCheck(strm) z_streamp strm; { struct inflate_state FAR *state; if (strm == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) return 1; state = (struct inflate_state FAR *)strm->state; if (state == Z_NULL || state->strm != strm || state->mode < HEAD || state->mode > SYNC) return 1; return 0; } int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; if (state->wrap) /* to support ill-conceived Java test suite */ strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->flags = -1; state->dmax = 32768U; state->head = Z_NULL; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int ZEXPORT inflateReset(strm) z_streamp strm; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; state->wnext = 0; return inflateResetKeep(strm); } int ZEXPORT inflateReset2(strm, windowBits) z_streamp strm; int windowBits; { int wrap; struct inflate_state FAR *state; /* get the state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { wrap = 0; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } /* set number of window bits, free window if different */ if (windowBits && (windowBits < 8 || windowBits > 15)) return Z_STREAM_ERROR; if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { ZFREE(strm, state->window); state->window = Z_NULL; } /* update state and reset the rest of it */ state->wrap = wrap; state->wbits = (unsigned)windowBits; return inflateReset(strm); } int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) z_streamp strm; int windowBits; const char *version; int stream_size; { int ret; struct inflate_state FAR *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->strm = strm; state->window = Z_NULL; state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); strm->state = Z_NULL; } return ret; } int ZEXPORT inflateInit_(strm, version, stream_size) z_streamp strm; const char *version; int stream_size; { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } int ZEXPORT inflatePrime(strm, bits, value) z_streamp strm; int bits; int value; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += (unsigned)value << state->bits; state->bits += (uInt)bits; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ local void fixedtables(state) struct inflate_state FAR *state; { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed() { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ local int updatewindow(strm, end, copy) z_streamp strm; const Bytef *end; unsigned copy; { struct inflate_state FAR *state; unsigned dist; state = (struct inflate_state FAR *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char FAR *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->wnext = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ if (copy >= state->wsize) { zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } else { state->wnext += dist; if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE_CHECK(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE_CHECK(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int ZEXPORT inflate(strm, flush) z_streamp strm; int flush; { struct inflate_state FAR *state; z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char FAR *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ if (state->wbits == 0) state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; state->flags = 0; /* indicate zlib header */ Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); state->mode = TIME; /* fallthrough */ case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if ((state->flags & 0x0200) && (state->wrap & 4)) CRC4(state->check, hold); INITBITS(); state->mode = OS; /* fallthrough */ case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; /* fallthrough */ case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if ((state->flags & 0x0200) && (state->wrap & 4)) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; /* fallthrough */ case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL) { len = state->head->extra_len - state->length; zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; /* fallthrough */ case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; /* fallthrough */ case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; /* fallthrough */ case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; /* fallthrough */ case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; /* fallthrough */ case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; /* fallthrough */ case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; /* fallthrough */ case COPY_: state->mode = COPY; /* fallthrough */ case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; /* fallthrough */ case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; /* fallthrough */ case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; /* fallthrough */ case LEN_: state->mode = LEN; /* fallthrough */ case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; break; } state->back = 0; for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->back = -1; state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; /* fallthrough */ case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; /* fallthrough */ case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; /* fallthrough */ case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; /* fallthrough */ case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->wnext) { copy -= state->wnext; from = state->window + (state->wsize - copy); } else from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE_CHECK(state->check, put - out, out); out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; /* fallthrough */ case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; /* fallthrough */ case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: /* fallthrough */ default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE_CHECK(state->check, strm->next_out - out, out); strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) z_streamp strm; Bytef *dictionary; uInt *dictLength; { struct inflate_state FAR *state; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ if (state->whave && dictionary != Z_NULL) { zmemcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); zmemcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); } if (dictLength != Z_NULL) *dictLength = state->whave; return Z_OK; } int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; unsigned long dictid; int ret; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary identifier */ if (state->mode == DICT) { dictid = adler32(0L, Z_NULL, 0); dictid = adler32(dictid, dictionary, dictLength); if (dictid != state->check) return Z_DATA_ERROR; } /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ ret = updatewindow(strm, dictionary + dictLength, dictLength); if (ret) { state->mode = MEM; return Z_MEM_ERROR; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int ZEXPORT inflateGetHeader(strm, head) z_streamp strm; gz_headerp head; { struct inflate_state FAR *state; /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; const unsigned char FAR *buf; unsigned len; { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int ZEXPORT inflateSync(strm) z_streamp strm; { unsigned len; /* number of bytes to look at or looked at */ int flags; /* temporary to save header status */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state FAR *state; /* check parameters */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold <<= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; if (state->flags == -1) state->wrap = 0; /* if no header yet, treat as raw */ else state->wrap &= ~4; /* no point in computing a check value now */ flags = state->flags; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->flags = flags; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int ZEXPORT inflateSyncPoint(strm) z_streamp strm; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } int ZEXPORT inflateCopy(dest, source) z_streamp dest; z_streamp source; { struct inflate_state FAR *state; struct inflate_state FAR *copy; unsigned char FAR *window; unsigned wsize; /* check input */ if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; /* allocate space */ copy = (struct inflate_state FAR *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char FAR *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state FAR *)copy; return Z_OK; } int ZEXPORT inflateUndermine(strm, subvert) z_streamp strm; int subvert; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR state->sane = !subvert; return Z_OK; #else (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } int ZEXPORT inflateValidate(strm, check) z_streamp strm; int check; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (check && state->wrap) state->wrap |= 4; else state->wrap &= ~4; return Z_OK; } long ZEXPORT inflateMark(strm) z_streamp strm; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return -(1L << 16); state = (struct inflate_state FAR *)strm->state; return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } unsigned long ZEXPORT inflateCodesUsed(strm) z_streamp strm; { struct inflate_state FAR *state; if (inflateStateCheck(strm)) return (unsigned long)-1; state = (struct inflate_state FAR *)strm->state; return (unsigned long)(state->next - state->codes); } optee_os-4.3.0/core/lib/zlib/inflate.h000066400000000000000000000150771464416617300176120ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* inflate.h -- internal inflate state definition * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif /* Possible inflate modes between inflate() calls */ typedef enum { HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ EXLEN, /* i: waiting for extra length (gzip) */ EXTRA, /* i: waiting for extra bytes (gzip) */ NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ TYPEDO, /* i: same, but skip check to exit inflate on new block */ STORED, /* i: waiting for stored size (length and complement) */ COPY_, /* i/o: same as COPY below, but only first time in */ COPY, /* i/o: waiting for input or output to copy stored block */ TABLE, /* i: waiting for dynamic block table lengths */ LENLENS, /* i: waiting for code length code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */ LEN_, /* i: same as LEN below, but only first time in */ LEN, /* i: waiting for length/lit/eob code */ LENEXT, /* i: waiting for length extra bits */ DIST, /* i: waiting for distance code */ DISTEXT, /* i: waiting for distance extra bits */ MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ LENGTH, /* i: waiting for 32-bit length (gzip) */ DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; /* State transitions between above modes - (most modes can go to BAD or MEM on error -- not shown for clarity) Process header: HEAD -> (gzip) or (zlib) or (raw) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE (raw) -> TYPEDO Read deflate blocks: TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK STORED -> COPY_ -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN_ LEN_ -> LEN Read deflate codes in fixed or dynamic block: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* State maintained between inflate() calls -- approximately 7K bytes, not including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip, bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags, 0 if zlib, or -1 if raw or no header yet */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const FAR *lencode; /* starting table for length/literal codes */ code const FAR *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code FAR *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; optee_os-4.3.0/core/lib/zlib/inftrees.c000066400000000000000000000313511464416617300177730ustar00rootroot00000000000000// SPDX-License-Identifier: Zlib /* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.2.12 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) codetype type; unsigned short FAR *lens; unsigned codes; code FAR * FAR *table; unsigned FAR *bits; unsigned short FAR *work; { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftrees.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ match = 20; break; case LENS: base = lbase; extra = lext; match = 257; break; default: /* DISTS */ base = dbase; extra = dext; match = 0; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } else if (work[sym] >= match) { here.op = (unsigned char)(extra[work[sym] - match]); here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used > ENOUGH_LENS) || (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ if (huff != 0) { here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; next[huff] = here; } /* set return parameters */ *table += used; *bits = root; return 0; } optee_os-4.3.0/core/lib/zlib/inftrees.h000066400000000000000000000056241464416617300200040ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table() */ typedef enum { CODES, LENS, DISTS } codetype; int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, unsigned codes, code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work)); optee_os-4.3.0/core/lib/zlib/sub.mk000066400000000000000000000004521464416617300171300ustar00rootroot00000000000000global-incdirs-y += . srcs-y += adler32.c srcs-y += inffast.c srcs-y += inflate.c srcs-y += inftrees.c srcs-y += zutil.c cflags-remove-y += -Wold-style-definition cflags-remove-y += -Wswitch-default cflags-remove-y += -Wstrict-prototypes cflags-y += $(call cc-option,-Wno-deprecated-non-prototype) optee_os-4.3.0/core/lib/zlib/zconf.h000066400000000000000000000402111464416617300172730ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H #define Z_SOLO #define ZLIB_CONST #define NO_GZIP /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateGetDictionary z_deflateGetDictionary # define deflateInit z_deflateInit # define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # ifndef Z_SOLO # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzfread z_gzfread # define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # ifdef _WIN32 # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ # define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader # define inflateInit z_inflateInit # define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress # define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO # define zcalloc z_zcalloc # define zcfree z_zcfree # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # ifndef Z_SOLO # define gzFile z_gzFile # endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif #ifdef Z_SOLO typedef unsigned long z_size_t; #else # define z_longlong long long # if defined(NO_SIZE_T) typedef unsigned NO_SIZE_T z_size_t; # elif defined(STDC) # include typedef size_t z_size_t; # else typedef unsigned long z_size_t; # endif # undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif #ifndef Z_ARG /* function prototypes for stdarg */ # if defined(STDC) || defined(Z_HAVE_STDARG_H) # define Z_ARG(args) args # else # define Z_ARG(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) # define Z_HAVE_UNISTD_H #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif /* Other places expect _LFS64_LARGEFILE to be defined with a valid value */ #ifndef _LFS64_LARGEFILE #define _LFS64_LARGEFILE 0 #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ optee_os-4.3.0/core/lib/zlib/zlib.h000066400000000000000000002761111464416617300171260ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.12, March 11th, 2022 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.2.12" #define ZLIB_VERNUM 0x12c0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 12 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip and raw deflate streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text for deflate, or the decoding state for inflate */ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. In that case, zlib is thread-safe. When zalloc and zfree are Z_NULL on entry to the initialization function, they are set to internal routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary. Some output may be provided even if flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), which can be used if desired to determine whether or not there is more ouput in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six to avoid repeated flush markers due to avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used in the first deflate call after deflateInit if all the compression is to be done in a single step. In order to complete in one call, avail_out must be at least the value returned by deflateBound (see below). Then deflate is guaranteed to return Z_STREAM_END. If not enough output space is provided, deflate will not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the Adler-32 checksum of all input read so far (that is, total_in bytes). If a gzip stream is being generated, then strm->adler will be the CRC-32 checksum of the input read so far. (See deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL or the state was inadvertently written over by the application), or Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression. Actual decompression will be done by inflate(). So next_in, and avail_in, next_out, and avail_out are unused and unchanged. The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), then next_in and avail_in are updated accordingly, and processing will resume at this point for the next call of inflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. If the caller of inflate() does not provide both available input and available output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and inflate() can be called again to continue the operation as if Z_NO_FLUSH had been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of inflate() as noted below, when inflate() returns early when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output produced so far. The CRC-32 is checked against the gzip trailer, as is the uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value, in which case strm->msg points to a string with a more specific error), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL, or the state was inadvertently written over by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress was possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is to be attempted. */ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state was inconsistent. */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. For the current implementation of deflate(), a windowBits value of 8 (a window size of 256 bytes) is not supported. As a result, a request for 8 will result in 9 (a 512-byte window). In that case, providing 8 to inflateInit2() will result in an error when the zlib header with 9 is checked against the initialization of inflate(). The remedy is to not use 8 with deflateInit2() with this initialization, or at least in that case use 9 with inflateInit2(). windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to the appropriate value, if the operating system was determined at compile time. If a gzip stream is being written, strm->adler is a CRC-32 instead of an Adler-32. For raw deflate or gzip encoding, a request for a 256-byte window is rejected as invalid, since only the zlib header provides a means of transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this function must be called either before any call of deflate, or immediately after the completion of a deflate block, i.e. after all input has been consumed and all output has been delivered when using any of the flush options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similary, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up to 258 bytes less in that case, due to how zlib's implementation of deflate manages the sliding window and lookahead for matches, where matches can be up to 258 bytes long. If the application needs the last window-size bytes of input, then that would need to be saved by the application outside of zlib. deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been set unchanged. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the strategy is changed, and if there have been any deflate() calls since the state was initialized or reset, then the input available so far is compressed with the old level and strategy using deflate(strm, Z_BLOCK). There are three approaches for the compression levels 0, 1..3, and 4..9 respectively. The new level and strategy will take effect at the next call of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not take effect. In this case, deflateParams() can be called again with the same parameters and more output space to try again. In order to assure a change in the parameters on the first try, the deflate stream should be flushed using deflate() with Z_BLOCK or other flush request until strm.avail_out is not zero, before calling deflateParams(). Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be applied to the the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if there was not enough output space to complete the compression of the available input data before a change in the strategy or approach. Note that in the case of a Z_BUF_ERROR, the parameters are not changed. A return value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be retried with more output space. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen)); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, unsigned *pending, int *bits)); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are Z_NULL, then those values are not set. deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head)); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to 255, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see below), inflate() will *not* automatically decode concatenated gzip members. inflate() will return Z_STREAM_END at the end of the gzip member. The state would need to be reset to continue decoding a subsequent gzip member. This *must* be done if there is more data after a gzip member, in order for the decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similary, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. All full flush points have this pattern, but not all occurrences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, int windowBits)); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. If the window size is changed, then the memory allocated for the window is freed, and the window will be reallocated by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value)); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head)); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window)); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func) OF((void FAR *, z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than inflate() for file i/o applications, in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. inflate() can be faster on modern CPUs when used with large buffers. inflateBack() trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the default behavior of inflate(), which expects a zlib header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero -- buf is ignored in that case -- and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ #ifndef Z_SOLO /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress() is equivalent to compress2() with a level parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong *sourceLen)); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of source bytes consumed. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); Open the gzip (.gz) file at path for reading and decompressing, or compressing and writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or appending with no compression and not using the gzip format. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. The addition of "x" when writing will create the file exclusively, which fails if the file already exists. On systems that support it, the addition of "e" when reading or writing will set the flag to close the file on an execve() call. These functions, as well as gzip, will read and decode a sequence of gzip streams in a file. The append function of gzopen() can be used to create such a file. (Also see gzflush() for another way to do this.) When appending, gzopen does not test whether the file begins with a gzip stream, nor does it look for the end of the gzip streams to begin appending. gzopen will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. When reading, this will be detected automatically by looking for the magic two- byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* Associate a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. If you are using fileno() to get the file descriptor from a FILE *, then you will have to use dup() to avoid double-close()ing the file descriptor. Both gzclose() and fclose() will close the associated file descriptor, so they need to have different file descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* Set the internal buffer size used by this library's functions for file to size. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Three times that size in buffer space is allocated. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level and strategy for file. See the description of deflateInit2 for the meaning of these parameters. Previously provided data is flushed before applying the parameter changes. gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not opened for writing, Z_ERRNO if there is an error writing the flushed data, or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be concatenated in the input file, and will all be decompressed by gzread(). If something other than a gzip stream is encountered after a gzip stream, that remaining trailing garbage is ignored (and no error is returned). gzread can be used to read a gzip file that is being concurrently written. Upon reaching the end of the input, gzread will return with the available data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then gzclearerr can be used to clear the end of file indicator in order to permit gzread to be tried again. Z_OK indicates that a gzip stream was completed on the last gzread. Z_BUF_ERROR indicates that the input file ended in the middle of a gzip stream. Note that gzread does not return -1 in the event of an incomplete gzip stream. This error is deferred until gzclose(), which will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip stream. Alternatively, gzerror can be used before gzclose to detect this case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. If len is too large to fit in an int, then nothing is read, -1 is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, gzFile file)); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of stdio's fread(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfread() returns the number of full items read of size size, or zero if the end of the file was reached and a full item could not be read, or if there was an error. gzerror() must be consulted if zero is returned in order to determine if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is read, zero is returned, and the error state is set to Z_STREAM_ERROR. In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a multiple of size, then the final partial item is nevetheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written file, reseting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* Compress and write the len uncompressed bytes at buf to file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, z_size_t nitems, gzFile file)); /* Compress and write nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfwrite() returns the number of full items written of size size, or zero if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is written, zero is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Convert, format, compress, and write the arguments (...) to file under control of the string format, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or a negative zlib error code in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf(), because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); /* Compress and write the given null-terminated string s to file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* Read and decompress bytes from file into buf, until len-1 characters are read, or until a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len is one, the string is terminated with a null character. If no characters are read due to an end-of-file or len is less than one, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* Push c back onto the stream for file to be read as the first character on the next read. At least one character of push-back is always allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* Flush all pending output to file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); Set the starting position to offset relative to whence for the next gzread or gzwrite on file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* Rewind file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); Return the starting position for the next gzread or gzwrite on file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); Return the current compressed (actual) read or write offset of file. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Return true (1) if the end-of-file indicator for file has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). When writing, gzdirect() returns true (1) if transparent writing was requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: gzdirect() is not needed when writing. Transparent writing must be explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flush all pending output for file, if necessary, close file and deallocate the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* Return the error message for the last error which occurred on file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); /* Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. An Adler-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, z_size_t len)); /* Same as adler32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, z_size_t len)); /* Same as crc32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ /* ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); Return the operator corresponding to length len2, to be used with crc32_combine_op(). */ ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than crc32_combine() if the generated op is used more than once. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); #ifdef Z_PREFIX_SET # define z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define z_inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #else # define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #endif #ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The * user should not mess with these exposed elements, since their names or * behavior could change in the future, perhaps even capriciously. They can * only be used by the gzgetc() macro. You have been warned. */ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) # ifdef Z_PREFIX_SET # define z_gzopen z_gzopen64 # define z_gzseek z_gzseek64 # define z_gztell z_gztell64 # define z_gzoffset z_gzoffset64 # define z_adler32_combine z_adler32_combine64 # define z_crc32_combine z_crc32_combine64 # define z_crc32_combine_gen z_crc32_combine_gen64 # else # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 # define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); # endif #else ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); #endif #else /* Z_SOLO */ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); #endif /* !Z_SOLO */ /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if defined(_WIN32) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, const char *format, va_list va)); # endif #endif #ifdef __cplusplus } #endif #endif /* ZLIB_H */ optee_os-4.3.0/core/lib/zlib/zutil.c000066400000000000000000000163051464416617300173250ustar00rootroot00000000000000// SPDX-License-Identifier: Zlib /* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" #ifndef Z_SOLO # include "gzguts.h" #endif z_const char * const z_errmsg[10] = { (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ (z_const char *)"stream end", /* Z_STREAM_END 1 */ (z_const char *)"", /* Z_OK 0 */ (z_const char *)"file error", /* Z_ERRNO (-1) */ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ (z_const char *)"" }; const char * ZEXPORT zlibVersion() { return ZLIB_VERSION; } uLong ZEXPORT zlibCompileFlags() { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch ((int)(sizeof(uLong))) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch ((int)(sizeof(voidpf))) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch ((int)(sizeof(z_off_t))) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef ZLIB_DEBUG flags += 1 << 8; #endif #if defined(ASMV) || defined(ASMINF) flags += 1 << 9; #endif #ifdef ZLIB_WINAPI flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf flags += 1L << 25; # ifdef HAS_vsprintf_void flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void flags += 1L << 26; # endif # endif #else flags += 1L << 24; # ifdef NO_snprintf flags += 1L << 25; # ifdef HAS_sprintf_void flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void flags += 1L << 26; # endif # endif #endif return flags; } #ifdef ZLIB_DEBUG #include # ifndef verbose # define verbose 0 # endif int ZLIB_INTERNAL z_verbose = verbose; void ZLIB_INTERNAL z_error (m) char *m; { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char * ZEXPORT zError(err) int err; { return ERR_MSG(err); } #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ int errno = 0; #endif #ifndef HAVE_MEMCPY void ZLIB_INTERNAL zmemcpy(dest, source, len) Bytef* dest; const Bytef* source; uInt len; { if (len == 0) return; do { *dest++ = *source++; /* ??? to be unrolled */ } while (--len != 0); } int ZLIB_INTERNAL zmemcmp(s1, s2, len) const Bytef* s1; const Bytef* s2; uInt len; { uInt j; for (j = 0; j < len; j++) { if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; } return 0; } void ZLIB_INTERNAL zmemzero(dest, len) Bytef* dest; uInt len; { if (len == 0) return; do { *dest++ = 0; /* ??? to be unrolled */ } while (--len != 0); } #endif #ifndef Z_SOLO #ifdef SYS16BIT #ifdef __TURBOC__ /* Turbo C in 16-bit mode */ # define MY_ZCALLOC /* Turbo C malloc() does not allow dynamic allocation of 64K bytes * and farmalloc(64K) returns a pointer with an offset of 8, so we * must fix the pointer. Warning: the pointer must be put back to its * original form in order to free it, use zcfree(). */ #define MAX_PTR 10 /* 10*64K = 640K */ local int next_ptr = 0; typedef struct ptr_table_s { voidpf org_ptr; voidpf new_ptr; } ptr_table; local ptr_table table[MAX_PTR]; /* This table is used to remember the original form of pointers * to large buffers (64K). Such pointers are normalized with a zero offset. * Since MSDOS is not a preemptive multitasking OS, this table is not * protected from concurrent access. This hack doesn't work anyway on * a protected system like OS/2. Use Microsoft C instead. */ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { voidpf buf; ulg bsize = (ulg)items*size; (void)opaque; /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ if (bsize < 65520L) { buf = farmalloc(bsize); if (*(ush*)&buf != 0) return buf; } else { buf = farmalloc(bsize + 16L); } if (buf == NULL || next_ptr >= MAX_PTR) return NULL; table[next_ptr].org_ptr = buf; /* Normalize the pointer to seg:0 */ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; *(ush*)&buf = 0; table[next_ptr++].new_ptr = buf; return buf; } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; (void)opaque; if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; } /* Find the original pointer */ for (n = 0; n < next_ptr; n++) { if (ptr != table[n].new_ptr) continue; farfree(table[n].org_ptr); while (++n < next_ptr) { table[n-1] = table[n]; } next_ptr--; return; } Assert(0, "zcfree: ptr not found"); } #endif /* __TURBOC__ */ #ifdef M_I86 /* Microsoft C in 16-bit mode */ # define MY_ZCALLOC #if (!defined(_MSC_VER) || (_MSC_VER <= 600)) # define _halloc halloc # define _hfree hfree #endif voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { (void)opaque; return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { (void)opaque; _hfree(ptr); } #endif /* M_I86 */ #endif /* SYS16BIT */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef STDC extern voidp malloc OF((uInt size)); extern voidp calloc OF((uInt items, uInt size)); extern void free OF((voidpf ptr)); #endif voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) voidpf opaque; unsigned items; unsigned size; { (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void ZLIB_INTERNAL zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { (void)opaque; free(ptr); } #endif /* MY_ZCALLOC */ #endif /* !Z_SOLO */ optee_os-4.3.0/core/lib/zlib/zutil.h000066400000000000000000000161501464416617300173300ustar00rootroot00000000000000/* SPDX-License-Identifier: Zlib */ /* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* @(#) $Id$ */ #ifndef ZUTIL_H #define ZUTIL_H #ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL #endif #include "zlib.h" #if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif # include # include #endif #ifndef local # define local static #endif /* since "static" is used to mean two completely different things in C, we define "local" for the non-static meaning of "static", for readability (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; #if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC) # include # if (ULONG_MAX == 0xffffffffffffffff) # define Z_U8 unsigned long # elif (ULLONG_MAX == 0xffffffffffffffff) # define Z_U8 unsigned long long # elif (UINT_MAX == 0xffffffffffffffff) # define Z_U8 unsigned # endif #endif extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 # ifndef Z_SOLO # if defined(__TURBOC__) || defined(__BORLANDC__) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) /* Allow compilation with ANSI keywords only enabled */ void _Cdecl farfree( void *block ); void *_Cdecl farmalloc( unsigned long nbytes ); # else # include # endif # else /* MSC or DJGPP */ # include # endif # endif #endif #ifdef AMIGA # define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) # define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif #ifdef __370__ # if __TARGET_LIB__ < 0x20000000 # define OS_CODE 4 # elif __TARGET_LIB__ < 0x40000000 # define OS_CODE 11 # else # define OS_CODE 8 # endif #endif #if defined(ATARI) || defined(atarist) # define OS_CODE 5 #endif #ifdef OS2 # define OS_CODE 6 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 7 # ifndef Z_SOLO # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ # else # ifndef fdopen # define fdopen(fd,mode) NULL /* No fdopen() */ # endif # endif # endif #endif #ifdef __acorn # define OS_CODE 13 #endif #if defined(WIN32) && !defined(__CYGWIN__) # define OS_CODE 10 #endif #ifdef _BEOS_ # define OS_CODE 16 #endif #ifdef __TOS_OS400__ # define OS_CODE 18 #endif #ifdef __APPLE__ # define OS_CODE 19 #endif #if defined(_BEOS_) || defined(RISCOS) # define fdopen(fd,mode) NULL /* No fdopen() */ #endif #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX # if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ # else # define fdopen(fd,type) _fdopen(fd,type) # endif #endif #if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ #if !defined(_WIN32) && \ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif /* common defaults */ #ifndef OS_CODE # define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) /* Use our own functions for small and medium model with MSC <= 5.0. * You may have to use the same strategy for Borland C (untested). * The __SC__ check is for Symantec. */ # define NO_MEMCPY #endif #if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) # define HAVE_MEMCPY #endif #ifdef HAVE_MEMCPY # ifdef SMALL_MEDIUM /* MSDOS small or medium model */ # define zmemcpy _fmemcpy # define zmemcmp _fmemcmp # define zmemzero(dest, len) _fmemset(dest, 0, len) # else # define zmemcpy memcpy # define zmemcmp memcmp # define zmemzero(dest, len) memset(dest, 0, len) # endif #else void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); #endif /* Diagnostic functions */ #ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error OF((char *m)); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif #ifndef Z_SOLO voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, unsigned size)); void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); #endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} /* Reverse the bytes in a 32-bit value */ #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) #endif /* ZUTIL_H */ optee_os-4.3.0/core/mm/000077500000000000000000000000001464416617300147105ustar00rootroot00000000000000optee_os-4.3.0/core/mm/core_mmu.c000066400000000000000000002024311464416617300166640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, 2022 Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef DEBUG_XLAT_TABLE #define DEBUG_XLAT_TABLE 0 #endif #define SHM_VASPACE_SIZE (1024 * 1024 * 32) /* Physical Secure DDR pool */ tee_mm_pool_t tee_mm_sec_ddr; /* Virtual memory pool for core mappings */ tee_mm_pool_t core_virt_mem_pool; /* Virtual memory pool for shared memory mappings */ tee_mm_pool_t core_virt_shm_pool; #ifdef CFG_CORE_PHYS_RELOCATABLE unsigned long core_mmu_tee_load_pa __nex_bss; #else const unsigned long core_mmu_tee_load_pa = TEE_LOAD_ADDR; #endif /* * These variables are initialized before .bss is cleared. To avoid * resetting them when .bss is cleared we're storing them in .data instead, * even if they initially are zero. */ #ifdef CFG_CORE_RESERVED_SHM /* Default NSec shared memory allocated from NSec world */ unsigned long default_nsec_shm_size __nex_bss; unsigned long default_nsec_shm_paddr __nex_bss; #endif static struct tee_mmap_region static_memory_map[CFG_MMAP_REGIONS #if defined(CFG_CORE_ASLR) || defined(CFG_CORE_PHYS_RELOCATABLE) + 1 #endif + 1] __nex_bss; /* Define the platform's memory layout. */ struct memaccess_area { paddr_t paddr; size_t size; }; #define MEMACCESS_AREA(a, s) { .paddr = a, .size = s } static struct memaccess_area secure_only[] __nex_data = { #ifdef CFG_CORE_PHYS_RELOCATABLE MEMACCESS_AREA(0, 0), #else #ifdef TRUSTED_SRAM_BASE MEMACCESS_AREA(TRUSTED_SRAM_BASE, TRUSTED_SRAM_SIZE), #endif MEMACCESS_AREA(TRUSTED_DRAM_BASE, TRUSTED_DRAM_SIZE), #endif }; static struct memaccess_area nsec_shared[] __nex_data = { #ifdef CFG_CORE_RESERVED_SHM MEMACCESS_AREA(TEE_SHMEM_START, TEE_SHMEM_SIZE), #endif }; #if defined(CFG_SECURE_DATA_PATH) static const char *tz_sdp_match = "linaro,secure-heap"; static struct memaccess_area sec_sdp; #ifdef CFG_TEE_SDP_MEM_BASE register_sdp_mem(CFG_TEE_SDP_MEM_BASE, CFG_TEE_SDP_MEM_SIZE); #endif #ifdef TEE_SDP_TEST_MEM_BASE register_sdp_mem(TEE_SDP_TEST_MEM_BASE, TEE_SDP_TEST_MEM_SIZE); #endif #endif #ifdef CFG_CORE_RESERVED_SHM register_phys_mem(MEM_AREA_NSEC_SHM, TEE_SHMEM_START, TEE_SHMEM_SIZE); #endif static unsigned int mmu_spinlock; static uint32_t mmu_lock(void) { return cpu_spin_lock_xsave(&mmu_spinlock); } static void mmu_unlock(uint32_t exceptions) { cpu_spin_unlock_xrestore(&mmu_spinlock, exceptions); } void core_mmu_get_secure_memory(paddr_t *base, paddr_size_t *size) { /* * The first range is always used to cover OP-TEE core memory, but * depending on configuration it may cover more than that. */ *base = secure_only[0].paddr; *size = secure_only[0].size; } void core_mmu_set_secure_memory(paddr_t base, size_t size) { #ifdef CFG_CORE_PHYS_RELOCATABLE static_assert(ARRAY_SIZE(secure_only) == 1); #endif runtime_assert(IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)); assert(!secure_only[0].size); assert(base && size); DMSG("Physical secure memory base %#"PRIxPA" size %#zx", base, size); secure_only[0].paddr = base; secure_only[0].size = size; } void core_mmu_get_ta_range(paddr_t *base, size_t *size) { paddr_t b = 0; size_t s = 0; static_assert(!(TEE_RAM_VA_SIZE % SMALL_PAGE_SIZE)); #ifdef TA_RAM_START b = TA_RAM_START; s = TA_RAM_SIZE; #else static_assert(ARRAY_SIZE(secure_only) <= 2); if (ARRAY_SIZE(secure_only) == 1) { vaddr_t load_offs = 0; assert(core_mmu_tee_load_pa >= secure_only[0].paddr); load_offs = core_mmu_tee_load_pa - secure_only[0].paddr; assert(secure_only[0].size > load_offs + TEE_RAM_VA_SIZE + TEE_SDP_TEST_MEM_SIZE); b = secure_only[0].paddr + load_offs + TEE_RAM_VA_SIZE; s = secure_only[0].size - load_offs - TEE_RAM_VA_SIZE - TEE_SDP_TEST_MEM_SIZE; } else { assert(secure_only[1].size > TEE_SDP_TEST_MEM_SIZE); b = secure_only[1].paddr; s = secure_only[1].size - TEE_SDP_TEST_MEM_SIZE; } #endif if (base) *base = b; if (size) *size = s; } static struct tee_mmap_region *get_memory_map(void) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { struct tee_mmap_region *map = virt_get_memory_map(); if (map) return map; } return static_memory_map; } static bool _pbuf_intersects(struct memaccess_area *a, size_t alen, paddr_t pa, size_t size) { size_t n; for (n = 0; n < alen; n++) if (core_is_buffer_intersect(pa, size, a[n].paddr, a[n].size)) return true; return false; } #define pbuf_intersects(a, pa, size) \ _pbuf_intersects((a), ARRAY_SIZE(a), (pa), (size)) static bool _pbuf_is_inside(struct memaccess_area *a, size_t alen, paddr_t pa, size_t size) { size_t n; for (n = 0; n < alen; n++) if (core_is_buffer_inside(pa, size, a[n].paddr, a[n].size)) return true; return false; } #define pbuf_is_inside(a, pa, size) \ _pbuf_is_inside((a), ARRAY_SIZE(a), (pa), (size)) static bool pa_is_in_map(struct tee_mmap_region *map, paddr_t pa, size_t len) { paddr_t end_pa = 0; if (!map) return false; if (SUB_OVERFLOW(len, 1, &end_pa) || ADD_OVERFLOW(pa, end_pa, &end_pa)) return false; return (pa >= map->pa && end_pa <= map->pa + map->size - 1); } static bool va_is_in_map(struct tee_mmap_region *map, vaddr_t va) { if (!map) return false; return (va >= map->va && va <= (map->va + map->size - 1)); } /* check if target buffer fits in a core default map area */ static bool pbuf_inside_map_area(unsigned long p, size_t l, struct tee_mmap_region *map) { return core_is_buffer_inside(p, l, map->pa, map->size); } static struct tee_mmap_region *find_map_by_type(enum teecore_memtypes type) { struct tee_mmap_region *map; for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) if (map->type == type) return map; return NULL; } static struct tee_mmap_region * find_map_by_type_and_pa(enum teecore_memtypes type, paddr_t pa, size_t len) { struct tee_mmap_region *map; for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) { if (map->type != type) continue; if (pa_is_in_map(map, pa, len)) return map; } return NULL; } static struct tee_mmap_region *find_map_by_va(void *va) { struct tee_mmap_region *map = get_memory_map(); unsigned long a = (unsigned long)va; while (!core_mmap_is_end_of_table(map)) { if (a >= map->va && a <= (map->va - 1 + map->size)) return map; map++; } return NULL; } static struct tee_mmap_region *find_map_by_pa(unsigned long pa) { struct tee_mmap_region *map = get_memory_map(); while (!core_mmap_is_end_of_table(map)) { /* Skip unmapped regions */ if ((map->attr & TEE_MATTR_VALID_BLOCK) && pa >= map->pa && pa <= (map->pa + map->size - 1)) return map; map++; } return NULL; } #if defined(CFG_SECURE_DATA_PATH) static bool dtb_get_sdp_region(void) { void *fdt = NULL; int node = 0; int tmp_node = 0; paddr_t tmp_addr = 0; size_t tmp_size = 0; if (!IS_ENABLED(CFG_EMBED_DTB)) return false; fdt = get_embedded_dt(); if (!fdt) panic("No DTB found"); node = fdt_node_offset_by_compatible(fdt, -1, tz_sdp_match); if (node < 0) { DMSG("No %s compatible node found", tz_sdp_match); return false; } tmp_node = node; while (tmp_node >= 0) { tmp_node = fdt_node_offset_by_compatible(fdt, tmp_node, tz_sdp_match); if (tmp_node >= 0) DMSG("Ignore SDP pool node %s, supports only 1 node", fdt_get_name(fdt, tmp_node, NULL)); } tmp_addr = fdt_reg_base_address(fdt, node); if (tmp_addr == DT_INFO_INVALID_REG) { EMSG("%s: Unable to get base addr from DT", tz_sdp_match); return false; } tmp_size = fdt_reg_size(fdt, node); if (tmp_size == DT_INFO_INVALID_REG_SIZE) { EMSG("%s: Unable to get size of base addr from DT", tz_sdp_match); return false; } sec_sdp.paddr = tmp_addr; sec_sdp.size = tmp_size; return true; } #endif #if defined(CFG_CORE_DYN_SHM) || defined(CFG_SECURE_DATA_PATH) static bool pbuf_is_special_mem(paddr_t pbuf, size_t len, const struct core_mmu_phys_mem *start, const struct core_mmu_phys_mem *end) { const struct core_mmu_phys_mem *mem; for (mem = start; mem < end; mem++) { if (core_is_buffer_inside(pbuf, len, mem->addr, mem->size)) return true; } return false; } #endif #ifdef CFG_CORE_DYN_SHM static void carve_out_phys_mem(struct core_mmu_phys_mem **mem, size_t *nelems, paddr_t pa, size_t size) { struct core_mmu_phys_mem *m = *mem; size_t n = 0; while (true) { if (n >= *nelems) { DMSG("No need to carve out %#" PRIxPA " size %#zx", pa, size); return; } if (core_is_buffer_inside(pa, size, m[n].addr, m[n].size)) break; if (!core_is_buffer_outside(pa, size, m[n].addr, m[n].size)) panic(); n++; } if (pa == m[n].addr && size == m[n].size) { /* Remove this entry */ (*nelems)--; memmove(m + n, m + n + 1, sizeof(*m) * (*nelems - n)); m = nex_realloc(m, sizeof(*m) * *nelems); if (!m) panic(); *mem = m; } else if (pa == m[n].addr) { m[n].addr += size; m[n].size -= size; } else if ((pa + size) == (m[n].addr + m[n].size)) { m[n].size -= size; } else { /* Need to split the memory entry */ m = nex_realloc(m, sizeof(*m) * (*nelems + 1)); if (!m) panic(); *mem = m; memmove(m + n + 1, m + n, sizeof(*m) * (*nelems - n)); (*nelems)++; m[n].size = pa - m[n].addr; m[n + 1].size -= size + m[n].size; m[n + 1].addr = pa + size; } } static void check_phys_mem_is_outside(struct core_mmu_phys_mem *start, size_t nelems, struct tee_mmap_region *map) { size_t n; for (n = 0; n < nelems; n++) { if (!core_is_buffer_outside(start[n].addr, start[n].size, map->pa, map->size)) { EMSG("Non-sec mem (%#" PRIxPA ":%#" PRIxPASZ ") overlaps map (type %d %#" PRIxPA ":%#zx)", start[n].addr, start[n].size, map->type, map->pa, map->size); panic(); } } } static const struct core_mmu_phys_mem *discovered_nsec_ddr_start __nex_bss; static size_t discovered_nsec_ddr_nelems __nex_bss; static int cmp_pmem_by_addr(const void *a, const void *b) { const struct core_mmu_phys_mem *pmem_a = a; const struct core_mmu_phys_mem *pmem_b = b; return CMP_TRILEAN(pmem_a->addr, pmem_b->addr); } void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start, size_t nelems) { struct core_mmu_phys_mem *m = start; size_t num_elems = nelems; struct tee_mmap_region *map = static_memory_map; const struct core_mmu_phys_mem __maybe_unused *pmem; size_t n = 0; assert(!discovered_nsec_ddr_start); assert(m && num_elems); qsort(m, num_elems, sizeof(*m), cmp_pmem_by_addr); /* * Non-secure shared memory and also secure data * path memory are supposed to reside inside * non-secure memory. Since NSEC_SHM and SDP_MEM * are used for a specific purpose make holes for * those memory in the normal non-secure memory. * * This has to be done since for instance QEMU * isn't aware of which memory range in the * non-secure memory is used for NSEC_SHM. */ #ifdef CFG_SECURE_DATA_PATH if (dtb_get_sdp_region()) carve_out_phys_mem(&m, &num_elems, sec_sdp.paddr, sec_sdp.size); for (pmem = phys_sdp_mem_begin; pmem < phys_sdp_mem_end; pmem++) carve_out_phys_mem(&m, &num_elems, pmem->addr, pmem->size); #endif for (n = 0; n < ARRAY_SIZE(secure_only); n++) carve_out_phys_mem(&m, &num_elems, secure_only[n].paddr, secure_only[n].size); for (map = static_memory_map; !core_mmap_is_end_of_table(map); map++) { switch (map->type) { case MEM_AREA_NSEC_SHM: carve_out_phys_mem(&m, &num_elems, map->pa, map->size); break; case MEM_AREA_EXT_DT: case MEM_AREA_MANIFEST_DT: case MEM_AREA_RAM_NSEC: case MEM_AREA_RES_VASPACE: case MEM_AREA_SHM_VASPACE: case MEM_AREA_TS_VASPACE: case MEM_AREA_PAGER_VASPACE: break; default: check_phys_mem_is_outside(m, num_elems, map); } } discovered_nsec_ddr_start = m; discovered_nsec_ddr_nelems = num_elems; if (!core_mmu_check_end_pa(m[num_elems - 1].addr, m[num_elems - 1].size)) panic(); } static bool get_discovered_nsec_ddr(const struct core_mmu_phys_mem **start, const struct core_mmu_phys_mem **end) { if (!discovered_nsec_ddr_start) return false; *start = discovered_nsec_ddr_start; *end = discovered_nsec_ddr_start + discovered_nsec_ddr_nelems; return true; } static bool pbuf_is_nsec_ddr(paddr_t pbuf, size_t len) { const struct core_mmu_phys_mem *start; const struct core_mmu_phys_mem *end; if (!get_discovered_nsec_ddr(&start, &end)) return false; return pbuf_is_special_mem(pbuf, len, start, end); } bool core_mmu_nsec_ddr_is_defined(void) { const struct core_mmu_phys_mem *start; const struct core_mmu_phys_mem *end; if (!get_discovered_nsec_ddr(&start, &end)) return false; return start != end; } #else static bool pbuf_is_nsec_ddr(paddr_t pbuf __unused, size_t len __unused) { return false; } #endif /*CFG_CORE_DYN_SHM*/ #define MSG_MEM_INSTERSECT(pa1, sz1, pa2, sz2) \ EMSG("[%" PRIxPA " %" PRIx64 "] intersects [%" PRIxPA " %" PRIx64 "]", \ pa1, (uint64_t)pa1 + (sz1), pa2, (uint64_t)pa2 + (sz2)) #ifdef CFG_SECURE_DATA_PATH static bool pbuf_is_sdp_mem(paddr_t pbuf, size_t len) { bool is_sdp_mem = false; if (sec_sdp.size) is_sdp_mem = core_is_buffer_inside(pbuf, len, sec_sdp.paddr, sec_sdp.size); if (!is_sdp_mem) is_sdp_mem = pbuf_is_special_mem(pbuf, len, phys_sdp_mem_begin, phys_sdp_mem_end); return is_sdp_mem; } static struct mobj *core_sdp_mem_alloc_mobj(paddr_t pa, size_t size) { struct mobj *mobj = mobj_phys_alloc(pa, size, TEE_MATTR_MEM_TYPE_CACHED, CORE_MEM_SDP_MEM); if (!mobj) panic("can't create SDP physical memory object"); return mobj; } struct mobj **core_sdp_mem_create_mobjs(void) { const struct core_mmu_phys_mem *mem = NULL; struct mobj **mobj_base = NULL; struct mobj **mobj = NULL; int cnt = phys_sdp_mem_end - phys_sdp_mem_begin; if (sec_sdp.size) cnt++; /* SDP mobjs table must end with a NULL entry */ mobj_base = calloc(cnt + 1, sizeof(struct mobj *)); if (!mobj_base) panic("Out of memory"); mobj = mobj_base; for (mem = phys_sdp_mem_begin; mem < phys_sdp_mem_end; mem++, mobj++) *mobj = core_sdp_mem_alloc_mobj(mem->addr, mem->size); if (sec_sdp.size) *mobj = core_sdp_mem_alloc_mobj(sec_sdp.paddr, sec_sdp.size); return mobj_base; } #else /* CFG_SECURE_DATA_PATH */ static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused) { return false; } #endif /* CFG_SECURE_DATA_PATH */ /* Check special memories comply with registered memories */ static void verify_special_mem_areas(struct tee_mmap_region *mem_map, const struct core_mmu_phys_mem *start, const struct core_mmu_phys_mem *end, const char *area_name __maybe_unused) { const struct core_mmu_phys_mem *mem; const struct core_mmu_phys_mem *mem2; struct tee_mmap_region *mmap; if (start == end) { DMSG("No %s memory area defined", area_name); return; } for (mem = start; mem < end; mem++) DMSG("%s memory [%" PRIxPA " %" PRIx64 "]", area_name, mem->addr, (uint64_t)mem->addr + mem->size); /* Check memories do not intersect each other */ for (mem = start; mem + 1 < end; mem++) { for (mem2 = mem + 1; mem2 < end; mem2++) { if (core_is_buffer_intersect(mem2->addr, mem2->size, mem->addr, mem->size)) { MSG_MEM_INSTERSECT(mem2->addr, mem2->size, mem->addr, mem->size); panic("Special memory intersection"); } } } /* * Check memories do not intersect any mapped memory. * This is called before reserved VA space is loaded in mem_map. */ for (mem = start; mem < end; mem++) { for (mmap = mem_map; mmap->type != MEM_AREA_END; mmap++) { if (core_is_buffer_intersect(mem->addr, mem->size, mmap->pa, mmap->size)) { MSG_MEM_INSTERSECT(mem->addr, mem->size, mmap->pa, mmap->size); panic("Special memory intersection"); } } } } static void add_phys_mem(struct tee_mmap_region *memory_map, size_t num_elems, const char *mem_name __maybe_unused, enum teecore_memtypes mem_type, paddr_t mem_addr, paddr_size_t mem_size, size_t *last) { size_t n = 0; paddr_t pa; paddr_size_t size; if (!mem_size) /* Discard null size entries */ return; /* * If some ranges of memory of the same type do overlap * each others they are coalesced into one entry. To help this * added entries are sorted by increasing physical. * * Note that it's valid to have the same physical memory as several * different memory types, for instance the same device memory * mapped as both secure and non-secure. This will probably not * happen often in practice. */ DMSG("%s type %s 0x%08" PRIxPA " size 0x%08" PRIxPASZ, mem_name, teecore_memtype_name(mem_type), mem_addr, mem_size); while (true) { if (n >= (num_elems - 1)) { EMSG("Out of entries (%zu) in memory_map", num_elems); panic(); } if (n == *last) break; pa = memory_map[n].pa; size = memory_map[n].size; if (mem_type == memory_map[n].type && ((pa <= (mem_addr + (mem_size - 1))) && (mem_addr <= (pa + (size - 1))))) { DMSG("Physical mem map overlaps 0x%" PRIxPA, mem_addr); memory_map[n].pa = MIN(pa, mem_addr); memory_map[n].size = MAX(size, mem_size) + (pa - memory_map[n].pa); return; } if (mem_type < memory_map[n].type || (mem_type == memory_map[n].type && mem_addr < pa)) break; /* found the spot where to insert this memory */ n++; } memmove(memory_map + n + 1, memory_map + n, sizeof(struct tee_mmap_region) * (*last - n)); (*last)++; memset(memory_map + n, 0, sizeof(memory_map[0])); memory_map[n].type = mem_type; memory_map[n].pa = mem_addr; memory_map[n].size = mem_size; } static void add_va_space(struct tee_mmap_region *memory_map, size_t num_elems, enum teecore_memtypes type, size_t size, size_t *last) { size_t n = 0; DMSG("type %s size 0x%08zx", teecore_memtype_name(type), size); while (true) { if (n >= (num_elems - 1)) { EMSG("Out of entries (%zu) in memory_map", num_elems); panic(); } if (n == *last) break; if (type < memory_map[n].type) break; n++; } memmove(memory_map + n + 1, memory_map + n, sizeof(struct tee_mmap_region) * (*last - n)); (*last)++; memset(memory_map + n, 0, sizeof(memory_map[0])); memory_map[n].type = type; memory_map[n].size = size; } uint32_t core_mmu_type_to_attr(enum teecore_memtypes t) { const uint32_t attr = TEE_MATTR_VALID_BLOCK; const uint32_t tagged = TEE_MATTR_MEM_TYPE_TAGGED << TEE_MATTR_MEM_TYPE_SHIFT; const uint32_t cached = TEE_MATTR_MEM_TYPE_CACHED << TEE_MATTR_MEM_TYPE_SHIFT; const uint32_t noncache = TEE_MATTR_MEM_TYPE_DEV << TEE_MATTR_MEM_TYPE_SHIFT; switch (t) { case MEM_AREA_TEE_RAM: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | tagged; case MEM_AREA_TEE_RAM_RX: case MEM_AREA_INIT_RAM_RX: case MEM_AREA_IDENTITY_MAP_RX: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRX | tagged; case MEM_AREA_TEE_RAM_RO: case MEM_AREA_INIT_RAM_RO: return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | tagged; case MEM_AREA_TEE_RAM_RW: case MEM_AREA_NEX_RAM_RO: /* This has to be r/w during init runtime */ case MEM_AREA_NEX_RAM_RW: case MEM_AREA_TEE_ASAN: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged; case MEM_AREA_TEE_COHERENT: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | noncache; case MEM_AREA_TA_RAM: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged; case MEM_AREA_NSEC_SHM: case MEM_AREA_NEX_NSEC_SHM: return attr | TEE_MATTR_PRW | cached; case MEM_AREA_MANIFEST_DT: return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; case MEM_AREA_TRANSFER_LIST: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; case MEM_AREA_EXT_DT: /* * If CFG_MAP_EXT_DT_SECURE is enabled map the external device * tree as secure non-cached memory, otherwise, fall back to * non-secure mapping. */ if (IS_ENABLED(CFG_MAP_EXT_DT_SECURE)) return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | noncache; fallthrough; case MEM_AREA_IO_NSEC: return attr | TEE_MATTR_PRW | noncache; case MEM_AREA_IO_SEC: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | noncache; case MEM_AREA_RAM_NSEC: return attr | TEE_MATTR_PRW | cached; case MEM_AREA_RAM_SEC: case MEM_AREA_SEC_RAM_OVERALL: return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached; case MEM_AREA_ROM_SEC: return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached; case MEM_AREA_RES_VASPACE: case MEM_AREA_SHM_VASPACE: return 0; case MEM_AREA_PAGER_VASPACE: return TEE_MATTR_SECURE; default: panic("invalid type"); } } static bool __maybe_unused map_is_tee_ram(const struct tee_mmap_region *mm) { switch (mm->type) { case MEM_AREA_TEE_RAM: case MEM_AREA_TEE_RAM_RX: case MEM_AREA_TEE_RAM_RO: case MEM_AREA_TEE_RAM_RW: case MEM_AREA_INIT_RAM_RX: case MEM_AREA_INIT_RAM_RO: case MEM_AREA_NEX_RAM_RW: case MEM_AREA_NEX_RAM_RO: case MEM_AREA_TEE_ASAN: return true; default: return false; } } static bool __maybe_unused map_is_secure(const struct tee_mmap_region *mm) { return !!(core_mmu_type_to_attr(mm->type) & TEE_MATTR_SECURE); } static bool __maybe_unused map_is_pgdir(const struct tee_mmap_region *mm) { return mm->region_size == CORE_MMU_PGDIR_SIZE; } static int cmp_mmap_by_lower_va(const void *a, const void *b) { const struct tee_mmap_region *mm_a = a; const struct tee_mmap_region *mm_b = b; return CMP_TRILEAN(mm_a->va, mm_b->va); } static void dump_mmap_table(struct tee_mmap_region *memory_map) { struct tee_mmap_region *map; for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { vaddr_t __maybe_unused vstart; vstart = map->va + ((vaddr_t)map->pa & (map->region_size - 1)); DMSG("type %-12s va 0x%08" PRIxVA "..0x%08" PRIxVA " pa 0x%08" PRIxPA "..0x%08" PRIxPA " size 0x%08zx (%s)", teecore_memtype_name(map->type), vstart, vstart + map->size - 1, map->pa, (paddr_t)(map->pa + map->size - 1), map->size, map->region_size == SMALL_PAGE_SIZE ? "smallpg" : "pgdir"); } } #if DEBUG_XLAT_TABLE static void dump_xlat_table(vaddr_t va, unsigned int level) { struct core_mmu_table_info tbl_info; unsigned int idx = 0; paddr_t pa; uint32_t attr; core_mmu_find_table(NULL, va, level, &tbl_info); va = tbl_info.va_base; for (idx = 0; idx < tbl_info.num_entries; idx++) { core_mmu_get_entry(&tbl_info, idx, &pa, &attr); if (attr || level > CORE_MMU_BASE_TABLE_LEVEL) { const char *security_bit = ""; if (core_mmu_entry_have_security_bit(attr)) { if (attr & TEE_MATTR_SECURE) security_bit = "S"; else security_bit = "NS"; } if (attr & TEE_MATTR_TABLE) { DMSG_RAW("%*s [LVL%d] VA:0x%010" PRIxVA " TBL:0x%010" PRIxPA " %s", level * 2, "", level, va, pa, security_bit); dump_xlat_table(va, level + 1); } else if (attr) { DMSG_RAW("%*s [LVL%d] VA:0x%010" PRIxVA " PA:0x%010" PRIxPA " %s-%s-%s-%s", level * 2, "", level, va, pa, mattr_is_cached(attr) ? "MEM" : "DEV", attr & TEE_MATTR_PW ? "RW" : "RO", attr & TEE_MATTR_PX ? "X " : "XN", security_bit); } else { DMSG_RAW("%*s [LVL%d] VA:0x%010" PRIxVA " INVALID\n", level * 2, "", level, va); } } va += BIT64(tbl_info.shift); } } #else static void dump_xlat_table(vaddr_t va __unused, int level __unused) { } #endif /* * Reserves virtual memory space for pager usage. * * From the start of the first memory used by the link script + * TEE_RAM_VA_SIZE should be covered, either with a direct mapping or empty * mapping for pager usage. This adds translation tables as needed for the * pager to operate. */ static void add_pager_vaspace(struct tee_mmap_region *mmap, size_t num_elems, size_t *last) { paddr_t begin = 0; paddr_t end = 0; size_t size = 0; size_t pos = 0; size_t n = 0; if (*last >= (num_elems - 1)) { EMSG("Out of entries (%zu) in memory map", num_elems); panic(); } for (n = 0; !core_mmap_is_end_of_table(mmap + n); n++) { if (map_is_tee_ram(mmap + n)) { if (!begin) begin = mmap[n].pa; pos = n + 1; } } end = mmap[pos - 1].pa + mmap[pos - 1].size; assert(end - begin < TEE_RAM_VA_SIZE); size = TEE_RAM_VA_SIZE - (end - begin); assert(pos <= *last); memmove(mmap + pos + 1, mmap + pos, sizeof(struct tee_mmap_region) * (*last - pos)); (*last)++; memset(mmap + pos, 0, sizeof(mmap[0])); mmap[pos].type = MEM_AREA_PAGER_VASPACE; mmap[pos].va = 0; mmap[pos].size = size; mmap[pos].region_size = SMALL_PAGE_SIZE; mmap[pos].attr = core_mmu_type_to_attr(MEM_AREA_PAGER_VASPACE); } static void check_sec_nsec_mem_config(void) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(secure_only); n++) { if (pbuf_intersects(nsec_shared, secure_only[n].paddr, secure_only[n].size)) panic("Invalid memory access config: sec/nsec"); } } static void collect_device_mem_ranges(struct tee_mmap_region *memory_map, size_t num_elems, size_t *last) { const char *compatible = "arm,ffa-manifest-device-regions"; void *fdt = get_manifest_dt(); const char *name = NULL; uint64_t page_count = 0; uint64_t base = 0; int subnode = 0; int node = 0; assert(fdt); node = fdt_node_offset_by_compatible(fdt, 0, compatible); if (node < 0) return; fdt_for_each_subnode(subnode, fdt, node) { name = fdt_get_name(fdt, subnode, NULL); if (!name) continue; if (dt_getprop_as_number(fdt, subnode, "base-address", &base)) { EMSG("Mandatory field is missing: base-address"); continue; } if (base & SMALL_PAGE_MASK) { EMSG("base-address is not page aligned"); continue; } if (dt_getprop_as_number(fdt, subnode, "pages-count", &page_count)) { EMSG("Mandatory field is missing: pages-count"); continue; } add_phys_mem(memory_map, num_elems, name, MEM_AREA_IO_SEC, base, page_count * SMALL_PAGE_SIZE, last); } } static size_t collect_mem_ranges(struct tee_mmap_region *memory_map, size_t num_elems) { const struct core_mmu_phys_mem *mem = NULL; vaddr_t ram_start = secure_only[0].paddr; size_t last = 0; #define ADD_PHYS_MEM(_type, _addr, _size) \ add_phys_mem(memory_map, num_elems, #_addr, (_type), \ (_addr), (_size), &last) if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) { ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RO, ram_start, VCORE_UNPG_RX_PA - ram_start); ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RX, VCORE_UNPG_RX_PA, VCORE_UNPG_RX_SZ); ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RO, VCORE_UNPG_RO_PA, VCORE_UNPG_RO_SZ); if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RO, VCORE_UNPG_RW_PA, VCORE_UNPG_RW_SZ); ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RW, VCORE_NEX_RW_PA, VCORE_NEX_RW_SZ); } else { ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RW, VCORE_UNPG_RW_PA, VCORE_UNPG_RW_SZ); } if (IS_ENABLED(CFG_WITH_PAGER)) { ADD_PHYS_MEM(MEM_AREA_INIT_RAM_RX, VCORE_INIT_RX_PA, VCORE_INIT_RX_SZ); ADD_PHYS_MEM(MEM_AREA_INIT_RAM_RO, VCORE_INIT_RO_PA, VCORE_INIT_RO_SZ); } } else { ADD_PHYS_MEM(MEM_AREA_TEE_RAM, TEE_RAM_START, TEE_RAM_PH_SIZE); } if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, TRUSTED_DRAM_BASE, TRUSTED_DRAM_SIZE); } else { /* * Every guest will have own TA RAM if virtualization * support is enabled. */ paddr_t ta_base = 0; size_t ta_size = 0; core_mmu_get_ta_range(&ta_base, &ta_size); ADD_PHYS_MEM(MEM_AREA_TA_RAM, ta_base, ta_size); } if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS) && IS_ENABLED(CFG_WITH_PAGER)) { /* * Asan ram is part of MEM_AREA_TEE_RAM_RW when pager is * disabled. */ ADD_PHYS_MEM(MEM_AREA_TEE_ASAN, ASAN_MAP_PA, ASAN_MAP_SZ); } #undef ADD_PHYS_MEM /* Collect device memory info from SP manifest */ if (IS_ENABLED(CFG_CORE_SEL2_SPMC)) collect_device_mem_ranges(memory_map, num_elems, &last); for (mem = phys_mem_map_begin; mem < phys_mem_map_end; mem++) { /* Only unmapped virtual range may have a null phys addr */ assert(mem->addr || !core_mmu_type_to_attr(mem->type)); add_phys_mem(memory_map, num_elems, mem->name, mem->type, mem->addr, mem->size, &last); } if (IS_ENABLED(CFG_SECURE_DATA_PATH)) verify_special_mem_areas(memory_map, phys_sdp_mem_begin, phys_sdp_mem_end, "SDP"); add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE, CFG_RESERVED_VASPACE_SIZE, &last); add_va_space(memory_map, num_elems, MEM_AREA_SHM_VASPACE, SHM_VASPACE_SIZE, &last); memory_map[last].type = MEM_AREA_END; return last; } static void assign_mem_granularity(struct tee_mmap_region *memory_map) { struct tee_mmap_region *map = NULL; /* * Assign region sizes, note that MEM_AREA_TEE_RAM always uses * SMALL_PAGE_SIZE. */ for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { paddr_t mask = map->pa | map->size; if (!(mask & CORE_MMU_PGDIR_MASK)) map->region_size = CORE_MMU_PGDIR_SIZE; else if (!(mask & SMALL_PAGE_MASK)) map->region_size = SMALL_PAGE_SIZE; else panic("Impossible memory alignment"); if (map_is_tee_ram(map)) map->region_size = SMALL_PAGE_SIZE; } } static bool place_tee_ram_at_top(paddr_t paddr) { return paddr > BIT64(core_mmu_get_va_width()) / 2; } /* * MMU arch driver shall override this function if it helps * optimizing the memory footprint of the address translation tables. */ bool __weak core_mmu_prefer_tee_ram_at_top(paddr_t paddr) { return place_tee_ram_at_top(paddr); } static bool assign_mem_va_dir(vaddr_t tee_ram_va, struct tee_mmap_region *memory_map, bool tee_ram_at_top) { struct tee_mmap_region *map = NULL; vaddr_t va = 0; bool va_is_secure = true; /* * tee_ram_va might equals 0 when CFG_CORE_ASLR=y. * 0 is by design an invalid va, so return false directly. */ if (!tee_ram_va) return false; /* Clear eventual previous assignments */ for (map = memory_map; !core_mmap_is_end_of_table(map); map++) map->va = 0; /* * TEE RAM regions are always aligned with region_size. * * Note that MEM_AREA_PAGER_VASPACE also counts as TEE RAM here * since it handles virtual memory which covers the part of the ELF * that cannot fit directly into memory. */ va = tee_ram_va; for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { if (map_is_tee_ram(map) || map->type == MEM_AREA_PAGER_VASPACE) { assert(!(va & (map->region_size - 1))); assert(!(map->size & (map->region_size - 1))); map->va = va; if (ADD_OVERFLOW(va, map->size, &va)) return false; if (va >= BIT64(core_mmu_get_va_width())) return false; } } if (tee_ram_at_top) { /* * Map non-tee ram regions at addresses lower than the tee * ram region. */ va = tee_ram_va; for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { map->attr = core_mmu_type_to_attr(map->type); if (map->va) continue; if (!IS_ENABLED(CFG_WITH_LPAE) && va_is_secure != map_is_secure(map)) { va_is_secure = !va_is_secure; va = ROUNDDOWN(va, CORE_MMU_PGDIR_SIZE); } if (SUB_OVERFLOW(va, map->size, &va)) return false; va = ROUNDDOWN(va, map->region_size); /* * Make sure that va is aligned with pa for * efficient pgdir mapping. Basically pa & * pgdir_mask should be == va & pgdir_mask */ if (map->size > 2 * CORE_MMU_PGDIR_SIZE) { if (SUB_OVERFLOW(va, CORE_MMU_PGDIR_SIZE, &va)) return false; va += (map->pa - va) & CORE_MMU_PGDIR_MASK; } map->va = va; } } else { /* * Map non-tee ram regions at addresses higher than the tee * ram region. */ for (map = memory_map; !core_mmap_is_end_of_table(map); map++) { map->attr = core_mmu_type_to_attr(map->type); if (map->va) continue; if (!IS_ENABLED(CFG_WITH_LPAE) && va_is_secure != map_is_secure(map)) { va_is_secure = !va_is_secure; if (ROUNDUP_OVERFLOW(va, CORE_MMU_PGDIR_SIZE, &va)) return false; } if (ROUNDUP_OVERFLOW(va, map->region_size, &va)) return false; /* * Make sure that va is aligned with pa for * efficient pgdir mapping. Basically pa & * pgdir_mask should be == va & pgdir_mask */ if (map->size > 2 * CORE_MMU_PGDIR_SIZE) { vaddr_t offs = (map->pa - va) & CORE_MMU_PGDIR_MASK; if (ADD_OVERFLOW(va, offs, &va)) return false; } map->va = va; if (ADD_OVERFLOW(va, map->size, &va)) return false; if (va >= BIT64(core_mmu_get_va_width())) return false; } } return true; } static bool assign_mem_va(vaddr_t tee_ram_va, struct tee_mmap_region *memory_map) { bool tee_ram_at_top = place_tee_ram_at_top(tee_ram_va); /* * Check that we're not overlapping with the user VA range. */ if (IS_ENABLED(CFG_WITH_LPAE)) { /* * User VA range is supposed to be defined after these * mappings have been established. */ assert(!core_mmu_user_va_range_is_defined()); } else { vaddr_t user_va_base = 0; size_t user_va_size = 0; assert(core_mmu_user_va_range_is_defined()); core_mmu_get_user_va_range(&user_va_base, &user_va_size); if (tee_ram_va < (user_va_base + user_va_size)) return false; } if (IS_ENABLED(CFG_WITH_PAGER)) { bool prefered_dir = core_mmu_prefer_tee_ram_at_top(tee_ram_va); /* Try whole mapping covered by a single base xlat entry */ if (prefered_dir != tee_ram_at_top && assign_mem_va_dir(tee_ram_va, memory_map, prefered_dir)) return true; } return assign_mem_va_dir(tee_ram_va, memory_map, tee_ram_at_top); } static int cmp_init_mem_map(const void *a, const void *b) { const struct tee_mmap_region *mm_a = a; const struct tee_mmap_region *mm_b = b; int rc = 0; rc = CMP_TRILEAN(mm_a->region_size, mm_b->region_size); if (!rc) rc = CMP_TRILEAN(mm_a->pa, mm_b->pa); /* * 32bit MMU descriptors cannot mix secure and non-secure mapping in * the same level2 table. Hence sort secure mapping from non-secure * mapping. */ if (!rc && !IS_ENABLED(CFG_WITH_LPAE)) rc = CMP_TRILEAN(map_is_secure(mm_a), map_is_secure(mm_b)); return rc; } static bool mem_map_add_id_map(struct tee_mmap_region *memory_map, size_t num_elems, size_t *last, vaddr_t id_map_start, vaddr_t id_map_end) { struct tee_mmap_region *map = NULL; vaddr_t start = ROUNDDOWN(id_map_start, SMALL_PAGE_SIZE); vaddr_t end = ROUNDUP(id_map_end, SMALL_PAGE_SIZE); size_t len = end - start; if (*last >= num_elems - 1) { EMSG("Out of entries (%zu) in memory map", num_elems); panic(); } for (map = memory_map; !core_mmap_is_end_of_table(map); map++) if (core_is_buffer_intersect(map->va, map->size, start, len)) return false; *map = (struct tee_mmap_region){ .type = MEM_AREA_IDENTITY_MAP_RX, /* * Could use CORE_MMU_PGDIR_SIZE to potentially save a * translation table, at the increased risk of clashes with * the rest of the memory map. */ .region_size = SMALL_PAGE_SIZE, .pa = start, .va = start, .size = len, .attr = core_mmu_type_to_attr(MEM_AREA_IDENTITY_MAP_RX), }; (*last)++; return true; } static unsigned long init_mem_map(struct tee_mmap_region *memory_map, size_t num_elems, unsigned long seed) { /* * @id_map_start and @id_map_end describes a physical memory range * that must be mapped Read-Only eXecutable at identical virtual * addresses. */ vaddr_t id_map_start = (vaddr_t)__identity_map_init_start; vaddr_t id_map_end = (vaddr_t)__identity_map_init_end; vaddr_t start_addr = secure_only[0].paddr; unsigned long offs = 0; size_t last = 0; last = collect_mem_ranges(memory_map, num_elems); assign_mem_granularity(memory_map); /* * To ease mapping and lower use of xlat tables, sort mapping * description moving small-page regions after the pgdir regions. */ qsort(memory_map, last, sizeof(struct tee_mmap_region), cmp_init_mem_map); if (IS_ENABLED(CFG_WITH_PAGER)) add_pager_vaspace(memory_map, num_elems, &last); if (IS_ENABLED(CFG_CORE_ASLR) && seed) { vaddr_t base_addr = start_addr + seed; const unsigned int va_width = core_mmu_get_va_width(); const vaddr_t va_mask = GENMASK_64(va_width - 1, SMALL_PAGE_SHIFT); vaddr_t ba = base_addr; size_t n = 0; for (n = 0; n < 3; n++) { if (n) ba = base_addr ^ BIT64(va_width - n); ba &= va_mask; if (assign_mem_va(ba, memory_map) && mem_map_add_id_map(memory_map, num_elems, &last, id_map_start, id_map_end)) { offs = ba - start_addr; DMSG("Mapping core at %#"PRIxVA" offs %#lx", ba, offs); goto out; } else { DMSG("Failed to map core at %#"PRIxVA, ba); } } EMSG("Failed to map core with seed %#lx", seed); } if (!assign_mem_va(start_addr, memory_map)) panic(); out: qsort(memory_map, last, sizeof(struct tee_mmap_region), cmp_mmap_by_lower_va); dump_mmap_table(memory_map); return offs; } static void check_mem_map(struct tee_mmap_region *map) { struct tee_mmap_region *m = NULL; for (m = map; !core_mmap_is_end_of_table(m); m++) { switch (m->type) { case MEM_AREA_TEE_RAM: case MEM_AREA_TEE_RAM_RX: case MEM_AREA_TEE_RAM_RO: case MEM_AREA_TEE_RAM_RW: case MEM_AREA_INIT_RAM_RX: case MEM_AREA_INIT_RAM_RO: case MEM_AREA_NEX_RAM_RW: case MEM_AREA_NEX_RAM_RO: case MEM_AREA_IDENTITY_MAP_RX: if (!pbuf_is_inside(secure_only, m->pa, m->size)) panic("TEE_RAM can't fit in secure_only"); break; case MEM_AREA_TA_RAM: if (!pbuf_is_inside(secure_only, m->pa, m->size)) panic("TA_RAM can't fit in secure_only"); break; case MEM_AREA_NSEC_SHM: if (!pbuf_is_inside(nsec_shared, m->pa, m->size)) panic("NS_SHM can't fit in nsec_shared"); break; case MEM_AREA_SEC_RAM_OVERALL: case MEM_AREA_TEE_COHERENT: case MEM_AREA_TEE_ASAN: case MEM_AREA_IO_SEC: case MEM_AREA_IO_NSEC: case MEM_AREA_EXT_DT: case MEM_AREA_MANIFEST_DT: case MEM_AREA_TRANSFER_LIST: case MEM_AREA_RAM_SEC: case MEM_AREA_RAM_NSEC: case MEM_AREA_ROM_SEC: case MEM_AREA_RES_VASPACE: case MEM_AREA_SHM_VASPACE: case MEM_AREA_PAGER_VASPACE: break; default: EMSG("Uhandled memtype %d", m->type); panic(); } } } static struct tee_mmap_region *get_tmp_mmap(void) { struct tee_mmap_region *tmp_mmap = (void *)__heap1_start; #ifdef CFG_WITH_PAGER if (__heap1_end - __heap1_start < (ptrdiff_t)sizeof(static_memory_map)) tmp_mmap = (void *)__heap2_start; #endif memset(tmp_mmap, 0, sizeof(static_memory_map)); return tmp_mmap; } /* * core_init_mmu_map() - init tee core default memory mapping * * This routine sets the static default TEE core mapping. If @seed is > 0 * and configured with CFG_CORE_ASLR it will map tee core at a location * based on the seed and return the offset from the link address. * * If an error happened: core_init_mmu_map is expected to panic. * * Note: this function is weak just to make it possible to exclude it from * the unpaged area. */ void __weak core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg) { #ifndef CFG_NS_VIRTUALIZATION vaddr_t start = ROUNDDOWN((vaddr_t)__nozi_start, SMALL_PAGE_SIZE); #else vaddr_t start = ROUNDDOWN((vaddr_t)__vcore_nex_rw_start, SMALL_PAGE_SIZE); #endif vaddr_t len = ROUNDUP((vaddr_t)__nozi_end, SMALL_PAGE_SIZE) - start; struct tee_mmap_region *tmp_mmap = get_tmp_mmap(); unsigned long offs = 0; if (IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE) && (core_mmu_tee_load_pa & SMALL_PAGE_MASK)) panic("OP-TEE load address is not page aligned"); check_sec_nsec_mem_config(); /* * Add a entry covering the translation tables which will be * involved in some virt_to_phys() and phys_to_virt() conversions. */ static_memory_map[0] = (struct tee_mmap_region){ .type = MEM_AREA_TEE_RAM, .region_size = SMALL_PAGE_SIZE, .pa = start, .va = start, .size = len, .attr = core_mmu_type_to_attr(MEM_AREA_IDENTITY_MAP_RX), }; COMPILE_TIME_ASSERT(CFG_MMAP_REGIONS >= 13); offs = init_mem_map(tmp_mmap, ARRAY_SIZE(static_memory_map), seed); check_mem_map(tmp_mmap); core_init_mmu(tmp_mmap); dump_xlat_table(0x0, CORE_MMU_BASE_TABLE_LEVEL); core_init_mmu_regs(cfg); cfg->map_offset = offs; memcpy(static_memory_map, tmp_mmap, sizeof(static_memory_map)); } bool core_mmu_mattr_is_ok(uint32_t mattr) { /* * Keep in sync with core_mmu_lpae.c:mattr_to_desc and * core_mmu_v7.c:mattr_to_texcb */ switch ((mattr >> TEE_MATTR_MEM_TYPE_SHIFT) & TEE_MATTR_MEM_TYPE_MASK) { case TEE_MATTR_MEM_TYPE_DEV: case TEE_MATTR_MEM_TYPE_STRONGLY_O: case TEE_MATTR_MEM_TYPE_CACHED: case TEE_MATTR_MEM_TYPE_TAGGED: return true; default: return false; } } /* * test attributes of target physical buffer * * Flags: pbuf_is(SECURE, NOT_SECURE, RAM, IOMEM, KEYVAULT). * */ bool core_pbuf_is(uint32_t attr, paddr_t pbuf, size_t len) { paddr_t ta_base = 0; size_t ta_size = 0; struct tee_mmap_region *map; /* Empty buffers complies with anything */ if (len == 0) return true; switch (attr) { case CORE_MEM_SEC: return pbuf_is_inside(secure_only, pbuf, len); case CORE_MEM_NON_SEC: return pbuf_is_inside(nsec_shared, pbuf, len) || pbuf_is_nsec_ddr(pbuf, len); case CORE_MEM_TEE_RAM: return core_is_buffer_inside(pbuf, len, TEE_RAM_START, TEE_RAM_PH_SIZE); case CORE_MEM_TA_RAM: core_mmu_get_ta_range(&ta_base, &ta_size); return core_is_buffer_inside(pbuf, len, ta_base, ta_size); #ifdef CFG_CORE_RESERVED_SHM case CORE_MEM_NSEC_SHM: return core_is_buffer_inside(pbuf, len, TEE_SHMEM_START, TEE_SHMEM_SIZE); #endif case CORE_MEM_SDP_MEM: return pbuf_is_sdp_mem(pbuf, len); case CORE_MEM_CACHED: map = find_map_by_pa(pbuf); if (!map || !pbuf_inside_map_area(pbuf, len, map)) return false; return mattr_is_cached(map->attr); default: return false; } } /* test attributes of target virtual buffer (in core mapping) */ bool core_vbuf_is(uint32_t attr, const void *vbuf, size_t len) { paddr_t p; /* Empty buffers complies with anything */ if (len == 0) return true; p = virt_to_phys((void *)vbuf); if (!p) return false; return core_pbuf_is(attr, p, len); } /* core_va2pa - teecore exported service */ static int __maybe_unused core_va2pa_helper(void *va, paddr_t *pa) { struct tee_mmap_region *map; map = find_map_by_va(va); if (!va_is_in_map(map, (vaddr_t)va)) return -1; /* * We can calculate PA for static map. Virtual address ranges * reserved to core dynamic mapping return a 'match' (return 0;) * together with an invalid null physical address. */ if (map->pa) *pa = map->pa + (vaddr_t)va - map->va; else *pa = 0; return 0; } static void *map_pa2va(struct tee_mmap_region *map, paddr_t pa, size_t len) { if (!pa_is_in_map(map, pa, len)) return NULL; return (void *)(vaddr_t)(map->va + pa - map->pa); } /* * teecore gets some memory area definitions */ void core_mmu_get_mem_by_type(enum teecore_memtypes type, vaddr_t *s, vaddr_t *e) { struct tee_mmap_region *map = find_map_by_type(type); if (map) { *s = map->va; *e = map->va + map->size; } else { *s = 0; *e = 0; } } enum teecore_memtypes core_mmu_get_type_by_pa(paddr_t pa) { struct tee_mmap_region *map = find_map_by_pa(pa); if (!map) return MEM_AREA_MAXTYPE; return map->type; } void core_mmu_set_entry(struct core_mmu_table_info *tbl_info, unsigned int idx, paddr_t pa, uint32_t attr) { assert(idx < tbl_info->num_entries); core_mmu_set_entry_primitive(tbl_info->table, tbl_info->level, idx, pa, attr); } void core_mmu_get_entry(struct core_mmu_table_info *tbl_info, unsigned int idx, paddr_t *pa, uint32_t *attr) { assert(idx < tbl_info->num_entries); core_mmu_get_entry_primitive(tbl_info->table, tbl_info->level, idx, pa, attr); } static void clear_region(struct core_mmu_table_info *tbl_info, struct tee_mmap_region *region) { unsigned int end = 0; unsigned int idx = 0; /* va, len and pa should be block aligned */ assert(!core_mmu_get_block_offset(tbl_info, region->va)); assert(!core_mmu_get_block_offset(tbl_info, region->size)); assert(!core_mmu_get_block_offset(tbl_info, region->pa)); idx = core_mmu_va2idx(tbl_info, region->va); end = core_mmu_va2idx(tbl_info, region->va + region->size); while (idx < end) { core_mmu_set_entry(tbl_info, idx, 0, 0); idx++; } } static void set_region(struct core_mmu_table_info *tbl_info, struct tee_mmap_region *region) { unsigned int end; unsigned int idx; paddr_t pa; /* va, len and pa should be block aligned */ assert(!core_mmu_get_block_offset(tbl_info, region->va)); assert(!core_mmu_get_block_offset(tbl_info, region->size)); assert(!core_mmu_get_block_offset(tbl_info, region->pa)); idx = core_mmu_va2idx(tbl_info, region->va); end = core_mmu_va2idx(tbl_info, region->va + region->size); pa = region->pa; while (idx < end) { core_mmu_set_entry(tbl_info, idx, pa, region->attr); idx++; pa += BIT64(tbl_info->shift); } } static void set_pg_region(struct core_mmu_table_info *dir_info, struct vm_region *region, struct pgt **pgt, struct core_mmu_table_info *pg_info) { struct tee_mmap_region r = { .va = region->va, .size = region->size, .attr = region->attr, }; vaddr_t end = r.va + r.size; uint32_t pgt_attr = (r.attr & TEE_MATTR_SECURE) | TEE_MATTR_TABLE; while (r.va < end) { if (!pg_info->table || r.va >= (pg_info->va_base + CORE_MMU_PGDIR_SIZE)) { /* * We're assigning a new translation table. */ unsigned int idx; /* Virtual addresses must grow */ assert(r.va > pg_info->va_base); idx = core_mmu_va2idx(dir_info, r.va); pg_info->va_base = core_mmu_idx2va(dir_info, idx); /* * Advance pgt to va_base, note that we may need to * skip multiple page tables if there are large * holes in the vm map. */ while ((*pgt)->vabase < pg_info->va_base) { *pgt = SLIST_NEXT(*pgt, link); /* We should have allocated enough */ assert(*pgt); } assert((*pgt)->vabase == pg_info->va_base); pg_info->table = (*pgt)->tbl; core_mmu_set_entry(dir_info, idx, virt_to_phys(pg_info->table), pgt_attr); } r.size = MIN(CORE_MMU_PGDIR_SIZE - (r.va - pg_info->va_base), end - r.va); if (!(*pgt)->populated && !mobj_is_paged(region->mobj)) { size_t granule = BIT(pg_info->shift); size_t offset = r.va - region->va + region->offset; r.size = MIN(r.size, mobj_get_phys_granule(region->mobj)); r.size = ROUNDUP(r.size, SMALL_PAGE_SIZE); if (mobj_get_pa(region->mobj, offset, granule, &r.pa) != TEE_SUCCESS) panic("Failed to get PA of unpaged mobj"); set_region(pg_info, &r); } r.va += r.size; } } static bool can_map_at_level(paddr_t paddr, vaddr_t vaddr, size_t size_left, paddr_t block_size, struct tee_mmap_region *mm __maybe_unused) { /* VA and PA are aligned to block size at current level */ if ((vaddr | paddr) & (block_size - 1)) return false; /* Remainder fits into block at current level */ if (size_left < block_size) return false; #ifdef CFG_WITH_PAGER /* * If pager is enabled, we need to map tee ram * regions with small pages only */ if (map_is_tee_ram(mm) && block_size != SMALL_PAGE_SIZE) return false; #endif return true; } void core_mmu_map_region(struct mmu_partition *prtn, struct tee_mmap_region *mm) { struct core_mmu_table_info tbl_info; unsigned int idx; vaddr_t vaddr = mm->va; paddr_t paddr = mm->pa; ssize_t size_left = mm->size; unsigned int level; bool table_found; uint32_t old_attr; assert(!((vaddr | paddr) & SMALL_PAGE_MASK)); while (size_left > 0) { level = CORE_MMU_BASE_TABLE_LEVEL; while (true) { paddr_t block_size = 0; assert(core_mmu_level_in_range(level)); table_found = core_mmu_find_table(prtn, vaddr, level, &tbl_info); if (!table_found) panic("can't find table for mapping"); block_size = BIT64(tbl_info.shift); idx = core_mmu_va2idx(&tbl_info, vaddr); if (!can_map_at_level(paddr, vaddr, size_left, block_size, mm)) { bool secure = mm->attr & TEE_MATTR_SECURE; /* * This part of the region can't be mapped at * this level. Need to go deeper. */ if (!core_mmu_entry_to_finer_grained(&tbl_info, idx, secure)) panic("Can't divide MMU entry"); level = tbl_info.next_level; continue; } /* We can map part of the region at current level */ core_mmu_get_entry(&tbl_info, idx, NULL, &old_attr); if (old_attr) panic("Page is already mapped"); core_mmu_set_entry(&tbl_info, idx, paddr, mm->attr); paddr += block_size; vaddr += block_size; size_left -= block_size; break; } } } TEE_Result core_mmu_map_pages(vaddr_t vstart, paddr_t *pages, size_t num_pages, enum teecore_memtypes memtype) { TEE_Result ret; struct core_mmu_table_info tbl_info; struct tee_mmap_region *mm; unsigned int idx; uint32_t old_attr; uint32_t exceptions; vaddr_t vaddr = vstart; size_t i; bool secure; assert(!(core_mmu_type_to_attr(memtype) & TEE_MATTR_PX)); secure = core_mmu_type_to_attr(memtype) & TEE_MATTR_SECURE; if (vaddr & SMALL_PAGE_MASK) return TEE_ERROR_BAD_PARAMETERS; exceptions = mmu_lock(); mm = find_map_by_va((void *)vaddr); if (!mm || !va_is_in_map(mm, vaddr + num_pages * SMALL_PAGE_SIZE - 1)) panic("VA does not belong to any known mm region"); if (!core_mmu_is_dynamic_vaspace(mm)) panic("Trying to map into static region"); for (i = 0; i < num_pages; i++) { if (pages[i] & SMALL_PAGE_MASK) { ret = TEE_ERROR_BAD_PARAMETERS; goto err; } while (true) { if (!core_mmu_find_table(NULL, vaddr, UINT_MAX, &tbl_info)) panic("Can't find pagetable for vaddr "); idx = core_mmu_va2idx(&tbl_info, vaddr); if (tbl_info.shift == SMALL_PAGE_SHIFT) break; /* This is supertable. Need to divide it. */ if (!core_mmu_entry_to_finer_grained(&tbl_info, idx, secure)) panic("Failed to spread pgdir on small tables"); } core_mmu_get_entry(&tbl_info, idx, NULL, &old_attr); if (old_attr) panic("Page is already mapped"); core_mmu_set_entry(&tbl_info, idx, pages[i], core_mmu_type_to_attr(memtype)); vaddr += SMALL_PAGE_SIZE; } /* * Make sure all the changes to translation tables are visible * before returning. TLB doesn't need to be invalidated as we are * guaranteed that there's no valid mapping in this range. */ core_mmu_table_write_barrier(); mmu_unlock(exceptions); return TEE_SUCCESS; err: mmu_unlock(exceptions); if (i) core_mmu_unmap_pages(vstart, i); return ret; } TEE_Result core_mmu_map_contiguous_pages(vaddr_t vstart, paddr_t pstart, size_t num_pages, enum teecore_memtypes memtype) { struct core_mmu_table_info tbl_info = { }; struct tee_mmap_region *mm = NULL; unsigned int idx = 0; uint32_t old_attr = 0; uint32_t exceptions = 0; vaddr_t vaddr = vstart; paddr_t paddr = pstart; size_t i = 0; bool secure = false; assert(!(core_mmu_type_to_attr(memtype) & TEE_MATTR_PX)); secure = core_mmu_type_to_attr(memtype) & TEE_MATTR_SECURE; if ((vaddr | paddr) & SMALL_PAGE_MASK) return TEE_ERROR_BAD_PARAMETERS; exceptions = mmu_lock(); mm = find_map_by_va((void *)vaddr); if (!mm || !va_is_in_map(mm, vaddr + num_pages * SMALL_PAGE_SIZE - 1)) panic("VA does not belong to any known mm region"); if (!core_mmu_is_dynamic_vaspace(mm)) panic("Trying to map into static region"); for (i = 0; i < num_pages; i++) { while (true) { if (!core_mmu_find_table(NULL, vaddr, UINT_MAX, &tbl_info)) panic("Can't find pagetable for vaddr "); idx = core_mmu_va2idx(&tbl_info, vaddr); if (tbl_info.shift == SMALL_PAGE_SHIFT) break; /* This is supertable. Need to divide it. */ if (!core_mmu_entry_to_finer_grained(&tbl_info, idx, secure)) panic("Failed to spread pgdir on small tables"); } core_mmu_get_entry(&tbl_info, idx, NULL, &old_attr); if (old_attr) panic("Page is already mapped"); core_mmu_set_entry(&tbl_info, idx, paddr, core_mmu_type_to_attr(memtype)); paddr += SMALL_PAGE_SIZE; vaddr += SMALL_PAGE_SIZE; } /* * Make sure all the changes to translation tables are visible * before returning. TLB doesn't need to be invalidated as we are * guaranteed that there's no valid mapping in this range. */ core_mmu_table_write_barrier(); mmu_unlock(exceptions); return TEE_SUCCESS; } void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages) { struct core_mmu_table_info tbl_info; struct tee_mmap_region *mm; size_t i; unsigned int idx; uint32_t exceptions; exceptions = mmu_lock(); mm = find_map_by_va((void *)vstart); if (!mm || !va_is_in_map(mm, vstart + num_pages * SMALL_PAGE_SIZE - 1)) panic("VA does not belong to any known mm region"); if (!core_mmu_is_dynamic_vaspace(mm)) panic("Trying to unmap static region"); for (i = 0; i < num_pages; i++, vstart += SMALL_PAGE_SIZE) { if (!core_mmu_find_table(NULL, vstart, UINT_MAX, &tbl_info)) panic("Can't find pagetable"); if (tbl_info.shift != SMALL_PAGE_SHIFT) panic("Invalid pagetable level"); idx = core_mmu_va2idx(&tbl_info, vstart); core_mmu_set_entry(&tbl_info, idx, 0, 0); } tlbi_all(); mmu_unlock(exceptions); } void core_mmu_populate_user_map(struct core_mmu_table_info *dir_info, struct user_mode_ctx *uctx) { struct core_mmu_table_info pg_info = { }; struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct pgt *pgt = NULL; struct pgt *p = NULL; struct vm_region *r = NULL; if (TAILQ_EMPTY(&uctx->vm_info.regions)) return; /* Nothing to map */ /* * Allocate all page tables in advance. */ pgt_get_all(uctx); pgt = SLIST_FIRST(pgt_cache); core_mmu_set_info_table(&pg_info, dir_info->next_level, 0, NULL); TAILQ_FOREACH(r, &uctx->vm_info.regions, link) set_pg_region(dir_info, r, &pgt, &pg_info); /* Record that the translation tables now are populated. */ SLIST_FOREACH(p, pgt_cache, link) { p->populated = true; if (p == pgt) break; } assert(p == pgt); } TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr, size_t len) { struct core_mmu_table_info tbl_info = { }; struct tee_mmap_region *res_map = NULL; struct tee_mmap_region *map = NULL; paddr_t pa = virt_to_phys(addr); size_t granule = 0; ptrdiff_t i = 0; paddr_t p = 0; size_t l = 0; map = find_map_by_type_and_pa(type, pa, len); if (!map) return TEE_ERROR_GENERIC; res_map = find_map_by_type(MEM_AREA_RES_VASPACE); if (!res_map) return TEE_ERROR_GENERIC; if (!core_mmu_find_table(NULL, res_map->va, UINT_MAX, &tbl_info)) return TEE_ERROR_GENERIC; granule = BIT(tbl_info.shift); if (map < static_memory_map || map >= static_memory_map + ARRAY_SIZE(static_memory_map)) return TEE_ERROR_GENERIC; i = map - static_memory_map; /* Check that we have a full match */ p = ROUNDDOWN(pa, granule); l = ROUNDUP(len + pa - p, granule); if (map->pa != p || map->size != l) return TEE_ERROR_GENERIC; clear_region(&tbl_info, map); tlbi_all(); /* If possible remove the va range from res_map */ if (res_map->va - map->size == map->va) { res_map->va -= map->size; res_map->size += map->size; } /* Remove the entry. */ memmove(map, map + 1, (ARRAY_SIZE(static_memory_map) - i - 1) * sizeof(*map)); /* Clear the last new entry in case it was used */ memset(static_memory_map + ARRAY_SIZE(static_memory_map) - 1, 0, sizeof(*map)); return TEE_SUCCESS; } struct tee_mmap_region * core_mmu_find_mapping_exclusive(enum teecore_memtypes type, size_t len) { struct tee_mmap_region *map = NULL; struct tee_mmap_region *map_found = NULL; if (!len) return NULL; for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) { if (map->type != type) continue; if (map_found) return NULL; map_found = map; } if (!map_found || map_found->size < len) return NULL; return map_found; } void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len) { struct core_mmu_table_info tbl_info; struct tee_mmap_region *map; size_t n; size_t granule; paddr_t p; size_t l; if (!len) return NULL; if (!core_mmu_check_end_pa(addr, len)) return NULL; /* Check if the memory is already mapped */ map = find_map_by_type_and_pa(type, addr, len); if (map && pbuf_inside_map_area(addr, len, map)) return (void *)(vaddr_t)(map->va + addr - map->pa); /* Find the reserved va space used for late mappings */ map = find_map_by_type(MEM_AREA_RES_VASPACE); if (!map) return NULL; if (!core_mmu_find_table(NULL, map->va, UINT_MAX, &tbl_info)) return NULL; granule = BIT64(tbl_info.shift); p = ROUNDDOWN(addr, granule); l = ROUNDUP(len + addr - p, granule); /* Ban overflowing virtual addresses */ if (map->size < l) return NULL; /* * Something is wrong, we can't fit the va range into the selected * table. The reserved va range is possibly missaligned with * granule. */ if (core_mmu_va2idx(&tbl_info, map->va + len) >= tbl_info.num_entries) return NULL; /* Find end of the memory map */ n = 0; while (!core_mmap_is_end_of_table(static_memory_map + n)) n++; if (n < (ARRAY_SIZE(static_memory_map) - 1)) { /* There's room for another entry */ static_memory_map[n].va = map->va; static_memory_map[n].size = l; static_memory_map[n + 1].type = MEM_AREA_END; map->va += l; map->size -= l; map = static_memory_map + n; } else { /* * There isn't room for another entry, steal the reserved * entry as it's not useful for anything else any longer. */ map->size = l; } map->type = type; map->region_size = granule; map->attr = core_mmu_type_to_attr(type); map->pa = p; set_region(&tbl_info, map); /* Make sure the new entry is visible before continuing. */ core_mmu_table_write_barrier(); return (void *)(vaddr_t)(map->va + addr - map->pa); } #ifdef CFG_WITH_PAGER static vaddr_t get_linear_map_end_va(void) { /* this is synced with the generic linker file kern.ld.S */ return (vaddr_t)__heap2_end; } static paddr_t get_linear_map_end_pa(void) { return get_linear_map_end_va() - boot_mmu_config.map_offset; } #endif #if defined(CFG_TEE_CORE_DEBUG) static void check_pa_matches_va(void *va, paddr_t pa) { TEE_Result res = TEE_ERROR_GENERIC; vaddr_t v = (vaddr_t)va; paddr_t p = 0; struct core_mmu_table_info ti __maybe_unused = { }; if (core_mmu_user_va_range_is_defined()) { vaddr_t user_va_base = 0; size_t user_va_size = 0; core_mmu_get_user_va_range(&user_va_base, &user_va_size); if (v >= user_va_base && v <= (user_va_base - 1 + user_va_size)) { if (!core_mmu_user_mapping_is_active()) { if (pa) panic("issue in linear address space"); return; } res = vm_va2pa(to_user_mode_ctx(thread_get_tsd()->ctx), va, &p); if (res == TEE_ERROR_NOT_SUPPORTED) return; if (res == TEE_SUCCESS && pa != p) panic("bad pa"); if (res != TEE_SUCCESS && pa) panic("false pa"); return; } } #ifdef CFG_WITH_PAGER if (is_unpaged(va)) { if (v - boot_mmu_config.map_offset != pa) panic("issue in linear address space"); return; } if (tee_pager_get_table_info(v, &ti)) { uint32_t a; /* * Lookups in the page table managed by the pager is * dangerous for addresses in the paged area as those pages * changes all the time. But some ranges are safe, * rw-locked areas when the page is populated for instance. */ core_mmu_get_entry(&ti, core_mmu_va2idx(&ti, v), &p, &a); if (a & TEE_MATTR_VALID_BLOCK) { paddr_t mask = BIT64(ti.shift) - 1; p |= v & mask; if (pa != p) panic(); } else { if (pa) panic(); } return; } #endif if (!core_va2pa_helper(va, &p)) { /* Verfiy only the static mapping (case non null phys addr) */ if (p && pa != p) { DMSG("va %p maps 0x%" PRIxPA ", expect 0x%" PRIxPA, va, p, pa); panic(); } } else { if (pa) { DMSG("va %p unmapped, expect 0x%" PRIxPA, va, pa); panic(); } } } #else static void check_pa_matches_va(void *va __unused, paddr_t pa __unused) { } #endif paddr_t virt_to_phys(void *va) { paddr_t pa = 0; if (!arch_va2pa_helper(va, &pa)) pa = 0; check_pa_matches_va(memtag_strip_tag(va), pa); return pa; } #if defined(CFG_TEE_CORE_DEBUG) static void check_va_matches_pa(paddr_t pa, void *va) { paddr_t p = 0; if (!va) return; p = virt_to_phys(va); if (p != pa) { DMSG("va %p maps 0x%" PRIxPA " expect 0x%" PRIxPA, va, p, pa); panic(); } } #else static void check_va_matches_pa(paddr_t pa __unused, void *va __unused) { } #endif static void *phys_to_virt_ts_vaspace(paddr_t pa, size_t len) { if (!core_mmu_user_mapping_is_active()) return NULL; return vm_pa2va(to_user_mode_ctx(thread_get_tsd()->ctx), pa, len); } #ifdef CFG_WITH_PAGER static void *phys_to_virt_tee_ram(paddr_t pa, size_t len) { paddr_t end_pa = 0; if (SUB_OVERFLOW(len, 1, &end_pa) || ADD_OVERFLOW(pa, end_pa, &end_pa)) return NULL; if (pa >= TEE_LOAD_ADDR && pa < get_linear_map_end_pa()) { if (end_pa > get_linear_map_end_pa()) return NULL; return (void *)(vaddr_t)(pa + boot_mmu_config.map_offset); } return tee_pager_phys_to_virt(pa, len); } #else static void *phys_to_virt_tee_ram(paddr_t pa, size_t len) { struct tee_mmap_region *mmap = NULL; mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM, pa, len); if (!mmap) mmap = find_map_by_type_and_pa(MEM_AREA_NEX_RAM_RW, pa, len); if (!mmap) mmap = find_map_by_type_and_pa(MEM_AREA_NEX_RAM_RO, pa, len); if (!mmap) mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM_RW, pa, len); if (!mmap) mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM_RO, pa, len); if (!mmap) mmap = find_map_by_type_and_pa(MEM_AREA_TEE_RAM_RX, pa, len); /* * Note that MEM_AREA_INIT_RAM_RO and MEM_AREA_INIT_RAM_RX are only * used with pager and not needed here. */ return map_pa2va(mmap, pa, len); } #endif void *phys_to_virt(paddr_t pa, enum teecore_memtypes m, size_t len) { void *va = NULL; switch (m) { case MEM_AREA_TS_VASPACE: va = phys_to_virt_ts_vaspace(pa, len); break; case MEM_AREA_TEE_RAM: case MEM_AREA_TEE_RAM_RX: case MEM_AREA_TEE_RAM_RO: case MEM_AREA_TEE_RAM_RW: case MEM_AREA_NEX_RAM_RO: case MEM_AREA_NEX_RAM_RW: va = phys_to_virt_tee_ram(pa, len); break; case MEM_AREA_SHM_VASPACE: /* Find VA from PA in dynamic SHM is not yet supported */ va = NULL; break; default: va = map_pa2va(find_map_by_type_and_pa(m, pa, len), pa, len); } if (m != MEM_AREA_SEC_RAM_OVERALL) check_va_matches_pa(pa, va); return va; } void *phys_to_virt_io(paddr_t pa, size_t len) { struct tee_mmap_region *map = NULL; void *va = NULL; map = find_map_by_type_and_pa(MEM_AREA_IO_SEC, pa, len); if (!map) map = find_map_by_type_and_pa(MEM_AREA_IO_NSEC, pa, len); if (!map) return NULL; va = map_pa2va(map, pa, len); check_va_matches_pa(pa, va); return va; } vaddr_t core_mmu_get_va(paddr_t pa, enum teecore_memtypes type, size_t len) { if (cpu_mmu_enabled()) return (vaddr_t)phys_to_virt(pa, type, len); return (vaddr_t)pa; } #ifdef CFG_WITH_PAGER bool is_unpaged(const void *va) { vaddr_t v = (vaddr_t)va; return v >= VCORE_START_VA && v < get_linear_map_end_va(); } #endif #ifdef CFG_NS_VIRTUALIZATION bool is_nexus(const void *va) { vaddr_t v = (vaddr_t)va; return v >= VCORE_START_VA && v < VCORE_NEX_RW_PA + VCORE_NEX_RW_SZ; } #endif void core_mmu_init_virtualization(void) { paddr_t b1 = 0; paddr_size_t s1 = 0; static_assert(ARRAY_SIZE(secure_only) <= 2); if (ARRAY_SIZE(secure_only) == 2) { b1 = secure_only[1].paddr; s1 = secure_only[1].size; } virt_init_memory(static_memory_map, secure_only[0].paddr, secure_only[0].size, b1, s1); } vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len) { assert(p->pa); if (cpu_mmu_enabled()) { if (!p->va) p->va = (vaddr_t)phys_to_virt_io(p->pa, len); assert(p->va); return p->va; } return p->pa; } vaddr_t io_pa_or_va_secure(struct io_pa_va *p, size_t len) { assert(p->pa); if (cpu_mmu_enabled()) { if (!p->va) p->va = (vaddr_t)phys_to_virt(p->pa, MEM_AREA_IO_SEC, len); assert(p->va); return p->va; } return p->pa; } vaddr_t io_pa_or_va_nsec(struct io_pa_va *p, size_t len) { assert(p->pa); if (cpu_mmu_enabled()) { if (!p->va) p->va = (vaddr_t)phys_to_virt(p->pa, MEM_AREA_IO_NSEC, len); assert(p->va); return p->va; } return p->pa; } #ifdef CFG_CORE_RESERVED_SHM static TEE_Result teecore_init_pub_ram(void) { vaddr_t s = 0; vaddr_t e = 0; /* get virtual addr/size of NSec shared mem allocated from teecore */ core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &s, &e); if (s >= e || s & SMALL_PAGE_MASK || e & SMALL_PAGE_MASK) panic("invalid PUB RAM"); /* extra check: we could rely on core_mmu_get_mem_by_type() */ if (!tee_vbuf_is_non_sec(s, e - s)) panic("PUB RAM is not non-secure"); #ifdef CFG_PL310 /* Allocate statically the l2cc mutex */ tee_l2cc_store_mutex_boot_pa(virt_to_phys((void *)s)); s += sizeof(uint32_t); /* size of a pl310 mutex */ s = ROUNDUP(s, SMALL_PAGE_SIZE); /* keep required alignment */ #endif default_nsec_shm_paddr = virt_to_phys((void *)s); default_nsec_shm_size = e - s; return TEE_SUCCESS; } early_init(teecore_init_pub_ram); #endif /*CFG_CORE_RESERVED_SHM*/ void core_mmu_init_ta_ram(void) { vaddr_t s = 0; vaddr_t e = 0; paddr_t ps = 0; size_t size = 0; /* * Get virtual addr/size of RAM where TA are loaded/executedNSec * shared mem allocated from teecore. */ if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) virt_get_ta_ram(&s, &e); else core_mmu_get_mem_by_type(MEM_AREA_TA_RAM, &s, &e); ps = virt_to_phys((void *)s); size = e - s; if (!ps || (ps & CORE_MMU_USER_CODE_MASK) || !size || (size & CORE_MMU_USER_CODE_MASK)) panic("invalid TA RAM"); /* extra check: we could rely on core_mmu_get_mem_by_type() */ if (!tee_pbuf_is_sec(ps, size)) panic("TA RAM is not secure"); if (!tee_mm_is_empty(&tee_mm_sec_ddr)) panic("TA RAM pool is not empty"); /* remove previous config and init TA ddr memory pool */ tee_mm_final(&tee_mm_sec_ddr); tee_mm_init(&tee_mm_sec_ddr, ps, size, CORE_MMU_USER_CODE_SHIFT, TEE_MM_POOL_NO_FLAGS); } optee_os-4.3.0/core/mm/file.c000066400000000000000000000113231464416617300157730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include struct file_slice_elem { struct file_slice slice; SLIST_ENTRY(file_slice_elem) link; }; /* * struct file - file resources * @tag: Tag or hash uniquely identifying a file * @taglen: Byte length of @tag * @refc: Reference counter * @link: Linked list element * @num_slices: Number of elements in the @slices array below * @slices: Array of file slices holding the fobjs of this file * * A file is constructed of slices which may be shared in different * mappings/contexts. There may be holes in the file for ranges of the file * that can't be shared. */ struct file { uint8_t tag[FILE_TAG_SIZE]; unsigned int taglen; struct refcount refc; TAILQ_ENTRY(file) link; struct mutex mu; SLIST_HEAD(, file_slice_elem) slice_head; }; static struct mutex file_mu = MUTEX_INITIALIZER; static TAILQ_HEAD(, file) file_head = TAILQ_HEAD_INITIALIZER(file_head); static int file_tag_cmp(const struct file *f, const uint8_t *tag, unsigned int taglen) { if (f->taglen != taglen) return -1; return memcmp(tag, f->tag, taglen); } static struct file *file_find_tag_unlocked(const uint8_t *tag, unsigned int taglen) { struct file *f = NULL; TAILQ_FOREACH(f, &file_head, link) if (!file_tag_cmp(f, tag, taglen)) return f; return NULL; } static void file_free(struct file *f) { mutex_destroy(&f->mu); while (!SLIST_EMPTY(&f->slice_head)) { struct file_slice_elem *fse = SLIST_FIRST(&f->slice_head); SLIST_REMOVE_HEAD(&f->slice_head, link); fobj_put(fse->slice.fobj); free(fse); } free(f); } TEE_Result file_add_slice(struct file *f, struct fobj *fobj, unsigned int page_offset) { struct file_slice_elem *fse = NULL; unsigned int s = 0; /* Check for conflicts */ if (file_find_slice(f, page_offset)) return TEE_ERROR_BAD_PARAMETERS; fse = calloc(1, sizeof(*fse)); if (!fse) return TEE_ERROR_OUT_OF_MEMORY; fse->slice.fobj = fobj_get(fobj); if (!fse->slice.fobj || ADD_OVERFLOW(page_offset, fse->slice.fobj->num_pages, &s)) { fobj_put(fse->slice.fobj); free(fse); return TEE_ERROR_BAD_PARAMETERS; } fse->slice.page_offset = page_offset; SLIST_INSERT_HEAD(&f->slice_head, fse, link); return TEE_SUCCESS; } struct file *file_get(struct file *f) { if (f && !refcount_inc(&f->refc)) panic(); return f; } struct file *file_get_by_tag(const uint8_t *tag, unsigned int taglen) { struct file *f = NULL; if (taglen > sizeof(f->tag)) return NULL; mutex_lock(&file_mu); /* * If file is found and reference counter can be increased, we're done. * If file can't be found, it doesn't exist so it has to be added. * If it's found but reference counter is 0, the situation is * a bit complicated: * - file_put() is about to free the file as soon as it can obtain the * mutex. * - Unless there's a mismatch between file_get() and file_put() only * one thread calling file_put() is about to free the file. * * There's a window of opportunity where file_put() is called * (without a mutex being held, which is quite OK) while we're * holding the mutex here and are searching for the file and it's * found, but just after file_put() has decreased the reference * counter. * * To keep it simple we're adding a new file at the head (so new * searches finds this file instead of the old being freed) instead * of complicating file_put() by trying to rescue the file and * possibly hiding a case of mismatching file_put() and file_get(). */ f = file_find_tag_unlocked(tag, taglen); if (f && refcount_inc(&f->refc)) goto out; f = calloc(1, sizeof(*f)); if (!f) goto out; memcpy(f->tag, tag, taglen); f->taglen = taglen; refcount_set(&f->refc, 1); mutex_init(&f->mu); SLIST_INIT(&f->slice_head); TAILQ_INSERT_HEAD(&file_head, f, link); out: mutex_unlock(&file_mu); return f; } void file_put(struct file *f) { if (f && refcount_dec(&f->refc)) { mutex_lock(&file_mu); TAILQ_REMOVE(&file_head, f, link); mutex_unlock(&file_mu); file_free(f); } } struct file_slice *file_find_slice(struct file *f, unsigned int page_offset) { struct file_slice_elem *fse = NULL; assert(f->mu.state); SLIST_FOREACH(fse, &f->slice_head, link) { struct file_slice *fs = &fse->slice; if (page_offset >= fs->page_offset && page_offset < fs->page_offset + fs->fobj->num_pages) return fs; } return NULL; } void file_lock(struct file *f) { mutex_lock(&f->mu); } bool file_trylock(struct file *f) { return mutex_trylock(&f->mu); } void file_unlock(struct file *f) { mutex_unlock(&f->mu); } optee_os-4.3.0/core/mm/fobj.c000066400000000000000000000476331464416617300160110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_WITH_PAGER #define RWP_AE_KEY_BITS 256 struct rwp_aes_gcm_iv { uint32_t iv[3]; }; #define RWP_AES_GCM_TAG_LEN 16 struct rwp_state { uint64_t iv; uint8_t tag[RWP_AES_GCM_TAG_LEN]; }; /* * Note that this struct is padded to a size which is a power of 2, this * guarantees that this state will not span two pages. This avoids a corner * case in the pager when making the state available. */ struct rwp_state_padded { struct rwp_state state; uint64_t pad; }; struct fobj_rwp_unpaged_iv { uint8_t *store; struct rwp_state *state; struct fobj fobj; }; struct fobj_rwp_paged_iv { size_t idx; struct fobj fobj; }; const struct fobj_ops ops_rwp_paged_iv; const struct fobj_ops ops_rwp_unpaged_iv; static struct internal_aes_gcm_key rwp_ae_key; static struct rwp_state_padded *rwp_state_base; static uint8_t *rwp_store_base; static void fobj_init(struct fobj *fobj, const struct fobj_ops *ops, unsigned int num_pages) { fobj->ops = ops; fobj->num_pages = num_pages; refcount_set(&fobj->refc, 1); TAILQ_INIT(&fobj->regions); } static void fobj_uninit(struct fobj *fobj) { assert(!refcount_val(&fobj->refc)); assert(TAILQ_EMPTY(&fobj->regions)); tee_pager_invalidate_fobj(fobj); } static TEE_Result rwp_load_page(void *va, struct rwp_state *state, const uint8_t *src) { struct rwp_aes_gcm_iv iv = { .iv = { (vaddr_t)state, state->iv >> 32, state->iv } }; if (!state->iv) { /* * IV still zero which means that this is previously unused * page. */ memset(va, 0, SMALL_PAGE_SIZE); return TEE_SUCCESS; } return internal_aes_gcm_dec(&rwp_ae_key, &iv, sizeof(iv), NULL, 0, src, SMALL_PAGE_SIZE, va, state->tag, sizeof(state->tag)); } static TEE_Result rwp_save_page(const void *va, struct rwp_state *state, uint8_t *dst) { size_t tag_len = sizeof(state->tag); struct rwp_aes_gcm_iv iv = { }; assert(state->iv + 1 > state->iv); state->iv++; /* * IV is constructed as recommended in section "8.2.1 Deterministic * Construction" of "Recommendation for Block Cipher Modes of * Operation: Galois/Counter Mode (GCM) and GMAC", * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf */ iv.iv[0] = (vaddr_t)state; iv.iv[1] = state->iv >> 32; iv.iv[2] = state->iv; return internal_aes_gcm_enc(&rwp_ae_key, &iv, sizeof(iv), NULL, 0, va, SMALL_PAGE_SIZE, dst, state->tag, &tag_len); } static struct rwp_state_padded *idx_to_state_padded(size_t idx) { assert(rwp_state_base); return rwp_state_base + idx; } static uint8_t *idx_to_store(size_t idx) { assert(rwp_store_base); return rwp_store_base + idx * SMALL_PAGE_SIZE; } static struct fobj *rwp_paged_iv_alloc(unsigned int num_pages) { struct fobj_rwp_paged_iv *rwp = NULL; tee_mm_entry_t *mm = NULL; size_t size = 0; COMPILE_TIME_ASSERT(IS_POWER_OF_TWO(sizeof(struct rwp_state_padded))); rwp = calloc(1, sizeof(*rwp)); if (!rwp) return NULL; if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size)) goto err; mm = tee_mm_alloc(&tee_mm_sec_ddr, size); if (!mm) goto err; rwp->idx = (tee_mm_get_smem(mm) - tee_mm_sec_ddr.lo) / SMALL_PAGE_SIZE; memset(idx_to_state_padded(rwp->idx), 0, num_pages * sizeof(struct rwp_state_padded)); fobj_init(&rwp->fobj, &ops_rwp_paged_iv, num_pages); return &rwp->fobj; err: tee_mm_free(mm); free(rwp); return NULL; } static struct fobj_rwp_paged_iv *to_rwp_paged_iv(struct fobj *fobj) { assert(fobj->ops == &ops_rwp_paged_iv); return container_of(fobj, struct fobj_rwp_paged_iv, fobj); } static TEE_Result rwp_paged_iv_load_page(struct fobj *fobj, unsigned int page_idx, void *va) { struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); uint8_t *src = idx_to_store(rwp->idx) + page_idx * SMALL_PAGE_SIZE; struct rwp_state_padded *st = idx_to_state_padded(rwp->idx + page_idx); assert(refcount_val(&fobj->refc)); assert(page_idx < fobj->num_pages); return rwp_load_page(va, &st->state, src); } DECLARE_KEEP_PAGER(rwp_paged_iv_load_page); static TEE_Result rwp_paged_iv_save_page(struct fobj *fobj, unsigned int page_idx, const void *va) { struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); uint8_t *dst = idx_to_store(rwp->idx) + page_idx * SMALL_PAGE_SIZE; struct rwp_state_padded *st = idx_to_state_padded(rwp->idx + page_idx); assert(page_idx < fobj->num_pages); if (!refcount_val(&fobj->refc)) { /* * This fobj is being teared down, it just hasn't had the time * to call tee_pager_invalidate_fobj() yet. */ assert(TAILQ_EMPTY(&fobj->regions)); return TEE_SUCCESS; } return rwp_save_page(va, &st->state, dst); } DECLARE_KEEP_PAGER(rwp_paged_iv_save_page); static void rwp_paged_iv_free(struct fobj *fobj) { struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); paddr_t pa = rwp->idx * SMALL_PAGE_SIZE + tee_mm_sec_ddr.lo; tee_mm_entry_t *mm = tee_mm_find(&tee_mm_sec_ddr, pa); assert(mm); fobj_uninit(fobj); tee_mm_free(mm); free(rwp); } static vaddr_t rwp_paged_iv_get_iv_vaddr(struct fobj *fobj, unsigned int page_idx) { struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj); struct rwp_state_padded *st = idx_to_state_padded(rwp->idx + page_idx); assert(page_idx < fobj->num_pages); return (vaddr_t)&st->state & ~SMALL_PAGE_MASK; } DECLARE_KEEP_PAGER(rwp_paged_iv_get_iv_vaddr); /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct fobj_ops ops_rwp_paged_iv __weak __relrodata_unpaged("ops_rwp_paged_iv") = { .free = rwp_paged_iv_free, .load_page = rwp_paged_iv_load_page, .save_page = rwp_paged_iv_save_page, .get_iv_vaddr = rwp_paged_iv_get_iv_vaddr, }; static struct fobj *rwp_unpaged_iv_alloc(unsigned int num_pages) { struct fobj_rwp_unpaged_iv *rwp = NULL; tee_mm_entry_t *mm = NULL; size_t size = 0; rwp = calloc(1, sizeof(*rwp)); if (!rwp) return NULL; rwp->state = calloc(num_pages, sizeof(*rwp->state)); if (!rwp->state) goto err_free_rwp; if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size)) goto err_free_state; mm = tee_mm_alloc(&tee_mm_sec_ddr, size); if (!mm) goto err_free_state; rwp->store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM, size); assert(rwp->store); fobj_init(&rwp->fobj, &ops_rwp_unpaged_iv, num_pages); return &rwp->fobj; err_free_state: free(rwp->state); err_free_rwp: free(rwp); return NULL; } static struct fobj_rwp_unpaged_iv *to_rwp_unpaged_iv(struct fobj *fobj) { assert(fobj->ops == &ops_rwp_unpaged_iv); return container_of(fobj, struct fobj_rwp_unpaged_iv, fobj); } static TEE_Result rwp_unpaged_iv_load_page(struct fobj *fobj, unsigned int page_idx, void *va) { struct fobj_rwp_unpaged_iv *rwp = to_rwp_unpaged_iv(fobj); uint8_t *src = rwp->store + page_idx * SMALL_PAGE_SIZE; assert(refcount_val(&fobj->refc)); assert(page_idx < fobj->num_pages); return rwp_load_page(va, rwp->state + page_idx, src); } DECLARE_KEEP_PAGER(rwp_unpaged_iv_load_page); static TEE_Result rwp_unpaged_iv_save_page(struct fobj *fobj, unsigned int page_idx, const void *va) { struct fobj_rwp_unpaged_iv *rwp = to_rwp_unpaged_iv(fobj); uint8_t *dst = rwp->store + page_idx * SMALL_PAGE_SIZE; assert(page_idx < fobj->num_pages); if (!refcount_val(&fobj->refc)) { /* * This fobj is being teared down, it just hasn't had the time * to call tee_pager_invalidate_fobj() yet. */ assert(TAILQ_EMPTY(&fobj->regions)); return TEE_SUCCESS; } return rwp_save_page(va, rwp->state + page_idx, dst); } DECLARE_KEEP_PAGER(rwp_unpaged_iv_save_page); static void rwp_unpaged_iv_free(struct fobj *fobj) { struct fobj_rwp_unpaged_iv *rwp = NULL; tee_mm_entry_t *mm = NULL; if (IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV)) panic(); rwp = to_rwp_unpaged_iv(fobj); mm = tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rwp->store)); assert(mm); fobj_uninit(fobj); tee_mm_free(mm); free(rwp->state); free(rwp); } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct fobj_ops ops_rwp_unpaged_iv __weak __relrodata_unpaged("ops_rwp_unpaged_iv") = { .free = rwp_unpaged_iv_free, .load_page = rwp_unpaged_iv_load_page, .save_page = rwp_unpaged_iv_save_page, }; static TEE_Result rwp_init(void) { uint8_t key[RWP_AE_KEY_BITS / 8] = { 0 }; struct fobj *fobj = NULL; size_t num_pool_pages = 0; size_t num_fobj_pages = 0; if (crypto_rng_read(key, sizeof(key)) != TEE_SUCCESS) panic("failed to generate random"); if (crypto_aes_expand_enc_key(key, sizeof(key), rwp_ae_key.data, sizeof(rwp_ae_key.data), &rwp_ae_key.rounds)) panic("failed to expand key"); if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV)) return TEE_SUCCESS; assert(tee_mm_sec_ddr.size && !(tee_mm_sec_ddr.size & SMALL_PAGE_SIZE)); num_pool_pages = tee_mm_sec_ddr.size / SMALL_PAGE_SIZE; num_fobj_pages = ROUNDUP(num_pool_pages * sizeof(*rwp_state_base), SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE; /* * Each page in the pool needs a struct rwp_state. * * This isn't entirely true, the pages not used by * fobj_rw_paged_alloc() don't need any. A future optimization * may try to avoid allocating for such pages. */ fobj = rwp_unpaged_iv_alloc(num_fobj_pages); if (!fobj) panic(); rwp_state_base = (void *)tee_pager_init_iv_region(fobj); assert(rwp_state_base); rwp_store_base = phys_to_virt(tee_mm_sec_ddr.lo, MEM_AREA_TA_RAM, tee_mm_sec_ddr.size); assert(rwp_store_base); return TEE_SUCCESS; } driver_init_late(rwp_init); struct fobj *fobj_rw_paged_alloc(unsigned int num_pages) { assert(num_pages); if (IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV)) return rwp_paged_iv_alloc(num_pages); else return rwp_unpaged_iv_alloc(num_pages); } struct fobj_rop { uint8_t *hashes; uint8_t *store; struct fobj fobj; }; const struct fobj_ops ops_ro_paged; static void rop_init(struct fobj_rop *rop, const struct fobj_ops *ops, unsigned int num_pages, void *hashes, void *store) { rop->hashes = hashes; rop->store = store; fobj_init(&rop->fobj, ops, num_pages); } struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes, void *store) { struct fobj_rop *rop = NULL; assert(num_pages && hashes && store); rop = calloc(1, sizeof(*rop)); if (!rop) return NULL; rop_init(rop, &ops_ro_paged, num_pages, hashes, store); return &rop->fobj; } static struct fobj_rop *to_rop(struct fobj *fobj) { assert(fobj->ops == &ops_ro_paged); return container_of(fobj, struct fobj_rop, fobj); } static void rop_uninit(struct fobj_rop *rop) { fobj_uninit(&rop->fobj); tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rop->store))); free(rop->hashes); } static void rop_free(struct fobj *fobj) { struct fobj_rop *rop = to_rop(fobj); rop_uninit(rop); free(rop); } static TEE_Result rop_load_page_helper(struct fobj_rop *rop, unsigned int page_idx, void *va) { const uint8_t *hash = rop->hashes + page_idx * TEE_SHA256_HASH_SIZE; const uint8_t *src = rop->store + page_idx * SMALL_PAGE_SIZE; assert(refcount_val(&rop->fobj.refc)); assert(page_idx < rop->fobj.num_pages); memcpy(va, src, SMALL_PAGE_SIZE); return hash_sha256_check(hash, va, SMALL_PAGE_SIZE); } static TEE_Result rop_load_page(struct fobj *fobj, unsigned int page_idx, void *va) { return rop_load_page_helper(to_rop(fobj), page_idx, va); } DECLARE_KEEP_PAGER(rop_load_page); static TEE_Result rop_save_page(struct fobj *fobj __unused, unsigned int page_idx __unused, const void *va __unused) { return TEE_ERROR_GENERIC; } DECLARE_KEEP_PAGER(rop_save_page); /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct fobj_ops ops_ro_paged __weak __relrodata_unpaged("ops_ro_paged") = { .free = rop_free, .load_page = rop_load_page, .save_page = rop_save_page, }; #ifdef CFG_CORE_ASLR /* * When using relocated pages the relocation information must be applied * before the pages can be used. With read-only paging the content is only * integrity protected so relocation cannot be applied on pages in the less * secure "store" or the load_address selected by ASLR could be given away. * This means that each time a page has been loaded and verified it has to * have its relocation information applied before it can be used. * * Only the relative relocations are supported, this allows a rather compact * represenation of the needed relocation information in this struct. * r_offset is replaced with the offset into the page that need to be updated, * this number can never be larger than SMALL_PAGE_SIZE so a uint16_t can be * used to represent it. * * All relocations are converted and stored in @relocs. @page_reloc_idx is * an array of length @rop.fobj.num_pages with an entry for each page. If * @page_reloc_idx[page_idx] isn't UINT16_MAX it's an index into @relocs. */ struct fobj_ro_reloc_paged { uint16_t *page_reloc_idx; uint16_t *relocs; unsigned int num_relocs; struct fobj_rop rop; }; const struct fobj_ops ops_ro_reloc_paged; static unsigned int get_num_rels(unsigned int num_pages, unsigned int reloc_offs, const uint32_t *reloc, unsigned int num_relocs) { const unsigned int align_mask __maybe_unused = sizeof(long) - 1; unsigned int nrels = 0; unsigned int n = 0; vaddr_t offs = 0; /* * Count the number of relocations which are needed for these * pages. Also check that the data is well formed, only expected * relocations and sorted in order of address which it applies to. */ for (; n < num_relocs; n++) { assert(IS_ALIGNED_WITH_TYPE(reloc[n], unsigned long)); assert(offs < reloc[n]); /* check that it's sorted */ offs = reloc[n]; if (offs >= reloc_offs && offs <= reloc_offs + num_pages * SMALL_PAGE_SIZE) nrels++; } return nrels; } static void init_rels(struct fobj_ro_reloc_paged *rrp, unsigned int reloc_offs, const uint32_t *reloc, unsigned int num_relocs) { unsigned int npg = rrp->rop.fobj.num_pages; unsigned int pg_idx = 0; unsigned int reln = 0; unsigned int n = 0; uint32_t r = 0; for (n = 0; n < npg; n++) rrp->page_reloc_idx[n] = UINT16_MAX; for (n = 0; n < num_relocs ; n++) { if (reloc[n] < reloc_offs) continue; /* r is the offset from beginning of this fobj */ r = reloc[n] - reloc_offs; pg_idx = r / SMALL_PAGE_SIZE; if (pg_idx >= npg) break; if (rrp->page_reloc_idx[pg_idx] == UINT16_MAX) rrp->page_reloc_idx[pg_idx] = reln; rrp->relocs[reln] = r - pg_idx * SMALL_PAGE_SIZE; reln++; } assert(reln == rrp->num_relocs); } struct fobj *fobj_ro_reloc_paged_alloc(unsigned int num_pages, void *hashes, unsigned int reloc_offs, const void *reloc, unsigned int reloc_len, void *store) { struct fobj_ro_reloc_paged *rrp = NULL; const unsigned int num_relocs = reloc_len / sizeof(uint32_t); unsigned int nrels = 0; assert(IS_ALIGNED_WITH_TYPE(reloc, uint32_t)); assert(IS_ALIGNED_WITH_TYPE(reloc_len, uint32_t)); assert(num_pages && hashes && store); if (!reloc_len) { assert(!reloc); return fobj_ro_paged_alloc(num_pages, hashes, store); } assert(reloc); nrels = get_num_rels(num_pages, reloc_offs, reloc, num_relocs); if (!nrels) return fobj_ro_paged_alloc(num_pages, hashes, store); rrp = calloc(1, sizeof(*rrp) + num_pages * sizeof(uint16_t) + nrels * sizeof(uint16_t)); if (!rrp) return NULL; rop_init(&rrp->rop, &ops_ro_reloc_paged, num_pages, hashes, store); rrp->page_reloc_idx = (uint16_t *)(rrp + 1); rrp->relocs = rrp->page_reloc_idx + num_pages; rrp->num_relocs = nrels; init_rels(rrp, reloc_offs, reloc, num_relocs); return &rrp->rop.fobj; } static struct fobj_ro_reloc_paged *to_rrp(struct fobj *fobj) { assert(fobj->ops == &ops_ro_reloc_paged); return container_of(fobj, struct fobj_ro_reloc_paged, rop.fobj); } static void rrp_free(struct fobj *fobj) { struct fobj_ro_reloc_paged *rrp = to_rrp(fobj); rop_uninit(&rrp->rop); free(rrp); } static TEE_Result rrp_load_page(struct fobj *fobj, unsigned int page_idx, void *va) { struct fobj_ro_reloc_paged *rrp = to_rrp(fobj); unsigned int end_rel = rrp->num_relocs; TEE_Result res = TEE_SUCCESS; unsigned long *where = NULL; unsigned int n = 0; res = rop_load_page_helper(&rrp->rop, page_idx, va); if (res) return res; /* Find the reloc index of the next page to tell when we're done */ for (n = page_idx + 1; n < fobj->num_pages; n++) { if (rrp->page_reloc_idx[n] != UINT16_MAX) { end_rel = rrp->page_reloc_idx[n]; break; } } for (n = rrp->page_reloc_idx[page_idx]; n < end_rel; n++) { where = (void *)((vaddr_t)va + rrp->relocs[n]); *where += boot_mmu_config.map_offset; } return TEE_SUCCESS; } DECLARE_KEEP_PAGER(rrp_load_page); /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct fobj_ops ops_ro_reloc_paged __weak __relrodata_unpaged("ops_ro_reloc_paged") = { .free = rrp_free, .load_page = rrp_load_page, .save_page = rop_save_page, /* Direct reuse */ }; #endif /*CFG_CORE_ASLR*/ const struct fobj_ops ops_locked_paged; struct fobj *fobj_locked_paged_alloc(unsigned int num_pages) { struct fobj *f = NULL; assert(num_pages); f = calloc(1, sizeof(*f)); if (!f) return NULL; fobj_init(f, &ops_locked_paged, num_pages); return f; } static void lop_free(struct fobj *fobj) { assert(fobj->ops == &ops_locked_paged); fobj_uninit(fobj); free(fobj); } static TEE_Result lop_load_page(struct fobj *fobj __maybe_unused, unsigned int page_idx __maybe_unused, void *va) { assert(fobj->ops == &ops_locked_paged); assert(refcount_val(&fobj->refc)); assert(page_idx < fobj->num_pages); memset(va, 0, SMALL_PAGE_SIZE); return TEE_SUCCESS; } DECLARE_KEEP_PAGER(lop_load_page); static TEE_Result lop_save_page(struct fobj *fobj __unused, unsigned int page_idx __unused, const void *va __unused) { return TEE_ERROR_GENERIC; } DECLARE_KEEP_PAGER(lop_save_page); /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct fobj_ops ops_locked_paged __weak __relrodata_unpaged("ops_locked_paged") = { .free = lop_free, .load_page = lop_load_page, .save_page = lop_save_page, }; #endif /*CFG_WITH_PAGER*/ #ifndef CFG_PAGED_USER_TA struct fobj_sec_mem { tee_mm_entry_t *mm; struct fobj fobj; }; const struct fobj_ops ops_sec_mem; struct fobj *fobj_sec_mem_alloc(unsigned int num_pages) { struct fobj_sec_mem *f = calloc(1, sizeof(*f)); size_t size = 0; void *va = NULL; if (!f) return NULL; if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size)) goto err; f->mm = tee_mm_alloc(&tee_mm_sec_ddr, size); if (!f->mm) goto err; va = phys_to_virt(tee_mm_get_smem(f->mm), MEM_AREA_TA_RAM, size); if (!va) goto err; memtag_clear_mem(va, size); f->fobj.ops = &ops_sec_mem; f->fobj.num_pages = num_pages; refcount_set(&f->fobj.refc, 1); return &f->fobj; err: tee_mm_free(f->mm); free(f); return NULL; } static struct fobj_sec_mem *to_sec_mem(struct fobj *fobj) { assert(fobj->ops == &ops_sec_mem); return container_of(fobj, struct fobj_sec_mem, fobj); } static void sec_mem_free(struct fobj *fobj) { struct fobj_sec_mem *f = to_sec_mem(fobj); assert(!refcount_val(&fobj->refc)); tee_mm_free(f->mm); free(f); } static paddr_t sec_mem_get_pa(struct fobj *fobj, unsigned int page_idx) { struct fobj_sec_mem *f = to_sec_mem(fobj); assert(refcount_val(&fobj->refc)); assert(page_idx < fobj->num_pages); return tee_mm_get_smem(f->mm) + page_idx * SMALL_PAGE_SIZE; } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct fobj_ops ops_sec_mem __weak __relrodata_unpaged("ops_sec_mem") = { .free = sec_mem_free, .get_pa = sec_mem_get_pa, }; #endif /*PAGED_USER_TA*/ optee_os-4.3.0/core/mm/mobj.c000066400000000000000000000277031464416617300160140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2022, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct mobj *mobj_sec_ddr; struct mobj *mobj_tee_ram_rx; struct mobj *mobj_tee_ram_rw; /* * mobj_phys implementation */ struct mobj_phys { struct mobj mobj; enum buf_is_attr battr; /* Defined by TEE_MATTR_MEM_TYPE_* in tee_mmu_types.h */ uint32_t mem_type; vaddr_t va; paddr_t pa; }; static struct mobj_phys *to_mobj_phys(struct mobj *mobj); static void *mobj_phys_get_va(struct mobj *mobj, size_t offset, size_t len) { struct mobj_phys *moph = to_mobj_phys(mobj); if (!moph->va || !mobj_check_offset_and_len(mobj, offset, len)) return NULL; return (void *)(moph->va + offset); } static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs, size_t granule, paddr_t *pa) { struct mobj_phys *moph = to_mobj_phys(mobj); paddr_t p; if (!pa) return TEE_ERROR_GENERIC; p = moph->pa + offs; if (granule) { if (granule != SMALL_PAGE_SIZE && granule != CORE_MMU_PGDIR_SIZE) return TEE_ERROR_GENERIC; p &= ~(granule - 1); } *pa = p; return TEE_SUCCESS; } DECLARE_KEEP_PAGER(mobj_phys_get_pa); static TEE_Result mobj_phys_get_mem_type(struct mobj *mobj, uint32_t *mem_type) { struct mobj_phys *moph = to_mobj_phys(mobj); if (!mem_type) return TEE_ERROR_GENERIC; *mem_type = moph->mem_type; return TEE_SUCCESS; } static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr) { struct mobj_phys *moph = to_mobj_phys(mobj); enum buf_is_attr a; a = moph->battr; switch (attr) { case CORE_MEM_SEC: return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM || a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM; case CORE_MEM_NON_SEC: return a == CORE_MEM_NSEC_SHM; case CORE_MEM_TEE_RAM: case CORE_MEM_TA_RAM: case CORE_MEM_NSEC_SHM: case CORE_MEM_SDP_MEM: return attr == a; default: return false; } } static void mobj_phys_free(struct mobj *mobj) { struct mobj_phys *moph = to_mobj_phys(mobj); free(moph); } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct mobj_ops mobj_phys_ops __weak __relrodata_unpaged("mobj_phys_ops") = { .get_va = mobj_phys_get_va, .get_pa = mobj_phys_get_pa, .get_phys_offs = NULL, /* only offset 0 */ .get_mem_type = mobj_phys_get_mem_type, .matches = mobj_phys_matches, .free = mobj_phys_free, }; static struct mobj_phys *to_mobj_phys(struct mobj *mobj) { assert(mobj->ops == &mobj_phys_ops); return container_of(mobj, struct mobj_phys, mobj); } static struct mobj *mobj_phys_init(paddr_t pa, size_t size, uint32_t mem_type, enum buf_is_attr battr, enum teecore_memtypes area_type) { void *va = NULL; struct mobj_phys *moph = NULL; struct tee_mmap_region *map = NULL; if ((pa & CORE_MMU_USER_PARAM_MASK) || (size & CORE_MMU_USER_PARAM_MASK)) { DMSG("Expect %#x alignment", CORE_MMU_USER_PARAM_SIZE); return NULL; } if (pa) { va = phys_to_virt(pa, area_type, size); } else { map = core_mmu_find_mapping_exclusive(area_type, size); if (!map) return NULL; pa = map->pa; va = (void *)map->va; } /* Only SDP memory may not have a virtual address */ if (!va && battr != CORE_MEM_SDP_MEM) return NULL; moph = calloc(1, sizeof(*moph)); if (!moph) return NULL; moph->battr = battr; moph->mem_type = mem_type; moph->mobj.size = size; moph->mobj.ops = &mobj_phys_ops; refcount_set(&moph->mobj.refc, 1); moph->pa = pa; moph->va = (vaddr_t)va; return &moph->mobj; } struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t mem_type, enum buf_is_attr battr) { enum teecore_memtypes area_type; switch (battr) { case CORE_MEM_TEE_RAM: area_type = MEM_AREA_TEE_RAM_RW_DATA; break; case CORE_MEM_TA_RAM: area_type = MEM_AREA_TA_RAM; break; case CORE_MEM_NSEC_SHM: area_type = MEM_AREA_NSEC_SHM; break; case CORE_MEM_SDP_MEM: area_type = MEM_AREA_SDP_MEM; break; default: DMSG("can't allocate with specified attribute"); return NULL; } return mobj_phys_init(pa, size, mem_type, battr, area_type); } /* * mobj_virt implementation */ static void mobj_virt_assert_type(struct mobj *mobj); static void *mobj_virt_get_va(struct mobj *mobj, size_t offset, size_t len __maybe_unused) { mobj_virt_assert_type(mobj); assert(mobj_check_offset_and_len(mobj, offset, len)); return (void *)(vaddr_t)offset; } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct mobj_ops mobj_virt_ops __weak __relrodata_unpaged("mobj_virt_ops") = { .get_va = mobj_virt_get_va, }; static void mobj_virt_assert_type(struct mobj *mobj __maybe_unused) { assert(mobj->ops == &mobj_virt_ops); } struct mobj mobj_virt = { .ops = &mobj_virt_ops, .size = SIZE_MAX }; /* * mobj_shm implementation. mobj_shm represents buffer in predefined shm region * - it is physically contiguous. * - it is identified in static physical layout as MEM_AREA_NSEC_SHM. * - it creates mobjs that match specific CORE_MEM_NSEC_SHM and non secure * generic CORE_MEM_NON_SEC. */ struct mobj_shm { struct mobj mobj; paddr_t pa; uint64_t cookie; }; static struct mobj_shm *to_mobj_shm(struct mobj *mobj); static void *mobj_shm_get_va(struct mobj *mobj, size_t offset, size_t len) { struct mobj_shm *m = to_mobj_shm(mobj); if (!mobj_check_offset_and_len(mobj, offset, len)) return NULL; return phys_to_virt(m->pa + offset, MEM_AREA_NSEC_SHM, mobj->size - offset); } static TEE_Result mobj_shm_get_pa(struct mobj *mobj, size_t offs, size_t granule, paddr_t *pa) { struct mobj_shm *m = to_mobj_shm(mobj); paddr_t p; if (!pa || offs >= mobj->size) return TEE_ERROR_GENERIC; p = m->pa + offs; if (granule) { if (granule != SMALL_PAGE_SIZE && granule != CORE_MMU_PGDIR_SIZE) return TEE_ERROR_GENERIC; p &= ~(granule - 1); } *pa = p; return TEE_SUCCESS; } DECLARE_KEEP_PAGER(mobj_shm_get_pa); static size_t mobj_shm_get_phys_offs(struct mobj *mobj, size_t granule) { assert(IS_POWER_OF_TWO(granule)); return to_mobj_shm(mobj)->pa & (granule - 1); } static bool mobj_shm_matches(struct mobj *mobj __unused, enum buf_is_attr attr) { return attr == CORE_MEM_NSEC_SHM || attr == CORE_MEM_NON_SEC; } static TEE_Result mobj_shm_get_mem_type(struct mobj *mobj __unused, uint32_t *mem_type) { if (!mem_type) return TEE_ERROR_GENERIC; *mem_type = TEE_MATTR_MEM_TYPE_CACHED; return TEE_SUCCESS; } static void mobj_shm_free(struct mobj *mobj) { struct mobj_shm *m = to_mobj_shm(mobj); free(m); } static uint64_t mobj_shm_get_cookie(struct mobj *mobj) { return to_mobj_shm(mobj)->cookie; } /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct mobj_ops mobj_shm_ops __weak __relrodata_unpaged("mobj_shm_ops") = { .get_va = mobj_shm_get_va, .get_pa = mobj_shm_get_pa, .get_phys_offs = mobj_shm_get_phys_offs, .get_mem_type = mobj_shm_get_mem_type, .matches = mobj_shm_matches, .free = mobj_shm_free, .get_cookie = mobj_shm_get_cookie, }; static struct mobj_shm *to_mobj_shm(struct mobj *mobj) { assert(mobj->ops == &mobj_shm_ops); return container_of(mobj, struct mobj_shm, mobj); } struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie) { struct mobj_shm *m; if (!core_pbuf_is(CORE_MEM_NSEC_SHM, pa, size)) return NULL; m = calloc(1, sizeof(*m)); if (!m) return NULL; m->mobj.size = size; m->mobj.ops = &mobj_shm_ops; m->mobj.phys_granule = SMALL_PAGE_SIZE; refcount_set(&m->mobj.refc, 1); m->pa = pa; m->cookie = cookie; return &m->mobj; } struct mobj_with_fobj { struct fobj *fobj; struct file *file; struct mobj mobj; uint8_t mem_type; }; const struct mobj_ops mobj_with_fobj_ops; struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file, uint32_t mem_type) { struct mobj_with_fobj *m = NULL; assert(!(mem_type & ~TEE_MATTR_MEM_TYPE_MASK)); if (!fobj) return NULL; if (mem_type > UINT8_MAX) return NULL; m = calloc(1, sizeof(*m)); if (!m) return NULL; m->mobj.ops = &mobj_with_fobj_ops; refcount_set(&m->mobj.refc, 1); m->mobj.size = fobj->num_pages * SMALL_PAGE_SIZE; m->mobj.phys_granule = SMALL_PAGE_SIZE; m->fobj = fobj_get(fobj); m->file = file_get(file); m->mem_type = mem_type; return &m->mobj; } static struct mobj_with_fobj *to_mobj_with_fobj(struct mobj *mobj) { assert(mobj && mobj->ops == &mobj_with_fobj_ops); return container_of(mobj, struct mobj_with_fobj, mobj); } static bool mobj_with_fobj_matches(struct mobj *mobj __maybe_unused, enum buf_is_attr attr) { assert(to_mobj_with_fobj(mobj)); /* * All fobjs are supposed to be mapped secure so classify it as * CORE_MEM_SEC. Stay out of CORE_MEM_TEE_RAM etc, if that information * needed it can probably be carried in another way than to put the * burden directly on fobj. */ return attr == CORE_MEM_SEC; } static void mobj_with_fobj_free(struct mobj *mobj) { struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); fobj_put(m->fobj); file_put(m->file); free(m); } static struct fobj *mobj_with_fobj_get_fobj(struct mobj *mobj) { return fobj_get(to_mobj_with_fobj(mobj)->fobj); } static TEE_Result mobj_with_fobj_get_mem_type(struct mobj *mobj, uint32_t *mem_type) { struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); if (!mem_type) return TEE_ERROR_GENERIC; *mem_type = m->mem_type; return TEE_SUCCESS; } static TEE_Result mobj_with_fobj_get_pa(struct mobj *mobj, size_t offs, size_t granule, paddr_t *pa) { struct mobj_with_fobj *f = to_mobj_with_fobj(mobj); paddr_t p = 0; if (!f->fobj->ops->get_pa) { assert(mobj_is_paged(mobj)); return TEE_ERROR_NOT_SUPPORTED; } p = f->fobj->ops->get_pa(f->fobj, offs / SMALL_PAGE_SIZE) + offs % SMALL_PAGE_SIZE; if (granule) { if (granule != SMALL_PAGE_SIZE && granule != CORE_MMU_PGDIR_SIZE) return TEE_ERROR_GENERIC; p &= ~(granule - 1); } *pa = p; return TEE_SUCCESS; } DECLARE_KEEP_PAGER(mobj_with_fobj_get_pa); /* * Note: this variable is weak just to ease breaking its dependency chain * when added to the unpaged area. */ const struct mobj_ops mobj_with_fobj_ops __weak __relrodata_unpaged("mobj_with_fobj_ops") = { .matches = mobj_with_fobj_matches, .free = mobj_with_fobj_free, .get_fobj = mobj_with_fobj_get_fobj, .get_mem_type = mobj_with_fobj_get_mem_type, .get_pa = mobj_with_fobj_get_pa, }; #ifdef CFG_PAGED_USER_TA bool mobj_is_paged(struct mobj *mobj) { if (mobj->ops == &mobj_with_fobj_ops && !to_mobj_with_fobj(mobj)->fobj->ops->get_pa) return true; return false; } #endif /*CFG_PAGED_USER_TA*/ static TEE_Result mobj_init(void) { mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo, tee_mm_sec_ddr.size, TEE_MATTR_MEM_TYPE_CACHED, CORE_MEM_TA_RAM); if (!mobj_sec_ddr) panic("Failed to register secure ta ram"); if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) { mobj_tee_ram_rx = mobj_phys_init(0, VCORE_UNPG_RX_SZ, TEE_MATTR_MEM_TYPE_CACHED, CORE_MEM_TEE_RAM, MEM_AREA_TEE_RAM_RX); if (!mobj_tee_ram_rx) panic("Failed to register tee ram rx"); mobj_tee_ram_rw = mobj_phys_init(0, VCORE_UNPG_RW_SZ, TEE_MATTR_MEM_TYPE_CACHED, CORE_MEM_TEE_RAM, MEM_AREA_TEE_RAM_RW_DATA); if (!mobj_tee_ram_rw) panic("Failed to register tee ram rw"); } else { mobj_tee_ram_rw = mobj_phys_init(TEE_RAM_START, VCORE_UNPG_RW_PA + VCORE_UNPG_RW_SZ - TEE_RAM_START, TEE_MATTR_MEM_TYPE_CACHED, CORE_MEM_TEE_RAM, MEM_AREA_TEE_RAM_RW_DATA); if (!mobj_tee_ram_rw) panic("Failed to register tee ram"); mobj_tee_ram_rx = mobj_tee_ram_rw; } return TEE_SUCCESS; } driver_init_late(mobj_init); optee_os-4.3.0/core/mm/mobj_dyn_shm.c000066400000000000000000000274371464416617300175410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2017, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct mutex shm_mu = MUTEX_INITIALIZER; static struct condvar shm_cv = CONDVAR_INITIALIZER; static size_t shm_release_waiters; /* * mobj_reg_shm implementation. Describes shared memory provided by normal world */ struct mobj_reg_shm { struct mobj mobj; SLIST_ENTRY(mobj_reg_shm) next; uint64_t cookie; tee_mm_entry_t *mm; paddr_t page_offset; struct refcount mapcount; bool guarded; bool releasing; bool release_frees; paddr_t pages[]; }; static size_t mobj_reg_shm_size(size_t nr_pages) { size_t s = 0; if (MUL_OVERFLOW(sizeof(paddr_t), nr_pages, &s)) return 0; if (ADD_OVERFLOW(sizeof(struct mobj_reg_shm), s, &s)) return 0; return s; } static SLIST_HEAD(reg_shm_head, mobj_reg_shm) reg_shm_list = SLIST_HEAD_INITIALIZER(reg_shm_head); static unsigned int reg_shm_slist_lock = SPINLOCK_UNLOCK; static unsigned int reg_shm_map_lock = SPINLOCK_UNLOCK; static struct mobj_reg_shm *to_mobj_reg_shm(struct mobj *mobj); static TEE_Result mobj_reg_shm_get_pa(struct mobj *mobj, size_t offst, size_t granule, paddr_t *pa) { struct mobj_reg_shm *mobj_reg_shm = to_mobj_reg_shm(mobj); size_t full_offset = 0; paddr_t p = 0; if (!pa) return TEE_ERROR_GENERIC; if (offst >= mobj->size) return TEE_ERROR_GENERIC; full_offset = offst + mobj_reg_shm->page_offset; switch (granule) { case 0: p = mobj_reg_shm->pages[full_offset / SMALL_PAGE_SIZE] + (full_offset & SMALL_PAGE_MASK); break; case SMALL_PAGE_SIZE: p = mobj_reg_shm->pages[full_offset / SMALL_PAGE_SIZE]; break; default: return TEE_ERROR_GENERIC; } *pa = p; return TEE_SUCCESS; } DECLARE_KEEP_PAGER(mobj_reg_shm_get_pa); static size_t mobj_reg_shm_get_phys_offs(struct mobj *mobj, size_t granule __maybe_unused) { assert(granule >= mobj->phys_granule); return to_mobj_reg_shm(mobj)->page_offset; } static void *mobj_reg_shm_get_va(struct mobj *mobj, size_t offst, size_t len) { struct mobj_reg_shm *mrs = to_mobj_reg_shm(mobj); if (!mrs->mm || !mobj_check_offset_and_len(mobj, offst, len)) return NULL; return (void *)(vaddr_t)(tee_mm_get_smem(mrs->mm) + offst + mrs->page_offset); } static void reg_shm_unmap_helper(struct mobj_reg_shm *r) { assert(r->mm); assert(r->mm->pool->shift == SMALL_PAGE_SHIFT); core_mmu_unmap_pages(tee_mm_get_smem(r->mm), r->mm->size); tee_mm_free(r->mm); r->mm = NULL; } static void reg_shm_free_helper(struct mobj_reg_shm *mobj_reg_shm) { uint32_t exceptions = cpu_spin_lock_xsave(®_shm_map_lock); if (mobj_reg_shm->mm) reg_shm_unmap_helper(mobj_reg_shm); cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); SLIST_REMOVE(®_shm_list, mobj_reg_shm, mobj_reg_shm, next); free(mobj_reg_shm); } static void mobj_reg_shm_free(struct mobj *mobj) { struct mobj_reg_shm *r = to_mobj_reg_shm(mobj); uint32_t exceptions = 0; if (r->guarded && !r->releasing) { /* * Guarded registersted shared memory can't be released * by cookie, only by mobj_put(). However, unguarded * registered shared memory can also be freed by mobj_put() * unless mobj_reg_shm_release_by_cookie() is waiting for * the mobj to be released. */ exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); reg_shm_free_helper(r); cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); } else { /* * We've reached the point where an unguarded reg shm can * be released by cookie. Notify eventual waiters. */ exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); r->release_frees = true; cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); mutex_lock(&shm_mu); if (shm_release_waiters) condvar_broadcast(&shm_cv); mutex_unlock(&shm_mu); } } static TEE_Result mobj_reg_shm_get_mem_type(struct mobj *mobj __unused, uint32_t *mt) { if (!mt) return TEE_ERROR_GENERIC; *mt = TEE_MATTR_MEM_TYPE_CACHED; return TEE_SUCCESS; } static TEE_Result mobj_reg_shm_inc_map(struct mobj *mobj) { TEE_Result res = TEE_SUCCESS; struct mobj_reg_shm *r = to_mobj_reg_shm(mobj); uint32_t exceptions = 0; size_t sz = 0; while (true) { if (refcount_inc(&r->mapcount)) return TEE_SUCCESS; exceptions = cpu_spin_lock_xsave(®_shm_map_lock); if (!refcount_val(&r->mapcount)) break; /* continue to reinitialize */ /* * If another thread beat us to initialize mapcount, * restart to make sure we still increase it. */ cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); } /* * If we have beaten another thread calling mobj_reg_shm_dec_map() * to get the lock we need only to reinitialize mapcount to 1. */ if (!r->mm) { sz = ROUNDUP(mobj->size + r->page_offset, SMALL_PAGE_SIZE); r->mm = tee_mm_alloc(&core_virt_shm_pool, sz); if (!r->mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = core_mmu_map_pages(tee_mm_get_smem(r->mm), r->pages, sz / SMALL_PAGE_SIZE, MEM_AREA_NSEC_SHM); if (res) { tee_mm_free(r->mm); r->mm = NULL; goto out; } } refcount_set(&r->mapcount, 1); out: cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); return res; } static TEE_Result mobj_reg_shm_dec_map(struct mobj *mobj) { struct mobj_reg_shm *r = to_mobj_reg_shm(mobj); uint32_t exceptions = 0; if (!refcount_dec(&r->mapcount)) return TEE_SUCCESS; exceptions = cpu_spin_lock_xsave(®_shm_map_lock); /* * Check that another thread hasn't been able to: * - increase the mapcount * - or, increase the mapcount, decrease it again, and set r->mm to * NULL * before we acquired the spinlock */ if (!refcount_val(&r->mapcount) && r->mm) reg_shm_unmap_helper(r); cpu_spin_unlock_xrestore(®_shm_map_lock, exceptions); return TEE_SUCCESS; } static bool mobj_reg_shm_matches(struct mobj *mobj, enum buf_is_attr attr); static uint64_t mobj_reg_shm_get_cookie(struct mobj *mobj) { return to_mobj_reg_shm(mobj)->cookie; } /* * When CFG_PREALLOC_RPC_CACHE is disabled, this variable is weak just * to ease breaking its dependency chain when added to the unpaged area. * When CFG_PREALLOC_RPC_CACHE is enabled, releasing RPC preallocated * shm mandates these resources to be unpaged. */ const struct mobj_ops mobj_reg_shm_ops __weak __relrodata_unpaged("mobj_reg_shm_ops") = { .get_pa = mobj_reg_shm_get_pa, .get_phys_offs = mobj_reg_shm_get_phys_offs, .get_va = mobj_reg_shm_get_va, .get_mem_type = mobj_reg_shm_get_mem_type, .matches = mobj_reg_shm_matches, .free = mobj_reg_shm_free, .get_cookie = mobj_reg_shm_get_cookie, .inc_map = mobj_reg_shm_inc_map, .dec_map = mobj_reg_shm_dec_map, }; #ifdef CFG_PREALLOC_RPC_CACHE /* Releasing RPC preallocated shm mandates few resources to be unpaged */ DECLARE_KEEP_PAGER(mobj_reg_shm_get_cookie); DECLARE_KEEP_PAGER(mobj_reg_shm_matches); DECLARE_KEEP_PAGER(mobj_reg_shm_free); #endif static bool mobj_reg_shm_matches(struct mobj *mobj __maybe_unused, enum buf_is_attr attr) { assert(mobj->ops == &mobj_reg_shm_ops); return attr == CORE_MEM_NON_SEC || attr == CORE_MEM_REG_SHM; } static struct mobj_reg_shm *to_mobj_reg_shm(struct mobj *mobj) { assert(mobj->ops == &mobj_reg_shm_ops); return container_of(mobj, struct mobj_reg_shm, mobj); } struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages, paddr_t page_offset, uint64_t cookie) { struct mobj_reg_shm *mobj_reg_shm = NULL; size_t i = 0; uint32_t exceptions = 0; size_t s = 0; if (!num_pages || page_offset >= SMALL_PAGE_SIZE) return NULL; s = mobj_reg_shm_size(num_pages); if (!s) return NULL; mobj_reg_shm = calloc(1, s); if (!mobj_reg_shm) return NULL; mobj_reg_shm->mobj.ops = &mobj_reg_shm_ops; mobj_reg_shm->mobj.size = num_pages * SMALL_PAGE_SIZE - page_offset; mobj_reg_shm->mobj.phys_granule = SMALL_PAGE_SIZE; refcount_set(&mobj_reg_shm->mobj.refc, 1); mobj_reg_shm->cookie = cookie; mobj_reg_shm->guarded = true; mobj_reg_shm->page_offset = page_offset; memcpy(mobj_reg_shm->pages, pages, sizeof(*pages) * num_pages); /* Ensure loaded references match format and security constraints */ for (i = 0; i < num_pages; i++) { if (mobj_reg_shm->pages[i] & SMALL_PAGE_MASK) goto err; /* Only Non-secure memory can be mapped there */ if (!core_pbuf_is(CORE_MEM_NON_SEC, mobj_reg_shm->pages[i], SMALL_PAGE_SIZE)) goto err; } exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); SLIST_INSERT_HEAD(®_shm_list, mobj_reg_shm, next); cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); return &mobj_reg_shm->mobj; err: free(mobj_reg_shm); return NULL; } void mobj_reg_shm_unguard(struct mobj *mobj) { uint32_t exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); to_mobj_reg_shm(mobj)->guarded = false; cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); } static struct mobj_reg_shm *reg_shm_find_unlocked(uint64_t cookie) { struct mobj_reg_shm *mobj_reg_shm = NULL; SLIST_FOREACH(mobj_reg_shm, ®_shm_list, next) if (mobj_reg_shm->cookie == cookie) return mobj_reg_shm; return NULL; } struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie) { uint32_t exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); struct mobj_reg_shm *r = reg_shm_find_unlocked(cookie); cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); if (!r) return NULL; return mobj_get(&r->mobj); } TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie) { uint32_t exceptions = 0; struct mobj_reg_shm *r = NULL; /* * Try to find r and see can be released by this function, if so * call mobj_put(). Otherwise this function is called either by * wrong cookie and perhaps a second time, regardless return * TEE_ERROR_BAD_PARAMETERS. */ exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); r = reg_shm_find_unlocked(cookie); if (!r || r->guarded || r->releasing) r = NULL; else r->releasing = true; cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); if (!r) return TEE_ERROR_BAD_PARAMETERS; mobj_put(&r->mobj); /* * We've established that this function can release the cookie. * Now we wait until mobj_reg_shm_free() is called by the last * mobj_put() needed to free this mobj. Note that the call to * mobj_put() above could very well be that call. * * Once mobj_reg_shm_free() is called it will set r->release_frees * to true and we can free the mobj here. */ mutex_lock(&shm_mu); shm_release_waiters++; assert(shm_release_waiters); while (true) { exceptions = cpu_spin_lock_xsave(®_shm_slist_lock); if (r->release_frees) { reg_shm_free_helper(r); r = NULL; } cpu_spin_unlock_xrestore(®_shm_slist_lock, exceptions); if (!r) break; condvar_wait(&shm_cv, &shm_mu); } assert(shm_release_waiters); shm_release_waiters--; mutex_unlock(&shm_mu); return TEE_SUCCESS; } struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages, paddr_t page_offset, uint64_t cookie) { struct mobj *mobj = mobj_reg_shm_alloc(pages, num_pages, page_offset, cookie); if (!mobj) return NULL; if (mobj_inc_map(mobj)) { mobj_put(mobj); return NULL; } return mobj; } static TEE_Result mobj_mapped_shm_init(void) { vaddr_t pool_start = 0; vaddr_t pool_end = 0; core_mmu_get_mem_by_type(MEM_AREA_SHM_VASPACE, &pool_start, &pool_end); if (!pool_start || !pool_end) panic("Can't find region for shmem pool"); if (!tee_mm_init(&core_virt_shm_pool, pool_start, pool_end - pool_start, SMALL_PAGE_SHIFT, TEE_MM_POOL_NO_FLAGS)) panic("Could not create shmem pool"); DMSG("Shared memory address range: %" PRIxVA ", %" PRIxVA, pool_start, pool_end); return TEE_SUCCESS; } preinit(mobj_mapped_shm_init); optee_os-4.3.0/core/mm/pgt_cache.c000066400000000000000000000472221464416617300170000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, 2022 Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include /* * With pager enabled we allocate page table from the pager. * * For LPAE each page table is a complete page which is allocated and freed * using the interface provided by the pager. * * For compat v7 page tables there's room for four page table in one page * so we need to keep track of how much of an allocated page is used. When * a page is completely unused it's returned to the pager. * * With pager disabled we have a static allocation of page tables instead. * * In all cases we limit the number of active page tables to * PGT_CACHE_SIZE. This pool of page tables are shared between all * threads. In case a thread can't allocate the needed number of pager * tables it will release all its current tables and wait for some more to * be freed. A threads allocated tables are freed each time a TA is * unmapped so each thread should be able to allocate the needed tables in * turn if needed. */ #if defined(CFG_CORE_PREALLOC_EL0_TBLS) || \ (defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE)) struct pgt_parent { size_t num_used; struct pgt_cache pgt_cache; #if defined(CFG_CORE_PREALLOC_EL0_TBLS) tee_mm_entry_t *mm; SLIST_ENTRY(pgt_parent) link; #endif }; #endif #if defined(CFG_CORE_PREALLOC_EL0_TBLS) /* * Pick something large enough that tee_mm_alloc() doesn't have to be * called for each needed translation table. */ #define PGT_PARENT_SIZE (4 * SMALL_PAGE_SIZE) #define PGT_PARENT_TBL_COUNT (PGT_PARENT_SIZE / PGT_SIZE) SLIST_HEAD(pgt_parent_list, pgt_parent); static struct pgt_parent_list parent_list = SLIST_HEAD_INITIALIZER(parent_list); static unsigned int parent_spinlock = SPINLOCK_UNLOCK; static void free_pgt(struct pgt *pgt) { struct pgt_parent *parent = NULL; uint32_t exceptions = 0; exceptions = cpu_spin_lock_xsave(&parent_spinlock); assert(pgt && pgt->parent); parent = pgt->parent; assert(parent->num_used <= PGT_PARENT_TBL_COUNT && parent->num_used > 0); if (parent->num_used == PGT_PARENT_TBL_COUNT) SLIST_INSERT_HEAD(&parent_list, parent, link); parent->num_used--; if (!parent->num_used && SLIST_NEXT(SLIST_FIRST(&parent_list), link)) { /* * If this isn't the last pgt_parent with free entries we * can free this. */ SLIST_REMOVE(&parent_list, parent, pgt_parent, link); tee_mm_free(parent->mm); free(parent); } else { SLIST_INSERT_HEAD(&parent->pgt_cache, pgt, link); pgt->vabase = 0; pgt->populated = false; } cpu_spin_unlock_xrestore(&parent_spinlock, exceptions); } static struct pgt_parent *alloc_pgt_parent(void) { struct pgt_parent *parent = NULL; struct pgt *pgt = NULL; uint8_t *tbl = NULL; size_t sz = 0; size_t n = 0; sz = sizeof(*parent) + sizeof(*pgt) * PGT_PARENT_TBL_COUNT; parent = calloc(1, sz); if (!parent) return NULL; parent->mm = tee_mm_alloc(&tee_mm_sec_ddr, PGT_PARENT_SIZE); if (!parent->mm) { free(parent); return NULL; } tbl = phys_to_virt(tee_mm_get_smem(parent->mm), MEM_AREA_TA_RAM, PGT_PARENT_SIZE); assert(tbl); /* "can't fail" */ SLIST_INIT(&parent->pgt_cache); pgt = (struct pgt *)(parent + 1); for (n = 0; n < PGT_PARENT_TBL_COUNT; n++) { pgt[n].parent = parent; pgt[n].tbl = tbl + n * PGT_SIZE; SLIST_INSERT_HEAD(&parent->pgt_cache, pgt + n, link); } return parent; } static struct pgt *alloc_pgt(vaddr_t vabase) { struct pgt_parent *parent = NULL; uint32_t exceptions = 0; struct pgt *pgt = NULL; exceptions = cpu_spin_lock_xsave(&parent_spinlock); parent = SLIST_FIRST(&parent_list); if (!parent) { parent = alloc_pgt_parent(); if (!parent) goto out; SLIST_INSERT_HEAD(&parent_list, parent, link); } pgt = SLIST_FIRST(&parent->pgt_cache); SLIST_REMOVE_HEAD(&parent->pgt_cache, link); parent->num_used++; assert(pgt && parent->num_used <= PGT_PARENT_TBL_COUNT); if (parent->num_used == PGT_PARENT_TBL_COUNT) SLIST_REMOVE_HEAD(&parent_list, link); pgt->vabase = vabase; out: cpu_spin_unlock_xrestore(&parent_spinlock, exceptions); return pgt; } static bool pgt_entry_matches(struct pgt *p, vaddr_t begin, vaddr_t last) { if (!p) return false; if (last <= begin) return false; return core_is_buffer_inside(p->vabase, CORE_MMU_PGDIR_SIZE, begin, last - begin); } void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct pgt *next_p = NULL; struct pgt *p = NULL; /* * Do the special case where the first element in the list is * removed first. */ p = SLIST_FIRST(pgt_cache); while (pgt_entry_matches(p, begin, last)) { SLIST_REMOVE_HEAD(pgt_cache, link); free_pgt(p); p = SLIST_FIRST(pgt_cache); } /* * p either points to the first element in the list or it's NULL, * if NULL the list is empty and we're done. */ if (!p) return; /* * Do the common case where the next element in the list is * removed. */ while (true) { next_p = SLIST_NEXT(p, link); if (!next_p) break; if (pgt_entry_matches(next_p, begin, last)) { SLIST_REMOVE_AFTER(p, link); free_pgt(next_p); continue; } p = SLIST_NEXT(p, link); } } void pgt_flush(struct user_mode_ctx *uctx) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct pgt *p = NULL; while (true) { p = SLIST_FIRST(pgt_cache); if (!p) break; SLIST_REMOVE_HEAD(pgt_cache, link); free_pgt(p); } } void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct pgt *p = NULL; #ifdef CFG_WITH_LPAE uint64_t *tbl = NULL; #else uint32_t *tbl = NULL; #endif unsigned int idx = 0; unsigned int n = 0; SLIST_FOREACH(p, pgt_cache, link) { vaddr_t b = MAX(p->vabase, begin); vaddr_t e = MIN(p->vabase + CORE_MMU_PGDIR_SIZE, end); if (b >= e) continue; tbl = p->tbl; idx = (b - p->vabase) / SMALL_PAGE_SIZE; n = (e - b) / SMALL_PAGE_SIZE; memset(tbl + idx, 0, n * sizeof(*tbl)); } } static struct pgt *prune_before_va(struct pgt_cache *pgt_cache, struct pgt *p, struct pgt *pp, vaddr_t va) { while (p && p->vabase < va) { if (pp) { assert(p == SLIST_NEXT(pp, link)); SLIST_REMOVE_AFTER(pp, link); free_pgt(p); p = SLIST_NEXT(pp, link); } else { assert(p == SLIST_FIRST(pgt_cache)); SLIST_REMOVE_HEAD(pgt_cache, link); free_pgt(p); p = SLIST_FIRST(pgt_cache); } } return p; } bool pgt_check_avail(struct user_mode_ctx *uctx) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct vm_info *vm_info = &uctx->vm_info; struct pgt *p = SLIST_FIRST(pgt_cache); struct vm_region *r = NULL; struct pgt *pp = NULL; vaddr_t va = 0; bool p_used = false; /* * Prune unused tables. This is normally not needed since * pgt_flush_range() does this too, but in the error path of for * instance vm_remap() such calls may not be done. So for increased * robustness remove all unused translation tables before we may * allocate new ones. */ TAILQ_FOREACH(r, &vm_info->regions, link) { for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { if (!p_used) p = prune_before_va(pgt_cache, p, pp, va); if (!p) goto prune_done; if (p->vabase < va) { pp = p; p = SLIST_NEXT(pp, link); if (!p) goto prune_done; p_used = false; } if (p->vabase == va) p_used = true; } } prune_done: p = SLIST_FIRST(pgt_cache); pp = NULL; TAILQ_FOREACH(r, &vm_info->regions, link) { for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { if (p && p->vabase < va) { pp = p; p = SLIST_NEXT(pp, link); } if (p) { if (p->vabase == va) continue; assert(p->vabase > va); } p = alloc_pgt(va); if (!p) return false; if (pp) SLIST_INSERT_AFTER(pp, p, link); else SLIST_INSERT_HEAD(pgt_cache, p, link); } } return true; } #else /* !CFG_CORE_PREALLOC_EL0_TBLS */ #define PGT_CACHE_SIZE ROUNDUP(CFG_PGT_CACHE_ENTRIES, PGT_NUM_PGT_PER_PAGE) #if defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE) static struct pgt_parent pgt_parents[PGT_CACHE_SIZE / PGT_NUM_PGT_PER_PAGE]; #else static struct pgt_cache pgt_free_list = SLIST_HEAD_INITIALIZER(pgt_free_list); #endif /* * When a user TA context is temporarily unmapped the used struct pgt's of * the context (page tables holding valid physical pages) are saved in this * cache in the hope that it will remain in the cache when the context is * mapped again. */ static struct pgt_cache pgt_cache_list = SLIST_HEAD_INITIALIZER(pgt_cache_list); static struct pgt pgt_entries[PGT_CACHE_SIZE]; static struct mutex pgt_mu = MUTEX_INITIALIZER; static struct condvar pgt_cv = CONDVAR_INITIALIZER; #if defined(CFG_WITH_PAGER) && defined(CFG_WITH_LPAE) /* * Simple allocation of translation tables from pager, one translation * table is one page. */ void pgt_init(void) { size_t n; for (n = 0; n < PGT_CACHE_SIZE; n++) { struct pgt *p = pgt_entries + n; p->tbl = tee_pager_alloc(PGT_SIZE); SLIST_INSERT_HEAD(&pgt_free_list, p, link); } } #elif defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE) /* * Four translation tables per page -> need to keep track of the page * allocated from the pager. */ void pgt_init(void) { size_t n; size_t m; COMPILE_TIME_ASSERT(PGT_CACHE_SIZE % PGT_NUM_PGT_PER_PAGE == 0); COMPILE_TIME_ASSERT(PGT_SIZE * PGT_NUM_PGT_PER_PAGE == SMALL_PAGE_SIZE); for (n = 0; n < ARRAY_SIZE(pgt_parents); n++) { uint8_t *tbl = tee_pager_alloc(SMALL_PAGE_SIZE); SLIST_INIT(&pgt_parents[n].pgt_cache); for (m = 0; m < PGT_NUM_PGT_PER_PAGE; m++) { struct pgt *p = pgt_entries + n * PGT_NUM_PGT_PER_PAGE + m; p->tbl = tbl + m * PGT_SIZE; p->parent = &pgt_parents[n]; SLIST_INSERT_HEAD(&pgt_parents[n].pgt_cache, p, link); } } } #else /* Static allocation of translation tables */ void pgt_init(void) { /* * We're putting this in .nozi.* instead of .bss because .nozi.* already * has a large alignment, while .bss has a small alignment. The current * link script is optimized for small alignment in .bss */ static uint8_t pgt_tables[PGT_CACHE_SIZE][PGT_SIZE] __aligned(PGT_SIZE) __section(".nozi.pgt_cache"); size_t n; for (n = 0; n < ARRAY_SIZE(pgt_tables); n++) { struct pgt *p = pgt_entries + n; p->tbl = pgt_tables[n]; SLIST_INSERT_HEAD(&pgt_free_list, p, link); } } #endif #if defined(CFG_WITH_LPAE) || !defined(CFG_WITH_PAGER) /* Simple allocation of translation tables from pager or static allocation */ static struct pgt *pop_from_free_list(void) { struct pgt *p = SLIST_FIRST(&pgt_free_list); if (p) { SLIST_REMOVE_HEAD(&pgt_free_list, link); memset(p->tbl, 0, PGT_SIZE); p->populated = false; } return p; } static void push_to_free_list(struct pgt *p) { SLIST_INSERT_HEAD(&pgt_free_list, p, link); #if defined(CFG_WITH_PAGER) tee_pager_release_phys(p->tbl, PGT_SIZE); #endif } #else /* * Four translation tables per page -> need to keep track of the page * allocated from the pager. */ static struct pgt *pop_from_free_list(void) { size_t n; for (n = 0; n < ARRAY_SIZE(pgt_parents); n++) { struct pgt *p = SLIST_FIRST(&pgt_parents[n].pgt_cache); if (p) { SLIST_REMOVE_HEAD(&pgt_parents[n].pgt_cache, link); pgt_parents[n].num_used++; memset(p->tbl, 0, PGT_SIZE); p->populated = false; return p; } } return NULL; } static void push_to_free_list(struct pgt *p) { SLIST_INSERT_HEAD(&p->parent->pgt_cache, p, link); assert(p->parent->num_used > 0); p->parent->num_used--; if (!p->parent->num_used) { vaddr_t va = (vaddr_t)p->tbl & ~SMALL_PAGE_MASK; tee_pager_release_phys((void *)va, SMALL_PAGE_SIZE); } } #endif static void push_to_cache_list(struct pgt *pgt) { SLIST_INSERT_HEAD(&pgt_cache_list, pgt, link); } static bool match_pgt(struct pgt *pgt, vaddr_t vabase, void *ctx) { return pgt->ctx == ctx && pgt->vabase == vabase; } static struct pgt *pop_from_cache_list(vaddr_t vabase, void *ctx) { struct pgt *pgt; struct pgt *p; pgt = SLIST_FIRST(&pgt_cache_list); if (!pgt) return NULL; if (match_pgt(pgt, vabase, ctx)) { SLIST_REMOVE_HEAD(&pgt_cache_list, link); return pgt; } while (true) { p = SLIST_NEXT(pgt, link); if (!p) break; if (match_pgt(p, vabase, ctx)) { SLIST_REMOVE_AFTER(pgt, link); break; } pgt = p; } return p; } static uint16_t get_num_used_entries(struct pgt *pgt __maybe_unused) { #ifdef CFG_PAGED_USER_TA return pgt->num_used_entries; #else return 0; #endif } static struct pgt *pop_least_used_from_cache_list(void) { struct pgt *pgt = NULL; struct pgt *p_prev = NULL; size_t least_used = 0; size_t next_used = 0; pgt = SLIST_FIRST(&pgt_cache_list); if (!pgt) return NULL; least_used = get_num_used_entries(pgt); while (true) { if (!SLIST_NEXT(pgt, link)) break; next_used = get_num_used_entries(SLIST_NEXT(pgt, link)); if (next_used <= least_used) { p_prev = pgt; least_used = next_used; } pgt = SLIST_NEXT(pgt, link); } if (p_prev) { pgt = SLIST_NEXT(p_prev, link); SLIST_REMOVE_AFTER(p_prev, link); } else { pgt = SLIST_FIRST(&pgt_cache_list); SLIST_REMOVE_HEAD(&pgt_cache_list, link); } return pgt; } static void pgt_free_unlocked(struct pgt_cache *pgt_cache) { while (!SLIST_EMPTY(pgt_cache)) { struct pgt *p = SLIST_FIRST(pgt_cache); SLIST_REMOVE_HEAD(pgt_cache, link); /* * With paging enabled we free all tables which doesn't * refer to any paged pages any longer. This reduces the * pressure the pool of physical pages. */ if (IS_ENABLED(CFG_PAGED_USER_TA) && !get_num_used_entries(p)) { tee_pager_pgt_save_and_release_entries(p); p->ctx = NULL; p->vabase = 0; push_to_free_list(p); continue; } push_to_cache_list(p); } } static struct pgt *pop_from_some_list(vaddr_t vabase, void *ctx) { struct pgt *p = pop_from_cache_list(vabase, ctx); if (p) return p; p = pop_from_free_list(); if (!p) { p = pop_least_used_from_cache_list(); if (!p) return NULL; tee_pager_pgt_save_and_release_entries(p); memset(p->tbl, 0, PGT_SIZE); p->populated = false; } p->ctx = ctx; p->vabase = vabase; return p; } void pgt_flush(struct user_mode_ctx *uctx) { struct ts_ctx *ctx = uctx->ts_ctx; struct pgt *pp = NULL; struct pgt *p = NULL; mutex_lock(&pgt_mu); while (true) { p = SLIST_FIRST(&pgt_cache_list); if (!p) goto out; if (p->ctx != ctx) break; SLIST_REMOVE_HEAD(&pgt_cache_list, link); tee_pager_pgt_save_and_release_entries(p); p->ctx = NULL; p->vabase = 0; push_to_free_list(p); } pp = p; while (true) { p = SLIST_NEXT(pp, link); if (!p) break; if (p->ctx == ctx) { SLIST_REMOVE_AFTER(pp, link); tee_pager_pgt_save_and_release_entries(p); p->ctx = NULL; p->vabase = 0; push_to_free_list(p); } else { pp = p; } } out: mutex_unlock(&pgt_mu); } static void flush_pgt_entry(struct pgt *p) { tee_pager_pgt_save_and_release_entries(p); p->ctx = NULL; p->vabase = 0; } static bool pgt_entry_matches(struct pgt *p, void *ctx, vaddr_t begin, vaddr_t last) { if (!p) return false; if (p->ctx != ctx) return false; if (last <= begin) return false; if (!core_is_buffer_inside(p->vabase, CORE_MMU_PGDIR_SIZE, begin, last - begin)) return false; return true; } static void flush_ctx_range_from_list(struct pgt_cache *pgt_cache, void *ctx, vaddr_t begin, vaddr_t last) { struct pgt *p; struct pgt *next_p; /* * Do the special case where the first element in the list is * removed first. */ p = SLIST_FIRST(pgt_cache); while (pgt_entry_matches(p, ctx, begin, last)) { flush_pgt_entry(p); SLIST_REMOVE_HEAD(pgt_cache, link); push_to_free_list(p); p = SLIST_FIRST(pgt_cache); } /* * p either points to the first element in the list or it's NULL, * if NULL the list is empty and we're done. */ if (!p) return; /* * Do the common case where the next element in the list is * removed. */ while (true) { next_p = SLIST_NEXT(p, link); if (!next_p) break; if (pgt_entry_matches(next_p, ctx, begin, last)) { flush_pgt_entry(next_p); SLIST_REMOVE_AFTER(p, link); push_to_free_list(next_p); continue; } p = SLIST_NEXT(p, link); } } void pgt_flush_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t last) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct ts_ctx *ctx = uctx->ts_ctx; mutex_lock(&pgt_mu); flush_ctx_range_from_list(pgt_cache, ctx, begin, last); flush_ctx_range_from_list(&pgt_cache_list, ctx, begin, last); condvar_broadcast(&pgt_cv); mutex_unlock(&pgt_mu); } static void clear_ctx_range_from_list(struct pgt_cache *pgt_cache, void *ctx, vaddr_t begin, vaddr_t end) { struct pgt *p = NULL; #ifdef CFG_WITH_LPAE uint64_t *tbl = NULL; #else uint32_t *tbl = NULL; #endif unsigned int idx = 0; unsigned int n = 0; SLIST_FOREACH(p, pgt_cache, link) { vaddr_t b = MAX(p->vabase, begin); vaddr_t e = MIN(p->vabase + CORE_MMU_PGDIR_SIZE, end); if (p->ctx != ctx) continue; if (b >= e) continue; tbl = p->tbl; idx = (b - p->vabase) / SMALL_PAGE_SIZE; n = (e - b) / SMALL_PAGE_SIZE; memset(tbl + idx, 0, n * sizeof(*tbl)); } } void pgt_clear_range(struct user_mode_ctx *uctx, vaddr_t begin, vaddr_t end) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct ts_ctx *ctx = uctx->ts_ctx; mutex_lock(&pgt_mu); clear_ctx_range_from_list(pgt_cache, ctx, begin, end); clear_ctx_range_from_list(&pgt_cache_list, ctx, begin, end); mutex_unlock(&pgt_mu); } static bool pgt_alloc_unlocked(struct pgt_cache *pgt_cache, struct ts_ctx *ctx, struct vm_info *vm_info) { struct vm_region *r = NULL; struct pgt *pp = NULL; struct pgt *p = NULL; vaddr_t va = 0; TAILQ_FOREACH(r, &vm_info->regions, link) { for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { if (p && p->vabase == va) continue; p = pop_from_some_list(va, ctx); if (!p) { pgt_free_unlocked(pgt_cache); return false; } if (pp) SLIST_INSERT_AFTER(pp, p, link); else SLIST_INSERT_HEAD(pgt_cache, p, link); pp = p; } } return true; } bool pgt_check_avail(struct user_mode_ctx *uctx) { struct vm_info *vm_info = &uctx->vm_info; struct vm_region *r = NULL; size_t tbl_count = 0; vaddr_t last_va = 0; vaddr_t va = 0; TAILQ_FOREACH(r, &vm_info->regions, link) { for (va = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); va < r->va + r->size; va += CORE_MMU_PGDIR_SIZE) { if (va == last_va) continue; tbl_count++; last_va = va; } } return tbl_count <= PGT_CACHE_SIZE; } void pgt_get_all(struct user_mode_ctx *uctx) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; struct vm_info *vm_info = &uctx->vm_info; if (TAILQ_EMPTY(&vm_info->regions)) return; mutex_lock(&pgt_mu); pgt_free_unlocked(pgt_cache); while (!pgt_alloc_unlocked(pgt_cache, uctx->ts_ctx, vm_info)) { assert(pgt_check_avail(uctx)); DMSG("Waiting for page tables"); condvar_broadcast(&pgt_cv); condvar_wait(&pgt_cv, &pgt_mu); } mutex_unlock(&pgt_mu); } void pgt_put_all(struct user_mode_ctx *uctx) { struct pgt_cache *pgt_cache = &uctx->pgt_cache; if (SLIST_EMPTY(pgt_cache)) return; mutex_lock(&pgt_mu); pgt_free_unlocked(pgt_cache); condvar_broadcast(&pgt_cv); mutex_unlock(&pgt_mu); } struct pgt *pgt_pop_from_cache_list(vaddr_t vabase, struct ts_ctx *ctx) { struct pgt *pgt = NULL; mutex_lock(&pgt_mu); pgt = pop_from_cache_list(vabase, ctx); mutex_unlock(&pgt_mu); return pgt; } void pgt_push_to_cache_list(struct pgt *pgt) { mutex_lock(&pgt_mu); push_to_cache_list(pgt); mutex_unlock(&pgt_mu); } #endif /* !CFG_CORE_PREALLOC_EL0_TBLS */ optee_os-4.3.0/core/mm/sub.mk000066400000000000000000000004161464416617300160330ustar00rootroot00000000000000srcs-y += mobj.c srcs-y += fobj.c cflags-fobj.c-$(CFG_CORE_PAGE_TAG_AND_IV) := -Wno-missing-noreturn srcs-y += file.c srcs-y += vm.c srcs-y += core_mmu.c srcs-y += pgt_cache.c srcs-y += tee_mm.c ifneq ($(CFG_CORE_FFA),y) srcs-$(CFG_CORE_DYN_SHM) += mobj_dyn_shm.c endif optee_os-4.3.0/core/mm/tee_mm.c000066400000000000000000000204251464416617300163250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include static void *pmalloc(tee_mm_pool_t *pool, size_t size) { if (pool->flags & TEE_MM_POOL_NEX_MALLOC) return nex_malloc(size); else return malloc(size); } static void *pcalloc(tee_mm_pool_t *pool, size_t num_el, size_t size) { if (pool->flags & TEE_MM_POOL_NEX_MALLOC) return nex_calloc(num_el, size); else return calloc(num_el, size); } static void pfree(tee_mm_pool_t *pool, void *ptr) { if (pool->flags & TEE_MM_POOL_NEX_MALLOC) nex_free(ptr); else free(ptr); } bool tee_mm_init(tee_mm_pool_t *pool, paddr_t lo, paddr_size_t size, uint8_t shift, uint32_t flags) { paddr_size_t rounded = 0; paddr_t initial_lo = lo; if (pool == NULL) return false; lo = ROUNDUP(lo, 1 << shift); rounded = lo - initial_lo; size = ROUNDDOWN(size - rounded, 1 << shift); assert(((uint64_t)size >> shift) < (uint64_t)UINT32_MAX); pool->lo = lo; pool->size = size; pool->shift = shift; pool->flags = flags; pool->entry = pcalloc(pool, 1, sizeof(tee_mm_entry_t)); if (pool->entry == NULL) return false; if (pool->flags & TEE_MM_POOL_HI_ALLOC) pool->entry->offset = ((size - 1) >> shift) + 1; pool->entry->pool = pool; pool->lock = SPINLOCK_UNLOCK; return true; } void tee_mm_final(tee_mm_pool_t *pool) { if (pool == NULL || pool->entry == NULL) return; while (pool->entry->next != NULL) tee_mm_free(pool->entry->next); pfree(pool, pool->entry); pool->entry = NULL; } static void tee_mm_add(tee_mm_entry_t *p, tee_mm_entry_t *nn) { /* add to list */ nn->next = p->next; p->next = nn; } #ifdef CFG_WITH_STATS static size_t tee_mm_stats_allocated(tee_mm_pool_t *pool) { tee_mm_entry_t *entry; uint32_t sz = 0; if (!pool) return 0; entry = pool->entry; while (entry) { sz += entry->size; entry = entry->next; } return sz << pool->shift; } void tee_mm_get_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats, bool reset) { uint32_t exceptions; if (!pool) return; memset(stats, 0, sizeof(*stats)); exceptions = cpu_spin_lock_xsave(&pool->lock); stats->size = pool->size; stats->max_allocated = pool->max_allocated; stats->allocated = tee_mm_stats_allocated(pool); if (reset) pool->max_allocated = 0; cpu_spin_unlock_xrestore(&pool->lock, exceptions); } static void update_max_allocated(tee_mm_pool_t *pool) { size_t sz = tee_mm_stats_allocated(pool); if (sz > pool->max_allocated) pool->max_allocated = sz; } #else /* CFG_WITH_STATS */ static inline void update_max_allocated(tee_mm_pool_t *pool __unused) { } #endif /* CFG_WITH_STATS */ tee_mm_entry_t *tee_mm_alloc(tee_mm_pool_t *pool, size_t size) { size_t psize; tee_mm_entry_t *entry; tee_mm_entry_t *nn; size_t remaining; uint32_t exceptions; /* Check that pool is initialized */ if (!pool || !pool->entry) return NULL; nn = pmalloc(pool, sizeof(tee_mm_entry_t)); if (!nn) return NULL; exceptions = cpu_spin_lock_xsave(&pool->lock); entry = pool->entry; if (!size) psize = 0; else psize = ((size - 1) >> pool->shift) + 1; /* find free slot */ if (pool->flags & TEE_MM_POOL_HI_ALLOC) { while (entry->next != NULL && psize > (entry->offset - entry->next->offset - entry->next->size)) entry = entry->next; } else { while (entry->next != NULL && psize > (entry->next->offset - entry->size - entry->offset)) entry = entry->next; } /* check if we have enough memory */ if (entry->next == NULL) { if (pool->flags & TEE_MM_POOL_HI_ALLOC) { /* * entry->offset is a "block count" offset from * pool->lo. The byte offset is * (entry->offset << pool->shift). * In the HI_ALLOC allocation scheme the memory is * allocated from the end of the segment, thus to * validate there is sufficient memory validate that * (entry->offset << pool->shift) > size. */ if ((entry->offset << pool->shift) < size) { /* out of memory */ goto err; } } else { if (!pool->size) panic("invalid pool"); remaining = pool->size; remaining -= ((entry->offset + entry->size) << pool->shift); if (remaining < size) { /* out of memory */ goto err; } } } tee_mm_add(entry, nn); if (pool->flags & TEE_MM_POOL_HI_ALLOC) nn->offset = entry->offset - psize; else nn->offset = entry->offset + entry->size; nn->size = psize; nn->pool = pool; update_max_allocated(pool); cpu_spin_unlock_xrestore(&pool->lock, exceptions); return nn; err: cpu_spin_unlock_xrestore(&pool->lock, exceptions); pfree(pool, nn); return NULL; } static inline bool fit_in_gap(tee_mm_pool_t *pool, tee_mm_entry_t *e, paddr_t offslo, paddr_t offshi) { if (pool->flags & TEE_MM_POOL_HI_ALLOC) { if (offshi > e->offset || (e->next != NULL && (offslo < e->next->offset + e->next->size)) || (offshi << pool->shift) - 1 > pool->size) /* memory not available */ return false; } else { if (offslo < (e->offset + e->size) || (e->next != NULL && (offshi > e->next->offset)) || (offshi << pool->shift) > pool->size) /* memory not available */ return false; } return true; } tee_mm_entry_t *tee_mm_alloc2(tee_mm_pool_t *pool, paddr_t base, size_t size) { tee_mm_entry_t *entry; paddr_t offslo; paddr_t offshi; tee_mm_entry_t *mm; uint32_t exceptions; /* Check that pool is initialized */ if (!pool || !pool->entry) return NULL; /* Wrapping and sanity check */ if ((base + size) < base || base < pool->lo) return NULL; mm = pmalloc(pool, sizeof(tee_mm_entry_t)); if (!mm) return NULL; exceptions = cpu_spin_lock_xsave(&pool->lock); entry = pool->entry; offslo = (base - pool->lo) >> pool->shift; offshi = ((base - pool->lo + size - 1) >> pool->shift) + 1; /* find slot */ if (pool->flags & TEE_MM_POOL_HI_ALLOC) { while (entry->next != NULL && offshi < entry->next->offset + entry->next->size) entry = entry->next; } else { while (entry->next != NULL && offslo > entry->next->offset) entry = entry->next; } /* Check that memory is available */ if (!fit_in_gap(pool, entry, offslo, offshi)) goto err; tee_mm_add(entry, mm); mm->offset = offslo; mm->size = offshi - offslo; mm->pool = pool; update_max_allocated(pool); cpu_spin_unlock_xrestore(&pool->lock, exceptions); return mm; err: cpu_spin_unlock_xrestore(&pool->lock, exceptions); pfree(pool, mm); return NULL; } void tee_mm_free(tee_mm_entry_t *p) { tee_mm_entry_t *entry; uint32_t exceptions; if (!p || !p->pool) return; exceptions = cpu_spin_lock_xsave(&p->pool->lock); entry = p->pool->entry; /* remove entry from list */ while (entry->next != NULL && entry->next != p) entry = entry->next; if (!entry->next) panic("invalid mm_entry"); entry->next = entry->next->next; cpu_spin_unlock_xrestore(&p->pool->lock, exceptions); pfree(p->pool, p); } size_t tee_mm_get_bytes(const tee_mm_entry_t *mm) { if (!mm || !mm->pool) return 0; else return mm->size << mm->pool->shift; } bool tee_mm_addr_is_within_range(const tee_mm_pool_t *pool, paddr_t addr) { return pool && addr >= pool->lo && addr <= (pool->lo + (pool->size - 1)); } bool tee_mm_is_empty(tee_mm_pool_t *pool) { bool ret; uint32_t exceptions; if (pool == NULL || pool->entry == NULL) return true; exceptions = cpu_spin_lock_xsave(&pool->lock); ret = pool->entry == NULL || pool->entry->next == NULL; cpu_spin_unlock_xrestore(&pool->lock, exceptions); return ret; } tee_mm_entry_t *tee_mm_find(const tee_mm_pool_t *pool, paddr_t addr) { tee_mm_entry_t *entry = pool->entry; uint16_t offset = (addr - pool->lo) >> pool->shift; uint32_t exceptions; if (!tee_mm_addr_is_within_range(pool, addr)) return NULL; exceptions = cpu_spin_lock_xsave(&((tee_mm_pool_t *)pool)->lock); while (entry->next != NULL) { entry = entry->next; if ((offset >= entry->offset) && (offset < (entry->offset + entry->size))) { cpu_spin_unlock_xrestore(&((tee_mm_pool_t *)pool)->lock, exceptions); return entry; } } cpu_spin_unlock_xrestore(&((tee_mm_pool_t *)pool)->lock, exceptions); return NULL; } uintptr_t tee_mm_get_smem(const tee_mm_entry_t *mm) { return (mm->offset << mm->pool->shift) + mm->pool->lo; } optee_os-4.3.0/core/mm/vm.c000066400000000000000000000777671464416617300155260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2021, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2021, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CFG_PL310 #include #endif #define TEE_MMU_UDATA_ATTR (TEE_MATTR_VALID_BLOCK | \ TEE_MATTR_PRW | TEE_MATTR_URW | \ TEE_MATTR_SECURE) #define TEE_MMU_UCODE_ATTR (TEE_MATTR_VALID_BLOCK | \ TEE_MATTR_PRW | TEE_MATTR_URWX | \ TEE_MATTR_SECURE) #define TEE_MMU_UCACHE_DEFAULT_ATTR (TEE_MATTR_MEM_TYPE_CACHED << \ TEE_MATTR_MEM_TYPE_SHIFT) static vaddr_t select_va_in_range(const struct vm_region *prev_reg, const struct vm_region *next_reg, const struct vm_region *reg, size_t pad_begin, size_t pad_end, size_t granul) { const uint32_t f = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT | VM_FLAG_SHAREABLE; vaddr_t begin_va = 0; vaddr_t end_va = 0; size_t pad = 0; /* * Insert an unmapped entry to separate regions with differing * VM_FLAG_EPHEMERAL, VM_FLAG_PERMANENT or VM_FLAG_SHAREABLE * bits as they never are to be contiguous with another region. */ if (prev_reg->flags && (prev_reg->flags & f) != (reg->flags & f)) pad = SMALL_PAGE_SIZE; else pad = 0; #ifndef CFG_WITH_LPAE if ((prev_reg->attr & TEE_MATTR_SECURE) != (reg->attr & TEE_MATTR_SECURE)) granul = CORE_MMU_PGDIR_SIZE; #endif if (ADD_OVERFLOW(prev_reg->va, prev_reg->size, &begin_va) || ADD_OVERFLOW(begin_va, pad_begin, &begin_va) || ADD_OVERFLOW(begin_va, pad, &begin_va) || ROUNDUP_OVERFLOW(begin_va, granul, &begin_va)) return 0; if (reg->va) { if (reg->va < begin_va) return 0; begin_va = reg->va; } if (next_reg->flags && (next_reg->flags & f) != (reg->flags & f)) pad = SMALL_PAGE_SIZE; else pad = 0; #ifndef CFG_WITH_LPAE if ((next_reg->attr & TEE_MATTR_SECURE) != (reg->attr & TEE_MATTR_SECURE)) granul = CORE_MMU_PGDIR_SIZE; #endif if (ADD_OVERFLOW(begin_va, reg->size, &end_va) || ADD_OVERFLOW(end_va, pad_end, &end_va) || ADD_OVERFLOW(end_va, pad, &end_va) || ROUNDUP_OVERFLOW(end_va, granul, &end_va)) return 0; if (end_va <= next_reg->va) { assert(!reg->va || reg->va == begin_va); return begin_va; } return 0; } static TEE_Result alloc_pgt(struct user_mode_ctx *uctx) { struct thread_specific_data *tsd __maybe_unused; if (!pgt_check_avail(uctx)) { EMSG("Page tables are not available"); return TEE_ERROR_OUT_OF_MEMORY; } #ifdef CFG_PAGED_USER_TA tsd = thread_get_tsd(); if (uctx->ts_ctx == tsd->ctx) { /* * The supplied utc is the current active utc, allocate the * page tables too as the pager needs to use them soon. */ pgt_get_all(uctx); } #endif return TEE_SUCCESS; } static void rem_um_region(struct user_mode_ctx *uctx, struct vm_region *r) { vaddr_t begin = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); vaddr_t last = ROUNDUP(r->va + r->size, CORE_MMU_PGDIR_SIZE); struct vm_region *r2 = NULL; if (mobj_is_paged(r->mobj)) { tee_pager_rem_um_region(uctx, r->va, r->size); } else { pgt_clear_range(uctx, r->va, r->va + r->size); tlbi_va_range_asid(r->va, r->size, SMALL_PAGE_SIZE, uctx->vm_info.asid); } /* * Figure out how much virtual memory on a CORE_MMU_PGDIR_SIZE * grunalarity can be freed. Only completely unused * CORE_MMU_PGDIR_SIZE ranges can be supplied to pgt_flush_range(). * * Note that there's is no margin for error here, both flushing too * many or too few translation tables can be fatal. */ r2 = TAILQ_NEXT(r, link); if (r2) last = MIN(last, ROUNDDOWN(r2->va, CORE_MMU_PGDIR_SIZE)); r2 = TAILQ_PREV(r, vm_region_head, link); if (r2) begin = MAX(begin, ROUNDUP(r2->va + r2->size, CORE_MMU_PGDIR_SIZE)); if (begin < last) pgt_flush_range(uctx, begin, last); } static void set_pa_range(struct core_mmu_table_info *ti, vaddr_t va, paddr_t pa, size_t size, uint32_t attr) { unsigned int end = core_mmu_va2idx(ti, va + size); unsigned int idx = core_mmu_va2idx(ti, va); while (idx < end) { core_mmu_set_entry(ti, idx, pa, attr); idx++; pa += BIT64(ti->shift); } } static void set_reg_in_table(struct core_mmu_table_info *ti, struct vm_region *r) { vaddr_t va = MAX(r->va, ti->va_base); vaddr_t end = MIN(r->va + r->size, ti->va_base + CORE_MMU_PGDIR_SIZE); size_t sz = MIN(end - va, mobj_get_phys_granule(r->mobj)); size_t granule = BIT(ti->shift); size_t offset = 0; paddr_t pa = 0; while (va < end) { offset = va - r->va + r->offset; if (mobj_get_pa(r->mobj, offset, granule, &pa)) panic("Failed to get PA"); set_pa_range(ti, va, pa, sz, r->attr); va += sz; } } static void set_um_region(struct user_mode_ctx *uctx, struct vm_region *r) { struct pgt *p = SLIST_FIRST(&uctx->pgt_cache); struct core_mmu_table_info ti = { }; assert(!mobj_is_paged(r->mobj)); core_mmu_set_info_table(&ti, CORE_MMU_PGDIR_LEVEL, 0, NULL); if (p) { /* All the pgts are already allocated, update in place */ do { ti.va_base = p->vabase; ti.table = p->tbl; set_reg_in_table(&ti, r); p = SLIST_NEXT(p, link); } while (p); } else { /* * We may have a few pgts in the cache list, update the * ones found. */ for (ti.va_base = ROUNDDOWN(r->va, CORE_MMU_PGDIR_SIZE); ti.va_base < r->va + r->size; ti.va_base += CORE_MMU_PGDIR_SIZE) { p = pgt_pop_from_cache_list(ti.va_base, uctx->ts_ctx); if (!p) continue; ti.table = p->tbl; set_reg_in_table(&ti, r); pgt_push_to_cache_list(p); } } } static TEE_Result umap_add_region(struct vm_info *vmi, struct vm_region *reg, size_t pad_begin, size_t pad_end, size_t align) { struct vm_region dummy_first_reg = { }; struct vm_region dummy_last_reg = { }; struct vm_region *r = NULL; struct vm_region *prev_r = NULL; vaddr_t va_range_base = 0; size_t va_range_size = 0; size_t granul; vaddr_t va = 0; size_t offs_plus_size = 0; core_mmu_get_user_va_range(&va_range_base, &va_range_size); dummy_first_reg.va = va_range_base; dummy_last_reg.va = va_range_base + va_range_size; /* Check alignment, it has to be at least SMALL_PAGE based */ if ((reg->va | reg->size | pad_begin | pad_end) & SMALL_PAGE_MASK) return TEE_ERROR_ACCESS_CONFLICT; /* Check that the mobj is defined for the entire range */ if (ADD_OVERFLOW(reg->offset, reg->size, &offs_plus_size)) return TEE_ERROR_BAD_PARAMETERS; if (offs_plus_size > ROUNDUP(reg->mobj->size, SMALL_PAGE_SIZE)) return TEE_ERROR_BAD_PARAMETERS; granul = MAX(align, SMALL_PAGE_SIZE); if (!IS_POWER_OF_TWO(granul)) return TEE_ERROR_BAD_PARAMETERS; prev_r = &dummy_first_reg; TAILQ_FOREACH(r, &vmi->regions, link) { va = select_va_in_range(prev_r, r, reg, pad_begin, pad_end, granul); if (va) { reg->va = va; TAILQ_INSERT_BEFORE(r, reg, link); return TEE_SUCCESS; } prev_r = r; } r = TAILQ_LAST(&vmi->regions, vm_region_head); if (!r) r = &dummy_first_reg; va = select_va_in_range(r, &dummy_last_reg, reg, pad_begin, pad_end, granul); if (va) { reg->va = va; TAILQ_INSERT_TAIL(&vmi->regions, reg, link); return TEE_SUCCESS; } return TEE_ERROR_ACCESS_CONFLICT; } TEE_Result vm_map_pad(struct user_mode_ctx *uctx, vaddr_t *va, size_t len, uint32_t prot, uint32_t flags, struct mobj *mobj, size_t offs, size_t pad_begin, size_t pad_end, size_t align) { TEE_Result res = TEE_SUCCESS; struct vm_region *reg = NULL; uint32_t attr = 0; if (prot & ~TEE_MATTR_PROT_MASK) return TEE_ERROR_BAD_PARAMETERS; reg = calloc(1, sizeof(*reg)); if (!reg) return TEE_ERROR_OUT_OF_MEMORY; if (!mobj_is_paged(mobj)) { uint32_t mem_type = 0; res = mobj_get_mem_type(mobj, &mem_type); if (res) goto err_free_reg; attr |= mem_type << TEE_MATTR_MEM_TYPE_SHIFT; } attr |= TEE_MATTR_VALID_BLOCK; if (mobj_is_secure(mobj)) attr |= TEE_MATTR_SECURE; reg->mobj = mobj_get(mobj); reg->offset = offs; reg->va = *va; reg->size = ROUNDUP(len, SMALL_PAGE_SIZE); reg->attr = attr | prot; reg->flags = flags; res = umap_add_region(&uctx->vm_info, reg, pad_begin, pad_end, align); if (res) goto err_put_mobj; res = alloc_pgt(uctx); if (res) goto err_rem_reg; if (mobj_is_paged(mobj)) { struct fobj *fobj = mobj_get_fobj(mobj); if (!fobj) { res = TEE_ERROR_GENERIC; goto err_rem_reg; } res = tee_pager_add_um_region(uctx, reg->va, fobj, prot); fobj_put(fobj); if (res) goto err_rem_reg; } else { set_um_region(uctx, reg); } /* * If the context currently is active set it again to update * the mapping. */ if (thread_get_tsd()->ctx == uctx->ts_ctx) vm_set_ctx(uctx->ts_ctx); *va = reg->va; return TEE_SUCCESS; err_rem_reg: TAILQ_REMOVE(&uctx->vm_info.regions, reg, link); err_put_mobj: mobj_put(reg->mobj); err_free_reg: free(reg); return res; } static struct vm_region *find_vm_region(struct vm_info *vm_info, vaddr_t va) { struct vm_region *r = NULL; TAILQ_FOREACH(r, &vm_info->regions, link) if (va >= r->va && va < r->va + r->size) return r; return NULL; } static bool va_range_is_contiguous(struct vm_region *r0, vaddr_t va, size_t len, bool (*cmp_regs)(const struct vm_region *r0, const struct vm_region *r, const struct vm_region *rn)) { struct vm_region *r = r0; vaddr_t end_va = 0; if (ADD_OVERFLOW(va, len, &end_va)) return false; while (true) { struct vm_region *r_next = TAILQ_NEXT(r, link); vaddr_t r_end_va = r->va + r->size; if (r_end_va >= end_va) return true; if (!r_next) return false; if (r_end_va != r_next->va) return false; if (cmp_regs && !cmp_regs(r0, r, r_next)) return false; r = r_next; } } static TEE_Result split_vm_region(struct user_mode_ctx *uctx, struct vm_region *r, vaddr_t va) { struct vm_region *r2 = NULL; size_t diff = va - r->va; assert(diff && diff < r->size); r2 = calloc(1, sizeof(*r2)); if (!r2) return TEE_ERROR_OUT_OF_MEMORY; if (mobj_is_paged(r->mobj)) { TEE_Result res = tee_pager_split_um_region(uctx, va); if (res) { free(r2); return res; } } r2->mobj = mobj_get(r->mobj); r2->offset = r->offset + diff; r2->va = va; r2->size = r->size - diff; r2->attr = r->attr; r2->flags = r->flags; r->size = diff; TAILQ_INSERT_AFTER(&uctx->vm_info.regions, r, r2, link); return TEE_SUCCESS; } static TEE_Result split_vm_range(struct user_mode_ctx *uctx, vaddr_t va, size_t len, bool (*cmp_regs)(const struct vm_region *r0, const struct vm_region *r, const struct vm_region *rn), struct vm_region **r0_ret) { TEE_Result res = TEE_SUCCESS; struct vm_region *r = NULL; vaddr_t end_va = 0; if ((va | len) & SMALL_PAGE_MASK) return TEE_ERROR_BAD_PARAMETERS; if (ADD_OVERFLOW(va, len, &end_va)) return TEE_ERROR_BAD_PARAMETERS; /* * Find first vm_region in range and check that the entire range is * contiguous. */ r = find_vm_region(&uctx->vm_info, va); if (!r || !va_range_is_contiguous(r, va, len, cmp_regs)) return TEE_ERROR_BAD_PARAMETERS; /* * If needed split regions so that va and len covers only complete * regions. */ if (va != r->va) { res = split_vm_region(uctx, r, va); if (res) return res; r = TAILQ_NEXT(r, link); } *r0_ret = r; r = find_vm_region(&uctx->vm_info, va + len - 1); if (!r) return TEE_ERROR_BAD_PARAMETERS; if (end_va != r->va + r->size) { res = split_vm_region(uctx, r, end_va); if (res) return res; } return TEE_SUCCESS; } static void merge_vm_range(struct user_mode_ctx *uctx, vaddr_t va, size_t len) { struct vm_region *r_next = NULL; struct vm_region *r = NULL; vaddr_t end_va = 0; if (ADD_OVERFLOW(va, len, &end_va)) return; tee_pager_merge_um_region(uctx, va, len); for (r = TAILQ_FIRST(&uctx->vm_info.regions);; r = r_next) { r_next = TAILQ_NEXT(r, link); if (!r_next) return; /* Try merging with the region just before va */ if (r->va + r->size < va) continue; /* * If r->va is well past our range we're done. * Note that if it's just the page after our range we'll * try to merge. */ if (r->va > end_va) return; if (r->va + r->size != r_next->va) continue; if (r->mobj != r_next->mobj || r->flags != r_next->flags || r->attr != r_next->attr) continue; if (r->offset + r->size != r_next->offset) continue; TAILQ_REMOVE(&uctx->vm_info.regions, r_next, link); r->size += r_next->size; mobj_put(r_next->mobj); free(r_next); r_next = r; } } static bool cmp_region_for_remap(const struct vm_region *r0, const struct vm_region *r, const struct vm_region *rn) { /* * All the essentionals has to match for remap to make sense. The * essentials are, mobj/fobj, attr, flags and the offset should be * contiguous. * * Note that vm_remap() depends on mobj/fobj to be the same. */ return r0->flags == r->flags && r0->attr == r->attr && r0->mobj == r->mobj && rn->offset == r->offset + r->size; } TEE_Result vm_remap(struct user_mode_ctx *uctx, vaddr_t *new_va, vaddr_t old_va, size_t len, size_t pad_begin, size_t pad_end) { struct vm_region_head regs = TAILQ_HEAD_INITIALIZER(regs); TEE_Result res = TEE_SUCCESS; struct vm_region *r0 = NULL; struct vm_region *r = NULL; struct vm_region *r_next = NULL; struct vm_region *r_last = NULL; struct vm_region *r_first = NULL; struct fobj *fobj = NULL; vaddr_t next_va = 0; assert(thread_get_tsd()->ctx == uctx->ts_ctx); if (!len || ((len | old_va) & SMALL_PAGE_MASK)) return TEE_ERROR_BAD_PARAMETERS; res = split_vm_range(uctx, old_va, len, cmp_region_for_remap, &r0); if (res) return res; if (mobj_is_paged(r0->mobj)) { fobj = mobj_get_fobj(r0->mobj); if (!fobj) panic(); } for (r = r0; r; r = r_next) { if (r->va + r->size > old_va + len) break; r_next = TAILQ_NEXT(r, link); rem_um_region(uctx, r); TAILQ_REMOVE(&uctx->vm_info.regions, r, link); TAILQ_INSERT_TAIL(®s, r, link); } /* * Synchronize change to translation tables. Even though the pager * case unmaps immediately we may still free a translation table. */ vm_set_ctx(uctx->ts_ctx); r_first = TAILQ_FIRST(®s); while (!TAILQ_EMPTY(®s)) { r = TAILQ_FIRST(®s); TAILQ_REMOVE(®s, r, link); if (r_last) { r->va = r_last->va + r_last->size; res = umap_add_region(&uctx->vm_info, r, 0, 0, 0); } else { r->va = *new_va; res = umap_add_region(&uctx->vm_info, r, pad_begin, pad_end + len - r->size, 0); } if (!res) { r_last = r; res = alloc_pgt(uctx); } if (!res) { if (!fobj) set_um_region(uctx, r); else res = tee_pager_add_um_region(uctx, r->va, fobj, r->attr); } if (res) { /* * Something went wrong move all the recently added * regions back to regs for later reinsertion at * the original spot. */ struct vm_region *r_tmp = NULL; struct vm_region *r_stop = NULL; if (r != r_last) { /* * umap_add_region() failed, move r back to * regs before all the rest are moved back. */ TAILQ_INSERT_HEAD(®s, r, link); } if (r_last) r_stop = TAILQ_NEXT(r_last, link); for (r = r_first; r != r_stop; r = r_next) { r_next = TAILQ_NEXT(r, link); TAILQ_REMOVE(&uctx->vm_info.regions, r, link); if (r_tmp) TAILQ_INSERT_AFTER(®s, r_tmp, r, link); else TAILQ_INSERT_HEAD(®s, r, link); r_tmp = r; } goto err_restore_map; } } fobj_put(fobj); vm_set_ctx(uctx->ts_ctx); *new_va = r_first->va; return TEE_SUCCESS; err_restore_map: next_va = old_va; while (!TAILQ_EMPTY(®s)) { r = TAILQ_FIRST(®s); TAILQ_REMOVE(®s, r, link); r->va = next_va; next_va += r->size; if (umap_add_region(&uctx->vm_info, r, 0, 0, 0)) panic("Cannot restore mapping"); if (alloc_pgt(uctx)) panic("Cannot restore mapping"); if (fobj) { if (tee_pager_add_um_region(uctx, r->va, fobj, r->attr)) panic("Cannot restore mapping"); } else { set_um_region(uctx, r); } } fobj_put(fobj); vm_set_ctx(uctx->ts_ctx); return res; } static bool cmp_region_for_get_flags(const struct vm_region *r0, const struct vm_region *r, const struct vm_region *rn __unused) { return r0->flags == r->flags; } TEE_Result vm_get_flags(struct user_mode_ctx *uctx, vaddr_t va, size_t len, uint32_t *flags) { struct vm_region *r = NULL; if (!len || ((len | va) & SMALL_PAGE_MASK)) return TEE_ERROR_BAD_PARAMETERS; r = find_vm_region(&uctx->vm_info, va); if (!r) return TEE_ERROR_BAD_PARAMETERS; if (!va_range_is_contiguous(r, va, len, cmp_region_for_get_flags)) return TEE_ERROR_BAD_PARAMETERS; *flags = r->flags; return TEE_SUCCESS; } static bool cmp_region_for_get_prot(const struct vm_region *r0, const struct vm_region *r, const struct vm_region *rn __unused) { return (r0->attr & TEE_MATTR_PROT_MASK) == (r->attr & TEE_MATTR_PROT_MASK); } TEE_Result vm_get_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, uint16_t *prot) { struct vm_region *r = NULL; if (!len || ((len | va) & SMALL_PAGE_MASK)) return TEE_ERROR_BAD_PARAMETERS; r = find_vm_region(&uctx->vm_info, va); if (!r) return TEE_ERROR_BAD_PARAMETERS; if (!va_range_is_contiguous(r, va, len, cmp_region_for_get_prot)) return TEE_ERROR_BAD_PARAMETERS; *prot = r->attr & TEE_MATTR_PROT_MASK; return TEE_SUCCESS; } TEE_Result vm_set_prot(struct user_mode_ctx *uctx, vaddr_t va, size_t len, uint32_t prot) { TEE_Result res = TEE_SUCCESS; struct vm_region *r0 = NULL; struct vm_region *r = NULL; bool was_writeable = false; bool need_sync = false; assert(thread_get_tsd()->ctx == uctx->ts_ctx); if (prot & ~TEE_MATTR_PROT_MASK || !len) return TEE_ERROR_BAD_PARAMETERS; res = split_vm_range(uctx, va, len, NULL, &r0); if (res) return res; for (r = r0; r; r = TAILQ_NEXT(r, link)) { if (r->va + r->size > va + len) break; if (r->attr & (TEE_MATTR_UW | TEE_MATTR_PW)) was_writeable = true; r->attr &= ~TEE_MATTR_PROT_MASK; r->attr |= prot; if (!mobj_is_paged(r->mobj)) { need_sync = true; set_um_region(uctx, r); /* * Normally when set_um_region() is called we * change from no mapping to some mapping, but in * this case we change the permissions on an * already present mapping so some TLB invalidation * is needed. We also depend on the dsb() performed * as part of the TLB invalidation. */ tlbi_va_range_asid(r->va, r->size, SMALL_PAGE_SIZE, uctx->vm_info.asid); } } for (r = r0; r; r = TAILQ_NEXT(r, link)) { if (r->va + r->size > va + len) break; if (mobj_is_paged(r->mobj)) { if (!tee_pager_set_um_region_attr(uctx, r->va, r->size, prot)) panic(); } else if (was_writeable) { cache_op_inner(DCACHE_AREA_CLEAN, (void *)r->va, r->size); } } if (need_sync && was_writeable) cache_op_inner(ICACHE_INVALIDATE, NULL, 0); merge_vm_range(uctx, va, len); return TEE_SUCCESS; } static void umap_remove_region(struct vm_info *vmi, struct vm_region *reg) { TAILQ_REMOVE(&vmi->regions, reg, link); mobj_put(reg->mobj); free(reg); } TEE_Result vm_unmap(struct user_mode_ctx *uctx, vaddr_t va, size_t len) { TEE_Result res = TEE_SUCCESS; struct vm_region *r = NULL; struct vm_region *r_next = NULL; size_t end_va = 0; size_t unmap_end_va = 0; size_t l = 0; assert(thread_get_tsd()->ctx == uctx->ts_ctx); if (ROUNDUP_OVERFLOW(len, SMALL_PAGE_SIZE, &l)) return TEE_ERROR_BAD_PARAMETERS; if (!l || (va & SMALL_PAGE_MASK)) return TEE_ERROR_BAD_PARAMETERS; if (ADD_OVERFLOW(va, l, &end_va)) return TEE_ERROR_BAD_PARAMETERS; res = split_vm_range(uctx, va, l, NULL, &r); if (res) return res; while (true) { r_next = TAILQ_NEXT(r, link); unmap_end_va = r->va + r->size; rem_um_region(uctx, r); umap_remove_region(&uctx->vm_info, r); if (!r_next || unmap_end_va == end_va) break; r = r_next; } return TEE_SUCCESS; } static TEE_Result map_kinit(struct user_mode_ctx *uctx) { TEE_Result res = TEE_SUCCESS; struct mobj *mobj = NULL; size_t offs = 0; vaddr_t va = 0; size_t sz = 0; uint32_t prot = 0; thread_get_user_kcode(&mobj, &offs, &va, &sz); if (sz) { prot = TEE_MATTR_PRX; if (IS_ENABLED(CFG_CORE_BTI)) prot |= TEE_MATTR_GUARDED; res = vm_map(uctx, &va, sz, prot, VM_FLAG_PERMANENT, mobj, offs); if (res) return res; } thread_get_user_kdata(&mobj, &offs, &va, &sz); if (sz) return vm_map(uctx, &va, sz, TEE_MATTR_PRW, VM_FLAG_PERMANENT, mobj, offs); return TEE_SUCCESS; } TEE_Result vm_info_init(struct user_mode_ctx *uctx, struct ts_ctx *ts_ctx) { TEE_Result res; uint32_t asid = asid_alloc(); if (!asid) { DMSG("Failed to allocate ASID"); return TEE_ERROR_GENERIC; } memset(uctx, 0, sizeof(*uctx)); TAILQ_INIT(&uctx->vm_info.regions); SLIST_INIT(&uctx->pgt_cache); uctx->vm_info.asid = asid; uctx->ts_ctx = ts_ctx; res = map_kinit(uctx); if (res) vm_info_final(uctx); return res; } void vm_clean_param(struct user_mode_ctx *uctx) { struct vm_region *next_r; struct vm_region *r; TAILQ_FOREACH_SAFE(r, &uctx->vm_info.regions, link, next_r) { if (r->flags & VM_FLAG_EPHEMERAL) { rem_um_region(uctx, r); umap_remove_region(&uctx->vm_info, r); } } } static void check_param_map_empty(struct user_mode_ctx *uctx __maybe_unused) { struct vm_region *r = NULL; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) assert(!(r->flags & VM_FLAG_EPHEMERAL)); } static TEE_Result param_mem_to_user_va(struct user_mode_ctx *uctx, struct param_mem *mem, void **user_va) { struct vm_region *region = NULL; TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { vaddr_t va = 0; size_t phys_offs = 0; if (!(region->flags & VM_FLAG_EPHEMERAL)) continue; if (mem->mobj != region->mobj) continue; phys_offs = mobj_get_phys_offs(mem->mobj, CORE_MMU_USER_PARAM_SIZE); phys_offs += mem->offs; if (phys_offs < region->offset) continue; if (phys_offs >= (region->offset + region->size)) continue; va = region->va + phys_offs - region->offset; *user_va = (void *)va; return TEE_SUCCESS; } return TEE_ERROR_GENERIC; } static int cmp_param_mem(const void *a0, const void *a1) { const struct param_mem *m1 = a1; const struct param_mem *m0 = a0; int ret; /* Make sure that invalid param_mem are placed last in the array */ if (!m0->mobj && !m1->mobj) return 0; if (!m0->mobj) return 1; if (!m1->mobj) return -1; ret = CMP_TRILEAN(mobj_is_secure(m0->mobj), mobj_is_secure(m1->mobj)); if (ret) return ret; ret = CMP_TRILEAN((vaddr_t)m0->mobj, (vaddr_t)m1->mobj); if (ret) return ret; ret = CMP_TRILEAN(m0->offs, m1->offs); if (ret) return ret; return CMP_TRILEAN(m0->size, m1->size); } TEE_Result vm_map_param(struct user_mode_ctx *uctx, struct tee_ta_param *param, void *param_va[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; size_t n; size_t m; struct param_mem mem[TEE_NUM_PARAMS]; memset(mem, 0, sizeof(mem)); for (n = 0; n < TEE_NUM_PARAMS; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); size_t phys_offs; if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; phys_offs = mobj_get_phys_offs(param->u[n].mem.mobj, CORE_MMU_USER_PARAM_SIZE); mem[n].mobj = param->u[n].mem.mobj; mem[n].offs = ROUNDDOWN(phys_offs + param->u[n].mem.offs, CORE_MMU_USER_PARAM_SIZE); mem[n].size = ROUNDUP(phys_offs + param->u[n].mem.offs - mem[n].offs + param->u[n].mem.size, CORE_MMU_USER_PARAM_SIZE); /* * For size 0 (raw pointer parameter), add minimum size * value to allow address to be mapped */ if (!mem[n].size) mem[n].size = CORE_MMU_USER_PARAM_SIZE; } /* * Sort arguments so NULL mobj is last, secure mobjs first, then by * mobj pointer value since those entries can't be merged either, * finally by offset. * * This should result in a list where all mergeable entries are * next to each other and unused/invalid entries are at the end. */ qsort(mem, TEE_NUM_PARAMS, sizeof(struct param_mem), cmp_param_mem); for (n = 1, m = 0; n < TEE_NUM_PARAMS && mem[n].mobj; n++) { if (mem[n].mobj == mem[m].mobj && (mem[n].offs == (mem[m].offs + mem[m].size) || core_is_buffer_intersect(mem[m].offs, mem[m].size, mem[n].offs, mem[n].size))) { mem[m].size = mem[n].offs + mem[n].size - mem[m].offs; continue; } m++; if (n != m) mem[m] = mem[n]; } /* * We'd like 'm' to be the number of valid entries. Here 'm' is the * index of the last valid entry if the first entry is valid, else * 0. */ if (mem[0].mobj) m++; check_param_map_empty(uctx); for (n = 0; n < m; n++) { vaddr_t va = 0; res = vm_map(uctx, &va, mem[n].size, TEE_MATTR_PRW | TEE_MATTR_URW, VM_FLAG_EPHEMERAL | VM_FLAG_SHAREABLE, mem[n].mobj, mem[n].offs); if (res) goto out; } for (n = 0; n < TEE_NUM_PARAMS; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; if (!param->u[n].mem.mobj) continue; res = param_mem_to_user_va(uctx, ¶m->u[n].mem, param_va + n); if (res != TEE_SUCCESS) goto out; } res = alloc_pgt(uctx); out: if (res) vm_clean_param(uctx); return res; } void vm_info_final(struct user_mode_ctx *uctx) { if (!uctx->vm_info.asid) return; pgt_flush(uctx); tee_pager_rem_um_regions(uctx); /* clear MMU entries to avoid clash when asid is reused */ tlbi_asid(uctx->vm_info.asid); asid_free(uctx->vm_info.asid); uctx->vm_info.asid = 0; while (!TAILQ_EMPTY(&uctx->vm_info.regions)) umap_remove_region(&uctx->vm_info, TAILQ_FIRST(&uctx->vm_info.regions)); } /* return true only if buffer fits inside TA private memory */ bool vm_buf_is_inside_um_private(const struct user_mode_ctx *uctx, const void *va, size_t size) { struct vm_region *r = NULL; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { if (r->flags & VM_FLAGS_NONPRIV) continue; if (core_is_buffer_inside((vaddr_t)va, size, r->va, r->size)) return true; } return false; } /* return true only if buffer intersects TA private memory */ bool vm_buf_intersects_um_private(const struct user_mode_ctx *uctx, const void *va, size_t size) { struct vm_region *r = NULL; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { if (r->attr & VM_FLAGS_NONPRIV) continue; if (core_is_buffer_intersect((vaddr_t)va, size, r->va, r->size)) return true; } return false; } TEE_Result vm_buf_to_mboj_offs(const struct user_mode_ctx *uctx, const void *va, size_t size, struct mobj **mobj, size_t *offs) { struct vm_region *r = NULL; TAILQ_FOREACH(r, &uctx->vm_info.regions, link) { if (!r->mobj) continue; if (core_is_buffer_inside((vaddr_t)va, size, r->va, r->size)) { size_t poffs; poffs = mobj_get_phys_offs(r->mobj, CORE_MMU_USER_PARAM_SIZE); *mobj = r->mobj; *offs = (vaddr_t)va - r->va + r->offset - poffs; return TEE_SUCCESS; } } return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result tee_mmu_user_va2pa_attr(const struct user_mode_ctx *uctx, void *ua, paddr_t *pa, uint32_t *attr) { struct vm_region *region = NULL; TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { if (!core_is_buffer_inside((vaddr_t)ua, 1, region->va, region->size)) continue; if (pa) { TEE_Result res; paddr_t p; size_t offset; size_t granule; /* * mobj and input user address may each include * a specific offset-in-granule position. * Drop both to get target physical page base * address then apply only user address * offset-in-granule. * Mapping lowest granule is the small page. */ granule = MAX(region->mobj->phys_granule, (size_t)SMALL_PAGE_SIZE); assert(!granule || IS_POWER_OF_TWO(granule)); offset = region->offset + ROUNDDOWN((vaddr_t)ua - region->va, granule); res = mobj_get_pa(region->mobj, offset, granule, &p); if (res != TEE_SUCCESS) return res; *pa = p | ((vaddr_t)ua & (granule - 1)); } if (attr) *attr = region->attr; return TEE_SUCCESS; } return TEE_ERROR_ACCESS_DENIED; } TEE_Result vm_va2pa(const struct user_mode_ctx *uctx, void *ua, paddr_t *pa) { return tee_mmu_user_va2pa_attr(uctx, ua, pa, NULL); } void *vm_pa2va(const struct user_mode_ctx *uctx, paddr_t pa, size_t pa_size) { paddr_t p = 0; struct vm_region *region = NULL; TAILQ_FOREACH(region, &uctx->vm_info.regions, link) { size_t granule = 0; size_t size = 0; size_t ofs = 0; /* pa2va is expected only for memory tracked through mobj */ if (!region->mobj) continue; /* Physically granulated memory object must be scanned */ granule = region->mobj->phys_granule; assert(!granule || IS_POWER_OF_TWO(granule)); for (ofs = region->offset; ofs < region->size; ofs += size) { if (granule) { /* From current offset to buffer/granule end */ size = granule - (ofs & (granule - 1)); if (size > (region->size - ofs)) size = region->size - ofs; } else { size = region->size; } if (mobj_get_pa(region->mobj, ofs, granule, &p)) continue; if (core_is_buffer_inside(pa, pa_size, p, size)) { /* Remove region offset (mobj phys offset) */ ofs -= region->offset; /* Get offset-in-granule */ p = pa - p; return (void *)(region->va + ofs + (vaddr_t)p); } } } return NULL; } TEE_Result vm_check_access_rights(const struct user_mode_ctx *uctx, uint32_t flags, uaddr_t uaddr, size_t len) { uaddr_t a = 0; uaddr_t end_addr = 0; size_t addr_incr = MIN(CORE_MMU_USER_CODE_SIZE, CORE_MMU_USER_PARAM_SIZE); if (ADD_OVERFLOW(uaddr, len, &end_addr)) return TEE_ERROR_ACCESS_DENIED; if ((flags & TEE_MEMORY_ACCESS_NONSECURE) && (flags & TEE_MEMORY_ACCESS_SECURE)) return TEE_ERROR_ACCESS_DENIED; /* * Rely on TA private memory test to check if address range is private * to TA or not. */ if (!(flags & TEE_MEMORY_ACCESS_ANY_OWNER) && !vm_buf_is_inside_um_private(uctx, (void *)uaddr, len)) return TEE_ERROR_ACCESS_DENIED; for (a = ROUNDDOWN(uaddr, addr_incr); a < end_addr; a += addr_incr) { uint32_t attr; TEE_Result res; res = tee_mmu_user_va2pa_attr(uctx, (void *)a, NULL, &attr); if (res != TEE_SUCCESS) return res; if ((flags & TEE_MEMORY_ACCESS_NONSECURE) && (attr & TEE_MATTR_SECURE)) return TEE_ERROR_ACCESS_DENIED; if ((flags & TEE_MEMORY_ACCESS_SECURE) && !(attr & TEE_MATTR_SECURE)) return TEE_ERROR_ACCESS_DENIED; if ((flags & TEE_MEMORY_ACCESS_WRITE) && !(attr & TEE_MATTR_UW)) return TEE_ERROR_ACCESS_DENIED; if ((flags & TEE_MEMORY_ACCESS_READ) && !(attr & TEE_MATTR_UR)) return TEE_ERROR_ACCESS_DENIED; } return TEE_SUCCESS; } void vm_set_ctx(struct ts_ctx *ctx) { struct thread_specific_data *tsd = thread_get_tsd(); struct user_mode_ctx *uctx = NULL; core_mmu_set_user_map(NULL); if (is_user_mode_ctx(tsd->ctx)) { /* * We're coming from a user mode context so we must make * the pgts available for reuse. */ uctx = to_user_mode_ctx(tsd->ctx); pgt_put_all(uctx); } if (is_user_mode_ctx(ctx)) { struct core_mmu_user_map map = { }; uctx = to_user_mode_ctx(ctx); core_mmu_create_user_map(uctx, &map); core_mmu_set_user_map(&map); tee_pager_assign_um_tables(uctx); } tsd->ctx = ctx; } struct mobj *vm_get_mobj(struct user_mode_ctx *uctx, vaddr_t va, size_t *len, uint16_t *prot, size_t *offs) { struct vm_region *r = NULL; size_t r_offs = 0; if (!len || ((*len | va) & SMALL_PAGE_MASK)) return NULL; r = find_vm_region(&uctx->vm_info, va); if (!r) return NULL; r_offs = va - r->va; *len = MIN(r->size - r_offs, *len); *offs = r->offset + r_offs; *prot = r->attr & TEE_MATTR_PROT_MASK; return mobj_get(r->mobj); } optee_os-4.3.0/core/pta/000077500000000000000000000000001464416617300150635ustar00rootroot00000000000000optee_os-4.3.0/core/pta/apdu.c000066400000000000000000000041601464416617300161610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) Foundries Ltd. 2021 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #define PTA_NAME "pta.apdu" static TEE_Result get_apdu_type(uint32_t val, enum crypto_apdu_type *type) { switch (val) { case PTA_APDU_TXRX_CASE_NO_HINT: *type = CRYPTO_APDU_CASE_NO_HINT; break; case PTA_APDU_TXRX_CASE_1: *type = CRYPTO_APDU_CASE_1; break; case PTA_APDU_TXRX_CASE_2: *type = CRYPTO_APDU_CASE_2; break; case PTA_APDU_TXRX_CASE_2E: *type = CRYPTO_APDU_CASE_2E; break; case PTA_APDU_TXRX_CASE_3: *type = CRYPTO_APDU_CASE_3; break; case PTA_APDU_TXRX_CASE_3E: *type = CRYPTO_APDU_CASE_3E; break; case PTA_APDU_TXRX_CASE_4: *type = CRYPTO_APDU_CASE_4; break; case PTA_APDU_TXRX_CASE_4E: *type = CRYPTO_APDU_CASE_4E; break; default: return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result invoke_command(void *session_context __unused, uint32_t command_id, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT); enum crypto_apdu_type type = CRYPTO_APDU_CASE_NO_HINT; TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED; size_t len = 0; FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; switch (command_id) { case PTA_CMD_TXRX_APDU_RAW_FRAME: ret = get_apdu_type(params[0].value.a, &type); if (ret) return ret; len = params[3].memref.size; ret = crypto_se_do_apdu(type, params[1].memref.buffer, params[1].memref.size, params[2].memref.buffer, params[2].memref.size, params[3].memref.buffer, &len); if (!ret) params[3].memref.size = len; break; default: return TEE_ERROR_NOT_IMPLEMENTED; } return ret; } pseudo_ta_register(.uuid = PTA_APDU_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/attestation.c000066400000000000000000000447371464416617300176050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2021, Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define PTA_NAME "attestation.pta" #define MAX_KEY_SIZE 4096 static TEE_UUID pta_uuid = PTA_ATTESTATION_UUID; static struct rsa_keypair *key; static const uint8_t key_file_name[] = "key"; static TEE_Result allocate_key(void) { assert(!key); key = calloc(1, sizeof(*key)); if (!key) return TEE_ERROR_OUT_OF_MEMORY; COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE <= MAX_KEY_SIZE); return crypto_acipher_alloc_rsa_keypair(key, MAX_KEY_SIZE); } static void free_key(void) { crypto_acipher_free_rsa_keypair(key); free(key); key = NULL; } static TEE_Result generate_key(void) { uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537); TEE_Result res = TEE_ERROR_GENERIC; res = allocate_key(); if (res) goto err; res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key->e); if (res) goto err; /* * For security reasons, the RSA modulus size has to be at least the * size of the data to be signed. */ DMSG("Generating %u bit RSA key pair", CFG_ATTESTATION_PTA_KEY_SIZE); COMPILE_TIME_ASSERT(CFG_ATTESTATION_PTA_KEY_SIZE >= TEE_SHA256_HASH_SIZE); res = crypto_acipher_gen_rsa_key(key, CFG_ATTESTATION_PTA_KEY_SIZE); if (!res) goto out; err: free_key(); out: return res; } /* * Return values: * > 0 : Number of bytes written to buf * 0 : @sz too large (> UINT16_MAX) or @buf_sz too small */ static size_t serialize_bignum(uint8_t *buf, size_t buf_sz, struct bignum *bn) { uint8_t *p = buf; size_t sz = crypto_bignum_num_bytes(bn); uint16_t val = TEE_U16_TO_BIG_ENDIAN(sz); size_t total_sz = sizeof(val) + sz; if (sz > UINT16_MAX || total_sz > buf_sz) return 0; memcpy(p, &val, sizeof(val)); p += sizeof(val); crypto_bignum_bn2bin(bn, p); return total_sz; } static size_t bufsize(size_t e_sz, size_t d_sz, size_t n_sz) { /* * Serialized key pair is 3 bignums (e, p and n) plus their sizes * encoded as uint16_t. */ return e_sz + d_sz + n_sz + 3 * sizeof(uint16_t); } static TEE_Result serialize_key(uint8_t *buf, size_t size) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *p = buf; size_t needed_sz = 0; size_t e_sz = 0; size_t d_sz = 0; size_t n_sz = 0; size_t sz = 0; assert(key); e_sz = crypto_bignum_num_bytes(key->e); d_sz = crypto_bignum_num_bytes(key->d); n_sz = crypto_bignum_num_bytes(key->n); if (e_sz > UINT16_MAX || d_sz > UINT16_MAX || n_sz > UINT16_MAX) goto err; needed_sz = bufsize(e_sz, d_sz, n_sz); if (size < needed_sz) goto err; sz = serialize_bignum(p, needed_sz, key->e); if (!sz) goto err; p += sz; needed_sz -= sz; sz = serialize_bignum(p, needed_sz, key->d); if (!sz) goto err; p += sz; needed_sz -= sz; sz = serialize_bignum(p, needed_sz, key->n); if (!sz) goto err; needed_sz -= sz; assert(!needed_sz); return TEE_SUCCESS; err: return res; } static size_t deserialize_bignum(uint8_t *buf, size_t max_sz, struct bignum *bn) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *p = buf; uint16_t val = 0; size_t sz = 0; if (max_sz < sizeof(val)) return 0; memcpy(&val, p, sizeof(val)); sz = TEE_U16_FROM_BIG_ENDIAN(val); p += sizeof(val); max_sz -= sizeof(val); if (max_sz < sz) return 0; res = crypto_bignum_bin2bn(p, sz, bn); if (res) return 0; return sizeof(val) + sz; } static TEE_Result deserialize_key(uint8_t *buf, size_t buf_sz) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *p = buf; size_t sz = 0; res = allocate_key(); if (res) return res; sz = deserialize_bignum(p, buf_sz, key->e); if (!sz) goto err; p += sz; buf_sz -= sz; sz = deserialize_bignum(p, buf_sz, key->d); if (!sz) goto err; p += sz; buf_sz -= sz; sz = deserialize_bignum(p, buf_sz, key->n); if (!sz) goto err; return TEE_SUCCESS; err: free_key(); return TEE_ERROR_GENERIC; } static TEE_Result sec_storage_obj_read(TEE_UUID *uuid, uint32_t storage_id, const uint8_t *obj_id, size_t obj_id_len, uint8_t *data, size_t *len, size_t offset, uint32_t flags) { const struct tee_file_operations *fops = NULL; TEE_Result res = TEE_ERROR_BAD_STATE; struct tee_file_handle *fh = NULL; struct tee_pobj *po = NULL; size_t file_size = 0; size_t read_len = 0; fops = tee_svc_storage_file_ops(storage_id); if (!fops) return TEE_ERROR_NOT_IMPLEMENTED; if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, &po); if (res) return res; res = po->fops->open(po, &file_size, &fh); if (res) goto out; read_len = *len; res = po->fops->read(fh, offset, data, NULL, &read_len); if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); po->fops->remove(po); } else if (!res) { *len = read_len; } po->fops->close(&fh); out: tee_pobj_release(po); return res; } static TEE_Result sec_storage_obj_write(TEE_UUID *uuid, uint32_t storage_id, const uint8_t *obj_id, size_t obj_id_len, const uint8_t *data, size_t len, size_t offset, uint32_t flags) { const struct tee_file_operations *fops = NULL; struct tee_file_handle *fh = NULL; TEE_Result res = TEE_SUCCESS; struct tee_pobj *po = NULL; fops = tee_svc_storage_file_ops(storage_id); if (!fops) return TEE_ERROR_NOT_IMPLEMENTED; if (obj_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; res = tee_pobj_get(uuid, (void *)obj_id, obj_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, &po); if (res) return res; res = po->fops->open(po, NULL, &fh); if (res == TEE_ERROR_ITEM_NOT_FOUND) res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, NULL, 0, &fh); if (!res) { res = po->fops->write(fh, offset, data, NULL, len); po->fops->close(&fh); } tee_pobj_release(po); return res; } static TEE_Result load_key(uint8_t *buf, size_t size) { TEE_Result res = TEE_ERROR_GENERIC; DMSG("Loading RSA key pair from secure storage"); res = sec_storage_obj_read(&pta_uuid, TEE_STORAGE_PRIVATE, key_file_name, sizeof(key_file_name) - 1, buf, &size, 0, TEE_DATA_FLAG_ACCESS_READ); if (res) return res; DMSG("Read %zu bytes", size); res = deserialize_key(buf, size); if (!res) DMSG("Loaded %zu bit key pair", crypto_bignum_num_bits(key->n)); return res; } static TEE_Result write_key(uint8_t *buf, size_t size) { TEE_Result res = TEE_ERROR_GENERIC; DMSG("Saving key pair"); res = serialize_key(buf, size); if (res) return res; res = sec_storage_obj_write(&pta_uuid, TEE_STORAGE_PRIVATE, key_file_name, sizeof(key_file_name) - 1, buf, size, 0, TEE_DATA_FLAG_ACCESS_WRITE); if (!res) DMSG("Wrote %zu bytes", size); return res; } static TEE_Result init_key(void) { TEE_Result res = TEE_SUCCESS; uint8_t *buf = NULL; size_t size = 0; if (!key) { /* * e is 65537 so its bignum size is 3 bytes. d and n can be up * to MAX_KEY_SIZE bits. */ size = bufsize(3, MAX_KEY_SIZE / 8, MAX_KEY_SIZE / 8); buf = calloc(1, size); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = load_key(buf, size); if (res == TEE_ERROR_ITEM_NOT_FOUND) { res = generate_key(); if (res) goto out; res = write_key(buf, size); } } out: free(buf); return res; } static TEE_Result cmd_get_pubkey(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *e = params[0].memref.buffer; size_t *e_out_sz = ¶ms[0].memref.size; uint8_t *n = params[1].memref.buffer; size_t *n_out_sz = ¶ms[1].memref.size; size_t sz = 0; if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; res = init_key(); if (res) return res; sz = crypto_bignum_num_bytes(key->e); if (*e_out_sz >= sz) crypto_bignum_bn2bin(key->e, e); else res = TEE_ERROR_SHORT_BUFFER; *e_out_sz = sz; sz = crypto_bignum_num_bytes(key->n); if (*n_out_sz >= sz) crypto_bignum_bn2bin(key->n, n); else res = TEE_ERROR_SHORT_BUFFER; *n_out_sz = sz; params[2].value.a = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256; return res; } static TEE_Result hash_binary(const TEE_UUID *uuid, uint8_t *hash) { TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND; unsigned int tag_len = FILE_TAG_SIZE; const struct ts_store_ops *ops = NULL; struct ts_store_handle *h = NULL; SCATTERED_ARRAY_FOREACH(ops, ta_stores, struct ts_store_ops) { res = ops->open(uuid, &h); if (!res) break; /* TA found */ } if (res) return res; /* * Output hash size is assumed to be the same size as the file tag * size which is the size of the digest in the TA shdr. If one or the * other changes, additional hashing will be needed. */ COMPILE_TIME_ASSERT(FILE_TAG_SIZE == TEE_SHA256_HASH_SIZE); assert(ops); res = ops->get_tag(h, hash, &tag_len); if (res) goto out; DMSG("TA %pUl hash:", uuid); DHEXDUMP(hash, TEE_SHA256_HASH_SIZE); out: ops->close(h); return res; } /* Hash @nonce and @hash into @digest */ static TEE_Result digest_nonce_and_hash(uint8_t *digest, uint8_t *nonce, size_t nonce_sz, uint8_t *hash) { TEE_Result res = TEE_SUCCESS; void *ctx = NULL; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); if (res) return res; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, nonce, nonce_sz); if (res) goto out; res = crypto_hash_update(ctx, hash, TEE_SHA256_HASH_SIZE); if (res) goto out; res = crypto_hash_final(ctx, digest, TEE_SHA256_HASH_SIZE); out: crypto_hash_free_ctx(ctx); return res; } static TEE_Result sign_digest(uint8_t *sig, size_t sig_len, const uint8_t *digest) { return crypto_acipher_rsassa_sign(TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, key, TEE_SHA256_HASH_SIZE, /* salt len */ digest, TEE_SHA256_HASH_SIZE, sig, &sig_len); } /* * Sign the first 32 bytes contained in @buf and append signature * out = [ hash | sig(sha256(nonce | hash)) ] * ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ * 32B modulus size */ static TEE_Result sign_buffer(uint8_t *buf, size_t buf_sz, uint8_t *nonce, size_t nonce_sz) { uint8_t digest[TEE_SHA256_HASH_SIZE] = { }; TEE_Result res = TEE_SUCCESS; res = digest_nonce_and_hash(digest, nonce, nonce_sz, buf); if (res) return res; return sign_digest(buf + TEE_SHA256_HASH_SIZE, buf_sz - TEE_SHA256_HASH_SIZE, digest); } /* * Is region valid for hashing? * Exclude writable regions as well as those that are not specific to the TA * (ldelf, kernel or temporary mappings). */ static bool is_region_valid(struct vm_region *r) { uint32_t dontwant = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT | VM_FLAG_LDELF; uint32_t want = VM_FLAG_READONLY; return ((r->flags & want) == want && !(r->flags & dontwant)); } /* * With this comparison function, we're hashing the smaller regions first. * Regions of equal size are ordered based on their content (memcmp()). * Identical regions can be in any order since they will yield the same hash * anyways. */ static int cmp_regions(const void *a, const void *b) { const struct vm_region *r1 = *(const struct vm_region **)a; const struct vm_region *r2 = *(const struct vm_region **)b; if (r1->size < r2->size) return -1; if (r1->size > r2->size) return 1; return memcmp((void *)r1->va, (void *)r2->va, r1->size); } static TEE_Result hash_regions(struct vm_info *vm_info, uint8_t *hash) { TEE_Result res = TEE_SUCCESS; struct vm_region *r = NULL; struct vm_region **regions = NULL; size_t nregions = 0; void *ctx = NULL; size_t i = 0; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); if (res) return res; res = crypto_hash_init(ctx); if (res) goto out; /* * Make an array of region pointers so we can use qsort() to order it. */ TAILQ_FOREACH(r, &vm_info->regions, link) if (is_region_valid(r)) nregions++; regions = malloc(nregions * sizeof(*regions)); if (!regions) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } TAILQ_FOREACH(r, &vm_info->regions, link) if (is_region_valid(r)) regions[i++] = r; enter_user_access(); /* * Sort regions so that they are in a consistent order even when TA ASLR * is enabled. */ qsort(regions, nregions, sizeof(*regions), cmp_regions); /* Hash regions in order */ for (i = 0; i < nregions; i++) { r = regions[i]; DMSG("va %p size %zu", (void *)r->va, r->size); res = crypto_hash_update(ctx, (uint8_t *)r->va, r->size); if (res) break; } exit_user_access(); if (res) goto out; res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE); out: free(regions); crypto_hash_free_ctx(ctx); return res; } static TEE_Result cmd_get_ta_shdr_digest(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_UUID *uuid = params[0].memref.buffer; size_t uuid_sz = params[0].memref.size; uint8_t *nonce = params[1].memref.buffer; size_t nonce_sz = params[1].memref.size; uint8_t *out = params[2].memref.buffer; size_t out_sz = params[2].memref.size; size_t min_out_sz = 0; TEE_Result res = TEE_SUCCESS; if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; if (uuid_sz != sizeof(*uuid)) return TEE_ERROR_BAD_PARAMETERS; if (!nonce || !nonce_sz) return TEE_ERROR_BAD_PARAMETERS; if (!out && out_sz) return TEE_ERROR_BAD_PARAMETERS; res = init_key(); if (res) return res; min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n); params[2].memref.size = min_out_sz; if (out_sz < min_out_sz) return TEE_ERROR_SHORT_BUFFER; out_sz = min_out_sz; res = hash_binary(uuid, out); if (res) return res; return sign_buffer(out, out_sz, nonce, nonce_sz); } static TEE_Result cmd_hash_ta_memory(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t *nonce = params[0].memref.buffer; size_t nonce_sz = params[0].memref.size; uint8_t *out = params[1].memref.buffer; size_t out_sz = params[1].memref.size; struct user_mode_ctx *uctx = NULL; TEE_Result res = TEE_SUCCESS; struct ts_session *s = NULL; size_t min_out_sz = 0; if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; if (!nonce || !nonce_sz) return TEE_ERROR_BAD_PARAMETERS; if (!out && out_sz) return TEE_ERROR_BAD_PARAMETERS; /* Check that we're called from a user TA */ s = ts_get_calling_session(); if (!s) return TEE_ERROR_ACCESS_DENIED; uctx = to_user_mode_ctx(s->ctx); if (!uctx) return TEE_ERROR_ACCESS_DENIED; res = init_key(); if (res) return res; min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n); params[1].memref.size = min_out_sz; if (out_sz < min_out_sz) return TEE_ERROR_SHORT_BUFFER; out_sz = min_out_sz; s = ts_pop_current_session(); res = hash_regions(&uctx->vm_info, out); ts_push_current_session(s); if (res) return res; return sign_buffer(out, out_sz, nonce, nonce_sz); } static TEE_Result cmd_hash_tee_memory(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t *nonce = params[0].memref.buffer; size_t nonce_sz = params[0].memref.size; uint8_t *out = params[1].memref.buffer; size_t out_sz = params[1].memref.size; TEE_Result res = TEE_SUCCESS; size_t min_out_sz = 0; void *ctx = NULL; if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; if (!nonce || !nonce_sz) return TEE_ERROR_BAD_PARAMETERS; if (!out && out_sz) return TEE_ERROR_BAD_PARAMETERS; res = init_key(); if (res) return res; min_out_sz = TEE_SHA256_HASH_SIZE + crypto_bignum_num_bytes(key->n); params[1].memref.size = min_out_sz; if (out_sz < min_out_sz) return TEE_ERROR_SHORT_BUFFER; out_sz = min_out_sz; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256); if (res) return res; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, __text_start, __text_data_start - __text_start); if (res) goto out; res = crypto_hash_update(ctx, __text_data_end, __text_end - __text_data_end); if (IS_ENABLED(CFG_WITH_PAGER)) { res = crypto_hash_update(ctx, __text_init_start, __text_init_end - __text_init_start); if (res) goto out; res = crypto_hash_update(ctx, __text_pageable_start, __text_pageable_end - __text_pageable_start); if (res) goto out; } if (res) goto out; res = crypto_hash_update(ctx, __rodata_start, __rodata_end - __rodata_start); if (res) goto out; if (IS_ENABLED(CFG_WITH_PAGER)) { res = crypto_hash_update(ctx, __rodata_init_start, __rodata_init_end - __rodata_init_start); if (res) goto out; res = crypto_hash_update(ctx, __rodata_pageable_start, __rodata_pageable_end - __rodata_pageable_start); if (res) goto out; } res = crypto_hash_final(ctx, out, TEE_SHA256_HASH_SIZE); if (res) goto out; DHEXDUMP(out, TEE_SHA256_HASH_SIZE); res = sign_buffer(out, out_sz, nonce, nonce_sz); out: crypto_hash_free_ctx(ctx); return res; } static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_BAD_PARAMETERS; TEE_Result res2 = TEE_ERROR_GENERIC; TEE_Param bparams[TEE_NUM_PARAMS] = { }; TEE_Param *eparams = NULL; res = to_bounce_params(param_types, params, bparams, &eparams); if (res) return res; switch (cmd_id) { case PTA_ATTESTATION_GET_PUBKEY: res = cmd_get_pubkey(param_types, eparams); break; case PTA_ATTESTATION_GET_TA_SHDR_DIGEST: res = cmd_get_ta_shdr_digest(param_types, eparams); break; case PTA_ATTESTATION_HASH_TA_MEMORY: res = cmd_hash_ta_memory(param_types, eparams); break; case PTA_ATTESTATION_HASH_TEE_MEMORY: res = cmd_hash_tee_memory(param_types, eparams); break; default: break; } res2 = from_bounce_params(param_types, params, bparams, eparams); if (!res && res2) res = res2; return res; } pseudo_ta_register(.uuid = PTA_ATTESTATION_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/bcm/000077500000000000000000000000001464416617300156245ustar00rootroot00000000000000optee_os-4.3.0/core/pta/bcm/bnxt.c000066400000000000000000000067131464416617300167520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include #define BNXT_SERVICE_UUID \ {0x6272636D, 0x2019, 0x0716, \ {0x42, 0x43, 0x4D, 0x5F, 0x53, 0x43, 0x48, 0x49} } /* * enum pta_bnxt_cmd - commands supported by this PTA * PTA_BNXT_FASTBOOT: boot bnxt device by copying f/w into sram * * PTA_BNXT_HEALTH_STATUS: check health of bnxt device * [out] value[0].a - health status * * PTA_BNXT_HANDSHAKE_STATUS: check bnxt device is booted * [inout] value[0].a - max timeout value * value[0].a - boot status * * PTA_BNXT_CRASH_DUMP_COPY: copy the core dump into shm * [inout] memref[0].buf: destination addr * [in] value[1].a: offset * [in] value[1].b: size */ enum pta_bnxt_cmd { PTA_BNXT_FASTBOOT = 0, PTA_BNXT_HEALTH_STATUS, PTA_BNXT_HANDSHAKE_STATUS, PTA_BNXT_CRASH_DUMP_COPY, }; #define BNXT_TA_NAME "pta_bnxt.ta" static TEE_Result get_bnxt_status(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { if (type != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; p[0].value.a = bnxt_health_status(); return TEE_SUCCESS; } static TEE_Result get_bnxt_handshake_status(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { if (type != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; p[0].value.a = bnxt_wait_handshake(p[0].value.a); return TEE_SUCCESS; } static TEE_Result copy_bnxt_crash_dump(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t *d = NULL; uint32_t offset = 0; uint32_t req_len = 0; TEE_Result res = TEE_SUCCESS; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { DMSG("bad parameters types: 0x%" PRIx32, types); return TEE_ERROR_BAD_PARAMETERS; } d = (uint32_t *)params[0].memref.buffer; offset = params[1].value.a; req_len = params[1].value.b; if (!d || params[0].memref.size < req_len) return TEE_ERROR_BAD_PARAMETERS; res = bnxt_copy_crash_dump((uint8_t *)d, offset, req_len); return res; } static TEE_Result invoke_command(void *session_context __unused, uint32_t cmd_id, uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused) { TEE_Result res = TEE_SUCCESS; DMSG("command entry point[%d] for \"%s\"", cmd_id, BNXT_TA_NAME); switch (cmd_id) { case PTA_BNXT_FASTBOOT: DMSG("bnxt fastboot"); if (bnxt_load_fw(1) != BNXT_SUCCESS) return TEE_ERROR_TARGET_DEAD; break; case PTA_BNXT_HEALTH_STATUS: DMSG("bnxt health status"); return get_bnxt_status(param_types, params); case PTA_BNXT_HANDSHAKE_STATUS: DMSG("bnxt handshake status"); return get_bnxt_handshake_status(param_types, params); case PTA_BNXT_CRASH_DUMP_COPY: DMSG("bnxt copy crash dump data"); return copy_bnxt_crash_dump(param_types, params); default: DMSG("cmd: %d Not supported %s", cmd_id, BNXT_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } return res; } pseudo_ta_register(.uuid = BNXT_SERVICE_UUID, .name = BNXT_TA_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_DEVICE_ENUM, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/bcm/elog.c000066400000000000000000000144221464416617300167210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #include #include #include #define ELOG_SERVICE_UUID \ { 0x6272636D, 0x2019, 0x0701, \ { 0x42, 0x43, 0x4D, 0x5F, 0x45, 0x4C, 0x4F, 0x47 } } #define ELOG_TA_NAME "pta_bcm_elog.ta" #define BCM_NITRO_FW_LOAD_ADDR 0x8ae00000 #define BCM_NITRO_CRASH_DUMP_BASE_ADDR 0x8b000000 /* Default ELOG buffer size 1MB */ #define DEFAULT_ELOG_BUFFER_SIZE 0x100000U /* * Get Error log memory dump * * [out] memref[0]: Destination * [in] value[1].a: Offset */ #define PTA_BCM_ELOG_CMD_GET_ELOG_MEM 1 /* * Get nitro crash_dump memory * * [out] memref[0]: Destination * [in] value[1].a: Offset */ #define PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP 2 /* * Load nitro firmware memory * * [in] memref[0]: Nitro f/w image data * [in] value[1].a: Offset for loading f/w image * [in] value[2].a: Firmware image size */ #define PTA_BCM_ELOG_CMD_LOAD_NITRO_FW 3 #define BCM_ELOG_GLOBAL_METADATA_SIG 0x45524c47 #define MAX_NITRO_CRASH_DUMP_MEM_SIZE 0x2000000 #define MAX_NITRO_FW_LOAD_MEM_SIZE 0x200000 /* Load Nitro fw image to SEC DDR memory */ static TEE_Result pta_elog_load_nitro_fw(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; paddr_t src_paddr = BCM_NITRO_FW_LOAD_ADDR + BNXT_IMG_SECMEM_OFFSET; vaddr_t src_vaddr = 0; uint32_t offset = 0; size_t end_offs = 0; size_t sz = 0; char *buf = NULL; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } /* Check if firmware file size exceeds reserved memory size */ if (params[2].value.a > MAX_NITRO_FW_LOAD_MEM_SIZE) { EMSG("Invalid access"); return TEE_ERROR_EXCESS_DATA; } offset = params[1].value.a; buf = params[0].memref.buffer; sz = params[0].memref.size; /* * Check that we under no circumstances will attempt to write * beyond BCM_NITRO_FW_LOAD_ADDR + MAX_NITRO_FW_LOAD_MEM_SIZE. */ if (ADD_OVERFLOW(sz, offset, &end_offs) || end_offs > MAX_NITRO_FW_LOAD_MEM_SIZE - BNXT_IMG_SECMEM_OFFSET) { EMSG("Invalid access"); return TEE_ERROR_ACCESS_DENIED; } src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset, MEM_AREA_RAM_SEC, sz); if (!src_vaddr) { EMSG("Not enough memory mapped"); return TEE_ERROR_BAD_PARAMETERS; } memcpy((char *)src_vaddr, buf, sz); cache_op_inner(DCACHE_AREA_CLEAN, (void *)src_vaddr, sz); return res; } static uint32_t get_dump_data(vaddr_t src, TEE_Param params[TEE_NUM_PARAMS]) { char *buf = NULL; uint32_t sz = 0; buf = params[0].memref.buffer; sz = params[0].memref.size; /* * If request size exceeds default buf size * override request size to default DEFAULT_ELOG_BUFFER_SIZE */ if (sz > DEFAULT_ELOG_BUFFER_SIZE) sz = DEFAULT_ELOG_BUFFER_SIZE; DMSG("buf %p sz 0x%x", buf, sz); memcpy(buf, (char *)src, sz); params[0].memref.size = sz; return sz; } /* Copy nitro crash dump data */ static TEE_Result pta_elog_nitro_crash_dump(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; paddr_t src_paddr = BCM_NITRO_CRASH_DUMP_BASE_ADDR; vaddr_t src_vaddr = 0; uint32_t offset = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t sz = 0; if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } offset = params[1].value.a; /* * Check if offset is within memory range reserved for nitro crash dump * minus default size of buffer */ if (offset > MAX_NITRO_CRASH_DUMP_MEM_SIZE - DEFAULT_ELOG_BUFFER_SIZE) { EMSG("Invalid access"); return TEE_ERROR_ACCESS_DENIED; } sz = MIN(params[0].memref.size, DEFAULT_ELOG_BUFFER_SIZE); src_vaddr = (vaddr_t)phys_to_virt((uintptr_t)src_paddr + offset, MEM_AREA_RAM_SEC, sz); if (!src_vaddr) { EMSG("Not enough memory mapped"); return TEE_ERROR_BAD_PARAMETERS; } /* TODO : check if NITRO_CRASH_DUMP is available */ cache_op_inner(DCACHE_AREA_INVALIDATE, (void *)src_vaddr, DEFAULT_ELOG_BUFFER_SIZE); get_dump_data(src_vaddr, params); return res; } /* Copy soc error log data */ static TEE_Result pta_elog_dump(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; paddr_t src_paddr = CFG_BCM_ELOG_BASE; vaddr_t src_vaddr = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t sz = 0; if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } sz = MIN(params[0].memref.size, DEFAULT_ELOG_BUFFER_SIZE); src_vaddr = (vaddr_t)phys_to_virt(src_paddr, MEM_AREA_RAM_NSEC, sz); if (!src_vaddr) { EMSG("Not enough memory mapped"); return TEE_ERROR_BAD_PARAMETERS; } /* Validate if Error logs are present */ if ((*(uint32_t *)src_vaddr) != BCM_ELOG_GLOBAL_METADATA_SIG) { EMSG("Elog Not setup"); return TEE_ERROR_NOT_SUPPORTED; } get_dump_data(src_vaddr, params); return res; } static TEE_Result invoke_command(void *session_context __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; DMSG("command entry point[%d] for \"%s\"", cmd_id, ELOG_TA_NAME); switch (cmd_id) { case PTA_BCM_ELOG_CMD_GET_ELOG_MEM: res = pta_elog_dump(param_types, params); break; case PTA_BCM_ELOG_CMD_GET_NITRO_CRASH_DUMP: res = pta_elog_nitro_crash_dump(param_types, params); break; case PTA_BCM_ELOG_CMD_LOAD_NITRO_FW: res = pta_elog_load_nitro_fw(param_types, params); break; default: EMSG("cmd: %d Not supported %s", cmd_id, ELOG_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } return res; } pseudo_ta_register(.uuid = ELOG_SERVICE_UUID, .name = ELOG_TA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/bcm/gpio.c000066400000000000000000000107561464416617300167370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019 Broadcom. */ #include #include #include #include #define GPIO_SERVICE_UUID \ { 0x6272636D, 0x2018, 0x1101, \ { 0x42, 0x43, 0x4D, 0x5F, 0x47, 0x50, 0x49, 0x4F } } /* * Configure GPIO Pin * * [in] value[0].a: gpio pin number * [in] value[0].b: direction to configure */ #define PTA_BCM_GPIO_CMD_CFG 0 /* * Set GPIO pin * * [in] value[0].a: gpio pin number * [in] value[0].b: value drive on pin */ #define PTA_BCM_GPIO_CMD_SET 1 /* * Get GPIO pin * * [in] value[0].a: gpio pin number * [out] value[1].a: value read from gpio pin */ #define PTA_BCM_GPIO_CMD_GET 2 #define GPIO_TA_NAME "pta_bcm_gpio.ta" static TEE_Result pta_gpio_config(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t gpio_num = 0; struct bcm_gpio_chip *bcm_gc = NULL; struct gpio_chip *gc = NULL; bool dir = false; TEE_Result res = TEE_SUCCESS; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } gpio_num = params[0].value.a; dir = params[0].value.b; bcm_gc = bcm_gpio_pin_to_chip(gpio_num); if (!bcm_gc) { EMSG("GPIO %u not supported", gpio_num); return TEE_ERROR_NOT_SUPPORTED; } gc = &bcm_gc->chip; /* Make gpio secure. */ iproc_gpio_set_secure(gpio_num); if (dir) { /* Set GPIO to output with default value to 0 */ gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_OUT); gc->ops->set_value(NULL, gpio_num, 0); } else { gc->ops->set_direction(NULL, gpio_num, GPIO_DIR_IN); } return res; } static TEE_Result pta_gpio_set(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t gpio_num = 0; uint32_t val = 0; TEE_Result res = TEE_SUCCESS; struct bcm_gpio_chip *bcm_gc = NULL; struct gpio_chip *gc = NULL; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } gpio_num = params[0].value.a; val = !!params[0].value.b; bcm_gc = bcm_gpio_pin_to_chip(gpio_num); if (!bcm_gc) { EMSG("GPIO %u not supported", gpio_num); return TEE_ERROR_NOT_SUPPORTED; } gc = &bcm_gc->chip; /* * For setting a value to GPIO Pin, * need to make sure the PIN is configured in * output direction. */ if (gc->ops->get_direction(NULL, gpio_num) != GPIO_DIR_OUT) { EMSG("gpio pin %u is configured as INPUT", gpio_num); return TEE_ERROR_ACCESS_DENIED; } gc->ops->set_value(NULL, gpio_num, val); DMSG("GPIO(%d) value = 0x%08x", gpio_num, gc->ops->get_value(NULL, gpio_num)); return res; } static TEE_Result pta_gpio_get(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t gpio_num = 0; struct bcm_gpio_chip *bcm_gc = NULL; struct gpio_chip *gc = NULL; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } gpio_num = params[0].value.a; bcm_gc = bcm_gpio_pin_to_chip(gpio_num); if (!bcm_gc) { EMSG("GPIO %u not supported", gpio_num); return TEE_ERROR_NOT_SUPPORTED; } gc = &bcm_gc->chip; params[1].value.a = gc->ops->get_value(NULL, gpio_num); DMSG("gpio(%d) value = 0x%08x", gpio_num, params[1].value.a); return TEE_SUCCESS; } static TEE_Result invoke_command(void *session_context __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; DMSG("command entry point[%d] for \"%s\"", cmd_id, GPIO_TA_NAME); switch (cmd_id) { case PTA_BCM_GPIO_CMD_CFG: res = pta_gpio_config(param_types, params); break; case PTA_BCM_GPIO_CMD_SET: res = pta_gpio_set(param_types, params); break; case PTA_BCM_GPIO_CMD_GET: res = pta_gpio_get(param_types, params); break; default: EMSG("cmd: %d Not supported %s", cmd_id, GPIO_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } return res; } pseudo_ta_register(.uuid = GPIO_SERVICE_UUID, .name = GPIO_TA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/bcm/hwrng.c000066400000000000000000000033611464416617300171200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Broadcom */ #include #include #include #include #define HWRNG_SERVICE_UUID \ { 0x6272636D, 0x2019, 0x0201, \ { 0x42, 0x43, 0x4D, 0x5F, 0x52, 0x4E, 0x47, 0x30 } } /* * Get a HW generated random number * * [out] value[0].a: Generated 32-bit random number */ #define PTA_BCM_HWRNG_CMD_GET 0 #define HWRNG_TA_NAME "pta_hwrng.ta" static TEE_Result pta_hwrng_get(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t num_words = 0; uint32_t rnd_num = 0; uint32_t res = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } num_words = bcm_hwrng_read_rng(&rnd_num, 1); if (num_words < 1) { res = TEE_ERROR_NO_DATA; } else { DMSG("Random Value is: 0x%08x", rnd_num); params[0].value.a = rnd_num; res = TEE_SUCCESS; } return res; } static TEE_Result invoke_command(void *session_context __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; DMSG("command entry point[%d] for \"%s\"", cmd_id, HWRNG_TA_NAME); switch (cmd_id) { case PTA_BCM_HWRNG_CMD_GET: res = pta_hwrng_get(param_types, params); break; default: EMSG("cmd: %d Not supported %s", cmd_id, HWRNG_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } return res; } pseudo_ta_register(.uuid = HWRNG_SERVICE_UUID, .name = HWRNG_TA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/bcm/sotp.c000066400000000000000000000047741464416617300167710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Broadcom */ #include #include #include #include #include #define SOTP_SERVICE_UUID \ {0x6272636D, 0x2018, 0x1101, \ {0x42, 0x43, 0x4D, 0x5F, 0x53, 0x4F, 0x54, 0x50} } enum pta_bcm_sotp_cmd { PTA_BCM_SOTP_CMD_READ = 0, PTA_BCM_SOTP_CMD_WRITE, }; #define SOTP_TA_NAME "pta_bcm_sotp.ta" static bool sotp_access_disabled; /** * close_session() - Print a debug message when closing a session and set the * driver to disallow any more pta sessions to connect. * @pSessionContext Unused. */ static void close_session(void *pSessionContext __unused) { DMSG("close entry point for \"%s\"", SOTP_TA_NAME); if (IS_ENABLED(CFG_BCM_SOTP_SINGLE_SESSION)) sotp_access_disabled = true; } static TEE_Result pta_sotp_read(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint64_t sotp_row_value = 0; uint32_t val = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } val = params[0].value.a; bcm_iproc_sotp_mem_read(val, true, &sotp_row_value); reg_pair_from_64(sotp_row_value, ¶ms[1].value.a, ¶ms[1].value.b); return TEE_SUCCESS; } static TEE_Result pta_sotp_write(uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused) { /* Nothing as of now */ return TEE_ERROR_NOT_IMPLEMENTED; } static TEE_Result invoke_command(void *session_context __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; DMSG("command entry point[%d] for \"%s\"", cmd_id, SOTP_TA_NAME); if (IS_ENABLED(CFG_BCM_SOTP_SINGLE_SESSION) && sotp_access_disabled) { DMSG("bcm sotp pta access disabled"); return TEE_ERROR_ACCESS_DENIED; } switch (cmd_id) { case PTA_BCM_SOTP_CMD_READ: res = pta_sotp_read(param_types, params); break; case PTA_BCM_SOTP_CMD_WRITE: res = pta_sotp_write(param_types, params); break; default: EMSG("cmd %d Not supported %s", cmd_id, SOTP_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } return res; } pseudo_ta_register(.uuid = SOTP_SERVICE_UUID, .name = SOTP_TA_NAME, .flags = PTA_DEFAULT_FLAGS, .close_session_entry_point = close_session, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/bcm/sub.mk000066400000000000000000000003001464416617300167370ustar00rootroot00000000000000srcs-$(CFG_BNXT_FW) += bnxt.c srcs-$(CFG_SP805_WDT) += wdt.c srcs-$(CFG_BCM_HWRNG) += hwrng.c srcs-$(CFG_BCM_SOTP) += sotp.c srcs-$(CFG_BCM_GPIO) += gpio.c srcs-$(CFG_BCM_ELOG_DUMP) += elog.c optee_os-4.3.0/core/pta/bcm/wdt.c000066400000000000000000000102071464416617300165660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Broadcom */ #include #include #include #include #include #include #include #define SEC_WD_SERVICE_UUID \ { 0x6272636D, 0x2019, 0x0801, \ { 0x42, 0x43, 0x4D, 0x5F, 0x57, 0x44, 0x54, 0x30 } } #define PTA_BCM_SEC_WD_CMD_CONFIG 0 #define PTA_BCM_SEC_WD_CMD_START 1 #define PTA_BCM_SEC_WD_CMD_PING 2 #define PTA_BCM_SEC_WD_CMD_STOP 3 #define PTA_BCM_SEC_WD_CMD_SET_TIMEOUT 4 #define SEC_WD_TA_NAME "pta_bcm_sec_wd.ta" static struct sp805_wdt_data wd_pd; static void wd_isr_handler(struct wdt_chip *chip __unused) { /* Do nothing */ DMSG("Watchdog ISR handler !!!"); } static TEE_Result pta_wd_config(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t timeout = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } timeout = params[0].value.a; sp805_wdt_init(&wd_pd, SEC_WDT_BASE, SEC_WDT_CLK_HZ, timeout); sp805_register_itr_handler(&wd_pd, GIC_SPI_TO_ITNUM(SEC_WDT_INTR), ITRF_TRIGGER_LEVEL, wd_isr_handler); wd_pd.chip.ops->start(&wd_pd.chip); return TEE_SUCCESS; } static TEE_Result pta_wd_start(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS] __unused) { uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } wd_pd.chip.ops->start(&wd_pd.chip); return TEE_SUCCESS; } static TEE_Result pta_wd_ping(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS] __unused) { uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } wd_pd.chip.ops->ping(&wd_pd.chip); return TEE_SUCCESS; } static TEE_Result pta_wd_stop(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS] __unused) { uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } wd_pd.chip.ops->stop(&wd_pd.chip); return TEE_SUCCESS; } static TEE_Result pta_wd_set_timeout(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t timeout = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_param_types != param_types) { EMSG("Invalid Param types"); return TEE_ERROR_BAD_PARAMETERS; } timeout = params[0].value.a; wd_pd.chip.ops->set_timeout(&wd_pd.chip, timeout); return TEE_SUCCESS; } static TEE_Result invoke_command(void *session_context __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; DMSG("command entry point[%d] for \"%s\"", cmd_id, SEC_WD_TA_NAME); switch (cmd_id) { case PTA_BCM_SEC_WD_CMD_CONFIG: res = pta_wd_config(param_types, params); break; case PTA_BCM_SEC_WD_CMD_START: res = pta_wd_start(param_types, params); break; case PTA_BCM_SEC_WD_CMD_PING: res = pta_wd_ping(param_types, params); break; case PTA_BCM_SEC_WD_CMD_STOP: res = pta_wd_stop(param_types, params); break; case PTA_BCM_SEC_WD_CMD_SET_TIMEOUT: res = pta_wd_set_timeout(param_types, params); break; default: EMSG("cmd: %d Not supported %s", cmd_id, SEC_WD_TA_NAME); res = TEE_ERROR_NOT_SUPPORTED; break; } return res; } pseudo_ta_register(.uuid = SEC_WD_SERVICE_UUID, .name = SEC_WD_TA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/device.c000066400000000000000000000050131464416617300164650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited */ /* * This pseudo TA is used by normal world OS TEE driver to fetch pseudo TA's * UUIDs which can act as TEE bus devices. */ #include #include #include #include #include #include #include #include #include #define PTA_NAME "device.pta" static void add_ta(uint32_t flags, const TEE_UUID *uuid, uint8_t *buf, uint32_t blen, uint32_t *pos, uint32_t rflags) { if ((flags & TA_FLAG_DEVICE_ENUM) && (flags & TA_FLAG_DEVICE_ENUM_SUPP)) { EMSG(PTA_NAME ": skipping TA %pUl, inconsistent flags", uuid); return; } if (flags & rflags) { if (*pos + sizeof(*uuid) <= blen) tee_uuid_to_octets(buf + *pos, uuid); *pos += sizeof(*uuid); } } static TEE_Result get_devices(uint32_t types, TEE_Param params[TEE_NUM_PARAMS], uint32_t rflags) { const struct pseudo_ta_head *ta = NULL; const struct embedded_ts *eta = NULL; void *buf = NULL; uint32_t blen = 0; uint32_t pos = 0; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; if (!params[0].memref.buffer && (params[0].memref.size > 0)) return TEE_ERROR_BAD_PARAMETERS; buf = params[0].memref.buffer; blen = params[0].memref.size; SCATTERED_ARRAY_FOREACH(ta, pseudo_tas, struct pseudo_ta_head) add_ta(ta->flags, &ta->uuid, buf, blen, &pos, rflags); if (stmm_get_uuid()) add_ta(TA_FLAG_DEVICE_ENUM_SUPP, stmm_get_uuid(), buf, blen, &pos, rflags); if (IS_ENABLED(CFG_EARLY_TA)) for_each_early_ta(eta) add_ta(eta->flags, &eta->uuid, buf, blen, &pos, rflags); params[0].memref.size = pos; if (pos > blen) return TEE_ERROR_SHORT_BUFFER; return TEE_SUCCESS; } static TEE_Result invoke_command(void *pSessionContext __unused, uint32_t nCommandID, uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]) { switch (nCommandID) { case PTA_CMD_GET_DEVICES: return get_devices(nParamTypes, pParams, TA_FLAG_DEVICE_ENUM); case PTA_CMD_GET_DEVICES_SUPP: return get_devices(nParamTypes, pParams, TA_FLAG_DEVICE_ENUM_SUPP); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_DEVICE_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/gprof.c000066400000000000000000000107771464416617300163600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include static TEE_Result gprof_send_rpc(TEE_UUID *uuid, void *buf, size_t len, uint32_t *id) { struct thread_param params[3] = { }; struct mobj *mobj; TEE_Result res = TEE_ERROR_GENERIC; char *va; mobj = thread_rpc_alloc_payload(sizeof(*uuid) + len); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; va = mobj_get_va(mobj, 0, sizeof(*uuid) + len); if (!va) goto exit; memcpy(va, uuid, sizeof(*uuid)); memcpy(va + sizeof(*uuid), buf, len); params[0] = THREAD_PARAM_VALUE(INOUT, *id, 0, 0); params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, sizeof(*uuid)); params[2] = THREAD_PARAM_MEMREF(IN, mobj, sizeof(*uuid), len); res = thread_rpc_cmd(OPTEE_RPC_CMD_GPROF, 3, params); if (res != TEE_SUCCESS) goto exit; *id = (uint32_t)params[0].u.value.a; exit: thread_rpc_free_payload(mobj); return res; } static TEE_Result gprof_send(struct ts_session *s, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; return gprof_send_rpc(&s->ctx->uuid, params[1].memref.buffer, params[1].memref.size, ¶ms[0].value.a); } static TEE_Result gprof_start_pc_sampling(struct ts_session *s, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct sample_buf *sbuf = NULL; uint32_t offset = 0; uint32_t scale = 0; uint32_t len = 0; uaddr_t buf = 0; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (s->sbuf) { DMSG("PC sampling already started"); return TEE_ERROR_BAD_STATE; } buf = (uaddr_t)params[0].memref.buffer; len = params[0].memref.size; offset = params[1].value.a; scale = params[1].value.b; sbuf = calloc(1, sizeof(*sbuf)); if (!sbuf) return TEE_ERROR_OUT_OF_MEMORY; sbuf->samples = (uint16_t *)buf; sbuf->nsamples = len / sizeof(*sbuf->samples); sbuf->offset = offset; sbuf->scale = scale; sbuf->freq = read_cntfrq(); sbuf->enabled = true; s->sbuf = sbuf; return TEE_SUCCESS; } static TEE_Result gprof_stop_pc_sampling(struct ts_session *s, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct sample_buf *sbuf = NULL; uint32_t rate = 0; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; sbuf = s->sbuf; if (!sbuf) return TEE_ERROR_BAD_STATE; assert(sbuf->samples); /* Stop sampling */ if (sbuf->enabled) sbuf->enabled = false; rate = ((uint64_t)sbuf->count * sbuf->freq) / sbuf->usr; params[0].value.a = rate; DMSG("TA sampling stats: sample count=%" PRIu32 " user time=%" PRIu64 " cntfrq=%" PRIu32 " rate=%" PRIu32, sbuf->count, sbuf->usr, sbuf->freq, rate); free(sbuf); s->sbuf = NULL; return TEE_SUCCESS; } /* * Trusted Application Entry Points */ static TEE_Result open_session(uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused, void **sess_ctx __unused) { struct ts_session *s = ts_get_calling_session(); /* Check that we're called from a user TA */ if (!s) return TEE_ERROR_ACCESS_DENIED; if (!is_user_ta_ctx(s->ctx)) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct ts_session *s = ts_get_calling_session(); switch (cmd_id) { case PTA_GPROF_SEND: return gprof_send(s, param_types, params); case PTA_GPROF_START_PC_SAMPLING: return gprof_start_pc_sampling(s, param_types, params); case PTA_GPROF_STOP_PC_SAMPLING: return gprof_stop_pc_sampling(s, param_types, params); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_GPROF_UUID, .name = "gprof", .flags = PTA_DEFAULT_FLAGS, .open_session_entry_point = open_session, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/hwrng.c000066400000000000000000000037431464416617300163630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, Linaro Limited * Copyright (c) 2021, EPAM Systems. All rights reserved. * * Based on plat-synquacer/rng_pta.c * */ #include #include #include #include #include #include #define PTA_NAME "rng.pta" /* This PTA only works with hardware random number generators */ static_assert(!IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)); static TEE_Result rng_get_entropy(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t *e = NULL; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { DMSG("bad parameters types: 0x%" PRIx32, types); return TEE_ERROR_BAD_PARAMETERS; } e = (uint8_t *)params[0].memref.buffer; if (!e) return TEE_ERROR_BAD_PARAMETERS; return crypto_rng_read(e, params[0].memref.size); } static TEE_Result rng_get_info(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { DMSG("bad parameters types: 0x%" PRIx32, types); return TEE_ERROR_BAD_PARAMETERS; } params[0].value.a = CFG_HWRNG_RATE; params[0].value.b = CFG_HWRNG_QUALITY; return TEE_SUCCESS; } static TEE_Result invoke_command(void *session __unused, uint32_t cmd, uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { FMSG(PTA_NAME" command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); switch (cmd) { case PTA_CMD_GET_ENTROPY: return rng_get_entropy(ptypes, params); case PTA_CMD_GET_RNG_INFO: return rng_get_info(ptypes, params); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_RNG_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/imx/000077500000000000000000000000001464416617300156605ustar00rootroot00000000000000optee_os-4.3.0/core/pta/imx/dek_blob.c000066400000000000000000000100561464416617300175670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2019, 2023 NXP */ #include #include #include #include #include #include #include #include #include #define PTA_NAME "dek_blob.pta" /* Blob size padding in bytes */ #define BLOB_PAD_SIZE 48 /* HAB Blob header values */ #define HAB_HDR_TAG 0x81 #define HAB_HDR_V4 0x43 #define HAB_HDR_MODE_CCM 0x66 #define HAB_HDR_ALG_AES 0x55 /* * DEK blobs are stored by the HAB in a secret key blob data structure. Notice * that the HAB supports a set of encryption algorithms, but the encrypted boot * protocol expects AES. The key length is a variable; it can be 128-bit, * 192-bit, or 256-bit. * For more info, see NXP application note AN12056 */ struct dek_blob_header { uint8_t tag; /* Constant identifying HAB struct: 0x81 */ uint8_t len_msb; /* Struct length in 8-bit msb */ uint8_t len_lsb; /* Struct length in 8-bit lsb */ uint8_t par; /* Constant value, HAB version: 0x43 */ uint8_t mode; /* AES encryption CCM mode: 0x66 */ uint8_t alg; /* AES encryption alg: 0x55 */ uint8_t size; /* Unwrapped key value size in bytes */ uint8_t flg; /* Key flags */ }; /* * Generate HAB DEK blob for encrypted boot * * payload [in] Plain text key to encapsulate. * payload_size [in] Plain text key size. Must be 128, 192 or 256 bits. * blob [out] DEK blob. * blob_size [in/out] DEK blob size. */ static TEE_Result do_generate(const uint8_t *payload, size_t payload_size, uint8_t *blob, size_t *blob_size) { struct dek_blob_header *header = NULL; size_t expected_blob_size = 0; size_t dek_size = 0; /* * Prevent against an unexpected padding of dek_blob_header structure * that must remain packed. This structure will be seriailized to a * buffer along the DEK blob. */ static_assert(sizeof(struct dek_blob_header) == 8 * sizeof(uint8_t)); assert(payload && blob && payload_size && blob_size); assert(payload_size == (128 / 8) || payload_size == (192 / 8) || payload_size == (256 / 8)); /* * The DEK size is equals to input key size plus the required blob * padding. The total output size is the DEK size plus its header */ dek_size = payload_size + BLOB_PAD_SIZE; expected_blob_size = sizeof(*header) + dek_size; /* Check that the output buffer has the required size */ if (*blob_size < expected_blob_size) { *blob_size = expected_blob_size; return TEE_ERROR_SHORT_BUFFER; } *blob_size = expected_blob_size; /* Defined header */ header = (struct dek_blob_header *)blob; header->tag = HAB_HDR_TAG; header->len_msb = 0; header->len_lsb = expected_blob_size; header->par = HAB_HDR_V4; header->mode = HAB_HDR_MODE_CCM; header->alg = HAB_HDR_ALG_AES; header->size = payload_size; header->flg = 0; /* Generate DEK */ return caam_dek_generate(payload, payload_size, blob + sizeof(*header), dek_size); } static TEE_Result cmd_dek_generate(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; if (params[0].memref.size != (128 / 8) && params[0].memref.size != (192 / 8) && params[0].memref.size != (256 / 8)) return TEE_ERROR_BAD_PARAMETERS; memset(params[1].memref.buffer, 0, params[1].memref.size); return do_generate(params[0].memref.buffer, params[0].memref.size, params[1].memref.buffer, ¶ms[1].memref.size); } static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd_id) { case PTA_IMX_DEK_BLOB_CMD_GENERATE: return cmd_dek_generate(param_types, params); default: return TEE_ERROR_BAD_PARAMETERS; } } pseudo_ta_register(.uuid = PTA_DEK_BLOB_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/imx/digprog.c000066400000000000000000000015231464416617300174600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP */ #include #include #include #define DIGPROG_PTA_NAME "digprog.pta" static TEE_Result invokeCommandEntryPoint(void *sess_ctx __unused, uint32_t cmd_id __unused, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; params[0].value.a = imx_get_digprog(); params[0].value.b = 0; return TEE_SUCCESS; } pseudo_ta_register(.uuid = PTA_DIGPROG_UUID, .name = DIGPROG_PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invokeCommandEntryPoint); optee_os-4.3.0/core/pta/imx/manufacturing_protection.c000066400000000000000000000062221464416617300231370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2019, 2023 NXP */ #include #include #include #include #include #include #include #define PTA_NAME "manufacturing_protection.pta" static TEE_Result mp_get_public_key(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t *data = NULL; size_t size = 0; TEE_Result res = TEE_ERROR_GENERIC; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; data = params[0].memref.buffer; size = params[0].memref.size; res = caam_mp_export_publickey(data, &size); if (res != TEE_SUCCESS) EMSG("MP public key export failed with code 0x%" PRIx32, res); params[0].memref.size = size; return res; } static TEE_Result mp_signature(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *msg = NULL; uint8_t *sig = NULL; uint8_t *mpmr = NULL; size_t msg_size = 0; size_t sig_size = 0; size_t mpmr_size = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; DMSG("MPSign function"); msg = params[0].memref.buffer; msg_size = params[0].memref.size; sig = params[1].memref.buffer; sig_size = params[1].memref.size; mpmr = params[2].memref.buffer; mpmr_size = params[2].memref.size; memset(sig, 0, sig_size); memset(mpmr, 0, mpmr_size); res = caam_mp_sign(msg, &msg_size, sig, &sig_size); params[1].memref.size = sig_size; if (res != TEE_SUCCESS) { EMSG("Manufacturing Protection signature failed 0x%" PRIx32, res); return res; } res = caam_mp_export_mpmr(mpmr, &mpmr_size); params[2].memref.size = mpmr_size; if (res != TEE_SUCCESS) EMSG("Manufacturing Protection export MPRM failed 0x%" PRIx32, res); return res; } static TEE_Result pta_mp_open_session(uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused, void **sess_ctx __unused) { struct ts_session *s = NULL; if (IS_ENABLED(CFG_NXP_CAAM_MP_NO_ACCESS_CTRL)) return TEE_SUCCESS; s = ts_get_calling_session(); if (!s || !is_user_ta_ctx(s->ctx)) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } static TEE_Result pta_mp_invoke_cmd(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd_id) { case PTA_IMX_MP_CMD_SIGNATURE_MPMR: return mp_signature(param_types, params); case PTA_IMX_MP_CMD_GET_PUBLIC_KEY: return mp_get_public_key(param_types, params); default: return TEE_ERROR_BAD_PARAMETERS; } } pseudo_ta_register(.uuid = PTA_MANUFACT_PROTEC_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .open_session_entry_point = pta_mp_open_session, .invoke_command_entry_point = pta_mp_invoke_cmd); optee_os-4.3.0/core/pta/imx/ocotp.c000066400000000000000000000036721464416617300171600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 NXP */ #include #include #include #include #define OCOTP_PTA_NAME "ocotp.pta" static TEE_Result chip_uid(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t val[IMX_UID_SIZE] = { }; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; /* On i.MX platforms, the chip UID is 64 bits long */ if (params[0].memref.size != sizeof(uint64_t)) return TEE_ERROR_BAD_PARAMETERS; if (tee_otp_get_die_id(val, IMX_UID_SIZE)) return TEE_ERROR_GENERIC; memcpy(params[0].memref.buffer, val, IMX_UID_SIZE); return TEE_SUCCESS; } static TEE_Result read_fuse(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result ret = TEE_ERROR_GENERIC; uint32_t val = 0; uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; params[1].value.a = 0; params[1].value.b = 0; ret = imx_ocotp_read(params[0].value.a, params[0].value.b, &val); if (!ret) params[1].value.a = val; return ret; } static TEE_Result invokeCommandEntryPoint(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd_id) { case PTA_OCOTP_CMD_CHIP_UID: return chip_uid(param_types, params); case PTA_OCOTP_CMD_READ_FUSE: return read_fuse(param_types, params); default: return TEE_ERROR_BAD_PARAMETERS; } } pseudo_ta_register(.uuid = PTA_OCOTP_UUID, .name = OCOTP_PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invokeCommandEntryPoint); optee_os-4.3.0/core/pta/imx/sub.mk000066400000000000000000000002531464416617300170020ustar00rootroot00000000000000srcs-$(CFG_IMX_DIGPROG) += digprog.c srcs-$(CFG_IMX_OCOTP) += ocotp.c srcs-$(CFG_NXP_CAAM_MP_DRV) += manufacturing_protection.c srcs-$(CFG_NXP_CAAM_DEK_DRV) += dek_blob.c optee_os-4.3.0/core/pta/k3/000077500000000000000000000000001464416617300154005ustar00rootroot00000000000000optee_os-4.3.0/core/pta/k3/otp.c000066400000000000000000000061731464416617300163550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Texas Instruments System Control Interface Driver * * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ * Manorit Chawdhry */ #include #include #include #include static TEE_Result write_otp_row(uint32_t param_types, TEE_Param params[4]) { TEE_Result ret = TEE_SUCCESS; const uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); /* * Safely get the invocation parameters */ if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; ret = ti_sci_write_otp_row(params[0].value.a, params[1].value.a, params[1].value.b); if (ret) return ret; DMSG("Written the value: 0x%08"PRIx32, params[1].value.a); return TEE_SUCCESS; } static TEE_Result read_otp_mmr(uint32_t param_types, TEE_Param params[4]) { TEE_Result ret = TEE_SUCCESS; const uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); /* * Safely get the invocation parameters */ if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; ret = ti_sci_read_otp_mmr(params[0].value.a, ¶ms[1].value.a); if (ret) return ret; DMSG("Got the value: 0x%08"PRIx32, params[1].value.a); return TEE_SUCCESS; } static TEE_Result lock_otp_row(uint32_t param_types, TEE_Param params[4]) { TEE_Result ret = TEE_SUCCESS; int hw_write_lock = 0; int hw_read_lock = 0; int soft_lock = 0; const uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); /* * Safely get the invocation parameters */ if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; if (params[0].value.b & K3_OTP_KEYWRITING_SOFT_LOCK) soft_lock = 0x5A; if (params[0].value.b & K3_OTP_KEYWRITING_HW_READ_LOCK) hw_read_lock = 0x5A; if (params[0].value.b & K3_OTP_KEYWRITING_HW_WRITE_LOCK) hw_write_lock = 0x5A; DMSG("hw_write_lock: 0x%#x", hw_write_lock); DMSG("hw_read_lock: 0x%#x", hw_read_lock); DMSG("soft_lock: 0x%#x", soft_lock); ret = ti_sci_lock_otp_row(params[0].value.a, hw_write_lock, hw_read_lock, soft_lock); if (ret) return ret; DMSG("Locked the row: 0x%08"PRIx32, params[1].value.a); return TEE_SUCCESS; } static TEE_Result invoke_command(void *session __unused, uint32_t command, uint32_t param_types, TEE_Param params[4]) { switch (command) { case TA_OTP_KEYWRITING_CMD_READ_MMR: return read_otp_mmr(param_types, params); case TA_OTP_KEYWRITING_CMD_WRITE_ROW: return write_otp_row(param_types, params); case TA_OTP_KEYWRITING_CMD_LOCK_ROW: return lock_otp_row(param_types, params); default: EMSG("Command ID 0x%"PRIx32" is not supported", command); return TEE_ERROR_NOT_SUPPORTED; } } pseudo_ta_register(.uuid = PTA_K3_OTP_KEYWRITING_UUID, .name = PTA_K3_OTP_KEYWRITING_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/k3/sub.mk000066400000000000000000000000471464416617300165230ustar00rootroot00000000000000srcs-$(CFG_K3_OTP_KEYWRITING) += otp.c optee_os-4.3.0/core/pta/rtc.c000066400000000000000000000122231464416617300160170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, Linaro Limited * Copyright (c) 2021, EPAM Systems. All rights reserved. * Copyright (c) 2022, Microchip * */ #include #include #include #include #include #include #define PTA_NAME "rtc.pta" static void rtc_pta_copy_time_from_optee(struct pta_rtc_time *pta_time, struct optee_rtc_time *optee_time) { pta_time->tm_sec = optee_time->tm_sec; pta_time->tm_min = optee_time->tm_min; pta_time->tm_hour = optee_time->tm_hour; pta_time->tm_mday = optee_time->tm_mday; pta_time->tm_mon = optee_time->tm_mon; pta_time->tm_year = optee_time->tm_year; pta_time->tm_wday = optee_time->tm_wday; } static TEE_Result rtc_pta_get_time(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; struct optee_rtc_time time = { }; struct pta_rtc_time *pta_time = NULL; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; pta_time = params[0].memref.buffer; if (!pta_time || params[0].memref.size != sizeof(*pta_time)) return TEE_ERROR_BAD_PARAMETERS; res = rtc_get_time(&time); if (res) return res; rtc_pta_copy_time_from_optee(pta_time, &time); return TEE_SUCCESS; } static TEE_Result rtc_pta_set_time(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { struct optee_rtc_time time = { }; struct pta_rtc_time *pta_time = NULL; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; pta_time = params[0].memref.buffer; if (!pta_time || params[0].memref.size != sizeof(*pta_time)) return TEE_ERROR_BAD_PARAMETERS; time.tm_sec = pta_time->tm_sec; time.tm_min = pta_time->tm_min; time.tm_hour = pta_time->tm_hour; time.tm_mday = pta_time->tm_mday; time.tm_mon = pta_time->tm_mon; time.tm_year = pta_time->tm_year; time.tm_wday = pta_time->tm_wday; return rtc_set_time(&time); } static TEE_Result rtc_pta_set_offset(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; return rtc_set_offset((int32_t)params[0].value.a); } static TEE_Result rtc_pta_get_offset(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; long offset = 0; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; res = rtc_get_offset(&offset); if (res) return res; if (offset > INT32_MAX || offset < INT32_MIN) return TEE_ERROR_OVERFLOW; params[0].value.a = (uint32_t)offset; return res; } static TEE_Result rtc_pta_get_info(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; struct pta_rtc_info *info = NULL; struct optee_rtc_time range_min = { }; struct optee_rtc_time range_max = { }; uint64_t features = 0; if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; info = params[0].memref.buffer; if (!info || params[0].memref.size != sizeof(*info)) return TEE_ERROR_BAD_PARAMETERS; memset(info, 0, sizeof(*info)); res = rtc_get_info(&features, &range_min, &range_max); if (res) return res; info->version = PTA_RTC_INFO_VERSION; if (features & RTC_CORRECTION_FEATURE) info->features |= PTA_RTC_FEATURE_CORRECTION; rtc_pta_copy_time_from_optee(&info->range_min, &range_min); rtc_pta_copy_time_from_optee(&info->range_max, &range_max); return TEE_SUCCESS; } static TEE_Result open_session(uint32_t ptypes __unused, TEE_Param par[TEE_NUM_PARAMS] __unused, void **session __unused) { struct ts_session *ts = ts_get_current_session(); struct tee_ta_session *ta_session = to_ta_session(ts); /* Only REE kernel is allowed to access RTC */ if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } static TEE_Result invoke_command(void *session __unused, uint32_t cmd, uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd) { case PTA_CMD_RTC_GET_INFO: return rtc_pta_get_info(ptypes, params); case PTA_CMD_RTC_GET_TIME: return rtc_pta_get_time(ptypes, params); case PTA_CMD_RTC_SET_TIME: return rtc_pta_set_time(ptypes, params); case PTA_CMD_RTC_GET_OFFSET: return rtc_pta_get_offset(ptypes, params); case PTA_CMD_RTC_SET_OFFSET: return rtc_pta_set_offset(ptypes, params); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_RTC_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, .open_session_entry_point = open_session, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/scmi.c000066400000000000000000000151071464416617300161660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2021, Linaro Limited * Copyright (c) 2019-2021, STMicroelectronics */ #include #include #include #include #include #include #include #include static uint32_t supported_caps(void) { uint32_t caps = 0; if (IS_ENABLED2(_CFG_SCMI_PTA_SMT_HEADER)) caps |= PTA_SCMI_CAPS_SMT_HEADER; if (IS_ENABLED2(_CFG_SCMI_PTA_MSG_HEADER)) caps |= PTA_SCMI_CAPS_MSG_HEADER; return caps; } static TEE_Result cmd_capabilities(uint32_t ptypes, TEE_Param param[TEE_NUM_PARAMS]) { const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (ptypes != exp_ptypes) return TEE_ERROR_BAD_PARAMETERS; param[0].value.a = supported_caps(); param[0].value.b = 0; return TEE_SUCCESS; } static TEE_Result cmd_process_smt_channel(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); unsigned int channel_id = params[0].value.a; if (ptypes != exp_ptypes) return TEE_ERROR_BAD_PARAMETERS; if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { struct scmi_msg_channel *channel = NULL; channel = plat_scmi_get_channel(channel_id); if (!channel) return TEE_ERROR_BAD_PARAMETERS; scmi_smt_threaded_entry(channel_id); return TEE_SUCCESS; } if (IS_ENABLED(CFG_SCMI_SCPFW)) return scmi_server_smt_process_thread(channel_id); return TEE_ERROR_NOT_SUPPORTED; } static TEE_Result cmd_process_smt_message(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); unsigned int channel_id = params[0].value.a; TEE_Param *param1 = params + 1; if (ptypes != exp_ptypes) return TEE_ERROR_BAD_PARAMETERS; if (IS_ENABLED(CFG_SCMI_MSG_SMT)) { struct scmi_msg_channel *channel = NULL; if (param1->memref.size < SMT_BUF_SLOT_SIZE) return TEE_ERROR_BAD_PARAMETERS; channel = plat_scmi_get_channel(channel_id); if (!channel) return TEE_ERROR_BAD_PARAMETERS; /* * Caller provides the buffer, we bind channel to that buffer. * Once message is processed, unbind the buffer since it is * valid only for the current invocation. */ scmi_smt_set_shared_buffer(channel, param1->memref.buffer); scmi_smt_threaded_entry(channel_id); scmi_smt_set_shared_buffer(channel, NULL); return TEE_SUCCESS; } return TEE_ERROR_NOT_SUPPORTED; } static TEE_Result cmd_process_msg_channel(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); unsigned int channel_id = params[0].value.a; void *in_buf = params[1].memref.buffer; size_t in_size = params[1].memref.size; void *out_buf = params[2].memref.buffer; size_t out_size = params[2].memref.size; if (ptypes != exp_pt || !in_buf || !out_buf) return TEE_ERROR_BAD_PARAMETERS; if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS)) { struct scmi_msg_channel *channel = NULL; if (!IS_ENABLED(CFG_SCMI_MSG_SHM_MSG)) return TEE_ERROR_NOT_SUPPORTED; channel = plat_scmi_get_channel(channel_id); if (!channel) return TEE_ERROR_BAD_PARAMETERS; res = scmi_msg_threaded_entry(channel_id, in_buf, in_size, out_buf, &out_size); if (!res) params[2].memref.size = out_size; return res; } if (IS_ENABLED(CFG_SCMI_SCPFW)) { if (!in_buf || !out_buf) return TEE_ERROR_BAD_PARAMETERS; res = scmi_server_msg_process_thread(channel_id, in_buf, in_size, out_buf, &out_size); if (!res) params[2].memref.size = (uint32_t)out_size; return res; } return TEE_ERROR_NOT_SUPPORTED; } static TEE_Result cmd_get_channel_handle(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_ptypes = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); unsigned int channel_id = params[0].value.a; unsigned int caps = params[0].value.b; if (ptypes != exp_ptypes || caps & ~PTA_SCMI_CAPS_MASK) return TEE_ERROR_BAD_PARAMETERS; if (!(caps & supported_caps())) return TEE_ERROR_NOT_SUPPORTED; if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS)) { struct scmi_msg_channel *channel = NULL; channel = plat_scmi_get_channel(channel_id); if (!channel) return TEE_ERROR_BAD_PARAMETERS; channel->threaded = true; params[0].value.a = scmi_smt_channel_handle(channel_id); return TEE_SUCCESS; } if (IS_ENABLED(CFG_SCMI_SCPFW)) { /* Only check the channel ID is known from SCP-firwmare */ return scmi_server_get_channel(channel_id, NULL); } return TEE_ERROR_NOT_SUPPORTED; } static TEE_Result pta_scmi_open_session(uint32_t ptypes __unused, TEE_Param par[TEE_NUM_PARAMS] __unused, void **session __unused) { struct ts_session *ts = ts_get_current_session(); struct tee_ta_session *ta_session = to_ta_session(ts); /* Only REE kernel is allowed to access SCMI resources */ if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) { DMSG("Expecting TEE_LOGIN_REE_KERNEL"); return TEE_ERROR_ACCESS_DENIED; } if (IS_ENABLED(CFG_SCMI_MSG_DRIVERS) || IS_ENABLED(CFG_SCMI_SCPFW)) return TEE_SUCCESS; return TEE_ERROR_NOT_SUPPORTED; } static TEE_Result pta_scmi_invoke_command(void *session __unused, uint32_t cmd, uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { FMSG("SCMI command %#"PRIx32" ptypes %#"PRIx32, cmd, ptypes); switch (cmd) { case PTA_SCMI_CMD_CAPABILITIES: return cmd_capabilities(ptypes, params); case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL: return cmd_process_smt_channel(ptypes, params); case PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE: return cmd_process_smt_message(ptypes, params); case PTA_SCMI_CMD_PROCESS_MSG_CHANNEL: return cmd_process_msg_channel(ptypes, params); case PTA_SCMI_CMD_GET_CHANNEL_HANDLE: return cmd_get_channel_handle(ptypes, params); default: return TEE_ERROR_NOT_SUPPORTED; } } pseudo_ta_register(.uuid = PTA_SCMI_UUID, .name = PTA_SCMI_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, .open_session_entry_point = pta_scmi_open_session, .invoke_command_entry_point = pta_scmi_invoke_command); optee_os-4.3.0/core/pta/scp03.c000066400000000000000000000021071464416617300161570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (C) Foundries Ltd. 2020 - All Rights Reserved * Author: Jorge Ramirez */ #include #include #include #define PTA_NAME "pta.scp03" static TEE_Result invoke_command(void *session_context __unused, uint32_t command_id, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); bool rotate_keys = false; FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; switch (command_id) { case PTA_CMD_ENABLE_SCP03: if (params[0].value.a == PTA_SCP03_SESSION_ROTATE_KEYS) rotate_keys = true; return crypto_se_enable_scp03(rotate_keys); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_SCP03_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/secstor_ta_mgmt.c000066400000000000000000000111411464416617300204170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include static TEE_Result check_install_conflict(const struct shdr_bootstrap_ta *bs_ta) { TEE_Result res; struct tee_tadb_ta_read *ta; TEE_UUID uuid; const struct tee_tadb_property *prop; tee_uuid_from_octets(&uuid, bs_ta->uuid); res = tee_tadb_ta_open(&uuid, &ta); if (res == TEE_ERROR_ITEM_NOT_FOUND) return TEE_SUCCESS; if (res) return res; prop = tee_tadb_ta_get_property(ta); if (prop->version > bs_ta->ta_version) res = TEE_ERROR_ACCESS_CONFLICT; tee_tadb_ta_close(ta); return res; } static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw, size_t nw_size) { TEE_Result res; struct tee_tadb_ta_write *ta; void *hash_ctx = NULL; size_t offs; const size_t buf_size = 2 * 4096; void *buf; struct tee_tadb_property property; struct shdr_bootstrap_ta bs_ta; if (shdr->img_type != SHDR_BOOTSTRAP_TA) return TEE_ERROR_SECURITY; if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr))) return TEE_ERROR_SECURITY; if (shdr->hash_size > buf_size) return TEE_ERROR_SECURITY; buf = malloc(buf_size); if (!buf) return TEE_ERROR_OUT_OF_MEMORY; /* * Initialize a hash context and run the algorithm over the signed * header (less the final file hash and its signature of course) */ res = crypto_hash_alloc_ctx(&hash_ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo)); if (res) goto err; res = crypto_hash_init(hash_ctx); if (res) goto err_free_hash_ctx; res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr)); if (res) goto err_free_hash_ctx; offs = SHDR_GET_SIZE(shdr); memcpy(&bs_ta, nw + offs, sizeof(bs_ta)); /* Check that we're not downgrading a TA */ res = check_install_conflict(&bs_ta); if (res) goto err_free_hash_ctx; res = crypto_hash_update(hash_ctx, (uint8_t *)&bs_ta, sizeof(bs_ta)); if (res) goto err_free_hash_ctx; offs += sizeof(bs_ta); memset(&property, 0, sizeof(property)); COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(bs_ta.uuid)); tee_uuid_from_octets(&property.uuid, bs_ta.uuid); property.version = bs_ta.ta_version; property.custom_size = 0; property.bin_size = nw_size - offs; DMSG("Installing %pUl", (void *)&property.uuid); res = tee_tadb_ta_create(&property, &ta); if (res) goto err_free_hash_ctx; while (offs < nw_size) { size_t l = MIN(buf_size, nw_size - offs); memcpy(buf, nw + offs, l); res = crypto_hash_update(hash_ctx, buf, l); if (res) goto err_ta_finalize; res = tee_tadb_ta_write(ta, buf, l); if (res) goto err_ta_finalize; offs += l; } res = crypto_hash_final(hash_ctx, buf, shdr->hash_size); if (res) goto err_ta_finalize; if (consttime_memcmp(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) { res = TEE_ERROR_SECURITY; goto err_ta_finalize; } crypto_hash_free_ctx(hash_ctx); free(buf); return tee_tadb_ta_close_and_commit(ta); err_ta_finalize: tee_tadb_ta_close_and_delete(ta); err_free_hash_ctx: crypto_hash_free_ctx(hash_ctx); err: free(buf); return res; } static TEE_Result bootstrap(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res; struct shdr *shdr; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (param_types != exp_pt) return TEE_ERROR_BAD_PARAMETERS; shdr = shdr_alloc_and_copy(0, params->memref.buffer, params->memref.size); if (!shdr) return TEE_ERROR_SECURITY; res = shdr_verify_signature(shdr); if (res) goto out; res = install_ta(shdr, params->memref.buffer, params->memref.size); out: shdr_free(shdr); return res; } static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd_id) { case PTA_SECSTOR_TA_MGMT_BOOTSTRAP: return bootstrap(param_types, params); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_SECSTOR_TA_MGMT_UUID, .name = "secstor_ta_mgmt", /* * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are * current part of PTA_DEFAULT_FLAGS, but as this TA * depends on those two flags we add them explicitly * too. */ .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE | TA_FLAG_MULTI_SESSION, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/stats.c000066400000000000000000000131461464416617300163720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { struct pta_stats_alloc *stats = NULL; uint32_t size_to_retrieve = 0; uint32_t pool_id = 0; uint32_t i = 0; /* * p[0].value.a = pool id (from 0 to n) * - 0 means all the pools to be retrieved * - 1..n means pool id * p[0].value.b = 0 if no reset of the stats * p[1].memref.buffer = output buffer to struct pta_stats_alloc */ if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) { return TEE_ERROR_BAD_PARAMETERS; } pool_id = p[0].value.a; if (pool_id > STATS_NB_POOLS) return TEE_ERROR_BAD_PARAMETERS; size_to_retrieve = sizeof(struct pta_stats_alloc); if (pool_id == ALLOC_ID_ALL) size_to_retrieve *= STATS_NB_POOLS; if (p[1].memref.size < size_to_retrieve) { p[1].memref.size = size_to_retrieve; return TEE_ERROR_SHORT_BUFFER; } p[1].memref.size = size_to_retrieve; stats = p[1].memref.buffer; for (i = ALLOC_ID_HEAP; i <= STATS_NB_POOLS; i++) { if (pool_id != ALLOC_ID_ALL && i != pool_id) continue; switch (i) { case ALLOC_ID_HEAP: malloc_get_stats(stats); strlcpy(stats->desc, "Heap", sizeof(stats->desc)); if (p[0].value.b) malloc_reset_stats(); break; case ALLOC_ID_PUBLIC_DDR: EMSG("public DDR not managed by secure side anymore"); break; case ALLOC_ID_TA_RAM: tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats, !!p[0].value.b); strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc)); break; #ifdef CFG_NS_VIRTUALIZATION case ALLOC_ID_NEXUS_HEAP: nex_malloc_get_stats(stats); strlcpy(stats->desc, "KHeap", sizeof(stats->desc)); if (p[0].value.b) nex_malloc_reset_stats(); break; #endif default: EMSG("Wrong pool id"); break; } stats++; } return TEE_SUCCESS; } static TEE_Result get_pager_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { struct tee_pager_stats stats = { }; if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE) != type) { EMSG("expect 3 output values as argument"); return TEE_ERROR_BAD_PARAMETERS; } tee_pager_get_stats(&stats); p[0].value.a = stats.npages; p[0].value.b = stats.npages_all; p[1].value.a = stats.ro_hits; p[1].value.b = stats.rw_hits; p[2].value.a = stats.hidden_hits; p[2].value.b = stats.zi_released; return TEE_SUCCESS; } static TEE_Result get_memleak_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) { if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) return TEE_ERROR_BAD_PARAMETERS; mdbg_check(1); return TEE_SUCCESS; } static TEE_Result get_user_ta_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS] __maybe_unused) { uint32_t res = TEE_SUCCESS; if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) return TEE_ERROR_BAD_PARAMETERS; #if defined(CFG_TA_STATS) res = tee_ta_instance_stats(p[0].memref.buffer, &p[0].memref.size); if (res != TEE_SUCCESS) DMSG("tee_ta_dump_stats return: 0x%"PRIx32, res); #else res = TEE_ERROR_NOT_SUPPORTED; #endif return res; } static TEE_Result get_system_time(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { TEE_Result ret = TEE_ERROR_GENERIC; TEE_Time ree_time = { }; TEE_Time tee_time = { }; if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) return TEE_ERROR_BAD_PARAMETERS; ret = tee_time_get_sys_time(&tee_time); if (ret) return ret; ret = tee_time_get_ree_time(&ree_time); if (ret) return ret; p[0].value.a = ree_time.seconds; p[0].value.b = ree_time.millis; p[1].value.a = tee_time.seconds; p[1].value.b = tee_time.millis; return TEE_SUCCESS; } static TEE_Result print_driver_info(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE) != type) return TEE_ERROR_BAD_PARAMETERS; switch (p[0].value.a) { case STATS_DRIVER_TYPE_CLOCK: clk_print_tree(); break; case STATS_DRIVER_TYPE_REGULATOR: regulator_print_tree(); break; default: return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } /* * Trusted Application Entry Points */ static TEE_Result invoke_command(void *psess __unused, uint32_t cmd, uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd) { case STATS_CMD_PAGER_STATS: return get_pager_stats(ptypes, params); case STATS_CMD_ALLOC_STATS: return get_alloc_stats(ptypes, params); case STATS_CMD_MEMLEAK_STATS: return get_memleak_stats(ptypes, params); case STATS_CMD_TA_STATS: return get_user_ta_stats(ptypes, params); case STATS_CMD_GET_TIME: return get_system_time(ptypes, params); case STATS_CMD_PRINT_DRIVER_INFO: return print_driver_info(ptypes, params); default: break; } return TEE_ERROR_BAD_PARAMETERS; } pseudo_ta_register(.uuid = STATS_UUID, .name = "stats.pta", .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/stm32mp/000077500000000000000000000000001464416617300163705ustar00rootroot00000000000000optee_os-4.3.0/core/pta/stm32mp/bsec_pta.c000066400000000000000000000166131464416617300203230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2022, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include static_assert(IS_ENABLED(CFG_STM32_BSEC)); #define PTA_NAME "bsec.pta" static TEE_Result bsec_check_access(uint32_t otp_id) { if (!stm32_bsec_nsec_can_access_otp(otp_id)) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } static TEE_Result bsec_read_mem(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t *buf = (uint32_t *)params[1].memref.buffer; uint32_t otp_start = 0; size_t otp_length = 0; uint32_t otp_id = 0; TEE_Result res = TEE_ERROR_GENERIC; size_t size = params[1].memref.size; bool locked = false; unsigned int otp_base_offset = params[0].value.a; unsigned int bsec_command = params[0].value.b; if (pt != exp_pt || !buf || !size || !IS_ALIGNED_WITH_TYPE(params[1].memref.buffer, uint32_t)) return TEE_ERROR_BAD_PARAMETERS; /* Check 32bits alignment */ if (otp_base_offset % BSEC_BYTES_PER_WORD || size % BSEC_BYTES_PER_WORD) return TEE_ERROR_BAD_PARAMETERS; otp_start = otp_base_offset / BSEC_BYTES_PER_WORD; otp_length = size / BSEC_BYTES_PER_WORD; for (otp_id = otp_start; otp_id < otp_start + otp_length; otp_id++, buf++) { res = bsec_check_access(otp_id); switch (bsec_command) { case PTA_BSEC_SHADOW_ACCESS: if (res) { /* Force 0 when access is not allowed */ *buf = 0x0; continue; } /* Read shadow register */ res = stm32_bsec_read_otp(buf, otp_id); FMSG("Read shadow %"PRIu32" val: %#"PRIx32, otp_id, *buf); break; case PTA_BSEC_FUSE_ACCESS: /* Check access */ if (res) goto out; /* Read fuse value */ res = stm32_bsec_shadow_read_otp(buf, otp_id); FMSG("Read fuse %"PRIu32" val: %#"PRIx32, otp_id, *buf); break; case PTA_BSEC_LOCKS_ACCESS: if (res) { /* Force error when access is not allowed */ *buf = PTA_BSEC_LOCK_ERROR; continue; } *buf = 0; /* Read lock value */ res = stm32_bsec_read_permanent_lock(otp_id, &locked); if (res) goto out; if (locked) *buf |= PTA_BSEC_LOCK_PERM; res = stm32_bsec_read_sr_lock(otp_id, &locked); if (res) goto out; if (locked) *buf |= PTA_BSEC_LOCK_SHADOW_R; res = stm32_bsec_read_sw_lock(otp_id, &locked); if (res) goto out; if (locked) *buf |= PTA_BSEC_LOCK_SHADOW_W; res = stm32_bsec_read_sp_lock(otp_id, &locked); if (res) goto out; if (locked) *buf |= PTA_BSEC_LOCK_SHADOW_P; FMSG("Read lock %"PRIu32" val: %#"PRIx32, otp_id, *buf); break; default: FMSG("%"PRIu32" invalid operation: %"PRIu32, otp_id, bsec_command); res = TEE_ERROR_BAD_PARAMETERS; } if (res) goto out; } FMSG("Buffer orig %p, size %zu", buf, size); res = TEE_SUCCESS; out: return res; } static TEE_Result bsec_write_mem(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t *buf = (uint32_t *)params[1].memref.buffer; size_t size = params[1].memref.size; uint32_t otp_start = 0; size_t otp_length = 0; uint32_t otp_id = 0; TEE_Result res = TEE_ERROR_GENERIC; unsigned int otp_base_offset = params[0].value.a; unsigned int bsec_command = params[0].value.b; if (pt != exp_pt || !buf || !size || !IS_ALIGNED_WITH_TYPE(params[1].memref.buffer, uint32_t)) return TEE_ERROR_BAD_PARAMETERS; /* Check 32bits alignment */ if (otp_base_offset % BSEC_BYTES_PER_WORD || size % BSEC_BYTES_PER_WORD) return TEE_ERROR_BAD_PARAMETERS; otp_start = otp_base_offset / BSEC_BYTES_PER_WORD; otp_length = size / BSEC_BYTES_PER_WORD; /* Initial check to ensure that all BSEC words are available */ for (otp_id = otp_start; otp_id < otp_start + otp_length; otp_id++) { res = bsec_check_access(otp_id); if (res) return res; } for (otp_id = otp_start; otp_id < otp_start + otp_length; otp_id++, buf++) { switch (bsec_command) { case PTA_BSEC_SHADOW_ACCESS: /* Write shadow register */ FMSG("Write shadow %"PRIx32" : %"PRIx32, otp_id, *buf); res = stm32_bsec_write_otp(*buf, otp_id); break; case PTA_BSEC_FUSE_ACCESS: /* Write fuse value */ FMSG("Write fuse %"PRIx32" : %08"PRIx32, otp_id, *buf); res = stm32_bsec_program_otp(*buf, otp_id); break; case PTA_BSEC_LOCKS_ACCESS: if (*buf & PTA_BSEC_LOCK_PERM) { FMSG("Perm lock access OTP: %u", otp_id); res = stm32_bsec_permanent_lock_otp(otp_id); if (res) break; } if (*buf & PTA_BSEC_LOCK_SHADOW_R) { FMSG("Shadow read lock"); res = stm32_bsec_set_sr_lock(otp_id); if (res) break; } if (*buf & PTA_BSEC_LOCK_SHADOW_W) { FMSG("Shadow write lock detected"); res = stm32_bsec_set_sw_lock(otp_id); if (res) break; } if (*buf & PTA_BSEC_LOCK_SHADOW_P) { FMSG("Shadow programming lock detected"); res = stm32_bsec_set_sp_lock(otp_id); } break; default: FMSG("OTP %"PRIx32" invalid operation: %"PRIx32, otp_id, bsec_command); res = TEE_ERROR_BAD_PARAMETERS; } if (res) return res; } return TEE_SUCCESS; } static TEE_Result bsec_pta_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Result res = TEE_ERROR_GENERIC; enum stm32_bsec_sec_state state = BSEC_STATE_INVALID; enum stm32_bsec_pta_sec_state pta_state = PTA_BSEC_STATE_INVALID; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; res = stm32_bsec_get_state(&state); if (res) return res; switch (state) { case BSEC_STATE_SEC_CLOSED: pta_state = PTA_BSEC_STATE_SEC_CLOSE; break; case BSEC_STATE_SEC_OPEN: pta_state = PTA_BSEC_STATE_SEC_OPEN; break; default: pta_state = PTA_BSEC_STATE_INVALID; break; } params[0].value.a = pta_state; return TEE_SUCCESS; } static TEE_Result bsec_pta_invoke_command(void *pSessionContext __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { FMSG(PTA_NAME" command %#"PRIx32" ptypes %#"PRIx32, cmd_id, param_types); switch (cmd_id) { case PTA_BSEC_CMD_READ_OTP: return bsec_read_mem(param_types, params); case PTA_BSEC_CMD_WRITE_OTP: return bsec_write_mem(param_types, params); case PTA_BSEC_CMD_GET_STATE: return bsec_pta_state(param_types, params); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } static TEE_Result pta_bsec_open_session(uint32_t ptypes __unused, TEE_Param par[TEE_NUM_PARAMS] __unused, void **session __unused) { uint32_t login = to_ta_session(ts_get_current_session())->clnt_id.login; if (login == TEE_LOGIN_REE_KERNEL) return TEE_SUCCESS; return TEE_ERROR_ACCESS_DENIED; } pseudo_ta_register(.uuid = PTA_BSEC_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, .open_session_entry_point = pta_bsec_open_session, .invoke_command_entry_point = bsec_pta_invoke_command); optee_os-4.3.0/core/pta/stm32mp/remoteproc_pta.c000066400000000000000000000225571464416617300215720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2023, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include "rproc_pub_key.h" #define PTA_NAME "remoteproc.pta" /* * UUID of the remoteproc Trusted application authorized to communicate with * the remoteproc pseudo TA. The UID should match the one defined in the * ta_remoteproc.h header file. */ #define TA_REMOTEPROC_UUID \ { 0x80a4c275, 0x0a47, 0x4905, \ { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } /* * Firmware states * REMOTEPROC_OFF: firmware is off * REMOTEPROC_ON: firmware is running */ enum rproc_load_state { REMOTEPROC_OFF = 0, REMOTEPROC_ON, }; /* Currently supporting a single remote processor instance */ static enum rproc_load_state rproc_ta_state = REMOTEPROC_OFF; static TEE_Result rproc_pta_capabilities(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (!stm32_rproc_get(params[0].value.a)) return TEE_ERROR_NOT_SUPPORTED; /* Support only ELF format */ params[1].value.a = PTA_RPROC_HWCAP_FMT_ELF; /* * Due to stm32mp1 pager, secure memory is too expensive. Support hash * protected image only, so that firmware image can be loaded from * non-secure memory. */ params[2].value.a = PTA_RPROC_HWCAP_PROT_HASH_TABLE; return TEE_SUCCESS; } static TEE_Result rproc_pta_load_segment(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT); TEE_Result res = TEE_ERROR_GENERIC; paddr_t pa = 0; void *dst = NULL; uint8_t *src = params[1].memref.buffer; size_t size = params[1].memref.size; uint8_t *hash = params[3].memref.buffer; paddr_t da = (paddr_t)reg_pair_to_64(params[2].value.b, params[2].value.a); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (!hash || params[3].memref.size != TEE_SHA256_HASH_SIZE) return TEE_ERROR_BAD_PARAMETERS; if (rproc_ta_state != REMOTEPROC_OFF) return TEE_ERROR_BAD_STATE; /* Get the physical address in local context mapping */ res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); if (res) return res; if (stm32_rproc_map(params[0].value.a, pa, size, &dst)) { EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); return TEE_ERROR_GENERIC; } /* Copy the segment to the remote processor memory */ memcpy(dst, src, size); /* Verify that loaded segment is valid */ res = hash_sha256_check(hash, dst, size); if (res) memset(dst, 0, size); stm32_rproc_unmap(params[0].value.a, dst, size); return res; } static TEE_Result rproc_pta_set_memory(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT); TEE_Result res = TEE_ERROR_GENERIC; paddr_t pa = 0; void *dst = NULL; paddr_t da = params[1].value.a; size_t size = params[2].value.a; uint8_t value = params[3].value.a && 0xFF; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (rproc_ta_state != REMOTEPROC_OFF) return TEE_ERROR_BAD_STATE; /* Get the physical address in CPU mapping */ res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); if (res) return res; res = stm32_rproc_map(params[0].value.a, pa, size, &dst); if (res) { EMSG("Can't map region %#"PRIxPA" size %zu", pa, size); return TEE_ERROR_GENERIC; } memset(dst, value, size); return stm32_rproc_unmap(params[0].value.a, dst, size); } static TEE_Result rproc_pta_da_to_pa(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT); TEE_Result res = TEE_ERROR_GENERIC; paddr_t da = params[1].value.a; size_t size = params[2].value.a; paddr_t pa = 0; DMSG("Conversion for address %#"PRIxPA" size %zu", da, size); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; /* Target address is expected 32bit, ensure 32bit MSB are zero */ if (params[1].value.b || params[2].value.b) return TEE_ERROR_BAD_PARAMETERS; res = stm32_rproc_da_to_pa(params[0].value.a, da, size, &pa); if (res) return res; reg_pair_from_64((uint64_t)pa, ¶ms[3].value.b, ¶ms[3].value.a); return TEE_SUCCESS; } static TEE_Result rproc_pta_start(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_ERROR_GENERIC; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (rproc_ta_state != REMOTEPROC_OFF) return TEE_ERROR_BAD_STATE; res = stm32_rproc_start(params[0].value.a); if (res) return res; rproc_ta_state = REMOTEPROC_ON; return TEE_SUCCESS; } static TEE_Result rproc_pta_stop(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Result res = TEE_ERROR_GENERIC; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (rproc_ta_state != REMOTEPROC_ON) return TEE_ERROR_BAD_STATE; res = stm32_rproc_stop(params[0].value.a); if (res) return res; rproc_ta_state = REMOTEPROC_OFF; return TEE_SUCCESS; } static TEE_Result rproc_pta_verify_rsa_signature(TEE_Param *hash, TEE_Param *sig, uint32_t algo) { struct rsa_public_key key = { }; TEE_Result res = TEE_ERROR_GENERIC; uint32_t e = TEE_U32_TO_BIG_ENDIAN(rproc_pub_key_exponent); size_t hash_size = (size_t)hash->memref.size; size_t sig_size = (size_t)sig->memref.size; res = crypto_acipher_alloc_rsa_public_key(&key, sig_size); if (res) return res; res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); if (res) goto out; res = crypto_bignum_bin2bn(rproc_pub_key_modulus, rproc_pub_key_modulus_size, key.n); if (res) goto out; res = crypto_acipher_rsassa_verify(algo, &key, hash_size, hash->memref.buffer, hash_size, sig->memref.buffer, sig_size); out: crypto_acipher_free_rsa_public_key(&key); return res; } static TEE_Result rproc_pta_verify_digest(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { struct rproc_pta_key_info *keyinfo = NULL; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (!stm32_rproc_get(params[0].value.a)) return TEE_ERROR_NOT_SUPPORTED; if (rproc_ta_state != REMOTEPROC_OFF) return TEE_ERROR_BAD_STATE; keyinfo = params[1].memref.buffer; if (!keyinfo || rproc_pta_keyinfo_size(keyinfo) != params[1].memref.size) return TEE_ERROR_BAD_PARAMETERS; if (keyinfo->algo != TEE_ALG_RSASSA_PKCS1_V1_5_SHA256) return TEE_ERROR_NOT_SUPPORTED; return rproc_pta_verify_rsa_signature(¶ms[2], ¶ms[3], keyinfo->algo); } static TEE_Result rproc_pta_invoke_command(void *session __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd_id) { case PTA_RPROC_HW_CAPABILITIES: return rproc_pta_capabilities(param_types, params); case PTA_RPROC_LOAD_SEGMENT_SHA256: return rproc_pta_load_segment(param_types, params); case PTA_RPROC_SET_MEMORY: return rproc_pta_set_memory(param_types, params); case PTA_RPROC_FIRMWARE_START: return rproc_pta_start(param_types, params); case PTA_RPROC_FIRMWARE_STOP: return rproc_pta_stop(param_types, params); case PTA_RPROC_FIRMWARE_DA_TO_PA: return rproc_pta_da_to_pa(param_types, params); case PTA_RPROC_VERIFY_DIGEST: return rproc_pta_verify_digest(param_types, params); default: return TEE_ERROR_NOT_IMPLEMENTED; } } /* * Pseudo Trusted Application entry points */ static TEE_Result rproc_pta_open_session(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], void **sess_ctx __unused) { struct ts_session *s = ts_get_calling_session(); const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct ts_ctx *ctx = NULL; TEE_UUID ta_uuid = TA_REMOTEPROC_UUID; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (!s || !is_user_ta_ctx(s->ctx)) return TEE_ERROR_ACCESS_DENIED; /* Check that we're called by the remoteproc Trusted application*/ ctx = s->ctx; if (memcmp(&ctx->uuid, &ta_uuid, sizeof(TEE_UUID))) return TEE_ERROR_ACCESS_DENIED; if (!stm32_rproc_get(params[0].value.a)) return TEE_ERROR_NOT_SUPPORTED; return TEE_SUCCESS; } pseudo_ta_register(.uuid = PTA_RPROC_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .invoke_command_entry_point = rproc_pta_invoke_command, .open_session_entry_point = rproc_pta_open_session); optee_os-4.3.0/core/pta/stm32mp/rproc_pub_key.h000066400000000000000000000006141464416617300214050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, STMicroelectronics - All Rights Reserved */ #ifndef PTA_STM32MP_RPROC_PUB_KEY_H #define PTA_STM32MP_RPROC_PUB_KEY_H #include extern const uint32_t rproc_pub_key_exponent; extern const uint8_t rproc_pub_key_modulus[]; extern const size_t rproc_pub_key_modulus_size; #endif /* PTA_STM32MP_RPROC_PUB_KEY_H */ optee_os-4.3.0/core/pta/stm32mp/sub.mk000066400000000000000000000001301464416617300175040ustar00rootroot00000000000000srcs-$(CFG_STM32_BSEC_PTA) += bsec_pta.c srcs-$(CFG_REMOTEPROC_PTA) += remoteproc_pta.c optee_os-4.3.0/core/pta/sub.mk000066400000000000000000000016361464416617300162130ustar00rootroot00000000000000subdirs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += tests srcs-$(CFG_ATTESTATION_PTA) += attestation.c srcs-$(CFG_DEVICE_ENUM_PTA) += device.c srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c ifeq ($(CFG_WITH_USER_TA),y) srcs-$(CFG_SECSTOR_TA_MGMT_PTA) += secstor_ta_mgmt.c endif srcs-$(CFG_WITH_STATS) += stats.c srcs-$(CFG_SYSTEM_PTA) += system.c srcs-$(CFG_SCP03_PTA) += scp03.c srcs-$(CFG_APDU_PTA) += apdu.c srcs-$(CFG_SCMI_PTA) += scmi.c srcs-$(CFG_HWRNG_PTA) += hwrng.c srcs-$(CFG_RTC_PTA) += rtc.c srcs-$(CFG_WIDEVINE_PTA) += widevine.c subdirs-y += bcm subdirs-y += stm32mp subdirs-y += imx subdirs-y += k3 ifeq ($(CFG_REMOTEPROC_PTA),y) gensrcs-y += rproc_pub_key produce-rproc_pub_key = rproc_pub_key.c depends-rproc_pub_key = $(RPROC_SIGN_KEY) scripts/pem_to_pub_c.py recipe-rproc_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py \ --prefix rproc_pub_key --key $(RPROC_SIGN_KEY) \ --out $(sub-dir-out)/rproc_pub_key.c endifoptee_os-4.3.0/core/pta/system.c000066400000000000000000000255571464416617300165710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2022 Linaro Limited * Copyright (c) 2020, Arm Limited. * Copyright (c) 2020, Open Mobile Platform LLC */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static unsigned int system_pnum; static TEE_Result system_rng_reseed(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { size_t entropy_sz = 0; uint8_t *entropy_input = NULL; void *seed_bbuf = NULL; TEE_Result res = TEE_SUCCESS; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; entropy_input = params[0].memref.buffer; entropy_sz = params[0].memref.size; if (!entropy_sz || !entropy_input) return TEE_ERROR_BAD_PARAMETERS; res = bb_memdup_user(entropy_input, entropy_sz, &seed_bbuf); if (res) return res; crypto_rng_add_event(CRYPTO_RNG_SRC_NONSECURE, &system_pnum, seed_bbuf, entropy_sz); bb_free(seed_bbuf, entropy_sz); return TEE_SUCCESS; } static TEE_Result system_derive_ta_unique_key(struct user_mode_ctx *uctx, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { size_t data_len = sizeof(TEE_UUID); TEE_Result res = TEE_ERROR_GENERIC; uint8_t *data = NULL; uint32_t access_flags = 0; void *subkey_bbuf = NULL; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (params[0].memref.size > TA_DERIVED_EXTRA_DATA_MAX_SIZE || params[1].memref.size < TA_DERIVED_KEY_MIN_SIZE || params[1].memref.size > TA_DERIVED_KEY_MAX_SIZE) return TEE_ERROR_BAD_PARAMETERS; /* * The derived key shall not end up in non-secure memory by * mistake. * * Note that we're allowing shared memory as long as it's * secure. This is needed because a TA always uses shared memory * when communicating with another TA. */ access_flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER | TEE_MEMORY_ACCESS_SECURE; res = vm_check_access_rights(uctx, access_flags, (uaddr_t)params[1].memref.buffer, params[1].memref.size); if (res != TEE_SUCCESS) return TEE_ERROR_SECURITY; /* Take extra data into account. */ if (ADD_OVERFLOW(data_len, params[0].memref.size, &data_len)) return TEE_ERROR_SECURITY; data = bb_alloc(data_len); if (!data) return TEE_ERROR_OUT_OF_MEMORY; memcpy(data, &uctx->ts_ctx->uuid, sizeof(TEE_UUID)); /* Append the user provided data */ res = copy_from_user(data + sizeof(TEE_UUID), params[0].memref.buffer, params[0].memref.size); if (res) goto out; subkey_bbuf = bb_alloc(params[1].memref.size); if (!subkey_bbuf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = huk_subkey_derive(HUK_SUBKEY_UNIQUE_TA, data, data_len, subkey_bbuf, params[1].memref.size); if (res) goto out; res = copy_to_user(params[1].memref.buffer, subkey_bbuf, params[1].memref.size); out: bb_free_wipe(subkey_bbuf, params[1].memref.size); bb_free_wipe(data, data_len); return res; } static TEE_Result system_map_zi(struct user_mode_ctx *uctx, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE); uint32_t prot = TEE_MATTR_URW | TEE_MATTR_PRW; TEE_Result res = TEE_ERROR_GENERIC; struct mobj *mobj = NULL; uint32_t pad_begin = 0; uint32_t vm_flags = 0; struct fobj *f = NULL; uint32_t pad_end = 0; size_t num_bytes = 0; vaddr_t va = 0; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (params[0].value.b & ~PTA_SYSTEM_MAP_FLAG_SHAREABLE) return TEE_ERROR_BAD_PARAMETERS; if (params[0].value.b & PTA_SYSTEM_MAP_FLAG_SHAREABLE) vm_flags |= VM_FLAG_SHAREABLE; num_bytes = params[0].value.a; va = reg_pair_to_64(params[1].value.a, params[1].value.b); pad_begin = params[2].value.a; pad_end = params[2].value.b; f = fobj_ta_mem_alloc(ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE)); if (!f) return TEE_ERROR_OUT_OF_MEMORY; mobj = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED); fobj_put(f); if (!mobj) return TEE_ERROR_OUT_OF_MEMORY; res = vm_map_pad(uctx, &va, num_bytes, prot, vm_flags, mobj, 0, pad_begin, pad_end, 0); mobj_put(mobj); if (!res) reg_pair_from_64(va, ¶ms[1].value.a, ¶ms[1].value.b); return res; } static TEE_Result system_unmap(struct user_mode_ctx *uctx, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Result res = TEE_SUCCESS; uint32_t vm_flags = 0; vaddr_t end_va = 0; vaddr_t va = 0; size_t sz = 0; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (params[0].value.b) return TEE_ERROR_BAD_PARAMETERS; va = reg_pair_to_64(params[1].value.a, params[1].value.b); sz = ROUNDUP(params[0].value.a, SMALL_PAGE_SIZE); /* * The vm_get_flags() and vm_unmap() are supposed to detect or * handle overflow directly or indirectly. However, this function * an API function so an extra guard here is in order. If nothing * else to make it easier to review the code. */ if (ADD_OVERFLOW(va, sz, &end_va)) return TEE_ERROR_BAD_PARAMETERS; res = vm_get_flags(uctx, va, sz, &vm_flags); if (res) return res; if (vm_flags & VM_FLAG_PERMANENT) return TEE_ERROR_ACCESS_DENIED; return vm_unmap(uctx, va, sz); } static TEE_Result system_dlopen(struct user_mode_ctx *uctx, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Result res = TEE_ERROR_GENERIC; struct ts_session *s = NULL; TEE_UUID uuid = { }; uint32_t flags = 0; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) return TEE_ERROR_BAD_PARAMETERS; res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); if (res) return res; flags = params[1].value.a; s = ts_pop_current_session(); res = ldelf_dlopen(uctx, &uuid, flags); ts_push_current_session(s); return res; } static TEE_Result system_dlsym(struct user_mode_ctx *uctx, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Result res = TEE_ERROR_GENERIC; struct ts_session *s = NULL; char *sym = NULL; TEE_UUID uuid = { }; size_t symlen = 0; vaddr_t va = 0; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) return TEE_ERROR_BAD_PARAMETERS; res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); if (res) return res; if (!params[1].memref.buffer) return TEE_ERROR_BAD_PARAMETERS; res = bb_strndup_user(params[1].memref.buffer, params[1].memref.size, &sym, &symlen); if (res) return res; s = ts_pop_current_session(); res = ldelf_dlsym(uctx, &uuid, sym, symlen, &va); ts_push_current_session(s); if (!res) reg_pair_from_64(va, ¶ms[2].value.a, ¶ms[2].value.b); return res; } static TEE_Result system_get_tpm_event_log(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); size_t size = 0; TEE_Result res = TEE_SUCCESS; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; size = params[0].memref.size; res = tpm_get_event_log(params[0].memref.buffer, &size); params[0].memref.size = size; return res; } static TEE_Result system_supp_plugin_invoke(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_OUTPUT); TEE_Result res = TEE_ERROR_GENERIC; size_t outlen = 0; TEE_UUID uuid = { }; if (exp_pt != param_types) return TEE_ERROR_BAD_PARAMETERS; if (!params[0].memref.buffer || params[0].memref.size != sizeof(uuid)) return TEE_ERROR_BAD_PARAMETERS; res = copy_from_user(&uuid, params[0].memref.buffer, sizeof(uuid)); if (res) return res; res = tee_invoke_supp_plugin_rpc(&uuid, params[1].value.a, /* cmd */ params[1].value.b, /* sub_cmd */ NULL, params[2].memref.buffer, /* data */ params[2].memref.size, /* in len */ &outlen); params[3].value.a = (uint32_t)outlen; return res; } static TEE_Result open_session(uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused, void **sess_ctx __unused) { struct ts_session *s = NULL; /* Check that we're called from a user TA */ s = ts_get_calling_session(); if (!s) return TEE_ERROR_ACCESS_DENIED; if (!is_user_ta_ctx(s->ctx)) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct ts_session *s = ts_get_calling_session(); struct user_mode_ctx *uctx = to_user_mode_ctx(s->ctx); switch (cmd_id) { case PTA_SYSTEM_ADD_RNG_ENTROPY: return system_rng_reseed(param_types, params); case PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY: return system_derive_ta_unique_key(uctx, param_types, params); case PTA_SYSTEM_MAP_ZI: return system_map_zi(uctx, param_types, params); case PTA_SYSTEM_UNMAP: return system_unmap(uctx, param_types, params); case PTA_SYSTEM_DLOPEN: return system_dlopen(uctx, param_types, params); case PTA_SYSTEM_DLSYM: return system_dlsym(uctx, param_types, params); case PTA_SYSTEM_GET_TPM_EVENT_LOG: return system_get_tpm_event_log(param_types, params); case PTA_SYSTEM_SUPP_PLUGIN_INVOKE: return system_supp_plugin_invoke(param_types, params); default: break; } return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_SYSTEM_UUID, .name = "system.pta", .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, .open_session_entry_point = open_session, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/tests/000077500000000000000000000000001464416617300162255ustar00rootroot00000000000000optee_os-4.3.0/core/pta/tests/aes_perf.c000066400000000000000000000124231464416617300201570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include "misc.h" /* * These keys and iv are copied from optee_test/ta/aes_perf/ta_aes_perf.c, * not because their actual values are important, rather that there's no * reason to use different values. */ static const uint8_t aes_key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; static const uint8_t aes_key2[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F }; static uint8_t aes_iv[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF }; static void free_ctx(void **ctx, uint32_t algo) { if (algo == TEE_ALG_AES_GCM) crypto_authenc_free_ctx(*ctx); else crypto_cipher_free_ctx(*ctx); *ctx = NULL; } static TEE_Result init_ctx(void **ctx, uint32_t algo, TEE_OperationMode mode, size_t key_size_bits, size_t payload_len) { TEE_Result res = TEE_SUCCESS; const uint8_t *key2 = NULL; const uint8_t *iv = NULL; size_t key2_len = 0; size_t key_len = 0; size_t iv_len = 0; if (key_size_bits % 8) return TEE_ERROR_BAD_PARAMETERS; key_len = key_size_bits / 8; if (key_len > sizeof(aes_key)) return TEE_ERROR_BAD_PARAMETERS; /* Alloc ctx */ switch (algo) { case TEE_ALG_AES_XTS: key2_len = key_len; key2 = aes_key2; fallthrough; case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_AES_CTR: res = crypto_cipher_alloc_ctx(ctx, algo); break; case TEE_ALG_AES_GCM: res = crypto_authenc_alloc_ctx(ctx, algo); break; default: return TEE_ERROR_BAD_PARAMETERS; } if (res) return res; /* Init ctx */ switch (algo) { case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_AES_CTR: case TEE_ALG_AES_XTS: iv = aes_iv; iv_len = sizeof(aes_iv); fallthrough; case TEE_ALG_AES_ECB_NOPAD: res = crypto_cipher_init(*ctx, mode, aes_key, key_len, key2, key2_len, iv, iv_len); break; case TEE_ALG_AES_GCM: res = crypto_authenc_init(*ctx, mode, aes_key, key_len, aes_iv, sizeof(aes_iv), TEE_AES_BLOCK_SIZE, 0, payload_len); break; default: return TEE_ERROR_BAD_PARAMETERS; } if (res) free_ctx(ctx, algo); return res; } static TEE_Result update_ae(void *ctx, TEE_OperationMode mode, const void *src, size_t len, void *dst) { size_t dlen = len; return crypto_authenc_update_payload(ctx, mode, src, len, dst, &dlen); } static TEE_Result update_cipher(void *ctx, TEE_OperationMode mode, const void *src, size_t len, void *dst) { return crypto_cipher_update(ctx, mode, false, src, len, dst); } static TEE_Result do_update(void *ctx, uint32_t algo, TEE_OperationMode mode, unsigned int rep_count, unsigned int unit_size, const uint8_t *in, size_t sz, uint8_t *out) { TEE_Result (*update_func)(void *ctx, TEE_OperationMode mode, const void *src, size_t len, void *dst) = NULL; TEE_Result res = TEE_SUCCESS; unsigned int n = 0; unsigned int m = 0; if (algo == TEE_ALG_AES_GCM) update_func = update_ae; else update_func = update_cipher; for (n = 0; n < rep_count; n++) { for (m = 0; m < sz / unit_size; m++) { res = update_func(ctx, mode, in + m * unit_size, unit_size, out + m * unit_size); if (res) return res; } if (sz % unit_size) res = update_func(ctx, mode, in + m * unit_size, sz % unit_size, out + m * unit_size); } return res; } TEE_Result core_aes_perf_tests(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_MEMREF_INOUT); TEE_Result res = TEE_SUCCESS; TEE_OperationMode mode = 0; unsigned int rep_count = 0; unsigned int unit_size = 0; size_t key_size_bits = 0; uint32_t algo = 0; void *ctx = NULL; if (param_types != exp_param_types) return TEE_ERROR_BAD_PARAMETERS; switch (params[0].value.b) { case PTA_INVOKE_TESTS_AES_ECB: algo = TEE_ALG_AES_ECB_NOPAD; break; case PTA_INVOKE_TESTS_AES_CBC: algo = TEE_ALG_AES_CBC_NOPAD; break; case PTA_INVOKE_TESTS_AES_CTR: algo = TEE_ALG_AES_CTR; break; case PTA_INVOKE_TESTS_AES_XTS: algo = TEE_ALG_AES_XTS; break; case PTA_INVOKE_TESTS_AES_GCM: algo = TEE_ALG_AES_GCM; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (params[0].value.a >> 16) mode = TEE_MODE_DECRYPT; else mode = TEE_MODE_ENCRYPT; key_size_bits = params[0].value.a & 0xffff; rep_count = params[1].value.a; unit_size = params[1].value.b; if (params[2].memref.size > params[3].memref.size) return TEE_ERROR_BAD_PARAMETERS; res = init_ctx(&ctx, algo, mode, key_size_bits, params[2].memref.size); if (res) return res; res = do_update(ctx, algo, mode, rep_count, unit_size, params[2].memref.buffer, params[2].memref.size, params[3].memref.buffer); free_ctx(&ctx, algo); return res; } optee_os-4.3.0/core/pta/tests/dt_driver_test.c000066400000000000000000000436661464416617300214310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited * * Tests introduce dummy test drivers and assiciated devices defined in * dt_driver_test.dtsi file with device resource dependencies. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define DT_TEST_MSG(...) FMSG("(dt-driver-test) " __VA_ARGS__) /* Test state IDs */ enum dt_test_sid { DEFAULT = 0, IN_PROGRESS, SUCCESS, FAILED }; /* * DT tests state to be reported from PTA_INVOKE_TESTS_CMD_DT_TEST_STATUS * possibly printed to console. A test can be skipped (DEFAULT) or be * successful (SUCCESS) orthewise it has failed (IN_PROGRESS, FAILED). */ struct dt_test_state { enum dt_test_sid probe_deferral; enum dt_test_sid probe_clocks; enum dt_test_sid probe_gpios; enum dt_test_sid probe_resets; enum dt_test_sid crypto_dependencies; }; /* * References allocated from heap to be free once test completed * dt_test_alloc(), dt_test_free(), dt_test_free_all() */ struct dt_test_free_ref { void *p; SLIST_ENTRY(dt_test_free_ref) link; }; static struct dt_test_state dt_test_state; static const char __maybe_unused * const dt_test_str_sid[] = { [DEFAULT] = "not run", [IN_PROGRESS] = "in-progress", [SUCCESS] = "successful", [FAILED] = "failed", }; /* Reference allocations during test for release_init_resource initcall level */ static SLIST_HEAD(dt_test_free_refs, dt_test_free_ref) dt_test_free_list = SLIST_HEAD_INITIALIZER(dt_test_free_list); static void __maybe_unused *dt_test_alloc(size_t size) { struct dt_test_free_ref *ref = NULL; ref = calloc(1, sizeof(*ref) + size); if (!ref) return NULL; ref->p = ref + 1; SLIST_INSERT_HEAD(&dt_test_free_list, ref, link); return ref->p; } static void __maybe_unused dt_test_free(void *p) { struct dt_test_free_ref *ref = NULL; struct dt_test_free_ref *t_ref = NULL; if (!p) return; SLIST_FOREACH_SAFE(ref, &dt_test_free_list, link, t_ref) { if (ref->p == p) { SLIST_REMOVE(&dt_test_free_list, ref, dt_test_free_ref, link); free(ref); return; } } panic(); } static void dt_test_free_all(void) { while (!SLIST_EMPTY(&dt_test_free_list)) { struct dt_test_free_ref *ref = SLIST_FIRST(&dt_test_free_list); SLIST_REMOVE(&dt_test_free_list, ref, dt_test_free_ref, link); free(ref); } } static TEE_Result dt_test_release(void) { dt_test_free_all(); DT_TEST_MSG("Probe deferral: %s", dt_test_str_sid[dt_test_state.probe_deferral]); DT_TEST_MSG("Clocks probe: %s", dt_test_str_sid[dt_test_state.probe_clocks]); DT_TEST_MSG("GPIO ctrl probe: %s", dt_test_str_sid[dt_test_state.probe_gpios]); DT_TEST_MSG("Reset ctrl probe: %s", dt_test_str_sid[dt_test_state.probe_resets]); DT_TEST_MSG("Crypto deps.: %s", dt_test_str_sid[dt_test_state.crypto_dependencies]); return dt_driver_test_status(); } release_init_resource(dt_test_release); TEE_Result dt_driver_test_status(void) { TEE_Result res = TEE_SUCCESS; if (dt_test_state.probe_deferral != SUCCESS) { EMSG("Probe deferral test failed"); res = TEE_ERROR_GENERIC; } if (IS_ENABLED(CFG_DRIVERS_CLK) && dt_test_state.probe_clocks != SUCCESS) { EMSG("Clocks probing test failed"); res = TEE_ERROR_GENERIC; } if (IS_ENABLED(CFG_DRIVERS_GPIOS) && dt_test_state.probe_gpios != SUCCESS) { EMSG("GPIO controllers probing test failed"); res = TEE_ERROR_GENERIC; } if (IS_ENABLED(CFG_DRIVERS_RSTCTRL) && dt_test_state.probe_resets != SUCCESS) { EMSG("Reset controllers probing test failed"); res = TEE_ERROR_GENERIC; } if (dt_test_state.crypto_dependencies != SUCCESS) { EMSG("Probe deferral on crypto dependencies test failed"); res = TEE_ERROR_GENERIC; } return res; } static TEE_Result probe_test_clocks(const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; struct clk *clk0 = NULL; struct clk *clk1 = NULL; struct clk *clk = NULL; DT_TEST_MSG("Probe clocks"); dt_test_state.probe_clocks = IN_PROGRESS; res = clk_dt_get_by_index(fdt, node, 0, &clk0); if (res) goto err; res = clk_dt_get_by_index(fdt, node, 1, &clk1); if (res) goto err; DT_TEST_MSG("Check valid clock references"); if (clk_enable(clk0)) { DT_TEST_MSG("Can't enable %s", clk_get_name(clk0)); res = TEE_ERROR_GENERIC; goto err; } clk_disable(clk0); res = clk_dt_get_by_name(fdt, node, "clk0", &clk); if (res || clk != clk0) { DT_TEST_MSG("Unexpected clock reference"); res = TEE_ERROR_GENERIC; goto err; } res = clk_dt_get_by_name(fdt, node, "clk1", &clk); if (res || clk != clk1) { DT_TEST_MSG("Unexpected clock reference"); res = TEE_ERROR_GENERIC; goto err; } DT_TEST_MSG("Bad clock reference"); res = clk_dt_get_by_index(fdt, node, 3, &clk); if (!res) { DT_TEST_MSG("Unexpected clock found on invalid index"); res = TEE_ERROR_GENERIC; goto err; } res = clk_dt_get_by_name(fdt, node, "clk2", &clk); if (!res) { DT_TEST_MSG("Unexpected clock found on invalid name"); res = TEE_ERROR_GENERIC; goto err; } dt_test_state.probe_clocks = SUCCESS; return TEE_SUCCESS; err: if (res != TEE_ERROR_DEFER_DRIVER_INIT) dt_test_state.probe_clocks = FAILED; return res; } static TEE_Result probe_test_resets(const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; struct rstctrl *rstctrl0 = NULL; struct rstctrl *rstctrl1 = NULL; struct rstctrl *rstctrl = NULL; DT_TEST_MSG("Probe reset controllers"); dt_test_state.probe_resets = IN_PROGRESS; res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl0); if (res) goto err; DT_TEST_MSG("Check valid reset controller"); if (rstctrl_assert(rstctrl0)) { EMSG("Can't assert rstctrl %s", rstctrl_name(rstctrl0)); res = TEE_ERROR_GENERIC; goto err; } res = rstctrl_dt_get_by_name(fdt, node, "rst0", &rstctrl); if (res) goto err; if (rstctrl != rstctrl0) { EMSG("Unexpected reset controller reference"); res = TEE_ERROR_GENERIC; goto err; } res = rstctrl_dt_get_by_name(fdt, node, "rst1", &rstctrl1); if (res) goto err; if (!rstctrl1 || rstctrl1 == rstctrl0) { EMSG("Unexpected reset controller reference"); res = TEE_ERROR_GENERIC; goto err; } dt_test_state.probe_resets = SUCCESS; return TEE_SUCCESS; err: if (res != TEE_ERROR_DEFER_DRIVER_INIT) dt_test_state.probe_resets = FAILED; return res; } static TEE_Result probe_test_gpios(const void *fdt, int node) { TEE_Result res = TEE_ERROR_GENERIC; struct gpio *gpio = NULL; DT_TEST_MSG("Probe GPIO controllers"); dt_test_state.probe_gpios = IN_PROGRESS; res = gpio_dt_get_by_index(fdt, node, 0, "test", &gpio); if (res) goto err; if (gpio_get_direction(gpio) != GPIO_DIR_IN) { EMSG("Unexpected gpio_get_direction() return value"); res = TEE_ERROR_GENERIC; goto err; } /* GPIO is declared as ACTIVE_LOW in device-tree */ if (gpio_get_value(gpio) != GPIO_LEVEL_LOW) { EMSG("Unexpected gpio_get_value() return value"); res = TEE_ERROR_GENERIC; goto err; } res = gpio_dt_get_by_index(fdt, node, 1, "test", &gpio); if (res) goto err; if (gpio_get_direction(gpio) != GPIO_DIR_IN) { EMSG("Unexpected gpio_get_direction() return value"); res = TEE_ERROR_GENERIC; goto err; } if (gpio_get_value(gpio) != GPIO_LEVEL_HIGH) { EMSG("Unexpected gpio_get_value() return value"); res = TEE_ERROR_GENERIC; goto err; } dt_test_state.probe_gpios = SUCCESS; return TEE_SUCCESS; err: if (res != TEE_ERROR_DEFER_DRIVER_INIT) dt_test_state.probe_gpios = FAILED; return res; } /* * Consumer test driver: instance probed from the compatible * node parsed in the DT. It consumes emulated resource obtained * from DT references. Probe shall succeed only once all resources * are found. */ static TEE_Result dt_test_consumer_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; if (IS_ENABLED(CFG_DRIVERS_CLK)) { res = probe_test_clocks(fdt, node); if (res) goto err_probe; } if (IS_ENABLED(CFG_DRIVERS_RSTCTRL)) { res = probe_test_resets(fdt, node); if (res) goto err_probe; } if (IS_ENABLED(CFG_DRIVERS_GPIO)) { res = probe_test_gpios(fdt, node); if (res) goto err_probe; } if (dt_test_state.probe_deferral != IN_PROGRESS) { dt_test_state.probe_deferral = FAILED; return TEE_ERROR_GENERIC; } dt_test_state.probe_deferral = SUCCESS; return TEE_SUCCESS; err_probe: assert(res); if (res == TEE_ERROR_DEFER_DRIVER_INIT && dt_test_state.probe_deferral == DEFAULT) { /* We expect at least a probe deferral */ dt_test_state.probe_deferral = IN_PROGRESS; } return res; } static const struct dt_device_match dt_test_consumer_match_table[] = { { .compatible = "linaro,dt-test-consumer", }, { } }; DEFINE_DT_DRIVER(dt_test_consumer_driver) = { .name = "dt-test-consumer", .match_table = dt_test_consumer_match_table, .probe = dt_test_consumer_probe, }; static TEE_Result dt_test_crypt_consumer_probe(const void *fdt __unused, int node __unused, const void *compat_data __unused) { TEE_Result res = dt_driver_get_crypto(); uint8_t __maybe_unused byte = 0; if (res == TEE_ERROR_DEFER_DRIVER_INIT && dt_test_state.crypto_dependencies == DEFAULT) { /* We expect to be deferred */ dt_test_state.crypto_dependencies = IN_PROGRESS; } if (res) return res; if (dt_test_state.crypto_dependencies == DEFAULT) { EMSG("Test expects at least a driver probe deferral"); dt_test_state.crypto_dependencies = FAILED; return TEE_ERROR_GENERIC; } if (crypto_rng_read(&byte, sizeof(byte))) { dt_test_state.crypto_dependencies = FAILED; return TEE_ERROR_GENERIC; } dt_test_state.crypto_dependencies = SUCCESS; return TEE_SUCCESS; } static const struct dt_device_match dt_test_crypt_consumer_match_table[] = { { .compatible = "linaro,dt-test-crypt-consumer", }, { } }; DEFINE_DT_DRIVER(dt_test_consumer_driver) = { .name = "dt-test-crypt-consumer", .match_table = dt_test_crypt_consumer_match_table, .probe = dt_test_crypt_consumer_probe, }; #ifdef CFG_DRIVERS_CLK #define DT_TEST_CLK_COUNT 2 #define DT_TEST_CLK0_BINDING_ID 3 #define DT_TEST_CLK1_BINDING_ID 7 static const char *dt_test_clk_name[DT_TEST_CLK_COUNT] = { "dt_test-clk3", "dt_test-clk7", }; /* Emulating a clock does not require operators */ static const struct clk_ops dt_test_clock_provider_ops; static TEE_Result dt_test_get_clk(struct dt_pargs *args, void *data, struct clk **out_device) { struct clk *clk_ref = data; struct clk *clk = NULL; if (args->args_count != 1) return TEE_ERROR_BAD_PARAMETERS; switch (args->args[0]) { case DT_TEST_CLK0_BINDING_ID: clk = clk_ref; break; case DT_TEST_CLK1_BINDING_ID: clk = clk_ref + 1; break; default: EMSG("Unexpected binding ID %"PRIu32, args->args[0]); return TEE_ERROR_BAD_PARAMETERS; } DT_TEST_MSG("Providing clock %s", clk_get_name(clk)); *out_device = clk; return TEE_SUCCESS; } static TEE_Result dt_test_clock_provider_probe(const void *fdt, int node, const void *compat_data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct clk *clk = NULL; size_t n = 0; DT_TEST_MSG("Register clocks"); clk = dt_test_alloc(DT_TEST_CLK_COUNT * sizeof(*clk)); if (!clk) return TEE_ERROR_OUT_OF_MEMORY; for (n = 0; n < DT_TEST_CLK_COUNT; n++) { clk[n].ops = &dt_test_clock_provider_ops; clk[n].name = dt_test_clk_name[n]; res = clk_register(clk + n); if (res) goto err; } res = clk_dt_register_clk_provider(fdt, node, dt_test_get_clk, clk); if (res) goto err; return TEE_SUCCESS; err: dt_test_free(clk); return res; } CLK_DT_DECLARE(dt_test_clock_provider, "linaro,dt-test-provider", dt_test_clock_provider_probe); #endif /* CFG_DRIVERS_CLK */ #ifdef CFG_DRIVERS_RSTCTRL #define DT_TEST_RSTCTRL_COUNT 2 #define DT_TEST_RSTCTRL0_BINDING_ID 5 #define DT_TEST_RSTCTRL1_BINDING_ID 35 struct dt_test_rstctrl { unsigned int dt_binding; struct rstctrl rstctrl; }; static struct dt_test_rstctrl *to_test_rstctrl(struct rstctrl *rstctrl) { return container_of(rstctrl, struct dt_test_rstctrl, rstctrl); } static TEE_Result dt_test_rstctrl_stub(struct rstctrl *rstctrl __maybe_unused, unsigned int to_us __unused) { struct dt_test_rstctrl *dev = to_test_rstctrl(rstctrl); switch (dev->dt_binding) { case DT_TEST_RSTCTRL0_BINDING_ID: case DT_TEST_RSTCTRL1_BINDING_ID: return TEE_SUCCESS; default: EMSG("Unexpected rstctrl reference"); return TEE_ERROR_GENERIC; } } static const char *dt_test_rstctrl_name(struct rstctrl *rstctrl __maybe_unused) { static const char *rstctrl_name[DT_TEST_RSTCTRL_COUNT] = { "dt_test-rstctrl5", "dt_test-rstctrl35", }; struct dt_test_rstctrl *dev = to_test_rstctrl(rstctrl); switch (dev->dt_binding) { case DT_TEST_RSTCTRL0_BINDING_ID: return rstctrl_name[0]; case DT_TEST_RSTCTRL1_BINDING_ID: return rstctrl_name[1]; default: EMSG("Unexpected rstctrl reference"); return NULL; } } const struct rstctrl_ops dt_test_rstctrl_ops = { .assert_level = dt_test_rstctrl_stub, .deassert_level = dt_test_rstctrl_stub, .get_name = dt_test_rstctrl_name, }; static TEE_Result dt_test_get_rstctrl(struct dt_pargs *args, void *data, struct rstctrl **out_device) { struct dt_test_rstctrl *ref = data; struct rstctrl *rstctrl = NULL; if (args->args_count != 1) return TEE_ERROR_BAD_PARAMETERS; switch (args->args[0]) { case DT_TEST_RSTCTRL0_BINDING_ID: rstctrl = &ref[0].rstctrl; break; case DT_TEST_RSTCTRL1_BINDING_ID: rstctrl = &ref[1].rstctrl; break; default: EMSG("Unexpected binding ID %"PRIu32, args->args[0]); return TEE_ERROR_BAD_PARAMETERS; } DT_TEST_MSG("Providing reset controller %s", rstctrl_name(rstctrl)); *out_device = rstctrl; return TEE_SUCCESS; } static TEE_Result dt_test_rstctrl_provider_probe(const void *fdt, int offs, const void *data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct dt_test_rstctrl *devices = NULL; DT_TEST_MSG("Register reset controllers"); assert(rstctrl_ops_is_valid(&dt_test_rstctrl_ops)); devices = dt_test_alloc(DT_TEST_RSTCTRL_COUNT * sizeof(*devices)); if (!devices) return TEE_ERROR_OUT_OF_MEMORY; devices[0].rstctrl.ops = &dt_test_rstctrl_ops; devices[0].dt_binding = DT_TEST_RSTCTRL0_BINDING_ID; devices[1].rstctrl.ops = &dt_test_rstctrl_ops; devices[1].dt_binding = DT_TEST_RSTCTRL1_BINDING_ID; res = rstctrl_register_provider(fdt, offs, dt_test_get_rstctrl, devices); if (res) { dt_test_free(devices); return res; } return TEE_SUCCESS; } RSTCTRL_DT_DECLARE(dt_test_rstctrl_provider, "linaro,dt-test-provider", dt_test_rstctrl_provider_probe); #endif /* CFG_DRIVERS_RSTCTRL */ #ifdef CFG_DRIVERS_GPIO #define DT_TEST_GPIO_COUNT 2 #define DT_TEST_GPIO0_PIN 1 #define DT_TEST_GPIO0_FLAGS GPIO_ACTIVE_LOW #define DT_TEST_GPIO1_PIN 2 #define DT_TEST_GPIO1_FLAGS GPIO_PULL_UP struct dt_test_gpio { unsigned int pin; unsigned int flags; struct gpio_chip gpio_chip; }; static struct dt_test_gpio *to_test_gpio(struct gpio_chip *chip) { return container_of(chip, struct dt_test_gpio, gpio_chip); } static enum gpio_dir dt_test_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio_pin) { struct dt_test_gpio *dtg = to_test_gpio(chip); if (dtg->pin != gpio_pin) panic("Invalid GPIO number"); return GPIO_DIR_IN; } static void dt_test_gpio_set_direction(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_dir direction __unused) { struct dt_test_gpio *dtg = to_test_gpio(chip); if (dtg->pin != gpio_pin) panic("Invalid GPIO number"); } static enum gpio_level dt_test_gpio_get_value(struct gpio_chip *chip, unsigned int gpio_pin) { struct dt_test_gpio *dtg = to_test_gpio(chip); if (dtg->pin != gpio_pin) panic("Invalid GPIO number"); return GPIO_LEVEL_HIGH; } static void dt_test_gpio_set_value(struct gpio_chip *chip, unsigned int gpio_pin, enum gpio_level value __unused) { struct dt_test_gpio *dtg = to_test_gpio(chip); if (dtg->pin != gpio_pin) panic("Invalid GPIO number"); } static const struct gpio_ops dt_test_gpio_ops = { .get_direction = dt_test_gpio_get_direction, .set_direction = dt_test_gpio_set_direction, .get_value = dt_test_gpio_get_value, .set_value = dt_test_gpio_set_value, }; static TEE_Result dt_test_gpio_get_dt(struct dt_pargs *args, void *data, struct gpio **out_device) { TEE_Result res = TEE_ERROR_GENERIC; struct gpio *gpio = NULL; struct dt_test_gpio *gpios = (struct dt_test_gpio *)data; res = gpio_dt_alloc_pin(args, &gpio); if (res) return res; switch (gpio->pin) { case DT_TEST_GPIO0_PIN: gpio->chip = &gpios[0].gpio_chip; if (gpio->dt_flags != gpios[0].flags) { EMSG("Unexpected dt_flags %#"PRIx32, gpio->dt_flags); free(gpio); return TEE_ERROR_GENERIC; } break; case DT_TEST_GPIO1_PIN: gpio->chip = &gpios[1].gpio_chip; if (gpio->dt_flags != gpios[1].flags) { EMSG("Unexpected dt_flags %#"PRIx32, gpio->dt_flags); free(gpio); return TEE_ERROR_GENERIC; } break; default: EMSG("Unexpected pin ID %u", gpio->pin); free(gpio); return TEE_ERROR_BAD_PARAMETERS; }; *out_device = gpio; return TEE_SUCCESS; } static TEE_Result dt_test_gpio_provider_probe(const void *fdt, int offs, const void *data __unused) { TEE_Result res = TEE_ERROR_GENERIC; struct dt_test_gpio *gpios = NULL; DT_TEST_MSG("Register GPIO controllers"); assert(gpio_ops_is_valid(&dt_test_gpio_ops)); gpios = dt_test_alloc(DT_TEST_GPIO_COUNT * sizeof(*gpios)); if (!gpios) return TEE_ERROR_OUT_OF_MEMORY; gpios[0].gpio_chip.ops = &dt_test_gpio_ops; gpios[0].pin = DT_TEST_GPIO0_PIN; gpios[0].flags = DT_TEST_GPIO0_FLAGS; gpios[1].gpio_chip.ops = &dt_test_gpio_ops; gpios[1].pin = DT_TEST_GPIO1_PIN; gpios[1].flags = DT_TEST_GPIO1_FLAGS; res = gpio_register_provider(fdt, offs, dt_test_gpio_get_dt, gpios); if (res) { dt_test_free(gpios); return res; } return TEE_SUCCESS; } GPIO_DT_DECLARE(dt_test_gpio_provider, "linaro,dt-test-provider", dt_test_gpio_provider_probe); #endif /* CFG_DRIVERS_GPIO */ optee_os-4.3.0/core/pta/tests/fs_htree.c000066400000000000000000000362651464416617300202040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include #include #include #include #include "misc.h" /* * The smallest blocks size that can hold two struct * tee_fs_htree_node_image or two struct tee_fs_htree_image. */ #define TEST_BLOCK_SIZE 144 struct test_aux { uint8_t *data; size_t data_len; size_t data_alloced; uint8_t *block; }; static TEE_Result test_get_offs_size(enum tee_fs_htree_type type, size_t idx, uint8_t vers, size_t *offs, size_t *size) { const size_t node_size = sizeof(struct tee_fs_htree_node_image); const size_t block_nodes = TEST_BLOCK_SIZE / (node_size * 2); size_t pbn = 0; size_t bidx = 0; COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE > sizeof(struct tee_fs_htree_node_image) * 2); COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE > sizeof(struct tee_fs_htree_image) * 2); assert(vers == 0 || vers == 1); /* * File layout * * phys block 0: * tee_fs_htree_image vers 0 @ offs = 0 * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image) * * phys block 1: * tee_fs_htree_node_image 0 vers 0 @ offs = 0 * tee_fs_htree_node_image 0 vers 1 @ offs = node_size * * phys block 2: * data block 0 vers 0 * * phys block 3: * tee_fs_htree_node_image 1 vers 0 @ offs = 0 * tee_fs_htree_node_image 1 vers 1 @ offs = node_size * * phys block 4: * data block 0 vers 1 * * ... */ switch (type) { case TEE_FS_HTREE_TYPE_HEAD: *offs = sizeof(struct tee_fs_htree_image) * vers; *size = sizeof(struct tee_fs_htree_image); return TEE_SUCCESS; case TEE_FS_HTREE_TYPE_NODE: pbn = 1 + ((idx / block_nodes) * block_nodes * 2); *offs = pbn * TEST_BLOCK_SIZE + 2 * node_size * (idx % block_nodes) + node_size * vers; *size = node_size; return TEE_SUCCESS; case TEE_FS_HTREE_TYPE_BLOCK: bidx = 2 * idx + vers; pbn = 2 + bidx + bidx / (block_nodes * 2 - 1); *offs = pbn * TEST_BLOCK_SIZE; *size = TEST_BLOCK_SIZE; return TEE_SUCCESS; default: return TEE_ERROR_GENERIC; } } static TEE_Result test_read_init(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data) { TEE_Result res = TEE_SUCCESS; struct test_aux *a = aux; size_t offs = 0; size_t sz = 0; res = test_get_offs_size(type, idx, vers, &offs, &sz); if (res == TEE_SUCCESS) { memset(op, 0, sizeof(*op)); op->params[0].u.value.a = (vaddr_t)aux; op->params[0].u.value.b = offs; op->params[0].u.value.c = sz; *data = a->block; } return res; } static void *uint_to_ptr(uintptr_t p) { return (void *)p; } static TEE_Result test_read_final(struct tee_fs_rpc_operation *op, size_t *bytes) { struct test_aux *a = uint_to_ptr(op->params[0].u.value.a); size_t offs = op->params[0].u.value.b; size_t sz = op->params[0].u.value.c; if (offs + sz <= a->data_len) *bytes = sz; else if (offs <= a->data_len) *bytes = a->data_len - offs; else *bytes = 0; memcpy(a->block, a->data + offs, *bytes); return TEE_SUCCESS; } static TEE_Result test_write_init(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data) { return test_read_init(aux, op, type, idx, vers, data); } static TEE_Result test_write_final(struct tee_fs_rpc_operation *op) { struct test_aux *a = uint_to_ptr(op->params[0].u.value.a); size_t offs = op->params[0].u.value.b; size_t sz = op->params[0].u.value.c; size_t end = offs + sz; if (end > a->data_alloced) { EMSG("out of bounds"); return TEE_ERROR_GENERIC; } memcpy(a->data + offs, a->block, sz); if (end > a->data_len) a->data_len = end; return TEE_SUCCESS; } static const struct tee_fs_htree_storage test_htree_ops = { .block_size = TEST_BLOCK_SIZE, .rpc_read_init = test_read_init, .rpc_read_final = test_read_final, .rpc_write_init = test_write_init, .rpc_write_final = test_write_final, }; #define CHECK_RES(res, cleanup) \ do { \ TEE_Result _res = (res); \ \ if (_res != TEE_SUCCESS) { \ EMSG("error: res = %#" PRIx32, _res); \ { cleanup; } \ } \ } while (0) static uint32_t val_from_bn_n_salt(size_t bn, size_t n, uint8_t salt) { assert(bn < UINT16_MAX); assert(n < UINT8_MAX); return SHIFT_U32(n, 16) | SHIFT_U32(bn, 8) | salt; } static TEE_Result write_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt) { uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)] = { 0 }; size_t n = 0; for (n = 0; n < ARRAY_SIZE(b); n++) b[n] = val_from_bn_n_salt(bn, n, salt); return tee_fs_htree_write_block(ht, bn, b); } static TEE_Result read_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt) { TEE_Result res = TEE_SUCCESS; uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)] = { 0 }; size_t n = 0; res = tee_fs_htree_read_block(ht, bn, b); if (res != TEE_SUCCESS) return res; for (n = 0; n < ARRAY_SIZE(b); n++) { if (b[n] != val_from_bn_n_salt(bn, n, salt)) { DMSG("Unpected b[%zu] %#" PRIx32 "(expected %#" PRIx32 ")", n, b[n], val_from_bn_n_salt(bn, n, salt)); return TEE_ERROR_TIME_NOT_SET; } } return TEE_SUCCESS; } static TEE_Result do_range(TEE_Result (*fn)(struct tee_fs_htree **ht, size_t bn, uint8_t salt), struct tee_fs_htree **ht, size_t begin, size_t num_blocks, size_t salt) { TEE_Result res = TEE_SUCCESS; size_t n = 0; for (n = 0; n < num_blocks; n++) { res = fn(ht, n + begin, salt); CHECK_RES(res, goto out); } out: return res; } static TEE_Result do_range_backwards(TEE_Result (*fn)(struct tee_fs_htree **ht, size_t bn, uint8_t salt), struct tee_fs_htree **ht, size_t begin, size_t num_blocks, size_t salt) { TEE_Result res = TEE_SUCCESS; size_t n = 0; for (n = 0; n < num_blocks; n++) { res = fn(ht, num_blocks - 1 - n + begin, salt); CHECK_RES(res, goto out); } out: return res; } static TEE_Result htree_test_rewrite(struct test_aux *aux, size_t num_blocks, size_t w_unsync_begin, size_t w_unsync_num) { struct ts_session *sess = ts_get_current_session(); const TEE_UUID *uuid = &sess->ctx->uuid; TEE_Result res = TEE_SUCCESS; struct tee_fs_htree *ht = NULL; size_t salt = 23; uint8_t hash[TEE_FS_HTREE_HASH_SIZE] = { 0 }; assert((w_unsync_begin + w_unsync_num) <= num_blocks); aux->data_len = 0; memset(aux->data, 0xce, aux->data_alloced); res = tee_fs_htree_open(true, hash, 0, uuid, &test_htree_ops, aux, &ht); CHECK_RES(res, goto out); /* * Intialize all blocks and verify that they read back as * expected. */ res = do_range(write_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); /* * Write all blocks again, but starting from the end using a new * salt, then verify that that read back as expected. */ salt++; res = do_range_backwards(write_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); /* * Use a new salt to write all blocks once more and verify that * they read back as expected. */ salt++; res = do_range(write_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); /* * Sync the changes of the nodes to memory, verify that all * blocks are read back as expected. */ res = tee_fs_htree_sync_to_storage(&ht, hash, NULL); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); /* * Close and reopen the hash-tree */ tee_fs_htree_close(&ht); res = tee_fs_htree_open(false, hash, 0, uuid, &test_htree_ops, aux, &ht); CHECK_RES(res, goto out); /* * Verify that all blocks are read as expected. */ res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); /* * Rewrite a few blocks and verify that all blocks are read as * expected. */ res = do_range_backwards(write_block, &ht, w_unsync_begin, w_unsync_num, salt + 1); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, w_unsync_begin, salt); CHECK_RES(res, goto out); res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 1); CHECK_RES(res, goto out); res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num, num_blocks - (w_unsync_begin + w_unsync_num), salt); CHECK_RES(res, goto out); /* * Rewrite the blocks from above again with another salt and * verify that they are read back as expected. */ res = do_range(write_block, &ht, w_unsync_begin, w_unsync_num, salt + 2); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, w_unsync_begin, salt); CHECK_RES(res, goto out); res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 2); CHECK_RES(res, goto out); res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num, num_blocks - (w_unsync_begin + w_unsync_num), salt); CHECK_RES(res, goto out); /* * Skip tee_fs_htree_sync_to_storage() and call * tee_fs_htree_close() directly to undo the changes since last * call to tee_fs_htree_sync_to_storage(). Reopen the hash-tree * and verify that recent changes indeed was discarded. */ tee_fs_htree_close(&ht); res = tee_fs_htree_open(false, hash, 0, uuid, &test_htree_ops, aux, &ht); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); /* * Close, reopen and verify that all blocks are read as expected * again but this time based on the counter value in struct * tee_fs_htree_image. */ tee_fs_htree_close(&ht); res = tee_fs_htree_open(false, NULL, 0, uuid, &test_htree_ops, aux, &ht); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, salt); CHECK_RES(res, goto out); out: tee_fs_htree_close(&ht); /* * read_block() returns TEE_ERROR_TIME_NOT_SET in case unexpected * data is read. */ if (res == TEE_ERROR_TIME_NOT_SET) res = TEE_ERROR_SECURITY; return res; } static void aux_free(struct test_aux *aux) { if (aux) { free(aux->data); free(aux->block); free(aux); } } static struct test_aux *aux_alloc(size_t num_blocks) { struct test_aux *aux = NULL; size_t o = 0; size_t sz = 0; if (test_get_offs_size(TEE_FS_HTREE_TYPE_BLOCK, num_blocks, 1, &o, &sz)) return NULL; aux = calloc(1, sizeof(*aux)); if (!aux) return NULL; aux->data_alloced = o + sz; aux->data = malloc(aux->data_alloced); if (!aux->data) goto err; aux->block = malloc(TEST_BLOCK_SIZE); if (!aux->block) goto err; return aux; err: aux_free(aux); return NULL; } static TEE_Result test_write_read(size_t num_blocks) { struct test_aux *aux = aux_alloc(num_blocks); TEE_Result res = TEE_SUCCESS; size_t n = 0; size_t m = 0; size_t o = 0; if (!aux) return TEE_ERROR_OUT_OF_MEMORY; /* * n is the number of block we're going to initialize/use. * m is the offset from where we'll rewrite blocks and expect * the changes to be visible until tee_fs_htree_close() is called * without a call to tee_fs_htree_sync_to_storage() before. * o is the number of blocks we're rewriting starting at m. */ for (n = 0; n < num_blocks; n += 3) { for (m = 0; m < n; m += 3) { for (o = 0; o < (n - m); o++) { res = htree_test_rewrite(aux, n, m, o); CHECK_RES(res, goto out); o += 2; } } } out: aux_free(aux); return res; } static TEE_Result test_corrupt_type(const TEE_UUID *uuid, uint8_t *hash, size_t num_blocks, struct test_aux *aux, enum tee_fs_htree_type type, size_t idx) { TEE_Result res = TEE_SUCCESS; struct test_aux aux2 = *aux; struct tee_fs_htree *ht = NULL; size_t offs = 0; size_t size = 0; size_t size0 = 0; size_t n = 0; res = test_get_offs_size(type, idx, 0, &offs, &size0); CHECK_RES(res, return res); aux2.data = malloc(aux->data_alloced); if (!aux2.data) return TEE_ERROR_OUT_OF_MEMORY; n = 0; while (true) { memcpy(aux2.data, aux->data, aux->data_len); res = test_get_offs_size(type, idx, 0, &offs, &size); CHECK_RES(res, goto out); aux2.data[offs + n]++; res = test_get_offs_size(type, idx, 1, &offs, &size); CHECK_RES(res, goto out); aux2.data[offs + n]++; /* * Errors in head or node is detected by * tee_fs_htree_open() errors in block is detected when * actually read by do_range(read_block) */ res = tee_fs_htree_open(false, hash, 0, uuid, &test_htree_ops, &aux2, &ht); if (!res) { res = do_range(read_block, &ht, 0, num_blocks, 1); /* * do_range(read_block,) is supposed to detect the * error. If TEE_ERROR_TIME_NOT_SET is returned * read_block() was acutally able to get some data, * but the data was incorrect. * * If res == TEE_SUCCESS or * res == TEE_ERROR_TIME_NOT_SET * there's some problem with the htree * implementation. */ if (res == TEE_ERROR_TIME_NOT_SET) { EMSG("error: data silently corrupted"); res = TEE_ERROR_SECURITY; goto out; } if (!res) break; tee_fs_htree_close(&ht); } /* We've tested the last byte, let's get out of here */ if (n == size0 - 1) break; /* Increase n exponentionally after 1 to skip some testing */ if (n) n += n; else n = 1; /* Make sure we test the last byte too */ if (n >= size0) n = size0 - 1; } if (res) { res = TEE_SUCCESS; } else { EMSG("error: data corruption undetected"); res = TEE_ERROR_SECURITY; } out: free(aux2.data); tee_fs_htree_close(&ht); return res; } static TEE_Result test_corrupt(size_t num_blocks) { struct ts_session *sess = ts_get_current_session(); const TEE_UUID *uuid = &sess->ctx->uuid; TEE_Result res = TEE_SUCCESS; struct tee_fs_htree *ht = NULL; uint8_t hash[TEE_FS_HTREE_HASH_SIZE] = { 0 }; struct test_aux *aux = NULL; size_t n = 0; aux = aux_alloc(num_blocks); if (!aux) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } aux->data_len = 0; memset(aux->data, 0xce, aux->data_alloced); /* Write the object and close it */ res = tee_fs_htree_open(true, hash, 0, uuid, &test_htree_ops, aux, &ht); CHECK_RES(res, goto out); res = do_range(write_block, &ht, 0, num_blocks, 1); CHECK_RES(res, goto out); res = tee_fs_htree_sync_to_storage(&ht, hash, NULL); CHECK_RES(res, goto out); tee_fs_htree_close(&ht); /* Verify that the object can be read correctly */ res = tee_fs_htree_open(false, hash, 0, uuid, &test_htree_ops, aux, &ht); CHECK_RES(res, goto out); res = do_range(read_block, &ht, 0, num_blocks, 1); CHECK_RES(res, goto out); tee_fs_htree_close(&ht); res = test_corrupt_type(uuid, hash, num_blocks, aux, TEE_FS_HTREE_TYPE_HEAD, 0); CHECK_RES(res, goto out); for (n = 0; n < num_blocks; n++) { res = test_corrupt_type(uuid, hash, num_blocks, aux, TEE_FS_HTREE_TYPE_NODE, n); CHECK_RES(res, goto out); } for (n = 0; n < num_blocks; n++) { res = test_corrupt_type(uuid, hash, num_blocks, aux, TEE_FS_HTREE_TYPE_BLOCK, n); CHECK_RES(res, goto out); } out: tee_fs_htree_close(&ht); aux_free(aux); return res; } TEE_Result core_fs_htree_tests(uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS] __unused) { TEE_Result res = TEE_SUCCESS; if (nParamTypes) return TEE_ERROR_BAD_PARAMETERS; res = test_write_read(10); if (res) return res; return test_corrupt(5); } optee_os-4.3.0/core/pta/tests/invoke.c000066400000000000000000000334541464416617300176750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "misc.h" #define TA_NAME "invoke_tests.pta" static TEE_Result test_trace(uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused) { IMSG("pseudo TA \"%s\" says \"Hello world !\"", TA_NAME); return TEE_SUCCESS; } static int test_v2p2v(void *va, size_t size) { struct ts_session *session = NULL; paddr_t p = 0; void *v = NULL; if (!va) return 0; session = ts_get_current_session(); p = virt_to_phys(va); /* 0 is not a valid physical address */ if (!p) return 1; if (to_ta_session(session)->clnt_id.login == TEE_LOGIN_TRUSTED_APP) { v = phys_to_virt(p, MEM_AREA_TS_VASPACE, size); } else { v = phys_to_virt(p, MEM_AREA_NSEC_SHM, size); if (!v) v = phys_to_virt(p, MEM_AREA_SDP_MEM, size); if (!v) v = phys_to_virt(p, MEM_AREA_SHM_VASPACE, size); } /* * Return an error only the vaddr found mismatches input address. * Finding a virtual address from a physical address cannot be painful * in some case (i.e pager). Moreover this operation is more debug * related. Thus do not report error if phys_to_virt failed */ if (v && va != v) { EMSG("Failed to p2v/v2p on caller TA memref arguments"); EMSG("va %p -> pa 0x%" PRIxPA " -> va %p", va, p, v); return 1; } return 0; } /* * Check PTA can be invoked with a memory reference on a NULL buffer */ static TEE_Result test_entry_memref_null(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != type) return TEE_ERROR_BAD_PARAMETERS; if (p[0].memref.buffer || p[0].memref.size) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } /* * Supported tests on parameters * (I, J, K, L refer to param index) * * Case 1: command parameters type are: 1 in/out value, 3 empty. * => process outI.a = inI.a + inI.b * Case 2: command parameters type are: 3 input value, 1 output value * => process = outI.a = inJ.a + inK.a + inL.a * Case 3: command parameters type are: 1 in/out memref, 3 empty. * => process = outI[0] = sum(inI[0..len-1]) */ static TEE_Result test_entry_params(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { size_t i; uint8_t d8, *in; /* case 1a: 1 input/output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INOUT) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { p[0].value.a = p[0].value.a + p[0].value.b; return TEE_SUCCESS; } /* case 1b: 1 input/output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INOUT) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { p[1].value.a = p[1].value.a + p[1].value.b; return TEE_SUCCESS; } /* case 1c: 1 input/output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INOUT) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { p[2].value.a = p[2].value.a + p[2].value.b; return TEE_SUCCESS; } /* case 1d: 1 input/output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INOUT)) { p[3].value.a = p[3].value.a + p[3].value.b; return TEE_SUCCESS; } /* case 2a: 3 input value arguments, 1 output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_OUTPUT) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) { p[0].value.a = p[1].value.a + p[2].value.a + p[3].value.a; p[0].value.b = p[1].value.b + p[2].value.b + p[3].value.b; return TEE_SUCCESS; } /* case 2a: 3 input value arguments, 1 output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_OUTPUT) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) { p[1].value.a = p[0].value.a + p[2].value.a + p[3].value.a; p[1].value.b = p[0].value.b + p[2].value.b + p[3].value.b; return TEE_SUCCESS; } /* case 2a: 3 input value arguments, 1 output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_OUTPUT) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_INPUT)) { p[2].value.a = p[0].value.a + p[1].value.a + p[3].value.a; p[2].value.b = p[0].value.b + p[1].value.b + p[3].value.b; return TEE_SUCCESS; } /* case 2a: 3 input value arguments, 1 output value argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_VALUE_INPUT) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_VALUE_OUTPUT)) { p[3].value.a = p[0].value.a + p[1].value.a + p[2].value.a; p[3].value.b = p[0].value.b + p[1].value.b + p[2].value.b; return TEE_SUCCESS; } DMSG("expect memref params: %p/%zu - %p/%zu - %p/%zu - %p/%zu", p[0].memref.buffer, p[0].memref.size, p[1].memref.buffer, p[1].memref.size, p[2].memref.buffer, p[2].memref.size, p[3].memref.buffer, p[3].memref.size); /* case 3a: 1 in/out memref argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_MEMREF_INOUT) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { in = (uint8_t *)p[0].memref.buffer; if (test_v2p2v(in, p[0].memref.size)) return TEE_ERROR_SECURITY; d8 = 0; for (i = 0; i < p[0].memref.size; i++) d8 += in[i]; *(uint8_t *)p[0].memref.buffer = d8; return TEE_SUCCESS; } /* case 3b: 1 in/out memref argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_MEMREF_INOUT) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { in = (uint8_t *)p[1].memref.buffer; if (test_v2p2v(in, p[1].memref.size)) return TEE_ERROR_SECURITY; d8 = 0; for (i = 0; i < p[1].memref.size; i++) d8 += in[i]; *(uint8_t *)p[1].memref.buffer = d8; return TEE_SUCCESS; } /* case 3c: 1 in/out memref argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_MEMREF_INOUT) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_NONE)) { in = (uint8_t *)p[2].memref.buffer; if (test_v2p2v(in, p[2].memref.size)) return TEE_ERROR_SECURITY; d8 = 0; for (i = 0; i < p[2].memref.size; i++) d8 += in[i]; *(uint8_t *)p[2].memref.buffer = d8; return TEE_SUCCESS; } /* case 3d: 1 in/out memref argument */ if ((TEE_PARAM_TYPE_GET(type, 0) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 1) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 2) == TEE_PARAM_TYPE_NONE) && (TEE_PARAM_TYPE_GET(type, 3) == TEE_PARAM_TYPE_MEMREF_INOUT)) { in = (uint8_t *)p[3].memref.buffer; if (test_v2p2v(in, p[3].memref.size)) return TEE_ERROR_SECURITY; d8 = 0; for (i = 0; i < p[3].memref.size; i++) d8 += in[i]; *(uint8_t *)p[3].memref.buffer = d8; return TEE_SUCCESS; } EMSG("unexpected parameters"); return TEE_ERROR_BAD_PARAMETERS; } /* * Test access to Secure Data Path memory from pseudo TAs */ static TEE_Result test_inject_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { char *src = p[0].memref.buffer; char *dst = p[1].memref.buffer; size_t sz = p[0].memref.size; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != type) { DMSG("bad parameter types"); return TEE_ERROR_BAD_PARAMETERS; } if (p[1].memref.size < sz) { p[1].memref.size = sz; return TEE_ERROR_SHORT_BUFFER; } if (!core_vbuf_is(CORE_MEM_NON_SEC, src, sz) || !core_vbuf_is(CORE_MEM_SDP_MEM, dst, sz)) { DMSG("bad memref secure attribute"); return TEE_ERROR_BAD_PARAMETERS; } if (!sz) return TEE_SUCCESS; /* Check that core can p2v and v2p over memory reference arguments */ if (test_v2p2v(src, sz) || test_v2p2v(dst, sz)) return TEE_ERROR_SECURITY; if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) return TEE_ERROR_GENERIC; memcpy(dst, src, sz); if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result test_transform_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { char *buf = p[0].memref.buffer; size_t sz = p[0].memref.size; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != type) { DMSG("bad parameter types"); return TEE_ERROR_BAD_PARAMETERS; } if (!core_vbuf_is(CORE_MEM_SDP_MEM, buf, sz)) { DMSG("bad memref secure attribute"); return TEE_ERROR_BAD_PARAMETERS; } if (!sz) return TEE_SUCCESS; /* Check that core can p2v and v2p over memory reference arguments */ if (test_v2p2v(buf, sz)) return TEE_ERROR_SECURITY; if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS) return TEE_ERROR_GENERIC; for (; sz; sz--, buf++) *buf = ~(*buf) + 1; if (cache_operation(TEE_CACHEFLUSH, buf, sz) != TEE_SUCCESS) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } static TEE_Result test_dump_sdp(uint32_t type, TEE_Param p[TEE_NUM_PARAMS]) { char *src = p[0].memref.buffer; char *dst = p[1].memref.buffer; size_t sz = p[0].memref.size; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != type) { DMSG("bad parameter types"); return TEE_ERROR_BAD_PARAMETERS; } if (p[1].memref.size < sz) { p[1].memref.size = sz; return TEE_ERROR_SHORT_BUFFER; } if (!core_vbuf_is(CORE_MEM_SDP_MEM, src, sz) || !core_vbuf_is(CORE_MEM_NON_SEC, dst, sz)) { DMSG("bad memref secure attribute"); return TEE_ERROR_BAD_PARAMETERS; } if (!sz) return TEE_SUCCESS; /* Check that core can p2v and v2p over memory reference arguments */ if (test_v2p2v(src, sz) || test_v2p2v(dst, sz)) return TEE_ERROR_SECURITY; if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) return TEE_ERROR_GENERIC; memcpy(dst, src, sz); if (cache_operation(TEE_CACHEFLUSH, dst, sz) != TEE_SUCCESS) return TEE_ERROR_GENERIC; return TEE_SUCCESS; } /* * Trusted Application Entry Points */ static TEE_Result create_ta(void) { DMSG("create entry point for pseudo TA \"%s\"", TA_NAME); return TEE_SUCCESS; } static void destroy_ta(void) { DMSG("destroy entry point for pseudo ta \"%s\"", TA_NAME); } static TEE_Result open_session(uint32_t nParamTypes __unused, TEE_Param pParams[TEE_NUM_PARAMS] __unused, void **ppSessionContext __unused) { DMSG("open entry point for pseudo ta \"%s\"", TA_NAME); return TEE_SUCCESS; } static void close_session(void *pSessionContext __unused) { DMSG("close entry point for pseudo ta \"%s\"", TA_NAME); } static TEE_Result invoke_command(void *pSessionContext __unused, uint32_t nCommandID, uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]) { FMSG("command entry point for pseudo ta \"%s\"", TA_NAME); switch (nCommandID) { case PTA_INVOKE_TESTS_CMD_TRACE: return test_trace(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_PARAMS: return test_entry_params(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_MEMREF_NULL: return test_entry_memref_null(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC: return test_inject_sdp(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC: return test_transform_sdp(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC: return test_dump_sdp(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_SELF_TESTS: return core_self_tests(nParamTypes, pParams); #if defined(CFG_REE_FS) && defined(CFG_WITH_USER_TA) case PTA_INVOKE_TESTS_CMD_FS_HTREE: return core_fs_htree_tests(nParamTypes, pParams); #endif case PTA_INVOKE_TESTS_CMD_MUTEX: return core_mutex_tests(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_LOCKDEP: return core_lockdep_tests(nParamTypes, pParams); case PTA_INVOKE_TEST_CMD_AES_PERF: return core_aes_perf_tests(nParamTypes, pParams); case PTA_INVOKE_TESTS_CMD_DT_DRIVER_TESTS: return core_dt_driver_tests(nParamTypes, pParams); default: break; } return TEE_ERROR_BAD_PARAMETERS; } pseudo_ta_register(.uuid = PTA_INVOKE_TESTS_UUID, .name = TA_NAME, .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SECURE_DATA_PATH | TA_FLAG_CONCURRENT | TA_FLAG_DEVICE_ENUM, .create_entry_point = create_ta, .destroy_entry_point = destroy_ta, .open_session_entry_point = open_session, .close_session_entry_point = close_session, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/pta/tests/lockdep.c000066400000000000000000000070301464416617300200120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ /* * Test lockdep with hypothetical thread and lock objects */ #include #include #include "misc.h" static int self_test_lockdep1(void) { TEE_Result res = TEE_ERROR_GENERIC; struct lockdep_node_head graph; struct lockdep_lock_head thread1; int count = 1; DMSG(""); TAILQ_INIT(&thread1); TAILQ_INIT(&graph); /* Not locked, expect failure */ res = __lockdep_lock_release(&thread1, 1); if (!res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread1, 1); if (res) return count; count++; res = __lockdep_lock_release(&thread1, 1); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread1, 1); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread1, 3); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread1, 2); if (res) return count; count++; res = __lockdep_lock_release(&thread1, 3); if (res) return count; count++; /* Already locked */ res = __lockdep_lock_acquire(&graph, &thread1, 2); if (!res) return count; lockdep_graph_delete(&graph); lockdep_queue_delete(&thread1); return 0; } static int self_test_lockdep2(void) { TEE_Result res = TEE_ERROR_GENERIC; struct lockdep_node_head graph; struct lockdep_lock_head thread1; struct lockdep_lock_head thread2; struct lockdep_lock_head thread3; int count = 1; DMSG(""); TAILQ_INIT(&thread1); TAILQ_INIT(&thread2); TAILQ_INIT(&thread3); TAILQ_INIT(&graph); res = __lockdep_lock_acquire(&graph, &thread1, 1); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread2, 2); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread1, 2); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread3, 3); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread2, 3); if (res) return count; count++; /* Deadlock 1-2-3 */ res = __lockdep_lock_acquire(&graph, &thread3, 1); if (!res) return count; lockdep_graph_delete(&graph); lockdep_queue_delete(&thread1); lockdep_queue_delete(&thread2); lockdep_queue_delete(&thread3); return 0; } static int self_test_lockdep3(void) { TEE_Result res = TEE_ERROR_GENERIC; struct lockdep_node_head graph; struct lockdep_lock_head thread1; struct lockdep_lock_head thread2; int count = 1; DMSG(""); TAILQ_INIT(&thread1); TAILQ_INIT(&thread2); TAILQ_INIT(&graph); res = __lockdep_lock_tryacquire(&graph, &thread1, 1); if (res) return count; count++; res = __lockdep_lock_release(&thread1, 1); if (res) return count; count++; res = __lockdep_lock_tryacquire(&graph, &thread1, 1); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread2, 2); if (res) return count; count++; res = __lockdep_lock_acquire(&graph, &thread1, 2); if (res) return count; count++; /* Deadlock 1-2 */ res = __lockdep_lock_acquire(&graph, &thread2, 1); if (!res) return count; lockdep_graph_delete(&graph); lockdep_queue_delete(&thread1); lockdep_queue_delete(&thread2); return 0; } TEE_Result core_lockdep_tests(uint32_t nParamTypes __unused, TEE_Param pParams[TEE_NUM_PARAMS] __unused) { int count = 0; count = self_test_lockdep1(); if (count) goto out; count = self_test_lockdep2(); if (count) goto out; count = self_test_lockdep3(); if (count) goto out; out: if (count) { DMSG("count=%d", count); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } optee_os-4.3.0/core/pta/tests/misc.c000066400000000000000000000341341464416617300173310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include "misc.h" /* * Enable expect LOG macro to enable/disable self tests traces. * * #define LOG DMSG_RAW * #define LOG(...) */ #define LOG(...) static int self_test_add_overflow(void) { uint32_t r_u32; int32_t r_s32; uintmax_t r_um; intmax_t r_sm; if (ADD_OVERFLOW(8U, 0U, &r_s32)) return -1; if (r_s32 != 8) return -1; if (ADD_OVERFLOW(32U, 30U, &r_u32)) return -1; if (r_u32 != 62) return -1; if (!ADD_OVERFLOW(UINT32_MAX, UINT32_MAX, &r_u32)) return -1; if (!ADD_OVERFLOW(UINT32_MAX / 2 + 1, UINT32_MAX / 2 + 1, &r_u32)) return -1; if (ADD_OVERFLOW(UINT32_MAX / 2, UINT32_MAX / 2 + 1, &r_u32)) return -1; if (r_u32 != UINT32_MAX) return -1; if (ADD_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32)) return -1; if (r_s32 != -1) return -1; if (ADD_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32)) return -1; if (r_s32 != -1) return -1; if (ADD_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32)) return -1; if (r_s32 != -1) return -1; if (ADD_OVERFLOW(INT32_MIN + 1, -1, &r_s32)) return -1; if (r_s32 != INT32_MIN) return -1; if (!ADD_OVERFLOW(INT32_MIN, -1, &r_s32)) return -1; if (!ADD_OVERFLOW(INT32_MIN + 1, -2, &r_s32)) return -1; if (!ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_s32)) return -1; if (ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_u32)) return -1; if (!ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_sm)) return -1; if (ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_um)) return -1; if (!ADD_OVERFLOW(INT32_MAX / 2 + 1, INT32_MAX / 2 + 1, &r_s32)) return -1; if (ADD_OVERFLOW(INT32_MAX / 2, INT32_MAX / 2 + 1, &r_s32)) return -1; if (r_s32 != INT32_MAX) return -1; return 0; } static int self_test_sub_overflow(void) { uint32_t r_u32; int32_t r_s32; intmax_t r_sm; if (SUB_OVERFLOW(8U, 1U, &r_s32)) return -1; if (r_s32 != 7) return -1; if (SUB_OVERFLOW(32U, 30U, &r_u32)) return -1; if (r_u32 != 2) return -1; if (!SUB_OVERFLOW(30U, 31U, &r_u32)) return -1; if (SUB_OVERFLOW(30, 31, &r_s32)) return -1; if (r_s32 != -1) return -1; if (SUB_OVERFLOW(-1, INT32_MAX, &r_s32)) return -1; if (r_s32 != INT32_MIN) return -1; if (!SUB_OVERFLOW(-2, INT32_MAX, &r_s32)) return -1; if (SUB_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32)) return -1; if (r_s32 != 61) return -1; if (SUB_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32)) return -1; if (r_s32 != 61) return -1; if (SUB_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32)) return -1; if (r_s32 != -61) return -1; if (SUB_OVERFLOW((int32_t)-31, (int32_t)-30, &r_s32)) return -1; if (r_s32 != -1) return -1; if (SUB_OVERFLOW((int32_t)31, -(INTMAX_MIN + 1), &r_sm)) return -1; if (r_sm != (INTMAX_MIN + 32)) return -1; return 0; } static int self_test_mul_unsigned_overflow(void) { const size_t um_half_shift = sizeof(uintmax_t) * 8 / 2; const uintmax_t um_half_mask = UINTMAX_MAX >> um_half_shift; uint32_t r_u32; uintmax_t r_um; if (MUL_OVERFLOW(32, 30, &r_u32)) return -1; if (r_u32 != 960) return -1; if (MUL_OVERFLOW(-32, -30, &r_u32)) return -1; if (r_u32 != 960) return -1; if (MUL_OVERFLOW(UINTMAX_MAX, 1, &r_um)) return -1; if (r_um != UINTMAX_MAX) return -1; if (MUL_OVERFLOW(UINTMAX_MAX / 4, 4, &r_um)) return -1; if (r_um != (UINTMAX_MAX - 3)) return -1; if (!MUL_OVERFLOW(UINTMAX_MAX / 4 + 1, 4, &r_um)) return -1; if (!MUL_OVERFLOW(UINTMAX_MAX, UINTMAX_MAX, &r_um)) return -1; if (!MUL_OVERFLOW(um_half_mask << um_half_shift, um_half_mask << um_half_shift, &r_um)) return -1; return 0; } static int self_test_mul_signed_overflow(void) { intmax_t r; if (MUL_OVERFLOW(32, -30, &r)) return -1; if (r != -960) return -1; if (MUL_OVERFLOW(-32, 30, &r)) return -1; if (r != -960) return -1; if (MUL_OVERFLOW(32, 30, &r)) return -1; if (r != 960) return -1; if (MUL_OVERFLOW(INTMAX_MAX, 1, &r)) return -1; if (r != INTMAX_MAX) return -1; if (MUL_OVERFLOW(INTMAX_MAX / 4, 4, &r)) return -1; if (r != (INTMAX_MAX - 3)) return -1; if (!MUL_OVERFLOW(INTMAX_MAX / 4 + 1, 4, &r)) return -1; if (!MUL_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r)) return -1; if (MUL_OVERFLOW(INTMAX_MIN + 1, 1, &r)) return -1; if (r != INTMAX_MIN + 1) return -1; if (MUL_OVERFLOW(1, INTMAX_MIN + 1, &r)) return -1; if (r != INTMAX_MIN + 1) return -1; if (MUL_OVERFLOW(0, INTMAX_MIN, &r)) return -1; if (r != 0) return -1; if (MUL_OVERFLOW(1, INTMAX_MIN, &r)) return -1; if (r != INTMAX_MIN) return -1; return 0; } /* test division support. resulting trace shall be manually checked */ static int self_test_division(void) { signed a, b, c, d; bool r; int ret = 0; LOG(""); LOG("division tests (division and modulo):"); /* get some unpredicted values to prevent compilation optimizations: */ /* => use the stack address */ LOG("- test with unsigned small integers:"); a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF); b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; c = a / b; d = a % b; r = ((b * c + d) == a); if (!r) ret = -1; LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)c); LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); LOG(" check results => %s", r ? "ok" : "FAILED !!!"); LOG(""); LOG("- test with signed small integers, negative numerator:"); a = (signed)(vaddr_t)&a; b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) - 1; c = a / b; d = a % b; r = ((b * c + d) == a); if (!r) ret = -1; LOG(" 0x%08x / 0x%08x = %d / %d = %d = 0x%x)", (unsigned)a, (unsigned)b, (signed)a, (signed)b, (signed)c, (unsigned)c); LOG(" 0x%08x %% 0x%08x = %d %% %d = %d = 0x%x)", (unsigned)a, (unsigned)b, (signed)a, (signed)b, (signed)d, (unsigned)d); LOG(" check results => %s", r ? "ok" : "FAILED !!!"); LOG(""); LOG("- test with signed small integers, negative denominator:"); a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF); b = -(signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; c = a / b; d = a % b; LOG("- test with unsigned integers, big numerator (> 0x80000000):"); a = (signed)(vaddr_t)&a; b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1; c = (signed)((unsigned)a / (unsigned)b); d = (signed)((unsigned)a % (unsigned)b); r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a); if (!r) ret = -1; LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)c); LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); LOG(" check results => %s", r ? "ok" : "FAILED !!!"); LOG(""); LOG("- test with unsigned integers, big num. & denom. (> 0x80000000):"); a = (signed)(vaddr_t)&a; b = (signed)((unsigned)(vaddr_t)&a - 1); c = (signed)((unsigned)a / (unsigned)b); d = (signed)((unsigned)a % (unsigned)b); r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a); if (!r) ret = -1; LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)", (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c, (unsigned)c); LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d); LOG(" check results => %s", r ? "ok" : "FAILED !!!"); LOG(""); return ret; } /* test malloc support. resulting trace shall be manually checked */ static int self_test_malloc(void) { char *p1 = NULL, *p2 = NULL; int *p3 = NULL, *p4 = NULL; bool r; int ret = 0; LOG("malloc tests:"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); /* test malloc */ p1 = malloc(1024); LOG("- p1 = malloc(1024)"); p2 = malloc(1024); LOG("- p2 = malloc(1024)"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p1 && p2 && malloc_buffer_is_within_alloced(p1, 1024) && !malloc_buffer_is_within_alloced(p1 + 25, 1000) && !malloc_buffer_is_within_alloced(p1 - 25, 500) && malloc_buffer_overlaps_heap(p1 - 25, 500)); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); /* test realloc */ p3 = realloc(p1, 3 * 1024); if (p3) p1 = NULL; LOG("- p3 = realloc(p1, 3*1024)"); LOG("- free p2"); free(p2); p2 = malloc(1024); LOG("- p2 = malloc(1024)"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p2 && p3); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- free p1, p2, p3"); free(p1); free(p2); free(p3); p1 = NULL; p2 = NULL; p3 = NULL; /* test calloc */ p3 = calloc(4, 1024); p4 = calloc(0x100, 1024 * 1024); LOG("- p3 = calloc(4, 1024)"); LOG("- p4 = calloc(0x100, 1024*1024) too big: should fail!"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p3 && !p4); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- free p3, p4"); free(p3); free(p4); p3 = NULL; p4 = NULL; /* test memalign */ p3 = memalign(0x1000, 1024); LOG("- p3 = memalign(%d, 1024)", 0x1000); p1 = malloc(1024); LOG("- p1 = malloc(1024)"); p4 = memalign(0x100, 512); LOG("- p4 = memalign(%d, 512)", 0x100); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p1 && p3 && p4 && !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100)); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- free p1, p3, p4"); free(p1); free(p3); free(p4); p1 = NULL; p3 = NULL; p4 = NULL; /* test memalign with invalid alignments */ p3 = memalign(100, 1024); LOG("- p3 = memalign(%d, 1024)", 100); p4 = memalign(0, 1024); LOG("- p4 = memalign(%d, 1024)", 0); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (!p3 && !p4); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- free p3, p4"); free(p3); free(p4); p3 = NULL; p4 = NULL; /* test free(NULL) */ LOG("- free NULL"); free(NULL); LOG(""); LOG("malloc test done"); return ret; } #ifdef CFG_NS_VIRTUALIZATION /* test nex_malloc support. resulting trace shall be manually checked */ static int self_test_nex_malloc(void) { char *p1 = NULL, *p2 = NULL; int *p3 = NULL, *p4 = NULL; bool r; int ret = 0; LOG("nex_malloc tests:"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); /* test malloc */ p1 = nex_malloc(1024); LOG("- p1 = nex_malloc(1024)"); p2 = nex_malloc(1024); LOG("- p2 = nex_malloc(1024)"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p1 && p2 && nex_malloc_buffer_is_within_alloced(p1, 1024) && !nex_malloc_buffer_is_within_alloced(p1 + 25, 1000) && !nex_malloc_buffer_is_within_alloced(p1 - 25, 500) && nex_malloc_buffer_overlaps_heap(p1 - 25, 500)); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); /* test realloc */ p3 = nex_realloc(p1, 3 * 1024); if (p3) p1 = NULL; LOG("- p3 = nex_realloc(p1, 3*1024)"); LOG("- nex_free p2"); nex_free(p2); p2 = nex_malloc(1024); LOG("- p2 = nex_malloc(1024)"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p2 && p3); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- nex_free p1, p2, p3"); nex_free(p1); nex_free(p2); nex_free(p3); p1 = NULL; p2 = NULL; p3 = NULL; /* test calloc */ p3 = nex_calloc(4, 1024); p4 = nex_calloc(0x100, 1024 * 1024); LOG("- p3 = nex_calloc(4, 1024)"); LOG("- p4 = nex_calloc(0x100, 1024*1024) too big: should fail!"); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p3 && !p4); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- nex_free p3, p4"); nex_free(p3); nex_free(p4); p3 = NULL; p4 = NULL; /* test memalign */ p3 = nex_memalign(0x1000, 1024); LOG("- p3 = nex_memalign(%d, 1024)", 0x1000); p1 = nex_malloc(1024); LOG("- p1 = nex_malloc(1024)"); p4 = nex_memalign(0x100, 512); LOG("- p4 = nex_memalign(%d, 512)", 0x100); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (p1 && p3 && p4 && !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100)); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- nex_free p1, p3, p4"); nex_free(p1); nex_free(p3); nex_free(p4); p1 = NULL; p3 = NULL; p4 = NULL; /* test memalign with invalid alignments */ p3 = nex_memalign(100, 1024); LOG("- p3 = nex_memalign(%d, 1024)", 100); p4 = nex_memalign(0, 1024); LOG("- p4 = nex_memalign(%d, 1024)", 0); LOG(" p1=%p p2=%p p3=%p p4=%p", (void *)p1, (void *)p2, (void *)p3, (void *)p4); r = (!p3 && !p4); if (!r) ret = -1; LOG(" => test %s", r ? "ok" : "FAILED"); LOG(""); LOG("- nex_free p3, p4"); nex_free(p3); nex_free(p4); p3 = NULL; p4 = NULL; /* test free(NULL) */ LOG("- nex_free NULL"); nex_free(NULL); LOG(""); LOG("nex_malloc test done"); return ret; } #else /* CFG_NS_VIRTUALIZATION */ static int self_test_nex_malloc(void) { return 0; } #endif /* exported entry points for some basic test */ TEE_Result core_self_tests(uint32_t nParamTypes __unused, TEE_Param pParams[TEE_NUM_PARAMS] __unused) { if (self_test_mul_signed_overflow() || self_test_add_overflow() || self_test_sub_overflow() || self_test_mul_unsigned_overflow() || self_test_division() || self_test_malloc() || self_test_nex_malloc()) { EMSG("some self_test_xxx failed! you should enable local LOG"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } /* Exported entrypoint for dt_driver tests */ TEE_Result core_dt_driver_tests(uint32_t nParamTypes __unused, TEE_Param pParams[TEE_NUM_PARAMS] __unused) { if (IS_ENABLED(CFG_DT_DRIVER_EMBEDDED_TEST)) { if (dt_driver_test_status()) return TEE_ERROR_GENERIC; } else { IMSG("dt_driver tests are not embedded"); } return TEE_SUCCESS; } optee_os-4.3.0/core/pta/tests/misc.h000066400000000000000000000020721464416617300173320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef CORE_PTA_TESTS_MISC_H #define CORE_PTA_TESTS_MISC_H #include #include #include /* basic run-time tests */ TEE_Result core_self_tests(uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]); TEE_Result core_fs_htree_tests(uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]); TEE_Result core_mutex_tests(uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]); #ifdef CFG_LOCKDEP TEE_Result core_lockdep_tests(uint32_t nParamTypes, TEE_Param pParams[TEE_NUM_PARAMS]); #else static inline TEE_Result core_lockdep_tests( uint32_t nParamTypes __unused, TEE_Param pParams[TEE_NUM_PARAMS] __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif TEE_Result core_aes_perf_tests(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]); TEE_Result core_dt_driver_tests(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]); #endif /*CORE_PTA_TESTS_MISC_H*/ optee_os-4.3.0/core/pta/tests/mutex.c000066400000000000000000000036031464416617300175350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include "misc.h" static uint32_t before_lock_readers; static uint32_t before_lock_writers; static uint32_t during_lock_readers; static uint32_t during_lock_writers; static uint64_t val0; static uint64_t val1; struct mutex test_mutex = MUTEX_INITIALIZER; static TEE_Result mutex_test_writer(TEE_Param params[TEE_NUM_PARAMS]) { size_t n; params[1].value.a = atomic_inc32(&before_lock_writers); mutex_lock(&test_mutex); atomic_dec32(&before_lock_writers); params[1].value.b = atomic_inc32(&during_lock_writers); for (n = 0; n < params[0].value.b; n++) { val0++; val1++; val1++; } atomic_dec32(&during_lock_writers); mutex_unlock(&test_mutex); return TEE_SUCCESS; } static TEE_Result mutex_test_reader(TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; size_t n; params[1].value.a = atomic_inc32(&before_lock_readers); mutex_read_lock(&test_mutex); atomic_dec32(&before_lock_readers); params[1].value.b = atomic_inc32(&during_lock_readers); for (n = 0; n < params[0].value.b; n++) { if (val0 * 2 != val1) res = TEE_ERROR_BAD_STATE; } atomic_dec32(&during_lock_readers); mutex_read_unlock(&test_mutex); return res; } TEE_Result core_mutex_tests(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) { DMSG("bad parameter types"); return TEE_ERROR_BAD_PARAMETERS; } switch (params[0].value.a) { case PTA_MUTEX_TEST_WRITER: return mutex_test_writer(params); case PTA_MUTEX_TEST_READER: return mutex_test_reader(params); default: return TEE_ERROR_BAD_PARAMETERS; } } optee_os-4.3.0/core/pta/tests/sub.mk000066400000000000000000000004131464416617300173450ustar00rootroot00000000000000srcs-$(call cfg-all-enabled,CFG_REE_FS CFG_WITH_USER_TA) += fs_htree.c srcs-y += invoke.c srcs-$(CFG_LOCKDEP) += lockdep.c srcs-y += misc.c cflags-misc.c-y += -fno-builtin srcs-y += mutex.c srcs-y += aes_perf.c srcs-$(CFG_DT_DRIVER_EMBEDDED_TEST) += dt_driver_test.c optee_os-4.3.0/core/pta/widevine.c000066400000000000000000000122331464416617300170420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, The ChromiumOS Authors */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PTA_NAME "widevine.pta" #define TPM_AUTH_PUB_MAX_SIZE 1024 #define WIDEVINE_PRIV_MAX_SIZE 32 #define CROS_HWSEC_TA_UUID \ { \ 0xed800e33, 0x3c58, 0x4cae, \ { \ 0xa7, 0xc0, 0xfd, 0x16, 0x0e, 0x35, 0xe0, 0x0d \ } \ } #define CROS_HDCP_PROV4_TA_UUID \ { \ 0x0feb839c, 0xee25, 0x4920, \ { \ 0x8e, 0xe3, 0xac, 0x8d, 0xaa, 0x86, 0x0d, 0x3b \ } \ } #define TA_OPTEE_OEMCRYPTO_UUID \ { \ 0xa92d116c, 0xce27, 0x4917, \ { \ 0xb3, 0x0c, 0x4a, 0x41, 0x6e, 0x2d, 0x93, 0x51 \ } \ } static const TEE_UUID allowed_ta_uuids[3] = { CROS_HWSEC_TA_UUID, CROS_HDCP_PROV4_TA_UUID, TA_OPTEE_OEMCRYPTO_UUID, }; /* * The TPM auth public key. Used to communicate with the TPM from OP-TEE. * The format of data should be TPM2B_PUBLIC. * For more information, please reference the 12.2.5 section: * https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf */ static uint8_t tpm_auth_pub[TPM_AUTH_PUB_MAX_SIZE]; static uint32_t tpm_auth_pub_size; /* * The Widevine root of trust secret. Used to sign the widevine * requests in OP-TEE. The value is an ECC NIST P-256 scalar. * For more information, please reference the G.1.2 section: * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf */ static uint8_t widevine_priv[WIDEVINE_PRIV_MAX_SIZE]; static uint32_t widevine_priv_size; static TEE_Result init_widevine_dt_data(void) { int node = 0; int len = 0; void *fdt = NULL; const void *value = NULL; fdt = get_secure_dt(); if (!fdt) return TEE_ERROR_NO_DATA; node = fdt_path_offset(fdt, "/options/op-tee/widevine"); if (node < 0) return TEE_ERROR_ITEM_NOT_FOUND; value = fdt_getprop(fdt, node, "tcg,tpm-auth-public-key", &len); if (!value) return TEE_ERROR_ITEM_NOT_FOUND; if (len > TPM_AUTH_PUB_MAX_SIZE) return TEE_ERROR_OVERFLOW; memcpy(tpm_auth_pub, value, len); tpm_auth_pub_size = len; value = fdt_getprop(fdt, node, "google,widevine-root-of-trust-ecc-p256", &len); if (!value) return TEE_ERROR_ITEM_NOT_FOUND; if (len > WIDEVINE_PRIV_MAX_SIZE) return TEE_ERROR_OVERFLOW; memcpy(widevine_priv, value, len); widevine_priv_size = len; return TEE_SUCCESS; } service_init(init_widevine_dt_data); static TEE_Result open_session(uint32_t param_types __unused, TEE_Param params[TEE_NUM_PARAMS] __unused, void **sess_ctx __unused) { size_t i = 0; struct ts_session *session = ts_get_calling_session(); /* Make sure we are called from a TA */ if (!is_user_ta_ctx(session->ctx)) return TEE_ERROR_ACCESS_DENIED; /* Make sure we are called from an allowed TA */ for (i = 0; i < ARRAY_SIZE(allowed_ta_uuids); i++) if (memcmp(&session->ctx->uuid, &allowed_ta_uuids[i], sizeof(TEE_UUID)) == 0) return TEE_SUCCESS; return TEE_ERROR_ACCESS_DENIED; } static TEE_Result get_dt_data(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS], uint32_t cmd) { uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint8_t *data = NULL; uint32_t data_length = 0; if (exp_pt != ptypes) return TEE_ERROR_BAD_PARAMETERS; if (cmd == PTA_WIDEVINE_GET_TPM_PUBKEY) { data = tpm_auth_pub; data_length = tpm_auth_pub_size; } else if (cmd == PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY) { data = widevine_priv; data_length = widevine_priv_size; } else { return TEE_ERROR_NOT_IMPLEMENTED; } if (data_length == 0) return TEE_ERROR_NO_DATA; if (data_length > params[0].memref.size) { params[0].memref.size = data_length; return TEE_ERROR_SHORT_BUFFER; } params[0].memref.size = data_length; memcpy(params[0].memref.buffer, data, data_length); return TEE_SUCCESS; } /* * Trusted Application Entry Points */ static TEE_Result invoke_command(void *psess __unused, uint32_t cmd, uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { return get_dt_data(ptypes, params, cmd); } pseudo_ta_register(.uuid = PTA_WIDEVINE_UUID, .name = PTA_NAME, .flags = PTA_DEFAULT_FLAGS, .open_session_entry_point = open_session, .invoke_command_entry_point = invoke_command); optee_os-4.3.0/core/sub.mk000066400000000000000000000063531464416617300154300ustar00rootroot00000000000000subdirs-y += crypto subdirs-y += drivers subdirs-y += kernel subdirs-y += mm subdirs-y += pta subdirs-y += tee subdirs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += tests ifeq ($(CFG_WITH_USER_TA),y) gensrcs-y += ta_pub_key produce-ta_pub_key = ta_pub_key.c depends-ta_pub_key = $(TA_PUBLIC_KEY) scripts/pem_to_pub_c.py recipe-ta_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py --prefix ta_pub_key \ --key $(TA_PUBLIC_KEY) --out $(sub-dir-out)/ta_pub_key.c gensrcs-y += ldelf produce-ldelf = ldelf_hex.c depends-ldelf = scripts/gen_ldelf_hex.py $(out-dir)/ldelf/ldelf.elf recipe-ldelf = $(PYTHON3) scripts/gen_ldelf_hex.py --input $(out-dir)/ldelf/ldelf.elf \ --output $(sub-dir-out)/ldelf_hex.c endif ifeq ($(CFG_WITH_USER_TA)-$(CFG_EARLY_TA),y-y) ifeq ($(CFG_EARLY_TA_COMPRESS),y) early-ta-compress = --compress endif define process_early_ta early-ta-$1-uuid := $(firstword $(subst ., ,$(notdir $1))) gensrcs-y += early-ta-$1 produce-early-ta-$1 = early_ta_$$(early-ta-$1-uuid).c depends-early-ta-$1 = $1 scripts/ts_bin_to_c.py recipe-early-ta-$1 = $(PYTHON3) scripts/ts_bin_to_c.py $(early-ta-compress) \ --ta $1 --out $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c endef $(foreach f, $(EARLY_TA_PATHS), $(eval $(call process_early_ta,$(f)))) $(foreach f, $(CFG_IN_TREE_EARLY_TAS), $(eval $(call \ process_early_ta,$(out-dir)/ta/$(f).stripped.elf))) endif define process_secure_partition sp-$1-uuid := $(firstword $(subst ., ,$(notdir $1))) gensrcs-y += sp-$1 produce-sp-$1 = sp_$$(sp-$1-uuid).c depends-sp-$1 = $1 scripts/ts_bin_to_c.py dtb-$1-path = $(dir $1) dtb-$1 = $$(dtb-$1-path)../manifest/$$(sp-$1-uuid).dtb recipe-sp-$1 = $(PYTHON3) scripts/ts_bin_to_c.py --compress --sp $1 \ --out $(sub-dir-out)/sp_$$(sp-$1-uuid).c \ --manifest $$(dtb-$1) endef $(foreach f, $(SP_PATHS), $(eval $(call process_secure_partition,$(f)))) ifeq ($(CFG_EMBED_DTB),y) core-embed-fdt-dts = $(arch-dir)/dts/$(CFG_EMBED_DTB_SOURCE_FILE) core-embed-fdt-dtb = $(out-dir)/$(arch-dir)/dts/$(CFG_EMBED_DTB_SOURCE_FILE:.dts=.dtb) core-embed-fdt-c = $(out-dir)/$(arch-dir)/dts/$(CFG_EMBED_DTB_SOURCE_FILE:.dts=.c) gensrcs-y += embedded_secure_dtb produce-embedded_secure_dtb = arch/$(ARCH)/dts/$(CFG_EMBED_DTB_SOURCE_FILE:.dts=.c) depends-embedded_secure_dtb = $(core-embed-fdt-dtb) scripts/bin_to_c.py recipe-embedded_secure_dtb = $(PYTHON3) scripts/bin_to_c.py \ --bin $(core-embed-fdt-dtb) \ --vname embedded_secure_dtb \ --out $(core-embed-fdt-c) $(eval $(call gen-dtb-file,$(core-embed-fdt-dts),$(core-embed-fdt-dtb))) endif ifeq ($(CFG_SHOW_CONF_ON_BOOT),y) conf-mk-xz-base64 := $(sub-dir-out)/conf.mk.xz.base64 cleanfiles += $(conf-mk-xz-base64) $(conf-mk-xz-base64): $(conf-mk-file) @$(cmd-echo-silent) ' GEN $@' $(q)tail +3 $< | xz | base64 -w 100 >$@ gensrcs-y += conf_str produce-conf_str = conf.mk.xz.base64.c depends-conf_str = $(conf-mk-xz-base64) recipe-conf_str = $(PYTHON3) scripts/bin_to_c.py --text --bin $(conf-mk-xz-base64) \ --out $(sub-dir-out)/conf.mk.xz.base64.c \ --vname conf_str endif ifneq ($(CFG_STMM_PATH),) gensrcs-y += stmm produce-stmm = stmm_hex.c depends-stmm = scripts/gen_stmm_hex.py $(CFG_STMM_PATH) recipe-stmm = scripts/gen_stmm_hex.py --input $(CFG_STMM_PATH) \ --output $(sub-dir-out)/stmm_hex.c cleanfiles += $(sub-dir-out)/stmm_hex.c endif optee_os-4.3.0/core/tee/000077500000000000000000000000001464416617300150545ustar00rootroot00000000000000optee_os-4.3.0/core/tee/entry_std.c000066400000000000000000000354461464416617300172470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015-2016, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SHM_CACHE_ATTRS \ (uint32_t)(core_mmu_is_shm_cached() ? \ TEE_MATTR_MEM_TYPE_CACHED : TEE_MATTR_MEM_TYPE_DEV) /* Sessions opened from normal world */ static struct tee_ta_session_head tee_open_sessions = TAILQ_HEAD_INITIALIZER(tee_open_sessions); #ifdef CFG_CORE_RESERVED_SHM static struct mobj *shm_mobj; #endif #ifdef CFG_SECURE_DATA_PATH static struct mobj **sdp_mem_mobjs; #endif static unsigned int session_pnum; static bool __maybe_unused param_mem_from_mobj(struct param_mem *mem, struct mobj *mobj, const paddr_t pa, const size_t sz) { paddr_t b; if (mobj_get_pa(mobj, 0, 0, &b) != TEE_SUCCESS) panic("mobj_get_pa failed"); if (!core_is_buffer_inside(pa, MAX(sz, 1UL), b, mobj->size)) return false; mem->mobj = mobj_get(mobj); mem->offs = pa - b; mem->size = sz; return true; } #ifdef CFG_CORE_FFA static TEE_Result set_fmem_param(const struct optee_msg_param_fmem *fmem, struct param_mem *mem) { size_t req_size = 0; uint64_t global_id = READ_ONCE(fmem->global_id); size_t sz = READ_ONCE(fmem->size); if (global_id == OPTEE_MSG_FMEM_INVALID_GLOBAL_ID && !sz) { mem->mobj = NULL; mem->offs = 0; mem->size = 0; return TEE_SUCCESS; } mem->mobj = mobj_ffa_get_by_cookie(global_id, READ_ONCE(fmem->internal_offs)); if (!mem->mobj) return TEE_ERROR_BAD_PARAMETERS; mem->offs = reg_pair_to_64(READ_ONCE(fmem->offs_high), READ_ONCE(fmem->offs_low)); mem->size = sz; /* * Check that the supplied offset and size is covered by the * previously verified MOBJ. */ if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || mem->mobj->size < req_size) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } #else /*!CFG_CORE_FFA*/ /* fill 'struct param_mem' structure if buffer matches a valid memory object */ static TEE_Result set_tmem_param(const struct optee_msg_param_tmem *tmem, uint32_t attr, struct param_mem *mem) { struct mobj __maybe_unused **mobj; paddr_t pa = READ_ONCE(tmem->buf_ptr); size_t sz = READ_ONCE(tmem->size); /* * Handle NULL memory reference */ if (!pa) { mem->mobj = NULL; mem->offs = 0; mem->size = 0; return TEE_SUCCESS; } /* Handle non-contiguous reference from a shared memory area */ if (attr & OPTEE_MSG_ATTR_NONCONTIG) { uint64_t shm_ref = READ_ONCE(tmem->shm_ref); mem->mobj = msg_param_mobj_from_noncontig(pa, sz, shm_ref, false); if (!mem->mobj) return TEE_ERROR_BAD_PARAMETERS; mem->offs = 0; mem->size = sz; return TEE_SUCCESS; } #ifdef CFG_CORE_RESERVED_SHM /* Handle memory reference in the contiguous shared memory */ if (param_mem_from_mobj(mem, shm_mobj, pa, sz)) return TEE_SUCCESS; #endif #ifdef CFG_SECURE_DATA_PATH /* Handle memory reference to Secure Data Path memory areas */ for (mobj = sdp_mem_mobjs; *mobj; mobj++) if (param_mem_from_mobj(mem, *mobj, pa, sz)) return TEE_SUCCESS; #endif return TEE_ERROR_BAD_PARAMETERS; } #ifdef CFG_CORE_DYN_SHM static TEE_Result set_rmem_param(const struct optee_msg_param_rmem *rmem, struct param_mem *mem) { size_t req_size = 0; uint64_t shm_ref = READ_ONCE(rmem->shm_ref); size_t sz = READ_ONCE(rmem->size); mem->mobj = mobj_reg_shm_get_by_cookie(shm_ref); if (!mem->mobj) return TEE_ERROR_BAD_PARAMETERS; mem->offs = READ_ONCE(rmem->offs); mem->size = sz; /* * Check that the supplied offset and size is covered by the * previously verified MOBJ. */ if (ADD_OVERFLOW(mem->offs, mem->size, &req_size) || mem->mobj->size < req_size) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } #endif /*CFG_CORE_DYN_SHM*/ #endif /*!CFG_CORE_FFA*/ static TEE_Result copy_in_params(const struct optee_msg_param *params, uint32_t num_params, struct tee_ta_param *ta_param, uint64_t *saved_attr) { TEE_Result res; size_t n; uint8_t pt[TEE_NUM_PARAMS] = { 0 }; if (num_params > TEE_NUM_PARAMS) return TEE_ERROR_BAD_PARAMETERS; memset(ta_param, 0, sizeof(*ta_param)); for (n = 0; n < num_params; n++) { uint32_t attr; saved_attr[n] = READ_ONCE(params[n].attr); if (saved_attr[n] & OPTEE_MSG_ATTR_META) return TEE_ERROR_BAD_PARAMETERS; attr = saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK; switch (attr) { case OPTEE_MSG_ATTR_TYPE_NONE: pt[n] = TEE_PARAM_TYPE_NONE; break; case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT: case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT: case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT: pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; ta_param->u[n].val.a = READ_ONCE(params[n].u.value.a); ta_param->u[n].val.b = READ_ONCE(params[n].u.value.b); break; #ifdef CFG_CORE_FFA case OPTEE_MSG_ATTR_TYPE_FMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_FMEM_INOUT: res = set_fmem_param(¶ms[n].u.fmem, &ta_param->u[n].mem); if (res) return res; pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - OPTEE_MSG_ATTR_TYPE_FMEM_INPUT; break; #else /*!CFG_CORE_FFA*/ case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: res = set_tmem_param(¶ms[n].u.tmem, saved_attr[n], &ta_param->u[n].mem); if (res) return res; pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; break; #ifdef CFG_CORE_DYN_SHM case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: res = set_rmem_param(¶ms[n].u.rmem, &ta_param->u[n].mem); if (res) return res; pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; break; #endif /*CFG_CORE_DYN_SHM*/ #endif /*!CFG_CORE_FFA*/ default: return TEE_ERROR_BAD_PARAMETERS; } } ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]); return TEE_SUCCESS; } static void cleanup_shm_refs(const uint64_t *saved_attr, struct tee_ta_param *param, uint32_t num_params) { size_t n; for (n = 0; n < MIN((unsigned int)TEE_NUM_PARAMS, num_params); n++) { switch (saved_attr[n]) { case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: #ifdef CFG_CORE_DYN_SHM case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: #endif mobj_put(param->u[n].mem.mobj); break; default: break; } } } static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params, struct optee_msg_param *params, uint64_t *saved_attr) { size_t n; for (n = 0; n < num_params; n++) { switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: switch (saved_attr[n] & OPTEE_MSG_ATTR_TYPE_MASK) { case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT: params[n].u.tmem.size = ta_param->u[n].mem.size; break; case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT: params[n].u.rmem.size = ta_param->u[n].mem.size; break; default: break; } break; case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: params[n].u.value.a = ta_param->u[n].val.a; params[n].u.value.b = ta_param->u[n].val.b; break; default: break; } } } /* * Extracts mandatory parameter for open session. * * Returns * false : mandatory parameter wasn't found or malformatted * true : paramater found and OK */ static TEE_Result get_open_session_meta(size_t num_params, struct optee_msg_param *params, size_t *num_meta, TEE_UUID *uuid, TEE_Identity *clnt_id) { const uint32_t req_attr = OPTEE_MSG_ATTR_META | OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; if (num_params < 2) return TEE_ERROR_BAD_PARAMETERS; if (params[0].attr != req_attr || params[1].attr != req_attr) return TEE_ERROR_BAD_PARAMETERS; tee_uuid_from_octets(uuid, (void *)¶ms[0].u.value); clnt_id->login = params[1].u.value.c; switch (clnt_id->login) { case TEE_LOGIN_PUBLIC: case TEE_LOGIN_REE_KERNEL: memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid)); break; case TEE_LOGIN_USER: case TEE_LOGIN_GROUP: case TEE_LOGIN_APPLICATION: case TEE_LOGIN_APPLICATION_USER: case TEE_LOGIN_APPLICATION_GROUP: tee_uuid_from_octets(&clnt_id->uuid, (void *)¶ms[1].u.value); break; default: return TEE_ERROR_BAD_PARAMETERS; } *num_meta = 2; return TEE_SUCCESS; } static void entry_open_session(struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res = TEE_ERROR_GENERIC; TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; struct tee_ta_session *s = NULL; TEE_Identity clnt_id = { }; TEE_UUID uuid = { }; struct tee_ta_param param = { }; size_t num_meta = 0; uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid, &clnt_id); if (res != TEE_SUCCESS) goto out; res = copy_in_params(arg->params + num_meta, num_params - num_meta, ¶m, saved_attr); if (res != TEE_SUCCESS) goto cleanup_shm_refs; res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid, &clnt_id, TEE_TIMEOUT_INFINITE, ¶m); if (res != TEE_SUCCESS) s = NULL; copy_out_param(¶m, num_params - num_meta, arg->params + num_meta, saved_attr); /* * The occurrence of open/close session command is usually * un-predictable, using this property to increase randomness * of prng */ plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, &session_pnum); cleanup_shm_refs: cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta); out: if (s) arg->session = s->id; else arg->session = 0; arg->ret = res; arg->ret_origin = err_orig; } static void entry_close_session(struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res; struct tee_ta_session *s; if (num_params) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, &session_pnum); s = tee_ta_find_session(arg->session, &tee_open_sessions); res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY); out: arg->ret = res; arg->ret_origin = TEE_ORIGIN_TEE; } static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res; TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; struct tee_ta_session *s; struct tee_ta_param param = { 0 }; uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; res = copy_in_params(arg->params, num_params, ¶m, saved_attr); if (res != TEE_SUCCESS) goto out; s = tee_ta_get_session(arg->session, true, &tee_open_sessions); if (!s) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY, TEE_TIMEOUT_INFINITE, arg->func, ¶m); tee_ta_put_session(s); copy_out_param(¶m, num_params, arg->params, saved_attr); out: cleanup_shm_refs(saved_attr, ¶m, num_params); arg->ret = res; arg->ret_origin = err_orig; } static void entry_cancel(struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res; TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; struct tee_ta_session *s; if (num_params) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } s = tee_ta_get_session(arg->session, false, &tee_open_sessions); if (!s) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY); tee_ta_put_session(s); out: arg->ret = res; arg->ret_origin = err_orig; } #ifndef CFG_CORE_FFA #ifdef CFG_CORE_DYN_SHM static void register_shm(struct optee_msg_arg *arg, uint32_t num_params) { struct optee_msg_param_tmem *tmem = NULL; struct mobj *mobj = NULL; arg->ret = TEE_ERROR_BAD_PARAMETERS; if (num_params != 1 || (arg->params[0].attr != (OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG))) return; tmem = &arg->params[0].u.tmem; mobj = msg_param_mobj_from_noncontig(tmem->buf_ptr, tmem->size, tmem->shm_ref, false); if (!mobj) return; mobj_reg_shm_unguard(mobj); arg->ret = TEE_SUCCESS; } static void unregister_shm(struct optee_msg_arg *arg, uint32_t num_params) { if (num_params == 1) { uint64_t cookie = arg->params[0].u.rmem.shm_ref; TEE_Result res = mobj_reg_shm_release_by_cookie(cookie); if (res) EMSG("Can't find mapping with given cookie"); arg->ret = res; } else { arg->ret = TEE_ERROR_BAD_PARAMETERS; arg->ret_origin = TEE_ORIGIN_TEE; } } #endif /*CFG_CORE_DYN_SHM*/ #endif void nsec_sessions_list_head(struct tee_ta_session_head **open_sessions) { *open_sessions = &tee_open_sessions; } /* Note: this function is weak to let platforms add special handling */ TEE_Result __weak tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) { return __tee_entry_std(arg, num_params); } /* * If tee_entry_std() is overridden, it's still supposed to call this * function. */ TEE_Result __tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res = TEE_SUCCESS; /* Enable foreign interrupts for STD calls */ thread_set_foreign_intr(true); switch (arg->cmd) { case OPTEE_MSG_CMD_OPEN_SESSION: entry_open_session(arg, num_params); break; case OPTEE_MSG_CMD_CLOSE_SESSION: entry_close_session(arg, num_params); break; case OPTEE_MSG_CMD_INVOKE_COMMAND: entry_invoke_command(arg, num_params); break; case OPTEE_MSG_CMD_CANCEL: entry_cancel(arg, num_params); break; #ifndef CFG_CORE_FFA #ifdef CFG_CORE_DYN_SHM case OPTEE_MSG_CMD_REGISTER_SHM: register_shm(arg, num_params); break; case OPTEE_MSG_CMD_UNREGISTER_SHM: unregister_shm(arg, num_params); break; #endif #endif case OPTEE_MSG_CMD_DO_BOTTOM_HALF: if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) notif_deliver_event(NOTIF_EVENT_DO_BOTTOM_HALF); else goto err; break; case OPTEE_MSG_CMD_STOP_ASYNC_NOTIF: if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) notif_deliver_event(NOTIF_EVENT_STOPPED); else goto err; break; default: err: EMSG("Unknown cmd 0x%x", arg->cmd); res = TEE_ERROR_NOT_IMPLEMENTED; } return res; } static TEE_Result default_mobj_init(void) { #ifdef CFG_CORE_RESERVED_SHM shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr, default_nsec_shm_size, SHM_CACHE_ATTRS, CORE_MEM_NSEC_SHM); if (!shm_mobj) panic("Failed to register shared memory"); #endif #ifdef CFG_SECURE_DATA_PATH sdp_mem_mobjs = core_sdp_mem_create_mobjs(); if (!sdp_mem_mobjs) panic("Failed to register SDP memory"); #endif return TEE_SUCCESS; } driver_init_late(default_mobj_init); optee_os-4.3.0/core/tee/fs_dirfile.c000066400000000000000000000176371464416617300173440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include #include #include struct tee_fs_dirfile_dirh { const struct tee_fs_dirfile_operations *fops; struct tee_file_handle *fh; int nbits; bitstr_t *files; size_t ndents; }; struct dirfile_entry { TEE_UUID uuid; uint8_t oid[TEE_OBJECT_ID_MAX_LEN]; uint32_t oidlen; uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; uint32_t file_number; }; #define OID_EMPTY_NAME 1 /* * An object can have an ID of size zero. This object is represented by * oidlen == 0 and oid[0] == OID_EMPTY_NAME. When both are zero, the entry is * not a valid object. */ static bool is_free(struct dirfile_entry *dent) { assert(dent->oidlen || !dent->oid[0] || dent->oid[0] == OID_EMPTY_NAME); return !dent->oidlen && !dent->oid[0]; } /* * File layout * * dirfile_entry.0 * ... * dirfile_entry.n * * where n the index is disconnected from file_number in struct dirfile_entry */ static TEE_Result maybe_grow_files(struct tee_fs_dirfile_dirh *dirh, int idx) { void *p; if (idx < dirh->nbits) return TEE_SUCCESS; p = realloc(dirh->files, bitstr_size(idx + 1)); if (!p) return TEE_ERROR_OUT_OF_MEMORY; dirh->files = p; bit_nclear(dirh->files, dirh->nbits, idx); dirh->nbits = idx + 1; return TEE_SUCCESS; } static TEE_Result set_file(struct tee_fs_dirfile_dirh *dirh, int idx) { TEE_Result res = maybe_grow_files(dirh, idx); if (!res) bit_set(dirh->files, idx); return res; } static void clear_file(struct tee_fs_dirfile_dirh *dirh, int idx) { if (idx < dirh->nbits) bit_clear(dirh->files, idx); } static bool test_file(struct tee_fs_dirfile_dirh *dirh, int idx) { if (idx < dirh->nbits) return bit_test(dirh->files, idx); return false; } static TEE_Result read_dent(struct tee_fs_dirfile_dirh *dirh, int idx, struct dirfile_entry *dent) { TEE_Result res; size_t l; l = sizeof(*dent); res = dirh->fops->read(dirh->fh, sizeof(struct dirfile_entry) * idx, dent, &l); if (!res && l != sizeof(*dent)) res = TEE_ERROR_ITEM_NOT_FOUND; return res; } static TEE_Result write_dent(struct tee_fs_dirfile_dirh *dirh, size_t n, struct dirfile_entry *dent) { TEE_Result res; res = dirh->fops->write(dirh->fh, sizeof(*dent) * n, dent, sizeof(*dent)); if (!res && n >= dirh->ndents) dirh->ndents = n + 1; return res; } TEE_Result tee_fs_dirfile_open(bool create, uint8_t *hash, uint32_t min_counter, const struct tee_fs_dirfile_operations *fops, struct tee_fs_dirfile_dirh **dirh_ret) { TEE_Result res; struct tee_fs_dirfile_dirh *dirh = calloc(1, sizeof(*dirh)); size_t n; if (!dirh) return TEE_ERROR_OUT_OF_MEMORY; dirh->fops = fops; res = fops->open(create, hash, min_counter, NULL, NULL, &dirh->fh); if (res) goto out; for (n = 0;; n++) { struct dirfile_entry dent = { }; res = read_dent(dirh, n, &dent); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) res = TEE_SUCCESS; goto out; } if (is_free(&dent)) continue; if (test_file(dirh, dent.file_number)) { DMSG("clearing duplicate file number %" PRIu32, dent.file_number); memset(&dent, 0, sizeof(dent)); res = write_dent(dirh, n, &dent); if (res) goto out; continue; } res = set_file(dirh, dent.file_number); if (res != TEE_SUCCESS) goto out; } out: if (!res) { dirh->ndents = n; *dirh_ret = dirh; } else { tee_fs_dirfile_close(dirh); } return res; } void tee_fs_dirfile_close(struct tee_fs_dirfile_dirh *dirh) { if (dirh) { dirh->fops->close(dirh->fh); free(dirh->files); free(dirh); } } TEE_Result tee_fs_dirfile_commit_writes(struct tee_fs_dirfile_dirh *dirh, uint8_t *hash, uint32_t *counter) { return dirh->fops->commit_writes(dirh->fh, hash, counter); } TEE_Result tee_fs_dirfile_get_tmp(struct tee_fs_dirfile_dirh *dirh, struct tee_fs_dirfile_fileh *dfh) { TEE_Result res; int i = 0; if (dirh->nbits) { bit_ffc(dirh->files, dirh->nbits, &i); if (i == -1) i = dirh->nbits; } res = set_file(dirh, i); if (!res) dfh->file_number = i; return res; } TEE_Result tee_fs_dirfile_find(struct tee_fs_dirfile_dirh *dirh, const TEE_UUID *uuid, const void *oid, size_t oidlen, struct tee_fs_dirfile_fileh *dfh) { TEE_Result res = TEE_SUCCESS; struct dirfile_entry dent = { }; int n = 0; for (n = 0;; n++) { res = read_dent(dirh, n, &dent); if (res) return res; if (is_free(&dent)) continue; if (dent.oidlen != oidlen) continue; assert(test_file(dirh, dent.file_number)); if (!memcmp(&dent.uuid, uuid, sizeof(dent.uuid)) && !memcmp(&dent.oid, oid, oidlen)) break; } if (dfh) { dfh->idx = n; dfh->file_number = dent.file_number; memcpy(dfh->hash, dent.hash, sizeof(dent.hash)); } return TEE_SUCCESS; } static TEE_Result find_empty_idx(struct tee_fs_dirfile_dirh *dh, int *idx) { struct dirfile_entry dent = { }; TEE_Result res = TEE_SUCCESS; int n = 0; for (n = 0;; n++) { res = read_dent(dh, n, &dent); if (res == TEE_ERROR_ITEM_NOT_FOUND) break; if (res) return res; if (is_free(&dent)) break; } *idx = n; return TEE_SUCCESS; } TEE_Result tee_fs_dirfile_fileh_to_fname(const struct tee_fs_dirfile_fileh *dfh, char *fname, size_t *fnlen) { int r; size_t l = *fnlen; if (dfh) r = snprintf(fname, l, "%" PRIx32, dfh->file_number); else r = snprintf(fname, l, "dirf.db"); if (r < 0) return TEE_ERROR_GENERIC; *fnlen = r + 1; if ((size_t)r >= l) return TEE_ERROR_SHORT_BUFFER; return TEE_SUCCESS; } TEE_Result tee_fs_dirfile_rename(struct tee_fs_dirfile_dirh *dirh, const TEE_UUID *uuid, struct tee_fs_dirfile_fileh *dfh, const void *oid, size_t oidlen) { TEE_Result res; struct dirfile_entry dent = { }; if (oidlen > sizeof(dent.oid)) return TEE_ERROR_BAD_PARAMETERS; memset(&dent, 0, sizeof(dent)); dent.uuid = *uuid; if (oidlen) memcpy(dent.oid, oid, oidlen); else dent.oid[0] = OID_EMPTY_NAME; dent.oidlen = oidlen; memcpy(dent.hash, dfh->hash, sizeof(dent.hash)); dent.file_number = dfh->file_number; if (dfh->idx < 0) { struct tee_fs_dirfile_fileh dfh2; res = tee_fs_dirfile_find(dirh, uuid, oid, oidlen, &dfh2); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) res = find_empty_idx(dirh, &dfh2.idx); if (res) return res; } dfh->idx = dfh2.idx; } return write_dent(dirh, dfh->idx, &dent); } TEE_Result tee_fs_dirfile_remove(struct tee_fs_dirfile_dirh *dirh, const struct tee_fs_dirfile_fileh *dfh) { TEE_Result res; struct dirfile_entry dent = { }; uint32_t file_number; res = read_dent(dirh, dfh->idx, &dent); if (res) return res; if (is_free(&dent)) return TEE_SUCCESS; file_number = dent.file_number; assert(dfh->file_number == file_number); assert(test_file(dirh, file_number)); memset(&dent, 0, sizeof(dent)); res = write_dent(dirh, dfh->idx, &dent); if (!res) clear_file(dirh, file_number); return res; } TEE_Result tee_fs_dirfile_update_hash(struct tee_fs_dirfile_dirh *dirh, const struct tee_fs_dirfile_fileh *dfh) { TEE_Result res; struct dirfile_entry dent = { }; res = read_dent(dirh, dfh->idx, &dent); if (res) return res; assert(dent.file_number == dfh->file_number); assert(test_file(dirh, dent.file_number)); memcpy(&dent.hash, dfh->hash, sizeof(dent.hash)); return write_dent(dirh, dfh->idx, &dent); } TEE_Result tee_fs_dirfile_get_next(struct tee_fs_dirfile_dirh *dirh, const TEE_UUID *uuid, int *idx, void *oid, size_t *oidlen) { TEE_Result res; int i = *idx + 1; struct dirfile_entry dent = { }; if (i < 0) i = 0; for (;; i++) { res = read_dent(dirh, i, &dent); if (res) return res; if (!memcmp(&dent.uuid, uuid, sizeof(dent.uuid)) && !is_free(&dent)) break; } if (*oidlen < dent.oidlen) return TEE_ERROR_SHORT_BUFFER; memcpy(oid, dent.oid, dent.oidlen); *oidlen = dent.oidlen; *idx = i; return TEE_SUCCESS; } optee_os-4.3.0/core/tee/fs_htree.c000066400000000000000000000532541464416617300170300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #define TEE_FS_HTREE_CHIP_ID_SIZE 32 #define TEE_FS_HTREE_HASH_ALG TEE_ALG_SHA256 #define TEE_FS_HTREE_TSK_SIZE TEE_FS_HTREE_HASH_SIZE #define TEE_FS_HTREE_ENC_ALG TEE_ALG_AES_ECB_NOPAD #define TEE_FS_HTREE_ENC_SIZE TEE_AES_BLOCK_SIZE #define TEE_FS_HTREE_SSK_SIZE TEE_FS_HTREE_HASH_SIZE #define TEE_FS_HTREE_AUTH_ENC_ALG TEE_ALG_AES_GCM #define TEE_FS_HTREE_HMAC_ALG TEE_ALG_HMAC_SHA256 #define BLOCK_NUM_TO_NODE_ID(num) ((num) + 1) #define NODE_ID_TO_BLOCK_NUM(id) ((id) - 1) /* * The hash tree is implemented as a binary tree with the purpose to ensure * integrity of the data in the nodes. The data in the nodes their turn * provides both integrity and confidentiality of the data blocks. * * The hash tree is saved in a file as: * +----------------------------+ * | htree_image.0 | * | htree_image.1 | * +----------------------------+ * | htree_node_image.1.0 | * | htree_node_image.1.1 | * +----------------------------+ * | htree_node_image.2.0 | * | htree_node_image.2.1 | * +----------------------------+ * | htree_node_image.3.0 | * | htree_node_image.3.1 | * +----------------------------+ * | htree_node_image.4.0 | * | htree_node_image.4.1 | * +----------------------------+ * ... * * htree_image is the header of the file, there's two instances of it. One * which is committed and the other is used when updating the file. Which * is committed is indicated by the "counter" field, the one with the * largest value is selected. * * htree_node_image is a node in the hash tree, each node has two instances * which is committed is decided by the parent node .flag bit * HTREE_NODE_COMMITTED_CHILD. Which version is the committed version of * node 1 is determined by the by the lowest bit of the counter field in * the header. * * Note that nodes start counting at 1 while blocks at 0, this means that * block 0 is represented by node 1. * * Where different elements are stored in the file is managed by the file * system. */ #define HTREE_NODE_COMMITTED_BLOCK BIT32(0) /* n is 0 or 1 */ #define HTREE_NODE_COMMITTED_CHILD(n) BIT32(1 + (n)) struct htree_node { size_t id; bool dirty; bool block_updated; struct tee_fs_htree_node_image node; struct htree_node *parent; struct htree_node *child[2]; }; struct tee_fs_htree { struct htree_node root; struct tee_fs_htree_image head; uint8_t fek[TEE_FS_HTREE_FEK_SIZE]; struct tee_fs_htree_imeta imeta; bool dirty; const TEE_UUID *uuid; const struct tee_fs_htree_storage *stor; void *stor_aux; }; struct traverse_arg; typedef TEE_Result (*traverse_cb_t)(struct traverse_arg *targ, struct htree_node *node); struct traverse_arg { struct tee_fs_htree *ht; traverse_cb_t cb; void *arg; }; static TEE_Result rpc_read(struct tee_fs_htree *ht, enum tee_fs_htree_type type, size_t idx, size_t vers, void *data, size_t dlen) { TEE_Result res; struct tee_fs_rpc_operation op; size_t bytes; void *p; res = ht->stor->rpc_read_init(ht->stor_aux, &op, type, idx, vers, &p); if (res != TEE_SUCCESS) return res; res = ht->stor->rpc_read_final(&op, &bytes); if (res != TEE_SUCCESS) return res; if (bytes != dlen) return TEE_ERROR_CORRUPT_OBJECT; memcpy(data, p, dlen); return TEE_SUCCESS; } static TEE_Result rpc_read_head(struct tee_fs_htree *ht, size_t vers, struct tee_fs_htree_image *head) { return rpc_read(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers, head, sizeof(*head)); } static TEE_Result rpc_read_node(struct tee_fs_htree *ht, size_t node_id, size_t vers, struct tee_fs_htree_node_image *node) { return rpc_read(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers, node, sizeof(*node)); } static TEE_Result rpc_write(struct tee_fs_htree *ht, enum tee_fs_htree_type type, size_t idx, size_t vers, const void *data, size_t dlen) { TEE_Result res; struct tee_fs_rpc_operation op; void *p; res = ht->stor->rpc_write_init(ht->stor_aux, &op, type, idx, vers, &p); if (res != TEE_SUCCESS) return res; memcpy(p, data, dlen); return ht->stor->rpc_write_final(&op); } static TEE_Result rpc_write_head(struct tee_fs_htree *ht, size_t vers, const struct tee_fs_htree_image *head) { return rpc_write(ht, TEE_FS_HTREE_TYPE_HEAD, 0, vers, head, sizeof(*head)); } static TEE_Result rpc_write_node(struct tee_fs_htree *ht, size_t node_id, size_t vers, const struct tee_fs_htree_node_image *node) { return rpc_write(ht, TEE_FS_HTREE_TYPE_NODE, node_id - 1, vers, node, sizeof(*node)); } static TEE_Result traverse_post_order(struct traverse_arg *targ, struct htree_node *node) { TEE_Result res; /* * This function is recursing but not very deep, only with Log(N) * maximum depth. */ if (!node) return TEE_SUCCESS; res = traverse_post_order(targ, node->child[0]); if (res != TEE_SUCCESS) return res; res = traverse_post_order(targ, node->child[1]); if (res != TEE_SUCCESS) return res; return targ->cb(targ, node); } static TEE_Result htree_traverse_post_order(struct tee_fs_htree *ht, traverse_cb_t cb, void *arg) { struct traverse_arg targ = { ht, cb, arg }; return traverse_post_order(&targ, &ht->root); } static size_t node_id_to_level(size_t node_id) { assert(node_id && node_id < UINT_MAX); /* Calculate level of the node, root node (1) has level 1 */ return sizeof(unsigned int) * 8 - __builtin_clz(node_id); } static struct htree_node *find_closest_node(struct tee_fs_htree *ht, size_t node_id) { struct htree_node *node = &ht->root; size_t level = node_id_to_level(node_id); size_t n; /* n = 1 because root node is level 1 */ for (n = 1; n < level; n++) { struct htree_node *child; size_t bit_idx; /* * The difference between levels of the current node and * the node we're looking for tells which bit decides * direction in the tree. * * As the first bit has index 0 we'll subtract 1 */ bit_idx = level - n - 1; child = node->child[((node_id >> bit_idx) & 1)]; if (!child) return node; node = child; } return node; } static struct htree_node *find_node(struct tee_fs_htree *ht, size_t node_id) { struct htree_node *node = find_closest_node(ht, node_id); if (node && node->id == node_id) return node; return NULL; } static TEE_Result get_node(struct tee_fs_htree *ht, bool create, size_t node_id, struct htree_node **node_ret) { struct htree_node *node; struct htree_node *nc; size_t n; node = find_closest_node(ht, node_id); if (!node) return TEE_ERROR_GENERIC; if (node->id == node_id) goto ret_node; /* * Trying to read beyond end of file should be caught earlier than * here. */ if (!create) return TEE_ERROR_GENERIC; /* * Add missing nodes, some nodes may already be there. When we've * processed the range all nodes up to node_id will be in the tree. */ for (n = node->id + 1; n <= node_id; n++) { node = find_closest_node(ht, n); if (node->id == n) continue; /* Node id n should be a child of node */ assert((n >> 1) == node->id); assert(!node->child[n & 1]); nc = calloc(1, sizeof(*nc)); if (!nc) return TEE_ERROR_OUT_OF_MEMORY; nc->id = n; nc->parent = node; node->child[n & 1] = nc; node = nc; } if (node->id > ht->imeta.max_node_id) ht->imeta.max_node_id = node->id; ret_node: *node_ret = node; return TEE_SUCCESS; } static int get_idx_from_counter(uint32_t counter0, uint32_t counter1) { if (!(counter0 & 1)) { if (!(counter1 & 1)) return 0; if (counter0 > counter1) return 0; else return 1; } if (counter1 & 1) return 1; else return -1; } static TEE_Result init_head_from_data(struct tee_fs_htree *ht, const uint8_t *hash, uint32_t min_counter) { TEE_Result res; int idx; if (hash) { for (idx = 0;; idx++) { res = rpc_read_node(ht, 1, idx, &ht->root.node); if (res != TEE_SUCCESS) return res; if (!memcmp(ht->root.node.hash, hash, sizeof(ht->root.node.hash))) { res = rpc_read_head(ht, idx, &ht->head); if (res != TEE_SUCCESS) return res; break; } if (idx) return TEE_ERROR_CORRUPT_OBJECT; } } else { struct tee_fs_htree_image head[2]; for (idx = 0; idx < 2; idx++) { res = rpc_read_head(ht, idx, head + idx); if (res != TEE_SUCCESS) return res; } idx = get_idx_from_counter(head[0].counter, head[1].counter); if (idx < 0) return TEE_ERROR_SECURITY; res = rpc_read_node(ht, 1, idx, &ht->root.node); if (res != TEE_SUCCESS) return res; ht->head = head[idx]; } if (ht->head.counter < min_counter) return TEE_ERROR_SECURITY; ht->root.id = 1; return TEE_SUCCESS; } static TEE_Result init_tree_from_data(struct tee_fs_htree *ht) { TEE_Result res; struct tee_fs_htree_node_image node_image; struct htree_node *node; struct htree_node *nc; size_t committed_version; size_t node_id = 2; while (node_id <= ht->imeta.max_node_id) { node = find_node(ht, node_id >> 1); if (!node) return TEE_ERROR_GENERIC; committed_version = !!(node->node.flags & HTREE_NODE_COMMITTED_CHILD(node_id & 1)); res = rpc_read_node(ht, node_id, committed_version, &node_image); if (res != TEE_SUCCESS) return res; res = get_node(ht, true, node_id, &nc); if (res != TEE_SUCCESS) return res; nc->node = node_image; node_id++; } return TEE_SUCCESS; } static TEE_Result calc_node_hash(struct htree_node *node, struct tee_fs_htree_meta *meta, void *ctx, uint8_t *digest) { TEE_Result res; uint8_t *ndata = (uint8_t *)&node->node + sizeof(node->node.hash); size_t nsize = sizeof(node->node) - sizeof(node->node.hash); res = crypto_hash_init(ctx); if (res != TEE_SUCCESS) return res; res = crypto_hash_update(ctx, ndata, nsize); if (res != TEE_SUCCESS) return res; if (meta) { res = crypto_hash_update(ctx, (void *)meta, sizeof(*meta)); if (res != TEE_SUCCESS) return res; } if (node->child[0]) { res = crypto_hash_update(ctx, node->child[0]->node.hash, sizeof(node->child[0]->node.hash)); if (res != TEE_SUCCESS) return res; } if (node->child[1]) { res = crypto_hash_update(ctx, node->child[1]->node.hash, sizeof(node->child[1]->node.hash)); if (res != TEE_SUCCESS) return res; } return crypto_hash_final(ctx, digest, TEE_FS_HTREE_HASH_SIZE); } static TEE_Result authenc_init(void **ctx_ret, TEE_OperationMode mode, struct tee_fs_htree *ht, struct tee_fs_htree_node_image *ni, size_t payload_len) { TEE_Result res = TEE_SUCCESS; const uint32_t alg = TEE_FS_HTREE_AUTH_ENC_ALG; void *ctx; size_t aad_len = TEE_FS_HTREE_FEK_SIZE + TEE_FS_HTREE_IV_SIZE; uint8_t *iv; if (ni) { iv = ni->iv; } else { iv = ht->head.iv; aad_len += TEE_FS_HTREE_HASH_SIZE + sizeof(ht->head.counter); } if (mode == TEE_MODE_ENCRYPT) { res = crypto_rng_read(iv, TEE_FS_HTREE_IV_SIZE); if (res != TEE_SUCCESS) return res; } res = crypto_authenc_alloc_ctx(&ctx, alg); if (res != TEE_SUCCESS) return res; res = crypto_authenc_init(ctx, mode, ht->fek, TEE_FS_HTREE_FEK_SIZE, iv, TEE_FS_HTREE_IV_SIZE, TEE_FS_HTREE_TAG_SIZE, aad_len, payload_len); if (res != TEE_SUCCESS) goto err_free; if (!ni) { res = crypto_authenc_update_aad(ctx, mode, ht->root.node.hash, TEE_FS_HTREE_FEK_SIZE); if (res != TEE_SUCCESS) goto err; res = crypto_authenc_update_aad(ctx, mode, (void *)&ht->head.counter, sizeof(ht->head.counter)); if (res != TEE_SUCCESS) goto err; } res = crypto_authenc_update_aad(ctx, mode, ht->head.enc_fek, TEE_FS_HTREE_FEK_SIZE); if (res != TEE_SUCCESS) goto err; res = crypto_authenc_update_aad(ctx, mode, iv, TEE_FS_HTREE_IV_SIZE); if (res != TEE_SUCCESS) goto err; *ctx_ret = ctx; return TEE_SUCCESS; err: crypto_authenc_final(ctx); err_free: crypto_authenc_free_ctx(ctx); return res; } static TEE_Result authenc_decrypt_final(void *ctx, const uint8_t *tag, const void *crypt, size_t len, void *plain) { TEE_Result res; size_t out_size = len; res = crypto_authenc_dec_final(ctx, crypt, len, plain, &out_size, tag, TEE_FS_HTREE_TAG_SIZE); crypto_authenc_final(ctx); crypto_authenc_free_ctx(ctx); if (res == TEE_SUCCESS && out_size != len) return TEE_ERROR_GENERIC; if (res == TEE_ERROR_MAC_INVALID) return TEE_ERROR_CORRUPT_OBJECT; return res; } static TEE_Result authenc_encrypt_final(void *ctx, uint8_t *tag, const void *plain, size_t len, void *crypt) { TEE_Result res; size_t out_size = len; size_t out_tag_size = TEE_FS_HTREE_TAG_SIZE; res = crypto_authenc_enc_final(ctx, plain, len, crypt, &out_size, tag, &out_tag_size); crypto_authenc_final(ctx); crypto_authenc_free_ctx(ctx); if (res == TEE_SUCCESS && (out_size != len || out_tag_size != TEE_FS_HTREE_TAG_SIZE)) return TEE_ERROR_GENERIC; return res; } static TEE_Result verify_root(struct tee_fs_htree *ht) { TEE_Result res; void *ctx; res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_DECRYPT, ht->head.enc_fek, sizeof(ht->fek), ht->fek); if (res != TEE_SUCCESS) return res; res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, NULL, sizeof(ht->imeta)); if (res != TEE_SUCCESS) return res; return authenc_decrypt_final(ctx, ht->head.tag, ht->head.imeta, sizeof(ht->imeta), &ht->imeta); } static TEE_Result verify_node(struct traverse_arg *targ, struct htree_node *node) { void *ctx = targ->arg; TEE_Result res; uint8_t digest[TEE_FS_HTREE_HASH_SIZE]; if (node->parent) res = calc_node_hash(node, NULL, ctx, digest); else res = calc_node_hash(node, &targ->ht->imeta.meta, ctx, digest); if (res == TEE_SUCCESS && consttime_memcmp(digest, node->node.hash, sizeof(digest))) return TEE_ERROR_CORRUPT_OBJECT; return res; } static TEE_Result verify_tree(struct tee_fs_htree *ht) { TEE_Result res; void *ctx; res = crypto_hash_alloc_ctx(&ctx, TEE_FS_HTREE_HASH_ALG); if (res != TEE_SUCCESS) return res; res = htree_traverse_post_order(ht, verify_node, ctx); crypto_hash_free_ctx(ctx); return res; } static TEE_Result init_root_node(struct tee_fs_htree *ht) { TEE_Result res; void *ctx; res = crypto_hash_alloc_ctx(&ctx, TEE_FS_HTREE_HASH_ALG); if (res != TEE_SUCCESS) return res; ht->root.id = 1; ht->root.dirty = true; res = calc_node_hash(&ht->root, &ht->imeta.meta, ctx, ht->root.node.hash); crypto_hash_free_ctx(ctx); return res; } TEE_Result tee_fs_htree_open(bool create, uint8_t *hash, uint32_t min_counter, const TEE_UUID *uuid, const struct tee_fs_htree_storage *stor, void *stor_aux, struct tee_fs_htree **ht_ret) { TEE_Result res; struct tee_fs_htree *ht = calloc(1, sizeof(*ht)); if (!ht) return TEE_ERROR_OUT_OF_MEMORY; ht->uuid = uuid; ht->stor = stor; ht->stor_aux = stor_aux; if (create) { const struct tee_fs_htree_image dummy_head = { .counter = min_counter, }; res = crypto_rng_read(ht->fek, sizeof(ht->fek)); if (res != TEE_SUCCESS) goto out; res = tee_fs_fek_crypt(ht->uuid, TEE_MODE_ENCRYPT, ht->fek, sizeof(ht->fek), ht->head.enc_fek); if (res != TEE_SUCCESS) goto out; res = init_root_node(ht); if (res != TEE_SUCCESS) goto out; ht->dirty = true; res = tee_fs_htree_sync_to_storage(&ht, hash, NULL); if (res != TEE_SUCCESS) goto out; res = rpc_write_head(ht, 0, &dummy_head); } else { res = init_head_from_data(ht, hash, min_counter); if (res != TEE_SUCCESS) goto out; res = verify_root(ht); if (res != TEE_SUCCESS) goto out; res = init_tree_from_data(ht); if (res != TEE_SUCCESS) goto out; res = verify_tree(ht); } out: if (res == TEE_SUCCESS) *ht_ret = ht; else tee_fs_htree_close(&ht); return res; } struct tee_fs_htree_meta *tee_fs_htree_get_meta(struct tee_fs_htree *ht) { return &ht->imeta.meta; } void tee_fs_htree_meta_set_dirty(struct tee_fs_htree *ht) { ht->dirty = true; ht->root.dirty = true; } static TEE_Result free_node(struct traverse_arg *targ __unused, struct htree_node *node) { if (node->parent) free(node); return TEE_SUCCESS; } void tee_fs_htree_close(struct tee_fs_htree **ht) { if (!*ht) return; htree_traverse_post_order(*ht, free_node, NULL); free(*ht); *ht = NULL; } static TEE_Result htree_sync_node_to_storage(struct traverse_arg *targ, struct htree_node *node) { TEE_Result res; uint8_t vers; struct tee_fs_htree_meta *meta = NULL; /* * The node can be dirty while the block isn't updated due to * updated children, but if block is updated the node has to be * dirty. */ assert(node->dirty >= node->block_updated); if (!node->dirty) return TEE_SUCCESS; if (node->parent) { uint32_t f = HTREE_NODE_COMMITTED_CHILD(node->id & 1); node->parent->dirty = true; node->parent->node.flags ^= f; vers = !!(node->parent->node.flags & f); } else { /* * Counter isn't updated yet, it's increased just before * writing the header. */ vers = !(targ->ht->head.counter & 1); meta = &targ->ht->imeta.meta; } res = calc_node_hash(node, meta, targ->arg, node->node.hash); if (res != TEE_SUCCESS) return res; node->dirty = false; node->block_updated = false; return rpc_write_node(targ->ht, node->id, vers, &node->node); } static TEE_Result update_root(struct tee_fs_htree *ht) { TEE_Result res; void *ctx; ht->head.counter++; res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, NULL, sizeof(ht->imeta)); if (res != TEE_SUCCESS) return res; return authenc_encrypt_final(ctx, ht->head.tag, &ht->imeta, sizeof(ht->imeta), &ht->head.imeta); } TEE_Result tee_fs_htree_sync_to_storage(struct tee_fs_htree **ht_arg, uint8_t *hash, uint32_t *counter) { TEE_Result res; struct tee_fs_htree *ht = *ht_arg; void *ctx; if (!ht) return TEE_ERROR_CORRUPT_OBJECT; if (!ht->dirty) return TEE_SUCCESS; res = crypto_hash_alloc_ctx(&ctx, TEE_FS_HTREE_HASH_ALG); if (res != TEE_SUCCESS) return res; res = htree_traverse_post_order(ht, htree_sync_node_to_storage, ctx); if (res != TEE_SUCCESS) goto out; /* All the nodes are written to storage now. Time to update root. */ res = update_root(ht); if (res != TEE_SUCCESS) goto out; res = rpc_write_head(ht, ht->head.counter & 1, &ht->head); if (res != TEE_SUCCESS) goto out; ht->dirty = false; if (hash) memcpy(hash, ht->root.node.hash, sizeof(ht->root.node.hash)); if (counter) *counter = ht->head.counter; out: crypto_hash_free_ctx(ctx); if (res != TEE_SUCCESS) tee_fs_htree_close(ht_arg); return res; } static TEE_Result get_block_node(struct tee_fs_htree *ht, bool create, size_t block_num, struct htree_node **node) { TEE_Result res; struct htree_node *nd; res = get_node(ht, create, BLOCK_NUM_TO_NODE_ID(block_num), &nd); if (res == TEE_SUCCESS) *node = nd; return res; } TEE_Result tee_fs_htree_write_block(struct tee_fs_htree **ht_arg, size_t block_num, const void *block) { struct tee_fs_htree *ht = *ht_arg; TEE_Result res; struct tee_fs_rpc_operation op; struct htree_node *node = NULL; uint8_t block_vers; void *ctx; void *enc_block; if (!ht) return TEE_ERROR_CORRUPT_OBJECT; res = get_block_node(ht, true, block_num, &node); if (res != TEE_SUCCESS) goto out; if (!node->block_updated) node->node.flags ^= HTREE_NODE_COMMITTED_BLOCK; block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK); res = ht->stor->rpc_write_init(ht->stor_aux, &op, TEE_FS_HTREE_TYPE_BLOCK, block_num, block_vers, &enc_block); if (res != TEE_SUCCESS) goto out; res = authenc_init(&ctx, TEE_MODE_ENCRYPT, ht, &node->node, ht->stor->block_size); if (res != TEE_SUCCESS) goto out; res = authenc_encrypt_final(ctx, node->node.tag, block, ht->stor->block_size, enc_block); if (res != TEE_SUCCESS) goto out; res = ht->stor->rpc_write_final(&op); if (res != TEE_SUCCESS) goto out; node->block_updated = true; node->dirty = true; ht->dirty = true; out: if (res != TEE_SUCCESS) tee_fs_htree_close(ht_arg); return res; } TEE_Result tee_fs_htree_read_block(struct tee_fs_htree **ht_arg, size_t block_num, void *block) { struct tee_fs_htree *ht = *ht_arg; TEE_Result res; struct tee_fs_rpc_operation op; struct htree_node *node; uint8_t block_vers; size_t len; void *ctx; void *enc_block; if (!ht) return TEE_ERROR_CORRUPT_OBJECT; res = get_block_node(ht, false, block_num, &node); if (res != TEE_SUCCESS) goto out; block_vers = !!(node->node.flags & HTREE_NODE_COMMITTED_BLOCK); res = ht->stor->rpc_read_init(ht->stor_aux, &op, TEE_FS_HTREE_TYPE_BLOCK, block_num, block_vers, &enc_block); if (res != TEE_SUCCESS) goto out; res = ht->stor->rpc_read_final(&op, &len); if (res != TEE_SUCCESS) goto out; if (len != ht->stor->block_size) { res = TEE_ERROR_CORRUPT_OBJECT; goto out; } res = authenc_init(&ctx, TEE_MODE_DECRYPT, ht, &node->node, ht->stor->block_size); if (res != TEE_SUCCESS) goto out; res = authenc_decrypt_final(ctx, node->node.tag, enc_block, ht->stor->block_size, block); out: if (res != TEE_SUCCESS) tee_fs_htree_close(ht_arg); return res; } TEE_Result tee_fs_htree_truncate(struct tee_fs_htree **ht_arg, size_t block_num) { struct tee_fs_htree *ht = *ht_arg; size_t node_id = BLOCK_NUM_TO_NODE_ID(block_num); struct htree_node *node; if (!ht) return TEE_ERROR_CORRUPT_OBJECT; while (node_id < ht->imeta.max_node_id) { node = find_closest_node(ht, ht->imeta.max_node_id); assert(node && node->id == ht->imeta.max_node_id); assert(!node->child[0] && !node->child[1]); assert(node->parent); assert(node->parent->child[node->id & 1] == node); node->parent->child[node->id & 1] = NULL; free(node); ht->imeta.max_node_id--; ht->dirty = true; } return TEE_SUCCESS; } optee_os-4.3.0/core/tee/socket.c000066400000000000000000000175061464416617300165210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2017, Linaro Limited */ #include #include #include #include #include #include #include #include static uint32_t get_instance_id(struct ts_session *sess) { return sess->ctx->ops->get_instance_id(sess->ctx); } static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct thread_param tpm[4] = { }; struct mobj *mobj = NULL; TEE_Result res = TEE_SUCCESS; void *va = NULL; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT); if (exp_pt != param_types) { DMSG("got param_types 0x%x, expected 0x%x", param_types, exp_pt); return TEE_ERROR_BAD_PARAMETERS; } va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, THREAD_SHM_TYPE_APPLICATION, params[1].memref.size, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; res = copy_from_user(va, params[1].memref.buffer, params[1].memref.size); if (res) return res; tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_OPEN, instance_id, 0); tpm[1] = THREAD_PARAM_VALUE(IN, params[0].value.b, /* server port number */ params[2].value.a, /* protocol */ params[0].value.a /* ip version */); tpm[2] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size); tpm[3] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 4, tpm); if (res == TEE_SUCCESS) params[3].value.a = tpm[3].u.value.a; return res; } static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct thread_param tpm = { }; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) { DMSG("got param_types 0x%x, expected 0x%x", param_types, exp_pt); return TEE_ERROR_BAD_PARAMETERS; } tpm = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_CLOSE, instance_id, params[0].value.a); return thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); } static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct thread_param tpm[3] = { }; struct mobj *mobj = NULL; TEE_Result res = TEE_SUCCESS; void *va = NULL; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) { DMSG("got param_types 0x%x, expected 0x%x", param_types, exp_pt); return TEE_ERROR_BAD_PARAMETERS; } va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, THREAD_SHM_TYPE_APPLICATION, params[1].memref.size, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; res = copy_from_user(va, params[1].memref.buffer, params[1].memref.size); if (res) return res; tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_SEND, instance_id, params[0].value.a /* handle */); tpm[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, params[1].memref.size); tpm[2] = THREAD_PARAM_VALUE(INOUT, params[0].value.b, /* timeout */ 0, 0); res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); params[2].value.a = tpm[2].u.value.b; /* transmitted bytes */ return res; } static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct thread_param tpm[3] = { }; struct mobj *mobj = NULL; TEE_Result res = TEE_SUCCESS; void *va = NULL; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) { DMSG("got param_types 0x%x, expected 0x%x", param_types, exp_pt); return TEE_ERROR_BAD_PARAMETERS; } if (params[1].memref.size) { va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, THREAD_SHM_TYPE_APPLICATION, params[1].memref.size, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; } tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_RECV, instance_id, params[0].value.a /* handle */); tpm[1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, params[1].memref.size); tpm[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* timeout */, 0, 0); res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); if (params[1].memref.size) { TEE_Result res2 = TEE_SUCCESS; res2 = copy_to_user(params[1].memref.buffer, va, MIN(params[1].memref.size, tpm[1].u.memref.size)); if (res2) return res2; } params[1].memref.size = tpm[1].u.memref.size; return res; } static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { struct thread_param tpm[3] = { }; struct mobj *mobj = NULL; TEE_Result res = TEE_SUCCESS; void *va = NULL; uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (exp_pt != param_types) { DMSG("got param_types 0x%x, expected 0x%x", param_types, exp_pt); return TEE_ERROR_BAD_PARAMETERS; } va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_SOCKET, THREAD_SHM_TYPE_APPLICATION, params[1].memref.size, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; res = copy_from_user(va, params[1].memref.buffer, params[1].memref.size); if (res) return res; tpm[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SOCKET_IOCTL, instance_id, params[0].value.a /* handle */); tpm[1] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, params[1].memref.size); tpm[2] = THREAD_PARAM_VALUE(IN, params[0].value.b /* ioctl command */, 0, 0); res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 3, tpm); if (tpm[1].u.memref.size <= params[1].memref.size) { TEE_Result res2 = TEE_SUCCESS; res2 = copy_to_user(params[1].memref.buffer, va, tpm[1].u.memref.size); if (res2) return res2; } params[1].memref.size = tpm[1].u.memref.size; return res; } typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]); static const ta_func ta_funcs[] = { [PTA_SOCKET_OPEN] = socket_open, [PTA_SOCKET_CLOSE] = socket_close, [PTA_SOCKET_SEND] = socket_send, [PTA_SOCKET_RECV] = socket_recv, [PTA_SOCKET_IOCTL] = socket_ioctl, }; /* * Trusted Application Entry Points */ static TEE_Result pta_socket_open_session(uint32_t param_types __unused, TEE_Param pParams[TEE_NUM_PARAMS] __unused, void **sess_ctx) { struct ts_session *s = ts_get_calling_session(); /* Check that we're called from a TA */ if (!s || !is_user_ta_ctx(s->ctx)) return TEE_ERROR_ACCESS_DENIED; *sess_ctx = (void *)(vaddr_t)get_instance_id(s); return TEE_SUCCESS; } static void pta_socket_close_session(void *sess_ctx) { TEE_Result res; struct thread_param tpm = { .attr = THREAD_PARAM_ATTR_VALUE_IN, .u.value = { .a = OPTEE_RPC_SOCKET_CLOSE_ALL, .b = (vaddr_t)sess_ctx, }, }; res = thread_rpc_cmd(OPTEE_RPC_CMD_SOCKET, 1, &tpm); if (res != TEE_SUCCESS) DMSG("OPTEE_RPC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res); } static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id]) return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params); return TEE_ERROR_NOT_IMPLEMENTED; } pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket", .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT, .open_session_entry_point = pta_socket_open_session, .close_session_entry_point = pta_socket_close_session, .invoke_command_entry_point = pta_socket_invoke_command); optee_os-4.3.0/core/tee/sub.mk000066400000000000000000000026141464416617300162010ustar00rootroot00000000000000CFG_CRYPTO ?= y ifeq (y,$(CFG_CRYPTO)) # HMAC-based Extract-and-Expand Key Derivation Function # http://tools.ietf.org/html/rfc5869 # This is an OP-TEE extension, not part of the GlobalPlatform Internal API v1.0 CFG_CRYPTO_HKDF ?= y # NIST SP800-56A Concatenation Key Derivation Function # This is an OP-TEE extension CFG_CRYPTO_CONCAT_KDF ?= y # PKCS #5 v2.0 / RFC 2898 key derivation function 2 # This is an OP-TEE extension CFG_CRYPTO_PBKDF2 ?= y endif srcs-y += entry_std.c srcs-y += tee_cryp_utl.c srcs-$(CFG_CRYPTO_HKDF) += tee_cryp_hkdf.c srcs-$(CFG_CRYPTO_CONCAT_KDF) += tee_cryp_concat_kdf.c ifneq ($(CFG_CRYPTO_HW_PBKDF2),y) srcs-$(CFG_CRYPTO_PBKDF2) += tee_cryp_pbkdf2.c endif ifeq ($(CFG_WITH_USER_TA),y) srcs-y += tee_obj.c srcs-y += tee_svc.c srcs-y += tee_svc_cryp.c srcs-y += tee_svc_storage.c cppflags-tee_svc.c-y += -DTEE_IMPL_VERSION=$(TEE_IMPL_VERSION) srcs-y += tee_time_generic.c srcs-$(CFG_SECSTOR_TA) += tadb.c srcs-$(CFG_GP_SOCKETS) += socket.c srcs-y += tee_ta_enc_manager.c endif #CFG_WITH_USER_TA,y srcs-$(_CFG_WITH_SECURE_STORAGE) += tee_fs_key_manager.c srcs-$(CFG_RPMB_FS) += tee_rpmb_fs.c srcs-$(CFG_REE_FS) += tee_ree_fs.c srcs-$(CFG_REE_FS) += fs_dirfile.c srcs-$(CFG_REE_FS) += fs_htree.c srcs-$(CFG_REE_FS) += tee_fs_rpc.c ifeq ($(call cfg-one-enabled,CFG_WITH_USER_TA _CFG_WITH_SECURE_STORAGE),y) srcs-y += tee_pobj.c endif srcs-y += uuid.c srcs-y += tee_supp_plugin_rpc.c optee_os-4.3.0/core/tee/tadb.c000066400000000000000000000413221464416617300161340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define TADB_MAX_BUFFER_SIZE (64U * 1024) #define TADB_AUTH_ENC_ALG TEE_ALG_AES_GCM #define TADB_IV_SIZE TEE_AES_BLOCK_SIZE #define TADB_TAG_SIZE TEE_AES_BLOCK_SIZE #define TADB_KEY_SIZE TEE_AES_MAX_KEY_SIZE struct tee_tadb_dir { const struct tee_file_operations *ops; struct tee_file_handle *fh; int nbits; bitstr_t *files; }; /* * struct tadb_entry - TA database entry * @prop: properties of TA * @file_number: encrypted TA is stored in .ta * @iv: Initialization vector of the authentication crypto * @tag: Tag used to validate the authentication encrypted TA * @key: Key used to decrypt the TA */ struct tadb_entry { struct tee_tadb_property prop; uint32_t file_number; uint8_t iv[TADB_IV_SIZE]; uint8_t tag[TADB_TAG_SIZE]; uint8_t key[TADB_KEY_SIZE]; }; struct tadb_header { uint32_t opaque_len; uint8_t opaque[]; }; struct tee_tadb_ta_write { struct tee_tadb_dir *db; int fd; struct tadb_entry entry; size_t pos; void *ctx; }; struct tee_tadb_ta_read { struct tee_tadb_dir *db; int fd; struct tadb_entry entry; size_t pos; void *ctx; struct mobj *ta_mobj; uint8_t *ta_buf; }; static const char tadb_obj_id[] = "ta.db"; static struct tee_tadb_dir *tadb_db; static unsigned int tadb_db_refc; static struct mutex tadb_mutex = MUTEX_INITIALIZER; static void file_num_to_str(char *buf, size_t blen, uint32_t file_number) { int rc __maybe_unused = 0; rc = snprintf(buf, blen, "%" PRIu32 ".ta", file_number); assert(rc >= 0); } static bool is_null_uuid(const TEE_UUID *uuid) { const TEE_UUID null_uuid = { 0 }; return !memcmp(uuid, &null_uuid, sizeof(*uuid)); } static TEE_Result ta_operation_open(unsigned int cmd, uint32_t file_number, int *fd) { struct thread_param params[3] = { }; struct mobj *mobj = NULL; TEE_Result res = TEE_SUCCESS; void *va = NULL; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, THREAD_SHM_TYPE_APPLICATION, TEE_FS_NAME_MAX, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; file_num_to_str(va, TEE_FS_NAME_MAX, file_number); params[0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0); params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX); params[2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0); res = thread_rpc_cmd(OPTEE_RPC_CMD_FS, ARRAY_SIZE(params), params); if (!res) *fd = params[2].u.value.a; return res; } static TEE_Result ta_operation_remove(uint32_t file_number) { struct thread_param params[2] = { }; struct mobj *mobj = NULL; void *va = NULL; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, THREAD_SHM_TYPE_APPLICATION, TEE_FS_NAME_MAX, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; file_num_to_str(va, TEE_FS_NAME_MAX, file_number); params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0); params[1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX); return thread_rpc_cmd(OPTEE_RPC_CMD_FS, ARRAY_SIZE(params), params); } static TEE_Result maybe_grow_files(struct tee_tadb_dir *db, int idx) { void *p; if (idx < db->nbits) return TEE_SUCCESS; p = realloc(db->files, bitstr_size(idx + 1)); if (!p) return TEE_ERROR_OUT_OF_MEMORY; db->files = p; bit_nclear(db->files, db->nbits, idx); db->nbits = idx + 1; return TEE_SUCCESS; } static TEE_Result set_file(struct tee_tadb_dir *db, int idx) { TEE_Result res = maybe_grow_files(db, idx); if (!res) bit_set(db->files, idx); return res; } static void clear_file(struct tee_tadb_dir *db, int idx) { /* * This is safe because db->nbits > 0 implies that * db->files is non-NULL (see maybe_grow_files()). */ if (idx < db->nbits) bit_clear(db->files, idx); } static bool test_file(struct tee_tadb_dir *db, int idx) { /* * This is safe because db->nbits > 0 implies that * db->files is non-NULL (see maybe_grow_files()). */ if (idx < db->nbits) return bit_test(db->files, idx); return false; } static TEE_Result read_ent(struct tee_tadb_dir *db, size_t idx, struct tadb_entry *entry) { size_t l = sizeof(*entry); TEE_Result res = db->ops->read(db->fh, idx * l, entry, NULL, &l); if (!res && l != sizeof(*entry)) return TEE_ERROR_ITEM_NOT_FOUND; return res; } static TEE_Result write_ent(struct tee_tadb_dir *db, size_t idx, const struct tadb_entry *entry) { const size_t l = sizeof(*entry); return db->ops->write(db->fh, idx * l, entry, NULL, l); } static TEE_Result tadb_open(struct tee_tadb_dir **db_ret) { TEE_Result res; struct tee_tadb_dir *db = calloc(1, sizeof(*db)); struct tee_pobj po = { .obj_id = (void *)tadb_obj_id, .obj_id_len = sizeof(tadb_obj_id) }; if (!db) return TEE_ERROR_OUT_OF_MEMORY; db->ops = tee_svc_storage_file_ops(TEE_STORAGE_PRIVATE); res = db->ops->open(&po, NULL, &db->fh); if (res == TEE_ERROR_ITEM_NOT_FOUND) res = db->ops->create(&po, false, NULL, 0, NULL, 0, NULL, NULL, 0, &db->fh); if (res) free(db); else *db_ret = db; return res; } static TEE_Result tee_tadb_open(struct tee_tadb_dir **db) { TEE_Result res = TEE_SUCCESS; mutex_lock(&tadb_mutex); if (!tadb_db_refc) { assert(!tadb_db); res = tadb_open(&tadb_db); if (res) goto err; } tadb_db_refc++; *db = tadb_db; err: mutex_unlock(&tadb_mutex); return res; } static void tadb_put(struct tee_tadb_dir *db) { assert(db == tadb_db); mutex_lock(&tadb_mutex); assert(tadb_db_refc); tadb_db_refc--; if (!tadb_db_refc) { db->ops->close(&db->fh); free(db->files); free(db); tadb_db = NULL; } mutex_unlock(&tadb_mutex); } static void tee_tadb_close(struct tee_tadb_dir *db) { tadb_put(db); } static TEE_Result tadb_authenc_init(TEE_OperationMode mode, const struct tadb_entry *entry, void **ctx_ret) { TEE_Result res; void *ctx; const size_t enc_size = entry->prop.custom_size + entry->prop.bin_size; res = crypto_authenc_alloc_ctx(&ctx, TADB_AUTH_ENC_ALG); if (res) return res; res = crypto_authenc_init(ctx, mode, entry->key, sizeof(entry->key), entry->iv, sizeof(entry->iv), sizeof(entry->tag), 0, enc_size); if (res) crypto_authenc_free_ctx(ctx); else *ctx_ret = ctx; return res; } static TEE_Result tadb_update_payload(void *ctx, TEE_OperationMode mode, const void *src, size_t len, void *dst) { TEE_Result res; size_t sz = len; res = crypto_authenc_update_payload(ctx, mode, (const uint8_t *)src, len, dst, &sz); assert(res || sz == len); return res; } static TEE_Result populate_files(struct tee_tadb_dir *db) { TEE_Result res; size_t idx; /* * If db->files isn't NULL the bitfield is already populated and * there's nothing left to do here for now. */ if (db->nbits) return TEE_SUCCESS; /* * Iterate over the TA database and set the bits in the bit field * for used file numbers. Note that set_file() will allocate and * grow the bitfield as needed. * * At the same time clean out duplicate file numbers, the first * entry with the file number has precedence. Duplicate entries is * not supposed to be able to happen, but if it still does better * to clean it out here instead of letting the error spread with * unexpected side effects. */ for (idx = 0;; idx++) { struct tadb_entry entry = { }; res = read_ent(db, idx, &entry); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) return TEE_SUCCESS; goto err; } if (is_null_uuid(&entry.prop.uuid)) continue; if (test_file(db, entry.file_number)) { IMSG("Clearing duplicate file number %" PRIu32, entry.file_number); memset(&entry, 0, sizeof(entry)); res = write_ent(db, idx, &entry); if (res) goto err; continue; } res = set_file(db, entry.file_number); if (res) goto err; } err: free(db->files); db->files = NULL; db->nbits = 0; return res; } TEE_Result tee_tadb_ta_create(const struct tee_tadb_property *property, struct tee_tadb_ta_write **ta_ret) { TEE_Result res; struct tee_tadb_ta_write *ta; int i = 0; if (is_null_uuid(&property->uuid)) return TEE_ERROR_GENERIC; ta = calloc(1, sizeof(*ta)); if (!ta) return TEE_ERROR_OUT_OF_MEMORY; res = tee_tadb_open(&ta->db); if (res) goto err_free; mutex_lock(&tadb_mutex); /* * Since we're going to search for next free file number below we * need to populate the bitfield holding used file numbers. */ res = populate_files(ta->db); if (res) goto err_mutex; if (ta->db->files) { bit_ffc(ta->db->files, ta->db->nbits, &i); if (i == -1) i = ta->db->nbits; } res = set_file(ta->db, i); if (res) goto err_mutex; mutex_unlock(&tadb_mutex); ta->entry.file_number = i; ta->entry.prop = *property; res = crypto_rng_read(ta->entry.iv, sizeof(ta->entry.iv)); if (res) goto err_put; res = crypto_rng_read(ta->entry.key, sizeof(ta->entry.key)); if (res) goto err_put; res = ta_operation_open(OPTEE_RPC_FS_CREATE, ta->entry.file_number, &ta->fd); if (res) goto err_put; res = tadb_authenc_init(TEE_MODE_ENCRYPT, &ta->entry, &ta->ctx); if (res) goto err_put; *ta_ret = ta; return TEE_SUCCESS; err_mutex: mutex_unlock(&tadb_mutex); err_put: tadb_put(ta->db); err_free: free(ta); return res; } TEE_Result tee_tadb_ta_write(struct tee_tadb_ta_write *ta, const void *buf, size_t len) { TEE_Result res; const uint8_t *rb = buf; size_t rl = len; struct tee_fs_rpc_operation op; while (rl) { size_t wl = MIN(rl, TADB_MAX_BUFFER_SIZE); void *wb; res = tee_fs_rpc_write_init(&op, OPTEE_RPC_CMD_FS, ta->fd, ta->pos, wl, &wb); if (res) return res; res = tadb_update_payload(ta->ctx, TEE_MODE_ENCRYPT, rb, wl, wb); if (res) return res; res = tee_fs_rpc_write_final(&op); if (res) return res; rl -= wl; rb += wl; ta->pos += wl; } return TEE_SUCCESS; } void tee_tadb_ta_close_and_delete(struct tee_tadb_ta_write *ta) { crypto_authenc_final(ta->ctx); crypto_authenc_free_ctx(ta->ctx); tee_fs_rpc_close(OPTEE_RPC_CMD_FS, ta->fd); ta_operation_remove(ta->entry.file_number); mutex_lock(&tadb_mutex); clear_file(ta->db, ta->entry.file_number); mutex_unlock(&tadb_mutex); tadb_put(ta->db); free(ta); } static TEE_Result find_ent(struct tee_tadb_dir *db, const TEE_UUID *uuid, size_t *idx_ret, struct tadb_entry *entry_ret) { TEE_Result res; size_t idx; /* * Search for the provided uuid, if it's found return the index it * has together with TEE_SUCCESS. * * If the uuid can't be found return the number indexes together * with TEE_ERROR_ITEM_NOT_FOUND. */ for (idx = 0;; idx++) { struct tadb_entry entry = { }; res = read_ent(db, idx, &entry); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) break; return res; } if (!memcmp(&entry.prop.uuid, uuid, sizeof(*uuid))) { if (entry_ret) *entry_ret = entry; break; } } *idx_ret = idx; return res; } static TEE_Result find_free_ent_idx(struct tee_tadb_dir *db, size_t *idx) { const TEE_UUID null_uuid = { 0 }; TEE_Result res = find_ent(db, &null_uuid, idx, NULL); /* * Note that *idx is set to the number of entries on * TEE_ERROR_ITEM_NOT_FOUND. */ if (res == TEE_ERROR_ITEM_NOT_FOUND) return TEE_SUCCESS; return res; } TEE_Result tee_tadb_ta_close_and_commit(struct tee_tadb_ta_write *ta) { TEE_Result res; size_t dsz = 0; size_t sz = sizeof(ta->entry.tag); size_t idx; struct tadb_entry old_ent; bool have_old_ent = false; res = crypto_authenc_enc_final(ta->ctx, NULL, 0, NULL, &dsz, ta->entry.tag, &sz); if (res) goto err; tee_fs_rpc_close(OPTEE_RPC_CMD_FS, ta->fd); mutex_lock(&tadb_mutex); /* * First try to find an existing TA to replace. If there's one * we'll use the entry, but we should also remove the old encrypted * file. * * If there isn't an existing TA to replace, grab a new entry. */ res = find_ent(ta->db, &ta->entry.prop.uuid, &idx, &old_ent); if (!res) { have_old_ent = true; } else { res = find_free_ent_idx(ta->db, &idx); if (res) goto err_mutex; } res = write_ent(ta->db, idx, &ta->entry); if (res) goto err_mutex; if (have_old_ent) clear_file(ta->db, old_ent.file_number); mutex_unlock(&tadb_mutex); crypto_authenc_final(ta->ctx); crypto_authenc_free_ctx(ta->ctx); tadb_put(ta->db); free(ta); if (have_old_ent) ta_operation_remove(old_ent.file_number); return TEE_SUCCESS; err_mutex: mutex_unlock(&tadb_mutex); err: tee_tadb_ta_close_and_delete(ta); return res; } TEE_Result tee_tadb_ta_delete(const TEE_UUID *uuid) { const struct tadb_entry null_entry = { { { 0 } } }; struct tee_tadb_dir *db; struct tadb_entry entry; size_t idx; TEE_Result res; if (is_null_uuid(uuid)) return TEE_ERROR_GENERIC; res = tee_tadb_open(&db); if (res) return res; mutex_lock(&tadb_mutex); res = find_ent(db, uuid, &idx, &entry); if (res) { mutex_unlock(&tadb_mutex); tee_tadb_close(db); return res; } clear_file(db, entry.file_number); res = write_ent(db, idx, &null_entry); mutex_unlock(&tadb_mutex); tee_tadb_close(db); if (res) return res; ta_operation_remove(entry.file_number); return TEE_SUCCESS; } TEE_Result tee_tadb_ta_open(const TEE_UUID *uuid, struct tee_tadb_ta_read **ta_ret) { TEE_Result res = TEE_SUCCESS; size_t idx = 0; struct tee_tadb_ta_read *ta = NULL; if (is_null_uuid(uuid)) return TEE_ERROR_GENERIC; ta = calloc(1, sizeof(*ta)); if (!ta) return TEE_ERROR_OUT_OF_MEMORY; res = tee_tadb_open(&ta->db); if (res) goto err_free; /* Mustn't call tadb_put() */ mutex_read_lock(&tadb_mutex); res = find_ent(ta->db, uuid, &idx, &ta->entry); mutex_read_unlock(&tadb_mutex); if (res) goto err; res = ta_operation_open(OPTEE_RPC_FS_OPEN, ta->entry.file_number, &ta->fd); if (res) goto err; res = tadb_authenc_init(TEE_MODE_DECRYPT, &ta->entry, &ta->ctx); if (res) goto err; *ta_ret = ta; return TEE_SUCCESS; err: tadb_put(ta->db); err_free: free(ta); return res; } const struct tee_tadb_property * tee_tadb_ta_get_property(struct tee_tadb_ta_read *ta) { return &ta->entry.prop; } TEE_Result tee_tadb_get_tag(struct tee_tadb_ta_read *ta, uint8_t *tag, unsigned int *tag_len) { if (!tag || *tag_len < sizeof(ta->entry.tag)) { *tag_len = sizeof(ta->entry.tag); return TEE_ERROR_SHORT_BUFFER; } *tag_len = sizeof(ta->entry.tag); memcpy(tag, ta->entry.tag, sizeof(ta->entry.tag)); return TEE_SUCCESS; } static TEE_Result ta_load(struct tee_tadb_ta_read *ta) { struct thread_param params[2] = { }; TEE_Result res; const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; if (ta->ta_mobj) return TEE_SUCCESS; ta->ta_mobj = thread_rpc_alloc_payload(sz); if (!ta->ta_mobj) return TEE_ERROR_OUT_OF_MEMORY; ta->ta_buf = mobj_get_va(ta->ta_mobj, 0, sz); assert(ta->ta_buf); params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, ta->fd, 0); params[1] = THREAD_PARAM_MEMREF(OUT, ta->ta_mobj, 0, sz); res = thread_rpc_cmd(OPTEE_RPC_CMD_FS, ARRAY_SIZE(params), params); if (res) { thread_rpc_free_payload(ta->ta_mobj); ta->ta_mobj = NULL; } return res; } TEE_Result tee_tadb_ta_read(struct tee_tadb_ta_read *ta, void *buf_core, void *buf_user, size_t *len) { TEE_Result res = TEE_SUCCESS; const size_t sz = ta->entry.prop.custom_size + ta->entry.prop.bin_size; size_t l = MIN(*len, sz - ta->pos); size_t bb_len = MIN(1024U, l); size_t num_bytes = 0; size_t dst_len = 0; void *dst = NULL; void *bb = NULL; res = ta_load(ta); if (res) return res; if (buf_core) { dst = buf_core; dst_len = l; } else { bb = bb_alloc(bb_len); if (!bb) return TEE_ERROR_OUT_OF_MEMORY; dst = bb; dst_len = bb_len; } /* * This loop will only run once if buf_core is non-NULL, but as * many times as needed if the bounce buffer bb is used. That's why * dst doesn't need to be updated in the loop. */ while (num_bytes < l) { size_t n = MIN(dst_len, l - num_bytes); res = tadb_update_payload(ta->ctx, TEE_MODE_DECRYPT, ta->ta_buf + ta->pos + num_bytes, n, dst); if (res) goto out; if (buf_user) { res = copy_to_user((uint8_t *)buf_user + num_bytes, dst, n); if (res) goto out; } num_bytes += n; } ta->pos += l; if (ta->pos == sz) { size_t dl = 0; res = crypto_authenc_dec_final(ta->ctx, NULL, 0, NULL, &dl, ta->entry.tag, TADB_TAG_SIZE); if (res) return res; } *len = l; out: bb_free(bb, bb_len); return res; } void tee_tadb_ta_close(struct tee_tadb_ta_read *ta) { crypto_authenc_final(ta->ctx); crypto_authenc_free_ctx(ta->ctx); if (ta->ta_mobj) thread_rpc_free_payload(ta->ta_mobj); tee_fs_rpc_close(OPTEE_RPC_CMD_FS, ta->fd); tadb_put(ta->db); free(ta); } optee_os-4.3.0/core/tee/tee_cryp_concat_kdf.c000066400000000000000000000032261464416617300212100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited */ #include #include #include #include #include #include TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *other_info, size_t other_info_len, uint8_t *derived_key, size_t derived_key_len) { TEE_Result res; size_t hash_len, i, n, sz; void *ctx = NULL; uint8_t tmp[TEE_MAX_HASH_SIZE]; uint32_t be_count; uint8_t *out = derived_key; uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); res = crypto_hash_alloc_ctx(&ctx, hash_algo); if (res != TEE_SUCCESS) return res; res = tee_alg_get_digest_size(hash_algo, &hash_len); if (res != TEE_SUCCESS) goto out; n = derived_key_len / hash_len; sz = hash_len; for (i = 1; i <= n + 1; i++) { be_count = TEE_U32_TO_BIG_ENDIAN(i); res = crypto_hash_init(ctx); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, (uint8_t *)&be_count, sizeof(be_count)); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, shared_secret, shared_secret_len); if (res != TEE_SUCCESS) goto out; if (other_info && other_info_len) { res = crypto_hash_update(ctx, other_info, other_info_len); if (res != TEE_SUCCESS) goto out; } res = crypto_hash_final(ctx, tmp, sizeof(tmp)); if (res != TEE_SUCCESS) goto out; if (i == n + 1) sz = derived_key_len % hash_len; memcpy(out, tmp, sz); out += sz; } res = TEE_SUCCESS; out: crypto_hash_free_ctx(ctx); return res; } optee_os-4.3.0/core/tee/tee_cryp_hkdf.c000066400000000000000000000073161464416617300200350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited */ #include #include #include #include #include #include static const uint8_t zero_salt[TEE_MAX_HASH_SIZE]; static TEE_Result hkdf_extract(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, size_t salt_len, uint8_t *prk, size_t *prk_len) { TEE_Result res; void *ctx = NULL; uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); uint32_t hmac_algo = (TEE_OPERATION_MAC << 28) | hash_id; if (!salt || !salt_len) { /* * RFC 5869 section 2.2: * If not provided, [the salt] is set to a string of HashLen * zeros */ salt = zero_salt; res = tee_alg_get_digest_size(hash_algo, &salt_len); if (res != TEE_SUCCESS) goto out; } res = crypto_mac_alloc_ctx(&ctx, hmac_algo); if (res) goto out; /* * RFC 5869 section 2.1: "Note that in the extract step, 'IKM' is used * as the HMAC input, not as the HMAC key." * Therefore, salt is the HMAC key in the formula from section 2.2: * "PRK = HMAC-Hash(salt, IKM)" */ res = crypto_mac_init(ctx, salt, salt_len); if (res != TEE_SUCCESS) goto out; res = crypto_mac_update(ctx, ikm, ikm_len); if (res != TEE_SUCCESS) goto out; res = crypto_mac_final(ctx, prk, *prk_len); if (res != TEE_SUCCESS) goto out; res = tee_alg_get_digest_size(hash_algo, prk_len); out: crypto_mac_free_ctx(ctx); return res; } static TEE_Result hkdf_expand(uint32_t hash_id, const uint8_t *prk, size_t prk_len, const uint8_t *info, size_t info_len, uint8_t *okm, size_t okm_len) { uint8_t tn[TEE_MAX_HASH_SIZE]; size_t tn_len, hash_len, i, n, where; TEE_Result res = TEE_SUCCESS; void *ctx = NULL; uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); uint32_t hmac_algo = TEE_ALG_HMAC_ALGO(hash_id); res = tee_alg_get_digest_size(hash_algo, &hash_len); if (res != TEE_SUCCESS) goto out; if (!okm || prk_len < hash_len) { res = TEE_ERROR_BAD_STATE; goto out; } if (!info) info_len = 0; res = crypto_mac_alloc_ctx(&ctx, hmac_algo); if (res) goto out; /* N = ceil(L/HashLen) */ n = okm_len / hash_len; if ((okm_len % hash_len) != 0) n++; if (n > 255) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * RFC 5869 section 2.3 * T = T(1) | T(2) | T(3) | ... | T(N) * OKM = first L octets of T * T(0) = empty string (zero length) * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) * ... */ tn_len = 0; where = 0; for (i = 1; i <= n; i++) { uint8_t c = i; res = crypto_mac_init(ctx, prk, prk_len); if (res != TEE_SUCCESS) goto out; res = crypto_mac_update(ctx, tn, tn_len); if (res != TEE_SUCCESS) goto out; res = crypto_mac_update(ctx, info, info_len); if (res != TEE_SUCCESS) goto out; res = crypto_mac_update(ctx, &c, 1); if (res != TEE_SUCCESS) goto out; res = crypto_mac_final(ctx, tn, sizeof(tn)); if (res != TEE_SUCCESS) goto out; memcpy(okm + where, tn, (i < n) ? hash_len : (okm_len - where)); where += hash_len; tn_len = hash_len; } out: crypto_mac_free_ctx(ctx); return res; } TEE_Result tee_cryp_hkdf(uint32_t hash_id, const uint8_t *ikm, size_t ikm_len, const uint8_t *salt, size_t salt_len, const uint8_t *info, size_t info_len, uint8_t *okm, size_t okm_len) { TEE_Result res; uint8_t prk[TEE_MAX_HASH_SIZE]; size_t prk_len = sizeof(prk); res = hkdf_extract(hash_id, ikm, ikm_len, salt, salt_len, prk, &prk_len); if (res != TEE_SUCCESS) return res; res = hkdf_expand(hash_id, prk, prk_len, info, info_len, okm, okm_len); return res; } optee_os-4.3.0/core/tee/tee_cryp_pbkdf2.c000066400000000000000000000051311464416617300202620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, Linaro Limited */ #include #include #include #include #include #include struct hmac_parms { uint32_t algo; size_t hash_len; void *ctx; }; struct pbkdf2_parms { const uint8_t *password; size_t password_len; const uint8_t *salt; size_t salt_len; uint32_t iteration_count; }; static TEE_Result pbkdf2_f(uint8_t *out, size_t len, uint32_t idx, struct hmac_parms *h, struct pbkdf2_parms *p) { TEE_Result res; uint8_t u[TEE_MAX_HASH_SIZE]; uint32_t be_index; size_t i, j; memset(out, 0, len); for (i = 1; i <= p->iteration_count; i++) { res = crypto_mac_init(h->ctx, p->password, p->password_len); if (res != TEE_SUCCESS) return res; if (i == 1) { if (p->salt && p->salt_len) { res = crypto_mac_update(h->ctx, p->salt, p->salt_len); if (res != TEE_SUCCESS) return res; } be_index = TEE_U32_TO_BIG_ENDIAN(idx); res = crypto_mac_update(h->ctx, (uint8_t *)&be_index, sizeof(be_index)); if (res != TEE_SUCCESS) return res; } else { res = crypto_mac_update(h->ctx, u, h->hash_len); if (res != TEE_SUCCESS) return res; } res = crypto_mac_final(h->ctx, u, sizeof(u)); if (res != TEE_SUCCESS) return res; for (j = 0; j < len; j++) out[j] ^= u[j]; } return TEE_SUCCESS; } TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint32_t iteration_count, uint8_t *derived_key, size_t derived_key_len) { TEE_Result res; size_t i, l, r; uint8_t *out = derived_key; struct pbkdf2_parms pbkdf2_parms; struct hmac_parms hmac_parms = {0, }; hmac_parms.algo = TEE_ALG_HMAC_ALGO(hash_id); res = tee_alg_get_digest_size(hmac_parms.algo, &hmac_parms.hash_len); if (res != TEE_SUCCESS) return res; res = crypto_mac_alloc_ctx(&hmac_parms.ctx, hmac_parms.algo); if (res != TEE_SUCCESS) return res; pbkdf2_parms.password = password; pbkdf2_parms.password_len = password_len; pbkdf2_parms.salt = salt; pbkdf2_parms.salt_len = salt_len; pbkdf2_parms.iteration_count = iteration_count; l = derived_key_len / hmac_parms.hash_len; r = derived_key_len % hmac_parms.hash_len; for (i = 1; i <= l; i++) { res = pbkdf2_f(out, hmac_parms.hash_len, i, &hmac_parms, &pbkdf2_parms); if (res != TEE_SUCCESS) goto out; out += hmac_parms.hash_len; } if (r) res = pbkdf2_f(out, r, i, &hmac_parms, &pbkdf2_parms); out: crypto_mac_free_ctx(hmac_parms.ctx); return res; } optee_os-4.3.0/core/tee/tee_cryp_utl.c000066400000000000000000000116761464416617300177310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2021, Linaro Limited * Copyright (c) 2021, SumUp Services GmbH */ #include #include #include #include #include #include #include #include #include #include #include TEE_Result tee_alg_get_digest_size(uint32_t algo, size_t *size) { size_t digest_size = TEE_ALG_GET_DIGEST_SIZE(algo); if (!digest_size) return TEE_ERROR_NOT_SUPPORTED; *size = digest_size; return TEE_SUCCESS; } TEE_Result tee_hash_createdigest(uint32_t algo, const uint8_t *data, size_t datalen, uint8_t *digest, size_t digestlen) { TEE_Result res; void *ctx = NULL; res = crypto_hash_alloc_ctx(&ctx, algo); if (res) return res; res = crypto_hash_init(ctx); if (res) goto out; if (datalen != 0) { res = crypto_hash_update(ctx, data, datalen); if (res) goto out; } res = crypto_hash_final(ctx, digest, digestlen); out: crypto_hash_free_ctx(ctx); return res; } TEE_Result tee_cipher_get_block_size(uint32_t algo, size_t *size) { switch (algo) { case TEE_ALG_AES_CBC_MAC_NOPAD: case TEE_ALG_AES_CBC_MAC_PKCS5: case TEE_ALG_AES_CMAC: case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_AES_CTR: case TEE_ALG_AES_CTS: case TEE_ALG_AES_XTS: case TEE_ALG_AES_CCM: case TEE_ALG_AES_GCM: case TEE_ALG_SM4_ECB_NOPAD: case TEE_ALG_SM4_CBC_NOPAD: case TEE_ALG_SM4_XTS: case TEE_ALG_SM4_CTR: *size = 16; break; case TEE_ALG_DES_CBC_MAC_NOPAD: case TEE_ALG_DES_CBC_MAC_PKCS5: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_MAC_NOPAD: case TEE_ALG_DES3_CBC_MAC_PKCS5: case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: case TEE_ALG_DES3_CMAC: *size = 8; break; default: return TEE_ERROR_NOT_SUPPORTED; } return TEE_SUCCESS; } TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo, TEE_OperationMode mode, bool last_block, const uint8_t *data, size_t len, uint8_t *dst) { TEE_Result res; size_t block_size; if (mode != TEE_MODE_ENCRYPT && mode != TEE_MODE_DECRYPT) return TEE_ERROR_BAD_PARAMETERS; /* * Check that the block contains the correct number of data, apart * for the last block in some XTS / CTR / XTS mode */ res = tee_cipher_get_block_size(algo, &block_size); if (res != TEE_SUCCESS) return res; if ((len % block_size) != 0) { if (!last_block && algo != TEE_ALG_AES_CTR) return TEE_ERROR_BAD_PARAMETERS; switch (algo) { case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: case TEE_ALG_SM4_ECB_NOPAD: case TEE_ALG_SM4_CBC_NOPAD: return TEE_ERROR_BAD_PARAMETERS; case TEE_ALG_AES_CTR: case TEE_ALG_AES_XTS: case TEE_ALG_AES_CTS: case TEE_ALG_SM4_XTS: /* * These modes doesn't require padding for the last * block. * * This isn't entirely true, both XTS and CTS can only * encrypt minimum one block and also they need at least * one complete block in the last update to finish the * encryption. The algorithms are supposed to detect * that, we're only making sure that all data fed up to * that point consists of complete blocks. */ break; default: return TEE_ERROR_NOT_SUPPORTED; } } return crypto_cipher_update(ctx, mode, last_block, data, len, dst); } /* * Override this in your platform code to feed the PRNG platform-specific * jitter entropy. This implementation does not efficiently deliver entropy * and is here for backwards-compatibility. */ __weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum) { TEE_Time current; #ifdef CFG_SECURE_TIME_SOURCE_REE if (CRYPTO_RNG_SRC_IS_QUICK(sid)) return; /* Can't read REE time here */ #endif if (tee_time_get_sys_time(¤t) == TEE_SUCCESS) crypto_rng_add_event(sid, pnum, ¤t, sizeof(current)); } __weak void plat_rng_init(void) { TEE_Result res = TEE_SUCCESS; TEE_Time t; #ifndef CFG_SECURE_TIME_SOURCE_REE /* * This isn't much of a seed. Ideally we should either get a seed from * a hardware RNG or from a previously saved seed. * * Seeding with hardware RNG is currently up to the platform to * override this function. * * Seeding with a saved seed will require cooperation from normal * world, this is still TODO. */ res = tee_time_get_sys_time(&t); #else EMSG("Warning: seeding RNG with zeroes"); memset(&t, 0, sizeof(t)); #endif if (!res) res = crypto_rng_init(&t, sizeof(t)); if (res) { EMSG("Failed to initialize RNG: %#" PRIx32, res); panic(); } } static TEE_Result tee_cryp_init(void) { TEE_Result res = crypto_init(); if (res) { EMSG("Failed to initialize crypto API: %#" PRIx32, res); panic(); } plat_rng_init(); dt_driver_crypt_init_complete(); return TEE_SUCCESS; } service_init(tee_cryp_init); optee_os-4.3.0/core/tee/tee_fs_key_manager.c000066400000000000000000000142431464416617300210330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ /* * Acronyms: * * FEK - File Encryption Key * SSK - Secure Storage Key * TSK - Trusted app Storage Key * IV - Initial vector * HUK - Hardware Unique Key * RNG - Random Number Generator */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct tee_fs_ssk { bool is_init; uint8_t key[TEE_FS_KM_SSK_SIZE]; }; static struct tee_fs_ssk tee_fs_ssk; static TEE_Result do_hmac(void *out_key, size_t out_key_size, const void *in_key, size_t in_key_size, const void *message, size_t message_size) { TEE_Result res; void *ctx = NULL; if (!out_key || !in_key || !message) return TEE_ERROR_BAD_PARAMETERS; res = crypto_mac_alloc_ctx(&ctx, TEE_FS_KM_HMAC_ALG); if (res != TEE_SUCCESS) return res; res = crypto_mac_init(ctx, in_key, in_key_size); if (res != TEE_SUCCESS) goto exit; res = crypto_mac_update(ctx, message, message_size); if (res != TEE_SUCCESS) goto exit; res = crypto_mac_final(ctx, out_key, out_key_size); if (res != TEE_SUCCESS) goto exit; res = TEE_SUCCESS; exit: crypto_mac_free_ctx(ctx); return res; } TEE_Result tee_fs_fek_crypt(const TEE_UUID *uuid, TEE_OperationMode mode, const uint8_t *in_key, size_t size, uint8_t *out_key) { TEE_Result res; void *ctx = NULL; uint8_t tsk[TEE_FS_KM_TSK_SIZE]; uint8_t dst_key[size]; if (!in_key || !out_key) return TEE_ERROR_BAD_PARAMETERS; if (size != TEE_FS_KM_FEK_SIZE) return TEE_ERROR_BAD_PARAMETERS; if (tee_fs_ssk.is_init == 0) return TEE_ERROR_GENERIC; if (uuid) { res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, TEE_FS_KM_SSK_SIZE, uuid, sizeof(*uuid)); if (res != TEE_SUCCESS) return res; } else { /* * Pick something of a different size than TEE_UUID to * guarantee that there's never a conflict. */ uint8_t dummy[1] = { 0 }; res = do_hmac(tsk, sizeof(tsk), tee_fs_ssk.key, TEE_FS_KM_SSK_SIZE, dummy, sizeof(dummy)); if (res != TEE_SUCCESS) return res; } res = crypto_cipher_alloc_ctx(&ctx, TEE_FS_KM_ENC_FEK_ALG); if (res != TEE_SUCCESS) return res; res = crypto_cipher_init(ctx, mode, tsk, sizeof(tsk), NULL, 0, NULL, 0); if (res != TEE_SUCCESS) goto exit; res = crypto_cipher_update(ctx, mode, true, in_key, size, dst_key); if (res != TEE_SUCCESS) goto exit; crypto_cipher_final(ctx); memcpy(out_key, dst_key, sizeof(dst_key)); exit: crypto_cipher_free_ctx(ctx); memzero_explicit(tsk, sizeof(tsk)); memzero_explicit(dst_key, sizeof(dst_key)); return res; } static TEE_Result generate_fek(uint8_t *key, uint8_t len) { return crypto_rng_read(key, len); } static TEE_Result tee_fs_init_key_manager(void) { TEE_Result res = TEE_SUCCESS; COMPILE_TIME_ASSERT(TEE_FS_KM_SSK_SIZE <= HUK_SUBKEY_MAX_LEN); res = huk_subkey_derive(HUK_SUBKEY_SSK, NULL, 0, tee_fs_ssk.key, sizeof(tee_fs_ssk.key)); if (res == TEE_SUCCESS) tee_fs_ssk.is_init = 1; else memzero_explicit(&tee_fs_ssk, sizeof(tee_fs_ssk)); return res; } TEE_Result tee_fs_generate_fek(const TEE_UUID *uuid, void *buf, size_t buf_size) { TEE_Result res; if (buf_size != TEE_FS_KM_FEK_SIZE) return TEE_ERROR_BAD_PARAMETERS; res = generate_fek(buf, TEE_FS_KM_FEK_SIZE); if (res != TEE_SUCCESS) return res; return tee_fs_fek_crypt(uuid, TEE_MODE_ENCRYPT, buf, TEE_FS_KM_FEK_SIZE, buf); } static TEE_Result sha256(uint8_t *out, size_t out_size, const uint8_t *in, size_t in_size) { return tee_hash_createdigest(TEE_ALG_SHA256, in, in_size, out, out_size); } static TEE_Result aes_ecb(uint8_t out[TEE_AES_BLOCK_SIZE], const uint8_t in[TEE_AES_BLOCK_SIZE], const uint8_t *key, size_t key_size) { TEE_Result res; void *ctx = NULL; res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_ECB_NOPAD); if (res != TEE_SUCCESS) return res; res = crypto_cipher_init(ctx, TEE_MODE_ENCRYPT, key, key_size, NULL, 0, NULL, 0); if (res != TEE_SUCCESS) goto out; res = crypto_cipher_update(ctx, TEE_MODE_ENCRYPT, true, in, TEE_AES_BLOCK_SIZE, out); if (res != TEE_SUCCESS) goto out; crypto_cipher_final(ctx); res = TEE_SUCCESS; out: crypto_cipher_free_ctx(ctx); return res; } static TEE_Result essiv(uint8_t iv[TEE_AES_BLOCK_SIZE], const uint8_t fek[TEE_FS_KM_FEK_SIZE], uint16_t blk_idx) { TEE_Result res; uint8_t sha[TEE_SHA256_HASH_SIZE]; uint8_t pad_blkid[TEE_AES_BLOCK_SIZE] = { 0, }; res = sha256(sha, sizeof(sha), fek, TEE_FS_KM_FEK_SIZE); if (res != TEE_SUCCESS) return res; pad_blkid[0] = (blk_idx & 0xFF); pad_blkid[1] = (blk_idx & 0xFF00) >> 8; res = aes_ecb(iv, pad_blkid, sha, 16); memzero_explicit(sha, sizeof(sha)); return res; } /* * Encryption/decryption of RPMB FS file data. This is AES CBC with ESSIV. */ TEE_Result tee_fs_crypt_block(const TEE_UUID *uuid, uint8_t *out, const uint8_t *in, size_t size, uint16_t blk_idx, const uint8_t *encrypted_fek, TEE_OperationMode mode) { TEE_Result res; uint8_t fek[TEE_FS_KM_FEK_SIZE]; uint8_t iv[TEE_AES_BLOCK_SIZE]; void *ctx; DMSG("%scrypt block #%u", (mode == TEE_MODE_ENCRYPT) ? "En" : "De", blk_idx); /* Decrypt FEK */ res = tee_fs_fek_crypt(uuid, TEE_MODE_DECRYPT, encrypted_fek, TEE_FS_KM_FEK_SIZE, fek); if (res != TEE_SUCCESS) goto wipe; /* Compute initialization vector for this block */ res = essiv(iv, fek, blk_idx); if (res != TEE_SUCCESS) goto wipe; /* Run AES CBC */ res = crypto_cipher_alloc_ctx(&ctx, TEE_ALG_AES_CBC_NOPAD); if (res != TEE_SUCCESS) goto wipe; res = crypto_cipher_init(ctx, mode, fek, sizeof(fek), NULL, 0, iv, TEE_AES_BLOCK_SIZE); if (res != TEE_SUCCESS) goto exit; res = crypto_cipher_update(ctx, mode, true, in, size, out); if (res != TEE_SUCCESS) goto exit; crypto_cipher_final(ctx); exit: crypto_cipher_free_ctx(ctx); wipe: memzero_explicit(fek, sizeof(fek)); memzero_explicit(iv, sizeof(iv)); return res; } service_init_late(tee_fs_init_key_manager); optee_os-4.3.0/core/tee/tee_fs_rpc.c000066400000000000000000000115351464416617300173360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include struct tee_fs_dir { int nw_dir; struct tee_fs_dirent d; }; /* "/dirf.db" or "/" */ static TEE_Result create_filename(void *buf, size_t blen, const struct tee_fs_dirfile_fileh *dfh) { char *file = buf; size_t pos = 0; size_t l; if (pos >= blen) return TEE_ERROR_SHORT_BUFFER; file[pos] = '/'; pos++; if (pos >= blen) return TEE_ERROR_SHORT_BUFFER; l = blen - pos; return tee_fs_dirfile_fileh_to_fname(dfh, file + pos, &l); } static TEE_Result operation_commit(struct tee_fs_rpc_operation *op) { return thread_rpc_cmd(op->id, op->num_params, op->params); } static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd, const struct tee_fs_dirfile_fileh *dfh, int *fd) { struct tee_fs_rpc_operation op = { }; struct mobj *mobj = NULL; TEE_Result res = TEE_SUCCESS; void *va = NULL; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, THREAD_SHM_TYPE_APPLICATION, TEE_FS_NAME_MAX, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; res = create_filename(va, TEE_FS_NAME_MAX, dfh); if (res != TEE_SUCCESS) return res; op = (struct tee_fs_rpc_operation){ .id = id, .num_params = 3, .params = { [0] = THREAD_PARAM_VALUE(IN, cmd, 0, 0), [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), [2] = THREAD_PARAM_VALUE(OUT, 0, 0, 0), } }; res = operation_commit(&op); if (res == TEE_SUCCESS) *fd = op.params[2].u.value.a; return res; } TEE_Result tee_fs_rpc_open_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh, int *fd) { return operation_open_dfh(id, OPTEE_RPC_FS_OPEN, dfh, fd); } TEE_Result tee_fs_rpc_create_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh, int *fd) { return operation_open_dfh(id, OPTEE_RPC_FS_CREATE, dfh, fd); } TEE_Result tee_fs_rpc_close(uint32_t id, int fd) { struct tee_fs_rpc_operation op = { .id = id, .num_params = 1, .params = { [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_CLOSE, fd, 0), }, }; return operation_commit(&op); } TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, uint32_t id, int fd, tee_fs_off_t offset, size_t data_len, void **out_data) { struct mobj *mobj; uint8_t *va; if (offset < 0) return TEE_ERROR_BAD_PARAMETERS; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, THREAD_SHM_TYPE_APPLICATION, data_len, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; *op = (struct tee_fs_rpc_operation){ .id = id, .num_params = 2, .params = { [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_READ, fd, offset), [1] = THREAD_PARAM_MEMREF(OUT, mobj, 0, data_len), }, }; *out_data = va; return TEE_SUCCESS; } TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, size_t *data_len) { TEE_Result res = operation_commit(op); if (res == TEE_SUCCESS) *data_len = op->params[1].u.memref.size; return res; } TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, uint32_t id, int fd, tee_fs_off_t offset, size_t data_len, void **data) { struct mobj *mobj; uint8_t *va; if (offset < 0) return TEE_ERROR_BAD_PARAMETERS; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, THREAD_SHM_TYPE_APPLICATION, data_len, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; *op = (struct tee_fs_rpc_operation){ .id = id, .num_params = 2, .params = { [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_WRITE, fd, offset), [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, data_len), }, }; *data = va; return TEE_SUCCESS; } TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op) { return operation_commit(op); } TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len) { struct tee_fs_rpc_operation op = { .id = id, .num_params = 1, .params = { [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_TRUNCATE, fd, len), } }; return operation_commit(&op); } TEE_Result tee_fs_rpc_remove_dfh(uint32_t id, const struct tee_fs_dirfile_fileh *dfh) { struct tee_fs_rpc_operation op = { }; TEE_Result res = TEE_SUCCESS; struct mobj *mobj = NULL; void *va = NULL; va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_FS, THREAD_SHM_TYPE_APPLICATION, TEE_FS_NAME_MAX, &mobj); if (!va) return TEE_ERROR_OUT_OF_MEMORY; res = create_filename(va, TEE_FS_NAME_MAX, dfh); if (res != TEE_SUCCESS) return res; op = (struct tee_fs_rpc_operation){ .id = id, .num_params = 2, .params = { [0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_FS_REMOVE, 0, 0), [1] = THREAD_PARAM_MEMREF(IN, mobj, 0, TEE_FS_NAME_MAX), } }; return operation_commit(&op); } optee_os-4.3.0/core/tee/tee_obj.c000066400000000000000000000033371464416617300166350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include void tee_obj_add(struct user_ta_ctx *utc, struct tee_obj *o) { TAILQ_INSERT_TAIL(&utc->objects, o, link); } TEE_Result tee_obj_get(struct user_ta_ctx *utc, vaddr_t obj_id, struct tee_obj **obj) { struct tee_obj *o; TAILQ_FOREACH(o, &utc->objects, link) { if (obj_id == (vaddr_t)o) { *obj = o; return TEE_SUCCESS; } } return TEE_ERROR_BAD_STATE; } void tee_obj_close(struct user_ta_ctx *utc, struct tee_obj *o) { TAILQ_REMOVE(&utc->objects, o, link); if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { o->pobj->fops->close(&o->fh); tee_pobj_release(o->pobj); } tee_obj_free(o); } void tee_obj_close_all(struct user_ta_ctx *utc) { struct tee_obj_head *objects = &utc->objects; while (!TAILQ_EMPTY(objects)) tee_obj_close(utc, TAILQ_FIRST(objects)); } TEE_Result tee_obj_verify(struct tee_ta_session *sess, struct tee_obj *o) { TEE_Result res; const struct tee_file_operations *fops = o->pobj->fops; struct tee_file_handle *fh = NULL; if (!fops) return TEE_ERROR_STORAGE_NOT_AVAILABLE; res = fops->open(o->pobj, NULL, &fh); if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); fops->remove(o->pobj); tee_obj_close(to_user_ta_ctx(sess->ts_sess.ctx), o); } fops->close(&fh); return res; } struct tee_obj *tee_obj_alloc(void) { return calloc(1, sizeof(struct tee_obj)); } void tee_obj_free(struct tee_obj *o) { if (o) { tee_obj_attr_free(o); free(o->attr); free(o); } } optee_os-4.3.0/core/tee/tee_pobj.c000066400000000000000000000120361464416617300170110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs = TAILQ_HEAD_INITIALIZER(tee_pobjs); static struct mutex pobjs_mutex = MUTEX_INITIALIZER; static struct mutex pobjs_usage_mutex = MUTEX_INITIALIZER; static bool pobj_need_usage_lock(struct tee_pobj *obj) { /* Only lock if we don't have exclusive access to the object */ return obj->flags & (TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_SHARE_READ); } void tee_pobj_lock_usage(struct tee_pobj *obj) { if (pobj_need_usage_lock(obj)) mutex_lock(&pobjs_usage_mutex); } void tee_pobj_unlock_usage(struct tee_pobj *obj) { if (pobj_need_usage_lock(obj)) mutex_unlock(&pobjs_usage_mutex); } static TEE_Result tee_pobj_check_access(uint32_t oflags, uint32_t nflags) { /* meta is exclusive */ if ((oflags & TEE_DATA_FLAG_ACCESS_WRITE_META) || (nflags & TEE_DATA_FLAG_ACCESS_WRITE_META)) return TEE_ERROR_ACCESS_CONFLICT; /* * Excerpt of TEE Internal Core API Specification v1.1: * If more than one handle is opened on the same object, and if any * of these object handles was opened with the flag * TEE_DATA_FLAG_ACCESS_READ, then all the object handles MUST have been * opened with the flag TEE_DATA_FLAG_SHARE_READ */ if (((oflags & TEE_DATA_FLAG_ACCESS_READ) || (nflags & TEE_DATA_FLAG_ACCESS_READ)) && !((nflags & TEE_DATA_FLAG_SHARE_READ) && (oflags & TEE_DATA_FLAG_SHARE_READ))) return TEE_ERROR_ACCESS_CONFLICT; /* * Excerpt of TEE Internal Core API Specification v1.1: * An object can be opened with only share flags, which locks the access * to an object against a given mode. * An object can be opened with no flag set, which completely locks all * subsequent attempts to access the object */ if ((nflags & TEE_DATA_FLAG_SHARE_READ) != (oflags & TEE_DATA_FLAG_SHARE_READ)) return TEE_ERROR_ACCESS_CONFLICT; /* Same on WRITE access */ if (((oflags & TEE_DATA_FLAG_ACCESS_WRITE) || (nflags & TEE_DATA_FLAG_ACCESS_WRITE)) && !((nflags & TEE_DATA_FLAG_SHARE_WRITE) && (oflags & TEE_DATA_FLAG_SHARE_WRITE))) return TEE_ERROR_ACCESS_CONFLICT; if ((nflags & TEE_DATA_FLAG_SHARE_WRITE) != (oflags & TEE_DATA_FLAG_SHARE_WRITE)) return TEE_ERROR_ACCESS_CONFLICT; return TEE_SUCCESS; } TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len, uint32_t flags, enum tee_pobj_usage usage, const struct tee_file_operations *fops, struct tee_pobj **obj) { TEE_Result res = TEE_SUCCESS; struct tee_pobj *o = NULL; *obj = NULL; mutex_lock(&pobjs_mutex); /* Check if file is open */ TAILQ_FOREACH(o, &tee_pobjs, link) { if ((obj_id_len == o->obj_id_len) && (memcmp(obj_id, o->obj_id, obj_id_len) == 0) && (memcmp(uuid, &o->uuid, sizeof(TEE_UUID)) == 0) && (fops == o->fops)) { *obj = o; } } if (*obj) { if (usage == TEE_POBJ_USAGE_ENUM) { (*obj)->refcnt++; goto out; } if ((*obj)->creating || (usage == TEE_POBJ_USAGE_CREATE && !(flags & TEE_DATA_FLAG_OVERWRITE))) { res = TEE_ERROR_ACCESS_CONFLICT; goto out; } res = tee_pobj_check_access((*obj)->flags, flags); if (res == TEE_SUCCESS) (*obj)->refcnt++; goto out; } /* new file */ o = calloc(1, sizeof(struct tee_pobj)); if (!o) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } o->refcnt = 1; memcpy(&o->uuid, uuid, sizeof(TEE_UUID)); o->flags = flags; o->fops = fops; if (usage == TEE_POBJ_USAGE_CREATE) { o->temporary = true; o->creating = true; } o->obj_id = malloc(obj_id_len); if (o->obj_id == NULL) { free(o); res = TEE_ERROR_OUT_OF_MEMORY; goto out; } memcpy(o->obj_id, obj_id, obj_id_len); o->obj_id_len = obj_id_len; TAILQ_INSERT_TAIL(&tee_pobjs, o, link); *obj = o; res = TEE_SUCCESS; out: if (res != TEE_SUCCESS) *obj = NULL; mutex_unlock(&pobjs_mutex); return res; } void tee_pobj_create_final(struct tee_pobj *po) { mutex_lock(&pobjs_mutex); po->temporary = false; po->creating = false; mutex_unlock(&pobjs_mutex); } TEE_Result tee_pobj_release(struct tee_pobj *obj) { if (obj == NULL) return TEE_ERROR_BAD_PARAMETERS; mutex_lock(&pobjs_mutex); obj->refcnt--; if (obj->refcnt == 0) { TAILQ_REMOVE(&tee_pobjs, obj, link); free(obj->obj_id); free(obj); } mutex_unlock(&pobjs_mutex); return TEE_SUCCESS; } TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id, uint32_t obj_id_len) { TEE_Result res = TEE_SUCCESS; void *new_obj_id = NULL; if (obj == NULL || obj_id == NULL) return TEE_ERROR_BAD_PARAMETERS; mutex_lock(&pobjs_mutex); if (obj->refcnt != 1) { res = TEE_ERROR_BAD_STATE; goto exit; } new_obj_id = malloc(obj_id_len); if (new_obj_id == NULL) { res = TEE_ERROR_OUT_OF_MEMORY; goto exit; } memcpy(new_obj_id, obj_id, obj_id_len); /* update internal data */ free(obj->obj_id); obj->obj_id = new_obj_id; obj->obj_id_len = obj_id_len; new_obj_id = NULL; exit: mutex_unlock(&pobjs_mutex); free(new_obj_id); return res; } optee_os-4.3.0/core/tee/tee_ree_fs.c000066400000000000000000000621501464416617300173240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BLOCK_SHIFT 12 #define BLOCK_SIZE (1 << BLOCK_SHIFT) struct tee_fs_fd { struct tee_fs_htree *ht; int fd; struct tee_fs_dirfile_fileh dfh; const TEE_UUID *uuid; }; struct tee_fs_dir { struct tee_fs_dirfile_dirh *dirh; int idx; struct tee_fs_dirent d; const TEE_UUID *uuid; }; static int pos_to_block_num(int position) { return position >> BLOCK_SHIFT; } static struct mutex ree_fs_mutex = MUTEX_INITIALIZER; static void *get_tmp_block(void) { return mempool_alloc(mempool_default, BLOCK_SIZE); } static void put_tmp_block(void *tmp_block) { mempool_free(mempool_default, tmp_block); } static TEE_Result out_of_place_write(struct tee_fs_fd *fdp, size_t pos, const void *buf_core, const void *buf_user, size_t len) { TEE_Result res; size_t start_block_num = pos_to_block_num(pos); size_t end_block_num = pos_to_block_num(pos + len - 1); size_t remain_bytes = len; uint8_t *data_core_ptr = (uint8_t *)buf_core; uint8_t *data_user_ptr = (uint8_t *)buf_user; uint8_t *block; struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht); /* * It doesn't make sense to call this function if nothing is to be * written. This also guards against end_block_num getting an * unexpected value when pos == 0 and len == 0. */ if (!len) return TEE_ERROR_BAD_PARAMETERS; block = get_tmp_block(); if (!block) return TEE_ERROR_OUT_OF_MEMORY; while (start_block_num <= end_block_num) { size_t offset = pos % BLOCK_SIZE; size_t size_to_write = MIN(remain_bytes, (size_t)BLOCK_SIZE); if (size_to_write + offset > BLOCK_SIZE) size_to_write = BLOCK_SIZE - offset; if (start_block_num * BLOCK_SIZE < ROUNDUP(meta->length, BLOCK_SIZE)) { res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block); if (res != TEE_SUCCESS) goto exit; } else { memset(block, 0, BLOCK_SIZE); } if (data_core_ptr) { memcpy(block + offset, data_core_ptr, size_to_write); } else if (data_user_ptr) { res = copy_from_user(block + offset, data_user_ptr, size_to_write); if (res) return res; } else { memset(block + offset, 0, size_to_write); } res = tee_fs_htree_write_block(&fdp->ht, start_block_num, block); if (res != TEE_SUCCESS) goto exit; if (data_core_ptr) data_core_ptr += size_to_write; if (data_user_ptr) data_user_ptr += size_to_write; remain_bytes -= size_to_write; start_block_num++; pos += size_to_write; } if (pos > meta->length) { meta->length = pos; tee_fs_htree_meta_set_dirty(fdp->ht); } exit: if (block) put_tmp_block(block); return res; } static TEE_Result get_offs_size(enum tee_fs_htree_type type, size_t idx, uint8_t vers, size_t *offs, size_t *size) { const size_t node_size = sizeof(struct tee_fs_htree_node_image); const size_t block_nodes = BLOCK_SIZE / (node_size * 2); size_t pbn; size_t bidx; assert(vers == 0 || vers == 1); /* * File layout * [demo with input: * BLOCK_SIZE = 4096, * node_size = 66, * block_nodes = 4096/(66*2) = 31 ] * * phys block 0: * tee_fs_htree_image vers 0 @ offs = 0 * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image) * * phys block 1: * tee_fs_htree_node_image 0 vers 0 @ offs = 0 * tee_fs_htree_node_image 0 vers 1 @ offs = node_size * tee_fs_htree_node_image 1 vers 0 @ offs = node_size * 2 * tee_fs_htree_node_image 1 vers 1 @ offs = node_size * 3 * ... * tee_fs_htree_node_image 30 vers 0 @ offs = node_size * 60 * tee_fs_htree_node_image 30 vers 1 @ offs = node_size * 61 * * phys block 2: * data block 0 vers 0 * * phys block 3: * data block 0 vers 1 * * ... * phys block 62: * data block 30 vers 0 * * phys block 63: * data block 30 vers 1 * * phys block 64: * tee_fs_htree_node_image 31 vers 0 @ offs = 0 * tee_fs_htree_node_image 31 vers 1 @ offs = node_size * tee_fs_htree_node_image 32 vers 0 @ offs = node_size * 2 * tee_fs_htree_node_image 32 vers 1 @ offs = node_size * 3 * ... * tee_fs_htree_node_image 61 vers 0 @ offs = node_size * 60 * tee_fs_htree_node_image 61 vers 1 @ offs = node_size * 61 * * phys block 65: * data block 31 vers 0 * * phys block 66: * data block 31 vers 1 * ... */ switch (type) { case TEE_FS_HTREE_TYPE_HEAD: *offs = sizeof(struct tee_fs_htree_image) * vers; *size = sizeof(struct tee_fs_htree_image); return TEE_SUCCESS; case TEE_FS_HTREE_TYPE_NODE: pbn = 1 + ((idx / block_nodes) * block_nodes * 2); *offs = pbn * BLOCK_SIZE + 2 * node_size * (idx % block_nodes) + node_size * vers; *size = node_size; return TEE_SUCCESS; case TEE_FS_HTREE_TYPE_BLOCK: bidx = 2 * idx + vers; pbn = 2 + bidx + bidx / (block_nodes * 2 - 1); *offs = pbn * BLOCK_SIZE; *size = BLOCK_SIZE; return TEE_SUCCESS; default: return TEE_ERROR_GENERIC; } } static TEE_Result ree_fs_rpc_read_init(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data) { struct tee_fs_fd *fdp = aux; TEE_Result res; size_t offs; size_t size; res = get_offs_size(type, idx, vers, &offs, &size); if (res != TEE_SUCCESS) return res; return tee_fs_rpc_read_init(op, OPTEE_RPC_CMD_FS, fdp->fd, offs, size, data); } static TEE_Result ree_fs_rpc_write_init(void *aux, struct tee_fs_rpc_operation *op, enum tee_fs_htree_type type, size_t idx, uint8_t vers, void **data) { struct tee_fs_fd *fdp = aux; TEE_Result res; size_t offs; size_t size; res = get_offs_size(type, idx, vers, &offs, &size); if (res != TEE_SUCCESS) return res; return tee_fs_rpc_write_init(op, OPTEE_RPC_CMD_FS, fdp->fd, offs, size, data); } static const struct tee_fs_htree_storage ree_fs_storage_ops = { .block_size = BLOCK_SIZE, .rpc_read_init = ree_fs_rpc_read_init, .rpc_read_final = tee_fs_rpc_read_final, .rpc_write_init = ree_fs_rpc_write_init, .rpc_write_final = tee_fs_rpc_write_final, }; static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp, tee_fs_off_t new_file_len) { TEE_Result res; struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht); if ((size_t)new_file_len > meta->length) { size_t ext_len = new_file_len - meta->length; res = out_of_place_write(fdp, meta->length, NULL, NULL, ext_len); if (res != TEE_SUCCESS) return res; } else { size_t offs; size_t sz; res = get_offs_size(TEE_FS_HTREE_TYPE_BLOCK, ROUNDUP(new_file_len, BLOCK_SIZE) / BLOCK_SIZE, 1, &offs, &sz); if (res != TEE_SUCCESS) return res; res = tee_fs_htree_truncate(&fdp->ht, new_file_len / BLOCK_SIZE); if (res != TEE_SUCCESS) return res; res = tee_fs_rpc_truncate(OPTEE_RPC_CMD_FS, fdp->fd, offs + sz); if (res != TEE_SUCCESS) return res; meta->length = new_file_len; tee_fs_htree_meta_set_dirty(fdp->ht); } return TEE_SUCCESS; } static TEE_Result ree_fs_read_primitive(struct tee_file_handle *fh, size_t pos, void *buf_core, void *buf_user, size_t *len) { TEE_Result res; int start_block_num; int end_block_num; size_t remain_bytes; uint8_t *data_core_ptr = buf_core; uint8_t *data_user_ptr = buf_user; uint8_t *block = NULL; struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; struct tee_fs_htree_meta *meta = tee_fs_htree_get_meta(fdp->ht); /* One of buf_core and buf_user must be NULL */ assert(!buf_core || !buf_user); remain_bytes = *len; if ((pos + remain_bytes) < remain_bytes || pos > meta->length) remain_bytes = 0; else if (pos + remain_bytes > meta->length) remain_bytes = meta->length - pos; *len = remain_bytes; if (!remain_bytes) { res = TEE_SUCCESS; goto exit; } start_block_num = pos_to_block_num(pos); end_block_num = pos_to_block_num(pos + remain_bytes - 1); block = get_tmp_block(); if (!block) { res = TEE_ERROR_OUT_OF_MEMORY; goto exit; } while (start_block_num <= end_block_num) { size_t offset = pos % BLOCK_SIZE; size_t size_to_read = MIN(remain_bytes, (size_t)BLOCK_SIZE); if (size_to_read + offset > BLOCK_SIZE) size_to_read = BLOCK_SIZE - offset; res = tee_fs_htree_read_block(&fdp->ht, start_block_num, block); if (res != TEE_SUCCESS) goto exit; if (data_core_ptr) { memcpy(data_core_ptr, block + offset, size_to_read); data_core_ptr += size_to_read; } else if (data_user_ptr) { res = copy_to_user(data_user_ptr, block + offset, size_to_read); if (res) goto exit; data_user_ptr += size_to_read; } remain_bytes -= size_to_read; pos += size_to_read; start_block_num++; } res = TEE_SUCCESS; exit: if (block) put_tmp_block(block); return res; } static TEE_Result ree_fs_read(struct tee_file_handle *fh, size_t pos, void *buf_core, void *buf_user, size_t *len) { TEE_Result res; mutex_lock(&ree_fs_mutex); res = ree_fs_read_primitive(fh, pos, buf_core, buf_user, len); mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result ree_fs_write_primitive(struct tee_file_handle *fh, size_t pos, const void *buf_core, const void *buf_user, size_t len) { TEE_Result res; struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; size_t file_size; /* One of buf_core and buf_user must be NULL */ assert(!buf_core || !buf_user); if (!len) return TEE_SUCCESS; file_size = tee_fs_htree_get_meta(fdp->ht)->length; if ((pos + len) < len) return TEE_ERROR_BAD_PARAMETERS; if (file_size < pos) { res = ree_fs_ftruncate_internal(fdp, pos); if (res != TEE_SUCCESS) return res; } return out_of_place_write(fdp, pos, buf_core, buf_user, len); } static TEE_Result ree_fs_open_primitive(bool create, uint8_t *hash, uint32_t min_counter, const TEE_UUID *uuid, struct tee_fs_dirfile_fileh *dfh, struct tee_file_handle **fh) { TEE_Result res; struct tee_fs_fd *fdp; fdp = calloc(1, sizeof(struct tee_fs_fd)); if (!fdp) return TEE_ERROR_OUT_OF_MEMORY; fdp->fd = -1; fdp->uuid = uuid; if (create) res = tee_fs_rpc_create_dfh(OPTEE_RPC_CMD_FS, dfh, &fdp->fd); else res = tee_fs_rpc_open_dfh(OPTEE_RPC_CMD_FS, dfh, &fdp->fd); if (res != TEE_SUCCESS) goto out; res = tee_fs_htree_open(create, hash, min_counter, uuid, &ree_fs_storage_ops, fdp, &fdp->ht); out: if (res == TEE_SUCCESS) { if (dfh) fdp->dfh = *dfh; else fdp->dfh.idx = -1; *fh = (struct tee_file_handle *)fdp; } else { if (res == TEE_ERROR_SECURITY) DMSG("Secure storage corruption detected"); if (fdp->fd != -1) tee_fs_rpc_close(OPTEE_RPC_CMD_FS, fdp->fd); if (create) tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, dfh); free(fdp); } return res; } static void ree_fs_close_primitive(struct tee_file_handle *fh) { struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; if (fdp) { tee_fs_htree_close(&fdp->ht); tee_fs_rpc_close(OPTEE_RPC_CMD_FS, fdp->fd); free(fdp); } } static TEE_Result ree_dirf_commit_writes(struct tee_file_handle *fh, uint8_t *hash, uint32_t *counter) { TEE_Result res; struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash, counter); if (!res && hash) memcpy(hash, fdp->dfh.hash, sizeof(fdp->dfh.hash)); return res; } static TEE_Result dirf_read(struct tee_file_handle *fh, size_t pos, void *buf, size_t *len) { return ree_fs_read_primitive(fh, pos, buf, NULL, len); } static TEE_Result dirf_write(struct tee_file_handle *fh, size_t pos, const void *buf, size_t len) { return ree_fs_write_primitive(fh, pos, buf, NULL, len); } static const struct tee_fs_dirfile_operations ree_dirf_ops = { .open = ree_fs_open_primitive, .close = ree_fs_close_primitive, .read = dirf_read, .write = dirf_write, .commit_writes = ree_dirf_commit_writes, }; /* * ree_fs_dirh is caching the dirfile handle to avoid frequent opening and * closing of that handle. When ree_fs_dirh_refcount reaches 0, ree_fs_dirh * will be freed. However, ree_fs_dirh_refcount > 0 is not a guarantee that * ree_fs_dirh will not be freed, it may very well be freed earlier in an * error path. get_dirh() must be used to get the ree_fs_dirh pointer each * time it's needed if ree_fs_mutex has been unlocked in between. */ static struct tee_fs_dirfile_dirh *ree_fs_dirh; static size_t ree_fs_dirh_refcount; #ifdef CFG_REE_FS_INTEGRITY_RPMB static struct tee_file_handle *ree_fs_rpmb_fh; static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh) { TEE_Result res; uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; uint8_t *hashp = NULL; const char fname[] = "dirfile.db.hash"; res = tee_rpmb_fs_raw_open(fname, false, &ree_fs_rpmb_fh); if (!res) { size_t l = sizeof(hash); res = rpmb_fs_ops.read(ree_fs_rpmb_fh, 0, hash, NULL, &l); if (res) return res; if (l == sizeof(hash)) hashp = hash; } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { res = tee_rpmb_fs_raw_open(fname, true, &ree_fs_rpmb_fh); } if (res) return res; res = tee_fs_dirfile_open(false, hashp, 0, &ree_dirf_ops, dirh); if (res == TEE_ERROR_ITEM_NOT_FOUND) { if (hashp) { if (IS_ENABLED(CFG_REE_FS_ALLOW_RESET)) { DMSG("dirf.db not found, clear hash in RPMB"); res = rpmb_fs_ops.truncate(ree_fs_rpmb_fh, 0); if (res) { DMSG("Can't clear hash: %#"PRIx32, res); res = TEE_ERROR_SECURITY; goto out; } } else { DMSG("dirf.db file not found"); res = TEE_ERROR_SECURITY; goto out; } } res = tee_fs_dirfile_open(true, NULL, 0, &ree_dirf_ops, dirh); } out: if (res) rpmb_fs_ops.close(&ree_fs_rpmb_fh); return res; } static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh) { TEE_Result res; uint8_t hash[TEE_FS_HTREE_HASH_SIZE]; res = tee_fs_dirfile_commit_writes(dirh, hash, NULL); if (res) return res; return rpmb_fs_ops.write(ree_fs_rpmb_fh, 0, hash, NULL, sizeof(hash)); } static void close_dirh(struct tee_fs_dirfile_dirh **dirh) { tee_fs_dirfile_close(*dirh); *dirh = NULL; rpmb_fs_ops.close(&ree_fs_rpmb_fh); } #else /*!CFG_REE_FS_INTEGRITY_RPMB*/ static TEE_Result open_dirh(struct tee_fs_dirfile_dirh **dirh) { TEE_Result res = TEE_SUCCESS; uint32_t min_counter = 0; res = nv_counter_get_ree_fs(&min_counter); if (res) { static bool once; if (res != TEE_ERROR_NOT_IMPLEMENTED || !IS_ENABLED(CFG_INSECURE)) return res; if (!once) { IMSG("WARNING (insecure configuration): Failed to get monotonic counter for REE FS, using 0"); once = true; } min_counter = 0; } res = tee_fs_dirfile_open(false, NULL, min_counter, &ree_dirf_ops, dirh); if (res == TEE_ERROR_ITEM_NOT_FOUND) { if (min_counter) { if (!IS_ENABLED(CFG_REE_FS_ALLOW_RESET)) { DMSG("dirf.db file not found"); return TEE_ERROR_SECURITY; } DMSG("dirf.db not found, initializing with a non-zero monotonic counter"); } return tee_fs_dirfile_open(true, NULL, min_counter, &ree_dirf_ops, dirh); } return res; } static TEE_Result commit_dirh_writes(struct tee_fs_dirfile_dirh *dirh) { TEE_Result res = TEE_SUCCESS; uint32_t counter = 0; res = tee_fs_dirfile_commit_writes(dirh, NULL, &counter); if (res) return res; res = nv_counter_incr_ree_fs_to(counter); if (res == TEE_ERROR_NOT_IMPLEMENTED && IS_ENABLED(CFG_INSECURE)) { static bool once; if (!once) { IMSG("WARNING (insecure configuration): Failed to commit dirh counter %"PRIu32, counter); once = true; } return TEE_SUCCESS; } return res; } static void close_dirh(struct tee_fs_dirfile_dirh **dirh) { tee_fs_dirfile_close(*dirh); *dirh = NULL; } #endif /*!CFG_REE_FS_INTEGRITY_RPMB*/ static TEE_Result get_dirh(struct tee_fs_dirfile_dirh **dirh) { if (!ree_fs_dirh) { TEE_Result res = open_dirh(&ree_fs_dirh); if (res) { *dirh = NULL; return res; } } ree_fs_dirh_refcount++; assert(ree_fs_dirh); assert(ree_fs_dirh_refcount); *dirh = ree_fs_dirh; return TEE_SUCCESS; } static void put_dirh_primitive(bool close) { assert(ree_fs_dirh_refcount); /* * During the execution of one of the ree_fs_ops ree_fs_dirh is * guareteed to be a valid pointer. But when the fop has returned * another thread may get an error or something causing that fop * to do a put with close=1. * * For all fops but ree_fs_close() there's a call to get_dirh() to * get a new dirh which will open it again if it was closed before. * But in the ree_fs_close() case there's no call to get_dirh() * only to this function, put_dirh_primitive(), and in this case * ree_fs_dirh may actually be NULL. */ ree_fs_dirh_refcount--; if (ree_fs_dirh && (!ree_fs_dirh_refcount || close)) close_dirh(&ree_fs_dirh); } static void put_dirh(struct tee_fs_dirfile_dirh *dirh, bool close) { if (dirh) { assert(dirh == ree_fs_dirh); put_dirh_primitive(close); } } static TEE_Result ree_fs_open(struct tee_pobj *po, size_t *size, struct tee_file_handle **fh) { TEE_Result res; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_dirfile_fileh dfh; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res != TEE_SUCCESS) goto out; res = tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, &dfh); if (res != TEE_SUCCESS) goto out; res = ree_fs_open_primitive(false, dfh.hash, 0, &po->uuid, &dfh, fh); if (res == TEE_ERROR_ITEM_NOT_FOUND) { /* * If the object isn't found someone has tampered with it, * treat it as corrupt. */ res = TEE_ERROR_CORRUPT_OBJECT; } else if (!res && size) { struct tee_fs_fd *fdp = (struct tee_fs_fd *)*fh; *size = tee_fs_htree_get_meta(fdp->ht)->length; } out: if (res) put_dirh(dirh, true); mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result set_name(struct tee_fs_dirfile_dirh *dirh, struct tee_fs_fd *fdp, struct tee_pobj *po, bool overwrite) { TEE_Result res; bool have_old_dfh = false; struct tee_fs_dirfile_fileh old_dfh = { .idx = -1 }; res = tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, &old_dfh); if (!overwrite && !res) return TEE_ERROR_ACCESS_CONFLICT; if (!res) have_old_dfh = true; /* * If old_dfh wasn't found, the idx will be -1 and * tee_fs_dirfile_rename() will allocate a new index. */ fdp->dfh.idx = old_dfh.idx; old_dfh.idx = -1; res = tee_fs_dirfile_rename(dirh, &po->uuid, &fdp->dfh, po->obj_id, po->obj_id_len); if (res) return res; res = commit_dirh_writes(dirh); if (res) return res; if (have_old_dfh) tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &old_dfh); return TEE_SUCCESS; } static void ree_fs_close(struct tee_file_handle **fh) { if (*fh) { mutex_lock(&ree_fs_mutex); put_dirh_primitive(false); ree_fs_close_primitive(*fh); *fh = NULL; mutex_unlock(&ree_fs_mutex); } } static TEE_Result ree_fs_create(struct tee_pobj *po, bool overwrite, const void *head, size_t head_size, const void *attr, size_t attr_size, const void *data_core, const void *data_user, size_t data_size, struct tee_file_handle **fh) { struct tee_fs_fd *fdp; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_dirfile_fileh dfh; TEE_Result res; size_t pos = 0; /* One of data_core and data_user must be NULL */ assert(!data_core || !data_user); *fh = NULL; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; res = tee_fs_dirfile_get_tmp(dirh, &dfh); if (res) goto out; res = ree_fs_open_primitive(true, dfh.hash, 0, &po->uuid, &dfh, fh); if (res) goto out; if (head && head_size) { res = ree_fs_write_primitive(*fh, pos, head, NULL, head_size); if (res) goto out; pos += head_size; } if (attr && attr_size) { res = ree_fs_write_primitive(*fh, pos, attr, NULL, attr_size); if (res) goto out; pos += attr_size; } if ((data_core || data_user) && data_size) { res = ree_fs_write_primitive(*fh, pos, data_core, data_user, data_size); if (res) goto out; } fdp = (struct tee_fs_fd *)*fh; res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash, NULL); if (res) goto out; res = set_name(dirh, fdp, po, overwrite); out: if (res) { put_dirh(dirh, true); if (*fh) { ree_fs_close_primitive(*fh); *fh = NULL; tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &dfh); } } mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result ree_fs_write(struct tee_file_handle *fh, size_t pos, const void *buf_core, const void *buf_user, size_t len) { TEE_Result res; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; /* One of buf_core and buf_user must be NULL */ assert(!buf_core || !buf_user); mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; res = ree_fs_write_primitive(fh, pos, buf_core, buf_user, len); if (res) goto out; res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash, NULL); if (res) goto out; res = tee_fs_dirfile_update_hash(dirh, &fdp->dfh); if (res) goto out; res = commit_dirh_writes(dirh); out: put_dirh(dirh, res); mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result ree_fs_rename(struct tee_pobj *old, struct tee_pobj *new, bool overwrite) { TEE_Result res; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_dirfile_fileh dfh; struct tee_fs_dirfile_fileh remove_dfh = { .idx = -1 }; if (!new) return TEE_ERROR_BAD_PARAMETERS; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; res = tee_fs_dirfile_find(dirh, &new->uuid, new->obj_id, new->obj_id_len, &remove_dfh); if (!res && !overwrite) { res = TEE_ERROR_ACCESS_CONFLICT; goto out; } res = tee_fs_dirfile_find(dirh, &old->uuid, old->obj_id, old->obj_id_len, &dfh); if (res) goto out; res = tee_fs_dirfile_rename(dirh, &new->uuid, &dfh, new->obj_id, new->obj_id_len); if (res) goto out; if (remove_dfh.idx != -1) { res = tee_fs_dirfile_remove(dirh, &remove_dfh); if (res) goto out; } res = commit_dirh_writes(dirh); if (res) goto out; if (remove_dfh.idx != -1) tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &remove_dfh); out: put_dirh(dirh, res); mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result ree_fs_remove(struct tee_pobj *po) { TEE_Result res; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_dirfile_fileh dfh; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; res = tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, &dfh); if (res) goto out; res = tee_fs_dirfile_remove(dirh, &dfh); if (res) goto out; res = commit_dirh_writes(dirh); if (res) goto out; tee_fs_rpc_remove_dfh(OPTEE_RPC_CMD_FS, &dfh); assert(tee_fs_dirfile_find(dirh, &po->uuid, po->obj_id, po->obj_id_len, &dfh)); out: put_dirh(dirh, res); mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result ree_fs_truncate(struct tee_file_handle *fh, size_t len) { TEE_Result res; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_fd *fdp = (struct tee_fs_fd *)fh; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; res = ree_fs_ftruncate_internal(fdp, len); if (res) goto out; res = tee_fs_htree_sync_to_storage(&fdp->ht, fdp->dfh.hash, NULL); if (res) goto out; res = tee_fs_dirfile_update_hash(dirh, &fdp->dfh); if (res) goto out; res = commit_dirh_writes(dirh); out: put_dirh(dirh, res); mutex_unlock(&ree_fs_mutex); return res; } static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid, struct tee_fs_dir **dir) { TEE_Result res = TEE_SUCCESS; struct tee_fs_dirfile_dirh *dirh = NULL; struct tee_fs_dir *d = calloc(1, sizeof(*d)); if (!d) return TEE_ERROR_OUT_OF_MEMORY; d->uuid = uuid; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; /* See that there's at least one file */ d->idx = -1; d->d.oidlen = sizeof(d->d.oid); res = tee_fs_dirfile_get_next(dirh, d->uuid, &d->idx, d->d.oid, &d->d.oidlen); d->idx = -1; out: if (!res) { *dir = d; } else { if (d) put_dirh(dirh, false); free(d); } mutex_unlock(&ree_fs_mutex); return res; } static void ree_fs_closedir_rpc(struct tee_fs_dir *d) { if (d) { mutex_lock(&ree_fs_mutex); put_dirh(ree_fs_dirh, false); free(d); mutex_unlock(&ree_fs_mutex); } } static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d, struct tee_fs_dirent **ent) { struct tee_fs_dirfile_dirh *dirh = NULL; TEE_Result res = TEE_SUCCESS; mutex_lock(&ree_fs_mutex); res = get_dirh(&dirh); if (res) goto out; d->d.oidlen = sizeof(d->d.oid); res = tee_fs_dirfile_get_next(dirh, d->uuid, &d->idx, d->d.oid, &d->d.oidlen); if (res == TEE_SUCCESS) *ent = &d->d; put_dirh(dirh, res); out: mutex_unlock(&ree_fs_mutex); return res; } const struct tee_file_operations ree_fs_ops = { .open = ree_fs_open, .create = ree_fs_create, .close = ree_fs_close, .read = ree_fs_read, .write = ree_fs_write, .truncate = ree_fs_truncate, .rename = ree_fs_rename, .remove = ree_fs_remove, .opendir = ree_fs_opendir_rpc, .closedir = ree_fs_closedir_rpc, .readdir = ree_fs_readdir_rpc, }; optee_os-4.3.0/core/tee/tee_rpmb_fs.c000066400000000000000000002257031464416617300175160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RPMB_STORAGE_START_ADDRESS 0 #define RPMB_FS_FAT_START_ADDRESS 512 #define RPMB_BLOCK_SIZE_SHIFT 8 #define RPMB_CID_PRV_OFFSET 9 #define RPMB_CID_CRC_OFFSET 15 #define RPMB_FS_MAGIC 0x52504D42 #define FS_VERSION 2 #define FILE_IS_ACTIVE (1u << 0) #define FILE_IS_LAST_ENTRY (1u << 1) #define TEE_RPMB_FS_FILENAME_LENGTH 224 #define TMP_BLOCK_SIZE 4096U #define RPMB_MAX_RETRIES 10 /** * Utilized when caching is enabled, i.e., when CFG_RPMB_FS_CACHE_ENTRIES > 0. * Cache size + the number of entries that are repeatedly read in and buffered * once the cache is full. */ #define RPMB_BUF_MAX_ENTRIES (CFG_RPMB_FS_CACHE_ENTRIES + \ CFG_RPMB_FS_RD_ENTRIES) /** * FS parameters: Information often used by internal functions. * fat_start_address will be set by rpmb_fs_setup(). * rpmb_fs_parameters can be read by any other function. */ struct rpmb_fs_parameters { uint32_t fat_start_address; uint32_t max_rpmb_address; }; /** * File entry for a single file in a RPMB_FS partition. */ struct rpmb_fat_entry { uint32_t start_address; uint32_t data_size; uint32_t flags; uint32_t unused; uint8_t fek[TEE_FS_KM_FEK_SIZE]; char filename[TEE_RPMB_FS_FILENAME_LENGTH]; }; /** * Structure that describes buffered/cached FAT FS entries in RPMB storage. * This structure is used in functions traversing the FAT FS. */ struct rpmb_fat_entry_dir { /* * Buffer storing the FAT FS entries read in from RPMB storage. It * includes the optional cache entries (CFG_RPMB_FS_CACHE_ENTRIES) * and entries temporary read for current FAT FS traversal * (CFG_RPMB_FS_RD_ENTRIES) when not found from cached entries. */ struct rpmb_fat_entry *rpmb_fat_entry_buf; /* Current index of FAT FS entry to read from buffer. */ uint32_t idx_curr; /* Total number of FAT FS entries in buffer. */ uint32_t num_buffered; /* Total number of FAT FS entries read during traversal. */ uint32_t num_total_read; /* Indicates that last FAT FS entry was read. */ bool last_reached; }; /** * FAT entry context with reference to a FAT entry and its * location in RPMB. */ struct rpmb_file_handle { struct rpmb_fat_entry fat_entry; const TEE_UUID *uuid; char filename[TEE_RPMB_FS_FILENAME_LENGTH]; /* Address for current entry in RPMB */ uint32_t rpmb_fat_address; }; /** * RPMB_FS partition data */ struct rpmb_fs_partition { uint32_t rpmb_fs_magic; uint32_t fs_version; uint32_t write_counter; uint32_t fat_start_address; /* Do not use reserved[] for other purpose than partition data. */ uint8_t reserved[112]; }; /** * A node in a list of directory entries. */ struct tee_rpmb_fs_dirent { struct tee_fs_dirent entry; SIMPLEQ_ENTRY(tee_rpmb_fs_dirent) link; }; /** * The RPMB directory representation. It contains a queue of * RPMB directory entries: 'next'. * The current pointer points to the last directory entry * returned by readdir(). */ struct tee_fs_dir { struct tee_rpmb_fs_dirent *current; /* */ SIMPLEQ_HEAD(next_head, tee_rpmb_fs_dirent) next; }; static struct rpmb_fs_parameters *fs_par; static struct rpmb_fat_entry_dir *fat_entry_dir; /* * Lower interface to RPMB device */ #define RPMB_DATA_OFFSET (RPMB_STUFF_DATA_SIZE + RPMB_KEY_MAC_SIZE) #define RPMB_MAC_PROTECT_DATA_SIZE (RPMB_DATA_FRAME_SIZE - RPMB_DATA_OFFSET) #define RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM 0x0001 #define RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ 0x0002 #define RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE 0x0003 #define RPMB_MSG_TYPE_REQ_AUTH_DATA_READ 0x0004 #define RPMB_MSG_TYPE_REQ_RESULT_READ 0x0005 #define RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM 0x0100 #define RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ 0x0200 #define RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE 0x0300 #define RPMB_MSG_TYPE_RESP_AUTH_DATA_READ 0x0400 #define RPMB_STUFF_DATA_SIZE 196 #define RPMB_KEY_MAC_SIZE 32 #define RPMB_DATA_SIZE 256 #define RPMB_NONCE_SIZE 16 #define RPMB_DATA_FRAME_SIZE 512 #define RPMB_RESULT_OK 0x00 #define RPMB_RESULT_GENERAL_FAILURE 0x01 #define RPMB_RESULT_AUTH_FAILURE 0x02 #define RPMB_RESULT_COUNTER_FAILURE 0x03 #define RPMB_RESULT_ADDRESS_FAILURE 0x04 #define RPMB_RESULT_WRITE_FAILURE 0x05 #define RPMB_RESULT_READ_FAILURE 0x06 #define RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED 0x07 #define RPMB_RESULT_MASK 0x3F #define RPMB_RESULT_WR_CNT_EXPIRED 0x80 /* RPMB internal commands */ #define RPMB_CMD_DATA_REQ 0x00 #define RPMB_CMD_GET_DEV_INFO 0x01 #define RPMB_SIZE_SINGLE (128 * 1024) /* Error codes for get_dev_info request/response. */ #define RPMB_CMD_GET_DEV_INFO_RET_OK 0x00 #define RPMB_CMD_GET_DEV_INFO_RET_ERROR 0x01 struct rpmb_data_frame { uint8_t stuff_bytes[RPMB_STUFF_DATA_SIZE]; uint8_t key_mac[RPMB_KEY_MAC_SIZE]; uint8_t data[RPMB_DATA_SIZE]; uint8_t nonce[RPMB_NONCE_SIZE]; uint8_t write_counter[4]; uint8_t address[2]; uint8_t block_count[2]; uint8_t op_result[2]; uint8_t msg_type[2]; }; struct rpmb_req { uint16_t cmd; uint16_t dev_id; uint16_t block_count; /* variable length of data */ /* uint8_t data[]; REMOVED! */ }; #define TEE_RPMB_REQ_DATA(req) \ ((void *)((struct rpmb_req *)(req) + 1)) struct rpmb_raw_data { uint16_t msg_type; uint16_t *op_result; uint16_t *block_count; uint16_t *blk_idx; uint32_t *write_counter; uint8_t *nonce; uint8_t *key_mac; uint8_t *data; /* data length to read or write */ uint32_t len; /* Byte address offset in the first block involved */ uint8_t byte_offset; }; #define RPMB_EMMC_CID_SIZE 16 struct rpmb_dev_info { uint8_t cid[RPMB_EMMC_CID_SIZE]; /* EXT CSD-slice 168 "RPMB Size" */ uint8_t rpmb_size_mult; /* EXT CSD-slice 222 "Reliable Write Sector Count" */ uint8_t rel_wr_sec_c; /* Check the ret code and accept the data only if it is OK. */ uint8_t ret_code; }; /* * Struct for rpmb context data. * * @key RPMB key. * @cid eMMC card ID. * @wr_cnt Current write counter. * @max_blk_idx The highest block index supported by current device. * @rel_wr_blkcnt Max number of data blocks for each reliable write. * @dev_id Device ID of the eMMC device. * @wr_cnt_synced Flag indicating if write counter is synced to RPMB. * @key_derived Flag indicating if key has been generated. * @key_verified Flag indicating the key generated is verified ok. * @dev_info_synced Flag indicating if dev info has been retrieved from RPMB. */ struct tee_rpmb_ctx { uint8_t key[RPMB_KEY_MAC_SIZE]; uint8_t cid[RPMB_EMMC_CID_SIZE]; uint32_t wr_cnt; uint16_t max_blk_idx; uint16_t rel_wr_blkcnt; uint16_t dev_id; bool wr_cnt_synced; bool key_derived; bool key_verified; bool dev_info_synced; }; static struct tee_rpmb_ctx *rpmb_ctx; /* If set to true, don't try to access RPMB until rebooted */ static bool rpmb_dead; /* * Mutex to serialize the operations exported by this file. * It protects rpmb_ctx and prevents overlapping operations on eMMC devices with * different IDs. */ static struct mutex rpmb_mutex = MUTEX_INITIALIZER; #ifdef CFG_RPMB_TESTKEY static const uint8_t rpmb_test_key[RPMB_KEY_MAC_SIZE] = { 0xD3, 0xEB, 0x3E, 0xC3, 0x6E, 0x33, 0x4C, 0x9F, 0x98, 0x8C, 0xE2, 0xC0, 0xB8, 0x59, 0x54, 0x61, 0x0D, 0x2B, 0xCF, 0x86, 0x64, 0x84, 0x4D, 0xF2, 0xAB, 0x56, 0xE6, 0xC6, 0x1B, 0xB7, 0x01, 0xE4 }; static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused, uint8_t *key, uint32_t len) { TEE_Result res = TEE_SUCCESS; if (!key || RPMB_KEY_MAC_SIZE != len) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } DMSG("RPMB: Using test key"); memcpy(key, rpmb_test_key, RPMB_KEY_MAC_SIZE); out: return res; } #else /* !CFG_RPMB_TESTKEY */ static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused, uint8_t *key, uint32_t len) { uint8_t message[RPMB_EMMC_CID_SIZE]; if (!key || RPMB_KEY_MAC_SIZE != len) return TEE_ERROR_BAD_PARAMETERS; IMSG("RPMB: Using generated key"); /* * PRV/CRC would be changed when doing eMMC FFU * The following fields should be masked off when deriving RPMB key * * CID [55: 48]: PRV (Product revision) * CID [07: 01]: CRC (CRC7 checksum) * CID [00]: not used */ memcpy(message, rpmb_ctx->cid, RPMB_EMMC_CID_SIZE); memset(message + RPMB_CID_PRV_OFFSET, 0, 1); memset(message + RPMB_CID_CRC_OFFSET, 0, 1); return huk_subkey_derive(HUK_SUBKEY_RPMB, message, sizeof(message), key, len); } #endif /* !CFG_RPMB_TESTKEY */ static void u32_to_bytes(uint32_t u32, uint8_t *bytes) { *bytes = (uint8_t) (u32 >> 24); *(bytes + 1) = (uint8_t) (u32 >> 16); *(bytes + 2) = (uint8_t) (u32 >> 8); *(bytes + 3) = (uint8_t) u32; } static void bytes_to_u32(uint8_t *bytes, uint32_t *u32) { *u32 = (uint32_t) ((*(bytes) << 24) + (*(bytes + 1) << 16) + (*(bytes + 2) << 8) + (*(bytes + 3))); } static void u16_to_bytes(uint16_t u16, uint8_t *bytes) { *bytes = (uint8_t) (u16 >> 8); *(bytes + 1) = (uint8_t) u16; } static void bytes_to_u16(uint8_t *bytes, uint16_t *u16) { *u16 = (uint16_t) ((*bytes << 8) + *(bytes + 1)); } static void get_op_result_bits(uint8_t *bytes, uint8_t *res) { *res = *(bytes + 1) & RPMB_RESULT_MASK; } static TEE_Result tee_rpmb_mac_calc(uint8_t *mac, uint32_t macsize, uint8_t *key, uint32_t keysize, struct rpmb_data_frame *datafrms, uint16_t blkcnt) { TEE_Result res = TEE_ERROR_GENERIC; int i; void *ctx = NULL; if (!mac || !key || !datafrms) return TEE_ERROR_BAD_PARAMETERS; res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); if (res) return res; res = crypto_mac_init(ctx, key, keysize); if (res != TEE_SUCCESS) goto func_exit; for (i = 0; i < blkcnt; i++) { res = crypto_mac_update(ctx, datafrms[i].data, RPMB_MAC_PROTECT_DATA_SIZE); if (res != TEE_SUCCESS) goto func_exit; } res = crypto_mac_final(ctx, mac, macsize); if (res != TEE_SUCCESS) goto func_exit; res = TEE_SUCCESS; func_exit: crypto_mac_free_ctx(ctx); return res; } struct tee_rpmb_mem { struct mobj *phreq_mobj; struct mobj *phresp_mobj; size_t req_size; size_t resp_size; }; static void tee_rpmb_free(struct tee_rpmb_mem *mem) { if (!mem) return; if (mem->phreq_mobj) { thread_rpc_free_payload(mem->phreq_mobj); mem->phreq_mobj = NULL; } if (mem->phresp_mobj) { thread_rpc_free_payload(mem->phresp_mobj); mem->phresp_mobj = NULL; } } static TEE_Result tee_rpmb_alloc(size_t req_size, size_t resp_size, struct tee_rpmb_mem *mem, void **req, void **resp) { TEE_Result res = TEE_SUCCESS; size_t req_s = ROUNDUP(req_size, sizeof(uint32_t)); size_t resp_s = ROUNDUP(resp_size, sizeof(uint32_t)); if (!mem) return TEE_ERROR_BAD_PARAMETERS; memset(mem, 0, sizeof(*mem)); mem->phreq_mobj = thread_rpc_alloc_payload(req_s); mem->phresp_mobj = thread_rpc_alloc_payload(resp_s); if (!mem->phreq_mobj || !mem->phresp_mobj) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } *req = mobj_get_va(mem->phreq_mobj, 0, req_s); *resp = mobj_get_va(mem->phresp_mobj, 0, resp_s); if (!*req || !*resp) { res = TEE_ERROR_GENERIC; goto out; } mem->req_size = req_size; mem->resp_size = resp_size; out: if (res != TEE_SUCCESS) tee_rpmb_free(mem); return res; } static TEE_Result tee_rpmb_invoke(struct tee_rpmb_mem *mem) { struct thread_param params[2] = { [0] = THREAD_PARAM_MEMREF(IN, mem->phreq_mobj, 0, mem->req_size), [1] = THREAD_PARAM_MEMREF(OUT, mem->phresp_mobj, 0, mem->resp_size), }; return thread_rpc_cmd(OPTEE_RPC_CMD_RPMB, 2, params); } static bool is_zero(const uint8_t *buf, size_t size) { size_t i; for (i = 0; i < size; i++) if (buf[i]) return false; return true; } static TEE_Result encrypt_block(uint8_t *out, const uint8_t *in, uint16_t blk_idx, const uint8_t *fek, const TEE_UUID *uuid) { return tee_fs_crypt_block(uuid, out, in, RPMB_DATA_SIZE, blk_idx, fek, TEE_MODE_ENCRYPT); } static TEE_Result decrypt_block(uint8_t *out, const uint8_t *in, uint16_t blk_idx, const uint8_t *fek, const TEE_UUID *uuid) { return tee_fs_crypt_block(uuid, out, in, RPMB_DATA_SIZE, blk_idx, fek, TEE_MODE_DECRYPT); } /* Decrypt/copy at most one block of data */ static TEE_Result decrypt(uint8_t *out, const struct rpmb_data_frame *frm, size_t size, size_t offset, uint16_t blk_idx __maybe_unused, const uint8_t *fek, const TEE_UUID *uuid) { uint8_t *tmp __maybe_unused; TEE_Result res = TEE_SUCCESS; if ((size + offset < size) || (size + offset > RPMB_DATA_SIZE)) panic("invalid size or offset"); if (!fek) { /* Block is not encrypted (not a file data block) */ memcpy(out, frm->data + offset, size); } else if (is_zero(fek, TEE_FS_KM_FEK_SIZE)) { /* The file was created with encryption disabled */ return TEE_ERROR_SECURITY; } else { /* Block is encrypted */ if (size < RPMB_DATA_SIZE) { /* * Since output buffer is not large enough to hold one * block we must allocate a temporary buffer. */ tmp = malloc(RPMB_DATA_SIZE); if (!tmp) return TEE_ERROR_OUT_OF_MEMORY; res = decrypt_block(tmp, frm->data, blk_idx, fek, uuid); if (res == TEE_SUCCESS) memcpy(out, tmp + offset, size); free(tmp); } else { res = decrypt_block(out, frm->data, blk_idx, fek, uuid); } } return res; } static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req, struct rpmb_raw_data *rawdata, uint16_t nbr_frms, uint16_t dev_id, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res = TEE_ERROR_GENERIC; int i; struct rpmb_data_frame *datafrm; if (!req || !rawdata || !nbr_frms) return TEE_ERROR_BAD_PARAMETERS; /* * Check write blockcount is not bigger than reliable write * blockcount. */ if ((rawdata->msg_type == RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) && (nbr_frms > rpmb_ctx->rel_wr_blkcnt)) { DMSG("wr_blkcnt(%d) > rel_wr_blkcnt(%d)", nbr_frms, rpmb_ctx->rel_wr_blkcnt); return TEE_ERROR_GENERIC; } req->cmd = RPMB_CMD_DATA_REQ; req->dev_id = dev_id; /* Allocate memory for construct all data packets and calculate MAC. */ datafrm = calloc(nbr_frms, RPMB_DATA_FRAME_SIZE); if (!datafrm) return TEE_ERROR_OUT_OF_MEMORY; for (i = 0; i < nbr_frms; i++) { u16_to_bytes(rawdata->msg_type, datafrm[i].msg_type); if (rawdata->block_count) u16_to_bytes(*rawdata->block_count, datafrm[i].block_count); if (rawdata->blk_idx) { /* Check the block index is within range. */ if ((*rawdata->blk_idx + nbr_frms - 1) > rpmb_ctx->max_blk_idx) { res = TEE_ERROR_GENERIC; goto func_exit; } u16_to_bytes(*rawdata->blk_idx, datafrm[i].address); } if (rawdata->write_counter) u32_to_bytes(*rawdata->write_counter, datafrm[i].write_counter); if (rawdata->nonce) memcpy(datafrm[i].nonce, rawdata->nonce, RPMB_NONCE_SIZE); if (rawdata->data) { if (fek) { res = encrypt_block(datafrm[i].data, rawdata->data + (i * RPMB_DATA_SIZE), *rawdata->blk_idx + i, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; } else { memcpy(datafrm[i].data, rawdata->data + (i * RPMB_DATA_SIZE), RPMB_DATA_SIZE); } } } if (rawdata->key_mac) { if (rawdata->msg_type == RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE) { res = tee_rpmb_mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE, rpmb_ctx->key, RPMB_KEY_MAC_SIZE, datafrm, nbr_frms); if (res != TEE_SUCCESS) goto func_exit; } memcpy(datafrm[nbr_frms - 1].key_mac, rawdata->key_mac, RPMB_KEY_MAC_SIZE); } memcpy(TEE_RPMB_REQ_DATA(req), datafrm, nbr_frms * RPMB_DATA_FRAME_SIZE); if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) { for (i = 0; i < nbr_frms; i++) { DMSG("Dumping data frame %d:", i); DHEXDUMP((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE, 512 - RPMB_STUFF_DATA_SIZE); } } res = TEE_SUCCESS; func_exit: free(datafrm); return res; } static TEE_Result data_cpy_mac_calc_1b(struct rpmb_raw_data *rawdata, struct rpmb_data_frame *frm, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res; uint8_t *data; uint16_t idx; if (rawdata->len + rawdata->byte_offset > RPMB_DATA_SIZE) return TEE_ERROR_BAD_PARAMETERS; res = tee_rpmb_mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE, rpmb_ctx->key, RPMB_KEY_MAC_SIZE, frm, 1); if (res != TEE_SUCCESS) return res; data = rawdata->data; bytes_to_u16(frm->address, &idx); res = decrypt(data, frm, rawdata->len, rawdata->byte_offset, idx, fek, uuid); return res; } static TEE_Result tee_rpmb_data_cpy_mac_calc(struct rpmb_data_frame *datafrm, struct rpmb_raw_data *rawdata, uint16_t nbr_frms, struct rpmb_data_frame *lastfrm, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res = TEE_ERROR_GENERIC; int i; void *ctx = NULL; uint16_t offset; uint32_t size; uint8_t *data; uint16_t start_idx; struct rpmb_data_frame localfrm; if (!datafrm || !rawdata || !nbr_frms || !lastfrm) return TEE_ERROR_BAD_PARAMETERS; if (nbr_frms == 1) return data_cpy_mac_calc_1b(rawdata, lastfrm, fek, uuid); /* nbr_frms > 1 */ data = rawdata->data; res = crypto_mac_alloc_ctx(&ctx, TEE_ALG_HMAC_SHA256); if (res) goto func_exit; res = crypto_mac_init(ctx, rpmb_ctx->key, RPMB_KEY_MAC_SIZE); if (res != TEE_SUCCESS) goto func_exit; /* * Note: JEDEC JESD84-B51: "In every packet the address is the start * address of the full access (not address of the individual half a * sector)" */ bytes_to_u16(lastfrm->address, &start_idx); for (i = 0; i < (nbr_frms - 1); i++) { /* * By working on a local copy of the RPMB frame, we ensure that * the data can not be modified after the MAC is computed but * before the payload is decrypted/copied to the output buffer. */ memcpy(&localfrm, &datafrm[i], RPMB_DATA_FRAME_SIZE); res = crypto_mac_update(ctx, localfrm.data, RPMB_MAC_PROTECT_DATA_SIZE); if (res != TEE_SUCCESS) goto func_exit; if (i == 0) { /* First block */ offset = rawdata->byte_offset; size = RPMB_DATA_SIZE - offset; } else { /* Middle blocks */ size = RPMB_DATA_SIZE; offset = 0; } res = decrypt(data, &localfrm, size, offset, start_idx + i, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; data += size; } /* Last block */ size = (rawdata->len + rawdata->byte_offset) % RPMB_DATA_SIZE; if (size == 0) size = RPMB_DATA_SIZE; res = decrypt(data, lastfrm, size, 0, start_idx + nbr_frms - 1, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; /* Update MAC against the last block */ res = crypto_mac_update(ctx, lastfrm->data, RPMB_MAC_PROTECT_DATA_SIZE); if (res != TEE_SUCCESS) goto func_exit; res = crypto_mac_final(ctx, rawdata->key_mac, RPMB_KEY_MAC_SIZE); if (res != TEE_SUCCESS) goto func_exit; res = TEE_SUCCESS; func_exit: crypto_mac_free_ctx(ctx); return res; } static TEE_Result tee_rpmb_resp_unpack_verify(struct rpmb_data_frame *datafrm, struct rpmb_raw_data *rawdata, uint16_t nbr_frms, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res = TEE_ERROR_GENERIC; uint16_t msg_type; uint32_t wr_cnt; uint16_t blk_idx; uint8_t op_result; struct rpmb_data_frame lastfrm; if (!datafrm || !rawdata || !nbr_frms) return TEE_ERROR_BAD_PARAMETERS; if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) { size_t i = 0; for (i = 0; i < nbr_frms; i++) { DMSG("Dumping data frame %zu:", i); DHEXDUMP((uint8_t *)&datafrm[i] + RPMB_STUFF_DATA_SIZE, 512 - RPMB_STUFF_DATA_SIZE); } } /* Make sure the last data packet can't be modified once verified */ memcpy(&lastfrm, &datafrm[nbr_frms - 1], RPMB_DATA_FRAME_SIZE); /* Handle operation result and translate to TEEC error code. */ get_op_result_bits(lastfrm.op_result, &op_result); if (op_result == RPMB_RESULT_AUTH_KEY_NOT_PROGRAMMED) return TEE_ERROR_ITEM_NOT_FOUND; if (op_result != RPMB_RESULT_OK) return TEE_ERROR_GENERIC; /* Check the response msg_type. */ bytes_to_u16(lastfrm.msg_type, &msg_type); if (msg_type != rawdata->msg_type) { DMSG("Unexpected msg_type (0x%04x != 0x%04x)", msg_type, rawdata->msg_type); return TEE_ERROR_GENERIC; } if (rawdata->blk_idx) { bytes_to_u16(lastfrm.address, &blk_idx); if (blk_idx != *rawdata->blk_idx) { DMSG("Unexpected block index"); return TEE_ERROR_GENERIC; } } if (rawdata->write_counter) { wr_cnt = *rawdata->write_counter; bytes_to_u32(lastfrm.write_counter, rawdata->write_counter); if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE) { /* Verify the write counter is incremented by 1 */ if (*rawdata->write_counter != wr_cnt + 1) { DMSG("Counter mismatched (0x%04x/0x%04x)", *rawdata->write_counter, wr_cnt + 1); return TEE_ERROR_SECURITY; } rpmb_ctx->wr_cnt++; } } if (rawdata->nonce) { if (buf_compare_ct(rawdata->nonce, lastfrm.nonce, RPMB_NONCE_SIZE) != 0) { DMSG("Nonce mismatched"); return TEE_ERROR_SECURITY; } } if (rawdata->key_mac) { if (msg_type == RPMB_MSG_TYPE_RESP_AUTH_DATA_READ) { if (!rawdata->data) return TEE_ERROR_GENERIC; res = tee_rpmb_data_cpy_mac_calc(datafrm, rawdata, nbr_frms, &lastfrm, fek, uuid); if (res != TEE_SUCCESS) return res; } else { /* * There should be only one data frame for * other msg types. */ if (nbr_frms != 1) return TEE_ERROR_GENERIC; res = tee_rpmb_mac_calc(rawdata->key_mac, RPMB_KEY_MAC_SIZE, rpmb_ctx->key, RPMB_KEY_MAC_SIZE, &lastfrm, 1); if (res != TEE_SUCCESS) return res; } if (consttime_memcmp(rawdata->key_mac, (datafrm + nbr_frms - 1)->key_mac, RPMB_KEY_MAC_SIZE) != 0) { DMSG("MAC mismatched:"); if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) DHEXDUMP(rawdata->key_mac, RPMB_KEY_MAC_SIZE); return TEE_ERROR_SECURITY; } } return TEE_SUCCESS; } static TEE_Result tee_rpmb_get_dev_info(uint16_t dev_id, struct rpmb_dev_info *dev_info) { TEE_Result res = TEE_ERROR_GENERIC; struct tee_rpmb_mem mem; struct rpmb_dev_info *di; struct rpmb_req *req = NULL; uint8_t *resp = NULL; uint32_t req_size; uint32_t resp_size; if (!dev_info) return TEE_ERROR_BAD_PARAMETERS; req_size = sizeof(struct rpmb_req); resp_size = sizeof(struct rpmb_dev_info); res = tee_rpmb_alloc(req_size, resp_size, &mem, (void *)&req, (void *)&resp); if (res != TEE_SUCCESS) goto func_exit; req->cmd = RPMB_CMD_GET_DEV_INFO; req->dev_id = dev_id; di = (struct rpmb_dev_info *)resp; di->ret_code = RPMB_CMD_GET_DEV_INFO_RET_ERROR; res = tee_rpmb_invoke(&mem); if (res != TEE_SUCCESS) goto func_exit; if (di->ret_code != RPMB_CMD_GET_DEV_INFO_RET_OK) { res = TEE_ERROR_GENERIC; goto func_exit; } memcpy((uint8_t *)dev_info, resp, sizeof(struct rpmb_dev_info)); if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) { DMSG("Dumping dev_info:"); DHEXDUMP((uint8_t *)dev_info, sizeof(struct rpmb_dev_info)); } res = TEE_SUCCESS; func_exit: tee_rpmb_free(&mem); return res; } static TEE_Result tee_rpmb_init_read_wr_cnt(uint16_t dev_id, uint32_t *wr_cnt, uint16_t *op_result) { TEE_Result res = TEE_ERROR_GENERIC; struct tee_rpmb_mem mem; uint16_t msg_type; uint8_t nonce[RPMB_NONCE_SIZE]; uint8_t hmac[RPMB_KEY_MAC_SIZE]; struct rpmb_req *req = NULL; struct rpmb_data_frame *resp = NULL; struct rpmb_raw_data rawdata; uint32_t req_size; uint32_t resp_size; if (!wr_cnt) return TEE_ERROR_BAD_PARAMETERS; req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE; resp_size = RPMB_DATA_FRAME_SIZE; res = tee_rpmb_alloc(req_size, resp_size, &mem, (void *)&req, (void *)&resp); if (res != TEE_SUCCESS) goto func_exit; res = crypto_rng_read(nonce, RPMB_NONCE_SIZE); if (res != TEE_SUCCESS) goto func_exit; msg_type = RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ; memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); rawdata.msg_type = msg_type; rawdata.nonce = nonce; res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL, NULL); if (res != TEE_SUCCESS) goto func_exit; res = tee_rpmb_invoke(&mem); if (res != TEE_SUCCESS) goto func_exit; msg_type = RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ; memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); rawdata.msg_type = msg_type; rawdata.op_result = op_result; rawdata.write_counter = wr_cnt; rawdata.nonce = nonce; rawdata.key_mac = hmac; res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL, NULL); if (res != TEE_SUCCESS) goto func_exit; res = TEE_SUCCESS; func_exit: tee_rpmb_free(&mem); return res; } static TEE_Result tee_rpmb_verify_key_sync_counter(uint16_t dev_id) { uint16_t op_result = 0; TEE_Result res = TEE_ERROR_GENERIC; res = tee_rpmb_init_read_wr_cnt(dev_id, &rpmb_ctx->wr_cnt, &op_result); if (res == TEE_SUCCESS) { rpmb_ctx->key_verified = true; rpmb_ctx->wr_cnt_synced = true; } else EMSG("Verify key returning 0x%x", res); return res; } #ifdef CFG_RPMB_WRITE_KEY static TEE_Result tee_rpmb_write_key(uint16_t dev_id) { TEE_Result res = TEE_ERROR_GENERIC; struct tee_rpmb_mem mem = { 0 }; uint16_t msg_type; struct rpmb_req *req = NULL; struct rpmb_data_frame *resp = NULL; struct rpmb_raw_data rawdata; uint32_t req_size; uint32_t resp_size; req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE; resp_size = RPMB_DATA_FRAME_SIZE; res = tee_rpmb_alloc(req_size, resp_size, &mem, (void *)&req, (void *)&resp); if (res != TEE_SUCCESS) goto func_exit; msg_type = RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM; memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); rawdata.msg_type = msg_type; rawdata.key_mac = rpmb_ctx->key; res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL, NULL); if (res != TEE_SUCCESS) goto func_exit; res = tee_rpmb_invoke(&mem); if (res != TEE_SUCCESS) goto func_exit; msg_type = RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM; memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); rawdata.msg_type = msg_type; res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL, NULL); if (res != TEE_SUCCESS) goto func_exit; res = TEE_SUCCESS; func_exit: tee_rpmb_free(&mem); return res; } static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id) { TEE_Result res; if (!plat_rpmb_key_is_ready()) { DMSG("RPMB INIT: platform indicates RPMB key is not ready"); return TEE_ERROR_BAD_STATE; } DMSG("RPMB INIT: Writing Key value:"); DHEXDUMP(rpmb_ctx->key, RPMB_KEY_MAC_SIZE); res = tee_rpmb_write_key(dev_id); if (res == TEE_SUCCESS) { DMSG("RPMB INIT: Verifying Key"); res = tee_rpmb_verify_key_sync_counter(dev_id); } return res; } #else static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id __unused) { DMSG("RPMB INIT: CFG_RPMB_WRITE_KEY is not set"); return TEE_ERROR_STORAGE_NOT_AVAILABLE; } #endif /* This function must never return TEE_SUCCESS if rpmb_ctx == NULL */ static TEE_Result tee_rpmb_init(uint16_t dev_id) { TEE_Result res = TEE_SUCCESS; struct rpmb_dev_info dev_info = { }; uint32_t nblocks = 0; if (rpmb_dead) return TEE_ERROR_COMMUNICATION; if (!rpmb_ctx) { rpmb_ctx = calloc(1, sizeof(struct tee_rpmb_ctx)); if (!rpmb_ctx) return TEE_ERROR_OUT_OF_MEMORY; } else if (rpmb_ctx->dev_id != dev_id) { memset(rpmb_ctx, 0x00, sizeof(struct tee_rpmb_ctx)); } rpmb_ctx->dev_id = dev_id; if (!rpmb_ctx->dev_info_synced) { DMSG("RPMB: Syncing device information"); dev_info.rpmb_size_mult = 0; dev_info.rel_wr_sec_c = 0; res = tee_rpmb_get_dev_info(dev_id, &dev_info); if (res != TEE_SUCCESS) goto func_exit; DMSG("RPMB: RPMB size is %d*128 KB", dev_info.rpmb_size_mult); DMSG("RPMB: Reliable Write Sector Count is %d", dev_info.rel_wr_sec_c); if (dev_info.rpmb_size_mult == 0) { res = TEE_ERROR_GENERIC; goto func_exit; } if (MUL_OVERFLOW(dev_info.rpmb_size_mult, RPMB_SIZE_SINGLE / RPMB_DATA_SIZE, &nblocks) || SUB_OVERFLOW(nblocks, 1, &rpmb_ctx->max_blk_idx)) { res = TEE_ERROR_BAD_PARAMETERS; goto func_exit; } memcpy(rpmb_ctx->cid, dev_info.cid, RPMB_EMMC_CID_SIZE); #ifdef RPMB_DRIVER_MULTIPLE_WRITE_FIXED rpmb_ctx->rel_wr_blkcnt = dev_info.rel_wr_sec_c * 2; #else rpmb_ctx->rel_wr_blkcnt = 1; #endif rpmb_ctx->dev_info_synced = true; } if (!rpmb_ctx->key_derived) { DMSG("RPMB INIT: Deriving key"); res = tee_rpmb_key_gen(dev_id, rpmb_ctx->key, RPMB_KEY_MAC_SIZE); if (res != TEE_SUCCESS) { EMSG("RPMB INIT: Deriving key failed with error 0x%x", res); goto func_exit; } rpmb_ctx->key_derived = true; } /* Perform a write counter read to verify if the key is ok. */ if (!rpmb_ctx->wr_cnt_synced || !rpmb_ctx->key_verified) { DMSG("RPMB INIT: Verifying Key"); res = tee_rpmb_verify_key_sync_counter(dev_id); if (res == TEE_ERROR_ITEM_NOT_FOUND && !rpmb_ctx->key_verified) { /* * Need to write the key here and verify it. */ DMSG("RPMB INIT: Auth key not yet written"); res = tee_rpmb_write_and_verify_key(dev_id); } else if (res != TEE_SUCCESS) { EMSG("Verify key failed!"); EMSG("Make sure key here matches device key"); } } func_exit: return res; } /* * Read RPMB data in bytes. * * @dev_id Device ID of the eMMC device. * @addr Byte address of data. * @data Pointer to the data. * @len Size of data in bytes. * @fek Encrypted File Encryption Key or NULL. */ static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data, uint32_t len, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res = TEE_ERROR_GENERIC; struct tee_rpmb_mem mem = { 0 }; uint16_t msg_type; uint8_t nonce[RPMB_NONCE_SIZE]; uint8_t hmac[RPMB_KEY_MAC_SIZE]; struct rpmb_req *req = NULL; struct rpmb_data_frame *resp = NULL; struct rpmb_raw_data rawdata; uint32_t req_size; uint32_t resp_size; uint16_t blk_idx; uint16_t blkcnt; uint8_t byte_offset; if (!data || !len) return TEE_ERROR_BAD_PARAMETERS; blk_idx = addr / RPMB_DATA_SIZE; byte_offset = addr % RPMB_DATA_SIZE; if (len + byte_offset + RPMB_DATA_SIZE < RPMB_DATA_SIZE) { /* Overflow */ return TEE_ERROR_BAD_PARAMETERS; } blkcnt = ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE; res = tee_rpmb_init(dev_id); if (res != TEE_SUCCESS) goto func_exit; req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE; resp_size = RPMB_DATA_FRAME_SIZE * blkcnt; res = tee_rpmb_alloc(req_size, resp_size, &mem, (void *)&req, (void *)&resp); if (res != TEE_SUCCESS) goto func_exit; msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_READ; res = crypto_rng_read(nonce, RPMB_NONCE_SIZE); if (res != TEE_SUCCESS) goto func_exit; memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); rawdata.msg_type = msg_type; rawdata.nonce = nonce; rawdata.blk_idx = &blk_idx; res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL, NULL); if (res != TEE_SUCCESS) goto func_exit; req->block_count = blkcnt; DMSG("Read %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""), blk_idx); res = tee_rpmb_invoke(&mem); if (res != TEE_SUCCESS) goto func_exit; msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_READ; memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data)); rawdata.msg_type = msg_type; rawdata.block_count = &blkcnt; rawdata.blk_idx = &blk_idx; rawdata.nonce = nonce; rawdata.key_mac = hmac; rawdata.data = data; rawdata.len = len; rawdata.byte_offset = byte_offset; res = tee_rpmb_resp_unpack_verify(resp, &rawdata, blkcnt, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; res = TEE_SUCCESS; func_exit: tee_rpmb_free(&mem); return res; } static TEE_Result write_req(uint16_t dev_id, uint16_t blk_idx, const void *data_blks, uint16_t blkcnt, const uint8_t *fek, const TEE_UUID *uuid, struct tee_rpmb_mem *mem, void *req, void *resp) { TEE_Result res = TEE_SUCCESS; uint8_t hmac[RPMB_KEY_MAC_SIZE] = { }; uint32_t wr_cnt = rpmb_ctx->wr_cnt; struct rpmb_raw_data rawdata = { }; size_t retry_count = 0; assert(mem->req_size <= sizeof(struct rpmb_req) + blkcnt * RPMB_DATA_FRAME_SIZE); assert(mem->resp_size <= RPMB_DATA_FRAME_SIZE); while (true) { memset(req, 0, mem->req_size); memset(resp, 0, mem->resp_size); memset(&rawdata, 0, sizeof(struct rpmb_raw_data)); rawdata.msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE; rawdata.block_count = &blkcnt; rawdata.blk_idx = &blk_idx; rawdata.write_counter = &wr_cnt; rawdata.key_mac = hmac; rawdata.data = (uint8_t *)data_blks; res = tee_rpmb_req_pack(req, &rawdata, blkcnt, dev_id, fek, uuid); if (res) { /* * If we haven't tried to send a request yet we can * allow a failure here since there's no chance of * an intercepted request with a valid write * counter. */ if (!retry_count) return res; retry_count++; if (retry_count >= RPMB_MAX_RETRIES) goto out_of_retries; DMSG("Request pack failed, retrying %zu", retry_count); continue; } res = tee_rpmb_invoke(mem); if (res != TEE_SUCCESS) { retry_count++; if (retry_count >= RPMB_MAX_RETRIES) goto out_of_retries; /* * To force wr_cnt sync next time, as it might get * out of sync due to inconsistent operation result! */ rpmb_ctx->wr_cnt_synced = false; DMSG("Write invoke failed, retrying %zu", retry_count); continue; } memset(&rawdata, 0, sizeof(struct rpmb_raw_data)); rawdata.msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_WRITE; rawdata.block_count = &blkcnt; rawdata.blk_idx = &blk_idx; rawdata.write_counter = &wr_cnt; rawdata.key_mac = hmac; res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL, NULL); if (res != TEE_SUCCESS) { retry_count++; if (retry_count >= RPMB_MAX_RETRIES) goto out_of_retries; /* * To force wr_cnt sync next time, as it might get * out of sync due to inconsistent operation result! */ rpmb_ctx->wr_cnt_synced = false; DMSG("Write resp unpack verify failed, retrying %zu", retry_count); continue; } return TEE_SUCCESS; } out_of_retries: rpmb_dead = true; /* * We're using this error code to cause an eventuall calling TA to * panic since we don't know if the data to be written has been * committed to storage or not. */ return TEE_ERROR_COMMUNICATION; } static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx, const uint8_t *data_blks, uint16_t blkcnt, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res; struct tee_rpmb_mem mem; struct rpmb_req *req = NULL; struct rpmb_data_frame *resp = NULL; uint32_t req_size; uint32_t resp_size; uint32_t nbr_writes; uint16_t tmp_blkcnt; uint16_t tmp_blk_idx; uint16_t i; DMSG("Write %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""), blk_idx); if (!data_blks || !blkcnt) return TEE_ERROR_BAD_PARAMETERS; res = tee_rpmb_init(dev_id); if (res != TEE_SUCCESS) return res; /* * We need to split data when block count * is bigger than reliable block write count. */ if (blkcnt < rpmb_ctx->rel_wr_blkcnt) req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE * blkcnt; else req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE * rpmb_ctx->rel_wr_blkcnt; resp_size = RPMB_DATA_FRAME_SIZE; res = tee_rpmb_alloc(req_size, resp_size, &mem, (void *)&req, (void *)&resp); if (res != TEE_SUCCESS) return res; nbr_writes = blkcnt / rpmb_ctx->rel_wr_blkcnt; if (blkcnt % rpmb_ctx->rel_wr_blkcnt > 0) nbr_writes += 1; tmp_blkcnt = rpmb_ctx->rel_wr_blkcnt; tmp_blk_idx = blk_idx; for (i = 0; i < nbr_writes; i++) { size_t offs = i * rpmb_ctx->rel_wr_blkcnt * RPMB_DATA_SIZE; /* * To handle the last write of block count which is * equal or smaller than reliable write block count. */ if (i == nbr_writes - 1) tmp_blkcnt = blkcnt - rpmb_ctx->rel_wr_blkcnt * (nbr_writes - 1); res = write_req(dev_id, tmp_blk_idx, data_blks + offs, tmp_blkcnt, fek, uuid, &mem, req, resp); if (res) goto out; tmp_blk_idx += tmp_blkcnt; } out: tee_rpmb_free(&mem); return res; } static bool tee_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr, uint32_t len) { uint8_t byte_offset = addr % RPMB_DATA_SIZE; uint16_t blkcnt = ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE; return (blkcnt <= rpmb_ctx->rel_wr_blkcnt); } /* * Write RPMB data in bytes. * * @dev_id Device ID of the eMMC device. * @addr Byte address of data. * @data Pointer to the data. * @len Size of data in bytes. * @fek Encrypted File Encryption Key or NULL. */ static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr, const uint8_t *data, uint32_t len, const uint8_t *fek, const TEE_UUID *uuid) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *data_tmp = NULL; uint16_t blk_idx; uint16_t blkcnt; uint8_t byte_offset; blk_idx = addr / RPMB_DATA_SIZE; byte_offset = addr % RPMB_DATA_SIZE; blkcnt = ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE; if (byte_offset == 0 && (len % RPMB_DATA_SIZE) == 0) { res = tee_rpmb_write_blk(dev_id, blk_idx, data, blkcnt, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; } else { data_tmp = calloc(blkcnt, RPMB_DATA_SIZE); if (!data_tmp) { res = TEE_ERROR_OUT_OF_MEMORY; goto func_exit; } /* Read the complete blocks */ res = tee_rpmb_read(dev_id, blk_idx * RPMB_DATA_SIZE, data_tmp, blkcnt * RPMB_DATA_SIZE, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; /* Partial update of the data blocks */ memcpy(data_tmp + byte_offset, data, len); res = tee_rpmb_write_blk(dev_id, blk_idx, data_tmp, blkcnt, fek, uuid); if (res != TEE_SUCCESS) goto func_exit; } res = TEE_SUCCESS; func_exit: free(data_tmp); return res; } /* * Read the RPMB max block. * * @dev_id Device ID of the eMMC device. * @counter Pointer to receive the max block. */ static TEE_Result tee_rpmb_get_max_block(uint16_t dev_id, uint32_t *max_block) { TEE_Result res = TEE_SUCCESS; if (!max_block) return TEE_ERROR_BAD_PARAMETERS; if (rpmb_dead) return TEE_ERROR_COMMUNICATION; if (!rpmb_ctx || !rpmb_ctx->dev_info_synced) { res = tee_rpmb_init(dev_id); if (res != TEE_SUCCESS) goto func_exit; } *max_block = rpmb_ctx->max_blk_idx; func_exit: return res; } /* * End of lower interface to RPMB device */ static TEE_Result get_fat_start_address(uint32_t *addr); static TEE_Result rpmb_fs_setup(void); /** * fat_entry_dir_free: Free the FAT entry dir. */ static void fat_entry_dir_free(void) { if (fat_entry_dir) { free(fat_entry_dir->rpmb_fat_entry_buf); free(fat_entry_dir); fat_entry_dir = NULL; } } /** * fat_entry_dir_init: Initialize the FAT FS entry buffer/cache * This function must be called before reading FAT FS entries using the * function fat_entry_dir_get_next. This initializes the buffer/cache with the * first FAT FS entries. */ static TEE_Result fat_entry_dir_init(void) { TEE_Result res = TEE_ERROR_GENERIC; struct rpmb_fat_entry *fe = NULL; uint32_t fat_address = 0; uint32_t num_elems_read = 0; if (fat_entry_dir) return TEE_SUCCESS; res = rpmb_fs_setup(); if (res) return res; res = get_fat_start_address(&fat_address); if (res) return res; fat_entry_dir = calloc(1, sizeof(struct rpmb_fat_entry_dir)); if (!fat_entry_dir) return TEE_ERROR_OUT_OF_MEMORY; /* * If caching is enabled, read in up to the maximum cache size, but * never more than the single read in size. Otherwise, read in as many * entries fit into the temporary buffer. */ if (CFG_RPMB_FS_CACHE_ENTRIES) num_elems_read = MIN(CFG_RPMB_FS_CACHE_ENTRIES, CFG_RPMB_FS_RD_ENTRIES); else num_elems_read = CFG_RPMB_FS_RD_ENTRIES; /* * Allocate memory for the FAT FS entries to read in. */ fe = calloc(num_elems_read, sizeof(struct rpmb_fat_entry)); if (!fe) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, (uint8_t *)fe, num_elems_read * sizeof(*fe), NULL, NULL); if (res) goto out; fat_entry_dir->rpmb_fat_entry_buf = fe; /* * We use this variable when getting next entries from the buffer/cache * to see whether we have to read in more entries from storage. */ fat_entry_dir->num_buffered = num_elems_read; return TEE_SUCCESS; out: fat_entry_dir_free(); free(fe); return res; } /** * fat_entry_dir_deinit: If caching is enabled, free the temporary buffer for * FAT FS entries in case the cache was too small. Keep the elements in the * cache. Reset the counter variables to start the next traversal from fresh * from the first cached entry. If caching is disabled, just free the * temporary buffer by calling fat_entry_dir_free and return. */ static void fat_entry_dir_deinit(void) { struct rpmb_fat_entry *fe = NULL; if (!fat_entry_dir) return; if (!CFG_RPMB_FS_CACHE_ENTRIES) { fat_entry_dir_free(); return; } fe = fat_entry_dir->rpmb_fat_entry_buf; fat_entry_dir->idx_curr = 0; fat_entry_dir->num_total_read = 0; fat_entry_dir->last_reached = false; if (fat_entry_dir->num_buffered > CFG_RPMB_FS_CACHE_ENTRIES) { fat_entry_dir->num_buffered = CFG_RPMB_FS_CACHE_ENTRIES; fe = realloc(fe, fat_entry_dir->num_buffered * sizeof(*fe)); /* * In case realloc fails, we are on the safe side if we destroy * the whole structure. Upon the next init, the cache has to be * re-established, but this case should not happen in practice. */ if (!fe) fat_entry_dir_free(); else fat_entry_dir->rpmb_fat_entry_buf = fe; } } /** * fat_entry_dir_update: Updates a persisted FAT FS entry in the cache. * This function updates the FAT entry fat_entry that was written to address * fat_address onto RPMB storage in the cache. */ static TEE_Result __maybe_unused fat_entry_dir_update (struct rpmb_fat_entry *fat_entry, uint32_t fat_address) { uint32_t fat_entry_buf_idx = 0; /* Use a temp var to avoid compiler warning if caching disabled. */ uint32_t max_cache_entries = CFG_RPMB_FS_CACHE_ENTRIES; assert(!((fat_address - RPMB_FS_FAT_START_ADDRESS) % sizeof(struct rpmb_fat_entry))); /* Nothing to update if the cache is not initialized. */ if (!fat_entry_dir) return TEE_SUCCESS; fat_entry_buf_idx = (fat_address - RPMB_FS_FAT_START_ADDRESS) / sizeof(struct rpmb_fat_entry); /* Only need to write if index points to an entry in cache. */ if (fat_entry_buf_idx < fat_entry_dir->num_buffered && fat_entry_buf_idx < max_cache_entries) { memcpy(fat_entry_dir->rpmb_fat_entry_buf + fat_entry_buf_idx, fat_entry, sizeof(struct rpmb_fat_entry)); } return TEE_SUCCESS; } /** * fat_entry_dir_get_next: Get next FAT FS entry. * Read either from cache/buffer, or by reading from RPMB storage if the * elements in the buffer/cache are fully read. When reading in from RPMB * storage, the buffer is overwritten in case caching is disabled. * In case caching is enabled, the cache is either further filled, or a * temporary buffer populated if the cache is already full. * The FAT FS entry is written to fat_entry. The respective address in RPMB * storage is written to fat_address, if not NULL. When the last FAT FS entry * was previously read, the function indicates this case by writing a NULL * pointer to fat_entry. * Returns a value different TEE_SUCCESS if the next FAT FS entry could not be * retrieved. */ static TEE_Result fat_entry_dir_get_next(struct rpmb_fat_entry **fat_entry, uint32_t *fat_address) { TEE_Result res = TEE_ERROR_GENERIC; struct rpmb_fat_entry *fe = NULL; uint32_t num_elems_read = 0; uint32_t fat_address_local = 0; assert(fat_entry_dir && fat_entry); /* Don't read further if we previously read the last FAT FS entry. */ if (fat_entry_dir->last_reached) { *fat_entry = NULL; return TEE_SUCCESS; } fe = fat_entry_dir->rpmb_fat_entry_buf; /* Determine address of FAT FS entry in RPMB storage. */ fat_address_local = RPMB_FS_FAT_START_ADDRESS + (fat_entry_dir->num_total_read * sizeof(struct rpmb_fat_entry)); /* * We've read all so-far buffered elements, so we need to * read in more entries from RPMB storage. */ if (fat_entry_dir->idx_curr >= fat_entry_dir->num_buffered) { /* * This is the case where we do not cache entries, so just read * in next set of FAT FS entries into the buffer. * Goto the end of the when statement if that is done. */ if (!CFG_RPMB_FS_CACHE_ENTRIES) { num_elems_read = CFG_RPMB_FS_RD_ENTRIES; fat_entry_dir->idx_curr = 0; res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address_local, (uint8_t *)fe, num_elems_read * sizeof(*fe), NULL, NULL); if (res) return res; goto post_read_in; } /* * We cache FAT FS entries, and the buffer is not completely * filled. Further keep on extending the buffer up to its max * size by reading in from RPMB. */ if (fat_entry_dir->num_total_read < RPMB_BUF_MAX_ENTRIES) { /* * Read at most as many elements as fit in the buffer * and no more than the defined number of entries to * read in at once. */ num_elems_read = MIN(RPMB_BUF_MAX_ENTRIES - fat_entry_dir->num_total_read, (uint32_t)CFG_RPMB_FS_RD_ENTRIES); /* * Expand the buffer to fit in the additional entries. */ fe = realloc(fe, (fat_entry_dir->num_buffered + num_elems_read) * sizeof(*fe)); if (!fe) return TEE_ERROR_OUT_OF_MEMORY; fat_entry_dir->rpmb_fat_entry_buf = fe; /* Read in to the next free slot in the buffer/cache. */ res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address_local, (uint8_t *)(fe + fat_entry_dir->num_total_read), num_elems_read * sizeof(*fe), NULL, NULL); if (res) return res; fat_entry_dir->num_buffered += num_elems_read; } else { /* * This happens when we have read as many elements as * can possibly fit into the buffer. * As the first part of the buffer serves as our cache, * we only overwrite the last part that serves as our * temporary buffer used to iteratively read in entries * when the cache is full. Read in the temporary buffer * maximum size. */ num_elems_read = CFG_RPMB_FS_RD_ENTRIES; /* Reset index to beginning of the temporary buffer. */ fat_entry_dir->idx_curr = CFG_RPMB_FS_CACHE_ENTRIES; /* Read in elements after the end of the cache. */ res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address_local, (uint8_t *)(fe + fat_entry_dir->idx_curr), num_elems_read * sizeof(*fe), NULL, NULL); if (res) return res; } } post_read_in: if (fat_address) *fat_address = fat_address_local; *fat_entry = fe + fat_entry_dir->idx_curr; fat_entry_dir->idx_curr++; fat_entry_dir->num_total_read++; /* * Indicate last entry was read. * Ensures we return a zero value for fat_entry on next invocation. */ if ((*fat_entry)->flags & FILE_IS_LAST_ENTRY) fat_entry_dir->last_reached = true; return TEE_SUCCESS; } #if (TRACE_LEVEL >= TRACE_FLOW) static void dump_fat(void) { TEE_Result res = TEE_ERROR_SECURITY; struct rpmb_fat_entry *fe = NULL; if (!fs_par) return; if (fat_entry_dir_init()) return; while (true) { res = fat_entry_dir_get_next(&fe, NULL); if (res || !fe) break; FMSG("flags %#"PRIx32", size %"PRIu32", address %#"PRIx32 ", filename '%s'", fe->flags, fe->data_size, fe->start_address, fe->filename); } fat_entry_dir_deinit(); } #else static void dump_fat(void) { } #endif #if (TRACE_LEVEL >= TRACE_DEBUG) static void dump_fh(struct rpmb_file_handle *fh) { DMSG("fh->filename=%s", fh->filename); DMSG("fh->rpmb_fat_address=%u", fh->rpmb_fat_address); DMSG("fh->fat_entry.start_address=%u", fh->fat_entry.start_address); DMSG("fh->fat_entry.data_size=%u", fh->fat_entry.data_size); } #else static void dump_fh(struct rpmb_file_handle *fh __unused) { } #endif /* "/TA_uuid/object_id" or "/TA_uuid/.object_id" */ static TEE_Result create_filename(void *buf, size_t blen, struct tee_pobj *po, bool transient) { uint8_t *file = buf; uint32_t pos = 0; uint32_t hslen = 1 /* Leading slash */ + TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + po->obj_id_len) + 1; /* Intermediate slash */ /* +1 for the '.' (temporary persistent object) */ if (transient) hslen++; if (blen < hslen) return TEE_ERROR_SHORT_BUFFER; file[pos++] = '/'; pos += tee_b2hs((uint8_t *)&po->uuid, &file[pos], sizeof(TEE_UUID), hslen); file[pos++] = '/'; if (transient) file[pos++] = '.'; tee_b2hs(po->obj_id, file + pos, po->obj_id_len, hslen - pos); return TEE_SUCCESS; } /* "/TA_uuid" */ static TEE_Result create_dirname(void *buf, size_t blen, const TEE_UUID *uuid) { uint8_t *dir = buf; uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID)) + 1; if (blen < hslen) return TEE_ERROR_SHORT_BUFFER; dir[0] = '/'; tee_b2hs((uint8_t *)uuid, dir + 1, sizeof(TEE_UUID), hslen); return TEE_SUCCESS; } static struct rpmb_file_handle *alloc_file_handle(struct tee_pobj *po, bool temporary) { struct rpmb_file_handle *fh = NULL; fh = calloc(1, sizeof(struct rpmb_file_handle)); if (!fh) return NULL; if (po) create_filename(fh->filename, sizeof(fh->filename), po, temporary); return fh; } /** * write_fat_entry: Store info in a fat_entry to RPMB. */ static TEE_Result write_fat_entry(struct rpmb_file_handle *fh) { TEE_Result res = TEE_ERROR_GENERIC; /* Protect partition data. */ if (fh->rpmb_fat_address < sizeof(struct rpmb_fs_partition)) { res = TEE_ERROR_ACCESS_CONFLICT; goto out; } if (fh->rpmb_fat_address % sizeof(struct rpmb_fat_entry) != 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, fh->rpmb_fat_address, (uint8_t *)&fh->fat_entry, sizeof(struct rpmb_fat_entry), NULL, NULL); dump_fat(); /* If caching enabled, update a successfully written entry in cache. */ if (CFG_RPMB_FS_CACHE_ENTRIES && !res) res = fat_entry_dir_update(&fh->fat_entry, fh->rpmb_fat_address); out: return res; } /** * rpmb_fs_setup: Setup RPMB FS. * Set initial partition and FS values and write to RPMB. * Store frequently used data in RAM. */ static TEE_Result rpmb_fs_setup(void) { TEE_Result res = TEE_ERROR_GENERIC; struct rpmb_fs_partition *partition_data = NULL; struct rpmb_file_handle *fh = NULL; uint32_t max_rpmb_block = 0; if (fs_par) { res = TEE_SUCCESS; goto out; } res = tee_rpmb_get_max_block(CFG_RPMB_FS_DEV_ID, &max_rpmb_block); if (res != TEE_SUCCESS) goto out; /* * We're going to read a full block in order to have a full block * for the dummy write below. */ COMPILE_TIME_ASSERT(sizeof(struct rpmb_fs_partition) <= RPMB_DATA_SIZE); partition_data = calloc(1, RPMB_DATA_SIZE); if (!partition_data) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, RPMB_DATA_SIZE, NULL, NULL); if (res != TEE_SUCCESS) goto out; /* * Perform a write in order to increase the write counter. This * prevents late usage (replay attack) of a previously blocked * request with a valid write counter value. */ res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, RPMB_DATA_SIZE, NULL, NULL); if (res != TEE_SUCCESS) goto out; /* * We're reading again in case a stale request was committed * instead of the one issued above. If this succeeds we're in sync * with the RPMB block since there are no other possible stale * blocks with valid write counters available. */ res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, sizeof(struct rpmb_fs_partition), NULL, NULL); if (res != TEE_SUCCESS) goto out; #ifndef CFG_RPMB_RESET_FAT if (partition_data->rpmb_fs_magic == RPMB_FS_MAGIC) { if (partition_data->fs_version == FS_VERSION) { res = TEE_SUCCESS; goto store_fs_par; } else { EMSG("Wrong software is in use."); res = TEE_ERROR_ACCESS_DENIED; goto out; } } #else EMSG("**** Clearing Storage ****"); #endif /* Setup new partition data. */ partition_data->rpmb_fs_magic = RPMB_FS_MAGIC; partition_data->fs_version = FS_VERSION; partition_data->fat_start_address = RPMB_FS_FAT_START_ADDRESS; /* Initial FAT entry with FILE_IS_LAST_ENTRY flag set. */ fh = alloc_file_handle(NULL, false); if (!fh) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } fh->fat_entry.flags = FILE_IS_LAST_ENTRY; fh->rpmb_fat_address = partition_data->fat_start_address; /* Write init FAT entry and partition data to RPMB. */ res = write_fat_entry(fh); if (res != TEE_SUCCESS) goto out; res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS, (uint8_t *)partition_data, sizeof(struct rpmb_fs_partition), NULL, NULL); #ifndef CFG_RPMB_RESET_FAT store_fs_par: #endif /* Store FAT start address. */ fs_par = calloc(1, sizeof(struct rpmb_fs_parameters)); if (!fs_par) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } fs_par->fat_start_address = partition_data->fat_start_address; fs_par->max_rpmb_address = max_rpmb_block << RPMB_BLOCK_SIZE_SHIFT; dump_fat(); out: free(fh); free(partition_data); return res; } /** * get_fat_start_address: * FAT start_address from fs_par. */ static TEE_Result get_fat_start_address(uint32_t *addr) { if (!fs_par) return TEE_ERROR_NO_DATA; *addr = fs_par->fat_start_address; return TEE_SUCCESS; } /** * read_fat: Read FAT entries * Return matching FAT entry for read, rm rename and stat. * Build up memory pool and return matching entry for write operation. * "Last FAT entry" can be returned during write. */ static TEE_Result read_fat(struct rpmb_file_handle *fh, tee_mm_pool_t *p) { TEE_Result res = TEE_ERROR_GENERIC; tee_mm_entry_t *mm = NULL; struct rpmb_fat_entry *fe = NULL; uint32_t fat_address; bool entry_found = false; bool expand_fat = false; struct rpmb_file_handle last_fh; DMSG("fat_address %d", fh->rpmb_fat_address); res = fat_entry_dir_init(); if (res) goto out; /* * The pool is used to represent the current RPMB layout. To find * a slot for the file tee_mm_alloc is called on the pool. Thus * if it is not NULL the entire FAT must be traversed to fill in * the pool. */ while (true) { res = fat_entry_dir_get_next(&fe, &fat_address); if (res || !fe) break; /* * Look for an entry, matching filenames. (read, rm, * rename and stat.). Only store first filename match. */ if ((!strcmp(fh->filename, fe->filename)) && (fe->flags & FILE_IS_ACTIVE) && !entry_found) { entry_found = true; fh->rpmb_fat_address = fat_address; memcpy(&fh->fat_entry, fe, sizeof(*fe)); if (!p) break; } /* Add existing files to memory pool. (write) */ if (p) { if ((fe->flags & FILE_IS_ACTIVE) && fe->data_size > 0) { mm = tee_mm_alloc2(p, fe->start_address, fe->data_size); if (!mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } } /* Unused FAT entries can be reused (write) */ if (((fe->flags & FILE_IS_ACTIVE) == 0) && fh->rpmb_fat_address == 0) { fh->rpmb_fat_address = fat_address; memcpy(&fh->fat_entry, fe, sizeof(struct rpmb_fat_entry)); } if (((fe->flags & FILE_IS_LAST_ENTRY) != 0) && fh->rpmb_fat_address == fat_address) { /* * If the last entry was reached and was chosen * by the previous check, then the FAT needs to * be expanded. * fh->rpmb_fat_address is the address chosen * to store the files FAT entry and fat_address * is the current FAT entry address being * compared. */ expand_fat = true; } } } if (res) goto out; /* * Represent the FAT table in the pool. */ if (p) { /* * Since fat_address is the start of the last entry it needs to * be moved up by an entry. */ fat_address += sizeof(struct rpmb_fat_entry); /* Make room for yet a FAT entry and add to memory pool. */ if (expand_fat) fat_address += sizeof(struct rpmb_fat_entry); mm = tee_mm_alloc2(p, RPMB_STORAGE_START_ADDRESS, fat_address); if (!mm) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } if (expand_fat) { /* * Point fat_address to the beginning of the new * entry. */ fat_address -= sizeof(struct rpmb_fat_entry); memset(&last_fh, 0, sizeof(last_fh)); last_fh.fat_entry.flags = FILE_IS_LAST_ENTRY; last_fh.rpmb_fat_address = fat_address; res = write_fat_entry(&last_fh); if (res != TEE_SUCCESS) goto out; } } if (!fh->rpmb_fat_address) res = TEE_ERROR_ITEM_NOT_FOUND; out: fat_entry_dir_deinit(); return res; } static TEE_Result generate_fek(struct rpmb_fat_entry *fe, const TEE_UUID *uuid) { TEE_Result res; again: res = tee_fs_generate_fek(uuid, fe->fek, sizeof(fe->fek)); if (res != TEE_SUCCESS) return res; if (is_zero(fe->fek, sizeof(fe->fek))) goto again; return res; } static TEE_Result rpmb_fs_open_internal(struct rpmb_file_handle *fh, const TEE_UUID *uuid, bool create) { tee_mm_pool_t p; bool pool_result; paddr_size_t pool_sz = 0; TEE_Result res = TEE_ERROR_GENERIC; /* We need to do setup in order to make sure fs_par is filled in */ res = rpmb_fs_setup(); if (res != TEE_SUCCESS) goto out; fh->uuid = uuid; if (create) { /* Upper memory allocation must be used for RPMB_FS. */ pool_sz = fs_par->max_rpmb_address - RPMB_STORAGE_START_ADDRESS; pool_result = tee_mm_init(&p, RPMB_STORAGE_START_ADDRESS, pool_sz, RPMB_BLOCK_SIZE_SHIFT, TEE_MM_POOL_HI_ALLOC); if (!pool_result) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = read_fat(fh, &p); tee_mm_final(&p); if (res != TEE_SUCCESS) goto out; } else { res = read_fat(fh, NULL); if (res != TEE_SUCCESS) goto out; } /* * If this is opened with create and the entry found was not active * then this is a new file and the FAT entry must be written */ if (create) { if ((fh->fat_entry.flags & FILE_IS_ACTIVE) == 0) { memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry)); memcpy(fh->fat_entry.filename, fh->filename, strlen(fh->filename)); /* Start address and size are 0 */ fh->fat_entry.flags = FILE_IS_ACTIVE; res = generate_fek(&fh->fat_entry, uuid); if (res != TEE_SUCCESS) goto out; DMSG("GENERATE FEK key: %p", (void *)fh->fat_entry.fek); DHEXDUMP(fh->fat_entry.fek, sizeof(fh->fat_entry.fek)); res = write_fat_entry(fh); if (res != TEE_SUCCESS) goto out; } } res = TEE_SUCCESS; out: return res; } static void rpmb_fs_close(struct tee_file_handle **tfh) { struct rpmb_file_handle *fh = (struct rpmb_file_handle *)*tfh; free(fh); *tfh = NULL; } static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, size_t pos, void *buf_core, void *buf_user, size_t *len) { TEE_Result res; struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh; size_t size = *len; /* One of buf_core and buf_user must be NULL */ assert(!buf_core || !buf_user); if (!size) return TEE_SUCCESS; mutex_lock(&rpmb_mutex); dump_fh(fh); res = read_fat(fh, NULL); if (res != TEE_SUCCESS) goto out; if (pos >= fh->fat_entry.data_size) { *len = 0; goto out; } size = MIN(size, fh->fat_entry.data_size - pos); if (size) { if (buf_core) { res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fh->fat_entry.start_address + pos, buf_core, size, fh->fat_entry.fek, fh->uuid); if (res != TEE_SUCCESS) goto out; } else if (buf_user) { uint32_t f = TEE_MEMORY_ACCESS_WRITE; res = check_user_access(f, buf_user, size); if (res) goto out; enter_user_access(); res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fh->fat_entry.start_address + pos, buf_user, size, fh->fat_entry.fek, fh->uuid); exit_user_access(); if (res) goto out; } } *len = size; out: mutex_unlock(&rpmb_mutex); return res; } static TEE_Result update_write_helper(struct rpmb_file_handle *fh, size_t pos, const void *buf, size_t size, uintptr_t new_fat, size_t new_size) { uintptr_t old_fat = fh->fat_entry.start_address; size_t old_size = fh->fat_entry.data_size; const uint8_t *rem_buf = buf; size_t rem_size = size; uint8_t *blk_buf = NULL; size_t blk_offset = 0; size_t blk_size = 0; TEE_Result res = TEE_SUCCESS; blk_buf = mempool_alloc(mempool_default, TMP_BLOCK_SIZE); if (!blk_buf) return TEE_ERROR_OUT_OF_MEMORY; while (blk_offset < new_size) { uint8_t *copy_dst = blk_buf; size_t copy_size = 0; size_t rd_size = 0; blk_size = MIN(TMP_BLOCK_SIZE, new_size - blk_offset); memset(blk_buf, 0, blk_size); /* Possibly read old RPMB data in temporary buffer */ if (blk_offset < pos && blk_offset < old_size) { rd_size = MIN(blk_size, old_size - blk_offset); res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, old_fat + blk_offset, blk_buf, rd_size, fh->fat_entry.fek, fh->uuid); if (res != TEE_SUCCESS) break; } /* Possibly update data in temporary buffer */ if ((blk_offset + TMP_BLOCK_SIZE > pos) && (blk_offset < pos + size)) { size_t offset = 0; copy_dst = blk_buf; copy_size = TMP_BLOCK_SIZE; if (blk_offset < pos) { offset = pos - blk_offset; copy_dst += offset; copy_size -= offset; } copy_size = MIN(copy_size, rem_size); memcpy(copy_dst, rem_buf, copy_size); rem_buf += copy_size; rem_size -= copy_size; } /* Write temporary buffer to new RPMB destination */ res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, new_fat + blk_offset, blk_buf, blk_size, fh->fat_entry.fek, fh->uuid); if (res != TEE_SUCCESS) break; blk_offset += blk_size; } mempool_free(mempool_default, blk_buf); return res; } static TEE_Result rpmb_fs_write_primitive(struct rpmb_file_handle *fh, size_t pos, const void *buf, size_t size) { TEE_Result res = TEE_ERROR_GENERIC; tee_mm_pool_t p = { }; bool pool_result = false; size_t end = 0; uint32_t start_addr = 0; paddr_size_t pool_sz = 0; if (!size) return TEE_SUCCESS; if (!fs_par) { res = TEE_ERROR_GENERIC; goto out; } dump_fh(fh); /* Upper memory allocation must be used for RPMB_FS. */ pool_sz = fs_par->max_rpmb_address - RPMB_STORAGE_START_ADDRESS; pool_result = tee_mm_init(&p, RPMB_STORAGE_START_ADDRESS, pool_sz, RPMB_BLOCK_SIZE_SHIFT, TEE_MM_POOL_HI_ALLOC); if (!pool_result) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = read_fat(fh, &p); if (res != TEE_SUCCESS) goto out; if (fh->fat_entry.flags & FILE_IS_LAST_ENTRY) panic("invalid last entry flag"); if (ADD_OVERFLOW(pos, size, &end)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (ADD_OVERFLOW(fh->fat_entry.start_address, pos, &start_addr)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (end <= fh->fat_entry.data_size && tee_rpmb_write_is_atomic(CFG_RPMB_FS_DEV_ID, start_addr, size)) { DMSG("Updating data in-place"); res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, start_addr, buf, size, fh->fat_entry.fek, fh->uuid); } else { /* * File must be extended, or update cannot be atomic: allocate, * read, update, write. */ size_t new_size = MAX(end, fh->fat_entry.data_size); tee_mm_entry_t *mm = tee_mm_alloc(&p, new_size); uintptr_t new_fat_entry = 0; DMSG("Need to re-allocate"); if (!mm) { DMSG("RPMB: No space left"); res = TEE_ERROR_STORAGE_NO_SPACE; goto out; } new_fat_entry = tee_mm_get_smem(mm); res = update_write_helper(fh, pos, buf, size, new_fat_entry, new_size); if (res == TEE_SUCCESS) { fh->fat_entry.data_size = new_size; fh->fat_entry.start_address = new_fat_entry; res = write_fat_entry(fh); } } out: if (pool_result) tee_mm_final(&p); return res; } static TEE_Result rpmb_fs_write(struct tee_file_handle *tfh, size_t pos, const void *buf_core, const void *buf_user, size_t size) { TEE_Result res = TEE_SUCCESS; /* One of buf_core and buf_user must be NULL */ assert(!buf_core || !buf_user); if (!size) return TEE_SUCCESS; mutex_lock(&rpmb_mutex); if (buf_core) { res = rpmb_fs_write_primitive((struct rpmb_file_handle *)tfh, pos, buf_core, size); } else if (buf_user) { uint32_t f = TEE_MEMORY_ACCESS_READ; res = check_user_access(f, buf_user, size); if (res) goto out; enter_user_access(); res = rpmb_fs_write_primitive((struct rpmb_file_handle *)tfh, pos, buf_user, size); exit_user_access(); } out: mutex_unlock(&rpmb_mutex); return res; } static TEE_Result rpmb_fs_remove_internal(struct rpmb_file_handle *fh) { TEE_Result res; res = read_fat(fh, NULL); if (res) return res; /* Clear this file entry. */ memset(&fh->fat_entry, 0, sizeof(struct rpmb_fat_entry)); return write_fat_entry(fh); } static TEE_Result rpmb_fs_remove(struct tee_pobj *po) { TEE_Result res; struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); if (!fh) return TEE_ERROR_OUT_OF_MEMORY; mutex_lock(&rpmb_mutex); res = rpmb_fs_remove_internal(fh); mutex_unlock(&rpmb_mutex); free(fh); return res; } static TEE_Result rpmb_fs_rename_internal(struct tee_pobj *old, struct tee_pobj *new, bool overwrite) { TEE_Result res = TEE_ERROR_GENERIC; struct rpmb_file_handle *fh_old = NULL; struct rpmb_file_handle *fh_new = NULL; if (!old) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (new) fh_old = alloc_file_handle(old, old->temporary); else fh_old = alloc_file_handle(old, true); if (!fh_old) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } if (new) fh_new = alloc_file_handle(new, new->temporary); else fh_new = alloc_file_handle(old, false); if (!fh_new) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = read_fat(fh_old, NULL); if (res != TEE_SUCCESS) goto out; res = read_fat(fh_new, NULL); if (res == TEE_SUCCESS) { if (!overwrite) { res = TEE_ERROR_ACCESS_CONFLICT; goto out; } /* Clear this file entry. */ memset(&fh_new->fat_entry, 0, sizeof(struct rpmb_fat_entry)); res = write_fat_entry(fh_new); if (res != TEE_SUCCESS) goto out; } memset(fh_old->fat_entry.filename, 0, TEE_RPMB_FS_FILENAME_LENGTH); memcpy(fh_old->fat_entry.filename, fh_new->filename, strlen(fh_new->filename)); res = write_fat_entry(fh_old); out: free(fh_old); free(fh_new); return res; } static TEE_Result rpmb_fs_rename(struct tee_pobj *old, struct tee_pobj *new, bool overwrite) { TEE_Result res; mutex_lock(&rpmb_mutex); res = rpmb_fs_rename_internal(old, new, overwrite); mutex_unlock(&rpmb_mutex); return res; } static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length) { struct rpmb_file_handle *fh = (struct rpmb_file_handle *)tfh; tee_mm_pool_t p; bool pool_result = false; tee_mm_entry_t *mm; uint32_t newsize; uint8_t *newbuf = NULL; uintptr_t newaddr; TEE_Result res = TEE_ERROR_GENERIC; paddr_size_t pool_sz = 0; mutex_lock(&rpmb_mutex); if (length > INT32_MAX) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } newsize = length; res = read_fat(fh, NULL); if (res != TEE_SUCCESS) goto out; if (newsize > fh->fat_entry.data_size) { /* Extend file */ pool_sz = fs_par->max_rpmb_address - RPMB_STORAGE_START_ADDRESS; pool_result = tee_mm_init(&p, RPMB_STORAGE_START_ADDRESS, pool_sz, RPMB_BLOCK_SIZE_SHIFT, TEE_MM_POOL_HI_ALLOC); if (!pool_result) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = read_fat(fh, &p); if (res != TEE_SUCCESS) goto out; mm = tee_mm_alloc(&p, newsize); newbuf = calloc(1, newsize); if (!mm || !newbuf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } if (fh->fat_entry.data_size) { res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fh->fat_entry.start_address, newbuf, fh->fat_entry.data_size, fh->fat_entry.fek, fh->uuid); if (res != TEE_SUCCESS) goto out; } newaddr = tee_mm_get_smem(mm); res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, newaddr, newbuf, newsize, fh->fat_entry.fek, fh->uuid); if (res != TEE_SUCCESS) goto out; } else { /* Don't change file location */ newaddr = fh->fat_entry.start_address; } /* fh->pos is unchanged */ fh->fat_entry.data_size = newsize; fh->fat_entry.start_address = newaddr; res = write_fat_entry(fh); out: mutex_unlock(&rpmb_mutex); if (pool_result) tee_mm_final(&p); if (newbuf) free(newbuf); return res; } static void rpmb_fs_dir_free(struct tee_fs_dir *dir) { struct tee_rpmb_fs_dirent *e; if (!dir) return; free(dir->current); while ((e = SIMPLEQ_FIRST(&dir->next))) { SIMPLEQ_REMOVE_HEAD(&dir->next, link); free(e); } } static TEE_Result rpmb_fs_dir_populate(const char *path, struct tee_fs_dir *dir) { struct tee_rpmb_fs_dirent *current = NULL; struct rpmb_fat_entry *fe = NULL; uint32_t fat_address; uint32_t filelen; char *filename; bool matched; struct tee_rpmb_fs_dirent *next = NULL; uint32_t pathlen; TEE_Result res = TEE_ERROR_GENERIC; char temp; mutex_lock(&rpmb_mutex); res = fat_entry_dir_init(); if (res) goto out; pathlen = strlen(path); while (true) { res = fat_entry_dir_get_next(&fe, &fat_address); if (res || !fe) break; filename = fe->filename; if (fe->flags & FILE_IS_ACTIVE) { matched = false; filelen = strlen(filename); if (filelen > pathlen) { temp = filename[pathlen]; filename[pathlen] = '\0'; if (strcmp(filename, path) == 0) matched = true; filename[pathlen] = temp; } if (matched) { next = malloc(sizeof(*next)); if (!next) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } next->entry.oidlen = tee_hs2b((uint8_t *) &filename[pathlen], next->entry.oid, filelen - pathlen, sizeof(next->entry.oid)); if (next->entry.oidlen) { SIMPLEQ_INSERT_TAIL(&dir->next, next, link); current = next; } else { free(next); next = NULL; } } } } if (res) goto out; if (current) res = TEE_SUCCESS; else res = TEE_ERROR_ITEM_NOT_FOUND; /* No directories were found. */ out: mutex_unlock(&rpmb_mutex); fat_entry_dir_deinit(); if (res) rpmb_fs_dir_free(dir); return res; } static TEE_Result rpmb_fs_opendir(const TEE_UUID *uuid, struct tee_fs_dir **dir) { uint32_t len; char path_local[TEE_RPMB_FS_FILENAME_LENGTH]; TEE_Result res = TEE_ERROR_GENERIC; struct tee_fs_dir *rpmb_dir = NULL; if (!uuid || !dir) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } memset(path_local, 0, sizeof(path_local)); if (create_dirname(path_local, sizeof(path_local) - 1, uuid)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } len = strlen(path_local); /* Add a slash to correctly match the full directory name. */ if (path_local[len - 1] != '/') path_local[len] = '/'; rpmb_dir = calloc(1, sizeof(*rpmb_dir)); if (!rpmb_dir) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } SIMPLEQ_INIT(&rpmb_dir->next); res = rpmb_fs_dir_populate(path_local, rpmb_dir); if (res != TEE_SUCCESS) { free(rpmb_dir); rpmb_dir = NULL; goto out; } *dir = rpmb_dir; out: return res; } static TEE_Result rpmb_fs_readdir(struct tee_fs_dir *dir, struct tee_fs_dirent **ent) { if (!dir) return TEE_ERROR_GENERIC; free(dir->current); dir->current = SIMPLEQ_FIRST(&dir->next); if (!dir->current) return TEE_ERROR_ITEM_NOT_FOUND; SIMPLEQ_REMOVE_HEAD(&dir->next, link); *ent = &dir->current->entry; return TEE_SUCCESS; } static void rpmb_fs_closedir(struct tee_fs_dir *dir) { if (dir) { rpmb_fs_dir_free(dir); free(dir); } } static TEE_Result rpmb_fs_open(struct tee_pobj *po, size_t *size, struct tee_file_handle **ret_fh) { TEE_Result res; struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); if (!fh) return TEE_ERROR_OUT_OF_MEMORY; mutex_lock(&rpmb_mutex); res = rpmb_fs_open_internal(fh, &po->uuid, false); if (!res && size) *size = fh->fat_entry.data_size; mutex_unlock(&rpmb_mutex); if (res) free(fh); else *ret_fh = (struct tee_file_handle *)fh; return res; } static TEE_Result rpmb_fs_create(struct tee_pobj *po, bool overwrite, const void *head, size_t head_size, const void *attr, size_t attr_size, const void *data_core, const void *data_user, size_t data_size, struct tee_file_handle **ret_fh) { TEE_Result res; size_t pos = 0; struct rpmb_file_handle *fh = alloc_file_handle(po, po->temporary); /* One of data_core and data_user must be NULL */ assert(!data_core || !data_user); if (!fh) return TEE_ERROR_OUT_OF_MEMORY; mutex_lock(&rpmb_mutex); res = rpmb_fs_open_internal(fh, &po->uuid, true); if (res) goto out; if (head && head_size) { res = rpmb_fs_write_primitive(fh, pos, head, head_size); if (res) goto out; pos += head_size; } if (attr && attr_size) { res = rpmb_fs_write_primitive(fh, pos, attr, attr_size); if (res) goto out; pos += attr_size; } if (data_size) { if (data_core) { res = rpmb_fs_write_primitive(fh, pos, data_core, data_size); if (res) goto out; } else if (data_user) { uint32_t f = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; res = check_user_access(f, data_user, data_size); if (res) goto out; enter_user_access(); res = rpmb_fs_write_primitive(fh, pos, data_user, data_size); exit_user_access(); if (res) goto out; } } if (po->temporary) { /* * If it's a temporary filename (which it normally is) * rename into the final filename now that the file is * fully initialized. */ po->temporary = false; res = rpmb_fs_rename_internal(po, NULL, overwrite); if (res) { po->temporary = true; goto out; } /* Update file handle after rename. */ create_filename(fh->filename, sizeof(fh->filename), po, false); } out: if (res) { rpmb_fs_remove_internal(fh); free(fh); } else { *ret_fh = (struct tee_file_handle *)fh; } mutex_unlock(&rpmb_mutex); return res; } const struct tee_file_operations rpmb_fs_ops = { .open = rpmb_fs_open, .create = rpmb_fs_create, .close = rpmb_fs_close, .read = rpmb_fs_read, .write = rpmb_fs_write, .truncate = rpmb_fs_truncate, .rename = rpmb_fs_rename, .remove = rpmb_fs_remove, .opendir = rpmb_fs_opendir, .closedir = rpmb_fs_closedir, .readdir = rpmb_fs_readdir, }; TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create, struct tee_file_handle **ret_fh) { TEE_Result res; struct rpmb_file_handle *fh = calloc(1, sizeof(*fh)); static const TEE_UUID uuid = { 0 }; if (!fh) return TEE_ERROR_OUT_OF_MEMORY; snprintf(fh->filename, sizeof(fh->filename), "/%s", fname); mutex_lock(&rpmb_mutex); res = rpmb_fs_open_internal(fh, &uuid, create); mutex_unlock(&rpmb_mutex); if (res) { if (create) rpmb_fs_remove_internal(fh); free(fh); } else { *ret_fh = (struct tee_file_handle *)fh; } return res; } bool __weak plat_rpmb_key_is_ready(void) { return true; } optee_os-4.3.0/core/tee/tee_supp_plugin_rpc.c000066400000000000000000000043701464416617300212720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Open Mobile Platform LLC */ #include #include #include #include #include #include #include #include #include #include #include #include TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, uint32_t sub_cmd, void *buf_core, void *buf_user, size_t len, size_t *outlen) { TEE_Result res = TEE_ERROR_GENERIC; struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS]; uint32_t uuid_words[4] = { }; void *va = NULL; struct mobj *mobj = NULL; /* * sizeof 'TEE_UUID' and array 'uuid_words' must be same size, * because 'tee_uuid_to_octets()' is used to copy variable * with one type to another. * * Array 'uuid_words' is used just for convenient work with * 'TEE_UUID' as with uint32_t values. */ COMPILE_TIME_ASSERT(sizeof(TEE_UUID) == sizeof(uuid_words)); if (!uuid || (len && !buf_core && !buf_user) || (!len && (buf_core || buf_user)) || (buf_core && buf_user)) return TEE_ERROR_BAD_PARAMETERS; if (len) { mobj = thread_rpc_alloc_payload(len); if (!mobj) { EMSG("can't create mobj for plugin data"); return TEE_ERROR_OUT_OF_MEMORY; } va = mobj_get_va(mobj, 0, len); if (!va) { EMSG("can't get va from mobj"); goto out; } if (buf_core) memcpy(va, buf_core, len); if (buf_user) { res = copy_from_user(va, buf_user, len); if (res) goto out; } } tee_uuid_to_octets((uint8_t *)uuid_words, uuid); params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SUPP_PLUGIN_INVOKE, uuid_words[0], uuid_words[1]); params[1] = THREAD_PARAM_VALUE(IN, uuid_words[2], uuid_words[3], cmd); params[2] = THREAD_PARAM_VALUE(INOUT, sub_cmd, 0, 0); params[3] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, len); res = thread_rpc_cmd(OPTEE_RPC_CMD_SUPP_PLUGIN, 4, params); if (outlen) *outlen = params[2].u.value.b; if (len && outlen && *outlen) { if (buf_core) memcpy(buf_core, va, *outlen <= len ? *outlen : len); if (buf_user) res = copy_to_user(buf_user, va, len); } out: if (len) thread_rpc_free_payload(mobj); return res; } optee_os-4.3.0/core/tee/tee_svc.c000066400000000000000000000627151464416617300166630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020-2022 Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include vaddr_t tee_svc_uref_base; void syscall_log(const void *buf, size_t len) { if (IS_ENABLED(CFG_TEE_CORE_TA_TRACE)) { char *kbuf = NULL; size_t sz = 0; if (!len || ADD_OVERFLOW(len, 1, &sz)) return; kbuf = malloc(sz); if (!kbuf) return; if (copy_from_user(kbuf, buf, len) == TEE_SUCCESS) { kbuf[len] = '\0'; trace_ext_puts(kbuf); } free_wipe(kbuf); } } TEE_Result syscall_not_supported(void) { return TEE_ERROR_NOT_SUPPORTED; } /* Configuration properties */ /* API implementation version */ static const char api_vers[] = TO_STR(CFG_TEE_API_VERSION); /* Implementation description (implementation-dependent) */ static const char descr[] = TO_STR(CFG_TEE_IMPL_DESCR); /* * TA persistent time protection level * 100: Persistent time based on an REE-controlled real-time clock * and on the TEE Trusted Storage for the storage of origins (default). * 1000: Persistent time based on a TEE-controlled real-time clock * and the TEE Trusted Storage. * The real-time clock MUST be out of reach of software attacks * from the REE. */ static const uint32_t ta_time_prot_lvl = 100; /* Elliptic Curve Cryptographic support */ #ifdef CFG_CRYPTO_ECC static const bool crypto_ecc_en = 1; #else static const bool crypto_ecc_en; #endif /* * Trusted storage anti rollback protection level * 100: Antirollback enforced at REE level * 1000: Antirollback TEE-controlled hardware */ #ifdef CFG_RPMB_FS static const uint32_t ts_antiroll_prot_lvl = 1000; #else static const uint32_t ts_antiroll_prot_lvl = 100; #endif /* Trusted OS implementation version */ static const char trustedos_impl_version[] = TO_STR(TEE_IMPL_VERSION); /* Trusted OS implementation version (binary value) */ static const uint32_t trustedos_impl_bin_version; /* 0 by default */ /* Trusted OS implementation manufacturer name */ static const char trustedos_manufacturer[] = TO_STR(CFG_TEE_MANUFACTURER); /* Trusted firmware version */ static const char fw_impl_version[] = TO_STR(CFG_TEE_FW_IMPL_VERSION); /* Trusted firmware version (binary value) */ static const uint32_t fw_impl_bin_version; /* 0 by default */ /* Trusted firmware manufacturer name */ static const char fw_manufacturer[] = TO_STR(CFG_TEE_FW_MANUFACTURER); static TEE_Result get_prop_tee_dev_id(struct ts_session *sess __unused, void *buf, size_t *blen) { TEE_Result res; TEE_UUID uuid; const size_t nslen = 5; uint8_t data[5 + FVR_DIE_ID_NUM_REGS * sizeof(uint32_t)] = { 'O', 'P', 'T', 'E', 'E' }; if (*blen < sizeof(uuid)) { *blen = sizeof(uuid); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(uuid); if (tee_otp_get_die_id(data + nslen, sizeof(data) - nslen)) return TEE_ERROR_BAD_STATE; res = tee_hash_createdigest(TEE_ALG_SHA256, data, sizeof(data), (uint8_t *)&uuid, sizeof(uuid)); if (res != TEE_SUCCESS) return TEE_ERROR_BAD_STATE; /* * Changes the random value into and UUID as specifiec * in RFC 4122. The magic values are from the example * code in the RFC. * * TEE_UUID is defined slightly different from the RFC, * but close enough for our purpose. */ uuid.timeHiAndVersion &= 0x0fff; uuid.timeHiAndVersion |= 5 << 12; /* uuid.clock_seq_hi_and_reserved in the RFC */ uuid.clockSeqAndNode[0] &= 0x3f; uuid.clockSeqAndNode[0] |= 0x80; return copy_to_user(buf, &uuid, sizeof(TEE_UUID)); } static TEE_Result get_prop_tee_sys_time_prot_level(struct ts_session *sess __unused, void *buf, size_t *blen) { uint32_t prot; if (*blen < sizeof(prot)) { *blen = sizeof(prot); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(prot); prot = tee_time_get_sys_time_protection_level(); return copy_to_user(buf, &prot, sizeof(prot)); } static TEE_Result get_prop_client_id(struct ts_session *sess, void *buf, size_t *blen) { if (*blen < sizeof(TEE_Identity)) { *blen = sizeof(TEE_Identity); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(TEE_Identity); return copy_to_user(buf, &to_ta_session(sess)->clnt_id, sizeof(TEE_Identity)); } static TEE_Result get_prop_client_endian(struct ts_session *sess __unused, void *buf, size_t *blen) { const uint32_t endian = 0; /* assume little-endian */ if (*blen < sizeof(endian)) { *blen = sizeof(endian); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(endian); return copy_to_user(buf, &endian, sizeof(endian)); } static TEE_Result get_prop_ta_app_id(struct ts_session *sess, void *buf, size_t *blen) { if (*blen < sizeof(TEE_UUID)) { *blen = sizeof(TEE_UUID); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(TEE_UUID); return copy_to_user(buf, &sess->ctx->uuid, sizeof(TEE_UUID)); } #ifdef CFG_TA_BTI static TEE_Result get_prop_feat_bti_implemented(struct ts_session *sess __unused, void *buf, size_t *blen) { bool bti_impl = false; if (*blen < sizeof(bti_impl)) { *blen = sizeof(bti_impl); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(bti_impl); bti_impl = feat_bti_is_implemented(); return copy_to_user(buf, &bti_impl, sizeof(bti_impl)); } #endif #ifdef CFG_TA_PAUTH static TEE_Result get_prop_feat_pauth_implemented(struct ts_session *sess __unused, void *buf, size_t *blen) { bool pauth_impl = false; if (*blen < sizeof(pauth_impl)) { *blen = sizeof(pauth_impl); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(pauth_impl); pauth_impl = feat_pauth_is_implemented(); return copy_to_user(buf, &pauth_impl, sizeof(pauth_impl)); } #endif #if MEMTAG_IS_ENABLED static TEE_Result get_prop_feat_memtag_implemented(struct ts_session *sess __unused, void *buf, size_t *blen) { uint32_t v = 0; if (*blen < sizeof(v)) { *blen = sizeof(v); return TEE_ERROR_SHORT_BUFFER; } *blen = sizeof(v); if (memtag_is_enabled()) v = feat_mte_implemented(); return copy_to_user(buf, &v, sizeof(v)); } #endif /* Properties of the set TEE_PROPSET_CURRENT_CLIENT */ const struct tee_props tee_propset_client[] = { { .name = "gpd.client.identity", .prop_type = USER_TA_PROP_TYPE_IDENTITY, .get_prop_func = get_prop_client_id }, { .name = "gpd.client.endian", .prop_type = USER_TA_PROP_TYPE_U32, .get_prop_func = get_prop_client_endian }, }; /* Properties of the set TEE_PROPSET_CURRENT_TA */ const struct tee_props tee_propset_ta[] = { { .name = "gpd.ta.appID", .prop_type = USER_TA_PROP_TYPE_UUID, .get_prop_func = get_prop_ta_app_id }, /* * Following properties are processed directly in libutee: * TA_PROP_STR_SINGLE_INSTANCE * TA_PROP_STR_MULTI_SESSION * TA_PROP_STR_KEEP_ALIVE * TA_PROP_STR_DATA_SIZE * TA_PROP_STR_STACK_SIZE * TA_PROP_STR_VERSION * TA_PROP_STR_DESCRIPTION * USER_TA_PROP_TYPE_STRING, * TA_DESCRIPTION */ }; /* Properties of the set TEE_PROPSET_TEE_IMPLEMENTATION */ const struct tee_props tee_propset_tee[] = { { .name = "gpd.tee.apiversion", .prop_type = USER_TA_PROP_TYPE_STRING, .data = api_vers, .len = sizeof(api_vers), }, { .name = "gpd.tee.description", .prop_type = USER_TA_PROP_TYPE_STRING, .data = descr, .len = sizeof(descr) }, { .name = "gpd.tee.deviceID", .prop_type = USER_TA_PROP_TYPE_UUID, .get_prop_func = get_prop_tee_dev_id }, { .name = "gpd.tee.systemTime.protectionLevel", .prop_type = USER_TA_PROP_TYPE_U32, .get_prop_func = get_prop_tee_sys_time_prot_level }, { .name = "gpd.tee.TAPersistentTime.protectionLevel", .prop_type = USER_TA_PROP_TYPE_U32, .data = &ta_time_prot_lvl, .len = sizeof(ta_time_prot_lvl) }, { .name = "gpd.tee.cryptography.ecc", .prop_type = USER_TA_PROP_TYPE_BOOL, .data = &crypto_ecc_en, .len = sizeof(crypto_ecc_en) }, { .name = "gpd.tee.trustedStorage.antiRollback.protectionLevel", .prop_type = USER_TA_PROP_TYPE_U32, .data = &ts_antiroll_prot_lvl, .len = sizeof(ts_antiroll_prot_lvl) }, { .name = "gpd.tee.trustedos.implementation.version", .prop_type = USER_TA_PROP_TYPE_STRING, .data = trustedos_impl_version, .len = sizeof(trustedos_impl_version) }, { .name = "gpd.tee.trustedos.implementation.binaryversion", .prop_type = USER_TA_PROP_TYPE_U32, .data = &trustedos_impl_bin_version, .len = sizeof(trustedos_impl_bin_version) }, { .name = "gpd.tee.trustedos.manufacturer", .prop_type = USER_TA_PROP_TYPE_STRING, .data = trustedos_manufacturer, .len = sizeof(trustedos_manufacturer) }, { .name = "gpd.tee.firmware.implementation.version", .prop_type = USER_TA_PROP_TYPE_STRING, .data = fw_impl_version, .len = sizeof(fw_impl_version) }, { .name = "gpd.tee.firmware.implementation.binaryversion", .prop_type = USER_TA_PROP_TYPE_U32, .data = &fw_impl_bin_version, .len = sizeof(fw_impl_bin_version) }, { .name = "gpd.tee.firmware.manufacturer", .prop_type = USER_TA_PROP_TYPE_STRING, .data = fw_manufacturer, .len = sizeof(fw_manufacturer) }, #ifdef CFG_TA_BTI { .name = "org.trustedfirmware.optee.cpu.feat_bti_implemented", .prop_type = USER_TA_PROP_TYPE_BOOL, .get_prop_func = get_prop_feat_bti_implemented }, #endif #ifdef CFG_TA_PAUTH { .name = "org.trustedfirmware.optee.cpu.feat_pauth_implemented", .prop_type = USER_TA_PROP_TYPE_BOOL, .get_prop_func = get_prop_feat_pauth_implemented }, #endif #if MEMTAG_IS_ENABLED { .name = "org.trustedfirmware.optee.cpu.feat_memtag_implemented", .prop_type = USER_TA_PROP_TYPE_U32, .get_prop_func = get_prop_feat_memtag_implemented } #endif /* * Following properties are processed directly in libutee: * gpd.tee.arith.maxBigIntSize */ }; __weak const struct tee_vendor_props vendor_props_client; __weak const struct tee_vendor_props vendor_props_ta; __weak const struct tee_vendor_props vendor_props_tee; static void get_prop_set(unsigned long prop_set, const struct tee_props **props, size_t *size, const struct tee_props **vendor_props, size_t *vendor_size) { if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_CURRENT_CLIENT) { *props = tee_propset_client; *size = ARRAY_SIZE(tee_propset_client); *vendor_props = vendor_props_client.props; *vendor_size = vendor_props_client.len; } else if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_CURRENT_TA) { *props = tee_propset_ta; *size = ARRAY_SIZE(tee_propset_ta); *vendor_props = vendor_props_ta.props; *vendor_size = vendor_props_ta.len; } else if ((TEE_PropSetHandle)prop_set == TEE_PROPSET_TEE_IMPLEMENTATION) { *props = tee_propset_tee; *size = ARRAY_SIZE(tee_propset_tee); *vendor_props = vendor_props_tee.props; *vendor_size = vendor_props_tee.len; } else { *props = NULL; *size = 0; *vendor_props = NULL; *vendor_size = 0; } } static const struct tee_props *get_prop_struct(unsigned long prop_set, unsigned long index) { const struct tee_props *props; const struct tee_props *vendor_props; size_t size; size_t vendor_size; get_prop_set(prop_set, &props, &size, &vendor_props, &vendor_size); if (index < size) return &(props[index]); index -= size; if (index < vendor_size) return &(vendor_props[index]); return NULL; } /* * prop_set is part of TEE_PROPSET_xxx * index is the index in the Property Set to retrieve * if name is not NULL, the name of "index" property is returned * if buf is not NULL, the property is returned */ TEE_Result syscall_get_property(unsigned long prop_set, unsigned long index, void *name, uint32_t *name_len, void *buf, uint32_t *blen, uint32_t *prop_type) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; TEE_Result res2 = TEE_SUCCESS; const struct tee_props *prop = NULL; uint32_t klen = 0; size_t klen_size = 0; uint32_t elen = 0; prop = get_prop_struct(prop_set, index); if (!prop) return TEE_ERROR_ITEM_NOT_FOUND; /* Get the property type */ if (prop_type) { res = copy_to_user(prop_type, &prop->prop_type, sizeof(*prop_type)); if (res != TEE_SUCCESS) return res; } /* Get the property */ if (buf && blen) { res = copy_from_user(&klen, blen, sizeof(klen)); if (res != TEE_SUCCESS) return res; if (prop->get_prop_func) { klen_size = klen; res = prop->get_prop_func(sess, buf, &klen_size); klen = klen_size; res2 = copy_to_user(blen, &klen, sizeof(*blen)); } else { if (klen < prop->len) res = TEE_ERROR_SHORT_BUFFER; else res = copy_to_user(buf, prop->data, prop->len); res2 = copy_to_user(blen, &prop->len, sizeof(*blen)); } if (res2 != TEE_SUCCESS) return res2; if (res != TEE_SUCCESS) return res; } /* Get the property name */ if (name && name_len) { res = copy_from_user(&klen, name_len, sizeof(klen)); if (res != TEE_SUCCESS) return res; elen = strlen(prop->name) + 1; if (klen < elen) res = TEE_ERROR_SHORT_BUFFER; else res = copy_to_user(name, prop->name, elen); res2 = copy_to_user(name_len, &elen, sizeof(*name_len)); if (res2 != TEE_SUCCESS) return res2; if (res != TEE_SUCCESS) return res; } return res; } /* * prop_set is part of TEE_PROPSET_xxx */ TEE_Result syscall_get_property_name_to_index(unsigned long prop_set, void *name, unsigned long name_len, uint32_t *index) { TEE_Result res = TEE_SUCCESS; const struct tee_props *props = NULL; size_t size = 0; const struct tee_props *vendor_props = NULL; size_t vendor_size = 0; char *kname = NULL; uint32_t i = 0; get_prop_set(prop_set, &props, &size, &vendor_props, &vendor_size); if (!props) return TEE_ERROR_ITEM_NOT_FOUND; if (!name || !name_len) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } kname = malloc(name_len); if (!kname) return TEE_ERROR_OUT_OF_MEMORY; res = copy_from_user(kname, name, name_len); if (res != TEE_SUCCESS) goto out; kname[name_len - 1] = 0; res = TEE_ERROR_ITEM_NOT_FOUND; for (i = 0; i < size; i++) { if (!strcmp(kname, props[i].name)) { res = copy_to_user(index, &i, sizeof(*index)); goto out; } } for (i = size; i < size + vendor_size; i++) { if (!strcmp(kname, vendor_props[i - size].name)) { res = copy_to_user(index, &i, sizeof(*index)); goto out; } } out: free_wipe(kname); return res; } static TEE_Result utee_param_to_param(struct user_ta_ctx *utc, struct tee_ta_param *p, struct utee_params *up) { TEE_Result res = TEE_SUCCESS; size_t n = 0; uint64_t types = 0; struct utee_params *up_bbuf = NULL; res = BB_MEMDUP_USER(up, sizeof(*up), &up_bbuf); if (res) goto out; types = up_bbuf->types; p->types = types; for (n = 0; n < TEE_NUM_PARAMS; n++) { uintptr_t a = up_bbuf->vals[n * 2]; size_t b = up_bbuf->vals[n * 2 + 1]; uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; switch (TEE_PARAM_TYPE_GET(types, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: flags |= TEE_MEMORY_ACCESS_WRITE; fallthrough; case TEE_PARAM_TYPE_MEMREF_INPUT: p->u[n].mem.offs = memtag_strip_tag_vaddr((void *)a); p->u[n].mem.size = b; if (!p->u[n].mem.offs) { /* Allow NULL memrefs if of size 0 */ if (p->u[n].mem.size) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } p->u[n].mem.mobj = NULL; break; } p->u[n].mem.mobj = &mobj_virt; res = vm_check_access_rights(&utc->uctx, flags, a, b); if (res) goto out; break; case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_INOUT: p->u[n].val.a = a; p->u[n].val.b = b; break; default: memset(&p->u[n], 0, sizeof(p->u[n])); break; } } out: bb_free(up_bbuf, sizeof(struct utee_params)); return res; } /* * TA invokes some TA with parameter. * If some parameters are memory references: * - either the memref is inside TA private RAM: TA is not allowed to expose * its private RAM: use a temporary memory buffer and copy the data. * - or the memref is not in the TA private RAM: * - if the memref was mapped to the TA, TA is allowed to expose it. * - if so, converts memref virtual address into a physical address. */ static TEE_Result tee_svc_copy_param(struct ts_session *sess, struct ts_session *called_sess, struct utee_params *callee_params, struct tee_ta_param *param) { struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; void *va = NULL; size_t n = 0; size_t s = 0; callee_params = memtag_strip_tag(callee_params); /* fill 'param' input struct with caller params description buffer */ if (!callee_params) { memset(param, 0, sizeof(*param)); } else { uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; res = vm_check_access_rights(&utc->uctx, flags, (uaddr_t)callee_params, sizeof(struct utee_params)); if (res != TEE_SUCCESS) return res; res = utee_param_to_param(utc, param, callee_params); if (res != TEE_SUCCESS) return res; } if (called_sess && is_pseudo_ta_ctx(called_sess->ctx)) { /* pseudo TA borrows the mapping of the calling TA */ return TEE_SUCCESS; } /* All mobj in param are of type MOJB_TYPE_VIRT */ for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(param->types, n)) { case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: va = (void *)param->u[n].mem.offs; s = param->u[n].mem.size; if (!s) { param->u[n].mem.mobj = NULL; break; } if (!va) return TEE_ERROR_BAD_PARAMETERS; /* uTA cannot expose its private memory */ if (vm_buf_is_inside_um_private(&utc->uctx, va, s)) return TEE_ERROR_BAD_PARAMETERS; res = vm_buf_to_mboj_offs(&utc->uctx, va, s, ¶m->u[n].mem.mobj, ¶m->u[n].mem.offs); if (res != TEE_SUCCESS) return res; break; default: break; } } return TEE_SUCCESS; } /* * Back from execution of service: update parameters passed from TA: * If some parameters were memory references: * - either the memref was temporary: copy back data and update size * - or it was the original TA memref: update only the size value. */ static TEE_Result tee_svc_update_out_param( struct tee_ta_param *param, struct utee_params *usr_param) { size_t n = 0; uint64_t *vals = usr_param->vals; uint64_t sz = 0; for (n = 0; n < TEE_NUM_PARAMS; n++) { TEE_Result res = TEE_SUCCESS; uint64_t val_buf[2] = { }; switch (TEE_PARAM_TYPE_GET(param->types, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: sz = param->u[n].mem.size; res = PUT_USER_SCALAR(sz, &usr_param->vals[n * 2 + 1]); if (res) return res; break; case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: val_buf[0] = param->u[n].val.a; val_buf[1] = param->u[n].val.b; res = copy_to_user(&vals[n * 2], val_buf, 2 * sizeof(uint64_t)); if (res) return res; break; default: continue; } } return TEE_SUCCESS; } /* Called when a TA calls an OpenSession on another TA */ TEE_Result syscall_open_ta_session(const TEE_UUID *dest, unsigned long cancel_req_to, struct utee_params *usr_param, uint32_t *ta_sess, uint32_t *ret_orig) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; uint32_t ret_o = TEE_ORIGIN_TEE; struct tee_ta_session *s = NULL; TEE_UUID *uuid = malloc(sizeof(TEE_UUID)); struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param)); TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity)); if (uuid == NULL || param == NULL || clnt_id == NULL) { res = TEE_ERROR_OUT_OF_MEMORY; goto out_free_only; } memset(param, 0, sizeof(struct tee_ta_param)); res = copy_from_user_private(uuid, dest, sizeof(TEE_UUID)); if (res != TEE_SUCCESS) goto function_exit; clnt_id->login = TEE_LOGIN_TRUSTED_APP; memcpy(&clnt_id->uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, NULL, usr_param, param); if (res != TEE_SUCCESS) goto function_exit; res = tee_ta_open_session(&ret_o, &s, &utc->open_sessions, uuid, clnt_id, cancel_req_to, param); vm_set_ctx(&utc->ta_ctx.ts_ctx); if (res != TEE_SUCCESS) goto function_exit; res = tee_svc_update_out_param(param, usr_param); function_exit: if (res == TEE_SUCCESS) copy_to_user_private(ta_sess, &s->id, sizeof(s->id)); copy_to_user_private(ret_orig, &ret_o, sizeof(ret_o)); out_free_only: free_wipe(param); free_wipe(uuid); free_wipe(clnt_id); return res; } TEE_Result syscall_close_ta_session(unsigned long ta_sess) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Identity clnt_id = { }; struct tee_ta_session *s = NULL; s = tee_ta_find_session(ta_sess, &utc->open_sessions); clnt_id.login = TEE_LOGIN_TRUSTED_APP; memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); return tee_ta_close_session(s, &utc->open_sessions, &clnt_id); } TEE_Result syscall_invoke_ta_command(unsigned long ta_sess, unsigned long cancel_req_to, unsigned long cmd_id, struct utee_params *usr_param, uint32_t *ret_orig) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; TEE_Result res2 = TEE_SUCCESS; uint32_t ret_o = TEE_ORIGIN_TEE; struct tee_ta_param param = { 0 }; TEE_Identity clnt_id = { }; struct tee_ta_session *called_sess = NULL; called_sess = tee_ta_get_session((uint32_t)ta_sess, true, &utc->open_sessions); if (!called_sess) return TEE_ERROR_BAD_PARAMETERS; clnt_id.login = TEE_LOGIN_TRUSTED_APP; memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, &called_sess->ts_sess, usr_param, ¶m); if (res != TEE_SUCCESS) goto function_exit; res = tee_ta_invoke_command(&ret_o, called_sess, &clnt_id, cancel_req_to, cmd_id, ¶m); if (res == TEE_ERROR_TARGET_DEAD) goto function_exit; res2 = tee_svc_update_out_param(¶m, usr_param); if (res2 != TEE_SUCCESS) { /* * Spec for TEE_InvokeTACommand() says: * "If the return origin is different from * TEE_ORIGIN_TRUSTED_APP, then the function has failed * before it could reach the destination Trusted * Application." * * But if we can't update params to the caller we have no * choice we need to return some error to indicate that * parameters aren't updated as expected. */ ret_o = TEE_ORIGIN_TEE; res = res2; } function_exit: tee_ta_put_session(called_sess); copy_to_user_private(ret_orig, &ret_o, sizeof(ret_o)); return res; } TEE_Result syscall_check_access_rights(unsigned long flags, const void *buf, size_t len) { struct ts_session *s = ts_get_current_session(); return vm_check_access_rights(&to_user_ta_ctx(s->ctx)->uctx, flags, memtag_strip_tag_vaddr(buf), len); } TEE_Result syscall_get_cancellation_flag(uint32_t *cancel) { struct ts_session *s = ts_get_current_session(); uint32_t c = 0; c = tee_ta_session_is_cancelled(to_ta_session(s), NULL); return copy_to_user(cancel, &c, sizeof(c)); } TEE_Result syscall_unmask_cancellation(uint32_t *old_mask) { struct ts_session *s = ts_get_current_session(); struct tee_ta_session *sess = NULL; uint32_t m = 0; sess = to_ta_session(s); m = sess->cancel_mask; sess->cancel_mask = false; return copy_to_user(old_mask, &m, sizeof(m)); } TEE_Result syscall_mask_cancellation(uint32_t *old_mask) { struct ts_session *s = ts_get_current_session(); struct tee_ta_session *sess = NULL; uint32_t m = 0; sess = to_ta_session(s); m = sess->cancel_mask; sess->cancel_mask = true; return copy_to_user(old_mask, &m, sizeof(m)); } TEE_Result syscall_wait(unsigned long timeout) { struct ts_session *s = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; uint32_t mytime = 0; TEE_Time base_time = { }; TEE_Time current_time = { }; res = tee_time_get_sys_time(&base_time); if (res != TEE_SUCCESS) return res; while (true) { res = tee_time_get_sys_time(¤t_time); if (res != TEE_SUCCESS) return res; if (tee_ta_session_is_cancelled(to_ta_session(s), ¤t_time)) return TEE_ERROR_CANCEL; mytime = (current_time.seconds - base_time.seconds) * 1000 + (int)current_time.millis - (int)base_time.millis; if (mytime >= timeout) return TEE_SUCCESS; tee_time_wait(timeout - mytime); } return res; } TEE_Result syscall_get_time(unsigned long cat, TEE_Time *mytime) { struct ts_session *s = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; TEE_Result res2 = TEE_SUCCESS; TEE_Time t = { }; switch (cat) { case UTEE_TIME_CAT_SYSTEM: res = tee_time_get_sys_time(&t); break; case UTEE_TIME_CAT_TA_PERSISTENT: res = tee_time_get_ta_time((const void *)&s->ctx->uuid, &t); break; case UTEE_TIME_CAT_REE: res = tee_time_get_ree_time(&t); break; default: res = TEE_ERROR_BAD_PARAMETERS; break; } if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) { res2 = copy_to_user_private(mytime, &t, sizeof(t)); if (res2 != TEE_SUCCESS) res = res2; } return res; } TEE_Result syscall_set_ta_time(const TEE_Time *mytime) { struct ts_session *s = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; TEE_Time t = { }; res = copy_from_user_private(&t, mytime, sizeof(t)); if (res != TEE_SUCCESS) return res; return tee_time_set_ta_time((const void *)&s->ctx->uuid, &t); } optee_os-4.3.0/core/tee/tee_svc_cryp.c000066400000000000000000003637021464416617300177200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, 2022-2023 Linaro Limited * Copyright (c) 2022, Technology Innovation Institute (TII) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CFG_CRYPTO_HKDF) #include #endif #if defined(CFG_CRYPTO_CONCAT_KDF) #include #endif #if defined(CFG_CRYPTO_PBKDF2) #include #endif enum cryp_state { CRYP_STATE_INITIALIZED = 0, CRYP_STATE_UNINITIALIZED }; typedef void (*tee_cryp_ctx_finalize_func_t) (void *ctx); struct tee_cryp_state { TAILQ_ENTRY(tee_cryp_state) link; uint32_t algo; uint32_t mode; vaddr_t key1; vaddr_t key2; void *ctx; tee_cryp_ctx_finalize_func_t ctx_finalize; enum cryp_state state; }; struct tee_cryp_obj_secret { uint32_t key_size; uint32_t alloc_size; /* * Pseudo code visualize layout of structure * Next follows data, such as: * uint8_t data[alloc_size] * key_size must never exceed alloc_size */ }; #define TEE_TYPE_ATTR_OPTIONAL BIT(0) #define TEE_TYPE_ATTR_REQUIRED BIT(1) #define TEE_TYPE_ATTR_OPTIONAL_GROUP BIT(2) #define TEE_TYPE_ATTR_SIZE_INDICATOR BIT(3) #define TEE_TYPE_ATTR_GEN_KEY_OPT BIT(4) #define TEE_TYPE_ATTR_GEN_KEY_REQ BIT(5) #define TEE_TYPE_ATTR_BIGNUM_MAXBITS BIT(6) /* Handle storing of generic secret keys of varying lengths */ #define ATTR_OPS_INDEX_SECRET 0 /* Convert to/from big-endian byte array and provider-specific bignum */ #define ATTR_OPS_INDEX_BIGNUM 1 /* Convert to/from value attribute depending on direction */ #define ATTR_OPS_INDEX_VALUE 2 /* Convert to/from curve25519 attribute depending on direction */ #define ATTR_OPS_INDEX_25519 3 #define ATTR_OPS_INDEX_448 4 /* Curve25519 key bytes size is always 32 bytes*/ #define KEY_SIZE_BYTES_25519 UL(32) #define KEY_SIZE_BYTES_448 UL(56) /* TEE Internal Core API v1.3.1, Table 6-8 */ #define TEE_ED25519_CTX_MAX_LENGTH 255 struct tee_cryp_obj_type_attrs { uint32_t attr_id; uint16_t flags; uint16_t ops_index; uint16_t raw_offs; uint16_t raw_size; }; #define RAW_DATA(_x, _y) \ .raw_offs = offsetof(_x, _y), .raw_size = MEMBER_SIZE(_x, _y) static const struct tee_cryp_obj_type_attrs tee_cryp_obj_secret_value_attrs[] = { { .attr_id = TEE_ATTR_SECRET_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_SECRET, .raw_offs = 0, .raw_size = 0 }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_rsa_pub_key_attrs[] = { { .attr_id = TEE_ATTR_RSA_MODULUS, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_public_key, n) }, { .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_public_key, e) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_rsa_keypair_attrs[] = { { .attr_id = TEE_ATTR_RSA_MODULUS, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, n) }, { .attr_id = TEE_ATTR_RSA_PUBLIC_EXPONENT, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_OPT, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, e) }, { .attr_id = TEE_ATTR_RSA_PRIVATE_EXPONENT, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, d) }, { .attr_id = TEE_ATTR_RSA_PRIME1, .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, p) }, { .attr_id = TEE_ATTR_RSA_PRIME2, .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, q) }, { .attr_id = TEE_ATTR_RSA_EXPONENT1, .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, dp) }, { .attr_id = TEE_ATTR_RSA_EXPONENT2, .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, dq) }, { .attr_id = TEE_ATTR_RSA_COEFFICIENT, .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct rsa_keypair, qp) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dsa_pub_key_attrs[] = { { .attr_id = TEE_ATTR_DSA_PRIME, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_public_key, p) }, { .attr_id = TEE_ATTR_DSA_SUBPRIME, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_public_key, q) }, { .attr_id = TEE_ATTR_DSA_BASE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_public_key, g) }, { .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_public_key, y) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dsa_keypair_attrs[] = { { .attr_id = TEE_ATTR_DSA_PRIME, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ | TEE_TYPE_ATTR_BIGNUM_MAXBITS | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_keypair, p) }, { .attr_id = TEE_ATTR_DSA_SUBPRIME, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_keypair, q) }, { .attr_id = TEE_ATTR_DSA_BASE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ | TEE_TYPE_ATTR_BIGNUM_MAXBITS, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_keypair, g) }, { .attr_id = TEE_ATTR_DSA_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_keypair, x) }, { .attr_id = TEE_ATTR_DSA_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_BIGNUM_MAXBITS, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dsa_keypair, y) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_dh_keypair_attrs[] = { { .attr_id = TEE_ATTR_DH_PRIME, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR | TEE_TYPE_ATTR_GEN_KEY_REQ, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dh_keypair, p) }, { .attr_id = TEE_ATTR_DH_BASE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_GEN_KEY_REQ, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dh_keypair, g) }, { .attr_id = TEE_ATTR_DH_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dh_keypair, y) }, { .attr_id = TEE_ATTR_DH_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dh_keypair, x) }, { .attr_id = TEE_ATTR_DH_SUBPRIME, .flags = TEE_TYPE_ATTR_OPTIONAL_GROUP | TEE_TYPE_ATTR_GEN_KEY_OPT, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct dh_keypair, q) }, { .attr_id = TEE_ATTR_DH_X_BITS, .flags = TEE_TYPE_ATTR_GEN_KEY_OPT, .ops_index = ATTR_OPS_INDEX_VALUE, RAW_DATA(struct dh_keypair, xbits) }, }; #if defined(CFG_CRYPTO_HKDF) static const struct tee_cryp_obj_type_attrs tee_cryp_obj_hkdf_ikm_attrs[] = { { .attr_id = TEE_ATTR_HKDF_IKM, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_SECRET, .raw_offs = 0, .raw_size = 0 }, }; #endif #if defined(CFG_CRYPTO_CONCAT_KDF) static const struct tee_cryp_obj_type_attrs tee_cryp_obj_concat_kdf_z_attrs[] = { { .attr_id = TEE_ATTR_CONCAT_KDF_Z, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_SECRET, .raw_offs = 0, .raw_size = 0 }, }; #endif #if defined(CFG_CRYPTO_PBKDF2) static const struct tee_cryp_obj_type_attrs tee_cryp_obj_pbkdf2_passwd_attrs[] = { { .attr_id = TEE_ATTR_PBKDF2_PASSWORD, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_SECRET, .raw_offs = 0, .raw_size = 0 }, }; #endif static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ecc_pub_key_attrs[] = { { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_public_key, x) }, { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_public_key, y) }, { .attr_id = TEE_ATTR_ECC_CURVE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR, .ops_index = ATTR_OPS_INDEX_VALUE, RAW_DATA(struct ecc_public_key, curve) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ecc_keypair_attrs[] = { { .attr_id = TEE_ATTR_ECC_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_keypair, d) }, { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_keypair, x) }, { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_keypair, y) }, { .attr_id = TEE_ATTR_ECC_CURVE, .flags = TEE_TYPE_ATTR_REQUIRED | TEE_TYPE_ATTR_SIZE_INDICATOR | TEE_TYPE_ATTR_GEN_KEY_REQ, .ops_index = ATTR_OPS_INDEX_VALUE, RAW_DATA(struct ecc_keypair, curve) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_sm2_pub_key_attrs[] = { { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_public_key, x) }, { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_public_key, y) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_sm2_keypair_attrs[] = { { .attr_id = TEE_ATTR_ECC_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_keypair, d) }, { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_X, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_keypair, x) }, { .attr_id = TEE_ATTR_ECC_PUBLIC_VALUE_Y, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_BIGNUM, RAW_DATA(struct ecc_keypair, y) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_x25519_keypair_attrs[] = { { .attr_id = TEE_ATTR_X25519_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_25519, RAW_DATA(struct montgomery_keypair, priv) }, { .attr_id = TEE_ATTR_X25519_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_25519, RAW_DATA(struct montgomery_keypair, pub) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_x448_keypair_attrs[] = { { .attr_id = TEE_ATTR_X448_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_448, RAW_DATA(struct montgomery_keypair, priv) }, { .attr_id = TEE_ATTR_X448_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_448, RAW_DATA(struct montgomery_keypair, pub) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ed25519_pub_key_attrs[] = { { .attr_id = TEE_ATTR_ED25519_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_25519, RAW_DATA(struct ed25519_public_key, pub) }, }; static const struct tee_cryp_obj_type_attrs tee_cryp_obj_ed25519_keypair_attrs[] = { { .attr_id = TEE_ATTR_ED25519_PRIVATE_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_25519, RAW_DATA(struct ed25519_keypair, priv) }, { .attr_id = TEE_ATTR_ED25519_PUBLIC_VALUE, .flags = TEE_TYPE_ATTR_REQUIRED, .ops_index = ATTR_OPS_INDEX_25519, RAW_DATA(struct ed25519_keypair, pub) }, }; struct tee_cryp_obj_type_props { TEE_ObjectType obj_type; uint16_t min_size; /* may not be smaller than this */ uint16_t max_size; /* may not be larger than this */ uint16_t alloc_size; /* this many bytes are allocated to hold data */ uint8_t quanta; /* may only be an multiple of this */ uint8_t num_type_attrs; const struct tee_cryp_obj_type_attrs *type_attrs; }; #define PROP(obj_type, quanta, min_size, max_size, alloc_size, type_attrs) \ { (obj_type), (min_size), (max_size), (alloc_size), (quanta), \ ARRAY_SIZE(type_attrs), (type_attrs) } static const struct tee_cryp_obj_type_props tee_cryp_obj_props[] = { PROP(TEE_TYPE_AES, 64, 128, 256, /* valid sizes 128, 192, 256 */ 256 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_DES, 64, 64, 64, /* Valid size 64 with parity */ 64 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_DES3, 64, 128, 192, /* Valid sizes 128, 192 with parity */ 192 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_SM4, 128, 128, 128, 128 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_MD5, 8, 64, 512, 512 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), #if defined(CFG_HMAC_64_1024_RANGE) PROP(TEE_TYPE_HMAC_SHA1, 8, 64, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA224, 8, 64, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA256, 8, 64, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA384, 8, 64, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA512, 8, 64, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), #else PROP(TEE_TYPE_HMAC_SHA1, 8, 80, 512, 512 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA224, 8, 112, 512, 512 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA256, 8, 192, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA384, 8, 256, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA512, 8, 256, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), #endif PROP(TEE_TYPE_HMAC_SHA3_224, 8, 192, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA3_256, 8, 256, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA3_384, 8, 256, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SHA3_512, 8, 256, 1024, 1024 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_HMAC_SM3, 8, 80, 1024, 512 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), PROP(TEE_TYPE_GENERIC_SECRET, 8, 0, 4096, 4096 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_secret_value_attrs), #if defined(CFG_CRYPTO_HKDF) PROP(TEE_TYPE_HKDF_IKM, 8, 0, 4096, 4096 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_hkdf_ikm_attrs), #endif #if defined(CFG_CRYPTO_CONCAT_KDF) PROP(TEE_TYPE_CONCAT_KDF_Z, 8, 0, 4096, 4096 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_concat_kdf_z_attrs), #endif #if defined(CFG_CRYPTO_PBKDF2) PROP(TEE_TYPE_PBKDF2_PASSWORD, 8, 0, 4096, 4096 / 8 + sizeof(struct tee_cryp_obj_secret), tee_cryp_obj_pbkdf2_passwd_attrs), #endif PROP(TEE_TYPE_RSA_PUBLIC_KEY, 1, 256, CFG_CORE_BIGNUM_MAX_BITS, sizeof(struct rsa_public_key), tee_cryp_obj_rsa_pub_key_attrs), PROP(TEE_TYPE_RSA_KEYPAIR, 1, 256, CFG_CORE_BIGNUM_MAX_BITS, sizeof(struct rsa_keypair), tee_cryp_obj_rsa_keypair_attrs), PROP(TEE_TYPE_DSA_PUBLIC_KEY, 64, 512, 3072, sizeof(struct dsa_public_key), tee_cryp_obj_dsa_pub_key_attrs), PROP(TEE_TYPE_DSA_KEYPAIR, 64, 512, 3072, sizeof(struct dsa_keypair), tee_cryp_obj_dsa_keypair_attrs), PROP(TEE_TYPE_DH_KEYPAIR, 1, 256, 2048, sizeof(struct dh_keypair), tee_cryp_obj_dh_keypair_attrs), PROP(TEE_TYPE_ECDSA_PUBLIC_KEY, 1, 192, 521, sizeof(struct ecc_public_key), tee_cryp_obj_ecc_pub_key_attrs), PROP(TEE_TYPE_ECDSA_KEYPAIR, 1, 192, 521, sizeof(struct ecc_keypair), tee_cryp_obj_ecc_keypair_attrs), PROP(TEE_TYPE_ECDH_PUBLIC_KEY, 1, 192, 521, sizeof(struct ecc_public_key), tee_cryp_obj_ecc_pub_key_attrs), PROP(TEE_TYPE_ECDH_KEYPAIR, 1, 192, 521, sizeof(struct ecc_keypair), tee_cryp_obj_ecc_keypair_attrs), PROP(TEE_TYPE_SM2_DSA_PUBLIC_KEY, 1, 256, 256, sizeof(struct ecc_public_key), tee_cryp_obj_sm2_pub_key_attrs), PROP(TEE_TYPE_SM2_DSA_KEYPAIR, 1, 256, 256, sizeof(struct ecc_keypair), tee_cryp_obj_sm2_keypair_attrs), PROP(TEE_TYPE_SM2_PKE_PUBLIC_KEY, 1, 256, 256, sizeof(struct ecc_public_key), tee_cryp_obj_sm2_pub_key_attrs), PROP(TEE_TYPE_SM2_PKE_KEYPAIR, 1, 256, 256, sizeof(struct ecc_keypair), tee_cryp_obj_sm2_keypair_attrs), PROP(TEE_TYPE_SM2_KEP_PUBLIC_KEY, 1, 256, 256, sizeof(struct ecc_public_key), tee_cryp_obj_sm2_pub_key_attrs), PROP(TEE_TYPE_SM2_KEP_KEYPAIR, 1, 256, 256, sizeof(struct ecc_keypair), tee_cryp_obj_sm2_keypair_attrs), PROP(TEE_TYPE_X25519_KEYPAIR, 1, 256, 256, sizeof(struct montgomery_keypair), tee_cryp_obj_x25519_keypair_attrs), PROP(TEE_TYPE_X448_KEYPAIR, 1, 448, 448, sizeof(struct montgomery_keypair), tee_cryp_obj_x448_keypair_attrs), PROP(TEE_TYPE_ED25519_PUBLIC_KEY, 1, 256, 256, sizeof(struct ed25519_public_key), tee_cryp_obj_ed25519_pub_key_attrs), PROP(TEE_TYPE_ED25519_KEYPAIR, 1, 256, 256, sizeof(struct ed25519_keypair), tee_cryp_obj_ed25519_keypair_attrs), }; struct attr_ops { TEE_Result (*from_user)(void *attr, const void *buffer, size_t size); TEE_Result (*to_user)(void *attr, struct ts_session *sess, void *buffer, uint64_t *size); TEE_Result (*to_binary)(void *attr, void *data, size_t data_len, size_t *offs); bool (*from_binary)(void *attr, const void *data, size_t data_len, size_t *offs); TEE_Result (*from_obj)(void *attr, void *src_attr); void (*free)(void *attr); void (*clear)(void *attr); }; static TEE_Result op_u32_to_binary_helper(uint32_t v, uint8_t *data, size_t data_len, size_t *offs) { uint32_t field; size_t next_offs; if (ADD_OVERFLOW(*offs, sizeof(field), &next_offs)) return TEE_ERROR_OVERFLOW; if (data && next_offs <= data_len) { field = TEE_U32_TO_BIG_ENDIAN(v); memcpy(data + *offs, &field, sizeof(field)); } (*offs) = next_offs; return TEE_SUCCESS; } static bool op_u32_from_binary_helper(uint32_t *v, const uint8_t *data, size_t data_len, size_t *offs) { uint32_t field; if (!data || (*offs + sizeof(field)) > data_len) return false; memcpy(&field, data + *offs, sizeof(field)); *v = TEE_U32_FROM_BIG_ENDIAN(field); (*offs) += sizeof(field); return true; } static TEE_Result op_attr_secret_value_from_user(void *attr, const void *buffer, size_t size) { TEE_Result res = TEE_SUCCESS; struct tee_cryp_obj_secret *key = attr; /* Data size has to fit in allocated buffer */ if (size > key->alloc_size) return TEE_ERROR_SECURITY; res = copy_from_user(key + 1, buffer, size); if (!res) key->key_size = size; return res; } static TEE_Result op_attr_secret_value_to_user(void *attr, struct ts_session *sess __unused, void *buffer, uint64_t *size) { TEE_Result res; struct tee_cryp_obj_secret *key = attr; uint64_t s; uint64_t key_size; res = copy_from_user(&s, size, sizeof(s)); if (res != TEE_SUCCESS) return res; key_size = key->key_size; res = copy_to_user(size, &key_size, sizeof(key_size)); if (res != TEE_SUCCESS) return res; if (s < key->key_size || !buffer) return TEE_ERROR_SHORT_BUFFER; return copy_to_user(buffer, key + 1, key->key_size); } static TEE_Result op_attr_secret_value_to_binary(void *attr, void *data, size_t data_len, size_t *offs) { TEE_Result res; struct tee_cryp_obj_secret *key = attr; size_t next_offs; res = op_u32_to_binary_helper(key->key_size, data, data_len, offs); if (res != TEE_SUCCESS) return res; if (ADD_OVERFLOW(*offs, key->key_size, &next_offs)) return TEE_ERROR_OVERFLOW; if (data && next_offs <= data_len) memcpy((uint8_t *)data + *offs, key + 1, key->key_size); (*offs) = next_offs; return TEE_SUCCESS; } static bool op_attr_secret_value_from_binary(void *attr, const void *data, size_t data_len, size_t *offs) { struct tee_cryp_obj_secret *key = attr; uint32_t s; if (!op_u32_from_binary_helper(&s, data, data_len, offs)) return false; if ((*offs + s) > data_len) return false; /* Data size has to fit in allocated buffer */ if (s > key->alloc_size) return false; key->key_size = s; memcpy(key + 1, (const uint8_t *)data + *offs, s); (*offs) += s; return true; } static TEE_Result op_attr_secret_value_from_obj(void *attr, void *src_attr) { struct tee_cryp_obj_secret *key = attr; struct tee_cryp_obj_secret *src_key = src_attr; if (src_key->key_size > key->alloc_size) return TEE_ERROR_BAD_STATE; memcpy(key + 1, src_key + 1, src_key->key_size); key->key_size = src_key->key_size; return TEE_SUCCESS; } static void op_attr_secret_value_clear(void *attr) { struct tee_cryp_obj_secret *key = attr; key->key_size = 0; memzero_explicit(key + 1, key->alloc_size); } static TEE_Result op_attr_bignum_from_user(void *attr, const void *buffer, size_t size) { TEE_Result res = TEE_SUCCESS; struct bignum **bn = attr; void *bbuf = NULL; res = bb_memdup_user(buffer, size, &bbuf); if (res) return res; res = crypto_bignum_bin2bn(bbuf, size, *bn); bb_free(bbuf, size); return res; } static TEE_Result op_attr_bignum_to_user(void *attr, struct ts_session *sess __unused, void *buffer, uint64_t *size) { TEE_Result res = TEE_SUCCESS; struct bignum **bn = attr; uint64_t req_size = 0; uint64_t s = 0; void *bbuf = NULL; res = copy_from_user(&s, size, sizeof(s)); if (res != TEE_SUCCESS) return res; req_size = crypto_bignum_num_bytes(*bn); res = copy_to_user(size, &req_size, sizeof(req_size)); if (res != TEE_SUCCESS) return res; if (!req_size) return TEE_SUCCESS; if (s < req_size || !buffer) return TEE_ERROR_SHORT_BUFFER; bbuf = bb_alloc(req_size); if (!bbuf) return TEE_ERROR_OUT_OF_MEMORY; /* * Write the bignum (wich raw data points to) into an array of * bytes (stored in buffer) */ crypto_bignum_bn2bin(*bn, bbuf); res = copy_to_user(buffer, bbuf, req_size); bb_free(bbuf, req_size); return res; } static TEE_Result op_attr_bignum_to_binary(void *attr, void *data, size_t data_len, size_t *offs) { TEE_Result res; struct bignum **bn = attr; uint32_t n = crypto_bignum_num_bytes(*bn); size_t next_offs; res = op_u32_to_binary_helper(n, data, data_len, offs); if (res != TEE_SUCCESS) return res; if (ADD_OVERFLOW(*offs, n, &next_offs)) return TEE_ERROR_OVERFLOW; if (data && next_offs <= data_len) crypto_bignum_bn2bin(*bn, (uint8_t *)data + *offs); (*offs) = next_offs; return TEE_SUCCESS; } static bool op_attr_bignum_from_binary(void *attr, const void *data, size_t data_len, size_t *offs) { struct bignum **bn = attr; uint32_t n; if (!op_u32_from_binary_helper(&n, data, data_len, offs)) return false; if ((*offs + n) > data_len) return false; if (crypto_bignum_bin2bn((const uint8_t *)data + *offs, n, *bn)) return false; (*offs) += n; return true; } static TEE_Result op_attr_bignum_from_obj(void *attr, void *src_attr) { struct bignum **bn = attr; struct bignum **src_bn = src_attr; crypto_bignum_copy(*bn, *src_bn); return TEE_SUCCESS; } static void op_attr_bignum_clear(void *attr) { struct bignum **bn = attr; crypto_bignum_clear(*bn); } static void op_attr_bignum_free(void *attr) { struct bignum **bn = attr; crypto_bignum_free(bn); } static TEE_Result op_attr_value_from_user(void *attr, const void *buffer, size_t size) { uint32_t *v = attr; if (size != sizeof(uint32_t) * 2) return TEE_ERROR_GENERIC; /* "can't happen */ /* Note that only the first value is copied */ memcpy(v, buffer, sizeof(uint32_t)); return TEE_SUCCESS; } static TEE_Result op_attr_value_to_user(void *attr, struct ts_session *sess __unused, void *buffer, uint64_t *size) { TEE_Result res; uint32_t *v = attr; uint64_t s; uint32_t value[2] = { *v }; uint64_t req_size = sizeof(value); res = copy_from_user(&s, size, sizeof(s)); if (res != TEE_SUCCESS) return res; if (s < req_size || !buffer) return TEE_ERROR_SHORT_BUFFER; return copy_to_user(buffer, value, req_size); } static TEE_Result op_attr_value_to_binary(void *attr, void *data, size_t data_len, size_t *offs) { uint32_t *v = attr; return op_u32_to_binary_helper(*v, data, data_len, offs); } static bool op_attr_value_from_binary(void *attr, const void *data, size_t data_len, size_t *offs) { uint32_t *v = attr; return op_u32_from_binary_helper(v, data, data_len, offs); } static TEE_Result op_attr_value_from_obj(void *attr, void *src_attr) { uint32_t *v = attr; uint32_t *src_v = src_attr; *v = *src_v; return TEE_SUCCESS; } static void op_attr_value_clear(void *attr) { uint32_t *v = attr; *v = 0; } static TEE_Result op_attr_25519_from_user(void *attr, const void *buffer, size_t size) { uint8_t **key = attr; if (size != KEY_SIZE_BYTES_25519 || !*key) return TEE_ERROR_SECURITY; return copy_from_user(*key, buffer, size); } static TEE_Result op_attr_25519_to_user(void *attr, struct ts_session *sess __unused, void *buffer, uint64_t *size) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t **key = attr; uint64_t s = 0; uint64_t key_size = (uint64_t)KEY_SIZE_BYTES_25519; res = copy_from_user(&s, size, sizeof(s)); if (res != TEE_SUCCESS) return res; res = copy_to_user(size, &key_size, sizeof(key_size)); if (res != TEE_SUCCESS) return res; if (s < key_size || !buffer) return TEE_ERROR_SHORT_BUFFER; return copy_to_user(buffer, *key, key_size); } static TEE_Result op_attr_25519_to_binary(void *attr, void *data, size_t data_len, size_t *offs) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t **key = attr; size_t next_offs = 0; uint64_t key_size = (uint64_t)KEY_SIZE_BYTES_25519; res = op_u32_to_binary_helper(key_size, data, data_len, offs); if (res != TEE_SUCCESS) return res; if (ADD_OVERFLOW(*offs, key_size, &next_offs)) return TEE_ERROR_OVERFLOW; if (data && next_offs <= data_len) memcpy((uint8_t *)data + *offs, *key, key_size); *offs = next_offs; return TEE_SUCCESS; } static bool op_attr_25519_from_binary(void *attr, const void *data, size_t data_len, size_t *offs) { uint8_t **key = attr; uint32_t s = 0; if (!op_u32_from_binary_helper(&s, data, data_len, offs)) return false; if (*offs + s > data_len) return false; if (s > (uint32_t)KEY_SIZE_BYTES_25519) return false; memcpy(*key, (const uint8_t *)data + *offs, s); *offs += s; return true; } static TEE_Result op_attr_25519_from_obj(void *attr, void *src_attr) { uint8_t **key = attr; uint8_t **src_key = src_attr; if (!*key || !*src_key) return TEE_ERROR_SECURITY; memcpy(*key, *src_key, KEY_SIZE_BYTES_25519); return TEE_SUCCESS; } static void op_attr_25519_clear(void *attr) { uint8_t **key = attr; assert(*key); memzero_explicit(*key, KEY_SIZE_BYTES_25519); } static void op_attr_25519_free(void *attr) { uint8_t **key = attr; op_attr_25519_clear(attr); free(*key); } static const struct attr_ops attr_ops[] = { [ATTR_OPS_INDEX_SECRET] = { .from_user = op_attr_secret_value_from_user, .to_user = op_attr_secret_value_to_user, .to_binary = op_attr_secret_value_to_binary, .from_binary = op_attr_secret_value_from_binary, .from_obj = op_attr_secret_value_from_obj, .free = op_attr_secret_value_clear, /* not a typo */ .clear = op_attr_secret_value_clear, }, [ATTR_OPS_INDEX_BIGNUM] = { .from_user = op_attr_bignum_from_user, .to_user = op_attr_bignum_to_user, .to_binary = op_attr_bignum_to_binary, .from_binary = op_attr_bignum_from_binary, .from_obj = op_attr_bignum_from_obj, .free = op_attr_bignum_free, .clear = op_attr_bignum_clear, }, [ATTR_OPS_INDEX_VALUE] = { .from_user = op_attr_value_from_user, .to_user = op_attr_value_to_user, .to_binary = op_attr_value_to_binary, .from_binary = op_attr_value_from_binary, .from_obj = op_attr_value_from_obj, .free = op_attr_value_clear, /* not a typo */ .clear = op_attr_value_clear, }, [ATTR_OPS_INDEX_25519] = { .from_user = op_attr_25519_from_user, .to_user = op_attr_25519_to_user, .to_binary = op_attr_25519_to_binary, .from_binary = op_attr_25519_from_binary, .from_obj = op_attr_25519_from_obj, .free = op_attr_25519_free, .clear = op_attr_25519_clear, }, }; static TEE_Result get_user_u64_as_size_t(size_t *dst, uint64_t *src) { uint64_t d = 0; TEE_Result res = copy_from_user(&d, src, sizeof(d)); /* * On 32-bit systems a size_t can't hold a uint64_t so we need to * check that the value isn't too large. */ if (!res && ADD_OVERFLOW(0, d, dst)) return TEE_ERROR_OVERFLOW; return res; } static TEE_Result put_user_u64(uint64_t *dst, size_t value) { uint64_t v = value; return copy_to_user(dst, &v, sizeof(v)); } TEE_Result syscall_cryp_obj_get_info(unsigned long obj, struct utee_object_info *info) { struct ts_session *sess = ts_get_current_session(); struct utee_object_info o_info = { }; TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) goto exit; o_info.obj_type = o->info.objectType; o_info.obj_size = o->info.objectSize; o_info.max_obj_size = o->info.maxObjectSize; if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { tee_pobj_lock_usage(o->pobj); o_info.obj_usage = o->pobj->obj_info_usage; tee_pobj_unlock_usage(o->pobj); } else { o_info.obj_usage = o->info.objectUsage; } o_info.data_size = o->info.dataSize; o_info.data_pos = o->info.dataPosition; o_info.handle_flags = o->info.handleFlags; res = copy_to_user_private(info, &o_info, sizeof(o_info)); exit: return res; } TEE_Result syscall_cryp_obj_restrict_usage(unsigned long obj, unsigned long usage) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res) return res; if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { uint32_t new_usage = 0; tee_pobj_lock_usage(o->pobj); new_usage = o->pobj->obj_info_usage & usage; res = tee_svc_storage_write_usage(o, new_usage); if (!res) o->pobj->obj_info_usage = new_usage; tee_pobj_unlock_usage(o->pobj); } else { o->info.objectUsage &= usage; } return res; } static int tee_svc_cryp_obj_find_type_attr_idx( uint32_t attr_id, const struct tee_cryp_obj_type_props *type_props) { size_t n; for (n = 0; n < type_props->num_type_attrs; n++) { if (attr_id == type_props->type_attrs[n].attr_id) return n; } return -1; } static const struct tee_cryp_obj_type_props *tee_svc_find_type_props( TEE_ObjectType obj_type) { size_t n; for (n = 0; n < ARRAY_SIZE(tee_cryp_obj_props); n++) { if (tee_cryp_obj_props[n].obj_type == obj_type) return tee_cryp_obj_props + n; } return NULL; } /* Set an attribute on an object */ static void set_attribute(struct tee_obj *o, const struct tee_cryp_obj_type_props *props, uint32_t attr) { int idx = tee_svc_cryp_obj_find_type_attr_idx(attr, props); if (idx < 0) return; o->have_attrs |= BIT(idx); } /* Get an attribute on an object */ static uint32_t get_attribute(const struct tee_obj *o, const struct tee_cryp_obj_type_props *props, uint32_t attr) { int idx = tee_svc_cryp_obj_find_type_attr_idx(attr, props); if (idx < 0) return 0; return o->have_attrs & BIT(idx); } TEE_Result syscall_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, void *buffer, uint64_t *size) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; const struct tee_cryp_obj_type_props *type_props = NULL; int idx = 0; const struct attr_ops *ops = NULL; void *attr = NULL; uint32_t obj_usage = 0; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return TEE_ERROR_ITEM_NOT_FOUND; /* Check that the object is initialized */ if (!(o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) return TEE_ERROR_BAD_PARAMETERS; /* Check that getting the attribute is allowed */ if (!(attr_id & TEE_ATTR_FLAG_PUBLIC)) { if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { tee_pobj_lock_usage(o->pobj); obj_usage = o->pobj->obj_info_usage; tee_pobj_unlock_usage(o->pobj); } else { obj_usage = o->info.objectUsage; } if (!(obj_usage & TEE_USAGE_EXTRACTABLE)) return TEE_ERROR_BAD_PARAMETERS; } type_props = tee_svc_find_type_props(o->info.objectType); if (!type_props) { /* Unknown object type, "can't happen" */ return TEE_ERROR_BAD_STATE; } idx = tee_svc_cryp_obj_find_type_attr_idx(attr_id, type_props); if ((idx < 0) || ((o->have_attrs & (1 << idx)) == 0)) return TEE_ERROR_ITEM_NOT_FOUND; ops = attr_ops + type_props->type_attrs[idx].ops_index; attr = (uint8_t *)o->attr + type_props->type_attrs[idx].raw_offs; return ops->to_user(attr, sess, buffer, size); } void tee_obj_attr_free(struct tee_obj *o) { const struct tee_cryp_obj_type_props *tp; size_t n; if (!o->attr) return; tp = tee_svc_find_type_props(o->info.objectType); if (!tp) return; for (n = 0; n < tp->num_type_attrs; n++) { const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; attr_ops[ta->ops_index].free((uint8_t *)o->attr + ta->raw_offs); } } void tee_obj_attr_clear(struct tee_obj *o) { const struct tee_cryp_obj_type_props *tp; size_t n; if (!o->attr) return; tp = tee_svc_find_type_props(o->info.objectType); if (!tp) return; for (n = 0; n < tp->num_type_attrs; n++) { const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; attr_ops[ta->ops_index].clear((uint8_t *)o->attr + ta->raw_offs); } } TEE_Result tee_obj_attr_to_binary(struct tee_obj *o, void *data, size_t *data_len) { const struct tee_cryp_obj_type_props *tp; size_t n; size_t offs = 0; size_t len = data ? *data_len : 0; TEE_Result res; if (o->info.objectType == TEE_TYPE_DATA) { *data_len = 0; return TEE_SUCCESS; /* pure data object */ } if (!o->attr) return TEE_ERROR_BAD_STATE; tp = tee_svc_find_type_props(o->info.objectType); if (!tp) return TEE_ERROR_BAD_STATE; for (n = 0; n < tp->num_type_attrs; n++) { const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; void *attr = (uint8_t *)o->attr + ta->raw_offs; res = attr_ops[ta->ops_index].to_binary(attr, data, len, &offs); if (res != TEE_SUCCESS) return res; } *data_len = offs; if (data && offs > len) return TEE_ERROR_SHORT_BUFFER; return TEE_SUCCESS; } TEE_Result tee_obj_attr_from_binary(struct tee_obj *o, const void *data, size_t data_len) { const struct tee_cryp_obj_type_props *tp; size_t n; size_t offs = 0; if (o->info.objectType == TEE_TYPE_DATA) return TEE_SUCCESS; /* pure data object */ if (!o->attr) return TEE_ERROR_BAD_STATE; tp = tee_svc_find_type_props(o->info.objectType); if (!tp) return TEE_ERROR_BAD_STATE; for (n = 0; n < tp->num_type_attrs; n++) { const struct tee_cryp_obj_type_attrs *ta = tp->type_attrs + n; void *attr = (uint8_t *)o->attr + ta->raw_offs; if (!attr_ops[ta->ops_index].from_binary(attr, data, data_len, &offs)) return TEE_ERROR_CORRUPT_OBJECT; } return TEE_SUCCESS; } TEE_Result tee_obj_attr_copy_from(struct tee_obj *o, const struct tee_obj *src) { TEE_Result res; const struct tee_cryp_obj_type_props *tp; const struct tee_cryp_obj_type_attrs *ta; size_t n; uint32_t have_attrs = 0; void *attr; void *src_attr; if (o->info.objectType == TEE_TYPE_DATA) return TEE_SUCCESS; /* pure data object */ if (!o->attr) return TEE_ERROR_BAD_STATE; tp = tee_svc_find_type_props(o->info.objectType); if (!tp) return TEE_ERROR_BAD_STATE; if (o->info.objectType == src->info.objectType) { have_attrs = src->have_attrs; for (n = 0; n < tp->num_type_attrs; n++) { ta = tp->type_attrs + n; attr = (uint8_t *)o->attr + ta->raw_offs; src_attr = (uint8_t *)src->attr + ta->raw_offs; res = attr_ops[ta->ops_index].from_obj(attr, src_attr); if (res != TEE_SUCCESS) return res; } } else { const struct tee_cryp_obj_type_props *tp_src; int idx; if (o->info.objectType == TEE_TYPE_RSA_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_RSA_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_DSA_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_DSA_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_ECDSA_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_ECDSA_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_ECDH_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_ECDH_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_SM2_DSA_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_SM2_DSA_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_SM2_PKE_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_SM2_PKE_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_SM2_KEP_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_SM2_KEP_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_ED25519_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_ED25519_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_X25519_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_X25519_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else if (o->info.objectType == TEE_TYPE_X448_PUBLIC_KEY) { if (src->info.objectType != TEE_TYPE_X448_KEYPAIR) return TEE_ERROR_BAD_PARAMETERS; } else { return TEE_ERROR_BAD_PARAMETERS; } tp_src = tee_svc_find_type_props(src->info.objectType); if (!tp_src) return TEE_ERROR_BAD_STATE; have_attrs = BIT32(tp->num_type_attrs) - 1; for (n = 0; n < tp->num_type_attrs; n++) { ta = tp->type_attrs + n; idx = tee_svc_cryp_obj_find_type_attr_idx(ta->attr_id, tp_src); if (idx < 0) return TEE_ERROR_BAD_STATE; attr = (uint8_t *)o->attr + ta->raw_offs; src_attr = (uint8_t *)src->attr + tp_src->type_attrs[idx].raw_offs; res = attr_ops[ta->ops_index].from_obj(attr, src_attr); if (res != TEE_SUCCESS) return res; } } o->have_attrs = have_attrs; return TEE_SUCCESS; } static bool is_gp_legacy_des_key_size(TEE_ObjectType type, size_t sz) { return IS_ENABLED(CFG_COMPAT_GP10_DES) && ((type == TEE_TYPE_DES && sz == 56) || (type == TEE_TYPE_DES3 && (sz == 112 || sz == 168))); } static TEE_Result check_key_size(const struct tee_cryp_obj_type_props *props, size_t key_size) { size_t sz = key_size; /* * In GP Internal API Specification 1.0 the partity bits aren't * counted when telling the size of the key in bits so add them * here if missing. */ if (is_gp_legacy_des_key_size(props->obj_type, sz)) sz += sz / 7; if (sz % props->quanta != 0) return TEE_ERROR_NOT_SUPPORTED; if (sz < props->min_size) return TEE_ERROR_NOT_SUPPORTED; if (sz > props->max_size) return TEE_ERROR_NOT_SUPPORTED; return TEE_SUCCESS; } TEE_Result tee_obj_set_type(struct tee_obj *o, uint32_t obj_type, size_t max_key_size) { TEE_Result res = TEE_SUCCESS; const struct tee_cryp_obj_type_props *type_props; /* Can only set type for newly allocated objs */ if (o->attr) return TEE_ERROR_BAD_STATE; /* * Verify that maxObjectSize is supported and find out how * much should be allocated. */ if (obj_type == TEE_TYPE_DATA) { if (max_key_size) return TEE_ERROR_NOT_SUPPORTED; } else { /* Find description of object */ type_props = tee_svc_find_type_props(obj_type); if (!type_props) return TEE_ERROR_NOT_SUPPORTED; /* Check that max_key_size follows restrictions */ res = check_key_size(type_props, max_key_size); if (res) return res; o->attr = calloc(1, type_props->alloc_size); if (!o->attr) return TEE_ERROR_OUT_OF_MEMORY; } /* If we have a key structure, pre-allocate the bignums inside */ switch (obj_type) { case TEE_TYPE_RSA_PUBLIC_KEY: res = crypto_acipher_alloc_rsa_public_key(o->attr, max_key_size); break; case TEE_TYPE_RSA_KEYPAIR: res = crypto_acipher_alloc_rsa_keypair(o->attr, max_key_size); break; case TEE_TYPE_DSA_PUBLIC_KEY: res = crypto_acipher_alloc_dsa_public_key(o->attr, max_key_size); break; case TEE_TYPE_DSA_KEYPAIR: res = crypto_acipher_alloc_dsa_keypair(o->attr, max_key_size); break; case TEE_TYPE_DH_KEYPAIR: res = crypto_acipher_alloc_dh_keypair(o->attr, max_key_size); break; case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDH_PUBLIC_KEY: case TEE_TYPE_SM2_DSA_PUBLIC_KEY: case TEE_TYPE_SM2_PKE_PUBLIC_KEY: case TEE_TYPE_SM2_KEP_PUBLIC_KEY: res = crypto_acipher_alloc_ecc_public_key(o->attr, obj_type, max_key_size); break; case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: case TEE_TYPE_SM2_DSA_KEYPAIR: case TEE_TYPE_SM2_PKE_KEYPAIR: case TEE_TYPE_SM2_KEP_KEYPAIR: res = crypto_acipher_alloc_ecc_keypair(o->attr, obj_type, max_key_size); break; case TEE_TYPE_X25519_KEYPAIR: res = crypto_acipher_alloc_x25519_keypair(o->attr, max_key_size); break; case TEE_TYPE_X448_KEYPAIR: res = crypto_acipher_alloc_x448_keypair(o->attr, max_key_size); break; case TEE_TYPE_ED25519_KEYPAIR: res = crypto_acipher_alloc_ed25519_keypair(o->attr, max_key_size); break; case TEE_TYPE_ED25519_PUBLIC_KEY: res = crypto_acipher_alloc_ed25519_public_key(o->attr, max_key_size); break; default: if (obj_type != TEE_TYPE_DATA) { struct tee_cryp_obj_secret *key = o->attr; key->alloc_size = type_props->alloc_size - sizeof(*key); } break; } if (res != TEE_SUCCESS) return res; o->info.objectType = obj_type; o->info.maxObjectSize = max_key_size; if (o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) o->pobj->obj_info_usage = TEE_USAGE_DEFAULT; else o->info.objectUsage = TEE_USAGE_DEFAULT; return TEE_SUCCESS; } TEE_Result syscall_cryp_obj_alloc(unsigned long obj_type, unsigned long max_key_size, uint32_t *obj) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; o = tee_obj_alloc(); if (!o) return TEE_ERROR_OUT_OF_MEMORY; res = tee_obj_set_type(o, obj_type, max_key_size); if (res != TEE_SUCCESS) { tee_obj_free(o); return res; } tee_obj_add(to_user_ta_ctx(sess->ctx), o); res = copy_kaddr_to_uref(obj, o); if (res != TEE_SUCCESS) tee_obj_close(to_user_ta_ctx(sess->ctx), o); return res; } TEE_Result syscall_cryp_obj_close(unsigned long obj) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; /* * If it's busy it's used by an operation, a client should never have * this handle. */ if (o->busy) return TEE_ERROR_ITEM_NOT_FOUND; tee_obj_close(to_user_ta_ctx(sess->ctx), o); return TEE_SUCCESS; } TEE_Result syscall_cryp_obj_reset(unsigned long obj) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) == 0) { tee_obj_attr_clear(o); o->info.objectSize = 0; o->info.objectUsage = TEE_USAGE_DEFAULT; } else { return TEE_ERROR_BAD_PARAMETERS; } /* the object is no more initialized */ o->info.handleFlags &= ~TEE_HANDLE_FLAG_INITIALIZED; return TEE_SUCCESS; } static TEE_Result copy_in_attrs(struct user_ta_ctx *utc, const struct utee_attribute *usr_attrs, uint32_t attr_count, TEE_Attribute *attrs) { TEE_Result res = TEE_SUCCESS; size_t size = 0; uint32_t n = 0; struct utee_attribute *usr_attrs_bbuf = NULL; if (MUL_OVERFLOW(sizeof(struct utee_attribute), attr_count, &size)) return TEE_ERROR_OVERFLOW; usr_attrs_bbuf = bb_alloc(size); if (!usr_attrs_bbuf) return TEE_ERROR_OUT_OF_MEMORY; res = copy_from_user(usr_attrs_bbuf, usr_attrs, size); if (res) goto out; for (n = 0; n < attr_count; n++) { attrs[n].attributeID = usr_attrs_bbuf[n].attribute_id; if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { attrs[n].content.value.a = usr_attrs_bbuf[n].a; attrs[n].content.value.b = usr_attrs_bbuf[n].b; } else { uintptr_t buf = usr_attrs_bbuf[n].a; size_t len = usr_attrs_bbuf[n].b; uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; buf = memtag_strip_tag_vaddr((void *)buf); res = vm_check_access_rights(&utc->uctx, flags, buf, len); if (res != TEE_SUCCESS) goto out; attrs[n].content.ref.buffer = (void *)buf; attrs[n].content.ref.length = len; } } out: bb_free(usr_attrs_bbuf, size); return res; } enum attr_usage { ATTR_USAGE_POPULATE, ATTR_USAGE_GENERATE_KEY }; static TEE_Result tee_svc_cryp_check_attr(enum attr_usage usage, const struct tee_cryp_obj_type_props *type_props, const TEE_Attribute *attrs, uint32_t attr_count) { uint32_t required_flag = 0; uint32_t opt_flag = 0; bool all_opt_needed = false; uint32_t req_attrs = 0; uint32_t opt_grp_attrs = 0; uint32_t attrs_found = 0; size_t n = 0; uint32_t bit = 0; uint32_t flags = 0; int idx = 0; if (usage == ATTR_USAGE_POPULATE) { required_flag = TEE_TYPE_ATTR_REQUIRED; opt_flag = TEE_TYPE_ATTR_OPTIONAL_GROUP; all_opt_needed = true; } else { required_flag = TEE_TYPE_ATTR_GEN_KEY_REQ; opt_flag = TEE_TYPE_ATTR_GEN_KEY_OPT; all_opt_needed = false; } /* * First find out which attributes are required and which belong to * the optional group */ for (n = 0; n < type_props->num_type_attrs; n++) { bit = 1 << n; flags = type_props->type_attrs[n].flags; if (flags & required_flag) req_attrs |= bit; else if (flags & opt_flag) opt_grp_attrs |= bit; } /* * Verify that all required attributes are in place and * that the same attribute isn't repeated. */ for (n = 0; n < attr_count; n++) { idx = tee_svc_cryp_obj_find_type_attr_idx( attrs[n].attributeID, type_props); /* attribute not defined in current object type */ if (idx < 0) return TEE_ERROR_ITEM_NOT_FOUND; bit = 1 << idx; /* attribute not repeated */ if ((attrs_found & bit) != 0) return TEE_ERROR_ITEM_NOT_FOUND; /* * Attribute not defined in current object type for this * usage. */ if (!(bit & (req_attrs | opt_grp_attrs))) return TEE_ERROR_ITEM_NOT_FOUND; attrs_found |= bit; } /* Required attribute missing */ if ((attrs_found & req_attrs) != req_attrs) return TEE_ERROR_ITEM_NOT_FOUND; /* * If the flag says that "if one of the optional attributes are included * all of them has to be included" this must be checked. */ if (all_opt_needed && (attrs_found & opt_grp_attrs) != 0 && (attrs_found & opt_grp_attrs) != opt_grp_attrs) return TEE_ERROR_ITEM_NOT_FOUND; return TEE_SUCCESS; } static TEE_Result get_ec_key_size(uint32_t curve, size_t *key_size) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: *key_size = 192; break; case TEE_ECC_CURVE_NIST_P224: *key_size = 224; break; case TEE_ECC_CURVE_NIST_P256: *key_size = 256; break; case TEE_ECC_CURVE_NIST_P384: *key_size = 384; break; case TEE_ECC_CURVE_NIST_P521: *key_size = 521; break; case TEE_ECC_CURVE_SM2: case TEE_ECC_CURVE_25519: *key_size = 256; break; default: return TEE_ERROR_NOT_SUPPORTED; } return TEE_SUCCESS; } static TEE_Result tee_svc_cryp_obj_populate_type( struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, const TEE_Attribute *attrs, uint32_t attr_count) { TEE_Result res = TEE_SUCCESS; uint32_t have_attrs = 0; size_t obj_size = 0; size_t n = 0; int idx = 0; const struct attr_ops *ops = NULL; void *attr = NULL; for (n = 0; n < attr_count; n++) { idx = tee_svc_cryp_obj_find_type_attr_idx( attrs[n].attributeID, type_props); /* attribute not defined in current object type */ if (idx < 0) return TEE_ERROR_ITEM_NOT_FOUND; have_attrs |= BIT32(idx); ops = attr_ops + type_props->type_attrs[idx].ops_index; attr = (uint8_t *)o->attr + type_props->type_attrs[idx].raw_offs; if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) res = ops->from_user(attr, &attrs[n].content.value, sizeof(attrs[n].content.value)); else res = ops->from_user(attr, attrs[n].content.ref.buffer, attrs[n].content.ref.length); if (res != TEE_SUCCESS) return res; /* * The attribute that gives the size of the object is * flagged with TEE_TYPE_ATTR_SIZE_INDICATOR. */ if (type_props->type_attrs[idx].flags & TEE_TYPE_ATTR_SIZE_INDICATOR) { /* There should be only one */ if (obj_size) return TEE_ERROR_BAD_STATE; /* * For ECDSA/ECDH we need to translate curve into * object size */ if (attrs[n].attributeID == TEE_ATTR_ECC_CURVE) { res = get_ec_key_size(attrs[n].content.value.a, &obj_size); if (res != TEE_SUCCESS) return res; } else { TEE_ObjectType obj_type = o->info.objectType; size_t sz = o->info.maxObjectSize; obj_size = attrs[n].content.ref.length * 8; /* Drop the parity bits for legacy objects */ if (is_gp_legacy_des_key_size(obj_type, sz)) obj_size -= obj_size / 8; } if (obj_size > o->info.maxObjectSize) return TEE_ERROR_BAD_STATE; res = check_key_size(type_props, obj_size); if (res != TEE_SUCCESS) return TEE_ERROR_BAD_PARAMETERS; } /* * Bignum attributes limited by the number of bits in * o->info.objectSize are flagged with * TEE_TYPE_ATTR_BIGNUM_MAXBITS. */ if (type_props->type_attrs[idx].flags & TEE_TYPE_ATTR_BIGNUM_MAXBITS) { if (crypto_bignum_num_bits(*(struct bignum **)attr) > o->info.maxObjectSize) return TEE_ERROR_BAD_STATE; } } o->have_attrs = have_attrs; o->info.objectSize = obj_size; /* * In GP Internal API Specification 1.0 the partity bits aren't * counted when telling the size of the key in bits so remove the * parity bits here. */ if (is_gp_legacy_des_key_size(o->info.objectType, o->info.maxObjectSize)) o->info.objectSize -= o->info.objectSize / 8; return TEE_SUCCESS; } TEE_Result syscall_cryp_obj_populate(unsigned long obj, struct utee_attribute *usr_attrs, unsigned long attr_count) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; const struct tee_cryp_obj_type_props *type_props = NULL; TEE_Attribute *attrs = NULL; size_t alloc_size = 0; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; /* Must be a transient object */ if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) return TEE_ERROR_BAD_PARAMETERS; /* Must not be initialized already */ if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) return TEE_ERROR_BAD_PARAMETERS; type_props = tee_svc_find_type_props(o->info.objectType); if (!type_props) return TEE_ERROR_NOT_IMPLEMENTED; if (MUL_OVERFLOW(sizeof(TEE_Attribute), attr_count, &alloc_size)) return TEE_ERROR_OVERFLOW; attrs = malloc(alloc_size); if (!attrs) return TEE_ERROR_OUT_OF_MEMORY; res = copy_in_attrs(to_user_ta_ctx(sess->ctx), usr_attrs, attr_count, attrs); if (res != TEE_SUCCESS) goto out; res = tee_svc_cryp_check_attr(ATTR_USAGE_POPULATE, type_props, attrs, attr_count); if (res != TEE_SUCCESS) goto out; res = tee_svc_cryp_obj_populate_type(o, type_props, attrs, attr_count); if (res == TEE_SUCCESS) o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; out: free_wipe(attrs); return res; } TEE_Result syscall_cryp_obj_copy(unsigned long dst, unsigned long src) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *dst_o = NULL; struct tee_obj *src_o = NULL; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(dst), &dst_o); if (res != TEE_SUCCESS) return res; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(src), &src_o); if (res != TEE_SUCCESS) return res; if ((src_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) return TEE_ERROR_BAD_PARAMETERS; if ((dst_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) return TEE_ERROR_BAD_PARAMETERS; if ((dst_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) return TEE_ERROR_BAD_PARAMETERS; res = tee_obj_attr_copy_from(dst_o, src_o); if (res != TEE_SUCCESS) return res; dst_o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; dst_o->info.objectSize = src_o->info.objectSize; if (src_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) { tee_pobj_lock_usage(src_o->pobj); dst_o->info.objectUsage = src_o->pobj->obj_info_usage; tee_pobj_unlock_usage(src_o->pobj); } else { dst_o->info.objectUsage = src_o->info.objectUsage; } return TEE_SUCCESS; } static TEE_Result check_pub_rsa_key(struct bignum *e) { size_t n = crypto_bignum_num_bytes(e); uint8_t bin_key[256 / 8] = { 0 }; /* * NIST SP800-56B requires public RSA key to be an odd integer in * the range 65537 <= e < 2^256. AOSP requires implementations to * support public exponents >= 3, which can be allowed by enabling * CFG_RSA_PUB_EXPONENT_3. */ if (n > sizeof(bin_key) || n < 1) return TEE_ERROR_BAD_PARAMETERS; crypto_bignum_bn2bin(e, bin_key); if (!(bin_key[n - 1] & 1)) /* key must be odd */ return TEE_ERROR_BAD_PARAMETERS; if (n <= 3) { uint32_t min_key = 65537; uint32_t key = 0; size_t m = 0; if (IS_ENABLED(CFG_RSA_PUB_EXPONENT_3)) min_key = 3; for (m = 0; m < n; m++) { key <<= 8; key |= bin_key[m]; } if (key < min_key) return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_rsa( struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res = TEE_SUCCESS; struct rsa_keypair *key = o->attr; uint32_t e = TEE_U32_TO_BIG_ENDIAN(65537); /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; if (get_attribute(o, type_props, TEE_ATTR_RSA_PUBLIC_EXPONENT)) { res = check_pub_rsa_key(key->e); if (res) return res; } else { res = crypto_bignum_bin2bn((const uint8_t *)&e, sizeof(e), key->e); if (res) return res; } res = crypto_acipher_gen_rsa_key(key, key_size); if (res != TEE_SUCCESS) return res; /* Set bits for all known attributes for this object type */ o->have_attrs = (1 << type_props->num_type_attrs) - 1; return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_dsa( struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res; /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; res = crypto_acipher_gen_dsa_key(o->attr, key_size); if (res != TEE_SUCCESS) return res; /* Set bits for all known attributes for this object type */ o->have_attrs = (1 << type_props->num_type_attrs) - 1; return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_dh( struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res; struct dh_keypair *tee_dh_key; struct bignum *dh_q = NULL; uint32_t dh_xbits = 0; /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; tee_dh_key = (struct dh_keypair *)o->attr; if (get_attribute(o, type_props, TEE_ATTR_DH_SUBPRIME)) dh_q = tee_dh_key->q; if (get_attribute(o, type_props, TEE_ATTR_DH_X_BITS)) dh_xbits = tee_dh_key->xbits; res = crypto_acipher_gen_dh_key(tee_dh_key, dh_q, dh_xbits, key_size); if (res != TEE_SUCCESS) return res; /* Set bits for the generated public and private key */ set_attribute(o, type_props, TEE_ATTR_DH_PUBLIC_VALUE); set_attribute(o, type_props, TEE_ATTR_DH_PRIVATE_VALUE); set_attribute(o, type_props, TEE_ATTR_DH_X_BITS); return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_ecc( struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res; struct ecc_keypair *tee_ecc_key; /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; tee_ecc_key = (struct ecc_keypair *)o->attr; res = crypto_acipher_gen_ecc_key(tee_ecc_key, key_size); if (res != TEE_SUCCESS) return res; /* Set bits for the generated public and private key */ set_attribute(o, type_props, TEE_ATTR_ECC_PRIVATE_VALUE); set_attribute(o, type_props, TEE_ATTR_ECC_PUBLIC_VALUE_X); set_attribute(o, type_props, TEE_ATTR_ECC_PUBLIC_VALUE_Y); set_attribute(o, type_props, TEE_ATTR_ECC_CURVE); return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_x25519(struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res = TEE_ERROR_GENERIC; struct montgomery_keypair *tee_x25519_key = NULL; /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; tee_x25519_key = (struct montgomery_keypair *)o->attr; res = crypto_acipher_gen_x25519_key(tee_x25519_key, key_size); if (res != TEE_SUCCESS) return res; /* Set bits for the generated public and private key */ set_attribute(o, type_props, TEE_ATTR_X25519_PRIVATE_VALUE); set_attribute(o, type_props, TEE_ATTR_X25519_PUBLIC_VALUE); return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_x448(struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res = TEE_ERROR_GENERIC; struct montgomery_keypair *tee_x448_key = NULL; /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; tee_x448_key = (struct montgomery_keypair *)o->attr; res = crypto_acipher_gen_x448_key(tee_x448_key, key_size); if (res != TEE_SUCCESS) return res; set_attribute(o, type_props, TEE_ATTR_X448_PRIVATE_VALUE); set_attribute(o, type_props, TEE_ATTR_X448_PUBLIC_VALUE); return TEE_SUCCESS; } static TEE_Result tee_svc_obj_generate_key_ed25519(struct tee_obj *o, const struct tee_cryp_obj_type_props *type_props, uint32_t key_size, const TEE_Attribute *params, uint32_t param_count) { TEE_Result res = TEE_ERROR_GENERIC; struct ed25519_keypair *key = NULL; /* Copy the present attributes into the obj before starting */ res = tee_svc_cryp_obj_populate_type(o, type_props, params, param_count); if (res != TEE_SUCCESS) return res; key = o->attr; res = crypto_acipher_gen_ed25519_key(key, key_size); if (res != TEE_SUCCESS) return res; /* Set bits for the generated public and private key */ set_attribute(o, type_props, TEE_ATTR_ED25519_PRIVATE_VALUE); set_attribute(o, type_props, TEE_ATTR_ED25519_PUBLIC_VALUE); return TEE_SUCCESS; } static TEE_Result tee_svc_obj_ed25519_parse_params(const TEE_Attribute *params, size_t num_params, bool *ph_flag, const uint8_t **ctx, size_t *ctx_len) { size_t n = 0; *ctx = NULL; for (n = 0; n < num_params; n++) { switch (params[n].attributeID) { case TEE_ATTR_EDDSA_PREHASH: if (params[n].content.value.b) return TEE_ERROR_BAD_PARAMETERS; if (!params[n].content.value.a) *ph_flag = false; else if (params[n].content.value.a == 1) *ph_flag = true; else return TEE_ERROR_BAD_PARAMETERS; break; case TEE_ATTR_EDDSA_CTX: /* several provided contexts are treated as error */ if (*ctx) return TEE_ERROR_BAD_PARAMETERS; *ctx_len = params[n].content.ref.length; if (*ctx_len > TEE_ED25519_CTX_MAX_LENGTH) return TEE_ERROR_BAD_PARAMETERS; if (!*ctx_len) break; *ctx = params[n].content.ref.buffer; if (!*ctx) return TEE_ERROR_BAD_PARAMETERS; break; default: return TEE_ERROR_BAD_PARAMETERS; } } return TEE_SUCCESS; } static TEE_Result tee_svc_obj_ed25519_sign(struct ed25519_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len, const TEE_Attribute *params, size_t num_params) { TEE_Result err = TEE_ERROR_GENERIC; size_t ctx_len = 0; const uint8_t *ctx = NULL; bool ph_flag = false; err = tee_svc_obj_ed25519_parse_params(params, num_params, &ph_flag, &ctx, &ctx_len); if (err != TEE_SUCCESS) return err; if (ph_flag || ctx) { return crypto_acipher_ed25519ctx_sign(key, msg, msg_len, sig, sig_len, ph_flag, ctx, ctx_len); } return crypto_acipher_ed25519_sign(key, msg, msg_len, sig, sig_len); } static TEE_Result tee_svc_obj_ed25519_verify(struct ed25519_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, const TEE_Attribute *params, size_t num_params) { TEE_Result err = TEE_ERROR_GENERIC; size_t ctx_len = 0; const uint8_t *ctx = NULL; bool ph_flag = false; err = tee_svc_obj_ed25519_parse_params(params, num_params, &ph_flag, &ctx, &ctx_len); if (err) return err; if (ph_flag || ctx) { return crypto_acipher_ed25519ctx_verify(key, msg, msg_len, sig, sig_len, ph_flag, ctx, ctx_len); } return crypto_acipher_ed25519_verify(key, msg, msg_len, sig, sig_len); } TEE_Result syscall_obj_generate_key(unsigned long obj, unsigned long key_size, const struct utee_attribute *usr_params, unsigned long param_count) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; const struct tee_cryp_obj_type_props *type_props = NULL; struct tee_obj *o = NULL; struct tee_cryp_obj_secret *key = NULL; size_t byte_size = 0; TEE_Attribute *params = NULL; size_t alloc_size = 0; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; /* Must be a transient object */ if ((o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT) != 0) return TEE_ERROR_BAD_STATE; /* Must not be initialized already */ if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) != 0) return TEE_ERROR_BAD_STATE; /* Find description of object */ type_props = tee_svc_find_type_props(o->info.objectType); if (!type_props) return TEE_ERROR_NOT_SUPPORTED; /* Check that key_size follows restrictions */ res = check_key_size(type_props, key_size); if (res) return res; if (MUL_OVERFLOW(sizeof(TEE_Attribute), param_count, &alloc_size)) return TEE_ERROR_OVERFLOW; params = malloc(alloc_size); if (!params) return TEE_ERROR_OUT_OF_MEMORY; res = copy_in_attrs(to_user_ta_ctx(sess->ctx), usr_params, param_count, params); if (res != TEE_SUCCESS) goto out; res = tee_svc_cryp_check_attr(ATTR_USAGE_GENERATE_KEY, type_props, params, param_count); if (res != TEE_SUCCESS) goto out; switch (o->info.objectType) { case TEE_TYPE_AES: case TEE_TYPE_DES: case TEE_TYPE_DES3: case TEE_TYPE_SM4: case TEE_TYPE_HMAC_MD5: case TEE_TYPE_HMAC_SHA1: case TEE_TYPE_HMAC_SHA224: case TEE_TYPE_HMAC_SHA256: case TEE_TYPE_HMAC_SHA384: case TEE_TYPE_HMAC_SHA512: case TEE_TYPE_HMAC_SHA3_224: case TEE_TYPE_HMAC_SHA3_256: case TEE_TYPE_HMAC_SHA3_384: case TEE_TYPE_HMAC_SHA3_512: case TEE_TYPE_HMAC_SM3: case TEE_TYPE_GENERIC_SECRET: byte_size = key_size / 8; /* * In GP Internal API Specification 1.0 the partity bits * aren't counted when telling the size of the key in bits. */ if (is_gp_legacy_des_key_size(o->info.objectType, key_size)) byte_size = (key_size + key_size / 7) / 8; key = (struct tee_cryp_obj_secret *)o->attr; if (byte_size > key->alloc_size) { res = TEE_ERROR_EXCESS_DATA; goto out; } res = crypto_rng_read((void *)(key + 1), byte_size); if (res != TEE_SUCCESS) goto out; key->key_size = byte_size; /* Set bits for all known attributes for this object type */ o->have_attrs = (1 << type_props->num_type_attrs) - 1; break; case TEE_TYPE_RSA_KEYPAIR: res = tee_svc_obj_generate_key_rsa(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; case TEE_TYPE_DSA_KEYPAIR: res = tee_svc_obj_generate_key_dsa(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; case TEE_TYPE_DH_KEYPAIR: res = tee_svc_obj_generate_key_dh(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: case TEE_TYPE_SM2_DSA_KEYPAIR: case TEE_TYPE_SM2_KEP_KEYPAIR: case TEE_TYPE_SM2_PKE_KEYPAIR: res = tee_svc_obj_generate_key_ecc(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; case TEE_TYPE_X25519_KEYPAIR: res = tee_svc_obj_generate_key_x25519(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; case TEE_TYPE_X448_KEYPAIR: res = tee_svc_obj_generate_key_x448(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; case TEE_TYPE_ED25519_KEYPAIR: res = tee_svc_obj_generate_key_ed25519(o, type_props, key_size, params, param_count); if (res != TEE_SUCCESS) goto out; break; default: res = TEE_ERROR_BAD_FORMAT; } out: free_wipe(params); if (res == TEE_SUCCESS) { o->info.objectSize = key_size; o->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; } return res; } static TEE_Result tee_svc_cryp_get_state(struct ts_session *sess, vaddr_t state_id, struct tee_cryp_state **state) { struct tee_cryp_state *s; struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TAILQ_FOREACH(s, &utc->cryp_states, link) { if (state_id == (vaddr_t)s) { *state = s; return TEE_SUCCESS; } } return TEE_ERROR_BAD_PARAMETERS; } static void cryp_state_free(struct user_ta_ctx *utc, struct tee_cryp_state *cs) { struct tee_obj *o; if (tee_obj_get(utc, cs->key1, &o) == TEE_SUCCESS) tee_obj_close(utc, o); if (tee_obj_get(utc, cs->key2, &o) == TEE_SUCCESS) tee_obj_close(utc, o); TAILQ_REMOVE(&utc->cryp_states, cs, link); if (cs->ctx_finalize != NULL) cs->ctx_finalize(cs->ctx); switch (TEE_ALG_GET_CLASS(cs->algo)) { case TEE_OPERATION_CIPHER: crypto_cipher_free_ctx(cs->ctx); break; case TEE_OPERATION_AE: crypto_authenc_free_ctx(cs->ctx); break; case TEE_OPERATION_DIGEST: crypto_hash_free_ctx(cs->ctx); break; case TEE_OPERATION_MAC: crypto_mac_free_ctx(cs->ctx); break; default: assert(!cs->ctx); } free(cs); } static TEE_Result tee_svc_cryp_check_key_type(const struct tee_obj *o, uint32_t algo, TEE_OperationMode mode) { uint32_t req_key_type; uint32_t req_key_type2 = 0; switch (TEE_ALG_GET_MAIN_ALG(algo)) { case TEE_MAIN_ALGO_MD5: req_key_type = TEE_TYPE_HMAC_MD5; break; case TEE_MAIN_ALGO_SHA1: req_key_type = TEE_TYPE_HMAC_SHA1; break; case TEE_MAIN_ALGO_SHA224: req_key_type = TEE_TYPE_HMAC_SHA224; break; case TEE_MAIN_ALGO_SHA256: req_key_type = TEE_TYPE_HMAC_SHA256; break; case TEE_MAIN_ALGO_SHA384: req_key_type = TEE_TYPE_HMAC_SHA384; break; case TEE_MAIN_ALGO_SHA512: req_key_type = TEE_TYPE_HMAC_SHA512; break; case TEE_MAIN_ALGO_SHA3_224: req_key_type = TEE_TYPE_HMAC_SHA3_224; break; case TEE_MAIN_ALGO_SHA3_256: req_key_type = TEE_TYPE_HMAC_SHA3_256; break; case TEE_MAIN_ALGO_SHA3_384: req_key_type = TEE_TYPE_HMAC_SHA3_384; break; case TEE_MAIN_ALGO_SHA3_512: req_key_type = TEE_TYPE_HMAC_SHA3_512; break; case TEE_MAIN_ALGO_SM3: req_key_type = TEE_TYPE_HMAC_SM3; break; case TEE_MAIN_ALGO_AES: req_key_type = TEE_TYPE_AES; break; case TEE_MAIN_ALGO_DES: req_key_type = TEE_TYPE_DES; break; case TEE_MAIN_ALGO_DES3: req_key_type = TEE_TYPE_DES3; break; case TEE_MAIN_ALGO_SM4: req_key_type = TEE_TYPE_SM4; break; case TEE_MAIN_ALGO_RSA: req_key_type = TEE_TYPE_RSA_KEYPAIR; if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY) req_key_type2 = TEE_TYPE_RSA_PUBLIC_KEY; break; case TEE_MAIN_ALGO_DSA: req_key_type = TEE_TYPE_DSA_KEYPAIR; if (mode == TEE_MODE_ENCRYPT || mode == TEE_MODE_VERIFY) req_key_type2 = TEE_TYPE_DSA_PUBLIC_KEY; break; case TEE_MAIN_ALGO_DH: req_key_type = TEE_TYPE_DH_KEYPAIR; break; case TEE_MAIN_ALGO_ECDSA: req_key_type = TEE_TYPE_ECDSA_KEYPAIR; if (mode == TEE_MODE_VERIFY) req_key_type2 = TEE_TYPE_ECDSA_PUBLIC_KEY; break; case TEE_MAIN_ALGO_ECDH: req_key_type = TEE_TYPE_ECDH_KEYPAIR; break; case TEE_MAIN_ALGO_ED25519: req_key_type = TEE_TYPE_ED25519_KEYPAIR; if (mode == TEE_MODE_VERIFY) req_key_type2 = TEE_TYPE_ED25519_PUBLIC_KEY; break; case TEE_MAIN_ALGO_SM2_PKE: if (mode == TEE_MODE_ENCRYPT) req_key_type = TEE_TYPE_SM2_PKE_PUBLIC_KEY; else req_key_type = TEE_TYPE_SM2_PKE_KEYPAIR; break; case TEE_MAIN_ALGO_SM2_DSA_SM3: if (mode == TEE_MODE_VERIFY) req_key_type = TEE_TYPE_SM2_DSA_PUBLIC_KEY; else req_key_type = TEE_TYPE_SM2_DSA_KEYPAIR; break; #if defined(CFG_CRYPTO_SM2_KEP) case TEE_MAIN_ALGO_SM2_KEP: req_key_type = TEE_TYPE_SM2_KEP_KEYPAIR; req_key_type2 = TEE_TYPE_SM2_KEP_PUBLIC_KEY; break; #endif #if defined(CFG_CRYPTO_HKDF) case TEE_MAIN_ALGO_HKDF: req_key_type = TEE_TYPE_HKDF_IKM; break; #endif #if defined(CFG_CRYPTO_CONCAT_KDF) case TEE_MAIN_ALGO_CONCAT_KDF: req_key_type = TEE_TYPE_CONCAT_KDF_Z; break; #endif #if defined(CFG_CRYPTO_PBKDF2) case TEE_MAIN_ALGO_PBKDF2: req_key_type = TEE_TYPE_PBKDF2_PASSWORD; break; #endif case TEE_MAIN_ALGO_X25519: req_key_type = TEE_TYPE_X25519_KEYPAIR; break; case TEE_MAIN_ALGO_X448: req_key_type = TEE_TYPE_X448_KEYPAIR; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (req_key_type != o->info.objectType && req_key_type2 != o->info.objectType) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } static uint32_t translate_compat_algo(uint32_t algo) { switch (algo) { case __OPTEE_ALG_ECDSA_P192: return TEE_ALG_ECDSA_SHA1; case __OPTEE_ALG_ECDSA_P224: return TEE_ALG_ECDSA_SHA224; case __OPTEE_ALG_ECDSA_P256: return TEE_ALG_ECDSA_SHA256; case __OPTEE_ALG_ECDSA_P384: return TEE_ALG_ECDSA_SHA384; case __OPTEE_ALG_ECDSA_P521: return TEE_ALG_ECDSA_SHA512; case __OPTEE_ALG_ECDH_P192: case __OPTEE_ALG_ECDH_P224: case __OPTEE_ALG_ECDH_P256: case __OPTEE_ALG_ECDH_P384: case __OPTEE_ALG_ECDH_P521: return TEE_ALG_ECDH_DERIVE_SHARED_SECRET; default: return algo; } } TEE_Result syscall_cryp_state_alloc(unsigned long algo, unsigned long mode, unsigned long key1, unsigned long key2, uint32_t *state) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_cryp_state *cs = NULL; struct tee_obj *o1 = NULL; struct tee_obj *o2 = NULL; algo = translate_compat_algo(algo); if (key1 != 0) { res = tee_obj_get(utc, uref_to_vaddr(key1), &o1); if (res != TEE_SUCCESS) return res; if (o1->busy) return TEE_ERROR_BAD_PARAMETERS; res = tee_svc_cryp_check_key_type(o1, algo, mode); if (res != TEE_SUCCESS) return res; } if (key2 != 0) { res = tee_obj_get(utc, uref_to_vaddr(key2), &o2); if (res != TEE_SUCCESS) return res; if (o2->busy) return TEE_ERROR_BAD_PARAMETERS; res = tee_svc_cryp_check_key_type(o2, algo, mode); if (res != TEE_SUCCESS) return res; } cs = calloc(1, sizeof(struct tee_cryp_state)); if (!cs) return TEE_ERROR_OUT_OF_MEMORY; TAILQ_INSERT_TAIL(&utc->cryp_states, cs, link); cs->algo = algo; cs->mode = mode; cs->state = CRYP_STATE_UNINITIALIZED; switch (TEE_ALG_GET_CLASS(algo)) { case TEE_OPERATION_CIPHER: if ((TEE_ALG_GET_CHAIN_MODE(algo) == TEE_CHAIN_MODE_XTS && (key1 == 0 || key2 == 0)) || (TEE_ALG_GET_CHAIN_MODE(algo) != TEE_CHAIN_MODE_XTS && (key1 == 0 || key2 != 0))) { res = TEE_ERROR_BAD_PARAMETERS; } else { res = crypto_cipher_alloc_ctx(&cs->ctx, algo); if (res != TEE_SUCCESS) break; } break; case TEE_OPERATION_AE: if (key1 == 0 || key2 != 0) { res = TEE_ERROR_BAD_PARAMETERS; } else { res = crypto_authenc_alloc_ctx(&cs->ctx, algo); if (res != TEE_SUCCESS) break; } break; case TEE_OPERATION_MAC: if (key1 == 0 || key2 != 0) { res = TEE_ERROR_BAD_PARAMETERS; } else { res = crypto_mac_alloc_ctx(&cs->ctx, algo); if (res != TEE_SUCCESS) break; } break; case TEE_OPERATION_DIGEST: if (key1 != 0 || key2 != 0) { res = TEE_ERROR_BAD_PARAMETERS; } else { res = crypto_hash_alloc_ctx(&cs->ctx, algo); if (res != TEE_SUCCESS) break; } break; case TEE_OPERATION_ASYMMETRIC_CIPHER: case TEE_OPERATION_ASYMMETRIC_SIGNATURE: if (algo == TEE_ALG_RSASSA_PKCS1_V1_5 && !IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) { res = TEE_ERROR_NOT_SUPPORTED; break; } if (key1 == 0 || key2 != 0) res = TEE_ERROR_BAD_PARAMETERS; break; case TEE_OPERATION_KEY_DERIVATION: if (algo == TEE_ALG_SM2_KEP) { if (key1 == 0 || key2 == 0) res = TEE_ERROR_BAD_PARAMETERS; } else { if (key1 == 0 || key2 != 0) res = TEE_ERROR_BAD_PARAMETERS; } break; default: res = TEE_ERROR_NOT_SUPPORTED; break; } if (res != TEE_SUCCESS) goto out; res = copy_kaddr_to_uref(state, cs); if (res != TEE_SUCCESS) goto out; /* Register keys */ if (o1 != NULL) { o1->busy = true; cs->key1 = (vaddr_t)o1; } if (o2 != NULL) { o2->busy = true; cs->key2 = (vaddr_t)o2; } out: if (res != TEE_SUCCESS) cryp_state_free(utc, cs); return res; } TEE_Result syscall_cryp_state_copy(unsigned long dst, unsigned long src) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_cryp_state *cs_dst = NULL; struct tee_cryp_state *cs_src = NULL; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(dst), &cs_dst); if (res != TEE_SUCCESS) return res; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(src), &cs_src); if (res != TEE_SUCCESS) return res; if (cs_dst->algo != cs_src->algo || cs_dst->mode != cs_src->mode) return TEE_ERROR_BAD_PARAMETERS; switch (TEE_ALG_GET_CLASS(cs_src->algo)) { case TEE_OPERATION_CIPHER: crypto_cipher_copy_state(cs_dst->ctx, cs_src->ctx); break; case TEE_OPERATION_AE: crypto_authenc_copy_state(cs_dst->ctx, cs_src->ctx); break; case TEE_OPERATION_DIGEST: crypto_hash_copy_state(cs_dst->ctx, cs_src->ctx); break; case TEE_OPERATION_MAC: crypto_mac_copy_state(cs_dst->ctx, cs_src->ctx); break; default: return TEE_ERROR_BAD_STATE; } cs_dst->state = cs_src->state; cs_dst->ctx_finalize = cs_src->ctx_finalize; return TEE_SUCCESS; } void tee_svc_cryp_free_states(struct user_ta_ctx *utc) { struct tee_cryp_state_head *states = &utc->cryp_states; while (!TAILQ_EMPTY(states)) cryp_state_free(utc, TAILQ_FIRST(states)); } TEE_Result syscall_cryp_state_free(unsigned long state) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_cryp_state *cs = NULL; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; cryp_state_free(to_user_ta_ctx(sess->ctx), cs); return TEE_SUCCESS; } TEE_Result syscall_hash_init(unsigned long state, const void *iv __maybe_unused, size_t iv_len __maybe_unused) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_cryp_state *cs = NULL; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; switch (TEE_ALG_GET_CLASS(cs->algo)) { case TEE_OPERATION_DIGEST: res = crypto_hash_init(cs->ctx); if (res != TEE_SUCCESS) return res; break; case TEE_OPERATION_MAC: { struct tee_obj *o; struct tee_cryp_obj_secret *key; res = tee_obj_get(to_user_ta_ctx(sess->ctx), cs->key1, &o); if (res != TEE_SUCCESS) return res; if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) return TEE_ERROR_BAD_PARAMETERS; key = (struct tee_cryp_obj_secret *)o->attr; res = crypto_mac_init(cs->ctx, (void *)(key + 1), key->key_size); if (res != TEE_SUCCESS) return res; break; } default: return TEE_ERROR_BAD_PARAMETERS; } cs->state = CRYP_STATE_INITIALIZED; return TEE_SUCCESS; } TEE_Result syscall_hash_update(unsigned long state, const void *chunk, size_t chunk_size) { struct ts_session *sess = ts_get_current_session(); struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; /* No data, but size provided isn't valid parameters. */ if (!chunk && chunk_size) return TEE_ERROR_BAD_PARAMETERS; /* Zero length hash is valid, but nothing we need to do. */ if (!chunk_size) return TEE_SUCCESS; chunk = memtag_strip_tag_const(chunk); res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)chunk, chunk_size); if (res != TEE_SUCCESS) return res; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; switch (TEE_ALG_GET_CLASS(cs->algo)) { case TEE_OPERATION_DIGEST: enter_user_access(); res = crypto_hash_update(cs->ctx, chunk, chunk_size); exit_user_access(); if (res != TEE_SUCCESS) return res; break; case TEE_OPERATION_MAC: enter_user_access(); res = crypto_mac_update(cs->ctx, chunk, chunk_size); exit_user_access(); if (res != TEE_SUCCESS) return res; break; default: return TEE_ERROR_BAD_PARAMETERS; } return TEE_SUCCESS; } static bool is_xof_algo(uint32_t algo) { return algo == TEE_ALG_SHAKE128 || algo == TEE_ALG_SHAKE256; } TEE_Result syscall_hash_final(unsigned long state, const void *chunk, size_t chunk_size, void *hash, uint64_t *hash_len) { struct ts_session *sess = ts_get_current_session(); struct tee_cryp_state *cs = NULL; TEE_Result res2 = TEE_SUCCESS; TEE_Result res = TEE_SUCCESS; size_t hash_size = 0; size_t hlen = 0; /* No data, but size provided isn't valid parameters. */ if (!chunk && chunk_size) return TEE_ERROR_BAD_PARAMETERS; chunk = memtag_strip_tag_const(chunk); hash = memtag_strip_tag(hash); res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)chunk, chunk_size); if (res != TEE_SUCCESS) return res; res = get_user_u64_as_size_t(&hlen, hash_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)hash, hlen); if (res != TEE_SUCCESS) return res; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; switch (TEE_ALG_GET_CLASS(cs->algo)) { case TEE_OPERATION_DIGEST: if (is_xof_algo(cs->algo)) { if (chunk_size) { enter_user_access(); res = crypto_hash_update(cs->ctx, chunk, chunk_size); exit_user_access(); if (res) return res; } /* * hash_size is supposed to be unchanged for XOF * algorithms so return directly. */ enter_user_access(); res = crypto_hash_final(cs->ctx, hash, hlen); exit_user_access(); return res; } res = tee_alg_get_digest_size(cs->algo, &hash_size); if (res != TEE_SUCCESS) return res; if (hlen < hash_size) { res = TEE_ERROR_SHORT_BUFFER; goto out; } if (chunk_size) { enter_user_access(); res = crypto_hash_update(cs->ctx, chunk, chunk_size); exit_user_access(); if (res != TEE_SUCCESS) return res; } enter_user_access(); res = crypto_hash_final(cs->ctx, hash, hash_size); exit_user_access(); if (res != TEE_SUCCESS) return res; break; case TEE_OPERATION_MAC: res = tee_alg_get_digest_size(cs->algo, &hash_size); if (res != TEE_SUCCESS) return res; if (hlen < hash_size) { res = TEE_ERROR_SHORT_BUFFER; goto out; } if (chunk_size) { enter_user_access(); res = crypto_mac_update(cs->ctx, chunk, chunk_size); exit_user_access(); if (res != TEE_SUCCESS) return res; } enter_user_access(); res = crypto_mac_final(cs->ctx, hash, hash_size); exit_user_access(); if (res != TEE_SUCCESS) return res; break; default: return TEE_ERROR_BAD_PARAMETERS; } out: res2 = put_user_u64(hash_len, hash_size); if (res2 != TEE_SUCCESS) return res2; return res; } TEE_Result syscall_cipher_init(unsigned long state, const void *iv, size_t iv_len) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); struct tee_cryp_obj_secret *key1 = NULL; struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; void *iv_bbuf = NULL; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_CIPHER) return TEE_ERROR_BAD_STATE; res = tee_obj_get(utc, cs->key1, &o); if (res != TEE_SUCCESS) return res; if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) return TEE_ERROR_BAD_PARAMETERS; key1 = o->attr; res = bb_memdup_user(iv, iv_len, &iv_bbuf); if (res) return res; if (tee_obj_get(utc, cs->key2, &o) == TEE_SUCCESS) { struct tee_cryp_obj_secret *key2 = o->attr; if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) return TEE_ERROR_BAD_PARAMETERS; res = crypto_cipher_init(cs->ctx, cs->mode, (uint8_t *)(key1 + 1), key1->key_size, (uint8_t *)(key2 + 1), key2->key_size, iv_bbuf, iv_len); } else { res = crypto_cipher_init(cs->ctx, cs->mode, (uint8_t *)(key1 + 1), key1->key_size, NULL, 0, iv_bbuf, iv_len); } if (res != TEE_SUCCESS) return res; cs->ctx_finalize = crypto_cipher_final; cs->state = CRYP_STATE_INITIALIZED; return TEE_SUCCESS; } static TEE_Result tee_svc_cipher_update_helper(unsigned long state, bool last_block, const void *src, size_t src_len, void *dst, uint64_t *dst_len) { struct ts_session *sess = ts_get_current_session(); struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; size_t dlen = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; src = memtag_strip_tag_const(src); dst = memtag_strip_tag(dst); res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)src, src_len); if (res != TEE_SUCCESS) return res; if (!dst_len) { dlen = 0; } else { struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx; uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; res = get_user_u64_as_size_t(&dlen, dst_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(uctx, flags, (uaddr_t)dst, dlen); if (res != TEE_SUCCESS) return res; } if (dlen < src_len) { res = TEE_ERROR_SHORT_BUFFER; goto out; } if (src_len > 0) { /* Permit src_len == 0 to finalize the operation */ enter_user_access(); res = tee_do_cipher_update(cs->ctx, cs->algo, cs->mode, last_block, src, src_len, dst); exit_user_access(); } if (last_block && cs->ctx_finalize != NULL) { cs->ctx_finalize(cs->ctx); cs->ctx_finalize = NULL; } out: if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) && dst_len != NULL) { TEE_Result res2; res2 = put_user_u64(dst_len, src_len); if (res2 != TEE_SUCCESS) res = res2; } return res; } TEE_Result syscall_cipher_update(unsigned long state, const void *src, size_t src_len, void *dst, uint64_t *dst_len) { return tee_svc_cipher_update_helper(state, false /* last_block */, src, src_len, dst, dst_len); } TEE_Result syscall_cipher_final(unsigned long state, const void *src, size_t src_len, void *dst, uint64_t *dst_len) { return tee_svc_cipher_update_helper(state, true /* last_block */, src, src_len, dst, dst_len); } #if defined(CFG_CRYPTO_HKDF) static TEE_Result get_hkdf_params(uint32_t algo, const TEE_Attribute *params, uint32_t param_count, void **salt, size_t *salt_len, void **info, size_t *info_len, size_t *okm_len, uint32_t *hash_id) { TEE_Result res = TEE_SUCCESS; size_t n; enum { SALT = 0x1, LENGTH = 0x2, INFO = 0x4, HASH = 0x8 }; uint8_t found = 0; *salt = *info = NULL; *salt_len = *info_len = *okm_len = 0; if (algo == TEE_ALG_HKDF) { *hash_id = TEE_ALG_SHA256; } else { *hash_id = TEE_ALG_GET_DIGEST_HASH(algo); found |= HASH; } for (n = 0; n < param_count; n++) { const TEE_Attribute *p = ¶ms[n]; switch (p->attributeID) { case __OPTEE_TEE_ATTR_HKDF_SALT: case TEE_ATTR_HKDF_SALT: if (!(found & SALT)) { *salt_len = p->content.ref.length; res = bb_memdup_user(p->content.ref.buffer, *salt_len, salt); if (res) return res; found |= SALT; } break; case TEE_ATTR_KDF_KEY_SIZE: case TEE_ATTR_HKDF_OKM_LENGTH: if (!(found & LENGTH)) { *okm_len = p->content.value.a; found |= LENGTH; } break; case __OPTEE_ATTR_HKDF_INFO: case TEE_ATTR_HKDF_INFO: if (!(found & INFO)) { *info_len = p->content.ref.length; res = bb_memdup_user(p->content.ref.buffer, *info_len, info); if (res) return res; found |= INFO; } break; case TEE_ATTR_HKDF_HASH_ALGORITHM: if (!(found & HASH)) { *hash_id = p->content.value.a; found |= HASH; } break; default: /* Unexpected attribute */ return TEE_ERROR_BAD_PARAMETERS; } } if (!(found & LENGTH)) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } #endif #if defined(CFG_CRYPTO_CONCAT_KDF) static TEE_Result get_concat_kdf_params(const TEE_Attribute *params, uint32_t param_count, void **other_info, size_t *other_info_len, size_t *derived_key_len) { size_t n; enum { LENGTH = 0x1, INFO = 0x2 }; uint8_t found = 0; *other_info = NULL; *other_info_len = *derived_key_len = 0; for (n = 0; n < param_count; n++) { const TEE_Attribute *p = ¶ms[n]; switch (p->attributeID) { case TEE_ATTR_CONCAT_KDF_OTHER_INFO: if (!(found & INFO)) { TEE_Result res = TEE_SUCCESS; *other_info_len = p->content.ref.length; res = bb_memdup_user(p->content.ref.buffer, *other_info_len, other_info); if (res) return res; found |= INFO; } break; case TEE_ATTR_CONCAT_KDF_DKM_LENGTH: if (!(found & LENGTH)) { *derived_key_len = p->content.value.a; found |= LENGTH; } break; default: /* Unexpected attribute */ return TEE_ERROR_BAD_PARAMETERS; } } if (!(found & LENGTH)) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } #endif #if defined(CFG_CRYPTO_PBKDF2) static TEE_Result get_pbkdf2_params(const TEE_Attribute *params, uint32_t param_count, void **salt, size_t *salt_len, size_t *derived_key_len, size_t *iteration_count) { size_t n; enum { SALT = 0x1, LENGTH = 0x2, COUNT = 0x4 }; uint8_t found = 0; *salt = NULL; *salt_len = *derived_key_len = *iteration_count = 0; for (n = 0; n < param_count; n++) { const TEE_Attribute *p = ¶ms[n]; switch (p->attributeID) { case TEE_ATTR_PBKDF2_SALT: if (!(found & SALT)) { TEE_Result res = TEE_SUCCESS; *salt_len = p->content.ref.length; res = bb_memdup_user(p->content.ref.buffer, *salt_len, salt); if (res) return res; found |= SALT; } break; case TEE_ATTR_PBKDF2_DKM_LENGTH: if (!(found & LENGTH)) { *derived_key_len = p->content.value.a; found |= LENGTH; } break; case TEE_ATTR_PBKDF2_ITERATION_COUNT: if (!(found & COUNT)) { *iteration_count = p->content.value.a; found |= COUNT; } break; default: /* Unexpected attribute */ return TEE_ERROR_BAD_PARAMETERS; } } if ((found & (LENGTH|COUNT)) != (LENGTH|COUNT)) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } #endif #if defined(CFG_CRYPTO_SM2_KEP) static TEE_Result get_sm2_kep_params(const TEE_Attribute *params, uint32_t param_count, struct ecc_public_key *peer_key, struct ecc_public_key *peer_eph_key, struct sm2_kep_parms *kep_parms) { TEE_Result res = TEE_ERROR_GENERIC; size_t n; enum { IS_INITIATOR, PEER_KEY_X, PEER_KEY_Y, PEER_EPH_KEY_X, PEER_EPH_KEY_Y, INITIATOR_ID, RESPONDER_ID, }; uint8_t mandatory = BIT(IS_INITIATOR) | BIT(PEER_KEY_X) | BIT(PEER_KEY_Y) | BIT(PEER_EPH_KEY_X) | BIT(PEER_EPH_KEY_Y) | BIT(INITIATOR_ID) | BIT(RESPONDER_ID); uint8_t found = 0; res = crypto_acipher_alloc_ecc_public_key(peer_key, TEE_TYPE_SM2_KEP_PUBLIC_KEY, 256); if (res) return res; res = crypto_acipher_alloc_ecc_public_key(peer_eph_key, TEE_TYPE_SM2_KEP_PUBLIC_KEY, 256); if (res) goto out_p; peer_key->curve = TEE_ECC_CURVE_SM2; peer_eph_key->curve = TEE_ECC_CURVE_SM2; for (n = 0; n < param_count; n++) { const TEE_Attribute *p = ¶ms[n]; void *bbuf = NULL; switch (p->attributeID) { case TEE_ATTR_SM2_KEP_USER: kep_parms->is_initiator = !p->content.value.a; found |= BIT(IS_INITIATOR); break; case TEE_ATTR_ECC_PUBLIC_VALUE_X: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; crypto_bignum_bin2bn(bbuf, p->content.ref.length, peer_key->x); found |= BIT(PEER_KEY_X); bb_free(bbuf, p->content.ref.length); break; case TEE_ATTR_ECC_PUBLIC_VALUE_Y: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; crypto_bignum_bin2bn(bbuf, p->content.ref.length, peer_key->y); found |= BIT(PEER_KEY_Y); bb_free(bbuf, p->content.ref.length); break; case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X: case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; crypto_bignum_bin2bn(bbuf, p->content.ref.length, peer_eph_key->x); found |= BIT(PEER_EPH_KEY_X); bb_free(bbuf, p->content.ref.length); break; case __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y: case TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; crypto_bignum_bin2bn(bbuf, p->content.ref.length, peer_eph_key->y); found |= BIT(PEER_EPH_KEY_Y); bb_free(bbuf, p->content.ref.length); break; case TEE_ATTR_SM2_ID_INITIATOR: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; kep_parms->initiator_id = bbuf; kep_parms->initiator_id_len = p->content.ref.length; found |= BIT(INITIATOR_ID); break; case TEE_ATTR_SM2_ID_RESPONDER: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; kep_parms->responder_id = bbuf; kep_parms->responder_id_len = p->content.ref.length; found |= BIT(RESPONDER_ID); break; case TEE_ATTR_SM2_KEP_CONFIRMATION_IN: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; kep_parms->conf_in = bbuf; kep_parms->conf_in_len = p->content.ref.length; break; case TEE_ATTR_SM2_KEP_CONFIRMATION_OUT: res = bb_memdup_user(p->content.ref.buffer, p->content.ref.length, &bbuf); if (res) return res; kep_parms->conf_out = bbuf; kep_parms->conf_out_len = p->content.ref.length; break; default: /* Unexpected attribute */ res = TEE_ERROR_BAD_PARAMETERS; goto out; } } if ((found & mandatory) != mandatory) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } return TEE_SUCCESS; out: crypto_acipher_free_ecc_public_key(peer_eph_key); out_p: crypto_acipher_free_ecc_public_key(peer_key); return res; } #endif TEE_Result syscall_cryp_derive_key(unsigned long state, const struct utee_attribute *usr_params, unsigned long param_count, unsigned long derived_key) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_ERROR_NOT_SUPPORTED; struct tee_obj *ko = NULL; struct tee_obj *so = NULL; struct tee_cryp_state *cs = NULL; struct tee_cryp_obj_secret *sk = NULL; const struct tee_cryp_obj_type_props *type_props = NULL; TEE_Attribute *params = NULL; size_t alloc_size = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (MUL_OVERFLOW(sizeof(TEE_Attribute), param_count, &alloc_size)) return TEE_ERROR_OVERFLOW; params = malloc(alloc_size); if (!params) return TEE_ERROR_OUT_OF_MEMORY; res = copy_in_attrs(utc, usr_params, param_count, params); if (res != TEE_SUCCESS) goto out; /* Get key set in operation */ res = tee_obj_get(utc, cs->key1, &ko); if (res != TEE_SUCCESS) goto out; res = tee_obj_get(utc, uref_to_vaddr(derived_key), &so); if (res != TEE_SUCCESS) goto out; /* Find information needed about the object to initialize */ sk = so->attr; /* Find description of object */ type_props = tee_svc_find_type_props(so->info.objectType); if (!type_props) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } if (cs->algo == TEE_ALG_DH_DERIVE_SHARED_SECRET) { struct bignum *pub = NULL; struct bignum *ss = NULL; size_t bin_size = 0; void *bbuf = NULL; if (param_count != 1 || params[0].attributeID != TEE_ATTR_DH_PUBLIC_VALUE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } bin_size = params[0].content.ref.length; if (MUL_OVERFLOW(bin_size, 8, &alloc_size)) { res = TEE_ERROR_OVERFLOW; goto out; } res = bb_memdup_user(params[0].content.ref.buffer, bin_size, &bbuf); if (res) goto out; pub = crypto_bignum_allocate(alloc_size); ss = crypto_bignum_allocate(alloc_size); if (pub && ss) { crypto_bignum_bin2bn(bbuf, bin_size, pub); res = crypto_acipher_dh_shared_secret(ko->attr, pub, ss); if (res == TEE_SUCCESS) { sk->key_size = crypto_bignum_num_bytes(ss); crypto_bignum_bn2bin(ss, (uint8_t *)(sk + 1)); so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } } else { res = TEE_ERROR_OUT_OF_MEMORY; } crypto_bignum_free(&pub); crypto_bignum_free(&ss); } else if (cs->algo == TEE_ALG_ECDH_DERIVE_SHARED_SECRET) { uint32_t curve = ((struct ecc_keypair *)ko->attr)->curve; struct ecc_public_key key_public = { }; uint8_t *pt_secret = NULL; unsigned long pt_secret_len = 0; uint32_t key_type = TEE_TYPE_ECDH_PUBLIC_KEY; void *x_bbuf = NULL; void *y_bbuf = NULL; if (param_count != 2 || params[0].attributeID != TEE_ATTR_ECC_PUBLIC_VALUE_X || params[1].attributeID != TEE_ATTR_ECC_PUBLIC_VALUE_Y) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } switch (curve) { case TEE_ECC_CURVE_NIST_P192: alloc_size = 192; break; case TEE_ECC_CURVE_NIST_P224: alloc_size = 224; break; case TEE_ECC_CURVE_NIST_P256: alloc_size = 256; break; case TEE_ECC_CURVE_NIST_P384: alloc_size = 384; break; case TEE_ECC_CURVE_NIST_P521: alloc_size = 521; break; default: res = TEE_ERROR_NOT_IMPLEMENTED; goto out; } res = bb_memdup_user(params[0].content.ref.buffer, params[0].content.ref.length, &x_bbuf); if (res) goto out; res = bb_memdup_user(params[1].content.ref.buffer, params[1].content.ref.length, &y_bbuf); if (res) goto out; /* Create the public key */ res = crypto_acipher_alloc_ecc_public_key(&key_public, key_type, alloc_size); if (res != TEE_SUCCESS) goto out; key_public.curve = curve; crypto_bignum_bin2bn(x_bbuf, params[0].content.ref.length, key_public.x); crypto_bignum_bin2bn(y_bbuf, params[1].content.ref.length, key_public.y); pt_secret = (uint8_t *)(sk + 1); pt_secret_len = sk->alloc_size; res = crypto_acipher_ecc_shared_secret(ko->attr, &key_public, pt_secret, &pt_secret_len); if (res == TEE_SUCCESS) { sk->key_size = pt_secret_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } /* free the public key */ crypto_acipher_free_ecc_public_key(&key_public); } #if defined(CFG_CRYPTO_HKDF) else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_HKDF) { void *salt, *info; size_t salt_len, info_len, okm_len; uint32_t hash_id = 0; struct tee_cryp_obj_secret *ik = ko->attr; const uint8_t *ikm = (const uint8_t *)(ik + 1); res = get_hkdf_params(cs->algo, params, param_count, &salt, &salt_len, &info, &info_len, &okm_len, &hash_id); if (res != TEE_SUCCESS) goto out; /* Requested size must fit into the output object's buffer */ if (okm_len > ik->alloc_size) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_cryp_hkdf(hash_id, ikm, ik->key_size, salt, salt_len, info, info_len, (uint8_t *)(sk + 1), okm_len); if (res == TEE_SUCCESS) { sk->key_size = okm_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } } #endif #if defined(CFG_CRYPTO_CONCAT_KDF) else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_CONCAT_KDF) { void *info; size_t info_len, derived_key_len; uint32_t hash_id = TEE_ALG_GET_DIGEST_HASH(cs->algo); struct tee_cryp_obj_secret *ss = ko->attr; const uint8_t *shared_secret = (const uint8_t *)(ss + 1); res = get_concat_kdf_params(params, param_count, &info, &info_len, &derived_key_len); if (res != TEE_SUCCESS) goto out; /* Requested size must fit into the output object's buffer */ if (derived_key_len > ss->alloc_size) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_cryp_concat_kdf(hash_id, shared_secret, ss->key_size, info, info_len, (uint8_t *)(sk + 1), derived_key_len); if (res == TEE_SUCCESS) { sk->key_size = derived_key_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } } #endif #if defined(CFG_CRYPTO_PBKDF2) else if (TEE_ALG_GET_MAIN_ALG(cs->algo) == TEE_MAIN_ALGO_PBKDF2) { void *salt; size_t salt_len, iteration_count, derived_key_len; uint32_t hash_id = TEE_ALG_GET_DIGEST_HASH(cs->algo); struct tee_cryp_obj_secret *ss = ko->attr; const uint8_t *password = (const uint8_t *)(ss + 1); res = get_pbkdf2_params(params, param_count, &salt, &salt_len, &derived_key_len, &iteration_count); if (res != TEE_SUCCESS) goto out; /* Requested size must fit into the output object's buffer */ if (derived_key_len > ss->alloc_size) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_cryp_pbkdf2(hash_id, password, ss->key_size, salt, salt_len, iteration_count, (uint8_t *)(sk + 1), derived_key_len); if (res == TEE_SUCCESS) { sk->key_size = derived_key_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } } #endif #if defined(CFG_CRYPTO_SM2_KEP) else if (cs->algo == TEE_ALG_SM2_KEP) { struct ecc_public_key peer_eph_key = { }; struct ecc_public_key peer_key = { }; struct sm2_kep_parms kep_parms = { .out = (uint8_t *)(sk + 1), .out_len = so->info.maxObjectSize, }; struct tee_obj *ko2 = NULL; res = tee_obj_get(utc, cs->key2, &ko2); if (res != TEE_SUCCESS) goto out; res = get_sm2_kep_params(params, param_count, &peer_key, &peer_eph_key, &kep_parms); if (res != TEE_SUCCESS) goto out; /* * key1 is our private keypair, key2 is our ephemeral public key */ res = crypto_acipher_sm2_kep_derive(ko->attr, /* key1 */ ko2->attr, /* key2 */ &peer_key, &peer_eph_key, &kep_parms); if (res == TEE_SUCCESS) { sk->key_size = kep_parms.out_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } crypto_acipher_free_ecc_public_key(&peer_key); crypto_acipher_free_ecc_public_key(&peer_eph_key); } #endif #if defined(CFG_CRYPTO_X25519) else if (cs->algo == TEE_ALG_X25519) { uint8_t *x25519_pub_key = NULL; uint8_t *pt_secret = NULL; unsigned long pt_secret_len = 0; void *bbuf = NULL; if (param_count != 1 || params[0].attributeID != TEE_ATTR_X25519_PUBLIC_VALUE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* X25519 public key size is 32 bytes */ if (params[0].content.ref.length != KEY_SIZE_BYTES_25519) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = bb_memdup_user(params[0].content.ref.buffer, params[0].content.ref.length, &bbuf); if (res) goto out; /* Set the public key */ x25519_pub_key = bbuf; pt_secret = (uint8_t *)(sk + 1); pt_secret_len = sk->alloc_size; res = crypto_acipher_x25519_shared_secret(ko->attr, x25519_pub_key, pt_secret, &pt_secret_len); if (res == TEE_SUCCESS) { sk->key_size = pt_secret_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } } #endif #if defined(CFG_CRYPTO_X448) else if (cs->algo == TEE_ALG_X448) { uint8_t *x448_pub_key = NULL; uint8_t *pt_secret = NULL; unsigned long pt_secret_len = 0; void *bbuf = NULL; if (param_count != 1 || params[0].attributeID != TEE_ATTR_X448_PUBLIC_VALUE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* X448 public key size is 56 bytes */ if (params[0].content.ref.length != KEY_SIZE_BYTES_448) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = bb_memdup_user(params[0].content.ref.buffer, params[0].content.ref.length, &bbuf); if (res) goto out; /* Set the public key */ x448_pub_key = bbuf; pt_secret = (uint8_t *)(sk + 1); pt_secret_len = sk->alloc_size; res = crypto_acipher_x448_shared_secret(ko->attr, x448_pub_key, pt_secret, &pt_secret_len); if (res == TEE_SUCCESS) { sk->key_size = pt_secret_len; so->info.handleFlags |= TEE_HANDLE_FLAG_INITIALIZED; set_attribute(so, type_props, TEE_ATTR_SECRET_VALUE); } } #endif else res = TEE_ERROR_NOT_SUPPORTED; out: free_wipe(params); return res; } TEE_Result syscall_cryp_random_number_generate(void *buf, size_t blen) { TEE_Result res = TEE_SUCCESS; void *bbuf = NULL; bbuf = bb_alloc(blen); if (!bbuf) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_rng_read(bbuf, blen); if (res != TEE_SUCCESS) return res; res = copy_to_user(buf, bbuf, blen); return res; } TEE_Result syscall_authenc_init(unsigned long state, const void *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len) { struct ts_session *sess = ts_get_current_session(); struct tee_cryp_obj_secret *key = NULL; struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; void *nonce_bbuf = NULL; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; res = tee_obj_get(to_user_ta_ctx(sess->ctx), cs->key1, &o); if (res != TEE_SUCCESS) return res; if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) return TEE_ERROR_BAD_PARAMETERS; key = o->attr; res = bb_memdup_user(nonce, nonce_len, &nonce_bbuf); if (res) return res; res = crypto_authenc_init(cs->ctx, cs->mode, (uint8_t *)(key + 1), key->key_size, nonce_bbuf, nonce_len, tag_len, aad_len, payload_len); if (res != TEE_SUCCESS) return res; cs->ctx_finalize = crypto_authenc_final; cs->state = CRYP_STATE_INITIALIZED; return TEE_SUCCESS; } TEE_Result syscall_authenc_update_aad(unsigned long state, const void *aad_data, size_t aad_data_len) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_cryp_state *cs = NULL; aad_data = memtag_strip_tag_const(aad_data); res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)aad_data, aad_data_len); if (res != TEE_SUCCESS) return res; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) return TEE_ERROR_BAD_STATE; enter_user_access(); res = crypto_authenc_update_aad(cs->ctx, cs->mode, aad_data, aad_data_len); exit_user_access(); if (res != TEE_SUCCESS) return res; return TEE_SUCCESS; } TEE_Result syscall_authenc_update_payload(unsigned long state, const void *src_data, size_t src_len, void *dst_data, uint64_t *dst_len) { struct ts_session *sess = ts_get_current_session(); struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; size_t dlen = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) return TEE_ERROR_BAD_STATE; src_data = memtag_strip_tag_const(src_data); dst_data = memtag_strip_tag(dst_data); res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)src_data, src_len); if (res != TEE_SUCCESS) return res; res = get_user_u64_as_size_t(&dlen, dst_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(&to_user_ta_ctx(sess->ctx)->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)dst_data, dlen); if (res != TEE_SUCCESS) return res; if (dlen < src_len) { res = TEE_ERROR_SHORT_BUFFER; goto out; } enter_user_access(); res = crypto_authenc_update_payload(cs->ctx, cs->mode, src_data, src_len, dst_data, &dlen); exit_user_access(); out: if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { TEE_Result res2 = put_user_u64(dst_len, dlen); if (res2 != TEE_SUCCESS) res = res2; } return res; } TEE_Result syscall_authenc_enc_final(unsigned long state, const void *src_data, size_t src_len, void *dst_data, uint64_t *dst_len, void *tag, uint64_t *tag_len) { struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx; struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; size_t dlen = 0; size_t tlen = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; if (cs->mode != TEE_MODE_ENCRYPT) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) return TEE_ERROR_BAD_STATE; src_data = memtag_strip_tag_const(src_data); dst_data = memtag_strip_tag(dst_data); tag = memtag_strip_tag(tag); res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)src_data, src_len); if (res != TEE_SUCCESS) return res; if (!dst_len) { dlen = 0; } else { res = get_user_u64_as_size_t(&dlen, dst_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)dst_data, dlen); if (res != TEE_SUCCESS) return res; } if (dlen < src_len) { res = TEE_ERROR_SHORT_BUFFER; goto out; } res = get_user_u64_as_size_t(&tlen, tag_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)tag, tlen); if (res != TEE_SUCCESS) return res; enter_user_access(); res = crypto_authenc_enc_final(cs->ctx, src_data, src_len, dst_data, &dlen, tag, &tlen); exit_user_access(); out: if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { TEE_Result res2 = TEE_SUCCESS; if (dst_len != NULL) { res2 = put_user_u64(dst_len, dlen); if (res2 != TEE_SUCCESS) return res2; } res2 = put_user_u64(tag_len, tlen); if (res2 != TEE_SUCCESS) return res2; } return res; } TEE_Result syscall_authenc_dec_final(unsigned long state, const void *src_data, size_t src_len, void *dst_data, uint64_t *dst_len, const void *tag, size_t tag_len) { struct ts_session *sess = ts_get_current_session(); struct user_mode_ctx *uctx = &to_user_ta_ctx(sess->ctx)->uctx; struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; size_t dlen = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->state != CRYP_STATE_INITIALIZED) return TEE_ERROR_BAD_STATE; if (cs->mode != TEE_MODE_DECRYPT) return TEE_ERROR_BAD_PARAMETERS; if (TEE_ALG_GET_CLASS(cs->algo) != TEE_OPERATION_AE) return TEE_ERROR_BAD_STATE; src_data = memtag_strip_tag_const(src_data); dst_data = memtag_strip_tag(dst_data); tag = memtag_strip_tag_const(tag); res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)src_data, src_len); if (res != TEE_SUCCESS) return res; if (!dst_len) { dlen = 0; } else { res = get_user_u64_as_size_t(&dlen, dst_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)dst_data, dlen); if (res != TEE_SUCCESS) return res; } if (dlen < src_len) { res = TEE_ERROR_SHORT_BUFFER; goto out; } /* Despite TEE Internal Core API up to v1.3, tag is [inbuf], not [in] */ res = vm_check_access_rights(uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)tag, tag_len); if (res != TEE_SUCCESS) return res; enter_user_access(); res = crypto_authenc_dec_final(cs->ctx, src_data, src_len, dst_data, &dlen, tag, tag_len); exit_user_access(); out: if ((res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) && dst_len != NULL) { TEE_Result res2 = put_user_u64(dst_len, dlen); if (res2 != TEE_SUCCESS) return res2; } return res; } static int pkcs1_get_salt_len(const TEE_Attribute *params, uint32_t num_params, size_t default_len) { size_t n; assert(default_len < INT_MAX); for (n = 0; n < num_params; n++) { if (params[n].attributeID == TEE_ATTR_RSA_PSS_SALT_LENGTH) { if (params[n].content.value.a < INT_MAX) return params[n].content.value.a; break; } } /* * If salt length isn't provided use the default value which is * the length of the digest. */ return default_len; } TEE_Result syscall_asymm_operate(unsigned long state, const struct utee_attribute *usr_params, size_t num_params, const void *src_data, size_t src_len, void *dst_data, uint64_t *dst_len) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_cryp_state *cs = NULL; size_t dlen = 0; struct tee_obj *o = NULL; void *label = NULL; size_t label_len = 0; size_t n = 0; int salt_len = 0; TEE_Attribute *params = NULL; size_t alloc_size = 0; uint32_t mgf_algo = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; src_data = memtag_strip_tag_const(src_data); dst_data = memtag_strip_tag(dst_data); res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)src_data, src_len); if (res != TEE_SUCCESS) return res; res = get_user_u64_as_size_t(&dlen, dst_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)dst_data, dlen); if (res != TEE_SUCCESS) return res; if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size)) return TEE_ERROR_OVERFLOW; params = malloc(alloc_size); if (!params) return TEE_ERROR_OUT_OF_MEMORY; res = copy_in_attrs(utc, usr_params, num_params, params); if (res != TEE_SUCCESS) goto out; res = tee_obj_get(utc, cs->key1, &o); if (res != TEE_SUCCESS) goto out; if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_GENERIC; goto out; } switch (cs->algo) { case TEE_ALG_RSA_NOPAD: if (cs->mode == TEE_MODE_ENCRYPT) { enter_user_access(); res = crypto_acipher_rsanopad_encrypt(o->attr, src_data, src_len, dst_data, &dlen); exit_user_access(); } else if (cs->mode == TEE_MODE_DECRYPT) { enter_user_access(); res = crypto_acipher_rsanopad_decrypt(o->attr, src_data, src_len, dst_data, &dlen); exit_user_access(); } else { /* * We will panic because "the mode is not compatible * with the function" */ res = TEE_ERROR_GENERIC; } break; case TEE_ALG_SM2_PKE: if (cs->mode == TEE_MODE_ENCRYPT) { enter_user_access(); res = crypto_acipher_sm2_pke_encrypt(o->attr, src_data, src_len, dst_data, &dlen); exit_user_access(); } else if (cs->mode == TEE_MODE_DECRYPT) { enter_user_access(); res = crypto_acipher_sm2_pke_decrypt(o->attr, src_data, src_len, dst_data, &dlen); exit_user_access(); } else { res = TEE_ERROR_GENERIC; } break; case TEE_ALG_RSAES_PKCS1_V1_5: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: for (n = 0; n < num_params; n++) { if (params[n].attributeID == TEE_ATTR_RSA_OAEP_LABEL) { label = params[n].content.ref.buffer; label_len = params[n].content.ref.length; break; } if (cs->algo != TEE_ALG_RSAES_PKCS1_V1_5 && params[n].attributeID == TEE_ATTR_RSA_OAEP_MGF_HASH) { void *buf = params[n].content.ref.buffer; if (params[n].content.ref.length != sizeof(mgf_algo)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = copy_from_user(&mgf_algo, buf, sizeof(mgf_algo)); if (res) goto out; } } if (!mgf_algo) mgf_algo = TEE_INTERNAL_HASH_TO_ALGO(cs->algo); if (cs->mode == TEE_MODE_ENCRYPT) { enter_user_access(); res = crypto_acipher_rsaes_encrypt(cs->algo, o->attr, label, label_len, mgf_algo, src_data, src_len, dst_data, &dlen); exit_user_access(); } else if (cs->mode == TEE_MODE_DECRYPT) { enter_user_access(); res = crypto_acipher_rsaes_decrypt( cs->algo, o->attr, label, label_len, mgf_algo, src_data, src_len, dst_data, &dlen); exit_user_access(); } else { res = TEE_ERROR_BAD_PARAMETERS; } break; #if defined(CFG_CRYPTO_RSASSA_NA1) case TEE_ALG_RSASSA_PKCS1_V1_5: #endif case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: if (cs->mode != TEE_MODE_SIGN) { res = TEE_ERROR_BAD_PARAMETERS; break; } salt_len = pkcs1_get_salt_len(params, num_params, src_len); enter_user_access(); res = crypto_acipher_rsassa_sign(cs->algo, o->attr, salt_len, src_data, src_len, dst_data, &dlen); exit_user_access(); break; case TEE_ALG_DSA_SHA1: case TEE_ALG_DSA_SHA224: case TEE_ALG_DSA_SHA256: enter_user_access(); res = crypto_acipher_dsa_sign(cs->algo, o->attr, src_data, src_len, dst_data, &dlen); exit_user_access(); break; case TEE_ALG_ED25519: enter_user_access(); res = tee_svc_obj_ed25519_sign(o->attr, src_data, src_len, dst_data, &dlen, params, num_params); exit_user_access(); break; case TEE_ALG_ECDSA_SHA1: case TEE_ALG_ECDSA_SHA224: case TEE_ALG_ECDSA_SHA256: case TEE_ALG_ECDSA_SHA384: case TEE_ALG_ECDSA_SHA512: case TEE_ALG_SM2_DSA_SM3: enter_user_access(); res = crypto_acipher_ecc_sign(cs->algo, o->attr, src_data, src_len, dst_data, &dlen); exit_user_access(); break; default: res = TEE_ERROR_BAD_PARAMETERS; break; } out: free_wipe(params); if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { TEE_Result res2 = put_user_u64(dst_len, dlen); if (res2 != TEE_SUCCESS) return res2; } return res; } TEE_Result syscall_asymm_verify(unsigned long state, const struct utee_attribute *usr_params, size_t num_params, const void *data, size_t data_len, const void *sig, size_t sig_len) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); struct tee_cryp_state *cs = NULL; TEE_Result res = TEE_SUCCESS; TEE_Attribute *params = NULL; struct tee_obj *o = NULL; size_t hash_size = 0; uint32_t hash_algo = 0; int salt_len = 0; size_t alloc_size = 0; res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs); if (res != TEE_SUCCESS) return res; if (cs->mode != TEE_MODE_VERIFY) return TEE_ERROR_BAD_PARAMETERS; data = memtag_strip_tag_const(data); sig = memtag_strip_tag_const(sig); res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)data, data_len); if (res != TEE_SUCCESS) return res; res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER, (uaddr_t)sig, sig_len); if (res != TEE_SUCCESS) return res; if (MUL_OVERFLOW(sizeof(TEE_Attribute), num_params, &alloc_size)) return TEE_ERROR_OVERFLOW; params = malloc(alloc_size); if (!params) return TEE_ERROR_OUT_OF_MEMORY; res = copy_in_attrs(utc, usr_params, num_params, params); if (res != TEE_SUCCESS) goto out; res = tee_obj_get(utc, cs->key1, &o); if (res != TEE_SUCCESS) goto out; if ((o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } switch (TEE_ALG_GET_MAIN_ALG(cs->algo)) { case TEE_MAIN_ALGO_RSA: if (cs->algo != TEE_ALG_RSASSA_PKCS1_V1_5) { hash_algo = TEE_DIGEST_HASH_TO_ALGO(cs->algo); res = tee_alg_get_digest_size(hash_algo, &hash_size); if (res != TEE_SUCCESS) break; if (data_len != hash_size) { res = TEE_ERROR_BAD_PARAMETERS; break; } salt_len = pkcs1_get_salt_len(params, num_params, hash_size); } enter_user_access(); res = crypto_acipher_rsassa_verify(cs->algo, o->attr, salt_len, data, data_len, sig, sig_len); exit_user_access(); break; case TEE_MAIN_ALGO_DSA: hash_algo = TEE_DIGEST_HASH_TO_ALGO(cs->algo); res = tee_alg_get_digest_size(hash_algo, &hash_size); if (res != TEE_SUCCESS) break; if (data_len != hash_size) { struct dsa_public_key *key = o->attr; /* * Depending on the DSA algorithm (NIST), the * digital signature output size may be truncated * to the size of a key pair (Q prime size). Q * prime size must be less or equal than the hash * output length of the hash algorithm involved. * * We're checking here in order to be able to * return this particular error code, which will * cause TEE_AsymmetricVerifyDigest() to panic as * required by GP. crypto_acipher_dsa_verify() is * implemented in the glue layer of the crypto * library and it might be a bit harder to catch * this particular case there or lead to duplicated * code in different crypto glue layers. * * The GP spec says that we SHOULD panic if * data_len != hash_size, but that would break a * few of the DSA tests in xtest where the * hash_size is larger than possible data_len. So * the compromise is in case data_len != hash_size * check that it's not smaller than what makes * sense. */ if (data_len != crypto_bignum_num_bytes(key->q)) { res = TEE_ERROR_BAD_PARAMETERS; break; } } enter_user_access(); res = crypto_acipher_dsa_verify(cs->algo, o->attr, data, data_len, sig, sig_len); exit_user_access(); break; case TEE_MAIN_ALGO_ED25519: enter_user_access(); res = tee_svc_obj_ed25519_verify(o->attr, data, data_len, sig, sig_len, params, num_params); exit_user_access(); break; case TEE_MAIN_ALGO_ECDSA: case TEE_MAIN_ALGO_SM2_DSA_SM3: enter_user_access(); res = crypto_acipher_ecc_verify(cs->algo, o->attr, data, data_len, sig, sig_len); exit_user_access(); break; default: res = TEE_ERROR_NOT_SUPPORTED; } out: free_wipe(params); return res; } optee_os-4.3.0/core/tee/tee_svc_storage.c000066400000000000000000000533161464416617300204040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, 2022-2023 Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Header of GP formated secure storage files */ struct tee_svc_storage_head { uint32_t attr_size; uint32_t objectSize; uint32_t maxObjectSize; uint32_t objectUsage; uint32_t objectType; uint32_t have_attrs; }; struct tee_storage_enum { TAILQ_ENTRY(tee_storage_enum) link; struct tee_fs_dir *dir; const struct tee_file_operations *fops; }; static TEE_Result tee_svc_storage_get_enum(struct user_ta_ctx *utc, vaddr_t enum_id, struct tee_storage_enum **e_out) { struct tee_storage_enum *e; TAILQ_FOREACH(e, &utc->storage_enums, link) { if (enum_id == (vaddr_t)e) { *e_out = e; return TEE_SUCCESS; } } return TEE_ERROR_BAD_PARAMETERS; } static TEE_Result tee_svc_close_enum(struct user_ta_ctx *utc, struct tee_storage_enum *e) { if (e == NULL || utc == NULL) return TEE_ERROR_BAD_PARAMETERS; TAILQ_REMOVE(&utc->storage_enums, e, link); if (e->fops) e->fops->closedir(e->dir); e->dir = NULL; e->fops = NULL; free(e); return TEE_SUCCESS; } static void remove_corrupt_obj(struct user_ta_ctx *utc, struct tee_obj *o) { o->pobj->fops->remove(o->pobj); if (!(utc->ta_ctx.flags & TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT)) tee_obj_close(utc, o); } static TEE_Result tee_svc_storage_read_head(struct tee_obj *o) { TEE_Result res = TEE_SUCCESS; size_t bytes; struct tee_svc_storage_head head; const struct tee_file_operations *fops = o->pobj->fops; void *attr = NULL; size_t size; size_t tmp = 0; assert(!o->fh); res = fops->open(o->pobj, &size, &o->fh); if (res != TEE_SUCCESS) goto exit; /* read head */ bytes = sizeof(struct tee_svc_storage_head); res = fops->read(o->fh, 0, &head, NULL, &bytes); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) EMSG("Head corrupt"); goto exit; } if (ADD_OVERFLOW(sizeof(head), head.attr_size, &tmp)) { res = TEE_ERROR_OVERFLOW; goto exit; } if (tmp > size) { res = TEE_ERROR_CORRUPT_OBJECT; goto exit; } if (bytes != sizeof(struct tee_svc_storage_head)) { res = TEE_ERROR_BAD_FORMAT; goto exit; } res = tee_obj_set_type(o, head.objectType, head.maxObjectSize); if (res != TEE_SUCCESS) goto exit; o->ds_pos = tmp; if (head.attr_size) { attr = malloc(head.attr_size); if (!attr) { res = TEE_ERROR_OUT_OF_MEMORY; goto exit; } /* read meta */ bytes = head.attr_size; res = fops->read(o->fh, sizeof(struct tee_svc_storage_head), attr, NULL, &bytes); if (res == TEE_ERROR_OUT_OF_MEMORY) goto exit; if (res != TEE_SUCCESS || bytes != head.attr_size) res = TEE_ERROR_CORRUPT_OBJECT; if (res) goto exit; } res = tee_obj_attr_from_binary(o, attr, head.attr_size); if (res != TEE_SUCCESS) goto exit; o->info.dataSize = size - sizeof(head) - head.attr_size; o->info.objectSize = head.objectSize; o->pobj->obj_info_usage = head.objectUsage; o->info.objectType = head.objectType; o->have_attrs = head.have_attrs; exit: free(attr); return res; } TEE_Result syscall_storage_obj_open(unsigned long storage_id, void *object_id, size_t object_id_len, unsigned long flags, uint32_t *obj) { const unsigned long valid_flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | TEE_DATA_FLAG_SHARE_WRITE; const struct tee_file_operations *fops = tee_svc_storage_file_ops(storage_id); struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_pobj *po = NULL; struct tee_obj *o = NULL; void *oid_bbuf = NULL; if (flags & ~valid_flags) return TEE_ERROR_BAD_PARAMETERS; if (!fops) { res = TEE_ERROR_ITEM_NOT_FOUND; goto exit; } if (object_id_len > TEE_OBJECT_ID_MAX_LEN) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } res = bb_memdup_user_private(object_id, object_id_len, &oid_bbuf); if (res) goto exit; res = tee_pobj_get((void *)&sess->ctx->uuid, oid_bbuf, object_id_len, flags, TEE_POBJ_USAGE_OPEN, fops, &po); bb_free(oid_bbuf, object_id_len); if (res != TEE_SUCCESS) goto err; o = tee_obj_alloc(); if (o == NULL) { tee_pobj_release(po); res = TEE_ERROR_OUT_OF_MEMORY; goto err; } o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED | flags; o->pobj = po; tee_obj_add(utc, o); tee_pobj_lock_usage(o->pobj); res = tee_svc_storage_read_head(o); tee_pobj_unlock_usage(o->pobj); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); goto err; } goto oclose; } res = copy_kaddr_to_uref(obj, o); if (res != TEE_SUCCESS) goto oclose; goto exit; oclose: tee_obj_close(utc, o); o = NULL; err: if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) res = TEE_ERROR_CORRUPT_OBJECT; if (res == TEE_ERROR_CORRUPT_OBJECT && o) remove_corrupt_obj(utc, o); exit: return res; } static TEE_Result tee_svc_storage_init_file(struct tee_obj *o, bool overwrite, struct tee_obj *attr_o, void *data, uint32_t len) { TEE_Result res = TEE_SUCCESS; struct tee_svc_storage_head head = { }; const struct tee_file_operations *fops = o->pobj->fops; void *attr = NULL; size_t attr_size = 0; if (attr_o) { if (o != attr_o) { res = tee_obj_set_type(o, attr_o->info.objectType, attr_o->info.maxObjectSize); if (res) return res; res = tee_obj_attr_copy_from(o, attr_o); if (res) return res; o->have_attrs = attr_o->have_attrs; o->pobj->obj_info_usage = attr_o->info.objectUsage; o->info.objectSize = attr_o->info.objectSize; } res = tee_obj_attr_to_binary(o, NULL, &attr_size); if (res) return res; if (attr_size) { attr = malloc(attr_size); if (!attr) return TEE_ERROR_OUT_OF_MEMORY; res = tee_obj_attr_to_binary(o, attr, &attr_size); if (res != TEE_SUCCESS) goto exit; } } else { res = tee_obj_set_type(o, TEE_TYPE_DATA, 0); if (res != TEE_SUCCESS) goto exit; } o->ds_pos = sizeof(struct tee_svc_storage_head) + attr_size; /* write head */ head.attr_size = attr_size; head.objectSize = o->info.objectSize; head.maxObjectSize = o->info.maxObjectSize; head.objectUsage = o->pobj->obj_info_usage; head.objectType = o->info.objectType; head.have_attrs = o->have_attrs; res = fops->create(o->pobj, overwrite, &head, sizeof(head), attr, attr_size, NULL, data, len, &o->fh); if (res) o->ds_pos = 0; else o->info.dataSize = len; exit: free(attr); return res; } TEE_Result syscall_storage_obj_create(unsigned long storage_id, void *object_id, size_t object_id_len, unsigned long flags, unsigned long attr, void *data, size_t len, uint32_t *obj) { const unsigned long valid_flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_SHARE_READ | TEE_DATA_FLAG_SHARE_WRITE | TEE_DATA_FLAG_OVERWRITE; const struct tee_file_operations *fops = tee_svc_storage_file_ops(storage_id); struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); struct tee_obj *attr_o = NULL; TEE_Result res = TEE_SUCCESS; struct tee_pobj *po = NULL; struct tee_obj *o = NULL; void *oid_bbuf = NULL; if (flags & ~valid_flags) return TEE_ERROR_BAD_PARAMETERS; if (!fops) return TEE_ERROR_ITEM_NOT_FOUND; if (object_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; object_id = memtag_strip_tag(object_id); data = memtag_strip_tag(data); /* Check presence of optional buffer */ if (len && !data) return TEE_ERROR_BAD_PARAMETERS; res = bb_memdup_user_private(object_id, object_id_len, &oid_bbuf); if (res) return res; res = tee_pobj_get((void *)&sess->ctx->uuid, oid_bbuf, object_id_len, flags, TEE_POBJ_USAGE_CREATE, fops, &po); bb_free(oid_bbuf, object_id_len); if (res != TEE_SUCCESS) goto err; if (attr != TEE_HANDLE_NULL) { res = tee_obj_get(utc, uref_to_vaddr(attr), &attr_o); if (res != TEE_SUCCESS) goto err; /* The supplied handle must be one of an initialized object */ if (!(attr_o->info.handleFlags & TEE_HANDLE_FLAG_INITIALIZED)) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } } if (!obj && attr_o && !(attr_o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { /* * The caller expects the supplied attributes handle to be * transformed into a persistent object. * * Persistent object keeps the objectUsage field in the * pobj so move the field below. */ uint32_t saved_flags = attr_o->info.handleFlags; attr_o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED | flags; attr_o->pobj = po; po->obj_info_usage = attr_o->info.objectUsage; res = tee_svc_storage_init_file(attr_o, flags & TEE_DATA_FLAG_OVERWRITE, attr_o, data, len); if (res) { attr_o->info.handleFlags = saved_flags; attr_o->pobj = NULL; goto err; } attr_o->info.objectUsage = 0; } else { o = tee_obj_alloc(); if (!o) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } o->info.handleFlags = TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED | flags; o->pobj = po; res = tee_svc_storage_init_file(o, flags & TEE_DATA_FLAG_OVERWRITE, attr_o, data, len); if (res != TEE_SUCCESS) goto err; po = NULL; /* o owns it from now on */ tee_obj_add(utc, o); if (obj) { res = copy_kaddr_to_uref(obj, o); if (res != TEE_SUCCESS) goto oclose; } tee_pobj_create_final(o->pobj); if (!obj) tee_obj_close(utc, o); } return TEE_SUCCESS; oclose: tee_obj_close(utc, o); return res; err: if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) res = TEE_ERROR_CORRUPT_OBJECT; if (res == TEE_ERROR_CORRUPT_OBJECT && po) fops->remove(po); if (o) { fops->close(&o->fh); tee_obj_free(o); } if (po) tee_pobj_release(po); return res; } TEE_Result syscall_storage_obj_del(unsigned long obj) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; res = tee_obj_get(utc, uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) return TEE_ERROR_ACCESS_CONFLICT; if (o->pobj == NULL || o->pobj->obj_id == NULL) return TEE_ERROR_BAD_STATE; if (IS_ENABLED(CFG_NXP_SE05X)) { /* Cryptographic layer house-keeping */ res = crypto_storage_obj_del(o); if (res) return res; } res = o->pobj->fops->remove(o->pobj); tee_obj_close(utc, o); return res; } TEE_Result syscall_storage_obj_rename(unsigned long obj, void *object_id, size_t object_id_len) { const struct tee_file_operations *fops = NULL; struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_pobj *po = NULL; struct tee_obj *o = NULL; char *new_file = NULL; char *old_file = NULL; void *oid_bbuf = NULL; if (object_id_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; res = tee_obj_get(utc, uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { res = TEE_ERROR_BAD_STATE; goto exit; } if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { res = TEE_ERROR_BAD_STATE; goto exit; } if (o->pobj == NULL || o->pobj->obj_id == NULL) { res = TEE_ERROR_BAD_STATE; goto exit; } res = bb_memdup_user_private(object_id, object_id_len, &oid_bbuf); if (res) goto exit; /* reserve dest name */ fops = o->pobj->fops; res = tee_pobj_get((void *)&sess->ctx->uuid, oid_bbuf, object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, TEE_POBJ_USAGE_RENAME, fops, &po); bb_free(oid_bbuf, object_id_len); if (res != TEE_SUCCESS) goto exit; /* move */ res = fops->rename(o->pobj, po, false /* no overwrite */); if (res) goto exit; res = tee_pobj_rename(o->pobj, po->obj_id, po->obj_id_len); exit: tee_pobj_release(po); free(new_file); free(old_file); return res; } TEE_Result syscall_storage_alloc_enum(uint32_t *obj_enum) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); struct tee_storage_enum *e = NULL; if (obj_enum == NULL) return TEE_ERROR_BAD_PARAMETERS; e = malloc(sizeof(struct tee_storage_enum)); if (e == NULL) return TEE_ERROR_OUT_OF_MEMORY; e->dir = NULL; e->fops = NULL; TAILQ_INSERT_TAIL(&utc->storage_enums, e, link); return copy_kaddr_to_uref(obj_enum, e); } TEE_Result syscall_storage_free_enum(unsigned long obj_enum) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); struct tee_storage_enum *e = NULL; TEE_Result res = TEE_SUCCESS; res = tee_svc_storage_get_enum(utc, uref_to_vaddr(obj_enum), &e); if (res != TEE_SUCCESS) return res; return tee_svc_close_enum(utc, e); } TEE_Result syscall_storage_reset_enum(unsigned long obj_enum) { struct ts_session *sess = ts_get_current_session(); struct tee_storage_enum *e = NULL; TEE_Result res = TEE_SUCCESS; res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj_enum), &e); if (res != TEE_SUCCESS) return res; if (e->fops) { e->fops->closedir(e->dir); e->fops = NULL; e->dir = NULL; } assert(!e->dir); return TEE_SUCCESS; } TEE_Result syscall_storage_start_enum(unsigned long obj_enum, unsigned long storage_id) { struct ts_session *sess = ts_get_current_session(); struct tee_storage_enum *e = NULL; TEE_Result res = TEE_SUCCESS; const struct tee_file_operations *fops = tee_svc_storage_file_ops(storage_id); res = tee_svc_storage_get_enum(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj_enum), &e); if (res != TEE_SUCCESS) return res; if (e->dir) { e->fops->closedir(e->dir); e->dir = NULL; } if (!fops) return TEE_ERROR_ITEM_NOT_FOUND; e->fops = fops; return fops->opendir(&sess->ctx->uuid, &e->dir); } TEE_Result syscall_storage_next_enum(unsigned long obj_enum, struct utee_object_info *info, void *obj_id, uint64_t *len) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); struct tee_storage_enum *e = NULL; struct tee_fs_dirent *d = NULL; TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; uint64_t l = 0; struct utee_object_info bbuf = { }; res = tee_svc_storage_get_enum(utc, uref_to_vaddr(obj_enum), &e); if (res != TEE_SUCCESS) goto exit; info = memtag_strip_tag(info); obj_id = memtag_strip_tag(obj_id); /* check rights of the provided buffers */ res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, (uaddr_t)info, sizeof(*info)); if (res != TEE_SUCCESS) goto exit; res = vm_check_access_rights(&utc->uctx, TEE_MEMORY_ACCESS_WRITE, (uaddr_t)obj_id, TEE_OBJECT_ID_MAX_LEN); if (res != TEE_SUCCESS) goto exit; if (!e->fops) { res = TEE_ERROR_ITEM_NOT_FOUND; goto exit; } res = e->fops->readdir(e->dir, &d); if (res != TEE_SUCCESS) goto exit; o = tee_obj_alloc(); if (o == NULL) { res = TEE_ERROR_OUT_OF_MEMORY; goto exit; } res = tee_pobj_get(&sess->ctx->uuid, d->oid, d->oidlen, 0, TEE_POBJ_USAGE_ENUM, e->fops, &o->pobj); if (res) goto exit; o->info.handleFlags = o->pobj->flags | TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; tee_pobj_lock_usage(o->pobj); res = tee_svc_storage_read_head(o); bbuf = (struct utee_object_info){ .obj_type = o->info.objectType, .obj_size = o->info.objectSize, .max_obj_size = o->info.maxObjectSize, .obj_usage = o->pobj->obj_info_usage, .data_size = o->info.dataSize, .data_pos = o->info.dataPosition, .handle_flags = o->info.handleFlags, }; tee_pobj_unlock_usage(o->pobj); if (res != TEE_SUCCESS) goto exit; res = copy_to_user(info, &bbuf, sizeof(bbuf)); if (res) goto exit; res = copy_to_user(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); if (res) goto exit; l = o->pobj->obj_id_len; res = copy_to_user_private(len, &l, sizeof(*len)); exit: if (o) { if (o->pobj) { o->pobj->fops->close(&o->fh); tee_pobj_release(o->pobj); } tee_obj_free(o); } return res; } TEE_Result syscall_storage_obj_read(unsigned long obj, void *data, size_t len, uint64_t *count) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; uint64_t u_count = 0; size_t pos_tmp = 0; size_t bytes = 0; res = tee_obj_get(utc, uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) goto exit; if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { res = TEE_ERROR_BAD_STATE; goto exit; } if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_READ)) { res = TEE_ERROR_ACCESS_CONFLICT; goto exit; } /* Guard o->info.dataPosition += bytes below from overflowing */ if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { res = TEE_ERROR_OVERFLOW; goto exit; } data = memtag_strip_tag(data); bytes = len; if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { res = TEE_ERROR_OVERFLOW; goto exit; } res = o->pobj->fops->read(o->fh, pos_tmp, NULL, data, &bytes); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); remove_corrupt_obj(utc, o); } goto exit; } o->info.dataPosition += bytes; u_count = bytes; res = copy_to_user_private(count, &u_count, sizeof(*count)); exit: return res; } TEE_Result syscall_storage_obj_write(unsigned long obj, void *data, size_t len) { struct ts_session *sess = ts_get_current_session(); struct user_ta_ctx *utc = to_user_ta_ctx(sess->ctx); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; size_t pos_tmp = 0; res = tee_obj_get(utc, uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) goto exit; if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { res = TEE_ERROR_BAD_STATE; goto exit; } if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { res = TEE_ERROR_ACCESS_CONFLICT; goto exit; } /* Guard o->info.dataPosition += bytes below from overflowing */ if (ADD_OVERFLOW(o->info.dataPosition, len, &pos_tmp)) { res = TEE_ERROR_OVERFLOW; goto exit; } data = memtag_strip_tag(data); if (ADD_OVERFLOW(o->ds_pos, o->info.dataPosition, &pos_tmp)) { res = TEE_ERROR_ACCESS_CONFLICT; goto exit; } res = o->pobj->fops->write(o->fh, pos_tmp, NULL, data, len); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) { EMSG("Object corrupt"); remove_corrupt_obj(utc, o); } goto exit; } o->info.dataPosition += len; if (o->info.dataPosition > o->info.dataSize) o->info.dataSize = o->info.dataPosition; exit: return res; } TEE_Result tee_svc_storage_write_usage(struct tee_obj *o, uint32_t usage) { const size_t pos = offsetof(struct tee_svc_storage_head, objectUsage); return o->pobj->fops->write(o->fh, pos, &usage, NULL, sizeof(usage)); } TEE_Result syscall_storage_obj_trunc(unsigned long obj, size_t len) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; size_t off = 0; size_t attr_size = 0; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) goto exit; if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) { res = TEE_ERROR_BAD_STATE; goto exit; } if (!(o->info.handleFlags & TEE_DATA_FLAG_ACCESS_WRITE)) { res = TEE_ERROR_ACCESS_CONFLICT; goto exit; } res = tee_obj_attr_to_binary(o, NULL, &attr_size); if (res != TEE_SUCCESS) goto exit; if (ADD_OVERFLOW(sizeof(struct tee_svc_storage_head), attr_size, &off)) { res = TEE_ERROR_OVERFLOW; goto exit; } if (ADD_OVERFLOW(len, off, &off)) { res = TEE_ERROR_OVERFLOW; goto exit; } res = o->pobj->fops->truncate(o->fh, off); switch (res) { case TEE_SUCCESS: o->info.dataSize = len; break; case TEE_ERROR_CORRUPT_OBJECT: EMSG("Object corruption"); remove_corrupt_obj(to_user_ta_ctx(sess->ctx), o); break; default: res = TEE_ERROR_GENERIC; break; } exit: return res; } TEE_Result syscall_storage_obj_seek(unsigned long obj, int32_t offset, unsigned long whence) { struct ts_session *sess = ts_get_current_session(); TEE_Result res = TEE_SUCCESS; struct tee_obj *o = NULL; tee_fs_off_t new_pos = 0; res = tee_obj_get(to_user_ta_ctx(sess->ctx), uref_to_vaddr(obj), &o); if (res != TEE_SUCCESS) return res; if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) return TEE_ERROR_BAD_STATE; switch (whence) { case TEE_DATA_SEEK_SET: new_pos = offset; break; case TEE_DATA_SEEK_CUR: if (ADD_OVERFLOW(o->info.dataPosition, offset, &new_pos)) return TEE_ERROR_OVERFLOW; break; case TEE_DATA_SEEK_END: if (ADD_OVERFLOW(o->info.dataSize, offset, &new_pos)) return TEE_ERROR_OVERFLOW; break; default: return TEE_ERROR_BAD_PARAMETERS; } if (new_pos < 0) new_pos = 0; if (new_pos > TEE_DATA_MAX_POSITION) { EMSG("Position is beyond TEE_DATA_MAX_POSITION"); return TEE_ERROR_BAD_PARAMETERS; } o->info.dataPosition = new_pos; return TEE_SUCCESS; } void tee_svc_storage_close_all_enum(struct user_ta_ctx *utc) { struct tee_storage_enum_head *eh = &utc->storage_enums; /* disregard return value */ while (!TAILQ_EMPTY(eh)) tee_svc_close_enum(utc, TAILQ_FIRST(eh)); } optee_os-4.3.0/core/tee/tee_ta_enc_manager.c000066400000000000000000000030561464416617300210040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include TEE_Result tee_ta_decrypt_init(void **enc_ctx, struct shdr_encrypted_ta *ehdr, size_t len) { TEE_Result res = TEE_SUCCESS; uint8_t key[TEE_TA_ENC_KEY_SIZE] = {0}; res = crypto_authenc_alloc_ctx(enc_ctx, ehdr->enc_algo); if (res != TEE_SUCCESS) return res; res = tee_otp_get_ta_enc_key(ehdr->flags & SHDR_ENC_KEY_TYPE_MASK, key, sizeof(key)); if (res != TEE_SUCCESS) goto out_init; res = crypto_authenc_init(*enc_ctx, TEE_MODE_DECRYPT, key, sizeof(key), SHDR_ENC_GET_IV(ehdr), ehdr->iv_size, ehdr->tag_size, 0, len); out_init: if (res != TEE_SUCCESS) crypto_authenc_free_ctx(*enc_ctx); memzero_explicit(key, sizeof(key)); return res; } TEE_Result tee_ta_decrypt_update(void *enc_ctx, uint8_t *dst, uint8_t *src, size_t len) { TEE_Result res = TEE_SUCCESS; size_t dlen = len; res = crypto_authenc_update_payload(enc_ctx, TEE_MODE_DECRYPT, src, len, dst, &dlen); if (res != TEE_SUCCESS) crypto_authenc_free_ctx(enc_ctx); return res; } TEE_Result tee_ta_decrypt_final(void *enc_ctx, struct shdr_encrypted_ta *ehdr, uint8_t *dst, uint8_t *src, size_t len) { TEE_Result res = TEE_SUCCESS; size_t dlen = len; res = crypto_authenc_dec_final(enc_ctx, src, len, dst, &dlen, SHDR_ENC_GET_TAG(ehdr), ehdr->tag_size); crypto_authenc_free_ctx(enc_ctx); return res; } optee_os-4.3.0/core/tee/tee_time_generic.c000066400000000000000000000060251464416617300205120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include struct tee_ta_time_offs { TEE_UUID uuid; TEE_Time offs; bool positive; }; static struct tee_ta_time_offs *tee_time_offs; static size_t tee_time_num_offs; static TEE_Result tee_time_ta_get_offs(const TEE_UUID *uuid, const TEE_Time **offs, bool *positive) { size_t n; for (n = 0; n < tee_time_num_offs; n++) { if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) == 0) { *offs = &tee_time_offs[n].offs; *positive = tee_time_offs[n].positive; return TEE_SUCCESS; } } return TEE_ERROR_TIME_NOT_SET; } static TEE_Result tee_time_ta_set_offs(const TEE_UUID *uuid, const TEE_Time *offs, bool positive) { size_t n; struct tee_ta_time_offs *o; for (n = 0; n < tee_time_num_offs; n++) { if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) == 0) { tee_time_offs[n].offs = *offs; tee_time_offs[n].positive = positive; return TEE_SUCCESS; } } n = tee_time_num_offs + 1; o = realloc(tee_time_offs, n * sizeof(struct tee_ta_time_offs)); if (!o) return TEE_ERROR_OUT_OF_MEMORY; tee_time_offs = o; tee_time_offs[tee_time_num_offs].uuid = *uuid; tee_time_offs[tee_time_num_offs].offs = *offs; tee_time_offs[tee_time_num_offs].positive = positive; tee_time_num_offs = n; return TEE_SUCCESS; } TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time) { TEE_Result res; const TEE_Time *offs; bool positive; TEE_Time t; TEE_Time t2; res = tee_time_ta_get_offs(uuid, &offs, &positive); if (res != TEE_SUCCESS) return res; res = tee_time_get_sys_time(&t); if (res != TEE_SUCCESS) return res; if (positive) { TEE_TIME_ADD(t, *offs, t2); /* Detect wrapping, the wrapped time should be returned. */ if (TEE_TIME_LT(t2, t)) res = TEE_ERROR_OVERFLOW; } else { TEE_TIME_SUB(t, *offs, t2); /* Detect wrapping, the wrapped time should be returned. */ if (TEE_TIME_LE(t, t2)) res = TEE_ERROR_OVERFLOW; } *time = t2; return res; } TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time) { TEE_Result res; TEE_Time offs; TEE_Time t; /* Check that time is normalized. */ if (time->millis >= TEE_TIME_MILLIS_BASE) return TEE_ERROR_BAD_PARAMETERS; res = tee_time_get_sys_time(&t); if (res != TEE_SUCCESS) return res; if (TEE_TIME_LT(t, *time)) { TEE_TIME_SUB(*time, t, offs); return tee_time_ta_set_offs(uuid, &offs, true); } else { TEE_TIME_SUB(t, *time, offs); return tee_time_ta_set_offs(uuid, &offs, false); } } void tee_time_busy_wait(uint32_t milliseconds_delay) { TEE_Time curr; TEE_Time delta; TEE_Time end; if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) panic(); delta.seconds = milliseconds_delay / 1000; delta.millis = milliseconds_delay % 1000; TEE_TIME_ADD(curr, delta, end); while (TEE_TIME_LT(curr, end)) if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) panic(); } optee_os-4.3.0/core/tee/uuid.c000066400000000000000000000014211464416617300161640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include void tee_uuid_to_octets(uint8_t *d, const TEE_UUID *s) { d[0] = s->timeLow >> 24; d[1] = s->timeLow >> 16; d[2] = s->timeLow >> 8; d[3] = s->timeLow; d[4] = s->timeMid >> 8; d[5] = s->timeMid; d[6] = s->timeHiAndVersion >> 8; d[7] = s->timeHiAndVersion; memcpy(d + 8, s->clockSeqAndNode, sizeof(s->clockSeqAndNode)); } void tee_uuid_from_octets(TEE_UUID *d, const uint8_t *s) { d->timeLow = SHIFT_U32(s[0], 24) | SHIFT_U32(s[1], 16) | SHIFT_U32(s[2], 8) | s[3]; d->timeMid = SHIFT_U32(s[4], 8) | s[5]; d->timeHiAndVersion = SHIFT_U32(s[6], 8) | s[7]; memcpy(d->clockSeqAndNode, s + 8, sizeof(d->clockSeqAndNode)); } optee_os-4.3.0/core/tests/000077500000000000000000000000001464416617300154415ustar00rootroot00000000000000optee_os-4.3.0/core/tests/ftmn_boot_tests.c000066400000000000000000000130431464416617300210170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #include #include #include #include /* * Simple straightforward tests. */ static TEE_Result simple_call_func_res; static TEE_Result __noinline simple_call_func1(void) { TEE_Result res = simple_call_func_res; FTMN_CALLEE_DONE(res); return res; } static TEE_Result __noinline simple_call_memcmp(const void *s1, const void *s2, size_t n) { if (!FTMN_CALLEE_DONE_MEMCMP(memcmp, s1, s2, n)) return TEE_SUCCESS; return TEE_ERROR_GENERIC; } static void __noinline simple_call(void) { TEE_Result res = TEE_SUCCESS; struct ftmn ftmn = { }; static const char s1[] = "s1"; simple_call_func_res = TEE_SUCCESS; FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, simple_call_func1); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(1), res); simple_call_func_res = TEE_ERROR_GENERIC; FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, simple_call_func1); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(2, 1), res); FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, simple_call_memcmp, s1, s1, sizeof(s1)); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(3, 2), res); } /* * Simulate calling with multiple unmitigated functions in the chain * between checked callee and the caller. The result has always been set * regardless of return value. */ static TEE_Result __noinline two_level_call_memcmp2(const void *s1, const void *s2, size_t n) { if (!FTMN_CALLEE_DONE_MEMCMP(memcmp, s1, s2, n)) return TEE_SUCCESS; /* * If FTMN_CALLEE_DONE_MEMCMP() returned non-zero the strings are * different. Update with an error code we can understand. */ FTMN_CALLEE_UPDATE_NOT_ZERO(TEE_ERROR_GENERIC); return TEE_ERROR_GENERIC; } static TEE_Result __noinline two_level_call_memcmp1(const void *s1, const void *s2, size_t n) { return two_level_call_memcmp2(s1, s2, n); } static TEE_Result __noinline two_level_call_memcmp(const void *s1, const void *s2, size_t n) { unsigned long func_hash = FTMN_FUNC_HASH("two_level_call_memcmp2"); struct ftmn ftmn = { }; TEE_Result res = TEE_SUCCESS; FTMN_PUSH_LINKED_CALL(&ftmn, func_hash); res = two_level_call_memcmp1(s1, s2, n); FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, 0, res); FTMN_POP_LINKED_CALL(&ftmn); FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR1, 0, res); return res; } static void __noinline two_level_call(void) { struct ftmn ftmn = { }; TEE_Result res = TEE_SUCCESS; static const char s1[] = "s1"; static const char s2[] = "s2"; FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, two_level_call_memcmp, s1, s1, sizeof(s1)); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(1), res); FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, two_level_call_memcmp, s1, s2, sizeof(s1)); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(2, 1), res); } /* * Simulate chained calls in several levels. * * For instance ree_fs_ta_open() -> shdr_verify_signature() -> * crypto_acipher_rsassa_verify() -> ... -> * mbedtls_rsa_rsassa_pss_verify_ext() */ static TEE_Result __noinline chained_call_memcmp2(const void *s1, const void *s2, size_t n) { if (!FTMN_CALLEE_DONE_MEMCMP(memcmp, s1, s2, n)) return TEE_SUCCESS; return TEE_ERROR_GENERIC; } static TEE_Result __noinline chained_call_memcmp1(const void *s1, const void *s2, size_t n) { TEE_Result res = chained_call_memcmp2(s1, s2, n); /* * If s1 and s2 has the same content but different pointers we're * testing the case with an error detected after the linked leaf * function has been called. */ if (!res && s1 != s2) res = TEE_ERROR_BAD_STATE; return res; } static TEE_Result __noinline chained_call_memcmp(const void *s1, const void *s2, size_t n) { struct ftmn ftmn = { }; TEE_Result res = TEE_SUCCESS; FTMN_PUSH_LINKED_CALL(&ftmn, FTMN_FUNC_HASH("chained_call_memcmp2")); res = chained_call_memcmp1(s1, s2, n); if (!res) FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, res); else FTMN_SET_CHECK_RES(&ftmn, FTMN_INCR0, res); FTMN_POP_LINKED_CALL(&ftmn); FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res); return res; } static void __noinline chained_calls(void) { struct ftmn ftmn = { }; static const char s[] = "s1s2s1"; TEE_Result res = TEE_SUCCESS; /* Test a normal success case. */ FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, chained_call_memcmp, s, s, 2); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(1), res); /* Test the case where the leaf function detects an error. */ FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, chained_call_memcmp, s, s + 2, 2); assert(res == TEE_ERROR_GENERIC); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(2, 1), TEE_ERROR_GENERIC); /* * Test the case where a function in the call chain detects an error * after a the leaf function has returned success. */ FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, chained_call_memcmp, s, s + 4, 2); assert(res == TEE_ERROR_BAD_STATE); ftmn_expect_state(&ftmn, FTMN_INCR1, FTMN_STEP_COUNT(3, 2), TEE_ERROR_BAD_STATE); } #define CALL_TEST_FUNC(x) do { \ DMSG("Calling " #x "()"); \ x(); \ DMSG("Return from " #x "()"); \ } while (0) static TEE_Result ftmn_boot_tests(void) { CALL_TEST_FUNC(simple_call); CALL_TEST_FUNC(two_level_call); CALL_TEST_FUNC(chained_calls); DMSG("*************************************************"); DMSG("************** Tests complete *****************"); DMSG("*************************************************"); return TEE_SUCCESS; } driver_init_late(ftmn_boot_tests); optee_os-4.3.0/core/tests/notif_test_wd.c000066400000000000000000000070431464416617300204610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2024, Linaro Limited */ #include #include #include #include #include #include #include #define TEST_WD_TIMER_PERIOD_MS 1000 struct wd_data { bool pending; bool enabled; uint16_t guest_id; unsigned int timeout_count; unsigned int call_count; struct callout callout; }; static struct wd_data default_wd_data; static unsigned int wd_data_id __nex_bss; static struct wd_data *get_wd_data(struct guest_partition *prtn) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { assert(prtn); return virt_get_guest_spec_data(prtn, wd_data_id); } return &default_wd_data; } static bool test_wd_callback(struct callout *co) { struct wd_data *wd = container_of(co, struct wd_data, callout); if (wd->pending) wd->timeout_count++; wd->call_count++; if (wd->call_count < 10 || !(wd->call_count % 60) || wd->pending) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) DMSG("WD %"PRIu16" call_count %u, timeout_count %u", wd->guest_id, wd->call_count, wd->timeout_count); else DMSG("WD call_count %u, timeout_count %u", wd->call_count, wd->timeout_count); } wd->pending = true; notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF, wd->guest_id); return true; } static void wd_ndrv_atomic_cb(struct notif_driver *ndrv __unused, enum notif_event ev, uint16_t guest_id) { if (ev == NOTIF_EVENT_STARTED) { struct guest_partition *prtn = virt_get_guest(guest_id); struct wd_data *wd = get_wd_data(prtn); if (!wd->enabled) { wd->guest_id = guest_id; callout_add(&wd->callout, test_wd_callback, TEST_WD_TIMER_PERIOD_MS); wd->enabled = true; } virt_put_guest(prtn); } } DECLARE_KEEP_PAGER(wd_ndrv_atomic_cb); static void wd_ndrv_yielding_cb(struct notif_driver *ndrv __unused, enum notif_event ev) { if (ev == NOTIF_EVENT_DO_BOTTOM_HALF) { struct guest_partition *prtn = virt_get_current_guest(); struct wd_data *wd = get_wd_data(prtn); if (wd->pending && wd->call_count < 10) DMSG("Clearing pending"); wd->pending = false; virt_put_guest(prtn); } } struct notif_driver wd_ndrv __nex_data = { .atomic_cb = wd_ndrv_atomic_cb, .yielding_cb = wd_ndrv_yielding_cb, }; static void wd_data_destroy(void *data) { struct wd_data *wd = data; callout_rem(&wd->callout); } static TEE_Result nex_init_test_wd(void) { TEE_Result res = TEE_SUCCESS; if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) { res = virt_add_guest_spec_data(&wd_data_id, sizeof(struct wd_data), wd_data_destroy); if (res) return res; } notif_register_driver(&wd_ndrv); return TEE_SUCCESS; } nex_early_init(nex_init_test_wd); struct periodic_data { unsigned int count; struct callout callout; }; static bool periodic_callback(struct callout *co) { struct periodic_data *d = container_of(co, struct periodic_data, callout); TEE_Time t = { }; if (tee_time_get_sys_time(&t)) panic(); d->count++; DMSG("seconds %"PRIu32" millis %"PRIu32" count %u", t.seconds, t.millis, d->count); if (d->count > 20) { DMSG("Disabling periodic callout"); return false; } return true; } DECLARE_KEEP_PAGER(periodic_callback); static TEE_Result nex_init_periodic_callback(void) { struct periodic_data *d = nex_calloc(1, sizeof(*d)); if (!d) return TEE_ERROR_OUT_OF_MEMORY; DMSG("Adding a periodic callout"); callout_add(&d->callout, periodic_callback, TEST_WD_TIMER_PERIOD_MS); return TEE_SUCCESS; } nex_early_init(nex_init_periodic_callback); optee_os-4.3.0/core/tests/sub.mk000066400000000000000000000001111464416617300165540ustar00rootroot00000000000000srcs-y += ftmn_boot_tests.c srcs-$(CFG_NOTIF_TEST_WD) += notif_test_wd.c optee_os-4.3.0/keys/000077500000000000000000000000001464416617300143225ustar00rootroot00000000000000optee_os-4.3.0/keys/default.pem000066400000000000000000000032171464416617300164540ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAploYrcCzzuMMkCt9QJusu1pJiEIKseCSwIaR5p7voOHxL5D2 Zt3qFVrAKLSd31IMbqXGGUOsaajyX/5gAKXSOswSAfNbugxRHCz0sHe51nI1HA9z zS8W+bqJhKCbv4tbf+iLi5/IceocbB8AoO7KPr8YjlebSGbri9RAUa6GoYb40Av6 ti4lLgX/dgFG1z3rH3z83x6Ci16wyqPqFr4tblRQnLhB7xfHf2BUqvlwoPiYLoL5 jF/7nIiOd7Aycpka4ARevx2q9/AFPLSV3U26OnGh+HKOHZjjE7rKsCe/h1lUJ/jo 7MaFN9I6leSlCZrQH6OGsJLYAh4zddsmvyf8NQIDAQABAoIBAEoooBfVcFMqpM8g lBXZUIe1GFLGHj5t/v4U/7Xv5KO0FfE+jpoNE+2xJzj+S+LikOhCvq1Enff8eRCS NfoT8kSD9QMpmhq2ovIMmIiS1yXihAqeWOF/vJ5XqjaV4tjhJ0k+Qfdco98knscU ixMzYLXYOvo509/TAe60EHhZdWtMKCmHqvFBRDhYFF+HUxWnJa39G1u828ljv8uN iRCXbEjoaWDwBJWRzDZJehrkQc2gQAkFpyePVqA3wm1tx1ZHEVwCqYOXOP49/LAc rQfoWUpm4chjEHnZEb+dQxa3N8Qeq2lqgcqrOX8NIfpzWTWQ1JM+ksinQwMJ0BDV +Lf1nAECgYEA2KBBtsj41ITez8iA0DpXovH1F9oU9aJ9JKopNos8zIZg012bE5Ib kFII0LiBGKLUP2PepTsPDIOxibLQDojg1aBGHISZVp/y81B4Rk7Wwg206ZQ848dM AhACIrzOtJLoVEZTPf7C5QrNMhViyf2c8vFBjfTuM7Ze6a0fsvfJ2ikCgYEAxJaO XKnOgKoG1Fe9JVM01U+260BEybNUbbXQCnvMjTSZCsOEmST9mhXhC56lhCNqmynt FxNuq/JMwtS3TRhrYCPPCLFly+JNTqUS1mLQ9ytVbaw6fp9mSxFUQE9d9obkGwJC 3uXEx+bc7YSGuwD34wikX0tB1zzGIXRH2JlB6y0CgYEAgFlDVjdxJwmqslXL7JQE xKizXPR7oqYpm4WucYDB/zRHPjSh41CYQEQ6sOAArUYcl4pmqmN5oSKOGFX37ASx oiEaKV9vMuIGIp+1A4NGvyc734FTKmo04Kv3d/mCR38bZINeYscFVou11EzTgXZg fZjwDFnooH8XcUCAHZuu3zECgYEAt6pltSMcgE7Z9JdIas/TI5vHLQEtgzhdH+bm SHUjRaWnekvy3VWW7deVGtMMlmi0V+US0iVgl5rXposv+gJfh0HNUrTSg2qZiWlm MQ+/Zb2BoeZv/A8Wdfnpue+svP+Hq8gwC6mlcJI7RFk1uw8LiXxwfWuFRv9LqMPH wBBnar0CgYAJF3ukzm7rnut19lzS4r1uEIuuPwk/DjEkkil7U9wE5fr+ds5rCtXj 9591DLHrtE/CBOWym2+tIDr7OnmfU+934524mtLWVZdf39/DFM9Fc1VaSualrj/1 BOLhBb7MEZqN7hHcQP7+49YW72GgX3pm0Ov5ke33FzN3ubIwAS6T7A== -----END RSA PRIVATE KEY----- optee_os-4.3.0/keys/default_ta.pem000077700000000000000000000000001464416617300212572default.pemustar00rootroot00000000000000optee_os-4.3.0/ldelf/000077500000000000000000000000001464416617300144355ustar00rootroot00000000000000optee_os-4.3.0/ldelf/dl.c000066400000000000000000000014441464416617300152030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include "dl.h" #include "ta_elf.h" TEE_Result dlopen_entry(struct dl_entry_arg *arg) { TEE_UUID zero = { }; if (arg->dlopen.flags != (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) return TEE_ERROR_BAD_PARAMETERS; if (!memcmp(&arg->dlopen.uuid, &zero, sizeof(zero))) return TEE_SUCCESS; return ta_elf_add_library(&arg->dlopen.uuid); } TEE_Result dlsym_entry(struct dl_entry_arg *arg) { struct ta_elf *elf = NULL; TEE_UUID zero = { }; if (memcmp(&arg->dlsym.uuid, &zero, sizeof(zero))) { elf = ta_elf_find_elf(&arg->dlsym.uuid); if (!elf) return TEE_ERROR_ITEM_NOT_FOUND; } return ta_elf_resolve_sym(arg->dlsym.symbol, &arg->dlsym.val, NULL, elf); } optee_os-4.3.0/ldelf/dl.h000066400000000000000000000004511464416617300152050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef LDELF_DL_H #define LDELF_DL_H #include #include TEE_Result dlopen_entry(struct dl_entry_arg *arg); TEE_Result dlsym_entry(struct dl_entry_arg *arg); #endif /*LDELF_DL_H*/ optee_os-4.3.0/ldelf/ftrace.c000066400000000000000000000061011464416617300160430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include "ftrace.h" #include "ta_elf.h" #define MIN_FTRACE_BUF_SIZE 1024 #define MAX_HEADER_STRLEN 128 static struct ftrace_buf *fbuf; bool ftrace_init(struct ftrace_buf **fbuf_ptr) { struct __ftrace_info *finfo = NULL; struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); TEE_Result res = TEE_SUCCESS; vaddr_t val = 0; int count = 0; size_t fbuf_size = 0; size_t pad = 0; char *p = NULL; char magic[] = { 'F', 'T', 'R', 'A', 'C', 'E', 0x00, 0x01 }; res = ta_elf_resolve_sym("__ftrace_info", &val, NULL, NULL); if (res) return false; finfo = (struct __ftrace_info *)val; assert(elf && elf->is_main); if (SUB_OVERFLOW(finfo->buf_end.ptr64, finfo->buf_start.ptr64, &fbuf_size)) return false; if (fbuf_size < MIN_FTRACE_BUF_SIZE) { DMSG("ftrace buffer too small"); return false; } fbuf = (struct ftrace_buf *)(vaddr_t)finfo->buf_start.ptr64; fbuf->head_off = sizeof(struct ftrace_buf); p = (char *)fbuf + fbuf->head_off; count = snprintk(p, MAX_HEADER_STRLEN, "Function graph for TA: %pUl @ %lx\n", (void *)&elf->uuid, elf->load_addr); assert(count < MAX_HEADER_STRLEN); p += count; fbuf->ret_func_ptr = finfo->ret_ptr.ptr64; fbuf->ret_idx = 0; fbuf->lr_idx = 0; fbuf->suspend_time = 0; fbuf->buf_off = fbuf->head_off + count; /* For proper alignment of uint64_t values in the ftrace buffer */ pad = 8 - (vaddr_t)p % 8; if (pad == 8) pad = 0; while (pad--) { *p++ = 0; fbuf->buf_off++; count++; } /* Delimiter for easier decoding */ memcpy(p, magic, sizeof(magic)); fbuf->buf_off += sizeof(magic); count += sizeof(magic); fbuf->curr_idx = 0; fbuf->max_size = fbuf_size - sizeof(struct ftrace_buf) - count; fbuf->syscall_trace_enabled = false; fbuf->syscall_trace_suspended = false; *fbuf_ptr = fbuf; return true; } void ftrace_copy_buf(void *pctx, void (*copy_func)(void *pctx, void *b, size_t bl)) { if (fbuf) { struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); char *hstart = (char *)fbuf + fbuf->head_off; char *cstart = (char *)fbuf + fbuf->buf_off; char *ccurr = cstart + fbuf->curr_idx * sizeof(uint64_t); size_t csize = 0; size_t dump_size = 0; char *end = NULL; assert(elf && elf->is_main); if (fbuf->overflow) csize = fbuf->max_size; else csize = fbuf->curr_idx * sizeof(uint64_t); dump_size = fbuf->buf_off - fbuf->head_off + csize; end = hstart + dump_size; /* Header */ copy_func(pctx, hstart, fbuf->buf_off - fbuf->head_off); if (fbuf->overflow) { /* From current index to end of circular buffer */ copy_func(pctx, ccurr, end - ccurr); } /* From start of circular buffer to current index */ copy_func(pctx, cstart, ccurr - cstart); } } void ftrace_map_lr(uint64_t *lr) { if (fbuf) { if (*lr == fbuf->ret_func_ptr && fbuf->lr_idx < fbuf->ret_idx) { fbuf->lr_idx++; *lr = fbuf->ret_stack[fbuf->ret_idx - fbuf->lr_idx]; } } } optee_os-4.3.0/ldelf/ftrace.h000066400000000000000000000007321464416617300160540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef FTRACE_H #define FTRACE_H #include #include #ifdef CFG_FTRACE_SUPPORT bool ftrace_init(struct ftrace_buf **fbuf_ptr); void ftrace_copy_buf(void *pctx, void (*copy_func)(void *pctx, void *b, size_t bl)); void ftrace_map_lr(uint64_t *lr); #else static inline void ftrace_map_lr(uint64_t *lr __unused) { } #endif #endif /*FTRACE_H*/ optee_os-4.3.0/ldelf/include/000077500000000000000000000000001464416617300160605ustar00rootroot00000000000000optee_os-4.3.0/ldelf/include/ldelf.h000066400000000000000000000062421464416617300173230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020-2023, Arm Limited * Copyright 2022-2023 NXP */ #ifndef __LDELF_H #define __LDELF_H #ifndef __ASSEMBLER__ #include #include #include /* Size of stack for TEE Core to allocate */ #define LDELF_STACK_SIZE (4096 * 2) /* * struct ldelf_arg - argument for ldelf * @uuid: [in] UUID of TA to load * @is_32bit: [out] 1 if a 32bit TA or 0 if a 64bit TA * @flags: [out] Flags field of TA header * @entry_func: [out] TA entry function * @stack_ptr: [out] TA stack pointer * @dump_entry: [out] Dump TA mappings and stack trace * @ftrace_entry: [out] Dump TA mappings and ftrace buffer * @fbuf: [out] ftrace buffer pointer * @dl_entry: [out] Dynamic linking interface (for libdl) */ struct ldelf_arg { TEE_UUID uuid; uint32_t is_32bit; uint32_t flags; uint64_t entry_func; uint64_t load_addr; uint64_t stack_ptr; uint64_t dump_entry; uint64_t ftrace_entry; uint64_t dl_entry; struct ftrace_buf *fbuf; }; #define DUMP_MAP_READ BIT(0) #define DUMP_MAP_WRITE BIT(1) #define DUMP_MAP_EXEC BIT(2) #define DUMP_MAP_SECURE BIT(3) #define DUMP_MAP_EPHEM BIT(4) #define DUMP_MAP_LDELF BIT(7) /* * struct dump_entry_arg - argument for ldelf_arg::dump_entry() */ struct dump_entry_arg { union { struct { uint32_t regs[16]; } arm32; struct { uint64_t fp; uint64_t sp; uint64_t pc; } arm64; struct { unsigned long fp; unsigned long sp; unsigned long pc; } rv; }; bool is_32bit; size_t num_maps; struct dump_map { vaddr_t va; paddr_t pa; size_t sz; uint32_t flags; } maps[]; }; /* * struct dl_entry_arg - argument for ldelf_arg::dl_entry() */ struct dl_entry_arg { uint32_t cmd; TEE_Result ret; union { struct { TEE_UUID uuid; /* in */ uint32_t flags; /* in */ } dlopen; struct { TEE_UUID uuid; /* in */ vaddr_t val; /* out */ char symbol[]; /* in */ } dlsym; }; }; /* * Values for dl_entry_arg::cmd */ #define LDELF_DL_ENTRY_DLOPEN 0 #define LDELF_DL_ENTRY_DLSYM 1 /* * Values for dl_entry_arg::dlopen::flags */ #define RTLD_NOW 2 #define RTLD_GLOBAL 0x100 #define RTLD_NODELETE 0x1000 #define LDELF_MAP_FLAG_SHAREABLE BIT32(0) #define LDELF_MAP_FLAG_WRITEABLE BIT32(1) #define LDELF_MAP_FLAG_EXECUTABLE BIT32(2) #define LDELF_MAP_FLAG_BTI BIT32(3) #endif /*!__ASSEMBLER__*/ #define LDELF_RETURN 0 #define LDELF_LOG 1 #define LDELF_PANIC 2 #define LDELF_MAP_ZI 3 #define LDELF_UNMAP 4 #define LDELF_OPEN_BIN 5 #define LDELF_CLOSE_BIN 6 #define LDELF_MAP_BIN 7 #define LDELF_CP_FROM_BIN 8 #define LDELF_SET_PROT 9 #define LDELF_REMAP 10 #define LDELF_GEN_RND_NUM 11 #define LDELF_SCN_MAX 11 /* * ldelf is loaded into memory by TEE Core. BSS is initialized and a * stack is allocated and supplied in SP register. A struct ldelf_arg * is placed in the stack and a pointer to the struct is provided in * r0/x0 on ARM and in a0/x10 on RISC-V. * * ldelf relocates itself to the address where it is loaded before the main * C routine is called. * * In the main C routine the TA is loaded using the PTA System interface. */ #endif /*__LDELF_H*/ optee_os-4.3.0/ldelf/include/ldelf_syscalls.h000066400000000000000000000023051464416617300212340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Arm Limited */ #ifndef LDELF_SYSCALLS_H #define LDELF_SYSCALLS_H #include #include #include void _ldelf_return(unsigned long ret) __noreturn; void _ldelf_log(const void *buf, size_t len); void _ldelf_panic(unsigned long code); TEE_Result _ldelf_map_zi(vaddr_t *va, size_t num_bytes, size_t pad_begin, size_t pad_end, unsigned long flags); TEE_Result _ldelf_unmap(vaddr_t va, size_t num_bytes); TEE_Result _ldelf_open_bin(const TEE_UUID *uuid, size_t uuid_size, uint32_t *handle); TEE_Result _ldelf_close_bin(unsigned long handle); TEE_Result _ldelf_map_bin(vaddr_t *va, size_t num_bytes, unsigned long handle, size_t offs, size_t pad_begin, size_t pad_end, unsigned long flags); TEE_Result _ldelf_cp_from_bin(void *dst, size_t offs, size_t num_bytes, unsigned long handle); TEE_Result _ldelf_set_prot(unsigned long va, size_t num_bytes, unsigned long flags); TEE_Result _ldelf_remap(unsigned long old_va, vaddr_t *new_va, size_t num_bytes, size_t pad_begin, size_t pad_end); TEE_Result _ldelf_gen_rnd_num(void *buf, size_t num_bytes); #endif /* LDELF_SYSCALLS_H */ optee_os-4.3.0/ldelf/ldelf.ld.S000066400000000000000000000045161464416617300162530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2016-2019, Linaro Limited */ #ifdef ARM32 OUTPUT_FORMAT("elf32-littlearm") OUTPUT_ARCH(arm) #endif #ifdef ARM64 OUTPUT_FORMAT("elf64-littleaarch64") OUTPUT_ARCH(aarch64) #endif #ifdef RV64 OUTPUT_ARCH(riscv) #endif ENTRY(_ldelf_start) SECTIONS { .text : { __text_start = .; *(.text._ldelf_start) *(.text .text.*) *(.stub) *(.glue_7) *(.glue_7t) *(.gnu.linkonce.t.*) /* Workaround for an erratum in ARM's VFP11 coprocessor */ *(.vfp11_veneer) __text_end = .; } .note.gnu.property : { *(.note.gnu.property) } .plt : { *(.plt) } .eh_frame : { *(.eh_frame) } .rodata : { *(.gnu.linkonce.r.*) *(.rodata .rodata.*) } /* .ARM.exidx is sorted, so has to go in its own output section. */ .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } .ARM.extab : { *(.ARM.extab*) } .ctors : { *(.ctors) } .dtors : { *(.dtors) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .hash : { *(.hash) } /* * Relocation sections may be aligned on 4 or 8 bytes. With ALIGN(8) * we avoid any padding between __reloc_begin and the first relocation. */ . = ALIGN(8); __reloc_begin = .; .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } .rel.dyn : { *(.rel.dyn) } .rela.dyn : { *(.rela.dyn) } .rel.ctors : { *(.rel.ctors) } .rela.ctors : { *(.rela.ctors) } .rel.dtors : { *(.rel.dtors) } .rela.dtors : { *(.rela.dtors) } .rel.init : { *(.rel.init) } .rela.init : { *(.rela.init) } .rel.fini : { *(.rel.fini) } .rela.fini : { *(.rela.fini) } .rel.bss : { *(.rel.bss) } .rela.bss : { *(.rela.bss) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } __reloc_end = .; /* Page align to allow dropping execute bit for RW data */ . = ALIGN(4096); .dynamic : { *(.dynamic) } .got : { *(.got.plt) *(.got) } .data : { *(.data .data.* .gnu.linkonce.d.*) } .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) } /DISCARD/ : { *(.interp) } } optee_os-4.3.0/ldelf/ldelf.mk000066400000000000000000000022441464416617300160560ustar00rootroot00000000000000include mk/cleanvars.mk # Set current submodule (used for module specific flags compile result etc) sm := ldelf sm-$(sm) := y link-out-dir$(sm) := $(out-dir)/$(sm) cppflags$(sm) := $(core-platform-cppflags) cflags$(sm) := $(core-platform-cflags) -fpie -fvisibility=hidden aflags$(sm) := $(core-platform-aflags) # ldelf is compiled for the same arch or register width as core ifeq ($(CFG_ARM64_core),y) CFG_ARM64_$(sm) := y endif ifeq ($(CFG_ARM32_core),y) CFG_ARM32_$(sm) := y endif ifeq ($(CFG_RV64_core),y) CFG_RV64_$(sm) := y endif ifeq ($(CFG_RV32_core),y) CFG_RV32_$(sm) := y endif arch-bits-$(sm) := $(arch-bits-core) cppflags$(sm) += -include $(conf-file) cppflags$(sm) += -DTRACE_LEVEL=$(CFG_TEE_CORE_LOG_LEVEL) cppflags$(sm) += -D__LDELF__ # Use same compiler as for core CROSS_COMPILE_$(sm) := $(CROSS_COMPILE_core) COMPILER_$(sm) := $(COMPILER_core) include mk/$(COMPILER_$(sm)).mk base-prefix := $(sm)- libname = utils libdir = lib/libutils include mk/lib.mk libname = utee libdir = lib/libutee include mk/lib.mk libname = unw libdir = lib/libunw include mk/lib.mk base-prefix := subdirs = ldelf include mk/subdir.mk include mk/compile.mk include ldelf/link.mk optee_os-4.3.0/ldelf/link.mk000066400000000000000000000037411464416617300157300ustar00rootroot00000000000000link-script$(sm) = ldelf/ldelf.ld.S link-script-pp$(sm) = $(link-out-dir$(sm))/ldelf.lds link-script-dep$(sm) = $(link-out-dir$(sm))/.ldelf.ld.d .PHONY: ldelf ldelf: $(link-out-dir$(sm))/ldelf.dmp ldelf: $(link-out-dir$(sm))/ldelf.elf all: ldelf cleanfiles += $(link-out-dir$(sm))/ldelf.dmp cleanfiles += $(link-out-dir$(sm))/ldelf.map cleanfiles += $(link-out-dir$(sm))/ldelf.elf cleanfiles += $(link-script-pp$(sm)) $(link-script-dep$(sm)) link-ldflags = -pie -static --gc-sections link-ldflags += -T $(link-script-pp$(sm)) link-ldflags += -Map=$(link-out-dir$(sm))/ldelf.map link-ldflags += --sort-section=alignment link-ldflags += -z max-page-size=4096 # OP-TEE always uses 4K alignment ifeq ($(CFG_CORE_BTI),y) link-ldflags += $(call ld-option,-z force-bti) --fatal-warnings endif ifeq ($(CFG_ARM32_$(sm)), y) link-ldflags += $(call ld-option,--no-warn-execstack) endif link-ldflags += $(link-ldflags$(sm)) link-ldadd = $(addprefix -L,$(libdirs)) link-ldadd += --start-group $(addprefix -l,$(libnames)) --end-group ldargs-ldelf.elf := $(link-ldflags) $(objs) $(link-ldadd) $(libgcc$(sm)) link-script-cppflags-$(sm) := \ $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ $(nostdinc$(sm)) $(CPPFLAGS) \ $(addprefix -I,$(incdirs$(sm)) $(link-out-dir$(sm))) \ $(cppflags$(sm))) -include $(link-script-dep$(sm)) link-script-pp-makefiles$(sm) = $(filter-out %.d %.cmd,$(MAKEFILE_LIST)) define gen-link-t $(link-script-pp$(sm)): $(link-script$(sm)) $(conf-file) \ $(link-script-pp-makefiles$(sm)) @$(cmd-echo-silent) ' CPP $$@' $(q)mkdir -p $$(dir $$@) $(q)$(CPP$(sm)) -P -MT $$@ -MD -MF $(link-script-dep$(sm)) \ $(link-script-cppflags-$(sm)) $$< -o $$@ $(link-out-dir$(sm))/ldelf.elf: $(objs) $(libdeps) $(link-script-pp$(sm)) @$(cmd-echo-silent) ' LD $$@' $(q)$(LD$(sm)) $(ldargs-ldelf.elf) -o $$@ $(link-out-dir$(sm))/ldelf.dmp: $(link-out-dir$(sm))/ldelf.elf @$(cmd-echo-silent) ' OBJDUMP $$@' $(q)$(OBJDUMP$(sm)) -l -x -d $$< > $$@ endef $(eval $(call gen-link-t)) optee_os-4.3.0/ldelf/main.c000066400000000000000000000104121464416617300155230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2022-2023, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include "dl.h" #include "ftrace.h" #include "sys.h" #include "ta_elf.h" static size_t mpool_size = 4 * SMALL_PAGE_SIZE; static vaddr_t mpool_base; static void __printf(2, 0) print_to_console(void *pctx __unused, const char *fmt, va_list ap) { trace_vprintf(NULL, 0, TRACE_ERROR, true, fmt, ap); } static void __noreturn __maybe_unused dump_ta_state(struct dump_entry_arg *arg) { struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); assert(elf && elf->is_main); EMSG_RAW("Status of TA %pUl", (void *)&elf->uuid); #if defined(ARM32) || defined(ARM64) EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64"); #elif defined(RV32) || defined(RV64) EMSG_RAW(" arch: %s", elf->is_32bit ? "riscv32" : "riscv64"); #endif ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue, arg->num_maps, arg->maps, mpool_base); #if defined(ARM32) || defined(ARM64) if (arg->is_32bit) ta_elf_stack_trace_a32(arg->arm32.regs); else ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp, arg->arm64.pc); #elif defined(RV32) || defined(RV64) ta_elf_stack_trace_riscv(arg->rv.fp, arg->rv.pc); #endif sys_return_cleanup(); } #ifdef CFG_FTRACE_SUPPORT struct print_buf_ctx { char *buf; size_t blen; size_t ret; }; static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt, va_list ap) { struct print_buf_ctx *pbuf = pctx; char *buf = NULL; size_t blen = 0; int ret = 0; if (pbuf->buf && pbuf->blen > pbuf->ret) { buf = pbuf->buf + pbuf->ret; blen = pbuf->blen - pbuf->ret; } ret = vsnprintk(buf, blen, fmt, ap); assert(ret >= 0); pbuf->ret += ret; } static void copy_to_pbuf(void *pctx, void *b, size_t bl) { struct print_buf_ctx *pbuf = pctx; char *buf = NULL; size_t blen = 0; if (pbuf->buf && pbuf->blen > pbuf->ret) { buf = pbuf->buf + pbuf->ret; blen = pbuf->blen - pbuf->ret; memcpy(buf, b, MIN(blen, bl)); } pbuf->ret += bl; } static void __noreturn ftrace_dump(void *buf, size_t *blen) { struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen }; ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue, 0, NULL, mpool_base); ftrace_copy_buf(&pbuf, copy_to_pbuf); *blen = pbuf.ret; sys_return_cleanup(); } #endif static void __noreturn dl_entry(struct dl_entry_arg *arg) { switch (arg->cmd) { case LDELF_DL_ENTRY_DLOPEN: arg->ret = dlopen_entry(arg); break; case LDELF_DL_ENTRY_DLSYM: arg->ret = dlsym_entry(arg); break; default: arg->ret = TEE_ERROR_NOT_SUPPORTED; } sys_return_cleanup(); } /* * ldelf()- Loads ELF into memory * @arg: Argument passing to/from TEE Core * * Only called from assembly */ void __noreturn ldelf(struct ldelf_arg *arg); void ldelf(struct ldelf_arg *arg) { TEE_Result res = TEE_SUCCESS; struct ta_elf *elf = NULL; DMSG("Loading TS %pUl", (void *)&arg->uuid); res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0); if (res) { EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res); panic(); } malloc_add_pool((void *)mpool_base, mpool_size); /* Load the main binary and get a list of dependencies, if any. */ ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr, &arg->flags); /* * Load binaries, ta_elf_load() may add external libraries to the * list, so the loop will end when all the dependencies are * satisfied. */ TAILQ_FOREACH(elf, &main_elf_queue, link) ta_elf_load_dependency(elf, arg->is_32bit); TAILQ_FOREACH(elf, &main_elf_queue, link) { ta_elf_relocate(elf); ta_elf_finalize_mappings(elf); } ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr); arg->ftrace_entry = 0; #ifdef CFG_FTRACE_SUPPORT if (ftrace_init(&arg->fbuf)) arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump; #endif TAILQ_FOREACH(elf, &main_elf_queue, link) DMSG("ELF (%pUl) at %#"PRIxVA, (void *)&elf->uuid, elf->load_addr); #if TRACE_LEVEL >= TRACE_ERROR arg->dump_entry = (vaddr_t)(void *)dump_ta_state; #else arg->dump_entry = 0; #endif arg->dl_entry = (vaddr_t)(void *)dl_entry; sys_return_cleanup(); } optee_os-4.3.0/ldelf/pauth.c000066400000000000000000000004311464416617300157200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #include "pauth.h" void pauth_strip_pac(uint64_t *lr) { const uint64_t va_mask = GENMASK_64(CFG_LPAE_ADDR_SPACE_BITS - 1, 0); *lr = *lr & va_mask; } optee_os-4.3.0/ldelf/pauth.h000066400000000000000000000003361464416617300157310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Linaro Limited */ #ifndef PAUTH_H #define PAUTH_H #include #include void pauth_strip_pac(uint64_t *lr); #endif /*PAUTH_H*/ optee_os-4.3.0/ldelf/start_a32.S000066400000000000000000000024341464416617300163660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include /* * _start() - Entry of ldelf * * See include/ldelf.h for details on TEE Core interaction. * * void start(struct ldelf_arg *arg); */ FUNC _ldelf_start , : /* * First ldelf needs to be relocated. The binary is compiled to * contain only a minimal number of R_ARM_RELATIVE relocations in * read/write memory, leaving read-only and executeble memory * untouched. */ adr r4, reloc_begin_rel ldr r5, reloc_begin_rel ldr r6, reloc_end_rel add r5, r5, r4 add r6, r6, r4 cmp r5, r6 beq 2f adr r4, _ldelf_start /* Get the load offset */ /* Loop over the relocations (Elf32_Rel) and process all entries */ 1: ldmia r5!, {r7-r8} /* r7 == r_offset, r8 = r_info */ and r8, r8, #0xff cmp r8, #R_ARM_RELATIVE /* We're currently only supporting R_ARM_RELATIVE relocations */ bne 3f /* Update the pointer at r_offset + load_offset */ add r7, r7, r4 ldr r8, [r7] add r8, r8, r4 str r8, [r7] cmp r5, r6 blo 1b 2: bl ldelf mov r0, #0 bl _ldelf_return 3: mov r0, #0 bl _ldelf_panic reloc_begin_rel: .word __reloc_begin - reloc_begin_rel reloc_end_rel: .word __reloc_end - reloc_end_rel END_FUNC _ldelf_start optee_os-4.3.0/ldelf/start_a64.S000066400000000000000000000026711464416617300163760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include /* * _start() - Entry of ldelf * * See include/ldelf.h for details on TEE Core interaction. * * void start(struct ldelf_arg *arg); */ FUNC _ldelf_start , : /* * First ldelf needs to be relocated. The binary is compiled to * contain only a minimal number of R_AARCH64_RELATIVE relocations * in read/write memory, leaving read-only and executeble memory * untouched. */ adr x4, reloc_begin_rel ldr w5, reloc_begin_rel ldr w6, reloc_end_rel add x5, x5, x4 add x6, x6, x4 cmp x5, x6 beq 2f adr x4, _ldelf_start /* Get the load offset */ /* Loop over the relocations (Elf64_Rela) and process all entries */ 1: ldp x7, x8, [x5], #16 /* x7 = r_offset, x8 = r_info */ ldr x9, [x5], #8 /* x9 = r_addend */ and x8, x8, #0xffffffff cmp x8, #R_AARCH64_RELATIVE /* We're currently only supporting R_AARCH64_RELATIVE relocations */ bne 3f /* * Update the pointer at r_offset + load_offset with r_addend + * load_offset. */ add x7, x7, x4 add x9, x9, x4 str x9, [x7] cmp x5, x6 blo 1b 2: bl ldelf mov x0, #0 bl _ldelf_return 3: mov x0, #0 bl _ldelf_panic reloc_begin_rel: .word __reloc_begin - reloc_begin_rel reloc_end_rel: .word __reloc_end - reloc_end_rel END_FUNC _ldelf_start BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/ldelf/start_rv64.S000066400000000000000000000025101464416617300165750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022 Beijing ESWIN Computing Technology Co., Ltd. */ #include #include /* * _ldelf_start() - Entry of ldelf * * See include/ldelf.h for details on TEE Core interaction. * * void _ldelf_start(struct ldelf_arg *arg); */ FUNC _ldelf_start , : /* * First ldelf needs to be relocated. The binary is compiled to * contain only a minimal number of R_RISCV_RELATIVE relocations in * read/write memory, leaving read-only and executable memory * untouched. */ lla a1, reloc_end_rel lw a3, 0(a1) lla a1, reloc_begin_rel lw a2, 0(a1) add a2, a2, a1 add a3, a3, a1 beq a2, a3, 2f lla a1, _ldelf_start /* Get the load offset */ /* Loop over the relocations (Elf64_Rela) and process all entries */ 1: ld t1, 0(a2) /* t1 = r_offset */ ld t2, 8(a2) /* t2 = r_info */ ld t3, 16(a2) /* t3 = r_addend */ addi a2, a2, 24 and t2, t2, 0xff addi t4, zero, R_RISCV_RELATIVE bne t2, t4, 3f /* Update the pointer at r_offset + load offset */ add t1, a1, t1 ld t4, 0(t1) add t4, t4, t3 add t4, t4, a1 sd t4, 0(t1) ble a2, a3, 1b 2: jal ldelf addi a0, a0, 0 jal _ldelf_return 3: addi a0, a0, 0 jal _ldelf_panic reloc_begin_rel: .word __reloc_begin - reloc_begin_rel reloc_end_rel: .word __reloc_end - reloc_end_rel END_FUNC _ldelf_start optee_os-4.3.0/ldelf/sub.mk000066400000000000000000000007771464416617300155720ustar00rootroot00000000000000global-incdirs-y += include srcs-$(CFG_ARM32_$(sm)) += start_a32.S srcs-$(CFG_ARM64_$(sm)) += start_a64.S srcs-$(CFG_ARM32_$(sm)) += syscalls_a32.S srcs-$(CFG_ARM64_$(sm)) += syscalls_a64.S srcs-$(CFG_ARM64_$(sm)) += tlsdesc_rel_a64.S srcs-$(CFG_RV64_$(sm)) += start_rv64.S srcs-$(call cfg-one-enabled,CFG_RV32_$(sm) CFG_RV64_$(sm)) += syscalls_rv.S srcs-y += dl.c srcs-y += main.c srcs-y += sys.c srcs-y += ta_elf.c srcs-y += ta_elf_rel.c srcs-$(CFG_FTRACE_SUPPORT) += ftrace.c srcs-$(CFG_TA_PAUTH) += pauth.c optee_os-4.3.0/ldelf/sys.c000066400000000000000000000037011464416617300154200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include #include #include "sys.h" int trace_level = TRACE_LEVEL; const char trace_ext_prefix[] = "LD"; void __panic(const char *file __maybe_unused, const int line __maybe_unused, const char *func __maybe_unused) { if (!file && !func) EMSG_RAW("Panic"); else EMSG_RAW("Panic at %s:%d %s%s%s", file ? file : "?", file ? line : 0, func ? "<" : "", func ? func : "", func ? ">" : ""); _ldelf_panic(1); /*NOTREACHED*/ while (true) ; } void sys_return_cleanup(void) { _ldelf_return(0); /*NOTREACHED*/ while (true) ; } TEE_Result sys_map_zi(size_t num_bytes, uint32_t flags, vaddr_t *va, size_t pad_begin, size_t pad_end) { return _ldelf_map_zi(va, num_bytes, pad_begin, pad_end, flags); } TEE_Result sys_unmap(vaddr_t va, size_t num_bytes) { return _ldelf_unmap(va, num_bytes); } TEE_Result sys_open_ta_bin(const TEE_UUID *uuid, uint32_t *handle) { return _ldelf_open_bin(uuid, sizeof(TEE_UUID), handle); } TEE_Result sys_close_ta_bin(uint32_t handle) { return _ldelf_close_bin(handle); } TEE_Result sys_map_ta_bin(vaddr_t *va, size_t num_bytes, uint32_t flags, uint32_t handle, size_t offs, size_t pad_begin, size_t pad_end) { return _ldelf_map_bin(va, num_bytes, handle, offs, pad_begin, pad_end, flags); } TEE_Result sys_copy_from_ta_bin(void *dst, size_t num_bytes, uint32_t handle, size_t offs) { return _ldelf_cp_from_bin(dst, offs, num_bytes, handle); } TEE_Result sys_set_prot(vaddr_t va, size_t num_bytes, uint32_t flags) { return _ldelf_set_prot(va, num_bytes, flags); } TEE_Result sys_remap(vaddr_t old_va, vaddr_t *new_va, size_t num_bytes, size_t pad_begin, size_t pad_end) { return _ldelf_remap(old_va, new_va, num_bytes, pad_begin, pad_end); } TEE_Result sys_gen_random_num(void *buf, size_t blen) { return _ldelf_gen_rnd_num(buf, blen); } optee_os-4.3.0/ldelf/sys.h000066400000000000000000000031441464416617300154260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020, Arm Limited */ #ifndef SYS_H #define SYS_H #include #include #include #include #include #include #if defined(CFG_TEE_CORE_DEBUG) #define panic() __panic(__FILE__, __LINE__, __func__) #else #define panic() __panic(NULL, 0, NULL) #endif /* A small page is the smallest unit of memory that can be mapped */ #define SMALL_PAGE_SHIFT 12 #define SMALL_PAGE_MASK 0x00000fff #define SMALL_PAGE_SIZE 0x00001000 void __noreturn __panic(const char *file, const int line, const char *func); void __noreturn sys_return_cleanup(void); #define err(res, ...) \ do { \ trace_printf_helper(TRACE_ERROR, true, __VA_ARGS__); \ _ldelf_return(res); \ } while (0) TEE_Result sys_map_zi(size_t num_bytes, uint32_t flags, vaddr_t *va, size_t pad_begin, size_t pad_end); TEE_Result sys_unmap(vaddr_t va, size_t num_bytes); TEE_Result sys_open_ta_bin(const TEE_UUID *uuid, uint32_t *handle); TEE_Result sys_close_ta_bin(uint32_t handle); TEE_Result sys_map_ta_bin(vaddr_t *va, size_t num_bytes, uint32_t flags, uint32_t handle, size_t offs, size_t pad_begin, size_t pad_end); TEE_Result sys_copy_from_ta_bin(void *dst, size_t num_bytes, uint32_t handle, size_t offs); TEE_Result sys_set_prot(vaddr_t va, size_t num_bytes, uint32_t flags); TEE_Result sys_remap(vaddr_t old_va, vaddr_t *new_va, size_t num_bytes, size_t pad_begin, size_t pad_end); TEE_Result sys_gen_random_num(void *buf, size_t blen); #endif /*SYS_H*/ optee_os-4.3.0/ldelf/syscalls_a32.S000066400000000000000000000016551464416617300170720ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2015, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include .section .text .balign 4 .code 32 .macro LDELF_SYSCALL name, scn, num_args FUNC \name , : .if \num_args > 8 .error "Too many arguments for syscall" .endif push {r5-r7, lr} UNWIND( .save {r5-r7, lr}) mov r7, #(\scn) .if \num_args <= 4 @ No arguments passed on stack mov r6, #0 .else @ Tell number of arguments passed on the stack mov r6, #(\num_args - 4) @ Point just before the push (4 registers) above on the first argument add r5, sp, #(4 * 4) .endif svc #0 pop {r5-r7, pc} END_FUNC \name .endm FUNC _ldelf_panic, : push {r0-r11, lr} UNWIND( .save {r0-r11, lr}) mov lr, pc push {lr} UNWIND( .save {lr}) mov r1, sp bl __ldelf_panic /* Not reached */ END_FUNC _ldelf_panic #include "syscalls_asm.S" optee_os-4.3.0/ldelf/syscalls_a64.S000066400000000000000000000010621464416617300170670ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2020, Arm Limited */ #include .section .text .macro LDELF_SYSCALL name, scn, num_args FUNC \name , : .if \num_args > 8 .error "Too many arguments for syscall" .endif mov x8, #(\scn) svc #0 ret END_FUNC \name .endm FUNC _ldelf_panic, : stp x29, x30, [sp, #-16]! mov x1, sp bl __ldelf_panic /* Not reached */ END_FUNC _ldelf_panic #include "syscalls_asm.S" BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/ldelf/syscalls_asm.S000066400000000000000000000013441464416617300172600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Arm Limited */ #include /* macro function name syscall num num of args */ LDELF_SYSCALL _ldelf_return, LDELF_RETURN, 1 LDELF_SYSCALL _ldelf_log, LDELF_LOG, 2 LDELF_SYSCALL __ldelf_panic, LDELF_PANIC, 1 LDELF_SYSCALL _ldelf_map_zi, LDELF_MAP_ZI, 6 LDELF_SYSCALL _ldelf_unmap, LDELF_UNMAP, 3 LDELF_SYSCALL _ldelf_open_bin, LDELF_OPEN_BIN, 3 LDELF_SYSCALL _ldelf_close_bin, LDELF_CLOSE_BIN, 1 LDELF_SYSCALL _ldelf_map_bin, LDELF_MAP_BIN, 8 LDELF_SYSCALL _ldelf_cp_from_bin, LDELF_CP_FROM_BIN, 4 LDELF_SYSCALL _ldelf_set_prot, LDELF_SET_PROT, 4 LDELF_SYSCALL _ldelf_remap, LDELF_REMAP, 7 LDELF_SYSCALL _ldelf_gen_rnd_num, LDELF_GEN_RND_NUM, 2 optee_os-4.3.0/ldelf/syscalls_rv.S000066400000000000000000000007621464416617300171320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 ESWIN Corp. or its affiliates. * Authors: * Liu Shiwei */ #include .section .text .macro LDELF_SYSCALL name, scn, num_args FUNC \name , : .if \num_args > 8 .error "Too many arguments for syscall" .endif li t0, \scn li t1, \num_args ecall ret END_FUNC \name .endm FUNC _ldelf_panic, : j __ldelf_panic /* Not reached */ END_FUNC _ldelf_panic #include "syscalls_asm.S" optee_os-4.3.0/ldelf/ta_elf.c000066400000000000000000001424651464416617300160470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020-2023, Arm Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sys.h" #include "ta_elf.h" /* * Layout of a 32-bit struct dl_phdr_info for a 64-bit ldelf to access a 32-bit * TA */ struct dl_phdr_info32 { uint32_t dlpi_addr; uint32_t dlpi_name; uint32_t dlpi_phdr; uint16_t dlpi_phnum; uint64_t dlpi_adds; uint64_t dlpi_subs; uint32_t dlpi_tls_modid; uint32_t dlpi_tls_data; }; static vaddr_t ta_stack; static vaddr_t ta_stack_size; struct ta_elf_queue main_elf_queue = TAILQ_HEAD_INITIALIZER(main_elf_queue); /* * Main application is always ID 1, shared libraries with TLS take IDs 2 and * above */ static void assign_tls_mod_id(struct ta_elf *elf) { static size_t last_tls_mod_id = 1; if (elf->is_main) assert(last_tls_mod_id == 1); /* Main always comes first */ elf->tls_mod_id = last_tls_mod_id++; } static struct ta_elf *queue_elf_helper(const TEE_UUID *uuid) { struct ta_elf *elf = calloc(1, sizeof(*elf)); if (!elf) return NULL; TAILQ_INIT(&elf->segs); elf->uuid = *uuid; TAILQ_INSERT_TAIL(&main_elf_queue, elf, link); return elf; } static struct ta_elf *queue_elf(const TEE_UUID *uuid) { struct ta_elf *elf = ta_elf_find_elf(uuid); if (elf) return NULL; elf = queue_elf_helper(uuid); if (!elf) err(TEE_ERROR_OUT_OF_MEMORY, "queue_elf_helper"); return elf; } struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid) { struct ta_elf *elf = NULL; TAILQ_FOREACH(elf, &main_elf_queue, link) if (!memcmp(uuid, &elf->uuid, sizeof(*uuid))) return elf; return NULL; } #if defined(ARM32) || defined(ARM64) static TEE_Result e32_parse_ehdr(struct ta_elf *elf, Elf32_Ehdr *ehdr) { if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB || (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE && ehdr->e_ident[EI_OSABI] != ELFOSABI_ARM) || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM || #ifndef CFG_WITH_VFP (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) || #endif ehdr->e_phentsize != sizeof(Elf32_Phdr) || ehdr->e_shentsize != sizeof(Elf32_Shdr)) return TEE_ERROR_BAD_FORMAT; if (ehdr->e_ident[EI_OSABI] == ELFOSABI_NONE && (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_V5) return TEE_ERROR_BAD_FORMAT; if (ehdr->e_ident[EI_OSABI] == ELFOSABI_ARM && (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_UNKNOWN) return TEE_ERROR_BAD_FORMAT; elf->is_32bit = true; elf->e_entry = ehdr->e_entry; elf->e_phoff = ehdr->e_phoff; elf->e_shoff = ehdr->e_shoff; elf->e_phnum = ehdr->e_phnum; elf->e_shnum = ehdr->e_shnum; elf->e_phentsize = ehdr->e_phentsize; elf->e_shentsize = ehdr->e_shentsize; return TEE_SUCCESS; } #ifdef ARM64 static TEE_Result e64_parse_ehdr(struct ta_elf *elf, Elf64_Ehdr *ehdr) { if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB || ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_AARCH64 || ehdr->e_flags || ehdr->e_phentsize != sizeof(Elf64_Phdr) || ehdr->e_shentsize != sizeof(Elf64_Shdr)) return TEE_ERROR_BAD_FORMAT; elf->is_32bit = false; elf->e_entry = ehdr->e_entry; elf->e_phoff = ehdr->e_phoff; elf->e_shoff = ehdr->e_shoff; elf->e_phnum = ehdr->e_phnum; elf->e_shnum = ehdr->e_shnum; elf->e_phentsize = ehdr->e_phentsize; elf->e_shentsize = ehdr->e_shentsize; return TEE_SUCCESS; } #else /*ARM64*/ static TEE_Result e64_parse_ehdr(struct ta_elf *elf __unused, Elf64_Ehdr *ehdr __unused) { return TEE_ERROR_NOT_SUPPORTED; } #endif /*ARM64*/ #endif /* ARM32 || ARM64 */ #if defined(RV64) static TEE_Result e32_parse_ehdr(struct ta_elf *elf __unused, Elf32_Ehdr *ehdr __unused) { return TEE_ERROR_BAD_FORMAT; } static TEE_Result e64_parse_ehdr(struct ta_elf *elf, Elf64_Ehdr *ehdr) { if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_ident[EI_DATA] != ELFDATA2LSB || ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_RISCV || ehdr->e_phentsize != sizeof(Elf64_Phdr) || ehdr->e_shentsize != sizeof(Elf64_Shdr)) return TEE_ERROR_BAD_FORMAT; elf->is_32bit = false; elf->e_entry = ehdr->e_entry; elf->e_phoff = ehdr->e_phoff; elf->e_shoff = ehdr->e_shoff; elf->e_phnum = ehdr->e_phnum; elf->e_shnum = ehdr->e_shnum; elf->e_phentsize = ehdr->e_phentsize; elf->e_shentsize = ehdr->e_shentsize; return TEE_SUCCESS; } #endif /* RV64 */ static void check_phdr_in_range(struct ta_elf *elf, unsigned int type, vaddr_t addr, size_t memsz) { vaddr_t max_addr = 0; if (ADD_OVERFLOW(addr, memsz, &max_addr)) err(TEE_ERROR_BAD_FORMAT, "Program header %#x overflow", type); /* * elf->load_addr and elf->max_addr are both using the * final virtual addresses, while this program header is * relative to 0. */ if (max_addr > elf->max_addr - elf->load_addr) err(TEE_ERROR_BAD_FORMAT, "Program header %#x out of bounds", type); } static void read_dyn(struct ta_elf *elf, vaddr_t addr, size_t idx, unsigned int *tag, size_t *val) { if (elf->is_32bit) { Elf32_Dyn *dyn = (Elf32_Dyn *)(addr + elf->load_addr); *tag = dyn[idx].d_tag; *val = dyn[idx].d_un.d_val; } else { Elf64_Dyn *dyn = (Elf64_Dyn *)(addr + elf->load_addr); *tag = dyn[idx].d_tag; *val = dyn[idx].d_un.d_val; } } static void check_range(struct ta_elf *elf, const char *name, const void *ptr, size_t sz) { size_t max_addr = 0; if ((vaddr_t)ptr < elf->load_addr) err(TEE_ERROR_BAD_FORMAT, "%s %p out of range", name, ptr); if (ADD_OVERFLOW((vaddr_t)ptr, sz, &max_addr)) err(TEE_ERROR_BAD_FORMAT, "%s range overflow", name); if (max_addr > elf->max_addr) err(TEE_ERROR_BAD_FORMAT, "%s %p..%#zx out of range", name, ptr, max_addr); } static void check_hashtab(struct ta_elf *elf, void *ptr, size_t num_buckets, size_t num_chains) { /* * Starting from 2 as the first two words are mandatory and hold * num_buckets and num_chains. So this function is called twice, * first to see that there's indeed room for num_buckets and * num_chains and then to see that all of it fits. * See http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash */ size_t num_words = 2; size_t sz = 0; if (!IS_ALIGNED_WITH_TYPE(ptr, uint32_t)) err(TEE_ERROR_BAD_FORMAT, "Bad alignment of DT_HASH %p", ptr); if (ADD_OVERFLOW(num_words, num_buckets, &num_words) || ADD_OVERFLOW(num_words, num_chains, &num_words) || MUL_OVERFLOW(num_words, sizeof(uint32_t), &sz)) err(TEE_ERROR_BAD_FORMAT, "DT_HASH overflow"); check_range(elf, "DT_HASH", ptr, sz); } static void check_gnu_hashtab(struct ta_elf *elf, void *ptr) { struct gnu_hashtab *h = ptr; size_t num_words = 4; /* nbuckets, symoffset, bloom_size, bloom_shift */ size_t bloom_words = 0; size_t sz = 0; if (!IS_ALIGNED_WITH_TYPE(ptr, uint32_t)) err(TEE_ERROR_BAD_FORMAT, "Bad alignment of DT_GNU_HASH %p", ptr); if (elf->gnu_hashtab_size < sizeof(*h)) err(TEE_ERROR_BAD_FORMAT, "DT_GNU_HASH too small"); /* Check validity of h->nbuckets and h->bloom_size */ if (elf->is_32bit) bloom_words = h->bloom_size; else bloom_words = h->bloom_size * 2; if (ADD_OVERFLOW(num_words, h->nbuckets, &num_words) || ADD_OVERFLOW(num_words, bloom_words, &num_words) || MUL_OVERFLOW(num_words, sizeof(uint32_t), &sz) || sz > elf->gnu_hashtab_size) err(TEE_ERROR_BAD_FORMAT, "DT_GNU_HASH overflow"); } static void save_hashtab(struct ta_elf *elf) { uint32_t *hashtab = NULL; size_t n = 0; if (elf->is_32bit) { Elf32_Shdr *shdr = elf->shdr; for (n = 0; n < elf->e_shnum; n++) { void *addr = (void *)(vaddr_t)(shdr[n].sh_addr + elf->load_addr); if (shdr[n].sh_type == SHT_HASH) { elf->hashtab = addr; } else if (shdr[n].sh_type == SHT_GNU_HASH) { elf->gnu_hashtab = addr; elf->gnu_hashtab_size = shdr[n].sh_size; } } } else { Elf64_Shdr *shdr = elf->shdr; for (n = 0; n < elf->e_shnum; n++) { void *addr = (void *)(vaddr_t)(shdr[n].sh_addr + elf->load_addr); if (shdr[n].sh_type == SHT_HASH) { elf->hashtab = addr; } else if (shdr[n].sh_type == SHT_GNU_HASH) { elf->gnu_hashtab = addr; elf->gnu_hashtab_size = shdr[n].sh_size; } } } if (elf->hashtab) { check_hashtab(elf, elf->hashtab, 0, 0); hashtab = elf->hashtab; check_hashtab(elf, elf->hashtab, hashtab[0], hashtab[1]); } if (elf->gnu_hashtab) check_gnu_hashtab(elf, elf->gnu_hashtab); } static void save_soname_from_segment(struct ta_elf *elf, unsigned int type, vaddr_t addr, size_t memsz) { size_t dyn_entsize = 0; size_t num_dyns = 0; size_t n = 0; unsigned int tag = 0; size_t val = 0; char *str_tab = NULL; if (type != PT_DYNAMIC) return; if (elf->is_32bit) dyn_entsize = sizeof(Elf32_Dyn); else dyn_entsize = sizeof(Elf64_Dyn); assert(!(memsz % dyn_entsize)); num_dyns = memsz / dyn_entsize; for (n = 0; n < num_dyns; n++) { read_dyn(elf, addr, n, &tag, &val); if (tag == DT_STRTAB) { str_tab = (char *)(val + elf->load_addr); break; } } for (n = 0; n < num_dyns; n++) { read_dyn(elf, addr, n, &tag, &val); if (tag == DT_SONAME) { elf->soname = str_tab + val; break; } } } static void save_soname(struct ta_elf *elf) { size_t n = 0; if (elf->is_32bit) { Elf32_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) save_soname_from_segment(elf, phdr[n].p_type, phdr[n].p_vaddr, phdr[n].p_memsz); } else { Elf64_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) save_soname_from_segment(elf, phdr[n].p_type, phdr[n].p_vaddr, phdr[n].p_memsz); } } static void e32_save_symtab(struct ta_elf *elf, size_t tab_idx) { Elf32_Shdr *shdr = elf->shdr; size_t str_idx = shdr[tab_idx].sh_link; elf->dynsymtab = (void *)(shdr[tab_idx].sh_addr + elf->load_addr); if (!IS_ALIGNED_WITH_TYPE(elf->dynsymtab, Elf32_Sym)) err(TEE_ERROR_BAD_FORMAT, "Bad alignment of dynsymtab %p", elf->dynsymtab); check_range(elf, "Dynsymtab", elf->dynsymtab, shdr[tab_idx].sh_size); if (shdr[tab_idx].sh_size % sizeof(Elf32_Sym)) err(TEE_ERROR_BAD_FORMAT, "Size of dynsymtab not an even multiple of Elf32_Sym"); elf->num_dynsyms = shdr[tab_idx].sh_size / sizeof(Elf32_Sym); if (str_idx >= elf->e_shnum) err(TEE_ERROR_BAD_FORMAT, "Dynstr section index out of range"); elf->dynstr = (void *)(shdr[str_idx].sh_addr + elf->load_addr); check_range(elf, "Dynstr", elf->dynstr, shdr[str_idx].sh_size); elf->dynstr_size = shdr[str_idx].sh_size; } static void e64_save_symtab(struct ta_elf *elf, size_t tab_idx) { Elf64_Shdr *shdr = elf->shdr; size_t str_idx = shdr[tab_idx].sh_link; elf->dynsymtab = (void *)(vaddr_t)(shdr[tab_idx].sh_addr + elf->load_addr); if (!IS_ALIGNED_WITH_TYPE(elf->dynsymtab, Elf64_Sym)) err(TEE_ERROR_BAD_FORMAT, "Bad alignment of .dynsym/DYNSYM %p", elf->dynsymtab); check_range(elf, ".dynsym/DYNSYM", elf->dynsymtab, shdr[tab_idx].sh_size); if (shdr[tab_idx].sh_size % sizeof(Elf64_Sym)) err(TEE_ERROR_BAD_FORMAT, "Size of .dynsym/DYNSYM not an even multiple of Elf64_Sym"); elf->num_dynsyms = shdr[tab_idx].sh_size / sizeof(Elf64_Sym); if (str_idx >= elf->e_shnum) err(TEE_ERROR_BAD_FORMAT, ".dynstr/STRTAB section index out of range"); elf->dynstr = (void *)(vaddr_t)(shdr[str_idx].sh_addr + elf->load_addr); check_range(elf, ".dynstr/STRTAB", elf->dynstr, shdr[str_idx].sh_size); elf->dynstr_size = shdr[str_idx].sh_size; } static void save_symtab(struct ta_elf *elf) { size_t n = 0; if (elf->is_32bit) { Elf32_Shdr *shdr = elf->shdr; for (n = 0; n < elf->e_shnum; n++) { if (shdr[n].sh_type == SHT_DYNSYM) { e32_save_symtab(elf, n); break; } } } else { Elf64_Shdr *shdr = elf->shdr; for (n = 0; n < elf->e_shnum; n++) { if (shdr[n].sh_type == SHT_DYNSYM) { e64_save_symtab(elf, n); break; } } } save_hashtab(elf); save_soname(elf); } static void init_elf(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; vaddr_t va = 0; uint32_t flags = LDELF_MAP_FLAG_SHAREABLE; size_t sz = 0; res = sys_open_ta_bin(&elf->uuid, &elf->handle); if (res) err(res, "sys_open_ta_bin(%pUl)", (void *)&elf->uuid); /* * Map it read-only executable when we're loading a library where * the ELF header is included in a load segment. */ if (!elf->is_main) flags |= LDELF_MAP_FLAG_EXECUTABLE; res = sys_map_ta_bin(&va, SMALL_PAGE_SIZE, flags, elf->handle, 0, 0, 0); if (res) err(res, "sys_map_ta_bin"); elf->ehdr_addr = va; if (!elf->is_main) { elf->load_addr = va; elf->max_addr = va + SMALL_PAGE_SIZE; elf->max_offs = SMALL_PAGE_SIZE; } if (!IS_ELF(*(Elf32_Ehdr *)va)) err(TEE_ERROR_BAD_FORMAT, "TA is not an ELF"); res = e32_parse_ehdr(elf, (void *)va); if (res == TEE_ERROR_BAD_FORMAT) res = e64_parse_ehdr(elf, (void *)va); if (res) err(res, "Cannot parse ELF"); if (MUL_OVERFLOW(elf->e_phnum, elf->e_phentsize, &sz) || ADD_OVERFLOW(sz, elf->e_phoff, &sz)) err(TEE_ERROR_BAD_FORMAT, "Program headers size overflow"); if (sz > SMALL_PAGE_SIZE) err(TEE_ERROR_NOT_SUPPORTED, "Cannot read program headers"); elf->phdr = (void *)(va + elf->e_phoff); } static size_t roundup(size_t v) { return ROUNDUP(v, SMALL_PAGE_SIZE); } static size_t rounddown(size_t v) { return ROUNDDOWN(v, SMALL_PAGE_SIZE); } static void add_segment(struct ta_elf *elf, size_t offset, size_t vaddr, size_t filesz, size_t memsz, size_t flags, size_t align) { struct segment *seg = calloc(1, sizeof(*seg)); if (!seg) err(TEE_ERROR_OUT_OF_MEMORY, "calloc"); if (memsz < filesz) err(TEE_ERROR_BAD_FORMAT, "Memsz smaller than filesz"); seg->offset = offset; seg->vaddr = vaddr; seg->filesz = filesz; seg->memsz = memsz; seg->flags = flags; seg->align = align; TAILQ_INSERT_TAIL(&elf->segs, seg, link); } static void parse_load_segments(struct ta_elf *elf) { size_t n = 0; if (elf->is_32bit) { Elf32_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) if (phdr[n].p_type == PT_LOAD) { add_segment(elf, phdr[n].p_offset, phdr[n].p_vaddr, phdr[n].p_filesz, phdr[n].p_memsz, phdr[n].p_flags, phdr[n].p_align); } else if (phdr[n].p_type == PT_ARM_EXIDX) { elf->exidx_start = phdr[n].p_vaddr; elf->exidx_size = phdr[n].p_filesz; } else if (phdr[n].p_type == PT_TLS) { assign_tls_mod_id(elf); } } else { Elf64_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) if (phdr[n].p_type == PT_LOAD) { add_segment(elf, phdr[n].p_offset, phdr[n].p_vaddr, phdr[n].p_filesz, phdr[n].p_memsz, phdr[n].p_flags, phdr[n].p_align); } else if (phdr[n].p_type == PT_TLS) { elf->tls_start = phdr[n].p_vaddr; elf->tls_filesz = phdr[n].p_filesz; elf->tls_memsz = phdr[n].p_memsz; } else if (IS_ENABLED(CFG_TA_BTI) && phdr[n].p_type == PT_GNU_PROPERTY) { elf->prop_start = phdr[n].p_vaddr; elf->prop_align = phdr[n].p_align; elf->prop_memsz = phdr[n].p_memsz; } } } static void copy_remapped_to(struct ta_elf *elf, const struct segment *seg) { uint8_t *dst = (void *)(seg->vaddr + elf->load_addr); size_t n = 0; size_t offs = seg->offset; size_t num_bytes = seg->filesz; if (offs < elf->max_offs) { n = MIN(elf->max_offs - offs, num_bytes); memcpy(dst, (void *)(elf->max_addr + offs - elf->max_offs), n); dst += n; offs += n; num_bytes -= n; } if (num_bytes) { TEE_Result res = sys_copy_from_ta_bin(dst, num_bytes, elf->handle, offs); if (res) err(res, "sys_copy_from_ta_bin"); elf->max_offs += offs; } } static void adjust_segments(struct ta_elf *elf) { struct segment *seg = NULL; struct segment *prev_seg = NULL; size_t prev_end_addr = 0; size_t align = 0; size_t mask = 0; /* Sanity check */ TAILQ_FOREACH(seg, &elf->segs, link) { size_t dummy __maybe_unused = 0; assert(seg->align >= SMALL_PAGE_SIZE); assert(!ADD_OVERFLOW(seg->vaddr, seg->memsz, &dummy)); assert(seg->filesz <= seg->memsz); assert((seg->offset & SMALL_PAGE_MASK) == (seg->vaddr & SMALL_PAGE_MASK)); prev_seg = TAILQ_PREV(seg, segment_head, link); if (prev_seg) { assert(seg->vaddr >= prev_seg->vaddr + prev_seg->memsz); assert(seg->offset >= prev_seg->offset + prev_seg->filesz); } if (!align) align = seg->align; assert(align == seg->align); } mask = align - 1; seg = TAILQ_FIRST(&elf->segs); if (seg) seg = TAILQ_NEXT(seg, link); while (seg) { prev_seg = TAILQ_PREV(seg, segment_head, link); prev_end_addr = prev_seg->vaddr + prev_seg->memsz; /* * This segment may overlap with the last "page" in the * previous segment in two different ways: * 1. Virtual address (and offset) overlaps => * Permissions needs to be merged. The offset must have * the SMALL_PAGE_MASK bits set as vaddr and offset must * add up with prevsion segment. * * 2. Only offset overlaps => * The same page in the ELF is mapped at two different * virtual addresses. As a limitation this segment must * be mapped as writeable. */ /* Case 1. */ if (rounddown(seg->vaddr) < prev_end_addr) { assert((seg->vaddr & mask) == (seg->offset & mask)); assert(prev_seg->memsz == prev_seg->filesz); /* * Merge the segments and their permissions. * Note that the may be a small hole between the * two sections. */ prev_seg->filesz = seg->vaddr + seg->filesz - prev_seg->vaddr; prev_seg->memsz = seg->vaddr + seg->memsz - prev_seg->vaddr; prev_seg->flags |= seg->flags; TAILQ_REMOVE(&elf->segs, seg, link); free(seg); seg = TAILQ_NEXT(prev_seg, link); continue; } /* Case 2. */ if ((seg->offset & mask) && rounddown(seg->offset) < (prev_seg->offset + prev_seg->filesz)) { assert(seg->flags & PF_W); seg->remapped_writeable = true; } /* * No overlap, but we may need to align address, offset and * size. */ seg->filesz += seg->vaddr - rounddown(seg->vaddr); seg->memsz += seg->vaddr - rounddown(seg->vaddr); seg->vaddr = rounddown(seg->vaddr); seg->offset = rounddown(seg->offset); seg = TAILQ_NEXT(seg, link); } } static void populate_segments_legacy(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; struct segment *seg = NULL; vaddr_t va = 0; assert(elf->is_legacy); TAILQ_FOREACH(seg, &elf->segs, link) { struct segment *last_seg = TAILQ_LAST(&elf->segs, segment_head); size_t pad_end = roundup(last_seg->vaddr + last_seg->memsz - seg->vaddr - seg->memsz); size_t num_bytes = roundup(seg->memsz); if (!elf->load_addr) va = 0; else va = seg->vaddr + elf->load_addr; if (!(seg->flags & PF_R)) err(TEE_ERROR_NOT_SUPPORTED, "Segment must be readable"); res = sys_map_zi(num_bytes, 0, &va, 0, pad_end); if (res) err(res, "sys_map_zi"); res = sys_copy_from_ta_bin((void *)va, seg->filesz, elf->handle, seg->offset); if (res) err(res, "sys_copy_from_ta_bin"); if (!elf->load_addr) elf->load_addr = va; elf->max_addr = va + num_bytes; elf->max_offs = seg->offset + seg->filesz; } } static size_t get_pad_begin(void) { #ifdef CFG_TA_ASLR size_t min = CFG_TA_ASLR_MIN_OFFSET_PAGES; size_t max = CFG_TA_ASLR_MAX_OFFSET_PAGES; TEE_Result res = TEE_SUCCESS; uint32_t rnd32 = 0; size_t rnd = 0; COMPILE_TIME_ASSERT(CFG_TA_ASLR_MIN_OFFSET_PAGES < CFG_TA_ASLR_MAX_OFFSET_PAGES); if (max > min) { res = sys_gen_random_num(&rnd32, sizeof(rnd32)); if (res) { DMSG("Random read failed: %#"PRIx32, res); return min * SMALL_PAGE_SIZE; } rnd = rnd32 % (max - min); } return (min + rnd) * SMALL_PAGE_SIZE; #else /*!CFG_TA_ASLR*/ return 0; #endif /*!CFG_TA_ASLR*/ } static void populate_segments(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; struct segment *seg = NULL; vaddr_t va = 0; size_t pad_begin = 0; assert(!elf->is_legacy); TAILQ_FOREACH(seg, &elf->segs, link) { struct segment *last_seg = TAILQ_LAST(&elf->segs, segment_head); size_t pad_end = roundup(last_seg->vaddr + last_seg->memsz - seg->vaddr - seg->memsz); if (seg->remapped_writeable) { size_t num_bytes = roundup(seg->vaddr + seg->memsz) - rounddown(seg->vaddr); assert(elf->load_addr); va = rounddown(elf->load_addr + seg->vaddr); assert(va >= elf->max_addr); res = sys_map_zi(num_bytes, 0, &va, 0, pad_end); if (res) err(res, "sys_map_zi"); copy_remapped_to(elf, seg); elf->max_addr = va + num_bytes; } else { uint32_t flags = 0; size_t filesz = seg->filesz; size_t memsz = seg->memsz; size_t offset = seg->offset; size_t vaddr = seg->vaddr; if (offset < elf->max_offs) { /* * We're in a load segment which overlaps * with (or is covered by) the first page * of a shared library. */ if (vaddr + filesz < SMALL_PAGE_SIZE) { size_t num_bytes = 0; /* * If this segment is completely * covered, take next. */ if (vaddr + memsz <= SMALL_PAGE_SIZE) continue; /* * All data of the segment is * loaded, but we need to zero * extend it. */ va = elf->max_addr; num_bytes = roundup(vaddr + memsz) - roundup(vaddr) - SMALL_PAGE_SIZE; assert(num_bytes); res = sys_map_zi(num_bytes, 0, &va, 0, 0); if (res) err(res, "sys_map_zi"); elf->max_addr = roundup(va + num_bytes); continue; } /* Partial overlap, remove the first page. */ vaddr += SMALL_PAGE_SIZE; filesz -= SMALL_PAGE_SIZE; memsz -= SMALL_PAGE_SIZE; offset += SMALL_PAGE_SIZE; } if (!elf->load_addr) { va = 0; pad_begin = get_pad_begin(); /* * If mapping with pad_begin fails we'll * retry without pad_begin, effectively * disabling ASLR for the current ELF file. */ } else { va = vaddr + elf->load_addr; pad_begin = 0; } if (seg->flags & PF_W) flags |= LDELF_MAP_FLAG_WRITEABLE; else flags |= LDELF_MAP_FLAG_SHAREABLE; if (seg->flags & PF_X) flags |= LDELF_MAP_FLAG_EXECUTABLE; if (!(seg->flags & PF_R)) err(TEE_ERROR_NOT_SUPPORTED, "Segment must be readable"); if (flags & LDELF_MAP_FLAG_WRITEABLE) { res = sys_map_zi(memsz, 0, &va, pad_begin, pad_end); if (pad_begin && res == TEE_ERROR_OUT_OF_MEMORY) res = sys_map_zi(memsz, 0, &va, 0, pad_end); if (res) err(res, "sys_map_zi"); res = sys_copy_from_ta_bin((void *)va, filesz, elf->handle, offset); if (res) err(res, "sys_copy_from_ta_bin"); } else { if (filesz != memsz) err(TEE_ERROR_BAD_FORMAT, "Filesz and memsz mismatch"); res = sys_map_ta_bin(&va, filesz, flags, elf->handle, offset, pad_begin, pad_end); if (pad_begin && res == TEE_ERROR_OUT_OF_MEMORY) res = sys_map_ta_bin(&va, filesz, flags, elf->handle, offset, 0, pad_end); if (res) err(res, "sys_map_ta_bin"); } if (!elf->load_addr) elf->load_addr = va; elf->max_addr = roundup(va + memsz); elf->max_offs += filesz; } } } static void ta_elf_add_bti(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; struct segment *seg = NULL; uint32_t flags = LDELF_MAP_FLAG_EXECUTABLE | LDELF_MAP_FLAG_BTI; TAILQ_FOREACH(seg, &elf->segs, link) { vaddr_t va = elf->load_addr + seg->vaddr; if (seg->flags & PF_X) { res = sys_set_prot(va, seg->memsz, flags); if (res) err(res, "sys_set_prot"); } } } static void parse_property_segment(struct ta_elf *elf) { char *desc = NULL; size_t align = elf->prop_align; size_t desc_offset = 0; size_t prop_offset = 0; vaddr_t va = 0; Elf_Note *note = NULL; char *name = NULL; if (!IS_ENABLED(CFG_TA_BTI) || !elf->prop_start) return; check_phdr_in_range(elf, PT_GNU_PROPERTY, elf->prop_start, elf->prop_memsz); va = elf->load_addr + elf->prop_start; note = (void *)va; name = (char *)(note + 1); if (elf->prop_memsz < sizeof(*note) + sizeof(ELF_NOTE_GNU)) return; if (note->n_type != NT_GNU_PROPERTY_TYPE_0 || note->n_namesz != sizeof(ELF_NOTE_GNU) || memcmp(name, ELF_NOTE_GNU, sizeof(ELF_NOTE_GNU)) || !IS_POWER_OF_TWO(align)) return; desc_offset = ROUNDUP(sizeof(*note) + sizeof(ELF_NOTE_GNU), align); if (desc_offset > elf->prop_memsz || ROUNDUP(desc_offset + note->n_descsz, align) > elf->prop_memsz) return; desc = (char *)(va + desc_offset); do { Elf_Prop *prop = (void *)(desc + prop_offset); size_t data_offset = prop_offset + sizeof(*prop); if (note->n_descsz < data_offset) return; data_offset = confine_array_index(data_offset, note->n_descsz); if (prop->pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { uint32_t *pr_data = (void *)(desc + data_offset); if (note->n_descsz < (data_offset + sizeof(*pr_data)) && prop->pr_datasz != sizeof(*pr_data)) return; if (*pr_data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) { DMSG("BTI Feature present in note property"); elf->bti_enabled = true; } } prop_offset += ROUNDUP(sizeof(*prop) + prop->pr_datasz, align); } while (prop_offset < note->n_descsz); } static void map_segments(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; parse_load_segments(elf); adjust_segments(elf); if (TAILQ_FIRST(&elf->segs)->offset < SMALL_PAGE_SIZE) { vaddr_t va = 0; size_t sz = elf->max_addr - elf->load_addr; struct segment *seg = TAILQ_LAST(&elf->segs, segment_head); size_t pad_begin = get_pad_begin(); /* * We're loading a library, if not other parts of the code * need to be updated too. */ assert(!elf->is_main); /* * Now that we know how much virtual memory is needed move * the already mapped part to a location which can * accommodate us. */ res = sys_remap(elf->load_addr, &va, sz, pad_begin, roundup(seg->vaddr + seg->memsz)); if (res == TEE_ERROR_OUT_OF_MEMORY) res = sys_remap(elf->load_addr, &va, sz, 0, roundup(seg->vaddr + seg->memsz)); if (res) err(res, "sys_remap"); elf->ehdr_addr = va; elf->load_addr = va; elf->max_addr = va + sz; elf->phdr = (void *)(va + elf->e_phoff); } } static void add_deps_from_segment(struct ta_elf *elf, unsigned int type, vaddr_t addr, size_t memsz) { size_t dyn_entsize = 0; size_t num_dyns = 0; size_t n = 0; unsigned int tag = 0; size_t val = 0; TEE_UUID uuid = { }; char *str_tab = NULL; size_t str_tab_sz = 0; if (type != PT_DYNAMIC) return; check_phdr_in_range(elf, type, addr, memsz); if (elf->is_32bit) dyn_entsize = sizeof(Elf32_Dyn); else dyn_entsize = sizeof(Elf64_Dyn); assert(!(memsz % dyn_entsize)); num_dyns = memsz / dyn_entsize; for (n = 0; n < num_dyns && !(str_tab && str_tab_sz); n++) { read_dyn(elf, addr, n, &tag, &val); if (tag == DT_STRTAB) str_tab = (char *)(val + elf->load_addr); else if (tag == DT_STRSZ) str_tab_sz = val; } check_range(elf, ".dynstr/STRTAB", str_tab, str_tab_sz); for (n = 0; n < num_dyns; n++) { TEE_Result res = TEE_SUCCESS; read_dyn(elf, addr, n, &tag, &val); if (tag != DT_NEEDED) continue; if (val >= str_tab_sz) err(TEE_ERROR_BAD_FORMAT, "Offset into .dynstr/STRTAB out of range"); res = tee_uuid_from_str(&uuid, str_tab + val); if (res) err(res, "Fail to get UUID from string"); queue_elf(&uuid); } } static void add_dependencies(struct ta_elf *elf) { size_t n = 0; if (elf->is_32bit) { Elf32_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) add_deps_from_segment(elf, phdr[n].p_type, phdr[n].p_vaddr, phdr[n].p_memsz); } else { Elf64_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) add_deps_from_segment(elf, phdr[n].p_type, phdr[n].p_vaddr, phdr[n].p_memsz); } } static void copy_section_headers(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; size_t sz = 0; size_t offs = 0; if (MUL_OVERFLOW(elf->e_shnum, elf->e_shentsize, &sz)) err(TEE_ERROR_BAD_FORMAT, "Section headers size overflow"); elf->shdr = malloc(sz); if (!elf->shdr) err(TEE_ERROR_OUT_OF_MEMORY, "malloc"); /* * We're assuming that section headers comes after the load segments, * but if it's a very small dynamically linked library the section * headers can still end up (partially?) in the first mapped page. */ if (elf->e_shoff < SMALL_PAGE_SIZE) { assert(!elf->is_main); offs = MIN(SMALL_PAGE_SIZE - elf->e_shoff, sz); memcpy(elf->shdr, (void *)(elf->load_addr + elf->e_shoff), offs); } if (offs < sz) { res = sys_copy_from_ta_bin((uint8_t *)elf->shdr + offs, sz - offs, elf->handle, elf->e_shoff + offs); if (res) err(res, "sys_copy_from_ta_bin"); } } static void close_handle(struct ta_elf *elf) { TEE_Result res = sys_close_ta_bin(elf->handle); if (res) err(res, "sys_close_ta_bin"); elf->handle = -1; } static void clean_elf_load_main(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; /* * Clean up from last attempt to load */ res = sys_unmap(elf->ehdr_addr, SMALL_PAGE_SIZE); if (res) err(res, "sys_unmap"); while (!TAILQ_EMPTY(&elf->segs)) { struct segment *seg = TAILQ_FIRST(&elf->segs); vaddr_t va = 0; size_t num_bytes = 0; va = rounddown(elf->load_addr + seg->vaddr); if (seg->remapped_writeable) num_bytes = roundup(seg->vaddr + seg->memsz) - rounddown(seg->vaddr); else num_bytes = seg->memsz; res = sys_unmap(va, num_bytes); if (res) err(res, "sys_unmap"); TAILQ_REMOVE(&elf->segs, seg, link); free(seg); } free(elf->shdr); memset(&elf->is_32bit, 0, (vaddr_t)&elf->uuid - (vaddr_t)&elf->is_32bit); TAILQ_INIT(&elf->segs); } #ifdef ARM64 /* * Allocates an offset in the TA's Thread Control Block for the TLS segment of * the @elf module. */ #define TCB_HEAD_SIZE (2 * sizeof(long)) static void set_tls_offset(struct ta_elf *elf) { static size_t next_offs = TCB_HEAD_SIZE; if (!elf->tls_start) return; /* Module has a TLS segment */ elf->tls_tcb_offs = next_offs; next_offs += elf->tls_memsz; } #else static void set_tls_offset(struct ta_elf *elf __unused) {} #endif static void load_main(struct ta_elf *elf) { vaddr_t va = 0; init_elf(elf); map_segments(elf); populate_segments(elf); add_dependencies(elf); copy_section_headers(elf); save_symtab(elf); close_handle(elf); set_tls_offset(elf); parse_property_segment(elf); if (elf->bti_enabled) ta_elf_add_bti(elf); if (!ta_elf_resolve_sym("ta_head", &va, NULL, elf)) elf->head = (struct ta_head *)va; else elf->head = (struct ta_head *)elf->load_addr; if (elf->head->depr_entry != UINT64_MAX) { /* * Legacy TAs sets their entry point in ta_head. For * non-legacy TAs the entry point of the ELF is set instead * and leaving the ta_head entry point set to UINT64_MAX to * indicate that it's not used. * * NB, everything before the commit a73b5878c89d ("Replace * ta_head.entry with elf entry") is considered legacy TAs * for ldelf. * * Legacy TAs cannot be mapped with shared memory segments * so restart the mapping if it turned out we're loading a * legacy TA. */ DMSG("Reloading TA %pUl as legacy TA", (void *)&elf->uuid); clean_elf_load_main(elf); elf->is_legacy = true; init_elf(elf); map_segments(elf); populate_segments_legacy(elf); add_dependencies(elf); copy_section_headers(elf); save_symtab(elf); close_handle(elf); elf->head = (struct ta_head *)elf->load_addr; /* * Check that the TA is still a legacy TA, if it isn't give * up now since we're likely under attack. */ if (elf->head->depr_entry == UINT64_MAX) err(TEE_ERROR_GENERIC, "TA %pUl was changed on disk to non-legacy", (void *)&elf->uuid); } } void ta_elf_load_main(const TEE_UUID *uuid, uint32_t *is_32bit, uint64_t *sp, uint32_t *ta_flags) { struct ta_elf *elf = queue_elf(uuid); vaddr_t va = 0; TEE_Result res = TEE_SUCCESS; assert(elf); elf->is_main = true; load_main(elf); *is_32bit = elf->is_32bit; res = sys_map_zi(elf->head->stack_size, 0, &va, 0, 0); if (res) err(res, "sys_map_zi stack"); if (elf->head->flags & ~TA_FLAGS_MASK) err(TEE_ERROR_BAD_FORMAT, "Invalid TA flags(s) %#"PRIx32, elf->head->flags & ~TA_FLAGS_MASK); *ta_flags = elf->head->flags; *sp = va + elf->head->stack_size; ta_stack = va; ta_stack_size = elf->head->stack_size; } void ta_elf_finalize_load_main(uint64_t *entry, uint64_t *load_addr) { struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue); TEE_Result res = TEE_SUCCESS; assert(elf->is_main); res = ta_elf_set_init_fini_info_compat(elf->is_32bit); if (res) err(res, "ta_elf_set_init_fini_info_compat"); res = ta_elf_set_elf_phdr_info(elf->is_32bit); if (res) err(res, "ta_elf_set_elf_phdr_info"); if (elf->is_legacy) *entry = elf->head->depr_entry; else *entry = elf->e_entry + elf->load_addr; *load_addr = elf->load_addr; } void ta_elf_load_dependency(struct ta_elf *elf, bool is_32bit) { if (elf->is_main) return; init_elf(elf); if (elf->is_32bit != is_32bit) err(TEE_ERROR_BAD_FORMAT, "ELF %pUl is %sbit (expected %sbit)", (void *)&elf->uuid, elf->is_32bit ? "32" : "64", is_32bit ? "32" : "64"); map_segments(elf); populate_segments(elf); add_dependencies(elf); copy_section_headers(elf); save_symtab(elf); close_handle(elf); set_tls_offset(elf); parse_property_segment(elf); if (elf->bti_enabled) ta_elf_add_bti(elf); } void ta_elf_finalize_mappings(struct ta_elf *elf) { TEE_Result res = TEE_SUCCESS; struct segment *seg = NULL; if (!elf->is_legacy) return; TAILQ_FOREACH(seg, &elf->segs, link) { vaddr_t va = elf->load_addr + seg->vaddr; uint32_t flags = 0; if (seg->flags & PF_W) flags |= LDELF_MAP_FLAG_WRITEABLE; if (seg->flags & PF_X) flags |= LDELF_MAP_FLAG_EXECUTABLE; res = sys_set_prot(va, seg->memsz, flags); if (res) err(res, "sys_set_prot"); } } static void __printf(3, 4) print_wrapper(void *pctx, print_func_t print_func, const char *fmt, ...) { va_list ap; va_start(ap, fmt); print_func(pctx, fmt, ap); va_end(ap); } static void print_seg(void *pctx, print_func_t print_func, size_t idx __maybe_unused, int elf_idx __maybe_unused, vaddr_t va __maybe_unused, paddr_t pa __maybe_unused, size_t sz __maybe_unused, uint32_t flags) { int rc __maybe_unused = 0; int width __maybe_unused = 8; char desc[14] __maybe_unused = ""; char flags_str[] __maybe_unused = "----"; if (elf_idx > -1) { rc = snprintf(desc, sizeof(desc), " [%d]", elf_idx); assert(rc >= 0); } else { if (flags & DUMP_MAP_EPHEM) { rc = snprintf(desc, sizeof(desc), " (param)"); assert(rc >= 0); } if (flags & DUMP_MAP_LDELF) { rc = snprintf(desc, sizeof(desc), " (ldelf)"); assert(rc >= 0); } if (va == ta_stack) { rc = snprintf(desc, sizeof(desc), " (stack)"); assert(rc >= 0); } } if (flags & DUMP_MAP_READ) flags_str[0] = 'r'; if (flags & DUMP_MAP_WRITE) flags_str[1] = 'w'; if (flags & DUMP_MAP_EXEC) flags_str[2] = 'x'; if (flags & DUMP_MAP_SECURE) flags_str[3] = 's'; print_wrapper(pctx, print_func, "region %2zu: va 0x%0*"PRIxVA" pa 0x%0*"PRIxPA" size 0x%06zx flags %s%s\n", idx, width, va, width, pa, sz, flags_str, desc); } static bool get_next_in_order(struct ta_elf_queue *elf_queue, struct ta_elf **elf, struct segment **seg, size_t *elf_idx) { struct ta_elf *e = NULL; struct segment *s = NULL; size_t idx = 0; vaddr_t va = 0; struct ta_elf *e2 = NULL; size_t i2 = 0; assert(elf && seg && elf_idx); e = *elf; s = *seg; assert((e == NULL && s == NULL) || (e != NULL && s != NULL)); if (s) { s = TAILQ_NEXT(s, link); if (s) { *seg = s; return true; } } if (e) va = e->load_addr; /* Find the ELF with next load address */ e = NULL; TAILQ_FOREACH(e2, elf_queue, link) { if (e2->load_addr > va) { if (!e || e2->load_addr < e->load_addr) { e = e2; idx = i2; } } i2++; } if (!e) return false; *elf = e; *seg = TAILQ_FIRST(&e->segs); *elf_idx = idx; return true; } void ta_elf_print_mappings(void *pctx, print_func_t print_func, struct ta_elf_queue *elf_queue, size_t num_maps, struct dump_map *maps, vaddr_t mpool_base) { struct segment *seg = NULL; struct ta_elf *elf = NULL; size_t elf_idx = 0; size_t idx = 0; size_t map_idx = 0; /* * Loop over all segments and maps, printing virtual address in * order. Segment has priority if the virtual address is present * in both map and segment. */ get_next_in_order(elf_queue, &elf, &seg, &elf_idx); while (true) { vaddr_t va = -1; paddr_t pa = -1; size_t sz = 0; uint32_t flags = DUMP_MAP_SECURE; if (seg) { va = rounddown(seg->vaddr + elf->load_addr); sz = roundup(seg->vaddr + seg->memsz) - rounddown(seg->vaddr); } while (map_idx < num_maps && maps[map_idx].va <= va) { uint32_t f = 0; /* If there's a match, it should be the same map */ if (maps[map_idx].va == va) { pa = maps[map_idx].pa; /* * In shared libraries the first page is * mapped separately with the rest of that * segment following back to back in a * separate entry. */ if (map_idx + 1 < num_maps && maps[map_idx].sz == SMALL_PAGE_SIZE) { vaddr_t next_va = maps[map_idx].va + maps[map_idx].sz; size_t comb_sz = maps[map_idx].sz + maps[map_idx + 1].sz; if (next_va == maps[map_idx + 1].va && comb_sz == sz && maps[map_idx].flags == maps[map_idx + 1].flags) { /* Skip this and next entry */ map_idx += 2; continue; } } assert(maps[map_idx].sz == sz); } else if (maps[map_idx].va < va) { if (maps[map_idx].va == mpool_base) f |= DUMP_MAP_LDELF; print_seg(pctx, print_func, idx, -1, maps[map_idx].va, maps[map_idx].pa, maps[map_idx].sz, maps[map_idx].flags | f); idx++; } map_idx++; } if (!seg) break; if (seg->flags & PF_R) flags |= DUMP_MAP_READ; if (seg->flags & PF_W) flags |= DUMP_MAP_WRITE; if (seg->flags & PF_X) flags |= DUMP_MAP_EXEC; print_seg(pctx, print_func, idx, elf_idx, va, pa, sz, flags); idx++; if (!get_next_in_order(elf_queue, &elf, &seg, &elf_idx)) seg = NULL; } elf_idx = 0; TAILQ_FOREACH(elf, elf_queue, link) { print_wrapper(pctx, print_func, " [%zu] %pUl @ 0x%0*"PRIxVA"\n", elf_idx, (void *)&elf->uuid, 8, elf->load_addr); elf_idx++; } } #ifdef CFG_UNWIND #if defined(ARM32) || defined(ARM64) /* Called by libunw */ bool find_exidx(vaddr_t addr, vaddr_t *idx_start, vaddr_t *idx_end) { struct segment *seg = NULL; struct ta_elf *elf = NULL; vaddr_t a = 0; TAILQ_FOREACH(elf, &main_elf_queue, link) { if (addr < elf->load_addr) continue; a = addr - elf->load_addr; TAILQ_FOREACH(seg, &elf->segs, link) { if (a < seg->vaddr) continue; if (a - seg->vaddr < seg->filesz) { *idx_start = elf->exidx_start + elf->load_addr; *idx_end = elf->exidx_start + elf->load_addr + elf->exidx_size; return true; } } } return false; } void ta_elf_stack_trace_a32(uint32_t regs[16]) { struct unwind_state_arm32 state = { }; memcpy(state.registers, regs, sizeof(state.registers)); print_stack_arm32(&state, ta_stack, ta_stack_size); } void ta_elf_stack_trace_a64(uint64_t fp, uint64_t sp, uint64_t pc) { struct unwind_state_arm64 state = { .fp = fp, .sp = sp, .pc = pc }; print_stack_arm64(&state, ta_stack, ta_stack_size); } #elif defined(RV32) || defined(RV64) void ta_elf_stack_trace_riscv(uint64_t fp, uint64_t pc) { struct unwind_state_riscv state = { .fp = fp, .pc = pc }; print_stack_riscv(&state, ta_stack, ta_stack_size); } #endif #endif /* CFG_UNWIND */ TEE_Result ta_elf_add_library(const TEE_UUID *uuid) { TEE_Result res = TEE_ERROR_GENERIC; struct ta_elf *ta = TAILQ_FIRST(&main_elf_queue); struct ta_elf *lib = ta_elf_find_elf(uuid); struct ta_elf *elf = NULL; if (lib) return TEE_SUCCESS; /* Already mapped */ lib = queue_elf_helper(uuid); if (!lib) return TEE_ERROR_OUT_OF_MEMORY; for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) ta_elf_load_dependency(elf, ta->is_32bit); for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) { ta_elf_relocate(elf); ta_elf_finalize_mappings(elf); } for (elf = lib; elf; elf = TAILQ_NEXT(elf, link)) DMSG("ELF (%pUl) at %#"PRIxVA, (void *)&elf->uuid, elf->load_addr); res = ta_elf_set_init_fini_info_compat(ta->is_32bit); if (res) return res; return ta_elf_set_elf_phdr_info(ta->is_32bit); } /* Get address/size of .init_array and .fini_array from the dynamic segment */ static void get_init_fini_array(struct ta_elf *elf, unsigned int type, vaddr_t addr, size_t memsz, vaddr_t *init, size_t *init_cnt, vaddr_t *fini, size_t *fini_cnt) { size_t addrsz = 0; size_t dyn_entsize = 0; size_t num_dyns = 0; size_t n = 0; unsigned int tag = 0; size_t val = 0; assert(type == PT_DYNAMIC); check_phdr_in_range(elf, type, addr, memsz); if (elf->is_32bit) { dyn_entsize = sizeof(Elf32_Dyn); addrsz = 4; } else { dyn_entsize = sizeof(Elf64_Dyn); addrsz = 8; } assert(!(memsz % dyn_entsize)); num_dyns = memsz / dyn_entsize; for (n = 0; n < num_dyns; n++) { read_dyn(elf, addr, n, &tag, &val); if (tag == DT_INIT_ARRAY) *init = val + elf->load_addr; else if (tag == DT_FINI_ARRAY) *fini = val + elf->load_addr; else if (tag == DT_INIT_ARRAYSZ) *init_cnt = val / addrsz; else if (tag == DT_FINI_ARRAYSZ) *fini_cnt = val / addrsz; } } /* Get address/size of .init_array and .fini_array in @elf (if present) */ static void elf_get_init_fini_array(struct ta_elf *elf, vaddr_t *init, size_t *init_cnt, vaddr_t *fini, size_t *fini_cnt) { size_t n = 0; if (elf->is_32bit) { Elf32_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) { if (phdr[n].p_type == PT_DYNAMIC) { get_init_fini_array(elf, phdr[n].p_type, phdr[n].p_vaddr, phdr[n].p_memsz, init, init_cnt, fini, fini_cnt); return; } } } else { Elf64_Phdr *phdr = elf->phdr; for (n = 0; n < elf->e_phnum; n++) { if (phdr[n].p_type == PT_DYNAMIC) { get_init_fini_array(elf, phdr[n].p_type, phdr[n].p_vaddr, phdr[n].p_memsz, init, init_cnt, fini, fini_cnt); return; } } } } /* * Deprecated by __elf_phdr_info below. Kept for compatibility. * * Pointers to ELF initialization and finalization functions are extracted by * ldelf and stored on the TA heap, then exported to the TA via the global * symbol __init_fini_info. libutee in OP-TEE 3.9.0 uses this mechanism. */ struct __init_fini { uint32_t flags; uint16_t init_size; uint16_t fini_size; void (**init)(void); /* @init_size entries */ void (**fini)(void); /* @fini_size entries */ }; #define __IFS_VALID BIT(0) #define __IFS_INIT_HAS_RUN BIT(1) #define __IFS_FINI_HAS_RUN BIT(2) struct __init_fini_info { uint32_t reserved; uint16_t size; uint16_t pad; struct __init_fini *ifs; /* @size entries */ }; /* 32-bit variants for a 64-bit ldelf to access a 32-bit TA */ struct __init_fini32 { uint32_t flags; uint16_t init_size; uint16_t fini_size; uint32_t init; uint32_t fini; }; struct __init_fini_info32 { uint32_t reserved; uint16_t size; uint16_t pad; uint32_t ifs; }; static TEE_Result realloc_ifs(vaddr_t va, size_t cnt, bool is_32bit) { struct __init_fini_info32 *info32 = (struct __init_fini_info32 *)va; struct __init_fini_info *info = (struct __init_fini_info *)va; struct __init_fini32 *ifs32 = NULL; struct __init_fini *ifs = NULL; size_t prev_cnt = 0; void *ptr = NULL; if (is_32bit) { ptr = (void *)(vaddr_t)info32->ifs; ptr = realloc(ptr, cnt * sizeof(struct __init_fini32)); if (!ptr) return TEE_ERROR_OUT_OF_MEMORY; ifs32 = ptr; prev_cnt = info32->size; if (cnt > prev_cnt) memset(ifs32 + prev_cnt, 0, (cnt - prev_cnt) * sizeof(*ifs32)); info32->ifs = (uint32_t)(vaddr_t)ifs32; info32->size = cnt; } else { ptr = realloc(info->ifs, cnt * sizeof(struct __init_fini)); if (!ptr) return TEE_ERROR_OUT_OF_MEMORY; ifs = ptr; prev_cnt = info->size; if (cnt > prev_cnt) memset(ifs + prev_cnt, 0, (cnt - prev_cnt) * sizeof(*ifs)); info->ifs = ifs; info->size = cnt; } return TEE_SUCCESS; } static void fill_ifs(vaddr_t va, size_t idx, struct ta_elf *elf, bool is_32bit) { struct __init_fini_info32 *info32 = (struct __init_fini_info32 *)va; struct __init_fini_info *info = (struct __init_fini_info *)va; struct __init_fini32 *ifs32 = NULL; struct __init_fini *ifs = NULL; size_t init_cnt = 0; size_t fini_cnt = 0; vaddr_t init = 0; vaddr_t fini = 0; if (is_32bit) { assert(idx < info32->size); ifs32 = &((struct __init_fini32 *)(vaddr_t)info32->ifs)[idx]; if (ifs32->flags & __IFS_VALID) return; elf_get_init_fini_array(elf, &init, &init_cnt, &fini, &fini_cnt); ifs32->init = (uint32_t)init; ifs32->init_size = init_cnt; ifs32->fini = (uint32_t)fini; ifs32->fini_size = fini_cnt; ifs32->flags |= __IFS_VALID; } else { assert(idx < info->size); ifs = &info->ifs[idx]; if (ifs->flags & __IFS_VALID) return; elf_get_init_fini_array(elf, &init, &init_cnt, &fini, &fini_cnt); ifs->init = (void (**)(void))init; ifs->init_size = init_cnt; ifs->fini = (void (**)(void))fini; ifs->fini_size = fini_cnt; ifs->flags |= __IFS_VALID; } } /* * Set or update __init_fini_info in the TA with information from the ELF * queue */ TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit) { struct __init_fini_info *info = NULL; TEE_Result res = TEE_SUCCESS; struct ta_elf *elf = NULL; vaddr_t info_va = 0; size_t cnt = 0; res = ta_elf_resolve_sym("__init_fini_info", &info_va, NULL, NULL); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) { /* * Not an error, only TAs linked against libutee from * OP-TEE 3.9.0 have this symbol. */ return TEE_SUCCESS; } return res; } assert(info_va); info = (struct __init_fini_info *)info_va; if (info->reserved) return TEE_ERROR_NOT_SUPPORTED; TAILQ_FOREACH(elf, &main_elf_queue, link) cnt++; /* Queue has at least one file (main) */ assert(cnt); res = realloc_ifs(info_va, cnt, is_32bit); if (res) goto err; cnt = 0; TAILQ_FOREACH(elf, &main_elf_queue, link) { fill_ifs(info_va, cnt, elf, is_32bit); cnt++; } return TEE_SUCCESS; err: free(info); return res; } static TEE_Result realloc_elf_phdr_info(vaddr_t va, size_t cnt, bool is_32bit) { struct __elf_phdr_info32 *info32 = (struct __elf_phdr_info32 *)va; struct __elf_phdr_info *info = (struct __elf_phdr_info *)va; struct dl_phdr_info32 *dlpi32 = NULL; struct dl_phdr_info *dlpi = NULL; size_t prev_cnt = 0; void *ptr = NULL; if (is_32bit) { ptr = (void *)(vaddr_t)info32->dlpi; ptr = realloc(ptr, cnt * sizeof(*dlpi32)); if (!ptr) return TEE_ERROR_OUT_OF_MEMORY; dlpi32 = ptr; prev_cnt = info32->count; if (cnt > prev_cnt) memset(dlpi32 + prev_cnt, 0, (cnt - prev_cnt) * sizeof(*dlpi32)); info32->dlpi = (uint32_t)(vaddr_t)dlpi32; info32->count = cnt; } else { ptr = realloc(info->dlpi, cnt * sizeof(*dlpi)); if (!ptr) return TEE_ERROR_OUT_OF_MEMORY; dlpi = ptr; prev_cnt = info->count; if (cnt > prev_cnt) memset(dlpi + prev_cnt, 0, (cnt - prev_cnt) * sizeof(*dlpi)); info->dlpi = dlpi; info->count = cnt; } return TEE_SUCCESS; } static void fill_elf_phdr_info(vaddr_t va, size_t idx, struct ta_elf *elf, bool is_32bit) { struct __elf_phdr_info32 *info32 = (struct __elf_phdr_info32 *)va; struct __elf_phdr_info *info = (struct __elf_phdr_info *)va; struct dl_phdr_info32 *dlpi32 = NULL; struct dl_phdr_info *dlpi = NULL; if (is_32bit) { assert(idx < info32->count); dlpi32 = (struct dl_phdr_info32 *)(vaddr_t)info32->dlpi + idx; dlpi32->dlpi_addr = elf->load_addr; if (elf->soname) dlpi32->dlpi_name = (vaddr_t)elf->soname; else dlpi32->dlpi_name = (vaddr_t)&info32->zero; dlpi32->dlpi_phdr = (vaddr_t)elf->phdr; dlpi32->dlpi_phnum = elf->e_phnum; dlpi32->dlpi_adds = 1; /* No unloading on dlclose() currently */ dlpi32->dlpi_subs = 0; /* No unloading on dlclose() currently */ dlpi32->dlpi_tls_modid = elf->tls_mod_id; dlpi32->dlpi_tls_data = elf->tls_start; } else { assert(idx < info->count); dlpi = info->dlpi + idx; dlpi->dlpi_addr = elf->load_addr; if (elf->soname) dlpi->dlpi_name = elf->soname; else dlpi->dlpi_name = &info32->zero; dlpi->dlpi_phdr = elf->phdr; dlpi->dlpi_phnum = elf->e_phnum; dlpi->dlpi_adds = 1; /* No unloading on dlclose() currently */ dlpi->dlpi_subs = 0; /* No unloading on dlclose() currently */ dlpi->dlpi_tls_modid = elf->tls_mod_id; dlpi->dlpi_tls_data = (void *)elf->tls_start; } } /* Set or update __elf_hdr_info in the TA with information from the ELF queue */ TEE_Result ta_elf_set_elf_phdr_info(bool is_32bit) { struct __elf_phdr_info *info = NULL; TEE_Result res = TEE_SUCCESS; struct ta_elf *elf = NULL; vaddr_t info_va = 0; size_t cnt = 0; res = ta_elf_resolve_sym("__elf_phdr_info", &info_va, NULL, NULL); if (res) { if (res == TEE_ERROR_ITEM_NOT_FOUND) { /* Older TA */ return TEE_SUCCESS; } return res; } assert(info_va); info = (struct __elf_phdr_info *)info_va; if (info->reserved) return TEE_ERROR_NOT_SUPPORTED; TAILQ_FOREACH(elf, &main_elf_queue, link) cnt++; res = realloc_elf_phdr_info(info_va, cnt, is_32bit); if (res) return res; cnt = 0; TAILQ_FOREACH(elf, &main_elf_queue, link) { fill_elf_phdr_info(info_va, cnt, elf, is_32bit); cnt++; } return TEE_SUCCESS; } optee_os-4.3.0/ldelf/ta_elf.h000066400000000000000000000072341464416617300160460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2022-2023, Arm Limited */ #ifndef TA_ELF_H #define TA_ELF_H #include #include #include #include #include struct segment { size_t offset; size_t vaddr; size_t filesz; size_t memsz; size_t flags; size_t align; bool remapped_writeable; TAILQ_ENTRY(segment) link; }; TAILQ_HEAD(segment_head, segment); struct ta_elf { bool is_main; bool is_32bit; /* Initialized from Elf32_Ehdr/Elf64_Ehdr */ bool is_legacy; bool bti_enabled; vaddr_t load_addr; vaddr_t max_addr; vaddr_t max_offs; vaddr_t ehdr_addr; /* Initialized from Elf32_Ehdr/Elf64_Ehdr */ vaddr_t e_entry; vaddr_t e_phoff; vaddr_t e_shoff; unsigned int e_phnum; unsigned int e_shnum; unsigned int e_phentsize; unsigned int e_shentsize; void *phdr; void *shdr; /* * dynsymtab and dynstr are used for external symbols, they may hold * other symbols too. */ void *dynsymtab; size_t num_dynsyms; const char *dynstr; size_t dynstr_size; /* DT_HASH hash table for faster resolution of external symbols */ void *hashtab; /* DT_GNU_HASH table as an alternative to DT_HASH */ void *gnu_hashtab; size_t gnu_hashtab_size; /* DT_SONAME */ char *soname; struct segment_head segs; vaddr_t exidx_start; size_t exidx_size; /* Thread Local Storage */ size_t tls_mod_id; /* PT_TLS segment */ vaddr_t tls_start; size_t tls_filesz; /* Covers the .tdata section */ size_t tls_memsz; /* Covers the .tdata and .tbss sections */ #ifdef ARM64 /* Offset of the copy of the TLS block in the TLS area of the TCB */ size_t tls_tcb_offs; #endif /* PT_GNU_PROPERTY segment */ vaddr_t prop_start; size_t prop_align; size_t prop_memsz; uint32_t handle; struct ta_head *head; TEE_UUID uuid; TAILQ_ENTRY(ta_elf) link; }; TAILQ_HEAD(ta_elf_queue, ta_elf); /* Format of the DT_GNU_HASH entry in the ELF dynamic section */ struct gnu_hashtab { uint32_t nbuckets; uint32_t symoffset; uint32_t bloom_size; uint32_t bloom_shift; /* * Followed by: * * uint{32,64}_t bloom[bloom_size]; * uint32_t buckets[nbuckets]; * uint32_t chain[]; */ }; typedef void (*print_func_t)(void *pctx, const char *fmt, va_list ap) __printf(2, 0); extern struct ta_elf_queue main_elf_queue; struct ta_elf *ta_elf_find_elf(const TEE_UUID *uuid); void ta_elf_load_main(const TEE_UUID *uuid, uint32_t *is_32bit, uint64_t *sp, uint32_t *ta_flags); void ta_elf_finalize_load_main(uint64_t *entry, uint64_t *load_addr); void ta_elf_load_dependency(struct ta_elf *elf, bool is_32bit); void ta_elf_relocate(struct ta_elf *elf); void ta_elf_finalize_mappings(struct ta_elf *elf); void ta_elf_print_mappings(void *pctx, print_func_t print_func, struct ta_elf_queue *elf_queue, size_t num_maps, struct dump_map *maps, vaddr_t mpool_base); #ifdef CFG_UNWIND void ta_elf_stack_trace_a32(uint32_t regs[16]); void ta_elf_stack_trace_a64(uint64_t fp, uint64_t sp, uint64_t pc); void ta_elf_stack_trace_riscv(uint64_t fp, uint64_t pc); #else static inline void ta_elf_stack_trace_a32(uint32_t regs[16] __unused) { } static inline void ta_elf_stack_trace_a64(uint64_t fp __unused, uint64_t sp __unused, uint64_t pc __unused) { } static inline void ta_elf_stack_trace_riscv(uint64_t fp __unused, uint64_t pc __unused) { } #endif /*CFG_UNWIND*/ TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val, struct ta_elf **found_elf, struct ta_elf *elf); TEE_Result ta_elf_add_library(const TEE_UUID *uuid); TEE_Result ta_elf_set_init_fini_info_compat(bool is_32bit); TEE_Result ta_elf_set_elf_phdr_info(bool is_32bit); #endif /*TA_ELF_H*/ optee_os-4.3.0/ldelf/ta_elf_rel.c000066400000000000000000000502371464416617300167040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include "sys.h" #include "ta_elf.h" static uint32_t elf_hash(const char *name) { const unsigned char *p = (const unsigned char *)name; uint32_t h = 0; uint32_t g = 0; while (*p) { h = (h << 4) + *p++; g = h & 0xf0000000; if (g) h ^= g >> 24; h &= ~g; } return h; } static uint32_t gnu_hash(const char *name) { const unsigned char *p = (const unsigned char *)name; uint32_t h = 5381; while (*p) h = (h << 5) + h + *p++; return h; } static bool sym_compare(struct ta_elf *elf, unsigned int st_bind, unsigned int st_type, size_t st_shndx, size_t st_name, size_t st_value, const char *name, vaddr_t *val, bool weak_ok) { bool bind_ok = false; if (!st_name) return false; if (st_name > elf->dynstr_size) err(TEE_ERROR_BAD_FORMAT, "Symbol name out of range"); if (strcmp(name, elf->dynstr + st_name)) return false; if (st_bind == STB_GLOBAL || (weak_ok && st_bind == STB_WEAK)) bind_ok = true; if (!bind_ok) return false; if (st_bind == STB_WEAK && st_shndx == SHN_UNDEF) { if (val) *val = 0; return true; } if (st_shndx == SHN_UNDEF || st_shndx == SHN_XINDEX) return false; switch (st_type) { case STT_NOTYPE: case STT_OBJECT: case STT_FUNC: if (st_value > (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "Symbol location out of range"); if (val) *val = st_value + elf->load_addr; break; case STT_TLS: if (val) *val = st_value; break; default: err(TEE_ERROR_NOT_SUPPORTED, "Symbol type not supported"); } return true; } static bool check_found_sym(struct ta_elf *elf, const char *name, vaddr_t *val, bool weak_ok, size_t n) { Elf32_Sym *sym32 = NULL; Elf64_Sym *sym64 = NULL; unsigned int st_bind = 0; unsigned int st_type = 0; size_t st_shndx = 0; size_t st_name = 0; size_t st_value = 0; if (n >= elf->num_dynsyms) err(TEE_ERROR_BAD_FORMAT, "Index out of range"); /* * We're loading values from sym[] which later * will be used to load something. * => Spectre V1 pattern, need to cap the index * against speculation. */ n = confine_array_index(n, elf->num_dynsyms); if (elf->is_32bit) { sym32 = elf->dynsymtab; st_bind = ELF32_ST_BIND(sym32[n].st_info); st_type = ELF32_ST_TYPE(sym32[n].st_info); st_shndx = sym32[n].st_shndx; st_name = sym32[n].st_name; st_value = sym32[n].st_value; } else { sym64 = elf->dynsymtab; st_bind = ELF64_ST_BIND(sym64[n].st_info); st_type = ELF64_ST_TYPE(sym64[n].st_info); st_shndx = sym64[n].st_shndx; st_name = sym64[n].st_name; st_value = sym64[n].st_value; } return sym_compare(elf, st_bind, st_type, st_shndx, st_name, st_value, name, val, weak_ok); } static TEE_Result resolve_sym_helper(const char *name, vaddr_t *val, struct ta_elf *elf, bool weak_ok) { uint32_t n = 0; uint32_t hash = 0; if (elf->gnu_hashtab) { struct gnu_hashtab *h = elf->gnu_hashtab; uint32_t *end = (void *)((uint8_t *)elf->gnu_hashtab + elf->gnu_hashtab_size); uint32_t *bucket = NULL; uint32_t *chain = NULL; uint32_t hashval = 0; hash = gnu_hash(name); if (elf->is_32bit) { uint32_t *bloom = (void *)(h + 1); uint32_t word = bloom[(hash / 32) % h->bloom_size]; uint32_t mask = BIT32(hash % 32) | BIT32((hash >> h->bloom_shift) % 32); if ((word & mask) != mask) return TEE_ERROR_ITEM_NOT_FOUND; bucket = bloom + h->bloom_size; } else { uint64_t *bloom = (void *)(h + 1); uint64_t word = bloom[(hash / 64) % h->bloom_size]; uint64_t mask = BIT64(hash % 64) | BIT64((hash >> h->bloom_shift) % 64); if ((word & mask) != mask) return TEE_ERROR_ITEM_NOT_FOUND; bucket = (uint32_t *)(bloom + h->bloom_size); } chain = bucket + h->nbuckets; n = bucket[hash % h->nbuckets]; if (n < h->symoffset) return TEE_ERROR_ITEM_NOT_FOUND; hash |= 1; do { size_t idx = n - h->symoffset; if (chain + idx > end) return TEE_ERROR_ITEM_NOT_FOUND; hashval = chain[idx]; if ((hashval | 1) == hash && check_found_sym(elf, name, val, weak_ok, n)) return TEE_SUCCESS; n++; } while (!(hashval & 1)); } else if (elf->hashtab) { /* * Using uint32_t here for convenience because both Elf64_Word * and Elf32_Word are 32-bit types */ uint32_t *hashtab = elf->hashtab; uint32_t nbuckets = hashtab[0]; uint32_t nchains = hashtab[1]; uint32_t *bucket = &hashtab[2]; uint32_t *chain = &bucket[nbuckets]; hash = elf_hash(name); for (n = bucket[hash % nbuckets]; n; n = chain[n]) { if (n >= nchains) err(TEE_ERROR_BAD_FORMAT, "Index out of range"); if (check_found_sym(elf, name, val, weak_ok, n)) return TEE_SUCCESS; } } return TEE_ERROR_ITEM_NOT_FOUND; } /* * Look for named symbol in @elf, or all modules if @elf == NULL. Global symbols * are searched first, then weak ones. Last option, when at least one weak but * undefined symbol exists, resolve to zero. Otherwise return * TEE_ERROR_ITEM_NOT_FOUND. * @val (if != 0) receives the symbol value * @found_elf (if != 0) receives the module where the symbol is found */ TEE_Result ta_elf_resolve_sym(const char *name, vaddr_t *val, struct ta_elf **found_elf, struct ta_elf *elf) { if (elf) { /* Search global symbols */ if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */)) goto success; /* Search weak symbols */ if (!resolve_sym_helper(name, val, elf, true /* weak_ok */)) goto success; } TAILQ_FOREACH(elf, &main_elf_queue, link) { if (!resolve_sym_helper(name, val, elf, false /* !weak_ok */)) goto success; if (!resolve_sym_helper(name, val, elf, true /* weak_ok */)) goto success; } return TEE_ERROR_ITEM_NOT_FOUND; success: if (found_elf) *found_elf = elf; return TEE_SUCCESS; } static void e32_get_sym_name(const Elf32_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf32_Rel *rel, const char **name, bool *weak_undef) { size_t sym_idx = 0; size_t name_idx = 0; sym_idx = ELF32_R_SYM(rel->r_info); if (sym_idx >= num_syms) err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); sym_idx = confine_array_index(sym_idx, num_syms); name_idx = sym_tab[sym_idx].st_name; if (name_idx >= str_tab_size) err(TEE_ERROR_BAD_FORMAT, "Name index out of range"); *name = str_tab + name_idx; if (!weak_undef) return; if (sym_tab[sym_idx].st_shndx == SHN_UNDEF && ELF32_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK) *weak_undef = true; else *weak_undef = false; } static void resolve_sym(const char *name, vaddr_t *val, struct ta_elf **mod, bool err_if_not_found) { TEE_Result res = ta_elf_resolve_sym(name, val, mod, NULL); if (res) { if (err_if_not_found) err(res, "Symbol %s not found", name); else if (val) *val = 0; } } static void e32_process_dyn_rel(const Elf32_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf32_Rel *rel, Elf32_Addr *where) { const char *name = NULL; vaddr_t val = 0; bool weak_undef = false; e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name, &weak_undef); resolve_sym(name, &val, NULL, !weak_undef); *where = val; } static void e32_tls_get_module(const Elf32_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf32_Rel *rel, struct ta_elf **mod) { const char *name = NULL; size_t sym_idx = 0; sym_idx = ELF32_R_SYM(rel->r_info); if (sym_idx >= num_syms) err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); sym_idx = confine_array_index(sym_idx, num_syms); if (!sym_idx || sym_tab[sym_idx].st_shndx != SHN_UNDEF) { /* No symbol, or symbol is defined in current module */ return; } e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name, NULL); resolve_sym(name, NULL, mod, false); } static void e32_tls_resolve(const Elf32_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf32_Rel *rel, vaddr_t *val) { const char *name = NULL; e32_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rel, &name, NULL); resolve_sym(name, val, NULL, false); } static void e32_relocate(struct ta_elf *elf, unsigned int rel_sidx) { Elf32_Shdr *shdr = elf->shdr; Elf32_Rel *rel = NULL; Elf32_Rel *rel_end = NULL; size_t sym_tab_idx = 0; Elf32_Sym *sym_tab = NULL; size_t num_syms = 0; size_t sh_end = 0; const char *str_tab = NULL; size_t str_tab_size = 0; assert(shdr[rel_sidx].sh_type == SHT_REL); assert(shdr[rel_sidx].sh_entsize == sizeof(Elf32_Rel)); sym_tab_idx = shdr[rel_sidx].sh_link; if (sym_tab_idx) { size_t str_tab_idx = 0; if (sym_tab_idx >= elf->e_shnum) err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf32_Sym)); /* Check the address is inside ELF memory */ if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, shdr[sym_tab_idx].sh_size, &sh_end)) err(TEE_ERROR_BAD_FORMAT, "Overflow"); if (sh_end >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); sym_tab = (Elf32_Sym *)(elf->load_addr + shdr[sym_tab_idx].sh_addr); num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); str_tab_idx = shdr[sym_tab_idx].sh_link; if (str_tab_idx) { if (str_tab_idx >= elf->e_shnum) err(TEE_ERROR_BAD_FORMAT, "STRTAB index out of range"); str_tab_idx = confine_array_index(str_tab_idx, elf->e_shnum); /* Check the address is inside ELF memory */ if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, shdr[str_tab_idx].sh_size, &sh_end)) err(TEE_ERROR_BAD_FORMAT, "Overflow"); if (sh_end >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "STRTAB out of range"); str_tab = (const char *)(elf->load_addr + shdr[str_tab_idx].sh_addr); str_tab_size = shdr[str_tab_idx].sh_size; } } /* Check the address is inside TA memory */ if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size, &sh_end)) err(TEE_ERROR_BAD_FORMAT, "Overflow"); if (sh_end >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); rel = (Elf32_Rel *)(elf->load_addr + shdr[rel_sidx].sh_addr); rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); for (; rel < rel_end; rel++) { struct ta_elf *mod = NULL; Elf32_Addr *where = NULL; size_t sym_idx = 0; vaddr_t val = 0; /* Check the address is inside TA memory */ if (rel->r_offset >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "Relocation offset out of range"); where = (Elf32_Addr *)(elf->load_addr + rel->r_offset); switch (ELF32_R_TYPE(rel->r_info)) { case R_ARM_NONE: /* * One would expect linker prevents such useless entry * in the relocation table. We still handle this type * here in case such entries exist. */ break; case R_ARM_ABS32: sym_idx = ELF32_R_SYM(rel->r_info); if (sym_idx >= num_syms) err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { /* Symbol is external */ e32_process_dyn_rel(sym_tab, num_syms, str_tab, str_tab_size, rel, where); } else { *where += elf->load_addr + sym_tab[sym_idx].st_value; } break; case R_ARM_REL32: sym_idx = ELF32_R_SYM(rel->r_info); if (sym_idx >= num_syms) err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); *where += sym_tab[sym_idx].st_value - rel->r_offset; break; case R_ARM_RELATIVE: *where += elf->load_addr; break; case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: if (!sym_tab) err(TEE_ERROR_BAD_FORMAT, "Missing symbol table"); e32_process_dyn_rel(sym_tab, num_syms, str_tab, str_tab_size, rel, where); break; case R_ARM_TLS_DTPMOD32: if (!sym_tab) err(TEE_ERROR_BAD_FORMAT, "Missing symbol table"); mod = elf; e32_tls_get_module(sym_tab, num_syms, str_tab, str_tab_size, rel, &mod); *where = mod->tls_mod_id; break; case R_ARM_TLS_DTPOFF32: if (!sym_tab) err(TEE_ERROR_BAD_FORMAT, "Missing symbol table"); e32_tls_resolve(sym_tab, num_syms, str_tab, str_tab_size, rel, &val); *where = val; break; default: err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %d", ELF32_R_TYPE(rel->r_info)); } } } #if defined(ARM64) || defined(RV64) static void e64_get_sym_name(const Elf64_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf64_Rela *rela, const char **name, bool *weak_undef) { size_t sym_idx = 0; size_t name_idx = 0; sym_idx = ELF64_R_SYM(rela->r_info); if (sym_idx >= num_syms) err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); sym_idx = confine_array_index(sym_idx, num_syms); name_idx = sym_tab[sym_idx].st_name; if (name_idx >= str_tab_size) err(TEE_ERROR_BAD_FORMAT, "Name index out of range"); *name = str_tab + name_idx; if (sym_tab[sym_idx].st_shndx == SHN_UNDEF && ELF64_ST_BIND(sym_tab[sym_idx].st_info) == STB_WEAK) *weak_undef = true; else *weak_undef = false; } static void e64_process_dyn_rela(const Elf64_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf64_Rela *rela, Elf64_Addr *where) { const char *name = NULL; uintptr_t val = 0; bool weak_undef = false; e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, &name, &weak_undef); resolve_sym(name, &val, NULL, !weak_undef); *where = val; } #ifdef ARM64 static void e64_process_tls_tprel_rela(const Elf64_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf64_Rela *rela, Elf64_Addr *where, struct ta_elf *elf) { struct ta_elf *mod = NULL; bool weak_undef = false; const char *name = NULL; size_t sym_idx = 0; vaddr_t symval = 0; sym_idx = ELF64_R_SYM(rela->r_info); if (sym_idx) { e64_get_sym_name(sym_tab, num_syms, str_tab, str_tab_size, rela, &name, &weak_undef); resolve_sym(name, &symval, &mod, !weak_undef); } else { mod = elf; } *where = symval + mod->tls_tcb_offs + rela->r_addend; } struct tlsdesc { long (*resolver)(struct tlsdesc *td); long value; }; /* Helper function written in assembly due to the calling convention */ long tlsdesc_resolve(struct tlsdesc *td); static void e64_process_tlsdesc_rela(const Elf64_Sym *sym_tab, size_t num_syms, const char *str_tab, size_t str_tab_size, Elf64_Rela *rela, Elf64_Addr *where, struct ta_elf *elf) { /* * @where points to a pair of 64-bit words in the GOT or PLT which is * mapped to a struct tlsdesc: * * - resolver() must return the offset of the thread-local variable * relative to TPIDR_EL0. * - value is implementation-dependent. The TLS_TPREL handling code is * re-used to get the desired offset so that tlsdesc_resolve() just * needs to return this value. * * Both the TA and ldelf are AArch64 so it is OK to point to a function * in ldelf. */ *where = (Elf64_Addr)tlsdesc_resolve; e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where + 1, elf); } #endif /*ARM64*/ static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx) { Elf64_Shdr *shdr = elf->shdr; Elf64_Rela *rela = NULL; Elf64_Rela *rela_end = NULL; size_t sym_tab_idx = 0; Elf64_Sym *sym_tab = NULL; size_t num_syms = 0; size_t sh_end = 0; const char *str_tab = NULL; size_t str_tab_size = 0; assert(shdr[rel_sidx].sh_type == SHT_RELA); assert(shdr[rel_sidx].sh_entsize == sizeof(Elf64_Rela)); sym_tab_idx = shdr[rel_sidx].sh_link; if (sym_tab_idx) { size_t str_tab_idx = 0; if (sym_tab_idx >= elf->e_shnum) err(TEE_ERROR_BAD_FORMAT, "SYMTAB index out of range"); sym_tab_idx = confine_array_index(sym_tab_idx, elf->e_shnum); assert(shdr[sym_tab_idx].sh_entsize == sizeof(Elf64_Sym)); /* Check the address is inside TA memory */ if (ADD_OVERFLOW(shdr[sym_tab_idx].sh_addr, shdr[sym_tab_idx].sh_size, &sh_end)) err(TEE_ERROR_BAD_FORMAT, "Overflow"); if (sh_end >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "SYMTAB out of range"); sym_tab = (Elf64_Sym *)(elf->load_addr + shdr[sym_tab_idx].sh_addr); num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf64_Sym); str_tab_idx = shdr[sym_tab_idx].sh_link; if (str_tab_idx) { if (str_tab_idx >= elf->e_shnum) err(TEE_ERROR_BAD_FORMAT, "STRTAB index out of range"); str_tab_idx = confine_array_index(str_tab_idx, elf->e_shnum); /* Check the address is inside ELF memory */ if (ADD_OVERFLOW(shdr[str_tab_idx].sh_addr, shdr[str_tab_idx].sh_size, &sh_end)) err(TEE_ERROR_BAD_FORMAT, "Overflow"); if (sh_end >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "STRTAB out of range"); str_tab = (const char *)(elf->load_addr + shdr[str_tab_idx].sh_addr); str_tab_size = shdr[str_tab_idx].sh_size; } } /* Check the address is inside TA memory */ if (ADD_OVERFLOW(shdr[rel_sidx].sh_addr, shdr[rel_sidx].sh_size, &sh_end)) err(TEE_ERROR_BAD_FORMAT, "Overflow"); if (sh_end >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, ".rel.*/REL out of range"); rela = (Elf64_Rela *)(elf->load_addr + shdr[rel_sidx].sh_addr); rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela); for (; rela < rela_end; rela++) { Elf64_Addr *where = NULL; size_t sym_idx __maybe_unused = 0; /* Check the address is inside TA memory */ if (rela->r_offset >= (elf->max_addr - elf->load_addr)) err(TEE_ERROR_BAD_FORMAT, "Relocation offset out of range"); where = (Elf64_Addr *)(elf->load_addr + rela->r_offset); switch (ELF64_R_TYPE(rela->r_info)) { #ifdef ARM64 case R_AARCH64_NONE: /* * One would expect linker prevents such useless entry * in the relocation table. We still handle this type * here in case such entries exist. */ break; case R_AARCH64_ABS64: sym_idx = ELF64_R_SYM(rela->r_info); if (sym_idx >= num_syms) err(TEE_ERROR_BAD_FORMAT, "Symbol index out of range"); sym_idx = confine_array_index(sym_idx, num_syms); if (sym_tab[sym_idx].st_shndx == SHN_UNDEF) { /* Symbol is external */ e64_process_dyn_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where); } else { *where = rela->r_addend + elf->load_addr + sym_tab[sym_idx].st_value; } break; case R_AARCH64_RELATIVE: *where = rela->r_addend + elf->load_addr; break; case R_AARCH64_GLOB_DAT: case R_AARCH64_JUMP_SLOT: e64_process_dyn_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where); break; case R_AARCH64_TLS_TPREL: e64_process_tls_tprel_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where, elf); break; case R_AARCH64_TLSDESC: e64_process_tlsdesc_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where, elf); break; #endif /*ARM64*/ #ifdef RV64 case R_RISCV_NONE: /* * One would expect linker prevents such useless entry * in the relocation table. We still handle this type * here in case such entries exist. */ break; case R_RISCV_RELATIVE: *where = rela->r_addend + elf->load_addr; break; case R_RISCV_64: e64_process_dyn_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where); *where += rela->r_addend; break; case R_RISCV_JUMP_SLOT: e64_process_dyn_rela(sym_tab, num_syms, str_tab, str_tab_size, rela, where); break; #endif /*RV64*/ default: err(TEE_ERROR_BAD_FORMAT, "Unknown relocation type %zd", ELF64_R_TYPE(rela->r_info)); } } } #else /*ARM64 || RV64*/ static void __noreturn e64_relocate(struct ta_elf *elf __unused, unsigned int rel_sidx __unused) { err(TEE_ERROR_NOT_SUPPORTED, "arm64 not supported"); } #endif /*ARM64 || RV64*/ void ta_elf_relocate(struct ta_elf *elf) { size_t n = 0; if (elf->is_32bit) { Elf32_Shdr *shdr = elf->shdr; for (n = 0; n < elf->e_shnum; n++) if (shdr[n].sh_type == SHT_REL) e32_relocate(elf, n); } else { Elf64_Shdr *shdr = elf->shdr; for (n = 0; n < elf->e_shnum; n++) if (shdr[n].sh_type == SHT_RELA) e64_relocate(elf, n); } } optee_os-4.3.0/ldelf/tlsdesc_rel_a64.S000066400000000000000000000011461464416617300175400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Huawei Technologies Co. Ltd. */ #include /* * long tlsdesc_resolve(struct tlsdesc *); * * Must preserve all registers except x0, x1 and the processor flags. * See https://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-ARM.txt section * "Resolvers' Calling Convention". The document applies to 32-bit Arm but other * sources mention similar constraints for other architectures. */ FUNC tlsdesc_resolve , : ldr x0, [x0, #8] ret END_FUNC tlsdesc_resolve BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/lib/000077500000000000000000000000001464416617300141155ustar00rootroot00000000000000optee_os-4.3.0/lib/libdl/000077500000000000000000000000001464416617300152035ustar00rootroot00000000000000optee_os-4.3.0/lib/libdl/dlfcn.c000066400000000000000000000051021464416617300164330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019 Linaro limited */ #include #include #include #include #include #include #include #include static TEE_TASessionHandle sess = TEE_HANDLE_NULL; static size_t hcount; static TEE_Result invoke_system_pta(uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { const TEE_UUID core_uuid = PTA_SYSTEM_UUID; TEE_Result res = TEE_ERROR_GENERIC; if (sess == TEE_HANDLE_NULL) { res = TEE_OpenTASession(&core_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, NULL); if (res) return res; } return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, param_types, params, NULL); } struct dl_handle { TEE_UUID uuid; }; void *dlopen(const char *filename, int flags) { TEE_Param params[TEE_NUM_PARAMS] = { }; struct dl_handle *h = NULL; uint32_t param_types = 0; TEE_Result res = TEE_ERROR_GENERIC; TEE_UUID uuid = { }; h = malloc(sizeof(*h)); if (!h) return NULL; if (filename) { res = tee_uuid_from_str(&uuid, filename); if (res) goto err; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); params[0].memref.buffer = (void *)&uuid; params[0].memref.size = sizeof(uuid); params[1].value.a = flags; res = invoke_system_pta(PTA_SYSTEM_DLOPEN, param_types, params); if (res) goto err; __utee_tcb_init(); __utee_call_elf_init_fn(); } hcount++; h->uuid = uuid; return (void *)h; err: free(h); return NULL; } int dlclose(void *handle) { free(handle); hcount--; if (!hcount && sess != TEE_HANDLE_NULL) { TEE_CloseTASession(sess); sess = TEE_HANDLE_NULL; } return 0; } void *dlsym(void *handle, const char *symbol) { TEE_Result res = TEE_ERROR_GENERIC; TEE_Param params[TEE_NUM_PARAMS] = { }; struct dl_handle *h = handle; uint32_t param_types = 0; void *ptr = NULL; if (!handle || !symbol) return NULL; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); params[0].memref.buffer = &h->uuid; params[0].memref.size = sizeof(h->uuid); params[1].memref.buffer = (void *)symbol; params[1].memref.size = strlen(symbol) + 1; res = invoke_system_pta(PTA_SYSTEM_DLSYM, param_types, params); if (!res) ptr = (void *)(vaddr_t)reg_pair_to_64(params[2].value.a, params[2].value.b); return ptr; } optee_os-4.3.0/lib/libdl/include/000077500000000000000000000000001464416617300166265ustar00rootroot00000000000000optee_os-4.3.0/lib/libdl/include/dlfcn.h000066400000000000000000000012011464416617300200570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019 Linaro limited */ #ifndef _DLFCN_H_ #define _DLFCN_H_ /* Relocations are performed when the object is loaded. */ #define RTLD_NOW 2 /* All symbols are available for relocation processing of other modules. */ #define RTLD_GLOBAL 0x100 /* Do not unload the shared object during dlclose(). */ #define RTLD_NODELETE 0x1000 /* Other flags are not supported */ /* Note: @flags must be (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE) */ void *dlopen(const char *filename, int flags); int dlclose(void *handle); void *dlsym(void *handle, const char *symbol); #endif /* _DLFCN_H_ */ optee_os-4.3.0/lib/libdl/sub.mk000066400000000000000000000000561464416617300163260ustar00rootroot00000000000000global-incdirs-y += include srcs-y += dlfcn.c optee_os-4.3.0/lib/libmbedtls/000077500000000000000000000000001464416617300162365ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/core/000077500000000000000000000000001464416617300171665ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/core/aes.c000066400000000000000000000026511464416617300201060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #if defined(MBEDTLS_AES_ALT) void mbedtls_aes_init(mbedtls_aes_context *ctx) { assert(ctx); memset(ctx, 0, sizeof(*ctx)); } void mbedtls_aes_free( mbedtls_aes_context *ctx ) { if (ctx) mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { assert(ctx && key); if (keybits != 128 && keybits != 192 && keybits != 256) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; if (crypto_accel_aes_expand_keys(key, keybits / 8, ctx->key, NULL, sizeof(ctx->key), &ctx->round_count)) return MBEDTLS_ERR_AES_BAD_INPUT_DATA; return 0; } int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { uint32_t enc_key[sizeof(ctx->key)] = { 0 }; assert(ctx && key); if (keybits != 128 && keybits != 192 && keybits != 256) return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; if (crypto_accel_aes_expand_keys(key, keybits / 8, enc_key, ctx->key, sizeof(ctx->key), &ctx->round_count)) return MBEDTLS_ERR_AES_BAD_INPUT_DATA; return 0; } #endif /*MBEDTLS_AES_ALT*/ optee_os-4.3.0/lib/libmbedtls/core/aes_cbc.c000066400000000000000000000070361464416617300207170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited * Copyright (C) 2021, Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" struct mbed_aes_cbc_ctx { struct crypto_cipher_ctx ctx; int mbed_mode; mbedtls_aes_context aes_ctx; unsigned char iv[TEE_AES_BLOCK_SIZE]; }; static const struct crypto_cipher_ops mbed_aes_cbc_ops; static struct mbed_aes_cbc_ctx *to_aes_cbc_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_aes_cbc_ops); return container_of(ctx, struct mbed_aes_cbc_ctx, ctx); } static TEE_Result mbed_aes_cbc_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv, size_t iv_len) { struct mbed_aes_cbc_ctx *c = to_aes_cbc_ctx(ctx); int mbed_res = 0; if (iv_len != sizeof(c->iv)) return TEE_ERROR_BAD_PARAMETERS; memcpy(c->iv, iv, sizeof(c->iv)); mbedtls_aes_init(&c->aes_ctx); if (mode == TEE_MODE_ENCRYPT) { c->mbed_mode = MBEDTLS_AES_ENCRYPT; mbed_res = mbedtls_aes_setkey_enc(&c->aes_ctx, key1, key1_len * 8); } else { c->mbed_mode = MBEDTLS_AES_DECRYPT; mbed_res = mbedtls_aes_setkey_dec(&c->aes_ctx, key1, key1_len * 8); } if (mbed_res) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_aes_cbc_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_aes_cbc_ctx *c = to_aes_cbc_ctx(ctx); if (mbedtls_aes_crypt_cbc(&c->aes_ctx, c->mbed_mode, len, c->iv, data, dst)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static void mbed_aes_cbc_final(struct crypto_cipher_ctx *ctx) { mbedtls_aes_free(&to_aes_cbc_ctx(ctx)->aes_ctx); } static void mbed_aes_cbc_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_aes_cbc_ctx(ctx)); } static void mbed_aes_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_aes_cbc_ctx *src = to_aes_cbc_ctx(src_ctx); struct mbed_aes_cbc_ctx *dst = to_aes_cbc_ctx(dst_ctx); memcpy(dst->iv, src->iv, sizeof(dst->iv)); dst->mbed_mode = src->mbed_mode; mbed_copy_mbedtls_aes_context(&dst->aes_ctx, &src->aes_ctx); } static const struct crypto_cipher_ops mbed_aes_cbc_ops = { .init = mbed_aes_cbc_init, .update = mbed_aes_cbc_update, .final = mbed_aes_cbc_final, .free_ctx = mbed_aes_cbc_free_ctx, .copy_state = mbed_aes_cbc_copy_state, }; TEE_Result crypto_aes_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_aes_cbc_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_aes_cbc_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } #if defined(MBEDTLS_AES_ALT) int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { if (length % 16) return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; if (mode == MBEDTLS_AES_ENCRYPT) crypto_accel_aes_cbc_enc(output, input, ctx->key, ctx->round_count, length / 16, iv); else crypto_accel_aes_cbc_dec(output, input, ctx->key, ctx->round_count, length / 16, iv); return 0; } #endif /*MBEDTLS_AES_ALT*/ optee_os-4.3.0/lib/libmbedtls/core/aes_ctr.c000066400000000000000000000104511464416617300207530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited * Copyright (C) 2021, Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" struct mbed_aes_ctr_ctx { struct crypto_cipher_ctx ctx; mbedtls_aes_context aes_ctx; size_t nc_off; unsigned char counter[TEE_AES_BLOCK_SIZE]; unsigned char block[TEE_AES_BLOCK_SIZE]; }; static const struct crypto_cipher_ops mbed_aes_ctr_ops; static struct mbed_aes_ctr_ctx *to_aes_ctr_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_aes_ctr_ops); return container_of(ctx, struct mbed_aes_ctr_ctx, ctx); } static TEE_Result mbed_aes_ctr_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode __unused, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv, size_t iv_len) { struct mbed_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); if (iv_len != sizeof(c->counter)) return TEE_ERROR_BAD_PARAMETERS; memcpy(c->counter, iv, sizeof(c->counter)); mbedtls_aes_init(&c->aes_ctx); c->nc_off = 0; if (mbedtls_aes_setkey_enc(&c->aes_ctx, key1, key1_len * 8)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_aes_ctr_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); if (mbedtls_aes_crypt_ctr(&c->aes_ctx, len, &c->nc_off, c->counter, c->block, data, dst)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static void mbed_aes_ctr_final(struct crypto_cipher_ctx *ctx) { struct mbed_aes_ctr_ctx *c = to_aes_ctr_ctx(ctx); mbedtls_aes_free(&c->aes_ctx); memset(c->block, 0, sizeof(c->block)); } static void mbed_aes_ctr_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_aes_ctr_ctx(ctx)); } static void mbed_aes_ctr_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_aes_ctr_ctx *src = to_aes_ctr_ctx(src_ctx); struct mbed_aes_ctr_ctx *dst = to_aes_ctr_ctx(dst_ctx); memcpy(dst->counter, src->counter, sizeof(dst->counter)); memcpy(dst->block, src->block, sizeof(dst->block)); dst->nc_off = src->nc_off; mbed_copy_mbedtls_aes_context(&dst->aes_ctx, &src->aes_ctx); } static const struct crypto_cipher_ops mbed_aes_ctr_ops = { .init = mbed_aes_ctr_init, .update = mbed_aes_ctr_update, .final = mbed_aes_ctr_final, .free_ctx = mbed_aes_ctr_free_ctx, .copy_state = mbed_aes_ctr_copy_state, }; TEE_Result crypto_aes_ctr_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_aes_ctr_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_aes_ctr_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } #if defined(MBEDTLS_AES_ALT) static void next_ctr(unsigned char stream_block[16], mbedtls_aes_context *ctx, unsigned char nonce_counter[16]) { const unsigned char zeroes[16] = { 0 }; crypto_accel_aes_ctr_be_enc(stream_block, zeroes, ctx->key, ctx->round_count, 1, nonce_counter); } int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output) { size_t offs = 0; if (*nc_off >= 16) return MBEDTLS_ERR_AES_BAD_INPUT_DATA; /* * If the stream_block is in use, continue until done or * stream_block is consumed. */ while (*nc_off) { output[offs] = stream_block[*nc_off] ^ input[offs]; offs++; *nc_off = (*nc_off + 1) % 16; if (offs == length) return 0; } if ((length - offs) >= 16) { size_t block_count = (length - offs) / 16; crypto_accel_aes_ctr_be_enc(output + offs, input + offs, ctx->key, ctx->round_count, block_count, nonce_counter); offs += block_count * 16; } while (offs < length) { if (!*nc_off) next_ctr(stream_block, ctx, nonce_counter); output[offs] = stream_block[*nc_off] ^ input[offs]; offs++; *nc_off = (*nc_off + 1) % 16; } return 0; } #endif /*MBEDTLS_AES_ALT*/ optee_os-4.3.0/lib/libmbedtls/core/aes_ecb.c000066400000000000000000000066651464416617300207300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited * Copyright (C) 2021, Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" struct mbed_aes_ecb_ctx { struct crypto_cipher_ctx ctx; int mbed_mode; mbedtls_aes_context aes_ctx; }; static const struct crypto_cipher_ops mbed_aes_ecb_ops; static struct mbed_aes_ecb_ctx *to_aes_ecb_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_aes_ecb_ops); return container_of(ctx, struct mbed_aes_ecb_ctx, ctx); } static TEE_Result mbed_aes_ecb_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct mbed_aes_ecb_ctx *c = to_aes_ecb_ctx(ctx); int mbed_res = 0; mbedtls_aes_init(&c->aes_ctx); if (mode == TEE_MODE_ENCRYPT) { c->mbed_mode = MBEDTLS_AES_ENCRYPT; mbed_res = mbedtls_aes_setkey_enc(&c->aes_ctx, key1, key1_len * 8); } else { c->mbed_mode = MBEDTLS_AES_DECRYPT; mbed_res = mbedtls_aes_setkey_dec(&c->aes_ctx, key1, key1_len * 8); } if (mbed_res) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_aes_ecb_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_aes_ecb_ctx *c = to_aes_ecb_ctx(ctx); size_t block_size = TEE_AES_BLOCK_SIZE; size_t offs = 0; if (len % block_size) return TEE_ERROR_BAD_PARAMETERS; for (offs = 0; offs < len; offs += block_size) { if (mbedtls_aes_crypt_ecb(&c->aes_ctx, c->mbed_mode, data + offs, dst + offs)) return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static void mbed_aes_ecb_final(struct crypto_cipher_ctx *ctx) { mbedtls_aes_free(&to_aes_ecb_ctx(ctx)->aes_ctx); } static void mbed_aes_ecb_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_aes_ecb_ctx(ctx)); } static void mbed_aes_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_aes_ecb_ctx *src = to_aes_ecb_ctx(src_ctx); struct mbed_aes_ecb_ctx *dst = to_aes_ecb_ctx(dst_ctx); dst->mbed_mode = src->mbed_mode; mbed_copy_mbedtls_aes_context(&dst->aes_ctx, &src->aes_ctx); } static const struct crypto_cipher_ops mbed_aes_ecb_ops = { .init = mbed_aes_ecb_init, .update = mbed_aes_ecb_update, .final = mbed_aes_ecb_final, .free_ctx = mbed_aes_ecb_free_ctx, .copy_state = mbed_aes_ecb_copy_state, }; TEE_Result crypto_aes_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_aes_ecb_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_aes_ecb_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } #if defined(MBEDTLS_AES_ALT) int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { if (mode == MBEDTLS_AES_ENCRYPT) crypto_accel_aes_ecb_enc(output, input, ctx->key, ctx->round_count, 1); else crypto_accel_aes_ecb_dec(output, input, ctx->key, ctx->round_count, 1); return 0; } #endif /*MBEDTLS_AES_ALT*/ optee_os-4.3.0/lib/libmbedtls/core/bignum.c000066400000000000000000000043751464416617300206240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ #define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) size_t crypto_bignum_num_bytes(struct bignum *a) { assert(a != NULL); return mbedtls_mpi_size((const mbedtls_mpi *)a); } size_t crypto_bignum_num_bits(struct bignum *a) { assert(a != NULL); return mbedtls_mpi_bitlen((const mbedtls_mpi *)a); } int32_t crypto_bignum_compare(struct bignum *a, struct bignum *b) { int ret = 0; assert(a != NULL); assert(b != NULL); ret = mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, (const mbedtls_mpi *)b); return CMP_TRILEAN(ret, 0); } void crypto_bignum_bn2bin(const struct bignum *from, uint8_t *to) { size_t len = 0; assert(from != NULL); assert(to != NULL); len = crypto_bignum_num_bytes((struct bignum *)from); if (mbedtls_mpi_write_binary((mbedtls_mpi *)from, to, len)) panic(); } TEE_Result crypto_bignum_bin2bn(const uint8_t *from, size_t fromsize, struct bignum *to) { assert(from != NULL); assert(to != NULL); if (mbedtls_mpi_read_binary((mbedtls_mpi *)to, from, fromsize)) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } void crypto_bignum_copy(struct bignum *to, const struct bignum *from) { assert(from != NULL); assert(to != NULL); if (mbedtls_mpi_copy((mbedtls_mpi *)to, (const mbedtls_mpi *)from)) panic(); } struct bignum *crypto_bignum_allocate(size_t size_bits) { mbedtls_mpi *bn = NULL; if (size_bits > CFG_CORE_BIGNUM_MAX_BITS) size_bits = CFG_CORE_BIGNUM_MAX_BITS; bn = calloc(1, sizeof(mbedtls_mpi)); if (!bn) return NULL; mbedtls_mpi_init(bn); if (mbedtls_mpi_grow(bn, BITS_TO_LIMBS(size_bits)) != 0) { free(bn); return NULL; } return (struct bignum *)bn; } void crypto_bignum_free(struct bignum **s) { assert(s); mbedtls_mpi_free((mbedtls_mpi *)*s); free(*s); *s = NULL; } void crypto_bignum_clear(struct bignum *s) { mbedtls_mpi *bn = (mbedtls_mpi *)s; memset(bn->p, 0, mbedtls_mpi_size((const mbedtls_mpi *)bn)); } optee_os-4.3.0/lib/libmbedtls/core/cmac.c000066400000000000000000000111031464416617300202310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited * Copyright (C) 2021, SumUp Services GmbH */ #include #include #include #include #include #include #include #include #include #include #include struct mbed_cmac_ctx { struct crypto_mac_ctx mac_ctx; mbedtls_cipher_context_t cipher_ctx; mbedtls_cipher_id_t cipher_id; }; static const struct crypto_mac_ops mbed_cmac_ops; static struct mbed_cmac_ctx *to_cmac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx); assert(ctx->ops == &mbed_cmac_ops); return container_of(ctx, struct mbed_cmac_ctx, mac_ctx); } static TEE_Result mbed_cmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); const mbedtls_cipher_info_t *cipher_info = NULL; cipher_info = mbedtls_cipher_info_from_values(c->cipher_id, len * 8, MBEDTLS_MODE_ECB); if (!cipher_info) return TEE_ERROR_NOT_SUPPORTED; if (mbedtls_cipher_setup_info(&c->cipher_ctx, cipher_info)) return TEE_ERROR_BAD_STATE; if (mbedtls_cipher_cmac_reset(&c->cipher_ctx)) return TEE_ERROR_BAD_STATE; if (mbedtls_cipher_cmac_starts(&c->cipher_ctx, key, len * 8)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_cmac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); if (mbedtls_cipher_cmac_update(&c->cipher_ctx, data, len)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_cmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); size_t block_size = TEE_AES_BLOCK_SIZE; uint8_t block_digest[TEE_AES_BLOCK_SIZE] = { }; uint8_t *tmp_digest = NULL; COMPILE_TIME_ASSERT(TEE_AES_BLOCK_SIZE >= TEE_DES_BLOCK_SIZE); if (len == 0) return TEE_ERROR_BAD_PARAMETERS; if (c->cipher_id == MBEDTLS_CIPHER_ID_3DES) block_size = TEE_DES_BLOCK_SIZE; if (len < block_size) tmp_digest = block_digest; /* use a tempory buffer */ else tmp_digest = digest; if (mbedtls_cipher_cmac_finish(&c->cipher_ctx, tmp_digest)) return TEE_ERROR_BAD_STATE; if (len < block_size) memcpy(digest, tmp_digest, len); return TEE_SUCCESS; } static void mbed_cmac_free_ctx(struct crypto_mac_ctx *ctx) { struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); mbedtls_cipher_free(&c->cipher_ctx); free(c); } static void mbed_cmac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct mbed_cmac_ctx *src = to_cmac_ctx(src_ctx); struct mbed_cmac_ctx *dst = to_cmac_ctx(dst_ctx); if (mbedtls_cipher_clone(&dst->cipher_ctx, &src->cipher_ctx)) panic(); } static const struct crypto_mac_ops mbed_cmac_ops = { .init = mbed_cmac_init, .update = mbed_cmac_update, .final = mbed_cmac_final, .free_ctx = mbed_cmac_free_ctx, .copy_state = mbed_cmac_copy_state, }; static TEE_Result crypto_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, const mbedtls_cipher_id_t cipher_id, int key_bitlen) { int mbed_res = 0; struct mbed_cmac_ctx *c = NULL; const mbedtls_cipher_info_t *cipher_info = NULL; /* * Use a default key length for getting 'cipher_info' to do the * setup. The 'cipher_info' will need to be re-assigned with final * key length obtained in mbed_cmac_init() above. * * This is safe since 'mbedtls_cipher_base_t' (used for cipher * context) uses the same fixed allocation all key lengths. */ cipher_info = mbedtls_cipher_info_from_values(cipher_id, key_bitlen, MBEDTLS_MODE_ECB); if (!cipher_info) return TEE_ERROR_NOT_SUPPORTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->cipher_id = cipher_id; c->mac_ctx.ops = &mbed_cmac_ops; mbedtls_cipher_init(&c->cipher_ctx); mbed_res = mbedtls_cipher_setup(&c->cipher_ctx, cipher_info); if (mbed_res) { free(c); if (mbed_res == MBEDTLS_ERR_CIPHER_ALLOC_FAILED) return TEE_ERROR_OUT_OF_MEMORY; return TEE_ERROR_NOT_SUPPORTED; } mbed_res = mbedtls_cipher_cmac_setup(&c->cipher_ctx); if (mbed_res) { free(c); return TEE_ERROR_NOT_SUPPORTED; } *ctx_ret = &c->mac_ctx; return TEE_SUCCESS; } TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) { return crypto_cmac_alloc_ctx(ctx_ret, MBEDTLS_CIPHER_ID_3DES, 192); } TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) { return crypto_cmac_alloc_ctx(ctx_ret, MBEDTLS_CIPHER_ID_AES, 128); } optee_os-4.3.0/lib/libmbedtls/core/des3_cbc.c000066400000000000000000000064021464416617300210010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include struct mbed_des3_cbc_ctx { struct crypto_cipher_ctx ctx; int mbed_mode; mbedtls_des3_context des3_ctx; unsigned char iv[TEE_DES_BLOCK_SIZE]; }; static const struct crypto_cipher_ops mbed_des3_cbc_ops; static struct mbed_des3_cbc_ctx *to_des3_cbc_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_des3_cbc_ops); return container_of(ctx, struct mbed_des3_cbc_ctx, ctx); } static TEE_Result mbed_des3_cbc_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct mbed_des3_cbc_ctx *c = to_des3_cbc_ctx(ctx); int mbed_res = 0; if (key1_len != MBEDTLS_DES_KEY_SIZE * 2 && key1_len != MBEDTLS_DES_KEY_SIZE * 3) return TEE_ERROR_BAD_PARAMETERS; if (iv_len != sizeof(c->iv)) return TEE_ERROR_BAD_PARAMETERS; memcpy(c->iv, iv, sizeof(c->iv)); mbedtls_des3_init(&c->des3_ctx); if (mode == TEE_MODE_ENCRYPT) { c->mbed_mode = MBEDTLS_DES_ENCRYPT; if (key1_len == MBEDTLS_DES_KEY_SIZE * 3) mbed_res = mbedtls_des3_set3key_enc(&c->des3_ctx, key1); else mbed_res = mbedtls_des3_set2key_enc(&c->des3_ctx, key1); } else { c->mbed_mode = MBEDTLS_DES_DECRYPT; if (key1_len == MBEDTLS_DES_KEY_SIZE * 3) mbed_res = mbedtls_des3_set3key_dec(&c->des3_ctx, key1); else mbed_res = mbedtls_des3_set2key_dec(&c->des3_ctx, key1); } if (mbed_res) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_des3_cbc_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_des3_cbc_ctx *c = to_des3_cbc_ctx(ctx); if (mbedtls_des3_crypt_cbc(&c->des3_ctx, c->mbed_mode, len, c->iv, data, dst)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static void mbed_des3_cbc_final(struct crypto_cipher_ctx *ctx) { mbedtls_des3_free(&to_des3_cbc_ctx(ctx)->des3_ctx); } static void mbed_des3_cbc_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_des3_cbc_ctx(ctx)); } static void mbed_des3_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_des3_cbc_ctx *src = to_des3_cbc_ctx(src_ctx); struct mbed_des3_cbc_ctx *dst = to_des3_cbc_ctx(dst_ctx); memcpy(dst->iv, src->iv, sizeof(dst->iv)); dst->mbed_mode = src->mbed_mode; dst->des3_ctx = src->des3_ctx; } static const struct crypto_cipher_ops mbed_des3_cbc_ops = { .init = mbed_des3_cbc_init, .update = mbed_des3_cbc_update, .final = mbed_des3_cbc_final, .free_ctx = mbed_des3_cbc_free_ctx, .copy_state = mbed_des3_cbc_copy_state, }; TEE_Result crypto_des3_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_des3_cbc_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_des3_cbc_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/lib/libmbedtls/core/des3_ecb.c000066400000000000000000000061431464416617300210050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include struct mbed_des3_ecb_ctx { struct crypto_cipher_ctx ctx; mbedtls_des3_context des3_ctx; }; static const struct crypto_cipher_ops mbed_des3_ecb_ops; static struct mbed_des3_ecb_ctx *to_des3_ecb_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_des3_ecb_ops); return container_of(ctx, struct mbed_des3_ecb_ctx, ctx); } static TEE_Result mbed_des3_ecb_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct mbed_des3_ecb_ctx *c = to_des3_ecb_ctx(ctx); int mbed_res = 0; if (key1_len != MBEDTLS_DES_KEY_SIZE * 2 && key1_len != MBEDTLS_DES_KEY_SIZE * 3) return TEE_ERROR_BAD_PARAMETERS; mbedtls_des3_init(&c->des3_ctx); if (key1_len == MBEDTLS_DES_KEY_SIZE * 3) { if (mode == TEE_MODE_ENCRYPT) mbed_res = mbedtls_des3_set3key_enc(&c->des3_ctx, key1); else mbed_res = mbedtls_des3_set3key_dec(&c->des3_ctx, key1); } else { if (mode == TEE_MODE_ENCRYPT) mbed_res = mbedtls_des3_set2key_enc(&c->des3_ctx, key1); else mbed_res = mbedtls_des3_set2key_dec(&c->des3_ctx, key1); } if (mbed_res) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_des3_ecb_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_des3_ecb_ctx *c = to_des3_ecb_ctx(ctx); size_t block_size = TEE_DES_BLOCK_SIZE; size_t offs = 0; if (len % block_size) return TEE_ERROR_BAD_PARAMETERS; for (offs = 0; offs < len; offs += block_size) { if (mbedtls_des3_crypt_ecb(&c->des3_ctx, data + offs, dst + offs)) return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static void mbed_des3_ecb_final(struct crypto_cipher_ctx *ctx) { mbedtls_des3_free(&to_des3_ecb_ctx(ctx)->des3_ctx); } static void mbed_des3_ecb_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_des3_ecb_ctx(ctx)); } static void mbed_des3_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_des3_ecb_ctx *src = to_des3_ecb_ctx(src_ctx); struct mbed_des3_ecb_ctx *dst = to_des3_ecb_ctx(dst_ctx); dst->des3_ctx = src->des3_ctx; } static const struct crypto_cipher_ops mbed_des3_ecb_ops = { .init = mbed_des3_ecb_init, .update = mbed_des3_ecb_update, .final = mbed_des3_ecb_final, .free_ctx = mbed_des3_ecb_free_ctx, .copy_state = mbed_des3_ecb_copy_state, }; TEE_Result crypto_des3_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_des3_ecb_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_des3_ecb_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/lib/libmbedtls/core/des_cbc.c000066400000000000000000000056701464416617300207240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include struct mbed_des_cbc_ctx { struct crypto_cipher_ctx ctx; int mbed_mode; mbedtls_des_context des_ctx; unsigned char iv[TEE_DES_BLOCK_SIZE]; }; static const struct crypto_cipher_ops mbed_des_cbc_ops; static struct mbed_des_cbc_ctx *to_des_cbc_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_des_cbc_ops); return container_of(ctx, struct mbed_des_cbc_ctx, ctx); } static TEE_Result mbed_des_cbc_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct mbed_des_cbc_ctx *c = to_des_cbc_ctx(ctx); int mbed_res = 0; if (key1_len != MBEDTLS_DES_KEY_SIZE) return TEE_ERROR_BAD_PARAMETERS; if (iv_len != sizeof(c->iv)) return TEE_ERROR_BAD_PARAMETERS; memcpy(c->iv, iv, sizeof(c->iv)); mbedtls_des_init(&c->des_ctx); if (mode == TEE_MODE_ENCRYPT) { c->mbed_mode = MBEDTLS_DES_ENCRYPT; mbed_res = mbedtls_des_setkey_enc(&c->des_ctx, key1); } else { c->mbed_mode = MBEDTLS_DES_DECRYPT; mbed_res = mbedtls_des_setkey_dec(&c->des_ctx, key1); } if (mbed_res) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_des_cbc_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_des_cbc_ctx *c = to_des_cbc_ctx(ctx); if (mbedtls_des_crypt_cbc(&c->des_ctx, c->mbed_mode, len, c->iv, data, dst)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static void mbed_des_cbc_final(struct crypto_cipher_ctx *ctx) { mbedtls_des_free(&to_des_cbc_ctx(ctx)->des_ctx); } static void mbed_des_cbc_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_des_cbc_ctx(ctx)); } static void mbed_des_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_des_cbc_ctx *src = to_des_cbc_ctx(src_ctx); struct mbed_des_cbc_ctx *dst = to_des_cbc_ctx(dst_ctx); memcpy(dst->iv, src->iv, sizeof(dst->iv)); dst->mbed_mode = src->mbed_mode; dst->des_ctx = src->des_ctx; } static const struct crypto_cipher_ops mbed_des_cbc_ops = { .init = mbed_des_cbc_init, .update = mbed_des_cbc_update, .final = mbed_des_cbc_final, .free_ctx = mbed_des_cbc_free_ctx, .copy_state = mbed_des_cbc_copy_state, }; TEE_Result crypto_des_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_des_cbc_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_des_cbc_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/lib/libmbedtls/core/des_ecb.c000066400000000000000000000054251464416617300207240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include struct mbed_des_ecb_ctx { struct crypto_cipher_ctx ctx; mbedtls_des_context des_ctx; }; static const struct crypto_cipher_ops mbed_des_ecb_ops; static struct mbed_des_ecb_ctx *to_des_ecb_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx && ctx->ops == &mbed_des_ecb_ops); return container_of(ctx, struct mbed_des_ecb_ctx, ctx); } static TEE_Result mbed_des_ecb_init(struct crypto_cipher_ctx *ctx, TEE_OperationMode mode, const uint8_t *key1, size_t key1_len, const uint8_t *key2 __unused, size_t key2_len __unused, const uint8_t *iv __unused, size_t iv_len __unused) { struct mbed_des_ecb_ctx *c = to_des_ecb_ctx(ctx); int mbed_res = 0; if (key1_len != MBEDTLS_DES_KEY_SIZE) return TEE_ERROR_BAD_PARAMETERS; mbedtls_des_init(&c->des_ctx); if (mode == TEE_MODE_ENCRYPT) mbed_res = mbedtls_des_setkey_enc(&c->des_ctx, key1); else mbed_res = mbedtls_des_setkey_dec(&c->des_ctx, key1); if (mbed_res) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_des_ecb_update(struct crypto_cipher_ctx *ctx, bool last_block __unused, const uint8_t *data, size_t len, uint8_t *dst) { struct mbed_des_ecb_ctx *c = to_des_ecb_ctx(ctx); size_t block_size = TEE_DES_BLOCK_SIZE; size_t offs = 0; if (len % block_size) return TEE_ERROR_BAD_PARAMETERS; for (offs = 0; offs < len; offs += block_size) { if (mbedtls_des_crypt_ecb(&c->des_ctx, data + offs, dst + offs)) return TEE_ERROR_BAD_STATE; } return TEE_SUCCESS; } static void mbed_des_ecb_final(struct crypto_cipher_ctx *ctx) { mbedtls_des_free(&to_des_ecb_ctx(ctx)->des_ctx); } static void mbed_des_ecb_free_ctx(struct crypto_cipher_ctx *ctx) { free(to_des_ecb_ctx(ctx)); } static void mbed_des_ecb_copy_state(struct crypto_cipher_ctx *dst_ctx, struct crypto_cipher_ctx *src_ctx) { struct mbed_des_ecb_ctx *src = to_des_ecb_ctx(src_ctx); struct mbed_des_ecb_ctx *dst = to_des_ecb_ctx(dst_ctx); dst->des_ctx = src->des_ctx; } static const struct crypto_cipher_ops mbed_des_ecb_ops = { .init = mbed_des_ecb_init, .update = mbed_des_ecb_update, .final = mbed_des_ecb_final, .free_ctx = mbed_des_ecb_free_ctx, .copy_state = mbed_des_ecb_copy_state, }; TEE_Result crypto_des_ecb_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) { struct mbed_des_ecb_ctx *c = NULL; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->ctx.ops = &mbed_des_ecb_ops; *ctx_ret = &c->ctx; return TEE_SUCCESS; } optee_os-4.3.0/lib/libmbedtls/core/dh.c000066400000000000000000000064351464416617300177350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include "mbed_helpers.h" TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s, size_t key_size_bits) { memset(s, 0, sizeof(*s)); s->g = crypto_bignum_allocate(key_size_bits); if (!s->g) goto err; s->p = crypto_bignum_allocate(key_size_bits); if (!s->p) goto err; s->y = crypto_bignum_allocate(key_size_bits); if (!s->y) goto err; s->x = crypto_bignum_allocate(key_size_bits); if (!s->x) goto err; s->q = crypto_bignum_allocate(key_size_bits); if (!s->q) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->g); crypto_bignum_free(&s->p); crypto_bignum_free(&s->y); crypto_bignum_free(&s->x); return TEE_ERROR_OUT_OF_MEMORY; } TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key, struct bignum *q __unused, size_t xbits, size_t key_size) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; mbedtls_dhm_context dhm; unsigned char *buf = NULL; size_t xbytes = 0; size_t len = 0; memset(&dhm, 0, sizeof(dhm)); mbedtls_dhm_init(&dhm); dhm.G = *(mbedtls_mpi *)key->g; dhm.P = *(mbedtls_mpi *)key->p; len = mbedtls_dhm_get_len(&dhm); if (key_size != 8 * len) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (xbits == 0) xbytes = len; else xbytes = xbits / 8; buf = malloc(len); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } lmd_res = mbedtls_dhm_make_public(&dhm, (int)xbytes, buf, len, mbd_rand, NULL); if (lmd_res != 0) { FMSG("mbedtls_dhm_make_public err, return is 0x%x", -lmd_res); res = TEE_ERROR_BAD_PARAMETERS; } else { crypto_bignum_bin2bn(buf, xbytes, key->y); crypto_bignum_copy(key->x, (void *)&dhm.X); res = TEE_SUCCESS; } out: free(buf); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&dhm.G); mbedtls_mpi_init(&dhm.P); mbedtls_dhm_free(&dhm); return res; } TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key, struct bignum *public_key, struct bignum *secret) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; mbedtls_dhm_context dhm; unsigned char *buf = NULL; size_t olen = 0; size_t len = 0; memset(&dhm, 0, sizeof(dhm)); mbedtls_dhm_init(&dhm); dhm.G = *(mbedtls_mpi *)private_key->g; dhm.P = *(mbedtls_mpi *)private_key->p; dhm.GX = *(mbedtls_mpi *)private_key->y; dhm.X = *(mbedtls_mpi *)private_key->x; dhm.GY = *(mbedtls_mpi *)public_key; len = mbedtls_dhm_get_len(&dhm); buf = malloc(len); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } lmd_res = mbedtls_dhm_calc_secret(&dhm, buf, len, &olen, mbd_rand, NULL); if (lmd_res != 0) { FMSG("mbedtls_dhm_calc_secret failed, ret is 0x%x", -lmd_res); res = TEE_ERROR_BAD_PARAMETERS; } else { crypto_bignum_bin2bn(buf, olen, secret); res = TEE_SUCCESS; } out: free(buf); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&dhm.G); mbedtls_mpi_init(&dhm.P); mbedtls_mpi_init(&dhm.GX); mbedtls_mpi_init(&dhm.X); mbedtls_mpi_init(&dhm.GY); mbedtls_dhm_free(&dhm); return res; } optee_os-4.3.0/lib/libmbedtls/core/ecc.c000066400000000000000000000321361464416617300200710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" #include "sm2-dsa.h" #include "sm2-pke.h" /* Translate mbedtls result to TEE result */ static TEE_Result get_tee_result(int lmd_res) { switch (lmd_res) { case 0: return TEE_SUCCESS; case MBEDTLS_ERR_ECP_VERIFY_FAILED: return TEE_ERROR_SIGNATURE_INVALID; case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: return TEE_ERROR_SHORT_BUFFER; default: return TEE_ERROR_BAD_STATE; } } static void ecc_free_public_key(struct ecc_public_key *s) { if (!s) return; crypto_bignum_free(&s->x); crypto_bignum_free(&s->y); } static TEE_Result ecc_get_keysize(uint32_t curve, uint32_t algo, size_t *key_size_bytes, size_t *key_size_bits) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: *key_size_bits = 192; *key_size_bytes = 24; break; case TEE_ECC_CURVE_NIST_P224: *key_size_bits = 224; *key_size_bytes = 28; break; case TEE_ECC_CURVE_NIST_P256: *key_size_bits = 256; *key_size_bytes = 32; break; case TEE_ECC_CURVE_NIST_P384: *key_size_bits = 384; *key_size_bytes = 48; break; case TEE_ECC_CURVE_NIST_P521: *key_size_bits = 521; *key_size_bytes = 66; break; case TEE_ECC_CURVE_SM2: *key_size_bits = 256; *key_size_bytes = 32; if (algo != 0 && algo != TEE_ALG_SM2_DSA_SM3 && algo != TEE_ALG_SM2_KEP && algo != TEE_ALG_SM2_PKE) return TEE_ERROR_BAD_PARAMETERS; break; default: *key_size_bits = 0; *key_size_bytes = 0; return TEE_ERROR_NOT_SUPPORTED; } return TEE_SUCCESS; } static mbedtls_ecp_group_id curve_to_group_id(uint32_t curve) { switch (curve) { case TEE_ECC_CURVE_NIST_P192: return MBEDTLS_ECP_DP_SECP192R1; case TEE_ECC_CURVE_NIST_P224: return MBEDTLS_ECP_DP_SECP224R1; case TEE_ECC_CURVE_NIST_P256: return MBEDTLS_ECP_DP_SECP256R1; case TEE_ECC_CURVE_NIST_P384: return MBEDTLS_ECP_DP_SECP384R1; case TEE_ECC_CURVE_NIST_P521: return MBEDTLS_ECP_DP_SECP521R1; case TEE_ECC_CURVE_SM2: return MBEDTLS_ECP_DP_SM2; default: return MBEDTLS_ECP_DP_NONE; } } static TEE_Result ecc_generate_keypair(struct ecc_keypair *key, size_t key_size) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; mbedtls_ecdsa_context ecdsa; mbedtls_ecp_group_id gid; size_t key_size_bytes = 0; size_t key_size_bits = 0; memset(&ecdsa, 0, sizeof(ecdsa)); memset(&gid, 0, sizeof(gid)); res = ecc_get_keysize(key->curve, 0, &key_size_bytes, &key_size_bits); if (res != TEE_SUCCESS) return res; if (key_size != key_size_bits) return TEE_ERROR_BAD_PARAMETERS; mbedtls_ecdsa_init(&ecdsa); /* Generate the ECC key */ gid = curve_to_group_id(key->curve); lmd_res = mbedtls_ecdsa_genkey(&ecdsa, gid, mbd_rand, NULL); if (lmd_res != 0) { res = TEE_ERROR_BAD_PARAMETERS; FMSG("mbedtls_ecdsa_genkey failed."); goto exit; } /* check the size of the keys */ if ((mbedtls_mpi_bitlen(&ecdsa.Q.X) > key_size_bits) || (mbedtls_mpi_bitlen(&ecdsa.Q.Y) > key_size_bits) || (mbedtls_mpi_bitlen(&ecdsa.d) > key_size_bits)) { res = TEE_ERROR_BAD_PARAMETERS; FMSG("Check the size of the keys failed."); goto exit; } /* check LMD is returning z==1 */ if (mbedtls_mpi_bitlen(&ecdsa.Q.Z) != 1) { res = TEE_ERROR_BAD_PARAMETERS; FMSG("Check LMD failed."); goto exit; } /* Copy the key */ crypto_bignum_copy(key->d, (void *)&ecdsa.d); crypto_bignum_copy(key->x, (void *)&ecdsa.Q.X); crypto_bignum_copy(key->y, (void *)&ecdsa.Q.Y); res = TEE_SUCCESS; exit: mbedtls_ecdsa_free(&ecdsa); /* Free the temporary key */ return res; } static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; const mbedtls_pk_info_t *pk_info = NULL; mbedtls_ecdsa_context ecdsa; mbedtls_ecp_group_id gid; size_t key_size_bytes = 0; size_t key_size_bits = 0; mbedtls_mpi r; mbedtls_mpi s; memset(&ecdsa, 0, sizeof(ecdsa)); memset(&gid, 0, sizeof(gid)); memset(&r, 0, sizeof(r)); memset(&s, 0, sizeof(s)); if (algo == 0) return TEE_ERROR_BAD_PARAMETERS; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); mbedtls_ecdsa_init(&ecdsa); gid = curve_to_group_id(key->curve); lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, gid); if (lmd_res != 0) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } ecdsa.d = *(mbedtls_mpi *)key->d; res = ecc_get_keysize(key->curve, algo, &key_size_bytes, &key_size_bits); if (res != TEE_SUCCESS) goto out; if (*sig_len < 2 * key_size_bytes) { *sig_len = 2 * key_size_bytes; res = TEE_ERROR_SHORT_BUFFER; goto out; } pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); if (pk_info == NULL) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } lmd_res = mbedtls_ecdsa_sign(&ecdsa.grp, &r, &s, &ecdsa.d, msg, msg_len, mbd_rand, NULL); if (lmd_res == 0) { *sig_len = 2 * key_size_bytes; memset(sig, 0, *sig_len); mbedtls_mpi_write_binary(&r, sig + *sig_len / 2 - mbedtls_mpi_size(&r), mbedtls_mpi_size(&r)); mbedtls_mpi_write_binary(&s, sig + *sig_len - mbedtls_mpi_size(&s), mbedtls_mpi_size(&s)); res = TEE_SUCCESS; } else { FMSG("mbedtls_ecdsa_sign failed, returned 0x%x", -lmd_res); res = TEE_ERROR_GENERIC; } out: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&ecdsa.d); mbedtls_ecdsa_free(&ecdsa); return res; } static TEE_Result ecc_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; mbedtls_ecdsa_context ecdsa; mbedtls_ecp_group_id gid; size_t key_size_bytes, key_size_bits = 0; uint8_t one[1] = { 1 }; mbedtls_mpi r; mbedtls_mpi s; memset(&ecdsa, 0, sizeof(ecdsa)); memset(&gid, 0, sizeof(gid)); memset(&r, 0, sizeof(r)); memset(&s, 0, sizeof(s)); if (algo == 0) return TEE_ERROR_BAD_PARAMETERS; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); mbedtls_ecdsa_init(&ecdsa); gid = curve_to_group_id(key->curve); lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, gid); if (lmd_res != 0) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } ecdsa.Q.X = *(mbedtls_mpi *)key->x; ecdsa.Q.Y = *(mbedtls_mpi *)key->y; mbedtls_mpi_read_binary(&ecdsa.Q.Z, one, sizeof(one)); res = ecc_get_keysize(key->curve, algo, &key_size_bytes, &key_size_bits); if (res != TEE_SUCCESS) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* check keysize vs sig_len */ if ((key_size_bytes * 2) != sig_len) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } mbedtls_mpi_read_binary(&r, sig, sig_len / 2); mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2); lmd_res = mbedtls_ecdsa_verify(&ecdsa.grp, msg, msg_len, &ecdsa.Q, &r, &s); if (lmd_res != 0) { FMSG("mbedtls_ecdsa_verify failed, returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); } out: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&ecdsa.Q.X); mbedtls_mpi_init(&ecdsa.Q.Y); mbedtls_ecdsa_free(&ecdsa); return res; } static TEE_Result ecc_shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; uint8_t one[1] = { 1 }; mbedtls_ecdh_context ecdh; mbedtls_ecp_group_id gid; size_t out_len = 0; memset(&ecdh, 0, sizeof(ecdh)); memset(&gid, 0, sizeof(gid)); mbedtls_ecdh_init(&ecdh); gid = curve_to_group_id(private_key->curve); lmd_res = mbedtls_ecdh_setup(&ecdh, gid); if (lmd_res != 0) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } assert(ecdh.var == MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0); ecdh.ctx.mbed_ecdh.d = *(mbedtls_mpi *)private_key->d; ecdh.ctx.mbed_ecdh.Qp.X = *(mbedtls_mpi *)public_key->x; ecdh.ctx.mbed_ecdh.Qp.Y = *(mbedtls_mpi *)public_key->y; mbedtls_mpi_read_binary(&ecdh.ctx.mbed_ecdh.Qp.Z, one, sizeof(one)); lmd_res = mbedtls_ecdh_calc_secret(&ecdh, &out_len, secret, *secret_len, mbd_rand, NULL); if (lmd_res != 0) { res = get_tee_result(lmd_res); goto out; } *secret_len = out_len; out: /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&ecdh.ctx.mbed_ecdh.d); mbedtls_mpi_init(&ecdh.ctx.mbed_ecdh.Qp.X); mbedtls_mpi_init(&ecdh.ctx.mbed_ecdh.Qp.Y); mbedtls_ecdh_free(&ecdh); return res; } static const struct crypto_ecc_keypair_ops ecc_keypair_ops = { .generate = ecc_generate_keypair, .sign = ecc_sign, .shared_secret = ecc_shared_secret, }; static const struct crypto_ecc_keypair_ops sm2_pke_keypair_ops = { .generate = ecc_generate_keypair, .decrypt = sm2_mbedtls_pke_decrypt, }; static const struct crypto_ecc_keypair_ops sm2_kep_keypair_ops = { .generate = ecc_generate_keypair, }; static const struct crypto_ecc_keypair_ops sm2_dsa_keypair_ops = { .generate = ecc_generate_keypair, .sign = sm2_mbedtls_dsa_sign, }; const struct crypto_ecc_keypair_ops * crypto_asym_get_ecc_keypair_ops(uint32_t key_type) { switch (key_type) { case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: return &ecc_keypair_ops; case TEE_TYPE_SM2_DSA_KEYPAIR: if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) return NULL; return &sm2_dsa_keypair_ops; case TEE_TYPE_SM2_PKE_KEYPAIR: if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) return NULL; return &sm2_pke_keypair_ops; case TEE_TYPE_SM2_KEP_KEYPAIR: if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) return NULL; return &sm2_kep_keypair_ops; default: return NULL; } } TEE_Result crypto_asym_alloc_ecc_keypair(struct ecc_keypair *s, uint32_t key_type, size_t key_size_bits) { memset(s, 0, sizeof(*s)); switch (key_type) { case TEE_TYPE_ECDSA_KEYPAIR: case TEE_TYPE_ECDH_KEYPAIR: s->ops = &ecc_keypair_ops; break; case TEE_TYPE_SM2_DSA_KEYPAIR: if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_dsa_keypair_ops; break; case TEE_TYPE_SM2_PKE_KEYPAIR: if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_pke_keypair_ops; break; case TEE_TYPE_SM2_KEP_KEYPAIR: if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_kep_keypair_ops; break; default: return TEE_ERROR_NOT_IMPLEMENTED; } s->d = crypto_bignum_allocate(key_size_bits); if (!s->d) goto err; s->x = crypto_bignum_allocate(key_size_bits); if (!s->x) goto err; s->y = crypto_bignum_allocate(key_size_bits); if (!s->y) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->d); crypto_bignum_free(&s->x); return TEE_ERROR_OUT_OF_MEMORY; } static const struct crypto_ecc_public_ops ecc_public_key_ops = { .free = ecc_free_public_key, .verify = ecc_verify, }; static const struct crypto_ecc_public_ops sm2_pke_public_key_ops = { .free = ecc_free_public_key, .encrypt = sm2_mbedtls_pke_encrypt, }; static const struct crypto_ecc_public_ops sm2_kep_public_key_ops = { .free = ecc_free_public_key, }; static const struct crypto_ecc_public_ops sm2_dsa_public_key_ops = { .free = ecc_free_public_key, .verify = sm2_mbedtls_dsa_verify, }; const struct crypto_ecc_public_ops* crypto_asym_get_ecc_public_ops(uint32_t key_type) { switch (key_type) { case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDH_PUBLIC_KEY: return &ecc_public_key_ops; case TEE_TYPE_SM2_DSA_PUBLIC_KEY: if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) return NULL; return &sm2_dsa_public_key_ops; case TEE_TYPE_SM2_PKE_PUBLIC_KEY: if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) return NULL; return &sm2_pke_public_key_ops; case TEE_TYPE_SM2_KEP_PUBLIC_KEY: if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) return NULL; return &sm2_kep_public_key_ops; default: return NULL; } } TEE_Result crypto_asym_alloc_ecc_public_key(struct ecc_public_key *s, uint32_t key_type, size_t key_size_bits) { memset(s, 0, sizeof(*s)); switch (key_type) { case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDH_PUBLIC_KEY: s->ops = &ecc_public_key_ops; break; case TEE_TYPE_SM2_DSA_PUBLIC_KEY: if (!IS_ENABLED(CFG_CRYPTO_SM2_DSA)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_dsa_public_key_ops; break; case TEE_TYPE_SM2_PKE_PUBLIC_KEY: if (!IS_ENABLED(CFG_CRYPTO_SM2_PKE)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_pke_public_key_ops; break; case TEE_TYPE_SM2_KEP_PUBLIC_KEY: if (!IS_ENABLED(CFG_CRYPTO_SM2_KEP)) return TEE_ERROR_NOT_IMPLEMENTED; s->curve = TEE_ECC_CURVE_SM2; s->ops = &sm2_kep_public_key_ops; break; default: return TEE_ERROR_NOT_IMPLEMENTED; } s->x = crypto_bignum_allocate(key_size_bits); if (!s->x) goto err; s->y = crypto_bignum_allocate(key_size_bits); if (!s->y) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->x); return TEE_ERROR_OUT_OF_MEMORY; } optee_os-4.3.0/lib/libmbedtls/core/hash.c000066400000000000000000000137311464416617300202620ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct mbed_hash_ctx { struct crypto_hash_ctx hash_ctx; mbedtls_md_context_t md_ctx; }; static const struct crypto_hash_ops mbed_hash_ops; static struct mbed_hash_ctx *to_hash_ctx(struct crypto_hash_ctx *ctx) { assert(ctx && ctx->ops == &mbed_hash_ops); return container_of(ctx, struct mbed_hash_ctx, hash_ctx); } static TEE_Result mbed_hash_init(struct crypto_hash_ctx *ctx) { if (mbedtls_md_starts(&to_hash_ctx(ctx)->md_ctx)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_hash_update(struct crypto_hash_ctx *ctx, const uint8_t *data, size_t len) { if (mbedtls_md_update(&to_hash_ctx(ctx)->md_ctx, data, len)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_hash_final(struct crypto_hash_ctx *ctx, uint8_t *digest, size_t len) { struct mbed_hash_ctx *hc = to_hash_ctx(ctx); uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; uint8_t *tmp_digest = NULL; size_t hash_size = 0; if (len == 0) return TEE_ERROR_BAD_PARAMETERS; hash_size = mbedtls_md_get_size(mbedtls_md_info_from_ctx(&hc->md_ctx)); if (hash_size > len) { if (hash_size > sizeof(block_digest)) return TEE_ERROR_BAD_STATE; tmp_digest = block_digest; /* use a tempory buffer */ } else { tmp_digest = digest; } if (mbedtls_md_finish(&hc->md_ctx, tmp_digest)) return TEE_ERROR_BAD_STATE; if (hash_size > len) memcpy(digest, tmp_digest, len); return TEE_SUCCESS; } static void mbed_hash_free_ctx(struct crypto_hash_ctx *ctx) { struct mbed_hash_ctx *hc = to_hash_ctx(ctx); mbedtls_md_free(&hc->md_ctx); free(hc); } static void mbed_hash_copy_state(struct crypto_hash_ctx *dst_ctx, struct crypto_hash_ctx *src_ctx) { struct mbed_hash_ctx *src = to_hash_ctx(src_ctx); struct mbed_hash_ctx *dst = to_hash_ctx(dst_ctx); if (mbedtls_md_clone(&dst->md_ctx, &src->md_ctx)) panic(); } static const struct crypto_hash_ops mbed_hash_ops = { .init = mbed_hash_init, .update = mbed_hash_update, .final = mbed_hash_final, .free_ctx = mbed_hash_free_ctx, .copy_state = mbed_hash_copy_state, }; static TEE_Result mbed_hash_alloc_ctx(struct crypto_hash_ctx **ctx_ret, mbedtls_md_type_t md_type) { int mbed_res = 0; struct mbed_hash_ctx *hc = NULL; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); if (!md_info) return TEE_ERROR_NOT_SUPPORTED; hc = calloc(1, sizeof(*hc)); if (!hc) return TEE_ERROR_OUT_OF_MEMORY; hc->hash_ctx.ops = &mbed_hash_ops; mbed_res = mbedtls_md_setup(&hc->md_ctx, md_info, 0); if (mbed_res) { free(hc); if (mbed_res == MBEDTLS_ERR_MD_ALLOC_FAILED) return TEE_ERROR_OUT_OF_MEMORY; return TEE_ERROR_NOT_SUPPORTED; } *ctx_ret = &hc->hash_ctx; return TEE_SUCCESS; } #if defined(CFG_CRYPTO_MD5) TEE_Result crypto_md5_alloc_ctx(struct crypto_hash_ctx **ctx) { return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_MD5); } #endif #if defined(CFG_CRYPTO_SHA1) TEE_Result crypto_sha1_alloc_ctx(struct crypto_hash_ctx **ctx) { return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA1); } #endif #if defined(CFG_CRYPTO_SHA224) TEE_Result crypto_sha224_alloc_ctx(struct crypto_hash_ctx **ctx) { return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA224); } #endif #if defined(CFG_CRYPTO_SHA256) TEE_Result crypto_sha256_alloc_ctx(struct crypto_hash_ctx **ctx) { return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA256); } #endif #if defined(CFG_CRYPTO_SHA384) TEE_Result crypto_sha384_alloc_ctx(struct crypto_hash_ctx **ctx) { return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA384); } #endif #if defined(CFG_CRYPTO_SHA512) TEE_Result crypto_sha512_alloc_ctx(struct crypto_hash_ctx **ctx) { return mbed_hash_alloc_ctx(ctx, MBEDTLS_MD_SHA512); } #endif #if defined(CFG_CRYPTO_SHA256) TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data, size_t data_size) { mbedtls_sha256_context hs; uint8_t digest[TEE_SHA256_HASH_SIZE] = { 0 }; memset(&hs, 0, sizeof(hs)); mbedtls_sha256_init(&hs); mbedtls_sha256_starts(&hs, 0); mbedtls_sha256_update(&hs, data, data_size); mbedtls_sha256_finish(&hs, digest); mbedtls_sha256_free(&hs); if (consttime_memcmp(digest, hash, sizeof(digest))) return TEE_ERROR_SECURITY; return TEE_SUCCESS; } #endif #if defined(MBEDTLS_SHA1_PROCESS_ALT) int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]) { MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA); MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA); crypto_accel_sha1_compress(ctx->state, data, 1); return 0; } #endif /*MBEDTLS_SHA1_PROCESS_ALT*/ #if defined(MBEDTLS_SHA256_PROCESS_ALT) int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64]) { MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA); MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA); crypto_accel_sha256_compress(ctx->state, data, 1); return 0; } #endif /*MBEDTLS_SHA256_PROCESS_ALT*/ #if defined(MBEDTLS_SHA512_PROCESS_ALT) int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[64]) { MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA); MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA); crypto_accel_sha512_compress(ctx->state, data, 1); return 0; } #endif /*MBEDTLS_SHA512_PROCESS_ALT*/ optee_os-4.3.0/lib/libmbedtls/core/hmac.c000066400000000000000000000100311464416617300202350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include struct mbed_hmac_ctx { struct crypto_mac_ctx mac_ctx; mbedtls_md_context_t md_ctx; }; static const struct crypto_mac_ops mbed_hmac_ops; static struct mbed_hmac_ctx *to_hmac_ctx(struct crypto_mac_ctx *ctx) { assert(ctx && ctx->ops == &mbed_hmac_ops); return container_of(ctx, struct mbed_hmac_ctx, mac_ctx); } static TEE_Result mbed_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key, size_t len) { if (mbedtls_md_hmac_starts(&to_hmac_ctx(ctx)->md_ctx, key, len)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_hmac_update(struct crypto_mac_ctx *ctx, const uint8_t *data, size_t len) { if (mbedtls_md_hmac_update(&to_hmac_ctx(ctx)->md_ctx, data, len)) return TEE_ERROR_BAD_STATE; return TEE_SUCCESS; } static TEE_Result mbed_hmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest, size_t len) { struct mbed_hmac_ctx *c = to_hmac_ctx(ctx); uint8_t block_digest[TEE_MAX_HASH_SIZE] = { 0 }; uint8_t *tmp_digest = NULL; size_t hmac_size = 0; if (len == 0) return TEE_ERROR_BAD_PARAMETERS; hmac_size = mbedtls_md_get_size(mbedtls_md_info_from_ctx(&c->md_ctx)); if (hmac_size > len) { if (hmac_size > sizeof(block_digest)) return TEE_ERROR_BAD_STATE; tmp_digest = block_digest; /* use a tempory buffer */ } else { tmp_digest = digest; } if (mbedtls_md_hmac_finish(&c->md_ctx, tmp_digest)) return TEE_ERROR_BAD_STATE; if (hmac_size > len) memcpy(digest, tmp_digest, len); return TEE_SUCCESS; } static void mbed_hmac_free_ctx(struct crypto_mac_ctx *ctx) { struct mbed_hmac_ctx *c = to_hmac_ctx(ctx); mbedtls_md_free(&c->md_ctx); free(c); } static void mbed_hmac_copy_state(struct crypto_mac_ctx *dst_ctx, struct crypto_mac_ctx *src_ctx) { struct mbed_hmac_ctx *src = to_hmac_ctx(src_ctx); struct mbed_hmac_ctx *dst = to_hmac_ctx(dst_ctx); if (mbedtls_md_clone(&dst->md_ctx, &src->md_ctx)) panic(); } static const struct crypto_mac_ops mbed_hmac_ops = { .init = mbed_hmac_init, .update = mbed_hmac_update, .final = mbed_hmac_final, .free_ctx = mbed_hmac_free_ctx, .copy_state = mbed_hmac_copy_state, }; static TEE_Result mbed_hmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, mbedtls_md_type_t md_type) { int mbed_res = 0; struct mbed_hmac_ctx *c = NULL; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); if (!md_info) return TEE_ERROR_NOT_SUPPORTED; c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->mac_ctx.ops = &mbed_hmac_ops; mbed_res = mbedtls_md_setup(&c->md_ctx, md_info, 1); if (mbed_res) { free(c); if (mbed_res == MBEDTLS_ERR_MD_ALLOC_FAILED) return TEE_ERROR_OUT_OF_MEMORY; return TEE_ERROR_NOT_SUPPORTED; } *ctx_ret = &c->mac_ctx; return TEE_SUCCESS; } #if defined(CFG_CRYPTO_MD5) TEE_Result crypto_hmac_md5_alloc_ctx(struct crypto_mac_ctx **ctx) { return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_MD5); } #endif #if defined(CFG_CRYPTO_SHA1) TEE_Result crypto_hmac_sha1_alloc_ctx(struct crypto_mac_ctx **ctx) { return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA1); } #endif #if defined(CFG_CRYPTO_SHA224) TEE_Result crypto_hmac_sha224_alloc_ctx(struct crypto_mac_ctx **ctx) { return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA224); } #endif #if defined(CFG_CRYPTO_SHA256) TEE_Result crypto_hmac_sha256_alloc_ctx(struct crypto_mac_ctx **ctx) { return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA256); } #endif #if defined(CFG_CRYPTO_SHA384) TEE_Result crypto_hmac_sha384_alloc_ctx(struct crypto_mac_ctx **ctx) { return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA384); } #endif #if defined(CFG_CRYPTO_SHA512) TEE_Result crypto_hmac_sha512_alloc_ctx(struct crypto_mac_ctx **ctx) { return mbed_hmac_alloc_ctx(ctx, MBEDTLS_MD_SHA512); } #endif optee_os-4.3.0/lib/libmbedtls/core/mbed_helpers.c000066400000000000000000000013041464416617300217610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include "mbed_helpers.h" /* Generate random number 1 <= n < max */ TEE_Result mbed_gen_random_upto(mbedtls_mpi *n, mbedtls_mpi *max) { size_t sz = mbedtls_mpi_size(max); bool found = false; int mres = 0; do { mres = mbedtls_mpi_fill_random(n, sz, mbd_rand, NULL); if (mres) return TEE_ERROR_BAD_STATE; if (mbedtls_mpi_bitlen(n) != 0 && mbedtls_mpi_cmp_mpi(n, max) == -1) found = true; } while (!found); return TEE_SUCCESS; } optee_os-4.3.0/lib/libmbedtls/core/mbed_helpers.h000066400000000000000000000013251464416617300217710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #ifndef MBED_HELPERS_H #define MBED_HELPERS_H #include #include #include #include #include static inline int mbd_rand(void *rng_state __unused, unsigned char *output, size_t len) { if (crypto_rng_read(output, len)) return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; return 0; } static inline void mbed_copy_mbedtls_aes_context(mbedtls_aes_context *dst, mbedtls_aes_context *src) { *dst = *src; } TEE_Result mbed_gen_random_upto(mbedtls_mpi *n, mbedtls_mpi *max); #endif /*MBED_HELPERS_H*/ optee_os-4.3.0/lib/libmbedtls/core/rsa.c000066400000000000000000000540601464416617300201240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" #include "../mbedtls/library/pk_wrap.h" #include "../mbedtls/library/rsa_alt_helpers.h" static TEE_Result get_tee_result(int lmd_res) { switch (lmd_res) { case 0: return TEE_SUCCESS; case MBEDTLS_ERR_RSA_PRIVATE_FAILED + MBEDTLS_ERR_MPI_BAD_INPUT_DATA: case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: case MBEDTLS_ERR_RSA_INVALID_PADDING: case MBEDTLS_ERR_PK_TYPE_MISMATCH: return TEE_ERROR_BAD_PARAMETERS; case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: return TEE_ERROR_SHORT_BUFFER; default: return TEE_ERROR_BAD_STATE; } } static uint32_t tee_algo_to_mbedtls_hash_algo(uint32_t algo) { switch (algo) { #if defined(CFG_CRYPTO_SHA1) case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: case TEE_ALG_SHA1: case TEE_ALG_DSA_SHA1: case TEE_ALG_HMAC_SHA1: return MBEDTLS_MD_SHA1; #endif #if defined(CFG_CRYPTO_MD5) case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: case TEE_ALG_MD5: case TEE_ALG_HMAC_MD5: return MBEDTLS_MD_MD5; #endif #if defined(CFG_CRYPTO_SHA224) case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: case TEE_ALG_SHA224: case TEE_ALG_DSA_SHA224: case TEE_ALG_HMAC_SHA224: return MBEDTLS_MD_SHA224; #endif #if defined(CFG_CRYPTO_SHA256) case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: case TEE_ALG_SHA256: case TEE_ALG_DSA_SHA256: case TEE_ALG_HMAC_SHA256: return MBEDTLS_MD_SHA256; #endif #if defined(CFG_CRYPTO_SHA384) case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: case TEE_ALG_SHA384: case TEE_ALG_HMAC_SHA384: return MBEDTLS_MD_SHA384; #endif #if defined(CFG_CRYPTO_SHA512) case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: case TEE_ALG_SHA512: case TEE_ALG_HMAC_SHA512: return MBEDTLS_MD_SHA512; #endif default: return MBEDTLS_MD_NONE; } } static TEE_Result rsa_complete_from_key_pair(mbedtls_rsa_context *rsa, struct rsa_keypair *key) { int lmd_res = 0; rsa->E = *(mbedtls_mpi *)key->e; rsa->N = *(mbedtls_mpi *)key->n; rsa->D = *(mbedtls_mpi *)key->d; rsa->len = mbedtls_mpi_size(&rsa->N); if (key->p && crypto_bignum_num_bytes(key->p)) { rsa->P = *(mbedtls_mpi *)key->p; rsa->Q = *(mbedtls_mpi *)key->q; rsa->QP = *(mbedtls_mpi *)key->qp; rsa->DP = *(mbedtls_mpi *)key->dp; rsa->DQ = *(mbedtls_mpi *)key->dq; } else { mbedtls_mpi_init_mempool(&rsa->P); mbedtls_mpi_init_mempool(&rsa->Q); mbedtls_mpi_init_mempool(&rsa->QP); mbedtls_mpi_init_mempool(&rsa->DP); mbedtls_mpi_init_mempool(&rsa->DQ); lmd_res = mbedtls_rsa_deduce_primes(&rsa->N, &rsa->E, &rsa->D, &rsa->P, &rsa->Q); if (lmd_res) { DMSG("mbedtls_rsa_deduce_primes() returned 0x%x", -lmd_res); goto err; } lmd_res = mbedtls_rsa_deduce_crt(&rsa->P, &rsa->Q, &rsa->D, &rsa->DP, &rsa->DQ, &rsa->QP); if (lmd_res) { DMSG("mbedtls_rsa_deduce_crt() returned 0x%x", -lmd_res); goto err; } } return TEE_SUCCESS; err: mbedtls_mpi_free(&rsa->P); mbedtls_mpi_free(&rsa->Q); mbedtls_mpi_free(&rsa->QP); mbedtls_mpi_free(&rsa->DP); mbedtls_mpi_free(&rsa->DQ); return get_tee_result(lmd_res); } static TEE_Result rsa_init_and_complete_from_key_pair(mbedtls_rsa_context *rsa, struct rsa_keypair *key) { mbedtls_rsa_init(rsa); return rsa_complete_from_key_pair(rsa, key); } static void mbd_rsa_free(mbedtls_rsa_context *rsa, struct rsa_keypair *key) { /* * The mpi's in @rsa are initialized from @key, but the primes and * CRT part are generated if @key doesn't have them. When freeing * we should only free the generated mpi's, the ones copied are * reset instead. */ mbedtls_mpi_init(&rsa->E); mbedtls_mpi_init(&rsa->N); mbedtls_mpi_init(&rsa->D); if (key->p && crypto_bignum_num_bytes(key->p)) { mbedtls_mpi_init(&rsa->P); mbedtls_mpi_init(&rsa->Q); mbedtls_mpi_init(&rsa->QP); mbedtls_mpi_init(&rsa->DP); mbedtls_mpi_init(&rsa->DQ); } mbedtls_rsa_free(rsa); } static void mbd_pk_free(mbedtls_pk_context *ctx, struct rsa_keypair *key) { mbedtls_rsa_context *rsa = ctx->pk_ctx; /* * Executing mbedtls_rsa_free twice is fine, as it does nothing if its * argument is NULL. */ mbd_rsa_free(rsa, key); mbedtls_pk_free(ctx); } TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, size_t key_size_bits) __weak __alias("sw_crypto_acipher_alloc_rsa_keypair"); TEE_Result sw_crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s, size_t key_size_bits) { memset(s, 0, sizeof(*s)); s->e = crypto_bignum_allocate(key_size_bits); if (!s->e) goto err; s->d = crypto_bignum_allocate(key_size_bits); if (!s->d) goto err; s->n = crypto_bignum_allocate(key_size_bits); if (!s->n) goto err; s->p = crypto_bignum_allocate(key_size_bits); if (!s->p) goto err; s->q = crypto_bignum_allocate(key_size_bits); if (!s->q) goto err; s->qp = crypto_bignum_allocate(key_size_bits); if (!s->qp) goto err; s->dp = crypto_bignum_allocate(key_size_bits); if (!s->dp) goto err; s->dq = crypto_bignum_allocate(key_size_bits); if (!s->dq) goto err; return TEE_SUCCESS; err: crypto_acipher_free_rsa_keypair(s); return TEE_ERROR_OUT_OF_MEMORY; } TEE_Result crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, size_t key_size_bits) __weak __alias("sw_crypto_acipher_alloc_rsa_public_key"); TEE_Result sw_crypto_acipher_alloc_rsa_public_key(struct rsa_public_key *s, size_t key_size_bits) { memset(s, 0, sizeof(*s)); s->e = crypto_bignum_allocate(key_size_bits); if (!s->e) return TEE_ERROR_OUT_OF_MEMORY; s->n = crypto_bignum_allocate(key_size_bits); if (!s->n) goto err; return TEE_SUCCESS; err: crypto_bignum_free(&s->e); return TEE_ERROR_OUT_OF_MEMORY; } void crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) __weak __alias("sw_crypto_acipher_free_rsa_public_key"); void sw_crypto_acipher_free_rsa_public_key(struct rsa_public_key *s) { if (!s) return; crypto_bignum_free(&s->n); crypto_bignum_free(&s->e); } void crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) __weak __alias("sw_crypto_acipher_free_rsa_keypair"); void sw_crypto_acipher_free_rsa_keypair(struct rsa_keypair *s) { if (!s) return; crypto_bignum_free(&s->e); crypto_bignum_free(&s->d); crypto_bignum_free(&s->n); crypto_bignum_free(&s->p); crypto_bignum_free(&s->q); crypto_bignum_free(&s->qp); crypto_bignum_free(&s->dp); crypto_bignum_free(&s->dq); } TEE_Result crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) __weak __alias("sw_crypto_acipher_gen_rsa_key"); TEE_Result sw_crypto_acipher_gen_rsa_key(struct rsa_keypair *key, size_t key_size) { TEE_Result res = TEE_SUCCESS; mbedtls_rsa_context rsa; mbedtls_ctr_drbg_context rngctx; int lmd_res = 0; uint32_t e = 0; mbedtls_ctr_drbg_init(&rngctx); if (mbedtls_ctr_drbg_seed(&rngctx, mbd_rand, NULL, NULL, 0)) return TEE_ERROR_BAD_STATE; memset(&rsa, 0, sizeof(rsa)); mbedtls_rsa_init(&rsa); /* get the public exponent */ mbedtls_mpi_write_binary((mbedtls_mpi *)key->e, (unsigned char *)&e, sizeof(uint32_t)); e = TEE_U32_FROM_BIG_ENDIAN(e); lmd_res = mbedtls_rsa_gen_key(&rsa, mbedtls_ctr_drbg_random, &rngctx, key_size, (int)e); mbedtls_ctr_drbg_free(&rngctx); if (lmd_res != 0) { res = get_tee_result(lmd_res); } else if ((size_t)mbedtls_mpi_bitlen(&rsa.N) != key_size) { res = TEE_ERROR_BAD_PARAMETERS; } else { /* Copy the key */ crypto_bignum_copy(key->e, (void *)&rsa.E); crypto_bignum_copy(key->d, (void *)&rsa.D); crypto_bignum_copy(key->n, (void *)&rsa.N); crypto_bignum_copy(key->p, (void *)&rsa.P); crypto_bignum_copy(key->q, (void *)&rsa.Q); crypto_bignum_copy(key->qp, (void *)&rsa.QP); crypto_bignum_copy(key->dp, (void *)&rsa.DP); crypto_bignum_copy(key->dq, (void *)&rsa.DQ); res = TEE_SUCCESS; } mbedtls_rsa_free(&rsa); return res; } TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsanopad_encrypt"); TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; mbedtls_rsa_context rsa; int lmd_res = 0; uint8_t *buf = NULL; unsigned long blen = 0; unsigned long offset = 0; memset(&rsa, 0, sizeof(rsa)); mbedtls_rsa_init(&rsa); rsa.E = *(mbedtls_mpi *)key->e; rsa.N = *(mbedtls_mpi *)key->n; rsa.len = crypto_bignum_num_bytes((void *)&rsa.N); blen = CFG_CORE_BIGNUM_MAX_BITS / 8; buf = malloc(blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } memset(buf, 0, blen); memcpy(buf + rsa.len - src_len, src, src_len); lmd_res = mbedtls_rsa_public(&rsa, buf, buf); if (lmd_res != 0) { FMSG("mbedtls_rsa_public() returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); goto out; } /* Remove the zero-padding (leave one zero if buff is all zeroes) */ offset = 0; while ((offset < rsa.len - 1) && (buf[offset] == 0)) offset++; if (*dst_len < rsa.len - offset) { *dst_len = rsa.len - offset; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = rsa.len - offset; memcpy(dst, buf + offset, *dst_len); out: free(buf); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&rsa.E); mbedtls_mpi_init(&rsa.N); mbedtls_rsa_free(&rsa); return res; } TEE_Result crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsanopad_decrypt"); TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; mbedtls_rsa_context rsa = { }; int lmd_res = 0; uint8_t *buf = NULL; unsigned long blen = 0; unsigned long offset = 0; res = rsa_init_and_complete_from_key_pair(&rsa, key); if (res) return res; blen = CFG_CORE_BIGNUM_MAX_BITS / 8; buf = malloc(blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } memset(buf, 0, blen); memcpy(buf + rsa.len - src_len, src, src_len); lmd_res = mbedtls_rsa_private(&rsa, mbd_rand, NULL, buf, buf); if (lmd_res != 0) { FMSG("mbedtls_rsa_private() returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); goto out; } /* Remove the zero-padding (leave one zero if buff is all zeroes) */ offset = 0; while ((offset < rsa.len - 1) && (buf[offset] == 0)) offset++; if (*dst_len < rsa.len - offset) { *dst_len = rsa.len - offset; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = rsa.len - offset; memcpy(dst, (char *)buf + offset, *dst_len); out: if (buf) free(buf); mbd_rsa_free(&rsa, key); return res; } TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label __unused, size_t label_len __unused, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsaes_decrypt"); TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key, const uint8_t *label __unused, size_t label_len __unused, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; int lmd_padding = 0; size_t blen = 0; size_t mod_size = 0; void *buf = NULL; mbedtls_pk_context ctx = { }; mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; uint32_t md_algo = MBEDTLS_MD_NONE; pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (!pk_info) { return TEE_ERROR_NOT_SUPPORTED; } mbedtls_pk_init(&ctx); res = mbedtls_pk_setup(&ctx, pk_info); if (res != 0) { goto out; } rsa = ctx.pk_ctx; res = rsa_complete_from_key_pair(rsa, key); if (res) return res; /* * Use a temporary buffer since we don't know exactly how large * the required size of the out buffer without doing a partial * decrypt. We know the upper bound though. */ if (algo == TEE_ALG_RSAES_PKCS1_V1_5) { mod_size = crypto_bignum_num_bytes(key->n); blen = mod_size - 11; lmd_padding = MBEDTLS_RSA_PKCS_V15; } else { /* Decoded message is always shorter than encrypted message */ blen = src_len; lmd_padding = MBEDTLS_RSA_PKCS_V21; } buf = malloc(blen); if (!buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } /* * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will * not be used in rsa, so skip it here. */ if (algo != TEE_ALG_RSAES_PKCS1_V1_5) { md_algo = tee_algo_to_mbedtls_hash_algo(algo); if (md_algo == MBEDTLS_MD_NONE) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } if (md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) { DMSG("Using a different MGF1 algorithm is not supported"); res = TEE_ERROR_NOT_SUPPORTED; goto out; } } mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo); lmd_res = pk_info->decrypt_func(&ctx, src, src_len, buf, &blen, blen, mbd_rand, NULL); if (lmd_res != 0) { FMSG("decrypt_func() returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); goto out; } if (*dst_len < blen) { *dst_len = blen; res = TEE_ERROR_SHORT_BUFFER; goto out; } res = TEE_SUCCESS; *dst_len = blen; memcpy(dst, buf, blen); out: if (buf) free(buf); mbd_pk_free(&ctx, key); return res; } TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label __unused, size_t label_len __unused, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) __weak __alias("sw_crypto_acipher_rsaes_encrypt"); TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo, struct rsa_public_key *key, const uint8_t *label __unused, size_t label_len __unused, uint32_t mgf_algo, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; int lmd_padding = 0; size_t mod_size = 0; mbedtls_pk_context ctx = { }; mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; uint32_t md_algo = MBEDTLS_MD_NONE; memset(&ctx, 0, sizeof(ctx)); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (!pk_info) { return TEE_ERROR_NOT_SUPPORTED; } mbedtls_pk_init(&ctx); res = mbedtls_pk_setup(&ctx, pk_info); if (res != 0) { goto out; } rsa = ctx.pk_ctx; rsa->E = *(mbedtls_mpi *)key->e; rsa->N = *(mbedtls_mpi *)key->n; mod_size = crypto_bignum_num_bytes(key->n); if (*dst_len < mod_size) { *dst_len = mod_size; res = TEE_ERROR_SHORT_BUFFER; goto out; } *dst_len = mod_size; rsa->len = mod_size; if (algo == TEE_ALG_RSAES_PKCS1_V1_5) lmd_padding = MBEDTLS_RSA_PKCS_V15; else lmd_padding = MBEDTLS_RSA_PKCS_V21; /* * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will * not be used in rsa, so skip it here. */ if (algo != TEE_ALG_RSAES_PKCS1_V1_5) { md_algo = tee_algo_to_mbedtls_hash_algo(algo); /* Using a different MGF1 algorithm is not supported. */ if (md_algo == MBEDTLS_MD_NONE || md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } } mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo); lmd_res = pk_info->encrypt_func(&ctx, src, src_len, dst, dst_len, *dst_len, mbd_rand, NULL); if (lmd_res != 0) { FMSG("encrypt_func() returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); goto out; } res = TEE_SUCCESS; out: /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&rsa->E); mbedtls_mpi_init(&rsa->N); mbedtls_pk_free(&ctx); return res; } TEE_Result crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len __unused, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) __weak __alias("sw_crypto_acipher_rsassa_sign"); TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key, int salt_len __unused, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; int lmd_padding = 0; size_t mod_size = 0; size_t hash_size = 0; mbedtls_pk_context ctx = { }; mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; uint32_t md_algo = 0; memset(&ctx, 0, sizeof(ctx)); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (!pk_info) { return TEE_ERROR_NOT_SUPPORTED; } mbedtls_pk_init(&ctx); res = mbedtls_pk_setup(&ctx, pk_info); if (res != 0) { goto err; } rsa = ctx.pk_ctx; res = rsa_complete_from_key_pair(rsa, key); if (res) return res; switch (algo) { case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: lmd_padding = MBEDTLS_RSA_PKCS_V15; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: lmd_padding = MBEDTLS_RSA_PKCS_V21; break; default: res = TEE_ERROR_BAD_PARAMETERS; goto err; } res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &hash_size); if (res != TEE_SUCCESS) goto err; if (msg_len != hash_size) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } mod_size = crypto_bignum_num_bytes(key->n); if (*sig_len < mod_size) { *sig_len = mod_size; res = TEE_ERROR_SHORT_BUFFER; goto err; } rsa->len = mod_size; md_algo = tee_algo_to_mbedtls_hash_algo(algo); if (md_algo == MBEDTLS_MD_NONE) { res = TEE_ERROR_NOT_SUPPORTED; goto err; } mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo); lmd_res = pk_info->sign_func(&ctx, md_algo, msg, msg_len, sig, *sig_len, sig_len, mbd_rand, NULL); if (lmd_res != 0) { FMSG("sign_func failed, returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); goto err; } res = TEE_SUCCESS; err: mbd_pk_free(&ctx, key); return res; } TEE_Result crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len __unused, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) __weak __alias("sw_crypto_acipher_rsassa_verify"); TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo, struct rsa_public_key *key, int salt_len __unused, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; int lmd_padding = 0; size_t hash_size = 0; size_t bigint_size = 0; mbedtls_pk_context ctx = { }; mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; uint32_t md_algo = 0; struct ftmn ftmn = { }; unsigned long arg_hash = 0; /* * The caller expects to call crypto_acipher_rsassa_verify(), * update the hash as needed. */ FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify")); memset(&ctx, 0, sizeof(ctx)); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (!pk_info) { return TEE_ERROR_NOT_SUPPORTED; } mbedtls_pk_init(&ctx); res = mbedtls_pk_setup(&ctx, pk_info); if (res != 0) { goto err; } rsa = ctx.pk_ctx; rsa->E = *(mbedtls_mpi *)key->e; rsa->N = *(mbedtls_mpi *)key->n; res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo), &hash_size); if (res != TEE_SUCCESS) goto err; if (msg_len != hash_size) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } bigint_size = crypto_bignum_num_bytes(key->n); if (sig_len < bigint_size) { res = TEE_ERROR_SIGNATURE_INVALID; goto err; } rsa->len = bigint_size; switch (algo) { case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pkcs1_v15_verify"); lmd_padding = MBEDTLS_RSA_PKCS_V15; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: arg_hash = FTMN_FUNC_HASH("mbedtls_rsa_rsassa_pss_verify_ext"); lmd_padding = MBEDTLS_RSA_PKCS_V21; break; default: res = TEE_ERROR_BAD_PARAMETERS; goto err; } md_algo = tee_algo_to_mbedtls_hash_algo(algo); if (md_algo == MBEDTLS_MD_NONE) { res = TEE_ERROR_NOT_SUPPORTED; goto err; } mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo); FTMN_PUSH_LINKED_CALL(&ftmn, arg_hash); lmd_res = pk_info->verify_func(&ctx, md_algo, msg, msg_len, sig, sig_len); if (!lmd_res) FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, lmd_res); FTMN_POP_LINKED_CALL(&ftmn); if (lmd_res != 0) { FMSG("verify_func failed, returned 0x%x", -lmd_res); res = TEE_ERROR_SIGNATURE_INVALID; goto err; } res = TEE_SUCCESS; goto out; err: FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, FTMN_INCR0, res); out: FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&rsa->E); mbedtls_mpi_init(&rsa->N); mbedtls_pk_free(&ctx); return res; } optee_os-4.3.0/lib/libmbedtls/core/sm2-dsa.c000066400000000000000000000141321464416617300206010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2021 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" #include "sm2-dsa.h" /* SM2 uses 256 bit unsigned integers in big endian format */ #define SM2_INT_SIZE_BYTES 32 /* * GM/T 0003.1‒2012 Part1 2 Section 6.1 */ TEE_Result sm2_mbedtls_dsa_sign(uint32_t algo __unused, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res = TEE_SUCCESS; mbedtls_ecp_group grp = { }; mbedtls_ecp_point x1y1p = { }; int mres = 0; mbedtls_mpi k = { }; mbedtls_mpi e = { }; mbedtls_mpi r = { }; mbedtls_mpi s = { }; mbedtls_mpi tmp = { }; if (*sig_len < 2 * SM2_INT_SIZE_BYTES) { *sig_len = 64; return TEE_ERROR_SHORT_BUFFER; } mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); mbedtls_mpi_init(&tmp); mbedtls_ecp_point_init(&x1y1p); mbedtls_ecp_group_init(&grp); mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); if (mres) { res = TEE_ERROR_GENERIC; goto out; } /* * Steps A1 and A2 are the generation of the hash value e from user * information (ZA) and the message to be signed (M). There are not done * here since @msg is expected to be the hash value e already. */ /* Step A3: generate random number 1 <= k < n */ do { res = mbed_gen_random_upto(&k, &grp.N); if (res) goto out; res = TEE_ERROR_BAD_STATE; /* Step A4: compute (x1, y1) = [k]G */ mres = mbedtls_ecp_mul(&grp, &x1y1p, &k, &grp.G, mbd_rand, NULL); if (mres) goto out; /* Step A5: compute r = (e + x1) mod n */ mbedtls_mpi_read_binary(&e, (unsigned char *)msg, msg_len); mres = mbedtls_mpi_add_mpi(&r, &e, &x1y1p.X); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&r, &r, &grp.N); if (mres) goto out; /* Step A5 (continued): return to A3 if r = 0 or r + k = n */ mres = mbedtls_mpi_add_mpi(&tmp, &r, &k); if (mres) goto out; } while (!mbedtls_mpi_cmp_int(&r, 0) || !mbedtls_mpi_cmp_mpi(&tmp, &grp.N)); /* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */ mres = mbedtls_mpi_add_int(&s, (mbedtls_mpi *)key->d, 1); if (mres) goto out; mres = mbedtls_mpi_inv_mod(&s, &s, &grp.N); if (mres) goto out; mres = mbedtls_mpi_mul_mpi(&tmp, &r, (mbedtls_mpi *)key->d); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&tmp, &tmp, &grp.N); if (mres) goto out; mres = mbedtls_mpi_sub_mpi(&tmp, &k, &tmp); if (mres) goto out; mres = mbedtls_mpi_mul_mpi(&s, &s, &tmp); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&s, &s, &grp.N); if (mres) goto out; /* Step A7: convert (r, s) to binary for output */ *sig_len = 2 * SM2_INT_SIZE_BYTES; memset(sig, 0, *sig_len); mres = mbedtls_mpi_write_binary(&r, sig, SM2_INT_SIZE_BYTES); if (mres) goto out; mres = mbedtls_mpi_write_binary(&s, sig + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (mres) goto out; res = TEE_SUCCESS; out: mbedtls_ecp_point_free(&x1y1p); mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_mpi_free(&tmp); mbedtls_ecp_group_free(&grp); return res; } /* * GM/T 0003.1‒2012 Part1 2 Section 7.1 */ TEE_Result sm2_mbedtls_dsa_verify(uint32_t algo __unused, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res = TEE_ERROR_BAD_STATE; mbedtls_ecp_group grp = { }; mbedtls_mpi rprime = { }; mbedtls_mpi sprime = { }; mbedtls_mpi t = { }; mbedtls_mpi eprime = { }; mbedtls_mpi R = { }; mbedtls_ecp_point x1y1p = { }; mbedtls_ecp_point PA = { }; int mres = 0; if (sig_len != 64) return TEE_ERROR_BAD_PARAMETERS; mbedtls_mpi_init(&rprime); mbedtls_mpi_init(&sprime); mbedtls_mpi_init(&t); mbedtls_mpi_init(&eprime); mbedtls_mpi_init(&R); mbedtls_ecp_point_init(&x1y1p); mbedtls_ecp_point_init(&PA); mbedtls_ecp_group_init(&grp); mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); if (mres) { res = TEE_ERROR_GENERIC; goto out; } mres = mbedtls_mpi_read_binary(&rprime, sig, 32); if (mres) goto out; mres = mbedtls_mpi_read_binary(&sprime, sig + 32, 32); if (mres) goto out; /* Step B1: verify r' in [1, n - 1] */ if (mbedtls_mpi_cmp_int(&rprime, 1) < 0 || mbedtls_mpi_cmp_mpi(&rprime, &grp.N) >= 0) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } /* Step B2: verify s' in [1, n - 1] */ if (mbedtls_mpi_cmp_int(&sprime, 1) < 0 || mbedtls_mpi_cmp_mpi(&sprime, &grp.N) >= 0) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } /* * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here * because @msg is supposed to contain the hash value e' already. */ /* Step B5: t = (r' + s') mod n and check t != 0 */ mres = mbedtls_mpi_add_mpi(&t, &rprime, &sprime); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&t, &t, &grp.N); if (mres) goto out; if (!mbedtls_mpi_cmp_int(&t, 0)) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } /* Step B6: (x1', y1') = [s']G + [t]PA */ mres = mbedtls_mpi_copy(&PA.X, (mbedtls_mpi *)key->x); if (mres) goto out; mres = mbedtls_mpi_copy(&PA.Y, (mbedtls_mpi *)key->y); if (mres) goto out; mres = mbedtls_mpi_lset(&PA.Z, 1); if (mres) goto out; mres = mbedtls_ecp_muladd(&grp, &x1y1p, &sprime, &grp.G, &t, &PA); if (mres) goto out; /* Step B7: compute R = (e' + x1') mod n and verify R == r' */ mres = mbedtls_mpi_read_binary(&eprime, msg, msg_len); if (mres) goto out; mres = mbedtls_mpi_add_mpi(&R, &eprime, &x1y1p.X); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&R, &R, &grp.N); if (mres) goto out; if (mbedtls_mpi_cmp_mpi(&R, &rprime)) { res = TEE_ERROR_SIGNATURE_INVALID; goto out; } res = TEE_SUCCESS; out: mbedtls_ecp_point_free(&x1y1p); mbedtls_ecp_point_free(&PA); mbedtls_mpi_free(&rprime); mbedtls_mpi_free(&sprime); mbedtls_mpi_free(&t); mbedtls_mpi_free(&eprime); mbedtls_mpi_free(&R); mbedtls_ecp_group_free(&grp); return res; } optee_os-4.3.0/lib/libmbedtls/core/sm2-dsa.h000066400000000000000000000010251464416617300206030ustar00rootroot00000000000000 // SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021 Huawei Technologies Co., Ltd */ #ifndef _SM2_DSA_H_ #include #include #include TEE_Result sm2_mbedtls_dsa_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len); TEE_Result sm2_mbedtls_dsa_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len); #endif /* _SM2_DSA_H_ */ optee_os-4.3.0/lib/libmbedtls/core/sm2-kep.c000066400000000000000000000274111464416617300206150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020-21 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include "mbed_helpers.h" /* SM2 uses 256 bit unsigned integers in big endian format */ #define SM2_INT_SIZE_BYTES 32 /* The public x and y values extracted from a public or private ECC key */ struct key_xy { mbedtls_mpi *x; mbedtls_mpi *y; }; /* * Compute a hash of a user's identity and public key * For user A: ZA = SM3(ENTLA || IDA || a || b || xG || yG || xA || yA) */ static TEE_Result sm2_kep_compute_Z(const mbedtls_ecp_group *grp, uint8_t *Z, size_t Zlen, const uint8_t *id, size_t idlen, struct key_xy *key) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t ENTLEN[2] = { }; uint8_t buf[SM2_INT_SIZE_BYTES] = { }; void *ctx = NULL; int mres = 0; if (Zlen < TEE_SM3_HASH_SIZE) return TEE_ERROR_SHORT_BUFFER; /* * ENTLEN is the length in bits if the user's distinguished identifier * encoded over 16 bits in big endian format. */ ENTLEN[0] = (idlen * 8) >> 8; ENTLEN[1] = idlen * 8; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, ENTLEN, sizeof(ENTLEN)); if (res) goto out; res = crypto_hash_update(ctx, id, idlen); if (res) goto out; mres = mbedtls_mpi_write_binary(&grp->A, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mres = mbedtls_mpi_write_binary(&grp->B, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mres = mbedtls_mpi_write_binary(&grp->G.X, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mres = mbedtls_mpi_write_binary(&grp->G.Y, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mres = mbedtls_mpi_write_binary(key->x, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; mres = mbedtls_mpi_write_binary(key->y, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; res = crypto_hash_final(ctx, Z, TEE_SM3_HASH_SIZE); out: crypto_hash_free_ctx(ctx); return res; } /* * Compute a verification value, to be checked against the value sent by the * peer. * On the initiator's side: * S1 = SM3(0x02 || yU || SM3(xU || ZA || ZB || x1 || y1 || x2 || y2)) * On the responder's side: * S2 = SM3(0x03 || yV || SM3(xV || ZA || ZB || x1 || y1 || x2 || y2)) */ static TEE_Result sm2_kep_compute_S(uint8_t *S, size_t S_len, uint8_t flag, mbedtls_ecp_point *UV, const uint8_t *ZAZB, size_t ZAZB_len, struct key_xy *initiator_eph_key, struct key_xy *responder_eph_key) { uint8_t hash[TEE_SM3_HASH_SIZE] = { }; TEE_Result res = TEE_ERROR_GENERIC; uint8_t buf[SM2_INT_SIZE_BYTES]; void *ctx = NULL; int mres = 0; if (S_len < TEE_SM3_HASH_SIZE) return TEE_ERROR_SHORT_BUFFER; res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; /* Compute the inner hash */ res = crypto_hash_init(ctx); if (res) goto out; /* xU or xV */ mres = mbedtls_mpi_write_binary(&UV->X, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* ZA || ZB */ res = crypto_hash_update(ctx, ZAZB, ZAZB_len); if (res) goto out; /* x1 */ mres = mbedtls_mpi_write_binary(initiator_eph_key->x, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* y1 */ mres = mbedtls_mpi_write_binary(initiator_eph_key->y, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* x2 */ mres = mbedtls_mpi_write_binary(responder_eph_key->x, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* y2 */ mres = mbedtls_mpi_write_binary(responder_eph_key->y, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; res = crypto_hash_final(ctx, hash, sizeof(hash)); if (res) goto out; /* Now compute S */ res = crypto_hash_init(ctx); if (res) goto out; /* 0x02 or 0x03 */ res = crypto_hash_update(ctx, &flag, sizeof(flag)); if (res) goto out; /* yU or yV */ mres = mbedtls_mpi_write_binary(&UV->Y, buf, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_GENERIC; goto out; } res = crypto_hash_update(ctx, buf, sizeof(buf)); if (res) goto out; /* Inner SM3(...) */ res = crypto_hash_update(ctx, hash, sizeof(hash)); if (res) goto out; res = crypto_hash_final(ctx, S, TEE_SM3_HASH_SIZE); out: crypto_hash_free_ctx(ctx); return res; } static void extract_xy_from_keypair(struct key_xy *xy, const struct ecc_keypair *pair) { xy->x = (mbedtls_mpi *)pair->x; xy->y = (mbedtls_mpi *)pair->y; /* Other fields are not used */ } static void extract_xy_from_public_key(struct key_xy *xy, const struct ecc_public_key *from) { xy->x = (mbedtls_mpi *)from->x; xy->y = (mbedtls_mpi *)from->y; } /* * GM/T 0003.1‒2012 Part 3 Section 6.1 * Key exchange protocol */ TEE_Result crypto_acipher_sm2_kep_derive(struct ecc_keypair *my_key, struct ecc_keypair *my_eph_key, struct ecc_public_key *peer_key, struct ecc_public_key *peer_eph_key, struct sm2_kep_parms *p) { /* * Variable names and documented steps reflect the initator side (user A * in the spec), but the other side is quite similar hence only one * function. */ uint8_t xUyUZAZB[2 * SM2_INT_SIZE_BYTES + 2 * TEE_SM3_HASH_SIZE] = { }; struct key_xy initiator_eph_key = { }; struct key_xy responder_eph_key = { }; struct key_xy initiator_key = { }; struct key_xy responder_key = { }; TEE_Result res = TEE_ERROR_BAD_STATE; uint8_t tmp[SM2_INT_SIZE_BYTES] = { }; mbedtls_ecp_group grp = { }; mbedtls_ecp_point PB = { }; mbedtls_ecp_point RB = { }; mbedtls_ecp_point U = { }; mbedtls_mpi x1bar = { }; mbedtls_mpi x2bar = { }; mbedtls_mpi tA = { }; mbedtls_mpi h = { }; mbedtls_mpi htA = { }; mbedtls_mpi one = { }; int mres = 0; if (p->is_initiator) { extract_xy_from_keypair(&initiator_eph_key, my_eph_key); extract_xy_from_public_key(&responder_eph_key, peer_eph_key); extract_xy_from_keypair(&initiator_key, my_key); extract_xy_from_public_key(&responder_key, peer_key); } else { extract_xy_from_public_key(&initiator_eph_key, peer_eph_key); extract_xy_from_keypair(&responder_eph_key, my_eph_key); extract_xy_from_public_key(&initiator_key, peer_key); extract_xy_from_keypair(&responder_key, my_key); } mbedtls_mpi_init(&x1bar); mbedtls_mpi_init(&x2bar); mbedtls_mpi_init(&tA); mbedtls_mpi_init(&h); mbedtls_mpi_init(&htA); mbedtls_mpi_init(&one); mbedtls_ecp_point_init(&PB); mbedtls_ecp_point_init(&RB); mbedtls_ecp_point_init(&U); mbedtls_ecp_group_init(&grp); mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); if (mres) goto out; /* * Steps A1-A3 are supposedly done already (generate ephemeral key, send * it to peer). * Step A4: (x1, y1) = RA; x1bar = 2^w + (x1 & (2^w - 1)) */ mres = mbedtls_mpi_write_binary((mbedtls_mpi *)my_eph_key->x, tmp, SM2_INT_SIZE_BYTES); if (mres) goto out; tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; mres = mbedtls_mpi_read_binary(&x1bar, tmp + SM2_INT_SIZE_BYTES / 2, SM2_INT_SIZE_BYTES / 2); if (mres) goto out; /* Step A5: tA = (dA + x1bar * rA) mod n */ mres = mbedtls_mpi_mul_mpi(&tA, &x1bar, (mbedtls_mpi *)my_eph_key->d); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&tA, &tA, &grp.N); if (mres) goto out; mres = mbedtls_mpi_add_mpi(&tA, &tA, (mbedtls_mpi *)my_key->d); if (mres) goto out; mres = mbedtls_mpi_mod_mpi(&tA, &tA, &grp.N); if (mres) goto out; /* Step A6: verify whether RB verifies the curve equation */ mbedtls_mpi_copy(&RB.X, (mbedtls_mpi *)peer_eph_key->x); mbedtls_mpi_copy(&RB.Y, (mbedtls_mpi *)peer_eph_key->y); mbedtls_mpi_lset(&RB.Z, 1); mres = mbedtls_ecp_check_pubkey(&grp, &RB); if (mres) goto out; /* Step A6 (continued): (x2, y2) = RB; x2bar = 2^w + (x2 & (2^w - 1)) */ mres = mbedtls_mpi_write_binary((mbedtls_mpi *)peer_eph_key->x, tmp, SM2_INT_SIZE_BYTES); if (mres) goto out; tmp[SM2_INT_SIZE_BYTES / 2] |= 0x80; mres = mbedtls_mpi_read_binary(&x2bar, tmp + SM2_INT_SIZE_BYTES / 2, SM2_INT_SIZE_BYTES / 2); if (mres) goto out; /* Step A7: compute U = [h.tA](PB + [x2bar]RB) and check for infinity */ mres = mbedtls_mpi_copy(&PB.X, (mbedtls_mpi *)peer_key->x); if (mres) goto out; mres = mbedtls_mpi_copy(&PB.Y, (mbedtls_mpi *)peer_key->y); if (mres) goto out; mres = mbedtls_mpi_lset(&PB.Z, 1); if (mres) goto out; mres = mbedtls_mpi_lset(&one, 1); if (mres) goto out; mres = mbedtls_ecp_muladd(&grp, &U, &one, &PB, &x2bar, &RB); if (mres) goto out; /* Note: the cofactor for SM2 is 1 so [h.tA] == tA */ mres = mbedtls_ecp_mul(&grp, &U, &tA, &U, mbd_rand, NULL); if (mres) goto out; /* * "Point is zero" is same as "point is at infinity". Returns 1 if * point is zero, < 0 on error and 0 if point is non-zero. */ mres = mbedtls_ecp_is_zero(&U); if (mres) goto out; /* Step A8: compute KA = KDF(xU || yU || ZA || ZB, klen) */ /* xU */ mres = mbedtls_mpi_write_binary(&U.X, xUyUZAZB, SM2_INT_SIZE_BYTES); if (mres) goto out; /* yU */ mres = mbedtls_mpi_write_binary(&U.Y, xUyUZAZB + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (mres) goto out; /* ZA */ res = sm2_kep_compute_Z(&grp, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, TEE_SM3_HASH_SIZE, p->initiator_id, p->initiator_id_len, &initiator_key); if (res) goto out; /* ZB */ res = sm2_kep_compute_Z(&grp, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES + TEE_SM3_HASH_SIZE, TEE_SM3_HASH_SIZE, p->responder_id, p->responder_id_len, &responder_key); if (res) goto out; res = sm2_kdf(xUyUZAZB, sizeof(xUyUZAZB), p->out, p->out_len); if (res) goto out; /* Step A9: compute S1 and check S1 == SB */ if (p->conf_in) { uint8_t S1[TEE_SM3_HASH_SIZE] = { }; uint8_t flag = p->is_initiator ? 0x02 : 0x03; if (p->conf_in_len < TEE_SM3_HASH_SIZE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = sm2_kep_compute_S(S1, sizeof(S1), flag, &U, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, 2 * SM2_INT_SIZE_BYTES, &initiator_eph_key, &responder_eph_key); if (res) goto out; if (consttime_memcmp(S1, p->conf_in, sizeof(S1))) { /* Verification failed */ res = TEE_ERROR_BAD_STATE; goto out; } } /* Step A10: compute SA */ if (p->conf_out) { uint8_t flag = p->is_initiator ? 0x03 : 0x02; if (p->conf_out_len < TEE_SM3_HASH_SIZE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = sm2_kep_compute_S(p->conf_out, TEE_SM3_HASH_SIZE, flag, &U, xUyUZAZB + 2 * SM2_INT_SIZE_BYTES, 2 * SM2_INT_SIZE_BYTES, &initiator_eph_key, &responder_eph_key); } out: mbedtls_mpi_free(&x1bar); mbedtls_mpi_free(&x2bar); mbedtls_mpi_free(&tA); mbedtls_mpi_free(&h); mbedtls_mpi_free(&htA); mbedtls_mpi_free(&one); mbedtls_ecp_point_free(&PB); mbedtls_ecp_point_free(&RB); mbedtls_ecp_point_free(&U); mbedtls_ecp_group_free(&grp); return res; } optee_os-4.3.0/lib/libmbedtls/core/sm2-pke.c000066400000000000000000000241371464416617300206170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019-2021 Huawei Technologies Co., Ltd */ #include #include #include #include #include #include #include #include #include #include #include "mbed_helpers.h" #include "sm2-pke.h" /* SM2 uses 256 bit unsigned integers in big endian format */ #define SM2_INT_SIZE_BYTES 32 static TEE_Result sm2_uncompressed_bytes_to_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *p, const uint8_t *x1y1, size_t max_size, size_t *consumed) { uint8_t *ptr = (uint8_t *)x1y1; int mres = 0; if (max_size < (size_t)(2 * SM2_INT_SIZE_BYTES)) return TEE_ERROR_BAD_PARAMETERS; mres = mbedtls_mpi_read_binary(&p->X, ptr, SM2_INT_SIZE_BYTES); if (mres) return TEE_ERROR_BAD_PARAMETERS; ptr += SM2_INT_SIZE_BYTES; mres = mbedtls_mpi_read_binary(&p->Y, ptr, SM2_INT_SIZE_BYTES); if (mres) return TEE_ERROR_BAD_PARAMETERS; mres = mbedtls_mpi_lset(&p->Z, 1); if (mres) return TEE_ERROR_BAD_PARAMETERS; mres = mbedtls_ecp_check_pubkey(grp, p); if (mres) return TEE_ERROR_BAD_PARAMETERS; *consumed = 2 * SM2_INT_SIZE_BYTES + 1; /* PC */ return TEE_SUCCESS; } /* * GM/T 0003.1‒2012 Part 1 Section 4.2.9 * Conversion of a byte string @buf to a point @p. Makes sure @p is on the curve * defined by domain parameters @dp. * Note: only the uncompressed form is supported. Uncompressed and hybrid forms * are TBD. */ static TEE_Result sm2_bytes_to_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *p, const uint8_t *buf, size_t max_size, size_t *consumed) { uint8_t PC = 0; if (!max_size) return TEE_ERROR_BAD_PARAMETERS; PC = buf[0]; switch (PC) { case 0x02: case 0x03: /* Compressed form */ return TEE_ERROR_NOT_SUPPORTED; case 0x04: /* Uncompressed form */ return sm2_uncompressed_bytes_to_point(grp, p, buf + 1, max_size - 1, consumed); case 0x06: case 0x07: /* Hybrid form */ return TEE_ERROR_NOT_SUPPORTED; default: return TEE_ERROR_BAD_PARAMETERS; } return TEE_ERROR_GENERIC; } static bool is_zero(const uint8_t *buf, size_t size) { uint8_t v = 0; size_t i = 0; for (i = 0; i < size; i++) v |= buf[i]; return !v; } /* * GM/T 0003.1‒2012 Part 4 Section 7.1 * Decryption algorithm */ TEE_Result sm2_mbedtls_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; uint8_t x2y2[64] = { }; mbedtls_ecp_point C1 = { }; size_t C1_len = 0; mbedtls_ecp_point x2y2p = { }; mbedtls_ecp_group grp = { }; void *ctx = NULL; int mres = 0; uint8_t *t = NULL; size_t C2_len = 0; size_t i = 0; size_t out_len = 0; uint8_t *eom = NULL; uint8_t u[TEE_SM3_HASH_SIZE] = { }; /* * Input buffer src is (C1 || C2 || C3) * - C1 represents a point (should be on the curve) * - C2 is the encrypted message * - C3 is a SM3 hash */ mbedtls_ecp_point_init(&C1); mbedtls_ecp_point_init(&x2y2p); mbedtls_ecp_group_init(&grp); mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); if (mres) { res = TEE_ERROR_GENERIC; goto out; } /* Step B1: read and validate point C1 from encrypted message */ res = sm2_bytes_to_point(&grp, &C1, src, src_len, &C1_len); if (res) goto out; /* * Step B2: S = [h]C1, the cofactor h is 1 for SM2 so S == C1. * The fact that S is on the curve has already been checked in * sm2_bytes_to_point(). */ /* Step B3: (x2, y2) = [dB]C1 */ mres = mbedtls_ecp_mul(&grp, &x2y2p, (mbedtls_mpi *)key->d, &C1, mbd_rand, NULL); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } if (mbedtls_mpi_size(&x2y2p.X) > SM2_INT_SIZE_BYTES || mbedtls_mpi_size(&x2y2p.Y) > SM2_INT_SIZE_BYTES) { res = TEE_ERROR_BAD_STATE; goto out; } mres = mbedtls_mpi_write_binary(&x2y2p.X, x2y2, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } mres = mbedtls_mpi_write_binary(&x2y2p.Y, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step B4: t = KDF(x2 || y2, klen) */ /* C = C1 || C2 || C3 */ if (src_len <= C1_len + TEE_SM3_HASH_SIZE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } C2_len = src_len - C1_len - TEE_SM3_HASH_SIZE; t = calloc(1, C2_len); if (!t) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = sm2_kdf(x2y2, sizeof(x2y2), t, C2_len); if (res) goto out; if (is_zero(t, C2_len)) { res = TEE_ERROR_CIPHERTEXT_INVALID; goto out; } /* Step B5: get C2 from C and compute Mprime = C2 (+) t */ out_len = MIN(*dst_len, C2_len); for (i = 0; i < out_len; i++) dst[i] = src[C1_len + i] ^ t[i]; *dst_len = out_len; if (out_len < C2_len) { eom = calloc(1, C2_len - out_len); if (!eom) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } for (i = out_len; i < C2_len; i++) eom[i - out_len] = src[C1_len + i] ^ t[i]; } /* Step B6: compute u = Hash(x2 || M' || y2) and compare with C3 */ res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_update(ctx, dst, out_len); if (res) goto out; if (out_len < C2_len) { res = crypto_hash_update(ctx, eom, C2_len - out_len); if (res) goto out; } res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_final(ctx, u, sizeof(u)); if (res) goto out; if (consttime_memcmp(u, src + C1_len + C2_len, TEE_SM3_HASH_SIZE)) { res = TEE_ERROR_CIPHERTEXT_INVALID; goto out; } out: free(eom); free(t); crypto_hash_free_ctx(ctx); mbedtls_ecp_point_free(&C1); mbedtls_ecp_point_free(&x2y2p); mbedtls_ecp_group_free(&grp); return res; } /* * GM/T 0003.1‒2012 Part 1 Section 4.2.8 * Conversion of point @p to a byte string @buf (uncompressed form). */ static TEE_Result sm2_point_to_bytes(uint8_t *buf, size_t *size, const mbedtls_ecp_point *p) { size_t xsize = mbedtls_mpi_size(&p->X); size_t ysize = mbedtls_mpi_size(&p->Y); size_t sz = 2 * SM2_INT_SIZE_BYTES + 1; int mres = 0; if (xsize > SM2_INT_SIZE_BYTES || ysize > SM2_INT_SIZE_BYTES || *size < sz) return TEE_ERROR_BAD_STATE; memset(buf, 0, sz); buf[0] = 0x04; /* Uncompressed form indicator */ mres = mbedtls_mpi_write_binary(&p->X, buf + 1, SM2_INT_SIZE_BYTES); if (mres) return TEE_ERROR_BAD_STATE; mres = mbedtls_mpi_write_binary(&p->Y, buf + 1 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (mres) return TEE_ERROR_BAD_STATE; *size = sz; return TEE_SUCCESS; } /* * GM/T 0003.1‒2012 Part 4 Section 6.1 * Encryption algorithm */ TEE_Result sm2_mbedtls_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len) { TEE_Result res = TEE_SUCCESS; mbedtls_ecp_group grp = { }; mbedtls_ecp_point x2y2p = { }; mbedtls_ecp_point PB = { }; mbedtls_ecp_point C1 = { }; uint8_t x2y2[64] = { }; uint8_t *t = NULL; int mres = 0; mbedtls_mpi k = { }; size_t C1_len = 0; void *ctx = NULL; size_t i = 0; mbedtls_mpi_init(&k); mbedtls_ecp_point_init(&x2y2p); mbedtls_ecp_point_init(&PB); mbedtls_ecp_point_init(&C1); mbedtls_ecp_group_init(&grp); mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2); if (mres) { res = TEE_ERROR_GENERIC; goto out; } /* Step A1: generate random number 1 <= k < n */ res = mbed_gen_random_upto(&k, &grp.N); if (res) goto out; /* Step A2: compute C1 = [k]G */ mres = mbedtls_ecp_mul(&grp, &C1, &k, &grp.G, mbd_rand, NULL); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } /* * Step A3: compute S = [h]PB and check for infinity. * The cofactor h is 1 for SM2 so S == PB, nothing to do. */ /* Step A4: compute (x2, y2) = [k]PB */ mbedtls_mpi_copy(&PB.X, (mbedtls_mpi *)key->x); mbedtls_mpi_copy(&PB.Y, (mbedtls_mpi *)key->y); mbedtls_mpi_lset(&PB.Z, 1); mres = mbedtls_ecp_mul(&grp, &x2y2p, &k, &PB, mbd_rand, NULL); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } if (mbedtls_mpi_size(&x2y2p.X) > SM2_INT_SIZE_BYTES || mbedtls_mpi_size(&x2y2p.Y) > SM2_INT_SIZE_BYTES) { res = TEE_ERROR_BAD_STATE; goto out; } mres = mbedtls_mpi_write_binary(&x2y2p.X, x2y2, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } mres = mbedtls_mpi_write_binary(&x2y2p.Y, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (mres) { res = TEE_ERROR_BAD_STATE; goto out; } /* Step A5: compute t = KDF(x2 || y2, klen) */ t = calloc(1, src_len); if (!t) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = sm2_kdf(x2y2, sizeof(x2y2), t, src_len); if (res) goto out; if (is_zero(t, src_len)) { res = TEE_ERROR_CIPHERTEXT_INVALID; goto out; } /* * Steps A6, A7, A8: * Compute C2 = M (+) t * Compute C3 = Hash(x2 || M || y2) * Output C = C1 || C2 || C3 */ /* C1 */ C1_len = *dst_len; res = sm2_point_to_bytes(dst, &C1_len, &C1); if (res) goto out; if (*dst_len < C1_len + src_len + TEE_SM3_HASH_SIZE) { *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; res = TEE_ERROR_SHORT_BUFFER; goto out; } /* C2 */ for (i = 0; i < src_len; i++) dst[i + C1_len] = src[i] ^ t[i]; /* C3 */ res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SM3); if (res) goto out; res = crypto_hash_init(ctx); if (res) goto out; res = crypto_hash_update(ctx, x2y2, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_update(ctx, src, src_len); if (res) goto out; res = crypto_hash_update(ctx, x2y2 + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES); if (res) goto out; res = crypto_hash_final(ctx, dst + C1_len + src_len, TEE_SM3_HASH_SIZE); if (res) goto out; *dst_len = C1_len + src_len + TEE_SM3_HASH_SIZE; out: crypto_hash_free_ctx(ctx); free(t); mbedtls_ecp_point_free(&x2y2p); mbedtls_ecp_point_free(&PB); mbedtls_ecp_point_free(&C1); mbedtls_ecp_group_free(&grp); mbedtls_mpi_free(&k); return res; } optee_os-4.3.0/lib/libmbedtls/core/sm2-pke.h000066400000000000000000000007751464416617300206260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021 Huawei Technologies Co., Ltd */ #ifndef _SM2_PKE_H_ #include #include #include TEE_Result sm2_mbedtls_pke_encrypt(struct ecc_public_key *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); TEE_Result sm2_mbedtls_pke_decrypt(struct ecc_keypair *key, const uint8_t *src, size_t src_len, uint8_t *dst, size_t *dst_len); #endif /* _SM2_PKE_H_ */ optee_os-4.3.0/lib/libmbedtls/core/sub.mk000066400000000000000000000017561464416617300203210ustar00rootroot00000000000000cppflags-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS srcs-y += mbed_helpers.c srcs-y += tomcrypt.c srcs-$(call cfg-one-enabled, CFG_CRYPTO_MD5 CFG_CRYPTO_SHA1 CFG_CRYPTO_SHA224 \ CFG_CRYPTO_SHA256 CFG_CRYPTO_SHA384 \ CFG_CRYPTO_SHA512) += hash.c ifeq ($(CFG_CRYPTO_AES),y) srcs-y += aes.c srcs-$(CFG_CRYPTO_ECB) += aes_ecb.c srcs-$(CFG_CRYPTO_CBC) += aes_cbc.c srcs-$(CFG_CRYPTO_CTR) += aes_ctr.c endif ifeq ($(CFG_CRYPTO_DES),y) srcs-$(CFG_CRYPTO_ECB) += des_ecb.c srcs-$(CFG_CRYPTO_ECB) += des3_ecb.c srcs-$(CFG_CRYPTO_CBC) += des_cbc.c srcs-$(CFG_CRYPTO_CBC) += des3_cbc.c endif srcs-$(CFG_CRYPTO_HMAC) += hmac.c srcs-$(CFG_CRYPTO_CMAC) += cmac.c ifneq ($(CFG_CRYPTO_DSA),y) srcs-$(call cfg-one-enabled, CFG_CRYPTO_RSA CFG_CRYPTO_DH \ CFG_CRYPTO_ECC) += bignum.c endif srcs-$(CFG_CRYPTO_RSA) += rsa.c srcs-$(CFG_CRYPTO_DH) += dh.c srcs-$(CFG_CRYPTO_ECC) += ecc.c srcs-$(CFG_CRYPTO_SM2_DSA) += sm2-dsa.c srcs-$(CFG_CRYPTO_SM2_KEP) += sm2-kep.c srcs-$(CFG_CRYPTO_SM2_PKE) += sm2-pke.c optee_os-4.3.0/lib/libmbedtls/core/tomcrypt.c000066400000000000000000000003721464416617300212150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2018, ARM Limited * Copyright (C) 2019, Linaro Limited */ #include #include TEE_Result crypto_init(void) { tomcrypt_init(); return TEE_SUCCESS; } optee_os-4.3.0/lib/libmbedtls/include/000077500000000000000000000000001464416617300176615ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/include/aes_alt.h000066400000000000000000000004311464416617300214400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2020, Linaro Limited */ #ifndef __MBEDTLS_AES_ALT_H #define __MBEDTLS_AES_ALT_H typedef struct mbedtls_aes_context { uint32_t key[60]; unsigned int round_count; } mbedtls_aes_context; #endif /*__MBEDTLS_AES_ALT_H*/ optee_os-4.3.0/lib/libmbedtls/include/mbedtls_config_kernel.h000066400000000000000000000060311464416617300243510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ #ifndef __MBEDTLS_CONFIG_KERNEL_H #define __MBEDTLS_CONFIG_KERNEL_H #ifdef ARM32 #define MBEDTLS_HAVE_INT32 #endif #ifdef ARM64 #define MBEDTLS_HAVE_INT64 #endif #define MBEDTLS_BIGNUM_C #define MBEDTLS_GENPRIME /* Test if Mbedtls is the primary crypto lib */ #ifdef CFG_CRYPTOLIB_NAME_mbedtls #if defined(CFG_CRYPTO_MD5) #define MBEDTLS_MD5_C #define MBEDTLS_MD_C #endif #if defined(CFG_CRYPTO_SHA1) #define MBEDTLS_SHA1_C #define MBEDTLS_MD_C #if defined(CFG_CORE_CRYPTO_SHA1_ACCEL) #define MBEDTLS_SHA1_PROCESS_ALT #endif #endif #if defined(CFG_CRYPTO_SHA224) || defined(CFG_CRYPTO_SHA256) #if defined(CFG_CRYPTO_SHA224) #define MBEDTLS_SHA224_C #endif #if defined(CFG_CRYPTO_SHA256) #define MBEDTLS_SHA256_C #endif #define MBEDTLS_MD_C #if defined(CFG_CORE_CRYPTO_SHA256_ACCEL) #define MBEDTLS_SHA256_PROCESS_ALT #endif #endif #if defined(CFG_CRYPTO_SHA384) || defined(CFG_CRYPTO_SHA512) #if defined(CFG_CRYPTO_SHA384) #define MBEDTLS_SHA384_C #endif #if defined(CFG_CRYPTO_SHA512) #define MBEDTLS_SHA512_C #endif #define MBEDTLS_MD_C #if defined(CFG_CORE_CRYPTO_SHA512_ACCEL) #define MBEDTLS_SHA512_PROCESS_ALT #endif #endif #if defined(CFG_CRYPTO_HMAC) #define MBEDTLS_MD_C #endif #if defined(CFG_CRYPTO_AES) #define MBEDTLS_AES_C #define MBEDTLS_AES_ROM_TABLES #if defined(CFG_CORE_CRYPTO_AES_ACCEL) #define MBEDTLS_AES_ALT #endif #endif #if defined(CFG_CRYPTO_DES) #define MBEDTLS_DES_C #endif #if defined(CFG_CRYPTO_CBC) #define MBEDTLS_CIPHER_MODE_CBC #endif #if defined(CFG_CRYPTO_CTR) #define MBEDTLS_CIPHER_MODE_CTR #endif #if defined(CFG_CRYPTO_CMAC) #define MBEDTLS_CMAC_C #define MBEDTLS_CIPHER_C #endif #if defined(CFG_CRYPTO_RSA) || defined(CFG_CRYPTO_DH) || defined(CFG_CRYPTO_ECC) #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V15 #define MBEDTLS_PKCS1_V21 #define MBEDTLS_PK_C #define MBEDTLS_GENPRIME #define MBEDTLS_CTR_DRBG_C #endif #if defined(CFG_CRYPTO_RSA) #define MBEDTLS_RSA_C #define MBEDTLS_RSA_GEN_KEY_MIN_BITS 128 #endif #if defined(CFG_CRYPTO_RSA) || defined(CFG_CRYPTO_ECC) #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif #if defined(CFG_CRYPTO_DH) #define MBEDTLS_DHM_C #endif #if defined(CFG_CRYPTO_ECC) #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_DP_SECP384R1_ENABLED #define MBEDTLS_ECP_DP_SECP521R1_ENABLED #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #define MBEDTLS_ECP_DP_SECP224K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_BP256R1_ENABLED #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_CURVE25519_ENABLED #define MBEDTLS_ECP_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECDH_C #define MBEDTLS_ECDH_LEGACY_CONTEXT #if defined(CFG_CRYPTO_DSA) || defined(CFG_CRYPTO_SM2_PKE) || \ defined(CFG_CRYPTO_SM2_KEP) #define MBEDTLS_ECP_DP_SM2_ENABLED #endif #endif #endif /*CFG_CRYPTOLIB_NAME_mbedtls*/ #endif /* __MBEDTLS_CONFIG_KERNEL_H */ optee_os-4.3.0/lib/libmbedtls/include/mbedtls_config_uta.h000066400000000000000000000034251464416617300236660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ #ifndef __MBEDTLS_CONFIG_UTA_H #define __MBEDTLS_CONFIG_UTA_H /* * When wrapping using TEE_BigInt to represent a mbedtls_mpi we can only * use 32-bit arithmetics. */ #define MBEDTLS_HAVE_INT32 #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_PKCS1_V15 #define MBEDTLS_CIPHER_C #define MBEDTLS_DES_C #define MBEDTLS_AES_C #define MBEDTLS_NIST_KW_C #define MBEDTLS_POLY1305_C #define MBEDTLS_CHACHA20_C #define MBEDTLS_CHACHAPOLY_C #define MBEDTLS_SHA1_C #define MBEDTLS_SHA256_C #define MBEDTLS_MD_C #define MBEDTLS_MD5_C #define MBEDTLS_CTR_DRBG_C #define MBEDTLS_ENTROPY_C #define MBEDTLS_NO_PLATFORM_ENTROPY #define MBEDTLS_BIGNUM_C #define MBEDTLS_GENPRIME #define MBEDTLS_RSA_C #define MBEDTLS_ECDH_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_DP_SECP384R1_ENABLED #define MBEDTLS_ECP_DP_SECP521R1_ENABLED #define MBEDTLS_ECP_DP_BP256R1_ENABLED #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #define MBEDTLS_ECP_DP_SECP224K1_ENABLED #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_PK_C #define MBEDTLS_PK_PARSE_C #define MBEDTLS_PK_WRITE_C #define MBEDTLS_OID_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #define MBEDTLS_X509_CRT_PARSE_C #define MBEDTLS_X509_CRT_WRITE_C #define MBEDTLS_X509_CSR_PARSE_C #define MBEDTLS_X509_CSR_WRITE_C #define MBEDTLS_X509_CREATE_C #define MBEDTLS_X509_CHECK_KEY_USAGE #define MBEDTLS_X509_USE_C #define MBEDTLS_BASE64_C #define MBEDTLS_CERTS_C #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_PEM_WRITE_C #endif /* __MBEDTLS_CONFIG_UTA_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/000077500000000000000000000000001464416617300176705ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/mbedtls/.uncrustify.cfg000066400000000000000000000143421464416617300226460ustar00rootroot00000000000000# Configuration options for Uncrustify specifying the Mbed TLS code style. # # Note: The code style represented by this file has not yet been introduced # to Mbed TLS. # # Copyright The Mbed TLS Contributors # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later # Wrap lines at 100 characters code_width = 100 # Allow splitting long for statements between the condition statements ls_for_split_full = true # Allow splitting function calls between arguments ls_func_split_full = true input_tab_size = 4 # Spaces-only indentation indent_with_tabs = 0 indent_columns = 4 # Indent 'case' 1 level from 'switch' indent_switch_case = indent_columns # Line-up strings broken by '\' indent_align_string = true # Braces on the same line (Egyptian-style braces) nl_enum_brace = remove nl_union_brace = remove nl_struct_brace = remove nl_do_brace = remove nl_if_brace = remove nl_for_brace = remove nl_else_brace = remove nl_while_brace = remove nl_switch_brace = remove # Braces on same line as keywords that follow them - 'else' and the 'while' in 'do {} while ()'; nl_brace_else = remove nl_brace_while = remove # Space before else on the same line sp_brace_else = add # If else is on the same line as '{', force exactly 1 space between them sp_else_brace = force # Functions are the exception and have braces on the next line nl_fcall_brace = add nl_fdef_brace = add # Force exactly one space between ')' and '{' in statements sp_sparen_brace = force # At least 1 space around assignment sp_assign = add # Remove spaces around the preprocessor '##' token-concatenate sp_pp_concat = ignore # At least 1 space around '||' and '&&' sp_bool = add # But no space after the '!' operator sp_not = remove # No space after the bitwise-not '~' operator sp_inv = remove # No space after the addressof '&' operator sp_addr = remove # No space around the member '.' and '->' operators sp_member = remove # No space after the dereference '*' operator sp_deref = remove # No space after a unary negation '-' sp_sign = remove # No space between the '++'/'--' operator and its operand sp_incdec = remove # At least 1 space around comparison operators sp_compare = add # Remove spaces inside all kinds of parentheses: # Remove spaces inside parentheses sp_inside_paren = remove # No spaces inside statement parentheses sp_inside_sparen = remove # No spaces inside cast parentheses '( char )x' -> '(char)x' sp_inside_paren_cast = remove # No spaces inside function parentheses sp_inside_fparen = remove # (The case where the function has no parameters/arguments) sp_inside_fparens = remove # No spaces inside the first parentheses in a function type sp_inside_tparen = remove # (Uncrustify >= 0.74.0) No spaces inside parens in for statements sp_inside_for = remove # Remove spaces between nested parentheses '( (' -> '((' sp_paren_paren = remove # (Uncrustify >= 0.74.0) sp_sparen_paren = remove # Remove spaces between ')' and adjacent '(' sp_cparen_oparen = remove # (Uncrustify >= 0.73.0) space between 'do' and '{' sp_do_brace_open = force # (Uncrustify >= 0.73.0) space between '}' and 'while' sp_brace_close_while = force # At least 1 space before a '*' pointer star sp_before_ptr_star = add # Remove spaces between pointer stars sp_between_ptr_star = remove # No space after a pointer star sp_after_ptr_star = remove # But allow a space in the case of e.g. char * const x; sp_after_ptr_star_qualifier = ignore # Remove space after star in a function return type sp_after_ptr_star_func = remove # At least 1 space after a type in variable definition etc sp_after_type = add # Force exactly 1 space between a statement keyword (e.g. 'if') and an opening parenthesis sp_before_sparen = force # Remove a space before a ';' sp_before_semi = remove # (Uncrustify >= 0.73.0) Remove space before a semi in a non-empty for sp_before_semi_for = remove # (Uncrustify >= 0.73.0) Remove space in empty first statement of a for sp_before_semi_for_empty = remove # (Uncrustify >= 0.74.0) Remove space in empty middle statement of a for sp_between_semi_for_empty = remove # Add a space after a ';' (unless a comment follows) sp_after_semi = add # (Uncrustify >= 0.73.0) Add a space after a semi in non-empty for statements sp_after_semi_for = add # (Uncrustify >= 0.73.0) No space after final semi in empty for statements sp_after_semi_for_empty = remove # Remove spaces on the inside of square brackets '[]' sp_inside_square = remove # Must have at least 1 space after a comma sp_after_comma = add # Must not have a space before a comma sp_before_comma = remove # No space before the ':' in a case statement sp_before_case_colon = remove # Must have space after a cast - '(char)x' -> '(char) x' sp_after_cast = add # No space between 'sizeof' and '(' sp_sizeof_paren = remove # At least 1 space inside '{ }' sp_inside_braces = add # At least 1 space inside '{ }' in an enum sp_inside_braces_enum = add # At least 1 space inside '{ }' in a struct sp_inside_braces_struct = add # At least 1 space between a function return type and the function name sp_type_func = add # No space between a function name and its arguments/parameters sp_func_proto_paren = remove sp_func_def_paren = remove sp_func_call_paren = remove # No space between '__attribute__' and '(' sp_attribute_paren = remove # No space between 'defined' and '(' in preprocessor conditions sp_defined_paren = remove # At least 1 space between a macro's name and its definition sp_macro = add sp_macro_func = add # Force exactly 1 space between a '}' and the name of a typedef if on the same line sp_brace_typedef = force # At least 1 space before a '\' line continuation sp_before_nl_cont = add # At least 1 space around '?' and ':' in ternary statements sp_cond_colon = add sp_cond_question = add # Space between #else/#endif and comment afterwards sp_endif_cmt = add # Remove newlines at the start of a file nl_start_of_file = remove # At least 1 newline at the end of a file nl_end_of_file = add nl_end_of_file_min = 1 # Add braces in single-line statements mod_full_brace_do = add mod_full_brace_for = add mod_full_brace_if = add mod_full_brace_while = add # Remove parentheses from return statements mod_paren_on_return = remove # Disable removal of leading spaces in a multi-line comment if the first and # last lines are the same length cmt_multi_check_last = false optee_os-4.3.0/lib/libmbedtls/mbedtls/BUGS.md000066400000000000000000000016361464416617300207600ustar00rootroot00000000000000## Known issues Known issues in Mbed TLS are [tracked on GitHub](https://github.com/Mbed-TLS/mbedtls/issues). ## Reporting a bug If you think you've found a bug in Mbed TLS, please follow these steps: 1. Make sure you're using the latest version of a [maintained branch](BRANCHES.md): `main`, `development`, or a long-time support branch. 2. Check [GitHub](https://github.com/Mbed-TLS/mbedtls/issues) to see if your issue has already been reported. If not, … 3. If the issue is a security risk (for example: buffer overflow, data leak), please report it confidentially as described in [`SECURITY.md`](SECURITY.md). If not, … 4. Please [create an issue on on GitHub](https://github.com/Mbed-TLS/mbedtls/issues). Please do not use GitHub for support questions. If you want to know how to do something with Mbed TLS, please see [`SUPPORT.md`](SUPPORT.md) for available documentation and support channels. optee_os-4.3.0/lib/libmbedtls/mbedtls/CONTRIBUTING.md000066400000000000000000000226341464416617300221300ustar00rootroot00000000000000Contributing ============ We gratefully accept bug reports and contributions from the community. All PRs are reviewed by the project team / community, and may need some modifications to be accepted. Quick Checklist for PR contributors ----------------------------------- More details on all of these points may be found in the sections below. - [Sign-off](#license-and-copyright): all commits must be signed off. - [Tests](#tests): please ensure the PR includes adequate tests. - [Changelog](#documentation): if needed, please provide a changelog entry. - [Backports](#long-term-support-branches): provide a backport if needed (it's fine to wait until the main PR is accepted). Coding Standards ---------------- - Contributions should include tests, as mentioned in the [Tests](#tests) and [Continuous Integration](#continuous-integration-tests) sections. Please check that your contribution passes basic tests before submission, and check the CI results after making a pull request. - The code should be written in a clean and readable style, and must follow [our coding standards](https://mbed-tls.readthedocs.io/en/latest/kb/development/mbedtls-coding-standards/). - The code should be written in a portable generic way, that will benefit the whole community, and not only your own needs. - The code should be secure, and will be reviewed from a security point of view as well. Making a Contribution --------------------- 1. [Check for open issues](https://github.com/Mbed-TLS/mbedtls/issues) or [start a discussion](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org) around a feature idea or a bug. 1. Fork the [Mbed TLS repository on GitHub](https://github.com/Mbed-TLS/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/Mbed-TLS/mbedtls/tree/development) as a basis. 1. Write a test which shows that the bug was fixed or that the feature works as expected. 1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. See our [review process guidelines](https://mbed-tls.readthedocs.io/en/latest/reviews/review-for-contributors/). 1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it. Backwards Compatibility ----------------------- The project aims to minimise the impact on users upgrading to newer versions of the library and it should not be necessary for a user to make any changes to their own code to work with a newer version of the library. Unless the user has made an active decision to use newer features, a newer generation of the library or a change has been necessary due to a security issue or other significant software defect, no modifications to their own code should be necessary. To achieve this, API compatibility is maintained between different versions of Mbed TLS on the main development branch and in LTS (Long Term Support) branches, as described in [BRANCHES.md](BRANCHES.md). To minimise such disruption to users, where a change to the interface is required, all changes to the ABI or API, even on the main development branch where new features are added, need to be justifiable by either being a significant enhancement, new feature or bug fix which is best resolved by an interface change. If there is an API change, the contribution, if accepted, will be merged only when there is a major release. No changes are permitted to the definition of functions in the public interface which will change the API. Instead the interface can only be changed by its extension. Where changes to an existing interface are necessary, functions in the public interface which need to be changed are marked as 'deprecated'. If there is a strong reason to replace an existing function with one that has a slightly different interface (different prototype, or different documented behavior), create a new function with a new name with the desired interface. Keep the old function, but mark it as deprecated. Periodically, the library will remove deprecated functions from the library which will be a breaking change in the API, but such changes will be made only in a planned, structured way that gives sufficient notice to users of the library. Long Term Support Branches -------------------------- Mbed TLS maintains several LTS (Long Term Support) branches, which are maintained continuously for a given period. The LTS branches are provided to allow users of the library to have a maintained, stable version of the library which contains only security fixes and fixes for other defects, without encountering additional features or API extensions which may introduce issues or change the code size or RAM usage, which can be significant considerations on some platforms. To allow users to take advantage of the LTS branches, these branches maintain backwards compatibility for both the public API and ABI. When backporting to these branches please observe the following rules: 1. Any change to the library which changes the API or ABI cannot be backported. 1. All bug fixes that correct a defect that is also present in an LTS branch must be backported to that LTS branch. If a bug fix introduces a change to the API such as a new function, the fix should be reworked to avoid the API change. API changes without very strong justification are unlikely to be accepted. 1. If a contribution is a new feature or enhancement, no backporting is required. Exceptions to this may be additional test cases or quality improvements such as changes to build or test scripts. It would be highly appreciated if contributions are backported to LTS branches in addition to the [development branch](https://github.com/Mbed-TLS/mbedtls/tree/development) by contributors. The list of maintained branches can be found in the [Current Branches section of BRANCHES.md](BRANCHES.md#current-branches). Tests ----- As mentioned, tests that show the correctness of the feature or bug fix should be added to the pull request, if no such tests exist. Mbed TLS includes a comprehensive set of test suites in the `tests/` directory that are dynamically generated to produce the actual test source files (e.g. `test_suite_rsa.c`). These files are generated from a `function file` (e.g. `suites/test_suite_rsa.function`) and a `data file` (e.g. `suites/test_suite_rsa.data`). The function file contains the test functions. The data file contains the test cases, specified as parameters that will be passed to the test function. [A Knowledge Base article describing how to add additional tests is available on the Mbed TLS website](https://mbed-tls.readthedocs.io/en/latest/kb/development/test_suites/). A test script `tests/scripts/basic-build-test.sh` is available to show test coverage of the library. New code contributions should provide a similar level of code coverage to that which already exists for the library. Sample applications, if needed, should be modified as well. Continuous Integration Tests ---------------------------- Once a PR has been made, the Continuous Integration (CI) tests are triggered and run. You should follow the result of the CI tests, and fix failures. It is advised to enable the [githooks scripts](https://github.com/Mbed-TLS/mbedtls/tree/development/tests/git-scripts) prior to pushing your changes, for catching some of the issues as early as possible. Documentation ------------- Mbed TLS is well documented, but if you think documentation is needed, speak out! 1. All interfaces should be documented through Doxygen. New APIs should introduce Doxygen documentation. 1. Complex parts in the code should include comments. 1. If needed, a Readme file is advised. 1. If a [Knowledge Base (KB)](https://mbed-tls.readthedocs.io/en/latest/kb/) article should be added, write this as a comment in the PR description. 1. A [ChangeLog](https://github.com/Mbed-TLS/mbedtls/blob/development/ChangeLog.d/00README.md) entry should be added for this contribution. License and Copyright --------------------- Unless specifically indicated otherwise in a file, Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. See the [LICENSE](LICENSE) file for the full text of these licenses. This means that users may choose which of these licenses they take the code under. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. All new files should include the standard SPDX license identifier where possible, i.e. "SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later". The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors". When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and is submitted under both the Apache-2.0 AND GPL-2.0-or-later licenses. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line. optee_os-4.3.0/lib/libmbedtls/mbedtls/ChangeLog000066400000000000000000012207571464416617300214600ustar00rootroot00000000000000Mbed TLS ChangeLog (Sorted per branch, date) = Mbed TLS 3.6.0 branch released 2024-03-28 API changes * Remove `tls13_` in mbedtls_ssl_tls13_conf_early_data() and mbedtls_ssl_tls13_conf_max_early_data_size() API names. Early data feature may not be TLS 1.3 specific in the future. Fixes #6909. Default behavior changes * psa_import_key() now only accepts RSA keys in the PSA standard formats. The undocumented ability to import other formats (PKCS#8, SubjectPublicKey, PEM) accepted by the pkparse module has been removed. Applications that need these formats can call mbedtls_pk_parse_{public,}key() followed by mbedtls_pk_import_into_psa(). Requirement changes * Drop support for Visual Studio 2013 and 2015, and Arm Compiler 5. New deprecations * Rename the MBEDTLS_SHA256_USE_A64_CRYPTO_xxx config options to MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_xxx. The old names may still be used, but are deprecated. * In the PSA API, domain parameters are no longer used for anything. They are deprecated and will be removed in a future version of the library. * mbedtls_ecp_write_key() is deprecated in favor of mbedtls_ecp_write_key_ext(). Removals * In the PSA API, the experimental way to encode the public exponent of an RSA key as a domain parameter is no longer supported. Use psa_generate_key_ext() instead. * Temporary function mbedtls_pk_wrap_as_opaque() is removed. To mimic the same behavior mbedtls_pk_get_psa_attributes() and mbedtls_pk_import_into_psa() can be used to import a PK key into PSA, while mbedtls_pk_setup_opaque() can be used to wrap a PSA key into a opaque PK context. Features * Added an example program showing how to hash with the PSA API. * Support Armv8-A Crypto Extension acceleration for SHA-256 when compiling for Thumb (T32) or 32-bit Arm (A32). * AES-NI is now supported in Windows builds with clang and clang-cl. Resolves #8372. * Add new mbedtls_x509_csr_parse_der_with_ext_cb() routine which allows parsing unsupported certificate extensions via user provided callback. * Enable the new option MBEDTLS_BLOCK_CIPHER_NO_DECRYPT to omit the decryption direction of block ciphers (AES, ARIA, Camellia). This affects both the low-level modules and the high-level APIs (the cipher and PSA interfaces). This option is incompatible with modes that use the decryption direction (ECB in PSA, CBC, XTS, KW) and with DES. * Support use of Armv8-A Cryptographic Extensions for hardware acclerated AES when compiling for Thumb (T32) or 32-bit Arm (A32). * If a cipher or AEAD mechanism has a PSA driver, you can now build the library without the corresponding built-in implementation. Generally speaking that requires both the key type and algorithm to be accelerated or they'll both be built in. However, for CCM and GCM the built-in implementation is able to take advantage of a driver that only accelerates the key type (that is, the block cipher primitive). See docs/driver-only-builds.md for full details and current limitations. * The CTR_DRBG module will now use AES from a PSA driver if MBEDTLS_AES_C is disabled. This requires PSA_WANT_ALG_ECB_NO_PADDING in addition to MBEDTLS_PSA_CRYPTO_C and PSA_WANT_KEY_TYPE_AES. * Fewer modules depend on MBEDTLS_CIPHER_C, making it possible to save code size by disabling it in more circumstances. In particular, the CCM and GCM modules no longer depend on MBEDTLS_CIPHER_C. Also, MBEDTLS_PSA_CRYPTO can now be enabled without MBEDTLS_CIPHER_C if all unauthenticated (non-AEAD) ciphers are disabled, or if they're all fully provided by drivers. See docs/driver-only-builds.md for full details and current limitations; in particular, NIST_KW and PKCS5/PKCS12 decryption still unconditionally depend on MBEDTLS_CIPHER_C. * Add support for record size limit extension as defined by RFC 8449 and configured with MBEDTLS_SSL_RECORD_SIZE_LIMIT. Application data sent and received will be fragmented according to Record size limits negotiated during handshake. * Improve performance of AES-GCM, AES-CTR and CTR-DRBG when hardware accelerated AES is not present (around 13-23% on 64-bit Arm). * Add functions mbedtls_ecc_group_to_psa() and mbedtls_ecc_group_from_psa() to convert between Mbed TLS and PSA curve identifiers. * Add utility functions to manipulate mbedtls_ecp_keypair objects, filling gaps made by making its fields private: mbedtls_ecp_set_public_key(), mbedtls_ecp_write_public_key(), mbedtls_ecp_keypair_calc_public(), mbedtls_ecp_keypair_get_group_id(). Fixes #5017, #5441, #8367, #8652. * Add functions mbedtls_md_psa_alg_from_type() and mbedtls_md_type_from_psa_alg() to convert between mbedtls_md_type_t and psa_algorithm_t. * Add partial platform support for z/OS. * Improve performance for gcc (versions older than 9.3.0) and IAR. * Add functions mbedtls_ecdsa_raw_to_der() and mbedtls_ecdsa_der_to_raw() to convert ECDSA signatures between raw and DER (ASN.1) formats. * Add support for using AES-CBC 128, 192, and 256 bit schemes with PKCS#5 PBES2. Keys encrypted this way can now be parsed by PK parse. * The new function mbedtls_rsa_get_bitlen() returns the length of the modulus in bits, i.e. the key size for an RSA key. * Add pc files for pkg-config, e.g.: pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509) * Add getter (mbedtls_ssl_session_get_ticket_creation_time()) to access `mbedtls_ssl_session.ticket_creation_time`. * The new functions mbedtls_pk_get_psa_attributes() and mbedtls_pk_import_into_psa() provide a uniform way to create a PSA key from a PK key. * The benchmark program now reports times for both ephemeral and static ECDH in all ECDH configurations. * Add support for 8-bit GCM tables for Shoup's algorithm to speedup GCM operations when hardware accelerated AES is not present. Improves performance by around 30% on 64-bit Intel; 125% on Armv7-M. * The new function psa_generate_key_ext() allows generating an RSA key pair with a custom public exponent. * The new function mbedtls_ecp_write_key_ext() is similar to mbedtls_ecp_write_key(), but can be used without separately calculating the output length. * Add new accessor to expose the private group id member of `mbedtls_ecdh_context` structure. * Add new accessor to expose the `MBEDTLS_PRIVATE(ca_istrue)` member of `mbedtls_x509_crt` structure. This requires setting the MBEDTLS_X509_EXT_BASIC_CONSTRAINTS bit in the certificate's ext_types field. * mbedtls_psa_get_random() is always available as soon as MBEDTLS_PSA_CRYPTO_CLIENT is enabled at build time and psa_crypto_init() is called at runtime. This together with MBEDTLS_PSA_RANDOM_STATE can be used as random number generator function (f_rng) and context (p_rng) in legacy functions. * The new functions mbedtls_pk_copy_from_psa() and mbedtls_pk_copy_public_from_psa() provide ways to set up a PK context with the same content as a PSA key. * Add new accessors to expose the private session-id, session-id length, and ciphersuite-id members of `mbedtls_ssl_session` structure. Add new accessor to expose the ciphersuite-id of `mbedtls_ssl_ciphersuite_t` structure.Design ref: #8529 * Mbed TLS now supports the writing and reading of TLS 1.3 early data (see docs/tls13-early-data.md). The support enablement is controlled at build time by the MBEDTLS_SSL_EARLY_DATA configuration option and at runtime by the mbedtls_ssl_conf_early_data() API (by default disabled in both cases). * Add protection for multithreaded access to the PSA keystore and protection for multithreaded access to the the PSA global state, including concurrently calling psa_crypto_init() when MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD are defined. See docs/architecture/psa-thread-safety/psa-thread-safety.md for more details. Resolves issues #3263 and #7945. Security * Fix a stack buffer overread (less than 256 bytes) when parsing a TLS 1.3 ClientHello in a TLS 1.3 server supporting some PSK key exchange mode. A malicious client could cause information disclosure or a denial of service. * Passing buffers that are stored in untrusted memory as arguments to PSA functions is now secure by default. The PSA core now protects against modification of inputs or exposure of intermediate outputs during operations. This is currently implemented by copying buffers. This feature increases code size and memory usage. If buffers passed to PSA functions are owned exclusively by the PSA core for the duration of the function call (i.e. no buffer parameters are in shared memory), copying may be disabled by setting MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS. Note that setting this option will cause input-output buffer overlap to be only partially supported (#3266). Fixes CVE-2024-28960. * Restore the maximum TLS version to be negotiated to the configured one when an SSL context is reset with the mbedtls_ssl_session_reset() API. An attacker was able to prevent an Mbed TLS server from establishing any TLS 1.3 connection potentially resulting in a Denial of Service or forced version downgrade from TLS 1.3 to TLS 1.2. Fixes #8654 reported by hey3e. Fixes CVE-2024-28755. * When negotiating TLS version on server side, do not fall back to the TLS 1.2 implementation of the protocol if it is disabled. - If the TLS 1.2 implementation was disabled at build time, a TLS 1.2 client could put the TLS 1.3-only server in an infinite loop processing a TLS 1.2 ClientHello, resulting in a denial of service. Reported by Matthias Mucha and Thomas Blattmann, SICK AG. - If the TLS 1.2 implementation was disabled at runtime, a TLS 1.2 client was able to successfully establish a TLS 1.2 connection with the server. Reported by alluettiv on GitHub. Fixes CVE-2024-28836. Bugfix * Fix the build with CMake when Everest or P256-m is enabled through a user configuration file or the compiler command line. Fixes #8165. * Fix compilation error in C++ programs when MBEDTLS_ASN1_PARSE_C is disabled. * Fix possible NULL dereference issue in X509 cert_req program if an entry in the san parameter is not separated by a colon. * Fix possible NULL dereference issue in X509 cert_write program if an entry in the san parameter is not separated by a colon. * Fix an inconsistency between implementations and usages of `__cpuid`, which mainly causes failures when building Windows target using mingw or clang. Fixes #8334 & #8332. * Fix build failure in conda-forge. Fixes #8422. * Fix parsing of CSRs with critical extensions. * Switch to milliseconds as the unit for ticket creation and reception time instead of seconds. That avoids rounding errors when computing the age of tickets compared to peer using a millisecond clock (observed with GnuTLS). Fixes #6623. * Fix TLS server accepting TLS 1.2 handshake while TLS 1.2 is disabled at runtime. Fixes #8593. * Remove accidental introduction of RSA signature algorithms in TLS Suite B Profile. Fixes #8221. * Fix unsupported PSA asymmetric encryption and decryption (psa_asymmetric_[en|de]crypt) with opaque keys. Resolves #8461. * On Linux on ARMv8, fix a build error with SHA-256 and SHA-512 acceleration detection when the libc headers do not define the corresponding constant. Reported by valord577. * Correct initial capacities for key derivation algorithms:TLS12_PRF, TLS12_PSK_TO_MS, PBKDF2-HMAC, PBKDF2-CMAC * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a multiple of 8. Fixes #868. * Avoid segmentation fault caused by releasing not initialized entropy resource in gen_key example. Fixes #8809. * mbedtls_pem_read_buffer() now performs a check on the padding data of decrypted keys and it rejects invalid ones. * Fix mbedtls_pk_sign(), mbedtls_pk_verify(), mbedtls_pk_decrypt() and mbedtls_pk_encrypt() on non-opaque RSA keys to honor the padding mode in the RSA context. Before, if MBEDTLS_USE_PSA_CRYPTO was enabled and the RSA context was configured for PKCS#1 v2.1 (PSS/OAEP), the sign/verify functions performed a PKCS#1 v1.5 signature instead and the encrypt/decrypt functions returned an error. Fixes #8824. * Fix missing bitflags in SSL session serialization headers. Their absence allowed SSL sessions saved in one configuration to be loaded in a different, incompatible configuration. * In TLS 1.3 clients, fix an interoperability problem due to the client generating a new random after a HelloRetryRequest. Fixes #8669. * Fix the restoration of the ALPN when loading serialized connection with the mbedtls_ssl_context_load() API. * Fix NULL pointer dereference in mbedtls_pk_verify_ext() when called using an opaque RSA context and specifying MBEDTLS_PK_RSASSA_PSS as key type. * Fix RSA opaque keys always using PKCS1 v1.5 algorithms instead of the primary algorithm of the wrapped PSA key. * Fully support arbitrary overlap between inputs and outputs of PSA functions. Note that overlap is still only partially supported when MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS is set (#3266). Changes * Use heap memory to allocate DER encoded public/private key. This reduces stack usage significantly for writing a public/private key to a PEM string. * PSA_WANT_ALG_CCM and PSA_WANT_ALG_CCM_STAR_NO_TAG are no more synonyms and they are now treated separately. This means that they should be individually enabled in order to enable respective support; also the corresponding MBEDTLS_PSA_ACCEL symbol should be defined in case acceleration is required. * Moved declaration of functions mbedtls_ecc_group_to_psa and mbedtls_ecc_group_of_psa from psa/crypto_extra.h to mbedtls/psa_util.h * mbedtls_pk_sign_ext() is now always available, not just when PSA (MBEDTLS_PSA_CRYPTO_C) is enabled. * Extended PSA Crypto configurations options for FFDH by making it possible to select only some of the parameters / groups, with the macros PSA_WANT_DH_RFC7919_XXXX. You now need to defined the corresponding macro for each size you want to support. Also, if you have an FFDH accelerator, you'll need to define the appropriate MBEDTLS_PSA_ACCEL macros to signal support for these domain parameters. * RSA support in PSA no longer auto-enables the pkparse and pkwrite modules, saving code size when those are not otherwise enabled. * mbedtls_mpi_exp_mod and code that uses it, notably RSA and DHM operations, have changed their speed/memory compromise as part of a proactive security improvement. The new default value of MBEDTLS_MPI_WINDOW_SIZE roughly preserves the current speed, at the expense of increasing memory consumption. * Rename directory containing Visual Studio files from visualc/VS2013 to visualc/VS2017. * The TLS 1.3 protocol is now enabled in the default configuration. = Mbed TLS 3.5.2 branch released 2024-01-26 Security * Fix a timing side channel in private key RSA operations. This side channel could be sufficient for an attacker to recover the plaintext. A local attacker or a remote attacker who is close to the victim on the network might have precise enough timing measurements to exploit this. It requires the attacker to send a large number of messages for decryption. For details, see "Everlasting ROBOT: the Marvin Attack", Hubert Kario. Reported by Hubert Kario, Red Hat. * Fix a failure to validate input when writing x509 extensions lengths which could result in an integer overflow, causing a zero-length buffer to be allocated to hold the extension. The extension would then be copied into the buffer, causing a heap buffer overflow. = Mbed TLS 3.5.1 branch released 2023-11-06 Changes * Mbed TLS is now released under a dual Apache-2.0 OR GPL-2.0-or-later license. Users may choose which license they take the code under. Bugfix * Fix accidental omission of MBEDTLS_TARGET_PREFIX in 3rdparty modules in CMake. = Mbed TLS 3.5.0 branch released 2023-10-05 API changes * Mbed TLS 3.4 introduced support for omitting the built-in implementation of ECDSA and/or EC J-PAKE when those are provided by a driver. However, there was a flaw in the logic checking if the built-in implementation, in that it failed to check if all the relevant curves were supported by the accelerator. As a result, it was possible to declare no curves as accelerated and still have the built-in implementation compiled out. Starting with this release, it is necessary to declare which curves are accelerated (using MBEDTLS_PSA_ACCEL_ECC_xxx macros), or they will be considered not accelerated, and the built-in implementation of the curves and any algorithm possible using them will be included in the build. * Add new millisecond time type `mbedtls_ms_time_t` and `mbedtls_ms_time()` function, needed for TLS 1.3 ticket lifetimes. Alternative implementations can be created using an ALT interface. Requirement changes * Officially require Python 3.8 now that earlier versions are out of support. * Minimum required Windows version is now Windows Vista, or Windows Server 2008. New deprecations * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR, where xxx is either ECC or RSA, are now being deprecated in favor of PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy. Here yyy can be: BASIC, IMPORT, EXPORT, GENERATE, DERIVE. The goal is to have a finer detail about the capabilities of the PSA side for either key. * MBEDTLS_CIPHER_BLKSIZE_MAX is deprecated in favor of MBEDTLS_MAX_BLOCK_LENGTH (if you intended what the name suggests: maximum size of any supported block cipher) or the new name MBEDTLS_CMAC_MAX_BLOCK_SIZE (if you intended the actual semantics: maximum size of a block cipher supported by the CMAC module). * mbedtls_pkcs5_pbes2() and mbedtls_pkcs12_pbe() functions are now deprecated in favor of mbedtls_pkcs5_pbes2_ext() and mbedtls_pkcs12_pbe_ext() as they offer more security by checking for overflow of the output buffer and reporting the actual length of the output. Features * All modules that use hashes or HMAC can now take advantage of PSA Crypto drivers when MBEDTLS_PSA_CRYPTO_C is enabled and psa_crypto_init() has been called. Previously (in 3.3), this was restricted to a few modules, and only in builds where MBEDTLS_MD_C was disabled; in particular the entropy module was not covered which meant an external RNG had to be provided - these limitations are lifted in this version. A new set of feature macros, MBEDTLS_MD_CAN_xxx, has been introduced that can be used to check for availability of hash algorithms, regardless of whether they're provided by a built-in implementation, a driver or both. See docs/driver-only-builds.md. * When a PSA driver for ECDH is present, it is now possible to disable MBEDTLS_ECDH_C in the build in order to save code size. For TLS 1.2 key exchanges based on ECDH(E) to work, this requires MBEDTLS_USE_PSA_CRYPTO. Restartable/interruptible ECDHE operations in TLS 1.2 (ECDHE-ECDSA key exchange) are not supported in those builds yet, as PSA does not have an API for restartable ECDH yet. * When all of ECDH, ECDSA and EC J-PAKE are either disabled or provided by a driver, it is possible to disable MBEDTLS_ECP_C (and MBEDTLS_BIGNUM_C if not required by another module) and still get support for ECC keys and algorithms in PSA, with some limitations. See docs/driver-only-builds.txt for details. * Add parsing of directoryName subtype for subjectAltName extension in x509 certificates. * Add support for server-side TLS version negotiation. If both TLS 1.2 and TLS 1.3 protocols are enabled, the TLS server now selects TLS 1.2 or TLS 1.3 depending on the capabilities and preferences of TLS clients. Fixes #6867. * X.509 hostname verification now supports IPAddress Subject Alternate Names. * Add support for reading and writing X25519 and X448 public and private keys in RFC 8410 format using the existing PK APIs. * When parsing X.509 certificates, support the extensions SignatureKeyIdentifier and AuthorityKeyIdentifier. * Don't include the PSA dispatch functions for PAKEs (psa_pake_setup() etc) if no PAKE algorithms are requested * Add support for the FFDH algorithm and DH key types in PSA, with parameters from RFC 7919. This includes a built-in implementation based on MBEDTLS_BIGNUM_C, and a driver dispatch layer enabling alternative implementations of FFDH through the driver entry points. * It is now possible to generate certificates with SubjectAltNames. Currently supported subtypes: DnsName, UniformResourceIdentifier, IP address, OtherName, and DirectoryName, as defined in RFC 5280. See mbedtls_x509write_crt_set_subject_alternative_name for more information. * X.509 hostname verification now partially supports URI Subject Alternate Names. Only exact matching, without any normalization procedures described in 7.4 of RFC5280, will result in a positive URI verification. * Add function mbedtls_oid_from_numeric_string() to parse an OID from a string to a DER-encoded mbedtls_asn1_buf. * Add SHA-3 family hash functions. * Add support to restrict AES to 128-bit keys in order to save code size. A new configuration option, MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH, can be used to enable this feature. * AES performance improvements. Uplift varies by platform, toolchain, optimisation flags and mode. Aarch64, gcc -Os and CCM, GCM and XTS benefit the most. On Aarch64, uplift is typically around 20 - 110%. When compiling with gcc -Os on Aarch64, AES-XTS improves by 4.5x. * Add support for PBKDF2-HMAC through the PSA API. * New symbols PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy (where xxx is either ECC, RSA or DH) were introduced in order to have finer accuracy in defining the PSA capabilities for each key. These capabilities, named yyy above, can be any of: BASIC, IMPORT, EXPORT, GENERATE, DERIVE. - DERIVE is only available for ECC keys, not for RSA or DH ones. - implementations are free to enable more than what it was strictly requested. For example BASIC internally enables IMPORT and EXPORT (useful for testing purposes), but this might change in the future. * Add support for FFDH key exchange in TLS 1.3. This is automatically enabled as soon as PSA_WANT_ALG_FFDH and the ephemeral or psk-ephemeral key exchange mode are enabled. By default, all groups are offered; the list of groups can be configured using the existing API function mbedtls_ssl_conf_groups(). * Improve mbedtls_x509_time performance and reduce memory use. * Reduce syscalls to time() during certificate verification. * Allow MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE to be set by setting the CMake variable of the same name at configuration time. * Add getter (mbedtls_ssl_cache_get_timeout()) to access `mbedtls_ssl_cache_context.timeout`. * Add getter (mbedtls_ssl_get_hostname()) to access `mbedtls_ssl_context.hostname`. * Add getter (mbedtls_ssl_conf_get_endpoint()) to access `mbedtls_ssl_config.endpoint`. * Support for "opaque" (PSA-held) ECC keys in the PK module has been extended: it is now possible to use mbedtls_pk_write_key_der(), mbedtls_pk_write_key_pem(), mbedtls_pk_check_pair(), and mbedtls_pk_verify() with opaque ECC keys (provided the PSA attributes allow it). * The documentation of mbedtls_ecp_group now describes the optimized representation of A for some curves. Fixes #8045. * Add a possibility to generate CSR's with RCF822 and directoryName subtype of subjectAltName extension in x509 certificates. * Add support for PBKDF2-CMAC through the PSA API. * New configuration option MBEDTLS_AES_USE_HARDWARE_ONLY introduced. When using CPU-accelerated AES (e.g., Arm Crypto Extensions), this option disables the plain C implementation and the run-time detection for the CPU feature, which reduces code size and avoids the vulnerability of the plain C implementation. * Accept arbitrary AttributeType and AttributeValue in certificate Distinguished Names using RFC 4514 syntax. * Applications using ECC over secp256r1 through the PSA API can use a new implementation with a much smaller footprint, but some minor usage restrictions. See the documentation of the new configuration option MBEDTLS_PSA_P256M_DRIVER_ENABLED for details. Security * Fix a case where potentially sensitive information held in memory would not be completely zeroized during TLS 1.2 handshake, in both server and client configurations. * In configurations with ARIA or Camellia but not AES, the value of MBEDTLS_CIPHER_BLKSIZE_MAX was 8, rather than 16 as the name might suggest. This did not affect any library code, because this macro was only used in relation with CMAC which does not support these ciphers. This may affect application code that uses this macro. * Developers using mbedtls_pkcs5_pbes2() or mbedtls_pkcs12_pbe() should review the size of the output buffer passed to this function, and note that the output after decryption may include CBC padding. Consider moving to the new functions mbedtls_pkcs5_pbes2_ext() or mbedtls_pkcs12_pbe_ext() which checks for overflow of the output buffer and reports the actual length of the output. * Improve padding calculations in CBC decryption, NIST key unwrapping and RSA OAEP decryption. With the previous implementation, some compilers (notably recent versions of Clang and IAR) could produce non-constant time code, which could allow a padding oracle attack if the attacker has access to precise timing measurements. * Updates to constant-time C code so that compilers are less likely to use conditional instructions, which can have an observable difference in timing. (Clang has been seen to do this.) Also introduce assembly implementations for 32- and 64-bit Arm and for x86 and x86-64, which are guaranteed not to use conditional instructions. * Fix definition of MBEDTLS_MD_MAX_BLOCK_SIZE, which was too small when MBEDTLS_SHA384_C was defined and MBEDTLS_SHA512_C was undefined. Mbed TLS itself was unaffected by this, but user code which used MBEDTLS_MD_MAX_BLOCK_SIZE could be affected. The only release containing this bug was Mbed TLS 3.4.0. * Fix a buffer overread when parsing short TLS application data records in null-cipher cipher suites. Credit to OSS-Fuzz. * Fix a remotely exploitable heap buffer overflow in TLS handshake parsing. In TLS 1.3, all configurations are affected except PSK-only ones, and both clients and servers are affected. In TLS 1.2, the affected configurations are those with MBEDTLS_USE_PSA_CRYPTO and ECDH enabled but DHM and RSA disabled, and only servers are affected, not clients. Credit to OSS-Fuzz. Bugfix * Fix proper sizing for PSA_EXPORT_[KEY_PAIR/PUBLIC_KEY]_MAX_SIZE and PSA_SIGNATURE_MAX_SIZE buffers when at least one accelerated EC is bigger than all built-in ones and RSA is disabled. Resolves #6622. * Add missing md.h includes to some of the external programs from the programs directory. Without this, even though the configuration was sufficient for a particular program to work, it would only print a message that one of the required defines is missing. * Fix declaration of mbedtls_ecdsa_sign_det_restartable() function in the ecdsa.h header file. There was a build warning when the configuration macro MBEDTLS_ECDSA_SIGN_ALT was defined. Resolves #7407. * Fix an error when MBEDTLS_ECDSA_SIGN_ALT is defined but not MBEDTLS_ECDSA_VERIFY_ALT, causing ecdsa verify to fail. Fixes #7498. * Fix missing PSA initialization in sample programs when MBEDTLS_USE_PSA_CRYPTO is enabled. * Fix the J-PAKE driver interface for user and peer to accept any values (previously accepted values were limited to "client" or "server"). * Fix clang and armclang compilation error when targeting certain Arm M-class CPUs (Cortex-M0, Cortex-M0+, Cortex-M1, Cortex-M23, SecurCore SC000). Fixes #1077. * Fix "unterminated '#pragma clang attribute push'" in sha256/sha512.c when built with MBEDTLS_SHAxxx_USE_A64_CRYPTO_IF_PRESENT but don't have a way to detect the crypto extensions required. A warning is still issued. * Fixed an issue that caused compile errors when using CMake and the IAR toolchain. * Fix very high stack usage in SSL debug code. Reported by Maximilian Gerhardt in #7804. * Fix a compilation failure in the constant_time module when building for arm64_32 (e.g., for watchos). Reported by Paulo Coutinho in #7787. * Fix crypt_and_hash decryption fail when used with a stream cipher mode of operation due to the input not being multiple of block size. Resolves #7417. * Fix a bug in which mbedtls_x509_string_to_names() would return success when given a invalid name string if it did not contain '=' or ','. * Fix compilation warnings in aes.c, which prevented the example TF-M configuration in configs/ from building cleanly: tfm_mbedcrypto_config_profile_medium.h with crypto_config_profile_medium.h. * In TLS 1.3, fix handshake failure when a client in its ClientHello proposes an handshake based on PSK only key exchange mode or at least one of the key exchange modes using ephemeral keys to a server that supports only the PSK key exchange mode. * Fix CCM* with no tag being not supported in a build with CCM as the only symmetric encryption algorithm and the PSA configuration enabled. * Fix the build with MBEDTLS_PSA_INJECT_ENTROPY. Fixes #7516. * Fix a compilation error on some platforms when including mbedtls/ssl.h with all TLS support disabled. Fixes #6628. * Fix x509 certificate generation to conform to RFC 5480 / RFC 5758 when using ECC key. The certificate was rejected by some crypto frameworks. Fixes #2924. * Fix a potential corruption of the passed-in IV when mbedtls_aes_crypt_cbc() is called with zero length and padlock is not enabled. * Fix compile failure due to empty enum in cipher_wrap.c, when building with a very minimal configuration. Fixes #7625. * Fix some cases where mbedtls_mpi_mod_exp, RSA key construction or ECDSA signature can silently return an incorrect result in low memory conditions. * Don't try to include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE when MBEDTLS_PSA_CRYPTO_CONFIG is disabled. * Fix IAR compiler warnings. * Fix an issue when parsing an otherName subject alternative name into a mbedtls_x509_san_other_name struct. The type-id of the otherName was not copied to the struct. This meant that the struct had incomplete information about the otherName SAN and contained uninitialized memory. * Fix the detection of HardwareModuleName otherName SANs. These were being detected by comparing the wrong field and the check was erroneously inverted. * Fix a build error in some configurations with MBEDTLS_PSA_CRYPTO_CONFIG enabled, where some low-level modules required by requested PSA crypto features were not getting automatically enabled. Fixes #7420. * Fix undefined symbols in some builds using TLS 1.3 with a custom configuration file. * Fix log level for the got supported group message. Fixes #6765 * Functions in the ssl_cache module now return a negative MBEDTLS_ERR_xxx error code on failure. Before, they returned 1 to indicate failure in some cases involving a missing entry or a full cache. * mbedtls_pk_parse_key() now rejects trailing garbage in encrypted keys. * Fix the build with CMake when Everest or P256-m is enabled through a user configuration file or the compiler command line. Fixes #8165. Changes * Enable Arm / Thumb bignum assembly for most Arm platforms when compiling with gcc, clang or armclang and -O0. * Enforce minimum RSA key size when generating a key to avoid accidental misuse. * Use heap memory to allocate DER encoded RSA private key. This reduces stack usage significantly for RSA signature operations when MBEDTLS_PSA_CRYPTO_C is defined. * Update Windows code to use BCryptGenRandom and wcslen, and ensure that conversions between size_t, ULONG, and int are always done safely. Original contribution by Kevin Kane #635, #730 followed by Simon Butcher #1453. * Users integrating their own PSA drivers should be aware that the file library/psa_crypto_driver_wrappers.c has been renamed to psa_crypto_driver_wrappers_no_static.c. * When using CBC with the cipher module, the requirement to call mbedtls_cipher_set_padding_mode() is now enforced. Previously, omitting this call accidentally applied a default padding mode chosen at compile time. = Mbed TLS 3.4.1 branch released 2023-08-04 Bugfix * Fix builds on Windows with clang Changes * Update test data to avoid failures of unit tests after 2023-08-07. = Mbed TLS 3.4.0 branch released 2023-03-28 Default behavior changes * The default priority order of TLS 1.3 cipher suites has been modified to follow the same rules as the TLS 1.2 cipher suites (see ssl_ciphersuites.c). The preferred cipher suite is now TLS_CHACHA20_POLY1305_SHA256. New deprecations * mbedtls_x509write_crt_set_serial() is now being deprecated in favor of mbedtls_x509write_crt_set_serial_raw(). The goal here is to remove any direct dependency of X509 on BIGNUM_C. * PSA to mbedtls error translation is now unified in psa_util.h, deprecating mbedtls_md_error_from_psa. Each file that performs error translation should define its own version of PSA_TO_MBEDTLS_ERR, optionally providing file-specific error pairs. Please see psa_util.h for more details. Features * Added partial support for parsing the PKCS #7 Cryptographic Message Syntax, as defined in RFC 2315. Currently, support is limited to the following: - Only the signed-data content type, version 1 is supported. - Only DER encoding is supported. - Only a single digest algorithm per message is supported. - Certificates must be in X.509 format. A message must have either 0 or 1 certificates. - There is no support for certificate revocation lists. - The authenticated and unauthenticated attribute fields of SignerInfo must be empty. Many thanks to Daniel Axtens, Nayna Jain, and Nick Child from IBM for contributing this feature, and to Demi-Marie Obenour for contributing various improvements, tests and bug fixes. * General performance improvements by accessing multiple bytes at a time. Fixes #1666. * Improvements to use of unaligned and byte-swapped memory, reducing code size and improving performance (depending on compiler and target architecture). * Add support for reading points in compressed format (MBEDTLS_ECP_PF_COMPRESSED) with mbedtls_ecp_point_read_binary() (and callers) for Short Weierstrass curves with prime p where p = 3 mod 4 (all mbedtls MBEDTLS_ECP_DP_SECP* and MBEDTLS_ECP_DP_BP* curves except MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1) * SHA224_C/SHA384_C are now independent from SHA384_C/SHA512_C respectively. This helps in saving code size when some of the above hashes are not required. * Add parsing of V3 extensions (key usage, Netscape cert-type, Subject Alternative Names) in x509 Certificate Sign Requests. * Use HOSTCC (if it is set) when compiling C code during generation of the configuration-independent files. This allows them to be generated when CC is set for cross compilation. * Add parsing of uniformResourceIdentifier subtype for subjectAltName extension in x509 certificates. * Add an interruptible version of sign and verify hash to the PSA interface, backed by internal library support for ECDSA signing and verification. * Add parsing of rfc822Name subtype for subjectAltName extension in x509 certificates. * The configuration macros MBEDTLS_PSA_CRYPTO_PLATFORM_FILE and MBEDTLS_PSA_CRYPTO_STRUCT_FILE specify alternative locations for the headers "psa/crypto_platform.h" and "psa/crypto_struct.h". * When a PSA driver for ECDSA is present, it is now possible to disable MBEDTLS_ECDSA_C in the build in order to save code size. For PK, X.509 and TLS to fully work, this requires MBEDTLS_USE_PSA_CRYPTO to be enabled. Restartable/interruptible ECDSA operations in PK, X.509 and TLS are not supported in those builds yet, as driver support for interruptible ECDSA operations is not present yet. * Add a driver dispatch layer for EC J-PAKE, enabling alternative implementations of EC J-PAKE through the driver entry points. * Add new API mbedtls_ssl_cache_remove for cache entry removal by its session id. * Add support to include the SubjectAltName extension to a CSR. * Add support for AES with the Armv8-A Cryptographic Extension on 64-bit Arm. A new configuration option, MBEDTLS_AESCE_C, can be used to enable this feature. Run-time detection is supported under Linux only. * When a PSA driver for EC J-PAKE is present, it is now possible to disable MBEDTLS_ECJPAKE_C in the build in order to save code size. For the corresponding TLS 1.2 key exchange to work, MBEDTLS_USE_PSA_CRYPTO needs to be enabled. * Add functions mbedtls_rsa_get_padding_mode() and mbedtls_rsa_get_md_alg() to read non-public fields for padding mode and hash id from an mbedtls_rsa_context, as requested in #6917. * AES-NI is now supported with Visual Studio. * AES-NI is now supported in 32-bit builds, or when MBEDTLS_HAVE_ASM is disabled, when compiling with GCC or Clang or a compatible compiler for a target CPU that supports the requisite instructions (for example gcc -m32 -msse2 -maes -mpclmul). (Generic x86 builds with GCC-like compilers still require MBEDTLS_HAVE_ASM and a 64-bit target.) * It is now possible to use a PSA-held (opaque) password with the TLS 1.2 ECJPAKE key exchange, using the new API function mbedtls_ssl_set_hs_ecjpake_password_opaque(). Security * Use platform-provided secure zeroization function where possible, such as explicit_bzero(). * Zeroize SSL cache entries when they are freed. * Fix a potential heap buffer overread in TLS 1.3 client-side when MBEDTLS_DEBUG_C is enabled. This may result in an application crash. * Add support for AES with the Armv8-A Cryptographic Extension on 64-bit Arm, so that these systems are no longer vulnerable to timing side-channel attacks. This is configured by MBEDTLS_AESCE_C, which is on by default. Reported by Demi Marie Obenour. * MBEDTLS_AESNI_C, which is enabled by default, was silently ignored on builds that couldn't compile the GCC-style assembly implementation (most notably builds with Visual Studio), leaving them vulnerable to timing side-channel attacks. There is now an intrinsics-based AES-NI implementation as a fallback for when the assembly one cannot be used. Bugfix * Fix possible integer overflow in mbedtls_timing_hardclock(), which could cause a crash in programs/test/benchmark. * Fix IAR compiler warnings. Fixes #6924. * Fix a bug in the build where directory names containing spaces were causing generate_errors.pl to error out resulting in a build failure. Fixes issue #6879. * In TLS 1.3, when using a ticket for session resumption, tweak its age calculation on the client side. It prevents a server with more accurate ticket timestamps (typically timestamps in milliseconds) compared to the Mbed TLS ticket timestamps (in seconds) to compute a ticket age smaller than the age computed and transmitted by the client and thus potentially reject the ticket. Fix #6623. * Fix compile error where MBEDTLS_RSA_C and MBEDTLS_X509_CRT_WRITE_C are defined, but MBEDTLS_PK_RSA_ALT_SUPPORT is not defined. Fixes #3174. * List PSA_WANT_ALG_CCM_STAR_NO_TAG in psa/crypto_config.h so that it can be toggled with config.py. * The key derivation algorithm PSA_ALG_TLS12_ECJPAKE_TO_PMS cannot be used on a shared secret from a key agreement since its input must be an ECC public key. Reject this properly. * mbedtls_x509write_crt_set_serial() now explicitly rejects serial numbers whose binary representation is longer than 20 bytes. This was already forbidden by the standard (RFC5280 - section 4.1.2.2) and now it's being enforced also at code level. * Fix potential undefined behavior in mbedtls_mpi_sub_abs(). Reported by Pascal Cuoq using TrustInSoft Analyzer in #6701; observed independently by Aaron Ucko under Valgrind. * Fix behavior of certain sample programs which could, when run with no arguments, access uninitialized memory in some cases. Fixes #6700 (which was found by TrustInSoft Analyzer during REDOCS'22) and #1120. * Fix parsing of X.509 SubjectAlternativeName extension. Previously, malformed alternative name components were not caught during initial certificate parsing, but only on subsequent calls to mbedtls_x509_parse_subject_alt_name(). Fixes #2838. * Make the fields of mbedtls_pk_rsassa_pss_options public. This makes it possible to verify RSA PSS signatures with the pk module, which was inadvertently broken since Mbed TLS 3.0. * Fix bug in conversion from OID to string in mbedtls_oid_get_numeric_string(). OIDs such as 2.40.0.25 are now printed correctly. * Reject OIDs with overlong-encoded subidentifiers when converting them to a string. * Reject OIDs with subidentifier values exceeding UINT_MAX. Such subidentifiers can be valid, but Mbed TLS cannot currently handle them. * Reject OIDs that have unterminated subidentifiers, or (equivalently) have the most-significant bit set in their last byte. * Silence warnings from clang -Wdocumentation about empty \retval descriptions, which started appearing with Clang 15. Fixes #6960. * Fix the handling of renegotiation attempts in TLS 1.3. They are now systematically rejected. * Fix an unused-variable warning in TLS 1.3-only builds if MBEDTLS_SSL_RENEGOTIATION was enabled. Fixes #6200. * Fix undefined behavior in mbedtls_ssl_read() and mbedtls_ssl_write() if len argument is 0 and buffer is NULL. * Allow setting user and peer identifiers for EC J-PAKE operation instead of role in PAKE PSA Crypto API as described in the specification. This is a partial fix that allows only "client" and "server" identifiers. * Fix a compilation error when PSA Crypto is built with support for TLS12_PRF but not TLS12_PSK_TO_MS. Reported by joerchan in #7125. * In the TLS 1.3 server, select the preferred client cipher suite, not the least preferred. The selection error was introduced in Mbed TLS 3.3.0. * Fix TLS 1.3 session resumption when the established pre-shared key is 384 bits long. That is the length of pre-shared keys created under a session where the cipher suite is TLS_AES_256_GCM_SHA384. * Fix an issue when compiling with MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT enabled, which required specifying compiler flags enabling SHA3 Crypto Extensions, where some compilers would emit EOR3 instructions in other modules, which would then fail if run on a CPU without the SHA3 extensions. Fixes #5758. Changes * Install the .cmake files into CMAKE_INSTALL_LIBDIR/cmake/MbedTLS, typically /usr/lib/cmake/MbedTLS. * Mixed-endian systems are explicitly not supported any more. * When MBEDTLS_USE_PSA_CRYPTO and MBEDTLS_ECDSA_DETERMINISTIC are both defined, mbedtls_pk_sign() now use deterministic ECDSA for ECDSA signatures. This aligns the behaviour with MBEDTLS_USE_PSA_CRYPTO to the behaviour without it, where deterministic ECDSA was already used. * Visual Studio: Rename the directory containing Visual Studio files from visualc/VS2010 to visualc/VS2013 as we do not support building with versions older than 2013. Update the solution file to specify VS2013 as a minimum. * programs/x509/cert_write: - now it accepts the serial number in 2 different formats: decimal and hex. They cannot be used simultaneously - "serial" is used for the decimal format and it's limted in size to unsigned long long int - "serial_hex" is used for the hex format; max length here is MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN*2 * The C code follows a new coding style. This is transparent for users but affects contributors and maintainers of local patches. For more information, see https://mbed-tls.readthedocs.io/en/latest/kb/how-to/rewrite-branch-for-coding-style/ * Changed the default MBEDTLS_ECP_WINDOW_SIZE from 6 to 2. As tested in issue 6790, the correlation between this define and RSA decryption performance has changed lately due to security fixes. To fix the performance degradation when using default values the window was reduced from 6 to 2, a value that gives the best or close to best results when tested on Cortex-M4 and Intel i7. * When enabling MBEDTLS_SHA256_USE_A64_CRYPTO_* or MBEDTLS_SHA512_USE_A64_CRYPTO_*, it is no longer necessary to specify compiler target flags on the command line; the library now sets target options within the appropriate modules. = Mbed TLS 3.3.0 branch released 2022-12-14 Default behavior changes * Previously the macro MBEDTLS_SSL_DTLS_CONNECTION_ID implemented version 05 of the IETF draft, and was marked experimental and disabled by default. It is now no longer experimental, and implements the final version from RFC 9146, which is not interoperable with the draft-05 version. If you need to communicate with peers that use earlier versions of Mbed TLS, then you need to define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT to 1, but then you won't be able to communicate with peers that use the standard (non-draft) version. If you need to interoperate with both classes of peers with the same build of Mbed TLS, please let us know about your situation on the mailing list or GitHub. Requirement changes * When building with PSA drivers using generate_driver_wrappers.py, or when building the library from the development branch rather than from a release, the Python module jsonschema is now necessary, in addition to jinja2. The official list of required Python modules is maintained in scripts/basic.requirements.txt and may change again in the future. New deprecations * Deprecate mbedtls_asn1_free_named_data(). Use mbedtls_asn1_free_named_data_list() or mbedtls_asn1_free_named_data_list_shallow(). Features * Support rsa_pss_rsae_* signature algorithms in TLS 1.2. * make: enable building unversioned shared library, with e.g.: "SHARED=1 SOEXT_TLS=so SOEXT_X509=so SOEXT_CRYPTO=so make lib" resulting in library names like "libmbedtls.so" rather than "libmbedcrypto.so.11". * Expose the EC J-PAKE functionality through the Draft PSA PAKE Crypto API. Only the ECC primitive with secp256r1 curve and SHA-256 hash algorithm are supported in this implementation. * Some modules can now use PSA drivers for hashes, including with no built-in implementation present, but only in some configurations. - RSA OAEP and PSS (PKCS#1 v2.1), PKCS5, PKCS12 and EC J-PAKE now use hashes from PSA when (and only when) MBEDTLS_MD_C is disabled. - PEM parsing of encrypted files now uses MD-5 from PSA when (and only when) MBEDTLS_MD5_C is disabled. See the documentation of the corresponding macros in mbedtls_config.h for details. Note that some modules are not able to use hashes from PSA yet, including the entropy module. As a consequence, for now the only way to build with all hashes only provided by drivers (no built-in hash) is to use MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. * When MBEDTLS_USE_PSA_CRYPTO is enabled, X.509, TLS 1.2 and TLS 1.3 now properly negotiate/accept hashes based on their availability in PSA. As a consequence, they now work in configurations where the built-in implementations of (some) hashes are excluded and those hashes are only provided by PSA drivers. (See previous entry for limitation on RSA-PSS though: that module only use hashes from PSA when MBEDTLS_MD_C is off). * Add support for opaque keys as the private keys associated to certificates for authentication in TLS 1.3. * Add the LMS post-quantum-safe stateful-hash asymmetric signature scheme. Signature verification is production-ready, but generation is for testing purposes only. This currently only supports one parameter set (LMS_SHA256_M32_H10), meaning that each private key can be used to sign 1024 messages. As such, it is not intended for use in TLS, but instead for verification of assets transmitted over an insecure channel, particularly firmware images. * Add the LM-OTS post-quantum-safe one-time signature scheme, which is required for LMS. This can be used independently, but each key can only be used to sign one message so is impractical for most circumstances. * Mbed TLS now supports TLS 1.3 key establishment via pre-shared keys. The pre-shared keys can be provisioned externally or via the ticket mechanism (session resumption). The ticket mechanism is supported when the configuration option MBEDTLS_SSL_SESSION_TICKETS is enabled. New options MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED control the support for the three possible TLS 1.3 key exchange modes. * cert_write: support for setting extended key usage attributes. A corresponding new public API call has been added in the library, mbedtls_x509write_crt_set_ext_key_usage(). * cert_write: support for writing certificate files in either PEM or DER format. * The PSA driver wrapper generator generate_driver_wrappers.py now supports a subset of the driver description language, including the following entry points: import_key, export_key, export_public_key, get_builtin_key, copy_key. * The new functions mbedtls_asn1_free_named_data_list() and mbedtls_asn1_free_named_data_list_shallow() simplify the management of memory in named data lists in X.509 structures. * The TLS 1.2 EC J-PAKE key exchange can now use the PSA Crypto API. Additional PSA key slots will be allocated in the process of such key exchange for builds that enable MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED and MBEDTLS_USE_PSA_CRYPTO. * Add support for DTLS Connection ID as defined by RFC 9146, controlled by MBEDTLS_SSL_DTLS_CONNECTION_ID (enabled by default) and configured with mbedtls_ssl_set_cid(). * Add a driver dispatch layer for raw key agreement, enabling alternative implementations of raw key agreement through the key_agreement driver entry point. This entry point is specified in the proposed PSA driver interface, but had not yet been implemented. * Add an ad-hoc key derivation function handling EC J-PAKE to PMS calculation that can be used to derive the session secret in TLS 1.2, as described in draft-cragie-tls-ecjpake-01. This can be achieved by using PSA_ALG_TLS12_ECJPAKE_TO_PMS as the key derivation algorithm. Security * Fix potential heap buffer overread and overwrite in DTLS if MBEDTLS_SSL_DTLS_CONNECTION_ID is enabled and MBEDTLS_SSL_CID_IN_LEN_MAX > 2 * MBEDTLS_SSL_CID_OUT_LEN_MAX. * Fix an issue where an adversary with access to precise enough information about memory accesses (typically, an untrusted operating system attacking a secure enclave) could recover an RSA private key after observing the victim performing a single private-key operation if the window size used for the exponentiation was 3 or smaller. Found and reported by Zili KOU, Wenjian HE, Sharad Sinha, and Wei ZHANG. See "Cache Side-channel Attacks and Defenses of the Sliding Window Algorithm in TEEs" - Design, Automation and Test in Europe 2023. Bugfix * Refactor mbedtls_aes_context to support shallow-copying. Fixes #2147. * Fix an issue with in-tree CMake builds in releases with GEN_FILES turned off: if a shipped file was missing from the working directory, it could be turned into a symbolic link to itself. * Fix a long-standing build failure when building x86 PIC code with old gcc (4.x). The code will be slower, but will compile. We do however recommend upgrading to a more recent compiler instead. Fixes #1910. * Fix support for little-endian Microblaze when MBEDTLS_HAVE_ASM is defined. Contributed by Kazuyuki Kimura to fix #2020. * Use double quotes to include private header file psa_crypto_cipher.h. Fixes 'file not found with include' error when building with Xcode. * Fix handling of broken symlinks when loading certificates using mbedtls_x509_crt_parse_path(). Instead of returning an error as soon as a broken link is encountered, skip the broken link and continue parsing other certificate files. Contributed by Eduardo Silva in #2602. * Fix an interoperability failure between an Mbed TLS client with both TLS 1.2 and TLS 1.3 support, and a TLS 1.2 server that supports rsa_pss_rsae_* signature algorithms. This failed because Mbed TLS advertised support for PSS in both TLS 1.2 and 1.3, but only actually supported PSS in TLS 1.3. * Fix a compilation error when using CMake with an IAR toolchain. Fixes #5964. * Fix a build error due to a missing prototype warning when MBEDTLS_DEPRECATED_REMOVED is enabled. * Fix mbedtls_ctr_drbg_free() on an initialized but unseeded context. When MBEDTLS_AES_ALT is enabled, it could call mbedtls_aes_free() on an uninitialized context. * Fix a build issue on Windows using CMake where the source and build directories could not be on different drives. Fixes #5751. * Fix bugs and missing dependencies when building and testing configurations with only one encryption type enabled in TLS 1.2. * Provide the missing definition of mbedtls_setbuf() in some configurations with MBEDTLS_PLATFORM_C disabled. Fixes #6118, #6196. * Fix compilation errors when trying to build with PSA drivers for AEAD (GCM, CCM, Chacha20-Poly1305). * Fix memory leak in ssl_parse_certificate_request() caused by mbedtls_x509_get_name() not freeing allocated objects in case of error. Change mbedtls_x509_get_name() to clean up allocated objects on error. * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not MBEDTLS_USE_PSA_CRYPTO or MBEDTLS_PK_WRITE_C. Fixes #6408. * Fix build failure with MBEDTLS_RSA_C and MBEDTLS_PSA_CRYPTO_C but not MBEDTLS_PK_PARSE_C. Fixes #6409. * Fix ECDSA verification, where it was not always validating the public key. This bug meant that it was possible to verify a signature with an invalid public key, in some cases. Reported by Guido Vranken using Cryptofuzz in #4420. * Fix a possible null pointer dereference if a memory allocation fails in TLS PRF code. Reported by Michael Madsen in #6516. * Fix TLS 1.3 session resumption. Fixes #6488. * Add a configuration check to exclude optional client authentication in TLS 1.3 (where it is forbidden). * Fix a bug in which mbedtls_x509_crt_info() would produce non-printable bytes when parsing certificates containing a binary RFC 4108 HardwareModuleName as a Subject Alternative Name extension. Hardware serial numbers are now rendered in hex format. Fixes #6262. * Fix bug in error reporting in dh_genprime.c where upon failure, the error code returned by mbedtls_mpi_write_file() is overwritten and therefore not printed. * In the bignum module, operations of the form (-A) - (+A) or (-A) - (-A) with A > 0 created an unintended representation of the value 0 which was not processed correctly by some bignum operations. Fix this. This had no consequence on cryptography code, but might affect applications that call bignum directly and use negative numbers. * Fix a bug whereby the list of signature algorithms sent as part of the TLS 1.2 server certificate request would get corrupted, meaning the first algorithm would not get sent and an entry consisting of two random bytes would be sent instead. Found by Serban Bejan and Dudek Sebastian. * Fix undefined behavior (typically harmless in practice) of mbedtls_mpi_add_mpi(), mbedtls_mpi_add_abs() and mbedtls_mpi_add_int() when both operands are 0 and the left operand is represented with 0 limbs. * Fix undefined behavior (typically harmless in practice) when some bignum functions receive the most negative value of mbedtls_mpi_sint. Credit to OSS-Fuzz. Fixes #6597. * Fix undefined behavior (typically harmless in practice) in PSA ECB encryption and decryption. * Move some SSL-specific code out of libmbedcrypto where it had been placed accidentally. * Fix a build error when compiling the bignum module for some Arm platforms. Fixes #6089, #6124, #6217. Changes * Add the ability to query PSA_WANT_xxx macros to query_compile_time_config. * Calling AEAD tag-specific functions for non-AEAD algorithms (which should not be done - they are documented for use only by AES-GCM and ChaCha20+Poly1305) now returns MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE instead of success (0). = Mbed TLS 3.2.1 branch released 2022-07-12 Bugfix * Re-add missing generated file library/psa_crypto_driver_wrappers.c = Mbed TLS 3.2.0 branch released 2022-07-11 Default behavior changes * mbedtls_cipher_set_iv will now fail with ChaCha20 and ChaCha20+Poly1305 for IV lengths other than 12. The library was silently overwriting this length with 12, but did not inform the caller about it. Fixes #4301. Requirement changes * The library will no longer compile out of the box on a platform without setbuf(). If your platform does not have setbuf(), you can configure an alternative function by enabling MBEDTLS_PLATFORM_SETBUF_ALT or MBEDTLS_PLATFORM_SETBUF_MACRO. New deprecations * Deprecate mbedtls_ssl_conf_max_version() and mbedtls_ssl_conf_min_version() in favor of mbedtls_ssl_conf_max_tls_version() and mbedtls_ssl_conf_min_tls_version(). * Deprecate mbedtls_cipher_setup_psa(). Use psa_aead_xxx() or psa_cipher_xxx() directly instead. * Secure element drivers enabled by MBEDTLS_PSA_CRYPTO_SE_C are deprecated. This was intended as an experimental feature, but had not been explicitly documented as such. Use opaque drivers with the interface enabled by MBEDTLS_PSA_CRYPTO_DRIVERS instead. * Deprecate mbedtls_ssl_conf_sig_hashes() in favor of the more generic mbedtls_ssl_conf_sig_algs(). Signature algorithms for the TLS 1.2 and TLS 1.3 handshake should now be configured with mbedtls_ssl_conf_sig_algs(). Features * Add accessor to obtain ciphersuite id from ssl context. * Add accessors to get members from ciphersuite info. * Add mbedtls_ssl_ticket_rotate() for external ticket rotation. * Add accessor to get the raw buffer pointer from a PEM context. * The structures mbedtls_ssl_config and mbedtls_ssl_context now store a piece of user data which is reserved for the application. The user data can be either a pointer or an integer. * Add an accessor function to get the configuration associated with an SSL context. * Add a function to access the protocol version from an SSL context in a form that's easy to compare. Fixes #5407. * Add function mbedtls_md_info_from_ctx() to recall the message digest information that was used to set up a message digest context. * Add ALPN support in TLS 1.3 clients. * Add server certificate selection callback near end of Client Hello. Register callback with mbedtls_ssl_conf_cert_cb(). * Provide mechanism to reset handshake cert list by calling mbedtls_ssl_set_hs_own_cert() with NULL value for own_cert param. * Add accessor mbedtls_ssl_get_hs_sni() to retrieve SNI from within cert callback (mbedtls_ssl_conf_cert_cb()) during handshake. * The X.509 module now uses PSA hash acceleration if present. * Add support for psa crypto key derivation for elliptic curve keys. Fixes #3260. * Add function mbedtls_timing_get_final_delay() to access the private final delay field in an mbedtls_timing_delay_context, as requested in #5183. * Add mbedtls_pk_sign_ext() which allows generating RSA-PSS signatures when PSA Crypto is enabled. * Add function mbedtls_ecp_export() to export ECP key pair parameters. Fixes #4838. * Add function mbedtls_ssl_is_handshake_over() to enable querying if the SSL Handshake has completed or not, and thus whether to continue calling mbedtls_ssl_handshake_step(), requested in #4383. * Add the function mbedtls_ssl_get_own_cid() to access our own connection id within mbedtls_ssl_context, as requested in #5184. * Introduce mbedtls_ssl_hs_cb_t typedef for use with mbedtls_ssl_conf_cert_cb() and perhaps future callbacks during TLS handshake. * Add functions mbedtls_ssl_conf_max_tls_version() and mbedtls_ssl_conf_min_tls_version() that use a single value to specify the protocol version. * Extend the existing PSA_ALG_TLS12_PSK_TO_MS() algorithm to support mixed-PSK. Add an optional input PSA_KEY_DERIVATION_INPUT_OTHER_SECRET holding the other secret. * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, you may list the PSA crypto feature requirements in the file named by the new macro MBEDTLS_PSA_CRYPTO_CONFIG_FILE instead of the default psa/crypto_config.h. Furthermore you may name an additional file to include after the main file with the macro MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE. * Add the function mbedtls_x509_crt_has_ext_type() to access the ext types field within mbedtls_x509_crt context, as requested in #5585. * Add HKDF-Expand and HKDF-Extract as separate algorithms in the PSA API. * Add support for the ARMv8 SHA-2 acceleration instructions when building for Aarch64. * Add support for authentication of TLS 1.3 clients by TLS 1.3 servers. * Add support for server HelloRetryRequest message. The TLS 1.3 client is now capable of negotiating another shared secret if the one sent in its first ClientHello was not suitable to the server. * Add support for client-side TLS version negotiation. If both TLS 1.2 and TLS 1.3 protocols are enabled in the build of Mbed TLS, the TLS client now negotiates TLS 1.3 or TLS 1.2 with TLS servers. * Enable building of Mbed TLS with TLS 1.3 protocol support but without TLS 1.2 protocol support. * Mbed TLS provides an implementation of a TLS 1.3 server (ephemeral key establishment only). See docs/architecture/tls13-support.md for a description of the support. The MBEDTLS_SSL_PROTO_TLS1_3 and MBEDTLS_SSL_SRV_C configuration options control this. * Add accessors to configure DN hints for certificate request: mbedtls_ssl_conf_dn_hints() and mbedtls_ssl_set_hs_dn_hints() * The configuration option MBEDTLS_USE_PSA_CRYPTO, which previously affected only a limited subset of crypto operations in TLS, X.509 and PK, now causes most of them to be done using PSA Crypto; see docs/use-psa-crypto.md for the list of exceptions. * The function mbedtls_pk_setup_opaque() now supports RSA key pairs as well. Opaque keys can now be used everywhere a private key is expected in the TLS and X.509 modules. * Opaque pre-shared keys for TLS, provisioned with mbedtls_ssl_conf_psk_opaque() or mbedtls_ssl_set_hs_psk_opaque(), which previously only worked for "pure" PSK key exchange, now can also be used for the "mixed" PSK key exchanges as well: ECDHE-PSK, DHE-PSK, RSA-PSK. * cmake now detects if it is being built as a sub-project, and in that case disables the target export/installation and package configuration. * Make USE_PSA_CRYPTO compatible with KEY_ID_ENCODES_OWNER. Fixes #5259. * Add example programs cipher_aead_demo.c, md_hmac_demo.c, aead_demo.c and hmac_demo.c, which use PSA and the md/cipher interfaces side by side in order to illustrate how the operation is performed in PSA. Addresses #5208. Security * Zeroize dynamically-allocated buffers used by the PSA Crypto key storage module before freeing them. These buffers contain secret key material, and could thus potentially leak the key through freed heap. * Fix potential memory leak inside mbedtls_ssl_cache_set() with an invalid session id length. * Add the platform function mbedtls_setbuf() to allow buffering to be disabled on stdio files, to stop secrets loaded from said files being potentially left in memory after file operations. Reported by Glenn Strauss. * Fix a potential heap buffer overread in TLS 1.2 server-side when MBEDTLS_USE_PSA_CRYPTO is enabled, an opaque key (created with mbedtls_pk_setup_opaque()) is provisioned, and a static ECDH ciphersuite is selected. This may result in an application crash or potentially an information leak. * Fix a buffer overread in DTLS ClientHello parsing in servers with MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE enabled. An unauthenticated client or a man-in-the-middle could cause a DTLS server to read up to 255 bytes after the end of the SSL input buffer. The buffer overread only happens when MBEDTLS_SSL_IN_CONTENT_LEN is less than a threshold that depends on the exact configuration: 258 bytes if using mbedtls_ssl_cookie_check(), and possibly up to 571 bytes with a custom cookie check function. Reported by the Cybeats PSI Team. * Fix a buffer overread in TLS 1.3 Certificate parsing. An unauthenticated client or server could cause an MbedTLS server or client to overread up to 64 kBytes of data and potentially overread the input buffer by that amount minus the size of the input buffer. As overread data undergoes various checks, the likelihood of reaching the boundary of the input buffer is rather small but increases as its size MBEDTLS_SSL_IN_CONTENT_LEN decreases. * Fix check of certificate key usage in TLS 1.3. The usage of the public key provided by a client or server certificate for authentication was not checked properly when validating the certificate. This could cause a client or server to be able to authenticate itself through a certificate to an Mbed TLS TLS 1.3 server or client while it does not own a proper certificate to do so. Bugfix * Declare or use PSA_WANT_ALG_CCM_STAR_NO_TAG following the general pattern for PSA_WANT_xxx symbols. Previously you had to specify PSA_WANT_ALG_CCM for PSA_ALG_CCM_STAR_NO_TAG. * Fix a memory leak if mbedtls_ssl_config_defaults() is called twice. * Fixed swap of client and server random bytes when exporting them alongside TLS 1.3 handshake and application traffic secret. * Fix several bugs (warnings, compiler and linker errors, test failures) in reduced configurations when MBEDTLS_USE_PSA_CRYPTO is enabled. * Fix a bug in (D)TLS curve negotiation: when MBEDTLS_USE_PSA_CRYPTO was enabled and an ECDHE-ECDSA or ECDHE-RSA key exchange was used, the client would fail to check that the curve selected by the server for ECDHE was indeed one that was offered. As a result, the client would accept any curve that it supported, even if that curve was not allowed according to its configuration. Fixes #5291. * The TLS 1.3 implementation is now compatible with the MBEDTLS_USE_PSA_CRYPTO configuration option. * Fix unit tests that used 0 as the file UID. This failed on some implementations of PSA ITS. Fixes #3838. * Fix mbedtls_ssl_get_version() not reporting TLSv1.3. Fixes #5406. * Fix API violation in mbedtls_md_process() test by adding a call to mbedtls_md_starts(). Fixes #2227. * Fix compile errors when MBEDTLS_HAVE_TIME is not defined. Add tests to catch bad uses of time.h. * Fix a race condition in out-of-source builds with CMake when generated data files are already present. Fixes #5374. * Fix the library search path when building a shared library with CMake on Windows. * Fix bug in the alert sending function mbedtls_ssl_send_alert_message() potentially leading to corrupted alert messages being sent in case the function needs to be re-called after initially returning MBEDTLS_SSL_WANT_WRITE. Fixes #1916. * In configurations with MBEDTLS_SSL_DTLS_CONNECTION_ID enabled but not MBEDTLS_DEBUG_C, DTLS handshakes using CID would crash due to a null pointer dereference. Fix this. Fixes #3998. The fix was released, but not announced, in Mbed TLS 3.1.0. * Fix incorrect documentation of mbedtls_x509_crt_profile. The previous documentation stated that the `allowed_pks` field applies to signatures only, but in fact it does apply to the public key type of the end entity certificate, too. Fixes #1992. * Fix undefined behavior in mbedtls_asn1_find_named_data(), where val is not NULL and val_len is zero. * Fix compilation error with mingw32. Fixed by Cameron Cawley in #4211. * Fix compilation error when using C++ Builder on Windows. Reported by Miroslav Mastny in #4015. * psa_raw_key_agreement() now returns PSA_ERROR_BUFFER_TOO_SMALL when applicable. Fixes #5735. * Fix a bug in the x25519 example program where the removal of MBEDTLS_ECDH_LEGACY_CONTEXT caused the program not to run. Fixes #4901 and #3191. * Fix a TLS 1.3 handshake failure when the peer Finished message has not been received yet when we first try to fetch it. * Encode X.509 dates before 1/1/2000 as UTCTime rather than GeneralizedTime. Fixes #5465. * Add mbedtls_x509_dn_get_next function to return the next relative DN in an X509 name, to allow walking the name list. Fixes #5431. * Fix order value of curve x448. * Fix string representation of DNs when outputting values containing commas and other special characters, conforming to RFC 1779. Fixes #769. * Silence a warning from GCC 12 in the selftest program. Fixes #5974. * Fix check_config.h to check that we have MBEDTLS_SSL_KEEP_PEER_CERTIFICATE when MBEDTLS_SSL_PROTO_TLS1_3 is specified, and make this and other dependencies explicit in the documentation. Fixes #5610. * Fix mbedtls_asn1_write_mpi() writing an incorrect encoding of 0. * Fix a TLS 1.3 handshake failure when the first attempt to send the client Finished message on the network cannot be satisfied. Fixes #5499. * Fix resource leaks in mbedtls_pk_parse_public_key() in low memory conditions. * Fix server connection identifier setting for outgoing encrypted records on DTLS 1.2 session resumption. After DTLS 1.2 session resumption with connection identifier, the Mbed TLS client now properly sends the server connection identifier in encrypted record headers. Fix #5872. * Fix a null pointer dereference when performing some operations on zero represented with 0 limbs (specifically mbedtls_mpi_mod_int() dividing by 2, and mbedtls_mpi_write_string() in base 2). * Fix record sizes larger than 16384 being sometimes accepted despite being non-compliant. This could not lead to a buffer overflow. In particular, application data size was already checked correctly. * Fix MBEDTLS_SVC_KEY_ID_GET_KEY_ID() and MBEDTLS_SVC_KEY_ID_GET_OWNER_ID() which have been broken, resulting in compilation errors, since Mbed TLS 3.0. * Ensure that TLS 1.2 ciphersuite/certificate and key selection takes into account not just the type of the key (RSA vs EC) but also what it can actually do. Resolves #5831. * Fix CMake windows host detection, especially when cross compiling. * Fix an error in make where the absence of a generated file caused make to break on a clean checkout. Fixes #5340. * Work around an MSVC ARM64 compiler bug causing incorrect behaviour in mbedtls_mpi_exp_mod(). Reported by Tautvydas Žilys in #5467. * Removed the prompt to exit from all windows build programs, which was causing issues in CI/CD environments. Changes * The file library/psa_crypto_driver_wrappers.c is now generated from a template. In the future, the generation will support driver descriptions. For the time being, to customize this file, see docs/proposed/psa-driver-wrappers-codegen-migration-guide.md * Return PSA_ERROR_INVALID_ARGUMENT if the algorithm passed to one-shot AEAD functions is not an AEAD algorithm. This aligns them with the multipart functions, and the PSA Crypto API 1.1 specification. * In mbedtls_pk_parse_key(), if no password is provided, don't allocate a temporary variable on the heap. Suggested by Sergey Kanatov in #5304. * Assume source files are in UTF-8 when using MSVC with CMake. * Fix runtime library install location when building with CMake and MinGW. DLLs are now installed in the bin directory instead of lib. * cmake: Use GnuInstallDirs to customize install directories Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if LIB_INSTALL_DIR is set. * Add a CMake option that enables static linking of the runtime library in Microsoft Visual C++ compiler. Contributed by Microplankton. * In CMake builds, add aliases for libraries so that the normal MbedTLS::* targets work when MbedTLS is built as a subdirectory. This allows the use of FetchContent, as requested in #5688. = mbed TLS 3.1.0 branch released 2021-12-17 API changes * New error code for GCM: MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL. Alternative GCM implementations are expected to verify the length of the provided output buffers and to return the MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL in case the buffer length is too small. * You can configure groups for a TLS key exchange with the new function mbedtls_ssl_conf_groups(). It extends mbedtls_ssl_conf_curves(). * Declare a number of structure fields as public: the fields of mbedtls_ecp_curve_info, the fields describing the result of ASN.1 and X.509 parsing, and finally the field fd of mbedtls_net_context on POSIX/Unix-like platforms. Requirement changes * Sign-magnitude and one's complement representations for signed integers are not supported. Two's complement is the only supported representation. New deprecations * Deprecate mbedtls_ssl_conf_curves() in favor of the more generic mbedtls_ssl_conf_groups(). Removals * Remove the partial support for running unit tests via Greentea on Mbed OS, which had been unmaintained since 2018. Features * Enable support for Curve448 via the PSA API. Contributed by Archana Madhavan in #4626. Fixes #3399 and #4249. * The identifier of the CID TLS extension can be configured by defining MBEDTLS_TLS_EXT_CID at compile time. * Implement the PSA multipart AEAD interface, currently supporting ChaChaPoly and GCM. * Warn if errors from certain functions are ignored. This is currently supported on GCC-like compilers and on MSVC and can be configured through the macro MBEDTLS_CHECK_RETURN. The warnings are always enabled (where supported) for critical functions where ignoring the return value is almost always a bug. Enable the new configuration option MBEDTLS_CHECK_RETURN_WARNING to get warnings for other functions. This is currently implemented in the AES, DES and md modules, and will be extended to other modules in the future. * Add missing PSA macros declared by PSA Crypto API 1.0.0: PSA_ALG_IS_SIGN_HASH, PSA_ALG_NONE, PSA_HASH_BLOCK_LENGTH, PSA_KEY_ID_NULL. * Add support for CCM*-no-tag cipher to the PSA. Currently only 13-byte long IV's are supported. For decryption a minimum of 16-byte long input is expected. These restrictions may be subject to change. * Add new API mbedtls_ct_memcmp for constant time buffer comparison. * Add functions to get the IV and block size from cipher_info structs. * Add functions to check if a cipher supports variable IV or key size. * Add the internal implementation of and support for CCM to the PSA multipart AEAD interface. * Mbed TLS provides a minimum viable implementation of the TLS 1.3 protocol. See docs/architecture/tls13-support.md for the definition of the TLS 1.3 Minimum Viable Product (MVP). The MBEDTLS_SSL_PROTO_TLS1_3 configuration option controls the enablement of the support. The APIs mbedtls_ssl_conf_min_version() and mbedtls_ssl_conf_max_version() allow to select the 1.3 version of the protocol to establish a TLS connection. * Add PSA API definition for ARIA. Security * Zeroize several intermediate variables used to calculate the expected value when verifying a MAC or AEAD tag. This hardens the library in case the value leaks through a memory disclosure vulnerability. For example, a memory disclosure vulnerability could have allowed a man-in-the-middle to inject fake ciphertext into a DTLS connection. * In psa_aead_generate_nonce(), do not read back from the output buffer. This fixes a potential policy bypass or decryption oracle vulnerability if the output buffer is in memory that is shared with an untrusted application. * In psa_cipher_generate_iv() and psa_cipher_encrypt(), do not read back from the output buffer. This fixes a potential policy bypass or decryption oracle vulnerability if the output buffer is in memory that is shared with an untrusted application. * Fix a double-free that happened after mbedtls_ssl_set_session() or mbedtls_ssl_get_session() failed with MBEDTLS_ERR_SSL_ALLOC_FAILED (out of memory). After that, calling mbedtls_ssl_session_free() and mbedtls_ssl_free() would cause an internal session buffer to be free()'d twice. Bugfix * Stop using reserved identifiers as local variables. Fixes #4630. * The GNU makefiles invoke python3 in preference to python except on Windows. The check was accidentally not performed when cross-compiling for Windows on Linux. Fix this. Fixes #4774. * Prevent divide by zero if either of PSA_CIPHER_ENCRYPT_OUTPUT_SIZE() or PSA_CIPHER_UPDATE_OUTPUT_SIZE() were called using an asymmetric key type. * Fix a parameter set but unused in psa_crypto_cipher.c. Fixes #4935. * Don't use the obsolete header path sys/fcntl.h in unit tests. These header files cause compilation errors in musl. Fixes #4969. * Fix missing constraints on x86_64 and aarch64 assembly code for bignum multiplication that broke some bignum operations with (at least) Clang 12. Fixes #4116, #4786, #4917, #4962. * Fix mbedtls_cipher_crypt: AES-ECB when MBEDTLS_USE_PSA_CRYPTO is enabled. * Failures of alternative implementations of AES or DES single-block functions enabled with MBEDTLS_AES_ENCRYPT_ALT, MBEDTLS_AES_DECRYPT_ALT, MBEDTLS_DES_CRYPT_ECB_ALT or MBEDTLS_DES3_CRYPT_ECB_ALT were ignored. This does not concern the implementation provided with Mbed TLS, where this function cannot fail, or full-module replacements with MBEDTLS_AES_ALT or MBEDTLS_DES_ALT. Reported by Armelle Duboc in #1092. * Some failures of HMAC operations were ignored. These failures could only happen with an alternative implementation of the underlying hash module. * Fix the error returned by psa_generate_key() for a public key. Fixes #4551. * Fix compile-time or run-time errors in PSA AEAD functions when ChachaPoly is disabled. Fixes #5065. * Remove PSA'a AEAD finish/verify output buffer limitation for GCM. The requirement of minimum 15 bytes for output buffer in psa_aead_finish() and psa_aead_verify() does not apply to the built-in implementation of GCM. * Move GCM's update output buffer length verification from PSA AEAD to the built-in implementation of the GCM. The requirement for output buffer size to be equal or greater then input buffer size is valid only for the built-in implementation of GCM. Alternative GCM implementations can process whole blocks only. * Fix the build of sample programs when neither MBEDTLS_ERROR_C nor MBEDTLS_ERROR_STRERROR_DUMMY is enabled. * Fix PSA_ALG_RSA_PSS verification accepting an arbitrary salt length. This algorithm now accepts only the same salt length for verification that it produces when signing, as documented. Use the new algorithm PSA_ALG_RSA_PSS_ANY_SALT to accept any salt length. Fixes #4946. * The existing predicate macro name PSA_ALG_IS_HASH_AND_SIGN is now reserved for algorithm values that fully encode the hashing step, as per the PSA Crypto API specification. This excludes PSA_ALG_RSA_PKCS1V15_SIGN_RAW and PSA_ALG_ECDSA_ANY. The new predicate macro PSA_ALG_IS_SIGN_HASH covers all algorithms that can be used with psa_{sign,verify}_hash(), including these two. * Fix issue in Makefile on Linux with SHARED=1, that caused shared libraries not to list other shared libraries they need. * Fix a bug in mbedtls_gcm_starts() when the bit length of the iv exceeds 2^32. Fixes #4884. * Fix an uninitialized variable warning in test_suite_ssl.function with GCC version 11. * Fix the build when no SHA2 module is included. Fixes #4930. * Fix the build when only the bignum module is included. Fixes #4929. * Fix a potential invalid pointer dereference and infinite loop bugs in pkcs12 functions when the password is empty. Fix the documentation to better describe the inputs to these functions and their possible values. Fixes #5136. * The key usage flags PSA_KEY_USAGE_SIGN_MESSAGE now allows the MAC operations psa_mac_compute() and psa_mac_sign_setup(). * The key usage flags PSA_KEY_USAGE_VERIFY_MESSAGE now allows the MAC operations psa_mac_verify() and psa_mac_verify_setup(). Changes * Explicitly mark the fields mbedtls_ssl_session.exported and mbedtls_ssl_config.respect_cli_pref as private. This was an oversight during the run-up to the release of Mbed TLS 3.0. The fields were never intended to be public. * Implement multi-part CCM API. The multi-part functions: mbedtls_ccm_starts(), mbedtls_ccm_set_lengths(), mbedtls_ccm_update_ad(), mbedtls_ccm_update(), mbedtls_ccm_finish() were introduced in mbedTLS 3.0 release, however their implementation was postponed until now. Implemented functions support chunked data input for both CCM and CCM* algorithms. * Remove MBEDTLS_SSL_EXPORT_KEYS, making it always on and increasing the code size by about 80B on an M0 build. This option only gated an ability to set a callback, but was deemed unnecessary as it was yet another define to remember when writing tests, or test configurations. Fixes #4653. * Improve the performance of base64 constant-flow code. The result is still slower than the original non-constant-flow implementation, but much faster than the previous constant-flow implementation. Fixes #4814. * Ignore plaintext/ciphertext lengths for CCM*-no-tag operations. For CCM* encryption/decryption without authentication, input length will be ignored. * Indicate in the error returned if the nonce length used with ChaCha20-Poly1305 is invalid, and not just unsupported. * The mbedcrypto library includes a new source code module constant_time.c, containing various functions meant to resist timing side channel attacks. This module does not have a separate configuration option, and functions from this module will be included in the build as required. Currently most of the interface of this module is private and may change at any time. * The generated configuration-independent files are now automatically generated by the CMake build system on Unix-like systems. This is not yet supported when cross-compiling. = Mbed TLS 3.0.0 branch released 2021-07-07 API changes * Remove HAVEGE module. The design of HAVEGE makes it unsuitable for microcontrollers. Platforms with a more complex CPU usually have an operating system interface that provides better randomness. Instead of HAVEGE, declare OS or hardware RNG interfaces with mbedtls_entropy_add_source() and/or use an entropy seed file created securely during device provisioning. See https://mbed-tls.readthedocs.io/en/latest/kb/how-to/add-entropy-sources-to-entropy-pool/ for more information. * Add missing const attributes to API functions. * Remove helpers for the transition from Mbed TLS 1.3 to Mbed TLS 2.0: the header compat-1.3.h and the script rename.pl. * Remove certs module from the API. Transfer keys and certificates embedded in the library to the test component. This contributes to minimizing library API and discourages users from using unsafe keys in production. * Move alt helpers and definitions. Various helpers and definitions available for use in alt implementations have been moved out of the include/ directory and into the library/ directory. The files concerned are ecp_internal.h and rsa_internal.h which have also been renamed to ecp_internal_alt.h and rsa_alt_helpers.h respectively. * Move internal headers. Header files that were only meant for the library's internal use and were not meant to be used in application code have been moved out of the include/ directory. The headers concerned are bn_mul.h, aesni.h, padlock.h, entropy_poll.h and *_internal.h. * Drop support for parsing SSLv2 ClientHello (MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO). * Drop support for SSLv3 (MBEDTLS_SSL_PROTO_SSL3). * Drop support for TLS record-level compression (MBEDTLS_ZLIB_SUPPORT). * Drop support for RC4 TLS ciphersuites. * Drop support for single-DES ciphersuites. * Drop support for MBEDTLS_SSL_HW_RECORD_ACCEL. * Update AEAD output size macros to bring them in line with the PSA Crypto API version 1.0 spec. This version of the spec parameterizes them on the key type used, as well as the key bit-size in the case of PSA_AEAD_TAG_LENGTH. * Add configuration option MBEDTLS_X509_REMOVE_INFO which removes the mbedtls_x509_*_info(), mbedtls_debug_print_crt() as well as other functions and constants only used by those functions. This reduces the code footprint by several kB. * Remove SSL error codes `MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED` and `MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH` which are never returned from the public SSL API. * Remove `MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE` and return `MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL` instead. * The output parameter of mbedtls_sha512_finish, mbedtls_sha512, mbedtls_sha256_finish and mbedtls_sha256 now has a pointer type rather than array type. This removes spurious warnings in some compilers when outputting a SHA-384 or SHA-224 hash into a buffer of exactly the hash size. * Remove the MBEDTLS_TEST_NULL_ENTROPY config option. Fixes #4388. * The interface of the GCM module has changed to remove restrictions on how the input to multipart operations is broken down. mbedtls_gcm_finish() now takes extra output parameters for the last partial output block. mbedtls_gcm_update() now takes extra parameters for the output length. The software implementation always produces the full output at each call to mbedtls_gcm_update(), but alternative implementations activated by MBEDTLS_GCM_ALT may delay partial blocks to the next call to mbedtls_gcm_update() or mbedtls_gcm_finish(). Furthermore, applications no longer pass the associated data to mbedtls_gcm_starts(), but to the new function mbedtls_gcm_update_ad(). These changes are backward compatible for users of the cipher API. * Replace MBEDTLS_SHA512_NO_SHA384 config option with MBEDTLS_SHA384_C. This separates config option enabling the SHA384 algorithm from option enabling the SHA512 algorithm. Fixes #4034. * Introduce MBEDTLS_SHA224_C. This separates config option enabling the SHA224 algorithm from option enabling SHA256. * The getter and setter API of the SSL session cache (used for session-ID based session resumption) has changed to that of a key-value store with keys being session IDs and values being opaque instances of `mbedtls_ssl_session`. * Remove the mode parameter from RSA operation functions. Signature and decryption functions now always use the private key and verification and encryption use the public key. Verification functions also no longer have RNG parameters. * Modify semantics of `mbedtls_ssl_conf_[opaque_]psk()`: In Mbed TLS 2.X, the API prescribes that later calls overwrite the effect of earlier calls. In Mbed TLS 3.0, calling `mbedtls_ssl_conf_[opaque_]psk()` more than once will fail, leaving the PSK that was configured first intact. Support for more than one PSK may be added in 3.X. * The function mbedtls_x509write_csr_set_extension() has an extra parameter which allows to mark an extension as critical. Fixes #4055. * For multi-part AEAD operations with the cipher module, calling mbedtls_cipher_finish() is now mandatory. Previously the documentation was unclear on this point, and this function happened to never do anything with the currently implemented AEADs, so in practice it was possible to skip calling it, which is no longer supported. * The option MBEDTLS_ECP_FIXED_POINT_OPTIM use pre-computed comb tables instead of computing tables in runtime. Thus, this option now increase code size, and it does not increase RAM usage in runtime anymore. * Remove the SSL APIs mbedtls_ssl_get_input_max_frag_len() and mbedtls_ssl_get_output_max_frag_len(), and add a new API mbedtls_ssl_get_max_in_record_payload(), complementing the existing mbedtls_ssl_get_max_out_record_payload(). Uses of mbedtls_ssl_get_input_max_frag_len() and mbedtls_ssl_get_input_max_frag_len() should be replaced by mbedtls_ssl_get_max_in_record_payload() and mbedtls_ssl_get_max_out_record_payload(), respectively. * mbedtls_rsa_init() now always selects the PKCS#1v1.5 encoding for an RSA key. To use an RSA key with PSS or OAEP, call mbedtls_rsa_set_padding() after initializing the context. mbedtls_rsa_set_padding() now returns an error if its parameters are invalid. * Replace MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE by a runtime configuration function mbedtls_ssl_conf_preference_order(). Fixes #4398. * Instead of accessing the len field of a DHM context, which is no longer supported, use the new function mbedtls_dhm_get_len() . * In modules that implement cryptographic hash functions, many functions mbedtls_xxx() now return int instead of void, and the corresponding function mbedtls_xxx_ret() which was identical except for returning int has been removed. This also concerns mbedtls_xxx_drbg_update(). See the migration guide for more information. Fixes #4212. * For all functions that take a random number generator (RNG) as a parameter, this parameter is now mandatory (that is, NULL is not an acceptable value). Functions which previously accepted NULL and now reject it are: the X.509 CRT and CSR writing functions; the PK and RSA sign and decrypt function; mbedtls_rsa_private(); the functions in DHM and ECDH that compute the shared secret; the scalar multiplication functions in ECP. * The following functions now require an RNG parameter: mbedtls_ecp_check_pub_priv(), mbedtls_pk_check_pair(), mbedtls_pk_parse_key(), mbedtls_pk_parse_keyfile(). * mbedtls_ssl_conf_export_keys_ext_cb() and mbedtls_ssl_conf_export_keys_cb() have been removed and replaced by a new API mbedtls_ssl_set_export_keys_cb(). Raw keys and IVs are no longer passed to the callback. Further, callbacks now receive an additional parameter indicating the type of secret that's being exported, paving the way for the larger number of secrets in TLS 1.3. Finally, the key export callback and context are now connection-specific. * Signature functions in the RSA and PK modules now require the hash length parameter to be the size of the hash input. For RSA signatures other than raw PKCS#1 v1.5, this must match the output size of the specified hash algorithm. * The functions mbedtls_pk_sign(), mbedtls_pk_sign_restartable(), mbedtls_ecdsa_write_signature() and mbedtls_ecdsa_write_signature_restartable() now take an extra parameter indicating the size of the output buffer for the signature. * Implement one-shot cipher functions, psa_cipher_encrypt and psa_cipher_decrypt, according to the PSA Crypto API 1.0.0 specification. * Direct access to fields of structures declared in public headers is no longer supported except for fields that are documented public. Use accessor functions instead. For more information, see the migration guide entry "Most structure fields are now private". * mbedtls_ssl_get_session_pointer() has been removed, and mbedtls_ssl_{set,get}_session() may now only be called once for any given SSL context. Default behavior changes * Enable by default the functionalities which have no reason to be disabled. They are: ARIA block cipher, CMAC mode, elliptic curve J-PAKE library and Key Wrapping mode as defined in NIST SP 800-38F. Fixes #4036. * Some default policies for X.509 certificate verification and TLS have changed: curves and hashes weaker than 255 bits are no longer accepted by default. The default order in TLS now favors faster curves over larger curves. Requirement changes * The library now uses the %zu format specifier with the printf() family of functions, so requires a toolchain that supports it. This change does not affect the maintained LTS branches, so when contributing changes please bear this in mind and do not add them to backported code. * If you build the development version of Mbed TLS, rather than an official release, some configuration-independent files are now generated at build time rather than checked into source control. This includes some library source files as well as the Visual Studio solution. Perl, Python 3 and a C compiler for the host platform are required. See “Generated source files in the development branch” in README.md for more information. * Refresh the minimum supported versions of tools to build the library. CMake versions older than 3.10.2 and Python older than 3.6 are no longer supported. Removals * Remove the MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES compile-time option, which was off by default. Users should not trust certificates signed with SHA-1 due to the known attacks against SHA-1. If needed, SHA-1 certificates can still be verified by using a custom verification profile. * Removed deprecated things in psa/crypto_compat.h. Fixes #4284 * Removed deprecated functions from hashing modules. Fixes #4280. * Remove PKCS#11 library wrapper. PKCS#11 has limited functionality, lacks automated tests and has scarce documentation. Also, PSA Crypto provides a more flexible private key management. More details on PCKS#11 wrapper removal can be found in the mailing list https://lists.trustedfirmware.org/pipermail/mbed-tls/2020-April/000024.html * Remove deprecated error codes. Fix #4283 * Remove MBEDTLS_ENABLE_WEAK_CIPHERSUITES configuration option. Fixes #4416. * Remove the MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES compile-time option. This option has been inactive for a long time. Please use the `lifetime` parameter of `mbedtls_ssl_ticket_setup()` instead. * Remove the following deprecated functions and constants of hex-encoded primes based on RFC 5114 and RFC 3526 from library code and tests: mbedtls_aes_encrypt(), mbedtls_aes_decrypt(), mbedtls_mpi_is_prime(), mbedtls_cipher_auth_encrypt(), mbedtls_cipher_auth_decrypt(), mbedtls_ctr_drbg_update(), mbedtls_hmac_drbg_update(), mbedtls_ecdsa_write_signature_det(), mbedtls_ecdsa_sign_det(), mbedtls_ssl_conf_dh_param(), mbedtls_ssl_get_max_frag_len(), MBEDTLS_DHM_RFC5114_MODP_2048_P, MBEDTLS_DHM_RFC5114_MODP_2048_G, MBEDTLS_DHM_RFC3526_MODP_2048_P, MBEDTLS_DHM_RFC3526_MODP_2048_G, MBEDTLS_DHM_RFC3526_MODP_3072_P, MBEDTLS_DHM_RFC3526_MODP_3072_G, MBEDTLS_DHM_RFC3526_MODP_4096_P, MBEDTLS_DHM_RFC3526_MODP_4096_G. Remove the deprecated file: include/mbedtls/net.h. Fixes #4282. * Remove MBEDTLS_SSL_MAX_CONTENT_LEN configuration option, since MBEDTLS_SSL_IN_CONTENT_LEN and MBEDTLS_SSL_OUT_CONTENT_LEN replace it. Fixes #4362. * Remove the MBEDTLS_SSL_RECORD_CHECKING option and enable by default its previous action. Fixes #4361. * Remove support for TLS 1.0, TLS 1.1 and DTLS 1.0, as well as support for CBC record splitting, fallback SCSV, and the ability to configure ciphersuites per version, which are no longer relevant. This removes the configuration options MBEDTLS_SSL_PROTO_TLS1, MBEDTLS_SSL_PROTO_TLS1_1, MBEDTLS_SSL_CBC_RECORD_SPLITTING and MBEDTLS_SSL_FALLBACK_SCSV as well as the functions mbedtls_ssl_conf_cbc_record_splitting(), mbedtls_ssl_get_key_exchange_md_ssl_tls(), mbedtls_ssl_conf_fallback(), and mbedtls_ssl_conf_ciphersuites_for_version(). Fixes #4286. * The RSA module no longer supports private-key operations with the public key and vice versa. * Remove the MBEDTLS_SSL_DTLS_BADMAC_LIMIT config.h option. Fixes #4403. * Remove all the 3DES ciphersuites: MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA. Remove the MBEDTLS_REMOVE_3DES_CIPHERSUITES option which is no longer relevant. Fixes #4367. * Remove the MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 option and let the code behave as if it was always disabled. Fixes #4386. * Remove MBEDTLS_ECDH_LEGACY_CONTEXT config option since this was purely for backward compatibility which is no longer supported. Addresses #4404. * Remove the following macros: MBEDTLS_CHECK_PARAMS, MBEDTLS_CHECK_PARAMS_ASSERT, MBEDTLS_PARAM_FAILED, MBEDTLS_PARAM_FAILED_ALT. Fixes #4313. * Remove the MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION config.h option. The mbedtls_x509_crt_parse_der_with_ext_cb() is the way to go for migration path. Fixes #4378. * Remove the MBEDTLS_X509_CHECK_KEY_USAGE and MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE config.h options and let the code behave as if they were always enabled. Fixes #4405. * MBEDTLS_ECP_MAX_BITS is no longer a configuration option because it is now determined automatically based on supported curves. * Remove the following functions: mbedtls_timing_self_test(), mbedtls_hardclock_poll(), mbedtls_timing_hardclock() and mbedtls_set_alarm(). Fixes #4083. * The configuration option MBEDTLS_ECP_NO_INTERNAL_RNG has been removed as it no longer had any effect. * Remove all support for MD2, MD4, RC4, Blowfish and XTEA. This removes the corresponding modules and all their APIs and related configuration options. Fixes #4084. * Remove MBEDTLS_SSL_TRUNCATED_HMAC and also remove MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT config option. Users are better served by using a CCM-8 ciphersuite than a CBC ciphersuite with truncated HMAC. See issue #4341 for more details. * Remove the compile-time option MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE. Features * Add mbedtls_rsa_rsassa_pss_sign_ext() function allowing to generate a signature with a specific salt length. This function allows to validate test cases provided in the NIST's CAVP test suite. Contributed by Cédric Meuter in PR #3183. * Added support for built-in driver keys through the PSA opaque crypto driver interface. Refer to the documentation of MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS for more information. * Implement psa_sign_message() and psa_verify_message(). * The multi-part GCM interface (mbedtls_gcm_update() or mbedtls_cipher_update()) no longer requires the size of partial inputs to be a multiple of 16. * The multi-part GCM interface now supports chunked associated data through multiple calls to mbedtls_gcm_update_ad(). * The new function mbedtls_mpi_random() generates a random value in a given range uniformly. * Alternative implementations of the AES, DHM, ECJPAKE, ECP, RSA and timing modules had undocumented constraints on their context types. These constraints have been relaxed. See docs/architecture/alternative-implementations.md for the remaining constraints. * The new functions mbedtls_dhm_get_len() and mbedtls_dhm_get_bitlen() query the size of the modulus in a Diffie-Hellman context. * The new function mbedtls_dhm_get_value() copy a field out of a Diffie-Hellman context. * Use the new function mbedtls_ecjpake_set_point_format() to select the point format for ECJPAKE instead of accessing the point_format field directly, which is no longer supported. * Implement psa_mac_compute() and psa_mac_verify() as defined in the PSA Cryptograpy API 1.0.0 specification. Security * Fix a bias in the generation of finite-field Diffie-Hellman-Merkle (DHM) private keys and of blinding values for DHM and elliptic curves (ECP) computations. Reported by FlorianF89 in #4245. * Fix a potential side channel vulnerability in ECDSA ephemeral key generation. An adversary who is capable of very precise timing measurements could learn partial information about the leading bits of the nonce used for the signature, allowing the recovery of the private key after observing a large number of signature operations. This completes a partial fix in Mbed TLS 2.20.0. * Fix an issue where an adversary with access to precise enough information about memory accesses (typically, an untrusted operating system attacking a secure enclave) could recover an RSA private key after observing the victim performing a single private-key operation. Found and reported by Zili KOU, Wenjian HE, Sharad Sinha, and Wei ZHANG. * Fix an issue where an adversary with access to precise enough timing information (typically, a co-located process) could recover a Curve25519 or Curve448 static ECDH key after inputting a chosen public key and observing the victim performing the corresponding private-key operation. Found and reported by Leila Batina, Lukas Chmielewski, Björn Haase, Niels Samwel and Peter Schwabe. Bugfix * Fix premature fopen() call in mbedtls_entropy_write_seed_file which may lead to the seed file corruption in case if the path to the seed file is equal to MBEDTLS_PLATFORM_STD_NV_SEED_FILE. Contributed by Victor Krasnoshchok in #3616. * PSA functions creating a key now return PSA_ERROR_INVALID_ARGUMENT rather than PSA_ERROR_INVALID_HANDLE when the identifier specified for the key to create is not valid, bringing them in line with version 1.0.0 of the specification. Fix #4271. * Add printf function attributes to mbedtls_debug_print_msg to ensure we get printf format specifier warnings. * PSA functions other than psa_open_key now return PSA_ERROR_INVALID_HANDLE rather than PSA_ERROR_DOES_NOT_EXIST for an invalid handle, bringing them in line with version 1.0.0 of the specification. Fix #4162. * Fix a bug in ECDSA that would cause it to fail when the hash is all-bits zero. Fixes #1792 * Fix some cases in the bignum module where the library constructed an unintended representation of the value 0 which was not processed correctly by some bignum operations. This could happen when mbedtls_mpi_read_string() was called on "-0", or when mbedtls_mpi_mul_mpi() and mbedtls_mpi_mul_int() was called with one of the arguments being negative and the other being 0. Fixes #4643. * Fix a compilation error when MBEDTLS_ECP_RANDOMIZE_MXZ_ALT is defined. Fixes #4217. * Fix an incorrect error code when parsing a PKCS#8 private key. * In a TLS client, enforce the Diffie-Hellman minimum parameter size set with mbedtls_ssl_conf_dhm_min_bitlen() precisely. Before, the minimum size was rounded down to the nearest multiple of 8. * In library/net_sockets.c, _POSIX_C_SOURCE and _XOPEN_SOURCE are defined to specific values. If the code is used in a context where these are already defined, this can result in a compilation error. Instead, assume that if they are defined, the values will be adequate to build Mbed TLS. * With MBEDTLS_PSA_CRYPTO_C disabled, some functions were getting built nonetheless, resulting in undefined reference errors when building a shared library. Reported by Guillermo Garcia M. in #4411. * The cipher suite TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384 was not available when SHA-1 was disabled and was offered when SHA-1 was enabled but SHA-384 was disabled. Fix the dependency. Fixes #4472. * Do not offer SHA384 cipher suites when SHA-384 is disabled. Fixes #4499. * Fix test suite code on platforms where int32_t is not int, such as Arm Cortex-M. Fixes #4530. * Fix some issues affecting MBEDTLS_ARIA_ALT implementations: a misplaced directive in a header and a missing initialization in the self-test. * Fix a missing initialization in the Camellia self-test, affecting MBEDTLS_CAMELLIA_ALT implementations. * Restore the ability to configure PSA via Mbed TLS options to support RSA key pair operations but exclude RSA key generation. When MBEDTLS_GENPRIME is not defined PSA will no longer attempt to use mbedtls_rsa_gen_key(). Fixes #4512. * Fix a regression introduced in 2.24.0 which broke (D)TLS CBC ciphersuites (when the encrypt-then-MAC extension is not in use) with some ALT implementations of the underlying hash (SHA-1, SHA-256, SHA-384), causing the affected side to wrongly reject valid messages. Fixes #4118. * Remove outdated check-config.h check that prevented implementing the timing module on Mbed OS. Fixes #4633. * Fix PSA_ALG_TLS12_PRF and PSA_ALG_TLS12_PSK_TO_MS being too permissive about missing inputs. * Fix mbedtls_net_poll() and mbedtls_net_recv_timeout() often failing with MBEDTLS_ERR_NET_POLL_FAILED on Windows. Fixes #4465. * Fix a resource leak in a test suite with an alternative AES implementation. Fixes #4176. * Fix a crash in mbedtls_mpi_debug_mpi on a bignum having 0 limbs. This could notably be triggered by setting the TLS debug level to 3 or above and using a Montgomery curve for the key exchange. Reported by lhuang04 in #4578. Fixes #4608. * psa_verify_hash() was relying on implementation-specific behavior of mbedtls_rsa_rsassa_pss_verify() and was causing failures in some _ALT implementations. This reliance is now removed. Fixes #3990. * Disallow inputs of length different from the corresponding hash when signing or verifying with PSA_ALG_RSA_PSS (The PSA Crypto API mandates that PSA_ALG_RSA_PSS uses the same hash throughout the algorithm.) * Fix a null pointer dereference when mbedtls_mpi_exp_mod() was called with A=0 represented with 0 limbs. Up to and including Mbed TLS 2.26, this bug could not be triggered by code that constructed A with one of the mbedtls_mpi_read_xxx functions (including in particular TLS code) since those always built an mpi object with at least one limb. Credit to OSS-Fuzz. Fixes #4641. * Fix mbedtls_mpi_gcd(G,A,B) when the value of B is zero. This had no effect on Mbed TLS's internal use of mbedtls_mpi_gcd(), but may affect applications that call mbedtls_mpi_gcd() directly. Fixes #4642. * The PSA API no longer allows the creation or destruction of keys with a read-only lifetime. The persistence level PSA_KEY_PERSISTENCE_READ_ONLY can now only be used as intended, for keys that cannot be modified through normal use of the API. * When MBEDTLS_PSA_CRYPTO_SPM is enabled, crypto_spe.h was not included in all the right places. Include it from crypto_platform.h, which is the natural place. Fixes #4649. * Fix which alert is sent in some cases to conform to the applicable RFC: on an invalid Finished message value, an invalid max_fragment_length extension, or an unsupported extension used by the server. * Correct (change from 12 to 13 bytes) the value of the macro describing the maximum nonce length returned by psa_aead_generate_nonce(). Changes * Fix the setting of the read timeout in the DTLS sample programs. * Add extra printf compiler warning flags to builds. * Fix memsan build false positive in x509_crt.c with clang 11 * Alternative implementations of CMAC may now opt to not support 3DES as a CMAC block cipher, and still pass the CMAC self test. * Remove the AES sample application programs/aes/aescrypt2 which shows bad cryptographic practice. Fix #1906. * Remove configs/config-psa-crypto.h, which no longer had any intended differences from the default configuration, but had accidentally diverged. * When building the test suites with GNU make, invoke python3 or python, not python2, which is no longer supported upstream. * fix build failure on MinGW toolchain when __USE_MING_ANSI_STDIO is on. When that flag is on, standard GNU C printf format specifiers should be used. * Replace MBEDTLS_SSL_CID_PADDING_GRANULARITY and MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY with a new single unified option MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY. Fixes #4335. * Reduce the default value of MBEDTLS_ECP_WINDOW_SIZE. This reduces RAM usage during ECC operations at a negligible performance cost. * mbedtls_mpi_read_binary(), mbedtls_mpi_read_binary_le() and mbedtls_mpi_read_string() now construct an mbedtls_mpi object with 0 limbs when their input has length 0. Note that this is an implementation detail and can change at any time, so this change should be transparent, but it may result in mbedtls_mpi_write_binary() or mbedtls_mpi_write_string() now writing an empty string where it previously wrote one or more zero digits when operating from values constructed with an mpi_read function and some mpi operations. * Add CMake package config generation for CMake projects consuming Mbed TLS. * config.h has been split into build_info.h and mbedtls_config.h build_info.h is intended to be included from C code directly, while mbedtls_config.h is intended to be edited by end users wishing to change the build configuration, and should generally only be included from build_info.h. * The handling of MBEDTLS_CONFIG_FILE has been moved into build_info.h. * A config file version symbol, MBEDTLS_CONFIG_VERSION was introduced. Defining it to a particular value will ensure that Mbed TLS interprets the config file in a way that's compatible with the config file format used by the Mbed TLS release whose MBEDTLS_VERSION_NUMBER has the same value. The only value supported by Mbed TLS 3.0.0 is 0x03000000. * Various changes to which alert and/or error code may be returned * during the TLS handshake. * Implicitly add PSA_KEY_USAGE_SIGN_MESSAGE key usage policy flag when PSA_KEY_USAGE_SIGN_HASH flag is set and PSA_KEY_USAGE_VERIFY_MESSAGE flag when PSA_KEY_USAGE_VERIFY_HASH flag is set. This usage flag extension is also applied when loading a key from storage. = mbed TLS 2.26.0 branch released 2021-03-08 API changes * Renamed the PSA Crypto API output buffer size macros to bring them in line with version 1.0.0 of the specification. * The API glue function mbedtls_ecc_group_of_psa() now takes the curve size in bits rather than bytes, with an additional flag to indicate if the size may have been rounded up to a whole number of bytes. * Renamed the PSA Crypto API AEAD tag length macros to bring them in line with version 1.0.0 of the specification. Default behavior changes * In mbedtls_rsa_context objects, the ver field was formerly documented as always 0. It is now reserved for internal purposes and may take different values. New deprecations * PSA_KEY_EXPORT_MAX_SIZE, PSA_HASH_SIZE, PSA_MAC_FINAL_SIZE, PSA_BLOCK_CIPHER_BLOCK_SIZE, PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE and PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN have been renamed, and the old names deprecated. * PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH and PSA_ALG_AEAD_WITH_TAG_LENGTH have been renamed, and the old names deprecated. Features * The PSA crypto subsystem can now use HMAC_DRBG instead of CTR_DRBG. CTR_DRBG is used by default if it is available, but you can override this choice by setting MBEDTLS_PSA_HMAC_DRBG_MD_TYPE at compile time. Fix #3354. * Automatic fallback to a software implementation of ECP when MBEDTLS_ECP_xxx_ALT accelerator hooks are in use can now be turned off through setting the new configuration flag MBEDTLS_ECP_NO_FALLBACK. * The PSA crypto subsystem can now be configured to use less static RAM by tweaking the setting for the maximum amount of keys simultaneously in RAM. MBEDTLS_PSA_KEY_SLOT_COUNT sets the maximum number of volatile keys that can exist simultaneously. It has a sensible default if not overridden. * Partial implementation of the PSA crypto driver interface: Mbed TLS can now use an external random generator instead of the library's own entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG and see the documentation of mbedtls_psa_external_get_random() for details. * Applications using both mbedtls_xxx and psa_xxx functions (for example, applications using TLS and MBEDTLS_USE_PSA_CRYPTO) can now use the PSA random generator with mbedtls_xxx functions. See the documentation of mbedtls_psa_get_random() for details. * In the PSA API, the policy for a MAC or AEAD algorithm can specify a minimum MAC or tag length thanks to the new wildcards PSA_ALG_AT_LEAST_THIS_LENGTH_MAC and PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG. Security * Fix a security reduction in CTR_DRBG when the initial seeding obtained a nonce from entropy. Applications were affected if they called mbedtls_ctr_drbg_set_nonce_len(), if they called mbedtls_ctr_drbg_set_entropy_len() with a size that was 3/2 times the key length, or when the entropy module uses SHA-256 and CTR_DRBG uses AES-256. In such cases, a random nonce was necessary to achieve the advertised security strength, but the code incorrectly used a constant instead of entropy from the nonce. Found by John Stroebel in #3819 and fixed in #3973. * Fix a buffer overflow in mbedtls_mpi_sub_abs() when calculating |A| - |B| where |B| is larger than |A| and has more limbs (so the function should return MBEDTLS_ERR_MPI_NEGATIVE_VALUE). Only applications calling mbedtls_mpi_sub_abs() directly are affected: all calls inside the library were safe since this function is only called with |A| >= |B|. Reported by Guido Vranken in #4042. * Fix an errorneous estimation for an internal buffer in mbedtls_pk_write_key_pem(). If MBEDTLS_MPI_MAX_SIZE is set to an odd value the function might fail to write a private RSA keys of the largest supported size. Found by Daniel Otte, reported in #4093 and fixed in #4094. * Fix a stack buffer overflow with mbedtls_net_poll() and mbedtls_net_recv_timeout() when given a file descriptor that is beyond FD_SETSIZE. Reported by FigBug in #4169. * Guard against strong local side channel attack against base64 tables by making access aceess to them use constant flow code. Bugfix * Fix use-after-scope error in programs/ssl/ssl_client2.c and ssl_server2.c * Fix memory leak that occured when calling psa_close_key() on a wrapped key with MBEDTLS_PSA_CRYPTO_SE_C defined. * Fix an incorrect error code if an RSA private operation glitched. * Fix a memory leak in an error case in psa_generate_derived_key_internal(). * Fix a resource leak in CTR_DRBG and HMAC_DRBG when MBEDTLS_THREADING_C is enabled, on platforms where initializing a mutex allocates resources. This was a regression introduced in the previous release. Reported in #4017, #4045 and #4071. * Ensure that calling mbedtls_rsa_free() or mbedtls_entropy_free() twice is safe. This happens for RSA when some Mbed TLS library functions fail. Such a double-free was not safe when MBEDTLS_THREADING_C was enabled on platforms where freeing a mutex twice is not safe. * Fix a resource leak in a bad-arguments case of mbedtls_rsa_gen_key() when MBEDTLS_THREADING_C is enabled on platforms where initializing a mutex allocates resources. * Fixes a bug where, if the library was configured to include support for both the old SE interface and the new PSA driver interface, external keys were not loaded from storage. This was fixed by #3996. * This change makes 'mbedtls_x509write_crt_set_basic_constraints' consistent with RFC 5280 4.2.1.9 which says: "Conforming CAs MUST include this extension in all CA certificates that contain public keys used to validate digital signatures on certificates and MUST mark the extension as critical in such certificates." Previous to this change, the extension was always marked as non-critical. This was fixed by #3698. Changes * A new library C file psa_crypto_client.c has been created to contain the PSA code needed by a PSA crypto client when the PSA crypto implementation is not included into the library. * On recent enough versions of FreeBSD and DragonFlyBSD, the entropy module now uses the getrandom syscall instead of reading from /dev/urandom. = mbed TLS 2.25.0 branch released 2020-12-11 API changes * The numerical values of the PSA Crypto API macros have been updated to conform to version 1.0.0 of the specification. * PSA_ALG_STREAM_CIPHER replaces PSA_ALG_CHACHA20 and PSA_ALG_ARC4. The underlying stream cipher is determined by the key type (PSA_KEY_TYPE_CHACHA20 or PSA_KEY_TYPE_ARC4). * The functions mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_decrypt() no longer accept NIST_KW contexts, as they have no way to check if the output buffer is large enough. Please use mbedtls_cipher_auth_encrypt_ext() and mbedtls_cipher_auth_decrypt_ext() instead. Credit to OSS-Fuzz and Cryptofuzz. Fixes #3665. Requirement changes * Update the minimum required CMake version to 2.8.12. This silences a warning on CMake 3.19.0. #3801 New deprecations * PSA_ALG_CHACHA20 and PSA_ALG_ARC4 have been deprecated. Use PSA_ALG_STREAM_CIPHER instead. * The functions mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_decrypt() are deprecated in favour of the new functions mbedtls_cipher_auth_encrypt_ext() and mbedtls_cipher_auth_decrypt_ext(). Please note that with AEAD ciphers, these new functions always append the tag to the ciphertext, and include the tag in the ciphertext length. Features * Partial implementation of the new PSA Crypto accelerator APIs. (Symmetric ciphers, asymmetric signing/verification and key generation, validate_key entry point, and export_public_key interface.) * Add support for ECB to the PSA cipher API. * In PSA, allow using a key declared with a base key agreement algorithm in combined key agreement and derivation operations, as long as the key agreement algorithm in use matches the algorithm the key was declared with. This is currently non-standard behaviour, but expected to make it into a future revision of the PSA Crypto standard. * Add MBEDTLS_TARGET_PREFIX CMake variable, which is prefixed to the mbedtls, mbedcrypto, mbedx509 and apidoc CMake target names. This can be used by external CMake projects that include this one to avoid CMake target name clashes. The default value of this variable is "", so default target names are unchanged. * Add support for DTLS-SRTP as defined in RFC 5764. Contributed by Johan Pascal, improved by Ron Eldor. * In the PSA API, it is no longer necessary to open persistent keys: operations now accept the key identifier. The type psa_key_handle_t is now identical to psa_key_id_t instead of being platform-defined. This bridges the last major gap to compliance with the PSA Cryptography specification version 1.0.0. Opening persistent keys is still supported for backward compatibility, but will be deprecated and later removed in future releases. * PSA_AEAD_NONCE_LENGTH, PSA_AEAD_NONCE_MAX_SIZE, PSA_CIPHER_IV_LENGTH and PSA_CIPHER_IV_MAX_SIZE macros have been added as defined in version 1.0.0 of the PSA Crypto API specification. Security * The functions mbedtls_cipher_auth_encrypt() and mbedtls_cipher_auth_decrypt() would write past the minimum documented size of the output buffer when used with NIST_KW. As a result, code using those functions as documented with NIST_KW could have a buffer overwrite of up to 15 bytes, with consequences ranging up to arbitrary code execution depending on the location of the output buffer. * Limit the size of calculations performed by mbedtls_mpi_exp_mod to MBEDTLS_MPI_MAX_SIZE to prevent a potential denial of service when generating Diffie-Hellman key pairs. Credit to OSS-Fuzz. * A failure of the random generator was ignored in mbedtls_mpi_fill_random(), which is how most uses of randomization in asymmetric cryptography (including key generation, intermediate value randomization and blinding) are implemented. This could cause failures or the silent use of non-random values. A random generator can fail if it needs reseeding and cannot not obtain entropy, or due to an internal failure (which, for Mbed TLS's own CTR_DRBG or HMAC_DRBG, can only happen due to a misconfiguration). * Fix a compliance issue whereby we were not checking the tag on the algorithm parameters (only the size) when comparing the signature in the description part of the cert to the real signature. This meant that a NULL algorithm parameters entry would look identical to an array of REAL (size zero) to the library and thus the certificate would be considered valid. However, if the parameters do not match in *any* way then the certificate should be considered invalid, and indeed OpenSSL marks these certs as invalid when mbedtls did not. Many thanks to guidovranken who found this issue via differential fuzzing and reported it in #3629. * Zeroising of local buffers and variables which are used for calculations in mbedtls_pkcs5_pbkdf2_hmac(), mbedtls_internal_sha*_process(), mbedtls_internal_md*_process() and mbedtls_internal_ripemd160_process() functions to erase sensitive data from memory. Reported by Johan Malmgren and Johan Uppman Bruce from Sectra. Bugfix * Fix an invalid (but nonzero) return code from mbedtls_pk_parse_subpubkey() when the input has trailing garbage. Fixes #2512. * Fix build failure in configurations where MBEDTLS_USE_PSA_CRYPTO is enabled but ECDSA is disabled. Contributed by jdurkop. Fixes #3294. * Include the psa_constant_names generated source code in the source tree instead of generating it at build time. Fixes #3524. * Fix rsa_prepare_blinding() to retry when the blinding value is not invertible (mod N), instead of returning MBEDTLS_ERR_RSA_RNG_FAILED. This addresses a regression but is rare in practice (approx. 1 in 2/sqrt(N)). Found by Synopsys Coverity, fix contributed by Peter Kolbus (Garmin). Fixes #3647. * Use socklen_t on Android and other POSIX-compliant system * Fix the build when the macro _GNU_SOURCE is defined to a non-empty value. Fix #3432. * Consistently return PSA_ERROR_INVALID_ARGUMENT on invalid cipher input sizes (instead of PSA_ERROR_BAD_STATE in some cases) to make the psa_cipher_* functions compliant with the PSA Crypto API specification. * mbedtls_ecp_curve_list() now lists Curve25519 and Curve448 under the names "x25519" and "x448". These curves support ECDH but not ECDSA. If you need only the curves that support ECDSA, filter the list with mbedtls_ecdsa_can_do(). * Fix psa_generate_key() returning an error when asked to generate an ECC key pair on Curve25519 or secp244k1. * Fix psa_key_derivation_output_key() to allow the output of a combined key agreement and subsequent key derivation operation to be used as a key inside of the PSA Crypto core. * Fix handling of EOF against 0xff bytes and on platforms with unsigned chars. Fixes a build failure on platforms where char is unsigned. Fixes #3794. * Fix an off-by-one error in the additional data length check for CCM, which allowed encryption with a non-standard length field. Fixes #3719. * Correct the default IV size for mbedtls_cipher_info_t structures using MBEDTLS_MODE_ECB to 0, since ECB mode ciphers don't use IVs. * Make arc4random_buf available on NetBSD and OpenBSD when _POSIX_C_SOURCE is defined. Fix contributed in #3571. * Fix conditions for including string.h in error.c. Fixes #3866. * psa_set_key_id() now also sets the lifetime to persistent for keys located in a secure element. * Attempting to create a volatile key with a non-zero key identifier now fails. Previously the key identifier was just ignored when creating a volatile key. * Attempting to create or register a key with a key identifier in the vendor range now fails. * Fix build failures on GCC 11. Fixes #3782. * Add missing arguments of debug message in mbedtls_ssl_decrypt_buf. * Fix a memory leak in mbedtls_mpi_sub_abs() when the result was negative (an error condition) and the second operand was aliased to the result. * Fix a case in elliptic curve arithmetic where an out-of-memory condition could go undetected, resulting in an incorrect result. * In CTR_DRBG and HMAC_DRBG, don't reset the reseed interval in seed(). Fixes #2927. * In PEM writing functions, fill the trailing part of the buffer with null bytes. This guarantees that the corresponding parsing function can read the buffer back, which was the case for mbedtls_x509write_{crt,csr}_pem until this property was inadvertently broken in Mbed TLS 2.19.0. Fixes #3682. * Fix a build failure that occurred with the MBEDTLS_AES_SETKEY_DEC_ALT option on. In this configuration key management methods that are required for MBEDTLS_CIPHER_MODE_XTS were excluded from the build and made it fail. Fixes #3818. Reported by John Stroebel. Changes * Reduce stack usage significantly during sliding window exponentiation. Reported in #3591 and fix contributed in #3592 by Daniel Otte. * The PSA persistent storage format is updated to always store the key bits attribute. No automatic upgrade path is provided. Previously stored keys must be erased, or manually upgraded based on the key storage format specification (docs/architecture/mbed-crypto-storage-specification.md). Fixes #3740. * Remove the zeroization of a pointer variable in AES rounds. It was valid but spurious and misleading since it looked like a mistaken attempt to zeroize the pointed-to buffer. Reported by Antonio de la Piedra, CEA Leti, France. = mbed TLS 2.24.0 branch released 2020-09-01 API changes * In the PSA API, rename the types of elliptic curve and Diffie-Hellman group families to psa_ecc_family_t and psa_dh_family_t, in line with the PSA Crypto API specification version 1.0.0. Rename associated macros as well: PSA_ECC_CURVE_xxx renamed to PSA_ECC_FAMILY_xxx PSA_DH_GROUP_xxx renamed to PSA_DH_FAMILY_xxx PSA_KEY_TYPE_GET_CURVE renamed to to PSA_KEY_TYPE_ECC_GET_FAMILY PSA_KEY_TYPE_GET_GROUP renamed to PSA_KEY_TYPE_DH_GET_FAMILY Default behavior changes * Stop storing persistent information about externally stored keys created through PSA Crypto with a volatile lifetime. Reported in #3288 and contributed by Steven Cooreman in #3382. Features * The new function mbedtls_ecp_write_key() exports private ECC keys back to a byte buffer. It is the inverse of the existing mbedtls_ecp_read_key(). * Support building on e2k (Elbrus) architecture: correctly enable -Wformat-signedness, and fix the code that causes signed-one-bit-field and sign-compare warnings. Contributed by makise-homura (Igor Molchanov) . Security * Fix a vulnerability in the verification of X.509 certificates when matching the expected common name (the cn argument of mbedtls_x509_crt_verify()) with the actual certificate name: when the subjecAltName extension is present, the expected name was compared to any name in that extension regardless of its type. This means that an attacker could for example impersonate a 4-bytes or 16-byte domain by getting a certificate for the corresponding IPv4 or IPv6 (this would require the attacker to control that IP address, though). Similar attacks using other subjectAltName name types might be possible. Found and reported by kFYatek in #3498. * When checking X.509 CRLs, a certificate was only considered as revoked if its revocationDate was in the past according to the local clock if available. In particular, on builds without MBEDTLS_HAVE_TIME_DATE, certificates were never considered as revoked. On builds with MBEDTLS_HAVE_TIME_DATE, an attacker able to control the local clock (for example, an untrusted OS attacking a secure enclave) could prevent revocation of certificates via CRLs. Fixed by no longer checking the revocationDate field, in accordance with RFC 5280. Reported by yuemonangong in #3340. Reported independently and fixed by Raoul Strackx and Jethro Beekman in #3433. * In (D)TLS record decryption, when using a CBC ciphersuites without the Encrypt-then-Mac extension, use constant code flow memory access patterns to extract and check the MAC. This is an improvement to the existing countermeasure against Lucky 13 attacks. The previous countermeasure was effective against network-based attackers, but less so against local attackers. The new countermeasure defends against local attackers, even if they have access to fine-grained measurements. In particular, this fixes a local Lucky 13 cache attack found and reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihan) Bai, Grant Hernandez, and Kevin Butler (University of Florida) and Dave Tian (Purdue University). * Fix side channel in RSA private key operations and static (finite-field) Diffie-Hellman. An adversary with precise enough timing and memory access information (typically an untrusted operating system attacking a secure enclave) could bypass an existing counter-measure (base blinding) and potentially fully recover the private key. * Fix a 1-byte buffer overread in mbedtls_x509_crl_parse_der(). Credit to OSS-Fuzz for detecting the problem and to Philippe Antoine for pinpointing the problematic code. * Zeroising of plaintext buffers in mbedtls_ssl_read() to erase unused application data from memory. Reported in #689 by Johan Uppman Bruce of Sectra. Bugfix * Library files installed after a CMake build no longer have execute permission. * Use local labels in mbedtls_padlock_has_support() to fix an invalid symbol redefinition if the function is inlined. Reported in #3451 and fix contributed in #3452 by okhowang. * Fix the endianness of Curve25519 keys imported/exported through the PSA APIs. psa_import_key and psa_export_key will now correctly expect/output Montgomery keys in little-endian as defined by RFC7748. Contributed by Steven Cooreman in #3425. * Fix build errors when the only enabled elliptic curves are Montgomery curves. Raised by signpainter in #941 and by Taiki-San in #1412. This also fixes missing declarations reported by Steven Cooreman in #1147. * Fix self-test failure when the only enabled short Weierstrass elliptic curve is secp192k1. Fixes #2017. * PSA key import will now correctly import a Curve25519/Curve448 public key instead of erroring out. Contributed by Steven Cooreman in #3492. * Use arc4random_buf on NetBSD instead of rand implementation with cyclical lower bits. Fix contributed in #3540. * Fix a memory leak in mbedtls_md_setup() when using HMAC under low memory conditions. Reported and fix suggested by Guido Vranken in #3486. * Fix bug in redirection of unit test outputs on platforms where stdout is defined as a macro. First reported in #2311 and fix contributed in #3528. Changes * Only pass -Wformat-signedness to versions of GCC that support it. Reported in #3478 and fix contributed in #3479 by okhowang. * Reduce the stack consumption of mbedtls_x509write_csr_der() which previously could lead to stack overflow on constrained devices. Contributed by Doru Gucea and Simon Leet in #3464. * Undefine the ASSERT macro before defining it locally, in case it is defined in a platform header. Contributed by Abdelatif Guettouche in #3557. * Update copyright notices to use Linux Foundation guidance. As a result, the copyright of contributors other than Arm is now acknowledged, and the years of publishing are no longer tracked in the source files. This also eliminates the need for the lines declaring the files to be part of MbedTLS. Fixes #3457. * Add the command line parameter key_pwd to the ssl_client2 and ssl_server2 example applications which allows to provide a password for the key file specified through the existing key_file argument. This allows the use of these applications with password-protected key files. Analogously but for ssl_server2 only, add the command line parameter key_pwd2 which allows to set a password for the key file provided through the existing key_file2 argument. = mbed TLS 2.23.0 branch released 2020-07-01 Default behavior changes * In the experimental PSA secure element interface, change the encoding of key lifetimes to encode a persistence level and the location. Although C prototypes do not effectively change, code calling psa_register_se_driver() must be modified to pass the driver's location instead of the keys' lifetime. If the library is upgraded on an existing device, keys created with the old lifetime value will not be readable or removable through Mbed TLS after the upgrade. Features * New functions in the error module return constant strings for high- and low-level error codes, complementing mbedtls_strerror() which constructs a string for any error code, including compound ones, but requires a writable buffer. Contributed by Gaurav Aggarwal in #3176. * The new utility programs/ssl/ssl_context_info prints a human-readable dump of an SSL context saved with mbedtls_ssl_context_save(). * Add support for midipix, a POSIX layer for Microsoft Windows. * Add new mbedtls_x509_crt_parse_der_with_ext_cb() routine which allows parsing unsupported certificate extensions via user provided callback. Contributed by Nicola Di Lieto in #3243 as a solution to #3241. * Pass the "certificate policies" extension to the callback supplied to mbedtls_x509_crt_parse_der_with_ext_cb() if it contains unsupported policies (#3419). * Added support to entropy_poll for the kern.arandom syscall supported on some BSD systems. Contributed by Nia Alarie in #3423. * Add support for Windows 2000 in net_sockets. Contributed by opatomic. #3239 Security * Fix a side channel vulnerability in modular exponentiation that could reveal an RSA private key used in a secure enclave. Noticed by Sangho Lee, Ming-Wei Shih, Prasun Gera, Taesoo Kim and Hyesoon Kim (Georgia Institute of Technology); and Marcus Peinado (Microsoft Research). Reported by Raoul Strackx (Fortanix) in #3394. * Fix side channel in mbedtls_ecp_check_pub_priv() and mbedtls_pk_parse_key() / mbedtls_pk_parse_keyfile() (when loading a private key that didn't include the uncompressed public key), as well as mbedtls_ecp_mul() / mbedtls_ecp_mul_restartable() when called with a NULL f_rng argument. An attacker with access to precise enough timing and memory access information (typically an untrusted operating system attacking a secure enclave) could fully recover the ECC private key. Found and reported by Alejandro Cabrera Aldaya and Billy Brumley. * Fix issue in Lucky 13 counter-measure that could make it ineffective when hardware accelerators were used (using one of the MBEDTLS_SHAxxx_ALT macros). This would cause the original Lucky 13 attack to be possible in those configurations, allowing an active network attacker to recover plaintext after repeated timing measurements under some conditions. Reported and fix suggested by Luc Perneel in #3246. Bugfix * Fix the Visual Studio Release x64 build configuration for mbedtls itself. Completes a previous fix in Mbed TLS 2.19 that only fixed the build for the example programs. Reported in #1430 and fix contributed by irwir. * Fix undefined behavior in X.509 certificate parsing if the pathLenConstraint basic constraint value is equal to INT_MAX. The actual effect with almost every compiler is the intended behavior, so this is unlikely to be exploitable anywhere. #3192 * Fix issue with a detected HW accelerated record error not being exposed due to shadowed variable. Contributed by Sander Visser in #3310. * Avoid NULL pointer dereferencing if mbedtls_ssl_free() is called with a NULL pointer argument. Contributed by Sander Visser in #3312. * Fix potential linker errors on dual world platforms by inlining mbedtls_gcc_group_to_psa(). This allows the pk.c module to link separately from psa_crypto.c. Fixes #3300. * Remove dead code in X.509 certificate parsing. Contributed by irwir in #2855. * Include asn1.h in error.c. Fixes #3328 reported by David Hu. * Fix potential memory leaks in ecp_randomize_jac() and ecp_randomize_mxz() when PRNG function fails. Contributed by Jonas Lejeune in #3318. * Remove unused macros from MSVC projects. Reported in #3297 and fix submitted in #3333 by irwir. * Add additional bounds checks in ssl_write_client_hello() preventing output buffer overflow if the configuration declared a buffer that was too small. * Set _POSIX_C_SOURCE to at least 200112L in C99 code. Reported in #3420 and fix submitted in #3421 by Nia Alarie. * Fix building library/net_sockets.c and the ssl_mail_client program on NetBSD. Contributed by Nia Alarie in #3422. * Fix false positive uninitialised variable reported by cpp-check. Contributed by Sander Visser in #3311. * Update iv and len context pointers manually when reallocating buffers using the MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH feature. This caused issues when receiving a connection with CID, when these fields were shifted in ssl_parse_record_header(). Changes * Fix warnings about signedness issues in format strings. The build is now clean of -Wformat-signedness warnings. Contributed by Kenneth Soerensen in #3153. * Fix minor performance issue in operations on Curve25519 caused by using a suboptimal modular reduction in one place. Found and fix contributed by Aurelien Jarno in #3209. * Combine identical cases in switch statements in md.c. Contributed by irwir in #3208. * Simplify a bounds check in ssl_write_certificate_request(). Contributed by irwir in #3150. * Unify the example programs termination to call mbedtls_exit() instead of using a return command. This has been done to enable customization of the behavior in bare metal environments. * Fix mbedtls_x509_dn_gets to escape non-ASCII characters as "?". Contributed by Koh M. Nakagawa in #3326. * Use FindPython3 when cmake version >= 3.15.0 * Abort the ClientHello writing function as soon as some extension doesn't fit into the record buffer. Previously, such extensions were silently dropped. As a consequence, the TLS handshake now fails when the output buffer is not large enough to hold the ClientHello. * The unit tests now rely on header files in tests/include/test and source files in tests/src. When building with make or cmake, the files in tests/src are compiled and the resulting object linked into each test executable. * The ECP module, enabled by `MBEDTLS_ECP_C`, now depends on `MBEDTLS_CTR_DRBG_C` or `MBEDTLS_HMAC_DRBG_C` for some side-channel coutermeasures. If side channels are not a concern, this dependency can be avoided by enabling the new option `MBEDTLS_ECP_NO_INTERNAL_RNG`. * Align MSVC error flag with GCC and Clang. Contributed by Carlos Gomes Martinho. #3147 * Remove superfluous assignment in mbedtls_ssl_parse_certificate(). Reported in #3182 and fix submitted by irwir. #3217 * Fix typo in XTS tests. Reported and fix submitted by Kxuan. #3319 = mbed TLS 2.22.0 branch released 2020-04-14 New deprecations * Deprecate MBEDTLS_SSL_HW_RECORD_ACCEL that enables function hooks in the SSL module for hardware acceleration of individual records. * Deprecate mbedtls_ssl_get_max_frag_len() in favour of mbedtls_ssl_get_output_max_frag_len() and mbedtls_ssl_get_input_max_frag_len() to be more precise about which max fragment length is desired. Security * Fix issue in DTLS handling of new associations with the same parameters (RFC 6347 section 4.2.8): an attacker able to send forged UDP packets to the server could cause it to drop established associations with legitimate clients, resulting in a Denial of Service. This could only happen when MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE was enabled in config.h (which it is by default). * Fix side channel in ECC code that allowed an adversary with access to precise enough timing and memory access information (typically an untrusted operating system attacking a secure enclave) to fully recover an ECDSA private key. Found and reported by Alejandro Cabrera Aldaya, Billy Brumley and Cesar Pereida Garcia. CVE-2020-10932 * Fix a potentially remotely exploitable buffer overread in a DTLS client when parsing the Hello Verify Request message. Features * The new build option MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH automatically resizes the I/O buffers before and after handshakes, reducing the memory consumption during application data transfer. Bugfix * Fix compilation failure when both MBEDTLS_SSL_PROTO_DTLS and MBEDTLS_SSL_HW_RECORD_ACCEL are enabled. * Remove a spurious check in ssl_parse_client_psk_identity that triggered a warning with some compilers. Fix contributed by irwir in #2856. * Fix a function name in a debug message. Contributed by Ercan Ozturk in #3013. Changes * Mbed Crypto is no longer a Git submodule. The crypto part of the library is back directly in the present repository. * Split mbedtls_ssl_get_max_frag_len() into mbedtls_ssl_get_output_max_frag_len() and mbedtls_ssl_get_input_max_frag_len() to ensure that a sufficient input buffer is allocated by the server (if MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is defined), regardless of what MFL was configured for it. = mbed TLS 2.21.0 branch released 2020-02-20 New deprecations * Deprecate MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO that enables parsing SSLv2 ClientHello messages. * Deprecate MBEDTLS_SSL_PROTO_SSL3 that enables support for SSLv3. * Deprecate for MBEDTLS_PKCS11_C, the wrapper around the pkcs11-helper library which allows TLS authentication to use keys stored in a PKCS#11 token such as a smartcard. Security * Fix potential memory overread when performing an ECDSA signature operation. The overread only happens with cryptographically low probability (of the order of 2^-n where n is the bitsize of the curve) unless the RNG is broken, and could result in information disclosure or denial of service (application crash or extra resource consumption). Found by Auke Zeilstra and Peter Schwabe, using static analysis. * To avoid a side channel vulnerability when parsing an RSA private key, read all the CRT parameters from the DER structure rather than reconstructing them. Found by Alejandro Cabrera Aldaya and Billy Bob Brumley. Reported and fix contributed by Jack Lloyd. ARMmbed/mbed-crypto#352 Features * The new build option MBEDTLS_SHA512_NO_SHA384 allows building SHA-512 support without SHA-384. API changes * Change the encoding of key types and curves in the PSA API. The new values are aligned with the upcoming release of the PSA Crypto API specification version 1.0.0. The main change which may break some existing code is that elliptic curve key types no longer encode the exact curve: a psa_ecc_curve_t or psa_key_type_t value only encodes a curve family and the key size determines the exact curve (for example, PSA_ECC_CURVE_SECP_R1 with 256 bits is P256R1). ARMmbed/mbed-crypto#330 Bugfix * Fix an unchecked call to mbedtls_md() in the x509write module. * Fix build failure with MBEDTLS_ZLIB_SUPPORT enabled. Reported by Jack Lloyd in #2859. Fix submitted by jiblime in #2963. * Fix some false-positive uninitialized variable warnings in X.509. Fix contributed by apple-ihack-geek in #2663. * Fix a possible error code mangling in psa_mac_verify_finish() when a cryptographic accelerator fails. ARMmbed/mbed-crypto#345 * Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some RSA keys that would later be rejected by functions expecting private keys. Found by Catena cyber using oss-fuzz (issue 20467). * Fix a bug in mbedtls_pk_parse_key() that would cause it to accept some RSA keys with invalid values by silently fixing those values. = mbed TLS 2.20.0 branch released 2020-01-15 Default behavior changes * The initial seeding of a CTR_DRBG instance makes a second call to the entropy function to obtain entropy for a nonce if the entropy size is less than 3/2 times the key size. In case you want to disable the extra call to grab entropy, you can call mbedtls_ctr_drbg_set_nonce_len() to force the nonce length to 0. Security * Enforce that mbedtls_entropy_func() gathers a total of MBEDTLS_ENTROPY_BLOCK_SIZE bytes or more from strong sources. In the default configuration, on a platform with a single entropy source, the entropy module formerly only grabbed 32 bytes, which is good enough for security if the source is genuinely strong, but less than the expected 64 bytes (size of the entropy accumulator). * Zeroize local variables in mbedtls_internal_aes_encrypt() and mbedtls_internal_aes_decrypt() before exiting the function. The value of these variables can be used to recover the last round key. To follow best practice and to limit the impact of buffer overread vulnerabilities (like Heartbleed) we need to zeroize them before exiting the function. Issue reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihang) Bai, Grant Hernandez, and Kevin Butler (University of Florida) and Dave Tian (Purdue University). * Fix side channel vulnerability in ECDSA. Our bignum implementation is not constant time/constant trace, so side channel attacks can retrieve the blinded value, factor it (as it is smaller than RSA keys and not guaranteed to have only large prime factors), and then, by brute force, recover the key. Reported by Alejandro Cabrera Aldaya and Billy Brumley. * Fix side channel vulnerability in ECDSA key generation. Obtaining precise timings on the comparison in the key generation enabled the attacker to learn leading bits of the ephemeral key used during ECDSA signatures and to recover the private key. Reported by Jeremy Dubeuf. * Catch failure of AES functions in mbedtls_ctr_drbg_random(). Uncaught failures could happen with alternative implementations of AES. Bug reported and fix proposed by Johan Uppman Bruce and Christoffer Lauri, Sectra. Features * Key derivation inputs in the PSA API can now either come from a key object or from a buffer regardless of the step type. * The CTR_DRBG module can grab a nonce from the entropy source during the initial seeding. The default nonce length is chosen based on the key size to achieve the security strength defined by NIST SP 800-90A. You can change it with mbedtls_ctr_drbg_set_nonce_len(). * Add ENUMERATED tag support to the ASN.1 module. Contributed by msopiha-linaro in ARMmbed/mbed-crypto#307. API changes * In the PSA API, forbid zero-length keys. To pass a zero-length input to a key derivation function, use a buffer instead (this is now always possible). * Rename psa_asymmetric_sign() to psa_sign_hash() and psa_asymmetric_verify() to psa_verify_hash(). Bugfix * Fix an incorrect size in a debugging message. Reported and fix submitted by irwir. Fixes #2717. * Fix an unused variable warning when compiling without DTLS. Reported and fix submitted by irwir. Fixes #2800. * Remove a useless assignment. Reported and fix submitted by irwir. Fixes #2801. * Fix a buffer overflow in the PSA HMAC code when using a long key with an unsupported algorithm. Fixes ARMmbed/mbed-crypto#254. * Fix mbedtls_asn1_get_int to support any number of leading zeros. Credit to OSS-Fuzz for finding a bug in an intermediate version of the fix. * Fix mbedtls_asn1_get_bitstring_null to correctly parse bitstrings of at most 2 bytes. * mbedtls_ctr_drbg_set_entropy_len() and mbedtls_hmac_drbg_set_entropy_len() now work if you call them before mbedtls_ctr_drbg_seed() or mbedtls_hmac_drbg_seed(). Changes * Remove the technical possibility to define custom mbedtls_md_info structures, which was exposed only in an internal header. * psa_close_key(0) and psa_destroy_key(0) now succeed (doing nothing, as before). * Variables containing error codes are now initialized to an error code rather than success, so that coding mistakes or memory corruption tends to cause functions to return this error code rather than a success. There are no known instances where this changes the behavior of the library: this is merely a robustness improvement. ARMmbed/mbed-crypto#323 * Remove a useless call to mbedtls_ecp_group_free(). Contributed by Alexander Krizhanovsky in ARMmbed/mbed-crypto#210. * Speed up PBKDF2 by caching the digest calculation. Contributed by Jack Lloyd and Fortanix Inc in ARMmbed/mbed-crypto#277. * Small performance improvement of mbedtls_mpi_div_mpi(). Contributed by Alexander Krizhanovsky in ARMmbed/mbed-crypto#308. = mbed TLS 2.19.1 branch released 2019-09-16 Features * Declare include headers as PUBLIC to propagate to CMake project consumers Contributed by Zachary J. Fields in PR #2949. * Add nss_keylog to ssl_client2 and ssl_server2, enabling easier analysis of TLS sessions with tools like Wireshark. API Changes * Make client_random and server_random const in mbedtls_ssl_export_keys_ext_t, so that the key exporter is discouraged from modifying the client/server hello. Bugfix * Fix some false-positive uninitialized variable warnings in crypto. Fix contributed by apple-ihack-geek in #2663. = mbed TLS 2.19.0 branch released 2019-09-06 Security * Fix a missing error detection in ECJPAKE. This could have caused a predictable shared secret if a hardware accelerator failed and the other side of the key exchange had a similar bug. * When writing a private EC key, use a constant size for the private value, as specified in RFC 5915. Previously, the value was written as an ASN.1 INTEGER, which caused the size of the key to leak about 1 bit of information on average and could cause the value to be 1 byte too large for the output buffer. * The deterministic ECDSA calculation reused the scheme's HMAC-DRBG to implement blinding. Because of this for the same key and message the same blinding value was generated. This reduced the effectiveness of the countermeasure and leaked information about the private key through side channels. Reported by Jack Lloyd. Features * Add new API functions mbedtls_ssl_session_save() and mbedtls_ssl_session_load() to allow serializing a session, for example to store it in non-volatile storage, and later using it for TLS session resumption. * Add a new API function mbedtls_ssl_check_record() to allow checking that an incoming record is valid, authentic and has not been seen before. This feature can be used alongside Connection ID and SSL context serialisation. The feature is enabled at compile-time by MBEDTLS_SSL_RECORD_CHECKING option. * New implementation of X25519 (ECDH using Curve25519) from Project Everest (https://project-everest.github.io/). It can be enabled at compile time with MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED. This implementation is formally verified and significantly faster, but is only supported on x86 platforms (32-bit and 64-bit) using GCC, Clang or Visual Studio. Contributed by Christoph Wintersteiger from Microsoft Research. * Add mbedtls_net_close(), enabling the building of forking servers where the parent process closes the client socket and continue accepting, and the child process closes the listening socket and handles the client socket. Contributed by Robert Larsen in #2803. API Changes * Add DER-encoded test CRTs to library/certs.c, allowing the example programs ssl_server2 and ssl_client2 to be run if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254. * The HAVEGE state type now uses uint32_t elements instead of int. * The functions mbedtls_ecp_curve_list() and mbedtls_ecp_grp_id_list() now list all curves for which at least one of ECDH or ECDSA is supported, not just curves for which both are supported. Call mbedtls_ecdsa_can_do() or mbedtls_ecdh_can_do() on each result to check whether each algorithm is supported. * The new function mbedtls_ecdsa_sign_det_ext() is similar to mbedtls_ecdsa_sign_det() but allows passing an external RNG for the purpose of blinding. New deprecations * Deprecate mbedtls_ecdsa_sign_det() in favor of a functions that can take an RNG function as an input. * Calling mbedtls_ecdsa_write_signature() with NULL as the f_rng argument is now deprecated. Bugfix * Fix missing bounds checks in X.509 parsing functions that could lead to successful parsing of ill-formed X.509 CRTs. Fixes #2437. * Fix multiple X.509 functions previously returning ASN.1 low-level error codes to always wrap these codes into X.509 high level error codes before returning. Fixes #2431. * Fix to allow building test suites with any warning that detects unused functions. Fixes #1628. * Fix typo in net_would_block(). Fixes #528 reported by github-monoculture. * Remove redundant include file in timing.c. Fixes #2640 reported by irwir. * Fix build failure when building with mingw on Windows by including stdarg.h where needed. Fixes #2656. * Fix Visual Studio Release x64 build configuration by inheriting PlatformToolset from the project configuration. Fixes #1430 reported by irwir. * Enable Suite B with subset of ECP curves. Make sure the code compiles even if some curves are not defined. Fixes #1591 reported by dbedev. * Fix misuse of signed arithmetic in the HAVEGE module. #2598 * Avoid use of statically sized stack buffers for certificate writing. This previously limited the maximum size of DER encoded certificates in mbedtls_x509write_crt_der() to 2Kb. Reported by soccerGB in #2631. * Fix partial zeroing in x509_get_other_name. Found and fixed by ekse, #2716. * Update test certificates that were about to expire. Reported by Bernhard M. Wiedemann in #2357. * Fix the build on ARMv5TE in ARM mode to not use assembly instructions that are only available in Thumb mode. Fix contributed by Aurelien Jarno in #2169. * Fix propagation of restart contexts in restartable EC operations. This could previously lead to segmentation faults in builds using an address-sanitizer and enabling but not using MBEDTLS_ECP_RESTARTABLE. * Fix memory leak in in mpi_miller_rabin(). Contributed by Jens Wiklander in #2363 * Improve code clarity in x509_crt module, removing false-positive uninitialized variable warnings on some recent toolchains (GCC8, etc). Discovered and fixed by Andy Gross (Linaro), #2392. * Fix bug in endianness conversion in bignum module. This lead to functionally incorrect code on bigendian systems which don't have __BYTE_ORDER__ defined. Reported by Brendan Shanks. Fixes #2622. Changes * Replace multiple uses of MD2 by SHA-256 in X.509 test suite. Fixes #821. * Make it easier to define MBEDTLS_PARAM_FAILED as assert (which config.h suggests). #2671 * Make `make clean` clean all programs always. Fixes #1862. * Add a Dockerfile and helper scripts (all-in-docker.sh, basic-in-docker.sh, docker-env.sh) to simplify running test suites on a Linux host. Contributed by Peter Kolbus (Garmin). * Add `reproducible` option to `ssl_client2` and `ssl_server2` to enable test runs without variability. Contributed by Philippe Antoine (Catena cyber) in #2681. * Extended .gitignore to ignore Visual Studio artifacts. Fixed by ConfusedSushi. * Adds fuzz targets, especially for continuous fuzzing with OSS-Fuzz. Contributed by Philippe Antoine (Catena cyber). * Remove the crypto part of the library from Mbed TLS. The crypto code and tests are now only available via Mbed Crypto, which Mbed TLS references as a Git submodule. = mbed TLS 2.18.1 branch released 2019-07-12 Bugfix * Fix build failure when building with mingw on Windows by including stdarg.h where needed. Fixes #2656. Changes * Enable building of Mbed TLS as a CMake subproject. Suggested and fixed by Ashley Duncan in #2609. = mbed TLS 2.18.0 branch released 2019-06-11 Features * Add the Any Policy certificate policy oid, as defined in rfc 5280 section 4.2.1.4. * It is now possible to use NIST key wrap mode via the mbedtls_cipher API. Contributed by Jack Lloyd and Fortanix Inc. * Add the Wi-SUN Field Area Network (FAN) device extended key usage. * Add the oid certificate policy x509 extension. * It is now possible to perform RSA PKCS v1.5 signatures with RIPEMD-160 digest. Contributed by Jack Lloyd and Fortanix Inc. * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, and the used tls-prf. * Add public API for tls-prf function, according to requested enum. * Add support for parsing otherName entries in the Subject Alternative Name X.509 certificate extension, specifically type hardware module name, as defined in RFC 4108 section 5. * Add support for parsing certificate policies extension, as defined in RFC 5280 section 4.2.1.4. Currently, only the "Any Policy" policy is supported. * List all SAN types in the subject_alt_names field of the certificate. Resolves #459. * Add support for draft-05 of the Connection ID extension, as specified in https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05. The Connection ID extension allows to keep DTLS connections beyond the lifetime of the underlying transport by adding a connection identifier to the DTLS record header. This identifier can be used to associated an incoming record with the correct connection data even after the peer has changed its IP or port. The feature is enabled at compile-time by setting MBEDTLS_SSL_DTLS_CONNECTION_ID (disabled by default), and at run-time through the new APIs mbedtls_ssl_conf_cid() and mbedtls_ssl_set_cid(). API Changes * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, and the used tls-prf. * Add public API for tls-prf function, according to requested enum. Bugfix * Fix private key DER output in the key_app_writer example. File contents were shifted by one byte, creating an invalid ASN.1 tag. Fixed by Christian Walther in #2239. * Fix potential memory leak in X.509 self test. Found and fixed by Junhwan Park, #2106. * Reduce stack usage of hkdf tests. Fixes #2195. * Fix 1-byte buffer overflow in mbedtls_mpi_write_string() when used with negative inputs. Found by Guido Vranken in #2404. Credit to OSS-Fuzz. * Fix bugs in the AEAD test suite which would be exposed by ciphers which either used both encrypt and decrypt key schedules, or which perform padding. GCM and CCM were not affected. Fixed by Jack Lloyd. * Fix incorrect default port number in ssl_mail_client example's usage. Found and fixed by irwir. #2337 * Add psa_util.h to test/cpp_dummy_build to fix build_default_make_gcc_and_cxx. Fixed by Peter Kolbus (Garmin). #2579 * Add missing parentheses around parameters in the definition of the public macro MBEDTLS_X509_ID_FLAG. This could lead to invalid evaluation in case operators binding less strongly than subtraction were used for the parameter. * Add a check for MBEDTLS_X509_CRL_PARSE_C in ssl_server2, guarding the crl sni entry parameter. Reported by inestlerode in #560. * Set the next sequence of the subject_alt_name to NULL when deleting sequence on failure. Found and fix suggested by Philippe Antoine. Credit to OSS-Fuzz. Changes * Server's RSA certificate in certs.c was SHA-1 signed. In the default mbedTLS configuration only SHA-2 signed certificates are accepted. This certificate is used in the demo server programs, which lead the client programs to fail at the peer's certificate verification due to an unacceptable hash signature. The certificate has been updated to one that is SHA-256 signed. Fix contributed by Illya Gerasymchuk. * Return from various debugging routines immediately if the provided SSL context is unset. * Remove dead code from bignum.c in the default configuration. Found by Coverity, reported and fixed by Peter Kolbus (Garmin). Fixes #2309. * Add test for minimal value of MBEDTLS_MPI_WINDOW_SIZE to all.sh. Contributed by Peter Kolbus (Garmin). * Change wording in the `mbedtls_ssl_conf_max_frag_len()`'s documentation to improve clarity. Fixes #2258. = mbed TLS 2.17.0 branch released 2019-03-19 Features * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()` which allows copy-less parsing of DER encoded X.509 CRTs, at the cost of additional lifetime constraints on the input buffer, but at the benefit of reduced RAM consumption. * Add a new function mbedtls_asn1_write_named_bitstring() to write ASN.1 named bitstring in DER as required by RFC 5280 Appendix B. * Add MBEDTLS_REMOVE_3DES_CIPHERSUITES to allow removing 3DES ciphersuites from the default list (enabled by default). See https://sweet32.info/SWEET32_CCS16.pdf. API Changes * Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`. See the Features section for more information. * Allow to opt in to the removal the API mbedtls_ssl_get_peer_cert() for the benefit of saving RAM, by disabling the new compile-time option MBEDTLS_SSL_KEEP_PEER_CERTIFICATE (enabled by default for API stability). Disabling this option makes mbedtls_ssl_get_peer_cert() always return NULL, and removes the peer_cert field from the mbedtls_ssl_session structure which otherwise stores the peer's certificate. Security * Make mbedtls_ecdh_get_params return an error if the second key belongs to a different group from the first. Before, if an application passed keys that belonged to different group, the first key's data was interpreted according to the second group, which could lead to either an error or a meaningless output from mbedtls_ecdh_get_params. In the latter case, this could expose at most 5 bits of the private key. Bugfix * Fix a compilation issue with mbedtls_ecp_restart_ctx not being defined when MBEDTLS_ECP_ALT is defined. Reported by jwhui. Fixes #2242. * Run the AD too long test only if MBEDTLS_CCM_ALT is not defined. Raised as a comment in #1996. * Reduce the stack consumption of mbedtls_mpi_fill_random() which could previously lead to a stack overflow on constrained targets. * Add `MBEDTLS_SELF_TEST` for the mbedtls_self_test functions in the header files, which missed the precompilation check. #971 * Fix returning the value 1 when mbedtls_ecdsa_genkey failed. * Remove a duplicate #include in a sample program. Fixed by Masashi Honma #2326. * Remove the mbedtls namespacing from the header file, to fix a "file not found" build error. Fixed by Haijun Gu #2319. * Fix signed-to-unsigned integer conversion warning in X.509 module. Fixes #2212. * Reduce stack usage of `mpi_write_hlp()` by eliminating recursion. Fixes #2190. * Fix false failure in all.sh when backup files exist in include/mbedtls (e.g. config.h.bak). Fixed by Peter Kolbus (Garmin) #2407. * Ensure that unused bits are zero when writing ASN.1 bitstrings when using mbedtls_asn1_write_bitstring(). * Fix issue when writing the named bitstrings in KeyUsage and NsCertType extensions in CSRs and CRTs that caused these bitstrings to not be encoded correctly as trailing zeroes were not accounted for as unused bits in the leading content octet. Fixes #1610. Changes * Reduce RAM consumption during session renegotiation by not storing the peer CRT chain and session ticket twice. * Include configuration file in all header files that use configuration, instead of relying on other header files that they include. Inserted as an enhancement for #1371 * Add support for alternative CSR headers, as used by Microsoft and defined in RFC 7468. Found by Michael Ernst. Fixes #767. * Correct many misspellings. Fixed by MisterDA #2371. * Provide an abstraction of vsnprintf to allow alternative implementations for platforms that don't provide it. Based on contributions by Joris Aerts and Nathaniel Wesley Filardo. * Fix clobber list in MIPS assembly for large integer multiplication. Previously, this could lead to functionally incorrect assembly being produced by some optimizing compilers, showing up as failures in e.g. RSA or ECC signature operations. Reported in #1722, fix suggested by Aurelien Jarno and submitted by Jeffrey Martin. * Reduce the complexity of the timing tests. They were assuming more than the underlying OS actually guarantees. * Fix configuration queries in ssl-opt.h. #2030 * Ensure that ssl-opt.h can be run in OS X. #2029 * Re-enable certain interoperability tests in ssl-opt.sh which had previously been disabled for lack of a sufficiently recent version of GnuTLS on the CI. * Ciphersuites based on 3DES now have the lowest priority by default when they are enabled. = mbed TLS 2.16.0 branch released 2018-12-21 Features * Add a new config.h option of MBEDTLS_CHECK_PARAMS that enables validation of parameters in the API. This allows detection of obvious misuses of the API, such as passing NULL pointers. The API of existing functions hasn't changed, but requirements on parameters have been made more explicit in the documentation. See the corresponding API documentation for each function to see for which parameter values it is defined. This feature is disabled by default. See its API documentation in config.h for additional steps you have to take when enabling it. API Changes * The following functions in the random generator modules have been deprecated and replaced as shown below. The new functions change the return type from void to int to allow returning error codes when using MBEDTLS__ALT for the underlying AES or message digest primitive. Fixes #1798. mbedtls_ctr_drbg_update() -> mbedtls_ctr_drbg_update_ret() mbedtls_hmac_drbg_update() -> mbedtls_hmac_drbg_update_ret() * Extend ECDH interface to enable alternative implementations. * Deprecate error codes of the form MBEDTLS_ERR_xxx_INVALID_KEY_LENGTH for ARIA, CAMELLIA and Blowfish. These error codes will be replaced by the more generic per-module error codes MBEDTLS_ERR_xxx_BAD_INPUT_DATA. * Additional parameter validation checks have been added for the following modules - AES, ARIA, Blowfish, CAMELLIA, CCM, GCM, DHM, ECP, ECDSA, ECDH, ECJPAKE, SHA, Chacha20 and Poly1305, cipher, pk, RSA, and MPI. Where modules have had parameter validation added, existing parameter checks may have changed. Some modules, such as Chacha20 had existing parameter validation whereas other modules had little. This has now been changed so that the same level of validation is present in all modules, and that it is now optional with the MBEDTLS_CHECK_PARAMS flag which by default is off. That means that checks which were previously present by default will no longer be. New deprecations * Deprecate mbedtls_ctr_drbg_update and mbedtls_hmac_drbg_update in favor of functions that can return an error code. Bugfix * Fix for Clang, which was reporting a warning for the bignum.c inline assembly for AMD64 targets creating string literals greater than those permitted by the ISO C99 standard. Found by Aaron Jones. Fixes #482. * Fix runtime error in `mbedtls_platform_entropy_poll()` when run through qemu user emulation. Reported and fix suggested by randombit in #1212. Fixes #1212. * Fix an unsafe bounds check when restoring an SSL session from a ticket. This could lead to a buffer overflow, but only in case ticket authentication was broken. Reported and fix suggested by Guido Vranken in #659. * Add explicit integer to enumeration type casts to example program programs/pkey/gen_key which previously led to compilation failure on some toolchains. Reported by phoenixmcallister. Fixes #2170. * Fix double initialization of ECC hardware that made some accelerators hang. * Clarify documentation of mbedtls_ssl_set_own_cert() regarding the absence of check for certificate/key matching. Reported by Attila Molnar, #507. = mbed TLS 2.15.1 branch released 2018-11-30 Changes * Update the Mbed Crypto submodule to version 0.1.0b2. = mbed TLS 2.15.0 branch released 2018-11-23 Features * Add an experimental build option, USE_CRYPTO_SUBMODULE, to enable use of Mbed Crypto as the source of the cryptography implementation. * Add an experimental configuration option, MBEDTLS_PSA_CRYPTO_C, to enable the PSA Crypto API from Mbed Crypto when additionally used with the USE_CRYPTO_SUBMODULE build option. Changes * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() from the cipher abstraction layer. Fixes #2198. = mbed TLS 2.14.1 branch released 2018-11-30 Security * Fix timing variations and memory access variations in RSA PKCS#1 v1.5 decryption that could lead to a Bleichenbacher-style padding oracle attack. In TLS, this affects servers that accept ciphersuites based on RSA decryption (i.e. ciphersuites whose name contains RSA but not (EC)DH(E)). Discovered by Eyal Ronen (Weizmann Institute), Robert Gillham (University of Adelaide), Daniel Genkin (University of Michigan), Adi Shamir (Weizmann Institute), David Wong (NCC Group), and Yuval Yarom (University of Adelaide, Data61). The attack is described in more detail in the paper available here: http://cat.eyalro.net/cat.pdf CVE-2018-19608 * In mbedtls_mpi_write_binary(), don't leak the exact size of the number via branching and memory access patterns. An attacker who could submit a plaintext for RSA PKCS#1 v1.5 decryption but only observe the timing of the decryption and not its result could nonetheless decrypt RSA plaintexts and forge RSA signatures. Other asymmetric algorithms may have been similarly vulnerable. Reported by Eyal Ronen, Robert Gillham, Daniel Genkin, Adi Shamir, David Wong and Yuval Yarom. * Wipe sensitive buffers on the stack in the CTR_DRBG and HMAC_DRBG modules. API Changes * The new functions mbedtls_ctr_drbg_update_ret() and mbedtls_hmac_drbg_update_ret() are similar to mbedtls_ctr_drbg_update() and mbedtls_hmac_drbg_update() respectively, but the new functions report errors whereas the old functions return void. We recommend that applications use the new functions. = mbed TLS 2.14.0 branch released 2018-11-19 Security * Fix overly strict DN comparison when looking for CRLs belonging to a particular CA. This previously led to ignoring CRLs when the CRL's issuer name and the CA's subject name differed in their string encoding (e.g., one using PrintableString and the other UTF8String) or in the choice of upper and lower case. Reported by Henrik Andersson of Bosch GmbH in issue #1784. * Fix a flawed bounds check in server PSK hint parsing. In case the incoming message buffer was placed within the first 64KiB of address space and a PSK-(EC)DHE ciphersuite was used, this allowed an attacker to trigger a memory access up to 64KiB beyond the incoming message buffer, potentially leading to an application crash or information disclosure. * Fix mbedtls_mpi_is_prime() to use more rounds of probabilistic testing. The previous settings for the number of rounds made it practical for an adversary to construct non-primes that would be erroneously accepted as primes with high probability. This does not have an impact on the security of TLS, but can matter in other contexts with numbers chosen potentially by an adversary that should be prime and can be validated. For example, the number of rounds was enough to securely generate RSA key pairs or Diffie-Hellman parameters, but was insufficient to validate Diffie-Hellman parameters properly. See "Prime and Prejudice" by by Martin R. Albrecht and Jake Massimo and Kenneth G. Paterson and Juraj Somorovsky. Features * Add support for temporarily suspending expensive ECC computations after some configurable amount of operations. This is intended to be used in constrained, single-threaded systems where ECC is time consuming and can block other operations until they complete. This is disabled by default, but can be enabled by MBEDTLS_ECP_RESTARTABLE at compile time and configured by mbedtls_ecp_set_max_ops() at runtime. It applies to the new xxx_restartable functions in ECP, ECDSA, PK and X.509 (CRL not supported yet), and to existing functions in ECDH and SSL (currently only implemented client-side, for ECDHE-ECDSA ciphersuites in TLS 1.2, including client authentication). * Add support for Arm CPU DSP extensions to accelerate asymmetric key operations. On CPUs where the extensions are available, they can accelerate MPI multiplications used in ECC and RSA cryptography. Contributed by Aurelien Jarno. * Extend RSASSA-PSS signature to allow a smaller salt size. Previously, PSS signature always used a salt with the same length as the hash, and returned an error if this was not possible. Now the salt size may be up to two bytes shorter. This allows the library to support all hash and signature sizes that comply with FIPS 186-4, including SHA-512 with a 1024-bit key. * Add support for 128-bit keys in CTR_DRBG. Note that using keys shorter than 256 bits limits the security of generated material to 128 bits. API Changes * Add a common error code of `MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED` for a feature that is not supported by underlying alternative implementations implementing cryptographic primitives. This is useful for hardware accelerators that don't implement all options or features. New deprecations * All module specific errors following the form MBEDTLS_ERR_XXX_FEATURE_UNAVAILABLE that indicate a feature is not supported are deprecated and are now replaced by the new equivalent platform error. * All module specific generic hardware acceleration errors following the form MBEDTLS_ERR_XXX_HW_ACCEL_FAILED that are deprecated and are replaced by the equivalent plaform error. * Deprecate the function mbedtls_mpi_is_prime() in favor of mbedtls_mpi_is_prime_ext() which allows specifying the number of Miller-Rabin rounds. Bugfix * Fix wrong order of freeing in programs/ssl/ssl_server2 example application leading to a memory leak in case both MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE are set. Fixes #2069. * Fix a bug in the update function for SSL ticket keys which previously invalidated keys of a lifetime of less than a 1s. Fixes #1968. * Fix failure in hmac_drbg in the benchmark sample application, when MBEDTLS_THREADING_C is defined. Found by TrinityTonic, #1095 * Fix a bug in the record decryption routine ssl_decrypt_buf() which lead to accepting properly authenticated but improperly padded records in case of CBC ciphersuites using Encrypt-then-MAC. * Fix memory leak and freeing without initialization in the example program programs/x509/cert_write. Fixes #1422. * Ignore IV in mbedtls_cipher_set_iv() when the cipher mode is MBEDTLS_MODE_ECB. Found by ezdevelop. Fixes #1091. * Zeroize memory used for buffering or reassembling handshake messages after use. * Use `mbedtls_platform_zeroize()` instead of `memset()` for zeroization of sensitive data in the example programs aescrypt2 and crypt_and_hash. * Change the default string format used for various X.509 DN attributes to UTF8String. Previously, the use of the PrintableString format led to wildcards and non-ASCII characters being unusable in some DN attributes. Reported by raprepo in #1860 and by kevinpt in #468. Fix contributed by Thomas-Dee. * Fix compilation failure for configurations which use compile time replacements of standard calloc/free functions through the macros MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_FREE_MACRO. Reported by ole-de and ddhome2006. Fixes #882, #1642 and #1706. Changes * Removed support for Yotta as a build tool. * Add tests for session resumption in DTLS. * Close a test gap in (D)TLS between the client side and the server side: test the handling of large packets and small packets on the client side in the same way as on the server side. * Change the dtls_client and dtls_server samples to work by default over IPv6 and optionally by a build option over IPv4. * Change the use of Windows threading to use Microsoft Visual C++ runtime calls, rather than Win32 API calls directly. This is necessary to avoid conflict with C runtime usage. Found and fixed by irwir. * Remember the string format of X.509 DN attributes when replicating X.509 DNs. Previously, DN attributes were always written in their default string format (mostly PrintableString), which could lead to CRTs being created which used PrintableStrings in the issuer field even though the signing CA used UTF8Strings in its subject field; while X.509 compliant, such CRTs were rejected in some applications, e.g. some versions of Firefox, curl and GnuTLS. Reported in #1033 by Moschn. Fix contributed by Thomas-Dee. * Improve documentation of mbedtls_ssl_get_verify_result(). Fixes #517 reported by github-monoculture. * Add MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR flag to mbedtls_mpi_gen_prime() and use it to reduce error probability in RSA key generation to levels mandated by FIPS-186-4. = mbed TLS 2.13.1 branch released 2018-09-06 API Changes * Extend the platform module with an abstraction mbedtls_platform_gmtime_r() whose implementation should behave as a thread-safe version of gmtime(). This allows users to configure such an implementation at compile time when the target system cannot be deduced automatically, by setting the option MBEDTLS_PLATFORM_GMTIME_R_ALT. At this stage Mbed TLS is only able to automatically select implementations for Windows and POSIX C libraries. Bugfix * Fix build failures on platforms where only gmtime() is available but neither gmtime_r() nor gmtime_s() are present. Fixes #1907. = mbed TLS 2.13.0 branch released 2018-08-31 Security * Fix an issue in the X.509 module which could lead to a buffer overread during certificate extensions parsing. In case of receiving malformed input (extensions length field equal to 0), an illegal read of one byte beyond the input buffer is made. Found and analyzed by Nathan Crandall. Features * Add support for fragmentation of outgoing DTLS handshake messages. This is controlled by the maximum fragment length as set locally or negotiated with the peer, as well as by a new per-connection MTU option, set using mbedtls_ssl_set_mtu(). * Add support for auto-adjustment of MTU to a safe value during the handshake when flights do not get through (RFC 6347, section 4.1.1.1, last paragraph). * Add support for packing multiple records within a single datagram, enabled by default. * Add support for buffering out-of-order handshake messages in DTLS. The maximum amount of RAM used for this can be controlled by the compile-time constant MBEDTLS_SSL_DTLS_MAX_BUFFERING defined in mbedtls/config.h. API Changes * Add function mbedtls_ssl_set_datagram_packing() to configure the use of datagram packing (enabled by default). Bugfix * Fix a potential memory leak in mbedtls_ssl_setup() function. An allocation failure in the function could lead to other buffers being leaked. * Fixes an issue with MBEDTLS_CHACHAPOLY_C which would not compile if MBEDTLS_ARC4_C and MBEDTLS_CIPHER_NULL_CIPHER weren't also defined. #1890 * Fix a memory leak in ecp_mul_comb() if ecp_precompute_comb() fails. Fix contributed by Espressif Systems. * Add ecc extensions only if an ecc based ciphersuite is used. This improves compliance to RFC 4492, and as a result, solves interoperability issues with BouncyCastle. Raised by milenamil in #1157. * Replace printf with mbedtls_printf in the ARIA module. Found by TrinityTonic in #1908. * Fix potential use-after-free in mbedtls_ssl_get_max_frag_len() and mbedtls_ssl_get_record_expansion() after a session reset. Fixes #1941. * Fix a bug that caused SSL/TLS clients to incorrectly abort the handshake with TLS versions 1.1 and earlier when the server requested authentication without providing a list of CAs. This was due to an overly strict bounds check in parsing the CertificateRequest message, introduced in Mbed TLS 2.12.0. Fixes #1954. * Fix a miscalculation of the maximum record expansion in mbedtls_ssl_get_record_expansion() in case of ChachaPoly ciphersuites, or CBC ciphersuites in (D)TLS versions 1.1 or higher. Fixes #1913, #1914. * Fix undefined shifts with negative values in certificates parsing (found by Catena cyber using oss-fuzz) * Fix memory leak and free without initialization in pk_encrypt and pk_decrypt example programs. Reported by Brace Stout. Fixes #1128. * Remove redundant else statement. Raised by irwir. Fixes #1776. Changes * Copy headers preserving timestamps when doing a "make install". Contributed by xueruini. * Allow the forward declaration of public structs. Contributed by Dawid Drozd. Fixes #1215 raised by randombit. * Improve compatibility with some alternative CCM implementations by using CCM test vectors from RAM. * Add support for buffering of out-of-order handshake messages. * Add warnings to the documentation of the HKDF module to reduce the risk of misusing the mbedtls_hkdf_extract() and mbedtls_hkdf_expand() functions. Fixes #1775. Reported by Brian J. Murray. = mbed TLS 2.12.0 branch released 2018-07-25 Security * Fix a vulnerability in TLS ciphersuites based on CBC and using SHA-384, in (D)TLS 1.0 to 1.2, that allowed an active network attacker to partially recover the plaintext of messages under some conditions by exploiting timing measurements. With DTLS, the attacker could perform this recovery by sending many messages in the same connection. With TLS or if mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if the same secret (for example a HTTP Cookie) has been repeatedly sent over connections manipulated by the attacker. Connections using GCM or CCM instead of CBC, using hash sizes other than SHA-384, or using Encrypt-then-Mac (RFC 7366) were not affected. The vulnerability was caused by a miscalculation (for SHA-384) in a countermeasure to the original Lucky 13 attack. Found by Kenny Paterson, Eyal Ronen and Adi Shamir. * Fix a vulnerability in TLS ciphersuites based on CBC, in (D)TLS 1.0 to 1.2, that allowed a local attacker, able to execute code on the local machine as well as manipulate network packets, to partially recover the plaintext of messages under some conditions by using a cache attack targeting an internal MD/SHA buffer. With TLS or if mbedtls_ssl_conf_dtls_badmac_limit() was used, the attack only worked if the same secret (for example a HTTP Cookie) has been repeatedly sent over connections manipulated by the attacker. Connections using GCM or CCM instead of CBC or using Encrypt-then-Mac (RFC 7366) were not affected. Found by Kenny Paterson, Eyal Ronen and Adi Shamir. * Add a counter-measure against a vulnerability in TLS ciphersuites based on CBC, in (D)TLS 1.0 to 1.2, that allowed a local attacker, able to execute code on the local machine as well as manipulate network packets, to partially recover the plaintext of messages under some conditions (see previous entry) by using a cache attack targeting the SSL input record buffer. Connections using GCM or CCM instead of CBC or using Encrypt-then-Mac (RFC 7366) were not affected. Found by Kenny Paterson, Eyal Ronen and Adi Shamir. Features * Add new crypto primitives from RFC 7539: stream cipher Chacha20, one-time authenticator Poly1305 and AEAD construct Chacha20-Poly1305. Contributed by Daniel King. * Add support for CHACHA20-POLY1305 ciphersuites from RFC 7905. * Add platform support for the Haiku OS. (https://www.haiku-os.org). Contributed by Augustin Cavalier. * Make the receive and transmit buffers independent sizes, for situations where the outgoing buffer can be fixed at a smaller size than the incoming buffer, which can save some RAM. If buffer lengths are kept equal, there is no functional difference. Contributed by Angus Gratton, and also independently contributed again by Paul Sokolovsky. * Add support for key wrapping modes based on AES as defined by NIST SP 800-38F algorithms KW and KWP and by RFC 3394 and RFC 5649. Bugfix * Fix the key_app_writer example which was writing a leading zero byte which was creating an invalid ASN.1 tag. Found by Aryeh R. Fixes #1257. * Fix compilation error on C++, because of a variable named new. Found and fixed by Hirotaka Niisato in #1783. * Fix "no symbols" warning issued by ranlib when building on Mac OS X. Fix contributed by tabascoeye. * Clarify documentation for mbedtls_ssl_write() to include 0 as a valid return value. Found by @davidwu2000. #839 * Fix a memory leak in mbedtls_x509_csr_parse(), found by catenacyber, Philippe Antoine. Fixes #1623. * Remove unused headers included in x509.c. Found by Chris Hanson and fixed by Brendan Shanks. Part of a fix for #992. * Fix compilation error when MBEDTLS_ARC4_C is disabled and MBEDTLS_CIPHER_NULL_CIPHER is enabled. Found by TrinityTonic in #1719. * Added length checks to some TLS parsing functions. Found and fixed by Philippe Antoine from Catena cyber. #1663. * Fix the inline assembly for the MPI multiply helper function for i386 and i386 with SSE2. Found by László Langó. Fixes #1550 * Fix namespacing in header files. Remove the `mbedtls` namespacing in the `#include` in the header files. Resolves #857 * Fix compiler warning of 'use before initialisation' in mbedtls_pk_parse_key(). Found by Martin Boye Petersen and fixed by Dawid Drozd. #1098 * Fix decryption for zero length messages (which contain all padding) when a CBC based ciphersuite is used together with Encrypt-then-MAC. Previously, such a message was wrongly reported as an invalid record and therefore lead to the connection being terminated. Seen most often with OpenSSL using TLS 1.0. Reported by @kFYatek and by Conor Murphy on the forum. Fix contributed by Espressif Systems. Fixes #1632 * Fix ssl_client2 example to send application data with 0-length content when the request_size argument is set to 0 as stated in the documentation. Fixes #1833. * Correct the documentation for `mbedtls_ssl_get_session()`. This API has deep copy of the session, and the peer certificate is not lost. Fixes #926. * Fix build using -std=c99. Fixed by Nick Wilson. Changes * Fail when receiving a TLS alert message with an invalid length, or invalid zero-length messages when using TLS 1.2. Contributed by Espressif Systems. * Change the default behaviour of mbedtls_hkdf_extract() to return an error when calling with a NULL salt and non-zero salt_len. Contributed by Brian J Murray * Change the shebang line in Perl scripts to look up perl in the PATH. Contributed by fbrosson. * Allow overriding the time on Windows via the platform-time abstraction. Fixed by Nick Wilson. * Use gmtime_r/gmtime_s for thread-safety. Fixed by Nick Wilson. = mbed TLS 2.11.0 branch released 2018-06-18 Features * Add additional block mode, OFB (Output Feedback), to the AES module and cipher abstraction module. * Implement the HMAC-based extract-and-expand key derivation function (HKDF) per RFC 5869. Contributed by Thomas Fossati. * Add support for the CCM* block cipher mode as defined in IEEE Std. 802.15.4. * Add support for the XTS block cipher mode with AES (AES-XTS). Contributed by Aorimn in pull request #414. * In TLS servers, support offloading private key operations to an external cryptoprocessor. Private key operations can be asynchronous to allow non-blocking operation of the TLS server stack. Bugfix * Fix the cert_write example to handle certificates signed with elliptic curves as well as RSA. Fixes #777 found by dbedev. * Fix for redefinition of _WIN32_WINNT to avoid overriding a definition used by user applications. Found and fixed by Fabio Alessandrelli. * Fix compilation warnings with IAR toolchain, on 32 bit platform. Reported by rahmanih in #683 * Fix braces in mbedtls_memory_buffer_alloc_status(). Found by sbranden, #552. Changes * Changed CMake defaults for IAR to treat all compiler warnings as errors. * Changed the Clang parameters used in the CMake build files to work for versions later than 3.6. Versions of Clang earlier than this may no longer work. Fixes #1072 = mbed TLS 2.10.0 branch released 2018-06-06 Features * Add support for ARIA cipher (RFC 5794) and associated TLS ciphersuites (RFC 6209). Disabled by default, see MBEDTLS_ARIA_C in config.h API Changes * Extend the platform module with a util component that contains functionality shared by multiple Mbed TLS modules. At this stage platform_util.h (and its associated platform_util.c) only contain mbedtls_platform_zeroize(), which is a critical function from a security point of view. mbedtls_platform_zeroize() needs to be regularly tested against compilers to ensure that calls to it are not removed from the output binary as part of redundant code elimination optimizations. Therefore, mbedtls_platform_zeroize() is moved to the platform module to facilitate testing and maintenance. Bugfix * Fix an issue with MicroBlaze support in bn_mul.h which was causing the build to fail. Found by zv-io. Fixes #1651. Changes * Support TLS testing in out-of-source builds using cmake. Fixes #1193. * Fix redundant declaration of mbedtls_ssl_list_ciphersuites. Raised by TrinityTonic. #1359. = mbed TLS 2.9.0 branch released 2018-04-30 Security * Fix an issue in the X.509 module which could lead to a buffer overread during certificate validation. Additionally, the issue could also lead to unnecessary callback checks being made or to some validation checks to be omitted. The overread could be triggered remotely, while the other issues would require a non DER-compliant certificate to be correctly signed by a trusted CA, or a trusted CA with a non DER-compliant certificate. Found by luocm. Fixes #825. * Fix the buffer length assertion in the ssl_parse_certificate_request() function which led to an arbitrary overread of the message buffer. The overreads could be caused by receiving a malformed message at the point where an optional signature algorithms list is expected when the signature algorithms section is too short. In builds with debug output, the overread data is output with the debug data. * Fix a client-side bug in the validation of the server's ciphersuite choice which could potentially lead to the client accepting a ciphersuite it didn't offer or a ciphersuite that cannot be used with the TLS or DTLS version chosen by the server. This could lead to corruption of internal data structures for some configurations. Features * Add an option, MBEDTLS_AES_FEWER_TABLES, to dynamically compute smaller AES tables during runtime, thereby reducing the RAM/ROM footprint by ~6KiB. Suggested and contributed by jkivilin in pull request #394. * Add initial support for Curve448 (RFC 7748). Only mbedtls_ecp_mul() and ECDH primitive functions (mbedtls_ecdh_gen_public(), mbedtls_ecdh_compute_shared()) are supported for now. Contributed by Nicholas Wilson in pull request #348. API Changes * Extend the public API with the function of mbedtls_net_poll() to allow user applications to wait for a network context to become ready before reading or writing. * Add function mbedtls_ssl_check_pending() to the public API to allow a check for whether more more data is pending to be processed in the internal message buffers. This function is necessary to determine when it is safe to idle on the underlying transport in case event-driven IO is used. Bugfix * Fix a spurious uninitialized variable warning in cmac.c. Fix independently contributed by Brian J Murray and David Brown. * Add missing dependencies in test suites that led to build failures in configurations that omit certain hashes or public-key algorithms. Fixes #1040. * Fix C89 incompatibility in benchmark.c. Contributed by Brendan Shanks. #1353 * Add missing dependencies for MBEDTLS_HAVE_TIME_DATE and MBEDTLS_VERSION_FEATURES in some test suites. Contributed by Deomid Ryabkov. Fixes #1299, #1475. * Fix the Makefile build process for building shared libraries on Mac OS X. Fixed by mnacamura. * Fix parsing of PKCS#8 encoded Elliptic Curve keys. Previously Mbed TLS was unable to parse keys which had only the optional parameters field of the ECPrivateKey structure. Found by Jethro Beekman, fixed in #1379. * Return the plaintext data more quickly on unpadded CBC decryption, as stated in the mbedtls_cipher_update() documentation. Contributed by Andy Leiserson. * Fix overriding and ignoring return values when parsing and writing to a file in pk_sign program. Found by kevlut in #1142. * Restrict usage of error code MBEDTLS_ERR_SSL_WANT_READ to situations where data needs to be fetched from the underlying transport in order to make progress. Previously, this error code was also occasionally returned when unexpected messages were being discarded, ignoring that further messages could potentially already be pending to be processed in the internal buffers; these cases led to deadlocks when event-driven I/O was used. Found and reported by Hubert Mis in #772. * Fix buffer length assertions in the ssl_parse_certificate_request() function which leads to a potential one byte overread of the message buffer. * Fix invalid buffer sizes passed to zlib during record compression and decompression. * Fix the soversion of libmbedcrypto to match the soversion of the maintained 2.7 branch. The soversion was increased in Mbed TLS version 2.7.1 to reflect breaking changes in that release, but the increment was missed in 2.8.0 and later releases outside of the 2.7 branch. Changes * Remove some redundant code in bignum.c. Contributed by Alexey Skalozub. * Support cmake builds where Mbed TLS is a subproject. Fix contributed independently by Matthieu Volat and Arne Schwabe. * Improve testing in configurations that omit certain hashes or public-key algorithms. Includes contributions by Gert van Dijk. * Improve negative testing of X.509 parsing. * Do not define global mutexes around readdir() and gmtime() in configurations where the feature is disabled. Found and fixed by Gergely Budai. * Harden the function mbedtls_ssl_config_free() against misuse, so that it doesn't leak memory if the user doesn't use mbedtls_ssl_conf_psk() and instead incorrectly manipulates the configuration structure directly. Found and fix submitted by junyeonLEE in #1220. * Provide an empty implementation of mbedtls_pkcs5_pbes2() when MBEDTLS_ASN1_PARSE_C is not enabled. This allows the use of PBKDF2 without PBES2. Fixed by Marcos Del Sol Vives. * Add the order of the base point as N in the mbedtls_ecp_group structure for Curve25519 (other curves had it already). Contributed by Nicholas Wilson #481 * Improve the documentation of mbedtls_net_accept(). Contributed by Ivan Krylov. * Improve the documentation of mbedtls_ssl_write(). Suggested by Paul Sokolovsky in #1356. * Add an option in the Makefile to support ar utilities where the operation letter must not be prefixed by '-', such as LLVM. Found and fixed by Alex Hixon. * Allow configuring the shared library extension by setting the DLEXT environment variable when using the project makefiles. * Optimize unnecessary zeroing in mbedtls_mpi_copy. Based on a contribution by Alexey Skalozub in #405. * In the SSL module, when f_send, f_recv or f_recv_timeout report transmitting more than the required length, return an error. Raised by Sam O'Connor in #1245. * Improve robustness of mbedtls_ssl_derive_keys against the use of HMAC functions with non-HMAC ciphersuites. Independently contributed by Jiayuan Chen in #1377. Fixes #1437. * Improve security of RSA key generation by including criteria from FIPS 186-4. Contributed by Jethro Beekman. #1380 * Declare functions in header files even when an alternative implementation of the corresponding module is activated by defining the corresponding MBEDTLS_XXX_ALT macro. This means that alternative implementations do not need to copy the declarations, and ensures that they will have the same API. * Add platform setup and teardown calls in test suites. = mbed TLS 2.8.0 branch released 2018-03-16 Default behavior changes * The truncated HMAC extension now conforms to RFC 6066. This means that when both sides of a TLS connection negotiate the truncated HMAC extension, Mbed TLS can now interoperate with other compliant implementations, but this breaks interoperability with prior versions of Mbed TLS. To restore the old behavior, enable the (deprecated) option MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT in config.h. Found by Andreas Walz (ivESK, Offenburg University of Applied Sciences). Security * Fix implementation of the truncated HMAC extension. The previous implementation allowed an offline 2^80 brute force attack on the HMAC key of a single, uninterrupted connection (with no resumption of the session). * Verify results of RSA private key operations to defend against Bellcore glitch attack. * Fix a buffer overread in ssl_parse_server_key_exchange() that could cause a crash on invalid input. * Fix a buffer overread in ssl_parse_server_psk_hint() that could cause a crash on invalid input. * Fix CRL parsing to reject CRLs containing unsupported critical extensions. Found by Falko Strenzke and Evangelos Karatsiolis. Features * Extend PKCS#8 interface by introducing support for the entire SHA algorithms family when encrypting private keys using PKCS#5 v2.0. This allows reading encrypted PEM files produced by software that uses PBKDF2-SHA2, such as OpenSSL 1.1. Submitted by Antonio Quartulli, OpenVPN Inc. Fixes #1339 * Add support for public keys encoded in PKCS#1 format. #1122 New deprecations * Deprecate support for record compression (configuration option MBEDTLS_ZLIB_SUPPORT). Bugfix * Fix the name of a DHE parameter that was accidentally changed in 2.7.0. Fixes #1358. * Fix test_suite_pk to work on 64-bit ILP32 systems. #849 * Fix mbedtls_x509_crt_profile_suiteb, which used to reject all certificates with flag MBEDTLS_X509_BADCERT_BAD_PK even when the key type was correct. In the context of SSL, this resulted in handshake failure. Reported by daniel in the Mbed TLS forum. #1351 * Fix Windows x64 builds with the included mbedTLS.sln file. #1347 * Fix setting version TLSv1 as minimal version, even if TLS 1 is not enabled. Set MBEDTLS_SSL_MIN_MAJOR_VERSION and MBEDTLS_SSL_MIN_MINOR_VERSION instead of MBEDTLS_SSL_MAJOR_VERSION_3 and MBEDTLS_SSL_MINOR_VERSION_1. #664 * Fix compilation error on Mingw32 when _TRUNCATE is defined. Use _TRUNCATE only if __MINGW32__ not defined. Fix suggested by Thomas Glanzmann and Nick Wilson on issue #355 * In test_suite_pk, pass valid parameters when testing for hash length overflow. #1179 * Fix memory allocation corner cases in memory_buffer_alloc.c module. Found by Guido Vranken. #639 * Log correct number of ciphersuites used in Client Hello message. #918 * Fix X509 CRT parsing that would potentially accept an invalid tag when parsing the subject alternative names. * Fix a possible arithmetic overflow in ssl_parse_server_key_exchange() that could cause a key exchange to fail on valid data. * Fix a possible arithmetic overflow in ssl_parse_server_psk_hint() that could cause a key exchange to fail on valid data. * Don't define mbedtls_aes_decrypt and mbedtls_aes_encrypt under MBEDTLS_DEPRECATED_REMOVED. #1388 * Fix a 1-byte heap buffer overflow (read-only) during private key parsing. Found through fuzz testing. Changes * Fix tag lengths and value ranges in the documentation of CCM encryption. Contributed by Mathieu Briand. * Fix typo in a comment ctr_drbg.c. Contributed by Paul Sokolovsky. * Remove support for the library reference configuration for picocoin. * MD functions deprecated in 2.7.0 are no longer inline, to provide a migration path for those depending on the library's ABI. * Clarify the documentation of mbedtls_ssl_setup. * Use (void) when defining functions with no parameters. Contributed by Joris Aerts. #678 = mbed TLS 2.7.0 branch released 2018-02-03 Security * Fix a heap corruption issue in the implementation of the truncated HMAC extension. When the truncated HMAC extension is enabled and CBC is used, sending a malicious application packet could be used to selectively corrupt 6 bytes on the peer's heap, which could potentially lead to crash or remote code execution. The issue could be triggered remotely from either side in both TLS and DTLS. CVE-2018-0488 * Fix a buffer overflow in RSA-PSS verification when the hash was too large for the key size, which could potentially lead to crash or remote code execution. Found by Seth Terashima, Qualcomm Product Security Initiative, Qualcomm Technologies Inc. CVE-2018-0487 * Fix buffer overflow in RSA-PSS verification when the unmasked data is all zeros. * Fix an unsafe bounds check in ssl_parse_client_psk_identity() when adding 64 KiB to the address of the SSL buffer and causing a wrap around. * Fix a potential heap buffer overflow in mbedtls_ssl_write(). When the (by default enabled) maximum fragment length extension is disabled in the config and the application data buffer passed to mbedtls_ssl_write is larger than the internal message buffer (16384 bytes by default), the latter overflows. The exploitability of this issue depends on whether the application layer can be forced into sending such large packets. The issue was independently reported by Tim Nordell via e-mail and by Florin Petriuc and sjorsdewit on GitHub. Fix proposed by Florin Petriuc in #1022. Fixes #707. * Add a provision to prevent compiler optimizations breaking the time constancy of mbedtls_ssl_safer_memcmp(). * Ensure that buffers are cleared after use if they contain sensitive data. Changes were introduced in multiple places in the library. * Set PEM buffer to zero before freeing it, to avoid decoded private keys being leaked to memory after release. * Fix dhm_check_range() failing to detect trivial subgroups and potentially leaking 1 bit of the private key. Reported by prashantkspatil. * Make mbedtls_mpi_read_binary() constant-time with respect to the input data. Previously, trailing zero bytes were detected and omitted for the sake of saving memory, but potentially leading to slight timing differences. Reported by Marco Macchetti, Kudelski Group. * Wipe stack buffer temporarily holding EC private exponent after keypair generation. * Fix a potential heap buffer over-read in ALPN extension parsing (server-side). Could result in application crash, but only if an ALPN name larger than 16 bytes had been configured on the server. * Change default choice of DHE parameters from untrustworthy RFC 5114 to RFC 3526 containing parameters generated in a nothing-up-my-sleeve manner. Features * Allow comments in test data files. * The selftest program can execute a subset of the tests based on command line arguments. * New unit tests for timing. Improve the self-test to be more robust when run on a heavily-loaded machine. * Add alternative implementation support for CCM and CMAC (MBEDTLS_CCM_ALT, MBEDTLS_CMAC_ALT). Submitted by Steven Cooreman, Silicon Labs. * Add support for alternative implementations of GCM, selected by the configuration flag MBEDTLS_GCM_ALT. * Add support for alternative implementations for ECDSA, controlled by new configuration flags MBEDTLS_ECDSA_SIGN_ALT, MBEDTLS_ECDSA_VERIFY_ALT and MBEDTLS_ECDSDA_GENKEY_AT in config.h. The following functions from the ECDSA module can be replaced with alternative implementation: mbedtls_ecdsa_sign(), mbedtls_ecdsa_verify() and mbedtls_ecdsa_genkey(). * Add support for alternative implementation of ECDH, controlled by the new configuration flags MBEDTLS_ECDH_COMPUTE_SHARED_ALT and MBEDTLS_ECDH_GEN_PUBLIC_ALT in config.h. The following functions from the ECDH module can be replaced with an alternative implementation: mbedtls_ecdh_gen_public() and mbedtls_ecdh_compute_shared(). * Add support for alternative implementation of ECJPAKE, controlled by the new configuration flag MBEDTLS_ECJPAKE_ALT. * Add mechanism to provide alternative implementation of the DHM module. API Changes * Extend RSA interface by multiple functions allowing structure- independent setup and export of RSA contexts. Most notably, mbedtls_rsa_import() and mbedtls_rsa_complete() are introduced for setting up RSA contexts from partial key material and having them completed to the needs of the implementation automatically. This allows to setup private RSA contexts from keys consisting of N,D,E only, even if P,Q are needed for the purpose or CRT and/or blinding. * The configuration option MBEDTLS_RSA_ALT can be used to define alternative implementations of the RSA interface declared in rsa.h. * The following functions in the message digest modules (MD2, MD4, MD5, SHA1, SHA256, SHA512) have been deprecated and replaced as shown below. The new functions change the return type from void to int to allow returning error codes when using MBEDTLS__ALT. mbedtls__starts() -> mbedtls__starts_ret() mbedtls__update() -> mbedtls__update_ret() mbedtls__finish() -> mbedtls__finish_ret() mbedtls__process() -> mbedtls_internal__process() New deprecations * Deprecate usage of RSA primitives with non-matching key-type (e.g. signing with a public key). * Direct manipulation of structure fields of RSA contexts is deprecated. Users are advised to use the extended RSA API instead. * Deprecate usage of message digest functions that return void (mbedtls__starts, mbedtls__update, mbedtls__finish and mbedtls__process where is any of MD2, MD4, MD5, SHA1, SHA256, SHA512) in favor of functions that can return an error code. * Deprecate untrustworthy DHE parameters from RFC 5114. Superseded by parameters from RFC 3526 or the newly added parameters from RFC 7919. * Deprecate hex string DHE constants MBEDTLS_DHM_RFC3526_MODP_2048_P etc. Supserseded by binary encoded constants MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN etc. * Deprecate mbedtls_ssl_conf_dh_param() for setting default DHE parameters from hex strings. Superseded by mbedtls_ssl_conf_dh_param_bin() accepting DHM parameters in binary form, matching the new constants. Bugfix * Fix ssl_parse_record_header() to silently discard invalid DTLS records as recommended in RFC 6347 Section 4.1.2.7. * Fix memory leak in mbedtls_ssl_set_hostname() when called multiple times. Found by projectgus and Jethro Beekman, #836. * Fix usage help in ssl_server2 example. Found and fixed by Bei Lin. * Parse signature algorithm extension when renegotiating. Previously, renegotiated handshakes would only accept signatures using SHA-1 regardless of the peer's preferences, or fail if SHA-1 was disabled. * Fix leap year calculation in x509_date_is_valid() to ensure that invalid dates on leap years with 100 and 400 intervals are handled correctly. Found by Nicholas Wilson. #694 * Fix some invalid RSA-PSS signatures with keys of size 8N+1 that were accepted. Generating these signatures required the private key. * Fix out-of-memory problem when parsing 4096-bit PKCS8-encrypted RSA keys. Found independently by Florian in the mbed TLS forum and by Mishamax. #878, #1019. * Fix variable used before assignment compilation warnings with IAR toolchain. Found by gkerrien38. * Fix unchecked return codes from AES, DES and 3DES functions in pem_aes_decrypt(), pem_des_decrypt() and pem_des3_decrypt() respectively. If a call to one of the functions of the cryptographic primitive modules failed, the error may not be noticed by the function mbedtls_pem_read_buffer() causing it to return invalid values. Found by Guido Vranken. #756 * Include configuration file in md.h, to fix compilation warnings. Reported by aaronmdjones in #1001 * Correct extraction of signature-type from PK instance in X.509 CRT and CSR writing routines that prevented these functions to work with alternative RSA implementations. Raised by J.B. in the Mbed TLS forum. Fixes #1011. * Don't print X.509 version tag for v1 CRT's, and omit extensions for non-v3 CRT's. * Fix bugs in RSA test suite under MBEDTLS_NO_PLATFORM_ENTROPY. #1023 #1024 * Fix net_would_block() to avoid modification by errno through fcntl() call. Found by nkolban. Fixes #845. * Fix handling of handshake messages in mbedtls_ssl_read() in case MBEDTLS_SSL_RENEGOTIATION is disabled. Found by erja-gp. * Add a check for invalid private parameters in mbedtls_ecdsa_sign(). Reported by Yolan Romailler. * Fix word size check in in pk.c to not depend on MBEDTLS_HAVE_INT64. * Fix incorrect unit in benchmark output. #850 * Add size-checks for record and handshake message content, securing fragile yet non-exploitable code-paths. * Fix crash when calling mbedtls_ssl_cache_free() twice. Found by MilenkoMitrovic, #1104 * Fix mbedtls_timing_alarm(0) on Unix and MinGW. * Fix use of uninitialized memory in mbedtls_timing_get_timer() when reset=1. * Fix possible memory leaks in mbedtls_gcm_self_test(). * Added missing return code checks in mbedtls_aes_self_test(). * Fix issues in RSA key generation program programs/x509/rsa_genkey and the RSA test suite where the failure of CTR DRBG initialization lead to freeing an RSA context and several MPI's without proper initialization beforehand. * Fix error message in programs/pkey/gen_key.c. Found and fixed by Chris Xue. * Fix programs/pkey/dh_server.c so that it actually works with dh_client.c. Found and fixed by Martijn de Milliano. * Fix an issue in the cipher decryption with the mode MBEDTLS_PADDING_ONE_AND_ZEROS that sometimes accepted invalid padding. Note, this padding mode is not used by the TLS protocol. Found and fixed by Micha Kraus. * Fix the entropy.c module to not call mbedtls_sha256_starts() or mbedtls_sha512_starts() in the mbedtls_entropy_init() function. * Fix the entropy.c module to ensure that mbedtls_sha256_init() or mbedtls_sha512_init() is called before operating on the relevant context structure. Do not assume that zeroizing a context is a correct way to reset it. Found independently by ccli8 on Github. * In mbedtls_entropy_free(), properly free the message digest context. * Fix status handshake status message in programs/ssl/dtls_client.c. Found and fixed by muddog. Changes * Extend cert_write example program by options to set the certificate version and the message digest. Further, allow enabling/disabling of authority identifier, subject identifier and basic constraints extensions. * Only check for necessary RSA structure fields in `mbedtls_rsa_private`. In particular, don't require P,Q if neither CRT nor blinding are used. Reported and fix proposed independently by satur9nine and sliai on GitHub. * Only run AES-192 self-test if AES-192 is available. Fixes #963. * Tighten the RSA PKCS#1 v1.5 signature verification code and remove the undeclared dependency of the RSA module on the ASN.1 module. * Update all internal usage of deprecated message digest functions to the new ones with return codes. In particular, this modifies the mbedtls_md_info_t structure. Propagate errors from these functions everywhere except some locations in the ssl_tls.c module. * Improve CTR_DRBG error handling by propagating underlying AES errors. * Add MBEDTLS_ERR_XXX_HW_ACCEL_FAILED error codes for all cryptography modules where the software implementation can be replaced by a hardware implementation. * Add explicit warnings for the use of MD2, MD4, MD5, SHA-1, DES and ARC4 throughout the library. = mbed TLS 2.6.0 branch released 2017-08-10 Security * Fix authentication bypass in SSL/TLS: when authmode is set to optional, mbedtls_ssl_get_verify_result() would incorrectly return 0 when the peer's X.509 certificate chain had more than MBEDTLS_X509_MAX_INTERMEDIATE_CA (default: 8) intermediates, even when it was not trusted. This could be triggered remotely from either side. (With authmode set to 'required' (the default), the handshake was correctly aborted). * Reliably wipe sensitive data after use in the AES example applications programs/aes/aescrypt2 and programs/aes/crypt_and_hash. Found by Laurent Simon. Features * Add the functions mbedtls_platform_setup() and mbedtls_platform_teardown() and the context struct mbedtls_platform_context to perform platform-specific setup and teardown operations. The macro MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT allows the functions to be overridden by the user in a platform_alt.h file. These new functions are required in some embedded environments to provide a means of initialising underlying cryptographic acceleration hardware. API Changes * Reverted API/ABI breaking changes introduced in mbed TLS 2.5.1, to make the API consistent with mbed TLS 2.5.0. Specifically removed the inline qualifier from the functions mbedtls_aes_decrypt, mbedtls_aes_encrypt, mbedtls_ssl_ciphersuite_uses_ec and mbedtls_ssl_ciphersuite_uses_psk. Found by James Cowgill. #978 * Certificate verification functions now set flags to -1 in case the full chain was not verified due to an internal error (including in the verify callback) or chain length limitations. * With authmode set to optional, the TLS handshake is now aborted if the verification of the peer's certificate failed due to an overlong chain or a fatal error in the verify callback. Bugfix * Add a check if iv_len is zero in GCM, and return an error if it is zero. Reported by roberto. #716 * Replace preprocessor condition from #if defined(MBEDTLS_THREADING_PTHREAD) to #if defined(MBEDTLS_THREADING_C) as the library cannot assume they will always be implemented by pthread support. #696 * Fix a resource leak on Windows platforms in mbedtls_x509_crt_parse_path(), in the case of an error. Found by redplait. #590 * Add MBEDTLS_MPI_CHK to check for error value of mbedtls_mpi_fill_random. Reported and fix suggested by guidovranken. #740 * Fix conditional preprocessor directives in bignum.h to enable 64-bit compilation when using ARM Compiler 6. * Fix a potential integer overflow in the version verification for DER encoded X.509 CRLs. The overflow could enable maliciously constructed CRLs to bypass the version verification check. Found by Peng Li/Yueh-Hsun Lin, KNOX Security, Samsung Research America * Fix potential integer overflow in the version verification for DER encoded X.509 CSRs. The overflow could enable maliciously constructed CSRs to bypass the version verification check. Found by Peng Li/Yueh-Hsun Lin, KNOX Security, Samsung Research America * Fix a potential integer overflow in the version verification for DER encoded X.509 certificates. The overflow could enable maliciously constructed certificates to bypass the certificate verification check. * Fix a call to the libc function time() to call the platform abstraction function mbedtls_time() instead. Found by wairua. #666 * Avoid shadowing of time and index functions through mbed TLS function arguments. Found by inestlerode. #557. Changes * Added config.h option MBEDTLS_NO_UDBL_DIVISION, to prevent the use of 64-bit division. This is useful on embedded platforms where 64-bit division created a dependency on external libraries. #708 * Removed mutexes from ECP hardware accelerator code. Now all hardware accelerator code in the library leaves concurrency handling to the platform. Reported by Steven Cooreman. #863 * Define the macro MBEDTLS_AES_ROM_TABLES in the configuration file config-no-entropy.h to reduce the RAM footprint. * Added a test script that can be hooked into git that verifies commits before they are pushed. * Improve documentation of PKCS1 decryption functions. = mbed TLS 2.5.1 released 2017-06-21 Security * Fixed unlimited overread of heap-based buffer in mbedtls_ssl_read(). The issue could only happen client-side with renegotiation enabled. Could result in DoS (application crash) or information leak (if the application layer sent data read from mbedtls_ssl_read() back to the server or to a third party). Can be triggered remotely. * Removed SHA-1 and RIPEMD-160 from the default hash algorithms for certificate verification. SHA-1 can be turned back on with a compile-time option if needed. * Fixed offset in FALLBACK_SCSV parsing that caused TLS server to fail to detect it sometimes. Reported by Hugo Leisink. #810 * Tighten parsing of RSA PKCS#1 v1.5 signatures, to avoid a potential Bleichenbacher/BERserk-style attack. Bugfix * Remove size zero arrays from ECJPAKE test suite. Size zero arrays are not valid C and they prevented the test from compiling in Visual Studio 2015 and with GCC using the -Wpedantic compilation option. * Fix insufficient support for signature-hash-algorithm extension, resulting in compatibility problems with Chrome. Found by hfloyrd. #823 * Fix behaviour that hid the original cause of fatal alerts in some cases when sending the alert failed. The fix makes sure not to hide the error that triggered the alert. * Fix SSLv3 renegotiation behaviour and stop processing data received from peer after sending a fatal alert to refuse a renegotiation attempt. Previous behaviour was to keep processing data even after the alert has been sent. * Accept empty trusted CA chain in authentication mode MBEDTLS_SSL_VERIFY_OPTIONAL. Found by Jethro Beekman. #864 * Fix implementation of mbedtls_ssl_parse_certificate() to not annihilate fatal errors in authentication mode MBEDTLS_SSL_VERIFY_OPTIONAL and to reflect bad EC curves within verification result. * Fix bug that caused the modular inversion function to accept the invalid modulus 1 and therefore to hang. Found by blaufish. #641. * Fix incorrect sign computation in modular exponentiation when the base is a negative MPI. Previously the result was always negative. Found by Guido Vranken. * Fix a numerical underflow leading to stack overflow in mpi_read_file() that was triggered uppon reading an empty line. Found by Guido Vranken. Changes * Send fatal alerts in more cases. The previous behaviour was to skip sending the fatal alert and just drop the connection. * Clarify ECDSA documentation and improve the sample code to avoid misunderstanding and potentially dangerous use of the API. Pointed out by Jean-Philippe Aumasson. = mbed TLS 2.5.0 branch released 2017-05-17 Security * Wipe stack buffers in RSA private key operations (rsa_rsaes_pkcs1_v15_decrypt(), rsa_rsaes_oaep_decrypt). Found by Laurent Simon. * Add exponent blinding to RSA private operations as a countermeasure against side-channel attacks like the cache attack described in https://arxiv.org/abs/1702.08719v2. Found and fix proposed by Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and Stefan Mangard. Features * Add hardware acceleration support for the Elliptic Curve Point module. This involved exposing parts of the internal interface to enable replacing the core functions and adding and alternative, module level replacement support for enabling the extension of the interface. * Add a new configuration option to 'mbedtls_ssl_config' to enable suppressing the CA list in Certificate Request messages. The default behaviour has not changed, namely every configured CAs name is included. API Changes * The following functions in the AES module have been deprecated and replaced by the functions shown below. The new functions change the return type from void to int to allow returning error codes when using MBEDTLS_AES_ALT, MBEDTLS_AES_DECRYPT_ALT or MBEDTLS_AES_ENCRYPT_ALT. mbedtls_aes_decrypt() -> mbedtls_internal_aes_decrypt() mbedtls_aes_encrypt() -> mbedtls_internal_aes_encrypt() Bugfix * Remove macros from compat-1.3.h that correspond to deleted items from most recent versions of the library. Found by Kyle Keen. * Fixed issue in the Threading module that prevented mutexes from initialising. Found by sznaider. #667 #843 * Add checks in the PK module for the RSA functions on 64-bit systems. The PK and RSA modules use different types for passing hash length and without these checks the type cast could lead to data loss. Found by Guido Vranken. = mbed TLS 2.4.2 branch released 2017-03-08 Security * Add checks to prevent signature forgeries for very large messages while using RSA through the PK module in 64-bit systems. The issue was caused by some data loss when casting a size_t to an unsigned int value in the functions rsa_verify_wrap(), rsa_sign_wrap(), rsa_alt_sign_wrap() and mbedtls_pk_sign(). Found by Jean-Philippe Aumasson. * Fixed potential livelock during the parsing of a CRL in PEM format in mbedtls_x509_crl_parse(). A string containing a CRL followed by trailing characters after the footer could result in the execution of an infinite loop. The issue can be triggered remotely. Found by Greg Zaverucha, Microsoft. * Removed MD5 from the allowed hash algorithms for CertificateRequest and CertificateVerify messages, to prevent SLOTH attacks against TLS 1.2. Introduced by interoperability fix for #513. * Fixed a bug that caused freeing a buffer that was allocated on the stack, when verifying the validity of a key on secp224k1. This could be triggered remotely for example with a maliciously constructed certificate and potentially could lead to remote code execution on some platforms. Reported independently by rongsaws and Aleksandar Nikolic, Cisco Talos team. #569 CVE-2017-2784 Bugfix * Fix output certificate verification flags set by x509_crt_verify_top() when traversing a chain of trusted CA. The issue would cause both flags, MBEDTLS_X509_BADCERT_NOT_TRUSTED and MBEDTLS_X509_BADCERT_EXPIRED, to be set when the verification conditions are not met regardless of the cause. Found by Harm Verhagen and inestlerode. #665 #561 * Fix the redefinition of macro ssl_set_bio to an undefined symbol mbedtls_ssl_set_bio_timeout in compat-1.3.h, by removing it. Found by omlib-lin. #673 * Fix unused variable/function compilation warnings in pem.c, x509_crt.c and x509_csr.c that are reported when building mbed TLS with a config.h that does not define MBEDTLS_PEM_PARSE_C. Found by omnium21. #562 * Fix incorrect renegotiation condition in ssl_check_ctr_renegotiate() that would compare 64 bits of the record counter instead of 48 bits as indicated in RFC 6347 Section 4.3.1. This could cause the execution of the renegotiation routines at unexpected times when the protocol is DTLS. Found by wariua. #687 * Fixed multiple buffer overreads in mbedtls_pem_read_buffer() when parsing the input string in PEM format to extract the different components. Found by Eyal Itkin. * Fixed potential arithmetic overflow in mbedtls_ctr_drbg_reseed() that could cause buffer bound checks to be bypassed. Found by Eyal Itkin. * Fixed potential arithmetic overflows in mbedtls_cipher_update() that could cause buffer bound checks to be bypassed. Found by Eyal Itkin. * Fixed potential arithmetic overflow in mbedtls_md2_update() that could cause buffer bound checks to be bypassed. Found by Eyal Itkin. * Fixed potential arithmetic overflow in mbedtls_base64_decode() that could cause buffer bound checks to be bypassed. Found by Eyal Itkin. * Fixed heap overreads in mbedtls_x509_get_time(). Found by Peng Li/Yueh-Hsun Lin, KNOX Security, Samsung Research America. * Fix potential memory leak in mbedtls_x509_crl_parse(). The leak was caused by missing calls to mbedtls_pem_free() in cases when a MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT error was encountered. Found and fix proposed by Guido Vranken. #722 * Fixed the templates used to generate project and solution files for Visual Studio 2015 as well as the files themselves, to remove a build warning generated in Visual Studio 2015. Reported by Steve Valliere. #742 * Fix a resource leak in ssl_cookie, when using MBEDTLS_THREADING_C. Raised and fix suggested by Alan Gillingham in the mbed TLS forum. #771 * Fix 1 byte buffer overflow in mbedtls_mpi_write_string() when the MPI number to write in hexadecimal is negative and requires an odd number of digits. Found and fixed by Guido Vranken. * Fix unlisted DES configuration dependency in some pkparse test cases. Found by inestlerode. #555 = mbed TLS 2.4.1 branch released 2016-12-13 Changes * Update to CMAC test data, taken from - NIST Special Publication 800-38B - Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication – October 2016 = mbed TLS 2.4.0 branch released 2016-10-17 Security * Removed the MBEDTLS_SSL_AEAD_RANDOM_IV option, because it was not compliant with RFC-5116 and could lead to session key recovery in very long TLS sessions. "Nonce-Disrespecting Adversaries Practical Forgery Attacks on GCM in TLS" - H. Bock, A. Zauner, S. Devlin, J. Somorovsky, P. Jovanovic. https://eprint.iacr.org/2016/475.pdf * Fixed potential stack corruption in mbedtls_x509write_crt_der() and mbedtls_x509write_csr_der() when the signature is copied to the buffer without checking whether there is enough space in the destination. The issue cannot be triggered remotely. Found by Jethro Beekman. Features * Added support for CMAC for AES and 3DES and AES-CMAC-PRF-128, as defined by NIST SP 800-38B, RFC-4493 and RFC-4615. * Added hardware entropy selftest to verify that the hardware entropy source is functioning correctly. * Added a script to print build environment info for diagnostic use in test scripts, which is also now called by all.sh. * Added the macro MBEDTLS_X509_MAX_FILE_PATH_LEN that enables the user to configure the maximum length of a file path that can be buffered when calling mbedtls_x509_crt_parse_path(). * Added a configuration file config-no-entropy.h that configures the subset of library features that do not require an entropy source. * Added the macro MBEDTLS_ENTROPY_MIN_HARDWARE in config.h. This allows users to configure the minimum number of bytes for entropy sources using the mbedtls_hardware_poll() function. Bugfix * Fix for platform time abstraction to avoid dependency issues where a build may need time but not the standard C library abstraction, and added configuration consistency checks to check_config.h * Fix dependency issue in Makefile to allow parallel builds. * Fix incorrect handling of block lengths in crypt_and_hash.c sample program, when GCM is used. Found by udf2457. #441 * Fix for key exchanges based on ECDH-RSA or ECDH-ECDSA which weren't enabled unless others were also present. Found by David Fernandez. #428 * Fix for out-of-tree builds using CMake. Found by jwurzer, and fix based on a contribution from Tobias Tangemann. #541 * Fixed cert_app.c sample program for debug output and for use when no root certificates are provided. * Fix conditional statement that would cause a 1 byte overread in mbedtls_asn1_get_int(). Found and fixed by Guido Vranken. #599 * Fixed pthread implementation to avoid unintended double initialisations and double frees. Found by Niklas Amnebratt. * Fixed the sample applications gen_key.c, cert_req.c and cert_write.c for builds where the configuration MBEDTLS_PEM_WRITE_C is not defined. Found by inestlerode. #559. * Fix mbedtls_x509_get_sig() to update the ASN1 type in the mbedtls_x509_buf data structure until after error checks are successful. Found by subramanyam-c. #622 * Fix documentation and implementation missmatch for function arguments of mbedtls_gcm_finish(). Found by cmiatpaar. #602 * Guarantee that P>Q at RSA key generation. Found by inestlerode. #558 * Fix potential byte overread when verifying malformed SERVER_HELLO in ssl_parse_hello_verify_request() for DTLS. Found by Guido Vranken. * Fix check for validity of date when parsing in mbedtls_x509_get_time(). Found by subramanyam-c. #626 * Fix compatibility issue with Internet Explorer client authentication, where the limited hash choices prevented the client from sending its certificate. Found by teumas. #513 * Fix compilation without MBEDTLS_SELF_TEST enabled. Changes * Extended test coverage of special cases, and added new timing test suite. * Removed self-tests from the basic-built-test.sh script, and added all missing self-tests to the test suites, to ensure self-tests are only executed once. * Added support for 3 and 4 byte lengths to mbedtls_asn1_write_len(). * Added support for a Yotta specific configuration file - through the symbol YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE. * Added optimization for code space for X.509/OID based on configured features. Contributed by Aviv Palivoda. * Renamed source file library/net.c to library/net_sockets.c to avoid naming collision in projects which also have files with the common name net.c. For consistency, the corresponding header file, net.h, is marked as deprecated, and its contents moved to net_sockets.h. * Changed the strategy for X.509 certificate parsing and validation, to no longer disregard certificates with unrecognised fields. = mbed TLS 2.3.0 branch released 2016-06-28 Security * Fix missing padding length check in mbedtls_rsa_rsaes_pkcs1_v15_decrypt required by PKCS1 v2.2 * Fix potential integer overflow to buffer overflow in mbedtls_rsa_rsaes_pkcs1_v15_encrypt and mbedtls_rsa_rsaes_oaep_encrypt (not triggerable remotely in (D)TLS). * Fix a potential integer underflow to buffer overread in mbedtls_rsa_rsaes_oaep_decrypt. It is not triggerable remotely in SSL/TLS. Features * Support for platform abstraction of the standard C library time() function. Bugfix * Fix bug in mbedtls_mpi_add_mpi() that caused wrong results when the three arguments where the same (in-place doubling). Found and fixed by Janos Follath. #309 * Fix potential build failures related to the 'apidoc' target, introduced in the previous patch release. Found by Robert Scheck. #390 #391 * Fix issue in Makefile that prevented building using armar. #386 * Fix memory leak that occurred only when ECJPAKE was enabled and ECDHE and ECDSA was disabled in config.h . The leak didn't occur by default. * Fix an issue that caused valid certificates to be rejected whenever an expired or not yet valid certificate was parsed before a valid certificate in the trusted certificate list. * Fix bug in mbedtls_x509_crt_parse that caused trailing extra data in the buffer after DER certificates to be included in the raw representation. * Fix issue that caused a hang when generating RSA keys of odd bitlength * Fix bug in mbedtls_rsa_rsaes_pkcs1_v15_encrypt that made null pointer dereference possible. * Fix issue that caused a crash if invalid curves were passed to mbedtls_ssl_conf_curves. #373 * Fix issue in ssl_fork_server which was preventing it from functioning. #429 * Fix memory leaks in test framework * Fix test in ssl-opt.sh that does not run properly with valgrind * Fix unchecked calls to mmbedtls_md_setup(). Fix by Brian Murray. #502 Changes * On ARM platforms, when compiling with -O0 with GCC, Clang or armcc5, don't use the optimized assembly for bignum multiplication. This removes the need to pass -fomit-frame-pointer to avoid a build error with -O0. * Disabled SSLv3 in the default configuration. * Optimized mbedtls_mpi_zeroize() for MPI integer size. (Fix by Alexey Skalozub). * Fix non-compliance server extension handling. Extensions for SSLv3 are now ignored, as required by RFC6101. = mbed TLS 2.2.1 released 2016-01-05 Security * Fix potential double free when mbedtls_asn1_store_named_data() fails to allocate memory. Only used for certificate generation, not triggerable remotely in SSL/TLS. Found by Rafał Przywara. #367 * Disable MD5 handshake signatures in TLS 1.2 by default to prevent the SLOTH attack on TLS 1.2 server authentication (other attacks from the SLOTH paper do not apply to any version of mbed TLS or PolarSSL). https://www.mitls.org/pages/attacks/SLOTH Bugfix * Fix over-restrictive length limit in GCM. Found by Andreas-N. #362 * Fix bug in certificate validation that caused valid chains to be rejected when the first intermediate certificate has pathLenConstraint=0. Found by Nicholas Wilson. Introduced in mbed TLS 2.2.0. #280 * Removed potential leak in mbedtls_rsa_rsassa_pkcs1_v15_sign(), found by JayaraghavendranK. #372 * Fix suboptimal handling of unexpected records that caused interop issues with some peers over unreliable links. Avoid dropping an entire DTLS datagram if a single record in a datagram is unexpected, instead only drop the record and look at subsequent records (if any are present) in the same datagram. Found by jeannotlapin. #345 = mbed TLS 2.2.0 released 2015-11-04 Security * Fix potential double free if mbedtls_ssl_conf_psk() is called more than once and some allocation fails. Cannot be forced remotely. Found by Guido Vranken, Intelworks. * Fix potential heap corruption on Windows when mbedtls_x509_crt_parse_path() is passed a path longer than 2GB. Cannot be triggered remotely. Found by Guido Vranken, Intelworks. * Fix potential buffer overflow in some asn1_write_xxx() functions. Cannot be triggered remotely unless you create X.509 certificates based on untrusted input or write keys of untrusted origin. Found by Guido Vranken, Intelworks. * The X509 max_pathlen constraint was not enforced on intermediate certificates. Found by Nicholas Wilson, fix and tests provided by Janos Follath. #280 and #319 Features * Experimental support for EC J-PAKE as defined in Thread 1.0.0. Disabled by default as the specification might still change. * Added a key extraction callback to accees the master secret and key block. (Potential uses include EAP-TLS and Thread.) Bugfix * Self-signed certificates were not excluded from pathlen counting, resulting in some valid X.509 being incorrectly rejected. Found and fix provided by Janos Follath. #319 * Fix build error with configurations where ECDHE-PSK is the only key exchange. Found and fix provided by Chris Hammond. #270 * Fix build error with configurations where RSA, RSA-PSK, ECDH-RSA or ECHD-ECDSA if the only key exchange. Multiple reports. #310 * Fixed a bug causing some handshakes to fail due to some non-fatal alerts not being properly ignored. Found by mancha and Kasom Koht-arsa, #308 * mbedtls_x509_crt_verify(_with_profile)() now also checks the key type and size/curve against the profile. Before that, there was no way to set a minimum key size for end-entity certificates with RSA keys. Found by Matthew Page of Scannex Electronics Ltd. * Fix failures in MPI on Sparc(64) due to use of bad assembly code. Found by Kurt Danielson. #292 * Fix typo in name of the extKeyUsage OID. Found by inestlerode, #314 * Fix bug in ASN.1 encoding of booleans that caused generated CA certificates to be rejected by some applications, including OS X Keychain. Found and fixed by Jonathan Leroy, Inikup. Changes * Improved performance of mbedtls_ecp_muladd() when one of the scalars is 1 or -1. = mbed TLS 2.1.2 released 2015-10-06 Security * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer overflow of the hostname or session ticket. Found by Guido Vranken, Intelworks. * Fix potential double-free if mbedtls_ssl_set_hs_psk() is called more than once in the same handhake and mbedtls_ssl_conf_psk() was used. Found and patch provided by Guido Vranken, Intelworks. Cannot be forced remotely. * Fix stack buffer overflow in pkcs12 decryption (used by mbedtls_pk_parse_key(file)() when the password is > 129 bytes. Found by Guido Vranken, Intelworks. Not triggerable remotely. * Fix potential buffer overflow in mbedtls_mpi_read_string(). Found by Guido Vranken, Intelworks. Not exploitable remotely in the context of TLS, but might be in other uses. On 32 bit machines, requires reading a string of close to or larger than 1GB to exploit; on 64 bit machines, would require reading a string of close to or larger than 2^62 bytes. * Fix potential random memory allocation in mbedtls_pem_read_buffer() on crafted PEM input data. Found and fix provided by Guido Vranken, Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you accept PEM data from an untrusted source. * Fix possible heap buffer overflow in base64_encoded() when the input buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken, Intelworks. Not trigerrable remotely in TLS. * Fix potential double-free if mbedtls_conf_psk() is called repeatedly on the same mbedtls_ssl_config object and memory allocation fails. Found by Guido Vranken, Intelworks. Cannot be forced remotely. * Fix potential heap buffer overflow in servers that perform client authentication against a crafted CA cert. Cannot be triggered remotely unless you allow third parties to pick trust CAs for client auth. Found by Guido Vranken, Intelworks. Bugfix * Fix compile error in net.c with musl libc. Found and patch provided by zhasha (#278). * Fix macroization of 'inline' keyword when building as C++. (#279) Changes * Added checking of hostname length in mbedtls_ssl_set_hostname() to ensure domain names are compliant with RFC 1035. * Fixed paths for check_config.h in example config files. (Found by bachp) (#291) = mbed TLS 2.1.1 released 2015-09-17 Security * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5 signatures. (Found by Florian Weimer, Red Hat.) https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/ * Fix possible client-side NULL pointer dereference (read) when the client tries to continue the handshake after it failed (a misuse of the API). (Found and patch provided by Fabian Foerg, Gotham Digital Science using afl-fuzz.) Bugfix * Fix warning when using a 64bit platform. (found by embedthis) (#275) * Fix off-by-one error in parsing Supported Point Format extension that caused some handshakes to fail. Changes * Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow use of mbedtls_x509_crt_profile_next. (found by NWilson) * When a client initiates a reconnect from the same port as a live connection, if cookie verification is available (MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be detected and mbedtls_ssl_read() will return MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new handshake with the same context. (See RFC 6347 section 4.2.8.) = mbed TLS 2.1.0 released 2015-09-04 Features * Added support for yotta as a build system. * Primary open source license changed to Apache 2.0 license. Bugfix * Fix segfault in the benchmark program when benchmarking DHM. * Fix build error with CMake and pre-4.5 versions of GCC (found by Hugo Leisink). * Fix bug when parsing a ServerHello without extensions (found by David Sears). * Fix bug in CMake lists that caused libmbedcrypto.a not to be installed (found by Benoit Lecocq). * Fix bug in Makefile that caused libmbedcrypto and libmbedx509 not to be installed (found by Rawi666). * Fix compile error with armcc 5 with --gnu option. * Fix bug in Makefile that caused programs not to be installed correctly (found by robotanarchy) (#232). * Fix bug in Makefile that prevented from installing without building the tests (found by robotanarchy) (#232). * Fix missing -static-libgcc when building shared libraries for Windows with make. * Fix link error when building shared libraries for Windows with make. * Fix error when loading libmbedtls.so. * Fix bug in mbedtls_ssl_conf_default() that caused the default preset to be always used (found by dcb314) (#235) * Fix bug in mbedtls_rsa_public() and mbedtls_rsa_private() that could result trying to unlock an unlocked mutex on invalid input (found by Fredrik Axelsson) (#257) * Fix -Wshadow warnings (found by hnrkp) (#240) * Fix memory corruption on client with overlong PSK identity, around SSL_MAX_CONTENT_LEN or higher - not triggerrable remotely (found by Aleksandrs Saveljevs) (#238) * Fix unused function warning when using MBEDTLS_MDx_ALT or MBEDTLS_SHAxxx_ALT (found by Henrik) (#239) * Fix memory corruption in pkey programs (found by yankuncheng) (#210) Changes * The PEM parser now accepts a trailing space at end of lines (#226). * It is now possible to #include a user-provided configuration file at the end of the default config.h by defining MBEDTLS_USER_CONFIG_FILE on the compiler's command line. * When verifying a certificate chain, if an intermediate certificate is trusted, no later cert is checked. (suggested by hannes-landeholm) (#220). * Prepend a "thread identifier" to debug messages (issue pointed out by Hugo Leisink) (#210). * Add mbedtls_ssl_get_max_frag_len() to query the current maximum fragment length. = mbed TLS 2.0.0 released 2015-07-13 Features * Support for DTLS 1.0 and 1.2 (RFC 6347). * Ability to override core functions from MDx, SHAx, AES and DES modules with custom implementation (eg hardware accelerated), complementing the ability to override the whole module. * New server-side implementation of session tickets that rotate keys to preserve forward secrecy, and allows sharing across multiple contexts. * Added a concept of X.509 cerificate verification profile that controls which algorithms and key sizes (curves for ECDSA) are acceptable. * Expanded configurability of security parameters in the SSL module with mbedtls_ssl_conf_dhm_min_bitlen() and mbedtls_ssl_conf_sig_hashes(). * Introduced a concept of presets for SSL security-relevant configuration parameters. API Changes * The library has been split into libmbedcrypto, libmbedx509, libmbedtls. You now need to link to all of them if you use TLS for example. * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace. Some names have been further changed to make them more consistent. Migration helpers scripts/rename.pl and include/mbedtls/compat-1.3.h are provided. Full list of renamings in scripts/data_files/rename-1.3-2.0.txt * Renamings of fields inside structures, not covered by the previous list: mbedtls_cipher_info_t.key_length -> key_bitlen mbedtls_cipher_context_t.key_length -> key_bitlen mbedtls_ecp_curve_info.size -> bit_size * Headers are now found in the 'mbedtls' directory (previously 'polarssl'). * The following _init() functions that could return errors have been split into an _init() that returns void and another function that should generally be the first function called on this context after init: mbedtls_ssl_init() -> mbedtls_ssl_setup() mbedtls_ccm_init() -> mbedtls_ccm_setkey() mbedtls_gcm_init() -> mbedtls_gcm_setkey() mbedtls_hmac_drbg_init() -> mbedtls_hmac_drbg_seed(_buf)() mbedtls_ctr_drbg_init() -> mbedtls_ctr_drbg_seed() Note that for mbedtls_ssl_setup(), you need to be done setting up the ssl_config structure before calling it. * Most ssl_set_xxx() functions (all except ssl_set_bio(), ssl_set_hostname(), ssl_set_session() and ssl_set_client_transport_id(), plus ssl_legacy_renegotiation()) have been renamed to mbedtls_ssl_conf_xxx() (see rename.pl and compat-1.3.h above) and their first argument's type changed from ssl_context to ssl_config. * ssl_set_bio() changed signature (contexts merged, order switched, one additional callback for read-with-timeout). * The following functions have been introduced and must be used in callback implementations (SNI, PSK) instead of their *conf counterparts: mbedtls_ssl_set_hs_own_cert() mbedtls_ssl_set_hs_ca_chain() mbedtls_ssl_set_hs_psk() * mbedtls_ssl_conf_ca_chain() lost its last argument (peer_cn), now set using mbedtls_ssl_set_hostname(). * mbedtls_ssl_conf_session_cache() changed prototype (only one context pointer, parameters reordered). * On server, mbedtls_ssl_conf_session_tickets_cb() must now be used in place of mbedtls_ssl_conf_session_tickets() to enable session tickets. * The SSL debug callback gained two new arguments (file name, line number). * Debug modes were removed. * mbedtls_ssl_conf_truncated_hmac() now returns void. * mbedtls_memory_buffer_alloc_init() now returns void. * X.509 verification flags are now an uint32_t. Affect the signature of: mbedtls_ssl_get_verify_result() mbedtls_x509_ctr_verify_info() mbedtls_x509_crt_verify() (flags, f_vrfy -> needs to be updated) mbedtls_ssl_conf_verify() (f_vrfy -> needs to be updated) * The following functions changed prototype to avoid an in-out length parameter: mbedtls_base64_encode() mbedtls_base64_decode() mbedtls_mpi_write_string() mbedtls_dhm_calc_secret() * In the NET module, all "int" and "int *" arguments for file descriptors changed type to "mbedtls_net_context *". * net_accept() gained new arguments for the size of the client_ip buffer. * In the threading layer, mbedtls_mutex_init() and mbedtls_mutex_free() now return void. * ecdsa_write_signature() gained an additional md_alg argument and ecdsa_write_signature_det() was deprecated. * pk_sign() no longer accepts md_alg == POLARSSL_MD_NONE with ECDSA. * Last argument of x509_crt_check_key_usage() and mbedtls_x509write_crt_set_key_usage() changed from int to unsigned. * test_ca_list (from certs.h) is renamed to test_cas_pem and is only available if POLARSSL_PEM_PARSE_C is defined (it never worked without). * Test certificates in certs.c are no longer guaranteed to be nul-terminated strings; use the new *_len variables instead of strlen(). * Functions mbedtls_x509_xxx_parse(), mbedtls_pk_parse_key(), mbedtls_pk_parse_public_key() and mbedtls_dhm_parse_dhm() now expect the length parameter to include the terminating null byte for PEM input. * Signature of mpi_mul_mpi() changed to make the last argument unsigned * calloc() is now used instead of malloc() everywhere. API of platform layer and the memory_buffer_alloc module changed accordingly. (Thanks to Mansour Moufid for helping with the replacement.) * Change SSL_DISABLE_RENEGOTIATION config.h flag to SSL_RENEGOTIATION (support for renegotiation now needs explicit enabling in config.h). * Split MBEDTLS_HAVE_TIME into MBEDTLS_HAVE_TIME and MBEDTLS_HAVE_TIME_DATE in config.h * net_connect() and net_bind() have a new 'proto' argument to choose between TCP and UDP, using the macros NET_PROTO_TCP or NET_PROTO_UDP. Their 'port' argument type is changed to a string. * Some constness fixes Removals * Removed mbedtls_ecp_group_read_string(). Only named groups are supported. * Removed mbedtls_ecp_sub() and mbedtls_ecp_add(), use mbedtls_ecp_muladd(). * Removed individual mdX_hmac, shaX_hmac, mdX_file and shaX_file functions (use generic functions from md.h) * Removed mbedtls_timing_msleep(). Use mbedtls_net_usleep() or a custom waiting function. * Removed test DHM parameters from the test certs module. * Removed the PBKDF2 module (use PKCS5). * Removed POLARSSL_ERROR_STRERROR_BC (use mbedtls_strerror()). * Removed compat-1.2.h (helper for migrating from 1.2 to 1.3). * Removed openssl.h (very partial OpenSSL compatibility layer). * Configuration options POLARSSL_HAVE_LONGLONG was removed (now always on). * Configuration options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 have been removed (compiler is required to support 32-bit operations). * Configuration option POLARSSL_HAVE_IPV6 was removed (always enabled). * Removed test program o_p_test, the script compat.sh does more. * Removed test program ssl_test, superseded by ssl-opt.sh. * Removed helper script active-config.pl New deprecations * md_init_ctx() is deprecated in favour of md_setup(), that adds a third argument (allowing memory savings if HMAC is not used) Semi-API changes (technically public, morally private) * Renamed a few headers to include _internal in the name. Those headers are not supposed to be included by users. * Changed md_info_t into an opaque structure (use md_get_xxx() accessors). * Changed pk_info_t into an opaque structure. * Changed cipher_base_t into an opaque structure. * Removed sig_oid2 and rename sig_oid1 to sig_oid in x509_crt and x509_crl. * x509_crt.key_usage changed from unsigned char to unsigned int. * Removed r and s from ecdsa_context * Removed mode from des_context and des3_context Default behavior changes * The default minimum TLS version is now TLS 1.0. * RC4 is now blacklisted by default in the SSL/TLS layer, and excluded from the default ciphersuite list returned by ssl_list_ciphersuites() * Support for receiving SSLv2 ClientHello is now disabled by default at compile time. * The default authmode for SSL/TLS clients is now REQUIRED. * Support for RSA_ALT contexts in the PK layer is now optional. Since is is enabled in the default configuration, this is only noticeable if using a custom config.h * Default DHM parameters server-side upgraded from 1024 to 2048 bits. * A minimum RSA key size of 2048 bits is now enforced during ceritificate chain verification. * Negotiation of truncated HMAC is now disabled by default on server too. * The following functions are now case-sensitive: mbedtls_cipher_info_from_string() mbedtls_ecp_curve_info_from_name() mbedtls_md_info_from_string() mbedtls_ssl_ciphersuite_from_string() mbedtls_version_check_feature() Requirement changes * The minimum MSVC version required is now 2010 (better C99 support). * The NET layer now unconditionnaly relies on getaddrinfo() and select(). * Compiler is required to support C99 types such as long long and uint32_t. API changes from the 1.4 preview branch * ssl_set_bio_timeout() was removed, split into mbedtls_ssl_set_bio() with new prototype, and mbedtls_ssl_set_read_timeout(). * The following functions now return void: mbedtls_ssl_conf_transport() mbedtls_ssl_conf_max_version() mbedtls_ssl_conf_min_version() * DTLS no longer hard-depends on TIMING_C, but uses a callback interface instead, see mbedtls_ssl_set_timer_cb(), with the Timing module providing an example implementation, see mbedtls_timing_delay_context and mbedtls_timing_set/get_delay(). * With UDP sockets, it is no longer necessary to call net_bind() again after a successful net_accept(). Changes * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now thread-safe if MBEDTLS_THREADING_C is enabled. * Reduced ROM fooprint of SHA-256 and added an option to reduce it even more (at the expense of performance) MBEDTLS_SHA256_SMALLER. = mbed TLS 1.3 branch Security * With authmode set to SSL_VERIFY_OPTIONAL, verification of keyUsage and extendedKeyUsage on the leaf certificate was lost (results not accessible via ssl_get_verify_results()). * Add countermeasure against "Lucky 13 strikes back" cache-based attack, https://dl.acm.org/citation.cfm?id=2714625 Features * Improve ECC performance by using more efficient doubling formulas (contributed by Peter Dettman). * Add x509_crt_verify_info() to display certificate verification results. * Add support for reading DH parameters with privateValueLength included (contributed by Daniel Kahn Gillmor). * Add support for bit strings in X.509 names (request by Fredrik Axelsson). * Add support for id-at-uniqueIdentifier in X.509 names. * Add support for overriding snprintf() (except on Windows) and exit() in the platform layer. * Add an option to use macros instead of function pointers in the platform layer (helps get rid of unwanted references). * Improved Makefiles for Windows targets by fixing library targets and making cross-compilation easier (thanks to Alon Bar-Lev). * The benchmark program also prints heap usage for public-key primitives if POLARSSL_MEMORY_BUFFER_ALLOC_C and POLARSSL_MEMORY_DEBUG are defined. * New script ecc-heap.sh helps measuring the impact of ECC parameters on speed and RAM (heap only for now) usage. * New script memory.sh helps measuring the ROM and RAM requirements of two reduced configurations (PSK-CCM and NSA suite B). * Add config flag POLARSSL_DEPRECATED_WARNING (off by default) to produce warnings on use of deprecated functions (with GCC and Clang only). * Add config flag POLARSSL_DEPRECATED_REMOVED (off by default) to produce errors on use of deprecated functions. Bugfix * Fix compile errors with PLATFORM_NO_STD_FUNCTIONS. * Fix compile error with PLATFORM_EXIT_ALT (thanks to Rafał Przywara). * Fix bug in entropy.c when THREADING_C is also enabled that caused entropy_free() to crash (thanks to Rafał Przywara). * Fix memory leak when gcm_setkey() and ccm_setkey() are used more than once on the same context. * Fix bug in ssl_mail_client when password is longer that username (found by Bruno Pape). * Fix undefined behaviour (memcmp( NULL, NULL, 0 );) in X.509 modules (detected by Clang's 3.6 UBSan). * mpi_size() and mpi_msb() would segfault when called on an mpi that is initialized but not set (found by pravic). * Fix detection of support for getrandom() on Linux (reported by syzzer) by doing it at runtime (using uname) rather that compile time. * Fix handling of symlinks by "make install" (found by Gaël PORTAY). * Fix potential NULL pointer dereference (not trigerrable remotely) when ssl_write() is called before the handshake is finished (introduced in 1.3.10) (first reported by Martin Blumenstingl). * Fix bug in pk_parse_key() that caused some valid private EC keys to be rejected. * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). * Fix thread safety bug in RSA operations (found by Fredrik Axelsson). * Fix hardclock() (only used in the benchmarking program) with some versions of mingw64 (found by kxjhlele). * Fix warnings from mingw64 in timing.c (found by kxjklele). * Fix potential unintended sign extension in asn1_get_len() on 64-bit platforms. * Fix potential memory leak in ssl_set_psk() (found by Mansour Moufid). * Fix compile error when POLARSSL_SSL_DISABLE_RENEGOTATION and POLARSSL_SSL_SSESSION_TICKETS where both enabled in config.h (introduced in 1.3.10). * Add missing extern "C" guard in aesni.h (reported by amir zamani). * Add missing dependency on SHA-256 in some x509 programs (reported by Gergely Budai). * Fix bug related to ssl_set_curves(): the client didn't check that the curve picked by the server was actually allowed. Changes * Remove bias in mpi_gen_prime (contributed by Pascal Junod). * Remove potential sources of timing variations (some contributed by Pascal Junod). * Options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 are deprecated. * Enabling POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated. * compat-1.2.h and openssl.h are deprecated. * Adjusting/overriding CFLAGS and LDFLAGS with the make build system is now more flexible (warning: OFLAGS is not used any more) (see the README) (contributed by Alon Bar-Lev). * ssl_set_own_cert() no longer calls pk_check_pair() since the performance impact was bad for some users (this was introduced in 1.3.10). * Move from SHA-1 to SHA-256 in example programs using signatures (suggested by Thorsten Mühlfelder). * Remove some unneeded inclusions of header files from the standard library "minimize" others (eg use stddef.h if only size_t is needed). * Change #include lines in test files to use double quotes instead of angle brackets for uniformity with the rest of the code. * Remove dependency on sscanf() in X.509 parsing modules. = mbed TLS 1.3.10 released 2015-02-09 Security * NULL pointer dereference in the buffer-based allocator when the buffer is full and polarssl_free() is called (found by Mark Hasemeyer) (only possible if POLARSSL_MEMORY_BUFFER_ALLOC_C is enabled, which it is not by default). * Fix remotely-triggerable uninitialised pointer dereference caused by crafted X.509 certificate (TLS server is not affected if it doesn't ask for a client certificate) (found using Codenomicon Defensics). * Fix remotely-triggerable memory leak caused by crafted X.509 certificates (TLS server is not affected if it doesn't ask for a client certificate) (found using Codenomicon Defensics). * Fix potential stack overflow while parsing crafted X.509 certificates (TLS server is not affected if it doesn't ask for a client certificate) (found using Codenomicon Defensics). * Fix timing difference that could theoretically lead to a Bleichenbacher-style attack in the RSA and RSA-PSK key exchanges (reported by Sebastian Schinzel). Features * Add support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv). * Add support for Extended Master Secret (draft-ietf-tls-session-hash). * Add support for Encrypt-then-MAC (RFC 7366). * Add function pk_check_pair() to test if public and private keys match. * Add x509_crl_parse_der(). * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the length of an X.509 verification chain. * Support for renegotiation can now be disabled at compile-time * Support for 1/n-1 record splitting, a countermeasure against BEAST. * Certificate selection based on signature hash, preferring SHA-1 over SHA-2 for pre-1.2 clients when multiple certificates are available. * Add support for getrandom() syscall on recent Linux kernels with Glibc or a compatible enough libc (eg uClibc). * Add ssl_set_arc4_support() to make it easier to disable RC4 at runtime while using the default ciphersuite list. * Added new error codes and debug messages about selection of ciphersuite/certificate. Bugfix * Stack buffer overflow if ctr_drbg_update() is called with too large add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). * Possible buffer overflow of length at most POLARSSL_MEMORY_ALIGN_MULTIPLE if memory_buffer_alloc_init() was called with buf not aligned and len not a multiple of POLARSSL_MEMORY_ALIGN_MULTIPLE (not triggerable remotely). * User set CFLAGS were ignored by Cmake with gcc (introduced in 1.3.9, found by Julian Ospald). * Fix potential undefined behaviour in Camellia. * Fix potential failure in ECDSA signatures when POLARSSL_ECP_MAX_BITS is a multiple of 8 (found by Gergely Budai). * Fix unchecked return code in x509_crt_parse_path() on Windows (found by Peter Vaskovic). * Fix assembly selection for MIPS64 (thanks to James Cowgill). * ssl_get_verify_result() now works even if the handshake was aborted due to a failed verification (found by Fredrik Axelsson). * Skip writing and parsing signature_algorithm extension if none of the key exchanges enabled needs certificates. This fixes a possible interop issue with some servers when a zero-length extension was sent. (Reported by Peter Dettman.) * On a 0-length input, base64_encode() did not correctly set output length (found by Hendrik van den Boogaard). Changes * Use deterministic nonces for AEAD ciphers in TLS by default (possible to switch back to random with POLARSSL_SSL_AEAD_RANDOM_IV in config.h). * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. * ssl_set_own_cert() now returns an error on key-certificate mismatch. * Forbid repeated extensions in X.509 certificates. * debug_print_buf() now prints a text view in addition to hexadecimal. * A specific error is now returned when there are ciphersuites in common but none of them is usable due to external factors such as no certificate with a suitable (extended)KeyUsage or curve or no PSK set. * It is now possible to disable negotiation of truncated HMAC server-side at runtime with ssl_set_truncated_hmac(). * Example programs for SSL client and server now disable SSLv3 by default. * Example programs for SSL client and server now disable RC4 by default. * Use platform.h in all test suites and programs. = PolarSSL 1.3.9 released 2014-10-20 Security * Lowest common hash was selected from signature_algorithms extension in TLS 1.2 (found by Darren Bane) (introduced in 1.3.8). * Remotely-triggerable memory leak when parsing some X.509 certificates (server is not affected if it doesn't ask for a client certificate) (found using Codenomicon Defensics). * Remotely-triggerable memory leak when parsing crafted ClientHello (not affected if ECC support was compiled out) (found using Codenomicon Defensics). Bugfix * Support escaping of commas in x509_string_to_names() * Fix compile error in ssl_pthread_server (found by Julian Ospald). * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). * Fix compile error in timing.c when POLARSSL_NET_C and POLARSSL_SELFTEST are defined but not POLARSSL_HAVE_TIME (found by Stephane Di Vito). * Remove non-existent file from VS projects (found by Peter Vaskovic). * ssl_read() could return non-application data records on server while renegotation was pending, and on client when a HelloRequest was received. * Server-initiated renegotiation would fail with non-blocking I/O if the write callback returned WANT_WRITE when requesting renegotiation. * ssl_close_notify() could send more than one message in some circumstances with non-blocking I/O. * Fix compiler warnings on iOS (found by Sander Niemeijer). * x509_crt_parse() did not increase total_failed on PEM error * Fix compile error with armcc in mpi_is_prime() * Fix potential bad read in parsing ServerHello (found by Adrien Vialletelle). Changes * Ciphersuites using SHA-256 or SHA-384 now require TLS 1.x (there is no standard defining how to use SHA-2 with SSL 3.0). * Ciphersuites using RSA-PSK key exchange new require TLS 1.x (the spec is ambiguous on how to encode some packets with SSL 3.0). * Made buffer size in pk_write_(pub)key_pem() more dynamic, eg smaller if RSA is disabled, larger if POLARSSL_MPI_MAX_SIZE is larger. * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. * POLARSSL_MPI_MAX_SIZE now defaults to 1024 in order to allow 8192 bits RSA keys. * Accept spaces at end of line or end of buffer in base64_decode(). * X.509 certificates with more than one AttributeTypeAndValue per RelativeDistinguishedName are not accepted any more. = PolarSSL 1.3.8 released 2014-07-11 Security * Fix length checking for AEAD ciphersuites (found by Codenomicon). It was possible to crash the server (and client) using crafted messages when a GCM suite was chosen. Features * Add CCM module and cipher mode to Cipher Layer * Support for CCM and CCM_8 ciphersuites * Support for parsing and verifying RSASSA-PSS signatures in the X.509 modules (certificates, CRLs and CSRs). * Blowfish in the cipher layer now supports variable length keys. * Add example config.h for PSK with CCM, optimized for low RAM usage. * Optimize for RAM usage in example config.h for NSA Suite B profile. * Add POLARSSL_REMOVE_ARC4_CIPHERSUITES to allow removing RC4 ciphersuites from the default list (inactive by default). * Add server-side enforcement of sent renegotiation requests (ssl_set_renegotiation_enforced()) * Add SSL_CIPHERSUITES config.h flag to allow specifying a list of ciphersuites to use and save some memory if the list is small. Changes * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is required on some platforms (e.g. OpenBSD) * Migrate zeroizing of data to polarssl_zeroize() instead of memset() against unwanted compiler optimizations * md_list() now returns hashes strongest first * Selection of hash for signing ServerKeyExchange in TLS 1.2 now picks strongest offered by client. * All public contexts have _init() and _free() functions now for simpler usage pattern Bugfix * Fix in debug_print_msg() * Enforce alignment in the buffer allocator even if buffer is not aligned * Remove less-than-zero checks on unsigned numbers * Stricter check on SSL ClientHello internal sizes compared to actual packet size (found by TrustInSoft) * Fix WSAStartup() return value check (found by Peter Vaskovic) * Other minor issues (found by Peter Vaskovic) * Fix symlink command for cross compiling with CMake (found by Andre Heinecke) * Fix DER output of gen_key app (found by Gergely Budai) * Very small records were incorrectly rejected when truncated HMAC was in use with some ciphersuites and versions (RC4 in all versions, CBC with versions < TLS 1.1). * Very large records using more than 224 bytes of padding were incorrectly rejected with CBC-based ciphersuites and TLS >= 1.1 * Very large records using less padding could cause a buffer overread of up to 32 bytes with CBC-based ciphersuites and TLS >= 1.1 * Restore ability to use a v1 cert as a CA if trusted locally. (This had been removed in 1.3.6.) * Restore ability to locally trust a self-signed cert that is not a proper CA for use as an end entity certificate. (This had been removed in 1.3.6.) * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). * Use \n\t rather than semicolons for bn_mul asm, since some assemblers interpret semicolons as comment delimiters (found by Barry K. Nathan). * Fix off-by-one error in parsing Supported Point Format extension that caused some handshakes to fail. * Fix possible miscomputation of the premaster secret with DHE-PSK key exchange that caused some handshakes to fail with other implementations. (Failure rate <= 1/255 with common DHM moduli.) * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). * Fix base64_decode() to return and check length correctly (in case of tight buffers) * Fix mpi_write_string() to write "00" as hex output for empty MPI (found by Hui Dong) = PolarSSL 1.3.7 released on 2014-05-02 Features * debug_set_log_mode() added to determine raw or full logging * debug_set_threshold() added to ignore messages over threshold level * version_check_feature() added to check for compile-time options at run-time Changes * POLARSSL_CONFIG_OPTIONS has been removed. All values are individually checked and filled in the relevant module headers * Debug module only outputs full lines instead of parts * Better support for the different Attribute Types from IETF PKIX (RFC 5280) * AES-NI now compiles with "old" assemblers too * Ciphersuites based on RC4 now have the lowest priority by default Bugfix * Only iterate over actual certificates in ssl_write_certificate_request() (found by Matthew Page) * Typos in platform.c and pkcs11.c (found by Daniel Phillips and Steffan Karger) * cert_write app should use subject of issuer certificate as issuer of cert * Fix false reject in padding check in ssl_decrypt_buf() for CBC ciphersuites, for full SSL frames of data. * Improve interoperability by not writing extension length in ClientHello / ServerHello when no extensions are present (found by Matthew Page) * rsa_check_pubkey() now allows an E up to N * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings * mpi_fill_random() was creating numbers larger than requested on big-endian platform when size was not an integer number of limbs * Fix dependencies issues in X.509 test suite. * Some parts of ssl_tls.c were compiled even when the module was disabled. * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) * Fix detection of Clang on some Apple platforms with CMake (found by Barry K. Nathan) = PolarSSL 1.3.6 released on 2014-04-11 Features * Support for the ALPN SSL extension * Add option 'use_dev_random' to gen_key application * Enable verification of the keyUsage extension for CA and leaf certificates (POLARSSL_X509_CHECK_KEY_USAGE) * Enable verification of the extendedKeyUsage extension (POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) Changes * x509_crt_info() now prints information about parsed extensions as well * pk_verify() now returns a specific error code when the signature is valid but shorter than the supplied length. * Use UTC time to check certificate validity. * Reject certificates with times not in UTC, per RFC 5280. Security * Avoid potential timing leak in ecdsa_sign() by blinding modular division. (Found by Watson Ladd.) * The notAfter date of some certificates was no longer checked since 1.3.5. This affects certificates in the user-supplied chain except the top certificate. If the user-supplied chain contains only one certificates, it is not affected (ie, its notAfter date is properly checked). * Prevent potential NULL pointer dereference in ssl_read_record() (found by TrustInSoft) Bugfix * The length of various ClientKeyExchange messages was not properly checked. * Some example server programs were not sending the close_notify alert. * Potential memory leak in mpi_exp_mod() when error occurs during calculation of RR. * Fixed malloc/free default #define in platform.c (found by Gergely Budai). * Fixed type which made POLARSSL_ENTROPY_FORCE_SHA256 uneffective (found by Gergely Budai). * Fix #include path in ecdsa.h which wasn't accepted by some compilers. (found by Gergely Budai) * Fix compile errors when POLARSSL_ERROR_STRERROR_BC is undefined (found by Shuo Chen). * oid_get_numeric_string() used to truncate the output without returning an error if the output buffer was just 1 byte too small. * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len. * Calling pk_debug() on an RSA-alt key would segfault. * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys. * Potential buffer overwrite in pem_write_buffer() because of low length indication (found by Thijs Alkemade) * EC curves constants, which should be only in ROM since 1.3.3, were also stored in RAM due to missing 'const's (found by Gergely Budai). = PolarSSL 1.3.5 released on 2014-03-26 Features * HMAC-DRBG as a separate module * Option to set the Curve preference order (disabled by default) * Single Platform compatilibity layer (for memory / printf / fprintf) * Ability to provide alternate timing implementation * Ability to force the entropy module to use SHA-256 as its basis (POLARSSL_ENTROPY_FORCE_SHA256) * Testing script ssl-opt.sh added for testing 'live' ssl option interoperability against OpenSSL and PolarSSL * Support for reading EC keys that use SpecifiedECDomain in some cases. * Entropy module now supports seed writing and reading Changes * Deprecated the Memory layer * entropy_add_source(), entropy_update_manual() and entropy_gather() now thread-safe if POLARSSL_THREADING_C defined * Improvements to the CMake build system, contributed by Julian Ospald. * Work around a bug of the version of Clang shipped by Apple with Mavericks that prevented bignum.c from compiling. (Reported by Rafael Baptista.) * Revamped the compat.sh interoperatibility script to include support for testing against GnuTLS * Deprecated ssl_set_own_cert_rsa() and ssl_set_own_cert_rsa_alt() * Improvements to tests/Makefile, contributed by Oden Eriksson. Security * Forbid change of server certificate during renegotiation to prevent "triple handshake" attack when authentication mode is 'optional' (the attack was already impossible when authentication is required). * Check notBefore timestamp of certificates and CRLs from the future. * Forbid sequence number wrapping * Fixed possible buffer overflow with overlong PSK * Possible remotely-triggered out-of-bounds memory access fixed (found by TrustInSoft) Bugfix * ecp_gen_keypair() does more tries to prevent failure because of statistics * Fixed bug in RSA PKCS#1 v1.5 "reversed" operations * Fixed testing with out-of-source builds using cmake * Fixed version-major intolerance in server * Fixed CMake symlinking on out-of-source builds * Fixed dependency issues in test suite * Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0 * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by Alex Wilson.) * ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled. * m_sleep() was sleeping twice too long on most Unix platforms. * Fixed bug with session tickets and non-blocking I/O in the unlikely case send() would return an EAGAIN error when sending the ticket. * ssl_cache was leaking memory when reusing a timed out entry containing a client certificate. * ssl_srv was leaking memory when client presented a timed out ticket containing a client certificate * ssl_init() was leaving a dirty pointer in ssl_context if malloc of out_ctr failed * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc of one of them failed * Fix typo in rsa_copy() that impacted PKCS#1 v2 contexts * x509_get_current_time() uses localtime_r() to prevent thread issues = PolarSSL 1.3.4 released on 2014-01-27 Features * Support for the Koblitz curves: secp192k1, secp224k1, secp256k1 * Support for RIPEMD-160 * Support for AES CFB8 mode * Support for deterministic ECDSA (RFC 6979) Bugfix * Potential memory leak in bignum_selftest() * Replaced expired test certificate * ssl_mail_client now terminates lines with CRLF, instead of LF * net module handles timeouts on blocking sockets better (found by Tilman Sauerbeck) * Assembly format fixes in bn_mul.h Security * Missing MPI_CHK calls added around unguarded mpi calls (found by TrustInSoft) = PolarSSL 1.3.3 released on 2013-12-31 Features * EC key generation support in gen_key app * Support for adhering to client ciphersuite order preference (POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) * Support for Curve25519 * Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites * Support for IPv6 in the NET module * AES-NI support for AES, AES-GCM and AES key scheduling * SSL Pthread-based server example added (ssl_pthread_server) Changes * gen_prime() speedup * Speedup of ECP multiplication operation * Relaxed some SHA2 ciphersuite's version requirements * Dropped use of readdir_r() instead of readdir() with threading support * More constant-time checks in the RSA module * Split off curves from ecp.c into ecp_curves.c * Curves are now stored fully in ROM * Memory usage optimizations in ECP module * Removed POLARSSL_THREADING_DUMMY Bugfix * Fixed bug in mpi_set_bit() on platforms where t_uint is wider than int * Fixed X.509 hostname comparison (with non-regular characters) * SSL now gracefully handles missing RNG * Missing defines / cases for RSA_PSK key exchange * crypt_and_hash app checks MAC before final decryption * Potential memory leak in ssl_ticket_keys_init() * Memory leak in benchmark application * Fixed x509_crt_parse_path() bug on Windows platforms * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by TrustInSoft) * Fixed potential overflow in certificate size verification in ssl_write_certificate() (found by TrustInSoft) Security * Possible remotely-triggered out-of-bounds memory access fixed (found by TrustInSoft) = PolarSSL 1.3.2 released on 2013-11-04 Features * PK tests added to test framework * Added optional optimization for NIST MODP curves (POLARSSL_ECP_NIST_OPTIM) * Support for Camellia-GCM mode and ciphersuites Changes * Padding checks in cipher layer are now constant-time * Value comparisons in SSL layer are now constant-time * Support for serialNumber, postalAddress and postalCode in X509 names * SSL Renegotiation was refactored Bugfix * More stringent checks in cipher layer * Server does not send out extensions not advertised by client * Prevent possible alignment warnings on casting from char * to 'aligned *' * Misc fixes and additions to dependency checks * Const correctness * cert_write with selfsign should use issuer_name as subject_name * Fix ECDSA corner case: missing reduction mod N (found by DualTachyon) * Defines to handle UEFI environment under MSVC * Server-side initiated renegotiations send HelloRequest = PolarSSL 1.3.1 released on 2013-10-15 Features * Support for Brainpool curves and TLS ciphersuites (RFC 7027) * Support for ECDHE-PSK key-exchange and ciphersuites * Support for RSA-PSK key-exchange and ciphersuites Changes * RSA blinding locks for a smaller amount of time * TLS compression only allocates working buffer once * Introduced POLARSSL_HAVE_READDIR_R for systems without it * config.h is more script-friendly Bugfix * Missing MSVC defines added * Compile errors with POLARSSL_RSA_NO_CRT * Header files with 'polarssl/' * Const correctness * Possible naming collision in dhm_context * Better support for MSVC * threading_set_alt() name * Added missing x509write_crt_set_version() = PolarSSL 1.3.0 released on 2013-10-01 Features * Elliptic Curve Cryptography module added * Elliptic Curve Diffie Hellman module added * Ephemeral Elliptic Curve Diffie Hellman support for SSL/TLS (ECDHE-based ciphersuites) * Ephemeral Elliptic Curve Digital Signature Algorithm support for SSL/TLS (ECDSA-based ciphersuites) * Ability to specify allowed ciphersuites based on the protocol version. * PSK and DHE-PSK based ciphersuites added * Memory allocation abstraction layer added * Buffer-based memory allocator added (no malloc() / free() / HEAP usage) * Threading abstraction layer added (dummy / pthread / alternate) * Public Key abstraction layer added * Parsing Elliptic Curve keys * Parsing Elliptic Curve certificates * Support for max_fragment_length extension (RFC 6066) * Support for truncated_hmac extension (RFC 6066) * Support for zeros-and-length (ANSI X.923) padding, one-and-zeros (ISO/IEC 7816-4) padding and zero padding in the cipher layer * Support for session tickets (RFC 5077) * Certificate Request (CSR) generation with extensions (key_usage, ns_cert_type) * X509 Certificate writing with extensions (basic_constraints, issuer_key_identifier, etc) * Optional blinding for RSA, DHM and EC * Support for multiple active certificate / key pairs in SSL servers for the same host (Not to be confused with SNI!) Changes * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2 individually * Introduced separate SSL Ciphersuites module that is based on Cipher and MD information * Internals for SSL module adapted to have separate IV pointer that is dynamically set (Better support for hardware acceleration) * Moved all OID functionality to a separate module. RSA function prototypes for the RSA sign and verify functions changed as a result * Split up the GCM module into a starts/update/finish cycle * Client and server now filter sent and accepted ciphersuites on minimum and maximum protocol version * Ability to disable server_name extension (RFC 6066) * Renamed error_strerror() to the less conflicting polarssl_strerror() (Ability to keep old as well with POLARSSL_ERROR_STRERROR_BC) * SHA2 renamed to SHA256, SHA4 renamed to SHA512 and functions accordingly * All RSA operations require a random generator for blinding purposes * X509 core refactored * x509_crt_verify() now case insensitive for cn (RFC 6125 6.4) * Also compiles / runs without time-based functions (!POLARSSL_HAVE_TIME) * Support faulty X509 v1 certificates with extensions (POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) Bugfix * Fixed parse error in ssl_parse_certificate_request() * zlib compression/decompression skipped on empty blocks * Support for AIX header locations in net.c module * Fixed file descriptor leaks Security * RSA blinding on CRT operations to counter timing attacks (found by Cyril Arnaud and Pierre-Alain Fouque) = Version 1.2.14 released 2015-05-?? Security * Fix potential invalid memory read in the server, that allows a client to crash it remotely (found by Caj Larsson). * Fix potential invalid memory read in certificate parsing, that allows a client to crash the server remotely if client authentication is enabled (found using Codenomicon Defensics). * Add countermeasure against "Lucky 13 strikes back" cache-based attack, https://dl.acm.org/citation.cfm?id=2714625 Bugfix * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). * Fix hardclock() (only used in the benchmarking program) with some versions of mingw64 (found by kxjhlele). * Fix warnings from mingw64 in timing.c (found by kxjklele). * Fix potential unintended sign extension in asn1_get_len() on 64-bit platforms (found with Coverity Scan). = Version 1.2.13 released 2015-02-16 Note: Although PolarSSL has been renamed to mbed TLS, no changes reflecting this will be made in the 1.2 branch at this point. Security * Fix remotely-triggerable uninitialised pointer dereference caused by crafted X.509 certificate (TLS server is not affected if it doesn't ask for a client certificate) (found using Codenomicon Defensics). * Fix remotely-triggerable memory leak caused by crafted X.509 certificates (TLS server is not affected if it doesn't ask for a client certificate) (found using Codenomicon Defensics). * Fix potential stack overflow while parsing crafted X.509 certificates (TLS server is not affected if it doesn't ask for a client certificate) found using Codenomicon Defensics). * Fix buffer overread of size 1 when parsing crafted X.509 certificates (TLS server is not affected if it doesn't ask for a client certificate). Bugfix * Fix potential undefined behaviour in Camellia. * Fix memory leaks in PKCS#5 and PKCS#12. * Stack buffer overflow if ctr_drbg_update() is called with too large add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). * Fix bug in MPI/bignum on s390/s390x (reported by Dan Horák) (introduced in 1.2.12). * Fix unchecked return code in x509_crt_parse_path() on Windows (found by Peter Vaskovic). * Fix assembly selection for MIPS64 (thanks to James Cowgill). * ssl_get_verify_result() now works even if the handshake was aborted due to a failed verification (found by Fredrik Axelsson). * Skip writing and parsing signature_algorithm extension if none of the key exchanges enabled needs certificates. This fixes a possible interop issue with some servers when a zero-length extension was sent. (Reported by Peter Dettman.) * On a 0-length input, base64_encode() did not correctly set output length (found by Hendrik van den Boogaard). Changes * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. * Forbid repeated extensions in X.509 certificates. * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the length of an X.509 verification chain (default = 8). = Version 1.2.12 released 2014-10-24 Security * Remotely-triggerable memory leak when parsing some X.509 certificates (server is not affected if it doesn't ask for a client certificate). (Found using Codenomicon Defensics.) Bugfix * Fix potential bad read in parsing ServerHello (found by Adrien Vialletelle). * ssl_close_notify() could send more than one message in some circumstances with non-blocking I/O. * x509_crt_parse() did not increase total_failed on PEM error * Fix compiler warnings on iOS (found by Sander Niemeijer). * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). * ssl_read() could return non-application data records on server while renegotation was pending, and on client when a HelloRequest was received. * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). Changes * X.509 certificates with more than one AttributeTypeAndValue per RelativeDistinguishedName are not accepted any more. * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. * Accept spaces at end of line or end of buffer in base64_decode(). = Version 1.2.11 released 2014-07-11 Features * Entropy module now supports seed writing and reading Changes * Introduced POLARSSL_HAVE_READDIR_R for systems without it * Improvements to the CMake build system, contributed by Julian Ospald. * Work around a bug of the version of Clang shipped by Apple with Mavericks that prevented bignum.c from compiling. (Reported by Rafael Baptista.) * Improvements to tests/Makefile, contributed by Oden Eriksson. * Use UTC time to check certificate validity. * Reject certificates with times not in UTC, per RFC 5280. * Migrate zeroizing of data to polarssl_zeroize() instead of memset() against unwanted compiler optimizations Security * Forbid change of server certificate during renegotiation to prevent "triple handshake" attack when authentication mode is optional (the attack was already impossible when authentication is required). * Check notBefore timestamp of certificates and CRLs from the future. * Forbid sequence number wrapping * Prevent potential NULL pointer dereference in ssl_read_record() (found by TrustInSoft) * Fix length checking for AEAD ciphersuites (found by Codenomicon). It was possible to crash the server (and client) using crafted messages when a GCM suite was chosen. Bugfix * Fixed X.509 hostname comparison (with non-regular characters) * SSL now gracefully handles missing RNG * crypt_and_hash app checks MAC before final decryption * Fixed x509_crt_parse_path() bug on Windows platforms * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by TrustInSoft) * Fixed potential overflow in certificate size verification in ssl_write_certificate() (found by TrustInSoft) * Fix ASM format in bn_mul.h * Potential memory leak in bignum_selftest() * Replaced expired test certificate * ssl_mail_client now terminates lines with CRLF, instead of LF * Fix bug in RSA PKCS#1 v1.5 "reversed" operations * Fixed testing with out-of-source builds using cmake * Fixed version-major intolerance in server * Fixed CMake symlinking on out-of-source builds * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by Alex Wilson.) * ssl_init() was leaving a dirty pointer in ssl_context if malloc of out_ctr failed * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc of one of them failed * x509_get_current_time() uses localtime_r() to prevent thread issues * Some example server programs were not sending the close_notify alert. * Potential memory leak in mpi_exp_mod() when error occurs during calculation of RR. * Improve interoperability by not writing extension length in ClientHello when no extensions are present (found by Matthew Page) * rsa_check_pubkey() now allows an E up to N * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings * mpi_fill_random() was creating numbers larger than requested on big-endian platform when size was not an integer number of limbs * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) * Stricter check on SSL ClientHello internal sizes compared to actual packet size (found by TrustInSoft) * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). * Use \n\t rather than semicolons for bn_mul asm, since some assemblers interpret semicolons as comment delimiters (found by Barry K. Nathan). * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). * Fix base64_decode() to return and check length correctly (in case of tight buffers) = Version 1.2.10 released 2013-10-07 Changes * Changed RSA blinding to a slower but thread-safe version Bugfix * Fixed memory leak in RSA as a result of introduction of blinding * Fixed ssl_pkcs11_decrypt() prototype * Fixed MSVC project files = Version 1.2.9 released 2013-10-01 Changes * x509_verify() now case insensitive for cn (RFC 6125 6.4) Bugfix * Fixed potential memory leak when failing to resume a session * Fixed potential file descriptor leaks (found by Remi Gacogne) * Minor fixes Security * Fixed potential heap buffer overflow on large hostname setting * Fixed potential negative value misinterpretation in load_file() * RSA blinding on CRT operations to counter timing attacks (found by Cyril Arnaud and Pierre-Alain Fouque) = Version 1.2.8 released 2013-06-19 Features * Parsing of PKCS#8 encrypted private key files * PKCS#12 PBE and derivation functions * Centralized module option values in config.h to allow user-defined settings without editing header files by using POLARSSL_CONFIG_OPTIONS Changes * HAVEGE random generator disabled by default * Internally split up x509parse_key() into a (PEM) handler function and specific DER parser functions for the PKCS#1 and unencrypted PKCS#8 private key formats * Added mechanism to provide alternative implementations for all symmetric cipher and hash algorithms (e.g. POLARSSL_AES_ALT in config.h) * PKCS#5 module added. Moved PBKDF2 functionality inside and deprecated old PBKDF2 module Bugfix * Secure renegotiation extension should only be sent in case client supports secure renegotiation * Fixed offset for cert_type list in ssl_parse_certificate_request() * Fixed const correctness issues that have no impact on the ABI * x509parse_crt() now better handles PEM error situations * ssl_parse_certificate() now calls x509parse_crt_der() directly instead of the x509parse_crt() wrapper that can also parse PEM certificates * x509parse_crtpath() is now reentrant and uses more portable stat() * Fixed bignum.c and bn_mul.h to support Thumb2 and LLVM compiler * Fixed values for 2-key Triple DES in cipher layer * ssl_write_certificate_request() can handle empty ca_chain Security * A possible DoS during the SSL Handshake, due to faulty parsing of PEM-encoded certificates has been fixed (found by Jack Lloyd) = Version 1.2.7 released 2013-04-13 Features * Ability to specify allowed ciphersuites based on the protocol version. Changes * Default Blowfish keysize is now 128-bits * Test suites made smaller to accommodate Raspberry Pi Bugfix * Fix for MPI assembly for ARM * GCM adapted to support sizes > 2^29 = Version 1.2.6 released 2013-03-11 Bugfix * Fixed memory leak in ssl_free() and ssl_reset() for active session * Corrected GCM counter incrementation to use only 32-bits instead of 128-bits (found by Yawning Angel) * Fixes for 64-bit compilation with MS Visual Studio * Fixed net_bind() for specified IP addresses on little endian systems * Fixed assembly code for ARM (Thumb and regular) for some compilers Changes * Internally split up rsa_pkcs1_encrypt(), rsa_pkcs1_decrypt(), rsa_pkcs1_sign() and rsa_pkcs1_verify() to separate PKCS#1 v1.5 and PKCS#1 v2.1 functions * Added support for custom labels when using rsa_rsaes_oaep_encrypt() or rsa_rsaes_oaep_decrypt() * Re-added handling for SSLv2 Client Hello when the define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is set * The SSL session cache module (ssl_cache) now also retains peer_cert information (not the entire chain) Security * Removed further timing differences during SSL message decryption in ssl_decrypt_buf() * Removed timing differences due to bad padding from rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 operations = Version 1.2.5 released 2013-02-02 Changes * Allow enabling of dummy error_strerror() to support some use-cases * Debug messages about padding errors during SSL message decryption are disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL * Sending of security-relevant alert messages that do not break interoperability can be switched on/off with the flag POLARSSL_SSL_ALL_ALERT_MESSAGES Security * Removed timing differences during SSL message decryption in ssl_decrypt_buf() due to badly formatted padding = Version 1.2.4 released 2013-01-25 Changes * More advanced SSL ciphersuite representation and moved to more dynamic SSL core * Added ssl_handshake_step() to allow single stepping the handshake process Bugfix * Memory leak when using RSA_PKCS_V21 operations fixed * Handle future version properly in ssl_write_certificate_request() * Correctly handle CertificateRequest message in client for <= TLS 1.1 without DN list = Version 1.2.3 released 2012-11-26 Bugfix * Server not always sending correct CertificateRequest message = Version 1.2.2 released 2012-11-24 Changes * Added p_hw_data to ssl_context for context specific hardware acceleration data * During verify trust-CA is only checked for expiration and CRL presence Bugfixes * Fixed client authentication compatibility * Fixed dependency on POLARSSL_SHA4_C in SSL modules = Version 1.2.1 released 2012-11-20 Changes * Depth that the certificate verify callback receives is now numbered bottom-up (Peer cert depth is 0) Bugfixes * Fixes for MSVC6 * Moved mpi_inv_mod() outside POLARSSL_GENPRIME * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel Pégourié-Gonnard) * Fixed possible segfault in mpi_shift_r() (found by Manuel Pégourié-Gonnard) * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 = Version 1.2.0 released 2012-10-31 Features * Added support for NULL cipher (POLARSSL_CIPHER_NULL_CIPHER) and weak ciphersuites (POLARSSL_ENABLE_WEAK_CIPHERSUITES). They are disabled by default! * Added support for wildcard certificates * Added support for multi-domain certificates through the X509 Subject Alternative Name extension * Added preliminary ASN.1 buffer writing support * Added preliminary X509 Certificate Request writing support * Added key_app_writer example application * Added cert_req example application * Added base Galois Counter Mode (GCM) for AES * Added TLS 1.2 support (RFC 5246) * Added GCM suites to TLS 1.2 (RFC 5288) * Added commandline error code convertor (util/strerror) * Added support for Hardware Acceleration hooking in SSL/TLS * Added OpenSSL / PolarSSL compatibility script (tests/compat.sh) and example application (programs/ssl/o_p_test) (requires OpenSSL) * Added X509 CA Path support * Added Thumb assembly optimizations * Added DEFLATE compression support as per RFC3749 (requires zlib) * Added blowfish algorithm (Generic and cipher layer) * Added PKCS#5 PBKDF2 key derivation function * Added Secure Renegotiation (RFC 5746) * Added predefined DHM groups from RFC 5114 * Added simple SSL session cache implementation * Added ServerName extension parsing (SNI) at server side * Added option to add minimum accepted SSL/TLS protocol version Changes * Removed redundant POLARSSL_DEBUG_MSG define * AES code only check for Padlock once * Fixed const-correctness mpi_get_bit() * Documentation for mpi_lsb() and mpi_msb() * Moved out_msg to out_hdr + 32 to support hardware acceleration * Changed certificate verify behaviour to comply with RFC 6125 section 6.3 to not match CN if subjectAltName extension is present (Closes ticket #56) * Cipher layer cipher_mode_t POLARSSL_MODE_CFB128 is renamed to POLARSSL_MODE_CFB, to also handle different block size CFB modes. * Removed handling for SSLv2 Client Hello (as per RFC 5246 recommendation) * Revamped session resumption handling * Generalized external private key implementation handling (like PKCS#11) in SSL/TLS * Revamped x509_verify() and the SSL f_vrfy callback implementations * Moved from unsigned long to fixed width uint32_t types throughout code * Renamed ciphersuites naming scheme to IANA reserved names Bugfix * Fixed handling error in mpi_cmp_mpi() on longer B values (found by Hui Dong) * Fixed potential heap corruption in x509_name allocation * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket #52) * Handle encryption with private key and decryption with public key as per RFC 2313 * Handle empty certificate subject names * Prevent reading over buffer boundaries on X509 certificate parsing * mpi_add_abs() now correctly handles adding short numbers to long numbers with carry rollover (found by Ruslan Yushchenko) * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob * Fixed MPI assembly for SPARC64 platform Security * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi Vanderbeken) = Version 1.1.8 released on 2013-10-01 Bugfix * Fixed potential memory leak when failing to resume a session * Fixed potential file descriptor leaks Security * Potential buffer-overflow for ssl_read_record() (independently found by both TrustInSoft and Paul Brodeur of Leviathan Security Group) * Potential negative value misinterpretation in load_file() * Potential heap buffer overflow on large hostname setting = Version 1.1.7 released on 2013-06-19 Changes * HAVEGE random generator disabled by default Bugfix * x509parse_crt() now better handles PEM error situations * ssl_parse_certificate() now calls x509parse_crt_der() directly instead of the x509parse_crt() wrapper that can also parse PEM certificates * Fixed values for 2-key Triple DES in cipher layer * ssl_write_certificate_request() can handle empty ca_chain Security * A possible DoS during the SSL Handshake, due to faulty parsing of PEM-encoded certificates has been fixed (found by Jack Lloyd) = Version 1.1.6 released on 2013-03-11 Bugfix * Fixed net_bind() for specified IP addresses on little endian systems Changes * Allow enabling of dummy error_strerror() to support some use-cases * Debug messages about padding errors during SSL message decryption are disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL Security * Removed timing differences during SSL message decryption in ssl_decrypt_buf() * Removed timing differences due to bad padding from rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 operations = Version 1.1.5 released on 2013-01-16 Bugfix * Fixed MPI assembly for SPARC64 platform * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob * mpi_add_abs() now correctly handles adding short numbers to long numbers with carry rollover * Moved mpi_inv_mod() outside POLARSSL_GENPRIME * Prevent reading over buffer boundaries on X509 certificate parsing * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket #52) * Fixed possible segfault in mpi_shift_r() (found by Manuel Pégourié-Gonnard) * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel Pégourié-Gonnard) * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 * Memory leak when using RSA_PKCS_V21 operations fixed * Handle encryption with private key and decryption with public key as per RFC 2313 * Fixes for MSVC6 Security * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi Vanderbeken) = Version 1.1.4 released on 2012-05-31 Bugfix * Correctly handle empty SSL/TLS packets (Found by James Yonan) * Fixed potential heap corruption in x509_name allocation * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) = Version 1.1.3 released on 2012-04-29 Bugfix * Fixed random MPI generation to not generate more size than requested. = Version 1.1.2 released on 2012-04-26 Bugfix * Fixed handling error in mpi_cmp_mpi() on longer B values (found by Hui Dong) Security * Fixed potential memory corruption on miscrafted client messages (found by Frama-C team at CEA LIST) * Fixed generation of DHM parameters to correct length (found by Ruslan Yushchenko) = Version 1.1.1 released on 2012-01-23 Bugfix * Check for failed malloc() in ssl_set_hostname() and x509_get_entries() (Closes ticket #47, found by Hugo Leisink) * Fixed issues with Intel compiler on 64-bit systems (Closes ticket #50) * Fixed multiple compiler warnings for VS6 and armcc * Fixed bug in CTR_CRBG selftest = Version 1.1.0 released on 2011-12-22 Features * Added ssl_session_reset() to allow better multi-connection pools of SSL contexts without needing to set all non-connection-specific data and pointers again. Adapted ssl_server to use this functionality. * Added ssl_set_max_version() to allow clients to offer a lower maximum supported version to a server to help buggy server implementations. (Closes ticket #36) * Added cipher_get_cipher_mode() and cipher_get_cipher_operation() introspection functions (Closes ticket #40) * Added CTR_DRBG based on AES-256-CTR (NIST SP 800-90) random generator * Added a generic entropy accumulator that provides support for adding custom entropy sources and added some generic and platform dependent entropy sources Changes * Documentation for AES and Camellia in modes CTR and CFB128 clarified. * Fixed rsa_encrypt and rsa_decrypt examples to use public key for encryption and private key for decryption. (Closes ticket #34) * Inceased maximum size of ASN1 length reads to 32-bits. * Added an EXPLICIT tag number parameter to x509_get_ext() * Added a separate CRL entry extension parsing function * Separated the ASN.1 parsing code from the X.509 specific parsing code. So now there is a module that is controlled with POLARSSL_ASN1_PARSE_C. * Changed the defined key-length of DES ciphers in cipher.h to include the parity bits, to prevent mistakes in copying data. (Closes ticket #33) * Loads of minimal changes to better support WINCE as a build target (Credits go to Marco Lizza) * Added POLARSSL_MPI_WINDOW_SIZE definition to allow easier time to memory trade-off * Introduced POLARSSL_MPI_MAX_SIZE and POLARSSL_MPI_MAX_BITS for MPI size management (Closes ticket #44) * Changed the used random function pointer to more flexible format. Renamed havege_rand() to havege_random() to prevent mistakes. Lots of changes as a consequence in library code and programs * Moved all examples programs to use the new entropy and CTR_DRBG * Added permissive certificate parsing to x509parse_crt() and x509parse_crtfile(). With permissive parsing the parsing does not stop on encountering a parse-error. Beware that the meaning of return values has changed! * All error codes are now negative. Even on mermory failures and IO errors. Bugfix * Fixed faulty HMAC-MD2 implementation. Found by dibac. (Closes ticket #37) * Fixed a bug where the CRL parser expected an EXPLICIT ASN.1 tag before version numbers * Allowed X509 key usage parsing to accept 4 byte values instead of the standard 1 byte version sometimes used by Microsoft. (Closes ticket #38) * Fixed incorrect behaviour in case of RSASSA-PSS with a salt length smaller than the hash length. (Closes ticket #41) * If certificate serial is longer than 32 octets, serial number is now appended with '....' after first 28 octets * Improved build support for s390x and sparc64 in bignum.h * Fixed MS Visual C++ name clash with int64 in sha4.h * Corrected removal of leading "00:" in printing serial numbers in certificates and CRLs = Version 1.0.0 released on 2011-07-27 Features * Expanded cipher layer with support for CFB128 and CTR mode * Added rsa_encrypt and rsa_decrypt simple example programs. Changes * The generic cipher and message digest layer now have normal error codes instead of integers Bugfix * Undid faulty bug fix in ssl_write() when flushing old data (Ticket #18) = Version 0.99-pre5 released on 2011-05-26 Features * Added additional Cipher Block Modes to symmetric ciphers (AES CTR, Camellia CTR, XTEA CBC) including the option to enable and disable individual modes when needed * Functions requiring File System functions can now be disabled by undefining POLARSSL_FS_IO * A error_strerror function() has been added to translate between error codes and their description. * Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter functions. * Added ssl_mail_client and ssl_fork_server as example programs. Changes * Major argument / variable rewrite. Introduced use of size_t instead of int for buffer lengths and loop variables for better unsigned / signed use. Renamed internal bigint types t_int and t_dbl to t_uint and t_udbl in the process * mpi_init() and mpi_free() now only accept a single MPI argument and do not accept variable argument lists anymore. * The error codes have been remapped and combining error codes is now done with a PLUS instead of an OR as error codes used are negative. * Changed behaviour of net_read(), ssl_fetch_input() and ssl_recv(). net_recv() now returns 0 on EOF instead of POLARSSL_ERR_NET_CONN_RESET. ssl_fetch_input() returns POLARSSL_ERR_SSL_CONN_EOF on an EOF from its f_recv() function. ssl_read() returns 0 if a POLARSSL_ERR_SSL_CONN_EOF is received after the handshake. * Network functions now return POLARSSL_ERR_NET_WANT_READ or POLARSSL_ERR_NET_WANT_WRITE instead of the ambiguous POLARSSL_ERR_NET_TRY_AGAIN = Version 0.99-pre4 released on 2011-04-01 Features * Added support for PKCS#1 v2.1 encoding and thus support for the RSAES-OAEP and RSASSA-PSS operations. * Reading of Public Key files incorporated into default x509 functionality as well. * Added mpi_fill_random() for centralized filling of big numbers with random data (Fixed ticket #10) Changes * Debug print of MPI now removes leading zero octets and displays actual bit size of the value. * x509parse_key() (and as a consequence x509parse_keyfile()) does not zeroize memory in advance anymore. Use rsa_init() before parsing a key or keyfile! Bugfix * Debug output of MPI's now the same independent of underlying platform (32-bit / 64-bit) (Fixes ticket #19, found by Mads Kiilerich and Mihai Militaru) * Fixed bug in ssl_write() when flushing old data (Fixed ticket #18, found by Nikolay Epifanov) * Fixed proper handling of RSASSA-PSS verification with variable length salt lengths = Version 0.99-pre3 released on 2011-02-28 This release replaces version 0.99-pre2 which had possible copyright issues. Features * Parsing PEM private keys encrypted with DES and AES are now supported as well (Fixes ticket #5) * Added crl_app program to allow easy reading and printing of X509 CRLs from file Changes * Parsing of PEM files moved to separate module (Fixes ticket #13). Also possible to remove PEM support for systems only using DER encoding Bugfixes * Corrected parsing of UTCTime dates before 1990 and after 1950 * Support more exotic OID's when parsing certificates (found by Mads Kiilerich) * Support more exotic name representations when parsing certificates (found by Mads Kiilerich) * Replaced the expired test certificates * Do not bail out if no client certificate specified. Try to negotiate anonymous connection (Fixes ticket #12, found by Boris Krasnovskiy) Security fixes * Fixed a possible Man-in-the-Middle attack on the Diffie Hellman key exchange (thanks to Larry Highsmith, Subreption LLC) = Version 0.99-pre1 released on 2011-01-30 Features Note: Most of these features have been donated by Fox-IT * Added Doxygen source code documentation parts * Added reading of DHM context from memory and file * Improved X509 certificate parsing to include extended certificate fields, including Key Usage * Improved certificate verification and verification against the available CRLs * Detection for DES weak keys and parity bits added * Improvements to support integration in other applications: + Added generic message digest and cipher wrapper + Improved information about current capabilities, status, objects and configuration + Added verification callback on certificate chain verification to allow external blacklisting + Additional example programs to show usage * Added support for PKCS#11 through the use of the libpkcs11-helper library Changes * x509parse_time_expired() checks time in addition to the existing date check * The ciphers member of ssl_context and the cipher member of ssl_session have been renamed to ciphersuites and ciphersuite respectively. This clarifies the difference with the generic cipher layer and is better naming altogether = Version 0.14.0 released on 2010-08-16 Features * Added support for SSL_EDH_RSA_AES_128_SHA and SSL_EDH_RSA_CAMELLIA_128_SHA ciphersuites * Added compile-time and run-time version information * Expanded ssl_client2 arguments for more flexibility * Added support for TLS v1.1 Changes * Made Makefile cleaner * Removed dependency on rand() in rsa_pkcs1_encrypt(). Now using random fuction provided to function and changed the prototype of rsa_pkcs1_encrypt(), rsa_init() and rsa_gen_key(). * Some SSL defines were renamed in order to avoid future confusion Bug fixes * Fixed CMake out of source build for tests (found by kkert) * rsa_check_private() now supports PKCS1v2 keys as well * Fixed deadlock in rsa_pkcs1_encrypt() on failing random generator = Version 0.13.1 released on 2010-03-24 Bug fixes * Fixed Makefile in library that was mistakenly merged * Added missing const string fixes = Version 0.13.0 released on 2010-03-21 Features * Added option parsing for host and port selection to ssl_client2 * Added support for GeneralizedTime in X509 parsing * Added cert_app program to allow easy reading and printing of X509 certificates from file or SSL connection. Changes * Added const correctness for main code base * X509 signature algorithm determination is now in a function to allow easy future expansion * Changed symmetric cipher functions to identical interface (returning int result values) * Changed ARC4 to use separate input/output buffer * Added reset function for HMAC context as speed-up for specific use-cases Bug fixes * Fixed bug resulting in failure to send the last certificate in the chain in ssl_write_certificate() and ssl_write_certificate_request() (found by fatbob) * Added small fixes for compiler warnings on a Mac (found by Frank de Brabander) * Fixed algorithmic bug in mpi_is_prime() (found by Smbat Tonoyan) = Version 0.12.1 released on 2009-10-04 Changes * Coverage test definitions now support 'depends_on' tagging system. * Tests requiring specific hashing algorithms now honor the defines. Bug fixes * Changed typo in #ifdef in x509parse.c (found by Eduardo) = Version 0.12.0 released on 2009-07-28 Features * Added CMake makefiles as alternative to regular Makefiles. * Added preliminary Code Coverage tests for AES, ARC4, Base64, MPI, SHA-family, MD-family, HMAC-SHA-family, Camellia, DES, 3-DES, RSA PKCS#1, XTEA, Diffie-Hellman and X509parse. Changes * Error codes are not (necessarily) negative. Keep this is mind when checking for errors. * RSA_RAW renamed to SIG_RSA_RAW for consistency. * Fixed typo in name of POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE. * Changed interface for AES and Camellia setkey functions to indicate invalid key lengths. Bug fixes * Fixed include location of endian.h on FreeBSD (found by Gabriel) * Fixed include location of endian.h and name clash on Apples (found by Martin van Hensbergen) * Fixed HMAC-MD2 by modifying md2_starts(), so that the required HMAC ipad and opad variables are not cleared. (found by code coverage tests) * Prevented use of long long in bignum if POLARSSL_HAVE_LONGLONG not defined (found by Giles Bathgate). * Fixed incorrect handling of negative strings in mpi_read_string() (found by code coverage tests). * Fixed segfault on handling empty rsa_context in rsa_check_pubkey() and rsa_check_privkey() (found by code coverage tests). * Fixed incorrect handling of one single negative input value in mpi_add_abs() (found by code coverage tests). * Fixed incorrect handling of negative first input value in mpi_sub_abs() (found by code coverage tests). * Fixed incorrect handling of negative first input value in mpi_mod_mpi() and mpi_mod_int(). Resulting change also affects mpi_write_string() (found by code coverage tests). * Corrected is_prime() results for 0, 1 and 2 (found by code coverage tests). * Fixed Camellia and XTEA for 64-bit Windows systems. = Version 0.11.1 released on 2009-05-17 * Fixed missing functionality for SHA-224, SHA-256, SHA384, SHA-512 in rsa_pkcs1_sign() = Version 0.11.0 released on 2009-05-03 * Fixed a bug in mpi_gcd() so that it also works when both input numbers are even and added testcases to check (found by Pierre Habouzit). * Added support for SHA-224, SHA-256, SHA-384 and SHA-512 one way hash functions with the PKCS#1 v1.5 signing and verification. * Fixed minor bug regarding mpi_gcd located within the POLARSSL_GENPRIME block. * Fixed minor memory leak in x509parse_crt() and added better handling of 'full' certificate chains (found by Mathias Olsson). * Centralized file opening and reading for x509 files into load_file() * Made definition of net_htons() endian-clean for big endian systems (Found by Gernot). * Undefining POLARSSL_HAVE_ASM now also handles prevents asm in padlock and timing code. * Fixed an off-by-one buffer allocation in ssl_set_hostname() responsible for crashes and unwanted behaviour. * Added support for Certificate Revocation List (CRL) parsing. * Added support for CRL revocation to x509parse_verify() and SSL/TLS code. * Fixed compatibility of XTEA and Camellia on a 64-bit system (found by Felix von Leitner). = Version 0.10.0 released on 2009-01-12 * Migrated XySSL to PolarSSL * Added XTEA symmetric cipher * Added Camellia symmetric cipher * Added support for ciphersuites: SSL_RSA_CAMELLIA_128_SHA, SSL_RSA_CAMELLIA_256_SHA and SSL_EDH_RSA_CAMELLIA_256_SHA * Fixed dangerous bug that can cause a heap overflow in rsa_pkcs1_decrypt (found by Christophe Devine) ================================================================ XySSL ChangeLog = Version 0.9 released on 2008-03-16 * Added support for ciphersuite: SSL_RSA_AES_128_SHA * Enabled support for large files by default in aescrypt2.c * Preliminary openssl wrapper contributed by David Barrett * Fixed a bug in ssl_write() that caused the same payload to be sent twice in non-blocking mode when send returns EAGAIN * Fixed ssl_parse_client_hello(): session id and challenge must not be swapped in the SSLv2 ClientHello (found by Greg Robson) * Added user-defined callback debug function (Krystian Kolodziej) * Before freeing a certificate, properly zero out all cert. data * Fixed the "mode" parameter so that encryption/decryption are not swapped on PadLock; also fixed compilation on older versions of gcc (bug reported by David Barrett) * Correctly handle the case in padlock_xcryptcbc() when input or output data is non-aligned by falling back to the software implementation, as VIA Nehemiah cannot handle non-aligned buffers * Fixed a memory leak in x509parse_crt() which was reported by Greg Robson-Garth; some x509write.c fixes by Pascal Vizeli, thanks to Matthew Page who reported several bugs * Fixed x509_get_ext() to accept some rare certificates which have an INTEGER instead of a BOOLEAN for BasicConstraints::cA. * Added support on the client side for the TLS "hostname" extension (patch contributed by David Patino) * Make x509parse_verify() return BADCERT_CN_MISMATCH when an empty string is passed as the CN (bug reported by spoofy) * Added an option to enable/disable the BN assembly code * Updated rsa_check_privkey() to verify that (D*E) = 1 % (P-1)*(Q-1) * Disabled obsolete hash functions by default (MD2, MD4); updated selftest and benchmark to not test ciphers that have been disabled * Updated x509parse_cert_info() to correctly display byte 0 of the serial number, setup correct server port in the ssl client example * Fixed a critical denial-of-service with X.509 cert. verification: peer may cause xyssl to loop indefinitely by sending a certificate for which the RSA signature check fails (bug reported by Benoit) * Added test vectors for: AES-CBC, AES-CFB, DES-CBC and 3DES-CBC, HMAC-MD5, HMAC-SHA1, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 * Fixed HMAC-SHA-384 and HMAC-SHA-512 (thanks to Josh Sinykin) * Modified ssl_parse_client_key_exchange() to protect against Daniel Bleichenbacher attack on PKCS#1 v1.5 padding, as well as the Klima-Pokorny-Rosa extension of Bleichenbacher's attack * Updated rsa_gen_key() so that ctx->N is always nbits in size * Fixed assembly PPC compilation errors on Mac OS X, thanks to David Barrett and Dusan Semen = Version 0.8 released on 2007-10-20 * Modified the HMAC functions to handle keys larger than 64 bytes, thanks to Stephane Desneux and gary ng * Fixed ssl_read_record() to properly update the handshake message digests, which fixes IE6/IE7 client authentication * Cleaned up the XYSSL* #defines, suggested by Azriel Fasten * Fixed net_recv(), thanks to Lorenz Schori and Egon Kocjan * Added user-defined callbacks for handling I/O and sessions * Added lots of debugging output in the SSL/TLS functions * Added preliminary X.509 cert. writing by Pascal Vizeli * Added preliminary support for the VIA PadLock routines * Added AES-CFB mode of operation, contributed by chmike * Added an SSL/TLS stress testing program (ssl_test.c) * Updated the RSA PKCS#1 code to allow choosing between RSA_PUBLIC and RSA_PRIVATE, as suggested by David Barrett * Updated ssl_read() to skip 0-length records from OpenSSL * Fixed the make install target to comply with *BSD make * Fixed a bug in mpi_read_binary() on 64-bit platforms * mpi_is_prime() speedups, thanks to Kevin McLaughlin * Fixed a long standing memory leak in mpi_is_prime() * Replaced realloc with malloc in mpi_grow(), and set the sign of zero as positive in mpi_init() (reported by Jonathan M. McCune) = Version 0.7 released on 2007-07-07 * Added support for the MicroBlaze soft-core processor * Fixed a bug in ssl_tls.c which sometimes prevented SSL connections from being established with non-blocking I/O * Fixed a couple bugs in the VS6 and UNIX Makefiles * Fixed the "PIC register ebx clobbered in asm" bug * Added HMAC starts/update/finish support functions * Added the SHA-224, SHA-384 and SHA-512 hash functions * Fixed the net_set_*block routines, thanks to Andreas * Added a few demonstration programs: md5sum, sha1sum, dh_client, dh_server, rsa_genkey, rsa_sign, rsa_verify * Added new bignum import and export helper functions * Rewrote README.txt in program/ssl/ca to better explain how to create a test PKI = Version 0.6 released on 2007-04-01 * Ciphers used in SSL/TLS can now be disabled at compile time, to reduce the memory footprint on embedded systems * Added multiply assembly code for the TriCore and modified havege_struct for this processor, thanks to David Patiño * Added multiply assembly code for 64-bit PowerPCs, thanks to Peking University and the OSU Open Source Lab * Added experimental support of Quantum Cryptography * Added support for autoconf, contributed by Arnaud Cornet * Fixed "long long" compilation issues on IA-64 and PPC64 * Fixed a bug introduced in xyssl-0.5/timing.c: hardclock was not being correctly defined on ARM and MIPS = Version 0.5 released on 2007-03-01 * Added multiply assembly code for SPARC and Alpha * Added (beta) support for non-blocking I/O operations * Implemented session resuming and client authentication * Fixed some portability issues on WinCE, MINIX 3, Plan9 (thanks to Benjamin Newman), HP-UX, FreeBSD and Solaris * Improved the performance of the EDH key exchange * Fixed a bug that caused valid packets with a payload size of 16384 bytes to be rejected = Version 0.4 released on 2007-02-01 * Added support for Ephemeral Diffie-Hellman key exchange * Added multiply asm code for SSE2, ARM, PPC, MIPS and M68K * Various improvement to the modular exponentiation code * Rewrote the headers to generate the API docs with doxygen * Fixed a bug in ssl_encrypt_buf (incorrect padding was generated) and in ssl_parse_client_hello (max. client version was not properly set), thanks to Didier Rebeix * Fixed another bug in ssl_parse_client_hello: clients with cipherlists larger than 96 bytes were incorrectly rejected * Fixed a couple memory leak in x509_read.c = Version 0.3 released on 2007-01-01 * Added server-side SSLv3 and TLSv1.0 support * Multiple fixes to enhance the compatibility with g++, thanks to Xosé Antón Otero Ferreira * Fixed a bug in the CBC code, thanks to dowst; also, the bignum code is no longer dependent on long long * Updated rsa_pkcs1_sign to handle arbitrary large inputs * Updated timing.c for improved compatibility with i386 and 486 processors, thanks to Arnaud Cornet = Version 0.2 released on 2006-12-01 * Updated timing.c to support ARM and MIPS arch * Updated the MPI code to support 8086 on MSVC 1.5 * Added the copyright notice at the top of havege.h * Fixed a bug in sha2_hmac, thanks to newsoft/Wenfang Zhang * Fixed a bug reported by Adrian Rüegsegger in x509_read_key * Fixed a bug reported by Torsten Lauter in ssl_read_record * Fixed a bug in rsa_check_privkey that would wrongly cause valid RSA keys to be dismissed (thanks to oldwolf) * Fixed a bug in mpi_is_prime that caused some primes to fail the Miller-Rabin primality test I'd also like to thank Younès Hafri for the CRUX linux port, Khalil Petit who added XySSL into pkgsrc and Arnaud Cornet who maintains the Debian package :-) = Version 0.1 released on 2006-11-01 optee_os-4.3.0/lib/libmbedtls/mbedtls/LICENSE000066400000000000000000000722341464416617300207050ustar00rootroot00000000000000Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. This means that users may choose which of these licenses they take the code under. The full text of each of these licenses is given below. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================== GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. optee_os-4.3.0/lib/libmbedtls/mbedtls/README.md000066400000000000000000000522251464416617300211550ustar00rootroot00000000000000README for Mbed TLS =================== Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems. Mbed TLS includes a reference implementation of the [PSA Cryptography API](#psa-cryptography-api). This is currently a preview for evaluation purposes only. Configuration ------------- Mbed TLS should build out of the box on most systems. Some platform specific options are available in the fully documented configuration file `include/mbedtls/mbedtls_config.h`, which is also the place where features can be selected. This file can be edited manually, or in a more programmatic way using the Python 3 script `scripts/config.py` (use `--help` for usage instructions). Compiler options can be set using conventional environment variables such as `CC` and `CFLAGS` when using the Make and CMake build system (see below). We provide some non-standard configurations focused on specific use cases in the `configs/` directory. You can read more about those in `configs/README.txt` Documentation ------------- The main Mbed TLS documentation is available via [ReadTheDocs](https://mbed-tls.readthedocs.io/). Documentation for the PSA Cryptography API is available [on GitHub](https://arm-software.github.io/psa-api/crypto/). To generate a local copy of the library documentation in HTML format, tailored to your compile-time configuration: 1. Make sure that [Doxygen](http://www.doxygen.nl/) is installed. 1. Run `make apidoc`. 1. Browse `apidoc/index.html` or `apidoc/modules.html`. For other sources of documentation, see the [SUPPORT](SUPPORT.md) document. Compiling --------- There are currently three active build systems used within Mbed TLS releases: - GNU Make - CMake - Microsoft Visual Studio The main systems used for development are CMake and GNU Make. Those systems are always complete and up-to-date. The others should reflect all changes present in the CMake and Make build system, although features may not be ported there automatically. The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx509, and libmbedtls. Note that libmbedtls depends on libmbedx509 and libmbedcrypto, and libmbedx509 depends on libmbedcrypto. As a result, some linkers will expect flags to be in a specific order, for example the GNU linker wants `-lmbedtls -lmbedx509 -lmbedcrypto`. ### Tool versions You need the following tools to build the library with the provided makefiles: * GNU Make 3.82 or a build tool that CMake supports. * A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, Arm Compiler 6, IAR 8 and Visual Studio 2017. More recent versions should work. Slightly older versions may work. * Python 3.8 to generate the test code. Python is also needed to integrate PSA drivers and to build the development branch (see next section). * Perl to run the tests, and to generate some source files in the development branch. * CMake 3.10.2 or later (if using CMake). * Microsoft Visual Studio 2017 or later (if using Visual Studio). * Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work). ### Git usage The `development` branch and the `mbedtls-3.6` long-term support branch of Mbed TLS use a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules#_cloning_submodules) ([framework](https://github.com/Mbed-TLS/mbedtls-framework)). This is not needed to merely compile the library at a release tag. This is not needed to consume a release archive (zip or tar). ### Generated source files in the development branch The source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch. The following tools are required: * Perl, for some library source files and for Visual Studio build files. * Python 3.8 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run: ``` python3 -m pip install --user -r scripts/basic.requirements.txt ``` Depending on your Python installation, you may need to invoke `python` instead of `python3`. To install the packages system-wide, omit the `--user` option. * A C compiler for the host platform, for some test data. If you are cross-compiling, you must set the `CC` environment variable to a C compiler for the host platform when generating the configuration-independent files. Any of the following methods are available to generate the configuration-independent files: * If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files. * On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically. * Run `make generated_files` to generate all the configuration-independent files. * On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files. * On Windows, run `scripts\make_generated_files.bat` to generate all the configuration-independent files. ### Make We require GNU Make. To build the library and the sample programs, GNU Make and a C compiler are sufficient. Some of the more advanced build targets require some Unix/Linux tools. We intentionally only use a minimum of functionality in the makefiles in order to keep them as simple and independent of different toolchains as possible, to allow users to more easily move between different platforms. Users who need more features are recommended to use CMake. In order to build from the source code using GNU Make, just enter at the command line: make In order to run the tests, enter: make check The tests need Python to be built and Perl to be run. If you don't have one of them installed, you can skip building the tests with: make no_test You'll still be able to run a much smaller set of tests with: programs/test/selftest In order to build for a Windows platform, you should use `WINDOWS_BUILD=1` if the target is Windows but the build environment is Unix-like (for instance when cross-compiling, or compiling from an MSYS shell), and `WINDOWS=1` if the build environment is a Windows shell (for instance using mingw32-make) (in that case some targets will not be available). Setting the variable `SHARED` in your environment will build shared libraries in addition to the static libraries. Setting `DEBUG` gives you a debug build. You can override `CFLAGS` and `LDFLAGS` by setting them in your environment or on the make command line; compiler warning options may be overridden separately using `WARNING_CFLAGS`. Some directory-specific options (for example, `-I` directives) are still preserved. Please note that setting `CFLAGS` overrides its default value of `-O2` and setting `WARNING_CFLAGS` overrides its default value (starting with `-Wall -Wextra`), so if you just want to add some warning options to the default ones, you can do so by setting `CFLAGS=-O2 -Werror` for example. Setting `WARNING_CFLAGS` is useful when you want to get rid of its default content (for example because your compiler doesn't accept `-Wall` as an option). Directory-specific options cannot be overridden from the command line. Depending on your platform, you might run into some issues. Please check the Makefiles in `library/`, `programs/` and `tests/` for options to manually add or remove for specific platforms. You can also check [the Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/) for articles on your platform or issue. In case you find that you need to do something else as well, please let us know what, so we can add it to the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/). ### CMake In order to build the source using CMake in a separate directory (recommended), just enter at the command line: mkdir /path/to/build_dir && cd /path/to/build_dir cmake /path/to/mbedtls_source cmake --build . In order to run the tests, enter: ctest The test suites need Python to be built and Perl to be executed. If you don't have one of these installed, you'll want to disable the test suites with: cmake -DENABLE_TESTING=Off /path/to/mbedtls_source If you disabled the test suites, but kept the programs enabled, you can still run a much smaller set of tests with: programs/test/selftest To configure CMake for building shared libraries, use: cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On /path/to/mbedtls_source There are many different build modes available within the CMake buildsystem. Most of them are available for gcc and clang, though some are compiler-specific: - `Release`. This generates the default code without any unnecessary information in the binary files. - `Debug`. This generates debug information and disables optimization of the code. - `Coverage`. This generates code coverage information in addition to debug information. - `ASan`. This instruments the code with AddressSanitizer to check for memory errors. (This includes LeakSanitizer, with recent version of gcc and clang.) (With recent version of clang, this mode also instruments the code with UndefinedSanitizer to check for undefined behaviour.) - `ASanDbg`. Same as ASan but slower, with debug information and better stack traces. - `MemSan`. This instruments the code with MemorySanitizer to check for uninitialised memory reads. Experimental, needs recent clang on Linux/x86\_64. - `MemSanDbg`. Same as MemSan but slower, with debug information, better stack traces and origin tracking. - `Check`. This activates the compiler warnings that depend on optimization and treats all warnings as errors. Switching build modes in CMake is simple. For debug mode, enter at the command line: cmake -D CMAKE_BUILD_TYPE=Debug /path/to/mbedtls_source To list other available CMake options, use: cmake -LH Note that, with CMake, you can't adjust the compiler or its flags after the initial invocation of cmake. This means that `CC=your_cc make` and `make CC=your_cc` will *not* work (similarly with `CFLAGS` and other variables). These variables need to be adjusted when invoking cmake for the first time, for example: CC=your_cc cmake /path/to/mbedtls_source If you already invoked cmake and want to change those settings, you need to remove the build directory and create it again. Note that it is possible to build in-place; this will however overwrite the provided Makefiles (see `scripts/tmp_ignore_makefiles.sh` if you want to prevent `git status` from showing them as modified). In order to do so, from the Mbed TLS source directory, use: cmake . make If you want to change `CC` or `CFLAGS` afterwards, you will need to remove the CMake cache. This can be done with the following command using GNU find: find . -iname '*cmake*' -not -name CMakeLists.txt -exec rm -rf {} + You can now make the desired change: CC=your_cc cmake . make Regarding variables, also note that if you set CFLAGS when invoking cmake, your value of CFLAGS doesn't override the content provided by cmake (depending on the build mode as seen above), it's merely prepended to it. #### Consuming Mbed TLS Mbed TLS provides a package config file for consumption as a dependency in other CMake projects. You can include Mbed TLS's CMake targets yourself with: find_package(MbedTLS) If prompted, set `MbedTLS_DIR` to `${YOUR_MBEDTLS_INSTALL_DIR}/cmake`. This creates the following targets: - `MbedTLS::mbedcrypto` (Crypto library) - `MbedTLS::mbedtls` (TLS library) - `MbedTLS::mbedx509` (X509 library) You can then use these directly through `target_link_libraries()`: add_executable(xyz) target_link_libraries(xyz PUBLIC MbedTLS::mbedtls MbedTLS::mbedcrypto MbedTLS::mbedx509) This will link the Mbed TLS libraries to your library or application, and add its include directories to your target (transitively, in the case of `PUBLIC` or `INTERFACE` link libraries). #### Mbed TLS as a subproject Mbed TLS supports being built as a CMake subproject. One can use `add_subdirectory()` from a parent CMake project to include Mbed TLS as a subproject. ### Microsoft Visual Studio The build files for Microsoft Visual Studio are generated for Visual Studio 2017. The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available. In the development branch of Mbed TLS, the Visual Studio solution files need to be generated first as described in [“Generated source files in the development branch”](#generated-source-files-in-the-development-branch). Example programs ---------------- We've included example programs for a lot of different features and uses in [`programs/`](programs/README.md). Please note that the goal of these sample programs is to demonstrate specific features of the library, and the code may need to be adapted to build a real-world application. Tests ----- Mbed TLS includes an elaborate test suite in `tests/` that initially requires Python to generate the tests files (e.g. `test\_suite\_mpi.c`). These files are generated from a `function file` (e.g. `suites/test\_suite\_mpi.function`) and a `data file` (e.g. `suites/test\_suite\_mpi.data`). The `function file` contains the test functions. The `data file` contains the test cases, specified as parameters that will be passed to the test function. For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, additional test scripts are available: - `tests/ssl-opt.sh` runs integration tests for various TLS options (renegotiation, resumption, etc.) and tests interoperability of these options with other implementations. - `tests/compat.sh` tests interoperability of every ciphersuite with other implementations. - `tests/scripts/test-ref-configs.pl` test builds in various reduced configurations. - `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on. - `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc). Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/main/README.md#quick-start). Porting Mbed TLS ---------------- Mbed TLS can be ported to many different architectures, OS's and platforms. Before starting a port, you may find the following Knowledge Base articles useful: - [Porting Mbed TLS to a new environment or OS](https://mbed-tls.readthedocs.io/en/latest/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS/) - [What external dependencies does Mbed TLS rely on?](https://mbed-tls.readthedocs.io/en/latest/kb/development/what-external-dependencies-does-mbedtls-rely-on/) - [How do I configure Mbed TLS](https://mbed-tls.readthedocs.io/en/latest/kb/compiling-and-building/how-do-i-configure-mbedtls/) Mbed TLS is mostly written in portable C99; however, it has a few platform requirements that go beyond the standard, but are met by most modern architectures: - Bytes must be 8 bits. - All-bits-zero must be a valid representation of a null pointer. - Signed integers must be represented using two's complement. - `int` and `size_t` must be at least 32 bits wide. - The types `uint8_t`, `uint16_t`, `uint32_t` and their signed equivalents must be available. - Mixed-endian platforms are not supported. - SIZE_MAX must be at least as big as INT_MAX and UINT_MAX. PSA cryptography API -------------------- ### PSA API Arm's [Platform Security Architecture (PSA)](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) is a holistic set of threat models, security analyses, hardware and firmware architecture specifications, and an open source firmware reference implementation. PSA provides a recipe, based on industry best practice, that allows security to be consistently designed in, at both a hardware and firmware level. The [PSA cryptography API](https://arm-software.github.io/psa-api/crypto/) provides access to a set of cryptographic primitives. It has a dual purpose. First, it can be used in a PSA-compliant platform to build services, such as secure boot, secure storage and secure communication. Second, it can also be used independently of other PSA components on any platform. The design goals of the PSA cryptography API include: * The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired. * The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example, in order to take advantage of hardware accelerators. * All access to the keys happens through key identifiers, which allows support for external cryptoprocessors that is transparent to applications. * The interface to algorithms is generic, favoring algorithm agility. * The interface is designed to be easy to use and hard to accidentally misuse. Arm welcomes feedback on the design of the API. If you think something could be improved, please open an issue on our Github repository. Alternatively, if you prefer to provide your feedback privately, please email us at [`mbed-crypto@arm.com`](mailto:mbed-crypto@arm.com). All feedback received by email is treated confidentially. ### PSA implementation in Mbed TLS Mbed TLS includes a reference implementation of the PSA Cryptography API. However, it does not aim to implement the whole specification; in particular it does not implement all the algorithms. The X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details. ### PSA drivers Mbed TLS supports drivers for cryptographic accelerators, secure elements and random generators. This is work in progress. Please note that the driver interfaces are not fully stable yet and may change without notice. We intend to preserve backward compatibility for application code (using the PSA Crypto API), but the code of the drivers may have to change in future minor releases of Mbed TLS. Please see the [PSA driver example and guide](docs/psa-driver-example-and-guide.md) for information on writing a driver. When using drivers, you will generally want to enable two compilation options (see the reference manual for more information): * `MBEDTLS_USE_PSA_CRYPTO` is necessary so that the X.509 and TLS code calls the PSA drivers rather than the built-in software implementation. * `MBEDTLS_PSA_CRYPTO_CONFIG` allows you to enable PSA cryptographic mechanisms without including the code of the corresponding software implementation. This is not yet supported for all mechanisms. License ------- Unless specifically indicated otherwise in a file, Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. See the [LICENSE](LICENSE) file for the full text of these licenses, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information. ### Third-party code included in Mbed TLS This project contains code from other projects. This code is located within the `3rdparty/` directory. The original license text is included within project subdirectories, where it differs from the normal Mbed TLS license, and/or in source files. The projects are listed below: * `3rdparty/everest/`: Files stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license. * `3rdparty/p256-m/p256-m/`: Files have been taken from the [p256-m](https://github.com/mpg/p256-m) repository. The code in the original repository is distributed under the Apache 2.0 license. It is distributed in Mbed TLS under a dual Apache-2.0 OR GPL-2.0-or-later license with permission from the author. Contributing ------------ We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this. Contact ------- * To report a security vulnerability in Mbed TLS, please email . For more information, see [`SECURITY.md`](SECURITY.md). * To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/Mbed-TLS/mbedtls/issues/new/choose). * Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS. optee_os-4.3.0/lib/libmbedtls/mbedtls/SECURITY.md000066400000000000000000000142311464416617300214620ustar00rootroot00000000000000## Reporting Vulnerabilities If you think you have found an Mbed TLS security vulnerability, then please send an email to the security team at . ## Security Incident Handling Process Our security process is detailed in our [security center](https://developer.trustedfirmware.org/w/mbed-tls/security-center/). Its primary goal is to ensure fixes are ready to be deployed when the issue goes public. ## Maintained branches Only the maintained branches, as listed in [`BRANCHES.md`](BRANCHES.md), get security fixes. Users are urged to always use the latest version of a maintained branch. ## Threat model We classify attacks based on the capabilities of the attacker. ### Remote attacks In this section, we consider an attacker who can observe and modify data sent over the network. This includes observing the content and timing of individual packets, as well as suppressing or delaying legitimate messages, and injecting messages. Mbed TLS aims to fully protect against remote attacks and to enable the user application in providing full protection against remote attacks. Said protection is limited to providing security guarantees offered by the protocol being implemented. (For example Mbed TLS alone won't guarantee that the messages will arrive without delay, as the TLS protocol doesn't guarantee that either.) **Warning!** Block ciphers do not yet achieve full protection against attackers who can measure the timing of packets with sufficient precision. For details and workarounds see the [Block Ciphers](#block-ciphers) section. ### Local attacks In this section, we consider an attacker who can run software on the same machine. The attacker has insufficient privileges to directly access Mbed TLS assets such as memory and files. #### Timing attacks The attacker is able to observe the timing of instructions executed by Mbed TLS by leveraging shared hardware that both Mbed TLS and the attacker have access to. Typical attack vectors include cache timings, memory bus contention and branch prediction. Mbed TLS provides limited protection against timing attacks. The cost of protecting against timing attacks widely varies depending on the granularity of the measurements and the noise present. Therefore the protection in Mbed TLS is limited. We are only aiming to provide protection against **publicly documented attack techniques**. As attacks keep improving, so does Mbed TLS's protection. Mbed TLS is moving towards a model of fully timing-invariant code, but has not reached this point yet. **Remark:** Timing information can be observed over the network or through physical side channels as well. Remote and physical timing attacks are covered in the [Remote attacks](remote-attacks) and [Physical attacks](physical-attacks) sections respectively. **Warning!** Block ciphers do not yet achieve full protection. For details and workarounds see the [Block Ciphers](#block-ciphers) section. #### Local non-timing side channels The attacker code running on the platform has access to some sensor capable of picking up information on the physical state of the hardware while Mbed TLS is running. This could for example be an analogue-to-digital converter on the platform that is located unfortunately enough to pick up the CPU noise. Mbed TLS doesn't make any security guarantees against local non-timing-based side channel attacks. If local non-timing attacks are present in a use case or a user application's threat model, they need to be mitigated by the platform. #### Local fault injection attacks Software running on the same hardware can affect the physical state of the device and introduce faults. Mbed TLS doesn't make any security guarantees against local fault injection attacks. If local fault injection attacks are present in a use case or a user application's threat model, they need to be mitigated by the platform. ### Physical attacks In this section, we consider an attacker who has access to physical information about the hardware Mbed TLS is running on and/or can alter the physical state of the hardware (e.g. power analysis, radio emissions or fault injection). Mbed TLS doesn't make any security guarantees against physical attacks. If physical attacks are present in a use case or a user application's threat model, they need to be mitigated by physical countermeasures. ### Caveats #### Out-of-scope countermeasures Mbed TLS has evolved organically and a well defined threat model hasn't always been present. Therefore, Mbed TLS might have countermeasures against attacks outside the above defined threat model. The presence of such countermeasures don't mean that Mbed TLS provides protection against a class of attacks outside of the above described threat model. Neither does it mean that the failure of such a countermeasure is considered a vulnerability. #### Block ciphers Currently there are four block ciphers in Mbed TLS: AES, CAMELLIA, ARIA and DES. The pure software implementation in Mbed TLS implementation uses lookup tables, which are vulnerable to timing attacks. These timing attacks can be physical, local or depending on network latency even a remote. The attacks can result in key recovery. **Workarounds:** - Turn on hardware acceleration for AES. This is supported only on selected architectures and currently only available for AES. See configuration options `MBEDTLS_AESCE_C`, `MBEDTLS_AESNI_C` and `MBEDTLS_PADLOCK_C` for details. - Add a secure alternative implementation (typically hardware acceleration) for the vulnerable cipher. See the [Alternative Implementations Guide](docs/architecture/alternative-implementations.md) for more information. - Use cryptographic mechanisms that are not based on block ciphers. In particular, for authenticated encryption, use ChaCha20/Poly1305 instead of block cipher modes. For random generation, use HMAC\_DRBG instead of CTR\_DRBG. #### Everest The HACL* implementation of X25519 taken from the Everest project only protects against remote timing attacks. (See their [Security Policy](https://github.com/hacl-star/hacl-star/blob/main/SECURITY.md).) The Everest variant is only used when `MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED` configuration option is defined. This option is off by default. optee_os-4.3.0/lib/libmbedtls/mbedtls/SUPPORT.md000066400000000000000000000012501464416617300213640ustar00rootroot00000000000000## Documentation Here are some useful sources of information about using Mbed TLS: - [ReadTheDocs](https://mbed-tls.readthedocs.io/); - API documentation, see the [Documentation section of the README](README.md#documentation); - the `docs` directory in the source tree; - the [Mbed TLS Knowledge Base](https://mbed-tls.readthedocs.io/en/latest/kb/); - the [Mbed TLS mailing-list archives](https://lists.trustedfirmware.org/archives/list/mbed-tls@lists.trustedfirmware.org/). ## Asking Questions If you can't find your answer in the above sources, please use the [Mbed TLS mailing list](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org). optee_os-4.3.0/lib/libmbedtls/mbedtls/dco.txt000066400000000000000000000026151464416617300212020ustar00rootroot00000000000000Developer Certificate of Origin Version 1.1 Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 Letterman Drive Suite D4700 San Francisco, CA, 94129 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. optee_os-4.3.0/lib/libmbedtls/mbedtls/include/000077500000000000000000000000001464416617300213135ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/000077500000000000000000000000001464416617300227455ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/aes.h000066400000000000000000000665711464416617300237050ustar00rootroot00000000000000/** * \file aes.h * * \brief This file contains AES definitions and functions. * * The Advanced Encryption Standard (AES) specifies a FIPS-approved * cryptographic algorithm that can be used to protect electronic * data. * * The AES algorithm is a symmetric block cipher that can * encrypt and decrypt information. For more information, see * FIPS Publication 197: Advanced Encryption Standard and * ISO/IEC 18033-2:2006: Information technology -- Security * techniques -- Encryption algorithms -- Part 2: Asymmetric * ciphers. * * The AES-XTS block mode is standardized by NIST SP 800-38E * * and described in detail by IEEE P1619 * . */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AES_H #define MBEDTLS_AES_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include #include /* padlock.c and aesni.c rely on these values! */ #define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ #define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ /* Error codes in range 0x0020-0x0022 */ /** Invalid key length. */ #define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /** Invalid data input length. */ #define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /* Error codes in range 0x0021-0x0025 */ /** Invalid input data. */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_AES_ALT) // Regular implementation // /** * \brief The AES context-type definition. */ typedef struct mbedtls_aes_context { int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ size_t MBEDTLS_PRIVATE(rk_offset); /*!< The offset in array elements to AES round keys in the buffer. */ #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C) uint32_t MBEDTLS_PRIVATE(buf)[44]; /*!< Aligned data buffer to hold 10 round keys for 128-bit case. */ #else uint32_t MBEDTLS_PRIVATE(buf)[68]; /*!< Unaligned data buffer. This buffer can hold 32 extra Bytes, which can be used for one of the following purposes:
  • Alignment if VIA padlock is used.
  • Simplifying key expansion in the 256-bit case by generating an extra round key.
*/ #endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH && !MBEDTLS_PADLOCK_C */ } mbedtls_aes_context; #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief The AES XTS context-type definition. */ typedef struct mbedtls_aes_xts_context { mbedtls_aes_context MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block encryption or decryption. */ mbedtls_aes_context MBEDTLS_PRIVATE(tweak); /*!< The AES context used for tweak computation. */ } mbedtls_aes_xts_context; #endif /* MBEDTLS_CIPHER_MODE_XTS */ #else /* MBEDTLS_AES_ALT */ #include "aes_alt.h" #endif /* MBEDTLS_AES_ALT */ /** * \brief This function initializes the specified AES context. * * It must be the first API called before using * the context. * * \param ctx The AES context to initialize. This must not be \c NULL. */ void mbedtls_aes_init(mbedtls_aes_context *ctx); /** * \brief This function releases and clears the specified AES context. * * \param ctx The AES context to clear. * If this is \c NULL, this function does nothing. * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_free(mbedtls_aes_context *ctx); #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief This function initializes the specified AES XTS context. * * It must be the first API called before using * the context. * * \param ctx The AES XTS context to initialize. This must not be \c NULL. */ void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx); /** * \brief This function releases and clears the specified AES XTS context. * * \param ctx The AES XTS context to clear. * If this is \c NULL, this function does nothing. * Otherwise, the context must have been at least initialized. */ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx); #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** * \brief This function sets the encryption key. * * \param ctx The AES context to which the key should be bound. * It must be initialized. * \param key The encryption key. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed in bits. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief This function sets the decryption key. * * \param ctx The AES context to which the key should be bound. * It must be initialized. * \param key The decryption key. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of data passed. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief This function prepares an XTS context for encryption and * sets the encryption key. * * \param ctx The AES XTS context to which the key should be bound. * It must be initialized. * \param key The encryption key. This is comprised of the XTS key1 * concatenated with the XTS key2. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of \p key passed in bits. Valid options are: *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • *
  • 512 bits (each of key1 and key2 is a 256-bit key)
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits); /** * \brief This function prepares an XTS context for decryption and * sets the decryption key. * * \param ctx The AES XTS context to which the key should be bound. * It must be initialized. * \param key The decryption key. This is comprised of the XTS key1 * concatenated with the XTS key2. * This must be a readable buffer of size \p keybits bits. * \param keybits The size of \p key passed in bits. Valid options are: *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • *
  • 512 bits (each of key1 and key2 is a 256-bit key)
* * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** * \brief This function performs an AES single-block encryption or * decryption operation. * * It performs the operation defined in the \p mode parameter * (encrypt or decrypt), on the input data buffer defined in * the \p input parameter. * * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or * mbedtls_aes_setkey_dec() must be called before the first * call to this API with the same context. * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param input The buffer holding the input data. * It must be readable and at least \c 16 Bytes long. * \param output The buffer where the output data will be written. * It must be writeable and at least \c 16 Bytes long. * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief This function performs an AES-CBC encryption or decryption operation * on full blocks. * * It performs the operation defined in the \p mode * parameter (encrypt/decrypt), on the input data buffer defined in * the \p input parameter. * * It can be called as many times as needed, until all the input * data is processed. mbedtls_aes_init(), and either * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called * before the first call to this API with the same context. * * \note This function operates on full blocks, that is, the input size * must be a multiple of the AES block size of \c 16 Bytes. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the IV, you should * either save it manually or use the cipher module instead. * * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of the input data in Bytes. This must be a * multiple of the block size (\c 16 Bytes). * \param iv Initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH * on failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /** * \brief This function performs an AES-XTS encryption or decryption * operation for an entire XTS data unit. * * AES-XTS encrypts or decrypts blocks based on their location as * defined by a data unit number. The data unit number must be * provided by \p data_unit. * * NIST SP 800-38E limits the maximum size of a data unit to 2^20 * AES blocks. If the data unit is larger than this, this function * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. * * \param ctx The AES XTS context to use for AES XTS operations. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of a data unit in Bytes. This can be any * length between 16 bytes and 2^24 bytes inclusive * (between 1 and 2^20 block cipher blocks). * \param data_unit The address of the data unit encoded as an array of 16 * bytes in little-endian format. For disk encryption, this * is typically the index of the block device sector that * contains the data. * \param input The buffer holding the input data (which is an entire * data unit). This function reads \p length Bytes from \p * input. * \param output The buffer holding the output data (which is an entire * data unit). This function writes \p length Bytes to \p * output. * * \return \c 0 on success. * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is * smaller than an AES block in size (16 Bytes) or if \p * length is larger than 2^20 blocks (16 MiB). */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an AES-CFB128 encryption or decryption * operation. * * It performs the operation defined in the \p mode * parameter (encrypt or decrypt), on the input data buffer * defined in the \p input parameter. * * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), * regardless of whether you are performing an encryption or decryption * operation, that is, regardless of the \p mode parameter. This is * because CFB mode uses the same key schedule for encryption and * decryption. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the * IV, you must either save it manually or use the cipher * module instead. * * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT. * \param length The length of the input data in Bytes. * \param iv_off The offset in IV (updated after use). * It must point to a valid \c size_t. * \param iv The initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); /** * \brief This function performs an AES-CFB8 encryption or decryption * operation. * * It performs the operation defined in the \p mode * parameter (encrypt/decrypt), on the input data buffer defined * in the \p input parameter. * * Due to the nature of CFB, you must use the same key schedule for * both encryption and decryption operations. Therefore, you must * use the context initialized with mbedtls_aes_setkey_enc() for * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * #MBEDTLS_AES_DECRYPT * \param length The length of the input data. * \param iv The initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /*MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /** * \brief This function performs an AES-OFB (Output Feedback Mode) * encryption or decryption operation. * * For OFB, you must set up the context with * mbedtls_aes_setkey_enc(), regardless of whether you are * performing an encryption or decryption operation. This is * because OFB mode uses the same key schedule for encryption and * decryption. * * The OFB operation is identical for encryption or decryption, * therefore no operation mode needs to be specified. * * \note Upon exit, the content of iv, the Initialisation Vector, is * updated so that you can call the same function again on the next * block(s) of data and get the same result as if it was encrypted * in one call. This allows a "streaming" usage, by initialising * iv_off to 0 before the first call, and preserving its value * between calls. * * For non-streaming use, the iv should be initialised on each call * to a unique value, and iv_off set to 0 on each call. * * If you need to retain the contents of the initialisation vector, * you must either save it manually or use the cipher module * instead. * * \warning For the OFB mode, the initialisation vector must be unique * every encryption operation. Reuse of an initialisation vector * will compromise security. * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param length The length of the input data. * \param iv_off The offset in IV (updated after use). * It must point to a valid \c size_t. * \param iv The initialization vector (updated after use). * It must be a readable and writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief This function performs an AES-CTR encryption or decryption * operation. * * Due to the nature of CTR, you must use the same key schedule * for both encryption and decryption operations. Therefore, you * must use the context initialized with mbedtls_aes_setkey_enc() * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with * the same nonce and key. * * There are two common strategies for managing nonces with CTR: * * 1. You can handle everything as a single message processed over * successive calls to this function. In that case, you want to * set \p nonce_counter and \p nc_off to 0 for the first call, and * then preserve the values of \p nonce_counter, \p nc_off and \p * stream_block across calls to this function as they will be * updated by this function. * * With this strategy, you must not encrypt more than 2**128 * blocks of data with the same key. * * 2. You can encrypt separate messages by dividing the \p * nonce_counter buffer in two areas: the first one used for a * per-message nonce, handled by yourself, and the second one * updated by this function internally. * * For example, you might reserve the first 12 bytes for the * per-message nonce, and the last 4 bytes for internal use. In that * case, before calling this function on a new message you need to * set the first 12 bytes of \p nonce_counter to your chosen nonce * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p * stream_block to be ignored). That way, you can encrypt at most * 2**96 messages of up to 2**32 blocks each with the same key. * * The per-message nonce (or information sufficient to reconstruct * it) needs to be communicated with the ciphertext and must be unique. * The recommended way to ensure uniqueness is to use a message * counter. An alternative is to generate random nonces, but this * limits the number of messages that can be securely encrypted: * for example, with 96-bit random nonces, you should not encrypt * more than 2**32 messages with the same key. * * Note that for both strategies, sizes are measured in blocks and * that an AES block is 16 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * * \param ctx The AES context to use for encryption or decryption. * It must be initialized and bound to a key. * \param length The length of the input data. * \param nc_off The offset in the current \p stream_block, for * resuming within the current cipher stream. The * offset pointer should be 0 at the start of a stream. * It must point to a valid \c size_t. * \param nonce_counter The 128-bit nonce and counter. * It must be a readable-writeable buffer of \c 16 Bytes. * \param stream_block The saved stream block for resuming. This is * overwritten by the function. * It must be a readable-writeable buffer of \c 16 Bytes. * \param input The buffer holding the input data. * It must be readable and of size \p length Bytes. * \param output The buffer holding the output data. * It must be writeable and of size \p length Bytes. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ /** * \brief Internal AES block encryption function. This is only * exposed to allow overriding it using * \c MBEDTLS_AES_ENCRYPT_ALT. * * \param ctx The AES context to use for encryption. * \param input The plaintext block. * \param output The output (ciphertext) block. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal AES block decryption function. This is only * exposed to allow overriding it using see * \c MBEDTLS_AES_DECRYPT_ALT. * * \param ctx The AES context to use for decryption. * \param input The ciphertext block. * \param output The output (plaintext) block. * * \return \c 0 on success. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_aes_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* aes.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/aria.h000066400000000000000000000352241464416617300240400ustar00rootroot00000000000000/** * \file aria.h * * \brief ARIA block cipher * * The ARIA algorithm is a symmetric block cipher that can encrypt and * decrypt information. It is defined by the Korean Agency for * Technology and Standards (KATS) in KS X 1213:2004 (in * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) * and also described by the IETF in RFC 5794. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ARIA_H #define MBEDTLS_ARIA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #include "mbedtls/platform_util.h" #define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ #define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ #define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ #define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */ #define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ /** Bad input data. */ #define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /** Invalid data input length. */ #define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_ARIA_ALT) // Regular implementation // /** * \brief The ARIA context-type definition. */ typedef struct mbedtls_aria_context { unsigned char MBEDTLS_PRIVATE(nr); /*!< The number of rounds (12, 14 or 16) */ /*! The ARIA round keys. */ uint32_t MBEDTLS_PRIVATE(rk)[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; } mbedtls_aria_context; #else /* MBEDTLS_ARIA_ALT */ #include "aria_alt.h" #endif /* MBEDTLS_ARIA_ALT */ /** * \brief This function initializes the specified ARIA context. * * It must be the first API called before using * the context. * * \param ctx The ARIA context to initialize. This must not be \c NULL. */ void mbedtls_aria_init(mbedtls_aria_context *ctx); /** * \brief This function releases and clears the specified ARIA context. * * \param ctx The ARIA context to clear. This may be \c NULL, in which * case this function returns immediately. If it is not \c NULL, * it must point to an initialized ARIA context. */ void mbedtls_aria_free(mbedtls_aria_context *ctx); /** * \brief This function sets the encryption key. * * \param ctx The ARIA context to which the key should be bound. * This must be initialized. * \param key The encryption key. This must be a readable buffer * of size \p keybits Bits. * \param keybits The size of \p key in Bits. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief This function sets the decryption key. * * \param ctx The ARIA context to which the key should be bound. * This must be initialized. * \param key The decryption key. This must be a readable buffer * of size \p keybits Bits. * \param keybits The size of data passed. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief This function performs an ARIA single-block encryption or * decryption operation. * * It performs encryption or decryption (depending on whether * the key was set for encryption on decryption) on the input * data buffer defined in the \p input parameter. * * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or * mbedtls_aria_setkey_dec() must be called before the first * call to this API with the same context. * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param input The 16-Byte buffer holding the input data. * \param output The 16-Byte buffer holding the output data. * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx, const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], unsigned char output[MBEDTLS_ARIA_BLOCKSIZE]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief This function performs an ARIA-CBC encryption or decryption operation * on full blocks. * * It performs the operation defined in the \p mode * parameter (encrypt/decrypt), on the input data buffer defined in * the \p input parameter. * * It can be called as many times as needed, until all the input * data is processed. mbedtls_aria_init(), and either * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called * before the first call to this API with the same context. * * \note This function operates on aligned blocks, that is, the input size * must be a multiple of the ARIA block size of 16 Bytes. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the IV, you should * either save it manually or use the cipher module instead. * * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_ARIA_ENCRYPT for encryption, or * #MBEDTLS_ARIA_DECRYPT for decryption. * \param length The length of the input data in Bytes. This must be a * multiple of the block size (16 Bytes). * \param iv Initialization vector (updated after use). * This must be a readable buffer of size 16 Bytes. * \param input The buffer holding the input data. This must * be a readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, int mode, size_t length, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an ARIA-CFB128 encryption or decryption * operation. * * It performs the operation defined in the \p mode * parameter (encrypt or decrypt), on the input data buffer * defined in the \p input parameter. * * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), * regardless of whether you are performing an encryption or decryption * operation, that is, regardless of the \p mode parameter. This is * because CFB mode uses the same key schedule for encryption and * decryption. * * \note Upon exit, the content of the IV is updated so that you can * call the same function again on the next * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If you need to retain the contents of the * IV, you must either save it manually or use the cipher * module instead. * * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_ARIA_ENCRYPT for encryption, or * #MBEDTLS_ARIA_DECRYPT for decryption. * \param length The length of the input data \p input in Bytes. * \param iv_off The offset in IV (updated after use). * This must not be larger than 15. * \param iv The initialization vector (updated after use). * This must be a readable buffer of size 16 Bytes. * \param input The buffer holding the input data. This must * be a readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief This function performs an ARIA-CTR encryption or decryption * operation. * * Due to the nature of CTR, you must use the same key schedule * for both encryption and decryption operations. Therefore, you * must use the context initialized with mbedtls_aria_setkey_enc() * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with * the same nonce and key. * * There are two common strategies for managing nonces with CTR: * * 1. You can handle everything as a single message processed over * successive calls to this function. In that case, you want to * set \p nonce_counter and \p nc_off to 0 for the first call, and * then preserve the values of \p nonce_counter, \p nc_off and \p * stream_block across calls to this function as they will be * updated by this function. * * With this strategy, you must not encrypt more than 2**128 * blocks of data with the same key. * * 2. You can encrypt separate messages by dividing the \p * nonce_counter buffer in two areas: the first one used for a * per-message nonce, handled by yourself, and the second one * updated by this function internally. * * For example, you might reserve the first 12 bytes for the * per-message nonce, and the last 4 bytes for internal use. In that * case, before calling this function on a new message you need to * set the first 12 bytes of \p nonce_counter to your chosen nonce * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p * stream_block to be ignored). That way, you can encrypt at most * 2**96 messages of up to 2**32 blocks each with the same key. * * The per-message nonce (or information sufficient to reconstruct * it) needs to be communicated with the ciphertext and must be unique. * The recommended way to ensure uniqueness is to use a message * counter. An alternative is to generate random nonces, but this * limits the number of messages that can be securely encrypted: * for example, with 96-bit random nonces, you should not encrypt * more than 2**32 messages with the same key. * * Note that for both strategies, sizes are measured in blocks and * that an ARIA block is 16 bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * * \param ctx The ARIA context to use for encryption or decryption. * This must be initialized and bound to a key. * \param length The length of the input data \p input in Bytes. * \param nc_off The offset in Bytes in the current \p stream_block, * for resuming within the current cipher stream. The * offset pointer should be \c 0 at the start of a * stream. This must not be larger than \c 15 Bytes. * \param nonce_counter The 128-bit nonce and counter. This must point to * a read/write buffer of length \c 16 bytes. * \param stream_block The saved stream block for resuming. This must * point to a read/write buffer of length \c 16 bytes. * This is overwritten by the function. * \param input The buffer holding the input data. This must * be a readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must * be a writable buffer of length \p length Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine. * * \return \c 0 on success, or \c 1 on failure. */ int mbedtls_aria_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* aria.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h000066400000000000000000000652541464416617300237740ustar00rootroot00000000000000/** * \file asn1.h * * \brief Generic ASN.1 parsing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ASN1_H #define MBEDTLS_ASN1_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /** * \addtogroup asn1_module * \{ */ /** * \name ASN1 Error codes * These error codes are combined with other error codes for * higher error granularity. * e.g. X.509 and PKCS #7 error codes * ASN1 is a standard to specify data structures. * \{ */ /** Out of data when parsing an ASN1 data structure. */ #define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /** ASN1 tag was of an unexpected value. */ #define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /** Error when trying to determine the length or invalid length. */ #define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /** Actual length differs from expected length. */ #define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /** Data is invalid. */ #define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /** Memory allocation failed */ #define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /** Buffer too small when writing ASN.1 data structure. */ #define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /** \} name ASN1 Error codes */ /** * \name DER constants * These constants comply with the DER encoded ASN.1 type tags. * DER encoding uses hexadecimal representation. * An example DER sequence is:\n * - 0x02 -- tag indicating INTEGER * - 0x01 -- length in octets * - 0x05 -- value * Such sequences are typically read into \c ::mbedtls_x509_buf. * \{ */ #define MBEDTLS_ASN1_BOOLEAN 0x01 #define MBEDTLS_ASN1_INTEGER 0x02 #define MBEDTLS_ASN1_BIT_STRING 0x03 #define MBEDTLS_ASN1_OCTET_STRING 0x04 #define MBEDTLS_ASN1_NULL 0x05 #define MBEDTLS_ASN1_OID 0x06 #define MBEDTLS_ASN1_ENUMERATED 0x0A #define MBEDTLS_ASN1_UTF8_STRING 0x0C #define MBEDTLS_ASN1_SEQUENCE 0x10 #define MBEDTLS_ASN1_SET 0x11 #define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 #define MBEDTLS_ASN1_T61_STRING 0x14 #define MBEDTLS_ASN1_IA5_STRING 0x16 #define MBEDTLS_ASN1_UTC_TIME 0x17 #define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 #define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C #define MBEDTLS_ASN1_BMP_STRING 0x1E #define MBEDTLS_ASN1_PRIMITIVE 0x00 #define MBEDTLS_ASN1_CONSTRUCTED 0x20 #define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 /* Slightly smaller way to check if tag is a string tag * compared to canonical implementation. */ #define MBEDTLS_ASN1_IS_STRING_TAG(tag) \ ((unsigned int) (tag) < 32u && ( \ ((1u << (tag)) & ((1u << MBEDTLS_ASN1_BMP_STRING) | \ (1u << MBEDTLS_ASN1_UTF8_STRING) | \ (1u << MBEDTLS_ASN1_T61_STRING) | \ (1u << MBEDTLS_ASN1_IA5_STRING) | \ (1u << MBEDTLS_ASN1_UNIVERSAL_STRING) | \ (1u << MBEDTLS_ASN1_PRINTABLE_STRING))) != 0)) /* * Bit masks for each of the components of an ASN.1 tag as specified in * ITU X.690 (08/2015), section 8.1 "General rules for encoding", * paragraph 8.1.2.2: * * Bit 8 7 6 5 1 * +-------+-----+------------+ * | Class | P/C | Tag number | * +-------+-----+------------+ */ #define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 #define MBEDTLS_ASN1_TAG_PC_MASK 0x20 #define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F /** \} name DER constants */ /** Returns the size of the binary string, without the trailing \\0 */ #define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) /** * Compares an mbedtls_asn1_buf structure to a reference OID. * * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a * 'unsigned char *oid' here! */ #define MBEDTLS_OID_CMP(oid_str, oid_buf) \ ((MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len) || \ memcmp((oid_str), (oid_buf)->p, (oid_buf)->len) != 0) #define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ ((MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len)) || \ memcmp((oid_str), (oid_buf), (oid_buf_len)) != 0) #ifdef __cplusplus extern "C" { #endif /** * \name Functions to parse ASN.1 data structures * \{ */ /** * Type-length-value structure that allows for ASN1 using DER. */ typedef struct mbedtls_asn1_buf { int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ size_t len; /**< ASN1 length, in octets. */ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ } mbedtls_asn1_buf; /** * Container for ASN1 bit strings. */ typedef struct mbedtls_asn1_bitstring { size_t len; /**< ASN1 length, in octets. */ unsigned char unused_bits; /**< Number of unused bits at the end of the string */ unsigned char *p; /**< Raw ASN1 data for the bit string */ } mbedtls_asn1_bitstring; /** * Container for a sequence of ASN.1 items */ typedef struct mbedtls_asn1_sequence { mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ /** The next entry in the sequence. * * The details of memory management for sequences are not documented and * may change in future versions. Set this field to \p NULL when * initializing a structure, and do not modify it except via Mbed TLS * library functions. */ struct mbedtls_asn1_sequence *next; } mbedtls_asn1_sequence; /** * Container for a sequence or list of 'named' ASN.1 data items */ typedef struct mbedtls_asn1_named_data { mbedtls_asn1_buf oid; /**< The object identifier. */ mbedtls_asn1_buf val; /**< The named value. */ /** The next entry in the sequence. * * The details of memory management for named data sequences are not * documented and may change in future versions. Set this field to \p NULL * when initializing a structure, and do not modify it except via Mbed TLS * library functions. */ struct mbedtls_asn1_named_data *next; /** Merge next item into the current one? * * This field exists for the sake of Mbed TLS's X.509 certificate parsing * code and may change in future versions of the library. */ unsigned char MBEDTLS_PRIVATE(next_merged); } mbedtls_asn1_named_data; #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Get the length of an ASN.1 element. * Updates the pointer to immediately behind the length. * * \param p On entry, \c *p points to the first byte of the length, * i.e. immediately after the tag. * On successful completion, \c *p points to the first byte * after the length, i.e. the first byte of the content. * On error, the value of \c *p is undefined. * \param end End of data. * \param len On successful completion, \c *len contains the length * read from the ASN.1 input. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element * would end beyond \p end. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. */ int mbedtls_asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len); /** * \brief Get the tag and length of the element. * Check for the requested tag. * Updates the pointer to immediately behind the tag and length. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * after the length, i.e. the first byte of the content. * On error, the value of \c *p is undefined. * \param end End of data. * \param len On successful completion, \c *len contains the length * read from the ASN.1 input. * \param tag The expected tag. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start * with the requested tag. * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element * would end beyond \p end. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable. */ int mbedtls_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag); #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_PARSE_C) /** * \brief Retrieve a boolean ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param val On success, the parsed value (\c 0 or \c 1). * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BOOLEAN. */ int mbedtls_asn1_get_bool(unsigned char **p, const unsigned char *end, int *val); /** * \brief Retrieve an integer ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param val On success, the parsed value. * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 INTEGER. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does * not fit in an \c int. */ int mbedtls_asn1_get_int(unsigned char **p, const unsigned char *end, int *val); /** * \brief Retrieve an enumerated ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param val On success, the parsed value. * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 ENUMERATED. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does * not fit in an \c int. */ int mbedtls_asn1_get_enum(unsigned char **p, const unsigned char *end, int *val); /** * \brief Retrieve a bitstring ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p is equal to \p end. * On error, the value of \c *p is undefined. * \param end End of data. * \param bs On success, ::mbedtls_asn1_bitstring information about * the parsed value. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains * extra data after a valid BIT STRING. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BIT STRING. */ int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, mbedtls_asn1_bitstring *bs); /** * \brief Retrieve a bitstring ASN.1 tag without unused bits and its * value. * Updates the pointer to the beginning of the bit/octet string. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * of the content of the BIT STRING. * On error, the value of \c *p is undefined. * \param end End of data. * \param len On success, \c *len is the length of the content in bytes. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with * a valid BIT STRING with a nonzero number of unused bits. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 BIT STRING. */ int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, size_t *len); /** * \brief Parses and splits an ASN.1 "SEQUENCE OF ". * Updates the pointer to immediately behind the full sequence tag. * * This function allocates memory for the sequence elements. You can free * the allocated memory with mbedtls_asn1_sequence_free(). * * \note On error, this function may return a partial list in \p cur. * You must set `cur->next = NULL` before calling this function! * Otherwise it is impossible to distinguish a previously non-null * pointer from a pointer to an object allocated by this function. * * \note If the sequence is empty, this function does not modify * \c *cur. If the sequence is valid and non-empty, this * function sets `cur->buf.tag` to \p tag. This allows * callers to distinguish between an empty sequence and * a one-element sequence. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p is equal to \p end. * On error, the value of \c *p is undefined. * \param end End of data. * \param cur A ::mbedtls_asn1_sequence which this function fills. * When this function returns, \c *cur is the head of a linked * list. Each node in this list is allocated with * mbedtls_calloc() apart from \p cur itself, and should * therefore be freed with mbedtls_free(). * The list describes the content of the sequence. * The head of the list (i.e. \c *cur itself) describes the * first element, `*cur->next` describes the second element, etc. * For each element, `buf.tag == tag`, `buf.len` is the length * of the content of the content of the element, and `buf.p` * points to the first byte of the content (i.e. immediately * past the length of the element). * Note that list elements may be allocated even on error. * \param tag Each element of the sequence must have this tag. * * \return 0 if successful. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains * extra data after a valid SEQUENCE OF \p tag. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with * an ASN.1 SEQUENCE in which an element has a tag that * is different from \p tag. * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 SEQUENCE. */ int mbedtls_asn1_get_sequence_of(unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag); /** * \brief Free a heap-allocated linked list presentation of * an ASN.1 sequence, including the first element. * * There are two common ways to manage the memory used for the representation * of a parsed ASN.1 sequence: * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). * When you have finished processing the sequence, * call mbedtls_asn1_sequence_free() on `head`. * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, * for example on the stack. Make sure that `head->next == NULL`. * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). * When you have finished processing the sequence, * call mbedtls_asn1_sequence_free() on `head->cur`, * then free `head` itself in the appropriate manner. * * \param seq The address of the first sequence component. This may * be \c NULL, in which case this functions returns * immediately. */ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq); /** * \brief Traverse an ASN.1 SEQUENCE container and * call a callback for each entry. * * This function checks that the input is a SEQUENCE of elements that * each have a "must" tag, and calls a callback function on the elements * that have a "may" tag. * * For example, to validate that the input is a SEQUENCE of `tag1` and call * `cb` on each element, use * ``` * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); * ``` * * To validate that the input is a SEQUENCE of ANY and call `cb` on * each element, use * ``` * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); * ``` * * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} * and call `cb` on each element that is an OCTET STRING, use * ``` * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); * ``` * * The callback is called on the elements with a "may" tag from left to * right. If the input is not a valid SEQUENCE of elements with a "must" tag, * the callback is called on the elements up to the leftmost point where * the input is invalid. * * \warning This function is still experimental and may change * at any time. * * \param p The address of the pointer to the beginning of * the ASN.1 SEQUENCE header. This is updated to * point to the end of the ASN.1 SEQUENCE container * on a successful invocation. * \param end The end of the ASN.1 SEQUENCE container. * \param tag_must_mask A mask to be applied to the ASN.1 tags found within * the SEQUENCE before comparing to \p tag_must_val. * \param tag_must_val The required value of each ASN.1 tag found in the * SEQUENCE, after masking with \p tag_must_mask. * Mismatching tags lead to an error. * For example, a value of \c 0 for both \p tag_must_mask * and \p tag_must_val means that every tag is allowed, * while a value of \c 0xFF for \p tag_must_mask means * that \p tag_must_val is the only allowed tag. * \param tag_may_mask A mask to be applied to the ASN.1 tags found within * the SEQUENCE before comparing to \p tag_may_val. * \param tag_may_val The desired value of each ASN.1 tag found in the * SEQUENCE, after masking with \p tag_may_mask. * Mismatching tags will be silently ignored. * For example, a value of \c 0 for \p tag_may_mask and * \p tag_may_val means that any tag will be considered, * while a value of \c 0xFF for \p tag_may_mask means * that all tags with value different from \p tag_may_val * will be ignored. * \param cb The callback to trigger for each component * in the ASN.1 SEQUENCE that matches \p tag_may_val. * The callback function is called with the following * parameters: * - \p ctx. * - The tag of the current element. * - A pointer to the start of the current element's * content inside the input. * - The length of the content of the current element. * If the callback returns a non-zero value, * the function stops immediately, * forwarding the callback's return value. * \param ctx The context to be passed to the callback \p cb. * * \return \c 0 if successful the entire ASN.1 SEQUENCE * was traversed without parsing or callback errors. * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input * contains extra data after a valid SEQUENCE * of elements with an accepted tag. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts * with an ASN.1 SEQUENCE in which an element has a tag * that is not accepted. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 SEQUENCE. * \return A non-zero error code forwarded from the callback * \p cb in case the latter returns a non-zero value. */ int mbedtls_asn1_traverse_sequence_of( unsigned char **p, const unsigned char *end, unsigned char tag_must_mask, unsigned char tag_must_val, unsigned char tag_may_mask, unsigned char tag_may_val, int (*cb)(void *ctx, int tag, unsigned char *start, size_t len), void *ctx); #if defined(MBEDTLS_BIGNUM_C) /** * \brief Retrieve an integer ASN.1 tag and its value. * Updates the pointer to immediately behind the full tag. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the ASN.1 element. * On error, the value of \c *p is undefined. * \param end End of data. * \param X On success, the parsed value. * * \return 0 if successful. * \return An ASN.1 error code if the input does not start with * a valid ASN.1 INTEGER. * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does * not fit in an \c int. * \return An MPI error code if the parsed value is too large. */ int mbedtls_asn1_get_mpi(unsigned char **p, const unsigned char *end, mbedtls_mpi *X); #endif /* MBEDTLS_BIGNUM_C */ /** * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. * Updates the pointer to immediately behind the full * AlgorithmIdentifier. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the AlgorithmIdentifier element. * On error, the value of \c *p is undefined. * \param end End of data. * \param alg The buffer to receive the OID. * \param params The buffer to receive the parameters. * This is zeroized if there are no parameters. * * \return 0 if successful or a specific ASN.1 or MPI error code. */ int mbedtls_asn1_get_alg(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params); /** * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no * params. * Updates the pointer to immediately behind the full * AlgorithmIdentifier. * * \param p On entry, \c *p points to the start of the ASN.1 element. * On successful completion, \c *p points to the first byte * beyond the AlgorithmIdentifier element. * On error, the value of \c *p is undefined. * \param end End of data. * \param alg The buffer to receive the OID. * * \return 0 if successful or a specific ASN.1 or MPI error code. */ int mbedtls_asn1_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg); /** * \brief Find a specific named_data entry in a sequence or list based on * the OID. * * \param list The list to seek through * \param oid The OID to look for * \param len Size of the OID * * \return NULL if not found, or a pointer to the existing entry. */ const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, const char *oid, size_t len); #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Free a mbedtls_asn1_named_data entry * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use mbedtls_asn1_free_named_data_list() * or mbedtls_asn1_free_named_data_list_shallow(). * * \param entry The named data entry to free. * This function calls mbedtls_free() on * `entry->oid.p` and `entry->val.p`. */ void MBEDTLS_DEPRECATED mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Free all entries in a mbedtls_asn1_named_data list. * * \param head Pointer to the head of the list of named data entries to free. * This function calls mbedtls_free() on * `entry->oid.p` and `entry->val.p` and then on `entry` * for each list entry, and sets \c *head to \c NULL. */ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head); /** * \brief Free all shallow entries in a mbedtls_asn1_named_data list, * but do not free internal pointer targets. * * \param name Head of the list of named data entries to free. * This function calls mbedtls_free() on each list element. */ void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name); /** \} name Functions to parse ASN.1 data structures */ /** \} addtogroup asn1_module */ #endif /* MBEDTLS_ASN1_PARSE_C */ #ifdef __cplusplus } #endif #endif /* asn1.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h000066400000000000000000000402541464416617300250400ustar00rootroot00000000000000/** * \file asn1write.h * * \brief ASN.1 buffer writing functionality */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #define MBEDTLS_ASN1_CHK_ADD(g, f) \ do \ { \ if ((ret = (f)) < 0) \ return ret; \ else \ (g) += ret; \ } while (0) #define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f) \ do \ { \ if ((ret = (f)) < 0) \ goto cleanup; \ else \ (g) += ret; \ } while (0) #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Write a length field in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param len The length value to write. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len); /** * \brief Write an ASN.1 tag in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param tag The tag to write. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag); #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA*/ #if defined(MBEDTLS_ASN1_WRITE_C) /** * \brief Write raw buffer data. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param buf The data buffer to write. * \param size The length of the data buffer. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); #if defined(MBEDTLS_BIGNUM_C) /** * \brief Write an arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param X The MPI to write. * It must be non-negative. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X); #endif /* MBEDTLS_BIGNUM_C */ /** * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start); /** * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param oid The OID to write. * \param oid_len The length of the OID. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len); /** * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param oid The OID of the algorithm to write. * \param oid_len The length of the algorithm's OID. * \param par_len The length of the parameters, which must be already written. * If 0, NULL parameters are added * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len); /** * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param oid The OID of the algorithm to write. * \param oid_len The length of the algorithm's OID. * \param par_len The length of the parameters, which must be already written. * \param has_par If there are any parameters. If 0, par_len must be 0. If 1 * and \p par_len is 0, NULL parameters are added. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len, int has_par); /** * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param boolean The boolean value to write, either \c 0 or \c 1. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean); /** * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param val The integer value to write. * It must be non-negative. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val); /** * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value * in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param val The integer value to write. * * \return The number of bytes written to \p p on success. * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val); /** * \brief Write a string in ASN.1 format using a specific * string encoding tag. * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param tag The string encoding tag to write, e.g. * #MBEDTLS_ASN1_UTF8_STRING. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len); /** * \brief Write a string in ASN.1 format using the PrintableString * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** * \brief Write a UTF8 string in ASN.1 format using the UTF8String * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING). * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** * \brief Write a string in ASN.1 format using the IA5String * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param text The string to write. * \param text_len The length of \p text in bytes (which might * be strictly larger than the number of characters). * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len); /** * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and * value in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param buf The bitstring to write. * \param bits The total number of bits in the bitstring. * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); /** * \brief This function writes a named bitstring tag * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format. * * As stated in RFC 5280 Appendix B, trailing zeroes are * omitted when encoding named bitstrings in DER. * * \note This function works backwards within the data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer which is used for bounds-checking. * \param buf The bitstring to write. * \param bits The total number of bits in the bitstring. * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_named_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits); /** * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) * and value in ASN.1 format. * * \note This function works backwards in data buffer. * * \param p The reference to the current position pointer. * \param start The start of the buffer, for bounds-checking. * \param buf The buffer holding the data to write. * \param size The length of the data buffer \p buf. * * \return The number of bytes written to \p p on success. * \return A negative error code on failure. */ int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size); /** * \brief Create or find a specific named_data entry for writing in a * sequence or list based on the OID. If not already in there, * a new entry is added to the head of the list. * Warning: Destructive behaviour for the val data! * * \param list The pointer to the location of the head of the list to seek * through (will be updated in case of a new entry). * \param oid The OID to look for. * \param oid_len The size of the OID. * \param val The associated data to store. If this is \c NULL, * no data is copied to the new or existing buffer. * \param val_len The minimum length of the data buffer needed. * If this is 0, do not allocate a buffer for the associated * data. * If the OID was already present, enlarge, shrink or free * the existing buffer to fit \p val_len. * * \return A pointer to the new / existing entry on success. * \return \c NULL if there was a memory allocation error. */ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **list, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len); #ifdef __cplusplus } #endif #endif /* MBEDTLS_ASN1_WRITE_C */ #endif /* MBEDTLS_ASN1_WRITE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/base64.h000066400000000000000000000050651464416617300242100ustar00rootroot00000000000000/** * \file base64.h * * \brief RFC 1521 base64 encoding/decoding */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H #include "mbedtls/build_info.h" #include /** Output buffer too small. */ #define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /** Invalid character in input. */ #define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C #ifdef __cplusplus extern "C" { #endif /** * \brief Encode a buffer into base64 format * * \param dst destination buffer * \param dlen size of the destination buffer * \param olen number of bytes written * \param src source buffer * \param slen amount of data to be encoded * * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. * *olen is always updated to reflect the amount * of data that has (or would have) been written. * If that length cannot be represented, then no data is * written to the buffer and *olen is set to the maximum * length representable as a size_t. * * \note Call this function with dlen = 0 to obtain the * required buffer size in *olen */ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); /** * \brief Decode a base64-formatted buffer * * \param dst destination buffer (can be NULL for checking size) * \param dlen size of the destination buffer * \param olen number of bytes written * \param src source buffer * \param slen amount of data to be decoded * * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is * not correct. *olen is always updated to reflect the amount * of data that has (or would have) been written. * * \note Call this function with *dst = NULL or dlen = 0 to obtain * the required buffer size in *olen */ int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_base64_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* base64.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h000066400000000000000000001331611464416617300244040ustar00rootroot00000000000000/** * \file bignum.h * * \brief Multi-precision integer library */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_H #define MBEDTLS_BIGNUM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #if defined(MBEDTLS_FS_IO) #include #endif /** An error occurred while reading from or writing to a file. */ #define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /** Bad input parameters to function. */ #define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /** There is an invalid character in the digit string. */ #define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /** The buffer is too small to write to. */ #define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /** The input arguments are negative or result in illegal output. */ #define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /** The input argument for division is zero, which is not allowed. */ #define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /** The input arguments are not acceptable. */ #define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /** Memory allocation failed. */ #define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 #define MBEDTLS_MPI_CHK(f) \ do \ { \ if ((ret = (f)) != 0) \ goto cleanup; \ } while (0) /* * Maximum size MPIs are allowed to grow to in number of limbs. */ #define MBEDTLS_MPI_MAX_LIMBS 10000 #if !defined(MBEDTLS_MPI_WINDOW_SIZE) /* * Maximum window size used for modular exponentiation. Default: 3 * Minimum value: 1. Maximum value: 6. * * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used * for the sliding window calculation. (So 8 by default) * * Reduction in size, reduces speed. */ #define MBEDTLS_MPI_WINDOW_SIZE 3 /**< Maximum window size used. */ #endif /* !MBEDTLS_MPI_WINDOW_SIZE */ #if !defined(MBEDTLS_MPI_MAX_SIZE) /* * Maximum size of MPIs allowed in bits and bytes for user-MPIs. * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) * * Note: Calculations can temporarily result in larger MPIs. So the number * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. */ #define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ #endif /* !MBEDTLS_MPI_MAX_SIZE */ #define MBEDTLS_MPI_MAX_BITS (8 * MBEDTLS_MPI_MAX_SIZE) /**< Maximum number of bits for usable MPIs. */ /* * When reading from files with mbedtls_mpi_read_file() and writing to files with * mbedtls_mpi_write_file() the buffer should have space * for a (short) label, the MPI (in the provided radix), the newline * characters and the '\0'. * * By default we assume at least a 10 char label, a minimum radix of 10 * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). * Autosized at compile time for at least a 10 char label, a minimum radix * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. * * This used to be statically sized to 1250 for a maximum of 4096 bit * numbers (1234 decimal chars). * * Calculate using the formula: * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + * LabelSize + 6 */ #define MBEDTLS_MPI_MAX_BITS_SCALE100 (100 * MBEDTLS_MPI_MAX_BITS) #define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 #define MBEDTLS_MPI_RW_BUFFER_SIZE (((MBEDTLS_MPI_MAX_BITS_SCALE100 + \ MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / \ MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6) /* * Define the base integer type, architecture-wise. * * 32 or 64-bit integer types can be forced regardless of the underlying * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 * respectively and undefining MBEDTLS_HAVE_ASM. * * Double-width integers (e.g. 128-bit in 64-bit architectures) can be * disabled by defining MBEDTLS_NO_UDBL_DIVISION. */ #if !defined(MBEDTLS_HAVE_INT32) #if defined(_MSC_VER) && defined(_M_AMD64) /* Always choose 64-bit when using MSC */ #if !defined(MBEDTLS_HAVE_INT64) #define MBEDTLS_HAVE_INT64 #endif /* !MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #elif defined(__GNUC__) && ( \ defined(__amd64__) || defined(__x86_64__) || \ defined(__ppc64__) || defined(__powerpc64__) || \ defined(__ia64__) || defined(__alpha__) || \ (defined(__sparc__) && defined(__arch64__)) || \ defined(__s390x__) || defined(__mips64) || \ defined(__aarch64__)) #if !defined(MBEDTLS_HAVE_INT64) #define MBEDTLS_HAVE_INT64 #endif /* MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) /* mbedtls_t_udbl defined as 128-bit unsigned int */ typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #elif defined(__ARMCC_VERSION) && defined(__aarch64__) /* * __ARMCC_VERSION is defined for both armcc and armclang and * __aarch64__ is only defined by armclang when compiling 64-bit code */ #if !defined(MBEDTLS_HAVE_INT64) #define MBEDTLS_HAVE_INT64 #endif /* !MBEDTLS_HAVE_INT64 */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) /* mbedtls_t_udbl defined as 128-bit unsigned int */ typedef __uint128_t mbedtls_t_udbl; #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #elif defined(MBEDTLS_HAVE_INT64) /* Force 64-bit integers with unknown compiler */ typedef int64_t mbedtls_mpi_sint; typedef uint64_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT64_MAX #endif #endif /* !MBEDTLS_HAVE_INT32 */ #if !defined(MBEDTLS_HAVE_INT64) /* Default to 32-bit compilation */ #if !defined(MBEDTLS_HAVE_INT32) #define MBEDTLS_HAVE_INT32 #endif /* !MBEDTLS_HAVE_INT32 */ typedef int32_t mbedtls_mpi_sint; typedef uint32_t mbedtls_mpi_uint; #define MBEDTLS_MPI_UINT_MAX UINT32_MAX #if !defined(MBEDTLS_NO_UDBL_DIVISION) typedef uint64_t mbedtls_t_udbl; #define MBEDTLS_HAVE_UDBL #endif /* !MBEDTLS_NO_UDBL_DIVISION */ #endif /* !MBEDTLS_HAVE_INT64 */ /* * Sanity check that exactly one of MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 is defined, * so that code elsewhere doesn't have to check. */ #if (!(defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64))) || \ (defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64)) #error "Only 32-bit or 64-bit limbs are supported in bignum" #endif /** \typedef mbedtls_mpi_uint * \brief The type of machine digits in a bignum, called _limbs_. * * This is always an unsigned integer type with no padding bits. The size * is platform-dependent. */ /** \typedef mbedtls_mpi_sint * \brief The signed type corresponding to #mbedtls_mpi_uint. * * This is always an signed integer type with no padding bits. The size * is platform-dependent. */ #ifdef __cplusplus extern "C" { #endif /** * \brief MPI structure */ typedef struct mbedtls_mpi { /** Pointer to limbs. * * This may be \c NULL if \c n is 0. */ mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); /** Sign: -1 if the mpi is negative, 1 otherwise. * * The number 0 must be represented with `s = +1`. Although many library * functions treat all-limbs-zero as equivalent to a valid representation * of 0 regardless of the sign bit, there are exceptions, so bignum * functions and external callers must always set \c s to +1 for the * number zero. * * Note that this implies that calloc() or `... = {0}` does not create * a valid MPI representation. You must call mbedtls_mpi_init(). */ signed short MBEDTLS_PRIVATE(s); /** Total number of limbs in \c p. */ unsigned short MBEDTLS_PRIVATE(n); /* Make sure that MBEDTLS_MPI_MAX_LIMBS fits in n. * Use the same limit value on all platforms so that we don't have to * think about different behavior on the rare platforms where * unsigned short can store values larger than the minimum required by * the C language, which is 65535. */ #if MBEDTLS_MPI_MAX_LIMBS > 65535 #error "MBEDTLS_MPI_MAX_LIMBS > 65535 is not supported" #endif short use_mempool; } mbedtls_mpi; extern void *mbedtls_mpi_mempool; /** * \brief Initialize an MPI context. * * This makes the MPI ready to be set or freed, * but does not define a value for the MPI. * * \param X The MPI context to initialize. This must not be \c NULL. */ void mbedtls_mpi_init(mbedtls_mpi *X); void mbedtls_mpi_init_mempool(mbedtls_mpi *X); /** * \brief This function frees the components of an MPI context. * * \param X The MPI context to be cleared. This may be \c NULL, * in which case this function is a no-op. If it is * not \c NULL, it must point to an initialized MPI. */ void mbedtls_mpi_free(mbedtls_mpi *X); /** * \brief Enlarge an MPI to the specified number of limbs. * * \note This function does nothing if the MPI is * already large enough. * * \param X The MPI to grow. It must be initialized. * \param nblimbs The target number of limbs. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs); /** * \brief This function resizes an MPI downwards, keeping at least the * specified number of limbs. * * If \c X is smaller than \c nblimbs, it is resized up * instead. * * \param X The MPI to shrink. This must point to an initialized MPI. * \param nblimbs The minimum number of limbs to keep. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed * (this can only happen when resizing up). * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs); /** * \brief Make a copy of an MPI. * * \param X The destination MPI. This must point to an initialized MPI. * \param Y The source MPI. This must point to an initialized MPI. * * \note The limb-buffer in the destination MPI is enlarged * if necessary to hold the value in the source MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Swap the contents of two MPIs. * * \param X The first MPI. It must be initialized. * \param Y The second MPI. It must be initialized. */ void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y); /** * \brief Perform a safe conditional copy of MPI which doesn't * reveal whether the condition was true or not. * * \param X The MPI to conditionally assign to. This must point * to an initialized MPI. * \param Y The MPI to be assigned from. This must point to an * initialized MPI. * \param assign The condition deciding whether to perform the * assignment or not. Must be either 0 or 1: * * \c 1: Perform the assignment `X = Y`. * * \c 0: Keep the original value of \p X. * * \note This function is equivalent to * `if( assign ) mbedtls_mpi_copy( X, Y );` * except that it avoids leaking any information about whether * the assignment was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). * * \warning If \p assign is neither 0 nor 1, the result of this function * is indeterminate, and the resulting value in \p X might be * neither its original value nor the value in \p Y. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign); /** * \brief Perform a safe conditional swap which doesn't * reveal whether the condition was true or not. * * \param X The first MPI. This must be initialized. * \param Y The second MPI. This must be initialized. * \param swap The condition deciding whether to perform * the swap or not. Must be either 0 or 1: * * \c 1: Swap the values of \p X and \p Y. * * \c 0: Keep the original values of \p X and \p Y. * * \note This function is equivalent to * if( swap ) mbedtls_mpi_swap( X, Y ); * except that it avoids leaking any information about whether * the swap was done or not (the above code may leak * information through branch prediction and/or memory access * patterns analysis). * * \warning If \p swap is neither 0 nor 1, the result of this function * is indeterminate, and both \p X and \p Y might end up with * values different to either of the original ones. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. * */ int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap); /** * \brief Store integer value in MPI. * * \param X The MPI to set. This must be initialized. * \param z The value to use. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z); /** * \brief Get a specific bit from an MPI. * * \param X The MPI to query. This must be initialized. * \param pos Zero-based index of the bit to query. * * \return \c 0 or \c 1 on success, depending on whether bit \c pos * of \c X is unset or set. * \return A negative error code on failure. */ int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos); /** * \brief Modify a specific bit in an MPI. * * \note This function will grow the target MPI if necessary to set a * bit to \c 1 in a not yet existing limb. It will not grow if * the bit should be set to \c 0. * * \param X The MPI to modify. This must be initialized. * \param pos Zero-based index of the bit to modify. * \param val The desired value of bit \c pos: \c 0 or \c 1. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val); /** * \brief Return the number of bits of value \c 0 before the * least significant bit of value \c 1. * * \note This is the same as the zero-based index of * the least significant bit of value \c 1. * * \param X The MPI to query. * * \return The number of bits of value \c 0 before the least significant * bit of value \c 1 in \p X. */ size_t mbedtls_mpi_lsb(const mbedtls_mpi *X); /** * \brief Return the number of bits up to and including the most * significant bit of value \c 1. * * * \note This is same as the one-based index of the most * significant bit of value \c 1. * * \param X The MPI to query. This must point to an initialized MPI. * * \return The number of bits up to and including the most * significant bit of value \c 1. */ size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X); /** * \brief Return the total size of an MPI value in bytes. * * \param X The MPI to use. This must point to an initialized MPI. * * \note The value returned by this function may be less than * the number of bytes used to store \p X internally. * This happens if and only if there are trailing bytes * of value zero. * * \return The least number of bytes capable of storing * the absolute value of \p X. */ size_t mbedtls_mpi_size(const mbedtls_mpi *X); /** * \brief Import an MPI from an ASCII string. * * \param X The destination MPI. This must point to an initialized MPI. * \param radix The numeric base of the input string. * \param s Null-terminated string buffer. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s); /** * \brief Export an MPI to an ASCII string. * * \param X The source MPI. This must point to an initialized MPI. * \param radix The numeric base of the output string. * \param buf The buffer to write the string to. This must be writable * buffer of length \p buflen Bytes. * \param buflen The available size in Bytes of \p buf. * \param olen The address at which to store the length of the string * written, including the final \c NULL byte. This must * not be \c NULL. * * \note You can call this function with `buflen == 0` to obtain the * minimum required buffer size in `*olen`. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf * is too small to hold the value of \p X in the desired base. * In this case, `*olen` is nonetheless updated to contain the * size of \p buf required for a successful call. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen); #if defined(MBEDTLS_FS_IO) /** * \brief Read an MPI from a line in an opened file. * * \param X The destination MPI. This must point to an initialized MPI. * \param radix The numeric base of the string representation used * in the source line. * \param fin The input file handle to use. This must not be \c NULL. * * \note On success, this function advances the file stream * to the end of the current line or to EOF. * * The function returns \c 0 on an empty line. * * Leading whitespaces are ignored, as is a * '0x' prefix for radix \c 16. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer * is too small. * \return Another negative error code on failure. */ int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin); /** * \brief Export an MPI into an opened file. * * \param p A string prefix to emit prior to the MPI data. * For example, this might be a label, or "0x" when * printing in base \c 16. This may be \c NULL if no prefix * is needed. * \param X The source MPI. This must point to an initialized MPI. * \param radix The numeric base to be used in the emitted string. * \param fout The output file handle. This may be \c NULL, in which case * the output is written to \c stdout. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout); #endif /* MBEDTLS_FS_IO */ /** * \brief Import an MPI from unsigned big endian binary data. * * \param X The destination MPI. This must point to an initialized MPI. * \param buf The input buffer. This must be a readable buffer of length * \p buflen Bytes. * \param buflen The length of the input buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); /** * \brief Import X from unsigned binary data, little endian * * \param X The destination MPI. This must point to an initialized MPI. * \param buf The input buffer. This must be a readable buffer of length * \p buflen Bytes. * \param buflen The length of the input buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, const unsigned char *buf, size_t buflen); /** * \brief Export X into unsigned binary data, big endian. * Always fills the whole buffer, which will start with zeros * if the number is smaller. * * \param X The source MPI. This must point to an initialized MPI. * \param buf The output buffer. This must be a writable buffer of length * \p buflen Bytes. * \param buflen The size of the output buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't * large enough to hold the value of \p X. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); /** * \brief Export X into unsigned binary data, little endian. * Always fills the whole buffer, which will end with zeros * if the number is smaller. * * \param X The source MPI. This must point to an initialized MPI. * \param buf The output buffer. This must be a writable buffer of length * \p buflen Bytes. * \param buflen The size of the output buffer \p buf in Bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't * large enough to hold the value of \p X. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, unsigned char *buf, size_t buflen); /** * \brief Perform a left-shift on an MPI: X <<= count * * \param X The MPI to shift. This must point to an initialized MPI. * The MPI pointed by \p X may be resized to fit * the resulting number. * \param count The number of bits to shift by. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count); /** * \brief Perform a right-shift on an MPI: X >>= count * * \param X The MPI to shift. This must point to an initialized MPI. * \param count The number of bits to shift by. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count); /** * \brief Compare the absolute values of two MPIs. * * \param X The left-hand MPI. This must point to an initialized MPI. * \param Y The right-hand MPI. This must point to an initialized MPI. * * \return \c 1 if `|X|` is greater than `|Y|`. * \return \c -1 if `|X|` is lesser than `|Y|`. * \return \c 0 if `|X|` is equal to `|Y|`. */ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Compare two MPIs. * * \param X The left-hand MPI. This must point to an initialized MPI. * \param Y The right-hand MPI. This must point to an initialized MPI. * * \return \c 1 if \p X is greater than \p Y. * \return \c -1 if \p X is lesser than \p Y. * \return \c 0 if \p X is equal to \p Y. */ int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y); /** * \brief Check if an MPI is less than the other in constant time. * * \param X The left-hand MPI. This must point to an initialized MPI * with the same allocated length as Y. * \param Y The right-hand MPI. This must point to an initialized MPI * with the same allocated length as X. * \param ret The result of the comparison: * \c 1 if \p X is less than \p Y. * \c 0 if \p X is greater than or equal to \p Y. * * \return 0 on success. * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of * the two input MPIs is not the same. */ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned *ret); /** * \brief Compare an MPI with an integer. * * \param X The left-hand MPI. This must point to an initialized MPI. * \param z The integer value to compare \p X to. * * \return \c 1 if \p X is greater than \p z. * \return \c -1 if \p X is lesser than \p z. * \return \c 0 if \p X is equal to \p z. */ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z); /** * \brief Perform an unsigned addition of MPIs: X = |A| + |B| * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first summand. This must point to an initialized MPI. * \param B The second summand. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| * * \param X The destination MPI. This must point to an initialized MPI. * \param A The minuend. This must point to an initialized MPI. * \param B The subtrahend. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a signed addition of MPIs: X = A + B * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first summand. This must point to an initialized MPI. * \param B The second summand. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a signed subtraction of MPIs: X = A - B * * \param X The destination MPI. This must point to an initialized MPI. * \param A The minuend. This must point to an initialized MPI. * \param B The subtrahend. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a signed addition of an MPI and an integer: X = A + b * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first summand. This must point to an initialized MPI. * \param b The second summand. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a signed subtraction of an MPI and an integer: * X = A - b * * \param X The destination MPI. This must point to an initialized MPI. * \param A The minuend. This must point to an initialized MPI. * \param b The subtrahend. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a multiplication of two MPIs: X = A * B * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first factor. This must point to an initialized MPI. * \param B The second factor. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a multiplication of an MPI with an unsigned integer: * X = A * b * * \param X The destination MPI. This must point to an initialized MPI. * \param A The first factor. This must point to an initialized MPI. * \param b The second factor. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b); /** * \brief Perform a division with remainder of two MPIs: * A = Q * B + R * * \param Q The destination MPI for the quotient. * This may be \c NULL if the value of the * quotient is not needed. This must not alias A or B. * \param R The destination MPI for the remainder value. * This may be \c NULL if the value of the * remainder is not needed. This must not alias A or B. * \param A The dividend. This must point to an initialized MPI. * \param B The divisor. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a division with remainder of an MPI by an integer: * A = Q * b + R * * \param Q The destination MPI for the quotient. * This may be \c NULL if the value of the * quotient is not needed. This must not alias A. * \param R The destination MPI for the remainder value. * This may be \c NULL if the value of the * remainder is not needed. This must not alias A. * \param A The dividend. This must point to an initialized MPi. * \param b The divisor. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a modular reduction. R = A mod B * * \param R The destination MPI for the residue value. * This must point to an initialized MPI. * \param A The MPI to compute the residue of. * This must point to an initialized MPI. * \param B The base of the modular reduction. * This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. * \return Another negative error code on different kinds of failure. * */ int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Perform a modular reduction with respect to an integer. * r = A mod b * * \param r The address at which to store the residue. * This must not be \c NULL. * \param A The MPI to compute the residue of. * This must point to an initialized MPi. * \param b The integer base of the modular reduction. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b); /** * \brief Perform a sliding-window exponentiation: X = A^E mod N * * \param X The destination MPI. This must point to an initialized MPI. * This must not alias E or N. * \param A The base of the exponentiation. * This must point to an initialized MPI. * \param E The exponent MPI. This must point to an initialized MPI. * \param N The base for the modular reduction. This must point to an * initialized MPI. * \param prec_RR A helper MPI depending solely on \p N which can be used to * speed-up multiple modular exponentiations for the same value * of \p N. This may be \c NULL. If it is not \c NULL, it must * point to an initialized MPI. If it hasn't been used after * the call to mbedtls_mpi_init(), this function will compute * the helper value and store it in \p prec_RR for reuse on * subsequent calls to this function. Otherwise, the function * will assume that \p prec_RR holds the helper value set by a * previous call to mbedtls_mpi_exp_mod(), and reuse it. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or * even, or if \c E is negative. * \return Another negative error code on different kinds of failures. * */ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR); /** * \brief Fill an MPI with a number of random bytes. * * \param X The destination MPI. This must point to an initialized MPI. * \param size The number of random bytes to generate. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on failure. * * \note The bytes obtained from the RNG are interpreted * as a big-endian representation of an MPI; this can * be relevant in applications like deterministic ECDSA. */ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination MPI. This must point to an initialized MPI. * \param min The minimum value to return. * It must be nonnegative. * \param N The upper bound of the range, exclusive. * In other words, this is one plus the maximum value to return. * \p N must be strictly larger than \p min. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid * or if they are incompatible. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. * \return Another negative error code on failure. */ int mbedtls_mpi_random(mbedtls_mpi *X, mbedtls_mpi_sint min, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Compute the greatest common divisor: G = gcd(A, B) * * \param G The destination MPI. This must point to an initialized MPI. * \param A The first operand. This must point to an initialized MPI. * \param B The second operand. This must point to an initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return Another negative error code on different kinds of failure. */ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B); /** * \brief Compute the modular inverse: X = A^-1 mod N * * \param X The destination MPI. This must point to an initialized MPI. * \param A The MPI to calculate the modular inverse of. This must point * to an initialized MPI. * \param N The base of the modular inversion. This must point to an * initialized MPI. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than * or equal to one. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p A has no modular * inverse with respect to \p N. */ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N); /** * \brief Miller-Rabin primality test. * * \warning If \p X is potentially generated by an adversary, for example * when validating cryptographic parameters that you didn't * generate yourself and that are supposed to be prime, then * \p rounds should be at least the half of the security * strength of the cryptographic algorithm. On the other hand, * if \p X is chosen uniformly or non-adversarially (as is the * case when mbedtls_mpi_gen_prime calls this function), then * \p rounds can be much lower. * * \param X The MPI to check for primality. * This must point to an initialized MPI. * \param rounds The number of bases to perform the Miller-Rabin primality * test for. The probability of returning 0 on a composite is * at most 2-2*\p rounds . * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't use * a context parameter. * * \return \c 0 if successful, i.e. \p X is probably prime. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. * \return Another negative error code on other kinds of failure. */ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Flags for mbedtls_mpi_gen_prime() * * Each of these flags is a constraint on the result X returned by * mbedtls_mpi_gen_prime(). */ typedef enum { MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ } mbedtls_mpi_gen_prime_flag_t; /** * \brief Generate a prime number. * * \param X The destination MPI to store the generated prime in. * This must point to an initialized MPi. * \param nbits The required size of the destination MPI in bits. * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't use * a context parameter. * * \return \c 0 if successful, in which case \p X holds a * probably prime number. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between * \c 3 and #MBEDTLS_MPI_MAX_BITS. */ int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Montgomery initialization * * \param mm The -1/m mod N result * \param N The modulus */ void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ); /** * \brief Montgomery multiplication: A = A * B * R^-1 mod N * \A Parameter and result * \B Parameter * \N Modulus * \mm Parameter from mbedtls_mpi_montg_init() * \T Temporary variable, should be as twice as big as N + 2 */ void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, mbedtls_mpi *T ); /** * \brief Montgomery reduction: A = A * R^-1 mod N * \A Parameter and result * \N Modulus * \mm Parameter from mbedtls_mpi_montg_init() * \T Temporary variable, should be as twice as big as N + 2 */ void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, mbedtls_mpi *T); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_mpi_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* bignum.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/block_cipher.h000066400000000000000000000035311464416617300255440ustar00rootroot00000000000000/** * \file block_cipher.h * * \brief Internal abstraction layer. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BLOCK_CIPHER_H #define MBEDTLS_BLOCK_CIPHER_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) #include "psa/crypto_types.h" #endif #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_BLOCK_CIPHER_ID_NONE = 0, /**< Unset. */ MBEDTLS_BLOCK_CIPHER_ID_AES, /**< The AES cipher. */ MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ MBEDTLS_BLOCK_CIPHER_ID_ARIA, /**< The Aria cipher. */ } mbedtls_block_cipher_id_t; /** * Used internally to indicate whether a context uses legacy or PSA. * * Internal use only. */ typedef enum { MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY = 0, MBEDTLS_BLOCK_CIPHER_ENGINE_PSA, } mbedtls_block_cipher_engine_t; typedef struct { mbedtls_block_cipher_id_t MBEDTLS_PRIVATE(id); #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) mbedtls_block_cipher_engine_t MBEDTLS_PRIVATE(engine); mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_key_id); #endif union { unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_AES_C) mbedtls_aes_context MBEDTLS_PRIVATE(aes); #endif #if defined(MBEDTLS_ARIA_C) mbedtls_aria_context MBEDTLS_PRIVATE(aria); #endif #if defined(MBEDTLS_CAMELLIA_C) mbedtls_camellia_context MBEDTLS_PRIVATE(camellia); #endif } MBEDTLS_PRIVATE(ctx); } mbedtls_block_cipher_context_t; #ifdef __cplusplus } #endif #endif /* MBEDTLS_BLOCK_CIPHER_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h000066400000000000000000000126561464416617300252420ustar00rootroot00000000000000/** * \file mbedtls/build_info.h * * \brief Build-time configuration info * * Include this file if you need to depend on the * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BUILD_INFO_H #define MBEDTLS_BUILD_INFO_H /* * This set of compile-time defines can be used to determine the version number * of the Mbed TLS library used. Run-time variables for the same can be found in * version.h */ /** * The version number x.y.z is split into three parts. * Major, Minor, Patchlevel */ #define MBEDTLS_VERSION_MAJOR 3 #define MBEDTLS_VERSION_MINOR 6 #define MBEDTLS_VERSION_PATCH 0 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ #define MBEDTLS_VERSION_NUMBER 0x03060000 #define MBEDTLS_VERSION_STRING "3.6.0" #define MBEDTLS_VERSION_STRING_FULL "Mbed TLS 3.6.0" /* Macros for build-time platform detection */ #if !defined(MBEDTLS_ARCH_IS_ARM64) && \ (defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) #define MBEDTLS_ARCH_IS_ARM64 #endif #if !defined(MBEDTLS_ARCH_IS_ARM32) && \ (defined(__arm__) || defined(_M_ARM) || \ defined(_M_ARMT) || defined(__thumb__) || defined(__thumb2__)) #define MBEDTLS_ARCH_IS_ARM32 #endif #if !defined(MBEDTLS_ARCH_IS_X64) && \ (defined(__amd64__) || defined(__x86_64__) || \ ((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC))) #define MBEDTLS_ARCH_IS_X64 #endif #if !defined(MBEDTLS_ARCH_IS_X86) && \ (defined(__i386__) || defined(_X86_) || \ (defined(_M_IX86) && !defined(_M_I86))) #define MBEDTLS_ARCH_IS_X86 #endif #if !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ (defined(_M_ARM64) || defined(_M_ARM64EC)) #define MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64 #endif /* This is defined if the architecture is Armv8-A, or higher */ #if !defined(MBEDTLS_ARCH_IS_ARMV8_A) #if defined(__ARM_ARCH) && defined(__ARM_ARCH_PROFILE) #if (__ARM_ARCH >= 8) && (__ARM_ARCH_PROFILE == 'A') /* GCC, clang, armclang and IAR */ #define MBEDTLS_ARCH_IS_ARMV8_A #endif #elif defined(__ARM_ARCH_8A) /* Alternative defined by clang */ #define MBEDTLS_ARCH_IS_ARMV8_A #elif defined(_M_ARM64) || defined(_M_ARM64EC) /* MSVC ARM64 is at least Armv8.0-A */ #define MBEDTLS_ARCH_IS_ARMV8_A #endif #endif #if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \ && !defined(__llvm__) && !defined(__INTEL_COMPILER) /* Defined if the compiler really is gcc and not clang, etc */ #define MBEDTLS_COMPILER_IS_GCC #define MBEDTLS_GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) #define _CRT_SECURE_NO_DEPRECATE 1 #endif /* Define `inline` on some non-C99-compliant compilers. */ #if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && \ !defined(inline) && !defined(__cplusplus) #define inline __inline #endif /* X.509, TLS and non-PSA crypto configuration */ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/mbedtls_config.h" #else #include MBEDTLS_CONFIG_FILE #endif #if defined(MBEDTLS_CONFIG_VERSION) && ( \ MBEDTLS_CONFIG_VERSION < 0x03000000 || \ MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER) #error "Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported" #endif /* Target and application specific configurations * * Allow user to override any previous default. * */ #if defined(MBEDTLS_USER_CONFIG_FILE) #include MBEDTLS_USER_CONFIG_FILE #endif /* PSA crypto configuration */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) #if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE) #include MBEDTLS_PSA_CRYPTO_CONFIG_FILE #else #include "psa/crypto_config.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE) #include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE #endif #endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ /* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if * MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined * to ensure a 128-bit key size in CTR_DRBG. */ #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && defined(MBEDTLS_CTR_DRBG_C) #define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY #endif /* Auto-enable MBEDTLS_MD_C if needed by a module that didn't require it * in a previous release, to ensure backwards compatibility. */ #if defined(MBEDTLS_PKCS5_C) #define MBEDTLS_MD_C #endif /* PSA crypto specific configuration options * - If config_psa.h reads a configuration option in preprocessor directive, * this symbol should be set before its inclusion. (e.g. MBEDTLS_MD_C) * - If config_psa.h writes a configuration option in conditional directive, * this symbol should be consulted after its inclusion. * (e.g. MBEDTLS_MD_LIGHT) */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \ defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ || \ defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* The same as the previous, but with separation only */ #include "mbedtls/config_psa.h" #endif #include "mbedtls/config_adjust_legacy_crypto.h" #include "mbedtls/config_adjust_x509.h" #include "mbedtls/config_adjust_ssl.h" /* Make sure all configuration symbols are set before including check_config.h, * even the ones that are calculated programmatically. */ #include "mbedtls/check_config.h" #endif /* MBEDTLS_BUILD_INFO_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h000066400000000000000000000321001464416617300246610ustar00rootroot00000000000000/** * \file camellia.h * * \brief Camellia block cipher */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CAMELLIA_H #define MBEDTLS_CAMELLIA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #include "mbedtls/platform_util.h" #define MBEDTLS_CAMELLIA_ENCRYPT 1 #define MBEDTLS_CAMELLIA_DECRYPT 0 /** Bad input data. */ #define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /** Invalid data input length. */ #define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_CAMELLIA_ALT) // Regular implementation // /** * \brief CAMELLIA context structure */ typedef struct mbedtls_camellia_context { int MBEDTLS_PRIVATE(nr); /*!< number of rounds */ uint32_t MBEDTLS_PRIVATE(rk)[68]; /*!< CAMELLIA round keys */ } mbedtls_camellia_context; #else /* MBEDTLS_CAMELLIA_ALT */ #include "camellia_alt.h" #endif /* MBEDTLS_CAMELLIA_ALT */ /** * \brief Initialize a CAMELLIA context. * * \param ctx The CAMELLIA context to be initialized. * This must not be \c NULL. */ void mbedtls_camellia_init(mbedtls_camellia_context *ctx); /** * \brief Clear a CAMELLIA context. * * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, * in which case this function returns immediately. If it is not * \c NULL, it must be initialized. */ void mbedtls_camellia_free(mbedtls_camellia_context *ctx); /** * \brief Perform a CAMELLIA key schedule operation for encryption. * * \param ctx The CAMELLIA context to use. This must be initialized. * \param key The encryption key to use. This must be a readable buffer * of size \p keybits Bits. * \param keybits The length of \p key in Bits. This must be either \c 128, * \c 192 or \c 256. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Perform a CAMELLIA key schedule operation for decryption. * * \param ctx The CAMELLIA context to use. This must be initialized. * \param key The decryption key. This must be a readable buffer * of size \p keybits Bits. * \param keybits The length of \p key in Bits. This must be either \c 128, * \c 192 or \c 256. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * \param input The input block. This must be a readable buffer * of size \c 16 Bytes. * \param output The output block. This must be a writable buffer * of size \c 16 Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * \param length The length in Bytes of the input data \p input. * This must be a multiple of \c 16 Bytes. * \param iv The initialization vector. This must be a read/write buffer * of length \c 16 Bytes. It is updated to allow streaming * use as explained above. * \param input The buffer holding the input data. This must point to a * readable buffer of length \p length Bytes. * \param output The buffer holding the output data. This must point to a * writable buffer of length \p length Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption * operation. * * \note Due to the nature of CFB mode, you should use the same * key for both encryption and decryption. In particular, calls * to this function should be preceded by a key-schedule via * mbedtls_camellia_setkey_enc() regardless of whether \p mode * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param mode The mode of operation. This must be either * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * \param length The length of the input data \p input. Any value is allowed. * \param iv_off The current offset in the IV. This must be smaller * than \c 16 Bytes. It is updated after this call to allow * the aforementioned streaming usage. * \param iv The initialization vector. This must be a read/write buffer * of length \c 16 Bytes. It is updated after this call to * allow the aforementioned streaming usage. * \param input The buffer holding the input data. This must be a readable * buffer of size \p length Bytes. * \param output The buffer to hold the output data. This must be a writable * buffer of length \p length Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /** * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. * * *note Due to the nature of CTR mode, you should use the same * key for both encryption and decryption. In particular, calls * to this function should be preceded by a key-schedule via * mbedtls_camellia_setkey_enc() regardless of whether the mode * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. * * \warning You must never reuse a nonce value with the same key. Doing so * would void the encryption for the two messages encrypted with * the same nonce and key. * * There are two common strategies for managing nonces with CTR: * * 1. You can handle everything as a single message processed over * successive calls to this function. In that case, you want to * set \p nonce_counter and \p nc_off to 0 for the first call, and * then preserve the values of \p nonce_counter, \p nc_off and \p * stream_block across calls to this function as they will be * updated by this function. * * With this strategy, you must not encrypt more than 2**128 * blocks of data with the same key. * * 2. You can encrypt separate messages by dividing the \p * nonce_counter buffer in two areas: the first one used for a * per-message nonce, handled by yourself, and the second one * updated by this function internally. * * For example, you might reserve the first \c 12 Bytes for the * per-message nonce, and the last \c 4 Bytes for internal use. * In that case, before calling this function on a new message you * need to set the first \c 12 Bytes of \p nonce_counter to your * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 * (which will cause \p stream_block to be ignored). That way, you * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks * each with the same key. * * The per-message nonce (or information sufficient to reconstruct * it) needs to be communicated with the ciphertext and must be * unique. The recommended way to ensure uniqueness is to use a * message counter. An alternative is to generate random nonces, * but this limits the number of messages that can be securely * encrypted: for example, with 96-bit random nonces, you should * not encrypt more than 2**32 messages with the same key. * * Note that for both strategies, sizes are measured in blocks and * that a CAMELLIA block is \c 16 Bytes. * * \warning Upon return, \p stream_block contains sensitive data. Its * content must not be written to insecure storage and should be * securely discarded as soon as it's no longer needed. * * \param ctx The CAMELLIA context to use. This must be initialized * and bound to a key. * \param length The length of the input data \p input in Bytes. * Any value is allowed. * \param nc_off The offset in the current \p stream_block (for resuming * within current cipher stream). The offset pointer to * should be \c 0 at the start of a stream. It is updated * at the end of this call. * \param nonce_counter The 128-bit nonce and counter. This must be a read/write * buffer of length \c 16 Bytes. * \param stream_block The saved stream-block for resuming. This must be a * read/write buffer of length \c 16 Bytes. * \param input The input data stream. This must be a readable buffer of * size \p length Bytes. * \param output The output data stream. This must be a writable buffer * of size \p length Bytes. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_camellia_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* camellia.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h000066400000000000000000000617441464416617300236740ustar00rootroot00000000000000/** * \file ccm.h * * \brief This file provides an API for the CCM authenticated encryption * mode for block ciphers. * * CCM combines Counter mode encryption with CBC-MAC authentication * for 128-bit block ciphers. * * Input to CCM includes the following elements: *
  • Payload - data that is both authenticated and encrypted.
  • *
  • Associated data (Adata) - data that is authenticated but not * encrypted, For example, a header.
  • *
  • Nonce - A unique value that is assigned to the payload and the * associated data.
* * Definition of CCM: * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf * RFC 3610 "Counter with CBC-MAC (CCM)" * * Related: * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" * * Definition of CCM*: * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks * Integer representation is fixed most-significant-octet-first order and * the representation of octets is most-significant-bit-first order. This is * consistent with RFC 3610. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CCM_H #define MBEDTLS_CCM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "mbedtls/block_cipher.h" #endif #define MBEDTLS_CCM_DECRYPT 0 #define MBEDTLS_CCM_ENCRYPT 1 #define MBEDTLS_CCM_STAR_DECRYPT 2 #define MBEDTLS_CCM_STAR_ENCRYPT 3 /** Bad input parameters to the function. */ #define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /** Authenticated decryption failed. */ #define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_CCM_ALT) // Regular implementation // /** * \brief The CCM context-type definition. The CCM context is passed * to the APIs called. */ typedef struct mbedtls_ccm_context { unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working buffer */ unsigned char MBEDTLS_PRIVATE(ctr)[16]; /*!< The counter buffer */ size_t MBEDTLS_PRIVATE(plaintext_len); /*!< Total plaintext length */ size_t MBEDTLS_PRIVATE(add_len); /*!< Total authentication data length */ size_t MBEDTLS_PRIVATE(tag_len); /*!< Total tag length */ size_t MBEDTLS_PRIVATE(processed); /*!< Track how many bytes of input data were processed (chunked input). Used independently for both auth data and plaintext/ciphertext. This variable is set to zero after auth data input is finished. */ unsigned int MBEDTLS_PRIVATE(q); /*!< The Q working value */ unsigned int MBEDTLS_PRIVATE(mode); /*!< The operation to perform: #MBEDTLS_CCM_ENCRYPT or #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or #MBEDTLS_CCM_STAR_DECRYPT. */ #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx); /*!< The cipher context used. */ #else mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ #endif int MBEDTLS_PRIVATE(state); /*!< Working value holding context's state. Used for chunked data input */ } mbedtls_ccm_context; #else /* MBEDTLS_CCM_ALT */ #include "ccm_alt.h" #endif /* MBEDTLS_CCM_ALT */ /** * \brief This function initializes the specified CCM context, * to make references valid, and prepare the context * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). * * \param ctx The CCM context to initialize. This must not be \c NULL. */ void mbedtls_ccm_init(mbedtls_ccm_context *ctx); /** * \brief This function initializes the CCM context set in the * \p ctx parameter and sets the encryption key. * * \param ctx The CCM context to initialize. This must be an initialized * context. * \param cipher The 128-bit block cipher to use. * \param key The encryption key. This must not be \c NULL. * \param keybits The key size in bits. This must be acceptable by the cipher. * * \return \c 0 on success. * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits); /** * \brief This function releases and clears the specified CCM context * and underlying cipher sub-context. * * \param ctx The CCM context to clear. If this is \c NULL, the function * has no effect. Otherwise, this must be initialized. */ void mbedtls_ccm_free(mbedtls_ccm_context *ctx); /** * \brief This function encrypts a buffer using CCM. * * \note The tag is written to a separate buffer. To concatenate * the \p tag with the \p output, as done in RFC-3610: * Counter with CBC-MAC (CCM), use * \p tag = \p output + \p length, and make sure that the * output buffer is at least \p length + \p tag_len wide. * * \param ctx The CCM context to use for encryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. If \p ad_len is greater than * zero, \p ad must be a readable buffer of at least that * length. * \param ad_len The length of additional data in Bytes. * This must be less than `2^16 - 2^8`. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * writable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); /** * \brief This function encrypts a buffer using CCM*. * * \note The tag is written to a separate buffer. To concatenate * the \p tag with the \p output, as done in RFC-3610: * Counter with CBC-MAC (CCM), use * \p tag = \p output + \p length, and make sure that the * output buffer is at least \p length + \p tag_len wide. * * \note When using this function in a variable tag length context, * the tag length has to be encoded into the \p iv passed to * this function. * * \param ctx The CCM context to use for encryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. This must be a readable buffer of * at least \p ad_len Bytes. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * writable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 0, 4, 6, 8, 10, 12, 14 or 16. * * \warning Passing \c 0 as \p tag_len means that the message is no * longer authenticated. * * \return \c 0 on success. * \return A CCM or cipher-specific error code on failure. */ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len); /** * \brief This function performs a CCM authenticated decryption of a * buffer. * * \param ctx The CCM context to use for decryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. This must be a readable buffer * of at least that \p ad_len Bytes.. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * * \return \c 0 on success. This indicates that the message is authentic. * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. * \return A cipher-specific error code on calculation failure. */ int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); /** * \brief This function performs a CCM* authenticated decryption of a * buffer. * * \note When using this function in a variable tag length context, * the tag length has to be decoded from \p iv and passed to * this function as \p tag_len. (\p tag needs to be adjusted * accordingly.) * * \param ctx The CCM context to use for decryption. This must be * initialized and bound to a key. * \param length The length of the input data in Bytes. * For tag length = 0, input length is ignored. * \param iv The initialization vector (nonce). This must be a readable * buffer of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * \param ad The additional data field. This must be a readable buffer of * at least that \p ad_len Bytes. * \param ad_len The length of additional data in Bytes. * This must be less than 2^16 - 2^8. * \param input The buffer holding the input data. If \p length is greater * than zero, \p input must be a readable buffer of at least * that length. * \param output The buffer holding the output data. If \p length is greater * than zero, \p output must be a writable buffer of at least * that length. * \param tag The buffer holding the authentication field. This must be a * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the authentication field in Bytes. * 0, 4, 6, 8, 10, 12, 14 or 16. * * \warning Passing \c 0 as \p tag_len means that the message is nos * longer authenticated. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. * \return A cipher-specific error code on calculation failure. */ int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len); /** * \brief This function starts a CCM encryption or decryption * operation. * * This function and mbedtls_ccm_set_lengths() must be called * before calling mbedtls_ccm_update_ad() or * mbedtls_ccm_update(). This function can be called before * or after mbedtls_ccm_set_lengths(). * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must be initialized. * \param mode The operation to perform: #MBEDTLS_CCM_ENCRYPT or * #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or * #MBEDTLS_CCM_STAR_DECRYPT. * \param iv The initialization vector. This must be a readable buffer * of at least \p iv_len Bytes. * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, * or 13. The length L of the message length field is * 15 - \p iv_len. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * \p mode is invalid, * \p iv_len is invalid (lower than \c 7 or greater than * \c 13). */ int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, int mode, const unsigned char *iv, size_t iv_len); /** * \brief This function declares the lengths of the message * and additional data for a CCM encryption or decryption * operation. * * This function and mbedtls_ccm_starts() must be called * before calling mbedtls_ccm_update_ad() or * mbedtls_ccm_update(). This function can be called before * or after mbedtls_ccm_starts(). * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must be initialized. * \param total_ad_len The total length of additional data in bytes. * This must be less than `2^16 - 2^8`. * \param plaintext_len The length in bytes of the plaintext to encrypt or * result of the decryption (thus not encompassing the * additional data that are not encrypted). * \param tag_len The length of the tag to generate in Bytes: * 4, 6, 8, 10, 12, 14 or 16. * For CCM*, zero is also valid. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * \p total_ad_len is greater than \c 0xFF00. */ int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, size_t total_ad_len, size_t plaintext_len, size_t tag_len); /** * \brief This function feeds an input buffer as associated data * (authenticated but not encrypted data) in a CCM * encryption or decryption operation. * * You may call this function zero, one or more times * to pass successive parts of the additional data. The * lengths \p ad_len of the data parts should eventually add * up exactly to the total length of additional data * \c total_ad_len passed to mbedtls_ccm_set_lengths(). You * may not call this function after calling * mbedtls_ccm_update(). * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must have been started with * mbedtls_ccm_starts(), the lengths of the message and * additional data must have been declared with * mbedtls_ccm_set_lengths() and this must not have yet * received any input with mbedtls_ccm_update(). * \param ad The buffer holding the additional data, or \c NULL * if \p ad_len is \c 0. * \param ad_len The length of the additional data. If \c 0, * \p ad may be \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * total input length too long. */ int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, const unsigned char *ad, size_t ad_len); /** * \brief This function feeds an input buffer into an ongoing CCM * encryption or decryption operation. * * You may call this function zero, one or more times * to pass successive parts of the input: the plaintext to * encrypt, or the ciphertext (not including the tag) to * decrypt. After the last part of the input, call * mbedtls_ccm_finish(). The lengths \p input_len of the * data parts should eventually add up exactly to the * plaintext length \c plaintext_len passed to * mbedtls_ccm_set_lengths(). * * This function may produce output in one of the following * ways: * - Immediate output: the output length is always equal * to the input length. * - Buffered output: except for the last part of input data, * the output consists of a whole number of 16-byte blocks. * If the total input length so far (not including * associated data) is 16 \* *B* + *A* with *A* < 16 then * the total output length is 16 \* *B*. * For the last part of input data, the output length is * equal to the input length plus the number of bytes (*A*) * buffered in the previous call to the function (if any). * The function uses the plaintext length * \c plaintext_len passed to mbedtls_ccm_set_lengths() * to detect the last part of input data. * * In particular: * - It is always correct to call this function with * \p output_size >= \p input_len + 15. * - If \p input_len is a multiple of 16 for all the calls * to this function during an operation (not necessary for * the last one) then it is correct to use \p output_size * =\p input_len. * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must have been started with * mbedtls_ccm_starts() and the lengths of the message and * additional data must have been declared with * mbedtls_ccm_set_lengths(). * \param input The buffer holding the input data. If \p input_len * is greater than zero, this must be a readable buffer * of at least \p input_len bytes. * \param input_len The length of the input data in bytes. * \param output The buffer for the output data. If \p output_size * is greater than zero, this must be a writable buffer of * at least \p output_size bytes. * \param output_size The size of the output buffer in bytes. * See the function description regarding the output size. * \param output_len On success, \p *output_len contains the actual * length of the output written in \p output. * On failure, the content of \p *output_len is * unspecified. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * total input length too long, * or \p output_size too small. */ int mbedtls_ccm_update(mbedtls_ccm_context *ctx, const unsigned char *input, size_t input_len, unsigned char *output, size_t output_size, size_t *output_len); /** * \brief This function finishes the CCM operation and generates * the authentication tag. * * It wraps up the CCM stream, and generates the * tag. The tag can have a maximum length of 16 Bytes. * * \note This function is not implemented in Mbed TLS yet. * * \param ctx The CCM context. This must have been started with * mbedtls_ccm_starts() and the lengths of the message and * additional data must have been declared with * mbedtls_ccm_set_lengths(). * \param tag The buffer for holding the tag. If \p tag_len is greater * than zero, this must be a writable buffer of at least \p * tag_len Bytes. * \param tag_len The length of the tag. Must match the tag length passed to * mbedtls_ccm_set_lengths() function. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: * \p ctx is in an invalid state, * invalid value of \p tag_len, * the total amount of additional data passed to * mbedtls_ccm_update_ad() was lower than the total length of * additional data \c total_ad_len passed to * mbedtls_ccm_set_lengths(), * the total amount of input data passed to * mbedtls_ccm_update() was lower than the plaintext length * \c plaintext_len passed to mbedtls_ccm_set_lengths(). */ int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, unsigned char *tag, size_t tag_len); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /** * \brief The CCM checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_ccm_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CCM_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h000066400000000000000000000171051464416617300244730ustar00rootroot00000000000000/** * \file chacha20.h * * \brief This file contains ChaCha20 definitions and functions. * * ChaCha20 is a stream cipher that can encrypt and decrypt * information. ChaCha was created by Daniel Bernstein as a variant of * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf * ChaCha20 is the variant with 20 rounds, that was also standardized * in RFC 7539. * * \author Daniel King */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHACHA20_H #define MBEDTLS_CHACHA20_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** Invalid input parameter(s). */ #define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_CHACHA20_ALT) typedef struct mbedtls_chacha20_context { uint32_t MBEDTLS_PRIVATE(state)[16]; /*! The state (before round operations). */ uint8_t MBEDTLS_PRIVATE(keystream8)[64]; /*! Leftover keystream bytes. */ size_t MBEDTLS_PRIVATE(keystream_bytes_used); /*! Number of keystream bytes already used. */ } mbedtls_chacha20_context; #else /* MBEDTLS_CHACHA20_ALT */ #include "chacha20_alt.h" #endif /* MBEDTLS_CHACHA20_ALT */ /** * \brief This function initializes the specified ChaCha20 context. * * It must be the first API called before using * the context. * * It is usually followed by calls to * \c mbedtls_chacha20_setkey() and * \c mbedtls_chacha20_starts(), then one or more calls to * to \c mbedtls_chacha20_update(), and finally to * \c mbedtls_chacha20_free(). * * \param ctx The ChaCha20 context to initialize. * This must not be \c NULL. */ void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx); /** * \brief This function releases and clears the specified * ChaCha20 context. * * \param ctx The ChaCha20 context to clear. This may be \c NULL, * in which case this function is a no-op. If it is not * \c NULL, it must point to an initialized context. * */ void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx); /** * \brief This function sets the encryption/decryption key. * * \note After using this function, you must also call * \c mbedtls_chacha20_starts() to set a nonce before you * start encrypting/decrypting data with * \c mbedtls_chacha_update(). * * \param ctx The ChaCha20 context to which the key should be bound. * It must be initialized. * \param key The encryption/decryption key. This must be \c 32 Bytes * in length. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. */ int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx, const unsigned char key[32]); /** * \brief This function sets the nonce and initial counter value. * * \note A ChaCha20 context can be re-used with the same key by * calling this function to change the nonce. * * \warning You must never use the same nonce twice with the same key. * This would void any confidentiality guarantees for the * messages encrypted with the same nonce and key. * * \param ctx The ChaCha20 context to which the nonce should be bound. * It must be initialized and bound to a key. * \param nonce The nonce. This must be \c 12 Bytes in size. * \param counter The initial counter value. This is usually \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is * NULL. */ int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx, const unsigned char nonce[12], uint32_t counter); /** * \brief This function encrypts or decrypts data. * * Since ChaCha20 is a stream cipher, the same operation is * used for encrypting and decrypting data. * * \note The \p input and \p output pointers must either be equal or * point to non-overlapping buffers. * * \note \c mbedtls_chacha20_setkey() and * \c mbedtls_chacha20_starts() must be called at least once * to setup the context before this function can be called. * * \note This function can be called multiple times in a row in * order to encrypt of decrypt data piecewise with the same * key and nonce. * * \param ctx The ChaCha20 context to use for encryption or decryption. * It must be initialized and bound to a key and nonce. * \param size The length of the input data in Bytes. * \param input The buffer holding the input data. * This pointer can be \c NULL if `size == 0`. * \param output The buffer holding the output data. * This must be able to hold \p size Bytes. * This pointer can be \c NULL if `size == 0`. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, size_t size, const unsigned char *input, unsigned char *output); /** * \brief This function encrypts or decrypts data with ChaCha20 and * the given key and nonce. * * Since ChaCha20 is a stream cipher, the same operation is * used for encrypting and decrypting data. * * \warning You must never use the same (key, nonce) pair more than * once. This would void any confidentiality guarantees for * the messages encrypted with the same nonce and key. * * \note The \p input and \p output pointers must either be equal or * point to non-overlapping buffers. * * \param key The encryption/decryption key. * This must be \c 32 Bytes in length. * \param nonce The nonce. This must be \c 12 Bytes in size. * \param counter The initial counter value. This is usually \c 0. * \param size The length of the input data in Bytes. * \param input The buffer holding the input data. * This pointer can be \c NULL if `size == 0`. * \param output The buffer holding the output data. * This must be able to hold \p size Bytes. * This pointer can be \c NULL if `size == 0`. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chacha20_crypt(const unsigned char key[32], const unsigned char nonce[12], uint32_t counter, size_t size, const unsigned char *input, unsigned char *output); #if defined(MBEDTLS_SELF_TEST) /** * \brief The ChaCha20 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_chacha20_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CHACHA20_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h000066400000000000000000000363551464416617300252450ustar00rootroot00000000000000/** * \file chachapoly.h * * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and * functions. * * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption * with Associated Data (AEAD) that can be used to encrypt and * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel * Bernstein and was standardized in RFC 7539. * * \author Daniel King */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHACHAPOLY_H #define MBEDTLS_CHACHAPOLY_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" /* for shared error codes */ #include "mbedtls/poly1305.h" /** The requested operation is not permitted in the current state. */ #define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /** Authenticated decryption failed: data was not authentic. */ #define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ } mbedtls_chachapoly_mode_t; #if !defined(MBEDTLS_CHACHAPOLY_ALT) #include "mbedtls/chacha20.h" typedef struct mbedtls_chachapoly_context { mbedtls_chacha20_context MBEDTLS_PRIVATE(chacha20_ctx); /**< The ChaCha20 context. */ mbedtls_poly1305_context MBEDTLS_PRIVATE(poly1305_ctx); /**< The Poly1305 context. */ uint64_t MBEDTLS_PRIVATE(aad_len); /**< The length (bytes) of the Additional Authenticated Data. */ uint64_t MBEDTLS_PRIVATE(ciphertext_len); /**< The length (bytes) of the ciphertext. */ int MBEDTLS_PRIVATE(state); /**< The current state of the context. */ mbedtls_chachapoly_mode_t MBEDTLS_PRIVATE(mode); /**< Cipher mode (encrypt or decrypt). */ } mbedtls_chachapoly_context; #else /* !MBEDTLS_CHACHAPOLY_ALT */ #include "chachapoly_alt.h" #endif /* !MBEDTLS_CHACHAPOLY_ALT */ /** * \brief This function initializes the specified ChaCha20-Poly1305 context. * * It must be the first API called before using * the context. It must be followed by a call to * \c mbedtls_chachapoly_setkey() before any operation can be * done, and to \c mbedtls_chachapoly_free() once all * operations with that context have been finished. * * In order to encrypt or decrypt full messages at once, for * each message you should make a single call to * \c mbedtls_chachapoly_crypt_and_tag() or * \c mbedtls_chachapoly_auth_decrypt(). * * In order to encrypt messages piecewise, for each * message you should make a call to * \c mbedtls_chachapoly_starts(), then 0 or more calls to * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to * \c mbedtls_chachapoly_update(), then one call to * \c mbedtls_chachapoly_finish(). * * \warning Decryption with the piecewise API is discouraged! Always * use \c mbedtls_chachapoly_auth_decrypt() when possible! * * If however this is not possible because the data is too * large to fit in memory, you need to: * * - call \c mbedtls_chachapoly_starts() and (if needed) * \c mbedtls_chachapoly_update_aad() as above, * - call \c mbedtls_chachapoly_update() multiple times and * ensure its output (the plaintext) is NOT used in any other * way than placing it in temporary storage at this point, * - call \c mbedtls_chachapoly_finish() to compute the * authentication tag and compared it in constant time to the * tag received with the ciphertext. * * If the tags are not equal, you must immediately discard * all previous outputs of \c mbedtls_chachapoly_update(), * otherwise you can now safely use the plaintext. * * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. */ void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx); /** * \brief This function releases and clears the specified * ChaCha20-Poly1305 context. * * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which * case this function is a no-op. */ void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx); /** * \brief This function sets the ChaCha20-Poly1305 * symmetric encryption key. * * \param ctx The ChaCha20-Poly1305 context to which the key should be * bound. This must be initialized. * \param key The \c 256 Bit (\c 32 Bytes) key. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx, const unsigned char key[32]); /** * \brief This function starts a ChaCha20-Poly1305 encryption or * decryption operation. * * \warning You must never use the same nonce twice with the same key. * This would void any confidentiality and authenticity * guarantees for the messages encrypted with the same nonce * and key. * * \note If the context is being used for AAD only (no data to * encrypt or decrypt) then \p mode can be set to any value. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \param ctx The ChaCha20-Poly1305 context. This must be initialized * and bound to a key. * \param nonce The nonce/IV to use for the message. * This must be a readable buffer of length \c 12 Bytes. * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx, const unsigned char nonce[12], mbedtls_chachapoly_mode_t mode); /** * \brief This function feeds additional data to be authenticated * into an ongoing ChaCha20-Poly1305 operation. * * The Additional Authenticated Data (AAD), also called * Associated Data (AD) is only authenticated but not * encrypted nor included in the encrypted output. It is * usually transmitted separately from the ciphertext or * computed locally by each party. * * \note This function is called before data is encrypted/decrypted. * I.e. call this function to process the AAD before calling * \c mbedtls_chachapoly_update(). * * You may call this function multiple times to process * an arbitrary amount of AAD. It is permitted to call * this function 0 times, if no AAD is used. * * This function cannot be called any more if data has * been processed by \c mbedtls_chachapoly_update(), * or if the context has been finished. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \param ctx The ChaCha20-Poly1305 context. This must be initialized * and bound to a key. * \param aad_len The length in Bytes of the AAD. The length has no * restrictions. * \param aad Buffer containing the AAD. * This pointer can be \c NULL if `aad_len == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA * if \p ctx or \p aad are NULL. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operations has not been started or has been * finished, or if the AAD has been finished. */ int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx, const unsigned char *aad, size_t aad_len); /** * \brief Thus function feeds data to be encrypted or decrypted * into an on-going ChaCha20-Poly1305 * operation. * * The direction (encryption or decryption) depends on the * mode that was given when calling * \c mbedtls_chachapoly_starts(). * * You may call this function multiple times to process * an arbitrary amount of data. It is permitted to call * this function 0 times, if no data is to be encrypted * or decrypted. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. * \param len The length (in bytes) of the data to encrypt or decrypt. * \param input The buffer containing the data to encrypt or decrypt. * This pointer can be \c NULL if `len == 0`. * \param output The buffer to where the encrypted or decrypted data is * written. This must be able to hold \p len bytes. * This pointer can be \c NULL if `len == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operation has not been started or has been * finished. * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx, size_t len, const unsigned char *input, unsigned char *output); /** * \brief This function finished the ChaCha20-Poly1305 operation and * generates the MAC (authentication tag). * * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. * * \warning Decryption with the piecewise API is discouraged, see the * warning on \c mbedtls_chachapoly_init(). * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE * if the operation has not been started or has been * finished. * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx, unsigned char mac[16]); /** * \brief This function performs a complete ChaCha20-Poly1305 * authenticated encryption with the previously-set key. * * \note Before using this function, you must set the key with * \c mbedtls_chachapoly_setkey(). * * \warning You must never use the same nonce twice with the same key. * This would void any confidentiality and authenticity * guarantees for the messages encrypted with the same nonce * and key. * * \param ctx The ChaCha20-Poly1305 context to use (holds the key). * This must be initialized. * \param length The length (in bytes) of the data to encrypt or decrypt. * \param nonce The 96-bit (12 bytes) nonce/IV to use. * \param aad The buffer containing the additional authenticated * data (AAD). This pointer can be \c NULL if `aad_len == 0`. * \param aad_len The length (in bytes) of the AAD data to process. * \param input The buffer containing the data to encrypt or decrypt. * This pointer can be \c NULL if `ilen == 0`. * \param output The buffer to where the encrypted or decrypted data * is written. This pointer can be \c NULL if `ilen == 0`. * \param tag The buffer to where the computed 128-bit (16 bytes) MAC * is written. This must not be \c NULL. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char *input, unsigned char *output, unsigned char tag[16]); /** * \brief This function performs a complete ChaCha20-Poly1305 * authenticated decryption with the previously-set key. * * \note Before using this function, you must set the key with * \c mbedtls_chachapoly_setkey(). * * \param ctx The ChaCha20-Poly1305 context to use (holds the key). * \param length The length (in Bytes) of the data to decrypt. * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. * \param aad The buffer containing the additional authenticated data (AAD). * This pointer can be \c NULL if `aad_len == 0`. * \param aad_len The length (in bytes) of the AAD data to process. * \param tag The buffer holding the authentication tag. * This must be a readable buffer of length \c 16 Bytes. * \param input The buffer containing the data to decrypt. * This pointer can be \c NULL if `ilen == 0`. * \param output The buffer to where the decrypted data is written. * This pointer can be \c NULL if `ilen == 0`. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED * if the data was not authentic. * \return Another negative error code on other kinds of failure. */ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char tag[16], const unsigned char *input, unsigned char *output); #if defined(MBEDTLS_SELF_TEST) /** * \brief The ChaCha20-Poly1305 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_chachapoly_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CHACHAPOLY_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h000066400000000000000000001341711464416617300255270ustar00rootroot00000000000000/** * \file check_config.h * * \brief Consistency checks for configuration options */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CHECK_CONFIG_H #define MBEDTLS_CHECK_CONFIG_H /* *INDENT-OFF* */ /* * We assume CHAR_BIT is 8 in many places. In practice, this is true on our * target platforms, so not an issue, but let's just be extra sure. */ #include #if CHAR_BIT != 8 #error "Mbed TLS requires a platform with 8-bit chars" #endif #include #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #if !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_C is required on Windows" #endif /* See auto-enabling SNPRINTF_ALT and VSNPRINTF_ALT * in * config_adjust_legacy_crypto.h */ #endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */ #if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) #error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" #endif #if defined(MBEDTLS_DEPRECATED_WARNING) && \ !defined(__GNUC__) && !defined(__clang__) #error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) #error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" #endif /* Limitations on ECC key types acceleration: if we have any of `PUBLIC_KEY`, * `KEY_PAIR_BASIC`, `KEY_PAIR_IMPORT`, `KEY_PAIR_EXPORT` then we must have * all 4 of them. */ #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #error "Unsupported partial support for ECC key type acceleration, see docs/driver-only-builds.md" #endif /* not all of public, basic, import, export */ #endif /* one of public, basic, import, export */ /* Limitations on ECC curves acceleration: partial curve acceleration is only * supported with crypto excluding PK, X.509 or TLS. * Note: no need to check X.509 as it depends on PK. */ #if defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \ defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \ defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \ defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \ defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \ defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) #if defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #if defined(MBEDTLS_PK_C) || \ defined(MBEDTLS_SSL_TLS_C) #error "Unsupported partial support for ECC curves acceleration, see docs/driver-only-builds.md" #endif /* modules beyond what's supported */ #endif /* not all curves accelerated */ #endif /* some curve accelerated */ #if defined(MBEDTLS_CTR_DRBG_C) && !(defined(MBEDTLS_AES_C) || \ (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_KEY_TYPE_AES) && \ defined(PSA_WANT_ALG_ECB_NO_PADDING))) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) #error "MBEDTLS_DHM_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_CMAC_C) && \ ( !defined(MBEDTLS_CIPHER_C ) || ( !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) ) ) #error "MBEDTLS_CMAC_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_NIST_KW_C) && \ ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) #error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) && defined(MBEDTLS_PSA_CRYPTO_CONFIG) #if defined(PSA_WANT_ALG_CBC_NO_PADDING) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_NO_PADDING cannot be defined simultaneously" #endif #if defined(PSA_WANT_ALG_CBC_PKCS7) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_PKCS7 cannot be defined simultaneously" #endif #if defined(PSA_WANT_ALG_ECB_NO_PADDING) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_ECB_NO_PADDING cannot be defined simultaneously" #endif #if defined(PSA_WANT_KEY_TYPE_DES) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_KEY_TYPE_DES cannot be defined simultaneously" #endif #endif #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) #if defined(MBEDTLS_CIPHER_MODE_CBC) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_CBC cannot be defined simultaneously" #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_XTS cannot be defined simultaneously" #endif #if defined(MBEDTLS_DES_C) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_DES_C cannot be defined simultaneously" #endif #if defined(MBEDTLS_NIST_KW_C) #error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_NIST_KW_C cannot be defined simultaneously" #endif #endif #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECDH_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECDSA_C) && \ ( !defined(MBEDTLS_ECP_C) || \ !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \ !defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_ASN1_WRITE_C) ) #error "MBEDTLS_ECDSA_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_ASN1_WRITE_C) #error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_WRITE_C for ECDSA signature" #endif #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && !defined(MBEDTLS_ASN1_PARSE_C) #error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_PARSE_C for ECDSA verification" #endif #endif /* MBEDTLS_PK_C && MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_ECJPAKE_C) && \ !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RESTARTABLE) && \ ( defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ defined(MBEDTLS_ECDSA_SIGN_ALT) || \ defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ defined(MBEDTLS_ECP_INTERNAL_ALT) || \ defined(MBEDTLS_ECP_ALT) ) #error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative ECP implementation" #endif #if defined(MBEDTLS_ECP_RESTARTABLE) && \ !defined(MBEDTLS_ECP_C) #error "MBEDTLS_ECP_RESTARTABLE defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_LIGHT) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) #error "MBEDTLS_ECP_C defined (or a subset enabled), but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_C) && \ !(defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA256)) #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_C) && \ defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" #endif #if defined(MBEDTLS_ENTROPY_C) && \ (defined(MBEDTLS_ENTROPY_FORCE_SHA256) || !defined(MBEDTLS_MD_CAN_SHA512)) \ && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" #endif #if defined(MBEDTLS_ENTROPY_C) && \ defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_MD_CAN_SHA256) #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #endif #if defined(__has_feature) #if __has_feature(memory_sanitizer) #define MBEDTLS_HAS_MEMSAN // #undef at the end of this paragraph #endif #endif #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) #error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" #endif #undef MBEDTLS_HAS_MEMSAN // temporary macro defined above #if defined(MBEDTLS_CCM_C) && \ !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \ defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA)) #error "MBEDTLS_CCM_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_GCM_C) && \ !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \ defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA)) #error "MBEDTLS_GCM_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C) #error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C) #error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT) #error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" #endif #if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HKDF_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || \ !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) #error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ !defined(MBEDTLS_CAN_ECDH) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ ( !defined(MBEDTLS_CAN_ECDH) || \ !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || \ !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ ( !defined(PSA_WANT_ALG_JPAKE) || \ !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ !defined(PSA_WANT_ECC_SECP_R1_256) ) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ ( !defined(MBEDTLS_ECJPAKE_C) || \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Use of EC J-PAKE in TLS requires SHA-256. */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ !defined(MBEDTLS_MD_CAN_SHA256) #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ !defined(MBEDTLS_MD_CAN_SHA256) && \ !defined(MBEDTLS_MD_CAN_SHA512) && \ !defined(MBEDTLS_MD_CAN_SHA1) #error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires SHA-512, SHA-256 or SHA-1". #endif #if defined(MBEDTLS_MD_C) && \ !defined(MBEDTLS_MD_CAN_MD5) && \ !defined(MBEDTLS_MD_CAN_RIPEMD160) && \ !defined(MBEDTLS_MD_CAN_SHA1) && \ !defined(MBEDTLS_MD_CAN_SHA224) && \ !defined(MBEDTLS_MD_CAN_SHA256) && \ !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA512) && \ !defined(MBEDTLS_MD_CAN_SHA3_224) && \ !defined(MBEDTLS_MD_CAN_SHA3_256) && \ !defined(MBEDTLS_MD_CAN_SHA3_384) && \ !defined(MBEDTLS_MD_CAN_SHA3_512) #error "MBEDTLS_MD_C defined, but no hash algorithm" #endif #if defined(MBEDTLS_LMS_C) && \ ! ( defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_ALG_SHA_256) ) #error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256" #endif #if defined(MBEDTLS_LMS_PRIVATE) && \ ( !defined(MBEDTLS_LMS_C) ) #error "MBEDTLS_LMS_PRIVATE requires MBEDTLS_LMS_C" #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites" #endif #if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites" #endif #if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) #error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) #error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_C) && \ !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_PK_HAVE_ECC_KEYS) #error "MBEDTLS_PK_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_PARSE_C) && \ (!defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_OID_C) || \ !defined(MBEDTLS_PK_C)) #error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PK_WRITE_C) && \ (!defined(MBEDTLS_ASN1_WRITE_C) || \ !defined(MBEDTLS_OID_C) || \ !defined(MBEDTLS_PK_C)) #error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ defined(MBEDTLS_PLATFORM_EXIT_ALT) ) #error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SETBUF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SETBUF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_SETBUF) ||\ defined(MBEDTLS_PLATFORM_SETBUF_ALT) ) #error "MBEDTLS_PLATFORM_SETBUF_MACRO and MBEDTLS_PLATFORM_STD_SETBUF/MBEDTLS_PLATFORM_SETBUF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) && \ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_MS_TIME_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ defined(MBEDTLS_PLATFORM_TIME_ALT) ) #error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ defined(MBEDTLS_PLATFORM_TIME_ALT) ) #error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) #error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ defined(MBEDTLS_PLATFORM_STD_FREE) #error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) #error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" #endif #if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) #error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ defined(MBEDTLS_PLATFORM_STD_CALLOC) #error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) #error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" #endif #if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) #error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) #error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_VSNPRINTF_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) #error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) ||\ defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) ) #error "MBEDTLS_PLATFORM_VSNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_VSNPRINTF/MBEDTLS_PLATFORM_VSNPRINTF_ALT cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) #error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) #error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) #error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ !defined(MBEDTLS_PLATFORM_EXIT_ALT) #error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ !defined(MBEDTLS_HAVE_TIME) ) #error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) #error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ !defined(MBEDTLS_PLATFORM_PRINTF_ALT) #error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) #error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) #error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ !defined(MBEDTLS_ENTROPY_NV_SEED) #error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) #error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) #error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) #error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) #error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" #endif #if defined(MBEDTLS_PSA_CRYPTO_C) && \ !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \ defined(MBEDTLS_ENTROPY_C) ) || \ defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ) #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" #endif #if defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_HAVE_SOFT_BLOCK_MODE) && \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) && !defined(MBEDTLS_CIPHER_C) #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) #error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "MBEDTLS_PSA_CRYPTO_SE_C is deprecated and will be removed in a future version of Mbed TLS" #endif #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ ! defined(MBEDTLS_PSA_CRYPTO_C) #error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ defined(MBEDTLS_ENTROPY_NV_SEED) ) #error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" #endif #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" #endif #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) #error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" #endif #if defined(MBEDTLS_PSA_ITS_FILE_C) && \ !defined(MBEDTLS_FS_IO) #error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ !defined(MBEDTLS_OID_C) ) #error "MBEDTLS_RSA_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ !defined(MBEDTLS_PKCS1_V15) ) #error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) #error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) && \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #error "Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*" #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #if !defined(MBEDTLS_SHA512_C) #error "MBEDTLS_SHA512_USE_A64_CRYPTO_* defined without MBEDTLS_SHA512_C" #endif #if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT) #error "MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*" #endif #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) && !defined(__aarch64__) #error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system" #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) && \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #error "Must only define one of MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #if !defined(MBEDTLS_SHA256_C) #error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_* defined without MBEDTLS_SHA256_C" #endif #if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT) #error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" #endif #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) && !defined(MBEDTLS_ARCH_IS_ARMV8_A) #error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY defined on non-Armv8-A system" #endif /* TLS 1.3 requires separate HKDF parts from PSA, * and at least one ciphersuite, so at least SHA-256 or SHA-384 * from PSA to use with HKDF. * * Note: for dependencies common with TLS 1.2 (running handshake hash), * see MBEDTLS_SSL_TLS_C. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ !(defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \ defined(PSA_WANT_ALG_HKDF_EXTRACT) && \ defined(PSA_WANT_ALG_HKDF_EXPAND) && \ (defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384))) #error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if !( (defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)) && \ defined(MBEDTLS_X509_CRT_PARSE_C) && \ ( defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || defined(MBEDTLS_PKCS1_V21) ) ) #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites" #endif #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) #if !( defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) ) #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites" #endif #endif /* * The current implementation of TLS 1.3 requires MBEDTLS_SSL_KEEP_PEER_CERTIFICATE. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #error "MBEDTLS_SSL_PROTO_TLS1_3 defined without MBEDTLS_SSL_KEEP_PEER_CERTIFICATE" #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) #error "One or more versions of the TLS protocol are enabled " \ "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" #endif #if defined(MBEDTLS_SSL_EARLY_DATA) && \ ( !defined(MBEDTLS_SSL_SESSION_TICKETS) || \ ( !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) && \ !defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) ) ) #error "MBEDTLS_SSL_EARLY_DATA defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) && \ ((MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0) || \ (MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX)) #error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE must be in the range(0..UINT32_MAX)" #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) #error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && !defined(MBEDTLS_X509_CRT_PARSE_C) #error "MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS_C) && !(defined(MBEDTLS_CIPHER_C) || \ defined(MBEDTLS_USE_PSA_CRYPTO)) #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif /* TLS 1.2 and 1.3 require SHA-256 or SHA-384 (running handshake hash) */ #if defined(MBEDTLS_SSL_TLS_C) #if defined(MBEDTLS_USE_PSA_CRYPTO) #if !(defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384)) #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif #else /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_MD_C) || \ !(defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA384)) #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) #error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS_C) && \ !( defined(MBEDTLS_SSL_PROTO_TLS1_2) || defined(MBEDTLS_SSL_PROTO_TLS1_3) ) #error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) #error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) #error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \ MBEDTLS_SSL_CID_IN_LEN_MAX > 255 #error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \ MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 #error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && \ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS" #endif #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_2) #error "MBEDTLS_SSL_RENEGOTIATION defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TICKET_C) && ( !defined(MBEDTLS_CIPHER_C) && \ !defined(MBEDTLS_USE_PSA_CRYPTO) ) #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TICKET_C) && \ !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \ defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) ) #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) && \ MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH >= 256 #error "MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH must be less than 256" #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ !defined(MBEDTLS_X509_CRT_PARSE_C) #error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" #endif #if defined(MBEDTLS_THREADING_PTHREAD) #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" #endif #define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph #endif #if defined(MBEDTLS_THREADING_ALT) #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" #endif #define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph #endif #if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) #error "MBEDTLS_THREADING_C defined, single threading implementation required" #endif #undef MBEDTLS_THREADING_IMPL // temporary macro defined above #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_CLIENT) #error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" #endif #if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) #error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_USE_C) && \ (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_PK_PARSE_C) || \ ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) #error "MBEDTLS_X509_USE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CREATE_C) && \ (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ !defined(MBEDTLS_PK_PARSE_C) || \ ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) ) #error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) #error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) #error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) && \ ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) #error "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK defined, but not all prerequisites" #endif #if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) #error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" #endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ #if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ defined(MBEDTLS_HAVE_ASM) #error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" #endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ #if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) #error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ) #error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && ( !defined(MBEDTLS_SSL_PROTO_TLS1_3) ) #error "MBEDTLS_SSL_RECORD_SIZE_LIMIT defined, but not all prerequisites" #endif #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && \ !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \ defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) ) #error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites" #endif /* Reject attempts to enable options that have been removed and that could * cause a build to succeed but with features removed. */ #if defined(MBEDTLS_HAVEGE_C) //no-check-names #error "MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/2599" #endif #if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names #error "MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names #error "MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names #error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names #error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names #error "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates." #endif #if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names #error "MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4031" #endif #if defined(MBEDTLS_CHECK_PARAMS) //no-check-names #error "MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4313" #endif #if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names #error "MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" #endif #if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names #error "MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4335" #endif #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names #error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/Mbed-TLS/mbedtls/issues/4341" #endif #if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \ ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \ ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) || \ ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || \ ( !defined(MBEDTLS_MD_C) ) ) #error "MBEDTLS_PKCS7_C is defined, but not all prerequisites" #endif /* * Avoid warning from -pedantic. This is a convenient place for this * workaround since this is included by every single file before the * #if defined(MBEDTLS_xxx_C) that results in empty translation units. */ typedef int mbedtls_iso_c_forbids_empty_translation_units; /* *INDENT-ON* */ #endif /* MBEDTLS_CHECK_CONFIG_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h000066400000000000000000001517421464416617300244020ustar00rootroot00000000000000/** * \file cipher.h * * \brief This file contains an abstraction interface for use with the cipher * primitives provided by the library. It provides a common interface to all of * the available cipher operations. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CIPHER_H #define MBEDTLS_CIPHER_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include "mbedtls/platform_util.h" #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #define MBEDTLS_CIPHER_MODE_AEAD #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) #define MBEDTLS_CIPHER_MODE_WITH_PADDING #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ defined(MBEDTLS_CHACHA20_C) #define MBEDTLS_CIPHER_MODE_STREAM #endif /** The selected feature is not available. */ #define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /** Bad input parameters. */ #define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /** Failed to allocate memory. */ #define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /** Input data contains invalid padding and is rejected. */ #define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /** Decryption of block requires a full block. */ #define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /** Authentication failed (for AEAD modes). */ #define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /** The context is invalid. For example, because it was freed. */ #define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ #define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ #ifdef __cplusplus extern "C" { #endif /** * \brief Supported cipher types. * * \warning DES/3DES are considered weak ciphers and their use * constitutes a security risk. We recommend considering stronger * ciphers instead. */ typedef enum { MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. \warning DES is considered weak. */ MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ } mbedtls_cipher_id_t; /** * \brief Supported {cipher type, cipher mode} pairs. * * \warning DES/3DES are considered weak ciphers and their use * constitutes a security risk. We recommend considering stronger * ciphers instead. */ typedef enum { MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. \warning DES is considered weak. */ MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. \warning DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. \warning 3DES is considered weak. */ MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */ MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ } mbedtls_cipher_type_t; /** Supported cipher modes. */ typedef enum { MBEDTLS_MODE_NONE = 0, /**< None. */ MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ MBEDTLS_MODE_CCM_STAR_NO_TAG, /**< The CCM*-no-tag cipher mode. */ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ } mbedtls_cipher_mode_t; /** Supported cipher padding types. */ typedef enum { MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ } mbedtls_cipher_padding_t; /** Type of operation. */ typedef enum { MBEDTLS_OPERATION_NONE = -1, MBEDTLS_DECRYPT = 0, MBEDTLS_ENCRYPT, } mbedtls_operation_t; enum { /** Undefined key length. */ MBEDTLS_KEY_LENGTH_NONE = 0, /** Key length, in bits (including parity), for DES keys. \warning DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES = 64, /** Key length in bits, including parity, for DES in two-key EDE. \warning 3DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES_EDE = 128, /** Key length in bits, including parity, for DES in three-key EDE. \warning 3DES is considered weak. */ MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, }; /** Maximum length of any IV, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined * in library/ssl_misc.h. */ #define MBEDTLS_MAX_IV_LENGTH 16 /** Maximum block size of any cipher, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined * in library/ssl_misc.h. */ #define MBEDTLS_MAX_BLOCK_LENGTH 16 /** Maximum key length, in Bytes. */ /* This should ideally be derived automatically from list of ciphers. * For now, only check whether XTS is enabled which uses 64 Byte keys, * and use 32 Bytes as an upper bound for the maximum key length otherwise. * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined * in library/ssl_misc.h, which however deliberately ignores the case of XTS * since the latter isn't used in SSL/TLS. */ #if defined(MBEDTLS_CIPHER_MODE_XTS) #define MBEDTLS_MAX_KEY_LENGTH 64 #else #define MBEDTLS_MAX_KEY_LENGTH 32 #endif /* MBEDTLS_CIPHER_MODE_XTS */ /** * Base cipher information (opaque struct). */ typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; /** * CMAC context (opaque struct). */ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; /** * Cipher information. Allows calling cipher functions * in a generic way. * * \note The library does not support custom cipher info structures, * only built-in structures returned by the functions * mbedtls_cipher_info_from_string(), * mbedtls_cipher_info_from_type(), * mbedtls_cipher_info_from_values(), * mbedtls_cipher_info_from_psa(). * * \note Some fields store a value that has been right-shifted to save * code-size, so should not be used directly. The accessor * functions adjust for this and return the "natural" value. */ typedef struct mbedtls_cipher_info_t { /** Name of the cipher. */ const char *MBEDTLS_PRIVATE(name); /** The block size, in bytes. */ unsigned int MBEDTLS_PRIVATE(block_size) : 5; /** IV or nonce size, in bytes (right shifted by #MBEDTLS_IV_SIZE_SHIFT). * For ciphers that accept variable IV sizes, * this is the recommended size. */ unsigned int MBEDTLS_PRIVATE(iv_size) : 3; /** The cipher key length, in bits (right shifted by #MBEDTLS_KEY_BITLEN_SHIFT). * This is the default length for variable sized ciphers. * Includes parity bits for ciphers like DES. */ unsigned int MBEDTLS_PRIVATE(key_bitlen) : 4; /** The cipher mode (as per mbedtls_cipher_mode_t). * For example, MBEDTLS_MODE_CBC. */ unsigned int MBEDTLS_PRIVATE(mode) : 4; /** Full cipher identifier (as per mbedtls_cipher_type_t). * For example, MBEDTLS_CIPHER_AES_256_CBC. * * This could be 7 bits, but 8 bits retains byte alignment for the * next field, which reduces code size to access that field. */ unsigned int MBEDTLS_PRIVATE(type) : 8; /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the * cipher supports variable IV or variable key sizes, respectively. */ unsigned int MBEDTLS_PRIVATE(flags) : 2; /** Index to LUT for base cipher information and functions. */ unsigned int MBEDTLS_PRIVATE(base_idx) : 5; } mbedtls_cipher_info_t; /* For internal use only. * These are used to more compactly represent the fields above. */ #define MBEDTLS_KEY_BITLEN_SHIFT 6 #define MBEDTLS_IV_SIZE_SHIFT 2 /** * Generic cipher context. */ typedef struct mbedtls_cipher_context_t { /** Information about the associated cipher. */ const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info); /** Key length to use. */ int MBEDTLS_PRIVATE(key_bitlen); /** Operation that the key of the context has been * initialized for. */ mbedtls_operation_t MBEDTLS_PRIVATE(operation); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** Padding functions to use, if relevant for * the specific cipher mode. */ void(*MBEDTLS_PRIVATE(add_padding))(unsigned char *output, size_t olen, size_t data_len); int(*MBEDTLS_PRIVATE(get_padding))(unsigned char *input, size_t ilen, size_t *data_len); #endif /** Buffer for input that has not been processed yet. */ unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH]; /** Number of Bytes that have not been processed yet. */ size_t MBEDTLS_PRIVATE(unprocessed_len); /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number * for XTS-mode. */ unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH]; /** IV size in Bytes, for ciphers with variable-length IVs. */ size_t MBEDTLS_PRIVATE(iv_size); /** The cipher-specific context. */ void *MBEDTLS_PRIVATE(cipher_ctx); #if defined(MBEDTLS_CMAC_C) /** CMAC-specific context. */ mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx); #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** Indicates whether the cipher operations should be performed * by Mbed TLS' own crypto library or an external implementation * of the PSA Crypto API. * This is unset if the cipher context was established through * mbedtls_cipher_setup(), and set if it was established through * mbedtls_cipher_setup_psa(). */ unsigned char MBEDTLS_PRIVATE(psa_enabled); #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ } mbedtls_cipher_context_t; /** * \brief This function retrieves the list of ciphers supported * by the generic cipher module. * * For any cipher identifier in the returned list, you can * obtain the corresponding generic cipher information structure * via mbedtls_cipher_info_from_type(), which can then be used * to prepare a cipher context via mbedtls_cipher_setup(). * * * \return A statically-allocated array of cipher identifiers * of type cipher_type_t. The last entry is zero. */ const int *mbedtls_cipher_list(void); /** * \brief This function retrieves the cipher-information * structure associated with the given cipher name. * * \param cipher_name Name of the cipher to search for. This must not be * \c NULL. * * \return The cipher information structure associated with the * given \p cipher_name. * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_name); /** * \brief This function retrieves the cipher-information * structure associated with the given cipher type. * * \param cipher_type Type of the cipher to search for. * * \return The cipher information structure associated with the * given \p cipher_type. * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type); /** * \brief This function retrieves the cipher-information * structure associated with the given cipher ID, * key size and mode. * * \param cipher_id The ID of the cipher to search for. For example, * #MBEDTLS_CIPHER_ID_AES. * \param key_bitlen The length of the key in bits. * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. * * \return The cipher information structure associated with the * given \p cipher_id. * \return \c NULL if the associated cipher information is not found. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode); /** * \brief Retrieve the identifier for a cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. */ static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( const mbedtls_cipher_info_t *info) { if (info == NULL) { return MBEDTLS_CIPHER_NONE; } else { return (mbedtls_cipher_type_t) info->MBEDTLS_PRIVATE(type); } } /** * \brief Retrieve the operation mode for a cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The cipher mode (\c MBEDTLS_MODE_xxx). * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. */ static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( const mbedtls_cipher_info_t *info) { if (info == NULL) { return MBEDTLS_MODE_NONE; } else { return (mbedtls_cipher_mode_t) info->MBEDTLS_PRIVATE(mode); } } /** * \brief Retrieve the key size for a cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The key length in bits. * For variable-sized ciphers, this is the default length. * For DES, this includes the parity bits. * \return \c 0 if \p info is \c NULL. */ static inline size_t mbedtls_cipher_info_get_key_bitlen( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } else { return ((size_t) info->MBEDTLS_PRIVATE(key_bitlen)) << MBEDTLS_KEY_BITLEN_SHIFT; } } /** * \brief Retrieve the human-readable name for a * cipher info structure. * * \param[in] info The cipher info structure to query. * This may be \c NULL. * * \return The cipher name, which is a human readable string, * with static storage duration. * \return \c NULL if \p info is \c NULL. */ static inline const char *mbedtls_cipher_info_get_name( const mbedtls_cipher_info_t *info) { if (info == NULL) { return NULL; } else { return info->MBEDTLS_PRIVATE(name); } } /** * \brief This function returns the size of the IV or nonce * for the cipher info structure, in bytes. * * \param info The cipher info structure. This may be \c NULL. * * \return The recommended IV size. * \return \c 0 for ciphers not using an IV or a nonce. * \return \c 0 if \p info is \c NULL. */ static inline size_t mbedtls_cipher_info_get_iv_size( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return ((size_t) info->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT; } /** * \brief This function returns the block size of the given * cipher info structure in bytes. * * \param info The cipher info structure. This may be \c NULL. * * \return The block size of the cipher. * \return \c 1 if the cipher is a stream cipher. * \return \c 0 if \p info is \c NULL. */ static inline size_t mbedtls_cipher_info_get_block_size( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return (size_t) (info->MBEDTLS_PRIVATE(block_size)); } /** * \brief This function returns a non-zero value if the key length for * the given cipher is variable. * * \param info The cipher info structure. This may be \c NULL. * * \return Non-zero if the key length is variable, \c 0 otherwise. * \return \c 0 if the given pointer is \c NULL. */ static inline int mbedtls_cipher_info_has_variable_key_bitlen( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN; } /** * \brief This function returns a non-zero value if the IV size for * the given cipher is variable. * * \param info The cipher info structure. This may be \c NULL. * * \return Non-zero if the IV size is variable, \c 0 otherwise. * \return \c 0 if the given pointer is \c NULL. */ static inline int mbedtls_cipher_info_has_variable_iv_size( const mbedtls_cipher_info_t *info) { if (info == NULL) { return 0; } return info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN; } /** * \brief This function initializes a \p ctx as NONE. * * \param ctx The context to be initialized. This must not be \c NULL. */ void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx); /** * \brief This function frees and clears the cipher-specific * context of \p ctx. Freeing \p ctx itself remains the * responsibility of the caller. * * \param ctx The context to be freed. If this is \c NULL, the * function has no effect, otherwise this must point to an * initialized context. */ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx); /** * \brief Clone the state of an cipher context * * \note The two contexts must have been setup to the same type * (cloning from AES to DES make no sense). * * \param dst The destination context * \param src The context to be cloned * * \return \c 0 on success, * \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure. */ int mbedtls_cipher_clone(mbedtls_cipher_context_t *dst, const mbedtls_cipher_context_t *src); /** * \brief This function prepares a cipher context for * use with the given cipher primitive. * * \note After calling this function, you should call * mbedtls_cipher_setkey() and, if the mode uses padding, * mbedtls_cipher_set_padding_mode(), then for each * message to encrypt or decrypt with this key, either: * - mbedtls_cipher_crypt() for one-shot processing with * non-AEAD modes; * - mbedtls_cipher_auth_encrypt_ext() or * mbedtls_cipher_auth_decrypt_ext() for one-shot * processing with AEAD modes or NIST_KW; * - for multi-part processing, see the documentation of * mbedtls_cipher_reset(). * * \param ctx The context to prepare. This must be initialized by * a call to mbedtls_cipher_init() first. * \param cipher_info The cipher to use. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. */ int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); #if defined(MBEDTLS_USE_PSA_CRYPTO) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function initializes a cipher context for * PSA-based use with the given cipher primitive. * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use psa_aead_xxx() / psa_cipher_xxx() directly * instead. * * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. * * \param ctx The context to initialize. May not be \c NULL. * \param cipher_info The cipher to use. * \param taglen For AEAD ciphers, the length in bytes of the * authentication tag to use. Subsequent uses of * mbedtls_cipher_auth_encrypt_ext() or * mbedtls_cipher_auth_decrypt_ext() must provide * the same tag length. * For non-AEAD ciphers, the value must be \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the * cipher-specific context fails. */ int MBEDTLS_DEPRECATED mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, size_t taglen); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ /** * \brief setup the cipher info structure. * * \param ctx cipher's context. Must have been initialised. * \param cipher_info cipher to use. * * \return 0 on success, * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure */ int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); /** * \brief This function returns the block size of the given cipher * in bytes. * * \param ctx The context of the cipher. * * \return The block size of the underlying cipher. * \return \c 1 if the cipher is a stream cipher. * \return \c 0 if \p ctx has not been initialized. */ static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } return (unsigned int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size); } /** * \brief This function returns the mode of operation for * the cipher. For example, MBEDTLS_MODE_CBC. * * \param ctx The context of the cipher. This must be initialized. * * \return The mode of operation. * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. */ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_MODE_NONE; } return (mbedtls_cipher_mode_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode); } /** * \brief This function returns the size of the IV or nonce * of the cipher, in Bytes. * * \param ctx The context of the cipher. This must be initialized. * * \return The recommended IV size if no IV has been set. * \return \c 0 for ciphers not using an IV or a nonce. * \return The actual size if an IV has been set. */ static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } if (ctx->MBEDTLS_PRIVATE(iv_size) != 0) { return (int) ctx->MBEDTLS_PRIVATE(iv_size); } return (int) (((int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT); } /** * \brief This function returns the type of the given cipher. * * \param ctx The context of the cipher. This must be initialized. * * \return The type of the cipher. * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. */ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_CIPHER_NONE; } return (mbedtls_cipher_type_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type); } /** * \brief This function returns the name of the given cipher * as a string. * * \param ctx The context of the cipher. This must be initialized. * * \return The name of the cipher. * \return NULL if \p ctx has not been not initialized. */ static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return 0; } return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(name); } /** * \brief This function returns the key length of the cipher. * * \param ctx The context of the cipher. This must be initialized. * * \return The key length of the cipher in bits. * \return #MBEDTLS_KEY_LENGTH_NONE if \p ctx has not been * initialized. */ static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_KEY_LENGTH_NONE; } return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen) << MBEDTLS_KEY_BITLEN_SHIFT; } /** * \brief This function returns the operation of the given cipher. * * \param ctx The context of the cipher. This must be initialized. * * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. */ static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx) { if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) { return MBEDTLS_OPERATION_NONE; } return ctx->MBEDTLS_PRIVATE(operation); } /** * \brief This function sets the key to use with the given context. * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param key The key to use. This must be a readable buffer of at * least \p key_bitlen Bits. * \param key_bitlen The key length to use, in Bits. * \param operation The operation that the key will be used for: * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation); #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /** * \brief This function sets the padding mode, for cipher modes * that use padding. * * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param mode The padding mode. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE * if the selected padding mode is not supported. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * does not support padding. */ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode); #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ /** * \brief This function sets the initialization vector (IV) * or nonce. * * \note Some ciphers do not use IVs nor nonce. For these * ciphers, this function has no effect. * * \note For #MBEDTLS_CIPHER_CHACHA20, the nonce length must * be 12, and the initial counter value is 0. * * \note For #MBEDTLS_CIPHER_CHACHA20_POLY1305, the nonce length * must be 12. * * \param ctx The generic cipher context. This must be initialized and * bound to a cipher information structure. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This * must be a readable buffer of at least \p iv_len Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size IV. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. */ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len); /** * \brief This function resets the cipher state. * * \note With non-AEAD ciphers, the order of calls for each message * is as follows: * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update() one or more times * 4. mbedtls_cipher_finish() * . * This sequence can be repeated to encrypt or decrypt multiple * messages with the same key. * * \note With AEAD ciphers, the order of calls for each message * is as follows: * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update_ad() * 4. mbedtls_cipher_update() one or more times * 5. mbedtls_cipher_finish() * 6. mbedtls_cipher_check_tag() (for decryption) or * mbedtls_cipher_write_tag() (for encryption). * . * This sequence can be repeated to encrypt or decrypt multiple * messages with the same key. * * \param ctx The generic cipher context. This must be bound to a key. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. */ int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function adds additional data for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. * * \param ctx The generic cipher context. This must be initialized. * \param ad The additional data to use. This must be a readable * buffer of at least \p ad_len Bytes. * \param ad_len The length of \p ad in Bytes. * * \return \c 0 on success. * \return A specific error code on failure. */ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len); #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic cipher update function. It encrypts or * decrypts using the given cipher context. Writes as * many block-sized blocks of data as possible to output. * Any data that cannot be written immediately is either * added to the next block, or flushed when * mbedtls_cipher_finish() is called. * Exception: For MBEDTLS_MODE_ECB, expects a single block * in size. For example, 16 Bytes for AES. * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data. * \param output The buffer for the output data. This must be able to * hold at least `ilen + block_size`. This must not be the * same buffer as \p input. * \param olen The length of the output data, to be updated with the * actual number of Bytes written. This must not be * \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an * unsupported mode for a cipher. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); /** * \brief The generic cipher finalization function. If data still * needs to be flushed from an incomplete block, the data * contained in it is padded to the size of * the last block, and written to the \p output buffer. * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param output The buffer to write data to. This needs to be a writable * buffer of at least block_size Bytes. * \param olen The length of the data written to the \p output buffer. * This may not be \c NULL. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption * expecting a full block but not receiving one. * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding * while decrypting. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen); #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function writes a tag for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. * This must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. This must be initialized, * bound to a key, and have just completed a cipher * operation through mbedtls_cipher_finish() the tag for * which should be written. * \param tag The buffer to write the tag to. This must be a writable * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to write. * * \return \c 0 on success. * \return A specific error code on failure. */ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len); /** * \brief This function checks the tag for AEAD ciphers. * Currently supported with GCM and ChaCha20+Poly1305. * This must be called after mbedtls_cipher_finish(). * * \param ctx The generic cipher context. This must be initialized. * \param tag The buffer holding the tag. This must be a readable * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to check. * * \return \c 0 on success. * \return A specific error code on failure. */ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len); #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /** * \brief The generic all-in-one encryption/decryption function, * for all ciphers except AEAD constructs. * * \param ctx The generic cipher context. This must be initialized. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * This must be a readable buffer of at least \p iv_len * Bytes. * \param iv_len The IV length for ciphers with variable-size IV. * This parameter is discarded by ciphers with fixed-size * IV. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The buffer for the output data. This must be able to * hold at least `ilen + block_size`. This must not be the * same buffer as \p input. * \param olen The length of the output data, to be updated with the * actual number of Bytes written. This must not be * \c NULL. * * \note Some ciphers do not use IVs nor nonce. For these * ciphers, use \p iv = NULL and \p iv_len = 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption * expecting a full block but not receiving one. * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding * while decrypting. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen); #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) /** * \brief The authenticated encryption (AEAD/NIST_KW) function. * * \note For AEAD modes, the tag will be appended to the * ciphertext, as recommended by RFC 5116. * (NIST_KW doesn't have a separate tag.) * * \param ctx The generic cipher context. This must be initialized and * bound to a key, with an AEAD algorithm or NIST_KW. * \param iv The nonce to use. This must be a readable buffer of * at least \p iv_len Bytes and may be \c NULL if \p * iv_len is \c 0. * \param iv_len The length of the nonce. For AEAD ciphers, this must * satisfy the constraints imposed by the cipher used. * For NIST_KW, this must be \c 0. * \param ad The additional data to authenticate. This must be a * readable buffer of at least \p ad_len Bytes, and may * be \c NULL is \p ad_len is \c 0. * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes, and may be * \c NULL if \p ilen is \c 0. * \param ilen The length of the input data. * \param output The buffer for the output data. This must be a * writable buffer of at least \p output_len Bytes, and * must not be \c NULL. * \param output_len The length of the \p output buffer in Bytes. For AEAD * ciphers, this must be at least \p ilen + \p tag_len. * For NIST_KW, this must be at least \p ilen + 8 * (rounded up to a multiple of 8 if KWP is used); * \p ilen + 15 is always a safe value. * \param olen This will be filled with the actual number of Bytes * written to the \p output buffer. This must point to a * writable object of type \c size_t. * \param tag_len The desired length of the authentication tag. For AEAD * ciphers, this must match the constraints imposed by * the cipher used, and in particular must not be \c 0. * For NIST_KW, this must be \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len); /** * \brief The authenticated encryption (AEAD/NIST_KW) function. * * \note If the data is not authentic, then the output buffer * is zeroed out to prevent the unauthentic plaintext being * used, making this interface safer. * * \note For AEAD modes, the tag must be appended to the * ciphertext, as recommended by RFC 5116. * (NIST_KW doesn't have a separate tag.) * * \param ctx The generic cipher context. This must be initialized and * bound to a key, with an AEAD algorithm or NIST_KW. * \param iv The nonce to use. This must be a readable buffer of * at least \p iv_len Bytes and may be \c NULL if \p * iv_len is \c 0. * \param iv_len The length of the nonce. For AEAD ciphers, this must * satisfy the constraints imposed by the cipher used. * For NIST_KW, this must be \c 0. * \param ad The additional data to authenticate. This must be a * readable buffer of at least \p ad_len Bytes, and may * be \c NULL is \p ad_len is \c 0. * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. * \param input The buffer holding the input data. This must be a * readable buffer of at least \p ilen Bytes, and may be * \c NULL if \p ilen is \c 0. * \param ilen The length of the input data. For AEAD ciphers this * must be at least \p tag_len. For NIST_KW this must be * at least \c 8. * \param output The buffer for the output data. This must be a * writable buffer of at least \p output_len Bytes, and * may be \c NULL if \p output_len is \c 0. * \param output_len The length of the \p output buffer in Bytes. For AEAD * ciphers, this must be at least \p ilen - \p tag_len. * For NIST_KW, this must be at least \p ilen - 8. * \param olen This will be filled with the actual number of Bytes * written to the \p output buffer. This must point to a * writable object of type \c size_t. * \param tag_len The actual length of the authentication tag. For AEAD * ciphers, this must match the constraints imposed by * the cipher used, and in particular must not be \c 0. * For NIST_KW, this must be \c 0. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * parameter-verification failure. * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len); #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CIPHER_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h000066400000000000000000000251421464416617300240250ustar00rootroot00000000000000/** * \file cmac.h * * \brief This file contains CMAC definitions and functions. * * The Cipher-based Message Authentication Code (CMAC) Mode for * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. * It is supported with AES and DES. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #ifdef __cplusplus extern "C" { #endif #define MBEDTLS_AES_BLOCK_SIZE 16 #define MBEDTLS_DES3_BLOCK_SIZE 8 /* We don't support Camellia or ARIA in this module */ #if defined(MBEDTLS_AES_C) #define MBEDTLS_CMAC_MAX_BLOCK_SIZE 16 /**< The longest block used by CMAC is that of AES. */ #else #define MBEDTLS_CMAC_MAX_BLOCK_SIZE 8 /**< The longest block used by CMAC is that of 3DES. */ #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** The longest block supported by the cipher module. * * \deprecated * For the maximum block size of a cipher supported by the CMAC module, * use #MBEDTLS_CMAC_MAX_BLOCK_SIZE. * For the maximum block size of a cipher supported by the cipher module, * use #MBEDTLS_MAX_BLOCK_LENGTH. */ /* Before Mbed TLS 3.5, this was the maximum block size supported by the CMAC * module, so it didn't take Camellia or ARIA into account. Since the name * of the macro doesn't even convey "CMAC", this was misleading. Now the size * is sufficient for any cipher, but the name is defined in cmac.h for * backward compatibility. */ #define MBEDTLS_CIPHER_BLKSIZE_MAX MBEDTLS_MAX_BLOCK_LENGTH #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if !defined(MBEDTLS_CMAC_ALT) /** * The CMAC context structure. */ struct mbedtls_cmac_context_t { /** The internal state of the CMAC algorithm. */ unsigned char MBEDTLS_PRIVATE(state)[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; /** Unprocessed data - either data that was not block aligned and is still * pending processing, or the final block. */ unsigned char MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; /** The length of data pending processing. */ size_t MBEDTLS_PRIVATE(unprocessed_len); }; #else /* !MBEDTLS_CMAC_ALT */ #include "cmac_alt.h" #endif /* !MBEDTLS_CMAC_ALT */ /** * \brief Initialises and allocate CMAC context memory * Must be called with an initialized cipher context. * * \param ctx The cipher context used for the CMAC operation, initialized * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, * or MBEDTLS_CIPHER_DES_EDE3_ECB. * \return \c 0 on success. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx); /** * \brief This function starts a new CMAC computation * by setting the CMAC key, and preparing to authenticate * the input data. * It must be called with an initialized cipher context. * * Once this function has completed, data can be supplied * to the CMAC computation by calling * mbedtls_cipher_cmac_update(). * * To start a CMAC computation using the same key as a previous * CMAC computation, use mbedtls_cipher_cmac_finish(). * * \note When the CMAC implementation is supplied by an alternate * implementation (through #MBEDTLS_CMAC_ALT), some ciphers * may not be supported by that implementation, and thus * return an error. Alternate implementations must support * AES-128 and AES-256, and may support AES-192 and 3DES. * * \param ctx The cipher context used for the CMAC operation, initialized * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, * or MBEDTLS_CIPHER_DES_EDE3_ECB. * \param key The CMAC key. * \param keybits The length of the CMAC key in bits. * Must be supported by the cipher. * * \return \c 0 on success. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits); /** * \brief This function feeds an input buffer into an ongoing CMAC * computation. * * The CMAC computation must have previously been started * by calling mbedtls_cipher_cmac_starts() or * mbedtls_cipher_cmac_reset(). * * Call this function as many times as needed to input the * data to be authenticated. * Once all of the required data has been input, * call mbedtls_cipher_cmac_finish() to obtain the result * of the CMAC operation. * * \param ctx The cipher context used for the CMAC operation. * \param input The buffer holding the input data. * \param ilen The length of the input data. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes an ongoing CMAC operation, and * writes the result to the output buffer. * * It should be followed either by * mbedtls_cipher_cmac_reset(), which starts another CMAC * operation with the same key, or mbedtls_cipher_free(), * which clears the cipher context. * * \param ctx The cipher context used for the CMAC operation. * \param output The output buffer for the CMAC checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, unsigned char *output); /** * \brief This function starts a new CMAC operation with the same * key as the previous one. * * It should be called after finishing the previous CMAC * operation with mbedtls_cipher_cmac_finish(). * After calling this function, * call mbedtls_cipher_cmac_update() to supply the new * CMAC operation with data. * * \param ctx The cipher context used for the CMAC operation. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx); /** * \brief This function calculates the full generic CMAC * on the input buffer with the provided key. * * The function allocates the context, performs the * calculation, and frees the context. * * The CMAC result is calculated as * output = generic CMAC(cmac key, input buffer). * * \note When the CMAC implementation is supplied by an alternate * implementation (through #MBEDTLS_CMAC_ALT), some ciphers * may not be supported by that implementation, and thus * return an error. Alternate implementations must support * AES-128 and AES-256, and may support AES-192 and 3DES. * * \param cipher_info The cipher information. * \param key The CMAC key. * \param keylen The length of the CMAC key in bits. * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The buffer for the generic CMAC result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * if parameter verification fails. */ int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output); #if defined(MBEDTLS_AES_C) /** * \brief This function implements the AES-CMAC-PRF-128 pseudorandom * function, as defined in * RFC-4615: The Advanced Encryption Standard-Cipher-based * Message Authentication Code-Pseudo-Random Function-128 * (AES-CMAC-PRF-128) Algorithm for the Internet Key * Exchange Protocol (IKE). * * \param key The key to use. * \param key_len The key length in Bytes. * \param input The buffer holding the input data. * \param in_len The length of the input data in Bytes. * \param output The buffer holding the generated 16 Bytes of * pseudorandom output. * * \return \c 0 on success. */ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_len, const unsigned char *input, size_t in_len, unsigned char output[16]); #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_SELF_TEST) && (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C)) /** * \brief The CMAC checkup routine. * * \note In case the CMAC routines are provided by an alternative * implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the * checkup routine will succeed even if the implementation does * not support the less widely used AES-192 or 3DES primitives. * The self-test requires at least AES-128 and AES-256 to be * supported by the underlying implementation. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_cmac_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_CMAC_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h000066400000000000000000000033071464416617300250110ustar00rootroot00000000000000/** * \file compat-2.x.h * * \brief Compatibility definitions * * \deprecated Use the new names directly instead */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if defined(MBEDTLS_DEPRECATED_WARNING) #warning "Including compat-2.x.h is deprecated" #endif #ifndef MBEDTLS_COMPAT2X_H #define MBEDTLS_COMPAT2X_H /* * Macros for renamed functions */ #define mbedtls_ctr_drbg_update_ret mbedtls_ctr_drbg_update #define mbedtls_hmac_drbg_update_ret mbedtls_hmac_drbg_update #define mbedtls_md5_starts_ret mbedtls_md5_starts #define mbedtls_md5_update_ret mbedtls_md5_update #define mbedtls_md5_finish_ret mbedtls_md5_finish #define mbedtls_md5_ret mbedtls_md5 #define mbedtls_ripemd160_starts_ret mbedtls_ripemd160_starts #define mbedtls_ripemd160_update_ret mbedtls_ripemd160_update #define mbedtls_ripemd160_finish_ret mbedtls_ripemd160_finish #define mbedtls_ripemd160_ret mbedtls_ripemd160 #define mbedtls_sha1_starts_ret mbedtls_sha1_starts #define mbedtls_sha1_update_ret mbedtls_sha1_update #define mbedtls_sha1_finish_ret mbedtls_sha1_finish #define mbedtls_sha1_ret mbedtls_sha1 #define mbedtls_sha256_starts_ret mbedtls_sha256_starts #define mbedtls_sha256_update_ret mbedtls_sha256_update #define mbedtls_sha256_finish_ret mbedtls_sha256_finish #define mbedtls_sha256_ret mbedtls_sha256 #define mbedtls_sha512_starts_ret mbedtls_sha512_starts #define mbedtls_sha512_update_ret mbedtls_sha512_update #define mbedtls_sha512_finish_ret mbedtls_sha512_finish #define mbedtls_sha512_ret mbedtls_sha512 #endif /* MBEDTLS_COMPAT2X_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h000066400000000000000000000417711464416617300306730ustar00rootroot00000000000000/** * \file mbedtls/config_adjust_legacy_crypto.h * \brief Adjust legacy configuration configuration * * Automatically enable certain dependencies. Generally, MBEDLTS_xxx * configurations need to be explicitly enabled by the user: enabling * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a * compilation error. However, we do automatically enable certain options * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option * used to identify parts of a module that are used by other module, and we * don't want to make the symbol MBEDTLS_xxx_B part of the public API. * Another case is if A didn't depend on B in earlier versions, and we * want to use B in A but we need to preserve backward compatibility with * configurations that explicitly activate MBEDTLS_xxx_A but not * MBEDTLS_xxx_B. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H #define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H /* Ideally, we'd set those as defaults in mbedtls_config.h, but * putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py. * * So, adjust it here. * Not related to crypto, but this is the bottom of the stack. */ #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define MBEDTLS_PLATFORM_SNPRINTF_ALT #endif #if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) #define MBEDTLS_PLATFORM_VSNPRINTF_ALT #endif #endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */ /* Auto-enable CIPHER_C when any of the unauthenticated ciphers is builtin * in PSA. */ #if defined(MBEDTLS_PSA_CRYPTO_C) && \ (defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)) #define MBEDTLS_CIPHER_C #endif /* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C. * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C. */ #if defined(MBEDTLS_MD_C) #define MBEDTLS_MD_LIGHT #endif /* Auto-enable MBEDTLS_MD_LIGHT if needed by a module that didn't require it * in a previous release, to ensure backwards compatibility. */ #if defined(MBEDTLS_ECJPAKE_C) || \ defined(MBEDTLS_PEM_PARSE_C) || \ defined(MBEDTLS_ENTROPY_C) || \ defined(MBEDTLS_PK_C) || \ defined(MBEDTLS_PKCS12_C) || \ defined(MBEDTLS_RSA_C) || \ defined(MBEDTLS_SSL_TLS_C) || \ defined(MBEDTLS_X509_USE_C) || \ defined(MBEDTLS_X509_CREATE_C) #define MBEDTLS_MD_LIGHT #endif #if defined(MBEDTLS_MD_LIGHT) /* * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx. * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA * (see below). * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed * via PSA (see below). * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed * via a direct legacy call (see below). * * The md module performs an algorithm via PSA if there is a PSA hash * accelerator and the PSA driver subsytem is initialized at the time the * operation is started, and makes a direct legacy call otherwise. */ /* PSA accelerated implementations */ #if defined(MBEDTLS_PSA_CRYPTO_C) #if defined(MBEDTLS_PSA_ACCEL_ALG_MD5) #define MBEDTLS_MD_CAN_MD5 #define MBEDTLS_MD_MD5_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) #define MBEDTLS_MD_CAN_SHA1 #define MBEDTLS_MD_SHA1_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) #define MBEDTLS_MD_CAN_SHA224 #define MBEDTLS_MD_SHA224_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) #define MBEDTLS_MD_CAN_SHA256 #define MBEDTLS_MD_SHA256_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) #define MBEDTLS_MD_CAN_SHA384 #define MBEDTLS_MD_SHA384_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) #define MBEDTLS_MD_CAN_SHA512 #define MBEDTLS_MD_SHA512_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) #define MBEDTLS_MD_CAN_RIPEMD160 #define MBEDTLS_MD_RIPEMD160_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224) #define MBEDTLS_MD_CAN_SHA3_224 #define MBEDTLS_MD_SHA3_224_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256) #define MBEDTLS_MD_CAN_SHA3_256 #define MBEDTLS_MD_SHA3_256_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384) #define MBEDTLS_MD_CAN_SHA3_384 #define MBEDTLS_MD_SHA3_384_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512) #define MBEDTLS_MD_CAN_SHA3_512 #define MBEDTLS_MD_SHA3_512_VIA_PSA #define MBEDTLS_MD_SOME_PSA #endif #endif /* MBEDTLS_PSA_CRYPTO_C */ /* Built-in implementations */ #if defined(MBEDTLS_MD5_C) #define MBEDTLS_MD_CAN_MD5 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA1_C) #define MBEDTLS_MD_CAN_SHA1 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA224_C) #define MBEDTLS_MD_CAN_SHA224 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA256_C) #define MBEDTLS_MD_CAN_SHA256 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA384_C) #define MBEDTLS_MD_CAN_SHA384 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA512_C) #define MBEDTLS_MD_CAN_SHA512 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_SHA3_C) #define MBEDTLS_MD_CAN_SHA3_224 #define MBEDTLS_MD_CAN_SHA3_256 #define MBEDTLS_MD_CAN_SHA3_384 #define MBEDTLS_MD_CAN_SHA3_512 #define MBEDTLS_MD_SOME_LEGACY #endif #if defined(MBEDTLS_RIPEMD160_C) #define MBEDTLS_MD_CAN_RIPEMD160 #define MBEDTLS_MD_SOME_LEGACY #endif #endif /* MBEDTLS_MD_LIGHT */ /* BLOCK_CIPHER module can dispatch to PSA when: * - PSA is enabled and drivers have been initialized * - desired key type is supported on the PSA side * If the above conditions are not met, but the legacy support is enabled, then * BLOCK_CIPHER will dynamically fallback to it. * * In case BLOCK_CIPHER is defined (see below) the following symbols/helpers * can be used to define its capabilities: * - MBEDTLS_BLOCK_CIPHER_SOME_PSA: there is at least 1 key type between AES, * ARIA and Camellia which is supported through a driver; * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_PSA: xxx key type is supported through a * driver; * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_LEGACY: xxx key type is supported through * a legacy module (i.e. MBEDTLS_xxx_C) */ #if defined(MBEDTLS_PSA_CRYPTO_C) #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) #define MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA #define MBEDTLS_BLOCK_CIPHER_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) #define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA #define MBEDTLS_BLOCK_CIPHER_SOME_PSA #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) #define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA #define MBEDTLS_BLOCK_CIPHER_SOME_PSA #endif #endif /* MBEDTLS_PSA_CRYPTO_C */ #if defined(MBEDTLS_AES_C) #define MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY #endif #if defined(MBEDTLS_ARIA_C) #define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY #endif #if defined(MBEDTLS_CAMELLIA_C) #define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY #endif /* Helpers to state that BLOCK_CIPHER module supports AES, ARIA and/or Camellia * block ciphers via either PSA or legacy. */ #if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) || \ defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY) #define MBEDTLS_BLOCK_CIPHER_CAN_AES #endif #if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) || \ defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY) #define MBEDTLS_BLOCK_CIPHER_CAN_ARIA #endif #if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) || \ defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY) #define MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA #endif /* GCM_C and CCM_C can either depend on (in order of preference) BLOCK_CIPHER_C * or CIPHER_C. The former is auto-enabled when: * - CIPHER_C is not defined, which is also the legacy solution; * - BLOCK_CIPHER_SOME_PSA because in this case BLOCK_CIPHER can take advantage * of the driver's acceleration. */ #if (defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)) && \ (!defined(MBEDTLS_CIPHER_C) || defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)) #define MBEDTLS_BLOCK_CIPHER_C #endif /* Helpers for GCM/CCM capabilities */ #if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_AES)) #define MBEDTLS_CCM_GCM_CAN_AES #endif #if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_ARIA_C)) || \ (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_ARIA)) #define MBEDTLS_CCM_GCM_CAN_ARIA #endif #if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_CAMELLIA_C)) || \ (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA)) #define MBEDTLS_CCM_GCM_CAN_CAMELLIA #endif /* MBEDTLS_ECP_LIGHT is auto-enabled by the following symbols: * - MBEDTLS_ECP_C because now it consists of MBEDTLS_ECP_LIGHT plus functions * for curve arithmetic. As a consequence if MBEDTLS_ECP_C is required for * some reason, then MBEDTLS_ECP_LIGHT should be enabled as well. * - MBEDTLS_PK_PARSE_EC_EXTENDED and MBEDTLS_PK_PARSE_EC_COMPRESSED because * these features are not supported in PSA so the only way to have them is * to enable the built-in solution. * Both of them are temporary dependencies: * - PK_PARSE_EC_EXTENDED will be removed after #7779 and #7789 * - support for compressed points should also be added to PSA, but in this * case there is no associated issue to track it yet. * - PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE because Weierstrass key derivation * still depends on ECP_LIGHT. * - PK_C + USE_PSA + PSA_WANT_ALG_ECDSA is a temporary dependency which will * be fixed by #7453. */ #if defined(MBEDTLS_ECP_C) || \ defined(MBEDTLS_PK_PARSE_EC_EXTENDED) || \ defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define MBEDTLS_ECP_LIGHT #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while * in previous version compressed points were automatically supported as long * as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward * compatibility, we auto-enable PK_PARSE_EC_COMPRESSED when these conditions * are met. */ #if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_ECP_C) #define MBEDTLS_PK_PARSE_EC_COMPRESSED #endif /* Helper symbol to state that there is support for ECDH, either through * library implementation (ECDH_C) or through PSA. */ #if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \ (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)) #define MBEDTLS_CAN_ECDH #endif /* PK module can achieve ECDSA functionalities by means of either software * implementations (ECDSA_C) or through a PSA driver. The following defines * are meant to list these capabilities in a general way which abstracts how * they are implemented under the hood. */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_ECDSA_C) #define MBEDTLS_PK_CAN_ECDSA_SIGN #define MBEDTLS_PK_CAN_ECDSA_VERIFY #endif /* MBEDTLS_ECDSA_C */ #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(PSA_WANT_ALG_ECDSA) #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define MBEDTLS_PK_CAN_ECDSA_SIGN #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #define MBEDTLS_PK_CAN_ECDSA_VERIFY #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ #endif /* PSA_WANT_ALG_ECDSA */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN) #define MBEDTLS_PK_CAN_ECDSA_SOME #endif /* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT * is defined as well to include all PSA code. */ #if defined(MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_CLIENT #endif /* MBEDTLS_PSA_CRYPTO_C */ /* Helpers to state that each key is supported either on the builtin or PSA side. */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521) #define MBEDTLS_ECP_HAVE_SECP521R1 #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #define MBEDTLS_ECP_HAVE_BP512R1 #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448) #define MBEDTLS_ECP_HAVE_CURVE448 #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #define MBEDTLS_ECP_HAVE_BP384R1 #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384) #define MBEDTLS_ECP_HAVE_SECP384R1 #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #define MBEDTLS_ECP_HAVE_BP256R1 #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256) #define MBEDTLS_ECP_HAVE_SECP256K1 #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256) #define MBEDTLS_ECP_HAVE_SECP256R1 #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255) #define MBEDTLS_ECP_HAVE_CURVE25519 #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224) #define MBEDTLS_ECP_HAVE_SECP224K1 #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224) #define MBEDTLS_ECP_HAVE_SECP224R1 #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192) #define MBEDTLS_ECP_HAVE_SECP192K1 #endif #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192) #define MBEDTLS_ECP_HAVE_SECP192R1 #endif /* Helper symbol to state that the PK module has support for EC keys. This * can either be provided through the legacy ECP solution or through the * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA (see pk.h for its description). */ #if defined(MBEDTLS_ECP_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #define MBEDTLS_PK_HAVE_ECC_KEYS #endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */ /* Historically pkparse did not check the CBC padding when decrypting * a key. This was a bug, which is now fixed. As a consequence, pkparse * now needs PKCS7 padding support, but existing configurations might not * enable it, so we enable it here. */ #if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) #define MBEDTLS_CIPHER_PADDING_PKCS7 #endif /* Backwards compatibility for some macros which were renamed to reflect that * they are related to Armv8, not aarch64. */ #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \ !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) #define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY #endif /* psa_util file features some ECDSA conversion functions, to convert between * legacy's ASN.1 DER format and PSA's raw one. */ #if defined(MBEDTLS_ECDSA_C) || (defined(MBEDTLS_PSA_CRYPTO_C) && \ (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA))) #define MBEDTLS_PSA_UTIL_HAVE_ECDSA #endif /* Some internal helpers to determine which keys are availble. */ #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_SSL_HAVE_AES #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ARIA_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ARIA)) #define MBEDTLS_SSL_HAVE_ARIA #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CAMELLIA_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_CAMELLIA)) #define MBEDTLS_SSL_HAVE_CAMELLIA #endif /* Some internal helpers to determine which operation modes are availble. */ #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING)) #define MBEDTLS_SSL_HAVE_CBC #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM)) #define MBEDTLS_SSL_HAVE_GCM #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CCM_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM)) #define MBEDTLS_SSL_HAVE_CCM #endif #if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CHACHAPOLY_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305)) #define MBEDTLS_SSL_HAVE_CHACHAPOLY #endif #if defined(MBEDTLS_SSL_HAVE_GCM) || defined(MBEDTLS_SSL_HAVE_CCM) || \ defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) #define MBEDTLS_SSL_HAVE_AEAD #endif #endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h000066400000000000000000001043441464416617300311550ustar00rootroot00000000000000/** * \file mbedtls/config_adjust_legacy_from_psa.h * \brief Adjust PSA configuration: activate legacy implementations * * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations * of cryptographic mechanisms as needed to fulfill the needs of the PSA * configuration. Generally speaking, we activate a legacy mechanism if * it's needed for a requested PSA mechanism and there is no PSA driver * for it. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H #define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H /* Define appropriate ACCEL macros for the p256-m driver. * In the future, those should be generated from the drivers JSON description. */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 #define MBEDTLS_PSA_ACCEL_ALG_ECDSA #define MBEDTLS_PSA_ACCEL_ALG_ECDH #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE #endif /* * ECC: support for a feature is controlled by a triplet or a pair: * (curve, key_type public/basic, alg) or (curve, key_type_). * * A triplet/pair is accelerated if all of is components are accelerated; * otherwise each component needs to be built in. * * We proceed in two passes: * 1. Check if acceleration is complete for curves, key types, algs. * 2. Then enable built-ins for each thing that's either not accelerated of * doesn't have complete acceleration of the other triplet/pair components. * * Note: this needs psa/crypto_adjust_keypair_types.h to have been included * already, so that we know the full set of key types that are requested. */ /* ECC: curves: is acceleration complete? */ #if (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) && \ !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256)) || \ (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) && \ !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384)) || \ (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) && \ !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512)) || \ (defined(PSA_WANT_ECC_SECP_R1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192)) || \ (defined(PSA_WANT_ECC_SECP_R1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224)) || \ (defined(PSA_WANT_ECC_SECP_R1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256)) || \ (defined(PSA_WANT_ECC_SECP_R1_384) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384)) || \ (defined(PSA_WANT_ECC_SECP_R1_521) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)) || \ (defined(PSA_WANT_ECC_SECP_K1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192)) || \ (defined(PSA_WANT_ECC_SECP_K1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224)) || \ (defined(PSA_WANT_ECC_SECP_K1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES #endif #if (defined(PSA_WANT_ECC_MONTGOMERY_255) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255)) || \ (defined(PSA_WANT_ECC_MONTGOMERY_448) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES #endif /* ECC: algs: is acceleration complete? */ #if (defined(PSA_WANT_ALG_ECDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)) || \ (defined(PSA_WANT_ALG_ECDSA) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)) || \ (defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)) || \ (defined(PSA_WANT_ALG_JPAKE) && !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS #endif /* ECC: key types: is acceleration complete? */ #if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC #endif /* Special case: we don't support cooked key derivation in drivers yet */ #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #undef MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE #endif /* Note: the condition about key derivation is always true as DERIVE can't be * accelerated yet */ #if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)) || \ (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) #define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES #endif /* ECC: curves: enable built-ins as needed. * * We need the curve built-in: * - if it's not accelerated, or * - if there's a key type with missing acceleration, or * - if there's a alg with missing acceleration. */ #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 #define MBEDTLS_ECP_DP_BP256R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 #define MBEDTLS_ECP_DP_BP384R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 #define MBEDTLS_ECP_DP_BP512R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ #if defined(PSA_WANT_ECC_MONTGOMERY_255) #if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 #define MBEDTLS_ECP_DP_CURVE25519_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_MONTGOMERY_255 */ #if defined(PSA_WANT_ECC_MONTGOMERY_448) #if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 #define MBEDTLS_ECP_DP_CURVE448_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_MONTGOMERY_448 */ #if defined(PSA_WANT_ECC_SECP_R1_192) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_192 */ #if defined(PSA_WANT_ECC_SECP_R1_224) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 #define MBEDTLS_ECP_DP_SECP224R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_224 */ #if defined(PSA_WANT_ECC_SECP_R1_256) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_256 */ #if defined(PSA_WANT_ECC_SECP_R1_384) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 #define MBEDTLS_ECP_DP_SECP384R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_384 */ #if defined(PSA_WANT_ECC_SECP_R1_521) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 #define MBEDTLS_ECP_DP_SECP521R1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_R1_521 */ #if defined(PSA_WANT_ECC_SECP_K1_192) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 #define MBEDTLS_ECP_DP_SECP192K1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_K1_192 */ #if defined(PSA_WANT_ECC_SECP_K1_224) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 #define MBEDTLS_ECP_DP_SECP224K1_ENABLED /* https://github.com/Mbed-TLS/mbedtls/issues/3541 */ #error "SECP224K1 is buggy via the PSA API in Mbed TLS." #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_K1_224 */ #if defined(PSA_WANT_ECC_SECP_K1_256) #if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #endif /* missing accel */ #endif /* PSA_WANT_ECC_SECP_K1_256 */ /* ECC: algs: enable built-ins as needed. * * We need the alg built-in: * - if it's not accelerated, or * - if there's a relevant curve (see below) with missing acceleration, or * - if there's a key type among (public, basic) with missing acceleration. * * Relevant curves are: * - all curves for ECDH * - Weierstrass curves for (deterministic) ECDSA * - secp256r1 for EC J-PAKE */ #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) #if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 #define MBEDTLS_ECDSA_DETERMINISTIC #define MBEDTLS_HMAC_DRBG_C #define MBEDTLS_MD_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ #if defined(PSA_WANT_ALG_ECDH) #if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 #define MBEDTLS_ECDH_C #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_ECDH */ #if defined(PSA_WANT_ALG_ECDSA) #if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_ECDSA */ #if defined(PSA_WANT_ALG_JPAKE) #if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE) || \ !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC) #define MBEDTLS_PSA_BUILTIN_PAKE 1 #define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_BIGNUM_C #define MBEDTLS_ECP_C #define MBEDTLS_ECJPAKE_C #endif /* missing accel */ #endif /* PSA_WANT_ALG_JPAKE */ /* ECC: key types: enable built-ins as needed. * * We need the key type built-in: * - if it's not accelerated, or * - if there's a curve with missing acceleration, or * - only for public/basic: if there's an alg with missing acceleration. */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 #endif /* missing accel */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ /* Note: the condition is always true as DERIVE can't be accelerated yet */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #endif /* missing accel */ #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define MBEDTLS_ECP_LIGHT #define MBEDTLS_BIGNUM_C #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #define MBEDTLS_ECP_C #define MBEDTLS_BIGNUM_C #endif /* End of ECC section */ /* * DH key types follow the same pattern used above for EC keys. They are defined * by a triplet (group, key_type, alg). A triplet is accelerated if all its * component are accelerated, otherwise each component needs to be builtin. */ /* DH: groups: is acceleration complete? */ #if (defined(PSA_WANT_DH_RFC7919_2048) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048)) || \ (defined(PSA_WANT_DH_RFC7919_3072) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072)) || \ (defined(PSA_WANT_DH_RFC7919_4096) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096)) || \ (defined(PSA_WANT_DH_RFC7919_6144) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144)) || \ (defined(PSA_WANT_DH_RFC7919_8192) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192)) #define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS #endif /* DH: algs: is acceleration complete? */ #if defined(PSA_WANT_ALG_FFDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) #define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS #endif /* DH: key types: is acceleration complete? */ #if (defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT)) || \ (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) && \ !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE)) #define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES #endif #if defined(PSA_WANT_DH_RFC7919_2048) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ #endif /* PSA_WANT_DH_RFC7919_2048 */ #if defined(PSA_WANT_DH_RFC7919_3072) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ #endif /* PSA_WANT_DH_RFC7919_3072 */ #if defined(PSA_WANT_DH_RFC7919_4096) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ #endif /* PSA_WANT_DH_RFC7919_4096 */ #if defined(PSA_WANT_DH_RFC7919_6144) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ #endif /* PSA_WANT_DH_RFC7919_6144 */ #if defined(PSA_WANT_DH_RFC7919_8192) #if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1 #endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ #endif /* PSA_WANT_DH_RFC7919_8192 */ #if defined(PSA_WANT_ALG_FFDH) #if !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES) #define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1 #define MBEDTLS_BIGNUM_C #endif /* !MBEDTLS_PSA_ACCEL_ALG_FFDH */ #endif /* PSA_WANT_ALG_FFDH */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC */ #endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \ defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1 #define MBEDTLS_BIGNUM_C #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY */ #endif /* PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY */ /* End of DH section */ #if defined(PSA_WANT_ALG_HKDF) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF) /* * The PSA implementation has its own implementation of HKDF, separate from * hkdf.c. No need to enable MBEDTLS_HKDF_C here. */ #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */ #endif /* PSA_WANT_ALG_HKDF */ #if defined(PSA_WANT_ALG_HKDF_EXTRACT) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT) /* * The PSA implementation has its own implementation of HKDF, separate from * hkdf.c. No need to enable MBEDTLS_HKDF_C here. */ #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */ #endif /* PSA_WANT_ALG_HKDF_EXTRACT */ #if defined(PSA_WANT_ALG_HKDF_EXPAND) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND) /* * The PSA implementation has its own implementation of HKDF, separate from * hkdf.c. No need to enable MBEDTLS_HKDF_C here. */ #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */ #endif /* PSA_WANT_ALG_HKDF_EXPAND */ #if defined(PSA_WANT_ALG_HMAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ #endif /* PSA_WANT_ALG_HMAC */ #if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5) #define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 #define MBEDTLS_MD5_C #endif #if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) #define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 #define MBEDTLS_RIPEMD160_C #endif #if defined(PSA_WANT_ALG_RSA_OAEP) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V21 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */ #endif /* PSA_WANT_ALG_RSA_OAEP */ #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V15 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */ #endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */ #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V15 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */ #endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ #if defined(PSA_WANT_ALG_RSA_PSS) #if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_PKCS1_V21 #endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */ #endif /* PSA_WANT_ALG_RSA_PSS */ #if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 #define MBEDTLS_SHA1_C #endif #if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 #define MBEDTLS_SHA224_C #endif #if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 #define MBEDTLS_SHA256_C #endif #if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 #define MBEDTLS_SHA384_C #endif #if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 #define MBEDTLS_SHA512_C #endif #if defined(PSA_WANT_ALG_SHA3_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_SHA3_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_SHA3_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_SHA3_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1 #define MBEDTLS_SHA3_C #endif #if defined(PSA_WANT_ALG_PBKDF2_HMAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC) #define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1 #define PSA_HAVE_SOFT_PBKDF2_HMAC 1 #if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ #endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ #endif /* PSA_WANT_ALG_PBKDF2_HMAC */ #if defined(PSA_WANT_ALG_TLS12_PRF) #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */ #endif /* PSA_WANT_ALG_TLS12_PRF */ #if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */ #endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */ #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) #if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */ #endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #define MBEDTLS_GENPRIME #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 #define MBEDTLS_RSA_C #define MBEDTLS_BIGNUM_C #define MBEDTLS_OID_C #define MBEDTLS_ASN1_PARSE_C #define MBEDTLS_ASN1_WRITE_C #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */ #endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ /* If any of the block modes are requested that don't have an * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking * in the block cipher key types. */ #if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \ (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \ (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \ (defined(PSA_WANT_ALG_ECB_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)) || \ (defined(PSA_WANT_ALG_CBC_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \ (defined(PSA_WANT_ALG_CBC_PKCS7) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \ (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)) #define PSA_HAVE_SOFT_BLOCK_MODE 1 #endif #if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) #if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128) #define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 1 #define PSA_HAVE_SOFT_PBKDF2_CMAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128 */ #endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ #if defined(PSA_WANT_KEY_TYPE_AES) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) #define PSA_HAVE_SOFT_KEY_TYPE_AES 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 #define MBEDTLS_AES_C #endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_AES */ #if defined(PSA_WANT_KEY_TYPE_ARIA) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) #define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 #define MBEDTLS_ARIA_C #endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_ARIA */ #if defined(PSA_WANT_KEY_TYPE_CAMELLIA) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) #define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 #define MBEDTLS_CAMELLIA_C #endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_CAMELLIA */ #if defined(PSA_WANT_KEY_TYPE_DES) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) #define PSA_HAVE_SOFT_KEY_TYPE_DES 1 #endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ defined(PSA_HAVE_SOFT_BLOCK_MODE) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 #define MBEDTLS_DES_C #endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */ #endif /* PSA_WANT_KEY_TYPE_DES */ #if defined(PSA_WANT_ALG_STREAM_CIPHER) #if !defined(MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 #endif /* MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER */ #endif /* PSA_WANT_ALG_STREAM_CIPHER */ #if defined(PSA_WANT_KEY_TYPE_CHACHA20) #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 #define MBEDTLS_CHACHA20_C #endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */ #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ /* If any of the software block ciphers are selected, define * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these * situations. */ #if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define PSA_HAVE_SOFT_BLOCK_CIPHER 1 #endif #if defined(PSA_WANT_ALG_CBC_MAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC) #error "CBC-MAC is not yet supported via the PSA API in Mbed TLS." #define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1 #endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */ #endif /* PSA_WANT_ALG_CBC_MAC */ #if defined(PSA_WANT_ALG_CMAC) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 #define MBEDTLS_CMAC_C #endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */ #endif /* PSA_WANT_ALG_CMAC */ #if defined(PSA_HAVE_SOFT_PBKDF2_HMAC) || \ defined(PSA_HAVE_SOFT_PBKDF2_CMAC) #define PSA_HAVE_SOFT_PBKDF2 1 #endif /* PSA_HAVE_SOFT_PBKDF2_HMAC || PSA_HAVE_SOFT_PBKDF2_CMAC */ #if defined(PSA_WANT_ALG_CTR) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 #define MBEDTLS_CIPHER_MODE_CTR #endif #endif /* PSA_WANT_ALG_CTR */ #if defined(PSA_WANT_ALG_CFB) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 #define MBEDTLS_CIPHER_MODE_CFB #endif #endif /* PSA_WANT_ALG_CFB */ #if defined(PSA_WANT_ALG_OFB) #if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 #define MBEDTLS_CIPHER_MODE_OFB #endif #endif /* PSA_WANT_ALG_OFB */ #if defined(PSA_WANT_ALG_ECB_NO_PADDING) && \ !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING) #define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 #endif #if defined(PSA_WANT_ALG_CBC_NO_PADDING) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 #endif #endif /* PSA_WANT_ALG_CBC_NO_PADDING */ #if defined(PSA_WANT_ALG_CBC_PKCS7) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \ defined(PSA_HAVE_SOFT_BLOCK_CIPHER) #define MBEDTLS_CIPHER_MODE_CBC #define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 #define MBEDTLS_CIPHER_PADDING_PKCS7 #endif #endif /* PSA_WANT_ALG_CBC_PKCS7 */ #if defined(PSA_WANT_ALG_CCM) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 #define MBEDTLS_CCM_C #endif #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 #define MBEDTLS_CCM_C #endif #endif /* PSA_WANT_ALG_CCM_STAR_NO_TAG */ #if defined(PSA_WANT_ALG_GCM) #if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) #define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 #define MBEDTLS_GCM_C #endif #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) #if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305) #if defined(PSA_WANT_KEY_TYPE_CHACHA20) #define MBEDTLS_CHACHAPOLY_C #define MBEDTLS_CHACHA20_C #define MBEDTLS_POLY1305_C #define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 #endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ #endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */ #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ #endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h000066400000000000000000000255251464416617300311600ustar00rootroot00000000000000/** * \file mbedtls/config_adjust_psa_from_legacy.h * \brief Adjust PSA configuration: construct PSA configuration from legacy * * When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable * cryptographic mechanisms through the PSA interface when the corresponding * legacy mechanism is enabled. In many cases, this just enables the PSA * wrapper code around the legacy implementation, but we also do this for * some mechanisms where PSA has its own independent implementation so * that high-level modules that can use either cryptographic API have the * same feature set in both cases. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H #define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H /* * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG * is not defined */ #if defined(MBEDTLS_CCM_C) #define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 #define PSA_WANT_ALG_CCM 1 #if defined(MBEDTLS_CIPHER_C) #define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1 #define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 #endif /* MBEDTLS_CIPHER_C */ #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CMAC_C) #define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 #define PSA_WANT_ALG_CMAC 1 #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_ECDH_C) #define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 #define PSA_WANT_ALG_ECDH 1 #endif /* MBEDTLS_ECDH_C */ #if defined(MBEDTLS_ECDSA_C) #define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 #define PSA_WANT_ALG_ECDSA 1 #define PSA_WANT_ALG_ECDSA_ANY 1 // Only add in DETERMINISTIC support if ECDSA is also enabled #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 #define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_ECP_C) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 /* Normally we wouldn't enable this because it's not implemented in ecp.c, * but since it used to be available any time ECP_C was enabled, let's enable * it anyway for the sake of backwards compatibility */ #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 /* See comment for PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE above. */ #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_DHM_C) #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 #define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #define PSA_WANT_ALG_FFDH 1 #define PSA_WANT_DH_RFC7919_2048 1 #define PSA_WANT_DH_RFC7919_3072 1 #define PSA_WANT_DH_RFC7919_4096 1 #define PSA_WANT_DH_RFC7919_6144 1 #define PSA_WANT_DH_RFC7919_8192 1 #define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1 #define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1 #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_GCM_C) #define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 #define PSA_WANT_ALG_GCM 1 #endif /* MBEDTLS_GCM_C */ /* Enable PSA HKDF algorithm if mbedtls HKDF is supported. * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when * PSA HKDF is enabled, so enable both algorithms together * with PSA HKDF. */ #if defined(MBEDTLS_HKDF_C) #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define PSA_WANT_ALG_HMAC 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 #define PSA_WANT_ALG_HKDF 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1 #define PSA_WANT_ALG_HKDF_EXTRACT 1 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1 #define PSA_WANT_ALG_HKDF_EXPAND 1 #endif /* MBEDTLS_HKDF_C */ #define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 #define PSA_WANT_ALG_HMAC 1 #define PSA_WANT_KEY_TYPE_HMAC 1 #if defined(MBEDTLS_MD_C) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 #define PSA_WANT_ALG_TLS12_PRF 1 #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 #define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_MD5_C) #define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 #define PSA_WANT_ALG_MD5 1 #endif #if defined(MBEDTLS_ECJPAKE_C) #define MBEDTLS_PSA_BUILTIN_PAKE 1 #define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1 #define PSA_WANT_ALG_JPAKE 1 #endif #if defined(MBEDTLS_RIPEMD160_C) #define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 #define PSA_WANT_ALG_RIPEMD160 1 #endif #if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_PKCS1_V15) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1 #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) #define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 #define PSA_WANT_ALG_RSA_OAEP 1 #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 #define PSA_WANT_ALG_RSA_PSS 1 #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_GENPRIME) #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #endif /* MBEDTLS_GENPRIME */ #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SHA1_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 #define PSA_WANT_ALG_SHA_1 1 #endif #if defined(MBEDTLS_SHA224_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 #define PSA_WANT_ALG_SHA_224 1 #endif #if defined(MBEDTLS_SHA256_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 #define PSA_WANT_ALG_SHA_256 1 #endif #if defined(MBEDTLS_SHA384_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 #define PSA_WANT_ALG_SHA_384 1 #endif #if defined(MBEDTLS_SHA512_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 #define PSA_WANT_ALG_SHA_512 1 #endif #if defined(MBEDTLS_SHA3_C) #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1 #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1 #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1 #define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1 #define PSA_WANT_ALG_SHA3_224 1 #define PSA_WANT_ALG_SHA3_256 1 #define PSA_WANT_ALG_SHA3_384 1 #define PSA_WANT_ALG_SHA3_512 1 #endif #if defined(MBEDTLS_AES_C) #define PSA_WANT_KEY_TYPE_AES 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 #endif #if defined(MBEDTLS_ARIA_C) #define PSA_WANT_KEY_TYPE_ARIA 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 #endif #if defined(MBEDTLS_CAMELLIA_C) #define PSA_WANT_KEY_TYPE_CAMELLIA 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 #endif #if defined(MBEDTLS_DES_C) #define PSA_WANT_KEY_TYPE_DES 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) #define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1 #define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 #endif #if defined(MBEDTLS_CHACHA20_C) #define PSA_WANT_KEY_TYPE_CHACHA20 1 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 /* ALG_STREAM_CIPHER requires CIPHER_C in order to be supported in PSA */ #if defined(MBEDTLS_CIPHER_C) #define PSA_WANT_ALG_STREAM_CIPHER 1 #define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 #endif #if defined(MBEDTLS_CHACHAPOLY_C) #define PSA_WANT_ALG_CHACHA20_POLY1305 1 #define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 #endif #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) #define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 #define PSA_WANT_ALG_CBC_NO_PADDING 1 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) #define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 #define PSA_WANT_ALG_CBC_PKCS7 1 #endif #endif #if (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \ defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) && \ defined(MBEDTLS_CIPHER_C) #define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 #define PSA_WANT_ALG_ECB_NO_PADDING 1 #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) #define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 #define PSA_WANT_ALG_CFB 1 #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) #define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 #define PSA_WANT_ALG_CTR 1 #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) #define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 #define PSA_WANT_ALG_OFB 1 #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 #define PSA_WANT_ECC_MONTGOMERY_255 1 #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 #define PSA_WANT_ECC_MONTGOMERY_448 1 #endif #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 #define PSA_WANT_ECC_SECP_R1_192 1 #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 #define PSA_WANT_ECC_SECP_R1_224 1 #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 #define PSA_WANT_ECC_SECP_R1_256 1 #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 #define PSA_WANT_ECC_SECP_R1_384 1 #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 #define PSA_WANT_ECC_SECP_R1_521 1 #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 #define PSA_WANT_ECC_SECP_K1_192 1 #endif /* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ #if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 #define PSA_WANT_ECC_SECP_K1_224 1 #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 #define PSA_WANT_ECC_SECP_K1_256 1 #endif #endif /* MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h000066400000000000000000000111561464416617300320620ustar00rootroot00000000000000/** * \file mbedtls/config_adjust_psa_superset_legacy.h * \brief Adjust PSA configuration: automatic enablement from legacy * * To simplify some edge cases, we automatically enable certain cryptographic * mechanisms in the PSA API if they are enabled in the legacy API. The general * idea is that if legacy module M uses mechanism A internally, and A has * both a legacy and a PSA implementation, we enable A through PSA whenever * it's enabled through legacy. This facilitates the transition to PSA * implementations of A for users of M. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H #define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H /****************************************************************/ /* Hashes that are built in are also enabled in PSA. * This simplifies dependency declarations especially * for modules that obey MBEDTLS_USE_PSA_CRYPTO. */ /****************************************************************/ #if defined(MBEDTLS_MD5_C) #define PSA_WANT_ALG_MD5 1 #endif #if defined(MBEDTLS_RIPEMD160_C) #define PSA_WANT_ALG_RIPEMD160 1 #endif #if defined(MBEDTLS_SHA1_C) #define PSA_WANT_ALG_SHA_1 1 #endif #if defined(MBEDTLS_SHA224_C) #define PSA_WANT_ALG_SHA_224 1 #endif #if defined(MBEDTLS_SHA256_C) #define PSA_WANT_ALG_SHA_256 1 #endif #if defined(MBEDTLS_SHA384_C) #define PSA_WANT_ALG_SHA_384 1 #endif #if defined(MBEDTLS_SHA512_C) #define PSA_WANT_ALG_SHA_512 1 #endif #if defined(MBEDTLS_SHA3_C) #define PSA_WANT_ALG_SHA3_224 1 #define PSA_WANT_ALG_SHA3_256 1 #define PSA_WANT_ALG_SHA3_384 1 #define PSA_WANT_ALG_SHA3_512 1 #endif /* Ensure that the PSA's supported curves (PSA_WANT_ECC_xxx) are always a * superset of the builtin ones (MBEDTLS_ECP_DP_xxx). */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ #endif /*MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #if !defined(PSA_WANT_ECC_MONTGOMERY_255) #define PSA_WANT_ECC_MONTGOMERY_255 1 #endif /* PSA_WANT_ECC_MONTGOMERY_255 */ #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #if !defined(PSA_WANT_ECC_MONTGOMERY_448) #define PSA_WANT_ECC_MONTGOMERY_448 1 #endif /* PSA_WANT_ECC_MONTGOMERY_448 */ #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_192) #define PSA_WANT_ECC_SECP_R1_192 1 #endif /* PSA_WANT_ECC_SECP_R1_192 */ #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_224) #define PSA_WANT_ECC_SECP_R1_224 1 #endif /* PSA_WANT_ECC_SECP_R1_224 */ #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_256) #define PSA_WANT_ECC_SECP_R1_256 1 #endif /* PSA_WANT_ECC_SECP_R1_256 */ #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_384) #define PSA_WANT_ECC_SECP_R1_384 1 #endif /* PSA_WANT_ECC_SECP_R1_384 */ #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_R1_521) #define PSA_WANT_ECC_SECP_R1_521 1 #endif /* PSA_WANT_ECC_SECP_R1_521 */ #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_K1_192) #define PSA_WANT_ECC_SECP_K1_192 1 #endif /* PSA_WANT_ECC_SECP_K1_192 */ #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ /* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */ #if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_K1_224) #define PSA_WANT_ECC_SECP_K1_224 1 #endif /* PSA_WANT_ECC_SECP_K1_224 */ #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #if !defined(PSA_WANT_ECC_SECP_K1_256) #define PSA_WANT_ECC_SECP_K1_256 1 #endif /* PSA_WANT_ECC_SECP_K1_256 */ #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #endif /* MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_ssl.h000066400000000000000000000056021464416617300266210ustar00rootroot00000000000000/** * \file mbedtls/config_adjust_ssl.h * \brief Adjust TLS configuration * * Automatically enable certain dependencies. Generally, MBEDLTS_xxx * configurations need to be explicitly enabled by the user: enabling * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a * compilation error. However, we do automatically enable certain options * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option * used to identify parts of a module that are used by other module, and we * don't want to make the symbol MBEDTLS_xxx_B part of the public API. * Another case is if A didn't depend on B in earlier versions, and we * want to use B in A but we need to preserve backward compatibility with * configurations that explicitly activate MBEDTLS_xxx_A but not * MBEDTLS_xxx_B. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_SSL_H #define MBEDTLS_CONFIG_ADJUST_SSL_H /* The following blocks make it easier to disable all of TLS, * or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all * key exchanges, options and extensions related to them. */ #if !defined(MBEDTLS_SSL_TLS_C) #undef MBEDTLS_SSL_CLI_C #undef MBEDTLS_SSL_SRV_C #undef MBEDTLS_SSL_PROTO_TLS1_3 #undef MBEDTLS_SSL_PROTO_TLS1_2 #undef MBEDTLS_SSL_PROTO_DTLS #endif #if !(defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)) #undef MBEDTLS_SSL_TICKET_C #endif #if !defined(MBEDTLS_SSL_PROTO_DTLS) #undef MBEDTLS_SSL_DTLS_ANTI_REPLAY #undef MBEDTLS_SSL_DTLS_CONNECTION_ID #undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT #undef MBEDTLS_SSL_DTLS_HELLO_VERIFY #undef MBEDTLS_SSL_DTLS_SRTP #undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE #endif #if !defined(MBEDTLS_SSL_PROTO_TLS1_2) #undef MBEDTLS_SSL_ENCRYPT_THEN_MAC #undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET #undef MBEDTLS_SSL_RENEGOTIATION #undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED #undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED #endif #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) #undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED #undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED #undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED #undef MBEDTLS_SSL_EARLY_DATA #undef MBEDTLS_SSL_RECORD_SIZE_LIMIT #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) #define MBEDTLS_SSL_TLS1_2_SOME_ECC #endif #endif /* MBEDTLS_CONFIG_ADJUST_SSL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_x509.h000066400000000000000000000020261464416617300265220ustar00rootroot00000000000000/** * \file mbedtls/config_adjust_x509.h * \brief Adjust X.509 configuration * * Automatically enable certain dependencies. Generally, MBEDLTS_xxx * configurations need to be explicitly enabled by the user: enabling * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a * compilation error. However, we do automatically enable certain options * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option * used to identify parts of a module that are used by other module, and we * don't want to make the symbol MBEDTLS_xxx_B part of the public API. * Another case is if A didn't depend on B in earlier versions, and we * want to use B in A but we need to preserve backward compatibility with * configurations that explicitly activate MBEDTLS_xxx_A but not * MBEDTLS_xxx_B. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_ADJUST_X509_H #define MBEDTLS_CONFIG_ADJUST_X509_H #endif /* MBEDTLS_CONFIG_ADJUST_X509_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h000066400000000000000000000032021464416617300252230ustar00rootroot00000000000000/** * \file mbedtls/config_psa.h * \brief PSA crypto configuration options (set of defines) * * This set of compile-time options takes settings defined in * include/mbedtls/mbedtls_config.h and include/psa/crypto_config.h and uses * those definitions to define symbols used in the library code. * * Users and integrators should not edit this file, please edit * include/mbedtls/mbedtls_config.h for MBEDTLS_XXX settings or * include/psa/crypto_config.h for PSA_WANT_XXX settings. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONFIG_PSA_H #define MBEDTLS_CONFIG_PSA_H #include "psa/crypto_legacy.h" #include "psa/crypto_adjust_config_synonyms.h" #include "mbedtls/config_adjust_psa_superset_legacy.h" #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* Require built-in implementations based on PSA requirements */ /* We need this to have a complete list of requirements * before we deduce what built-ins are required. */ #include "psa/crypto_adjust_config_key_pair_types.h" #include "mbedtls/config_adjust_legacy_from_psa.h" #else /* MBEDTLS_PSA_CRYPTO_CONFIG */ /* Infer PSA requirements from Mbed TLS capabilities */ #include "mbedtls/config_adjust_psa_from_legacy.h" /* Hopefully the file above will have enabled keypair symbols in a consistent * way, but including this here fixes them if that wasn't the case. */ #include "psa/crypto_adjust_config_key_pair_types.h" #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ #if defined(PSA_WANT_ALG_JPAKE) #define PSA_WANT_ALG_SOME_PAKE 1 #endif #include "psa/crypto_adjust_auto_enabled.h" #endif /* MBEDTLS_CONFIG_PSA_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h000066400000000000000000000023111464416617300257620ustar00rootroot00000000000000/** * Constant-time functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_H #define MBEDTLS_CONSTANT_TIME_H #include /** Constant-time buffer comparison without branches. * * This is equivalent to the standard memcmp function, but is likely to be * compiled to code using bitwise operations rather than a branch, such that * the time taken is constant w.r.t. the data pointed to by \p a and \p b, * and w.r.t. whether \p a and \p b are equal or not. It is not constant-time * w.r.t. \p n . * * This function can be used to write constant-time code by replacing branches * with bit operations using masks. * * \param a Pointer to the first buffer, containing at least \p n bytes. May not be NULL. * \param b Pointer to the second buffer, containing at least \p n bytes. May not be NULL. * \param n The number of bytes to compare. * * \return Zero if the contents of the two buffers are the same, * otherwise non-zero. */ int mbedtls_ct_memcmp(const void *a, const void *b, size_t n); #endif /* MBEDTLS_CONSTANT_TIME_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h000066400000000000000000000603211464416617300247060ustar00rootroot00000000000000/** * \file ctr_drbg.h * * \brief This file contains definitions and functions for the * CTR_DRBG pseudorandom generator. * * CTR_DRBG is a standardized way of building a PRNG from a block-cipher * in counter mode operation, as defined in NIST SP 800-90A: * Recommendation for Random Number Generation Using Deterministic Random * Bit Generators. * * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) * as the underlying block cipher, with a derivation function. * * The security strength as defined in NIST SP 800-90A is * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is * kept at its default value (and not overridden in mbedtls_config.h) and that the * DRBG instance is set up with default parameters. * See the documentation of mbedtls_ctr_drbg_seed() for more * information. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" /* In case AES_C is defined then it is the primary option for backward * compatibility purposes. If that's not available, PSA is used instead */ #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #else #include "psa/crypto.h" #endif #include "entropy.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** The entropy source failed. */ #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /** The requested random buffer length is too big. */ #define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /** The input (entropy + additional data) is too large. */ #define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /** Read or write error in file. */ #define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A #define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) #define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size in bytes used by the cipher. * * Compile-time choice: 16 bytes (128 bits) * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. */ #else #define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size in bytes used by the cipher. * * Compile-time choice: 32 bytes (256 bits) * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. */ #endif #define MBEDTLS_CTR_DRBG_KEYBITS (MBEDTLS_CTR_DRBG_KEYSIZE * 8) /**< The key size for the DRBG operation, in bits. */ #define MBEDTLS_CTR_DRBG_SEEDLEN (MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE) /**< The seed length, calculated as (counter + AES key). */ /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them using the compiler command * line. * \{ */ /** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN * * \brief The amount of entropy used per seed by default, in bytes. */ #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) /** This is 48 bytes because the entropy module uses SHA-512. */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ /** This is 32 bytes because the entropy module uses SHA-256. */ #if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) /** \warning To achieve a 256-bit security strength, you must pass a nonce * to mbedtls_ctr_drbg_seed(). */ #endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< The interval before reseed is performed by default. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) #define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< The maximum number of additional input Bytes. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) #define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< The maximum number of requested Bytes per call. */ #endif #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< The maximum size of seed or reseed buffer in bytes. */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< Prediction resistance is disabled. */ #define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance is enabled. */ #ifdef __cplusplus extern "C" { #endif #if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 /** The default length of the nonce read from the entropy source. * * This is \c 0 because a single read from the entropy source is sufficient * to include a nonce. * See the documentation of mbedtls_ctr_drbg_seed() for more information. */ #define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0 #else /** The default length of the nonce read from the entropy source. * * This is half of the default entropy length because a single read from * the entropy source does not provide enough material to form a nonce. * See the documentation of mbedtls_ctr_drbg_seed() for more information. */ #define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN (MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2 #endif #if !defined(MBEDTLS_AES_C) typedef struct mbedtls_ctr_drbg_psa_context { mbedtls_svc_key_id_t key_id; psa_cipher_operation_t operation; } mbedtls_ctr_drbg_psa_context; #endif /** * \brief The CTR_DRBG context structure. */ typedef struct mbedtls_ctr_drbg_context { unsigned char MBEDTLS_PRIVATE(counter)[16]; /*!< The counter (V). */ int MBEDTLS_PRIVATE(reseed_counter); /*!< The reseed counter. * This is the number of requests that have * been made since the last (re)seeding, * minus one. * Before the initial seeding, this field * contains the amount of entropy in bytes * to use as a nonce for the initial seeding, * or -1 if no nonce length has been explicitly * set (see mbedtls_ctr_drbg_set_nonce_len()). */ int MBEDTLS_PRIVATE(prediction_resistance); /*!< This determines whether prediction resistance is enabled, that is whether to systematically reseed before each random generation. */ size_t MBEDTLS_PRIVATE(entropy_len); /*!< The amount of entropy grabbed on each seed or reseed operation, in bytes. */ int MBEDTLS_PRIVATE(reseed_interval); /*!< The reseed interval. * This is the maximum number of requests * that can be made between reseedings. */ #if defined(MBEDTLS_AES_C) mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */ #else mbedtls_ctr_drbg_psa_context MBEDTLS_PRIVATE(psa_ctx); /*!< The PSA context. */ #endif /* * Callbacks (Entropy) */ int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< The entropy callback function. */ void *MBEDTLS_PRIVATE(p_entropy); /*!< The context for the entropy function. */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized if and only if f_entropy != NULL. * This means that the mutex is initialized during the initial seeding * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). * * Note that this invariant may change without notice. Do not rely on it * and do not access the mutex directly in application code. */ mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_ctr_drbg_context; /** * \brief This function initializes the CTR_DRBG context, * and prepares it for mbedtls_ctr_drbg_seed() * or mbedtls_ctr_drbg_free(). * * \note The reseed interval is * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. * You can override it by calling * mbedtls_ctr_drbg_set_reseed_interval(). * * \param ctx The CTR_DRBG context to initialize. */ void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx); /** * \brief This function seeds and sets up the CTR_DRBG * entropy source for future reseeds. * * A typical choice for the \p f_entropy and \p p_entropy parameters is * to use the entropy module: * - \p f_entropy is mbedtls_entropy_func(); * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized * with mbedtls_entropy_init() (which registers the platform's default * entropy sources). * * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). * * The entropy nonce length is: * - \c 0 if the entropy length is at least 3/2 times the entropy length, * which guarantees that the security strength is the maximum permitted * by the key size and entropy length according to NIST SP 800-90A §10.2.1; * - Half the entropy length otherwise. * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). * With the default entropy length, the entropy nonce length is * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN. * * You can provide a nonce and personalization string in addition to the * entropy source, to make this instantiation as unique as possible. * See SP 800-90A §8.6.7 for more details about nonces. * * The _seed_material_ value passed to the derivation function in * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2 * is the concatenation of the following strings: * - A string obtained by calling \p f_entropy function for the entropy * length. */ #if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0 /** * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string * obtained by calling \p f_entropy function for the specified length. */ #else /** * - A string obtained by calling \p f_entropy function for the entropy nonce * length. If the entropy nonce length is \c 0, this function does not * make a second call to \p f_entropy. */ #endif #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * after this function returns successfully, * it is safe to call mbedtls_ctr_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * - The \p custom string. * * \note To achieve the nominal security strength permitted * by CTR_DRBG, the entropy length must be: * - at least 16 bytes for a 128-bit strength * (maximum achievable strength when using AES-128); * - at least 32 bytes for a 256-bit strength * (maximum achievable strength when using AES-256). * * In addition, if you do not pass a nonce in \p custom, * the sum of the entropy length * and the entropy nonce length must be: * - at least 24 bytes for a 128-bit strength * (maximum achievable strength when using AES-128); * - at least 48 bytes for a 256-bit strength * (maximum achievable strength when using AES-256). * * \param ctx The CTR_DRBG context to seed. * It must have been initialized with * mbedtls_ctr_drbg_init(). * After a successful call to mbedtls_ctr_drbg_seed(), * you may not call mbedtls_ctr_drbg_seed() again on * the same context unless you call * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() * again first. * After a failed call to mbedtls_ctr_drbg_seed(), * you must call mbedtls_ctr_drbg_free(). * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. * \p f_entropy is always called with a buffer size * less than or equal to the entropy length. * \param p_entropy The entropy context to pass to \p f_entropy. * \param custom The personalization string. * This can be \c NULL, in which case the personalization * string is empty regardless of the value of \p len. * \param len The length of the personalization string. * This must be at most * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len); /** * \brief This function resets CTR_DRBG context to the state immediately * after initial call of mbedtls_ctr_drbg_init(). * * \param ctx The CTR_DRBG context to clear. */ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx); /** * \brief This function turns prediction resistance on or off. * The default value is off. * * \note If enabled, entropy is gathered at the beginning of * every call to mbedtls_ctr_drbg_random_with_add() * or mbedtls_ctr_drbg_random(). * Only use this if your entropy source has sufficient * throughput. * * \param ctx The CTR_DRBG context. * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. */ void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, int resistance); /** * \brief This function sets the amount of entropy grabbed on each * seed or reseed. * * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * * \note The security strength of CTR_DRBG is bounded by the * entropy length. Thus: * - When using AES-256 * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, * which is the default), * \p len must be at least 32 (in bytes) * to achieve a 256-bit strength. * - When using AES-128 * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) * \p len must be at least 16 (in bytes) * to achieve a 128-bit strength. * * \param ctx The CTR_DRBG context. * \param len The amount of entropy to grab, in bytes. * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT * and at most the maximum length accepted by the * entropy function that is set in the context. */ void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, size_t len); /** * \brief This function sets the amount of entropy grabbed * as a nonce for the initial seeding. * * Call this function before calling mbedtls_ctr_drbg_seed() to read * a nonce from the entropy source during the initial seeding. * * \param ctx The CTR_DRBG context. * \param len The amount of entropy to grab for the nonce, in bytes. * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT * and at most the maximum length accepted by the * entropy function that is set in the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED * if the initial seeding has already taken place. */ int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, size_t len); /** * \brief This function sets the reseed interval. * * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() * or mbedtls_ctr_drbg_random_with_add() after which the entropy function * is called again. * * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. * * \param ctx The CTR_DRBG context. * \param interval The reseed interval. */ void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, int interval); /** * \brief This function reseeds the CTR_DRBG context, that is * extracts data from the entropy source. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The CTR_DRBG context. * \param additional Additional data to add to the state. Can be \c NULL. * \param len The length of the additional data. * This must be less than * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len * where \c entropy_len is the entropy length * configured for the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. */ int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len); /** * \brief This function updates the state of the CTR_DRBG context. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The CTR_DRBG context. * \param additional The data to update the state with. This must not be * \c NULL unless \p add_len is \c 0. * \param add_len Length of \p additional in bytes. This must be at * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if * \p add_len is more than * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * \return An error from the underlying AES cipher on failure. */ int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len); /** * \brief This function updates a CTR_DRBG instance with additional * data and uses it to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. * \param output_len The length of the buffer in bytes. * \param additional Additional data to update. Can be \c NULL, in which * case the additional data is empty regardless of * the value of \p add_len. * \param add_len The length of the additional data * if \p additional is not \c NULL. * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT * and less than * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len * where \c entropy_len is the entropy length * configured for the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len); /** * \brief This function uses CTR_DRBG to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * it is safe to call mbedtls_ctr_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. * \param output_len The length of the buffer in bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. */ int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, size_t output_len); #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. * * \param ctx The CTR_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed * failure. */ int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); /** * \brief This function reads and updates a seed file. The seed * is added to this instance. * * \param ctx The CTR_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on * reseed failure. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing * seed file is too large. */ int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /** * \brief The CTR_DRBG checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_ctr_drbg_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* ctr_drbg.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/debug.h000066400000000000000000000121651464416617300242110ustar00rootroot00000000000000/** * \file debug.h * * \brief Functions for controlling and providing debug output from the library. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DEBUG_H #define MBEDTLS_DEBUG_H #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_DEBUG_C) #define MBEDTLS_DEBUG_STRIP_PARENS(...) __VA_ARGS__ #define MBEDTLS_SSL_DEBUG_MSG(level, args) \ mbedtls_debug_print_msg(ssl, level, __FILE__, __LINE__, \ MBEDTLS_DEBUG_STRIP_PARENS args) #define MBEDTLS_SSL_DEBUG_RET(level, text, ret) \ mbedtls_debug_print_ret(ssl, level, __FILE__, __LINE__, text, ret) #define MBEDTLS_SSL_DEBUG_BUF(level, text, buf, len) \ mbedtls_debug_print_buf(ssl, level, __FILE__, __LINE__, text, buf, len) #if defined(MBEDTLS_BIGNUM_C) #define MBEDTLS_SSL_DEBUG_MPI(level, text, X) \ mbedtls_debug_print_mpi(ssl, level, __FILE__, __LINE__, text, X) #endif #if defined(MBEDTLS_ECP_C) #define MBEDTLS_SSL_DEBUG_ECP(level, text, X) \ mbedtls_debug_print_ecp(ssl, level, __FILE__, __LINE__, text, X) #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if !defined(MBEDTLS_X509_REMOVE_INFO) #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) \ mbedtls_debug_print_crt(ssl, level, __FILE__, __LINE__, text, crt) #else #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) do { } while (0) #endif /* MBEDTLS_X509_REMOVE_INFO */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_ECDH_C) #define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr) \ mbedtls_debug_printf_ecdh(ssl, level, __FILE__, __LINE__, ecdh, attr) #endif #else /* MBEDTLS_DEBUG_C */ #define MBEDTLS_SSL_DEBUG_MSG(level, args) do { } while (0) #define MBEDTLS_SSL_DEBUG_RET(level, text, ret) do { } while (0) #define MBEDTLS_SSL_DEBUG_BUF(level, text, buf, len) do { } while (0) #define MBEDTLS_SSL_DEBUG_MPI(level, text, X) do { } while (0) #define MBEDTLS_SSL_DEBUG_ECP(level, text, X) do { } while (0) #define MBEDTLS_SSL_DEBUG_CRT(level, text, crt) do { } while (0) #define MBEDTLS_SSL_DEBUG_ECDH(level, ecdh, attr) do { } while (0) #endif /* MBEDTLS_DEBUG_C */ /** * \def MBEDTLS_PRINTF_ATTRIBUTE * * Mark a function as having printf attributes, and thus enable checking * via -wFormat and other flags. This does nothing on builds with compilers * that do not support the format attribute * * Module: library/debug.c * Caller: * * This module provides debugging functions. */ #if defined(__has_attribute) #if __has_attribute(format) #if defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((__format__(gnu_printf, string_index, first_to_check))) #else /* defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 */ #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ __attribute__((format(printf, string_index, first_to_check))) #endif #else /* __has_attribute(format) */ #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) #endif /* __has_attribute(format) */ #else /* defined(__has_attribute) */ #define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) #endif /** * \def MBEDTLS_PRINTF_SIZET * * MBEDTLS_PRINTF_xxx: Due to issues with older window compilers * and MinGW we need to define the printf specifier for size_t * and long long per platform. * * Module: library/debug.c * Caller: * * This module provides debugging functions. */ #if (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) #include #define MBEDTLS_PRINTF_SIZET PRIuPTR #define MBEDTLS_PRINTF_LONGLONG "I64d" #else \ /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ #define MBEDTLS_PRINTF_SIZET "zu" #define MBEDTLS_PRINTF_LONGLONG "lld" #endif \ /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ #if !defined(MBEDTLS_PRINTF_MS_TIME) #include #if !defined(PRId64) #define MBEDTLS_PRINTF_MS_TIME MBEDTLS_PRINTF_LONGLONG #else #define MBEDTLS_PRINTF_MS_TIME PRId64 #endif #endif /* MBEDTLS_PRINTF_MS_TIME */ #ifdef __cplusplus extern "C" { #endif /** * \brief Set the threshold error level to handle globally all debug output. * Debug messages that have a level over the threshold value are * discarded. * (Default value: 0 = No debug ) * * \param threshold threshold level of messages to filter on. Messages at a * higher level will be discarded. * - Debug levels * - 0 No debug * - 1 Error * - 2 State change * - 3 Informational * - 4 Verbose */ void mbedtls_debug_set_threshold(int threshold); #ifdef __cplusplus } #endif #endif /* MBEDTLS_DEBUG_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/des.h000066400000000000000000000310541464416617300236740ustar00rootroot00000000000000/** * \file des.h * * \brief DES block cipher * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #ifndef MBEDTLS_DES_H #define MBEDTLS_DES_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include #include #define MBEDTLS_DES_ENCRYPT 1 #define MBEDTLS_DES_DECRYPT 0 /** The data input has an invalid length. */ #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 #define MBEDTLS_DES_KEY_SIZE 8 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_DES_ALT) // Regular implementation // /** * \brief DES context structure * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ typedef struct mbedtls_des_context { uint32_t MBEDTLS_PRIVATE(sk)[32]; /*!< DES subkeys */ } mbedtls_des_context; /** * \brief Triple-DES context structure * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ typedef struct mbedtls_des3_context { uint32_t MBEDTLS_PRIVATE(sk)[96]; /*!< 3DES subkeys */ } mbedtls_des3_context; #else /* MBEDTLS_DES_ALT */ #include "des_alt.h" #endif /* MBEDTLS_DES_ALT */ /** * \brief Initialize DES context * * \param ctx DES context to be initialized * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_init(mbedtls_des_context *ctx); /** * \brief Clear DES context * * \param ctx DES context to be cleared * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_free(mbedtls_des_context *ctx); /** * \brief Initialize Triple-DES context * * \param ctx DES3 context to be initialized * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des3_init(mbedtls_des3_context *ctx); /** * \brief Clear Triple-DES context * * \param ctx DES3 context to be cleared * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des3_free(mbedtls_des3_context *ctx); /** * \brief Set key parity on the given key to odd. * * DES keys are 56 bits long, but each byte is padded with * a parity bit to allow verification. * * \param key 8-byte secret key * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Check that key parity on the given key is odd. * * DES keys are 56 bits long, but each byte is padded with * a parity bit to allow verification. * * \param key 8-byte secret key * * \return 0 is parity was ok, 1 if parity was not correct. * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Check that key is not a weak or semi-weak DES key * * \param key 8-byte secret key * * \return 0 if no weak key was found, 1 if a weak key was identified. * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief DES key schedule (56-bit, encryption) * * \param ctx DES context to be initialized * \param key 8-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief DES key schedule (56-bit, decryption) * * \param ctx DES context to be initialized * \param key 8-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); /** * \brief Triple-DES key schedule (112-bit, encryption) * * \param ctx 3DES context to be initialized * \param key 16-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (112-bit, decryption) * * \param ctx 3DES context to be initialized * \param key 16-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); /** * \brief Triple-DES key schedule (168-bit, encryption) * * \param ctx 3DES context to be initialized * \param key 24-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief Triple-DES key schedule (168-bit, decryption) * * \param ctx 3DES context to be initialized * \param key 24-byte secret key * * \return 0 * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); /** * \brief DES-ECB block encryption/decryption * * \param ctx DES context * \param input 64-bit input block * \param output 64-bit output block * * \return 0 if successful * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, const unsigned char input[8], unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief DES-CBC buffer encryption/decryption * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx DES context * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT * \param length length of the input data * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ /** * \brief 3DES-ECB block encryption/decryption * * \param ctx 3DES context * \param input 64-bit input block * \param output 64-bit output block * * \return 0 if successful * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, const unsigned char input[8], unsigned char output[8]); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** * \brief 3DES-CBC buffer encryption/decryption * * \note Upon exit, the content of the IV is updated so that you can * call the function same function again on the following * block(s) of data and get the same result as if it was * encrypted in one call. This allows a "streaming" usage. * If on the other hand you need to retain the contents of the * IV, you should either save it manually or use the cipher * module instead. * * \param ctx 3DES context * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT * \param length length of the input data * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data * * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ /** * \brief Internal function for key expansion. * (Only exposed to allow overriding it, * see MBEDTLS_DES_SETKEY_ALT) * * \param SK Round keys * \param key Base key * * \warning DES/3DES are considered weak ciphers and their use constitutes a * security risk. We recommend considering stronger ciphers * instead. */ void mbedtls_des_setkey(uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE]); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_des_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* des.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h000066400000000000000000001404431464416617300236740ustar00rootroot00000000000000/** * \file dhm.h * * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange * definitions and functions. * * Diffie-Hellman-Merkle (DHM) key exchange is defined in * RFC-2631: Diffie-Hellman Key Agreement Method and * Public-Key Cryptography Standards (PKCS) #3: Diffie * Hellman Key Agreement Standard. * * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for * Internet Key Exchange (IKE) defines a number of standardized * Diffie-Hellman groups for IKE. * * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF * Standards defines a number of standardized Diffie-Hellman * groups that can be used. * * \warning The security of the DHM key exchange relies on the proper choice * of prime modulus - optimally, it should be a safe prime. The usage * of non-safe primes both decreases the difficulty of the underlying * discrete logarithm problem and can lead to small subgroup attacks * leaking private exponent bits when invalid public keys are used * and not detected. This is especially relevant if the same DHM * parameters are reused for multiple key exchanges as in static DHM, * while the criticality of small-subgroup attacks is lower for * ephemeral DHM. * * \warning For performance reasons, the code does neither perform primality * nor safe primality tests, nor the expensive checks for invalid * subgroups. Moreover, even if these were performed, non-standardized * primes cannot be trusted because of the possibility of backdoors * that can't be effectively checked for. * * \warning Diffie-Hellman-Merkle is therefore a security risk when not using * standardized primes generated using a trustworthy ("nothing up * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS * protocol, DH parameters need to be negotiated, so using the default * primes systematically is not always an option. If possible, use * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, * and for which the TLS protocol mandates the use of standard * parameters. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DHM_H #define MBEDTLS_DHM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" /* * DHM Error codes */ /** Bad input parameters. */ #define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /** Reading of the DHM parameters failed. */ #define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /** Making of the DHM parameters failed. */ #define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /** Reading of the public values failed. */ #define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /** Making of the public value failed. */ #define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /** Calculation of the DHM secret failed. */ #define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /** The ASN.1 data is not formatted correctly. */ #define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /** Allocation of memory failed. */ #define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /** Read or write of file failed. */ #define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /** Setting the modulus and generator failed. */ #define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /** Which parameter to access in mbedtls_dhm_get_value(). */ typedef enum { MBEDTLS_DHM_PARAM_P, /*!< The prime modulus. */ MBEDTLS_DHM_PARAM_G, /*!< The generator. */ MBEDTLS_DHM_PARAM_X, /*!< Our secret value. */ MBEDTLS_DHM_PARAM_GX, /*!< Our public key = \c G^X mod \c P. */ MBEDTLS_DHM_PARAM_GY, /*!< The public key of the peer = \c G^Y mod \c P. */ MBEDTLS_DHM_PARAM_K, /*!< The shared secret = \c G^(XY) mod \c P. */ } mbedtls_dhm_parameter; #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_DHM_ALT) /** * \brief The DHM context structure. */ typedef struct mbedtls_dhm_context { mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The prime modulus. */ mbedtls_mpi MBEDTLS_PRIVATE(G); /*!< The generator. */ mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< Our secret value. */ mbedtls_mpi MBEDTLS_PRIVATE(GX); /*!< Our public key = \c G^X mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(GY); /*!< The public key of the peer = \c G^Y mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(K); /*!< The shared secret = \c G^(XY) mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< The cached value = \c R^2 mod \c P. */ mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(pX); /*!< The previous \c X. */ } mbedtls_dhm_context; #else /* MBEDTLS_DHM_ALT */ #include "dhm_alt.h" #endif /* MBEDTLS_DHM_ALT */ /** * \brief This function initializes the DHM context. * * \param ctx The DHM context to initialize. */ void mbedtls_dhm_init(mbedtls_dhm_context *ctx); /** * \brief This function parses the DHM parameters in a * TLS ServerKeyExchange handshake message * (DHM modulus, generator, and public key). * * \note In a TLS handshake, this is the how the client * sets up its DHM context from the server's public * DHM key material. * * \param ctx The DHM context to use. This must be initialized. * \param p On input, *p must be the start of the input buffer. * On output, *p is updated to point to the end of the data * that has been read. On success, this is the first byte * past the end of the ServerKeyExchange parameters. * On error, this is the point at which an error has been * detected, which is usually not useful except to debug * failures. * \param end The end of the input buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx, unsigned char **p, const unsigned char *end); /** * \brief This function generates a DHM key pair and exports its * public part together with the DHM parameters in the format * used in a TLS ServerKeyExchange handshake message. * * \note This function assumes that the DHM parameters \c ctx->P * and \c ctx->G have already been properly set. For that, use * mbedtls_dhm_set_group() below in conjunction with * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). * * \note In a TLS handshake, this is the how the server generates * and exports its DHM key material. * * \param ctx The DHM context to use. This must be initialized * and have the DHM parameters set. It may or may not * already have imported the peer's public key. * \param x_size The private key size in Bytes. * \param olen The address at which to store the number of Bytes * written on success. This must not be \c NULL. * \param output The destination buffer. This must be a writable buffer of * sufficient size to hold the reduced binary presentation of * the modulus, the generator and the public key, each wrapped * with a 2-byte length field. It is the responsibility of the * caller to ensure that enough space is available. Refer to * mbedtls_mpi_size() to computing the byte-size of an MPI. * \param f_rng The RNG function. Must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function sets the prime modulus and generator. * * \note This function can be used to set \c ctx->P, \c ctx->G * in preparation for mbedtls_dhm_make_params(). * * \param ctx The DHM context to configure. This must be initialized. * \param P The MPI holding the DHM prime modulus. This must be * an initialized MPI. * \param G The MPI holding the DHM generator. This must be an * initialized MPI. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx, const mbedtls_mpi *P, const mbedtls_mpi *G); /** * \brief This function imports the raw public value of the peer. * * \note In a TLS handshake, this is the how the server imports * the Client's public DHM key. * * \param ctx The DHM context to use. This must be initialized and have * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). * It may or may not already have generated its own private key. * \param input The input buffer containing the \c G^Y value of the peer. * This must be a readable buffer of size \p ilen Bytes. * \param ilen The size of the input buffer \p input in Bytes. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function creates a DHM key pair and exports * the raw public key in big-endian format. * * \note The destination buffer is always fully written * so as to contain a big-endian representation of G^X mod P. * If it is larger than \c ctx->len, it is padded accordingly * with zero-bytes at the beginning. * * \param ctx The DHM context to use. This must be initialized and * have the DHM parameters set. It may or may not already * have imported the peer's public key. * \param x_size The private key size in Bytes. * \param output The destination buffer. This must be a writable buffer of * size \p olen Bytes. * \param olen The length of the destination buffer. This must be at least * equal to `ctx->len` (the size of \c P). * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function derives and exports the shared secret * \c (G^Y)^X mod \c P. * * \note If \p f_rng is not \c NULL, it is used to blind the input as * a countermeasure against timing attacks. Blinding is used * only if our private key \c X is re-used, and not used * otherwise. We recommend always passing a non-NULL * \p f_rng argument. * * \param ctx The DHM context to use. This must be initialized * and have its own private key generated and the peer's * public key imported. * \param output The buffer to write the generated shared key to. This * must be a writable buffer of size \p output_size Bytes. * \param output_size The size of the destination buffer. This must be at * least the size of \c ctx->len (the size of \c P). * \param olen On exit, holds the actual number of Bytes written. * \param f_rng The RNG function. Must not be \c NULL. Used for * blinding. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. */ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function returns the size of the prime modulus in bits. * * \param ctx The DHM context to query. * * \return The size of the prime modulus in bits, * i.e. the number n such that 2^(n-1) <= P < 2^n. */ size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx); /** * \brief This function returns the size of the prime modulus in bytes. * * \param ctx The DHM context to query. * * \return The size of the prime modulus in bytes, * i.e. the number n such that 2^(8*(n-1)) <= P < 2^(8*n). */ size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx); /** * \brief This function copies a parameter of a DHM key. * * \param ctx The DHM context to query. * \param param The parameter to copy. * \param dest The MPI object to copy the value into. It must be * initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p param is invalid. * \return An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails. */ int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, mbedtls_dhm_parameter param, mbedtls_mpi *dest); /** * \brief This function frees and clears the components * of a DHM context. * * \param ctx The DHM context to free and clear. This may be \c NULL, * in which case this function is a no-op. If it is not \c NULL, * it must point to an initialized DHM context. */ void mbedtls_dhm_free(mbedtls_dhm_context *ctx); #if defined(MBEDTLS_ASN1_PARSE_C) /** * \brief This function parses DHM parameters in PEM or DER format. * * \param dhm The DHM context to import the DHM parameters into. * This must be initialized. * \param dhmin The input buffer. This must be a readable buffer of * length \p dhminlen Bytes. * \param dhminlen The size of the input buffer \p dhmin, including the * terminating \c NULL Byte for PEM data. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error * code on failure. */ int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen); #if defined(MBEDTLS_FS_IO) /** * \brief This function loads and parses DHM parameters from a file. * * \param dhm The DHM context to load the parameters to. * This must be initialized. * \param path The filename to read the DHM parameters from. * This must not be \c NULL. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX * error code on failure. */ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_SELF_TEST) /** * \brief The DMH checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_dhm_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif /** * RFC 3526, RFC 5114 and RFC 7919 standardize a number of * Diffie-Hellman groups, some of which are included here * for use within the SSL/TLS module and the user's convenience * when configuring the Diffie-Hellman parameters by hand * through \c mbedtls_ssl_conf_dh_param. * * The following lists the source of the above groups in the standards: * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup * - RFC 3526 section 3: 2048-bit MODP Group * - RFC 3526 section 4: 3072-bit MODP Group * - RFC 3526 section 5: 4096-bit MODP Group * - RFC 7919 section A.1: ffdhe2048 * - RFC 7919 section A.2: ffdhe3072 * - RFC 7919 section A.3: ffdhe4096 * - RFC 7919 section A.4: ffdhe6144 * - RFC 7919 section A.5: ffdhe8192 * * The constants with suffix "_p" denote the chosen prime moduli, while * the constants with suffix "_g" denote the chosen generator * of the associated prime field. * * The constants further suffixed with "_bin" are provided in binary format, * while all other constants represent null-terminated strings holding the * hexadecimal presentation of the respective numbers. * * The primes from RFC 3526 and RFC 7919 have been generating by the following * trust-worthy procedure: * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number * the first and last 64 bits are all 1, and the remaining N - 128 bits of * which are 0x7ff...ff. * - Add the smallest multiple of the first N - 129 bits of the binary expansion * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string * such that the resulting integer is a safe-prime. * - The result is the respective RFC 3526 / 7919 prime, and the corresponding * generator is always chosen to be 2 (which is a square for these prime, * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a * bit in the private exponent). * */ /* * Trustworthy DHM parameters in binary form */ #define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } #define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } #define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } #define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } #endif /* dhm.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h000066400000000000000000000462531464416617300240330ustar00rootroot00000000000000/** * \file ecdh.h * * \brief This file contains ECDH definitions and functions. * * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous * key agreement protocol allowing two parties to establish a shared * secret over an insecure channel. Each party must have an * elliptic-curve public–private key pair. * * For more information, see NIST SP 800-56A Rev. 2: Recommendation for * Pair-Wise Key Establishment Schemes Using Discrete Logarithm * Cryptography. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECDH_H #define MBEDTLS_ECDH_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ecp.h" /* * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context * defined in `ecdh.h`). For most applications, the choice of format makes * no difference, since all library functions can work with either format, * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. * The new format used when this option is disabled is smaller * (56 bytes on a 32-bit platform). In future versions of the library, it * will support alternative implementations of ECDH operations. * The new format is incompatible with applications that access * context fields directly and with restartable ECP operations. */ #if defined(MBEDTLS_ECP_RESTARTABLE) #define MBEDTLS_ECDH_LEGACY_CONTEXT #else #undef MBEDTLS_ECDH_LEGACY_CONTEXT #endif #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) #undef MBEDTLS_ECDH_LEGACY_CONTEXT #include "everest/everest.h" #endif #ifdef __cplusplus extern "C" { #endif /** * Defines the source of the imported EC key. */ typedef enum { MBEDTLS_ECDH_OURS, /**< Our key. */ MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ } mbedtls_ecdh_side; #if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) /** * Defines the ECDH implementation used. * * Later versions of the library may add new variants, therefore users should * not make any assumptions about them. */ typedef enum { MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */ #endif } mbedtls_ecdh_variant; /** * The context used by the default ECDH implementation. * * Later versions might change the structure of this context, therefore users * should not make any assumptions about the structure of * mbedtls_ecdh_context_mbed. */ typedef struct mbedtls_ecdh_context_mbed { mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ #endif } mbedtls_ecdh_context_mbed; #endif /** * * \warning Performing multiple operations concurrently on the same * ECDSA context is not supported; objects of this type * should not be shared between multiple threads. * \brief The ECDH context structure. */ typedef struct mbedtls_ecdh_context { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ int MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ mbedtls_ecp_point MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(_d); /*!< The previous \p d. */ #if defined(MBEDTLS_ECP_RESTARTABLE) int MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. */ mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #else uint8_t MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages as defined in RFC 4492. */ mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);/*!< The elliptic curve used. */ mbedtls_ecdh_variant MBEDTLS_PRIVATE(var); /*!< The ECDH implementation/structure used. */ union { mbedtls_ecdh_context_mbed MBEDTLS_PRIVATE(mbed_ecdh); #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) mbedtls_ecdh_context_everest MBEDTLS_PRIVATE(everest_ecdh); #endif } MBEDTLS_PRIVATE(ctx); /*!< Implementation-specific context. The context in use is specified by the \c var field. */ #if defined(MBEDTLS_ECP_RESTARTABLE) uint8_t MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. Functions of an alternative implementation not supporting restartable mode must return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error if this flag is set. */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ } mbedtls_ecdh_context; /** * \brief Return the ECP group for provided context. * * \note To access group specific fields, users should use * `mbedtls_ecp_curve_info_from_grp_id` or * `mbedtls_ecp_group_load` on the extracted `group_id`. * * \param ctx The ECDH context to parse. This must not be \c NULL. * * \return The \c mbedtls_ecp_group_id of the context. */ mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx); /** * \brief Check whether a given group can be used for ECDH. * * \param gid The ECP group ID to check. * * \return \c 1 if the group can be used, \c 0 otherwise */ int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid); /** * \brief This function generates an ECDH keypair on an elliptic * curve. * * This function performs the first of two core computations * implemented during the ECDH key exchange. The second core * computation is performed by mbedtls_ecdh_compute_shared(). * * \see ecp.h * * \param grp The ECP group to use. This must be initialized and have * domain parameters loaded, for example through * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). * \param d The destination MPI (private key). * This must be initialized. * \param Q The destination point (public key). * This must be initialized. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function computes the shared secret. * * This function performs the second of two core computations * implemented during the ECDH key exchange. The first core * computation is performed by mbedtls_ecdh_gen_public(). * * \see ecp.h * * \note If \p f_rng is not NULL, it is used to implement * countermeasures against side-channel attacks. * For more information, see mbedtls_ecp_mul(). * * \param grp The ECP group to use. This must be initialized and have * domain parameters loaded, for example through * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). * \param z The destination MPI (shared secret). * This must be initialized. * \param Q The public key from another party. * This must be initialized. * \param d Our secret exponent (private key). * This must be initialized. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't need a * context argument. * * \return \c 0 on success. * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function initializes an ECDH context. * * \param ctx The ECDH context to initialize. This must not be \c NULL. */ void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx); /** * \brief This function sets up the ECDH context with the information * given. * * This function should be called after mbedtls_ecdh_init() but * before mbedtls_ecdh_make_params(). There is no need to call * this function before mbedtls_ecdh_read_params(). * * This is the first function used by a TLS server for ECDHE * ciphersuites. * * \param ctx The ECDH context to set up. This must be initialized. * \param grp_id The group id of the group to set up the context for. * * \return \c 0 on success. */ int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id); /** * \brief This function frees a context. * * \param ctx The context to free. This may be \c NULL, in which * case this function does nothing. If it is not \c NULL, * it must point to an initialized ECDH context. */ void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx); /** * \brief This function generates an EC key pair and exports its * in the format used in a TLS ServerKeyExchange handshake * message. * * This is the second function used by a TLS server for ECDHE * ciphersuites. (It is called after mbedtls_ecdh_setup().) * * \see ecp.h * * \param ctx The ECDH context to use. This must be initialized * and bound to a group, for example via mbedtls_ecdh_setup(). * \param olen The address at which to store the number of Bytes written. * \param buf The destination buffer. This must be a writable buffer of * length \p blen Bytes. * \param blen The length of the destination buffer \p buf in Bytes. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function parses the ECDHE parameters in a * TLS ServerKeyExchange handshake message. * * \note In a TLS handshake, this is the how the client * sets up its ECDHE context from the server's public * ECDHE key material. * * \see ecp.h * * \param ctx The ECDHE context to use. This must be initialized. * \param buf On input, \c *buf must be the start of the input buffer. * On output, \c *buf is updated to point to the end of the * data that has been read. On success, this is the first byte * past the end of the ServerKeyExchange parameters. * On error, this is the point at which an error has been * detected, which is usually not useful except to debug * failures. * \param end The end of the input buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx, const unsigned char **buf, const unsigned char *end); /** * \brief This function sets up an ECDH context from an EC key. * * It is used by clients and servers in place of the * ServerKeyEchange for static ECDH, and imports ECDH * parameters from the EC key information of a certificate. * * \see ecp.h * * \param ctx The ECDH context to set up. This must be initialized. * \param key The EC key to use. This must be initialized. * \param side Defines the source of the key. Possible values are: * - #MBEDTLS_ECDH_OURS: The key is ours. * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. * * \return \c 0 on success. * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side); /** * \brief This function generates a public key and exports it * as a TLS ClientKeyExchange payload. * * This is the second function used by a TLS client for ECDH(E) * ciphersuites. * * \see ecp.h * * \param ctx The ECDH context to use. This must be initialized * and bound to a group, the latter usually by * mbedtls_ecdh_read_params(). * \param olen The address at which to store the number of Bytes written. * This must not be \c NULL. * \param buf The destination buffer. This must be a writable buffer * of length \p blen Bytes. * \param blen The size of the destination buffer \p buf in Bytes. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL in case \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function parses and processes the ECDHE payload of a * TLS ClientKeyExchange message. * * This is the third function used by a TLS server for ECDH(E) * ciphersuites. (It is called after mbedtls_ecdh_setup() and * mbedtls_ecdh_make_params().) * * \see ecp.h * * \param ctx The ECDH context to use. This must be initialized * and bound to a group, for example via mbedtls_ecdh_setup(). * \param buf The pointer to the ClientKeyExchange payload. This must * be a readable buffer of length \p blen Bytes. * \param blen The length of the input buffer \p buf in Bytes. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen); /** * \brief This function derives and exports the shared secret. * * This is the last function used by both TLS client * and servers. * * \note If \p f_rng is not NULL, it is used to implement * countermeasures against side-channel attacks. * For more information, see mbedtls_ecp_mul(). * * \see ecp.h * \param ctx The ECDH context to use. This must be initialized * and have its own private key generated and the peer's * public key imported. * \param olen The address at which to store the total number of * Bytes written on success. This must not be \c NULL. * \param buf The buffer to write the generated shared key to. This * must be a writable buffer of size \p blen Bytes. * \param blen The length of the destination buffer \p buf in Bytes. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context. This may be \c NULL if \p f_rng * doesn't need a context argument. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief This function enables restartable EC computations for this * context. (Default: disabled.) * * \see \c mbedtls_ecp_set_max_ops() * * \note It is not possible to safely disable restartable * computations once enabled, except by free-ing the context, * which cancels possible in-progress operations. * * \param ctx The ECDH context to use. This must be initialized. */ void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx); #endif /* MBEDTLS_ECP_RESTARTABLE */ #ifdef __cplusplus } #endif #endif /* ecdh.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h000066400000000000000000000760711464416617300242100ustar00rootroot00000000000000/** * \file ecdsa.h * * \brief This file contains ECDSA definitions and functions. * * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in * Standards for Efficient Cryptography Group (SECG): * SEC1 Elliptic Curve Cryptography. * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECDSA_H #define MBEDTLS_ECDSA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ecp.h" #include "mbedtls/md.h" /** * \brief Maximum ECDSA signature size for a given curve bit size * * \param bits Curve size in bits * \return Maximum signature size in bytes * * \note This macro returns a compile-time constant if its argument * is one. It may evaluate its argument multiple times. */ /* * Ecdsa-Sig-Value ::= SEQUENCE { * r INTEGER, * s INTEGER * } * * For each of r and s, the value (V) may include an extra initial "0" bit. */ #define MBEDTLS_ECDSA_MAX_SIG_LEN(bits) \ (/*T,L of SEQUENCE*/ ((bits) >= 61 * 8 ? 3 : 2) + \ /*T,L of r,s*/ 2 * (((bits) >= 127 * 8 ? 3 : 2) + \ /*V of r,s*/ ((bits) + 8) / 8)) /** The maximal size of an ECDSA signature in Bytes. */ #define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN(MBEDTLS_ECP_MAX_BITS) #ifdef __cplusplus extern "C" { #endif /** * \brief The ECDSA context structure. * * \warning Performing multiple operations concurrently on the same * ECDSA context is not supported; objects of this type * should not be shared between multiple threads. * * \note pk_wrap module assumes that "ecdsa_context" is identical * to "ecp_keypair" (see for example structure * "mbedtls_eckey_info" where ECDSA sign/verify functions * are used also for EC key) */ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Internal restart context for ecdsa_verify() * * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; /** * \brief Internal restart context for ecdsa_sign() * * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** * \brief Internal restart context for ecdsa_sign_det() * * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; #endif /** * \brief General context for resuming ECDSA operations */ typedef struct { mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(ecp); /*!< base context for ECP restart and shared administrative info */ mbedtls_ecdsa_restart_ver_ctx *MBEDTLS_PRIVATE(ver); /*!< ecdsa_verify() sub-context */ mbedtls_ecdsa_restart_sig_ctx *MBEDTLS_PRIVATE(sig); /*!< ecdsa_sign() sub-context */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) mbedtls_ecdsa_restart_det_ctx *MBEDTLS_PRIVATE(det); /*!< ecdsa_sign_det() sub-context */ #endif } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_ecdsa_restart_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief This function checks whether a given group can be used * for ECDSA. * * \param gid The ECP group ID to check. * * \return \c 1 if the group can be used, \c 0 otherwise */ int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid); /** * \brief This function computes the ECDSA signature of a * previously-hashed message. * * \note The deterministic version implemented in * mbedtls_ecdsa_sign_det_ext() is usually preferred. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated * as defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized. * \param buf The content to be signed. This is usually the hash of * the original data to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX * or \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** * \brief This function computes the ECDSA signature of a * previously-hashed message, deterministic version. * * For more information, see RFC-6979: Deterministic * Usage of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA). * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized * and setup, for example through mbedtls_ecp_gen_privkey(). * \param buf The hashed content to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param md_alg The hash algorithm used to hash the original data. * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This * may be \c NULL if \p f_rng_blind doesn't need a context * parameter. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if !defined(MBEDTLS_ECDSA_SIGN_ALT) /** * \brief This function computes the ECDSA signature of a * previously-hashed message, in a restartable way. * * \note The deterministic version implemented in * mbedtls_ecdsa_sign_det_restartable() is usually * preferred. * * \note This function is like \c mbedtls_ecdsa_sign() but * it can return early and restart according to the * limit set with \c mbedtls_ecp_set_max_ops() to * reduce blocking. * * \note If the bitlength of the message hash is larger * than the bitlength of the group order, then the * hash is truncated as defined in Standards for * Efficient Cryptography Group (SECG): SEC1 Elliptic * Curve Cryptography, section 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized * and setup, for example through * mbedtls_ecp_gen_privkey(). * \param buf The hashed content to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context parameter. * \param rs_ctx The restart context to use. This may be \c NULL * to disable restarting. If it is not \c NULL, it * must point to an initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c * mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX, \c * MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX * error code on failure. */ int mbedtls_ecdsa_sign_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx); #endif /* !MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /** * \brief This function computes the ECDSA signature of a * previously-hashed message, in a restartable way. * * \note This function is like \c * mbedtls_ecdsa_sign_det_ext() but it can return * early and restart according to the limit set with * \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \note If the bitlength of the message hash is larger * than the bitlength of the group order, then the * hash is truncated as defined in Standards for * Efficient Cryptography Group (SECG): SEC1 Elliptic * Curve Cryptography, section 4.1.3, step 5. * * \see ecp.h * * \param grp The context for the elliptic curve to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param r The MPI context in which to store the first part * the signature. This must be initialized. * \param s The MPI context in which to store the second part * the signature. This must be initialized. * \param d The private signing key. This must be initialized * and setup, for example through * mbedtls_ecp_gen_privkey(). * \param buf The hashed content to be signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param md_alg The hash algorithm used to hash the original data. * \param f_rng_blind The RNG function used for blinding. This must not be * \c NULL. * \param p_rng_blind The RNG context to be passed to \p f_rng_blind. This may be * \c NULL if \p f_rng_blind doesn't need a context parameter. * \param rs_ctx The restart context to use. This may be \c NULL * to disable restarting. If it is not \c NULL, it * must point to an initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c * mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX, \c * MBEDTLS_ERR_MPI_XXX or \c MBEDTLS_ERR_ASN1_XXX * error code on failure. */ int mbedtls_ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx); #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /** * \brief This function verifies the ECDSA signature of a * previously-hashed message. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.4, step 3. * * \see ecp.h * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param buf The hashed content that was signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param Q The public key to use for verification. This must be * initialized and setup. * \param r The first integer of the signature. * This must be initialized. * \param s The second integer of the signature. * This must be initialized. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); #if !defined(MBEDTLS_ECDSA_VERIFY_ALT) /** * \brief This function verifies the ECDSA signature of a * previously-hashed message, in a restartable manner * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.4, step 3. * * \see ecp.h * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param buf The hashed content that was signed. This must be a readable * buffer of length \p blen Bytes. It may be \c NULL if * \p blen is zero. * \param blen The length of \p buf in Bytes. * \param Q The public key to use for verification. This must be * initialized and setup. * \param r The first integer of the signature. * This must be initialized. * \param s The second integer of the signature. * This must be initialized. * \param rs_ctx The restart context to use. This may be \c NULL to disable * restarting. If it is not \c NULL, it must point to an * initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * error code on failure. */ int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s, mbedtls_ecdsa_restart_ctx *rs_ctx); #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ /** * \brief This function computes the ECDSA signature and writes it * to a buffer, serialized as defined in RFC-4492: * Elliptic Curve Cryptography (ECC) Cipher Suites for * Transport Layer Security (TLS). * * \warning It is not thread-safe to use the same context in * multiple threads. * * \note The deterministic version is used if * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more * information, see RFC-6979: Deterministic Usage * of the Digital Signature Algorithm (DSA) and Elliptic * Curve Digital Signature Algorithm (ECDSA). * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.3, step 5. * * \see ecp.h * * \param ctx The ECDSA context to use. This must be initialized * and have a group and private key bound to it, for example * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). * \param md_alg The message digest that was used to hash the message. * \param hash The message hash to be signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The length of the hash \p hash in Bytes. * \param sig The buffer to which to write the signature. This must be a * writable buffer of length at least twice as large as the * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of * #MBEDTLS_ECDSA_MAX_LEN is always safe. * \param sig_size The size of the \p sig buffer in bytes. * \param slen The address at which to store the actual length of * the signature written. Must not be \c NULL. * \param f_rng The RNG function. This must not be \c NULL if * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, * it is used only for blinding and may be set to \c NULL, but * doing so is DEPRECATED. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't use a context. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function computes the ECDSA signature and writes it * to a buffer, in a restartable way. * * \see \c mbedtls_ecdsa_write_signature() * * \note This function is like \c mbedtls_ecdsa_write_signature() * but it can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param ctx The ECDSA context to use. This must be initialized * and have a group and private key bound to it, for example * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). * \param md_alg The message digest that was used to hash the message. * \param hash The message hash to be signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The length of the hash \p hash in Bytes. * \param sig The buffer to which to write the signature. This must be a * writable buffer of length at least twice as large as the * size of the curve used, plus 9. For example, 73 Bytes if * a 256-bit curve is used. A buffer length of * #MBEDTLS_ECDSA_MAX_LEN is always safe. * \param sig_size The size of the \p sig buffer in bytes. * \param slen The address at which to store the actual length of * the signature written. Must not be \c NULL. * \param f_rng The RNG function. This must not be \c NULL if * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, * it is unused and may be set to \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng is \c NULL or doesn't use a context. * \param rs_ctx The restart context to use. This may be \c NULL to disable * restarting. If it is not \c NULL, it must point to an * initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx); /** * \brief This function reads and verifies an ECDSA signature. * * \note If the bitlength of the message hash is larger than the * bitlength of the group order, then the hash is truncated as * defined in Standards for Efficient Cryptography Group * (SECG): SEC1 Elliptic Curve Cryptography, section * 4.1.4, step 3. * * \see ecp.h * * \param ctx The ECDSA context to use. This must be initialized * and have a group and public key bound to it. * \param hash The message hash that was signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The size of the hash \p hash. * \param sig The signature to read and verify. This must be a readable * buffer of length \p slen Bytes. * \param slen The size of \p sig in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid * signature in \p sig, but its length is less than \p siglen. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen); /** * \brief This function reads and verifies an ECDSA signature, * in a restartable way. * * \see \c mbedtls_ecdsa_read_signature() * * \note This function is like \c mbedtls_ecdsa_read_signature() * but it can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param ctx The ECDSA context to use. This must be initialized * and have a group and public key bound to it. * \param hash The message hash that was signed. This must be a readable * buffer of length \p hlen Bytes. * \param hlen The size of the hash \p hash. * \param sig The signature to read and verify. This must be a readable * buffer of length \p slen Bytes. * \param slen The size of \p sig in Bytes. * \param rs_ctx The restart context to use. This may be \c NULL to disable * restarting. If it is not \c NULL, it must point to an * initialized restart context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid * signature in \p sig, but its length is less than \p siglen. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx); /** * \brief This function generates an ECDSA keypair on the given curve. * * \see ecp.h * * \param ctx The ECDSA context to store the keypair in. * This must be initialized. * \param gid The elliptic curve to use. One of the various * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function sets up an ECDSA context from an EC key pair. * * \see ecp.h * * \param ctx The ECDSA context to setup. This must be initialized. * \param key The EC key to use. This must be initialized and hold * a private-public key pair or a public key. In the former * case, the ECDSA context may be used for signature creation * and verification after this call. In the latter case, it * may be used for signature verification. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. */ int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key); /** * \brief This function initializes an ECDSA context. * * \param ctx The ECDSA context to initialize. * This must not be \c NULL. */ void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx); /** * \brief This function frees an ECDSA context. * * \param ctx The ECDSA context to free. This may be \c NULL, * in which case this function does nothing. If it * is not \c NULL, it must be initialized. */ void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx); #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context. * * \param ctx The restart context to initialize. * This must not be \c NULL. */ void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx); /** * \brief Free the components of a restart context. * * \param ctx The restart context to free. This may be \c NULL, * in which case this function does nothing. If it * is not \c NULL, it must be initialized. */ void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx); #endif /* MBEDTLS_ECP_RESTARTABLE */ #ifdef __cplusplus } #endif #endif /* ecdsa.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h000066400000000000000000000310351464416617300245220ustar00rootroot00000000000000/** * \file ecjpake.h * * \brief Elliptic curve J-PAKE */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECJPAKE_H #define MBEDTLS_ECJPAKE_H #include "mbedtls/private_access.h" /* * J-PAKE is a password-authenticated key exchange that allows deriving a * strong shared secret from a (potentially low entropy) pre-shared * passphrase, with forward secrecy and mutual authentication. * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling * * This file implements the Elliptic Curve variant of J-PAKE, * as defined in Chapter 7.4 of the Thread v1.0 Specification, * available to members of the Thread Group http://threadgroup.org/ * * As the J-PAKE algorithm is inherently symmetric, so is our API. * Each party needs to send its first round message, in any order, to the * other party, then each sends its second round message, in any order. * The payloads are serialized in a way suitable for use in TLS, but could * also be use outside TLS. */ #include "mbedtls/build_info.h" #include "mbedtls/ecp.h" #include "mbedtls/md.h" #ifdef __cplusplus extern "C" { #endif /** * Roles in the EC J-PAKE exchange */ typedef enum { MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ MBEDTLS_ECJPAKE_SERVER, /**< Server */ MBEDTLS_ECJPAKE_NONE, /**< Undefined */ } mbedtls_ecjpake_role; #if !defined(MBEDTLS_ECJPAKE_ALT) /** * EC J-PAKE context structure. * * J-PAKE is a symmetric protocol, except for the identifiers used in * Zero-Knowledge Proofs, and the serialization of the second message * (KeyExchange) as defined by the Thread spec. * * In order to benefit from this symmetry, we choose a different naming * convention from the Thread v1.0 spec. Correspondence is indicated in the * description as a pair C: client name, S: server name */ typedef struct mbedtls_ecjpake_context { mbedtls_md_type_t MBEDTLS_PRIVATE(md_type); /**< Hash to use */ mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /**< Elliptic curve */ mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); /**< Are we client or server? */ int MBEDTLS_PRIVATE(point_format); /**< Format for point export */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xm1); /**< My public key 1 C: X1, S: X3 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xm2); /**< My public key 2 C: X2, S: X4 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xp1); /**< Peer public key 1 C: X3, S: X1 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xp2); /**< Peer public key 2 C: X4, S: X2 */ mbedtls_ecp_point MBEDTLS_PRIVATE(Xp); /**< Peer public key C: Xs, S: Xc */ mbedtls_mpi MBEDTLS_PRIVATE(xm1); /**< My private key 1 C: x1, S: x3 */ mbedtls_mpi MBEDTLS_PRIVATE(xm2); /**< My private key 2 C: x2, S: x4 */ mbedtls_mpi MBEDTLS_PRIVATE(s); /**< Pre-shared secret (passphrase) */ } mbedtls_ecjpake_context; #else /* MBEDTLS_ECJPAKE_ALT */ #include "ecjpake_alt.h" #endif /* MBEDTLS_ECJPAKE_ALT */ /** * \brief Initialize an ECJPAKE context. * * \param ctx The ECJPAKE context to initialize. * This must not be \c NULL. */ void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx); /** * \brief Set up an ECJPAKE context for use. * * \note Currently the only values for hash/curve allowed by the * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. * * \param ctx The ECJPAKE context to set up. This must be initialized. * \param role The role of the caller. This must be either * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. * \param hash The identifier of the hash function to use, * for example #MBEDTLS_MD_SHA256. * \param curve The identifier of the elliptic curve to use, * for example #MBEDTLS_ECP_DP_SECP256R1. * \param secret The pre-shared secret (passphrase). This must be * a readable not empty buffer of length \p len Bytes. It need * only be valid for the duration of this call. * \param len The length of the pre-shared secret \p secret. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, mbedtls_ecjpake_role role, mbedtls_md_type_t hash, mbedtls_ecp_group_id curve, const unsigned char *secret, size_t len); /** * \brief Set the point format for future reads and writes. * * \param ctx The ECJPAKE context to configure. * \param point_format The point format to use: * #MBEDTLS_ECP_PF_UNCOMPRESSED (default) * or #MBEDTLS_ECP_PF_COMPRESSED. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p point_format * is invalid. */ int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, int point_format); /** * \brief Check if an ECJPAKE context is ready for use. * * \param ctx The ECJPAKE context to check. This must be * initialized. * * \return \c 0 if the context is ready for use. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. */ int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx); /** * \brief Generate and write the first round message * (TLS: contents of the Client/ServerHello extension, * excluding extension type and length bytes). * * \param ctx The ECJPAKE context to use. This must be * initialized and set up. * \param buf The buffer to write the contents to. This must be a * writable buffer of length \p len Bytes. * \param len The length of \p buf in Bytes. * \param olen The address at which to store the total number * of Bytes written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Read and process the first round message * (TLS: contents of the Client/ServerHello extension, * excluding extension type and length bytes). * * \param ctx The ECJPAKE context to use. This must be initialized * and set up. * \param buf The buffer holding the first round message. This must * be a readable buffer of length \p len Bytes. * \param len The length in Bytes of \p buf. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len); /** * \brief Generate and write the second round message * (TLS: contents of the Client/ServerKeyExchange). * * \param ctx The ECJPAKE context to use. This must be initialized, * set up, and already have performed round one. * \param buf The buffer to write the round two contents to. * This must be a writable buffer of length \p len Bytes. * \param len The size of \p buf in Bytes. * \param olen The address at which to store the total number of Bytes * written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Read and process the second round message * (TLS: contents of the Client/ServerKeyExchange). * * \param ctx The ECJPAKE context to use. This must be initialized * and set up and already have performed round one. * \param buf The buffer holding the second round message. This must * be a readable buffer of length \p len Bytes. * \param len The length in Bytes of \p buf. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len); /** * \brief Derive the shared secret * (TLS: Pre-Master Secret). * * \param ctx The ECJPAKE context to use. This must be initialized, * set up and have performed both round one and two. * \param buf The buffer to write the derived secret to. This must * be a writable buffer of length \p len Bytes. * \param len The length of \p buf in Bytes. * \param olen The address at which to store the total number of Bytes * written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Write the shared key material to be passed to a Key * Derivation Function as described in RFC8236. * * \param ctx The ECJPAKE context to use. This must be initialized, * set up and have performed both round one and two. * \param buf The buffer to write the derived secret to. This must * be a writable buffer of length \p len Bytes. * \param len The length of \p buf in Bytes. * \param olen The address at which to store the total number of bytes * written to \p buf. This must not be \c NULL. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This * may be \c NULL if \p f_rng doesn't use a context. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This clears an ECJPAKE context and frees any * embedded data structure. * * \param ctx The ECJPAKE context to free. This may be \c NULL, * in which case this function does nothing. If it is not * \c NULL, it must point to an initialized ECJPAKE context. */ void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if a test failed */ int mbedtls_ecjpake_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* ecjpake.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h000066400000000000000000002112661464416617300236750ustar00rootroot00000000000000/** * \file ecp.h * * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). * * The use of ECP in cryptography and TLS is defined in * Standards for Efficient Cryptography Group (SECG): SEC1 * Elliptic Curve Cryptography and * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites * for Transport Layer Security (TLS). * * RFC-2409: The Internet Key Exchange (IKE) defines ECP * group types. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECP_H #define MBEDTLS_ECP_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include "mbedtls/bignum.h" /* * ECP error codes */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /** The buffer is too small to write to. */ #define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /** The requested feature is not available, for example, the requested curve is not supported. */ #define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /** The signature is not valid. */ #define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /** Memory allocation failed. */ #define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /** Generation of random value, such as ephemeral key, failed. */ #define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /** Invalid private or public key. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /** The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /** Operation in progress, call again with the same parameters to continue. */ #define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /* Flags indicating whether to include code that is specific to certain * types of curves. These flags are for internal library use only. */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SM2_ENABLED) #define MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define MBEDTLS_ECP_MONTGOMERY_ENABLED #endif #ifdef __cplusplus extern "C" { #endif /** * Domain-parameter identifiers: curve, subgroup, and generator. * * \note Only curves over prime fields are supported. * * \warning This library does not support validation of arbitrary domain * parameters. Therefore, only standardized domain parameters from trusted * sources should be used. See mbedtls_ecp_group_load(). */ /* Note: when adding a new curve: * - Add it at the end of this enum, otherwise you'll break the ABI by * changing the numerical value for existing curves. * - Increment MBEDTLS_ECP_DP_MAX below if needed. * - Update the calculation of MBEDTLS_ECP_MAX_BITS below. * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to * mbedtls_config.h. * - List the curve as a dependency of MBEDTLS_ECP_C and * MBEDTLS_ECDSA_C if supported in check_config.h. * - Add the curve to the appropriate curve type macro * MBEDTLS_ECP_yyy_ENABLED above. * - Add the necessary definitions to ecp_curves.c. * - Add the curve to the ecp_supported_curves array in ecp.c. * - Add the curve to applicable profiles in x509_crt.c. * - Add the curve to applicable presets in ssl_tls.c. */ typedef enum { MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ MBEDTLS_ECP_DP_SM2, /*!< Domain parameters for SM2. */ } mbedtls_ecp_group_id; /** * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. */ #define MBEDTLS_ECP_DP_MAX 14 /* * Curve types */ typedef enum { MBEDTLS_ECP_TYPE_NONE = 0, MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ } mbedtls_ecp_curve_type; /** * Curve information, for use by other modules. * * The fields of this structure are part of the public API and can be * accessed directly by applications. Future versions of the library may * add extra fields or reorder existing fields. */ typedef struct mbedtls_ecp_curve_info { mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ uint16_t bit_size; /*!< The curve size in bits. */ const char *name; /*!< A human-friendly name. */ } mbedtls_ecp_curve_info; /** * \brief The ECP point structure, in Jacobian coordinates. * * \note All functions expect and return points satisfying * the following condition: Z == 0 or * Z == 1. Other values of \p Z are * used only by internal functions. * The point is zero, or "at infinity", if Z == 0. * Otherwise, \p X and \p Y are its standard (affine) * coordinates. */ typedef struct mbedtls_ecp_point { mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< The X coordinate of the ECP point. */ mbedtls_mpi MBEDTLS_PRIVATE(Y); /*!< The Y coordinate of the ECP point. */ mbedtls_mpi MBEDTLS_PRIVATE(Z); /*!< The Z coordinate of the ECP point. */ } mbedtls_ecp_point; #if !defined(MBEDTLS_ECP_ALT) /* * default Mbed TLS elliptic curve arithmetic implementation * * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an * alternative implementation for the whole module and it will replace this * one.) */ /** * \brief The ECP group structure. * * We consider two types of curve equations: *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P * (SEC1 + RFC-4492)
  • *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, * Curve448)
* In both cases, the generator (\p G) for a prime-order subgroup is fixed. * * For Short Weierstrass, this subgroup is the whole curve, and its * cardinality is denoted by \p N. Our code requires that \p N is an * odd prime as mbedtls_ecp_mul() requires an odd number, and * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. * * The default implementation only initializes \p A without setting it to the * authentic value for curves with A = -3(SECP256R1, etc), in which * case you need to load \p A by yourself when using domain parameters directly, * for example: * \code * mbedtls_mpi_init(&A); * mbedtls_ecp_group_init(&grp); * CHECK_RETURN(mbedtls_ecp_group_load(&grp, grp_id)); * if (mbedtls_ecp_group_a_is_minus_3(&grp)) { * CHECK_RETURN(mbedtls_mpi_sub_int(&A, &grp.P, 3)); * } else { * CHECK_RETURN(mbedtls_mpi_copy(&A, &grp.A)); * } * * do_something_with_a(&A); * * cleanup: * mbedtls_mpi_free(&A); * mbedtls_ecp_group_free(&grp); * \endcode * * For Montgomery curves, we do not store \p A, but (A + 2) / 4, * which is the quantity used in the formulas. Additionally, \p nbits is * not the size of \p N but the required size for private keys. * * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer * which is congruent mod \p P to the given MPI, and is close enough to \p pbits * in size, so that it may be efficiently brought in the 0..P-1 range by a few * additions or subtractions. Therefore, it is only an approximative modular * reduction. It must return 0 on success and non-zero on failure. * * \note Alternative implementations of the ECP module must obey the * following constraints. * * Group IDs must be distinct: if two group structures have * the same ID, then they must be identical. * * The fields \c id, \c P, \c A, \c B, \c G, \c N, * \c pbits and \c nbits must have the same type and semantics * as in the built-in implementation. * They must be available for reading, but direct modification * of these fields does not need to be supported. * They do not need to be at the same offset in the structure. */ typedef struct mbedtls_ecp_group { mbedtls_ecp_group_id id; /*!< An internal group identifier. */ mbedtls_mpi P; /*!< The prime modulus of the base field. */ mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. Note that \p A is not set to the authentic value in some cases. Refer to detailed description of ::mbedtls_ecp_group if using domain parameters in the structure. For Montgomery curves: (A + 2) / 4. */ mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. For Montgomery curves: unused. */ mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ mbedtls_mpi N; /*!< The order of \p G. */ size_t pbits; /*!< The number of bits in \p P.*/ size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. For Montgomery curves: the number of bits in the private keys. */ /* End of public fields */ unsigned int MBEDTLS_PRIVATE(h); /*!< \internal 1 if the constants are static. */ int(*MBEDTLS_PRIVATE(modp))(mbedtls_mpi *); /*!< The function for fast pseudo-reduction mod \p P (see above).*/ int(*MBEDTLS_PRIVATE(t_pre))(mbedtls_ecp_point *, void *); /*!< Unused. */ int(*MBEDTLS_PRIVATE(t_post))(mbedtls_ecp_point *, void *); /*!< Unused. */ void *MBEDTLS_PRIVATE(t_data); /*!< Unused. */ mbedtls_ecp_point *MBEDTLS_PRIVATE(T); /*!< Pre-computed points for ecp_mul_comb(). */ size_t MBEDTLS_PRIVATE(T_size); /*!< The number of dynamic allocated pre-computed points. */ } mbedtls_ecp_group; /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h, or define them using the compiler command line. * \{ */ #if !defined(MBEDTLS_ECP_WINDOW_SIZE) /* * Maximum "window" size used for point multiplication. * Default: a point where higher memory usage yields diminishing performance * returns. * Minimum value: 2. Maximum value: 7. * * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) * points used for point multiplication. This value is directly tied to EC * peak memory usage, so decreasing it by one should roughly cut memory usage * by two (if large curves are in use). * * Reduction in size may reduce speed, but larger curves are impacted first. * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): * w-size: 6 5 4 3 2 * 521 145 141 135 120 97 * 384 214 209 198 177 146 * 256 320 320 303 262 226 * 224 475 475 453 398 342 * 192 640 640 633 587 476 */ #define MBEDTLS_ECP_WINDOW_SIZE 4 /**< The maximum window size used. */ #endif /* MBEDTLS_ECP_WINDOW_SIZE */ #if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) /* * Trade code size for speed on fixed-point multiplication. * * This speeds up repeated multiplication of the generator (that is, the * multiplication in ECDSA signatures, and half of the multiplications in * ECDSA verification and ECDHE) by a factor roughly 3 to 4. * * For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes * of code size if n < 384 and 8n otherwise. * * Change this value to 0 to reduce code size. */ #define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ #endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ /** \} name SECTION: Module settings */ #else /* MBEDTLS_ECP_ALT */ #include "ecp_alt.h" #endif /* MBEDTLS_ECP_ALT */ /** * The maximum size of the groups, that is, of \c N and \c P. */ #if !defined(MBEDTLS_ECP_LIGHT) /* Dummy definition to help code that has optional ECP support and * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */ #define MBEDTLS_ECP_MAX_BITS 1 /* Note: the curves must be listed in DECREASING size! */ #elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 521 #elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 512 #elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) #define MBEDTLS_ECP_MAX_BITS 448 #elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 384 #elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 384 #elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 256 #elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 256 #elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 256 #elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #define MBEDTLS_ECP_MAX_BITS 255 #elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 225 // n is slightly above 2^224 #elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 224 #elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 192 #elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #define MBEDTLS_ECP_MAX_BITS 192 #else /* !MBEDTLS_ECP_LIGHT */ #error "Missing definition of MBEDTLS_ECP_MAX_BITS" #endif /* !MBEDTLS_ECP_LIGHT */ #define MBEDTLS_ECP_MAX_BYTES ((MBEDTLS_ECP_MAX_BITS + 7) / 8) #define MBEDTLS_ECP_MAX_PT_LEN (2 * MBEDTLS_ECP_MAX_BYTES + 1) #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Internal restart context for multiplication * * \note Opaque struct */ typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; /** * \brief Internal restart context for ecp_muladd() * * \note Opaque struct */ typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; /** * \brief General context for resuming ECC operations */ typedef struct { unsigned MBEDTLS_PRIVATE(ops_done); /*!< current ops count */ unsigned MBEDTLS_PRIVATE(depth); /*!< call depth (0 = top-level) */ mbedtls_ecp_restart_mul_ctx *MBEDTLS_PRIVATE(rsm); /*!< ecp_mul_comb() sub-context */ mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(ma); /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; /* * Operation counts for restartable functions */ #define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ #define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ #define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ #define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ /** * \brief Internal; for restartable functions in other modules. * Check and update basic ops budget. * * \param grp Group structure * \param rs_ctx Restart context * \param ops Number of basic ops to do * * \return \c 0 if doing \p ops basic ops is still allowed, * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. */ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops); /* Utility macro for checking and updating ops budget */ #define MBEDTLS_ECP_BUDGET(ops) \ MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, rs_ctx, \ (unsigned) (ops))); #else /* MBEDTLS_ECP_RESTARTABLE */ #define MBEDTLS_ECP_BUDGET(ops) /* no-op; for compatibility */ /* We want to declare restartable versions of existing functions anyway */ typedef void mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief The ECP key-pair structure. * * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. * * \note Members are deliberately in the same order as in the * ::mbedtls_ecdsa_context structure. */ typedef struct mbedtls_ecp_keypair { mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< Elliptic curve and base point */ mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< our secret value */ mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< our public value */ } mbedtls_ecp_keypair; /** * The uncompressed point format for Short Weierstrass curves * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). */ #define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /** * The compressed point format for Short Weierstrass curves * (MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX). * * \warning While this format is supported for all concerned curves for * writing, when it comes to parsing, it is not supported for all * curves. Specifically, parsing compressed points on * MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1 is not * supported. */ #define MBEDTLS_ECP_PF_COMPRESSED 1 /* * Some other constants from RFC 4492 */ #define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Set the maximum number of basic operations done in a row. * * If more operations are needed to complete a computation, * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the * function performing the computation. It is then the * caller's responsibility to either call again with the same * parameters until it returns 0 or an error code; or to free * the restart context if the operation is to be aborted. * * It is strictly required that all input parameters and the * restart context be the same on successive calls for the * same operation, but output parameters need not be the * same; they must not be used until the function finally * returns 0. * * This only applies to functions whose documentation * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the * SSL module). For functions that accept a "restart context" * argument, passing NULL disables restart and makes the * function equivalent to the function with the same name * with \c _restartable removed. For functions in the ECDH * module, restart is disabled unless the function accepts * an "ECDH context" argument and * mbedtls_ecdh_enable_restart() was previously called on * that context. For function in the SSL module, restart is * only enabled for specific sides and key exchanges * (currently only for clients and ECDHE-ECDSA). * * \warning Using the PSA interruptible interfaces with keys in local * storage and no accelerator driver will also call this * function to set the values specified via those interfaces, * overwriting values previously set. Care should be taken if * mixing these two interfaces. * * \param max_ops Maximum number of basic operations done in a row. * Default: 0 (unlimited). * Lower (non-zero) values mean ECC functions will block for * a lesser maximum amount of time. * * \note A "basic operation" is defined as a rough equivalent of a * multiplication in GF(p) for the NIST P-256 curve. * As an indication, with default settings, a scalar * multiplication (full run of \c mbedtls_ecp_mul()) is: * - about 3300 basic operations for P-256 * - about 9400 basic operations for P-384 * * \note Very low values are not always respected: sometimes * functions need to block for a minimum number of * operations, and will do so even if max_ops is set to a * lower value. That minimum depends on the curve size, and * can be made lower by decreasing the value of * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the * lowest effective value for various curves and values of * that parameter (w for short): * w=6 w=5 w=4 w=3 w=2 * P-256 208 208 160 136 124 * P-384 682 416 320 272 248 * P-521 1364 832 640 544 496 * * \note This setting is currently ignored by Curve25519. */ void mbedtls_ecp_set_max_ops(unsigned max_ops); /** * \brief Check if restart is enabled (max_ops != 0) * * \return \c 0 if \c max_ops == 0 (restart disabled) * \return \c 1 otherwise (restart enabled) */ int mbedtls_ecp_restart_is_enabled(void); #endif /* MBEDTLS_ECP_RESTARTABLE */ /* * Get the type of a curve */ mbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp); /** * \brief This function retrieves the information defined in * mbedtls_ecp_curve_info() for all supported curves. * * \note This function returns information about all curves * supported by the library. Some curves may not be * supported for all algorithms. Call mbedtls_ecdh_can_do() * or mbedtls_ecdsa_can_do() to check if a curve is * supported for ECDH or ECDSA. * * \return A statically allocated array. The last entry is 0. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void); /** * \brief This function retrieves the list of internal group * identifiers of all supported curves in the order of * preference. * * \note This function returns information about all curves * supported by the library. Some curves may not be * supported for all algorithms. Call mbedtls_ecdh_can_do() * or mbedtls_ecdsa_can_do() to check if a curve is * supported for ECDH or ECDSA. * * \return A statically allocated array, * terminated with MBEDTLS_ECP_DP_NONE. */ const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void); /** * \brief This function retrieves curve information from an internal * group identifier. * * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. * * \return The associated curve information on success. * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id); /** * \brief This function retrieves curve information from a TLS * NamedCurve value. * * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. * * \return The associated curve information on success. * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id); /** * \brief This function retrieves curve information from a * human-readable name. * * \param name The human-readable name. * * \return The associated curve information on success. * \return NULL on failure. */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name); /** * \brief This function initializes a point as zero. * * \param pt The point to initialize. */ void mbedtls_ecp_point_init(mbedtls_ecp_point *pt); /** * \brief This function initializes an ECP group context * without loading any domain parameters. * * \note After this function is called, domain parameters * for various ECP groups can be loaded through the * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() * functions. */ void mbedtls_ecp_group_init(mbedtls_ecp_group *grp); /** * \brief This function initializes a key pair as an invalid one. * * \param key The key pair to initialize. */ void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key); /** * \brief This function frees the components of a point. * * \param pt The point to free. */ void mbedtls_ecp_point_free(mbedtls_ecp_point *pt); /** * \brief This function frees the components of an ECP group. * * \param grp The group to free. This may be \c NULL, in which * case this function returns immediately. If it is not * \c NULL, it must point to an initialized ECP group. */ void mbedtls_ecp_group_free(mbedtls_ecp_group *grp); /** * \brief This function frees the components of a key pair. * * \param key The key pair to free. This may be \c NULL, in which * case this function returns immediately. If it is not * \c NULL, it must point to an initialized ECP key pair. */ void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key); #if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context. * * \param ctx The restart context to initialize. This must * not be \c NULL. */ void mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx); /** * \brief Free the components of a restart context. * * \param ctx The restart context to free. This may be \c NULL, in which * case this function returns immediately. If it is not * \c NULL, it must point to an initialized restart context. */ void mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx); #endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief This function copies the contents of point \p Q into * point \p P. * * \param P The destination point. This must be initialized. * \param Q The source point. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code for other kinds of failure. */ int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); /** * \brief This function copies the contents of group \p src into * group \p dst. * * \param dst The destination group. This must be initialized. * \param src The source group. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src); /** * \brief This function sets a point to the point at infinity. * * \param pt The point to set. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt); /** * \brief This function checks if a point is the point at infinity. * * \param pt The point to test. This must be initialized. * * \return \c 1 if the point is zero. * \return \c 0 if the point is non-zero. * \return A negative error code on failure. */ int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt); /** * \brief This function compares two points. * * \note This assumes that the points are normalized. Otherwise, * they may compare as "not equal" even if they are. * * \param P The first point to compare. This must be initialized. * \param Q The second point to compare. This must be initialized. * * \return \c 0 if the points are equal. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. */ int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); /** * \brief This function imports a non-zero point from two ASCII * strings. * * \param P The destination point. This must be initialized. * \param radix The numeric base of the input. * \param x The first affine coordinate, as a null-terminated string. * \param y The second affine coordinate, as a null-terminated string. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. */ int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, const char *x, const char *y); /** * \brief This function exports a point into unsigned binary data. * * \param grp The group to which the point should belong. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param P The point to export. This must be initialized. * \param format The point format. This must be either * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. * (For groups without these formats, this parameter is * ignored. But it still has to be either of the above * values.) * \param olen The address at which to store the length of * the output in Bytes. This must not be \c NULL. * \param buf The output buffer. This must be a writable buffer * of length \p buflen Bytes. * \param buflen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer * is too small to hold the point. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * or the export for the given group is not implemented. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen); /** * \brief This function imports a point from unsigned binary data. * * \note This function does not check that the point actually * belongs to the given group, see mbedtls_ecp_check_pubkey() * for that. * * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for * limitations. * * \param grp The group to which the point should belong. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param P The destination context to import the point to. * This must be initialized. * \param buf The input buffer. This must be a readable buffer * of length \p ilen Bytes. * \param ilen The length of the input buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the * given group is not implemented. */ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, const unsigned char *buf, size_t ilen); /** * \brief This function imports a point from a TLS ECPoint record. * * \note On function return, \p *buf is updated to point immediately * after the ECPoint record. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param pt The destination point. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the buffer. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization * failure. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. */ int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t len); /** * \brief This function exports a point as a TLS ECPoint record * defined in RFC 4492, Section 5.4. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param pt The point to be exported. This must be initialized. * \param format The point format to use. This must be either * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. * \param olen The address at which to store the length in Bytes * of the data written. * \param buf The target buffer. This must be a writable buffer of * length \p blen Bytes. * \param blen The length of the target buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer * is too small to hold the exported point. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen); /** * \brief This function sets up an ECP group context * from a standardized set of domain parameters. * * \note The index should be a value of the NamedCurve enum, * as defined in RFC-4492: Elliptic Curve Cryptography * (ECC) Cipher Suites for Transport Layer Security (TLS), * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. * * \param grp The group context to setup. This must be initialized. * \param id The identifier of the domain parameter set to load. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't * correspond to a known group. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id); /** * \brief This function sets up an ECP group context from a TLS * ECParameters record as defined in RFC 4492, Section 5.4. * * \note The read pointer \p buf is updated to point right after * the ECParameters record on exit. * * \param grp The group context to setup. This must be initialized. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the input buffer \c *buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not * recognized. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len); /** * \brief This function extracts an elliptic curve group ID from a * TLS ECParameters record as defined in RFC 4492, Section 5.4. * * \note The read pointer \p buf is updated to point right after * the ECParameters record on exit. * * \param grp The address at which to store the group id. * This must not be \c NULL. * \param buf The address of the pointer to the start of the input buffer. * \param len The length of the input buffer \c *buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not * recognized. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, const unsigned char **buf, size_t len); /** * \brief This function exports an elliptic curve as a TLS * ECParameters record as defined in RFC 4492, Section 5.4. * * \param grp The ECP group to be exported. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param olen The address at which to store the number of Bytes written. * This must not be \c NULL. * \param buf The buffer to write to. This must be a writable buffer * of length \p blen Bytes. * \param blen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output * buffer is too small to hold the exported group. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen); /** * \brief This function performs a scalar multiplication of a point * by an integer: \p R = \p m * \p P. * * It is not thread-safe to use same group in multiple threads. * * \note To prevent timing attacks, this function * executes the exact same sequence of base-field * operations for any valid \p m. It avoids any if-branch or * array index depending on the value of \p m. It also uses * \p f_rng to randomize some intermediate results. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply. This must be initialized. * \param P The point to multiply. This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private * key, or \p P is not a valid public key. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function performs multiplication of a point by * an integer: \p R = \p m * \p P in a restartable way. * * \see mbedtls_ecp_mul() * * \note This function does the same as \c mbedtls_ecp_mul(), but * it can return early and restart according to the limit set * with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply. This must be initialized. * \param P The point to multiply. This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private * key, or \p P is not a valid public key. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx); #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /** * \brief This function checks if domain parameter A of the curve is * \c -3. * * \note This function is only defined for short Weierstrass curves. * It may not be included in builds without any short * Weierstrass curve. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * * \return \c 1 if A = -3. * \return \c 0 Otherwise. */ static inline int mbedtls_ecp_group_a_is_minus_3(const mbedtls_ecp_group *grp) { return grp->A.MBEDTLS_PRIVATE(p) == NULL; } /** * \brief This function performs multiplication and addition of two * points by integers: \p R = \p m * \p P + \p n * \p Q * * It is not thread-safe to use same group in multiple threads. * * \note In contrast to mbedtls_ecp_mul(), this function does not * guarantee a constant execution flow and timing. * * \note This function is only defined for short Weierstrass curves. * It may not be included in builds without any short * Weierstrass curve. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply \p P. * This must be initialized. * \param P The point to multiply by \p m. This must be initialized. * \param n The integer by which to multiply \p Q. * This must be initialized. * \param Q The point to be multiplied by \p n. * This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not * valid private keys, or \p P or \p Q are not valid public * keys. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not * designate a short Weierstrass curve. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q); /** * \brief This function performs multiplication and addition of two * points by integers: \p R = \p m * \p P + \p n * \p Q in a * restartable way. * * \see \c mbedtls_ecp_muladd() * * \note This function works the same as \c mbedtls_ecp_muladd(), * but it can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \note This function is only defined for short Weierstrass curves. * It may not be included in builds without any short * Weierstrass curve. * * \param grp The ECP group to use. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param R The point in which to store the result of the calculation. * This must be initialized. * \param m The integer by which to multiply \p P. * This must be initialized. * \param P The point to multiply by \p m. This must be initialized. * \param n The integer by which to multiply \p Q. * This must be initialized. * \param Q The point to be multiplied by \p n. * This must be initialized. * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not * valid private keys, or \p P or \p Q are not valid public * keys. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not * designate a short Weierstrass curve. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_muladd_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx); #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ /** * \brief This function checks that a point is a valid public key * on this curve. * * It only checks that the point is non-zero, has * valid coordinates and lies on the curve. It does not verify * that it is indeed a multiple of \c G. This additional * check is computationally more expensive, is not required * by standards, and should not be necessary if the group * used has a small cofactor. In particular, it is useless for * the NIST groups which all have a cofactor of 1. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure, to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group the point should belong to. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param pt The point to check. This must be initialized. * * \return \c 0 if the point is a valid public key. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not * a valid public key for the given curve. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt); /** * \brief This function checks that an \c mbedtls_mpi is a * valid private key for this curve. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group the private key should belong to. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param d The integer to check. This must be initialized. * * \return \c 0 if the point is a valid private key. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid * private key for the given curve. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d); /** * \brief This function generates a private key. * * \param grp The ECP group to generate a private key for. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param d The destination MPI (secret part). This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function generates a keypair with a configurable base * point. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group to generate a key pair for. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param G The base point to use. This must be initialized * and belong to \p grp. It replaces the default base * point \c grp->G used by mbedtls_ecp_gen_keypair(). * \param d The destination MPI (secret part). * This must be initialized. * \param Q The destination point (public part). * This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function generates an ECP keypair. * * \note This function uses bare components rather than an * ::mbedtls_ecp_keypair structure to ease use with other * structures, such as ::mbedtls_ecdh_context or * ::mbedtls_ecdsa_context. * * \param grp The ECP group to generate a key pair for. * This must be initialized and have group parameters * set, for example through mbedtls_ecp_group_load(). * \param d The destination MPI (secret part). * This must be initialized. * \param Q The destination point (public part). * This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief This function generates an ECP key. * * \param grp_id The ECP group identifier. * \param key The destination key. This must be initialized. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code * on failure. */ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \brief Set the public key in a key pair object. * * \note This function does not check that the point actually * belongs to the given group. Call mbedtls_ecp_check_pubkey() * on \p Q before calling this function to check that. * * \note This function does not check that the public key matches * the private key that is already in \p key, if any. * To check the consistency of the resulting key pair object, * call mbedtls_ecp_check_pub_priv() after setting both * the public key and the private key. * * \param grp_id The ECP group identifier. * \param key The key pair object. It must be initialized. * If its group has already been set, it must match \p grp_id. * If its group has not been set, it will be set to \p grp_id. * If the public key has already been set, it is overwritten. * \param Q The public key to copy. This must be a point on the * curve indicated by \p grp_id. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p key does not * match \p grp_id. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for * the group is not implemented. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const mbedtls_ecp_point *Q); /** * \brief This function reads an elliptic curve private key. * * \note This function does not set the public key in the * key pair object. Without a public key, the key pair object * cannot be used with operations that require the public key. * Call mbedtls_ecp_keypair_calc_public() to set the public * key from the private key. Alternatively, you can call * mbedtls_ecp_set_public_key() to set the public key part, * and then optionally mbedtls_ecp_check_pub_priv() to check * that the private and public parts are consistent. * * \note If a public key has already been set in the key pair * object, this function does not check that it is consistent * with the private key. Call mbedtls_ecp_check_pub_priv() * after setting both the public key and the private key * to make that check. * * \param grp_id The ECP group identifier. * \param key The destination key. * \param buf The buffer containing the binary representation of the * key. (Big endian integer for Weierstrass curves, byte * string for Montgomery curves.) * \param buflen The length of the buffer in bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is * invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for * the group is not implemented. * \return Another negative error code on different kinds of failure. */ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const unsigned char *buf, size_t buflen); #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function exports an elliptic curve private key. * * \deprecated Note that although this function accepts an output * buffer that is smaller or larger than the key, most key * import interfaces require the output to have exactly * key's nominal length. It is generally simplest to * pass the key's nominal length as \c buflen, after * checking that the output buffer is large enough. * See the description of the \p buflen parameter for * how to calculate the nominal length. * To avoid this difficulty, use mbedtls_ecp_write_key_ext() * instead. * mbedtls_ecp_write_key() is deprecated and will be * removed in a future version of the library. * * \note If the private key was not set in \p key, * the output is unspecified. Future versions * may return an error in that case. * * \param key The private key. * \param buf The output buffer for containing the binary representation * of the key. * For Weierstrass curves, this is the big-endian * representation, padded with null bytes at the beginning * to reach \p buflen bytes. * For Montgomery curves, this is the standard byte string * representation (which is little-endian), padded with * null bytes at the end to reach \p buflen bytes. * \param buflen The total length of the buffer in bytes. * The length of the output is * (`grp->nbits` + 7) / 8 bytes * where `grp->nbits` is the private key size in bits. * For Weierstrass keys, if the output buffer is smaller, * leading zeros are trimmed to fit if possible. For * Montgomery keys, the output buffer must always be large * enough for the nominal length. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or * #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key * representation is larger than the available space in \p buf. * \return Another negative error code on different kinds of failure. */ int MBEDTLS_DEPRECATED mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, unsigned char *buf, size_t buflen); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief This function exports an elliptic curve private key. * * \param key The private key. * \param olen On success, the length of the private key. * This is always (`grp->nbits` + 7) / 8 bytes * where `grp->nbits` is the private key size in bits. * \param buf The output buffer for containing the binary representation * of the key. * \param buflen The total length of the buffer in bytes. * #MBEDTLS_ECP_MAX_BYTES is always sufficient. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key * representation is larger than the available space in \p buf. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if no private key is * set in \p key. * \return Another negative error code on different kinds of failure. */ int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key, size_t *olen, unsigned char *buf, size_t buflen); /** * \brief This function exports an elliptic curve public key. * * \note If the public key was not set in \p key, * the output is unspecified. Future versions * may return an error in that case. * * \param key The public key. * \param format The point format. This must be either * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. * (For groups without these formats, this parameter is * ignored. But it still has to be either of the above * values.) * \param olen The address at which to store the length of * the output in Bytes. This must not be \c NULL. * \param buf The output buffer. This must be a writable buffer * of length \p buflen Bytes. * \param buflen The length of the output buffer \p buf in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer * is too small to hold the point. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format * or the export for the given group is not implemented. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key, int format, size_t *olen, unsigned char *buf, size_t buflen); /** * \brief This function checks that the keypair objects * \p pub and \p prv have the same group and the * same public point, and that the private key in * \p prv is consistent with the public key. * * \param pub The keypair structure holding the public key. This * must be initialized. If it contains a private key, that * part is ignored. * \param prv The keypair structure holding the full keypair. * This must be initialized. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success, meaning that the keys are valid and match. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX * error code on calculation failure. */ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \brief Calculate the public key from a private key in a key pair. * * \param key A keypair structure. It must have a private key set. * If the public key is set, it will be overwritten. * \param f_rng The RNG function. This must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c * NULL if \p f_rng doesn't need a context. * * \return \c 0 on success. The key pair object can be used for * operations that require the public key. * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX * error code on calculation failure. */ int mbedtls_ecp_keypair_calc_public( mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \brief Query the group that a key pair belongs to. * * \param key The key pair to query. * * \return The group ID for the group registered in the key pair * object. * This is \c MBEDTLS_ECP_DP_NONE if no group has been set * in the key pair object. */ mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( const mbedtls_ecp_keypair *key); /** * \brief This function exports generic key-pair parameters. * * Each of the output parameters can be a null pointer * if you do not need that parameter. * * \note If the private key or the public key was not set in \p key, * the corresponding output is unspecified. Future versions * may return an error in that case. * * \param key The key pair to export from. * \param grp Slot for exported ECP group. * It must either be null or point to an initialized ECP group. * \param d Slot for the exported secret value. * It must either be null or point to an initialized mpi. * \param Q Slot for the exported public value. * It must either be null or point to an initialized ECP point. * * \return \c 0 on success, * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if key id doesn't * correspond to a known group. * \return Another negative error code on other kinds of failure. */ int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q); #if defined(MBEDTLS_SELF_TEST) /** * \brief The ECP checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_ecp_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* ecp.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h000066400000000000000000000224121464416617300246170ustar00rootroot00000000000000/** * \file entropy.h * * \brief Entropy accumulator implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ENTROPY_H #define MBEDTLS_ENTROPY_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include "md.h" #if defined(MBEDTLS_MD_CAN_SHA512) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR #define MBEDTLS_ENTROPY_MD MBEDTLS_MD_SHA512 #define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ #else #if defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR #define MBEDTLS_ENTROPY_MD MBEDTLS_MD_SHA256 #define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ #endif #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** Critical entropy source failure. */ #define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /** No more sources can be added. */ #define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /** No sources have been added to poll. */ #define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /** No strong sources have been added to poll. */ #define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /** Read/write error in file. */ #define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) #define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ #endif #if !defined(MBEDTLS_ENTROPY_MAX_GATHER) #define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ #define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES #define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ #define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ #ifdef __cplusplus extern "C" { #endif /** * \brief Entropy poll callback pointer * * \param data Callback-specific data pointer * \param output Data to fill * \param len Maximum size to provide * \param olen The actual amount of bytes put into the buffer (Can be 0) * * \return 0 if no critical failures occurred, * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise */ typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, size_t *olen); /** * \brief Entropy source state */ typedef struct mbedtls_entropy_source_state { mbedtls_entropy_f_source_ptr MBEDTLS_PRIVATE(f_source); /**< The entropy source callback */ void *MBEDTLS_PRIVATE(p_source); /**< The callback data pointer */ size_t MBEDTLS_PRIVATE(size); /**< Amount received in bytes */ size_t MBEDTLS_PRIVATE(threshold); /**< Minimum bytes required before release */ int MBEDTLS_PRIVATE(strong); /**< Is the source strong? */ } mbedtls_entropy_source_state; /** * \brief Entropy context structure */ typedef struct mbedtls_entropy_context { mbedtls_md_context_t MBEDTLS_PRIVATE(accumulator); int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init. * 1 after the first update. * -1 after free. */ int MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */ mbedtls_entropy_source_state MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES]; #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) int MBEDTLS_PRIVATE(initial_entropy_run); #endif } mbedtls_entropy_context; #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback */ int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif /** * \brief Initialize the context * * \param ctx Entropy context to initialize */ void mbedtls_entropy_init(mbedtls_entropy_context *ctx); /** * \brief Free the data in the context * * \param ctx Entropy context to free */ void mbedtls_entropy_free(mbedtls_entropy_context *ctx); /** * \brief Adds an entropy source to poll * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param ctx Entropy context * \param f_source Entropy function * \param p_source Function data * \param threshold Minimum required from source before entropy is released * ( with mbedtls_entropy_func() ) (in bytes) * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or * MBEDTLS_ENTROPY_SOURCE_WEAK. * At least one strong source needs to be added. * Weaker sources (such as the cycle counter) can be used as * a complement. * * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES */ int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, mbedtls_entropy_f_source_ptr f_source, void *p_source, size_t threshold, int strong); /** * \brief Trigger an extra gather poll for the accumulator * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param ctx Entropy context * * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_gather(mbedtls_entropy_context *ctx); /** * \brief Retrieve entropy from the accumulator * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data Entropy context * \param output Buffer to fill * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE * * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_func(void *data, unsigned char *output, size_t len); /** * \brief Add data to the accumulator manually * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param ctx Entropy context * \param data Data to add * \param len Length of data * * \return 0 if successful */ int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, const unsigned char *data, size_t len); #if defined(MBEDTLS_ENTROPY_NV_SEED) /** * \brief Trigger an update of the seed file in NV by using the * current entropy pool. * * \param ctx Entropy context * * \return 0 if successful */ int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx); #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_FS_IO) /** * \brief Write a seed file * * \param ctx Entropy context * \param path Name of the file * * \return 0 if successful, * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path); /** * \brief Read and update a seed file. Seed is added to this * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are * read from the seed file. The rest is ignored. * * \param ctx Entropy context * \param path Name of the file * * \return 0 if successful, * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED */ int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * This module self-test also calls the entropy self-test, * mbedtls_entropy_source_self_test(); * * \return 0 if successful, or 1 if a test failed */ int mbedtls_entropy_self_test(int verbose); #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) /** * \brief Checkup routine * * Verifies the integrity of the hardware entropy source * provided by the function 'mbedtls_hardware_poll()'. * * Note this is the only hardware entropy source that is known * at link time, and other entropy sources configured * dynamically at runtime by the function * mbedtls_entropy_add_source() will not be tested. * * \return 0 if successful, or 1 if a test failed */ int mbedtls_entropy_source_self_test(int verbose); #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* entropy.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/error.h000066400000000000000000000146171464416617300242600ustar00rootroot00000000000000/** * \file error.h * * \brief Error to string translation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H #include "mbedtls/build_info.h" #include /** * Error code layout. * * Currently we try to keep all error codes within the negative space of 16 * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In * addition we'd like to give two layers of information on the error if * possible. * * For that purpose the error codes are segmented in the following manner: * * 16 bit error code bit-segmentation * * 1 bit - Unused (sign bit) * 3 bits - High level module ID * 5 bits - Module-dependent error code * 7 bits - Low level module errors * * For historical reasons, low-level error codes are divided in even and odd, * even codes were assigned first, and -1 is reserved for other errors. * * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) * * Module Nr Codes assigned * ERROR 2 0x006E 0x0001 * MPI 7 0x0002-0x0010 * GCM 3 0x0012-0x0016 0x0013-0x0013 * THREADING 3 0x001A-0x001E * AES 5 0x0020-0x0022 0x0021-0x0025 * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 * BASE64 2 0x002A-0x002C * OID 1 0x002E-0x002E 0x000B-0x000B * PADLOCK 1 0x0030-0x0030 * DES 2 0x0032-0x0032 0x0033-0x0033 * CTR_DBRG 4 0x0034-0x003A * ENTROPY 3 0x003C-0x0040 0x003D-0x003F * NET 13 0x0042-0x0052 0x0043-0x0049 * ARIA 4 0x0058-0x005E * ASN1 7 0x0060-0x006C * CMAC 1 0x007A-0x007A * PBKDF2 1 0x007C-0x007C * HMAC_DRBG 4 0x0003-0x0009 * CCM 3 0x000D-0x0011 * MD5 1 0x002F-0x002F * RIPEMD160 1 0x0031-0x0031 * SHA1 1 0x0035-0x0035 0x0073-0x0073 * SHA256 1 0x0037-0x0037 0x0074-0x0074 * SHA512 1 0x0039-0x0039 0x0075-0x0075 * SHA-3 1 0x0076-0x0076 * CHACHA20 3 0x0051-0x0055 * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 * PLATFORM 2 0x0070-0x0072 * LMS 5 0x0011-0x0019 * * High-level module nr (3 bits - 0x0...-0x7...) * Name ID Nr of Errors * PEM 1 9 * PKCS#12 1 4 (Started from top) * X509 2 20 * PKCS5 2 4 (Started from top) * DHM 3 11 * PK 3 15 (Started from top) * RSA 4 11 * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) * PKCS7 5 12 (Started from 0x5300) * SSL 5 2 (Started from 0x5F00) * CIPHER 6 8 (Started from 0x6080) * SSL 6 22 (Started from top, plus 0x6000) * SSL 7 20 (Started from 0x7000, gaps at * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80) * * Module dependent error code (5 bits 0x.00.-0x.F8.) */ #ifdef __cplusplus extern "C" { #endif /** Generic error */ #define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /** This is a bug in the library */ #define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /** Hardware accelerator failed */ #define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /** The requested feature is not supported by the platform */ #define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /** * \brief Combines a high-level and low-level error code together. * * Wrapper macro for mbedtls_error_add(). See that function for * more details. */ #define MBEDTLS_ERROR_ADD(high, low) \ mbedtls_error_add(high, low, __FILE__, __LINE__) #if defined(MBEDTLS_TEST_HOOKS) /** * \brief Testing hook called before adding/combining two error codes together. * Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS. */ extern void (*mbedtls_test_hook_error_add)(int, int, const char *, int); #endif /** * \brief Combines a high-level and low-level error code together. * * This function can be called directly however it is usually * called via the #MBEDTLS_ERROR_ADD macro. * * While a value of zero is not a negative error code, it is still an * error code (that denotes success) and can be combined with both a * negative error code or another value of zero. * * \note When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to * call \link mbedtls_test_hook_error_add \endlink. * * \param high high-level error code. See error.h for more details. * \param low low-level error code. See error.h for more details. * \param file file where this error code addition occurred. * \param line line where this error code addition occurred. */ static inline int mbedtls_error_add(int high, int low, const char *file, int line) { #if defined(MBEDTLS_TEST_HOOKS) if (*mbedtls_test_hook_error_add != NULL) { (*mbedtls_test_hook_error_add)(high, low, file, line); } #endif (void) file; (void) line; return high + low; } /** * \brief Translate an Mbed TLS error code into a string representation. * The result is truncated if necessary and always includes a * terminating null byte. * * \param errnum error code * \param buffer buffer to place representation in * \param buflen length of the buffer */ void mbedtls_strerror(int errnum, char *buffer, size_t buflen); /** * \brief Translate the high-level part of an Mbed TLS error code into a string * representation. * * This function returns a const pointer to an un-modifiable string. The caller * must not try to modify the string. It is intended to be used mostly for * logging purposes. * * \param error_code error code * * \return The string representation of the error code, or \c NULL if the error * code is unknown. */ const char *mbedtls_high_level_strerr(int error_code); /** * \brief Translate the low-level part of an Mbed TLS error code into a string * representation. * * This function returns a const pointer to an un-modifiable string. The caller * must not try to modify the string. It is intended to be used mostly for * logging purposes. * * \param error_code error code * * \return The string representation of the error code, or \c NULL if the error * code is unknown. */ const char *mbedtls_low_level_strerr(int error_code); #ifdef __cplusplus } #endif #endif /* error.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h000066400000000000000000000421171464416617300236710ustar00rootroot00000000000000/** * \file gcm.h * * \brief This file contains GCM definitions and functions. * * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation * (GCM), Natl. Inst. Stand. Technol. * * For more information on GCM, see NIST SP 800-38D: Recommendation for * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_GCM_H #define MBEDTLS_GCM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "mbedtls/block_cipher.h" #endif #include #define MBEDTLS_GCM_ENCRYPT 1 #define MBEDTLS_GCM_DECRYPT 0 /** Authenticated decryption failed. */ #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /** Bad input parameters to function. */ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /** An output buffer is too small. */ #define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL -0x0016 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_GCM_ALT) #if defined(MBEDTLS_GCM_LARGE_TABLE) #define MBEDTLS_GCM_HTABLE_SIZE 256 #else #define MBEDTLS_GCM_HTABLE_SIZE 16 #endif /** * \brief The GCM context structure. */ typedef struct mbedtls_gcm_context { #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx); /*!< The cipher context used. */ #else mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ #endif uint64_t MBEDTLS_PRIVATE(H)[MBEDTLS_GCM_HTABLE_SIZE][2]; /*!< Precalculated HTable. */ uint64_t MBEDTLS_PRIVATE(len); /*!< The total length of the encrypted data. */ uint64_t MBEDTLS_PRIVATE(add_len); /*!< The total length of the additional data. */ unsigned char MBEDTLS_PRIVATE(base_ectr)[16]; /*!< The first ECTR for tag. */ unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working value. */ unsigned char MBEDTLS_PRIVATE(buf)[16]; /*!< The buf working value. */ unsigned char MBEDTLS_PRIVATE(mode); /*!< The operation to perform: #MBEDTLS_GCM_ENCRYPT or #MBEDTLS_GCM_DECRYPT. */ unsigned char MBEDTLS_PRIVATE(acceleration); /*!< The acceleration to use. */ } mbedtls_gcm_context; #else /* !MBEDTLS_GCM_ALT */ #include "gcm_alt.h" #endif /* !MBEDTLS_GCM_ALT */ /** * \brief This function initializes the specified GCM context, * to make references valid, and prepares the context * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). * * The function does not bind the GCM context to a particular * cipher, nor set the key. For this purpose, use * mbedtls_gcm_setkey(). * * \param ctx The GCM context to initialize. This must not be \c NULL. */ void mbedtls_gcm_init(mbedtls_gcm_context *ctx); /** * \brief This function associates a GCM context with a * cipher algorithm and a key. * * \param ctx The GCM context. This must be initialized. * \param cipher The 128-bit block cipher to use. * \param key The encryption key. This must be a readable buffer of at * least \p keybits bits. * \param keybits The key size in bits. Valid options are: *
  • 128 bits
  • *
  • 192 bits
  • *
  • 256 bits
* * \return \c 0 on success. * \return A cipher-specific error code on failure. */ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits); /** * \brief This function performs GCM encryption or decryption of a buffer. * * \note For encryption, the output buffer can be the same as the * input buffer. For decryption, the output buffer cannot be * the same as input buffer. If the buffers overlap, the output * buffer must trail at least 8 Bytes behind the input buffer. * * \warning When this function performs a decryption, it outputs the * authentication tag and does not verify that the data is * authentic. You should use this function to perform encryption * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. * * \param ctx The GCM context to use for encryption or decryption. This * must be initialized. * \param mode The operation to perform: * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. * The ciphertext is written to \p output and the * authentication tag is written to \p tag. * - #MBEDTLS_GCM_DECRYPT to perform decryption. * The plaintext is written to \p output and the * authentication tag is written to \p tag. * Note that this mode is not recommended, because it does * not verify the authenticity of the data. For this reason, * you should use mbedtls_gcm_auth_decrypt() instead of * calling this function in decryption mode. * \param length The length of the input data, which is equal to the length * of the output data. * \param iv The initialization vector. This must be a readable buffer of * at least \p iv_len Bytes. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. This must be of at * least that size in Bytes. * \param add_len The length of the additional data. * \param input The buffer holding the input data. If \p length is greater * than zero, this must be a readable buffer of at least that * size in Bytes. * \param output The buffer for holding the output data. If \p length is greater * than zero, this must be a writable buffer of at least that * size in Bytes. * \param tag_len The length of the tag to generate. * \param tag The buffer for holding the tag. This must be a writable * buffer of at least \p tag_len Bytes. * * \return \c 0 if the encryption or decryption was performed * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, * this does not indicate that the data is authentic. * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are * not valid or a cipher-specific error code if the encryption * or decryption failed. */ int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, size_t tag_len, unsigned char *tag); /** * \brief This function performs a GCM authenticated decryption of a * buffer. * * \note For decryption, the output buffer cannot be the same as * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. This must be initialized. * \param length The length of the ciphertext to decrypt, which is also * the length of the decrypted plaintext. * \param iv The initialization vector. This must be a readable buffer * of at least \p iv_len Bytes. * \param iv_len The length of the IV. * \param add The buffer holding the additional data. This must be of at * least that size in Bytes. * \param add_len The length of the additional data. * \param tag The buffer holding the tag to verify. This must be a * readable buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to verify. * \param input The buffer holding the ciphertext. If \p length is greater * than zero, this must be a readable buffer of at least that * size. * \param output The buffer for holding the decrypted plaintext. If \p length * is greater than zero, this must be a writable buffer of at * least that size. * * \return \c 0 if successful and authenticated. * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are * not valid or a cipher-specific error code if the decryption * failed. */ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *tag, size_t tag_len, const unsigned char *input, unsigned char *output); /** * \brief This function starts a GCM encryption or decryption * operation. * * \param ctx The GCM context. This must be initialized. * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or * #MBEDTLS_GCM_DECRYPT. * \param iv The initialization vector. This must be a readable buffer of * at least \p iv_len Bytes. * \param iv_len The length of the IV. * * \return \c 0 on success. */ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, int mode, const unsigned char *iv, size_t iv_len); /** * \brief This function feeds an input buffer as associated data * (authenticated but not encrypted data) in a GCM * encryption or decryption operation. * * Call this function after mbedtls_gcm_starts() to pass * the associated data. If the associated data is empty, * you do not need to call this function. You may not * call this function after calling mbedtls_cipher_update(). * * \param ctx The GCM context. This must have been started with * mbedtls_gcm_starts() and must not have yet received * any input with mbedtls_gcm_update(). * \param add The buffer holding the additional data, or \c NULL * if \p add_len is \c 0. * \param add_len The length of the additional data. If \c 0, * \p add may be \c NULL. * * \return \c 0 on success. */ int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, const unsigned char *add, size_t add_len); /** * \brief This function feeds an input buffer into an ongoing GCM * encryption or decryption operation. * * You may call this function zero, one or more times * to pass successive parts of the input: the plaintext to * encrypt, or the ciphertext (not including the tag) to * decrypt. After the last part of the input, call * mbedtls_gcm_finish(). * * This function may produce output in one of the following * ways: * - Immediate output: the output length is always equal * to the input length. * - Buffered output: the output consists of a whole number * of 16-byte blocks. If the total input length so far * (not including associated data) is 16 \* *B* + *A* * with *A* < 16 then the total output length is 16 \* *B*. * * In particular: * - It is always correct to call this function with * \p output_size >= \p input_length + 15. * - If \p input_length is a multiple of 16 for all the calls * to this function during an operation, then it is * correct to use \p output_size = \p input_length. * * \note For decryption, the output buffer cannot be the same as * input buffer. If the buffers overlap, the output buffer * must trail at least 8 Bytes behind the input buffer. * * \param ctx The GCM context. This must be initialized. * \param input The buffer holding the input data. If \p input_length * is greater than zero, this must be a readable buffer * of at least \p input_length bytes. * \param input_length The length of the input data in bytes. * \param output The buffer for the output data. If \p output_size * is greater than zero, this must be a writable buffer of * of at least \p output_size bytes. * \param output_size The size of the output buffer in bytes. * See the function description regarding the output size. * \param output_length On success, \p *output_length contains the actual * length of the output written in \p output. * On failure, the content of \p *output_length is * unspecified. * * \return \c 0 on success. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: * total input length too long, * unsupported input/output buffer overlap detected, * or \p output_size too small. */ int mbedtls_gcm_update(mbedtls_gcm_context *ctx, const unsigned char *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length); /** * \brief This function finishes the GCM operation and generates * the authentication tag. * * It wraps up the GCM stream, and generates the * tag. The tag can have a maximum length of 16 Bytes. * * \param ctx The GCM context. This must be initialized. * \param tag The buffer for holding the tag. This must be a writable * buffer of at least \p tag_len Bytes. * \param tag_len The length of the tag to generate. This must be at least * four. * \param output The buffer for the final output. * If \p output_size is nonzero, this must be a writable * buffer of at least \p output_size bytes. * \param output_size The size of the \p output buffer in bytes. * This must be large enough for the output that * mbedtls_gcm_update() has not produced. In particular: * - If mbedtls_gcm_update() produces immediate output, * or if the total input size is a multiple of \c 16, * then mbedtls_gcm_finish() never produces any output, * so \p output_size can be \c 0. * - \p output_size never needs to be more than \c 15. * \param output_length On success, \p *output_length contains the actual * length of the output written in \p output. * On failure, the content of \p *output_length is * unspecified. * * \return \c 0 on success. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: * invalid value of \p tag_len, * or \p output_size too small. */ int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, unsigned char *output, size_t output_size, size_t *output_length, unsigned char *tag, size_t tag_len); /** * \brief This function clears a GCM context and the underlying * cipher sub-context. * * \param ctx The GCM context to clear. If this is \c NULL, the call has * no effect. Otherwise, this must be initialized. */ void mbedtls_gcm_free(mbedtls_gcm_context *ctx); #if defined(MBEDTLS_SELF_TEST) /** * \brief The GCM checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_gcm_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* gcm.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h000066400000000000000000000121321464416617300240310ustar00rootroot00000000000000/** * \file hkdf.h * * \brief This file contains the HKDF interface. * * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is * specified by RFC 5869. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_HKDF_H #define MBEDTLS_HKDF_H #include "mbedtls/build_info.h" #include "mbedtls/md.h" /** * \name HKDF Error codes * \{ */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /** \} name */ #ifdef __cplusplus extern "C" { #endif /** * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function * (HKDF). * * \param md A hash function; md.size denotes the length of the hash * function output in bytes. * \param salt An optional salt value (a non-secret random value); * if the salt is not provided, a string of all zeros of * md.size length is used as the salt. * \param salt_len The length in bytes of the optional \p salt. * \param ikm The input keying material. * \param ikm_len The length in bytes of \p ikm. * \param info An optional context and application specific information * string. This can be a zero-length string. * \param info_len The length of \p info in bytes. * \param okm The output keying material of \p okm_len bytes. * \param okm_len The length of the output keying material in bytes. This * must be less than or equal to 255 * md.size bytes. * * \return 0 on success. * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying * MD layer. */ int mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len); /** * \brief Take the input keying material \p ikm and extract from it a * fixed-length pseudorandom key \p prk. * * \warning This function should only be used if the security of it has been * studied and established in that particular context (eg. TLS 1.3 * key schedule). For standard HKDF security guarantees use * \c mbedtls_hkdf instead. * * \param md A hash function; md.size denotes the length of the * hash function output in bytes. * \param salt An optional salt value (a non-secret random value); * if the salt is not provided, a string of all zeros * of md.size length is used as the salt. * \param salt_len The length in bytes of the optional \p salt. * \param ikm The input keying material. * \param ikm_len The length in bytes of \p ikm. * \param[out] prk A pseudorandom key of at least md.size bytes. * * \return 0 on success. * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying * MD layer. */ int mbedtls_hkdf_extract(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, unsigned char *prk); /** * \brief Expand the supplied \p prk into several additional pseudorandom * keys, which is the output of the HKDF. * * \warning This function should only be used if the security of it has been * studied and established in that particular context (eg. TLS 1.3 * key schedule). For standard HKDF security guarantees use * \c mbedtls_hkdf instead. * * \param md A hash function; md.size denotes the length of the hash * function output in bytes. * \param prk A pseudorandom key of at least md.size bytes. \p prk is * usually the output from the HKDF extract step. * \param prk_len The length in bytes of \p prk. * \param info An optional context and application specific information * string. This can be a zero-length string. * \param info_len The length of \p info in bytes. * \param okm The output keying material of \p okm_len bytes. * \param okm_len The length of the output keying material in bytes. This * must be less than or equal to 255 * md.size bytes. * * \return 0 on success. * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying * MD layer. */ int mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk, size_t prk_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len); #ifdef __cplusplus } #endif #endif /* hkdf.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h000066400000000000000000000441351464416617300250330ustar00rootroot00000000000000/** * \file hmac_drbg.h * * \brief The HMAC_DRBG pseudorandom generator. * * This module implements the HMAC_DRBG pseudorandom generator described * in NIST SP 800-90A: Recommendation for Random Number Generation Using * Deterministic Random Bit Generators. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_HMAC_DRBG_H #define MBEDTLS_HMAC_DRBG_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/md.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /* * Error codes */ /** Too many random requested in single call. */ #define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /** Input too large (Entropy + additional). */ #define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /** Read/write error in file. */ #define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /** The entropy source failed. */ #define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) #define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ #endif #if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) #define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ #endif #if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) #define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ #endif #if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) #define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ #define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ #ifdef __cplusplus extern "C" { #endif /** * HMAC_DRBG context. */ typedef struct mbedtls_hmac_drbg_context { /* Working state: the key K is not stored explicitly, * but is implied by the HMAC context */ mbedtls_md_context_t MBEDTLS_PRIVATE(md_ctx); /*!< HMAC context (inc. K) */ unsigned char MBEDTLS_PRIVATE(V)[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ int MBEDTLS_PRIVATE(reseed_counter); /*!< reseed counter */ /* Administrative state */ size_t MBEDTLS_PRIVATE(entropy_len); /*!< entropy bytes grabbed on each (re)seed */ int MBEDTLS_PRIVATE(prediction_resistance); /*!< enable prediction resistance (Automatic reseed before every random generation) */ int MBEDTLS_PRIVATE(reseed_interval); /*!< reseed interval */ /* Callbacks */ int(*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< entropy function */ void *MBEDTLS_PRIVATE(p_entropy); /*!< context for the entropy function */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized if and only if * md_ctx->md_info != NULL. This means that the mutex is initialized * during the initial seeding in mbedtls_hmac_drbg_seed() or * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). * * Note that this invariant may change without notice. Do not rely on it * and do not access the mutex directly in application code. */ mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_hmac_drbg_context; /** * \brief HMAC_DRBG context initialization. * * This function makes the context ready for mbedtls_hmac_drbg_seed(), * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). * * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL * by default. Override this value by calling * mbedtls_hmac_drbg_set_reseed_interval(). * * \param ctx HMAC_DRBG context to be initialized. */ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx); /** * \brief HMAC_DRBG initial seeding. * * Set the initial seed and set up the entropy source for future reseeds. * * A typical choice for the \p f_entropy and \p p_entropy parameters is * to use the entropy module: * - \p f_entropy is mbedtls_entropy_func(); * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized * with mbedtls_entropy_init() (which registers the platform's default * entropy sources). * * You can provide a personalization string in addition to the * entropy source, to make this instantiation as unique as possible. * * \note By default, the security strength as defined by NIST is: * - 128 bits if \p md_info is SHA-1; * - 192 bits if \p md_info is SHA-224; * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. * Note that SHA-256 is just as efficient as SHA-224. * The security strength can be reduced if a smaller * entropy length is set with * mbedtls_hmac_drbg_set_entropy_len(). * * \note The default entropy length is the security strength * (converted from bits to bytes). You can override * it by calling mbedtls_hmac_drbg_set_entropy_len(). * * \note During the initial seeding, this function calls * the entropy source to obtain a nonce * whose length is half the entropy length. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * after this function returns successfully, * it is safe to call mbedtls_hmac_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param ctx HMAC_DRBG context to be seeded. * \param md_info MD algorithm to use for HMAC_DRBG. * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. * \p f_entropy is always called with a length that is * less than or equal to the entropy length. * \param p_entropy The entropy context to pass to \p f_entropy. * \param custom The personalization string. * This can be \c NULL, in which case the personalization * string is empty regardless of the value of \p len. * \param len The length of the personalization string. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT * and also at most * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len * 3 / 2 * where \c entropy_len is the entropy length * described above. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is * invalid. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough * memory to allocate context data. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if the call to \p f_entropy failed. */ int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len); /** * \brief Initialisation of simplified HMAC_DRBG (never reseeds). * * This function is meant for use in algorithms that need a pseudorandom * input such as deterministic ECDSA. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * after this function returns successfully, * it is safe to call mbedtls_hmac_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param ctx HMAC_DRBG context to be initialised. * \param md_info MD algorithm to use for HMAC_DRBG. * \param data Concatenation of the initial entropy string and * the additional data. * \param data_len Length of \p data in bytes. * * \return \c 0 if successful. or * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is * invalid. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough * memory to allocate context data. */ int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, const unsigned char *data, size_t data_len); /** * \brief This function turns prediction resistance on or off. * The default value is off. * * \note If enabled, entropy is gathered at the beginning of * every call to mbedtls_hmac_drbg_random_with_add() * or mbedtls_hmac_drbg_random(). * Only use this if your entropy source has sufficient * throughput. * * \param ctx The HMAC_DRBG context. * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. */ void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx, int resistance); /** * \brief This function sets the amount of entropy grabbed on each * seed or reseed. * * See the documentation of mbedtls_hmac_drbg_seed() for the default value. * * \param ctx The HMAC_DRBG context. * \param len The amount of entropy to grab, in bytes. */ void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len); /** * \brief Set the reseed interval. * * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() * or mbedtls_hmac_drbg_random_with_add() after which the entropy function * is called again. * * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. * * \param ctx The HMAC_DRBG context. * \param interval The reseed interval. */ void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval); /** * \brief This function updates the state of the HMAC_DRBG context. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The HMAC_DRBG context. * \param additional The data to update the state with. * If this is \c NULL, there is no additional data. * \param add_len Length of \p additional in bytes. * Unused if \p additional is \c NULL. * * \return \c 0 on success, or an error from the underlying * hash calculation. */ int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len); /** * \brief This function reseeds the HMAC_DRBG context, that is * extracts data from the entropy source. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param ctx The HMAC_DRBG context. * \param additional Additional data to add to the state. * If this is \c NULL, there is no additional data * and \p len should be \c 0. * \param len The length of the additional data. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT * and also at most * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len * where \c entropy_len is the entropy length * (see mbedtls_hmac_drbg_set_entropy_len()). * * \return \c 0 if successful. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if a call to the entropy function failed. */ int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len); /** * \brief This function updates an HMAC_DRBG instance with additional * data and uses it to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * * \note This function is not thread-safe. It is not safe * to call this function if another thread might be * concurrently obtaining random numbers from the same * context or updating or reseeding the same context. * * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. * \param output_len The length of the buffer in bytes. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * \param additional Additional data to update with. * If this is \c NULL, there is no additional data * and \p add_len should be \c 0. * \param add_len The length of the additional data. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if a call to the entropy source failed. * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. */ int mbedtls_hmac_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len); /** * \brief This function uses HMAC_DRBG to generate random data. * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. */ #if defined(MBEDTLS_THREADING_C) /** * \note When Mbed TLS is built with threading support, * it is safe to call mbedtls_ctr_drbg_random() * from multiple threads. Other operations, including * reseeding, are not thread-safe. */ #endif /* MBEDTLS_THREADING_C */ /** * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. * \param out_len The length of the buffer in bytes. * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED * if a call to the entropy source failed. * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. */ int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len); /** * \brief This function resets HMAC_DRBG context to the state immediately * after initial call of mbedtls_hmac_drbg_init(). * * \param ctx The HMAC_DRBG context to free. */ void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx); #if defined(MBEDTLS_FS_IO) /** * \brief This function writes a seed file. * * \param ctx The HMAC_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed * failure. */ int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path); /** * \brief This function reads and updates a seed file. The seed * is added to this instance. * * \param ctx The HMAC_DRBG context. * \param path The name of the file. * * \return \c 0 on success. * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on * reseed failure. * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing * seed file is too large. */ int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /** * \brief The HMAC_DRBG Checkup routine. * * \return \c 0 if successful. * \return \c 1 if the test failed. */ int mbedtls_hmac_drbg_self_test(int verbose); #endif #ifdef __cplusplus } #endif #endif /* hmac_drbg.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/lms.h000066400000000000000000000503651464416617300237220ustar00rootroot00000000000000/** * \file lms.h * * \brief This file provides an API for the LMS post-quantum-safe stateful-hash public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. * This implementation currently only supports a single parameter set * MBEDTLS_LMS_SHA256_M32_H10 in order to reduce complexity. This is one * of the signature schemes recommended by the IETF draft SUIT standard * for IOT firmware upgrades (RFC9019). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LMS_H #define MBEDTLS_LMS_H #include #include #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #define MBEDTLS_ERR_LMS_BAD_INPUT_DATA -0x0011 /**< Bad data has been input to an LMS function */ #define MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS -0x0013 /**< Specified LMS key has utilised all of its private keys */ #define MBEDTLS_ERR_LMS_VERIFY_FAILED -0x0015 /**< LMS signature verification failed */ #define MBEDTLS_ERR_LMS_ALLOC_FAILED -0x0017 /**< LMS failed to allocate space for a private key */ #define MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL -0x0019 /**< Input/output buffer is too small to contain requited data */ /* Currently only defined for SHA256, 32 is the max hash output size */ #define MBEDTLS_LMOTS_N_HASH_LEN_MAX (32u) #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX (34u) #define MBEDTLS_LMOTS_N_HASH_LEN(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 32u : 0) #define MBEDTLS_LMOTS_I_KEY_ID_LEN (16u) #define MBEDTLS_LMOTS_Q_LEAF_ID_LEN (4u) #define MBEDTLS_LMOTS_TYPE_LEN (4u) #define MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) ((type) == MBEDTLS_LMOTS_SHA256_N32_W8 ? 34u : 0) #define MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) (MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type) + \ (MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(type) * \ MBEDTLS_LMOTS_N_HASH_LEN(type))) #define MBEDTLS_LMS_TYPE_LEN (4) #define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0) /* The length of a hash output, Currently only implemented for SHA256. * Max is 32 bytes. */ #define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0) #define MBEDTLS_LMS_M_NODE_BYTES_MAX 32 #define MBEDTLS_LMS_SIG_LEN(type, otstype) (MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ MBEDTLS_LMOTS_SIG_LEN(otstype) + \ MBEDTLS_LMS_TYPE_LEN + \ (MBEDTLS_LMS_H_TREE_HEIGHT(type) * \ MBEDTLS_LMS_M_NODE_BYTES(type))) #define MBEDTLS_LMS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMS_TYPE_LEN + \ MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_I_KEY_ID_LEN + \ MBEDTLS_LMS_M_NODE_BYTES(type)) #ifdef __cplusplus extern "C" { #endif /** The Identifier of the LMS parameter set, as per * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml * We are only implementing a subset of the types, particularly H10, for the sake of simplicity. */ typedef enum { MBEDTLS_LMS_SHA256_M32_H10 = 0x6, } mbedtls_lms_algorithm_type_t; /** The Identifier of the LMOTS parameter set, as per * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml. * We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity. */ typedef enum { MBEDTLS_LMOTS_SHA256_N32_W8 = 4 } mbedtls_lmots_algorithm_type_t; /** LMOTS parameters structure. * * This contains the metadata associated with an LMOTS key, detailing the * algorithm type, the key ID, and the leaf identifier should be key be part of * a LMS key. */ typedef struct { unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key identifier. */ unsigned char MBEDTLS_PRIVATE(q_leaf_identifier[MBEDTLS_LMOTS_Q_LEAF_ID_LEN]); /*!< Which leaf of the LMS key this is. 0 if the key is not part of an LMS key. */ mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LM-OTS key type identifier as per IANA. Only SHA256_N32_W8 is currently supported. */ } mbedtls_lmots_parameters_t; /** LMOTS public context structure. * * A LMOTS public key is a hash output, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lmots_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PUBLIC_KEY -> INIT [label="free"]; * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; * } * \enddot */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(public_key)[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ } mbedtls_lmots_public_t; #if defined(MBEDTLS_LMS_PRIVATE) /** LMOTS private context structure. * * A LMOTS private key is one hash output for each of digit of the digest + * checksum, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lmots_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PRIVATE_KEY -> INIT [label="free"]; * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; * HAVE_PRIVATE_KEY -> INIT [label="sign"]; * } * \enddot */ typedef struct { mbedtls_lmots_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(private_key)[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][ MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lmots_private_t; #endif /* defined(MBEDTLS_LMS_PRIVATE) */ /** LMS parameters structure. * * This contains the metadata associated with an LMS key, detailing the * algorithm type, the type of the underlying OTS algorithm, and the key ID. */ typedef struct { unsigned char MBEDTLS_PRIVATE(I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN]); /*!< The key identifier. */ mbedtls_lmots_algorithm_type_t MBEDTLS_PRIVATE(otstype); /*!< The LM-OTS key type identifier as per IANA. Only SHA256_N32_W8 is currently supported. */ mbedtls_lms_algorithm_type_t MBEDTLS_PRIVATE(type); /*!< The LMS key type identifier as per IANA. Only SHA256_M32_H10 is currently supported. */ } mbedtls_lms_parameters_t; /** LMS public context structure. * * A LMS public key is the hash output that is the root of the Merkle tree, and * the applicable parameter set * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lms_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PUBLIC_KEY -> INIT [label="free"]; * INIT -> HAVE_PUBLIC_KEY [label="import_public_key"]; * INIT -> HAVE_PUBLIC_KEY [label="calculate_public_key from private key"]; * HAVE_PUBLIC_KEY -> HAVE_PUBLIC_KEY [label="export_public_key"]; * } * \enddot */ typedef struct { mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); unsigned char MBEDTLS_PRIVATE(T_1_pub_key)[MBEDTLS_LMS_M_NODE_BYTES_MAX]; /*!< The public key, in the form of the Merkle tree root node. */ unsigned char MBEDTLS_PRIVATE(have_public_key); /*!< Whether the context contains a public key. Boolean values only. */ } mbedtls_lms_public_t; #if defined(MBEDTLS_LMS_PRIVATE) /** LMS private context structure. * * A LMS private key is a set of LMOTS private keys, an index to the next usable * key, and the applicable parameter set. * * The context must be initialized before it is used. A public key must either * be imported or generated from a private context. * * \dot * digraph lms_public_t { * UNINITIALIZED -> INIT [label="init"]; * HAVE_PRIVATE_KEY -> INIT [label="free"]; * INIT -> HAVE_PRIVATE_KEY [label="generate_private_key"]; * } * \enddot */ typedef struct { mbedtls_lms_parameters_t MBEDTLS_PRIVATE(params); uint32_t MBEDTLS_PRIVATE(q_next_usable_key); /*!< The index of the next OTS key that has not been used. */ mbedtls_lmots_private_t *MBEDTLS_PRIVATE(ots_private_keys); /*!< The private key material. One OTS key for each leaf node in the Merkle tree. NULL when have_private_key is 0 and non-NULL otherwise. is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ mbedtls_lmots_public_t *MBEDTLS_PRIVATE(ots_public_keys); /*!< The OTS key public keys, used to build the Merkle tree. NULL when have_private_key is 0 and non-NULL otherwise. Is 2^MBEDTLS_LMS_H_TREE_HEIGHT(type) in length. */ unsigned char MBEDTLS_PRIVATE(have_private_key); /*!< Whether the context contains a private key. Boolean values only. */ } mbedtls_lms_private_t; #endif /* defined(MBEDTLS_LMS_PRIVATE) */ /** * \brief This function initializes an LMS public context * * \param ctx The uninitialized LMS context that will then be * initialized. */ void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx); /** * \brief This function uninitializes an LMS public context * * \param ctx The initialized LMS context that will then be * uninitialized. */ void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx); /** * \brief This function imports an LMS public key into a * public LMS context. * * \note Before this function is called, the context must * have been initialized. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMS context store the key in. * \param key The buffer from which the key will be read. * #MBEDTLS_LMS_PUBLIC_KEY_LEN bytes will be read from * this. * \param key_size The size of the key being imported. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, const unsigned char *key, size_t key_size); /** * \brief This function exports an LMS public key from a * LMS public context that already contains a public * key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a public key. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMS public context that contains * the public key. * \param key The buffer into which the key will be output. Must * be at least #MBEDTLS_LMS_PUBLIC_KEY_LEN in size. * \param key_size The size of the key buffer. * \param key_len If not NULL, will be written with the size of the * key. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len); /** * \brief This function verifies a LMS signature, using a * LMS context that contains a public key. * * \note Before this function is called, the context must * have been initialized and must contain a public key * (either by import or generation). * * \param ctx The initialized LMS public context from which the * public key will be read. * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf from which the signature will be read. * #MBEDTLS_LMS_SIG_LEN bytes will be read from * this. * \param sig_size The size of the signature to be verified. * * \return \c 0 on successful verification. * \return A non-zero error code on failure. */ int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size); #if defined(MBEDTLS_LMS_PRIVATE) /** * \brief This function initializes an LMS private context * * \param ctx The uninitialized LMS private context that will * then be initialized. */ void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx); /** * \brief This function uninitializes an LMS private context * * \param ctx The initialized LMS private context that will then * be uninitialized. */ void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx); /** * \brief This function generates an LMS private key, and * stores in into an LMS private context. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note The seed must have at least 256 bits of entropy. * * \param ctx The initialized LMOTS context to generate the key * into. * \param type The LMS parameter set identifier. * \param otstype The LMOTS parameter set identifier. * \param f_rng The RNG function to be used to generate the key ID. * \param p_rng The RNG context to be passed to f_rng * \param seed The seed used to deterministically generate the * key. * \param seed_size The length of the seed. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, mbedtls_lms_algorithm_type_t type, mbedtls_lmots_algorithm_type_t otstype, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *seed, size_t seed_size); /** * \brief This function calculates an LMS public key from a * LMS context that already contains a private key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a private key. * * \param ctx The initialized LMS public context to calculate the key * from and store it into. * * \param priv_ctx The LMS private context to read the private key * from. This must have been initialized and contain a * private key. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, const mbedtls_lms_private_t *priv_ctx); /** * \brief This function creates a LMS signature, using a * LMS context that contains unused private keys. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note Before this function is called, the context must * have been initialized and must contain a private * key. * * \note Each of the LMOTS private keys inside a LMS private * key can only be used once. If they are reused, then * attackers may be able to forge signatures with that * key. This is all handled transparently, but it is * important to not perform copy operations on LMS * contexts that contain private key material. * * \param ctx The initialized LMS private context from which the * private key will be read. * \param f_rng The RNG function to be used for signature * generation. * \param p_rng The RNG context to be passed to f_rng * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf into which the signature will be stored. * Must be at least #MBEDTLS_LMS_SIG_LEN in size. * \param sig_size The size of the buffer the signature will be * written into. * \param sig_len If not NULL, will be written with the size of the * signature. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, unsigned int msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len); #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_LMS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/mbedtls_config.h000066400000000000000000000002671464416617300261020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ #ifdef __KERNEL__ #include #else #include #endif optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/md.h000066400000000000000000000474151464416617300235310ustar00rootroot00000000000000/** * \file md.h * * \brief This file contains the generic functions for message-digest * (hashing) and HMAC. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_H #define MBEDTLS_MD_H #include "mbedtls/private_access.h" #include #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" /** The selected feature is not available. */ #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /** Bad input parameters to function. */ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /** Failed to allocate memory. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /** Opening or reading of file failed. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 #ifdef __cplusplus extern "C" { #endif /** * \brief Supported message digests. * * \warning MD5 and SHA-1 are considered weak message digests and * their use constitutes a security risk. We recommend considering * stronger message digests instead. * */ /* Note: these are aligned with the definitions of PSA_ALG_ macros for hashes, * in order to enable an efficient implementation of conversion functions. * This is tested by md_to_from_psa() in test_suite_md. */ typedef enum { MBEDTLS_MD_NONE=0, /**< None. */ MBEDTLS_MD_MD5=0x03, /**< The MD5 message digest. */ MBEDTLS_MD_RIPEMD160=0x04, /**< The RIPEMD-160 message digest. */ MBEDTLS_MD_SHA1=0x05, /**< The SHA-1 message digest. */ MBEDTLS_MD_SHA224=0x08, /**< The SHA-224 message digest. */ MBEDTLS_MD_SHA256=0x09, /**< The SHA-256 message digest. */ MBEDTLS_MD_SHA384=0x0a, /**< The SHA-384 message digest. */ MBEDTLS_MD_SHA512=0x0b, /**< The SHA-512 message digest. */ MBEDTLS_MD_SHA3_224=0x10, /**< The SHA3-224 message digest. */ MBEDTLS_MD_SHA3_256=0x11, /**< The SHA3-256 message digest. */ MBEDTLS_MD_SHA3_384=0x12, /**< The SHA3-384 message digest. */ MBEDTLS_MD_SHA3_512=0x13, /**< The SHA3-512 message digest. */ } mbedtls_md_type_t; /* Note: this should always be >= PSA_HASH_MAX_SIZE * in all builds with both CRYPTO_C and MD_LIGHT. * * This is to make things easier for modules such as TLS that may define a * buffer size using MD_MAX_SIZE in a part of the code that's common to PSA * and legacy, then assume the buffer's size is PSA_HASH_MAX_SIZE in another * part of the code based on PSA. */ #if defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA3_512) #define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ #elif defined(MBEDTLS_MD_CAN_SHA384) || defined(MBEDTLS_MD_CAN_SHA3_384) #define MBEDTLS_MD_MAX_SIZE 48 /* longest known is SHA384 */ #elif defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA3_256) #define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 */ #elif defined(MBEDTLS_MD_CAN_SHA224) || defined(MBEDTLS_MD_CAN_SHA3_224) #define MBEDTLS_MD_MAX_SIZE 28 /* longest known is SHA224 */ #else #define MBEDTLS_MD_MAX_SIZE 20 /* longest known is SHA1 or RIPE MD-160 or smaller (MD5 and earlier) */ #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) #define MBEDTLS_MD_MAX_BLOCK_SIZE 144 /* the longest known is SHA3-224 */ #elif defined(MBEDTLS_MD_CAN_SHA3_256) #define MBEDTLS_MD_MAX_BLOCK_SIZE 136 #elif defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_MD_MAX_BLOCK_SIZE 128 #elif defined(MBEDTLS_MD_CAN_SHA3_384) #define MBEDTLS_MD_MAX_BLOCK_SIZE 104 #elif defined(MBEDTLS_MD_CAN_SHA3_512) #define MBEDTLS_MD_MAX_BLOCK_SIZE 72 #else #define MBEDTLS_MD_MAX_BLOCK_SIZE 64 #endif /** * Opaque struct. * * Constructed using either #mbedtls_md_info_from_string or * #mbedtls_md_info_from_type. * * Fields can be accessed with #mbedtls_md_get_size, * #mbedtls_md_get_type and #mbedtls_md_get_name. */ /* Defined internally in library/md_wrap.h. */ typedef struct mbedtls_md_info_t mbedtls_md_info_t; /** * Used internally to indicate whether a context uses legacy or PSA. * * Internal use only. */ typedef enum { MBEDTLS_MD_ENGINE_LEGACY = 0, MBEDTLS_MD_ENGINE_PSA, } mbedtls_md_engine_t; /** * The generic message-digest context. */ typedef struct mbedtls_md_context_t { /** Information about the associated message digest. */ const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); #if defined(MBEDTLS_MD_SOME_PSA) /** Are hash operations dispatched to PSA or legacy? */ mbedtls_md_engine_t MBEDTLS_PRIVATE(engine); #endif /** The digest-specific context (legacy) or the PSA operation. */ void *MBEDTLS_PRIVATE(md_ctx); #if defined(MBEDTLS_MD_C) /** The HMAC part of the context. */ void *MBEDTLS_PRIVATE(hmac_ctx); #endif } mbedtls_md_context_t; /** * \brief This function returns the message-digest information * associated with the given digest type. * * \param md_type The type of digest to search for. * * \return The message-digest information associated with \p md_type. * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type); /** * \brief This function initializes a message-digest context without * binding it to a particular message-digest algorithm. * * This function should always be called first. It prepares the * context for mbedtls_md_setup() for binding it to a * message-digest algorithm. */ void mbedtls_md_init(mbedtls_md_context_t *ctx); /** * \brief This function clears the internal structure of \p ctx and * frees any embedded internal structure, but does not free * \p ctx itself. * * If you have called mbedtls_md_setup() on \p ctx, you must * call mbedtls_md_free() when you are no longer using the * context. * Calling this function if you have previously * called mbedtls_md_init() and nothing else is optional. * You must not call this function if you have not called * mbedtls_md_init(). */ void mbedtls_md_free(mbedtls_md_context_t *ctx); /** * \brief This function selects the message digest algorithm to use, * and allocates internal structures. * * It should be called after mbedtls_md_init() or * mbedtls_md_free(). Makes it necessary to call * mbedtls_md_free() later. * * \param ctx The context to set up. * \param md_info The information structure of the message-digest algorithm * to use. * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), * or non-zero: HMAC is used with this context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac); /** * \brief This function clones the state of a message-digest * context. * * \note You must call mbedtls_md_setup() on \c dst before calling * this function. * * \note The two contexts must have the same type, * for example, both are SHA-256. * * \warning This function clones the message-digest state, not the * HMAC state. * * \param dst The destination context. * \param src The context to be cloned. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. * \return #MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE if both contexts are * not using the same engine. This can be avoided by moving * the call to psa_crypto_init() before the first call to * mbedtls_md_setup(). */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_clone(mbedtls_md_context_t *dst, const mbedtls_md_context_t *src); /** * \brief This function extracts the message-digest size from the * message-digest information structure. * * \param md_info The information structure of the message-digest algorithm * to use. * * \return The size of the message-digest output in Bytes. */ unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info); /** * \brief This function gives the message-digest size associated to * message-digest type. * * \param md_type The message-digest type. * * \return The size of the message-digest output in Bytes, * or 0 if the message-digest type is not known. */ static inline unsigned char mbedtls_md_get_size_from_type(mbedtls_md_type_t md_type) { return mbedtls_md_get_size(mbedtls_md_info_from_type(md_type)); } /** * \brief This function extracts the message-digest type from the * message-digest information structure. * * \param md_info The information structure of the message-digest algorithm * to use. * * \return The type of the message digest. */ mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); /** * \brief This function starts a message-digest computation. * * You must call this function after setting up the context * with mbedtls_md_setup(), and before passing data with * mbedtls_md_update(). * * \param ctx The generic message-digest context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_starts(mbedtls_md_context_t *ctx); /** * \brief This function feeds an input buffer into an ongoing * message-digest computation. * * You must call mbedtls_md_starts() before calling this * function. You may call this function multiple times. * Afterwards, call mbedtls_md_finish(). * * \param ctx The generic message-digest context. * \param input The buffer holding the input data. * \param ilen The length of the input data. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the digest operation, * and writes the result to the output buffer. * * Call this function after a call to mbedtls_md_starts(), * followed by any number of calls to mbedtls_md_update(). * Afterwards, you may either clear the context with * mbedtls_md_free(), or call mbedtls_md_starts() to reuse * the context for another digest operation with the same * algorithm. * * \param ctx The generic message-digest context. * \param output The buffer for the generic message-digest checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief This function calculates the message-digest of a buffer, * with respect to a configurable message-digest algorithm * in a single call. * * The result is calculated as * Output = message_digest(input buffer). * * \param md_info The information structure of the message-digest algorithm * to use. * \param input The buffer holding the data. * \param ilen The length of the input data. * \param output The generic message-digest checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output); /** * \brief This function returns the list of digests supported by the * generic digest module. * * \note The list starts with the strongest available hashes. * * \return A statically allocated array of digests. Each element * in the returned list is an integer belonging to the * message-digest enumeration #mbedtls_md_type_t. * The last entry is 0. */ const int *mbedtls_md_list(void); /** * \brief This function returns the message-digest information * associated with the given digest name. * * \param md_name The name of the digest to search for. * * \return The message-digest information associated with \p md_name. * \return NULL if the associated message-digest information is not found. */ const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name); /** * \brief This function returns the name of the message digest for * the message-digest information structure given. * * \param md_info The information structure of the message-digest algorithm * to use. * * \return The name of the message digest. */ const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); /** * \brief This function returns the message-digest information * from the given context. * * \param ctx The context from which to extract the information. * This must be initialized (or \c NULL). * * \return The message-digest information associated with \p ctx. * \return \c NULL if \p ctx is \c NULL. */ const mbedtls_md_info_t *mbedtls_md_info_from_ctx( const mbedtls_md_context_t *ctx); #if defined(MBEDTLS_FS_IO) /** * \brief This function calculates the message-digest checksum * result of the contents of the provided file. * * The result is calculated as * Output = message_digest(file contents). * * \param md_info The information structure of the message-digest algorithm * to use. * \param path The input file name. * \param output The generic message-digest checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing * the file pointed by \p path. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output); #endif /* MBEDTLS_FS_IO */ /** * \brief This function sets the HMAC key and prepares to * authenticate a new message. * * Call this function after mbedtls_md_setup(), to use * the MD context for an HMAC calculation, then call * mbedtls_md_hmac_update() to provide the input data, and * mbedtls_md_hmac_finish() to get the HMAC value. * * \param ctx The message digest context containing an embedded HMAC * context. * \param key The HMAC secret key. * \param keylen The length of the HMAC key in Bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen); /** * \brief This function feeds an input buffer into an ongoing HMAC * computation. * * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() * before calling this function. * You may call this function multiple times to pass the * input piecewise. * Afterwards, call mbedtls_md_hmac_finish(). * * \param ctx The message digest context containing an embedded HMAC * context. * \param input The buffer holding the input data. * \param ilen The length of the input data. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the HMAC operation, and writes * the result to the output buffer. * * Call this function after mbedtls_md_hmac_starts() and * mbedtls_md_hmac_update() to get the HMAC value. Afterwards * you may either call mbedtls_md_free() to clear the context, * or call mbedtls_md_hmac_reset() to reuse the context with * the same HMAC key. * * \param ctx The message digest context containing an embedded HMAC * context. * \param output The generic HMAC checksum result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output); /** * \brief This function prepares to authenticate a new message with * the same key as the previous HMAC operation. * * You may call this function after mbedtls_md_hmac_finish(). * Afterwards call mbedtls_md_hmac_update() to pass the new * input. * * \param ctx The message digest context containing an embedded HMAC * context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx); /** * \brief This function calculates the full generic HMAC * on the input buffer with the provided key. * * The function allocates the context, performs the * calculation, and frees the context. * * The HMAC result is calculated as * output = generic HMAC(hmac key, input buffer). * * \param md_info The information structure of the message-digest algorithm * to use. * \param key The HMAC secret key. * \param keylen The length of the HMAC secret key in Bytes. * \param input The buffer holding the input data. * \param ilen The length of the input data. * \param output The generic HMAC result. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * failure. */ MBEDTLS_CHECK_RETURN_TYPICAL int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output); #ifdef __cplusplus } #endif #endif /* MBEDTLS_MD_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/md5.h000066400000000000000000000123571464416617300236130ustar00rootroot00000000000000/** * \file md5.h * * \brief MD5 message digest algorithm (hash function) * * \warning MD5 is considered a weak message digest and its use constitutes a * security risk. We recommend considering stronger message * digests instead. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD5_H #define MBEDTLS_MD5_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_MD5_ALT) // Regular implementation // /** * \brief MD5 context structure * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ typedef struct mbedtls_md5_context { uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ uint32_t MBEDTLS_PRIVATE(state)[4]; /*!< intermediate digest state */ unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ } mbedtls_md5_context; #else /* MBEDTLS_MD5_ALT */ #include "md5_alt.h" #endif /* MBEDTLS_MD5_ALT */ /** * \brief Initialize MD5 context * * \param ctx MD5 context to be initialized * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ void mbedtls_md5_init(mbedtls_md5_context *ctx); /** * \brief Clear MD5 context * * \param ctx MD5 context to be cleared * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ void mbedtls_md5_free(mbedtls_md5_context *ctx); /** * \brief Clone (the state of) an MD5 context * * \param dst The destination context * \param src The context to be cloned * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ void mbedtls_md5_clone(mbedtls_md5_context *dst, const mbedtls_md5_context *src); /** * \brief MD5 context setup * * \param ctx context to be initialized * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_starts(mbedtls_md5_context *ctx); /** * \brief MD5 process buffer * * \param ctx MD5 context * \param input buffer holding the data * \param ilen length of the input data * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_update(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); /** * \brief MD5 final digest * * \param ctx MD5 context * \param output MD5 checksum result * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_finish(mbedtls_md5_context *ctx, unsigned char output[16]); /** * \brief MD5 process data block (internal use only) * * \param ctx MD5 context * \param data buffer holding one block of data * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]); /** * \brief Output = MD5( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output MD5 checksum result * * \return 0 if successful * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5(const unsigned char *input, size_t ilen, unsigned char output[16]); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed * * \warning MD5 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ int mbedtls_md5_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_md5.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h000066400000000000000000000111621464416617300271320ustar00rootroot00000000000000/** * \file memory_buffer_alloc.h * * \brief Buffer-based memory allocator */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H #define MBEDTLS_MEMORY_BUFFER_ALLOC_H #include "mbedtls/build_info.h" #include /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) #define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ #endif /** \} name SECTION: Module settings */ #define MBEDTLS_MEMORY_VERIFY_NONE 0 #define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) #define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) #define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | \ MBEDTLS_MEMORY_VERIFY_FREE) #ifdef __cplusplus extern "C" { #endif /** * \brief Initialize use of stack-based memory allocator. * The stack-based allocator does memory management inside the * presented buffer and does not call calloc() and free(). * It sets the global mbedtls_calloc() and mbedtls_free() pointers * to its own functions. * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if * MBEDTLS_THREADING_C is defined) * * \note This code is not optimized and provides a straight-forward * implementation of a stack-based memory allocator. * * \param buf buffer to use as heap * \param len size of the buffer */ void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len); /** * \brief Free the mutex for thread-safety and clear remaining memory */ void mbedtls_memory_buffer_alloc_free(void); /** * \brief Determine when the allocator should automatically verify the state * of the entire chain of headers / meta-data. * (Default: MBEDTLS_MEMORY_VERIFY_NONE) * * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS */ void mbedtls_memory_buffer_set_verify(int verify); #if defined(MBEDTLS_MEMORY_DEBUG) /** * \brief Print out the status of the allocated memory (primarily for use * after a program should have de-allocated all memory) * Prints out a list of 'still allocated' blocks and their stack * trace if MBEDTLS_MEMORY_BACKTRACE is defined. */ void mbedtls_memory_buffer_alloc_status(void); /** * \brief Get the number of alloc/free so far. * * \param alloc_count Number of allocations. * \param free_count Number of frees. */ void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count); /** * \brief Get the peak heap usage so far * * \param max_used Peak number of bytes in use or committed. This * includes bytes in allocated blocks too small to split * into smaller blocks but larger than the requested size. * \param max_blocks Peak number of blocks in use, including free and used */ void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks); /** * \brief Reset peak statistics */ void mbedtls_memory_buffer_alloc_max_reset(void); /** * \brief Get the current heap usage * * \param cur_used Current number of bytes in use or committed. This * includes bytes in allocated blocks too small to split * into smaller blocks but larger than the requested size. * \param cur_blocks Current number of blocks in use, including free and used */ void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks); #endif /* MBEDTLS_MEMORY_DEBUG */ /** * \brief Verifies that all headers in the memory buffer are correct * and contain sane values. Helps debug buffer-overflow errors. * * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. * Prints out full header information if MBEDTLS_MEMORY_DEBUG * is defined. (Includes stack trace information for each block if * MBEDTLS_MEMORY_BACKTRACE is defined as well). * * \return 0 if verified, 1 otherwise */ int mbedtls_memory_buffer_alloc_verify(void); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if a test failed */ int mbedtls_memory_buffer_alloc_self_test(int verbose); #endif #ifdef __cplusplus } #endif #endif /* memory_buffer_alloc.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h000066400000000000000000000265561464416617300254550ustar00rootroot00000000000000/** * \file net_sockets.h * * \brief Network sockets abstraction layer to integrate Mbed TLS into a * BSD-style sockets API. * * The network sockets module provides an example integration of the * Mbed TLS library into a BSD sockets implementation. The module is * intended to be an example of how Mbed TLS can be integrated into a * networking stack, as well as to be Mbed TLS's network integration * for its supported platforms. * * The module is intended only to be used with the Mbed TLS library and * is not intended to be used by third party application software * directly. * * The supported platforms are as follows: * * Microsoft Windows and Windows CE * * POSIX/Unix platforms including Linux, OS X * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_NET_SOCKETS_H #define MBEDTLS_NET_SOCKETS_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #include #include /** Failed to open a socket. */ #define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /** The connection to the given server / port failed. */ #define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /** Binding of the socket failed. */ #define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /** Could not listen on the socket. */ #define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /** Could not accept the incoming connection. */ #define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /** Reading information from the socket failed. */ #define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /** Sending information through the socket failed. */ #define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /** Connection was reset by peer. */ #define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /** Failed to get an IP address for the given hostname. */ #define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /** Buffer is too small to hold the data. */ #define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /** The context is invalid, eg because it was free()ed. */ #define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /** Polling the net context failed. */ #define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /** Input invalid. */ #define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 #define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ #define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ #define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ #define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ #define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ #ifdef __cplusplus extern "C" { #endif /** * Wrapper type for sockets. * * Currently backed by just a file descriptor, but might be more in the future * (eg two file descriptors for combined IPv4 + IPv6 support, or additional * structures for hand-made UDP demultiplexing). */ typedef struct mbedtls_net_context { /** The underlying file descriptor. * * This field is only guaranteed to be present on POSIX/Unix-like platforms. * On other platforms, it may have a different type, have a different * meaning, or be absent altogether. */ int fd; } mbedtls_net_context; /** * \brief Initialize a context * Just makes the context ready to be used or freed safely. * * \param ctx Context to initialize */ void mbedtls_net_init(mbedtls_net_context *ctx); /** * \brief Initiate a connection with host:port in the given protocol * * \param ctx Socket to use * \param host Host to connect to * \param port Port to connect to * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP * * \return 0 if successful, or one of: * MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_UNKNOWN_HOST, * MBEDTLS_ERR_NET_CONNECT_FAILED * * \note Sets the socket in connected mode even with UDP. */ int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto); /** * \brief Create a receiving socket on bind_ip:port in the chosen * protocol. If bind_ip == NULL, all interfaces are bound. * * \param ctx Socket to use * \param bind_ip IP to bind to, can be NULL * \param port Port number to use * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP * * \return 0 if successful, or one of: * MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_UNKNOWN_HOST, * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_LISTEN_FAILED * * \note Regardless of the protocol, opens the sockets and binds it. * In addition, make the socket listening if protocol is TCP. */ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto); /** * \brief Accept a connection from a remote client * * \param bind_ctx Relevant socket * \param client_ctx Will contain the connected client socket * \param client_ip Will contain the client IP address, can be NULL * \param buf_size Size of the client_ip buffer * \param cip_len Will receive the size of the client IP written, * can be NULL if client_ip is null * * \return 0 if successful, or * MBEDTLS_ERR_NET_SOCKET_FAILED, * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_ACCEPT_FAILED, or * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to * non-blocking and accept() would block. */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *cip_len); /** * \brief Check and wait for the context to be ready for read/write * * \note The current implementation of this function uses * select() and returns an error if the file descriptor * is \c FD_SETSIZE or greater. * * \param ctx Socket to check * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and * MBEDTLS_NET_POLL_WRITE specifying the events * to wait for: * - If MBEDTLS_NET_POLL_READ is set, the function * will return as soon as the net context is available * for reading. * - If MBEDTLS_NET_POLL_WRITE is set, the function * will return as soon as the net context is available * for writing. * \param timeout Maximal amount of time to wait before returning, * in milliseconds. If \c timeout is zero, the * function returns immediately. If \c timeout is * -1u, the function blocks potentially indefinitely. * * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE * on success or timeout, or a negative return code otherwise. */ int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout); /** * \brief Set the socket blocking * * \param ctx Socket to set * * \return 0 if successful, or a non-zero error code */ int mbedtls_net_set_block(mbedtls_net_context *ctx); /** * \brief Set the socket non-blocking * * \param ctx Socket to set * * \return 0 if successful, or a non-zero error code */ int mbedtls_net_set_nonblock(mbedtls_net_context *ctx); /** * \brief Portable usleep helper * * \param usec Amount of microseconds to sleep * * \note Real amount of time slept will not be less than * select()'s timeout granularity (typically, 10ms). */ void mbedtls_net_usleep(unsigned long usec); /** * \brief Read at most 'len' characters. If no error occurs, * the actual amount read is returned. * * \param ctx Socket * \param buf The buffer to write to * \param len Maximum length of the buffer * * \return the number of bytes received, * or a non-zero error code; with a non-blocking socket, * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. */ int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len); /** * \brief Write at most 'len' characters. If no error occurs, * the actual amount read is returned. * * \param ctx Socket * \param buf The buffer to read from * \param len The length of the buffer * * \return the number of bytes sent, * or a non-zero error code; with a non-blocking socket, * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. */ int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len); /** * \brief Read at most 'len' characters, blocking for at most * 'timeout' seconds. If no error occurs, the actual amount * read is returned. * * \note The current implementation of this function uses * select() and returns an error if the file descriptor * is \c FD_SETSIZE or greater. * * \param ctx Socket * \param buf The buffer to write to * \param len Maximum length of the buffer * \param timeout Maximum number of milliseconds to wait for data * 0 means no timeout (wait forever) * * \return The number of bytes received if successful. * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. * Another negative error code (MBEDTLS_ERR_NET_xxx) * for other failures. * * \note This function will block (until data becomes available or * timeout is reached) even if the socket is set to * non-blocking. Handling timeouts with non-blocking reads * requires a different strategy. */ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout); /** * \brief Closes down the connection and free associated data * * \param ctx The context to close * * \note This function frees and clears data associated with the * context but does not free the memory pointed to by \p ctx. * This memory is the responsibility of the caller. */ void mbedtls_net_close(mbedtls_net_context *ctx); /** * \brief Gracefully shutdown the connection and free associated data * * \param ctx The context to free * * \note This function frees and clears data associated with the * context but does not free the memory pointed to by \p ctx. * This memory is the responsibility of the caller. */ void mbedtls_net_free(mbedtls_net_context *ctx); #ifdef __cplusplus } #endif #endif /* net_sockets.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h000066400000000000000000000155011464416617300245760ustar00rootroot00000000000000/** * \file nist_kw.h * * \brief This file provides an API for key wrapping (KW) and key wrapping with * padding (KWP) as defined in NIST SP 800-38F. * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf * * Key wrapping specifies a deterministic authenticated-encryption mode * of operation, according to NIST SP 800-38F: Recommendation for * Block Cipher Modes of Operation: Methods for Key Wrapping. Its * purpose is to protect cryptographic keys. * * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. * https://tools.ietf.org/html/rfc3394 * https://tools.ietf.org/html/rfc5649 * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_NIST_KW_H #define MBEDTLS_NIST_KW_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #ifdef __cplusplus extern "C" { #endif typedef enum { MBEDTLS_KW_MODE_KW = 0, MBEDTLS_KW_MODE_KWP = 1 } mbedtls_nist_kw_mode_t; #if !defined(MBEDTLS_NIST_KW_ALT) // Regular implementation // /** * \brief The key wrapping context-type definition. The key wrapping context is passed * to the APIs called. * * \note The definition of this type may change in future library versions. * Don't make any assumptions on this context! */ typedef struct { mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ } mbedtls_nist_kw_context; #else /* MBEDTLS_NIST_key wrapping_ALT */ #include "nist_kw_alt.h" #endif /* MBEDTLS_NIST_KW_ALT */ /** * \brief This function initializes the specified key wrapping context * to make references valid and prepare the context * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). * * \param ctx The key wrapping context to initialize. * */ void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx); /** * \brief This function initializes the key wrapping context set in the * \p ctx parameter and sets the encryption key. * * \param ctx The key wrapping context. * \param cipher The 128-bit block cipher to use. Only AES is supported. * \param key The Key Encryption Key (KEK). * \param keybits The KEK size in bits. This must be acceptable by the cipher. * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping * * \return \c 0 on success. * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers * which are not supported. * \return cipher-specific error code on failure of the underlying cipher. */ int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits, const int is_wrap); /** * \brief This function releases and clears the specified key wrapping context * and underlying cipher sub-context. * * \param ctx The key wrapping context to clear. */ void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx); /** * \brief This function encrypts a buffer using key wrapping. * * \param ctx The key wrapping context to use for encryption. * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) * \param input The buffer holding the input data. * \param in_len The length of the input data in Bytes. * The input uses units of 8 Bytes called semiblocks. *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
* \param[out] output The buffer holding the output data. *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of * 8 bytes for KWP (15 bytes at most).
* \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. * \param[in] out_size The capacity of the output buffer. * * \return \c 0 on success. * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. * \return cipher-specific error code on failure of the underlying cipher. */ int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size); /** * \brief This function decrypts a buffer using key wrapping. * * \param ctx The key wrapping context to use for decryption. * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) * \param input The buffer holding the input data. * \param in_len The length of the input data in Bytes. * The input uses units of 8 Bytes called semiblocks. * The input must be a multiple of semiblocks. *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
* \param[out] output The buffer holding the output data. * The output buffer's minimal length is 8 bytes shorter than \p in_len. * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, * depending on how much padding was added to the data. * \param[in] out_size The capacity of the output buffer. * * \return \c 0 on success. * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. * \return cipher-specific error code on failure of the underlying cipher. */ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size); #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /** * \brief The key wrapping checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_nist_kw_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_NIST_KW_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/oid.h000066400000000000000000001164141464416617300237000ustar00rootroot00000000000000/** * \file oid.h * * \brief Object Identifier (OID) database */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_OID_H #define MBEDTLS_OID_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/pk.h" #include #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif #include "mbedtls/md.h" /** OID is not found. */ #define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /** output buffer is too small */ #define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /* This is for the benefit of X.509, but defined here in order to avoid * having a "backwards" include of x.509.h here */ /* * X.509 extension types (internal, arbitrary values for bitsets) */ #define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) #define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) #define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) #define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) #define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) #define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) #define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) #define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) #define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) #define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) #define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) #define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) #define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) #define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) #define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) #define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) /* * Maximum number of OID components allowed */ #define MBEDTLS_OID_MAX_COMPONENTS 128 /* * Top level OID tuples */ #define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ #define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ #define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ #define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ /* * ISO Member bodies OID parts */ #define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ #define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ #define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ #define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ #define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ MBEDTLS_OID_ORG_ANSI_X9_62 /* * ISO Identified organization OID parts */ #define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ #define MBEDTLS_OID_ORG_OIW "\x0e" #define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" #define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" #define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" #define MBEDTLS_OID_ORG_THAWTE "\x65" /* thawte(101) */ #define MBEDTLS_OID_THAWTE MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_THAWTE #define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ #define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_CERTICOM #define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ #define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_ORG_TELETRUST /* * ISO ITU OID parts */ #define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ #define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US \ MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ #define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ #define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ #define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ #define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ /* ISO arc for standard certificate and CRL extensions */ #define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ #define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ /** * Private Internet Extensions * { iso(1) identified-organization(3) dod(6) internet(1) * security(5) mechanisms(5) pkix(7) } */ #define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD \ "\x01" #define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" /* * Arc for standard naming attributes */ #define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ #define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ #define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ #define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ #define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ #define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ #define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ #define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ #define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ #define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ #define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ #define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ #define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ #define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ #define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ #define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */ #define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ #define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ #define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ #define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ /* * OIDs for standard certificate extensions */ #define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ #define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ #define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ #define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ #define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ #define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ #define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ #define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ #define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ #define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ #define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ #define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ #define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ #define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ #define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ /* * Certificate policies */ #define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ /* * Netscape certificate extensions */ #define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" #define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" #define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" #define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" #define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" #define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" #define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" #define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" #define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" #define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" #define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" /* * OIDs for CRL extensions */ #define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" #define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ /* * X.509 v3 Extended key usage OIDs */ #define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ #define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ #define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ #define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ #define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ #define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ #define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ #define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ /** * Wi-SUN Alliance Field Area Network * { iso(1) identified-organization(3) dod(6) internet(1) * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } */ #define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" #define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ #define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ /* * PKCS definition OIDs */ #define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ #define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ #define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ #define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ #define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ #define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ /* * PKCS#1 OIDs */ #define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ #define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ #define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ #define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ #define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ #define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ #define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ #define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" #define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ /* RFC 4055 */ #define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ #define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ /* * Digest algorithms */ #define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ #define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x07" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x08" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x09" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */ #define MBEDTLS_OID_DIGEST_ALG_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x0a" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */ #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ #define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ #define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ #define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ #define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ #define MBEDTLS_OID_HMAC_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x0d" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */ #define MBEDTLS_OID_HMAC_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x0e" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */ #define MBEDTLS_OID_HMAC_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x0f" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */ #define MBEDTLS_OID_HMAC_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x10" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */ #define MBEDTLS_OID_HMAC_RIPEMD160 MBEDTLS_OID_INTERNET "\x05\x05\x08\x01\x04" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */ /* * Encryption algorithms, * the following standardized object identifiers are specified at * https://datatracker.ietf.org/doc/html/rfc8018#appendix-C. */ #define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG \ MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ #define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ #define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ #define MBEDTLS_OID_AES_128_CBC MBEDTLS_OID_AES "\x02" /** aes128-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes128-CBC-PAD(2) } */ #define MBEDTLS_OID_AES_192_CBC MBEDTLS_OID_AES "\x16" /** aes192-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes192-CBC-PAD(22) } */ #define MBEDTLS_OID_AES_256_CBC MBEDTLS_OID_AES "\x2a" /** aes256-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes256-CBC-PAD(42) } */ /* * Key Wrapping algorithms */ /* * RFC 5649 */ #define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ #define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ #define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ #define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ #define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ #define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ /* * PKCS#5 OIDs */ #define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ #define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ #define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ /* * PKCS#5 PBES1 algorithms */ #define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ #define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ #define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ /* * PKCS#7 OIDs */ #define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ #define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ #define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ #define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ #define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ /* * PKCS#8 OIDs */ #define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ /* * PKCS#12 PBE OIDs */ #define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ #define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ /* * EC key algorithms from RFC 5480 */ /* id-ecPublicKey OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ #define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" /* id-ecDH OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) * schemes(1) ecdh(12) } */ #define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" /* * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 */ /* secp192r1 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ #define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" /* secp224r1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ #define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" /* secp256r1 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ #define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" /* secp384r1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ #define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" /* secp521r1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ #define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" /* secp192k1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ #define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" /* secp224k1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ #define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" /* secp256k1 OBJECT IDENTIFIER ::= { * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ #define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" /* RFC 5639 4.1 * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) * identified-organization(3) teletrust(36) algorithm(3) signature- * algorithm(3) ecSign(2) 8} * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ #define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" /* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ #define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" /* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ #define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" /* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ #define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" /* * SEC1 C.1 * * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} */ #define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" #define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" /* * ECDSA signature identifiers, from RFC 5480 */ #define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ #define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ /* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ #define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" /* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 1 } */ #define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" /* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 2 } */ #define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" /* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 3 } */ #define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" /* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) * ecdsa-with-SHA2(3) 4 } */ #define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" /* * EC key algorithms from RFC 8410 */ #define MBEDTLS_OID_X25519 MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } */ #define MBEDTLS_OID_X448 MBEDTLS_OID_THAWTE "\x6f" /**< id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } */ #define MBEDTLS_OID_ED25519 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } */ #define MBEDTLS_OID_ED448 MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } */ #ifdef __cplusplus extern "C" { #endif /** * \brief Base OID descriptor structure */ typedef struct mbedtls_oid_descriptor_t { const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ #if !defined(MBEDTLS_X509_REMOVE_INFO) const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ #endif } mbedtls_oid_descriptor_t; /** * \brief Translate an ASN.1 OID into its numeric representation * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") * * \param buf buffer to put representation in * \param size size of the buffer * \param oid OID to translate * * \return Length of the string written (excluding final NULL) or * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); /** * \brief Translate a string containing a dotted-decimal * representation of an ASN.1 OID into its encoded form * (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D"). * On success, this function allocates oid->buf from the * heap. It must be freed by the caller using mbedtls_free(). * * \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID * \param oid_str string representation of the OID to parse * \param size length of the OID string, not including any null terminator * * \return 0 if successful * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not * represent a valid OID * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to * allocate oid->buf */ int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size); /** * \brief Translate an X.509 extension OID into local values * * \param oid OID to use * \param ext_type place to store the extension type * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); /** * \brief Translate an X.509 attribute type OID into the short name * (e.g. the OID for an X520 Common Name into "CN") * * \param oid OID to use * \param short_name place to store the string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name); /** * \brief Translate PublicKeyAlgorithm OID into pk_type * * \param oid OID to use * \param pk_alg place to store public key algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg); /** * \brief Translate pk_type into PublicKeyAlgorithm OID * * \param pk_alg Public key type to look for * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, const char **oid, size_t *olen); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /** * \brief Translate NamedCurve OID into an EC group identifier * * \param oid OID to use * \param grp_id place to store group id * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); /** * \brief Translate EC group identifier into NamedCurve OID * * \param grp_id EC group identifier * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, const char **oid, size_t *olen); /** * \brief Translate AlgorithmIdentifier OID into an EC group identifier, * for curves that are directly encoded at this level * * \param oid OID to use * \param grp_id place to store group id * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); /** * \brief Translate EC group identifier into AlgorithmIdentifier OID, * for curves that are directly encoded at this level * * \param grp_id EC group identifier * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id, const char **oid, size_t *olen); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /** * \brief Translate SignatureAlgorithm OID into md_type and pk_type * * \param oid OID to use * \param md_alg place to store message digest algorithm * \param pk_alg place to store public key algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg); /** * \brief Translate SignatureAlgorithm OID into description * * \param oid OID to use * \param desc place to store string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc); /** * \brief Translate md_type and pk_type into SignatureAlgorithm OID * * \param md_alg message digest algorithm * \param pk_alg public key algorithm * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const char **oid, size_t *olen); /** * \brief Translate hmac algorithm OID into md_type * * \param oid OID to use * \param md_hmac place to store message hmac algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); /** * \brief Translate hash algorithm OID into md_type * * \param oid OID to use * \param md_alg place to store message digest algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Translate Extended Key Usage OID into description * * \param oid OID to use * \param desc place to store string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); #endif /** * \brief Translate certificate policies OID into description * * \param oid OID to use * \param desc place to store string pointer * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_certificate_policies(const mbedtls_asn1_buf *oid, const char **desc); /** * \brief Translate md_type into hash algorithm OID * * \param md_alg message digest algorithm * \param oid place to store ASN.1 OID string pointer * \param olen length of the OID * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen); #if defined(MBEDTLS_CIPHER_C) /** * \brief Translate encryption algorithm OID into cipher_type * * \param oid OID to use * \param cipher_alg place to store cipher algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); #if defined(MBEDTLS_PKCS12_C) /** * \brief Translate PKCS#12 PBE algorithm OID into md_type and * cipher_type * * \param oid OID to use * \param md_alg place to store message digest algorithm * \param cipher_alg place to store cipher algorithm * * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND */ int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, mbedtls_cipher_type_t *cipher_alg); #endif /* MBEDTLS_PKCS12_C */ #endif /* MBEDTLS_CIPHER_C */ #ifdef __cplusplus } #endif #endif /* oid.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/pem.h000066400000000000000000000134141464416617300237020ustar00rootroot00000000000000/** * \file pem.h * * \brief Privacy Enhanced Mail (PEM) decoding */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PEM_H #define MBEDTLS_PEM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include /** * \name PEM Error codes * These error codes are returned in case of errors reading the * PEM data. * \{ */ /** No PEM header or footer found. */ #define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /** PEM string is not as expected. */ #define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /** Failed to allocate memory. */ #define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /** RSA IV is not in hex-format. */ #define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /** Unsupported key encryption algorithm. */ #define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /** Private key password can't be empty. */ #define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /** Unavailable feature, e.g. hashing/encryption combination. */ #define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /** Bad input parameters to function. */ #define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /** \} name PEM Error codes */ #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_PEM_PARSE_C) /** * \brief PEM context structure */ typedef struct mbedtls_pem_context { unsigned char *MBEDTLS_PRIVATE(buf); /*!< buffer for decoded data */ size_t MBEDTLS_PRIVATE(buflen); /*!< length of the buffer */ unsigned char *MBEDTLS_PRIVATE(info); /*!< buffer for extra header information */ } mbedtls_pem_context; /** * \brief PEM context setup * * \param ctx context to be initialized */ void mbedtls_pem_init(mbedtls_pem_context *ctx); /** * \brief Read a buffer for PEM information and store the resulting * data into the specified context buffers. * * \param ctx context to use * \param header header string to seek and expect * \param footer footer string to seek and expect * \param data source data to look in (must be nul-terminated) * \param pwd password for decryption (can be NULL) * \param pwdlen length of password * \param use_len destination for total length used from data buffer. It is * set after header is correctly read, so unless you get * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is * the length to skip. * * \note Attempts to check password correctness by verifying if * the decrypted text starts with an ASN.1 sequence of * appropriate length * * \note \c mbedtls_pem_free must be called on PEM context before * the PEM context can be reused in another call to * \c mbedtls_pem_read_buffer * * \return 0 on success, or a specific PEM error code */ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len); /** * \brief Get the pointer to the decoded binary data in a PEM context. * * \param ctx PEM context to access. * \param buflen On success, this will contain the length of the binary data. * This must be a valid (non-null) pointer. * * \return A pointer to the decoded binary data. * * \note The returned pointer remains valid only until \p ctx is modified or freed. */ static inline const unsigned char *mbedtls_pem_get_buffer(mbedtls_pem_context *ctx, size_t *buflen) { *buflen = ctx->MBEDTLS_PRIVATE(buflen); return ctx->MBEDTLS_PRIVATE(buf); } /** * \brief PEM context memory freeing * * \param ctx context to be freed */ void mbedtls_pem_free(mbedtls_pem_context *ctx); #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a buffer of PEM information from a DER encoded * buffer. * * \param header The header string to write. * \param footer The footer string to write. * \param der_data The DER data to encode. * \param der_len The length of the DER data \p der_data in Bytes. * \param buf The buffer to write to. * \param buf_len The length of the output buffer \p buf in Bytes. * \param olen The address at which to store the total length written * or required (if \p buf_len is not enough). * * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len * to request the length of the resulting PEM buffer in * `*olen`. * * \note This function may be called with overlapping \p der_data * and \p buf buffers. * * \return \c 0 on success. * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large * enough to hold the PEM buffer. In this case, `*olen` holds * the required minimum size of \p buf. * \return Another PEM or BASE64 error code on other kinds of failure. */ int mbedtls_pem_write_buffer(const char *header, const char *footer, const unsigned char *der_data, size_t der_len, unsigned char *buf, size_t buf_len, size_t *olen); #endif /* MBEDTLS_PEM_WRITE_C */ #ifdef __cplusplus } #endif #endif /* pem.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/pk.h000066400000000000000000001601731464416617300235400ustar00rootroot00000000000000/** * \file pk.h * * \brief Public Key abstraction layer */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_H #define MBEDTLS_PK_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/md.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa/crypto.h" #endif /** Memory allocation failed. */ #define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /** Type mismatch, eg attempt to encrypt with an ECDSA key */ #define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /** Bad input parameters to function. */ #define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /** Read/write of file failed. */ #define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /** Unsupported key version */ #define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /** Invalid key tag or value. */ #define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /** Key algorithm is unsupported (only RSA and EC are supported). */ #define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /** Private key password can't be empty. */ #define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /** The pubkey tag or value is invalid (only RSA and EC are supported). */ #define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /** The algorithm tag or value is invalid. */ #define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /** Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /** Unavailable feature, e.g. RSA disabled for RSA key. */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /** The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /** The output buffer is too small. */ #define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 #ifdef __cplusplus extern "C" { #endif /** * \brief Public key types */ typedef enum { MBEDTLS_PK_NONE=0, MBEDTLS_PK_RSA, MBEDTLS_PK_ECKEY, MBEDTLS_PK_ECKEY_DH, MBEDTLS_PK_ECDSA, MBEDTLS_PK_RSA_ALT, MBEDTLS_PK_RSASSA_PSS, MBEDTLS_PK_OPAQUE, } mbedtls_pk_type_t; /** * \brief Options for RSASSA-PSS signature verification. * See \c mbedtls_rsa_rsassa_pss_verify_ext() */ typedef struct mbedtls_pk_rsassa_pss_options { /** The digest to use for MGF1 in PSS. * * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is * disabled, this must be equal to the \c md_alg argument passed * to mbedtls_pk_verify_ext(). In a future version of the library, * this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is * enabled regardless of the status of #MBEDTLS_RSA_C. */ mbedtls_md_type_t mgf1_hash_id; /** The expected length of the salt, in bytes. This may be * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. * * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only * #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be * ignored (allowing any salt length). */ int expected_salt_len; } mbedtls_pk_rsassa_pss_options; /** * \brief Maximum size of a signature made by mbedtls_pk_sign(). */ /* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature * size among the supported signature types. Do it by starting at 0, * then incrementally increasing to be large enough for each supported * signature mechanism. * * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). */ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 #if (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT)) && \ MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* For RSA, the signature can be as large as the bignum module allows. * For RSA_ALT, the signature size is not necessarily tied to what the * bignum module can do, but in the absence of any specific setting, * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE #endif #if defined(MBEDTLS_ECDSA_C) && \ MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* For ECDSA, the ecdsa module exports a constant for the maximum * signature size. */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made * through the PSA API in the PSA representation. */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE #endif #if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE /* The Mbed TLS representation is different for ECDSA signatures: * PSA uses the raw concatenation of r and s, * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the * types, lengths (represented by up to 2 bytes), and potential leading * zeros of the INTEGERs and the SEQUENCE. */ #undef MBEDTLS_PK_SIGNATURE_MAX_SIZE #define MBEDTLS_PK_SIGNATURE_MAX_SIZE (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11) #endif #endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ /* Internal helper to define which fields in the pk_context structure below * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly) * format. It should be noted that this only affects how data is stored, not * which functions are used for various operations. The overall picture looks * like this: * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data * structure and legacy functions * - if USE_PSA is defined and * - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly * format and use PSA functions * - if !ECP_C then use new raw data and PSA functions directly. * * The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the * ecp_keypair structure inside the pk_context so they can modify it using * ECP functions which are not under PK module's control. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ !defined(MBEDTLS_ECP_C) #define MBEDTLS_PK_USE_PSA_EC_DATA #endif /** * \brief Types for interfacing with the debug module */ typedef enum { MBEDTLS_PK_DEBUG_NONE = 0, MBEDTLS_PK_DEBUG_MPI, MBEDTLS_PK_DEBUG_ECP, MBEDTLS_PK_DEBUG_PSA_EC, } mbedtls_pk_debug_type; /** * \brief Item to send to the debug module */ typedef struct mbedtls_pk_debug_item { mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); const char *MBEDTLS_PRIVATE(name); void *MBEDTLS_PRIVATE(value); } mbedtls_pk_debug_item; /** Maximum number of item send for debugging, plus 1 */ #define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 /** * \brief Public key information and operations * * \note The library does not support custom pk info structures, * only built-in structures returned by * mbedtls_cipher_info_from_type(). */ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; #define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \ PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /** * \brief Public key container */ typedef struct mbedtls_pk_context { const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ void *MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ /* The following field is used to store the ID of a private key in the * following cases: * - opaque key when MBEDTLS_USE_PSA_CRYPTO is defined * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case: * - the pk_ctx above is not not used to store the private key anymore. * Actually that field not populated at all in this case because also * the public key will be stored in raw format as explained below * - this ID is used for all private key operations (ex: sign, check * key pair, key write, etc) using PSA functions * * Note: this private key storing solution only affects EC keys, not the * other ones. The latters still use the pk_ctx to store their own * context. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* The following fields are meant for storing the public key in raw format * which is handy for: * - easily importing it into the PSA context * - reducing the ECP module dependencies in the PK one. * * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled: * - the pk_ctx above is not used anymore for storing the public key * inside the ecp_keypair structure * - the following fields are used for all public key operations: signature * verify, key pair check and key write. * - For a key pair, priv_id contains the private key. For a public key, * priv_id is null. * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy * ecp_keypair structure is used for storing the public key and performing * all the operations. * * Note: This new public key storing solution only works for EC keys, not * other ones. The latters still use pk_ctx to store their own * context. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) uint8_t MBEDTLS_PRIVATE(pub_raw)[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; /**< Raw public key */ size_t MBEDTLS_PRIVATE(pub_raw_len); /**< Valid bytes in "pub_raw" */ psa_ecc_family_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ size_t MBEDTLS_PRIVATE(ec_bits); /**< Curve's bits of pk */ #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } mbedtls_pk_context; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Context for resuming operations */ typedef struct { const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ void *MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ } mbedtls_pk_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_pk_restart_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** * \brief Types for RSA-alt abstraction */ typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /** * \brief Return information associated with the given PK type * * \param pk_type PK type to search for. * * \return The PK info associated with the type or NULL if not found. */ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); /** * \brief Initialize a #mbedtls_pk_context (as NONE). * * \param ctx The context to initialize. * This must not be \c NULL. */ void mbedtls_pk_init(mbedtls_pk_context *ctx); /** * \brief Free the components of a #mbedtls_pk_context. * * \param ctx The context to clear. It must have been initialized. * If this is \c NULL, this function does nothing. * * \note For contexts that have been set up with * mbedtls_pk_setup_opaque(), this does not free the underlying * PSA key and you still need to call psa_destroy_key() * independently if you want to destroy that key. */ void mbedtls_pk_free(mbedtls_pk_context *ctx); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context * * \param ctx The context to initialize. * This must not be \c NULL. */ void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx); /** * \brief Free the components of a restart context * * \param ctx The context to clear. It must have been initialized. * If this is \c NULL, this function does nothing. */ void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** * \brief Initialize a PK context with the information given * and allocates the type-specific PK subcontext. * * \param ctx Context to initialize. It must not have been set * up yet (type #MBEDTLS_PK_NONE). * \param info Information to use * * \return 0 on success, * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. * * \note For contexts holding an RSA-alt key, use * \c mbedtls_pk_setup_rsa_alt() instead. */ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Initialize a PK context to wrap a PSA key. * * \note This function replaces mbedtls_pk_setup() for contexts * that wrap a (possibly opaque) PSA key instead of * storing and manipulating the key material directly. * * \param ctx The context to initialize. It must be empty (type NONE). * \param key The PSA key to wrap, which must hold an ECC or RSA key * pair (see notes below). * * \note The wrapped key must remain valid as long as the * wrapping PK context is in use, that is at least between * the point this function is called and the point * mbedtls_pk_free() is called on this context. The wrapped * key might then be independently used or destroyed. * * \note This function is currently only available for ECC or RSA * key pairs (that is, keys containing private key material). * Support for other key types may be added later. * * \return \c 0 on success. * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input * (context already used, invalid key identifier). * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an * ECC key pair. * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. */ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, const mbedtls_svc_key_id_t key); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /** * \brief Initialize an RSA-alt context * * \param ctx Context to initialize. It must not have been set * up yet (type #MBEDTLS_PK_NONE). * \param key RSA key pointer * \param decrypt_func Decryption function * \param sign_func Signing function * \param key_len_func Function returning key length in bytes * * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the * context wasn't already initialized as RSA_ALT. * * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. */ int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, mbedtls_pk_rsa_alt_decrypt_func decrypt_func, mbedtls_pk_rsa_alt_sign_func sign_func, mbedtls_pk_rsa_alt_key_len_func key_len_func); #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /** * \brief Get the size in bits of the underlying key * * \param ctx The context to query. It must have been initialized. * * \return Key size in bits, or 0 on error */ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); /** * \brief Get the length in bytes of the underlying key * * \param ctx The context to query. It must have been initialized. * * \return Key length in bytes, or 0 on error */ static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) { return (mbedtls_pk_get_bitlen(ctx) + 7) / 8; } /** * \brief Tell if a context can do the operation given by type * * \param ctx The context to query. It must have been initialized. * \param type The desired type. * * \return 1 if the context can do operations on the given type. * \return 0 if the context cannot do the operations on the given * type. This is always the case for a context that has * been initialized but not set up, or that has been * cleared with mbedtls_pk_free(). */ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Tell if context can do the operation given by PSA algorithm * * \param ctx The context to query. It must have been initialized. * \param alg PSA algorithm to check against, the following are allowed: * PSA_ALG_RSA_PKCS1V15_SIGN(hash), * PSA_ALG_RSA_PSS(hash), * PSA_ALG_RSA_PKCS1V15_CRYPT, * PSA_ALG_ECDSA(hash), * PSA_ALG_ECDH, where hash is a specific hash. * \param usage PSA usage flag to check against, must be composed of: * PSA_KEY_USAGE_SIGN_HASH * PSA_KEY_USAGE_DECRYPT * PSA_KEY_USAGE_DERIVE. * Context key must match all passed usage flags. * * \warning Since the set of allowed algorithms and usage flags may be * expanded in the future, the return value \c 0 should not * be taken in account for non-allowed algorithms and usage * flags. * * \return 1 if the context can do operations on the given type. * \return 0 if the context cannot do the operations on the given * type, for non-allowed algorithms and usage flags, or * for a context that has been initialized but not set up * or that has been cleared with mbedtls_pk_free(). */ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, psa_key_usage_t usage); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /** * \brief Determine valid PSA attributes that can be used to * import a key into PSA. * * The attributes determined by this function are suitable * for calling mbedtls_pk_import_into_psa() to create * a PSA key with the same key material. * * The typical flow of operations involving this function is * ``` * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * int ret = mbedtls_pk_get_psa_attributes(pk, &attributes); * if (ret != 0) ...; // error handling omitted * // Tweak attributes if desired * psa_key_id_t key_id = 0; * ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id); * if (ret != 0) ...; // error handling omitted * ``` * * \note This function does not support RSA-alt contexts * (set up with mbedtls_pk_setup_rsa_alt()). * * \param[in] pk The PK context to use. It must have been set up. * It can either contain a key pair or just a public key. * \param usage A single `PSA_KEY_USAGE_xxx` flag among the following: * - #PSA_KEY_USAGE_DECRYPT: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type, and the usage policy will allow * #PSA_KEY_USAGE_ENCRYPT as well as * #PSA_KEY_USAGE_DECRYPT. * - #PSA_KEY_USAGE_DERIVE: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type. * - #PSA_KEY_USAGE_ENCRYPT: The output * \p attributes will contain a public key type. * - #PSA_KEY_USAGE_SIGN_HASH: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type, and the usage policy will allow * #PSA_KEY_USAGE_VERIFY_HASH as well as * #PSA_KEY_USAGE_SIGN_HASH. * - #PSA_KEY_USAGE_SIGN_MESSAGE: \p pk must contain a * key pair. The output \p attributes will contain a * key pair type, and the usage policy will allow * #PSA_KEY_USAGE_VERIFY_MESSAGE as well as * #PSA_KEY_USAGE_SIGN_MESSAGE. * - #PSA_KEY_USAGE_VERIFY_HASH: The output * \p attributes will contain a public key type. * - #PSA_KEY_USAGE_VERIFY_MESSAGE: The output * \p attributes will contain a public key type. * \param[out] attributes * On success, valid attributes to import the key into PSA. * - The lifetime and key identifier are unchanged. If the * attribute structure was initialized or reset before * calling this function, this will result in a volatile * key. Call psa_set_key_identifier() before or after this * function if you wish to create a persistent key. Call * psa_set_key_lifetime() before or after this function if * you wish to import the key in a secure element. * - The key type and bit-size are determined by the contents * of the PK context. If the PK context contains a key * pair, the key type can be either a key pair type or * the corresponding public key type, depending on * \p usage. If the PK context contains a public key, * the key type is a public key type. * - The key's policy is determined by the key type and * the \p usage parameter. The usage always allows * \p usage, exporting and copying the key, and * possibly other permissions as documented for the * \p usage parameter. * The permitted algorithm policy is determined as follows * based on the #mbedtls_pk_type_t type of \p pk, * the chosen \p usage and other factors: * - #MBEDTLS_PK_RSA whose underlying * #mbedtls_rsa_context has the padding mode * #MBEDTLS_RSA_PKCS_V15: * #PSA_ALG_RSA_PKCS1V15_SIGN(#PSA_ALG_ANY_HASH) * if \p usage is SIGN/VERIFY, and * #PSA_ALG_RSA_PKCS1V15_CRYPT * if \p usage is ENCRYPT/DECRYPT. * - #MBEDTLS_PK_RSA whose underlying * #mbedtls_rsa_context has the padding mode * #MBEDTLS_RSA_PKCS_V21 and the digest type * corresponding to the PSA algorithm \c hash: * #PSA_ALG_RSA_PSS_ANY_SALT(#PSA_ALG_ANY_HASH) * if \p usage is SIGN/VERIFY, and * #PSA_ALG_RSA_OAEP(\c hash) * if \p usage is ENCRYPT/DECRYPT. * - #MBEDTLS_PK_RSA_ALT: not supported. * - #MBEDTLS_PK_ECDSA or #MBEDTLS_PK_ECKEY * if \p usage is SIGN/VERIFY: * #PSA_ALG_DETERMINISTIC_ECDSA(#PSA_ALG_ANY_HASH) * if #MBEDTLS_ECDSA_DETERMINISTIC is enabled, * otherwise #PSA_ALG_ECDSA(#PSA_ALG_ANY_HASH). * - #MBEDTLS_PK_ECKEY_DH or #MBEDTLS_PK_ECKEY * if \p usage is DERIVE: * #PSA_ALG_ECDH. * - #MBEDTLS_PK_OPAQUE: same as the primary algorithm * set for the underlying PSA key, except that * sign/decrypt flags are removed if the type is * set to a public key type. * The underlying key must allow \p usage. * Note that the enrollment algorithm set with * psa_set_key_enrollment_algorithm() is not copied. * * \return 0 on success. * #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain * a key of the type identified in \p attributes. * Another error code on other failures. */ int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk, psa_key_usage_t usage, psa_key_attributes_t *attributes); /** * \brief Import a key into the PSA key store. * * This function is equivalent to calling psa_import_key() * with the key material from \p pk. * * The typical way to use this function is: * -# Call mbedtls_pk_get_psa_attributes() to obtain * attributes for the given key. * -# If desired, modify the attributes, for example: * - To create a persistent key, call * psa_set_key_identifier() and optionally * psa_set_key_lifetime(). * - To import only the public part of a key pair: * * psa_set_key_type(&attributes, * PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( * psa_get_key_type(&attributes))); * - Restrict the key usage if desired. * -# Call mbedtls_pk_import_into_psa(). * * \note This function does not support RSA-alt contexts * (set up with mbedtls_pk_setup_rsa_alt()). * * \param[in] pk The PK context to use. It must have been set up. * It can either contain a key pair or just a public key. * \param[in] attributes * The attributes to use for the new key. They must be * compatible with \p pk. In particular, the key type * must match the content of \p pk. * If \p pk contains a key pair, the key type in * attributes can be either the key pair type or the * corresponding public key type (to import only the * public part). * \param[out] key_id * On success, the identifier of the newly created key. * On error, this is #MBEDTLS_SVC_KEY_ID_INIT. * * \return 0 on success. * #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain * a key of the type identified in \p attributes. * Another error code on other failures. */ int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id); /** * \brief Create a PK context starting from a key stored in PSA. * This key: * - must be exportable and * - must be an RSA or EC key pair or public key (FFDH is not supported in PK). * * The resulting PK object will be a transparent type: * - #MBEDTLS_PK_RSA for RSA keys or * - #MBEDTLS_PK_ECKEY for EC keys. * * Once this functions returns the PK object will be completely * independent from the original PSA key that it was generated * from. * Calling mbedtls_pk_sign(), mbedtls_pk_verify(), * mbedtls_pk_encrypt(), mbedtls_pk_decrypt() on the resulting * PK context will perform the corresponding algorithm for that * PK context type. * * For ECDSA, the choice of deterministic vs randomized will * be based on the compile-time setting #MBEDTLS_ECDSA_DETERMINISTIC. * * For an RSA key, the output PK context will allow both * encrypt/decrypt and sign/verify regardless of the original * key's policy. * The original key's policy determines the output key's padding * mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS, * otherwise PKCS1 v1.5 is set. * * \param key_id The key identifier of the key stored in PSA. * \param pk The PK context that will be filled. It must be initialized, * but not set up. * * \return 0 on success. * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input * parameters are not correct. */ int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk); /** * \brief Create a PK context for the public key of a PSA key. * * The key must be an RSA or ECC key. It can be either a * public key or a key pair, and only the public key is copied. * The resulting PK object will be a transparent type: * - #MBEDTLS_PK_RSA for RSA keys or * - #MBEDTLS_PK_ECKEY for EC keys. * * Once this functions returns the PK object will be completely * independent from the original PSA key that it was generated * from. * Calling mbedtls_pk_verify() or * mbedtls_pk_encrypt() on the resulting * PK context will perform the corresponding algorithm for that * PK context type. * * For an RSA key, the output PK context will allow both * encrypt and verify regardless of the original key's policy. * The original key's policy determines the output key's padding * mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS, * otherwise PKCS1 v1.5 is set. * * \param key_id The key identifier of the key stored in PSA. * \param pk The PK context that will be filled. It must be initialized, * but not set up. * * \return 0 on success. * \return MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input * parameters are not correct. */ int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk); #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /** * \brief Verify signature (including padding if relevant). * * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used. * This can be #MBEDTLS_MD_NONE if the signature algorithm * does not rely on a hash algorithm (non-deterministic * ECDSA, RSA PKCS#1 v1.5). * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then * \p hash is the DigestInfo structure used by RFC 8017 * §9.2 steps 3–6. If \p md_alg is a valid hash * algorithm then \p hash is the digest itself, and this * function calculates the DigestInfo encoding internally. * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Signature to verify * \param sig_len Signature length * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or PSS (accepting any salt length), * depending on the padding mode in the underlying RSA context. * For a pk object constructed by parsing, this is PKCS#1 v1.5 * by default. Use mbedtls_pk_verify_ext() to explicitly select * a different algorithm. * * \return 0 on success (signature is valid), * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid * signature in \p sig but its length is less than \p sig_len, * or a specific error code. */ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** * \brief Restartable version of \c mbedtls_pk_verify() * * \note Performs the same job as \c mbedtls_pk_verify(), but can * return early and restart according to the limit set with * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC * operations. For RSA, same as \c mbedtls_pk_verify(). * * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) * \param sig Signature to verify * \param sig_len Signature length * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_verify(), or * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, mbedtls_pk_restart_ctx *rs_ctx); /** * \brief Verify signature, with options. * (Includes verification of the padding depending on type.) * * \param type Signature type (inc. possible padding type) to verify * \param options Pointer to type-specific options, or NULL * \param ctx The PK context to use. It must have been set up. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length or 0 (see notes) * \param sig Signature to verify * \param sig_len Signature length * * \return 0 on success (signature is valid), * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be * used for this type of signatures, * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid * signature in \p sig but its length is less than \p sig_len, * or a specific error code. * * \note If hash_len is 0, then the length associated with md_alg * is used instead, or an error returned if it is invalid. * * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 * * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point * to a mbedtls_pk_rsassa_pss_options structure, * otherwise it must be NULL. Note that if * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not * verified as PSA_ALG_RSA_PSS_ANY_SALT is used. */ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** * \brief Make signature, including padding if relevant. * * \param ctx The PK context to use. It must have been set up * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or PSS (using the largest possible salt * length up to the hash length), depending on the padding mode * in the underlying RSA context. For a pk object constructed * by parsing, this is PKCS#1 v1.5 by default. Use * mbedtls_pk_verify_ext() to explicitly select a different * algorithm. * * \return 0 on success, or a specific error code. * * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. */ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Make signature given a signature type. * * \param pk_type Signature type. * \param ctx The PK context to use. It must have been set up * with a private key. * \param md_alg Hash algorithm used (see notes) * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \return 0 on success, or a specific error code. * * \note When \p pk_type is #MBEDTLS_PK_RSASSA_PSS, * see #PSA_ALG_RSA_PSS for a description of PSS options used. * * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. * */ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Restartable version of \c mbedtls_pk_sign() * * \note Performs the same job as \c mbedtls_pk_sign(), but can * return early and restart according to the limit set with * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC * operations. For RSA, same as \c mbedtls_pk_sign(). * * \param ctx The PK context to use. It must have been set up * with a private key. * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) * \param hash Hash of the message to sign * \param hash_len Hash length * \param sig Place to write the signature. * It must have enough room for the signature. * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. * You may use a smaller buffer if it is large enough * given the key type. * \param sig_size The size of the \p sig buffer in bytes. * \param sig_len On successful return, * the number of bytes written to \p sig. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_sign(). * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx); /** * \brief Decrypt message (including padding if relevant). * * \param ctx The PK context to use. It must have been set up * with a private key. * \param input Input to decrypt * \param ilen Input size * \param output Decrypted output * \param olen Decrypted message length * \param osize Size of the output buffer * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or OAEP, depending on the padding mode in * the underlying RSA context. For a pk object constructed by * parsing, this is PKCS#1 v1.5 by default. * * \return 0 on success, or a specific error code. */ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Encrypt message (including padding if relevant). * * \param ctx The PK context to use. It must have been set up. * \param input Message to encrypt * \param ilen Message size * \param output Encrypted output * \param olen Encrypted output length * \param osize Size of the output buffer * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \note For keys of type #MBEDTLS_PK_RSA, the signature algorithm is * either PKCS#1 v1.5 or OAEP, depending on the padding mode in * the underlying RSA context. For a pk object constructed by * parsing, this is PKCS#1 v1.5 by default. * * \note \p f_rng is used for padding generation. * * \return 0 on success, or a specific error code. */ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Check if a public-private pair of keys matches. * * \param pub Context holding a public key. * \param prv Context holding a private (and public) key. * \param f_rng RNG function, must not be \c NULL. * \param p_rng RNG parameter * * \return \c 0 on success (keys were checked and match each other). * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not * be checked - in that case they may or may not match. * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. * \return Another non-zero value if the keys do not match. */ int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Export debug information * * \param ctx The PK context to use. It must have been initialized. * \param items Place to write debug items * * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA */ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items); /** * \brief Access the type name * * \param ctx The PK context to use. It must have been initialized. * * \return Type name on success, or "invalid PK" */ const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); /** * \brief Get the key type * * \param ctx The PK context to use. It must have been initialized. * * \return Type on success. * \return #MBEDTLS_PK_NONE for a context that has not been set up. */ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); #if defined(MBEDTLS_RSA_C) /** * Quick access to an RSA context inside a PK context. * * \warning This function can only be used when the type of the context, as * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. * Ensuring that is the caller's responsibility. * Alternatively, you can check whether this function returns NULL. * * \return The internal RSA context held by the PK context, or NULL. */ static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_RSA: return (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) /** * Quick access to an EC context inside a PK context. * * \warning This function can only be used when the type of the context, as * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. * Ensuring that is the caller's responsibility. * Alternatively, you can check whether this function returns NULL. * * \return The internal EC context held by the PK context, or NULL. */ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_PK_PARSE_C) /** \ingroup pk_module */ /** * \brief Parse a private key in PEM or DER format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param key Input buffer to parse. * The buffer must contain the input exactly, with no * extra trailing material. For PEM, the buffer must * contain a null-terminated string. * \param keylen Size of \b key in bytes. * For PEM data, this includes the terminating null byte, * so \p keylen must be equal to `strlen(key) + 1`. * \param pwd Optional password for decryption. * Pass \c NULL if expecting a non-encrypted key. * Pass a string of \p pwdlen bytes if expecting an encrypted * key; a non-encrypted key will also be accepted. * The empty password is not supported. * \param pwdlen Size of the password in bytes. * Ignored if \p pwd is \c NULL. * \param f_rng RNG function, must not be \c NULL. Used for blinding. * \param p_rng RNG parameter * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \ingroup pk_module */ /** * \brief Parse a public key in PEM or DER format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param key Input buffer to parse. * The buffer must contain the input exactly, with no * extra trailing material. For PEM, the buffer must * contain a null-terminated string. * \param keylen Size of \b key in bytes. * For PEM data, this includes the terminating null byte, * so \p keylen must be equal to `strlen(key) + 1`. * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for * limitations. * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen); #if defined(MBEDTLS_FS_IO) /** \ingroup pk_module */ /** * \brief Load and parse a private key * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param path filename to read the private key from * \param password Optional password to decrypt the file. * Pass \c NULL if expecting a non-encrypted key. * Pass a null-terminated string if expecting an encrypted * key; a non-encrypted key will also be accepted. * The empty password is not supported. * \param f_rng RNG function, must not be \c NULL. Used for blinding. * \param p_rng RNG parameter * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * specific key type, check the result with mbedtls_pk_can_do(). * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, const char *password, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** \ingroup pk_module */ /** * \brief Load and parse a public key * * \param ctx The PK context to fill. It must have been initialized * but not set up. * \param path filename to read the public key from * * \note On entry, ctx must be empty, either freshly initialised * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If * you need a specific key type, check the result with * mbedtls_pk_can_do(). * * \note The key is also checked for correctness. * * \return 0 if successful, or a specific PK or PEM error code */ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) /** * \brief Write a private key to a PKCS#1 or SEC1 DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx PK context which must contain a valid private key. * \param buf buffer to write to * \param size size of the buffer * * \return length of data written if successful, or a specific * error code */ int mbedtls_pk_write_key_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a public key to a SubjectPublicKeyInfo DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx PK context which must contain a valid public or private key. * \param buf buffer to write to * \param size size of the buffer * * \return length of data written if successful, or a specific * error code */ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a public key to a PEM string * * \param ctx PK context which must contain a valid public or private key. * \param buf Buffer to write to. The output includes a * terminating null byte. * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); /** * \brief Write a private key to a PKCS#1 or SEC1 PEM string * * \param ctx PK context which must contain a valid private key. * \param buf Buffer to write to. The output includes a * terminating null byte. * \param size Size of the buffer in bytes. * * \return 0 if successful, or a specific error code */ int mbedtls_pk_write_key_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ /* * WARNING: Low-level functions. You probably do not want to use these unless * you are certain you do ;) */ #if defined(MBEDTLS_PK_PARSE_C) /** * \brief Parse a SubjectPublicKeyInfo DER structure * * \param p the position in the ASN.1 data * \param end end of the buffer * \param pk The PK context to fill. It must have been initialized * but not set up. * * \return 0 if successful, or a specific PK error code */ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, mbedtls_pk_context *pk); #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) /** * \brief Write a subjectPublicKey to ASN.1 data * Note: function works backwards in data buffer * * \param p reference to current position pointer * \param start start of the buffer (for bounds-checking) * \param key PK context which must contain a valid public or private key. * * \return the length written or a negative error code */ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key); #endif /* MBEDTLS_PK_WRITE_C */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_PK_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h000066400000000000000000000210061464416617300242200ustar00rootroot00000000000000/** * \file pkcs12.h * * \brief PKCS#12 Personal Information Exchange Syntax */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PKCS12_H #define MBEDTLS_PKCS12_H #include "mbedtls/build_info.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/asn1.h" #include /** Bad input parameters to function. */ #define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /** Feature not available, e.g. unsupported encryption scheme. */ #define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /** PBE ASN.1 data not as expected. */ #define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 #define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ #define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ #define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ #define MBEDTLS_PKCS12_PBE_DECRYPT MBEDTLS_DECRYPT #define MBEDTLS_PKCS12_PBE_ENCRYPT MBEDTLS_ENCRYPT #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS12 Password Based function (encryption / decryption) * for cipher-based and mbedtls_md-based PBE's * * \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must * be enabled at compile time. * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use mbedtls_pkcs12_pbe_ext() instead. * * \warning When decrypting: * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile * time, this function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile * time, this function does not validate the CBC padding. * * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure * \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or * #MBEDTLS_PKCS12_PBE_DECRYPT * \param cipher_type the cipher used * \param md_type the mbedtls_md used * \param pwd Latin1-encoded password used. This may only be \c NULL when * \p pwdlen is 0. No null terminator should be used. * \param pwdlen length of the password (may be 0) * \param data the input data * \param len data length * \param output Output buffer. * On success, it contains the encrypted or decrypted data, * possibly followed by the CBC padding. * On failure, the content is indeterminate. * For decryption, there must be enough room for \p len * bytes. * For encryption, there must be enough room for * \p len + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * * \return 0 if successful, or a MBEDTLS_ERR_XXX code */ int MBEDTLS_DEPRECATED mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) /** * \brief PKCS12 Password Based function (encryption / decryption) * for cipher-based and mbedtls_md-based PBE's * * * \warning When decrypting: * - This function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure * \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or * #MBEDTLS_PKCS12_PBE_DECRYPT * \param cipher_type the cipher used * \param md_type the mbedtls_md used * \param pwd Latin1-encoded password used. This may only be \c NULL when * \p pwdlen is 0. No null terminator should be used. * \param pwdlen length of the password (may be 0) * \param data the input data * \param len data length * \param output Output buffer. * On success, it contains the encrypted or decrypted data, * possibly followed by the CBC padding. * On failure, the content is indeterminate. * For decryption, there must be enough room for \p len * bytes. * For encryption, there must be enough room for * \p len + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * \param output_size size of output buffer. * This must be big enough to accommodate for output plus * padding data. * \param output_len On success, length of actual data written to the output buffer. * * \return 0 if successful, or a MBEDTLS_ERR_XXX code */ int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output, size_t output_size, size_t *output_len); #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ /** * \brief The PKCS#12 derivation function uses a password and a salt * to produce pseudo-random bits for a particular "purpose". * * Depending on the given id, this function can produce an * encryption/decryption key, an initialization vector or an * integrity key. * * \param data buffer to store the derived data in * \param datalen length of buffer to fill * \param pwd The password to use. For compliance with PKCS#12 §B.1, this * should be a BMPString, i.e. a Unicode string where each * character is encoded as 2 bytes in big-endian order, with * no byte order mark and with a null terminator (i.e. the * last two bytes should be 0x00 0x00). * \param pwdlen length of the password (may be 0). * \param salt Salt buffer to use. This may only be \c NULL when * \p saltlen is 0. * \param saltlen length of the salt (may be zero) * \param mbedtls_md mbedtls_md type to use during the derivation * \param id id that describes the purpose (can be * #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or * #MBEDTLS_PKCS12_DERIVE_MAC_KEY) * \param iterations number of iterations * * \return 0 if successful, or a MD, BIGNUM type error. */ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, const unsigned char *pwd, size_t pwdlen, const unsigned char *salt, size_t saltlen, mbedtls_md_type_t mbedtls_md, int id, int iterations); #ifdef __cplusplus } #endif #endif /* pkcs12.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h000066400000000000000000000201631464416617300241450ustar00rootroot00000000000000/** * \file pkcs5.h * * \brief PKCS#5 functions * * \author Mathias Olsson */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PKCS5_H #define MBEDTLS_PKCS5_H #include "mbedtls/build_info.h" #include "mbedtls/platform_util.h" #include "mbedtls/asn1.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include #include /** Bad input parameters to function. */ #define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /** Unexpected ASN.1 data. */ #define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /** Requested encryption or digest alg not available. */ #define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /** Given private key password does not allow for correct decryption. */ #define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 #define MBEDTLS_PKCS5_DECRYPT MBEDTLS_DECRYPT #define MBEDTLS_PKCS5_ENCRYPT MBEDTLS_ENCRYPT #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS#5 PBES2 function * * \note When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must * be enabled at compile time. * * \deprecated This function is deprecated and will be removed in a * future version of the library. * Please use mbedtls_pkcs5_pbes2_ext() instead. * * \warning When decrypting: * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile * time, this function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile * time, this function does not validate the CBC padding. * * \param pbe_params the ASN.1 algorithm parameters * \param mode either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT * \param pwd password to use when generating key * \param pwdlen length of password * \param data data to process * \param datalen length of data * \param output Output buffer. * On success, it contains the encrypted or decrypted data, * possibly followed by the CBC padding. * On failure, the content is indeterminate. * For decryption, there must be enough room for \p datalen * bytes. * For encryption, there must be enough room for * \p datalen + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) /** * \brief PKCS#5 PBES2 function * * \warning When decrypting: * - This function validates the CBC padding and returns * #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is * invalid. Note that this can help active adversaries * attempting to brute-forcing the password. Note also that * there is no guarantee that an invalid password will be * detected (the chances of a valid padding with a random * password are about 1/255). * * \param pbe_params the ASN.1 algorithm parameters * \param mode either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT * \param pwd password to use when generating key * \param pwdlen length of password * \param data data to process * \param datalen length of data * \param output Output buffer. * On success, it contains the decrypted data. * On failure, the content is indetermidate. * For decryption, there must be enough room for \p datalen * bytes. * For encryption, there must be enough room for * \p datalen + 1 bytes, rounded up to the block size of * the block cipher identified by \p pbe_params. * \param output_size size of output buffer. * This must be big enough to accommodate for output plus * padding data. * \param output_len On success, length of actual data written to the output buffer. * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if parsing or decryption fails. */ int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output, size_t output_size, size_t *output_len); #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C*/ /** * \brief PKCS#5 PBKDF2 using HMAC without using the HMAC context * * \param md_type Hash algorithm used * \param password Password to use when generating key * \param plen Length of password * \param salt Salt to use when generating key * \param slen Length of salt * \param iteration_count Iteration count * \param key_length Length of generated key in bytes * \param output Generated key. Must be at least as big as key_length * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_type, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output); #if defined(MBEDTLS_MD_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief PKCS#5 PBKDF2 using HMAC * * \deprecated Superseded by mbedtls_pkcs5_pbkdf2_hmac_ext(). * * \param ctx Generic HMAC context * \param password Password to use when generating key * \param plen Length of password * \param salt Salt to use when generating key * \param slen Length of salt * \param iteration_count Iteration count * \param key_length Length of generated key in bytes * \param output Generated key. Must be at least as big as key_length * * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. */ int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output); #endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_pkcs5_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* pkcs5.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h000066400000000000000000000226211464416617300241500ustar00rootroot00000000000000/** * \file pkcs7.h * * \brief PKCS #7 generic defines and structures * https://tools.ietf.org/html/rfc2315 */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /** * Note: For the time being, this implementation of the PKCS #7 cryptographic * message syntax is a partial implementation of RFC 2315. * Differences include: * - The RFC specifies 6 different content types. The only type currently * supported in Mbed TLS is the signed-data content type. * - The only supported PKCS #7 Signed Data syntax version is version 1 * - The RFC specifies support for BER. This implementation is limited to * DER only. * - The RFC specifies that multiple digest algorithms can be specified * in the Signed Data type. Only one digest algorithm is supported in Mbed TLS. * - The RFC specifies the Signed Data type can contain multiple X.509 or PKCS #6 extended * certificates. In Mbed TLS, this list can only contain 0 or 1 certificates * and they must be in X.509 format. * - The RFC specifies the Signed Data type can contain * certificate-revocation lists (CRLs). This implementation has no support * for CRLs so it is assumed to be an empty list. * - The RFC allows for SignerInfo structure to optionally contain * unauthenticatedAttributes and authenticatedAttributes. In Mbed TLS it is * assumed these fields are empty. * - The RFC allows for the signed Data type to contain contentInfo. This * implementation assumes the type is DATA and the content is empty. */ #ifndef MBEDTLS_PKCS7_H #define MBEDTLS_PKCS7_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/x509_crt.h" /** * \name PKCS #7 Module Error codes * \{ */ #define MBEDTLS_ERR_PKCS7_INVALID_FORMAT -0x5300 /**< The format is invalid, e.g. different type expected. */ #define MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE -0x5380 /**< Unavailable feature, e.g. anything other than signed data. */ #define MBEDTLS_ERR_PKCS7_INVALID_VERSION -0x5400 /**< The PKCS #7 version element is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO -0x5480 /**< The PKCS #7 content info is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_ALG -0x5500 /**< The algorithm tag or value is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_CERT -0x5580 /**< The certificate tag or value is invalid or cannot be parsed. */ #define MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE -0x5600 /**< Error parsing the signature */ #define MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO -0x5680 /**< Error parsing the signer's info */ #define MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA -0x5700 /**< Input invalid. */ #define MBEDTLS_ERR_PKCS7_ALLOC_FAILED -0x5780 /**< Allocation of memory failed. */ #define MBEDTLS_ERR_PKCS7_VERIFY_FAIL -0x5800 /**< Verification Failed */ #define MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID -0x5880 /**< The PKCS #7 date issued/expired dates are invalid */ /* \} name */ /** * \name PKCS #7 Supported Version * \{ */ #define MBEDTLS_PKCS7_SUPPORTED_VERSION 0x01 /* \} name */ #ifdef __cplusplus extern "C" { #endif /** * Type-length-value structure that allows for ASN.1 using DER. */ typedef mbedtls_asn1_buf mbedtls_pkcs7_buf; /** * Container for ASN.1 named information objects. * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). */ typedef mbedtls_asn1_named_data mbedtls_pkcs7_name; /** * Container for a sequence of ASN.1 items */ typedef mbedtls_asn1_sequence mbedtls_pkcs7_sequence; /** * PKCS #7 types */ typedef enum { MBEDTLS_PKCS7_NONE=0, MBEDTLS_PKCS7_DATA, MBEDTLS_PKCS7_SIGNED_DATA, MBEDTLS_PKCS7_ENVELOPED_DATA, MBEDTLS_PKCS7_SIGNED_AND_ENVELOPED_DATA, MBEDTLS_PKCS7_DIGESTED_DATA, MBEDTLS_PKCS7_ENCRYPTED_DATA, } mbedtls_pkcs7_type; /** * Structure holding PKCS #7 signer info */ typedef struct mbedtls_pkcs7_signer_info { int MBEDTLS_PRIVATE(version); mbedtls_x509_buf MBEDTLS_PRIVATE(serial); mbedtls_x509_name MBEDTLS_PRIVATE(issuer); mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw); mbedtls_x509_buf MBEDTLS_PRIVATE(alg_identifier); mbedtls_x509_buf MBEDTLS_PRIVATE(sig_alg_identifier); mbedtls_x509_buf MBEDTLS_PRIVATE(sig); struct mbedtls_pkcs7_signer_info *MBEDTLS_PRIVATE(next); } mbedtls_pkcs7_signer_info; /** * Structure holding the signed data section */ typedef struct mbedtls_pkcs7_signed_data { int MBEDTLS_PRIVATE(version); mbedtls_pkcs7_buf MBEDTLS_PRIVATE(digest_alg_identifiers); int MBEDTLS_PRIVATE(no_of_certs); mbedtls_x509_crt MBEDTLS_PRIVATE(certs); int MBEDTLS_PRIVATE(no_of_crls); mbedtls_x509_crl MBEDTLS_PRIVATE(crl); int MBEDTLS_PRIVATE(no_of_signers); mbedtls_pkcs7_signer_info MBEDTLS_PRIVATE(signers); } mbedtls_pkcs7_signed_data; /** * Structure holding PKCS #7 structure, only signed data for now */ typedef struct mbedtls_pkcs7 { mbedtls_pkcs7_buf MBEDTLS_PRIVATE(raw); mbedtls_pkcs7_signed_data MBEDTLS_PRIVATE(signed_data); } mbedtls_pkcs7; /** * \brief Initialize mbedtls_pkcs7 structure. * * \param pkcs7 mbedtls_pkcs7 structure. */ void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7); /** * \brief Parse a single DER formatted PKCS #7 detached signature. * * \param pkcs7 The mbedtls_pkcs7 structure to be filled by the parser. * \param buf The buffer holding only the DER encoded PKCS #7 content. * \param buflen The size in bytes of \p buf. The size must be exactly the * length of the DER encoded PKCS #7 content. * * \note This function makes an internal copy of the PKCS #7 buffer * \p buf. In particular, \p buf may be destroyed or reused * after this call returns. * \note Signatures with internal data are not supported. * * \return The \c mbedtls_pkcs7_type of \p buf, if successful. * \return A negative error code on failure. */ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, const size_t buflen); /** * \brief Verification of PKCS #7 signature against a caller-supplied * certificate. * * For each signer in the PKCS structure, this function computes * a signature over the supplied data, using the supplied * certificate and the same digest algorithm as specified by the * signer. It then compares this signature against the * signer's signature; verification succeeds if any comparison * matches. * * This function does not use the certificates held within the * PKCS #7 structure itself, and does not check that the * certificate is signed by a trusted certification authority. * * \param pkcs7 mbedtls_pkcs7 structure containing signature. * \param cert Certificate containing key to verify signature. * \param data Plain data on which signature has to be verified. * \param datalen Length of the data. * * \note This function internally calculates the hash on the supplied * plain data for signature verification. * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *data, size_t datalen); /** * \brief Verification of PKCS #7 signature against a caller-supplied * certificate. * * For each signer in the PKCS structure, this function * validates a signature over the supplied hash, using the * supplied certificate and the same digest algorithm as * specified by the signer. Verification succeeds if any * signature is good. * * This function does not use the certificates held within the * PKCS #7 structure itself, and does not check that the * certificate is signed by a trusted certification authority. * * \param pkcs7 PKCS #7 structure containing signature. * \param cert Certificate containing key to verify signature. * \param hash Hash of the plain data on which signature has to be verified. * \param hashlen Length of the hash. * * \note This function is different from mbedtls_pkcs7_signed_data_verify() * in that it is directly passed the hash of the data. * * \return 0 if the signature verifies, or a negative error code on failure. */ int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *hash, size_t hashlen); /** * \brief Unallocate all PKCS #7 data and zeroize the memory. * It doesn't free \p pkcs7 itself. This should be done by the caller. * * \param pkcs7 mbedtls_pkcs7 structure to free. */ void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7); #ifdef __cplusplus } #endif #endif /* pkcs7.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/platform.h000066400000000000000000000417541464416617300247550ustar00rootroot00000000000000/** * \file platform.h * * \brief This file contains the definitions and functions of the * Mbed TLS platform abstraction layer. * * The platform abstraction layer removes the need for the library * to directly link to standard C library functions or operating * system services, making the library easier to port and embed. * Application developers and users of the library can provide their own * implementations of these functions, or implementations specific to * their platform, which can be statically linked to the library or * dynamically configured at runtime. * * When all compilation options related to platform abstraction are * disabled, this header just defines `mbedtls_xxx` function names * as aliases to the standard `xxx` function. * * Most modules in the library and example programs are expected to * include this header. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_H #define MBEDTLS_PLATFORM_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #ifdef __cplusplus extern "C" { #endif /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ /* The older Microsoft Windows common runtime provides non-conforming * implementations of some standard library functions, including snprintf * and vsnprintf. This affects MSVC and MinGW builds. */ #if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) #define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF #define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF #endif #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) #include #include #if defined(MBEDTLS_HAVE_TIME) #include #endif #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) #define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ #else #define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ #endif #endif #if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) #define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ #else #define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ #endif #endif #if !defined(MBEDTLS_PLATFORM_STD_PRINTF) #define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) #define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) #define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_FREE) #define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_SETBUF) #define MBEDTLS_PLATFORM_STD_SETBUF setbuf /**< The default \c setbuf function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT) #define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_TIME) #define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) #define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ #endif #if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) #define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ #endif #if defined(MBEDTLS_FS_IO) #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) #define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read #endif #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write #endif #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) #define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" #endif #endif /* MBEDTLS_FS_IO */ #else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ #if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) #include MBEDTLS_PLATFORM_STD_MEM_HDR #endif #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ /* Enable certain documented defines only when generating doxygen to avoid * an "unrecognized define" error. */ #if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC) #define MBEDTLS_PLATFORM_STD_CALLOC #endif #if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE) #define MBEDTLS_PLATFORM_STD_FREE #endif /** \} name SECTION: Module settings */ /* * The function pointers for calloc and free. * Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE * in mbedtls_config.h for more information about behaviour and requirements. */ #if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ defined(MBEDTLS_PLATFORM_CALLOC_MACRO) #undef mbedtls_free #undef mbedtls_calloc #define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO #define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO #else /* For size_t */ #include extern void *mbedtls_calloc(size_t n, size_t size); extern void mbedtls_free(void *ptr); /** * \brief This function dynamically sets the memory-management * functions used by the library, during runtime. * * \param calloc_func The \c calloc function implementation. * \param free_func The \c free function implementation. * * \return \c 0. */ int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), void (*free_func)(void *)); #endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ #else /* !MBEDTLS_PLATFORM_MEMORY */ #undef mbedtls_free #undef mbedtls_calloc #define mbedtls_free free #define mbedtls_calloc calloc #endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ /* * The function pointers for fprintf */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) /* We need FILE * */ #include extern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...); /** * \brief This function dynamically configures the fprintf * function that is called when the * mbedtls_fprintf() function is invoked by the library. * * \param fprintf_func The \c fprintf function implementation. * * \return \c 0. */ int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *stream, const char *, ...)); #else #undef mbedtls_fprintf #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) #define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO #else #define mbedtls_fprintf fprintf #endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ /* * The function pointers for printf */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) extern int (*mbedtls_printf)(const char *format, ...); /** * \brief This function dynamically configures the snprintf * function that is called when the mbedtls_snprintf() * function is invoked by the library. * * \param printf_func The \c printf function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)); #else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ #undef mbedtls_printf #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) #define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO #else #define mbedtls_printf printf #endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ /* * The function pointers for snprintf * * The snprintf implementation should conform to C99: * - it *must* always correctly zero-terminate the buffer * (except when n == 0, then it must leave the buffer untouched) * - however it is acceptable to return -1 instead of the required length when * the destination buffer is too short. */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) /* For Windows (inc. MSYS2), we provide our own fixed implementation */ int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...); #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) extern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...); /** * \brief This function allows configuring a custom * \c snprintf function pointer. * * \param snprintf_func The \c snprintf function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, const char *format, ...)); #else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #undef mbedtls_snprintf #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) #define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO #else #define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF #endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ /* * The function pointers for vsnprintf * * The vsnprintf implementation should conform to C99: * - it *must* always correctly zero-terminate the buffer * (except when n == 0, then it must leave the buffer untouched) * - however it is acceptable to return -1 instead of the required length when * the destination buffer is too short. */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) #include /* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg); #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) #include extern int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, va_list arg); /** * \brief Set your own snprintf function pointer * * \param vsnprintf_func The \c vsnprintf function implementation * * \return \c 0 */ int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, const char *format, va_list arg)); #else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #undef mbedtls_vsnprintf #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) #define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO #else #define mbedtls_vsnprintf vsnprintf #endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ /* * The function pointers for setbuf */ #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) #include /** * \brief Function pointer to call for `setbuf()` functionality * (changing the internal buffering on stdio calls). * * \note The library calls this function to disable * buffering when reading or writing sensitive data, * to avoid having extra copies of sensitive data * remaining in stdio buffers after the file is * closed. If this is not a concern, for example if * your platform's stdio doesn't have any buffering, * you can set mbedtls_setbuf to a function that * does nothing. * * The library always calls this function with * `buf` equal to `NULL`. */ extern void (*mbedtls_setbuf)(FILE *stream, char *buf); /** * \brief Dynamically configure the function that is called * when the mbedtls_setbuf() function is called by the * library. * * \param setbuf_func The \c setbuf function implementation * * \return \c 0 */ int mbedtls_platform_set_setbuf(void (*setbuf_func)( FILE *stream, char *buf)); #else #undef mbedtls_setbuf #if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) /** * \brief Macro defining the function for the library to * call for `setbuf` functionality (changing the * internal buffering on stdio calls). * * \note See extra comments on the mbedtls_setbuf() function * pointer above. * * \return \c 0 on success, negative on error. */ #define mbedtls_setbuf MBEDTLS_PLATFORM_SETBUF_MACRO #else #define mbedtls_setbuf setbuf #endif /* MBEDTLS_PLATFORM_SETBUF_MACRO */ #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ /* * The function pointers for exit */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) extern void (*mbedtls_exit)(int status); /** * \brief This function dynamically configures the exit * function that is called when the mbedtls_exit() * function is invoked by the library. * * \param exit_func The \c exit function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_exit(void (*exit_func)(int status)); #else #undef mbedtls_exit #if defined(MBEDTLS_PLATFORM_EXIT_MACRO) #define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO #else #define mbedtls_exit exit #endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ /* * The default exit values */ #if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) #define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS #else #define MBEDTLS_EXIT_SUCCESS 0 #endif #if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) #define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE #else #define MBEDTLS_EXIT_FAILURE 1 #endif /* * The function pointers for reading from and writing a seed file to * Non-Volatile storage (NV) in a platform-independent way * * Only enabled when the NV seed entropy source is enabled */ #if defined(MBEDTLS_ENTROPY_NV_SEED) #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) /* Internal standard platform definitions */ int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len); int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len); #endif #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) extern int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len); extern int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len); /** * \brief This function allows configuring custom seed file writing and * reading functions. * * \param nv_seed_read_func The seed reading function implementation. * \param nv_seed_write_func The seed writing function implementation. * * \return \c 0 on success. */ int mbedtls_platform_set_nv_seed( int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len), int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len) ); #else #undef mbedtls_nv_seed_read #undef mbedtls_nv_seed_write #if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) #define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO #define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO #else #define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read #define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write #endif #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) /** * \brief The platform context structure. * * \note This structure may be used to assist platform-specific * setup or teardown operations. */ typedef struct mbedtls_platform_context { char MBEDTLS_PRIVATE(dummy); /**< A placeholder member, as empty structs are not portable. */ } mbedtls_platform_context; #else #include "platform_alt.h" #endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ /** * \brief This function performs any platform-specific initialization * operations. * * \note This function should be called before any other library functions. * * Its implementation is platform-specific, and unless * platform-specific code is provided, it does nothing. * * \note The usage and necessity of this function is dependent on the platform. * * \param ctx The platform context. * * \return \c 0 on success. */ int mbedtls_platform_setup(mbedtls_platform_context *ctx); /** * \brief This function performs any platform teardown operations. * * \note This function should be called after every other Mbed TLS module * has been correctly freed using the appropriate free function. * * Its implementation is platform-specific, and unless * platform-specific code is provided, it does nothing. * * \note The usage and necessity of this function is dependent on the platform. * * \param ctx The platform context. * */ void mbedtls_platform_teardown(mbedtls_platform_context *ctx); #ifdef __cplusplus } #endif #endif /* platform.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h000066400000000000000000000036221464416617300257630ustar00rootroot00000000000000/** * \file platform_time.h * * \brief Mbed TLS Platform time abstraction */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_TIME_H #define MBEDTLS_PLATFORM_TIME_H #include "mbedtls/build_info.h" #ifdef __cplusplus extern "C" { #endif /* * The time_t datatype */ #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; #else /* For time_t */ #include typedef time_t mbedtls_time_t; #endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ #if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) typedef MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO mbedtls_ms_time_t; #else #include #include typedef int64_t mbedtls_ms_time_t; #endif /* MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO */ /** * \brief Get time in milliseconds. * * \return Monotonically-increasing current time in milliseconds. * * \note Define MBEDTLS_PLATFORM_MS_TIME_ALT to be able to provide an * alternative implementation * * \warning This function returns a monotonically-increasing time value from a * start time that will differ from platform to platform, and possibly * from run to run of the process. * */ mbedtls_ms_time_t mbedtls_ms_time(void); /* * The function pointers for time */ #if defined(MBEDTLS_PLATFORM_TIME_ALT) extern mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *time); /** * \brief Set your own time function pointer * * \param time_func the time function implementation * * \return 0 */ int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *time)); #else #if defined(MBEDTLS_PLATFORM_TIME_MACRO) #define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO #else #define mbedtls_time time #endif /* MBEDTLS_PLATFORM_TIME_MACRO */ #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #ifdef __cplusplus } #endif #endif /* platform_time.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h000066400000000000000000000175021464416617300260040ustar00rootroot00000000000000/** * \file platform_util.h * * \brief Common and shared functions used by multiple modules in the Mbed TLS * library. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PLATFORM_UTIL_H #define MBEDTLS_PLATFORM_UTIL_H #include "mbedtls/build_info.h" #include #if defined(MBEDTLS_HAVE_TIME_DATE) #include "mbedtls/platform_time.h" #include #endif /* MBEDTLS_HAVE_TIME_DATE */ #ifdef __cplusplus extern "C" { #endif /* Internal helper macros for deprecating API constants. */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) #define MBEDTLS_DEPRECATED __attribute__((deprecated)) MBEDTLS_DEPRECATED typedef char const *mbedtls_deprecated_string_constant_t; #define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) \ ((mbedtls_deprecated_string_constant_t) (VAL)) MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; #define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) \ ((mbedtls_deprecated_numeric_constant_t) (VAL)) #else /* MBEDTLS_DEPRECATED_WARNING */ #define MBEDTLS_DEPRECATED #define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) VAL #define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) VAL #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* MBEDTLS_DEPRECATED_REMOVED */ /* Implementation of the check-return facility. * See the user documentation in mbedtls_config.h. * * Do not use this macro directly to annotate function: instead, * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL * depending on how important it is to check the return value. */ #if !defined(MBEDTLS_CHECK_RETURN) #if defined(__GNUC__) #define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) #elif defined(_MSC_VER) && _MSC_VER >= 1700 #include #define MBEDTLS_CHECK_RETURN _Check_return_ #else #define MBEDTLS_CHECK_RETURN #endif #endif /** Critical-failure function * * This macro appearing at the beginning of the declaration of a function * indicates that its return value should be checked in all applications. * Omitting the check is very likely to indicate a bug in the application * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN * is implemented for the compiler in use. * * \note The use of this macro is a work in progress. * This macro may be added to more functions in the future. * Such an extension is not considered an API break, provided that * there are near-unavoidable circumstances under which the function * can fail. For example, signature/MAC/AEAD verification functions, * and functions that require a random generator, are considered * return-check-critical. */ #define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN /** Ordinary-failure function * * This macro appearing at the beginning of the declaration of a function * indicates that its return value should be generally be checked in portable * applications. Omitting the check will result in a compile-time warning if * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration. * * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value * of a function that is annotated with #MBEDTLS_CHECK_RETURN. * * \note The use of this macro is a work in progress. * This macro will be added to more functions in the future. * Eventually this should appear before most functions returning * an error code (as \c int in the \c mbedtls_xxx API or * as ::psa_status_t in the \c psa_xxx API). */ #if defined(MBEDTLS_CHECK_RETURN_WARNING) #define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN #else #define MBEDTLS_CHECK_RETURN_TYPICAL #endif /** Benign-failure function * * This macro appearing at the beginning of the declaration of a function * indicates that it is rarely useful to check its return value. * * This macro has an empty expansion. It exists for documentation purposes: * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function * has been analyzed for return-check usefulness, whereas the lack of * an annotation indicates that the function has not been analyzed and its * return-check usefulness is unknown. */ #define MBEDTLS_CHECK_RETURN_OPTIONAL /** \def MBEDTLS_IGNORE_RETURN * * Call this macro with one argument, a function call, to suppress a warning * from #MBEDTLS_CHECK_RETURN due to that function call. */ #if !defined(MBEDTLS_IGNORE_RETURN) /* GCC doesn't silence the warning with just (void)(result). * (void)!(result) is known to work up at least up to GCC 10, as well * as with Clang and MSVC. * * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 */ #define MBEDTLS_IGNORE_RETURN(result) ((void) !(result)) #endif /* If the following macro is defined, the library is being built by the test * framework, and the framework is going to provide a replacement * mbedtls_platform_zeroize() using a preprocessor macro, so the function * declaration should be omitted. */ #if !defined(MBEDTLS_TEST_DEFINES_ZEROIZE) //no-check-names /** * \brief Securely zeroize a buffer * * The function is meant to wipe the data contained in a buffer so * that it can no longer be recovered even if the program memory * is later compromised. Call this function on sensitive data * stored on the stack before returning from a function, and on * sensitive data stored on the heap before freeing the heap * object. * * It is extremely difficult to guarantee that calls to * mbedtls_platform_zeroize() are not removed by aggressive * compiler optimizations in a portable way. For this reason, Mbed * TLS provides the configuration option * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure * mbedtls_platform_zeroize() to use a suitable implementation for * their platform and needs * * \param buf Buffer to be zeroized * \param len Length of the buffer in bytes * */ void mbedtls_platform_zeroize(void *buf, size_t len); #endif #if defined(MBEDTLS_HAVE_TIME_DATE) /** * \brief Platform-specific implementation of gmtime_r() * * The function is a thread-safe abstraction that behaves * similarly to the gmtime_r() function from Unix/POSIX. * * Mbed TLS will try to identify the underlying platform and * make use of an appropriate underlying implementation (e.g. * gmtime_r() for POSIX and gmtime_s() for Windows). If this is * not possible, then gmtime() will be used. In this case, calls * from the library to gmtime() will be guarded by the mutex * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is * enabled. It is recommended that calls from outside the library * are also guarded by this mutex. * * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will * unconditionally use the alternative implementation for * mbedtls_platform_gmtime_r() supplied by the user at compile time. * * \param tt Pointer to an object containing time (in seconds) since the * epoch to be converted * \param tm_buf Pointer to an object where the results will be stored * * \return Pointer to an object of type struct tm on success, otherwise * NULL */ struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, struct tm *tm_buf); #endif /* MBEDTLS_HAVE_TIME_DATE */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_PLATFORM_UTIL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h000066400000000000000000000136061464416617300244200ustar00rootroot00000000000000/** * \file poly1305.h * * \brief This file contains Poly1305 definitions and functions. * * Poly1305 is a one-time message authenticator that can be used to * authenticate messages. Poly1305-AES was created by Daniel * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic * Poly1305 algorithm (not tied to AES) was also standardized in RFC * 7539. * * \author Daniel King */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_POLY1305_H #define MBEDTLS_POLY1305_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** Invalid input parameter(s). */ #define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_POLY1305_ALT) typedef struct mbedtls_poly1305_context { uint32_t MBEDTLS_PRIVATE(r)[4]; /** The value for 'r' (low 128 bits of the key). */ uint32_t MBEDTLS_PRIVATE(s)[4]; /** The value for 's' (high 128 bits of the key). */ uint32_t MBEDTLS_PRIVATE(acc)[5]; /** The accumulator number. */ uint8_t MBEDTLS_PRIVATE(queue)[16]; /** The current partial block of data. */ size_t MBEDTLS_PRIVATE(queue_len); /** The number of bytes stored in 'queue'. */ } mbedtls_poly1305_context; #else /* MBEDTLS_POLY1305_ALT */ #include "poly1305_alt.h" #endif /* MBEDTLS_POLY1305_ALT */ /** * \brief This function initializes the specified Poly1305 context. * * It must be the first API called before using * the context. * * It is usually followed by a call to * \c mbedtls_poly1305_starts(), then one or more calls to * \c mbedtls_poly1305_update(), then one call to * \c mbedtls_poly1305_finish(), then finally * \c mbedtls_poly1305_free(). * * \param ctx The Poly1305 context to initialize. This must * not be \c NULL. */ void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx); /** * \brief This function releases and clears the specified * Poly1305 context. * * \param ctx The Poly1305 context to clear. This may be \c NULL, in which * case this function is a no-op. If it is not \c NULL, it must * point to an initialized Poly1305 context. */ void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx); /** * \brief This function sets the one-time authentication key. * * \warning The key must be unique and unpredictable for each * invocation of Poly1305. * * \param ctx The Poly1305 context to which the key should be bound. * This must be initialized. * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx, const unsigned char key[32]); /** * \brief This functions feeds an input buffer into an ongoing * Poly1305 computation. * * It is called between \c mbedtls_cipher_poly1305_starts() and * \c mbedtls_cipher_poly1305_finish(). * It can be called repeatedly to process a stream of data. * * \param ctx The Poly1305 context to use for the Poly1305 operation. * This must be initialized and bound to a key. * \param ilen The length of the input data in Bytes. * Any value is accepted. * \param input The buffer holding the input data. * This pointer can be \c NULL if `ilen == 0`. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function generates the Poly1305 Message * Authentication Code (MAC). * * \param ctx The Poly1305 context to use for the Poly1305 operation. * This must be initialized and bound to a key. * \param mac The buffer to where the MAC is written. This must * be a writable buffer of length \c 16 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx, unsigned char mac[16]); /** * \brief This function calculates the Poly1305 MAC of the input * buffer with the provided key. * * \warning The key must be unique and unpredictable for each * invocation of Poly1305. * * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. * \param ilen The length of the input data in Bytes. * Any value is accepted. * \param input The buffer holding the input data. * This pointer can be \c NULL if `ilen == 0`. * \param mac The buffer to where the MAC is written. This must be * a writable buffer of length \c 16 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_poly1305_mac(const unsigned char key[32], const unsigned char *input, size_t ilen, unsigned char mac[16]); #if defined(MBEDTLS_SELF_TEST) /** * \brief The Poly1305 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_poly1305_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_POLY1305_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h000066400000000000000000000006631464416617300261160ustar00rootroot00000000000000/** * \file private_access.h * * \brief Macro wrapper for struct's members. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PRIVATE_ACCESS_H #define MBEDTLS_PRIVATE_ACCESS_H #ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS #define MBEDTLS_PRIVATE(member) private_##member #else #define MBEDTLS_PRIVATE(member) member #endif #endif /* MBEDTLS_PRIVATE_ACCESS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h000066400000000000000000000177411464416617300247500ustar00rootroot00000000000000/** * \file psa_util.h * * \brief Utility functions for the use of the PSA Crypto library. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_UTIL_H #define MBEDTLS_PSA_UTIL_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "psa/crypto.h" /* ASN1 defines used in the ECDSA conversion functions. * Note: intentionally not adding MBEDTLS_ASN1_[PARSE|WRITE]_C guards here * otherwise error codes would be unknown in test_suite_psa_crypto_util.data.*/ #include #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /** The random generator function for the PSA subsystem. * * This function is suitable as the `f_rng` random generator function * parameter of many `mbedtls_xxx` functions. * * The implementation of this function depends on the configuration of the * library. * * \note This function may only be used if the PSA crypto subsystem is active. * This means that you must call psa_crypto_init() before any call to * this function, and you must not call this function after calling * mbedtls_psa_crypto_free(). * * \param p_rng This parameter is only kept for backward compatibility * reasons with legacy `f_rng` functions and it's ignored. * Set to #MBEDTLS_PSA_RANDOM_STATE or NULL. * \param output The buffer to fill. It must have room for * \c output_size bytes. * \param output_size The number of bytes to write to \p output. * This function may fail if \p output_size is too * large. It is guaranteed to accept any output size * requested by Mbed TLS library functions. The * maximum request size depends on the library * configuration. * * \return \c 0 on success. * \return An `MBEDTLS_ERR_ENTROPY_xxx`, * `MBEDTLS_ERR_PLATFORM_xxx, * `MBEDTLS_ERR_CTR_DRBG_xxx` or * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error. */ int mbedtls_psa_get_random(void *p_rng, unsigned char *output, size_t output_size); /** The random generator state for the PSA subsystem. * * This macro always expands to NULL because the `p_rng` parameter is unused * in mbedtls_psa_get_random(), but it's kept for interface's backward * compatibility. */ #define MBEDTLS_PSA_RANDOM_STATE NULL /** \defgroup psa_tls_helpers TLS helper functions * @{ */ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #include /** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. * * \param grpid An Mbed TLS elliptic curve identifier * (`MBEDTLS_ECP_DP_xxx`). * \param[out] bits On success the bit size of the curve; 0 on failure. * * \return If the curve is supported in the PSA API, this function * returns the proper PSA curve identifier * (`PSA_ECC_FAMILY_xxx`). This holds even if the curve is * not supported by the ECP module. * \return \c 0 if the curve is not supported in the PSA API. */ psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, size_t *bits); /** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. * * \param family A PSA elliptic curve family identifier * (`PSA_ECC_FAMILY_xxx`). * \param bits The bit-length of a private key on \p curve. * * \return If the curve is supported in the PSA API, this function * returns the corresponding Mbed TLS elliptic curve * identifier (`MBEDTLS_ECP_DP_xxx`). * \return #MBEDTLS_ECP_DP_NONE if the combination of \c curve * and \p bits is not supported. */ mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, size_t bits); #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ /** * \brief This function returns the PSA algorithm identifier * associated with the given digest type. * * \param md_type The type of digest to search for. Must not be NONE. * * \warning If \p md_type is \c MBEDTLS_MD_NONE, this function will * not return \c PSA_ALG_NONE, but an invalid algorithm. * * \warning This function does not check if the algorithm is * supported, it always returns the corresponding identifier. * * \return The PSA algorithm identifier associated with \p md_type, * regardless of whether it is supported or not. */ static inline psa_algorithm_t mbedtls_md_psa_alg_from_type(mbedtls_md_type_t md_type) { return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) md_type; } /** * \brief This function returns the given digest type * associated with the PSA algorithm identifier. * * \param psa_alg The PSA algorithm identifier to search for. * * \warning This function does not check if the algorithm is * supported, it always returns the corresponding identifier. * * \return The MD type associated with \p psa_alg, * regardless of whether it is supported or not. */ static inline mbedtls_md_type_t mbedtls_md_type_from_psa_alg(psa_algorithm_t psa_alg) { return (mbedtls_md_type_t) (psa_alg & PSA_ALG_HASH_MASK); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** Convert an ECDSA signature from raw format to DER ASN.1 format. * * \param bits Size of each coordinate in bits. * \param raw Buffer that contains the signature in raw format. * \param raw_len Length of \p raw in bytes. This must be * PSA_BITS_TO_BYTES(bits) bytes. * \param[out] der Buffer that will be filled with the converted DER * output. It can overlap with raw buffer. * \param der_size Size of \p der in bytes. It is enough if \p der_size * is at least the size of the actual output. (The size * of the output can vary depending on the presence of * leading zeros in the data.) You can use * #MBEDTLS_ECDSA_MAX_SIG_LEN(\p bits) to determine a * size that is large enough for all signatures for a * given value of \p bits. * \param[out] der_len On success it contains the amount of valid data * (in bytes) written to \p der. It's undefined * in case of failure. */ int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, unsigned char *der, size_t der_size, size_t *der_len); /** Convert an ECDSA signature from DER ASN.1 format to raw format. * * \param bits Size of each coordinate in bits. * \param der Buffer that contains the signature in DER format. * \param der_len Size of \p der in bytes. * \param[out] raw Buffer that will be filled with the converted raw * signature. It can overlap with der buffer. * \param raw_size Size of \p raw in bytes. Must be at least * 2 * PSA_BITS_TO_BYTES(bits) bytes. * \param[out] raw_len On success it is updated with the amount of valid * data (in bytes) written to \p raw. It's undefined * in case of failure. */ int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, unsigned char *raw, size_t raw_size, size_t *raw_len); #endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ /**@}*/ #endif /* MBEDTLS_PSA_UTIL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h000066400000000000000000000065611464416617300246350ustar00rootroot00000000000000/** * \file ripemd160.h * * \brief RIPE MD-160 message digest */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RIPEMD160_H #define MBEDTLS_RIPEMD160_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_RIPEMD160_ALT) // Regular implementation // /** * \brief RIPEMD-160 context structure */ typedef struct mbedtls_ripemd160_context { uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< intermediate digest state */ unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ } mbedtls_ripemd160_context; #else /* MBEDTLS_RIPEMD160_ALT */ #include "ripemd160_alt.h" #endif /* MBEDTLS_RIPEMD160_ALT */ /** * \brief Initialize RIPEMD-160 context * * \param ctx RIPEMD-160 context to be initialized */ void mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx); /** * \brief Clear RIPEMD-160 context * * \param ctx RIPEMD-160 context to be cleared */ void mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx); /** * \brief Clone (the state of) a RIPEMD-160 context * * \param dst The destination context * \param src The context to be cloned */ void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst, const mbedtls_ripemd160_context *src); /** * \brief RIPEMD-160 context setup * * \param ctx context to be initialized * * \return 0 if successful */ int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx); /** * \brief RIPEMD-160 process buffer * * \param ctx RIPEMD-160 context * \param input buffer holding the data * \param ilen length of the input data * * \return 0 if successful */ int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, const unsigned char *input, size_t ilen); /** * \brief RIPEMD-160 final digest * * \param ctx RIPEMD-160 context * \param output RIPEMD-160 checksum result * * \return 0 if successful */ int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, unsigned char output[20]); /** * \brief RIPEMD-160 process data block (internal use only) * * \param ctx RIPEMD-160 context * \param data buffer holding one block of data * * \return 0 if successful */ int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx, const unsigned char data[64]); /** * \brief Output = RIPEMD-160( input buffer ) * * \param input buffer holding the data * \param ilen length of the input data * \param output RIPEMD-160 checksum result * * \return 0 if successful */ int mbedtls_ripemd160(const unsigned char *input, size_t ilen, unsigned char output[20]); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine * * \return 0 if successful, or 1 if the test failed */ int mbedtls_ripemd160_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_ripemd160.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h000066400000000000000000001570751464416617300237220ustar00rootroot00000000000000/** * \file rsa.h * * \brief This file provides an API for the RSA public-key cryptosystem. * * The RSA public-key cryptosystem is defined in Public-Key * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption * and Public-Key Cryptography Standards (PKCS) #1 v2.1: * RSA Cryptography Specifications. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_H #define MBEDTLS_RSA_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #include "mbedtls/md.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /* * RSA Error codes */ /** Bad input parameters to function. */ #define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /** Input data contains invalid padding and is rejected. */ #define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /** Something failed during generation of a key. */ #define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /** Key failed to pass the validity check of the library. */ #define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /** The public key operation failed. */ #define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /** The private key operation failed. */ #define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /** The PKCS#1 verification failed. */ #define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /** The output buffer for decryption is not large enough. */ #define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /** The random generator failed to generate non-zeros. */ #define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /* * RSA constants */ #define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ #define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ #define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ #define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ #define MBEDTLS_RSA_SALT_LEN_ANY -1 /* * The above constants may be used even if the RSA module is compile out, * eg for alternative (PKCS#11) RSA implementations in the PK layers. */ #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_RSA_ALT) // Regular implementation // #if !defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS) #define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024 #elif MBEDTLS_RSA_GEN_KEY_MIN_BITS < 128 #error "MBEDTLS_RSA_GEN_KEY_MIN_BITS must be at least 128 bits" #endif /** * \brief The RSA context structure. */ typedef struct mbedtls_rsa_context { int MBEDTLS_PRIVATE(ver); /*!< Reserved for internal purposes. * Do not set this field in application * code. Its meaning might change without * notice. */ size_t MBEDTLS_PRIVATE(len); /*!< The size of \p N in Bytes. */ mbedtls_mpi MBEDTLS_PRIVATE(N); /*!< The public modulus. */ mbedtls_mpi MBEDTLS_PRIVATE(E); /*!< The public exponent. */ mbedtls_mpi MBEDTLS_PRIVATE(D); /*!< The private exponent. */ mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The first prime factor. */ mbedtls_mpi MBEDTLS_PRIVATE(Q); /*!< The second prime factor. */ mbedtls_mpi MBEDTLS_PRIVATE(DP); /*!< D % (P - 1). */ mbedtls_mpi MBEDTLS_PRIVATE(DQ); /*!< D % (Q - 1). */ mbedtls_mpi MBEDTLS_PRIVATE(QP); /*!< 1 / (Q % P). */ mbedtls_mpi MBEDTLS_PRIVATE(RN); /*!< cached R^2 mod N. */ mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< cached R^2 mod P. */ mbedtls_mpi MBEDTLS_PRIVATE(RQ); /*!< cached R^2 mod Q. */ mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The cached blinding value. */ mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The cached un-blinding value. */ int MBEDTLS_PRIVATE(padding); /*!< Selects padding mode: #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ int MBEDTLS_PRIVATE(hash_id); /*!< Hash identifier of mbedtls_md_type_t type, as specified in md.h for use in the MGF mask generating function used in the EME-OAEP and EMSA-PSS encodings. */ #if defined(MBEDTLS_THREADING_C) /* Invariant: the mutex is initialized iff ver != 0. */ mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< Thread-safety mutex. */ #endif } mbedtls_rsa_context; #else /* MBEDTLS_RSA_ALT */ #include "rsa_alt.h" #endif /* MBEDTLS_RSA_ALT */ /** * \brief This function initializes an RSA context. * * \note This function initializes the padding and the hash * identifier to respectively #MBEDTLS_RSA_PKCS_V15 and * #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more * information about those parameters. * * \param ctx The RSA context to initialize. This must not be \c NULL. */ void mbedtls_rsa_init(mbedtls_rsa_context *ctx); /** * \brief This function sets padding for an already initialized RSA * context. * * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP * encryption scheme and the RSASSA-PSS signature scheme. * * \note The \p hash_id parameter is ignored when using * #MBEDTLS_RSA_PKCS_V15 padding. * * \note The choice of padding mode is strictly enforced for private * key operations, since there might be security concerns in * mixing padding modes. For public key operations it is * a default value, which can be overridden by calling specific * \c mbedtls_rsa_rsaes_xxx or \c mbedtls_rsa_rsassa_xxx * functions. * * \note The hash selected in \p hash_id is always used for OEAP * encryption. For PSS signatures, it is always used for * making signatures, but can be overridden for verifying them. * If set to #MBEDTLS_MD_NONE, it is always overridden. * * \param ctx The initialized RSA context to be configured. * \param padding The padding mode to use. This must be either * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. * \param hash_id The hash identifier for PSS or OAEP, if \p padding is * #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this * function but may be not suitable for some operations. * Ignored if \p padding is #MBEDTLS_RSA_PKCS_V15. * * \return \c 0 on success. * \return #MBEDTLS_ERR_RSA_INVALID_PADDING failure: * \p padding or \p hash_id is invalid. */ int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, mbedtls_md_type_t hash_id); /** * \brief This function retrieves padding mode of initialized * RSA context. * * \param ctx The initialized RSA context. * * \return RSA padding mode. * */ int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx); /** * \brief This function retrieves hash identifier of mbedtls_md_type_t * type. * * \param ctx The initialized RSA context. * * \return Hash identifier of mbedtls_md_type_t type. * */ int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx); /** * \brief This function imports a set of core parameters into an * RSA context. * * \note This function can be called multiple times for successive * imports, if the parameters are not simultaneously present. * * Any sequence of calls to this function should be followed * by a call to mbedtls_rsa_complete(), which checks and * completes the provided information to a ready-for-use * public or private RSA key. * * \note See mbedtls_rsa_complete() for more information on which * parameters are necessary to set up a private or public * RSA key. * * \note The imported parameters are copied and need not be preserved * for the lifetime of the RSA context being set up. * * \param ctx The initialized RSA context to store the parameters in. * \param N The RSA modulus. This may be \c NULL. * \param P The first prime factor of \p N. This may be \c NULL. * \param Q The second prime factor of \p N. This may be \c NULL. * \param D The private exponent. This may be \c NULL. * \param E The public exponent. This may be \c NULL. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_rsa_import(mbedtls_rsa_context *ctx, const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E); /** * \brief This function imports core RSA parameters, in raw big-endian * binary format, into an RSA context. * * \note This function can be called multiple times for successive * imports, if the parameters are not simultaneously present. * * Any sequence of calls to this function should be followed * by a call to mbedtls_rsa_complete(), which checks and * completes the provided information to a ready-for-use * public or private RSA key. * * \note See mbedtls_rsa_complete() for more information on which * parameters are necessary to set up a private or public * RSA key. * * \note The imported parameters are copied and need not be preserved * for the lifetime of the RSA context being set up. * * \param ctx The initialized RSA context to store the parameters in. * \param N The RSA modulus. This may be \c NULL. * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. * \param P The first prime factor of \p N. This may be \c NULL. * \param P_len The Byte length of \p P; it is ignored if \p P == NULL. * \param Q The second prime factor of \p N. This may be \c NULL. * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. * \param D The private exponent. This may be \c NULL. * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. * \param E The public exponent. This may be \c NULL. * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx, unsigned char const *N, size_t N_len, unsigned char const *P, size_t P_len, unsigned char const *Q, size_t Q_len, unsigned char const *D, size_t D_len, unsigned char const *E, size_t E_len); /** * \brief This function completes an RSA context from * a set of imported core parameters. * * To setup an RSA public key, precisely \c N and \c E * must have been imported. * * To setup an RSA private key, sufficient information must * be present for the other parameters to be derivable. * * The default implementation supports the following: *
  • Derive \c P, \c Q from \c N, \c D, \c E.
  • *
  • Derive \c N, \c D from \c P, \c Q, \c E.
* Alternative implementations need not support these. * * If this function runs successfully, it guarantees that * the RSA context can be used for RSA operations without * the risk of failure or crash. * * \warning This function need not perform consistency checks * for the imported parameters. In particular, parameters that * are not needed by the implementation might be silently * discarded and left unchecked. To check the consistency * of the key material, see mbedtls_rsa_check_privkey(). * * \param ctx The initialized RSA context holding imported parameters. * * \return \c 0 on success. * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations * failed. * */ int mbedtls_rsa_complete(mbedtls_rsa_context *ctx); /** * \brief This function exports the core parameters of an RSA key. * * If this function runs successfully, the non-NULL buffers * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully * written, with additional unused space filled leading by * zero Bytes. * * Possible reasons for returning * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    *
  • An alternative RSA implementation is in use, which * stores the key externally, and either cannot or should * not export it into RAM.
  • *
  • A SW or HW implementation might not support a certain * deduction. For example, \p P, \p Q from \p N, \p D, * and \p E if the former are not part of the * implementation.
* * If the function fails due to an unsupported operation, * the RSA context stays intact and remains usable. * * \param ctx The initialized RSA context. * \param N The MPI to hold the RSA modulus. * This may be \c NULL if this field need not be exported. * \param P The MPI to hold the first prime factor of \p N. * This may be \c NULL if this field need not be exported. * \param Q The MPI to hold the second prime factor of \p N. * This may be \c NULL if this field need not be exported. * \param D The MPI to hold the private exponent. * This may be \c NULL if this field need not be exported. * \param E The MPI to hold the public exponent. * This may be \c NULL if this field need not be exported. * * \return \c 0 on success. * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the * requested parameters cannot be done due to missing * functionality or because of security policies. * \return A non-zero return code on any other failure. * */ int mbedtls_rsa_export(const mbedtls_rsa_context *ctx, mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, mbedtls_mpi *D, mbedtls_mpi *E); /** * \brief This function exports core parameters of an RSA key * in raw big-endian binary format. * * If this function runs successfully, the non-NULL buffers * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully * written, with additional unused space filled leading by * zero Bytes. * * Possible reasons for returning * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    *
  • An alternative RSA implementation is in use, which * stores the key externally, and either cannot or should * not export it into RAM.
  • *
  • A SW or HW implementation might not support a certain * deduction. For example, \p P, \p Q from \p N, \p D, * and \p E if the former are not part of the * implementation.
* If the function fails due to an unsupported operation, * the RSA context stays intact and remains usable. * * \note The length parameters are ignored if the corresponding * buffer pointers are NULL. * * \param ctx The initialized RSA context. * \param N The Byte array to store the RSA modulus, * or \c NULL if this field need not be exported. * \param N_len The size of the buffer for the modulus. * \param P The Byte array to hold the first prime factor of \p N, * or \c NULL if this field need not be exported. * \param P_len The size of the buffer for the first prime factor. * \param Q The Byte array to hold the second prime factor of \p N, * or \c NULL if this field need not be exported. * \param Q_len The size of the buffer for the second prime factor. * \param D The Byte array to hold the private exponent, * or \c NULL if this field need not be exported. * \param D_len The size of the buffer for the private exponent. * \param E The Byte array to hold the public exponent, * or \c NULL if this field need not be exported. * \param E_len The size of the buffer for the public exponent. * * \return \c 0 on success. * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the * requested parameters cannot be done due to missing * functionality or because of security policies. * \return A non-zero return code on any other failure. */ int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx, unsigned char *N, size_t N_len, unsigned char *P, size_t P_len, unsigned char *Q, size_t Q_len, unsigned char *D, size_t D_len, unsigned char *E, size_t E_len); /** * \brief This function exports CRT parameters of a private RSA key. * * \note Alternative RSA implementations not using CRT-parameters * internally can implement this function based on * mbedtls_rsa_deduce_opt(). * * \param ctx The initialized RSA context. * \param DP The MPI to hold \c D modulo `P-1`, * or \c NULL if it need not be exported. * \param DQ The MPI to hold \c D modulo `Q-1`, * or \c NULL if it need not be exported. * \param QP The MPI to hold modular inverse of \c Q modulo \c P, * or \c NULL if it need not be exported. * * \return \c 0 on success. * \return A non-zero error code on failure. * */ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP); /** * \brief This function retrieves the length of the RSA modulus in bits. * * \param ctx The initialized RSA context. * * \return The length of the RSA modulus in bits. * */ size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx); /** * \brief This function retrieves the length of RSA modulus in Bytes. * * \param ctx The initialized RSA context. * * \return The length of the RSA modulus in Bytes. * */ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx); /** * \brief This function generates an RSA keypair. * * \note mbedtls_rsa_init() must be called before this function, * to set up the RSA context. * * \param ctx The initialized RSA context used to hold the key. * \param f_rng The RNG function to be used for key generation. * This is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. * This may be \c NULL if \p f_rng doesn't need a context. * \param nbits The size of the public key in bits. * \param exponent The public exponent to use. For example, \c 65537. * This must be odd and greater than \c 1. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent); /** * \brief This function checks if a context contains at least an RSA * public key. * * If the function runs successfully, it is guaranteed that * enough information is present to perform an RSA public key * operation using mbedtls_rsa_public(). * * \param ctx The initialized RSA context to check. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx); /** * \brief This function checks if a context contains an RSA private key * and perform basic consistency checks. * * \note The consistency checks performed by this function not only * ensure that mbedtls_rsa_private() can be called successfully * on the given context, but that the various parameters are * mutually consistent with high probability, in the sense that * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. * * \warning This function should catch accidental misconfigurations * like swapping of parameters, but it cannot establish full * trust in neither the quality nor the consistency of the key * material that was used to setup the given RSA context: *
  • Consistency: Imported parameters that are irrelevant * for the implementation might be silently dropped. If dropped, * the current function does not have access to them, * and therefore cannot check them. See mbedtls_rsa_complete(). * If you want to check the consistency of the entire * content of a PKCS1-encoded RSA private key, for example, you * should use mbedtls_rsa_validate_params() before setting * up the RSA context. * Additionally, if the implementation performs empirical checks, * these checks substantiate but do not guarantee consistency.
  • *
  • Quality: This function is not expected to perform * extended quality assessments like checking that the prime * factors are safe. Additionally, it is the responsibility of the * user to ensure the trustworthiness of the source of his RSA * parameters, which goes beyond what is effectively checkable * by the library.
* * \param ctx The initialized RSA context to check. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx); /** * \brief This function checks a public-private RSA key pair. * * It checks each of the contexts, and makes sure they match. * * \param pub The initialized RSA context holding the public key. * \param prv The initialized RSA context holding the private key. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv); /** * \brief This function performs an RSA public key operation. * * \param ctx The initialized RSA context to use. * \param input The input buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \note This function does not handle message padding. * * \note Make sure to set \p input[0] = 0 or ensure that * input is smaller than \c N. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output); /** * \brief This function performs an RSA private key operation. * * \note Blinding is used if and only if a PRNG is provided. * * \note If blinding is used, both the base of exponentiation * and the exponent are blinded, providing protection * against some side-channel attacks. * * \warning It is deprecated and a security risk to not provide * a PRNG here and thereby prevent the use of blinding. * Future versions of the library may enforce the presence * of a PRNG. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function, used for blinding. It is mandatory. * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context. * \param input The input buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output); /** * \brief This function adds the message padding, then performs an RSA * operation. * * It is the generic wrapper for performing a PKCS#1 encryption * operation. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG to use. It is used for padding generation * and it is mandatory. * \param p_rng The RNG context to be passed to \p f_rng. May be * \c NULL if \p f_rng doesn't need a context argument. * \param ilen The length of the plaintext in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if * `ilen == 0`. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output); /** * \brief This function performs a PKCS#1 v1.5 encryption operation * (RSAES-PKCS1-v1_5-ENCRYPT). * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. It is mandatory and used for * padding generation. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * \param ilen The length of the plaintext in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if * `ilen == 0`. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output); /** * \brief This function performs a PKCS#1 v2.1 OAEP encryption * operation (RSAES-OAEP-ENCRYPT). * * \note The output buffer must be as large as the size * of ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. This is needed for padding * generation and is mandatory. * \param p_rng The RNG context to be passed to \p f_rng. This may * be \c NULL if \p f_rng doesn't need a context argument. * \param label The buffer holding the custom label to use. * This must be a readable buffer of length \p label_len * Bytes. It may be \c NULL if \p label_len is \c 0. * \param label_len The length of the label in Bytes. * \param ilen The length of the plaintext buffer \p input in Bytes. * \param input The input data to encrypt. This must be a readable * buffer of size \p ilen Bytes. It may be \c NULL if * `ilen == 0`. * \param output The output buffer. This must be a writable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output); /** * \brief This function performs an RSA operation, then removes the * message padding. * * It is the generic wrapper for performing a PKCS#1 decryption * operation. * * \warning When \p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15, * mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an * inherently dangerous function (CWE-242). * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N (for example, * 128 Bytes if RSA-1024 is used) to be able to hold an * arbitrary decrypted message. If it is not large enough to * hold the decryption of the particular ciphertext provided, * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The buffer used to hold the plaintext. This must * be a writable buffer of length \p output_max_len Bytes. * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); /** * \brief This function performs a PKCS#1 v1.5 decryption * operation (RSAES-PKCS1-v1_5-DECRYPT). * * \warning This is an inherently dangerous function (CWE-242). Unless * it is used in a side channel free and safe way (eg. * implementing the TLS protocol as per 7.4.7.1 of RFC 5246), * the calling code is vulnerable. * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for example, * 128 Bytes if RSA-1024 is used, to be able to hold an * arbitrary decrypted message. If it is not large enough to * hold the decryption of the particular ciphertext provided, * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The buffer used to hold the plaintext. This must * be a writable buffer of length \p output_max_len Bytes. * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. * */ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); /** * \brief This function performs a PKCS#1 v2.1 OAEP decryption * operation (RSAES-OAEP-DECRYPT). * * \note The output buffer length \c output_max_len should be * as large as the size \p ctx->len of \p ctx->N, for * example, 128 Bytes if RSA-1024 is used, to be able to * hold an arbitrary decrypted message. If it is not * large enough to hold the decryption of the particular * ciphertext provided, the function returns * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory. * \param p_rng The RNG context to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context. * \param label The buffer holding the custom label to use. * This must be a readable buffer of length \p label_len * Bytes. It may be \c NULL if \p label_len is \c 0. * \param label_len The length of the label in Bytes. * \param olen The address at which to store the length of * the plaintext. This must not be \c NULL. * \param input The ciphertext buffer. This must be a readable buffer * of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * \param output The buffer used to hold the plaintext. This must * be a writable buffer of length \p output_max_len Bytes. * \param output_max_len The length in Bytes of the output buffer \p output. * * \return \c 0 on success. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len); /** * \brief This function performs a private RSA operation to sign * a message digest using PKCS#1. * * It is the generic wrapper for performing a PKCS#1 * signature. * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_sign() for details on * \p md_alg and \p hash_id. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function to use. This is mandatory and * must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); /** * \brief This function performs a PKCS#1 v1.5 signature * operation (RSASSA-PKCS1-v1_5-SIGN). * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. This is used for blinding and is * mandatory; see mbedtls_rsa_private() for more. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); #if defined(MBEDTLS_PKCS1_V21) /** * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * * \note The \c hash_id set in \p ctx by calling * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography * Specifications. * * \note This function enforces that the provided salt length complies * with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1 * step 3. The constraint is that the hash length plus the salt * length plus 2 bytes must be at most the key length. If this * constraint is not met, this function returns * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. It is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param saltlen The length of the salt that should be used. * If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use * the largest possible salt length up to the hash length, * which is the largest permitted by some standards including * FIPS 186-4 §5.5. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig); /** * \brief This function performs a PKCS#1 v2.1 PSS signature * operation (RSASSA-PSS-SIGN). * * \note The \c hash_id set in \p ctx by calling * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography * Specifications. * * \note This function always uses the maximum possible salt size, * up to the length of the payload hash. This choice of salt * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 * v2.2) §9.1.1 step 3. Furthermore this function enforces a * minimum salt size which is the hash size minus 2 bytes. If * this minimum size is too large given the key size (the salt * size, plus the hash size, plus 2 bytes must be no more than * the key size in bytes), this function returns * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. * * \param ctx The initialized RSA context to use. * \param f_rng The RNG function. It is mandatory and must not be \c NULL. * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL * if \p f_rng doesn't need a context argument. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer to hold the signature. This must be a writable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. A buffer length of * #MBEDTLS_MPI_MAX_SIZE is always safe. * * \return \c 0 if the signing operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); #endif /* MBEDTLS_PKCS1_V21 */ /** * \brief This function performs a public RSA operation and checks * the message digest. * * This is the generic wrapper for performing a PKCS#1 * verification. * * \note For PKCS#1 v2.1 encoding, see comments on * mbedtls_rsa_rsassa_pss_verify() about \c md_alg and * \c hash_id. * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig); /** * \brief This function performs a PKCS#1 v1.5 verification * operation (RSASSA-PKCS1-v1_5-VERIFY). * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig); /** * \brief This function performs a PKCS#1 v2.1 PSS verification * operation (RSASSA-PSS-VERIFY). * * \note The \c hash_id set in \p ctx by calling * mbedtls_rsa_set_padding() selects the hash used for the * encoding operation and for the mask generation function * (MGF1). For more details on the encoding operation and the * mask generation function, consult RFC-3447: Public-Key * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography * Specifications. If the \c hash_id set in \p ctx by * mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \p md_alg * parameter is used. * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig); /** * \brief This function performs a PKCS#1 v2.1 PSS verification * operation (RSASSA-PSS-VERIFY). * * \note The \p sig buffer must be as large as the size * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. * * \note The \c hash_id set in \p ctx by mbedtls_rsa_set_padding() is * ignored. * * \param ctx The initialized RSA public key context to use. * \param md_alg The message-digest algorithm used to hash the original data. * Use #MBEDTLS_MD_NONE for signing raw data. * \param hashlen The length of the message digest or raw data in Bytes. * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the * output length of the corresponding hash algorithm. * \param hash The buffer holding the message digest or raw data. * This must be a readable buffer of at least \p hashlen Bytes. * \param mgf1_hash_id The message digest algorithm used for the * verification operation and the mask generation * function (MGF1). For more details on the encoding * operation and the mask generation function, consult * RFC-3447: Public-Key Cryptography Standards * (PKCS) #1 v2.1: RSA Cryptography * Specifications. * \param expected_salt_len The length of the salt used in padding. Use * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. * \param sig The buffer holding the signature. This must be a readable * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes * for an 2048-bit RSA modulus. * * \return \c 0 if the verify operation was successful. * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. */ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, mbedtls_md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig); /** * \brief This function copies the components of an RSA context. * * \param dst The destination context. This must be initialized. * \param src The source context. This must be initialized. * * \return \c 0 on success. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. */ int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src); /** * \brief This function frees the components of an RSA key. * * \param ctx The RSA context to free. May be \c NULL, in which case * this function is a no-op. If it is not \c NULL, it must * point to an initialized RSA context. */ void mbedtls_rsa_free(mbedtls_rsa_context *ctx); #if defined(MBEDTLS_SELF_TEST) /** * \brief The RSA checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_rsa_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* rsa.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h000066400000000000000000000165151464416617300237620ustar00rootroot00000000000000/** * \file sha1.h * * \brief This file contains SHA-1 definitions and functions. * * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in * FIPS 180-4: Secure Hash Standard (SHS). * * \warning SHA-1 is considered a weak message digest and its use constitutes * a security risk. We recommend considering stronger message * digests instead. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA1_H #define MBEDTLS_SHA1_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** SHA-1 input data was malformed. */ #define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_SHA1_ALT) // Regular implementation // /** * \brief The SHA-1 context structure. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * */ typedef struct mbedtls_sha1_context { uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< The intermediate digest state. */ unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ } mbedtls_sha1_context; #else /* MBEDTLS_SHA1_ALT */ #include "sha1_alt.h" #endif /* MBEDTLS_SHA1_ALT */ /** * \brief This function initializes a SHA-1 context. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to initialize. * This must not be \c NULL. * */ void mbedtls_sha1_init(mbedtls_sha1_context *ctx); /** * \brief This function clears a SHA-1 context. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to clear. This may be \c NULL, * in which case this function does nothing. If it is * not \c NULL, it must point to an initialized * SHA-1 context. * */ void mbedtls_sha1_free(mbedtls_sha1_context *ctx); /** * \brief This function clones the state of a SHA-1 context. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param dst The SHA-1 context to clone to. This must be initialized. * \param src The SHA-1 context to clone from. This must be initialized. * */ void mbedtls_sha1_clone(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src); /** * \brief This function starts a SHA-1 checksum calculation. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to initialize. This must be initialized. * * \return \c 0 on success. * \return A negative error code on failure. * */ int mbedtls_sha1_starts(mbedtls_sha1_context *ctx); /** * \brief This function feeds an input buffer into an ongoing SHA-1 * checksum calculation. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the input data. * This must be a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data \p input in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the SHA-1 operation, and writes * the result to the output buffer. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to use. This must be initialized and * have a hash operation started. * \param output The SHA-1 checksum result. This must be a writable * buffer of length \c 20 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20]); /** * \brief SHA-1 process data block (internal use only). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param ctx The SHA-1 context to use. This must be initialized. * \param data The data block being processed. This must be a * readable buffer of length \c 64 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. * */ int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]); /** * \brief This function calculates the SHA-1 checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-1 result is calculated as * output = SHA-1(input buffer). * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \param input The buffer holding the input data. * This must be a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data \p input in Bytes. * \param output The SHA-1 checksum result. * This must be a writable buffer of length \c 20 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. * */ int mbedtls_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]); #if defined(MBEDTLS_SELF_TEST) /** * \brief The SHA-1 checkup routine. * * \warning SHA-1 is considered a weak message digest and its use * constitutes a security risk. We recommend considering * stronger message digests instead. * * \return \c 0 on success. * \return \c 1 on failure. * */ int mbedtls_sha1_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha1.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h000066400000000000000000000153371464416617300241370ustar00rootroot00000000000000/** * \file sha256.h * * \brief This file contains SHA-224 and SHA-256 definitions and functions. * * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA256_H #define MBEDTLS_SHA256_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** SHA-256 input data was malformed. */ #define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_SHA256_ALT) // Regular implementation // /** * \brief The SHA-256 context structure. * * The structure is used both for SHA-256 and for SHA-224 * checksum calculations. The choice between these two is * made in the call to mbedtls_sha256_starts(). */ typedef struct mbedtls_sha256_context { unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ uint32_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ #if defined(MBEDTLS_SHA224_C) int MBEDTLS_PRIVATE(is224); /*!< Determines which function to use: 0: Use SHA-256, or 1: Use SHA-224. */ #endif } mbedtls_sha256_context; #else /* MBEDTLS_SHA256_ALT */ #include "sha256_alt.h" #endif /* MBEDTLS_SHA256_ALT */ /** * \brief This function initializes a SHA-256 context. * * \param ctx The SHA-256 context to initialize. This must not be \c NULL. */ void mbedtls_sha256_init(mbedtls_sha256_context *ctx); /** * \brief This function clears a SHA-256 context. * * \param ctx The SHA-256 context to clear. This may be \c NULL, in which * case this function returns immediately. If it is not \c NULL, * it must point to an initialized SHA-256 context. */ void mbedtls_sha256_free(mbedtls_sha256_context *ctx); /** * \brief This function clones the state of a SHA-256 context. * * \param dst The destination context. This must be initialized. * \param src The context to clone. This must be initialized. */ void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src); /** * \brief This function starts a SHA-224 or SHA-256 checksum * calculation. * * \param ctx The context to use. This must be initialized. * \param is224 This determines which function to use. This must be * either \c 0 for SHA-256, or \c 1 for SHA-224. * * \note is224 must be defined accordingly to the enabled * MBEDTLS_SHA224_C/MBEDTLS_SHA256_C symbols otherwise the * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224); /** * \brief This function feeds an input buffer into an ongoing * SHA-256 checksum calculation. * * \param ctx The SHA-256 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the SHA-256 operation, and writes * the result to the output buffer. * * \param ctx The SHA-256 context. This must be initialized * and have a hash operation started. * \param output The SHA-224 or SHA-256 checksum result. * This must be a writable buffer of length \c 32 bytes * for SHA-256, \c 28 bytes for SHA-224. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char *output); /** * \brief This function processes a single data block within * the ongoing SHA-256 computation. This function is for * internal use only. * * \param ctx The SHA-256 context. This must be initialized. * \param data The buffer holding one block of data. This must * be a readable buffer of length \c 64 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[64]); /** * \brief This function calculates the SHA-224 or SHA-256 * checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-256 result is calculated as * output = SHA-256(input buffer). * * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-224 or SHA-256 checksum result. * This must be a writable buffer of length \c 32 bytes * for SHA-256, \c 28 bytes for SHA-224. * \param is224 Determines which function to use. This must be * either \c 0 for SHA-256, or \c 1 for SHA-224. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha256(const unsigned char *input, size_t ilen, unsigned char *output, int is224); #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SHA224_C) /** * \brief The SHA-224 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha224_self_test(int verbose); #endif /* MBEDTLS_SHA224_C */ #if defined(MBEDTLS_SHA256_C) /** * \brief The SHA-256 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha256_self_test(int verbose); #endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha256.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/sha3.h000066400000000000000000000126631464416617300237640ustar00rootroot00000000000000/** * \file sha3.h * * \brief This file contains SHA-3 definitions and functions. * * The Secure Hash Algorithms cryptographic * hash functions are defined in FIPS 202: SHA-3 Standard: * Permutation-Based Hash and Extendable-Output Functions . */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA3_H #define MBEDTLS_SHA3_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include #ifdef __cplusplus extern "C" { #endif /** SHA-3 input data was malformed. */ #define MBEDTLS_ERR_SHA3_BAD_INPUT_DATA -0x0076 /** * SHA-3 family id. * * It identifies the family (SHA3-256, SHA3-512, etc.) */ typedef enum { MBEDTLS_SHA3_NONE = 0, /*!< Operation not defined. */ MBEDTLS_SHA3_224, /*!< SHA3-224 */ MBEDTLS_SHA3_256, /*!< SHA3-256 */ MBEDTLS_SHA3_384, /*!< SHA3-384 */ MBEDTLS_SHA3_512, /*!< SHA3-512 */ } mbedtls_sha3_id; /** * \brief The SHA-3 context structure. * * The structure is used SHA-3 checksum calculations. */ typedef struct { uint64_t MBEDTLS_PRIVATE(state[25]); uint32_t MBEDTLS_PRIVATE(index); uint16_t MBEDTLS_PRIVATE(olen); uint16_t MBEDTLS_PRIVATE(max_block_size); } mbedtls_sha3_context; /** * \brief This function initializes a SHA-3 context. * * \param ctx The SHA-3 context to initialize. This must not be \c NULL. */ void mbedtls_sha3_init(mbedtls_sha3_context *ctx); /** * \brief This function clears a SHA-3 context. * * \param ctx The SHA-3 context to clear. This may be \c NULL, in which * case this function returns immediately. If it is not \c NULL, * it must point to an initialized SHA-3 context. */ void mbedtls_sha3_free(mbedtls_sha3_context *ctx); /** * \brief This function clones the state of a SHA-3 context. * * \param dst The destination context. This must be initialized. * \param src The context to clone. This must be initialized. */ void mbedtls_sha3_clone(mbedtls_sha3_context *dst, const mbedtls_sha3_context *src); /** * \brief This function starts a SHA-3 checksum * calculation. * * \param ctx The context to use. This must be initialized. * \param id The id of the SHA-3 family. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id); /** * \brief This function feeds an input buffer into an ongoing * SHA-3 checksum calculation. * * \param ctx The SHA-3 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3_update(mbedtls_sha3_context *ctx, const uint8_t *input, size_t ilen); /** * \brief This function finishes the SHA-3 operation, and writes * the result to the output buffer. * * \param ctx The SHA-3 context. This must be initialized * and have a hash operation started. * \param output The SHA-3 checksum result. * This must be a writable buffer of length \c olen bytes. * \param olen Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256, * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64, * respectively. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, uint8_t *output, size_t olen); /** * \brief This function calculates the SHA-3 * checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-3 result is calculated as * output = SHA-3(id, input buffer, d). * * \param id The id of the SHA-3 family. * \param input The buffer holding the data. This must be a readable * buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-3 checksum result. * This must be a writable buffer of length \c olen bytes. * \param olen Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256, * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64, * respectively. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, size_t ilen, uint8_t *output, size_t olen); #if defined(MBEDTLS_SELF_TEST) /** * \brief Checkup routine for the algorithms implemented * by this module: SHA3-224, SHA3-256, SHA3-384, SHA3-512. * * \return 0 if successful, or 1 if the test failed. */ int mbedtls_sha3_self_test(int verbose); #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha3.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h000066400000000000000000000162061464416617300241260ustar00rootroot00000000000000/** * \file sha512.h * \brief This file contains SHA-384 and SHA-512 definitions and functions. * * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SHA512_H #define MBEDTLS_SHA512_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #include /** SHA-512 input data was malformed. */ #define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_SHA512_ALT) // Regular implementation // /** * \brief The SHA-512 context structure. * * The structure is used both for SHA-384 and for SHA-512 * checksum calculations. The choice between these two is * made in the call to mbedtls_sha512_starts(). */ typedef struct mbedtls_sha512_context { uint64_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ uint64_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ unsigned char MBEDTLS_PRIVATE(buffer)[128]; /*!< The data block being processed. */ #if defined(MBEDTLS_SHA384_C) int MBEDTLS_PRIVATE(is384); /*!< Determines which function to use: 0: Use SHA-512, or 1: Use SHA-384. */ #endif } mbedtls_sha512_context; #else /* MBEDTLS_SHA512_ALT */ #include "sha512_alt.h" #endif /* MBEDTLS_SHA512_ALT */ /** * \brief This function initializes a SHA-512 context. * * \param ctx The SHA-512 context to initialize. This must * not be \c NULL. */ void mbedtls_sha512_init(mbedtls_sha512_context *ctx); /** * \brief This function clears a SHA-512 context. * * \param ctx The SHA-512 context to clear. This may be \c NULL, * in which case this function does nothing. If it * is not \c NULL, it must point to an initialized * SHA-512 context. */ void mbedtls_sha512_free(mbedtls_sha512_context *ctx); /** * \brief This function clones the state of a SHA-512 context. * * \param dst The destination context. This must be initialized. * \param src The context to clone. This must be initialized. */ void mbedtls_sha512_clone(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src); /** * \brief This function starts a SHA-384 or SHA-512 checksum * calculation. * * \param ctx The SHA-512 context to use. This must be initialized. * \param is384 Determines which function to use. This must be * either \c 0 for SHA-512, or \c 1 for SHA-384. * * \note is384 must be defined accordingly to the enabled * MBEDTLS_SHA384_C/MBEDTLS_SHA512_C symbols otherwise the * function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384); /** * \brief This function feeds an input buffer into an ongoing * SHA-512 checksum calculation. * * \param ctx The SHA-512 context. This must be initialized * and have a hash operation started. * \param input The buffer holding the input data. This must * be a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen); /** * \brief This function finishes the SHA-512 operation, and writes * the result to the output buffer. * * \param ctx The SHA-512 context. This must be initialized * and have a hash operation started. * \param output The SHA-384 or SHA-512 checksum result. * This must be a writable buffer of length \c 64 bytes * for SHA-512, \c 48 bytes for SHA-384. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char *output); /** * \brief This function processes a single data block within * the ongoing SHA-512 computation. * This function is for internal use only. * * \param ctx The SHA-512 context. This must be initialized. * \param data The buffer holding one block of data. This * must be a readable buffer of length \c 128 Bytes. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[128]); /** * \brief This function calculates the SHA-512 or SHA-384 * checksum of a buffer. * * The function allocates the context, performs the * calculation, and frees the context. * * The SHA-512 result is calculated as * output = SHA-512(input buffer). * * \param input The buffer holding the input data. This must be * a readable buffer of length \p ilen Bytes. * \param ilen The length of the input data in Bytes. * \param output The SHA-384 or SHA-512 checksum result. * This must be a writable buffer of length \c 64 bytes * for SHA-512, \c 48 bytes for SHA-384. * \param is384 Determines which function to use. This must be either * \c 0 for SHA-512, or \c 1 for SHA-384. * * \note is384 must be defined accordingly with the supported * symbols in the config file. If: * - is384 is 0, but \c MBEDTLS_SHA384_C is not defined, or * - is384 is 1, but \c MBEDTLS_SHA512_C is not defined * then the function will return * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_sha512(const unsigned char *input, size_t ilen, unsigned char *output, int is384); #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SHA384_C) /** * \brief The SHA-384 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha384_self_test(int verbose); #endif /* MBEDTLS_SHA384_C */ #if defined(MBEDTLS_SHA512_C) /** * \brief The SHA-512 checkup routine. * * \return \c 0 on success. * \return \c 1 on failure. */ int mbedtls_sha512_self_test(int verbose); #endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SELF_TEST */ #ifdef __cplusplus } #endif #endif /* mbedtls_sha512.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h000066400000000000000000010121361464416617300237230ustar00rootroot00000000000000/** * \file ssl.h * * \brief SSL/TLS functions. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_H #define MBEDTLS_SSL_H #include "mbedtls/platform_util.h" #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" #include "mbedtls/ssl_ciphersuites.h" #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/x509_crt.h" #include "mbedtls/x509_crl.h" #endif #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" #endif #include "mbedtls/md.h" #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) #include "mbedtls/ecdh.h" #endif #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #include "psa/crypto.h" /* * SSL Error codes */ /** A cryptographic operation is in progress. Try again later. */ #define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /** The requested feature is not available. */ #define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /** Bad input parameters to function. */ #define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /** Verification of the message MAC failed. */ #define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /** An invalid SSL record was received. */ #define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /** The connection indicated an EOF. */ #define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /** A message could not be parsed due to a syntactic error. */ #define MBEDTLS_ERR_SSL_DECODE_ERROR -0x7300 /* Error space gap */ /** No RNG was provided to the SSL module. */ #define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /** No client certification received from the client, but required by the authentication mode. */ #define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /** Client received an extended server hello containing an unsupported extension */ #define MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION -0x7500 /** No ALPN protocols supported that the client advertises */ #define MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL -0x7580 /** The own private key or pre-shared key is not set, but needed. */ #define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /** No CA Chain is set, but required to operate. */ #define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /** An unexpected message was received from our peer. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /** A fatal alert message was received from our peer. */ #define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /** No server could be identified matching the client's SNI. */ #define MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME -0x7800 /** The peer notified us that the connection is going to be closed. */ #define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /* Error space gap */ /* Error space gap */ /** Processing of the Certificate handshake message failed. */ #define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00 /* Error space gap */ /** * Received NewSessionTicket Post Handshake Message. * This error code is experimental and may be changed or removed without notice. */ #define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00 /** Not possible to read early data */ #define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80 /** * Early data has been received as part of an on-going handshake. * This error code can be returned only on server side if and only if early * data has been enabled by means of the mbedtls_ssl_conf_early_data() API. * This error code can then be returned by mbedtls_ssl_handshake(), * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if * early data has been received as part of the handshake sequence they * triggered. To read the early data, call mbedtls_ssl_read_early_data(). */ #define MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA -0x7C00 /** Not possible to write early data */ #define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA -0x7C80 /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /** Cache entry not found */ #define MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND -0x7E80 /** Memory allocation failed */ #define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /** Hardware acceleration function returned with error */ #define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /** Hardware acceleration function skipped / left alone data */ #define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /** Handshake protocol not within min/max boundaries */ #define MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION -0x6E80 /** The handshake negotiation failed. */ #define MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE -0x6E00 /** Session ticket has expired. */ #define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ #define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /** Unknown identity received (eg, PSK identity) */ #define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /** Internal error (eg, unexpected failure in lower-level module) */ #define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /** A counter would wrap (eg, too many messages exchanged). */ #define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /** Unexpected message at ServerHello in renegotiation. */ #define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /** DTLS client must retry for hello verification */ #define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /** A buffer is too small to receive or write a message */ #define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /* Error space gap */ /** No data of requested type currently available on underlying transport. */ #define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /** Connection requires a write call. */ #define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /** The operation timed out. */ #define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /** The client initiated a reconnect from the same port. */ #define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /** Record header looks valid but is not expected. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /** The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /** A field in a message was incorrect or inconsistent with other fields. */ #define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER -0x6600 /** Internal-only message signaling that further message-processing should be done */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /** The asynchronous operation is not completed yet. */ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /** Internal-only message signaling that a message arrived early. */ #define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /* Error space gap */ /** An encrypted DTLS-frame with an unexpected CID was received. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 /** An operation failed due to an unexpected version or configuration. */ #define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 /** Invalid value in SSL config */ #define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 /* * Constants from RFC 8446 for TLS 1.3 PSK modes * * Those are used in the Pre-Shared Key Exchange Modes extension. * See Section 4.2.9 in RFC 8446. */ #define MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE 0 /* Pure PSK-based exchange */ #define MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE 1 /* PSK+ECDHE-based exchange */ /* * TLS 1.3 NamedGroup values * * From RF 8446 * enum { * // Elliptic Curve Groups (ECDHE) * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), * x25519(0x001D), x448(0x001E), * // Finite Field Groups (DHE) * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), * ffdhe6144(0x0103), ffdhe8192(0x0104), * // Reserved Code Points * ffdhe_private_use(0x01FC..0x01FF), * ecdhe_private_use(0xFE00..0xFEFF), * (0xFFFF) * } NamedGroup; * */ /* Elliptic Curve Groups (ECDHE) */ #define MBEDTLS_SSL_IANA_TLS_GROUP_NONE 0 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 0x0012 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 0x0013 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 0x0014 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 0x0015 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 0x0016 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 0x0017 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 0x0018 #define MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 0x0019 #define MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 0x001A #define MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 0x001B #define MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 0x001C #define MBEDTLS_SSL_IANA_TLS_GROUP_X25519 0x001D #define MBEDTLS_SSL_IANA_TLS_GROUP_X448 0x001E /* Finite Field Groups (DHE) */ #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 0x0100 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072 0x0101 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096 0x0102 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144 0x0103 #define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192 0x0104 /* * TLS 1.3 Key Exchange Modes * * Mbed TLS internal identifiers for use with the SSL configuration API * mbedtls_ssl_conf_tls13_key_exchange_modes(). */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK (1u << 0) /*!< Pure-PSK TLS 1.3 key exchange, * encompassing both externally agreed PSKs * as well as resumption PSKs. */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL (1u << 1) /*!< Pure-Ephemeral TLS 1.3 key exchanges, * including for example ECDHE and DHE * key exchanges. */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL (1u << 2) /*!< PSK-Ephemeral TLS 1.3 key exchanges, * using both a PSK and an ephemeral * key exchange. */ /* Convenience macros for sets of key exchanges. */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL \ (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) /*!< All TLS 1.3 key exchanges */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL \ (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All PSK-based TLS 1.3 key exchanges */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL \ (MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL | \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) /*!< All ephemeral TLS 1.3 key exchanges */ #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE (0) /* * Various constants */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /* These are the high and low bytes of ProtocolVersion as defined by: * - RFC 5246: ProtocolVersion version = { 3, 3 }; // TLS v1.2 * - RFC 8446: see section 4.2.1 */ #define MBEDTLS_SSL_MAJOR_VERSION_3 3 #define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ #define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 */ #endif /* MBEDTLS_DEPRECATED_REMOVED */ #define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ #define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ #define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ #define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ #define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ /* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c * NONE must be zero so that memset()ing structure to zero works */ #define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ #define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ #define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ #define MBEDTLS_SSL_IS_CLIENT 0 #define MBEDTLS_SSL_IS_SERVER 1 #define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 #define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 #define MBEDTLS_SSL_CID_DISABLED 0 #define MBEDTLS_SSL_CID_ENABLED 1 #define MBEDTLS_SSL_ETM_DISABLED 0 #define MBEDTLS_SSL_ETM_ENABLED 1 #define MBEDTLS_SSL_COMPRESS_NULL 0 #define MBEDTLS_SSL_VERIFY_NONE 0 #define MBEDTLS_SSL_VERIFY_OPTIONAL 1 #define MBEDTLS_SSL_VERIFY_REQUIRED 2 #define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ #define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 #define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 #define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 #define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 #define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 #define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 #define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 #define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 #define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 #define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 #define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 #define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 #define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 #define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ #define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 #define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 #define MBEDTLS_SSL_PRESET_DEFAULT 0 #define MBEDTLS_SSL_PRESET_SUITEB 2 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 #define MBEDTLS_SSL_EARLY_DATA_DISABLED 0 #define MBEDTLS_SSL_EARLY_DATA_ENABLED 1 #define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 #define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 #define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT 1 #define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER 0 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(PSA_WANT_ALG_SHA_384) #define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 48 #elif defined(PSA_WANT_ALG_SHA_256) #define MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN 32 #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ /* * Default range for DTLS retransmission timer value, in milliseconds. * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. */ #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 /* * Whether early data record should be discarded or not and how. * * The client has indicated early data and the server has rejected them. * The server has then to skip past early data by either: * - attempting to deprotect received records using the handshake traffic * key, discarding records which fail deprotection (up to the configured * max_early_data_size). Once a record is deprotected successfully, * it is treated as the start of the client's second flight and the * server proceeds as with an ordinary 1-RTT handshake. * - skipping all records with an external content type of * "application_data" (indicating that they are encrypted), up to the * configured max_early_data_size. This is the expected behavior if the * server has sent an HelloRetryRequest message. The server ignores * application data message before 2nd ClientHello. */ #define MBEDTLS_SSL_EARLY_DATA_NO_DISCARD 0 #define MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD 1 #define MBEDTLS_SSL_EARLY_DATA_DISCARD 2 /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ /* * Maximum fragment length in bytes, * determines the size of each of the two internal I/O buffers. * * Note: the RFC defines the default size of SSL / TLS messages. If you * change the value here, other clients / servers may not be able to * communicate with you anymore. Only change this value if you control * both sides of the connection and have it reduced at both sides, or * if you're using the Max Fragment Length extension and you know all your * peers are using it too! */ #if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) #define MBEDTLS_SSL_IN_CONTENT_LEN 16384 #endif #if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) #define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 #endif /* * Maximum number of heap-allocated bytes for the purpose of * DTLS handshake message reassembly and future message buffering. */ #if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) #define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 #endif /* * Maximum length of CIDs for incoming and outgoing messages. */ #if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX) #define MBEDTLS_SSL_CID_IN_LEN_MAX 32 #endif #if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) #define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 #endif #if !defined(MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) #define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 #endif #if !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) #define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE 1024 #endif #if !defined(MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) #define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000 #endif #if !defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH) #define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32 #endif #if !defined(MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS) #define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1 #endif /** \} name SECTION: Module settings */ /* * Default to standard CID mode */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) #define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0 #endif /* * Length of the verify data for secure renegotiation */ #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 /* * Signaling ciphersuite values (SCSV) */ #define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ /* * Supported Signature and Hash algorithms (For TLS 1.2) * RFC 5246 section 7.4.1.4.1 */ #define MBEDTLS_SSL_HASH_NONE 0 #define MBEDTLS_SSL_HASH_MD5 1 #define MBEDTLS_SSL_HASH_SHA1 2 #define MBEDTLS_SSL_HASH_SHA224 3 #define MBEDTLS_SSL_HASH_SHA256 4 #define MBEDTLS_SSL_HASH_SHA384 5 #define MBEDTLS_SSL_HASH_SHA512 6 #define MBEDTLS_SSL_SIG_ANON 0 #define MBEDTLS_SSL_SIG_RSA 1 #define MBEDTLS_SSL_SIG_ECDSA 3 /* * TLS 1.3 signature algorithms * RFC 8446, Section 4.2.3 */ /* RSASSA-PKCS1-v1_5 algorithms */ #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256 0x0401 #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384 0x0501 #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512 0x0601 /* ECDSA algorithms */ #define MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256 0x0403 #define MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384 0x0503 #define MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512 0x0603 /* RSASSA-PSS algorithms with public key OID rsaEncryption */ #define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256 0x0804 #define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384 0x0805 #define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512 0x0806 /* EdDSA algorithms */ #define MBEDTLS_TLS1_3_SIG_ED25519 0x0807 #define MBEDTLS_TLS1_3_SIG_ED448 0x0808 /* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ #define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256 0x0809 #define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384 0x080A #define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512 0x080B /* LEGACY ALGORITHMS */ #define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1 0x0201 #define MBEDTLS_TLS1_3_SIG_ECDSA_SHA1 0x0203 #define MBEDTLS_TLS1_3_SIG_NONE 0x0 /* * Client Certificate Types * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 */ #define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 #define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 /* * Message, alert and handshake types */ #define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 #define MBEDTLS_SSL_MSG_ALERT 21 #define MBEDTLS_SSL_MSG_HANDSHAKE 22 #define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 #define MBEDTLS_SSL_MSG_CID 25 #define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 #define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 #define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ #define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ #define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ #define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ #define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ #define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ #define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ #define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ #define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ #define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ #define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ #define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ #define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ #define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ #define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ #define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ #define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ #define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ #define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ #define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ #define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ #define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ #define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ #define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ #define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ #define MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION 109 /* 0x6d -- new in TLS 1.3 */ #define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ #define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ #define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ #define MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED 116 /* 0x74 */ #define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ #define MBEDTLS_SSL_HS_HELLO_REQUEST 0 #define MBEDTLS_SSL_HS_CLIENT_HELLO 1 #define MBEDTLS_SSL_HS_SERVER_HELLO 2 #define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 #define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 #define MBEDTLS_SSL_HS_END_OF_EARLY_DATA 5 #define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS 8 #define MBEDTLS_SSL_HS_CERTIFICATE 11 #define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 #define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 #define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 #define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 #define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 #define MBEDTLS_SSL_HS_FINISHED 20 #define MBEDTLS_SSL_HS_MESSAGE_HASH 254 /* * TLS extensions */ #define MBEDTLS_TLS_EXT_SERVERNAME 0 #define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 #define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 #define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 #define MBEDTLS_TLS_EXT_STATUS_REQUEST 5 /* RFC 6066 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 #define MBEDTLS_TLS_EXT_SUPPORTED_GROUPS 10 /* RFC 8422,7919 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 #define MBEDTLS_TLS_EXT_SIG_ALG 13 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_USE_SRTP 14 #define MBEDTLS_TLS_EXT_HEARTBEAT 15 /* RFC 6520 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_ALPN 16 #define MBEDTLS_TLS_EXT_SCT 18 /* RFC 6962 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_CLI_CERT_TYPE 19 /* RFC 7250 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_SERV_CERT_TYPE 20 /* RFC 7250 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_PADDING 21 /* RFC 7685 TLS 1.2 and 1.3 */ #define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ #define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ #define MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT 28 /* RFC 8449 (implemented for TLS 1.3 only) */ #define MBEDTLS_TLS_EXT_SESSION_TICKET 35 #define MBEDTLS_TLS_EXT_PRE_SHARED_KEY 41 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_EARLY_DATA 42 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS 43 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_COOKIE 44 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES 45 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_CERT_AUTH 47 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_OID_FILTERS 48 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH 49 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_SIG_ALG_CERT 50 /* RFC 8446 TLS 1.3 */ #define MBEDTLS_TLS_EXT_KEY_SHARE 51 /* RFC 8446 TLS 1.3 */ #if MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 #define MBEDTLS_TLS_EXT_CID 54 /* RFC 9146 DTLS 1.2 CID */ #else #define MBEDTLS_TLS_EXT_CID 254 /* Pre-RFC 9146 DTLS 1.2 CID */ #endif #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ #define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 /* * Size defines */ #if !defined(MBEDTLS_PSK_MAX_LEN) /* * If the library supports TLS 1.3 tickets and the cipher suite * TLS1-3-AES-256-GCM-SHA384, set the PSK maximum length to 48 instead of 32. * That way, the TLS 1.3 client and server are able to resume sessions where * the cipher suite is TLS1-3-AES-256-GCM-SHA384 (pre-shared keys are 48 * bytes long in that case). */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) && \ defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_PSK_MAX_LEN 48 /* 384 bits */ #else #define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ #endif #endif /* !MBEDTLS_PSK_MAX_LEN */ /* Dummy type used only for its size */ union mbedtls_ssl_premaster_secret { unsigned char dummy; /* Make the union non-empty even with SSL disabled */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ #endif }; #define MBEDTLS_PREMASTER_SIZE sizeof(union mbedtls_ssl_premaster_secret) #define MBEDTLS_TLS1_3_MD_MAX_SIZE PSA_HASH_MAX_SIZE /* Length in number of bytes of the TLS sequence number */ #define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8 #ifdef __cplusplus extern "C" { #endif /* * SSL state machine */ typedef enum { MBEDTLS_SSL_HELLO_REQUEST, MBEDTLS_SSL_CLIENT_HELLO, MBEDTLS_SSL_SERVER_HELLO, MBEDTLS_SSL_SERVER_CERTIFICATE, MBEDTLS_SSL_SERVER_KEY_EXCHANGE, MBEDTLS_SSL_CERTIFICATE_REQUEST, MBEDTLS_SSL_SERVER_HELLO_DONE, MBEDTLS_SSL_CLIENT_CERTIFICATE, MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, MBEDTLS_SSL_CERTIFICATE_VERIFY, MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, MBEDTLS_SSL_CLIENT_FINISHED, MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, MBEDTLS_SSL_SERVER_FINISHED, MBEDTLS_SSL_FLUSH_BUFFERS, MBEDTLS_SSL_HANDSHAKE_WRAPUP, MBEDTLS_SSL_NEW_SESSION_TICKET, MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, MBEDTLS_SSL_HELLO_RETRY_REQUEST, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS, MBEDTLS_SSL_END_OF_EARLY_DATA, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST, MBEDTLS_SSL_HANDSHAKE_OVER, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH, } mbedtls_ssl_states; /* * Early data status, client side only. */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) typedef enum { /* * See documentation of mbedtls_ssl_get_early_data_status(). */ MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED, MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED, MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED, } mbedtls_ssl_early_data_status; #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ /** * \brief Callback type: send data on the network. * * \note That callback may be either blocking or non-blocking. * * \param ctx Context for the send callback (typically a file descriptor) * \param buf Buffer holding the data to send * \param len Length of the data to send * * \return The callback must return the number of bytes sent if any, * or a non-zero error code. * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE * must be returned when the operation would block. * * \note The callback is allowed to send fewer bytes than requested. * It must always return the number of bytes actually sent. */ typedef int mbedtls_ssl_send_t(void *ctx, const unsigned char *buf, size_t len); /** * \brief Callback type: receive data from the network. * * \note That callback may be either blocking or non-blocking. * * \param ctx Context for the receive callback (typically a file * descriptor) * \param buf Buffer to write the received data to * \param len Length of the receive buffer * * \returns If data has been received, the positive number of bytes received. * \returns \c 0 if the connection has been closed. * \returns If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ * must be returned when the operation would block. * \returns Another negative error code on other kinds of failures. * * \note The callback may receive fewer bytes than the length of the * buffer. It must always return the number of bytes actually * received and written to the buffer. */ typedef int mbedtls_ssl_recv_t(void *ctx, unsigned char *buf, size_t len); /** * \brief Callback type: receive data from the network, with timeout * * \note That callback must block until data is received, or the * timeout delay expires, or the operation is interrupted by a * signal. * * \param ctx Context for the receive callback (typically a file descriptor) * \param buf Buffer to write the received data to * \param len Length of the receive buffer * \param timeout Maximum number of milliseconds to wait for data * 0 means no timeout (potentially waiting forever) * * \return The callback must return the number of bytes received, * or a non-zero error code: * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. * * \note The callback may receive fewer bytes than the length of the * buffer. It must always return the number of bytes actually * received and written to the buffer. */ typedef int mbedtls_ssl_recv_timeout_t(void *ctx, unsigned char *buf, size_t len, uint32_t timeout); /** * \brief Callback type: set a pair of timers/delays to watch * * \param ctx Context pointer * \param int_ms Intermediate delay in milliseconds * \param fin_ms Final delay in milliseconds * 0 cancels the current timer. * * \note This callback must at least store the necessary information * for the associated \c mbedtls_ssl_get_timer_t callback to * return correct information. * * \note If using an event-driven style of programming, an event must * be generated when the final delay is passed. The event must * cause a call to \c mbedtls_ssl_handshake() with the proper * SSL context to be scheduled. Care must be taken to ensure * that at most one such call happens at a time. * * \note Only one timer at a time must be running. Calling this * function while a timer is running must cancel it. Cancelled * timers must not generate any event. */ typedef void mbedtls_ssl_set_timer_t(void *ctx, uint32_t int_ms, uint32_t fin_ms); /** * \brief Callback type: get status of timers/delays * * \param ctx Context pointer * * \return This callback must return: * -1 if cancelled (fin_ms == 0), * 0 if none of the delays have passed, * 1 if only the intermediate delay has passed, * 2 if the final delay has passed. */ typedef int mbedtls_ssl_get_timer_t(void *ctx); /* Defined below */ typedef struct mbedtls_ssl_session mbedtls_ssl_session; typedef struct mbedtls_ssl_context mbedtls_ssl_context; typedef struct mbedtls_ssl_config mbedtls_ssl_config; /* Defined in library/ssl_misc.h */ typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; #if defined(MBEDTLS_X509_CRT_PARSE_C) typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK /* 1U << 0 */ #define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION \ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL /* 1U << 2 */ #define MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA (1U << 3) #define MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK \ (MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION | \ MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION | \ MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ /** * \brief Callback type: server-side session cache getter * * The session cache is logically a key value store, with * keys being session IDs and values being instances of * mbedtls_ssl_session. * * This callback retrieves an entry in this key-value store. * * \param data The address of the session cache structure to query. * \param session_id The buffer holding the session ID to query. * \param session_id_len The length of \p session_id in Bytes. * \param session The address of the session structure to populate. * It is initialized with mbdtls_ssl_session_init(), * and the callback must always leave it in a state * where it can safely be freed via * mbedtls_ssl_session_free() independent of the * return code of this function. * * \return \c 0 on success * \return A non-zero return value on failure. * */ typedef int mbedtls_ssl_cache_get_t(void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session); /** * \brief Callback type: server-side session cache setter * * The session cache is logically a key value store, with * keys being session IDs and values being instances of * mbedtls_ssl_session. * * This callback sets an entry in this key-value store. * * \param data The address of the session cache structure to modify. * \param session_id The buffer holding the session ID to query. * \param session_id_len The length of \p session_id in Bytes. * \param session The address of the session to be stored in the * session cache. * * \return \c 0 on success * \return A non-zero return value on failure. */ typedef int mbedtls_ssl_cache_set_t(void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Callback type: start external signature operation. * * This callback is called during an SSL handshake to start * a signature decryption operation using an * external processor. The parameter \p cert contains * the public key; it is up to the callback function to * determine how to access the associated private key. * * This function typically sends or enqueues a request, and * does not wait for the operation to complete. This allows * the handshake step to be non-blocking. * * The parameters \p ssl and \p cert are guaranteed to remain * valid throughout the handshake. On the other hand, this * function must save the contents of \p hash if the value * is needed for later processing, because the \p hash buffer * is no longer valid after this function returns. * * This function may call mbedtls_ssl_set_async_operation_data() * to store an operation context for later retrieval * by the resume or cancel callback. * * \note For RSA signatures, this function must produce output * that is consistent with PKCS#1 v1.5 in the same way as * mbedtls_rsa_pkcs1_sign(). Before the private key operation, * apply the padding steps described in RFC 8017, section 9.2 * "EMSA-PKCS1-v1_5" as follows. * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 * encoding, treating \p hash as the DigestInfo to be * padded. In other words, apply EMSA-PKCS1-v1_5 starting * from step 3, with `T = hash` and `tLen = hash_len`. * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 * encoding, treating \p hash as the hash to be encoded and * padded. In other words, apply EMSA-PKCS1-v1_5 starting * from step 2, with `digestAlgorithm` obtained by calling * mbedtls_oid_get_oid_by_md() on \p md_alg. * * \note For ECDSA signatures, the output format is the DER encoding * `Ecdsa-Sig-Value` defined in * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). * * \param ssl The SSL connection instance. It should not be * modified other than via * mbedtls_ssl_set_async_operation_data(). * \param cert Certificate containing the public key. * In simple cases, this is one of the pointers passed to * mbedtls_ssl_conf_own_cert() when configuring the SSL * connection. However, if other callbacks are used, this * property may not hold. For example, if an SNI callback * is registered with mbedtls_ssl_conf_sni(), then * this callback determines what certificate is used. * \param md_alg Hash algorithm. * \param hash Buffer containing the hash. This buffer is * no longer valid when the function returns. * \param hash_len Size of the \c hash buffer in bytes. * * \return 0 if the operation was started successfully and the SSL * stack should call the resume callback immediately. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation * was started successfully and the SSL stack should return * immediately without calling the resume callback yet. * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external * processor does not support this key. The SSL stack will * use the private key object instead. * \return Any other error indicates a fatal failure and is * propagated up the call chain. The callback should * use \c MBEDTLS_ERR_PK_xxx error codes, and must not * use \c MBEDTLS_ERR_SSL_xxx error codes except as * directed in the documentation of this callback. */ typedef int mbedtls_ssl_async_sign_t(mbedtls_ssl_context *ssl, mbedtls_x509_crt *cert, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len); /** * \brief Callback type: start external decryption operation. * * This callback is called during an SSL handshake to start * an RSA decryption operation using an * external processor. The parameter \p cert contains * the public key; it is up to the callback function to * determine how to access the associated private key. * * This function typically sends or enqueues a request, and * does not wait for the operation to complete. This allows * the handshake step to be non-blocking. * * The parameters \p ssl and \p cert are guaranteed to remain * valid throughout the handshake. On the other hand, this * function must save the contents of \p input if the value * is needed for later processing, because the \p input buffer * is no longer valid after this function returns. * * This function may call mbedtls_ssl_set_async_operation_data() * to store an operation context for later retrieval * by the resume or cancel callback. * * \warning RSA decryption as used in TLS is subject to a potential * timing side channel attack first discovered by Bleichenbacher * in 1998. This attack can be remotely exploitable * in practice. To avoid this attack, you must ensure that * if the callback performs an RSA decryption, the time it * takes to execute and return the result does not depend * on whether the RSA decryption succeeded or reported * invalid padding. * * \param ssl The SSL connection instance. It should not be * modified other than via * mbedtls_ssl_set_async_operation_data(). * \param cert Certificate containing the public key. * In simple cases, this is one of the pointers passed to * mbedtls_ssl_conf_own_cert() when configuring the SSL * connection. However, if other callbacks are used, this * property may not hold. For example, if an SNI callback * is registered with mbedtls_ssl_conf_sni(), then * this callback determines what certificate is used. * \param input Buffer containing the input ciphertext. This buffer * is no longer valid when the function returns. * \param input_len Size of the \p input buffer in bytes. * * \return 0 if the operation was started successfully and the SSL * stack should call the resume callback immediately. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation * was started successfully and the SSL stack should return * immediately without calling the resume callback yet. * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external * processor does not support this key. The SSL stack will * use the private key object instead. * \return Any other error indicates a fatal failure and is * propagated up the call chain. The callback should * use \c MBEDTLS_ERR_PK_xxx error codes, and must not * use \c MBEDTLS_ERR_SSL_xxx error codes except as * directed in the documentation of this callback. */ typedef int mbedtls_ssl_async_decrypt_t(mbedtls_ssl_context *ssl, mbedtls_x509_crt *cert, const unsigned char *input, size_t input_len); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Callback type: resume external operation. * * This callback is called during an SSL handshake to resume * an external operation started by the * ::mbedtls_ssl_async_sign_t or * ::mbedtls_ssl_async_decrypt_t callback. * * This function typically checks the status of a pending * request or causes the request queue to make progress, and * does not wait for the operation to complete. This allows * the handshake step to be non-blocking. * * This function may call mbedtls_ssl_get_async_operation_data() * to retrieve an operation context set by the start callback. * It may call mbedtls_ssl_set_async_operation_data() to modify * this context. * * Note that when this function returns a status other than * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any * resources associated with the operation. * * \param ssl The SSL connection instance. It should not be * modified other than via * mbedtls_ssl_set_async_operation_data(). * \param output Buffer containing the output (signature or decrypted * data) on success. * \param output_len On success, number of bytes written to \p output. * \param output_size Size of the \p output buffer in bytes. * * \return 0 if output of the operation is available in the * \p output buffer. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation * is still in progress. Subsequent requests for progress * on the SSL connection will call the resume callback * again. * \return Any other error means that the operation is aborted. * The SSL handshake is aborted. The callback should * use \c MBEDTLS_ERR_PK_xxx error codes, and must not * use \c MBEDTLS_ERR_SSL_xxx error codes except as * directed in the documentation of this callback. */ typedef int mbedtls_ssl_async_resume_t(mbedtls_ssl_context *ssl, unsigned char *output, size_t *output_len, size_t output_size); /** * \brief Callback type: cancel external operation. * * This callback is called if an SSL connection is closed * while an asynchronous operation is in progress. Note that * this callback is not called if the * ::mbedtls_ssl_async_resume_t callback has run and has * returned a value other than * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case * the asynchronous operation has already completed. * * This function may call mbedtls_ssl_get_async_operation_data() * to retrieve an operation context set by the start callback. * * \param ssl The SSL connection instance. It should not be * modified. */ typedef void mbedtls_ssl_async_cancel_t(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 #if defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32 #elif defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48 #elif defined(MBEDTLS_MD_CAN_SHA1) #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20 #else /* This is already checked in check_config.h, but be sure. */ #error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT." #endif #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ typedef struct { unsigned char client_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char server_application_traffic_secret_N[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char resumption_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } mbedtls_ssl_tls13_application_secrets; #if defined(MBEDTLS_SSL_DTLS_SRTP) #define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH 255 #define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH 4 /* * For code readability use a typedef for DTLS-SRTP profiles * * Use_srtp extension protection profiles values as defined in * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml * * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value * must be updated too. */ #define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80 ((uint16_t) 0x0001) #define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32 ((uint16_t) 0x0002) #define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80 ((uint16_t) 0x0005) #define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32 ((uint16_t) 0x0006) /* This one is not iana defined, but for code readability. */ #define MBEDTLS_TLS_SRTP_UNSET ((uint16_t) 0x0000) typedef uint16_t mbedtls_ssl_srtp_profile; typedef struct mbedtls_dtls_srtp_info_t { /*! The SRTP profile that was negotiated. */ mbedtls_ssl_srtp_profile MBEDTLS_PRIVATE(chosen_dtls_srtp_profile); /*! The length of mki_value. */ uint16_t MBEDTLS_PRIVATE(mki_len); /*! The mki_value used, with max size of 256 bytes. */ unsigned char MBEDTLS_PRIVATE(mki_value)[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; } mbedtls_dtls_srtp_info; #endif /* MBEDTLS_SSL_DTLS_SRTP */ /** Human-friendly representation of the (D)TLS protocol version. */ typedef enum { MBEDTLS_SSL_VERSION_UNKNOWN, /*!< Context not in use or version not yet negotiated. */ MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303, /*!< (D)TLS 1.2 */ MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304, /*!< (D)TLS 1.3 */ } mbedtls_ssl_protocol_version; /* * This structure is used for storing current session data. * * Note: when changing this definition, we need to check and update: * - in tests/suites/test_suite_ssl.function: * ssl_populate_session() and ssl_serialize_session_save_load() * - in library/ssl_tls.c: * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() * mbedtls_ssl_session_save() and ssl_session_load() * ssl_session_copy() */ struct mbedtls_ssl_session { #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) unsigned char MBEDTLS_PRIVATE(mfl_code); /*!< MaxFragmentLength negotiated by peer */ #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ /*!< RecordSizeLimit received from the peer */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) uint16_t MBEDTLS_PRIVATE(record_size_limit); #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ unsigned char MBEDTLS_PRIVATE(exported); uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ /** TLS version negotiated in the session. Used if and when renegotiating * or resuming a session instead of the configured minor TLS version. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t MBEDTLS_PRIVATE(start); /*!< start time of current session */ #endif int MBEDTLS_PRIVATE(ciphersuite); /*!< chosen ciphersuite */ size_t MBEDTLS_PRIVATE(id_len); /*!< session id length */ unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */ unsigned char MBEDTLS_PRIVATE(master)[48]; /*!< the master secret */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_x509_crt *MBEDTLS_PRIVATE(peer_cert); /*!< peer X.509 cert chain */ #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /*! The digest of the peer's end-CRT. This must be kept to detect CRT * changes during renegotiation, mitigating the triple handshake attack. */ unsigned char *MBEDTLS_PRIVATE(peer_cert_digest); size_t MBEDTLS_PRIVATE(peer_cert_digest_len); mbedtls_md_type_t MBEDTLS_PRIVATE(peer_cert_digest_type); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ uint32_t MBEDTLS_PRIVATE(verify_result); /*!< verification result */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) unsigned char *MBEDTLS_PRIVATE(ticket); /*!< RFC 5077 session ticket */ size_t MBEDTLS_PRIVATE(ticket_len); /*!< session ticket length */ uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< ticket lifetime hint */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_HAVE_TIME) /*! When a ticket is created by a TLS server as part of an established TLS * session, the ticket creation time may need to be saved for the ticket * module to be able to check the ticket age when the ticket is used. * That's the purpose of this field. * Before creating a new ticket, an Mbed TLS server set this field with * its current time in milliseconds. This time may then be saved in the * session ticket data by the session ticket writing function and * recovered by the ticket parsing function later when the ticket is used. * The ticket module may then use this time to compute the ticket age and * determine if it has expired or not. * The Mbed TLS implementations of the session ticket writing and parsing * functions save and retrieve the ticket creation time as part of the * session ticket data. The session ticket parsing function relies on * the mbedtls_ssl_session_get_ticket_creation_time() API to get the * ticket creation time from the session ticket data. */ mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) uint32_t MBEDTLS_PRIVATE(ticket_age_add); /*!< Randomly generated value used to obscure the age of the ticket */ uint8_t MBEDTLS_PRIVATE(ticket_flags); /*!< Ticket flags */ uint8_t MBEDTLS_PRIVATE(resumption_key_len); /*!< resumption_key length */ unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN]; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C) char *MBEDTLS_PRIVATE(hostname); /*!< host name binded with tickets */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) char *ticket_alpn; /*!< ALPN negotiated in the session during which the ticket was generated. */ #endif #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C) /*! Time in milliseconds when the last ticket was received. */ mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_EARLY_DATA) uint32_t MBEDTLS_PRIVATE(max_early_data_size); /*!< maximum amount of early data in tickets */ #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) int MBEDTLS_PRIVATE(encrypt_then_mac); /*!< flag for EtM activation */ #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_application_secrets MBEDTLS_PRIVATE(app_secrets); #endif }; /* * Identifiers for PRFs used in various versions of TLS. */ typedef enum { MBEDTLS_SSL_TLS_PRF_NONE, MBEDTLS_SSL_TLS_PRF_SHA384, MBEDTLS_SSL_TLS_PRF_SHA256, MBEDTLS_SSL_HKDF_EXPAND_SHA384, MBEDTLS_SSL_HKDF_EXPAND_SHA256 } mbedtls_tls_prf_types; typedef enum { MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0, #if defined(MBEDTLS_SSL_PROTO_TLS1_3) MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } mbedtls_ssl_key_export_type; /** * \brief Callback type: Export key alongside random values for * session identification, and PRF for * implementation of TLS key exporters. * * \param p_expkey Context for the callback. * \param type The type of the key that is being exported. * \param secret The address of the buffer holding the secret * that's being exporterd. * \param secret_len The length of \p secret in bytes. * \param client_random The client random bytes. * \param server_random The server random bytes. * \param tls_prf_type The identifier for the PRF used in the handshake * to which the key belongs. */ typedef void mbedtls_ssl_export_keys_t(void *p_expkey, mbedtls_ssl_key_export_type type, const unsigned char *secret, size_t secret_len, const unsigned char client_random[32], const unsigned char server_random[32], mbedtls_tls_prf_types tls_prf_type); #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Callback type: generic handshake callback * * \note Callbacks may use user_data funcs to set/get app user data. * See \c mbedtls_ssl_get_user_data_p() * \c mbedtls_ssl_get_user_data_n() * \c mbedtls_ssl_conf_get_user_data_p() * \c mbedtls_ssl_conf_get_user_data_n() * * \param ssl \c mbedtls_ssl_context on which the callback is run * * \return The return value of the callback is 0 if successful, * or a specific MBEDTLS_ERR_XXX code, which will cause * the handshake to be aborted. */ typedef int (*mbedtls_ssl_hs_cb_t)(mbedtls_ssl_context *ssl); #endif /* A type for storing user data in a library structure. * * The representation of type may change in future versions of the library. * Only the behaviors guaranteed by documented accessor functions are * guaranteed to remain stable. */ typedef union { uintptr_t n; /* typically a handle to an associated object */ void *p; /* typically a pointer to extra data */ } mbedtls_ssl_user_data_t; /** * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. */ struct mbedtls_ssl_config { /* Group items mostly by size. This helps to reduce memory wasted to * padding. It also helps to keep smaller fields early in the structure, * so that elements tend to be in the 128-element direct access window * on Arm Thumb, which reduces the code size. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(max_tls_version); /*!< max. TLS version used */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(min_tls_version); /*!< min. TLS version used */ /* * Flags (could be bit-fields to save RAM, but separate bytes make * the code smaller on architectures with an instruction for direct * byte access). */ uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ uint8_t MBEDTLS_PRIVATE(transport); /*!< 0: stream (TLS), 1: datagram (DTLS) */ uint8_t MBEDTLS_PRIVATE(authmode); /*!< MBEDTLS_SSL_VERIFY_XXX */ /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ uint8_t MBEDTLS_PRIVATE(allow_legacy_renegotiation); /*!< MBEDTLS_LEGACY_XXX */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) uint8_t MBEDTLS_PRIVATE(mfl_code); /*!< desired fragment length indicator (MBEDTLS_SSL_MAX_FRAG_LEN_XXX) */ #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) uint8_t MBEDTLS_PRIVATE(encrypt_then_mac); /*!< negotiate encrypt-then-mac? */ #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) uint8_t MBEDTLS_PRIVATE(extended_ms); /*!< negotiate extended master secret? */ #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) uint8_t MBEDTLS_PRIVATE(anti_replay); /*!< detect and prevent replay? */ #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_CLI_C) uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_3) uint16_t MBEDTLS_PRIVATE(new_session_tickets_count); /*!< number of NewSessionTicket */ #endif #if defined(MBEDTLS_SSL_SRV_C) uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in Certificate Request messages? */ uint8_t MBEDTLS_PRIVATE(respect_cli_pref); /*!< pick the ciphersuite according to the client's preferences rather than ours? */ #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) uint8_t MBEDTLS_PRIVATE(ignore_unexpected_cid); /*!< Should DTLS record with * unexpected CID * lead to failure? */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_DTLS_SRTP) uint8_t MBEDTLS_PRIVATE(dtls_srtp_mki_support); /* support having mki_value in the use_srtp extension? */ #endif /* * Pointers */ /** Allowed ciphersuites for (D)TLS 1.2 (0-terminated) */ const int *MBEDTLS_PRIVATE(ciphersuite_list); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /** Allowed TLS 1.3 key exchange modes. */ int MBEDTLS_PRIVATE(tls13_kex_modes); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /** Callback for printing debug output */ void(*MBEDTLS_PRIVATE(f_dbg))(void *, int, const char *, int, const char *); void *MBEDTLS_PRIVATE(p_dbg); /*!< context for the debug function */ /** Callback for getting (pseudo-)random numbers */ int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ /** Callback to retrieve a session from the cache */ mbedtls_ssl_cache_get_t *MBEDTLS_PRIVATE(f_get_cache); /** Callback to store a session into the cache */ mbedtls_ssl_cache_set_t *MBEDTLS_PRIVATE(f_set_cache); void *MBEDTLS_PRIVATE(p_cache); /*!< context for cache callbacks */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /** Callback for setting cert according to SNI extension */ int(*MBEDTLS_PRIVATE(f_sni))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_sni); /*!< context for SNI callback */ #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) /** Callback to customize X.509 certificate chain verification */ int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_SSL_SRV_C) /** Callback to retrieve PSK key from identity */ int(*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_psk); /*!< context for PSK callback */ #endif #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a cookie for ClientHello verification */ int(*MBEDTLS_PRIVATE(f_cookie_write))(void *, unsigned char **, unsigned char *, const unsigned char *, size_t); /** Callback to verify validity of a ClientHello cookie */ int(*MBEDTLS_PRIVATE(f_cookie_check))(void *, const unsigned char *, size_t, const unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_cookie); /*!< context for the cookie callbacks */ #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** Callback to create & write a session ticket */ int(*MBEDTLS_PRIVATE(f_ticket_write))(void *, const mbedtls_ssl_session *, unsigned char *, const unsigned char *, size_t *, uint32_t *); /** Callback to parse a session ticket into a session structure */ int(*MBEDTLS_PRIVATE(f_ticket_parse))(void *, mbedtls_ssl_session *, unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_ticket); /*!< context for the ticket callbacks */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) size_t MBEDTLS_PRIVATE(cid_len); /*!< The length of CIDs for incoming DTLS records. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt_profile *MBEDTLS_PRIVATE(cert_profile); /*!< verification profile */ mbedtls_ssl_key_cert *MBEDTLS_PRIVATE(key_cert); /*!< own certificate/key pair(s) */ mbedtls_x509_crt *MBEDTLS_PRIVATE(ca_chain); /*!< trusted CAs */ mbedtls_x509_crl *MBEDTLS_PRIVATE(ca_crl); /*!< trusted CAs CRLs */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) mbedtls_x509_crt_ca_cb_t MBEDTLS_PRIVATE(f_ca_cb); void *MBEDTLS_PRIVATE(p_ca_cb); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_ssl_async_sign_t *MBEDTLS_PRIVATE(f_async_sign_start); /*!< start asynchronous signature operation */ mbedtls_ssl_async_decrypt_t *MBEDTLS_PRIVATE(f_async_decrypt_start); /*!< start asynchronous decryption operation */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ mbedtls_ssl_async_resume_t *MBEDTLS_PRIVATE(f_async_resume); /*!< resume asynchronous operation */ mbedtls_ssl_async_cancel_t *MBEDTLS_PRIVATE(f_async_cancel); /*!< cancel asynchronous operation */ void *MBEDTLS_PRIVATE(p_async_config_data); /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) const int *MBEDTLS_PRIVATE(sig_hashes); /*!< allowed signature hashes */ #endif const uint16_t *MBEDTLS_PRIVATE(sig_algs); /*!< allowed signature algorithms */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */ #endif const uint16_t *MBEDTLS_PRIVATE(group_list); /*!< allowed IANA NamedGroups */ #if defined(MBEDTLS_DHM_C) mbedtls_mpi MBEDTLS_PRIVATE(dhm_P); /*!< prime modulus for DHM */ mbedtls_mpi MBEDTLS_PRIVATE(dhm_G); /*!< generator for DHM */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psk_opaque); /*!< PSA key slot holding opaque PSK. This field * should only be set via * mbedtls_ssl_conf_psk_opaque(). * If either no PSK or a raw PSK have been * configured, this has value \c 0. */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ unsigned char *MBEDTLS_PRIVATE(psk); /*!< The raw pre-shared key. This field should * only be set via mbedtls_ssl_conf_psk(). * If either no PSK or an opaque PSK * have been configured, this has value NULL. */ size_t MBEDTLS_PRIVATE(psk_len); /*!< The length of the raw pre-shared key. * This field should only be set via * mbedtls_ssl_conf_psk(). * Its value is non-zero if and only if * \c psk is not \c NULL. */ unsigned char *MBEDTLS_PRIVATE(psk_identity); /*!< The PSK identity for PSK negotiation. * This field should only be set via * mbedtls_ssl_conf_psk(). * This is set if and only if either * \c psk or \c psk_opaque are set. */ size_t MBEDTLS_PRIVATE(psk_identity_len);/*!< The length of PSK identity. * This field should only be set via * mbedtls_ssl_conf_psk(). * Its value is non-zero if and only if * \c psk is not \c NULL or \c psk_opaque * is not \c 0. */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_SSL_EARLY_DATA) int MBEDTLS_PRIVATE(early_data_enabled); /*!< Early data enablement: * - MBEDTLS_SSL_EARLY_DATA_DISABLED, * - MBEDTLS_SSL_EARLY_DATA_ENABLED */ #if defined(MBEDTLS_SSL_SRV_C) /* The maximum amount of 0-RTT data. RFC 8446 section 4.6.1 */ uint32_t MBEDTLS_PRIVATE(max_early_data_size); #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_ALPN) const char **MBEDTLS_PRIVATE(alpn_list); /*!< ordered list of protocols */ #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) /*! ordered list of supported srtp profile */ const mbedtls_ssl_srtp_profile *MBEDTLS_PRIVATE(dtls_srtp_profile_list); /*! number of supported profiles */ size_t MBEDTLS_PRIVATE(dtls_srtp_profile_list_len); #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Numerical settings (int) */ uint32_t MBEDTLS_PRIVATE(read_timeout); /*!< timeout for mbedtls_ssl_read (ms) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) uint32_t MBEDTLS_PRIVATE(hs_timeout_min); /*!< initial value of the handshake retransmission timeout (ms) */ uint32_t MBEDTLS_PRIVATE(hs_timeout_max); /*!< maximum value of the handshake retransmission timeout (ms) */ #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) int MBEDTLS_PRIVATE(renego_max_records); /*!< grace period for renegotiation */ unsigned char MBEDTLS_PRIVATE(renego_period)[8]; /*!< value of the record counters that triggers renegotiation */ #endif unsigned int MBEDTLS_PRIVATE(badmac_limit); /*!< limit of records with a bad MAC */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) unsigned int MBEDTLS_PRIVATE(dhm_min_bitlen); /*!< min. bit length of the DHM prime */ #endif /** User data pointer or handle. * * The library sets this to \p 0 when creating a context and does not * access it afterwards. */ mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); #if defined(MBEDTLS_SSL_SRV_C) mbedtls_ssl_hs_cb_t MBEDTLS_PRIVATE(f_cert_cb); /*!< certificate selection callback */ #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) const mbedtls_x509_crt *MBEDTLS_PRIVATE(dn_hints);/*!< acceptable client cert issuers */ #endif }; struct mbedtls_ssl_context { const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */ /* * Miscellaneous */ int MBEDTLS_PRIVATE(state); /*!< SSL handshake: current state */ #if defined(MBEDTLS_SSL_RENEGOTIATION) int MBEDTLS_PRIVATE(renego_status); /*!< Initial, in progress, pending? */ int MBEDTLS_PRIVATE(renego_records_seen); /*!< Records since renego request, or with DTLS, number of retransmissions of request if renego_max_records is < 0 */ #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * Maximum TLS version to be negotiated, then negotiated TLS version. * * It is initialized as the configured maximum TLS version to be * negotiated by mbedtls_ssl_setup(). * * When renegotiating or resuming a session, it is overwritten in the * ClientHello writing preparation stage with the previously negotiated * TLS version. * * On client side, it is updated to the TLS version selected by the server * for the handshake when the ServerHello is received. * * On server side, it is updated to the TLS version the server selects for * the handshake when the ClientHello is received. */ mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) /** * State of the negotiation and transfer of early data. Reset to * MBEDTLS_SSL_EARLY_DATA_STATE_IDLE when the context is reset. */ int MBEDTLS_PRIVATE(early_data_state); #endif unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** Callback to customize X.509 certificate chain verification */ int(*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify callback */ #endif mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */ mbedtls_ssl_recv_t *MBEDTLS_PRIVATE(f_recv); /*!< Callback for network receive */ mbedtls_ssl_recv_timeout_t *MBEDTLS_PRIVATE(f_recv_timeout); /*!< Callback for network receive with timeout */ void *MBEDTLS_PRIVATE(p_bio); /*!< context for I/O operations */ /* * Session layer */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session_in); /*!< current session data (in) */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session_out); /*!< current session data (out) */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session); /*!< negotiated session data */ mbedtls_ssl_session *MBEDTLS_PRIVATE(session_negotiate); /*!< session data in negotiation */ mbedtls_ssl_handshake_params *MBEDTLS_PRIVATE(handshake); /*!< params required only during the handshake process */ /* * Record layer transformations */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_in); /*!< current transform params (in) * This is always a reference, * never an owning pointer. */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_out); /*!< current transform params (out) * This is always a reference, * never an owning pointer. */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform); /*!< negotiated transform params * This pointer owns the transform * it references. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!< transform params in negotiation * This pointer owns the transform * it references. */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /*! The application data transform in TLS 1.3. * This pointer owns the transform it references. */ mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_application); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Timers */ void *MBEDTLS_PRIVATE(p_timer); /*!< context for the timer callbacks */ mbedtls_ssl_set_timer_t *MBEDTLS_PRIVATE(f_set_timer); /*!< set timer callback */ mbedtls_ssl_get_timer_t *MBEDTLS_PRIVATE(f_get_timer); /*!< get timer callback */ /* * Record layer (incoming data) */ unsigned char *MBEDTLS_PRIVATE(in_buf); /*!< input buffer */ unsigned char *MBEDTLS_PRIVATE(in_ctr); /*!< 64-bit incoming message counter TLS: maintained by us DTLS: read from peer */ unsigned char *MBEDTLS_PRIVATE(in_hdr); /*!< start of record header */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char *MBEDTLS_PRIVATE(in_cid); /*!< The start of the CID; * (the end is marked by in_len). */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ unsigned char *MBEDTLS_PRIVATE(in_len); /*!< two-bytes message length field */ unsigned char *MBEDTLS_PRIVATE(in_iv); /*!< ivlen-byte IV */ unsigned char *MBEDTLS_PRIVATE(in_msg); /*!< message contents (in_iv+ivlen) */ unsigned char *MBEDTLS_PRIVATE(in_offt); /*!< read offset in application data */ int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */ size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */ size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */ #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) uint16_t MBEDTLS_PRIVATE(in_epoch); /*!< DTLS epoch for incoming records */ size_t MBEDTLS_PRIVATE(next_record_offset); /*!< offset of the next record in datagram (equal to in_left if none) */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) uint64_t MBEDTLS_PRIVATE(in_window_top); /*!< last validated record seq_num */ uint64_t MBEDTLS_PRIVATE(in_window); /*!< bitmask for replay detection */ #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ size_t MBEDTLS_PRIVATE(in_hslen); /*!< current handshake message length, including the handshake header */ int MBEDTLS_PRIVATE(nb_zero); /*!< # of 0-length encrypted messages */ int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message on next call to record layer? */ /* The following three variables indicate if and, if yes, * what kind of alert is pending to be sent. */ unsigned char MBEDTLS_PRIVATE(send_alert); /*!< Determines if a fatal alert should be sent. Values: - \c 0 , no alert is to be sent. - \c 1 , alert is to be sent. */ unsigned char MBEDTLS_PRIVATE(alert_type); /*!< Type of alert if send_alert != 0 */ int MBEDTLS_PRIVATE(alert_reason); /*!< The error code to be returned to the user once the fatal alert has been sent. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) uint8_t MBEDTLS_PRIVATE(disable_datagram_packing); /*!< Disable packing multiple records * within a single datagram. */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_EARLY_DATA) #if defined(MBEDTLS_SSL_SRV_C) /* * One of: * MBEDTLS_SSL_EARLY_DATA_NO_DISCARD * MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD * MBEDTLS_SSL_EARLY_DATA_DISCARD */ uint8_t MBEDTLS_PRIVATE(discard_early_data_record); #endif uint32_t MBEDTLS_PRIVATE(total_early_data_size); /*!< Number of received/written early data bytes */ #endif /* MBEDTLS_SSL_EARLY_DATA */ /* * Record layer (outgoing data) */ unsigned char *MBEDTLS_PRIVATE(out_buf); /*!< output buffer */ unsigned char *MBEDTLS_PRIVATE(out_ctr); /*!< 64-bit outgoing message counter */ unsigned char *MBEDTLS_PRIVATE(out_hdr); /*!< start of record header */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char *MBEDTLS_PRIVATE(out_cid); /*!< The start of the CID; * (the end is marked by in_len). */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ unsigned char *MBEDTLS_PRIVATE(out_len); /*!< two-bytes message length field */ unsigned char *MBEDTLS_PRIVATE(out_iv); /*!< ivlen-byte IV */ unsigned char *MBEDTLS_PRIVATE(out_msg); /*!< message contents (out_iv+ivlen) */ int MBEDTLS_PRIVATE(out_msgtype); /*!< record header: message type */ size_t MBEDTLS_PRIVATE(out_msglen); /*!< record header: message length */ size_t MBEDTLS_PRIVATE(out_left); /*!< amount of data not yet written */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t MBEDTLS_PRIVATE(out_buf_len); /*!< length of output buffer */ #endif unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Outgoing record sequence number. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) uint16_t MBEDTLS_PRIVATE(mtu); /*!< path mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * User settings */ #if defined(MBEDTLS_X509_CRT_PARSE_C) char *MBEDTLS_PRIVATE(hostname); /*!< expected peer CN for verification (and SNI if available) */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ALPN) const char *MBEDTLS_PRIVATE(alpn_chosen); /*!< negotiated protocol */ #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) /* * use_srtp extension */ mbedtls_dtls_srtp_info MBEDTLS_PRIVATE(dtls_srtp_info); #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Information for DTLS hello verify */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) unsigned char *MBEDTLS_PRIVATE(cli_id); /*!< transport-level ID of the client */ size_t MBEDTLS_PRIVATE(cli_id_len); /*!< length of cli_id */ #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Secure renegotiation */ /* needed to know when to send extension on server */ int MBEDTLS_PRIVATE(secure_renegotiation); /*!< does peer support legacy or secure renegotiation */ #if defined(MBEDTLS_SSL_RENEGOTIATION) size_t MBEDTLS_PRIVATE(verify_data_len); /*!< length of verify data stored */ char MBEDTLS_PRIVATE(own_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ char MBEDTLS_PRIVATE(peer_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* CID configuration to use in subsequent handshakes. */ /*! The next incoming CID, chosen by the user and applying to * all subsequent handshakes. This may be different from the * CID currently used in case the user has re-configured the CID * after an initial handshake. */ unsigned char MBEDTLS_PRIVATE(own_cid)[MBEDTLS_SSL_CID_IN_LEN_MAX]; uint8_t MBEDTLS_PRIVATE(own_cid_len); /*!< The length of \c own_cid. */ uint8_t MBEDTLS_PRIVATE(negotiate_cid); /*!< This indicates whether the CID extension should * be negotiated in the next handshake or not. * Possible values are #MBEDTLS_SSL_CID_ENABLED * and #MBEDTLS_SSL_CID_DISABLED. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /** Callback to export key block and master secret */ mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys); void *MBEDTLS_PRIVATE(p_export_keys); /*!< context for key export callback */ /** User data pointer or handle. * * The library sets this to \p 0 when creating a context and does not * access it afterwards. * * \warning Serializing and restoring an SSL context with * mbedtls_ssl_context_save() and mbedtls_ssl_context_load() * does not currently restore the user data. */ mbedtls_ssl_user_data_t MBEDTLS_PRIVATE(user_data); }; /** * \brief Return the name of the ciphersuite associated with the * given ID * * \param ciphersuite_id SSL ciphersuite ID * * \return a string containing the ciphersuite name */ const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id); /** * \brief Return the ID of the ciphersuite associated with the * given name * * \param ciphersuite_name SSL ciphersuite name * * \return the ID with the ciphersuite or 0 if not found */ int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name); /** * \brief Initialize an SSL context * Just makes the context ready for mbedtls_ssl_setup() or * mbedtls_ssl_free() * * \param ssl SSL context */ void mbedtls_ssl_init(mbedtls_ssl_context *ssl); /** * \brief Set up an SSL context for use * * \note No copy of the configuration context is made, it can be * shared by many mbedtls_ssl_context structures. * * \warning The conf structure will be accessed during the session. * It must not be modified or freed as long as the session * is active. * * \warning This function must be called exactly once per context. * Calling mbedtls_ssl_setup again is not supported, even * if no session is active. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param ssl SSL context * \param conf SSL configuration to use * * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if * memory allocation failed */ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf); /** * \brief Reset an already initialized SSL context for re-use * while retaining application-set variables, function * pointers and data. * * \param ssl SSL context * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED or MBEDTLS_ERR_SSL_HW_ACCEL_FAILED */ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl); /** * \brief Set the current endpoint type * * \param conf SSL configuration * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER */ void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint); /** * \brief Get the current endpoint type * * \param conf SSL configuration * * \return Endpoint type, either MBEDTLS_SSL_IS_CLIENT * or MBEDTLS_SSL_IS_SERVER */ static inline int mbedtls_ssl_conf_get_endpoint(const mbedtls_ssl_config *conf) { return conf->MBEDTLS_PRIVATE(endpoint); } /** * \brief Set the transport type (TLS or DTLS). * Default: TLS * * \note For DTLS, you must either provide a recv callback that * doesn't block, or one that handles timeouts, see * \c mbedtls_ssl_set_bio(). You also need to provide timer * callbacks with \c mbedtls_ssl_set_timer_cb(). * * \param conf SSL configuration * \param transport transport type: * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. */ void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport); /** * \brief Set the certificate verification mode * Default: NONE on server, REQUIRED on client * * \param conf SSL configuration * \param authmode can be: * * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked * (default on server) * (insecure on client) * * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the * handshake continues even if verification failed; * mbedtls_ssl_get_verify_result() can be called after the * handshake is complete. * * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, * handshake is aborted if verification failed. * (default on client) * * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at * the right time(s), which may not be obvious, while REQUIRED always perform * the verification as soon as possible. For example, REQUIRED was protecting * against the "triple handshake" attack even before it was found. */ void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode); #if defined(MBEDTLS_SSL_EARLY_DATA) /** * \brief Set the early data mode * Default: disabled on server and client * * \param conf The SSL configuration to use. * \param early_data_enabled can be: * * MBEDTLS_SSL_EARLY_DATA_DISABLED: * Early data functionality is disabled. This is the default on client and * server. * * MBEDTLS_SSL_EARLY_DATA_ENABLED: * Early data functionality is enabled and may be negotiated in the handshake. * Application using early data functionality needs to be aware that the * security properties for early data (also refered to as 0-RTT data) are * weaker than those for other kinds of TLS data. See the documentation of * mbedtls_ssl_write_early_data() and mbedtls_ssl_read_early_data() for more * information. * When early data functionality is enabled on server and only in that case, * the call to one of the APIs that trigger or resume an handshake sequence, * namely mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), * mbedtls_ssl_read() or mbedtls_ssl_write() may return with the error code * MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have * been received. To read the early data, call mbedtls_ssl_read_early_data() * before calling the original function again. */ void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, int early_data_enabled); #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the maximum amount of 0-RTT data in bytes * Default: #MBEDTLS_SSL_MAX_EARLY_DATA_SIZE * * This function sets the value of the max_early_data_size * field of the early data indication extension included in * the NewSessionTicket messages that the server may send. * * The value defines the maximum amount of 0-RTT data * in bytes that a client will be allowed to send when using * one of the tickets defined by the NewSessionTicket messages. * * \note When resuming a session using a ticket, if the server receives more * early data than allowed for the ticket, it terminates the connection. * The maximum amount of 0-RTT data should thus be large enough * to allow a minimum of early data to be exchanged. * * \param[in] conf The SSL configuration to use. * \param[in] max_early_data_size The maximum amount of 0-RTT data. * * \warning This interface DOES NOT influence/limit the amount of early data * that can be received through previously created and issued tickets, * which clients may have stored. */ void mbedtls_ssl_conf_max_early_data_size( mbedtls_ssl_config *conf, uint32_t max_early_data_size); #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set the verification callback (Optional). * * If set, the provided verify callback is called for each * certificate in the peer's CRT chain, including the trusted * root. For more information, please see the documentation of * \c mbedtls_x509_crt_verify(). * * \note For per context callbacks and contexts, please use * mbedtls_ssl_set_verify() instead. * * \param conf The SSL configuration to use. * \param f_vrfy The verification callback to use during CRT verification. * \param p_vrfy The opaque context to be passed to the callback. */ void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Set the random number generator callback * * \param conf SSL configuration * \param f_rng RNG function (mandatory) * \param p_rng RNG parameter */ void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Set the debug callback * * The callback has the following argument: * void * opaque context for the callback * int debug level * const char * file name * int line number * const char * message * * \param conf SSL configuration * \param f_dbg debug function * \param p_dbg debug parameter */ void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg); /** * \brief Return the SSL configuration structure associated * with the given SSL context. * * \note The pointer returned by this function is guaranteed to * remain valid until the context is freed. * * \param ssl The SSL context to query. * \return Pointer to the SSL configuration associated with \p ssl. */ static inline const mbedtls_ssl_config *mbedtls_ssl_context_get_config( const mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(conf); } /** * \brief Set the underlying BIO callbacks for write, read and * read-with-timeout. * * \param ssl SSL context * \param p_bio parameter (context) shared by BIO callbacks * \param f_send write callback * \param f_recv read callback * \param f_recv_timeout blocking read callback with timeout. * * \note One of f_recv or f_recv_timeout can be NULL, in which case * the other is used. If both are non-NULL, f_recv_timeout is * used and f_recv is ignored (as if it were NULL). * * \note The two most common use cases are: * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL * - blocking I/O, f_recv == NULL, f_recv_timeout != NULL * * \note For DTLS, you need to provide either a non-NULL * f_recv_timeout callback, or a f_recv that doesn't block. * * \note See the documentations of \c mbedtls_ssl_send_t, * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for * the conventions those callbacks must follow. * * \note On some platforms, net_sockets.c provides * \c mbedtls_net_send(), \c mbedtls_net_recv() and * \c mbedtls_net_recv_timeout() that are suitable to be used * here. */ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, void *p_bio, mbedtls_ssl_send_t *f_send, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout); #if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /** * \brief Configure the use of the Connection ID (CID) * extension in the next handshake. * * Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05 * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 * for legacy version) * * The DTLS CID extension allows the reliable association of * DTLS records to DTLS connections across changes in the * underlying transport (changed IP and Port metadata) by * adding explicit connection identifiers (CIDs) to the * headers of encrypted DTLS records. The desired CIDs are * configured by the application layer and are exchanged in * new `ClientHello` / `ServerHello` extensions during the * handshake, where each side indicates the CID it wants the * peer to use when writing encrypted messages. The CIDs are * put to use once records get encrypted: the stack discards * any incoming records that don't include the configured CID * in their header, and adds the peer's requested CID to the * headers of outgoing messages. * * This API enables or disables the use of the CID extension * in the next handshake and sets the value of the CID to * be used for incoming messages. * * \param ssl The SSL context to configure. This must be initialized. * \param enable This value determines whether the CID extension should * be used or not. Possible values are: * - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID. * - MBEDTLS_SSL_CID_DISABLED (default) to disable the use * of the CID. * \param own_cid The address of the readable buffer holding the CID we want * the peer to use when sending encrypted messages to us. * This may be \c NULL if \p own_cid_len is \c 0. * This parameter is unused if \p enable is set to * MBEDTLS_SSL_CID_DISABLED. * \param own_cid_len The length of \p own_cid. * This parameter is unused if \p enable is set to * MBEDTLS_SSL_CID_DISABLED. * * \note The value of \p own_cid_len must match the value of the * \c len parameter passed to mbedtls_ssl_conf_cid() * when configuring the ::mbedtls_ssl_config that \p ssl * is bound to. * * \note This CID configuration applies to subsequent handshakes * performed on the SSL context \p ssl, but does not trigger * one. You still have to call `mbedtls_ssl_handshake()` * (for the initial handshake) or `mbedtls_ssl_renegotiate()` * (for a renegotiation handshake) explicitly after a * successful call to this function to run the handshake. * * \note This call cannot guarantee that the use of the CID * will be successfully negotiated in the next handshake, * because the peer might not support it. Specifically: * - On the Client, enabling the use of the CID through * this call implies that the `ClientHello` in the next * handshake will include the CID extension, thereby * offering the use of the CID to the server. Only if * the `ServerHello` contains the CID extension, too, * the CID extension will actually be put to use. * - On the Server, enabling the use of the CID through * this call implies that the server will look for * the CID extension in a `ClientHello` from the client, * and, if present, reply with a CID extension in its * `ServerHello`. * * \note To check whether the use of the CID was negotiated * after the subsequent handshake has completed, please * use the API mbedtls_ssl_get_peer_cid(). * * \warning If the use of the CID extension is enabled in this call * and the subsequent handshake negotiates its use, Mbed TLS * will silently drop every packet whose CID does not match * the CID configured in \p own_cid. It is the responsibility * of the user to adapt the underlying transport to take care * of CID-based demultiplexing before handing datagrams to * Mbed TLS. * * \return \c 0 on success. In this case, the CID configuration * applies to the next handshake. * \return A negative error code on failure. */ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, int enable, unsigned char const *own_cid, size_t own_cid_len); /** * \brief Get information about our request for usage of the CID * extension in the current connection. * * \param ssl The SSL context to query. * \param enabled The address at which to store whether the CID extension * is requested to be used or not. If the CID is * requested, `*enabled` is set to * MBEDTLS_SSL_CID_ENABLED; otherwise, it is set to * MBEDTLS_SSL_CID_DISABLED. * \param own_cid The address of the buffer in which to store our own * CID (if the CID extension is requested). This may be * \c NULL in case the value of our CID isn't needed. If * it is not \c NULL, \p own_cid_len must not be \c NULL. * \param own_cid_len The address at which to store the size of our own CID * (if the CID extension is requested). This is also the * number of Bytes in \p own_cid that have been written. * This may be \c NULL in case the length of our own CID * isn't needed. If it is \c NULL, \p own_cid must be * \c NULL, too. * *\note If we are requesting an empty CID this function sets * `*enabled` to #MBEDTLS_SSL_CID_DISABLED (the rationale * for this is that the resulting outcome is the * same as if the CID extensions wasn't requested). * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], size_t *own_cid_len); /** * \brief Get information about the use of the CID extension * in the current connection. * * \param ssl The SSL context to query. * \param enabled The address at which to store whether the CID extension * is currently in use or not. If the CID is in use, * `*enabled` is set to MBEDTLS_SSL_CID_ENABLED; * otherwise, it is set to MBEDTLS_SSL_CID_DISABLED. * \param peer_cid The address of the buffer in which to store the CID * chosen by the peer (if the CID extension is used). * This may be \c NULL in case the value of peer CID * isn't needed. If it is not \c NULL, \p peer_cid_len * must not be \c NULL. * \param peer_cid_len The address at which to store the size of the CID * chosen by the peer (if the CID extension is used). * This is also the number of Bytes in \p peer_cid that * have been written. * This may be \c NULL in case the length of the peer CID * isn't needed. If it is \c NULL, \p peer_cid must be * \c NULL, too. * * \note This applies to the state of the CID negotiated in * the last complete handshake. If a handshake is in * progress, this function will attempt to complete * the handshake first. * * \note If CID extensions have been exchanged but both client * and server chose to use an empty CID, this function * sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED * (the rationale for this is that the resulting * communication is the same as if the CID extensions * hadn't been used). * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], size_t *peer_cid_len); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /** * \brief Set the Maximum Transport Unit (MTU). * Special value: 0 means unset (no limit). * This represents the maximum size of a datagram payload * handled by the transport layer (usually UDP) as determined * by the network link and stack. In practice, this controls * the maximum size datagram the DTLS layer will pass to the * \c f_send() callback set using \c mbedtls_ssl_set_bio(). * * \note The limit on datagram size is converted to a limit on * record payload by subtracting the current overhead of * encapsulation and encryption/authentication if any. * * \note This can be called at any point during the connection, for * example when a Path Maximum Transfer Unit (PMTU) * estimate becomes available from other sources, * such as lower (or higher) protocol layers. * * \note This setting only controls the size of the packets we send, * and does not restrict the size of the datagrams we're * willing to receive. Client-side, you can request the * server to use smaller records with \c * mbedtls_ssl_conf_max_frag_len(). * * \note If both a MTU and a maximum fragment length have been * configured (or negotiated with the peer), the resulting * lower limit on record payload (see first note) is used. * * \note This can only be used to decrease the maximum size * of datagrams (hence records, see first note) sent. It * cannot be used to increase the maximum size of records over * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. * * \note Values lower than the current record layer expansion will * result in an error when trying to send data. * * \param ssl SSL context * \param mtu Value of the path MTU in bytes */ void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set a connection-specific verification callback (optional). * * If set, the provided verify callback is called for each * certificate in the peer's CRT chain, including the trusted * root. For more information, please see the documentation of * \c mbedtls_x509_crt_verify(). * * \note This call is analogous to mbedtls_ssl_conf_verify() but * binds the verification callback and context to an SSL context * as opposed to an SSL configuration. * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify() * are both used, mbedtls_ssl_set_verify() takes precedence. * * \param ssl The SSL context to use. * \param f_vrfy The verification callback to use during CRT verification. * \param p_vrfy The opaque context to be passed to the callback. */ void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Set the timeout period for mbedtls_ssl_read() * (Default: no timeout.) * * \param conf SSL configuration context * \param timeout Timeout value in milliseconds. * Use 0 for no timeout (default). * * \note With blocking I/O, this will only work if a non-NULL * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). * With non-blocking I/O, this will only work if timer * callbacks were set with \c mbedtls_ssl_set_timer_cb(). * * \note With non-blocking I/O, you may also skip this function * altogether and handle timeouts at the application layer. */ void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout); /** * \brief Check whether a buffer contains a valid and authentic record * that has not been seen before. (DTLS only). * * This function does not change the user-visible state * of the SSL context. Its sole purpose is to provide * an indication of the legitimacy of an incoming record. * * This can be useful e.g. in distributed server environments * using the DTLS Connection ID feature, in which connections * might need to be passed between service instances on a change * of peer address, but where such disruptive operations should * only happen after the validity of incoming records has been * confirmed. * * \param ssl The SSL context to use. * \param buf The address of the buffer holding the record to be checked. * This must be a read/write buffer of length \p buflen Bytes. * \param buflen The length of \p buf in Bytes. * * \note This routine only checks whether the provided buffer begins * with a valid and authentic record that has not been seen * before, but does not check potential data following the * initial record. In particular, it is possible to pass DTLS * datagrams containing multiple records, in which case only * the first record is checked. * * \note This function modifies the input buffer \p buf. If you need * to preserve the original record, you have to maintain a copy. * * \return \c 0 if the record is valid and authentic and has not been * seen before. * \return MBEDTLS_ERR_SSL_INVALID_MAC if the check completed * successfully but the record was found to be not authentic. * \return MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed * successfully but the record was found to be invalid for * a reason different from authenticity checking. * \return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed * successfully but the record was found to be unexpected * in the state of the SSL context, including replayed records. * \return Another negative error code on different kinds of failure. * In this case, the SSL context becomes unusable and needs * to be freed or reset before reuse. */ int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t buflen); /** * \brief Set the timer callbacks (Mandatory for DTLS.) * * \param ssl SSL context * \param p_timer parameter (context) shared by timer callbacks * \param f_set_timer set timer callback * \param f_get_timer get timer callback. Must return: * * \note See the documentation of \c mbedtls_ssl_set_timer_t and * \c mbedtls_ssl_get_timer_t for the conventions this pair of * callbacks must follow. * * \note On some platforms, timing.c provides * \c mbedtls_timing_set_delay() and * \c mbedtls_timing_get_delay() that are suitable for using * here, except if using an event-driven style. * * \note See also the "DTLS tutorial" article in our knowledge base. * https://mbed-tls.readthedocs.io/en/latest/kb/how-to/dtls-tutorial */ void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, void *p_timer, mbedtls_ssl_set_timer_t *f_set_timer, mbedtls_ssl_get_timer_t *f_get_timer); #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the certificate selection callback (server-side only). * * If set, the callback is always called for each handshake, * after `ClientHello` processing has finished. * * \param conf The SSL configuration to register the callback with. * \param f_cert_cb The callback for selecting server certificate after * `ClientHello` processing has finished. */ static inline void mbedtls_ssl_conf_cert_cb(mbedtls_ssl_config *conf, mbedtls_ssl_hs_cb_t f_cert_cb) { conf->MBEDTLS_PRIVATE(f_cert_cb) = f_cert_cb; } #endif /* MBEDTLS_SSL_SRV_C */ /** * \brief Callback type: generate and write session ticket * * \note This describes what a callback implementation should do. * This callback should generate an encrypted and * authenticated ticket for the session and write it to the * output buffer. Here, ticket means the opaque ticket part * of the NewSessionTicket structure of RFC 5077. * * \param p_ticket Context for the callback * \param session SSL session to be written in the ticket * \param start Start of the output buffer * \param end End of the output buffer * \param tlen On exit, holds the length written * \param lifetime On exit, holds the lifetime of the ticket in seconds * * \return 0 if successful, or * a specific MBEDTLS_ERR_XXX code. */ typedef int mbedtls_ssl_ticket_write_t(void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, const unsigned char *end, size_t *tlen, uint32_t *lifetime); /** * \brief Callback type: parse and load session ticket * * \note This describes what a callback implementation should do. * This callback should parse a session ticket as generated * by the corresponding mbedtls_ssl_ticket_write_t function, * and, if the ticket is authentic and valid, load the * session. * * \note The implementation is allowed to modify the first len * bytes of the input buffer, eg to use it as a temporary * area for the decrypted ticket contents. * * \param p_ticket Context for the callback * \param session SSL session to be loaded * \param buf Start of the buffer containing the ticket * \param len Length of the ticket. * * \return 0 if successful, or * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or * any other non-zero code for other failures. */ typedef int mbedtls_ssl_ticket_parse_t(void *p_ticket, mbedtls_ssl_session *session, unsigned char *buf, size_t len); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) /** * \brief Configure SSL session ticket callbacks (server only). * (Default: none.) * * \note On server, session tickets are enabled by providing * non-NULL callbacks. * * \note On client, use \c mbedtls_ssl_conf_session_tickets(). * * \param conf SSL configuration context * \param f_ticket_write Callback for writing a ticket * \param f_ticket_parse Callback for parsing a ticket * \param p_ticket Context shared by the two callbacks */ void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, void *p_ticket); #if defined(MBEDTLS_HAVE_TIME) /** * \brief Get the creation time of a session ticket. * * \note See the documentation of \c ticket_creation_time for information about * the intended usage of this function. * * \param session SSL session * \param ticket_creation_time On exit, holds the ticket creation time in * milliseconds. * * \return 0 on success, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid. */ static inline int mbedtls_ssl_session_get_ticket_creation_time( mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time) { if (session == NULL || ticket_creation_time == NULL || session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time); return 0; } #endif /* MBEDTLS_HAVE_TIME */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ /** * \brief Get the session-id buffer. * * \param session SSL session. * * \return The address of the session-id buffer. */ static inline unsigned const char (*mbedtls_ssl_session_get_id(const mbedtls_ssl_session * session))[32] { return &session->MBEDTLS_PRIVATE(id); } /** * \brief Get the size of the session-id. * * \param session SSL session. * * \return size_t size of session-id buffer. */ static inline size_t mbedtls_ssl_session_get_id_len(const mbedtls_ssl_session *session) { return session->MBEDTLS_PRIVATE(id_len); } /** * \brief Get the ciphersuite-id. * * \param session SSL session. * * \return int represetation for ciphersuite. */ static inline int mbedtls_ssl_session_get_ciphersuite_id(const mbedtls_ssl_session *session) { return session->MBEDTLS_PRIVATE(ciphersuite); } /** * \brief Configure a key export callback. * (Default: none.) * * This API can be used for two purposes: * - Debugging: Use this API to e.g. generate an NSSKeylog * file and use it to inspect encrypted traffic in tools * such as Wireshark. * - Application-specific export: Use this API to implement * key exporters, e.g. for EAP-TLS or DTLS-SRTP. * * * \param ssl The SSL context to which the export * callback should be attached. * \param f_export_keys The callback for the key export. * \param p_export_keys The opaque context pointer to be passed to the * callback \p f_export_keys. */ void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, mbedtls_ssl_export_keys_t *f_export_keys, void *p_export_keys); /** \brief Set the user data in an SSL configuration to a pointer. * * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_p(). * * \note The library stores \c p without accessing it. It is the responsibility * of the caller to ensure that the pointer remains valid. * * \param conf The SSL configuration context to modify. * \param p The new value of the user data. */ static inline void mbedtls_ssl_conf_set_user_data_p( mbedtls_ssl_config *conf, void *p) { conf->MBEDTLS_PRIVATE(user_data).p = p; } /** \brief Set the user data in an SSL configuration to an integer. * * You can retrieve this value later with mbedtls_ssl_conf_get_user_data_n(). * * \param conf The SSL configuration context to modify. * \param n The new value of the user data. */ static inline void mbedtls_ssl_conf_set_user_data_n( mbedtls_ssl_config *conf, uintptr_t n) { conf->MBEDTLS_PRIVATE(user_data).n = n; } /** \brief Retrieve the user data in an SSL configuration as a pointer. * * This is the value last set with mbedtls_ssl_conf_set_user_data_p(), or * \c NULL if mbedtls_ssl_conf_set_user_data_p() has not previously been * called. The value is undefined if mbedtls_ssl_conf_set_user_data_n() has * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_p(). * * \param conf The SSL configuration context to modify. * \return The current value of the user data. */ static inline void *mbedtls_ssl_conf_get_user_data_p( mbedtls_ssl_config *conf) { return conf->MBEDTLS_PRIVATE(user_data).p; } /** \brief Retrieve the user data in an SSL configuration as an integer. * * This is the value last set with mbedtls_ssl_conf_set_user_data_n(), or * \c 0 if mbedtls_ssl_conf_set_user_data_n() has not previously been * called. The value is undefined if mbedtls_ssl_conf_set_user_data_p() has * been called without a subsequent call to mbedtls_ssl_conf_set_user_data_n(). * * \param conf The SSL configuration context to modify. * \return The current value of the user data. */ static inline uintptr_t mbedtls_ssl_conf_get_user_data_n( mbedtls_ssl_config *conf) { return conf->MBEDTLS_PRIVATE(user_data).n; } /** \brief Set the user data in an SSL context to a pointer. * * You can retrieve this value later with mbedtls_ssl_get_user_data_p(). * * \note The library stores \c p without accessing it. It is the responsibility * of the caller to ensure that the pointer remains valid. * * \param ssl The SSL context to modify. * \param p The new value of the user data. */ static inline void mbedtls_ssl_set_user_data_p( mbedtls_ssl_context *ssl, void *p) { ssl->MBEDTLS_PRIVATE(user_data).p = p; } /** \brief Set the user data in an SSL context to an integer. * * You can retrieve this value later with mbedtls_ssl_get_user_data_n(). * * \param ssl The SSL context to modify. * \param n The new value of the user data. */ static inline void mbedtls_ssl_set_user_data_n( mbedtls_ssl_context *ssl, uintptr_t n) { ssl->MBEDTLS_PRIVATE(user_data).n = n; } /** \brief Retrieve the user data in an SSL context as a pointer. * * This is the value last set with mbedtls_ssl_set_user_data_p(), or * \c NULL if mbedtls_ssl_set_user_data_p() has not previously been * called. The value is undefined if mbedtls_ssl_set_user_data_n() has * been called without a subsequent call to mbedtls_ssl_set_user_data_p(). * * \param ssl The SSL context to modify. * \return The current value of the user data. */ static inline void *mbedtls_ssl_get_user_data_p( mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(user_data).p; } /** \brief Retrieve the user data in an SSL context as an integer. * * This is the value last set with mbedtls_ssl_set_user_data_n(), or * \c 0 if mbedtls_ssl_set_user_data_n() has not previously been * called. The value is undefined if mbedtls_ssl_set_user_data_p() has * been called without a subsequent call to mbedtls_ssl_set_user_data_n(). * * \param ssl The SSL context to modify. * \return The current value of the user data. */ static inline uintptr_t mbedtls_ssl_get_user_data_n( mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(user_data).n; } #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /** * \brief Configure asynchronous private key operation callbacks. * * \param conf SSL configuration context * \param f_async_sign Callback to start a signature operation. See * the description of ::mbedtls_ssl_async_sign_t * for more information. This may be \c NULL if the * external processor does not support any signature * operation; in this case the private key object * associated with the certificate will be used. * \param f_async_decrypt Callback to start a decryption operation. See * the description of ::mbedtls_ssl_async_decrypt_t * for more information. This may be \c NULL if the * external processor does not support any decryption * operation; in this case the private key object * associated with the certificate will be used. * \param f_async_resume Callback to resume an asynchronous operation. See * the description of ::mbedtls_ssl_async_resume_t * for more information. This may not be \c NULL unless * \p f_async_sign and \p f_async_decrypt are both * \c NULL. * \param f_async_cancel Callback to cancel an asynchronous operation. See * the description of ::mbedtls_ssl_async_cancel_t * for more information. This may be \c NULL if * no cleanup is needed. * \param config_data A pointer to configuration data which can be * retrieved with * mbedtls_ssl_conf_get_async_config_data(). The * library stores this value without dereferencing it. */ void mbedtls_ssl_conf_async_private_cb(mbedtls_ssl_config *conf, mbedtls_ssl_async_sign_t *f_async_sign, mbedtls_ssl_async_decrypt_t *f_async_decrypt, mbedtls_ssl_async_resume_t *f_async_resume, mbedtls_ssl_async_cancel_t *f_async_cancel, void *config_data); /** * \brief Retrieve the configuration data set by * mbedtls_ssl_conf_async_private_cb(). * * \param conf SSL configuration context * \return The configuration data set by * mbedtls_ssl_conf_async_private_cb(). */ void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf); /** * \brief Retrieve the asynchronous operation user context. * * \note This function may only be called while a handshake * is in progress. * * \param ssl The SSL context to access. * * \return The asynchronous operation user context that was last * set during the current handshake. If * mbedtls_ssl_set_async_operation_data() has not yet been * called during the current handshake, this function returns * \c NULL. */ void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl); /** * \brief Retrieve the asynchronous operation user context. * * \note This function may only be called while a handshake * is in progress. * * \param ssl The SSL context to access. * \param ctx The new value of the asynchronous operation user context. * Call mbedtls_ssl_get_async_operation_data() later during the * same handshake to retrieve this value. */ void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl, void *ctx); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /** * \brief Callback type: generate a cookie * * \param ctx Context for the callback * \param p Buffer to write to, * must be updated to point right after the cookie * \param end Pointer to one past the end of the output buffer * \param info Client ID info that was passed to * \c mbedtls_ssl_set_client_transport_id() * \param ilen Length of info in bytes * * \return The callback must return 0 on success, * or a negative error code. */ typedef int mbedtls_ssl_cookie_write_t(void *ctx, unsigned char **p, unsigned char *end, const unsigned char *info, size_t ilen); /** * \brief Callback type: verify a cookie * * \param ctx Context for the callback * \param cookie Cookie to verify * \param clen Length of cookie * \param info Client ID info that was passed to * \c mbedtls_ssl_set_client_transport_id() * \param ilen Length of info in bytes * * \return The callback must return 0 if cookie is valid, * or a negative error code. */ typedef int mbedtls_ssl_cookie_check_t(void *ctx, const unsigned char *cookie, size_t clen, const unsigned char *info, size_t ilen); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /** * \brief Register callbacks for DTLS cookies * (Server only. DTLS only.) * * Default: dummy callbacks that fail, in order to force you to * register working callbacks (and initialize their context). * * To disable HelloVerifyRequest, register NULL callbacks. * * \warning Disabling hello verification allows your server to be used * for amplification in DoS attacks against other hosts. * Only disable if you known this can't happen in your * particular environment. * * \note See comments on \c mbedtls_ssl_handshake() about handling * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected * on the first handshake attempt when this is enabled. * * \note This is also necessary to handle client reconnection from * the same port as described in RFC 6347 section 4.2.8 (only * the variant with cookies is supported currently). See * comments on \c mbedtls_ssl_read() for details. * * \param conf SSL configuration * \param f_cookie_write Cookie write callback * \param f_cookie_check Cookie check callback * \param p_cookie Context for both callbacks */ void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf, mbedtls_ssl_cookie_write_t *f_cookie_write, mbedtls_ssl_cookie_check_t *f_cookie_check, void *p_cookie); /** * \brief Set client's transport-level identification info. * (Server only. DTLS only.) * * This is usually the IP address (and port), but could be * anything identify the client depending on the underlying * network stack. Used for HelloVerifyRequest with DTLS. * This is *not* used to route the actual packets. * * \param ssl SSL context * \param info Transport-level info identifying the client (eg IP + port) * \param ilen Length of info in bytes * * \note An internal copy is made, so the info buffer can be reused. * * \return 0 on success, * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. */ int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl, const unsigned char *info, size_t ilen); #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) /** * \brief Enable or disable anti-replay protection for DTLS. * (DTLS only, no effect on TLS.) * Default: enabled. * * \param conf SSL configuration * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. * * \warning Disabling this is a security risk unless the application * protocol handles duplicated packets in a safe way. You * should not disable this without careful consideration. * However, if your application already detects duplicated * packets and needs information about them to adjust its * transmission strategy, then you'll want to disable this. */ void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode); #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ /** * \brief Set a limit on the number of records with a bad MAC * before terminating the connection. * (DTLS only, no effect on TLS.) * Default: 0 (disabled). * * \param conf SSL configuration * \param limit Limit, or 0 to disable. * * \note If the limit is N, then the connection is terminated when * the Nth non-authentic record is seen. * * \note Records with an invalid header are not counted, only the * ones going through the authentication-decryption phase. * * \note This is a security trade-off related to the fact that it's * often relatively easy for an active attacker to inject UDP * datagrams. On one hand, setting a low limit here makes it * easier for such an attacker to forcibly terminated a * connection. On the other hand, a high limit or no limit * might make us waste resources checking authentication on * many bogus packets. */ void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit); #if defined(MBEDTLS_SSL_PROTO_DTLS) /** * \brief Allow or disallow packing of multiple handshake records * within a single datagram. * * \param ssl The SSL context to configure. * \param allow_packing This determines whether datagram packing may * be used or not. A value of \c 0 means that every * record will be sent in a separate datagram; a * value of \c 1 means that, if space permits, * multiple handshake messages (including CCS) belonging to * a single flight may be packed within a single datagram. * * \note This is enabled by default and should only be disabled * for test purposes, or if datagram packing causes * interoperability issues with peers that don't support it. * * \note Allowing datagram packing reduces the network load since * there's less overhead if multiple messages share the same * datagram. Also, it increases the handshake efficiency * since messages belonging to a single datagram will not * be reordered in transit, and so future message buffering * or flight retransmission (if no buffering is used) as * means to deal with reordering are needed less frequently. * * \note Application records are not affected by this option and * are currently always sent in separate datagrams. * */ void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl, unsigned allow_packing); /** * \brief Set retransmit timeout values for the DTLS handshake. * (DTLS only, no effect on TLS.) * * \param conf SSL configuration * \param min Initial timeout value in milliseconds. * Default: 1000 (1 second). * \param max Maximum timeout value in milliseconds. * Default: 60000 (60 seconds). * * \note Default values are from RFC 6347 section 4.2.4.1. * * \note The 'min' value should typically be slightly above the * expected round-trip time to your peer, plus whatever time * it takes for the peer to process the message. For example, * if your RTT is about 600ms and you peer needs up to 1s to * do the cryptographic operations in the handshake, then you * should set 'min' slightly above 1600. Lower values of 'min' * might cause spurious resends which waste network resources, * while larger value of 'min' will increase overall latency * on unreliable network links. * * \note The more unreliable your network connection is, the larger * your max / min ratio needs to be in order to achieve * reliable handshakes. * * \note Messages are retransmitted up to log2(ceil(max/min)) times. * For example, if min = 1s and max = 5s, the retransmit plan * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> * resend ... 5s -> give up and return a timeout error. */ void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, uint32_t max); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the session cache callbacks (server-side only) * If not set, no session resuming is done (except if session * tickets are enabled too). * * The session cache has the responsibility to check for stale * entries based on timeout. See RFC 5246 for recommendations. * * Warning: session.peer_cert is cleared by the SSL/TLS layer on * connection shutdown, so do not cache the pointer! Either set * it to NULL or make a full copy of the certificate. * * The get callback is called once during the initial handshake * to enable session resuming. The get function has the * following parameters: (void *parameter, mbedtls_ssl_session *session) * If a valid entry is found, it should fill the master of * the session object with the cached values and return 0, * return 1 otherwise. Optionally peer_cert can be set as well * if it is properly present in cache entry. * * The set callback is called once during the initial handshake * to enable session resuming after the entire handshake has * been finished. The set function has the following parameters: * (void *parameter, const mbedtls_ssl_session *session). The function * should create a cache entry for future retrieval based on * the data in the session structure and should keep in mind * that the mbedtls_ssl_session object presented (and all its referenced * data) is cleared by the SSL/TLS layer when the connection is * terminated. It is recommended to add metadata to determine if * an entry is still valid in the future. Return 0 if * successfully cached, return 1 otherwise. * * \param conf SSL configuration * \param p_cache parameter (context) for both callbacks * \param f_get_cache session get callback * \param f_set_cache session set callback */ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, void *p_cache, mbedtls_ssl_cache_get_t *f_get_cache, mbedtls_ssl_cache_set_t *f_set_cache); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /** * \brief Load a session for session resumption. * * Sessions loaded through this call will be considered * for session resumption in the next handshake. * * \note Even if this call succeeds, it is not guaranteed that * the next handshake will indeed be shortened through the * use of session resumption: The server is always free * to reject any attempt for resumption and fall back to * a full handshake. * * \note This function can handle a variety of mechanisms for session * resumption: For TLS 1.2, both session ID-based resumption and * ticket-based resumption will be considered. For TLS 1.3, * once implemented, sessions equate to tickets, and loading * one or more sessions via this call will lead to their * corresponding tickets being advertised as resumption PSKs * by the client. * * \note Calling this function multiple times will only be useful * once TLS 1.3 is supported. For TLS 1.2 connections, this * function should be called at most once. * * \param ssl The SSL context representing the connection which should * be attempted to be setup using session resumption. This * must be initialized via mbedtls_ssl_init() and bound to * an SSL configuration via mbedtls_ssl_setup(), but * the handshake must not yet have been started. * \param session The session to be considered for session resumption. * This must be a session previously exported via * mbedtls_ssl_get_session(), and potentially serialized and * deserialized through mbedtls_ssl_session_save() and * mbedtls_ssl_session_load() in the meantime. * * \return \c 0 if successful. * \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session * could not be loaded because of an implementation limitation. * This error is non-fatal, and has no observable effect on * the SSL context or the session that was attempted to be loaded. * \return Another negative error code on other kinds of failure. * * \sa mbedtls_ssl_get_session() * \sa mbedtls_ssl_session_load() */ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** * \brief Load serialized session data into a session structure. * On client, this can be used for loading saved sessions * before resuming them with mbedtls_ssl_set_session(). * On server, this can be used for alternative implementations * of session cache or session tickets. * * \warning If a peer certificate chain is associated with the session, * the serialized state will only contain the peer's * end-entity certificate and the result of the chain * verification (unless verification was disabled), but not * the rest of the chain. * * \see mbedtls_ssl_session_save() * \see mbedtls_ssl_set_session() * * \param session The session structure to be populated. It must have been * initialised with mbedtls_ssl_session_init() but not * populated yet. * \param buf The buffer holding the serialized session data. It must be a * readable buffer of at least \p len bytes. * \param len The size of the serialized data in bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data * was generated in a different version or configuration of * Mbed TLS. * \return Another negative value for other kinds of errors (for * example, unsupported features in the embedded certificate). */ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len); /** * \brief Save session structure as serialized data in a buffer. * On client, this can be used for saving session data, * potentially in non-volatile storage, for resuming later. * On server, this can be used for alternative implementations * of session cache or session tickets. * * \see mbedtls_ssl_session_load() * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a * writeable buffer of at least \p buf_len bytes, or may be \c * NULL if \p buf_len is \c 0. * \param buf_len The number of bytes available for writing in \p buf. * \param olen The size in bytes of the data that has been or would have * been written. It must point to a valid \c size_t. * * \note \p olen is updated to the correct value regardless of * whether \p buf_len was large enough. This makes it possible * to determine the necessary size by calling this function * with \p buf set to \c NULL and \p buf_len to \c 0. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. */ int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen); /** * \brief Set the list of allowed ciphersuites and the preference * order. First in the list has the highest preference. * * For TLS 1.2, the notion of ciphersuite determines both * the key exchange mechanism and the suite of symmetric * algorithms to be used during and after the handshake. * * For TLS 1.3 (in development), the notion of ciphersuite * only determines the suite of symmetric algorithms to be * used during and after the handshake, while key exchange * mechanisms are configured separately. * * In Mbed TLS, ciphersuites for both TLS 1.2 and TLS 1.3 * are configured via this function. For users of TLS 1.3, * there will be separate API for the configuration of key * exchange mechanisms. * * The list of ciphersuites passed to this function may * contain a mixture of TLS 1.2 and TLS 1.3 ciphersuite * identifiers. This is useful if negotiation of TLS 1.3 * should be attempted, but a fallback to TLS 1.2 would * be tolerated. * * \note By default, the server chooses its preferred * ciphersuite among those that the client supports. If * mbedtls_ssl_conf_preference_order() is called to prefer * the client's preferences, the server instead chooses * the client's preferred ciphersuite among those that * the server supports. * * \warning The ciphersuites array \p ciphersuites is not copied. * It must remain valid for the lifetime of the SSL * configuration \p conf. * * \param conf The SSL configuration to modify. * \param ciphersuites A 0-terminated list of IANA identifiers of supported * ciphersuites, accessible through \c MBEDTLS_TLS_XXX * and \c MBEDTLS_TLS1_3_XXX macros defined in * ssl_ciphersuites.h. */ void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, const int *ciphersuites); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /** * \brief Set the supported key exchange modes for TLS 1.3 connections. * * In contrast to TLS 1.2, the ciphersuite concept in TLS 1.3 does not * include the choice of key exchange mechanism. It is therefore not * covered by the API mbedtls_ssl_conf_ciphersuites(). See the * documentation of mbedtls_ssl_conf_ciphersuites() for more * information on the ciphersuite concept in TLS 1.2 and TLS 1.3. * * The present function is specific to TLS 1.3 and allows users to * configure the set of supported key exchange mechanisms in TLS 1.3. * * \param conf The SSL configuration the change should apply to. * \param kex_modes A bitwise combination of one or more of the following: * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK * This flag enables pure-PSK key exchanges. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL * This flag enables combined PSK-ephemeral key exchanges. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL * This flag enables pure-ephemeral key exchanges. * For convenience, the following pre-defined macros are * available for combinations of the above: * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL * Includes all of pure-PSK, PSK-ephemeral and pure-ephemeral. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL * Includes both pure-PSK and combined PSK-ephemeral * key exchanges, but excludes pure-ephemeral key exchanges. * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL * Includes both pure-ephemeral and combined PSK-ephemeral * key exchanges. * * \note If a PSK-based key exchange mode shall be supported, applications * must also use the APIs mbedtls_ssl_conf_psk() or * mbedtls_ssl_conf_psk_cb() or mbedtls_ssl_conf_psk_opaque() * to configure the PSKs to be used. * * \note If a pure-ephemeral key exchange mode shall be supported, * server-side applications must also provide a certificate via * mbedtls_ssl_conf_own_cert(). * */ void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, const int kex_modes); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0 #define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1 /** * \brief Specify the length of Connection IDs for incoming * encrypted DTLS records, as well as the behaviour * on unexpected CIDs. * * By default, the CID length is set to \c 0, * and unexpected CIDs are silently ignored. * * \param conf The SSL configuration to modify. * \param len The length in Bytes of the CID fields in encrypted * DTLS records using the CID mechanism. This must * not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX. * \param ignore_other_cids This determines the stack's behaviour when * receiving a record with an unexpected CID. * Possible values are: * - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE * In this case, the record is silently ignored. * - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL * In this case, the stack fails with the specific * error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID. * * \note The CID specification allows implementations to either * use a common length for all incoming connection IDs or * allow variable-length incoming IDs. Mbed TLS currently * requires a common length for all connections sharing the * same SSL configuration; this allows simpler parsing of * record headers. * * \return \c 0 on success. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p len * is too large. */ int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len, int ignore_other_cids); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set the X.509 security profile used for verification * * \note The restrictions are enforced for all certificates in the * chain. However, signatures in the handshake are not covered * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). * * \param conf SSL configuration * \param profile Profile to use */ void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, const mbedtls_x509_crt_profile *profile); /** * \brief Set the data required to verify peer certificate * * \note See \c mbedtls_x509_crt_verify() for notes regarding the * parameters ca_chain (maps to trust_ca for that function) * and ca_crl. * * \param conf SSL configuration * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs */ void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl); #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) /** * \brief Set DN hints sent to client in CertificateRequest message * * \note If not set, subject distinguished names (DNs) are taken * from \c mbedtls_ssl_conf_ca_chain() * or \c mbedtls_ssl_set_hs_ca_chain()) * * \param conf SSL configuration * \param crt crt chain whose subject DNs are issuer DNs of client certs * from which the client should select client peer certificate. */ static inline void mbedtls_ssl_conf_dn_hints(mbedtls_ssl_config *conf, const mbedtls_x509_crt *crt) { conf->MBEDTLS_PRIVATE(dn_hints) = crt; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief Set the trusted certificate callback. * * This API allows to register the set of trusted certificates * through a callback, instead of a linked list as configured * by mbedtls_ssl_conf_ca_chain(). * * This is useful for example in contexts where a large number * of CAs are used, and the inefficiency of maintaining them * in a linked list cannot be tolerated. It is also useful when * the set of trusted CAs needs to be modified frequently. * * See the documentation of `mbedtls_x509_crt_ca_cb_t` for * more information. * * \param conf The SSL configuration to register the callback with. * \param f_ca_cb The trusted certificate callback to use when verifying * certificate chains. * \param p_ca_cb The context to be passed to \p f_ca_cb (for example, * a reference to a trusted CA database). * * \note This API is incompatible with mbedtls_ssl_conf_ca_chain(): * Any call to this function overwrites the values set through * earlier calls to mbedtls_ssl_conf_ca_chain() or * mbedtls_ssl_conf_ca_cb(). * * \note This API is incompatible with CA indication in * CertificateRequest messages: A server-side SSL context which * is bound to an SSL configuration that uses a CA callback * configured via mbedtls_ssl_conf_ca_cb(), and which requires * client authentication, will send an empty CA list in the * corresponding CertificateRequest message. * * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain(): * If an SSL context is bound to an SSL configuration which uses * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then * calls to mbedtls_ssl_set_hs_ca_chain() have no effect. * * \note The use of this API disables the use of restartable ECC * during X.509 CRT signature verification (but doesn't affect * other uses). * * \warning This API is incompatible with the use of CRLs. Any call to * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through * earlier calls to mbedtls_ssl_conf_ca_chain(). * * \warning In multi-threaded environments, the callback \p f_ca_cb * must be thread-safe, and it is the user's responsibility * to guarantee this (for example through a mutex * contained in the callback context pointed to by \p p_ca_cb). */ void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ /** * \brief Set own certificate chain and private key * * \note own_cert should contain in order from the bottom up your * certificate chain. The top certificate (self-signed) * can be omitted. * * \note On server, this function can be called multiple times to * provision more than one cert/key pair (eg one ECDSA, one * RSA with SHA-256, one RSA with SHA-1). An adequate * certificate will be selected according to the client's * advertised capabilities. In case multiple certificates are * adequate, preference is given to the one set by the first * call to this function, then second, etc. * * \note On client, only the first call has any effect. That is, * only one client certificate can be provisioned. The * server's preferences in its CertificateRequest message will * be ignored and our only cert will be sent regardless of * whether it matches those preferences - the server can then * decide what it wants to do with it. * * \note The provided \p pk_key needs to match the public key in the * first certificate in \p own_cert, or all handshakes using * that certificate will fail. It is your responsibility * to ensure that; this function will not perform any check. * You may use mbedtls_pk_check_pair() in order to perform * this check yourself, but be aware that this function can * be computationally expensive on some key types. * * \param conf SSL configuration * \param own_cert own public certificate chain * \param pk_key own private key * * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED */ int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) /** * \brief Configure pre-shared keys (PSKs) and their * identities to be used in PSK-based ciphersuites. * * Only one PSK can be registered, through either * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). * If you attempt to register more than one PSK, this function * fails, though this may change in future versions, which * may add support for multiple PSKs. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. * * \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback * takes precedence over a PSK configured by this function. * * \param conf The SSL configuration to register the PSK with. * \param psk The pointer to the pre-shared key to use. * \param psk_len The length of the pre-shared key in bytes. * \param psk_identity The pointer to the pre-shared key identity. * \param psk_identity_len The length of the pre-shared key identity * in bytes. * * \note The PSK and its identity are copied internally and * hence need not be preserved by the caller for the lifetime * of the SSL configuration. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs * can be configured. In this case, the old PSK(s) remain intact. * \return Another negative error code on other kinds of failure. */ int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, const unsigned char *psk_identity, size_t psk_identity_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Configure one or more opaque pre-shared keys (PSKs) and * their identities to be used in PSK-based ciphersuites. * * Only one PSK can be registered, through either * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). * If you attempt to register more than one PSK, this function * fails, though this may change in future versions, which * may add support for multiple PSKs. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. * * \note An opaque PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in * the PSK callback takes precedence over an opaque PSK * configured by this function. * * \param conf The SSL configuration to register the PSK with. * \param psk The identifier of the key slot holding the PSK. * Until \p conf is destroyed or this function is successfully * called again, the key slot \p psk must be populated with a * key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy * allows its use for the key derivation algorithm applied * in the handshake. * \param psk_identity The pointer to the pre-shared key identity. * \param psk_identity_len The length of the pre-shared key identity * in bytes. * * \note The PSK identity hint is copied internally and hence need * not be preserved by the caller for the lifetime of the * SSL configuration. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs * can be configured. In this case, the old PSK(s) remain intact. * \return Another negative error code on other kinds of failure. */ int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, mbedtls_svc_key_id_t psk, const unsigned char *psk_identity, size_t psk_identity_len); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /** * \brief Set the pre-shared Key (PSK) for the current handshake. * * \note This should only be called inside the PSK callback, * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). * * \note A PSK set by this function takes precedence over a PSK * configured by \c mbedtls_ssl_conf_psk(). * * \param ssl The SSL context to configure a PSK for. * \param psk The pointer to the pre-shared key. * \param psk_len The length of the pre-shared key in bytes. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, const unsigned char *psk, size_t psk_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * \brief Set an opaque pre-shared Key (PSK) for the current handshake. * * \note This should only be called inside the PSK callback, * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). * * \note An opaque PSK set by this function takes precedence over an * opaque PSK configured by \c mbedtls_ssl_conf_psk_opaque(). * * \param ssl The SSL context to configure a PSK for. * \param psk The identifier of the key slot holding the PSK. * For the duration of the current handshake, the key slot * must be populated with a key of type * PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its * use for the key derivation algorithm * applied in the handshake. * * \return \c 0 if successful. * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t psk); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the PSK callback (server-side only). * * If set, the PSK callback is called for each * handshake where a PSK-based ciphersuite was negotiated. * The caller provides the identity received and wants to * receive the actual PSK data and length. * * The callback has the following parameters: * - \c void*: The opaque pointer \p p_psk. * - \c mbedtls_ssl_context*: The SSL context to which * the operation applies. * - \c const unsigned char*: The PSK identity * selected by the client. * - \c size_t: The length of the PSK identity * selected by the client. * * If a valid PSK identity is found, the callback should use * \c mbedtls_ssl_set_hs_psk() or * \c mbedtls_ssl_set_hs_psk_opaque() * on the SSL context to set the correct PSK and return \c 0. * Any other return value will result in a denied PSK identity. * * \note A dynamic PSK (i.e. set by the PSK callback) takes * precedence over a static PSK (i.e. set by * \c mbedtls_ssl_conf_psk() or * \c mbedtls_ssl_conf_psk_opaque()). * This means that if you set a PSK callback using this * function, you don't need to set a PSK using * \c mbedtls_ssl_conf_psk() or * \c mbedtls_ssl_conf_psk_opaque()). * * \param conf The SSL configuration to register the callback with. * \param f_psk The callback for selecting and setting the PSK based * in the PSK identity chosen by the client. * \param p_psk A pointer to an opaque structure to be passed to * the callback, for example a PSK store. */ void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_psk); #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) /** * \brief Set the Diffie-Hellman public P and G values * from big-endian binary presentations. * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) * * \param conf SSL configuration * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form * \param P_len Length of DHM modulus * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form * \param G_len Length of DHM generator * * \return 0 if successful */ int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf, const unsigned char *dhm_P, size_t P_len, const unsigned char *dhm_G, size_t G_len); /** * \brief Set the Diffie-Hellman public P and G values, * read from existing context (server-side only) * * \param conf SSL configuration * \param dhm_ctx Diffie-Hellman-Merkle context * * \return 0 if successful */ int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx); #endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) /** * \brief Set the minimum length for Diffie-Hellman parameters. * (Client-side only.) * (Default: 1024 bits.) * * \param conf SSL configuration * \param bitlen Minimum bit length of the DHM prime */ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, unsigned int bitlen); #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_ECP_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the allowed curves in order of preference. * * On server: this only affects selection of the ECDHE curve; * the curves used for ECDH and ECDSA are determined by the * list of available certificates instead. * * On client: this affects the list of curves offered for any * use. The server can override our preference order. * * Both sides: limits the set of curves accepted for use in * ECDHE and in the peer's end-entity certificate. * * \deprecated Superseded by mbedtls_ssl_conf_groups(). * * \note This has no influence on which curves are allowed inside the * certificate chains, see \c mbedtls_ssl_conf_cert_profile() * for that. For the end-entity certificate however, the key * will be accepted only if it is allowed both by this list * and by the cert profile. * * \note This list should be ordered by decreasing preference * (preferred curve first). * * \note The default list is the same set of curves that * #mbedtls_x509_crt_profile_default allows, plus * ECDHE-only curves selected according to the same criteria. * The order favors curves with the lowest resource usage. * * \note New minor versions of Mbed TLS may extend this list, * for example if new curves are added to the library. * New minor versions of Mbed TLS will not remove items * from this list unless serious security concerns require it. * New minor versions of Mbed TLS may change the order in * keeping with the general principle of favoring the lowest * resource usage. * * \param conf SSL configuration * \param curves Ordered list of allowed curves, * terminated by MBEDTLS_ECP_DP_NONE. */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, const mbedtls_ecp_group_id *curves); #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ /** * \brief Set the allowed groups in order of preference. * * On server: This only affects the choice of key agreement mechanism * * On client: this affects the list of groups offered for any * use. The server can override our preference order. * * Both sides: limits the set of groups accepted for use in * key sharing. * * \note This function replaces the deprecated mbedtls_ssl_conf_curves(), * which only allows ECP curves to be configured. * * \note The most recent invocation of either mbedtls_ssl_conf_curves() * or mbedtls_ssl_conf_groups() nullifies all previous invocations * of both. * * \note This list should be ordered by decreasing preference * (preferred group first). * * \note When this function is not called, a default list is used, * consisting of all supported curves at 255 bits and above, * and all supported finite fields at 2048 bits and above. * The order favors groups with the lowest resource usage. * * \note New minor versions of Mbed TLS will not remove items * from the default list unless serious security concerns require it. * New minor versions of Mbed TLS may change the order in * keeping with the general principle of favoring the lowest * resource usage. * * \param conf SSL configuration * \param groups List of allowed groups ordered by preference, terminated by 0. * Must contain valid IANA NamedGroup IDs (provided via either an integer * or using MBEDTLS_TLS1_3_NAMED_GROUP_XXX macros). */ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, const uint16_t *groups); #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) /** * \brief Set the allowed hashes for signatures during the handshake. * * \note This only affects which hashes are offered and can be used * for signatures during the handshake. Hashes for message * authentication and the TLS PRF are controlled by the * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes * used for certificate signature are controlled by the * verification profile, see \c mbedtls_ssl_conf_cert_profile(). * * \deprecated Superseded by mbedtls_ssl_conf_sig_algs(). * * \note This list should be ordered by decreasing preference * (preferred hash first). * * \note By default, all supported hashes whose length is at least * 256 bits are allowed. This is the same set as the default * for certificate verification * (#mbedtls_x509_crt_profile_default). * The preference order is currently unspecified and may * change in future versions. * * \note New minor versions of Mbed TLS may extend this list, * for example if new curves are added to the library. * New minor versions of Mbed TLS will not remove items * from this list unless serious security concerns require it. * * \param conf SSL configuration * \param hashes Ordered list of allowed signature hashes, * terminated by \c MBEDTLS_MD_NONE. */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, const int *hashes); #endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ /** * \brief Configure allowed signature algorithms for use in TLS * * \param conf The SSL configuration to use. * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms, * terminated by #MBEDTLS_TLS1_3_SIG_NONE. The list must remain * available throughout the lifetime of the conf object. * - For TLS 1.3, values of \c MBEDTLS_TLS1_3_SIG_XXXX should be * used. * - For TLS 1.2, values should be given as * "(HashAlgorithm << 8) | SignatureAlgorithm". */ void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, const uint16_t *sig_algs); #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Set or reset the hostname to check against the received * server certificate. It sets the ServerName TLS extension, * too, if that extension is enabled. (client-side only) * * \param ssl SSL context * \param hostname the server hostname, may be NULL to clear hostname * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. * * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on * too long input hostname. * * Hostname set to the one provided on success (cleared * when NULL). On allocation failure hostname is cleared. * On too long input failure, old hostname is unchanged. */ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname); /** * \brief Get the hostname that checked against the received * server certificate. It is used to set the ServerName * TLS extension, too, if that extension is enabled. * (client-side only) * * \param ssl SSL context * * \return const pointer to the hostname value */ static inline const char *mbedtls_ssl_get_hostname(mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(hostname); } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /** * \brief Retrieve SNI extension value for the current handshake. * Available in \c f_cert_cb of \c mbedtls_ssl_conf_cert_cb(), * this is the same value passed to \c f_sni callback of * \c mbedtls_ssl_conf_sni() and may be used instead of * \c mbedtls_ssl_conf_sni(). * * \param ssl SSL context * \param name_len pointer into which to store length of returned value. * 0 if SNI extension is not present or not yet processed. * * \return const pointer to SNI extension value. * - value is valid only when called in \c f_cert_cb * registered with \c mbedtls_ssl_conf_cert_cb(). * - value is NULL if SNI extension is not present. * - value is not '\0'-terminated. Use \c name_len for len. * - value must not be freed. */ const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, size_t *name_len); /** * \brief Set own certificate and key for the current handshake * * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within * the SNI callback or the certificate selection callback. * * \note Passing null \c own_cert clears the certificate list for * the current handshake. * * \param ssl SSL context * \param own_cert own public certificate chain * \param pk_key own private key * * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED */ int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key); /** * \brief Set the data required to verify peer certificate for the * current handshake * * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) * \param ca_crl trusted CA CRLs */ void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl); #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) /** * \brief Set DN hints sent to client in CertificateRequest message * * \note Same as \c mbedtls_ssl_conf_dn_hints() but for use within * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param crt crt chain whose subject DNs are issuer DNs of client certs * from which the client should select client peer certificate. */ void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, const mbedtls_x509_crt *crt); #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ /** * \brief Set authmode for the current handshake. * * \note Same as \c mbedtls_ssl_conf_authmode() but for use within * the SNI callback or the certificate selection callback. * * \param ssl SSL context * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or * MBEDTLS_SSL_VERIFY_REQUIRED */ void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, int authmode); /** * \brief Set server side ServerName TLS extension callback * (optional, server-side only). * * If set, the ServerName callback is called whenever the * server receives a ServerName TLS extension from the client * during a handshake. The ServerName callback has the * following parameters: (void *parameter, mbedtls_ssl_context *ssl, * const unsigned char *hostname, size_t len). If a suitable * certificate is found, the callback must set the * certificate(s) and key(s) to use with \c * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), * and may optionally adjust the CA and associated CRL with \c * mbedtls_ssl_set_hs_ca_chain() as well as the client * authentication mode with \c mbedtls_ssl_set_hs_authmode(), * then must return 0. If no matching name is found, the * callback may return non-zero to abort the handshake. * * \param conf SSL configuration * \param f_sni verification function * \param p_sni verification parameter */ void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_sni); #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /** * \brief Set the EC J-PAKE password for current handshake. * * \note An internal copy is made, and destroyed as soon as the * handshake is completed, or when the SSL context is reset or * freed. * * \note The SSL context needs to be already set up. The right place * to call this function is between \c mbedtls_ssl_setup() or * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). * Password cannot be empty (see RFC 8236). * * \param ssl SSL context * \param pw EC J-PAKE password (pre-shared secret). It cannot be empty * \param pw_len length of pw in bytes * * \return 0 on success, or a negative error code. */ int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len); /** * \brief Set the EC J-PAKE opaque password for current handshake. * * \note The key must remain valid until the handshake is over. * * \note The SSL context needs to be already set up. The right place * to call this function is between \c mbedtls_ssl_setup() or * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). * * \param ssl SSL context * \param pwd EC J-PAKE opaque password * * \return 0 on success, or a negative error code. */ int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t pwd); #endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) /** * \brief Set the supported Application Layer Protocols. * * \param conf SSL configuration * \param protos Pointer to a NULL-terminated list of supported protocols, * in decreasing preference order. The pointer to the list is * recorded by the library for later reference as required, so * the lifetime of the table must be at least as long as the * lifetime of the SSL configuration structure. * * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. */ int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos); /** * \brief Get the name of the negotiated Application Layer Protocol. * This function should be called after the handshake is * completed. * * \param ssl SSL context * * \return Protocol name, or NULL if no protocol was negotiated. */ const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) #if defined(MBEDTLS_DEBUG_C) static inline const char *mbedtls_ssl_get_srtp_profile_as_string(mbedtls_ssl_srtp_profile profile) { switch (profile) { case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: return "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80"; case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: return "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32"; case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: return "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80"; case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: return "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32"; default: break; } return ""; } #endif /* MBEDTLS_DEBUG_C */ /** * \brief Manage support for mki(master key id) value * in use_srtp extension. * MKI is an optional part of SRTP used for key management * and re-keying. See RFC3711 section 3.1 for details. * The default value is * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED. * * \param conf The SSL configuration to manage mki support. * \param support_mki_value Enable or disable mki usage. Values are * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED * or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED. */ void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf, int support_mki_value); /** * \brief Set the supported DTLS-SRTP protection profiles. * * \param conf SSL configuration * \param profiles Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated * supported protection profiles * in decreasing preference order. * The pointer to the list is recorded by the library * for later reference as required, so the lifetime * of the table must be at least as long as the lifetime * of the SSL configuration structure. * The list must not hold more than * MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements * (excluding the terminating MBEDTLS_TLS_SRTP_UNSET). * * \return 0 on success * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of * protection profiles is incorrect. */ int mbedtls_ssl_conf_dtls_srtp_protection_profiles (mbedtls_ssl_config *conf, const mbedtls_ssl_srtp_profile *profiles); /** * \brief Set the mki_value for the current DTLS-SRTP session. * * \param ssl SSL context to use. * \param mki_value The MKI value to set. * \param mki_len The length of the MKI value. * * \note This function is relevant on client side only. * The server discovers the mki value during handshake. * A mki value set on server side using this function * is ignored. * * \return 0 on success * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE */ int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl, unsigned char *mki_value, uint16_t mki_len); /** * \brief Get the negotiated DTLS-SRTP information: * Protection profile and MKI value. * * \warning This function must be called after the handshake is * completed. The value returned by this function must * not be trusted or acted upon before the handshake completes. * * \param ssl The SSL context to query. * \param dtls_srtp_info The negotiated DTLS-SRTP information: * - Protection profile in use. * A direct mapping of the iana defined value for protection * profile on an uint16_t. http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml * #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated * or peer's Hello packet was not parsed yet. * - mki size and value( if size is > 0 ). */ void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl, mbedtls_dtls_srtp_info *dtls_srtp_info); #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the maximum supported version sent from the client side * and/or accepted at the server side. * * See also the documentation of mbedtls_ssl_conf_min_version(). * * \note This ignores ciphersuites from higher versions. * * \note This function is deprecated and has been replaced by * \c mbedtls_ssl_conf_max_tls_version(). * * \param conf SSL configuration * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) * \param minor Minor version number * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Set the maximum supported version sent from the client side * and/or accepted at the server side. * * \note After the handshake, you can call * mbedtls_ssl_get_version_number() to see what version was * negotiated. * * \param conf SSL configuration * \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version) * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) */ static inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf, mbedtls_ssl_protocol_version tls_version) { conf->MBEDTLS_PRIVATE(max_tls_version) = tls_version; } #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the minimum accepted SSL/TLS protocol version * * \note By default, all supported versions are accepted. * Future versions of the library may disable older * protocol versions by default if they become deprecated. * * \note The following versions are supported (if enabled at * compile time): * - (D)TLS 1.2: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, * \p minor = #MBEDTLS_SSL_MINOR_VERSION_3 * - TLS 1.3: \p major = #MBEDTLS_SSL_MAJOR_VERSION_3, * \p minor = #MBEDTLS_SSL_MINOR_VERSION_4 * * Note that the numbers in the constant names are the * TLS internal protocol numbers, and the minor versions * differ by one from the human-readable versions! * * \note Input outside of the SSL_MAX_XXXXX_VERSION and * SSL_MIN_XXXXX_VERSION range is ignored. * * \note After the handshake, you can call * mbedtls_ssl_get_version_number() to see what version was * negotiated. * * \note This function is deprecated and has been replaced by * \c mbedtls_ssl_conf_min_tls_version(). * * \param conf SSL configuration * \param major Major version number (#MBEDTLS_SSL_MAJOR_VERSION_3) * \param minor Minor version number * (#MBEDTLS_SSL_MINOR_VERSION_3 for (D)TLS 1.2, * #MBEDTLS_SSL_MINOR_VERSION_4 for TLS 1.3) */ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor); #endif /* MBEDTLS_DEPRECATED_REMOVED */ /** * \brief Set the minimum supported version sent from the client side * and/or accepted at the server side. * * \note After the handshake, you can call * mbedtls_ssl_get_version_number() to see what version was * negotiated. * * \param conf SSL configuration * \param tls_version TLS protocol version number (\c mbedtls_ssl_protocol_version) * (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid) */ static inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf, mbedtls_ssl_protocol_version tls_version) { conf->MBEDTLS_PRIVATE(min_tls_version) = tls_version; } #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) /** * \brief Enable or disable Encrypt-then-MAC * (Default: MBEDTLS_SSL_ETM_ENABLED) * * \note This should always be enabled, it is a security * improvement, and should not cause any interoperability * issue (used only if the peer supports it too). * * \param conf SSL configuration * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED */ void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm); #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) /** * \brief Enable or disable Extended Master Secret negotiation. * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) * * \note This should always be enabled, it is a security fix to the * protocol, and should not cause any interoperability issue * (used only if the peer supports it too). * * \param conf SSL configuration * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED */ void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems); #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Whether to send a list of acceptable CAs in * CertificateRequest messages. * (Default: do send) * * \param conf SSL configuration * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED */ void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, char cert_req_ca_list); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate. * (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and * #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes) * (Server: set maximum fragment length to emit, * usually negotiated by the client during handshake) * (Client: set maximum fragment length to emit *and* * negotiate with the server during handshake) * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) * * \note On the client side, the maximum fragment length extension * *will not* be used, unless the maximum fragment length has * been set via this function to a value different than * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. * * \note With TLS, this currently only affects ApplicationData (sent * with \c mbedtls_ssl_read()), not handshake messages. * With DTLS, this affects both ApplicationData and handshake. * * \note This sets the maximum length for a record's payload, * excluding record overhead that will be added to it, see * \c mbedtls_ssl_get_record_expansion(). * * \note For DTLS, it is also possible to set a limit for the total * size of datagrams passed to the transport layer, including * record overhead, see \c mbedtls_ssl_set_mtu(). * * \param conf SSL configuration * \param mfl_code Code for maximum fragment length (allowed values: * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) * * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA */ int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Pick the ciphersuites order according to the second parameter * in the SSL Server module (MBEDTLS_SSL_SRV_C). * (Default, if never called: MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER) * * \param conf SSL configuration * \param order Server or client (MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER * or MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) */ void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_CLI_C) /** * \brief Enable / Disable session tickets (client only). * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) * * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). * * \param conf SSL configuration * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) */ void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets); #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_3) /** * \brief Number of NewSessionTicket messages for the server to send * after handshake completion. * * \note The default value is * \c MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS. * * \note In case of a session resumption, this setting only partially apply. * At most one ticket is sent in that case to just renew the pool of * tickets of the client. The rationale is to avoid the number of * tickets on the server to become rapidly out of control when the * server has the same configuration for all its connection instances. * * \param conf SSL configuration * \param num_tickets Number of NewSessionTicket. * */ void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, uint16_t num_tickets); #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3*/ #if defined(MBEDTLS_SSL_RENEGOTIATION) /** * \brief Enable / Disable renegotiation support for connection when * initiated by peer * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) * * \warning It is recommended to always disable renegotiation unless you * know you need it and you know what you're doing. In the * past, there have been several issues associated with * renegotiation or a poor understanding of its properties. * * \note Server-side, enabling renegotiation also makes the server * susceptible to a resource DoS by a malicious client. * * \param conf SSL configuration * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or * MBEDTLS_SSL_RENEGOTIATION_DISABLED) */ void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * \brief Prevent or allow legacy renegotiation. * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) * * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to * be established even if the peer does not support * secure renegotiation, but does not allow renegotiation * to take place if not secure. * (Interoperable and secure option) * * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations * with non-upgraded peers. Allowing legacy renegotiation * makes the connection vulnerable to specific man in the * middle attacks. (See RFC 5746) * (Most interoperable and least secure option) * * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections * if peer does not support secure renegotiation. Results * in interoperability issues with non-upgraded peers * that do not support renegotiation altogether. * (Most secure option, interoperability issues) * * \param conf SSL configuration * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, * SSL_ALLOW_LEGACY_RENEGOTIATION or * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) */ void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy); #if defined(MBEDTLS_SSL_RENEGOTIATION) /** * \brief Enforce renegotiation requests. * (Default: enforced, max_records = 16) * * When we request a renegotiation, the peer can comply or * ignore the request. This function allows us to decide * whether to enforce our renegotiation requests by closing * the connection if the peer doesn't comply. * * However, records could already be in transit from the peer * when the request is emitted. In order to increase * reliability, we can accept a number of records before the * expected handshake records. * * The optimal value is highly dependent on the specific usage * scenario. * * \note With DTLS and server-initiated renegotiation, the * HelloRequest is retransmitted every time mbedtls_ssl_read() times * out or receives Application Data, until: * - max_records records have beens seen, if it is >= 0, or * - the number of retransmits that would happen during an * actual handshake has been reached. * Please remember the request might be lost a few times * if you consider setting max_records to a really low value. * * \warning On client, the grace period can only happen during * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() * which always behave as if max_record was 0. The reason is, * if we receive application data from the server, we need a * place to write it, which only happens during mbedtls_ssl_read(). * * \param conf SSL configuration * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to * enforce renegotiation, or a non-negative value to enforce * it but allow for a grace period of max_records records. */ void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records); /** * \brief Set record counter threshold for periodic renegotiation. * (Default: 2^48 - 1) * * Renegotiation is automatically triggered when a record * counter (outgoing or incoming) crosses the defined * threshold. The default value is meant to prevent the * connection from being closed when the counter is about to * reached its maximal value (it is not allowed to wrap). * * Lower values can be used to enforce policies such as "keys * must be refreshed every N packets with cipher X". * * The renegotiation period can be disabled by setting * conf->disable_renegotiation to * MBEDTLS_SSL_RENEGOTIATION_DISABLED. * * \note When the configured transport is * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, * the maximum renegotiation period is 2^64 - 1. * * \param conf SSL configuration * \param period The threshold value: a big-endian 64-bit number. */ void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, const unsigned char period[8]); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * \brief Check if there is data already read from the * underlying transport but not yet processed. * * \param ssl SSL context * * \return 0 if nothing's pending, 1 otherwise. * * \note This is different in purpose and behaviour from * \c mbedtls_ssl_get_bytes_avail in that it considers * any kind of unprocessed data, not only unread * application data. If \c mbedtls_ssl_get_bytes * returns a non-zero value, this function will * also signal pending data, but the converse does * not hold. For example, in DTLS there might be * further records waiting to be processed from * the current underlying transport's datagram. * * \note If this function returns 1 (data pending), this * does not imply that a subsequent call to * \c mbedtls_ssl_read will provide any data; * e.g., the unprocessed data might turn out * to be an alert or a handshake message. * * \note This function is useful in the following situation: * If the SSL/TLS module successfully returns from an * operation - e.g. a handshake or an application record * read - and you're awaiting incoming data next, you * must not immediately idle on the underlying transport * to have data ready, but you need to check the value * of this function first. The reason is that the desired * data might already be read but not yet processed. * If, in contrast, a previous call to the SSL/TLS module * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary * to call this function, as the latter error code entails * that all internal data has been processed. * */ int mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl); /** * \brief Return the number of application data bytes * remaining to be read from the current record. * * \param ssl SSL context * * \return How many bytes are available in the application * data record read buffer. * * \note When working over a datagram transport, this is * useful to detect the current datagram's boundary * in case \c mbedtls_ssl_read has written the maximal * amount of data fitting into the input buffer. * */ size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl); /** * \brief Return the result of the certificate verification * * \param ssl The SSL context to use. * * \return \c 0 if the certificate verification was successful. * \return \c -1u if the result is not available. This may happen * e.g. if the handshake aborts early, or a verification * callback returned a fatal error. * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. */ uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl); /** * \brief Return the id of the current ciphersuite * * \param ssl SSL context * * \return a ciphersuite id */ int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl); /** * \brief Return the name of the current ciphersuite * * \param ssl SSL context * * \return a string containing the ciphersuite name */ const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl); /** * \brief Return the (D)TLS protocol version negotiated in the * given connection. * * \note If you call this function too early during the initial * handshake, before the two sides have agreed on a version, * this function returns #MBEDTLS_SSL_VERSION_UNKNOWN. * * \param ssl The SSL context to query. * \return The negotiated protocol version. */ static inline mbedtls_ssl_protocol_version mbedtls_ssl_get_version_number( const mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(tls_version); } /** * \brief Return the current TLS version * * \param ssl SSL context * * \return a string containing the TLS version */ const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl); /** * \brief Return the (maximum) number of bytes added by the record * layer: header + encryption/MAC overhead (inc. padding) * * \param ssl SSL context * * \return Current maximum record expansion in bytes */ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl); /** * \brief Return the current maximum outgoing record payload in bytes. * * \note The logic to determine the maximum outgoing record payload is * version-specific. It takes into account various factors, such as * the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions * such as the max fragment length or record size limit extension if * used, and for DTLS the path MTU as configured and current * record expansion. * * \note With DTLS, \c mbedtls_ssl_write() will return an error if * called with a larger length value. * With TLS, \c mbedtls_ssl_write() will fragment the input if * necessary and return the number of bytes written; it is up * to the caller to call \c mbedtls_ssl_write() again in * order to send the remaining bytes if any. * * \sa mbedtls_ssl_get_max_out_record_payload() * \sa mbedtls_ssl_get_record_expansion() * * \param ssl SSL context * * \return Current maximum payload for an outgoing record, * or a negative error code. */ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl); /** * \brief Return the current maximum incoming record payload in bytes. * * \note The logic to determine the maximum incoming record payload is * version-specific. It takes into account various factors, such as * the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN, extensions * such as the max fragment length extension or record size limit * extension if used, and the current record expansion. * * \sa mbedtls_ssl_set_mtu() * \sa mbedtls_ssl_get_max_in_record_payload() * \sa mbedtls_ssl_get_record_expansion() * * \param ssl SSL context * * \return Current maximum payload for an incoming record, * or a negative error code. */ int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl); #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * \brief Return the peer certificate from the current connection. * * \param ssl The SSL context to use. This must be initialized and setup. * * \return The current peer certificate, if available. * The returned certificate is owned by the SSL context and * is valid only until the next call to the SSL API. * \return \c NULL if no peer certificate is available. This might * be because the chosen ciphersuite doesn't use CRTs * (PSK-based ciphersuites, for example), or because * #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled, * allowing the stack to free the peer's CRT to save memory. * * \note For one-time inspection of the peer's certificate during * the handshake, consider registering an X.509 CRT verification * callback through mbedtls_ssl_conf_verify() instead of calling * this function. Using mbedtls_ssl_conf_verify() also comes at * the benefit of allowing you to influence the verification * process, for example by masking expected and tolerated * verification failures. * * \warning You must not use the pointer returned by this function * after any further call to the SSL API, including * mbedtls_ssl_read() and mbedtls_ssl_write(); this is * because the pointer might change during renegotiation, * which happens transparently to the user. * If you want to use the certificate across API calls, * you must make a copy. */ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) /** * \brief Export a session in order to resume it later. * * \param ssl The SSL context representing the connection for which to * to export a session structure for later resumption. * \param session The target structure in which to store the exported session. * This must have been initialized with mbedtls_ssl_session_init() * but otherwise be unused. * * \note This function can handle a variety of mechanisms for session * resumption: For TLS 1.2, both session ID-based resumption and * ticket-based resumption will be considered. For TLS 1.3, * once implemented, sessions equate to tickets, and calling * this function multiple times will export the available * tickets one a time until no further tickets are available, * in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will * be returned. * * \note Calling this function multiple times will only be useful * once TLS 1.3 is supported. For TLS 1.2 connections, this * function should be called at most once. * * \return \c 0 if successful. In this case, \p session can be used for * session resumption by passing it to mbedtls_ssl_set_session(), * and serialized for storage via mbedtls_ssl_session_save(). * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session * is available for export. * This error is a non-fatal, and has no observable effect on * the SSL context or the destination session. * \return Another negative error code on other kinds of failure. * * \sa mbedtls_ssl_set_session() * \sa mbedtls_ssl_session_save() */ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session); #endif /* MBEDTLS_SSL_CLI_C */ /** * \brief Perform the SSL handshake * * \param ssl SSL context * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous * operation is in progress (see * mbedtls_ssl_conf_async_private_cb()) - in this case you * must call this function again when the operation is ready. * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use * and the client did not demonstrate reachability yet - in * this case you must stop using the context (see below). * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as * defined in RFC 8446 (TLS 1.3 specification), has been * received as part of the handshake. This is server specific * and may occur only if the early data feature has been * enabled on server (see mbedtls_ssl_conf_early_data() * documentation). You must call mbedtls_ssl_read_early_data() * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * * \warning If this function returns something other than * \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current * connection must be closed. * * \note If DTLS is in use, then you may choose to handle * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging * purposes, as it is an expected return value rather than an * actual error, but you still need to reset/free the context. * * \note Remarks regarding event-driven DTLS: * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. This is not true for a successful handshake, * in which case the datagram of the underlying transport that is * currently being processed might or might not contain further * DTLS records. * * \note If the context is configured to allow TLS 1.3, or if * #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. */ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl); /** * \brief After calling mbedtls_ssl_handshake() to start the SSL * handshake you can call this function to check whether the * handshake is over for a given SSL context. This function * should be also used to determine when to stop calling * mbedtls_handshake_step() for that context. * * \param ssl SSL context * * \return \c 1 if handshake is over, \c 0 if it is still ongoing. */ static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl) { return ssl->MBEDTLS_PRIVATE(state) >= MBEDTLS_SSL_HANDSHAKE_OVER; } /** * \brief Perform a single step of the SSL handshake * * \note The state of the context (ssl->state) will be at * the next state after this function returns \c 0. Do not * call this function if mbedtls_ssl_is_handshake_over() * returns \c 1. * * \warning Whilst in the past you may have used direct access to the * context state (ssl->state) in order to ascertain when to * stop calling this function and although you can still do * so with something like ssl->MBEDTLS_PRIVATE(state) or by * defining MBEDTLS_ALLOW_PRIVATE_ACCESS, this is now * considered deprecated and could be broken in any future * release. If you still find you have good reason for such * direct access, then please do contact the team to explain * this (raise an issue or post to the mailing list), so that * we can add a solution to your problem that will be * guaranteed to work in the future. * * \param ssl SSL context * * \return See mbedtls_ssl_handshake(). * * \warning If this function returns something other than \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, you must stop using * the SSL context for reading or writing, and either free it * or call \c mbedtls_ssl_session_reset() on it before * re-using it for a new connection; the current connection * must be closed. */ int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_RENEGOTIATION) /** * \brief Initiate an SSL renegotiation on the running connection. * Client: perform the renegotiation right now. * Server: request renegotiation, which will be performed * during the next call to mbedtls_ssl_read() if honored by * client. * * \param ssl SSL context * * \return 0 if successful, or any mbedtls_ssl_handshake() return * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't * happen during a renegotiation. * * \warning If this function returns something other than \c 0, * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using * the SSL context for reading or writing, and either free it * or call \c mbedtls_ssl_session_reset() on it before * re-using it for a new connection; the current connection * must be closed. * */ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RENEGOTIATION */ /** * \brief Read at most 'len' application data bytes * * \param ssl SSL context * \param buf buffer that will hold the data * \param len maximum number of bytes to read * * \return The (positive) number of bytes read if successful. * \return \c 0 if the read end of the underlying transport was closed * without sending a CloseNotify beforehand, which might happen * because of various reasons (internal error of an underlying * stack, non-conformant peer not sending a CloseNotify and * such) - in this case you must stop using the context * (see below). * \return #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying * transport is still functional, but the peer has * acknowledged to not send anything anymore. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous * operation is in progress (see * mbedtls_ssl_conf_async_private_cb()) - in this case you * must call this function again when the operation is ready. * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server * side of a DTLS connection and the client is initiating a * new connection using the same source port. See below. * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as * defined in RFC 8446 (TLS 1.3 specification), has been * received as part of the handshake. This is server specific * and may occur only if the early data feature has been * enabled on server (see mbedtls_ssl_conf_early_data() * documentation). You must call mbedtls_ssl_read_early_data() * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * * \warning If this function returns something other than * a positive value, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current * connection must be closed. * * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait * for the client to resend a ClientHello, or directly * continue with \c mbedtls_ssl_handshake() with the same * context (as it has been reset internally). Either way, you * must make sure this is seen by the application as a new * connection: application state, if any, should be reset, and * most importantly the identity of the client must be checked * again. WARNING: not validating the identity of the client * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! * * \note Remarks regarding event-driven DTLS: * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was * initially available on the underlying transport, as this data may have * been only e.g. duplicated messages or a renegotiation request. * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even * when reacting to an incoming-data event from the underlying transport. * - On success, the datagram of the underlying transport that is currently * being processed may contain further DTLS records. You should call * \c mbedtls_ssl_check_pending to check for remaining records. * */ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); /** * \brief Try to write exactly 'len' application data bytes * * \warning This function will do partial writes in some cases. If the * return value is non-negative but less than length, the * function must be called again with updated arguments: * buf + ret, len - ret (if ret is the return value) until * it returns a value equal to the last 'len' argument. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * * \return The (non-negative) number of bytes actually written if * successful (may be less than \p len). * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous * operation is in progress (see * mbedtls_ssl_conf_async_private_cb()) - in this case you * must call this function again when the operation is ready. * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic * operation is in progress (see mbedtls_ecp_set_max_ops()) - * in this case you must call this function again to complete * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as * defined in RFC 8446 (TLS 1.3 specification), has been * received as part of the handshake. This is server specific * and may occur only if the early data feature has been * enabled on server (see mbedtls_ssl_conf_early_data() * documentation). You must call mbedtls_ssl_read_early_data() * to read the early data before resuming the handshake. * \return Another SSL error code - in this case you must stop using * the context (see below). * * \warning If this function returns something other than * a non-negative value, * #MBEDTLS_ERR_SSL_WANT_READ, * #MBEDTLS_ERR_SSL_WANT_WRITE, * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, * you must stop using the SSL context for reading or writing, * and either free it or call \c mbedtls_ssl_session_reset() * on it before re-using it for a new connection; the current * connection must be closed. * * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, * until it returns a value greater than or equal to 0. When * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be * some partial data in the output buffer, however this is not * yet sent. * * \note If the requested length is greater than the maximum * fragment length (either the built-in limit or the one set * or negotiated with the peer), then: * - with TLS, less bytes than requested are written. * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. * \c mbedtls_ssl_get_max_out_record_payload() may be used to * query the active maximum fragment length. * * \note Attempting to write 0 bytes will result in an empty TLS * application record being sent. */ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); /** * \brief Send an alert message * * \param ssl SSL context * \param level The alert level of the message * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) * \param message The alert message (SSL_ALERT_MSG_*) * * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using * the SSL context for reading or writing, and either free it or * call \c mbedtls_ssl_session_reset() on it before re-using it * for a new connection; the current connection must be closed. */ int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message); /** * \brief Notify the peer that the connection is being closed * * \param ssl SSL context * * \return 0 if successful, or a specific SSL error code. * * \note If this function returns something other than 0 or * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using * the SSL context for reading or writing, and either free it or * call \c mbedtls_ssl_session_reset() on it before re-using it * for a new connection; the current connection must be closed. */ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_EARLY_DATA) #if defined(MBEDTLS_SSL_SRV_C) /** * \brief Read at most 'len' bytes of early data * * \note This API is server specific. * * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. * IMPORTANT NOTE from section 2.3 of the specification: * * The security properties for 0-RTT data are weaker than * those for other kinds of TLS data. Specifically: * - This data is not forward secret, as it is encrypted * solely under keys derived using the offered PSK. * - There are no guarantees of non-replay between connections. * Protection against replay for ordinary TLS 1.3 1-RTT data * is provided via the server's Random value, but 0-RTT data * does not depend on the ServerHello and therefore has * weaker guarantees. This is especially relevant if the * data is authenticated either with TLS client * authentication or inside the application protocol. The * same warnings apply to any use of the * early_exporter_master_secret. * * \warning Mbed TLS does not implement any of the anti-replay defenses * defined in section 8 of the TLS 1.3 specification: * single-use of tickets or ClientHello recording within a * given time window. * * \note This function is used in conjunction with * mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), * mbedtls_ssl_read() and mbedtls_ssl_write() to read early * data when these functions return * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA. * * \param ssl SSL context, it must have been initialized and set up. * \param buf buffer that will hold the data * \param len maximum number of bytes to read * * \return The (positive) number of bytes read if successful. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. * \return #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA if it is not * possible to read early data for the SSL context \p ssl. Note * that this function is intended to be called for an SSL * context \p ssl only after a call to mbedtls_ssl_handshake(), * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or * mbedtls_ssl_write() for \p ssl that has returned * #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA. */ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len); #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /** * \brief Try to write exactly 'len' application data bytes while * performing the handshake (early data). * * \warning Early data is defined in the TLS 1.3 specification, RFC 8446. * IMPORTANT NOTE from section 2.3 of the specification: * * The security properties for 0-RTT data are weaker than * those for other kinds of TLS data. Specifically: * - This data is not forward secret, as it is encrypted * solely under keys derived using the offered PSK. * - There are no guarantees of non-replay between connections. * Protection against replay for ordinary TLS 1.3 1-RTT data * is provided via the server's Random value, but 0-RTT data * does not depend on the ServerHello and therefore has * weaker guarantees. This is especially relevant if the * data is authenticated either with TLS client * authentication or inside the application protocol. The * same warnings apply to any use of the * early_exporter_master_secret. * * \note This function behaves mainly as mbedtls_ssl_write(). The * specification of mbedtls_ssl_write() relevant to TLS 1.3 * (thus not the parts specific to (D)TLS1.2) applies to this * function and the present documentation is mainly restricted * to the differences with mbedtls_ssl_write(). One noticeable * difference though is that mbedtls_ssl_write() aims to * complete the handshake before to write application data * while mbedtls_ssl_write_early() aims to drive the handshake * just past the point where it is not possible to send early * data anymore. * * \param ssl SSL context * \param buf buffer holding the data * \param len how many bytes must be written * * \return The (non-negative) number of bytes actually written if * successful (may be less than \p len). * * \return One additional specific error code compared to * mbedtls_ssl_write(): * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA. * * #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it * is not possible to write early data for the SSL context * \p ssl. * * It may have been possible and it is not possible * anymore because the client received the server Finished * message, the server rejected early data or the maximum * number of allowed early data for the PSK in use has been * reached. * * It may never have been possible and will never be possible * for the SSL context \p ssl because the use of early data * is disabled for that context or more generally the context * is not suitably configured to enable early data or the first * call to the function was done while the handshake was * already completed. * * It is not possible to write early data for the SSL context * \p ssl and any subsequent call to this API will return this * error code. But this does not preclude for using it with * mbedtls_ssl_write(), mbedtls_ssl_read() or * mbedtls_ssl_handshake() and the handshake can be * completed by calling one of these APIs. * * \note This function may write early data only if the SSL context * has been configured for the handshake with a PSK for which * early data is allowed. * * \note To maximize the number of early data that can be written in * the course of the handshake, it is expected that this * function starts the handshake for the SSL context \p ssl. * But this is not mandatory. * * \note This function does not provide any information on whether * the server has accepted or will accept early data or not. * When it returns a positive value, it just means that it * has written early data to the server. To know whether the * server has accepted early data or not, you should call * mbedtls_ssl_get_early_data_status() with the handshake * completed. */ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); /** * \brief Get the status of the negotiation of the use of early data. * * \param ssl The SSL context to query * * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called * from the server-side. * * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called * prior to completion of the handshake. * * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED if the client * has not indicated the use of early data to the server. * * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has * indicated the use of early data and the server has accepted * it. * * \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has * indicated the use of early data but the server has rejected * it. In this situation, the client may want to re-send the * early data it may have tried to send by calling * mbedtls_ssl_write_early_data() as ordinary post-handshake * application data by calling mbedtls_ssl_write(). * */ int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_CLI_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ /** * \brief Free referenced items in an SSL context and clear memory * * \param ssl SSL context */ void mbedtls_ssl_free(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /** * \brief Save an active connection as serialized data in a buffer. * This allows the freeing or re-using of the SSL context * while still picking up the connection later in a way that * it entirely transparent to the peer. * * \see mbedtls_ssl_context_load() * * \note The serialized data only contains the data that is * necessary to resume the connection: negotiated protocol * options, session identifier, keys, etc. * Loading a saved SSL context does not restore settings and * state related to how the application accesses the context, * such as configured callback functions, user data, pending * incoming or outgoing data, etc. * * \note This feature is currently only available under certain * conditions, see the documentation of the return value * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. * * \note When this function succeeds, it calls * mbedtls_ssl_session_reset() on \p ssl which as a result is * no longer associated with the connection that has been * serialized. This avoids creating copies of the connection * state. You're then free to either re-use the context * structure for a different connection, or call * mbedtls_ssl_free() on it. See the documentation of * mbedtls_ssl_session_reset() for more details. * * \param ssl The SSL context to save. On success, it is no longer * associated with the connection that has been serialized. * \param buf The buffer to write the serialized data to. It must be a * writeable buffer of at least \p buf_len bytes, or may be \c * NULL if \p buf_len is \c 0. * \param buf_len The number of bytes available for writing in \p buf. * \param olen The size in bytes of the data that has been or would have * been written. It must point to a valid \c size_t. * * \note \p olen is updated to the correct value regardless of * whether \p buf_len was large enough. This makes it possible * to determine the necessary size by calling this function * with \p buf set to \c NULL and \p buf_len to \c 0. However, * the value of \p olen is only guaranteed to be correct when * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or * \c 0. If the return value is different, then the value of * \p olen is undefined. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed * while resetting the context. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, * or the connection does not use DTLS 1.2 with an AEAD * ciphersuite, or renegotiation is enabled. */ int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, unsigned char *buf, size_t buf_len, size_t *olen); /** * \brief Load serialized connection data to an SSL context. * * \see mbedtls_ssl_context_save() * * \warning The same serialized data must never be loaded into more * that one context. In order to ensure that, after * successfully loading serialized data to an SSL context, you * should immediately destroy or invalidate all copies of the * serialized data that was loaded. Loading the same data in * more than one context would cause severe security failures * including but not limited to loss of confidentiality. * * \note Before calling this function, the SSL context must be * prepared in one of the two following ways. The first way is * to take a context freshly initialised with * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with * the same ::mbedtls_ssl_config structure that was used in * the original connection. The second way is to * call mbedtls_ssl_session_reset() on a context that was * previously prepared as above but used in the meantime. * Either way, you must not use the context to perform a * handshake between calling mbedtls_ssl_setup() or * mbedtls_ssl_session_reset() and calling this function. You * may however call other setter functions in that time frame * as indicated in the note below. * * \note Before or after calling this function successfully, you * also need to configure some connection-specific callbacks * and settings before you can use the connection again * (unless they were already set before calling * mbedtls_ssl_session_reset() and the values are suitable for * the present connection). Specifically, you want to call * at least mbedtls_ssl_set_bio(), * mbedtls_ssl_set_timer_cb(), and * mbedtls_ssl_set_user_data_n() or * mbedtls_ssl_set_user_data_p() if they were set originally. * All other SSL setter functions * are not necessary to call, either because they're only used * in handshakes, or because the setting is already saved. You * might choose to call them anyway, for example in order to * share code between the cases of establishing a new * connection and the case of loading an already-established * connection. * * \note If you have new information about the path MTU, you want to * call mbedtls_ssl_set_mtu() after calling this function, as * otherwise this function would overwrite your * newly-configured value with the value that was active when * the context was saved. * * \note When this function returns an error code, it calls * mbedtls_ssl_free() on \p ssl. In this case, you need to * prepare the context with the usual sequence starting with a * call to mbedtls_ssl_init() if you want to use it again. * * \param ssl The SSL context structure to be populated. It must have * been prepared as described in the note above. * \param buf The buffer holding the serialized connection data. It must * be a readable buffer of at least \p len bytes. * \param len The size of the serialized data in bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data * comes from a different Mbed TLS version or build. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. */ int mbedtls_ssl_context_load(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len); #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /** * \brief Initialize an SSL configuration context * Just makes the context ready for * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). * * \note You need to call mbedtls_ssl_config_defaults() unless you * manually set all of the relevant fields yourself. * * \param conf SSL configuration context */ void mbedtls_ssl_config_init(mbedtls_ssl_config *conf); /** * \brief Load reasonable default SSL configuration values. * (You need to call mbedtls_ssl_config_init() first.) * * \param conf SSL configuration context * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS * \param preset a MBEDTLS_SSL_PRESET_XXX value * * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. * * \return 0 if successful, or * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. */ int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, int endpoint, int transport, int preset); /** * \brief Free an SSL configuration context * * \param conf SSL configuration context */ void mbedtls_ssl_config_free(mbedtls_ssl_config *conf); /** * \brief Initialize SSL session structure * * \param session SSL session */ void mbedtls_ssl_session_init(mbedtls_ssl_session *session); /** * \brief Free referenced items in an SSL session including the * peer certificate and clear memory * * \note A session object can be freed even if the SSL context * that was used to retrieve the session is still in use. * * \param session SSL session */ void mbedtls_ssl_session_free(mbedtls_ssl_session *session); /** * \brief TLS-PRF function for key derivation. * * \param prf The tls_prf type function type to be used. * \param secret Secret for the key derivation function. * \param slen Length of the secret. * \param label String label for the key derivation function, * terminated with null character. * \param random Random bytes. * \param rlen Length of the random bytes buffer. * \param dstbuf The buffer holding the derived key. * \param dlen Length of the output buffer. * * \return 0 on success. An SSL specific error on failure. */ int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); #ifdef __cplusplus } #endif #endif /* ssl.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h000066400000000000000000000137401464416617300250470ustar00rootroot00000000000000/** * \file ssl_cache.h * * \brief SSL session cache implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CACHE_H #define MBEDTLS_SSL_CACHE_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) #define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ #endif #if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) #define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ #endif /** \} name SECTION: Module settings */ #ifdef __cplusplus extern "C" { #endif typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; /** * \brief This structure is used for storing cache entries */ struct mbedtls_ssl_cache_entry { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t MBEDTLS_PRIVATE(timestamp); /*!< entry timestamp */ #endif unsigned char MBEDTLS_PRIVATE(session_id)[32]; /*!< session ID */ size_t MBEDTLS_PRIVATE(session_id_len); unsigned char *MBEDTLS_PRIVATE(session); /*!< serialized session */ size_t MBEDTLS_PRIVATE(session_len); mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(next); /*!< chain pointer */ }; /** * \brief Cache context */ struct mbedtls_ssl_cache_context { mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(chain); /*!< start of the chain */ int MBEDTLS_PRIVATE(timeout); /*!< cache entry timeout */ int MBEDTLS_PRIVATE(max_entries); /*!< maximum entries */ #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ #endif }; /** * \brief Initialize an SSL cache context * * \param cache SSL cache context */ void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache); /** * \brief Cache get callback implementation * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data The SSL cache context to use. * \param session_id The pointer to the buffer holding the session ID * for the session to load. * \param session_id_len The length of \p session_id in bytes. * \param session The address at which to store the session * associated with \p session_id, if present. * * \return \c 0 on success. * \return #MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND if there is * no cache entry with specified session ID found, or * any other negative error code for other failures. */ int mbedtls_ssl_cache_get(void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session); /** * \brief Cache set callback implementation * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data The SSL cache context to use. * \param session_id The pointer to the buffer holding the session ID * associated to \p session. * \param session_id_len The length of \p session_id in bytes. * \param session The session to store. * * \return \c 0 on success. * \return A negative error code on failure. */ int mbedtls_ssl_cache_set(void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session); /** * \brief Remove the cache entry by the session ID * (Thread-safe if MBEDTLS_THREADING_C is enabled) * * \param data The SSL cache context to use. * \param session_id The pointer to the buffer holding the session ID * associated to session. * \param session_id_len The length of \p session_id in bytes. * * \return \c 0 on success. This indicates the cache entry for * the session with provided ID is removed or does not * exist. * \return A negative error code on failure. */ int mbedtls_ssl_cache_remove(void *data, unsigned char const *session_id, size_t session_id_len); #if defined(MBEDTLS_HAVE_TIME) /** * \brief Set the cache timeout * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) * * A timeout of 0 indicates no timeout. * * \param cache SSL cache context * \param timeout cache entry timeout in seconds */ void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout); /** * \brief Get the cache timeout * * A timeout of 0 indicates no timeout. * * \param cache SSL cache context * * \return cache entry timeout in seconds */ static inline int mbedtls_ssl_cache_get_timeout(mbedtls_ssl_cache_context *cache) { return cache->MBEDTLS_PRIVATE(timeout); } #endif /* MBEDTLS_HAVE_TIME */ /** * \brief Set the maximum number of cache entries * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) * * \param cache SSL cache context * \param max cache entry maximum */ void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max); /** * \brief Free referenced items in a cache context and clear memory * * \param cache SSL cache context */ void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache); #ifdef __cplusplus } #endif #endif /* ssl_cache.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h000066400000000000000000000575161464416617300265240ustar00rootroot00000000000000/** * \file ssl_ciphersuites.h * * \brief SSL Ciphersuites for Mbed TLS */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CIPHERSUITES_H #define MBEDTLS_SSL_CIPHERSUITES_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/pk.h" #include "mbedtls/cipher.h" #include "mbedtls/md.h" #ifdef __cplusplus extern "C" { #endif /* * Supported ciphersuites (Official IANA names) */ #define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ #define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 #define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 #define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 #define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C #define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 #define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE #define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF #define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ #define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ #define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 #define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ #define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A #define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F #define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 #define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A #define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B #define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 #define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 #define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 #define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 #define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A #define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B #define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ /* The last two are named with PSK_DHE in the RFC, which looks like a typo */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ #define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ /* RFC 7905 */ #define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ #define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ #define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ #define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ #define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ /* RFC 8446, Appendix B.4 */ #define MBEDTLS_TLS1_3_AES_128_GCM_SHA256 0x1301 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_AES_256_GCM_SHA384 0x1302 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256 0x1303 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_AES_128_CCM_SHA256 0x1304 /**< TLS 1.3 */ #define MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256 0x1305 /**< TLS 1.3 */ /* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below */ typedef enum { MBEDTLS_KEY_EXCHANGE_NONE = 0, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_KEY_EXCHANGE_DHE_RSA, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, MBEDTLS_KEY_EXCHANGE_ECJPAKE, } mbedtls_key_exchange_type_t; /* Key exchanges using a certificate */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED #endif /* Key exchanges in either TLS 1.2 or 1.3 which are using an ECDSA * signature */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED #endif /* Key exchanges allowing client certificate requests. * * Note: that's almost the same as MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED * above, except RSA-PSK uses a server certificate but no client cert. * * Note: this difference is specific to TLS 1.2, as with TLS 1.3, things are * more symmetrical: client certs and server certs are either both allowed * (Ephemeral mode) or both disallowed (PSK and PKS-Ephemeral modes). */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED #endif /* Helper to state that certificate-based client authentication through ECDSA * is supported in TLS 1.2 */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) && \ defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) #define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED #endif /* ECDSA required for certificates in either TLS 1.2 or 1.3 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED #endif /* Key exchanges involving server signature in ServerKeyExchange */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED #endif /* Key exchanges using ECDH */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED #endif /* Key exchanges that don't involve ephemeral keys */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED #endif /* Key exchanges that involve ephemeral keys */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED #endif /* Key exchanges using a PSK */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED #endif /* Key exchanges using DHE */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED #endif /* Key exchanges using ECDHE */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED #endif /* TLS 1.2 key exchanges using ECDH or ECDHE*/ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED #endif /* TLS 1.3 PSK key exchanges */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED #endif /* TLS 1.2 or 1.3 key exchanges with PSK */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) #define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED #endif /* TLS 1.3 ephemeral key exchanges */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED #endif /* TLS 1.3 key exchanges using ECDHE */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) && \ defined(PSA_WANT_ALG_ECDH) #define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED #endif /* TLS 1.2 or 1.3 key exchanges using ECDH or ECDHE */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED #endif /* TLS 1.2 XXDH key exchanges: ECDH or ECDHE or FFDH */ #if (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)) #define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_1_2_ENABLED #endif /* The handshake params structure has a set of fields called xxdh_psa which are used: * - by TLS 1.2 with `USE_PSA` to do ECDH or ECDHE; * - by TLS 1.3 to do ECDHE or FFDHE. * The following macros can be used to guard their declaration and use. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) #define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) #define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED #endif typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; #define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ #define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, eg for CCM_8 */ #define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ /** * \brief This structure is used for storing ciphersuite information * * \note members are defined using integral types instead of enums * in order to pack structure and reduce memory usage by internal * \c ciphersuite_definitions[] */ struct mbedtls_ssl_ciphersuite_t { int MBEDTLS_PRIVATE(id); const char *MBEDTLS_PRIVATE(name); uint8_t MBEDTLS_PRIVATE(cipher); /* mbedtls_cipher_type_t */ uint8_t MBEDTLS_PRIVATE(mac); /* mbedtls_md_type_t */ uint8_t MBEDTLS_PRIVATE(key_exchange); /* mbedtls_key_exchange_type_t */ uint8_t MBEDTLS_PRIVATE(flags); uint16_t MBEDTLS_PRIVATE(min_tls_version); /* mbedtls_ssl_protocol_version */ uint16_t MBEDTLS_PRIVATE(max_tls_version); /* mbedtls_ssl_protocol_version */ }; const int *mbedtls_ssl_list_ciphersuites(void); const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(const char *ciphersuite_name); const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite_id); static inline const char *mbedtls_ssl_ciphersuite_get_name(const mbedtls_ssl_ciphersuite_t *info) { return info->MBEDTLS_PRIVATE(name); } static inline int mbedtls_ssl_ciphersuite_get_id(const mbedtls_ssl_ciphersuite_t *info) { return info->MBEDTLS_PRIVATE(id); } size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info); #ifdef __cplusplus } #endif #endif /* ssl_ciphersuites.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h000066400000000000000000000061331464416617300252530ustar00rootroot00000000000000/** * \file ssl_cookie.h * * \brief DTLS cookie callbacks implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_COOKIE_H #define MBEDTLS_SSL_COOKIE_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/ssl.h" #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #endif /* !MBEDTLS_USE_PSA_CRYPTO */ /** * \name SECTION: Module settings * * The configuration options you can set for this module are in this section. * Either change them in mbedtls_config.h or define them on the compiler command line. * \{ */ #ifndef MBEDTLS_SSL_COOKIE_TIMEOUT #define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ #endif /** \} name SECTION: Module settings */ #ifdef __cplusplus extern "C" { #endif /** * \brief Context for the default cookie functions. */ typedef struct mbedtls_ssl_cookie_ctx { #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_hmac_key); /*!< key id for the HMAC portion */ psa_algorithm_t MBEDTLS_PRIVATE(psa_hmac_alg); /*!< key algorithm for the HMAC portion */ #else mbedtls_md_context_t MBEDTLS_PRIVATE(hmac_ctx); /*!< context for the HMAC portion */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_HAVE_TIME) unsigned long MBEDTLS_PRIVATE(serial); /*!< serial number for expiration */ #endif unsigned long MBEDTLS_PRIVATE(timeout); /*!< timeout delay, in seconds if HAVE_TIME, or in number of tickets issued */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } mbedtls_ssl_cookie_ctx; /** * \brief Initialize cookie context */ void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx); /** * \brief Setup cookie context (generate keys) */ int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Set expiration delay for cookies * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) * * \param ctx Cookie context * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies * issued in the meantime. * 0 to disable expiration (NOT recommended) */ void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay); /** * \brief Free cookie context */ void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx); /** * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t */ mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; /** * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t */ mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; #ifdef __cplusplus } #endif #endif /* ssl_cookie.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h000066400000000000000000000165561464416617300252770ustar00rootroot00000000000000/** * \file ssl_ticket.h * * \brief TLS server ticket callbacks implementation */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_TICKET_H #define MBEDTLS_SSL_TICKET_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" /* * This implementation of the session ticket callbacks includes key * management, rotating the keys periodically in order to preserve forward * secrecy, when MBEDTLS_HAVE_TIME is defined. */ #include "mbedtls/ssl.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #ifdef __cplusplus extern "C" { #endif #define MBEDTLS_SSL_TICKET_MAX_KEY_BYTES 32 /*!< Max supported key length in bytes */ #define MBEDTLS_SSL_TICKET_KEY_NAME_BYTES 4 /*!< key name length in bytes */ /** * \brief Information for session ticket protection */ typedef struct mbedtls_ssl_ticket_key { unsigned char MBEDTLS_PRIVATE(name)[MBEDTLS_SSL_TICKET_KEY_NAME_BYTES]; /*!< random key identifier */ #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */ #endif /*! Lifetime of the key in seconds. This is also the lifetime of the * tickets created under that key. */ uint32_t MBEDTLS_PRIVATE(lifetime); #if !defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx); /*!< context for auth enc/decryption */ #else mbedtls_svc_key_id_t MBEDTLS_PRIVATE(key); /*!< key used for auth enc/decryption */ psa_algorithm_t MBEDTLS_PRIVATE(alg); /*!< algorithm of auth enc/decryption */ psa_key_type_t MBEDTLS_PRIVATE(key_type); /*!< key type */ size_t MBEDTLS_PRIVATE(key_bits); /*!< key length in bits */ #endif } mbedtls_ssl_ticket_key; /** * \brief Context for session ticket handling functions */ typedef struct mbedtls_ssl_ticket_context { mbedtls_ssl_ticket_key MBEDTLS_PRIVATE(keys)[2]; /*!< ticket protection keys */ unsigned char MBEDTLS_PRIVATE(active); /*!< index of the currently active key */ uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< lifetime of tickets in seconds */ /** Callback for getting (pseudo-)random numbers */ int(*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); #endif } mbedtls_ssl_ticket_context; /** * \brief Initialize a ticket context. * (Just make it ready for mbedtls_ssl_ticket_setup() * or mbedtls_ssl_ticket_free().) * * \param ctx Context to be initialized */ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx); /** * \brief Prepare context to be actually used * * \param ctx Context to be set up * \param f_rng RNG callback function (mandatory) * \param p_rng RNG callback context * \param cipher AEAD cipher to use for ticket protection. * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. * \param lifetime Tickets lifetime in seconds * Recommended value: 86400 (one day). * * \note It is highly recommended to select a cipher that is at * least as strong as the strongest ciphersuite * supported. Usually that means a 256-bit key. * * \note It is recommended to pick a reasonable lifetime so as not * to negate the benefits of forward secrecy. * * \note The TLS 1.3 specification states that ticket lifetime must * be smaller than seven days. If ticket lifetime has been * set to a value greater than seven days in this module then * if the TLS 1.3 is configured to send tickets after the * handshake it will fail the connection when trying to send * the first ticket. * * \return 0 if successful, * or a specific MBEDTLS_ERR_XXX error code */ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_cipher_type_t cipher, uint32_t lifetime); /** * \brief Rotate session ticket encryption key to new specified key. * Provides for external control of session ticket encryption * key rotation, e.g. for synchronization between different * machines. If this function is not used, or if not called * before ticket lifetime expires, then a new session ticket * encryption key is generated internally in order to avoid * unbounded session ticket encryption key lifetimes. * * \param ctx Context to be set up * \param name Session ticket encryption key name * \param nlength Session ticket encryption key name length in bytes * \param k Session ticket encryption key * \param klength Session ticket encryption key length in bytes * \param lifetime Tickets lifetime in seconds * Recommended value: 86400 (one day). * * \note \c name and \c k are recommended to be cryptographically * random data. * * \note \c nlength must match sizeof( ctx->name ) * * \note \c klength must be sufficient for use by cipher specified * to \c mbedtls_ssl_ticket_setup * * \note It is recommended to pick a reasonable lifetime so as not * to negate the benefits of forward secrecy. * * \note The TLS 1.3 specification states that ticket lifetime must * be smaller than seven days. If ticket lifetime has been * set to a value greater than seven days in this module then * if the TLS 1.3 is configured to send tickets after the * handshake it will fail the connection when trying to send * the first ticket. * * \return 0 if successful, * or a specific MBEDTLS_ERR_XXX error code */ int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, const unsigned char *name, size_t nlength, const unsigned char *k, size_t klength, uint32_t lifetime); /** * \brief Implementation of the ticket write callback * * \note See \c mbedtls_ssl_ticket_write_t for description */ mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; /** * \brief Implementation of the ticket parse callback * * \note See \c mbedtls_ssl_ticket_parse_t for description */ mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; /** * \brief Free a context's content and zeroize it. * * \param ctx Context to be cleaned up */ void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx); #ifdef __cplusplus } #endif #endif /* ssl_ticket.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/threading.h000066400000000000000000000120261464416617300250640ustar00rootroot00000000000000/** * \file threading.h * * \brief Threading abstraction layer */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_THREADING_H #define MBEDTLS_THREADING_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #ifdef __cplusplus extern "C" { #endif /** Bad input parameters to function. */ #define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /** Locking / unlocking / free failed with error code. */ #define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E #if defined(MBEDTLS_THREADING_PTHREAD) #include typedef struct mbedtls_threading_mutex_t { pthread_mutex_t MBEDTLS_PRIVATE(mutex); /* WARNING - state should only be accessed when holding the mutex lock in * tests/src/threading_helpers.c, otherwise corruption can occur. * state will be 0 after a failed init or a free, and nonzero after a * successful init. This field is for testing only and thus not considered * part of the public API of Mbed TLS and may change without notice.*/ char MBEDTLS_PRIVATE(state); } mbedtls_threading_mutex_t; #endif #if defined(MBEDTLS_THREADING_ALT) /* You should define the mbedtls_threading_mutex_t type in your header */ #include "threading_alt.h" /** * \brief Set your alternate threading implementation function * pointers and initialize global mutexes. If used, this * function must be called once in the main thread before any * other Mbed TLS function is called, and * mbedtls_threading_free_alt() must be called once in the main * thread after all other Mbed TLS functions. * * \note mutex_init() and mutex_free() don't return a status code. * If mutex_init() fails, it should leave its argument (the * mutex) in a state such that mutex_lock() will fail when * called with this argument. * * \param mutex_init the init function implementation * \param mutex_free the free function implementation * \param mutex_lock the lock function implementation * \param mutex_unlock the unlock function implementation */ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), void (*mutex_free)(mbedtls_threading_mutex_t *), int (*mutex_lock)(mbedtls_threading_mutex_t *), int (*mutex_unlock)(mbedtls_threading_mutex_t *)); /** * \brief Free global mutexes. */ void mbedtls_threading_free_alt(void); #endif /* MBEDTLS_THREADING_ALT */ #if defined(MBEDTLS_THREADING_C) /* * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock * * All these functions are expected to work or the result will be undefined. */ extern void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *mutex); extern void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *mutex); extern int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *mutex); extern int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *mutex); /* * Global mutexes */ #if defined(MBEDTLS_FS_IO) extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; #endif #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) /* This mutex may or may not be used in the default definition of * mbedtls_platform_gmtime_r(), but in order to determine that, * we need to check POSIX features, hence modify _POSIX_C_SOURCE. * With the current approach, this declaration is orphaned, lacking * an accompanying definition, in case mbedtls_platform_gmtime_r() * doesn't need it, but that's not a problem. */ extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* * A mutex used to make the PSA subsystem thread safe. * * key_slot_mutex protects the registered_readers and * state variable for all key slots in &global_data.key_slots. * * This mutex must be held when any read from or write to a state or * registered_readers field is performed, i.e. when calling functions: * psa_key_slot_state_transition(), psa_register_read(), psa_unregister_read(), * psa_key_slot_has_readers() and psa_wipe_key_slot(). */ extern mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex; /* * A mutex used to make the non-rng PSA global_data struct members thread safe. * * This mutex must be held when reading or writing to any of the PSA global_data * structure members, other than the rng_state or rng struct. */ extern mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex; /* * A mutex used to make the PSA global_data rng data thread safe. * * This mutex must be held when reading or writing to the PSA * global_data rng_state or rng struct members. */ extern mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex; #endif #endif /* MBEDTLS_THREADING_C */ #ifdef __cplusplus } #endif #endif /* threading.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/timing.h000066400000000000000000000052071464416617300244110ustar00rootroot00000000000000/** * \file timing.h * * \brief Portable interface to timeouts and to the CPU cycle counter */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_TIMING_H #define MBEDTLS_TIMING_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include #ifdef __cplusplus extern "C" { #endif #if !defined(MBEDTLS_TIMING_ALT) // Regular implementation // /** * \brief timer structure */ struct mbedtls_timing_hr_time { uint64_t MBEDTLS_PRIVATE(opaque)[4]; }; /** * \brief Context for mbedtls_timing_set/get_delay() */ typedef struct mbedtls_timing_delay_context { struct mbedtls_timing_hr_time MBEDTLS_PRIVATE(timer); uint32_t MBEDTLS_PRIVATE(int_ms); uint32_t MBEDTLS_PRIVATE(fin_ms); } mbedtls_timing_delay_context; #else /* MBEDTLS_TIMING_ALT */ #include "timing_alt.h" #endif /* MBEDTLS_TIMING_ALT */ /* Internal use */ unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset); /** * \brief Set a pair of delays to watch * (See \c mbedtls_timing_get_delay().) * * \param data Pointer to timing data. * Must point to a valid \c mbedtls_timing_delay_context struct. * \param int_ms First (intermediate) delay in milliseconds. * The effect if int_ms > fin_ms is unspecified. * \param fin_ms Second (final) delay in milliseconds. * Pass 0 to cancel the current delay. * * \note To set a single delay, either use \c mbedtls_timing_set_timer * directly or use this function with int_ms == fin_ms. */ void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms); /** * \brief Get the status of delays * (Memory helper: number of delays passed.) * * \param data Pointer to timing data * Must point to a valid \c mbedtls_timing_delay_context struct. * * \return -1 if cancelled (fin_ms = 0), * 0 if none of the delays are passed, * 1 if only the intermediate delay is passed, * 2 if the final delay is passed. */ int mbedtls_timing_get_delay(void *data); /** * \brief Get the final timing delay * * \param data Pointer to timing data * Must point to a valid \c mbedtls_timing_delay_context struct. * * \return Final timing delay in milliseconds. */ uint32_t mbedtls_timing_get_final_delay( const mbedtls_timing_delay_context *data); #ifdef __cplusplus } #endif #endif /* timing.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/version.h000066400000000000000000000043361464416617300246110ustar00rootroot00000000000000/** * \file version.h * * \brief Run-time version information */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This set of run-time variables can be used to determine the version number of * the Mbed TLS library used. Compile-time version defines for the same can be * found in build_info.h */ #ifndef MBEDTLS_VERSION_H #define MBEDTLS_VERSION_H #include "mbedtls/build_info.h" #if defined(MBEDTLS_VERSION_C) #ifdef __cplusplus extern "C" { #endif /** * Get the version number. * * \return The constructed version number in the format * MMNNPP00 (Major, Minor, Patch). */ unsigned int mbedtls_version_get_number(void); /** * Get the version string ("x.y.z"). * * \param string The string that will receive the value. * (Should be at least 9 bytes in size) */ void mbedtls_version_get_string(char *string); /** * Get the full version string ("Mbed TLS x.y.z"). * * \param string The string that will receive the value. The Mbed TLS version * string will use 18 bytes AT MOST including a terminating * null byte. * (So the buffer should be at least 18 bytes to receive this * version string). */ void mbedtls_version_get_string_full(char *string); /** * \brief Check if support for a feature was compiled into this * Mbed TLS binary. This allows you to see at runtime if the * library was for instance compiled with or without * Multi-threading support. * * \note only checks against defines in the sections "System * support", "Mbed TLS modules" and "Mbed TLS feature * support" in mbedtls_config.h * * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") * * \return 0 if the feature is present, * -1 if the feature is not present and * -2 if support for feature checking as a whole was not * compiled in. */ int mbedtls_version_check_feature(const char *feature); #ifdef __cplusplus } #endif #endif /* MBEDTLS_VERSION_C */ #endif /* version.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/x509.h000066400000000000000000000513441464416617300236320ustar00rootroot00000000000000/** * \file x509.h * * \brief X.509 generic defines and structures */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_H #define MBEDTLS_X509_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/asn1.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif /** * \addtogroup x509_module * \{ */ #if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) /** * Maximum number of intermediate CAs in a verification chain. * That is, maximum length of the chain, excluding the end-entity certificate * and the trusted root certificate. * * Set this to a low value to prevent an adversary from making you waste * resources verifying an overlong certificate chain. */ #define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 #endif /** * \name X509 Error codes * \{ */ /** Unavailable feature, e.g. RSA hashing/encryption combination. */ #define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /** Requested OID is unknown. */ #define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /** The CRT/CRL/CSR format is invalid, e.g. different type expected. */ #define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /** The CRT/CRL/CSR version element is invalid. */ #define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /** The serial tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /** The algorithm tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /** The name tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /** The date tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /** The signature tag or value invalid. */ #define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /** The extension tag or value is invalid. */ #define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /** CRT/CRL/CSR has an unsupported version number. */ #define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /** Signature algorithm (oid) is unsupported. */ #define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /** Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ #define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /** Certificate verification failed, e.g. CRL, CA or signature check failed. */ #define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /** Format not recognized as DER or PEM. */ #define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /** Input invalid. */ #define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /** Allocation of memory failed. */ #define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /** Read/write of file failed. */ #define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /** Destination buffer is too small. */ #define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ #define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /** \} name X509 Error codes */ /** * \name X509 Verify codes * \{ */ /* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ #define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ #define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ #define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ #define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ #define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ #define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ #define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ #define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ #define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ #define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ #define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ #define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ #define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ #define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ #define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ #define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ #define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ #define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ #define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ #define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ /** \} name X509 Verify codes */ /** \} addtogroup x509_module */ /* * X.509 v3 Subject Alternative Name types. * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER */ #define MBEDTLS_X509_SAN_OTHER_NAME 0 #define MBEDTLS_X509_SAN_RFC822_NAME 1 #define MBEDTLS_X509_SAN_DNS_NAME 2 #define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3 #define MBEDTLS_X509_SAN_DIRECTORY_NAME 4 #define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5 #define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6 #define MBEDTLS_X509_SAN_IP_ADDRESS 7 #define MBEDTLS_X509_SAN_REGISTERED_ID 8 /* * X.509 v3 Key Usage Extension flags * Reminder: update mbedtls_x509_info_key_usage() when adding new flags. */ #define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ #define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ #define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ #define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ #define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ #define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ #define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ #define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ #define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ /* * Netscape certificate types * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) */ #define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ #define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ #define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ #define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ #define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ #define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ #define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ #define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ /* * X.509 extension types * * Comments refer to the status for using certificates. Status can be * different for writing certificates or reading CRLs or CSRs. * * Those are defined in oid.h as oid.c needs them in a data structure. Since * these were previously defined here, let's have aliases for compatibility. */ #define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER #define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER #define MBEDTLS_X509_EXT_KEY_USAGE MBEDTLS_OID_X509_EXT_KEY_USAGE #define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES #define MBEDTLS_X509_EXT_POLICY_MAPPINGS MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS #define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME /* Supported (DNS) */ #define MBEDTLS_X509_EXT_ISSUER_ALT_NAME MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME #define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS #define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS /* Supported */ #define MBEDTLS_X509_EXT_NAME_CONSTRAINTS MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS #define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS #define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE #define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS #define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY #define MBEDTLS_X509_EXT_FRESHEST_CRL MBEDTLS_OID_X509_EXT_FRESHEST_CRL #define MBEDTLS_X509_EXT_NS_CERT_TYPE MBEDTLS_OID_X509_EXT_NS_CERT_TYPE /* * Storage format identifiers * Recognized formats: PEM and DER */ #define MBEDTLS_X509_FORMAT_DER 1 #define MBEDTLS_X509_FORMAT_PEM 2 #define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ #ifdef __cplusplus extern "C" { #endif /** * \addtogroup x509_module * \{ */ /** * \name Structures for parsing X.509 certificates, CRLs and CSRs * \{ */ /** * Type-length-value structure that allows for ASN1 using DER. */ typedef mbedtls_asn1_buf mbedtls_x509_buf; /** * Container for ASN1 bit strings. */ typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; /** * Container for ASN1 named information objects. * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). */ typedef mbedtls_asn1_named_data mbedtls_x509_name; /** * Container for a sequence of ASN.1 items */ typedef mbedtls_asn1_sequence mbedtls_x509_sequence; /* * Container for the fields of the Authority Key Identifier object */ typedef struct mbedtls_x509_authority { mbedtls_x509_buf keyIdentifier; mbedtls_x509_sequence authorityCertIssuer; mbedtls_x509_buf authorityCertSerialNumber; mbedtls_x509_buf raw; } mbedtls_x509_authority; /** Container for date and time (precision in seconds). */ typedef struct mbedtls_x509_time { int year, mon, day; /**< Date. */ int hour, min, sec; /**< Time. */ } mbedtls_x509_time; /** * From RFC 5280 section 4.2.1.6: * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * Future versions of the library may add new fields to this structure or * to its embedded union and structure. */ typedef struct mbedtls_x509_san_other_name { /** * The type_id is an OID as defined in RFC 5280. * To check the value of the type id, you should use * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. */ mbedtls_x509_buf type_id; /**< The type id. */ union { /** * From RFC 4108 section 5: * HardwareModuleName ::= SEQUENCE { * hwType OBJECT IDENTIFIER, * hwSerialNum OCTET STRING } */ struct { mbedtls_x509_buf oid; /**< The object identifier. */ mbedtls_x509_buf val; /**< The named value. */ } hardware_module_name; } value; } mbedtls_x509_san_other_name; /** * A structure for holding the parsed Subject Alternative Name, * according to type. * * Future versions of the library may add new fields to this structure or * to its embedded union and structure. */ typedef struct mbedtls_x509_subject_alternative_name { int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ union { mbedtls_x509_san_other_name other_name; mbedtls_x509_name directory_name; mbedtls_x509_buf unstructured_name; /**< The buffer for the unstructured types. rfc822Name, dnsName and uniformResourceIdentifier are currently supported. */ } san; /**< A union of the supported SAN types */ } mbedtls_x509_subject_alternative_name; typedef struct mbedtls_x509_san_list { mbedtls_x509_subject_alternative_name node; struct mbedtls_x509_san_list *next; } mbedtls_x509_san_list; /** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ /** \} addtogroup x509_module */ /** * \brief Store the certificate DN in printable form into buf; * no more than size characters will be written. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param dn The X509 name to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn); /** * \brief Convert the certificate DN string \p name into * a linked list of mbedtls_x509_name (equivalent to * mbedtls_asn1_named_data). * * \note This function allocates a linked list, and places the head * pointer in \p head. This list must later be freed by a * call to mbedtls_asn1_free_named_data_list(). * * \param[out] head Address in which to store the pointer to the head of the * allocated list of mbedtls_x509_name * \param[in] name The string representation of a DN to convert * * \return 0 on success, or a negative error code. */ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name); /** * \brief Return the next relative DN in an X509 name. * * \note Intended use is to compare function result to dn->next * in order to detect boundaries of multi-valued RDNs. * * \param dn Current node in the X509 name * * \return Pointer to the first attribute-value pair of the * next RDN in sequence, or NULL if end is reached. */ static inline mbedtls_x509_name *mbedtls_x509_dn_get_next( mbedtls_x509_name *dn) { while (dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL) { dn = dn->next; } return dn->next; } /** * \brief Store the certificate serial in printable form into buf; * no more than size characters will be written. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param serial The X509 serial to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial); /** * \brief Compare pair of mbedtls_x509_time. * * \param t1 mbedtls_x509_time to compare * \param t2 mbedtls_x509_time to compare * * \return < 0 if t1 is before t2 * 0 if t1 equals t2 * > 0 if t1 is after t2 */ int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2); #if defined(MBEDTLS_HAVE_TIME_DATE) /** * \brief Fill mbedtls_x509_time with provided mbedtls_time_t. * * \param tt mbedtls_time_t to convert * \param now mbedtls_x509_time to fill with converted mbedtls_time_t * * \return \c 0 on success * \return A non-zero return value on failure. */ int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now); #endif /* MBEDTLS_HAVE_TIME_DATE */ /** * \brief Check a given mbedtls_x509_time against the system time * and tell if it's in the past. * * \note Intended usage is "if( is_past( valid_to ) ) ERROR". * Hence the return value of 1 if on internal errors. * * \param to mbedtls_x509_time to check * * \return 1 if the given time is in the past or an error occurred, * 0 otherwise. */ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to); /** * \brief Check a given mbedtls_x509_time against the system time * and tell if it's in the future. * * \note Intended usage is "if( is_future( valid_from ) ) ERROR". * Hence the return value of 1 if on internal errors. * * \param from mbedtls_x509_time to check * * \return 1 if the given time is in the future or an error occurred, * 0 otherwise. */ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from); /** * \brief This function parses an item in the SubjectAlternativeNames * extension. Please note that this function might allocate * additional memory for a subject alternative name, thus * mbedtls_x509_free_subject_alt_name has to be called * to dispose of this additional memory afterwards. * * \param san_buf The buffer holding the raw data item of the subject * alternative name. * \param san The target structure to populate with the parsed presentation * of the subject alternative name encoded in \p san_buf. * * \note Supported GeneralName types, as defined in RFC 5280: * "rfc822Name", "dnsName", "directoryName", * "uniformResourceIdentifier" and "hardware_module_name" * of type "otherName", as defined in RFC 4108. * * \note This function should be called on a single raw data of * subject alternative name. For example, after successful * certificate parsing, one must iterate on every item in the * \c crt->subject_alt_names sequence, and pass it to * this function. * * \warning The target structure contains pointers to the raw data of the * parsed certificate, and its lifetime is restricted by the * lifetime of the certificate. * * \return \c 0 on success * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported * SAN type. * \return Another negative value for any other failure. */ int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, mbedtls_x509_subject_alternative_name *san); /** * \brief Unallocate all data related to subject alternative name * * \param san SAN structure - extra memory owned by this structure will be freed */ void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san); /** * \brief This function parses a CN string as an IP address. * * \param cn The CN string to parse. CN string MUST be null-terminated. * \param dst The target buffer to populate with the binary IP address. * The buffer MUST be 16 bytes to save IPv6, and should be * 4-byte aligned if the result will be used as struct in_addr. * e.g. uint32_t dst[4] * * \note \p cn is parsed as an IPv6 address if string contains ':', * else \p cn is parsed as an IPv4 address. * * \return Length of binary IP address; num bytes written to target. * \return \c 0 on failure to parse CN string as an IP address. */ size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst); #define MBEDTLS_X509_SAFE_SNPRINTF \ do { \ if (ret < 0 || (size_t) ret >= n) \ return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; \ \ n -= (size_t) ret; \ p += (size_t) ret; \ } while (0) #ifdef __cplusplus } #endif #endif /* MBEDTLS_X509_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h000066400000000000000000000143501464416617300244660ustar00rootroot00000000000000/** * \file x509_crl.h * * \brief X.509 certificate revocation list parsing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CRL_H #define MBEDTLS_X509_CRL_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #ifdef __cplusplus extern "C" { #endif /** * \addtogroup x509_module * \{ */ /** * \name Structures and functions for parsing CRLs * \{ */ /** * Certificate revocation list entry. * Contains the CA-specific serial numbers and revocation dates. * * Some fields of this structure are publicly readable. Do not modify * them except via Mbed TLS library functions: the effect of modifying * those fields or the data that those fields points to is unspecified. */ typedef struct mbedtls_x509_crl_entry { /** Direct access to the whole entry inside the containing buffer. */ mbedtls_x509_buf raw; /** The serial number of the revoked certificate. */ mbedtls_x509_buf serial; /** The revocation date of this entry. */ mbedtls_x509_time revocation_date; /** Direct access to the list of CRL entry extensions * (an ASN.1 constructed sequence). * * If there are no extensions, `entry_ext.len == 0` and * `entry_ext.p == NULL`. */ mbedtls_x509_buf entry_ext; /** Next element in the linked list of entries. * \p NULL indicates the end of the list. * Do not modify this field directly. */ struct mbedtls_x509_crl_entry *next; } mbedtls_x509_crl_entry; /** * Certificate revocation list structure. * Every CRL may have multiple entries. */ typedef struct mbedtls_x509_crl { mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ int version; /**< CRL version (1=v1, 2=v2) */ mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ mbedtls_x509_time this_update; mbedtls_x509_time next_update; mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ mbedtls_x509_buf crl_ext; mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid2); mbedtls_x509_buf MBEDTLS_PRIVATE(sig); mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ /** Next element in the linked list of CRL. * \p NULL indicates the end of the list. * Do not modify this field directly. */ struct mbedtls_x509_crl *next; } mbedtls_x509_crl; /** * \brief Parse a DER-encoded CRL and append it to the chained list * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in DER format * \param buflen size of the buffer * (including the terminating null byte for PEM data) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen); /** * \brief Parse one or more CRLs and append them to the chained list * * \note Multiple CRLs are accepted only if using PEM format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param buf buffer holding the CRL data in PEM or DER format * \param buflen size of the buffer * (including the terminating null byte for PEM data) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** * \brief Load one or more CRLs and append them to the chained list * * \note Multiple CRLs are accepted only if using PEM format * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param path filename to read the CRLs from (in PEM or DER encoding) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path); #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the CRL. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param crl The X509 CRL to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crl *crl); #endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Initialize a CRL (chain) * * \param crl CRL chain to initialize */ void mbedtls_x509_crl_init(mbedtls_x509_crl *crl); /** * \brief Unallocate all CRL data * * \param crl CRL chain to free */ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl); /** \} name Structures and functions for parsing CRLs */ /** \} addtogroup x509_module */ #ifdef __cplusplus } #endif #endif /* mbedtls_x509_crl.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h000066400000000000000000001564311464416617300245050ustar00rootroot00000000000000/** * \file x509_crt.h * * \brief X.509 certificate parsing and writing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CRT_H #define MBEDTLS_X509_CRT_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #include "mbedtls/x509_crl.h" #include "mbedtls/bignum.h" /** * \addtogroup x509_module * \{ */ #ifdef __cplusplus extern "C" { #endif /** * \name Structures and functions for parsing and writing X.509 certificates * \{ */ /** * Container for an X.509 certificate. The certificate may be chained. * * Some fields of this structure are publicly readable. Do not modify * them except via Mbed TLS library functions: the effect of modifying * those fields or the data that those fields points to is unspecified. */ typedef struct mbedtls_x509_crt { int MBEDTLS_PRIVATE(own_buffer); /**< Indicates if \c raw is owned * by the structure or not. */ mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ mbedtls_x509_time valid_to; /**< End time of certificate validity. */ mbedtls_x509_buf pk_raw; mbedtls_pk_context pk; /**< Container for the public key context. */ mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */ mbedtls_x509_buf subject_key_id; /**< Optional X.509 v3 extension subject key identifier. */ mbedtls_x509_authority authority_key_id; /**< Optional X.509 v3 extension authority key identifier. */ mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */ int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ int MBEDTLS_PRIVATE(ca_istrue); /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ int MBEDTLS_PRIVATE(max_pathlen); /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ unsigned int MBEDTLS_PRIVATE(key_usage); /**< Optional key usage extension value: See the values in x509.h */ mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ unsigned char MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */ mbedtls_x509_buf MBEDTLS_PRIVATE(sig); /**< Signature: hash of the tbs part signed with the private key. */ mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ /** Next certificate in the linked list that constitutes the CA chain. * \p NULL indicates the end of the list. * Do not modify this field directly. */ struct mbedtls_x509_crt *next; } mbedtls_x509_crt; /** * Build flag from an algorithm/curve identifier (pk, md, ecp) * Since 0 is always XXX_NONE, ignore it. */ #define MBEDTLS_X509_ID_FLAG(id) (1 << ((id) - 1)) /** * Security profile for certificate verification. * * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). * * The fields of this structure are part of the public API and can be * manipulated directly by applications. Future versions of the library may * add extra fields or reorder existing fields. * * You can create custom profiles by starting from a copy of * an existing profile, such as mbedtls_x509_crt_profile_default or * mbedtls_x509_ctr_profile_none and then tune it to your needs. * * For example to allow SHA-224 in addition to the default: * * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default; * my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ); * * Or to allow only RSA-3072+ with SHA-256: * * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_none; * my_profile.allowed_mds = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ); * my_profile.allowed_pks = MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA ); * my_profile.rsa_min_bitlen = 3072; */ typedef struct mbedtls_x509_crt_profile { uint32_t allowed_mds; /**< MDs for signatures */ uint32_t allowed_pks; /**< PK algs for public keys; * this applies to all certificates * in the provided chain. */ uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ } mbedtls_x509_crt_profile; #define MBEDTLS_X509_CRT_VERSION_1 0 #define MBEDTLS_X509_CRT_VERSION_2 1 #define MBEDTLS_X509_CRT_VERSION_3 2 #define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 20 #define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 #if !defined(MBEDTLS_X509_MAX_FILE_PATH_LEN) #define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 #endif /* This macro unfolds to the concatenation of macro invocations * X509_CRT_ERROR_INFO( error code, * error code as string, * human readable description ) * where X509_CRT_ERROR_INFO is defined by the user. * See x509_crt.c for an example of how to use this. */ #define MBEDTLS_X509_CRT_ERROR_INFO_LIST \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXPIRED, \ "MBEDTLS_X509_BADCERT_EXPIRED", \ "The certificate validity has expired") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_REVOKED, \ "MBEDTLS_X509_BADCERT_REVOKED", \ "The certificate has been revoked (is on a CRL)") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_CN_MISMATCH, \ "MBEDTLS_X509_BADCERT_CN_MISMATCH", \ "The certificate Common Name (CN) does not match with the expected CN") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NOT_TRUSTED, \ "MBEDTLS_X509_BADCERT_NOT_TRUSTED", \ "The certificate is not correctly signed by the trusted CA") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_NOT_TRUSTED, \ "MBEDTLS_X509_BADCRL_NOT_TRUSTED", \ "The CRL is not correctly signed by the trusted CA") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_EXPIRED, \ "MBEDTLS_X509_BADCRL_EXPIRED", \ "The CRL is expired") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_MISSING, \ "MBEDTLS_X509_BADCERT_MISSING", \ "Certificate was missing") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_SKIP_VERIFY, \ "MBEDTLS_X509_BADCERT_SKIP_VERIFY", \ "Certificate verification was skipped") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_OTHER, \ "MBEDTLS_X509_BADCERT_OTHER", \ "Other reason (can be used by verify callback)") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_FUTURE, \ "MBEDTLS_X509_BADCERT_FUTURE", \ "The certificate validity starts in the future") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_FUTURE, \ "MBEDTLS_X509_BADCRL_FUTURE", \ "The CRL is from the future") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_KEY_USAGE, \ "MBEDTLS_X509_BADCERT_KEY_USAGE", \ "Usage does not match the keyUsage extension") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, \ "MBEDTLS_X509_BADCERT_EXT_KEY_USAGE", \ "Usage does not match the extendedKeyUsage extension") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_NS_CERT_TYPE, \ "MBEDTLS_X509_BADCERT_NS_CERT_TYPE", \ "Usage does not match the nsCertType extension") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_MD, \ "MBEDTLS_X509_BADCERT_BAD_MD", \ "The certificate is signed with an unacceptable hash.") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_PK, \ "MBEDTLS_X509_BADCERT_BAD_PK", \ "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCERT_BAD_KEY, \ "MBEDTLS_X509_BADCERT_BAD_KEY", \ "The certificate is signed with an unacceptable key (eg bad curve, RSA too short).") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_MD, \ "MBEDTLS_X509_BADCRL_BAD_MD", \ "The CRL is signed with an unacceptable hash.") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_PK, \ "MBEDTLS_X509_BADCRL_BAD_PK", \ "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA).") \ X509_CRT_ERROR_INFO(MBEDTLS_X509_BADCRL_BAD_KEY, \ "MBEDTLS_X509_BADCRL_BAD_KEY", \ "The CRL is signed with an unacceptable key (eg bad curve, RSA too short).") /** * Container for writing a certificate (CRT) */ typedef struct mbedtls_x509write_cert { int MBEDTLS_PRIVATE(version); unsigned char MBEDTLS_PRIVATE(serial)[MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN]; size_t MBEDTLS_PRIVATE(serial_len); mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key); mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(issuer); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); char MBEDTLS_PRIVATE(not_before)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; char MBEDTLS_PRIVATE(not_after)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); } mbedtls_x509write_cert; /** * \brief Set Subject Alternative Name * * \param ctx Certificate context to use * \param san_list List of SAN values * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED * * \note "dnsName", "uniformResourceIdentifier", "IP address", * "otherName", and "DirectoryName", as defined in RFC 5280, * are supported. */ int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, const mbedtls_x509_san_list *san_list); /** * Item in a verification chain: cert and flags for it */ typedef struct { mbedtls_x509_crt *MBEDTLS_PRIVATE(crt); uint32_t MBEDTLS_PRIVATE(flags); } mbedtls_x509_crt_verify_chain_item; /** * Max size of verification chain: end-entity + intermediates + trusted root */ #define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) /** * Verification chain as built by \c mbedtls_crt_verify_chain() */ typedef struct { mbedtls_x509_crt_verify_chain_item MBEDTLS_PRIVATE(items)[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; unsigned MBEDTLS_PRIVATE(len); #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* This stores the list of potential trusted signers obtained from * the CA callback used for the CRT verification, if configured. * We must track it somewhere because the callback passes its * ownership to the caller. */ mbedtls_x509_crt *MBEDTLS_PRIVATE(trust_ca_cb_result); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } mbedtls_x509_crt_verify_chain; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Context for resuming X.509 verify operations */ typedef struct { /* for check_signature() */ mbedtls_pk_restart_ctx MBEDTLS_PRIVATE(pk); /* for find_parent_in() */ mbedtls_x509_crt *MBEDTLS_PRIVATE(parent); /* non-null iff parent_in in progress */ mbedtls_x509_crt *MBEDTLS_PRIVATE(fallback_parent); int MBEDTLS_PRIVATE(fallback_signature_is_good); /* for find_parent() */ int MBEDTLS_PRIVATE(parent_is_trusted); /* -1 if find_parent is not in progress */ /* for verify_chain() */ enum { x509_crt_rs_none, x509_crt_rs_find_parent, } MBEDTLS_PRIVATE(in_progress); /* none if no operation is in progress */ int MBEDTLS_PRIVATE(self_cnt); mbedtls_x509_crt_verify_chain MBEDTLS_PRIVATE(ver_chain); } mbedtls_x509_crt_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_x509_crt_restart_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * Default security profile. Should provide a good balance between security * and compatibility with current deployments. * * This profile permits: * - SHA2 hashes with at least 256 bits: SHA-256, SHA-384, SHA-512. * - Elliptic curves with 255 bits and above except secp256k1. * - RSA with 2048 bits and above. * * New minor versions of Mbed TLS may extend this profile, for example if * new algorithms are added to the library. New minor versions of Mbed TLS will * not reduce this profile unless serious security concerns require it. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; /** * Expected next default profile. Recommended for new deployments. * Currently targets a 128-bit security level, except for allowing RSA-2048. * This profile may change at any time. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; /** * NSA Suite B profile. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; /** * Empty profile that allows nothing. Useful as a basis for constructing * custom profiles. */ extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none; /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through * mbedtls_x509_crt_init(). * \param buf The buffer holding the DER encoded certificate. * \param buflen The size in Bytes of \p buf. * * \note This function makes an internal copy of the CRT buffer * \p buf. In particular, \p buf may be destroyed or reused * after this call returns. To avoid duplicating the CRT * buffer (at the cost of stricter lifetime constraints), * use mbedtls_x509_crt_parse_der_nocopy() instead. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); /** * \brief The type of certificate extension callbacks. * * Callbacks of this type are passed to and used by the * mbedtls_x509_crt_parse_der_with_ext_cb() routine when * it encounters either an unsupported extension or a * "certificate policies" extension containing any * unsupported certificate policies. * Future versions of the library may invoke the callback * in other cases, if and when the need arises. * * \param p_ctx An opaque context passed to the callback. * \param crt The certificate being parsed. * \param oid The OID of the extension. * \param critical Whether the extension is critical. * \param p Pointer to the start of the extension value * (the content of the OCTET STRING). * \param end End of extension value. * * \note The callback must fail and return a negative error code * if it can not parse or does not support the extension. * When the callback fails to parse a critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. * When the callback fails to parse a non critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips * the extension and continues parsing. * * \return \c 0 on success. * \return A negative error code on failure. */ typedef int (*mbedtls_x509_crt_ext_cb_t)(void *p_ctx, mbedtls_x509_crt const *crt, mbedtls_x509_buf const *oid, int critical, const unsigned char *p, const unsigned char *end); /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through * mbedtls_x509_crt_init(). * \param buf The buffer holding the DER encoded certificate. * \param buflen The size in Bytes of \p buf. * \param make_copy When not zero this function makes an internal copy of the * CRT buffer \p buf. In particular, \p buf may be destroyed * or reused after this call returns. * When zero this function avoids duplicating the CRT buffer * by taking temporary ownership thereof until the CRT * is destroyed (like mbedtls_x509_crt_parse_der_nocopy()) * \param cb A callback invoked for every unsupported certificate * extension. * \param p_ctx An opaque context passed to the callback. * * \note This call is functionally equivalent to * mbedtls_x509_crt_parse_der(), and/or * mbedtls_x509_crt_parse_der_nocopy() * but it calls the callback with every unsupported * certificate extension and additionally the * "certificate policies" extension if it contains any * unsupported certificate policies. * The callback must return a negative error code if it * does not know how to handle such an extension. * When the callback fails to parse a critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. * When the callback fails to parse a non critical extension * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips * the extension and continues parsing. * Future versions of the library may invoke the callback * in other cases, if and when the need arises. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx); /** * \brief Parse a single DER formatted certificate and add it * to the end of the provided chained list. This is a * variant of mbedtls_x509_crt_parse_der() which takes * temporary ownership of the CRT buffer until the CRT * is destroyed. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The pointer to the start of the CRT chain to attach to. * When parsing the first CRT in a chain, this should point * to an instance of ::mbedtls_x509_crt initialized through * mbedtls_x509_crt_init(). * \param buf The address of the readable buffer holding the DER encoded * certificate to use. On success, this buffer must be * retained and not be changed for the lifetime of the * CRT chain \p chain, that is, until \p chain is destroyed * through a call to mbedtls_x509_crt_free(). * \param buflen The size in Bytes of \p buf. * * \note This call is functionally equivalent to * mbedtls_x509_crt_parse_der(), but it avoids creating a * copy of the input buffer at the cost of stronger lifetime * constraints. This is useful in constrained environments * where duplication of the CRT cannot be tolerated. * * \return \c 0 if successful. * \return A negative error code on failure. */ int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); /** * \brief Parse one DER-encoded or one or more concatenated PEM-encoded * certificates and add them to the chained list. * * For CRTs in PEM encoding, the function parses permissively: * if at least one certificate can be parsed, the function * returns the number of certificates for which parsing failed * (hence \c 0 if all certificates were parsed successfully). * If no certificate could be parsed, the function returns * the first (negative) error encountered during parsing. * * PEM encoded certificates may be interleaved by other data * such as human readable descriptions of their content, as * long as the certificates are enclosed in the PEM specific * '-----{BEGIN/END} CERTIFICATE-----' delimiters. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain The chain to which to add the parsed certificates. * \param buf The buffer holding the certificate data in PEM or DER format. * For certificates in PEM encoding, this may be a concatenation * of multiple certificates; for DER encoding, the buffer must * comprise exactly one certificate. * \param buflen The size of \p buf, including the terminating \c NULL byte * in case of PEM encoded data. * * \return \c 0 if all certificates were parsed successfully. * \return The (positive) number of certificates that couldn't * be parsed if parsing was partly successful (see above). * \return A negative X509 or PEM error code otherwise. * */ int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** * \brief Load one or more certificates and add them * to the chained list. Parses permissively. If some * certificates can be parsed, the result is the number * of failed certificates it encountered. If none complete * correctly, the first error is returned. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param chain points to the start of the chain * \param path filename to read the certificates from * * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path); /** * \brief Load one or more certificate files from a path and add them * to the chained list. Parses permissively. If some * certificates can be parsed, the result is the number * of failed certificates it encountered. If none complete * correctly, the first error is returned. * * \param chain points to the start of the chain * \param path directory / folder to read the certificate files from * * \return 0 if all certificates parsed successfully, a positive number * if partly successful or a specific X509 or PEM error code */ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path); #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the * certificate. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param crt The X509 certificate to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt); /** * \brief Returns an informational string about the * verification status of a certificate. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param flags Verification flags created by mbedtls_x509_crt_verify() * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, uint32_t flags); #endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Verify a chain of certificates. * * The verify callback is a user-supplied callback that * can clear / modify / add flags for a certificate. If set, * the verification callback is called for each * certificate in the chain (from the trust-ca down to the * presented crt). The parameters for the callback are: * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, * int *flags). With the flags representing current flags for * that specific certificate and the certificate depth from * the bottom (Peer cert depth = 0). * * All flags left after returning from the callback * are also returned to the application. The function should * return 0 for anything (including invalid certificates) * other than fatal error, as a non-zero return code * immediately aborts the verification process. For fatal * errors, a specific error code should be used (different * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR * can be used if no better code is available. * * \note In case verification failed, the results can be displayed * using \c mbedtls_x509_crt_verify_info() * * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the * default security profile. * * \note It is your responsibility to provide up-to-date CRLs for * all trusted CAs. If no CRL is provided for the CA that was * used to sign the certificate, CRL verification is skipped * silently, that is *without* setting any flag. * * \note The \c trust_ca list can contain two types of certificates: * (1) those of trusted root CAs, so that certificates * chaining up to those CAs will be trusted, and (2) * self-signed end-entity certificates to be trusted (for * specific peers you know) - in that case, the self-signed * certificate doesn't need to have the CA bit set. * * \param crt The certificate chain to be verified. * \param trust_ca The list of trusted CAs. * \param ca_crl The list of CRLs for trusted CAs. * \param cn The expected Common Name. This will be checked to be * present in the certificate's subjectAltNames extension or, * if this extension is absent, as a CN component in its * Subject name. DNS names and IP addresses are fully * supported, while the URI subtype is partially supported: * only exact matching, without any normalization procedures * described in 7.4 of RFC5280, will result in a positive * URI verification. * This may be \c NULL if the CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * * \return \c 0 if the chain is valid with respect to the * passed CN, CAs, CRLs and security profile. * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the * certificate chain verification failed. In this case, * \c *flags will have one or more * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX * flags set. * \return Another negative error code in case of a fatal error * encountered during the verification process. */ int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); /** * \brief Verify a chain of certificates with respect to * a configurable security profile. * * \note Same as \c mbedtls_x509_crt_verify(), but with explicit * security profile. * * \note The restrictions on keys (RSA minimum size, allowed curves * for ECDSA) apply to all certificates: trusted root, * intermediate CAs if any, and end entity certificate. * * \param crt The certificate chain to be verified. * \param trust_ca The list of trusted CAs. * \param ca_crl The list of CRLs for trusted CAs. * \param profile The security profile to use for the verification. * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * * \return \c 0 if the chain is valid with respect to the * passed CN, CAs, CRLs and security profile. * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the * certificate chain verification failed. In this case, * \c *flags will have one or more * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX * flags set. * \return Another negative error code in case of a fatal error * encountered during the verification process. */ int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); /** * \brief Restartable version of \c mbedtls_crt_verify_with_profile() * * \note Performs the same job as \c mbedtls_crt_verify_with_profile() * but can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * * \param crt The certificate chain to be verified. * \param trust_ca The list of trusted CAs. * \param ca_crl The list of CRLs for trusted CAs. * \param profile The security profile to use for the verification. * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * \param rs_ctx The restart context to use. This may be set to \c NULL * to disable restartable ECC. * * \return See \c mbedtls_crt_verify_with_profile(), or * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx); /** * \brief The type of trusted certificate callbacks. * * Callbacks of this type are passed to and used by the CRT * verification routine mbedtls_x509_crt_verify_with_ca_cb() * when looking for trusted signers of a given certificate. * * On success, the callback returns a list of trusted * certificates to be considered as potential signers * for the input certificate. * * \param p_ctx An opaque context passed to the callback. * \param child The certificate for which to search a potential signer. * This will point to a readable certificate. * \param candidate_cas The address at which to store the address of the first * entry in the generated linked list of candidate signers. * This will not be \c NULL. * * \note The callback must only return a non-zero value on a * fatal error. If, in contrast, the search for a potential * signer completes without a single candidate, the * callback must return \c 0 and set \c *candidate_cas * to \c NULL. * * \return \c 0 on success. In this case, \c *candidate_cas points * to a heap-allocated linked list of instances of * ::mbedtls_x509_crt, and ownership of this list is passed * to the caller. * \return A negative error code on failure. */ typedef int (*mbedtls_x509_crt_ca_cb_t)(void *p_ctx, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidate_cas); #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which * uses a callback to acquire the list of trusted CA * certificates. * * \param crt The certificate chain to be verified. * \param f_ca_cb The callback to be used to query for potential signers * of a given child certificate. See the documentation of * ::mbedtls_x509_crt_ca_cb_t for more information. * \param p_ca_cb The opaque context to be passed to \p f_ca_cb. * \param profile The security profile for the verification. * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. * If the verification couldn't be completed, the flag value is * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. * * \return See \c mbedtls_crt_verify_with_profile(). */ int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy); #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ /** * \brief Check usage of certificate against keyUsage extension. * * \param crt Leaf certificate used. * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT * before using the certificate to perform an RSA key * exchange). * * \note Except for decipherOnly and encipherOnly, a bit set in the * usage argument means this bit MUST be set in the * certificate. For decipherOnly and encipherOnly, it means * that bit MAY be set. * * \return 0 is these uses of the certificate are allowed, * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension * is present but does not match the usage argument. * * \note You should only call this function on leaf certificates, on * (intermediate) CAs the keyUsage extension is automatically * checked by \c mbedtls_x509_crt_verify(). */ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, unsigned int usage); /** * \brief Check usage of certificate against extendedKeyUsage. * * \param crt Leaf certificate used. * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or * MBEDTLS_OID_CLIENT_AUTH). * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). * * \return 0 if this use of the certificate is allowed, * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. * * \note Usually only makes sense on leaf certificates. */ int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len); #if defined(MBEDTLS_X509_CRL_PARSE_C) /** * \brief Verify the certificate revocation status * * \param crt a certificate to be verified * \param crl the CRL to verify against * * \return 1 if the certificate is revoked, 0 otherwise * */ int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl); #endif /* MBEDTLS_X509_CRL_PARSE_C */ /** * \brief Initialize a certificate (chain) * * \param crt Certificate chain to initialize */ void mbedtls_x509_crt_init(mbedtls_x509_crt *crt); /** * \brief Unallocate all certificate data * * \param crt Certificate chain to free */ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context */ void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx); /** * \brief Free the components of a restart context */ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /** * \brief Query certificate for given extension type * * \param[in] ctx Certificate context to be queried, must not be \c NULL * \param ext_type Extension type being queried for, must be a valid * extension type. Must be one of the MBEDTLS_X509_EXT_XXX * values * * \return 0 if the given extension type is not present, * non-zero otherwise */ static inline int mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx, int ext_type) { return ctx->MBEDTLS_PRIVATE(ext_types) & ext_type; } /** * \brief Access the ca_istrue field * * \param[in] crt Certificate to be queried, must not be \c NULL * * \return \c 1 if this a CA certificate \c 0 otherwise. * \return MBEDTLS_ERR_X509_INVALID_EXTENSIONS if the certificate does not contain * the Optional Basic Constraint extension. * */ int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt); /** \} name Structures and functions for parsing and writing X.509 certificates */ #if defined(MBEDTLS_X509_CRT_WRITE_C) /** * \brief Initialize a CRT writing context * * \param ctx CRT context to initialize */ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx); /** * \brief Set the version for a Certificate * Default: MBEDTLS_X509_CRT_VERSION_3 * * \param ctx CRT context to use * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or * MBEDTLS_X509_CRT_VERSION_3) */ void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version); #if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Set the serial number for a Certificate. * * \deprecated This function is deprecated and will be removed in a * future version of the library. Please use * mbedtls_x509write_crt_set_serial_raw() instead. * * \note Even though the MBEDTLS_BIGNUM_C guard looks redundant since * X509 depends on PK and PK depends on BIGNUM, this emphasizes * a direct dependency between X509 and BIGNUM which is going * to be deprecated in the future. * * \param ctx CRT context to use * \param serial serial number to set * * \return 0 if successful */ int MBEDTLS_DEPRECATED mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial); #endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED /** * \brief Set the serial number for a Certificate. * * \param ctx CRT context to use * \param serial A raw array of bytes containing the serial number in big * endian format * \param serial_len Length of valid bytes (expressed in bytes) in \p serial * input buffer * * \return 0 if successful, or * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the provided input buffer * is too big (longer than MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) */ int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, unsigned char *serial, size_t serial_len); /** * \brief Set the validity period for a Certificate * Timestamps should be in string format for UTC timezone * i.e. "YYYYMMDDhhmmss" * e.g. "20131231235959" for December 31st 2013 * at 23:59:59 * * \param ctx CRT context to use * \param not_before not_before timestamp * \param not_after not_after timestamp * * \return 0 if timestamp was parsed successfully, or * a specific error code */ int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before, const char *not_after); /** * \brief Set the issuer name for a Certificate * Issuer names should contain a comma-separated list * of OID types and values: * e.g. "C=UK,O=ARM,CN=Mbed TLS CA" * * \param ctx CRT context to use * \param issuer_name issuer name to set * * \return 0 if issuer name was parsed successfully, or * a specific error code */ int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, const char *issuer_name); /** * \brief Set the subject name for a Certificate * Subject names should contain a comma-separated list * of OID types and values: * e.g. "C=UK,O=ARM,CN=Mbed TLS Server 1" * * \param ctx CRT context to use * \param subject_name subject name to set * * \return 0 if subject name was parsed successfully, or * a specific error code */ int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx, const char *subject_name); /** * \brief Set the subject public key for the certificate * * \param ctx CRT context to use * \param key public key to include */ void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key); /** * \brief Set the issuer key used for signing the certificate * * \param ctx CRT context to use * \param key private key to sign with */ void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key); /** * \brief Set the MD algorithm to use for the signature * (e.g. MBEDTLS_MD_SHA1) * * \param ctx CRT context to use * \param md_alg MD algorithm to use */ void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg); /** * \brief Generic function to add to or replace an extension in the * CRT * * \param ctx CRT context to use * \param oid OID of the extension * \param oid_len length of the OID * \param critical if the extension is critical (per the RFC's definition) * \param val value of the extension OCTET STRING * \param val_len length of the value data * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len); /** * \brief Set the basicConstraints extension for a CRT * * \param ctx CRT context to use * \param is_ca is this a CA certificate * \param max_pathlen maximum length of certificate chains below this * certificate (only for CA certificates, -1 is * unlimited) * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen); #if defined(MBEDTLS_MD_CAN_SHA1) /** * \brief Set the subjectKeyIdentifier extension for a CRT * Requires that mbedtls_x509write_crt_set_subject_key() has been * called before * * \param ctx CRT context to use * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx); /** * \brief Set the authorityKeyIdentifier extension for a CRT * Requires that mbedtls_x509write_crt_set_issuer_key() has been * called before * * \param ctx CRT context to use * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx); #endif /* MBEDTLS_MD_CAN_SHA1 */ /** * \brief Set the Key Usage Extension flags * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) * * \param ctx CRT context to use * \param key_usage key usage flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, unsigned int key_usage); /** * \brief Set the Extended Key Usage Extension * (e.g. MBEDTLS_OID_SERVER_AUTH) * * \param ctx CRT context to use * \param exts extended key usage extensions to set, a sequence of * MBEDTLS_ASN1_OID objects * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, const mbedtls_asn1_sequence *exts); /** * \brief Set the Netscape Cert Type flags * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) * * \param ctx CRT context to use * \param ns_cert_type Netscape Cert Type flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, unsigned char ns_cert_type); /** * \brief Free the contents of a CRT write context * * \param ctx CRT context to free */ void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx); /** * \brief Write a built up certificate to a X509 DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx certificate to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a built up certificate to a X509 PEM string * * \param ctx certificate to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return 0 if successful, or a specific error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CRT_WRITE_C */ /** \} addtogroup x509_module */ #ifdef __cplusplus } #endif #endif /* mbedtls_x509_crt.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h000066400000000000000000000343571464416617300245060ustar00rootroot00000000000000/** * \file x509_csr.h * * \brief X.509 certificate signing request parsing and writing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_CSR_H #define MBEDTLS_X509_CSR_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #ifdef __cplusplus extern "C" { #endif /** * \addtogroup x509_module * \{ */ /** * \name Structures and functions for X.509 Certificate Signing Requests (CSR) * \{ */ /** * Certificate Signing Request (CSR) structure. * * Some fields of this structure are publicly readable. Do not modify * them except via Mbed TLS library functions: the effect of modifying * those fields or the data that those fields point to is unspecified. */ typedef struct mbedtls_x509_csr { mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ int version; /**< CSR version (1=v1). */ mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ mbedtls_pk_context pk; /**< Container for the public key context. */ unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */ int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ mbedtls_x509_buf sig_oid; mbedtls_x509_buf MBEDTLS_PRIVATE(sig); mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ } mbedtls_x509_csr; /** * Container for writing a CSR */ typedef struct mbedtls_x509write_csr { mbedtls_pk_context *MBEDTLS_PRIVATE(key); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); } mbedtls_x509write_csr; #if defined(MBEDTLS_X509_CSR_PARSE_C) /** * \brief Load a Certificate Signing Request (CSR) in DER format * * \note Any unsupported requested extensions are silently * ignored, unless the critical flag is set, in which case * the CSR is rejected. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer * * \return 0 if successful, or a specific X509 error code */ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen); /** * \brief The type of certificate extension callbacks. * * Callbacks of this type are passed to and used by the * mbedtls_x509_csr_parse_der_with_ext_cb() routine when * it encounters either an unsupported extension. * Future versions of the library may invoke the callback * in other cases, if and when the need arises. * * \param p_ctx An opaque context passed to the callback. * \param csr The CSR being parsed. * \param oid The OID of the extension. * \param critical Whether the extension is critical. * \param p Pointer to the start of the extension value * (the content of the OCTET STRING). * \param end End of extension value. * * \note The callback must fail and return a negative error code * if it can not parse or does not support the extension. * When the callback fails to parse a critical extension * mbedtls_x509_csr_parse_der_with_ext_cb() also fails. * When the callback fails to parse a non critical extension * mbedtls_x509_csr_parse_der_with_ext_cb() simply skips * the extension and continues parsing. * * \return \c 0 on success. * \return A negative error code on failure. */ typedef int (*mbedtls_x509_csr_ext_cb_t)(void *p_ctx, mbedtls_x509_csr const *csr, mbedtls_x509_buf const *oid, int critical, const unsigned char *p, const unsigned char *end); /** * \brief Load a Certificate Signing Request (CSR) in DER format * * \note Any unsupported requested extensions are silently * ignored, unless the critical flag is set, in which case * the result of the callback function decides whether * CSR is rejected. * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer * \param cb A callback invoked for every unsupported certificate * extension. * \param p_ctx An opaque context passed to the callback. * * \return 0 if successful, or a specific X509 error code */ int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx); /** * \brief Load a Certificate Signing Request (CSR), DER or PEM format * * \note See notes for \c mbedtls_x509_csr_parse_der() * * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto * subsystem must have been initialized by calling * psa_crypto_init() before calling this function. * * \param csr CSR context to fill * \param buf buffer holding the CRL data * \param buflen size of the buffer * (including the terminating null byte for PEM data) * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen); #if defined(MBEDTLS_FS_IO) /** * \brief Load a Certificate Signing Request (CSR) * * \note See notes for \c mbedtls_x509_csr_parse() * * \param csr CSR context to fill * \param path filename to read the CSR from * * \return 0 if successful, or a specific X509 or PEM error code */ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path); #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Returns an informational string about the * CSR. * * \param buf Buffer to write to * \param size Maximum size of buffer * \param prefix A line prefix * \param csr The X509 CSR to represent * * \return The length of the string written (not including the * terminated nul byte), or a negative error code. */ int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_csr *csr); #endif /* !MBEDTLS_X509_REMOVE_INFO */ /** * \brief Initialize a CSR * * \param csr CSR to initialize */ void mbedtls_x509_csr_init(mbedtls_x509_csr *csr); /** * \brief Unallocate all CSR data * * \param csr CSR to free */ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr); #endif /* MBEDTLS_X509_CSR_PARSE_C */ /** \} name Structures and functions for X.509 Certificate Signing Requests (CSR) */ #if defined(MBEDTLS_X509_CSR_WRITE_C) /** * \brief Initialize a CSR context * * \param ctx CSR context to initialize */ void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx); /** * \brief Set the subject name for a CSR * Subject names should contain a comma-separated list * of OID types and values: * e.g. "C=UK,O=ARM,CN=Mbed TLS Server 1" * * \param ctx CSR context to use * \param subject_name subject name to set * * \return 0 if subject name was parsed successfully, or * a specific error code */ int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, const char *subject_name); /** * \brief Set the key for a CSR (public key will be included, * private key used to sign the CSR when writing it) * * \param ctx CSR context to use * \param key Asymmetric key to include */ void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key); /** * \brief Set the MD algorithm to use for the signature * (e.g. MBEDTLS_MD_SHA1) * * \param ctx CSR context to use * \param md_alg MD algorithm to use */ void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg); /** * \brief Set the Key Usage Extension flags * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) * * \param ctx CSR context to use * \param key_usage key usage flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED * * \note The decipherOnly flag from the Key Usage * extension is represented by bit 8 (i.e. * 0x8000), which cannot typically be represented * in an unsigned char. Therefore, the flag * decipherOnly (i.e. * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this * function. */ int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage); /** * \brief Set Subject Alternative Name * * \param ctx CSR context to use * \param san_list List of SAN values * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED * * \note Only "dnsName", "uniformResourceIdentifier" and "otherName", * as defined in RFC 5280, are supported. */ int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, const mbedtls_x509_san_list *san_list); /** * \brief Set the Netscape Cert Type flags * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) * * \param ctx CSR context to use * \param ns_cert_type Netscape Cert Type flags to set * * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, unsigned char ns_cert_type); /** * \brief Generic function to add to or replace an extension in the * CSR * * \param ctx CSR context to use * \param oid OID of the extension * \param oid_len length of the OID * \param critical Set to 1 to mark the extension as critical, 0 otherwise. * \param val value of the extension OCTET STRING * \param val_len length of the value data * * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED */ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len); /** * \brief Free the contents of a CSR context * * \param ctx CSR context to free */ void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx); /** * \brief Write a CSR (Certificate Signing Request) to a * DER structure * Note: data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer * * \param ctx CSR to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return length of data written if successful, or a specific * error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_PEM_WRITE_C) /** * \brief Write a CSR (Certificate Signing Request) to a * PEM string * * \param ctx CSR to write away * \param buf buffer to write to * \param size size of the buffer * \param f_rng RNG function. This must not be \c NULL. * \param p_rng RNG parameter * * \return 0 if successful, or a specific error code * * \note \p f_rng is used for the signature operation. */ int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CSR_WRITE_C */ /** \} addtogroup x509_module */ #ifdef __cplusplus } #endif #endif /* mbedtls_x509_csr.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/000077500000000000000000000000001464416617300220765ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/build_info.h000066400000000000000000000007641464416617300243700ustar00rootroot00000000000000/** * \file psa/build_info.h * * \brief Build-time PSA configuration info * * Include this file if you need to depend on the * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE * in PSA cryptography core specific files. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILD_INFO_H #define PSA_CRYPTO_BUILD_INFO_H #include "mbedtls/build_info.h" #endif /* PSA_CRYPTO_BUILD_INFO_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto.h000066400000000000000000007202121464416617300235730ustar00rootroot00000000000000/** * \file psa/crypto.h * \brief Platform Security Architecture cryptography module */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_H #define PSA_CRYPTO_H #if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) #include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE #else #include "crypto_platform.h" #endif #include #ifdef __DOXYGEN_ONLY__ /* This __DOXYGEN_ONLY__ block contains mock definitions for things that * must be defined in the crypto_platform.h header. These mock definitions * are present in this file as a convenience to generate pretty-printed * documentation that includes those definitions. */ /** \defgroup platform Implementation-specific definitions * @{ */ /**@}*/ #endif /* __DOXYGEN_ONLY__ */ #ifdef __cplusplus extern "C" { #endif /* The file "crypto_types.h" declares types that encode errors, * algorithms, key types, policies, etc. */ #include "crypto_types.h" /** \defgroup version API version * @{ */ /** * The major version of this implementation of the PSA Crypto API */ #define PSA_CRYPTO_API_VERSION_MAJOR 1 /** * The minor version of this implementation of the PSA Crypto API */ #define PSA_CRYPTO_API_VERSION_MINOR 0 /**@}*/ /* The file "crypto_values.h" declares macros to build and analyze values * of integral types defined in "crypto_types.h". */ #include "crypto_values.h" /** \defgroup initialization Library initialization * @{ */ /** * \brief Library initialization. * * Applications must call this function before calling any other * function in this module. * * Applications may call this function more than once. Once a call * succeeds, subsequent calls are guaranteed to succeed. * * If the application calls other functions before calling psa_crypto_init(), * the behavior is undefined. Implementations are encouraged to either perform * the operation as if the library had been initialized or to return * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, * implementations should not return a success status if the lack of * initialization may have security implications, for example due to improper * seeding of the random number generator. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_crypto_init(void); /**@}*/ /** \addtogroup attributes * @{ */ /** \def PSA_KEY_ATTRIBUTES_INIT * * This macro returns a suitable initializer for a key attribute structure * of type #psa_key_attributes_t. */ /** Return an initial value for a key attributes structure. */ static psa_key_attributes_t psa_key_attributes_init(void); /** Declare a key as persistent and set its key identifier. * * If the attribute structure currently declares the key as volatile (which * is the default content of an attribute structure), this function sets * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. * * This function does not access storage, it merely stores the given * value in the structure. * The persistent key will be written to storage when the attribute * structure is passed to a key creation function such as * psa_import_key(), psa_generate_key(), psa_generate_key_ext(), * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext() * or psa_copy_key(). * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param key The persistent identifier for the key. */ static void psa_set_key_id(psa_key_attributes_t *attributes, mbedtls_svc_key_id_t key); #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER /** Set the owner identifier of a key. * * When key identifiers encode key owner identifiers, psa_set_key_id() does * not allow to define in key attributes the owner of volatile keys as * psa_set_key_id() enforces the key to be persistent. * * This function allows to set in key attributes the owner identifier of a * key. It is intended to be used for volatile keys. For persistent keys, * it is recommended to use the PSA Cryptography API psa_set_key_id() to define * the owner of a key. * * \param[out] attributes The attribute structure to write to. * \param owner The key owner identifier. */ static void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, mbedtls_key_owner_id_t owner); #endif /** Set the location of a persistent key. * * To make a key persistent, you must give it a persistent key identifier * with psa_set_key_id(). By default, a key that has a persistent identifier * is stored in the default storage area identifier by * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage * area, or to explicitly declare the key as volatile. * * This function does not access storage, it merely stores the given * value in the structure. * The persistent key will be written to storage when the attribute * structure is passed to a key creation function such as * psa_import_key(), psa_generate_key(), psa_generate_key_ext(), * psa_key_derivation_output_key(), psa_key_derivation_output_key_ext() * or psa_copy_key(). * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param lifetime The lifetime for the key. * If this is #PSA_KEY_LIFETIME_VOLATILE, the * key will be volatile, and the key identifier * attribute is reset to 0. */ static void psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime); /** Retrieve the key identifier from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The persistent identifier stored in the attribute structure. * This value is unspecified if the attribute structure declares * the key as volatile. */ static mbedtls_svc_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes); /** Retrieve the lifetime from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The lifetime value stored in the attribute structure. */ static psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes); /** Declare usage flags for a key. * * Usage flags are part of a key's usage policy. They encode what * kind of operations are permitted on the key. For more details, * refer to the documentation of the type #psa_key_usage_t. * * This function overwrites any usage flags * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param usage_flags The usage flags to write. */ static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags); /** Retrieve the usage flags from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The usage flags stored in the attribute structure. */ static psa_key_usage_t psa_get_key_usage_flags( const psa_key_attributes_t *attributes); /** Declare the permitted algorithm policy for a key. * * The permitted algorithm policy of a key encodes which algorithm or * algorithms are permitted to be used with this key. The following * algorithm policies are supported: * - 0 does not allow any cryptographic operation with the key. The key * may be used for non-cryptographic actions such as exporting (if * permitted by the usage flags). * - An algorithm value permits this particular algorithm. * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified * signature scheme with any hash algorithm. * - An algorithm built from #PSA_ALG_AT_LEAST_THIS_LENGTH_MAC allows * any MAC algorithm from the same base class (e.g. CMAC) which * generates/verifies a MAC length greater than or equal to the length * encoded in the wildcard algorithm. * - An algorithm built from #PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG * allows any AEAD algorithm from the same base class (e.g. CCM) which * generates/verifies a tag length greater than or equal to the length * encoded in the wildcard algorithm. * * This function overwrites any algorithm policy * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param alg The permitted algorithm policy to write. */ static void psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg); /** Retrieve the algorithm policy from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The algorithm stored in the attribute structure. */ static psa_algorithm_t psa_get_key_algorithm( const psa_key_attributes_t *attributes); /** Declare the type of a key. * * This function overwrites any key type * previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param type The key type to write. * If this is 0, the key type in \p attributes * becomes unspecified. */ static void psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type); /** Declare the size of a key. * * This function overwrites any key size previously set in \p attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate each of its arguments exactly once. * * \param[out] attributes The attribute structure to write to. * \param bits The key size in bits. * If this is 0, the key size in \p attributes * becomes unspecified. Keys of size 0 are * not supported. */ static void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits); /** Retrieve the key type from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The key type stored in the attribute structure. */ static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); /** Retrieve the key size from key attributes. * * This function may be declared as `static` (i.e. without external * linkage). This function may be provided as a function-like macro, * but in this case it must evaluate its argument exactly once. * * \param[in] attributes The key attribute structure to query. * * \return The key size stored in the attribute structure, in bits. */ static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); /** Retrieve the attributes of a key. * * This function first resets the attribute structure as with * psa_reset_key_attributes(). It then copies the attributes of * the given key into the given attribute structure. * * \note This function may allocate memory or other resources. * Once you have called this function on an attribute structure, * you must call psa_reset_key_attributes() to free these resources. * * \param[in] key Identifier of the key to query. * \param[in,out] attributes On success, the attributes of the key. * On failure, equivalent to a * freshly-initialized structure. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, psa_key_attributes_t *attributes); /** Reset a key attribute structure to a freshly initialized state. * * You must initialize the attribute structure as described in the * documentation of the type #psa_key_attributes_t before calling this * function. Once the structure has been initialized, you may call this * function at any time. * * This function frees any auxiliary resources that the structure * may contain. * * \param[in,out] attributes The attribute structure to reset. */ void psa_reset_key_attributes(psa_key_attributes_t *attributes); /**@}*/ /** \defgroup key_management Key management * @{ */ /** Remove non-essential copies of key material from memory. * * If the key identifier designates a volatile key, this functions does not do * anything and returns successfully. * * If the key identifier designates a persistent key, then this function will * free all resources associated with the key in volatile memory. The key * data in persistent storage is not affected and the key can still be used. * * \param key Identifier of the key to purge. * * \retval #PSA_SUCCESS * The key material will have been removed from memory if it is not * currently required. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not a valid key identifier. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); /** Make a copy of a key. * * Copy key material from one location to another. * * This function is primarily useful to copy a key from one location * to another, since it populates a key using the material from * another key which may have a different lifetime. * * This function may be used to share a key with a different party, * subject to implementation-defined restrictions on key sharing. * * The policy on the source key must have the usage flag * #PSA_KEY_USAGE_COPY set. * This flag is sufficient to permit the copy if the key has the lifetime * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. * Some secure elements do not provide a way to copy a key without * making it extractable from the secure element. If a key is located * in such a secure element, then the key must have both usage flags * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make * a copy of the key outside the secure element. * * The resulting key may only be used in a way that conforms to * both the policy of the original key and the policy specified in * the \p attributes parameter: * - The usage flags on the resulting key are the bitwise-and of the * usage flags on the source policy and the usage flags in \p attributes. * - If both allow the same algorithm or wildcard-based * algorithm policy, the resulting key has the same algorithm policy. * - If either of the policies allows an algorithm and the other policy * allows a wildcard-based algorithm policy that includes this algorithm, * the resulting key allows the same algorithm. * - If the policies do not allow any algorithm in common, this function * fails with the status #PSA_ERROR_INVALID_ARGUMENT. * * The effect of this function on implementation-defined attributes is * implementation-defined. * * \param source_key The key to copy. It must allow the usage * #PSA_KEY_USAGE_COPY. If a private or secret key is * being copied outside of a secure element it must * also allow #PSA_KEY_USAGE_EXPORT. * \param[in] attributes The attributes for the new key. * They are used as follows: * - The key type and size may be 0. If either is * nonzero, it must match the corresponding * attribute of the source key. * - The key location (the lifetime and, for * persistent keys, the key identifier) is * used directly. * - The policy constraints (usage flags and * algorithm policy) are combined from * the source key and \p attributes so that * both sets of restrictions apply, as * described in the documentation of this function. * \param[out] target_key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE * \p source_key is invalid. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INVALID_ARGUMENT * The lifetime or identifier in \p attributes are invalid, or * the policy constraints on the source and specified in * \p attributes are incompatible, or * \p attributes specifies a key type or key size * which does not match the attributes of the source key. * \retval #PSA_ERROR_NOT_PERMITTED * The source key does not have the #PSA_KEY_USAGE_COPY usage flag, or * the source key is not exportable and its lifetime does not * allow copying it to the target's lifetime. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *target_key); /** * \brief Destroy a key. * * This function destroys a key from both volatile * memory and, if applicable, non-volatile storage. Implementations shall * make a best effort to ensure that the key material cannot be recovered. * * This function also erases any metadata such as policies and frees * resources associated with the key. * * If a key is currently in use in a multipart operation, then destroying the * key will cause the multipart operation to fail. * * \warning We can only guarantee that the the key material will * eventually be wiped from memory. With threading enabled * and during concurrent execution, copies of the key material may * still exist until all threads have finished using the key. * * \param key Identifier of the key to erase. If this is \c 0, do nothing and * return #PSA_SUCCESS. * * \retval #PSA_SUCCESS * \p key was a valid identifier and the key material that it * referred to has been erased. Alternatively, \p key is \c 0. * \retval #PSA_ERROR_NOT_PERMITTED * The key cannot be erased because it is * read-only, either due to a policy or due to physical restrictions. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid identifier nor \c 0. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * There was a failure in communication with the cryptoprocessor. * The key material may still be present in the cryptoprocessor. * \retval #PSA_ERROR_DATA_INVALID * This error is typically a result of either storage corruption on a * cleartext storage backend, or an attempt to read data that was * written by an incompatible version of the library. * \retval #PSA_ERROR_STORAGE_FAILURE * The storage is corrupted. Implementations shall make a best effort * to erase key material even in this stage, however applications * should be aware that it may be impossible to guarantee that the * key material is not recoverable in such cases. * \retval #PSA_ERROR_CORRUPTION_DETECTED * An unexpected condition which is not a storage corruption or * a communication failure occurred. The cryptoprocessor may have * been compromised. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); /**@}*/ /** \defgroup import_export Key import and export * @{ */ /** * \brief Import a key in binary format. * * This function supports any output from psa_export_key(). Refer to the * documentation of psa_export_public_key() for the format of public keys * and to the documentation of psa_export_key() for the format for * other key types. * * The key data determines the key size. The attributes may optionally * specify a key size; in this case it must match the size determined * from the key data. A key size of 0 in \p attributes indicates that * the key size is solely determined by the key data. * * Implementations must reject an attempt to import a key of size 0. * * This specification supports a single format for each key type. * Implementations may support other formats as long as the standard * format is supported. Implementations that support other formats * should ensure that the formats are clearly unambiguous so as to * minimize the risk that an invalid input is accidentally interpreted * according to a different format. * * \param[in] attributes The attributes for the new key. * The key size is always determined from the * \p data buffer. * If the key size in \p attributes is nonzero, * it must be equal to the size from \p data. * \param[out] key On success, an identifier to the newly created key. * For persistent keys, this is the key identifier * defined in \p attributes. * \c 0 on failure. * \param[in] data Buffer containing the key data. The content of this * buffer is interpreted according to the type declared * in \p attributes. * All implementations must support at least the format * described in the documentation * of psa_export_key() or psa_export_public_key() for * the chosen type. Implementations may allow other * formats, but should be conservative: implementations * should err on the side of rejecting content if it * may be erroneous (e.g. wrong type or truncated data). * \param data_length Size of the \p data buffer in bytes. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular persistent location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key attributes, as a whole, are invalid, or * the key data is not correctly formatted, or * the size in \p attributes is nonzero and does not match the size * of the key data. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, mbedtls_svc_key_id_t *key); /** * \brief Export a key in binary format. * * The output of this function can be passed to psa_import_key() to * create an equivalent object. * * If the implementation of psa_import_key() supports other formats * beyond the format specified here, the output from psa_export_key() * must use the representation specified here, not the original * representation. * * For standard key types, the output format is as follows: * * - For symmetric keys (including MAC keys), the format is the * raw bytes of the key. * - For DES, the key data consists of 8 bytes. The parity bits must be * correct. * - For Triple-DES, the format is the concatenation of the * two or three DES keys. * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format * is the non-encrypted DER encoding of the representation defined by * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. * ``` * RSAPrivateKey ::= SEQUENCE { * version INTEGER, -- must be 0 * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * } * ``` * - For elliptic curve key pairs (key types for which * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is * a representation of the private value as a `ceiling(m/8)`-byte string * where `m` is the bit size associated with the curve, i.e. the bit size * of the order of the curve's coordinate field. This byte string is * in little-endian order for Montgomery curves (curve types * `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass * curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX` * and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`). * For Weierstrass curves, this is the content of the `privateKey` field of * the `ECPrivateKey` format defined by RFC 5915. For Montgomery curves, * the format is defined by RFC 7748, and output is masked according to §5. * For twisted Edwards curves, the private key is as defined by RFC 8032 * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). * - For Diffie-Hellman key exchange key pairs (key types for which * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the * format is the representation of the private key `x` as a big-endian byte * string. The length of the byte string is the private key size in bytes * (leading zeroes are not stripped). * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is * true), the format is the same as for psa_export_public_key(). * * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. * * \param key Identifier of the key to export. It must allow the * usage #PSA_KEY_USAGE_EXPORT, unless it is a public * key. * \param[out] data Buffer where the key data is to be written. * \param data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_EXPORT flag. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p data buffer is too small. You can determine a * sufficient buffer size by calling * #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits) * where \c type is the key type * and \c bits is the key size in bits. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_export_key(mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Export a public key or the public part of a key pair in binary format. * * The output of this function can be passed to psa_import_key() to * create an object that is equivalent to the public key. * * This specification supports a single format for each key type. * Implementations may support other formats as long as the standard * format is supported. Implementations that support other formats * should ensure that the formats are clearly unambiguous so as to * minimize the risk that an invalid input is accidentally interpreted * according to a different format. * * For standard key types, the output format is as follows: * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. * ``` * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER } -- e * ``` * - For elliptic curve keys on a twisted Edwards curve (key types for which * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY * returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined * by RFC 8032 * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). * - For other elliptic curve public keys (key types for which * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed * representation defined by SEC1 §2.3.3 as the content of an ECPoint. * Let `m` be the bit size associated with the curve, i.e. the bit size of * `q` for a curve over `F_q`. The representation consists of: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. * - For Diffie-Hellman key exchange public keys (key types for which * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), * the format is the representation of the public key `y = g^x mod p` as a * big-endian byte string. The length of the byte string is the length of the * base prime `p` in bytes. * * Exporting a public key object or the public part of a key pair is * always permitted, regardless of the key's usage flags. * * \param key Identifier of the key to export. * \param[out] data Buffer where the key data is to be written. * \param data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is neither a public key nor a key pair. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p data buffer is too small. You can determine a * sufficient buffer size by calling * #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) * where \c type is the key type * and \c bits is the key size in bits. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size, size_t *data_length); /**@}*/ /** \defgroup hash Message digests * @{ */ /** Calculate the hash (digest) of a message. * * \note To verify the hash of a message against an * expected value, use psa_hash_compare() instead. * * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * \param[in] input Buffer containing the message to hash. * \param input_length Size of the \p input buffer in bytes. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\p alg). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p hash_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_compute(psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Calculate the hash (digest) of a message and compare it with a * reference value. * * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * \param[in] input Buffer containing the message to hash. * \param input_length Size of the \p input buffer in bytes. * \param[out] hash Buffer containing the expected hash value. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The expected hash is identical to the actual hash of the input. * \retval #PSA_ERROR_INVALID_SIGNATURE * The hash of the message was calculated successfully, but it * differs from the expected hash. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p input_length or \p hash_length do not match the hash size for \p alg * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_compare(psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *hash, size_t hash_length); /** The type of the state data structure for multipart hash operations. * * Before calling any function on a hash operation object, the application must * initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_hash_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_hash_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, * for example: * \code * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; * \endcode * - Assign the result of the function psa_hash_operation_init() * to the structure, for example: * \code * psa_hash_operation_t operation; * operation = psa_hash_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_hash_operation_s psa_hash_operation_t; /** \def PSA_HASH_OPERATION_INIT * * This macro returns a suitable initializer for a hash operation object * of type #psa_hash_operation_t. */ /** Return an initial value for a hash operation object. */ static psa_hash_operation_t psa_hash_operation_init(void); /** Set up a multipart hash operation. * * The sequence of operations to calculate a hash (message digest) * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. * -# Call psa_hash_setup() to specify the algorithm. * -# Call psa_hash_update() zero, one or more times, passing a fragment * of the message each time. The hash that is calculated is the hash * of the concatenation of these messages in order. * -# To calculate the hash, call psa_hash_finish(). * To compare the hash with an expected value, call psa_hash_verify(). * * If an error occurs at any step after a call to psa_hash_setup(), the * operation will need to be reset by a call to psa_hash_abort(). The * application may call psa_hash_abort() at any time after the operation * has been initialized. * * After a successful call to psa_hash_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_hash_finish() or psa_hash_verify(). * - A call to psa_hash_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_hash_operation_t and not yet in use. * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported hash algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a hash algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, psa_algorithm_t alg); /** Add a message fragment to a multipart hash operation. * * The application must call psa_hash_setup() before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[in] input Buffer containing the message fragment to hash. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_update(psa_hash_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the hash of a message. * * The application must call psa_hash_setup() before calling this function. * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to psa_hash_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_hash_abort(). * * \warning Applications should not call this function if they expect * a specific value for the hash. Call psa_hash_verify() instead. * Beware that comparing integrity or authenticity data such as * hash values with a function such as \c memcmp is risky * because the time taken by the comparison may leak information * about the hashed data which could allow an attacker to guess * a valid hash and thereby bypass security controls. * * \param[in,out] operation Active hash operation. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\c alg) where \c alg is the * hash algorithm that is calculated. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p hash buffer is too small. You can determine a * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) * where \c alg is the hash algorithm that is calculated. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_finish(psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Finish the calculation of the hash of a message and compare it with * an expected value. * * The application must call psa_hash_setup() before calling this function. * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to psa_hash_update(). It then * compares the calculated hash with the expected hash passed as a * parameter to this function. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_hash_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual hash and the expected hash is performed * in constant time. * * \param[in,out] operation Active hash operation. * \param[in] hash Buffer containing the expected hash value. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The expected hash is identical to the actual hash of the message. * \retval #PSA_ERROR_INVALID_SIGNATURE * The hash of the message was calculated successfully, but it * differs from the expected hash. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, const uint8_t *hash, size_t hash_length); /** Abort a hash operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_hash_setup() again. * * You may call this function any time after the operation object has * been initialized by one of the methods described in #psa_hash_operation_t. * * In particular, calling psa_hash_abort() after the operation has been * terminated by a call to psa_hash_abort(), psa_hash_finish() or * psa_hash_verify() is safe and has no effect. * * \param[in,out] operation Initialized hash operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_abort(psa_hash_operation_t *operation); /** Clone a hash operation. * * This function copies the state of an ongoing hash operation to * a new operation object. In other words, this function is equivalent * to calling psa_hash_setup() on \p target_operation with the same * algorithm that \p source_operation was set up for, then * psa_hash_update() on \p target_operation with the same input that * that was passed to \p source_operation. After this function returns, the * two objects are independent, i.e. subsequent calls involving one of * the objects do not affect the other object. * * \param[in] source_operation The active hash operation to clone. * \param[in,out] target_operation The operation object to set up. * It must be initialized but not active. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The \p source_operation state is not valid (it must be active), or * the \p target_operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation); /**@}*/ /** \defgroup MAC Message authentication codes * @{ */ /** Calculate the MAC (message authentication code) of a message. * * \note To verify the MAC of a message against an * expected value, use psa_mac_verify() instead. * Beware that comparing integrity or authenticity data such as * MAC values with a function such as \c memcmp is risky * because the time taken by the comparison may leak information * about the MAC value which could allow an attacker to guess * a valid MAC and thereby bypass security controls. * * \param key Identifier of the key to use for the operation. It * must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * \param[in] input Buffer containing the input message. * \param input_length Size of the \p input buffer in bytes. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Size of the \p mac buffer in bytes. * \param[out] mac_length On success, the number of bytes * that make up the MAC value. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p mac_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Calculate the MAC of a message and compare it with a reference value. * * \param key Identifier of the key to use for the operation. It * must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * \param[in] input Buffer containing the input message. * \param input_length Size of the \p input buffer in bytes. * \param[out] mac Buffer containing the expected MAC value. * \param mac_length Size of the \p mac buffer in bytes. * * \retval #PSA_SUCCESS * The expected MAC is identical to the actual MAC of the input. * \retval #PSA_ERROR_INVALID_SIGNATURE * The MAC of the message was calculated successfully, but it * differs from the expected value. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *mac, size_t mac_length); /** The type of the state data structure for multipart MAC operations. * * Before calling any function on a MAC operation object, the application must * initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_mac_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_mac_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, * for example: * \code * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; * \endcode * - Assign the result of the function psa_mac_operation_init() * to the structure, for example: * \code * psa_mac_operation_t operation; * operation = psa_mac_operation_init(); * \endcode * * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_mac_operation_s psa_mac_operation_t; /** \def PSA_MAC_OPERATION_INIT * * This macro returns a suitable initializer for a MAC operation object of type * #psa_mac_operation_t. */ /** Return an initial value for a MAC operation object. */ static psa_mac_operation_t psa_mac_operation_init(void); /** Set up a multipart MAC calculation operation. * * This function sets up the calculation of the MAC * (message authentication code) of a byte string. * To verify the MAC of a message against an * expected value, use psa_mac_verify_setup() instead. * * The sequence of operations to calculate a MAC is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. * -# Call psa_mac_sign_setup() to specify the algorithm and key. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. * -# At the end of the message, call psa_mac_sign_finish() to finish * calculating the MAC value and retrieve it. * * If an error occurs at any step after a call to psa_mac_sign_setup(), the * operation will need to be reset by a call to psa_mac_abort(). The * application may call psa_mac_abort() at any time after the operation * has been initialized. * * After a successful call to psa_mac_sign_setup(), the application must * eventually terminate the operation through one of the following methods: * - A successful call to psa_mac_sign_finish(). * - A call to psa_mac_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_mac_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. It * must remain valid until the operation terminates. * It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Set up a multipart MAC verification operation. * * This function sets up the verification of the MAC * (message authentication code) of a byte string against an expected value. * * The sequence of operations to verify a MAC is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. * -# Call psa_mac_verify_setup() to specify the algorithm and key. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. * -# At the end of the message, call psa_mac_verify_finish() to finish * calculating the actual MAC of the message and verify it against * the expected value. * * If an error occurs at any step after a call to psa_mac_verify_setup(), the * operation will need to be reset by a call to psa_mac_abort(). The * application may call psa_mac_abort() at any time after the operation * has been initialized. * * After a successful call to psa_mac_verify_setup(), the application must * eventually terminate the operation through one of the following methods: * - A successful call to psa_mac_verify_finish(). * - A call to psa_mac_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_mac_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. It * must remain valid until the operation terminates. * It must allow the usage * PSA_KEY_USAGE_VERIFY_MESSAGE. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key is not compatible with \c alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a MAC algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The key could not be retrieved from storage. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Add a message fragment to a multipart MAC operation. * * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() * before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] input Buffer containing the message fragment to add to * the MAC calculation. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the MAC of a message. * * The application must call psa_mac_sign_setup() before calling this function. * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to psa_mac_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_mac_abort(). * * \warning Applications should not call this function if they expect * a specific value for the MAC. Call psa_mac_verify_finish() instead. * Beware that comparing integrity or authenticity data such as * MAC values with a function such as \c memcmp is risky * because the time taken by the comparison may leak information * about the MAC value which could allow an attacker to guess * a valid MAC and thereby bypass security controls. * * \param[in,out] operation Active MAC operation. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Size of the \p mac buffer in bytes. * \param[out] mac_length On success, the number of bytes * that make up the MAC value. This is always * #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg) * where \c key_type and \c key_bits are the type and * bit-size respectively of the key and \c alg is the * MAC algorithm that is calculated. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p mac buffer is too small. You can determine a * sufficient buffer size by calling PSA_MAC_LENGTH(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac sign * operation), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Finish the calculation of the MAC of a message and compare it with * an expected value. * * The application must call psa_mac_verify_setup() before calling this function. * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to psa_mac_update(). It then * compares the calculated MAC with the expected MAC passed as a * parameter to this function. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_mac_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual MAC and the expected MAC is performed * in constant time. * * \param[in,out] operation Active MAC operation. * \param[in] mac Buffer containing the expected MAC value. * \param mac_length Size of the \p mac buffer in bytes. * * \retval #PSA_SUCCESS * The expected MAC is identical to the actual MAC of the message. * \retval #PSA_ERROR_INVALID_SIGNATURE * The MAC of the message was calculated successfully, but it * differs from the expected MAC. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac verify * operation), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length); /** Abort a MAC operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_mac_sign_setup() or psa_mac_verify_setup() again. * * You may call this function any time after the operation object has * been initialized by one of the methods described in #psa_mac_operation_t. * * In particular, calling psa_mac_abort() after the operation has been * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or * psa_mac_verify_finish() is safe and has no effect. * * \param[in,out] operation Initialized MAC operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_mac_abort(psa_mac_operation_t *operation); /**@}*/ /** \defgroup cipher Symmetric ciphers * @{ */ /** Encrypt a message using a symmetric cipher. * * This function encrypts a message with a random IV (initialization * vector). Use the multipart operation interface with a * #psa_cipher_operation_t object to provide other forms of IV. * * \param key Identifier of the key to use for the operation. * It must allow the usage #PSA_KEY_USAGE_ENCRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] input Buffer containing the message to encrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * The output contains the IV followed by * the ciphertext proper. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Decrypt a message using a symmetric cipher. * * This function decrypts a message encrypted with a symmetric cipher. * * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] input Buffer containing the message to decrypt. * This consists of the IV followed by the * ciphertext proper. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the plaintext is to be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** The type of the state data structure for multipart cipher operations. * * Before calling any function on a cipher operation object, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_cipher_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_cipher_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, * for example: * \code * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; * \endcode * - Assign the result of the function psa_cipher_operation_init() * to the structure, for example: * \code * psa_cipher_operation_t operation; * operation = psa_cipher_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_cipher_operation_s psa_cipher_operation_t; /** \def PSA_CIPHER_OPERATION_INIT * * This macro returns a suitable initializer for a cipher operation object of * type #psa_cipher_operation_t. */ /** Return an initial value for a cipher operation object. */ static psa_cipher_operation_t psa_cipher_operation_init(void); /** Set the key for a multipart symmetric encryption operation. * * The sequence of operations to encrypt a message with a symmetric cipher * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_cipher_operation_t, e.g. * #PSA_CIPHER_OPERATION_INIT. * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to * generate or set the IV (initialization vector). You should use * psa_cipher_generate_iv() unless the protocol you are implementing * requires a specific IV value. * -# Call psa_cipher_update() zero, one or more times, passing a fragment * of the message each time. * -# Call psa_cipher_finish(). * * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), * the operation will need to be reset by a call to psa_cipher_abort(). The * application may call psa_cipher_abort() at any time after the operation * has been initialized. * * After a successful call to psa_cipher_encrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_cipher_finish(). * - A call to psa_cipher_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Set the key for a multipart symmetric decryption operation. * * The sequence of operations to decrypt a message with a symmetric cipher * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_cipher_operation_t, e.g. * #PSA_CIPHER_OPERATION_INIT. * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the * decryption. If the IV is prepended to the ciphertext, you can call * psa_cipher_update() on a buffer containing the IV followed by the * beginning of the message. * -# Call psa_cipher_update() zero, one or more times, passing a fragment * of the message each time. * -# Call psa_cipher_finish(). * * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), * the operation will need to be reset by a call to psa_cipher_abort(). The * application may call psa_cipher_abort() at any time after the operation * has been initialized. * * After a successful call to psa_cipher_decrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_cipher_finish(). * - A call to psa_cipher_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a cipher algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Generate an IV for a symmetric encryption operation. * * This function generates a random IV (initialization vector), nonce * or initial counter value for the encryption operation as appropriate * for the chosen algorithm, key type and key size. * * The application must call psa_cipher_encrypt_setup() before * calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[out] iv Buffer where the generated IV is to be written. * \param iv_size Size of the \p iv buffer in bytes. * \param[out] iv_length On success, the number of bytes of the * generated IV. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p iv buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with no IV set), * or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, uint8_t *iv, size_t iv_size, size_t *iv_length); /** Set the IV for a symmetric encryption or decryption operation. * * This function sets the IV (initialization vector), nonce * or initial counter value for the encryption or decryption operation. * * The application must call psa_cipher_encrypt_setup() before * calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \note When encrypting, applications should use psa_cipher_generate_iv() * instead of this function, unless implementing a protocol that requires * a non-random IV. * * \param[in,out] operation Active cipher operation. * \param[in] iv Buffer containing the IV to use. * \param iv_length Size of the IV in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active cipher * encrypt operation, with no IV set), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length); /** Encrypt or decrypt a message fragment in an active cipher operation. * * Before calling this function, you must: * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). * The choice of setup function determines whether this function * encrypts or decrypts its input. * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() * (recommended when encrypting) or psa_cipher_set_iv(). * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with an IV set * if required for the algorithm), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting or decrypting a message in a cipher operation. * * The application must call psa_cipher_encrypt_setup() or * psa_cipher_decrypt_setup() before calling this function. The choice * of setup function determines whether this function encrypts or * decrypts its input. * * This function finishes the encryption or decryption of the message * formed by concatenating the inputs passed to preceding calls to * psa_cipher_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_cipher_abort(). * * \param[in,out] operation Active cipher operation. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with an IV set * if required for the algorithm), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); /** Abort a cipher operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. * * You may call this function any time after the operation object has * been initialized as described in #psa_cipher_operation_t. * * In particular, calling psa_cipher_abort() after the operation has been * terminated by a call to psa_cipher_abort() or psa_cipher_finish() * is safe and has no effect. * * \param[in,out] operation Initialized cipher operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); /**@}*/ /** \defgroup aead Authenticated encryption with associated data (AEAD) * @{ */ /** Process an authenticated encryption operation. * * \param key Identifier of the key to use for the * operation. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the \p nonce buffer in bytes. * \param[in] additional_data Additional data that will be authenticated * but not encrypted. * \param additional_data_length Size of \p additional_data in bytes. * \param[in] plaintext Data that will be authenticated and * encrypted. * \param plaintext_length Size of \p plaintext in bytes. * \param[out] ciphertext Output buffer for the authenticated and * encrypted data. The additional data is not * part of this output. For algorithms where the * encrypted data and the authentication tag * are defined as separate outputs, the * authentication tag is appended to the * encrypted data. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, * \p alg, \p plaintext_length) where * \c key_type is the type of \p key. * - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p * plaintext_length) evaluates to the maximum * ciphertext size of any supported AEAD * encryption. * \param[out] ciphertext_length On success, the size of the output * in the \p ciphertext buffer. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p ciphertext_size is too small. * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg, * \p plaintext_length) or * #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to * determine the required buffer size. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length); /** Process an authenticated decryption operation. * * \param key Identifier of the key to use for the * operation. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the \p nonce buffer in bytes. * \param[in] additional_data Additional data that has been authenticated * but not encrypted. * \param additional_data_length Size of \p additional_data in bytes. * \param[in] ciphertext Data that has been authenticated and * encrypted. For algorithms where the * encrypted data and the authentication tag * are defined as separate inputs, the buffer * must contain the encrypted data followed * by the authentication tag. * \param ciphertext_length Size of \p ciphertext in bytes. * \param[out] plaintext Output buffer for the decrypted data. * \param plaintext_size Size of the \p plaintext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, * \p alg, \p ciphertext_length) where * \c key_type is the type of \p key. * - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p * ciphertext_length) evaluates to the maximum * plaintext size of any supported AEAD * decryption. * \param[out] plaintext_length On success, the size of the output * in the \p plaintext buffer. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The ciphertext is not authentic. * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p plaintext_size is too small. * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg, * \p ciphertext_length) or * #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used * to determine the required buffer size. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length); /** The type of the state data structure for multipart AEAD operations. * * Before calling any function on an AEAD operation object, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_aead_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_aead_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, * for example: * \code * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; * \endcode * - Assign the result of the function psa_aead_operation_init() * to the structure, for example: * \code * psa_aead_operation_t operation; * operation = psa_aead_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_aead_operation_s psa_aead_operation_t; /** \def PSA_AEAD_OPERATION_INIT * * This macro returns a suitable initializer for an AEAD operation object of * type #psa_aead_operation_t. */ /** Return an initial value for an AEAD operation object. */ static psa_aead_operation_t psa_aead_operation_init(void); /** Set the key for a multipart authenticated encryption operation. * * The sequence of operations to encrypt a message with authentication * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_aead_operation_t, e.g. * #PSA_AEAD_OPERATION_INIT. * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. * -# If needed, call psa_aead_set_lengths() to specify the length of the * inputs to the subsequent calls to psa_aead_update_ad() and * psa_aead_update(). See the documentation of psa_aead_set_lengths() * for details. * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to * generate or set the nonce. You should use * psa_aead_generate_nonce() unless the protocol you are implementing * requires a specific nonce value. * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment * of the non-encrypted additional authenticated data each time. * -# Call psa_aead_update() zero, one or more times, passing a fragment * of the message to encrypt each time. * -# Call psa_aead_finish(). * * If an error occurs at any step after a call to psa_aead_encrypt_setup(), * the operation will need to be reset by a call to psa_aead_abort(). The * application may call psa_aead_abort() at any time after the operation * has been initialized. * * After a successful call to psa_aead_encrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_aead_finish(). * - A call to psa_aead_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_aead_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Set the key for a multipart authenticated decryption operation. * * The sequence of operations to decrypt a message with authentication * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_aead_operation_t, e.g. * #PSA_AEAD_OPERATION_INIT. * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. * -# If needed, call psa_aead_set_lengths() to specify the length of the * inputs to the subsequent calls to psa_aead_update_ad() and * psa_aead_update(). See the documentation of psa_aead_set_lengths() * for details. * -# Call psa_aead_set_nonce() with the nonce for the decryption. * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment * of the non-encrypted additional authenticated data each time. * -# Call psa_aead_update() zero, one or more times, passing a fragment * of the ciphertext to decrypt each time. * -# Call psa_aead_verify(). * * If an error occurs at any step after a call to psa_aead_decrypt_setup(), * the operation will need to be reset by a call to psa_aead_abort(). The * application may call psa_aead_abort() at any time after the operation * has been initialized. * * After a successful call to psa_aead_decrypt_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to psa_aead_verify(). * - A call to psa_aead_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #psa_aead_operation_t and not yet in use. * \param key Identifier of the key to use for the operation. * It must remain valid until the operation * terminates. It must allow the usage * #PSA_KEY_USAGE_DECRYPT. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not an AEAD algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or the * library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg); /** Generate a random nonce for an authenticated encryption operation. * * This function generates a random nonce for the authenticated encryption * operation with an appropriate size for the chosen algorithm, key type * and key size. * * The application must call psa_aead_encrypt_setup() before * calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[out] nonce Buffer where the generated nonce is to be * written. * \param nonce_size Size of the \p nonce buffer in bytes. * \param[out] nonce_length On success, the number of bytes of the * generated nonce. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p nonce buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active aead encrypt * operation, with no nonce set), or the library has not been * previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, uint8_t *nonce, size_t nonce_size, size_t *nonce_length); /** Set the nonce for an authenticated encryption or decryption operation. * * This function sets the nonce for the authenticated * encryption or decryption operation. * * The application must call psa_aead_encrypt_setup() or * psa_aead_decrypt_setup() before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \note When encrypting, applications should use psa_aead_generate_nonce() * instead of this function, unless implementing a protocol that requires * a non-random IV. * * \param[in,out] operation Active AEAD operation. * \param[in] nonce Buffer containing the nonce to use. * \param nonce_length Size of the nonce in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p nonce is not acceptable for the chosen algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, with no nonce * set), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length); /** Declare the lengths of the message and additional data for AEAD. * * The application must call this function before calling * psa_aead_update_ad() or psa_aead_update() if the algorithm for * the operation requires it. If the algorithm does not require it, * calling this function is optional, but if this function is called * then the implementation must enforce the lengths. * * You may call this function before or after setting the nonce with * psa_aead_set_nonce() or psa_aead_generate_nonce(). * * - For #PSA_ALG_CCM, calling this function is required. * - For the other AEAD algorithms defined in this specification, calling * this function is not required. * - For vendor-defined algorithm, refer to the vendor documentation. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param ad_length Size of the non-encrypted additional * authenticated data in bytes. * \param plaintext_length Size of the plaintext to encrypt in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * At least one of the lengths is not acceptable for the chosen * algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, and * psa_aead_update_ad() and psa_aead_update() must not have been * called yet), or the library has not been previously initialized * by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length); /** Pass additional data to an active AEAD operation. * * Additional data is authenticated, but not encrypted. * * You may call this function multiple times to pass successive fragments * of the additional data. You may not call this function after passing * data to encrypt or decrypt with psa_aead_update(). * * Before calling this function, you must: * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, * there is no guarantee that the input is valid. Therefore, until * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, * treat the input as untrusted and prepare to undo any action that * depends on the input if psa_aead_verify() returns an error status. * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the fragment of * additional data. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total input length overflows the additional data length that * was previously specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, have a nonce * set, have lengths set if required by the algorithm, and * psa_aead_update() must not have been called yet), or the library * has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, const uint8_t *input, size_t input_length); /** Encrypt or decrypt a message fragment in an active AEAD operation. * * Before calling this function, you must: * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). * The choice of setup function determines whether this function * encrypts or decrypts its input. * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). * 3. Call psa_aead_update_ad() to pass all the additional data. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, * there is no guarantee that the input is valid. Therefore, until * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: * - Do not use the output in any way other than storing it in a * confidential location. If you take any action that depends * on the tentative decrypted data, this action will need to be * undone if the input turns out not to be valid. Furthermore, * if an adversary can observe that this action took place * (for example through timing), they may be able to use this * fact as an oracle to decrypt any message encrypted with the * same key. * - In particular, do not copy the output anywhere but to a * memory or storage space that you have exclusive access to. * * This function does not require the input to be aligned to any * particular block boundary. If the implementation can only process * a whole block at a time, it must consume all the input provided, but * it may delay the end of the corresponding output until a subsequent * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() * provides sufficient input. The amount of data that can be delayed * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, * \c alg, \p input_length) where * \c key_type is the type of key and \c alg is * the algorithm that were used to set up the * operation. * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p * input_length) evaluates to the maximum * output size of any supported AEAD * algorithm. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to * determine the required buffer size. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously * specified with psa_aead_set_lengths(), or * the total input length overflows the plaintext length that * was previously specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, have a nonce * set, and have lengths set if required by the algorithm), or the * library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_update(psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting a message in an AEAD operation. * * The operation must have been set up with psa_aead_encrypt_setup(). * * This function finishes the authentication of the additional data * formed by concatenating the inputs passed to preceding calls to * psa_aead_update_ad() with the plaintext formed by concatenating the * inputs passed to preceding calls to psa_aead_update(). * * This function has two output buffers: * - \p ciphertext contains trailing ciphertext that was buffered from * preceding calls to psa_aead_update(). * - \p tag contains the authentication tag. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[out] ciphertext Buffer where the last part of the ciphertext * is to be written. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, * \c alg) where \c key_type is the type of key * and \c alg is the algorithm that were used to * set up the operation. * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to * the maximum output size of any supported AEAD * algorithm. * \param[out] ciphertext_length On success, the number of bytes of * returned ciphertext. * \param[out] tag Buffer where the authentication tag is * to be written. * \param tag_size Size of the \p tag buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c * key_type, \c key_bits, \c alg) where * \c key_type and \c key_bits are the type and * bit-size of the key, and \c alg is the * algorithm that were used in the call to * psa_aead_encrypt_setup(). * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the * maximum tag size of any supported AEAD * algorithm. * \param[out] tag_length On success, the number of bytes * that make up the returned tag. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p ciphertext or \p tag buffer is too small. * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, \c alg) or * #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the * required \p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\c key_type, * \c key_bits, \c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to * determine the required \p tag buffer size. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously * specified with psa_aead_set_lengths(), or * the total length of input to psa_aead_update() so far is * less than the plaintext length that was previously * specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active encryption * operation with a nonce set), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_finish(psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length); /** Finish authenticating and decrypting a message in an AEAD operation. * * The operation must have been set up with psa_aead_decrypt_setup(). * * This function finishes the authenticated decryption of the message * components: * * - The additional data consisting of the concatenation of the inputs * passed to preceding calls to psa_aead_update_ad(). * - The ciphertext consisting of the concatenation of the inputs passed to * preceding calls to psa_aead_update(). * - The tag passed to this function call. * * If the authentication tag is correct, this function outputs any remaining * plaintext and reports success. If the authentication tag is not correct, * this function returns #PSA_ERROR_INVALID_SIGNATURE. * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_aead_abort(). * * \note Implementations shall make the best effort to ensure that the * comparison between the actual tag and the expected tag is performed * in constant time. * * \param[in,out] operation Active AEAD operation. * \param[out] plaintext Buffer where the last part of the plaintext * is to be written. This is the remaining data * from previous calls to psa_aead_update() * that could not be processed until the end * of the input. * \param plaintext_size Size of the \p plaintext buffer in bytes. * This must be appropriate for the selected algorithm and key: * - A sufficient output size is * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, * \c alg) where \c key_type is the type of key * and \c alg is the algorithm that were used to * set up the operation. * - #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE evaluates to * the maximum output size of any supported AEAD * algorithm. * \param[out] plaintext_length On success, the number of bytes of * returned plaintext. * \param[in] tag Buffer containing the authentication tag. * \param tag_length Size of the \p tag buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculations were successful, but the authentication tag is * not correct. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p plaintext buffer is too small. * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, \c alg) or * #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the * required buffer size. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously * specified with psa_aead_set_lengths(), or * the total length of input to psa_aead_update() so far is * less than the plaintext length that was previously * specified with psa_aead_set_lengths(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active decryption * operation with a nonce set), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_verify(psa_aead_operation_t *operation, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length, const uint8_t *tag, size_t tag_length); /** Abort an AEAD operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. * * You may call this function any time after the operation object has * been initialized as described in #psa_aead_operation_t. * * In particular, calling psa_aead_abort() after the operation has been * terminated by a call to psa_aead_abort(), psa_aead_finish() or * psa_aead_verify() is safe and has no effect. * * \param[in,out] operation Initialized AEAD operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_aead_abort(psa_aead_operation_t *operation); /**@}*/ /** \defgroup asymmetric Asymmetric cryptography * @{ */ /** * \brief Sign a message with a private key. For hash-and-sign algorithms, * this includes the hashing step. * * \note To perform a multi-part hash-and-sign signature algorithm, first use * a multi-part hash operation and then pass the resulting hash to * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the * hash algorithm to use. * * \param[in] key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE. * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) * is true), that is compatible with the type of * \p key. * \param[in] input The input message to sign. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. This * must be appropriate for the selected * algorithm and key: * - The required signature size is * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and * bit-size respectively of key. * - #PSA_SIGNATURE_MAX_SIZE evaluates to the * maximum signature size of any supported * signature algorithm. * \param[out] signature_length On success, the number of bytes that make up * the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, * or it does not permit the requested algorithm. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** \brief Verify the signature of a message with a public key, using * a hash-and-sign verification algorithm. * * \note To perform a multi-part hash-and-sign signature verification * algorithm, first use a multi-part hash operation to hash the message * and then pass the resulting hash to psa_verify_hash(). * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm * to use. * * \param[in] key Identifier of the key to use for the operation. * It must be a public key or an asymmetric key * pair. The key must allow the usage * #PSA_KEY_USAGE_VERIFY_MESSAGE. * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) * is true), that is compatible with the type of * \p key. * \param[in] input The message whose signature is to be verified. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, * or it does not permit the requested algorithm. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed signature * is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length); /** * \brief Sign a hash or short message with a private key. * * Note that to perform a hash-and-sign signature algorithm, you must * first calculate the hash by calling psa_hash_setup(), psa_hash_update() * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). * Then pass the resulting hash as the \p hash * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_HASH. * \param alg A signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify the signature of a hash or short message using a public key. * * Note that to perform a hash-and-sign signature algorithm, you must * first calculate the hash by calling psa_hash_setup(), psa_hash_update() * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). * Then pass the resulting hash as the \p hash * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * * \param key Identifier of the key to use for the operation. It * must be a public key or an asymmetric key pair. The * key must allow the usage * #PSA_KEY_USAGE_VERIFY_HASH. * \param alg A signature algorithm (PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message whose signature is to be * verified. * \param hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Encrypt a short message with a public key. * * \param key Identifier of the key to use for the operation. * It must be a public key or an asymmetric key * pair. It must allow the usage * #PSA_KEY_USAGE_ENCRYPT. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to encrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the encrypted message is to * be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); /** * \brief Decrypt a short message with a private key. * * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. It must * allow the usage #PSA_KEY_USAGE_DECRYPT. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the decrypted message is to * be written. * \param output_size Size of the \c output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INVALID_PADDING \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); /**@}*/ /** \defgroup key_derivation Key derivation and pseudorandom generation * @{ */ /** The type of the state data structure for key derivation operations. * * Before calling any function on a key derivation operation object, the * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_key_derivation_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_key_derivation_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, * for example: * \code * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; * \endcode * - Assign the result of the function psa_key_derivation_operation_init() * to the structure, for example: * \code * psa_key_derivation_operation_t operation; * operation = psa_key_derivation_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_key_derivation_s psa_key_derivation_operation_t; /** \def PSA_KEY_DERIVATION_OPERATION_INIT * * This macro returns a suitable initializer for a key derivation operation * object of type #psa_key_derivation_operation_t. */ /** Return an initial value for a key derivation operation object. */ static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); /** Set up a key derivation operation. * * A key derivation algorithm takes some inputs and uses them to generate * a byte stream in a deterministic way. * This byte stream can be used to produce keys and other * cryptographic material. * * To derive a key: * -# Start with an initialized object of type #psa_key_derivation_operation_t. * -# Call psa_key_derivation_setup() to select the algorithm. * -# Provide the inputs for the key derivation by calling * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() * as appropriate. Which inputs are needed, in what order, and whether * they may be keys and if so of what type depends on the algorithm. * -# Optionally set the operation's maximum capacity with * psa_key_derivation_set_capacity(). You may do this before, in the middle * of or after providing inputs. For some algorithms, this step is mandatory * because the output depends on the maximum capacity. * -# To derive a key, call psa_key_derivation_output_key() or * psa_key_derivation_output_key_ext(). * To derive a byte string for a different purpose, call * psa_key_derivation_output_bytes(). * Successive calls to these functions use successive output bytes * calculated by the key derivation algorithm. * -# Clean up the key derivation operation object with * psa_key_derivation_abort(). * * If this function returns an error, the key derivation operation object is * not changed. * * If an error occurs at any step after a call to psa_key_derivation_setup(), * the operation will need to be reset by a call to psa_key_derivation_abort(). * * Implementations must reject an attempt to derive a key of size 0. * * \param[in,out] operation The key derivation operation object * to set up. It must * have been initialized but not set up yet. * \param alg The key derivation algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c alg is not a key derivation algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a key derivation algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation, psa_algorithm_t alg); /** Retrieve the current capacity of a key derivation operation. * * The capacity of a key derivation is the maximum number of bytes that it can * return. When you get *N* bytes of output from a key derivation operation, * this reduces its capacity by *N*. * * \param[in] operation The operation to query. * \param[out] capacity On success, the capacity of the operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_get_capacity( const psa_key_derivation_operation_t *operation, size_t *capacity); /** Set the maximum capacity of a key derivation operation. * * The capacity of a key derivation operation is the maximum number of bytes * that the key derivation operation can return from this point onwards. * * \param[in,out] operation The key derivation operation object to modify. * \param capacity The new capacity of the operation. * It must be less or equal to the operation's * current capacity. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p capacity is larger than the operation's current capacity. * In this case, the operation object remains valid and its capacity * remains unchanged. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active), or the * library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *operation, size_t capacity); /** Use the maximum possible capacity for a key derivation operation. * * Use this value as the capacity argument when setting up a key derivation * to indicate that the operation should have the maximum possible capacity. * The value of the maximum possible capacity depends on the key derivation * algorithm. */ #define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t) (-1)) /** Provide an input for key derivation or key agreement. * * Which inputs are required and in what order depends on the algorithm. * Refer to the documentation of each key derivation or key agreement * algorithm for information. * * This function passes direct inputs, which is usually correct for * non-secret inputs. To pass a secret input, which should be in a key * object, call psa_key_derivation_input_key() instead of this function. * Refer to the documentation of individual step types * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) * for more information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() and must not * have produced any output yet. * \param step Which step the input data is for. * \param[in] data Input data to use. * \param data_length Size of the \p data buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow direct inputs. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this input \p step, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_input_bytes( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length); /** Provide a numeric input for key derivation or key agreement. * * Which inputs are required and in what order depends on the algorithm. * However, when an algorithm requires a particular order, numeric inputs * usually come first as they tend to be configuration parameters. * Refer to the documentation of each key derivation or key agreement * algorithm for information. * * This function is used for inputs which are fixed-size non-negative * integers. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() and must not * have produced any output yet. * \param step Which step the input data is for. * \param[in] value The value of the numeric input. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow numeric inputs. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this input \p step, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_input_integer( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, uint64_t value); /** Provide an input for key derivation in the form of a key. * * Which inputs are required and in what order depends on the algorithm. * Refer to the documentation of each key derivation or key agreement * algorithm for information. * * This function obtains input from a key object, which is usually correct for * secret inputs or for non-secret personalization strings kept in the key * store. To pass a non-secret parameter which is not in the key store, * call psa_key_derivation_input_bytes() instead of this function. * Refer to the documentation of individual step types * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) * for more information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() and must not * have produced any output yet. * \param step Which step the input data is for. * \param key Identifier of the key. It must have an * appropriate type for step and must allow the * usage #PSA_KEY_USAGE_DERIVE or * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note) * and the algorithm used by the operation. * * \note Once all inputs steps are completed, the operations will allow: * - psa_key_derivation_output_bytes() if each input was either a direct input * or a key with #PSA_KEY_USAGE_DERIVE set; * - psa_key_derivation_output_key() or psa_key_derivation_output_key_ext() * if the input for step * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set; * - psa_key_derivation_verify_bytes() if each input was either a direct input * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set; * - psa_key_derivation_verify_key() under the same conditions as * psa_key_derivation_verify_bytes(). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key allows neither #PSA_KEY_USAGE_DERIVE nor * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this * algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c step is not compatible with the operation's algorithm, or * \c step does not allow key inputs of the given type * or does not allow key inputs at all. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this input \p step, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_input_key( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t key); /** Perform a key agreement and use the shared secret as input to a key * derivation. * * A key agreement algorithm takes two inputs: a private key \p private_key * a public key \p peer_key. * The result of this function is passed as input to a key derivation. * The output of this key derivation can be extracted by reading from the * resulting operation to produce keys and other cryptographic material. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to use. * It must have been set up with * psa_key_derivation_setup() with a * key agreement and derivation algorithm * \c alg (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) * is false). * The operation must be ready for an * input of the type given by \p step. * \param step Which step the input data is for. * \param private_key Identifier of the private key to use. It must * allow the usage #PSA_KEY_USAGE_DERIVE. * \param[in] peer_key Public key of the peer. The peer key must be in the * same format that psa_import_key() accepts for the * public key type corresponding to the type of * private_key. That is, this function performs the * equivalent of * #psa_import_key(..., * `peer_key`, `peer_key_length`) where * with key attributes indicating the public key * type corresponding to the type of `private_key`. * For example, for EC keys, this means that peer_key * is interpreted as a point on the curve that the * private key is on. The standard formats for public * keys are documented in the documentation of * psa_export_public_key(). * \param peer_key_length Size of \p peer_key in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \c private_key is not compatible with \c alg, * or \p peer_key is not valid for \c alg or not compatible with * \c private_key, or \c step does not allow an input resulting * from a key agreement. * \retval #PSA_ERROR_NOT_SUPPORTED * \c alg is not supported or is not a key derivation algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid for this key agreement \p step, * or the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key, size_t peer_key_length); /** Read some data from a key derivation operation. * * This function calculates output bytes from a key derivation algorithm and * return those bytes. * If you view the key derivation's output as a stream of bytes, this * function destructively reads the requested number of bytes from the * stream. * The operation's capacity decreases by the number of bytes read. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to read from. * \param[out] output Buffer where the output will be written. * \param output_length Number of bytes to output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * One of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * \p output_length bytes. Note that in this case, * no output is written to the output buffer. * The operation's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller output buffer. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_bytes( psa_key_derivation_operation_t *operation, uint8_t *output, size_t output_length); /** Derive a key from an ongoing key derivation operation. * * This function calculates output bytes from a key derivation algorithm * and uses those bytes to generate a key deterministically. * The key's location, usage policy, type and size are taken from * \p attributes. * * If you view the key derivation's output as a stream of bytes, this * function destructively reads as many bytes as required from the * stream. * The operation's capacity decreases by the number of bytes read. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error * state and must be aborted by calling psa_key_derivation_abort(). * * How much output is produced and consumed from the operation, and how * the key is derived, depends on the key type and on the key size * (denoted \c bits below): * * - For key types for which the key is an arbitrary sequence of bytes * of a given size, this function is functionally equivalent to * calling #psa_key_derivation_output_bytes * and passing the resulting output to #psa_import_key. * However, this function has a security benefit: * if the implementation provides an isolation boundary then * the key material is not exposed outside the isolation boundary. * As a consequence, for these key types, this function always consumes * exactly (\c bits / 8) bytes from the operation. * The following key types defined in this specification follow this scheme: * * - #PSA_KEY_TYPE_AES; * - #PSA_KEY_TYPE_ARIA; * - #PSA_KEY_TYPE_CAMELLIA; * - #PSA_KEY_TYPE_DERIVE; * - #PSA_KEY_TYPE_HMAC; * - #PSA_KEY_TYPE_PASSWORD_HASH. * * - For ECC keys on a Montgomery elliptic curve * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a * Montgomery curve), this function always draws a byte string whose * length is determined by the curve, and sets the mandatory bits * accordingly. That is: * * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte * string and process it as specified in RFC 7748 §5. * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte * string and process it as specified in RFC 7748 §5. * * - For key types for which the key is represented by a single sequence of * \c bits bits with constraints as to which bit sequences are acceptable, * this function draws a byte string of length (\c bits / 8) bytes rounded * up to the nearest whole number of bytes. If the resulting byte string * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. * This process is repeated until an acceptable byte string is drawn. * The byte string drawn from the operation is interpreted as specified * for the output produced by psa_export_key(). * The following key types defined in this specification follow this scheme: * * - #PSA_KEY_TYPE_DES. * Force-set the parity bits, but discard forbidden weak keys. * For 2-key and 3-key triple-DES, the three keys are generated * successively (for example, for 3-key triple-DES, * if the first 8 bytes specify a weak key and the next 8 bytes do not, * discard the first 8 bytes, use the next 8 bytes as the first key, * and continue reading output from the operation to derive the other * two keys). * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) * where \c group designates any Diffie-Hellman group) and * ECC keys on a Weierstrass elliptic curve * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a * Weierstrass curve). * For these key types, interpret the byte string as integer * in big-endian order. Discard it if it is not in the range * [0, *N* - 2] where *N* is the boundary of the private key domain * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, * or the order of the curve's base point for ECC). * Add 1 to the resulting integer and use this as the private key *x*. * This method allows compliance to NIST standards, specifically * the methods titled "key-pair generation by testing candidates" * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, * in FIPS 186-4 §B.1.2 for DSA, and * in NIST SP 800-56A §5.6.1.2.2 or * FIPS 186-4 §B.4.2 for elliptic curve keys. * * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, * the way in which the operation output is consumed is * implementation-defined. * * In all cases, the data that is read is discarded from the operation. * The operation's capacity is decreased by the number of bytes read. * * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, * the input to that step must be provided with psa_key_derivation_input_key(). * Future versions of this specification may include additional restrictions * on the derived key based on the attributes and strength of the secret key. * * \note This function is equivalent to calling * psa_key_derivation_output_key_ext() * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT * and `params_data_length == 0` (i.e. `params->data` is empty). * * \param[in] attributes The attributes for the new key. * If the key type to be created is * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in * the policy must be the same as in the current * operation. * \param[in,out] operation The key derivation operation object to read from. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INSUFFICIENT_DATA * There was not enough data to create the desired key. * Note that in this case, no output is written to the output buffer. * The operation's capacity is set to 0, thus subsequent calls to * this function will not succeed, even with a smaller output buffer. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. * \retval #PSA_ERROR_NOT_PERMITTED * The #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a * key; or one of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, mbedtls_svc_key_id_t *key); /** Derive a key from an ongoing key derivation operation with custom * production parameters. * * See the description of psa_key_derivation_out_key() for the operation of * this function with the default production parameters. * Mbed TLS currently does not currently support any non-default production * parameters. * * \note This function is experimental and may change in future minor * versions of Mbed TLS. * * \param[in] attributes The attributes for the new key. * If the key type to be created is * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in * the policy must be the same as in the current * operation. * \param[in,out] operation The key derivation operation object to read from. * \param[in] params Customization parameters for the key derivation. * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT * with \p params_data_length = 0, * this function is equivalent to * psa_key_derivation_output_key(). * Mbed TLS currently only supports the default * production parameters, i.e. * #PSA_KEY_PRODUCTION_PARAMETERS_INIT, * for all key types. * \param params_data_length * Length of `params->data` in bytes. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_INSUFFICIENT_DATA * There was not enough data to create the desired key. * Note that in this case, no output is written to the output buffer. * The operation's capacity is set to 0, thus subsequent calls to * this function will not succeed, even with a smaller output buffer. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. * \retval #PSA_ERROR_NOT_PERMITTED * The #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a * key; or one of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_DERIVE. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_output_key_ext( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key); /** Compare output data from a key derivation operation to an expected value. * * This function calculates output bytes from a key derivation algorithm and * compares those bytes to an expected value in constant time. * If you view the key derivation's output as a stream of bytes, this * function destructively reads the expected number of bytes from the * stream before comparing them. * The operation's capacity decreases by the number of bytes read. * * This is functionally equivalent to the following code: * \code * psa_key_derivation_output_bytes(operation, tmp, output_length); * if (memcmp(output, tmp, output_length) != 0) * return PSA_ERROR_INVALID_SIGNATURE; * \endcode * except (1) it works even if the key's policy does not allow outputting the * bytes, and (2) the comparison will be done in constant time. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, * the operation enters an error state and must be aborted by calling * psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to read from. * \param[in] expected_output Buffer containing the expected derivation output. * \param output_length Length of the expected output; this is also the * number of bytes that will be read. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The output was read successfully, but it differs from the expected * output. * \retval #PSA_ERROR_NOT_PERMITTED * One of the inputs was a key whose policy didn't allow * #PSA_KEY_USAGE_VERIFY_DERIVATION. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * \p output_length bytes. Note that in this case, * the operation's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller expected output. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_verify_bytes( psa_key_derivation_operation_t *operation, const uint8_t *expected_output, size_t output_length); /** Compare output data from a key derivation operation to an expected value * stored in a key object. * * This function calculates output bytes from a key derivation algorithm and * compares those bytes to an expected value, provided as key of type * #PSA_KEY_TYPE_PASSWORD_HASH. * If you view the key derivation's output as a stream of bytes, this * function destructively reads the number of bytes corresponding to the * length of the expected value from the stream before comparing them. * The operation's capacity decreases by the number of bytes read. * * This is functionally equivalent to exporting the key and calling * psa_key_derivation_verify_bytes() on the result, except that it * works even if the key cannot be exported. * * If this function returns an error status other than * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, * the operation enters an error state and must be aborted by calling * psa_key_derivation_abort(). * * \param[in,out] operation The key derivation operation object to read from. * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH * containing the expected output. Its policy must * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag * and the permitted algorithm must match the * operation. The value of this key was likely * computed by a previous call to * psa_key_derivation_output_key() or * psa_key_derivation_output_key_ext(). * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The output was read successfully, but if differs from the expected * output. * \retval #PSA_ERROR_INVALID_HANDLE * The key passed as the expected value does not exist. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key passed as the expected value has an invalid type. * \retval #PSA_ERROR_NOT_PERMITTED * The key passed as the expected value does not allow this usage or * this algorithm; or one of the inputs was a key whose policy didn't * allow #PSA_KEY_USAGE_VERIFY_DERIVATION. * \retval #PSA_ERROR_INSUFFICIENT_DATA * The operation's capacity was less than * the length of the expected value. In this case, * the operation's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller expected output. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps), or the library has not been previously * initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_verify_key( psa_key_derivation_operation_t *operation, psa_key_id_t expected); /** Abort a key derivation operation. * * Aborting an operation frees all associated resources except for the \c * operation structure itself. Once aborted, the operation object can be reused * for another operation by calling psa_key_derivation_setup() again. * * This function may be called at any time after the operation * object has been initialized as described in #psa_key_derivation_operation_t. * * In particular, it is valid to call psa_key_derivation_abort() twice, or to * call psa_key_derivation_abort() on an operation that has not been set up. * * \param[in,out] operation The operation to abort. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation); /** Perform a key agreement and return the raw shared secret. * * \warning The raw result of a key agreement algorithm such as finite-field * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should * not be used directly as key material. It should instead be passed as * input to a key derivation algorithm. To chain a key agreement with * a key derivation, use psa_key_derivation_key_agreement() and other * functions from the key derivation interface. * * \param alg The key agreement algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) * is true). * \param private_key Identifier of the private key to use. It must * allow the usage #PSA_KEY_USAGE_DERIVE. * \param[in] peer_key Public key of the peer. It must be * in the same format that psa_import_key() * accepts. The standard formats for public * keys are documented in the documentation * of psa_export_public_key(). * \param peer_key_length Size of \p peer_key in bytes. * \param[out] output Buffer where the decrypted message is to * be written. * \param output_size Size of the \c output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a key agreement algorithm, or * \p private_key is not compatible with \p alg, * or \p peer_key is not valid for \p alg or not compatible with * \p private_key. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p output_size is too small * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key, size_t peer_key_length, uint8_t *output, size_t output_size, size_t *output_length); /**@}*/ /** \defgroup random Random generation * @{ */ /** * \brief Generate random bytes. * * \warning This function **can** fail! Callers MUST check the return status * and MUST NOT use the content of the output buffer if the return * status is not #PSA_SUCCESS. * * \note To generate a key, use psa_generate_key() instead. * * \param[out] output Output buffer for the generated data. * \param output_size Number of bytes to generate and output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_random(uint8_t *output, size_t output_size); /** * \brief Generate a key or key pair. * * The key is generated randomly. * Its location, usage policy, type and size are taken from \p attributes. * * Implementations must reject an attempt to generate a key of size 0. * * The following type-specific considerations apply: * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), * the public exponent is 65537. * The modulus is a product of two probabilistic primes * between 2^{n-1} and 2^n where n is the bit size specified in the * attributes. * * \note This function is equivalent to calling psa_generate_key_ext() * with the production parameters #PSA_KEY_PRODUCTION_PARAMETERS_INIT * and `params_data_length == 0` (i.e. `params->data` is empty). * * \param[in] attributes The attributes for the new key. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key); /** * \brief Generate a key or key pair using custom production parameters. * * See the description of psa_generate_key() for the operation of this * function with the default production parameters. In addition, this function * supports the following production customizations, described in more detail * in the documentation of ::psa_key_production_parameters_t: * * - RSA keys: generation with a custom public exponent. * * \note This function is experimental and may change in future minor * versions of Mbed TLS. * * \param[in] attributes The attributes for the new key. * \param[in] params Customization parameters for the key generation. * When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT * with \p params_data_length = 0, * this function is equivalent to * psa_generate_key(). * \param params_data_length * Length of `params->data` in bytes. * \param[out] key On success, an identifier for the newly created * key. For persistent keys, this is the key * identifier defined in \p attributes. * \c 0 on failure. * * \retval #PSA_SUCCESS * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_ALREADY_EXISTS * This is an attempt to create a persistent key, and there is * already a persistent key with the given identifier. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key); /**@}*/ /** \defgroup interruptible_hash Interruptible sign/verify hash * @{ */ /** The type of the state data structure for interruptible hash * signing operations. * * Before calling any function on a sign hash operation object, the * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_sign_hash_interruptible_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_sign_hash_interruptible_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer * #PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: * \code * psa_sign_hash_interruptible_operation_t operation = * PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; * \endcode * - Assign the result of the function * psa_sign_hash_interruptible_operation_init() to the structure, for * example: * \code * psa_sign_hash_interruptible_operation_t operation; * operation = psa_sign_hash_interruptible_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_t; /** The type of the state data structure for interruptible hash * verification operations. * * Before calling any function on a sign hash operation object, the * application must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_verify_hash_interruptible_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_verify_hash_interruptible_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer * #PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT, for example: * \code * psa_verify_hash_interruptible_operation_t operation = * PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; * \endcode * - Assign the result of the function * psa_verify_hash_interruptible_operation_init() to the structure, for * example: * \code * psa_verify_hash_interruptible_operation_t operation; * operation = psa_verify_hash_interruptible_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_t; /** * \brief Set the maximum number of ops allowed to be * executed by an interruptible function in a * single call. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note The time taken to execute a single op is * implementation specific and depends on * software, hardware, the algorithm, key type and * curve chosen. Even within a single operation, * successive ops can take differing amounts of * time. The only guarantee is that lower values * for \p max_ops means functions will block for a * lesser maximum amount of time. The functions * \c psa_sign_interruptible_get_num_ops() and * \c psa_verify_interruptible_get_num_ops() are * provided to help with tuning this value. * * \note This value defaults to * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, which * means the whole operation will be done in one * go, regardless of the number of ops required. * * \note If more ops are needed to complete a * computation, #PSA_OPERATION_INCOMPLETE will be * returned by the function performing the * computation. It is then the caller's * responsibility to either call again with the * same operation context until it returns 0 or an * error code; or to call the relevant abort * function if the answer is no longer required. * * \note The interpretation of \p max_ops is also * implementation defined. On a hard real time * system, this can indicate a hard deadline, as a * real-time system needs a guarantee of not * spending more than X time, however care must be * taken in such an implementation to avoid the * situation whereby calls just return, not being * able to do any actual work within the allotted * time. On a non-real-time system, the * implementation can be more relaxed, but again * whether this number should be interpreted as as * hard or soft limit or even whether a less than * or equals as regards to ops executed in a * single call is implementation defined. * * \note For keys in local storage when no accelerator * driver applies, please see also the * documentation for \c mbedtls_ecp_set_max_ops(), * which is the internal implementation in these * cases. * * \warning With implementations that interpret this number * as a hard limit, setting this number too small * may result in an infinite loop, whereby each * call results in immediate return with no ops * done (as there is not enough time to execute * any), and thus no result will ever be achieved. * * \note This only applies to functions whose * documentation mentions they may return * #PSA_OPERATION_INCOMPLETE. * * \param max_ops The maximum number of ops to be executed in a * single call. This can be a number from 0 to * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 * is the least amount of work done per call. */ void psa_interruptible_set_max_ops(uint32_t max_ops); /** * \brief Get the maximum number of ops allowed to be * executed by an interruptible function in a * single call. This will return the last * value set by * \c psa_interruptible_set_max_ops() or * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED if * that function has never been called. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \return Maximum number of ops allowed to be * executed by an interruptible function in a * single call. */ uint32_t psa_interruptible_get_max_ops(void); /** * \brief Get the number of ops that a hash signing * operation has taken so far. If the operation * has completed, then this will represent the * number of ops required for the entire * operation. After initialization or calling * \c psa_sign_hash_interruptible_abort() on * the operation, a value of 0 will be returned. * * \note This interface is guaranteed re-entrant and * thus may be called from driver code. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * This is a helper provided to help you tune the * value passed to \c * psa_interruptible_set_max_ops(). * * \param operation The \c psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \return Number of ops that the operation has taken so * far. */ uint32_t psa_sign_hash_get_num_ops( const psa_sign_hash_interruptible_operation_t *operation); /** * \brief Get the number of ops that a hash verification * operation has taken so far. If the operation * has completed, then this will represent the * number of ops required for the entire * operation. After initialization or calling \c * psa_verify_hash_interruptible_abort() on the * operation, a value of 0 will be returned. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * This is a helper provided to help you tune the * value passed to \c * psa_interruptible_set_max_ops(). * * \param operation The \c * psa_verify_hash_interruptible_operation_t to * use. This must be initialized first. * * \return Number of ops that the operation has taken so * far. */ uint32_t psa_verify_hash_get_num_ops( const psa_verify_hash_interruptible_operation_t *operation); /** * \brief Start signing a hash or short message with a * private key, in an interruptible manner. * * \see \c psa_sign_hash_complete() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_sign_hash_complete() is equivalent to * \c psa_sign_hash() but * \c psa_sign_hash_complete() can return early and * resume according to the limit set with \c * psa_interruptible_set_max_ops() to reduce the * maximum time spent in a function call. * * \note Users should call \c psa_sign_hash_complete() * repeatedly on the same context after a * successful call to this function until \c * psa_sign_hash_complete() either returns 0 or an * error. \c psa_sign_hash_complete() will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call * \c psa_sign_hash_abort() at any point if they no * longer want the result. * * \note If this function returns an error status, the * operation enters an error state and must be * aborted by calling \c psa_sign_hash_abort(). * * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \param key Identifier of the key to use for the operation. * It must be an asymmetric key pair. The key must * allow the usage #PSA_KEY_USAGE_SIGN_HASH. * \param alg A signature algorithm (\c PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - call \c psa_sign_hash_complete() * with the same context to complete the operation * * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_SIGN_HASH flag, or it does * not permit the requested algorithm. * \retval #PSA_ERROR_BAD_STATE * An operation has previously been started on this context, and is * still in progress. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_hash_start( psa_sign_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length); /** * \brief Continue and eventually complete the action of * signing a hash or short message with a private * key, in an interruptible manner. * * \see \c psa_sign_hash_start() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_sign_hash_start() is equivalent to * \c psa_sign_hash() but this function can return * early and resume according to the limit set with * \c psa_interruptible_set_max_ops() to reduce the * maximum time spent in a function call. * * \note Users should call this function on the same * operation object repeatedly until it either * returns 0 or an error. This function will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call * \c psa_sign_hash_abort() at any point if they no * longer want the result. * * \note When this function returns successfully, the * operation becomes inactive. If this function * returns an error status, the operation enters an * error state and must be aborted by calling * \c psa_sign_hash_abort(). * * \param[in, out] operation The \c psa_sign_hash_interruptible_operation_t * to use. This must be initialized first, and have * had \c psa_sign_hash_start() called with it * first. * * \param[out] signature Buffer where the signature is to be written. * \param signature_size Size of the \p signature buffer in bytes. This * must be appropriate for the selected * algorithm and key: * - The required signature size is * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c * key_bits, \c alg) where \c key_type and \c * key_bits are the type and bit-size * respectively of key. * - #PSA_SIGNATURE_MAX_SIZE evaluates to the * maximum signature size of any supported * signature algorithm. * \param[out] signature_length On success, the number of bytes that make up * the returned signature value. * * \retval #PSA_SUCCESS * Operation completed successfully * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(). There is still work to be done. * Call this function again with the same operation object. * * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \c key. * * \retval #PSA_ERROR_BAD_STATE * An operation was not previously started on this context via * \c psa_sign_hash_start(). * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has either not been previously initialized by * psa_crypto_init() or you did not previously call * psa_sign_hash_start() with this operation object. It is * implementation-dependent whether a failure to initialize results in * this error code. */ psa_status_t psa_sign_hash_complete( psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Abort a sign hash operation. * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function is the only function that clears * the number of ops completed as part of the * operation. Please ensure you copy this value via * \c psa_sign_hash_get_num_ops() if required * before calling. * * \note Aborting an operation frees all associated * resources except for the \p operation structure * itself. Once aborted, the operation object can * be reused for another operation by calling \c * psa_sign_hash_start() again. * * \note You may call this function any time after the * operation object has been initialized. In * particular, calling \c psa_sign_hash_abort() * after the operation has already been terminated * by a call to \c psa_sign_hash_abort() or * psa_sign_hash_complete() is safe. * * \param[in,out] operation Initialized sign hash operation. * * \retval #PSA_SUCCESS * The operation was aborted successfully. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_sign_hash_abort( psa_sign_hash_interruptible_operation_t *operation); /** * \brief Start reading and verifying a hash or short * message, in an interruptible manner. * * \see \c psa_verify_hash_complete() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_verify_hash_complete() is equivalent to * \c psa_verify_hash() but \c * psa_verify_hash_complete() can return early and * resume according to the limit set with \c * psa_interruptible_set_max_ops() to reduce the * maximum time spent in a function. * * \note Users should call \c psa_verify_hash_complete() * repeatedly on the same operation object after a * successful call to this function until \c * psa_verify_hash_complete() either returns 0 or * an error. \c psa_verify_hash_complete() will * return #PSA_OPERATION_INCOMPLETE if there is * more work to do. Alternatively users can call * \c psa_verify_hash_abort() at any point if they * no longer want the result. * * \note If this function returns an error status, the * operation enters an error state and must be * aborted by calling \c psa_verify_hash_abort(). * * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t * to use. This must be initialized first. * * \param key Identifier of the key to use for the operation. * The key must allow the usage * #PSA_KEY_USAGE_VERIFY_HASH. * \param alg A signature algorithm (\c PSA_ALG_XXX * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) * is true), that is compatible with * the type of \p key. * \param[in] hash The hash whose signature is to be verified. * \param hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - please call \c * psa_verify_hash_complete() with the same context to complete the * operation. * * \retval #PSA_ERROR_BAD_STATE * Another operation has already been started on this context, and is * still in progress. * * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_VERIFY_HASH flag, or it does * not permit the requested algorithm. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval PSA_ERROR_DATA_CORRUPT \emptydescription * \retval PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_hash_start( psa_verify_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Continue and eventually complete the action of * reading and verifying a hash or short message * signed with a private key, in an interruptible * manner. * * \see \c psa_verify_hash_start() * * \warning This is a beta API, and thus subject to change * at any point. It is not bound by the usual * interface stability promises. * * \note This function combined with \c * psa_verify_hash_start() is equivalent to * \c psa_verify_hash() but this function can * return early and resume according to the limit * set with \c psa_interruptible_set_max_ops() to * reduce the maximum time spent in a function * call. * * \note Users should call this function on the same * operation object repeatedly until it either * returns 0 or an error. This function will return * #PSA_OPERATION_INCOMPLETE if there is more work * to do. Alternatively users can call * \c psa_verify_hash_abort() at any point if they * no longer want the result. * * \note When this function returns successfully, the * operation becomes inactive. If this function * returns an error status, the operation enters an * error state and must be aborted by calling * \c psa_verify_hash_abort(). * * \param[in, out] operation The \c psa_verify_hash_interruptible_operation_t * to use. This must be initialized first, and have * had \c psa_verify_hash_start() called with it * first. * * \retval #PSA_SUCCESS * Operation completed successfully, and the passed signature is valid. * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(). There is still work to be done. * Call this function again with the same operation object. * * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_BAD_STATE * An operation was not previously started on this context via * \c psa_verify_hash_start(). * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has either not been previously initialized by * psa_crypto_init() or you did not previously call * psa_verify_hash_start() on this object. It is * implementation-dependent whether a failure to initialize results in * this error code. */ psa_status_t psa_verify_hash_complete( psa_verify_hash_interruptible_operation_t *operation); /** * \brief Abort a verify hash operation. * * \warning This is a beta API, and thus subject to change at * any point. It is not bound by the usual interface * stability promises. * * \note This function is the only function that clears the * number of ops completed as part of the operation. * Please ensure you copy this value via * \c psa_verify_hash_get_num_ops() if required * before calling. * * \note Aborting an operation frees all associated * resources except for the operation structure * itself. Once aborted, the operation object can be * reused for another operation by calling \c * psa_verify_hash_start() again. * * \note You may call this function any time after the * operation object has been initialized. * In particular, calling \c psa_verify_hash_abort() * after the operation has already been terminated by * a call to \c psa_verify_hash_abort() or * psa_verify_hash_complete() is safe. * * \param[in,out] operation Initialized verify hash operation. * * \retval #PSA_SUCCESS * The operation was aborted successfully. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation); /**@}*/ #ifdef __cplusplus } #endif /* The file "crypto_sizes.h" contains definitions for size calculation * macros whose definitions are implementation-specific. */ #include "crypto_sizes.h" /* The file "crypto_struct.h" contains definitions for * implementation-specific structs that are declared above. */ #if defined(MBEDTLS_PSA_CRYPTO_STRUCT_FILE) #include MBEDTLS_PSA_CRYPTO_STRUCT_FILE #else #include "crypto_struct.h" #endif /* The file "crypto_extra.h" contains vendor-specific definitions. This * can include vendor-defined algorithms, extra functions, etc. */ #include "crypto_extra.h" #endif /* PSA_CRYPTO_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_auto_enabled.h000066400000000000000000000012221464416617300276400ustar00rootroot00000000000000/** * \file psa/crypto_adjust_auto_enabled.h * \brief Adjust PSA configuration: enable always-on features * * Always enable certain features which require a negligible amount of code * to implement, to avoid some edge cases in the configuration combinatorics. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H #define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H #define PSA_WANT_KEY_TYPE_DERIVE 1 #define PSA_WANT_KEY_TYPE_PASSWORD 1 #define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 #define PSA_WANT_KEY_TYPE_RAW_DATA 1 #endif /* PSA_CRYPTO_ADJUST_AUTO_ENABLED_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h000066400000000000000000000065121464416617300316010ustar00rootroot00000000000000/** * \file psa/crypto_adjust_config_key_pair_types.h * \brief Adjust PSA configuration for key pair types. * * See docs/proposed/psa-conditional-inclusion-c.md. * - Support non-basic operations in a keypair type implicitly enables basic * support for that keypair type. * - Support for a keypair type implicitly enables the corresponding public * key type. * - Basic support for a keypair type implicilty enables import/export support * for that keypair type. Warning: this is implementation-specific (mainly * for the benefit of testing) and may change in the future! */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H #define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H /***************************************************************** * ANYTHING -> BASIC ****************************************************************/ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #endif /***************************************************************** * BASIC -> corresponding PUBLIC ****************************************************************/ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #endif /***************************************************************** * BASIC -> IMPORT+EXPORT * * (Implementation-specific, may change in the future.) ****************************************************************/ /* Even though KEY_PAIR symbols' feature several level of support (BASIC, IMPORT, * EXPORT, GENERATE, DERIVE) we're not planning to have support only for BASIC * without IMPORT/EXPORT since these last 2 features are strongly used in tests. * In general it is allowed to include more feature than what is strictly * requested. * As a consequence IMPORT and EXPORT features will be automatically enabled * as soon as the BASIC one is. */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #endif #endif /* PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_synonyms.h000066400000000000000000000030311464416617300304420ustar00rootroot00000000000000/** * \file psa/crypto_adjust_config_synonyms.h * \brief Adjust PSA configuration: enable quasi-synonyms * * When two features require almost the same code, we automatically enable * both when either one is requested, to reduce the combinatorics of * possible configurations. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H #define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H /****************************************************************/ /* De facto synonyms */ /****************************************************************/ #if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA) #define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY #elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA) #define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW #elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN #endif #if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS) #define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT #elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS) #define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS #endif #endif /* PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h000066400000000000000000000163741464416617300275750ustar00rootroot00000000000000/* * Context structure declaration of the Mbed TLS software-based PSA drivers * called through the PSA Crypto driver dispatch layer. * This file contains the context structures of those algorithms which need to * rely on other algorithms, i.e. are 'composite' algorithms. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H #define PSA_CRYPTO_BUILTIN_COMPOSITES_H #include "mbedtls/private_access.h" #include #include "mbedtls/cmac.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) #include "mbedtls/ccm.h" #endif #include "mbedtls/chachapoly.h" /* * MAC multi-part operation definitions. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) #define MBEDTLS_PSA_BUILTIN_MAC #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) typedef struct { /** The HMAC algorithm in use */ psa_algorithm_t MBEDTLS_PRIVATE(alg); /** The hash context. */ struct psa_hash_operation_s hash_ctx; /** The HMAC part of the context. */ uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; } mbedtls_psa_hmac_operation_t; #define MBEDTLS_PSA_HMAC_OPERATION_INIT { 0, PSA_HASH_OPERATION_INIT, { 0 } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); union { unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac); #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_mac_operation_t; #define MBEDTLS_PSA_MAC_OPERATION_INIT { 0, { 0 } } #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) #define MBEDTLS_PSA_BUILTIN_AEAD 1 #endif /* Context structure for the Mbed TLS AEAD implementation. */ typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); psa_key_type_t MBEDTLS_PRIVATE(key_type); unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; uint8_t MBEDTLS_PRIVATE(tag_length); union { unsigned dummy; /* Enable easier initializing of the union. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) mbedtls_ccm_context MBEDTLS_PRIVATE(ccm); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) mbedtls_gcm_context MBEDTLS_PRIVATE(gcm); #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly); #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ } ctx; } mbedtls_psa_aead_operation_t; #define MBEDTLS_PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, { 0 } } #include "mbedtls/ecdsa.h" /* Context structure for the Mbed TLS interruptible sign hash implementation. */ typedef struct { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); uint32_t MBEDTLS_PRIVATE(num_ops); size_t MBEDTLS_PRIVATE(coordinate_bytes); psa_algorithm_t MBEDTLS_PRIVATE(alg); mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t MBEDTLS_PRIVATE(hash_length); #else /* Make the struct non-empty if algs not supported. */ unsigned MBEDTLS_PRIVATE(dummy); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } mbedtls_psa_sign_hash_interruptible_operation_t; #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) #define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 } #else #define MBEDTLS_PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #endif /* Context structure for the Mbed TLS interruptible verify hash * implementation.*/ typedef struct { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_context *MBEDTLS_PRIVATE(ctx); mbedtls_ecdsa_restart_ctx MBEDTLS_PRIVATE(restart_ctx); uint32_t MBEDTLS_PRIVATE(num_ops); uint8_t MBEDTLS_PRIVATE(hash)[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t MBEDTLS_PRIVATE(hash_length); mbedtls_mpi MBEDTLS_PRIVATE(r); mbedtls_mpi MBEDTLS_PRIVATE(s); #else /* Make the struct non-empty if algs not supported. */ unsigned MBEDTLS_PRIVATE(dummy); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } mbedtls_psa_verify_hash_interruptible_operation_t; #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) #define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { { 0 }, { 0 }, 0, 0, 0, 0, { 0 }, \ { 0 } } #else #define MBEDTLS_VERIFY_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #endif /* EC-JPAKE operation definitions */ #include "mbedtls/ecjpake.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) #define MBEDTLS_PSA_BUILTIN_PAKE 1 #endif /* Note: the format for mbedtls_ecjpake_read/write function has an extra * length byte for each step, plus an extra 3 bytes for ECParameters in the * server's 2nd round. */ #define MBEDTLS_PSA_JPAKE_BUFFER_SIZE ((3 + 1 + 65 + 1 + 65 + 1 + 32) * 2) typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); uint8_t *MBEDTLS_PRIVATE(password); size_t MBEDTLS_PRIVATE(password_len); #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]); size_t MBEDTLS_PRIVATE(buffer_length); size_t MBEDTLS_PRIVATE(buffer_offset); #endif /* Context structure for the Mbed TLS EC-JPAKE implementation. */ union { unsigned int MBEDTLS_PRIVATE(dummy); #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) mbedtls_ecjpake_context MBEDTLS_PRIVATE(jpake); #endif } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_pake_operation_t; #define MBEDTLS_PSA_PAKE_OPERATION_INIT { { 0 } } #endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_key_derivation.h000066400000000000000000000113771464416617300304220ustar00rootroot00000000000000/* * Context structure declaration of the Mbed TLS software-based PSA drivers * called through the PSA Crypto driver dispatch layer. * This file contains the context structures of key derivation algorithms * which need to rely on other algorithms. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H #define PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H #include "mbedtls/private_access.h" #include #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) typedef struct { uint8_t *MBEDTLS_PRIVATE(info); size_t MBEDTLS_PRIVATE(info_length); #if PSA_HASH_MAX_SIZE > 0xff #error "PSA_HASH_MAX_SIZE does not fit in uint8_t" #endif uint8_t MBEDTLS_PRIVATE(offset_in_block); uint8_t MBEDTLS_PRIVATE(block_number); unsigned int MBEDTLS_PRIVATE(state) : 2; unsigned int MBEDTLS_PRIVATE(info_set) : 1; uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE]; struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac); } psa_hkdf_key_derivation_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF || MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT || MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) typedef struct { uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE]; } psa_tls12_ecjpake_to_pms_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) typedef enum { PSA_TLS12_PRF_STATE_INIT, /* no input provided */ PSA_TLS12_PRF_STATE_SEED_SET, /* seed has been set */ PSA_TLS12_PRF_STATE_OTHER_KEY_SET, /* other key has been set - optional */ PSA_TLS12_PRF_STATE_KEY_SET, /* key has been set */ PSA_TLS12_PRF_STATE_LABEL_SET, /* label has been set */ PSA_TLS12_PRF_STATE_OUTPUT /* output has been started */ } psa_tls12_prf_key_derivation_state_t; typedef struct psa_tls12_prf_key_derivation_s { #if PSA_HASH_MAX_SIZE > 0xff #error "PSA_HASH_MAX_SIZE does not fit in uint8_t" #endif /* Indicates how many bytes in the current HMAC block have * not yet been read by the user. */ uint8_t MBEDTLS_PRIVATE(left_in_block); /* The 1-based number of the block. */ uint8_t MBEDTLS_PRIVATE(block_number); psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state); uint8_t *MBEDTLS_PRIVATE(secret); size_t MBEDTLS_PRIVATE(secret_length); uint8_t *MBEDTLS_PRIVATE(seed); size_t MBEDTLS_PRIVATE(seed_length); uint8_t *MBEDTLS_PRIVATE(label); size_t MBEDTLS_PRIVATE(label_length); #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) uint8_t *MBEDTLS_PRIVATE(other_secret); size_t MBEDTLS_PRIVATE(other_secret_length); #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE]; /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */ uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; } psa_tls12_prf_key_derivation_t; #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(PSA_HAVE_SOFT_PBKDF2) typedef enum { PSA_PBKDF2_STATE_INIT, /* no input provided */ PSA_PBKDF2_STATE_INPUT_COST_SET, /* input cost has been set */ PSA_PBKDF2_STATE_SALT_SET, /* salt has been set */ PSA_PBKDF2_STATE_PASSWORD_SET, /* password has been set */ PSA_PBKDF2_STATE_OUTPUT /* output has been started */ } psa_pbkdf2_key_derivation_state_t; typedef struct { psa_pbkdf2_key_derivation_state_t MBEDTLS_PRIVATE(state); uint64_t MBEDTLS_PRIVATE(input_cost); uint8_t *MBEDTLS_PRIVATE(salt); size_t MBEDTLS_PRIVATE(salt_length); uint8_t MBEDTLS_PRIVATE(password)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; size_t MBEDTLS_PRIVATE(password_length); uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; uint8_t MBEDTLS_PRIVATE(bytes_used); uint32_t MBEDTLS_PRIVATE(block_number); } psa_pbkdf2_key_derivation_t; #endif /* PSA_HAVE_SOFT_PBKDF2 */ #endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h000066400000000000000000000075341464416617300276010ustar00rootroot00000000000000/* * Context structure declaration of the Mbed TLS software-based PSA drivers * called through the PSA Crypto driver dispatch layer. * This file contains the context structures of those algorithms which do not * rely on other algorithms, i.e. are 'primitive' algorithms. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the Mbed TLS software-based PSA drivers. The * definitions of these objects are then used by crypto_struct.h to define the * implementation-defined types of PSA multi-part state objects. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H #define PSA_CRYPTO_BUILTIN_PRIMITIVES_H #include "mbedtls/private_access.h" #include /* * Hash multi-part operation definitions. */ #include "mbedtls/md5.h" #include "mbedtls/ripemd160.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/sha3.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) #define MBEDTLS_PSA_BUILTIN_HASH #endif typedef struct { psa_algorithm_t MBEDTLS_PRIVATE(alg); union { unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) mbedtls_md5_context md5; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) mbedtls_ripemd160_context ripemd160; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) mbedtls_sha1_context sha1; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) mbedtls_sha256_context sha256; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) mbedtls_sha512_context sha512; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) mbedtls_sha3_context sha3; #endif } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_hash_operation_t; #define MBEDTLS_PSA_HASH_OPERATION_INIT { 0, { 0 } } /* * Cipher multi-part operation definitions. */ #include "mbedtls/cipher.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) #define MBEDTLS_PSA_BUILTIN_CIPHER 1 #endif typedef struct { /* Context structure for the Mbed TLS cipher implementation. */ psa_algorithm_t MBEDTLS_PRIVATE(alg); uint8_t MBEDTLS_PRIVATE(iv_length); uint8_t MBEDTLS_PRIVATE(block_length); union { unsigned int MBEDTLS_PRIVATE(dummy); mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher); } MBEDTLS_PRIVATE(ctx); } mbedtls_psa_cipher_operation_t; #define MBEDTLS_PSA_CIPHER_OPERATION_INIT { 0, 0, 0, { 0 } } #endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h000066400000000000000000000210561464416617300251360ustar00rootroot00000000000000/** * \file psa/crypto_compat.h * * \brief PSA cryptography module: Backward compatibility aliases * * This header declares alternative names for macro and functions. * New application code should not use these names. * These names may be removed in a future version of Mbed TLS. * * \note This file may not be included directly. Applications must * include psa/crypto.h. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_COMPAT_H #define PSA_CRYPTO_COMPAT_H #ifdef __cplusplus extern "C" { #endif /* * To support both openless APIs and psa_open_key() temporarily, define * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. Do not mark the * type and its utility macros and functions deprecated yet. This will be done * in a subsequent phase. */ typedef mbedtls_svc_key_id_t psa_key_handle_t; #define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT /** Check whether a handle is null. * * \param handle Handle * * \return Non-zero if the handle is null, zero otherwise. */ static inline int psa_key_handle_is_null(psa_key_handle_t handle) { return mbedtls_svc_key_id_is_null(handle); } /** Open a handle to an existing persistent key. * * Open a handle to a persistent key. A key is persistent if it was created * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key * always has a nonzero key identifier, set with psa_set_key_id() when * creating the key. Implementations may provide additional pre-provisioned * keys that can be opened with psa_open_key(). Such keys have an application * key identifier in the vendor range, as documented in the description of * #psa_key_id_t. * * The application must eventually close the handle with psa_close_key() or * psa_destroy_key() to release associated resources. If the application dies * without calling one of these functions, the implementation should perform * the equivalent of a call to psa_close_key(). * * Some implementations permit an application to open the same key multiple * times. If this is successful, each call to psa_open_key() will return a * different key handle. * * \note This API is not part of the PSA Cryptography API Release 1.0.0 * specification. It was defined in the 1.0 Beta 3 version of the * specification but was removed in the 1.0.0 released version. This API is * kept for the time being to not break applications relying on it. It is not * deprecated yet but will be in the near future. * * \note Applications that rely on opening a key multiple times will not be * portable to implementations that only permit a single key handle to be * opened. See also :ref:\`key-handles\`. * * * \param key The persistent identifier of the key. * \param[out] handle On success, a handle to the key. * * \retval #PSA_SUCCESS * Success. The application can now use the value of `*handle` * to access the key. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * The implementation does not have sufficient resources to open the * key. This can be due to reaching an implementation limit on the * number of open keys, the number of open key handles, or available * memory. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no persistent key with key identifier \p key. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not a valid persistent key identifier. * \retval #PSA_ERROR_NOT_PERMITTED * The specified key exists, but the application does not have the * permission to access it. Note that this specification does not * define any way to create such a key, but it may be possible * through implementation-specific means. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle); /** Close a key handle. * * If the handle designates a volatile key, this will destroy the key material * and free all associated resources, just like psa_destroy_key(). * * If this is the last open handle to a persistent key, then closing the handle * will free all resources associated with the key in volatile memory. The key * data in persistent storage is not affected and can be opened again later * with a call to psa_open_key(). * * Closing the key handle makes the handle invalid, and the key handle * must not be used again by the application. * * \note This API is not part of the PSA Cryptography API Release 1.0.0 * specification. It was defined in the 1.0 Beta 3 version of the * specification but was removed in the 1.0.0 released version. This API is * kept for the time being to not break applications relying on it. It is not * deprecated yet but will be in the near future. * * \note If the key handle was used to set up an active * :ref:\`multipart operation \`, then closing the * key handle can cause the multipart operation to fail. Applications should * maintain the key handle until after the multipart operation has finished. * * \param handle The key handle to close. * If this is \c 0, do nothing and return \c PSA_SUCCESS. * * \retval #PSA_SUCCESS * \p handle was a valid handle or \c 0. It is now closed. * \retval #PSA_ERROR_INVALID_HANDLE * \p handle is not a valid handle nor \c 0. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_close_key(psa_key_handle_t handle); /** \addtogroup attributes * @{ */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** Custom Diffie-Hellman group. * * Mbed TLS does not support custom DH groups. * * \deprecated This value is not useful, so this macro will be removed in * a future version of the library. */ #define PSA_DH_FAMILY_CUSTOM \ ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e)) /** * \brief Set domain parameters for a key. * * \deprecated Mbed TLS no longer supports any domain parameters. * This function only does the equivalent of * psa_set_key_type() and will be removed in a future version * of the library. * * \param[in,out] attributes Attribute structure where \p type will be set. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * \param[in] data Ignored. * \param data_length Must be 0. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ static inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters( psa_key_attributes_t *attributes, psa_key_type_t type, const uint8_t *data, size_t data_length) { (void) data; if (data_length != 0) { return PSA_ERROR_NOT_SUPPORTED; } psa_set_key_type(attributes, type); return PSA_SUCCESS; } /** * \brief Get domain parameters for a key. * * \deprecated Mbed TLS no longer supports any domain parameters. * This function alwaya has an empty output and will be * removed in a future version of the library. * \param[in] attributes Ignored. * \param[out] data Ignored. * \param data_size Ignored. * \param[out] data_length Set to 0. * * \retval #PSA_SUCCESS \emptydescription */ static inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters( const psa_key_attributes_t *attributes, uint8_t *data, size_t data_size, size_t *data_length) { (void) attributes; (void) data; (void) data_size; *data_length = 0; return PSA_SUCCESS; } /** Safe output buffer size for psa_get_key_domain_parameters(). * */ #define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u) #endif /* MBEDTLS_DEPRECATED_REMOVED */ /**@}*/ #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_COMPAT_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_config.h000066400000000000000000000153711464416617300251230ustar00rootroot00000000000000/** * \file psa/crypto_config.h * \brief PSA crypto configuration options (set of defines) * */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /** * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h, * this file determines which cryptographic mechanisms are enabled * through the PSA Cryptography API (\c psa_xxx() functions). * * To enable a cryptographic mechanism, uncomment the definition of * the corresponding \c PSA_WANT_xxx preprocessor symbol. * To disable a cryptographic mechanism, comment out the definition of * the corresponding \c PSA_WANT_xxx preprocessor symbol. * The names of cryptographic mechanisms correspond to values * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead * of \c PSA_. * * Note that many cryptographic mechanisms involve two symbols: one for * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve * additional symbols. */ #else /** * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h, * this file is not used, and cryptographic mechanisms are supported * through the PSA API if and only if they are supported through the * mbedtls_xxx API. */ #endif /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CONFIG_H #define PSA_CRYPTO_CONFIG_H /* * CBC-MAC is not yet supported via the PSA API in Mbed TLS. */ //#define PSA_WANT_ALG_CBC_MAC 1 #define PSA_WANT_ALG_CBC_NO_PADDING 1 #define PSA_WANT_ALG_CBC_PKCS7 1 #define PSA_WANT_ALG_CCM 1 #define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 #define PSA_WANT_ALG_CMAC 1 #define PSA_WANT_ALG_CFB 1 #define PSA_WANT_ALG_CHACHA20_POLY1305 1 #define PSA_WANT_ALG_CTR 1 #define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 #define PSA_WANT_ALG_ECB_NO_PADDING 1 #define PSA_WANT_ALG_ECDH 1 #define PSA_WANT_ALG_FFDH 1 #define PSA_WANT_ALG_ECDSA 1 #define PSA_WANT_ALG_JPAKE 1 #define PSA_WANT_ALG_GCM 1 #define PSA_WANT_ALG_HKDF 1 #define PSA_WANT_ALG_HKDF_EXTRACT 1 #define PSA_WANT_ALG_HKDF_EXPAND 1 #define PSA_WANT_ALG_HMAC 1 #define PSA_WANT_ALG_MD5 1 #define PSA_WANT_ALG_OFB 1 #define PSA_WANT_ALG_PBKDF2_HMAC 1 #define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1 #define PSA_WANT_ALG_RIPEMD160 1 #define PSA_WANT_ALG_RSA_OAEP 1 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 #define PSA_WANT_ALG_RSA_PSS 1 #define PSA_WANT_ALG_SHA_1 1 #define PSA_WANT_ALG_SHA_224 1 #define PSA_WANT_ALG_SHA_256 1 #define PSA_WANT_ALG_SHA_384 1 #define PSA_WANT_ALG_SHA_512 1 #define PSA_WANT_ALG_SHA3_224 1 #define PSA_WANT_ALG_SHA3_256 1 #define PSA_WANT_ALG_SHA3_384 1 #define PSA_WANT_ALG_SHA3_512 1 #define PSA_WANT_ALG_STREAM_CIPHER 1 #define PSA_WANT_ALG_TLS12_PRF 1 #define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 #define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 /* XTS is not yet supported via the PSA API in Mbed TLS. * Note: when adding support, also adjust include/mbedtls/config_psa.h */ //#define PSA_WANT_ALG_XTS 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 #define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 #define PSA_WANT_ECC_MONTGOMERY_255 1 #define PSA_WANT_ECC_MONTGOMERY_448 1 #define PSA_WANT_ECC_SECP_K1_192 1 /* * SECP224K1 is buggy via the PSA API in Mbed TLS * (https://github.com/Mbed-TLS/mbedtls/issues/3541). Thus, do not enable it by * default. */ //#define PSA_WANT_ECC_SECP_K1_224 1 #define PSA_WANT_ECC_SECP_K1_256 1 #define PSA_WANT_ECC_SECP_R1_192 1 #define PSA_WANT_ECC_SECP_R1_224 1 /* For secp256r1, consider enabling #MBEDTLS_PSA_P256M_DRIVER_ENABLED * (see the description in mbedtls/mbedtls_config.h for details). */ #define PSA_WANT_ECC_SECP_R1_256 1 #define PSA_WANT_ECC_SECP_R1_384 1 #define PSA_WANT_ECC_SECP_R1_521 1 #define PSA_WANT_DH_RFC7919_2048 1 #define PSA_WANT_DH_RFC7919_3072 1 #define PSA_WANT_DH_RFC7919_4096 1 #define PSA_WANT_DH_RFC7919_6144 1 #define PSA_WANT_DH_RFC7919_8192 1 #define PSA_WANT_KEY_TYPE_DERIVE 1 #define PSA_WANT_KEY_TYPE_PASSWORD 1 #define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 #define PSA_WANT_KEY_TYPE_HMAC 1 #define PSA_WANT_KEY_TYPE_AES 1 #define PSA_WANT_KEY_TYPE_ARIA 1 #define PSA_WANT_KEY_TYPE_CAMELLIA 1 #define PSA_WANT_KEY_TYPE_CHACHA20 1 #define PSA_WANT_KEY_TYPE_DES 1 //#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 /* Deprecated */ #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 #define PSA_WANT_KEY_TYPE_RAW_DATA 1 //#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 /* Deprecated */ #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 /* * The following symbols extend and deprecate the legacy * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR ones. They include the usage of that key in * the name's suffix. "_USE" is the most generic and it can be used to describe * a generic suport, whereas other ones add more features on top of that and * they are more specific. */ #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 //#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE 1 /* Not supported */ #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 #define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 //#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE 1 /* Not supported */ #endif /* PSA_CRYPTO_CONFIG_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h000066400000000000000000000030271464416617300265140ustar00rootroot00000000000000/** * \file psa/crypto_driver_common.h * \brief Definitions for all PSA crypto drivers * * This file contains common definitions shared by all PSA crypto drivers. * Do not include it directly: instead, include the header file(s) for * the type(s) of driver that you are implementing. For example, if * you are writing a dynamically registered driver for a secure element, * include `psa/crypto_se_driver.h`. * * This file is part of the PSA Crypto Driver Model, containing functions for * driver developers to implement to enable hardware to be called in a * standardized way by a PSA Cryptographic API implementation. The functions * comprising the driver model, which driver authors implement, are not * intended to be called by application developers. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_COMMON_H #define PSA_CRYPTO_DRIVER_COMMON_H #include #include /* Include type definitions (psa_status_t, psa_algorithm_t, * psa_key_type_t, etc.) and macros to build and analyze values * of these types. */ #include "crypto_types.h" #include "crypto_values.h" /* Include size definitions which are used to size some arrays in operation * structures. */ #include /** For encrypt-decrypt functions, whether the operation is an encryption * or a decryption. */ typedef enum { PSA_CRYPTO_DRIVER_DECRYPT, PSA_CRYPTO_DRIVER_ENCRYPT } psa_encrypt_or_decrypt_t; #endif /* PSA_CRYPTO_DRIVER_COMMON_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h000066400000000000000000000134621464416617300313440ustar00rootroot00000000000000/* * Declaration of context structures for use with the PSA driver wrapper * interface. This file contains the context structures for 'composite' * operations, i.e. those operations which need to make use of other operations * from the primitives (crypto_driver_contexts_primitives.h) * * Warning: This file will be auto-generated in the future. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H #define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H #include "psa/crypto_driver_common.h" /* Include the context structure definitions for the Mbed TLS software drivers */ #include "psa/crypto_builtin_composites.h" /* Include the context structure definitions for those drivers that were * declared during the autogeneration process. */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) #include #endif #if defined(PSA_CRYPTO_DRIVER_TEST) #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC) typedef libtestdriver1_mbedtls_psa_mac_operation_t mbedtls_transparent_test_driver_mac_operation_t; typedef libtestdriver1_mbedtls_psa_mac_operation_t mbedtls_opaque_test_driver_mac_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT #else typedef mbedtls_psa_mac_operation_t mbedtls_transparent_test_driver_mac_operation_t; typedef mbedtls_psa_mac_operation_t mbedtls_opaque_test_driver_mac_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ MBEDTLS_PSA_MAC_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ MBEDTLS_PSA_MAC_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD) typedef libtestdriver1_mbedtls_psa_aead_operation_t mbedtls_transparent_test_driver_aead_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_AEAD_OPERATION_INIT #else typedef mbedtls_psa_aead_operation_t mbedtls_transparent_test_driver_aead_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ MBEDTLS_PSA_AEAD_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE) typedef libtestdriver1_mbedtls_psa_pake_operation_t mbedtls_transparent_test_driver_pake_operation_t; typedef libtestdriver1_mbedtls_psa_pake_operation_t mbedtls_opaque_test_driver_pake_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_PAKE_OPERATION_INIT #else typedef mbedtls_psa_pake_operation_t mbedtls_transparent_test_driver_pake_operation_t; typedef mbedtls_psa_pake_operation_t mbedtls_opaque_test_driver_pake_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_PAKE_OPERATION_INIT \ MBEDTLS_PSA_PAKE_OPERATION_INIT #define MBEDTLS_OPAQUE_TEST_DRIVER_PAKE_OPERATION_INIT \ MBEDTLS_PSA_PAKE_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_PAKE */ #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Define the context to be used for an operation that is executed through the * PSA Driver wrapper layer as the union of all possible driver's contexts. * * The union members are the driver's context structures, and the member names * are formatted as `'drivername'_ctx`. This allows for procedural generation * of both this file and the content of psa_crypto_driver_wrappers.h */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_mac_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx; mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx; #endif } psa_driver_mac_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_aead_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx; #endif } psa_driver_aead_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_sign_hash_interruptible_operation_t mbedtls_ctx; } psa_driver_sign_hash_interruptible_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_verify_hash_interruptible_operation_t mbedtls_ctx; } psa_driver_verify_hash_interruptible_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_pake_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_pake_operation_t transparent_test_driver_ctx; mbedtls_opaque_test_driver_pake_operation_t opaque_test_driver_ctx; #endif } psa_driver_pake_context_t; #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */ /* End of automatically generated file. */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h000066400000000000000000000040151464416617300321650ustar00rootroot00000000000000/* * Declaration of context structures for use with the PSA driver wrapper * interface. This file contains the context structures for key derivation * operations. * * Warning: This file will be auto-generated in the future. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H #define PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H #include "psa/crypto_driver_common.h" /* Include the context structure definitions for the Mbed TLS software drivers */ #include "psa/crypto_builtin_key_derivation.h" /* Include the context structure definitions for those drivers that were * declared during the autogeneration process. */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf); #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf); #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms); #endif #if defined(PSA_HAVE_SOFT_PBKDF2) psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2); #endif } psa_driver_key_derivation_context_t; #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H */ /* End of automatically generated file. */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h000066400000000000000000000077571464416617300313640ustar00rootroot00000000000000/* * Declaration of context structures for use with the PSA driver wrapper * interface. This file contains the context structures for 'primitive' * operations, i.e. those operations which do not rely on other contexts. * * Warning: This file will be auto-generated in the future. * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * \note This header and its content are not part of the Mbed TLS API and * applications must not depend on it. Its main purpose is to define the * multi-part state objects of the PSA drivers included in the cryptographic * library. The definitions of these objects are then used by crypto_struct.h * to define the implementation-defined types of PSA multi-part state objects. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H #define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H #include "psa/crypto_driver_common.h" /* Include the context structure definitions for the Mbed TLS software drivers */ #include "psa/crypto_builtin_primitives.h" /* Include the context structure definitions for those drivers that were * declared during the autogeneration process. */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) #include #endif #if defined(PSA_CRYPTO_DRIVER_TEST) #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER) typedef libtestdriver1_mbedtls_psa_cipher_operation_t mbedtls_transparent_test_driver_cipher_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_CIPHER_OPERATION_INIT #else typedef mbedtls_psa_cipher_operation_t mbedtls_transparent_test_driver_cipher_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ MBEDTLS_PSA_CIPHER_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH) typedef libtestdriver1_mbedtls_psa_hash_operation_t mbedtls_transparent_test_driver_hash_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ LIBTESTDRIVER1_MBEDTLS_PSA_HASH_OPERATION_INIT #else typedef mbedtls_psa_hash_operation_t mbedtls_transparent_test_driver_hash_operation_t; #define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ MBEDTLS_PSA_HASH_OPERATION_INIT #endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH */ typedef struct { unsigned int initialised : 1; mbedtls_transparent_test_driver_cipher_operation_t ctx; } mbedtls_opaque_test_driver_cipher_operation_t; #define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \ { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT } #endif /* PSA_CRYPTO_DRIVER_TEST */ /* Define the context to be used for an operation that is executed through the * PSA Driver wrapper layer as the union of all possible driver's contexts. * * The union members are the driver's context structures, and the member names * are formatted as `'drivername'_ctx`. This allows for procedural generation * of both this file and the content of psa_crypto_driver_wrappers.h */ typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_hash_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx; #endif } psa_driver_hash_context_t; typedef union { unsigned dummy; /* Make sure this union is always non-empty */ mbedtls_psa_cipher_operation_t mbedtls_ctx; #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx; mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx; #endif } psa_driver_cipher_context_t; #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */ /* End of automatically generated file. */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h000066400000000000000000002370271464416617300250050ustar00rootroot00000000000000/** * \file psa/crypto_extra.h * * \brief PSA cryptography module: Mbed TLS vendor extensions * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file is reserved for vendor-specific definitions. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_EXTRA_H #define PSA_CRYPTO_EXTRA_H #include "mbedtls/private_access.h" #include "crypto_types.h" #include "crypto_compat.h" #ifdef __cplusplus extern "C" { #endif /* UID for secure storage seed */ #define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 /* See mbedtls_config.h for definition */ #if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT) #define MBEDTLS_PSA_KEY_SLOT_COUNT 32 #endif /** \addtogroup attributes * @{ */ /** \brief Declare the enrollment algorithm for a key. * * An operation on a key may indifferently use the algorithm set with * psa_set_key_algorithm() or with this function. * * \param[out] attributes The attribute structure to write to. * \param alg2 A second algorithm that the key may be used * for, in addition to the algorithm set with * psa_set_key_algorithm(). * * \warning Setting an enrollment algorithm is not recommended, because * using the same key with different algorithms can allow some * attacks based on arithmetic relations between different * computations made with the same key, or can escalate harmless * side channels into exploitable ones. Use this function only * if it is necessary to support a protocol for which it has been * verified that the usage of the key with multiple algorithms * is safe. */ static inline void psa_set_key_enrollment_algorithm( psa_key_attributes_t *attributes, psa_algorithm_t alg2) { attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2; } /** Retrieve the enrollment algorithm policy from key attributes. * * \param[in] attributes The key attribute structure to query. * * \return The enrollment algorithm stored in the attribute structure. */ static inline psa_algorithm_t psa_get_key_enrollment_algorithm( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** Retrieve the slot number where a key is stored. * * A slot number is only defined for keys that are stored in a secure * element. * * This information is only useful if the secure element is not entirely * managed through the PSA Cryptography API. It is up to the secure * element driver to decide how PSA slot numbers map to any other interface * that the secure element may have. * * \param[in] attributes The key attribute structure to query. * \param[out] slot_number On success, the slot number containing the key. * * \retval #PSA_SUCCESS * The key is located in a secure element, and \p *slot_number * indicates the slot number that contains it. * \retval #PSA_ERROR_NOT_PERMITTED * The caller is not permitted to query the slot number. * Mbed TLS currently does not return this error. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is not located in a secure element. */ psa_status_t psa_get_key_slot_number( const psa_key_attributes_t *attributes, psa_key_slot_number_t *slot_number); /** Choose the slot number where a key is stored. * * This function declares a slot number in the specified attribute * structure. * * A slot number is only meaningful for keys that are stored in a secure * element. It is up to the secure element driver to decide how PSA slot * numbers map to any other interface that the secure element may have. * * \note Setting a slot number in key attributes for a key creation can * cause the following errors when creating the key: * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does * not support choosing a specific slot number. * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to * choose slot numbers in general or to choose this specific slot. * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not * valid in general or not valid for this specific key. * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the * selected slot. * * \param[out] attributes The attribute structure to write to. * \param slot_number The slot number to set. */ static inline void psa_set_key_slot_number( psa_key_attributes_t *attributes, psa_key_slot_number_t slot_number) { attributes->MBEDTLS_PRIVATE(has_slot_number) = 1; attributes->MBEDTLS_PRIVATE(slot_number) = slot_number; } /** Remove the slot number attribute from a key attribute structure. * * This function undoes the action of psa_set_key_slot_number(). * * \param[out] attributes The attribute structure to write to. */ static inline void psa_clear_key_slot_number( psa_key_attributes_t *attributes) { attributes->MBEDTLS_PRIVATE(has_slot_number) = 0; } /** Register a key that is already present in a secure element. * * The key must be located in a secure element designated by the * lifetime field in \p attributes, in the slot set with * psa_set_key_slot_number() in the attribute structure. * This function makes the key available through the key identifier * specified in \p attributes. * * \param[in] attributes The attributes of the existing key. * * \retval #PSA_SUCCESS * The key was successfully registered. * Note that depending on the design of the driver, this may or may * not guarantee that a key actually exists in the designated slot * and is compatible with the specified attributes. * \retval #PSA_ERROR_ALREADY_EXISTS * There is already a key with the identifier specified in * \p attributes. * \retval #PSA_ERROR_NOT_SUPPORTED * The secure element driver for the specified lifetime does not * support registering a key. * \retval #PSA_ERROR_INVALID_ARGUMENT * The identifier in \p attributes is invalid, namely the identifier is * not in the user range, or * \p attributes specifies a lifetime which is not located * in a secure element, or no slot number is specified in \p attributes, * or the specified slot number is not valid. * \retval #PSA_ERROR_NOT_PERMITTED * The caller is not authorized to register the specified key slot. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t mbedtls_psa_register_se_key( const psa_key_attributes_t *attributes); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ /**@}*/ /** * \brief Library deinitialization. * * This function clears all data associated with the PSA layer, * including the whole key store. * This function is not thread safe, it wipes every key slot regardless of * state and reader count. It should only be called when no slot is in use. * * This is an Mbed TLS extension. */ void mbedtls_psa_crypto_free(void); /** \brief Statistics about * resource consumption related to the PSA keystore. * * \note The content of this structure is not part of the stable API and ABI * of Mbed TLS and may change arbitrarily from version to version. */ typedef struct mbedtls_psa_stats_s { /** Number of slots containing key material for a volatile key. */ size_t MBEDTLS_PRIVATE(volatile_slots); /** Number of slots containing key material for a key which is in * internal persistent storage. */ size_t MBEDTLS_PRIVATE(persistent_slots); /** Number of slots containing a reference to a key in a * secure element. */ size_t MBEDTLS_PRIVATE(external_slots); /** Number of slots which are occupied, but do not contain * key material yet. */ size_t MBEDTLS_PRIVATE(half_filled_slots); /** Number of slots that contain cache data. */ size_t MBEDTLS_PRIVATE(cache_slots); /** Number of slots that are not used for anything. */ size_t MBEDTLS_PRIVATE(empty_slots); /** Number of slots that are locked. */ size_t MBEDTLS_PRIVATE(locked_slots); /** Largest key id value among open keys in internal persistent storage. */ psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id); /** Largest key id value among open keys in secure elements. */ psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id); } mbedtls_psa_stats_t; /** \brief Get statistics about * resource consumption related to the PSA keystore. * * \note When Mbed TLS is built as part of a service, with isolation * between the application and the keystore, the service may or * may not expose this function. */ void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats); /** * \brief Inject an initial entropy seed for the random generator into * secure storage. * * This function injects data to be used as a seed for the random generator * used by the PSA Crypto implementation. On devices that lack a trusted * entropy source (preferably a hardware random number generator), * the Mbed PSA Crypto implementation uses this value to seed its * random generator. * * On devices without a trusted entropy source, this function must be * called exactly once in the lifetime of the device. On devices with * a trusted entropy source, calling this function is optional. * In all cases, this function may only be called before calling any * other function in the PSA Crypto API, including psa_crypto_init(). * * When this function returns successfully, it populates a file in * persistent storage. Once the file has been created, this function * can no longer succeed. * * If any error occurs, this function does not change the system state. * You can call this function again after correcting the reason for the * error if possible. * * \warning This function **can** fail! Callers MUST check the return status. * * \warning If you use this function, you should use it as part of a * factory provisioning process. The value of the injected seed * is critical to the security of the device. It must be * *secret*, *unpredictable* and (statistically) *unique per device*. * You should be generate it randomly using a cryptographically * secure random generator seeded from trusted entropy sources. * You should transmit it securely to the device and ensure * that its value is not leaked or stored anywhere beyond the * needs of transmitting it from the point of generation to * the call of this function, and erase all copies of the value * once this function returns. * * This is an Mbed TLS extension. * * \note This function is only available on the following platforms: * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. * Note that you must provide compatible implementations of * mbedtls_nv_seed_read and mbedtls_nv_seed_write. * * In a client-server integration of PSA Cryptography, on the client side, * if the server supports this feature. * \param[in] seed Buffer containing the seed value to inject. * \param[in] seed_size Size of the \p seed buffer. * The size of the seed in bytes must be greater * or equal to both #MBEDTLS_ENTROPY_BLOCK_SIZE * and the value of \c MBEDTLS_ENTROPY_MIN_PLATFORM * in `library/entropy_poll.h` in the Mbed TLS source * code. * It must be less or equal to * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. * * \retval #PSA_SUCCESS * The seed value was injected successfully. The random generator * of the PSA Crypto implementation is now ready for use. * You may now call psa_crypto_init() and use the PSA Crypto * implementation. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p seed_size is out of range. * \retval #PSA_ERROR_STORAGE_FAILURE * There was a failure reading or writing from storage. * \retval #PSA_ERROR_NOT_PERMITTED * The library has already been initialized. It is no longer * possible to call this function. */ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size); /** \addtogroup crypto_types * @{ */ /** DSA public key. * * The import and export format is the * representation of the public key `y = g^x mod p` as a big-endian byte * string. The length of the byte string is the length of the base prime `p` * in bytes. */ #define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t) 0x4002) /** DSA key pair (private and public key). * * The import and export format is the * representation of the private key `x` as a big-endian byte string. The * length of the byte string is the private key size in bytes (leading zeroes * are not stripped). * * Deterministic DSA key derivation with psa_generate_derived_key follows * FIPS 186-4 §B.1.2: interpret the byte string as integer * in big-endian order. Discard it if it is not in the range * [0, *N* - 2] where *N* is the boundary of the private key domain * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, * or the order of the curve's base point for ECC). * Add 1 to the resulting integer and use this as the private key *x*. * */ #define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t) 0x7002) /** Whether a key type is a DSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_DSA(type) \ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) #define PSA_ALG_DSA_BASE ((psa_algorithm_t) 0x06000400) /** DSA signature with hashing. * * This is the signature scheme defined by FIPS 186-4, * with a random per-message secret number (*k*). * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding DSA signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DSA(hash_alg) \ (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t) 0x06000500) #define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG /** Deterministic DSA signature with hashing. * * This is the deterministic variant defined by RFC 6979 of * the signature scheme defined by FIPS 186-4. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding DSA signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_IS_DSA(alg) \ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ PSA_ALG_DSA_BASE) #define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) #define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) #define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) /* We need to expand the sample definition of this macro from * the API definition. */ #undef PSA_ALG_IS_VENDOR_HASH_AND_SIGN #define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) \ PSA_ALG_IS_DSA(alg) /**@}*/ /** \addtogroup attributes * @{ */ /** PAKE operation stages. */ #define PSA_PAKE_OPERATION_STAGE_SETUP 0 #define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1 #define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2 /**@}*/ /** \defgroup psa_external_rng External random generator * @{ */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** External random generator function, implemented by the platform. * * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled, * this function replaces Mbed TLS's entropy and DRBG modules for all * random generation triggered via PSA crypto interfaces. * * \note This random generator must deliver random numbers with cryptographic * quality and high performance. It must supply unpredictable numbers * with a uniform distribution. The implementation of this function * is responsible for ensuring that the random generator is seeded * with sufficient entropy. If you have a hardware TRNG which is slow * or delivers non-uniform output, declare it as an entropy source * with mbedtls_entropy_add_source() instead of enabling this option. * * \param[in,out] context Pointer to the random generator context. * This is all-bits-zero on the first call * and preserved between successive calls. * \param[out] output Output buffer. On success, this buffer * contains random data with a uniform * distribution. * \param output_size The size of the \p output buffer in bytes. * \param[out] output_length On success, set this value to \p output_size. * * \retval #PSA_SUCCESS * Success. The output buffer contains \p output_size bytes of * cryptographic-quality random data, and \c *output_length is * set to \p output_size. * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY * The random generator requires extra entropy and there is no * way to obtain entropy under current environment conditions. * This error should not happen under normal circumstances since * this function is responsible for obtaining as much entropy as * it needs. However implementations of this function may return * #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain * entropy without blocking indefinitely. * \retval #PSA_ERROR_HARDWARE_FAILURE * A failure of the random generator hardware that isn't covered * by #PSA_ERROR_INSUFFICIENT_ENTROPY. */ psa_status_t mbedtls_psa_external_get_random( mbedtls_psa_external_random_context_t *context, uint8_t *output, size_t output_size, size_t *output_length); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ /**@}*/ /** \defgroup psa_builtin_keys Built-in keys * @{ */ /** The minimum value for a key identifier that is built into the * implementation. * * The range of key identifiers from #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN * to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX within the range from * #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect * with any other set of implementation-chosen key identifiers. * * This value is part of the library's ABI since changing it would invalidate * the values of built-in key identifiers in applications. */ #define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ((psa_key_id_t) 0x7fff0000) /** The maximum value for a key identifier that is built into the * implementation. * * See #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN for more information. */ #define MBEDTLS_PSA_KEY_ID_BUILTIN_MAX ((psa_key_id_t) 0x7fffefff) /** A slot number identifying a key in a driver. * * Values of this type are used to identify built-in keys. */ typedef uint64_t psa_drv_slot_number_t; #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) /** Test whether a key identifier belongs to the builtin key range. * * \param key_id Key identifier to test. * * \retval 1 * The key identifier is a builtin key identifier. * \retval 0 * The key identifier is not a builtin key identifier. */ static inline int psa_key_id_is_builtin(psa_key_id_t key_id) { return (key_id >= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN) && (key_id <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX); } /** Platform function to obtain the location and slot number of a built-in key. * * An application-specific implementation of this function must be provided if * #MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled. This would typically be provided * as part of a platform's system image. * * #MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\p key_id) needs to be in the range from * #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX. * * In a multi-application configuration * (\c MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER is defined), * this function should check that #MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(\p key_id) * is allowed to use the given key. * * \param key_id The key ID for which to retrieve the * location and slot attributes. * \param[out] lifetime On success, the lifetime associated with the key * corresponding to \p key_id. Lifetime is a * combination of which driver contains the key, * and with what persistence level the key is * intended to be used. If the platform * implementation does not contain specific * information about the intended key persistence * level, the persistence level may be reported as * #PSA_KEY_PERSISTENCE_DEFAULT. * \param[out] slot_number On success, the slot number known to the driver * registered at the lifetime location reported * through \p lifetime which corresponds to the * requested built-in key. * * \retval #PSA_SUCCESS * The requested key identifier designates a built-in key. * In a multi-application configuration, the requested owner * is allowed to access it. * \retval #PSA_ERROR_DOES_NOT_EXIST * The requested key identifier is not a built-in key which is known * to this function. If a key exists in the key storage with this * identifier, the data from the storage will be used. * \return (any other error) * Any other error is propagated to the function that requested the key. * Common errors include: * - #PSA_ERROR_NOT_PERMITTED: the key exists but the requested owner * is not allowed to access it. */ psa_status_t mbedtls_psa_platform_get_builtin_key( mbedtls_svc_key_id_t key_id, psa_key_lifetime_t *lifetime, psa_drv_slot_number_t *slot_number); #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ /** @} */ /** \addtogroup crypto_types * @{ */ #define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t) 0x0a000000) /** Whether the specified algorithm is a password-authenticated key exchange. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a password-authenticated key exchange (PAKE) * algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_PAKE(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) /** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. * * This is J-PAKE as defined by RFC 8236, instantiated with the following * parameters: * * - The group can be either an elliptic curve or defined over a finite field. * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the * J-PAKE algorithm. * - A cryptographic hash function. * * To select these parameters and set up the cipher suite, call these functions * in any order: * * \code * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); * psa_pake_cs_set_primitive(cipher_suite, * PSA_PAKE_PRIMITIVE(type, family, bits)); * psa_pake_cs_set_hash(cipher_suite, hash); * \endcode * * For more information on how to set a specific curve or field, refer to the * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. * * After initializing a J-PAKE operation, call * * \code * psa_pake_setup(operation, cipher_suite); * psa_pake_set_user(operation, ...); * psa_pake_set_peer(operation, ...); * psa_pake_set_password_key(operation, ...); * \endcode * * The password is provided as a key. This can be the password text itself, * in an agreed character encoding, or some value derived from the password * as required by a higher level protocol. * * (The implementation converts the key material to a number as described in * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here * \c q is order of the group defined by the primitive set in the cipher suite. * The \c psa_pake_set_password_key() function returns an error if the result * of the reduction is 0.) * * The key exchange flow for J-PAKE is as follows: * -# To get the first round data that needs to be sent to the peer, call * \code * // Get g1 * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get the ZKP public key for x1 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get the ZKP proof for x1 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * // Get g2 * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get the ZKP public key for x2 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get the ZKP proof for x2 * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To provide the first round data received from the peer to the operation, * call * \code * // Set g3 * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set the ZKP public key for x3 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set the ZKP proof for x3 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * // Set g4 * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set the ZKP public key for x4 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set the ZKP proof for x4 * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To get the second round data that needs to be sent to the peer, call * \code * // Get A * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Get ZKP public key for x2*s * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Get ZKP proof for x2*s * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To provide the second round data received from the peer to the operation, * call * \code * // Set B * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); * // Set ZKP public key for x4*s * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); * // Set ZKP proof for x4*s * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); * \endcode * -# To access the shared secret call * \code * // Get Ka=Kb=K * psa_pake_get_implicit_key() * \endcode * * For more information consult the documentation of the individual * \c PSA_PAKE_STEP_XXX constants. * * At this point there is a cryptographic guarantee that only the authenticated * party who used the same password is able to compute the key. But there is no * guarantee that the peer is the party it claims to be and was able to do so. * * That is, the authentication is only implicit (the peer is not authenticated * at this point, and no action should be taken that assume that they are - like * for example accessing restricted files). * * To make the authentication explicit there are various methods, see Section 5 * of RFC 8236 for two examples. * */ #define PSA_ALG_JPAKE ((psa_algorithm_t) 0x0a000100) /** @} */ /** \defgroup pake Password-authenticated key exchange (PAKE) * * This is a proposed PAKE interface for the PSA Crypto API. It is not part of * the official PSA Crypto API yet. * * \note The content of this section is not part of the stable API and ABI * of Mbed TLS and may change arbitrarily from version to version. * Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and * #PSA_ALG_JPAKE. * @{ */ /** \brief Encoding of the application role of PAKE * * Encodes the application's role in the algorithm is being executed. For more * information see the documentation of individual \c PSA_PAKE_ROLE_XXX * constants. */ typedef uint8_t psa_pake_role_t; /** Encoding of input and output indicators for PAKE. * * Some PAKE algorithms need to exchange more data than just a single key share. * This type is for encoding additional input and output data for such * algorithms. */ typedef uint8_t psa_pake_step_t; /** Encoding of the type of the PAKE's primitive. * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional types must use an encoding in this range. * * For more information see the documentation of individual * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_primitive_type_t; /** \brief Encoding of the family of the primitive associated with the PAKE. * * For more information see the documentation of individual * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. */ typedef uint8_t psa_pake_family_t; /** \brief Encoding of the primitive associated with the PAKE. * * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. */ typedef uint32_t psa_pake_primitive_t; /** A value to indicate no role in a PAKE algorithm. * This value can be used in a call to psa_pake_set_role() for symmetric PAKE * algorithms which do not assign roles. */ #define PSA_PAKE_ROLE_NONE ((psa_pake_role_t) 0x00) /** The first peer in a balanced PAKE. * * Although balanced PAKE algorithms are symmetric, some of them needs an * ordering of peers for the transcript calculations. If the algorithm does not * need this, both #PSA_PAKE_ROLE_FIRST and #PSA_PAKE_ROLE_SECOND are * accepted. */ #define PSA_PAKE_ROLE_FIRST ((psa_pake_role_t) 0x01) /** The second peer in a balanced PAKE. * * Although balanced PAKE algorithms are symmetric, some of them needs an * ordering of peers for the transcript calculations. If the algorithm does not * need this, either #PSA_PAKE_ROLE_FIRST or #PSA_PAKE_ROLE_SECOND are * accepted. */ #define PSA_PAKE_ROLE_SECOND ((psa_pake_role_t) 0x02) /** The client in an augmented PAKE. * * Augmented PAKE algorithms need to differentiate between client and server. */ #define PSA_PAKE_ROLE_CLIENT ((psa_pake_role_t) 0x11) /** The server in an augmented PAKE. * * Augmented PAKE algorithms need to differentiate between client and server. */ #define PSA_PAKE_ROLE_SERVER ((psa_pake_role_t) 0x12) /** The PAKE primitive type indicating the use of elliptic curves. * * The values of the \c family and \c bits fields of the cipher suite identify a * specific elliptic curve, using the same mapping that is used for ECC * (::psa_ecc_family_t) keys. * * (Here \c family means the value returned by psa_pake_cs_get_family() and * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar * values: * -# The format for group elements is the same as for public keys on the * specific curve would be. For more information, consult the documentation of * psa_export_public_key(). * -# The format for scalars is the same as for private keys on the specific * curve would be. For more information, consult the documentation of * psa_export_key(). */ #define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t) 0x01) /** The PAKE primitive type indicating the use of Diffie-Hellman groups. * * The values of the \c family and \c bits fields of the cipher suite identify * a specific Diffie-Hellman group, using the same mapping that is used for * Diffie-Hellman (::psa_dh_family_t) keys. * * (Here \c family means the value returned by psa_pake_cs_get_family() and * \c bits means the value returned by psa_pake_cs_get_bits().) * * Input and output during the operation can involve group elements and scalar * values: * -# The format for group elements is the same as for public keys on the * specific group would be. For more information, consult the documentation of * psa_export_public_key(). * -# The format for scalars is the same as for private keys on the specific * group would be. For more information, consult the documentation of * psa_export_key(). */ #define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t) 0x02) /** Construct a PAKE primitive from type, family and bit-size. * * \param pake_type The type of the primitive * (value of type ::psa_pake_primitive_type_t). * \param pake_family The family of the primitive * (the type and interpretation of this parameter depends * on \p pake_type, for more information consult the * documentation of individual ::psa_pake_primitive_type_t * constants). * \param pake_bits The bit-size of the primitive * (Value of type \c size_t. The interpretation * of this parameter depends on \p pake_family, for more * information consult the documentation of individual * ::psa_pake_primitive_type_t constants). * * \return The constructed primitive value of type ::psa_pake_primitive_t. * Return 0 if the requested primitive can't be encoded as * ::psa_pake_primitive_t. */ #define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ ((psa_pake_primitive_t) (((pake_type) << 24 | \ (pake_family) << 16) | (pake_bits))) /** The key share being sent to or received from the peer. * * The format for both input and output at this step is the same as for public * keys on the group determined by the primitive (::psa_pake_primitive_t) would * be. * * For more information on the format, consult the documentation of * psa_export_public_key(). * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t) 0x01) /** A Schnorr NIZKP public key. * * This is the ephemeral public key in the Schnorr Non-Interactive * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235). * * The format for both input and output at this step is the same as for public * keys on the group determined by the primitive (::psa_pake_primitive_t) would * be. * * For more information on the format, consult the documentation of * psa_export_public_key(). * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t) 0x02) /** A Schnorr NIZKP proof. * * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the * value denoted by the letter 'r' in RFC 8235). * * Both for input and output, the value at this step is an integer less than * the order of the group selected in the cipher suite. The format depends on * the group as well: * * - For Montgomery curves, the encoding is little endian. * - For everything else the encoding is big endian (see Section 2.3.8 of * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). * * In both cases leading zeroes are allowed as long as the length in bytes does * not exceed the byte length of the group order. * * For information regarding how the group is determined, consult the * documentation #PSA_PAKE_PRIMITIVE. */ #define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t) 0x03) /** The type of the data structure for PAKE cipher suites. * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; /** Return an initial value for a PAKE cipher suite object. */ static psa_pake_cipher_suite_t psa_pake_cipher_suite_init(void); /** Retrieve the PAKE algorithm from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The PAKE algorithm stored in the cipher suite structure. */ static psa_algorithm_t psa_pake_cs_get_algorithm( const psa_pake_cipher_suite_t *cipher_suite); /** Declare the PAKE algorithm for the cipher suite. * * This function overwrites any PAKE algorithm * previously set in \p cipher_suite. * * \param[out] cipher_suite The cipher suite structure to write to. * \param algorithm The PAKE algorithm to write. * (`PSA_ALG_XXX` values of type ::psa_algorithm_t * such that #PSA_ALG_IS_PAKE(\c alg) is true.) * If this is 0, the PAKE algorithm in * \p cipher_suite becomes unspecified. */ static void psa_pake_cs_set_algorithm(psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t algorithm); /** Retrieve the primitive from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The primitive stored in the cipher suite structure. */ static psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t *cipher_suite); /** Declare the primitive for a PAKE cipher suite. * * This function overwrites any primitive previously set in \p cipher_suite. * * \param[out] cipher_suite The cipher suite structure to write to. * \param primitive The primitive to write. If this is 0, the * primitive type in \p cipher_suite becomes * unspecified. */ static void psa_pake_cs_set_primitive(psa_pake_cipher_suite_t *cipher_suite, psa_pake_primitive_t primitive); /** Retrieve the PAKE family from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The PAKE family stored in the cipher suite structure. */ static psa_pake_family_t psa_pake_cs_get_family( const psa_pake_cipher_suite_t *cipher_suite); /** Retrieve the PAKE primitive bit-size from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The PAKE primitive bit-size stored in the cipher suite structure. */ static uint16_t psa_pake_cs_get_bits( const psa_pake_cipher_suite_t *cipher_suite); /** Retrieve the hash algorithm from a PAKE cipher suite. * * \param[in] cipher_suite The cipher suite structure to query. * * \return The hash algorithm stored in the cipher suite structure. The return * value is 0 if the PAKE is not parametrised by a hash algorithm or if * the hash algorithm is not set. */ static psa_algorithm_t psa_pake_cs_get_hash( const psa_pake_cipher_suite_t *cipher_suite); /** Declare the hash algorithm for a PAKE cipher suite. * * This function overwrites any hash algorithm * previously set in \p cipher_suite. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[out] cipher_suite The cipher suite structure to write to. * \param hash The hash involved in the cipher suite. * (`PSA_ALG_XXX` values of type ::psa_algorithm_t * such that #PSA_ALG_IS_HASH(\c alg) is true.) * If this is 0, the hash algorithm in * \p cipher_suite becomes unspecified. */ static void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t hash); /** The type of the state data structure for PAKE operations. * * Before calling any function on a PAKE operation object, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_pake_operation_t operation; * memset(&operation, 0, sizeof(operation)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_pake_operation_t operation = {0}; * \endcode * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, * for example: * \code * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; * \endcode * - Assign the result of the function psa_pake_operation_init() * to the structure, for example: * \code * psa_pake_operation_t operation; * operation = psa_pake_operation_init(); * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure. * Implementation details can change in future versions without notice. */ typedef struct psa_pake_operation_s psa_pake_operation_t; /** The type of input values for PAKE operations. */ typedef struct psa_crypto_driver_pake_inputs_s psa_crypto_driver_pake_inputs_t; /** The type of computation stage for J-PAKE operations. */ typedef struct psa_jpake_computation_stage_s psa_jpake_computation_stage_t; /** Return an initial value for a PAKE operation object. */ static psa_pake_operation_t psa_pake_operation_init(void); /** Get the length of the password in bytes from given inputs. * * \param[in] inputs Operation inputs. * \param[out] password_len Password length. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Password hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_password_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *password_len); /** Get the password from given inputs. * * \param[in] inputs Operation inputs. * \param[out] buffer Return buffer for password. * \param buffer_size Size of the return buffer in bytes. * \param[out] buffer_length Actual size of the password in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Password hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_password( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *buffer, size_t buffer_size, size_t *buffer_length); /** Get the length of the user id in bytes from given inputs. * * \param[in] inputs Operation inputs. * \param[out] user_len User id length. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * User id hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_user_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *user_len); /** Get the length of the peer id in bytes from given inputs. * * \param[in] inputs Operation inputs. * \param[out] peer_len Peer id length. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Peer id hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_peer_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *peer_len); /** Get the user id from given inputs. * * \param[in] inputs Operation inputs. * \param[out] user_id User id. * \param user_id_size Size of \p user_id in bytes. * \param[out] user_id_len Size of the user id in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * User id hasn't been set yet. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p user_id is too small. */ psa_status_t psa_crypto_driver_pake_get_user( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *user_id, size_t user_id_size, size_t *user_id_len); /** Get the peer id from given inputs. * * \param[in] inputs Operation inputs. * \param[out] peer_id Peer id. * \param peer_id_size Size of \p peer_id in bytes. * \param[out] peer_id_length Size of the peer id in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Peer id hasn't been set yet. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p peer_id is too small. */ psa_status_t psa_crypto_driver_pake_get_peer( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length); /** Get the cipher suite from given inputs. * * \param[in] inputs Operation inputs. * \param[out] cipher_suite Return buffer for role. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * Cipher_suite hasn't been set yet. */ psa_status_t psa_crypto_driver_pake_get_cipher_suite( const psa_crypto_driver_pake_inputs_t *inputs, psa_pake_cipher_suite_t *cipher_suite); /** Set the session information for a password-authenticated key exchange. * * The sequence of operations to set up a password-authenticated key exchange * is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. * -# Initialize the operation object with one of the methods described in the * documentation for #psa_pake_operation_t, e.g. * #PSA_PAKE_OPERATION_INIT. * -# Call psa_pake_setup() to specify the cipher suite. * -# Call \c psa_pake_set_xxx() functions on the operation to complete the * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs * to be called depends on the algorithm in use. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * A typical sequence of calls to perform a password-authenticated key * exchange: * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the * key share that needs to be sent to the peer. * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide * the key share that was received from the peer. * -# Depending on the algorithm additional calls to psa_pake_output() and * psa_pake_input() might be necessary. * -# Call psa_pake_get_implicit_key() for accessing the shared secret. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * If an error occurs at any step after a call to psa_pake_setup(), * the operation will need to be reset by a call to psa_pake_abort(). The * application may call psa_pake_abort() at any time after the operation * has been initialized. * * After a successful call to psa_pake_setup(), the application must * eventually terminate the operation. The following events terminate an * operation: * - A call to psa_pake_abort(). * - A successful call to psa_pake_get_implicit_key(). * * \param[in,out] operation The operation object to set up. It must have * been initialized but not set up yet. * \param[in] cipher_suite The cipher suite to use. (A cipher suite fully * characterizes a PAKE algorithm and determines * the algorithm as well.) * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The algorithm in \p cipher_suite is not a PAKE algorithm, or the * PAKE primitive in \p cipher_suite is not compatible with the * PAKE algorithm, or the hash algorithm in \p cipher_suite is invalid * or not compatible with the PAKE algorithm and primitive. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm in \p cipher_suite is not a supported PAKE algorithm, * or the PAKE primitive in \p cipher_suite is not supported or not * compatible with the PAKE algorithm, or the hash algorithm in * \p cipher_suite is not supported or not compatible with the PAKE * algorithm and primitive. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_setup(psa_pake_operation_t *operation, const psa_pake_cipher_suite_t *cipher_suite); /** Set the password for a password-authenticated key exchange from key ID. * * Call this function when the password, or a value derived from the password, * is already present in the key store. * * \param[in,out] operation The operation object to set the password for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the password hasn't * been set yet (psa_pake_set_password_key() * hasn't been called yet). * \param password Identifier of the key holding the password or a * value derived from the password (eg. by a * memory-hard function). It must remain valid * until the operation terminates. It must be of * type #PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow * the usage #PSA_KEY_USAGE_DERIVE. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE * \p password is not a valid key identifier. * \retval #PSA_ERROR_NOT_PERMITTED * The key does not have the #PSA_KEY_USAGE_DERIVE flag, or it does not * permit the \p operation's algorithm. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key type for \p password is not #PSA_KEY_TYPE_PASSWORD or * #PSA_KEY_TYPE_PASSWORD_HASH, or \p password is not compatible with * the \p operation's cipher suite. * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size of \p password is not supported with the * \p operation's cipher suite. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must have been set up.), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, mbedtls_svc_key_id_t password); /** Set the user ID for a password-authenticated key exchange. * * Call this function to set the user ID. For PAKE algorithms that associate a * user identifier with each side of the session you need to call * psa_pake_set_peer() as well. For PAKE algorithms that associate a single * user identifier with the session, call psa_pake_set_user() only. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[in,out] operation The operation object to set the user ID for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the user ID hasn't * been set (psa_pake_set_user() hasn't been * called yet). * \param[in] user_id The user ID to authenticate with. * \param user_id_len Size of the \p user_id buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p user_id is not valid for the \p operation's algorithm and cipher * suite. * \retval #PSA_ERROR_NOT_SUPPORTED * The value of \p user_id is not supported by the implementation. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, const uint8_t *user_id, size_t user_id_len); /** Set the peer ID for a password-authenticated key exchange. * * Call this function in addition to psa_pake_set_user() for PAKE algorithms * that associate a user identifier with each side of the session. For PAKE * algorithms that associate a single user identifier with the session, call * psa_pake_set_user() only. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[in,out] operation The operation object to set the peer ID for. It * must have been set up by psa_pake_setup() and * not yet in use (neither psa_pake_output() nor * psa_pake_input() has been called yet). It must * be on operation for which the peer ID hasn't * been set (psa_pake_set_peer() hasn't been * called yet). * \param[in] peer_id The peer's ID to authenticate. * \param peer_id_len Size of the \p peer_id buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p peer_id is not valid for the \p operation's algorithm and cipher * suite. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm doesn't associate a second identity with the session. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * Calling psa_pake_set_peer() is invalid with the \p operation's * algorithm, the operation state is not valid, or the library has not * been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, const uint8_t *peer_id, size_t peer_id_len); /** Set the application role for a password-authenticated key exchange. * * Not all PAKE algorithms need to differentiate the communicating entities. * It is optional to call this function for PAKEs that don't require a role * to be specified. For such PAKEs the application role parameter is ignored, * or #PSA_PAKE_ROLE_NONE can be passed as \c role. * * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) * for more information. * * \param[in,out] operation The operation object to specify the * application's role for. It must have been set up * by psa_pake_setup() and not yet in use (neither * psa_pake_output() nor psa_pake_input() has been * called yet). It must be on operation for which * the application's role hasn't been specified * (psa_pake_set_role() hasn't been called yet). * \param role A value of type ::psa_pake_role_t indicating the * application's role in the PAKE the algorithm * that is being set up. For more information see * the documentation of \c PSA_PAKE_ROLE_XXX * constants. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The \p role is not a valid PAKE role in the \p operation’s algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * The \p role for this algorithm is not supported or is not valid. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid, or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_set_role(psa_pake_operation_t *operation, psa_pake_role_t role); /** Get output for a step of a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. * \param step The step of the algorithm for which the output is * requested. * \param[out] output Buffer where the output is to be written in the * format appropriate for this \p step. Refer to * the documentation of the individual * \c PSA_PAKE_STEP_XXX constants for more * information. * \param output_size Size of the \p output buffer in bytes. This must * be at least #PSA_PAKE_OUTPUT_SIZE(\c alg, \c * primitive, \p output_step) where \c alg and * \p primitive are the PAKE algorithm and primitive * in the operation's cipher suite, and \p step is * the output step. * * \param[out] output_length On success, the number of bytes of the returned * output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p step is not compatible with the operation's algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * \p step is not supported with the operation's algorithm. * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, and fully set * up, and this call must conform to the algorithm's requirements * for ordering of input and output steps), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_output(psa_pake_operation_t *operation, psa_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length); /** Provide input for a step of a password-authenticated key exchange. * * Depending on the algorithm being executed, you might need to call this * function several times or you might not need to call this at all. * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling psa_pake_abort(). * * \param[in,out] operation Active PAKE operation. * \param step The step for which the input is provided. * \param[in] input Buffer containing the input in the format * appropriate for this \p step. Refer to the * documentation of the individual * \c PSA_PAKE_STEP_XXX constants for more * information. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p input_length is not compatible with the \p operation’s algorithm, * or the \p input is not valid for the \p operation's algorithm, * cipher suite or \p step. * \retval #PSA_ERROR_NOT_SUPPORTED * \p step p is not supported with the \p operation's algorithm, or the * \p input is not supported for the \p operation's algorithm, cipher * suite or \p step. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active, and fully set * up, and this call must conform to the algorithm's requirements * for ordering of input and output steps), or * the library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_input(psa_pake_operation_t *operation, psa_pake_step_t step, const uint8_t *input, size_t input_length); /** Get implicitly confirmed shared secret from a PAKE. * * At this point there is a cryptographic guarantee that only the authenticated * party who used the same password is able to compute the key. But there is no * guarantee that the peer is the party it claims to be and was able to do so. * * That is, the authentication is only implicit. Since the peer is not * authenticated yet, no action should be taken yet that assumes that the peer * is who it claims to be. For example, do not access restricted files on the * peer's behalf until an explicit authentication has succeeded. * * This function can be called after the key exchange phase of the operation * has completed. It imports the shared secret output of the PAKE into the * provided derivation operation. The input step * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key * material in the key derivation operation. * * The exact sequence of calls to perform a password-authenticated key * exchange depends on the algorithm in use. Refer to the documentation of * individual PAKE algorithm types (`PSA_ALG_XXX` values of type * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more * information. * * When this function returns successfully, \p operation becomes inactive. * If this function returns an error status, both \p operation * and \c key_derivation operations enter an error state and must be aborted by * calling psa_pake_abort() and psa_key_derivation_abort() respectively. * * \param[in,out] operation Active PAKE operation. * \param[out] output A key derivation operation that is ready * for an input step of type * #PSA_KEY_DERIVATION_INPUT_SECRET. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the * algorithm in the \p output key derivation operation. * \retval #PSA_ERROR_NOT_SUPPORTED * Input from a PAKE is not supported by the algorithm in the \p output * key derivation operation. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_BAD_STATE * The PAKE operation state is not valid (it must be active, but beyond * that validity is specific to the algorithm), or * the library has not been previously initialized by psa_crypto_init(), * or the state of \p output is not valid for * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the * step is out of order or the application has done this step already * and it may not be repeated. * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, psa_key_derivation_operation_t *output); /** Abort a PAKE operation. * * Aborting an operation frees all associated resources except for the \c * operation structure itself. Once aborted, the operation object can be reused * for another operation by calling psa_pake_setup() again. * * This function may be called at any time after the operation * object has been initialized as described in #psa_pake_operation_t. * * In particular, calling psa_pake_abort() after the operation has been * terminated by a call to psa_pake_abort() or psa_pake_get_implicit_key() * is safe and has no effect. * * \param[in,out] operation The operation to abort. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t psa_pake_abort(psa_pake_operation_t *operation); /**@}*/ /** A sufficient output buffer size for psa_pake_output(). * * If the size of the output buffer is at least this large, it is guaranteed * that psa_pake_output() will not fail due to an insufficient output buffer * size. The actual size of the output might be smaller in any given call. * * See also #PSA_PAKE_OUTPUT_MAX_SIZE * * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. * \param output_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient output buffer size for the specified * PAKE algorithm, primitive, and output step. If the * PAKE algorithm, primitive, or output step is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) \ (alg == PSA_ALG_JPAKE && \ primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ PSA_ECC_FAMILY_SECP_R1, 256) ? \ ( \ output_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ output_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ 32 \ ) : \ 0) /** A sufficient input buffer size for psa_pake_input(). * * The value returned by this macro is guaranteed to be large enough for any * valid input to psa_pake_input() in an operation with the specified * parameters. * * See also #PSA_PAKE_INPUT_MAX_SIZE * * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_PAKE(\p alg) is true). * \param primitive A primitive of type ::psa_pake_primitive_t that is * compatible with algorithm \p alg. * \param input_step A value of type ::psa_pake_step_t that is valid for the * algorithm \p alg. * \return A sufficient input buffer size for the specified * input, cipher suite and algorithm. If the cipher suite, * the input type or PAKE algorithm is not recognized, or * the parameters are incompatible, return 0. */ #define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) \ (alg == PSA_ALG_JPAKE && \ primitive == PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, \ PSA_ECC_FAMILY_SECP_R1, 256) ? \ ( \ input_step == PSA_PAKE_STEP_KEY_SHARE ? 65 : \ input_step == PSA_PAKE_STEP_ZK_PUBLIC ? 65 : \ 32 \ ) : \ 0) /** Output buffer size for psa_pake_output() for any of the supported PAKE * algorithm and primitive suites and output step. * * This macro must expand to a compile-time constant integer. * * The value of this macro must be at least as large as the largest value * returned by PSA_PAKE_OUTPUT_SIZE() * * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p output_step). */ #define PSA_PAKE_OUTPUT_MAX_SIZE 65 /** Input buffer size for psa_pake_input() for any of the supported PAKE * algorithm and primitive suites and input step. * * This macro must expand to a compile-time constant integer. * * The value of this macro must be at least as large as the largest value * returned by PSA_PAKE_INPUT_SIZE() * * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p output_step). */ #define PSA_PAKE_INPUT_MAX_SIZE 65 /** Returns a suitable initializer for a PAKE cipher suite object of type * psa_pake_cipher_suite_t. */ #define PSA_PAKE_CIPHER_SUITE_INIT { PSA_ALG_NONE, 0, 0, 0, PSA_ALG_NONE } /** Returns a suitable initializer for a PAKE operation object of type * psa_pake_operation_t. */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_PAKE_OPERATION_INIT { 0 } #else #define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, 0, PSA_PAKE_OPERATION_STAGE_SETUP, \ { 0 }, { { 0 } } } #endif struct psa_pake_cipher_suite_s { psa_algorithm_t algorithm; psa_pake_primitive_type_t type; psa_pake_family_t family; uint16_t bits; psa_algorithm_t hash; }; static inline psa_algorithm_t psa_pake_cs_get_algorithm( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->algorithm; } static inline void psa_pake_cs_set_algorithm( psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t algorithm) { if (!PSA_ALG_IS_PAKE(algorithm)) { cipher_suite->algorithm = 0; } else { cipher_suite->algorithm = algorithm; } } static inline psa_pake_primitive_t psa_pake_cs_get_primitive( const psa_pake_cipher_suite_t *cipher_suite) { return PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, cipher_suite->bits); } static inline void psa_pake_cs_set_primitive( psa_pake_cipher_suite_t *cipher_suite, psa_pake_primitive_t primitive) { cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16)); cipher_suite->bits = (uint16_t) (0xFFFF & primitive); } static inline psa_pake_family_t psa_pake_cs_get_family( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->family; } static inline uint16_t psa_pake_cs_get_bits( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->bits; } static inline psa_algorithm_t psa_pake_cs_get_hash( const psa_pake_cipher_suite_t *cipher_suite) { return cipher_suite->hash; } static inline void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite, psa_algorithm_t hash) { if (!PSA_ALG_IS_HASH(hash)) { cipher_suite->hash = 0; } else { cipher_suite->hash = hash; } } struct psa_crypto_driver_pake_inputs_s { uint8_t *MBEDTLS_PRIVATE(password); size_t MBEDTLS_PRIVATE(password_len); uint8_t *MBEDTLS_PRIVATE(user); size_t MBEDTLS_PRIVATE(user_len); uint8_t *MBEDTLS_PRIVATE(peer); size_t MBEDTLS_PRIVATE(peer_len); psa_key_attributes_t MBEDTLS_PRIVATE(attributes); psa_pake_cipher_suite_t MBEDTLS_PRIVATE(cipher_suite); }; typedef enum psa_crypto_driver_pake_step { PSA_JPAKE_STEP_INVALID = 0, /* Invalid step */ PSA_JPAKE_X1_STEP_KEY_SHARE = 1, /* Round 1: input/output key share (for ephemeral private key X1).*/ PSA_JPAKE_X1_STEP_ZK_PUBLIC = 2, /* Round 1: input/output Schnorr NIZKP public key for the X1 key */ PSA_JPAKE_X1_STEP_ZK_PROOF = 3, /* Round 1: input/output Schnorr NIZKP proof for the X1 key */ PSA_JPAKE_X2_STEP_KEY_SHARE = 4, /* Round 1: input/output key share (for ephemeral private key X2).*/ PSA_JPAKE_X2_STEP_ZK_PUBLIC = 5, /* Round 1: input/output Schnorr NIZKP public key for the X2 key */ PSA_JPAKE_X2_STEP_ZK_PROOF = 6, /* Round 1: input/output Schnorr NIZKP proof for the X2 key */ PSA_JPAKE_X2S_STEP_KEY_SHARE = 7, /* Round 2: output X2S key (our key) */ PSA_JPAKE_X2S_STEP_ZK_PUBLIC = 8, /* Round 2: output Schnorr NIZKP public key for the X2S key (our key) */ PSA_JPAKE_X2S_STEP_ZK_PROOF = 9, /* Round 2: output Schnorr NIZKP proof for the X2S key (our key) */ PSA_JPAKE_X4S_STEP_KEY_SHARE = 10, /* Round 2: input X4S key (from peer) */ PSA_JPAKE_X4S_STEP_ZK_PUBLIC = 11, /* Round 2: input Schnorr NIZKP public key for the X4S key (from peer) */ PSA_JPAKE_X4S_STEP_ZK_PROOF = 12 /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */ } psa_crypto_driver_pake_step_t; typedef enum psa_jpake_round { PSA_JPAKE_FIRST = 0, PSA_JPAKE_SECOND = 1, PSA_JPAKE_FINISHED = 2 } psa_jpake_round_t; typedef enum psa_jpake_io_mode { PSA_JPAKE_INPUT = 0, PSA_JPAKE_OUTPUT = 1 } psa_jpake_io_mode_t; struct psa_jpake_computation_stage_s { /* The J-PAKE round we are currently on */ psa_jpake_round_t MBEDTLS_PRIVATE(round); /* The 'mode' we are currently in (inputting or outputting) */ psa_jpake_io_mode_t MBEDTLS_PRIVATE(io_mode); /* The number of completed inputs so far this round */ uint8_t MBEDTLS_PRIVATE(inputs); /* The number of completed outputs so far this round */ uint8_t MBEDTLS_PRIVATE(outputs); /* The next expected step (KEY_SHARE, ZK_PUBLIC or ZK_PROOF) */ psa_pake_step_t MBEDTLS_PRIVATE(step); }; #define PSA_JPAKE_EXPECTED_INPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \ ((round) == PSA_JPAKE_FIRST ? 2 : 1)) #define PSA_JPAKE_EXPECTED_OUTPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \ ((round) == PSA_JPAKE_FIRST ? 2 : 1)) struct psa_pake_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); /* Algorithm of the PAKE operation */ psa_algorithm_t MBEDTLS_PRIVATE(alg); /* A primitive of type compatible with algorithm */ psa_pake_primitive_t MBEDTLS_PRIVATE(primitive); /* Stage of the PAKE operation: waiting for the setup, collecting inputs * or computing. */ uint8_t MBEDTLS_PRIVATE(stage); /* Holds computation stage of the PAKE algorithms. */ union { uint8_t MBEDTLS_PRIVATE(dummy); #if defined(PSA_WANT_ALG_JPAKE) psa_jpake_computation_stage_t MBEDTLS_PRIVATE(jpake); #endif } MBEDTLS_PRIVATE(computation_stage); union { psa_driver_pake_context_t MBEDTLS_PRIVATE(ctx); psa_crypto_driver_pake_inputs_t MBEDTLS_PRIVATE(inputs); } MBEDTLS_PRIVATE(data); #endif }; static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init(void) { const struct psa_pake_cipher_suite_s v = PSA_PAKE_CIPHER_SUITE_INIT; return v; } static inline struct psa_pake_operation_s psa_pake_operation_init(void) { const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; return v; } #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_EXTRA_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_legacy.h000066400000000000000000000060571464416617300251230ustar00rootroot00000000000000/** * \file psa/crypto_legacy.h * * \brief Add temporary suppport for deprecated symbols before they are * removed from the library. * * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR * symbols are deprecated. * New symols add a suffix to that base name in order to clearly state what is * the expected use for the key (use, import, export, generate, derive). * Here we define some backward compatibility support for uses stil using * the legacy symbols. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_CRYPTO_LEGACY_H #define MBEDTLS_PSA_CRYPTO_LEGACY_H #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) //no-check-names #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 #endif #if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 #endif #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) //no-check-names #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 #endif #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 #endif #if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 #endif #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) //no-check-names #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE #endif #endif #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) //no-check-names #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT #endif #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE) #define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE #endif #endif #endif /* MBEDTLS_PSA_CRYPTO_LEGACY_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h000066400000000000000000000067421464416617300255040ustar00rootroot00000000000000/** * \file psa/crypto_platform.h * * \brief PSA cryptography module: Mbed TLS platform definitions * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file contains platform-dependent type definitions. * * In implementations with isolation between the application and the * cryptography module, implementers should take care to ensure that * the definitions that are exposed to applications match what the * module implements. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_PLATFORM_H #define PSA_CRYPTO_PLATFORM_H #include "mbedtls/private_access.h" /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" /* PSA requires several types which C99 provides in stdint.h. */ #include #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA * partition identifier. * * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that * translates a key identifier to a key storage file name assumes that * mbedtls_key_owner_id_t is a 32-bit integer. This function thus needs * reworking if mbedtls_key_owner_id_t is not defined as a 32-bit integer * here anymore. */ typedef int32_t mbedtls_key_owner_id_t; /** Compare two key owner identifiers. * * \param id1 First key owner identifier. * \param id2 Second key owner identifier. * * \return Non-zero if the two key owner identifiers are equal, zero otherwise. */ static inline int mbedtls_key_owner_id_equal(mbedtls_key_owner_id_t id1, mbedtls_key_owner_id_t id2) { return id1 == id2; } #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /* * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM * (Secure Partition Manager) integration which separates the code into two * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing * Environment). When building for the SPE, an additional header file should be * included. */ #if defined(MBEDTLS_PSA_CRYPTO_SPM) #define PSA_CRYPTO_SECURE 1 #include "crypto_spe.h" #endif // MBEDTLS_PSA_CRYPTO_SPM #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** The type of the context passed to mbedtls_psa_external_get_random(). * * Mbed TLS initializes the context to all-bits-zero before calling * mbedtls_psa_external_get_random() for the first time. * * The definition of this type in the Mbed TLS source code is for * demonstration purposes. Implementers of mbedtls_psa_external_get_random() * are expected to replace it with a custom definition. */ typedef struct { uintptr_t MBEDTLS_PRIVATE(opaque)[2]; } mbedtls_psa_external_random_context_t; #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) /** The type of the client handle used in context structures * * When a client view of the multipart context structures is required, * this handle is used to keep a mapping with the service side of the * context which contains the actual data. */ typedef uint32_t mbedtls_psa_client_handle_t; #endif #endif /* PSA_CRYPTO_PLATFORM_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h000066400000000000000000002045041464416617300256360ustar00rootroot00000000000000/** * \file psa/crypto_se_driver.h * \brief PSA external cryptoprocessor driver module * * This header declares types and function signatures for cryptography * drivers that access key material via opaque references. * This is meant for cryptoprocessors that have a separate key storage from the * space in which the PSA Crypto implementation runs, typically secure * elements (SEs). * * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), * containing functions for driver developers to implement to enable hardware * to be called in a standardized way by a PSA Cryptography API * implementation. The functions comprising the driver HAL, which driver * authors implement, are not intended to be called by application developers. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SE_DRIVER_H #define PSA_CRYPTO_SE_DRIVER_H #include "mbedtls/private_access.h" #include "crypto_driver_common.h" #ifdef __cplusplus extern "C" { #endif /** \defgroup se_init Secure element driver initialization */ /**@{*/ /** \brief Driver context structure * * Driver functions receive a pointer to this structure. * Each registered driver has one instance of this structure. * * Implementations must include the fields specified here and * may include other fields. */ typedef struct { /** A read-only pointer to the driver's persistent data. * * Drivers typically use this persistent data to keep track of * which slot numbers are available. This is only a guideline: * drivers may use the persistent data for any purpose, keeping * in mind the restrictions on when the persistent data is saved * to storage: the persistent data is only saved after calling * certain functions that receive a writable pointer to the * persistent data. * * The core allocates a memory buffer for the persistent data. * The pointer is guaranteed to be suitably aligned for any data type, * like a pointer returned by `malloc` (but the core can use any * method to allocate the buffer, not necessarily `malloc`). * * The size of this buffer is in the \c persistent_data_size field of * this structure. * * Before the driver is initialized for the first time, the content of * the persistent data is all-bits-zero. After a driver upgrade, if the * size of the persistent data has increased, the original data is padded * on the right with zeros; if the size has decreased, the original data * is truncated to the new size. * * This pointer is to read-only data. Only a few driver functions are * allowed to modify the persistent data. These functions receive a * writable pointer. These functions are: * - psa_drv_se_t::p_init * - psa_drv_se_key_management_t::p_allocate * - psa_drv_se_key_management_t::p_destroy * * The PSA Cryptography core saves the persistent data from one * session to the next. It does this before returning from API functions * that call a driver method that is allowed to modify the persistent * data, specifically: * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call * psa_drv_se_key_management_t::p_destroy to complete an action * that was interrupted by a power failure. * - Key creation functions cause a call to * psa_drv_se_key_management_t::p_allocate, and may cause a call to * psa_drv_se_key_management_t::p_destroy in case an error occurs. * - psa_destroy_key() causes a call to * psa_drv_se_key_management_t::p_destroy. */ const void *const MBEDTLS_PRIVATE(persistent_data); /** The size of \c persistent_data in bytes. * * This is always equal to the value of the `persistent_data_size` field * of the ::psa_drv_se_t structure when the driver is registered. */ const size_t MBEDTLS_PRIVATE(persistent_data_size); /** Driver transient data. * * The core initializes this value to 0 and does not read or modify it * afterwards. The driver may store whatever it wants in this field. */ uintptr_t MBEDTLS_PRIVATE(transient_data); } psa_drv_se_context_t; /** \brief A driver initialization function. * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param location The location value for which this driver * is registered. The driver will be invoked * for all keys whose lifetime is in this * location. * * \retval #PSA_SUCCESS * The driver is operational. * The core will update the persistent data in storage. * \return * Any other return value prevents the driver from being used in * this session. * The core will NOT update the persistent data in storage. */ typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, void *persistent_data, psa_key_location_t location); #if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Mbed TLS with secure element support enabled defines this type in * crypto_types.h because it is also visible to applications through an * implementation-specific extension. * For the PSA Cryptography specification, this type is only visible * via crypto_se_driver.h. */ /** An internal designation of a key slot between the core part of the * PSA Crypto implementation and the driver. The meaning of this value * is driver-dependent. */ typedef uint64_t psa_key_slot_number_t; #endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ /**@}*/ /** \defgroup se_mac Secure Element Message Authentication Codes * Generation and authentication of Message Authentication Codes (MACs) using * a secure element can be done either as a single function call (via the * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in * parts using the following sequence: * - `psa_drv_se_mac_setup_t` * - `psa_drv_se_mac_update_t` * - `psa_drv_se_mac_update_t` * - ... * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` * * If a previously started secure element MAC operation needs to be terminated, * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may * result in allocated resources not being freed or in other undefined * behavior. */ /**@{*/ /** \brief A function that starts a secure element MAC operation for a PSA * Crypto Driver implementation * * \param[in,out] drv_context The driver context structure. * \param[in,out] op_context A structure that will contain the * hardware-specific MAC context * \param[in] key_slot The slot of the key to be used for the * operation * \param[in] algorithm The algorithm to be used to underly the MAC * operation * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, void *op_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm); /** \brief A function that continues a previously started secure element MAC * operation * * \param[in,out] op_context A hardware-specific structure for the * previously-established MAC operation to be * updated * \param[in] p_input A buffer containing the message to be appended * to the MAC operation * \param[in] input_length The size in bytes of the input message buffer */ typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, const uint8_t *p_input, size_t input_length); /** \brief a function that completes a previously started secure element MAC * operation by returning the resulting MAC. * * \param[in,out] op_context A hardware-specific structure for the * previously started MAC operation to be * finished * \param[out] p_mac A buffer where the generated MAC will be * placed * \param[in] mac_size The size in bytes of the buffer that has been * allocated for the `output` buffer * \param[out] p_mac_length After completion, will contain the number of * bytes placed in the `p_mac` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, uint8_t *p_mac, size_t mac_size, size_t *p_mac_length); /** \brief A function that completes a previously started secure element MAC * operation by comparing the resulting MAC against a provided value * * \param[in,out] op_context A hardware-specific structure for the previously * started MAC operation to be finished * \param[in] p_mac The MAC value against which the resulting MAC * will be compared against * \param[in] mac_length The size in bytes of the value stored in `p_mac` * * \retval #PSA_SUCCESS * The operation completed successfully and the MACs matched each * other * \retval #PSA_ERROR_INVALID_SIGNATURE * The operation completed successfully, but the calculated MAC did * not match the provided MAC */ typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, const uint8_t *p_mac, size_t mac_length); /** \brief A function that aborts a previous started secure element MAC * operation * * \param[in,out] op_context A hardware-specific structure for the previously * started MAC operation to be aborted */ typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); /** \brief A function that performs a secure element MAC operation in one * command and returns the calculated MAC * * \param[in,out] drv_context The driver context structure. * \param[in] p_input A buffer containing the message to be MACed * \param[in] input_length The size in bytes of `p_input` * \param[in] key_slot The slot of the key to be used * \param[in] alg The algorithm to be used to underlie the MAC * operation * \param[out] p_mac A buffer where the generated MAC will be * placed * \param[in] mac_size The size in bytes of the `p_mac` buffer * \param[out] p_mac_length After completion, will contain the number of * bytes placed in the `output` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, const uint8_t *p_input, size_t input_length, psa_key_slot_number_t key_slot, psa_algorithm_t alg, uint8_t *p_mac, size_t mac_size, size_t *p_mac_length); /** \brief A function that performs a secure element MAC operation in one * command and compares the resulting MAC against a provided value * * \param[in,out] drv_context The driver context structure. * \param[in] p_input A buffer containing the message to be MACed * \param[in] input_length The size in bytes of `input` * \param[in] key_slot The slot of the key to be used * \param[in] alg The algorithm to be used to underlie the MAC * operation * \param[in] p_mac The MAC value against which the resulting MAC will * be compared against * \param[in] mac_length The size in bytes of `mac` * * \retval #PSA_SUCCESS * The operation completed successfully and the MACs matched each * other * \retval #PSA_ERROR_INVALID_SIGNATURE * The operation completed successfully, but the calculated MAC did * not match the provided MAC */ typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, const uint8_t *p_input, size_t input_length, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_mac, size_t mac_length); /** \brief A struct containing all of the function pointers needed to * perform secure element MAC operations * * PSA Crypto API implementations should populate the table as appropriate * upon startup. * * If one of the functions is not implemented (such as * `psa_drv_se_mac_generate_t`), it should be set to NULL. * * Driver implementers should ensure that they implement all of the functions * that make sense for their hardware, and that they provide a full solution * (for example, if they support `p_setup`, they should also support * `p_update` and at least one of `p_finish` or `p_finish_verify`). * */ typedef struct { /**The size in bytes of the hardware-specific secure element MAC context * structure */ size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a MAC setup operation */ psa_drv_se_mac_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that performs a MAC update operation */ psa_drv_se_mac_update_t MBEDTLS_PRIVATE(p_update); /** Function that completes a MAC operation */ psa_drv_se_mac_finish_t MBEDTLS_PRIVATE(p_finish); /** Function that completes a MAC operation with a verify check */ psa_drv_se_mac_finish_verify_t MBEDTLS_PRIVATE(p_finish_verify); /** Function that aborts a previously started MAC operation */ psa_drv_se_mac_abort_t MBEDTLS_PRIVATE(p_abort); /** Function that performs a MAC operation in one call */ psa_drv_se_mac_generate_t MBEDTLS_PRIVATE(p_mac); /** Function that performs a MAC and verify operation in one call */ psa_drv_se_mac_verify_t MBEDTLS_PRIVATE(p_mac_verify); } psa_drv_se_mac_t; /**@}*/ /** \defgroup se_cipher Secure Element Symmetric Ciphers * * Encryption and Decryption using secure element keys in block modes other * than ECB must be done in multiple parts, using the following flow: * - `psa_drv_se_cipher_setup_t` * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) * - `psa_drv_se_cipher_update_t` * - `psa_drv_se_cipher_update_t` * - ... * - `psa_drv_se_cipher_finish_t` * * If a previously started secure element Cipher operation needs to be * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure * to do so may result in allocated resources not being freed or in other * undefined behavior. * * In situations where a PSA Cryptographic API implementation is using a block * mode not-supported by the underlying hardware or driver, it can construct * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function * for the cipher operations. */ /**@{*/ /** \brief A function that provides the cipher setup function for a * secure element driver * * \param[in,out] drv_context The driver context structure. * \param[in,out] op_context A structure that will contain the * hardware-specific cipher context. * \param[in] key_slot The slot of the key to be used for the * operation * \param[in] algorithm The algorithm to be used in the cipher * operation * \param[in] direction Indicates whether the operation is an encrypt * or decrypt * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, void *op_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, psa_encrypt_or_decrypt_t direction); /** \brief A function that sets the initialization vector (if * necessary) for a secure element cipher operation * * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has * two IV functions: one to set the IV, and one to generate it internally. The * generate function is not necessary for the drivers to implement as the PSA * Crypto implementation can do the generation using its RNG features. * * \param[in,out] op_context A structure that contains the previously set up * hardware-specific cipher context * \param[in] p_iv A buffer containing the initialization vector * \param[in] iv_length The size (in bytes) of the `p_iv` buffer * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, const uint8_t *p_iv, size_t iv_length); /** \brief A function that continues a previously started secure element cipher * operation * * \param[in,out] op_context A hardware-specific structure for the * previously started cipher operation * \param[in] p_input A buffer containing the data to be * encrypted/decrypted * \param[in] input_size The size in bytes of the buffer pointed to * by `p_input` * \param[out] p_output The caller-allocated buffer where the * output will be placed * \param[in] output_size The allocated size in bytes of the * `p_output` buffer * \param[out] p_output_length After completion, will contain the number * of bytes placed in the `p_output` buffer * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, const uint8_t *p_input, size_t input_size, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** \brief A function that completes a previously started secure element cipher * operation * * \param[in,out] op_context A hardware-specific structure for the * previously started cipher operation * \param[out] p_output The caller-allocated buffer where the output * will be placed * \param[in] output_size The allocated size in bytes of the `p_output` * buffer * \param[out] p_output_length After completion, will contain the number of * bytes placed in the `p_output` buffer * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** \brief A function that aborts a previously started secure element cipher * operation * * \param[in,out] op_context A hardware-specific structure for the * previously started cipher operation */ typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); /** \brief A function that performs the ECB block mode for secure element * cipher operations * * Note: this function should only be used with implementations that do not * provide a needed higher-level operation. * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot The slot of the key to be used for the operation * \param[in] algorithm The algorithm to be used in the cipher operation * \param[in] direction Indicates whether the operation is an encrypt or * decrypt * \param[in] p_input A buffer containing the data to be * encrypted/decrypted * \param[in] input_size The size in bytes of the buffer pointed to by * `p_input` * \param[out] p_output The caller-allocated buffer where the output * will be placed * \param[in] output_size The allocated size in bytes of the `p_output` * buffer * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, psa_encrypt_or_decrypt_t direction, const uint8_t *p_input, size_t input_size, uint8_t *p_output, size_t output_size); /** * \brief A struct containing all of the function pointers needed to implement * cipher operations using secure elements. * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup or at build time. * * If one of the functions is not implemented (such as * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. */ typedef struct { /** The size in bytes of the hardware-specific secure element cipher * context structure */ size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a cipher setup operation */ psa_drv_se_cipher_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that sets a cipher IV (if necessary) */ psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv); /** Function that performs a cipher update operation */ psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update); /** Function that completes a cipher operation */ psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish); /** Function that aborts a cipher operation */ psa_drv_se_cipher_abort_t MBEDTLS_PRIVATE(p_abort); /** Function that performs ECB mode for a cipher operation * (Danger: ECB mode should not be used directly by clients of the PSA * Crypto Client API) */ psa_drv_se_cipher_ecb_t MBEDTLS_PRIVATE(p_ecb); } psa_drv_se_cipher_t; /**@}*/ /** \defgroup se_asymmetric Secure Element Asymmetric Cryptography * * Since the amount of data that can (or should) be encrypted or signed using * asymmetric keys is limited by the key size, asymmetric key operations using * keys in a secure element must be done in single function calls. */ /**@{*/ /** * \brief A function that signs a hash or short message with a private key in * a secure element * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of an asymmetric key pair * \param[in] alg A signature algorithm that is compatible * with the type of `key` * \param[in] p_hash The hash to sign * \param[in] hash_length Size of the `p_hash` buffer in bytes * \param[out] p_signature Buffer where the signature is to be written * \param[in] signature_size Size of the `p_signature` buffer in bytes * \param[out] p_signature_length On success, the number of bytes * that make up the returned signature value * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_hash, size_t hash_length, uint8_t *p_signature, size_t signature_size, size_t *p_signature_length); /** * \brief A function that verifies the signature a hash or short message using * an asymmetric public key in a secure element * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of a public key or an asymmetric key * pair * \param[in] alg A signature algorithm that is compatible with * the type of `key` * \param[in] p_hash The hash whose signature is to be verified * \param[in] hash_length Size of the `p_hash` buffer in bytes * \param[in] p_signature Buffer containing the signature to verify * \param[in] signature_length Size of the `p_signature` buffer in bytes * * \retval #PSA_SUCCESS * The signature is valid. */ typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_hash, size_t hash_length, const uint8_t *p_signature, size_t signature_length); /** * \brief A function that encrypts a short message with an asymmetric public * key in a secure element * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of a public key or an asymmetric key * pair * \param[in] alg An asymmetric encryption algorithm that is * compatible with the type of `key` * \param[in] p_input The message to encrypt * \param[in] input_length Size of the `p_input` buffer in bytes * \param[in] p_salt A salt or label, if supported by the * encryption algorithm * If the algorithm does not support a * salt, pass `NULL`. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass `NULL`. * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param[in] salt_length Size of the `p_salt` buffer in bytes * If `p_salt` is `NULL`, pass 0. * \param[out] p_output Buffer where the encrypted message is to * be written * \param[in] output_size Size of the `p_output` buffer in bytes * \param[out] p_output_length On success, the number of bytes that make up * the returned output * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_input, size_t input_length, const uint8_t *p_salt, size_t salt_length, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** * \brief A function that decrypts a short message with an asymmetric private * key in a secure element. * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Key slot of an asymmetric key pair * \param[in] alg An asymmetric encryption algorithm that is * compatible with the type of `key` * \param[in] p_input The message to decrypt * \param[in] input_length Size of the `p_input` buffer in bytes * \param[in] p_salt A salt or label, if supported by the * encryption algorithm * If the algorithm does not support a * salt, pass `NULL`. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass `NULL`. * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param[in] salt_length Size of the `p_salt` buffer in bytes * If `p_salt` is `NULL`, pass 0. * \param[out] p_output Buffer where the decrypted message is to * be written * \param[in] output_size Size of the `p_output` buffer in bytes * \param[out] p_output_length On success, the number of bytes * that make up the returned output * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t alg, const uint8_t *p_input, size_t input_length, const uint8_t *p_salt, size_t salt_length, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** * \brief A struct containing all of the function pointers needed to implement * asymmetric cryptographic operations using secure elements. * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup or at build time. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** Function that performs an asymmetric sign operation */ psa_drv_se_asymmetric_sign_t MBEDTLS_PRIVATE(p_sign); /** Function that performs an asymmetric verify operation */ psa_drv_se_asymmetric_verify_t MBEDTLS_PRIVATE(p_verify); /** Function that performs an asymmetric encrypt operation */ psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt); /** Function that performs an asymmetric decrypt operation */ psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt); } psa_drv_se_asymmetric_t; /**@}*/ /** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data * Authenticated Encryption with Additional Data (AEAD) operations with secure * elements must be done in one function call. While this creates a burden for * implementers as there must be sufficient space in memory for the entire * message, it prevents decrypted data from being made available before the * authentication operation is complete and the data is known to be authentic. */ /**@{*/ /** \brief A function that performs a secure element authenticated encryption * operation * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Slot containing the key to use. * \param[in] algorithm The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(`alg`) is true) * \param[in] p_nonce Nonce or IV to use * \param[in] nonce_length Size of the `p_nonce` buffer in bytes * \param[in] p_additional_data Additional data that will be * authenticated but not encrypted * \param[in] additional_data_length Size of `p_additional_data` in bytes * \param[in] p_plaintext Data that will be authenticated and * encrypted * \param[in] plaintext_length Size of `p_plaintext` in bytes * \param[out] p_ciphertext Output buffer for the authenticated and * encrypted data. The additional data is * not part of this output. For algorithms * where the encrypted data and the * authentication tag are defined as * separate outputs, the authentication * tag is appended to the encrypted data. * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in * bytes * \param[out] p_ciphertext_length On success, the size of the output in * the `p_ciphertext` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, const uint8_t *p_nonce, size_t nonce_length, const uint8_t *p_additional_data, size_t additional_data_length, const uint8_t *p_plaintext, size_t plaintext_length, uint8_t *p_ciphertext, size_t ciphertext_size, size_t *p_ciphertext_length); /** A function that performs a secure element authenticated decryption operation * * \param[in,out] drv_context The driver context structure. * \param[in] key_slot Slot containing the key to use * \param[in] algorithm The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(`alg`) is true) * \param[in] p_nonce Nonce or IV to use * \param[in] nonce_length Size of the `p_nonce` buffer in bytes * \param[in] p_additional_data Additional data that has been * authenticated but not encrypted * \param[in] additional_data_length Size of `p_additional_data` in bytes * \param[in] p_ciphertext Data that has been authenticated and * encrypted. * For algorithms where the encrypted data * and the authentication tag are defined * as separate inputs, the buffer must * contain the encrypted data followed by * the authentication tag. * \param[in] ciphertext_length Size of `p_ciphertext` in bytes * \param[out] p_plaintext Output buffer for the decrypted data * \param[in] plaintext_size Size of the `p_plaintext` buffer in * bytes * \param[out] p_plaintext_length On success, the size of the output in * the `p_plaintext` buffer * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, psa_algorithm_t algorithm, const uint8_t *p_nonce, size_t nonce_length, const uint8_t *p_additional_data, size_t additional_data_length, const uint8_t *p_ciphertext, size_t ciphertext_length, uint8_t *p_plaintext, size_t plaintext_size, size_t *p_plaintext_length); /** * \brief A struct containing all of the function pointers needed to implement * secure element Authenticated Encryption with Additional Data operations * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** Function that performs the AEAD encrypt operation */ psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt); /** Function that performs the AEAD decrypt operation */ psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt); } psa_drv_se_aead_t; /**@}*/ /** \defgroup se_key_management Secure Element Key Management * Currently, key management is limited to importing keys in the clear, * destroying keys, and exporting keys in the clear. * Whether a key may be exported is determined by the key policies in place * on the key slot. */ /**@{*/ /** An enumeration indicating how a key is created. */ typedef enum { PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ #ifndef __DOXYGEN_ONLY__ /** A key is being registered with mbedtls_psa_register_se_key(). * * The core only passes this value to * psa_drv_se_key_management_t::p_validate_slot_number, not to * psa_drv_se_key_management_t::p_allocate. The call to * `p_validate_slot_number` is not followed by any other call to the * driver: the key is considered successfully registered if the call to * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is * null. * * With this creation method, the driver must return #PSA_SUCCESS if * the given attributes are compatible with the existing key in the slot, * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there * is no key with the specified slot number. * * This is an Mbed TLS extension. */ PSA_KEY_CREATION_REGISTER, #endif } psa_key_creation_method_t; /** \brief A function that allocates a slot for a key. * * To create a key in a specific slot in a secure element, the core * first calls this function to determine a valid slot number, * then calls a function to create the key material in that slot. * In nominal conditions (that is, if no error occurs), * the effect of a call to a key creation function in the PSA Cryptography * API with a lifetime that places the key in a secure element is the * following: * -# The core calls psa_drv_se_key_management_t::p_allocate * (or in some implementations * psa_drv_se_key_management_t::p_validate_slot_number). The driver * selects (or validates) a suitable slot number given the key attributes * and the state of the secure element. * -# The core calls a key creation function in the driver. * * The key creation functions in the PSA Cryptography API are: * - psa_import_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT * then a call to psa_drv_se_key_management_t::p_import. * - psa_generate_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE * then a call to psa_drv_se_key_management_t::p_import. * - psa_key_derivation_output_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE * then a call to psa_drv_se_key_derivation_t::p_derive. * - psa_copy_key(), which causes * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY * then a call to psa_drv_se_key_management_t::p_export. * * In case of errors, other behaviors are possible. * - If the PSA Cryptography subsystem dies after the first step, * for example because the device has lost power abruptly, * the second step may never happen, or may happen after a reset * and re-initialization. Alternatively, after a reset and * re-initialization, the core may call * psa_drv_se_key_management_t::p_destroy on the slot number that * was allocated (or validated) instead of calling a key creation function. * - If an error occurs, the core may call * psa_drv_se_key_management_t::p_destroy on the slot number that * was allocated (or validated) instead of calling a key creation function. * * Errors and system resets also have an impact on the driver's persistent * data. If a reset happens before the overall key creation process is * completed (before or after the second step above), it is unspecified * whether the persistent data after the reset is identical to what it * was before or after the call to `p_allocate` (or `p_validate_slot_number`). * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param[in] attributes Attributes of the key. * \param method The way in which the key is being created. * \param[out] key_slot Slot where the key will be stored. * This must be a valid slot for a key of the * chosen type. It must be unoccupied. * * \retval #PSA_SUCCESS * Success. * The core will record \c *key_slot as the key slot where the key * is stored and will update the persistent data in storage. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription */ typedef psa_status_t (*psa_drv_se_allocate_key_t)( psa_drv_se_context_t *drv_context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t *key_slot); /** \brief A function that determines whether a slot number is valid * for a key. * * To create a key in a specific slot in a secure element, the core * first calls this function to validate the choice of slot number, * then calls a function to create the key material in that slot. * See the documentation of #psa_drv_se_allocate_key_t for more details. * * As of the PSA Cryptography API specification version 1.0, there is no way * for applications to trigger a call to this function. However some * implementations offer the capability to create or declare a key in * a specific slot via implementation-specific means, generally for the * sake of initial device provisioning or onboarding. Such a mechanism may * be added to a future version of the PSA Cryptography API specification. * * This function may update the driver's persistent data through * \p persistent_data. The core will save the updated persistent data at the * end of the key creation process. See the description of * ::psa_drv_se_allocate_key_t for more information. * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param[in] attributes Attributes of the key. * \param method The way in which the key is being created. * \param[in] key_slot Slot where the key is to be stored. * * \retval #PSA_SUCCESS * The given slot number is valid for a key with the given * attributes. * \retval #PSA_ERROR_INVALID_ARGUMENT * The given slot number is not valid for a key with the * given attributes. This includes the case where the slot * number is not valid at all. * \retval #PSA_ERROR_ALREADY_EXISTS * There is already a key with the specified slot number. * Drivers may choose to return this error from the key * creation function instead. */ typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( psa_drv_se_context_t *drv_context, void *persistent_data, const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_key_slot_number_t key_slot); /** \brief A function that imports a key into a secure element in binary format * * This function can support any output from psa_export_key(). Refer to the * documentation of psa_export_key() for the format for each key type. * * \param[in,out] drv_context The driver context structure. * \param key_slot Slot where the key will be stored. * This must be a valid slot for a key of the * chosen type. It must be unoccupied. * \param[in] attributes The key attributes, including the lifetime, * the key type and the usage policy. * Drivers should not access the key size stored * in the attributes: it may not match the * data passed in \p data. * Drivers can call psa_get_key_lifetime(), * psa_get_key_type(), * psa_get_key_usage_flags() and * psa_get_key_algorithm() to access this * information. * \param[in] data Buffer containing the key data. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] bits On success, the key size in bits. The driver * must determine this value after parsing the * key according to the key type. * This value is not used if the function fails. * * \retval #PSA_SUCCESS * Success. */ typedef psa_status_t (*psa_drv_se_import_key_t)( psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *bits); /** * \brief A function that destroys a secure element key and restore the slot to * its default state * * This function destroys the content of the key from a secure element. * Implementations shall make a best effort to ensure that any previous content * of the slot is unrecoverable. * * This function returns the specified slot to its default state. * * \param[in,out] drv_context The driver context structure. * \param[in,out] persistent_data A pointer to the persistent data * that allows writing. * \param key_slot The key slot to erase. * * \retval #PSA_SUCCESS * The slot's content, if any, has been erased. */ typedef psa_status_t (*psa_drv_se_destroy_key_t)( psa_drv_se_context_t *drv_context, void *persistent_data, psa_key_slot_number_t key_slot); /** * \brief A function that exports a secure element key in binary format * * The output of this function can be passed to psa_import_key() to * create an equivalent object. * * If a key is created with `psa_import_key()` and then exported with * this function, it is not guaranteed that the resulting data is * identical: the implementation may choose a different representation * of the same key if the format permits it. * * This function should generate output in the same format that * `psa_export_key()` does. Refer to the * documentation of `psa_export_key()` for the format for each key type. * * \param[in,out] drv_context The driver context structure. * \param[in] key Slot whose content is to be exported. This must * be an occupied key slot. * \param[out] p_data Buffer where the key data is to be written. * \param[in] data_size Size of the `p_data` buffer in bytes. * \param[out] p_data_length On success, the number of bytes * that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, psa_key_slot_number_t key, uint8_t *p_data, size_t data_size, size_t *p_data_length); /** * \brief A function that generates a symmetric or asymmetric key on a secure * element * * If the key type \c type recorded in \p attributes * is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\c type) = 1), * the driver may export the public key at the time of generation, * in the format documented for psa_export_public_key() by writing it * to the \p pubkey buffer. * This is optional, intended for secure elements that output the * public key at generation time and that cannot export the public key * later. Drivers that do not need this feature should leave * \p *pubkey_length set to 0 and should * implement the psa_drv_key_management_t::p_export_public function. * Some implementations do not support this feature, in which case * \p pubkey is \c NULL and \p pubkey_size is 0. * * \param[in,out] drv_context The driver context structure. * \param key_slot Slot where the key will be stored. * This must be a valid slot for a key of the * chosen type. It must be unoccupied. * \param[in] attributes The key attributes, including the lifetime, * the key type and size, and the usage policy. * Drivers can call psa_get_key_lifetime(), * psa_get_key_type(), psa_get_key_bits(), * psa_get_key_usage_flags() and * psa_get_key_algorithm() to access this * information. * \param[out] pubkey A buffer where the driver can write the * public key, when generating an asymmetric * key pair. * This is \c NULL when generating a symmetric * key or if the core does not support * exporting the public key at generation time. * \param pubkey_size The size of the `pubkey` buffer in bytes. * This is 0 when generating a symmetric * key or if the core does not support * exporting the public key at generation time. * \param[out] pubkey_length On entry, this is always 0. * On success, the number of bytes written to * \p pubkey. If this is 0 or unchanged on return, * the core will not read the \p pubkey buffer, * and will instead call the driver's * psa_drv_key_management_t::p_export_public * function to export the public key when needed. */ typedef psa_status_t (*psa_drv_se_generate_key_t)( psa_drv_se_context_t *drv_context, psa_key_slot_number_t key_slot, const psa_key_attributes_t *attributes, uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); /** * \brief A struct containing all of the function pointers needed to for secure * element key management * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup or at build time. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** Function that allocates a slot for a key. */ psa_drv_se_allocate_key_t MBEDTLS_PRIVATE(p_allocate); /** Function that checks the validity of a slot for a key. */ psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number); /** Function that performs a key import operation */ psa_drv_se_import_key_t MBEDTLS_PRIVATE(p_import); /** Function that performs a generation */ psa_drv_se_generate_key_t MBEDTLS_PRIVATE(p_generate); /** Function that performs a key destroy operation */ psa_drv_se_destroy_key_t MBEDTLS_PRIVATE(p_destroy); /** Function that performs a key export operation */ psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export); /** Function that performs a public key export operation */ psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export_public); } psa_drv_se_key_management_t; /**@}*/ /** \defgroup driver_derivation Secure Element Key Derivation and Agreement * Key derivation is the process of generating new key material using an * existing key and additional parameters, iterating through a basic * cryptographic function, such as a hash. * Key agreement is a part of cryptographic protocols that allows two parties * to agree on the same key value, but starting from different original key * material. * The flows are similar, and the PSA Crypto Driver Model uses the same functions * for both of the flows. * * There are two different final functions for the flows, * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. * `psa_drv_se_key_derivation_derive` is used when the key material should be * placed in a slot on the hardware and not exposed to the caller. * `psa_drv_se_key_derivation_export` is used when the key material should be * returned to the PSA Cryptographic API implementation. * * Different key derivation algorithms require a different number of inputs. * Instead of having an API that takes as input variable length arrays, which * can be problematic to manage on embedded platforms, the inputs are passed * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that * is called multiple times with different `collateral_id`s. Thus, for a key * derivation algorithm that required 3 parameter inputs, the flow would look * something like: * ~~~~~~~~~~~~~{.c} * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, * p_collateral_0, * collateral_0_size); * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, * p_collateral_1, * collateral_1_size); * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, * p_collateral_2, * collateral_2_size); * psa_drv_se_key_derivation_derive(); * ~~~~~~~~~~~~~ * * key agreement example: * ~~~~~~~~~~~~~{.c} * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); * psa_drv_se_key_derivation_export(p_session_key, * session_key_size, * &session_key_length); * ~~~~~~~~~~~~~ */ /**@{*/ /** \brief A function that Sets up a secure element key derivation operation by * specifying the algorithm and the source key sot * * \param[in,out] drv_context The driver context structure. * \param[in,out] op_context A hardware-specific structure containing any * context information for the implementation * \param[in] kdf_alg The algorithm to be used for the key derivation * \param[in] source_key The key to be used as the source material for * the key derivation * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, void *op_context, psa_algorithm_t kdf_alg, psa_key_slot_number_t source_key); /** \brief A function that provides collateral (parameters) needed for a secure * element key derivation or key agreement operation * * Since many key derivation algorithms require multiple parameters, it is * expected that this function may be called multiple times for the same * operation, each with a different algorithm-specific `collateral_id` * * \param[in,out] op_context A hardware-specific structure containing any * context information for the implementation * \param[in] collateral_id An ID for the collateral being provided * \param[in] p_collateral A buffer containing the collateral data * \param[in] collateral_size The size in bytes of the collateral * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, uint32_t collateral_id, const uint8_t *p_collateral, size_t collateral_size); /** \brief A function that performs the final secure element key derivation * step and place the generated key material in a slot * * \param[in,out] op_context A hardware-specific structure containing any * context information for the implementation * \param[in] dest_key The slot where the generated key material * should be placed * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, psa_key_slot_number_t dest_key); /** \brief A function that performs the final step of a secure element key * agreement and place the generated key material in a buffer * * \param[out] p_output Buffer in which to place the generated key * material * \param[in] output_size The size in bytes of `p_output` * \param[out] p_output_length Upon success, contains the number of bytes of * key material placed in `p_output` * * \retval #PSA_SUCCESS \emptydescription */ typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, uint8_t *p_output, size_t output_size, size_t *p_output_length); /** * \brief A struct containing all of the function pointers needed to for secure * element key derivation and agreement * * PSA Crypto API implementations should populate instances of the table as * appropriate upon startup. * * If one of the functions is not implemented, it should be set to NULL. */ typedef struct { /** The driver-specific size of the key derivation context */ size_t MBEDTLS_PRIVATE(context_size); /** Function that performs a key derivation setup */ psa_drv_se_key_derivation_setup_t MBEDTLS_PRIVATE(p_setup); /** Function that sets key derivation collateral */ psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral); /** Function that performs a final key derivation step */ psa_drv_se_key_derivation_derive_t MBEDTLS_PRIVATE(p_derive); /** Function that performs a final key derivation or agreement and * exports the key */ psa_drv_se_key_derivation_export_t MBEDTLS_PRIVATE(p_export); } psa_drv_se_key_derivation_t; /**@}*/ /** \defgroup se_registration Secure element driver registration */ /**@{*/ /** A structure containing pointers to all the entry points of a * secure element driver. * * Future versions of this specification may add extra substructures at * the end of this structure. */ typedef struct { /** The version of the driver HAL that this driver implements. * This is a protection against loading driver binaries built against * a different version of this specification. * Use #PSA_DRV_SE_HAL_VERSION. */ uint32_t MBEDTLS_PRIVATE(hal_version); /** The size of the driver's persistent data in bytes. * * This can be 0 if the driver does not need persistent data. * * See the documentation of psa_drv_se_context_t::persistent_data * for more information about why and how a driver can use * persistent data. */ size_t MBEDTLS_PRIVATE(persistent_data_size); /** The driver initialization function. * * This function is called once during the initialization of the * PSA Cryptography subsystem, before any other function of the * driver is called. If this function returns a failure status, * the driver will be unusable, at least until the next system reset. * * If this field is \c NULL, it is equivalent to a function that does * nothing and returns #PSA_SUCCESS. */ psa_drv_se_init_t MBEDTLS_PRIVATE(p_init); const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management); const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac); const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher); const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead); const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric); const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation); } psa_drv_se_t; /** The current version of the secure element driver HAL. */ /* 0.0.0 patchlevel 5 */ #define PSA_DRV_SE_HAL_VERSION 0x00000005 /** Register an external cryptoprocessor (secure element) driver. * * This function is only intended to be used by driver code, not by * application code. In implementations with separation between the * PSA cryptography module and applications, this function should * only be available to callers that run in the same memory space as * the cryptography module, and should not be exposed to applications * running in a different memory space. * * This function may be called before psa_crypto_init(). It is * implementation-defined whether this function may be called * after psa_crypto_init(). * * \note Implementations store metadata about keys including the lifetime * value, which contains the driver's location indicator. Therefore, * from one instantiation of the PSA Cryptography * library to the next one, if there is a key in storage with a certain * lifetime value, you must always register the same driver (or an * updated version that communicates with the same secure element) * with the same location value. * * \param location The location value through which this driver will * be exposed to applications. * This driver will be used for all keys such that * `location == #PSA_KEY_LIFETIME_GET_LOCATION( lifetime )`. * The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved * and may not be used for drivers. Implementations * may reserve other values. * \param[in] methods The method table of the driver. This structure must * remain valid for as long as the cryptography * module keeps running. It is typically a global * constant. * * \return #PSA_SUCCESS * The driver was successfully registered. Applications can now * use \p location to access keys through the methods passed to * this function. * \return #PSA_ERROR_BAD_STATE * This function was called after the initialization of the * cryptography module, and this implementation does not support * driver registration at this stage. * \return #PSA_ERROR_ALREADY_EXISTS * There is already a registered driver for this value of \p location. * \return #PSA_ERROR_INVALID_ARGUMENT * \p location is a reserved value. * \return #PSA_ERROR_NOT_SUPPORTED * `methods->hal_version` is not supported by this implementation. * \return #PSA_ERROR_INSUFFICIENT_MEMORY * \return #PSA_ERROR_NOT_PERMITTED * \return #PSA_ERROR_STORAGE_FAILURE * \return #PSA_ERROR_DATA_CORRUPT */ psa_status_t psa_register_se_driver( psa_key_location_t location, const psa_drv_se_t *methods); /**@}*/ #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_SE_DRIVER_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h000066400000000000000000001561701464416617300250160ustar00rootroot00000000000000/** * \file psa/crypto_sizes.h * * \brief PSA cryptography module: Mbed TLS buffer size macros * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file contains the definitions of macros that are useful to * compute buffer sizes. The signatures and semantics of these macros * are standardized, but the definitions are not, because they depend on * the available algorithms and, in some cases, on permitted tolerances * on buffer sizes. * * In implementations with isolation between the application and the * cryptography module, implementers should take care to ensure that * the definitions that are exposed to applications match what the * module implements. * * Macros that compute sizes whose values do not depend on the * implementation are in crypto.h. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SIZES_H #define PSA_CRYPTO_SIZES_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #define PSA_BITS_TO_BYTES(bits) (((bits) + 7u) / 8u) #define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8u) #define PSA_MAX_OF_THREE(a, b, c) ((a) <= (b) ? (b) <= (c) ? \ (c) : (b) : (a) <= (c) ? (c) : (a)) #define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ (((length) + (block_size) - 1) / (block_size) * (block_size)) /** The size of the output of psa_hash_finish(), in bytes. * * This is also the hash size that psa_hash_verify() expects. * * \param alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a * hash algorithm). * * \return The hash size for the specified hash algorithm. * If the hash algorithm is not recognized, return 0. */ #define PSA_HASH_LENGTH(alg) \ ( \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64u : \ 0u) /** The input block size of a hash algorithm, in bytes. * * Hash algorithms process their input data in blocks. Hash operations will * retain any partial blocks until they have enough input to fill the block or * until the operation is finished. * This affects the output from psa_hash_suspend(). * * \param alg A hash algorithm (\c PSA_ALG_XXX value such that * PSA_ALG_IS_HASH(\p alg) is true). * * \return The block size in bytes for the specified hash algorithm. * If the hash algorithm is not recognized, return 0. * An implementation can return either 0 or the correct size for a * hash algorithm that it recognizes, but does not support. */ #define PSA_HASH_BLOCK_LENGTH(alg) \ ( \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104u : \ PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72u : \ 0u) /** \def PSA_HASH_MAX_SIZE * * Maximum size of a hash. * * This macro expands to a compile-time constant integer. This value * is the maximum size of a hash in bytes. */ /* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-224, * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for * HMAC-SHA3-512. */ /* Note: PSA_HASH_MAX_SIZE should be kept in sync with MBEDTLS_MD_MAX_SIZE, * see the note on MBEDTLS_MD_MAX_SIZE for details. */ #if defined(PSA_WANT_ALG_SHA3_224) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 144u #elif defined(PSA_WANT_ALG_SHA3_256) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 136u #elif defined(PSA_WANT_ALG_SHA_512) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u #elif defined(PSA_WANT_ALG_SHA_384) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u #elif defined(PSA_WANT_ALG_SHA3_384) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 104u #elif defined(PSA_WANT_ALG_SHA3_512) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 72u #elif defined(PSA_WANT_ALG_SHA_256) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u #elif defined(PSA_WANT_ALG_SHA_224) #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u #else /* SHA-1 or smaller */ #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u #endif #if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA3_512) #define PSA_HASH_MAX_SIZE 64u #elif defined(PSA_WANT_ALG_SHA_384) || defined(PSA_WANT_ALG_SHA3_384) #define PSA_HASH_MAX_SIZE 48u #elif defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA3_256) #define PSA_HASH_MAX_SIZE 32u #elif defined(PSA_WANT_ALG_SHA_224) || defined(PSA_WANT_ALG_SHA3_224) #define PSA_HASH_MAX_SIZE 28u #else /* SHA-1 or smaller */ #define PSA_HASH_MAX_SIZE 20u #endif /** \def PSA_MAC_MAX_SIZE * * Maximum size of a MAC. * * This macro expands to a compile-time constant integer. This value * is the maximum size of a MAC in bytes. */ /* All non-HMAC MACs have a maximum size that's smaller than the * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ /* Note that the encoding of truncated MAC algorithms limits this value * to 64 bytes. */ #define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE /** The length of a tag for an AEAD algorithm, in bytes. * * This macro can be used to allocate a buffer of sufficient size to store the * tag output from psa_aead_finish(). * * See also #PSA_AEAD_TAG_MAX_SIZE. * * \param key_type The type of the AEAD key. * \param key_bits The size of the AEAD key in bits. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return The tag length for the specified algorithm and key. * If the AEAD algorithm does not have an identified * tag that can be distinguished from the rest of * the ciphertext, return 0. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ ((void) (key_bits), 0u)) /** The maximum tag size for all supported AEAD algorithms, in bytes. * * See also #PSA_AEAD_TAG_LENGTH(\p key_type, \p key_bits, \p alg). */ #define PSA_AEAD_TAG_MAX_SIZE 16u /* The maximum size of an RSA key on this implementation, in bits. * This is a vendor-specific macro. * * Mbed TLS does not set a hard limit on the size of RSA keys: any key * whose parameters fit in a bignum is accepted. However large keys can * induce a large memory usage and long computation times. Unlike other * auxiliary macros in this file and in crypto.h, which reflect how the * library is configured, this macro defines how the library is * configured. This implementation refuses to import or generate an * RSA key whose size is larger than the value defined here. * * Note that an implementation may set different size limits for different * operations, and does not need to accept all key sizes up to the limit. */ #define PSA_VENDOR_RSA_MAX_KEY_BITS 4096u /* The minimum size of an RSA key on this implementation, in bits. * This is a vendor-specific macro. * * Limits RSA key generation to a minimum due to avoid accidental misuse. * This value cannot be less than 128 bits. */ #if defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS) #define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS MBEDTLS_RSA_GEN_KEY_MIN_BITS #else #define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS 1024 #endif /* The maximum size of an DH key on this implementation, in bits. * This is a vendor-specific macro.*/ #if defined(PSA_WANT_DH_RFC7919_8192) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 8192u #elif defined(PSA_WANT_DH_RFC7919_6144) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 6144u #elif defined(PSA_WANT_DH_RFC7919_4096) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 4096u #elif defined(PSA_WANT_DH_RFC7919_3072) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 3072u #elif defined(PSA_WANT_DH_RFC7919_2048) #define PSA_VENDOR_FFDH_MAX_KEY_BITS 2048u #else #define PSA_VENDOR_FFDH_MAX_KEY_BITS 0u #endif /* The maximum size of an ECC key on this implementation, in bits. * This is a vendor-specific macro. */ #if defined(PSA_WANT_ECC_SECP_R1_521) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 521u #elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 512u #elif defined(PSA_WANT_ECC_MONTGOMERY_448) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 448u #elif defined(PSA_WANT_ECC_SECP_R1_384) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u #elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u #elif defined(PSA_WANT_ECC_SECP_R1_256) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u #elif defined(PSA_WANT_ECC_SECP_K1_256) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u #elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u #elif defined(PSA_WANT_ECC_MONTGOMERY_255) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 255u #elif defined(PSA_WANT_ECC_SECP_R1_224) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u #elif defined(PSA_WANT_ECC_SECP_K1_224) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u #elif defined(PSA_WANT_ECC_SECP_R1_192) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u #elif defined(PSA_WANT_ECC_SECP_K1_192) #define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u #else #define PSA_VENDOR_ECC_MAX_CURVE_BITS 0u #endif /** This macro returns the maximum supported length of the PSK for the * TLS-1.2 PSK-to-MS key derivation * (#PSA_ALG_TLS12_PSK_TO_MS(\c hash_alg)). * * The maximum supported length does not depend on the chosen hash algorithm. * * Quoting RFC 4279, Sect 5.3: * TLS implementations supporting these ciphersuites MUST support * arbitrary PSK identities up to 128 octets in length, and arbitrary * PSKs up to 64 octets in length. Supporting longer identities and * keys is RECOMMENDED. * * Therefore, no implementation should define a value smaller than 64 * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE. */ #define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128u /* The expected size of input passed to psa_tls12_ecjpake_to_pms_input, * which is expected to work with P-256 curve only. */ #define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65u /* The size of a serialized K.X coordinate to be used in * psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256 * curve. */ #define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32u /* The maximum number of iterations for PBKDF2 on this implementation, in bits. * This is a vendor-specific macro. This can be configured if necessary */ #define PSA_VENDOR_PBKDF2_MAX_ITERATIONS 0xffffffffU /** The maximum size of a block cipher. */ #define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16u /** The size of the output of psa_mac_sign_finish(), in bytes. * * This is also the MAC size that psa_mac_verify_finish() expects. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type The type of the MAC key. * \param key_bits The size of the MAC key in bits. * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_MAC(\p alg) is true). * * \return The MAC size for the specified algorithm with * the specified key parameters. * \return 0 if the MAC algorithm is not recognized. * \return Either 0 or the correct size for a MAC algorithm that * the implementation recognizes, but does not support. * \return Unspecified if the key parameters are not consistent * with the algorithm. */ #define PSA_MAC_LENGTH(key_type, key_bits, alg) \ ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) : \ PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ ((void) (key_type), (void) (key_bits), 0u)) /** The maximum size of the output of psa_aead_encrypt(), in bytes. * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_aead_encrypt() will not fail due to an * insufficient buffer size. Depending on the algorithm, the actual size of * the ciphertext may be smaller. * * See also #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param plaintext_length Size of the plaintext in bytes. * * \return The AEAD ciphertext size for the specified * algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ 0u) /** A sufficient output buffer size for psa_aead_encrypt(), for any of the * supported key types and AEAD algorithms. * * If the size of the ciphertext buffer is at least this large, it is guaranteed * that psa_aead_encrypt() will not fail due to an insufficient buffer size. * * \note This macro returns a compile-time constant if its arguments are * compile-time constants. * * See also #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, * \p plaintext_length). * * \param plaintext_length Size of the plaintext in bytes. * * \return A sufficient output buffer size for any of the * supported key types and AEAD algorithms. * */ #define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length) \ ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE) /** The maximum size of the output of psa_aead_decrypt(), in bytes. * * If the size of the plaintext buffer is at least this large, it is * guaranteed that psa_aead_decrypt() will not fail due to an * insufficient buffer size. Depending on the algorithm, the actual size of * the plaintext may be smaller. * * See also #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param ciphertext_length Size of the plaintext in bytes. * * \return The AEAD ciphertext size for the specified * algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ? \ (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ 0u) /** A sufficient output buffer size for psa_aead_decrypt(), for any of the * supported key types and AEAD algorithms. * * If the size of the plaintext buffer is at least this large, it is guaranteed * that psa_aead_decrypt() will not fail due to an insufficient buffer size. * * \note This macro returns a compile-time constant if its arguments are * compile-time constants. * * See also #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, * \p ciphertext_length). * * \param ciphertext_length Size of the ciphertext in bytes. * * \return A sufficient output buffer size for any of the * supported key types and AEAD algorithms. * */ #define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length) \ (ciphertext_length) /** The default nonce size for an AEAD algorithm, in bytes. * * This macro can be used to allocate a buffer of sufficient size to * store the nonce output from #psa_aead_generate_nonce(). * * See also #PSA_AEAD_NONCE_MAX_SIZE. * * \note This is not the maximum size of nonce supported as input to * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), * just the default size that is generated by #psa_aead_generate_nonce(). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is compatible with * algorithm \p alg. * * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return The default nonce size for the specified key type and algorithm. * If the key type or AEAD algorithm is not recognized, * or the parameters are incompatible, return 0. */ #define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \ MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13u : \ MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12u : \ 0u : \ (key_type) == PSA_KEY_TYPE_CHACHA20 && \ MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12u : \ 0u) /** The maximum default nonce size among all supported pairs of key types and * AEAD algorithms, in bytes. * * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() * may return. * * \note This is not the maximum size of nonce supported as input to * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), * just the largest size that may be generated by * #psa_aead_generate_nonce(). */ #define PSA_AEAD_NONCE_MAX_SIZE 13u /** A sufficient output buffer size for psa_aead_update(). * * If the size of the output buffer is at least this large, it is * guaranteed that psa_aead_update() will not fail due to an * insufficient buffer size. The actual size of the output may be smaller * in any given call. * * See also #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output buffer size for the specified * algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ /* For all the AEAD modes defined in this specification, it is possible * to emit output without delay. However, hardware may not always be * capable of this. So for modes based on a block cipher, allow the * implementation to delay the output until it has a full block. */ #define PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \ (input_length) : \ 0u) /** A sufficient output buffer size for psa_aead_update(), for any of the * supported key types and AEAD algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_aead_update() will not fail due to an insufficient buffer size. * * See also #PSA_AEAD_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. */ #define PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length) \ (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length))) /** A sufficient ciphertext buffer size for psa_aead_finish(). * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_aead_finish() will not fail due to an * insufficient ciphertext buffer size. The actual size of the output may * be smaller in any given call. * * See also #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE. * * \param key_type A symmetric key type that is compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return A sufficient ciphertext buffer size for the * specified algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ 0u) /** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the * supported key types and AEAD algorithms. * * See also #PSA_AEAD_FINISH_OUTPUT_SIZE(\p key_type, \p alg). */ #define PSA_AEAD_FINISH_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) /** A sufficient plaintext buffer size for psa_aead_verify(). * * If the size of the plaintext buffer is at least this large, it is * guaranteed that psa_aead_verify() will not fail due to an * insufficient plaintext buffer size. The actual size of the output may * be smaller in any given call. * * See also #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE. * * \param key_type A symmetric key type that is * compatible with algorithm \p alg. * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \return A sufficient plaintext buffer size for the * specified algorithm. * If the key type or AEAD algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg) \ (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ 0u) /** A sufficient plaintext buffer size for psa_aead_verify(), for any of the * supported key types and AEAD algorithms. * * See also #PSA_AEAD_VERIFY_OUTPUT_SIZE(\p key_type, \p alg). */ #define PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) #define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ (PSA_ALG_IS_RSA_OAEP(alg) ? \ 2u * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1u : \ 11u /*PKCS#1v1.5*/) /** * \brief ECDSA signature size for a given curve bit size * * \param curve_bits Curve size in bits. * \return Signature size in bytes. * * \note This macro returns a compile-time constant if its argument is one. */ #define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ (PSA_BITS_TO_BYTES(curve_bits) * 2u) /** Sufficient signature buffer size for psa_sign_hash(). * * This macro returns a sufficient buffer size for a signature using a key * of the specified type and size, with the specified algorithm. * Note that the actual size of the signature may be smaller * (some algorithms produce a variable-size signature). * * \warning This function may call its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type An asymmetric key type (this may indifferently be a * key pair type or a public key type). * \param key_bits The size of the key in bits. * \param alg The signature algorithm. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_sign_hash() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ ((void) alg, 0u)) #define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /** \def PSA_SIGNATURE_MAX_SIZE * * Maximum size of an asymmetric signature. * * This macro expands to a compile-time constant integer. This value * is the maximum size of a signature in bytes. */ #define PSA_SIGNATURE_MAX_SIZE 1 #if (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \ (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE > PSA_SIGNATURE_MAX_SIZE) #undef PSA_SIGNATURE_MAX_SIZE #define PSA_SIGNATURE_MAX_SIZE PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE #endif #if (defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) || defined(PSA_WANT_ALG_RSA_PSS)) && \ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_SIGNATURE_MAX_SIZE) #undef PSA_SIGNATURE_MAX_SIZE #define PSA_SIGNATURE_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) #endif /** Sufficient output buffer size for psa_asymmetric_encrypt(). * * This macro returns a sufficient buffer size for a ciphertext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the ciphertext may be smaller, depending * on the algorithm. * * \warning This function may call its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type An asymmetric key type (this may indifferently be a * key pair type or a public key type). * \param key_bits The size of the key in bits. * \param alg The asymmetric encryption algorithm. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_asymmetric_encrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \ 0u) /** A sufficient output buffer size for psa_asymmetric_encrypt(), for any * supported asymmetric encryption. * * See also #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). */ /* This macro assumes that RSA is the only supported asymmetric encryption. */ #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE \ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) /** Sufficient output buffer size for psa_asymmetric_decrypt(). * * This macro returns a sufficient buffer size for a plaintext produced using * a key of the specified type and size, with the specified algorithm. * Note that the actual size of the plaintext may be smaller, depending * on the algorithm. * * \warning This function may call its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type An asymmetric key type (this may indifferently be a * key pair type or a public key type). * \param key_bits The size of the key in bits. * \param alg The asymmetric encryption algorithm. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_asymmetric_decrypt() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the * return value is unspecified. */ #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ 0u) /** A sufficient output buffer size for psa_asymmetric_decrypt(), for any * supported asymmetric decryption. * * This macro assumes that RSA is the only supported asymmetric encryption. * * See also #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). */ #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE \ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) /* Maximum size of the ASN.1 encoding of an INTEGER with the specified * number of bits. * * This definition assumes that bits <= 2^19 - 9 so that the length field * is at most 3 bytes. The length of the encoding is the length of the * bit string padded to a whole number of bytes plus: * - 1 type byte; * - 1 to 3 length bytes; * - 0 to 1 bytes of leading 0 due to the sign bit. */ #define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ ((bits) / 8u + 5u) /* Maximum size of the export encoding of an RSA public key. * Assumes that the public exponent is less than 2^32. * * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER } -- e * * - 4 bytes of SEQUENCE overhead; * - n : INTEGER; * - 7 bytes for the public exponent. */ #define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11u) /* Maximum size of the export encoding of an RSA key pair. * Assumes that the public exponent is less than 2^32 and that the size * difference between the two primes is at most 1 bit. * * RSAPrivateKey ::= SEQUENCE { * version Version, -- 0 * modulus INTEGER, -- N-bit * publicExponent INTEGER, -- 32-bit * privateExponent INTEGER, -- N-bit * prime1 INTEGER, -- N/2-bit * prime2 INTEGER, -- N/2-bit * exponent1 INTEGER, -- N/2-bit * exponent2 INTEGER, -- N/2-bit * coefficient INTEGER, -- N/2-bit * } * * - 4 bytes of SEQUENCE overhead; * - 3 bytes of version; * - 7 half-size INTEGERs plus 2 full-size INTEGERs, * overapproximated as 9 half-size INTEGERS; * - 7 bytes for the public exponent. */ #define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ (9u * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2u + 1u) + 14u) /* Maximum size of the export encoding of a DSA public key. * * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } -- contains DSAPublicKey * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters Dss-Params } -- SEQUENCE of 3 INTEGERs * DSAPublicKey ::= INTEGER -- public key, Y * * - 3 * 4 bytes of SEQUENCE overhead; * - 1 + 1 + 7 bytes of algorithm (DSA OID); * - 4 bytes of BIT STRING overhead; * - 3 full-size INTEGERs (p, g, y); * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). */ #define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 59u) /* Maximum size of the export encoding of a DSA key pair. * * DSAPrivateKey ::= SEQUENCE { * version Version, -- 0 * prime INTEGER, -- p * subprime INTEGER, -- q * generator INTEGER, -- g * public INTEGER, -- y * private INTEGER, -- x * } * * - 4 bytes of SEQUENCE overhead; * - 3 bytes of version; * - 3 full-size INTEGERs (p, g, y); * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). */ #define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 75u) /* Maximum size of the export encoding of an ECC public key. * * The representation of an ECC public key is: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; * - where m is the bit size associated with the curve. * * - 1 byte + 2 * point size. */ #define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ (2u * PSA_BITS_TO_BYTES(key_bits) + 1u) /* Maximum size of the export encoding of an ECC key pair. * * An ECC key pair is represented by the secret value. */ #define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) /* Maximum size of the export encoding of an DH key pair. * * An DH key pair is represented by the secret value. */ #define PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) /* Maximum size of the export encoding of an DH public key. */ #define PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(key_bits) \ (PSA_BITS_TO_BYTES(key_bits)) /** Sufficient output buffer size for psa_export_key() or * psa_export_public_key(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * The following code illustrates how to allocate enough memory to export * a key by querying the key type and size at runtime. * \code{c} * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); * psa_key_type_t key_type = psa_get_key_type(&attributes); * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits); * psa_reset_key_attributes(&attributes); * uint8_t *buffer = malloc(buffer_size); * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); * \endcode * * \param key_type A supported key type. * \param key_bits The size of the key in bits. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_export_key() or psa_export_public_key() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not supported, * return either a sensible size or 0. * If the parameters are not valid, the return value is unspecified. */ #define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ 0u) /** Sufficient output buffer size for psa_export_public_key(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * The following code illustrates how to allocate enough memory to export * a public key by querying the key type and size at runtime. * \code{c} * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * psa_status_t status; * status = psa_get_key_attributes(key, &attributes); * if (status != PSA_SUCCESS) handle_error(...); * psa_key_type_t key_type = psa_get_key_type(&attributes); * size_t key_bits = psa_get_key_bits(&attributes); * size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits); * psa_reset_key_attributes(&attributes); * uint8_t *buffer = malloc(buffer_size); * if (buffer == NULL) handle_error(...); * size_t buffer_length; * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); * if (status != PSA_SUCCESS) handle_error(...); * \endcode * * \param key_type A public key or key pair key type. * \param key_bits The size of the key in bits. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_export_public_key() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that is not * supported, return either a sensible size or 0. * If the parameters are not valid, * the return value is unspecified. * * If the parameters are valid and supported, * return the same result as * #PSA_EXPORT_KEY_OUTPUT_SIZE( * \p #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\p key_type), * \p key_bits). */ #define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ 0u) /** Sufficient buffer size for exporting any asymmetric key pair. * * This macro expands to a compile-time constant integer. This value is * a sufficient buffer size when calling psa_export_key() to export any * asymmetric key pair, regardless of the exact key type and key size. * * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). */ #define PSA_EXPORT_KEY_PAIR_MAX_SIZE 1 #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \ (PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ PSA_EXPORT_KEY_PAIR_MAX_SIZE) #undef PSA_EXPORT_KEY_PAIR_MAX_SIZE #define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) && \ (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ PSA_EXPORT_KEY_PAIR_MAX_SIZE) #undef PSA_EXPORT_KEY_PAIR_MAX_SIZE #define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \ (PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \ PSA_EXPORT_KEY_PAIR_MAX_SIZE) #undef PSA_EXPORT_KEY_PAIR_MAX_SIZE #define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif /** Sufficient buffer size for exporting any asymmetric public key. * * This macro expands to a compile-time constant integer. This value is * a sufficient buffer size when calling psa_export_key() or * psa_export_public_key() to export any asymmetric public key, * regardless of the exact key type and key size. * * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). */ #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE 1 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ (PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) #undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) && \ (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) #undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) #endif #if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \ (PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \ PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) #undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif /** Sufficient output buffer size for psa_raw_key_agreement(). * * This macro returns a compile-time constant if its arguments are * compile-time constants. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE. * * \param key_type A supported key type. * \param key_bits The size of the key in bits. * * \return If the parameters are valid and supported, return * a buffer size in bytes that guarantees that * psa_raw_key_agreement() will not fail with * #PSA_ERROR_BUFFER_TOO_SMALL. * If the parameters are a valid combination that * is not supported, return either a sensible size or 0. * If the parameters are not valid, * the return value is unspecified. */ #define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ ((PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || \ PSA_KEY_TYPE_IS_DH_KEY_PAIR(key_type)) ? PSA_BITS_TO_BYTES(key_bits) : 0u) /** Maximum size of the output from psa_raw_key_agreement(). * * This macro expands to a compile-time constant integer. This value is the * maximum size of the output any raw key agreement algorithm, in bytes. * * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits). */ #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE 1 #if defined(PSA_WANT_ALG_ECDH) && \ (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) #undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) #endif #if defined(PSA_WANT_ALG_FFDH) && \ (PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE) #undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif /** The default IV size for a cipher algorithm, in bytes. * * The IV that is generated as part of a call to #psa_cipher_encrypt() is always * the default IV length for the algorithm. * * This macro can be used to allocate a buffer of sufficient size to * store the IV output from #psa_cipher_generate_iv() when using * a multi-part cipher operation. * * See also #PSA_CIPHER_IV_MAX_SIZE. * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is compatible with algorithm \p alg. * * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\p alg) is true). * * \return The default IV size for the specified key type and algorithm. * If the algorithm does not use an IV, return 0. * If the key type or cipher algorithm is not recognized, * or the parameters are incompatible, return 0. */ #define PSA_CIPHER_IV_LENGTH(key_type, alg) \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1 && \ ((alg) == PSA_ALG_CTR || \ (alg) == PSA_ALG_CFB || \ (alg) == PSA_ALG_OFB || \ (alg) == PSA_ALG_XTS || \ (alg) == PSA_ALG_CBC_NO_PADDING || \ (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ (key_type) == PSA_KEY_TYPE_CHACHA20 && \ (alg) == PSA_ALG_STREAM_CIPHER ? 12u : \ (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13u : \ 0u) /** The maximum IV size for all supported cipher algorithms, in bytes. * * See also #PSA_CIPHER_IV_LENGTH(). */ #define PSA_CIPHER_IV_MAX_SIZE 16u /** The maximum size of the output of psa_cipher_encrypt(), in bytes. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. * Depending on the algorithm, the actual size of the output might be smaller. * * See also #PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(\p input_length). * * \warning This macro may evaluate its arguments multiple times or * zero times, so you should not pass arguments that contain * side effects. * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ (alg == PSA_ALG_CBC_PKCS7 ? \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ (input_length) + 1u) + \ PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0u) : \ (PSA_ALG_IS_CIPHER(alg) ? \ (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : \ 0u)) /** A sufficient output buffer size for psa_cipher_encrypt(), for any of the * supported key types and cipher algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. * * See also #PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. * */ #define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length) \ (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ (input_length) + 1u) + \ PSA_CIPHER_IV_MAX_SIZE) /** The maximum size of the output of psa_cipher_decrypt(), in bytes. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. * Depending on the algorithm, the actual size of the output might be smaller. * * See also #PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(\p input_length). * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, * return 0. */ #define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ (PSA_ALG_IS_CIPHER(alg) && \ ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ (input_length) : \ 0u) /** A sufficient output buffer size for psa_cipher_decrypt(), for any of the * supported key types and cipher algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. * * See also #PSA_CIPHER_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. */ #define PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length) \ (input_length) /** A sufficient output buffer size for psa_cipher_update(). * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_update() will not fail due to an insufficient buffer size. * The actual size of the output might be smaller in any given call. * * See also #PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(\p input_length). * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param input_length Size of the input in bytes. * * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, return 0. */ #define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ (PSA_ALG_IS_CIPHER(alg) ? \ (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ (((alg) == PSA_ALG_CBC_PKCS7 || \ (alg) == PSA_ALG_CBC_NO_PADDING || \ (alg) == PSA_ALG_ECB_NO_PADDING) ? \ PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ input_length) : \ (input_length)) : 0u) : \ 0u) /** A sufficient output buffer size for psa_cipher_update(), for any of the * supported key types and cipher algorithms. * * If the size of the output buffer is at least this large, it is guaranteed * that psa_cipher_update() will not fail due to an insufficient buffer size. * * See also #PSA_CIPHER_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). * * \param input_length Size of the input in bytes. */ #define PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length) \ (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, input_length)) /** A sufficient ciphertext buffer size for psa_cipher_finish(). * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_cipher_finish() will not fail due to an insufficient * ciphertext buffer size. The actual size of the output might be smaller in * any given call. * * See also #PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE(). * * \param key_type A symmetric key type that is compatible with algorithm * alg. * \param alg A cipher algorithm (PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \return A sufficient output size for the specified key type and * algorithm. If the key type or cipher algorithm is not * recognized, or the parameters are incompatible, return 0. */ #define PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg) \ (PSA_ALG_IS_CIPHER(alg) ? \ (alg == PSA_ALG_CBC_PKCS7 ? \ PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ 0u) : \ 0u) /** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the * supported key types and cipher algorithms. * * See also #PSA_CIPHER_FINISH_OUTPUT_SIZE(\p key_type, \p alg). */ #define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) #endif /* PSA_CRYPTO_SIZES_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h000066400000000000000000000427731464416617300252100ustar00rootroot00000000000000/** * \file psa/crypto_struct.h * * \brief PSA cryptography module: Mbed TLS structured type implementations * * \note This file may not be included directly. Applications must * include psa/crypto.h. * * This file contains the definitions of some data structures with * implementation-specific definitions. * * In implementations with isolation between the application and the * cryptography module, it is expected that the front-end and the back-end * would have different versions of this file. * *

Design notes about multipart operation structures

* * For multipart operations without driver delegation support, each multipart * operation structure contains a `psa_algorithm_t alg` field which indicates * which specific algorithm the structure is for. When the structure is not in * use, `alg` is 0. Most of the structure consists of a union which is * discriminated by `alg`. * * For multipart operations with driver delegation support, each multipart * operation structure contains an `unsigned int id` field indicating which * driver got assigned to do the operation. When the structure is not in use, * 'id' is 0. The structure contains also a driver context which is the union * of the contexts of all drivers able to handle the type of multipart * operation. * * Note that when `alg` or `id` is 0, the content of other fields is undefined. * In particular, it is not guaranteed that a freshly-initialized structure * is all-zero: we initialize structures to something like `{0, 0}`, which * is only guaranteed to initializes the first member of the union; * GCC and Clang initialize the whole structure to 0 (at the time of writing), * but MSVC and CompCert don't. * * In Mbed TLS, multipart operation structures live independently from * the key. This allows Mbed TLS to free the key objects when destroying * a key slot. If a multipart operation needs to remember the key after * the setup function returns, the operation structure needs to contain a * copy of the key. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_STRUCT_H #define PSA_CRYPTO_STRUCT_H #include "mbedtls/private_access.h" #ifdef __cplusplus extern "C" { #endif /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" /* Include the context definition for the compiled-in drivers for the primitive * algorithms. */ #include "psa/crypto_driver_contexts_primitives.h" struct psa_hash_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_driver_wrappers.h. * ID value zero means the context is not valid or not assigned to * any driver (i.e. the driver context is not active, in use). */ unsigned int MBEDTLS_PRIVATE(id); psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_HASH_OPERATION_INIT { 0 } #else #define PSA_HASH_OPERATION_INIT { 0, { 0 } } #endif static inline struct psa_hash_operation_s psa_hash_operation_init(void) { const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; return v; } struct psa_cipher_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); unsigned int MBEDTLS_PRIVATE(iv_required) : 1; unsigned int MBEDTLS_PRIVATE(iv_set) : 1; uint8_t MBEDTLS_PRIVATE(default_iv_length); psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_CIPHER_OPERATION_INIT { 0 } #else #define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } } #endif static inline struct psa_cipher_operation_s psa_cipher_operation_init(void) { const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; return v; } /* Include the context definition for the compiled-in drivers for the composite * algorithms. */ #include "psa/crypto_driver_contexts_composites.h" struct psa_mac_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); uint8_t MBEDTLS_PRIVATE(mac_size); unsigned int MBEDTLS_PRIVATE(is_sign) : 1; psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_MAC_OPERATION_INIT { 0 } #else #define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } } #endif static inline struct psa_mac_operation_s psa_mac_operation_init(void) { const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; return v; } struct psa_aead_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); psa_algorithm_t MBEDTLS_PRIVATE(alg); psa_key_type_t MBEDTLS_PRIVATE(key_type); size_t MBEDTLS_PRIVATE(ad_remaining); size_t MBEDTLS_PRIVATE(body_remaining); unsigned int MBEDTLS_PRIVATE(nonce_set) : 1; unsigned int MBEDTLS_PRIVATE(lengths_set) : 1; unsigned int MBEDTLS_PRIVATE(ad_started) : 1; unsigned int MBEDTLS_PRIVATE(body_started) : 1; unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_AEAD_OPERATION_INIT { 0 } #else #define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } } #endif static inline struct psa_aead_operation_s psa_aead_operation_init(void) { const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; return v; } /* Include the context definition for the compiled-in drivers for the key * derivation algorithms. */ #include "psa/crypto_driver_contexts_key_derivation.h" struct psa_key_derivation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else psa_algorithm_t MBEDTLS_PRIVATE(alg); unsigned int MBEDTLS_PRIVATE(can_output_key) : 1; size_t MBEDTLS_PRIVATE(capacity); psa_driver_key_derivation_context_t MBEDTLS_PRIVATE(ctx); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_KEY_DERIVATION_OPERATION_INIT { 0 } #else /* This only zeroes out the first byte in the union, the rest is unspecified. */ #define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } #endif static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void) { const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; return v; } struct psa_key_production_parameters_s { /* Future versions may add other fields in this structure. */ uint32_t flags; uint8_t data[]; }; /** The default production parameters for key generation or key derivation. * * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext() * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and * `params_data_length == 0` is equivalent to * calling psa_generate_key() or psa_key_derivation_output_key() * respectively. */ #define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 } struct psa_key_policy_s { psa_key_usage_t MBEDTLS_PRIVATE(usage); psa_algorithm_t MBEDTLS_PRIVATE(alg); psa_algorithm_t MBEDTLS_PRIVATE(alg2); }; typedef struct psa_key_policy_s psa_key_policy_t; #define PSA_KEY_POLICY_INIT { 0, 0, 0 } static inline struct psa_key_policy_s psa_key_policy_init(void) { const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; return v; } /* The type used internally for key sizes. * Public interfaces use size_t, but internally we use a smaller type. */ typedef uint16_t psa_key_bits_t; /* The maximum value of the type used to represent bit-sizes. * This is used to mark an invalid key size. */ #define PSA_KEY_BITS_TOO_LARGE ((psa_key_bits_t) -1) /* The maximum size of a key in bits. * Currently defined as the maximum that can be represented, rounded down * to a whole number of bytes. * This is an uncast value so that it can be used in preprocessor * conditionals. */ #define PSA_MAX_KEY_BITS 0xfff8 struct psa_key_attributes_s { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number); int MBEDTLS_PRIVATE(has_slot_number); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_key_type_t MBEDTLS_PRIVATE(type); psa_key_bits_t MBEDTLS_PRIVATE(bits); psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime); psa_key_policy_t MBEDTLS_PRIVATE(policy); /* This type has a different layout in the client view wrt the * service view of the key id, i.e. in service view usually is * expected to have MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined * thus adding an owner field to the standard psa_key_id_t. For * implementations with client/service separation, this means the * object will be marshalled through a transport channel and * interpreted differently at each side of the transport. Placing * it at the end of structures allows to interpret the structure * at the client without reorganizing the memory layout of the * struct */ mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id); }; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER 0, 0, #else #define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER #endif #define PSA_KEY_ATTRIBUTES_INIT { PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER \ PSA_KEY_TYPE_NONE, 0, \ PSA_KEY_LIFETIME_VOLATILE, \ PSA_KEY_POLICY_INIT, \ MBEDTLS_SVC_KEY_ID_INIT } static inline struct psa_key_attributes_s psa_key_attributes_init(void) { const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; return v; } static inline void psa_set_key_id(psa_key_attributes_t *attributes, mbedtls_svc_key_id_t key) { psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(lifetime); attributes->MBEDTLS_PRIVATE(id) = key; if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { attributes->MBEDTLS_PRIVATE(lifetime) = PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_LIFETIME_PERSISTENT, PSA_KEY_LIFETIME_GET_LOCATION(lifetime)); } } static inline mbedtls_svc_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(id); } #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER static inline void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes, mbedtls_key_owner_id_t owner) { attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner; } #endif static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime) { attributes->MBEDTLS_PRIVATE(lifetime) = lifetime; if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0; #else attributes->MBEDTLS_PRIVATE(id) = 0; #endif } } static inline psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(lifetime); } static inline void psa_extend_key_usage_flags(psa_key_usage_t *usage_flags) { if (*usage_flags & PSA_KEY_USAGE_SIGN_HASH) { *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE; } if (*usage_flags & PSA_KEY_USAGE_VERIFY_HASH) { *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE; } } static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags) { psa_extend_key_usage_flags(&usage_flags); attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags; } static inline psa_key_usage_t psa_get_key_usage_flags( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage); } static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg) { attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg; } static inline psa_algorithm_t psa_get_key_algorithm( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg); } static inline void psa_set_key_type(psa_key_attributes_t *attributes, psa_key_type_t type) { attributes->MBEDTLS_PRIVATE(type) = type; } static inline psa_key_type_t psa_get_key_type( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(type); } static inline void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits) { if (bits > PSA_MAX_KEY_BITS) { attributes->MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE; } else { attributes->MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits; } } static inline size_t psa_get_key_bits( const psa_key_attributes_t *attributes) { return attributes->MBEDTLS_PRIVATE(bits); } /** * \brief The context for PSA interruptible hash signing. */ struct psa_sign_hash_interruptible_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); psa_driver_sign_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; uint32_t MBEDTLS_PRIVATE(num_ops); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #else #define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } #endif static inline struct psa_sign_hash_interruptible_operation_s psa_sign_hash_interruptible_operation_init(void) { const struct psa_sign_hash_interruptible_operation_s v = PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT; return v; } /** * \brief The context for PSA interruptible hash verification. */ struct psa_verify_hash_interruptible_operation_s { #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_psa_client_handle_t handle; #else /** Unique ID indicating which driver got assigned to do the * operation. Since driver contexts are driver-specific, swapping * drivers halfway through the operation is not supported. * ID values are auto-generated in psa_crypto_driver_wrappers.h * ID value zero means the context is not valid or not assigned to * any driver (i.e. none of the driver contexts are active). */ unsigned int MBEDTLS_PRIVATE(id); psa_driver_verify_hash_interruptible_context_t MBEDTLS_PRIVATE(ctx); unsigned int MBEDTLS_PRIVATE(error_occurred) : 1; uint32_t MBEDTLS_PRIVATE(num_ops); #endif }; #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C) #define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 } #else #define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 } #endif static inline struct psa_verify_hash_interruptible_operation_s psa_verify_hash_interruptible_operation_init(void) { const struct psa_verify_hash_interruptible_operation_s v = PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT; return v; } #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_STRUCT_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_types.h000066400000000000000000000454441464416617300250260ustar00rootroot00000000000000/** * \file psa/crypto_types.h * * \brief PSA cryptography module: type aliases. * * \note This file may not be included directly. Applications must * include psa/crypto.h. Drivers must include the appropriate driver * header file. * * This file contains portable definitions of integral types for properties * of cryptographic keys, designations of cryptographic algorithms, and * error codes returned by the library. * * This header file does not declare any function. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_TYPES_H #define PSA_CRYPTO_TYPES_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" /* Define the MBEDTLS_PRIVATE macro. */ #include "mbedtls/private_access.h" #if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE) #include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE #else #include "crypto_platform.h" #endif #include /** \defgroup error Error codes * @{ */ /** * \brief Function return status. * * This is either #PSA_SUCCESS (which is zero), indicating success, * or a small negative value indicating that an error occurred. Errors are * encoded as one of the \c PSA_ERROR_xxx values defined here. */ /* If #PSA_SUCCESS is already defined, it means that #psa_status_t * is also defined in an external header, so prevent its multiple * definition. */ #ifndef PSA_SUCCESS typedef int32_t psa_status_t; #endif /**@}*/ /** \defgroup crypto_types Key and algorithm types * @{ */ /** \brief Encoding of a key type. * * Values of this type are generally constructed by macros called * `PSA_KEY_TYPE_xxx`. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint16_t psa_key_type_t; /** The type of PSA elliptic curve family identifiers. * * Values of this type are generally constructed by macros called * `PSA_ECC_FAMILY_xxx`. * * The curve identifier is required to create an ECC key using the * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() * macros. * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional families must use an encoding in this range. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint8_t psa_ecc_family_t; /** The type of PSA Diffie-Hellman group family identifiers. * * Values of this type are generally constructed by macros called * `PSA_DH_FAMILY_xxx`. * * The group identifier is required to create a Diffie-Hellman key using the * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() * macros. * * Values defined by this standard will never be in the range 0x80-0xff. * Vendors who define additional families must use an encoding in this range. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint8_t psa_dh_family_t; /** \brief Encoding of a cryptographic algorithm. * * Values of this type are generally constructed by macros called * `PSA_ALG_xxx`. * * For algorithms that can be applied to multiple key types, this type * does not encode the key type. For example, for symmetric ciphers * based on a block cipher, #psa_algorithm_t encodes the block cipher * mode and the padding mode while the block cipher itself is encoded * via #psa_key_type_t. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_algorithm_t; /**@}*/ /** \defgroup key_lifetimes Key lifetimes * @{ */ /** Encoding of key lifetimes. * * The lifetime of a key indicates where it is stored and what system actions * may create and destroy it. * * Lifetime values have the following structure: * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\c lifetime)): * persistence level. This value indicates what device management * actions can cause it to be destroyed. In particular, it indicates * whether the key is _volatile_ or _persistent_. * See ::psa_key_persistence_t for more information. * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)): * location indicator. This value indicates which part of the system * has access to the key material and can perform operations using the key. * See ::psa_key_location_t for more information. * * Volatile keys are automatically destroyed when the application instance * terminates or on a power reset of the device. Persistent keys are * preserved until the application explicitly destroys them or until an * integration-specific device management event occurs (for example, * a factory reset). * * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t. * This identifier remains valid throughout the lifetime of the key, * even if the application instance that created the key terminates. * The application can call psa_open_key() to open a persistent key that * it created previously. * * The default lifetime of a key is #PSA_KEY_LIFETIME_VOLATILE. The lifetime * #PSA_KEY_LIFETIME_PERSISTENT is supported if persistent storage is * available. Other lifetime values may be supported depending on the * library configuration. * * Values of this type are generally constructed by macros called * `PSA_KEY_LIFETIME_xxx`. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_key_lifetime_t; /** Encoding of key persistence levels. * * What distinguishes different persistence levels is what device management * events may cause keys to be destroyed. _Volatile_ keys are destroyed * by a power reset. Persistent keys may be destroyed by events such as * a transfer of ownership or a factory reset. What management events * actually affect persistent keys at different levels is outside the * scope of the PSA Cryptography specification. * * The PSA Cryptography specification defines the following values of * persistence levels: * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key. * A volatile key is automatically destroyed by the implementation when * the application instance terminates. In particular, a volatile key * is automatically destroyed on a power reset of the device. * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT: * persistent key with a default lifetime. * - \c 2-254: currently not supported by Mbed TLS. * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY: * read-only or write-once key. * A key with this persistence level cannot be destroyed. * Mbed TLS does not currently offer a way to create such keys, but * integrations of Mbed TLS can use it for built-in keys that the * application cannot modify (for example, a hardware unique key (HUK)). * * \note Key persistence levels are 8-bit values. Key management * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which * encode the persistence as the lower 8 bits of a 32-bit value. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint8_t psa_key_persistence_t; /** Encoding of key location indicators. * * If an integration of Mbed TLS can make calls to external * cryptoprocessors such as secure elements, the location of a key * indicates which secure element performs the operations on the key. * Depending on the design of the secure element, the key * material may be stored either in the secure element, or * in wrapped (encrypted) form alongside the key metadata in the * primary local storage. * * The PSA Cryptography API specification defines the following values of * location indicators: * - \c 0: primary local storage. * This location is always available. * The primary local storage is typically the same storage area that * contains the key metadata. * - \c 1: primary secure element. * Integrations of Mbed TLS should support this value if there is a secure * element attached to the operating environment. * As a guideline, secure elements may provide higher resistance against * side channel and physical attacks than the primary local storage, but may * have restrictions on supported key types, sizes, policies and operations * and may have different performance characteristics. * - \c 2-0x7fffff: other locations defined by a PSA specification. * The PSA Cryptography API does not currently assign any meaning to these * locations, but future versions of that specification or other PSA * specifications may do so. * - \c 0x800000-0xffffff: vendor-defined locations. * No PSA specification will assign a meaning to locations in this range. * * \note Key location indicators are 24-bit values. Key management * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which * encode the location as the upper 24 bits of a 32-bit value. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_key_location_t; /** Encoding of identifiers of persistent keys. * * - Applications may freely choose key identifiers in the range * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. * - The implementation may define additional key identifiers in the range * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. * - 0 is reserved as an invalid key identifier. * - Key identifiers outside these ranges are reserved for future use. * * \note Values of this type are encoded in the persistent key store. * Any changes to how values are allocated must require careful * consideration to allow backward compatibility. */ typedef uint32_t psa_key_id_t; /** Encoding of key identifiers as seen inside the PSA Crypto implementation. * * When PSA Crypto is built as a library inside an application, this type * is identical to #psa_key_id_t. When PSA Crypto is built as a service * that can store keys on behalf of multiple clients, this type * encodes the #psa_key_id_t value seen by each client application as * well as extra information that identifies the client that owns * the key. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) typedef psa_key_id_t mbedtls_svc_key_id_t; #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /* Implementation-specific: The Mbed TLS library can be built as * part of a multi-client service that exposes the PSA Cryptography API in each * client and encodes the client identity in the key identifier argument of * functions such as psa_open_key(). */ typedef struct { psa_key_id_t MBEDTLS_PRIVATE(key_id); mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner); } mbedtls_svc_key_id_t; #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /**@}*/ /** \defgroup policy Key policies * @{ */ /** \brief Encoding of permitted usage on a key. * * Values of this type are generally constructed as bitwise-ors of macros * called `PSA_KEY_USAGE_xxx`. * * \note Values of this type are encoded in the persistent key store. * Any changes to existing values will require bumping the storage * format version and providing a translation when reading the old * format. */ typedef uint32_t psa_key_usage_t; /**@}*/ /** \defgroup attributes Key attributes * @{ */ /** The type of a structure containing key attributes. * * This is an opaque structure that can represent the metadata of a key * object. Metadata that can be stored in attributes includes: * - The location of the key in storage, indicated by its key identifier * and its lifetime. * - The key's policy, comprising usage flags and a specification of * the permitted algorithm(s). * - Information about the key itself: the key type and its size. * - Additional implementation-defined attributes. * * The actual key material is not considered an attribute of a key. * Key attributes do not contain information that is generally considered * highly confidential. * * An attribute structure works like a simple data structure where each function * `psa_set_key_xxx` sets a field and the corresponding function * `psa_get_key_xxx` retrieves the value of the corresponding field. * However, a future version of the library may report values that are * equivalent to the original one, but have a different encoding. Invalid * values may be mapped to different, also invalid values. * * An attribute structure may contain references to auxiliary resources, * for example pointers to allocated memory or indirect references to * pre-calculated values. In order to free such resources, the application * must call psa_reset_key_attributes(). As an exception, calling * psa_reset_key_attributes() on an attribute structure is optional if * the structure has only been modified by the following functions * since it was initialized or last reset with psa_reset_key_attributes(): * - psa_set_key_id() * - psa_set_key_lifetime() * - psa_set_key_type() * - psa_set_key_bits() * - psa_set_key_usage_flags() * - psa_set_key_algorithm() * * Before calling any function on a key attribute structure, the application * must initialize it by any of the following means: * - Set the structure to all-bits-zero, for example: * \code * psa_key_attributes_t attributes; * memset(&attributes, 0, sizeof(attributes)); * \endcode * - Initialize the structure to logical zero values, for example: * \code * psa_key_attributes_t attributes = {0}; * \endcode * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, * for example: * \code * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; * \endcode * - Assign the result of the function psa_key_attributes_init() * to the structure, for example: * \code * psa_key_attributes_t attributes; * attributes = psa_key_attributes_init(); * \endcode * * A freshly initialized attribute structure contains the following * values: * * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. * - key identifier: 0 (which is not a valid key identifier). * - type: \c 0 (meaning that the type is unspecified). * - key size: \c 0 (meaning that the size is unspecified). * - usage flags: \c 0 (which allows no usage except exporting a public key). * - algorithm: \c 0 (which allows no cryptographic usage, but allows * exporting). * * A typical sequence to create a key is as follows: * -# Create and initialize an attribute structure. * -# If the key is persistent, call psa_set_key_id(). * Also call psa_set_key_lifetime() to place the key in a non-default * location. * -# Set the key policy with psa_set_key_usage_flags() and * psa_set_key_algorithm(). * -# Set the key type with psa_set_key_type(). * Skip this step if copying an existing key with psa_copy_key(). * -# When generating a random key with psa_generate_key() or deriving a key * with psa_key_derivation_output_key(), set the desired key size with * psa_set_key_bits(). * -# Call a key creation function: psa_import_key(), psa_generate_key(), * psa_key_derivation_output_key() or psa_copy_key(). This function reads * the attribute structure, creates a key with these attributes, and * outputs a key identifier to the newly created key. * -# The attribute structure is now no longer necessary. * You may call psa_reset_key_attributes(), although this is optional * with the workflow presented here because the attributes currently * defined in this specification do not require any additional resources * beyond the structure itself. * * A typical sequence to query a key's attributes is as follows: * -# Call psa_get_key_attributes(). * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that * you are interested in. * -# Call psa_reset_key_attributes() to free any resources that may be * used by the attribute structure. * * Once a key has been created, it is impossible to change its attributes. */ typedef struct psa_key_attributes_s psa_key_attributes_t; #ifndef __DOXYGEN_ONLY__ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Mbed TLS defines this type in crypto_types.h because it is also * visible to applications through an implementation-specific extension. * For the PSA Cryptography specification, this type is only visible * via crypto_se_driver.h. */ typedef uint64_t psa_key_slot_number_t; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #endif /* !__DOXYGEN_ONLY__ */ /**@}*/ /** \defgroup derivation Key derivation * @{ */ /** \brief Encoding of the step of a key derivation. * * Values of this type are generally constructed by macros called * `PSA_KEY_DERIVATION_INPUT_xxx`. */ typedef uint16_t psa_key_derivation_step_t; /** \brief Custom parameters for key generation or key derivation. * * This is a structure type with at least the following fields: * * - \c flags: an unsigned integer type. 0 for the default production parameters. * - \c data: a flexible array of bytes. * * The interpretation of this structure depend on the type of the * created key. * * - #PSA_KEY_TYPE_RSA_KEY_PAIR: * - \c flags: must be 0. * - \c data: the public exponent, in little-endian order. * This must be an odd integer and must not be 1. * Implementations must support 65537, should support 3 and may * support other values. * When not using a driver, Mbed TLS supports values up to \c INT_MAX. * If this is empty or if the custom production parameters are omitted * altogether, the default value 65537 is used. * - Other key types: reserved for future use. \c flags must be 0. * */ typedef struct psa_key_production_parameters_s psa_key_production_parameters_t; /**@}*/ #endif /* PSA_CRYPTO_TYPES_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/include/psa/crypto_values.h000066400000000000000000003573401464416617300251620ustar00rootroot00000000000000/** * \file psa/crypto_values.h * * \brief PSA cryptography module: macros to build and analyze integer values. * * \note This file may not be included directly. Applications must * include psa/crypto.h. Drivers must include the appropriate driver * header file. * * This file contains portable definitions of macros to build and analyze * values of integral types that encode properties of cryptographic keys, * designations of cryptographic algorithms, and error codes returned by * the library. * * Note that many of the constants defined in this file are embedded in * the persistent key store, as part of key metadata (including usage * policies). As a consequence, they must not be changed (unless the storage * format version changes). * * This header file only defines preprocessor macros. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_VALUES_H #define PSA_CRYPTO_VALUES_H #include "mbedtls/private_access.h" /** \defgroup error Error codes * @{ */ /* PSA error codes */ /* Error codes are standardized across PSA domains (framework, crypto, storage, * etc.). Do not change the values in this section or even the expansions * of each macro: it must be possible to `#include` both this header * and some other PSA component's headers in the same C source, * which will lead to duplicate definitions of the `PSA_SUCCESS` and * `PSA_ERROR_xxx` macros, which is ok if and only if the macros expand * to the same sequence of tokens. * * If you must add a new * value, check with the Arm PSA framework group to pick one that other * domains aren't already using. */ /* Tell uncrustify not to touch the constant definitions, otherwise * it might change the spacing to something that is not PSA-compliant * (e.g. adding a space after casts). * * *INDENT-OFF* */ /** The action was completed successfully. */ #define PSA_SUCCESS ((psa_status_t)0) /** An error occurred that does not correspond to any defined * failure cause. * * Implementations may use this error code if none of the other standard * error codes are applicable. */ #define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) /** The requested operation or a parameter is not supported * by this implementation. * * Implementations should return this error code when an enumeration * parameter such as a key type, algorithm, etc. is not recognized. * If a combination of parameters is recognized and identified as * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ #define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) /** The requested action is denied by a policy. * * Implementations should return this error code when the parameters * are recognized as valid and supported, and a policy explicitly * denies the requested operation. * * If a subset of the parameters of a function call identify a * forbidden operation, and another subset of the parameters are * not valid or not supported, it is unspecified whether the function * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or * #PSA_ERROR_INVALID_ARGUMENT. */ #define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) /** An output buffer is too small. * * Applications can call the \c PSA_xxx_SIZE macro listed in the function * description to determine a sufficient buffer size. * * Implementations should preferably return this error code only * in cases when performing the operation with a larger output * buffer would succeed. However implementations may return this * error if a function has invalid or unsupported parameters in addition * to the parameters that determine the necessary output buffer size. */ #define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) /** Asking for an item that already exists * * Implementations should return this error, when attempting * to write an item (like a key) that already exists. */ #define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) /** Asking for an item that doesn't exist * * Implementations should return this error, if a requested item (like * a key) does not exist. */ #define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) /** The requested action cannot be performed in the current state. * * Multipart operations return this error when one of the * functions is called out of sequence. Refer to the function * descriptions for permitted sequencing of functions. * * Implementations shall not return this error code to indicate * that a key either exists or not, * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST * as applicable. * * Implementations shall not return this error code to indicate that a * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE * instead. */ #define PSA_ERROR_BAD_STATE ((psa_status_t)-137) /** The parameters passed to the function are invalid. * * Implementations may return this error any time a parameter or * combination of parameters are recognized as invalid. * * Implementations shall not return this error code to indicate that a * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE * instead. */ #define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) /** There is not enough runtime memory. * * If the action is carried out across multiple security realms, this * error can refer to available memory in any of the security realms. */ #define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) /** There is not enough persistent storage. * * Functions that modify the key storage return this error code if * there is insufficient storage space on the host media. In addition, * many functions that do not otherwise access storage may return this * error code if the implementation requires a mandatory log entry for * the requested action and the log storage space is full. */ #define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) /** There was a communication failure inside the implementation. * * This can indicate a communication failure between the application * and an external cryptoprocessor or between the cryptoprocessor and * an external volatile or persistent memory. A communication failure * may be transient or permanent depending on the cause. * * \warning If a function returns this error, it is undetermined * whether the requested action has completed or not. Implementations * should return #PSA_SUCCESS on successful completion whenever * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE * if the requested action was completed successfully in an external * cryptoprocessor but there was a breakdown of communication before * the cryptoprocessor could report the status to the application. */ #define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) /** There was a storage failure that may have led to data loss. * * This error indicates that some persistent storage is corrupted. * It should not be used for a corruption of volatile memory * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error * between the cryptoprocessor and its external storage (use * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). * * Note that a storage failure does not indicate that any data that was * previously read is invalid. However this previously read data may no * longer be readable from storage. * * When a storage failure occurs, it is no longer possible to ensure * the global integrity of the keystore. Depending on the global * integrity guarantees offered by the implementation, access to other * data may or may not fail even if the data is still readable but * its integrity cannot be guaranteed. * * Implementations should only use this error code to report a * permanent storage corruption. However application writers should * keep in mind that transient errors while reading the storage may be * reported using this error code. */ #define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) /** A hardware failure was detected. * * A hardware failure may be transient or permanent depending on the * cause. */ #define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) /** A tampering attempt was detected. * * If an application receives this error code, there is no guarantee * that previously accessed or computed data was correct and remains * confidential. Applications should not perform any security function * and should enter a safe failure state. * * Implementations may return this error code if they detect an invalid * state that cannot happen during normal operation and that indicates * that the implementation's security guarantees no longer hold. Depending * on the implementation architecture and on its security and safety goals, * the implementation may forcibly terminate the application. * * This error code is intended as a last resort when a security breach * is detected and it is unsure whether the keystore data is still * protected. Implementations shall only return this error code * to report an alarm from a tampering detector, to indicate that * the confidentiality of stored data can no longer be guaranteed, * or to indicate that the integrity of previously returned data is now * considered compromised. Implementations shall not use this error code * to indicate a hardware failure that merely makes it impossible to * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code * instead). * * This error indicates an attack against the application. Implementations * shall not return this error code as a consequence of the behavior of * the application itself. */ #define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) /** There is not enough entropy to generate random data needed * for the requested action. * * This error indicates a failure of a hardware random generator. * Application writers should note that this error can be returned not * only by functions whose purpose is to generate random data, such * as key, IV or nonce generation, but also by functions that execute * an algorithm with a randomized result, as well as functions that * use randomization of intermediate computations as a countermeasure * to certain attacks. * * Implementations should avoid returning this error after psa_crypto_init() * has succeeded. Implementations should generate sufficient * entropy during initialization and subsequently use a cryptographically * secure pseudorandom generator (PRNG). However implementations may return * this error at any time if a policy requires the PRNG to be reseeded * during normal operation. */ #define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) /** The signature, MAC or hash is incorrect. * * Verification functions return this error if the verification * calculations completed successfully, and the value to be verified * was determined to be incorrect. * * If the value to verify has an invalid size, implementations may return * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ #define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) /** The decrypted padding is incorrect. * * \warning In some protocols, when decrypting data, it is essential that * the behavior of the application does not depend on whether the padding * is correct, down to precise timing. Applications should prefer * protocols that use authenticated encryption rather than plain * encryption. If the application must perform a decryption of * unauthenticated data, the application writer should take care not * to reveal whether the padding is invalid. * * Implementations should strive to make valid and invalid padding * as close as possible to indistinguishable to an external observer. * In particular, the timing of a decryption operation should not * depend on the validity of the padding. */ #define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) /** Return this error when there's insufficient data when attempting * to read from a resource. */ #define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) /** This can be returned if a function can no longer operate correctly. * For example, if an essential initialization operation failed or * a mutex operation failed. */ #define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) /** The key identifier is not valid. See also :ref:\`key-handles\`. */ #define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) /** Stored data has been corrupted. * * This error indicates that some persistent storage has suffered corruption. * It does not indicate the following situations, which have specific error * codes: * * - A corruption of volatile memory - use #PSA_ERROR_CORRUPTION_DETECTED. * - A communication error between the cryptoprocessor and its external * storage - use #PSA_ERROR_COMMUNICATION_FAILURE. * - When the storage is in a valid state but is full - use * #PSA_ERROR_INSUFFICIENT_STORAGE. * - When the storage fails for other reasons - use * #PSA_ERROR_STORAGE_FAILURE. * - When the stored data is not valid - use #PSA_ERROR_DATA_INVALID. * * \note A storage corruption does not indicate that any data that was * previously read is invalid. However this previously read data might no * longer be readable from storage. * * When a storage failure occurs, it is no longer possible to ensure the * global integrity of the keystore. */ #define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) /** Data read from storage is not valid for the implementation. * * This error indicates that some data read from storage does not have a valid * format. It does not indicate the following situations, which have specific * error codes: * * - When the storage or stored data is corrupted - use #PSA_ERROR_DATA_CORRUPT * - When the storage fails for other reasons - use #PSA_ERROR_STORAGE_FAILURE * - An invalid argument to the API - use #PSA_ERROR_INVALID_ARGUMENT * * This error is typically a result of either storage corruption on a * cleartext storage backend, or an attempt to read data that was * written by an incompatible version of the library. */ #define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) /** The function that returns this status is defined as interruptible and * still has work to do, thus the user should call the function again with the * same operation context until it either returns #PSA_SUCCESS or any other * error. This is not an error per se, more a notification of status. */ #define PSA_OPERATION_INCOMPLETE ((psa_status_t)-248) /* *INDENT-ON* */ /**@}*/ /** \defgroup crypto_types Key and algorithm types * @{ */ /* Note that key type values, including ECC family and DH group values, are * embedded in the persistent key store, as part of key metadata. As a * consequence, they must not be changed (unless the storage format version * changes). */ /** An invalid key type value. * * Zero is not the encoding of any key type. */ #define PSA_KEY_TYPE_NONE ((psa_key_type_t) 0x0000) /** Vendor-defined key type flag. * * Key types defined by this standard will never have the * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should * respect the bitwise structure used by standard encodings whenever practical. */ #define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t) 0x8000) #define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t) 0x7000) #define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t) 0x1000) #define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t) 0x2000) #define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t) 0x4000) #define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t) 0x7000) #define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t) 0x3000) /** Whether a key type is vendor-defined. * * See also #PSA_KEY_TYPE_VENDOR_FLAG. */ #define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) /** Whether a key type is an unstructured array of bytes. * * This encompasses both symmetric keys and non-key data. */ #define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) /** Whether a key type is asymmetric: either a key pair or a public key. */ #define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) /** Whether a key type is the public part of a key pair. */ #define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) /** Whether a key type is a key pair containing a private part and a public * part. */ #define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) /** The key pair type corresponding to a public key type. * * You may also pass a key pair type as \p type, it will be left unchanged. * * \param type A public key type or key pair type. * * \return The corresponding key pair type. * If \p type is not a public key or a key pair, * the return value is undefined. */ #define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** The public key type corresponding to a key pair type. * * You may also pass a public key type as \p type, it will be left unchanged. * * \param type A public key type or key pair type. * * \return The corresponding public key type. * If \p type is not a public key or a key pair, * the return value is undefined. */ #define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) /** Raw data. * * A "key" of this type cannot be used for any cryptographic operation. * Applications may use this type to store arbitrary data in the keystore. */ #define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t) 0x1001) /** HMAC key. * * The key policy determines which underlying hash algorithm the key can be * used for. * * HMAC keys should generally have the same size as the underlying hash. * This size can be calculated with #PSA_HASH_LENGTH(\c alg) where * \c alg is the HMAC algorithm or the underlying hash algorithm. */ #define PSA_KEY_TYPE_HMAC ((psa_key_type_t) 0x1100) /** A secret for key derivation. * * This key type is for high-entropy secrets only. For low-entropy secrets, * #PSA_KEY_TYPE_PASSWORD should be used instead. * * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms. * * The key policy determines which key derivation algorithm the key * can be used for. */ #define PSA_KEY_TYPE_DERIVE ((psa_key_type_t) 0x1200) /** A low-entropy secret for password hashing or key derivation. * * This key type is suitable for passwords and passphrases which are typically * intended to be memorizable by humans, and have a low entropy relative to * their size. It can be used for randomly generated or derived keys with * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable * for such keys. It is not suitable for passwords with extremely low entropy, * such as numerical PINs. * * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of * key derivation algorithms. Algorithms that accept such an input were * designed to accept low-entropy secret and are known as password hashing or * key stretching algorithms. * * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of * key derivation algorithms, as the algorithms that take such an input expect * it to be high-entropy. * * The key policy determines which key derivation algorithm the key can be * used for, among the permissible subset defined above. */ #define PSA_KEY_TYPE_PASSWORD ((psa_key_type_t) 0x1203) /** A secret value that can be used to verify a password hash. * * The key policy determines which key derivation algorithm the key * can be used for, among the same permissible subset as for * #PSA_KEY_TYPE_PASSWORD. */ #define PSA_KEY_TYPE_PASSWORD_HASH ((psa_key_type_t) 0x1205) /** A secret value that can be used in when computing a password hash. * * The key policy determines which key derivation algorithm the key * can be used for, among the subset of algorithms that can use pepper. */ #define PSA_KEY_TYPE_PEPPER ((psa_key_type_t) 0x1206) /** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or * 32 bytes (AES-256). */ #define PSA_KEY_TYPE_AES ((psa_key_type_t) 0x2400) /** Key for a cipher, AEAD or MAC algorithm based on the * ARIA block cipher. */ #define PSA_KEY_TYPE_ARIA ((psa_key_type_t) 0x2406) /** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). * * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or * 192 bits (3-key 3DES). * * Note that single DES and 2-key 3DES are weak and strongly * deprecated and should only be used to decrypt legacy data. 3-key 3DES * is weak and deprecated and should only be used in legacy protocols. */ #define PSA_KEY_TYPE_DES ((psa_key_type_t) 0x2301) /** Key for a cipher, AEAD or MAC algorithm based on the * Camellia block cipher. */ #define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t) 0x2403) /** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. * * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. * * \note For ChaCha20 and ChaCha20_Poly1305, Mbed TLS only supports * 12-byte nonces. * * \note For ChaCha20, the initial counter value is 0. To encrypt or decrypt * with the initial counter value 1, you can process and discard a * 64-byte block before the real data. */ #define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t) 0x2004) /** RSA public key. * * The size of an RSA key is the bit size of the modulus. */ #define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t) 0x4001) /** RSA key pair (private and public key). * * The size of an RSA key is the bit size of the modulus. */ #define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t) 0x7001) /** Whether a key type is an RSA key (pair or public-only). */ #define PSA_KEY_TYPE_IS_RSA(type) \ (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) #define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4100) #define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t) 0x7100) #define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t) 0x00ff) /** Elliptic curve key pair. * * The size of an elliptic curve key is the bit size associated with the curve, * i.e. the bit size of *q* for a curve over a field *Fq*. * See the documentation of `PSA_ECC_FAMILY_xxx` curve families for details. * * \param curve A value of type ::psa_ecc_family_t that * identifies the ECC curve to be used. */ #define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) /** Elliptic curve public key. * * The size of an elliptic curve public key is the same as the corresponding * private key (see #PSA_KEY_TYPE_ECC_KEY_PAIR and the documentation of * `PSA_ECC_FAMILY_xxx` curve families). * * \param curve A value of type ::psa_ecc_family_t that * identifies the ECC curve to be used. */ #define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) /** Whether a key type is an elliptic curve key (pair or public-only). */ #define PSA_KEY_TYPE_IS_ECC(type) \ ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) /** Whether a key type is an elliptic curve key pair. */ #define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) /** Whether a key type is an elliptic curve public key. */ #define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) /** Extract the curve from an elliptic curve key type. */ #define PSA_KEY_TYPE_ECC_GET_FAMILY(type) \ ((psa_ecc_family_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ 0)) /** Check if the curve of given family is Weierstrass elliptic curve. */ #define PSA_ECC_FAMILY_IS_WEIERSTRASS(family) ((family & 0xc0) == 0) /** SEC Koblitz curves over prime fields. * * This family comprises the following curves: * secp192k1, secp224k1, secp256k1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note For secp224k1, the bit-size is 225 (size of a private value). * * \note Mbed TLS only supports secp192k1 and secp256k1. */ #define PSA_ECC_FAMILY_SECP_K1 ((psa_ecc_family_t) 0x17) /** SEC random curves over prime fields. * * This family comprises the following curves: * secp192r1, secp224r1, secp256r1, secp384r1, secp521r1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf */ #define PSA_ECC_FAMILY_SECP_R1 ((psa_ecc_family_t) 0x12) /* SECP160R2 (SEC2 v1, obsolete, not supported in Mbed TLS) */ #define PSA_ECC_FAMILY_SECP_R2 ((psa_ecc_family_t) 0x1b) /** SEC Koblitz curves over binary fields. * * This family comprises the following curves: * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_K1 ((psa_ecc_family_t) 0x27) /** SEC random curves over binary fields. * * This family comprises the following curves: * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. * They are defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) /** SEC additional random curves over binary fields. * * This family comprises the following curve: * sect163r2. * It is defined in _Standards for Efficient Cryptography_, * _SEC 2: Recommended Elliptic Curve Domain Parameters_. * https://www.secg.org/sec2-v2.pdf * * \note Mbed TLS does not support any curve in this family. */ #define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) /** Brainpool P random curves. * * This family comprises the following curves: * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. * It is defined in RFC 5639. * * \note Mbed TLS only supports the 256-bit, 384-bit and 512-bit curves * in this family. */ #define PSA_ECC_FAMILY_BRAINPOOL_P_R1 ((psa_ecc_family_t) 0x30) /** Curve25519 and Curve448. * * This family comprises the following Montgomery curves: * - 255-bit: Bernstein et al., * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. * - 448-bit: Hamburg, * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. */ #define PSA_ECC_FAMILY_MONTGOMERY ((psa_ecc_family_t) 0x41) /** The twisted Edwards curves Ed25519 and Ed448. * * These curves are suitable for EdDSA (#PSA_ALG_PURE_EDDSA for both curves, * #PSA_ALG_ED25519PH for the 255-bit curve, * #PSA_ALG_ED448PH for the 448-bit curve). * * This family comprises the following twisted Edwards curves: * - 255-bit: Edwards25519, the twisted Edwards curve birationally equivalent * to Curve25519. * Bernstein et al., _Twisted Edwards curves_, Africacrypt 2008. * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent * to Curve448. * Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. * * \note Mbed TLS does not support Edwards curves yet. */ #define PSA_ECC_FAMILY_TWISTED_EDWARDS ((psa_ecc_family_t) 0x42) #define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t) 0x4200) #define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t) 0x7200) #define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t) 0x00ff) /** Diffie-Hellman key pair. * * \param group A value of type ::psa_dh_family_t that identifies the * Diffie-Hellman group to be used. */ #define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) /** Diffie-Hellman public key. * * \param group A value of type ::psa_dh_family_t that identifies the * Diffie-Hellman group to be used. */ #define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) /** Whether a key type is a Diffie-Hellman key (pair or public-only). */ #define PSA_KEY_TYPE_IS_DH(type) \ ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) /** Whether a key type is a Diffie-Hellman key pair. */ #define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ PSA_KEY_TYPE_DH_KEY_PAIR_BASE) /** Whether a key type is a Diffie-Hellman public key. */ #define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) /** Extract the group from a Diffie-Hellman key type. */ #define PSA_KEY_TYPE_DH_GET_FAMILY(type) \ ((psa_dh_family_t) (PSA_KEY_TYPE_IS_DH(type) ? \ ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ 0)) /** Diffie-Hellman groups defined in RFC 7919 Appendix A. * * This family includes groups with the following key sizes (in bits): * 2048, 3072, 4096, 6144, 8192. A given implementation may support * all of these sizes or only a subset. */ #define PSA_DH_FAMILY_RFC7919 ((psa_dh_family_t) 0x03) #define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ (((type) >> 8) & 7) /** The block size of a block cipher. * * \param type A cipher key type (value of type #psa_key_type_t). * * \return The block size for a block cipher, or 1 for a stream cipher. * The return value is undefined if \p type is not a supported * cipher key type. * * \note It is possible to build stream cipher algorithms on top of a block * cipher, for example CTR mode (#PSA_ALG_CTR). * This macro only takes the key type into account, so it cannot be * used to determine the size of the data that #psa_cipher_update() * might buffer for future processing in general. * * \note This macro returns a compile-time constant if its argument is one. * * \warning This macro may evaluate its argument multiple times. */ #define PSA_BLOCK_CIPHER_BLOCK_LENGTH(type) \ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ 0u) /* Note that algorithm values are embedded in the persistent key store, * as part of key metadata. As a consequence, they must not be changed * (unless the storage format version changes). */ /** Vendor-defined algorithm flag. * * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG * bit set. Vendors who define additional algorithms must use an encoding with * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure * used by standard encodings whenever practical. */ #define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t) 0x80000000) #define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t) 0x7f000000) #define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t) 0x02000000) #define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t) 0x03000000) #define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t) 0x04000000) #define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t) 0x05000000) #define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t) 0x06000000) #define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t) 0x07000000) #define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t) 0x08000000) #define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t) 0x09000000) /** Whether an algorithm is vendor-defined. * * See also #PSA_ALG_VENDOR_FLAG. */ #define PSA_ALG_IS_VENDOR_DEFINED(alg) \ (((alg) & PSA_ALG_VENDOR_FLAG) != 0) /** Whether the specified algorithm is a hash algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a hash algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_HASH(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) /** Whether the specified algorithm is a MAC algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a MAC algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_MAC(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) /** Whether the specified algorithm is a symmetric cipher algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_CIPHER(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) /** Whether the specified algorithm is an authenticated encryption * with associated data (AEAD) algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_AEAD(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) /** Whether the specified algorithm is an asymmetric signature algorithm, * also known as public-key signature algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an asymmetric signature algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_SIGN(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) /** Whether the specified algorithm is an asymmetric encryption algorithm, * also known as public-key encryption algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an asymmetric encryption algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) /** Whether the specified algorithm is a key agreement algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_KEY_AGREEMENT(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a key derivation algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) /** Whether the specified algorithm is a key stretching / password hashing * algorithm. * * A key stretching / password hashing algorithm is a key derivation algorithm * that is suitable for use with a low-entropy secret such as a password. * Equivalently, it's a key derivation algorithm that uses a * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a key stretching / password hashing algorithm, 0 * otherwise. This macro may return either 0 or 1 if \p alg is not a * supported algorithm identifier. */ #define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ (PSA_ALG_IS_KEY_DERIVATION(alg) && \ (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) /** An invalid algorithm identifier value. */ /* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_ALG_NONE ((psa_algorithm_t)0) /* *INDENT-ON* */ #define PSA_ALG_HASH_MASK ((psa_algorithm_t) 0x000000ff) /** MD5 */ #define PSA_ALG_MD5 ((psa_algorithm_t) 0x02000003) /** PSA_ALG_RIPEMD160 */ #define PSA_ALG_RIPEMD160 ((psa_algorithm_t) 0x02000004) /** SHA1 */ #define PSA_ALG_SHA_1 ((psa_algorithm_t) 0x02000005) /** SHA2-224 */ #define PSA_ALG_SHA_224 ((psa_algorithm_t) 0x02000008) /** SHA2-256 */ #define PSA_ALG_SHA_256 ((psa_algorithm_t) 0x02000009) /** SHA2-384 */ #define PSA_ALG_SHA_384 ((psa_algorithm_t) 0x0200000a) /** SHA2-512 */ #define PSA_ALG_SHA_512 ((psa_algorithm_t) 0x0200000b) /** SHA2-512/224 */ #define PSA_ALG_SHA_512_224 ((psa_algorithm_t) 0x0200000c) /** SHA2-512/256 */ #define PSA_ALG_SHA_512_256 ((psa_algorithm_t) 0x0200000d) /** SHA3-224 */ #define PSA_ALG_SHA3_224 ((psa_algorithm_t) 0x02000010) /** SHA3-256 */ #define PSA_ALG_SHA3_256 ((psa_algorithm_t) 0x02000011) /** SHA3-384 */ #define PSA_ALG_SHA3_384 ((psa_algorithm_t) 0x02000012) /** SHA3-512 */ #define PSA_ALG_SHA3_512 ((psa_algorithm_t) 0x02000013) /** The first 512 bits (64 bytes) of the SHAKE256 output. * * This is the prehashing for Ed448ph (see #PSA_ALG_ED448PH). For other * scenarios where a hash function based on SHA3/SHAKE is desired, SHA3-512 * has the same output size and a (theoretically) higher security strength. */ #define PSA_ALG_SHAKE256_512 ((psa_algorithm_t) 0x02000015) /** In a hash-and-sign algorithm policy, allow any hash algorithm. * * This value may be used to form the algorithm usage field of a policy * for a signature algorithm that is parametrized by a hash. The key * may then be used to perform operations using the same signature * algorithm parametrized with any supported hash. * * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, #PSA_ALG_RSA_PSS_ANY_SALT, * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. * Then you may create and use a key as follows: * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: * ``` * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); * ``` * - Import or generate key material. * - Call psa_sign_hash() or psa_verify_hash(), passing * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each * call to sign or verify a message may use a different hash. * ``` * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); * ``` * * This value may not be used to build other algorithms that are * parametrized over a hash. For any valid use of this macro to build * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. * * This value may not be used to build an algorithm specification to * perform an operation. It is only valid to build policies. */ #define PSA_ALG_ANY_HASH ((psa_algorithm_t) 0x020000ff) #define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t) 0x00c00000) #define PSA_ALG_HMAC_BASE ((psa_algorithm_t) 0x03800000) /** Macro to build an HMAC algorithm. * * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HMAC algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HMAC(hash_alg) \ (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HMAC algorithm. * * HMAC is a family of MAC algorithms that are based on a hash function. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_HMAC(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ PSA_ALG_HMAC_BASE) /* In the encoding of a MAC algorithm, the bits corresponding to * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is * truncated. As an exception, the value 0 means the untruncated algorithm, * whatever its length is. The length is encoded in 6 bits, so it can * reach up to 63; the largest MAC is 64 bytes so its trivial truncation * to full length is correctly encoded as 0 and any non-trivial truncation * is correctly encoded as a value between 1 and 63. */ #define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t) 0x003f0000) #define PSA_MAC_TRUNCATION_OFFSET 16 /* In the encoding of a MAC algorithm, the bit corresponding to * #PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm * is a wildcard algorithm. A key with such wildcard algorithm as permitted * algorithm policy can be used with any algorithm corresponding to the * same base class and having a (potentially truncated) MAC length greater or * equal than the one encoded in #PSA_ALG_MAC_TRUNCATION_MASK. */ #define PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t) 0x00008000) /** Macro to build a truncated MAC algorithm. * * A truncated MAC algorithm is identical to the corresponding MAC * algorithm except that the MAC value for the truncated algorithm * consists of only the first \p mac_length bytes of the MAC value * for the untruncated algorithm. * * \note This macro may allow constructing algorithm identifiers that * are not valid, either because the specified length is larger * than the untruncated MAC or because the specified length is * smaller than permitted by the implementation. * * \note It is implementation-defined whether a truncated MAC that * is truncated to the same length as the MAC of the untruncated * algorithm is considered identical to the untruncated algorithm * for policy comparison purposes. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). This may be a truncated or untruncated * MAC algorithm. * \param mac_length Desired length of the truncated MAC in bytes. * This must be at most the full length of the MAC * and must be at least an implementation-specified * minimum. The implementation-specified minimum * shall not be zero. * * \return The corresponding MAC algorithm with the specified * length. * \return Unspecified if \p mac_alg is not a supported * MAC algorithm or if \p mac_length is too small or * too large for the specified MAC algorithm. */ #define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) | \ ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) /** Macro to build the base MAC algorithm corresponding to a truncated * MAC algorithm. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). This may be a truncated or untruncated * MAC algorithm. * * \return The corresponding base MAC algorithm. * \return Unspecified if \p mac_alg is not a supported * MAC algorithm. */ #define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) /** Length to which a MAC algorithm is truncated. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). * * \return Length of the truncated MAC in bytes. * \return 0 if \p mac_alg is a non-truncated MAC algorithm. * \return Unspecified if \p mac_alg is not a supported * MAC algorithm. */ #define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) /** Macro to build a MAC minimum-MAC-length wildcard algorithm. * * A minimum-MAC-length MAC wildcard algorithm permits all MAC algorithms * sharing the same base algorithm, and where the (potentially truncated) MAC * length of the specific algorithm is equal to or larger then the wildcard * algorithm's minimum MAC length. * * \note When setting the minimum required MAC length to less than the * smallest MAC length allowed by the base algorithm, this effectively * becomes an 'any-MAC-length-allowed' policy for that base algorithm. * * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) * is true). * \param min_mac_length Desired minimum length of the message authentication * code in bytes. This must be at most the untruncated * length of the MAC and must be at least 1. * * \return The corresponding MAC wildcard algorithm with the * specified minimum length. * \return Unspecified if \p mac_alg is not a supported MAC * algorithm or if \p min_mac_length is less than 1 or * too large for the specified MAC algorithm. */ #define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length) \ (PSA_ALG_TRUNCATED_MAC(mac_alg, min_mac_length) | \ PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) #define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t) 0x03c00000) /** The CBC-MAC construction over a block cipher * * \warning CBC-MAC is insecure in many cases. * A more secure mode, such as #PSA_ALG_CMAC, is recommended. */ #define PSA_ALG_CBC_MAC ((psa_algorithm_t) 0x03c00100) /** The CMAC construction over a block cipher */ #define PSA_ALG_CMAC ((psa_algorithm_t) 0x03c00200) /** Whether the specified algorithm is a MAC algorithm based on a block cipher. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ PSA_ALG_CIPHER_MAC_BASE) #define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t) 0x00800000) #define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t) 0x00400000) /** Whether the specified algorithm is a stream cipher. * * A stream cipher is a symmetric cipher that encrypts or decrypts messages * by applying a bitwise-xor with a stream of bytes that is generated * from a key. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier or if it is not a symmetric cipher algorithm. */ #define PSA_ALG_IS_STREAM_CIPHER(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) /** The stream cipher mode of a stream cipher algorithm. * * The underlying stream cipher is determined by the key type. * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20. */ #define PSA_ALG_STREAM_CIPHER ((psa_algorithm_t) 0x04800100) /** The CTR stream cipher mode. * * CTR is a stream cipher which is built from a block cipher. * The underlying block cipher is determined by the key type. * For example, to use AES-128-CTR, use this algorithm with * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). */ #define PSA_ALG_CTR ((psa_algorithm_t) 0x04c01000) /** The CFB stream cipher mode. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_CFB ((psa_algorithm_t) 0x04c01100) /** The OFB stream cipher mode. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_OFB ((psa_algorithm_t) 0x04c01200) /** The XTS cipher mode. * * XTS is a cipher mode which is built from a block cipher. It requires at * least one full block of input, but beyond this minimum the input * does not need to be a whole number of blocks. */ #define PSA_ALG_XTS ((psa_algorithm_t) 0x0440ff00) /** The Electronic Code Book (ECB) mode of a block cipher, with no padding. * * \warning ECB mode does not protect the confidentiality of the encrypted data * except in extremely narrow circumstances. It is recommended that applications * only use ECB if they need to construct an operating mode that the * implementation does not provide. Implementations are encouraged to provide * the modes that applications need in preference to supporting direct access * to ECB. * * The underlying block cipher is determined by the key type. * * This symmetric cipher mode can only be used with messages whose lengths are a * multiple of the block size of the chosen block cipher. * * ECB mode does not accept an initialization vector (IV). When using a * multi-part cipher operation with this algorithm, psa_cipher_generate_iv() * and psa_cipher_set_iv() must not be called. */ #define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t) 0x04404400) /** The CBC block cipher chaining mode, with no padding. * * The underlying block cipher is determined by the key type. * * This symmetric cipher mode can only be used with messages whose lengths * are whole number of blocks for the chosen block cipher. */ #define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t) 0x04404000) /** The CBC block cipher chaining mode with PKCS#7 padding. * * The underlying block cipher is determined by the key type. * * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. */ #define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t) 0x04404100) #define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t) 0x00400000) /** Whether the specified algorithm is an AEAD mode on a block cipher. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on * a block cipher, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) /** The CCM authenticated encryption algorithm. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_CCM ((psa_algorithm_t) 0x05500100) /** The CCM* cipher mode without authentication. * * This is CCM* as specified in IEEE 802.15.4 §7, with a tag length of 0. * For CCM* with a nonzero tag length, use the AEAD algorithm #PSA_ALG_CCM. * * The underlying block cipher is determined by the key type. * * Currently only 13-byte long IV's are supported. */ #define PSA_ALG_CCM_STAR_NO_TAG ((psa_algorithm_t) 0x04c01300) /** The GCM authenticated encryption algorithm. * * The underlying block cipher is determined by the key type. */ #define PSA_ALG_GCM ((psa_algorithm_t) 0x05500200) /** The Chacha20-Poly1305 AEAD algorithm. * * The ChaCha20_Poly1305 construction is defined in RFC 7539. * * Implementations must support 12-byte nonces, may support 8-byte nonces, * and should reject other sizes. * * Implementations must support 16-byte tags and should reject other sizes. */ #define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t) 0x05100500) /* In the encoding of an AEAD algorithm, the bits corresponding to * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. * The constants for default lengths follow this encoding. */ #define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t) 0x003f0000) #define PSA_AEAD_TAG_LENGTH_OFFSET 16 /* In the encoding of an AEAD algorithm, the bit corresponding to * #PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm * is a wildcard algorithm. A key with such wildcard algorithm as permitted * algorithm policy can be used with any algorithm corresponding to the * same base class and having a tag length greater than or equal to the one * encoded in #PSA_ALG_AEAD_TAG_LENGTH_MASK. */ #define PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t) 0x00008000) /** Macro to build a shortened AEAD algorithm. * * A shortened AEAD algorithm is similar to the corresponding AEAD * algorithm, but has an authentication tag that consists of fewer bytes. * Depending on the algorithm, the tag length may affect the calculation * of the ciphertext. * * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) * is true). * \param tag_length Desired length of the authentication tag in bytes. * * \return The corresponding AEAD algorithm with the specified * length. * \return Unspecified if \p aead_alg is not a supported * AEAD algorithm or if \p tag_length is not valid * for the specified AEAD algorithm. */ #define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \ (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | \ PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)) | \ ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ PSA_ALG_AEAD_TAG_LENGTH_MASK)) /** Retrieve the tag length of a specified AEAD algorithm * * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) * is true). * * \return The tag length specified by the input algorithm. * \return Unspecified if \p aead_alg is not a supported * AEAD algorithm. */ #define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg) \ (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> \ PSA_AEAD_TAG_LENGTH_OFFSET) /** Calculate the corresponding AEAD algorithm with the default tag length. * * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p aead_alg) is true). * * \return The corresponding AEAD algorithm with the default * tag length for that algorithm. */ #define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg) \ ( \ PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CCM) \ PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_GCM) \ PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ 0) #define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, ref) \ PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, 0) == \ PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ? \ ref : /** Macro to build an AEAD minimum-tag-length wildcard algorithm. * * A minimum-tag-length AEAD wildcard algorithm permits all AEAD algorithms * sharing the same base algorithm, and where the tag length of the specific * algorithm is equal to or larger then the minimum tag length specified by the * wildcard algorithm. * * \note When setting the minimum required tag length to less than the * smallest tag length allowed by the base algorithm, this effectively * becomes an 'any-tag-length-allowed' policy for that base algorithm. * * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that * #PSA_ALG_IS_AEAD(\p aead_alg) is true). * \param min_tag_length Desired minimum length of the authentication tag in * bytes. This must be at least 1 and at most the largest * allowed tag length of the algorithm. * * \return The corresponding AEAD wildcard algorithm with the * specified minimum length. * \return Unspecified if \p aead_alg is not a supported * AEAD algorithm or if \p min_tag_length is less than 1 * or too large for the specified AEAD algorithm. */ #define PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(aead_alg, min_tag_length) \ (PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, min_tag_length) | \ PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) #define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t) 0x06000200) /** RSA PKCS#1 v1.5 signature with hashing. * * This is the signature scheme defined by RFC 8017 * (PKCS#1: RSA Cryptography Specifications) under the name * RSASSA-PKCS1-v1_5. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Raw PKCS#1 v1.5 signature. * * The input to this algorithm is the DigestInfo structure used by * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 * steps 3–6. */ #define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE #define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) #define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t) 0x06000300) #define PSA_ALG_RSA_PSS_ANY_SALT_BASE ((psa_algorithm_t) 0x06001300) /** RSA PSS signature with hashing. * * This is the signature scheme defined by RFC 8017 * (PKCS#1: RSA Cryptography Specifications) under the name * RSASSA-PSS, with the message generation function MGF1, and with * a salt length equal to the length of the hash, or the largest * possible salt length for the algorithm and key size if that is * smaller than the hash length. The specified hash algorithm is * used to hash the input message, to create the salted hash, and * for the mask generation. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PSS signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PSS(hash_alg) \ (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** RSA PSS signature with hashing with relaxed verification. * * This algorithm has the same behavior as #PSA_ALG_RSA_PSS when signing, * but allows an arbitrary salt length (including \c 0) when verifying a * signature. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding RSA PSS signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg) \ (PSA_ALG_RSA_PSS_ANY_SALT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is RSA PSS with standard salt. * * \param alg An algorithm value or an algorithm policy wildcard. * * \return 1 if \p alg is of the form * #PSA_ALG_RSA_PSS(\c hash_alg), * where \c hash_alg is a hash algorithm or * #PSA_ALG_ANY_HASH. 0 otherwise. * This macro may return either 0 or 1 if \p alg is not * a supported algorithm identifier or policy. */ #define PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) /** Whether the specified algorithm is RSA PSS with any salt. * * \param alg An algorithm value or an algorithm policy wildcard. * * \return 1 if \p alg is of the form * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), * where \c hash_alg is a hash algorithm or * #PSA_ALG_ANY_HASH. 0 otherwise. * This macro may return either 0 or 1 if \p alg is not * a supported algorithm identifier or policy. */ #define PSA_ALG_IS_RSA_PSS_ANY_SALT(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_ANY_SALT_BASE) /** Whether the specified algorithm is RSA PSS. * * This includes any of the RSA PSS algorithm variants, regardless of the * constraints on salt length. * * \param alg An algorithm value or an algorithm policy wildcard. * * \return 1 if \p alg is of the form * #PSA_ALG_RSA_PSS(\c hash_alg) or * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), * where \c hash_alg is a hash algorithm or * #PSA_ALG_ANY_HASH. 0 otherwise. * This macro may return either 0 or 1 if \p alg is not * a supported algorithm identifier or policy. */ #define PSA_ALG_IS_RSA_PSS(alg) \ (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) || \ PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) #define PSA_ALG_ECDSA_BASE ((psa_algorithm_t) 0x06000600) /** ECDSA signature with hashing. * * This is the ECDSA signature scheme defined by ANSI X9.62, * with a random per-message secret number (*k*). * * The representation of the signature as a byte string consists of * the concatenation of the signature values *r* and *s*. Each of * *r* and *s* is encoded as an *N*-octet string, where *N* is the length * of the base point of the curve in octets. Each value is represented * in big-endian order (most significant octet first). * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding ECDSA signature algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_ECDSA(hash_alg) \ (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** ECDSA signature without hashing. * * This is the same signature scheme as #PSA_ALG_ECDSA(), but * without specifying a hash algorithm. This algorithm may only be * used to sign or verify a sequence of bytes that should be an * already-calculated hash. Note that the input is padded with * zeros on the left or truncated on the left as required to fit * the curve size. */ #define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE #define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t) 0x06000700) /** Deterministic ECDSA signature with hashing. * * This is the deterministic ECDSA signature scheme defined by RFC 6979. * * The representation of a signature is the same as with #PSA_ALG_ECDSA(). * * Note that when this algorithm is used for verification, signatures * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the * same private key are accepted. In other words, * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * This includes #PSA_ALG_ANY_HASH * when specifying the algorithm in a usage policy. * * \return The corresponding deterministic ECDSA signature * algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t) 0x00000100) #define PSA_ALG_IS_ECDSA(alg) \ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ PSA_ALG_ECDSA_BASE) #define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) #define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) #define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) /** Edwards-curve digital signature algorithm without prehashing (PureEdDSA), * using standard parameters. * * Contexts are not supported in the current version of this specification * because there is no suitable signature interface that can take the * context as a parameter. A future version of this specification may add * suitable functions and extend this algorithm to support contexts. * * PureEdDSA requires an elliptic curve key on a twisted Edwards curve. * In this specification, the following curves are supported: * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 255-bit: Ed25519 as specified * in RFC 8032. * The curve is Edwards25519. * The hash function used internally is SHA-512. * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 448-bit: Ed448 as specified * in RFC 8032. * The curve is Edwards448. * The hash function used internally is the first 114 bytes of the * SHAKE256 output. * * This algorithm can be used with psa_sign_message() and * psa_verify_message(). Since there is no prehashing, it cannot be used * with psa_sign_hash() or psa_verify_hash(). * * The signature format is the concatenation of R and S as defined by * RFC 8032 §5.1.6 and §5.2.6 (a 64-byte string for Ed25519, a 114-byte * string for Ed448). */ #define PSA_ALG_PURE_EDDSA ((psa_algorithm_t) 0x06000800) #define PSA_ALG_HASH_EDDSA_BASE ((psa_algorithm_t) 0x06000900) #define PSA_ALG_IS_HASH_EDDSA(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HASH_EDDSA_BASE) /** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), * using SHA-512 and the Edwards25519 curve. * * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. * * This algorithm is Ed25519 as specified in RFC 8032. * The curve is Edwards25519. * The prehash is SHA-512. * The hash function used internally is SHA-512. * * This is a hash-and-sign algorithm: to calculate a signature, * you can either: * - call psa_sign_message() on the message; * - or calculate the SHA-512 hash of the message * with psa_hash_compute() * or with a multi-part hash operation started with psa_hash_setup(), * using the hash algorithm #PSA_ALG_SHA_512, * then sign the calculated hash with psa_sign_hash(). * Verifying a signature is similar, using psa_verify_message() or * psa_verify_hash() instead of the signature function. */ #define PSA_ALG_ED25519PH \ (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHA_512 & PSA_ALG_HASH_MASK)) /** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), * using SHAKE256 and the Edwards448 curve. * * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. * * This algorithm is Ed448 as specified in RFC 8032. * The curve is Edwards448. * The prehash is the first 64 bytes of the SHAKE256 output. * The hash function used internally is the first 114 bytes of the * SHAKE256 output. * * This is a hash-and-sign algorithm: to calculate a signature, * you can either: * - call psa_sign_message() on the message; * - or calculate the first 64 bytes of the SHAKE256 output of the message * with psa_hash_compute() * or with a multi-part hash operation started with psa_hash_setup(), * using the hash algorithm #PSA_ALG_SHAKE256_512, * then sign the calculated hash with psa_sign_hash(). * Verifying a signature is similar, using psa_verify_message() or * psa_verify_hash() instead of the signature function. */ #define PSA_ALG_ED448PH \ (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHAKE256_512 & PSA_ALG_HASH_MASK)) /* Default definition, to be overridden if the library is extended with * more hash-and-sign algorithms that we want to keep out of this header * file. */ #define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0 /** Whether the specified algorithm is a signature algorithm that can be used * with psa_sign_hash() and psa_verify_hash(). * * This encompasses all strict hash-and-sign algorithms categorized by * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the * paradigm more loosely: * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) * * \param alg An algorithm identifier (value of type psa_algorithm_t). * * \return 1 if alg is a signature algorithm that can be used to sign a * hash. 0 if alg is a signature algorithm that can only be used * to sign a message. 0 if alg is not a signature algorithm. * This macro can return either 0 or 1 if alg is not a * supported algorithm identifier. */ #define PSA_ALG_IS_SIGN_HASH(alg) \ (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) /** Whether the specified algorithm is a signature algorithm that can be used * with psa_sign_message() and psa_verify_message(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if alg is a signature algorithm that can be used to sign a * message. 0 if \p alg is a signature algorithm that can only be used * to sign an already-calculated hash. 0 if \p alg is not a signature * algorithm. This macro can return either 0 or 1 if \p alg is not a * supported algorithm identifier. */ #define PSA_ALG_IS_SIGN_MESSAGE(alg) \ (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA) /** Whether the specified algorithm is a hash-and-sign algorithm. * * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms * structured in two parts: first the calculation of a hash in a way that * does not depend on the key, then the calculation of a signature from the * hash value and the key. Hash-and-sign algorithms encode the hash * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH * to extract this algorithm. * * Thus, for a hash-and-sign algorithm, * `psa_sign_message(key, alg, input, ...)` is equivalent to * ``` * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...); * psa_sign_hash(key, alg, hash, ..., signature, ...); * ``` * Most usefully, separating the hash from the signature allows the hash * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update() * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to * calculating the hash and then calling psa_verify_hash(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_HASH_AND_SIGN(alg) \ (PSA_ALG_IS_SIGN_HASH(alg) && \ ((alg) & PSA_ALG_HASH_MASK) != 0) /** Get the hash used by a hash-and-sign signature algorithm. * * A hash-and-sign algorithm is a signature algorithm which is * composed of two phases: first a hashing phase which does not use * the key and produces a hash of the input message, then a signing * phase which only uses the hash and the key and not the message * itself. * * \param alg A signature algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_SIGN(\p alg) is true). * * \return The underlying hash algorithm if \p alg is a hash-and-sign * algorithm. * \return 0 if \p alg is a signature algorithm that does not * follow the hash-and-sign structure. * \return Unspecified if \p alg is not a signature algorithm or * if it is not supported by the implementation. */ #define PSA_ALG_SIGN_GET_HASH(alg) \ (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) /** RSA PKCS#1 v1.5 encryption. * * \warning Calling psa_asymmetric_decrypt() with this algorithm as a * parameter is considered an inherently dangerous function * (CWE-242). Unless it is used in a side channel free and safe * way (eg. implementing the TLS protocol as per 7.4.7.1 of * RFC 5246), the calling code is vulnerable. * */ #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t) 0x07000200) #define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t) 0x07000300) /** RSA OAEP encryption. * * This is the encryption scheme defined by RFC 8017 * (PKCS#1: RSA Cryptography Specifications) under the name * RSAES-OAEP, with the message generation function MGF1. * * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use * for MGF1. * * \return The corresponding RSA OAEP encryption algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_RSA_OAEP(hash_alg) \ (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_IS_RSA_OAEP(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) #define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ (PSA_ALG_IS_RSA_OAEP(alg) ? \ ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) #define PSA_ALG_HKDF_BASE ((psa_algorithm_t) 0x08000100) /** Macro to build an HKDF algorithm. * * For example, `PSA_ALG_HKDF(PSA_ALG_SHA_256)` is HKDF using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. * It is optional; if omitted, the derivation uses an empty salt. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before * starting to generate output. * * \warning HKDF processes the salt as follows: first hash it with hash_alg * if the salt is longer than the block size of the hash algorithm; then * pad with null bytes up to the block size. As a result, it is possible * for distinct salt inputs to result in the same outputs. To ensure * unique outputs, it is recommended to use a fixed length for salt values. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF(hash_alg) \ (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HKDF algorithm. * * HKDF is a family of key derivation algorithms that are based on a hash * function and the HMAC construction. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_HKDF(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) #define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_HKDF_EXTRACT_BASE ((psa_algorithm_t) 0x08000400) /** Macro to build an HKDF-Extract algorithm. * * For example, `PSA_ALG_HKDF_EXTRACT(PSA_ALG_SHA_256)` is * HKDF-Extract using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - PSA_KEY_DERIVATION_INPUT_SALT is the salt. * - PSA_KEY_DERIVATION_INPUT_SECRET is the input keying material used in the * "extract" step. * The inputs are mandatory and must be passed in the order above. * Each input may only be passed once. * * \warning HKDF-Extract is not meant to be used on its own. PSA_ALG_HKDF * should be used instead if possible. PSA_ALG_HKDF_EXTRACT is provided * as a separate algorithm for the sake of protocols that use it as a * building block. It may also be a slight performance optimization * in applications that use HKDF with the same salt and key but many * different info strings. * * \warning HKDF processes the salt as follows: first hash it with hash_alg * if the salt is longer than the block size of the hash algorithm; then * pad with null bytes up to the block size. As a result, it is possible * for distinct salt inputs to result in the same outputs. To ensure * unique outputs, it is recommended to use a fixed length for salt values. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF-Extract algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF_EXTRACT(hash_alg) \ (PSA_ALG_HKDF_EXTRACT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HKDF-Extract algorithm. * * HKDF-Extract is a family of key derivation algorithms that are based * on a hash function and the HMAC construction. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an HKDF-Extract algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_HKDF_EXTRACT(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE) #define PSA_ALG_HKDF_EXPAND_BASE ((psa_algorithm_t) 0x08000500) /** Macro to build an HKDF-Expand algorithm. * * For example, `PSA_ALG_HKDF_EXPAND(PSA_ALG_SHA_256)` is * HKDF-Expand using HMAC-SHA-256. * * This key derivation algorithm uses the following inputs: * - PSA_KEY_DERIVATION_INPUT_SECRET is the pseudorandom key (PRK). * - PSA_KEY_DERIVATION_INPUT_INFO is the info string. * * The inputs are mandatory and must be passed in the order above. * Each input may only be passed once. * * \warning HKDF-Expand is not meant to be used on its own. `PSA_ALG_HKDF` * should be used instead if possible. `PSA_ALG_HKDF_EXPAND` is provided as * a separate algorithm for the sake of protocols that use it as a building * block. It may also be a slight performance optimization in applications * that use HKDF with the same salt and key but many different info strings. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding HKDF-Expand algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_HKDF_EXPAND(hash_alg) \ (PSA_ALG_HKDF_EXPAND_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is an HKDF-Expand algorithm. * * HKDF-Expand is a family of key derivation algorithms that are based * on a hash function and the HMAC construction. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an HKDF-Expand algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_HKDF_EXPAND(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) /** Whether the specified algorithm is an HKDF or HKDF-Extract or * HKDF-Expand algorithm. * * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is any HKDF type algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_ANY_HKDF(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE || \ ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXTRACT_BASE || \ ((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_EXPAND_BASE) #define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t) 0x08000200) /** Macro to build a TLS-1.2 PRF algorithm. * * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, * specified in Section 5 of RFC 5246. It is based on HMAC and can be * used with either SHA-256 or SHA-384. * * This key derivation algorithm uses the following inputs, which must be * passed in the order given here: * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. * * For the application to TLS-1.2 key expansion, the seed is the * concatenation of ServerHello.Random + ClientHello.Random, * and the label is "key expansion". * * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)` represents the * TLS 1.2 PRF using HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding TLS-1.2 PRF algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_TLS12_PRF(hash_alg) \ (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is a TLS-1.2 PRF algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_TLS12_PRF(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) #define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t) 0x08000300) /** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. * * In a pure-PSK handshake in TLS 1.2, the master secret is derived * from the PreSharedKey (PSK) through the application of padding * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). * The latter is based on HMAC and can be used with either SHA-256 * or SHA-384. * * This key derivation algorithm uses the following inputs, which must be * passed in the order given here: * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. * - #PSA_KEY_DERIVATION_INPUT_OTHER_SECRET is the other secret for the * computation of the premaster secret. This input is optional; * if omitted, it defaults to a string of null bytes with the same length * as the secret (PSK) input. * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. * * For the application to TLS-1.2, the seed (which is * forwarded to the TLS-1.2 PRF) is the concatenation of the * ClientHello.Random + ServerHello.Random, * the label is "master secret" or "extended master secret" and * the other secret depends on the key exchange specified in the cipher suite: * - for a plain PSK cipher suite (RFC 4279, Section 2), omit * PSA_KEY_DERIVATION_INPUT_OTHER_SECRET * - for a DHE-PSK (RFC 4279, Section 3) or ECDHE-PSK cipher suite * (RFC 5489, Section 2), the other secret should be the output of the * PSA_ALG_FFDH or PSA_ALG_ECDH key agreement performed with the peer. * The recommended way to pass this input is to use a key derivation * algorithm constructed as * PSA_ALG_KEY_AGREEMENT(ka_alg, PSA_ALG_TLS12_PSK_TO_MS(hash_alg)) * and to call psa_key_derivation_key_agreement(). Alternatively, * this input may be an output of `psa_raw_key_agreement()` passed with * psa_key_derivation_input_bytes(), or an equivalent input passed with * psa_key_derivation_input_bytes() or psa_key_derivation_input_key(). * - for a RSA-PSK cipher suite (RFC 4279, Section 4), the other secret * should be the 48-byte client challenge (the PreMasterSecret of * (RFC 5246, Section 7.4.7.1)) concatenation of the TLS version and * a 46-byte random string chosen by the client. On the server, this is * typically an output of psa_asymmetric_decrypt() using * PSA_ALG_RSA_PKCS1V15_CRYPT, passed to the key derivation operation * with `psa_key_derivation_input_bytes()`. * * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256)` represents the * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding TLS-1.2 PSK to MS algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) #define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) /* The TLS 1.2 ECJPAKE-to-PMS KDF. It takes the shared secret K (an EC point * in case of EC J-PAKE) and calculates SHA256(K.X) that the rest of TLS 1.2 * will use to derive the session secret, as defined by step 2 of * https://datatracker.ietf.org/doc/html/draft-cragie-tls-ecjpake-01#section-8.7. * Uses PSA_ALG_SHA_256. * This function takes a single input: * #PSA_KEY_DERIVATION_INPUT_SECRET is the shared secret K from EC J-PAKE. * The only supported curve is secp256r1 (the 256-bit curve in * #PSA_ECC_FAMILY_SECP_R1), so the input must be exactly 65 bytes. * The output has to be read as a single chunk of 32 bytes, defined as * PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE. */ #define PSA_ALG_TLS12_ECJPAKE_TO_PMS ((psa_algorithm_t) 0x08000609) /* This flag indicates whether the key derivation algorithm is suitable for * use on low-entropy secrets such as password - these algorithms are also * known as key stretching or password hashing schemes. These are also the * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD. * * Those algorithms cannot be combined with a key agreement algorithm. */ #define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG ((psa_algorithm_t) 0x00800000) #define PSA_ALG_PBKDF2_HMAC_BASE ((psa_algorithm_t) 0x08800100) /** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm. * * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). * This macro specifies the PBKDF2 algorithm constructed using a PRF based on * HMAC with the specified hash. * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)` specifies PBKDF2 * using the PRF HMAC-SHA-256. * * This key derivation algorithm uses the following inputs, which must be * provided in the following order: * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count. * This input step must be used exactly once. * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt. * This input step must be used one or more times; if used several times, the * inputs will be concatenated. This can be used to build the final salt * from multiple sources, both public and secret (also known as pepper). * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed. * This input step must be used exactly once. * * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_HASH(\p hash_alg) is true). * * \return The corresponding PBKDF2-HMAC-XXX algorithm. * \return Unspecified if \p hash_alg is not a supported * hash algorithm. */ #define PSA_ALG_PBKDF2_HMAC(hash_alg) \ (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) /** Whether the specified algorithm is a PBKDF2-HMAC algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a PBKDF2-HMAC algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key derivation algorithm identifier. */ #define PSA_ALG_IS_PBKDF2_HMAC(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE) #define PSA_ALG_PBKDF2_HMAC_GET_HASH(pbkdf2_alg) \ (PSA_ALG_CATEGORY_HASH | ((pbkdf2_alg) & PSA_ALG_HASH_MASK)) /** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm. * * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). * This macro specifies the PBKDF2 algorithm constructed using the * AES-CMAC-PRF-128 PRF specified by RFC 4615. * * This key derivation algorithm uses the same inputs as * #PSA_ALG_PBKDF2_HMAC() with the same constraints. */ #define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t) 0x08800200) #define PSA_ALG_IS_PBKDF2(kdf_alg) \ (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg) || \ ((kdf_alg) == PSA_ALG_PBKDF2_AES_CMAC_PRF_128)) #define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t) 0xfe00ffff) #define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t) 0xffff0000) /** Macro to build a combined algorithm that chains a key agreement with * a key derivation. * * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). * * \return The corresponding key agreement and derivation * algorithm. * \return Unspecified if \p ka_alg is not a supported * key agreement algorithm or \p kdf_alg is not a * supported key derivation algorithm. */ #define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ ((ka_alg) | (kdf_alg)) #define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) #define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) /** Whether the specified algorithm is a raw key agreement algorithm. * * A raw key agreement algorithm is one that does not specify * a key derivation function. * Usually, raw key agreement algorithms are constructed directly with * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are * constructed with #PSA_ALG_KEY_AGREEMENT(). * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. * This macro may return either 0 or 1 if \p alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) #define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) /** The finite-field Diffie-Hellman (DH) key agreement algorithm. * * The shared secret produced by key agreement is * `g^{ab}` in big-endian format. * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` * in bits. */ #define PSA_ALG_FFDH ((psa_algorithm_t) 0x09010000) /** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. * * This includes the raw finite field Diffie-Hellman algorithm as well as * finite-field Diffie-Hellman followed by any supporter key derivation * algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key agreement algorithm identifier. */ #define PSA_ALG_IS_FFDH(alg) \ (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) /** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. * * The shared secret produced by key agreement is the x-coordinate of * the shared secret point. It is always `ceiling(m / 8)` bytes long where * `m` is the bit size associated with the curve, i.e. the bit size of the * order of the curve's coordinate field. When `m` is not a multiple of 8, * the byte containing the most significant bit of the shared secret * is padded with zero bits. The byte order is either little-endian * or big-endian depending on the curve type. * * - For Montgomery curves (curve types `PSA_ECC_FAMILY_CURVEXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in little-endian byte order. * The bit size is 448 for Curve448 and 255 for Curve25519. * - For Weierstrass curves over prime fields (curve types * `PSA_ECC_FAMILY_SECPXXX` and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. * - For Weierstrass curves over binary fields (curve types * `PSA_ECC_FAMILY_SECTXXX`), * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` * in big-endian byte order. * The bit size is `m` for the field `F_{2^m}`. */ #define PSA_ALG_ECDH ((psa_algorithm_t) 0x09020000) /** Whether the specified algorithm is an elliptic curve Diffie-Hellman * algorithm. * * This includes the raw elliptic curve Diffie-Hellman algorithm as well as * elliptic curve Diffie-Hellman followed by any supporter key derivation * algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, * 0 otherwise. * This macro may return either 0 or 1 if \c alg is not a supported * key agreement algorithm identifier. */ #define PSA_ALG_IS_ECDH(alg) \ (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) /** Whether the specified algorithm encoding is a wildcard. * * Wildcard values may only be used to set the usage algorithm field in * a policy, not to perform an operation. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return 1 if \c alg is a wildcard algorithm encoding. * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for * an operation). * \return This macro may return either 0 or 1 if \c alg is not a supported * algorithm identifier. */ #define PSA_ALG_IS_WILDCARD(alg) \ (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ PSA_ALG_IS_MAC(alg) ? \ (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ PSA_ALG_IS_AEAD(alg) ? \ (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ (alg) == PSA_ALG_ANY_HASH) /** Get the hash used by a composite algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). * * \return The underlying hash algorithm if alg is a composite algorithm that * uses a hash algorithm. * * \return \c 0 if alg is not a composite algorithm that uses a hash. */ #define PSA_ALG_GET_HASH(alg) \ (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t) 0) : 0x02000000 | ((alg) & 0x000000ff)) /**@}*/ /** \defgroup key_lifetimes Key lifetimes * @{ */ /* Note that location and persistence level values are embedded in the * persistent key store, as part of key metadata. As a consequence, they * must not be changed (unless the storage format version changes). */ /** The default lifetime for volatile keys. * * A volatile key only exists as long as the identifier to it is not destroyed. * The key material is guaranteed to be erased on a power reset. * * A key with this lifetime is typically stored in the RAM area of the * PSA Crypto subsystem. However this is an implementation choice. * If an implementation stores data about the key in a non-volatile memory, * it must release all the resources associated with the key and erase the * key material if the calling application terminates. */ #define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t) 0x00000000) /** The default lifetime for persistent keys. * * A persistent key remains in storage until it is explicitly destroyed or * until the corresponding storage area is wiped. This specification does * not define any mechanism to wipe a storage area, but integrations may * provide their own mechanism (for example to perform a factory reset, * to prepare for device refurbishment, or to uninstall an application). * * This lifetime value is the default storage area for the calling * application. Integrations of Mbed TLS may support other persistent lifetimes. * See ::psa_key_lifetime_t for more information. */ #define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t) 0x00000001) /** The persistence level of volatile keys. * * See ::psa_key_persistence_t for more information. */ #define PSA_KEY_PERSISTENCE_VOLATILE ((psa_key_persistence_t) 0x00) /** The default persistence level for persistent keys. * * See ::psa_key_persistence_t for more information. */ #define PSA_KEY_PERSISTENCE_DEFAULT ((psa_key_persistence_t) 0x01) /** A persistence level indicating that a key is never destroyed. * * See ::psa_key_persistence_t for more information. */ #define PSA_KEY_PERSISTENCE_READ_ONLY ((psa_key_persistence_t) 0xff) #define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) \ ((psa_key_persistence_t) ((lifetime) & 0x000000ff)) #define PSA_KEY_LIFETIME_GET_LOCATION(lifetime) \ ((psa_key_location_t) ((lifetime) >> 8)) /** Whether a key lifetime indicates that the key is volatile. * * A volatile key is automatically destroyed by the implementation when * the application instance terminates. In particular, a volatile key * is automatically destroyed on a power reset of the device. * * A key that is not volatile is persistent. Persistent keys are * preserved until the application explicitly destroys them or until an * implementation-specific device management event occurs (for example, * a factory reset). * * \param lifetime The lifetime value to query (value of type * ::psa_key_lifetime_t). * * \return \c 1 if the key is volatile, otherwise \c 0. */ #define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime) \ (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ PSA_KEY_PERSISTENCE_VOLATILE) /** Whether a key lifetime indicates that the key is read-only. * * Read-only keys cannot be created or destroyed through the PSA Crypto API. * They must be created through platform-specific means that bypass the API. * * Some platforms may offer ways to destroy read-only keys. For example, * consider a platform with multiple levels of privilege, where a * low-privilege application can use a key but is not allowed to destroy * it, and the platform exposes the key to the application with a read-only * lifetime. High-privilege code can destroy the key even though the * application sees the key as read-only. * * \param lifetime The lifetime value to query (value of type * ::psa_key_lifetime_t). * * \return \c 1 if the key is read-only, otherwise \c 0. */ #define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime) \ (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ PSA_KEY_PERSISTENCE_READ_ONLY) /** Construct a lifetime from a persistence level and a location. * * \param persistence The persistence level * (value of type ::psa_key_persistence_t). * \param location The location indicator * (value of type ::psa_key_location_t). * * \return The constructed lifetime value. */ #define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \ ((location) << 8 | (persistence)) /** The local storage area for persistent keys. * * This storage area is available on all systems that can store persistent * keys without delegating the storage to a third-party cryptoprocessor. * * See ::psa_key_location_t for more information. */ #define PSA_KEY_LOCATION_LOCAL_STORAGE ((psa_key_location_t) 0x000000) #define PSA_KEY_LOCATION_VENDOR_FLAG ((psa_key_location_t) 0x800000) /* Note that key identifier values are embedded in the * persistent key store, as part of key metadata. As a consequence, they * must not be changed (unless the storage format version changes). */ /** The null key identifier. */ /* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */ #define PSA_KEY_ID_NULL ((psa_key_id_t)0) /* *INDENT-ON* */ /** The minimum value for a key identifier chosen by the application. */ #define PSA_KEY_ID_USER_MIN ((psa_key_id_t) 0x00000001) /** The maximum value for a key identifier chosen by the application. */ #define PSA_KEY_ID_USER_MAX ((psa_key_id_t) 0x3fffffff) /** The minimum value for a key identifier chosen by the implementation. */ #define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t) 0x40000000) /** The maximum value for a key identifier chosen by the implementation. */ #define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t) 0x7fffffff) #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) #define MBEDTLS_SVC_KEY_ID_INIT ((psa_key_id_t) 0) #define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) (id) #define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) (0) /** Utility to initialize a key identifier at runtime. * * \param unused Unused parameter. * \param key_id Identifier of the key. */ static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( unsigned int unused, psa_key_id_t key_id) { (void) unused; return key_id; } /** Compare two key identifiers. * * \param id1 First key identifier. * \param id2 Second key identifier. * * \return Non-zero if the two key identifier are equal, zero otherwise. */ static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, mbedtls_svc_key_id_t id2) { return id1 == id2; } /** Check whether a key identifier is null. * * \param key Key identifier. * * \return Non-zero if the key identifier is null, zero otherwise. */ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) { return key == 0; } #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #define MBEDTLS_SVC_KEY_ID_INIT ((mbedtls_svc_key_id_t){ 0, 0 }) #define MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) ((id).MBEDTLS_PRIVATE(key_id)) #define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(id) ((id).MBEDTLS_PRIVATE(owner)) /** Utility to initialize a key identifier at runtime. * * \param owner_id Identifier of the key owner. * \param key_id Identifier of the key. */ static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id) { return (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id, .MBEDTLS_PRIVATE(owner) = owner_id }; } /** Compare two key identifiers. * * \param id1 First key identifier. * \param id2 Second key identifier. * * \return Non-zero if the two key identifier are equal, zero otherwise. */ static inline int mbedtls_svc_key_id_equal(mbedtls_svc_key_id_t id1, mbedtls_svc_key_id_t id2) { return (id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id)) && mbedtls_key_owner_id_equal(id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner)); } /** Check whether a key identifier is null. * * \param key Key identifier. * * \return Non-zero if the key identifier is null, zero otherwise. */ static inline int mbedtls_svc_key_id_is_null(mbedtls_svc_key_id_t key) { return key.MBEDTLS_PRIVATE(key_id) == 0; } #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ /**@}*/ /** \defgroup policy Key policies * @{ */ /* Note that key usage flags are embedded in the * persistent key store, as part of key metadata. As a consequence, they * must not be changed (unless the storage format version changes). */ /** Whether the key may be exported. * * A public key or the public part of a key pair may always be exported * regardless of the value of this permission flag. * * If a key does not have export permission, implementations shall not * allow the key to be exported in plain form from the cryptoprocessor, * whether through psa_export_key() or through a proprietary interface. * The key may however be exportable in a wrapped form, i.e. in a form * where it is encrypted by another key. */ #define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t) 0x00000001) /** Whether the key may be copied. * * This flag allows the use of psa_copy_key() to make a copy of the key * with the same policy or a more restrictive policy. * * For lifetimes for which the key is located in a secure element which * enforce the non-exportability of keys, copying a key outside the secure * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. * Copying the key inside the secure element is permitted with just * #PSA_KEY_USAGE_COPY if the secure element supports it. * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY * is sufficient to permit the copy. */ #define PSA_KEY_USAGE_COPY ((psa_key_usage_t) 0x00000002) /** Whether the key may be used to encrypt a message. * * This flag allows the key to be used for a symmetric encryption operation, * for an AEAD encryption-and-authentication operation, * or for an asymmetric encryption operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t) 0x00000100) /** Whether the key may be used to decrypt a message. * * This flag allows the key to be used for a symmetric decryption operation, * for an AEAD decryption-and-verification operation, * or for an asymmetric decryption operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t) 0x00000200) /** Whether the key may be used to sign a message. * * This flag allows the key to be used for a MAC calculation operation or for * an asymmetric message signature operation, if otherwise permitted by the * key’s type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_SIGN_MESSAGE ((psa_key_usage_t) 0x00000400) /** Whether the key may be used to verify a message. * * This flag allows the key to be used for a MAC verification operation or for * an asymmetric message signature verification operation, if otherwise * permitted by the key’s type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_VERIFY_MESSAGE ((psa_key_usage_t) 0x00000800) /** Whether the key may be used to sign a message. * * This flag allows the key to be used for a MAC calculation operation * or for an asymmetric signature operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t) 0x00001000) /** Whether the key may be used to verify a message signature. * * This flag allows the key to be used for a MAC verification operation * or for an asymmetric signature verification operation, * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t) 0x00002000) /** Whether the key may be used to derive other keys or produce a password * hash. * * This flag allows the key to be used for a key derivation operation or for * a key agreement operation, if otherwise permitted by the key's type and * policy. * * If this flag is present on all keys used in calls to * psa_key_derivation_input_key() for a key derivation operation, then it * permits calling psa_key_derivation_output_bytes() or * psa_key_derivation_output_key() at the end of the operation. */ #define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t) 0x00004000) /** Whether the key may be used to verify the result of a key derivation, * including password hashing. * * This flag allows the key to be used: * * This flag allows the key to be used in a key derivation operation, if * otherwise permitted by the key's type and policy. * * If this flag is present on all keys used in calls to * psa_key_derivation_input_key() for a key derivation operation, then it * permits calling psa_key_derivation_verify_bytes() or * psa_key_derivation_verify_key() at the end of the operation. */ #define PSA_KEY_USAGE_VERIFY_DERIVATION ((psa_key_usage_t) 0x00008000) /**@}*/ /** \defgroup derivation Key derivation * @{ */ /* Key input steps are not embedded in the persistent storage, so you can * change them if needed: it's only an ABI change. */ /** A secret input for key derivation. * * This should be a key of type #PSA_KEY_TYPE_DERIVE * (passed to psa_key_derivation_input_key()) * or the shared secret resulting from a key agreement * (obtained via psa_key_derivation_key_agreement()). * * The secret can also be a direct input (passed to * key_derivation_input_bytes()). In this case, the derivation operation * may not be used to derive keys: the operation will only allow * psa_key_derivation_output_bytes(), * psa_key_derivation_verify_bytes(), or * psa_key_derivation_verify_key(), but not * psa_key_derivation_output_key(). */ #define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t) 0x0101) /** A low-entropy secret input for password hashing / key stretching. * * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to * psa_key_derivation_input_key()) or a direct input (passed to * psa_key_derivation_input_bytes()) that is a password or passphrase. It can * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or * the shared secret resulting from a key agreement. * * The secret can also be a direct input (passed to * key_derivation_input_bytes()). In this case, the derivation operation * may not be used to derive keys: the operation will only allow * psa_key_derivation_output_bytes(), * psa_key_derivation_verify_bytes(), or * psa_key_derivation_verify_key(), but not * psa_key_derivation_output_key(). */ #define PSA_KEY_DERIVATION_INPUT_PASSWORD ((psa_key_derivation_step_t) 0x0102) /** A high-entropy additional secret input for key derivation. * * This is typically the shared secret resulting from a key agreement obtained * via `psa_key_derivation_key_agreement()`. It may alternatively be a key of * type `PSA_KEY_TYPE_DERIVE` passed to `psa_key_derivation_input_key()`, or * a direct input passed to `psa_key_derivation_input_bytes()`. */ #define PSA_KEY_DERIVATION_INPUT_OTHER_SECRET \ ((psa_key_derivation_step_t) 0x0103) /** A label for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. */ #define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t) 0x0201) /** A salt for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or * #PSA_KEY_TYPE_PEPPER. */ #define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t) 0x0202) /** An information string for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. */ #define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t) 0x0203) /** A seed for key derivation. * * This should be a direct input. * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. */ #define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t) 0x0204) /** A cost parameter for password hashing / key stretching. * * This must be a direct input, passed to psa_key_derivation_input_integer(). */ #define PSA_KEY_DERIVATION_INPUT_COST ((psa_key_derivation_step_t) 0x0205) /**@}*/ /** \defgroup helper_macros Helper macros * @{ */ /* Helper macros */ /** Check if two AEAD algorithm identifiers refer to the same AEAD algorithm * regardless of the tag length they encode. * * \param aead_alg_1 An AEAD algorithm identifier. * \param aead_alg_2 An AEAD algorithm identifier. * * \return 1 if both identifiers refer to the same AEAD algorithm, * 0 otherwise. * Unspecified if neither \p aead_alg_1 nor \p aead_alg_2 are * a supported AEAD algorithm. */ #define MBEDTLS_PSA_ALG_AEAD_EQUAL(aead_alg_1, aead_alg_2) \ (!(((aead_alg_1) ^ (aead_alg_2)) & \ ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG))) /**@}*/ /**@}*/ /** \defgroup interruptible Interruptible operations * @{ */ /** Maximum value for use with \c psa_interruptible_set_max_ops() to determine * the maximum number of ops allowed to be executed by an interruptible * function in a single call. */ #define PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED UINT32_MAX /**@}*/ #endif /* PSA_CRYPTO_VALUES_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/000077500000000000000000000000001464416617300213345ustar00rootroot00000000000000optee_os-4.3.0/lib/libmbedtls/mbedtls/library/aes.c000066400000000000000000002317161464416617300222620ustar00rootroot00000000000000/* * FIPS-197 compliant AES implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. * * https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf */ #include "common.h" #if defined(MBEDTLS_AES_C) #include #include "mbedtls/aes.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #if !((defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_AESCE_C)) || \ (defined(MBEDTLS_ARCH_IS_X64) && defined(MBEDTLS_AESNI_C)) || \ (defined(MBEDTLS_ARCH_IS_X86) && defined(MBEDTLS_AESNI_C))) #error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites" #endif #endif #if defined(MBEDTLS_ARCH_IS_X86) #if defined(MBEDTLS_PADLOCK_C) #if !defined(MBEDTLS_HAVE_ASM) #error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" #endif #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \ "MBEDTLS_PADLOCK_C is set" #endif #endif #endif #if defined(MBEDTLS_PADLOCK_C) #include "padlock.h" #endif #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #endif #if defined(MBEDTLS_AESCE_C) #include "aesce.h" #endif #include "mbedtls/platform.h" #include "ctr.h" /* * This is a convenience shorthand macro to check if we need reverse S-box and * reverse tables. It's private and only defined in this file. */ #if (!defined(MBEDTLS_AES_DECRYPT_ALT) || \ (!defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY))) && \ !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) #define MBEDTLS_AES_NEED_REVERSE_TABLES #endif #if !defined(MBEDTLS_AES_ALT) #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) static int aes_padlock_ace = -1; #endif #if defined(MBEDTLS_AES_ROM_TABLES) /* * Forward S-box */ MBEDTLS_MAYBE_UNUSED static const unsigned char FSb[256] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; /* * Forward tables */ #define FT \ \ V(A5, 63, 63, C6), V(84, 7C, 7C, F8), V(99, 77, 77, EE), V(8D, 7B, 7B, F6), \ V(0D, F2, F2, FF), V(BD, 6B, 6B, D6), V(B1, 6F, 6F, DE), V(54, C5, C5, 91), \ V(50, 30, 30, 60), V(03, 01, 01, 02), V(A9, 67, 67, CE), V(7D, 2B, 2B, 56), \ V(19, FE, FE, E7), V(62, D7, D7, B5), V(E6, AB, AB, 4D), V(9A, 76, 76, EC), \ V(45, CA, CA, 8F), V(9D, 82, 82, 1F), V(40, C9, C9, 89), V(87, 7D, 7D, FA), \ V(15, FA, FA, EF), V(EB, 59, 59, B2), V(C9, 47, 47, 8E), V(0B, F0, F0, FB), \ V(EC, AD, AD, 41), V(67, D4, D4, B3), V(FD, A2, A2, 5F), V(EA, AF, AF, 45), \ V(BF, 9C, 9C, 23), V(F7, A4, A4, 53), V(96, 72, 72, E4), V(5B, C0, C0, 9B), \ V(C2, B7, B7, 75), V(1C, FD, FD, E1), V(AE, 93, 93, 3D), V(6A, 26, 26, 4C), \ V(5A, 36, 36, 6C), V(41, 3F, 3F, 7E), V(02, F7, F7, F5), V(4F, CC, CC, 83), \ V(5C, 34, 34, 68), V(F4, A5, A5, 51), V(34, E5, E5, D1), V(08, F1, F1, F9), \ V(93, 71, 71, E2), V(73, D8, D8, AB), V(53, 31, 31, 62), V(3F, 15, 15, 2A), \ V(0C, 04, 04, 08), V(52, C7, C7, 95), V(65, 23, 23, 46), V(5E, C3, C3, 9D), \ V(28, 18, 18, 30), V(A1, 96, 96, 37), V(0F, 05, 05, 0A), V(B5, 9A, 9A, 2F), \ V(09, 07, 07, 0E), V(36, 12, 12, 24), V(9B, 80, 80, 1B), V(3D, E2, E2, DF), \ V(26, EB, EB, CD), V(69, 27, 27, 4E), V(CD, B2, B2, 7F), V(9F, 75, 75, EA), \ V(1B, 09, 09, 12), V(9E, 83, 83, 1D), V(74, 2C, 2C, 58), V(2E, 1A, 1A, 34), \ V(2D, 1B, 1B, 36), V(B2, 6E, 6E, DC), V(EE, 5A, 5A, B4), V(FB, A0, A0, 5B), \ V(F6, 52, 52, A4), V(4D, 3B, 3B, 76), V(61, D6, D6, B7), V(CE, B3, B3, 7D), \ V(7B, 29, 29, 52), V(3E, E3, E3, DD), V(71, 2F, 2F, 5E), V(97, 84, 84, 13), \ V(F5, 53, 53, A6), V(68, D1, D1, B9), V(00, 00, 00, 00), V(2C, ED, ED, C1), \ V(60, 20, 20, 40), V(1F, FC, FC, E3), V(C8, B1, B1, 79), V(ED, 5B, 5B, B6), \ V(BE, 6A, 6A, D4), V(46, CB, CB, 8D), V(D9, BE, BE, 67), V(4B, 39, 39, 72), \ V(DE, 4A, 4A, 94), V(D4, 4C, 4C, 98), V(E8, 58, 58, B0), V(4A, CF, CF, 85), \ V(6B, D0, D0, BB), V(2A, EF, EF, C5), V(E5, AA, AA, 4F), V(16, FB, FB, ED), \ V(C5, 43, 43, 86), V(D7, 4D, 4D, 9A), V(55, 33, 33, 66), V(94, 85, 85, 11), \ V(CF, 45, 45, 8A), V(10, F9, F9, E9), V(06, 02, 02, 04), V(81, 7F, 7F, FE), \ V(F0, 50, 50, A0), V(44, 3C, 3C, 78), V(BA, 9F, 9F, 25), V(E3, A8, A8, 4B), \ V(F3, 51, 51, A2), V(FE, A3, A3, 5D), V(C0, 40, 40, 80), V(8A, 8F, 8F, 05), \ V(AD, 92, 92, 3F), V(BC, 9D, 9D, 21), V(48, 38, 38, 70), V(04, F5, F5, F1), \ V(DF, BC, BC, 63), V(C1, B6, B6, 77), V(75, DA, DA, AF), V(63, 21, 21, 42), \ V(30, 10, 10, 20), V(1A, FF, FF, E5), V(0E, F3, F3, FD), V(6D, D2, D2, BF), \ V(4C, CD, CD, 81), V(14, 0C, 0C, 18), V(35, 13, 13, 26), V(2F, EC, EC, C3), \ V(E1, 5F, 5F, BE), V(A2, 97, 97, 35), V(CC, 44, 44, 88), V(39, 17, 17, 2E), \ V(57, C4, C4, 93), V(F2, A7, A7, 55), V(82, 7E, 7E, FC), V(47, 3D, 3D, 7A), \ V(AC, 64, 64, C8), V(E7, 5D, 5D, BA), V(2B, 19, 19, 32), V(95, 73, 73, E6), \ V(A0, 60, 60, C0), V(98, 81, 81, 19), V(D1, 4F, 4F, 9E), V(7F, DC, DC, A3), \ V(66, 22, 22, 44), V(7E, 2A, 2A, 54), V(AB, 90, 90, 3B), V(83, 88, 88, 0B), \ V(CA, 46, 46, 8C), V(29, EE, EE, C7), V(D3, B8, B8, 6B), V(3C, 14, 14, 28), \ V(79, DE, DE, A7), V(E2, 5E, 5E, BC), V(1D, 0B, 0B, 16), V(76, DB, DB, AD), \ V(3B, E0, E0, DB), V(56, 32, 32, 64), V(4E, 3A, 3A, 74), V(1E, 0A, 0A, 14), \ V(DB, 49, 49, 92), V(0A, 06, 06, 0C), V(6C, 24, 24, 48), V(E4, 5C, 5C, B8), \ V(5D, C2, C2, 9F), V(6E, D3, D3, BD), V(EF, AC, AC, 43), V(A6, 62, 62, C4), \ V(A8, 91, 91, 39), V(A4, 95, 95, 31), V(37, E4, E4, D3), V(8B, 79, 79, F2), \ V(32, E7, E7, D5), V(43, C8, C8, 8B), V(59, 37, 37, 6E), V(B7, 6D, 6D, DA), \ V(8C, 8D, 8D, 01), V(64, D5, D5, B1), V(D2, 4E, 4E, 9C), V(E0, A9, A9, 49), \ V(B4, 6C, 6C, D8), V(FA, 56, 56, AC), V(07, F4, F4, F3), V(25, EA, EA, CF), \ V(AF, 65, 65, CA), V(8E, 7A, 7A, F4), V(E9, AE, AE, 47), V(18, 08, 08, 10), \ V(D5, BA, BA, 6F), V(88, 78, 78, F0), V(6F, 25, 25, 4A), V(72, 2E, 2E, 5C), \ V(24, 1C, 1C, 38), V(F1, A6, A6, 57), V(C7, B4, B4, 73), V(51, C6, C6, 97), \ V(23, E8, E8, CB), V(7C, DD, DD, A1), V(9C, 74, 74, E8), V(21, 1F, 1F, 3E), \ V(DD, 4B, 4B, 96), V(DC, BD, BD, 61), V(86, 8B, 8B, 0D), V(85, 8A, 8A, 0F), \ V(90, 70, 70, E0), V(42, 3E, 3E, 7C), V(C4, B5, B5, 71), V(AA, 66, 66, CC), \ V(D8, 48, 48, 90), V(05, 03, 03, 06), V(01, F6, F6, F7), V(12, 0E, 0E, 1C), \ V(A3, 61, 61, C2), V(5F, 35, 35, 6A), V(F9, 57, 57, AE), V(D0, B9, B9, 69), \ V(91, 86, 86, 17), V(58, C1, C1, 99), V(27, 1D, 1D, 3A), V(B9, 9E, 9E, 27), \ V(38, E1, E1, D9), V(13, F8, F8, EB), V(B3, 98, 98, 2B), V(33, 11, 11, 22), \ V(BB, 69, 69, D2), V(70, D9, D9, A9), V(89, 8E, 8E, 07), V(A7, 94, 94, 33), \ V(B6, 9B, 9B, 2D), V(22, 1E, 1E, 3C), V(92, 87, 87, 15), V(20, E9, E9, C9), \ V(49, CE, CE, 87), V(FF, 55, 55, AA), V(78, 28, 28, 50), V(7A, DF, DF, A5), \ V(8F, 8C, 8C, 03), V(F8, A1, A1, 59), V(80, 89, 89, 09), V(17, 0D, 0D, 1A), \ V(DA, BF, BF, 65), V(31, E6, E6, D7), V(C6, 42, 42, 84), V(B8, 68, 68, D0), \ V(C3, 41, 41, 82), V(B0, 99, 99, 29), V(77, 2D, 2D, 5A), V(11, 0F, 0F, 1E), \ V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C) #define V(a, b, c, d) 0x##a##b##c##d MBEDTLS_MAYBE_UNUSED static const uint32_t FT0[256] = { FT }; #undef V #define V(a, b, c, d) 0x##b##c##d##a MBEDTLS_MAYBE_UNUSED static const uint32_t FT1[256] = { FT }; #undef V #define V(a, b, c, d) 0x##c##d##a##b MBEDTLS_MAYBE_UNUSED static const uint32_t FT2[256] = { FT }; #undef V #define V(a, b, c, d) 0x##d##a##b##c MBEDTLS_MAYBE_UNUSED static const uint32_t FT3[256] = { FT }; #undef V #undef FT /* * Reverse S-box */ MBEDTLS_MAYBE_UNUSED static const unsigned char RSb[256] = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; /* * Reverse tables */ #define RT \ \ V(50, A7, F4, 51), V(53, 65, 41, 7E), V(C3, A4, 17, 1A), V(96, 5E, 27, 3A), \ V(CB, 6B, AB, 3B), V(F1, 45, 9D, 1F), V(AB, 58, FA, AC), V(93, 03, E3, 4B), \ V(55, FA, 30, 20), V(F6, 6D, 76, AD), V(91, 76, CC, 88), V(25, 4C, 02, F5), \ V(FC, D7, E5, 4F), V(D7, CB, 2A, C5), V(80, 44, 35, 26), V(8F, A3, 62, B5), \ V(49, 5A, B1, DE), V(67, 1B, BA, 25), V(98, 0E, EA, 45), V(E1, C0, FE, 5D), \ V(02, 75, 2F, C3), V(12, F0, 4C, 81), V(A3, 97, 46, 8D), V(C6, F9, D3, 6B), \ V(E7, 5F, 8F, 03), V(95, 9C, 92, 15), V(EB, 7A, 6D, BF), V(DA, 59, 52, 95), \ V(2D, 83, BE, D4), V(D3, 21, 74, 58), V(29, 69, E0, 49), V(44, C8, C9, 8E), \ V(6A, 89, C2, 75), V(78, 79, 8E, F4), V(6B, 3E, 58, 99), V(DD, 71, B9, 27), \ V(B6, 4F, E1, BE), V(17, AD, 88, F0), V(66, AC, 20, C9), V(B4, 3A, CE, 7D), \ V(18, 4A, DF, 63), V(82, 31, 1A, E5), V(60, 33, 51, 97), V(45, 7F, 53, 62), \ V(E0, 77, 64, B1), V(84, AE, 6B, BB), V(1C, A0, 81, FE), V(94, 2B, 08, F9), \ V(58, 68, 48, 70), V(19, FD, 45, 8F), V(87, 6C, DE, 94), V(B7, F8, 7B, 52), \ V(23, D3, 73, AB), V(E2, 02, 4B, 72), V(57, 8F, 1F, E3), V(2A, AB, 55, 66), \ V(07, 28, EB, B2), V(03, C2, B5, 2F), V(9A, 7B, C5, 86), V(A5, 08, 37, D3), \ V(F2, 87, 28, 30), V(B2, A5, BF, 23), V(BA, 6A, 03, 02), V(5C, 82, 16, ED), \ V(2B, 1C, CF, 8A), V(92, B4, 79, A7), V(F0, F2, 07, F3), V(A1, E2, 69, 4E), \ V(CD, F4, DA, 65), V(D5, BE, 05, 06), V(1F, 62, 34, D1), V(8A, FE, A6, C4), \ V(9D, 53, 2E, 34), V(A0, 55, F3, A2), V(32, E1, 8A, 05), V(75, EB, F6, A4), \ V(39, EC, 83, 0B), V(AA, EF, 60, 40), V(06, 9F, 71, 5E), V(51, 10, 6E, BD), \ V(F9, 8A, 21, 3E), V(3D, 06, DD, 96), V(AE, 05, 3E, DD), V(46, BD, E6, 4D), \ V(B5, 8D, 54, 91), V(05, 5D, C4, 71), V(6F, D4, 06, 04), V(FF, 15, 50, 60), \ V(24, FB, 98, 19), V(97, E9, BD, D6), V(CC, 43, 40, 89), V(77, 9E, D9, 67), \ V(BD, 42, E8, B0), V(88, 8B, 89, 07), V(38, 5B, 19, E7), V(DB, EE, C8, 79), \ V(47, 0A, 7C, A1), V(E9, 0F, 42, 7C), V(C9, 1E, 84, F8), V(00, 00, 00, 00), \ V(83, 86, 80, 09), V(48, ED, 2B, 32), V(AC, 70, 11, 1E), V(4E, 72, 5A, 6C), \ V(FB, FF, 0E, FD), V(56, 38, 85, 0F), V(1E, D5, AE, 3D), V(27, 39, 2D, 36), \ V(64, D9, 0F, 0A), V(21, A6, 5C, 68), V(D1, 54, 5B, 9B), V(3A, 2E, 36, 24), \ V(B1, 67, 0A, 0C), V(0F, E7, 57, 93), V(D2, 96, EE, B4), V(9E, 91, 9B, 1B), \ V(4F, C5, C0, 80), V(A2, 20, DC, 61), V(69, 4B, 77, 5A), V(16, 1A, 12, 1C), \ V(0A, BA, 93, E2), V(E5, 2A, A0, C0), V(43, E0, 22, 3C), V(1D, 17, 1B, 12), \ V(0B, 0D, 09, 0E), V(AD, C7, 8B, F2), V(B9, A8, B6, 2D), V(C8, A9, 1E, 14), \ V(85, 19, F1, 57), V(4C, 07, 75, AF), V(BB, DD, 99, EE), V(FD, 60, 7F, A3), \ V(9F, 26, 01, F7), V(BC, F5, 72, 5C), V(C5, 3B, 66, 44), V(34, 7E, FB, 5B), \ V(76, 29, 43, 8B), V(DC, C6, 23, CB), V(68, FC, ED, B6), V(63, F1, E4, B8), \ V(CA, DC, 31, D7), V(10, 85, 63, 42), V(40, 22, 97, 13), V(20, 11, C6, 84), \ V(7D, 24, 4A, 85), V(F8, 3D, BB, D2), V(11, 32, F9, AE), V(6D, A1, 29, C7), \ V(4B, 2F, 9E, 1D), V(F3, 30, B2, DC), V(EC, 52, 86, 0D), V(D0, E3, C1, 77), \ V(6C, 16, B3, 2B), V(99, B9, 70, A9), V(FA, 48, 94, 11), V(22, 64, E9, 47), \ V(C4, 8C, FC, A8), V(1A, 3F, F0, A0), V(D8, 2C, 7D, 56), V(EF, 90, 33, 22), \ V(C7, 4E, 49, 87), V(C1, D1, 38, D9), V(FE, A2, CA, 8C), V(36, 0B, D4, 98), \ V(CF, 81, F5, A6), V(28, DE, 7A, A5), V(26, 8E, B7, DA), V(A4, BF, AD, 3F), \ V(E4, 9D, 3A, 2C), V(0D, 92, 78, 50), V(9B, CC, 5F, 6A), V(62, 46, 7E, 54), \ V(C2, 13, 8D, F6), V(E8, B8, D8, 90), V(5E, F7, 39, 2E), V(F5, AF, C3, 82), \ V(BE, 80, 5D, 9F), V(7C, 93, D0, 69), V(A9, 2D, D5, 6F), V(B3, 12, 25, CF), \ V(3B, 99, AC, C8), V(A7, 7D, 18, 10), V(6E, 63, 9C, E8), V(7B, BB, 3B, DB), \ V(09, 78, 26, CD), V(F4, 18, 59, 6E), V(01, B7, 9A, EC), V(A8, 9A, 4F, 83), \ V(65, 6E, 95, E6), V(7E, E6, FF, AA), V(08, CF, BC, 21), V(E6, E8, 15, EF), \ V(D9, 9B, E7, BA), V(CE, 36, 6F, 4A), V(D4, 09, 9F, EA), V(D6, 7C, B0, 29), \ V(AF, B2, A4, 31), V(31, 23, 3F, 2A), V(30, 94, A5, C6), V(C0, 66, A2, 35), \ V(37, BC, 4E, 74), V(A6, CA, 82, FC), V(B0, D0, 90, E0), V(15, D8, A7, 33), \ V(4A, 98, 04, F1), V(F7, DA, EC, 41), V(0E, 50, CD, 7F), V(2F, F6, 91, 17), \ V(8D, D6, 4D, 76), V(4D, B0, EF, 43), V(54, 4D, AA, CC), V(DF, 04, 96, E4), \ V(E3, B5, D1, 9E), V(1B, 88, 6A, 4C), V(B8, 1F, 2C, C1), V(7F, 51, 65, 46), \ V(04, EA, 5E, 9D), V(5D, 35, 8C, 01), V(73, 74, 87, FA), V(2E, 41, 0B, FB), \ V(5A, 1D, 67, B3), V(52, D2, DB, 92), V(33, 56, 10, E9), V(13, 47, D6, 6D), \ V(8C, 61, D7, 9A), V(7A, 0C, A1, 37), V(8E, 14, F8, 59), V(89, 3C, 13, EB), \ V(EE, 27, A9, CE), V(35, C9, 61, B7), V(ED, E5, 1C, E1), V(3C, B1, 47, 7A), \ V(59, DF, D2, 9C), V(3F, 73, F2, 55), V(79, CE, 14, 18), V(BF, 37, C7, 73), \ V(EA, CD, F7, 53), V(5B, AA, FD, 5F), V(14, 6F, 3D, DF), V(86, DB, 44, 78), \ V(81, F3, AF, CA), V(3E, C4, 68, B9), V(2C, 34, 24, 38), V(5F, 40, A3, C2), \ V(72, C3, 1D, 16), V(0C, 25, E2, BC), V(8B, 49, 3C, 28), V(41, 95, 0D, FF), \ V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \ V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0) #define V(a, b, c, d) 0x##a##b##c##d MBEDTLS_MAYBE_UNUSED static const uint32_t RT0[256] = { RT }; #undef V #define V(a, b, c, d) 0x##b##c##d##a MBEDTLS_MAYBE_UNUSED static const uint32_t RT1[256] = { RT }; #undef V #define V(a, b, c, d) 0x##c##d##a##b MBEDTLS_MAYBE_UNUSED static const uint32_t RT2[256] = { RT }; #undef V #define V(a, b, c, d) 0x##d##a##b##c MBEDTLS_MAYBE_UNUSED static const uint32_t RT3[256] = { RT }; #undef V #undef RT /* * Round constants */ MBEDTLS_MAYBE_UNUSED static const uint32_t round_constants[10] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x0000001B, 0x00000036 }; #else /* MBEDTLS_AES_ROM_TABLES */ /* * Forward S-box & tables */ MBEDTLS_MAYBE_UNUSED static unsigned char FSb[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT0[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT1[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT2[256]; MBEDTLS_MAYBE_UNUSED static uint32_t FT3[256]; /* * Reverse S-box & tables */ MBEDTLS_MAYBE_UNUSED static unsigned char RSb[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT0[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT1[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT2[256]; MBEDTLS_MAYBE_UNUSED static uint32_t RT3[256]; /* * Round constants */ MBEDTLS_MAYBE_UNUSED static uint32_t round_constants[10]; /* * Tables generation code */ #define ROTL8(x) (((x) << 8) & 0xFFFFFFFF) | ((x) >> 24) #define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00)) #define MUL(x, y) (((x) && (y)) ? pow[(log[(x)]+log[(y)]) % 255] : 0) MBEDTLS_MAYBE_UNUSED static int aes_init_done = 0; MBEDTLS_MAYBE_UNUSED static void aes_gen_tables(void) { int i; uint8_t x, y, z; uint8_t pow[256]; uint8_t log[256]; /* * compute pow and log tables over GF(2^8) */ for (i = 0, x = 1; i < 256; i++) { pow[i] = x; log[x] = (uint8_t) i; x ^= XTIME(x); } /* * calculate the round constants */ for (i = 0, x = 1; i < 10; i++) { round_constants[i] = x; x = XTIME(x); } /* * generate the forward and reverse S-boxes */ FSb[0x00] = 0x63; #if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) RSb[0x63] = 0x00; #endif for (i = 1; i < 256; i++) { x = pow[255 - log[i]]; y = x; y = (y << 1) | (y >> 7); x ^= y; y = (y << 1) | (y >> 7); x ^= y; y = (y << 1) | (y >> 7); x ^= y; y = (y << 1) | (y >> 7); x ^= y ^ 0x63; FSb[i] = x; #if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) RSb[x] = (unsigned char) i; #endif } /* * generate the forward and reverse tables */ for (i = 0; i < 256; i++) { x = FSb[i]; y = XTIME(x); z = y ^ x; FT0[i] = ((uint32_t) y) ^ ((uint32_t) x << 8) ^ ((uint32_t) x << 16) ^ ((uint32_t) z << 24); #if !defined(MBEDTLS_AES_FEWER_TABLES) FT1[i] = ROTL8(FT0[i]); FT2[i] = ROTL8(FT1[i]); FT3[i] = ROTL8(FT2[i]); #endif /* !MBEDTLS_AES_FEWER_TABLES */ #if defined(MBEDTLS_AES_NEED_REVERSE_TABLES) x = RSb[i]; RT0[i] = ((uint32_t) MUL(0x0E, x)) ^ ((uint32_t) MUL(0x09, x) << 8) ^ ((uint32_t) MUL(0x0D, x) << 16) ^ ((uint32_t) MUL(0x0B, x) << 24); #if !defined(MBEDTLS_AES_FEWER_TABLES) RT1[i] = ROTL8(RT0[i]); RT2[i] = ROTL8(RT1[i]); RT3[i] = ROTL8(RT2[i]); #endif /* !MBEDTLS_AES_FEWER_TABLES */ #endif /* MBEDTLS_AES_NEED_REVERSE_TABLES */ } } #undef ROTL8 #endif /* MBEDTLS_AES_ROM_TABLES */ #if defined(MBEDTLS_AES_FEWER_TABLES) #define ROTL8(x) ((uint32_t) ((x) << 8) + (uint32_t) ((x) >> 24)) #define ROTL16(x) ((uint32_t) ((x) << 16) + (uint32_t) ((x) >> 16)) #define ROTL24(x) ((uint32_t) ((x) << 24) + (uint32_t) ((x) >> 8)) #define AES_RT0(idx) RT0[idx] #define AES_RT1(idx) ROTL8(RT0[idx]) #define AES_RT2(idx) ROTL16(RT0[idx]) #define AES_RT3(idx) ROTL24(RT0[idx]) #define AES_FT0(idx) FT0[idx] #define AES_FT1(idx) ROTL8(FT0[idx]) #define AES_FT2(idx) ROTL16(FT0[idx]) #define AES_FT3(idx) ROTL24(FT0[idx]) #else /* MBEDTLS_AES_FEWER_TABLES */ #define AES_RT0(idx) RT0[idx] #define AES_RT1(idx) RT1[idx] #define AES_RT2(idx) RT2[idx] #define AES_RT3(idx) RT3[idx] #define AES_FT0(idx) FT0[idx] #define AES_FT1(idx) FT1[idx] #define AES_FT2(idx) FT2[idx] #define AES_FT3(idx) FT3[idx] #endif /* MBEDTLS_AES_FEWER_TABLES */ void mbedtls_aes_init(mbedtls_aes_context *ctx) { memset(ctx, 0, sizeof(mbedtls_aes_context)); } void mbedtls_aes_free(mbedtls_aes_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aes_context)); } #if defined(MBEDTLS_CIPHER_MODE_XTS) void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx) { mbedtls_aes_init(&ctx->crypt); mbedtls_aes_init(&ctx->tweak); } void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) { if (ctx == NULL) { return; } mbedtls_aes_free(&ctx->crypt); mbedtls_aes_free(&ctx->tweak); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ /* Some implementations need the round keys to be aligned. * Return an offset to be added to buf, such that (buf + offset) is * correctly aligned. * Note that the offset is in units of elements of buf, i.e. 32-bit words, * i.e. an offset of 1 means 4 bytes and so on. */ #if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) || \ (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2) #define MAY_NEED_TO_ALIGN #endif MBEDTLS_MAYBE_UNUSED static unsigned mbedtls_aes_rk_offset(uint32_t *buf) { #if defined(MAY_NEED_TO_ALIGN) int align_16_bytes = 0; #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (aes_padlock_ace == -1) { aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); } if (aes_padlock_ace) { align_16_bytes = 1; } #endif #if defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2 if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { align_16_bytes = 1; } #endif if (align_16_bytes) { /* These implementations needs 16-byte alignment * for the round key array. */ unsigned delta = ((uintptr_t) buf & 0x0000000fU) / 4; if (delta == 0) { return 0; } else { return 4 - delta; // 16 bytes = 4 uint32_t } } #else /* MAY_NEED_TO_ALIGN */ (void) buf; #endif /* MAY_NEED_TO_ALIGN */ return 0; } /* * AES key schedule (encryption) */ #if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { uint32_t *RK; switch (keybits) { case 128: ctx->nr = 10; break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 192: ctx->nr = 12; break; case 256: ctx->nr = 14; break; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } #if !defined(MBEDTLS_AES_ROM_TABLES) if (aes_init_done == 0) { aes_gen_tables(); aes_init_done = 1; } #endif ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); RK = ctx->buf + ctx->rk_offset; #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { return mbedtls_aesni_setkey_enc((unsigned char *) RK, key, keybits); } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits); } #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) for (unsigned int i = 0; i < (keybits >> 5); i++) { RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2); } switch (ctx->nr) { case 10: for (unsigned int i = 0; i < 10; i++, RK += 4) { RK[4] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[3])] << 24); RK[5] = RK[1] ^ RK[4]; RK[6] = RK[2] ^ RK[5]; RK[7] = RK[3] ^ RK[6]; } break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 12: for (unsigned int i = 0; i < 8; i++, RK += 6) { RK[6] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[5])] << 24); RK[7] = RK[1] ^ RK[6]; RK[8] = RK[2] ^ RK[7]; RK[9] = RK[3] ^ RK[8]; RK[10] = RK[4] ^ RK[9]; RK[11] = RK[5] ^ RK[10]; } break; case 14: for (unsigned int i = 0; i < 7; i++, RK += 8) { RK[8] = RK[0] ^ round_constants[i] ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[7])] << 24); RK[9] = RK[1] ^ RK[8]; RK[10] = RK[2] ^ RK[9]; RK[11] = RK[3] ^ RK[10]; RK[12] = RK[4] ^ ((uint32_t) FSb[MBEDTLS_BYTE_0(RK[11])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[11])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[11])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[11])] << 24); RK[13] = RK[5] ^ RK[12]; RK[14] = RK[6] ^ RK[13]; RK[15] = RK[7] ^ RK[14]; } break; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ } return 0; #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ } #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ /* * AES key schedule (decryption) */ #if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits) { #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) uint32_t *SK; #endif int ret; mbedtls_aes_context cty; uint32_t *RK; mbedtls_aes_init(&cty); ctx->rk_offset = mbedtls_aes_rk_offset(ctx->buf); RK = ctx->buf + ctx->rk_offset; /* Also checks keybits */ if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) { goto exit; } ctx->nr = cty.nr; #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { mbedtls_aesni_inverse_key((unsigned char *) RK, (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr); goto exit; } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { mbedtls_aesce_inverse_key( (unsigned char *) RK, (const unsigned char *) (cty.buf + cty.rk_offset), ctx->nr); goto exit; } #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) SK = cty.buf + cty.rk_offset + cty.nr * 4; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; SK -= 8; for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) { for (int j = 0; j < 4; j++, SK++) { *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^ AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^ AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^ AES_RT3(FSb[MBEDTLS_BYTE_3(*SK)]); } } *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ exit: mbedtls_aes_free(&cty); return ret; } #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int mbedtls_aes_xts_decode_keys(const unsigned char *key, unsigned int keybits, const unsigned char **key1, unsigned int *key1bits, const unsigned char **key2, unsigned int *key2bits) { const unsigned int half_keybits = keybits / 2; const unsigned int half_keybytes = half_keybits / 8; switch (keybits) { case 256: break; case 512: break; default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } *key1bits = half_keybits; *key2bits = half_keybits; *key1 = &key[0]; *key2 = &key[half_keybytes]; return 0; } int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *key1, *key2; unsigned int key1bits, key2bits; ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits); if (ret != 0) { return ret; } /* Set the tweak key. Always set tweak key for the encryption mode. */ ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); if (ret != 0) { return ret; } /* Set crypt key for encryption. */ return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits); } int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *key1, *key2; unsigned int key1bits, key2bits; ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits); if (ret != 0) { return ret; } /* Set the tweak key. Always set tweak key for encryption. */ ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); if (ret != 0) { return ret; } /* Set crypt key for decryption. */ return mbedtls_aes_setkey_dec(&ctx->crypt, key1, key1bits); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \ do \ { \ (X0) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y0)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y1)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y2)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y3)); \ \ (X1) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y1)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y2)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y3)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y0)); \ \ (X2) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y2)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y3)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y0)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y1)); \ \ (X3) = *RK++ ^ AES_FT0(MBEDTLS_BYTE_0(Y3)) ^ \ AES_FT1(MBEDTLS_BYTE_1(Y0)) ^ \ AES_FT2(MBEDTLS_BYTE_2(Y1)) ^ \ AES_FT3(MBEDTLS_BYTE_3(Y2)); \ } while (0) #define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \ do \ { \ (X0) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y0)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y3)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y2)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y1)); \ \ (X1) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y1)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y0)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y3)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y2)); \ \ (X2) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y2)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y1)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y0)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y3)); \ \ (X3) = *RK++ ^ AES_RT0(MBEDTLS_BYTE_0(Y3)) ^ \ AES_RT1(MBEDTLS_BYTE_1(Y2)) ^ \ AES_RT2(MBEDTLS_BYTE_2(Y1)) ^ \ AES_RT3(MBEDTLS_BYTE_3(Y0)); \ } while (0) /* * AES-ECB block encryption */ #if !defined(MBEDTLS_AES_ENCRYPT_ALT) int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { int i; uint32_t *RK = ctx->buf + ctx->rk_offset; struct { uint32_t X[4]; uint32_t Y[4]; } t; t.X[0] = MBEDTLS_GET_UINT32_LE(input, 0); t.X[0] ^= *RK++; t.X[1] = MBEDTLS_GET_UINT32_LE(input, 4); t.X[1] ^= *RK++; t.X[2] = MBEDTLS_GET_UINT32_LE(input, 8); t.X[2] ^= *RK++; t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++; for (i = (ctx->nr >> 1) - 1; i > 0; i--) { AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); AES_FROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]); } AES_FROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); t.X[0] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[0])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[1])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[3])] << 24); t.X[1] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[1])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[2])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[0])] << 24); t.X[2] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[2])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[3])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[1])] << 24); t.X[3] = *RK++ ^ \ ((uint32_t) FSb[MBEDTLS_BYTE_0(t.Y[3])]) ^ ((uint32_t) FSb[MBEDTLS_BYTE_1(t.Y[0])] << 8) ^ ((uint32_t) FSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^ ((uint32_t) FSb[MBEDTLS_BYTE_3(t.Y[2])] << 24); MBEDTLS_PUT_UINT32_LE(t.X[0], output, 0); MBEDTLS_PUT_UINT32_LE(t.X[1], output, 4); MBEDTLS_PUT_UINT32_LE(t.X[2], output, 8); MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12); mbedtls_platform_zeroize(&t, sizeof(t)); return 0; } #endif /* !MBEDTLS_AES_ENCRYPT_ALT */ /* * AES-ECB block decryption */ #if !defined(MBEDTLS_AES_DECRYPT_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16]) { int i; uint32_t *RK = ctx->buf + ctx->rk_offset; struct { uint32_t X[4]; uint32_t Y[4]; } t; t.X[0] = MBEDTLS_GET_UINT32_LE(input, 0); t.X[0] ^= *RK++; t.X[1] = MBEDTLS_GET_UINT32_LE(input, 4); t.X[1] ^= *RK++; t.X[2] = MBEDTLS_GET_UINT32_LE(input, 8); t.X[2] ^= *RK++; t.X[3] = MBEDTLS_GET_UINT32_LE(input, 12); t.X[3] ^= *RK++; for (i = (ctx->nr >> 1) - 1; i > 0; i--) { AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); AES_RROUND(t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3]); } AES_RROUND(t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3]); t.X[0] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[0])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[3])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[2])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[1])] << 24); t.X[1] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[1])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[0])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[3])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[2])] << 24); t.X[2] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[2])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[1])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[0])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[3])] << 24); t.X[3] = *RK++ ^ \ ((uint32_t) RSb[MBEDTLS_BYTE_0(t.Y[3])]) ^ ((uint32_t) RSb[MBEDTLS_BYTE_1(t.Y[2])] << 8) ^ ((uint32_t) RSb[MBEDTLS_BYTE_2(t.Y[1])] << 16) ^ ((uint32_t) RSb[MBEDTLS_BYTE_3(t.Y[0])] << 24); MBEDTLS_PUT_UINT32_LE(t.X[0], output, 0); MBEDTLS_PUT_UINT32_LE(t.X[1], output, 4); MBEDTLS_PUT_UINT32_LE(t.X[2], output, 8); MBEDTLS_PUT_UINT32_LE(t.X[3], output, 12); mbedtls_platform_zeroize(&t, sizeof(t)); return 0; } #endif /* !MBEDTLS_AES_DECRYPT_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* VIA Padlock and our intrinsics-based implementation of AESNI require * the round keys to be aligned on a 16-byte boundary. We take care of this * before creating them, but the AES context may have moved (this can happen * if the library is called from a language with managed memory), and in later * calls it might have a different alignment with respect to 16-byte memory. * So we may need to realign. */ MBEDTLS_MAYBE_UNUSED static void aes_maybe_realign(mbedtls_aes_context *ctx) { unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf); if (new_offset != ctx->rk_offset) { memmove(ctx->buf + new_offset, // new address ctx->buf + ctx->rk_offset, // current address (ctx->nr + 1) * 16); // number of round keys * bytes per rk ctx->rk_offset = new_offset; } } /* * AES-ECB block encryption/decryption */ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } #if defined(MAY_NEED_TO_ALIGN) aes_maybe_realign(ctx); #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { return mbedtls_aesni_crypt_ecb(ctx, mode, input, output); } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { return mbedtls_aesce_crypt_ecb(ctx, mode, input, output); } #endif #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (aes_padlock_ace > 0) { return mbedtls_padlock_xcryptecb(ctx, mode, input, output); } #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { return mbedtls_internal_aes_decrypt(ctx, input, output); } else #endif { return mbedtls_internal_aes_encrypt(ctx, input, output); } #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * AES-CBC buffer encryption/decryption */ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[16]; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } /* Nothing to do if length is zero. */ if (length == 0) { return 0; } if (length % 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (aes_padlock_ace > 0) { if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) { return 0; } // If padlock data misaligned, we just fall back to // unaccelerated mode // } #endif const unsigned char *ivp = iv; if (mode == MBEDTLS_AES_DECRYPT) { while (length > 0) { memcpy(temp, input, 16); ret = mbedtls_aes_crypt_ecb(ctx, mode, input, output); if (ret != 0) { goto exit; } /* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on * the result for the next block in CBC, and the cost of transferring that data from * NEON registers, NEON is slower on aarch64. */ mbedtls_xor_no_simd(output, output, iv, 16); memcpy(iv, temp, 16); input += 16; output += 16; length -= 16; } } else { while (length > 0) { mbedtls_xor_no_simd(output, input, ivp, 16); ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output); if (ret != 0) { goto exit; } ivp = output; input += 16; output += 16; length -= 16; } memcpy(iv, ivp, 16); } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_XTS) typedef unsigned char mbedtls_be128[16]; /* * GF(2^128) multiplication function * * This function multiplies a field element by x in the polynomial field * representation. It uses 64-bit word operations to gain speed but compensates * for machine endianness and hence works correctly on both big and little * endian machines. */ #if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C) MBEDTLS_OPTIMIZE_FOR_PERFORMANCE #endif static inline void mbedtls_gf128mul_x_ble(unsigned char r[16], const unsigned char x[16]) { uint64_t a, b, ra, rb; a = MBEDTLS_GET_UINT64_LE(x, 0); b = MBEDTLS_GET_UINT64_LE(x, 8); ra = (a << 1) ^ 0x0087 >> (8 - ((b >> 63) << 3)); rb = (a >> 63) | (b << 1); MBEDTLS_PUT_UINT64_LE(ra, r, 0); MBEDTLS_PUT_UINT64_LE(rb, r, 8); } /* * AES-XTS buffer encryption/decryption * * Use of MBEDTLS_OPTIMIZE_FOR_PERFORMANCE here and for mbedtls_gf128mul_x_ble() * is a 3x performance improvement for gcc -Os, if we have hardware AES support. */ #if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C) MBEDTLS_OPTIMIZE_FOR_PERFORMANCE #endif int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t blocks = length / 16; size_t leftover = length % 16; unsigned char tweak[16]; unsigned char prev_tweak[16]; unsigned char tmp[16]; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } /* Data units must be at least 16 bytes long. */ if (length < 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ if (length > (1 << 20) * 16) { return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; } /* Compute the tweak. */ ret = mbedtls_aes_crypt_ecb(&ctx->tweak, MBEDTLS_AES_ENCRYPT, data_unit, tweak); if (ret != 0) { return ret; } while (blocks--) { if (MBEDTLS_UNLIKELY(leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0)) { /* We are on the last block in a decrypt operation that has * leftover bytes, so we need to use the next tweak for this block, * and this tweak for the leftover bytes. Save the current tweak for * the leftovers and then update the current tweak for use on this, * the last full block. */ memcpy(prev_tweak, tweak, sizeof(tweak)); mbedtls_gf128mul_x_ble(tweak, tweak); } mbedtls_xor(tmp, input, tweak, 16); ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); if (ret != 0) { return ret; } mbedtls_xor(output, tmp, tweak, 16); /* Update the tweak for the next block. */ mbedtls_gf128mul_x_ble(tweak, tweak); output += 16; input += 16; } if (leftover) { /* If we are on the leftover bytes in a decrypt operation, we need to * use the previous tweak for these bytes (as saved in prev_tweak). */ unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; /* We are now on the final part of the data unit, which doesn't divide * evenly by 16. It's time for ciphertext stealing. */ size_t i; unsigned char *prev_output = output - 16; /* Copy ciphertext bytes from the previous block to our output for each * byte of ciphertext we won't steal. */ for (i = 0; i < leftover; i++) { output[i] = prev_output[i]; } /* Copy the remainder of the input for this final round. */ mbedtls_xor(tmp, input, t, leftover); /* Copy ciphertext bytes from the previous block for input in this * round. */ mbedtls_xor(tmp + i, prev_output + i, t + i, 16 - i); ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); if (ret != 0) { return ret; } /* Write the result back to the previous block, overriding the previous * output we copied. */ mbedtls_xor(prev_output, tmp, t, 16); } return 0; } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 buffer encryption/decryption */ int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } n = *iv_off; if (n > 15) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } if (mode == MBEDTLS_AES_DECRYPT) { while (length--) { if (n == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } } c = *input++; *output++ = (unsigned char) (c ^ iv[n]); iv[n] = (unsigned char) c; n = (n + 1) & 0x0F; } } else { while (length--) { if (n == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } } iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); n = (n + 1) & 0x0F; } } *iv_off = n; ret = 0; exit: return ret; } /* * AES-CFB8 buffer encryption/decryption */ int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char c; unsigned char ov[17]; if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } while (length--) { memcpy(ov, iv, 16); ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } if (mode == MBEDTLS_AES_DECRYPT) { ov[16] = *input; } c = *output++ = (unsigned char) (iv[0] ^ *input++); if (mode == MBEDTLS_AES_ENCRYPT) { ov[16] = c; } memcpy(iv, ov + 1, 16); } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * AES-OFB (Output Feedback Mode) buffer encryption/decryption */ int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ret = 0; size_t n; n = *iv_off; if (n > 15) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } while (length--) { if (n == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); if (ret != 0) { goto exit; } } *output++ = *input++ ^ iv[n]; n = (n + 1) & 0x0F; } *iv_off = n; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR buffer encryption/decryption */ int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t offset = *nc_off; if (offset > 0x0F) { return MBEDTLS_ERR_AES_BAD_INPUT_DATA; } for (size_t i = 0; i < length;) { size_t n = 16; if (offset == 0) { ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block); if (ret != 0) { goto exit; } mbedtls_ctr_increment_counter(nonce_counter); } else { n -= offset; } if (n > (length - i)) { n = (length - i); } mbedtls_xor(&output[i], &input[i], &stream_block[offset], n); // offset might be non-zero for the last block, but in that case, we don't use it again offset = 0; i += n; } // capture offset for future resumption *nc_off = (*nc_off + length) % 16; ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* !MBEDTLS_AES_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * AES test vectors from: * * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static const unsigned char aes_test_ecb_dec[][16] = { { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } #endif }; #endif static const unsigned char aes_test_ecb_enc[][16] = { { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } #endif }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const unsigned char aes_test_cbc_dec[][16] = { { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } #endif }; static const unsigned char aes_test_cbc_enc[][16] = { { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } #endif }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 test vectors from: * * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ static const unsigned char aes_test_cfb128_key[][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } #endif }; static const unsigned char aes_test_cfb128_iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; static const unsigned char aes_test_cfb128_pt[64] = { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }; static const unsigned char aes_test_cfb128_ct[][64] = { { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } #endif }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * AES-OFB test vectors from: * * https://csrc.nist.gov/publications/detail/sp/800-38a/final */ static const unsigned char aes_test_ofb_key[][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } #endif }; static const unsigned char aes_test_ofb_iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; static const unsigned char aes_test_ofb_pt[64] = { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }; static const unsigned char aes_test_ofb_ct[][64] = { { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } #endif }; #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * AES-CTR test vectors from: * * http://www.faqs.org/rfcs/rfc3686.html */ static const unsigned char aes_test_ctr_key[][16] = { { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } }; static const unsigned char aes_test_ctr_nonce_counter[][16] = { { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } }; static const unsigned char aes_test_ctr_pt[][48] = { { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23 } }; static const unsigned char aes_test_ctr_ct[][48] = { { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, 0x25, 0xB2, 0x07, 0x2F } }; static const int aes_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /* * AES-XTS test vectors from: * * IEEE P1619/D16 Annex B * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) */ static const unsigned char aes_test_xts_key[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, }; static const unsigned char aes_test_xts_pt32[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, }; static const unsigned char aes_test_xts_ct32[][32] = { { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, }; static const unsigned char aes_test_xts_data_unit[][16] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; #endif /* MBEDTLS_CIPHER_MODE_XTS */ /* * Checkup routine */ int mbedtls_aes_self_test(int verbose) { int ret = 0, i, j, u, mode; unsigned int keybits; unsigned char key[32]; unsigned char buf[64]; const unsigned char *aes_tests; #if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_OFB) unsigned char iv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_OFB) size_t offset; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) int len; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif mbedtls_aes_context ctx; memset(key, 0, 32); mbedtls_aes_init(&ctx); if (verbose != 0) { #if defined(MBEDTLS_AES_ALT) mbedtls_printf(" AES note: alternative implementation.\n"); #else /* MBEDTLS_AES_ALT */ #if defined(MBEDTLS_AESNI_HAVE_CODE) #if MBEDTLS_AESNI_HAVE_CODE == 1 mbedtls_printf(" AES note: AESNI code present (assembly implementation).\n"); #elif MBEDTLS_AESNI_HAVE_CODE == 2 mbedtls_printf(" AES note: AESNI code present (intrinsics implementation).\n"); #else #error "Unrecognised value for MBEDTLS_AESNI_HAVE_CODE" #endif if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { mbedtls_printf(" AES note: using AESNI.\n"); } else #endif #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) { mbedtls_printf(" AES note: using VIA Padlock.\n"); } else #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { mbedtls_printf(" AES note: using AESCE.\n"); } else #endif { #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) mbedtls_printf(" AES note: built-in implementation.\n"); #endif } #endif /* MBEDTLS_AES_ALT */ } /* * ECB mode */ { static const int num_tests = sizeof(aes_test_ecb_enc) / sizeof(*aes_test_ecb_enc); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-ECB-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { if (verbose != 0) { mbedtls_printf("skipped\n"); } continue; } #endif memset(buf, 0, 16); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); aes_tests = aes_test_ecb_dec[u]; } else #endif { ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); aes_tests = aes_test_ecb_enc[u]; } /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } for (j = 0; j < 10000; j++) { ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf); if (ret != 0) { goto exit; } } if (memcmp(buf, aes_tests, 16) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ { static const int num_tests = sizeof(aes_test_cbc_dec) / sizeof(*aes_test_cbc_dec); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-CBC-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memset(iv, 0, 16); memset(prv, 0, 16); memset(buf, 0, 16); if (mode == MBEDTLS_AES_DECRYPT) { ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); aes_tests = aes_test_cbc_dec[u]; } else { ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); aes_tests = aes_test_cbc_enc[u]; } /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } for (j = 0; j < 10000; j++) { if (mode == MBEDTLS_AES_ENCRYPT) { unsigned char tmp[16]; memcpy(tmp, prv, 16); memcpy(prv, buf, 16); memcpy(buf, tmp, 16); } ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf); if (ret != 0) { goto exit; } } if (memcmp(buf, aes_tests, 16) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * CFB128 mode */ { static const int num_tests = sizeof(aes_test_cfb128_key) / sizeof(*aes_test_cfb128_key); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-CFB128-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memcpy(iv, aes_test_cfb128_iv, 16); memcpy(key, aes_test_cfb128_key[u], keybits / 8); offset = 0; ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } if (mode == MBEDTLS_AES_DECRYPT) { memcpy(buf, aes_test_cfb128_ct[u], 64); aes_tests = aes_test_cfb128_pt; } else { memcpy(buf, aes_test_cfb128_pt, 64); aes_tests = aes_test_cfb128_ct[u]; } ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, 64) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) /* * OFB mode */ { static const int num_tests = sizeof(aes_test_ofb_key) / sizeof(*aes_test_ofb_key); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; keybits = 128 + u * 64; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-OFB-%3u (%s): ", keybits, (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memcpy(iv, aes_test_ofb_iv, 16); memcpy(key, aes_test_ofb_key[u], keybits / 8); offset = 0; ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { mbedtls_printf("skipped\n"); continue; } else if (ret != 0) { goto exit; } if (mode == MBEDTLS_AES_DECRYPT) { memcpy(buf, aes_test_ofb_ct[u], 64); aes_tests = aes_test_ofb_pt; } else { memcpy(buf, aes_test_ofb_pt, 64); aes_tests = aes_test_ofb_ct[u]; } ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, 64) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode */ { static const int num_tests = sizeof(aes_test_ctr_key) / sizeof(*aes_test_ctr_key); for (i = 0; i < num_tests << 1; i++) { u = i >> 1; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-CTR-128 (%s): ", (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16); memcpy(key, aes_test_ctr_key[u], 16); offset = 0; if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) { goto exit; } len = aes_test_ctr_len[u]; if (mode == MBEDTLS_AES_DECRYPT) { memcpy(buf, aes_test_ctr_ct[u], len); aes_tests = aes_test_ctr_pt[u]; } else { memcpy(buf, aes_test_ctr_pt[u], len); aes_tests = aes_test_ctr_ct[u]; } ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, len) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } } if (verbose != 0) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) /* * XTS mode */ { static const int num_tests = sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); mbedtls_aes_xts_context ctx_xts; mbedtls_aes_xts_init(&ctx_xts); for (i = 0; i < num_tests << 1; i++) { const unsigned char *data_unit; u = i >> 1; mode = i & 1; if (verbose != 0) { mbedtls_printf(" AES-XTS-128 (%s): ", (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); } memset(key, 0, sizeof(key)); memcpy(key, aes_test_xts_key[u], 32); data_unit = aes_test_xts_data_unit[u]; len = sizeof(*aes_test_xts_ct32); if (mode == MBEDTLS_AES_DECRYPT) { ret = mbedtls_aes_xts_setkey_dec(&ctx_xts, key, 256); if (ret != 0) { goto exit; } memcpy(buf, aes_test_xts_ct32[u], len); aes_tests = aes_test_xts_pt32[u]; } else { ret = mbedtls_aes_xts_setkey_enc(&ctx_xts, key, 256); if (ret != 0) { goto exit; } memcpy(buf, aes_test_xts_pt32[u], len); aes_tests = aes_test_xts_ct32[u]; } ret = mbedtls_aes_crypt_xts(&ctx_xts, mode, len, data_unit, buf, buf); if (ret != 0) { goto exit; } if (memcmp(buf, aes_tests, len) != 0) { ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } mbedtls_aes_xts_free(&ctx_xts); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ ret = 0; exit: if (ret != 0 && verbose != 0) { mbedtls_printf("failed\n"); } mbedtls_aes_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_AES_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/aesce.c000066400000000000000000000476521464416617300225760ustar00rootroot00000000000000/* * Armv8-A Cryptographic Extension support functions for Aarch64 * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if defined(__clang__) && (__clang_major__ >= 4) /* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, * but that is defined by build_info.h, and we need this block to happen first. */ #if defined(__ARM_ARCH) #if __ARM_ARCH >= 8 #define MBEDTLS_AESCE_ARCH_IS_ARMV8_A #endif #endif #if defined(MBEDTLS_AESCE_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. * * The intrinsic declaration are guarded by predefined ACLE macros in clang: * these are normally only enabled by the -march option on the command line. * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_CRYPTO 1 /* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions * * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it * for older compilers. */ #define __ARM_FEATURE_AES 1 #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG #endif #endif /* defined(__clang__) && (__clang_major__ >= 4) */ #include #include "common.h" #if defined(MBEDTLS_AESCE_C) #include "aesce.h" #if defined(MBEDTLS_AESCE_HAVE_CODE) /* Compiler version checks. */ #if defined(__clang__) # if defined(MBEDTLS_ARCH_IS_ARM32) && (__clang_major__ < 11) # error "Minimum version of Clang for MBEDTLS_AESCE_C on 32-bit Arm or Thumb is 11.0." # elif defined(MBEDTLS_ARCH_IS_ARM64) && (__clang_major__ < 4) # error "Minimum version of Clang for MBEDTLS_AESCE_C on aarch64 is 4.0." # endif #elif defined(__GNUC__) # if __GNUC__ < 6 # error "Minimum version of GCC for MBEDTLS_AESCE_C is 6.0." # endif #elif defined(_MSC_VER) /* TODO: We haven't verified MSVC from 1920 to 1928. If someone verified that, * please update this and document of `MBEDTLS_AESCE_C` in * `mbedtls_config.h`. */ # if _MSC_VER < 1929 # error "Minimum version of MSVC for MBEDTLS_AESCE_C is 2019 version 16.11.2." # endif #elif defined(__ARMCC_VERSION) # if defined(MBEDTLS_ARCH_IS_ARM32) && (__ARMCC_VERSION < 6200002) /* TODO: We haven't verified armclang for 32-bit Arm/Thumb prior to 6.20. * If someone verified that, please update this and document of * `MBEDTLS_AESCE_C` in `mbedtls_config.h`. */ # error "Minimum version of armclang for MBEDTLS_AESCE_C on 32-bit Arm is 6.20." # elif defined(MBEDTLS_ARCH_IS_ARM64) && (__ARMCC_VERSION < 6060000) # error "Minimum version of armclang for MBEDTLS_AESCE_C on aarch64 is 6.6." # endif #endif #if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \ defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) # if defined(__ARMCOMPILER_VERSION) # if __ARMCOMPILER_VERSION <= 6090000 # error "Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C" # else # pragma clang attribute push (__attribute__((target("aes"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # endif # elif defined(__clang__) # pragma clang attribute push (__attribute__((target("aes"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(__GNUC__) # pragma GCC push_options # pragma GCC target ("+crypto") # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(_MSC_VER) # error "Required feature(__ARM_FEATURE_AES) is not enabled." # endif #endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */ #if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) #include #if !defined(HWCAP_NEON) #define HWCAP_NEON (1 << 12) #endif #if !defined(HWCAP2_AES) #define HWCAP2_AES (1 << 0) #endif #if !defined(HWCAP_AES) #define HWCAP_AES (1 << 3) #endif #if !defined(HWCAP_ASIMD) #define HWCAP_ASIMD (1 << 1) #endif signed char mbedtls_aesce_has_support_result = -1; #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) /* * AES instruction support detection routine */ int mbedtls_aesce_has_support_impl(void) { /* To avoid many calls to getauxval, cache the result. This is * thread-safe, because we store the result in a char so cannot * be vulnerable to non-atomic updates. * It is possible that we could end up setting result more than * once, but that is harmless. */ if (mbedtls_aesce_has_support_result == -1) { #if defined(MBEDTLS_ARCH_IS_ARM32) unsigned long auxval = getauxval(AT_HWCAP); unsigned long auxval2 = getauxval(AT_HWCAP2); if (((auxval & HWCAP_NEON) == HWCAP_NEON) && ((auxval2 & HWCAP2_AES) == HWCAP2_AES)) { mbedtls_aesce_has_support_result = 1; } else { mbedtls_aesce_has_support_result = 0; } #else unsigned long auxval = getauxval(AT_HWCAP); if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) == (HWCAP_ASIMD | HWCAP_AES)) { mbedtls_aesce_has_support_result = 1; } else { mbedtls_aesce_has_support_result = 0; } #endif } return mbedtls_aesce_has_support_result; } #endif #endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ /* Single round of AESCE encryption */ #define AESCE_ENCRYPT_ROUND \ block = vaeseq_u8(block, vld1q_u8(keys)); \ block = vaesmcq_u8(block); \ keys += 16 /* Two rounds of AESCE encryption */ #define AESCE_ENCRYPT_ROUND_X2 AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND MBEDTLS_OPTIMIZE_FOR_PERFORMANCE static uint8x16_t aesce_encrypt_block(uint8x16_t block, unsigned char *keys, int rounds) { /* 10, 12 or 14 rounds. Unroll loop. */ if (rounds == 10) { goto rounds_10; } if (rounds == 12) { goto rounds_12; } AESCE_ENCRYPT_ROUND_X2; rounds_12: AESCE_ENCRYPT_ROUND_X2; rounds_10: AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND_X2; AESCE_ENCRYPT_ROUND; /* AES AddRoundKey for the previous round. * SubBytes, ShiftRows for the final round. */ block = vaeseq_u8(block, vld1q_u8(keys)); keys += 16; /* Final round: no MixColumns */ /* Final AddRoundKey */ block = veorq_u8(block, vld1q_u8(keys)); return block; } /* Single round of AESCE decryption * * AES AddRoundKey, SubBytes, ShiftRows * * block = vaesdq_u8(block, vld1q_u8(keys)); * * AES inverse MixColumns for the next round. * * This means that we switch the order of the inverse AddRoundKey and * inverse MixColumns operations. We have to do this as AddRoundKey is * done in an atomic instruction together with the inverses of SubBytes * and ShiftRows. * * It works because MixColumns is a linear operation over GF(2^8) and * AddRoundKey is an exclusive or, which is equivalent to addition over * GF(2^8). (The inverse of MixColumns needs to be applied to the * affected round keys separately which has been done when the * decryption round keys were calculated.) * * block = vaesimcq_u8(block); */ #define AESCE_DECRYPT_ROUND \ block = vaesdq_u8(block, vld1q_u8(keys)); \ block = vaesimcq_u8(block); \ keys += 16 /* Two rounds of AESCE decryption */ #define AESCE_DECRYPT_ROUND_X2 AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static uint8x16_t aesce_decrypt_block(uint8x16_t block, unsigned char *keys, int rounds) { /* 10, 12 or 14 rounds. Unroll loop. */ if (rounds == 10) { goto rounds_10; } if (rounds == 12) { goto rounds_12; } AESCE_DECRYPT_ROUND_X2; rounds_12: AESCE_DECRYPT_ROUND_X2; rounds_10: AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND_X2; AESCE_DECRYPT_ROUND; /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the * last full round. */ block = vaesdq_u8(block, vld1q_u8(keys)); keys += 16; /* Inverse AddRoundKey for inverting the initial round key addition. */ block = veorq_u8(block, vld1q_u8(keys)); return block; } #endif /* * AES-ECB block en(de)cryption */ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { uint8x16_t block = vld1q_u8(&input[0]); unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { block = aesce_decrypt_block(block, keys, ctx->nr); } else #else (void) mode; #endif { block = aesce_encrypt_block(block, keys, ctx->nr); } vst1q_u8(&output[0], block); return 0; } /* * Compute decryption round keys from encryption round keys */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesce_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { int i, j; j = nr; vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16)); for (i = 1, j--; j > 0; i++, j--) { vst1q_u8(invkey + i * 16, vaesimcq_u8(vld1q_u8(fwdkey + j * 16))); } vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16)); } #endif static inline uint32_t aes_rot_word(uint32_t word) { return (word << (32 - 8)) | (word >> 8); } static inline uint32_t aes_sub_word(uint32_t in) { uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in)); uint8x16_t zero = vdupq_n_u8(0); /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields * the correct result as ShiftRows doesn't change the first row. */ v = vaeseq_u8(zero, v); return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0); } /* * Key expansion function */ static void aesce_setkey_enc(unsigned char *rk, const unsigned char *key, const size_t key_bit_length) { static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf * - Section 5, Nr = Nk + 6 * - Section 5.2, the length of round keys is Nb*(Nr+1) */ const size_t key_len_in_words = key_bit_length / 32; /* Nk */ const size_t round_key_len_in_words = 4; /* Nb */ const size_t rounds_needed = key_len_in_words + 6; /* Nr */ const size_t round_keys_len_in_words = round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */ const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words; memcpy(rk, key, key_len_in_words * 4); for (uint32_t *rki = (uint32_t *) rk; rki + key_len_in_words < rko_end; rki += key_len_in_words) { size_t iteration = (size_t) (rki - (uint32_t *) rk) / key_len_in_words; uint32_t *rko; rko = rki + key_len_in_words; rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); rko[0] ^= rcon[iteration] ^ rki[0]; rko[1] = rko[0] ^ rki[1]; rko[2] = rko[1] ^ rki[2]; rko[3] = rko[2] ^ rki[3]; if (rko + key_len_in_words > rko_end) { /* Do not write overflow words.*/ continue; } #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) switch (key_bit_length) { case 128: break; case 192: rko[4] = rko[3] ^ rki[4]; rko[5] = rko[4] ^ rki[5]; break; case 256: rko[4] = aes_sub_word(rko[3]) ^ rki[4]; rko[5] = rko[4] ^ rki[5]; rko[6] = rko[5] ^ rki[6]; rko[7] = rko[6] ^ rki[7]; break; } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ } } /* * Key expansion, wrapper */ int mbedtls_aesce_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits) { switch (bits) { case 128: case 192: case 256: aesce_setkey_enc(rk, key, bits); break; default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } return 0; } #if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_ARCH_IS_ARM32) #if defined(__clang__) /* On clang for A32/T32, work around some missing intrinsics and types which are listed in * [ACLE](https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#polynomial-1) * These are only required for GCM. */ #define vreinterpretq_u64_p64(a) ((uint64x2_t) a) typedef uint8x16_t poly128_t; static inline poly128_t vmull_p64(poly64_t a, poly64_t b) { poly128_t r; asm ("vmull.p64 %[r], %[a], %[b]" : [r] "=w" (r) : [a] "w" (a), [b] "w" (b) :); return r; } /* This is set to cause some more missing intrinsics to be defined below */ #define COMMON_MISSING_INTRINSICS static inline poly128_t vmull_high_p64(poly64x2_t a, poly64x2_t b) { return vmull_p64((poly64_t) (vget_high_u64((uint64x2_t) a)), (poly64_t) (vget_high_u64((uint64x2_t) b))); } #endif /* defined(__clang__) */ static inline uint8x16_t vrbitq_u8(uint8x16_t x) { /* There is no vrbitq_u8 instruction in A32/T32, so provide * an equivalent non-Neon implementation. Reverse bit order in each * byte with 4x rbit, rev. */ asm ("ldm %[p], { r2-r5 } \n\t" "rbit r2, r2 \n\t" "rev r2, r2 \n\t" "rbit r3, r3 \n\t" "rev r3, r3 \n\t" "rbit r4, r4 \n\t" "rev r4, r4 \n\t" "rbit r5, r5 \n\t" "rev r5, r5 \n\t" "stm %[p], { r2-r5 } \n\t" : /* Output: 16 bytes of memory pointed to by &x */ "+m" (*(uint8_t(*)[16]) &x) : [p] "r" (&x) : "r2", "r3", "r4", "r5" ); return x; } #endif /* defined(MBEDTLS_ARCH_IS_ARM32) */ #if defined(MBEDTLS_COMPILER_IS_GCC) && __GNUC__ == 5 /* Some intrinsics are not available for GCC 5.X. */ #define COMMON_MISSING_INTRINSICS #endif /* MBEDTLS_COMPILER_IS_GCC && __GNUC__ == 5 */ #if defined(COMMON_MISSING_INTRINSICS) /* Missing intrinsics common to both GCC 5, and Clang on 32-bit */ #define vreinterpretq_p64_u8(a) ((poly64x2_t) a) #define vreinterpretq_u8_p128(a) ((uint8x16_t) a) static inline poly64x1_t vget_low_p64(poly64x2_t a) { uint64x1_t r = vget_low_u64(vreinterpretq_u64_p64(a)); return (poly64x1_t) r; } #endif /* COMMON_MISSING_INTRINSICS */ /* vmull_p64/vmull_high_p64 wrappers. * * Older compilers miss some intrinsic functions for `poly*_t`. We use * uint8x16_t and uint8x16x3_t as input/output parameters. */ #if defined(MBEDTLS_COMPILER_IS_GCC) /* GCC reports incompatible type error without cast. GCC think poly64_t and * poly64x1_t are different, that is different with MSVC and Clang. */ #define MBEDTLS_VMULL_P64(a, b) vmull_p64((poly64_t) a, (poly64_t) b) #else /* MSVC reports `error C2440: 'type cast'` with cast. Clang does not report * error with/without cast. And I think poly64_t and poly64x1_t are same, no * cast for clang also. */ #define MBEDTLS_VMULL_P64(a, b) vmull_p64(a, b) #endif /* MBEDTLS_COMPILER_IS_GCC */ static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b) { return vreinterpretq_u8_p128( MBEDTLS_VMULL_P64( (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)), (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b)) )); } static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b) { return vreinterpretq_u8_p128( vmull_high_p64(vreinterpretq_p64_u8(a), vreinterpretq_p64_u8(b))); } /* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by * `x^128 + x^7 + x^2 + x + 1`. * * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b * multiplies to generate a 128b. * * `poly_mult_128` executes polynomial multiplication and outputs 256b that * represented by 3 128b due to code size optimization. * * Output layout: * | | | | * |------------|-------------|-------------| * | ret.val[0] | h3:h2:00:00 | high 128b | * | ret.val[1] | :m2:m1:00 | middle 128b | * | ret.val[2] | : :l1:l0 | low 128b | */ static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b) { uint8x16x3_t ret; uint8x16_t h, m, l; /* retval high/middle/low */ uint8x16_t c, d, e; h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */ l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */ c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */ d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */ e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */ m = veorq_u8(d, e); /* :m2:m1:00 = d + e */ ret.val[0] = h; ret.val[1] = m; ret.val[2] = l; return ret; } /* * Modulo reduction. * * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8 * * Section 4.3 * * Modular reduction is slightly more complex. Write the GCM modulus as f(z) = * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we * simply multiply the higher part of the operand by r(z) and add it to l(z). If * the result is still larger than 128 bits, we reduce again. */ static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input) { uint8x16_t const ZERO = vdupq_n_u8(0); uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87)); #if defined(__GNUC__) /* use 'asm' as an optimisation barrier to prevent loading MODULO from * memory. It is for GNUC compatible compilers. */ asm volatile ("" : "+w" (r)); #endif uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8)); uint8x16_t h, m, l; /* input high/middle/low 128b */ uint8x16_t c, d, e, f, g, n, o; h = input.val[0]; /* h3:h2:00:00 */ m = input.val[1]; /* :m2:m1:00 */ l = input.val[2]; /* : :l1:l0 */ c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */ d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */ e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */ f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */ g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */ n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */ o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */ return veorq_u8(o, g); /* = o1:o0 + g1:00 */ } /* * GCM multiplication: c = a times b in GF(2^128) */ void mbedtls_aesce_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { uint8x16_t va, vb, vc; va = vrbitq_u8(vld1q_u8(&a[0])); vb = vrbitq_u8(vld1q_u8(&b[0])); vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb))); vst1q_u8(&c[0], vc); } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #endif /* MBEDTLS_AESCE_HAVE_CODE */ #endif /* MBEDTLS_AESCE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/aesce.h000066400000000000000000000107651464416617300225760ustar00rootroot00000000000000/** * \file aesce.h * * \brief Support hardware AES acceleration on Armv8-A processors with * the Armv8-A Cryptographic Extension. * * \warning These functions are only for internal use by other library * functions; you must not call them directly. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AESCE_H #define MBEDTLS_AESCE_H #include "mbedtls/build_info.h" #include "common.h" #include "mbedtls/aes.h" #if defined(MBEDTLS_AESCE_C) \ && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \ && (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER)) /* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a * potentially suitable compiler (compiler version & flags are not checked when defining * this). */ #define MBEDTLS_AESCE_HAVE_CODE #ifdef __cplusplus extern "C" { #endif #if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) extern signed char mbedtls_aesce_has_support_result; /** * \brief Internal function to detect the crypto extension in CPUs. * * \return 1 if CPU has support for the feature, 0 otherwise */ int mbedtls_aesce_has_support_impl(void); #define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \ mbedtls_aesce_has_support_impl() : \ mbedtls_aesce_has_support_result) #else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ /* If we are not on Linux, we can't detect support so assume that it's supported. * Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set. */ #define MBEDTLS_AESCE_HAS_SUPPORT() 1 #endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */ /** * \brief Internal AES-ECB block encryption and decryption * * \warning This assumes that the context specifies either 10, 12 or 14 * rounds and will behave incorrectly if this is not the case. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param input 16-byte input block * \param output 16-byte output block * * \return 0 on success (cannot fail) */ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); /** * \brief Internal GCM multiplication: c = a * b in GF(2^128) * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param c Result * \param a First operand * \param b Second operand * * \note Both operands and result are bit strings interpreted as * elements of GF(2^128) as per the GCM spec. */ void mbedtls_aesce_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal round key inversion. This function computes * decryption round keys from the encryption round keys. * * \param invkey Round keys for the equivalent inverse cipher * \param fwdkey Original round keys (for encryption) * \param nr Number of rounds (that is, number of round keys minus one) */ void mbedtls_aesce_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Internal key expansion for encryption * * \param rk Destination buffer where the round keys are written * \param key Encryption key * \param bits Key size in bits (must be 128, 192 or 256) * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ int mbedtls_aesce_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits); #ifdef __cplusplus } #endif #else #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && defined(MBEDTLS_ARCH_IS_ARMV8_A) #error "AES hardware acceleration not supported on this platform / compiler" #endif #endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS && (MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */ #endif /* MBEDTLS_AESCE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/aesni.c000066400000000000000000001001701464416617300225760ustar00rootroot00000000000000/* * AES-NI support functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html * [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html */ #include "common.h" #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #include #if defined(MBEDTLS_AESNI_HAVE_CODE) #if MBEDTLS_AESNI_HAVE_CODE == 2 #if defined(__GNUC__) #include #elif defined(_MSC_VER) #include #else #error "`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler" #endif #include #endif #if defined(MBEDTLS_ARCH_IS_X86) #if defined(MBEDTLS_COMPILER_IS_GCC) #pragma GCC push_options #pragma GCC target ("pclmul,sse2,aes") #define MBEDTLS_POP_TARGET_PRAGMA #elif defined(__clang__) && (__clang_major__ >= 5) #pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function) #define MBEDTLS_POP_TARGET_PRAGMA #endif #endif #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) /* * AES-NI support detection routine */ int mbedtls_aesni_has_support(unsigned int what) { static int done = 0; static unsigned int c = 0; if (!done) { #if MBEDTLS_AESNI_HAVE_CODE == 2 static int info[4] = { 0, 0, 0, 0 }; #if defined(_MSC_VER) __cpuid(info, 1); #else __cpuid(1, info[0], info[1], info[2], info[3]); #endif c = info[2]; #else /* AESNI using asm */ asm ("movl $1, %%eax \n\t" "cpuid \n\t" : "=c" (c) : : "eax", "ebx", "edx"); #endif /* MBEDTLS_AESNI_HAVE_CODE */ done = 1; } return (c & what) != 0; } #endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */ #if MBEDTLS_AESNI_HAVE_CODE == 2 /* * AES-NI AES-ECB block en(de)cryption */ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset); unsigned nr = ctx->nr; // Number of remaining rounds // Load round key 0 __m128i state; memcpy(&state, input, 16); state = _mm_xor_si128(state, rk[0]); // state ^= *rk; ++rk; --nr; #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (mode == MBEDTLS_AES_DECRYPT) { while (nr != 0) { state = _mm_aesdec_si128(state, *rk); ++rk; --nr; } state = _mm_aesdeclast_si128(state, *rk); } else #else (void) mode; #endif { while (nr != 0) { state = _mm_aesenc_si128(state, *rk); ++rk; --nr; } state = _mm_aesenclast_si128(state, *rk); } memcpy(output, &state, 16); return 0; } /* * GCM multiplication: c = a times b in GF(2^128) * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. */ static void gcm_clmul(const __m128i aa, const __m128i bb, __m128i *cc, __m128i *dd) { /* * Caryless multiplication dd:cc = aa * bb * using [CLMUL-WP] algorithm 1 (p. 12). */ *cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0 *dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0 __m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0 __m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0 ff = _mm_xor_si128(ff, ee); // e1+f1:e0+f0 ee = ff; // e1+f1:e0+f0 ff = _mm_srli_si128(ff, 8); // 0:e1+f1 ee = _mm_slli_si128(ee, 8); // e0+f0:0 *dd = _mm_xor_si128(*dd, ff); // d1:d0+e1+f1 *cc = _mm_xor_si128(*cc, ee); // c1+e0+f0:c0 } static void gcm_shift(__m128i *cc, __m128i *dd) { /* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left, * taking advantage of [CLMUL-WP] eq 27 (p. 18). */ // // *cc = r1:r0 // // *dd = r3:r2 __m128i cc_lo = _mm_slli_epi64(*cc, 1); // r1<<1:r0<<1 __m128i dd_lo = _mm_slli_epi64(*dd, 1); // r3<<1:r2<<1 __m128i cc_hi = _mm_srli_epi64(*cc, 63); // r1>>63:r0>>63 __m128i dd_hi = _mm_srli_epi64(*dd, 63); // r3>>63:r2>>63 __m128i xmm5 = _mm_srli_si128(cc_hi, 8); // 0:r1>>63 cc_hi = _mm_slli_si128(cc_hi, 8); // r0>>63:0 dd_hi = _mm_slli_si128(dd_hi, 8); // 0:r1>>63 *cc = _mm_or_si128(cc_lo, cc_hi); // r1<<1|r0>>63:r0<<1 *dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63 } static __m128i gcm_reduce(__m128i xx) { // // xx = x1:x0 /* [CLMUL-WP] Algorithm 5 Step 2 */ __m128i aa = _mm_slli_epi64(xx, 63); // x1<<63:x0<<63 = stuff:a __m128i bb = _mm_slli_epi64(xx, 62); // x1<<62:x0<<62 = stuff:b __m128i cc = _mm_slli_epi64(xx, 57); // x1<<57:x0<<57 = stuff:c __m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0 return _mm_xor_si128(dd, xx); // x1+a+b+c:x0 = d:x0 } static __m128i gcm_mix(__m128i dx) { /* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */ __m128i ee = _mm_srli_epi64(dx, 1); // e1:x0>>1 = e1:e0' __m128i ff = _mm_srli_epi64(dx, 2); // f1:x0>>2 = f1:f0' __m128i gg = _mm_srli_epi64(dx, 7); // g1:x0>>7 = g1:g0' // e0'+f0'+g0' is almost e0+f0+g0, except for some missing // bits carried from d. Now get those bits back in. __m128i eh = _mm_slli_epi64(dx, 63); // d<<63:stuff __m128i fh = _mm_slli_epi64(dx, 62); // d<<62:stuff __m128i gh = _mm_slli_epi64(dx, 57); // d<<57:stuff __m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx); } void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { __m128i aa = { 0 }, bb = { 0 }, cc, dd; /* The inputs are in big-endian order, so byte-reverse them */ for (size_t i = 0; i < 16; i++) { ((uint8_t *) &aa)[i] = a[15 - i]; ((uint8_t *) &bb)[i] = b[15 - i]; } gcm_clmul(aa, bb, &cc, &dd); gcm_shift(&cc, &dd); /* * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 * using [CLMUL-WP] algorithm 5 (p. 18). * Currently dd:cc holds x3:x2:x1:x0 (already shifted). */ __m128i dx = gcm_reduce(cc); __m128i xh = gcm_mix(dx); cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0 /* Now byte-reverse the outputs */ for (size_t i = 0; i < 16; i++) { c[i] = ((uint8_t *) &cc)[15 - i]; } return; } /* * Compute decryption round keys from encryption round keys */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { __m128i *ik = (__m128i *) invkey; const __m128i *fk = (const __m128i *) fwdkey + nr; *ik = *fk; for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) { *ik = _mm_aesimc_si128(*fk); } *ik = *fk; } #endif /* * Key expansion, 128-bit case */ static __m128i aesni_set_rk_128(__m128i state, __m128i xword) { /* * Finish generating the next round key. * * On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff * with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST). * * On exit, xword is r7:r6:r5:r4 * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 * and this is returned, to be written to the round key buffer. */ xword = _mm_shuffle_epi32(xword, 0xff); // X:X:X:X xword = _mm_xor_si128(xword, state); // X+r3:X+r2:X+r1:r4 state = _mm_slli_si128(state, 4); // r2:r1:r0:0 xword = _mm_xor_si128(xword, state); // X+r3+r2:X+r2+r1:r5:r4 state = _mm_slli_si128(state, 4); // r1:r0:0:0 xword = _mm_xor_si128(xword, state); // X+r3+r2+r1:r6:r5:r4 state = _mm_slli_si128(state, 4); // r0:0:0:0 state = _mm_xor_si128(xword, state); // r7:r6:r5:r4 return state; } static void aesni_setkey_enc_128(unsigned char *rk_bytes, const unsigned char *key) { __m128i *rk = (__m128i *) rk_bytes; memcpy(&rk[0], key, 16); rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01)); rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02)); rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04)); rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08)); rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10)); rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20)); rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40)); rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80)); rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B)); rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36)); } /* * Key expansion, 192-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword, unsigned char *rk) { /* * Finish generating the next 6 quarter-keys. * * On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4 * and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON * (obtained with AESKEYGENASSIST). * * On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10 * and those are written to the round key buffer. */ xword = _mm_shuffle_epi32(xword, 0x55); // X:X:X:X xword = _mm_xor_si128(xword, *state0); // X+r3:X+r2:X+r1:X+r0 *state0 = _mm_slli_si128(*state0, 4); // r2:r1:r0:0 xword = _mm_xor_si128(xword, *state0); // X+r3+r2:X+r2+r1:X+r1+r0:X+r0 *state0 = _mm_slli_si128(*state0, 4); // r1:r0:0:0 xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0 *state0 = _mm_slli_si128(*state0, 4); // r0:0:0:0 xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0 *state0 = xword; // = r9:r8:r7:r6 xword = _mm_shuffle_epi32(xword, 0xff); // r9:r9:r9:r9 xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5:r9+r4 *state1 = _mm_slli_si128(*state1, 4); // stuff:stuff:r4:0 xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5+r4:r9+r4 *state1 = xword; // = stuff:stuff:r11:r10 /* Store state0 and the low half of state1 into rk, which is conceptually * an array of 24-byte elements. Since 24 is not a multiple of 16, * rk is not necessarily aligned so just `*rk = *state0` doesn't work. */ memcpy(rk, state0, 16); memcpy(rk + 16, state1, 8); } static void aesni_setkey_enc_192(unsigned char *rk, const unsigned char *key) { /* First round: use original key */ memcpy(rk, key, 24); /* aes.c guarantees that rk is aligned on a 16-byte boundary. */ __m128i state0 = ((__m128i *) rk)[0]; __m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7); aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* * Key expansion, 256-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword, __m128i *rk0, __m128i *rk1) { /* * Finish generating the next two round keys. * * On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and * xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON * (obtained with AESKEYGENASSIST). * * On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12 */ xword = _mm_shuffle_epi32(xword, 0xff); xword = _mm_xor_si128(xword, state0); state0 = _mm_slli_si128(state0, 4); xword = _mm_xor_si128(xword, state0); state0 = _mm_slli_si128(state0, 4); xword = _mm_xor_si128(xword, state0); state0 = _mm_slli_si128(state0, 4); state0 = _mm_xor_si128(state0, xword); *rk0 = state0; /* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 ) * and proceed to generate next round key from there */ xword = _mm_aeskeygenassist_si128(state0, 0x00); xword = _mm_shuffle_epi32(xword, 0xaa); xword = _mm_xor_si128(xword, state1); state1 = _mm_slli_si128(state1, 4); xword = _mm_xor_si128(xword, state1); state1 = _mm_slli_si128(state1, 4); xword = _mm_xor_si128(xword, state1); state1 = _mm_slli_si128(state1, 4); state1 = _mm_xor_si128(state1, xword); *rk1 = state1; } static void aesni_setkey_enc_256(unsigned char *rk_bytes, const unsigned char *key) { __m128i *rk = (__m128i *) rk_bytes; memcpy(&rk[0], key, 16); memcpy(&rk[1], key + 16, 16); /* * Main "loop" - Generating one more key than necessary, * see definition of mbedtls_aes_context.buf */ aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]); aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]); aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]); aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]); aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]); aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]); aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #else /* MBEDTLS_AESNI_HAVE_CODE == 1 */ #if defined(__has_feature) #if __has_feature(memory_sanitizer) #warning \ "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." #endif #endif /* * Binutils needs to be at least 2.19 to support AES-NI instructions. * Unfortunately, a lot of users have a lower version now (2014-04). * Emit bytecode directly in order to support "old" version of gas. * * Opcodes from the Intel architecture reference manual, vol. 3. * We always use registers, so we don't need prefixes for memory operands. * Operand macros are in gas order (src, dst) as opposed to Intel order * (dst, src) in order to blend better into the surrounding assembly code. */ #define AESDEC(regs) ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t" #define AESDECLAST(regs) ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t" #define AESENC(regs) ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t" #define AESENCLAST(regs) ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t" #define AESIMC(regs) ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t" #define AESKEYGENA(regs, imm) ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t" #define PCLMULQDQ(regs, imm) ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t" #define xmm0_xmm0 "0xC0" #define xmm0_xmm1 "0xC8" #define xmm0_xmm2 "0xD0" #define xmm0_xmm3 "0xD8" #define xmm0_xmm4 "0xE0" #define xmm1_xmm0 "0xC1" #define xmm1_xmm2 "0xD1" /* * AES-NI AES-ECB block en(de)cryption */ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { asm ("movdqu (%3), %%xmm0 \n\t" // load input "movdqu (%1), %%xmm1 \n\t" // load round key 0 "pxor %%xmm1, %%xmm0 \n\t" // round 0 "add $16, %1 \n\t" // point to next round key "subl $1, %0 \n\t" // normal rounds = nr - 1 "test %2, %2 \n\t" // mode? "jz 2f \n\t" // 0 = decrypt "1: \n\t" // encryption loop "movdqu (%1), %%xmm1 \n\t" // load round key AESENC(xmm1_xmm0) // do round "add $16, %1 \n\t" // point to next round key "subl $1, %0 \n\t" // loop "jnz 1b \n\t" "movdqu (%1), %%xmm1 \n\t" // load round key AESENCLAST(xmm1_xmm0) // last round #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) "jmp 3f \n\t" "2: \n\t" // decryption loop "movdqu (%1), %%xmm1 \n\t" AESDEC(xmm1_xmm0) // do round "add $16, %1 \n\t" "subl $1, %0 \n\t" "jnz 2b \n\t" "movdqu (%1), %%xmm1 \n\t" // load round key AESDECLAST(xmm1_xmm0) // last round #endif "3: \n\t" "movdqu %%xmm0, (%4) \n\t" // export output : : "r" (ctx->nr), "r" (ctx->buf + ctx->rk_offset), "r" (mode), "r" (input), "r" (output) : "memory", "cc", "xmm0", "xmm1"); return 0; } /* * GCM multiplication: c = a times b in GF(2^128) * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. */ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]) { unsigned char aa[16], bb[16], cc[16]; size_t i; /* The inputs are in big-endian order, so byte-reverse them */ for (i = 0; i < 16; i++) { aa[i] = a[15 - i]; bb[i] = b[15 - i]; } asm ("movdqu (%0), %%xmm0 \n\t" // a1:a0 "movdqu (%1), %%xmm1 \n\t" // b1:b0 /* * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 * using [CLMUL-WP] algorithm 1 (p. 12). */ "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 "movdqa %%xmm1, %%xmm3 \n\t" // same "movdqa %%xmm1, %%xmm4 \n\t" // same PCLMULQDQ(xmm0_xmm1, "0x00") // a0*b0 = c1:c0 PCLMULQDQ(xmm0_xmm2, "0x11") // a1*b1 = d1:d0 PCLMULQDQ(xmm0_xmm3, "0x10") // a0*b1 = e1:e0 PCLMULQDQ(xmm0_xmm4, "0x01") // a1*b0 = f1:f0 "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 "movdqa %%xmm4, %%xmm3 \n\t" // same "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 "pslldq $8, %%xmm3 \n\t" // e0+f0:0 "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 /* * Now shift the result one bit to the left, * taking advantage of [CLMUL-WP] eq 27 (p. 18) */ "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 "pslldq $8, %%xmm3 \n\t" // r0>>63:0 "pslldq $8, %%xmm4 \n\t" // r2>>63:0 "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 /* * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 * using [CLMUL-WP] algorithm 5 (p. 18). * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). */ /* Step 2 (1) */ "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 "movdqa %%xmm1, %%xmm4 \n\t" // same "movdqa %%xmm1, %%xmm5 \n\t" // same "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c /* Step 2 (2) */ "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c "pslldq $8, %%xmm3 \n\t" // a+b+c:0 "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 /* Steps 3 and 4 */ "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 "movdqa %%xmm1,%%xmm4 \n\t" // same "movdqa %%xmm1,%%xmm5 \n\t" // same "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing // bits carried from d. Now get those\t bits back in. "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 "movdqa %%xmm1,%%xmm4 \n\t" // same "movdqa %%xmm1,%%xmm5 \n\t" // same "psllq $63, %%xmm3 \n\t" // d<<63:stuff "psllq $62, %%xmm4 \n\t" // d<<62:stuff "psllq $57, %%xmm5 \n\t" // d<<57:stuff "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 "movdqu %%xmm0, (%2) \n\t" // done : : "r" (aa), "r" (bb), "r" (cc) : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5"); /* Now byte-reverse the outputs */ for (i = 0; i < 16; i++) { c[i] = cc[15 - i]; } return; } /* * Compute decryption round keys from encryption round keys */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr) { unsigned char *ik = invkey; const unsigned char *fk = fwdkey + 16 * nr; memcpy(ik, fk, 16); for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) { asm ("movdqu (%0), %%xmm0 \n\t" AESIMC(xmm0_xmm0) "movdqu %%xmm0, (%1) \n\t" : : "r" (fk), "r" (ik) : "memory", "xmm0"); } memcpy(ik, fk, 16); } #endif /* * Key expansion, 128-bit case */ static void aesni_setkey_enc_128(unsigned char *rk, const unsigned char *key) { asm ("movdqu (%1), %%xmm0 \n\t" // copy the original key "movdqu %%xmm0, (%0) \n\t" // as round key 0 "jmp 2f \n\t" // skip auxiliary routine /* * Finish generating the next round key. * * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff * with X = rot( sub( r3 ) ) ^ RCON. * * On exit, xmm0 is r7:r6:r5:r4 * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 * and those are written to the round key buffer. */ "1: \n\t" "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 "pslldq $4, %%xmm0 \n\t" // etc "pxor %%xmm0, %%xmm1 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! "add $16, %0 \n\t" // point to next round key "movdqu %%xmm0, (%0) \n\t" // write it "ret \n\t" /* Main "loop" */ "2: \n\t" AESKEYGENA(xmm0_xmm1, "0x01") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x02") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x04") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x08") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x10") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x20") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x40") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x80") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x1B") "call 1b \n\t" AESKEYGENA(xmm0_xmm1, "0x36") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } /* * Key expansion, 192-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_setkey_enc_192(unsigned char *rk, const unsigned char *key) { asm ("movdqu (%1), %%xmm0 \n\t" // copy original round key "movdqu %%xmm0, (%0) \n\t" "add $16, %0 \n\t" "movq 16(%1), %%xmm1 \n\t" "movq %%xmm1, (%0) \n\t" "add $8, %0 \n\t" "jmp 2f \n\t" // skip auxiliary routine /* * Finish generating the next 6 quarter-keys. * * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. * * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 * and those are written to the round key buffer. */ "1: \n\t" "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 "pslldq $4, %%xmm0 \n\t" // etc "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 "movdqu %%xmm0, (%0) \n\t" "add $16, %0 \n\t" "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 "movq %%xmm1, (%0) \n\t" "add $8, %0 \n\t" "ret \n\t" "2: \n\t" AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x80") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* * Key expansion, 256-bit case */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static void aesni_setkey_enc_256(unsigned char *rk, const unsigned char *key) { asm ("movdqu (%1), %%xmm0 \n\t" "movdqu %%xmm0, (%0) \n\t" "add $16, %0 \n\t" "movdqu 16(%1), %%xmm1 \n\t" "movdqu %%xmm1, (%0) \n\t" "jmp 2f \n\t" // skip auxiliary routine /* * Finish generating the next two round keys. * * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON * * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 * and those have been written to the output buffer. */ "1: \n\t" "pshufd $0xff, %%xmm2, %%xmm2 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm0, %%xmm2 \n\t" "pslldq $4, %%xmm0 \n\t" "pxor %%xmm2, %%xmm0 \n\t" "add $16, %0 \n\t" "movdqu %%xmm0, (%0) \n\t" /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) * and proceed to generate next round key from there */ AESKEYGENA(xmm0_xmm2, "0x00") "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" "pxor %%xmm1, %%xmm2 \n\t" "pslldq $4, %%xmm1 \n\t" "pxor %%xmm1, %%xmm2 \n\t" "pslldq $4, %%xmm1 \n\t" "pxor %%xmm1, %%xmm2 \n\t" "pslldq $4, %%xmm1 \n\t" "pxor %%xmm2, %%xmm1 \n\t" "add $16, %0 \n\t" "movdqu %%xmm1, (%0) \n\t" "ret \n\t" /* * Main "loop" - Generating one more key than necessary, * see definition of mbedtls_aes_context.buf */ "2: \n\t" AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t" AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t" : : "r" (rk), "r" (key) : "memory", "cc", "0"); } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AESNI_HAVE_CODE */ /* * Key expansion, wrapper */ int mbedtls_aesni_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits) { switch (bits) { case 128: aesni_setkey_enc_128(rk, key); break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 192: aesni_setkey_enc_192(rk, key); break; case 256: aesni_setkey_enc_256(rk, key); break; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; } return 0; } #endif /* MBEDTLS_AESNI_HAVE_CODE */ #endif /* MBEDTLS_AESNI_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/aesni.h000066400000000000000000000130611464416617300226050ustar00rootroot00000000000000/** * \file aesni.h * * \brief AES-NI for hardware AES acceleration on some Intel processors * * \warning These functions are only for internal use by other library * functions; you must not call them directly. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_AESNI_H #define MBEDTLS_AESNI_H #include "mbedtls/build_info.h" #include "mbedtls/aes.h" #define MBEDTLS_AESNI_AES 0x02000000u #define MBEDTLS_AESNI_CLMUL 0x00000002u #if defined(MBEDTLS_AESNI_C) && \ (defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_X86)) /* Can we do AESNI with intrinsics? * (Only implemented with certain compilers, only for certain targets.) */ #undef MBEDTLS_AESNI_HAVE_INTRINSICS #if defined(_MSC_VER) && !defined(__clang__) /* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support * VS 2013 and up for other reasons anyway, so no need to check the version. */ #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif /* GCC-like compilers: currently, we only support intrinsics if the requisite * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2` * or `clang -maes -mpclmul`). */ #if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__) #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif /* For 32-bit, we only support intrinsics */ #if defined(MBEDTLS_ARCH_IS_X86) && (defined(__GNUC__) || defined(__clang__)) #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif /* Choose the implementation of AESNI, if one is available. * * Favor the intrinsics-based implementation if it's available, for better * maintainability. * Performance is about the same (see #7380). * In the long run, we will likely remove the assembly implementation. */ #if defined(MBEDTLS_AESNI_HAVE_INTRINSICS) #define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics #elif defined(MBEDTLS_HAVE_ASM) && \ (defined(__GNUC__) || defined(__clang__)) && defined(MBEDTLS_ARCH_IS_X64) /* Can we do AESNI with inline assembly? * (Only implemented with gas syntax, only for 64-bit.) */ #define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly #else #error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available" #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) #ifdef __cplusplus extern "C" { #endif /** * \brief Internal function to detect the AES-NI feature in CPUs. * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param what The feature to detect * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) * * \return 1 if CPU has support for the feature, 0 otherwise */ #if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) int mbedtls_aesni_has_support(unsigned int what); #else #define mbedtls_aesni_has_support(what) 1 #endif /** * \brief Internal AES-NI AES-ECB block encryption and decryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param input 16-byte input block * \param output 16-byte output block * * \return 0 on success (cannot fail) */ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); /** * \brief Internal GCM multiplication: c = a * b in GF(2^128) * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param c Result * \param a First operand * \param b Second operand * * \note Both operands and result are bit strings interpreted as * elements of GF(2^128) as per the GCM spec. */ void mbedtls_aesni_gcm_mult(unsigned char c[16], const unsigned char a[16], const unsigned char b[16]); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** * \brief Internal round key inversion. This function computes * decryption round keys from the encryption round keys. * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param invkey Round keys for the equivalent inverse cipher * \param fwdkey Original round keys (for encryption) * \param nr Number of rounds (that is, number of round keys minus one) */ void mbedtls_aesni_inverse_key(unsigned char *invkey, const unsigned char *fwdkey, int nr); #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /** * \brief Internal key expansion for encryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param rk Destination buffer where the round keys are written * \param key Encryption key * \param bits Key size in bits (must be 128, 192 or 256) * * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH */ int mbedtls_aesni_setkey_enc(unsigned char *rk, const unsigned char *key, size_t bits); #ifdef __cplusplus } #endif #endif /* MBEDTLS_AESNI_HAVE_CODE */ #endif /* MBEDTLS_AESNI_C && (MBEDTLS_ARCH_IS_X64 || MBEDTLS_ARCH_IS_X86) */ #endif /* MBEDTLS_AESNI_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/alignment.h000066400000000000000000000642451464416617300234760ustar00rootroot00000000000000/** * \file alignment.h * * \brief Utility code for dealing with unaligned memory accesses */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LIBRARY_ALIGNMENT_H #define MBEDTLS_LIBRARY_ALIGNMENT_H #include #include #include /* * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory * accesses are known to be efficient. * * All functions defined here will behave correctly regardless, but might be less * efficient when this is not defined. */ #if defined(__ARM_FEATURE_UNALIGNED) \ || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \ || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) /* * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9 * (and later versions) for Arm v7 and later; all x86 platforms should have * efficient unaligned access. * * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached * device memory). */ #define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS #endif #if defined(__IAR_SYSTEMS_ICC__) && \ (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \ || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__)) #pragma language=save #pragma language=extended #define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA /* IAR recommend this technique for accessing unaligned data in * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data * This results in a single load / store instruction (if unaligned access is supported). * According to that document, this is only supported on certain architectures. */ #define UINT_UNALIGNED typedef uint16_t __packed mbedtls_uint16_unaligned_t; typedef uint32_t __packed mbedtls_uint32_unaligned_t; typedef uint64_t __packed mbedtls_uint64_unaligned_t; #elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \ ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS))) /* * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than * generating some LDR or LDRB instructions (similar for stores). * * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm * is affected. To keep it simple, we enable for all architectures. * * For versions of gcc < 5.4.0 this issue always happens. * For gcc < 6.3.0, this issue happens at -O0 * For all versions, this issue happens iff unaligned access is not supported. * * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is * supported, which is correct but not optimal. * * For performance (and code size, in some cases), we want to avoid the branch and just generate * some inline load/store instructions since the access is small and constant-size. * * The manual states: * "The packed attribute specifies that a variable or structure field should have the smallest * possible alignment—one byte for a variable" * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html * * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662 * * Tested with several versions of GCC from 4.5.0 up to 13.2.0 * We don't enable for older than 4.5.0 as this has not been tested. */ #define UINT_UNALIGNED_STRUCT typedef struct { uint16_t x; } __attribute__((packed)) mbedtls_uint16_unaligned_t; typedef struct { uint32_t x; } __attribute__((packed)) mbedtls_uint32_unaligned_t; typedef struct { uint64_t x; } __attribute__((packed)) mbedtls_uint64_unaligned_t; #endif /* * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising * for size. */ /** * Read the unsigned 16 bits integer from the given address, which need not * be aligned. * * \param p pointer to 2 bytes of data * \return Data at the given address */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline uint16_t mbedtls_get_unaligned_uint16(const void *p) { uint16_t r; #if defined(UINT_UNALIGNED) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; r = *p16; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; r = p16->x; #else memcpy(&r, p, sizeof(r)); #endif return r; } /** * Write the unsigned 16 bits integer to the given address, which need not * be aligned. * * \param p pointer to 2 bytes of data * \param x data to write */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x) { #if defined(UINT_UNALIGNED) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; *p16 = x; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p; p16->x = x; #else memcpy(p, &x, sizeof(x)); #endif } /** * Read the unsigned 32 bits integer from the given address, which need not * be aligned. * * \param p pointer to 4 bytes of data * \return Data at the given address */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline uint32_t mbedtls_get_unaligned_uint32(const void *p) { uint32_t r; #if defined(UINT_UNALIGNED) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; r = *p32; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; r = p32->x; #else memcpy(&r, p, sizeof(r)); #endif return r; } /** * Write the unsigned 32 bits integer to the given address, which need not * be aligned. * * \param p pointer to 4 bytes of data * \param x data to write */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x) { #if defined(UINT_UNALIGNED) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; *p32 = x; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p; p32->x = x; #else memcpy(p, &x, sizeof(x)); #endif } /** * Read the unsigned 64 bits integer from the given address, which need not * be aligned. * * \param p pointer to 8 bytes of data * \return Data at the given address */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline uint64_t mbedtls_get_unaligned_uint64(const void *p) { uint64_t r; #if defined(UINT_UNALIGNED) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; r = *p64; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; r = p64->x; #else memcpy(&r, p, sizeof(r)); #endif return r; } /** * Write the unsigned 64 bits integer to the given address, which need not * be aligned. * * \param p pointer to 8 bytes of data * \param x data to write */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif static inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x) { #if defined(UINT_UNALIGNED) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; *p64 = x; #elif defined(UINT_UNALIGNED_STRUCT) mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p; p64->x = x; #else memcpy(p, &x, sizeof(x)); #endif } #if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA) #pragma language=restore #endif /** Byte Reading Macros * * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th * byte from x, where byte 0 is the least significant byte. */ #define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff)) #define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff)) #define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff)) #define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff)) #define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff)) #define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff)) #define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff)) #define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff)) /* * Detect GCC built-in byteswap routines */ #if defined(__GNUC__) && defined(__GNUC_PREREQ) #if __GNUC_PREREQ(4, 8) #define MBEDTLS_BSWAP16 __builtin_bswap16 #endif /* __GNUC_PREREQ(4,8) */ #if __GNUC_PREREQ(4, 3) #define MBEDTLS_BSWAP32 __builtin_bswap32 #define MBEDTLS_BSWAP64 __builtin_bswap64 #endif /* __GNUC_PREREQ(4,3) */ #endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */ /* * Detect Clang built-in byteswap routines */ #if defined(__clang__) && defined(__has_builtin) #if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16) #define MBEDTLS_BSWAP16 __builtin_bswap16 #endif /* __has_builtin(__builtin_bswap16) */ #if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32) #define MBEDTLS_BSWAP32 __builtin_bswap32 #endif /* __has_builtin(__builtin_bswap32) */ #if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64) #define MBEDTLS_BSWAP64 __builtin_bswap64 #endif /* __has_builtin(__builtin_bswap64) */ #endif /* defined(__clang__) && defined(__has_builtin) */ /* * Detect MSVC built-in byteswap routines */ #if defined(_MSC_VER) #if !defined(MBEDTLS_BSWAP16) #define MBEDTLS_BSWAP16 _byteswap_ushort #endif #if !defined(MBEDTLS_BSWAP32) #define MBEDTLS_BSWAP32 _byteswap_ulong #endif #if !defined(MBEDTLS_BSWAP64) #define MBEDTLS_BSWAP64 _byteswap_uint64 #endif #endif /* defined(_MSC_VER) */ /* Detect armcc built-in byteswap routine */ #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32) #if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */ #include #endif #define MBEDTLS_BSWAP32 __rev #endif /* Detect IAR built-in byteswap routine */ #if defined(__IAR_SYSTEMS_ICC__) #if defined(__ARM_ACLE) #include #define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x))) #define MBEDTLS_BSWAP32 __rev #define MBEDTLS_BSWAP64 __revll #endif #endif /* * Where compiler built-ins are not present, fall back to C code that the * compiler may be able to detect and transform into the relevant bswap or * similar instruction. */ #if !defined(MBEDTLS_BSWAP16) static inline uint16_t mbedtls_bswap16(uint16_t x) { return (x & 0x00ff) << 8 | (x & 0xff00) >> 8; } #define MBEDTLS_BSWAP16 mbedtls_bswap16 #endif /* !defined(MBEDTLS_BSWAP16) */ #if !defined(MBEDTLS_BSWAP32) static inline uint32_t mbedtls_bswap32(uint32_t x) { return (x & 0x000000ff) << 24 | (x & 0x0000ff00) << 8 | (x & 0x00ff0000) >> 8 | (x & 0xff000000) >> 24; } #define MBEDTLS_BSWAP32 mbedtls_bswap32 #endif /* !defined(MBEDTLS_BSWAP32) */ #if !defined(MBEDTLS_BSWAP64) static inline uint64_t mbedtls_bswap64(uint64_t x) { return (x & 0x00000000000000ffULL) << 56 | (x & 0x000000000000ff00ULL) << 40 | (x & 0x0000000000ff0000ULL) << 24 | (x & 0x00000000ff000000ULL) << 8 | (x & 0x000000ff00000000ULL) >> 8 | (x & 0x0000ff0000000000ULL) >> 24 | (x & 0x00ff000000000000ULL) >> 40 | (x & 0xff00000000000000ULL) >> 56; } #define MBEDTLS_BSWAP64 mbedtls_bswap64 #endif /* !defined(MBEDTLS_BSWAP64) */ #if !defined(__BYTE_ORDER__) #if defined(__LITTLE_ENDIAN__) /* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */ #define MBEDTLS_IS_BIG_ENDIAN 0 #elif defined(__BIG_ENDIAN__) #define MBEDTLS_IS_BIG_ENDIAN 1 #else static const uint16_t mbedtls_byte_order_detector = { 0x100 }; #define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01) #endif #else #if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__) #define MBEDTLS_IS_BIG_ENDIAN 1 #else #define MBEDTLS_IS_BIG_ENDIAN 0 #endif #endif /* !defined(__BYTE_ORDER__) */ /** * Get the unsigned 32 bits integer corresponding to four bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the four bytes from. * \param offset Offset from \p data of the first and most significant * byte of the four bytes to build the 32 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT32_BE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? mbedtls_get_unaligned_uint32((data) + (offset)) \ : MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ ) /** * Put in memory a 32 bits unsigned integer in big-endian order. * * \param n 32 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 32 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 32 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT32_BE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \ } \ else \ { \ mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ } \ } /** * Get the unsigned 32 bits integer corresponding to four bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the four bytes from. * \param offset Offset from \p data of the first and least significant * byte of the four bytes to build the 32 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT32_LE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \ : mbedtls_get_unaligned_uint32((data) + (offset)) \ ) /** * Put in memory a 32 bits unsigned integer in little-endian order. * * \param n 32 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 32 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 32 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT32_LE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \ } \ else \ { \ mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \ } \ } /** * Get the unsigned 16 bits integer corresponding to two bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the two bytes from. * \param offset Offset from \p data of the first and least significant * byte of the two bytes to build the 16 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT16_LE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ : mbedtls_get_unaligned_uint16((data) + (offset)) \ ) /** * Put in memory a 16 bits unsigned integer in little-endian order. * * \param n 16 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 16 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 16 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT16_LE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ } \ else \ { \ mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ } \ } /** * Get the unsigned 16 bits integer corresponding to two bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the two bytes from. * \param offset Offset from \p data of the first and most significant * byte of the two bytes to build the 16 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT16_BE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? mbedtls_get_unaligned_uint16((data) + (offset)) \ : MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \ ) /** * Put in memory a 16 bits unsigned integer in big-endian order. * * \param n 16 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 16 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 16 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT16_BE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \ } \ else \ { \ mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \ } \ } /** * Get the unsigned 24 bits integer corresponding to three bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the three bytes from. * \param offset Offset from \p data of the first and most significant * byte of the three bytes to build the 24 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT24_BE(data, offset) \ ( \ ((uint32_t) (data)[(offset)] << 16) \ | ((uint32_t) (data)[(offset) + 1] << 8) \ | ((uint32_t) (data)[(offset) + 2]) \ ) /** * Put in memory a 24 bits unsigned integer in big-endian order. * * \param n 24 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 24 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 24 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT24_BE(n, data, offset) \ { \ (data)[(offset)] = MBEDTLS_BYTE_2(n); \ (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ (data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \ } /** * Get the unsigned 24 bits integer corresponding to three bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the three bytes from. * \param offset Offset from \p data of the first and least significant * byte of the three bytes to build the 24 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT24_LE(data, offset) \ ( \ ((uint32_t) (data)[(offset)]) \ | ((uint32_t) (data)[(offset) + 1] << 8) \ | ((uint32_t) (data)[(offset) + 2] << 16) \ ) /** * Put in memory a 24 bits unsigned integer in little-endian order. * * \param n 24 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 24 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 24 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT24_LE(n, data, offset) \ { \ (data)[(offset)] = MBEDTLS_BYTE_0(n); \ (data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \ (data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \ } /** * Get the unsigned 64 bits integer corresponding to eight bytes in * big-endian order (MSB first). * * \param data Base address of the memory to get the eight bytes from. * \param offset Offset from \p data of the first and most significant * byte of the eight bytes to build the 64 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT64_BE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? mbedtls_get_unaligned_uint64((data) + (offset)) \ : MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ ) /** * Put in memory a 64 bits unsigned integer in big-endian order. * * \param n 64 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 64 * bits unsigned integer in. * \param offset Offset from \p data where to put the most significant * byte of the 64 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT64_BE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ } \ else \ { \ mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ } \ } /** * Get the unsigned 64 bits integer corresponding to eight bytes in * little-endian order (LSB first). * * \param data Base address of the memory to get the eight bytes from. * \param offset Offset from \p data of the first and least significant * byte of the eight bytes to build the 64 bits unsigned * integer from. */ #define MBEDTLS_GET_UINT64_LE(data, offset) \ ((MBEDTLS_IS_BIG_ENDIAN) \ ? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \ : mbedtls_get_unaligned_uint64((data) + (offset)) \ ) /** * Put in memory a 64 bits unsigned integer in little-endian order. * * \param n 64 bits unsigned integer to put in memory. * \param data Base address of the memory where to put the 64 * bits unsigned integer in. * \param offset Offset from \p data where to put the least significant * byte of the 64 bits unsigned integer \p n. */ #define MBEDTLS_PUT_UINT64_LE(n, data, offset) \ { \ if (MBEDTLS_IS_BIG_ENDIAN) \ { \ mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \ } \ else \ { \ mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \ } \ } #endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/aria.c000066400000000000000000001041011464416617300224110ustar00rootroot00000000000000/* * ARIA implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This implementation is based on the following standards: * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf * [2] https://tools.ietf.org/html/rfc5794 */ #include "common.h" #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_ARIA_ALT) #include "mbedtls/platform_util.h" /* * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes * * This is submatrix P1 in [1] Appendix B.1 * * Common compilers fail to translate this to minimal number of instructions, * so let's provide asm versions for common platforms with C fallback. */ #if defined(MBEDTLS_HAVE_ASM) #if defined(__arm__) /* rev16 available from v6 up */ /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ (!defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000) && \ __ARM_ARCH >= 6 static inline uint32_t aria_p1(uint32_t x) { uint32_t r; __asm("rev16 %0, %1" : "=l" (r) : "l" (x)); return r; } #define ARIA_P1 aria_p1 #elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ (__TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3) static inline uint32_t aria_p1(uint32_t x) { uint32_t r; __asm("rev16 r, x"); return r; } #define ARIA_P1 aria_p1 #endif #endif /* arm */ #if defined(__GNUC__) && \ defined(__i386__) || defined(__amd64__) || defined(__x86_64__) /* I couldn't find an Intel equivalent of rev16, so two instructions */ #define ARIA_P1(x) ARIA_P2(ARIA_P3(x)) #endif /* x86 gnuc */ #endif /* MBEDTLS_HAVE_ASM && GNUC */ #if !defined(ARIA_P1) #define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) #endif /* * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits * * This is submatrix P2 in [1] Appendix B.1 * * Common compilers will translate this to a single instruction. */ #define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) /* * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness * * This is submatrix P3 in [1] Appendix B.1 */ #define ARIA_P3(x) MBEDTLS_BSWAP32(x) /* * ARIA Affine Transform * (a, b, c, d) = state in/out * * If we denote the first byte of input by 0, ..., the last byte by f, * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. * * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple * rearrangements on adjacent pairs, output is: * * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef * * Note: another presentation of the A transform can be found as the first * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. * The implementation below uses only P1 and P2 as they are sufficient. */ static inline void aria_a(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) { uint32_t ta, tb, tc; ta = *b; // 4567 *b = *a; // 0123 *a = ARIA_P2(ta); // 6745 tb = ARIA_P2(*d); // efcd *d = ARIA_P1(*c); // 98ba *c = ARIA_P1(tb); // fedc ta ^= *d; // 4567+98ba tc = ARIA_P2(*b); // 2301 ta = ARIA_P1(ta) ^ tc ^ *c; // 2301+5476+89ab+fedc tb ^= ARIA_P2(*d); // ba98+efcd tc ^= ARIA_P1(*a); // 2301+7654 *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT tb = ARIA_P2(tb) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc *a ^= ARIA_P1(tb); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT ta = ARIA_P2(ta); // 0123+7654+ab89+dcfe *d ^= ARIA_P1(ta) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT tc = ARIA_P2(tc); // 0123+5476 *c ^= ARIA_P1(tc) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT } /* * ARIA Substitution Layer SL1 / SL2 * (a, b, c, d) = state in/out * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) * * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 */ static inline void aria_sl(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d, const uint8_t sa[256], const uint8_t sb[256], const uint8_t sc[256], const uint8_t sd[256]) { *a = ((uint32_t) sa[MBEDTLS_BYTE_0(*a)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*a)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*a)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*a)]) << 24); *b = ((uint32_t) sa[MBEDTLS_BYTE_0(*b)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*b)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*b)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*b)]) << 24); *c = ((uint32_t) sa[MBEDTLS_BYTE_0(*c)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*c)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*c)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*c)]) << 24); *d = ((uint32_t) sa[MBEDTLS_BYTE_0(*d)]) ^ (((uint32_t) sb[MBEDTLS_BYTE_1(*d)]) << 8) ^ (((uint32_t) sc[MBEDTLS_BYTE_2(*d)]) << 16) ^ (((uint32_t) sd[MBEDTLS_BYTE_3(*d)]) << 24); } /* * S-Boxes */ static const uint8_t aria_sb1[256] = { 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; static const uint8_t aria_sb2[256] = { 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, 0xAF, 0xBA, 0xB5, 0x81 }; static const uint8_t aria_is1[256] = { 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; static const uint8_t aria_is2[256] = { 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, 0x03, 0xA2, 0xAC, 0x60 }; /* * Helper for key schedule: r = FO( p, k ) ^ x */ static void aria_fo_xor(uint32_t r[4], const uint32_t p[4], const uint32_t k[4], const uint32_t x[4]) { uint32_t a, b, c, d; a = p[0] ^ k[0]; b = p[1] ^ k[1]; c = p[2] ^ k[2]; d = p[3] ^ k[3]; aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2); aria_a(&a, &b, &c, &d); r[0] = a ^ x[0]; r[1] = b ^ x[1]; r[2] = c ^ x[2]; r[3] = d ^ x[3]; } /* * Helper for key schedule: r = FE( p, k ) ^ x */ static void aria_fe_xor(uint32_t r[4], const uint32_t p[4], const uint32_t k[4], const uint32_t x[4]) { uint32_t a, b, c, d; a = p[0] ^ k[0]; b = p[1] ^ k[1]; c = p[2] ^ k[2]; d = p[3] ^ k[3]; aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2); aria_a(&a, &b, &c, &d); r[0] = a ^ x[0]; r[1] = b ^ x[1]; r[2] = c ^ x[2]; r[3] = d ^ x[3]; } /* * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. * * We chose to store bytes into 32-bit words in little-endian format (see * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse * bytes here. */ static void aria_rot128(uint32_t r[4], const uint32_t a[4], const uint32_t b[4], uint8_t n) { uint8_t i, j; uint32_t t, u; const uint8_t n1 = n % 32; // bit offset const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset j = (n / 32) % 4; // initial word offset t = ARIA_P3(b[j]); // big endian for (i = 0; i < 4; i++) { j = (j + 1) % 4; // get next word, big endian u = ARIA_P3(b[j]); t <<= n1; // rotate t |= u >> n2; t = ARIA_P3(t); // back to little endian r[i] = a[i] ^ t; // store t = u; // move to next word } } /* * Set encryption key */ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits) { /* round constant masks */ const uint32_t rc[3][4] = { { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } }; int i; uint32_t w[4][4], *w2; if (keybits != 128 && keybits != 192 && keybits != 256) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } /* Copy key to W0 (and potential remainder to W1) */ w[0][0] = MBEDTLS_GET_UINT32_LE(key, 0); w[0][1] = MBEDTLS_GET_UINT32_LE(key, 4); w[0][2] = MBEDTLS_GET_UINT32_LE(key, 8); w[0][3] = MBEDTLS_GET_UINT32_LE(key, 12); memset(w[1], 0, 16); if (keybits >= 192) { w[1][0] = MBEDTLS_GET_UINT32_LE(key, 16); // 192 bit key w[1][1] = MBEDTLS_GET_UINT32_LE(key, 20); } if (keybits == 256) { w[1][2] = MBEDTLS_GET_UINT32_LE(key, 24); // 256 bit key w[1][3] = MBEDTLS_GET_UINT32_LE(key, 28); } i = (keybits - 128) >> 6; // index: 0, 1, 2 ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 aria_fo_xor(w[1], w[0], rc[i], w[1]); // W1 = FO(W0, CK1) ^ KR i = i < 2 ? i + 1 : 0; aria_fe_xor(w[2], w[1], rc[i], w[0]); // W2 = FE(W1, CK2) ^ W0 i = i < 2 ? i + 1 : 0; aria_fo_xor(w[3], w[2], rc[i], w[1]); // W3 = FO(W2, CK3) ^ W1 for (i = 0; i < 4; i++) { // create round keys w2 = w[(i + 1) & 3]; aria_rot128(ctx->rk[i], w[i], w2, 128 - 19); aria_rot128(ctx->rk[i + 4], w[i], w2, 128 - 31); aria_rot128(ctx->rk[i + 8], w[i], w2, 61); aria_rot128(ctx->rk[i + 12], w[i], w2, 31); } aria_rot128(ctx->rk[16], w[0], w[1], 19); /* w holds enough info to reconstruct the round keys */ mbedtls_platform_zeroize(w, sizeof(w)); return 0; } /* * Set decryption key */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx, const unsigned char *key, unsigned int keybits) { int i, j, k, ret; ret = mbedtls_aria_setkey_enc(ctx, key, keybits); if (ret != 0) { return ret; } /* flip the order of round keys */ for (i = 0, j = ctx->nr; i < j; i++, j--) { for (k = 0; k < 4; k++) { uint32_t t = ctx->rk[i][k]; ctx->rk[i][k] = ctx->rk[j][k]; ctx->rk[j][k] = t; } } /* apply affine transform to middle keys */ for (i = 1; i < ctx->nr; i++) { aria_a(&ctx->rk[i][0], &ctx->rk[i][1], &ctx->rk[i][2], &ctx->rk[i][3]); } return 0; } #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* * Encrypt a block */ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx, const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], unsigned char output[MBEDTLS_ARIA_BLOCKSIZE]) { int i; uint32_t a, b, c, d; a = MBEDTLS_GET_UINT32_LE(input, 0); b = MBEDTLS_GET_UINT32_LE(input, 4); c = MBEDTLS_GET_UINT32_LE(input, 8); d = MBEDTLS_GET_UINT32_LE(input, 12); i = 0; while (1) { a ^= ctx->rk[i][0]; b ^= ctx->rk[i][1]; c ^= ctx->rk[i][2]; d ^= ctx->rk[i][3]; i++; aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2); aria_a(&a, &b, &c, &d); a ^= ctx->rk[i][0]; b ^= ctx->rk[i][1]; c ^= ctx->rk[i][2]; d ^= ctx->rk[i][3]; i++; aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2); if (i >= ctx->nr) { break; } aria_a(&a, &b, &c, &d); } /* final key mixing */ a ^= ctx->rk[i][0]; b ^= ctx->rk[i][1]; c ^= ctx->rk[i][2]; d ^= ctx->rk[i][3]; MBEDTLS_PUT_UINT32_LE(a, output, 0); MBEDTLS_PUT_UINT32_LE(b, output, 4); MBEDTLS_PUT_UINT32_LE(c, output, 8); MBEDTLS_PUT_UINT32_LE(d, output, 12); return 0; } /* Initialize context */ void mbedtls_aria_init(mbedtls_aria_context *ctx) { memset(ctx, 0, sizeof(mbedtls_aria_context)); } /* Clear context */ void mbedtls_aria_free(mbedtls_aria_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aria_context)); } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * ARIA-CBC buffer encryption/decryption */ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx, int mode, size_t length, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output) { unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } if (length % MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_ARIA_DECRYPT) { while (length > 0) { memcpy(temp, input, MBEDTLS_ARIA_BLOCKSIZE); mbedtls_aria_crypt_ecb(ctx, input, output); mbedtls_xor(output, output, iv, MBEDTLS_ARIA_BLOCKSIZE); memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE); input += MBEDTLS_ARIA_BLOCKSIZE; output += MBEDTLS_ARIA_BLOCKSIZE; length -= MBEDTLS_ARIA_BLOCKSIZE; } } else { while (length > 0) { mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE); mbedtls_aria_crypt_ecb(ctx, output, output); memcpy(iv, output, MBEDTLS_ARIA_BLOCKSIZE); input += MBEDTLS_ARIA_BLOCKSIZE; output += MBEDTLS_ARIA_BLOCKSIZE; length -= MBEDTLS_ARIA_BLOCKSIZE; } } return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * ARIA-CFB128 buffer encryption/decryption */ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output) { unsigned char c; size_t n; if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } n = *iv_off; /* An overly large value of n can lead to an unlimited * buffer overflow. */ if (n >= MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } if (mode == MBEDTLS_ARIA_DECRYPT) { while (length--) { if (n == 0) { mbedtls_aria_crypt_ecb(ctx, iv, iv); } c = *input++; *output++ = c ^ iv[n]; iv[n] = c; n = (n + 1) & 0x0F; } } else { while (length--) { if (n == 0) { mbedtls_aria_crypt_ecb(ctx, iv, iv); } iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); n = (n + 1) & 0x0F; } } *iv_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * ARIA-CTR buffer encryption/decryption */ int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], const unsigned char *input, unsigned char *output) { int c, i; size_t n; n = *nc_off; /* An overly large value of n can lead to an unlimited * buffer overflow. */ if (n >= MBEDTLS_ARIA_BLOCKSIZE) { return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA; } while (length--) { if (n == 0) { mbedtls_aria_crypt_ecb(ctx, nonce_counter, stream_block); for (i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i--) { if (++nonce_counter[i - 1] != 0) { break; } } } c = *input++; *output++ = (unsigned char) (c ^ stream_block[n]); n = (n + 1) & 0x0F; } *nc_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* !MBEDTLS_ARIA_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * Basic ARIA ECB test vectors from RFC 5794 */ static const uint8_t aria_test1_ecb_key[32] = // test key { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit }; static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes }; static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext { { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } }; /* * Mode tests from "Test Vectors for ARIA" Version 1.0 * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf */ #if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_CTR)) static const uint8_t aria_test2_key[32] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit }; static const uint8_t aria_test2_pt[48] = { 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, }; #endif #if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = { 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV }; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext { { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext { { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext { { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #define ARIA_SELF_TEST_ASSERT(cond) \ do { \ if (cond) { \ if (verbose) \ mbedtls_printf("failed\n"); \ goto exit; \ } else { \ if (verbose) \ mbedtls_printf("passed\n"); \ } \ } while (0) /* * Checkup routine */ int mbedtls_aria_self_test(int verbose) { int i; uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; mbedtls_aria_context ctx; int ret = 1; #if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) size_t j; #endif #if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ defined(MBEDTLS_CIPHER_MODE_CFB) || \ defined(MBEDTLS_CIPHER_MODE_CTR)) uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; #endif mbedtls_aria_init(&ctx); /* * Test set 1 */ for (i = 0; i < 3; i++) { /* test ECB encryption */ if (verbose) { mbedtls_printf(" ARIA-ECB-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test1_ecb_key, 128 + 64 * i); mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_pt, blk); ARIA_SELF_TEST_ASSERT( memcmp(blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE) != 0); /* test ECB decryption */ if (verbose) { mbedtls_printf(" ARIA-ECB-%d (dec): ", 128 + 64 * i); #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) mbedtls_printf("skipped\n"); #endif } #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i); mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk); ARIA_SELF_TEST_ASSERT( memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE) != 0); #endif } if (verbose) { mbedtls_printf("\n"); } /* * Test set 2 */ #if defined(MBEDTLS_CIPHER_MODE_CBC) for (i = 0; i < 3; i++) { /* Test CBC encryption */ if (verbose) { mbedtls_printf(" ARIA-CBC-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0x55, sizeof(buf)); mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, aria_test2_pt, buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cbc_ct[i], 48) != 0); /* Test CBC decryption */ if (verbose) { mbedtls_printf(" ARIA-CBC-%d (dec): ", 128 + 64 * i); } mbedtls_aria_setkey_dec(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0xAA, sizeof(buf)); mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, aria_test2_cbc_ct[i], buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); } if (verbose) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) for (i = 0; i < 3; i++) { /* Test CFB encryption */ if (verbose) { mbedtls_printf(" ARIA-CFB-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0x55, sizeof(buf)); j = 0; mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, aria_test2_pt, buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cfb_ct[i], 48) != 0); /* Test CFB decryption */ if (verbose) { mbedtls_printf(" ARIA-CFB-%d (dec): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE); memset(buf, 0xAA, sizeof(buf)); j = 0; mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, iv, aria_test2_cfb_ct[i], buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); } if (verbose) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) for (i = 0; i < 3; i++) { /* Test CTR encryption */ if (verbose) { mbedtls_printf(" ARIA-CTR-%d (enc): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE); // IV = 0 memset(buf, 0x55, sizeof(buf)); j = 0; mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk, aria_test2_pt, buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_ctr_ct[i], 48) != 0); /* Test CTR decryption */ if (verbose) { mbedtls_printf(" ARIA-CTR-%d (dec): ", 128 + 64 * i); } mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i); memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE); // IV = 0 memset(buf, 0xAA, sizeof(buf)); j = 0; mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk, aria_test2_ctr_ct[i], buf); ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0); } if (verbose) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ ret = 0; exit: mbedtls_aria_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_ARIA_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/asn1parse.c000066400000000000000000000257521464416617300234100ustar00rootroot00000000000000/* * Generic ASN.1 parsing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #include "mbedtls/platform.h" /* * ASN.1 DER decoding routines */ int mbedtls_asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len) { if ((end - *p) < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } if ((**p & 0x80) == 0) { *len = *(*p)++; } else { int n = (**p) & 0x7F; if (n == 0 || n > 4) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } if ((end - *p) <= n) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } *len = 0; (*p)++; while (n--) { *len = (*len << 8) | **p; (*p)++; } } if (*len > (size_t) (end - *p)) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } return 0; } int mbedtls_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len, int tag) { if ((end - *p) < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } if (**p != tag) { return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG; } (*p)++; return mbedtls_asn1_get_len(p, end, len); } #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_PARSE_C) int mbedtls_asn1_get_bool(unsigned char **p, const unsigned char *end, int *val) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) { return ret; } if (len != 1) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } *val = (**p != 0) ? 1 : 0; (*p)++; return 0; } static int asn1_get_tagged_int(unsigned char **p, const unsigned char *end, int tag, int *val) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) { return ret; } /* * len==0 is malformed (0 must be represented as 020100 for INTEGER, * or 0A0100 for ENUMERATED tags */ if (len == 0) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } /* This is a cryptography library. Reject negative integers. */ if ((**p & 0x80) != 0) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } /* Skip leading zeros. */ while (len > 0 && **p == 0) { ++(*p); --len; } /* Reject integers that don't fit in an int. This code assumes that * the int type has no padding bit. */ if (len > sizeof(int)) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } if (len == sizeof(int) && (**p & 0x80) != 0) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } *val = 0; while (len-- > 0) { *val = (*val << 8) | **p; (*p)++; } return 0; } int mbedtls_asn1_get_int(unsigned char **p, const unsigned char *end, int *val) { return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val); } int mbedtls_asn1_get_enum(unsigned char **p, const unsigned char *end, int *val) { return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val); } #if defined(MBEDTLS_BIGNUM_C) int mbedtls_asn1_get_mpi(unsigned char **p, const unsigned char *end, mbedtls_mpi *X) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { return ret; } ret = mbedtls_mpi_read_binary(X, *p, len); *p += len; return ret; } #endif /* MBEDTLS_BIGNUM_C */ int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, mbedtls_asn1_bitstring *bs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Certificate type is a single byte bitstring */ if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) { return ret; } /* Check length, subtract one for actual bit string length */ if (bs->len < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } bs->len -= 1; /* Get number of unused bits, ensure unused bits <= 7 */ bs->unused_bits = **p; if (bs->unused_bits > 7) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } (*p)++; /* Get actual bitstring */ bs->p = *p; *p += bs->len; if (*p != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } /* * Traverse an ASN.1 "SEQUENCE OF " * and call a callback for each entry found. */ int mbedtls_asn1_traverse_sequence_of( unsigned char **p, const unsigned char *end, unsigned char tag_must_mask, unsigned char tag_must_val, unsigned char tag_may_mask, unsigned char tag_may_val, int (*cb)(void *ctx, int tag, unsigned char *start, size_t len), void *ctx) { int ret; size_t len; /* Get main sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if (*p + len != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } while (*p < end) { unsigned char const tag = *(*p)++; if ((tag & tag_must_mask) != tag_must_val) { return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG; } if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) { return ret; } if ((tag & tag_may_mask) == tag_may_val) { if (cb != NULL) { ret = cb(ctx, tag, *p, len); if (ret != 0) { return ret; } } } *p += len; } return 0; } /* * Get a bit string without unused bits */ int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, size_t *len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) { return ret; } if (*len == 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } --(*len); if (**p != 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } ++(*p); return 0; } void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq) { while (seq != NULL) { mbedtls_asn1_sequence *next = seq->next; mbedtls_free(seq); seq = next; } } typedef struct { int tag; mbedtls_asn1_sequence *cur; } asn1_get_sequence_of_cb_ctx_t; static int asn1_get_sequence_of_cb(void *ctx, int tag, unsigned char *start, size_t len) { asn1_get_sequence_of_cb_ctx_t *cb_ctx = (asn1_get_sequence_of_cb_ctx_t *) ctx; mbedtls_asn1_sequence *cur = cb_ctx->cur; if (cur->buf.p != NULL) { cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); if (cur->next == NULL) { return MBEDTLS_ERR_ASN1_ALLOC_FAILED; } cur = cur->next; } cur->buf.p = start; cur->buf.len = len; cur->buf.tag = tag; cb_ctx->cur = cur; return 0; } /* * Parses and splits an ASN.1 "SEQUENCE OF " */ int mbedtls_asn1_get_sequence_of(unsigned char **p, const unsigned char *end, mbedtls_asn1_sequence *cur, int tag) { asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; memset(cur, 0, sizeof(mbedtls_asn1_sequence)); return mbedtls_asn1_traverse_sequence_of( p, end, 0xFF, tag, 0, 0, asn1_get_sequence_of_cb, &cb_ctx); } int mbedtls_asn1_get_alg(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if ((end - *p) < 1) { return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } alg->tag = **p; end = *p + len; if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) { return ret; } alg->p = *p; *p += alg->len; if (*p == end) { mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf)); return 0; } params->tag = **p; (*p)++; if ((ret = mbedtls_asn1_get_len(p, end, ¶ms->len)) != 0) { return ret; } params->p = *p; *p += params->len; if (*p != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } int mbedtls_asn1_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf params; memset(¶ms, 0, sizeof(mbedtls_asn1_buf)); if ((ret = mbedtls_asn1_get_alg(p, end, alg, ¶ms)) != 0) { return ret; } if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } return 0; } #if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur) { if (cur == NULL) { return; } mbedtls_free(cur->oid.p); mbedtls_free(cur->val.p); mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data)); } #endif /* MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) { mbedtls_asn1_named_data *cur; while ((cur = *head) != NULL) { *head = cur->next; mbedtls_free(cur->oid.p); mbedtls_free(cur->val.p); mbedtls_free(cur); } } void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name) { for (mbedtls_asn1_named_data *next; name != NULL; name = next) { next = name->next; mbedtls_free(name); } } const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list, const char *oid, size_t len) { while (list != NULL) { if (list->oid.len == len && memcmp(list->oid.p, oid, len) == 0) { break; } list = list->next; } return list; } #endif /* MBEDTLS_ASN1_PARSE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/asn1write.c000066400000000000000000000303431464416617300234200ustar00rootroot00000000000000/* * ASN.1 buffer writing functionality * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #endif int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len) { #if SIZE_MAX > 0xFFFFFFFF if (len > 0xFFFFFFFF) { return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } #endif int required = 1; if (len >= 0x80) { for (size_t l = len; l != 0; l >>= 8) { required++; } } if (required > (*p - start)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } do { *--(*p) = MBEDTLS_BYTE_0(len); len >>= 8; } while (len); if (required > 1) { *--(*p) = (unsigned char) (0x80 + required - 1); } return required; } int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = tag; return 1; } #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ #if defined(MBEDTLS_ASN1_WRITE_C) static int mbedtls_asn1_write_len_and_tag(unsigned char **p, const unsigned char *start, size_t len, unsigned char tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); return (int) len; } int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size) { size_t len = 0; if (*p < start || (size_t) (*p - start) < size) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len = size; (*p) -= len; memcpy(*p, buf, len); return (int) len; } #if defined(MBEDTLS_BIGNUM_C) int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; // Write the MPI // len = mbedtls_mpi_size(X); /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not * as 0 digits. We need to end up with 020100, not with 0200. */ if (len == 0) { len = 1; } if (*p < start || (size_t) (*p - start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } (*p) -= len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len)); // DER format assumes 2s complement for numbers, so the leftmost bit // should be 0 for positive numbers and 1 for negative numbers. // if (X->s == 1 && **p & 0x80) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = 0x00; len += 1; } ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER); cleanup: return ret; } #endif /* MBEDTLS_BIGNUM_C */ int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start) { // Write NULL // return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL); } int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) oid, oid_len)); return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID); } int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len) { return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1); } int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start, const char *oid, size_t oid_len, size_t par_len, int has_par) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (has_par) { if (par_len == 0) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start)); } else { len += par_len; } } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); } int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean) { size_t len = 0; if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = (boolean) ? 255 : 0; len++; return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN); } static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag) { size_t len = 0; do { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len += 1; *--(*p) = val & 0xff; val >>= 8; } while (val > 0); if (**p & 0x80) { if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = 0x00; len += 1; } return mbedtls_asn1_write_len_and_tag(p, start, len, tag); } int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val) { return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER); } int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val) { return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED); } int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, const char *text, size_t text_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) text, text_len)); return mbedtls_asn1_write_len_and_tag(p, start, len, tag); } int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len); } int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len); } int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, const char *text, size_t text_len) { return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len); } int mbedtls_asn1_write_named_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits) { size_t unused_bits, byte_len; const unsigned char *cur_byte; unsigned char cur_byte_shifted; unsigned char bit; byte_len = (bits + 7) / 8; unused_bits = (byte_len * 8) - bits; /* * Named bitstrings require that trailing 0s are excluded in the encoding * of the bitstring. Trailing 0s are considered part of the 'unused' bits * when encoding this value in the first content octet */ if (bits != 0) { cur_byte = buf + byte_len - 1; cur_byte_shifted = *cur_byte >> unused_bits; for (;;) { bit = cur_byte_shifted & 0x1; cur_byte_shifted >>= 1; if (bit != 0) { break; } bits--; if (bits == 0) { break; } if (bits % 8 == 0) { cur_byte_shifted = *--cur_byte; } } } return mbedtls_asn1_write_bitstring(p, start, buf, bits); } int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t bits) { size_t len = 0; size_t unused_bits, byte_len; byte_len = (bits + 7) / 8; unused_bits = (byte_len * 8) - bits; if (*p < start || (size_t) (*p - start) < byte_len + 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len = byte_len + 1; /* Write the bitstring. Ensure the unused bits are zeroed */ if (byte_len > 0) { byte_len--; *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1); (*p) -= byte_len; memcpy(*p, buf, byte_len); } /* Write unused bits */ *--(*p) = (unsigned char) unused_bits; return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING); } int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, const unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size)); return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING); } #if !defined(MBEDTLS_ASN1_PARSE_C) /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ static mbedtls_asn1_named_data *asn1_find_named_data( mbedtls_asn1_named_data *list, const char *oid, size_t len) { while (list != NULL) { if (list->oid.len == len && memcmp(list->oid.p, oid, len) == 0) { break; } list = list->next; } return list; } #else #define asn1_find_named_data(list, oid, len) \ ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len)) #endif mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len) { mbedtls_asn1_named_data *cur; if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) { // Add new entry if not present yet based on OID // cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1, sizeof(mbedtls_asn1_named_data)); if (cur == NULL) { return NULL; } cur->oid.len = oid_len; cur->oid.p = mbedtls_calloc(1, oid_len); if (cur->oid.p == NULL) { mbedtls_free(cur); return NULL; } memcpy(cur->oid.p, oid, oid_len); cur->val.len = val_len; if (val_len != 0) { cur->val.p = mbedtls_calloc(1, val_len); if (cur->val.p == NULL) { mbedtls_free(cur->oid.p); mbedtls_free(cur); return NULL; } } cur->next = *head; *head = cur; } else if (val_len == 0) { mbedtls_free(cur->val.p); cur->val.p = NULL; } else if (cur->val.len != val_len) { /* * Enlarge existing value buffer if needed * Preserve old data until the allocation succeeded, to leave list in * a consistent state in case allocation fails. */ void *p = mbedtls_calloc(1, val_len); if (p == NULL) { return NULL; } mbedtls_free(cur->val.p); cur->val.p = p; cur->val.len = val_len; } if (val != NULL && val_len != 0) { memcpy(cur->val.p, val, val_len); } return cur; } #endif /* MBEDTLS_ASN1_WRITE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/base64.c000066400000000000000000000175231464416617300225740ustar00rootroot00000000000000/* * RFC 1521 base64 encoding/decoding * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include #include "common.h" #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #include "base64_internal.h" #include "constant_time_internal.h" #include #if defined(MBEDTLS_SELF_TEST) #include #include "mbedtls/platform.h" #endif /* MBEDTLS_SELF_TEST */ MBEDTLS_STATIC_TESTABLE unsigned char mbedtls_ct_base64_enc_char(unsigned char value) { unsigned char digit = 0; /* For each range of values, if value is in that range, mask digit with * the corresponding value. Since value can only be in a single range, * only at most one masking will change digit. */ digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value); digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26); digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52); digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+'); digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/'); return digit; } MBEDTLS_STATIC_TESTABLE signed char mbedtls_ct_base64_dec_value(unsigned char c) { unsigned char val = 0; /* For each range of digits, if c is in that range, mask val with * the corresponding value. Since c can only be in a single range, * only at most one masking will change val. Set val to one plus * the desired value so that it stays 0 if c is in none of the ranges. */ val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' + 0 + 1); val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1); val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1); val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1); val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1); /* At this point, val is 0 if c is an invalid digit and v+1 if c is * a digit with the value v. */ return val - 1; } /* * Encode a buffer into base64 format */ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) { size_t i, n; int C1, C2, C3; unsigned char *p; if (slen == 0) { *olen = 0; return 0; } n = slen / 3 + (slen % 3 != 0); if (n > (SIZE_MAX - 1) / 4) { *olen = SIZE_MAX; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } n *= 4; if ((dlen < n + 1) || (NULL == dst)) { *olen = n + 1; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } n = (slen / 3) * 3; for (i = 0, p = dst; i < n; i += 3) { C1 = *src++; C2 = *src++; C3 = *src++; *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F); *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4)) & 0x3F); *p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6)) & 0x3F); *p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F); } if (i < slen) { C1 = *src++; C2 = ((i + 1) < slen) ? *src++ : 0; *p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F); *p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4)) & 0x3F); if ((i + 1) < slen) { *p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F); } else { *p++ = '='; } *p++ = '='; } *olen = (size_t) (p - dst); *p = 0; return 0; } /* * Decode a base64-formatted buffer */ int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen) { size_t i; /* index in source */ size_t n; /* number of digits or trailing = in source */ uint32_t x; /* value accumulator */ unsigned accumulated_digits = 0; unsigned equals = 0; int spaces_present = 0; unsigned char *p; /* First pass: check for validity and get output length */ for (i = n = 0; i < slen; i++) { /* Skip spaces before checking for EOL */ spaces_present = 0; while (i < slen && src[i] == ' ') { ++i; spaces_present = 1; } /* Spaces at end of buffer are OK */ if (i == slen) { break; } if ((slen - i) >= 2 && src[i] == '\r' && src[i + 1] == '\n') { continue; } if (src[i] == '\n') { continue; } /* Space inside a line is an error */ if (spaces_present) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } if (src[i] > 127) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } if (src[i] == '=') { if (++equals > 2) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } } else { if (equals != 0) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } if (mbedtls_ct_base64_dec_value(src[i]) < 0) { return MBEDTLS_ERR_BASE64_INVALID_CHARACTER; } } n++; } if (n == 0) { *olen = 0; return 0; } /* The following expression is to calculate the following formula without * risk of integer overflow in n: * n = ( ( n * 6 ) + 7 ) >> 3; */ n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3); n -= equals; if (dst == NULL || dlen < n) { *olen = n; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } equals = 0; for (x = 0, p = dst; i > 0; i--, src++) { if (*src == '\r' || *src == '\n' || *src == ' ') { continue; } x = x << 6; if (*src == '=') { ++equals; } else { x |= mbedtls_ct_base64_dec_value(*src); } if (++accumulated_digits == 4) { accumulated_digits = 0; *p++ = MBEDTLS_BYTE_2(x); if (equals <= 1) { *p++ = MBEDTLS_BYTE_1(x); } if (equals <= 0) { *p++ = MBEDTLS_BYTE_0(x); } } } *olen = (size_t) (p - dst); return 0; } #if defined(MBEDTLS_SELF_TEST) static const unsigned char base64_test_dec[64] = { 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 }; static const unsigned char base64_test_enc[] = "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; /* * Checkup routine */ int mbedtls_base64_self_test(int verbose) { size_t len; const unsigned char *src; unsigned char buffer[128]; if (verbose != 0) { mbedtls_printf(" Base64 encoding test: "); } src = base64_test_dec; if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 || memcmp(base64_test_enc, buffer, 88) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (verbose != 0) { mbedtls_printf("passed\n Base64 decoding test: "); } src = base64_test_enc; if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 || memcmp(base64_test_dec, buffer, 64) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (verbose != 0) { mbedtls_printf("passed\n\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_BASE64_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/base64_internal.h000066400000000000000000000021731464416617300244700ustar00rootroot00000000000000/** * \file base64_internal.h * * \brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BASE64_INTERNAL #define MBEDTLS_BASE64_INTERNAL #include "common.h" #if defined(MBEDTLS_TEST_HOOKS) /** Given a value in the range 0..63, return the corresponding Base64 digit. * * The implementation assumes that letters are consecutive (e.g. ASCII * but not EBCDIC). * * \param value A value in the range 0..63. * * \return A base64 digit converted from \p value. */ unsigned char mbedtls_ct_base64_enc_char(unsigned char value); /** Given a Base64 digit, return its value. * * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), * return -1. * * The implementation assumes that letters are consecutive (e.g. ASCII * but not EBCDIC). * * \param c A base64 digit. * * \return The value of the base64 digit \p c. */ signed char mbedtls_ct_base64_dec_value(unsigned char c); #endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_BASE64_INTERNAL */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum.c000066400000000000000000002261271464416617300227730ustar00rootroot00000000000000/* * Multi-precision integer library * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this Multi-precision * Integer library: * * [1] Handbook of Applied Cryptography - 1997 * Menezes, van Oorschot and Vanstone * * [2] Multi-Precision Math * Tom St Denis * https://github.com/libtom/libtommath/blob/develop/tommath.pdf * * [3] GNU Multi-Precision Arithmetic Library * https://gmplib.org/manual/index.html * */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #include "bignum_core.h" #include "bn_mul.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "constant_time_internal.h" #include #include #include "mbedtls/platform.h" #include void *mbedtls_mpi_mempool; /* * Conditionally select an MPI sign in constant time. * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid * values.) */ static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond, signed short sign1, signed short sign2) { return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1; } /* * Compare signed values in constant time */ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned *ret) { mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result; if (X->n != Y->n) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0. * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. */ X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1); Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1); /* * If the signs are different, then the positive operand is the bigger. * That is if X is negative (X_is_negative == 1), then X < Y is true and it * is false if X is positive (X_is_negative == 0). */ different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign result = mbedtls_ct_bool_and(different_sign, X_is_negative); /* * Assuming signs are the same, compare X and Y. We switch the comparison * order if they are negative so that we get the right result, regardles of * sign. */ /* This array is used to conditionally swap the pointers in const time */ void * const p[2] = { X->p, Y->p }; size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1); mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n); /* * Store in result iff the signs are the same (i.e., iff different_sign == false). If * the signs differ, result has already been set, so we don't change it. */ result = mbedtls_ct_bool_or(result, mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt)); *ret = mbedtls_ct_uint_if_else_0(result, 1); return 0; } /* * Conditionally assign X = Y, without leaking information * about whether the assignment was made or not. * (Leaking information about the respective sizes of X and Y is ok however.) */ #if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ (_MSC_FULL_VER < 193131103) /* * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 */ __declspec(noinline) #endif int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign) { int ret = 0; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); { mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign); X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s); mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign); mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign); for (size_t i = Y->n; i < X->n; i++) { X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]); } } cleanup: return ret; } /* * Conditionally swap X and Y, without leaking information * about whether the swap was made or not. * Here it is not ok to simply swap the pointers, which would lead to * different memory access patterns when X and Y are used afterwards. */ int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap) { int ret = 0; int s; if (X == Y) { return 0; } mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n)); s = X->s; X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s); Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s); mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap); cleanup: return ret; } /* Implementation that should never be optimized out by the compiler */ #define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n)) /* * Implementation that should never be optimized out by the compiler. * Reintroduced to allow use of mempool. */ #define mbedtls_mpi_zeroize(v, n) mbedtls_platform_zeroize(v, ciL * (n)) /* * Initialize one MPI */ static void mpi_init(mbedtls_mpi *X, short use_mempool) { X->s = 1; X->use_mempool = use_mempool; X->n = 0; X->p = NULL; } void mbedtls_mpi_init(mbedtls_mpi *X) { mpi_init(X, 0 /*use_mempool*/); } void mbedtls_mpi_init_mempool(mbedtls_mpi *X) { mpi_init(X, !!mbedtls_mpi_mempool /*use_mempool*/); } /* * Unallocate one MPI */ void mbedtls_mpi_free(mbedtls_mpi *X) { if (X == NULL) { return; } if (X->p != NULL) { if(X->use_mempool) { mbedtls_mpi_zeroize(X->p, X->n); mempool_free(mbedtls_mpi_mempool, X->p); } else { mbedtls_mpi_zeroize_and_free(X->p, X->n); } } X->s = 1; X->n = 0; X->p = NULL; } /* * Enlarge to the specified number of limbs */ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs) { mbedtls_mpi_uint *p; if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } if (X->n < nblimbs) { if(X->use_mempool) { p = mempool_alloc(mbedtls_mpi_mempool, nblimbs * ciL); if(p == NULL) return MBEDTLS_ERR_MPI_ALLOC_FAILED; memset(p, 0, nblimbs * ciL); } else { p = (mbedtls_mpi_uint *) mbedtls_calloc(nblimbs, ciL); if (p == NULL) return MBEDTLS_ERR_MPI_ALLOC_FAILED; } if (X->p != NULL) { memcpy(p, X->p, X->n * ciL); if (X->use_mempool) { mbedtls_mpi_zeroize(X->p, X->n); mempool_free(mbedtls_mpi_mempool, X->p); } else { mbedtls_mpi_zeroize_and_free(X->p, X->n); } } /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ X->n = (unsigned short) nblimbs; X->p = p; } return 0; } /* * Resize down as much as possible, * while keeping at least the specified number of limbs */ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs) { mbedtls_mpi_uint *p; size_t i; if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } /* Actually resize up if there are currently fewer than nblimbs limbs. */ if (X->n <= nblimbs) { return mbedtls_mpi_grow(X, nblimbs); } /* After this point, then X->n > nblimbs and in particular X->n > 0. */ for (i = X->n - 1; i > 0; i--) { if (X->p[i] != 0) { break; } } i++; if (i < nblimbs) { i = nblimbs; } if (X->use_mempool) { p = mempool_alloc(mbedtls_mpi_mempool, i * ciL); if (p == NULL) return MBEDTLS_ERR_MPI_ALLOC_FAILED; memset(p, 0, i * ciL); } else { if ((p = (mbedtls_mpi_uint *) mbedtls_calloc(i, ciL)) == NULL) return MBEDTLS_ERR_MPI_ALLOC_FAILED; } if (X->p != NULL) { memcpy(p, X->p, i * ciL); if (X->use_mempool) { mbedtls_mpi_zeroize(X->p, X->n); mempool_free(mbedtls_mpi_mempool, X->p); } else { mbedtls_mpi_zeroize_and_free(X->p, X->n); } } /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */ X->n = (unsigned short) i; X->p = p; return 0; } /* Resize X to have exactly n limbs and set it to 0. */ static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs) { if (limbs == 0) { mbedtls_mpi_free(X); return 0; } else if (X->n == limbs) { memset(X->p, 0, limbs * ciL); X->s = 1; return 0; } else { mbedtls_mpi_free(X); return mbedtls_mpi_grow(X, limbs); } } /* * Copy the contents of Y into X. * * This function is not constant-time. Leading zeros in Y may be removed. * * Ensure that X does not shrink. This is not guaranteed by the public API, * but some code in the bignum module might still rely on this property. */ int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y) { int ret = 0; size_t i; if (X == Y) { return 0; } if (Y->n == 0) { if (X->n != 0) { X->s = 1; memset(X->p, 0, X->n * ciL); } return 0; } for (i = Y->n - 1; i > 0; i--) { if (Y->p[i] != 0) { break; } } i++; X->s = Y->s; if (X->n < i) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i)); } else { memset(X->p + i, 0, (X->n - i) * ciL); } memcpy(X->p, Y->p, i * ciL); cleanup: return ret; } /* * Swap the contents of X and Y */ void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y) { mbedtls_mpi T; memcpy(&T, X, sizeof(mbedtls_mpi)); memcpy(X, Y, sizeof(mbedtls_mpi)); memcpy(Y, &T, sizeof(mbedtls_mpi)); } static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z) { if (z >= 0) { return z; } /* Take care to handle the most negative value (-2^(biL-1)) correctly. * A naive -z would have undefined behavior. * Write this in a way that makes popular compilers happy (GCC, Clang, * MSVC). */ return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z; } /* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative. * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */ #define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1) /* * Set value from integer */ int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1)); memset(X->p, 0, X->n * ciL); X->p[0] = mpi_sint_abs(z); X->s = TO_SIGN(z); cleanup: return ret; } /* * Get a specific bit */ int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos) { if (X->n * biL <= pos) { return 0; } return (X->p[pos / biL] >> (pos % biL)) & 0x01; } /* * Set a bit to a specific value of 0 or 1 */ int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val) { int ret = 0; size_t off = pos / biL; size_t idx = pos % biL; if (val != 0 && val != 1) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (X->n * biL <= pos) { if (val == 0) { return 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, off + 1)); } X->p[off] &= ~((mbedtls_mpi_uint) 0x01 << idx); X->p[off] |= (mbedtls_mpi_uint) val << idx; cleanup: return ret; } /* * Return the number of less significant zero-bits */ size_t mbedtls_mpi_lsb(const mbedtls_mpi *X) { size_t i; #if defined(__has_builtin) #if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz) #define mbedtls_mpi_uint_ctz __builtin_ctz #elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl) #define mbedtls_mpi_uint_ctz __builtin_ctzl #elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll) #define mbedtls_mpi_uint_ctz __builtin_ctzll #endif #endif #if defined(mbedtls_mpi_uint_ctz) for (i = 0; i < X->n; i++) { if (X->p[i] != 0) { return i * biL + mbedtls_mpi_uint_ctz(X->p[i]); } } #else size_t count = 0; for (i = 0; i < X->n; i++) { for (size_t j = 0; j < biL; j++, count++) { if (((X->p[i] >> j) & 1) != 0) { return count; } } } #endif return 0; } /* * Return the number of bits */ size_t mbedtls_mpi_bitlen(const mbedtls_mpi *X) { return mbedtls_mpi_core_bitlen(X->p, X->n); } /* * Return the total size in bytes */ size_t mbedtls_mpi_size(const mbedtls_mpi *X) { return (mbedtls_mpi_bitlen(X) + 7) >> 3; } /* * Convert an ASCII character to digit value */ static int mpi_get_digit(mbedtls_mpi_uint *d, int radix, char c) { *d = 255; if (c >= 0x30 && c <= 0x39) { *d = c - 0x30; } if (c >= 0x41 && c <= 0x46) { *d = c - 0x37; } if (c >= 0x61 && c <= 0x66) { *d = c - 0x57; } if (*d >= (mbedtls_mpi_uint) radix) { return MBEDTLS_ERR_MPI_INVALID_CHARACTER; } return 0; } /* * Import from an ASCII string */ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, j, slen, n; int sign = 1; mbedtls_mpi_uint d; mbedtls_mpi T; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init_mempool(&T); if (s[0] == 0) { mbedtls_mpi_free(X); return 0; } if (s[0] == '-') { ++s; sign = -1; } slen = strlen(s); if (radix == 16) { if (slen > SIZE_MAX >> 2) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } n = BITS_TO_LIMBS(slen << 2); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); for (i = slen, j = 0; i > 0; i--, j++) { MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i - 1])); X->p[j / (2 * ciL)] |= d << ((j % (2 * ciL)) << 2); } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); for (i = 0; i < slen; i++) { MBEDTLS_MPI_CHK(mpi_get_digit(&d, radix, s[i])); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T, X, radix)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, &T, d)); } } if (sign < 0 && mbedtls_mpi_bitlen(X) != 0) { X->s = -1; } cleanup: mbedtls_mpi_free(&T); return ret; } /* * Helper to write the digits high-order first. */ static int mpi_write_hlp(mbedtls_mpi *X, int radix, char **p, const size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_uint r; size_t length = 0; char *p_end = *p + buflen; do { if (length >= buflen) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, radix)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(X, NULL, X, radix)); /* * Write the residue in the current position, as an ASCII character. */ if (r < 0xA) { *(--p_end) = (char) ('0' + r); } else { *(--p_end) = (char) ('A' + (r - 0xA)); } length++; } while (mbedtls_mpi_cmp_int(X, 0) != 0); memmove(*p, p_end, length); *p += length; cleanup: return ret; } /* * Export into an ASCII string */ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix, char *buf, size_t buflen, size_t *olen) { int ret = 0; size_t n; char *p; mbedtls_mpi T; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } n = mbedtls_mpi_bitlen(X); /* Number of bits necessary to present `n`. */ if (radix >= 4) { n >>= 1; /* Number of 4-adic digits necessary to present * `n`. If radix > 4, this might be a strict * overapproximation of the number of * radix-adic digits needed to present `n`. */ } if (radix >= 16) { n >>= 1; /* Number of hexadecimal digits necessary to * present `n`. */ } n += 1; /* Terminating null byte */ n += 1; /* Compensate for the divisions above, which round down `n` * in case it's not even. */ n += 1; /* Potential '-'-sign. */ n += (n & 1); /* Make n even to have enough space for hexadecimal writing, * which always uses an even number of hex-digits. */ if (buflen < n) { *olen = n; return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } p = buf; mbedtls_mpi_init_mempool(&T); if (X->s == -1) { *p++ = '-'; buflen--; } if (radix == 16) { int c; size_t i, j, k; for (i = X->n, k = 0; i > 0; i--) { for (j = ciL; j > 0; j--) { c = (X->p[i - 1] >> ((j - 1) << 3)) & 0xFF; if (c == 0 && k == 0 && (i + j) != 2) { continue; } *(p++) = "0123456789ABCDEF" [c / 16]; *(p++) = "0123456789ABCDEF" [c % 16]; k = 1; } } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T, X)); if (T.s == -1) { T.s = 1; } MBEDTLS_MPI_CHK(mpi_write_hlp(&T, radix, &p, buflen)); } *p++ = '\0'; *olen = (size_t) (p - buf); cleanup: mbedtls_mpi_free(&T); return ret; } #if defined(MBEDTLS_FS_IO) /* * Read X from an opened file */ int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin) { mbedtls_mpi_uint d; size_t slen; char *p; /* * Buffer should have space for (short) label and decimal formatted MPI, * newline characters and '\0' */ char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } memset(s, 0, sizeof(s)); if (fgets(s, sizeof(s) - 1, fin) == NULL) { return MBEDTLS_ERR_MPI_FILE_IO_ERROR; } slen = strlen(s); if (slen == sizeof(s) - 2) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } if (slen > 0 && s[slen - 1] == '\n') { slen--; s[slen] = '\0'; } if (slen > 0 && s[slen - 1] == '\r') { slen--; s[slen] = '\0'; } p = s + slen; while (p-- > s) { if (mpi_get_digit(&d, radix, *p) != 0) { break; } } return mbedtls_mpi_read_string(X, radix, p + 1); } /* * Write X into an opened file (or stdout if fout == NULL) */ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE *fout) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n, slen, plen; /* * Buffer should have space for (short) label and decimal formatted MPI, * newline characters and '\0' */ char s[MBEDTLS_MPI_RW_BUFFER_SIZE]; if (radix < 2 || radix > 16) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } memset(s, 0, sizeof(s)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_string(X, radix, s, sizeof(s) - 2, &n)); if (p == NULL) { p = ""; } plen = strlen(p); slen = strlen(s); s[slen++] = '\r'; s[slen++] = '\n'; if (fout != NULL) { if (fwrite(p, 1, plen, fout) != plen || fwrite(s, 1, slen, fout) != slen) { return MBEDTLS_ERR_MPI_FILE_IO_ERROR; } } else { mbedtls_printf("%s%s", p, s); } cleanup: return ret; } #endif /* MBEDTLS_FS_IO */ /* * Import X from unsigned binary data, little endian * * This function is guaranteed to return an MPI with exactly the necessary * number of limbs (in particular, it does not skip 0s in the input). */ int mbedtls_mpi_read_binary_le(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(buflen); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_le(X->p, X->n, buf, buflen)); cleanup: /* * This function is also used to import keys. However, wiping the buffers * upon failure is not necessary because failure only can happen before any * input is copied. */ return ret; } /* * Import X from unsigned binary data, big endian * * This function is guaranteed to return an MPI with exactly the necessary * number of limbs (in particular, it does not skip 0s in the input). */ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(buflen); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_core_read_be(X->p, X->n, buf, buflen)); cleanup: /* * This function is also used to import keys. However, wiping the buffers * upon failure is not necessary because failure only can happen before any * input is copied. */ return ret; } /* * Export X into unsigned binary data, little endian */ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X, unsigned char *buf, size_t buflen) { return mbedtls_mpi_core_write_le(X->p, X->n, buf, buflen); } /* * Export X into unsigned binary data, big endian */ int mbedtls_mpi_write_binary(const mbedtls_mpi *X, unsigned char *buf, size_t buflen) { return mbedtls_mpi_core_write_be(X->p, X->n, buf, buflen); } /* * Left-shift: X <<= count */ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; i = mbedtls_mpi_bitlen(X) + count; if (X->n * biL < i) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, BITS_TO_LIMBS(i))); } ret = 0; mbedtls_mpi_core_shift_l(X->p, X->n, count); cleanup: return ret; } /* * Right-shift: X >>= count */ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count) { if (X->n != 0) { mbedtls_mpi_core_shift_r(X->p, X->n, count); } return 0; } /* * Compare unsigned values */ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y) { size_t i, j; for (i = X->n; i > 0; i--) { if (X->p[i - 1] != 0) { break; } } for (j = Y->n; j > 0; j--) { if (Y->p[j - 1] != 0) { break; } } /* If i == j == 0, i.e. abs(X) == abs(Y), * we end up returning 0 at the end of the function. */ if (i > j) { return 1; } if (j > i) { return -1; } for (; i > 0; i--) { if (X->p[i - 1] > Y->p[i - 1]) { return 1; } if (X->p[i - 1] < Y->p[i - 1]) { return -1; } } return 0; } /* * Compare signed values */ int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y) { size_t i, j; for (i = X->n; i > 0; i--) { if (X->p[i - 1] != 0) { break; } } for (j = Y->n; j > 0; j--) { if (Y->p[j - 1] != 0) { break; } } if (i == 0 && j == 0) { return 0; } if (i > j) { return X->s; } if (j > i) { return -Y->s; } if (X->s > 0 && Y->s < 0) { return 1; } if (Y->s > 0 && X->s < 0) { return -1; } for (; i > 0; i--) { if (X->p[i - 1] > Y->p[i - 1]) { return X->s; } if (X->p[i - 1] < Y->p[i - 1]) { return -X->s; } } return 0; } /* * Compare signed values */ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z) { mbedtls_mpi Y; mbedtls_mpi_uint p[1]; *p = mpi_sint_abs(z); Y.s = TO_SIGN(z); Y.n = 1; Y.p = p; return mbedtls_mpi_cmp_mpi(X, &Y); } /* * Unsigned addition: X = |A| + |B| (HAC 14.7) */ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t j; mbedtls_mpi_uint *p; mbedtls_mpi_uint c; if (X == B) { const mbedtls_mpi *T = A; A = X; B = T; } if (X != A) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); } /* * X must always be positive as a result of unsigned additions. */ X->s = 1; for (j = B->n; j > 0; j--) { if (B->p[j - 1] != 0) { break; } } /* Exit early to avoid undefined behavior on NULL+0 when X->n == 0 * and B is 0 (of any size). */ if (j == 0) { return 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j)); /* j is the number of non-zero limbs of B. Add those to X. */ p = X->p; c = mbedtls_mpi_core_add(p, p, B->p, j); p += j; /* Now propagate any carry */ while (c != 0) { if (j >= X->n) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, j + 1)); p = X->p + j; } *p += c; c = (*p < c); j++; p++; } cleanup: return ret; } /* * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) */ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; mbedtls_mpi_uint carry; for (n = B->n; n > 0; n--) { if (B->p[n - 1] != 0) { break; } } if (n > A->n) { /* B >= (2^ciL)^n > A */ ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, A->n)); /* Set the high limbs of X to match A. Don't touch the lower limbs * because X might be aliased to B, and we must not overwrite the * significant digits of B. */ if (A->n > n && A != X) { memcpy(X->p + n, A->p + n, (A->n - n) * ciL); } if (X->n > A->n) { memset(X->p + A->n, 0, (X->n - A->n) * ciL); } carry = mbedtls_mpi_core_sub(X->p, A->p, B->p, n); if (carry != 0) { /* Propagate the carry through the rest of X. */ carry = mbedtls_mpi_core_sub_int(X->p + n, X->p + n, carry, X->n - n); /* If we have further carry/borrow, the result is negative. */ if (carry != 0) { ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; goto cleanup; } } /* X should always be positive as a result of unsigned subtractions. */ X->s = 1; cleanup: return ret; } /* Common function for signed addition and subtraction. * Calculate A + B * flip_B where flip_B is 1 or -1. */ static int add_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B, int flip_B) { int ret, s; s = A->s; if (A->s * B->s * flip_B < 0) { int cmp = mbedtls_mpi_cmp_abs(A, B); if (cmp >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, A, B)); /* If |A| = |B|, the result is 0 and we must set the sign bit * to +1 regardless of which of A or B was negative. Otherwise, * since |A| > |B|, the sign is the sign of A. */ X->s = cmp == 0 ? 1 : s; } else { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(X, B, A)); /* Since |A| < |B|, the sign is the opposite of A. */ X->s = -s; } } else { MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(X, A, B)); X->s = s; } cleanup: return ret; } /* * Signed addition: X = A + B */ int mbedtls_mpi_add_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { return add_sub_mpi(X, A, B, 1); } /* * Signed subtraction: X = A - B */ int mbedtls_mpi_sub_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { return add_sub_mpi(X, A, B, -1); } /* * Signed addition: X = A + b */ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) { mbedtls_mpi B; mbedtls_mpi_uint p[1]; p[0] = mpi_sint_abs(b); B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_add_mpi(X, A, &B); } /* * Signed subtraction: X = A - b */ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b) { mbedtls_mpi B; mbedtls_mpi_uint p[1]; p[0] = mpi_sint_abs(b); B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_sub_mpi(X, A, &B); } /* * Baseline multiplication: X = A * B (HAC 14.12) */ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, j; mbedtls_mpi TA, TB; int result_is_zero = 0; mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB); if (X == A) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA; } if (X == B) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); B = &TB; } for (i = A->n; i > 0; i--) { if (A->p[i - 1] != 0) { break; } } if (i == 0) { result_is_zero = 1; } for (j = B->n; j > 0; j--) { if (B->p[j - 1] != 0) { break; } } if (j == 0) { result_is_zero = 1; } MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0)); mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j); /* If the result is 0, we don't shortcut the operation, which reduces * but does not eliminate side channels leaking the zero-ness. We do * need to take care to set the sign bit properly since the library does * not fully support an MPI object with a value of 0 and s == -1. */ if (result_is_zero) { X->s = 1; } else { X->s = A->s * B->s; } cleanup: mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TA); return ret; } /* * Baseline multiplication: X = A * b */ int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b) { size_t n = A->n; while (n > 0 && A->p[n - 1] == 0) { --n; } /* The general method below doesn't work if b==0. */ if (b == 0 || n == 0) { return mbedtls_mpi_lset(X, 0); } /* Calculate A*b as A + A*(b-1) to take advantage of mbedtls_mpi_core_mla */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* In general, A * b requires 1 limb more than b. If * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same * number of limbs as A and the call to grow() is not required since * copy() will take care of the growth if needed. However, experimentally, * making the call to grow() unconditional causes slightly fewer * calls to calloc() in ECP code, presumably because it reuses the * same mpi for a while and this way the mpi is more likely to directly * grow to its final size. * * Note that calculating A*b as 0 + A*b doesn't work as-is because * A,X can be the same. */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, n + 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)); mbedtls_mpi_core_mla(X->p, X->n, A->p, n, b - 1); cleanup: return ret; } /* * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and * mbedtls_mpi_uint divisor, d */ static mbedtls_mpi_uint mbedtls_int_div_int(mbedtls_mpi_uint u1, mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r) { #if defined(MBEDTLS_HAVE_UDBL) mbedtls_t_udbl dividend, quotient; #else const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; const mbedtls_mpi_uint uint_halfword_mask = ((mbedtls_mpi_uint) 1 << biH) - 1; mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; mbedtls_mpi_uint u0_msw, u0_lsw; size_t s; #endif /* * Check for overflow */ if (0 == d || u1 >= d) { if (r != NULL) { *r = ~(mbedtls_mpi_uint) 0u; } return ~(mbedtls_mpi_uint) 0u; } #if defined(MBEDTLS_HAVE_UDBL) dividend = (mbedtls_t_udbl) u1 << biL; dividend |= (mbedtls_t_udbl) u0; quotient = dividend / d; if (quotient > ((mbedtls_t_udbl) 1 << biL) - 1) { quotient = ((mbedtls_t_udbl) 1 << biL) - 1; } if (r != NULL) { *r = (mbedtls_mpi_uint) (dividend - (quotient * d)); } return (mbedtls_mpi_uint) quotient; #else /* * Algorithm D, Section 4.3.1 - The Art of Computer Programming * Vol. 2 - Seminumerical Algorithms, Knuth */ /* * Normalize the divisor, d, and dividend, u0, u1 */ s = mbedtls_mpi_core_clz(d); d = d << s; u1 = u1 << s; u1 |= (u0 >> (biL - s)) & (-(mbedtls_mpi_sint) s >> (biL - 1)); u0 = u0 << s; d1 = d >> biH; d0 = d & uint_halfword_mask; u0_msw = u0 >> biH; u0_lsw = u0 & uint_halfword_mask; /* * Find the first quotient and remainder */ q1 = u1 / d1; r0 = u1 - d1 * q1; while (q1 >= radix || (q1 * d0 > radix * r0 + u0_msw)) { q1 -= 1; r0 += d1; if (r0 >= radix) { break; } } rAX = (u1 * radix) + (u0_msw - q1 * d); q0 = rAX / d1; r0 = rAX - q0 * d1; while (q0 >= radix || (q0 * d0 > radix * r0 + u0_lsw)) { q0 -= 1; r0 += d1; if (r0 >= radix) { break; } } if (r != NULL) { *r = (rAX * radix + u0_lsw - q0 * d) >> s; } quotient = q1 * radix + q0; return quotient; #endif } /* * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) */ int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, n, t, k; mbedtls_mpi X, Y, Z, T1, T2; mbedtls_mpi_uint TP2[3]; if (mbedtls_mpi_cmp_int(B, 0) == 0) { return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; } mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&Z); mbedtls_mpi_init_mempool(&T1); /* * Avoid dynamic memory allocations for constant-size T2. * * T2 is used for comparison only and the 3 limbs are assigned explicitly, * so nobody increase the size of the MPI and we're safe to use an on-stack * buffer. */ T2.s = 1; T2.n = sizeof(TP2) / sizeof(*TP2); T2.p = TP2; if (mbedtls_mpi_cmp_abs(A, B) < 0) { if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(Q, 0)); } if (R != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, A)); } return 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&X, A)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, B)); X.s = Y.s = 1; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&Z, A->n + 2)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Z, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T1, A->n + 2)); k = mbedtls_mpi_bitlen(&Y) % biL; if (k < biL - 1) { k = biL - 1 - k; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&X, k)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, k)); } else { k = 0; } n = X.n - 1; t = Y.n - 1; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&Y, biL * (n - t))); while (mbedtls_mpi_cmp_mpi(&X, &Y) >= 0) { Z.p[n - t]++; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &Y)); } MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, biL * (n - t))); for (i = n; i > t; i--) { if (X.p[i] >= Y.p[t]) { Z.p[i - t - 1] = ~(mbedtls_mpi_uint) 0u; } else { Z.p[i - t - 1] = mbedtls_int_div_int(X.p[i], X.p[i - 1], Y.p[t], NULL); } T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; T2.p[2] = X.p[i]; Z.p[i - t - 1]++; do { Z.p[i - t - 1]--; MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&T1, 0)); T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; T1.p[1] = Y.p[t]; MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &T1, Z.p[i - t - 1])); } while (mbedtls_mpi_cmp_mpi(&T1, &T2) > 0); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(&T1, &Y, Z.p[i - t - 1])); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&X, &X, &T1)); if (mbedtls_mpi_cmp_int(&X, 0) < 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&T1, &Y)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&T1, biL * (i - t - 1))); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&X, &X, &T1)); Z.p[i - t - 1]--; } } if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(Q, &Z)); Q->s = A->s * B->s; } if (R != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&X, k)); X.s = A->s; MBEDTLS_MPI_CHK(mbedtls_mpi_copy(R, &X)); if (mbedtls_mpi_cmp_int(R, 0) == 0) { R->s = 1; } } cleanup: mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&Z); mbedtls_mpi_free(&T1); mbedtls_platform_zeroize(TP2, sizeof(TP2)); return ret; } /* * Division by int: A = Q * b + R */ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b) { mbedtls_mpi B; mbedtls_mpi_uint p[1]; p[0] = mpi_sint_abs(b); B.s = TO_SIGN(b); B.n = 1; B.p = p; return mbedtls_mpi_div_mpi(Q, R, A, &B); } /* * Modulo: R = A mod B */ int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (mbedtls_mpi_cmp_int(B, 0) < 0) { return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; } MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(NULL, R, A, B)); while (mbedtls_mpi_cmp_int(R, 0) < 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(R, R, B)); } while (mbedtls_mpi_cmp_mpi(R, B) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(R, R, B)); } cleanup: return ret; } /* * Modulo: r = A mod b */ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b) { size_t i; mbedtls_mpi_uint x, y, z; if (b == 0) { return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO; } if (b < 0) { return MBEDTLS_ERR_MPI_NEGATIVE_VALUE; } /* * handle trivial cases */ if (b == 1 || A->n == 0) { *r = 0; return 0; } if (b == 2) { *r = A->p[0] & 1; return 0; } /* * general case */ for (i = A->n, y = 0; i > 0; i--) { x = A->p[i - 1]; y = (y << biH) | (x >> biH); z = y / b; y -= z * b; x <<= biH; y = (y << biH) | (x >> biH); z = y / b; y -= z * b; } /* * If A is negative, then the current y represents a negative value. * Flipping it to the positive side. */ if (A->s < 0 && y != 0) { y = b - y; } *r = y; return 0; } /** * \remark Replaced by our own because the original has been removed since * mbedtls v3.6.0. */ void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N) { *mm = mbedtls_mpi_core_montmul_init(N->p); } /** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) * * \param[in,out] A One of the numbers to multiply. * It must have at least as many limbs as N * (A->n >= N->n), and any limbs beyond n are ignored. * On successful completion, A contains the result of * the multiplication A * B * R^-1 mod N where * R = (2^ciL)^n. * \param[in] B One of the numbers to multiply. * It must be nonzero and must not have more limbs than N * (B->n <= N->n). * \param[in] N The modulus. \p N must be odd. * \param mm The value calculated by `mpi_montg_init(&mm, N)`. * This is -N^-1 mod 2^ciL. * \param[in,out] T A bignum for temporary storage. * It must be at least twice the limb size of N plus 1 * (T->n >= 2 * N->n + 1). * Its initial content is unused and * its final content is indeterminate. * It does not get reallocated. * \remark Replaced by our own because the original has been removed since * mbedtls v3.6.0. */ void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, mbedtls_mpi *T) { mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p); } /** * Montgomery reduction: A = A * R^-1 mod N * * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters. * * \remark Replaced by our own because the original has been removed since * mbedtls v3.6.0. */ void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, mbedtls_mpi *T) { mbedtls_mpi_uint z = 1; mbedtls_mpi U; U.n = U.s = (int) z; U.p = &z; mbedtls_mpi_montmul(A, &U, N, mm, T); } /** * Select an MPI from a table without leaking the index. * * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it * reads the entire table in order to avoid leaking the value of idx to an * attacker able to observe memory access patterns. * * \param[out] R Where to write the selected MPI. * \param[in] T The table to read from. * \param[in] T_size The number of elements in the table. * \param[in] idx The index of the element to select; * this must satisfy 0 <= idx < T_size. * * \return \c 0 on success, or a negative error code. */ static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; for (size_t i = 0; i < T_size; i++) { MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i], (unsigned char) mbedtls_ct_uint_eq(i, idx))); } cleanup: return ret; } /* * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) */ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *prec_RR) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t window_bitsize; size_t i, j, nblimbs; size_t bufsize, nbits; size_t exponent_bits_in_window = 0; mbedtls_mpi_uint ei, mm, state; mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos; int neg; if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(E, 0) < 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_bitlen(E) > MBEDTLS_MPI_MAX_BITS || mbedtls_mpi_bitlen(N) > MBEDTLS_MPI_MAX_BITS) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* * Init temps and window size */ mbedtls_mpi_montg_init(&mm, N); mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T); mbedtls_mpi_init(&Apos); mbedtls_mpi_init(&WW); memset(W, 0, sizeof(W)); i = mbedtls_mpi_bitlen(E); window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 : (i > 79) ? 4 : (i > 23) ? 3 : 1; #if (MBEDTLS_MPI_WINDOW_SIZE < 6) if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) { window_bitsize = MBEDTLS_MPI_WINDOW_SIZE; } #endif const size_t w_table_used_size = (size_t) 1 << window_bitsize; /* * This function is not constant-trace: its memory accesses depend on the * exponent value. To defend against timing attacks, callers (such as RSA * and DHM) should use exponent blinding. However this is not enough if the * adversary can find the exponent in a single trace, so this function * takes extra precautions against adversaries who can observe memory * access patterns. * * This function performs a series of multiplications by table elements and * squarings, and we want the prevent the adversary from finding out which * table element was used, and from distinguishing between multiplications * and squarings. Firstly, when multiplying by an element of the window * W[i], we do a constant-trace table lookup to obfuscate i. This leaves * squarings as having a different memory access patterns from other * multiplications. So secondly, we put the accumulator in the table as * well, and also do a constant-trace table lookup to multiply by the * accumulator which is W[x_index]. * * This way, all multiplications take the form of a lookup-and-multiply. * The number of lookup-and-multiply operations inside each iteration of * the main loop still depends on the bits of the exponent, but since the * other operations in the loop don't have an easily recognizable memory * trace, an adversary is unlikely to be able to observe the exact * patterns. * * An adversary may still be able to recover the exponent if they can * observe both memory accesses and branches. However, branch prediction * exploitation typically requires many traces of execution over the same * data, which is defeated by randomized blinding. */ const size_t x_index = 0; mbedtls_mpi_init(&W[x_index]); j = N->n + 1; /* All W[i] including the accumulator must have at least N->n limbs for * the mbedtls_mpi_montmul() and mbedtls_mpi_montred() calls later. * Here we ensure that * W[1] and the accumulator W[x_index] are large enough. later we'll grow * other W[i] to the same length. They must not be shrunk midway through * this function! */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2)); /* * Compensate for negative A (and correct at the end) */ neg = (A->s == -1); if (neg) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A)); Apos.s = 1; A = &Apos; } /* * If 1st call, pre-compute R^2 mod N */ if (prec_RR == NULL || prec_RR->p == NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N)); if (prec_RR != NULL) { memcpy(prec_RR, &RR, sizeof(mbedtls_mpi)); } } else { memcpy(&RR, prec_RR, sizeof(mbedtls_mpi)); } /* * W[1] = A * R^2 * R^-1 mod N = A * R mod N */ if (mbedtls_mpi_cmp_mpi(A, N) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N)); /* This should be a no-op because W[1] is already that large before * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow * in mbedtls_mpi_montmul() below, so let's make sure. */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1)); } else { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A)); } /* Note that this is safe because W[1] always has at least N->n limbs * (it grew above and was preserved by mbedtls_mpi_copy()). */ mbedtls_mpi_montmul(&W[1], &RR, N, mm, &T); /* * W[x_index] = R^2 * R^-1 mod N = R mod N */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR)); mbedtls_mpi_montred(&W[x_index], N, mm, &T); if (window_bitsize > 1) { /* * W[i] = W[1] ^ i * * The first bit of the sliding window is always 1 and therefore we * only need to store the second half of the table. * * (There are two special elements in the table: W[0] for the * accumulator/result and W[1] for A in Montgomery form. Both of these * are already set at this point.) */ j = w_table_used_size / 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1])); for (i = 0; i < window_bitsize - 1; i++) { mbedtls_mpi_montmul(&W[j], &W[j], N, mm, &T); } /* * W[i] = W[i - 1] * W[1] */ for (i = j + 1; i < w_table_used_size; i++) { MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1])); mbedtls_mpi_montmul(&W[i], &W[1], N, mm, &T); } } nblimbs = E->n; bufsize = 0; nbits = 0; state = 0; while (1) { if (bufsize == 0) { if (nblimbs == 0) { break; } nblimbs--; bufsize = sizeof(mbedtls_mpi_uint) << 3; } bufsize--; ei = (E->p[nblimbs] >> bufsize) & 1; /* * skip leading 0s */ if (ei == 0 && state == 0) { continue; } if (ei == 0 && state == 1) { /* * out of window, square W[x_index] */ MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T); continue; } /* * add ei to current window */ state = 2; nbits++; exponent_bits_in_window |= (ei << (window_bitsize - nbits)); if (nbits == window_bitsize) { /* * W[x_index] = W[x_index]^window_bitsize R^-1 mod N */ for (i = 0; i < window_bitsize; i++) { MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T); } /* * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N */ MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, exponent_bits_in_window)); mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T); state--; nbits = 0; exponent_bits_in_window = 0; } } /* * process the remaining bits */ for (i = 0; i < nbits; i++) { MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index)); mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T); exponent_bits_in_window <<= 1; if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) { MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1)); mbedtls_mpi_montmul(&W[x_index], &WW, N, mm, &T); } } /* * W[x_index] = A^E * R * R^-1 mod N = A^E mod N */ mbedtls_mpi_montred(&W[x_index], N, mm, &T); if (neg && E->n != 0 && (E->p[0] & 1) != 0) { W[x_index].s = -1; MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index])); } /* * Load the result in the output variable. */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index])); cleanup: /* The first bit of the sliding window is always 1 and therefore the first * half of the table was unused. */ for (i = w_table_used_size/2; i < w_table_used_size; i++) { mbedtls_mpi_free(&W[i]); } mbedtls_mpi_free(&W[x_index]); mbedtls_mpi_free(&W[1]); mbedtls_mpi_free(&T); mbedtls_mpi_free(&Apos); mbedtls_mpi_free(&WW); if (prec_RR == NULL || prec_RR->p == NULL) { mbedtls_mpi_free(&RR); } return ret; } /* * Greatest common divisor: G = gcd(A, B) (HAC 14.54) */ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t lz, lzt; mbedtls_mpi TA, TB; mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, B)); lz = mbedtls_mpi_lsb(&TA); lzt = mbedtls_mpi_lsb(&TB); /* The loop below gives the correct result when A==0 but not when B==0. * So have a special case for B==0. Leverage the fact that we just * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test * slightly more efficient than cmp_int(). */ if (lzt == 0 && mbedtls_mpi_get_bit(&TB, 0) == 0) { ret = mbedtls_mpi_copy(G, A); goto cleanup; } if (lzt < lz) { lz = lzt; } TA.s = TB.s = 1; /* We mostly follow the procedure described in HAC 14.54, but with some * minor differences: * - Sequences of multiplications or divisions by 2 are grouped into a * single shift operation. * - The procedure in HAC assumes that 0 < TB <= TA. * - The condition TB <= TA is not actually necessary for correctness. * TA and TB have symmetric roles except for the loop termination * condition, and the shifts at the beginning of the loop body * remove any significance from the ordering of TA vs TB before * the shifts. * - If TA = 0, the loop goes through 0 iterations and the result is * correctly TB. * - The case TB = 0 was short-circuited above. * * For the correctness proof below, decompose the original values of * A and B as * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), * and gcd(A',B') is odd or 0. * * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). * The code maintains the following invariant: * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) */ /* Proof that the loop terminates: * At each iteration, either the right-shift by 1 is made on a nonzero * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases * by at least 1, or the right-shift by 1 is made on zero and then * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted * since in that case TB is calculated from TB-TA with the condition TB>TA). */ while (mbedtls_mpi_cmp_int(&TA, 0) != 0) { /* Divisions by 2 preserve the invariant (I). */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, mbedtls_mpi_lsb(&TA))); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, mbedtls_mpi_lsb(&TB))); /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, * TA-TB is even so the division by 2 has an integer result. * Invariant (I) is preserved since any odd divisor of both TA and TB * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also * divides TA. */ if (mbedtls_mpi_cmp_mpi(&TA, &TB) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TA, &TA, &TB)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TA, 1)); } else { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(&TB, &TB, &TA)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TB, 1)); } /* Note that one of TA or TB is still odd. */ } /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. * At the loop exit, TA = 0, so gcd(TA,TB) = TB. * - If there was at least one loop iteration, then one of TA or TB is odd, * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, * lz = min(a,b) so gcd(A,B) = 2^lz * TB. * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&TB, lz)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(G, &TB)); cleanup: mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TB); return ret; } /* * Fill X with size bytes of random. * The bytes returned from the RNG are used in a specific order which * is suitable for deterministic ECDSA (see the specification of * mbedtls_mpi_random() and the implementation in mbedtls_mpi_fill_random()). */ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(size); /* Ensure that target MPI has exactly the necessary number of limbs */ MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs)); if (size == 0) { return 0; } ret = mbedtls_mpi_core_fill_random(X->p, X->n, size, f_rng, p_rng); cleanup: return ret; } int mbedtls_mpi_random(mbedtls_mpi *X, mbedtls_mpi_sint min, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (min < 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(N, min) <= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* Ensure that target MPI has exactly the same number of limbs * as the upper bound, even if the upper bound has leading zeros. * This is necessary for mbedtls_mpi_core_random. */ int ret = mbedtls_mpi_resize_clear(X, N->n); if (ret != 0) { return ret; } return mbedtls_mpi_core_random(X->p, min, N->p, X->n, f_rng, p_rng); } /* * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) */ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; if (mbedtls_mpi_cmp_int(N, 1) <= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TU); mbedtls_mpi_init_mempool(&U1); mbedtls_mpi_init_mempool(&U2); mbedtls_mpi_init_mempool(&G); mbedtls_mpi_init_mempool(&TB); mbedtls_mpi_init_mempool(&TV); mbedtls_mpi_init_mempool(&V1); mbedtls_mpi_init_mempool(&V2); MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, A, N)); if (mbedtls_mpi_cmp_int(&G, 1) != 0) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&TA, A, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TU, &TA)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TB, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TV, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U1, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&U2, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V1, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&V2, 1)); do { while ((TU.p[0] & 1) == 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TU, 1)); if ((U1.p[0] & 1) != 0 || (U2.p[0] & 1) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&U1, &U1, &TB)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &TA)); } MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U1, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&U2, 1)); } while ((TV.p[0] & 1) == 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&TV, 1)); if ((V1.p[0] & 1) != 0 || (V2.p[0] & 1) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, &TB)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &TA)); } MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V1, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&V2, 1)); } if (mbedtls_mpi_cmp_mpi(&TU, &TV) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TU, &TU, &TV)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U1, &U1, &V1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&U2, &U2, &V2)); } else { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&TV, &TV, &TU)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, &U1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V2, &V2, &U2)); } } while (mbedtls_mpi_cmp_int(&TU, 0) != 0); while (mbedtls_mpi_cmp_int(&V1, 0) < 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&V1, &V1, N)); } while (mbedtls_mpi_cmp_mpi(&V1, N) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&V1, &V1, N)); } MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &V1)); cleanup: mbedtls_mpi_free(&TA); mbedtls_mpi_free(&TU); mbedtls_mpi_free(&U1); mbedtls_mpi_free(&U2); mbedtls_mpi_free(&G); mbedtls_mpi_free(&TB); mbedtls_mpi_free(&TV); mbedtls_mpi_free(&V1); mbedtls_mpi_free(&V2); return ret; } #if defined(MBEDTLS_GENPRIME) /* Gaps between primes, starting at 3. https://oeis.org/A001223 */ static const unsigned char small_prime_gaps[] = { 2, 2, 4, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 14, 4, 6, 2, 10, 2, 6, 6, 4, 6, 6, 2, 10, 2, 4, 2, 12, 12, 4, 2, 4, 6, 2, 10, 6, 6, 6, 2, 6, 4, 2, 10, 14, 4, 2, 4, 14, 6, 10, 2, 4, 6, 8, 6, 6, 4, 6, 8, 4, 8, 10, 2, 10, 2, 6, 4, 6, 8, 4, 2, 4, 12, 8, 4, 8, 4, 6, 12, 2, 18, 6, 10, 6, 6, 2, 6, 10, 6, 6, 2, 6, 6, 4, 2, 12, 10, 2, 4, 6, 6, 2, 12, 4, 6, 8, 10, 8, 10, 8, 6, 6, 4, 8, 6, 4, 8, 4, 14, 10, 12, 2, 10, 2, 4, 2, 10, 14, 4, 2, 4, 14, 4, 2, 4, 20, 4, 8, 10, 8, 4, 6, 6, 14, 4, 6, 6, 8, 6, /*reaches 997*/ 0 /* the last entry is effectively unused */ }; /* * Small divisors test (X must be positive) * * Return values: * 0: no small factor (possible prime, more tests needed) * 1: certain prime * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime * other negative: error */ static int mpi_check_small_factors(const mbedtls_mpi *X) { int ret = 0; size_t i; mbedtls_mpi_uint r; unsigned p = 3; /* The first odd prime */ if ((X->p[0] & 1) == 0) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) { MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p)); if (r == 0) { if (mbedtls_mpi_cmp_int(X, p) == 0) { return 1; } else { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } } } cleanup: return ret; } /* * Miller-Rabin pseudo-primality test (HAC 4.24) */ static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, count; size_t i, j, k, s; mbedtls_mpi W, R, T, A, RR; mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R); mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&RR); /* * W = |X| - 1 * R = W >> lsb( W ) */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&W, X, 1)); s = mbedtls_mpi_lsb(&W); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&R, &W)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&R, s)); for (i = 0; i < rounds; i++) { /* * pick a random A, 1 < A < |X| - 1 */ count = 0; do { MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&A, X->n * ciL, f_rng, p_rng)); j = mbedtls_mpi_bitlen(&A); k = mbedtls_mpi_bitlen(&W); if (j > k) { A.p[A.n - 1] &= ((mbedtls_mpi_uint) 1 << (k - (A.n - 1) * biL - 1)) - 1; } if (count++ > 300) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup; } } while (mbedtls_mpi_cmp_mpi(&A, &W) >= 0 || mbedtls_mpi_cmp_int(&A, 1) <= 0); /* * A = A^R mod |X| */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&A, &A, &R, X, &RR)); if (mbedtls_mpi_cmp_mpi(&A, &W) == 0 || mbedtls_mpi_cmp_int(&A, 1) == 0) { continue; } j = 1; while (j < s && mbedtls_mpi_cmp_mpi(&A, &W) != 0) { /* * A = A * A mod |X| */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &A, &A)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&A, &T, X)); if (mbedtls_mpi_cmp_int(&A, 1) == 0) { break; } j++; } /* * not prime if A != |X| - 1 or A == 1 */ if (mbedtls_mpi_cmp_mpi(&A, &W) != 0 || mbedtls_mpi_cmp_int(&A, 1) == 0) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; break; } } cleanup: mbedtls_mpi_free(&W); mbedtls_mpi_free(&R); mbedtls_mpi_free(&T); mbedtls_mpi_free(&A); mbedtls_mpi_free(&RR); return ret; } /* * Pseudo-primality test: small factors, then Miller-Rabin */ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi XX; XX.s = 1; XX.n = X->n; XX.p = X->p; if (mbedtls_mpi_cmp_int(&XX, 0) == 0 || mbedtls_mpi_cmp_int(&XX, 1) == 0) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } if (mbedtls_mpi_cmp_int(&XX, 2) == 0) { return 0; } if ((ret = mpi_check_small_factors(&XX)) != 0) { if (ret == 1) { return 0; } return ret; } return mpi_miller_rabin(&XX, rounds, f_rng, p_rng); } /* * Prime number generation * * To generate an RSA key in a way recommended by FIPS 186-4, both primes must * be either 1024 bits or 1536 bits long, and flags must contain * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. */ int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #ifdef MBEDTLS_HAVE_INT64 // ceil(2^63.5) #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL #else // ceil(2^31.5) #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U #endif int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; size_t k, n; int rounds; mbedtls_mpi_uint r; mbedtls_mpi Y; if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init_mempool(&Y); n = BITS_TO_LIMBS(nbits); if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR) == 0) { /* * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 */ rounds = ((nbits >= 1300) ? 2 : (nbits >= 850) ? 3 : (nbits >= 650) ? 4 : (nbits >= 350) ? 8 : (nbits >= 250) ? 12 : (nbits >= 150) ? 18 : 27); } else { /* * 2^-100 error probability, number of rounds computed based on HAC, * fact 4.48 */ rounds = ((nbits >= 1450) ? 4 : (nbits >= 1150) ? 5 : (nbits >= 1000) ? 6 : (nbits >= 850) ? 7 : (nbits >= 750) ? 8 : (nbits >= 500) ? 13 : (nbits >= 250) ? 28 : (nbits >= 150) ? 40 : 51); } while (1) { MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(X, n * ciL, f_rng, p_rng)); /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ if (X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2) { continue; } k = n * biL; if (k > nbits) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(X, k - nbits)); } X->p[0] |= 1; if ((flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH) == 0) { ret = mbedtls_mpi_is_prime_ext(X, rounds, f_rng, p_rng); if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { goto cleanup; } } else { /* * A necessary condition for Y and X = 2Y + 1 to be prime * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). * Make sure it is satisfied, while keeping X = 3 mod 4 */ X->p[0] |= 2; MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, 3)); if (r == 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 8)); } else if (r == 1) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 4)); } /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Y, X)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Y, 1)); while (1) { /* * First, check small factors for X and Y * before doing Miller-Rabin on any of them */ if ((ret = mpi_check_small_factors(X)) == 0 && (ret = mpi_check_small_factors(&Y)) == 0 && (ret = mpi_miller_rabin(X, rounds, f_rng, p_rng)) == 0 && (ret = mpi_miller_rabin(&Y, rounds, f_rng, p_rng)) == 0) { goto cleanup; } if (ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { goto cleanup; } /* * Next candidates. We want to preserve Y = (X-1) / 2 and * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) * so up Y by 6 and X by 12. */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(X, X, 12)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&Y, &Y, 6)); } } } cleanup: mbedtls_mpi_free(&Y); return ret; } #endif /* MBEDTLS_GENPRIME */ #if defined(MBEDTLS_SELF_TEST) #define GCD_PAIR_COUNT 3 static const int gcd_pairs[GCD_PAIR_COUNT][3] = { { 693, 609, 21 }, { 1764, 868, 28 }, { 768454923, 542167814, 1 } }; /* * Checkup routine */ int mbedtls_mpi_self_test(int verbose) { int ret, i; mbedtls_mpi A, E, N, X, Y, U, V; mbedtls_mpi_init_mempool(&A); mbedtls_mpi_init_mempool(&E); mbedtls_mpi_init_mempool(&N); mbedtls_mpi_init_mempool(&X); mbedtls_mpi_init_mempool(&Y); mbedtls_mpi_init_mempool(&U); mbedtls_mpi_init_mempool(&V); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&A, 16, "EFE021C2645FD1DC586E69184AF4A31E" \ "D5F53E93B5F123FA41680867BA110131" \ "944FE7952E2517337780CB0DB80E61AA" \ "E7C8DDC6C5C6AADEB34EB38A2F40D5E6")); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&E, 16, "B2E7EFD37075B9F03FF989C7C5051C20" \ "34D2A323810251127E7BF8625A4F49A5" \ "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ "5B5C25763222FEFCCFC38B832366C29E")); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&N, 16, "0066A198186C18C10B2F5ED9B522752A" \ "9830B69916E535C8F047518A889A43A5" \ "94B6BED27A168D31D4A52F88925AA8F5")); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&X, &A, &N)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "602AB7ECA597A3D6B56FF9829A5E8B85" \ "9E857EA95A03512E2BAE7391688D264A" \ "A5663B0341DB9CCFD2C4C5F421FEC814" \ "8001B72E848A38CAE1C65F78E56ABDEF" \ "E12D3C039B8A02D6BE593F0BBBDA56F1" \ "ECF677152EF804370C1A305CAF3B5BF1" \ "30879B56C61DE584A0F53A2447A51E")); if (verbose != 0) { mbedtls_printf(" MPI test #1 (mul_mpi): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&X, &Y, &A, &N)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "256567336059E52CAE22925474705F39A94")); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&V, 16, "6613F26162223DF488E9CD48CC132C7A" \ "0AC93C701B001B092E4E5B9F73BCD27B" \ "9EE50D0657C77F374E903CDFA4C642")); if (verbose != 0) { mbedtls_printf(" MPI test #2 (div_mpi): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0 || mbedtls_mpi_cmp_mpi(&Y, &V) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&X, &A, &E, &N, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "36E139AEA55215609D2816998ED020BB" \ "BD96C37890F65171D948E9BC7CBAA4D9" \ "325D24D6A3C12710F10A09FA08AB87")); if (verbose != 0) { mbedtls_printf(" MPI test #3 (exp_mod): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&X, &A, &N)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&U, 16, "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ "C3DBA76456363A10869622EAC2DD84EC" \ "C5B8A74DAC4D09E03B5E0BE779F2DF61")); if (verbose != 0) { mbedtls_printf(" MPI test #4 (inv_mod): "); } if (mbedtls_mpi_cmp_mpi(&X, &U) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" MPI test #5 (simple gcd): "); } for (i = 0; i < GCD_PAIR_COUNT; i++) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&X, gcd_pairs[i][0])); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&Y, gcd_pairs[i][1])); MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&A, &X, &Y)); if (mbedtls_mpi_cmp_int(&A, gcd_pairs[i][2]) != 0) { if (verbose != 0) { mbedtls_printf("failed at %d\n", i); } ret = 1; goto cleanup; } } if (verbose != 0) { mbedtls_printf("passed\n"); } cleanup: if (ret != 0 && verbose != 0) { mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret); } mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N); mbedtls_mpi_free(&X); mbedtls_mpi_free(&Y); mbedtls_mpi_free(&U); mbedtls_mpi_free(&V); if (verbose != 0) { mbedtls_printf("\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_BIGNUM_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_core.c000066400000000000000000000667321464416617300240070ustar00rootroot00000000000000/* * Core bignum functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "constant_time_internal.h" #include "mbedtls/platform.h" #include "bignum_core.h" #include "bn_mul.h" #include "constant_time_internal.h" size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a) { #if defined(__has_builtin) #if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_clz) #define core_clz __builtin_clz #elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_clzl) #define core_clz __builtin_clzl #elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_clzll) #define core_clz __builtin_clzll #endif #endif #if defined(core_clz) return (size_t) core_clz(a); #else size_t j; mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); for (j = 0; j < biL; j++) { if (a & mask) { break; } mask >>= 1; } return j; #endif } size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs) { int i; size_t j; for (i = ((int) A_limbs) - 1; i >= 0; i--) { if (A[i] != 0) { j = biL - mbedtls_mpi_core_clz(A[i]); return (i * biL) + j; } } return 0; } static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a) { if (MBEDTLS_IS_BIG_ENDIAN) { /* Nothing to do on bigendian systems. */ return a; } else { #if defined(MBEDTLS_HAVE_INT32) return (mbedtls_mpi_uint) MBEDTLS_BSWAP32(a); #elif defined(MBEDTLS_HAVE_INT64) return (mbedtls_mpi_uint) MBEDTLS_BSWAP64(a); #endif } } void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, size_t A_limbs) { mbedtls_mpi_uint *cur_limb_left; mbedtls_mpi_uint *cur_limb_right; if (A_limbs == 0) { return; } /* * Traverse limbs and * - adapt byte-order in each limb * - swap the limbs themselves. * For that, simultaneously traverse the limbs from left to right * and from right to left, as long as the left index is not bigger * than the right index (it's not a problem if limbs is odd and the * indices coincide in the last iteration). */ for (cur_limb_left = A, cur_limb_right = A + (A_limbs - 1); cur_limb_left <= cur_limb_right; cur_limb_left++, cur_limb_right--) { mbedtls_mpi_uint tmp; /* Note that if cur_limb_left == cur_limb_right, * this code effectively swaps the bytes only once. */ tmp = mpi_bigendian_to_host(*cur_limb_left); *cur_limb_left = mpi_bigendian_to_host(*cur_limb_right); *cur_limb_right = tmp; } } /* Whether min <= A, in constant time. * A_limbs must be at least 1. */ mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, const mbedtls_mpi_uint *A, size_t A_limbs) { /* min <= least significant limb? */ mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min); /* limbs other than the least significant one are all zero? */ mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE; for (size_t i = 1; i < A_limbs; i++) { msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(A[i])); } /* min <= A iff the lowest limb of A is >= min or the other limbs * are not all zero. */ return mbedtls_ct_bool_or(msll_mask, min_le_lsl); } mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs) { mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE; for (size_t i = limbs; i > 0; i--) { /* * If B[i - 1] < A[i - 1] then A < B is false and the result must * remain 0. * * Again even if we can make a decision, we just mark the result and * the fact that we are done and continue looping. */ cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]); done = mbedtls_ct_bool_or(done, cond); /* * If A[i - 1] < B[i - 1] then A < B is true. * * Again even if we can make a decision, we just mark the result and * the fact that we are done and continue looping. */ cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]); ret = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done))); done = mbedtls_ct_bool_or(done, cond); } /* * If all the limbs were equal, then the numbers are equal, A < B is false * and leaving the result 0 is correct. */ return ret; } void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, mbedtls_ct_condition_t assign) { if (X == A) { return; } /* This function is very performance-sensitive for RSA. For this reason * we have the loop below, instead of calling mbedtls_ct_memcpy_if * (this is more optimal since here we don't have to handle the case where * we copy awkwardly sized data). */ for (size_t i = 0; i < limbs; i++) { X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]); } } void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, size_t limbs, mbedtls_ct_condition_t swap) { if (X == Y) { return; } for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint tmp = X[i]; X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]); Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]); } } int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length) { const size_t limbs = CHARS_TO_LIMBS(input_length); if (X_limbs < limbs) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } if (X != NULL) { memset(X, 0, X_limbs * ciL); for (size_t i = 0; i < input_length; i++) { size_t offset = ((i % ciL) << 3); X[i / ciL] |= ((mbedtls_mpi_uint) input[i]) << offset; } } return 0; } int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length) { const size_t limbs = CHARS_TO_LIMBS(input_length); if (X_limbs < limbs) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } /* If X_limbs is 0, input_length must also be 0 (from previous test). * Nothing to do. */ if (X_limbs == 0) { return 0; } memset(X, 0, X_limbs * ciL); /* memcpy() with (NULL, 0) is undefined behaviour */ if (input_length != 0) { size_t overhead = (X_limbs * ciL) - input_length; unsigned char *Xp = (unsigned char *) X; memcpy(Xp + overhead, input, input_length); } mbedtls_mpi_core_bigendian_to_host(X, X_limbs); return 0; } int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, size_t A_limbs, unsigned char *output, size_t output_length) { size_t stored_bytes = A_limbs * ciL; size_t bytes_to_copy; if (stored_bytes < output_length) { bytes_to_copy = stored_bytes; } else { bytes_to_copy = output_length; /* The output buffer is smaller than the allocated size of A. * However A may fit if its leading bytes are zero. */ for (size_t i = bytes_to_copy; i < stored_bytes; i++) { if (GET_BYTE(A, i) != 0) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } } } for (size_t i = 0; i < bytes_to_copy; i++) { output[i] = GET_BYTE(A, i); } if (stored_bytes < output_length) { /* Write trailing 0 bytes */ memset(output + stored_bytes, 0, output_length - stored_bytes); } return 0; } int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *X, size_t X_limbs, unsigned char *output, size_t output_length) { size_t stored_bytes; size_t bytes_to_copy; unsigned char *p; stored_bytes = X_limbs * ciL; if (stored_bytes < output_length) { /* There is enough space in the output buffer. Write initial * null bytes and record the position at which to start * writing the significant bytes. In this case, the execution * trace of this function does not depend on the value of the * number. */ bytes_to_copy = stored_bytes; p = output + output_length - stored_bytes; memset(output, 0, output_length - stored_bytes); } else { /* The output buffer is smaller than the allocated size of X. * However X may fit if its leading bytes are zero. */ bytes_to_copy = output_length; p = output; for (size_t i = bytes_to_copy; i < stored_bytes; i++) { if (GET_BYTE(X, i) != 0) { return MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL; } } } for (size_t i = 0; i < bytes_to_copy; i++) { p[bytes_to_copy - i - 1] = GET_BYTE(X, i); } return 0; } void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, size_t count) { size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; v0 = count / biL; v1 = count & (biL - 1); if (v0 > limbs || (v0 == limbs && v1 > 0)) { memset(X, 0, limbs * ciL); return; } /* * shift by count / limb_size */ if (v0 > 0) { for (i = 0; i < limbs - v0; i++) { X[i] = X[i + v0]; } for (; i < limbs; i++) { X[i] = 0; } } /* * shift by count % limb_size */ if (v1 > 0) { for (i = limbs; i > 0; i--) { r1 = X[i - 1] << (biL - v1); X[i - 1] >>= v1; X[i - 1] |= r0; r0 = r1; } } } void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, size_t count) { size_t i, v0, v1; mbedtls_mpi_uint r0 = 0, r1; v0 = count / (biL); v1 = count & (biL - 1); /* * shift by count / limb_size */ if (v0 > 0) { for (i = limbs; i > v0; i--) { X[i - 1] = X[i - v0 - 1]; } for (; i > 0; i--) { X[i - 1] = 0; } } /* * shift by count % limb_size */ if (v1 > 0) { for (i = v0; i < limbs; i++) { r1 = X[i] >> (biL - v1); X[i] <<= v1; X[i] |= r0; r0 = r1; } } } mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs) { mbedtls_mpi_uint c = 0; for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint t = c + A[i]; c = (t < A[i]); t += B[i]; c += (t < B[i]); X[i] = t; } return c; } mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, unsigned cond) { mbedtls_mpi_uint c = 0; mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond); for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]); mbedtls_mpi_uint t = c + X[i]; c = (t < X[i]); t += add; c += (t < add); X[i] = t; } return c; } mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs) { mbedtls_mpi_uint c = 0; for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint z = (A[i] < c); mbedtls_mpi_uint t = A[i] - c; c = (t < B[i]) + z; X[i] = t - B[i]; } return c; } mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len, const mbedtls_mpi_uint *s, size_t s_len, mbedtls_mpi_uint b) { mbedtls_mpi_uint c = 0; /* carry */ /* * It is a documented precondition of this function that d_len >= s_len. * If that's not the case, we swap these round: this turns what would be * a buffer overflow into an incorrect result. */ if (d_len < s_len) { s_len = d_len; } size_t excess_len = d_len - s_len; size_t steps_x8 = s_len / 8; size_t steps_x1 = s_len & 7; while (steps_x8--) { MULADDC_X8_INIT MULADDC_X8_CORE MULADDC_X8_STOP } while (steps_x1--) { MULADDC_X1_INIT MULADDC_X1_CORE MULADDC_X1_STOP } while (excess_len--) { *d += c; c = (*d < c); d++; } return c; } void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t A_limbs, const mbedtls_mpi_uint *B, size_t B_limbs) { memset(X, 0, (A_limbs + B_limbs) * ciL); for (size_t i = 0; i < B_limbs; i++) { (void) mbedtls_mpi_core_mla(X + i, A_limbs + 1, A, A_limbs, B[i]); } } /* * Fast Montgomery initialization (thanks to Tom St Denis). */ mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N) { mbedtls_mpi_uint x = N[0]; x += ((N[0] + 2) & 4) << 1; for (unsigned int i = biL; i >= 8; i /= 2) { x *= (2 - (N[0] * x)); } return ~x + 1; } void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t B_limbs, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T) { memset(T, 0, (2 * AN_limbs + 1) * ciL); for (size_t i = 0; i < AN_limbs; i++) { /* T = (T + u0*B + u1*N) / 2^biL */ mbedtls_mpi_uint u0 = A[i]; mbedtls_mpi_uint u1 = (T[0] + u0 * B[0]) * mm; (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, B, B_limbs, u0); (void) mbedtls_mpi_core_mla(T, AN_limbs + 2, N, AN_limbs, u1); T++; } /* * The result we want is (T >= N) ? T - N : T. * * For better constant-time properties in this function, we always do the * subtraction, with the result in X. * * We also look to see if there was any carry in the final additions in the * loop above. */ mbedtls_mpi_uint carry = T[AN_limbs]; mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, T, N, AN_limbs); /* * Using R as the Montgomery radix (auxiliary modulus) i.e. 2^(biL*AN_limbs): * * T can be in one of 3 ranges: * * 1) T < N : (carry, borrow) = (0, 1): we want T * 2) N <= T < R : (carry, borrow) = (0, 0): we want X * 3) T >= R : (carry, borrow) = (1, 1): we want X * * and (carry, borrow) = (1, 0) can't happen. * * So the correct return value is already in X if (carry ^ borrow) = 0, * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1. */ mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow), (unsigned char *) X, (unsigned char *) T, NULL, AN_limbs * sizeof(mbedtls_mpi_uint)); } int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, const mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, N->n * 2 * biL)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(X, N->n)); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, const mbedtls_mpi_uint *table, size_t limbs, size_t count, size_t index) { for (size_t i = 0; i < count; i++, table += limbs) { mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index); mbedtls_mpi_core_cond_assign(dest, table, limbs, assign); } } /* Fill X with n_bytes random bytes. * X must already have room for those bytes. * The ordering of the bytes returned from the RNG is suitable for * deterministic ECDSA (see RFC 6979 §3.3 and the specification of * mbedtls_mpi_core_random()). */ int mbedtls_mpi_core_fill_random( mbedtls_mpi_uint *X, size_t X_limbs, size_t n_bytes, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t limbs = CHARS_TO_LIMBS(n_bytes); const size_t overhead = (limbs * ciL) - n_bytes; if (X_limbs < limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } memset(X, 0, overhead); memset((unsigned char *) X + limbs * ciL, 0, (X_limbs - limbs) * ciL); MBEDTLS_MPI_CHK(f_rng(p_rng, (unsigned char *) X + overhead, n_bytes)); mbedtls_mpi_core_bigendian_to_host(X, limbs); cleanup: return ret; } int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_uint *N, size_t limbs, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE; size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs); size_t n_bytes = (n_bits + 7) / 8; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * When min == 0, each try has at worst a probability 1/2 of failing * (the msb has a probability 1/2 of being 0, and then the result will * be < N), so after 30 tries failure probability is a most 2**(-30). * * When N is just below a power of 2, as is the case when generating * a random scalar on most elliptic curves, 1 try is enough with * overwhelming probability. When N is just above a power of 2, * as when generating a random scalar on secp224k1, each try has * a probability of failing that is almost 1/2. * * The probabilities are almost the same if min is nonzero but negligible * compared to N. This is always the case when N is crypto-sized, but * it's convenient to support small N for testing purposes. When N * is small, use a higher repeat count, otherwise the probability of * failure is macroscopic. */ int count = (n_bytes > 4 ? 30 : 250); /* * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) * when f_rng is a suitably parametrized instance of HMAC_DRBG: * - use the same byte ordering; * - keep the leftmost n_bits bits of the generated octet string; * - try until result is in the desired range. * This also avoids any bias, which is especially important for ECDSA. */ do { MBEDTLS_MPI_CHK(mbedtls_mpi_core_fill_random(X, limbs, n_bytes, f_rng, p_rng)); mbedtls_mpi_core_shift_r(X, limbs, 8 * n_bytes - n_bits); if (--count == 0) { ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; goto cleanup; } ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs); lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs); } while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE); cleanup: return ret; } static size_t exp_mod_get_window_size(size_t Ebits) { #if MBEDTLS_MPI_WINDOW_SIZE >= 6 return (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1; #elif MBEDTLS_MPI_WINDOW_SIZE == 5 return (Ebits > 239) ? 5 : (Ebits > 79) ? 4 : 1; #elif MBEDTLS_MPI_WINDOW_SIZE > 1 return (Ebits > 79) ? MBEDTLS_MPI_WINDOW_SIZE : 1; #else (void) Ebits; return 1; #endif } size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs) { const size_t wsize = exp_mod_get_window_size(E_limbs * biL); const size_t welem = ((size_t) 1) << wsize; /* How big does each part of the working memory pool need to be? */ const size_t table_limbs = welem * AN_limbs; const size_t select_limbs = AN_limbs; const size_t temp_limbs = 2 * AN_limbs + 1; return table_limbs + select_limbs + temp_limbs; } static void exp_mod_precompute_window(const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, const mbedtls_mpi_uint *RR, size_t welem, mbedtls_mpi_uint *Wtable, mbedtls_mpi_uint *temp) { /* W[0] = 1 (in Montgomery presentation) */ memset(Wtable, 0, AN_limbs * ciL); Wtable[0] = 1; mbedtls_mpi_core_montmul(Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp); /* W[1] = A (already in Montgomery presentation) */ mbedtls_mpi_uint *W1 = Wtable + AN_limbs; memcpy(W1, A, AN_limbs * ciL); /* W[i+1] = W[i] * W[1], i >= 2 */ mbedtls_mpi_uint *Wprev = W1; for (size_t i = 2; i < welem; i++) { mbedtls_mpi_uint *Wcur = Wprev + AN_limbs; mbedtls_mpi_core_montmul(Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp); Wprev = Wcur; } } /* Exponentiation: X := A^E mod N. * * A must already be in Montgomery form. * * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero. * * RR must contain 2^{2*biL} mod N. * * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82 * (The difference is that the body in our loop processes a single bit instead * of a full window.) */ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T) { const size_t wsize = exp_mod_get_window_size(E_limbs * biL); const size_t welem = ((size_t) 1) << wsize; /* This is how we will use the temporary storage T, which must have space * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */ const size_t table_limbs = welem * AN_limbs; const size_t select_limbs = AN_limbs; /* Pointers to specific parts of the temporary working memory pool */ mbedtls_mpi_uint *const Wtable = T; mbedtls_mpi_uint *const Wselect = Wtable + table_limbs; mbedtls_mpi_uint *const temp = Wselect + select_limbs; /* * Window precomputation */ const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N); /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */ exp_mod_precompute_window(A, N, AN_limbs, mm, RR, welem, Wtable, temp); /* * Fixed window exponentiation */ /* X = 1 (in Montgomery presentation) initially */ memcpy(X, Wtable, AN_limbs * ciL); /* We'll process the bits of E from most significant * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant * (limb_index=0, E_bit_index=0). */ size_t E_limb_index = E_limbs; size_t E_bit_index = 0; /* At any given time, window contains window_bits bits from E. * window_bits can go up to wsize. */ size_t window_bits = 0; mbedtls_mpi_uint window = 0; do { /* Square */ mbedtls_mpi_core_montmul(X, X, X, AN_limbs, N, AN_limbs, mm, temp); /* Move to the next bit of the exponent */ if (E_bit_index == 0) { --E_limb_index; E_bit_index = biL - 1; } else { --E_bit_index; } /* Insert next exponent bit into window */ ++window_bits; window <<= 1; window |= (E[E_limb_index] >> E_bit_index) & 1; /* Clear window if it's full. Also clear the window at the end, * when we've finished processing the exponent. */ if (window_bits == wsize || (E_bit_index == 0 && E_limb_index == 0)) { /* Select Wtable[window] without leaking window through * memory access patterns. */ mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable, AN_limbs, welem, window); /* Multiply X by the selected element. */ mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm, temp); window = 0; window_bits = 0; } } while (!(E_bit_index == 0 && E_limb_index == 0)); } mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, mbedtls_mpi_uint c, /* doubles as carry */ size_t limbs) { for (size_t i = 0; i < limbs; i++) { mbedtls_mpi_uint s = A[i]; mbedtls_mpi_uint t = s - c; c = (t > s); X[i] = t; } return c; } mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, size_t limbs) { volatile const mbedtls_mpi_uint *force_read_A = A; mbedtls_mpi_uint bits = 0; for (size_t i = 0; i < limbs; i++) { bits |= force_read_A[i]; } return mbedtls_ct_bool(bits); } void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, const mbedtls_mpi_uint *rr, mbedtls_mpi_uint *T) { mbedtls_mpi_core_montmul(X, A, rr, AN_limbs, N, AN_limbs, mm, T); } void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T) { const mbedtls_mpi_uint Rinv = 1; /* 1/R in Mont. rep => 1 */ mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T); } #endif /* MBEDTLS_BIGNUM_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_core.h000066400000000000000000001043071464416617300240030ustar00rootroot00000000000000/** * Core bignum functions * * This interface should only be used by the legacy bignum module (bignum.h) * and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other * modules should use the high-level modular bignum interface (bignum_mod.h) * or the legacy bignum interface (bignum.h). * * This module is about processing non-negative integers with a fixed upper * bound that's of the form 2^n-1 where n is a multiple of #biL. * These can be thought of integers written in base 2^#biL with a fixed * number of digits. Digits in this base are called *limbs*. * Many operations treat these numbers as the principal representation of * a number modulo 2^n or a smaller bound. * * The functions in this module obey the following conventions unless * explicitly indicated otherwise: * * - **Overflow**: some functions indicate overflow from the range * [0, 2^n-1] by returning carry parameters, while others operate * modulo and so cannot overflow. This should be clear from the function * documentation. * - **Bignum parameters**: Bignums are passed as pointers to an array of * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: * - Bignum parameters called \p A, \p B, ... are inputs, and are * not modified by the function. * - For operations modulo some number, the modulus is called \p N * and is input-only. * - Bignum parameters called \p X, \p Y are outputs or input-output. * The initial content of output-only parameters is ignored. * - Some functions use different names that reflect traditional * naming of operands of certain operations (e.g. * divisor/dividend/quotient/remainder). * - \p T is a temporary storage area. The initial content of such * parameter is ignored and the final content is unspecified. * - **Bignum sizes**: bignum sizes are always expressed in limbs. * Most functions work on bignums of a given size and take a single * \p limbs parameter that applies to all parameters that are limb arrays. * All bignum sizes must be at least 1 and must be significantly less than * #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the * total size of all parameters overflows #SIZE_MAX is undefined. * - **Parameter ordering**: for bignum parameters, outputs come before inputs. * Temporaries come last. * - **Aliasing**: in general, output bignums may be aliased to one or more * inputs. As an exception, parameters that are documented as a modulus value * may not be aliased to an output. Outputs may not be aliased to one another. * Temporaries may not be aliased to any other parameter. * - **Overlap**: apart from aliasing of limb array pointers (where two * arguments are equal pointers), overlap is not supported and may result * in undefined behavior. * - **Error handling**: This is a low-level module. Functions generally do not * try to protect against invalid arguments such as nonsensical sizes or * null pointers. Note that some functions that operate on bignums of * different sizes have constraints about their size, and violating those * constraints may lead to buffer overflows. * - **Modular representatives**: functions that operate modulo \p N expect * all modular inputs to be in the range [0, \p N - 1] and guarantee outputs * in the range [0, \p N - 1]. If an input is out of range, outputs are * fully unspecified, though bignum values out of range should not cause * buffer overflows (beware that this is not extensively tested). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_CORE_H #define MBEDTLS_BIGNUM_CORE_H #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #include "constant_time_internal.h" #define ciL (sizeof(mbedtls_mpi_uint)) /** chars in limb */ #define biL (ciL << 3) /** bits in limb */ #define biH (ciL << 2) /** half limb size */ /* * Convert between bits/chars and number of limbs * Divide first in order to avoid potential overflows */ #define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0)) #define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0)) /* Get a specific byte, without range checks. */ #define GET_BYTE(X, i) \ (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff) /** Count leading zero bits in a given integer. * * \warning The result is undefined if \p a == 0 * * \param a Integer to count leading zero bits. * * \return The number of leading zero bits in \p a, if \p a != 0. * If \p a == 0, the result is undefined. */ size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a); /** Return the minimum number of bits required to represent the value held * in the MPI. * * \note This function returns 0 if all the limbs of \p A are 0. * * \param[in] A The address of the MPI. * \param A_limbs The number of limbs of \p A. * * \return The number of bits in \p A. */ size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs); /** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint * into the storage form used by mbedtls_mpi. * * \param[in,out] A The address of the MPI. * \param A_limbs The number of limbs of \p A. */ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A, size_t A_limbs); /** \brief Compare a machine integer with an MPI. * * This function operates in constant time with respect * to the values of \p min and \p A. * * \param min A machine integer. * \param[in] A An MPI. * \param A_limbs The number of limbs of \p A. * This must be at least 1. * * \return MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE. */ mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min, const mbedtls_mpi_uint *A, size_t A_limbs); /** * \brief Check if one unsigned MPI is less than another in constant * time. * * \param A The left-hand MPI. This must point to an array of limbs * with the same allocated length as \p B. * \param B The right-hand MPI. This must point to an array of limbs * with the same allocated length as \p A. * \param limbs The number of limbs in \p A and \p B. * This must not be 0. * * \return MBEDTLS_CT_TRUE if \p A is less than \p B. * MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B. */ mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs); /** * \brief Perform a safe conditional copy of an MPI which doesn't reveal * whether assignment was done or not. * * \param[out] X The address of the destination MPI. * This must be initialized. Must have enough limbs to * store the full value of \p A. * \param[in] A The address of the source MPI. This must be initialized. * \param limbs The number of limbs of \p A. * \param assign The condition deciding whether to perform the * assignment or not. Callers will need to use * the constant time interface (e.g. `mbedtls_ct_bool()`) * to construct this argument. * * \note This function avoids leaking any information about whether * the assignment was done or not. */ void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, mbedtls_ct_condition_t assign); /** * \brief Perform a safe conditional swap of two MPIs which doesn't reveal * whether the swap was done or not. * * \param[in,out] X The address of the first MPI. * This must be initialized. * \param[in,out] Y The address of the second MPI. * This must be initialized. * \param limbs The number of limbs of \p X and \p Y. * \param swap The condition deciding whether to perform * the swap or not. * * \note This function avoids leaking any information about whether * the swap was done or not. */ void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, size_t limbs, mbedtls_ct_condition_t swap); /** Import X from unsigned binary data, little-endian. * * The MPI needs to have enough limbs to store the full value (including any * most significant zero bytes in the input). * * \param[out] X The address of the MPI. * \param X_limbs The number of limbs of \p X. * \param[in] input The input buffer to import from. * \param input_length The length bytes of \p input. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't * large enough to hold the value in \p input. */ int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length); /** Import X from unsigned binary data, big-endian. * * The MPI needs to have enough limbs to store the full value (including any * most significant zero bytes in the input). * * \param[out] X The address of the MPI. * May only be #NULL if \p X_limbs is 0 and \p input_length * is 0. * \param X_limbs The number of limbs of \p X. * \param[in] input The input buffer to import from. * May only be #NULL if \p input_length is 0. * \param input_length The length in bytes of \p input. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't * large enough to hold the value in \p input. */ int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X, size_t X_limbs, const unsigned char *input, size_t input_length); /** Export A into unsigned binary data, little-endian. * * \note If \p output is shorter than \p A the export is still successful if the * value held in \p A fits in the buffer (that is, if enough of the most * significant bytes of \p A are 0). * * \param[in] A The address of the MPI. * \param A_limbs The number of limbs of \p A. * \param[out] output The output buffer to export to. * \param output_length The length in bytes of \p output. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't * large enough to hold the value of \p A. */ int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A, size_t A_limbs, unsigned char *output, size_t output_length); /** Export A into unsigned binary data, big-endian. * * \note If \p output is shorter than \p A the export is still successful if the * value held in \p A fits in the buffer (that is, if enough of the most * significant bytes of \p A are 0). * * \param[in] A The address of the MPI. * \param A_limbs The number of limbs of \p A. * \param[out] output The output buffer to export to. * \param output_length The length in bytes of \p output. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't * large enough to hold the value of \p A. */ int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A, size_t A_limbs, unsigned char *output, size_t output_length); /** \brief Shift an MPI in-place right by a number of bits. * * Shifting by more bits than there are bit positions * in \p X is valid and results in setting \p X to 0. * * This function's execution time depends on the value * of \p count (and of course \p limbs). * * \param[in,out] X The number to shift. * \param limbs The number of limbs of \p X. This must be at least 1. * \param count The number of bits to shift by. */ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs, size_t count); /** * \brief Shift an MPI in-place left by a number of bits. * * Shifting by more bits than there are bit positions * in \p X will produce an unspecified result. * * This function's execution time depends on the value * of \p count (and of course \p limbs). * \param[in,out] X The number to shift. * \param limbs The number of limbs of \p X. This must be at least 1. * \param count The number of bits to shift by. */ void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs, size_t count); /** * \brief Add two fixed-size large unsigned integers, returning the carry. * * Calculates `A + B` where `A` and `B` have the same size. * * This function operates modulo `2^(biL*limbs)` and returns the carry * (1 if there was a wraparound, and 0 otherwise). * * \p X may be aliased to \p A or \p B. * * \param[out] X The result of the addition. * \param[in] A Little-endian presentation of the left operand. * \param[in] B Little-endian presentation of the right operand. * \param limbs Number of limbs of \p X, \p A and \p B. * * \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise. */ mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs); /** * \brief Conditional addition of two fixed-size large unsigned integers, * returning the carry. * * Functionally equivalent to * * ``` * if( cond ) * X += A; * return carry; * ``` * * This function operates modulo `2^(biL*limbs)`. * * \param[in,out] X The pointer to the (little-endian) array * representing the bignum to accumulate onto. * \param[in] A The pointer to the (little-endian) array * representing the bignum to conditionally add * to \p X. This may be aliased to \p X but may not * overlap otherwise. * \param limbs Number of limbs of \p X and \p A. * \param cond Condition bit dictating whether addition should * happen or not. This must be \c 0 or \c 1. * * \warning If \p cond is neither 0 nor 1, the result of this function * is unspecified, and the resulting value in \p X might be * neither its original value nor \p X + \p A. * * \return 1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise. */ mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t limbs, unsigned cond); /** * \brief Subtract two fixed-size large unsigned integers, returning the borrow. * * Calculate `A - B` where \p A and \p B have the same size. * This function operates modulo `2^(biL*limbs)` and returns the carry * (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise). * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \param[out] X The result of the subtraction. * \param[in] A Little-endian presentation of left operand. * \param[in] B Little-endian presentation of right operand. * \param limbs Number of limbs of \p X, \p A and \p B. * * \return 1 if `A < B`. * 0 if `A >= B`. */ mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t limbs); /** * \brief Perform a fixed-size multiply accumulate operation: X += b * A * * \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not * otherwise overlap. * * This function operates modulo `2^(biL*X_limbs)`. * * \param[in,out] X The pointer to the (little-endian) array * representing the bignum to accumulate onto. * \param X_limbs The number of limbs of \p X. This must be * at least \p A_limbs. * \param[in] A The pointer to the (little-endian) array * representing the bignum to multiply with. * This may be aliased to \p X but may not overlap * otherwise. * \param A_limbs The number of limbs of \p A. * \param b X scalar to multiply with. * * \return The carry at the end of the operation. */ mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs, const mbedtls_mpi_uint *A, size_t A_limbs, mbedtls_mpi_uint b); /** * \brief Perform a known-size multiplication * * \p X may not be aliased to any of the inputs for this function. * \p A may be aliased to \p B. * * \param[out] X The pointer to the (little-endian) array to receive * the product of \p A_limbs and \p B_limbs. * This must be of length \p A_limbs + \p B_limbs. * \param[in] A The pointer to the (little-endian) array * representing the first factor. * \param A_limbs The number of limbs in \p A. * \param[in] B The pointer to the (little-endian) array * representing the second factor. * \param B_limbs The number of limbs in \p B. */ void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, size_t A_limbs, const mbedtls_mpi_uint *B, size_t B_limbs); /** * \brief Calculate initialisation value for fast Montgomery modular * multiplication * * \param[in] N Little-endian presentation of the modulus. This must have * at least one limb. * * \return The initialisation value for fast Montgomery modular multiplication */ mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N); /** * \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36) * * \p A and \p B must be in canonical form. That is, < \p N. * * \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs == * \p B_limbs) but may not overlap any parameters otherwise. * * \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may * not alias \p N (since they must be in canonical form, they cannot == \p N). * * \param[out] X The destination MPI, as a little-endian array of * length \p AN_limbs. * On successful completion, X contains the result of * the multiplication `A * B * R^-1` mod N where * `R = 2^(biL*AN_limbs)`. * \param[in] A Little-endian presentation of first operand. * Must have the same number of limbs as \p N. * \param[in] B Little-endian presentation of second operand. * \param[in] B_limbs The number of limbs in \p B. * Must be <= \p AN_limbs. * \param[in] N Little-endian presentation of the modulus. * This must be odd, and have exactly the same number * of limbs as \p A. * It may alias \p X, but must not alias or otherwise * overlap any of the other parameters. * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be calculated by `mbedtls_mpi_core_montmul_init()`. * \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs. * Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, size_t B_limbs, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T); /** * \brief Calculate the square of the Montgomery constant. (Needed * for conversion and operations in Montgomery form.) * * \param[out] X A pointer to the result of the calculation of * the square of the Montgomery constant: * 2^{2*n*biL} mod N. * \param[in] N Little-endian presentation of the modulus, which must be odd. * * \return 0 if successful. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space * to store the value of Montgomery constant squared. * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero. * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative. */ int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X, const mbedtls_mpi *N); #if defined(MBEDTLS_TEST_HOOKS) /** * Copy an MPI from a table without leaking the index. * * \param dest The destination buffer. This must point to a writable * buffer of at least \p limbs limbs. * \param table The address of the table. This must point to a readable * array of \p count elements of \p limbs limbs each. * \param limbs The number of limbs in each table entry. * \param count The number of entries in \p table. * \param index The (secret) table index to look up. This must be in the * range `0 .. count-1`. */ void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest, const mbedtls_mpi_uint *table, size_t limbs, size_t count, size_t index); #endif /* MBEDTLS_TEST_HOOKS */ /** * \brief Fill an integer with a number of random bytes. * * \param X The destination MPI. * \param X_limbs The number of limbs of \p X. * \param bytes The number of random bytes to generate. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. This may be * \c NULL if \p f_rng doesn't need a context argument. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have * enough room for \p bytes bytes. * \return A negative error code on RNG failure. * * \note The bytes obtained from the RNG are interpreted * as a big-endian representation of an MPI; this can * be relevant in applications like deterministic ECDSA. */ int mbedtls_mpi_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs, size_t bytes, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination MPI, with \p limbs limbs. * It must not be aliased with \p N or otherwise overlap it. * \param min The minimum value to return. * \param N The upper bound of the range, exclusive, with \p limbs limbs. * In other words, this is one plus the maximum value to return. * \p N must be strictly larger than \p min. * \param limbs The number of limbs of \p N and \p X. * This must not be 0. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. */ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_uint *N, size_t limbs, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Returns the number of limbs of working memory required for * a call to `mbedtls_mpi_core_exp_mod()`. * * \note This will always be at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. * * \param AN_limbs The number of limbs in the input `A` and the modulus `N` * (they must be the same size) that will be given to * `mbedtls_mpi_core_exp_mod()`. * \param E_limbs The number of limbs in the exponent `E` that will be given * to `mbedtls_mpi_core_exp_mod()`. * * \return The number of limbs of working memory required by * `mbedtls_mpi_core_exp_mod()`. */ size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs); /** * \brief Perform a modular exponentiation with secret exponent: * X = A^E mod N, where \p A is already in Montgomery form. * * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs == * \p AN_limbs. * * \param[out] X The destination MPI, as a little endian array of length * \p AN_limbs. * \param[in] A The base MPI, as a little endian array of length \p AN_limbs. * Must be in Montgomery form. * \param[in] N The modulus, as a little endian array of length \p AN_limbs. * \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR. * \param[in] E The exponent, as a little endian array of length \p E_limbs. * \param E_limbs The number of limbs in \p E. * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little * endian array of length \p AN_limbs. * \param[in,out] T Temporary storage of at least the number of limbs returned * by `mbedtls_mpi_core_exp_mod_working_limbs()`. * Its initial content is unused and its final content is * indeterminate. * It must not alias or otherwise overlap any of the other * parameters. * It is up to the caller to zeroize \p T when it is no * longer needed, and before freeing it if it was dynamically * allocated. */ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *E, size_t E_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T); /** * \brief Subtract unsigned integer from known-size large unsigned integers. * Return the borrow. * * \param[out] X The result of the subtraction. * \param[in] A The left operand. * \param b The unsigned scalar to subtract. * \param limbs Number of limbs of \p X and \p A. * * \return 1 if `A < b`. * 0 if `A >= b`. */ mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, mbedtls_mpi_uint b, size_t limbs); /** * \brief Determine if a given MPI has the value \c 0 in constant time with * respect to the value (but not with respect to the number of limbs). * * \param[in] A The MPI to test. * \param limbs Number of limbs in \p A. * * \return MBEDTLS_CT_FALSE if `A == 0` * MBEDTLS_CT_TRUE if `A != 0`. */ mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A, size_t limbs); /** * \brief Returns the number of limbs of working memory required for * a call to `mbedtls_mpi_core_montmul()`. * * \param AN_limbs The number of limbs in the input `A` and the modulus `N` * (they must be the same size) that will be given to * `mbedtls_mpi_core_montmul()` or one of the other functions * that specifies this as the amount of working memory needed. * * \return The number of limbs of working memory required by * `mbedtls_mpi_core_montmul()` (or other similar function). */ static inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs) { return 2 * AN_limbs + 1; } /** Convert an MPI into Montgomery form. * * \p X may be aliased to \p A, but may not otherwise overlap it. * * \p X may not alias \p N (it is in canonical form, so must be strictly less * than \p N). Nor may it alias or overlap \p rr (this is unlikely to be * required in practice.) * * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is * an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we * don't want to allocate memory. * * \param[out] X The result of the conversion. * Must have the same number of limbs as \p A. * \param[in] A The MPI to convert into Montgomery form. * Must have the same number of limbs as the modulus. * \param[in] N The address of the modulus, which gives the size of * the base `R` = 2^(biL*N->limbs). * \param[in] AN_limbs The number of limbs in \p X, \p A, \p N and \p rr. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be determined by calling * `mbedtls_mpi_core_montmul_init()`. * \param[in] rr The residue for `2^{2*n*biL} mod N`. * \param[in,out] T Temporary storage of size at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` * limbs. * Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, const mbedtls_mpi_uint *rr, mbedtls_mpi_uint *T); /** Convert an MPI from Montgomery form. * * \p X may be aliased to \p A, but may not otherwise overlap it. * * \p X may not alias \p N (it is in canonical form, so must be strictly less * than \p N). * * This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is * an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we * don't want to allocate memory. * * \param[out] X The result of the conversion. * Must have the same number of limbs as \p A. * \param[in] A The MPI to convert from Montgomery form. * Must have the same number of limbs as the modulus. * \param[in] N The address of the modulus, which gives the size of * the base `R` = 2^(biL*N->limbs). * \param[in] AN_limbs The number of limbs in \p X, \p A and \p N. * \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL. * This can be determined by calling * `mbedtls_mpi_core_montmul_init()`. * \param[in,out] T Temporary storage of size at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)` * limbs. * Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, mbedtls_mpi_uint mm, mbedtls_mpi_uint *T); #endif /* MBEDTLS_BIGNUM_CORE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_mod.c000066400000000000000000000263421464416617300236270ustar00rootroot00000000000000/** * Modular bignum functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) #include #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/bignum.h" #include "mbedtls/platform.h" #include "bignum_core.h" #include "bignum_mod.h" #include "bignum_mod_raw.h" #include "constant_time_internal.h" int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *p, size_t p_limbs) { if (p_limbs != N->limbs || !mbedtls_mpi_core_lt_ct(p, N->p, N->limbs)) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } r->limbs = N->limbs; r->p = p; return 0; } void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r) { if (r == NULL) { return; } r->limbs = 0; r->p = NULL; } void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N) { if (N == NULL) { return; } N->p = NULL; N->limbs = 0; N->bits = 0; N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; } void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N) { if (N == NULL) { return; } switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: if (N->rep.mont.rr != NULL) { mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr, N->limbs * sizeof(mbedtls_mpi_uint)); N->rep.mont.rr = NULL; } N->rep.mont.mm = 0; break; case MBEDTLS_MPI_MOD_REP_OPT_RED: N->rep.ored.modp = NULL; break; case MBEDTLS_MPI_MOD_REP_INVALID: break; } N->p = NULL; N->limbs = 0; N->bits = 0; N->int_rep = MBEDTLS_MPI_MOD_REP_INVALID; } static int set_mont_const_square(const mbedtls_mpi_uint **X, const mbedtls_mpi_uint *A, size_t limbs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi N; mbedtls_mpi RR; *X = NULL; mbedtls_mpi_init(&N); mbedtls_mpi_init(&RR); if (A == NULL || limbs == 0 || limbs >= (MBEDTLS_MPI_MAX_LIMBS / 2) - 2) { goto cleanup; } if (mbedtls_mpi_grow(&N, limbs)) { goto cleanup; } memcpy(N.p, A, sizeof(mbedtls_mpi_uint) * limbs); ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N); if (ret == 0) { *X = RR.p; RR.p = NULL; } cleanup: mbedtls_mpi_free(&N); mbedtls_mpi_free(&RR); ret = (ret != 0) ? MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED : 0; return ret; } static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs, mbedtls_mpi_mod_rep_selector int_rep) { N->p = p; N->limbs = p_limbs; N->bits = mbedtls_mpi_core_bitlen(p, p_limbs); N->int_rep = int_rep; } int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs) { int ret = 0; standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY); N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p); ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs); if (ret != 0) { mbedtls_mpi_mod_modulus_free(N); } return ret; } int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs, mbedtls_mpi_modp_fn modp) { standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED); N->rep.ored.modp = modp; return 0; } int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N) { if (N->limbs == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_uint *T = mbedtls_calloc(N->limbs * 2 + 1, ciL); if (T == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi_mod_raw_mul(X->p, A->p, B->p, N, T); mbedtls_free(T); return 0; } int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N) { if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_mod_raw_sub(X->p, A->p, B->p, N); return 0; } static int mbedtls_mpi_mod_inv_mont(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *working_memory) { /* Input already in Montgomery form, so there's little to do */ mbedtls_mpi_mod_raw_inv_prime(X->p, A->p, N->p, N->limbs, N->rep.mont.rr, working_memory); return 0; } static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *working_memory) { /* Need to convert input into Montgomery form */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_mod_modulus Nmont; mbedtls_mpi_mod_modulus_init(&Nmont); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs)); /* We'll use X->p to hold the Montgomery form of the input A->p */ mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs, Nmont.rep.mont.mm, Nmont.rep.mont.rr, working_memory); mbedtls_mpi_mod_raw_inv_prime(X->p, X->p, Nmont.p, Nmont.limbs, Nmont.rep.mont.rr, working_memory); /* And convert back from Montgomery form */ mbedtls_mpi_core_from_mont_rep(X->p, X->p, Nmont.p, Nmont.limbs, Nmont.rep.mont.mm, working_memory); cleanup: mbedtls_mpi_mod_modulus_free(&Nmont); return ret; } int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N) { if (X->limbs != N->limbs || A->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* Zero has the same value regardless of Montgomery form or not */ if (mbedtls_mpi_core_check_zero_ct(A->p, A->limbs) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } size_t working_limbs = mbedtls_mpi_mod_raw_inv_prime_working_limbs(N->limbs); mbedtls_mpi_uint *working_memory = mbedtls_calloc(working_limbs, sizeof(mbedtls_mpi_uint)); if (working_memory == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: ret = mbedtls_mpi_mod_inv_mont(X, A, N, working_memory); break; case MBEDTLS_MPI_MOD_REP_OPT_RED: ret = mbedtls_mpi_mod_inv_non_mont(X, A, N, working_memory); break; default: ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; break; } mbedtls_zeroize_and_free(working_memory, working_limbs * sizeof(mbedtls_mpi_uint)); return ret; } int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N) { if (X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_mod_raw_add(X->p, A->p, B->p, N); return 0; } int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (X->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng); } int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, const unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep) { int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; /* Do our best to check if r and m have been set up */ if (r->limbs == 0 || N->limbs == 0) { goto cleanup; } if (r->limbs != N->limbs) { goto cleanup; } ret = mbedtls_mpi_mod_raw_read(r->p, N, buf, buflen, ext_rep); if (ret != 0) { goto cleanup; } r->limbs = N->limbs; ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep(r->p, N); cleanup: return ret; } int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep) { /* Do our best to check if r and m have been set up */ if (r->limbs == 0 || N->limbs == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (r->limbs != N->limbs) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_uint *working_memory = r->p; size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs; if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) { working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint)); if (working_memory == NULL) { ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; goto cleanup; } memcpy(working_memory, r->p, working_memory_len); ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N); if (ret != 0) { goto cleanup; } } ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep); cleanup: if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY && working_memory != NULL) { mbedtls_zeroize_and_free(working_memory, working_memory_len); } return ret; } #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_mod.h000066400000000000000000000506011464416617300236270ustar00rootroot00000000000000/** * Modular bignum functions * * This module implements operations on integers modulo some fixed modulus. * * The functions in this module obey the following conventions unless * explicitly indicated otherwise: * * - **Modulus parameters**: the modulus is passed as a pointer to a structure * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an * array of limbs storing the bignum value of the modulus. The modulus must * be odd and is assumed to have no leading zeroes. The modulus is usually * named \c N and is usually input-only. Functions which take a parameter * of type \c const #mbedtls_mpi_mod_modulus* must not modify its value. * - **Bignum parameters**: Bignums are passed as pointers to an array of * limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type * #mbedtls_mpi_uint. Residues must be initialized before use, and must be * associated with the modulus \c N. Unless otherwise specified: * - Bignum parameters called \c A, \c B, ... are inputs and are not * modified by the function. Functions which take a parameter of * type \c const #mbedtls_mpi_mod_residue* must not modify its value. * - Bignum parameters called \c X, \c Y, ... are outputs or input-output. * The initial bignum value of output-only parameters is ignored, but * they must be set up and associated with the modulus \c N. Some * functions (typically constant-flow) require that the limbs in an * output residue are initialized. * - Bignum parameters called \c p are inputs used to set up a modulus or * residue. These must be pointers to an array of limbs. * - \c T is a temporary storage area. The initial content of such a * parameter is ignored and the final content is unspecified. * - Some functions use different names, such as \c r for the residue. * - **Bignum sizes**: bignum sizes are always expressed in limbs. Both * #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs * member storing its size. All bignum parameters must have the same * number of limbs as the modulus. All bignum sizes must be at least 1 and * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is * undefined. * - **Bignum representation**: the representation of inputs and outputs is * specified by the \c int_rep field of the modulus. * - **Parameter ordering**: for bignum parameters, outputs come before inputs. * The modulus is passed after residues. Temporaries come last. * - **Aliasing**: in general, output bignums may be aliased to one or more * inputs. Modulus values may not be aliased to any other parameter. Outputs * may not be aliased to one another. Temporaries may not be aliased to any * other parameter. * - **Overlap**: apart from aliasing of residue pointers (where two residue * arguments are equal pointers), overlap is not supported and may result * in undefined behavior. * - **Error handling**: functions generally check compatibility of input * sizes. Most functions will not check that input values are in canonical * form (i.e. that \c A < \c N), this is only checked during setup of a * residue structure. * - **Modular representatives**: all functions expect inputs to be in the * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. * Residues are set up with an associated modulus, and operations are only * guaranteed to work if the modulus is associated with all residue * parameters. If a residue is passed with a modulus other than the one it * is associated with, then it may be out of range. If an input is out of * range, outputs are fully unspecified, though bignum values out of range * should not cause buffer overflows (beware that this is not extensively * tested). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_MOD_H #define MBEDTLS_BIGNUM_MOD_H #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /** How residues associated with a modulus are represented. * * This also determines which fields of the modulus structure are valid and * what their contents are (see #mbedtls_mpi_mod_modulus). */ typedef enum { /** Representation not chosen (makes the modulus structure invalid). */ MBEDTLS_MPI_MOD_REP_INVALID = 0, /* Skip 1 as it is slightly easier to accidentally pass to functions. */ /** Montgomery representation. */ MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2, /* Optimised reduction available. This indicates a coordinate modulus (P) * and one or more of the following have been configured: * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM. * - A Kobliz Curve. * - A Fast Reduction Curve CURVE25519 or CURVE448. */ MBEDTLS_MPI_MOD_REP_OPT_RED, } mbedtls_mpi_mod_rep_selector; /* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to * make it easier to catch when they are accidentally swapped. */ typedef enum { MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0, MBEDTLS_MPI_MOD_EXT_REP_LE = 8, MBEDTLS_MPI_MOD_EXT_REP_BE } mbedtls_mpi_mod_ext_rep; typedef struct { mbedtls_mpi_uint *p; size_t limbs; } mbedtls_mpi_mod_residue; typedef struct { mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */ mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */ } mbedtls_mpi_mont_struct; typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs); typedef struct { mbedtls_mpi_modp_fn modp; /* The optimised reduction function pointer */ } mbedtls_mpi_opt_red_struct; typedef struct { const mbedtls_mpi_uint *p; size_t limbs; // number of limbs size_t bits; // bitlen of p mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union union rep { /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */ mbedtls_mpi_mont_struct mont; /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */ mbedtls_mpi_opt_red_struct ored; } rep; } mbedtls_mpi_mod_modulus; /** Setup a residue structure. * * The residue will be set up with the buffer \p p and modulus \p N. * * The memory pointed to by \p p will be used by the resulting residue structure. * The value at the pointed-to memory will be the initial value of \p r and must * hold a value that is less than the modulus. This value will be used as-is * and interpreted according to the value of the `N->int_rep` field. * * The modulus \p N will be the modulus associated with \p r. The residue \p r * should only be used in operations where the modulus is \p N. * * \param[out] r The address of the residue to setup. * \param[in] N The address of the modulus related to \p r. * \param[in] p The address of the limb array containing the value of \p r. * The memory pointed to by \p p will be used by \p r and must * not be modified in any way until after * mbedtls_mpi_mod_residue_release() is called. The data * pointed to by \p p must be less than the modulus (the value * pointed to by `N->p`) and already in the representation * indicated by `N->int_rep`. * \param p_limbs The number of limbs of \p p. Must be the same as the number * of limbs in the modulus \p N. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the * limbs in \p N or if \p p is not less than \p N. */ int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *p, size_t p_limbs); /** Unbind elements of a residue structure. * * This function removes the reference to the limb array that was passed to * mbedtls_mpi_mod_residue_setup() to make it safe to free or use again. * * This function invalidates \p r and it must not be used until after * mbedtls_mpi_mod_residue_setup() is called on it again. * * \param[out] r The address of residue to release. */ void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r); /** Initialize a modulus structure. * * \param[out] N The address of the modulus structure to initialize. */ void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N); /** Setup a modulus structure. * * \param[out] N The address of the modulus structure to populate. * \param[in] p The address of the limb array storing the value of \p N. * The memory pointed to by \p p will be used by \p N and must * not be modified in any way until after * mbedtls_mpi_mod_modulus_free() is called. * \param p_limbs The number of limbs of \p p. * * \return \c 0 if successful. */ int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs); /** Setup an optimised-reduction compatible modulus structure. * * \param[out] N The address of the modulus structure to populate. * \param[in] p The address of the limb array storing the value of \p N. * The memory pointed to by \p p will be used by \p N and must * not be modified in any way until after * mbedtls_mpi_mod_modulus_free() is called. * \param p_limbs The number of limbs of \p p. * \param modp A pointer to the optimised reduction function to use. \p p. * * \return \c 0 if successful. */ int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_mpi_uint *p, size_t p_limbs, mbedtls_mpi_modp_fn modp); /** Free elements of a modulus structure. * * This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup(). * * \warning This function does not free the limb array passed to * mbedtls_mpi_mod_modulus_setup() only removes the reference to it, * making it safe to free or to use it again. * * \param[in,out] N The address of the modulus structure to free. */ void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N); /** \brief Multiply two residues, returning the residue modulo the specified * modulus. * * \note Currently handles the case when `N->int_rep` is * MBEDTLS_MPI_MOD_REP_MONTGOMERY. * * The size of the operation is determined by \p N. \p A, \p B and \p X must * all be associated with the modulus \p N and must all have the same number * of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. They may not alias \p N (since they must be in canonical * form, they cannot == \p N). * * \param[out] X The address of the result MPI. Must have the same * number of limbs as \p N. * On successful completion, \p X contains the result of * the multiplication `A * B * R^-1` mod N where * `R = 2^(biL * N->limbs)`. * \param[in] A The address of the first MPI. * \param[in] B The address of the second MPI. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the multiplication. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not * have the same number of limbs or \p N is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. */ int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N); /** * \brief Perform a fixed-size modular subtraction. * * Calculate `A - B modulo N`. * * \p A, \p B and \p X must all have the same number of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \note This function does not check that \p A or \p B are in canonical * form (that is, are < \p N) - that will have been done by * mbedtls_mpi_mod_residue_setup(). * * \param[out] X The address of the result MPI. Must be initialized. * Must have the same number of limbs as the modulus \p N. * \param[in] A The address of the first MPI. * \param[in] B The address of the second MPI. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the subtraction. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not * have the correct number of limbs. */ int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N); /** * \brief Perform modular inversion of an MPI with respect to a modulus \p N. * * \p A and \p X must be associated with the modulus \p N and will therefore * have the same number of limbs as \p N. * * \p X may be aliased to \p A. * * \warning Currently only supports prime moduli, but does not check for them. * * \param[out] X The modular inverse of \p A with respect to \p N. * \param[in] A The number to calculate the modular inverse of. * Must not be 0. * \param[in] N The modulus to use. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not * have the same number of limbs. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough * memory (needed for conversion to and from Mongtomery form * when not in Montgomery form already, and for temporary use * by the inversion calculation itself). */ int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_modulus *N); /** * \brief Perform a fixed-size modular addition. * * Calculate `A + B modulo N`. * * \p A, \p B and \p X must all be associated with the modulus \p N and must * all have the same number of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \note This function does not check that \p A or \p B are in canonical * form (that is, are < \p N) - that will have been done by * mbedtls_mpi_mod_residue_setup(). * * \param[out] X The address of the result residue. Must be initialized. * Must have the same number of limbs as the modulus \p N. * \param[in] A The address of the first input residue. * \param[in] B The address of the second input residue. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the addition. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not * have the correct number of limbs. */ int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X, const mbedtls_mpi_mod_residue *A, const mbedtls_mpi_mod_residue *B, const mbedtls_mpi_mod_modulus *N); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination residue. * \param min The minimum value to return. It must be strictly smaller * than \b N. * \param N The modulus. * This is the upper bound of the output range, exclusive. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. */ int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Read a residue from a byte buffer. * * The residue will be automatically converted to the internal representation * based on the value of the `N->int_rep` field. * * The modulus \p N will be the modulus associated with \p r. The residue \p r * should only be used in operations where the modulus is \p N or a modulus * equivalent to \p N (in the sense that all their fields or memory pointed by * their fields hold the same value). * * \param[out] r The address of the residue. It must have exactly the same * number of limbs as the modulus \p N. * \param[in] N The address of the modulus. * \param[in] buf The input buffer to import from. * \param buflen The length in bytes of \p buf. * \param ext_rep The endianness of the number in the input buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't * large enough to hold the value in \p buf. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep * is invalid or the value in the buffer is not less than \p N. */ int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, const unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep); /** Write a residue into a byte buffer. * * The modulus \p N must be the modulus associated with \p r (see * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()). * * The residue will be automatically converted from the internal representation * based on the value of `N->int_rep` field. * * \warning If the buffer is smaller than `N->bits`, the number of * leading zeroes is leaked through timing. If \p r is * secret, the caller must ensure that \p buflen is at least * (`N->bits`+7)/8. * * \param[in] r The address of the residue. It must have the same number of * limbs as the modulus \p N. (\p r is an input parameter, but * its value will be modified during execution and restored * before the function returns.) * \param[in] N The address of the modulus associated with \p r. * \param[out] buf The output buffer to export to. * \param buflen The length in bytes of \p buf. * \param ext_rep The endianness in which the number should be written into * the output buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't * large enough to hold the value of \p r (without leading * zeroes). * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid. * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough * memory for conversion. Can occur only for moduli with * MBEDTLS_MPI_MOD_REP_MONTGOMERY. */ int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r, const mbedtls_mpi_mod_modulus *N, unsigned char *buf, size_t buflen, mbedtls_mpi_mod_ext_rep ext_rep); #endif /* MBEDTLS_BIGNUM_MOD_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c000066400000000000000000000221701464416617300244730ustar00rootroot00000000000000/* * Low-level modular bignum functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT) #include #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" #include "bignum_core.h" #include "bignum_mod_raw.h" #include "bignum_mod.h" #include "constant_time_internal.h" #include "bignum_mod_raw_invasive.h" void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char assign) { mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign)); } void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, const mbedtls_mpi_mod_modulus *N, unsigned char swap) { mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap)); } int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N, const unsigned char *input, size_t input_length, mbedtls_mpi_mod_ext_rep ext_rep) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (ext_rep) { case MBEDTLS_MPI_MOD_EXT_REP_LE: ret = mbedtls_mpi_core_read_le(X, N->limbs, input, input_length); break; case MBEDTLS_MPI_MOD_EXT_REP_BE: ret = mbedtls_mpi_core_read_be(X, N->limbs, input, input_length); break; default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (ret != 0) { goto cleanup; } if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } cleanup: return ret; } int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char *output, size_t output_length, mbedtls_mpi_mod_ext_rep ext_rep) { switch (ext_rep) { case MBEDTLS_MPI_MOD_EXT_REP_LE: return mbedtls_mpi_core_write_le(A, N->limbs, output, output_length); case MBEDTLS_MPI_MOD_EXT_REP_BE: return mbedtls_mpi_core_write_be(A, N->limbs, output, output_length); default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } } void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); } MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c); } void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *T) { /* Standard (A * B) multiplication stored into pre-allocated T * buffer of fixed limb size of (2N + 1). * * The space may not not fully filled by when * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */ const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2; switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs, N->rep.mont.mm, T); break; case MBEDTLS_MPI_MOD_REP_OPT_RED: mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs); /* Optimised Reduction */ (*N->rep.ored.modp)(T, T_limbs); /* Convert back to canonical representation */ mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N); memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint)); break; default: break; } } size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs) { /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent, * which will be the same size as the modulus and input (AN_limbs), * and additional space to pass to mbedtls_mpi_core_exp_mod(). */ return AN_limbs + mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs); } void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T) { /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and * |G| = N - 1, so we want * g^(|G|-1) = g^(N - 2) */ /* Use the first AN_limbs of T to hold N - 2 */ mbedtls_mpi_uint *Nminus2 = T; (void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs); /* Rest of T is given to exp_mod for its working space */ mbedtls_mpi_core_exp_mod(X, A, N, AN_limbs, Nminus2, AN_limbs, RR, T + AN_limbs); } void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint carry, borrow; carry = mbedtls_mpi_core_add(X, A, B, N->limbs); borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow)); } int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: return mbedtls_mpi_mod_raw_to_mont_rep(X, N); case MBEDTLS_MPI_MOD_REP_OPT_RED: return 0; default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } } int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { switch (N->int_rep) { case MBEDTLS_MPI_MOD_REP_MONTGOMERY: return mbedtls_mpi_mod_raw_from_mont_rep(X, N); case MBEDTLS_MPI_MOD_REP_OPT_RED: return 0; default: return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } } int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng); if (ret != 0) { return ret; } return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N); } int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_uint *T; const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, N->rep.mont.rr, T); mbedtls_zeroize_and_free(T, t_limbs * ciL); return 0; } int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N) { const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs); mbedtls_mpi_uint *T; if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T); mbedtls_zeroize_and_free(T, t_limbs * ciL); return 0; } void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N) { mbedtls_mpi_core_sub(X, N->p, A, N->limbs); /* If A=0 initially, then X=N now. Detect this by * subtracting N and catching the carry. */ mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs); (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow); } #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h000066400000000000000000000462211464416617300245030ustar00rootroot00000000000000/** * Low-level modular bignum functions * * This interface should only be used by the higher-level modular bignum * module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other * modules should use the high-level modular bignum interface (bignum_mod.h) * or the legacy bignum interface (bignum.h). * * This is a low-level interface to operations on integers modulo which * has no protection against passing invalid arguments such as arrays of * the wrong size. The functions in bignum_mod.h provide a higher-level * interface that includes protections against accidental misuse, at the * expense of code size and sometimes more cumbersome memory management. * * The functions in this module obey the following conventions unless * explicitly indicated otherwise: * - **Modulus parameters**: the modulus is passed as a pointer to a structure * of type #mbedtls_mpi_mod_modulus. The structure must be set up with an * array of limbs storing the bignum value of the modulus. The modulus must * be odd and is assumed to have no leading zeroes. The modulus is usually * named \c N and is usually input-only. * - **Bignum parameters**: Bignums are passed as pointers to an array of * limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified: * - Bignum parameters called \c A, \c B, ... are inputs, and are not * modified by the function. * - Bignum parameters called \c X, \c Y are outputs or input-output. * The initial content of output-only parameters is ignored. * - \c T is a temporary storage area. The initial content of such a * parameter is ignored and the final content is unspecified. * - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs * member of the modulus argument. All bignum parameters must have the same * number of limbs as the modulus. All bignum sizes must be at least 1 and * must be significantly less than #SIZE_MAX. The behavior if a size is 0 is * undefined. * - **Bignum representation**: the representation of inputs and outputs is * specified by the \c int_rep field of the modulus for arithmetic * functions. Utility functions may allow for different representation. * - **Parameter ordering**: for bignum parameters, outputs come before inputs. * The modulus is passed after other bignum input parameters. Temporaries * come last. * - **Aliasing**: in general, output bignums may be aliased to one or more * inputs. Modulus values may not be aliased to any other parameter. Outputs * may not be aliased to one another. Temporaries may not be aliased to any * other parameter. * - **Overlap**: apart from aliasing of limb array pointers (where two * arguments are equal pointers), overlap is not supported and may result * in undefined behavior. * - **Error handling**: This is a low-level module. Functions generally do not * try to protect against invalid arguments such as nonsensical sizes or * null pointers. Note that passing bignums with a different size than the * modulus may lead to buffer overflows. Some functions which allocate * memory or handle reading/writing of bignums will return an error if * memory allocation fails or if buffer sizes are invalid. * - **Modular representatives**: all functions expect inputs to be in the * range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If * an input is out of range, outputs are fully unspecified, though bignum * values out of range should not cause buffer overflows (beware that this is * not extensively tested). */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_MOD_RAW_H #define MBEDTLS_BIGNUM_MOD_RAW_H #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #include "bignum_mod.h" /** * \brief Perform a safe conditional copy of an MPI which doesn't reveal * whether the assignment was done or not. * * The size to copy is determined by \p N. * * \param[out] X The address of the destination MPI. * This must be initialized. Must have enough limbs to * store the full value of \p A. * \param[in] A The address of the source MPI. This must be initialized. * \param[in] N The address of the modulus related to \p X and \p A. * \param assign The condition deciding whether to perform the * assignment or not. Must be either 0 or 1: * * \c 1: Perform the assignment `X = A`. * * \c 0: Keep the original value of \p X. * * \note This function avoids leaking any information about whether * the assignment was done or not. * * \warning If \p assign is neither 0 nor 1, the result of this function * is indeterminate, and the resulting value in \p X might be * neither its original value nor the value in \p A. */ void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char assign); /** * \brief Perform a safe conditional swap of two MPIs which doesn't reveal * whether the swap was done or not. * * The size to swap is determined by \p N. * * \param[in,out] X The address of the first MPI. This must be initialized. * \param[in,out] Y The address of the second MPI. This must be initialized. * \param[in] N The address of the modulus related to \p X and \p Y. * \param swap The condition deciding whether to perform * the swap or not. Must be either 0 or 1: * * \c 1: Swap the values of \p X and \p Y. * * \c 0: Keep the original values of \p X and \p Y. * * \note This function avoids leaking any information about whether * the swap was done or not. * * \warning If \p swap is neither 0 nor 1, the result of this function * is indeterminate, and both \p X and \p Y might end up with * values different to either of the original ones. */ void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X, mbedtls_mpi_uint *Y, const mbedtls_mpi_mod_modulus *N, unsigned char swap); /** Import X from unsigned binary data. * * The MPI needs to have enough limbs to store the full value (including any * most significant zero bytes in the input). * * \param[out] X The address of the MPI. The size is determined by \p N. * (In particular, it must have at least as many limbs as * the modulus \p N.) * \param[in] N The address of the modulus related to \p X. * \param[in] input The input buffer to import from. * \param input_length The length in bytes of \p input. * \param ext_rep The endianness of the number in the input buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't * large enough to hold the value in \p input. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation * of \p N is invalid or \p X is not less than \p N. */ int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N, const unsigned char *input, size_t input_length, mbedtls_mpi_mod_ext_rep ext_rep); /** Export A into unsigned binary data. * * \param[in] A The address of the MPI. The size is determined by \p N. * (In particular, it must have at least as many limbs as * the modulus \p N.) * \param[in] N The address of the modulus related to \p A. * \param[out] output The output buffer to export to. * \param output_length The length in bytes of \p output. * \param ext_rep The endianness in which the number should be written into the output buffer. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't * large enough to hold the value of \p A. * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation * of \p N is invalid. */ int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N, unsigned char *output, size_t output_length, mbedtls_mpi_mod_ext_rep ext_rep); /** \brief Subtract two MPIs, returning the residue modulo the specified * modulus. * * The size of the operation is determined by \p N. \p A and \p B must have * the same number of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \param[out] X The address of the result MPI. * This must be initialized. Must have enough limbs to * store the full value of the result. * \param[in] A The address of the first MPI. This must be initialized. * \param[in] B The address of the second MPI. This must be initialized. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the subtraction. */ void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N); /** \brief Multiply two MPIs, returning the residue modulo the specified * modulus. * * \note Currently handles the case when `N->int_rep` is * MBEDTLS_MPI_MOD_REP_MONTGOMERY. * * The size of the operation is determined by \p N. \p A, \p B and \p X must * all be associated with the modulus \p N and must all have the same number * of limbs as \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. They may not alias \p N (since they must be in canonical * form, they cannot == \p N). * * \param[out] X The address of the result MPI. Must have the same * number of limbs as \p N. * On successful completion, \p X contains the result of * the multiplication `A * B * R^-1` mod N where * `R = 2^(biL * N->limbs)`. * \param[in] A The address of the first MPI. * \param[in] B The address of the second MPI. * \param[in] N The address of the modulus. Used to perform a modulo * operation on the result of the multiplication. * \param[in,out] T Temporary storage of size at least 2 * N->limbs + 1 * limbs. Its initial content is unused and * its final content is indeterminate. * It must not alias or otherwise overlap any of the * other parameters. */ void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N, mbedtls_mpi_uint *T); /** * \brief Returns the number of limbs of working memory required for * a call to `mbedtls_mpi_mod_raw_inv_prime()`. * * \note This will always be at least * `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`, * i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`. * * \param AN_limbs The number of limbs in the input `A` and the modulus `N` * (they must be the same size) that will be given to * `mbedtls_mpi_mod_raw_inv_prime()`. * * \return The number of limbs of working memory required by * `mbedtls_mpi_mod_raw_inv_prime()`. */ size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs); /** * \brief Perform fixed-width modular inversion of a Montgomery-form MPI with * respect to a modulus \p N that must be prime. * * \p X may be aliased to \p A, but not to \p N or \p RR. * * \param[out] X The modular inverse of \p A with respect to \p N. * Will be in Montgomery form. * \param[in] A The number to calculate the modular inverse of. * Must be in Montgomery form. Must not be 0. * \param[in] N The modulus, as a little-endian array of length \p AN_limbs. * Must be prime. * \param AN_limbs The number of limbs in \p A, \p N and \p RR. * \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little- * endian array of length \p AN_limbs. * \param[in,out] T Temporary storage of at least the number of limbs returned * by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`. * Its initial content is unused and its final content is * indeterminate. * It must not alias or otherwise overlap any of the other * parameters. * It is up to the caller to zeroize \p T when it is no * longer needed, and before freeing it if it was dynamically * allocated. */ void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *N, size_t AN_limbs, const mbedtls_mpi_uint *RR, mbedtls_mpi_uint *T); /** * \brief Perform a known-size modular addition. * * Calculate `A + B modulo N`. * * The number of limbs in each operand, and the result, is given by the * modulus \p N. * * \p X may be aliased to \p A or \p B, or even both, but may not overlap * either otherwise. * * \param[out] X The result of the modular addition. * \param[in] A Little-endian presentation of the left operand. This * must be smaller than \p N. * \param[in] B Little-endian presentation of the right operand. This * must be smaller than \p N. * \param[in] N The address of the modulus. */ void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_uint *B, const mbedtls_mpi_mod_modulus *N); /** Convert an MPI from canonical representation (little-endian limb array) * to the representation associated with the modulus. * * \param[in,out] X The limb array to convert. * It must have as many limbs as \p N. * It is converted in place. * If this function returns an error, the content of \p X * is unspecified. * \param[in] N The modulus structure. * * \return \c 0 if successful. * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. */ int mbedtls_mpi_mod_raw_canonical_to_modulus_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** Convert an MPI from the representation associated with the modulus * to canonical representation (little-endian limb array). * * \param[in,out] X The limb array to convert. * It must have as many limbs as \p N. * It is converted in place. * If this function returns an error, the content of \p X * is unspecified. * \param[in] N The modulus structure. * * \return \c 0 if successful. * Otherwise an \c MBEDTLS_ERR_MPI_xxx error code. */ int mbedtls_mpi_mod_raw_modulus_to_canonical_rep( mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** Generate a random number uniformly in a range. * * This function generates a random number between \p min inclusive and * \p N exclusive. * * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) * when the RNG is a suitably parametrized instance of HMAC_DRBG * and \p min is \c 1. * * \note There are `N - min` possible outputs. The lower bound * \p min can be reached, but the upper bound \p N cannot. * * \param X The destination MPI, in canonical representation modulo \p N. * It must not be aliased with \p N or otherwise overlap it. * \param min The minimum value to return. It must be strictly smaller * than \b N. * \param N The modulus. * This is the upper bound of the output range, exclusive. * \param f_rng The RNG function to use. This must not be \c NULL. * \param p_rng The RNG parameter to be passed to \p f_rng. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was * unable to find a suitable value within a limited number * of attempts. This has a negligible probability if \p N * is significantly larger than \p min, which is the case * for all usual cryptographic applications. */ int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X, mbedtls_mpi_uint min, const mbedtls_mpi_mod_modulus *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Convert an MPI into Montgomery form. * * \param X The address of the MPI. * Must have the same number of limbs as \p N. * \param N The address of the modulus, which gives the size of * the base `R` = 2^(biL*N->limbs). * * \return \c 0 if successful. */ int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** Convert an MPI back from Montgomery representation. * * \param X The address of the MPI. * Must have the same number of limbs as \p N. * \param N The address of the modulus, which gives the size of * the base `R`= 2^(biL*N->limbs). * * \return \c 0 if successful. */ int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); /** \brief Perform fixed width modular negation. * * The size of the operation is determined by \p N. \p A must have * the same number of limbs as \p N. * * \p X may be aliased to \p A. * * \param[out] X The result of the modular negation. * This must be initialized. * \param[in] A Little-endian presentation of the input operand. This * must be less than or equal to \p N. * \param[in] N The modulus to use. */ void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X, const mbedtls_mpi_uint *A, const mbedtls_mpi_mod_modulus *N); #endif /* MBEDTLS_BIGNUM_MOD_RAW_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h000066400000000000000000000020051464416617300263770ustar00rootroot00000000000000/** * \file bignum_mod_raw_invasive.h * * \brief Function declarations for invasive functions of Low-level * modular bignum. */ /** * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H #define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H #include "common.h" #include "mbedtls/bignum.h" #include "bignum_mod.h" #if defined(MBEDTLS_TEST_HOOKS) /** Convert the result of a quasi-reduction to its canonical representative. * * \param[in,out] X The address of the MPI to be converted. Must have the * same number of limbs as \p N. The input value must * be in range 0 <= X < 2N. * \param[in] N The address of the modulus. */ MBEDTLS_STATIC_TESTABLE void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X, const mbedtls_mpi_mod_modulus *N); #endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/block_cipher.c000066400000000000000000000146671464416617300241420ustar00rootroot00000000000000/** * \file block_cipher.c * * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, * for use by the GCM and CCM modules. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) #include "psa/crypto.h" #include "psa_crypto_core.h" #include "psa_util_internal.h" #endif #include "block_cipher_internal.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id) { switch (cipher_id) { #if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) case MBEDTLS_BLOCK_CIPHER_ID_AES: return PSA_KEY_TYPE_AES; #endif #if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: return PSA_KEY_TYPE_ARIA; #endif #if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: return PSA_KEY_TYPE_CAMELLIA; #endif default: return PSA_KEY_TYPE_NONE; } } static int mbedtls_cipher_error_from_psa(psa_status_t status) { return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors, psa_generic_status_to_mbedtls); } #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx) { #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { psa_destroy_key(ctx->psa_key_id); return; } #endif switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: mbedtls_aes_free(&ctx->ctx.aes); break; #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: mbedtls_aria_free(&ctx->ctx.aria); break; #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: mbedtls_camellia_free(&ctx->ctx.camellia); break; #endif default: break; } ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; } int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, mbedtls_cipher_id_t cipher_id) { ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES : (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA : (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA : MBEDTLS_BLOCK_CIPHER_ID_NONE; #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id); if (psa_key_type != PSA_KEY_TYPE_NONE && psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) { ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA; return 0; } ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY; #endif switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: mbedtls_aes_init(&ctx->ctx.aes); return 0; #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: mbedtls_aria_init(&ctx->ctx.aria); return 0; #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: mbedtls_camellia_init(&ctx->ctx.camellia); return 0; #endif default: ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE; return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, const unsigned char *key, unsigned key_bitlen) { #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id)); psa_set_key_bits(&key_attr, key_bitlen); psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id); if (status != PSA_SUCCESS) { return mbedtls_cipher_error_from_psa(status); } psa_reset_key_attributes(&key_attr); return 0; } #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen); #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen); #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen); #endif default: return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } } int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, const unsigned char input[16], unsigned char output[16]) { #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) { psa_status_t status; size_t olen; status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING, input, 16, output, 16, &olen); if (status != PSA_SUCCESS) { return mbedtls_cipher_error_from_psa(status); } return 0; } #endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */ switch (ctx->id) { #if defined(MBEDTLS_AES_C) case MBEDTLS_BLOCK_CIPHER_ID_AES: return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT, input, output); #endif #if defined(MBEDTLS_ARIA_C) case MBEDTLS_BLOCK_CIPHER_ID_ARIA: return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output); #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA: return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia, MBEDTLS_CAMELLIA_ENCRYPT, input, output); #endif default: return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } } #endif /* MBEDTLS_BLOCK_CIPHER_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/block_cipher_internal.h000066400000000000000000000065101464416617300260270ustar00rootroot00000000000000/** * \file block_cipher_internal.h * * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks, * for use by the GCM and CCM modules. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_BLOCK_CIPHER_INTERNAL_H #define MBEDTLS_BLOCK_CIPHER_INTERNAL_H #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #include "mbedtls/block_cipher.h" #ifdef __cplusplus extern "C" { #endif /** * \brief Initialize the context. * This must be the first API call before using the context. * * \param ctx The context to initialize. */ static inline void mbedtls_block_cipher_init(mbedtls_block_cipher_context_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } /** * \brief Set the block cipher to use with this context. * This must be called after mbedtls_block_cipher_init(). * * \param ctx The context to set up. * \param cipher_id The identifier of the cipher to use. * This must be either AES, ARIA or Camellia. * Warning: this is a ::mbedtls_cipher_id_t, * not a ::mbedtls_block_cipher_id_t! * * \retval \c 0 on success. * \retval #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if \p cipher_id was * invalid. */ int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx, mbedtls_cipher_id_t cipher_id); /** * \brief Set the key into the context. * * \param ctx The context to configure. * \param key The buffer holding the key material. * \param key_bitlen The size of the key in bits. * * \retval \c 0 on success. * \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not * properly set up before calling this function. * \retval One of #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH, * #MBEDTLS_ERR_ARIA_BAD_INPUT_DATA, * #MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA if \p key_bitlen is * invalid. */ int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx, const unsigned char *key, unsigned key_bitlen); /** * \brief Encrypt one block (16 bytes) with the configured key. * * \param ctx The context holding the key. * \param input The buffer holding the input block. Must be 16 bytes. * \param output The buffer to which the output block will be written. * Must be writable and 16 bytes long. * This must either not overlap with \p input, or be equal. * * \retval \c 0 on success. * \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not * properly set up before calling this function. * \retval Another negative value if encryption failed. */ int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx, const unsigned char input[16], unsigned char output[16]); /** * \brief Clear the context. * * \param ctx The context to clear. */ void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx); #ifdef __cplusplus } #endif #endif /* MBEDTLS_BLOCK_CIPHER_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/bn_mul.h000066400000000000000000001272421464416617300227710ustar00rootroot00000000000000/** * \file bn_mul.h * * \brief Multi-precision integer library */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Multiply source vector [s] with b, add result * to destination vector [d] and set carry c. * * Currently supports: * * . IA-32 (386+) . AMD64 / EM64T * . IA-32 (SSE2) . Motorola 68000 * . PowerPC, 32-bit . MicroBlaze * . PowerPC, 64-bit . TriCore * . SPARC v8 . ARM v3+ * . Alpha . MIPS32 * . C, longlong . C, generic */ #ifndef MBEDTLS_BN_MUL_H #define MBEDTLS_BN_MUL_H #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" /* * Conversion macros for embedded constants: * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 */ #if defined(MBEDTLS_HAVE_INT32) #define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d) \ ((mbedtls_mpi_uint) (a) << 0) | \ ((mbedtls_mpi_uint) (b) << 8) | \ ((mbedtls_mpi_uint) (c) << 16) | \ ((mbedtls_mpi_uint) (d) << 24) #define MBEDTLS_BYTES_TO_T_UINT_2(a, b) \ MBEDTLS_BYTES_TO_T_UINT_4(a, b, 0, 0) #define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h) \ MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d), \ MBEDTLS_BYTES_TO_T_UINT_4(e, f, g, h) #else /* 64-bits */ #define MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, e, f, g, h) \ ((mbedtls_mpi_uint) (a) << 0) | \ ((mbedtls_mpi_uint) (b) << 8) | \ ((mbedtls_mpi_uint) (c) << 16) | \ ((mbedtls_mpi_uint) (d) << 24) | \ ((mbedtls_mpi_uint) (e) << 32) | \ ((mbedtls_mpi_uint) (f) << 40) | \ ((mbedtls_mpi_uint) (g) << 48) | \ ((mbedtls_mpi_uint) (h) << 56) #define MBEDTLS_BYTES_TO_T_UINT_4(a, b, c, d) \ MBEDTLS_BYTES_TO_T_UINT_8(a, b, c, d, 0, 0, 0, 0) #define MBEDTLS_BYTES_TO_T_UINT_2(a, b) \ MBEDTLS_BYTES_TO_T_UINT_8(a, b, 0, 0, 0, 0, 0, 0) #endif /* bits in mbedtls_mpi_uint */ /* *INDENT-OFF* */ #if defined(MBEDTLS_HAVE_ASM) /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(__GNUC__) && \ ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) /* * GCC < 5.0 treated the x86 ebx (which is used for the GOT) as a * fixed reserved register when building as PIC, leading to errors * like: bn_mul.h:46:13: error: PIC register clobbered by 'ebx' in 'asm' * * This is fixed by an improved register allocator in GCC 5+. From the * release notes: * Register allocation improvements: Reuse of the PIC hard register, * instead of using a fixed register, was implemented on x86/x86-64 * targets. This improves generated PIC code performance as more hard * registers can be used. */ #if defined(__GNUC__) && __GNUC__ < 5 && defined(__PIC__) #define MULADDC_CANNOT_USE_EBX #endif /* * Disable use of the i386 assembly code below if option -O0, to disable all * compiler optimisations, is passed, detected with __OPTIMIZE__ * This is done as the number of registers used in the assembly code doesn't * work with the -O0 option. */ #if defined(__i386__) && defined(__OPTIMIZE__) && !defined(MULADDC_CANNOT_USE_EBX) #define MULADDC_X1_INIT \ { mbedtls_mpi_uint t; \ asm( \ "movl %%ebx, %0 \n\t" \ "movl %5, %%esi \n\t" \ "movl %6, %%edi \n\t" \ "movl %7, %%ecx \n\t" \ "movl %8, %%ebx \n\t" #define MULADDC_X1_CORE \ "lodsl \n\t" \ "mull %%ebx \n\t" \ "addl %%ecx, %%eax \n\t" \ "adcl $0, %%edx \n\t" \ "addl (%%edi), %%eax \n\t" \ "adcl $0, %%edx \n\t" \ "movl %%edx, %%ecx \n\t" \ "stosl \n\t" #define MULADDC_X1_STOP \ "movl %4, %%ebx \n\t" \ "movl %%ecx, %1 \n\t" \ "movl %%edi, %2 \n\t" \ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); } #if defined(MBEDTLS_HAVE_SSE2) #define MULADDC_X8_INIT MULADDC_X1_INIT #define MULADDC_X8_CORE \ "movd %%ecx, %%mm1 \n\t" \ "movd %%ebx, %%mm0 \n\t" \ "movd (%%edi), %%mm3 \n\t" \ "paddq %%mm3, %%mm1 \n\t" \ "movd (%%esi), %%mm2 \n\t" \ "pmuludq %%mm0, %%mm2 \n\t" \ "movd 4(%%esi), %%mm4 \n\t" \ "pmuludq %%mm0, %%mm4 \n\t" \ "movd 8(%%esi), %%mm6 \n\t" \ "pmuludq %%mm0, %%mm6 \n\t" \ "movd 12(%%esi), %%mm7 \n\t" \ "pmuludq %%mm0, %%mm7 \n\t" \ "paddq %%mm2, %%mm1 \n\t" \ "movd 4(%%edi), %%mm3 \n\t" \ "paddq %%mm4, %%mm3 \n\t" \ "movd 8(%%edi), %%mm5 \n\t" \ "paddq %%mm6, %%mm5 \n\t" \ "movd 12(%%edi), %%mm4 \n\t" \ "paddq %%mm4, %%mm7 \n\t" \ "movd %%mm1, (%%edi) \n\t" \ "movd 16(%%esi), %%mm2 \n\t" \ "pmuludq %%mm0, %%mm2 \n\t" \ "psrlq $32, %%mm1 \n\t" \ "movd 20(%%esi), %%mm4 \n\t" \ "pmuludq %%mm0, %%mm4 \n\t" \ "paddq %%mm3, %%mm1 \n\t" \ "movd 24(%%esi), %%mm6 \n\t" \ "pmuludq %%mm0, %%mm6 \n\t" \ "movd %%mm1, 4(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "movd 28(%%esi), %%mm3 \n\t" \ "pmuludq %%mm0, %%mm3 \n\t" \ "paddq %%mm5, %%mm1 \n\t" \ "movd 16(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm2 \n\t" \ "movd %%mm1, 8(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm7, %%mm1 \n\t" \ "movd 20(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm4 \n\t" \ "movd %%mm1, 12(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm2, %%mm1 \n\t" \ "movd 24(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm6 \n\t" \ "movd %%mm1, 16(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm4, %%mm1 \n\t" \ "movd 28(%%edi), %%mm5 \n\t" \ "paddq %%mm5, %%mm3 \n\t" \ "movd %%mm1, 20(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm6, %%mm1 \n\t" \ "movd %%mm1, 24(%%edi) \n\t" \ "psrlq $32, %%mm1 \n\t" \ "paddq %%mm3, %%mm1 \n\t" \ "movd %%mm1, 28(%%edi) \n\t" \ "addl $32, %%edi \n\t" \ "addl $32, %%esi \n\t" \ "psrlq $32, %%mm1 \n\t" \ "movd %%mm1, %%ecx \n\t" #define MULADDC_X8_STOP \ "emms \n\t" \ "movl %4, %%ebx \n\t" \ "movl %%ecx, %1 \n\t" \ "movl %%edi, %2 \n\t" \ "movl %%esi, %3 \n\t" \ : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ : "eax", "ebx", "ecx", "edx", "esi", "edi" \ ); } \ #endif /* SSE2 */ #endif /* i386 */ #if defined(__amd64__) || defined (__x86_64__) #define MULADDC_X1_INIT \ asm( \ "xorq %%r8, %%r8\n" #define MULADDC_X1_CORE \ "movq (%%rsi), %%rax\n" \ "mulq %%rbx\n" \ "addq $8, %%rsi\n" \ "addq %%rcx, %%rax\n" \ "movq %%r8, %%rcx\n" \ "adcq $0, %%rdx\n" \ "nop \n" \ "addq %%rax, (%%rdi)\n" \ "adcq %%rdx, %%rcx\n" \ "addq $8, %%rdi\n" #define MULADDC_X1_STOP \ : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ : "b" (b), "m" (*(const uint64_t (*)[16]) s) \ : "rax", "rdx", "r8" \ ); #endif /* AMD64 */ // The following assembly code assumes that a pointer will fit in a 64-bit register // (including ILP32 __aarch64__ ABIs such as on watchOS, hence the 2^32 - 1) #if defined(__aarch64__) && (UINTPTR_MAX == 0xfffffffful || UINTPTR_MAX == 0xfffffffffffffffful) /* * There are some issues around different compilers requiring different constraint * syntax for updating pointers from assembly code (see notes for * MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT in common.h), especially on aarch64_32 (aka ILP32). * * For this reason we cast the pointers to/from uintptr_t here. */ #define MULADDC_X1_INIT \ do { uintptr_t muladdc_d = (uintptr_t) d, muladdc_s = (uintptr_t) s; asm( #define MULADDC_X1_CORE \ "ldr x4, [%x2], #8 \n\t" \ "ldr x5, [%x1] \n\t" \ "mul x6, x4, %4 \n\t" \ "umulh x7, x4, %4 \n\t" \ "adds x5, x5, x6 \n\t" \ "adc x7, x7, xzr \n\t" \ "adds x5, x5, %0 \n\t" \ "adc %0, x7, xzr \n\t" \ "str x5, [%x1], #8 \n\t" #define MULADDC_X1_STOP \ : "+r" (c), \ "+r" (muladdc_d), \ "+r" (muladdc_s), \ "+m" (*(uint64_t (*)[16]) d) \ : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ : "x4", "x5", "x6", "x7", "cc" \ ); d = (mbedtls_mpi_uint *)muladdc_d; s = (mbedtls_mpi_uint *)muladdc_s; } while (0); #endif /* Aarch64 */ #if defined(__mc68020__) || defined(__mcpu32__) #define MULADDC_X1_INIT \ asm( \ "movl %3, %%a2 \n\t" \ "movl %4, %%a3 \n\t" \ "movl %5, %%d3 \n\t" \ "movl %6, %%d2 \n\t" \ "moveq #0, %%d0 \n\t" #define MULADDC_X1_CORE \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "moveq #0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "addxl %%d4, %%d3 \n\t" #define MULADDC_X1_STOP \ "movl %%d3, %0 \n\t" \ "movl %%a3, %1 \n\t" \ "movl %%a2, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ ); #define MULADDC_X8_INIT MULADDC_X1_INIT #define MULADDC_X8_CORE \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d4:%%d1 \n\t" \ "addxl %%d3, %%d1 \n\t" \ "addxl %%d0, %%d4 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "movel %%a2@+, %%d1 \n\t" \ "mulul %%d2, %%d3:%%d1 \n\t" \ "addxl %%d4, %%d1 \n\t" \ "addxl %%d0, %%d3 \n\t" \ "addl %%d1, %%a3@+ \n\t" \ "addxl %%d0, %%d3 \n\t" #define MULADDC_X8_STOP MULADDC_X1_STOP #endif /* MC68000 */ #if defined(__powerpc64__) || defined(__ppc64__) #if defined(__MACH__) && defined(__APPLE__) #define MULADDC_X1_INIT \ asm( \ "ld r3, %3 \n\t" \ "ld r4, %4 \n\t" \ "ld r5, %5 \n\t" \ "ld r6, %6 \n\t" \ "addi r3, r3, -8 \n\t" \ "addi r4, r4, -8 \n\t" \ "addic r5, r5, 0 \n\t" #define MULADDC_X1_CORE \ "ldu r7, 8(r3) \n\t" \ "mulld r8, r7, r6 \n\t" \ "mulhdu r9, r7, r6 \n\t" \ "adde r8, r8, r5 \n\t" \ "ld r7, 8(r4) \n\t" \ "addze r5, r9 \n\t" \ "addc r8, r8, r7 \n\t" \ "stdu r8, 8(r4) \n\t" #define MULADDC_X1_STOP \ "addze r5, r5 \n\t" \ "addi r4, r4, 8 \n\t" \ "addi r3, r3, 8 \n\t" \ "std r5, %0 \n\t" \ "std r4, %1 \n\t" \ "std r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #else /* __MACH__ && __APPLE__ */ #define MULADDC_X1_INIT \ asm( \ "ld %%r3, %3 \n\t" \ "ld %%r4, %4 \n\t" \ "ld %%r5, %5 \n\t" \ "ld %%r6, %6 \n\t" \ "addi %%r3, %%r3, -8 \n\t" \ "addi %%r4, %%r4, -8 \n\t" \ "addic %%r5, %%r5, 0 \n\t" #define MULADDC_X1_CORE \ "ldu %%r7, 8(%%r3) \n\t" \ "mulld %%r8, %%r7, %%r6 \n\t" \ "mulhdu %%r9, %%r7, %%r6 \n\t" \ "adde %%r8, %%r8, %%r5 \n\t" \ "ld %%r7, 8(%%r4) \n\t" \ "addze %%r5, %%r9 \n\t" \ "addc %%r8, %%r8, %%r7 \n\t" \ "stdu %%r8, 8(%%r4) \n\t" #define MULADDC_X1_STOP \ "addze %%r5, %%r5 \n\t" \ "addi %%r4, %%r4, 8 \n\t" \ "addi %%r3, %%r3, 8 \n\t" \ "std %%r5, %0 \n\t" \ "std %%r4, %1 \n\t" \ "std %%r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #endif /* __MACH__ && __APPLE__ */ #elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ #if defined(__MACH__) && defined(__APPLE__) #define MULADDC_X1_INIT \ asm( \ "lwz r3, %3 \n\t" \ "lwz r4, %4 \n\t" \ "lwz r5, %5 \n\t" \ "lwz r6, %6 \n\t" \ "addi r3, r3, -4 \n\t" \ "addi r4, r4, -4 \n\t" \ "addic r5, r5, 0 \n\t" #define MULADDC_X1_CORE \ "lwzu r7, 4(r3) \n\t" \ "mullw r8, r7, r6 \n\t" \ "mulhwu r9, r7, r6 \n\t" \ "adde r8, r8, r5 \n\t" \ "lwz r7, 4(r4) \n\t" \ "addze r5, r9 \n\t" \ "addc r8, r8, r7 \n\t" \ "stwu r8, 4(r4) \n\t" #define MULADDC_X1_STOP \ "addze r5, r5 \n\t" \ "addi r4, r4, 4 \n\t" \ "addi r3, r3, 4 \n\t" \ "stw r5, %0 \n\t" \ "stw r4, %1 \n\t" \ "stw r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #else /* __MACH__ && __APPLE__ */ #define MULADDC_X1_INIT \ asm( \ "lwz %%r3, %3 \n\t" \ "lwz %%r4, %4 \n\t" \ "lwz %%r5, %5 \n\t" \ "lwz %%r6, %6 \n\t" \ "addi %%r3, %%r3, -4 \n\t" \ "addi %%r4, %%r4, -4 \n\t" \ "addic %%r5, %%r5, 0 \n\t" #define MULADDC_X1_CORE \ "lwzu %%r7, 4(%%r3) \n\t" \ "mullw %%r8, %%r7, %%r6 \n\t" \ "mulhwu %%r9, %%r7, %%r6 \n\t" \ "adde %%r8, %%r8, %%r5 \n\t" \ "lwz %%r7, 4(%%r4) \n\t" \ "addze %%r5, %%r9 \n\t" \ "addc %%r8, %%r8, %%r7 \n\t" \ "stwu %%r8, 4(%%r4) \n\t" #define MULADDC_X1_STOP \ "addze %%r5, %%r5 \n\t" \ "addi %%r4, %%r4, 4 \n\t" \ "addi %%r3, %%r3, 4 \n\t" \ "stw %%r5, %0 \n\t" \ "stw %%r4, %1 \n\t" \ "stw %%r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ ); #endif /* __MACH__ && __APPLE__ */ #endif /* PPC32 */ /* * The Sparc(64) assembly is reported to be broken. * Disable it for now, until we're able to fix it. */ #if 0 && defined(__sparc__) #if defined(__sparc64__) #define MULADDC_X1_INIT \ asm( \ "ldx %3, %%o0 \n\t" \ "ldx %4, %%o1 \n\t" \ "ld %5, %%o2 \n\t" \ "ld %6, %%o3 \n\t" #define MULADDC_X1_CORE \ "ld [%%o0], %%o4 \n\t" \ "inc 4, %%o0 \n\t" \ "ld [%%o1], %%o5 \n\t" \ "umul %%o3, %%o4, %%o4 \n\t" \ "addcc %%o4, %%o2, %%o4 \n\t" \ "rd %%y, %%g1 \n\t" \ "addx %%g1, 0, %%g1 \n\t" \ "addcc %%o4, %%o5, %%o4 \n\t" \ "st %%o4, [%%o1] \n\t" \ "addx %%g1, 0, %%o2 \n\t" \ "inc 4, %%o1 \n\t" #define MULADDC_X1_STOP \ "st %%o2, %0 \n\t" \ "stx %%o1, %1 \n\t" \ "stx %%o0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "g1", "o0", "o1", "o2", "o3", "o4", \ "o5" \ ); #else /* __sparc64__ */ #define MULADDC_X1_INIT \ asm( \ "ld %3, %%o0 \n\t" \ "ld %4, %%o1 \n\t" \ "ld %5, %%o2 \n\t" \ "ld %6, %%o3 \n\t" #define MULADDC_X1_CORE \ "ld [%%o0], %%o4 \n\t" \ "inc 4, %%o0 \n\t" \ "ld [%%o1], %%o5 \n\t" \ "umul %%o3, %%o4, %%o4 \n\t" \ "addcc %%o4, %%o2, %%o4 \n\t" \ "rd %%y, %%g1 \n\t" \ "addx %%g1, 0, %%g1 \n\t" \ "addcc %%o4, %%o5, %%o4 \n\t" \ "st %%o4, [%%o1] \n\t" \ "addx %%g1, 0, %%o2 \n\t" \ "inc 4, %%o1 \n\t" #define MULADDC_X1_STOP \ "st %%o2, %0 \n\t" \ "st %%o1, %1 \n\t" \ "st %%o0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "g1", "o0", "o1", "o2", "o3", "o4", \ "o5" \ ); #endif /* __sparc64__ */ #endif /* __sparc__ */ #if defined(__microblaze__) || defined(microblaze) #define MULADDC_X1_INIT \ asm( \ "lwi r3, %3 \n\t" \ "lwi r4, %4 \n\t" \ "lwi r5, %5 \n\t" \ "lwi r6, %6 \n\t" \ "andi r7, r6, 0xffff \n\t" \ "bsrli r6, r6, 16 \n\t" #if(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) #define MULADDC_LHUI \ "lhui r9, r3, 0 \n\t" \ "addi r3, r3, 2 \n\t" \ "lhui r8, r3, 0 \n\t" #else #define MULADDC_LHUI \ "lhui r8, r3, 0 \n\t" \ "addi r3, r3, 2 \n\t" \ "lhui r9, r3, 0 \n\t" #endif #define MULADDC_X1_CORE \ MULADDC_LHUI \ "addi r3, r3, 2 \n\t" \ "mul r10, r9, r6 \n\t" \ "mul r11, r8, r7 \n\t" \ "mul r12, r9, r7 \n\t" \ "mul r13, r8, r6 \n\t" \ "bsrli r8, r10, 16 \n\t" \ "bsrli r9, r11, 16 \n\t" \ "add r13, r13, r8 \n\t" \ "add r13, r13, r9 \n\t" \ "bslli r10, r10, 16 \n\t" \ "bslli r11, r11, 16 \n\t" \ "add r12, r12, r10 \n\t" \ "addc r13, r13, r0 \n\t" \ "add r12, r12, r11 \n\t" \ "addc r13, r13, r0 \n\t" \ "lwi r10, r4, 0 \n\t" \ "add r12, r12, r10 \n\t" \ "addc r13, r13, r0 \n\t" \ "add r12, r12, r5 \n\t" \ "addc r5, r13, r0 \n\t" \ "swi r12, r4, 0 \n\t" \ "addi r4, r4, 4 \n\t" #define MULADDC_X1_STOP \ "swi r5, %0 \n\t" \ "swi r4, %1 \n\t" \ "swi r3, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r3", "r4", "r5", "r6", "r7", "r8", \ "r9", "r10", "r11", "r12", "r13" \ ); #endif /* MicroBlaze */ #if defined(__tricore__) #define MULADDC_X1_INIT \ asm( \ "ld.a %%a2, %3 \n\t" \ "ld.a %%a3, %4 \n\t" \ "ld.w %%d4, %5 \n\t" \ "ld.w %%d1, %6 \n\t" \ "xor %%d5, %%d5 \n\t" #define MULADDC_X1_CORE \ "ld.w %%d0, [%%a2+] \n\t" \ "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ "ld.w %%d0, [%%a3] \n\t" \ "addx %%d2, %%d2, %%d0 \n\t" \ "addc %%d3, %%d3, 0 \n\t" \ "mov %%d4, %%d3 \n\t" \ "st.w [%%a3+], %%d2 \n\t" #define MULADDC_X1_STOP \ "st.w %0, %%d4 \n\t" \ "st.a %1, %%a3 \n\t" \ "st.a %2, %%a2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "d0", "d1", "e2", "d4", "a2", "a3" \ ); #endif /* TriCore */ #if defined(__arm__) #if defined(__thumb__) && !defined(__thumb2__) #if defined(MBEDTLS_COMPILER_IS_GCC) /* * Thumb 1 ISA. This code path has only been tested successfully on gcc; * it does not compile on clang or armclang. */ #if !defined(__OPTIMIZE__) && defined(__GNUC__) /* * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about * our use of r7 below, unless -fomit-frame-pointer is passed. * * On the other hand, -fomit-frame-pointer is implied by any -Ox options with * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by * clang and armcc5 under the same conditions). * * If gcc needs to use r7, we use r1 as a scratch register and have a few extra * instructions to preserve/restore it; otherwise, we can use r7 and avoid * the preserve/restore overhead. */ #define MULADDC_SCRATCH "RS .req r1 \n\t" #define MULADDC_PRESERVE_SCRATCH "mov r10, r1 \n\t" #define MULADDC_RESTORE_SCRATCH "mov r1, r10 \n\t" #define MULADDC_SCRATCH_CLOBBER "r10" #else /* !defined(__OPTIMIZE__) && defined(__GNUC__) */ #define MULADDC_SCRATCH "RS .req r7 \n\t" #define MULADDC_PRESERVE_SCRATCH "" #define MULADDC_RESTORE_SCRATCH "" #define MULADDC_SCRATCH_CLOBBER "r7" #endif /* !defined(__OPTIMIZE__) && defined(__GNUC__) */ #define MULADDC_X1_INIT \ asm( \ MULADDC_SCRATCH \ "ldr r0, %3 \n\t" \ "ldr r1, %4 \n\t" \ "ldr r2, %5 \n\t" \ "ldr r3, %6 \n\t" \ "lsr r4, r3, #16 \n\t" \ "mov r9, r4 \n\t" \ "lsl r4, r3, #16 \n\t" \ "lsr r4, r4, #16 \n\t" \ "mov r8, r4 \n\t" \ #define MULADDC_X1_CORE \ MULADDC_PRESERVE_SCRATCH \ "ldmia r0!, {r6} \n\t" \ "lsr RS, r6, #16 \n\t" \ "lsl r6, r6, #16 \n\t" \ "lsr r6, r6, #16 \n\t" \ "mov r4, r8 \n\t" \ "mul r4, r6 \n\t" \ "mov r3, r9 \n\t" \ "mul r6, r3 \n\t" \ "mov r5, r9 \n\t" \ "mul r5, RS \n\t" \ "mov r3, r8 \n\t" \ "mul RS, r3 \n\t" \ "lsr r3, r6, #16 \n\t" \ "add r5, r5, r3 \n\t" \ "lsr r3, RS, #16 \n\t" \ "add r5, r5, r3 \n\t" \ "add r4, r4, r2 \n\t" \ "mov r2, #0 \n\t" \ "adc r5, r2 \n\t" \ "lsl r3, r6, #16 \n\t" \ "add r4, r4, r3 \n\t" \ "adc r5, r2 \n\t" \ "lsl r3, RS, #16 \n\t" \ "add r4, r4, r3 \n\t" \ "adc r5, r2 \n\t" \ MULADDC_RESTORE_SCRATCH \ "ldr r3, [r1] \n\t" \ "add r4, r4, r3 \n\t" \ "adc r2, r5 \n\t" \ "stmia r1!, {r4} \n\t" #define MULADDC_X1_STOP \ "str r2, %0 \n\t" \ "str r1, %1 \n\t" \ "str r0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r0", "r1", "r2", "r3", "r4", "r5", \ "r6", MULADDC_SCRATCH_CLOBBER, "r8", "r9", "cc" \ ); #endif /* !defined(__ARMCC_VERSION) && !defined(__clang__) */ #elif (__ARM_ARCH >= 6) && \ defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) /* Armv6-M (or later) with DSP Instruction Set Extensions. * Requires support for either Thumb 2 or Arm ISA. */ #define MULADDC_X1_INIT \ { \ mbedtls_mpi_uint tmp_a, tmp_b; \ asm volatile ( #define MULADDC_X1_CORE \ ".p2align 2 \n\t" \ "ldr %[a], [%[in]], #4 \n\t" \ "ldr %[b], [%[acc]] \n\t" \ "umaal %[b], %[carry], %[scalar], %[a] \n\t" \ "str %[b], [%[acc]], #4 \n\t" #define MULADDC_X1_STOP \ : [a] "=&r" (tmp_a), \ [b] "=&r" (tmp_b), \ [in] "+r" (s), \ [acc] "+r" (d), \ [carry] "+l" (c) \ : [scalar] "r" (b) \ : "memory" \ ); \ } #define MULADDC_X2_INIT \ { \ mbedtls_mpi_uint tmp_a0, tmp_b0; \ mbedtls_mpi_uint tmp_a1, tmp_b1; \ asm volatile ( /* - Make sure loop is 4-byte aligned to avoid stalls * upon repeated non-word aligned instructions in * some microarchitectures. * - Don't use ldm with post-increment or back-to-back * loads with post-increment and same address register * to avoid stalls on some microarchitectures. * - Bunch loads and stores to reduce latency on some * microarchitectures. E.g., on Cortex-M4, the first * in a series of load/store operations has latency * 2 cycles, while subsequent loads/stores are single-cycle. */ #define MULADDC_X2_CORE \ ".p2align 2 \n\t" \ "ldr %[a0], [%[in]], #+8 \n\t" \ "ldr %[b0], [%[acc]], #+8 \n\t" \ "ldr %[a1], [%[in], #-4] \n\t" \ "ldr %[b1], [%[acc], #-4] \n\t" \ "umaal %[b0], %[carry], %[scalar], %[a0] \n\t" \ "umaal %[b1], %[carry], %[scalar], %[a1] \n\t" \ "str %[b0], [%[acc], #-8] \n\t" \ "str %[b1], [%[acc], #-4] \n\t" #define MULADDC_X2_STOP \ : [a0] "=&r" (tmp_a0), \ [b0] "=&r" (tmp_b0), \ [a1] "=&r" (tmp_a1), \ [b1] "=&r" (tmp_b1), \ [in] "+r" (s), \ [acc] "+r" (d), \ [carry] "+l" (c) \ : [scalar] "r" (b) \ : "memory" \ ); \ } #else /* Thumb 2 or Arm ISA, without DSP extensions */ #define MULADDC_X1_INIT \ asm( \ "ldr r0, %3 \n\t" \ "ldr r1, %4 \n\t" \ "ldr r2, %5 \n\t" \ "ldr r3, %6 \n\t" #define MULADDC_X1_CORE \ "ldr r4, [r0], #4 \n\t" \ "mov r5, #0 \n\t" \ "ldr r6, [r1] \n\t" \ "umlal r2, r5, r3, r4 \n\t" \ "adds r4, r6, r2 \n\t" \ "adc r2, r5, #0 \n\t" \ "str r4, [r1], #4 \n\t" #define MULADDC_X1_STOP \ "str r2, %0 \n\t" \ "str r1, %1 \n\t" \ "str r0, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "r0", "r1", "r2", "r3", "r4", "r5", \ "r6", "cc" \ ); #endif /* ISA codepath selection */ #endif /* defined(__arm__) */ #if defined(__alpha__) #define MULADDC_X1_INIT \ asm( \ "ldq $1, %3 \n\t" \ "ldq $2, %4 \n\t" \ "ldq $3, %5 \n\t" \ "ldq $4, %6 \n\t" #define MULADDC_X1_CORE \ "ldq $6, 0($1) \n\t" \ "addq $1, 8, $1 \n\t" \ "mulq $6, $4, $7 \n\t" \ "umulh $6, $4, $6 \n\t" \ "addq $7, $3, $7 \n\t" \ "cmpult $7, $3, $3 \n\t" \ "ldq $5, 0($2) \n\t" \ "addq $7, $5, $7 \n\t" \ "cmpult $7, $5, $5 \n\t" \ "stq $7, 0($2) \n\t" \ "addq $2, 8, $2 \n\t" \ "addq $6, $3, $3 \n\t" \ "addq $5, $3, $3 \n\t" #define MULADDC_X1_STOP \ "stq $3, %0 \n\t" \ "stq $2, %1 \n\t" \ "stq $1, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ ); #endif /* Alpha */ #if defined(__mips__) && !defined(__mips64) #define MULADDC_X1_INIT \ asm( \ "lw $10, %3 \n\t" \ "lw $11, %4 \n\t" \ "lw $12, %5 \n\t" \ "lw $13, %6 \n\t" #define MULADDC_X1_CORE \ "lw $14, 0($10) \n\t" \ "multu $13, $14 \n\t" \ "addi $10, $10, 4 \n\t" \ "mflo $14 \n\t" \ "mfhi $9 \n\t" \ "addu $14, $12, $14 \n\t" \ "lw $15, 0($11) \n\t" \ "sltu $12, $14, $12 \n\t" \ "addu $15, $14, $15 \n\t" \ "sltu $14, $15, $14 \n\t" \ "addu $12, $12, $9 \n\t" \ "sw $15, 0($11) \n\t" \ "addu $12, $12, $14 \n\t" \ "addi $11, $11, 4 \n\t" #define MULADDC_X1_STOP \ "sw $12, %0 \n\t" \ "sw $11, %1 \n\t" \ "sw $10, %2 \n\t" \ : "=m" (c), "=m" (d), "=m" (s) \ : "m" (s), "m" (d), "m" (c), "m" (b) \ : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ ); #endif /* MIPS */ #endif /* GNUC */ #if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) #define MULADDC_X1_INIT \ __asm mov esi, s \ __asm mov edi, d \ __asm mov ecx, c \ __asm mov ebx, b #define MULADDC_X1_CORE \ __asm lodsd \ __asm mul ebx \ __asm add eax, ecx \ __asm adc edx, 0 \ __asm add eax, [edi] \ __asm adc edx, 0 \ __asm mov ecx, edx \ __asm stosd #define MULADDC_X1_STOP \ __asm mov c, ecx \ __asm mov d, edi \ __asm mov s, esi #if defined(MBEDTLS_HAVE_SSE2) #define EMIT __asm _emit #define MULADDC_X8_INIT MULADDC_X1_INIT #define MULADDC_X8_CORE \ EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ EMIT 0x0F EMIT 0x6E EMIT 0x1F \ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ EMIT 0x0F EMIT 0x6E EMIT 0x16 \ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ EMIT 0x0F EMIT 0x7E EMIT 0x0F \ EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ EMIT 0x0F EMIT 0x7E EMIT 0xC9 #define MULADDC_X8_STOP \ EMIT 0x0F EMIT 0x77 \ __asm mov c, ecx \ __asm mov d, edi \ __asm mov s, esi #endif /* SSE2 */ #endif /* MSVC */ #endif /* MBEDTLS_HAVE_ASM */ #if !defined(MULADDC_X1_CORE) #if defined(MBEDTLS_HAVE_UDBL) #define MULADDC_X1_INIT \ { \ mbedtls_t_udbl r; \ mbedtls_mpi_uint r0, r1; #define MULADDC_X1_CORE \ r = *(s++) * (mbedtls_t_udbl) b; \ r0 = (mbedtls_mpi_uint) r; \ r1 = (mbedtls_mpi_uint)( r >> biL ); \ r0 += c; r1 += (r0 < c); \ r0 += *d; r1 += (r0 < *d); \ c = r1; *(d++) = r0; #define MULADDC_X1_STOP \ } #else /* MBEDTLS_HAVE_UDBL */ #define MULADDC_X1_INIT \ { \ mbedtls_mpi_uint s0, s1, b0, b1; \ mbedtls_mpi_uint r0, r1, rx, ry; \ b0 = ( b << biH ) >> biH; \ b1 = ( b >> biH ); #define MULADDC_X1_CORE \ s0 = ( *s << biH ) >> biH; \ s1 = ( *s >> biH ); s++; \ rx = s0 * b1; r0 = s0 * b0; \ ry = s1 * b0; r1 = s1 * b1; \ r1 += ( rx >> biH ); \ r1 += ( ry >> biH ); \ rx <<= biH; ry <<= biH; \ r0 += rx; r1 += (r0 < rx); \ r0 += ry; r1 += (r0 < ry); \ r0 += c; r1 += (r0 < c); \ r0 += *d; r1 += (r0 < *d); \ c = r1; *(d++) = r0; #define MULADDC_X1_STOP \ } #endif /* C (longlong) */ #endif /* C (generic) */ #if !defined(MULADDC_X2_CORE) #define MULADDC_X2_INIT MULADDC_X1_INIT #define MULADDC_X2_STOP MULADDC_X1_STOP #define MULADDC_X2_CORE MULADDC_X1_CORE MULADDC_X1_CORE #endif /* MULADDC_X2_CORE */ #if !defined(MULADDC_X4_CORE) #define MULADDC_X4_INIT MULADDC_X2_INIT #define MULADDC_X4_STOP MULADDC_X2_STOP #define MULADDC_X4_CORE MULADDC_X2_CORE MULADDC_X2_CORE #endif /* MULADDC_X4_CORE */ #if !defined(MULADDC_X8_CORE) #define MULADDC_X8_INIT MULADDC_X4_INIT #define MULADDC_X8_STOP MULADDC_X4_STOP #define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE #endif /* MULADDC_X8_CORE */ /* *INDENT-ON* */ #endif /* bn_mul.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/camellia.c000066400000000000000000001041321464416617300232500ustar00rootroot00000000000000/* * Camellia implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The Camellia block cipher was designed by NTT and Mitsubishi Electric * Corporation. * * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf */ #include "common.h" #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #include "mbedtls/platform_util.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_CAMELLIA_ALT) static const unsigned char SIGMA_CHARS[6][8] = { { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } }; #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) static const unsigned char FSb[256] = { 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 }; #define SBOX1(n) FSb[(n)] #define SBOX2(n) (unsigned char) ((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) #define SBOX3(n) (unsigned char) ((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) #define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] #else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ static const unsigned char FSb[256] = { 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 }; static const unsigned char FSb2[256] = { 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 }; static const unsigned char FSb3[256] = { 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 }; static const unsigned char FSb4[256] = { 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 }; #define SBOX1(n) FSb[(n)] #define SBOX2(n) FSb2[(n)] #define SBOX3(n) FSb3[(n)] #define SBOX4(n) FSb4[(n)] #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ static const unsigned char shifts[2][4][4] = { { { 1, 1, 1, 1 }, /* KL */ { 0, 0, 0, 0 }, /* KR */ { 1, 1, 1, 1 }, /* KA */ { 0, 0, 0, 0 } /* KB */ }, { { 1, 0, 1, 1 }, /* KL */ { 1, 1, 0, 1 }, /* KR */ { 1, 1, 1, 0 }, /* KA */ { 1, 1, 0, 1 } /* KB */ } }; static const signed char indexes[2][4][20] = { { { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ }, { { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ } }; static const signed char transposes[2][20] = { { 21, 22, 23, 20, -1, -1, -1, -1, 18, 19, 16, 17, 11, 8, 9, 10, 15, 12, 13, 14 }, { 25, 26, 27, 24, 29, 30, 31, 28, 18, 19, 16, 17, -1, -1, -1, -1, -1, -1, -1, -1 } }; /* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ #define ROTL(DEST, SRC, SHIFT) \ { \ (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ } #define FL(XL, XR, KL, KR) \ { \ (XR) = ((((XL) &(KL)) << 1) | (((XL) &(KL)) >> 31)) ^ (XR); \ (XL) = ((XR) | (KR)) ^ (XL); \ } #define FLInv(YL, YR, KL, KR) \ { \ (YL) = ((YR) | (KR)) ^ (YL); \ (YR) = ((((YL) &(KL)) << 1) | (((YL) &(KL)) >> 31)) ^ (YR); \ } #define SHIFT_AND_PLACE(INDEX, OFFSET) \ { \ TK[0] = KC[(OFFSET) * 4 + 0]; \ TK[1] = KC[(OFFSET) * 4 + 1]; \ TK[2] = KC[(OFFSET) * 4 + 2]; \ TK[3] = KC[(OFFSET) * 4 + 3]; \ \ for (i = 1; i <= 4; i++) \ if (shifts[(INDEX)][(OFFSET)][i -1]) \ ROTL(TK + i * 4, TK, (15 * i) % 32); \ \ for (i = 0; i < 20; i++) \ if (indexes[(INDEX)][(OFFSET)][i] != -1) { \ RK[indexes[(INDEX)][(OFFSET)][i]] = TK[i]; \ } \ } static void camellia_feistel(const uint32_t x[2], const uint32_t k[2], uint32_t z[2]) { uint32_t I0, I1; I0 = x[0] ^ k[0]; I1 = x[1] ^ k[1]; I0 = ((uint32_t) SBOX1(MBEDTLS_BYTE_3(I0)) << 24) | ((uint32_t) SBOX2(MBEDTLS_BYTE_2(I0)) << 16) | ((uint32_t) SBOX3(MBEDTLS_BYTE_1(I0)) << 8) | ((uint32_t) SBOX4(MBEDTLS_BYTE_0(I0))); I1 = ((uint32_t) SBOX2(MBEDTLS_BYTE_3(I1)) << 24) | ((uint32_t) SBOX3(MBEDTLS_BYTE_2(I1)) << 16) | ((uint32_t) SBOX4(MBEDTLS_BYTE_1(I1)) << 8) | ((uint32_t) SBOX1(MBEDTLS_BYTE_0(I1))); I0 ^= (I1 << 8) | (I1 >> 24); I1 ^= (I0 << 16) | (I0 >> 16); I0 ^= (I1 >> 8) | (I1 << 24); I1 ^= (I0 >> 8) | (I0 << 24); z[0] ^= I1; z[1] ^= I0; } void mbedtls_camellia_init(mbedtls_camellia_context *ctx) { memset(ctx, 0, sizeof(mbedtls_camellia_context)); } void mbedtls_camellia_free(mbedtls_camellia_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_camellia_context)); } /* * Camellia key schedule (encryption) */ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits) { int idx; size_t i; uint32_t *RK; unsigned char t[64]; uint32_t SIGMA[6][2]; uint32_t KC[16]; uint32_t TK[20]; RK = ctx->rk; memset(t, 0, 64); memset(RK, 0, sizeof(ctx->rk)); switch (keybits) { case 128: ctx->nr = 3; idx = 0; break; case 192: case 256: ctx->nr = 4; idx = 1; break; default: return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } for (i = 0; i < keybits / 8; ++i) { t[i] = key[i]; } if (keybits == 192) { for (i = 0; i < 8; i++) { t[24 + i] = ~t[16 + i]; } } /* * Prepare SIGMA values */ for (i = 0; i < 6; i++) { SIGMA[i][0] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 0); SIGMA[i][1] = MBEDTLS_GET_UINT32_BE(SIGMA_CHARS[i], 4); } /* * Key storage in KC * Order: KL, KR, KA, KB */ memset(KC, 0, sizeof(KC)); /* Store KL, KR */ for (i = 0; i < 8; i++) { KC[i] = MBEDTLS_GET_UINT32_BE(t, i * 4); } /* Generate KA */ for (i = 0; i < 4; ++i) { KC[8 + i] = KC[i] ^ KC[4 + i]; } camellia_feistel(KC + 8, SIGMA[0], KC + 10); camellia_feistel(KC + 10, SIGMA[1], KC + 8); for (i = 0; i < 4; ++i) { KC[8 + i] ^= KC[i]; } camellia_feistel(KC + 8, SIGMA[2], KC + 10); camellia_feistel(KC + 10, SIGMA[3], KC + 8); if (keybits > 128) { /* Generate KB */ for (i = 0; i < 4; ++i) { KC[12 + i] = KC[4 + i] ^ KC[8 + i]; } camellia_feistel(KC + 12, SIGMA[4], KC + 14); camellia_feistel(KC + 14, SIGMA[5], KC + 12); } /* * Generating subkeys */ /* Manipulating KL */ SHIFT_AND_PLACE(idx, 0); /* Manipulating KR */ if (keybits > 128) { SHIFT_AND_PLACE(idx, 1); } /* Manipulating KA */ SHIFT_AND_PLACE(idx, 2); /* Manipulating KB */ if (keybits > 128) { SHIFT_AND_PLACE(idx, 3); } /* Do transpositions */ for (i = 0; i < 20; i++) { if (transposes[idx][i] != -1) { RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; } } return 0; } /* * Camellia key schedule (decryption) */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, unsigned int keybits) { int idx, ret; size_t i; mbedtls_camellia_context cty; uint32_t *RK; uint32_t *SK; mbedtls_camellia_init(&cty); /* Also checks keybits */ if ((ret = mbedtls_camellia_setkey_enc(&cty, key, keybits)) != 0) { goto exit; } ctx->nr = cty.nr; idx = (ctx->nr == 4); RK = ctx->rk; SK = cty.rk + 24 * 2 + 8 * idx * 2; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; for (i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4) { *RK++ = *SK++; *RK++ = *SK++; } SK -= 2; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; *RK++ = *SK++; exit: mbedtls_camellia_free(&cty); return ret; } #endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ /* * Camellia-ECB block encryption/decryption */ int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { int NR; uint32_t *RK, X[4]; if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } ((void) mode); NR = ctx->nr; RK = ctx->rk; X[0] = MBEDTLS_GET_UINT32_BE(input, 0); X[1] = MBEDTLS_GET_UINT32_BE(input, 4); X[2] = MBEDTLS_GET_UINT32_BE(input, 8); X[3] = MBEDTLS_GET_UINT32_BE(input, 12); X[0] ^= *RK++; X[1] ^= *RK++; X[2] ^= *RK++; X[3] ^= *RK++; while (NR) { --NR; camellia_feistel(X, RK, X + 2); RK += 2; camellia_feistel(X + 2, RK, X); RK += 2; camellia_feistel(X, RK, X + 2); RK += 2; camellia_feistel(X + 2, RK, X); RK += 2; camellia_feistel(X, RK, X + 2); RK += 2; camellia_feistel(X + 2, RK, X); RK += 2; if (NR) { FL(X[0], X[1], RK[0], RK[1]); RK += 2; FLInv(X[2], X[3], RK[0], RK[1]); RK += 2; } } X[2] ^= *RK++; X[3] ^= *RK++; X[0] ^= *RK++; X[1] ^= *RK++; MBEDTLS_PUT_UINT32_BE(X[2], output, 0); MBEDTLS_PUT_UINT32_BE(X[3], output, 4); MBEDTLS_PUT_UINT32_BE(X[0], output, 8); MBEDTLS_PUT_UINT32_BE(X[1], output, 12); return 0; } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * Camellia-CBC buffer encryption/decryption */ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { unsigned char temp[16]; if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } if (length % 16) { return MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_CAMELLIA_DECRYPT) { while (length > 0) { memcpy(temp, input, 16); mbedtls_camellia_crypt_ecb(ctx, mode, input, output); mbedtls_xor(output, output, iv, 16); memcpy(iv, temp, 16); input += 16; output += 16; length -= 16; } } else { while (length > 0) { mbedtls_xor(output, input, iv, 16); mbedtls_camellia_crypt_ecb(ctx, mode, output, output); memcpy(iv, output, 16); input += 16; output += 16; length -= 16; } } return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * Camellia-CFB128 buffer encryption/decryption */ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx, int mode, size_t length, size_t *iv_off, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int c; size_t n; if (mode != MBEDTLS_CAMELLIA_ENCRYPT && mode != MBEDTLS_CAMELLIA_DECRYPT) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } n = *iv_off; if (n >= 16) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } if (mode == MBEDTLS_CAMELLIA_DECRYPT) { while (length--) { if (n == 0) { mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv); } c = *input++; *output++ = (unsigned char) (c ^ iv[n]); iv[n] = (unsigned char) c; n = (n + 1) & 0x0F; } } else { while (length--) { if (n == 0) { mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv); } iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++); n = (n + 1) & 0x0F; } } *iv_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * Camellia-CTR buffer encryption/decryption */ int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx, size_t length, size_t *nc_off, unsigned char nonce_counter[16], unsigned char stream_block[16], const unsigned char *input, unsigned char *output) { int c, i; size_t n; n = *nc_off; if (n >= 16) { return MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA; } while (length--) { if (n == 0) { mbedtls_camellia_crypt_ecb(ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, stream_block); for (i = 16; i > 0; i--) { if (++nonce_counter[i - 1] != 0) { break; } } } c = *input++; *output++ = (unsigned char) (c ^ stream_block[n]); n = (n + 1) & 0x0F; } *nc_off = n; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* !MBEDTLS_CAMELLIA_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * Camellia test vectors from: * * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt * (For each bitlength: Key 0, Nr 39) */ #define CAMELLIA_TESTS_ECB 2 static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = { { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, }; static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = { { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = { { { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } }, { { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } }, { { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } } }; #if defined(MBEDTLS_CIPHER_MODE_CBC) #define CAMELLIA_TESTS_CBC 3 static const unsigned char camellia_test_cbc_key[3][32] = { { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } , { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } , { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } }; static const unsigned char camellia_test_cbc_iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } ; static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = { { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } }; static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = { { { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } }, { { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } }, { { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } } }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * Camellia-CTR test vectors from: * * http://www.faqs.org/rfcs/rfc5528.html */ static const unsigned char camellia_test_ctr_key[3][16] = { { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } }; static const unsigned char camellia_test_ctr_nonce_counter[3][16] = { { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } }; static const unsigned char camellia_test_ctr_pt[3][48] = { { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23 } }; static const unsigned char camellia_test_ctr_ct[3][48] = { { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, 0xDF, 0x50, 0x86, 0x96 } }; static const int camellia_test_ctr_len[3] = { 16, 32, 36 }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ /* * Checkup routine */ int mbedtls_camellia_self_test(int verbose) { int i, j, u, v; unsigned char key[32]; unsigned char buf[64]; unsigned char src[16]; unsigned char dst[16]; #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char iv[16]; #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) size_t offset, len; unsigned char nonce_counter[16]; unsigned char stream_block[16]; #endif int ret = 1; mbedtls_camellia_context ctx; mbedtls_camellia_init(&ctx); memset(key, 0, 32); for (j = 0; j < 6; j++) { u = j >> 1; v = j & 1; if (verbose != 0) { mbedtls_printf(" CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (v == MBEDTLS_CAMELLIA_DECRYPT) { if (verbose != 0) { mbedtls_printf("skipped\n"); } continue; } #endif for (i = 0; i < CAMELLIA_TESTS_ECB; i++) { memcpy(key, camellia_test_ecb_key[u][i], 16 + 8 * u); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (v == MBEDTLS_CAMELLIA_DECRYPT) { mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64); memcpy(src, camellia_test_ecb_cipher[u][i], 16); memcpy(dst, camellia_test_ecb_plain[i], 16); } else #endif { /* MBEDTLS_CAMELLIA_ENCRYPT */ mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64); memcpy(src, camellia_test_ecb_plain[i], 16); memcpy(dst, camellia_test_ecb_cipher[u][i], 16); } mbedtls_camellia_crypt_ecb(&ctx, v, src, buf); if (memcmp(buf, dst, 16) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ for (j = 0; j < 6; j++) { u = j >> 1; v = j & 1; if (verbose != 0) { mbedtls_printf(" CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } memcpy(src, camellia_test_cbc_iv, 16); memcpy(dst, camellia_test_cbc_iv, 16); memcpy(key, camellia_test_cbc_key[u], 16 + 8 * u); if (v == MBEDTLS_CAMELLIA_DECRYPT) { mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64); } else { mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64); } for (i = 0; i < CAMELLIA_TESTS_CBC; i++) { if (v == MBEDTLS_CAMELLIA_DECRYPT) { memcpy(iv, src, 16); memcpy(src, camellia_test_cbc_cipher[u][i], 16); memcpy(dst, camellia_test_cbc_plain[i], 16); } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ memcpy(iv, dst, 16); memcpy(src, camellia_test_cbc_plain[i], 16); memcpy(dst, camellia_test_cbc_cipher[u][i], 16); } mbedtls_camellia_crypt_cbc(&ctx, v, 16, iv, src, buf); if (memcmp(buf, dst, 16) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } if (verbose != 0) { mbedtls_printf("passed\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ if (verbose != 0) { mbedtls_printf("\n"); } #if defined(MBEDTLS_CIPHER_MODE_CTR) /* * CTR mode */ for (i = 0; i < 6; i++) { u = i >> 1; v = i & 1; if (verbose != 0) { mbedtls_printf(" CAMELLIA-CTR-128 (%s): ", (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); } memcpy(nonce_counter, camellia_test_ctr_nonce_counter[u], 16); memcpy(key, camellia_test_ctr_key[u], 16); offset = 0; mbedtls_camellia_setkey_enc(&ctx, key, 128); if (v == MBEDTLS_CAMELLIA_DECRYPT) { len = camellia_test_ctr_len[u]; memcpy(buf, camellia_test_ctr_ct[u], len); mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); if (memcmp(buf, camellia_test_ctr_pt[u], len) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } else { len = camellia_test_ctr_len[u]; memcpy(buf, camellia_test_ctr_pt[u], len); mbedtls_camellia_crypt_ctr(&ctx, len, &offset, nonce_counter, stream_block, buf, buf); if (memcmp(buf, camellia_test_ctr_ct[u], len) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ ret = 0; exit: mbedtls_camellia_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CAMELLIA_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ccm.c000066400000000000000000000555711464416617300222570ustar00rootroot00000000000000/* * NIST SP800-38C compliant CCM implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Definition of CCM: * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf * RFC 3610 "Counter with CBC-MAC (CCM)" * * Related: * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" */ #include "common.h" #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "block_cipher_internal.h" #endif #include #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #include #define mbedtls_printf printf #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_PLATFORM_C */ #if !defined(MBEDTLS_CCM_ALT) /* * Initialize context */ void mbedtls_ccm_init(mbedtls_ccm_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ccm_context)); } int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { return MBEDTLS_ERR_CCM_BAD_INPUT; } #else const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); if (cipher_info == NULL) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_CCM_BAD_INPUT; } mbedtls_cipher_free(&ctx->cipher_ctx); if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, MBEDTLS_ENCRYPT)) != 0) { return ret; } #endif return ret; } /* * Free context */ void mbedtls_ccm_free(mbedtls_ccm_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); #else mbedtls_cipher_free(&ctx->cipher_ctx); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context)); } #define CCM_STATE__CLEAR 0 #define CCM_STATE__STARTED (1 << 0) #define CCM_STATE__LENGTHS_SET (1 << 1) #define CCM_STATE__AUTH_DATA_STARTED (1 << 2) #define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) #define CCM_STATE__ERROR (1 << 4) /* * Encrypt or decrypt a partial block with CTR */ static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx, size_t offset, size_t use_len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp_buf[16] = { 0 }; #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf); #else size_t olen = 0; ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); return ret; } mbedtls_xor(output, input, tmp_buf + offset, use_len); mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); return ret; } static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) { ctx->state = CCM_STATE__CLEAR; memset(ctx->y, 0, 16); memset(ctx->ctr, 0, 16); } static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; size_t len_left; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen; #endif /* length calculation can be done only after both * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed */ if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) { return 0; } /* CCM expects non-empty tag. * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. */ if (ctx->tag_len == 0) { if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { ctx->plaintext_len = 0; } else { return MBEDTLS_ERR_CCM_BAD_INPUT; } } /* * First block: * 0 .. 0 flags * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() * iv_len+1 .. 15 length * * With flags as (bits): * 7 0 * 6 add present? * 5 .. 3 (t - 2) / 2 * 2 .. 0 q - 1 */ ctx->y[0] |= (ctx->add_len > 0) << 6; ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3; ctx->y[0] |= ctx->q - 1; for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) { ctx->y[15-i] = MBEDTLS_BYTE_0(len_left); } if (len_left > 0) { ctx->state |= CCM_STATE__ERROR; return MBEDTLS_ERR_CCM_BAD_INPUT; } /* Start CBC-MAC with first block*/ #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; return ret; } return 0; } int mbedtls_ccm_starts(mbedtls_ccm_context *ctx, int mode, const unsigned char *iv, size_t iv_len) { /* Also implies q is within bounds */ if (iv_len < 7 || iv_len > 13) { return MBEDTLS_ERR_CCM_BAD_INPUT; } ctx->mode = mode; ctx->q = 16 - 1 - (unsigned char) iv_len; /* * Prepare counter block for encryption: * 0 .. 0 flags * 1 .. iv_len nonce (aka iv) * iv_len+1 .. 15 counter (initially 1) * * With flags as (bits): * 7 .. 3 0 * 2 .. 0 q - 1 */ memset(ctx->ctr, 0, 16); ctx->ctr[0] = ctx->q - 1; memcpy(ctx->ctr + 1, iv, iv_len); memset(ctx->ctr + 1 + iv_len, 0, ctx->q); ctx->ctr[15] = 1; /* * See ccm_calculate_first_block_if_ready() for block layout description */ memcpy(ctx->y + 1, iv, iv_len); ctx->state |= CCM_STATE__STARTED; return ccm_calculate_first_block_if_ready(ctx); } int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx, size_t total_ad_len, size_t plaintext_len, size_t tag_len) { /* * Check length requirements: SP800-38C A.1 * Additional requirement: a < 2^16 - 2^8 to simplify the code. * 'length' checked later (when writing it to the first block) * * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). */ if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (total_ad_len >= 0xFF00) { return MBEDTLS_ERR_CCM_BAD_INPUT; } ctx->plaintext_len = plaintext_len; ctx->add_len = total_ad_len; ctx->tag_len = tag_len; ctx->processed = 0; ctx->state |= CCM_STATE__LENGTHS_SET; return ccm_calculate_first_block_if_ready(ctx); } int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx, const unsigned char *add, size_t add_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t use_len, offset; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen; #endif if (ctx->state & CCM_STATE__ERROR) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (add_len > 0) { if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) { if (add_len > ctx->add_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF); ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF); ctx->state |= CCM_STATE__AUTH_DATA_STARTED; } else if (ctx->processed + add_len > ctx->add_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } while (add_len > 0) { offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] * holding total auth data length */ use_len = 16 - offset; if (use_len > add_len) { use_len = add_len; } mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len); ctx->processed += use_len; add_len -= use_len; add += use_len; if (use_len + offset == 16 || ctx->processed == ctx->add_len) { #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; return ret; } } } if (ctx->processed == ctx->add_len) { ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; ctx->processed = 0; // prepare for mbedtls_ccm_update() } } return 0; } int mbedtls_ccm_update(mbedtls_ccm_context *ctx, const unsigned char *input, size_t input_len, unsigned char *output, size_t output_size, size_t *output_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; size_t use_len, offset; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen; #endif unsigned char local_output[16]; if (ctx->state & CCM_STATE__ERROR) { return MBEDTLS_ERR_CCM_BAD_INPUT; } /* Check against plaintext length only if performing operation with * authentication */ if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (output_size < input_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } *output_len = input_len; ret = 0; while (input_len > 0) { offset = ctx->processed % 16; use_len = 16 - offset; if (use_len > input_len) { use_len = input_len; } ctx->processed += use_len; if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \ ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) { mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len); if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; goto exit; } } ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output); if (ret != 0) { goto exit; } } if (ctx->mode == MBEDTLS_CCM_DECRYPT || \ ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) { /* Since output may be in shared memory, we cannot be sure that * it will contain what we wrote to it. Therefore, we should avoid using * it as input to any operations. * Write decrypted data to local_output to avoid using output variable as * input in the XOR operation for Y. */ ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output); if (ret != 0) { goto exit; } mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len); memcpy(output, local_output, use_len); if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen); #endif if (ret != 0) { ctx->state |= CCM_STATE__ERROR; goto exit; } } } if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) { for (i = 0; i < ctx->q; i++) { if (++(ctx->ctr)[15-i] != 0) { break; } } } input_len -= use_len; input += use_len; output += use_len; } exit: mbedtls_platform_zeroize(local_output, 16); return ret; } int mbedtls_ccm_finish(mbedtls_ccm_context *ctx, unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; if (ctx->state & CCM_STATE__ERROR) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) { return MBEDTLS_ERR_CCM_BAD_INPUT; } if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) { return MBEDTLS_ERR_CCM_BAD_INPUT; } /* * Authentication: reset counter and crypt/mask internal tag */ for (i = 0; i < ctx->q; i++) { ctx->ctr[15-i] = 0; } ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y); if (ret != 0) { return ret; } if (tag != NULL) { memcpy(tag, ctx->y, tag_len); } mbedtls_ccm_clear_state(ctx); return 0; } /* * Authenticated encryption or decryption */ static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_update(ctx, input, length, output, length, &olen)) != 0) { return ret; } if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) { return ret; } return 0; } /* * Authenticated encryption */ int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, unsigned char *tag, size_t tag_len) { return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } /* * Authenticated decryption */ static int mbedtls_ccm_compare_tags(const unsigned char *tag1, const unsigned char *tag2, size_t tag_len) { /* Check tag in "constant-time" */ int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len); if (diff != 0) { return MBEDTLS_ERR_CCM_AUTH_FAILED; } return 0; } static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; if ((ret = ccm_auth_crypt(ctx, mode, length, iv, iv_len, add, add_len, input, output, check_tag, tag_len)) != 0) { return ret; } if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) { mbedtls_platform_zeroize(output, length); return ret; } return 0; } int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, const unsigned char *tag, size_t tag_len) { return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag, tag_len); } #endif /* !MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /* * Examples 1 to 3 from SP800-38C Appendix C */ #define NB_TESTS 3 #define CCM_SELFTEST_PT_MAX_LEN 24 #define CCM_SELFTEST_CT_MAX_LEN 32 /* * The data is the same for all tests, only the used length changes */ static const unsigned char key_test_data[] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; static const unsigned char iv_test_data[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b }; static const unsigned char ad_test_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 }; static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, }; static const size_t iv_len_test_data[NB_TESTS] = { 7, 8, 12 }; static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } }; int mbedtls_ccm_self_test(int verbose) { mbedtls_ccm_context ctx; /* * Some hardware accelerators require the input and output buffers * would be in RAM, because the flash is not accessible. * Use buffers on the stack to hold the test vectors data. */ unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; size_t i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ccm_init(&ctx); if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, 8 * sizeof(key_test_data)) != 0) { if (verbose != 0) { mbedtls_printf(" CCM: setup failed"); } return 1; } for (i = 0; i < NB_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1); } memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN); memcpy(plaintext, msg_test_data, msg_len_test_data[i]); ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i], iv_test_data, iv_len_test_data[i], ad_test_data, add_len_test_data[i], plaintext, ciphertext, ciphertext + msg_len_test_data[i], tag_len_test_data[i]); if (ret != 0 || memcmp(ciphertext, res_test_data[i], msg_len_test_data[i] + tag_len_test_data[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN); ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i], iv_test_data, iv_len_test_data[i], ad_test_data, add_len_test_data[i], ciphertext, plaintext, ciphertext + msg_len_test_data[i], tag_len_test_data[i]); if (ret != 0 || memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (verbose != 0) { mbedtls_printf("passed\n"); } } mbedtls_ccm_free(&ctx); if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_CCM_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/chacha20.c000066400000000000000000000410101464416617300230450ustar00rootroot00000000000000/** * \file chacha20.c * * \brief ChaCha20 cipher. * * \author Daniel King * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_CHACHA20_ALT) #define ROTL32(value, amount) \ ((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount)))) #define CHACHA20_CTR_INDEX (12U) #define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U) /** * \brief ChaCha20 quarter round operation. * * The quarter round is defined as follows (from RFC 7539): * 1. a += b; d ^= a; d <<<= 16; * 2. c += d; b ^= c; b <<<= 12; * 3. a += b; d ^= a; d <<<= 8; * 4. c += d; b ^= c; b <<<= 7; * * \param state ChaCha20 state to modify. * \param a The index of 'a' in the state. * \param b The index of 'b' in the state. * \param c The index of 'c' in the state. * \param d The index of 'd' in the state. */ static inline void chacha20_quarter_round(uint32_t state[16], size_t a, size_t b, size_t c, size_t d) { /* a += b; d ^= a; d <<<= 16; */ state[a] += state[b]; state[d] ^= state[a]; state[d] = ROTL32(state[d], 16); /* c += d; b ^= c; b <<<= 12 */ state[c] += state[d]; state[b] ^= state[c]; state[b] = ROTL32(state[b], 12); /* a += b; d ^= a; d <<<= 8; */ state[a] += state[b]; state[d] ^= state[a]; state[d] = ROTL32(state[d], 8); /* c += d; b ^= c; b <<<= 7; */ state[c] += state[d]; state[b] ^= state[c]; state[b] = ROTL32(state[b], 7); } /** * \brief Perform the ChaCha20 inner block operation. * * This function performs two rounds: the column round and the * diagonal round. * * \param state The ChaCha20 state to update. */ static void chacha20_inner_block(uint32_t state[16]) { chacha20_quarter_round(state, 0, 4, 8, 12); chacha20_quarter_round(state, 1, 5, 9, 13); chacha20_quarter_round(state, 2, 6, 10, 14); chacha20_quarter_round(state, 3, 7, 11, 15); chacha20_quarter_round(state, 0, 5, 10, 15); chacha20_quarter_round(state, 1, 6, 11, 12); chacha20_quarter_round(state, 2, 7, 8, 13); chacha20_quarter_round(state, 3, 4, 9, 14); } /** * \brief Generates a keystream block. * * \param initial_state The initial ChaCha20 state (key, nonce, counter). * \param keystream Generated keystream bytes are written to this buffer. */ static void chacha20_block(const uint32_t initial_state[16], unsigned char keystream[64]) { uint32_t working_state[16]; size_t i; memcpy(working_state, initial_state, CHACHA20_BLOCK_SIZE_BYTES); for (i = 0U; i < 10U; i++) { chacha20_inner_block(working_state); } working_state[0] += initial_state[0]; working_state[1] += initial_state[1]; working_state[2] += initial_state[2]; working_state[3] += initial_state[3]; working_state[4] += initial_state[4]; working_state[5] += initial_state[5]; working_state[6] += initial_state[6]; working_state[7] += initial_state[7]; working_state[8] += initial_state[8]; working_state[9] += initial_state[9]; working_state[10] += initial_state[10]; working_state[11] += initial_state[11]; working_state[12] += initial_state[12]; working_state[13] += initial_state[13]; working_state[14] += initial_state[14]; working_state[15] += initial_state[15]; for (i = 0U; i < 16; i++) { size_t offset = i * 4U; MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset); } mbedtls_platform_zeroize(working_state, sizeof(working_state)); } void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx) { mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state)); mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); /* Initially, there's no keystream bytes available */ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; } void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx) { if (ctx != NULL) { mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context)); } } int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx, const unsigned char key[32]) { /* ChaCha20 constants - the string "expand 32-byte k" */ ctx->state[0] = 0x61707865; ctx->state[1] = 0x3320646e; ctx->state[2] = 0x79622d32; ctx->state[3] = 0x6b206574; /* Set key */ ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0); ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4); ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8); ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12); ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16); ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20); ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24); ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28); return 0; } int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx, const unsigned char nonce[12], uint32_t counter) { /* Counter */ ctx->state[12] = counter; /* Nonce */ ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0); ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4); ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8); mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8)); /* Initially, there's no keystream bytes available */ ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; return 0; } int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx, size_t size, const unsigned char *input, unsigned char *output) { size_t offset = 0U; /* Use leftover keystream bytes, if available */ while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) { output[offset] = input[offset] ^ ctx->keystream8[ctx->keystream_bytes_used]; ctx->keystream_bytes_used++; offset++; size--; } /* Process full blocks */ while (size >= CHACHA20_BLOCK_SIZE_BYTES) { /* Generate new keystream block and increment counter */ chacha20_block(ctx->state, ctx->keystream8); ctx->state[CHACHA20_CTR_INDEX]++; mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U); offset += CHACHA20_BLOCK_SIZE_BYTES; size -= CHACHA20_BLOCK_SIZE_BYTES; } /* Last (partial) block */ if (size > 0U) { /* Generate new keystream block and increment counter */ chacha20_block(ctx->state, ctx->keystream8); ctx->state[CHACHA20_CTR_INDEX]++; mbedtls_xor(output + offset, input + offset, ctx->keystream8, size); ctx->keystream_bytes_used = size; } return 0; } int mbedtls_chacha20_crypt(const unsigned char key[32], const unsigned char nonce[12], uint32_t counter, size_t data_len, const unsigned char *input, unsigned char *output) { mbedtls_chacha20_context ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_chacha20_init(&ctx); ret = mbedtls_chacha20_setkey(&ctx, key); if (ret != 0) { goto cleanup; } ret = mbedtls_chacha20_starts(&ctx, nonce, counter); if (ret != 0) { goto cleanup; } ret = mbedtls_chacha20_update(&ctx, data_len, input, output); cleanup: mbedtls_chacha20_free(&ctx); return ret; } #endif /* !MBEDTLS_CHACHA20_ALT */ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_keys[2][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }; static const unsigned char test_nonces[2][12] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } }; static const uint32_t test_counters[2] = { 0U, 1U }; static const unsigned char test_input[2][375] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f } }; static const unsigned char test_output[2][375] = { { 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 }, { 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 } }; static const size_t test_lengths[2] = { 64U, 375U }; /* Make sure no other definition is already present. */ #undef ASSERT #define ASSERT(cond, args) \ do \ { \ if (!(cond)) \ { \ if (verbose != 0) \ mbedtls_printf args; \ \ return -1; \ } \ } \ while (0) int mbedtls_chacha20_self_test(int verbose) { unsigned char output[381]; unsigned i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; for (i = 0U; i < 2U; i++) { if (verbose != 0) { mbedtls_printf(" ChaCha20 test %u ", i); } ret = mbedtls_chacha20_crypt(test_keys[i], test_nonces[i], test_counters[i], test_lengths[i], test_input[i], output); ASSERT(0 == ret, ("error code: %i\n", ret)); ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]), ("failed (output)\n")); if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* !MBEDTLS_CHACHA20_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/chachapoly.c000066400000000000000000000342501464416617300236170ustar00rootroot00000000000000/** * \file chachapoly.c * * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_CHACHAPOLY_ALT) #define CHACHAPOLY_STATE_INIT (0) #define CHACHAPOLY_STATE_AAD (1) #define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */ #define CHACHAPOLY_STATE_FINISHED (3) /** * \brief Adds nul bytes to pad the AAD for Poly1305. * * \param ctx The ChaCha20-Poly1305 context. */ static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx) { uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U); unsigned char zeroes[15]; if (partial_block_len == 0U) { return 0; } memset(zeroes, 0, sizeof(zeroes)); return mbedtls_poly1305_update(&ctx->poly1305_ctx, zeroes, 16U - partial_block_len); } /** * \brief Adds nul bytes to pad the ciphertext for Poly1305. * * \param ctx The ChaCha20-Poly1305 context. */ static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx) { uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U); unsigned char zeroes[15]; if (partial_block_len == 0U) { return 0; } memset(zeroes, 0, sizeof(zeroes)); return mbedtls_poly1305_update(&ctx->poly1305_ctx, zeroes, 16U - partial_block_len); } void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx) { mbedtls_chacha20_init(&ctx->chacha20_ctx); mbedtls_poly1305_init(&ctx->poly1305_ctx); ctx->aad_len = 0U; ctx->ciphertext_len = 0U; ctx->state = CHACHAPOLY_STATE_INIT; ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; } void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx) { if (ctx == NULL) { return; } mbedtls_chacha20_free(&ctx->chacha20_ctx); mbedtls_poly1305_free(&ctx->poly1305_ctx); ctx->aad_len = 0U; ctx->ciphertext_len = 0U; ctx->state = CHACHAPOLY_STATE_INIT; ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; } int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx, const unsigned char key[32]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key); return ret; } int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx, const unsigned char nonce[12], mbedtls_chachapoly_mode_t mode) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char poly1305_key[64]; /* Set counter = 0, will be update to 1 when generating Poly1305 key */ ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U); if (ret != 0) { goto cleanup; } /* Generate the Poly1305 key by getting the ChaCha20 keystream output with * counter = 0. This is the same as encrypting a buffer of zeroes. * Only the first 256-bits (32 bytes) of the key is used for Poly1305. * The other 256 bits are discarded. */ memset(poly1305_key, 0, sizeof(poly1305_key)); ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key), poly1305_key, poly1305_key); if (ret != 0) { goto cleanup; } ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key); if (ret == 0) { ctx->aad_len = 0U; ctx->ciphertext_len = 0U; ctx->state = CHACHAPOLY_STATE_AAD; ctx->mode = mode; } cleanup: mbedtls_platform_zeroize(poly1305_key, 64U); return ret; } int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx, const unsigned char *aad, size_t aad_len) { if (ctx->state != CHACHAPOLY_STATE_AAD) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } ctx->aad_len += aad_len; return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len); } int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx, size_t len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ctx->state != CHACHAPOLY_STATE_AAD) && (ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } if (ctx->state == CHACHAPOLY_STATE_AAD) { ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; ret = chachapoly_pad_aad(ctx); if (ret != 0) { return ret; } } ctx->ciphertext_len += len; if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) { ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output); if (ret != 0) { return ret; } ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len); if (ret != 0) { return ret; } } else { /* DECRYPT */ ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len); if (ret != 0) { return ret; } ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output); if (ret != 0) { return ret; } } return 0; } int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx, unsigned char mac[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char len_block[16]; if (ctx->state == CHACHAPOLY_STATE_INIT) { return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } if (ctx->state == CHACHAPOLY_STATE_AAD) { ret = chachapoly_pad_aad(ctx); if (ret != 0) { return ret; } } else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) { ret = chachapoly_pad_ciphertext(ctx); if (ret != 0) { return ret; } } ctx->state = CHACHAPOLY_STATE_FINISHED; /* The lengths of the AAD and ciphertext are processed by * Poly1305 as the final 128-bit block, encoded as little-endian integers. */ MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0); MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8); ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U); if (ret != 0) { return ret; } ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac); return ret; } static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx, mbedtls_chachapoly_mode_t mode, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char *input, unsigned char *output, unsigned char tag[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chachapoly_starts(ctx, nonce, mode); if (ret != 0) { goto cleanup; } ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len); if (ret != 0) { goto cleanup; } ret = mbedtls_chachapoly_update(ctx, length, input, output); if (ret != 0) { goto cleanup; } ret = mbedtls_chachapoly_finish(ctx, tag); cleanup: return ret; } int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char *input, unsigned char *output, unsigned char tag[16]) { return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, length, nonce, aad, aad_len, input, output, tag); } int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx, size_t length, const unsigned char nonce[12], const unsigned char *aad, size_t aad_len, const unsigned char tag[16], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; int diff; if ((ret = chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, aad, aad_len, input, output, check_tag)) != 0) { return ret; } /* Check tag in "constant-time" */ diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag)); if (diff != 0) { mbedtls_platform_zeroize(output, length); return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED; } return 0; } #endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_key[1][32] = { { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f } }; static const unsigned char test_nonce[1][12] = { { 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ } }; static const unsigned char test_aad[1][12] = { { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 } }; static const size_t test_aad_len[1] = { 12U }; static const unsigned char test_input[1][114] = { { 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x74, 0x2e } }; static const unsigned char test_output[1][114] = { { 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, 0x61, 0x16 } }; static const size_t test_input_len[1] = { 114U }; static const unsigned char test_mac[1][16] = { { 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 } }; /* Make sure no other definition is already present. */ #undef ASSERT #define ASSERT(cond, args) \ do \ { \ if (!(cond)) \ { \ if (verbose != 0) \ mbedtls_printf args; \ \ return -1; \ } \ } \ while (0) int mbedtls_chachapoly_self_test(int verbose) { mbedtls_chachapoly_context ctx; unsigned i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char output[200]; unsigned char mac[16]; for (i = 0U; i < 1U; i++) { if (verbose != 0) { mbedtls_printf(" ChaCha20-Poly1305 test %u ", i); } mbedtls_chachapoly_init(&ctx); ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]); ASSERT(0 == ret, ("setkey() error code: %i\n", ret)); ret = mbedtls_chachapoly_encrypt_and_tag(&ctx, test_input_len[i], test_nonce[i], test_aad[i], test_aad_len[i], test_input[i], output, mac); ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret)); ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]), ("failure (wrong output)\n")); ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failure (wrong MAC)\n")); mbedtls_chachapoly_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CHACHAPOLY_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/check_crypto_config.h000066400000000000000000000130201464416617300255030ustar00rootroot00000000000000/** * \file check_crypto_config.h * * \brief Consistency checks for PSA configuration options */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * It is recommended to include this file from your crypto_config.h * in order to catch dependency issues early. */ #ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H #define MBEDTLS_CHECK_CRYPTO_CONFIG_H #if defined(PSA_WANT_ALG_CCM) && \ !(defined(PSA_WANT_KEY_TYPE_AES) || \ defined(PSA_WANT_KEY_TYPE_CAMELLIA)) #error "PSA_WANT_ALG_CCM defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_CMAC) && \ !(defined(PSA_WANT_KEY_TYPE_AES) || \ defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \ defined(PSA_WANT_KEY_TYPE_DES)) #error "PSA_WANT_ALG_CMAC defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_ECDSA) && \ !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)) #error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_GCM) && \ !(defined(PSA_WANT_KEY_TYPE_AES) || \ defined(PSA_WANT_KEY_TYPE_CAMELLIA)) #error "PSA_WANT_ALG_GCM defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_OAEP) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_RSA_PSS) && \ !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)) #error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites" #endif #if (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \ defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) && \ !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx defined, but not all prerequisites" #endif #if (defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)) && \ !defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) #error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx defined, but not all prerequisites" #endif #if (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)) && \ !defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) #error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_xxx defined, but not all prerequisites" #endif #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) #if defined(MBEDTLS_DEPRECATED_REMOVED) #error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #elif defined(MBEDTLS_DEPRECATED_WARNING) #warning "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \ future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \ symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE" #endif /* MBEDTLS_DEPRECATED_WARNING */ #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE) #error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE defined, but feature is not supported" #endif #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE) #error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE defined, but feature is not supported" #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ !(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512)) #error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" #endif #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \ !defined(PSA_WANT_ALG_SHA_256) #error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites" #endif #endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/cipher.c000066400000000000000000001664631464416617300227720ustar00rootroot00000000000000/** * \file cipher.c * * \brief Generic cipher wrapper for Mbed TLS * * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #include "cipher_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #include "constant_time_internal.h" #include #include #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #endif #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #endif #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" #endif #include "mbedtls/platform.h" static int supported_init = 0; static inline const mbedtls_cipher_base_t *mbedtls_cipher_get_base( const mbedtls_cipher_info_t *info) { return mbedtls_cipher_base_lookup_table[info->base_idx]; } const int *mbedtls_cipher_list(void) { const mbedtls_cipher_definition_t *def; int *type; if (!supported_init) { def = mbedtls_cipher_definitions; type = mbedtls_cipher_supported; while (def->type != 0) { *type++ = (*def++).type; } *type = 0; supported_init = 1; } return mbedtls_cipher_supported; } const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type) { const mbedtls_cipher_definition_t *def; for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { if (def->type == cipher_type) { return def->info; } } return NULL; } const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name) { const mbedtls_cipher_definition_t *def; if (NULL == cipher_name) { return NULL; } for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { if (!strcmp(def->info->name, cipher_name)) { return def->info; } } return NULL; } const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, int key_bitlen, const mbedtls_cipher_mode_t mode) { const mbedtls_cipher_definition_t *def; for (def = mbedtls_cipher_definitions; def->info != NULL; def++) { if (mbedtls_cipher_get_base(def->info)->cipher == cipher_id && mbedtls_cipher_info_get_key_bitlen(def->info) == (unsigned) key_bitlen && def->info->mode == mode) { return def->info; } } return NULL; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) static inline psa_key_type_t mbedtls_psa_translate_cipher_type( mbedtls_cipher_type_t cipher) { switch (cipher) { case MBEDTLS_CIPHER_AES_128_CCM: case MBEDTLS_CIPHER_AES_192_CCM: case MBEDTLS_CIPHER_AES_256_CCM: case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_AES_128_GCM: case MBEDTLS_CIPHER_AES_192_GCM: case MBEDTLS_CIPHER_AES_256_GCM: case MBEDTLS_CIPHER_AES_128_CBC: case MBEDTLS_CIPHER_AES_192_CBC: case MBEDTLS_CIPHER_AES_256_CBC: case MBEDTLS_CIPHER_AES_128_ECB: case MBEDTLS_CIPHER_AES_192_ECB: case MBEDTLS_CIPHER_AES_256_ECB: return PSA_KEY_TYPE_AES; /* ARIA not yet supported in PSA. */ /* case MBEDTLS_CIPHER_ARIA_128_CCM: case MBEDTLS_CIPHER_ARIA_192_CCM: case MBEDTLS_CIPHER_ARIA_256_CCM: case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG: case MBEDTLS_CIPHER_ARIA_128_GCM: case MBEDTLS_CIPHER_ARIA_192_GCM: case MBEDTLS_CIPHER_ARIA_256_GCM: case MBEDTLS_CIPHER_ARIA_128_CBC: case MBEDTLS_CIPHER_ARIA_192_CBC: case MBEDTLS_CIPHER_ARIA_256_CBC: return( PSA_KEY_TYPE_ARIA ); */ default: return 0; } } static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( mbedtls_cipher_mode_t mode, size_t taglen) { switch (mode) { case MBEDTLS_MODE_ECB: return PSA_ALG_ECB_NO_PADDING; case MBEDTLS_MODE_GCM: return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen); case MBEDTLS_MODE_CCM: return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen); case MBEDTLS_MODE_CCM_STAR_NO_TAG: return PSA_ALG_CCM_STAR_NO_TAG; case MBEDTLS_MODE_CBC: if (taglen == 0) { return PSA_ALG_CBC_NO_PADDING; } else { return 0; } default: return 0; } } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx) { memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); } void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { if (ctx->cipher_ctx != NULL) { mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; if (cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED) { /* xxx_free() doesn't allow to return failures. */ (void) psa_destroy_key(cipher_psa->slot); } mbedtls_zeroize_and_free(cipher_psa, sizeof(*cipher_psa)); } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); return; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_CMAC_C) if (ctx->cmac_ctx) { mbedtls_zeroize_and_free(ctx->cmac_ctx, sizeof(mbedtls_cmac_context_t)); } #endif if (ctx->cipher_ctx) { mbedtls_cipher_get_base(ctx->cipher_info)->ctx_free_func(ctx->cipher_ctx); } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t)); } int mbedtls_cipher_clone(mbedtls_cipher_context_t *dst, const mbedtls_cipher_context_t *src) { if (dst == NULL || dst->cipher_info == NULL || src == NULL || src->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } dst->cipher_info = src->cipher_info; dst->key_bitlen = src->key_bitlen; dst->operation = src->operation; #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) dst->add_padding = src->add_padding; dst->get_padding = src->get_padding; #endif memcpy(dst->unprocessed_data, src->unprocessed_data, MBEDTLS_MAX_BLOCK_LENGTH); dst->unprocessed_len = src->unprocessed_len; memcpy(dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH); dst->iv_size = src->iv_size; if (mbedtls_cipher_get_base(dst->cipher_info)->ctx_clone_func) mbedtls_cipher_get_base(dst->cipher_info)->ctx_clone_func(dst->cipher_ctx, src->cipher_ctx); #if defined(MBEDTLS_CMAC_C) if (dst->cmac_ctx != NULL && src->cmac_ctx != NULL) memcpy(dst->cmac_ctx, src->cmac_ctx, sizeof(mbedtls_cmac_context_t)); #endif return 0; } int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info) { if (cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); if (mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func != NULL) { ctx->cipher_ctx = mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func(); if (ctx->cipher_ctx == NULL) { return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } } ctx->cipher_info = cipher_info; return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, size_t taglen) { psa_algorithm_t alg; mbedtls_cipher_context_psa *cipher_psa; if (NULL == cipher_info || NULL == ctx) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* Check that the underlying cipher mode and cipher type are * supported by the underlying PSA Crypto implementation. */ alg = mbedtls_psa_translate_cipher_mode(((mbedtls_cipher_mode_t) cipher_info->mode), taglen); if (alg == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } if (mbedtls_psa_translate_cipher_type(((mbedtls_cipher_type_t) cipher_info->type)) == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } memset(ctx, 0, sizeof(mbedtls_cipher_context_t)); cipher_psa = mbedtls_calloc(1, sizeof(mbedtls_cipher_context_psa)); if (cipher_psa == NULL) { return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; } cipher_psa->alg = alg; ctx->cipher_ctx = cipher_psa; ctx->cipher_info = cipher_info; ctx->psa_enabled = 1; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) { if (NULL == cipher_info || NULL == ctx) return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; ctx->cipher_info = cipher_info; return 0; } int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, int key_bitlen, const mbedtls_operation_t operation) { if (operation != MBEDTLS_ENCRYPT && operation != MBEDTLS_DECRYPT) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) && MBEDTLS_DECRYPT == operation) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; size_t const key_bytelen = ((size_t) key_bitlen + 7) / 8; psa_status_t status; psa_key_type_t key_type; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; /* PSA Crypto API only accepts byte-aligned keys. */ if (key_bitlen % 8 != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* Don't allow keys to be set multiple times. */ if (cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } key_type = mbedtls_psa_translate_cipher_type( ((mbedtls_cipher_type_t) ctx->cipher_info->type)); if (key_type == 0) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } psa_set_key_type(&attributes, key_type); /* Mbed TLS' cipher layer doesn't enforce the mode of operation * (encrypt vs. decrypt): it is possible to setup a key for encryption * and use it for AEAD decryption. Until tests relying on this * are changed, allow any usage in PSA. */ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, cipher_psa->alg); status = psa_import_key(&attributes, key, key_bytelen, &cipher_psa->slot); switch (status) { case PSA_SUCCESS: break; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; default: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } /* Indicate that we own the key slot and need to * destroy it in mbedtls_cipher_free(). */ cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; ctx->key_bitlen = key_bitlen; ctx->operation = operation; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 && (int) mbedtls_cipher_info_get_key_bitlen(ctx->cipher_info) != key_bitlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ctx->key_bitlen = key_bitlen; ctx->operation = operation; #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /* * For OFB, CFB and CTR mode always use the encryption key schedule */ if (MBEDTLS_ENCRYPT == operation || MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key, ctx->key_bitlen); } if (MBEDTLS_DECRYPT == operation) { return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_dec_func(ctx->cipher_ctx, key, ctx->key_bitlen); } #else if (operation == MBEDTLS_ENCRYPT || operation == MBEDTLS_DECRYPT) { return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key, ctx->key_bitlen); } #endif return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len) { size_t actual_iv_size; if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ /* avoid buffer overflow in ctx->iv */ if (iv_len > MBEDTLS_MAX_IV_LENGTH) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) { actual_iv_size = iv_len; } else { actual_iv_size = mbedtls_cipher_info_get_iv_size(ctx->cipher_info); /* avoid reading past the end of input buffer */ if (actual_iv_size > iv_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } #if defined(MBEDTLS_CHACHA20_C) if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20) { /* Even though the actual_iv_size is overwritten with a correct value * of 12 from the cipher info, return an error to indicate that * the input iv_len is wrong. */ if (iv_len != 12) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != mbedtls_chacha20_starts((mbedtls_chacha20_context *) ctx->cipher_ctx, iv, 0U)) { /* Initial counter value */ return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } #if defined(MBEDTLS_CHACHAPOLY_C) if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305 && iv_len != 12) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #endif #endif #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, iv, iv_len); } #endif #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int set_lengths_result; int ccm_star_mode; set_lengths_result = mbedtls_ccm_set_lengths( (mbedtls_ccm_context *) ctx->cipher_ctx, 0, 0, 0); if (set_lengths_result != 0) { return set_lengths_result; } if (ctx->operation == MBEDTLS_DECRYPT) { ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT; } else if (ctx->operation == MBEDTLS_ENCRYPT) { ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT; } else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_ccm_starts((mbedtls_ccm_context *) ctx->cipher_ctx, ccm_star_mode, iv, iv_len); } #endif if (actual_iv_size != 0) { memcpy(ctx->iv, iv, actual_iv_size); ctx->iv_size = actual_iv_size; } return 0; } int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* We don't support resetting PSA-based * cipher contexts, yet. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ ctx->unprocessed_len = 0; return 0; } #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, const unsigned char *ad, size_t ad_len) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx, ad, ad_len); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { int result; mbedtls_chachapoly_mode_t mode; mode = (ctx->operation == MBEDTLS_ENCRYPT) ? MBEDTLS_CHACHAPOLY_ENCRYPT : MBEDTLS_CHACHAPOLY_DECRYPT; result = mbedtls_chachapoly_starts((mbedtls_chachapoly_context *) ctx->cipher_ctx, ctx->iv, mode); if (result != 0) { return result; } return mbedtls_chachapoly_update_aad((mbedtls_chachapoly_context *) ctx->cipher_ctx, ad, ad_len); } #endif return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t block_size; if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ *olen = 0; block_size = mbedtls_cipher_get_block_size(ctx); if (0 == block_size) { return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; } if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_ECB) { if (ilen != block_size) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } *olen = ilen; if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ecb_func(ctx->cipher_ctx, ctx->operation, input, output))) { return ret; } return 0; } #if defined(MBEDTLS_GCM_C) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_GCM) { return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx, input, ilen, output, ilen, olen); } #endif #if defined(MBEDTLS_CCM_C) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CCM_STAR_NO_TAG) { return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx, input, ilen, output, ilen, olen); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305) { *olen = ilen; return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx, ilen, input, output); } #endif if (input == output && (ctx->unprocessed_len != 0 || ilen % block_size)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_CIPHER_MODE_CBC) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CBC) { size_t copy_len = 0; /* * If there is not enough data for a full block, cache it. */ if ((ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && ilen <= block_size - ctx->unprocessed_len) || (ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && ilen < block_size - ctx->unprocessed_len) || (ctx->operation == MBEDTLS_ENCRYPT && ilen < block_size - ctx->unprocessed_len)) { memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, ilen); ctx->unprocessed_len += ilen; return 0; } /* * Process cached data first */ if (0 != ctx->unprocessed_len) { copy_len = block_size - ctx->unprocessed_len; memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, copy_len); if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, ctx->operation, block_size, ctx->iv, ctx-> unprocessed_data, output))) { return ret; } *olen += block_size; output += block_size; ctx->unprocessed_len = 0; input += copy_len; ilen -= copy_len; } /* * Cache final, incomplete block */ if (0 != ilen) { /* Encryption: only cache partial blocks * Decryption w/ padding: always keep at least one whole block * Decryption w/o padding: only cache partial blocks */ copy_len = ilen % block_size; if (copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding) { copy_len = block_size; } memcpy(ctx->unprocessed_data, &(input[ilen - copy_len]), copy_len); ctx->unprocessed_len += copy_len; ilen -= copy_len; } /* * Process remaining full blocks */ if (ilen) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output))) { return ret; } *olen += ilen; } return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CFB) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cfb_func(ctx->cipher_ctx, ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_OFB) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ofb_func(ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CTR) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ctr_func(ctx->cipher_ctx, ilen, &ctx->unprocessed_len, ctx->iv, ctx->unprocessed_data, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_XTS) { if (ctx->unprocessed_len > 0) { /* We can only process an entire data unit at a time. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } ret = mbedtls_cipher_get_base(ctx->cipher_info)->xts_func(ctx->cipher_ctx, ctx->operation, ilen, ctx->iv, input, output); if (ret != 0) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_MODE_STREAM) if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_STREAM) { if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->stream_func(ctx->cipher_ctx, ilen, input, output))) { return ret; } *olen = ilen; return 0; } #endif /* MBEDTLS_CIPHER_MODE_STREAM */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) /* * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len */ static void add_pkcs_padding(unsigned char *output, size_t output_len, size_t data_len) { size_t padding_len = output_len - data_len; unsigned char i; for (i = 0; i < padding_len; i++) { output[data_len + i] = (unsigned char) padding_len; } } static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; unsigned char padding_len; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } padding_len = input[input_len - 1]; *data_len = input_len - padding_len; mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len); bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0)); /* The number of bytes checked must be independent of padding_len, * so pick input_len, which is usually 8 or 16 (one block) */ pad_idx = input_len - padding_len; for (i = 0; i < input_len; i++) { mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx); mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len); bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) /* * One and zeros padding: fill with 80 00 ... 00 */ static void add_one_and_zeros_padding(unsigned char *output, size_t output_len, size_t data_len) { size_t padding_len = output_len - data_len; unsigned char i = 0; output[data_len] = 0x80; for (i = 1; i < padding_len; i++) { output[data_len + i] = 0x00; } } static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE; mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE; *data_len = 0; for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) { mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]); mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding); *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len); bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad); in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) /* * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length */ static void add_zeros_and_len_padding(unsigned char *output, size_t output_len, size_t data_len) { size_t padding_len = output_len - data_len; unsigned char i = 0; for (i = 1; i < padding_len; i++) { output[data_len + i - 1] = 0x00; } output[output_len - 1] = (unsigned char) padding_len; } static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; unsigned char padding_len; mbedtls_ct_condition_t bad; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } padding_len = input[input_len - 1]; *data_len = input_len - padding_len; /* Avoid logical || since it results in a branch */ bad = mbedtls_ct_uint_gt(padding_len, input_len); bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0)); /* The number of bytes checked must be independent of padding_len */ pad_idx = input_len - padding_len; for (i = 0; i < input_len - 1; i++) { mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx); mbedtls_ct_condition_t nonzero_pad_byte; nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i])); bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) /* * Zero padding: fill with 00 ... 00 */ static void add_zeros_padding(unsigned char *output, size_t output_len, size_t data_len) { memset(output + data_len, 0, output_len - data_len); } static int get_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i; mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *data_len = 0; for (i = input_len; i > 0; i--) { prev_done = done; done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0)); *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len); } return 0; } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ /* * No padding: don't pad :) * * There is no add_padding function (check for NULL in mbedtls_cipher_finish) * but a trivial get_padding function */ static int get_no_padding(unsigned char *input, size_t input_len, size_t *data_len) { if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *data_len = input_len; return 0; } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ *olen = 0; #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) /* CBC mode requires padding so we make sure a call to * mbedtls_cipher_set_padding_mode has been done successfully. */ if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { if (ctx->get_padding == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } } #endif if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_XTS == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_STREAM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return 0; } if ((MBEDTLS_CIPHER_CHACHA20 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) || (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type))) { return 0; } if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { if (ctx->unprocessed_len != 0) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } return 0; } #if defined(MBEDTLS_CIPHER_MODE_CBC) if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = 0; if (MBEDTLS_ENCRYPT == ctx->operation) { /* check for 'no padding' mode */ if (NULL == ctx->add_padding) { if (0 != ctx->unprocessed_len) { return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } return 0; } ctx->add_padding(ctx->unprocessed_data, mbedtls_cipher_get_iv_size(ctx), ctx->unprocessed_len); } else if (mbedtls_cipher_get_block_size(ctx) != ctx->unprocessed_len) { /* * For decrypt operations, expect a full block, * or an empty block if no padding */ if (NULL == ctx->add_padding && 0 == ctx->unprocessed_len) { return 0; } return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED; } /* cipher block */ if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx, ctx->operation, mbedtls_cipher_get_block_size( ctx), ctx->iv, ctx->unprocessed_data, output))) { return ret; } /* Set output size for decryption */ if (MBEDTLS_DECRYPT == ctx->operation) { return ctx->get_padding(output, mbedtls_cipher_get_block_size(ctx), olen); } /* Set output size for encryption */ *olen = mbedtls_cipher_get_block_size(ctx); return 0; } #else ((void) output); #endif /* MBEDTLS_CIPHER_MODE_CBC */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode) { if (NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto knows about CBC padding * schemes, we currently don't make them * accessible through the cipher layer. */ if (mode != MBEDTLS_PADDING_NONE) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ switch (mode) { #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) case MBEDTLS_PADDING_PKCS7: ctx->add_padding = add_pkcs_padding; ctx->get_padding = get_pkcs_padding; break; #endif #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) case MBEDTLS_PADDING_ONE_AND_ZEROS: ctx->add_padding = add_one_and_zeros_padding; ctx->get_padding = get_one_and_zeros_padding; break; #endif #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) case MBEDTLS_PADDING_ZEROS_AND_LEN: ctx->add_padding = add_zeros_and_len_padding; ctx->get_padding = get_zeros_and_len_padding; break; #endif #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) case MBEDTLS_PADDING_ZEROS: ctx->add_padding = add_zeros_padding; ctx->get_padding = get_zeros_padding; break; #endif case MBEDTLS_PADDING_NONE: ctx->add_padding = NULL; ctx->get_padding = get_no_padding; break; default: return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } return 0; } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, unsigned char *tag, size_t tag_len) { if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (MBEDTLS_ENCRYPT != ctx->operation) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { size_t output_length; /* The code here doesn't yet support alternative implementations * that can delay up to a block of output. */ return mbedtls_gcm_finish((mbedtls_gcm_context *) ctx->cipher_ctx, NULL, 0, &output_length, tag, tag_len); } #endif #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* Don't allow truncated MAC for Poly1305 */ if (tag_len != 16U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context *) ctx->cipher_ctx, tag); } #endif return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, const unsigned char *tag, size_t tag_len) { unsigned char check_tag[16]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ctx->cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (MBEDTLS_DECRYPT != ctx->operation) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* While PSA Crypto has an API for multipart * operations, we currently don't make it * accessible through the cipher layer. */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ /* Status to return on a non-authenticated algorithm. */ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { size_t output_length; /* The code here doesn't yet support alternative implementations * that can delay up to a block of output. */ if (tag_len > sizeof(check_tag)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != (ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, NULL, 0, &output_length, check_tag, tag_len))) { return ret; } /* Check the tag in "constant-time" */ if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto exit; } } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* Don't allow truncated MAC for Poly1305 */ if (tag_len != sizeof(check_tag)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context *) ctx->cipher_ctx, check_tag); if (ret != 0) { return ret; } /* Check the tag in "constant-time" */ if (mbedtls_ct_memcmp(tag, check_tag, tag_len) != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto exit; } } #endif /* MBEDTLS_CHACHAPOLY_C */ exit: mbedtls_platform_zeroize(check_tag, tag_len); return ret; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ /* * Packet-oriented wrapper for non-AEAD modes */ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t finish_olen; #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will * still be in its default state of 0, which is * guaranteed to be invalid, hence the PSA-call * below will gracefully fail. */ mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; psa_status_t status; psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; size_t part_len; if (ctx->operation == MBEDTLS_DECRYPT) { status = psa_cipher_decrypt_setup(&cipher_op, cipher_psa->slot, cipher_psa->alg); } else if (ctx->operation == MBEDTLS_ENCRYPT) { status = psa_cipher_encrypt_setup(&cipher_op, cipher_psa->slot, cipher_psa->alg); } else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* In the following, we can immediately return on an error, * because the PSA Crypto API guarantees that cipher operations * are terminated by unsuccessful calls to psa_cipher_update(), * and by any call to psa_cipher_finish(). */ if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) != MBEDTLS_MODE_ECB) { status = psa_cipher_set_iv(&cipher_op, iv, iv_len); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } status = psa_cipher_update(&cipher_op, input, ilen, output, ilen, olen); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } status = psa_cipher_finish(&cipher_op, output + *olen, ilen - *olen, &part_len); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } *olen += part_len; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) { return ret; } if ((ret = mbedtls_cipher_reset(ctx)) != 0) { return ret; } if ((ret = mbedtls_cipher_update(ctx, input, ilen, output, olen)) != 0) { return ret; } if ((ret = mbedtls_cipher_finish(ctx, output + *olen, &finish_olen)) != 0) { return ret; } *olen += finish_olen; return 0; } #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* * Packet-oriented encryption for AEAD modes: internal function used by * mbedtls_cipher_auth_encrypt_ext(). */ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, unsigned char *tag, size_t tag_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will * still be in its default state of 0, which is * guaranteed to be invalid, hence the PSA-call * below will gracefully fail. */ mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; psa_status_t status; /* PSA Crypto API always writes the authentication tag * at the end of the encrypted message. */ if (output == NULL || tag != output + ilen) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } status = psa_aead_encrypt(cipher_psa->slot, cipher_psa->alg, iv, iv_len, ad, ad_len, input, ilen, output, ilen + tag_len, olen); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } *olen -= tag_len; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { *olen = ilen; return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, iv, iv_len, ad, ad_len, input, output, tag_len, tag); } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { *olen = ilen; return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, tag, tag_len); } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { /* ChachaPoly has fixed length nonce and MAC (tag) */ if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) || (tag_len != 16U)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *olen = ilen; return mbedtls_chachapoly_encrypt_and_tag(ctx->cipher_ctx, ilen, iv, ad, ad_len, input, output, tag); } #endif /* MBEDTLS_CHACHAPOLY_C */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } /* * Packet-oriented encryption for AEAD modes: internal function used by * mbedtls_cipher_auth_encrypt_ext(). */ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, const unsigned char *tag, size_t tag_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) if (ctx->psa_enabled == 1) { /* As in the non-PSA case, we don't check that * a key has been set. If not, the key slot will * still be in its default state of 0, which is * guaranteed to be invalid, hence the PSA-call * below will gracefully fail. */ mbedtls_cipher_context_psa * const cipher_psa = (mbedtls_cipher_context_psa *) ctx->cipher_ctx; psa_status_t status; /* PSA Crypto API always writes the authentication tag * at the end of the encrypted message. */ if (input == NULL || tag != input + ilen) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } status = psa_aead_decrypt(cipher_psa->slot, cipher_psa->alg, iv, iv_len, ad, ad_len, input, ilen + tag_len, output, ilen, olen); if (status == PSA_ERROR_INVALID_SIGNATURE) { return MBEDTLS_ERR_CIPHER_AUTH_FAILED; } else if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_GCM_C) if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; ret = mbedtls_gcm_auth_decrypt(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, tag, tag_len, input, output); if (ret == MBEDTLS_ERR_GCM_AUTH_FAILED) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } return ret; } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *olen = ilen; ret = mbedtls_ccm_auth_decrypt(ctx->cipher_ctx, ilen, iv, iv_len, ad, ad_len, input, output, tag, tag_len); if (ret == MBEDTLS_ERR_CCM_AUTH_FAILED) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } return ret; } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHAPOLY_C) if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* ChachaPoly has fixed length nonce and MAC (tag) */ if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) || (tag_len != 16U)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } *olen = ilen; ret = mbedtls_chachapoly_auth_decrypt(ctx->cipher_ctx, ilen, iv, ad, ad_len, tag, input, output); if (ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } return ret; } #endif /* MBEDTLS_CHACHAPOLY_C */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_CIPHER_MODE_AEAD */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) /* * Packet-oriented encryption for AEAD/NIST_KW: public function. */ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len) { #if defined(MBEDTLS_NIST_KW_C) if ( #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) ctx->psa_enabled == 0 && #endif (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) { mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ? MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; /* There is no iv, tag or ad associated with KW and KWP, * so these length should be 0 as documented. */ if (iv_len != 0 || tag_len != 0 || ad_len != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } (void) iv; (void) ad; return mbedtls_nist_kw_wrap(ctx->cipher_ctx, mode, input, ilen, output, olen, output_len); } #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* AEAD case: check length before passing on to shared function */ if (output_len < ilen + tag_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } int ret = mbedtls_cipher_aead_encrypt(ctx, iv, iv_len, ad, ad_len, input, ilen, output, olen, output + ilen, tag_len); *olen += tag_len; return ret; #else return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_CIPHER_MODE_AEAD */ } /* * Packet-oriented decryption for AEAD/NIST_KW: public function. */ int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx, const unsigned char *iv, size_t iv_len, const unsigned char *ad, size_t ad_len, const unsigned char *input, size_t ilen, unsigned char *output, size_t output_len, size_t *olen, size_t tag_len) { #if defined(MBEDTLS_NIST_KW_C) if ( #if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED) ctx->psa_enabled == 0 && #endif (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) || MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) { mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ? MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; /* There is no iv, tag or ad associated with KW and KWP, * so these length should be 0 as documented. */ if (iv_len != 0 || tag_len != 0 || ad_len != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } (void) iv; (void) ad; return mbedtls_nist_kw_unwrap(ctx->cipher_ctx, mode, input, ilen, output, olen, output_len); } #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_CIPHER_MODE_AEAD) /* AEAD case: check length before passing on to shared function */ if (ilen < tag_len || output_len < ilen - tag_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_cipher_aead_decrypt(ctx, iv, iv_len, ad, ad_len, input, ilen - tag_len, output, olen, input + ilen - tag_len, tag_len); #else return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_CIPHER_MODE_AEAD */ } #endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ #endif /* MBEDTLS_CIPHER_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/cipher_wrap.c000066400000000000000000002066761464416617300240240ustar00rootroot00000000000000/** * \file cipher_wrap.c * * \brief Generic cipher wrapper for Mbed TLS * * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include #if defined(MBEDTLS_CIPHER_C) #include "cipher_wrap.h" #include "mbedtls/error.h" #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #endif #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #endif #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #include #endif #include "mbedtls/platform.h" enum mbedtls_cipher_base_index { #if defined(MBEDTLS_AES_C) MBEDTLS_CIPHER_BASE_INDEX_AES, #endif #if defined(MBEDTLS_ARIA_C) MBEDTLS_CIPHER_BASE_INDEX_ARIA, #endif #if defined(MBEDTLS_CAMELLIA_C) MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA, #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) MBEDTLS_CIPHER_BASE_INDEX_CCM_AES, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C) MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C) MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA, #endif #if defined(MBEDTLS_CHACHA20_C) MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE, #endif #if defined(MBEDTLS_CHACHAPOLY_C) MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE, #endif #if defined(MBEDTLS_DES_C) MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3, #endif #if defined(MBEDTLS_DES_C) MBEDTLS_CIPHER_BASE_INDEX_DES_EDE, #endif #if defined(MBEDTLS_DES_C) MBEDTLS_CIPHER_BASE_INDEX_DES, #endif #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) MBEDTLS_CIPHER_BASE_INDEX_GCM_AES, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C) MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C) MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA, #endif #if defined(MBEDTLS_NIST_KW_C) MBEDTLS_CIPHER_BASE_INDEX_KW_AES, #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C) MBEDTLS_CIPHER_BASE_INDEX_XTS_AES, #endif /* Prevent compile failure due to empty enum */ MBEDTLS_CIPHER_BASE_PREVENT_EMPTY_ENUM }; #if defined(MBEDTLS_GCM_C) && \ (defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) /* shared by all GCM ciphers */ static void *gcm_ctx_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_gcm_context)); if (ctx != NULL) { mbedtls_gcm_init((mbedtls_gcm_context *) ctx); } return ctx; } static void gcm_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_gcm_context)); } static void gcm_ctx_free(void *ctx) { mbedtls_gcm_free(ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) && \ (defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) /* shared by all CCM ciphers */ static void *ccm_ctx_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ccm_context)); if (ctx != NULL) { mbedtls_ccm_init((mbedtls_ccm_context *) ctx); } return ctx; } static void ccm_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_ccm_context)); } static void ccm_ctx_free(void *ctx) { mbedtls_ccm_free(ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_AES_C) static int aes_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_ecb((mbedtls_aes_context *) ctx, operation, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int aes_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_cbc((mbedtls_aes_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int aes_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_cfb128((mbedtls_aes_context *) ctx, operation, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) static int aes_crypt_ofb_wrap(void *ctx, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_ofb((mbedtls_aes_context *) ctx, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aes_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output) { return mbedtls_aes_crypt_ctr((mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int aes_crypt_xts_wrap(void *ctx, mbedtls_operation_t operation, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output) { mbedtls_aes_xts_context *xts_ctx = ctx; int mode; switch (operation) { case MBEDTLS_ENCRYPT: mode = MBEDTLS_AES_ENCRYPT; break; case MBEDTLS_DECRYPT: mode = MBEDTLS_AES_DECRYPT; break; default: return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return mbedtls_aes_crypt_xts(xts_ctx, mode, length, data_unit, input, output); } #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int aes_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aes_setkey_dec((mbedtls_aes_context *) ctx, key, key_bitlen); } #endif static int aes_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aes_setkey_enc((mbedtls_aes_context *) ctx, key, key_bitlen); } static void *aes_ctx_alloc(void) { mbedtls_aes_context *aes = mbedtls_calloc(1, sizeof(mbedtls_aes_context)); if (aes == NULL) { return NULL; } mbedtls_aes_init(aes); return aes; } static void aes_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_aes_context)); } static void aes_ctx_free(void *ctx) { mbedtls_aes_free((mbedtls_aes_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t aes_info = { MBEDTLS_CIPHER_ID_AES, aes_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) aes_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) aes_crypt_cfb128_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) aes_crypt_ofb_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aes_crypt_ctr_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif aes_setkey_enc_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) aes_setkey_dec_wrap, #endif aes_ctx_alloc, aes_ctx_clone, aes_ctx_free }; static const mbedtls_cipher_info_t aes_128_ecb_info = { "AES-128-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_AES_128_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ecb_info = { "AES-192-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_AES_192_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ecb_info = { "AES-256-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_AES_256_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t aes_128_cbc_info = { "AES-128-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_AES_128_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_cbc_info = { "AES-192-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_AES_192_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_cbc_info = { "AES-256-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_AES_256_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t aes_128_cfb128_info = { "AES-128-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_AES_128_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_cfb128_info = { "AES-192-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_AES_192_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_cfb128_info = { "AES-256-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_AES_256_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_OFB) static const mbedtls_cipher_info_t aes_128_ofb_info = { "AES-128-OFB", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_OFB, MBEDTLS_CIPHER_AES_128_OFB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ofb_info = { "AES-192-OFB", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_OFB, MBEDTLS_CIPHER_AES_192_OFB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ofb_info = { "AES-256-OFB", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_OFB, MBEDTLS_CIPHER_AES_256_OFB, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aes_128_ctr_info = { "AES-128-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_AES_128_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ctr_info = { "AES-192-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_AES_192_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; static const mbedtls_cipher_info_t aes_256_ctr_info = { "AES-256-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_AES_256_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_XTS) static int xts_aes_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { mbedtls_aes_xts_context *xts_ctx = ctx; return mbedtls_aes_xts_setkey_enc(xts_ctx, key, key_bitlen); } static int xts_aes_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { mbedtls_aes_xts_context *xts_ctx = ctx; return mbedtls_aes_xts_setkey_dec(xts_ctx, key, key_bitlen); } static void *xts_aes_ctx_alloc(void) { mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc(1, sizeof(*xts_ctx)); if (xts_ctx != NULL) { mbedtls_aes_xts_init(xts_ctx); } return xts_ctx; } static void xts_aes_ctx_free(void *ctx) { mbedtls_aes_xts_context *xts_ctx = ctx; if (xts_ctx == NULL) { return; } mbedtls_aes_xts_free(xts_ctx); mbedtls_free(xts_ctx); } static const mbedtls_cipher_base_t xts_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) aes_crypt_xts_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif xts_aes_setkey_enc_wrap, xts_aes_setkey_dec_wrap, xts_aes_ctx_alloc, xts_aes_ctx_free }; static const mbedtls_cipher_info_t aes_128_xts_info = { "AES-128-XTS", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_XTS, MBEDTLS_CIPHER_AES_128_XTS, 0, MBEDTLS_CIPHER_BASE_INDEX_XTS_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_256_xts_info = { "AES-256-XTS", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 512 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_XTS, MBEDTLS_CIPHER_AES_256_XTS, 0, MBEDTLS_CIPHER_BASE_INDEX_XTS_AES }; #endif #endif /* MBEDTLS_CIPHER_MODE_XTS */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES) static int gcm_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen); } #endif /* MBEDTLS_GCM_C && MBEDTLS_CCM_GCM_CAN_AES */ #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_base_t gcm_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif #if defined(MBEDTLS_GCM_C) gcm_aes_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_aes_setkey_wrap, #endif gcm_ctx_alloc, gcm_ctx_clone, gcm_ctx_free, #else NULL, NULL, NULL, NULL, #endif /* MBEDTLS_GCM_C */ }; #endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_gcm_info = { "AES-128-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_gcm_info = { "AES-192-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_AES_192_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; static const mbedtls_cipher_info_t aes_256_gcm_info = { "AES-256-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_AES }; #endif #endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES) static int ccm_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen); } #endif /* MBEDTLS_CCM_C && MBEDTLS_CCM_GCM_CAN_AES */ #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_base_t ccm_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif #if defined(MBEDTLS_CCM_C) ccm_aes_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_aes_setkey_wrap, #endif ccm_ctx_alloc, ccm_ctx_clone, ccm_ctx_free, #else NULL, NULL, NULL, NULL, #endif }; #endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_ccm_info = { "AES-128-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ccm_info = { "AES-192-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_AES_192_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; static const mbedtls_cipher_info_t aes_256_ccm_info = { "AES-256-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #endif #endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA) static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = { "AES-128-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = { "AES-192-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = { "AES-256-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_AES }; #endif #endif /* MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA */ #if defined(MBEDTLS_CAMELLIA_C) static int camellia_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_ecb((mbedtls_camellia_context *) ctx, operation, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int camellia_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_cbc((mbedtls_camellia_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int camellia_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_cfb128((mbedtls_camellia_context *) ctx, operation, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static int camellia_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output) { return mbedtls_camellia_crypt_ctr((mbedtls_camellia_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int camellia_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_camellia_setkey_dec((mbedtls_camellia_context *) ctx, key, key_bitlen); } #endif static int camellia_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_camellia_setkey_enc((mbedtls_camellia_context *) ctx, key, key_bitlen); } static void *camellia_ctx_alloc(void) { mbedtls_camellia_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_camellia_context)); if (ctx == NULL) { return NULL; } mbedtls_camellia_init(ctx); return ctx; } static void camellia_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_camellia_context)); } static void camellia_ctx_free(void *ctx) { mbedtls_camellia_free((mbedtls_camellia_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t camellia_info = { MBEDTLS_CIPHER_ID_CAMELLIA, camellia_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) camellia_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) camellia_crypt_cfb128_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) camellia_crypt_ctr_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif camellia_setkey_enc_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) camellia_setkey_dec_wrap, #endif camellia_ctx_alloc, camellia_ctx_clone, camellia_ctx_free }; static const mbedtls_cipher_info_t camellia_128_ecb_info = { "CAMELLIA-128-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_CAMELLIA_128_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ecb_info = { "CAMELLIA-192-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_CAMELLIA_192_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ecb_info = { "CAMELLIA-256-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_CAMELLIA_256_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t camellia_128_cbc_info = { "CAMELLIA-128-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_CAMELLIA_128_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_cbc_info = { "CAMELLIA-192-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_CAMELLIA_192_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_cbc_info = { "CAMELLIA-256-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_CAMELLIA_256_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t camellia_128_cfb128_info = { "CAMELLIA-128-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_CAMELLIA_128_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_cfb128_info = { "CAMELLIA-192-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_CAMELLIA_192_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_cfb128_info = { "CAMELLIA-256-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_CAMELLIA_256_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t camellia_128_ctr_info = { "CAMELLIA-128-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_CAMELLIA_128_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ctr_info = { "CAMELLIA-192-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_CAMELLIA_192_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ctr_info = { "CAMELLIA-256-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_CAMELLIA_256_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_GCM_C) static int gcm_camellia_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, key_bitlen); } static const mbedtls_cipher_base_t gcm_camellia_info = { MBEDTLS_CIPHER_ID_CAMELLIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif gcm_camellia_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_camellia_setkey_wrap, #endif gcm_ctx_alloc, gcm_ctx_clone, gcm_ctx_free, }; static const mbedtls_cipher_info_t camellia_128_gcm_info = { "CAMELLIA-128-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_gcm_info = { "CAMELLIA-192-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_CAMELLIA_192_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_gcm_info = { "CAMELLIA-256-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA }; #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) static int ccm_camellia_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, key, key_bitlen); } static const mbedtls_cipher_base_t ccm_camellia_info = { MBEDTLS_CIPHER_ID_CAMELLIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif ccm_camellia_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_camellia_setkey_wrap, #endif ccm_ctx_alloc, ccm_ctx_clone, ccm_ctx_free, }; static const mbedtls_cipher_info_t camellia_128_ccm_info = { "CAMELLIA-128-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_CAMELLIA_128_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ccm_info = { "CAMELLIA-192-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_CAMELLIA_192_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ccm_info = { "CAMELLIA-256-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_CAMELLIA_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = { "CAMELLIA-128-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = { "CAMELLIA-192-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = { "CAMELLIA-256-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA }; #endif /* MBEDTLS_CCM_C */ #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) static int aria_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { (void) operation; return mbedtls_aria_crypt_ecb((mbedtls_aria_context *) ctx, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int aria_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aria_crypt_cbc((mbedtls_aria_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static int aria_crypt_cfb128_wrap(void *ctx, mbedtls_operation_t operation, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_aria_crypt_cfb128((mbedtls_aria_context *) ctx, operation, length, iv_off, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static int aria_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output) { return mbedtls_aria_crypt_ctr((mbedtls_aria_context *) ctx, length, nc_off, nonce_counter, stream_block, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) static int aria_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aria_setkey_dec((mbedtls_aria_context *) ctx, key, key_bitlen); } #endif static int aria_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_aria_setkey_enc((mbedtls_aria_context *) ctx, key, key_bitlen); } static void *aria_ctx_alloc(void) { mbedtls_aria_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_aria_context)); if (ctx == NULL) { return NULL; } mbedtls_aria_init(ctx); return ctx; } static void aria_ctx_free(void *ctx) { mbedtls_aria_free((mbedtls_aria_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t aria_info = { MBEDTLS_CIPHER_ID_ARIA, aria_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) aria_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) aria_crypt_cfb128_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) aria_crypt_ctr_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif aria_setkey_enc_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) aria_setkey_dec_wrap, #endif aria_ctx_alloc, aria_ctx_free }; static const mbedtls_cipher_info_t aria_128_ecb_info = { "ARIA-128-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_ARIA_128_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_ecb_info = { "ARIA-192-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_ARIA_192_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_ecb_info = { "ARIA-256-ECB", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_ARIA_256_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t aria_128_cbc_info = { "ARIA-128-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_ARIA_128_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_cbc_info = { "ARIA-192-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_ARIA_192_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_cbc_info = { "ARIA-256-CBC", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_ARIA_256_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) static const mbedtls_cipher_info_t aria_128_cfb128_info = { "ARIA-128-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_ARIA_128_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_cfb128_info = { "ARIA-192-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_ARIA_192_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_cfb128_info = { "ARIA-256-CFB128", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CFB, MBEDTLS_CIPHER_ARIA_256_CFB128, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) static const mbedtls_cipher_info_t aria_128_ctr_info = { "ARIA-128-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_ARIA_128_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_192_ctr_info = { "ARIA-192-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_ARIA_192_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; static const mbedtls_cipher_info_t aria_256_ctr_info = { "ARIA-256-CTR", 16, 16 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CTR, MBEDTLS_CIPHER_ARIA_256_CTR, 0, MBEDTLS_CIPHER_BASE_INDEX_ARIA }; #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_GCM_C) static int gcm_aria_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, key, key_bitlen); } static const mbedtls_cipher_base_t gcm_aria_info = { MBEDTLS_CIPHER_ID_ARIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif gcm_aria_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) gcm_aria_setkey_wrap, #endif gcm_ctx_alloc, gcm_ctx_free, }; static const mbedtls_cipher_info_t aria_128_gcm_info = { "ARIA-128-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; static const mbedtls_cipher_info_t aria_192_gcm_info = { "ARIA-192-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_ARIA_192_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; static const mbedtls_cipher_info_t aria_256_gcm_info = { "ARIA-256-GCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_GCM, MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA }; #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_CCM_C) static int ccm_aria_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, key, key_bitlen); } static const mbedtls_cipher_base_t ccm_aria_info = { MBEDTLS_CIPHER_ID_ARIA, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif ccm_aria_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) ccm_aria_setkey_wrap, #endif ccm_ctx_alloc, ccm_ctx_free, }; static const mbedtls_cipher_info_t aria_128_ccm_info = { "ARIA-128-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_ARIA_128_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_192_ccm_info = { "ARIA-192-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_ARIA_192_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_256_ccm_info = { "ARIA-256-CCM", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM, MBEDTLS_CIPHER_ARIA_256_CCM, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = { "ARIA-128-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = { "ARIA-192-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = { "ARIA-256-CCM*-NO-TAG", 16, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, MBEDTLS_CIPHER_VARIABLE_IV_LEN, MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA }; #endif /* MBEDTLS_CCM_C */ #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_DES_C) static int des_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { ((void) operation); return mbedtls_des_crypt_ecb((mbedtls_des_context *) ctx, input, output); } static int des3_crypt_ecb_wrap(void *ctx, mbedtls_operation_t operation, const unsigned char *input, unsigned char *output) { ((void) operation); return mbedtls_des3_crypt_ecb((mbedtls_des3_context *) ctx, input, output); } #if defined(MBEDTLS_CIPHER_MODE_CBC) static int des_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_des_crypt_cbc((mbedtls_des_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CBC) static int des3_crypt_cbc_wrap(void *ctx, mbedtls_operation_t operation, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output) { return mbedtls_des3_crypt_cbc((mbedtls_des3_context *) ctx, operation, length, iv, input, output); } #endif /* MBEDTLS_CIPHER_MODE_CBC */ static int des_setkey_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des_setkey_dec((mbedtls_des_context *) ctx, key); } static int des_setkey_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des_setkey_enc((mbedtls_des_context *) ctx, key); } static int des3_set2key_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set2key_dec((mbedtls_des3_context *) ctx, key); } static int des3_set2key_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set2key_enc((mbedtls_des3_context *) ctx, key); } static int des3_set3key_dec_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set3key_dec((mbedtls_des3_context *) ctx, key); } static int des3_set3key_enc_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) key_bitlen); return mbedtls_des3_set3key_enc((mbedtls_des3_context *) ctx, key); } static void *des_ctx_alloc(void) { mbedtls_des_context *des = mbedtls_calloc(1, sizeof(mbedtls_des_context)); if (des == NULL) { return NULL; } mbedtls_des_init(des); return des; } static void des_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_des_context)); } static void des_ctx_free(void *ctx) { mbedtls_des_free((mbedtls_des_context *) ctx); mbedtls_free(ctx); } static void *des3_ctx_alloc(void) { mbedtls_des3_context *des3; des3 = mbedtls_calloc(1, sizeof(mbedtls_des3_context)); if (des3 == NULL) { return NULL; } mbedtls_des3_init(des3); return des3; } static void des3_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_des3_context)); } static void des3_ctx_free(void *ctx) { mbedtls_des3_free((mbedtls_des3_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t des_info = { MBEDTLS_CIPHER_ID_DES, des_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) des_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif des_setkey_enc_wrap, des_setkey_dec_wrap, des_ctx_alloc, des_ctx_clone, des_ctx_free }; static const mbedtls_cipher_info_t des_ecb_info = { "DES-ECB", 8, 0 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_DES_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_DES }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_cbc_info = { "DES-CBC", 8, 8 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_DES_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_DES }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ static const mbedtls_cipher_base_t des_ede_info = { MBEDTLS_CIPHER_ID_DES, des3_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) des3_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif des3_set2key_enc_wrap, des3_set2key_dec_wrap, des3_ctx_alloc, des3_ctx_clone, des3_ctx_free }; static const mbedtls_cipher_info_t des_ede_ecb_info = { "DES-EDE-ECB", 8, 0 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_DES_EDE_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_ede_cbc_info = { "DES-EDE-CBC", 8, 8 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_DES_EDE_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ static const mbedtls_cipher_base_t des_ede3_info = { MBEDTLS_CIPHER_ID_3DES, des3_crypt_ecb_wrap, #if defined(MBEDTLS_CIPHER_MODE_CBC) des3_crypt_cbc_wrap, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif des3_set3key_enc_wrap, des3_set3key_dec_wrap, des3_ctx_alloc, des3_ctx_clone, des3_ctx_free }; static const mbedtls_cipher_info_t des_ede3_ecb_info = { "DES-EDE3-ECB", 8, 0 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_ECB, MBEDTLS_CIPHER_DES_EDE3_ECB, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3 }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const mbedtls_cipher_info_t des_ede3_cbc_info = { "DES-EDE3-CBC", 8, 8 >> MBEDTLS_IV_SIZE_SHIFT, MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CBC, MBEDTLS_CIPHER_DES_EDE3_CBC, 0, MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3 }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_CHACHA20_C) static int chacha20_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { if (key_bitlen != 256U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != mbedtls_chacha20_setkey((mbedtls_chacha20_context *) ctx, key)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return 0; } static int chacha20_stream_wrap(void *ctx, size_t length, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_chacha20_update(ctx, length, input, output); if (ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return ret; } static void *chacha20_ctx_alloc(void) { mbedtls_chacha20_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_chacha20_context)); if (ctx == NULL) { return NULL; } mbedtls_chacha20_init(ctx); return ctx; } static void chacha20_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_chacha20_context)); } static void chacha20_ctx_free(void *ctx) { mbedtls_chacha20_free((mbedtls_chacha20_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t chacha20_base_info = { MBEDTLS_CIPHER_ID_CHACHA20, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) chacha20_stream_wrap, #endif chacha20_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) chacha20_setkey_wrap, #endif chacha20_ctx_alloc, chacha20_ctx_clone, chacha20_ctx_free }; static const mbedtls_cipher_info_t chacha20_info = { "CHACHA20", 1, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_STREAM, MBEDTLS_CIPHER_CHACHA20, 0, MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE }; #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) static int chachapoly_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { if (key_bitlen != 256U) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (0 != mbedtls_chachapoly_setkey((mbedtls_chachapoly_context *) ctx, key)) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } return 0; } static void *chachapoly_ctx_alloc(void) { mbedtls_chachapoly_context *ctx; ctx = mbedtls_calloc(1, sizeof(mbedtls_chachapoly_context)); if (ctx == NULL) { return NULL; } mbedtls_chachapoly_init(ctx); return ctx; } static void chachapoly_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_chachapoly_context)); } static void chachapoly_ctx_free(void *ctx) { mbedtls_chachapoly_free((mbedtls_chachapoly_context *) ctx); mbedtls_free(ctx); } static const mbedtls_cipher_base_t chachapoly_base_info = { MBEDTLS_CIPHER_ID_CHACHA20, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif chachapoly_setkey_wrap, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) chachapoly_setkey_wrap, #endif chachapoly_ctx_alloc, chachapoly_ctx_clone, chachapoly_ctx_free }; static const mbedtls_cipher_info_t chachapoly_info = { "CHACHA20-POLY1305", 1, 12 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_CHACHAPOLY, MBEDTLS_CIPHER_CHACHA20_POLY1305, 0, MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE }; #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) static int null_crypt_stream(void *ctx, size_t length, const unsigned char *input, unsigned char *output) { ((void) ctx); memmove(output, input, length); return 0; } static int null_setkey(void *ctx, const unsigned char *key, unsigned int key_bitlen) { ((void) ctx); ((void) key); ((void) key_bitlen); return 0; } static void *null_ctx_alloc(void) { return (void *) 1; } static void null_ctx_clone(void *dst, const void *src) { ((void) dst); ((void) src); } static void null_ctx_free(void *ctx) { ((void) ctx); } static const mbedtls_cipher_base_t null_base_info = { MBEDTLS_CIPHER_ID_NULL, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) null_crypt_stream, #endif null_setkey, #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) null_setkey, #endif null_ctx_alloc, null_ctx_clone, null_ctx_free }; static const mbedtls_cipher_info_t null_cipher_info = { "NULL", 1, 0 >> MBEDTLS_IV_SIZE_SHIFT, 0 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_STREAM, MBEDTLS_CIPHER_NULL, 0, MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE }; #endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ #if defined(MBEDTLS_NIST_KW_C) static void *kw_ctx_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_nist_kw_context)); if (ctx != NULL) { mbedtls_nist_kw_init((mbedtls_nist_kw_context *) ctx); } return ctx; } static void kw_ctx_clone(void *dst, const void *src) { memcpy(dst, src, sizeof(mbedtls_nist_kw_context)); } static void kw_ctx_free(void *ctx) { mbedtls_nist_kw_free(ctx); mbedtls_free(ctx); } static int kw_aes_setkey_wrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1); } static int kw_aes_setkey_unwrap(void *ctx, const unsigned char *key, unsigned int key_bitlen) { return mbedtls_nist_kw_setkey((mbedtls_nist_kw_context *) ctx, MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0); } static const mbedtls_cipher_base_t kw_aes_info = { MBEDTLS_CIPHER_ID_AES, NULL, #if defined(MBEDTLS_CIPHER_MODE_CBC) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) NULL, #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) NULL, #endif kw_aes_setkey_wrap, kw_aes_setkey_unwrap, kw_ctx_alloc, kw_ctx_clone, kw_ctx_free, }; static const mbedtls_cipher_info_t aes_128_nist_kw_info = { "AES-128-KW", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KW, MBEDTLS_CIPHER_AES_128_KW, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_nist_kw_info = { "AES-192-KW", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KW, MBEDTLS_CIPHER_AES_192_KW, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; static const mbedtls_cipher_info_t aes_256_nist_kw_info = { "AES-256-KW", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KW, MBEDTLS_CIPHER_AES_256_KW, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #endif static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { "AES-128-KWP", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 128 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KWP, MBEDTLS_CIPHER_AES_128_KWP, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { "AES-192-KWP", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 192 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KWP, MBEDTLS_CIPHER_AES_192_KWP, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { "AES-256-KWP", 16, 0 >> MBEDTLS_IV_SIZE_SHIFT, 256 >> MBEDTLS_KEY_BITLEN_SHIFT, MBEDTLS_MODE_KWP, MBEDTLS_CIPHER_AES_256_KWP, 0, MBEDTLS_CIPHER_BASE_INDEX_KW_AES }; #endif #endif /* MBEDTLS_NIST_KW_C */ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = { #if defined(MBEDTLS_AES_C) { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, #endif #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, #endif #endif #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, #endif #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, #endif #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA) { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, &aes_128_ccm_star_no_tag_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, &aes_192_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, &aes_256_ccm_star_no_tag_info }, #endif #endif #if defined(MBEDTLS_CAMELLIA_C) { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, #endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, #endif #if defined(MBEDTLS_CCM_C) { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, &camellia_128_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, &camellia_192_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, &camellia_256_ccm_star_no_tag_info }, #endif #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, #endif #if defined(MBEDTLS_GCM_C) { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, #endif #if defined(MBEDTLS_CCM_C) { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, &aria_128_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, &aria_192_ccm_star_no_tag_info }, { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, &aria_256_ccm_star_no_tag_info }, #endif #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_DES_C) { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, #if defined(MBEDTLS_CIPHER_MODE_CBC) { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, #endif #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_CHACHA20_C) { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, #endif #if defined(MBEDTLS_CHACHAPOLY_C) { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, #endif #if defined(MBEDTLS_NIST_KW_C) { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info }, { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info }, #endif { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info }, { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info }, #endif #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) { MBEDTLS_CIPHER_NULL, &null_cipher_info }, #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ { MBEDTLS_CIPHER_NONE, NULL } }; #define NUM_CIPHERS (sizeof(mbedtls_cipher_definitions) / \ sizeof(mbedtls_cipher_definitions[0])) int mbedtls_cipher_supported[NUM_CIPHERS]; const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[] = { #if defined(MBEDTLS_AES_C) [MBEDTLS_CIPHER_BASE_INDEX_AES] = &aes_info, #endif #if defined(MBEDTLS_ARIA_C) [MBEDTLS_CIPHER_BASE_INDEX_ARIA] = &aria_info, #endif #if defined(MBEDTLS_CAMELLIA_C) [MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA] = &camellia_info, #endif #if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) [MBEDTLS_CIPHER_BASE_INDEX_CCM_AES] = &ccm_aes_info, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C) [MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA] = &ccm_aria_info, #endif #if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C) [MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA] = &ccm_camellia_info, #endif #if defined(MBEDTLS_CHACHA20_C) [MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE] = &chacha20_base_info, #endif #if defined(MBEDTLS_CHACHAPOLY_C) [MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE] = &chachapoly_base_info, #endif #if defined(MBEDTLS_DES_C) [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3] = &des_ede3_info, #endif #if defined(MBEDTLS_DES_C) [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE] = &des_ede_info, #endif #if defined(MBEDTLS_DES_C) [MBEDTLS_CIPHER_BASE_INDEX_DES] = &des_info, #endif #if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) [MBEDTLS_CIPHER_BASE_INDEX_GCM_AES] = &gcm_aes_info, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C) [MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA] = &gcm_aria_info, #endif #if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C) [MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA] = &gcm_camellia_info, #endif #if defined(MBEDTLS_NIST_KW_C) [MBEDTLS_CIPHER_BASE_INDEX_KW_AES] = &kw_aes_info, #endif #if defined(MBEDTLS_CIPHER_NULL_CIPHER) [MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE] = &null_base_info, #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C) [MBEDTLS_CIPHER_BASE_INDEX_XTS_AES] = &xts_aes_info #endif }; #endif /* MBEDTLS_CIPHER_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/cipher_wrap.h000066400000000000000000000142041464416617300240110ustar00rootroot00000000000000/** * \file cipher_wrap.h * * \brief Cipher wrappers. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CIPHER_WRAP_H #define MBEDTLS_CIPHER_WRAP_H #include "mbedtls/build_info.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #ifdef __cplusplus extern "C" { #endif /* Support for GCM either through Mbed TLS SW implementation or PSA */ #if defined(MBEDTLS_GCM_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM)) #define MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA #endif #if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM) && defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CCM_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM)) #define MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA #endif #if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM) && defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CCM_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)) #define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA #endif #if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && \ defined(PSA_WANT_KEY_TYPE_AES)) #define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CHACHAPOLY_C) || \ (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305)) #define MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA #endif #if defined(MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA) || \ defined(MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA) #define MBEDTLS_CIPHER_HAVE_SOME_AEAD_VIA_LEGACY_OR_USE_PSA #endif /** * Base cipher information. The non-mode specific functions and values. */ struct mbedtls_cipher_base_t { /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ mbedtls_cipher_id_t cipher; /** Encrypt using ECB */ int (*ecb_func)(void *ctx, mbedtls_operation_t mode, const unsigned char *input, unsigned char *output); #if defined(MBEDTLS_CIPHER_MODE_CBC) /** Encrypt using CBC */ int (*cbc_func)(void *ctx, mbedtls_operation_t mode, size_t length, unsigned char *iv, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_CFB) /** Encrypt using CFB (Full length) */ int (*cfb_func)(void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_OFB) /** Encrypt using OFB (Full length) */ int (*ofb_func)(void *ctx, size_t length, size_t *iv_off, unsigned char *iv, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_CTR) /** Encrypt using CTR */ int (*ctr_func)(void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter, unsigned char *stream_block, const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_XTS) /** Encrypt or decrypt using XTS. */ int (*xts_func)(void *ctx, mbedtls_operation_t mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output); #endif #if defined(MBEDTLS_CIPHER_MODE_STREAM) /** Encrypt using STREAM */ int (*stream_func)(void *ctx, size_t length, const unsigned char *input, unsigned char *output); #endif /** Set key for encryption purposes */ int (*setkey_enc_func)(void *ctx, const unsigned char *key, unsigned int key_bitlen); #if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) /** Set key for decryption purposes */ int (*setkey_dec_func)(void *ctx, const unsigned char *key, unsigned int key_bitlen); #endif /** Allocate a new context */ void * (*ctx_alloc_func)(void); /** Clone context **/ void (*ctx_clone_func)( void *dst, const void *src ); /** Free the given context */ void (*ctx_free_func)(void *ctx); }; typedef struct { mbedtls_cipher_type_t type; const mbedtls_cipher_info_t *info; } mbedtls_cipher_definition_t; #if defined(MBEDTLS_USE_PSA_CRYPTO) typedef enum { MBEDTLS_CIPHER_PSA_KEY_UNSET = 0, MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */ /* use raw key material internally imported */ /* as a volatile key, and which hence need */ /* to destroy that key when the context is */ /* freed. */ MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */ /* which use a key provided by the */ /* user, and which hence will not be */ /* destroyed when the context is freed. */ } mbedtls_cipher_psa_key_ownership; typedef struct { psa_algorithm_t alg; mbedtls_svc_key_id_t slot; mbedtls_cipher_psa_key_ownership slot_state; } mbedtls_cipher_context_psa; #endif /* MBEDTLS_USE_PSA_CRYPTO */ extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; extern int mbedtls_cipher_supported[]; extern const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[]; #ifdef __cplusplus } #endif #endif /* MBEDTLS_CIPHER_WRAP_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/cmac.c000066400000000000000000001020171464416617300224040ustar00rootroot00000000000000/** * \file cmac.c * * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The * CMAC Mode for Authentication * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf * * - RFC 4493 - The AES-CMAC Algorithm * https://tools.ietf.org/html/rfc4493 * * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) * Algorithm for the Internet Key Exchange Protocol (IKE) * https://tools.ietf.org/html/rfc4615 * * Additional test vectors: ISO/IEC 9797-1 * */ #include "common.h" #if defined(MBEDTLS_CMAC_C) #include "mbedtls/cmac.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "constant_time_internal.h" #include #if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) /* * Multiplication by u in the Galois field of GF(2^n) * * As explained in NIST SP 800-38B, this can be computed: * * If MSB(p) = 0, then p = (p << 1) * If MSB(p) = 1, then p = (p << 1) ^ R_n * with R_64 = 0x1B and R_128 = 0x87 * * Input and output MUST NOT point to the same buffer * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. */ static int cmac_multiply_by_u(unsigned char *output, const unsigned char *input, size_t blocksize) { const unsigned char R_128 = 0x87; unsigned char R_n; uint32_t overflow = 0x00; int i; if (blocksize == MBEDTLS_AES_BLOCK_SIZE) { R_n = R_128; } #if defined(MBEDTLS_DES_C) else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) { const unsigned char R_64 = 0x1B; R_n = R_64; } #endif else { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } for (i = (int) blocksize - 4; i >= 0; i -= 4) { uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0); uint32_t new_overflow = i32 >> 31; i32 = (i32 << 1) | overflow; MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0); overflow = new_overflow; } R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n); output[blocksize - 1] ^= R_n; return 0; } /* * Generate subkeys * * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm */ static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx, unsigned char *K1, unsigned char *K2) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; size_t olen, block_size; mbedtls_platform_zeroize(L, sizeof(L)); block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); /* Calculate Ek(0) */ if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) { goto exit; } /* * Generate K1 and K2 */ if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) { goto exit; } if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) { goto exit; } exit: mbedtls_platform_zeroize(L, sizeof(L)); return ret; } #endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ #if !defined(MBEDTLS_CMAC_ALT) /* * Create padded last block from (partial) last block. * * We can't use the padding option from the cipher layer, as it only works for * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. */ static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE], size_t padded_block_len, const unsigned char *last_block, size_t last_block_len) { size_t j; for (j = 0; j < padded_block_len; j++) { if (j < last_block_len) { padded_block[j] = last_block[j]; } else if (j == last_block_len) { padded_block[j] = 0x80; } else { padded_block[j] = 0x00; } } } int mbedtls_cipher_cmac_setup(mbedtls_cipher_context_t *ctx) { mbedtls_cmac_context_t *cmac_ctx; /* Allocated and initialise in the cipher context memory for the CMAC * context */ cmac_ctx = mbedtls_calloc(1, sizeof(mbedtls_cmac_context_t)); if (cmac_ctx == NULL) return MBEDTLS_ERR_CIPHER_ALLOC_FAILED; ctx->cmac_ctx = cmac_ctx; mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state)); return 0; } int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, const unsigned char *key, size_t keybits) { mbedtls_cipher_type_t type; int retval; if (ctx == NULL || ctx->cipher_info == NULL || key == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if ((retval = mbedtls_cipher_setkey(ctx, key, (int) keybits, MBEDTLS_ENCRYPT)) != 0) { return retval; } type = mbedtls_cipher_info_get_type(ctx->cipher_info); switch (type) { case MBEDTLS_CIPHER_AES_128_ECB: case MBEDTLS_CIPHER_AES_192_ECB: case MBEDTLS_CIPHER_AES_256_ECB: case MBEDTLS_CIPHER_DES_EDE3_ECB: break; default: return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* Check if cmac ctx had been allocated by mbedtls_cipher_cmac_setup() */ if( ctx->cmac_ctx != NULL ) return 0; return mbedtls_cipher_cmac_setup( ctx ); } int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, size_t ilen) { mbedtls_cmac_context_t *cmac_ctx; unsigned char *state; int ret = 0; size_t n, j, olen, block_size; if (ctx == NULL || ctx->cipher_info == NULL || input == NULL || ctx->cmac_ctx == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cmac_ctx = ctx->cmac_ctx; block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); state = ctx->cmac_ctx->state; /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */ MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); /* Is there data still to process from the last call, that's greater in * size than a block? */ if (cmac_ctx->unprocessed_len > 0 && ilen > block_size - cmac_ctx->unprocessed_len) { memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input, block_size - cmac_ctx->unprocessed_len); mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; } input += block_size - cmac_ctx->unprocessed_len; ilen -= block_size - cmac_ctx->unprocessed_len; cmac_ctx->unprocessed_len = 0; } /* n is the number of blocks including any final partial block */ n = (ilen + block_size - 1) / block_size; /* Iterate across the input data in block sized chunks, excluding any * final partial or complete block */ for (j = 1; j < n; j++) { mbedtls_xor_no_simd(state, input, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; } ilen -= block_size; input += block_size; } /* If there is data left over that wasn't aligned to a block */ if (ilen > 0) { memcpy(&cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], input, ilen); cmac_ctx->unprocessed_len += ilen; } exit: return ret; } int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, unsigned char *output) { mbedtls_cmac_context_t *cmac_ctx; unsigned char *state, *last_block; unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen, block_size; if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || output == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cmac_ctx = ctx->cmac_ctx; block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning state = cmac_ctx->state; mbedtls_platform_zeroize(K1, sizeof(K1)); mbedtls_platform_zeroize(K2, sizeof(K2)); cmac_generate_subkeys(ctx, K1, K2); last_block = cmac_ctx->unprocessed_block; /* Calculate last block */ if (cmac_ctx->unprocessed_len < block_size) { cmac_pad(M_last, block_size, last_block, cmac_ctx->unprocessed_len); mbedtls_xor(M_last, M_last, K2, block_size); } else { /* Last block is complete block */ mbedtls_xor(M_last, last_block, K1, block_size); } mbedtls_xor(state, M_last, state, block_size); if ((ret = mbedtls_cipher_update(ctx, state, block_size, state, &olen)) != 0) { goto exit; } memcpy(output, state, block_size); exit: /* Wipe the generated keys on the stack, and any other transients to avoid * side channel leakage */ mbedtls_platform_zeroize(K1, sizeof(K1)); mbedtls_platform_zeroize(K2, sizeof(K2)); cmac_ctx->unprocessed_len = 0; mbedtls_platform_zeroize(cmac_ctx->unprocessed_block, sizeof(cmac_ctx->unprocessed_block)); mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE); return ret; } int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx) { mbedtls_cmac_context_t *cmac_ctx; if (ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cmac_ctx = ctx->cmac_ctx; /* Reset the internal state */ cmac_ctx->unprocessed_len = 0; mbedtls_platform_zeroize(cmac_ctx->unprocessed_block, sizeof(cmac_ctx->unprocessed_block)); mbedtls_platform_zeroize(cmac_ctx->state, sizeof(cmac_ctx->state)); return 0; } int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output) { mbedtls_cipher_context_t ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (cipher_info == NULL || key == NULL || input == NULL || output == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } mbedtls_cipher_init(&ctx); if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) { goto exit; } ret = mbedtls_cipher_cmac_starts(&ctx, key, keylen); if (ret != 0) { goto exit; } ret = mbedtls_cipher_cmac_update(&ctx, input, ilen); if (ret != 0) { goto exit; } ret = mbedtls_cipher_cmac_finish(&ctx, output); exit: mbedtls_cipher_free(&ctx); return ret; } #if defined(MBEDTLS_AES_C) /* * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 */ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_length, const unsigned char *input, size_t in_len, unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_cipher_info_t *cipher_info; unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; if (key == NULL || input == NULL || output == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); if (cipher_info == NULL) { /* Failing at this point must be due to a build issue */ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto exit; } if (key_length == MBEDTLS_AES_BLOCK_SIZE) { /* Use key as is */ memcpy(int_key, key, MBEDTLS_AES_BLOCK_SIZE); } else { memset(zero_key, 0, MBEDTLS_AES_BLOCK_SIZE); ret = mbedtls_cipher_cmac(cipher_info, zero_key, 128, key, key_length, int_key); if (ret != 0) { goto exit; } } ret = mbedtls_cipher_cmac(cipher_info, int_key, 128, input, in_len, output); exit: mbedtls_platform_zeroize(int_key, sizeof(int_key)); return ret; } #endif /* MBEDTLS_AES_C */ #endif /* !MBEDTLS_CMAC_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * CMAC test data for SP800-38B * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf * * AES-CMAC-PRF-128 test data from RFC 4615 * https://tools.ietf.org/html/rfc4615#page-4 */ #define NB_CMAC_TESTS_PER_KEY 4 #define NB_PRF_TESTS 3 #if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) /* All CMAC test inputs are truncated from the same 64 byte buffer. */ static const unsigned char test_message[] = { /* PT */ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; #endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* Truncation point of message for AES CMAC tests */ static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { /* Mlen */ 0, 16, 20, 64 }; /* CMAC-AES128 Test Data */ static const unsigned char aes_128_key[16] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { { /* K1 */ 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde }, { /* K2 */ 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b } }; static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { { /* Example #1 */ 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 }, { /* Example #2 */ 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c }, { /* Example #3 */ 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde }, { /* Example #4 */ 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } }; /* CMAC-AES192 Test Data */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const unsigned char aes_192_key[24] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b }; static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { { /* K1 */ 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 }, { /* K2 */ 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c } }; static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { { /* Example #1 */ 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 }, { /* Example #2 */ 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 }, { /* Example #3 */ 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 }, { /* Example #4 */ 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 } }; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* CMAC-AES256 Test Data */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) static const unsigned char aes_256_key[32] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 }; static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { { /* K1 */ 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f }, { /* K2 */ 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 } }; static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { { /* Example #1 */ 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 }, { /* Example #2 */ 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c }, { /* Example #3 */ 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 }, { /* Example #4 */ 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 } }; #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) /* Truncation point of message for 3DES CMAC tests */ static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { 0, 16, 20, 32 }; /* CMAC-TDES (Generation) - 2 Key Test Data */ static const unsigned char des3_2key_key[24] = { /* Key1 */ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, /* Key2 */ 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, /* Key3 */ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; static const unsigned char des3_2key_subkeys[2][8] = { { /* K1 */ 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 }, { /* K2 */ 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 } }; static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { { /* Sample #1 */ 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 }, { /* Sample #2 */ 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b }, { /* Sample #3 */ 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 }, { /* Sample #4 */ 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb } }; /* CMAC-TDES (Generation) - 3 Key Test Data */ static const unsigned char des3_3key_key[24] = { /* Key1 */ 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, /* Key2 */ 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, /* Key3 */ 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 }; static const unsigned char des3_3key_subkeys[2][8] = { { /* K1 */ 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 }, { /* K2 */ 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b } }; static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { { /* Sample #1 */ 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 }, { /* Sample #2 */ 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 }, { /* Sample #3 */ 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 }, { /* Sample #4 */ 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 } }; #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* AES AES-CMAC-PRF-128 Test Data */ static const unsigned char PRFK[] = { /* Key */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xed, 0xcb }; /* Sizes in bytes */ static const size_t PRFKlen[NB_PRF_TESTS] = { 18, 16, 10 }; /* Message */ static const unsigned char PRFM[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13 }; static const unsigned char PRFT[NB_PRF_TESTS][16] = { { 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a }, { 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d }, { 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d } }; #endif /* MBEDTLS_AES_C */ static int cmac_test_subkeys(int verbose, const char *testname, const unsigned char *key, int keybits, const unsigned char *subkeys, mbedtls_cipher_type_t cipher_type, int block_size, int num_tests) { int i, ret = 0; mbedtls_cipher_context_t ctx; const mbedtls_cipher_info_t *cipher_info; unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { /* Failing at this point must be due to a build issue */ return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } for (i = 0; i < num_tests; i++) { if (verbose != 0) { mbedtls_printf(" %s CMAC subkey #%d: ", testname, i + 1); } mbedtls_cipher_init(&ctx); if ((ret = mbedtls_cipher_setup(&ctx, cipher_info)) != 0) { if (verbose != 0) { mbedtls_printf("test execution failed\n"); } goto cleanup; } if ((ret = mbedtls_cipher_setkey(&ctx, key, keybits, MBEDTLS_ENCRYPT)) != 0) { /* When CMAC is implemented by an alternative implementation, or * the underlying primitive itself is implemented alternatively, * AES-192 may be unavailable. This should not cause the selftest * function to fail. */ if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) && cipher_type == MBEDTLS_CIPHER_AES_192_ECB) { if (verbose != 0) { mbedtls_printf("skipped\n"); } goto next_test; } if (verbose != 0) { mbedtls_printf("test execution failed\n"); } goto cleanup; } ret = cmac_generate_subkeys(&ctx, K1, K2); if (ret != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto cleanup; } if ((ret = memcmp(K1, subkeys, block_size)) != 0 || (ret = memcmp(K2, &subkeys[block_size], block_size)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } next_test: mbedtls_cipher_free(&ctx); } ret = 0; goto exit; cleanup: mbedtls_cipher_free(&ctx); exit: return ret; } static int cmac_test_wth_cipher(int verbose, const char *testname, const unsigned char *key, int keybits, const unsigned char *messages, const unsigned int message_lengths[4], const unsigned char *expected_result, mbedtls_cipher_type_t cipher_type, int block_size, int num_tests) { const mbedtls_cipher_info_t *cipher_info; int i, ret = 0; unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE]; cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { /* Failing at this point must be due to a build issue */ ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto exit; } for (i = 0; i < num_tests; i++) { if (verbose != 0) { mbedtls_printf(" %s CMAC #%d: ", testname, i + 1); } if ((ret = mbedtls_cipher_cmac(cipher_info, key, keybits, messages, message_lengths[i], output)) != 0) { /* When CMAC is implemented by an alternative implementation, or * the underlying primitive itself is implemented alternatively, * AES-192 and/or 3DES may be unavailable. This should not cause * the selftest function to fail. */ if ((ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) && (cipher_type == MBEDTLS_CIPHER_AES_192_ECB || cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB)) { if (verbose != 0) { mbedtls_printf("skipped\n"); } continue; } if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } if ((ret = memcmp(output, &expected_result[i * block_size], block_size)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } ret = 0; exit: return ret; } #if defined(MBEDTLS_AES_C) static int test_aes128_cmac_prf(int verbose) { int i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; for (i = 0; i < NB_PRF_TESTS; i++) { mbedtls_printf(" AES CMAC 128 PRF #%d: ", i); ret = mbedtls_aes_cmac_prf_128(PRFK, PRFKlen[i], PRFM, 20, output); if (ret != 0 || memcmp(output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return ret; } else if (verbose != 0) { mbedtls_printf("passed\n"); } } return ret; } #endif /* MBEDTLS_AES_C */ int mbedtls_cmac_self_test(int verbose) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_AES_C) /* AES-128 */ if ((ret = cmac_test_subkeys(verbose, "AES 128", aes_128_key, 128, (const unsigned char *) aes_128_subkeys, MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "AES 128", aes_128_key, 128, test_message, aes_message_lengths, (const unsigned char *) aes_128_expected_result, MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } /* AES-192 */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) if ((ret = cmac_test_subkeys(verbose, "AES 192", aes_192_key, 192, (const unsigned char *) aes_192_subkeys, MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "AES 192", aes_192_key, 192, test_message, aes_message_lengths, (const unsigned char *) aes_192_expected_result, MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ /* AES-256 */ #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) if ((ret = cmac_test_subkeys(verbose, "AES 256", aes_256_key, 256, (const unsigned char *) aes_256_subkeys, MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "AES 256", aes_256_key, 256, test_message, aes_message_lengths, (const unsigned char *) aes_256_expected_result, MBEDTLS_CIPHER_AES_256_ECB, MBEDTLS_AES_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) /* 3DES 2 key */ if ((ret = cmac_test_subkeys(verbose, "3DES 2 key", des3_2key_key, 192, (const unsigned char *) des3_2key_subkeys, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "3DES 2 key", des3_2key_key, 192, test_message, des3_message_lengths, (const unsigned char *) des3_2key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } /* 3DES 3 key */ if ((ret = cmac_test_subkeys(verbose, "3DES 3 key", des3_3key_key, 192, (const unsigned char *) des3_3key_subkeys, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } if ((ret = cmac_test_wth_cipher(verbose, "3DES 3 key", des3_3key_key, 192, test_message, des3_message_lengths, (const unsigned char *) des3_3key_expected_result, MBEDTLS_CIPHER_DES_EDE3_ECB, MBEDTLS_DES3_BLOCK_SIZE, NB_CMAC_TESTS_PER_KEY)) != 0) { return ret; } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if ((ret = test_aes128_cmac_prf(verbose)) != 0) { return ret; } #endif /* MBEDTLS_AES_C */ if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CMAC_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/common.h000066400000000000000000000405071464416617300230030ustar00rootroot00000000000000/** * \file common.h * * \brief Utility macros for internal use in the library */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LIBRARY_COMMON_H #define MBEDTLS_LIBRARY_COMMON_H #include "mbedtls/build_info.h" #include "alignment.h" #include #include #include #include #if defined(__ARM_NEON) /* * Undefine and restore __section and __data from compiler.h to prevent * collision with arm_neon.h */ #pragma push_macro("__section") #pragma push_macro("__data") #undef __section #undef __data #include #pragma pop_macro("__data") #pragma pop_macro("__section") #define MBEDTLS_HAVE_NEON_INTRINSICS #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) #include #define MBEDTLS_HAVE_NEON_INTRINSICS #endif /** Helper to define a function as static except when building invasive tests. * * If a function is only used inside its own source file and should be * declared `static` to allow the compiler to optimize for code size, * but that function has unit tests, define it with * ``` * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } * ``` * and declare it in a header in the `library/` directory with * ``` * #if defined(MBEDTLS_TEST_HOOKS) * int mbedtls_foo(...); * #endif * ``` */ #if defined(MBEDTLS_TEST_HOOKS) #define MBEDTLS_STATIC_TESTABLE #else #define MBEDTLS_STATIC_TESTABLE static #endif #if defined(MBEDTLS_TEST_HOOKS) extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file); #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \ do { \ if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \ { \ (*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \ } \ } while (0) #else #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) #endif /* defined(MBEDTLS_TEST_HOOKS) */ /** \def ARRAY_LENGTH * Return the number of elements of a static or stack array. * * \param array A value of array (not pointer) type. * * \return The number of elements of the array. */ /* A correct implementation of ARRAY_LENGTH, but which silently gives * a nonsensical result if called with a pointer rather than an array. */ #define ARRAY_LENGTH_UNSAFE(array) \ (sizeof(array) / sizeof(*(array))) #if defined(__GNUC__) /* Test if arg and &(arg)[0] have the same type. This is true if arg is * an array but not if it's a pointer. */ #define IS_ARRAY_NOT_POINTER(arg) \ (!__builtin_types_compatible_p(__typeof__(arg), \ __typeof__(&(arg)[0]))) /* A compile-time constant with the value 0. If `const_expr` is not a * compile-time constant with a nonzero value, cause a compile-time error. */ #define STATIC_ASSERT_EXPR(const_expr) \ (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); })) /* Return the scalar value `value` (possibly promoted). This is a compile-time * constant if `value` is. `condition` must be a compile-time constant. * If `condition` is false, arrange to cause a compile-time error. */ #define STATIC_ASSERT_THEN_RETURN(condition, value) \ (STATIC_ASSERT_EXPR(condition) ? 0 : (value)) #define ARRAY_LENGTH(array) \ (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array), \ ARRAY_LENGTH_UNSAFE(array))) #else /* If we aren't sure the compiler supports our non-standard tricks, * fall back to the unsafe implementation. */ #define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array) #endif /** Allow library to access its structs' private members. * * Although structs defined in header files are publicly available, * their members are private and should not be accessed by the user. */ #define MBEDTLS_ALLOW_PRIVATE_ACCESS /** * \brief Securely zeroize a buffer then free it. * * Similar to making consecutive calls to * \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has * code size savings, and potential for optimisation in the future. * * Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0. * * \param buf Buffer to be zeroized then freed. * \param len Length of the buffer in bytes */ void mbedtls_zeroize_and_free(void *buf, size_t len); /** Return an offset into a buffer. * * This is just the addition of an offset to a pointer, except that this * function also accepts an offset of 0 into a buffer whose pointer is null. * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. * A null pointer is a valid buffer pointer when the size is 0, for example * as the result of `malloc(0)` on some platforms.) * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline unsigned char *mbedtls_buffer_offset( unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } /** Return an offset into a read-only buffer. * * Similar to mbedtls_buffer_offset(), but for const pointers. * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline const unsigned char *mbedtls_buffer_offset_const( const unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } /* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif /** * Perform a fast block XOR operation, such that * r[i] = a[i] ^ b[i] where 0 <= i < n * * \param r Pointer to result (buffer of at least \p n bytes). \p r * may be equal to either \p a or \p b, but behaviour when * it overlaps in other ways is undefined. * \param a Pointer to input (buffer of at least \p n bytes) * \param b Pointer to input (buffer of at least \p n bytes) * \param n Number of bytes to process. * * \note Depending on the situation, it may be faster to use either mbedtls_xor() or * mbedtls_xor_no_simd() (these are functionally equivalent). * If the result is used immediately after the xor operation in non-SIMD code (e.g, in * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster. * For targets without SIMD support, they will behave the same. */ static inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n) { size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) #if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \ (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300)) /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */ for (; (i + 16) <= n; i += 16) { uint8x16_t v1 = vld1q_u8(a + i); uint8x16_t v2 = vld1q_u8(b + i); uint8x16_t x = veorq_u8(v1, v2); vst1q_u8(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case * where n is a constant multiple of 16. * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time * constant, and is a very small perf regression if n is not a compile-time constant. */ if (n % 16 == 0) { return; } #endif #elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) /* This codepath probably only makes sense on architectures with 64-bit registers */ for (; (i + 8) <= n; i += 8) { uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); mbedtls_put_unaligned_uint64(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) if (n % 8 == 0) { return; } #endif #else for (; (i + 4) <= n; i += 4) { uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); mbedtls_put_unaligned_uint32(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) if (n % 4 == 0) { return; } #endif #endif #endif for (; i < n; i++) { r[i] = a[i] ^ b[i]; } } /* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */ #if defined(__IAR_SYSTEMS_ICC__) #pragma inline = forced #elif defined(__GNUC__) __attribute__((always_inline)) #endif /** * Perform a fast block XOR operation, such that * r[i] = a[i] ^ b[i] where 0 <= i < n * * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5% * better in AES-CBC). * * \param r Pointer to result (buffer of at least \p n bytes). \p r * may be equal to either \p a or \p b, but behaviour when * it overlaps in other ways is undefined. * \param a Pointer to input (buffer of at least \p n bytes) * \param b Pointer to input (buffer of at least \p n bytes) * \param n Number of bytes to process. * * \note Depending on the situation, it may be faster to use either mbedtls_xor() or * mbedtls_xor_no_simd() (these are functionally equivalent). * If the result is used immediately after the xor operation in non-SIMD code (e.g, in * AES-CBC), there may be additional latency to transfer the data from SIMD to scalar * registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where * the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster. * For targets without SIMD support, they will behave the same. */ static inline void mbedtls_xor_no_simd(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n) { size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) #if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) /* This codepath probably only makes sense on architectures with 64-bit registers */ for (; (i + 8) <= n; i += 8) { uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); mbedtls_put_unaligned_uint64(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case * where n is a constant multiple of 8. * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time * constant, and is a very small perf regression if n is not a compile-time constant. */ if (n % 8 == 0) { return; } #endif #else for (; (i + 4) <= n; i += 4) { uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i); mbedtls_put_unaligned_uint32(r + i, x); } #if defined(__IAR_SYSTEMS_ICC__) if (n % 4 == 0) { return; } #endif #endif #endif for (; i < n; i++) { r[i] = a[i] ^ b[i]; } } /* Fix MSVC C99 compatible issue * MSVC support __func__ from visual studio 2015( 1900 ) * Use MSVC predefine macro to avoid name check fail. */ #if (defined(_MSC_VER) && (_MSC_VER <= 1900)) #define /*no-check-names*/ __func__ __FUNCTION__ #endif /* Define `asm` for compilers which don't define it. */ /* *INDENT-OFF* */ #ifndef asm #if defined(__IAR_SYSTEMS_ICC__) #define asm __asm #else #define asm __asm__ #endif #endif /* *INDENT-ON* */ /* * Define the constraint used for read-only pointer operands to aarch64 asm. * * This is normally the usual "r", but for aarch64_32 (aka ILP32, * as found in watchos), "p" is required to avoid warnings from clang. * * Note that clang does not recognise '+p' or '=p', and armclang * does not recognise 'p' at all. Therefore, to update a pointer from * aarch64 assembly, it is necessary to use something like: * * uintptr_t uptr = (uintptr_t) ptr; * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : ) * ptr = (void*) uptr; * * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings. */ #if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM) #if UINTPTR_MAX == 0xfffffffful /* ILP32: Specify the pointer operand slightly differently, as per #7787. */ #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p" #elif UINTPTR_MAX == 0xfffffffffffffffful /* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */ #define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r" #else #error "Unrecognised pointer size for aarch64" #endif #endif /* Always provide a static assert macro, so it can be used unconditionally. * It will expand to nothing on some systems. * Can be used outside functions (but don't add a trailing ';' in that case: * the semicolon is included here to avoid triggering -Wextra-semi when * MBEDTLS_STATIC_ASSERT() expands to nothing). * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it * defines static_assert even with -std=c99, but then complains about it. */ #if defined(static_assert) && !defined(__FreeBSD__) #define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg); #else #define MBEDTLS_STATIC_ASSERT(expr, msg) #endif #if defined(__has_builtin) #define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x) #else #define MBEDTLS_HAS_BUILTIN(x) 0 #endif /* Define compiler branch hints */ #if MBEDTLS_HAS_BUILTIN(__builtin_expect) #define MBEDTLS_LIKELY(x) __builtin_expect(!!(x), 1) #define MBEDTLS_UNLIKELY(x) __builtin_expect(!!(x), 0) #else #define MBEDTLS_LIKELY(x) x #define MBEDTLS_UNLIKELY(x) x #endif /* MBEDTLS_ASSUME may be used to provide additional information to the compiler * which can result in smaller code-size. */ #if MBEDTLS_HAS_BUILTIN(__builtin_assume) /* clang provides __builtin_assume */ #define MBEDTLS_ASSUME(x) __builtin_assume(x) #elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable) /* gcc and IAR can use __builtin_unreachable */ #define MBEDTLS_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0) #elif defined(_MSC_VER) /* Supported by MSVC since VS 2005 */ #define MBEDTLS_ASSUME(x) __assume(x) #else #define MBEDTLS_ASSUME(x) do { } while (0) #endif /* For gcc -Os, override with -O2 for a given function. * * This will not affect behaviour for other optimisation settings, e.g. -O0. */ #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__) #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2"))) #else #define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE #endif /* Suppress compiler warnings for unused functions and variables. */ #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute) # if __has_attribute(unused) # define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) # endif #endif #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__) # define MBEDTLS_MAYBE_UNUSED __attribute__((unused)) #endif #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__) /* IAR does support __attribute__((unused)), but only if the -e flag (extended language support) * is given; the pragma always works. * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless. * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't * able to find documentation). */ # if (__VER__ >= 5020000) # define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177") # endif #endif #if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER) # define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189)) #endif #if !defined(MBEDTLS_MAYBE_UNUSED) # define MBEDTLS_MAYBE_UNUSED #endif #endif /* MBEDTLS_LIBRARY_COMMON_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/constant_time.c000066400000000000000000000212301464416617300243450ustar00rootroot00000000000000/** * Constant-time functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following functions are implemented without using comparison operators, as those * might be translated to branches by some compilers on some platforms. */ #include #include #include "common.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include #if !defined(MBEDTLS_CT_ASM) /* * Define an object with the value zero, such that the compiler cannot prove that it * has the value zero (because it is volatile, it "may be modified in ways unknown to * the implementation"). */ volatile mbedtls_ct_uint_t mbedtls_ct_zero = 0; #endif /* * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to * perform fast unaligned access to volatile data. * * This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile * memory accesses. * * Some of these definitions could be moved into alignment.h but for now they are * only used here. */ #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && \ ((defined(MBEDTLS_CT_ARM_ASM) && (UINTPTR_MAX == 0xfffffffful)) || \ defined(MBEDTLS_CT_AARCH64_ASM)) /* We check pointer sizes to avoid issues with them not matching register size requirements */ #define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p) { /* This is UB, even where it's safe: * return *((volatile uint32_t*)p); * so instead the same thing is expressed in assembly below. */ uint32_t r; #if defined(MBEDTLS_CT_ARM_ASM) asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :); #elif defined(MBEDTLS_CT_AARCH64_ASM) asm volatile ("ldr %w0, [%1]" : "=r" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :); #else #error "No assembly defined for mbedtls_get_unaligned_volatile_uint32" #endif return r; } #endif /* defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && (defined(MBEDTLS_CT_ARM_ASM) || defined(MBEDTLS_CT_AARCH64_ASM)) */ int mbedtls_ct_memcmp(const void *a, const void *b, size_t n) { size_t i = 0; /* * `A` and `B` are cast to volatile to ensure that the compiler * generates code that always fully reads both buffers. * Otherwise it could generate a test to exit early if `diff` has all * bits set early in the loop. */ volatile const unsigned char *A = (volatile const unsigned char *) a; volatile const unsigned char *B = (volatile const unsigned char *) b; uint32_t diff = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS) for (; (i + 4) <= n; i += 4) { uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i); uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i); diff |= x ^ y; } #endif for (; i < n; i++) { /* Read volatile data in order before computing diff. * This avoids IAR compiler warning: * 'the order of volatile accesses is undefined ..' */ unsigned char x = A[i], y = B[i]; diff |= x ^ y; } #if (INT_MAX < INT32_MAX) /* We don't support int smaller than 32-bits, but if someone tried to build * with this configuration, there is a risk that, for differing data, the * only bits set in diff are in the top 16-bits, and would be lost by a * simple cast from uint32 to int. * This would have significant security implications, so protect against it. */ #error "mbedtls_ct_memcmp() requires minimum 32-bit ints" #else /* The bit-twiddling ensures that when we cast uint32_t to int, we are casting * a value that is in the range 0..INT_MAX - a value larger than this would * result in implementation defined behaviour. * * This ensures that the value returned by the function is non-zero iff * diff is non-zero. */ return (int) ((diff & 0xffff) | (diff >> 16)); #endif } #if defined(MBEDTLS_NIST_KW_C) int mbedtls_ct_memcmp_partial(const void *a, const void *b, size_t n, size_t skip_head, size_t skip_tail) { unsigned int diff = 0; volatile const unsigned char *A = (volatile const unsigned char *) a; volatile const unsigned char *B = (volatile const unsigned char *) b; size_t valid_end = n - skip_tail; for (size_t i = 0; i < n; i++) { unsigned char x = A[i], y = B[i]; unsigned int d = x ^ y; mbedtls_ct_condition_t valid = mbedtls_ct_bool_and(mbedtls_ct_uint_ge(i, skip_head), mbedtls_ct_uint_lt(i, valid_end)); diff |= mbedtls_ct_uint_if_else_0(valid, d); } /* Since we go byte-by-byte, the only bits set will be in the bottom 8 bits, so the * cast from uint to int is safe. */ return (int) diff; } #endif #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset) { volatile unsigned char *buf = start; for (size_t i = 0; i < total; i++) { mbedtls_ct_condition_t no_op = mbedtls_ct_uint_gt(total - offset, i); /* The first `total - offset` passes are a no-op. The last * `offset` passes shift the data one byte to the left and * zero out the last byte. */ for (size_t n = 0; n < total - 1; n++) { unsigned char current = buf[n]; unsigned char next = buf[n+1]; buf[n] = mbedtls_ct_uint_if(no_op, current, next); } buf[total-1] = mbedtls_ct_uint_if_else_0(no_op, buf[total-1]); } } #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition, unsigned char *dest, const unsigned char *src1, const unsigned char *src2, size_t len) { #if defined(MBEDTLS_CT_SIZE_64) const uint64_t mask = (uint64_t) condition; const uint64_t not_mask = (uint64_t) ~mbedtls_ct_compiler_opaque(condition); #else const uint32_t mask = (uint32_t) condition; const uint32_t not_mask = (uint32_t) ~mbedtls_ct_compiler_opaque(condition); #endif /* If src2 is NULL, setup src2 so that we read from the destination address. * * This means that if src2 == NULL && condition is false, the result will be a * no-op because we read from dest and write the same data back into dest. */ if (src2 == NULL) { src2 = dest; } /* dest[i] = c1 == c2 ? src[i] : dest[i] */ size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) #if defined(MBEDTLS_CT_SIZE_64) for (; (i + 8) <= len; i += 8) { uint64_t a = mbedtls_get_unaligned_uint64(src1 + i) & mask; uint64_t b = mbedtls_get_unaligned_uint64(src2 + i) & not_mask; mbedtls_put_unaligned_uint64(dest + i, a | b); } #else for (; (i + 4) <= len; i += 4) { uint32_t a = mbedtls_get_unaligned_uint32(src1 + i) & mask; uint32_t b = mbedtls_get_unaligned_uint32(src2 + i) & not_mask; mbedtls_put_unaligned_uint32(dest + i, a | b); } #endif /* defined(MBEDTLS_CT_SIZE_64) */ #endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */ for (; i < len; i++) { dest[i] = (src1[i] & mask) | (src2[i] & not_mask); } } void mbedtls_ct_memcpy_offset(unsigned char *dest, const unsigned char *src, size_t offset, size_t offset_min, size_t offset_max, size_t len) { size_t offsetval; for (offsetval = offset_min; offsetval <= offset_max; offsetval++) { mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offsetval, offset), dest, src + offsetval, NULL, len); } } #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len) { uint32_t mask = (uint32_t) ~condition; uint8_t *p = (uint8_t *) buf; size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) for (; (i + 4) <= len; i += 4) { mbedtls_put_unaligned_uint32((void *) (p + i), mbedtls_get_unaligned_uint32((void *) (p + i)) & mask); } #endif for (; i < len; i++) { p[i] = p[i] & mask; } } #endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/constant_time_impl.h000066400000000000000000000525231464416617300254040ustar00rootroot00000000000000/** * Constant-time functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_IMPL_H #define MBEDTLS_CONSTANT_TIME_IMPL_H #include #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /* * To improve readability of constant_time_internal.h, the static inline * definitions are here, and constant_time_internal.h has only the declarations. * * This results in duplicate declarations of the form: * static inline void f(); // from constant_time_internal.h * static inline void f() { ... } // from constant_time_impl.h * when constant_time_internal.h is included. * * This appears to behave as if the declaration-without-definition was not present * (except for warnings if gcc -Wredundant-decls or similar is used). * * Disable -Wredundant-decls so that gcc does not warn about this. This is re-enabled * at the bottom of this file. */ #if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wredundant-decls" #endif /* Disable asm under Memsan because it confuses Memsan and generates false errors. * * We also disable under Valgrind by default, because it's more useful * for Valgrind to test the plain C implementation. MBEDTLS_TEST_CONSTANT_FLOW_ASM //no-check-names * may be set to permit building asm under Valgrind. */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) || \ (defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) && !defined(MBEDTLS_TEST_CONSTANT_FLOW_ASM)) //no-check-names #define MBEDTLS_CT_NO_ASM #elif defined(__has_feature) #if __has_feature(memory_sanitizer) #define MBEDTLS_CT_NO_ASM #endif #endif /* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ #if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \ __ARMCC_VERSION >= 6000000) && !defined(MBEDTLS_CT_NO_ASM) #define MBEDTLS_CT_ASM #if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__)) #define MBEDTLS_CT_ARM_ASM #elif defined(__aarch64__) #define MBEDTLS_CT_AARCH64_ASM #elif defined(__amd64__) || defined(__x86_64__) #define MBEDTLS_CT_X86_64_ASM #elif defined(__i386__) #define MBEDTLS_CT_X86_ASM #endif #endif #define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8) /* ============================================================================ * Core const-time primitives */ /* Ensure that the compiler cannot know the value of x (i.e., cannot optimise * based on its value) after this function is called. * * If we are not using assembly, this will be fairly inefficient, so its use * should be minimised. */ #if !defined(MBEDTLS_CT_ASM) extern volatile mbedtls_ct_uint_t mbedtls_ct_zero; #endif /** * \brief Ensure that a value cannot be known at compile time. * * \param x The value to hide from the compiler. * \return The same value that was passed in, such that the compiler * cannot prove its value (even for calls of the form * x = mbedtls_ct_compiler_opaque(1), x will be unknown). * * \note This is mainly used in constructing mbedtls_ct_condition_t * values and performing operations over them, to ensure that * there is no way for the compiler to ever know anything about * the value of an mbedtls_ct_condition_t. */ static inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x) { #if defined(MBEDTLS_CT_ASM) asm volatile ("" : [x] "+r" (x) :); return x; #else return x ^ mbedtls_ct_zero; #endif } /* * Selecting unified syntax is needed for gcc, and harmless on clang. * * This is needed because on Thumb 1, condition flags are always set, so * e.g. "negs" is supported but "neg" is not (on Thumb 2, both exist). * * Under Thumb 1 unified syntax, only the "negs" form is accepted, and * under divided syntax, only the "neg" form is accepted. clang only * supports unified syntax. * * On Thumb 2 and Arm, both compilers are happy with the "s" suffix, * although we don't actually care about setting the flags. * * For old versions of gcc (see #8516 for details), restore divided * syntax afterwards - otherwise old versions of gcc seem to apply * unified syntax globally, which breaks other asm code. */ #if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__thumb__) && !defined(__thumb2__) && \ (__GNUC__ < 11) && !defined(__ARM_ARCH_2__) #define RESTORE_ASM_SYNTAX ".syntax divided \n\t" #else #define RESTORE_ASM_SYNTAX #endif /* Convert a number into a condition in constant time. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x) { /* * Define mask-generation code that, as far as possible, will not use branches or conditional instructions. * * For some platforms / type sizes, we define assembly to assure this. * * Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into * conditional instructions or branches by trunk clang, gcc, or MSVC v19. */ #if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) mbedtls_ct_uint_t s; asm volatile ("neg %x[s], %x[x] \n\t" "orr %x[x], %x[s], %x[x] \n\t" "asr %x[x], %x[x], 63 \n\t" : [s] "=&r" (s), [x] "+&r" (x) : : ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s; asm volatile (".syntax unified \n\t" "negs %[s], %[x] \n\t" "orrs %[x], %[x], %[s] \n\t" "asrs %[x], %[x], #31 \n\t" RESTORE_ASM_SYNTAX : [s] "=&l" (s), [x] "+&l" (x) : : "cc" /* clobbers flag bits */ ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) uint64_t s; asm volatile ("mov %[x], %[s] \n\t" "neg %[s] \n\t" "or %[x], %[s] \n\t" "sar $63, %[s] \n\t" : [s] "=&a" (s) : [x] "D" (x) : ); return (mbedtls_ct_condition_t) s; #elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s; asm volatile ("mov %[x], %[s] \n\t" "neg %[s] \n\t" "or %[s], %[x] \n\t" "sar $31, %[x] \n\t" : [s] "=&c" (s), [x] "+&a" (x) : : ); return (mbedtls_ct_condition_t) x; #else const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x); #if defined(_MSC_VER) /* MSVC has a warning about unary minus on unsigned, but this is * well-defined and precisely what we want to do here */ #pragma warning( push ) #pragma warning( disable : 4146 ) #endif // y is negative (i.e., top bit set) iff x is non-zero mbedtls_ct_int_t y = (-xo) | -(xo >> 1); // extract only the sign bit of y so that y == 1 (if x is non-zero) or 0 (if x is zero) y = (((mbedtls_ct_uint_t) y) >> (MBEDTLS_CT_SIZE - 1)); // -y has all bits set (if x is non-zero), or all bits clear (if x is zero) return (mbedtls_ct_condition_t) (-y); #if defined(_MSC_VER) #pragma warning( pop ) #endif #endif } static inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition, mbedtls_ct_uint_t if1, mbedtls_ct_uint_t if0) { #if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) asm volatile ("and %x[if1], %x[if1], %x[condition] \n\t" "mvn %x[condition], %x[condition] \n\t" "and %x[condition], %x[condition], %x[if0] \n\t" "orr %x[condition], %x[if1], %x[condition]" : [condition] "+&r" (condition), [if1] "+&r" (if1) : [if0] "r" (if0) : ); return (mbedtls_ct_uint_t) condition; #elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) asm volatile (".syntax unified \n\t" "ands %[if1], %[if1], %[condition] \n\t" "mvns %[condition], %[condition] \n\t" "ands %[condition], %[condition], %[if0] \n\t" "orrs %[condition], %[if1], %[condition] \n\t" RESTORE_ASM_SYNTAX : [condition] "+&l" (condition), [if1] "+&l" (if1) : [if0] "l" (if0) : "cc" ); return (mbedtls_ct_uint_t) condition; #elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) asm volatile ("and %[condition], %[if1] \n\t" "not %[condition] \n\t" "and %[condition], %[if0] \n\t" "or %[if1], %[if0] \n\t" : [condition] "+&D" (condition), [if1] "+&S" (if1), [if0] "+&a" (if0) : : ); return if0; #elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) asm volatile ("and %[condition], %[if1] \n\t" "not %[condition] \n\t" "and %[if0], %[condition] \n\t" "or %[condition], %[if1] \n\t" : [condition] "+&c" (condition), [if1] "+&a" (if1) : [if0] "b" (if0) : ); return if1; #else mbedtls_ct_condition_t not_cond = (mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition)); return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0)); #endif } static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { #if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) uint64_t s1; asm volatile ("eor %x[s1], %x[y], %x[x] \n\t" "sub %x[x], %x[x], %x[y] \n\t" "bic %x[x], %x[x], %x[s1] \n\t" "and %x[s1], %x[s1], %x[y] \n\t" "orr %x[s1], %x[x], %x[s1] \n\t" "asr %x[x], %x[s1], 63" : [s1] "=&r" (s1), [x] "+&r" (x) : [y] "r" (y) : ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s1; asm volatile ( ".syntax unified \n\t" #if defined(__thumb__) && !defined(__thumb2__) "movs %[s1], %[x] \n\t" "eors %[s1], %[s1], %[y] \n\t" #else "eors %[s1], %[x], %[y] \n\t" #endif "subs %[x], %[x], %[y] \n\t" "bics %[x], %[x], %[s1] \n\t" "ands %[y], %[s1], %[y] \n\t" "orrs %[x], %[x], %[y] \n\t" "asrs %[x], %[x], #31 \n\t" RESTORE_ASM_SYNTAX : [s1] "=&l" (s1), [x] "+&l" (x), [y] "+&l" (y) : : "cc" ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64)) uint64_t s; asm volatile ("mov %[x], %[s] \n\t" "xor %[y], %[s] \n\t" "sub %[y], %[x] \n\t" "and %[s], %[y] \n\t" "not %[s] \n\t" "and %[s], %[x] \n\t" "or %[y], %[x] \n\t" "sar $63, %[x] \n\t" : [s] "=&a" (s), [x] "+&D" (x), [y] "+&S" (y) : : ); return (mbedtls_ct_condition_t) x; #elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32) uint32_t s; asm volatile ("mov %[x], %[s] \n\t" "xor %[y], %[s] \n\t" "sub %[y], %[x] \n\t" "and %[s], %[y] \n\t" "not %[s] \n\t" "and %[s], %[x] \n\t" "or %[y], %[x] \n\t" "sar $31, %[x] \n\t" : [s] "=&b" (s), [x] "+&a" (x), [y] "+&c" (y) : : ); return (mbedtls_ct_condition_t) x; #else /* Ensure that the compiler cannot optimise the following operations over x and y, * even if it knows the value of x and y. */ const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x); const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y); /* * Check if the most significant bits (MSB) of the operands are different. * cond is true iff the MSBs differ. */ mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1)); /* * If the MSB are the same then the difference x-y will be negative (and * have its MSB set to 1 during conversion to unsigned) if and only if x> (MBEDTLS_CT_SIZE - 1); // Convert to a condition (i.e., all bits set iff non-zero) return mbedtls_ct_bool(ret); #endif } static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { /* diff = 0 if x == y, non-zero otherwise */ const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y); /* all ones if x != y, 0 otherwise */ return mbedtls_ct_bool(diff); } static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char high, unsigned char c, unsigned char t) { const unsigned char co = (unsigned char) mbedtls_ct_compiler_opaque(c); const unsigned char to = (unsigned char) mbedtls_ct_compiler_opaque(t); /* low_mask is: 0 if low <= c, 0x...ff if low > c */ unsigned low_mask = ((unsigned) co - low) >> 8; /* high_mask is: 0 if c <= high, 0x...ff if c > high */ unsigned high_mask = ((unsigned) high - co) >> 8; return (unsigned char) (~(low_mask | high_mask)) & to; } /* ============================================================================ * Everything below here is trivial wrapper functions */ static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition, size_t if1, size_t if0) { return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, unsigned if1, unsigned if0) { return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1, mbedtls_ct_condition_t if0) { return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } #if defined(MBEDTLS_BIGNUM_C) static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, mbedtls_mpi_uint if1, mbedtls_mpi_uint if0) { return (mbedtls_mpi_uint) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } #endif static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1) { return (size_t) (condition & if1); } static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1) { return (unsigned) (condition & if1); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1) { return (mbedtls_ct_condition_t) (condition & if1); } #if defined(MBEDTLS_BIGNUM_C) static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, mbedtls_mpi_uint if1) { return (mbedtls_mpi_uint) (condition & if1); } #endif /* MBEDTLS_BIGNUM_C */ static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) { /* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be * in the range -32767..0, and we require 32-bit int and uint types. * * This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for * converting back to int. */ return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), (mbedtls_ct_uint_t) (-if0))); } static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1) { return -((int) (condition & (-if1))); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return ~mbedtls_ct_uint_ne(x, y); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return mbedtls_ct_uint_lt(y, x); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return ~mbedtls_ct_uint_lt(x, y); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { return ~mbedtls_ct_uint_gt(x, y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x ^ y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x & y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x | y); } static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x) { return (mbedtls_ct_condition_t) (~x); } #if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4) /* Restore warnings for -Wredundant-decls on gcc */ #pragma GCC diagnostic pop #endif #endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/constant_time_internal.h000066400000000000000000000503771464416617300262640ustar00rootroot00000000000000/** * Constant-time functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H #define MBEDTLS_CONSTANT_TIME_INTERNAL_H #include #include #include "common.h" #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif /* The constant-time interface provides various operations that are likely * to result in constant-time code that does not branch or use conditional * instructions for secret data (for secret pointers, this also applies to * the data pointed to). * * It has three main parts: * * - boolean operations * These are all named mbedtls_ct__. * They operate over and return mbedtls_ct_condition_t. * All arguments are considered secret. * example: bool x = y | z => x = mbedtls_ct_bool_or(y, z) * example: bool x = y == z => x = mbedtls_ct_uint_eq(y, z) * * - conditional data selection * These are all named mbedtls_ct__if and mbedtls_ct__if_else_0 * All arguments are considered secret. * example: size_t a = x ? b : c => a = mbedtls_ct_size_if(x, b, c) * example: unsigned a = x ? b : 0 => a = mbedtls_ct_uint_if_else_0(x, b) * * - block memory operations * Only some arguments are considered secret, as documented for each * function. * example: if (x) memcpy(...) => mbedtls_ct_memcpy_if(x, ...) * * mbedtls_ct_condition_t must be treated as opaque and only created and * manipulated via the functions in this header. The compiler should never * be able to prove anything about its value at compile-time. * * mbedtls_ct_uint_t is an unsigned integer type over which constant time * operations may be performed via the functions in this header. It is as big * as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast * to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other * not-larger integer types). * * For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations * are used to ensure that the generated code is constant time. For other * architectures, it uses a plain C fallback designed to yield constant-time code * (this has been observed to be constant-time on latest gcc, clang and MSVC * as of May 2023). * * For readability, the static inline definitions are separated out into * constant_time_impl.h. */ #if (SIZE_MAX > 0xffffffffffffffffULL) /* Pointer size > 64-bit */ typedef size_t mbedtls_ct_condition_t; typedef size_t mbedtls_ct_uint_t; typedef ptrdiff_t mbedtls_ct_int_t; #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX)) #elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64) /* 32-bit < pointer size <= 64-bit, or 64-bit MPI */ typedef uint64_t mbedtls_ct_condition_t; typedef uint64_t mbedtls_ct_uint_t; typedef int64_t mbedtls_ct_int_t; #define MBEDTLS_CT_SIZE_64 #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX)) #else /* Pointer size <= 32-bit, and no 64-bit MPIs */ typedef uint32_t mbedtls_ct_condition_t; typedef uint32_t mbedtls_ct_uint_t; typedef int32_t mbedtls_ct_int_t; #define MBEDTLS_CT_SIZE_32 #define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX)) #endif #define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0)) /* ============================================================================ * Boolean operations */ /** Convert a number into a mbedtls_ct_condition_t. * * \param x Number to convert. * * \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0 * */ static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x); /** Boolean "not equal" operation. * * Functionally equivalent to: * * \p x != \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "equals" operation. * * Functionally equivalent to: * * \p x == \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "less than" operation. * * Functionally equivalent to: * * \p x < \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "greater than" operation. * * Functionally equivalent to: * * \p x > \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "greater or equal" operation. * * Functionally equivalent to: * * \p x >= \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x >= \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean "less than or equal" operation. * * Functionally equivalent to: * * \p x <= \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x <= \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); /** Boolean not-equals operation. * * Functionally equivalent to: * * \p x != \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \note This is more efficient than mbedtls_ct_uint_ne if both arguments are * mbedtls_ct_condition_t. * * \return MBEDTLS_CT_TRUE if \p x != \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y); /** Boolean "and" operation. * * Functionally equivalent to: * * \p x && \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x && \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y); /** Boolean "or" operation. * * Functionally equivalent to: * * \p x || \p y * * \param x The first value to analyze. * \param y The second value to analyze. * * \return MBEDTLS_CT_TRUE if \p x || \p y, * otherwise MBEDTLS_CT_FALSE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x, mbedtls_ct_condition_t y); /** Boolean "not" operation. * * Functionally equivalent to: * * ! \p x * * \param x The value to invert * * \return MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x); /* ============================================================================ * Data selection operations */ /** Choose between two size_t values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition, size_t if1, size_t if0); /** Choose between two unsigned values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, unsigned if1, unsigned if0); /** Choose between two mbedtls_ct_condition_t values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1, mbedtls_ct_condition_t if0); #if defined(MBEDTLS_BIGNUM_C) /** Choose between two mbedtls_mpi_uint values. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \ mbedtls_mpi_uint if1, \ mbedtls_mpi_uint if0); #endif /** Choose between an unsigned value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1); /** Choose between an mbedtls_ct_condition_t and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, mbedtls_ct_condition_t if1); /** Choose between a size_t value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1); #if defined(MBEDTLS_BIGNUM_C) /** Choose between an mbedtls_mpi_uint value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, mbedtls_mpi_uint if1); #endif /** Constant-flow char selection * * \param low Secret. Bottom of range * \param high Secret. Top of range * \param c Secret. Value to compare to range * \param t Secret. Value to return, if in range * * \return \p t if \p low <= \p c <= \p high, 0 otherwise. */ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char high, unsigned char c, unsigned char t); /** Choose between two error values. The values must be in the range [-32767..0]. * * Functionally equivalent to: * * condition ? if1 : if0. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0); /** Choose between an error value and 0. The error value must be in the range [-32767..0]. * * Functionally equivalent to: * * condition ? if1 : 0. * * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but * results in smaller code size. * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1); /* ============================================================================ * Block memory operations */ #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) /** Conditionally set a block of memory to zero. * * Regardless of the condition, every byte will be read once and written to * once. * * \param condition Secret. Condition to test. * \param buf Secret. Pointer to the start of the buffer. * \param len Number of bytes to set to zero. * * \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees * about not being optimised away if the memory is never read again. */ void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len); /** Shift some data towards the left inside a buffer. * * Functionally equivalent to: * * memmove(start, start + offset, total - offset); * memset(start + (total - offset), 0, offset); * * Timing independence comes at the expense of performance. * * \param start Secret. Pointer to the start of the buffer. * \param total Total size of the buffer. * \param offset Secret. Offset from which to copy \p total - \p offset bytes. */ void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset); #endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */ /** Conditional memcpy. * * Functionally equivalent to: * * if (condition) { * memcpy(dest, src1, len); * } else { * if (src2 != NULL) * memcpy(dest, src2, len); * } * * It will always read len bytes from src1. * If src2 != NULL, it will always read len bytes from src2. * If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest). * * \param condition The condition * \param dest Secret. Destination pointer. * \param src1 Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE). * This may be equal to \p dest, but may not overlap in other ways. * \param src2 Secret (contents only - may branch to determine if this parameter is NULL). * Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL. * This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1. * \param len Number of bytes to copy. */ void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition, unsigned char *dest, const unsigned char *src1, const unsigned char *src2, size_t len ); /** Copy data from a secret position. * * Functionally equivalent to: * * memcpy(dst, src + offset, len) * * This function copies \p len bytes from \p src + \p offset to * \p dst, with a code flow and memory access pattern that does not depend on * \p offset, but only on \p offset_min, \p offset_max and \p len. * * \note This function reads from \p dest, but the value that * is read does not influence the result and this * function's behavior is well-defined regardless of the * contents of the buffers. This may result in false * positives from static or dynamic analyzers, especially * if \p dest is not initialized. * * \param dest Secret. The destination buffer. This must point to a writable * buffer of at least \p len bytes. * \param src Secret. The base of the source buffer. This must point to a * readable buffer of at least \p offset_max + \p len * bytes. Shouldn't overlap with \p dest * \param offset Secret. The offset in the source buffer from which to copy. * This must be no less than \p offset_min and no greater * than \p offset_max. * \param offset_min The minimal value of \p offset. * \param offset_max The maximal value of \p offset. * \param len The number of bytes to copy. */ void mbedtls_ct_memcpy_offset(unsigned char *dest, const unsigned char *src, size_t offset, size_t offset_min, size_t offset_max, size_t len); /* Documented in include/mbedtls/constant_time.h. a and b are secret. int mbedtls_ct_memcmp(const void *a, const void *b, size_t n); */ #if defined(MBEDTLS_NIST_KW_C) /** Constant-time buffer comparison without branches. * * Similar to mbedtls_ct_memcmp, except that the result only depends on part of * the input data - differences in the head or tail are ignored. Functionally equivalent to: * * memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail) * * Time taken depends on \p n, but not on \p skip_head or \p skip_tail . * * Behaviour is undefined if ( \p skip_head + \p skip_tail) > \p n. * * \param a Secret. Pointer to the first buffer, containing at least \p n bytes. May not be NULL. * \param b Secret. Pointer to the second buffer, containing at least \p n bytes. May not be NULL. * \param n The number of bytes to examine (total size of the buffers). * \param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer. * These bytes will still be read. * \param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer. * These bytes will still be read. * * \return Zero if the contents of the two buffers are the same, otherwise non-zero. */ int mbedtls_ct_memcmp_partial(const void *a, const void *b, size_t n, size_t skip_head, size_t skip_tail); #endif /* Include the implementation of static inline functions above. */ #include "constant_time_impl.h" #endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ctr.h000066400000000000000000000016631464416617300223030ustar00rootroot00000000000000/** * \file ctr.h * * \brief This file contains common functionality for counter algorithms. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_CTR_H #define MBEDTLS_CTR_H #include "common.h" /** * \brief Increment a big-endian 16-byte value. * This is quite performance-sensitive for AES-CTR and CTR-DRBG. * * \param n A 16-byte value to be incremented. */ static inline void mbedtls_ctr_increment_counter(uint8_t n[16]) { // The 32-bit version seems to perform about the same as a 64-bit version // on 64-bit architectures, so no need to define a 64-bit version. for (int i = 3;; i--) { uint32_t x = MBEDTLS_GET_UINT32_BE(n, i << 2); x += 1; MBEDTLS_PUT_UINT32_BE(x, n, i << 2); if (x != 0 || i == 0) { break; } } } #endif /* MBEDTLS_CTR_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ctr_drbg.c000066400000000000000000000770531464416617300233020ustar00rootroot00000000000000/* * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The NIST SP 800-90 DRBGs are described in the following publication. * * https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf */ #include "common.h" #if defined(MBEDTLS_CTR_DRBG_C) #include "ctr.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_FS_IO) #include #endif /* Using error translation functions from PSA to MbedTLS */ #if !defined(MBEDTLS_AES_C) #include "psa_util_internal.h" #endif #include "mbedtls/platform.h" #if !defined(MBEDTLS_AES_C) static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx, unsigned char *key, size_t key_len) { psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES); status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id); if (status != PSA_SUCCESS) { goto exit; } status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING); if (status != PSA_SUCCESS) { goto exit; } exit: psa_reset_key_attributes(&key_attr); return status; } static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx) { psa_cipher_abort(&psa_ctx->operation); psa_destroy_key(psa_ctx->key_id); psa_ctx->operation = psa_cipher_operation_init(); psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT; } #endif /* * CTR_DRBG context initialization */ void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); #if defined(MBEDTLS_AES_C) mbedtls_aes_init(&ctx->aes_ctx); #else ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; ctx->psa_ctx.operation = psa_cipher_operation_init(); #endif /* Indicate that the entropy nonce length is not set explicitly. * See mbedtls_ctr_drbg_set_nonce_len(). */ ctx->reseed_counter = -1; ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; } /* * This function resets CTR_DRBG context to the state immediately * after initial call of mbedtls_ctr_drbg_init(). */ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_THREADING_C) /* The mutex is initialized iff f_entropy is set. */ if (ctx->f_entropy != NULL) { mbedtls_mutex_free(&ctx->mutex); } #endif #if defined(MBEDTLS_AES_C) mbedtls_aes_free(&ctx->aes_ctx); #else ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context)); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; ctx->reseed_counter = -1; } void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, int resistance) { ctx->prediction_resistance = resistance; } void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, size_t len) { ctx->entropy_len = len; } int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, size_t len) { /* If mbedtls_ctr_drbg_seed() has already been called, it's * too late. Return the error code that's closest to making sense. */ if (ctx->f_entropy != NULL) { return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } /* This shouldn't be an issue because * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible * configuration, but make sure anyway. */ if (len > INT_MAX) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } /* For backward compatibility with Mbed TLS <= 2.19, store the * entropy nonce length in a field that already exists, but isn't * used until after the initial seeding. */ /* Due to the capping of len above, the value fits in an int. */ ctx->reseed_counter = (int) len; return 0; } void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, int interval) { ctx->reseed_interval = interval; } static int block_cipher_df(unsigned char *output, const unsigned char *data, size_t data_len) { unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; unsigned char *p, *iv; int ret = 0; #if defined(MBEDTLS_AES_C) mbedtls_aes_context aes_ctx; #else psa_status_t status; size_t tmp_len; mbedtls_ctr_drbg_psa_context psa_ctx; psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_ctx.operation = psa_cipher_operation_init(); #endif int i, j; size_t buf_len, use_len; if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16); /* * Construct IV (16 bytes) and S in buffer * IV = Counter (in 32-bits) padded to 16 with zeroes * S = Length input string (in 32-bits) || Length of output (in 32-bits) || * data || 0x80 * (Total is padded to a multiple of 16-bytes with zeroes) */ p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; MBEDTLS_PUT_UINT32_BE(data_len, p, 0); p += 4 + 3; *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; memcpy(p, data, data_len); p[data_len] = 0x80; buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) { key[i] = i; } #if defined(MBEDTLS_AES_C) mbedtls_aes_init(&aes_ctx); if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } #else status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key)); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif /* * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data */ for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { p = buf; memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE); use_len = buf_len; while (use_len > 0) { mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain)) != 0) { goto exit; } #else status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif } memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE); /* * Update IV */ buf[3]++; } /* * Do final encryption with reduced data */ #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } #else ctr_drbg_destroy_psa_contex(&psa_ctx); status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; p = output; for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv)) != 0) { goto exit; } #else status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE); p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } exit: #if defined(MBEDTLS_AES_C) mbedtls_aes_free(&aes_ctx); #else ctr_drbg_destroy_psa_contex(&psa_ctx); #endif /* * tidy up the stack */ mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(tmp, sizeof(tmp)); mbedtls_platform_zeroize(key, sizeof(key)); mbedtls_platform_zeroize(chain, sizeof(chain)); if (0 != ret) { /* * wipe partial seed from memory */ mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN); } return ret; } /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) * ctr_drbg_update_internal(ctx, provided_data) * implements * CTR_DRBG_Update(provided_data, Key, V) * with inputs and outputs * ctx->aes_ctx = Key * ctx->counter = V */ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN]) { unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char *p = tmp; int j; int ret = 0; #if !defined(MBEDTLS_AES_C) psa_status_t status; size_t tmp_len; #endif memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN); for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { /* * Increase counter */ mbedtls_ctr_increment_counter(ctx->counter); /* * Crypt counter block */ #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p)) != 0) { goto exit; } #else status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif p += MBEDTLS_CTR_DRBG_BLOCKSIZE; } mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN); /* * Update key and counter */ #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { goto exit; } #else ctr_drbg_destroy_psa_contex(&ctx->psa_ctx); status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE); exit: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) * mbedtls_ctr_drbg_update(ctx, additional, add_len) * implements * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, * security_strength) -> initial_working_state * with inputs * ctx->counter = all-bits-0 * ctx->aes_ctx = context from all-bits-0 key * additional[:add_len] = entropy_input || nonce || personalization_string * and with outputs * ctx = initial_working_state */ int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len) { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (add_len == 0) { return 0; } if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { goto exit; } if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { goto exit; } exit: mbedtls_platform_zeroize(add_input, sizeof(add_input)); return ret; } /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) * implements * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) * -> new_working_state * with inputs * ctx contains working_state * additional[:len] = additional_input * and entropy_input comes from calling ctx->f_entropy * for (ctx->entropy_len + nonce_len) bytes * and with output * ctx contains new_working_state */ static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len, size_t nonce_len) { unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; size_t seedlen = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT); /* Gather entropy_len bytes of entropy to seed state. */ if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) { return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += ctx->entropy_len; /* Gather entropy for a nonce if requested. */ if (nonce_len != 0) { if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) { return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += nonce_len; } /* Add additional data if provided. */ if (additional != NULL && len != 0) { memcpy(seed + seedlen, additional, len); seedlen += len; } /* Reduce to 384 bits. */ if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) { goto exit; } /* Update state. */ if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) { goto exit; } ctx->reseed_counter = 1; exit: mbedtls_platform_zeroize(seed, sizeof(seed)); return ret; } int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, const unsigned char *additional, size_t len) { return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0); } /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length * is sufficient to achieve the maximum security strength given the key * size and entropy length. If there is enough entropy in the initial * call to the entropy function to serve as both the entropy input and * the nonce, don't make a second call to get a nonce. */ static size_t good_nonce_len(size_t entropy_len) { if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) { return 0; } else { return (entropy_len + 1) / 2; } } /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) * implements * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, * security_strength) -> initial_working_state * with inputs * custom[:len] = nonce || personalization_string * where entropy_input comes from f_entropy for ctx->entropy_len bytes * and with outputs * ctx = initial_working_state */ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; size_t nonce_len; memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE); /* The mutex is initialized iff f_entropy is set. */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; if (ctx->entropy_len == 0) { ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; } /* ctx->reseed_counter contains the desired amount of entropy to * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). * If it's -1, indicating that the entropy nonce length was not set * explicitly, use a sufficiently large nonce for security. */ nonce_len = (ctx->reseed_counter >= 0 ? (size_t) ctx->reseed_counter : good_nonce_len(ctx->entropy_len)); /* Initialize with an empty key. */ #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { return ret; } #else psa_status_t status; status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); return status; } #endif /* Do the initial seeding. */ if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, nonce_len)) != 0) { return ret; } return 0; } /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) * implements * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) * -> working_state_after_reseed * if required, then * CTR_DRBG_Generate(working_state_after_reseed, * requested_number_of_bits, additional_input) * -> status, returned_bits, new_working_state * with inputs * ctx contains working_state * requested_number_of_bits = 8 * output_len * additional[:add_len] = additional_input * and entropy_input comes from calling ctx->f_entropy * and with outputs * status = SUCCESS (this function does the reseed internally) * returned_bits = output[:output_len] * ctx contains new_working_state */ int mbedtls_ctr_drbg_random_with_add(void *p_rng, unsigned char *output, size_t output_len, const unsigned char *additional, size_t add_len) { int ret = 0; mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; unsigned char *p = output; struct { unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; } locals; size_t use_len; if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) { return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG; } if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) { return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; } memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); if (ctx->reseed_counter > ctx->reseed_interval || ctx->prediction_resistance) { if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) { return ret; } add_len = 0; } if (add_len > 0) { if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) { goto exit; } if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { goto exit; } } while (output_len > 0) { /* * Increase counter (treat it as a 128-bit big-endian integer). */ mbedtls_ctr_increment_counter(ctx->counter); /* * Crypt counter block */ #if defined(MBEDTLS_AES_C) if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, locals.tmp)) != 0) { goto exit; } #else psa_status_t status; size_t tmp_len; status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter), locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len); if (status != PSA_SUCCESS) { ret = psa_generic_status_to_mbedtls(status); goto exit; } #endif use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; /* * Copy random block to destination */ memcpy(p, locals.tmp, use_len); p += use_len; output_len -= use_len; } if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) { goto exit; } ctx->reseed_counter++; exit: mbedtls_platform_zeroize(&locals, sizeof(locals)); return ret; } int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, size_t output_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } #if defined(MBEDTLS_FS_IO) int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path) { int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; FILE *f; unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; if ((f = fopen(path, "wb")) == NULL) { return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); if ((ret = mbedtls_ctr_drbg_random(ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) { goto exit; } if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) != MBEDTLS_CTR_DRBG_MAX_INPUT) { ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } else { ret = 0; } exit: mbedtls_platform_zeroize(buf, sizeof(buf)); fclose(f); return ret; } int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path) { int ret = 0; FILE *f = NULL; size_t n; unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; unsigned char c; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); n = fread(buf, 1, sizeof(buf), f); if (fread(&c, 1, 1, f) != 0) { ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; goto exit; } if (n == 0 || ferror(f)) { ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; goto exit; } fclose(f); f = NULL; ret = mbedtls_ctr_drbg_update(ctx, buf, n); exit: mbedtls_platform_zeroize(buf, sizeof(buf)); if (f != NULL) { fclose(f); } if (ret != 0) { return ret; } return mbedtls_ctr_drbg_write_seed_file(ctx, path); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /* The CTR_DRBG NIST test vectors used here are available at * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip * * The parameters used to derive the test data are: * * [AES-128 use df] * [PredictionResistance = True/False] * [EntropyInputLen = 128] * [NonceLen = 64] * [PersonalizationStringLen = 128] * [AdditionalInputLen = 0] * [ReturnedBitsLen = 512] * * [AES-256 use df] * [PredictionResistance = True/False] * [EntropyInputLen = 256] * [NonceLen = 128] * [PersonalizationStringLen = 256] * [AdditionalInputLen = 0] * [ReturnedBitsLen = 512] * */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) static const unsigned char entropy_source_pr[] = { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; static const unsigned char entropy_source_nopr[] = { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; static const unsigned char pers_pr[] = { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; static const unsigned char pers_nopr[] = { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; static const unsigned char result_pr[] = { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; static const unsigned char result_nopr[] = { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ static const unsigned char entropy_source_pr[] = { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; static const unsigned char entropy_source_nopr[] = { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; static const unsigned char pers_pr[] = { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; static const unsigned char pers_nopr[] = { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; static const unsigned char result_pr[] = { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; static const unsigned char result_nopr[] = { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ static size_t test_offset; static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf, size_t len) { const unsigned char *p = data; memcpy(buf, p + test_offset, len); test_offset += len; return 0; } #define CHK(c) if ((c) != 0) \ { \ if (verbose != 0) \ mbedtls_printf("failed\n"); \ return 1; \ } #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 /* * Checkup routine */ int mbedtls_ctr_drbg_self_test(int verbose) { mbedtls_ctr_drbg_context ctx; unsigned char buf[sizeof(result_pr)]; mbedtls_ctr_drbg_init(&ctx); /* * Based on a NIST CTR_DRBG test vector (PR = True) */ if (verbose != 0) { mbedtls_printf(" CTR_DRBG (PR = TRUE) : "); } test_offset = 0; mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); CHK(mbedtls_ctr_drbg_seed(&ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_pr, pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE)); mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON); CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr))); CHK(memcmp(buf, result_pr, sizeof(result_pr))); mbedtls_ctr_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } /* * Based on a NIST CTR_DRBG test vector (PR = FALSE) */ if (verbose != 0) { mbedtls_printf(" CTR_DRBG (PR = FALSE): "); } mbedtls_ctr_drbg_init(&ctx); test_offset = 0; mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); CHK(mbedtls_ctr_drbg_seed(&ctx, ctr_drbg_self_test_entropy, (void *) entropy_source_nopr, pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE)); CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0)); CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr))); CHK(memcmp(buf, result_nopr, sizeof(result_nopr))); mbedtls_ctr_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_CTR_DRBG_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/debug.c000066400000000000000000000343541464416617300225770ustar00rootroot00000000000000/* * Debugging routines * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_DEBUG_C) #include "mbedtls/platform.h" #include "debug_internal.h" #include "mbedtls/error.h" #include #include #include /* DEBUG_BUF_SIZE must be at least 2 */ #define DEBUG_BUF_SIZE 512 static int debug_threshold = 0; void mbedtls_debug_set_threshold(int threshold) { debug_threshold = threshold; } /* * All calls to f_dbg must be made via this function */ static inline void debug_send_line(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *str) { /* * If in a threaded environment, we need a thread identifier. * Since there is no portable way to get one, use the address of the ssl * context instead, as it shouldn't be shared between threads. */ #if defined(MBEDTLS_THREADING_C) char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *) ssl, str); ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr); #else ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str); #endif } MBEDTLS_PRINTF_ATTRIBUTE(5, 6) void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *format, ...) { va_list argp; char str[DEBUG_BUF_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, "DEBUG_BUF_SIZE too small"); if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } va_start(argp, format); ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp); va_end(argp); if (ret < 0) { ret = 0; } else { if (ret >= DEBUG_BUF_SIZE - 1) { ret = DEBUG_BUF_SIZE - 2; } } str[ret] = '\n'; str[ret + 1] = '\0'; debug_send_line(ssl, level, file, line, str); } void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, int ret) { char str[DEBUG_BUF_SIZE]; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } /* * With non-blocking I/O and examples that just retry immediately, * the logs would be quickly flooded with WANT_READ, so ignore that. * Don't ignore WANT_WRITE however, since it is usually rare. */ if (ret == MBEDTLS_ERR_SSL_WANT_READ) { return; } mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)\n", text, ret, (unsigned int) -ret); debug_send_line(ssl, level, file, line, str); } void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const unsigned char *buf, size_t len) { char str[DEBUG_BUF_SIZE]; char txt[17]; size_t i, idx = 0; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)\n", text, (unsigned int) len); debug_send_line(ssl, level, file, line, str); memset(txt, 0, sizeof(txt)); for (i = 0; i < len; i++) { if (i >= 4096) { break; } if (i % 16 == 0) { if (i > 0) { mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s\n", txt); debug_send_line(ssl, level, file, line, str); idx = 0; memset(txt, 0, sizeof(txt)); } idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ", (unsigned int) i); } idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", (unsigned int) buf[i]); txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.'; } if (len > 0) { for (/* i = i */; i % 16 != 0; i++) { idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " "); } mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s\n", txt); debug_send_line(ssl, level, file, line, str); } } #if defined(MBEDTLS_ECP_LIGHT) void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_ecp_point *X) { char str[DEBUG_BUF_SIZE]; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } mbedtls_snprintf(str, sizeof(str), "%s(X)", text); mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X); mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y); } #endif /* MBEDTLS_ECP_LIGHT */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const unsigned char *buf, size_t len) { char str[DEBUG_BUF_SIZE]; size_t i, idx = 0; mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n", text, (unsigned int) len * 8); debug_send_line(ssl, level, file, line, str); for (i = 0; i < len; i++) { if (i >= 4096) { break; } if (i % 16 == 0) { if (i > 0) { mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); idx = 0; } } idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", (unsigned int) buf[i]); } if (len > 0) { for (/* i = i */; i % 16 != 0; i++) { idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " "); } mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); } } void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_pk_context *pk) { char str[DEBUG_BUF_SIZE]; const uint8_t *coord_start; size_t coord_len; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold) { return; } /* For the description of pk->pk_raw content please refer to the description * psa_export_public_key() function. */ coord_len = (pk->pub_raw_len - 1)/2; /* X coordinate */ coord_start = pk->pub_raw + 1; mbedtls_snprintf(str, sizeof(str), "%s(X)", text); mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len); /* Y coordinate */ coord_start = coord_start + coord_len; mbedtls_snprintf(str, sizeof(str), "%s(Y)", text); mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #if defined(MBEDTLS_BIGNUM_C) void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_mpi *X) { char str[DEBUG_BUF_SIZE]; size_t bitlen; size_t idx = 0; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || NULL == X || level > debug_threshold) { return; } bitlen = mbedtls_mpi_bitlen(X); mbedtls_snprintf(str, sizeof(str), "value of '%s' (%u bits) is:\n", text, (unsigned) bitlen); debug_send_line(ssl, level, file, line, str); if (bitlen == 0) { str[0] = ' '; str[1] = '0'; str[2] = '0'; idx = 3; } else { int n; for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) { size_t limb_offset = n / sizeof(mbedtls_mpi_uint); size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint); unsigned char octet = (X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff; mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", octet); idx += 3; /* Wrap lines after 16 octets that each take 3 columns */ if (idx >= 3 * 16) { mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); idx = 0; } } } if (idx != 0) { mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n"); debug_send_line(ssl, level, file, line, str); } } #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) static void debug_print_pk(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_pk_context *pk) { size_t i; mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; char name[16]; memset(items, 0, sizeof(items)); if (mbedtls_pk_debug(pk, items) != 0) { debug_send_line(ssl, level, file, line, "invalid PK context\n"); return; } for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) { if (items[i].type == MBEDTLS_PK_DEBUG_NONE) { return; } mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name); name[sizeof(name) - 1] = '\0'; #if defined(MBEDTLS_RSA_C) if (items[i].type == MBEDTLS_PK_DEBUG_MPI) { mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value); } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_LIGHT) if (items[i].type == MBEDTLS_PK_DEBUG_ECP) { mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value); } else #endif /* MBEDTLS_ECP_LIGHT */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) { mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value); } else #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ { debug_send_line(ssl, level, file, line, "should not happen\n"); } } } static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text) { char str[DEBUG_BUF_SIZE]; const char *start, *cur; start = text; for (cur = text; *cur != '\0'; cur++) { if (*cur == '\n') { size_t len = (size_t) (cur - start) + 1; if (len > DEBUG_BUF_SIZE - 1) { len = DEBUG_BUF_SIZE - 1; } memcpy(str, start, len); str[len] = '\0'; debug_send_line(ssl, level, file, line, str); start = cur + 1; } } } void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_x509_crt *crt) { char str[DEBUG_BUF_SIZE]; int i = 0; if (NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || NULL == crt || level > debug_threshold) { return; } while (crt != NULL) { char buf[1024]; mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i); debug_send_line(ssl, level, file, line, str); mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); debug_print_line_by_line(ssl, level, file, line, buf); debug_print_pk(ssl, level, file, line, "crt->", &crt->pk); crt = crt->next; } } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \ defined(MBEDTLS_ECDH_C) static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const mbedtls_ecdh_context *ecdh, mbedtls_debug_ecdh_attr attr) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) const mbedtls_ecdh_context *ctx = ecdh; #else const mbedtls_ecdh_context_mbed *ctx = &ecdh->ctx.mbed_ecdh; #endif switch (attr) { case MBEDTLS_DEBUG_ECDH_Q: mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Q", &ctx->Q); break; case MBEDTLS_DEBUG_ECDH_QP: mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Qp", &ctx->Qp); break; case MBEDTLS_DEBUG_ECDH_Z: mbedtls_debug_print_mpi(ssl, level, file, line, "ECDH: z", &ctx->z); break; default: break; } } void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const mbedtls_ecdh_context *ecdh, mbedtls_debug_ecdh_attr attr) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr); #else switch (ecdh->var) { default: mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr); } #endif } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED && MBEDTLS_ECDH_C */ #endif /* MBEDTLS_DEBUG_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/debug_internal.h000066400000000000000000000160331464416617300244720ustar00rootroot00000000000000/** * \file debug_internal.h * * \brief Internal part of the public "debug.h". */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_DEBUG_INTERNAL_H #define MBEDTLS_DEBUG_INTERNAL_H #include "mbedtls/debug.h" /** * \brief Print a message to the debug output. This function is always used * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl * context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the message has occurred in * \param line line number the message has occurred at * \param format format specifier, in printf format * \param ... variables used by the format specifier * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6); /** * \brief Print the return value of a function to the debug output. This * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, * which supplies the ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text the name of the function that returned the error * \param ret the return code value * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, int ret); /** * \brief Output a buffer of size len bytes to the debug output. This function * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, * which supplies the ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the buffer being dumped. Normally the * variable or buffer name * \param buf the buffer to be outputted * \param len length of the buffer * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const unsigned char *buf, size_t len); #if defined(MBEDTLS_BIGNUM_C) /** * \brief Print a MPI variable to the debug output. This function is always * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the * ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the MPI being output. Normally the * variable name * \param X the MPI variable * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_mpi *X); #endif #if defined(MBEDTLS_ECP_LIGHT) /** * \brief Print an ECP point to the debug output. This function is always * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the * ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the ECP point being output. Normally the * variable name * \param X the ECP point * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_ecp_point *X); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) /** * \brief Print a X.509 certificate structure to the debug output. This * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, * which supplies the ssl context, file and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param text a name or label for the certificate being output * \param crt X.509 certificate structure * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const char *text, const mbedtls_x509_crt *crt); #endif /* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function only works for the built-in implementation. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \ defined(MBEDTLS_ECDH_C) typedef enum { MBEDTLS_DEBUG_ECDH_Q, MBEDTLS_DEBUG_ECDH_QP, MBEDTLS_DEBUG_ECDH_Z, } mbedtls_debug_ecdh_attr; /** * \brief Print a field of the ECDH structure in the SSL context to the debug * output. This function is always used through the * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file * and line number parameters. * * \param ssl SSL context * \param level error level of the debug message * \param file file the error has occurred in * \param line line number the error has occurred in * \param ecdh the ECDH context * \param attr the identifier of the attribute being output * * \attention This function is intended for INTERNAL usage within the * library only. */ void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level, const char *file, int line, const mbedtls_ecdh_context *ecdh, mbedtls_debug_ecdh_attr attr); #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED && MBEDTLS_ECDH_C */ #endif /* MBEDTLS_DEBUG_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/des.c000066400000000000000000000766321464416617300222710ustar00rootroot00000000000000/* * FIPS-46-3 compliant Triple-DES implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * DES, on which TDES is based, was originally designed by Horst Feistel * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). * * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf */ #include "common.h" #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_DES_ALT) /* * Expanded DES S-boxes */ static const uint32_t SB1[64] = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, 0x00010400, 0x00000000, 0x01010004 }; static const uint32_t SB2[64] = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, 0x80100020, 0x80108020, 0x00108000 }; static const uint32_t SB3[64] = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, 0x00000008, 0x08020008, 0x00020200 }; static const uint32_t SB4[64] = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002000, 0x00802080 }; static const uint32_t SB5[64] = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, 0x40080000, 0x02080100, 0x40000100 }; static const uint32_t SB6[64] = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, 0x20000000, 0x00400010, 0x20004010 }; static const uint32_t SB7[64] = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, 0x04000800, 0x00000800, 0x00200002 }; static const uint32_t SB8[64] = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, 0x00040040, 0x10000000, 0x10041000 }; /* * PC1: left and right halves bit-swap */ static const uint32_t LHs[16] = { 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00010000, 0x00010001, 0x00010100, 0x00010101, 0x01000000, 0x01000001, 0x01000100, 0x01000101, 0x01010000, 0x01010001, 0x01010100, 0x01010101 }; static const uint32_t RHs[16] = { 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, 0x01010101, }; /* * Initial Permutation macro */ #define DES_IP(X, Y) \ do \ { \ T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ } while (0) /* * Final Permutation macro */ #define DES_FP(X, Y) \ do \ { \ (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ } while (0) /* * DES round macro */ #define DES_ROUND(X, Y) \ do \ { \ T = *SK++ ^ (X); \ (Y) ^= SB8[(T) & 0x3F] ^ \ SB6[(T >> 8) & 0x3F] ^ \ SB4[(T >> 16) & 0x3F] ^ \ SB2[(T >> 24) & 0x3F]; \ \ T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ (Y) ^= SB7[(T) & 0x3F] ^ \ SB5[(T >> 8) & 0x3F] ^ \ SB3[(T >> 16) & 0x3F] ^ \ SB1[(T >> 24) & 0x3F]; \ } while (0) #define SWAP(a, b) \ do \ { \ uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ } while (0) void mbedtls_des_init(mbedtls_des_context *ctx) { memset(ctx, 0, sizeof(mbedtls_des_context)); } void mbedtls_des_free(mbedtls_des_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des_context)); } void mbedtls_des3_init(mbedtls_des3_context *ctx) { memset(ctx, 0, sizeof(mbedtls_des3_context)); } void mbedtls_des3_free(mbedtls_des3_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_des3_context)); } static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, 254 }; void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) { key[i] = odd_parity_table[key[i] / 2]; } } /* * Check the given key's parity, returns 1 on failure, 0 on SUCCESS */ int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; for (i = 0; i < MBEDTLS_DES_KEY_SIZE; i++) { if (key[i] != odd_parity_table[key[i] / 2]) { return 1; } } return 0; } /* * Table of weak and semi-weak keys * * Source: http://en.wikipedia.org/wiki/Weak_key * * Weak: * Alternating ones + zeros (0x0101010101010101) * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) * '0xE0E0E0E0F1F1F1F1' * '0x1F1F1F1F0E0E0E0E' * * Semi-weak: * 0x011F011F010E010E and 0x1F011F010E010E01 * 0x01E001E001F101F1 and 0xE001E001F101F101 * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 * */ #define WEAK_KEY_COUNT 16 static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } }; int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; for (i = 0; i < WEAK_KEY_COUNT; i++) { if (memcmp(weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0) { return 1; } } return 0; } #if !defined(MBEDTLS_DES_SETKEY_ALT) void mbedtls_des_setkey(uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; uint32_t X, Y, T; X = MBEDTLS_GET_UINT32_BE(key, 0); Y = MBEDTLS_GET_UINT32_BE(key, 4); /* * Permuted Choice 1 */ T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); T = ((Y) ^ X) & 0x10101010; X ^= T; Y ^= (T); X = (LHs[(X) & 0xF] << 3) | (LHs[(X >> 8) & 0xF] << 2) | (LHs[(X >> 16) & 0xF] << 1) | (LHs[(X >> 24) & 0xF]) | (LHs[(X >> 5) & 0xF] << 7) | (LHs[(X >> 13) & 0xF] << 6) | (LHs[(X >> 21) & 0xF] << 5) | (LHs[(X >> 29) & 0xF] << 4); Y = (RHs[(Y >> 1) & 0xF] << 3) | (RHs[(Y >> 9) & 0xF] << 2) | (RHs[(Y >> 17) & 0xF] << 1) | (RHs[(Y >> 25) & 0xF]) | (RHs[(Y >> 4) & 0xF] << 7) | (RHs[(Y >> 12) & 0xF] << 6) | (RHs[(Y >> 20) & 0xF] << 5) | (RHs[(Y >> 28) & 0xF] << 4); X &= 0x0FFFFFFF; Y &= 0x0FFFFFFF; /* * calculate subkeys */ for (i = 0; i < 16; i++) { if (i < 2 || i == 8 || i == 15) { X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; } else { X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; } *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) | ((Y >> 14) & 0x00000200) | ((Y) & 0x00000100) | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) | ((Y) & 0x00000200) | ((Y << 7) & 0x00000100) | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); } } #endif /* !MBEDTLS_DES_SETKEY_ALT */ /* * DES key schedule (56-bit, encryption) */ int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { mbedtls_des_setkey(ctx->sk, key); return 0; } /* * DES key schedule (56-bit, decryption) */ int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]) { int i; mbedtls_des_setkey(ctx->sk, key); for (i = 0; i < 16; i += 2) { SWAP(ctx->sk[i], ctx->sk[30 - i]); SWAP(ctx->sk[i + 1], ctx->sk[31 - i]); } return 0; } static void des3_set2key(uint32_t esk[96], uint32_t dsk[96], const unsigned char key[MBEDTLS_DES_KEY_SIZE*2]) { int i; mbedtls_des_setkey(esk, key); mbedtls_des_setkey(dsk + 32, key + 8); for (i = 0; i < 32; i += 2) { dsk[i] = esk[30 - i]; dsk[i + 1] = esk[31 - i]; esk[i + 32] = dsk[62 - i]; esk[i + 33] = dsk[63 - i]; esk[i + 64] = esk[i]; esk[i + 65] = esk[i + 1]; dsk[i + 64] = dsk[i]; dsk[i + 65] = dsk[i + 1]; } } /* * Triple-DES key schedule (112-bit, encryption) */ int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]) { uint32_t sk[96]; des3_set2key(ctx->sk, sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } /* * Triple-DES key schedule (112-bit, decryption) */ int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]) { uint32_t sk[96]; des3_set2key(sk, ctx->sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } static void des3_set3key(uint32_t esk[96], uint32_t dsk[96], const unsigned char key[24]) { int i; mbedtls_des_setkey(esk, key); mbedtls_des_setkey(dsk + 32, key + 8); mbedtls_des_setkey(esk + 64, key + 16); for (i = 0; i < 32; i += 2) { dsk[i] = esk[94 - i]; dsk[i + 1] = esk[95 - i]; esk[i + 32] = dsk[62 - i]; esk[i + 33] = dsk[63 - i]; dsk[i + 64] = esk[30 - i]; dsk[i + 65] = esk[31 - i]; } } /* * Triple-DES key schedule (168-bit, encryption) */ int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]) { uint32_t sk[96]; des3_set3key(ctx->sk, sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } /* * Triple-DES key schedule (168-bit, decryption) */ int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]) { uint32_t sk[96]; des3_set3key(sk, ctx->sk, key); mbedtls_platform_zeroize(sk, sizeof(sk)); return 0; } /* * DES-ECB block encryption/decryption */ #if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, const unsigned char input[8], unsigned char output[8]) { int i; uint32_t X, Y, T, *SK; SK = ctx->sk; X = MBEDTLS_GET_UINT32_BE(input, 0); Y = MBEDTLS_GET_UINT32_BE(input, 4); DES_IP(X, Y); for (i = 0; i < 8; i++) { DES_ROUND(Y, X); DES_ROUND(X, Y); } DES_FP(Y, X); MBEDTLS_PUT_UINT32_BE(Y, output, 0); MBEDTLS_PUT_UINT32_BE(X, output, 4); return 0; } #endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * DES-CBC buffer encryption/decryption */ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[8]; if (length % 8) { return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_DES_ENCRYPT) { while (length > 0) { mbedtls_xor(output, input, iv, 8); ret = mbedtls_des_crypt_ecb(ctx, output, output); if (ret != 0) { goto exit; } memcpy(iv, output, 8); input += 8; output += 8; length -= 8; } } else { /* MBEDTLS_DES_DECRYPT */ while (length > 0) { memcpy(temp, input, 8); ret = mbedtls_des_crypt_ecb(ctx, input, output); if (ret != 0) { goto exit; } mbedtls_xor(output, output, iv, 8); memcpy(iv, temp, 8); input += 8; output += 8; length -= 8; } } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ /* * 3DES-ECB block encryption/decryption */ #if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, const unsigned char input[8], unsigned char output[8]) { int i; uint32_t X, Y, T, *SK; SK = ctx->sk; X = MBEDTLS_GET_UINT32_BE(input, 0); Y = MBEDTLS_GET_UINT32_BE(input, 4); DES_IP(X, Y); for (i = 0; i < 8; i++) { DES_ROUND(Y, X); DES_ROUND(X, Y); } for (i = 0; i < 8; i++) { DES_ROUND(X, Y); DES_ROUND(Y, X); } for (i = 0; i < 8; i++) { DES_ROUND(Y, X); DES_ROUND(X, Y); } DES_FP(Y, X); MBEDTLS_PUT_UINT32_BE(Y, output, 0); MBEDTLS_PUT_UINT32_BE(X, output, 4); return 0; } #endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * 3DES-CBC buffer encryption/decryption */ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, int mode, size_t length, unsigned char iv[8], const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char temp[8]; if (length % 8) { return MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH; } if (mode == MBEDTLS_DES_ENCRYPT) { while (length > 0) { mbedtls_xor(output, input, iv, 8); ret = mbedtls_des3_crypt_ecb(ctx, output, output); if (ret != 0) { goto exit; } memcpy(iv, output, 8); input += 8; output += 8; length -= 8; } } else { /* MBEDTLS_DES_DECRYPT */ while (length > 0) { memcpy(temp, input, 8); ret = mbedtls_des3_crypt_ecb(ctx, input, output); if (ret != 0) { goto exit; } mbedtls_xor(output, output, iv, 8); memcpy(iv, temp, 8); input += 8; output += 8; length -= 8; } } ret = 0; exit: return ret; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* !MBEDTLS_DES_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * DES and 3DES test vectors from: * * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip */ static const unsigned char des3_test_keys[24] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 }; static const unsigned char des3_test_buf[8] = { 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 }; static const unsigned char des3_test_ecb_dec[3][8] = { { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 }, { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 }, { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D } }; static const unsigned char des3_test_ecb_enc[3][8] = { { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB }, { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 }, { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F } }; #if defined(MBEDTLS_CIPHER_MODE_CBC) static const unsigned char des3_test_iv[8] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, }; static const unsigned char des3_test_cbc_dec[3][8] = { { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A }, { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 }, { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF } }; static const unsigned char des3_test_cbc_enc[3][8] = { { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D }, { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 }, { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 } }; #endif /* MBEDTLS_CIPHER_MODE_CBC */ /* * Checkup routine */ int mbedtls_des_self_test(int verbose) { int i, j, u, v, ret = 0; mbedtls_des_context ctx; mbedtls_des3_context ctx3; unsigned char buf[8]; #if defined(MBEDTLS_CIPHER_MODE_CBC) unsigned char prv[8]; unsigned char iv[8]; #endif mbedtls_des_init(&ctx); mbedtls_des3_init(&ctx3); /* * ECB mode */ for (i = 0; i < 6; i++) { u = i >> 1; v = i & 1; if (verbose != 0) { mbedtls_printf(" DES%c-ECB-%3d (%s): ", (u == 0) ? ' ' : '3', 56 + u * 56, (v == MBEDTLS_DES_DECRYPT) ? "dec" : "enc"); } memcpy(buf, des3_test_buf, 8); switch (i) { case 0: ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys); break; case 1: ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys); break; case 2: ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys); break; case 3: ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys); break; case 4: ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys); break; case 5: ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys); break; default: return 1; } if (ret != 0) { goto exit; } for (j = 0; j < 100; j++) { if (u == 0) { ret = mbedtls_des_crypt_ecb(&ctx, buf, buf); } else { ret = mbedtls_des3_crypt_ecb(&ctx3, buf, buf); } if (ret != 0) { goto exit; } } if ((v == MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_ecb_dec[u], 8) != 0) || (v != MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_ecb_enc[u], 8) != 0)) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * CBC mode */ for (i = 0; i < 6; i++) { u = i >> 1; v = i & 1; if (verbose != 0) { mbedtls_printf(" DES%c-CBC-%3d (%s): ", (u == 0) ? ' ' : '3', 56 + u * 56, (v == MBEDTLS_DES_DECRYPT) ? "dec" : "enc"); } memcpy(iv, des3_test_iv, 8); memcpy(prv, des3_test_iv, 8); memcpy(buf, des3_test_buf, 8); switch (i) { case 0: ret = mbedtls_des_setkey_dec(&ctx, des3_test_keys); break; case 1: ret = mbedtls_des_setkey_enc(&ctx, des3_test_keys); break; case 2: ret = mbedtls_des3_set2key_dec(&ctx3, des3_test_keys); break; case 3: ret = mbedtls_des3_set2key_enc(&ctx3, des3_test_keys); break; case 4: ret = mbedtls_des3_set3key_dec(&ctx3, des3_test_keys); break; case 5: ret = mbedtls_des3_set3key_enc(&ctx3, des3_test_keys); break; default: return 1; } if (ret != 0) { goto exit; } if (v == MBEDTLS_DES_DECRYPT) { for (j = 0; j < 100; j++) { if (u == 0) { ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf); } else { ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf); } if (ret != 0) { goto exit; } } } else { for (j = 0; j < 100; j++) { unsigned char tmp[8]; if (u == 0) { ret = mbedtls_des_crypt_cbc(&ctx, v, 8, iv, buf, buf); } else { ret = mbedtls_des3_crypt_cbc(&ctx3, v, 8, iv, buf, buf); } if (ret != 0) { goto exit; } memcpy(tmp, prv, 8); memcpy(prv, buf, 8); memcpy(buf, tmp, 8); } memcpy(buf, prv, 8); } if ((v == MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_cbc_dec[u], 8) != 0) || (v != MBEDTLS_DES_DECRYPT && memcmp(buf, des3_test_cbc_enc[u], 8) != 0)) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ if (verbose != 0) { mbedtls_printf("\n"); } exit: mbedtls_des_free(&ctx); mbedtls_des3_free(&ctx3); if (ret != 0) { ret = 1; } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_DES_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/dhm.c000066400000000000000000000465371464416617300222670ustar00rootroot00000000000000/* * Diffie-Hellman-Merkle key exchange * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the Diffie-Hellman-Merkle algorithm: * * [1] Handbook of Applied Cryptography - 1997, Chapter 12 * Menezes, van Oorschot and Vanstone * */ #include "common.h" #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #endif #include "mbedtls/platform.h" #if !defined(MBEDTLS_DHM_ALT) /* * helper to validate the mbedtls_mpi size and import it */ static int dhm_read_bignum(mbedtls_mpi *X, unsigned char **p, const unsigned char *end) { int ret, n; if (end - *p < 2) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } n = MBEDTLS_GET_UINT16_BE(*p, 0); (*p) += 2; if ((size_t) (end - *p) < (size_t) n) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret); } (*p) += n; return 0; } /* * Verify sanity of parameter with regards to P * * Parameter should be: 2 <= public_param <= P - 2 * * This means that we need to return an error if * public_param < 2 or public_param > P-2 * * For more information on the attack, see: * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 */ static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P) { mbedtls_mpi U; int ret = 0; mbedtls_mpi_init(&U); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2)); if (mbedtls_mpi_cmp_int(param, 2) < 0 || mbedtls_mpi_cmp_mpi(param, &U) > 0) { ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } cleanup: mbedtls_mpi_free(&U); return ret; } void mbedtls_dhm_init(mbedtls_dhm_context *ctx) { memset(ctx, 0, sizeof(mbedtls_dhm_context)); } size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx) { return mbedtls_mpi_bitlen(&ctx->P); } size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx) { return mbedtls_mpi_size(&ctx->P); } int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx, mbedtls_dhm_parameter param, mbedtls_mpi *dest) { const mbedtls_mpi *src = NULL; switch (param) { case MBEDTLS_DHM_PARAM_P: src = &ctx->P; break; case MBEDTLS_DHM_PARAM_G: src = &ctx->G; break; case MBEDTLS_DHM_PARAM_X: src = &ctx->X; break; case MBEDTLS_DHM_PARAM_GX: src = &ctx->GX; break; case MBEDTLS_DHM_PARAM_GY: src = &ctx->GY; break; case MBEDTLS_DHM_PARAM_K: src = &ctx->K; break; default: return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } return mbedtls_mpi_copy(dest, src); } /* * Parse the ServerKeyExchange parameters */ int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx, unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 || (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 || (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) { return ret; } if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) { return ret; } return 0; } /* * Pick a random R in the range [2, M-2] for blinding or key generation. */ static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1)); cleanup: return ret; } static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if (x_size < 0) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) { MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng)); } else { /* Generate X as large as possible ( <= P - 2 ) */ ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED; } if (ret != 0) { return ret; } } /* * Calculate GX = G^X mod P */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X, &ctx->P, &ctx->RP)); if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) { return ret; } cleanup: return ret; } /* * Setup and write the ServerKeyExchange parameters */ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; size_t n1, n2, n3; unsigned char *p; ret = dhm_make_common(ctx, x_size, f_rng, p_rng); if (ret != 0) { goto cleanup; } /* * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are * not required". We omit leading zeros for compactness. */ #define DHM_MPI_EXPORT(X, n) \ do { \ MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \ p + 2, \ (n))); \ *p++ = MBEDTLS_BYTE_1(n); \ *p++ = MBEDTLS_BYTE_0(n); \ p += (n); \ } while (0) n1 = mbedtls_mpi_size(&ctx->P); n2 = mbedtls_mpi_size(&ctx->G); n3 = mbedtls_mpi_size(&ctx->GX); p = output; DHM_MPI_EXPORT(&ctx->P, n1); DHM_MPI_EXPORT(&ctx->G, n2); DHM_MPI_EXPORT(&ctx->GX, n3); *olen = (size_t) (p - output); cleanup: if (ret != 0 && ret > -128) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret); } return ret; } /* * Set prime modulus and generator */ int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx, const mbedtls_mpi *P, const mbedtls_mpi *G) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 || (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret); } return 0; } /* * Import the peer's public value G^Y */ int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret); } return 0; } /* * Create own private value X and export G^X */ int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size, unsigned char *output, size_t olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } ret = dhm_make_common(ctx, x_size, f_rng, p_rng); if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) { return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED; } if (ret != 0) { goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen)); cleanup: if (ret != 0 && ret > -128) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret); } return ret; } /* * Use the blinding method and optimisation suggested in section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ static int dhm_update_blinding(mbedtls_dhm_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; mbedtls_mpi R; mbedtls_mpi_init(&R); /* * Don't use any blinding the first time a particular X is used, * but remember it to use blinding next time. */ if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1)); return 0; } /* * Ok, we need blinding. Can we re-use existing values? * If yes, just update them by squaring them. */ if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P)); return 0; } /* * We need to generate blinding values from scratch */ /* Vi = random( 2, P-2 ) */ MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng)); /* Vf = Vi^-X mod P * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), * then elevate to the Xth power. */ MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP)); cleanup: mbedtls_mpi_free(&R); return ret; } /* * Derive and export the shared secret (G^Y)^X mod P */ int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi GYb; if (f_rng == NULL) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if (output_size < mbedtls_dhm_get_len(ctx)) { return MBEDTLS_ERR_DHM_BAD_INPUT_DATA; } if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) { return ret; } mbedtls_mpi_init(&GYb); /* Blind peer's value */ MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P)); /* Do modular exponentiation */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X, &ctx->P, &ctx->RP)); /* Unblind secret value */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P)); /* Output the secret without any leading zero byte. This is mandatory * for TLS per RFC 5246 §8.1.2. */ *olen = mbedtls_mpi_size(&ctx->K); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen)); cleanup: mbedtls_mpi_free(&GYb); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret); } return 0; } /* * Free the components of a DHM key */ void mbedtls_dhm_free(mbedtls_dhm_context *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->pX); mbedtls_mpi_free(&ctx->Vf); mbedtls_mpi_free(&ctx->Vi); mbedtls_mpi_free(&ctx->RP); mbedtls_mpi_free(&ctx->K); mbedtls_mpi_free(&ctx->GY); mbedtls_mpi_free(&ctx->GX); mbedtls_mpi_free(&ctx->X); mbedtls_mpi_free(&ctx->G); mbedtls_mpi_free(&ctx->P); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context)); } #if defined(MBEDTLS_ASN1_PARSE_C) /* * Parse DHM parameters */ int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p, *end; #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_context pem; #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN DH PARAMETERS-----", "-----END DH PARAMETERS-----", dhmin, NULL, 0, &dhminlen); } if (ret == 0) { /* * Was PEM encoded */ dhminlen = pem.buflen; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { goto exit; } p = (ret == 0) ? pem.buf : (unsigned char *) dhmin; #else p = (unsigned char *) dhmin; #endif /* MBEDTLS_PEM_PARSE_C */ end = p + dhminlen; /* * DHParams ::= SEQUENCE { * prime INTEGER, -- P * generator INTEGER, -- g * privateValueLength INTEGER OPTIONAL * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret); goto exit; } end = p + len; if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 || (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret); goto exit; } if (p != end) { /* This might be the optional privateValueLength. * If so, we can cleanly discard it */ mbedtls_mpi rec; mbedtls_mpi_init(&rec); ret = mbedtls_asn1_get_mpi(&p, end, &rec); mbedtls_mpi_free(&rec); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret); goto exit; } if (p != end) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); goto exit; } } ret = 0; exit: #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_free(&pem); #endif if (ret != 0) { mbedtls_dhm_free(dhm); } return ret; } #if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. * * The file is expected to contain either PEM or DER encoded data. * A terminating null byte is always appended. It is included in the announced * length only if the data looks like it is PEM encoded. */ static int load_file(const char *path, unsigned char **buf, size_t *n) { FILE *f; long size; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } /* The data loaded here is public, so don't bother disabling buffering. */ fseek(f, 0, SEEK_END); if ((size = ftell(f)) == -1) { fclose(f); return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } fseek(f, 0, SEEK_SET); *n = (size_t) size; if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { fclose(f); return MBEDTLS_ERR_DHM_ALLOC_FAILED; } if (fread(*buf, 1, *n, f) != *n) { fclose(f); mbedtls_zeroize_and_free(*buf, *n + 1); return MBEDTLS_ERR_DHM_FILE_IO_ERROR; } fclose(f); (*buf)[*n] = '\0'; if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { ++*n; } return 0; } /* * Load and parse DHM parameters */ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_dhm_parse_dhm(dhm, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_ASN1_PARSE_C */ #endif /* MBEDTLS_DHM_ALT */ #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PEM_PARSE_C) static const char mbedtls_test_dhm_params[] = "-----BEGIN DH PARAMETERS-----\r\n" "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" "-----END DH PARAMETERS-----\r\n"; #else /* MBEDTLS_PEM_PARSE_C */ static const char mbedtls_test_dhm_params[] = { 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; #endif /* MBEDTLS_PEM_PARSE_C */ static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params); /* * Checkup routine */ int mbedtls_dhm_self_test(int verbose) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_dhm_context dhm; mbedtls_dhm_init(&dhm); if (verbose != 0) { mbedtls_printf(" DHM parameter load: "); } if ((ret = mbedtls_dhm_parse_dhm(&dhm, (const unsigned char *) mbedtls_test_dhm_params, mbedtls_test_dhm_params_len)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n\n"); } exit: mbedtls_dhm_free(&dhm); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_DHM_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecdh.c000066400000000000000000000522141464416617300224070ustar00rootroot00000000000000/* * Elliptic curve Diffie-Hellman * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * SEC1 https://www.secg.org/sec1-v2.pdf * RFC 4492 */ #include "common.h" #if defined(MBEDTLS_ECDH_C) #include "mbedtls/ecdh.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; #endif static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( const mbedtls_ecdh_context *ctx) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ctx->grp.id; #else return ctx->grp_id; #endif } int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid) { /* At this time, all groups support ECDH. */ (void) gid; return 1; } #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) /* * Generate public key (restartable version) * * Note: this internal function relies on its caller preserving the value of * the output parameter 'd' across continuation calls. This would not be * acceptable for a public function but is OK here as we control call sites. */ static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int restarting = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); #endif /* If multiplication is in progress, we already generated a privkey */ if (!restarting) { MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng)); } MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G, f_rng, p_rng, rs_ctx)); cleanup: return ret; } /* * Generate public key */ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) /* * Compute shared secret (SEC1 3.3.1) */ static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point P; mbedtls_ecp_point_init(&P); MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q, f_rng, p_rng, rs_ctx)); if (mbedtls_ecp_is_zero(&P)) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X)); cleanup: mbedtls_ecp_point_free(&P); return ret; } /* * Compute shared secret (SEC1 3.3.1) */ int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return ecdh_compute_shared_restartable(grp, z, Q, d, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx) { mbedtls_ecp_group_init(&ctx->grp); mbedtls_mpi_init(&ctx->d); mbedtls_ecp_point_init(&ctx->Q); mbedtls_ecp_point_init(&ctx->Qp); mbedtls_mpi_init(&ctx->z); #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_init(&ctx->rs); #endif } mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ctx->MBEDTLS_PRIVATE(grp).id; #else return ctx->MBEDTLS_PRIVATE(grp_id); #endif } /* * Initialize context */ void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) ecdh_init_internal(ctx); mbedtls_ecp_point_init(&ctx->Vi); mbedtls_ecp_point_init(&ctx->Vf); mbedtls_mpi_init(&ctx->_d); #else memset(ctx, 0, sizeof(mbedtls_ecdh_context)); ctx->var = MBEDTLS_ECDH_VARIANT_NONE; #endif ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; #if defined(MBEDTLS_ECP_RESTARTABLE) ctx->restart_enabled = 0; #endif } static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx, mbedtls_ecp_group_id grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ecp_group_load(&ctx->grp, grp_id); if (ret != 0) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } return 0; } /* * Setup context */ int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_setup_internal(ctx, grp_id); #else switch (grp_id) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; ctx->grp_id = grp_id; return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id); #endif default: ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; ctx->grp_id = grp_id; ecdh_init_internal(&ctx->ctx.mbed_ecdh); return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id); } #endif } static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx) { mbedtls_ecp_group_free(&ctx->grp); mbedtls_mpi_free(&ctx->d); mbedtls_ecp_point_free(&ctx->Q); mbedtls_ecp_point_free(&ctx->Qp); mbedtls_mpi_free(&ctx->z); #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_free(&ctx->rs); #endif } #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Enable restartable operations for context */ void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx) { ctx->restart_enabled = 1; } #endif /* * Free context */ void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) mbedtls_ecp_point_free(&ctx->Vi); mbedtls_ecp_point_free(&ctx->Vf); mbedtls_mpi_free(&ctx->_d); ecdh_free_internal(ctx); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: mbedtls_everest_free(&ctx->ctx.everest_ecdh); break; #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: ecdh_free_internal(&ctx->ctx.mbed_ecdh); break; default: break; } ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; ctx->var = MBEDTLS_ECDH_VARIANT_NONE; ctx->grp_id = MBEDTLS_ECP_DP_NONE; #endif } static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx, size_t *olen, int point_format, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int restart_enabled) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t grp_len, pt_len; #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx *rs_ctx = NULL; #endif if (ctx->grp.pbits == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_RESTARTABLE) if (restart_enabled) { rs_ctx = &ctx->rs; } #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng, rs_ctx)) != 0) { return ret; } #else if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng)) != 0) { return ret; } #endif /* MBEDTLS_ECP_RESTARTABLE */ if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf, blen)) != 0) { return ret; } buf += grp_len; blen -= grp_len; if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, &pt_len, buf, blen)) != 0) { return ret; } *olen = grp_len + pt_len; return 0; } /* * Setup and write the ServerKeyExchange parameters (RFC 4492) * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int restart_enabled = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen, buf, blen, f_rng, p_rng); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx, const unsigned char **buf, const unsigned char *end) { return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf, (size_t) (end - *buf)); } /* * Read the ServerKeyExchange parameters (RFC 4492) * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx, const unsigned char **buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf))) != 0) { return ret; } if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) { return ret; } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_read_params_internal(ctx, buf, end); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh, buf, end); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh, buf, end); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* If it's not our key, just import the public part as Qp */ if (side == MBEDTLS_ECDH_THEIRS) { return mbedtls_ecp_copy(&ctx->Qp, &key->Q); } /* Our key: import public (as Q) and private parts */ if (side != MBEDTLS_ECDH_OURS) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 || (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) { return ret; } return 0; } /* * Get parameters from a keypair */ int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) { /* This is the first call to get_params(). Set up the context * for use with the group. */ if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) { return ret; } } else { /* This is not the first call to get_params(). Check that the * current key's group is the same as the context's, which was set * from the first key's group. */ if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_get_params_internal(ctx, key, side); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: { mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? MBEDTLS_EVEREST_ECDH_OURS : MBEDTLS_EVEREST_ECDH_THEIRS; return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh, key, s); } #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh, key, side); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx, size_t *olen, int point_format, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int restart_enabled) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx *rs_ctx = NULL; #endif if (ctx->grp.pbits == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_RESTARTABLE) if (restart_enabled) { rs_ctx = &ctx->rs; } #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng, rs_ctx)) != 0) { return ret; } #else if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng)) != 0) { return ret; } #endif /* MBEDTLS_ECP_RESTARTABLE */ return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen, buf, blen); } /* * Setup and export the client public value */ int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int restart_enabled = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #endif #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen, buf, blen, f_rng, p_rng); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen, ctx->point_format, buf, blen, f_rng, p_rng, restart_enabled); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx, const unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p, blen)) != 0) { return ret; } if ((size_t) (p - buf) != blen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return 0; } /* * Parse and import the client's public value */ int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, const unsigned char *buf, size_t blen) { #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_read_public_internal(ctx, buf, blen); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh, buf, blen); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh, buf, blen); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int restart_enabled) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx *rs_ctx = NULL; #endif if (ctx == NULL || ctx->grp.pbits == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_RESTARTABLE) if (restart_enabled) { rs_ctx = &ctx->rs; } #else (void) restart_enabled; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx)) != 0) { return ret; } #else if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng)) != 0) { return ret; } #endif /* MBEDTLS_ECP_RESTARTABLE */ if (mbedtls_mpi_size(&ctx->z) > blen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0); if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen); } return mbedtls_mpi_write_binary(&ctx->z, buf, *olen); } /* * Derive and export the shared secret */ int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int restart_enabled = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restart_enabled = ctx->restart_enabled; #endif #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng, restart_enabled); #else switch (ctx->var) { #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) case MBEDTLS_ECDH_VARIANT_EVEREST: return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen, buf, blen, f_rng, p_rng); #endif case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf, blen, f_rng, p_rng, restart_enabled); default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #endif } #endif /* MBEDTLS_ECDH_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecdsa.c000066400000000000000000000651561464416617300225740ustar00rootroot00000000000000/* * Elliptic curve DSA * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * SEC1 https://www.secg.org/sec1-v2.pdf */ #include "common.h" #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #include "mbedtls/asn1write.h" #include #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #include "mbedtls/hmac_drbg.h" #endif #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Sub-context for ecdsa_verify() */ struct mbedtls_ecdsa_restart_ver { mbedtls_mpi u1, u2; /* intermediate values */ enum { /* what to do next? */ ecdsa_ver_init = 0, /* getting started */ ecdsa_ver_muladd, /* muladd step */ } state; }; /* * Init verify restart sub-context */ static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx) { mbedtls_mpi_init(&ctx->u1); mbedtls_mpi_init(&ctx->u2); ctx->state = ecdsa_ver_init; } /* * Free the components of a verify restart sub-context */ static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->u1); mbedtls_mpi_free(&ctx->u2); ecdsa_restart_ver_init(ctx); } /* * Sub-context for ecdsa_sign() */ struct mbedtls_ecdsa_restart_sig { int sign_tries; int key_tries; mbedtls_mpi k; /* per-signature random */ mbedtls_mpi r; /* r value */ enum { /* what to do next? */ ecdsa_sig_init = 0, /* getting started */ ecdsa_sig_mul, /* doing ecp_mul() */ ecdsa_sig_modn, /* mod N computations */ } state; }; /* * Init verify sign sub-context */ static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx) { ctx->sign_tries = 0; ctx->key_tries = 0; mbedtls_mpi_init(&ctx->k); mbedtls_mpi_init(&ctx->r); ctx->state = ecdsa_sig_init; } /* * Free the components of a sign restart sub-context */ static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->k); mbedtls_mpi_free(&ctx->r); } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Sub-context for ecdsa_sign_det() */ struct mbedtls_ecdsa_restart_det { mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ enum { /* what to do next? */ ecdsa_det_init = 0, /* getting started */ ecdsa_det_sign, /* make signature */ } state; }; /* * Init verify sign_det sub-context */ static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx) { mbedtls_hmac_drbg_init(&ctx->rng_ctx); ctx->state = ecdsa_det_init; } /* * Free the components of a sign_det restart sub-context */ static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_hmac_drbg_free(&ctx->rng_ctx); ecdsa_restart_det_init(ctx); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp) /* Utility macro for checking and updating ops budget */ #define ECDSA_BUDGET(ops) \ MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops)); /* Call this when entering a function that needs its own sub-context */ #define ECDSA_RS_ENTER(SUB) do { \ /* reset ops count for this call if top-level */ \ if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \ rs_ctx->ecp.ops_done = 0; \ \ /* set up our own sub-context if needed */ \ if (mbedtls_ecp_restart_is_enabled() && \ rs_ctx != NULL && rs_ctx->SUB == NULL) \ { \ rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \ if (rs_ctx->SUB == NULL) \ return MBEDTLS_ERR_ECP_ALLOC_FAILED; \ \ ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \ } \ } while (0) /* Call this when leaving a function that needs its own sub-context */ #define ECDSA_RS_LEAVE(SUB) do { \ /* clear our sub-context when not in progress (done or error) */ \ if (rs_ctx != NULL && rs_ctx->SUB != NULL && \ ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \ { \ ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \ mbedtls_free(rs_ctx->SUB); \ rs_ctx->SUB = NULL; \ } \ \ if (rs_ctx != NULL) \ rs_ctx->ecp.depth--; \ } while (0) #else /* MBEDTLS_ECP_RESTARTABLE */ #define ECDSA_RS_ECP NULL #define ECDSA_BUDGET(ops) /* no-op; for compatibility */ #define ECDSA_RS_ENTER(SUB) (void) rs_ctx #define ECDSA_RS_LEAVE(SUB) (void) rs_ctx #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 */ static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x, const unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n_size = (grp->nbits + 7) / 8; size_t use_size = blen > n_size ? n_size : blen; MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size)); if (use_size * 8 > grp->nbits) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits)); } /* While at it, reduce modulo N */ if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N)); } cleanup: return ret; } #endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid) { switch (gid) { #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED case MBEDTLS_ECP_DP_CURVE25519: return 0; #endif #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED case MBEDTLS_ECP_DP_CURVE448: return 0; #endif default: return 1; } } #if !defined(MBEDTLS_ECDSA_SIGN_ALT) /* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret, key_tries, sign_tries; int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; mbedtls_mpi *pk = &k, *pr = r; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Make sure d is in range 1..n-1 */ if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } mbedtls_ecp_point_init(&R); mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t); ECDSA_RS_ENTER(sig); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { /* redirect to our context */ p_sign_tries = &rs_ctx->sig->sign_tries; p_key_tries = &rs_ctx->sig->key_tries; pk = &rs_ctx->sig->k; pr = &rs_ctx->sig->r; /* jump to current step */ if (rs_ctx->sig->state == ecdsa_sig_mul) { goto mul; } if (rs_ctx->sig->state == ecdsa_sig_modn) { goto modn; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ *p_sign_tries = 0; do { if ((*p_sign_tries)++ > 10) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ *p_key_tries = 0; do { if ((*p_key_tries)++ > 10) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { rs_ctx->sig->state = ecdsa_sig_mul; } mul: #endif MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G, f_rng_blind, p_rng_blind, ECDSA_RS_ECP)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N)); } while (mbedtls_mpi_cmp_int(pr, 0) == 0); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { rs_ctx->sig->state = ecdsa_sig_modn; } modn: #endif /* * Accounting for everything up to the end of the loop * (step 6, but checking now avoids saving e and t) */ ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4); /* * Step 5: derive MPI from hashed message */ MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen)); /* * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind, p_rng_blind)); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N)); } while (mbedtls_mpi_cmp_int(s, 0) == 0); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->sig != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr)); } #endif cleanup: mbedtls_ecp_point_free(&R); mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t); ECDSA_RS_LEAVE(sig); return ret; } /* * Compute ECDSA signature of a hashed message */ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { /* Use the same RNG for both blinding and ephemeral key generation */ return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng, p_rng, NULL); } #endif /* !MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper * * note: The f_rng_blind parameter must not be NULL. * */ int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context rng_ctx; mbedtls_hmac_drbg_context *p_rng = &rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = (grp->nbits + 7) / 8; const mbedtls_md_info_t *md_info; mbedtls_mpi h; if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_mpi_init(&h); mbedtls_hmac_drbg_init(&rng_ctx); ECDSA_RS_ENTER(det); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->det != NULL) { /* redirect to our context */ p_rng = &rs_ctx->det->rng_ctx; /* jump to current step */ if (rs_ctx->det->state == ecdsa_det_sign) { goto sign; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len)); MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len)); MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->det != NULL) { rs_ctx->det->state = ecdsa_det_sign; } sign: #endif #if defined(MBEDTLS_ECDSA_SIGN_ALT) (void) f_rng_blind; (void) p_rng_blind; ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng); #else ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng, f_rng_blind, p_rng_blind, rs_ctx); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ cleanup: mbedtls_hmac_drbg_free(&rng_ctx); mbedtls_mpi_free(&h); ECDSA_RS_LEAVE(det); return ret; } /* * Deterministic signature wrapper */ int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind) { return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, f_rng_blind, p_rng_blind, NULL); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; mbedtls_mpi *pu1 = &u1, *pu2 = &u2; mbedtls_ecp_point_init(&R); mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv); mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2); /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } ECDSA_RS_ENTER(ver); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ver != NULL) { /* redirect to our context */ pu1 = &rs_ctx->ver->u1; pu2 = &rs_ctx->ver->u2; /* jump to current step */ if (rs_ctx->ver->state == ecdsa_ver_muladd) { goto muladd; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* * Step 1: make sure r and s are in range 1..n-1 */ if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 || mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } /* * Step 3: derive MPI from hashed message */ MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen)); /* * Step 4: u1 = e / s mod n, u2 = r / s mod n */ ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ver != NULL) { rs_ctx->ver->state = ecdsa_ver_muladd; } muladd: #endif /* * Step 5: R = u1 G + u2 Q */ MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp, &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP)); if (mbedtls_ecp_is_zero(&R)) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } /* * Step 6: convert xR to an integer (no-op) * Step 7: reduce xR mod n (gives v) */ MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N)); /* * Step 8: check if v (that is, R.X) is equal to r */ if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } cleanup: mbedtls_ecp_point_free(&R); mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv); mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2); ECDSA_RS_LEAVE(ver); return ret; } /* * Verify ECDSA signature of hashed message */ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) { return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); } #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ /* * Convert a signature (given by context) to ASN.1 */ static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, unsigned char *sig, size_t sig_size, size_t *slen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; unsigned char *p = buf + sizeof(buf); size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); if (len > sig_size) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } memcpy(sig, p, len); *slen = len; return 0; } /* * Compute and write signature */ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi r, s; if (f_rng == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d, hash, hlen, md_alg, f_rng, p_rng, rs_ctx)); #else (void) md_alg; #if defined(MBEDTLS_ECDSA_SIGN_ALT) (void) rs_ctx; MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng)); #else /* Use the same RNG for both blinding and ephemeral key generation */ MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng, f_rng, p_rng, rs_ctx)); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); return ret; } /* * Compute and write signature */ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t sig_size, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecdsa_write_signature_restartable( ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, NULL); } /* * Read and check signature */ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen) { return mbedtls_ecdsa_read_signature_restartable( ctx, hash, hlen, sig, slen, NULL); } /* * Restartable read and check signature */ int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if (p + len != end) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); goto cleanup; } if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 || (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } #if defined(MBEDTLS_ECDSA_VERIFY_ALT) (void) rs_ctx; if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen, &ctx->Q, &r, &s)) != 0) { goto cleanup; } #else if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen, &ctx->Q, &r, &s, rs_ctx)) != 0) { goto cleanup; } #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ /* At this point we know that the buffer starts with a valid signature. * Return 0 if the buffer just contains the signature, and a specific * error code if the valid signature is followed by more data. */ if (p != end) { ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; } cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); return ret; } #if !defined(MBEDTLS_ECDSA_GENKEY_ALT) /* * Generate key pair */ int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; ret = mbedtls_ecp_group_load(&ctx->grp, gid); if (ret != 0) { return ret; } return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng); } #endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ /* * Set context from an mbedtls_ecp_keypair */ int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 || (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 || (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) { mbedtls_ecdsa_free(ctx); } return ret; } /* * Initialize context */ void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx) { mbedtls_ecp_keypair_init(ctx); } /* * Free context */ void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx) { if (ctx == NULL) { return; } mbedtls_ecp_keypair_free(ctx); } #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx) { mbedtls_ecp_restart_init(&ctx->ecp); ctx->ver = NULL; ctx->sig = NULL; #if defined(MBEDTLS_ECDSA_DETERMINISTIC) ctx->det = NULL; #endif } /* * Free the components of a restart context */ void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_ecp_restart_free(&ctx->ecp); ecdsa_restart_ver_free(ctx->ver); mbedtls_free(ctx->ver); ctx->ver = NULL; ecdsa_restart_sig_free(ctx->sig); mbedtls_free(ctx->sig); ctx->sig = NULL; #if defined(MBEDTLS_ECDSA_DETERMINISTIC) ecdsa_restart_det_free(ctx->det); mbedtls_free(ctx->det); ctx->det = NULL; #endif } #endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDSA_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecjpake.c000066400000000000000000001217161464416617300231120ustar00rootroot00000000000000/* * Elliptic curve J-PAKE * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References in the code are to the Thread v1.0 Specification, * available to members of the Thread Group http://threadgroup.org/ */ #include "common.h" #if defined(MBEDTLS_ECJPAKE_C) #include "mbedtls/ecjpake.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if !defined(MBEDTLS_ECJPAKE_ALT) /* * Convert a mbedtls_ecjpake_role to identifier string */ static const char * const ecjpake_id[] = { "client", "server" }; #define ID_MINE (ecjpake_id[ctx->role]) #define ID_PEER (ecjpake_id[1 - ctx->role]) /** * Helper to Compute a hash from md_type */ static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type, const unsigned char *input, size_t ilen, unsigned char *output) { return mbedtls_md(mbedtls_md_info_from_type(md_type), input, ilen, output); } /* * Initialize context */ void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx) { ctx->md_type = MBEDTLS_MD_NONE; mbedtls_ecp_group_init(&ctx->grp); ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; mbedtls_ecp_point_init(&ctx->Xm1); mbedtls_ecp_point_init(&ctx->Xm2); mbedtls_ecp_point_init(&ctx->Xp1); mbedtls_ecp_point_init(&ctx->Xp2); mbedtls_ecp_point_init(&ctx->Xp); mbedtls_mpi_init(&ctx->xm1); mbedtls_mpi_init(&ctx->xm2); mbedtls_mpi_init(&ctx->s); } /* * Free context */ void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx) { if (ctx == NULL) { return; } ctx->md_type = MBEDTLS_MD_NONE; mbedtls_ecp_group_free(&ctx->grp); mbedtls_ecp_point_free(&ctx->Xm1); mbedtls_ecp_point_free(&ctx->Xm2); mbedtls_ecp_point_free(&ctx->Xp1); mbedtls_ecp_point_free(&ctx->Xp2); mbedtls_ecp_point_free(&ctx->Xp); mbedtls_mpi_free(&ctx->xm1); mbedtls_mpi_free(&ctx->xm2); mbedtls_mpi_free(&ctx->s); } /* * Setup context */ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx, mbedtls_ecjpake_role role, mbedtls_md_type_t hash, mbedtls_ecp_group_id curve, const unsigned char *secret, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } ctx->role = role; if ((mbedtls_md_info_from_type(hash)) == NULL) { return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; } ctx->md_type = hash; MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len)); cleanup: if (ret != 0) { mbedtls_ecjpake_free(ctx); } return ret; } int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx, int point_format) { switch (point_format) { case MBEDTLS_ECP_PF_UNCOMPRESSED: case MBEDTLS_ECP_PF_COMPRESSED: ctx->point_format = point_format; return 0; default: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } /* * Check if context is ready for use */ int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx) { if (ctx->md_type == MBEDTLS_MD_NONE || ctx->grp.id == MBEDTLS_ECP_DP_NONE || ctx->s.p == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return 0; } /* * Write a point plus its length to a buffer */ static int ecjpake_write_len_point(unsigned char **p, const unsigned char *end, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *P) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Need at least 4 for length plus 1 for point */ if (end < *p || end - *p < 5) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } ret = mbedtls_ecp_point_write_binary(grp, P, pf, &len, *p + 4, (size_t) (end - (*p + 4))); if (ret != 0) { return ret; } MBEDTLS_PUT_UINT32_BE(len, *p, 0); *p += 4 + len; return 0; } /* * Size of the temporary buffer for ecjpake_hash: * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) */ #define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6) /* * Compute hash for ZKP (7.4.2.2.2.1) */ static int ecjpake_hash(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, const mbedtls_ecp_point *V, const mbedtls_ecp_point *X, const char *id, mbedtls_mpi *h) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[ECJPAKE_HASH_BUF_LEN]; unsigned char *p = buf; const unsigned char *end = buf + sizeof(buf); const size_t id_len = strlen(id); unsigned char hash[MBEDTLS_MD_MAX_SIZE]; /* Write things to temporary buffer */ MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G)); MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V)); MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X)); if (end - p < 4) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } MBEDTLS_PUT_UINT32_BE(id_len, p, 0); p += 4; if (end < p || (size_t) (end - p) < id_len) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } memcpy(p, id, id_len); p += id_len; /* Compute hash */ MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type, buf, (size_t) (p - buf), hash)); /* Turn it into an integer mod n */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash, mbedtls_md_get_size_from_type(md_type))); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N)); cleanup: return ret; } /* * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) */ static int ecjpake_zkp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, const mbedtls_ecp_point *X, const char *id, const unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point V, VV; mbedtls_mpi r, h; size_t r_len; mbedtls_ecp_point_init(&V); mbedtls_ecp_point_init(&VV); mbedtls_mpi_init(&r); mbedtls_mpi_init(&h); /* * struct { * ECPoint V; * opaque r<1..2^8-1>; * } ECSchnorrZKP; */ if (end < *p) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p))); if (end < *p || (size_t) (end - *p) < 1) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } r_len = *(*p)++; if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len)); *p += r_len; /* * Verification */ MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp, &VV, &h, X, &r, G)); if (mbedtls_ecp_point_cmp(&VV, &V) != 0) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } cleanup: mbedtls_ecp_point_free(&V); mbedtls_ecp_point_free(&VV); mbedtls_mpi_free(&r); mbedtls_mpi_free(&h); return ret; } /* * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) */ static int ecjpake_zkp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, const mbedtls_mpi *x, const mbedtls_ecp_point *X, const char *id, unsigned char **p, const unsigned char *end, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point V; mbedtls_mpi v; mbedtls_mpi h; /* later recycled to hold r */ size_t len; if (end < *p) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } mbedtls_ecp_point_init(&V); mbedtls_mpi_init(&v); mbedtls_mpi_init(&h); /* Compute signature */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, &v, &V, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */ MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */ /* Write it out */ MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V, pf, &len, *p, (size_t) (end - *p))); *p += len; len = mbedtls_mpi_size(&h); /* actually r */ if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } *(*p)++ = MBEDTLS_BYTE_0(len); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */ *p += len; cleanup: mbedtls_ecp_point_free(&V); mbedtls_mpi_free(&v); mbedtls_mpi_free(&h); return ret; } /* * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof * Output: verified public key X */ static int ecjpake_kkp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_ecp_point *X, const char *id, const unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (end < *p) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * struct { * ECPoint X; * ECSchnorrZKP zkp; * } ECJPAKEKeyKP; */ MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p))); if (mbedtls_ecp_is_zero(X)) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end)); cleanup: return ret; } /* * Generate an ECJPAKEKeyKP * Output: the serialized structure, plus private/public key pair */ static int ecjpake_kkp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_mpi *x, mbedtls_ecp_point *X, const char *id, unsigned char **p, const unsigned char *end, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if (end < *p) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } /* Generate key (7.4.2.3.1) and write it out */ MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X, pf, &len, *p, (size_t) (end - *p))); *p += len; /* Generate and write proof */ MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id, p, end, f_rng, p_rng)); cleanup: return ret; } /* * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs * Outputs: verified peer public keys Xa, Xb */ static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_ecp_point *Xa, mbedtls_ecp_point *Xb, const char *id, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; const unsigned char *end = buf + len; /* * struct { * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; * } ECJPAKEKeyKPPairList; */ MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end)); MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end)); if (p != end) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } cleanup: return ret; } /* * Generate a ECJPAKEKeyKPPairList * Outputs: the serialized structure, plus two private/public key pairs */ static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type, const mbedtls_ecp_group *grp, const int pf, const mbedtls_ecp_point *G, mbedtls_mpi *xm1, mbedtls_ecp_point *Xa, mbedtls_mpi *xm2, mbedtls_ecp_point *Xb, const char *id, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; const unsigned char *end = buf + len; MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id, &p, end, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id, &p, end, f_rng, p_rng)); *olen = (size_t) (p - buf); cleanup: return ret; } /* * Read and process the first round message */ int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len) { return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->Xp1, &ctx->Xp2, ID_PEER, buf, len); } /* * Generate and write the first round message */ int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format, &ctx->grp.G, &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, ID_MINE, buf, len, olen, f_rng, p_rng); } /* * Compute the sum of three points R = A + B + C */ static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *A, const mbedtls_ecp_point *B, const mbedtls_ecp_point *C) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi one; mbedtls_mpi_init(&one); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C)); cleanup: mbedtls_mpi_free(&one); return ret; } /* * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) */ int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; const unsigned char *end = buf + len; mbedtls_ecp_group grp; mbedtls_ecp_point G; /* C: GB, S: GA */ mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&G); /* * Server: GA = X3 + X4 + X1 (7.4.2.6.1) * Client: GB = X1 + X2 + X3 (7.4.2.5.1) * Unified: G = Xm1 + Xm2 + Xp1 * We need that before parsing in order to check Xp as we read it */ MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G, &ctx->Xm1, &ctx->Xm2, &ctx->Xp1)); /* * struct { * ECParameters curve_params; // only client reading server msg * ECJPAKEKeyKP ecjpake_key_kp; * } Client/ServerECJPAKEParams; */ if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) { MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len)); if (grp.id != ctx->grp.id) { ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; goto cleanup; } } MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp, ctx->point_format, &G, &ctx->Xp, ID_PEER, &p, end)); if (p != end) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } cleanup: mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&G); return ret; } /* * Compute R = +/- X * S mod N, taking care not to leak S */ static int ecjpake_mul_secret(mbedtls_mpi *R, int sign, const mbedtls_mpi *X, const mbedtls_mpi *S, const mbedtls_mpi *N, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi b; /* Blinding value, then s + N * blinding */ mbedtls_mpi_init(&b); /* b = s + rnd-128-bit * N */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S)); /* R = sign * X * b mod N */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b)); R->s *= sign; MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N)); cleanup: mbedtls_mpi_free(&b); return ret; } /* * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) */ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point G; /* C: GA, S: GB */ mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ mbedtls_mpi xm; /* C: xc, S: xs */ unsigned char *p = buf; const unsigned char *end = buf + len; size_t ec_len; mbedtls_ecp_point_init(&G); mbedtls_ecp_point_init(&Xm); mbedtls_mpi_init(&xm); /* * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) * * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G */ MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G, &ctx->Xp1, &ctx->Xp2, &ctx->Xm1)); MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s, &ctx->grp.N, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng)); /* * Now write things out * * struct { * ECParameters curve_params; // only server writing its message * ECJPAKEKeyKP ecjpake_key_kp; * } Client/ServerECJPAKEParams; */ if (ctx->role == MBEDTLS_ECJPAKE_SERVER) { if (end < p) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len, p, (size_t) (end - p))); p += ec_len; } if (end < p) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm, ctx->point_format, &ec_len, p, (size_t) (end - p))); p += ec_len; MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp, ctx->point_format, &G, &xm, &Xm, ID_MINE, &p, end, f_rng, p_rng)); *olen = (size_t) (p - buf); cleanup: mbedtls_ecp_point_free(&G); mbedtls_ecp_point_free(&Xm); mbedtls_mpi_free(&xm); return ret; } /* * Derive PMS (7.4.2.7 / 7.4.2.8) */ static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx, mbedtls_ecp_point *K, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi m_xm2_s, one; mbedtls_mpi_init(&m_xm2_s); mbedtls_mpi_init(&one); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); /* * Client: K = ( Xs - X4 * x2 * s ) * x2 * Server: K = ( Xc - X2 * x4 * s ) * x4 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 */ MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s, &ctx->grp.N, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K, &one, &ctx->Xp, &m_xm2_s, &ctx->Xp2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K, f_rng, p_rng)); cleanup: mbedtls_mpi_free(&m_xm2_s); mbedtls_mpi_free(&one); return ret; } int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point K; unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; size_t x_bytes; *olen = mbedtls_md_get_size_from_type(ctx->md_type); if (len < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } mbedtls_ecp_point_init(&K); ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); if (ret) { goto cleanup; } /* PMS = SHA-256( K.X ) */ x_bytes = (ctx->grp.pbits + 7) / 8; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes)); MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type, kx, x_bytes, buf)); cleanup: mbedtls_ecp_point_free(&K); return ret; } int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx, unsigned char *buf, size_t len, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point K; mbedtls_ecp_point_init(&K); ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng); if (ret) { goto cleanup; } ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format, olen, buf, len); if (ret != 0) { goto cleanup; } cleanup: mbedtls_ecp_point_free(&K); return ret; } #undef ID_MINE #undef ID_PEER #endif /* ! MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_SELF_TEST) #include "mbedtls/platform.h" #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ !defined(MBEDTLS_MD_CAN_SHA256) int mbedtls_ecjpake_self_test(int verbose) { (void) verbose; return 0; } #else static const unsigned char ecjpake_test_password[] = { 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, 0x65, 0x73, 0x74 }; #if !defined(MBEDTLS_ECJPAKE_ALT) static const unsigned char ecjpake_test_x1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 }; static const unsigned char ecjpake_test_x2[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 }; static const unsigned char ecjpake_test_x3[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 }; static const unsigned char ecjpake_test_x4[] = { 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 }; static const unsigned char ecjpake_test_cli_one[] = { 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 }; static const unsigned char ecjpake_test_srv_one[] = { 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 }; static const unsigned char ecjpake_test_srv_two[] = { 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c }; static const unsigned char ecjpake_test_cli_two[] = { 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c }; static const unsigned char ecjpake_test_shared_key[] = { 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80, 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79, 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1, 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0, 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12, 0x17, 0xc3, 0xde, 0x27, 0xb4, }; static const unsigned char ecjpake_test_pms[] = { 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 }; /* * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! * * This is the linear congruential generator from numerical recipes, * except we only use the low byte as the output. See * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use */ static int self_test_rng(void *ctx, unsigned char *out, size_t len) { static uint32_t state = 42; (void) ctx; for (size_t i = 0; i < len; i++) { state = state * 1664525u + 1013904223u; out[i] = (unsigned char) state; } return 0; } /* Load my private keys and generate the corresponding public keys */ static int ecjpake_test_load(mbedtls_ecjpake_context *ctx, const unsigned char *xm1, size_t len1, const unsigned char *xm2, size_t len2) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1, &ctx->grp.G, self_test_rng, NULL)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2, &ctx->grp.G, self_test_rng, NULL)); cleanup: return ret; } #endif /* ! MBEDTLS_ECJPAKE_ALT */ /* For tests we don't need a secure RNG; * use the LGC from Numerical Recipes for simplicity */ static int ecjpake_lgc(void *p, unsigned char *out, size_t len) { static uint32_t x = 42; (void) p; while (len > 0) { size_t use_len = len > 4 ? 4 : len; x = 1664525 * x + 1013904223; memcpy(out, &x, use_len); out += use_len; len -= use_len; } return 0; } #define TEST_ASSERT(x) \ do { \ if (x) \ ret = 0; \ else \ { \ ret = 1; \ goto cleanup; \ } \ } while (0) /* * Checkup routine */ int mbedtls_ecjpake_self_test(int verbose) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecjpake_context cli; mbedtls_ecjpake_context srv; unsigned char buf[512], pms[32]; size_t len, pmslen; mbedtls_ecjpake_init(&cli); mbedtls_ecjpake_init(&srv); if (verbose != 0) { mbedtls_printf(" ECJPAKE test #0 (setup): "); } TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, ecjpake_test_password, sizeof(ecjpake_test_password)) == 0); TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, ecjpake_test_password, sizeof(ecjpake_test_password)) == 0); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" ECJPAKE test #1 (random handshake): "); } TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli, pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0); TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == pmslen); TEST_ASSERT(memcmp(buf, pms, len) == 0); if (verbose != 0) { mbedtls_printf("passed\n"); } #if !defined(MBEDTLS_ECJPAKE_ALT) /* 'reference handshake' tests can only be run against implementations * for which we have 100% control over how the random ephemeral keys * are generated. This is only the case for the internal Mbed TLS * implementation, so these tests are skipped in case the internal * implementation is swapped out for an alternative one. */ if (verbose != 0) { mbedtls_printf(" ECJPAKE test #2 (reference handshake): "); } /* Simulate generation of round one */ MBEDTLS_MPI_CHK(ecjpake_test_load(&cli, ecjpake_test_x1, sizeof(ecjpake_test_x1), ecjpake_test_x2, sizeof(ecjpake_test_x2))); MBEDTLS_MPI_CHK(ecjpake_test_load(&srv, ecjpake_test_x3, sizeof(ecjpake_test_x3), ecjpake_test_x4, sizeof(ecjpake_test_x4))); /* Read round one */ TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, ecjpake_test_cli_one, sizeof(ecjpake_test_cli_one)) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, ecjpake_test_srv_one, sizeof(ecjpake_test_srv_one)) == 0); /* Skip generation of round two, read round two */ TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, ecjpake_test_srv_two, sizeof(ecjpake_test_srv_two)) == 0); TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, ecjpake_test_cli_two, sizeof(ecjpake_test_cli_two)) == 0); /* Server derives PMS */ TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_pms)); TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0); /* Server derives K as unsigned binary data */ TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0); memset(buf, 0, len); /* Avoid interferences with next step */ /* Client derives PMS */ TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_pms)); TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0); /* Client derives K as unsigned binary data */ TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli, buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0); TEST_ASSERT(len == sizeof(ecjpake_test_shared_key)); TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0); if (verbose != 0) { mbedtls_printf("passed\n"); } #endif /* ! MBEDTLS_ECJPAKE_ALT */ cleanup: mbedtls_ecjpake_free(&cli); mbedtls_ecjpake_free(&srv); if (ret != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; } if (verbose != 0) { mbedtls_printf("\n"); } return ret; } #undef TEST_ASSERT #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_ECJPAKE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecp.c000066400000000000000000003464471464416617300222710ustar00rootroot00000000000000/* * Elliptic curves over GF(p): generic functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * SEC1 https://www.secg.org/sec1-v2.pdf * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf * RFC 4492 for the related TLS structures and constants * - https://www.rfc-editor.org/rfc/rfc4492 * RFC 7748 for the Curve448 and Curve25519 curve definitions * - https://www.rfc-editor.org/rfc/rfc7748 * * [Curve25519] https://cr.yp.to/ecdh/curve25519-20060209.pdf * * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis * for elliptic curve cryptosystems. In : Cryptographic Hardware and * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. * * * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to * render ECC resistant against Side Channel Attacks. IACR Cryptology * ePrint Archive, 2004, vol. 2004, p. 342. * */ #include "common.h" /** * \brief Function level alternative implementation. * * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to * replace certain functions in this module. The alternative implementations are * typically hardware accelerators and need to activate the hardware before the * computation starts and deactivate it after it finishes. The * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve * this purpose. * * To preserve the correct functionality the following conditions must hold: * * - The alternative implementation must be activated by * mbedtls_internal_ecp_init() before any of the replaceable functions is * called. * - mbedtls_internal_ecp_free() must \b only be called when the alternative * implementation is activated. * - mbedtls_internal_ecp_init() must \b not be called when the alternative * implementation is activated. * - Public functions must not return while the alternative implementation is * activated. * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) * \endcode ensures that the alternative implementation supports the current * group. */ #if defined(MBEDTLS_ECP_INTERNAL_ALT) #endif #if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/threading.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "bn_mul.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) #include "mbedtls/platform.h" #include "ecp_internal_alt.h" #if defined(MBEDTLS_SELF_TEST) /* * Counts of point addition and doubling, and field multiplications. * Used to test resistance of point multiplication to simple timing attacks. */ #if defined(MBEDTLS_ECP_C) static unsigned long add_count, dbl_count; #endif /* MBEDTLS_ECP_C */ static unsigned long mul_count; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. * * Default value 0 means that ECC operations will not yield. * Note that regardless of the value of ecp_max_ops, always at * least one step is performed before yielding. * * Setting ecp_max_ops=1 can be suitable for testing purposes * as it will interrupt computation at all possible points. */ static unsigned ecp_max_ops = 0; /* * Set ecp_max_ops */ void mbedtls_ecp_set_max_ops(unsigned max_ops) { ecp_max_ops = max_ops; } /* * Check if restart is enabled */ int mbedtls_ecp_restart_is_enabled(void) { return ecp_max_ops != 0; } /* * Restart sub-context for ecp_mul_comb() */ struct mbedtls_ecp_restart_mul { mbedtls_ecp_point R; /* current intermediate result */ size_t i; /* current index in various loops, 0 outside */ mbedtls_ecp_point *T; /* table for precomputed points */ unsigned char T_size; /* number of points in table T */ enum { /* what were we doing last time we returned? */ ecp_rsm_init = 0, /* nothing so far, dummy initial state */ ecp_rsm_pre_dbl, /* precompute 2^n multiples */ ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ ecp_rsm_pre_add, /* precompute remaining points by adding */ ecp_rsm_pre_norm_add, /* normalize all precomputed points */ ecp_rsm_comb_core, /* ecp_mul_comb_core() */ ecp_rsm_final_norm, /* do the final normalization */ } state; }; /* * Init restart_mul sub-context */ static void ecp_restart_rsm_init(mbedtls_ecp_restart_mul_ctx *ctx) { mbedtls_ecp_point_init(&ctx->R); ctx->i = 0; ctx->T = NULL; ctx->T_size = 0; ctx->state = ecp_rsm_init; } /* * Free the components of a restart_mul sub-context */ static void ecp_restart_rsm_free(mbedtls_ecp_restart_mul_ctx *ctx) { unsigned char i; if (ctx == NULL) { return; } mbedtls_ecp_point_free(&ctx->R); if (ctx->T != NULL) { for (i = 0; i < ctx->T_size; i++) { mbedtls_ecp_point_free(ctx->T + i); } mbedtls_free(ctx->T); } ecp_restart_rsm_init(ctx); } /* * Restart context for ecp_muladd() */ struct mbedtls_ecp_restart_muladd { mbedtls_ecp_point mP; /* mP value */ mbedtls_ecp_point R; /* R intermediate result */ enum { /* what should we do next? */ ecp_rsma_mul1 = 0, /* first multiplication */ ecp_rsma_mul2, /* second multiplication */ ecp_rsma_add, /* addition */ ecp_rsma_norm, /* normalization */ } state; }; /* * Init restart_muladd sub-context */ static void ecp_restart_ma_init(mbedtls_ecp_restart_muladd_ctx *ctx) { mbedtls_ecp_point_init(&ctx->mP); mbedtls_ecp_point_init(&ctx->R); ctx->state = ecp_rsma_mul1; } /* * Free the components of a restart_muladd sub-context */ static void ecp_restart_ma_free(mbedtls_ecp_restart_muladd_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_ecp_point_free(&ctx->mP); mbedtls_ecp_point_free(&ctx->R); ecp_restart_ma_init(ctx); } /* * Initialize a restart context */ void mbedtls_ecp_restart_init(mbedtls_ecp_restart_ctx *ctx) { ctx->ops_done = 0; ctx->depth = 0; ctx->rsm = NULL; ctx->ma = NULL; } /* * Free the components of a restart context */ void mbedtls_ecp_restart_free(mbedtls_ecp_restart_ctx *ctx) { if (ctx == NULL) { return; } ecp_restart_rsm_free(ctx->rsm); mbedtls_free(ctx->rsm); ecp_restart_ma_free(ctx->ma); mbedtls_free(ctx->ma); mbedtls_ecp_restart_init(ctx); } /* * Check if we can do the next step */ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops) { if (rs_ctx != NULL && ecp_max_ops != 0) { /* scale depending on curve size: the chosen reference is 256-bit, * and multiplication is quadratic. Round to the closest integer. */ if (grp->pbits >= 512) { ops *= 4; } else if (grp->pbits >= 384) { ops *= 2; } /* Avoid infinite loops: always allow first step. * Because of that, however, it's not generally true * that ops_done <= ecp_max_ops, so the check * ops_done > ecp_max_ops below is mandatory. */ if ((rs_ctx->ops_done != 0) && (rs_ctx->ops_done > ecp_max_ops || ops > ecp_max_ops - rs_ctx->ops_done)) { return MBEDTLS_ERR_ECP_IN_PROGRESS; } /* update running count */ rs_ctx->ops_done += ops; } return 0; } /* Call this when entering a function that needs its own sub-context */ #define ECP_RS_ENTER(SUB) do { \ /* reset ops count for this call if top-level */ \ if (rs_ctx != NULL && rs_ctx->depth++ == 0) \ rs_ctx->ops_done = 0; \ \ /* set up our own sub-context if needed */ \ if (mbedtls_ecp_restart_is_enabled() && \ rs_ctx != NULL && rs_ctx->SUB == NULL) \ { \ rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \ if (rs_ctx->SUB == NULL) \ return MBEDTLS_ERR_ECP_ALLOC_FAILED; \ \ ecp_restart_## SUB ##_init(rs_ctx->SUB); \ } \ } while (0) /* Call this when leaving a function that needs its own sub-context */ #define ECP_RS_LEAVE(SUB) do { \ /* clear our sub-context when not in progress (done or error) */ \ if (rs_ctx != NULL && rs_ctx->SUB != NULL && \ ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \ { \ ecp_restart_## SUB ##_free(rs_ctx->SUB); \ mbedtls_free(rs_ctx->SUB); \ rs_ctx->SUB = NULL; \ } \ \ if (rs_ctx != NULL) \ rs_ctx->depth--; \ } while (0) #else /* MBEDTLS_ECP_RESTARTABLE */ #define ECP_RS_ENTER(sub) (void) rs_ctx; #define ECP_RS_LEAVE(sub) (void) rs_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_C) static void mpi_init_many(mbedtls_mpi *arr, size_t size) { while (size--) { mbedtls_mpi_init(arr++); } } static void mpi_free_many(mbedtls_mpi *arr, size_t size) { while (size--) { mbedtls_mpi_free(arr++); } } #endif /* MBEDTLS_ECP_C */ /* * List of supported curves: * - internal ID * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7) * - size in bits * - readable name * * Curves are listed in order: largest curves first, and for a given size, * fastest curves first. * * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve! */ static const mbedtls_ecp_curve_info ecp_supported_curves[] = { #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) { MBEDTLS_ECP_DP_CURVE25519, 29, 256, "x25519" }, #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) { MBEDTLS_ECP_DP_CURVE448, 30, 448, "x448" }, #endif #if defined(MBEDTLS_ECP_DP_SM2_ENABLED) /* https://tools.ietf.org/id/draft-yang-tls-tls13-sm-suites-05.html */ { MBEDTLS_ECP_DP_SM2, 41, 256, "sm2" }, #endif { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, }; #define ECP_NB_CURVES sizeof(ecp_supported_curves) / \ sizeof(ecp_supported_curves[0]) static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; /* * List of supported curves and associated info */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list(void) { return ecp_supported_curves; } /* * List of supported curves, group ID only */ const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list(void) { static int init_done = 0; if (!init_done) { size_t i = 0; const mbedtls_ecp_curve_info *curve_info; for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { ecp_supported_grp_id[i++] = curve_info->grp_id; } ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; init_done = 1; } return ecp_supported_grp_id; } /* * Get the curve info for the internal identifier */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id(mbedtls_ecp_group_id grp_id) { const mbedtls_ecp_curve_info *curve_info; for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { if (curve_info->grp_id == grp_id) { return curve_info; } } return NULL; } /* * Get the curve info from the TLS identifier */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id(uint16_t tls_id) { const mbedtls_ecp_curve_info *curve_info; for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { if (curve_info->tls_id == tls_id) { return curve_info; } } return NULL; } /* * Get the curve info from the name */ const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name(const char *name) { const mbedtls_ecp_curve_info *curve_info; if (name == NULL) { return NULL; } for (curve_info = mbedtls_ecp_curve_list(); curve_info->grp_id != MBEDTLS_ECP_DP_NONE; curve_info++) { if (strcmp(curve_info->name, name) == 0) { return curve_info; } } return NULL; } /* * Get the type of a curve */ mbedtls_ecp_curve_type mbedtls_ecp_get_type(const mbedtls_ecp_group *grp) { if (grp->G.X.p == NULL) { return MBEDTLS_ECP_TYPE_NONE; } if (grp->G.Y.p == NULL) { return MBEDTLS_ECP_TYPE_MONTGOMERY; } else { return MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS; } } /* * Initialize (the components of) a point */ void mbedtls_ecp_point_init(mbedtls_ecp_point *pt) { mbedtls_mpi_init(&pt->X); mbedtls_mpi_init(&pt->Y); mbedtls_mpi_init(&pt->Z); } /* * Initialize (the components of) a group */ void mbedtls_ecp_group_init(mbedtls_ecp_group *grp) { grp->id = MBEDTLS_ECP_DP_NONE; mbedtls_mpi_init(&grp->P); mbedtls_mpi_init(&grp->A); mbedtls_mpi_init(&grp->B); mbedtls_ecp_point_init(&grp->G); mbedtls_mpi_init(&grp->N); grp->pbits = 0; grp->nbits = 0; grp->h = 0; grp->modp = NULL; grp->t_pre = NULL; grp->t_post = NULL; grp->t_data = NULL; grp->T = NULL; grp->T_size = 0; } /* * Initialize (the components of) a key pair */ void mbedtls_ecp_keypair_init(mbedtls_ecp_keypair *key) { mbedtls_ecp_group_init(&key->grp); mbedtls_mpi_init(&key->d); mbedtls_ecp_point_init(&key->Q); } /* * Unallocate (the components of) a point */ void mbedtls_ecp_point_free(mbedtls_ecp_point *pt) { if (pt == NULL) { return; } mbedtls_mpi_free(&(pt->X)); mbedtls_mpi_free(&(pt->Y)); mbedtls_mpi_free(&(pt->Z)); } /* * Check that the comb table (grp->T) is static initialized. */ static int ecp_group_is_static_comb_table(const mbedtls_ecp_group *grp) { #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 return grp->T != NULL && grp->T_size == 0; #else (void) grp; return 0; #endif } /* * Unallocate (the components of) a group */ void mbedtls_ecp_group_free(mbedtls_ecp_group *grp) { size_t i; if (grp == NULL) { return; } if (grp->h != 1) { mbedtls_mpi_free(&grp->A); mbedtls_mpi_free(&grp->B); mbedtls_ecp_point_free(&grp->G); #if !defined(MBEDTLS_ECP_WITH_MPI_UINT) mbedtls_mpi_free(&grp->N); mbedtls_mpi_free(&grp->P); #endif } if (!ecp_group_is_static_comb_table(grp) && grp->T != NULL) { for (i = 0; i < grp->T_size; i++) { mbedtls_ecp_point_free(&grp->T[i]); } mbedtls_free(grp->T); } mbedtls_platform_zeroize(grp, sizeof(mbedtls_ecp_group)); } /* * Unallocate (the components of) a key pair */ void mbedtls_ecp_keypair_free(mbedtls_ecp_keypair *key) { if (key == NULL) { return; } mbedtls_ecp_group_free(&key->grp); mbedtls_mpi_free(&key->d); mbedtls_ecp_point_free(&key->Q); } /* * Copy the contents of a point */ int mbedtls_ecp_copy(mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->X, &Q->X)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Y, &Q->Y)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&P->Z, &Q->Z)); cleanup: return ret; } /* * Copy the contents of a group object */ int mbedtls_ecp_group_copy(mbedtls_ecp_group *dst, const mbedtls_ecp_group *src) { return mbedtls_ecp_group_load(dst, src->id); } /* * Set point to zero */ int mbedtls_ecp_set_zero(mbedtls_ecp_point *pt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Y, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 0)); cleanup: return ret; } /* * Tell if a point is zero */ int mbedtls_ecp_is_zero(mbedtls_ecp_point *pt) { return mbedtls_mpi_cmp_int(&pt->Z, 0) == 0; } /* * Compare two points lazily */ int mbedtls_ecp_point_cmp(const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q) { if (mbedtls_mpi_cmp_mpi(&P->X, &Q->X) == 0 && mbedtls_mpi_cmp_mpi(&P->Y, &Q->Y) == 0 && mbedtls_mpi_cmp_mpi(&P->Z, &Q->Z) == 0) { return 0; } return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Import a non-zero point from ASCII strings */ int mbedtls_ecp_point_read_string(mbedtls_ecp_point *P, int radix, const char *x, const char *y) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->X, radix, x)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&P->Y, radix, y)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&P->Z, 1)); cleanup: return ret; } /* * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748) */ int mbedtls_ecp_point_write_binary(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, int format, size_t *olen, unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; size_t plen; if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && format != MBEDTLS_ECP_PF_COMPRESSED) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } plen = mbedtls_mpi_size(&grp->P); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) (void) format; /* Montgomery curves always use the same point format */ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { *olen = plen; if (buflen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->X, buf, plen)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { /* * Common case: P == 0 */ if (mbedtls_mpi_cmp_int(&P->Z, 0) == 0) { if (buflen < 1) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } buf[0] = 0x00; *olen = 1; return 0; } if (format == MBEDTLS_ECP_PF_UNCOMPRESSED) { *olen = 2 * plen + 1; if (buflen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } buf[0] = 0x04; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->Y, buf + 1 + plen, plen)); } else if (format == MBEDTLS_ECP_PF_COMPRESSED) { *olen = plen + 1; if (buflen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } buf[0] = 0x02 + mbedtls_mpi_get_bit(&P->Y, 0); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&P->X, buf + 1, plen)); } } #endif cleanup: return ret; } #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, const mbedtls_mpi *X, mbedtls_mpi *Y, int parity_bit); #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ /* * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748) */ int mbedtls_ecp_point_read_binary(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char *buf, size_t ilen) { int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; size_t plen; if (ilen < 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } plen = mbedtls_mpi_size(&grp->P); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { if (plen != ilen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&pt->X, buf, plen)); mbedtls_mpi_free(&pt->Y); if (grp->id == MBEDTLS_ECP_DP_CURVE25519) { /* Set most significant bit to 0 as prescribed in RFC7748 §5 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&pt->X, plen * 8 - 1, 0)); } MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { if (buf[0] == 0x00) { if (ilen == 1) { return mbedtls_ecp_set_zero(pt); } else { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } if (ilen < 1 + plen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&pt->X, buf + 1, plen)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&pt->Z, 1)); if (buf[0] == 0x04) { /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */ if (ilen != 1 + plen * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return mbedtls_mpi_read_binary(&pt->Y, buf + 1 + plen, plen); } else if (buf[0] == 0x02 || buf[0] == 0x03) { /* format == MBEDTLS_ECP_PF_COMPRESSED */ if (ilen != 1 + plen) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return mbedtls_ecp_sw_derive_y(grp, &pt->X, &pt->Y, (buf[0] & 1)); } else { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } } #endif cleanup: return ret; } /* * Import a point from a TLS ECPoint record (RFC 4492) * struct { * opaque point <1..2^8-1>; * } ECPoint; */ int mbedtls_ecp_tls_read_point(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, const unsigned char **buf, size_t buf_len) { unsigned char data_len; const unsigned char *buf_start; /* * We must have at least two bytes (1 for length, at least one for data) */ if (buf_len < 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } data_len = *(*buf)++; if (data_len < 1 || data_len > buf_len - 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Save buffer start for read_binary and update buf */ buf_start = *buf; *buf += data_len; return mbedtls_ecp_point_read_binary(grp, pt, buf_start, data_len); } /* * Export a point as a TLS ECPoint record (RFC 4492) * struct { * opaque point <1..2^8-1>; * } ECPoint; */ int mbedtls_ecp_tls_write_point(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, int format, size_t *olen, unsigned char *buf, size_t blen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (format != MBEDTLS_ECP_PF_UNCOMPRESSED && format != MBEDTLS_ECP_PF_COMPRESSED) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * buffer length must be at least one, for our length byte */ if (blen < 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if ((ret = mbedtls_ecp_point_write_binary(grp, pt, format, olen, buf + 1, blen - 1)) != 0) { return ret; } /* * write length to the first byte and update total length */ buf[0] = (unsigned char) *olen; ++*olen; return 0; } /* * Set a group from an ECParameters record (RFC 4492) */ int mbedtls_ecp_tls_read_group(mbedtls_ecp_group *grp, const unsigned char **buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, len)) != 0) { return ret; } return mbedtls_ecp_group_load(grp, grp_id); } /* * Read a group id from an ECParameters record (RFC 4492) and convert it to * mbedtls_ecp_group_id. */ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp, const unsigned char **buf, size_t len) { uint16_t tls_id; const mbedtls_ecp_curve_info *curve_info; /* * We expect at least three bytes (see below) */ if (len < 3) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * First byte is curve_type; only named_curve is handled */ if (*(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Next two bytes are the namedcurve value */ tls_id = MBEDTLS_GET_UINT16_BE(*buf, 0); *buf += 2; if ((curve_info = mbedtls_ecp_curve_info_from_tls_id(tls_id)) == NULL) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } *grp = curve_info->grp_id; return 0; } /* * Write the ECParameters record corresponding to a group (RFC 4492) */ int mbedtls_ecp_tls_write_group(const mbedtls_ecp_group *grp, size_t *olen, unsigned char *buf, size_t blen) { const mbedtls_ecp_curve_info *curve_info; if ((curve_info = mbedtls_ecp_curve_info_from_grp_id(grp->id)) == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * We are going to write 3 bytes (see below) */ *olen = 3; if (blen < *olen) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } /* * First byte is curve_type, always named_curve */ *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; /* * Next two bytes are the namedcurve value */ MBEDTLS_PUT_UINT16_BE(curve_info->tls_id, buf, 0); return 0; } /* * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. * See the documentation of struct mbedtls_ecp_group. * * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. */ static int ecp_modp(mbedtls_mpi *N, const mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (grp->modp == NULL) { return mbedtls_mpi_mod_mpi(N, N, &grp->P); } /* N->s < 0 is a much faster test, which fails only if N is 0 */ if ((N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) || mbedtls_mpi_bitlen(N) > 2 * grp->pbits) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MBEDTLS_MPI_CHK(grp->modp(N)); /* N->s < 0 is a much faster test, which fails only if N is 0 */ while (N->s < 0 && mbedtls_mpi_cmp_int(N, 0) != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &grp->P)); } while (mbedtls_mpi_cmp_mpi(N, &grp->P) >= 0) { /* we known P, N and the result are positive */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs(N, N, &grp->P)); } cleanup: return ret; } /* * Fast mod-p functions expect their argument to be in the 0..p^2 range. * * In order to guarantee that, we need to ensure that operands of * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will * bring the result back to this range. * * The following macros are shortcuts for doing that. */ /* * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi */ #if defined(MBEDTLS_SELF_TEST) #define INC_MUL_COUNT mul_count++; #else #define INC_MUL_COUNT #endif #define MOD_MUL(N) \ do \ { \ MBEDTLS_MPI_CHK(ecp_modp(&(N), grp)); \ INC_MUL_COUNT \ } while (0) static inline int mbedtls_mpi_mul_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(X, A, B)); MOD_MUL(*X); cleanup: return ret; } /* * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi * N->s < 0 is a very fast test, which fails only if N is 0 */ #define MOD_SUB(N) \ do { \ while ((N)->s < 0 && mbedtls_mpi_cmp_int((N), 0) != 0) \ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P)); \ } while (0) MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(X, A, B)); MOD_SUB(X); cleanup: return ret; } /* * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. * We known P, N and the result are positive, so sub_abs is correct, and * a bit faster. */ #define MOD_ADD(N) \ while (mbedtls_mpi_cmp_mpi((N), &grp->P) >= 0) \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_abs((N), (N), &grp->P)) static inline int mbedtls_mpi_add_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, A, B)); MOD_ADD(X); cleanup: return ret; } MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint c) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int(X, A, c)); MOD_ADD(X); cleanup: return ret; } MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint c) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(X, A, c)); MOD_SUB(X); cleanup: return ret; } #define MPI_ECP_SUB_INT(X, A, c) \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c)) MBEDTLS_MAYBE_UNUSED static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp, mbedtls_mpi *X, size_t count) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(X, count)); MOD_ADD(X); cleanup: return ret; } /* * Macro wrappers around ECP modular arithmetic * * Currently, these wrappers are defined via the bignum module. */ #define MPI_ECP_ADD(X, A, B) \ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mod(grp, X, A, B)) #define MPI_ECP_SUB(X, A, B) \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mod(grp, X, A, B)) #define MPI_ECP_MUL(X, A, B) \ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, B)) #define MPI_ECP_SQR(X, A) \ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mod(grp, X, A, A)) #define MPI_ECP_MUL_INT(X, A, c) \ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_int_mod(grp, X, A, c)) #define MPI_ECP_INV(dst, src) \ MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod((dst), (src), &grp->P)) #define MPI_ECP_MOV(X, A) \ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A)) #define MPI_ECP_SHIFT_L(X, count) \ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l_mod(grp, X, count)) #define MPI_ECP_LSET(X, c) \ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, c)) #define MPI_ECP_CMP_INT(X, c) \ mbedtls_mpi_cmp_int(X, c) #define MPI_ECP_CMP(X, Y) \ mbedtls_mpi_cmp_mpi(X, Y) /* Needs f_rng, p_rng to be defined. */ #define MPI_ECP_RAND(X) \ MBEDTLS_MPI_CHK(mbedtls_mpi_random((X), 2, &grp->P, f_rng, p_rng)) /* Conditional negation * Needs grp and a temporary MPI tmp to be defined. */ #define MPI_ECP_COND_NEG(X, cond) \ do \ { \ unsigned char nonzero = mbedtls_mpi_cmp_int((X), 0) != 0; \ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&tmp, &grp->P, (X))); \ MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), &tmp, \ nonzero & cond)); \ } while (0) #define MPI_ECP_NEG(X) MPI_ECP_COND_NEG((X), 1) #define MPI_ECP_VALID(X) \ ((X)->p != NULL) #define MPI_ECP_COND_ASSIGN(X, Y, cond) \ MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign((X), (Y), (cond))) #define MPI_ECP_COND_SWAP(X, Y, cond) \ MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_swap((X), (Y), (cond))) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * Computes the right-hand side of the Short Weierstrass equation * RHS = X^3 + A X + B */ static int ecp_sw_rhs(const mbedtls_ecp_group *grp, mbedtls_mpi *rhs, const mbedtls_mpi *X) { int ret; /* Compute X^3 + A X + B as X (X^2 + A) + B */ MPI_ECP_SQR(rhs, X); /* Special case for A = -3 */ if (mbedtls_ecp_group_a_is_minus_3(grp)) { MPI_ECP_SUB_INT(rhs, rhs, 3); } else { MPI_ECP_ADD(rhs, rhs, &grp->A); } MPI_ECP_MUL(rhs, rhs, X); MPI_ECP_ADD(rhs, rhs, &grp->B); cleanup: return ret; } /* * Derive Y from X and a parity bit */ static int mbedtls_ecp_sw_derive_y(const mbedtls_ecp_group *grp, const mbedtls_mpi *X, mbedtls_mpi *Y, int parity_bit) { /* w = y^2 = x^3 + ax + b * y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) * * Note: this method for extracting square root does not validate that w * was indeed a square so this function will return garbage in Y if X * does not correspond to a point on the curve. */ /* Check prerequisite p = 3 mod 4 */ if (mbedtls_mpi_get_bit(&grp->P, 0) != 1 || mbedtls_mpi_get_bit(&grp->P, 1) != 1) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } int ret; mbedtls_mpi exp; mbedtls_mpi_init(&exp); /* use Y to store intermediate result, actually w above */ MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, Y, X)); /* w = y^2 */ /* Y contains y^2 intermediate result */ /* exp = ((p+1)/4) */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&exp, &grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 2)); /* sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(Y, Y /*y^2*/, &exp, &grp->P, NULL)); /* check parity bit match or else invert Y */ /* This quick inversion implementation is valid because Y != 0 for all * Short Weierstrass curves supported by mbedtls, as each supported curve * has an order that is a large prime, so each supported curve does not * have any point of order 2, and a point with Y == 0 would be of order 2 */ if (mbedtls_mpi_get_bit(Y, 0) != parity_bit) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(Y, &grp->P, Y)); } cleanup: mbedtls_mpi_free(&exp); return ret; } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * For curves in short Weierstrass form, we do all the internal operations in * Jacobian coordinates. * * For multiplication, we'll use a comb method with countermeasures against * SPA, hence timing attacks. */ /* * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) * Cost: 1N := 1I + 3M + 1S */ static int ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt) { if (MPI_ECP_CMP_INT(&pt->Z, 0) == 0) { return 0; } #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_normalize_jac(grp, pt); } #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi T; mbedtls_mpi_init(&T); MPI_ECP_INV(&T, &pt->Z); /* T <- 1 / Z */ MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y' <- Y*T = Y / Z */ MPI_ECP_SQR(&T, &T); /* T <- T^2 = 1 / Z^2 */ MPI_ECP_MUL(&pt->X, &pt->X, &T); /* X <- X * T = X / Z^2 */ MPI_ECP_MUL(&pt->Y, &pt->Y, &T); /* Y'' <- Y' * T = Y / Z^3 */ MPI_ECP_LSET(&pt->Z, 1); cleanup: mbedtls_mpi_free(&T); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */ } /* * Normalize jacobian coordinates of an array of (pointers to) points, * using Montgomery's trick to perform only one inversion mod P. * (See for example Cohen's "A Course in Computational Algebraic Number * Theory", Algorithm 10.3.4.) * * Warning: fails (returning an error) if one of the points is zero! * This should never happen, see choice of w in ecp_mul_comb(). * * Cost: 1N(t) := 1I + (6t - 3)M + 1S */ static int ecp_normalize_jac_many(const mbedtls_ecp_group *grp, mbedtls_ecp_point *T[], size_t T_size) { if (T_size < 2) { return ecp_normalize_jac(grp, *T); } #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_normalize_jac_many(grp, T, T_size); } #endif #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi *c, t; if ((c = mbedtls_calloc(T_size, sizeof(mbedtls_mpi))) == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } mbedtls_mpi_init(&t); mpi_init_many(c, T_size); /* * c[i] = Z_0 * ... * Z_i, i = 0,..,n := T_size-1 */ MPI_ECP_MOV(&c[0], &T[0]->Z); for (i = 1; i < T_size; i++) { MPI_ECP_MUL(&c[i], &c[i-1], &T[i]->Z); } /* * c[n] = 1 / (Z_0 * ... * Z_n) mod P */ MPI_ECP_INV(&c[T_size-1], &c[T_size-1]); for (i = T_size - 1;; i--) { /* At the start of iteration i (note that i decrements), we have * - c[j] = Z_0 * .... * Z_j for j < i, * - c[j] = 1 / (Z_0 * .... * Z_j) for j == i, * * This is maintained via * - c[i-1] <- c[i] * Z_i * * We also derive 1/Z_i = c[i] * c[i-1] for i>0 and use that * to do the actual normalization. For i==0, we already have * c[0] = 1 / Z_0. */ if (i > 0) { /* Compute 1/Z_i and establish invariant for the next iteration. */ MPI_ECP_MUL(&t, &c[i], &c[i-1]); MPI_ECP_MUL(&c[i-1], &c[i], &T[i]->Z); } else { MPI_ECP_MOV(&t, &c[0]); } /* Now t holds 1 / Z_i; normalize as in ecp_normalize_jac() */ MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); MPI_ECP_SQR(&t, &t); MPI_ECP_MUL(&T[i]->X, &T[i]->X, &t); MPI_ECP_MUL(&T[i]->Y, &T[i]->Y, &t); /* * Post-precessing: reclaim some memory by shrinking coordinates * - not storing Z (always 1) * - shrinking other coordinates, but still keeping the same number of * limbs as P, as otherwise it will too likely be regrown too fast. */ MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->X, grp->P.n)); MBEDTLS_MPI_CHK(mbedtls_mpi_shrink(&T[i]->Y, grp->P.n)); MPI_ECP_LSET(&T[i]->Z, 1); if (i == 0) { break; } } cleanup: mbedtls_mpi_free(&t); mpi_free_many(c, T_size); mbedtls_free(c); return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */ } /* * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid */ static int ecp_safe_invert_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *Q, unsigned char inv) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi tmp; mbedtls_mpi_init(&tmp); MPI_ECP_COND_NEG(&Q->Y, inv); cleanup: mbedtls_mpi_free(&tmp); return ret; } /* * Point doubling R = 2 P, Jacobian coordinates * * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . * * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. * * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. * * Cost: 1D := 3M + 4S (A == 0) * 4M + 4S (A == -3) * 3M + 6S + 1a otherwise */ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P, mbedtls_mpi tmp[4]) { #if defined(MBEDTLS_SELF_TEST) dbl_count++; #endif #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_double_jac(grp, R, P); } #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Special case for A = -3 */ if (mbedtls_ecp_group_a_is_minus_3(grp)) { /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */ MPI_ECP_SQR(&tmp[1], &P->Z); MPI_ECP_ADD(&tmp[2], &P->X, &tmp[1]); MPI_ECP_SUB(&tmp[3], &P->X, &tmp[1]); MPI_ECP_MUL(&tmp[1], &tmp[2], &tmp[3]); MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); } else { /* tmp[0] <- M = 3.X^2 + A.Z^4 */ MPI_ECP_SQR(&tmp[1], &P->X); MPI_ECP_MUL_INT(&tmp[0], &tmp[1], 3); /* Optimize away for "koblitz" curves with A = 0 */ if (MPI_ECP_CMP_INT(&grp->A, 0) != 0) { /* M += A.Z^4 */ MPI_ECP_SQR(&tmp[1], &P->Z); MPI_ECP_SQR(&tmp[2], &tmp[1]); MPI_ECP_MUL(&tmp[1], &tmp[2], &grp->A); MPI_ECP_ADD(&tmp[0], &tmp[0], &tmp[1]); } } /* tmp[1] <- S = 4.X.Y^2 */ MPI_ECP_SQR(&tmp[2], &P->Y); MPI_ECP_SHIFT_L(&tmp[2], 1); MPI_ECP_MUL(&tmp[1], &P->X, &tmp[2]); MPI_ECP_SHIFT_L(&tmp[1], 1); /* tmp[3] <- U = 8.Y^4 */ MPI_ECP_SQR(&tmp[3], &tmp[2]); MPI_ECP_SHIFT_L(&tmp[3], 1); /* tmp[2] <- T = M^2 - 2.S */ MPI_ECP_SQR(&tmp[2], &tmp[0]); MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); MPI_ECP_SUB(&tmp[2], &tmp[2], &tmp[1]); /* tmp[1] <- S = M(S - T) - U */ MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[2]); MPI_ECP_MUL(&tmp[1], &tmp[1], &tmp[0]); MPI_ECP_SUB(&tmp[1], &tmp[1], &tmp[3]); /* tmp[3] <- U = 2.Y.Z */ MPI_ECP_MUL(&tmp[3], &P->Y, &P->Z); MPI_ECP_SHIFT_L(&tmp[3], 1); /* Store results */ MPI_ECP_MOV(&R->X, &tmp[2]); MPI_ECP_MOV(&R->Y, &tmp[1]); MPI_ECP_MOV(&R->Z, &tmp[3]); cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */ } /* * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) * * The coordinates of Q must be normalized (= affine), * but those of P don't need to. R is not normalized. * * P,Q,R may alias, but only at the level of EC points: they must be either * equal as pointers, or disjoint (including the coordinate data buffers). * Fine-grained aliasing at the level of coordinates is not supported. * * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. * None of these cases can happen as intermediate step in ecp_mul_comb(): * - at each step, P, Q and R are multiples of the base point, the factor * being less than its order, so none of them is zero; * - Q is an odd multiple of the base point, P an even multiple, * due to the choice of precomputed points in the modified comb method. * So branches for these cases do not leak secret information. * * Cost: 1A := 8M + 3S */ static int ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, mbedtls_mpi tmp[4]) { #if defined(MBEDTLS_SELF_TEST) add_count++; #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_add_mixed(grp, R, P, Q); } #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* NOTE: Aliasing between input and output is allowed, so one has to make * sure that at the point X,Y,Z are written, {P,Q}->{X,Y,Z} are no * longer read from. */ mbedtls_mpi * const X = &R->X; mbedtls_mpi * const Y = &R->Y; mbedtls_mpi * const Z = &R->Z; if (!MPI_ECP_VALID(&Q->Z)) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Trivial cases: P == 0 or Q == 0 (case 1) */ if (MPI_ECP_CMP_INT(&P->Z, 0) == 0) { return mbedtls_ecp_copy(R, Q); } if (MPI_ECP_CMP_INT(&Q->Z, 0) == 0) { return mbedtls_ecp_copy(R, P); } /* * Make sure Q coordinates are normalized */ if (MPI_ECP_CMP_INT(&Q->Z, 1) != 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } MPI_ECP_SQR(&tmp[0], &P->Z); MPI_ECP_MUL(&tmp[1], &tmp[0], &P->Z); MPI_ECP_MUL(&tmp[0], &tmp[0], &Q->X); MPI_ECP_MUL(&tmp[1], &tmp[1], &Q->Y); MPI_ECP_SUB(&tmp[0], &tmp[0], &P->X); MPI_ECP_SUB(&tmp[1], &tmp[1], &P->Y); /* Special cases (2) and (3) */ if (MPI_ECP_CMP_INT(&tmp[0], 0) == 0) { if (MPI_ECP_CMP_INT(&tmp[1], 0) == 0) { ret = ecp_double_jac(grp, R, P, tmp); goto cleanup; } else { ret = mbedtls_ecp_set_zero(R); goto cleanup; } } /* {P,Q}->Z no longer used, so OK to write to Z even if there's aliasing. */ MPI_ECP_MUL(Z, &P->Z, &tmp[0]); MPI_ECP_SQR(&tmp[2], &tmp[0]); MPI_ECP_MUL(&tmp[3], &tmp[2], &tmp[0]); MPI_ECP_MUL(&tmp[2], &tmp[2], &P->X); MPI_ECP_MOV(&tmp[0], &tmp[2]); MPI_ECP_SHIFT_L(&tmp[0], 1); /* {P,Q}->X no longer used, so OK to write to X even if there's aliasing. */ MPI_ECP_SQR(X, &tmp[1]); MPI_ECP_SUB(X, X, &tmp[0]); MPI_ECP_SUB(X, X, &tmp[3]); MPI_ECP_SUB(&tmp[2], &tmp[2], X); MPI_ECP_MUL(&tmp[2], &tmp[2], &tmp[1]); MPI_ECP_MUL(&tmp[3], &tmp[3], &P->Y); /* {P,Q}->Y no longer used, so OK to write to Y even if there's aliasing. */ MPI_ECP_SUB(Y, &tmp[2], &tmp[3]); cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */ } /* * Randomize jacobian coordinates: * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l * This is sort of the reverse operation of ecp_normalize_jac(). * * This countermeasure was first suggested in [2]. */ static int ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_randomize_jac(grp, pt, f_rng, p_rng); } #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi l; mbedtls_mpi_init(&l); /* Generate l such that 1 < l < p */ MPI_ECP_RAND(&l); /* Z' = l * Z */ MPI_ECP_MUL(&pt->Z, &pt->Z, &l); /* Y' = l * Y */ MPI_ECP_MUL(&pt->Y, &pt->Y, &l); /* X' = l^2 * X */ MPI_ECP_SQR(&l, &l); MPI_ECP_MUL(&pt->X, &pt->X, &l); /* Y'' = l^2 * Y' = l^3 * Y */ MPI_ECP_MUL(&pt->Y, &pt->Y, &l); cleanup: mbedtls_mpi_free(&l); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; } return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */ } /* * Check and define parameters used by the comb method (see below for details) */ #if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 #error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" #endif /* d = ceil( n / w ) */ #define COMB_MAX_D (MBEDTLS_ECP_MAX_BITS + 1) / 2 /* number of precomputed points */ #define COMB_MAX_PRE (1 << (MBEDTLS_ECP_WINDOW_SIZE - 1)) /* * Compute the representation of m that will be used with our comb method. * * The basic comb method is described in GECC 3.44 for example. We use a * modified version that provides resistance to SPA by avoiding zero * digits in the representation as in [3]. We modify the method further by * requiring that all K_i be odd, which has the small cost that our * representation uses one more K_i, due to carries, but saves on the size of * the precomputed table. * * Summary of the comb method and its modifications: * * - The goal is to compute m*P for some w*d-bit integer m. * * - The basic comb method splits m into the w-bit integers * x[0] .. x[d-1] where x[i] consists of the bits in m whose * index has residue i modulo d, and computes m * P as * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. * * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., * thereby successively converting it into a form where all summands * are nonzero, at the cost of negative summands. This is the basic idea of [3]. * * - More generally, even if x[i+1] != 0, we can first transform the sum as * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. * Performing and iterating this procedure for those x[i] that are even * (keeping track of carry), we can transform the original sum into one of the form * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] * with all x'[i] odd. It is therefore only necessary to know S at odd indices, * which is why we are only computing half of it in the first place in * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. * * - For the sake of compactness, only the seven low-order bits of x[i] * are used to represent its absolute value (K_i in the paper), and the msb * of x[i] encodes the sign (s_i in the paper): it is set if and only if * if s_i == -1; * * Calling conventions: * - x is an array of size d + 1 * - w is the size, ie number of teeth, of the comb, and must be between * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d * (the result will be incorrect if these assumptions are not satisfied) */ static void ecp_comb_recode_core(unsigned char x[], size_t d, unsigned char w, const mbedtls_mpi *m) { size_t i, j; unsigned char c, cc, adjust; memset(x, 0, d+1); /* First get the classical comb values (except for x_d = 0) */ for (i = 0; i < d; i++) { for (j = 0; j < w; j++) { x[i] |= mbedtls_mpi_get_bit(m, i + d * j) << j; } } /* Now make sure x_1 .. x_d are odd */ c = 0; for (i = 1; i <= d; i++) { /* Add carry and update it */ cc = x[i] & c; x[i] = x[i] ^ c; c = cc; /* Adjust if needed, avoiding branches */ adjust = 1 - (x[i] & 0x01); c |= x[i] & (x[i-1] * adjust); x[i] = x[i] ^ (x[i-1] * adjust); x[i-1] |= adjust << 7; } } /* * Precompute points for the adapted comb method * * Assumption: T must be able to hold 2^{w - 1} elements. * * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. * * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) * * Note: Even comb values (those where P would be omitted from the * sum defining T[i] above) are not needed in our adaption * the comb method. See ecp_comb_recode_core(). * * This function currently works in four steps: * (1) [dbl] Computation of intermediate T[i] for 2-power values of i * (2) [norm_dbl] Normalization of coordinates of these T[i] * (3) [add] Computation of all T[i] * (4) [norm_add] Normalization of all T[i] * * Step 1 can be interrupted but not the others; together with the final * coordinate normalization they are the largest steps done at once, depending * on the window size. Here are operation counts for P-256: * * step (2) (3) (4) * w = 5 142 165 208 * w = 4 136 77 160 * w = 3 130 33 136 * w = 2 124 11 124 * * So if ECC operations are blocking for too long even with a low max_ops * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order * to minimize maximum blocking time. */ static int ecp_precompute_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point T[], const mbedtls_ecp_point *P, unsigned char w, size_t d, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char i; size_t j = 0; const unsigned char T_size = 1U << (w - 1); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1] = { NULL }; mbedtls_mpi tmp[4]; mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) { goto dbl; } if (rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl) { goto norm_dbl; } if (rs_ctx->rsm->state == ecp_rsm_pre_add) { goto add; } if (rs_ctx->rsm->state == ecp_rsm_pre_norm_add) { goto norm_add; } } #else (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_dbl; /* initial state for the loop */ rs_ctx->rsm->i = 0; } dbl: #endif /* * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&T[0], P)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) { j = rs_ctx->rsm->i; } else #endif j = 0; for (; j < d * (w - 1); j++) { MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL); i = 1U << (j / d); cur = T + i; if (j % d == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_copy(cur, T + (i >> 1))); } MBEDTLS_MPI_CHK(ecp_double_jac(grp, cur, cur, tmp)); } #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; } norm_dbl: #endif /* * Normalize current elements in T to allow them to be used in * ecp_add_mixed() below, which requires one normalized input. * * As T has holes, use an auxiliary array of pointers to elements in T. * */ j = 0; for (i = 1; i < T_size; i <<= 1) { TT[j++] = T + i; } MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2); MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_add; } add: #endif /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ MBEDTLS_ECP_BUDGET((T_size - 1) * MBEDTLS_ECP_OPS_ADD); for (i = 1; i < T_size; i <<= 1) { j = i; while (j--) { MBEDTLS_MPI_CHK(ecp_add_mixed(grp, &T[i + j], &T[j], &T[i], tmp)); } } #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_pre_norm_add; } norm_add: #endif /* * Normalize final elements in T. Even though there are no holes now, we * still need the auxiliary array for homogeneity with the previous * call. Also, skip T[0] which is already normalised, being a copy of P. */ for (j = 0; j + 1 < T_size; j++) { TT[j] = T + j + 1; } MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV + 6 * j - 2); MBEDTLS_MPI_CHK(ecp_normalize_jac_many(grp, TT, j)); /* Free Z coordinate (=1 after normalization) to save RAM. * This makes T[i] invalid as mbedtls_ecp_points, but this is OK * since from this point onwards, they are only accessed indirectly * via the getter function ecp_select_comb() which does set the * target's Z coordinate to 1. */ for (i = 0; i < T_size; i++) { mbedtls_mpi_free(&T[i].Z); } cleanup: mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { if (rs_ctx->rsm->state == ecp_rsm_pre_dbl) { rs_ctx->rsm->i = j; } } #endif return ret; } /* * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] * * See ecp_comb_recode_core() for background */ static int ecp_select_comb(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point T[], unsigned char T_size, unsigned char i) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char ii, j; /* Ignore the "sign" bit and scale down */ ii = (i & 0x7Fu) >> 1; /* Read the whole table to thwart cache-based timing attacks */ for (j = 0; j < T_size; j++) { MPI_ECP_COND_ASSIGN(&R->X, &T[j].X, j == ii); MPI_ECP_COND_ASSIGN(&R->Y, &T[j].Y, j == ii); } /* Safely invert result if i is "negative" */ MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, R, i >> 7)); MPI_ECP_LSET(&R->Z, 1); cleanup: return ret; } /* * Core multiplication algorithm for the (modified) comb method. * This part is actually common with the basic comb method (GECC 3.44) * * Cost: d A + d D + 1 R */ static int ecp_mul_comb_core(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point T[], unsigned char T_size, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point Txi; mbedtls_mpi tmp[4]; size_t i; mbedtls_ecp_point_init(&Txi); mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->state != ecp_rsm_comb_core) { rs_ctx->rsm->i = 0; rs_ctx->rsm->state = ecp_rsm_comb_core; } /* new 'if' instead of nested for the sake of the 'else' branch */ if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0) { /* restore current index (R already pointing to rs_ctx->rsm->R) */ i = rs_ctx->rsm->i; } else #endif { /* Start with a non-zero point and randomize its coordinates */ i = d; MBEDTLS_MPI_CHK(ecp_select_comb(grp, R, T, T_size, x[i])); if (f_rng != 0) { MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, R, f_rng, p_rng)); } } while (i != 0) { MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD); --i; MBEDTLS_MPI_CHK(ecp_double_jac(grp, R, R, tmp)); MBEDTLS_MPI_CHK(ecp_select_comb(grp, &Txi, T, T_size, x[i])); MBEDTLS_MPI_CHK(ecp_add_mixed(grp, R, R, &Txi, tmp)); } cleanup: mbedtls_ecp_point_free(&Txi); mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { rs_ctx->rsm->i = i; /* no need to save R, already pointing to rs_ctx->rsm->R */ } #endif return ret; } /* * Recode the scalar to get constant-time comb multiplication * * As the actual scalar recoding needs an odd scalar as a starting point, * this wrapper ensures that by replacing m by N - m if necessary, and * informs the caller that the result of multiplication will be negated. * * This works because we only support large prime order for Short Weierstrass * curves, so N is always odd hence either m or N - m is. * * See ecp_comb_recode_core() for background. */ static int ecp_comb_recode_scalar(const mbedtls_ecp_group *grp, const mbedtls_mpi *m, unsigned char k[COMB_MAX_D + 1], size_t d, unsigned char w, unsigned char *parity_trick) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi M, mm; mbedtls_mpi_init(&M); mbedtls_mpi_init(&mm); /* N is always odd (see above), just make extra sure */ if (mbedtls_mpi_get_bit(&grp->N, 0) != 1) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* do we need the parity trick? */ *parity_trick = (mbedtls_mpi_get_bit(m, 0) == 0); /* execute parity fix in constant time */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&M, m)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&mm, &grp->N, m)); MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(&M, &mm, *parity_trick)); /* actual scalar recoding */ ecp_comb_recode_core(k, d, w, &M); cleanup: mbedtls_mpi_free(&mm); mbedtls_mpi_free(&M); return ret; } /* * Perform comb multiplication (for short Weierstrass curves) * once the auxiliary table has been pre-computed. * * Scalar recoding may use a parity trick that makes us compute -m * P, * if that is the case we'll need to recover m * P at the end. */ static int ecp_mul_comb_after_precomp(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *T, unsigned char T_size, unsigned char w, size_t d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { RR = &rs_ctx->rsm->R; if (rs_ctx->rsm->state == ecp_rsm_final_norm) { goto final_norm; } } #endif MBEDTLS_MPI_CHK(ecp_comb_recode_scalar(grp, m, k, d, w, &parity_trick)); MBEDTLS_MPI_CHK(ecp_mul_comb_core(grp, RR, T, T_size, k, d, f_rng, p_rng, rs_ctx)); MBEDTLS_MPI_CHK(ecp_safe_invert_jac(grp, RR, parity_trick)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { rs_ctx->rsm->state = ecp_rsm_final_norm; } final_norm: MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV); #endif /* * Knowledge of the jacobian coordinates may leak the last few bits of the * scalar [1], and since our MPI implementation isn't constant-flow, * inversion (used for coordinate normalization) may leak the full value * of its input via side-channels [2]. * * [1] https://eprint.iacr.org/2003/191 * [2] https://eprint.iacr.org/2020/055 * * Avoid the leak by randomizing coordinates before we normalize them. */ if (f_rng != 0) { MBEDTLS_MPI_CHK(ecp_randomize_jac(grp, RR, f_rng, p_rng)); } MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, RR)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL) { MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, RR)); } #endif cleanup: return ret; } /* * Pick window size based on curve size and whether we optimize for base point */ static unsigned char ecp_pick_window_size(const mbedtls_ecp_group *grp, unsigned char p_eq_g) { unsigned char w; /* * Minimize the number of multiplications, that is minimize * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) * (see costs of the various parts, with 1S = 1M) */ w = grp->nbits >= 384 ? 5 : 4; /* * If P == G, pre-compute a bit more, since this may be re-used later. * Just adding one avoids upping the cost of the first mul too much, * and the memory cost too. */ if (p_eq_g) { w++; } /* * If static comb table may not be used (!p_eq_g) or static comb table does * not exists, make sure w is within bounds. * (The last test is useful only for very small curves in the test suite.) * * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of * static comb table, because the size of static comb table is fixed when * it is generated. */ #if (MBEDTLS_ECP_WINDOW_SIZE < 6) if ((!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE) { w = MBEDTLS_ECP_WINDOW_SIZE; } #endif if (w >= grp->nbits) { w = 2; } return w; } /* * Multiplication using the comb method - for curves in short Weierstrass form * * This function is mainly responsible for administrative work: * - managing the restart context if enabled * - managing the table of precomputed points (passed between the below two * functions): allocation, computation, ownership transfer, freeing. * * It delegates the actual arithmetic work to: * ecp_precompute_comb() and ecp_mul_comb_with_precomp() * * See comments on ecp_comb_recode_core() regarding the computation strategy. */ static int ecp_mul_comb(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char w, p_eq_g, i; size_t d; unsigned char T_size = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; ECP_RS_ENTER(rsm); /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = (MPI_ECP_CMP(&P->Y, &grp->G.Y) == 0 && MPI_ECP_CMP(&P->X, &grp->G.X) == 0); #else p_eq_g = 0; #endif /* Pick window size and deduce related sizes */ w = ecp_pick_window_size(grp, p_eq_g); T_size = 1U << (w - 1); d = (grp->nbits + w - 1) / w; /* Pre-computed table: do we have it already for the base point? */ if (p_eq_g && grp->T != NULL) { /* second pointer to the same table, will be deleted on exit */ T = grp->T; T_ok = 1; } else #if defined(MBEDTLS_ECP_RESTARTABLE) /* Pre-computed table: do we have one in progress? complete? */ if (rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL) { /* transfer ownership of T from rsm to local function */ T = rs_ctx->rsm->T; rs_ctx->rsm->T = NULL; rs_ctx->rsm->T_size = 0; /* This effectively jumps to the call to mul_comb_after_precomp() */ T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; } else #endif /* Allocate table if we didn't have any */ { T = mbedtls_calloc(T_size, sizeof(mbedtls_ecp_point)); if (T == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } for (i = 0; i < T_size; i++) { mbedtls_ecp_point_init(&T[i]); } T_ok = 0; } /* Compute table (or finish computing it) if not done already */ if (!T_ok) { MBEDTLS_MPI_CHK(ecp_precompute_comb(grp, T, P, w, d, rs_ctx)); if (p_eq_g) { /* almost transfer ownership of T to the group, but keep a copy of * the pointer to use for calling the next function more easily */ grp->T = T; grp->T_size = T_size; } } /* Actual comb multiplication using precomputed points */ MBEDTLS_MPI_CHK(ecp_mul_comb_after_precomp(grp, R, m, T, T_size, w, d, f_rng, p_rng, rs_ctx)); cleanup: /* does T belong to the group? */ if (T == grp->T) { T = NULL; } /* does T belong to the restart context? */ #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL) { /* transfer ownership of T from local function to rsm */ rs_ctx->rsm->T_size = T_size; rs_ctx->rsm->T = T; T = NULL; } #endif /* did T belong to us? then let's destroy it! */ if (T != NULL) { for (i = 0; i < T_size; i++) { mbedtls_ecp_point_free(&T[i]); } mbedtls_free(T); } /* prevent caller from using invalid value */ int should_free_R = (ret != 0); #if defined(MBEDTLS_ECP_RESTARTABLE) /* don't free R while in progress in case R == P */ if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { should_free_R = 0; } #endif if (should_free_R) { mbedtls_ecp_point_free(R); } ECP_RS_LEAVE(rsm); return ret; } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) /* * For Montgomery curves, we do all the internal arithmetic in projective * coordinates. Import/export of points uses only the x coordinates, which is * internally represented as X / Z. * * For scalar multiplication, we'll use a Montgomery ladder. */ /* * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 * Cost: 1M + 1I */ static int ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P) { #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_normalize_mxz(grp, P); } #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MPI_ECP_INV(&P->Z, &P->Z); MPI_ECP_MUL(&P->X, &P->X, &P->Z); MPI_ECP_LSET(&P->Z, 1); cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */ } /* * Randomize projective x/z coordinates: * (X, Z) -> (l X, l Z) for random l * This is sort of the reverse operation of ecp_normalize_mxz(). * * This countermeasure was first suggested in [2]. * Cost: 2M */ static int ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_randomize_mxz(grp, P, f_rng, p_rng); } #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi l; mbedtls_mpi_init(&l); /* Generate l such that 1 < l < p */ MPI_ECP_RAND(&l); MPI_ECP_MUL(&P->X, &P->X, &l); MPI_ECP_MUL(&P->Z, &P->Z, &l); cleanup: mbedtls_mpi_free(&l); if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; } return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */ } /* * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), * for Montgomery curves in x/z coordinates. * * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 * with * d = X1 * P = (X2, Z2) * Q = (X3, Z3) * R = (X4, Z4) * S = (X5, Z5) * and eliminating temporary variables tO, ..., t4. * * Cost: 5M + 4S */ static int ecp_double_add_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, mbedtls_mpi T[4]) { #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) if (mbedtls_internal_ecp_grp_capable(grp)) { return mbedtls_internal_ecp_double_add_mxz(grp, R, S, P, Q, d); } #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MPI_ECP_ADD(&T[0], &P->X, &P->Z); /* Pp := PX + PZ */ MPI_ECP_SUB(&T[1], &P->X, &P->Z); /* Pm := PX - PZ */ MPI_ECP_ADD(&T[2], &Q->X, &Q->Z); /* Qp := QX + XZ */ MPI_ECP_SUB(&T[3], &Q->X, &Q->Z); /* Qm := QX - QZ */ MPI_ECP_MUL(&T[3], &T[3], &T[0]); /* Qm * Pp */ MPI_ECP_MUL(&T[2], &T[2], &T[1]); /* Qp * Pm */ MPI_ECP_SQR(&T[0], &T[0]); /* Pp^2 */ MPI_ECP_SQR(&T[1], &T[1]); /* Pm^2 */ MPI_ECP_MUL(&R->X, &T[0], &T[1]); /* Pp^2 * Pm^2 */ MPI_ECP_SUB(&T[0], &T[0], &T[1]); /* Pp^2 - Pm^2 */ MPI_ECP_MUL(&R->Z, &grp->A, &T[0]); /* A * (Pp^2 - Pm^2) */ MPI_ECP_ADD(&R->Z, &T[1], &R->Z); /* [ A * (Pp^2-Pm^2) ] + Pm^2 */ MPI_ECP_ADD(&S->X, &T[3], &T[2]); /* Qm*Pp + Qp*Pm */ MPI_ECP_SQR(&S->X, &S->X); /* (Qm*Pp + Qp*Pm)^2 */ MPI_ECP_SUB(&S->Z, &T[3], &T[2]); /* Qm*Pp - Qp*Pm */ MPI_ECP_SQR(&S->Z, &S->Z); /* (Qm*Pp - Qp*Pm)^2 */ MPI_ECP_MUL(&S->Z, d, &S->Z); /* d * ( Qm*Pp - Qp*Pm )^2 */ MPI_ECP_MUL(&R->Z, &T[0], &R->Z); /* [A*(Pp^2-Pm^2)+Pm^2]*(Pp^2-Pm^2) */ cleanup: return ret; #endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */ } /* * Multiplication with Montgomery ladder in x/z coordinates, * for curves in Montgomery form */ static int ecp_mul_mxz(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; unsigned char b; mbedtls_ecp_point RP; mbedtls_mpi PX; mbedtls_mpi tmp[4]; mbedtls_ecp_point_init(&RP); mbedtls_mpi_init(&PX); mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); if (f_rng == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Save PX and read from P before writing to R, in case P == R */ MPI_ECP_MOV(&PX, &P->X); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(&RP, P)); /* Set R to zero in modified x/z coordinates */ MPI_ECP_LSET(&R->X, 1); MPI_ECP_LSET(&R->Z, 0); mbedtls_mpi_free(&R->Y); /* RP.X might be slightly larger than P, so reduce it */ MOD_ADD(&RP.X); /* Randomize coordinates of the starting point */ MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, &RP, f_rng, p_rng)); /* Loop invariant: R = result so far, RP = R + P */ i = grp->nbits + 1; /* one past the (zero-based) required msb for private keys */ while (i-- > 0) { b = mbedtls_mpi_get_bit(m, i); /* * if (b) R = 2R + P else R = 2R, * which is: * if (b) double_add( RP, R, RP, R ) * else double_add( R, RP, R, RP ) * but using safe conditional swaps to avoid leaks */ MPI_ECP_COND_SWAP(&R->X, &RP.X, b); MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); MBEDTLS_MPI_CHK(ecp_double_add_mxz(grp, R, &RP, R, &RP, &PX, tmp)); MPI_ECP_COND_SWAP(&R->X, &RP.X, b); MPI_ECP_COND_SWAP(&R->Z, &RP.Z, b); } /* * Knowledge of the projective coordinates may leak the last few bits of the * scalar [1], and since our MPI implementation isn't constant-flow, * inversion (used for coordinate normalization) may leak the full value * of its input via side-channels [2]. * * [1] https://eprint.iacr.org/2003/191 * [2] https://eprint.iacr.org/2020/055 * * Avoid the leak by randomizing coordinates before we normalize them. */ MBEDTLS_MPI_CHK(ecp_randomize_mxz(grp, R, f_rng, p_rng)); MBEDTLS_MPI_CHK(ecp_normalize_mxz(grp, R)); cleanup: mbedtls_ecp_point_free(&RP); mbedtls_mpi_free(&PX); mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); return ret; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ /* * Restartable multiplication R = m * P * * This internal function can be called without an RNG in case where we know * the inputs are not sensitive. */ static int ecp_mul_restartable_internal(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif #if defined(MBEDTLS_ECP_RESTARTABLE) /* reset ops count for this call if top-level */ if (rs_ctx != NULL && rs_ctx->depth++ == 0) { rs_ctx->ops_done = 0; } #else (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) { MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp)); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ int restarting = 0; #if defined(MBEDTLS_ECP_RESTARTABLE) restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); #endif /* skip argument check when restarting */ if (!restarting) { /* check_privkey is free */ MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_CHK); /* Common sanity checks */ MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(grp, m)); MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); } ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { MBEDTLS_MPI_CHK(ecp_mul_mxz(grp, R, m, P, f_rng, p_rng)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(ecp_mul_comb(grp, R, m, P, f_rng, p_rng, rs_ctx)); } #endif cleanup: #if defined(MBEDTLS_ECP_INTERNAL_ALT) if (is_grp_capable) { mbedtls_internal_ecp_free(grp); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL) { rs_ctx->depth--; } #endif return ret; } /* * Restartable multiplication R = m * P */ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx) { if (f_rng == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mul_restartable_internal(grp, R, m, P, f_rng, p_rng, rs_ctx); } /* * Multiplication R = m * P */ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_mul_restartable(grp, R, m, P, f_rng, p_rng, NULL); } #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * Check that an affine point is valid as a public key, * short weierstrass curves (SEC1 3.2.3.1) */ static int ecp_check_pubkey_sw(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi YY, RHS; /* pt coordinates must be normalized for our checks */ if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0 || mbedtls_mpi_cmp_int(&pt->Y, 0) < 0 || mbedtls_mpi_cmp_mpi(&pt->X, &grp->P) >= 0 || mbedtls_mpi_cmp_mpi(&pt->Y, &grp->P) >= 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } mbedtls_mpi_init(&YY); mbedtls_mpi_init(&RHS); /* * YY = Y^2 * RHS = X^3 + A X + B */ MPI_ECP_SQR(&YY, &pt->Y); MBEDTLS_MPI_CHK(ecp_sw_rhs(grp, &RHS, &pt->X)); if (MPI_ECP_CMP(&YY, &RHS) != 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; } cleanup: mbedtls_mpi_free(&YY); mbedtls_mpi_free(&RHS); return ret; } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* * R = m * P with shortcuts for m == 0, m == 1 and m == -1 * NOT constant-time - ONLY for short Weierstrass! */ static int mbedtls_ecp_mul_shortcuts(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi tmp; mbedtls_mpi_init(&tmp); if (mbedtls_mpi_cmp_int(m, 0) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_set_zero(R)); } else if (mbedtls_mpi_cmp_int(m, 1) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); } else if (mbedtls_mpi_cmp_int(m, -1) == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_pubkey(grp, P)); MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); MPI_ECP_NEG(&R->Y); } else { MBEDTLS_MPI_CHK(ecp_mul_restartable_internal(grp, R, m, P, NULL, NULL, rs_ctx)); } cleanup: mbedtls_mpi_free(&tmp); return ret; } /* * Restartable linear combination * NOT constant-time */ int mbedtls_ecp_muladd_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point mP; mbedtls_ecp_point *pmP = &mP; mbedtls_ecp_point *pR = R; mbedtls_mpi tmp[4]; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif if (mbedtls_ecp_get_type(grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } mbedtls_ecp_point_init(&mP); mpi_init_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); ECP_RS_ENTER(ma); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { /* redirect intermediate results to restart context */ pmP = &rs_ctx->ma->mP; pR = &rs_ctx->ma->R; /* jump to next operation */ if (rs_ctx->ma->state == ecp_rsma_mul2) { goto mul2; } if (rs_ctx->ma->state == ecp_rsma_add) { goto add; } if (rs_ctx->ma->state == ecp_rsma_norm) { goto norm; } } #endif /* MBEDTLS_ECP_RESTARTABLE */ MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pmP, m, P, rs_ctx)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_mul2; } mul2: #endif MBEDTLS_MPI_CHK(mbedtls_ecp_mul_shortcuts(grp, pR, n, Q, rs_ctx)); #if defined(MBEDTLS_ECP_INTERNAL_ALT) if ((is_grp_capable = mbedtls_internal_ecp_grp_capable(grp))) { MBEDTLS_MPI_CHK(mbedtls_internal_ecp_init(grp)); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_add; } add: #endif MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_ADD); MBEDTLS_MPI_CHK(ecp_add_mixed(grp, pR, pmP, pR, tmp)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { rs_ctx->ma->state = ecp_rsma_norm; } norm: #endif MBEDTLS_ECP_BUDGET(MBEDTLS_ECP_OPS_INV); MBEDTLS_MPI_CHK(ecp_normalize_jac(grp, pR)); #if defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && rs_ctx->ma != NULL) { MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, pR)); } #endif cleanup: mpi_free_many(tmp, sizeof(tmp) / sizeof(mbedtls_mpi)); #if defined(MBEDTLS_ECP_INTERNAL_ALT) if (is_grp_capable) { mbedtls_internal_ecp_free(grp); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ mbedtls_ecp_point_free(&mP); ECP_RS_LEAVE(ma); return ret; } /* * Linear combination * NOT constant-time */ int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q) { return mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL); } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n), .use_mempool = 0 } #define ECP_MPI_INIT_ARRAY(x) \ ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) /* * Constants for the two points other than 0, 1, -1 (mod p) in * https://cr.yp.to/ecdh.html#validate * See ecp_check_pubkey_x25519(). */ static const mbedtls_mpi_uint x25519_bad_point_1[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a), MBEDTLS_BYTES_TO_T_UINT_8(0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00), }; static const mbedtls_mpi_uint x25519_bad_point_2[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57), }; static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY( x25519_bad_point_1); static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY( x25519_bad_point_2); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ /* * Check that the input point is not one of the low-order points. * This is recommended by the "May the Fourth" paper: * https://eprint.iacr.org/2017/806.pdf * Those points are never sent by an honest peer. */ static int ecp_check_bad_points_mx(const mbedtls_mpi *X, const mbedtls_mpi *P, const mbedtls_ecp_group_id grp_id) { int ret; mbedtls_mpi XmP; mbedtls_mpi_init(&XmP); /* Reduce X mod P so that we only need to check values less than P. * We know X < 2^256 so we can proceed by subtraction. */ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&XmP, X)); while (mbedtls_mpi_cmp_mpi(&XmP, P) >= 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&XmP, &XmP, P)); } /* Check against the known bad values that are less than P. For Curve448 * these are 0, 1 and -1. For Curve25519 we check the values less than P * from the following list: https://cr.yp.to/ecdh.html#validate */ if (mbedtls_mpi_cmp_int(&XmP, 1) <= 0) { /* takes care of 0 and 1 */ ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) if (grp_id == MBEDTLS_ECP_DP_CURVE25519) { if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_1) == 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } if (mbedtls_mpi_cmp_mpi(&XmP, &ecp_x25519_bad_point_2) == 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } } #else (void) grp_id; #endif /* Final check: check if XmP + 1 is P (final because it changes XmP!) */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&XmP, &XmP, 1)); if (mbedtls_mpi_cmp_mpi(&XmP, P) == 0) { ret = MBEDTLS_ERR_ECP_INVALID_KEY; goto cleanup; } ret = 0; cleanup: mbedtls_mpi_free(&XmP); return ret; } /* * Check validity of a public key for Montgomery curves with x-only schemes */ static int ecp_check_pubkey_mx(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { /* [Curve25519 p. 5] Just check X is the correct number of bytes */ /* Allow any public value, if it's too big then we'll just reduce it mod p * (RFC 7748 sec. 5 para. 3). */ if (mbedtls_mpi_size(&pt->X) > (grp->nbits + 7) / 8) { return MBEDTLS_ERR_ECP_INVALID_KEY; } /* Implicit in all standards (as they don't consider negative numbers): * X must be non-negative. This is normally ensured by the way it's * encoded for transmission, but let's be extra sure. */ if (mbedtls_mpi_cmp_int(&pt->X, 0) < 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } return ecp_check_bad_points_mx(&pt->X, &grp->P, grp->id); } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ /* * Check that a point is valid as a public key */ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt) { /* Must use affine coordinates */ if (mbedtls_mpi_cmp_int(&pt->Z, 1) != 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return ecp_check_pubkey_mx(grp, pt); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return ecp_check_pubkey_sw(grp, pt); } #endif return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* * Check that an mbedtls_mpi is valid as a private key */ int mbedtls_ecp_check_privkey(const mbedtls_ecp_group *grp, const mbedtls_mpi *d) { #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { /* see RFC 7748 sec. 5 para. 5 */ if (mbedtls_mpi_get_bit(d, 0) != 0 || mbedtls_mpi_get_bit(d, 1) != 0 || mbedtls_mpi_bitlen(d) - 1 != grp->nbits) { /* mbedtls_mpi_bitlen is one-based! */ return MBEDTLS_ERR_ECP_INVALID_KEY; } /* see [Curve25519] page 5 */ if (grp->nbits == 254 && mbedtls_mpi_get_bit(d, 2) != 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } return 0; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { /* see SEC1 3.2 */ if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) { return MBEDTLS_ERR_ECP_INVALID_KEY; } else { return 0; } } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_gen_privkey_mx(size_t high_bit, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; size_t n_random_bytes = high_bit / 8 + 1; /* [Curve25519] page 5 */ /* Generate a (high_bit+1)-bit random number by generating just enough * random bytes, then shifting out extra bits from the top (necessary * when (high_bit+1) is not a multiple of 8). */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(d, n_random_bytes, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(d, 8 * n_random_bytes - high_bit - 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, high_bit, 1)); /* Make sure the last two bits are unset for Curve448, three bits for Curve25519 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 0, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 1, 0)); if (high_bit == 254) { MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(d, 2, 0)); } cleanup: return ret; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) static int mbedtls_ecp_gen_privkey_sw( const mbedtls_mpi *N, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = mbedtls_mpi_random(d, 1, N, f_rng, p_rng); switch (ret) { case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: return MBEDTLS_ERR_ECP_RANDOM_FAILED; default: return ret; } } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ /* * Generate a private key */ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_ecp_gen_privkey_mx(grp->nbits, d, f_rng, p_rng); } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return mbedtls_ecp_gen_privkey_sw(&grp->N, d, f_rng, p_rng); } #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_C) /* * Generate a keypair with configurable base point */ int mbedtls_ecp_gen_keypair_base(mbedtls_ecp_group *grp, const mbedtls_ecp_point *G, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, Q, d, G, f_rng, p_rng)); cleanup: return ret; } /* * Generate key pair, wrapper for conventional base point */ int mbedtls_ecp_gen_keypair(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_gen_keypair_base(grp, &grp->G, d, Q, f_rng, p_rng); } /* * Generate a keypair, prettier wrapper */ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } return mbedtls_ecp_gen_keypair(&key->grp, &key->d, &key->Q, f_rng, p_rng); } #endif /* MBEDTLS_ECP_C */ int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (key->grp.id == MBEDTLS_ECP_DP_NONE) { /* Group not set yet */ if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } } else if (key->grp.id != grp_id) { /* Group mismatch */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return mbedtls_ecp_copy(&key->Q, Q); } #define ECP_CURVE25519_KEY_SIZE 32 #define ECP_CURVE448_KEY_SIZE 56 /* * Read a private key. */ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, const unsigned char *buf, size_t buflen) { int ret = 0; if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) { return ret; } ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { /* * Mask the key as mandated by RFC7748 for Curve25519 and Curve448. */ if (grp_id == MBEDTLS_ECP_DP_CURVE25519) { if (buflen != ECP_CURVE25519_KEY_SIZE) { return MBEDTLS_ERR_ECP_INVALID_KEY; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen)); /* Set the three least significant bits to 0 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 2, 0)); /* Set the most significant bit to 0 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(&key->d, ECP_CURVE25519_KEY_SIZE * 8 - 1, 0) ); /* Set the second most significant bit to 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(&key->d, ECP_CURVE25519_KEY_SIZE * 8 - 2, 1) ); } else if (grp_id == MBEDTLS_ECP_DP_CURVE448) { if (buflen != ECP_CURVE448_KEY_SIZE) { return MBEDTLS_ERR_ECP_INVALID_KEY; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&key->d, buf, buflen)); /* Set the two least significant bits to 0 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 0, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&key->d, 1, 0)); /* Set the most significant bit to 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(&key->d, ECP_CURVE448_KEY_SIZE * 8 - 1, 1) ); } } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&key->d, buf, buflen)); } #endif if (ret == 0) { MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(&key->grp, &key->d)); } cleanup: if (ret != 0) { mbedtls_mpi_free(&key->d); } return ret; } /* * Write a private key. */ #if !defined MBEDTLS_DEPRECATED_REMOVED int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key, unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { if (key->grp.id == MBEDTLS_ECP_DP_CURVE25519) { if (buflen < ECP_CURVE25519_KEY_SIZE) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } } else if (key->grp.id == MBEDTLS_ECP_DP_CURVE448) { if (buflen < ECP_CURVE448_KEY_SIZE) { return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&key->d, buf, buflen)); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&key->d, buf, buflen)); } #endif cleanup: return ret; } #endif /* MBEDTLS_DEPRECATED_REMOVED */ int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key, size_t *olen, unsigned char *buf, size_t buflen) { size_t len = (key->grp.nbits + 7) / 8; if (len > buflen) { /* For robustness, ensure *olen <= buflen even on error. */ *olen = 0; return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; } *olen = len; /* Private key not set */ if (key->d.n == 0) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { return mbedtls_mpi_write_binary_le(&key->d, buf, len); } #endif #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { return mbedtls_mpi_write_binary(&key->d, buf, len); } #endif /* Private key set but no recognized curve type? This shouldn't happen. */ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } /* * Write a public key. */ int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key, int format, size_t *olen, unsigned char *buf, size_t buflen) { return mbedtls_ecp_point_write_binary(&key->grp, &key->Q, format, olen, buf, buflen); } #if defined(MBEDTLS_ECP_C) /* * Check a public-private key pair */ int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_point Q; mbedtls_ecp_group grp; if (pub->grp.id == MBEDTLS_ECP_DP_NONE || pub->grp.id != prv->grp.id || mbedtls_mpi_cmp_mpi(&pub->Q.X, &prv->Q.X) || mbedtls_mpi_cmp_mpi(&pub->Q.Y, &prv->Q.Y) || mbedtls_mpi_cmp_mpi(&pub->Q.Z, &prv->Q.Z)) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_ecp_point_init(&Q); mbedtls_ecp_group_init(&grp); /* mbedtls_ecp_mul() needs a non-const group... */ mbedtls_ecp_group_copy(&grp, &prv->grp); /* Also checks d is valid */ MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &Q, &prv->d, &prv->grp.G, f_rng, p_rng)); if (mbedtls_mpi_cmp_mpi(&Q.X, &prv->Q.X) || mbedtls_mpi_cmp_mpi(&Q.Y, &prv->Q.Y) || mbedtls_mpi_cmp_mpi(&Q.Z, &prv->Q.Z)) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } cleanup: mbedtls_ecp_point_free(&Q); mbedtls_ecp_group_free(&grp); return ret; } int mbedtls_ecp_keypair_calc_public(mbedtls_ecp_keypair *key, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, f_rng, p_rng); } #endif /* MBEDTLS_ECP_C */ mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id( const mbedtls_ecp_keypair *key) { return key->grp.id; } /* * Export generic key-pair parameters. */ int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (grp != NULL && (ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) { return ret; } if (d != NULL && (ret = mbedtls_mpi_copy(d, &key->d)) != 0) { return ret; } if (Q != NULL && (ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) { return ret; } return 0; } #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_ECP_C) /* * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! * * This is the linear congruential generator from numerical recipes, * except we only use the low byte as the output. See * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use */ static int self_test_rng(void *ctx, unsigned char *out, size_t len) { static uint32_t state = 42; (void) ctx; for (size_t i = 0; i < len; i++) { state = state * 1664525u + 1013904223u; out[i] = (unsigned char) state; } return 0; } /* Adjust the exponent to be a valid private point for the specified curve. * This is sometimes necessary because we use a single set of exponents * for all curves but the validity of values depends on the curve. */ static int self_test_adjust_exponent(const mbedtls_ecp_group *grp, mbedtls_mpi *m) { int ret = 0; switch (grp->id) { /* If Curve25519 is available, then that's what we use for the * Montgomery test, so we don't need the adjustment code. */ #if !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: /* Move highest bit from 254 to N-1. Setting bit N-1 is * necessary to enforce the highest-bit-set constraint. */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, 254, 0)); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(m, grp->nbits, 1)); /* Copy second-highest bit from 253 to N-2. This is not * necessary but improves the test variety a bit. */ MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit(m, grp->nbits - 1, mbedtls_mpi_get_bit(m, 253))); break; #endif #endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */ default: /* Non-Montgomery curves and Curve25519 need no adjustment. */ (void) grp; (void) m; goto cleanup; } cleanup: return ret; } /* Calculate R = m.P for each m in exponents. Check that the number of * basic operations doesn't depend on the value of m. */ static int self_test_point(int verbose, mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_mpi *m, const mbedtls_ecp_point *P, const char *const *exponents, size_t n_exponents) { int ret = 0; size_t i = 0; unsigned long add_c_prev, dbl_c_prev, mul_c_prev; add_count = 0; dbl_count = 0; mul_count = 0; MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[0])); MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL)); for (i = 1; i < n_exponents; i++) { add_c_prev = add_count; dbl_c_prev = dbl_count; mul_c_prev = mul_count; add_count = 0; dbl_count = 0; mul_count = 0; MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(m, 16, exponents[i])); MBEDTLS_MPI_CHK(self_test_adjust_exponent(grp, m)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(grp, R, m, P, self_test_rng, NULL)); if (add_count != add_c_prev || dbl_count != dbl_c_prev || mul_count != mul_c_prev) { ret = 1; break; } } cleanup: if (verbose != 0) { if (ret != 0) { mbedtls_printf("failed (%u)\n", (unsigned int) i); } else { mbedtls_printf("passed\n"); } } return ret; } #endif /* MBEDTLS_ECP_C */ /* * Checkup routine */ int mbedtls_ecp_self_test(int verbose) { #if defined(MBEDTLS_ECP_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; mbedtls_ecp_point R, P; mbedtls_mpi m; #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* Exponents especially adapted for secp192k1, which has the lowest * order n of all supported curves (secp192r1 is in a slightly larger * field but the order of its base point is slightly smaller). */ const char *sw_exponents[] = { "000000000000000000000000000000000000000000000001", /* one */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8C", /* n - 1 */ "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ "400000000000000000000000000000000000000000000000", /* one and zeros */ "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ "555555555555555555555555555555555555555555555555", /* 101010... */ }; #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) const char *m_exponents[] = { /* Valid private values for Curve25519. In a build with Curve448 * but not Curve25519, they will be adjusted in * self_test_adjust_exponent(). */ "4000000000000000000000000000000000000000000000000000000000000000", "5C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C30", "5715ECCE24583F7A7023C24164390586842E816D7280A49EF6DF4EAE6B280BF8", "41A2B017516F6D254E1F002BCCBADD54BE30F8CEC737A0E912B4963B6BA74460", "5555555555555555555555555555555555555555555555555555555555555550", "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8", }; #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ mbedtls_ecp_group_init(&grp); mbedtls_ecp_point_init(&R); mbedtls_ecp_point_init(&P); mbedtls_mpi_init(&m); #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) /* Use secp192r1 if available, or any available curve */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP192R1)); #else MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, mbedtls_ecp_curve_list()->grp_id)); #endif if (verbose != 0) { mbedtls_printf(" ECP SW test #1 (constant op_count, base point G): "); } /* Do a dummy multiplication first to trigger precomputation */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&m, 2)); MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&grp, &P, &m, &grp.G, self_test_rng, NULL)); ret = self_test_point(verbose, &grp, &R, &m, &grp.G, sw_exponents, sizeof(sw_exponents) / sizeof(sw_exponents[0])); if (ret != 0) { goto cleanup; } if (verbose != 0) { mbedtls_printf(" ECP SW test #2 (constant op_count, other point): "); } /* We computed P = 2G last time, use it */ ret = self_test_point(verbose, &grp, &R, &m, &P, sw_exponents, sizeof(sw_exponents) / sizeof(sw_exponents[0])); if (ret != 0) { goto cleanup; } mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&R); #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) if (verbose != 0) { mbedtls_printf(" ECP Montgomery test (constant op_count): "); } #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519)); #elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE448)); #else #error "MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test" #endif ret = self_test_point(verbose, &grp, &R, &m, &grp.G, m_exponents, sizeof(m_exponents) / sizeof(m_exponents[0])); if (ret != 0) { goto cleanup; } #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ cleanup: if (ret < 0 && verbose != 0) { mbedtls_printf("Unexpected error, return code = %08X\n", (unsigned int) ret); } mbedtls_ecp_group_free(&grp); mbedtls_ecp_point_free(&R); mbedtls_ecp_point_free(&P); mbedtls_mpi_free(&m); if (verbose != 0) { mbedtls_printf("\n"); } return ret; #else /* MBEDTLS_ECP_C */ (void) verbose; return 0; #endif /* MBEDTLS_ECP_C */ } #endif /* MBEDTLS_SELF_TEST */ #endif /* !MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_LIGHT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecp_curves.c000066400000000000000000011573621464416617300236550ustar00rootroot00000000000000/* * Elliptic curves over GF(p): curve-specific data and functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if !defined(MBEDTLS_ECP_WITH_MPI_UINT) #if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "bn_mul.h" #include "bignum_core.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) #define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) #define ECP_POINT_INIT_XY_Z0(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } #define ECP_POINT_INIT_XY_Z1(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* For these curves, we build the group parameters dynamically. */ #define ECP_LOAD_GROUP static const mbedtls_mpi_uint mpi_one[] = { 1 }; #endif /* * Note: the constants are in little-endian order * to be directly usable in MPIs */ /* * Domain parameters for secp192r1 */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static const mbedtls_mpi_uint secp192r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64), }; static const mbedtls_mpi_uint secp192r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), }; static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), }; static const mbedtls_mpi_uint secp192r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), }; static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), }; static const mbedtls_mpi_uint secp192r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), }; static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), }; static const mbedtls_mpi_uint secp192r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), }; static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), }; static const mbedtls_mpi_uint secp192r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), }; static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), }; static const mbedtls_mpi_uint secp192r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), }; static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), }; static const mbedtls_mpi_uint secp192r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), }; static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), }; static const mbedtls_mpi_uint secp192r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), }; static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), }; static const mbedtls_mpi_uint secp192r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), }; static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), }; static const mbedtls_mpi_uint secp192r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), }; static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), }; static const mbedtls_mpi_uint secp192r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), }; static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), }; static const mbedtls_mpi_uint secp192r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), }; static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), }; static const mbedtls_mpi_uint secp192r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), }; static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), }; static const mbedtls_mpi_uint secp192r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), }; static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), }; static const mbedtls_mpi_uint secp192r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), }; static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), }; static const mbedtls_ecp_point secp192r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), }; #else #define secp192r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ /* * Domain parameters for secp224r1 */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static const mbedtls_mpi_uint secp224r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C), MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4), }; static const mbedtls_mpi_uint secp224r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7), }; static const mbedtls_mpi_uint secp224r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD), }; static const mbedtls_mpi_uint secp224r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), }; #else #define secp224r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ /* * Domain parameters for secp256r1 */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static const mbedtls_mpi_uint secp256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A), }; static const mbedtls_mpi_uint secp256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), }; static const mbedtls_mpi_uint secp256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), }; static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), }; static const mbedtls_mpi_uint secp256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), }; static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), }; static const mbedtls_mpi_uint secp256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), }; static const mbedtls_mpi_uint secp256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), }; static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), }; static const mbedtls_mpi_uint secp256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), }; static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), }; static const mbedtls_mpi_uint secp256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), }; static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), }; static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), }; static const mbedtls_mpi_uint secp256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), }; static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), }; static const mbedtls_mpi_uint secp256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), }; static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), }; static const mbedtls_mpi_uint secp256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), }; static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), }; static const mbedtls_mpi_uint secp256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), }; static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), }; static const mbedtls_mpi_uint secp256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), }; static const mbedtls_mpi_uint secp256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), }; static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), }; static const mbedtls_ecp_point secp256r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), }; #else #define secp256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ /* * Domain parameters for secp384r1 */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static const mbedtls_mpi_uint secp384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3), }; static const mbedtls_mpi_uint secp384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), }; static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), }; static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), }; static const mbedtls_mpi_uint secp384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), }; static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), }; static const mbedtls_mpi_uint secp384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), }; static const mbedtls_mpi_uint secp384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), }; static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), }; static const mbedtls_mpi_uint secp384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), }; static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), }; static const mbedtls_mpi_uint secp384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), }; static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), }; static const mbedtls_mpi_uint secp384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), }; static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), }; static const mbedtls_mpi_uint secp384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), }; static const mbedtls_mpi_uint secp384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), }; static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), }; static const mbedtls_mpi_uint secp384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), }; static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), }; static const mbedtls_mpi_uint secp384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), }; static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), }; static const mbedtls_mpi_uint secp384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), }; static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), }; static const mbedtls_mpi_uint secp384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), }; static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), }; static const mbedtls_mpi_uint secp384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), }; static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), }; static const mbedtls_mpi_uint secp384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), }; static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), }; static const mbedtls_mpi_uint secp384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), }; static const mbedtls_mpi_uint secp384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), }; static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), }; static const mbedtls_mpi_uint secp384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), }; static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), }; static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), }; static const mbedtls_mpi_uint secp384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), }; static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), }; static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), }; static const mbedtls_mpi_uint secp384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), }; static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), }; static const mbedtls_mpi_uint secp384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), }; static const mbedtls_mpi_uint secp384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), }; static const mbedtls_mpi_uint secp384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), }; static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), }; static const mbedtls_mpi_uint secp384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), }; static const mbedtls_mpi_uint secp384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), }; static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), }; static const mbedtls_mpi_uint secp384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), }; static const mbedtls_ecp_point secp384r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), }; #else #define secp384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ /* * Domain parameters for secp521r1 */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static const mbedtls_mpi_uint secp521r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; static const mbedtls_mpi_uint secp521r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95), MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00), }; static const mbedtls_mpi_uint secp521r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00), }; static const mbedtls_mpi_uint secp521r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01), }; static const mbedtls_mpi_uint secp521r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp521r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp521r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), }; #else #define secp521r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static const mbedtls_mpi_uint secp192k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp192k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00), }; static const mbedtls_mpi_uint secp192k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), }; static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), }; static const mbedtls_mpi_uint secp192k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), }; static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), }; static const mbedtls_mpi_uint secp192k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), }; static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), }; static const mbedtls_mpi_uint secp192k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), }; static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), }; static const mbedtls_mpi_uint secp192k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), }; static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), }; static const mbedtls_mpi_uint secp192k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), }; static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), }; static const mbedtls_mpi_uint secp192k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), }; static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), }; static const mbedtls_mpi_uint secp192k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), }; static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), }; static const mbedtls_mpi_uint secp192k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), }; static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), }; static const mbedtls_mpi_uint secp192k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), }; static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), }; static const mbedtls_mpi_uint secp192k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), }; static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), }; static const mbedtls_mpi_uint secp192k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), }; static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), }; static const mbedtls_mpi_uint secp192k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), }; static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), }; static const mbedtls_mpi_uint secp192k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), }; static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), }; static const mbedtls_mpi_uint secp192k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), }; static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), }; static const mbedtls_ecp_point secp192k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), }; #else #define secp192k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static const mbedtls_mpi_uint secp224k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp224k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00), }; static const mbedtls_mpi_uint secp224k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1), }; static const mbedtls_mpi_uint secp224k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E), }; static const mbedtls_mpi_uint secp224k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), }; #else #define secp224k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static const mbedtls_mpi_uint secp256k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp256k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00), }; static const mbedtls_mpi_uint secp256k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), }; static const mbedtls_mpi_uint secp256k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), }; static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), }; static const mbedtls_mpi_uint secp256k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), }; static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), }; static const mbedtls_mpi_uint secp256k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), }; static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), }; static const mbedtls_mpi_uint secp256k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), }; static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), }; static const mbedtls_mpi_uint secp256k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), }; static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), }; static const mbedtls_mpi_uint secp256k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), }; static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), }; static const mbedtls_mpi_uint secp256k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), }; static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), }; static const mbedtls_mpi_uint secp256k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), }; static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), }; static const mbedtls_mpi_uint secp256k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), }; static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), }; static const mbedtls_mpi_uint secp256k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), }; static const mbedtls_mpi_uint secp256k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), }; static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), }; static const mbedtls_mpi_uint secp256k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), }; static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), }; static const mbedtls_mpi_uint secp256k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), }; static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), }; static const mbedtls_ecp_point secp256k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), }; #else #define secp256k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ /* * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) static const mbedtls_mpi_uint brainpoolP256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; static const mbedtls_mpi_uint brainpoolP256r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D), }; static const mbedtls_mpi_uint brainpoolP256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26), }; static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), }; static const mbedtls_ecp_point brainpoolP256r1_T[16] = { ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), }; #else #define brainpoolP256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ /* * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) static const mbedtls_mpi_uint brainpoolP384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; static const mbedtls_mpi_uint brainpoolP384r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B), }; static const mbedtls_mpi_uint brainpoolP384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), }; static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), }; static const mbedtls_ecp_point brainpoolP384r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), }; #else #define brainpoolP384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ /* * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) static const mbedtls_mpi_uint brainpoolP512r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; static const mbedtls_mpi_uint brainpoolP512r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78), }; static const mbedtls_mpi_uint brainpoolP512r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), }; static const mbedtls_ecp_point brainpoolP512r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), }; #else #define brainpoolP512r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(ECP_LOAD_GROUP) /* * Domain parameters for SM2 (GM/T 0003 Part 5) */ #if defined(MBEDTLS_ECP_DP_SM2_ENABLED) static const mbedtls_mpi_uint sm2_p[] = { MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), }; static const mbedtls_mpi_uint sm2_a[] = { MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), }; static const mbedtls_mpi_uint sm2_b[] = { MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x0E, 0x94, 0x4D, 0x41, 0xBD, 0xBC, 0xDD ), MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x8F, 0xAB, 0x15, 0xF5, 0x89, 0x97, 0xF3 ), MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x09, 0x65, 0xCF, 0x4B, 0x9E, 0x5A, 0x4D ), MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x5E, 0x9F, 0x9D, 0x9E, 0xFA, 0xE9, 0x28 ), }; static const mbedtls_mpi_uint sm2_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x74, 0x4C, 0x33, 0x89, 0x45, 0x5A, 0x71 ), MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x0B, 0x66, 0xF2, 0xBF, 0x0B, 0xE3, 0x8F ), MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0xC9, 0x39, 0x6A, 0x46, 0x04, 0x99, 0x5F ), MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x81, 0x19, 0x1F, 0x2C, 0xAE, 0xC4, 0x32 ), }; static const mbedtls_mpi_uint sm2_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xF0, 0x39, 0x21, 0xE5, 0x32, 0xDF, 0x02 ), MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x47, 0x2A, 0xC6, 0x7C, 0x87, 0xA9, 0xD0 ), MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0x21, 0x69, 0x6B, 0xE3, 0xCE, 0xBD, 0x59 ), MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x77, 0xF6, 0xF4, 0xA2, 0x36, 0x37, 0xBC ), }; static const mbedtls_mpi_uint sm2_n[] = { MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x41, 0xD5, 0x39, 0x09, 0xF4, 0xBB, 0x53 ), MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0x05, 0xC6, 0x21, 0x6B, 0xDF, 0x03, 0x72 ), MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), }; #define sm2_T NULL #endif /* MBEDTLS_ECP_DP_SM2_ENABLED */ /* * Create an MPI from embedded constants * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint)) */ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { X->s = 1; X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); X->p = (mbedtls_mpi_uint *) p; } /* * Set an MPI to static value 1 */ static inline void ecp_mpi_set1(mbedtls_mpi *X) { X->s = 1; X->n = 1; X->p = (mbedtls_mpi_uint *) mpi_one; /* X->p will not be modified so the cast is safe */ } /* * Make group available from embedded constants */ static int ecp_group_load(mbedtls_ecp_group *grp, const mbedtls_mpi_uint *p, size_t plen, const mbedtls_mpi_uint *a, size_t alen, const mbedtls_mpi_uint *b, size_t blen, const mbedtls_mpi_uint *gx, size_t gxlen, const mbedtls_mpi_uint *gy, size_t gylen, const mbedtls_mpi_uint *n, size_t nlen, const mbedtls_ecp_point *T) { ecp_mpi_load(&grp->P, p, plen); if (a != NULL) { ecp_mpi_load(&grp->A, a, alen); } ecp_mpi_load(&grp->B, b, blen); ecp_mpi_load(&grp->N, n, nlen); ecp_mpi_load(&grp->G.X, gx, gxlen); ecp_mpi_load(&grp->G.Y, gy, gylen); ecp_mpi_set1(&grp->G.Z); grp->pbits = mbedtls_mpi_bitlen(&grp->P); grp->nbits = mbedtls_mpi_bitlen(&grp->N); grp->h = 1; grp->T = (mbedtls_ecp_point *) T; /* * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. */ grp->T_size = 0; return 0; } #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_NIST_OPTIM) /* Forward declarations */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static int ecp_mod_p256(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static int ecp_mod_p384(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static int ecp_mod_p521(mbedtls_mpi *); #endif #define NIST_MODP(P) grp->modp = ecp_mod_ ## P; #else #define NIST_MODP(P) #endif /* MBEDTLS_ECP_NIST_OPTIM */ /* Additional forward declarations */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) static int ecp_mod_p255(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) static int ecp_mod_p448(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static int ecp_mod_p192k1(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static int ecp_mod_p224k1(mbedtls_mpi *); #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static int ecp_mod_p256k1(mbedtls_mpi *); #endif #if defined(ECP_LOAD_GROUP) #define LOAD_GROUP_A(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ G ## _a, sizeof(G ## _a), \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #define LOAD_GROUP(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ NULL, 0, \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Constants used by ecp_use_curve25519() */ static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; static const unsigned char curve25519_part_of_n[] = { 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, }; /* * Specialized function for creating the Curve25519 group */ static int ecp_use_curve25519(mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24)); /* P = 2^255 - 19 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 255)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 19)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); /* N = 2^252 + 27742317777372353535851937790883648493 */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&grp->N, curve25519_part_of_n, sizeof(curve25519_part_of_n))); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 252, 1)); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); /* Actually, the required msb for private keys */ grp->nbits = 254; cleanup: if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Constants used by ecp_use_curve448() */ static const mbedtls_mpi_sint curve448_a24 = 0x98AA; static const unsigned char curve448_part_of_n[] = { 0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24, 0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93, 0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC, 0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D, }; /* * Specialized function for creating the Curve448 group */ static int ecp_use_curve448(mbedtls_ecp_group *grp) { mbedtls_mpi Ns; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_init(&Ns); /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); /* P = 2^448 - 2^224 - 1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 446, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&Ns, curve448_part_of_n, sizeof(curve448_part_of_n))); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&grp->N, &grp->N, &Ns)); /* Actually, the required msb for private keys */ grp->nbits = 447; cleanup: mbedtls_mpi_free(&Ns); if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ /* * Set a group using well-known domain parameters */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) { mbedtls_ecp_group_free(grp); mbedtls_ecp_group_init(grp); grp->id = id; switch (id) { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: NIST_MODP(p192); return LOAD_GROUP(secp192r1); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) case MBEDTLS_ECP_DP_SECP224R1: NIST_MODP(p224); return LOAD_GROUP(secp224r1); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) case MBEDTLS_ECP_DP_SECP256R1: NIST_MODP(p256); return LOAD_GROUP(secp256r1); #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) case MBEDTLS_ECP_DP_SECP384R1: NIST_MODP(p384); return LOAD_GROUP(secp384r1); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) case MBEDTLS_ECP_DP_SECP521R1: NIST_MODP(p521); return LOAD_GROUP(secp521r1); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) case MBEDTLS_ECP_DP_SECP192K1: grp->modp = ecp_mod_p192k1; return LOAD_GROUP_A(secp192k1); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) case MBEDTLS_ECP_DP_SECP224K1: grp->modp = ecp_mod_p224k1; return LOAD_GROUP_A(secp224k1); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) case MBEDTLS_ECP_DP_SECP256K1: grp->modp = ecp_mod_p256k1; return LOAD_GROUP_A(secp256k1); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) case MBEDTLS_ECP_DP_BP256R1: return LOAD_GROUP_A(brainpoolP256r1); #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) case MBEDTLS_ECP_DP_BP384R1: return LOAD_GROUP_A(brainpoolP384r1); #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SM2_ENABLED) case MBEDTLS_ECP_DP_SM2: return( LOAD_GROUP_A( sm2 ) ); #endif /* MBEDTLS_ECP_DP_SM2_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) case MBEDTLS_ECP_DP_BP512R1: return LOAD_GROUP_A(brainpoolP512r1); #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: grp->modp = ecp_mod_p255; return ecp_use_curve25519(grp); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: grp->modp = ecp_mod_p448; return ecp_use_curve448(grp); #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ default: grp->id = MBEDTLS_ECP_DP_NONE; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } } #if defined(MBEDTLS_ECP_NIST_OPTIM) /* * Fast reduction modulo the primes used by the NIST curves. * * These functions are critical for speed, but not needed for correct * operations. So, we make the choice to heavily rely on the internals of our * bignum library, which creates a tight coupling between these functions and * our MPI implementation. However, the coupling between the ECP module and * MPI remains loose, since these functions can be deactivated at will. */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /* * Compared to the way things are presented in FIPS 186-3 D.2, * we proceed in columns, from right (least significant chunk) to left, * adding chunks to N in place, and keeping a carry for the next chunk. * This avoids moving things around in memory, and uselessly adding zeros, * compared to the more straightforward, line-oriented approach. * * For this prime we need to handle data in chunks of 64 bits. * Since this is always a multiple of our basic mbedtls_mpi_uint, we can * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. */ /* Add 64-bit chunks (dst += src) and update carry */ static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry) { unsigned char i; mbedtls_mpi_uint c = 0; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) { *dst += c; c = (*dst < c); *dst += *src; c += (*dst < *src); } *carry += c; } /* Add carry to a 64-bit chunk and update carry */ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) { unsigned char i; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) { *dst += *carry; *carry = (*dst < *carry); } } #define WIDTH 8 / sizeof(mbedtls_mpi_uint) #define A(i) N->p + (i) * WIDTH #define ADD(i) add64(p, A(i), &c) #define NEXT p += WIDTH; carry64(p, &c) #define LAST p += WIDTH; *p = c; while (++p < end) *p = 0 /* * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) */ static int ecp_mod_p192(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_uint c = 0; mbedtls_mpi_uint *p, *end; /* Make sure we have enough blocks so that A(5) is legal */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, 6 * WIDTH)); p = N->p; end = p + N->n; ADD(3); ADD(5); NEXT; // A0 += A3 + A5 ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 ADD(4); ADD(5); LAST; // A2 += A4 + A5 cleanup: return ret; } #undef WIDTH #undef A #undef ADD #undef NEXT #undef LAST #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * The reader is advised to first understand ecp_mod_p192() since the same * general structure is used here, but with additional complications: * (1) chunks of 32 bits, and (2) subtractions. */ /* * For these primes, we need to handle data in chunks of 32 bits. * This makes it more complicated if we use 64 bits limbs in MPI, * which prevents us from using a uniform access method as for p192. * * So, we define a mini abstraction layer to access 32 bit chunks, * load them in 'cur' for work, and store them back from 'cur' when done. * * While at it, also define the size of N in terms of 32-bit chunks. */ #define LOAD32 cur = A(i); #if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ #define MAX32 N->n #define A(j) N->p[j] #define STORE32 N->p[i] = cur; #else /* 64-bit */ #define MAX32 N->n * 2 #define A(j) (j) % 2 ? (uint32_t) (N->p[(j)/2] >> 32) : \ (uint32_t) (N->p[(j)/2]) #define STORE32 \ if (i % 2) { \ N->p[i/2] &= 0x00000000FFFFFFFF; \ N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ } else { \ N->p[i/2] &= 0xFFFFFFFF00000000; \ N->p[i/2] |= (mbedtls_mpi_uint) cur; \ } #endif /* sizeof( mbedtls_mpi_uint ) */ /* * Helpers for addition and subtraction of chunks, with signed carry. */ static inline void add32(uint32_t *dst, uint32_t src, signed char *carry) { *dst += src; *carry += (*dst < src); } static inline void sub32(uint32_t *dst, uint32_t src, signed char *carry) { *carry -= (*dst < src); *dst -= src; } #define ADD(j) add32(&cur, A(j), &c); #define SUB(j) sub32(&cur, A(j), &c); /* * Helpers for the main 'loop' */ #define INIT(b) \ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \ signed char c = 0, cc; \ uint32_t cur; \ size_t i = 0, bits = (b); \ /* N is the size of the product of two b-bit numbers, plus one */ \ /* limb for fix_negative */ \ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, (b) * 2 / biL + 1)); \ LOAD32; #define NEXT \ STORE32; i++; LOAD32; \ cc = c; c = 0; \ if (cc < 0) \ sub32(&cur, -cc, &c); \ else \ add32(&cur, cc, &c); \ #define LAST \ STORE32; i++; \ cur = c > 0 ? c : 0; STORE32; \ cur = 0; while (++i < MAX32) { STORE32; } \ if (c < 0) mbedtls_ecp_fix_negative(N, c, bits); /* * If the result is negative, we get it in the form * c * 2^bits + N, with c negative and N positive shorter than 'bits' */ static void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits) { size_t i; /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so * set the absolute value to 0xfff...fff - N. There is no carry * since we're subtracting from all-bits-one. */ for (i = 0; i <= bits / 8 / sizeof(mbedtls_mpi_uint); i++) { N->p[i] = ~(mbedtls_mpi_uint) 0 - N->p[i]; } /* Add 1, taking care of the carry. */ i = 0; do { ++N->p[i]; } while (N->p[i++] == 0 && i <= bits / 8 / sizeof(mbedtls_mpi_uint)); /* Invert the sign. * Now N = N0 - 2^bits where N0 is the initial value of N. */ N->s = -1; /* Add |c| * 2^bits to the absolute value. Since c and N are * negative, this adds c * 2^bits. */ mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c; #if defined(MBEDTLS_HAVE_INT64) if (bits == 224) { msw <<= 32; } #endif N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw; } #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) /* * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) */ static int ecp_mod_p224(mbedtls_mpi *N) { INIT(224); SUB(7); SUB(11); NEXT; // A0 += -A7 - A11 SUB(8); SUB(12); NEXT; // A1 += -A8 - A12 SUB(9); SUB(13); NEXT; // A2 += -A9 - A13 SUB(10); ADD(7); ADD(11); NEXT; // A3 += -A10 + A7 + A11 SUB(11); ADD(8); ADD(12); NEXT; // A4 += -A11 + A8 + A12 SUB(12); ADD(9); ADD(13); NEXT; // A5 += -A12 + A9 + A13 SUB(13); ADD(10); LAST; // A6 += -A13 + A10 cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) /* * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) */ static int ecp_mod_p256(mbedtls_mpi *N) { INIT(256); ADD(8); ADD(9); SUB(11); SUB(12); SUB(13); SUB(14); NEXT; // A0 ADD(9); ADD(10); SUB(12); SUB(13); SUB(14); SUB(15); NEXT; // A1 ADD(10); ADD(11); SUB(13); SUB(14); SUB(15); NEXT; // A2 ADD(11); ADD(11); ADD(12); ADD(12); ADD(13); SUB(15); SUB(8); SUB(9); NEXT; // A3 ADD(12); ADD(12); ADD(13); ADD(13); ADD(14); SUB(9); SUB(10); NEXT; // A4 ADD(13); ADD(13); ADD(14); ADD(14); ADD(15); SUB(10); SUB(11); NEXT; // A5 ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13); SUB(8); SUB(9); NEXT; // A6 ADD(15); ADD(15); ADD(15); ADD(8); SUB(10); SUB(11); SUB(12); SUB(13); LAST; // A7 cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) */ static int ecp_mod_p384(mbedtls_mpi *N) { INIT(384); ADD(12); ADD(21); ADD(20); SUB(23); NEXT; // A0 ADD(13); ADD(22); ADD(23); SUB(12); SUB(20); NEXT; // A2 ADD(14); ADD(23); SUB(13); SUB(21); NEXT; // A2 ADD(15); ADD(12); ADD(20); ADD(21); SUB(14); SUB(22); SUB(23); NEXT; // A3 ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22); SUB(15); SUB(23); SUB(23); NEXT; // A4 ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23); SUB(16); NEXT; // A5 ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22); SUB(17); NEXT; // A6 ADD(19); ADD(16); ADD(15); ADD(23); SUB(18); NEXT; // A7 ADD(20); ADD(17); ADD(16); SUB(19); NEXT; // A8 ADD(21); ADD(18); ADD(17); SUB(20); NEXT; // A9 ADD(22); ADD(19); ADD(18); SUB(21); NEXT; // A10 ADD(23); ADD(20); ADD(19); SUB(22); LAST; // A11 cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #undef A #undef LOAD32 #undef STORE32 #undef MAX32 #undef INIT #undef NEXT #undef LAST #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || MBEDTLS_ECP_DP_SECP256R1_ENABLED || MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) /* * Here we have an actual Mersenne prime, so things are more straightforward. * However, chunks are aligned on a 'weird' boundary (521 bits). */ /* Size of p521 in terms of mbedtls_mpi_uint */ #define P521_WIDTH (521 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* Bits to keep in the most significant mbedtls_mpi_uint */ #define P521_MASK 0x01FF /* * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) * Write N as A1 + 2^521 A0, return A0 + A1 */ static int ecp_mod_p521(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi M; mbedtls_mpi_uint Mp[P521_WIDTH + 1]; /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: * we need to hold bits 513 to 1056, which is 34 limbs, that is * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ if (N->n < P521_WIDTH) { return 0; } /* M = A1 */ M.s = 1; M.n = N->n - (P521_WIDTH - 1); if (M.n > P521_WIDTH + 1) { M.n = P521_WIDTH + 1; } M.p = Mp; memcpy(Mp, N->p + P521_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 521 % (8 * sizeof(mbedtls_mpi_uint)))); /* N = A0 */ N->p[P521_WIDTH - 1] &= P521_MASK; for (i = P521_WIDTH; i < N->n; i++) { N->p[i] = 0; } /* N = A0 + A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); cleanup: return ret; } #undef P521_WIDTH #undef P521_MASK #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_ECP_NIST_OPTIM */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Size of p255 in terms of mbedtls_mpi_uint */ #define P255_WIDTH (255 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* * Fast quasi-reduction modulo p255 = 2^255 - 19 * Write N as A0 + 2^256 A1, return A0 + 38 * A1 */ static int ecp_mod_p255(mbedtls_mpi *N) { mbedtls_mpi_uint Mp[P255_WIDTH]; /* Helper references for top part of N */ mbedtls_mpi_uint * const NT_p = N->p + P255_WIDTH; const size_t NT_n = N->n - P255_WIDTH; if (N->n <= P255_WIDTH) { return 0; } if (NT_n > P255_WIDTH) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Split N as N + 2^256 M */ memcpy(Mp, NT_p, sizeof(mbedtls_mpi_uint) * NT_n); memset(NT_p, 0, sizeof(mbedtls_mpi_uint) * NT_n); /* N = A0 + 38 * A1 */ mbedtls_mpi_core_mla(N->p, P255_WIDTH + 1, Mp, NT_n, 38); return 0; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Size of p448 in terms of mbedtls_mpi_uint */ #define P448_WIDTH (448 / 8 / sizeof(mbedtls_mpi_uint)) /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ #define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) #define P224_SIZE (224 / 8) #define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) #define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) #define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) /* * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference * implementation of Curve448, which uses its own special 56-bit limbs rather * than a generic bignum library. We could squeeze some extra speed out on * 32-bit machines by splitting N up into 32-bit limbs and doing the * arithmetic using the limbs directly as we do for the NIST primes above, * but for 64-bit targets it should use half the number of operations if we do * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. */ static int ecp_mod_p448(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi M, Q; mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; if (N->n <= P448_WIDTH) { return 0; } /* M = A1 */ M.s = 1; M.n = N->n - (P448_WIDTH); if (M.n > P448_WIDTH) { /* Shouldn't be called with N larger than 2^896! */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } M.p = Mp; memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + P448_WIDTH, M.n * sizeof(mbedtls_mpi_uint)); /* N = A0 */ for (i = P448_WIDTH; i < N->n; i++) { N->p[i] = 0; } /* N += A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M)); /* Q = B1, N += B1 */ Q = M; Q.p = Qp; memcpy(Qp, Mp, sizeof(Qp)); MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&Q, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &Q)); /* M = (B0 + B1) * 2^224, N += M */ if (sizeof(mbedtls_mpi_uint) > 4) { Mp[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS); } for (i = P224_WIDTH_MAX; i < M.n; ++i) { Mp[i] = 0; } MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&M, &M, &Q)); M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&M, 224)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(N, N, &M)); cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo P = 2^s - R, * with R about 33 bits, used by the Koblitz curves. * * Write N as A0 + 2^224 A1, return A0 + R * A1. * Actually do two passes, since R is big. */ #define P_KOBLITZ_MAX (256 / 8 / sizeof(mbedtls_mpi_uint)) // Max limbs in P #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R static inline int ecp_mod_koblitz(mbedtls_mpi *N, const mbedtls_mpi_uint *Rp, size_t p_limbs, size_t adjust, size_t shift, mbedtls_mpi_uint mask) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_mpi M, R; mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; if (N->n < p_limbs) { return 0; } /* Init R */ R.s = 1; R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */ R.n = P_KOBLITZ_R; /* Common setup for M */ M.s = 1; M.p = Mp; /* M = A1 */ M.n = (unsigned short) (N->n - (p_limbs - adjust)); if (M.n > p_limbs + adjust) { M.n = (unsigned short) (p_limbs + adjust); } memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); if (shift != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); } M.n += R.n; /* Make room for multiplication by R */ /* N = A0 */ if (mask != 0) { N->p[p_limbs - 1] &= mask; } for (i = p_limbs; i < N->n; i++) { N->p[i] = 0; } /* N = A0 + R * A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); /* Second pass */ /* M = A1 */ M.n = (unsigned short) (N->n - (p_limbs - adjust)); if (M.n > p_limbs + adjust) { M.n = (unsigned short) (p_limbs + adjust); } memset(Mp, 0, sizeof(Mp)); memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); if (shift != 0) { MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); } M.n += R.n; /* Make room for multiplication by R */ /* N = A0 */ if (mask != 0) { N->p[p_limbs - 1] &= mask; } for (i = p_limbs; i < N->n; i++) { N->p[i] = 0; } /* N = A0 + R * A1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); cleanup: return ret; } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || MBEDTLS_ECP_DP_SECP224K1_ENABLED) || MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 */ static int ecp_mod_p192k1(mbedtls_mpi *N) { static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; return ecp_mod_koblitz(N, Rp, 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) /* * Fast quasi-reduction modulo p224k1 = 2^224 - R, * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 */ static int ecp_mod_p224k1(mbedtls_mpi *N) { static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; #if defined(MBEDTLS_HAVE_INT64) return ecp_mod_koblitz(N, Rp, 4, 1, 32, 0xFFFFFFFF); #else return ecp_mod_koblitz(N, Rp, 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); #endif } #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo p256k1 = 2^256 - R, * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 */ static int ecp_mod_p256k1(mbedtls_mpi *N) { static const mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; return ecp_mod_koblitz(N, Rp, 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE mbedtls_ecp_variant mbedtls_ecp_get_variant(void) { return MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT; } #endif /* MBEDTLS_TEST_HOOKS */ #endif /* !MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_LIGHT */ #endif /* MBEDTLS_ECP_WITH_MPI_UINT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecp_curves_new.c000066400000000000000000012246651464416617300245270ustar00rootroot00000000000000/* * Elliptic curves over GF(p): curve-specific data and functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ECP_WITH_MPI_UINT) #if defined(MBEDTLS_ECP_LIGHT) #include "mbedtls/ecp.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "constant_time_internal.h" #include "bn_mul.h" #include "bignum_core.h" #include "ecp_invasive.h" #include #if !defined(MBEDTLS_ECP_ALT) #define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) } #define ECP_MPI_INIT_ARRAY(x) \ ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint)) #define ECP_POINT_INIT_XY_Z0(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) } #define ECP_POINT_INIT_XY_Z1(x, y) { \ ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) } #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* For these curves, we build the group parameters dynamically. */ #define ECP_LOAD_GROUP static mbedtls_mpi_uint mpi_one[] = { 1 }; #endif /* * Note: the constants are in little-endian order * to be directly usable in MPIs */ /* * Domain parameters for secp192r1 */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static const mbedtls_mpi_uint secp192r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64), }; static const mbedtls_mpi_uint secp192r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18), }; static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07), }; static const mbedtls_mpi_uint secp192r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED), }; static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E), }; static const mbedtls_mpi_uint secp192r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E), }; static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14), }; static const mbedtls_mpi_uint secp192r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2), }; static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB), }; static const mbedtls_mpi_uint secp192r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7), }; static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2), }; static const mbedtls_mpi_uint secp192r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62), }; static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC), }; static const mbedtls_mpi_uint secp192r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F), }; static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55), }; static const mbedtls_mpi_uint secp192r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF), }; static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31), }; static const mbedtls_mpi_uint secp192r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC), }; static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83), }; static const mbedtls_mpi_uint secp192r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98), }; static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5), }; static const mbedtls_mpi_uint secp192r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD), }; static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F), }; static const mbedtls_mpi_uint secp192r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD), }; static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A), }; static const mbedtls_mpi_uint secp192r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66), }; static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7), }; static const mbedtls_mpi_uint secp192r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45), }; static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71), }; static const mbedtls_mpi_uint secp192r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC), }; static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2), }; static const mbedtls_mpi_uint secp192r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48), }; static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C), }; static const mbedtls_ecp_point secp192r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), }; #else #define secp192r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ /* * Domain parameters for secp224r1 */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static const mbedtls_mpi_uint secp224r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C), MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4), }; static const mbedtls_mpi_uint secp224r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7), }; static const mbedtls_mpi_uint secp224r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD), }; static const mbedtls_mpi_uint secp224r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), }; #else #define secp224r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ /* * Domain parameters for secp256r1 */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static const mbedtls_mpi_uint secp256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A), }; static const mbedtls_mpi_uint secp256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B), }; static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F), }; static const mbedtls_mpi_uint secp256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20), }; static const mbedtls_mpi_uint secp256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62), }; static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7), }; static const mbedtls_mpi_uint secp256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00), }; static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03), }; static const mbedtls_mpi_uint secp256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C), }; static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3), }; static const mbedtls_mpi_uint secp256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED), }; static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3), }; static const mbedtls_mpi_uint secp256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95), }; static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68), }; static const mbedtls_mpi_uint secp256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54), }; static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6), }; static const mbedtls_mpi_uint secp256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE), }; static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4), }; static const mbedtls_mpi_uint secp256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86), }; static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16), }; static const mbedtls_mpi_uint secp256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18), }; static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C), }; static const mbedtls_mpi_uint secp256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6), }; static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF), }; static const mbedtls_mpi_uint secp256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E), }; static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44), }; static const mbedtls_mpi_uint secp256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4), }; static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7), }; static const mbedtls_mpi_uint secp256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82), }; static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43), }; static const mbedtls_ecp_point secp256r1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), }; #else #define secp256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ /* * Domain parameters for secp384r1 */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static const mbedtls_mpi_uint secp384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3), }; static const mbedtls_mpi_uint secp384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36), }; static const mbedtls_mpi_uint secp384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD), }; static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE), }; static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3), }; static const mbedtls_mpi_uint secp384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD), }; static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F), }; static const mbedtls_mpi_uint secp384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48), }; static const mbedtls_mpi_uint secp384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A), }; static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08), }; static const mbedtls_mpi_uint secp384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F), }; static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74), }; static const mbedtls_mpi_uint secp384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03), }; static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB), }; static const mbedtls_mpi_uint secp384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF), }; static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97), }; static const mbedtls_mpi_uint secp384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5), }; static const mbedtls_mpi_uint secp384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91), }; static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5), }; static const mbedtls_mpi_uint secp384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15), }; static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98), }; static const mbedtls_mpi_uint secp384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F), }; static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10), }; static const mbedtls_mpi_uint secp384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1), }; static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0), }; static const mbedtls_mpi_uint secp384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC), }; static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6), }; static const mbedtls_mpi_uint secp384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A), }; static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53), }; static const mbedtls_mpi_uint secp384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC), }; static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85), }; static const mbedtls_mpi_uint secp384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23), }; static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3), }; static const mbedtls_mpi_uint secp384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6), }; static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67), }; static const mbedtls_mpi_uint secp384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC), }; static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA), }; static const mbedtls_mpi_uint secp384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE), }; static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05), }; static const mbedtls_mpi_uint secp384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA), }; static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63), }; static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1), }; static const mbedtls_mpi_uint secp384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D), }; static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D), }; static const mbedtls_mpi_uint secp384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF), }; static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71), }; static const mbedtls_mpi_uint secp384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F), }; static const mbedtls_mpi_uint secp384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2), }; static const mbedtls_mpi_uint secp384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7), }; static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21), }; static const mbedtls_mpi_uint secp384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E), }; static const mbedtls_mpi_uint secp384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6), }; static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42), }; static const mbedtls_mpi_uint secp384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12), }; static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77), }; static const mbedtls_mpi_uint secp384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B), }; static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41), }; static const mbedtls_ecp_point secp384r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), }; #else #define secp384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ /* * Domain parameters for secp521r1 */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static const mbedtls_mpi_uint secp521r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; static const mbedtls_mpi_uint secp521r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95), MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00), }; static const mbedtls_mpi_uint secp521r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00), }; static const mbedtls_mpi_uint secp521r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01), }; static const mbedtls_mpi_uint secp521r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp521r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp521r1_T[32] = { ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), }; #else #define secp521r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static const mbedtls_mpi_uint secp192k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp192k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp192k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00), }; static const mbedtls_mpi_uint secp192k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp192k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB), }; static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B), }; static const mbedtls_mpi_uint secp192k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E), }; static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7), }; static const mbedtls_mpi_uint secp192k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28), }; static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4), }; static const mbedtls_mpi_uint secp192k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C), }; static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A), }; static const mbedtls_mpi_uint secp192k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF), }; static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F), }; static const mbedtls_mpi_uint secp192k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9), }; static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D), }; static const mbedtls_mpi_uint secp192k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5), }; static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B), }; static const mbedtls_mpi_uint secp192k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC), }; static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E), }; static const mbedtls_mpi_uint secp192k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82), }; static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22), }; static const mbedtls_mpi_uint secp192k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05), }; static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96), }; static const mbedtls_mpi_uint secp192k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D), }; static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D), }; static const mbedtls_mpi_uint secp192k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67), }; static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C), }; static const mbedtls_mpi_uint secp192k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF), }; static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD), }; static const mbedtls_mpi_uint secp192k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8), }; static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9), }; static const mbedtls_mpi_uint secp192k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76), }; static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35), }; static const mbedtls_mpi_uint secp192k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63), }; static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8), }; static const mbedtls_ecp_point secp192k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), }; #else #define secp192k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static const mbedtls_mpi_uint secp224k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp224k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00), }; static const mbedtls_mpi_uint secp224k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1), }; static const mbedtls_mpi_uint secp224k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E), }; static const mbedtls_mpi_uint secp224k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp224k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00), }; static const mbedtls_ecp_point secp224k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), }; #else #define secp224k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static const mbedtls_mpi_uint secp256k1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; static const mbedtls_mpi_uint secp256k1_a[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00), }; static const mbedtls_mpi_uint secp256k1_b[] = { MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00), }; static const mbedtls_mpi_uint secp256k1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint secp256k1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79), }; static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48), }; static const mbedtls_mpi_uint secp256k1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC), }; static const mbedtls_mpi_uint secp256k1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF), }; static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4), }; static const mbedtls_mpi_uint secp256k1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54), }; static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE), }; static const mbedtls_mpi_uint secp256k1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E), }; static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0), }; static const mbedtls_mpi_uint secp256k1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1), }; static const mbedtls_mpi_uint secp256k1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15), }; static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05), }; static const mbedtls_mpi_uint secp256k1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72), }; static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22), }; static const mbedtls_mpi_uint secp256k1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16), }; static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E), }; static const mbedtls_mpi_uint secp256k1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E), }; static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D), }; static const mbedtls_mpi_uint secp256k1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0), }; static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01), }; static const mbedtls_mpi_uint secp256k1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12), }; static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25), }; static const mbedtls_mpi_uint secp256k1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B), }; static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B), }; static const mbedtls_mpi_uint secp256k1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64), }; static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F), }; static const mbedtls_mpi_uint secp256k1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07), }; static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9), }; static const mbedtls_mpi_uint secp256k1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89), }; static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB), }; static const mbedtls_ecp_point secp256k1_T[16] = { ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), }; #else #define secp256k1_T NULL #endif #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ /* * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) static const mbedtls_mpi_uint brainpoolP256r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; static const mbedtls_mpi_uint brainpoolP256r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D), }; static const mbedtls_mpi_uint brainpoolP256r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26), }; static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B), }; static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80), }; static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36), }; static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47), }; static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87), }; static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19), }; static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C), }; static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57), }; static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E), }; static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51), }; static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17), }; static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72), }; static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10), }; static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98), }; static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F), }; static const mbedtls_ecp_point brainpoolP256r1_T[16] = { ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), }; #else #define brainpoolP256r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ /* * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) static const mbedtls_mpi_uint brainpoolP384r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; static const mbedtls_mpi_uint brainpoolP384r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B), }; static const mbedtls_mpi_uint brainpoolP384r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04), }; static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C), }; static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82), }; static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E), }; static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39), }; static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28), }; static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03), }; static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C), MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9), MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04), MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31), }; static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55), }; static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63), }; static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77), }; static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79), }; static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88), }; static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42), }; static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31), MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12), }; static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D), }; static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70), }; static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73), }; static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F), }; static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F), }; static const mbedtls_ecp_point brainpoolP384r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), }; #else #define brainpoolP384r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ /* * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) static const mbedtls_mpi_uint brainpoolP512r1_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; static const mbedtls_mpi_uint brainpoolP512r1_a[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78), }; static const mbedtls_mpi_uint brainpoolP512r1_b[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA), }; #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81), }; static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78), MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88), }; static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2), }; static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49), }; static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99), }; static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE), MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD), MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01), }; static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83), MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42), }; static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E), MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89), MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D), MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51), MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D), MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46), MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62), MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8), MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02), }; static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9), MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D), MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE), MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E), MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1), MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0), MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B), MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D), MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5), }; static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9), MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D), MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5), MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E), MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17), MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F), MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69), MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C), MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8), MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D), MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4), MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2), MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16), MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5), MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1), MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E), MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B), MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B), MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63), }; static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF), MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24), }; static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86), MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4), MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC), MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F), MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E), MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01), MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93), }; static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2), MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24), MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4), MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8), MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81), MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68), MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36), MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87), MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60), MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9), MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34), MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56), MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC), MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E), }; static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7), MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79), MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C), MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14), MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71), MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A), MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57), MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6), MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA), MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82), MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3), MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A), MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05), MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12), MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0), MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3), MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22), MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB), MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A), MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7), MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D), MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44), MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0), MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39), MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF), MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20), MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D), MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41), MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A), }; static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4), MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53), MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96), MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD), MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B), MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA), MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4), MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE), MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90), }; static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6), MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC), MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2), MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D), MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B), MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13), MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95), MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3), MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45), MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98), MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B), MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD), MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84), MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B), MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18), }; static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B), MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43), MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A), MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11), MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E), MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC), MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2), MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB), MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A), MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E), MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB), MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93), MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08), MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34), }; static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25), MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C), MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1), MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9), MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63), MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1), MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4), MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42), }; static const mbedtls_ecp_point brainpoolP512r1_T[32] = { ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), }; #else #define brainpoolP512r1_T NULL #endif #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* * Create an MPI from embedded constants * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint) and * len < 1048576) */ static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len) { X->s = 1; X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint)); X->p = (mbedtls_mpi_uint *) p; } #endif #if defined(ECP_LOAD_GROUP) /* * Set an MPI to static value 1 */ static inline void ecp_mpi_set1(mbedtls_mpi *X) { X->s = 1; X->n = 1; X->p = mpi_one; } /* * Make group available from embedded constants */ static int ecp_group_load(mbedtls_ecp_group *grp, const mbedtls_mpi_uint *p, size_t plen, const mbedtls_mpi_uint *a, size_t alen, const mbedtls_mpi_uint *b, size_t blen, const mbedtls_mpi_uint *gx, size_t gxlen, const mbedtls_mpi_uint *gy, size_t gylen, const mbedtls_mpi_uint *n, size_t nlen, const mbedtls_ecp_point *T) { ecp_mpi_load(&grp->P, p, plen); if (a != NULL) { ecp_mpi_load(&grp->A, a, alen); } ecp_mpi_load(&grp->B, b, blen); ecp_mpi_load(&grp->N, n, nlen); ecp_mpi_load(&grp->G.X, gx, gxlen); ecp_mpi_load(&grp->G.Y, gy, gylen); ecp_mpi_set1(&grp->G.Z); grp->pbits = mbedtls_mpi_bitlen(&grp->P); grp->nbits = mbedtls_mpi_bitlen(&grp->N); grp->h = 1; grp->T = (mbedtls_ecp_point *) T; /* * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. */ grp->T_size = 0; return 0; } #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_NIST_OPTIM) /* Forward declarations */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) static int ecp_mod_p192(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) static int ecp_mod_p224(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) static int ecp_mod_p256(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) static int ecp_mod_p384(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) static int ecp_mod_p521(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n); #endif #define NIST_MODP(P) grp->modp = ecp_mod_ ## P; #else #define NIST_MODP(P) #endif /* MBEDTLS_ECP_NIST_OPTIM */ /* Additional forward declarations */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) static int ecp_mod_p255(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) static int ecp_mod_p448(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *, size_t); #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) static int ecp_mod_p192k1(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) static int ecp_mod_p224k1(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) static int ecp_mod_p256k1(mbedtls_mpi *); MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(ECP_LOAD_GROUP) #define LOAD_GROUP_A(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ G ## _a, sizeof(G ## _a), \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #define LOAD_GROUP(G) ecp_group_load(grp, \ G ## _p, sizeof(G ## _p), \ NULL, 0, \ G ## _b, sizeof(G ## _b), \ G ## _gx, sizeof(G ## _gx), \ G ## _gy, sizeof(G ## _gy), \ G ## _n, sizeof(G ## _n), \ G ## _T \ ) #endif /* ECP_LOAD_GROUP */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Constants used by ecp_use_curve25519() */ static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; /* P = 2^255 - 19 */ static const mbedtls_mpi_uint curve25519_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F) }; /* N = 2^252 + 27742317777372353535851937790883648493 */ static const mbedtls_mpi_uint curve25519_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58), MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14), MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00), MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10) }; /* * Specialized function for creating the Curve25519 group */ static int ecp_use_curve25519(mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24)); ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n)); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); /* Actually, the required msb for private keys */ grp->nbits = 254; cleanup: if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Constants used by ecp_use_curve448() */ static const mbedtls_mpi_sint curve448_a24 = 0x98AA; /* P = 2^448 - 2^224 - 1 */ static const mbedtls_mpi_uint curve448_p[] = { MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) }; /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ static const mbedtls_mpi_uint curve448_n[] = { MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23), MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21), MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4), MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF), MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F), MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00) }; /* * Specialized function for creating the Curve448 group */ static int ecp_use_curve448(mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Actually ( A + 2 ) / 4 */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24)); ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p)); grp->pbits = mbedtls_mpi_bitlen(&grp->P); /* Y intentionally not set, since we use x/z coordinates. * This is used as a marker to identify Montgomery curves! */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5)); MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1)); mbedtls_mpi_free(&grp->G.Y); ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n)); /* Actually, the required msb for private keys */ grp->nbits = 447; cleanup: if (ret != 0) { mbedtls_ecp_group_free(grp); } return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ /* * Set a group using well-known domain parameters */ int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id) { mbedtls_ecp_group_free(grp); mbedtls_ecp_group_init(grp); grp->id = id; switch (id) { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: NIST_MODP(p192); return LOAD_GROUP(secp192r1); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) case MBEDTLS_ECP_DP_SECP224R1: NIST_MODP(p224); return LOAD_GROUP(secp224r1); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) case MBEDTLS_ECP_DP_SECP256R1: NIST_MODP(p256); return LOAD_GROUP(secp256r1); #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) case MBEDTLS_ECP_DP_SECP384R1: NIST_MODP(p384); return LOAD_GROUP(secp384r1); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) case MBEDTLS_ECP_DP_SECP521R1: NIST_MODP(p521); return LOAD_GROUP(secp521r1); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) case MBEDTLS_ECP_DP_SECP192K1: grp->modp = ecp_mod_p192k1; return LOAD_GROUP_A(secp192k1); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) case MBEDTLS_ECP_DP_SECP224K1: grp->modp = ecp_mod_p224k1; return LOAD_GROUP_A(secp224k1); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) case MBEDTLS_ECP_DP_SECP256K1: grp->modp = ecp_mod_p256k1; return LOAD_GROUP_A(secp256k1); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) case MBEDTLS_ECP_DP_BP256R1: return LOAD_GROUP_A(brainpoolP256r1); #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) case MBEDTLS_ECP_DP_BP384R1: return LOAD_GROUP_A(brainpoolP384r1); #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) case MBEDTLS_ECP_DP_BP512R1: return LOAD_GROUP_A(brainpoolP512r1); #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: grp->modp = ecp_mod_p255; return ecp_use_curve25519(grp); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: grp->modp = ecp_mod_p448; return ecp_use_curve448(grp); #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ default: grp->id = MBEDTLS_ECP_DP_NONE; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } } #if defined(MBEDTLS_ECP_NIST_OPTIM) /* * Fast reduction modulo the primes used by the NIST curves. * * These functions are critical for speed, but not needed for correct * operations. So, we make the choice to heavily rely on the internals of our * bignum library, which creates a tight coupling between these functions and * our MPI implementation. However, the coupling between the ECP module and * MPI remains loose, since these functions can be deactivated at will. */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /* * Compared to the way things are presented in FIPS 186-3 D.2, * we proceed in columns, from right (least significant chunk) to left, * adding chunks to N in place, and keeping a carry for the next chunk. * This avoids moving things around in memory, and uselessly adding zeros, * compared to the more straightforward, line-oriented approach. * * For this prime we need to handle data in chunks of 64 bits. * Since this is always a multiple of our basic mbedtls_mpi_uint, we can * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. */ /* Add 64-bit chunks (dst += src) and update carry */ static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry) { unsigned char i; mbedtls_mpi_uint c = 0; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) { *dst += c; c = (*dst < c); *dst += *src; c += (*dst < *src); } *carry += c; } /* Add carry to a 64-bit chunk and update carry */ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry) { unsigned char i; for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) { *dst += *carry; *carry = (*dst < *carry); } } #define WIDTH 8 / sizeof(mbedtls_mpi_uint) #define A(i) Np + (i) * WIDTH #define ADD(i) add64(p, A(i), &c) #define NEXT p += WIDTH; carry64(p, &c) #define LAST p += WIDTH; do *p = 0; while (++p < end) #define RESET last_carry[0] = c; c = 0; p = Np #define ADD_LAST add64(p, last_carry, &c) /* * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) */ static int ecp_mod_p192(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(192) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) { mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 }; mbedtls_mpi_uint *p, *end; if (Nn != BITS_TO_LIMBS(192) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } p = Np; end = p + Nn; ADD(3); ADD(5); NEXT; // A0 += A3 + A5 ADD(3); ADD(4); ADD(5); NEXT; // A1 += A3 + A4 + A5 ADD(4); ADD(5); // A2 += A4 + A5 RESET; /* Use the reduction for the carry as well: * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 * It can generate a carry. */ ADD_LAST; NEXT; // A0 += last_carry ADD_LAST; NEXT; // A1 += last_carry // A2 += carry RESET; /* Use the reduction for the carry as well: * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192 */ ADD_LAST; NEXT; // A0 += last_carry ADD_LAST; NEXT; // A1 += last_carry // A2 += carry LAST; return 0; } #undef WIDTH #undef A #undef ADD #undef NEXT #undef LAST #undef RESET #undef ADD_LAST #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * The reader is advised to first understand ecp_mod_p192() since the same * general structure is used here, but with additional complications: * (1) chunks of 32 bits, and (2) subtractions. */ /* * For these primes, we need to handle data in chunks of 32 bits. * This makes it more complicated if we use 64 bits limbs in MPI, * which prevents us from using a uniform access method as for p192. * * So, we define a mini abstraction layer to access 32 bit chunks, * load them in 'cur' for work, and store them back from 'cur' when done. * * While at it, also define the size of N in terms of 32-bit chunks. */ #define LOAD32 cur = A(i); #if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ #define MAX32 X_limbs #define A(j) X[j] #define STORE32 X[i] = (mbedtls_mpi_uint) cur; #define STORE0 X[i] = 0; #else /* 64 bit */ #define MAX32 X_limbs * 2 #define A(j) \ (j) % 2 ? \ (uint32_t) (X[(j) / 2] >> 32) : \ (uint32_t) (X[(j) / 2]) #define STORE32 \ if (i % 2) { \ X[i/2] &= 0x00000000FFFFFFFF; \ X[i/2] |= (uint64_t) (cur) << 32; \ } else { \ X[i/2] &= 0xFFFFFFFF00000000; \ X[i/2] |= (uint32_t) cur; \ } #define STORE0 \ if (i % 2) { \ X[i/2] &= 0x00000000FFFFFFFF; \ } else { \ X[i/2] &= 0xFFFFFFFF00000000; \ } #endif static inline int8_t extract_carry(int64_t cur) { return (int8_t) (cur >> 32); } #define ADD(j) cur += A(j) #define SUB(j) cur -= A(j) #define ADD_CARRY(cc) cur += (cc) #define SUB_CARRY(cc) cur -= (cc) #define ADD_LAST ADD_CARRY(last_c) #define SUB_LAST SUB_CARRY(last_c) /* * Helpers for the main 'loop' */ #define INIT(b) \ int8_t c = 0, last_c; \ int64_t cur; \ size_t i = 0; \ LOAD32; #define NEXT \ c = extract_carry(cur); \ STORE32; i++; LOAD32; \ ADD_CARRY(c); #define RESET \ c = extract_carry(cur); \ last_c = c; \ STORE32; i = 0; LOAD32; \ c = 0; \ #define LAST \ c = extract_carry(cur); \ STORE32; i++; \ if (c != 0) \ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; \ while (i < MAX32) { STORE0; i++; } #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) /* * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) */ static int ecp_mod_p224(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(224) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs) { if (X_limbs != BITS_TO_LIMBS(224) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } INIT(224); SUB(7); SUB(11); NEXT; // A0 += -A7 - A11 SUB(8); SUB(12); NEXT; // A1 += -A8 - A12 SUB(9); SUB(13); NEXT; // A2 += -A9 - A13 SUB(10); ADD(7); ADD(11); NEXT; // A3 += -A10 + A7 + A11 SUB(11); ADD(8); ADD(12); NEXT; // A4 += -A11 + A8 + A12 SUB(12); ADD(9); ADD(13); NEXT; // A5 += -A12 + A9 + A13 SUB(13); ADD(10); // A6 += -A13 + A10 RESET; /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */ SUB_LAST; NEXT; // A0 -= last_c ; NEXT; // A1 ; NEXT; // A2 ADD_LAST; NEXT; // A3 += last_c ; NEXT; // A4 ; NEXT; // A5 // A6 /* The carry reduction cannot generate a carry * (see commit 73e8553 for details)*/ LAST; return 0; } #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) /* * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) */ static int ecp_mod_p256(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(256) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs) { if (X_limbs != BITS_TO_LIMBS(256) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } INIT(256); ADD(8); ADD(9); SUB(11); SUB(12); SUB(13); SUB(14); NEXT; // A0 ADD(9); ADD(10); SUB(12); SUB(13); SUB(14); SUB(15); NEXT; // A1 ADD(10); ADD(11); SUB(13); SUB(14); SUB(15); NEXT; // A2 ADD(11); ADD(11); ADD(12); ADD(12); ADD(13); SUB(15); SUB(8); SUB(9); NEXT; // A3 ADD(12); ADD(12); ADD(13); ADD(13); ADD(14); SUB(9); SUB(10); NEXT; // A4 ADD(13); ADD(13); ADD(14); ADD(14); ADD(15); SUB(10); SUB(11); NEXT; // A5 ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13); SUB(8); SUB(9); NEXT; // A6 ADD(15); ADD(15); ADD(15); ADD(8); SUB(10); SUB(11); SUB(12); SUB(13); // A7 RESET; /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 * to modulo reduce the final carry. */ ADD_LAST; NEXT; // A0 ; NEXT; // A1 ; NEXT; // A2 SUB_LAST; NEXT; // A3 ; NEXT; // A4 ; NEXT; // A5 SUB_LAST; NEXT; // A6 ADD_LAST; // A7 RESET; /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1 * to modulo reduce the carry generated by the previous reduction. */ ADD_LAST; NEXT; // A0 ; NEXT; // A1 ; NEXT; // A2 SUB_LAST; NEXT; // A3 ; NEXT; // A4 ; NEXT; // A5 SUB_LAST; NEXT; // A6 ADD_LAST; // A7 LAST; return 0; } #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /* * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) */ static int ecp_mod_p384(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(384) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p384_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs) { if (X_limbs != BITS_TO_LIMBS(384) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } INIT(384); ADD(12); ADD(21); ADD(20); SUB(23); NEXT; // A0 ADD(13); ADD(22); ADD(23); SUB(12); SUB(20); NEXT; // A1 ADD(14); ADD(23); SUB(13); SUB(21); NEXT; // A2 ADD(15); ADD(12); ADD(20); ADD(21); SUB(14); SUB(22); SUB(23); NEXT; // A3 ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22); SUB(15); SUB(23); SUB(23); NEXT; // A4 ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23); SUB(16); NEXT; // A5 ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22); SUB(17); NEXT; // A6 ADD(19); ADD(16); ADD(15); ADD(23); SUB(18); NEXT; // A7 ADD(20); ADD(17); ADD(16); SUB(19); NEXT; // A8 ADD(21); ADD(18); ADD(17); SUB(20); NEXT; // A9 ADD(22); ADD(19); ADD(18); SUB(21); NEXT; // A10 ADD(23); ADD(20); ADD(19); SUB(22); // A11 RESET; /* Use 2^384 = P + 2^128 + 2^96 - 2^32 + 1 to modulo reduce the final carry */ ADD_LAST; NEXT; // A0 SUB_LAST; NEXT; // A1 ; NEXT; // A2 ADD_LAST; NEXT; // A3 ADD_LAST; NEXT; // A4 ; NEXT; // A5 ; NEXT; // A6 ; NEXT; // A7 ; NEXT; // A8 ; NEXT; // A9 ; NEXT; // A10 // A11 RESET; ADD_LAST; NEXT; // A0 SUB_LAST; NEXT; // A1 ; NEXT; // A2 ADD_LAST; NEXT; // A3 ADD_LAST; NEXT; // A4 ; NEXT; // A5 ; NEXT; // A6 ; NEXT; // A7 ; NEXT; // A8 ; NEXT; // A9 ; NEXT; // A10 // A11 LAST; return 0; } #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #undef LOAD32 #undef MAX32 #undef A #undef STORE32 #undef STORE0 #undef ADD #undef SUB #undef ADD_CARRY #undef SUB_CARRY #undef ADD_LAST #undef SUB_LAST #undef INIT #undef NEXT #undef RESET #undef LAST #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || MBEDTLS_ECP_DP_SECP256R1_ENABLED || MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) /* Size of p521 in terms of mbedtls_mpi_uint */ #define P521_WIDTH (521 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* Bits to keep in the most significant mbedtls_mpi_uint */ #define P521_MASK 0x01FF /* * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) */ static int ecp_mod_p521(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(521) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs) { mbedtls_mpi_uint carry = 0; if (X_limbs != BITS_TO_LIMBS(521) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Step 1: Reduction to P521_WIDTH limbs */ /* Helper references for bottom part of X */ mbedtls_mpi_uint *X0 = X; size_t X0_limbs = P521_WIDTH; /* Helper references for top part of X */ mbedtls_mpi_uint *X1 = X + X0_limbs; size_t X1_limbs = X_limbs - X0_limbs; /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1. * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.) * The high order limb of the result will be held in carry and the rest * in X0 (that is the result will be represented as * 2^P521_WIDTH carry + X0). * * Also, note that the resulting carry is either 0 or 1: * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512 * therefore * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9) * which in turn is less than 2 * 2^(512 + biL). */ mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9); carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift); /* Set X to X0 (by clearing the top part). */ memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint)); /* Step 2: Reduction modulo P521 * * At this point X is reduced to P521_WIDTH limbs. What remains is to add * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */ /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521. * Also, recall that carry is either 0 or 1. */ mbedtls_mpi_uint addend = carry << (biL - 9); /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */ addend += (X[P521_WIDTH - 1] >> 9); X[P521_WIDTH - 1] &= P521_MASK; /* Reuse the top part of X (already zeroed) as a helper array for * carrying out the addition. */ mbedtls_mpi_uint *addend_arr = X + P521_WIDTH; addend_arr[0] = addend; (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH); /* Both addends were less than P521 therefore X < 2 * P521. (This also means * that the result fit in P521_WIDTH limbs and there won't be any carry.) */ /* Clear the reused part of X. */ addend_arr[0] = 0; return 0; } #undef P521_WIDTH #undef P521_MASK #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_ECP_NIST_OPTIM */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /* Size of p255 in terms of mbedtls_mpi_uint */ #define P255_WIDTH (255 / 8 / sizeof(mbedtls_mpi_uint) + 1) /* * Fast quasi-reduction modulo p255 = 2^255 - 19 * Write N as A0 + 2^256 A1, return A0 + 38 * A1 */ static int ecp_mod_p255(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(255) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p255_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_Limbs) { if (X_Limbs != BITS_TO_LIMBS(255) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } mbedtls_mpi_uint *carry = mbedtls_calloc(P255_WIDTH, ciL); if (carry == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } /* Step 1: Reduction to P255_WIDTH limbs */ if (X_Limbs > P255_WIDTH) { /* Helper references for top part of X */ mbedtls_mpi_uint * const A1 = X + P255_WIDTH; const size_t A1_limbs = X_Limbs - P255_WIDTH; /* X = A0 + 38 * A1, capture carry out */ *carry = mbedtls_mpi_core_mla(X, P255_WIDTH, A1, A1_limbs, 38); /* Clear top part */ memset(A1, 0, sizeof(mbedtls_mpi_uint) * A1_limbs); } /* Step 2: Reduce to <2p * Split as A0 + 2^255*c, with c a scalar, and compute A0 + 19*c */ *carry <<= 1; *carry += (X[P255_WIDTH - 1] >> (biL - 1)); *carry *= 19; /* Clear top bit */ X[P255_WIDTH - 1] <<= 1; X[P255_WIDTH - 1] >>= 1; /* Since the top bit for X has been cleared 0 + 0 + Carry * will not overflow. * * Furthermore for 2p = 2^256-38. When a carry propagation on the highest * limb occurs, X > 2^255 and all the remaining bits on the limb are zero. * - If X < 2^255 ==> X < 2p * - If X > 2^255 ==> X < 2^256 - 2^255 < 2p */ (void) mbedtls_mpi_core_add(X, X, carry, P255_WIDTH); mbedtls_free(carry); return 0; } #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /* Size of p448 in terms of mbedtls_mpi_uint */ #define P448_WIDTH (448 / 8 / sizeof(mbedtls_mpi_uint)) /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ #define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y)) #define P224_SIZE (224 / 8) #define P224_WIDTH_MIN (P224_SIZE / sizeof(mbedtls_mpi_uint)) #define P224_WIDTH_MAX DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint)) #define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224) static int ecp_mod_p448(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(448) * 2; /* This is required as some tests and use cases do not pass in a Bignum of * the correct size, and expect the growth to be done automatically, which * will no longer happen. */ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p448_raw(N->p, N->n); cleanup: return ret; } /* * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + * (B0 + B1) * 2^224. This is different to the reference implementation of * Curve448, which uses its own special 56-bit limbs rather than a generic * bignum library. We could squeeze some extra speed out on 32-bit machines by * splitting N up into 32-bit limbs and doing the arithmetic using the limbs * directly as we do for the NIST primes above, but for 64-bit targets it should * use half the number of operations if we do the reduction with 224-bit limbs, * since mpi_core_add will then use 64-bit adds. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs) { size_t round; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (X_limbs != BITS_TO_LIMBS(448) * 2) { return 0; } size_t M_limbs = X_limbs - (P448_WIDTH); if (M_limbs > P448_WIDTH) { /* Shouldn't be called with X larger than 2^896! */ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } /* Both M and Q require an extra limb to catch carries. */ M_limbs++; const size_t Q_limbs = M_limbs; mbedtls_mpi_uint *M = NULL; mbedtls_mpi_uint *Q = NULL; M = mbedtls_calloc(M_limbs, ciL); if (M == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } Q = mbedtls_calloc(Q_limbs, ciL); if (Q == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } /* M = A1 */ memset(M, 0, (M_limbs * ciL)); /* Do not copy into the overflow limb, as this would read past the end of * X. */ memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); /* X = A0 */ memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); /* X = X + M = A0 + A1 */ /* Carry here fits in oversize X. Oversize M means it will get * added in, not returned as carry. */ (void) mbedtls_mpi_core_add(X, X, M, M_limbs); /* Q = B1 = M >> 224 */ memcpy(Q, (char *) M + P224_SIZE, P224_SIZE); memset((char *) Q + P224_SIZE, 0, P224_SIZE); /* X = X + Q = (A0 + A1) + B1 * Oversize Q catches potential carry here when X is already max 448 bits. */ (void) mbedtls_mpi_core_add(X, X, Q, Q_limbs); /* M = B0 */ #ifdef MBEDTLS_HAVE_INT64 M[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS); #endif memset(M + P224_WIDTH_MAX, 0, ((M_limbs - P224_WIDTH_MAX) * ciL)); /* M = M + Q = B0 + B1 */ (void) mbedtls_mpi_core_add(M, M, Q, Q_limbs); /* M = (B0 + B1) * 2^224 */ /* Shifted carry bit from the addition fits in oversize M. */ memmove((char *) M + P224_SIZE, M, P224_SIZE + ciL); memset(M, 0, P224_SIZE); /* X = X + M = (A0 + A1 + B1) + (B0 + B1) * 2^224 */ (void) mbedtls_mpi_core_add(X, X, M, M_limbs); /* In the second and third rounds A1 and B0 have at most 1 non-zero limb and * B1=0. * Using this we need to calculate: * A0 + A1 + B1 + (B0 + B1) * 2^224 = A0 + A1 + B0 * 2^224. */ for (round = 0; round < 2; ++round) { /* M = A1 */ memset(M, 0, (M_limbs * ciL)); memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL)); /* X = A0 */ memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL)); /* M = A1 + B0 * 2^224 * We know that only one limb of A1 will be non-zero and that it will be * limb 0. We also know that B0 is the bottom 224 bits of A1 (which is * then shifted up 224 bits), so, given M is currently A1 this turns * into: * M = M + (M << 224) * As the single non-zero limb in B0 will be A1 limb 0 shifted up by 224 * bits, we can just move that into the right place, shifted up * accordingly.*/ M[P224_WIDTH_MIN] = M[0] << (224 & (biL - 1)); /* X = A0 + (A1 + B0 * 2^224) */ (void) mbedtls_mpi_core_add(X, X, M, M_limbs); } ret = 0; cleanup: mbedtls_free(M); mbedtls_free(Q); return ret; } #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo P = 2^s - R, * with R about 33 bits, used by the Koblitz curves. * * Write X as A0 + 2^224 A1, return A0 + R * A1. */ #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, size_t X_limbs, mbedtls_mpi_uint *R, size_t bits) { int ret = 0; /* Determine if A1 is aligned to limb bitsize. If not then the used limbs * of P, A0 and A1 must be set accordingly and there is a middle limb * which is shared by A0 and A1 and need to handle accordingly. */ size_t shift = bits % biL; size_t adjust = (shift + biL - 1) / biL; size_t P_limbs = bits / biL + adjust; mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL); if (A1 == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } /* Create a buffer to store the value of `R * A1` */ size_t R_limbs = P_KOBLITZ_R; size_t M_limbs = P_limbs + R_limbs; mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); if (M == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } mbedtls_mpi_uint mask = 0; if (adjust != 0) { mask = ((mbedtls_mpi_uint) 1 << shift) - 1; } /* Two passes are needed to reduce the value of `A0 + R * A1` and then * we need an additional one to reduce the possible overflow during * the addition. */ for (size_t pass = 0; pass < 3; pass++) { /* Copy A1 */ memcpy(A1, X + P_limbs - adjust, P_limbs * ciL); /* Shift A1 to be aligned */ if (shift != 0) { mbedtls_mpi_core_shift_r(A1, P_limbs, shift); } /* Zeroize the A1 part of the shared limb */ if (mask != 0) { X[P_limbs - 1] &= mask; } /* X = A0 * Zeroize the A1 part of X to keep only the A0 part. */ for (size_t i = P_limbs; i < X_limbs; i++) { X[i] = 0; } /* X = A0 + R * A1 */ mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs); (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs); /* Carry can not be generated since R is a 33-bit value and stored in * 64 bits. The result value of the multiplication is at most * P length + 33 bits in length and the result value of the addition * is at most P length + 34 bits in length. So the result of the * addition always fits in P length + 64 bits. */ } cleanup: mbedtls_free(M); mbedtls_free(A1); return ret; } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || MBEDTLS_ECP_DP_SECP224K1_ENABLED) || MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 */ static int ecp_mod_p192k1(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(192) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p192k1_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) { static mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; if (X_limbs != BITS_TO_LIMBS(192) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mod_koblitz(X, X_limbs, Rp, 192); } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) /* * Fast quasi-reduction modulo p224k1 = 2^224 - R, * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 */ static int ecp_mod_p224k1(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(224) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p224k1_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) { static mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; if (X_limbs != BITS_TO_LIMBS(224) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mod_koblitz(X, X_limbs, Rp, 224); } #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /* * Fast quasi-reduction modulo p256k1 = 2^256 - R, * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 */ static int ecp_mod_p256k1(mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t expected_width = BITS_TO_LIMBS(256) * 2; MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); ret = mbedtls_ecp_mod_p256k1_raw(N->p, expected_width); cleanup: return ret; } MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs) { static mbedtls_mpi_uint Rp[] = { MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; if (X_limbs != BITS_TO_LIMBS(256) * 2) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } return ecp_mod_koblitz(X, X_limbs, Rp, 256); } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_ecp_group_id id, const mbedtls_ecp_modulus_type ctype) { mbedtls_mpi_modp_fn modp = NULL; mbedtls_mpi_uint *p = NULL; size_t p_limbs; if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \ ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } switch (id) { #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) case MBEDTLS_ECP_DP_SECP192R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p192_raw; #endif p = (mbedtls_mpi_uint *) secp192r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p)); } else { p = (mbedtls_mpi_uint *) secp192r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) case MBEDTLS_ECP_DP_SECP224R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p224_raw; #endif p = (mbedtls_mpi_uint *) secp224r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p)); } else { p = (mbedtls_mpi_uint *) secp224r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) case MBEDTLS_ECP_DP_SECP256R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p256_raw; #endif p = (mbedtls_mpi_uint *) secp256r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p)); } else { p = (mbedtls_mpi_uint *) secp256r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) case MBEDTLS_ECP_DP_SECP384R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p384_raw; #endif p = (mbedtls_mpi_uint *) secp384r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p)); } else { p = (mbedtls_mpi_uint *) secp384r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) case MBEDTLS_ECP_DP_SECP521R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { #if defined(MBEDTLS_ECP_NIST_OPTIM) modp = &mbedtls_ecp_mod_p521_raw; #endif p = (mbedtls_mpi_uint *) secp521r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p)); } else { p = (mbedtls_mpi_uint *) secp521r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) case MBEDTLS_ECP_DP_BP256R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { p = (mbedtls_mpi_uint *) brainpoolP256r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p)); } else { p = (mbedtls_mpi_uint *) brainpoolP256r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) case MBEDTLS_ECP_DP_BP384R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { p = (mbedtls_mpi_uint *) brainpoolP384r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p)); } else { p = (mbedtls_mpi_uint *) brainpoolP384r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) case MBEDTLS_ECP_DP_BP512R1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { p = (mbedtls_mpi_uint *) brainpoolP512r1_p; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p)); } else { p = (mbedtls_mpi_uint *) brainpoolP512r1_n; p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) case MBEDTLS_ECP_DP_CURVE25519: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p255_raw; p = (mbedtls_mpi_uint *) curve25519_p; p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p)); } else { p = (mbedtls_mpi_uint *) curve25519_n; p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) case MBEDTLS_ECP_DP_SECP192K1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p192k1_raw; p = (mbedtls_mpi_uint *) secp192k1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p)); } else { p = (mbedtls_mpi_uint *) secp192k1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) case MBEDTLS_ECP_DP_SECP224K1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p224k1_raw; p = (mbedtls_mpi_uint *) secp224k1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p)); } else { p = (mbedtls_mpi_uint *) secp224k1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) case MBEDTLS_ECP_DP_SECP256K1: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p256k1_raw; p = (mbedtls_mpi_uint *) secp256k1_p; p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p)); } else { p = (mbedtls_mpi_uint *) secp256k1_n; p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n)); } break; #endif #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) case MBEDTLS_ECP_DP_CURVE448: if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) { modp = &mbedtls_ecp_mod_p448_raw; p = (mbedtls_mpi_uint *) curve448_p; p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p)); } else { p = (mbedtls_mpi_uint *) curve448_n; p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n)); } break; #endif default: case MBEDTLS_ECP_DP_NONE: return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } if (modp != NULL) { if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } } else { if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } } return 0; } #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE mbedtls_ecp_variant mbedtls_ecp_get_variant(void) { return MBEDTLS_ECP_VARIANT_WITH_MPI_UINT; } #endif /* MBEDTLS_TEST_HOOKS */ #endif /* !MBEDTLS_ECP_ALT */ #endif /* MBEDTLS_ECP_LIGHT */ #endif /* MBEDTLS_ECP_WITH_MPI_UINT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h000066400000000000000000000250421464416617300250130ustar00rootroot00000000000000/** * \file ecp_internal_alt.h * * \brief Function declarations for alternative implementation of elliptic curve * point arithmetic. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. * * * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis * for elliptic curve cryptosystems. In : Cryptographic Hardware and * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. * * * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to * render ECC resistant against Side Channel Attacks. IACR Cryptology * ePrint Archive, 2004, vol. 2004, p. 342. * * * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. * * * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic * Curve Cryptography. * * [6] Digital Signature Standard (DSS), FIPS 186-4. * * * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer * Security (TLS), RFC 4492. * * * [8] * * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. * Springer Science & Business Media, 1 Aug 2000 */ #ifndef MBEDTLS_ECP_INTERNAL_H #define MBEDTLS_ECP_INTERNAL_H #include "mbedtls/build_info.h" #if defined(MBEDTLS_ECP_INTERNAL_ALT) /** * \brief Indicate if the Elliptic Curve Point module extension can * handle the group. * * \param grp The pointer to the elliptic curve group that will be the * basis of the cryptographic computations. * * \return Non-zero if successful. */ unsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp); /** * \brief Initialise the Elliptic Curve Point module extension. * * If mbedtls_internal_ecp_grp_capable returns true for a * group, this function has to be able to initialise the * module for it. * * This module can be a driver to a crypto hardware * accelerator, for which this could be an initialise function. * * \param grp The pointer to the group the module needs to be * initialised for. * * \return 0 if successful. */ int mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp); /** * \brief Frees and deallocates the Elliptic Curve Point module * extension. * * \param grp The pointer to the group the module was initialised for. */ void mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp); #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) /** * \brief Randomize jacobian coordinates: * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. * * \param grp Pointer to the group representing the curve. * * \param pt The point on the curve to be randomised, given with Jacobian * coordinates. * * \param f_rng A function pointer to the random number generator. * * \param p_rng A pointer to the random number generator state. * * \return 0 if successful. */ int mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) /** * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. * * The coordinates of Q must be normalized (= affine), * but those of P don't need to. R is not normalized. * * This function is used only as a subrutine of * ecp_mul_comb(). * * Special cases: (1) P or Q is zero, (2) R is zero, * (3) P == Q. * None of these cases can happen as intermediate step in * ecp_mul_comb(): * - at each step, P, Q and R are multiples of the base * point, the factor being less than its order, so none of * them is zero; * - Q is an odd multiple of the base point, P an even * multiple, due to the choice of precomputed points in the * modified comb method. * So branches for these cases do not leak secret information. * * We accept Q->Z being unset (saving memory in tables) as * meaning 1. * * Cost in field operations if done by [5] 3.22: * 1A := 8M + 3S * * \param grp Pointer to the group representing the curve. * * \param R Pointer to a point structure to hold the result. * * \param P Pointer to the first summand, given with Jacobian * coordinates * * \param Q Pointer to the second summand, given with affine * coordinates. * * \return 0 if successful. */ int mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q); #endif /** * \brief Point doubling R = 2 P, Jacobian coordinates. * * Cost: 1D := 3M + 4S (A == 0) * 4M + 4S (A == -3) * 3M + 6S + 1a otherwise * when the implementation is based on the "dbl-1998-cmo-2" * doubling formulas in [8] and standard optimizations are * applied when curve parameter A is one of { 0, -3 }. * * \param grp Pointer to the group representing the curve. * * \param R Pointer to a point structure to hold the result. * * \param P Pointer to the point that has to be doubled, given with * Jacobian coordinates. * * \return 0 if successful. */ #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) int mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point *P); #endif /** * \brief Normalize jacobian coordinates of an array of (pointers to) * points. * * Using Montgomery's trick to perform only one inversion mod P * the cost is: * 1N(t) := 1I + (6t - 3)M + 1S * (See for example Algorithm 10.3.4. in [9]) * * This function is used only as a subrutine of * ecp_mul_comb(). * * Warning: fails (returning an error) if one of the points is * zero! * This should never happen, see choice of w in ecp_mul_comb(). * * \param grp Pointer to the group representing the curve. * * \param T Array of pointers to the points to normalise. * * \param t_len Number of elements in the array. * * \return 0 if successful, * an error if one of the points is zero. */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) int mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp, mbedtls_ecp_point *T[], size_t t_len); #endif /** * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. * * Cost in field operations if done by [5] 3.2.1: * 1N := 1I + 3M + 1S * * \param grp Pointer to the group representing the curve. * * \param pt pointer to the point to be normalised. This is an * input/output parameter. * * \return 0 if successful. */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) int mbedtls_internal_ecp_normalize_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt); #endif #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) int mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, const mbedtls_mpi *d); #endif /** * \brief Randomize projective x/z coordinates: * (X, Z) -> (l X, l Z) for random l * * \param grp pointer to the group representing the curve * * \param P the point on the curve to be randomised given with * projective coordinates. This is an input/output parameter. * * \param f_rng a function pointer to the random number generator * * \param p_rng a pointer to the random number generator state * * \return 0 if successful */ #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) int mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /** * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. * * \param grp pointer to the group representing the curve * * \param P pointer to the point to be normalised. This is an * input/output parameter. * * \return 0 if successful */ #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) int mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp, mbedtls_ecp_point *P); #endif #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #endif /* ecp_internal_alt.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ecp_invasive.h000066400000000000000000000325221464416617300241640ustar00rootroot00000000000000/** * \file ecp_invasive.h * * \brief ECP module: interfaces for invasive testing only. * * The interfaces in this file are intended for testing purposes only. * They SHOULD NOT be made available in library integrations except when * building the library for testing. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ECP_INVASIVE_H #define MBEDTLS_ECP_INVASIVE_H #include "common.h" #include "mbedtls/bignum.h" #include "bignum_mod.h" #include "mbedtls/ecp.h" /* * Curve modulus types */ typedef enum { MBEDTLS_ECP_MOD_NONE = 0, MBEDTLS_ECP_MOD_COORDINATE, MBEDTLS_ECP_MOD_SCALAR } mbedtls_ecp_modulus_type; typedef enum { MBEDTLS_ECP_VARIANT_NONE = 0, MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT, MBEDTLS_ECP_VARIANT_WITH_MPI_UINT } mbedtls_ecp_variant; #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_LIGHT) /** Queries the ecp variant. * * \return The id of the ecp variant. */ MBEDTLS_STATIC_TESTABLE mbedtls_ecp_variant mbedtls_ecp_get_variant(void); #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) /** Generate a private key on a Montgomery curve (Curve25519 or Curve448). * * This function implements key generation for the set of secret keys * specified in [Curve25519] p. 5 and in [Curve448]. The resulting value * has the lower bits masked but is not necessarily canonical. * * \note - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf * - [RFC7748] https://tools.ietf.org/html/rfc7748 * * \p high_bit The position of the high-order bit of the key to generate. * This is the bit-size of the key minus 1: * 254 for Curve25519 or 447 for Curve448. * \param d The randomly generated key. This is a number of size * exactly \p high_bit + 1 bits, with the least significant bits * masked as specified in [Curve25519] and in [RFC7748] §5. * \param f_rng The RNG function. * \param p_rng The RNG context to be passed to \p f_rng. * * \return \c 0 on success. * \return \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure. */ int mbedtls_ecp_gen_privkey_mx(size_t high_bit, mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) /** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) * * This operation expects a 384 bit MPI and the result of the reduction * is a 192 bit MPI. * * \param[in,out] Np The address of the MPI to be converted. * Must have twice as many limbs as the modulus. * Upon return this holds the reduced value. The bitlength * of the reduced value is the same as that of the modulus * (192 bits). * \param[in] Nn The length of \p Np in limbs. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn); #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) /** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 448-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (224 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the * limb size that sores a 448-bit MPI. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) /** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 512-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (256 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the * limb size that sores a 512-bit MPI. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) /** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5) * * \param[in,out] X The address of the MPI to be converted. * Must have twice as many limbs as the modulus * (the modulus is 521 bits long). Upon return this * holds the reduced value. The reduced value is * in range `0 <= X < 2 * N` (where N is the modulus). * and its the bitlength is one plus the bitlength * of the modulus. * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs does not have * twice as many limbs as the modulus. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) /** Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 768-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (384 bits). * \param[in] X_limbs The length of \p N in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p N_n does not have * twice as many limbs as the modulus. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) /** Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 384-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (192 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) /** Fast quasi-reduction modulo p224k1 = 2^224 - R, * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 448-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (224 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) /** Fast quasi-reduction modulo p256k1 = 2^256 - R, * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 512-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * The bitlength of the reduced value is the same as * that of the modulus (256 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) /** Fast quasi-reduction modulo p255 = 2^255 - 19 * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 510-bit MPI * (double the bitlength of the modulus). * Upon return holds the reduced value which is * in range `0 <= X < 2 * N` (where N is the modulus). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) /** Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 + * (B0 + B1) * 2^224. * * \param[in,out] X The address of the MPI to be converted. * Must have exact limb size that stores a 896-bit MPI * (double the bitlength of the modulus). Upon return * holds the reduced value which is in range `0 <= X < * N` (where N is the modulus). The bitlength of the * reduced value is the same as that of the modulus * (448 bits). * \param[in] X_limbs The length of \p X in limbs. * * \return \c 0 on Success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have * twice as many limbs as the modulus. * \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation * failed. */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs); #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ /** Initialise a modulus with hard-coded const curve data. * * \note The caller is responsible for the \p N modulus' memory. * mbedtls_mpi_mod_modulus_free(&N) should be invoked at the * end of its lifecycle. * * \param[in,out] N The address of the modulus structure to populate. * Must be initialized. * \param[in] id The mbedtls_ecp_group_id for which to initialise the modulus. * \param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P) * or a scalar modulus (N). * * \return \c 0 if successful. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not * have the correct number of limbs. * */ MBEDTLS_STATIC_TESTABLE int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N, const mbedtls_ecp_group_id id, const mbedtls_ecp_modulus_type ctype); #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_INVASIVE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/entropy.c000066400000000000000000000432531464416617300232070ustar00rootroot00000000000000/* * Entropy accumulator implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "entropy_poll.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_FS_IO) #include #endif #include "mbedtls/platform.h" #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ void mbedtls_entropy_init(mbedtls_entropy_context *ctx) { ctx->source_count = 0; memset(ctx->source, 0, sizeof(ctx->source)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif ctx->accumulator_started = 0; mbedtls_md_init(&ctx->accumulator); /* Reminder: Update ENTROPY_HAVE_STRONG in the test files * when adding more strong entropy sources here. */ #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL, MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL, MBEDTLS_ENTROPY_MIN_HARDWARE, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG); ctx->initial_entropy_run = 0; #endif #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ } void mbedtls_entropy_free(mbedtls_entropy_context *ctx) { /* If the context was already free, don't call free() again. * This is important for mutexes which don't allow double-free. */ if (ctx->accumulator_started == -1) { return; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif mbedtls_md_free(&ctx->accumulator); #if defined(MBEDTLS_ENTROPY_NV_SEED) ctx->initial_entropy_run = 0; #endif ctx->source_count = 0; mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source)); ctx->accumulator_started = -1; } int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, mbedtls_entropy_f_source_ptr f_source, void *p_source, size_t threshold, int strong) { int idx, ret = 0; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif idx = ctx->source_count; if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) { ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; goto exit; } ctx->source[idx].f_source = f_source; ctx->source[idx].p_source = p_source; ctx->source[idx].threshold = threshold; ctx->source[idx].strong = strong; ctx->source_count++; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Entropy accumulator update */ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id, const unsigned char *data, size_t len) { unsigned char header[2]; unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = len; const unsigned char *p = data; int ret = 0; if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) { if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), data, len, tmp)) != 0) { goto cleanup; } p = tmp; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; } header[0] = source_id; header[1] = use_len & 0xFF; /* * Start the accumulator if this has not already happened. Note that * it is sufficient to start the accumulator here only because all calls to * gather entropy eventually execute this code. */ if (ctx->accumulator_started == 0) { ret = mbedtls_md_setup(&ctx->accumulator, mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0); if (ret != 0) { goto cleanup; } ret = mbedtls_md_starts(&ctx->accumulator); if (ret != 0) { goto cleanup; } ctx->accumulator_started = 1; } if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) { goto cleanup; } ret = mbedtls_md_update(&ctx->accumulator, p, use_len); cleanup: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, const unsigned char *data, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Run through the different sources to add entropy to our accumulator */ static int entropy_gather_internal(mbedtls_entropy_context *ctx) { int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; int i; int have_one_strong = 0; unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; size_t olen; if (ctx->source_count == 0) { return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED; } /* * Run through our entropy sources */ for (i = 0; i < ctx->source_count; i++) { if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) { have_one_strong = 1; } olen = 0; if ((ret = ctx->source[i].f_source(ctx->source[i].p_source, buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) { goto cleanup; } /* * Add if we actually gathered something */ if (olen > 0) { if ((ret = entropy_update(ctx, (unsigned char) i, buf, olen)) != 0) { return ret; } ctx->source[i].size += olen; } } if (have_one_strong == 0) { ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; } cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } /* * Thread-safe wrapper for entropy_gather_internal() */ int mbedtls_entropy_gather(mbedtls_entropy_context *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = entropy_gather_internal(ctx); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } int mbedtls_entropy_func(void *data, unsigned char *output, size_t len) { int ret, count = 0, i, thresholds_reached; size_t strong_size; mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } #if defined(MBEDTLS_ENTROPY_NV_SEED) /* Update the NV entropy seed before generating any entropy for outside * use. */ if (ctx->initial_entropy_run == 0) { ctx->initial_entropy_run = 1; if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) { return ret; } } #endif #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif /* * Always gather extra entropy before a call */ do { if (count++ > ENTROPY_MAX_LOOP) { ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if ((ret = entropy_gather_internal(ctx)) != 0) { goto exit; } thresholds_reached = 1; strong_size = 0; for (i = 0; i < ctx->source_count; i++) { if (ctx->source[i].size < ctx->source[i].threshold) { thresholds_reached = 0; } if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) { strong_size += ctx->source[i].size; } } } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE); memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); /* * Note that at this stage it is assumed that the accumulator was started * in a previous call to entropy_update(). If this is not guaranteed, the * code below will fail. */ if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) { goto exit; } /* * Reset accumulator and counters and recycle existing entropy */ mbedtls_md_free(&ctx->accumulator); mbedtls_md_init(&ctx->accumulator); ret = mbedtls_md_setup(&ctx->accumulator, mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_starts(&ctx->accumulator); if (ret != 0) { goto exit; } if ((ret = mbedtls_md_update(&ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { goto exit; } /* * Perform second hashing on entropy */ if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) { goto exit; } for (i = 0; i < ctx->source_count; i++) { ctx->source[i].size = 0; } memcpy(output, buf, len); ret = 0; exit: mbedtls_platform_zeroize(buf, sizeof(buf)); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } #if defined(MBEDTLS_ENTROPY_NV_SEED) int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx) { int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; /* Read new seed and write it to NV */ if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { return ret; } if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) { return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } /* Manually update the remaining stream with a separator value to diverge */ memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE); return ret; } #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_FS_IO) int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; FILE *f = NULL; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) { ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; goto exit; } if ((f = fopen(path, "wb")) == NULL) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; goto exit; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; goto exit; } ret = 0; exit: mbedtls_platform_zeroize(buf, sizeof(buf)); if (f != NULL) { fclose(f); } return ret; } int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path) { int ret = 0; FILE *f; size_t n; unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE]; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); fseek(f, 0, SEEK_END); n = (size_t) ftell(f); fseek(f, 0, SEEK_SET); if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) { n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; } if (fread(buf, 1, n, f) != n) { ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; } else { ret = mbedtls_entropy_update_manual(ctx, buf, n); } fclose(f); mbedtls_platform_zeroize(buf, sizeof(buf)); if (ret != 0) { return ret; } return mbedtls_entropy_write_seed_file(ctx, path); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) /* * Dummy source function */ static int entropy_dummy_source(void *data, unsigned char *output, size_t len, size_t *olen) { ((void) data); memset(output, 0x2a, len); *olen = len; return 0; } #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len) { int ret = 0; size_t entropy_len = 0; size_t olen = 0; size_t attempts = buf_len; while (attempts > 0 && entropy_len < buf_len) { if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len, buf_len - entropy_len, &olen)) != 0) { return ret; } entropy_len += olen; attempts--; } if (entropy_len < buf_len) { ret = 1; } return ret; } static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf, size_t buf_len) { unsigned char set = 0xFF; unsigned char unset = 0x00; size_t i; for (i = 0; i < buf_len; i++) { set &= buf[i]; unset |= buf[i]; } return set == 0xFF || unset == 0x00; } /* * A test to ensure that the entropy sources are functioning correctly * and there is no obvious failure. The test performs the following checks: * - The entropy source is not providing only 0s (all bits unset) or 1s (all * bits set). * - The entropy source is not providing values in a pattern. Because the * hardware could be providing data in an arbitrary length, this check polls * the hardware entropy source twice and compares the result to ensure they * are not equal. * - The error code returned by the entropy source is not an error. */ int mbedtls_entropy_source_self_test(int verbose) { int ret = 0; unsigned char buf0[2 * sizeof(unsigned long long int)]; unsigned char buf1[2 * sizeof(unsigned long long int)]; if (verbose != 0) { mbedtls_printf(" ENTROPY_BIAS test: "); } memset(buf0, 0x00, sizeof(buf0)); memset(buf1, 0x00, sizeof(buf1)); if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) { goto cleanup; } if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) { goto cleanup; } /* Make sure that the returned values are not all 0 or 1 */ if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) { goto cleanup; } if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) { goto cleanup; } /* Make sure that the entropy source is not returning values in a * pattern */ ret = memcmp(buf0, buf1, sizeof(buf0)) == 0; cleanup: if (verbose != 0) { if (ret != 0) { mbedtls_printf("failed\n"); } else { mbedtls_printf("passed\n"); } mbedtls_printf("\n"); } return ret != 0; } #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ /* * The actual entropy quality is hard to test, but we can at least * test that the functions don't cause errors and write the correct * amount of data to buffers. */ int mbedtls_entropy_self_test(int verbose) { int ret = 1; mbedtls_entropy_context ctx; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; size_t i, j; if (verbose != 0) { mbedtls_printf(" ENTROPY test: "); } mbedtls_entropy_init(&ctx); /* First do a gather to make sure we have default sources */ if ((ret = mbedtls_entropy_gather(&ctx)) != 0) { goto cleanup; } ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16, MBEDTLS_ENTROPY_SOURCE_WEAK); if (ret != 0) { goto cleanup; } if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) { goto cleanup; } /* * To test that mbedtls_entropy_func writes correct number of bytes: * - use the whole buffer and rely on ASan to detect overruns * - collect entropy 8 times and OR the result in an accumulator: * any byte should then be 0 with probably 2^(-64), so requiring * each of the 32 or 64 bytes to be non-zero has a false failure rate * of at most 2^(-58) which is acceptable. */ for (i = 0; i < 8; i++) { if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) { goto cleanup; } for (j = 0; j < sizeof(buf); j++) { acc[j] |= buf[j]; } } for (j = 0; j < sizeof(buf); j++) { if (acc[j] == 0) { ret = 1; goto cleanup; } } #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) if ((ret = mbedtls_entropy_source_self_test(0)) != 0) { goto cleanup; } #endif cleanup: mbedtls_entropy_free(&ctx); if (verbose != 0) { if (ret != 0) { mbedtls_printf("failed\n"); } else { mbedtls_printf("passed\n"); } mbedtls_printf("\n"); } return ret != 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_ENTROPY_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/entropy_poll.c000066400000000000000000000140731464416617300242330ustar00rootroot00000000000000/* * Platform-specific and custom entropy polling functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE) /* Ensure that syscall() is available even when compiling with -std=c99 */ #define _GNU_SOURCE #endif #include "common.h" #include #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #include "entropy_poll.h" #include "mbedtls/error.h" #if defined(MBEDTLS_TIMING_C) #include "mbedtls/timing.h" #endif #include "mbedtls/platform.h" #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) && !defined(__MVS__) #error \ "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h" #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #include #include int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { ((void) data); *olen = 0; /* * BCryptGenRandom takes ULONG for size, which is smaller than size_t on * 64-bit Windows platforms. Extract entropy in chunks of len (dependent * on ULONG_MAX) size. */ while (len != 0) { unsigned long ulong_bytes = (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len; if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } *olen += ulong_bytes; len -= ulong_bytes; } return 0; } #else /* _WIN32 && !EFIX64 && !EFI32 */ /* * Test for Linux getrandom() support. * Since there is no wrapper in the libc yet, use the generic syscall wrapper * available in GNU libc and compatible libc's (eg uClibc). */ #if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__)) #include #include #if defined(SYS_getrandom) #define HAVE_GETRANDOM #include static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) { /* MemSan cannot understand that the syscall writes to the buffer */ #if defined(__has_feature) #if __has_feature(memory_sanitizer) memset(buf, 0, buflen); #endif #endif return (int) syscall(SYS_getrandom, buf, buflen, flags); } #endif /* SYS_getrandom */ #endif /* __linux__ || __midipix__ */ #if defined(__FreeBSD__) || defined(__DragonFly__) #include #if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \ (defined(__DragonFly__) && __DragonFly_version >= 500700) #include #include #define HAVE_GETRANDOM static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) { return (int) getrandom(buf, buflen, flags); } #endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) || (__DragonFly__ && __DragonFly_version >= 500700) */ #endif /* __FreeBSD__ || __DragonFly__ */ /* * Some BSD systems provide KERN_ARND. * This is equivalent to reading from /dev/urandom, only it doesn't require an * open file descriptor, and provides up to 256 bytes per call (basically the * same as getentropy(), but with a longer history). * * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 */ #if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) #include #include #if defined(KERN_ARND) #define HAVE_SYSCTL_ARND static int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen) { int name[2]; size_t len; name[0] = CTL_KERN; name[1] = KERN_ARND; while (buflen > 0) { len = buflen > 256 ? 256 : buflen; if (sysctl(name, 2, buf, &len, NULL, 0) == -1) { return -1; } buflen -= len; buf += len; } return 0; } #endif /* KERN_ARND */ #endif /* __FreeBSD__ || __NetBSD__ */ #include int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen) { FILE *file; size_t read_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) data); #if defined(HAVE_GETRANDOM) ret = getrandom_wrapper(output, len, 0); if (ret >= 0) { *olen = (size_t) ret; return 0; } else if (errno != ENOSYS) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } /* Fall through if the system call isn't known. */ #else ((void) ret); #endif /* HAVE_GETRANDOM */ #if defined(HAVE_SYSCTL_ARND) ((void) file); ((void) read_len); if (sysctl_arnd_wrapper(output, len) == -1) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } *olen = len; return 0; #else *olen = 0; file = fopen("/dev/urandom", "rb"); if (file == NULL) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(file, NULL); read_len = fread(output, 1, len, file); if (read_len != len) { fclose(file); return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } fclose(file); *olen = len; return 0; #endif /* HAVE_SYSCTL_ARND */ } #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ #if defined(MBEDTLS_ENTROPY_NV_SEED) int mbedtls_nv_seed_poll(void *data, unsigned char *output, size_t len, size_t *olen) { unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; ((void) data); memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } if (len < use_len) { use_len = len; } memcpy(output, buf, use_len); *olen = use_len; return 0; } #endif /* MBEDTLS_ENTROPY_NV_SEED */ #endif /* MBEDTLS_ENTROPY_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/entropy_poll.h000066400000000000000000000032411464416617300242330ustar00rootroot00000000000000/** * \file entropy_poll.h * * \brief Platform-specific and custom entropy polling functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_ENTROPY_POLL_H #define MBEDTLS_ENTROPY_POLL_H #include "mbedtls/build_info.h" #include #ifdef __cplusplus extern "C" { #endif /* * Default thresholds for built-in sources, in bytes */ #define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ #if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) #define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ #endif #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback */ int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) /** * \brief Entropy poll callback for a hardware source * * \warning This is not provided by Mbed TLS! * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h. * * \note This must accept NULL as its first argument. */ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif #if defined(MBEDTLS_ENTROPY_NV_SEED) /** * \brief Entropy poll callback for a non-volatile seed file * * \note This must accept NULL as its first argument. */ int mbedtls_nv_seed_poll(void *data, unsigned char *output, size_t len, size_t *olen); #endif #ifdef __cplusplus } #endif #endif /* entropy_poll.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/error.c000066400000000000000000001105721464416617300226370ustar00rootroot00000000000000/* * Error message information * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/error.h" #if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) #if defined(MBEDTLS_ERROR_C) #include "mbedtls/platform.h" #include #include #if defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #endif #if defined(MBEDTLS_ARIA_C) #include "mbedtls/aria.h" #endif #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #endif #if defined(MBEDTLS_BASE64_C) #include "mbedtls/base64.h" #endif #if defined(MBEDTLS_BIGNUM_C) #include "mbedtls/bignum.h" #endif #if defined(MBEDTLS_CAMELLIA_C) #include "mbedtls/camellia.h" #endif #if defined(MBEDTLS_CCM_C) #include "mbedtls/ccm.h" #endif #if defined(MBEDTLS_CHACHA20_C) #include "mbedtls/chacha20.h" #endif #if defined(MBEDTLS_CHACHAPOLY_C) #include "mbedtls/chachapoly.h" #endif #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #endif #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif #if defined(MBEDTLS_DHM_C) #include "mbedtls/dhm.h" #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ENTROPY_C) #include "mbedtls/entropy.h" #endif #if defined(MBEDTLS_ERROR_C) #include "mbedtls/error.h" #endif #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #endif #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #endif #if defined(MBEDTLS_HKDF_C) #include "mbedtls/hkdf.h" #endif #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #endif #if defined(MBEDTLS_LMS_C) #include "mbedtls/lms.h" #endif #if defined(MBEDTLS_MD_C) #include "mbedtls/md.h" #endif #if defined(MBEDTLS_NET_C) #include "mbedtls/net_sockets.h" #endif #if defined(MBEDTLS_OID_C) #include "mbedtls/oid.h" #endif #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_PK_C) #include "mbedtls/pk.h" #endif #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #endif #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #endif #if defined(MBEDTLS_PKCS7_C) #include "mbedtls/pkcs7.h" #endif #if defined(MBEDTLS_POLY1305_C) #include "mbedtls/poly1305.h" #endif #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif #if defined(MBEDTLS_SHA1_C) #include "mbedtls/sha1.h" #endif #if defined(MBEDTLS_SHA256_C) #include "mbedtls/sha256.h" #endif #if defined(MBEDTLS_SHA3_C) #include "mbedtls/sha3.h" #endif #if defined(MBEDTLS_SHA512_C) #include "mbedtls/sha512.h" #endif #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/ssl.h" #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) #include "mbedtls/x509.h" #endif const char *mbedtls_high_level_strerr(int error_code) { int high_level_error_code; if (error_code < 0) { error_code = -error_code; } /* Extract the high-level part from the error code. */ high_level_error_code = error_code & 0xFF80; switch (high_level_error_code) { /* Begin Auto-Generated Code. */ #if defined(MBEDTLS_CIPHER_C) case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE): return( "CIPHER - The selected feature is not available" ); case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA): return( "CIPHER - Bad input parameters" ); case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED): return( "CIPHER - Failed to allocate memory" ); case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING): return( "CIPHER - Input data contains invalid padding and is rejected" ); case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED): return( "CIPHER - Decryption of block requires a full block" ); case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED): return( "CIPHER - Authentication failed (for AEAD modes)" ); case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): return( "CIPHER - The context is invalid. For example, because it was freed" ); #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_DHM_C) case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA): return( "DHM - Bad input parameters" ); case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED): return( "DHM - Reading of the DHM parameters failed" ); case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED): return( "DHM - Making of the DHM parameters failed" ); case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED): return( "DHM - Reading of the public values failed" ); case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED): return( "DHM - Making of the public value failed" ); case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED): return( "DHM - Calculation of the DHM secret failed" ); case -(MBEDTLS_ERR_DHM_INVALID_FORMAT): return( "DHM - The ASN.1 data is not formatted correctly" ); case -(MBEDTLS_ERR_DHM_ALLOC_FAILED): return( "DHM - Allocation of memory failed" ); case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): return( "DHM - Read or write of file failed" ); case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): return( "DHM - Setting the modulus and generator failed" ); #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_ECP_C) case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA): return( "ECP - Bad input parameters to function" ); case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL): return( "ECP - The buffer is too small to write to" ); case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE): return( "ECP - The requested feature is not available, for example, the requested curve is not supported" ); case -(MBEDTLS_ERR_ECP_VERIFY_FAILED): return( "ECP - The signature is not valid" ); case -(MBEDTLS_ERR_ECP_ALLOC_FAILED): return( "ECP - Memory allocation failed" ); case -(MBEDTLS_ERR_ECP_RANDOM_FAILED): return( "ECP - Generation of random value, such as ephemeral key, failed" ); case -(MBEDTLS_ERR_ECP_INVALID_KEY): return( "ECP - Invalid private or public key" ); case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): return( "ECP - The buffer contains a valid signature followed by more data" ); case -(MBEDTLS_ERR_ECP_IN_PROGRESS): return( "ECP - Operation in progress, call again with the same parameters to continue" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE): return( "MD - The selected feature is not available" ); case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA): return( "MD - Bad input parameters to function" ); case -(MBEDTLS_ERR_MD_ALLOC_FAILED): return( "MD - Failed to allocate memory" ); case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): return( "MD - Opening or reading of file failed" ); #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT): return( "PEM - No PEM header or footer found" ); case -(MBEDTLS_ERR_PEM_INVALID_DATA): return( "PEM - PEM string is not as expected" ); case -(MBEDTLS_ERR_PEM_ALLOC_FAILED): return( "PEM - Failed to allocate memory" ); case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV): return( "PEM - RSA IV is not in hex-format" ); case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG): return( "PEM - Unsupported key encryption algorithm" ); case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED): return( "PEM - Private key password can't be empty" ); case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH): return( "PEM - Given private key password does not allow for correct decryption" ); case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE): return( "PEM - Unavailable feature, e.g. hashing/encryption combination" ); case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA): return( "PEM - Bad input parameters to function" ); #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_PK_C) case -(MBEDTLS_ERR_PK_ALLOC_FAILED): return( "PK - Memory allocation failed" ); case -(MBEDTLS_ERR_PK_TYPE_MISMATCH): return( "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA): return( "PK - Bad input parameters to function" ); case -(MBEDTLS_ERR_PK_FILE_IO_ERROR): return( "PK - Read/write of file failed" ); case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION): return( "PK - Unsupported key version" ); case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT): return( "PK - Invalid key tag or value" ); case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG): return( "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED): return( "PK - Private key password can't be empty" ); case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH): return( "PK - Given private key password does not allow for correct decryption" ); case -(MBEDTLS_ERR_PK_INVALID_PUBKEY): return( "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); case -(MBEDTLS_ERR_PK_INVALID_ALG): return( "PK - The algorithm tag or value is invalid" ); case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE): return( "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE): return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): return( "PK - The buffer contains a valid signature followed by more data" ); case -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL): return( "PK - The output buffer is too small" ); #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PKCS12_C) case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA): return( "PKCS12 - Bad input parameters to function" ); case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE): return( "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT): return( "PKCS12 - PBE ASN.1 data not as expected" ); case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH): return( "PKCS12 - Given private key password does not allow for correct decryption" ); #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PKCS5_C) case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA): return( "PKCS5 - Bad input parameters to function" ); case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT): return( "PKCS5 - Unexpected ASN.1 data" ); case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE): return( "PKCS5 - Requested encryption or digest alg not available" ); case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH): return( "PKCS5 - Given private key password does not allow for correct decryption" ); #endif /* MBEDTLS_PKCS5_C */ #if defined(MBEDTLS_PKCS7_C) case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT): return( "PKCS7 - The format is invalid, e.g. different type expected" ); case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE): return( "PKCS7 - Unavailable feature, e.g. anything other than signed data" ); case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION): return( "PKCS7 - The PKCS #7 version element is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO): return( "PKCS7 - The PKCS #7 content info is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_ALG): return( "PKCS7 - The algorithm tag or value is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_CERT): return( "PKCS7 - The certificate tag or value is invalid or cannot be parsed" ); case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE): return( "PKCS7 - Error parsing the signature" ); case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO): return( "PKCS7 - Error parsing the signer's info" ); case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA): return( "PKCS7 - Input invalid" ); case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED): return( "PKCS7 - Allocation of memory failed" ); case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL): return( "PKCS7 - Verification Failed" ); case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID): return( "PKCS7 - The PKCS #7 date issued/expired dates are invalid" ); #endif /* MBEDTLS_PKCS7_C */ #if defined(MBEDTLS_RSA_C) case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): return( "RSA - Bad input parameters to function" ); case -(MBEDTLS_ERR_RSA_INVALID_PADDING): return( "RSA - Input data contains invalid padding and is rejected" ); case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED): return( "RSA - Something failed during generation of a key" ); case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED): return( "RSA - Key failed to pass the validity check of the library" ); case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED): return( "RSA - The public key operation failed" ); case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED): return( "RSA - The private key operation failed" ); case -(MBEDTLS_ERR_RSA_VERIFY_FAILED): return( "RSA - The PKCS#1 verification failed" ); case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE): return( "RSA - The output buffer for decryption is not large enough" ); case -(MBEDTLS_ERR_RSA_RNG_FAILED): return( "RSA - The random generator failed to generate non-zeros" ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SSL_TLS_C) case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): return( "SSL - A cryptographic operation is in progress. Try again later" ); case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): return( "SSL - The requested feature is not available" ); case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): return( "SSL - Bad input parameters to function" ); case -(MBEDTLS_ERR_SSL_INVALID_MAC): return( "SSL - Verification of the message MAC failed" ); case -(MBEDTLS_ERR_SSL_INVALID_RECORD): return( "SSL - An invalid SSL record was received" ); case -(MBEDTLS_ERR_SSL_CONN_EOF): return( "SSL - The connection indicated an EOF" ); case -(MBEDTLS_ERR_SSL_DECODE_ERROR): return( "SSL - A message could not be parsed due to a syntactic error" ); case -(MBEDTLS_ERR_SSL_NO_RNG): return( "SSL - No RNG was provided to the SSL module" ); case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): return( "SSL - No client certification received from the client, but required by the authentication mode" ); case -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION): return( "SSL - Client received an extended server hello containing an unsupported extension" ); case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL): return( "SSL - No ALPN protocols supported that the client advertises" ); case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): return( "SSL - The own private key or pre-shared key is not set, but needed" ); case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): return( "SSL - No CA Chain is set, but required to operate" ); case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE): return( "SSL - An unexpected message was received from our peer" ); case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): return( "SSL - A fatal alert message was received from our peer" ); case -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME): return( "SSL - No server could be identified matching the client's SNI" ); case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): return( "SSL - The peer notified us that the connection is going to be closed" ); case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE): return( "SSL - Processing of the Certificate handshake message failed" ); case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET): return( "SSL - * Received NewSessionTicket Post Handshake Message. This error code is experimental and may be changed or removed without notice" ); case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA): return( "SSL - Not possible to read early data" ); case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA): return( "SSL - * Early data has been received as part of an on-going handshake. This error code can be returned only on server side if and only if early data has been enabled by means of the mbedtls_ssl_conf_early_data() API. This error code can then be returned by mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if early data has been received as part of the handshake sequence they triggered. To read the early data, call mbedtls_ssl_read_early_data()" ); case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA): return( "SSL - Not possible to write early data" ); case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND): return( "SSL - Cache entry not found" ); case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): return( "SSL - Memory allocation failed" ); case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): return( "SSL - Hardware acceleration function returned with error" ); case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): return( "SSL - Hardware acceleration function skipped / left alone data" ); case -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION): return( "SSL - Handshake protocol not within min/max boundaries" ); case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE): return( "SSL - The handshake negotiation failed" ); case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): return( "SSL - Session ticket has expired" ); case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): return( "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY): return( "SSL - Unknown identity received (eg, PSK identity)" ); case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR): return( "SSL - Internal error (eg, unexpected failure in lower-level module)" ); case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING): return( "SSL - A counter would wrap (eg, too many messages exchanged)" ); case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO): return( "SSL - Unexpected message at ServerHello in renegotiation" ); case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED): return( "SSL - DTLS client must retry for hello verification" ); case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): return( "SSL - A buffer is too small to receive or write a message" ); case -(MBEDTLS_ERR_SSL_WANT_READ): return( "SSL - No data of requested type currently available on underlying transport" ); case -(MBEDTLS_ERR_SSL_WANT_WRITE): return( "SSL - Connection requires a write call" ); case -(MBEDTLS_ERR_SSL_TIMEOUT): return( "SSL - The operation timed out" ); case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT): return( "SSL - The client initiated a reconnect from the same port" ); case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD): return( "SSL - Record header looks valid but is not expected" ); case -(MBEDTLS_ERR_SSL_NON_FATAL): return( "SSL - The alert message received indicates a non-fatal error" ); case -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER): return( "SSL - A field in a message was incorrect or inconsistent with other fields" ); case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): return( "SSL - Internal-only message signaling that further message-processing should be done" ); case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): return( "SSL - The asynchronous operation is not completed yet" ); case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE): return( "SSL - Internal-only message signaling that a message arrived early" ); case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID): return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): return( "SSL - An operation failed due to an unexpected version or configuration" ); case -(MBEDTLS_ERR_SSL_BAD_CONFIG): return( "SSL - Invalid value in SSL config" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE): return( "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); case -(MBEDTLS_ERR_X509_UNKNOWN_OID): return( "X509 - Requested OID is unknown" ); case -(MBEDTLS_ERR_X509_INVALID_FORMAT): return( "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); case -(MBEDTLS_ERR_X509_INVALID_VERSION): return( "X509 - The CRT/CRL/CSR version element is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_SERIAL): return( "X509 - The serial tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_ALG): return( "X509 - The algorithm tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_NAME): return( "X509 - The name tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_DATE): return( "X509 - The date tag or value is invalid" ); case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE): return( "X509 - The signature tag or value invalid" ); case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS): return( "X509 - The extension tag or value is invalid" ); case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION): return( "X509 - CRT/CRL/CSR has an unsupported version number" ); case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG): return( "X509 - Signature algorithm (oid) is unsupported" ); case -(MBEDTLS_ERR_X509_SIG_MISMATCH): return( "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED): return( "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT): return( "X509 - Format not recognized as DER or PEM" ); case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA): return( "X509 - Input invalid" ); case -(MBEDTLS_ERR_X509_ALLOC_FAILED): return( "X509 - Allocation of memory failed" ); case -(MBEDTLS_ERR_X509_FILE_IO_ERROR): return( "X509 - Read/write of file failed" ); case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL): return( "X509 - Destination buffer is too small" ); case -(MBEDTLS_ERR_X509_FATAL_ERROR): return( "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); #endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ /* End Auto-Generated Code. */ default: break; } return NULL; } const char *mbedtls_low_level_strerr(int error_code) { int low_level_error_code; if (error_code < 0) { error_code = -error_code; } /* Extract the low-level part from the error code. */ low_level_error_code = error_code & ~0xFF80; switch (low_level_error_code) { /* Begin Auto-Generated Code. */ #if defined(MBEDTLS_AES_C) case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH): return( "AES - Invalid key length" ); case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH): return( "AES - Invalid data input length" ); case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): return( "AES - Invalid input data" ); #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_ARIA_C) case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): return( "ARIA - Bad input data" ); case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): return( "ARIA - Invalid data input length" ); #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_ASN1_PARSE_C) case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA): return( "ASN1 - Out of data when parsing an ASN1 data structure" ); case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG): return( "ASN1 - ASN1 tag was of an unexpected value" ); case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH): return( "ASN1 - Error when trying to determine the length or invalid length" ); case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH): return( "ASN1 - Actual length differs from expected length" ); case -(MBEDTLS_ERR_ASN1_INVALID_DATA): return( "ASN1 - Data is invalid" ); case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED): return( "ASN1 - Memory allocation failed" ); case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL): return( "ASN1 - Buffer too small when writing ASN.1 data structure" ); #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_BASE64_C) case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL): return( "BASE64 - Output buffer too small" ); case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER): return( "BASE64 - Invalid character in input" ); #endif /* MBEDTLS_BASE64_C */ #if defined(MBEDTLS_BIGNUM_C) case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR): return( "BIGNUM - An error occurred while reading from or writing to a file" ); case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA): return( "BIGNUM - Bad input parameters to function" ); case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER): return( "BIGNUM - There is an invalid character in the digit string" ); case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL): return( "BIGNUM - The buffer is too small to write to" ); case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE): return( "BIGNUM - The input arguments are negative or result in illegal output" ); case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO): return( "BIGNUM - The input argument for division is zero, which is not allowed" ); case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE): return( "BIGNUM - The input arguments are not acceptable" ); case -(MBEDTLS_ERR_MPI_ALLOC_FAILED): return( "BIGNUM - Memory allocation failed" ); #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_CAMELLIA_C) case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): return( "CAMELLIA - Bad input data" ); case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): return( "CAMELLIA - Invalid data input length" ); #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_CCM_C) case -(MBEDTLS_ERR_CCM_BAD_INPUT): return( "CCM - Bad input parameters to the function" ); case -(MBEDTLS_ERR_CCM_AUTH_FAILED): return( "CCM - Authenticated decryption failed" ); #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHA20_C) case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): return( "CHACHA20 - Invalid input parameter(s)" ); #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE): return( "CHACHAPOLY - The requested operation is not permitted in the current state" ); case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED): return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CTR_DRBG_C) case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): return( "CTR_DRBG - The entropy source failed" ); case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG): return( "CTR_DRBG - The requested random buffer length is too big" ); case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG): return( "CTR_DRBG - The input (entropy + additional data) is too large" ); case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR): return( "CTR_DRBG - Read or write error in file" ); #endif /* MBEDTLS_CTR_DRBG_C */ #if defined(MBEDTLS_DES_C) case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): return( "DES - The data input has an invalid length" ); #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_ENTROPY_C) case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED): return( "ENTROPY - Critical entropy source failure" ); case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES): return( "ENTROPY - No more sources can be added" ); case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED): return( "ENTROPY - No sources have been added to poll" ); case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE): return( "ENTROPY - No strong sources have been added to poll" ); case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR): return( "ENTROPY - Read/write error in file" ); #endif /* MBEDTLS_ENTROPY_C */ #if defined(MBEDTLS_ERROR_C) case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR): return( "ERROR - Generic error" ); case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED): return( "ERROR - This is a bug in the library" ); #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_PLATFORM_C) case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): return( "PLATFORM - Hardware accelerator failed" ); case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): return( "PLATFORM - The requested feature is not supported by the platform" ); #endif /* MBEDTLS_PLATFORM_C */ #if defined(MBEDTLS_GCM_C) case -(MBEDTLS_ERR_GCM_AUTH_FAILED): return( "GCM - Authenticated decryption failed" ); case -(MBEDTLS_ERR_GCM_BAD_INPUT): return( "GCM - Bad input parameters to function" ); case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL): return( "GCM - An output buffer is too small" ); #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_HKDF_C) case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA): return( "HKDF - Bad input parameters to function" ); #endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG): return( "HMAC_DRBG - Too many random requested in single call" ); case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG): return( "HMAC_DRBG - Input too large (Entropy + additional)" ); case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR): return( "HMAC_DRBG - Read/write error in file" ); case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED): return( "HMAC_DRBG - The entropy source failed" ); #endif /* MBEDTLS_HMAC_DRBG_C */ #if defined(MBEDTLS_LMS_C) case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA): return( "LMS - Bad data has been input to an LMS function" ); case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS): return( "LMS - Specified LMS key has utilised all of its private keys" ); case -(MBEDTLS_ERR_LMS_VERIFY_FAILED): return( "LMS - LMS signature verification failed" ); case -(MBEDTLS_ERR_LMS_ALLOC_FAILED): return( "LMS - LMS failed to allocate space for a private key" ); case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL): return( "LMS - Input/output buffer is too small to contain requited data" ); #endif /* MBEDTLS_LMS_C */ #if defined(MBEDTLS_NET_C) case -(MBEDTLS_ERR_NET_SOCKET_FAILED): return( "NET - Failed to open a socket" ); case -(MBEDTLS_ERR_NET_CONNECT_FAILED): return( "NET - The connection to the given server / port failed" ); case -(MBEDTLS_ERR_NET_BIND_FAILED): return( "NET - Binding of the socket failed" ); case -(MBEDTLS_ERR_NET_LISTEN_FAILED): return( "NET - Could not listen on the socket" ); case -(MBEDTLS_ERR_NET_ACCEPT_FAILED): return( "NET - Could not accept the incoming connection" ); case -(MBEDTLS_ERR_NET_RECV_FAILED): return( "NET - Reading information from the socket failed" ); case -(MBEDTLS_ERR_NET_SEND_FAILED): return( "NET - Sending information through the socket failed" ); case -(MBEDTLS_ERR_NET_CONN_RESET): return( "NET - Connection was reset by peer" ); case -(MBEDTLS_ERR_NET_UNKNOWN_HOST): return( "NET - Failed to get an IP address for the given hostname" ); case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL): return( "NET - Buffer is too small to hold the data" ); case -(MBEDTLS_ERR_NET_INVALID_CONTEXT): return( "NET - The context is invalid, eg because it was free()ed" ); case -(MBEDTLS_ERR_NET_POLL_FAILED): return( "NET - Polling the net context failed" ); case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA): return( "NET - Input invalid" ); #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) case -(MBEDTLS_ERR_OID_NOT_FOUND): return( "OID - OID is not found" ); case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL): return( "OID - output buffer is too small" ); #endif /* MBEDTLS_OID_C */ #if defined(MBEDTLS_POLY1305_C) case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): return( "POLY1305 - Invalid input parameter(s)" ); #endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_SHA1_C) case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): return( "SHA1 - SHA-1 input data was malformed" ); #endif /* MBEDTLS_SHA1_C */ #if defined(MBEDTLS_SHA256_C) case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): return( "SHA256 - SHA-256 input data was malformed" ); #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA3_C) case -(MBEDTLS_ERR_SHA3_BAD_INPUT_DATA): return( "SHA3 - SHA-3 input data was malformed" ); #endif /* MBEDTLS_SHA3_C */ #if defined(MBEDTLS_SHA512_C) case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): return( "SHA512 - SHA-512 input data was malformed" ); #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_THREADING_C) case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): return( "THREADING - Bad input parameters to function" ); case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): return( "THREADING - Locking / unlocking / free failed with error code" ); #endif /* MBEDTLS_THREADING_C */ /* End Auto-Generated Code. */ default: break; } return NULL; } void mbedtls_strerror(int ret, char *buf, size_t buflen) { size_t len; int use_ret; const char *high_level_error_description = NULL; const char *low_level_error_description = NULL; if (buflen == 0) { return; } memset(buf, 0x00, buflen); if (ret < 0) { ret = -ret; } if (ret & 0xFF80) { use_ret = ret & 0xFF80; // Translate high level error code. high_level_error_description = mbedtls_high_level_strerr(ret); if (high_level_error_description == NULL) { mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret); } else { mbedtls_snprintf(buf, buflen, "%s", high_level_error_description); } #if defined(MBEDTLS_SSL_TLS_C) // Early return in case of a fatal error - do not try to translate low // level code. if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) { return; } #endif /* MBEDTLS_SSL_TLS_C */ } use_ret = ret & ~0xFF80; if (use_ret == 0) { return; } // If high level code is present, make a concatenation between both // error strings. // len = strlen(buf); if (len > 0) { if (buflen - len < 5) { return; } mbedtls_snprintf(buf + len, buflen - len, " : "); buf += len + 3; buflen -= len + 3; } // Translate low level error code. low_level_error_description = mbedtls_low_level_strerr(ret); if (low_level_error_description == NULL) { mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret); } else { mbedtls_snprintf(buf, buflen, "%s", low_level_error_description); } } #else /* MBEDTLS_ERROR_C */ /* * Provide a dummy implementation when MBEDTLS_ERROR_C is not defined */ void mbedtls_strerror(int ret, char *buf, size_t buflen) { ((void) ret); if (buflen > 0) { buf[0] = '\0'; } } #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_TEST_HOOKS) void (*mbedtls_test_hook_error_add)(int, int, const char *, int); #endif #endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/gcm.c000066400000000000000000001270341464416617300222550ustar00rootroot00000000000000/* * NIST SP800-38D compliant GCM implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf * * See also: * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf * * We use the algorithm described as Shoup's method with 4-bit tables in * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. */ #include "common.h" #if defined(MBEDTLS_GCM_C) #include "mbedtls/gcm.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_BLOCK_CIPHER_C) #include "block_cipher_internal.h" #endif #include #if defined(MBEDTLS_AESNI_C) #include "aesni.h" #endif #if defined(MBEDTLS_AESCE_C) #include "aesce.h" #endif #if !defined(MBEDTLS_GCM_ALT) /* Used to select the acceleration mechanism */ #define MBEDTLS_GCM_ACC_SMALLTABLE 0 #define MBEDTLS_GCM_ACC_LARGETABLE 1 #define MBEDTLS_GCM_ACC_AESNI 2 #define MBEDTLS_GCM_ACC_AESCE 3 /* * Initialize a context */ void mbedtls_gcm_init(mbedtls_gcm_context *ctx) { memset(ctx, 0, sizeof(mbedtls_gcm_context)); } static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx) { #if defined(MBEDTLS_GCM_LARGE_TABLE) ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE; #else ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE; #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) /* With CLMUL support, we need only h, not the rest of the table */ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { ctx->acceleration = MBEDTLS_GCM_ACC_AESNI; } #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { ctx->acceleration = MBEDTLS_GCM_ACC_AESCE; } #endif } static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2]) { uint8_t *u8Dst = (uint8_t *) dst; uint8_t *u8Src = (uint8_t *) src; MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0); u8Dst[8] |= (u8Src[7] & 0x01) << 7; MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0); u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0; } /* * Precompute small multiples of H, that is set * HH[i] || HL[i] = H times i, * where i is seen as a field element as in [MGV], ie high-order bits * correspond to low powers of P. The result is stored in the same way, that * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL * corresponds to P^127. */ static int gcm_gen_table(mbedtls_gcm_context *ctx) { int ret, i, j; uint64_t u64h[2] = { 0 }; uint8_t *h = (uint8_t *) u64h; #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h); #else size_t olen = 0; ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen); #endif if (ret != 0) { return ret; } gcm_set_acceleration(ctx); /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */ ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0]; ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1]; switch (ctx->acceleration) { #if defined(MBEDTLS_AESNI_HAVE_CODE) case MBEDTLS_GCM_ACC_AESNI: return 0; #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) case MBEDTLS_GCM_ACC_AESCE: return 0; #endif default: /* 0 corresponds to 0 in GF(2^128) */ ctx->H[0][0] = 0; ctx->H[0][1] = 0; for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) { gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]); } #if !defined(MBEDTLS_GCM_LARGE_TABLE) /* pack elements of H as 64-bits ints, big-endian */ for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) { MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0); MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0); } #endif for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) { for (j = 1; j < i; j++) { mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j], (unsigned char *) ctx->H[i], (unsigned char *) ctx->H[j], 16); } } } return 0; } int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (keybits != 128 && keybits != 192 && keybits != 256) { return MBEDTLS_ERR_GCM_BAD_INPUT; } #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) { return ret; } if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) { return ret; } #else const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); if (cipher_info == NULL) { return MBEDTLS_ERR_GCM_BAD_INPUT; } if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_GCM_BAD_INPUT; } mbedtls_cipher_free(&ctx->cipher_ctx); if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, MBEDTLS_ENCRYPT)) != 0) { return ret; } #endif if ((ret = gcm_gen_table(ctx)) != 0) { return ret; } return 0; } #if defined(MBEDTLS_GCM_LARGE_TABLE) static const uint16_t last8[256] = { 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05, 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b, 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19, 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17, 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d, 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33, 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21, 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f, 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75, 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b, 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69, 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67, 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d, 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43, 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51, 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f, 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4, 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea, 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8, 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6, 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc, 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2, 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0, 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece, 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94, 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a, 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88, 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86, 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac, 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2, 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0, 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe }; static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2]) { int i; uint64_t u64z[2]; uint16_t *u16z = (uint16_t *) u64z; uint8_t *u8z = (uint8_t *) u64z; uint8_t rem; u64z[0] = 0; u64z[1] = 0; if (MBEDTLS_IS_BIG_ENDIAN) { for (i = 15; i > 0; i--) { mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16); rem = u8z[15]; u64z[1] >>= 8; u8z[8] = u8z[7]; u64z[0] >>= 8; u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0); } } else { for (i = 15; i > 0; i--) { mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16); rem = u8z[15]; u64z[1] <<= 8; u8z[8] = u8z[7]; u64z[0] <<= 8; u16z[0] ^= last8[rem]; } } mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16); } #else /* * Shoup's method for multiplication use this table with * last4[x] = x times P^128 * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] */ static const uint16_t last4[16] = { 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 }; static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2]) { int i = 0; unsigned char lo, hi, rem; uint64_t u64z[2]; const uint64_t *pu64z = NULL; uint8_t *u8z = (uint8_t *) u64z; lo = x[15] & 0xf; hi = (x[15] >> 4) & 0xf; pu64z = H[lo]; rem = (unsigned char) pu64z[1] & 0xf; u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4); u64z[0] = (pu64z[0] >> 4); u64z[0] ^= (uint64_t) last4[rem] << 48; mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16); for (i = 14; i >= 0; i--) { lo = x[i] & 0xf; hi = (x[i] >> 4) & 0xf; rem = (unsigned char) u64z[1] & 0xf; u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4); u64z[0] = (u64z[0] >> 4); u64z[0] ^= (uint64_t) last4[rem] << 48; mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16); rem = (unsigned char) u64z[1] & 0xf; u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4); u64z[0] = (u64z[0] >> 4); u64z[0] ^= (uint64_t) last4[rem] << 48; mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16); } MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0); MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8); } #endif /* * Sets output to x times H using the precomputed tables. * x and output are seen as elements of GF(2^128) as in [MGV]. */ static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16], unsigned char output[16]) { switch (ctx->acceleration) { #if defined(MBEDTLS_AESNI_HAVE_CODE) case MBEDTLS_GCM_ACC_AESNI: mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]); break; #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) case MBEDTLS_GCM_ACC_AESCE: mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]); break; #endif #if defined(MBEDTLS_GCM_LARGE_TABLE) case MBEDTLS_GCM_ACC_LARGETABLE: gcm_mult_largetable(output, x, ctx->H); break; #else case MBEDTLS_GCM_ACC_SMALLTABLE: gcm_mult_smalltable(output, x, ctx->H); break; #endif } return; } int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, int mode, const unsigned char *iv, size_t iv_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char work_buf[16]; const unsigned char *p; size_t use_len; uint64_t iv_bits; #if !defined(MBEDTLS_BLOCK_CIPHER_C) size_t olen = 0; #endif /* IV is limited to 2^64 bits, so 2^61 bytes */ /* IV is not allowed to be zero length */ if (iv_len == 0 || (uint64_t) iv_len >> 61 != 0) { return MBEDTLS_ERR_GCM_BAD_INPUT; } memset(ctx->y, 0x00, sizeof(ctx->y)); memset(ctx->buf, 0x00, sizeof(ctx->buf)); ctx->mode = mode; ctx->len = 0; ctx->add_len = 0; if (iv_len == 12) { memcpy(ctx->y, iv, iv_len); ctx->y[15] = 1; } else { memset(work_buf, 0x00, 16); iv_bits = (uint64_t) iv_len * 8; MBEDTLS_PUT_UINT64_BE(iv_bits, work_buf, 8); p = iv; while (iv_len > 0) { use_len = (iv_len < 16) ? iv_len : 16; #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110) #pragma GCC diagnostic push #pragma GCC diagnostic warning "-Wstringop-overflow=0" #endif mbedtls_xor(ctx->y, ctx->y, p, use_len); #if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110) #pragma GCC diagnostic pop #endif gcm_mult(ctx, ctx->y, ctx->y); iv_len -= use_len; p += use_len; } mbedtls_xor(ctx->y, ctx->y, work_buf, 16); gcm_mult(ctx, ctx->y, ctx->y); } #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr); #else ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen); #endif if (ret != 0) { return ret; } return 0; } /** * mbedtls_gcm_context::buf contains the partial state of the computation of * the authentication tag. * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate * different stages of the computation: * * len == 0 && add_len == 0: initial state * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have * a partial block of AD that has been * xored in but not yet multiplied in. * * len == 0 && add_len % 16 == 0: the authentication tag is correct if * the data ends now. * * len % 16 != 0: the first `len % 16` bytes have * a partial block of ciphertext that has * been xored in but not yet multiplied in. * * len > 0 && len % 16 == 0: the authentication tag is correct if * the data ends now. */ int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx, const unsigned char *add, size_t add_len) { const unsigned char *p; size_t use_len, offset; uint64_t new_add_len; /* AD is limited to 2^64 bits, ie 2^61 bytes * Also check for possible overflow */ #if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL if (add_len > 0xFFFFFFFFFFFFFFFFULL) { return MBEDTLS_ERR_GCM_BAD_INPUT; } #endif new_add_len = ctx->add_len + (uint64_t) add_len; if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) { return MBEDTLS_ERR_GCM_BAD_INPUT; } offset = ctx->add_len % 16; p = add; if (offset != 0) { use_len = 16 - offset; if (use_len > add_len) { use_len = add_len; } mbedtls_xor(ctx->buf + offset, ctx->buf + offset, p, use_len); if (offset + use_len == 16) { gcm_mult(ctx, ctx->buf, ctx->buf); } ctx->add_len += use_len; add_len -= use_len; p += use_len; } ctx->add_len += add_len; while (add_len >= 16) { mbedtls_xor(ctx->buf, ctx->buf, p, 16); gcm_mult(ctx, ctx->buf, ctx->buf); add_len -= 16; p += 16; } if (add_len > 0) { mbedtls_xor(ctx->buf, ctx->buf, p, add_len); } return 0; } /* Increment the counter. */ static void gcm_incr(unsigned char y[16]) { uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12); x++; MBEDTLS_PUT_UINT32_BE(x, y, 12); } /* Calculate and apply the encryption mask. Process use_len bytes of data, * starting at position offset in the mask block. */ static int gcm_mask(mbedtls_gcm_context *ctx, unsigned char ectr[16], size_t offset, size_t use_len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_BLOCK_CIPHER_C) ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr); #else size_t olen = 0; ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen); #endif if (ret != 0) { mbedtls_platform_zeroize(ectr, 16); return ret; } if (ctx->mode == MBEDTLS_GCM_DECRYPT) { mbedtls_xor(ctx->buf + offset, ctx->buf + offset, input, use_len); } mbedtls_xor(output, ectr + offset, input, use_len); if (ctx->mode == MBEDTLS_GCM_ENCRYPT) { mbedtls_xor(ctx->buf + offset, ctx->buf + offset, output, use_len); } return 0; } int mbedtls_gcm_update(mbedtls_gcm_context *ctx, const unsigned char *input, size_t input_length, unsigned char *output, size_t output_size, size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = input; unsigned char *out_p = output; size_t offset; unsigned char ectr[16] = { 0 }; if (output_size < input_length) { return MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL; } *output_length = input_length; /* Exit early if input_length==0 so that we don't do any pointer arithmetic * on a potentially null pointer. * Returning early also means that the last partial block of AD remains * untouched for mbedtls_gcm_finish */ if (input_length == 0) { return 0; } if (output > input && (size_t) (output - input) < input_length) { return MBEDTLS_ERR_GCM_BAD_INPUT; } /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes * Also check for possible overflow */ if (ctx->len + input_length < ctx->len || (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull) { return MBEDTLS_ERR_GCM_BAD_INPUT; } if (ctx->len == 0 && ctx->add_len % 16 != 0) { gcm_mult(ctx, ctx->buf, ctx->buf); } offset = ctx->len % 16; if (offset != 0) { size_t use_len = 16 - offset; if (use_len > input_length) { use_len = input_length; } if ((ret = gcm_mask(ctx, ectr, offset, use_len, p, out_p)) != 0) { return ret; } if (offset + use_len == 16) { gcm_mult(ctx, ctx->buf, ctx->buf); } ctx->len += use_len; input_length -= use_len; p += use_len; out_p += use_len; } ctx->len += input_length; while (input_length >= 16) { gcm_incr(ctx->y); if ((ret = gcm_mask(ctx, ectr, 0, 16, p, out_p)) != 0) { return ret; } gcm_mult(ctx, ctx->buf, ctx->buf); input_length -= 16; p += 16; out_p += 16; } if (input_length > 0) { gcm_incr(ctx->y); if ((ret = gcm_mask(ctx, ectr, 0, input_length, p, out_p)) != 0) { return ret; } } mbedtls_platform_zeroize(ectr, sizeof(ectr)); return 0; } int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, unsigned char *output, size_t output_size, size_t *output_length, unsigned char *tag, size_t tag_len) { unsigned char work_buf[16]; uint64_t orig_len; uint64_t orig_add_len; /* We never pass any output in finish(). The output parameter exists only * for the sake of alternative implementations. */ (void) output; (void) output_size; *output_length = 0; /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of * the two multiplications would overflow. */ orig_len = ctx->len * 8; orig_add_len = ctx->add_len * 8; if (ctx->len == 0 && ctx->add_len % 16 != 0) { gcm_mult(ctx, ctx->buf, ctx->buf); } if (tag_len > 16 || tag_len < 4) { return MBEDTLS_ERR_GCM_BAD_INPUT; } if (ctx->len % 16 != 0) { gcm_mult(ctx, ctx->buf, ctx->buf); } memcpy(tag, ctx->base_ectr, tag_len); if (orig_len || orig_add_len) { memset(work_buf, 0x00, 16); MBEDTLS_PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0); MBEDTLS_PUT_UINT32_BE((orig_add_len), work_buf, 4); MBEDTLS_PUT_UINT32_BE((orig_len >> 32), work_buf, 8); MBEDTLS_PUT_UINT32_BE((orig_len), work_buf, 12); mbedtls_xor(ctx->buf, ctx->buf, work_buf, 16); gcm_mult(ctx, ctx->buf, ctx->buf); mbedtls_xor(tag, tag, ctx->buf, tag_len); } return 0; } int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, int mode, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *input, unsigned char *output, size_t tag_len, unsigned char *tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len)) != 0) { return ret; } if ((ret = mbedtls_gcm_update_ad(ctx, add, add_len)) != 0) { return ret; } if ((ret = mbedtls_gcm_update(ctx, input, length, output, length, &olen)) != 0) { return ret; } if ((ret = mbedtls_gcm_finish(ctx, NULL, 0, &olen, tag, tag_len)) != 0) { return ret; } return 0; } int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, size_t length, const unsigned char *iv, size_t iv_len, const unsigned char *add, size_t add_len, const unsigned char *tag, size_t tag_len, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char check_tag[16]; int diff; if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag)) != 0) { return ret; } /* Check tag in "constant-time" */ diff = mbedtls_ct_memcmp(tag, check_tag, tag_len); if (diff != 0) { mbedtls_platform_zeroize(output, length); return MBEDTLS_ERR_GCM_AUTH_FAILED; } return 0; } void mbedtls_gcm_free(mbedtls_gcm_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_BLOCK_CIPHER_C) mbedtls_block_cipher_free(&ctx->block_cipher_ctx); #else mbedtls_cipher_free(&ctx->cipher_ctx); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context)); } #endif /* !MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES) /* * AES-GCM test vectors from: * * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */ #define MAX_TESTS 6 static const int key_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; static const unsigned char key_test_data[][32] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, }; static const size_t iv_len_test_data[MAX_TESTS] = { 12, 12, 12, 12, 8, 60 }; static const int iv_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 2 }; static const unsigned char iv_test_data[][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }, { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, 0xa6, 0x37, 0xb3, 0x9b }, }; static const size_t add_len_test_data[MAX_TESTS] = { 0, 0, 0, 20, 20, 20 }; static const int add_index_test_data[MAX_TESTS] = { 0, 0, 0, 1, 1, 1 }; static const unsigned char additional_test_data[][64] = { { 0x00 }, { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }, }; static const size_t pt_len_test_data[MAX_TESTS] = { 0, 16, 64, 60, 60, 60 }; static const int pt_index_test_data[MAX_TESTS] = { 0, 0, 1, 1, 1, 1 }; static const unsigned char pt_test_data[][64] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, }; static const unsigned char ct_test_data[][64] = { { 0x00 }, { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91 }, { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, 0xc2, 0x3f, 0x45, 0x98 }, { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, 0x4c, 0x34, 0xae, 0xe5 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x00 }, { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, 0xcc, 0xda, 0x27, 0x10 }, { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, 0xa0, 0xf0, 0x62, 0xf7 }, { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, 0xe9, 0xb7, 0x37, 0x3b }, { 0x00 }, { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, 0xbc, 0xc9, 0xf6, 0x62 }, { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, 0xf4, 0x7c, 0x9b, 0x1f }, { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, 0x44, 0xae, 0x7e, 0x3f }, #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ }; static const unsigned char tag_test_data[][16] = { { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ }; int mbedtls_gcm_self_test(int verbose) { mbedtls_gcm_context ctx; unsigned char buf[64]; unsigned char tag_buf[16]; int i, j, ret; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; size_t olen; if (verbose != 0) { #if defined(MBEDTLS_GCM_ALT) mbedtls_printf(" GCM note: alternative implementation.\n"); #else /* MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_AESNI_HAVE_CODE) if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) { mbedtls_printf(" GCM note: using AESNI.\n"); } else #endif #if defined(MBEDTLS_AESCE_HAVE_CODE) if (MBEDTLS_AESCE_HAS_SUPPORT()) { mbedtls_printf(" GCM note: using AESCE.\n"); } else #endif mbedtls_printf(" GCM note: built-in implementation.\n"); #endif /* MBEDTLS_GCM_ALT */ } static const int loop_limit = (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS; for (j = 0; j < loop_limit; j++) { int key_len = 128 + 64 * j; for (i = 0; i < MAX_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "enc"); } mbedtls_gcm_init(&ctx); ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); /* * AES-192 is an optional feature that may be unavailable when * there is an alternative underlying implementation i.e. when * MBEDTLS_AES_ALT is defined. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192) { mbedtls_printf("skipped\n"); break; } else if (ret != 0) { goto exit; } ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, pt_len_test_data[i], iv_test_data[iv_index_test_data[i]], iv_len_test_data[i], additional_test_data[add_index_test_data[i]], add_len_test_data[i], pt_test_data[pt_index_test_data[i]], buf, 16, tag_buf); #if defined(MBEDTLS_GCM_ALT) /* Allow alternative implementations to only support 12-byte nonces. */ if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && iv_len_test_data[i] != 12) { mbedtls_printf("skipped\n"); break; } #endif /* defined(MBEDTLS_GCM_ALT) */ if (ret != 0) { goto exit; } if (memcmp(buf, ct_test_data[j * 6 + i], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } mbedtls_gcm_init(&ctx); if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d (%s): ", key_len, i, "dec"); } ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); if (ret != 0) { goto exit; } ret = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT, pt_len_test_data[i], iv_test_data[iv_index_test_data[i]], iv_len_test_data[i], additional_test_data[add_index_test_data[i]], add_len_test_data[i], ct_test_data[j * 6 + i], buf, 16, tag_buf); if (ret != 0) { goto exit; } if (memcmp(buf, pt_test_data[pt_index_test_data[i]], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } mbedtls_gcm_init(&ctx); if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", key_len, i, "enc"); } ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); if (ret != 0) { goto exit; } ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, iv_test_data[iv_index_test_data[i]], iv_len_test_data[i]); if (ret != 0) { goto exit; } ret = mbedtls_gcm_update_ad(&ctx, additional_test_data[add_index_test_data[i]], add_len_test_data[i]); if (ret != 0) { goto exit; } if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], 32, buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != 32) { goto exit; } ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]] + 32, rest_len, buf + 32, sizeof(buf) - 32, &olen); if (ret != 0) { goto exit; } if (olen != rest_len) { goto exit; } } else { ret = mbedtls_gcm_update(&ctx, pt_test_data[pt_index_test_data[i]], pt_len_test_data[i], buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != pt_len_test_data[i]) { goto exit; } } ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); if (ret != 0) { goto exit; } if (memcmp(buf, ct_test_data[j * 6 + i], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } mbedtls_gcm_init(&ctx); if (verbose != 0) { mbedtls_printf(" AES-GCM-%3d #%d split (%s): ", key_len, i, "dec"); } ret = mbedtls_gcm_setkey(&ctx, cipher, key_test_data[key_index_test_data[i]], key_len); if (ret != 0) { goto exit; } ret = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv_test_data[iv_index_test_data[i]], iv_len_test_data[i]); if (ret != 0) { goto exit; } ret = mbedtls_gcm_update_ad(&ctx, additional_test_data[add_index_test_data[i]], add_len_test_data[i]); if (ret != 0) { goto exit; } if (pt_len_test_data[i] > 32) { size_t rest_len = pt_len_test_data[i] - 32; ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], 32, buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != 32) { goto exit; } ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i] + 32, rest_len, buf + 32, sizeof(buf) - 32, &olen); if (ret != 0) { goto exit; } if (olen != rest_len) { goto exit; } } else { ret = mbedtls_gcm_update(&ctx, ct_test_data[j * 6 + i], pt_len_test_data[i], buf, sizeof(buf), &olen); if (ret != 0) { goto exit; } if (olen != pt_len_test_data[i]) { goto exit; } } ret = mbedtls_gcm_finish(&ctx, NULL, 0, &olen, tag_buf, 16); if (ret != 0) { goto exit; } if (memcmp(buf, pt_test_data[pt_index_test_data[i]], pt_len_test_data[i]) != 0 || memcmp(tag_buf, tag_test_data[j * 6 + i], 16) != 0) { ret = 1; goto exit; } mbedtls_gcm_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } } } if (verbose != 0) { mbedtls_printf("\n"); } ret = 0; exit: if (ret != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } mbedtls_gcm_free(&ctx); } return ret; } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_GCM_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/hkdf.c000066400000000000000000000075711464416617300224260ustar00rootroot00000000000000/* * HKDF implementation -- RFC 5869 * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_HKDF_C) #include #include "mbedtls/hkdf.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" int mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char prk[MBEDTLS_MD_MAX_SIZE]; ret = mbedtls_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk); if (ret == 0) { ret = mbedtls_hkdf_expand(md, prk, mbedtls_md_get_size(md), info, info_len, okm, okm_len); } mbedtls_platform_zeroize(prk, sizeof(prk)); return ret; } int mbedtls_hkdf_extract(const mbedtls_md_info_t *md, const unsigned char *salt, size_t salt_len, const unsigned char *ikm, size_t ikm_len, unsigned char *prk) { unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; if (salt == NULL) { size_t hash_len; if (salt_len != 0) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } hash_len = mbedtls_md_get_size(md); if (hash_len == 0) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } salt = null_salt; salt_len = hash_len; } return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk); } int mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk, size_t prk_len, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len) { size_t hash_len; size_t where = 0; size_t n; size_t t_len = 0; size_t i; int ret = 0; mbedtls_md_context_t ctx; unsigned char t[MBEDTLS_MD_MAX_SIZE]; if (okm == NULL) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } hash_len = mbedtls_md_get_size(md); if (prk_len < hash_len || hash_len == 0) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } if (info == NULL) { info = (const unsigned char *) ""; info_len = 0; } n = okm_len / hash_len; if (okm_len % hash_len != 0) { n++; } /* * Per RFC 5869 Section 2.3, okm_len must not exceed * 255 times the hash length */ if (n > 255) { return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; } mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) { goto exit; } memset(t, 0, hash_len); /* * Compute T = T(1) | T(2) | T(3) | ... | T(N) * Where T(N) is defined in RFC 5869 Section 2.3 */ for (i = 1; i <= n; i++) { size_t num_to_copy; unsigned char c = i & 0xff; ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&ctx, t, t_len); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&ctx, info, info_len); if (ret != 0) { goto exit; } /* The constant concatenated to the end of each T(n) is a single octet. * */ ret = mbedtls_md_hmac_update(&ctx, &c, 1); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&ctx, t); if (ret != 0) { goto exit; } num_to_copy = i != n ? hash_len : okm_len - where; memcpy(okm + where, t, num_to_copy); where += hash_len; t_len = hash_len; } exit: mbedtls_md_free(&ctx); mbedtls_platform_zeroize(t, sizeof(t)); return ret; } #endif /* MBEDTLS_HKDF_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/hmac_drbg.c000066400000000000000000000450371464416617300234170ustar00rootroot00000000000000/* * HMAC_DRBG implementation (NIST SP 800-90) * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The NIST SP 800-90A DRBGs are described in the following publication. * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf * References below are based on rev. 1 (January 2012). */ #include "common.h" #if defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_FS_IO) #include #endif #include "mbedtls/platform.h" /* * HMAC_DRBG context initialization */ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx) { memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context)); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; } /* * HMAC_DRBG update, using optional additional data (10.1.2.2) */ int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len) { size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info); unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1; unsigned char sep[1]; unsigned char K[MBEDTLS_MD_MAX_SIZE]; int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; for (sep[0] = 0; sep[0] < rounds; sep[0]++) { /* Step 1 or 4 */ if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, ctx->V, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, sep, 1)) != 0) { goto exit; } if (rounds == 2) { if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, additional, add_len)) != 0) { goto exit; } } if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) { goto exit; } /* Step 2 or 5 */ if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, ctx->V, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) { goto exit; } } exit: mbedtls_platform_zeroize(K, sizeof(K)); return ret; } /* * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) */ int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, const unsigned char *data, size_t data_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) { return ret; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif /* * Set initial working state. * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, mbedtls_md_get_size(md_info))) != 0) { return ret; } memset(ctx->V, 0x01, mbedtls_md_get_size(md_info)); if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) { return ret; } return 0; } /* * Internal function used both for seeding and reseeding the DRBG. * Comments starting with arabic numbers refer to section 10.1.2.4 * of SP800-90A, while roman numbers refer to section 9.2. */ static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len, int use_nonce) { unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; size_t seedlen = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; { size_t total_entropy_len; if (use_nonce == 0) { total_entropy_len = ctx->entropy_len; } else { total_entropy_len = ctx->entropy_len * 3 / 2; } /* III. Check input length */ if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT || total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) { return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; } } memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT); /* IV. Gather entropy_len bytes of entropy for the seed */ if ((ret = ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) != 0) { return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += ctx->entropy_len; /* For initial seeding, allow adding of nonce generated * from the entropy source. See Sect 8.6.7 in SP800-90A. */ if (use_nonce) { /* Note: We don't merge the two calls to f_entropy() in order * to avoid requesting too much entropy from f_entropy() * at once. Specifically, if the underlying digest is not * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which * is larger than the maximum of 32 Bytes that our own * entropy source implementation can emit in a single * call in configurations disabling SHA-512. */ if ((ret = ctx->f_entropy(ctx->p_entropy, seed + seedlen, ctx->entropy_len / 2)) != 0) { return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED; } seedlen += ctx->entropy_len / 2; } /* 1. Concatenate entropy and additional data if any */ if (additional != NULL && len != 0) { memcpy(seed + seedlen, additional, len); seedlen += len; } /* 2. Update state */ if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) { goto exit; } /* 3. Reset reseed_counter */ ctx->reseed_counter = 1; exit: /* 4. Done */ mbedtls_platform_zeroize(seed, seedlen); return ret; } /* * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 */ int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len) { return hmac_drbg_reseed_core(ctx, additional, len, 0); } /* * HMAC_DRBG initialisation (10.1.2.3 + 9.1) * * The nonce is not passed as a separate parameter but extracted * from the entropy source as suggested in 8.6.7. */ int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx, const mbedtls_md_info_t *md_info, int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, const unsigned char *custom, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t md_size; if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) { return ret; } /* The mutex is initialized iff the md context is set up. */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif md_size = mbedtls_md_get_size(md_info); /* * Set initial working state. * Use the V memory location, which is currently all 0, to initialize the * MD context with an all-zero key. Then set V to its initial value. */ if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) { return ret; } memset(ctx->V, 0x01, md_size); ctx->f_entropy = f_entropy; ctx->p_entropy = p_entropy; if (ctx->entropy_len == 0) { /* * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by * each hash function, then according to SP800-90A rev1 10.1 table 2, * min_entropy_len (in bits) is security_strength. * * (This also matches the sizes used in the NIST test vectors.) */ ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ 32; /* better (256+) -> 256 bits */ } if ((ret = hmac_drbg_reseed_core(ctx, custom, len, 1 /* add nonce */)) != 0) { return ret; } return 0; } /* * Set prediction resistance */ void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx, int resistance) { ctx->prediction_resistance = resistance; } /* * Set entropy length grabbed for seeding */ void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len) { ctx->entropy_len = len; } /* * Set reseed interval */ void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval) { ctx->reseed_interval = interval; } /* * HMAC_DRBG random function with optional additional data: * 10.1.2.5 (arabic) + 9.3 (Roman) */ int mbedtls_hmac_drbg_random_with_add(void *p_rng, unsigned char *output, size_t out_len, const unsigned char *additional, size_t add_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info); size_t left = out_len; unsigned char *out = output; /* II. Check request length */ if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) { return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG; } /* III. Check input length */ if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) { return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; } /* 1. (aka VII and IX) Check reseed counter and PR */ if (ctx->f_entropy != NULL && /* For no-reseeding instances */ (ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || ctx->reseed_counter > ctx->reseed_interval)) { if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) { return ret; } add_len = 0; /* VII.4 */ } /* 2. Use additional data if any */ if (additional != NULL && add_len != 0) { if ((ret = mbedtls_hmac_drbg_update(ctx, additional, add_len)) != 0) { goto exit; } } /* 3, 4, 5. Generate bytes */ while (left != 0) { size_t use_len = left > md_len ? md_len : left; if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx, ctx->V, md_len)) != 0) { goto exit; } if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) { goto exit; } memcpy(out, ctx->V, use_len); out += use_len; left -= use_len; } /* 6. Update */ if ((ret = mbedtls_hmac_drbg_update(ctx, additional, add_len)) != 0) { goto exit; } /* 7. Update reseed counter */ ctx->reseed_counter++; exit: /* 8. Done */ return ret; } /* * HMAC_DRBG random function */ int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * This function resets HMAC_DRBG context to the state immediately * after initial call of mbedtls_hmac_drbg_init(). */ void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx) { if (ctx == NULL) { return; } #if defined(MBEDTLS_THREADING_C) /* The mutex is initialized iff the md context is set up. */ if (ctx->md_ctx.md_info != NULL) { mbedtls_mutex_free(&ctx->mutex); } #endif mbedtls_md_free(&ctx->md_ctx); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context)); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; } #if defined(MBEDTLS_FS_IO) int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; FILE *f; unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT]; if ((f = fopen(path, "wb")) == NULL) { return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) { goto exit; } if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) { ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; goto exit; } ret = 0; exit: fclose(f); mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path) { int ret = 0; FILE *f = NULL; size_t n; unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT]; unsigned char c; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); n = fread(buf, 1, sizeof(buf), f); if (fread(&c, 1, 1, f) != 0) { ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; goto exit; } if (n == 0 || ferror(f)) { ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; goto exit; } fclose(f); f = NULL; ret = mbedtls_hmac_drbg_update(ctx, buf, n); exit: mbedtls_platform_zeroize(buf, sizeof(buf)); if (f != NULL) { fclose(f); } if (ret != 0) { return ret; } return mbedtls_hmac_drbg_write_seed_file(ctx, path); } #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_SELF_TEST) #if !defined(MBEDTLS_MD_CAN_SHA1) /* Dummy checkup routine */ int mbedtls_hmac_drbg_self_test(int verbose) { (void) verbose; return 0; } #else #define OUTPUT_LEN 80 /* From a NIST PR=true test vector */ static const unsigned char entropy_pr[] = { 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; static const unsigned char result_pr[OUTPUT_LEN] = { 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; /* From a NIST PR=false test vector */ static const unsigned char entropy_nopr[] = { 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, 0xe9, 0x9d, 0xfe, 0xdf }; static const unsigned char result_nopr[OUTPUT_LEN] = { 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; /* "Entropy" from buffer */ static size_t test_offset; static int hmac_drbg_self_test_entropy(void *data, unsigned char *buf, size_t len) { const unsigned char *p = data; memcpy(buf, p + test_offset, len); test_offset += len; return 0; } #define CHK(c) if ((c) != 0) \ { \ if (verbose != 0) \ mbedtls_printf("failed\n"); \ return 1; \ } /* * Checkup routine for HMAC_DRBG with SHA-1 */ int mbedtls_hmac_drbg_self_test(int verbose) { mbedtls_hmac_drbg_context ctx; unsigned char buf[OUTPUT_LEN]; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); mbedtls_hmac_drbg_init(&ctx); /* * PR = True */ if (verbose != 0) { mbedtls_printf(" HMAC_DRBG (PR = True) : "); } test_offset = 0; CHK(mbedtls_hmac_drbg_seed(&ctx, md_info, hmac_drbg_self_test_entropy, (void *) entropy_pr, NULL, 0)); mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(memcmp(buf, result_pr, OUTPUT_LEN)); mbedtls_hmac_drbg_free(&ctx); mbedtls_hmac_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } /* * PR = False */ if (verbose != 0) { mbedtls_printf(" HMAC_DRBG (PR = False) : "); } mbedtls_hmac_drbg_init(&ctx); test_offset = 0; CHK(mbedtls_hmac_drbg_seed(&ctx, md_info, hmac_drbg_self_test_entropy, (void *) entropy_nopr, NULL, 0)); CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0)); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN)); CHK(memcmp(buf, result_nopr, OUTPUT_LEN)); mbedtls_hmac_drbg_free(&ctx); mbedtls_hmac_drbg_free(&ctx); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_HMAC_DRBG_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/lmots.c000066400000000000000000000647221464416617300226510ustar00rootroot00000000000000/* * The LM-OTS one-time public-key signature scheme * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the LM-OTS algorithm: * * [1] IETF RFC8554 * D. McGrew, M. Curcio, S.Fluhrer * https://datatracker.ietf.org/doc/html/rfc8554 * * [2] NIST Special Publication 800-208 * David A. Cooper et. al. * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf */ #include "common.h" #if defined(MBEDTLS_LMS_C) #include #include "lmots.h" #include "mbedtls/lms.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "psa_util_internal.h" #include "psa/crypto.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_lms_errors, ARRAY_LENGTH(psa_to_lms_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define PUBLIC_KEY_TYPE_OFFSET (0) #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) #define PUBLIC_KEY_Q_LEAF_ID_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ MBEDTLS_LMOTS_I_KEY_ID_LEN) #define PUBLIC_KEY_KEY_HASH_OFFSET (PUBLIC_KEY_Q_LEAF_ID_OFFSET + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN) /* We only support parameter sets that use 8-bit digits, as it does not require * translation logic between digits and bytes */ #define W_WINTERNITZ_PARAMETER (8u) #define CHECKSUM_LEN (2) #define I_DIGIT_IDX_LEN (2) #define J_HASH_IDX_LEN (1) #define D_CONST_LEN (2) #define DIGIT_MAX_VALUE ((1u << W_WINTERNITZ_PARAMETER) - 1u) #define D_CONST_LEN (2) static const unsigned char D_PUBLIC_CONSTANT_BYTES[D_CONST_LEN] = { 0x80, 0x80 }; static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81 }; #if defined(MBEDTLS_TEST_HOOKS) int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL; #endif /* defined(MBEDTLS_TEST_HOOKS) */ /* Calculate the checksum digits that are appended to the end of the LMOTS digit * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of * the checksum algorithm. * * params The LMOTS parameter set, I and q values which * describe the key being used. * * digest The digit string to create the digest from. As * this does not contain a checksum, it is the same * size as a hash output. */ static unsigned short lmots_checksum_calculate(const mbedtls_lmots_parameters_t *params, const unsigned char *digest) { size_t idx; unsigned sum = 0; for (idx = 0; idx < MBEDTLS_LMOTS_N_HASH_LEN(params->type); idx++) { sum += DIGIT_MAX_VALUE - digest[idx]; } return sum; } /* Create the string of digest digits (in the base determined by the Winternitz * parameter with the checksum appended to the end (Q || cksm(Q)). See NIST * SP800-208 section 3.1 or RFC8554 Algorithm 3 step 5 (also used in Algorithm * 4b step 3) for details. * * params The LMOTS parameter set, I and q values which * describe the key being used. * * msg The message that will be hashed to create the * digest. * * msg_size The size of the message. * * C_random_value The random value that will be combined with the * message digest. This is always the same size as a * hash output for whichever hash algorithm is * determined by the parameter set. * * output An output containing the digit string (+ * checksum) of length P digits (in the case of * MBEDTLS_LMOTS_SHA256_N32_W8, this means it is of * size P bytes). */ static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_len, const unsigned char *C_random_value, unsigned char *out) { psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned short checksum; status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_MESSAGE_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, C_random_value, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, msg, msg_len); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } checksum = lmots_checksum_calculate(params, out); MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } /* Hash each element of the string of digits (+ checksum), producing a hash * output for each element. This is used in several places (by varying the * hash_idx_min/max_values) in order to calculate a public key from a private * key (RFC8554 Algorithm 1 step 4), in order to sign a message (RFC8554 * Algorithm 3 step 5), and to calculate a public key candidate from a * signature and message (RFC8554 Algorithm 4b step 3). * * params The LMOTS parameter set, I and q values which * describe the key being used. * * x_digit_array The array of digits (of size P, 34 in the case of * MBEDTLS_LMOTS_SHA256_N32_W8). * * hash_idx_min_values An array of the starting values of the j iterator * for each of the members of the digit array. If * this value in NULL, then all iterators will start * at 0. * * hash_idx_max_values An array of the upper bound values of the j * iterator for each of the members of the digit * array. If this value in NULL, then iterator is * bounded to be less than 2^w - 1 (255 in the case * of MBEDTLS_LMOTS_SHA256_N32_W8) * * output An array containing a hash output for each member * of the digit string P. In the case of * MBEDTLS_LMOTS_SHA256_N32_W8, this is of size 32 * * 34. */ static int hash_digit_array(const mbedtls_lmots_parameters_t *params, const unsigned char *x_digit_array, const unsigned char *hash_idx_min_values, const unsigned char *hash_idx_max_values, unsigned char *output) { unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[I_DIGIT_IDX_LEN]; unsigned int j_hash_idx; unsigned char j_hash_idx_bytes[J_HASH_IDX_LEN]; unsigned int j_hash_idx_min; unsigned int j_hash_idx_max; psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char tmp_hash[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; for (i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type); i_digit_idx++) { memcpy(tmp_hash, &x_digit_array[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], MBEDTLS_LMOTS_N_HASH_LEN(params->type)); j_hash_idx_min = hash_idx_min_values != NULL ? hash_idx_min_values[i_digit_idx] : 0; j_hash_idx_max = hash_idx_max_values != NULL ? hash_idx_max_values[i_digit_idx] : DIGIT_MAX_VALUE; for (j_hash_idx = j_hash_idx_min; j_hash_idx < j_hash_idx_max; j_hash_idx++) { status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); if (status != PSA_SUCCESS) { goto exit; } j_hash_idx_bytes[0] = (uint8_t) j_hash_idx; status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, tmp_hash, sizeof(tmp_hash), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } psa_hash_abort(&op); } memcpy(&output[i_digit_idx * MBEDTLS_LMOTS_N_HASH_LEN(params->type)], tmp_hash, MBEDTLS_LMOTS_N_HASH_LEN(params->type)); } exit: psa_hash_abort(&op); mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash)); return PSA_TO_MBEDTLS_ERR(status); } /* Combine the hashes of the digit array into a public key. This is used in * in order to calculate a public key from a private key (RFC8554 Algorithm 1 * step 4), and to calculate a public key candidate from a signature and message * (RFC8554 Algorithm 4b step 3). * * params The LMOTS parameter set, I and q values which describe * the key being used. * y_hashed_digits The array of hashes, one hash for each digit of the * symbol array (which is of size P, 34 in the case of * MBEDTLS_LMOTS_SHA256_N32_W8) * * pub_key The output public key (or candidate public key in * case this is being run as part of signature * verification), in the form of a hash output. */ static int public_key_from_hashed_digit_array(const mbedtls_lmots_parameters_t *params, const unsigned char *y_hashed_digits, unsigned char *pub_key) { psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_PUBLIC_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, y_hashed_digits, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(params->type) * MBEDTLS_LMOTS_N_HASH_LEN(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->type), &output_hash_len); if (status != PSA_SUCCESS) { exit: psa_hash_abort(&op); } return PSA_TO_MBEDTLS_ERR(status); } #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_lms_error_from_psa(psa_status_t status) { switch (status) { case PSA_SUCCESS: return 0; case PSA_ERROR_HARDWARE_FAILURE: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; case PSA_ERROR_INVALID_ARGUMENT: return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; default: return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx) { mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_len) { if (key_len < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = (mbedtls_lmots_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } memcpy(ctx->params.I_key_identifier, key + PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(ctx->params.q_leaf_identifier, key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); memcpy(ctx->public_key, key + PUBLIC_KEY_KEY_HASH_OFFSET, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); ctx->have_public_key = 1; return 0; } int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len) { if (key_size < MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(key + PUBLIC_KEY_Q_LEAF_ID_OFFSET, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); memcpy(key + PUBLIC_KEY_KEY_HASH_OFFSET, ctx->public_key, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); if (key_len != NULL) { *key_len = MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type); } return 0; } int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size, unsigned char *out, size_t out_size, size_t *out_len) { unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (msg == NULL && msg_size != 0) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size != MBEDTLS_LMOTS_SIG_LEN(params->type) || out_size < MBEDTLS_LMOTS_N_HASH_LEN(params->type)) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = create_digit_array_with_checksum(params, msg, msg_size, sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_digit_array); if (ret) { return ret; } ret = hash_digit_array(params, sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(params->type), tmp_digit_array, NULL, (unsigned char *) y_hashed_digits); if (ret) { return ret; } ret = public_key_from_hashed_digit_array(params, (unsigned char *) y_hashed_digits, out); if (ret) { return ret; } if (out_len != NULL) { *out_len = MBEDTLS_LMOTS_N_HASH_LEN(params->type); } return 0; } int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size) { unsigned char Kc_public_key_candidate[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (msg == NULL && msg_size != 0) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.type != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size < MBEDTLS_LMOTS_SIG_TYPE_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } ret = mbedtls_lmots_calculate_public_key_candidate(&ctx->params, msg, msg_size, sig, sig_size, Kc_public_key_candidate, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), NULL); if (ret) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (memcmp(&Kc_public_key_candidate, ctx->public_key, sizeof(ctx->public_key))) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } return 0; } #if defined(MBEDTLS_LMS_PRIVATE) void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx) { mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, mbedtls_lmots_algorithm_type_t type, const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], uint32_t q_leaf_identifier, const unsigned char *seed, size_t seed_size) { psa_hash_operation_t op = PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned int i_digit_idx; unsigned char i_digit_idx_bytes[2]; unsigned char const_bytes[1] = { 0xFF }; if (ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (type != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = type; memcpy(ctx->params.I_key_identifier, I_key_identifier, sizeof(ctx->params.I_key_identifier)); MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0); for (i_digit_idx = 0; i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type); i_digit_idx++) { status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, ctx->params.I_key_identifier, sizeof(ctx->params.I_key_identifier)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, ctx->params.q_leaf_identifier, MBEDTLS_LMOTS_Q_LEAF_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0); status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, const_bytes, sizeof(const_bytes)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, seed, seed_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, ctx->private_key[i_digit_idx], MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } psa_hash_abort(&op); } ctx->have_private_key = 1; exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, const mbedtls_lmots_private_t *priv_ctx) { unsigned char y_hashed_digits[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that a private key is loaded */ if (!priv_ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = hash_digit_array(&priv_ctx->params, (unsigned char *) priv_ctx->private_key, NULL, NULL, (unsigned char *) y_hashed_digits); if (ret) { goto exit; } ret = public_key_from_hashed_digit_array(&priv_ctx->params, (unsigned char *) y_hashed_digits, ctx->public_key); if (ret) { goto exit; } memcpy(&ctx->params, &priv_ctx->params, sizeof(ctx->params)); ctx->have_public_key = 1; exit: mbedtls_platform_zeroize(y_hashed_digits, sizeof(y_hashed_digits)); return ret; } int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len) { unsigned char tmp_digit_array[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX]; /* Create a temporary buffer to prepare the signature in. This allows us to * finish creating a signature (ensuring the process doesn't fail), and then * erase the private key **before** writing any data into the sig parameter * buffer. If data were directly written into the sig buffer, it might leak * a partial signature on failure, which effectively compromises the private * key. */ unsigned char tmp_sig[MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT_MAX][MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char tmp_c_random[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (msg == NULL && msg_size != 0) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size < MBEDTLS_LMOTS_SIG_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } /* Check that a private key is loaded */ if (!ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = f_rng(p_rng, tmp_c_random, MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); if (ret) { return ret; } ret = create_digit_array_with_checksum(&ctx->params, msg, msg_size, tmp_c_random, tmp_digit_array); if (ret) { goto exit; } ret = hash_digit_array(&ctx->params, (unsigned char *) ctx->private_key, NULL, tmp_digit_array, (unsigned char *) tmp_sig); if (ret) { goto exit; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET); /* Test hook to check if sig is being written to before we invalidate the * private key. */ #if defined(MBEDTLS_TEST_HOOKS) if (mbedtls_lmots_sign_private_key_invalidated_hook != NULL) { ret = (*mbedtls_lmots_sign_private_key_invalidated_hook)(sig); if (ret != 0) { return ret; } } #endif /* defined(MBEDTLS_TEST_HOOKS) */ /* We've got a valid signature now, so it's time to make sure the private * key can't be reused. */ ctx->have_private_key = 0; mbedtls_platform_zeroize(ctx->private_key, sizeof(ctx->private_key)); memcpy(sig + MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET, tmp_c_random, MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(ctx->params.type)); memcpy(sig + MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(ctx->params.type), tmp_sig, MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type) * MBEDTLS_LMOTS_N_HASH_LEN(ctx->params.type)); if (sig_len != NULL) { *sig_len = MBEDTLS_LMOTS_SIG_LEN(ctx->params.type); } ret = 0; exit: mbedtls_platform_zeroize(tmp_digit_array, sizeof(tmp_digit_array)); mbedtls_platform_zeroize(tmp_sig, sizeof(tmp_sig)); return ret; } #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #endif /* defined(MBEDTLS_LMS_C) */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/lmots.h000066400000000000000000000306231464416617300226470ustar00rootroot00000000000000/** * \file lmots.h * * \brief This file provides an API for the LM-OTS post-quantum-safe one-time * public-key signature scheme as defined in RFC8554 and NIST.SP.200-208. * This implementation currently only supports a single parameter set * MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_LMOTS_H #define MBEDTLS_LMOTS_H #include "mbedtls/build_info.h" #include "psa/crypto.h" #include "mbedtls/lms.h" #include #include #define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \ MBEDTLS_LMOTS_I_KEY_ID_LEN + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \ MBEDTLS_LMOTS_N_HASH_LEN(type)) #define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0) #define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) #define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \ MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type)) #ifdef __cplusplus extern "C" { #endif #if defined(MBEDTLS_TEST_HOOKS) extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *); #endif /* defined(MBEDTLS_TEST_HOOKS) */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief This function converts a \ref psa_status_t to a * low-level LMS error code. * * \param status The psa_status_t to convert * * \return The corresponding LMS error code. */ int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status); #endif /** * \brief This function initializes a public LMOTS context * * \param ctx The uninitialized LMOTS context that will then be * initialized. */ void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx); /** * \brief This function uninitializes a public LMOTS context * * \param ctx The initialized LMOTS context that will then be * uninitialized. */ void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx); /** * \brief This function imports an LMOTS public key into a * LMOTS context. * * \note Before this function is called, the context must * have been initialized. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMOTS context store the key in. * \param key The buffer from which the key will be read. * #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read * from this. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx, const unsigned char *key, size_t key_size); /** * \brief This function exports an LMOTS public key from a * LMOTS context that already contains a public key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a public key. * * \note See IETF RFC8554 for details of the encoding of * this public key. * * \param ctx The initialized LMOTS context that contains the * public key. * \param key The buffer into which the key will be output. Must * be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len); /** * \brief This function creates a candidate public key from * an LMOTS signature. This can then be compared to * the real public key to determine the validity of * the signature. * * \note This function is exposed publicly to be used in LMS * signature verification, it is expected that * mbedtls_lmots_verify will be used for LMOTS * signature verification. * * \param params The LMOTS parameter set, q and I values as an * mbedtls_lmots_parameters_t struct. * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buffer from which the signature will be read. * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from * this. * \param out The buffer where the candidate public key will be * stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN * bytes in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size, unsigned char *out, size_t out_size, size_t *out_len); /** * \brief This function verifies a LMOTS signature, using a * LMOTS context that contains a public key. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note Before this function is called, the context must * have been initialized and must contain a public key * (either by import or calculation from a private * key). * * \param ctx The initialized LMOTS context from which the public * key will be read. * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf from which the signature will be read. * #MBEDTLS_LMOTS_SIG_LEN bytes will be read from * this. * * \return \c 0 on successful verification. * \return A non-zero error code on failure. */ int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size); #if defined(MBEDTLS_LMS_PRIVATE) /** * \brief This function initializes a private LMOTS context * * \param ctx The uninitialized LMOTS context that will then be * initialized. */ void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx); /** * \brief This function uninitializes a private LMOTS context * * \param ctx The initialized LMOTS context that will then be * uninitialized. */ void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx); /** * \brief This function calculates an LMOTS private key, and * stores in into an LMOTS context. * * \warning This function is **not intended for use in * production**, due to as-yet unsolved problems with * handling stateful keys. The API for this function * may change considerably in future versions. * * \note The seed must have at least 256 bits of entropy. * * \param ctx The initialized LMOTS context to generate the key * into. * \param I_key_identifier The key identifier of the key, as a 16-byte string. * \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is * not being used as part of an LMS key, this should * be set to 0. * \param seed The seed used to deterministically generate the * key. * \param seed_size The length of the seed. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx, mbedtls_lmots_algorithm_type_t type, const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN], uint32_t q_leaf_identifier, const unsigned char *seed, size_t seed_size); /** * \brief This function generates an LMOTS public key from a * LMOTS context that already contains a private key. * * \note Before this function is called, the context must * have been initialized and the context must contain * a private key. * * \param ctx The initialized LMOTS context to generate the key * from and store it into. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx, const mbedtls_lmots_private_t *priv_ctx); /** * \brief This function creates a LMOTS signature, using a * LMOTS context that contains a private key. * * \note Before this function is called, the context must * have been initialized and must contain a private * key. * * \note LMOTS private keys can only be used once, otherwise * attackers may be able to create forged signatures. * If the signing operation is successful, the private * key in the context will be erased, and no further * signing will be possible until another private key * is loaded * * \param ctx The initialized LMOTS context from which the * private key will be read. * \param f_rng The RNG function to be used for signature * generation. * \param p_rng The RNG context to be passed to f_rng * \param msg The buffer from which the message will be read. * \param msg_size The size of the message that will be read. * \param sig The buf into which the signature will be stored. * Must be at least #MBEDTLS_LMOTS_SIG_LEN in size. * * \return \c 0 on success. * \return A non-zero error code on failure. */ int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, size_t msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len); #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #ifdef __cplusplus } #endif #endif /* MBEDTLS_LMOTS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/lms.c000066400000000000000000000626711464416617300223070ustar00rootroot00000000000000/* * The LMS stateful-hash public-key signature scheme * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the LMS algorithm: * * [1] IETF RFC8554 * D. McGrew, M. Curcio, S.Fluhrer * https://datatracker.ietf.org/doc/html/rfc8554 * * [2] NIST Special Publication 800-208 * David A. Cooper et. al. * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-208.pdf */ #include "common.h" #if defined(MBEDTLS_LMS_C) #include #include "lmots.h" #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/lms.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_lms_errors, ARRAY_LENGTH(psa_to_lms_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define SIG_Q_LEAF_ID_OFFSET (0) #define SIG_OTS_SIG_OFFSET (SIG_Q_LEAF_ID_OFFSET + \ MBEDTLS_LMOTS_Q_LEAF_ID_LEN) #define SIG_TYPE_OFFSET(otstype) (SIG_OTS_SIG_OFFSET + \ MBEDTLS_LMOTS_SIG_LEN(otstype)) #define SIG_PATH_OFFSET(otstype) (SIG_TYPE_OFFSET(otstype) + \ MBEDTLS_LMS_TYPE_LEN) #define PUBLIC_KEY_TYPE_OFFSET (0) #define PUBLIC_KEY_OTSTYPE_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \ MBEDTLS_LMS_TYPE_LEN) #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_OTSTYPE_OFFSET + \ MBEDTLS_LMOTS_TYPE_LEN) #define PUBLIC_KEY_ROOT_NODE_OFFSET (PUBLIC_KEY_I_KEY_ID_OFFSET + \ MBEDTLS_LMOTS_I_KEY_ID_LEN) /* Currently only support H=10 */ #define H_TREE_HEIGHT_MAX 10 #define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u)) #define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type)) #define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \ (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))) #define D_CONST_LEN (2) static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 }; static const unsigned char D_INTR_CONSTANT_BYTES[D_CONST_LEN] = { 0x83, 0x83 }; /* Calculate the value of a leaf node of the Merkle tree (which is a hash of a * public key and some other parameters like the leaf index). This function * implements RFC8554 section 5.3, in the case where r >= 2^h. * * params The LMS parameter set, the underlying LMOTS * parameter set, and I value which describe the key * being used. * * pub_key The public key of the private whose index * corresponds to the index of this leaf node. This * is a hash output. * * r_node_idx The index of this node in the Merkle tree. Note * that the root node of the Merkle tree is * 1-indexed. * * out The output node value, which is a hash output. */ static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params, unsigned char *pub_key, unsigned int r_node_idx, unsigned char *out) { psa_hash_operation_t op; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; op = psa_hash_operation_init(); status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); status = psa_hash_update(&op, r_node_idx_bytes, 4); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_LEAF_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, pub_key, MBEDTLS_LMOTS_N_HASH_LEN(params->otstype)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } /* Calculate the value of an internal node of the Merkle tree (which is a hash * of a public key and some other parameters like the node index). This function * implements RFC8554 section 5.3, in the case where r < 2^h. * * params The LMS parameter set, the underlying LMOTS * parameter set, and I value which describe the key * being used. * * left_node The value of the child of this node which is on * the left-hand side. As with all nodes on the * Merkle tree, this is a hash output. * * right_node The value of the child of this node which is on * the right-hand side. As with all nodes on the * Merkle tree, this is a hash output. * * r_node_idx The index of this node in the Merkle tree. Note * that the root node of the Merkle tree is * 1-indexed. * * out The output node value, which is a hash output. */ static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params, const unsigned char *left_node, const unsigned char *right_node, unsigned int r_node_idx, unsigned char *out) { psa_hash_operation_t op; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_hash_len; unsigned char r_node_idx_bytes[4]; op = psa_hash_operation_init(); status = psa_hash_setup(&op, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, params->I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0); status = psa_hash_update(&op, r_node_idx_bytes, 4); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, D_INTR_CONSTANT_BYTES, D_CONST_LEN); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, left_node, MBEDTLS_LMS_M_NODE_BYTES(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&op, right_node, MBEDTLS_LMS_M_NODE_BYTES(params->type)); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&op, out, MBEDTLS_LMS_M_NODE_BYTES(params->type), &output_hash_len); if (status != PSA_SUCCESS) { goto exit; } exit: psa_hash_abort(&op); return PSA_TO_MBEDTLS_ERR(status); } void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx) { mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx, const unsigned char *key, size_t key_size) { mbedtls_lms_algorithm_type_t type; mbedtls_lmots_algorithm_type_t otstype; type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET); if (type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = type; if (key_size != MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } otstype = (mbedtls_lmots_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET); if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.otstype = otstype; memcpy(ctx->params.I_key_identifier, key + PUBLIC_KEY_I_KEY_ID_OFFSET, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(ctx->T_1_pub_key, key + PUBLIC_KEY_ROOT_NODE_OFFSET, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); ctx->have_public_key = 1; return 0; } int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx, unsigned char *key, size_t key_size, size_t *key_len) { if (key_size < MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET); MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET); memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); memcpy(key +PUBLIC_KEY_ROOT_NODE_OFFSET, ctx->T_1_pub_key, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)); if (key_len != NULL) { *key_len = MBEDTLS_LMS_PUBLIC_KEY_LEN(ctx->params.type); } return 0; } int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx, const unsigned char *msg, size_t msg_size, const unsigned char *sig, size_t sig_size) { unsigned int q_leaf_identifier; unsigned char Kc_candidate_ots_pub_key[MBEDTLS_LMOTS_N_HASH_LEN_MAX]; unsigned char Tc_candidate_root_node[MBEDTLS_LMS_M_NODE_BYTES_MAX]; unsigned int height; unsigned int curr_node_id; unsigned int parent_node_id; const unsigned char *left_node; const unsigned char *right_node; mbedtls_lmots_parameters_t ots_params; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (!ctx->have_public_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size != MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (sig_size < SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_TYPE_LEN) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (sig_size < SIG_TYPE_OFFSET(ctx->params.otstype) + MBEDTLS_LMS_TYPE_LEN) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype)) != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET); if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } memcpy(ots_params.I_key_identifier, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0); ots_params.type = ctx->params.otstype; ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params, msg, msg_size, sig + SIG_OTS_SIG_OFFSET, MBEDTLS_LMOTS_SIG_LEN(ctx->params.otstype), Kc_candidate_ots_pub_key, sizeof(Kc_candidate_ots_pub_key), NULL); if (ret != 0) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } create_merkle_leaf_value( &ctx->params, Kc_candidate_ots_pub_key, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, Tc_candidate_root_node); curr_node_id = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier; for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); height++) { parent_node_id = curr_node_id / 2; /* Left/right node ordering matters for the hash */ if (curr_node_id & 1) { left_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); right_node = Tc_candidate_root_node; } else { left_node = Tc_candidate_root_node; right_node = sig + SIG_PATH_OFFSET(ctx->params.otstype) + height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); } create_merkle_internal_value(&ctx->params, left_node, right_node, parent_node_id, Tc_candidate_root_node); curr_node_id /= 2; } if (memcmp(Tc_candidate_root_node, ctx->T_1_pub_key, MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type))) { return MBEDTLS_ERR_LMS_VERIFY_FAILED; } return 0; } #if defined(MBEDTLS_LMS_PRIVATE) /* Calculate a full Merkle tree based on a private key. This function * implements RFC8554 section 5.3, and is used to generate a public key (as the * public key is the root node of the Merkle tree). * * ctx The LMS private context, containing a parameter * set and private key material consisting of both * public and private OTS. * * tree The output tree, which is 2^(H + 1) hash outputs. * In the case of H=10 we have 2048 tree nodes (of * which 1024 of them are leaf nodes). Note that * because the Merkle tree root is 1-indexed, the 0 * index tree node is never used. */ static int calculate_merkle_tree(const mbedtls_lms_private_t *ctx, unsigned char *tree) { unsigned int priv_key_idx; unsigned int r_node_idx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* First create the leaf nodes, in ascending order */ for (priv_key_idx = 0; priv_key_idx < MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type); priv_key_idx++) { r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + priv_key_idx; ret = create_merkle_leaf_value(&ctx->params, ctx->ots_public_keys[priv_key_idx].public_key, r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES( ctx->params.type)]); if (ret != 0) { return ret; } } /* Then the internal nodes, in reverse order so that we can guarantee the * parent has been created */ for (r_node_idx = MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) - 1; r_node_idx > 0; r_node_idx--) { ret = create_merkle_internal_value(&ctx->params, &tree[(r_node_idx * 2) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], &tree[(r_node_idx * 2 + 1) * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)], r_node_idx, &tree[r_node_idx * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)]); if (ret != 0) { return ret; } } return 0; } /* Calculate a path from a leaf node of the Merkle tree to the root of the tree, * and return the full path. This function implements RFC8554 section 5.4.1, as * the Merkle path is the main component of an LMS signature. * * ctx The LMS private context, containing a parameter * set and private key material consisting of both * public and private OTS. * * leaf_node_id Which leaf node to calculate the path from. * * path The output path, which is H hash outputs. */ static int get_merkle_path(mbedtls_lms_private_t *ctx, unsigned int leaf_node_id, unsigned char *path) { const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type); unsigned int curr_node_id = leaf_node_id; unsigned int adjacent_node_id; unsigned char *tree = NULL; unsigned int height; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type), node_bytes); if (tree == NULL) { return MBEDTLS_ERR_LMS_ALLOC_FAILED; } ret = calculate_merkle_tree(ctx, tree); if (ret != 0) { goto exit; } for (height = 0; height < MBEDTLS_LMS_H_TREE_HEIGHT(ctx->params.type); height++) { adjacent_node_id = curr_node_id ^ 1; memcpy(&path[height * node_bytes], &tree[adjacent_node_id * node_bytes], node_bytes); curr_node_id >>= 1; } ret = 0; exit: mbedtls_zeroize_and_free(tree, node_bytes * (size_t) MERKLE_TREE_NODE_AM(ctx->params.type)); return ret; } void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx) { memset(ctx, 0, sizeof(*ctx)); } void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx) { unsigned int idx; if (ctx->have_private_key) { if (ctx->ots_private_keys != NULL) { for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { mbedtls_lmots_private_free(&ctx->ots_private_keys[idx]); } } if (ctx->ots_public_keys != NULL) { for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { mbedtls_lmots_public_free(&ctx->ots_public_keys[idx]); } } mbedtls_free(ctx->ots_private_keys); mbedtls_free(ctx->ots_public_keys); } mbedtls_platform_zeroize(ctx, sizeof(*ctx)); } int mbedtls_lms_generate_private_key(mbedtls_lms_private_t *ctx, mbedtls_lms_algorithm_type_t type, mbedtls_lmots_algorithm_type_t otstype, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *seed, size_t seed_size) { unsigned int idx = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ctx->params.type = type; ctx->params.otstype = otstype; ctx->have_private_key = 1; ret = f_rng(p_rng, ctx->params.I_key_identifier, MBEDTLS_LMOTS_I_KEY_ID_LEN); if (ret != 0) { goto exit; } /* Requires a cast to size_t to avoid an implicit cast warning on certain * platforms (particularly Windows) */ ctx->ots_private_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof(*ctx->ots_private_keys)); if (ctx->ots_private_keys == NULL) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } /* Requires a cast to size_t to avoid an implicit cast warning on certain * platforms (particularly Windows) */ ctx->ots_public_keys = mbedtls_calloc((size_t) MERKLE_TREE_LEAF_NODE_AM(ctx->params.type), sizeof(*ctx->ots_public_keys)); if (ctx->ots_public_keys == NULL) { ret = MBEDTLS_ERR_LMS_ALLOC_FAILED; goto exit; } for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { mbedtls_lmots_private_init(&ctx->ots_private_keys[idx]); mbedtls_lmots_public_init(&ctx->ots_public_keys[idx]); } for (idx = 0; idx < MERKLE_TREE_LEAF_NODE_AM(ctx->params.type); idx++) { ret = mbedtls_lmots_generate_private_key(&ctx->ots_private_keys[idx], otstype, ctx->params.I_key_identifier, idx, seed, seed_size); if (ret != 0) { goto exit; } ret = mbedtls_lmots_calculate_public_key(&ctx->ots_public_keys[idx], &ctx->ots_private_keys[idx]); if (ret != 0) { goto exit; } } ctx->q_next_usable_key = 0; exit: if (ret != 0) { mbedtls_lms_private_free(ctx); } return ret; } int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx, const mbedtls_lms_private_t *priv_ctx) { const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *tree = NULL; if (!priv_ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (priv_ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (priv_ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type), node_bytes); if (tree == NULL) { return MBEDTLS_ERR_LMS_ALLOC_FAILED; } memcpy(&ctx->params, &priv_ctx->params, sizeof(mbedtls_lmots_parameters_t)); ret = calculate_merkle_tree(priv_ctx, tree); if (ret != 0) { goto exit; } /* Root node is always at position 1, due to 1-based indexing */ memcpy(ctx->T_1_pub_key, &tree[node_bytes], node_bytes); ctx->have_public_key = 1; ret = 0; exit: mbedtls_zeroize_and_free(tree, node_bytes * (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type)); return ret; } int mbedtls_lms_sign(mbedtls_lms_private_t *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *msg, unsigned int msg_size, unsigned char *sig, size_t sig_size, size_t *sig_len) { uint32_t q_leaf_identifier; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (!ctx->have_private_key) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (sig_size < MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype)) { return MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL; } if (ctx->params.type != MBEDTLS_LMS_SHA256_M32_H10) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->params.otstype != MBEDTLS_LMOTS_SHA256_N32_W8) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } if (ctx->q_next_usable_key >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) { return MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS; } q_leaf_identifier = ctx->q_next_usable_key; /* This new value must _always_ be written back to the disk before the * signature is returned. */ ctx->q_next_usable_key += 1; if (MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) < SIG_OTS_SIG_OFFSET) { return MBEDTLS_ERR_LMS_BAD_INPUT_DATA; } ret = mbedtls_lmots_sign(&ctx->ots_private_keys[q_leaf_identifier], f_rng, p_rng, msg, msg_size, sig + SIG_OTS_SIG_OFFSET, MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype) - SIG_OTS_SIG_OFFSET, NULL); if (ret != 0) { return ret; } MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype)); MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET); ret = get_merkle_path(ctx, MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier, sig + SIG_PATH_OFFSET(ctx->params.otstype)); if (ret != 0) { return ret; } if (sig_len != NULL) { *sig_len = MBEDTLS_LMS_SIG_LEN(ctx->params.type, ctx->params.otstype); } return 0; } #endif /* defined(MBEDTLS_LMS_PRIVATE) */ #endif /* defined(MBEDTLS_LMS_C) */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/md.c000066400000000000000000000730461464416617300221120ustar00rootroot00000000000000/** * \file md.c * * \brief Generic message digest wrapper for Mbed TLS * * \author Adriaan de Jong * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" /* * Availability of functions in this module is controlled by two * feature macros: * - MBEDTLS_MD_C enables the whole module; * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing * most hash metadata (everything except string names); is it * automatically set whenever MBEDTLS_MD_C is defined. * * In this file, functions from MD_LIGHT are at the top, MD_C at the end. * * In the future we may want to change the contract of some functions * (behaviour with NULL arguments) depending on whether MD_C is defined or * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary. * * For these reasons, we're keeping MD_LIGHT internal for now. */ #if defined(MBEDTLS_MD_LIGHT) #include "mbedtls/md.h" #include "md_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/md5.h" #include "mbedtls/ripemd160.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/sha3.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "md_psa.h" #include "psa_util_internal.h" #endif #if defined(MBEDTLS_MD_SOME_PSA) #include "psa_crypto_core.h" #endif #include "mbedtls/platform.h" #include #if defined(MBEDTLS_FS_IO) #include #endif /* See comment above MBEDTLS_MD_MAX_SIZE in md.h */ #if defined(MBEDTLS_PSA_CRYPTO_C) && MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE #error "Internal error: MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE" #endif #if defined(MBEDTLS_MD_C) #define MD_INFO(type, out_size, block_size) type, out_size, block_size, #else #define MD_INFO(type, out_size, block_size) type, out_size, #endif #if defined(MBEDTLS_MD_CAN_MD5) static const mbedtls_md_info_t mbedtls_md5_info = { MD_INFO(MBEDTLS_MD_MD5, 16, 64) }; #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) static const mbedtls_md_info_t mbedtls_ripemd160_info = { MD_INFO(MBEDTLS_MD_RIPEMD160, 20, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA1) static const mbedtls_md_info_t mbedtls_sha1_info = { MD_INFO(MBEDTLS_MD_SHA1, 20, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA224) static const mbedtls_md_info_t mbedtls_sha224_info = { MD_INFO(MBEDTLS_MD_SHA224, 28, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA256) static const mbedtls_md_info_t mbedtls_sha256_info = { MD_INFO(MBEDTLS_MD_SHA256, 32, 64) }; #endif #if defined(MBEDTLS_MD_CAN_SHA384) static const mbedtls_md_info_t mbedtls_sha384_info = { MD_INFO(MBEDTLS_MD_SHA384, 48, 128) }; #endif #if defined(MBEDTLS_MD_CAN_SHA512) static const mbedtls_md_info_t mbedtls_sha512_info = { MD_INFO(MBEDTLS_MD_SHA512, 64, 128) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) static const mbedtls_md_info_t mbedtls_sha3_224_info = { MD_INFO(MBEDTLS_MD_SHA3_224, 28, 144) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) static const mbedtls_md_info_t mbedtls_sha3_256_info = { MD_INFO(MBEDTLS_MD_SHA3_256, 32, 136) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) static const mbedtls_md_info_t mbedtls_sha3_384_info = { MD_INFO(MBEDTLS_MD_SHA3_384, 48, 104) }; #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) static const mbedtls_md_info_t mbedtls_sha3_512_info = { MD_INFO(MBEDTLS_MD_SHA3_512, 64, 72) }; #endif const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type) { switch (md_type) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_MD_MD5: return &mbedtls_md5_info; #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) case MBEDTLS_MD_RIPEMD160: return &mbedtls_ripemd160_info; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_MD_SHA1: return &mbedtls_sha1_info; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_MD_SHA224: return &mbedtls_sha224_info; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return &mbedtls_sha256_info; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return &mbedtls_sha384_info; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_MD_SHA512: return &mbedtls_sha512_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) case MBEDTLS_MD_SHA3_224: return &mbedtls_sha3_224_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) case MBEDTLS_MD_SHA3_256: return &mbedtls_sha3_256_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) case MBEDTLS_MD_SHA3_384: return &mbedtls_sha3_384_info; #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) case MBEDTLS_MD_SHA3_512: return &mbedtls_sha3_512_info; #endif default: return NULL; } } #if defined(MBEDTLS_MD_SOME_PSA) static psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info) { switch (info->type) { #if defined(MBEDTLS_MD_MD5_VIA_PSA) case MBEDTLS_MD_MD5: return PSA_ALG_MD5; #endif #if defined(MBEDTLS_MD_RIPEMD160_VIA_PSA) case MBEDTLS_MD_RIPEMD160: return PSA_ALG_RIPEMD160; #endif #if defined(MBEDTLS_MD_SHA1_VIA_PSA) case MBEDTLS_MD_SHA1: return PSA_ALG_SHA_1; #endif #if defined(MBEDTLS_MD_SHA224_VIA_PSA) case MBEDTLS_MD_SHA224: return PSA_ALG_SHA_224; #endif #if defined(MBEDTLS_MD_SHA256_VIA_PSA) case MBEDTLS_MD_SHA256: return PSA_ALG_SHA_256; #endif #if defined(MBEDTLS_MD_SHA384_VIA_PSA) case MBEDTLS_MD_SHA384: return PSA_ALG_SHA_384; #endif #if defined(MBEDTLS_MD_SHA512_VIA_PSA) case MBEDTLS_MD_SHA512: return PSA_ALG_SHA_512; #endif #if defined(MBEDTLS_MD_SHA3_224_VIA_PSA) case MBEDTLS_MD_SHA3_224: return PSA_ALG_SHA3_224; #endif #if defined(MBEDTLS_MD_SHA3_256_VIA_PSA) case MBEDTLS_MD_SHA3_256: return PSA_ALG_SHA3_256; #endif #if defined(MBEDTLS_MD_SHA3_384_VIA_PSA) case MBEDTLS_MD_SHA3_384: return PSA_ALG_SHA3_384; #endif #if defined(MBEDTLS_MD_SHA3_512_VIA_PSA) case MBEDTLS_MD_SHA3_512: return PSA_ALG_SHA3_512; #endif default: return PSA_ALG_NONE; } } static int md_can_use_psa(const mbedtls_md_info_t *info) { psa_algorithm_t alg = psa_alg_of_md(info); if (alg == PSA_ALG_NONE) { return 0; } return psa_can_do_hash(alg); } #endif /* MBEDTLS_MD_SOME_PSA */ void mbedtls_md_init(mbedtls_md_context_t *ctx) { /* Note: this sets engine (if present) to MBEDTLS_MD_ENGINE_LEGACY */ memset(ctx, 0, sizeof(mbedtls_md_context_t)); } void mbedtls_md_free(mbedtls_md_context_t *ctx) { if (ctx == NULL || ctx->md_info == NULL) { return; } if (ctx->md_ctx != NULL) { #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { psa_hash_abort(ctx->md_ctx); } else #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: mbedtls_md5_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: mbedtls_ripemd160_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: mbedtls_sha1_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: mbedtls_sha256_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: mbedtls_sha256_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: mbedtls_sha512_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: mbedtls_sha512_free(ctx->md_ctx); break; #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: mbedtls_sha3_free(ctx->md_ctx); break; #endif default: /* Shouldn't happen */ break; } mbedtls_free(ctx->md_ctx); } #if defined(MBEDTLS_MD_C) if (ctx->hmac_ctx != NULL) { mbedtls_zeroize_and_free(ctx->hmac_ctx, 2 * ctx->md_info->block_size); } #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md_context_t)); } int mbedtls_md_clone(mbedtls_md_context_t *dst, const mbedtls_md_context_t *src) { if (dst == NULL || dst->md_info == NULL || src == NULL || src->md_info == NULL || dst->md_info != src->md_info) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #if defined(MBEDTLS_MD_SOME_PSA) if (src->engine != dst->engine) { /* This can happen with src set to legacy because PSA wasn't ready * yet, and dst to PSA because it became ready in the meantime. * We currently don't support that case (we'd need to re-allocate * md_ctx to the size of the appropriate MD context). */ return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; } if (src->engine == MBEDTLS_MD_ENGINE_PSA) { psa_status_t status = psa_hash_clone(src->md_ctx, dst->md_ctx); return mbedtls_md_error_from_psa(status); } #endif switch (src->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: mbedtls_md5_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: mbedtls_ripemd160_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: mbedtls_sha1_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: mbedtls_sha256_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: mbedtls_sha512_clone(dst->md_ctx, src->md_ctx); break; #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: mbedtls_sha3_clone(dst->md_ctx, src->md_ctx); break; #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } if (dst->hmac_ctx != NULL && src->hmac_ctx != NULL) memcpy(dst->hmac_ctx, src->hmac_ctx, 2 * src->md_info->block_size); return 0; } #define ALLOC(type) \ do { \ ctx->md_ctx = mbedtls_calloc(1, sizeof(mbedtls_##type##_context)); \ if (ctx->md_ctx == NULL) \ return MBEDTLS_ERR_MD_ALLOC_FAILED; \ mbedtls_##type##_init(ctx->md_ctx); \ } \ while (0) int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac) { #if defined(MBEDTLS_MD_C) if (ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } ctx->md_info = md_info; ctx->md_ctx = NULL; #if defined(MBEDTLS_MD_C) ctx->hmac_ctx = NULL; #else if (hmac != 0) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (md_can_use_psa(ctx->md_info)) { ctx->md_ctx = mbedtls_calloc(1, sizeof(psa_hash_operation_t)); if (ctx->md_ctx == NULL) { return MBEDTLS_ERR_MD_ALLOC_FAILED; } ctx->engine = MBEDTLS_MD_ENGINE_PSA; } else #endif switch (md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: ALLOC(md5); break; #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: ALLOC(ripemd160); break; #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: ALLOC(sha1); break; #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: ALLOC(sha256); break; #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: ALLOC(sha256); break; #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: ALLOC(sha512); break; #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: ALLOC(sha512); break; #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: ALLOC(sha3); break; #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #if defined(MBEDTLS_MD_C) if (hmac != 0) { ctx->hmac_ctx = mbedtls_calloc(2, md_info->block_size); if (ctx->hmac_ctx == NULL) { mbedtls_md_free(ctx); return MBEDTLS_ERR_MD_ALLOC_FAILED; } } #endif return 0; } #undef ALLOC int mbedtls_md_starts(mbedtls_md_context_t *ctx) { #if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { psa_algorithm_t alg = psa_alg_of_md(ctx->md_info); psa_hash_abort(ctx->md_ctx); psa_status_t status = psa_hash_setup(ctx->md_ctx, alg); return mbedtls_md_error_from_psa(status); } #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1_starts(ctx->md_ctx); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256_starts(ctx->md_ctx, 1); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256_starts(ctx->md_ctx, 0); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512_starts(ctx->md_ctx, 1); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512_starts(ctx->md_ctx, 0); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_224); case MBEDTLS_MD_SHA3_256: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_256); case MBEDTLS_MD_SHA3_384: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_384); case MBEDTLS_MD_SHA3_512: return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_512); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen) { #if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { psa_status_t status = psa_hash_update(ctx->md_ctx, input, ilen); return mbedtls_md_error_from_psa(status); } #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512_update(ctx->md_ctx, input, ilen); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: return mbedtls_sha3_update(ctx->md_ctx, input, ilen); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output) { #if defined(MBEDTLS_MD_C) if (ctx == NULL || ctx->md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #endif #if defined(MBEDTLS_MD_SOME_PSA) if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) { size_t size = ctx->md_info->size; psa_status_t status = psa_hash_finish(ctx->md_ctx, output, size, &size); return mbedtls_md_error_from_psa(status); } #endif switch (ctx->md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512_finish(ctx->md_ctx, output); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: case MBEDTLS_MD_SHA3_256: case MBEDTLS_MD_SHA3_384: case MBEDTLS_MD_SHA3_512: return mbedtls_sha3_finish(ctx->md_ctx, output, ctx->md_info->size); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, unsigned char *output) { if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } #if defined(MBEDTLS_MD_SOME_PSA) if (md_can_use_psa(md_info)) { size_t size = md_info->size; psa_status_t status = psa_hash_compute(psa_alg_of_md(md_info), input, ilen, output, size, &size); return mbedtls_md_error_from_psa(status); } #endif switch (md_info->type) { #if defined(MBEDTLS_MD5_C) case MBEDTLS_MD_MD5: return mbedtls_md5(input, ilen, output); #endif #if defined(MBEDTLS_RIPEMD160_C) case MBEDTLS_MD_RIPEMD160: return mbedtls_ripemd160(input, ilen, output); #endif #if defined(MBEDTLS_SHA1_C) case MBEDTLS_MD_SHA1: return mbedtls_sha1(input, ilen, output); #endif #if defined(MBEDTLS_SHA224_C) case MBEDTLS_MD_SHA224: return mbedtls_sha256(input, ilen, output, 1); #endif #if defined(MBEDTLS_SHA256_C) case MBEDTLS_MD_SHA256: return mbedtls_sha256(input, ilen, output, 0); #endif #if defined(MBEDTLS_SHA384_C) case MBEDTLS_MD_SHA384: return mbedtls_sha512(input, ilen, output, 1); #endif #if defined(MBEDTLS_SHA512_C) case MBEDTLS_MD_SHA512: return mbedtls_sha512(input, ilen, output, 0); #endif #if defined(MBEDTLS_SHA3_C) case MBEDTLS_MD_SHA3_224: return mbedtls_sha3(MBEDTLS_SHA3_224, input, ilen, output, md_info->size); case MBEDTLS_MD_SHA3_256: return mbedtls_sha3(MBEDTLS_SHA3_256, input, ilen, output, md_info->size); case MBEDTLS_MD_SHA3_384: return mbedtls_sha3(MBEDTLS_SHA3_384, input, ilen, output, md_info->size); case MBEDTLS_MD_SHA3_512: return mbedtls_sha3(MBEDTLS_SHA3_512, input, ilen, output, md_info->size); #endif default: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } } unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info) { if (md_info == NULL) { return 0; } return md_info->size; } mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info) { if (md_info == NULL) { return MBEDTLS_MD_NONE; } return md_info->type; } #if defined(MBEDTLS_PSA_CRYPTO_C) int mbedtls_md_error_from_psa(psa_status_t status) { return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors, psa_generic_status_to_mbedtls); } #endif /* MBEDTLS_PSA_CRYPTO_C */ /************************************************************************ * Functions above this separator are part of MBEDTLS_MD_LIGHT, * * functions below are only available when MBEDTLS_MD_C is set. * ************************************************************************/ #if defined(MBEDTLS_MD_C) /* * Reminder: update profiles in x509_crt.c when adding a new hash! */ static const int supported_digests[] = { #if defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_MD_SHA512, #endif #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_MD_SHA384, #endif #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_MD_SHA256, #endif #if defined(MBEDTLS_MD_CAN_SHA224) MBEDTLS_MD_SHA224, #endif #if defined(MBEDTLS_MD_CAN_SHA1) MBEDTLS_MD_SHA1, #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) MBEDTLS_MD_RIPEMD160, #endif #if defined(MBEDTLS_MD_CAN_MD5) MBEDTLS_MD_MD5, #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) MBEDTLS_MD_SHA3_224, #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) MBEDTLS_MD_SHA3_256, #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) MBEDTLS_MD_SHA3_384, #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) MBEDTLS_MD_SHA3_512, #endif MBEDTLS_MD_NONE }; const int *mbedtls_md_list(void) { return supported_digests; } typedef struct { const char *md_name; mbedtls_md_type_t md_type; } md_name_entry; static const md_name_entry md_names[] = { #if defined(MBEDTLS_MD_CAN_MD5) { "MD5", MBEDTLS_MD_MD5 }, #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) { "RIPEMD160", MBEDTLS_MD_RIPEMD160 }, #endif #if defined(MBEDTLS_MD_CAN_SHA1) { "SHA1", MBEDTLS_MD_SHA1 }, { "SHA", MBEDTLS_MD_SHA1 }, // compatibility fallback #endif #if defined(MBEDTLS_MD_CAN_SHA224) { "SHA224", MBEDTLS_MD_SHA224 }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { "SHA256", MBEDTLS_MD_SHA256 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { "SHA384", MBEDTLS_MD_SHA384 }, #endif #if defined(MBEDTLS_MD_CAN_SHA512) { "SHA512", MBEDTLS_MD_SHA512 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) { "SHA3-224", MBEDTLS_MD_SHA3_224 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) { "SHA3-256", MBEDTLS_MD_SHA3_256 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) { "SHA3-384", MBEDTLS_MD_SHA3_384 }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) { "SHA3-512", MBEDTLS_MD_SHA3_512 }, #endif { NULL, MBEDTLS_MD_NONE }, }; const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name) { if (NULL == md_name) { return NULL; } const md_name_entry *entry = md_names; while (entry->md_name != NULL && strcmp(entry->md_name, md_name) != 0) { ++entry; } return mbedtls_md_info_from_type(entry->md_type); } const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info) { if (md_info == NULL) { return NULL; } const md_name_entry *entry = md_names; while (entry->md_type != MBEDTLS_MD_NONE && entry->md_type != md_info->type) { ++entry; } return entry->md_name; } const mbedtls_md_info_t *mbedtls_md_info_from_ctx( const mbedtls_md_context_t *ctx) { if (ctx == NULL) { return NULL; } return ctx->MBEDTLS_PRIVATE(md_info); } #if defined(MBEDTLS_FS_IO) int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; FILE *f; size_t n; mbedtls_md_context_t ctx; unsigned char buf[1024]; if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_MD_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) { goto cleanup; } if ((ret = mbedtls_md_starts(&ctx)) != 0) { goto cleanup; } while ((n = fread(buf, 1, sizeof(buf), f)) > 0) { if ((ret = mbedtls_md_update(&ctx, buf, n)) != 0) { goto cleanup; } } if (ferror(f) != 0) { ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; } else { ret = mbedtls_md_finish(&ctx, output); } cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); fclose(f); mbedtls_md_free(&ctx); return ret; } #endif /* MBEDTLS_FS_IO */ int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char sum[MBEDTLS_MD_MAX_SIZE]; unsigned char *ipad, *opad; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } if (keylen > (size_t) ctx->md_info->block_size) { if ((ret = mbedtls_md_starts(ctx)) != 0) { goto cleanup; } if ((ret = mbedtls_md_update(ctx, key, keylen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_finish(ctx, sum)) != 0) { goto cleanup; } keylen = ctx->md_info->size; key = sum; } ipad = (unsigned char *) ctx->hmac_ctx; opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; memset(ipad, 0x36, ctx->md_info->block_size); memset(opad, 0x5C, ctx->md_info->block_size); mbedtls_xor(ipad, ipad, key, keylen); mbedtls_xor(opad, opad, key, keylen); if ((ret = mbedtls_md_starts(ctx)) != 0) { goto cleanup; } if ((ret = mbedtls_md_update(ctx, ipad, ctx->md_info->block_size)) != 0) { goto cleanup; } cleanup: mbedtls_platform_zeroize(sum, sizeof(sum)); return ret; } int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen) { if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } return mbedtls_md_update(ctx, input, ilen); } int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; unsigned char *opad; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; if ((ret = mbedtls_md_finish(ctx, tmp)) != 0) { return ret; } if ((ret = mbedtls_md_starts(ctx)) != 0) { return ret; } if ((ret = mbedtls_md_update(ctx, opad, ctx->md_info->block_size)) != 0) { return ret; } if ((ret = mbedtls_md_update(ctx, tmp, ctx->md_info->size)) != 0) { return ret; } return mbedtls_md_finish(ctx, output); } int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *ipad; if (ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } ipad = (unsigned char *) ctx->hmac_ctx; if ((ret = mbedtls_md_starts(ctx)) != 0) { return ret; } return mbedtls_md_update(ctx, ipad, ctx->md_info->block_size); } int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, const unsigned char *input, size_t ilen, unsigned char *output) { mbedtls_md_context_t ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (md_info == NULL) { return MBEDTLS_ERR_MD_BAD_INPUT_DATA; } mbedtls_md_init(&ctx); if ((ret = mbedtls_md_setup(&ctx, md_info, 1)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_starts(&ctx, key, keylen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_update(&ctx, input, ilen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_finish(&ctx, output)) != 0) { goto cleanup; } cleanup: mbedtls_md_free(&ctx); return ret; } #endif /* MBEDTLS_MD_C */ #endif /* MBEDTLS_MD_LIGHT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/md5.c000066400000000000000000000304011464416617300221630ustar00rootroot00000000000000/* * RFC 1321 compliant MD5 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The MD5 algorithm was designed by Ron Rivest in 1991. * * http://www.ietf.org/rfc/rfc1321.txt */ #include "common.h" #if defined(MBEDTLS_MD5_C) #include "mbedtls/md5.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_MD5_ALT) void mbedtls_md5_init(mbedtls_md5_context *ctx) { memset(ctx, 0, sizeof(mbedtls_md5_context)); } void mbedtls_md5_free(mbedtls_md5_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context)); } void mbedtls_md5_clone(mbedtls_md5_context *dst, const mbedtls_md5_context *src) { *dst = *src; } /* * MD5 context setup */ int mbedtls_md5_starts(mbedtls_md5_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; return 0; } #if !defined(MBEDTLS_MD5_PROCESS_ALT) int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[64]) { struct { uint32_t X[16], A, B, C, D; } local; local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0); local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4); local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8); local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12); local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16); local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20); local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24); local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28); local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32); local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36); local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40); local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44); local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48); local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52); local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56); local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60); #define S(x, n) \ (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) #define P(a, b, c, d, k, s, t) \ do \ { \ (a) += F((b), (c), (d)) + local.X[(k)] + (t); \ (a) = S((a), (s)) + (b); \ } while (0) local.A = ctx->state[0]; local.B = ctx->state[1]; local.C = ctx->state[2]; local.D = ctx->state[3]; #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) P(local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478); P(local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756); P(local.C, local.D, local.A, local.B, 2, 17, 0x242070DB); P(local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE); P(local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF); P(local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A); P(local.C, local.D, local.A, local.B, 6, 17, 0xA8304613); P(local.B, local.C, local.D, local.A, 7, 22, 0xFD469501); P(local.A, local.B, local.C, local.D, 8, 7, 0x698098D8); P(local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF); P(local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1); P(local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE); P(local.A, local.B, local.C, local.D, 12, 7, 0x6B901122); P(local.D, local.A, local.B, local.C, 13, 12, 0xFD987193); P(local.C, local.D, local.A, local.B, 14, 17, 0xA679438E); P(local.B, local.C, local.D, local.A, 15, 22, 0x49B40821); #undef F #define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) P(local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562); P(local.D, local.A, local.B, local.C, 6, 9, 0xC040B340); P(local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51); P(local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA); P(local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D); P(local.D, local.A, local.B, local.C, 10, 9, 0x02441453); P(local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681); P(local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8); P(local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6); P(local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6); P(local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87); P(local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED); P(local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905); P(local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8); P(local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9); P(local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A); #undef F #define F(x, y, z) ((x) ^ (y) ^ (z)) P(local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942); P(local.D, local.A, local.B, local.C, 8, 11, 0x8771F681); P(local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122); P(local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C); P(local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44); P(local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9); P(local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60); P(local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70); P(local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6); P(local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA); P(local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085); P(local.B, local.C, local.D, local.A, 6, 23, 0x04881D05); P(local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039); P(local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5); P(local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8); P(local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665); #undef F #define F(x, y, z) ((y) ^ ((x) | ~(z))) P(local.A, local.B, local.C, local.D, 0, 6, 0xF4292244); P(local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97); P(local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7); P(local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039); P(local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3); P(local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92); P(local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D); P(local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1); P(local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F); P(local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0); P(local.C, local.D, local.A, local.B, 6, 15, 0xA3014314); P(local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1); P(local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82); P(local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235); P(local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB); P(local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391); #undef F ctx->state[0] += local.A; ctx->state[1] += local.B; ctx->state[2] += local.C; ctx->state[3] += local.D; /* Zeroise variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_MD5_PROCESS_ALT */ /* * MD5 process buffer */ int mbedtls_md5_update(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= 64) { if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) { return ret; } input += 64; ilen -= 64; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * MD5 final digest */ int mbedtls_md5_finish(mbedtls_md5_context *ctx, unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ used = ctx->total[0] & 0x3F; ctx->buffer[used++] = 0x80; if (used <= 56) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, 64 - used); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 56); } /* * Add message length */ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_LE(low, ctx->buffer, 56); MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60); if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); ret = 0; exit: mbedtls_md5_free(ctx); return ret; } #endif /* !MBEDTLS_MD5_ALT */ /* * output = MD5( input buffer ) */ int mbedtls_md5(const unsigned char *input, size_t ilen, unsigned char output[16]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md5_context ctx; mbedtls_md5_init(&ctx); if ((ret = mbedtls_md5_starts(&ctx)) != 0) { goto exit; } if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_md5_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * RFC 1321 test vectors */ static const unsigned char md5_test_buf[7][81] = { { "" }, { "a" }, { "abc" }, { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } }; static const size_t md5_test_buflen[7] = { 0, 1, 3, 14, 26, 62, 80 }; static const unsigned char md5_test_sum[7][16] = { { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } }; /* * Checkup routine */ int mbedtls_md5_self_test(int verbose) { int i, ret = 0; unsigned char md5sum[16]; for (i = 0; i < 7; i++) { if (verbose != 0) { mbedtls_printf(" MD5 test #%d: ", i + 1); } ret = mbedtls_md5(md5_test_buf[i], md5_test_buflen[i], md5sum); if (ret != 0) { goto fail; } if (memcmp(md5sum, md5_test_sum[i], 16) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_MD5_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/md_psa.h000066400000000000000000000012211464416617300227440ustar00rootroot00000000000000/** * Translation between MD and PSA identifiers (algorithms, errors). * * Note: this internal module will go away when everything becomes based on * PSA Crypto; it is a helper for the transition period. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_PSA_H #define MBEDTLS_MD_PSA_H #include "common.h" #include "mbedtls/md.h" #include "psa/crypto.h" /** Convert PSA status to MD error code. * * \param status PSA status. * * \return The corresponding MD error code, */ int mbedtls_md_error_from_psa(psa_status_t status); #endif /* MBEDTLS_MD_PSA_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/md_wrap.h000066400000000000000000000016001464416617300231330ustar00rootroot00000000000000/** * \file md_wrap.h * * \brief Message digest wrappers. * * \warning This in an internal header. Do not include directly. * * \author Adriaan de Jong */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_MD_WRAP_H #define MBEDTLS_MD_WRAP_H #include "mbedtls/build_info.h" #include "mbedtls/md.h" #ifdef __cplusplus extern "C" { #endif /** * Message digest information. * Allows message digest functions to be called in a generic way. */ struct mbedtls_md_info_t { /** Digest identifier */ mbedtls_md_type_t type; /** Output length of the digest function in bytes */ unsigned char size; #if defined(MBEDTLS_MD_C) /** Block length of the digest function in bytes */ unsigned char block_size; #endif }; #ifdef __cplusplus } #endif #endif /* MBEDTLS_MD_WRAP_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c000066400000000000000000000442351464416617300255230ustar00rootroot00000000000000/* * Buffer-based memory allocator * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #include "mbedtls/memory_buffer_alloc.h" /* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C is dependent upon MBEDTLS_PLATFORM_C */ #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_MEMORY_BACKTRACE) #include #endif #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #define MAGIC1 0xFF00AA55 #define MAGIC2 0xEE119966 #define MAX_BT 20 typedef struct _memory_header memory_header; struct _memory_header { size_t magic1; size_t size; size_t alloc; memory_header *prev; memory_header *next; memory_header *prev_free; memory_header *next_free; #if defined(MBEDTLS_MEMORY_BACKTRACE) char **trace; size_t trace_count; #endif size_t magic2; }; typedef struct { unsigned char *buf; size_t len; memory_header *first; memory_header *first_free; int verify; #if defined(MBEDTLS_MEMORY_DEBUG) size_t alloc_count; size_t free_count; size_t total_used; size_t maximum_used; size_t header_count; size_t maximum_header_count; #endif #if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t mutex; #endif } buffer_alloc_ctx; static buffer_alloc_ctx heap; #if defined(MBEDTLS_MEMORY_DEBUG) static void debug_header(memory_header *hdr) { #if defined(MBEDTLS_MEMORY_BACKTRACE) size_t i; #endif mbedtls_fprintf(stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " "ALLOC(%zu), SIZE(%10zu)\n", (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, hdr->alloc, hdr->size); mbedtls_fprintf(stderr, " FPREV(%10zu), FNEXT(%10zu)\n", (size_t) hdr->prev_free, (size_t) hdr->next_free); #if defined(MBEDTLS_MEMORY_BACKTRACE) mbedtls_fprintf(stderr, "TRACE: \n"); for (i = 0; i < hdr->trace_count; i++) { mbedtls_fprintf(stderr, "%s\n", hdr->trace[i]); } mbedtls_fprintf(stderr, "\n"); #endif } static void debug_chain(void) { memory_header *cur = heap.first; mbedtls_fprintf(stderr, "\nBlock list\n"); while (cur != NULL) { debug_header(cur); cur = cur->next; } mbedtls_fprintf(stderr, "Free list\n"); cur = heap.first_free; while (cur != NULL) { debug_header(cur); cur = cur->next_free; } } #endif /* MBEDTLS_MEMORY_DEBUG */ static int verify_header(memory_header *hdr) { if (hdr->magic1 != MAGIC1) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: MAGIC1 mismatch\n"); #endif return 1; } if (hdr->magic2 != MAGIC2) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: MAGIC2 mismatch\n"); #endif return 1; } if (hdr->alloc > 1) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: alloc has illegal value\n"); #endif return 1; } if (hdr->prev != NULL && hdr->prev == hdr->next) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: prev == next\n"); #endif return 1; } if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: prev_free == next_free\n"); #endif return 1; } return 0; } static int verify_chain(void) { memory_header *prv = heap.first, *cur; if (prv == NULL || verify_header(prv) != 0) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification of first header " "failed\n"); #endif return 1; } if (heap.first->prev != NULL) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification failed: " "first->prev != NULL\n"); #endif return 1; } cur = heap.first->next; while (cur != NULL) { if (verify_header(cur) != 0) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification of header " "failed\n"); #endif return 1; } if (cur->prev != prv) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: verification failed: " "cur->prev != prv\n"); #endif return 1; } prv = cur; cur = cur->next; } return 0; } static void *buffer_alloc_calloc(size_t n, size_t size) { memory_header *new, *cur = heap.first_free; unsigned char *p; void *ret; size_t original_len, len; #if defined(MBEDTLS_MEMORY_BACKTRACE) void *trace_buffer[MAX_BT]; size_t trace_cnt; #endif if (heap.buf == NULL || heap.first == NULL) { return NULL; } original_len = len = n * size; if (n == 0 || size == 0 || len / n != size) { return NULL; } else if (len > (size_t) -MBEDTLS_MEMORY_ALIGN_MULTIPLE) { return NULL; } if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) { len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; } // Find block that fits // while (cur != NULL) { if (cur->size >= len) { break; } cur = cur->next_free; } if (cur == NULL) { return NULL; } if (cur->alloc != 0) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: block in free_list but allocated " "data\n"); #endif mbedtls_exit(1); } #if defined(MBEDTLS_MEMORY_DEBUG) heap.alloc_count++; #endif // Found location, split block if > memory_header + 4 room left // if (cur->size - len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) { cur->alloc = 1; // Remove from free_list // if (cur->prev_free != NULL) { cur->prev_free->next_free = cur->next_free; } else { heap.first_free = cur->next_free; } if (cur->next_free != NULL) { cur->next_free->prev_free = cur->prev_free; } cur->prev_free = NULL; cur->next_free = NULL; #if defined(MBEDTLS_MEMORY_DEBUG) heap.total_used += cur->size; if (heap.total_used > heap.maximum_used) { heap.maximum_used = heap.total_used; } #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) trace_cnt = backtrace(trace_buffer, MAX_BT); cur->trace = backtrace_symbols(trace_buffer, trace_cnt); cur->trace_count = trace_cnt; #endif if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) { mbedtls_exit(1); } ret = (unsigned char *) cur + sizeof(memory_header); memset(ret, 0, original_len); return ret; } p = ((unsigned char *) cur) + sizeof(memory_header) + len; new = (memory_header *) p; new->size = cur->size - len - sizeof(memory_header); new->alloc = 0; new->prev = cur; new->next = cur->next; #if defined(MBEDTLS_MEMORY_BACKTRACE) new->trace = NULL; new->trace_count = 0; #endif new->magic1 = MAGIC1; new->magic2 = MAGIC2; if (new->next != NULL) { new->next->prev = new; } // Replace cur with new in free_list // new->prev_free = cur->prev_free; new->next_free = cur->next_free; if (new->prev_free != NULL) { new->prev_free->next_free = new; } else { heap.first_free = new; } if (new->next_free != NULL) { new->next_free->prev_free = new; } cur->alloc = 1; cur->size = len; cur->next = new; cur->prev_free = NULL; cur->next_free = NULL; #if defined(MBEDTLS_MEMORY_DEBUG) heap.header_count++; if (heap.header_count > heap.maximum_header_count) { heap.maximum_header_count = heap.header_count; } heap.total_used += cur->size; if (heap.total_used > heap.maximum_used) { heap.maximum_used = heap.total_used; } #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) trace_cnt = backtrace(trace_buffer, MAX_BT); cur->trace = backtrace_symbols(trace_buffer, trace_cnt); cur->trace_count = trace_cnt; #endif if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) { mbedtls_exit(1); } ret = (unsigned char *) cur + sizeof(memory_header); memset(ret, 0, original_len); return ret; } static void buffer_alloc_free(void *ptr) { memory_header *hdr, *old = NULL; unsigned char *p = (unsigned char *) ptr; if (ptr == NULL || heap.buf == NULL || heap.first == NULL) { return; } if (p < heap.buf || p >= heap.buf + heap.len) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: mbedtls_free() outside of managed " "space\n"); #endif mbedtls_exit(1); } p -= sizeof(memory_header); hdr = (memory_header *) p; if (verify_header(hdr) != 0) { mbedtls_exit(1); } if (hdr->alloc != 1) { #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_fprintf(stderr, "FATAL: mbedtls_free() on unallocated " "data\n"); #endif mbedtls_exit(1); } hdr->alloc = 0; #if defined(MBEDTLS_MEMORY_DEBUG) heap.free_count++; heap.total_used -= hdr->size; #endif #if defined(MBEDTLS_MEMORY_BACKTRACE) free(hdr->trace); hdr->trace = NULL; hdr->trace_count = 0; #endif // Regroup with block before // if (hdr->prev != NULL && hdr->prev->alloc == 0) { #if defined(MBEDTLS_MEMORY_DEBUG) heap.header_count--; #endif hdr->prev->size += sizeof(memory_header) + hdr->size; hdr->prev->next = hdr->next; old = hdr; hdr = hdr->prev; if (hdr->next != NULL) { hdr->next->prev = hdr; } memset(old, 0, sizeof(memory_header)); } // Regroup with block after // if (hdr->next != NULL && hdr->next->alloc == 0) { #if defined(MBEDTLS_MEMORY_DEBUG) heap.header_count--; #endif hdr->size += sizeof(memory_header) + hdr->next->size; old = hdr->next; hdr->next = hdr->next->next; if (hdr->prev_free != NULL || hdr->next_free != NULL) { if (hdr->prev_free != NULL) { hdr->prev_free->next_free = hdr->next_free; } else { heap.first_free = hdr->next_free; } if (hdr->next_free != NULL) { hdr->next_free->prev_free = hdr->prev_free; } } hdr->prev_free = old->prev_free; hdr->next_free = old->next_free; if (hdr->prev_free != NULL) { hdr->prev_free->next_free = hdr; } else { heap.first_free = hdr; } if (hdr->next_free != NULL) { hdr->next_free->prev_free = hdr; } if (hdr->next != NULL) { hdr->next->prev = hdr; } memset(old, 0, sizeof(memory_header)); } // Prepend to free_list if we have not merged // (Does not have to stay in same order as prev / next list) // if (old == NULL) { hdr->next_free = heap.first_free; if (heap.first_free != NULL) { heap.first_free->prev_free = hdr; } heap.first_free = hdr; } if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) { mbedtls_exit(1); } } void mbedtls_memory_buffer_set_verify(int verify) { heap.verify = verify; } int mbedtls_memory_buffer_alloc_verify(void) { return verify_chain(); } #if defined(MBEDTLS_MEMORY_DEBUG) void mbedtls_memory_buffer_alloc_status(void) { mbedtls_fprintf(stderr, "Current use: %zu blocks / %zu bytes, max: %zu blocks / " "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", heap.header_count, heap.total_used, heap.maximum_header_count, heap.maximum_used, heap.maximum_header_count * sizeof(memory_header) + heap.maximum_used, heap.alloc_count, heap.free_count); if (heap.first->next == NULL) { mbedtls_fprintf(stderr, "All memory de-allocated in stack buffer\n"); } else { mbedtls_fprintf(stderr, "Memory currently allocated:\n"); debug_chain(); } } void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count) { *alloc_count = heap.alloc_count; *free_count = heap.free_count; } void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks) { *max_used = heap.maximum_used; *max_blocks = heap.maximum_header_count; } void mbedtls_memory_buffer_alloc_max_reset(void) { heap.maximum_used = 0; heap.maximum_header_count = 0; } void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks) { *cur_used = heap.total_used; *cur_blocks = heap.header_count; } #endif /* MBEDTLS_MEMORY_DEBUG */ #if defined(MBEDTLS_THREADING_C) static void *buffer_alloc_calloc_mutexed(size_t n, size_t size) { void *buf; if (mbedtls_mutex_lock(&heap.mutex) != 0) { return NULL; } buf = buffer_alloc_calloc(n, size); if (mbedtls_mutex_unlock(&heap.mutex)) { return NULL; } return buf; } static void buffer_alloc_free_mutexed(void *ptr) { /* We have no good option here, but corrupting the heap seems * worse than losing memory. */ if (mbedtls_mutex_lock(&heap.mutex)) { return; } buffer_alloc_free(ptr); (void) mbedtls_mutex_unlock(&heap.mutex); } #endif /* MBEDTLS_THREADING_C */ void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len) { memset(&heap, 0, sizeof(buffer_alloc_ctx)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&heap.mutex); mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed, buffer_alloc_free_mutexed); #else mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free); #endif if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) { return; } else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) { /* Adjust len first since buf is used in the computation */ len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; } memset(buf, 0, len); heap.buf = buf; heap.len = len; heap.first = (memory_header *) buf; heap.first->size = len - sizeof(memory_header); heap.first->magic1 = MAGIC1; heap.first->magic2 = MAGIC2; heap.first_free = heap.first; } void mbedtls_memory_buffer_alloc_free(void) { #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&heap.mutex); #endif mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx)); } #if defined(MBEDTLS_SELF_TEST) static int check_pointer(void *p) { if (p == NULL) { return -1; } if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) { return -1; } return 0; } static int check_all_free(void) { if ( #if defined(MBEDTLS_MEMORY_DEBUG) heap.total_used != 0 || #endif heap.first != heap.first_free || (void *) heap.first != (void *) heap.buf) { return -1; } return 0; } #define TEST_ASSERT(condition) \ if (!(condition)) \ { \ if (verbose != 0) \ mbedtls_printf("failed\n"); \ \ ret = 1; \ goto cleanup; \ } int mbedtls_memory_buffer_alloc_self_test(int verbose) { unsigned char buf[1024]; unsigned char *p, *q, *r, *end; int ret = 0; if (verbose != 0) { mbedtls_printf(" MBA test #1 (basic alloc-free cycle): "); } mbedtls_memory_buffer_alloc_init(buf, sizeof(buf)); p = mbedtls_calloc(1, 1); q = mbedtls_calloc(1, 128); r = mbedtls_calloc(1, 16); TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0 && check_pointer(r) == 0); mbedtls_free(r); mbedtls_free(q); mbedtls_free(p); TEST_ASSERT(check_all_free() == 0); /* Memorize end to compare with the next test */ end = heap.buf + heap.len; mbedtls_memory_buffer_alloc_free(); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" MBA test #2 (buf not aligned): "); } mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1); TEST_ASSERT(heap.buf + heap.len == end); p = mbedtls_calloc(1, 1); q = mbedtls_calloc(1, 128); r = mbedtls_calloc(1, 16); TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0 && check_pointer(r) == 0); mbedtls_free(r); mbedtls_free(q); mbedtls_free(p); TEST_ASSERT(check_all_free() == 0); mbedtls_memory_buffer_alloc_free(); if (verbose != 0) { mbedtls_printf("passed\n"); } if (verbose != 0) { mbedtls_printf(" MBA test #3 (full): "); } mbedtls_memory_buffer_alloc_init(buf, sizeof(buf)); p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header)); TEST_ASSERT(check_pointer(p) == 0); TEST_ASSERT(mbedtls_calloc(1, 1) == NULL); mbedtls_free(p); p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16); q = mbedtls_calloc(1, 16); TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0); TEST_ASSERT(mbedtls_calloc(1, 1) == NULL); mbedtls_free(q); TEST_ASSERT(mbedtls_calloc(1, 17) == NULL); mbedtls_free(p); TEST_ASSERT(check_all_free() == 0); mbedtls_memory_buffer_alloc_free(); if (verbose != 0) { mbedtls_printf("passed\n"); } cleanup: mbedtls_memory_buffer_alloc_free(); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/net_sockets.c000066400000000000000000000431421464416617300240250ustar00rootroot00000000000000/* * TCP/IP or UDP/IP networking functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must * be set before mbedtls_config.h, which pulls in glibc's features.h indirectly. * Harmless on other platforms. */ #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200112L #endif #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE 600 /* sockaddr_storage */ #endif #include "common.h" #if defined(MBEDTLS_NET_C) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h" #endif #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/error.h" #include #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) #define IS_EINTR(ret) ((ret) == WSAEINTR) #include #include #include #if (_WIN32_WINNT < 0x0501) #include #endif #if defined(_MSC_VER) #if defined(_WIN32_WCE) #pragma comment( lib, "ws2.lib" ) #else #pragma comment( lib, "ws2_32.lib" ) #endif #endif /* _MSC_VER */ #define read(fd, buf, len) recv(fd, (char *) (buf), (int) (len), 0) #define write(fd, buf, len) send(fd, (char *) (buf), (int) (len), 0) #define close(fd) closesocket(fd) static int wsa_init_done = 0; #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ #include #include #include #include #include #include #include #include #include #include #define IS_EINTR(ret) ((ret) == EINTR) #define SOCKET int #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* Some MS functions want int and MSVC warns if we pass size_t, * but the standard functions use socklen_t, so cast only for MSVC */ #if defined(_MSC_VER) #define MSVC_INT_CAST (int) #else #define MSVC_INT_CAST #endif #include #if defined(MBEDTLS_HAVE_TIME) #include #endif #include /* * Prepare for using the sockets interface */ static int net_prepare(void) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) WSADATA wsaData; if (wsa_init_done == 0) { if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { return MBEDTLS_ERR_NET_SOCKET_FAILED; } wsa_init_done = 1; } #else #if !defined(EFIX64) && !defined(EFI32) signal(SIGPIPE, SIG_IGN); #endif #endif return 0; } /* * Return 0 if the file descriptor is valid, an error otherwise. * If for_select != 0, check whether the file descriptor is within the range * allowed for fd_set used for the FD_xxx macros and the select() function. */ static int check_fd(int fd, int for_select) { if (fd < 0) { return MBEDTLS_ERR_NET_INVALID_CONTEXT; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) (void) for_select; #else /* A limitation of select() is that it only works with file descriptors * that are strictly less than FD_SETSIZE. This is a limitation of the * fd_set type. Error out early, because attempting to call FD_SET on a * large file descriptor is a buffer overflow on typical platforms. */ if (for_select && fd >= FD_SETSIZE) { return MBEDTLS_ERR_NET_POLL_FAILED; } #endif return 0; } /* * Initialize a context */ void mbedtls_net_init(mbedtls_net_context *ctx) { ctx->fd = -1; } /* * Initiate a TCP connection with host:port and the given protocol */ int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host, const char *port, int proto) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; struct addrinfo hints, *addr_list, *cur; if ((ret = net_prepare()) != 0) { return ret; } /* Do name resolution with both IPv6 and IPv4 */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; if (getaddrinfo(host, port, &hints, &addr_list) != 0) { return MBEDTLS_ERR_NET_UNKNOWN_HOST; } /* Try the sockaddrs until a connection succeeds */ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; for (cur = addr_list; cur != NULL; cur = cur->ai_next) { ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); if (ctx->fd < 0) { ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) { ret = 0; break; } close(ctx->fd); ret = MBEDTLS_ERR_NET_CONNECT_FAILED; } freeaddrinfo(addr_list); return ret; } /* * Create a listening socket on bind_ip:port */ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto) { int n, ret; struct addrinfo hints, *addr_list, *cur; if ((ret = net_prepare()) != 0) { return ret; } /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; if (bind_ip == NULL) { hints.ai_flags = AI_PASSIVE; } if (getaddrinfo(bind_ip, port, &hints, &addr_list) != 0) { return MBEDTLS_ERR_NET_UNKNOWN_HOST; } /* Try the sockaddrs until a binding succeeds */ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; for (cur = addr_list; cur != NULL; cur = cur->ai_next) { ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); if (ctx->fd < 0) { ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } n = 1; if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &n, sizeof(n)) != 0) { close(ctx->fd); ret = MBEDTLS_ERR_NET_SOCKET_FAILED; continue; } if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) { close(ctx->fd); ret = MBEDTLS_ERR_NET_BIND_FAILED; continue; } /* Listen only makes sense for TCP */ if (proto == MBEDTLS_NET_PROTO_TCP) { if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) { close(ctx->fd); ret = MBEDTLS_ERR_NET_LISTEN_FAILED; continue; } } /* Bind was successful */ ret = 0; break; } freeaddrinfo(addr_list); return ret; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. */ static int net_would_block(const mbedtls_net_context *ctx) { ((void) ctx); return WSAGetLastError() == WSAEWOULDBLOCK; } #else /* * Check if the requested operation would be blocking on a non-blocking socket * and thus 'failed' with a negative return value. * * Note: on a blocking socket this function always returns 0! */ static int net_would_block(const mbedtls_net_context *ctx) { int err = errno; /* * Never return 'WOULD BLOCK' on a blocking socket */ if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) { errno = err; return 0; } switch (errno = err) { #if defined EAGAIN case EAGAIN: #endif #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif return 1; } return 0; } #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ /* * Accept a connection from a remote client */ int mbedtls_net_accept(mbedtls_net_context *bind_ctx, mbedtls_net_context *client_ctx, void *client_ip, size_t buf_size, size_t *cip_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int type; struct sockaddr_storage client_addr; #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) socklen_t n = (socklen_t) sizeof(client_addr); socklen_t type_len = (socklen_t) sizeof(type); #else int n = (int) sizeof(client_addr); int type_len = (int) sizeof(type); #endif /* Is this a TCP or UDP socket? */ if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE, (void *) &type, &type_len) != 0 || (type != SOCK_STREAM && type != SOCK_DGRAM)) { return MBEDTLS_ERR_NET_ACCEPT_FAILED; } if (type == SOCK_STREAM) { /* TCP: actual accept() */ ret = client_ctx->fd = (int) accept(bind_ctx->fd, (struct sockaddr *) &client_addr, &n); } else { /* UDP: wait for a message, but keep it in the queue */ char buf[1] = { 0 }; ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK, (struct sockaddr *) &client_addr, &n); #if defined(_WIN32) if (ret == SOCKET_ERROR && WSAGetLastError() == WSAEMSGSIZE) { /* We know buf is too small, thanks, just peeking here */ ret = 0; } #endif } if (ret < 0) { if (net_would_block(bind_ctx) != 0) { return MBEDTLS_ERR_SSL_WANT_READ; } return MBEDTLS_ERR_NET_ACCEPT_FAILED; } /* UDP: hijack the listening socket to communicate with the client, * then bind a new socket to accept new connections */ if (type != SOCK_STREAM) { struct sockaddr_storage local_addr; int one = 1; if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) { return MBEDTLS_ERR_NET_ACCEPT_FAILED; } client_ctx->fd = bind_ctx->fd; bind_ctx->fd = -1; /* In case we exit early */ n = sizeof(struct sockaddr_storage); if (getsockname(client_ctx->fd, (struct sockaddr *) &local_addr, &n) != 0 || (bind_ctx->fd = (int) socket(local_addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0 || setsockopt(bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof(one)) != 0) { return MBEDTLS_ERR_NET_SOCKET_FAILED; } if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) { return MBEDTLS_ERR_NET_BIND_FAILED; } } if (client_ip != NULL) { if (client_addr.ss_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; *cip_len = sizeof(addr4->sin_addr.s_addr); if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len); } else { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; *cip_len = sizeof(addr6->sin6_addr.s6_addr); if (buf_size < *cip_len) { return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL; } memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len); } } return 0; } /* * Set the socket blocking or non-blocking */ int mbedtls_net_set_block(mbedtls_net_context *ctx) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) u_long n = 0; return ioctlsocket(ctx->fd, FIONBIO, &n); #else return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK); #endif } int mbedtls_net_set_nonblock(mbedtls_net_context *ctx) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) u_long n = 1; return ioctlsocket(ctx->fd, FIONBIO, &n); #else return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK); #endif } /* * Check if data is available on the socket */ int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; struct timeval tv; fd_set read_fds; fd_set write_fds; int fd = ctx->fd; ret = check_fd(fd, 1); if (ret != 0) { return ret; } #if defined(__has_feature) #if __has_feature(memory_sanitizer) /* Ensure that memory sanitizers consider read_fds and write_fds as * initialized even on platforms such as Glibc/x86_64 where FD_ZERO * is implemented in assembly. */ memset(&read_fds, 0, sizeof(read_fds)); memset(&write_fds, 0, sizeof(write_fds)); #endif #endif FD_ZERO(&read_fds); if (rw & MBEDTLS_NET_POLL_READ) { rw &= ~MBEDTLS_NET_POLL_READ; FD_SET((SOCKET) fd, &read_fds); } FD_ZERO(&write_fds); if (rw & MBEDTLS_NET_POLL_WRITE) { rw &= ~MBEDTLS_NET_POLL_WRITE; FD_SET((SOCKET) fd, &write_fds); } if (rw != 0) { return MBEDTLS_ERR_NET_BAD_INPUT_DATA; } tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; do { ret = select(fd + 1, &read_fds, &write_fds, NULL, timeout == (uint32_t) -1 ? NULL : &tv); } while (IS_EINTR(ret)); if (ret < 0) { return MBEDTLS_ERR_NET_POLL_FAILED; } ret = 0; if (FD_ISSET(fd, &read_fds)) { ret |= MBEDTLS_NET_POLL_READ; } if (FD_ISSET(fd, &write_fds)) { ret |= MBEDTLS_NET_POLL_WRITE; } return ret; } /* * Portable usleep helper */ void mbedtls_net_usleep(unsigned long usec) { #if defined(_WIN32) Sleep((usec + 999) / 1000); #else struct timeval tv; tv.tv_sec = usec / 1000000; #if defined(__unix__) || defined(__unix) || \ (defined(__APPLE__) && defined(__MACH__)) tv.tv_usec = (suseconds_t) usec % 1000000; #else tv.tv_usec = usec % 1000000; #endif select(0, NULL, NULL, NULL, &tv); #endif } /* * Read at most 'len' characters */ int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int fd = ((mbedtls_net_context *) ctx)->fd; ret = check_fd(fd, 0); if (ret != 0) { return ret; } ret = (int) read(fd, buf, len); if (ret < 0) { if (net_would_block(ctx) != 0) { return MBEDTLS_ERR_SSL_WANT_READ; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) if (WSAGetLastError() == WSAECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } #else if (errno == EPIPE || errno == ECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } if (errno == EINTR) { return MBEDTLS_ERR_SSL_WANT_READ; } #endif return MBEDTLS_ERR_NET_RECV_FAILED; } return ret; } /* * Read at most 'len' characters, blocking for at most 'timeout' ms */ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; struct timeval tv; fd_set read_fds; int fd = ((mbedtls_net_context *) ctx)->fd; ret = check_fd(fd, 1); if (ret != 0) { return ret; } FD_ZERO(&read_fds); FD_SET((SOCKET) fd, &read_fds); tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv); /* Zero fds ready means we timed out */ if (ret == 0) { return MBEDTLS_ERR_SSL_TIMEOUT; } if (ret < 0) { #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) if (WSAGetLastError() == WSAEINTR) { return MBEDTLS_ERR_SSL_WANT_READ; } #else if (errno == EINTR) { return MBEDTLS_ERR_SSL_WANT_READ; } #endif return MBEDTLS_ERR_NET_RECV_FAILED; } /* This call will not block */ return mbedtls_net_recv(ctx, buf, len); } /* * Write at most 'len' characters */ int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int fd = ((mbedtls_net_context *) ctx)->fd; ret = check_fd(fd, 0); if (ret != 0) { return ret; } ret = (int) write(fd, buf, len); if (ret < 0) { if (net_would_block(ctx) != 0) { return MBEDTLS_ERR_SSL_WANT_WRITE; } #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ !defined(EFI32) if (WSAGetLastError() == WSAECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } #else if (errno == EPIPE || errno == ECONNRESET) { return MBEDTLS_ERR_NET_CONN_RESET; } if (errno == EINTR) { return MBEDTLS_ERR_SSL_WANT_WRITE; } #endif return MBEDTLS_ERR_NET_SEND_FAILED; } return ret; } /* * Close the connection */ void mbedtls_net_close(mbedtls_net_context *ctx) { if (ctx->fd == -1) { return; } close(ctx->fd); ctx->fd = -1; } /* * Gracefully close the connection */ void mbedtls_net_free(mbedtls_net_context *ctx) { if (ctx->fd == -1) { return; } shutdown(ctx->fd, 2); close(ctx->fd); ctx->fd = -1; } #endif /* MBEDTLS_NET_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/nist_kw.c000066400000000000000000000544401464416617300231650ustar00rootroot00000000000000/* * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes * only * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Definition of Key Wrapping: * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" * * Note: RFC 3394 defines different methodology for intermediate operations for * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. */ #include "common.h" #if defined(MBEDTLS_NIST_KW_C) #include "mbedtls/nist_kw.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #include "constant_time_internal.h" #include #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_NIST_KW_ALT) #define KW_SEMIBLOCK_LENGTH 8 #define MIN_SEMIBLOCKS_COUNT 3 /*! The 64-bit default integrity check value (ICV) for KW mode. */ static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 }; /*! The 32-bit default integrity check value (ICV) for KWP mode. */ static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 }; /* * Initialize context */ void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx) { memset(ctx, 0, sizeof(mbedtls_nist_kw_context)); } int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx, mbedtls_cipher_id_t cipher, const unsigned char *key, unsigned int keybits, const int is_wrap) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_cipher_info_t *cipher_info; cipher_info = mbedtls_cipher_info_from_values(cipher, keybits, MBEDTLS_MODE_ECB); if (cipher_info == NULL) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* * SP 800-38F currently defines AES cipher as the only block cipher allowed: * "For KW and KWP, the underlying block cipher shall be approved, and the * block size shall be 128 bits. Currently, the AES block cipher, with key * lengths of 128, 192, or 256 bits, is the only block cipher that fits * this profile." * Currently we don't support other 128 bit block ciphers for key wrapping, * such as Camellia and Aria. */ if (cipher != MBEDTLS_CIPHER_ID_AES) { return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } mbedtls_cipher_free(&ctx->cipher_ctx); if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits, is_wrap ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) ) != 0) { return ret; } return 0; } /* * Free context */ void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx) { mbedtls_cipher_free(&ctx->cipher_ctx); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context)); } /* * Helper function for Xoring the uint64_t "t" with the encrypted A. * Defined in NIST SP 800-38F section 6.1 */ static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t) { size_t i = 0; for (i = 0; i < sizeof(t); i++) { A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff; } } /* * KW-AE as defined in SP 800-38F section 6.2 * KWP-AE as defined in SP 800-38F section 6.3 */ int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size) { int ret = 0; size_t semiblocks = 0; size_t s; size_t olen, padlen = 0; uint64_t t = 0; unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; *out_len = 0; /* * Generate the String to work on */ if (mode == MBEDTLS_KW_MODE_KW) { if (out_size < in_len + KW_SEMIBLOCK_LENGTH) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* * According to SP 800-38F Table 1, the plaintext length for KW * must be between 2 to 2^54-1 semiblocks inclusive. */ if (in_len < 16 || #if SIZE_MAX > 0x1FFFFFFFFFFFFF8 in_len > 0x1FFFFFFFFFFFFF8 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH); memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len); } else { if (in_len % 8 != 0) { padlen = (8 - (in_len % 8)); } if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } /* * According to SP 800-38F Table 1, the plaintext length for KWP * must be between 1 and 2^32-1 octets inclusive. */ if (in_len < 1 #if SIZE_MAX > 0xFFFFFFFF || in_len > 0xFFFFFFFF #endif ) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2); MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output, KW_SEMIBLOCK_LENGTH / 2); memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len); memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen); } semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1; s = 6 * (semiblocks - 1); if (mode == MBEDTLS_KW_MODE_KWP && in_len <= KW_SEMIBLOCK_LENGTH) { memcpy(inbuff, output, 16); ret = mbedtls_cipher_update(&ctx->cipher_ctx, inbuff, 16, output, &olen); if (ret != 0) { goto cleanup; } } else { unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; unsigned char *A = output; /* * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 */ if (semiblocks < MIN_SEMIBLOCKS_COUNT) { ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; goto cleanup; } /* Calculate intermediate values */ for (t = 1; t <= s; t++) { memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH); ret = mbedtls_cipher_update(&ctx->cipher_ctx, inbuff, 16, outbuff, &olen); if (ret != 0) { goto cleanup; } memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); calc_a_xor_t(A, t); memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); R2 += KW_SEMIBLOCK_LENGTH; if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) { R2 = output + KW_SEMIBLOCK_LENGTH; } } } *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; cleanup: if (ret != 0) { memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH); } mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2); mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2); return ret; } /* * W-1 function as defined in RFC 3394 section 2.2.2 * This function assumes the following: * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. * 3. Minimal number of semiblocks is 3. * 4. A is a buffer to hold the first semiblock of the input buffer. */ static int unwrap(mbedtls_nist_kw_context *ctx, const unsigned char *input, size_t semiblocks, unsigned char A[KW_SEMIBLOCK_LENGTH], unsigned char *output, size_t *out_len) { int ret = 0; const size_t s = 6 * (semiblocks - 1); size_t olen; uint64_t t = 0; unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; unsigned char *R = NULL; *out_len = 0; if (semiblocks < MIN_SEMIBLOCKS_COUNT) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } memcpy(A, input, KW_SEMIBLOCK_LENGTH); memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; /* Calculate intermediate values */ for (t = s; t >= 1; t--) { calc_a_xor_t(A, t); memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH); memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH); ret = mbedtls_cipher_update(&ctx->cipher_ctx, inbuff, 16, outbuff, &olen); if (ret != 0) { goto cleanup; } memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); /* Set R as LSB64 of outbuff */ memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); if (R == output) { R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH; } else { R -= KW_SEMIBLOCK_LENGTH; } } *out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH; cleanup: if (ret != 0) { memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH); } mbedtls_platform_zeroize(inbuff, sizeof(inbuff)); mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); return ret; } /* * KW-AD as defined in SP 800-38F section 6.2 * KWP-AD as defined in SP 800-38F section 6.3 */ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, const unsigned char *input, size_t in_len, unsigned char *output, size_t *out_len, size_t out_size) { int ret = 0; size_t olen; unsigned char A[KW_SEMIBLOCK_LENGTH]; int diff; *out_len = 0; if (out_size < in_len - KW_SEMIBLOCK_LENGTH) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (mode == MBEDTLS_KW_MODE_KW) { /* * According to SP 800-38F Table 1, the ciphertext length for KW * must be between 3 to 2^54 semiblocks inclusive. */ if (in_len < 24 || #if SIZE_MAX > 0x200000000000000 in_len > 0x200000000000000 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, A, output, out_len); if (ret != 0) { goto cleanup; } /* Check ICV in "constant-time" */ diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; goto cleanup; } } else if (mode == MBEDTLS_KW_MODE_KWP) { size_t padlen = 0; uint32_t Plen; /* * According to SP 800-38F Table 1, the ciphertext length for KWP * must be between 2 to 2^29 semiblocks inclusive. */ if (in_len < KW_SEMIBLOCK_LENGTH * 2 || #if SIZE_MAX > 0x100000000 in_len > 0x100000000 || #endif in_len % KW_SEMIBLOCK_LENGTH != 0) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } if (in_len == KW_SEMIBLOCK_LENGTH * 2) { unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; ret = mbedtls_cipher_update(&ctx->cipher_ctx, input, 16, outbuff, &olen); if (ret != 0) { goto cleanup; } memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH); memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH); mbedtls_platform_zeroize(outbuff, sizeof(outbuff)); *out_len = KW_SEMIBLOCK_LENGTH; } else { /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH, A, output, out_len); if (ret != 0) { goto cleanup; } } /* Check ICV in "constant-time" */ diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2); /* * Plen is the length of the plaintext, when the input is valid. * If Plen is larger than the plaintext and padding, padlen will be * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 }; diff = mbedtls_ct_memcmp_partial( &output[*out_len - KW_SEMIBLOCK_LENGTH], zero, KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0); if (diff != 0) { ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; } if (ret != 0) { goto cleanup; } memset(output + Plen, 0, padlen); *out_len = Plen; } else { ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; goto cleanup; } cleanup: if (ret != 0) { memset(output, 0, *out_len); *out_len = 0; } mbedtls_platform_zeroize(&diff, sizeof(diff)); mbedtls_platform_zeroize(A, sizeof(A)); return ret; } #endif /* !MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) /* * Test vectors taken from NIST * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW */ static const unsigned int key_len[] = { 16, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 24, 32 #endif }; static const unsigned char kw_key[][32] = { { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } #endif }; static const unsigned char kw_msg[][40] = { { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } #endif }; static const size_t kw_msg_len[] = { 16, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 40, 24 #endif }; static const size_t kw_out_len[] = { 24, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 48, 32 #endif }; static const unsigned char kw_res[][48] = { { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } #endif }; static const unsigned char kwp_key[][32] = { { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } #endif }; static const unsigned char kwp_msg[][31] = { { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, 0x96 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, { 0xd1 } #endif }; static const size_t kwp_msg_len[] = { 9, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 31, 1 #endif }; static const unsigned char kwp_res[][48] = { { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } #endif }; static const size_t kwp_out_len[] = { 24, #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) 40, 16 #endif }; int mbedtls_nist_kw_self_test(int verbose) { mbedtls_nist_kw_context ctx; unsigned char out[48]; size_t olen; int i; int ret = 0; mbedtls_nist_kw_init(&ctx); /* * KW mode */ { static const int num_tests = sizeof(kw_key) / sizeof(*kw_key); for (i = 0; i < num_tests; i++) { if (verbose != 0) { mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8); } ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kw_key[i], key_len[i] * 8, 1); if (ret != 0) { if (verbose != 0) { mbedtls_printf(" KW: setup failed "); } goto end; } ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], kw_msg_len[i], out, &olen, sizeof(out)); if (ret != 0 || kw_out_len[i] != olen || memcmp(out, kw_res[i], kw_out_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed. "); } ret = 1; goto end; } if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kw_key[i], key_len[i] * 8, 0)) != 0) { if (verbose != 0) { mbedtls_printf(" KW: setup failed "); } goto end; } ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, out, olen, out, &olen, sizeof(out)); if (ret != 0 || olen != kw_msg_len[i] || memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto end; } if (verbose != 0) { mbedtls_printf(" passed\n"); } } } /* * KWP mode */ { static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key); for (i = 0; i < num_tests; i++) { olen = sizeof(out); if (verbose != 0) { mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8); } ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], key_len[i] * 8, 1); if (ret != 0) { if (verbose != 0) { mbedtls_printf(" KWP: setup failed "); } goto end; } ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], kwp_msg_len[i], out, &olen, sizeof(out)); if (ret != 0 || kwp_out_len[i] != olen || memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed. "); } ret = 1; goto end; } if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], key_len[i] * 8, 0)) != 0) { if (verbose != 0) { mbedtls_printf(" KWP: setup failed "); } goto end; } ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out, olen, out, &olen, sizeof(out)); if (ret != 0 || olen != kwp_msg_len[i] || memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed. "); } ret = 1; goto end; } if (verbose != 0) { mbedtls_printf(" passed\n"); } } } end: mbedtls_nist_kw_free(&ctx); if (verbose != 0) { mbedtls_printf("\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_NIST_KW_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/oid.c000066400000000000000000001131131464416617300222530ustar00rootroot00000000000000/** * \file oid.c * * \brief Object Identifier (OID) database * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_OID_C) #include "mbedtls/oid.h" #include "mbedtls/rsa.h" #include "mbedtls/error.h" #include "mbedtls/pk.h" #include #include #include "mbedtls/platform.h" /* * Macro to automatically add the size of #define'd OIDs */ #define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) /* * Macro to generate mbedtls_oid_descriptor_t */ #if !defined(MBEDTLS_X509_REMOVE_INFO) #define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } #define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } #else #define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } #define NULL_OID_DESCRIPTOR { NULL, 0 } #endif /* * Macro to generate an internal function for oid_XXX_from_asn1() (used by * the other functions) */ #define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST) \ static const TYPE_T *oid_ ## NAME ## _from_asn1( \ const mbedtls_asn1_buf *oid) \ { \ const TYPE_T *p = (LIST); \ const mbedtls_oid_descriptor_t *cur = \ (const mbedtls_oid_descriptor_t *) p; \ if (p == NULL || oid == NULL) return NULL; \ while (cur->asn1 != NULL) { \ if (cur->asn1_len == oid->len && \ memcmp(cur->asn1, oid->p, oid->len) == 0) { \ return p; \ } \ p++; \ cur = (const mbedtls_oid_descriptor_t *) p; \ } \ return NULL; \ } #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Macro to generate a function for retrieving a single attribute from the * descriptor of an mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ { \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ *ATTR1 = data->descriptor.ATTR1; \ return 0; \ } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Macro to generate a function for retrieving a single attribute from an * mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ { \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ *ATTR1 = data->ATTR1; \ return 0; \ } /* * Macro to generate a function for retrieving two attributes from an * mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ ATTR2_TYPE, ATTR2) \ int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ ATTR2_TYPE * ATTR2) \ { \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ *(ATTR1) = data->ATTR1; \ *(ATTR2) = data->ATTR2; \ return 0; \ } /* * Macro to generate a function for retrieving the OID based on a single * attribute from a mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen) \ { \ const TYPE_T *cur = (LIST); \ while (cur->descriptor.asn1 != NULL) { \ if (cur->ATTR1 == (ATTR1)) { \ *oid = cur->descriptor.asn1; \ *olen = cur->descriptor.asn1_len; \ return 0; \ } \ cur++; \ } \ return MBEDTLS_ERR_OID_NOT_FOUND; \ } /* * Macro to generate a function for retrieving the OID based on two * attributes from a mbedtls_oid_descriptor_t wrapper. */ #define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ ATTR2_TYPE, ATTR2) \ int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid, \ size_t *olen) \ { \ const TYPE_T *cur = (LIST); \ while (cur->descriptor.asn1 != NULL) { \ if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) { \ *oid = cur->descriptor.asn1; \ *olen = cur->descriptor.asn1_len; \ return 0; \ } \ cur++; \ } \ return MBEDTLS_ERR_OID_NOT_FOUND; \ } /* * For X520 attribute types */ typedef struct { mbedtls_oid_descriptor_t descriptor; const char *short_name; } oid_x520_attr_t; static const oid_x520_attr_t oid_x520_attr_type[] = { { OID_DESCRIPTOR(MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name"), "CN", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country"), "C", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality"), "L", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE, "id-at-state", "State"), "ST", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName", "Organization"), "O", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit"), "OU", }, { OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL, "emailAddress", "E-mail address"), "emailAddress", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER, "id-at-serialNumber", "Serial number"), "serialNumber", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS, "id-at-postalAddress", "Postal address"), "postalAddress", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code"), "postalCode", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname"), "SN", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name"), "GN", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials"), "initials", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER, "id-at-generationQualifier", "Generation qualifier"), "generationQualifier", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE, "id-at-title", "Title"), "title", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, "id-at-dnQualifier", "Distinguished Name qualifier"), "dnQualifier", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym"), "pseudonym", }, { OID_DESCRIPTOR(MBEDTLS_OID_UID, "id-uid", "User Id"), "uid", }, { OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT, "id-domainComponent", "Domain component"), "DC", }, { OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, "id-at-uniqueIdentifier", "Unique Identifier"), "uniqueIdentifier", }, { NULL_OID_DESCRIPTOR, NULL, } }; FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) /* * For X509 extensions */ typedef struct { mbedtls_oid_descriptor_t descriptor; int ext_type; } oid_x509_ext_t; static const oid_x509_ext_t oid_x509_ext[] = { { OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, "id-ce-basicConstraints", "Basic Constraints"), MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, }, { OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage"), MBEDTLS_OID_X509_EXT_KEY_USAGE, }, { OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE, "id-ce-extKeyUsage", "Extended Key Usage"), MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, }, { OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME, "id-ce-subjectAltName", "Subject Alt Name"), MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, }, { OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, "id-netscape-certtype", "Netscape Certificate Type"), MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, }, { OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, "id-ce-certificatePolicies", "Certificate Policies"), MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, }, { OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, "id-ce-subjectKeyIdentifier", "Subject Key Identifier"), MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, }, { OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, "id-ce-authorityKeyIdentifier", "Authority Key Identifier"), MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, }, { NULL_OID_DESCRIPTOR, 0, }, }; FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) #if !defined(MBEDTLS_X509_REMOVE_INFO) static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = { OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH, "id-kp-serverAuth", "TLS Web Server Authentication"), OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH, "id-kp-clientAuth", "TLS Web Client Authentication"), OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing"), OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"), OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping"), OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing"), OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN, "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)"), NULL_OID_DESCRIPTOR, }; FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) static const mbedtls_oid_descriptor_t oid_certificate_policies[] = { OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy"), NULL_OID_DESCRIPTOR, }; FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * For SignatureAlgorithmIdentifier */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_alg; mbedtls_pk_type_t pk_alg; } oid_sig_alg_t; static const oid_sig_alg_t oid_sig_alg[] = { #if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_MD_CAN_MD5) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5"), MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_MD5 */ #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", "RSA with SHA-224"), MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA224 */ #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", "RSA with SHA-256"), MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", "RSA with SHA-384"), MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", "RSA with SHA-512"), MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1"), MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224"), MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256"), MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384"), MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512"), MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, }, #endif /* MBEDTLS_MD_CAN_SHA512 */ #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #if defined(MBEDTLS_RSA_C) { OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS"), MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, }, #endif /* MBEDTLS_RSA_C */ { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) #if !defined(MBEDTLS_X509_REMOVE_INFO) FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) #endif FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) /* * For PublicKeyInfo (PKCS1, RFC 5480) */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_pk_type_t pk_alg; } oid_pk_alg_t; static const oid_pk_alg_t oid_pk_alg[] = { { OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA"), MBEDTLS_PK_RSA, }, { OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key"), MBEDTLS_PK_ECKEY, }, { OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH"), MBEDTLS_PK_ECKEY_DH, }, { NULL_OID_DESCRIPTOR, MBEDTLS_PK_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * For elliptic curves that use namedCurve inside ECParams (RFC 5480) */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_ecp_group_id grp_id; } oid_ecp_grp_t; static const oid_ecp_grp_t oid_ecp_grp[] = { #if defined(MBEDTLS_ECP_HAVE_SECP192R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1"), MBEDTLS_ECP_DP_SECP192R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP192R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP224R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1"), MBEDTLS_ECP_DP_SECP224R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP224R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP256R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1"), MBEDTLS_ECP_DP_SECP256R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP256R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP384R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1"), MBEDTLS_ECP_DP_SECP384R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP384R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP521R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1"), MBEDTLS_ECP_DP_SECP521R1, }, #endif /* MBEDTLS_ECP_HAVE_SECP521R1 */ #if defined(MBEDTLS_ECP_HAVE_SECP192K1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1"), MBEDTLS_ECP_DP_SECP192K1, }, #endif /* MBEDTLS_ECP_HAVE_SECP192K1 */ #if defined(MBEDTLS_ECP_HAVE_SECP224K1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1"), MBEDTLS_ECP_DP_SECP224K1, }, #endif /* MBEDTLS_ECP_HAVE_SECP224K1 */ #if defined(MBEDTLS_ECP_HAVE_SECP256K1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1"), MBEDTLS_ECP_DP_SECP256K1, }, #endif /* MBEDTLS_ECP_HAVE_SECP256K1 */ #if defined(MBEDTLS_ECP_HAVE_BP256R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1", "brainpool256r1"), MBEDTLS_ECP_DP_BP256R1, }, #endif /* MBEDTLS_ECP_HAVE_BP256R1 */ #if defined(MBEDTLS_ECP_HAVE_BP384R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1", "brainpool384r1"), MBEDTLS_ECP_DP_BP384R1, }, #endif /* MBEDTLS_ECP_HAVE_BP384R1 */ #if defined(MBEDTLS_ECP_HAVE_BP512R1) { OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1", "brainpool512r1"), MBEDTLS_ECP_DP_BP512R1, }, #endif /* MBEDTLS_ECP_HAVE_BP512R1 */ { NULL_OID_DESCRIPTOR, MBEDTLS_ECP_DP_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) /* * For Elliptic Curve algorithms that are directly * encoded in the AlgorithmIdentifier (RFC 8410) */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_ecp_group_id grp_id; } oid_ecp_grp_algid_t; static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] = { #if defined(MBEDTLS_ECP_HAVE_CURVE25519) { OID_DESCRIPTOR(MBEDTLS_OID_X25519, "X25519", "X25519"), MBEDTLS_ECP_DP_CURVE25519, }, #endif /* MBEDTLS_ECP_HAVE_CURVE25519 */ #if defined(MBEDTLS_ECP_HAVE_CURVE448) { OID_DESCRIPTOR(MBEDTLS_OID_X448, "X448", "X448"), MBEDTLS_ECP_DP_CURVE448, }, #endif /* MBEDTLS_ECP_HAVE_CURVE448 */ { NULL_OID_DESCRIPTOR, MBEDTLS_ECP_DP_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid) FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid, oid_ecp_grp_algid_t, grp_id_algid, mbedtls_ecp_group_id, grp_id) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid, oid_ecp_grp_algid_t, oid_ecp_grp_algid, mbedtls_ecp_group_id, grp_id) #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_CIPHER_C) /* * For PKCS#5 PBES2 encryption algorithm */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_cipher_type_t cipher_alg; } oid_cipher_alg_t; static const oid_cipher_alg_t oid_cipher_alg[] = { { OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC"), MBEDTLS_CIPHER_DES_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"), MBEDTLS_CIPHER_DES_EDE3_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC, "aes128-cbc", "AES128-CBC"), MBEDTLS_CIPHER_AES_128_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC, "aes192-cbc", "AES192-CBC"), MBEDTLS_CIPHER_AES_192_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC, "aes256-cbc", "AES256-CBC"), MBEDTLS_CIPHER_AES_256_CBC, }, { NULL_OID_DESCRIPTOR, MBEDTLS_CIPHER_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) #endif /* MBEDTLS_CIPHER_C */ /* * For digestAlgorithm */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_alg; } oid_md_alg_t; static const oid_md_alg_t oid_md_alg[] = { #if defined(MBEDTLS_MD_CAN_MD5) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5"), MBEDTLS_MD_MD5, }, #endif #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1"), MBEDTLS_MD_SHA1, }, #endif #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224"), MBEDTLS_MD_SHA224, }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256"), MBEDTLS_MD_SHA256, }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384"), MBEDTLS_MD_SHA384, }, #endif #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512"), MBEDTLS_MD_SHA512, }, #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"), MBEDTLS_MD_RIPEMD160, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_224) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224, "id-sha3-224", "SHA-3-224"), MBEDTLS_MD_SHA3_224, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_256) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256, "id-sha3-256", "SHA-3-256"), MBEDTLS_MD_SHA3_256, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_384) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384, "id-sha3-384", "SHA-3-384"), MBEDTLS_MD_SHA3_384, }, #endif #if defined(MBEDTLS_MD_CAN_SHA3_512) { OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512, "id-sha3-512", "SHA-3-512"), MBEDTLS_MD_SHA3_512, }, #endif { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) /* * For HMAC digestAlgorithm */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_hmac; } oid_md_hmac_t; static const oid_md_hmac_t oid_md_hmac[] = { #if defined(MBEDTLS_MD_CAN_SHA1) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1"), MBEDTLS_MD_SHA1, }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA224) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224"), MBEDTLS_MD_SHA224, }, #endif /* MBEDTLS_MD_CAN_SHA224 */ #if defined(MBEDTLS_MD_CAN_SHA256) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256"), MBEDTLS_MD_SHA256, }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384"), MBEDTLS_MD_SHA384, }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512"), MBEDTLS_MD_SHA512, }, #endif /* MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_MD_CAN_SHA3_224) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224, "hmacSHA3-224", "HMAC-SHA3-224"), MBEDTLS_MD_SHA3_224, }, #endif /* MBEDTLS_MD_CAN_SHA3_224 */ #if defined(MBEDTLS_MD_CAN_SHA3_256) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256, "hmacSHA3-256", "HMAC-SHA3-256"), MBEDTLS_MD_SHA3_256, }, #endif /* MBEDTLS_MD_CAN_SHA3_256 */ #if defined(MBEDTLS_MD_CAN_SHA3_384) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384, "hmacSHA3-384", "HMAC-SHA3-384"), MBEDTLS_MD_SHA3_384, }, #endif /* MBEDTLS_MD_CAN_SHA3_384 */ #if defined(MBEDTLS_MD_CAN_SHA3_512) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512, "hmacSHA3-512", "HMAC-SHA3-512"), MBEDTLS_MD_SHA3_512, }, #endif /* MBEDTLS_MD_CAN_SHA3_512 */ #if defined(MBEDTLS_MD_CAN_RIPEMD160) { OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160, "hmacRIPEMD160", "HMAC-RIPEMD160"), MBEDTLS_MD_RIPEMD160, }, #endif /* MBEDTLS_MD_CAN_RIPEMD160 */ { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_C) /* * For PKCS#12 PBEs */ typedef struct { mbedtls_oid_descriptor_t descriptor; mbedtls_md_type_t md_alg; mbedtls_cipher_type_t cipher_alg; } oid_pkcs12_pbe_alg_t; static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = { { OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES"), MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, }, { OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES"), MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, }, { NULL_OID_DESCRIPTOR, MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, }, }; FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) #endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */ /* Return the x.y.z.... style numeric string for the given OID */ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; char *p = buf; size_t n = size; unsigned int value = 0; if (size > INT_MAX) { /* Avoid overflow computing return value */ return MBEDTLS_ERR_ASN1_INVALID_LENGTH; } if (oid->len <= 0) { /* OID must not be empty */ return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } for (size_t i = 0; i < oid->len; i++) { /* Prevent overflow in value. */ if (value > (UINT_MAX >> 7)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } if ((value == 0) && ((oid->p[i]) == 0x80)) { /* Overlong encoding is not allowed */ return MBEDTLS_ERR_ASN1_INVALID_DATA; } value <<= 7; value |= oid->p[i] & 0x7F; if (!(oid->p[i] & 0x80)) { /* Last byte */ if (n == size) { int component1; unsigned int component2; /* First subidentifier contains first two OID components */ if (value >= 80) { component1 = '2'; component2 = value - 80; } else if (value >= 40) { component1 = '1'; component2 = value - 40; } else { component1 = '0'; component2 = value; } ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2); } else { ret = mbedtls_snprintf(p, n, ".%u", value); } if (ret < 2 || (size_t) ret >= n) { return MBEDTLS_ERR_OID_BUF_TOO_SMALL; } n -= (size_t) ret; p += ret; value = 0; } } if (value != 0) { /* Unterminated subidentifier */ return MBEDTLS_ERR_ASN1_OUT_OF_DATA; } return (int) (size - n); } static int oid_parse_number(unsigned int *num, const char **p, const char *bound) { int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; *num = 0; while (*p < bound && **p >= '0' && **p <= '9') { ret = 0; if (*num > (UINT_MAX / 10)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } *num *= 10; *num += **p - '0'; (*p)++; } return ret; } static size_t oid_subidentifier_num_bytes(unsigned int value) { size_t num_bytes = 0; do { value >>= 7; num_bytes++; } while (value != 0); return num_bytes; } static int oid_subidentifier_encode_into(unsigned char **p, unsigned char *bound, unsigned int value) { size_t num_bytes = oid_subidentifier_num_bytes(value); if ((size_t) (bound - *p) < num_bytes) { return MBEDTLS_ERR_OID_BUF_TOO_SMALL; } (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f); value >>= 7; for (size_t i = 2; i <= num_bytes; i++) { (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f); value >>= 7; } *p += num_bytes; return 0; } /* Return the OID for the given x.y.z.... style numeric string */ int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size) { int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; const char *str_ptr = oid_str; const char *str_bound = oid_str + size; unsigned int val = 0; unsigned int component1, component2; size_t encoded_len; unsigned char *resized_mem; /* Count the number of dots to get a worst-case allocation size. */ size_t num_dots = 0; for (size_t i = 0; i < size; i++) { if (oid_str[i] == '.') { num_dots++; } } /* Allocate maximum possible required memory: * There are (num_dots + 1) integer components, but the first 2 share the * same subidentifier, so we only need num_dots subidentifiers maximum. */ if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } /* Each byte can store 7 bits, calculate number of bytes for a * subidentifier: * * bytes = ceil(subidentifer_size * 8 / 7) */ size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7) + 1; size_t max_possible_bytes = num_dots * bytes_per_subidentifier; oid->p = mbedtls_calloc(max_possible_bytes, 1); if (oid->p == NULL) { return MBEDTLS_ERR_ASN1_ALLOC_FAILED; } unsigned char *out_ptr = oid->p; unsigned char *out_bound = oid->p + max_possible_bytes; ret = oid_parse_number(&component1, &str_ptr, str_bound); if (ret != 0) { goto error; } if (component1 > 2) { /* First component can't be > 2 */ ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } if (str_ptr >= str_bound || *str_ptr != '.') { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } str_ptr++; ret = oid_parse_number(&component2, &str_ptr, str_bound); if (ret != 0) { goto error; } if ((component1 < 2) && (component2 > 39)) { /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */ ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } if (str_ptr < str_bound) { if (*str_ptr == '.') { str_ptr++; } else { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } } if (component2 > (UINT_MAX - (component1 * 40))) { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } ret = oid_subidentifier_encode_into(&out_ptr, out_bound, (component1 * 40) + component2); if (ret != 0) { goto error; } while (str_ptr < str_bound) { ret = oid_parse_number(&val, &str_ptr, str_bound); if (ret != 0) { goto error; } if (str_ptr < str_bound) { if (*str_ptr == '.') { str_ptr++; } else { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto error; } } ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val); if (ret != 0) { goto error; } } encoded_len = (size_t) (out_ptr - oid->p); resized_mem = mbedtls_calloc(encoded_len, 1); if (resized_mem == NULL) { ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; goto error; } memcpy(resized_mem, oid->p, encoded_len); mbedtls_free(oid->p); oid->p = resized_mem; oid->len = encoded_len; oid->tag = MBEDTLS_ASN1_OID; return 0; error: mbedtls_free(oid->p); oid->p = NULL; oid->len = 0; return ret; } #endif /* MBEDTLS_OID_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/padlock.c000066400000000000000000000103311464416617300231130ustar00rootroot00000000000000/* * VIA PadLock support functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * This implementation is based on the VIA PadLock Programming Guide: * * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ * programming_guide.pdf */ #include "common.h" #if defined(MBEDTLS_PADLOCK_C) #include "padlock.h" #include #if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE) /* * PadLock detection routine */ int mbedtls_padlock_has_support(int feature) { static int flags = -1; int ebx = 0, edx = 0; if (flags == -1) { asm ("movl %%ebx, %0 \n\t" "movl $0xC0000000, %%eax \n\t" "cpuid \n\t" "cmpl $0xC0000001, %%eax \n\t" "movl $0, %%edx \n\t" "jb 1f \n\t" "movl $0xC0000001, %%eax \n\t" "cpuid \n\t" "1: \n\t" "movl %%edx, %1 \n\t" "movl %2, %%ebx \n\t" : "=m" (ebx), "=m" (edx) : "m" (ebx) : "eax", "ecx", "edx"); flags = edx; } return flags & feature; } /* * PadLock AES-ECB block en(de)cryption */ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]) { int ebx = 0; uint32_t *rk; uint32_t *blk; uint32_t *ctrl; unsigned char buf[256]; rk = ctx->buf + ctx->rk_offset; if (((long) rk & 15) != 0) { return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; } blk = MBEDTLS_PADLOCK_ALIGN16(buf); memcpy(blk, input, 16); ctrl = blk + 4; *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode^1) - 10) << 9); asm ("pushfl \n\t" "popfl \n\t" "movl %%ebx, %0 \n\t" "movl $1, %%ecx \n\t" "movl %2, %%edx \n\t" "movl %3, %%ebx \n\t" "movl %4, %%esi \n\t" "movl %4, %%edi \n\t" ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" "movl %1, %%ebx \n\t" : "=m" (ebx) : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) : "memory", "ecx", "edx", "esi", "edi"); memcpy(output, blk, 16); return 0; } #if defined(MBEDTLS_CIPHER_MODE_CBC) /* * PadLock AES-CBC buffer en(de)cryption */ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output) { int ebx = 0; size_t count; uint32_t *rk; uint32_t *iw; uint32_t *ctrl; unsigned char buf[256]; rk = ctx->buf + ctx->rk_offset; if (((long) input & 15) != 0 || ((long) output & 15) != 0 || ((long) rk & 15) != 0) { return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED; } iw = MBEDTLS_PADLOCK_ALIGN16(buf); memcpy(iw, iv, 16); ctrl = iw + 4; *ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9); count = (length + 15) >> 4; asm ("pushfl \n\t" "popfl \n\t" "movl %%ebx, %0 \n\t" "movl %2, %%ecx \n\t" "movl %3, %%edx \n\t" "movl %4, %%ebx \n\t" "movl %5, %%esi \n\t" "movl %6, %%edi \n\t" "movl %7, %%eax \n\t" ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" "movl %1, %%ebx \n\t" : "=m" (ebx) : "m" (ebx), "m" (count), "m" (ctrl), "m" (rk), "m" (input), "m" (output), "m" (iw) : "memory", "eax", "ecx", "edx", "esi", "edi"); memcpy(iv, iw, 16); return 0; } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_VIA_PADLOCK_HAVE_CODE */ #endif /* MBEDTLS_PADLOCK_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/padlock.h000066400000000000000000000063351464416617300231310ustar00rootroot00000000000000/** * \file padlock.h * * \brief VIA PadLock ACE for HW encryption/decryption supported by some * processors * * \warning These functions are only for internal use by other library * functions; you must not call them directly. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PADLOCK_H #define MBEDTLS_PADLOCK_H #include "mbedtls/build_info.h" #include "mbedtls/aes.h" #define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ #if defined(__has_feature) #if __has_feature(address_sanitizer) #define MBEDTLS_HAVE_ASAN #endif #endif /* * - `padlock` is implements with GNUC assembly for x86 target. * - Some versions of ASan result in errors about not enough registers. */ #if defined(MBEDTLS_PADLOCK_C) && \ defined(__GNUC__) && defined(MBEDTLS_ARCH_IS_X86) && \ defined(MBEDTLS_HAVE_ASM) && \ !defined(MBEDTLS_HAVE_ASAN) #define MBEDTLS_VIA_PADLOCK_HAVE_CODE #include #define MBEDTLS_PADLOCK_RNG 0x000C #define MBEDTLS_PADLOCK_ACE 0x00C0 #define MBEDTLS_PADLOCK_PHE 0x0C00 #define MBEDTLS_PADLOCK_PMM 0x3000 #define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) #ifdef __cplusplus extern "C" { #endif /** * \brief Internal PadLock detection routine * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param feature The feature to detect * * \return non-zero if CPU has support for the feature, 0 otherwise */ int mbedtls_padlock_has_support(int feature); /** * \brief Internal PadLock AES-ECB block en(de)cryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param input 16-byte input block * \param output 16-byte output block * * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16]); /** * \brief Internal PadLock AES-CBC buffer en(de)cryption * * \note This function is only for internal use by other library * functions; you must not call it directly. * * \param ctx AES context * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT * \param length length of the input data * \param iv initialization vector (updated after use) * \param input buffer holding the input data * \param output buffer holding the output data * * \return 0 if success, 1 if operation failed */ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx, int mode, size_t length, unsigned char iv[16], const unsigned char *input, unsigned char *output); #ifdef __cplusplus } #endif #endif /* HAVE_X86 */ #endif /* padlock.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pem.c000066400000000000000000000344451464416617300222730ustar00rootroot00000000000000/* * Privacy Enhanced Mail (PEM) decoding * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #include "mbedtls/base64.h" #include "mbedtls/des.h" #include "mbedtls/aes.h" #include "mbedtls/md.h" #include "mbedtls/cipher.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif #if defined(MBEDTLS_MD_CAN_MD5) && \ defined(MBEDTLS_CIPHER_MODE_CBC) && \ (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)) #define PEM_RFC1421 #endif /* MBEDTLS_MD_CAN_MD5 && MBEDTLS_CIPHER_MODE_CBC && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ #if defined(MBEDTLS_PEM_PARSE_C) void mbedtls_pem_init(mbedtls_pem_context *ctx) { memset(ctx, 0, sizeof(mbedtls_pem_context)); } #if defined(PEM_RFC1421) /* * Read a 16-byte hex string and convert it to binary */ static int pem_get_iv(const unsigned char *s, unsigned char *iv, size_t iv_len) { size_t i, j, k; memset(iv, 0, iv_len); for (i = 0; i < iv_len * 2; i++, s++) { if (*s >= '0' && *s <= '9') { j = *s - '0'; } else if (*s >= 'A' && *s <= 'F') { j = *s - '7'; } else if (*s >= 'a' && *s <= 'f') { j = *s - 'W'; } else { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } k = ((i & 1) != 0) ? j : j << 4; iv[i >> 1] = (unsigned char) (iv[i >> 1] | k); } return 0; } static int pem_pbkdf1(unsigned char *key, size_t keylen, unsigned char *iv, const unsigned char *pwd, size_t pwdlen) { mbedtls_md_context_t md5_ctx; const mbedtls_md_info_t *md5_info; unsigned char md5sum[16]; size_t use_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_init(&md5_ctx); /* Prepare the context. (setup() errors gracefully on NULL info.) */ md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) { goto exit; } /* * key[ 0..15] = MD5(pwd || IV) */ if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { goto exit; } if (keylen <= 16) { memcpy(key, md5sum, keylen); goto exit; } memcpy(key, md5sum, 16); /* * key[16..23] = MD5(key[ 0..15] || pwd || IV]) */ if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) { goto exit; } use_len = 16; if (keylen < 32) { use_len = keylen - 16; } memcpy(key + 16, md5sum, use_len); exit: mbedtls_md_free(&md5_ctx); mbedtls_platform_zeroize(md5sum, 16); return ret; } #if defined(MBEDTLS_DES_C) /* * Decrypt with DES-CBC, using PBKDF1 for key derivation */ static int pem_des_decrypt(unsigned char des_iv[8], unsigned char *buf, size_t buflen, const unsigned char *pwd, size_t pwdlen) { mbedtls_des_context des_ctx; unsigned char des_key[8]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_des_init(&des_ctx); if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) { goto exit; } ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen, des_iv, buf, buf); exit: mbedtls_des_free(&des_ctx); mbedtls_platform_zeroize(des_key, 8); return ret; } /* * Decrypt with 3DES-CBC, using PBKDF1 for key derivation */ static int pem_des3_decrypt(unsigned char des3_iv[8], unsigned char *buf, size_t buflen, const unsigned char *pwd, size_t pwdlen) { mbedtls_des3_context des3_ctx; unsigned char des3_key[24]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_des3_init(&des3_ctx); if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) { goto exit; } ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen, des3_iv, buf, buf); exit: mbedtls_des3_free(&des3_ctx); mbedtls_platform_zeroize(des3_key, 24); return ret; } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) /* * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation */ static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen, unsigned char *buf, size_t buflen, const unsigned char *pwd, size_t pwdlen) { mbedtls_aes_context aes_ctx; unsigned char aes_key[32]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_aes_init(&aes_ctx); if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) { goto exit; } if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) { goto exit; } ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen, aes_iv, buf, buf); exit: mbedtls_aes_free(&aes_ctx); mbedtls_platform_zeroize(aes_key, keylen); return ret; } #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) { /* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */ size_t pad_len = input[input_len - 1]; size_t i; if (pad_len > input_len) { return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; } *data_len = input_len - pad_len; for (i = *data_len; i < input_len; i++) { if (input[i] != pad_len) { return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH; } } return 0; } #endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */ #endif /* PEM_RFC1421 */ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, const unsigned char *data, const unsigned char *pwd, size_t pwdlen, size_t *use_len) { int ret, enc; size_t len; unsigned char *buf; const unsigned char *s1, *s2, *end; #if defined(PEM_RFC1421) unsigned char pem_iv[16]; mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; #else ((void) pwd); ((void) pwdlen); #endif /* PEM_RFC1421 */ if (ctx == NULL) { return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; } s1 = (unsigned char *) strstr((const char *) data, header); if (s1 == NULL) { return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } s2 = (unsigned char *) strstr((const char *) data, footer); if (s2 == NULL || s2 <= s1) { return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } s1 += strlen(header); if (*s1 == ' ') { s1++; } if (*s1 == '\r') { s1++; } if (*s1 == '\n') { s1++; } else { return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } end = s2; end += strlen(footer); if (*end == ' ') { end++; } if (*end == '\r') { end++; } if (*end == '\n') { end++; } *use_len = (size_t) (end - data); enc = 0; if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) { #if defined(PEM_RFC1421) enc++; s1 += 22; if (*s1 == '\r') { s1++; } if (*s1 == '\n') { s1++; } else { return MBEDTLS_ERR_PEM_INVALID_DATA; } #if defined(MBEDTLS_DES_C) if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) { enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; s1 += 23; if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } s1 += 16; } else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) { enc_alg = MBEDTLS_CIPHER_DES_CBC; s1 += 18; if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } s1 += 16; } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) { if (s2 - s1 < 22) { return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; } else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) { enc_alg = MBEDTLS_CIPHER_AES_128_CBC; } else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) { enc_alg = MBEDTLS_CIPHER_AES_192_CBC; } else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) { enc_alg = MBEDTLS_CIPHER_AES_256_CBC; } else { return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; } s1 += 22; if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) { return MBEDTLS_ERR_PEM_INVALID_ENC_IV; } s1 += 32; } #endif /* MBEDTLS_AES_C */ if (enc_alg == MBEDTLS_CIPHER_NONE) { return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG; } if (*s1 == '\r') { s1++; } if (*s1 == '\n') { s1++; } else { return MBEDTLS_ERR_PEM_INVALID_DATA; } #else return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; #endif /* PEM_RFC1421 */ } if (s1 >= s2) { return MBEDTLS_ERR_PEM_INVALID_DATA; } ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1)); if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); } if (len == 0) { return MBEDTLS_ERR_PEM_BAD_INPUT_DATA; } if ((buf = mbedtls_calloc(1, len)) == NULL) { return MBEDTLS_ERR_PEM_ALLOC_FAILED; } if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) { mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret); } if (enc != 0) { #if defined(PEM_RFC1421) if (pwd == NULL) { mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED; } ret = 0; #if defined(MBEDTLS_DES_C) if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) { ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen); } else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) { ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen); } #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_AES_C) if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) { ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen); } else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) { ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen); } else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) { ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen); } #endif /* MBEDTLS_AES_C */ if (ret != 0) { mbedtls_zeroize_and_free(buf, len); return ret; } /* Check PKCS padding and update data length based on padding info. * This can be used to detect invalid padding data and password * mismatches. */ size_t unpadded_len; ret = pem_check_pkcs_padding(buf, len, &unpadded_len); if (ret != 0) { mbedtls_zeroize_and_free(buf, len); return ret; } len = unpadded_len; #else mbedtls_zeroize_and_free(buf, len); return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE; #endif /* PEM_RFC1421 */ } ctx->buf = buf; ctx->buflen = len; return 0; } void mbedtls_pem_free(mbedtls_pem_context *ctx) { if (ctx->buf != NULL) { mbedtls_zeroize_and_free(ctx->buf, ctx->buflen); } mbedtls_free(ctx->info); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context)); } #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) int mbedtls_pem_write_buffer(const char *header, const char *footer, const unsigned char *der_data, size_t der_len, unsigned char *buf, size_t buf_len, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *encode_buf = NULL, *c, *p = buf; size_t len = 0, use_len, add_len = 0; mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len); add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1; if (use_len + add_len > buf_len) { *olen = use_len + add_len; return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL; } if (use_len != 0 && ((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) { return MBEDTLS_ERR_PEM_ALLOC_FAILED; } if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data, der_len)) != 0) { mbedtls_free(encode_buf); return ret; } memcpy(p, header, strlen(header)); p += strlen(header); c = encode_buf; while (use_len) { len = (use_len > 64) ? 64 : use_len; memcpy(p, c, len); use_len -= len; p += len; c += len; *p++ = '\n'; } memcpy(p, footer, strlen(footer)); p += strlen(footer); *p++ = '\0'; *olen = (size_t) (p - buf); /* Clean any remaining data previously written to the buffer */ memset(buf + *olen, 0, buf_len - *olen); mbedtls_free(encode_buf); return 0; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pk.c000066400000000000000000001465471464416617300221330ustar00rootroot00000000000000/* * Public Key abstraction layer * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_C) #include "mbedtls/pk.h" #include "pk_wrap.h" #include "pkwrite.h" #include "pk_internal.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "rsa_internal.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif #include #include #define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \ (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \ PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE /* * Initialise a mbedtls_pk_context */ void mbedtls_pk_init(mbedtls_pk_context *ctx) { ctx->pk_info = NULL; ctx->pk_ctx = NULL; #if defined(MBEDTLS_USE_PSA_CRYPTO) ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw)); ctx->pub_raw_len = 0; ctx->ec_family = 0; ctx->ec_bits = 0; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } /* * Free (the components of) a mbedtls_pk_context */ void mbedtls_pk_free(mbedtls_pk_context *ctx) { if (ctx == NULL) { return; } if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) { ctx->pk_info->ctx_free_func(ctx->pk_ctx); } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* The ownership of the priv_id key for opaque keys is external of the PK * module. It's the user responsibility to clear it after use. */ if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) { psa_destroy_key(ctx->priv_id); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx) { ctx->pk_info = NULL; ctx->rs_ctx = NULL; } /* * Free the components of a restart context */ void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx) { if (ctx == NULL || ctx->pk_info == NULL || ctx->pk_info->rs_free_func == NULL) { return; } ctx->pk_info->rs_free_func(ctx->rs_ctx); ctx->pk_info = NULL; ctx->rs_ctx = NULL; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* * Get pk_info structure from type */ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) { switch (pk_type) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: return &mbedtls_rsa_info; #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: return &mbedtls_eckey_info; case MBEDTLS_PK_ECKEY_DH: return &mbedtls_eckeydh_info; #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) case MBEDTLS_PK_ECDSA: return &mbedtls_ecdsa_info; #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ /* MBEDTLS_PK_RSA_ALT omitted on purpose */ default: return NULL; } } /* * Initialise context */ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) { if (info == NULL || ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if ((info->ctx_alloc_func != NULL) && ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } ctx->pk_info = info; return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * Initialise a PSA-wrapping context */ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, const mbedtls_svc_key_id_t key) { const mbedtls_pk_info_t *info = NULL; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t type; if (ctx == NULL || ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } type = psa_get_key_type(&attributes); psa_reset_key_attributes(&attributes); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { info = &mbedtls_ecdsa_opaque_info; } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { info = &mbedtls_rsa_opaque_info; } else { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } ctx->pk_info = info; ctx->priv_id = key; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* * Initialize an RSA-alt context */ int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, mbedtls_pk_rsa_alt_decrypt_func decrypt_func, mbedtls_pk_rsa_alt_sign_func sign_func, mbedtls_pk_rsa_alt_key_len_func key_len_func) { mbedtls_rsa_alt_context *rsa_alt; const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; if (ctx->pk_info != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } ctx->pk_info = info; rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; rsa_alt->key = key; rsa_alt->decrypt_func = decrypt_func; rsa_alt->sign_func = sign_func; rsa_alt->key_len_func = key_len_func; return 0; } #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ /* * Tell if a PK can do the operations of the given type */ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) { /* A context with null pk_info is not set up yet and can't do anything. * For backward compatibility, also accept NULL instead of a context * pointer. */ if (ctx == NULL || ctx->pk_info == NULL) { return 0; } return ctx->pk_info->can_do(type); } #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * Tell if a PK can do the operations of the given PSA algorithm */ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, psa_key_usage_t usage) { psa_key_usage_t key_usage; /* A context with null pk_info is not set up yet and can't do anything. * For backward compatibility, also accept NULL instead of a context * pointer. */ if (ctx == NULL || ctx->pk_info == NULL) { return 0; } /* Filter out non allowed algorithms */ if (PSA_ALG_IS_ECDSA(alg) == 0 && PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 && PSA_ALG_IS_RSA_PSS(alg) == 0 && alg != PSA_ALG_RSA_PKCS1V15_CRYPT && PSA_ALG_IS_ECDH(alg) == 0) { return 0; } /* Filter out non allowed usage flags */ if (usage == 0 || (usage & ~(PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_DERIVE)) != 0) { return 0; } /* Wildcard hash is not allowed */ if (PSA_ALG_IS_SIGN_HASH(alg) && PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) { return 0; } if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) { mbedtls_pk_type_t type; if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) { type = MBEDTLS_PK_ECKEY; } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { type = MBEDTLS_PK_RSA; } else if (PSA_ALG_IS_RSA_PSS(alg)) { type = MBEDTLS_PK_RSASSA_PSS; } else { return 0; } if (ctx->pk_info->can_do(type) == 0) { return 0; } switch (type) { case MBEDTLS_PK_ECKEY: key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE; break; case MBEDTLS_PK_RSA: case MBEDTLS_PK_RSASSA_PSS: key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT; break; default: /* Should never happen */ return 0; } return (key_usage & usage) == usage; } psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; status = psa_get_key_attributes(ctx->priv_id, &attributes); if (status != PSA_SUCCESS) { return 0; } psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes); /* Key's enrollment is available only when an Mbed TLS implementation of PSA * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined. * Even though we don't officially support using other implementations of PSA * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations * separated. */ #if defined(MBEDTLS_PSA_CRYPTO_C) psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes); #endif /* MBEDTLS_PSA_CRYPTO_C */ key_usage = psa_get_key_usage_flags(&attributes); psa_reset_key_attributes(&attributes); if ((key_usage & usage) != usage) { return 0; } /* * Common case: the key alg [or alg2] only allows alg. * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH * directly. * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with * a fixed hash on key_alg [or key_alg2]. */ if (alg == key_alg) { return 1; } #if defined(MBEDTLS_PSA_CRYPTO_C) if (alg == key_alg2) { return 1; } #endif /* MBEDTLS_PSA_CRYPTO_C */ /* * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash, * and alg is the same hash-and-sign family with any hash, * then alg is compliant with this key alg */ if (PSA_ALG_IS_SIGN_HASH(alg)) { if (PSA_ALG_IS_SIGN_HASH(key_alg) && PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH && (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) { return 1; } #if defined(MBEDTLS_PSA_CRYPTO_C) if (PSA_ALG_IS_SIGN_HASH(key_alg2) && PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH && (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) { return 1; } #endif /* MBEDTLS_PSA_CRYPTO_C */ } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #if defined(MBEDTLS_RSA_C) static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa, int want_crypt) { if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { if (want_crypt) { mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa); return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type)); } else { return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH); } } else { if (want_crypt) { return PSA_ALG_RSA_PKCS1V15_CRYPT; } else { return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH); } } } #endif /* MBEDTLS_RSA_C */ int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk, psa_key_usage_t usage, psa_key_attributes_t *attributes) { mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); psa_key_usage_t more_usage = usage; if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) { more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE; } else if (usage == PSA_KEY_USAGE_SIGN_HASH) { more_usage |= PSA_KEY_USAGE_VERIFY_HASH; } else if (usage == PSA_KEY_USAGE_DECRYPT) { more_usage |= PSA_KEY_USAGE_ENCRYPT; } more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY; int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE || usage == PSA_KEY_USAGE_VERIFY_HASH || usage == PSA_KEY_USAGE_ENCRYPT); switch (pk_type) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: { int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */ switch (usage) { case PSA_KEY_USAGE_SIGN_MESSAGE: case PSA_KEY_USAGE_SIGN_HASH: case PSA_KEY_USAGE_VERIFY_MESSAGE: case PSA_KEY_USAGE_VERIFY_HASH: /* Nothing to do. */ break; case PSA_KEY_USAGE_DECRYPT: case PSA_KEY_USAGE_ENCRYPT: want_crypt = 1; break; default: return MBEDTLS_ERR_PK_TYPE_MISMATCH; } /* Detect the presence of a private key in a way that works both * in CRT and non-CRT configurations. */ mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); int has_private = (mbedtls_rsa_check_privkey(rsa) == 0); if (want_private && !has_private) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_set_key_type(attributes, (want_private ? PSA_KEY_TYPE_RSA_KEY_PAIR : PSA_KEY_TYPE_RSA_PUBLIC_KEY)); psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk)); psa_set_key_algorithm(attributes, psa_algorithm_for_rsa(rsa, want_crypt)); break; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: { int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH); int derive_ok = (pk_type != MBEDTLS_PK_ECDSA); #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) psa_ecc_family_t family = pk->ec_family; size_t bits = pk->ec_bits; int has_private = 0; if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) { has_private = 1; } #else const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); int has_private = (ec->d.n != 0); size_t bits = 0; psa_ecc_family_t family = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); #endif psa_algorithm_t alg = 0; switch (usage) { case PSA_KEY_USAGE_SIGN_MESSAGE: case PSA_KEY_USAGE_SIGN_HASH: case PSA_KEY_USAGE_VERIFY_MESSAGE: case PSA_KEY_USAGE_VERIFY_HASH: if (!sign_ok) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH); #else alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH); #endif break; case PSA_KEY_USAGE_DERIVE: alg = PSA_ALG_ECDH; if (!derive_ok) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; default: return MBEDTLS_ERR_PK_TYPE_MISMATCH; } if (want_private && !has_private) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_set_key_type(attributes, (want_private ? PSA_KEY_TYPE_ECC_KEY_PAIR(family) : PSA_KEY_TYPE_ECC_PUBLIC_KEY(family))); psa_set_key_bits(attributes, bits); psa_set_key_algorithm(attributes, alg); break; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) case MBEDTLS_PK_RSA_ALT: return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_USE_PSA_CRYPTO) case MBEDTLS_PK_OPAQUE: { psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_get_key_attributes(pk->priv_id, &old_attributes); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_key_type_t old_type = psa_get_key_type(&old_attributes); switch (usage) { case PSA_KEY_USAGE_SIGN_MESSAGE: case PSA_KEY_USAGE_SIGN_HASH: case PSA_KEY_USAGE_VERIFY_MESSAGE: case PSA_KEY_USAGE_VERIFY_HASH: if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) || old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; case PSA_KEY_USAGE_DECRYPT: case PSA_KEY_USAGE_ENCRYPT: if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; case PSA_KEY_USAGE_DERIVE: if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } break; default: return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_key_type_t new_type = old_type; /* Opaque keys are always key pairs, so we don't need a check * on the input if the required usage is private. We just need * to adjust the type correctly if the required usage is public. */ if (!want_private) { new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type); } more_usage = psa_get_key_usage_flags(&old_attributes); if ((usage & more_usage) == 0) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } psa_set_key_type(attributes, new_type); psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes)); psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes)); break; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ default: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(attributes, more_usage); /* Key's enrollment is available only when an Mbed TLS implementation of PSA * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined. * Even though we don't officially support using other implementations of PSA * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations * separated. */ #if defined(MBEDTLS_PSA_CRYPTO_C) psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE); #endif return 0; } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO) static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *new_key_id) { unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; size_t key_length = 0; psa_status_t status = psa_export_key(old_key_id, key_buffer, sizeof(key_buffer), &key_length); if (status != PSA_SUCCESS) { return status; } status = psa_import_key(attributes, key_buffer, key_length, new_key_id); mbedtls_platform_zeroize(key_buffer, key_length); return status; } static int copy_into_psa(mbedtls_svc_key_id_t old_key_id, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *new_key_id) { /* Normally, we prefer copying: it's more efficient and works even * for non-exportable keys. */ psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id); if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ || status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) { /* There are edge cases where copying won't work, but export+import * might: * - If the old key does not allow PSA_KEY_USAGE_COPY. * - If the old key's usage does not allow what attributes wants. * Because the key was intended for use in the pk module, and may * have had a policy chosen solely for what pk needs rather than * based on a detailed understanding of PSA policies, we are a bit * more liberal than psa_copy_key() here. */ /* Here we need to check that the types match, otherwise we risk * importing nonsensical data. */ psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; status = psa_get_key_attributes(old_key_id, &old_attributes); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_key_type_t old_type = psa_get_key_type(&old_attributes); psa_reset_key_attributes(&old_attributes); if (old_type != psa_get_key_type(attributes)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } status = export_import_into_psa(old_key_id, attributes, new_key_id); } return PSA_PK_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */ static int import_pair_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id) { switch (mbedtls_pk_get_type(pk)) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: { if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } unsigned char key_buffer[ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)]; unsigned char *const key_end = key_buffer + sizeof(key_buffer); unsigned char *key_data = key_end; int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), key_buffer, &key_data); if (ret < 0) { return ret; } size_t key_length = key_end - key_data; ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, key_data, key_length, key_id)); mbedtls_platform_zeroize(key_data, key_length); return ret; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: { /* We need to check the curve family, otherwise the import could * succeed with nonsensical data. * We don't check the bit-size: it's optional in attributes, * and if it's specified, psa_import_key() will know from the key * data length and will check that the bit-size matches. */ psa_key_type_t to_type = psa_get_key_type(attributes); #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) psa_ecc_family_t from_family = pk->ec_family; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); size_t from_bits = 0; psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id, &from_bits); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (mbedtls_svc_key_id_is_null(pk->priv_id)) { /* We have a public key and want a key pair. */ return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return copy_into_psa(pk->priv_id, attributes, key_id); #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ if (ec->d.n == 0) { /* Private key not set. Assume the input is a public key only. * (The other possibility is that it's an incomplete object * where the group is set but neither the public key nor * the private key. This is not possible through ecp.h * functions, so we don't bother reporting a more suitable * error in that case.) */ return MBEDTLS_ERR_PK_TYPE_MISMATCH; } unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t key_length = 0; int ret = mbedtls_ecp_write_key_ext(ec, &key_length, key_buffer, sizeof(key_buffer)); if (ret < 0) { return ret; } ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, key_buffer, key_length, key_id)); mbedtls_platform_zeroize(key_buffer, key_length); return ret; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_USE_PSA_CRYPTO) case MBEDTLS_PK_OPAQUE: return copy_into_psa(pk->priv_id, attributes, key_id); #endif /* MBEDTLS_USE_PSA_CRYPTO */ default: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } } static int import_public_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id) { psa_key_type_t psa_type = psa_get_key_type(attributes); #if defined(MBEDTLS_RSA_C) || \ (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \ defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; #endif unsigned char *key_data = NULL; size_t key_length = 0; switch (mbedtls_pk_get_type(pk)) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_PK_RSA: { if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } unsigned char *const key_end = key_buffer + sizeof(key_buffer); key_data = key_end; int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk), key_buffer, &key_data); if (ret < 0) { return ret; } key_length = (size_t) ret; break; } #endif /*MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: { /* We need to check the curve family, otherwise the import could * succeed with nonsensical data. * We don't check the bit-size: it's optional in attributes, * and if it's specified, psa_import_key() will know from the key * data length and will check that the bit-size matches. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } key_data = (unsigned char *) pk->pub_raw; key_length = pk->pub_raw_len; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk); size_t from_bits = 0; psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id, &from_bits); if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } int ret = mbedtls_ecp_write_public_key( ec, MBEDTLS_ECP_PF_UNCOMPRESSED, &key_length, key_buffer, sizeof(key_buffer)); if (ret < 0) { return ret; } key_data = key_buffer; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ break; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_USE_PSA_CRYPTO) case MBEDTLS_PK_OPAQUE: { psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = psa_get_key_attributes(pk->priv_id, &old_attributes); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_key_type_t old_type = psa_get_key_type(&old_attributes); psa_reset_key_attributes(&old_attributes); if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } status = psa_export_public_key(pk->priv_id, key_buffer, sizeof(key_buffer), &key_length); if (status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(status); } key_data = key_buffer; break; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ default: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes, key_data, key_length, key_id)); } int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk, const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key_id) { /* Set the output immediately so that it won't contain garbage even * if we error out before calling psa_import_key(). */ *key_id = MBEDTLS_SVC_KEY_ID_INIT; #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes)); if (want_public) { return import_public_into_psa(pk, attributes, key_id); } else { return import_pair_into_psa(pk, attributes, key_id); } } static int copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk, int public_only) { psa_status_t status; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t key_type; psa_algorithm_t alg_type; size_t key_bits; /* Use a buffer size large enough to contain either a key pair or public key. */ unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE]; size_t exp_key_len; int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; if (pk == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } status = psa_get_key_attributes(key_id, &key_attr); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (public_only) { status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len); } else { status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len); } if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto exit; } key_type = psa_get_key_type(&key_attr); if (public_only) { key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); } key_bits = psa_get_key_bits(&key_attr); alg_type = psa_get_key_algorithm(&key_attr); #if defined(MBEDTLS_RSA_C) if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) || (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) { ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); if (ret != 0) { goto exit; } if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) { ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len); } else { ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len); } if (ret != 0) { goto exit; } mbedtls_md_type_t md_type = MBEDTLS_MD_NONE; if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) { md_type = mbedtls_md_type_from_psa_alg(alg_type); } if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) { ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type); } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) || alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) { ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type); } if (ret != 0) { goto exit; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) { mbedtls_ecp_group_id grp_id; ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); if (ret != 0) { goto exit; } grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits); ret = mbedtls_pk_ecc_set_group(pk, grp_id); if (ret != 0) { goto exit; } if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) { ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len); if (ret != 0) { goto exit; } ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); } else { ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len); } if (ret != 0) { goto exit; } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } exit: psa_reset_key_attributes(&key_attr); mbedtls_platform_zeroize(exp_key, sizeof(exp_key)); return ret; } int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk) { return copy_from_psa(key_id, pk, 0); } int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk) { return copy_from_psa(key_id, pk, 1); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /* * Helper for mbedtls_pk_sign and mbedtls_pk_verify */ static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) { if (*hash_len != 0) { return 0; } *hash_len = mbedtls_md_get_size_from_type(md_alg); if (*hash_len == 0) { return -1; } return 0; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Helper to set up a restart context if needed */ static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx, const mbedtls_pk_info_t *info) { /* Don't do anything if already set up or invalid */ if (ctx == NULL || ctx->pk_info != NULL) { return 0; } /* Should never happen when we're called */ if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } ctx->pk_info = info; return 0; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* * Verify a signature (restartable) */ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, mbedtls_pk_restart_ctx *rs_ctx) { if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* optimization: use non-restartable version if restart disabled */ if (rs_ctx != NULL && mbedtls_ecp_restart_is_enabled() && ctx->pk_info->verify_rs_func != NULL) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { return ret; } ret = ctx->pk_info->verify_rs_func(ctx, md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_pk_restart_free(rs_ctx); } return ret; } #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ (void) rs_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ if (ctx->pk_info->verify_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len, sig, sig_len); } /* * Verify a signature */ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len, sig, sig_len, NULL); } /* * Verify a signature with options */ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (!mbedtls_pk_can_do(ctx, type)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } if (type != MBEDTLS_PK_RSASSA_PSS) { /* General case: no options */ if (options != NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len); } /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa() * below would return a NULL pointer. */ if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_rsassa_pss_options *pss_opts; #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif if (options == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (pss_opts->mgf1_hash_id == md_alg) { unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; unsigned char *p; int key_len; size_t signature_length; psa_status_t status = PSA_ERROR_DATA_CORRUPT; psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT; psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg); p = buf + sizeof(buf); key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p); if (key_len < 0) { return key_len; } psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, psa_sig_alg); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { psa_destroy_key(key_id); return PSA_PK_TO_MBEDTLS_ERR(status); } /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH * on a valid signature with trailing data in a buffer, but * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact, * so for this reason the passed sig_len is overwritten. Smaller * signature lengths should not be accepted for verification. */ signature_length = sig_len > mbedtls_pk_get_len(ctx) ? mbedtls_pk_get_len(ctx) : sig_len; status = psa_verify_hash(key_id, psa_sig_alg, hash, hash_len, sig, signature_length); destruction_status = psa_destroy_key(key_id); if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } if (status == PSA_SUCCESS) { status = destruction_status; } return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { if (sig_len < mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx), md_alg, (unsigned int) hash_len, hash, pss_opts->mgf1_hash_id, pss_opts->expected_salt_len, sig); if (ret != 0) { return ret; } if (sig_len > mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return 0; } #else return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* * Make a signature (restartable) */ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_pk_restart_ctx *rs_ctx) { if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* optimization: use non-restartable version if restart disabled */ if (rs_ctx != NULL && mbedtls_ecp_restart_is_enabled() && ctx->pk_info->sign_rs_func != NULL) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { return ret; } ret = ctx->pk_info->sign_rs_func(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, rs_ctx->rs_ctx); if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_pk_restart_free(rs_ctx); } return ret; } #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ (void) rs_ctx; #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ if (ctx->pk_info->sign_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->sign_func(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng); } /* * Make a signature */ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, NULL); } /* * Make a signature given a signature type. */ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (!mbedtls_pk_can_do(ctx, pk_type)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } if (pk_type != MBEDTLS_PK_RSASSA_PSS) { return mbedtls_pk_sign(ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng); } #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) #if defined(MBEDTLS_USE_PSA_CRYPTO) const psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); if (psa_md_alg == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t psa_alg, sign_alg; #if defined(MBEDTLS_PSA_CRYPTO_C) psa_algorithm_t psa_enrollment_alg; #endif /* MBEDTLS_PSA_CRYPTO_C */ psa_status_t status; status = psa_get_key_attributes(ctx->priv_id, &key_attr); if (status != PSA_SUCCESS) { return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } psa_alg = psa_get_key_algorithm(&key_attr); #if defined(MBEDTLS_PSA_CRYPTO_C) psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr); #endif /* MBEDTLS_PSA_CRYPTO_C */ psa_reset_key_attributes(&key_attr); /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between * alg and enrollment alg should be of type RSA_PSS. */ if (PSA_ALG_IS_RSA_PSS(psa_alg)) { sign_alg = psa_alg; } #if defined(MBEDTLS_PSA_CRYPTO_C) else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) { sign_alg = psa_enrollment_alg; } #endif /* MBEDTLS_PSA_CRYPTO_C */ else { /* The opaque key has no RSA PSS algorithm associated. */ return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* Adjust the hashing algorithm. */ sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg); status = psa_sign_hash(ctx->priv_id, sign_alg, hash, hash_len, sig, sig_size, sig_len); return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg), ctx->pk_ctx, hash, hash_len, sig, sig_size, sig_len); #else /* MBEDTLS_USE_PSA_CRYPTO */ if (sig_size < mbedtls_pk_get_len(ctx)) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } if (pk_hashlen_helper(md_alg, &hash_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx); const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); if (ret == 0) { *sig_len = rsa_ctx->len; } return ret; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #else return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ } /* * Decrypt message */ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info->decrypt_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->decrypt_func(ctx, input, ilen, output, olen, osize, f_rng, p_rng); } /* * Encrypt message */ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info->encrypt_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } return ctx->pk_info->encrypt_func(ctx, input, ilen, output, olen, osize, f_rng, p_rng); } /* * Check public-private key pair */ int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { if (pub->pk_info == NULL || prv->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (f_rng == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (prv->pk_info->check_pair_func == NULL) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) { if (pub->pk_info->type != MBEDTLS_PK_RSA) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } } else { if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) && (pub->pk_info != prv->pk_info)) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } } return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub, (mbedtls_pk_context *) prv, f_rng, p_rng); } /* * Get key size in bits */ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) { /* For backward compatibility, accept NULL or a context that * isn't set up yet, and return a fake value that should be safe. */ if (ctx == NULL || ctx->pk_info == NULL) { return 0; } return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx); } /* * Export debug information */ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items) { if (ctx->pk_info == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (ctx->pk_info->debug_func == NULL) { return MBEDTLS_ERR_PK_TYPE_MISMATCH; } ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items); return 0; } /* * Access the PK type name */ const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx) { if (ctx == NULL || ctx->pk_info == NULL) { return "invalid PK"; } return ctx->pk_info->name; } /* * Access the PK type */ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) { if (ctx == NULL || ctx->pk_info == NULL) { return MBEDTLS_PK_NONE; } return ctx->pk_info->type; } #endif /* MBEDTLS_PK_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pk_ecc.c000066400000000000000000000213321464416617300227250ustar00rootroot00000000000000/* * ECC setters for PK. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/pk.h" #include "mbedtls/error.h" #include "mbedtls/ecp.h" #include "pk_internal.h" #if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS) int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) size_t ec_bits; psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits); /* group may already be initialized; if so, make sure IDs match */ if ((pk->ec_family != 0 && pk->ec_family != ec_family) || (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* set group */ pk->ec_family = ec_family; pk->ec_bits = ec_bits; return 0; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk); /* grp may already be initialized; if so, make sure IDs match */ if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE && mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* set group */ return mbedtls_ecp_group_load(&(ecp->grp), grp_id); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_usage_t flags; psa_status_t status; psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) { /* Do not set algorithm here because Montgomery keys cannot do ECDSA and * the PK module cannot do ECDH. When the key will be used in TLS for * ECDH, it will be exported and then re-imported with proper flags * and algorithm. */ flags = PSA_KEY_USAGE_EXPORT; } else { psa_set_key_algorithm(&attributes, MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH)); flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_EXPORT; } psa_set_key_usage_flags(&attributes, flags); status = psa_import_key(&attributes, key, key_len, &pk->priv_id); return psa_pk_status_to_mbedtls(status); #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } return 0; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, const unsigned char *prv, size_t prv_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) (void) f_rng; (void) p_rng; (void) prv; (void) prv_len; psa_status_t status; status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw), &pk->pub_raw_len); return psa_pk_status_to_mbedtls(status); #elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */ (void) f_rng; (void) p_rng; psa_status_t status; mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; size_t curve_bits; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits); /* Import private key into PSA, from serialized input */ mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); status = psa_import_key(&key_attr, prv, prv_len, &key_id); if (status != PSA_SUCCESS) { return psa_pk_status_to_mbedtls(status); } /* Export public key from PSA */ unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t pub_len; status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len); psa_status_t destruction_status = psa_destroy_key(key_id); if (status != PSA_SUCCESS) { return psa_pk_status_to_mbedtls(status); } else if (destruction_status != PSA_SUCCESS) { return psa_pk_status_to_mbedtls(destruction_status); } /* Load serialized public key into ecp_keypair structure */ return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len); #else /* MBEDTLS_USE_PSA_CRYPTO */ (void) prv; (void) prv_len; mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case. * * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA * functions to handle keys. However, currently psa_import_key() does not * support compressed points. In case that support was explicitly requested, * this fallback uses ECP functions to get the job done. This is the reason * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT. * * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group(). * out: will have the public key set. * [in] pub, pub_len: the public key as an ECPoint, * in any format supported by ECP. * * Return: * - 0 on success; * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid * but not supported; * - another error code otherwise. */ static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len) { #if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) (void) pk; (void) pub; (void) pub_len; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; #else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ mbedtls_ecp_keypair ecp_key; mbedtls_ecp_group_id ecp_group_id; int ret; ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); mbedtls_ecp_keypair_init(&ecp_key); ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id); if (ret != 0) { goto exit; } ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q, pub, pub_len); if (ret != 0) { goto exit; } ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &pk->pub_raw_len, pk->pub_raw, sizeof(pk->pub_raw)); exit: mbedtls_ecp_keypair_free(&ecp_key); return ret; #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* Load the key */ if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) { /* Format directly supported by PSA: * - non-Weierstrass curves that only have one format; * - uncompressed format for Weierstrass curves. */ if (pub_len > sizeof(pk->pub_raw)) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } memcpy(pk->pub_raw, pub, pub_len); pk->pub_raw_len = pub_len; } else { /* Other format, try the fallback */ int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len); if (ret != 0) { return ret; } } /* Validate the key by trying to import it */ mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_usage_flags(&key_attrs, 0); psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)); psa_set_key_bits(&key_attrs, pk->ec_bits); if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len, &key_id) != PSA_SUCCESS) || (psa_destroy_key(key_id) != PSA_SUCCESS)) { return MBEDTLS_ERR_PK_INVALID_PUBKEY; } return 0; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ int ret; mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx; ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len); if (ret != 0) { return ret; } return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } #endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pk_internal.h000066400000000000000000000175031464416617300240210ustar00rootroot00000000000000/** * \file pk_internal.h * * \brief Public Key abstraction layer: internal (i.e. library only) functions * and definitions. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_INTERNAL_H #define MBEDTLS_PK_INTERNAL_H #include "mbedtls/pk.h" #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include "psa/crypto.h" #include "psa_util_internal.h" #define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status) #define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ psa_to_pk_rsa_errors, \ psa_pk_status_to_mbedtls) #define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ psa_to_pk_ecdsa_errors, \ psa_pk_status_to_mbedtls) #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ /* Headers/footers for PEM files */ #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----" #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----" #define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----" #define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----" #define PEM_BEGIN_PUBLIC_KEY_RSA "-----BEGIN RSA PUBLIC KEY-----" #define PEM_END_PUBLIC_KEY_RSA "-----END RSA PUBLIC KEY-----" #define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----" #define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----" #define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----" #define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----" #define PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----BEGIN ENCRYPTED PRIVATE KEY-----" #define PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----END ENCRYPTED PRIVATE KEY-----" #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA) /** * Public function mbedtls_pk_ec() can be used to get direct access to the * wrapped ecp_keypair structure pointed to the pk_ctx. However this is not * ideal because it bypasses the PK module on the control of its internal * structure (pk_context) fields. * For backward compatibility we keep mbedtls_pk_ec() when ECP_C is defined, but * we provide 2 very similar functions when only ECP_LIGHT is enabled and not * ECP_C. * These variants embed the "ro" or "rw" keywords in their name to make the * usage of the returned pointer explicit. Of course the returned value is * const or non-const accordingly. */ static inline const mbedtls_ecp_keypair *mbedtls_pk_ec_ro(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: return (const mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } static inline mbedtls_ecp_keypair *mbedtls_pk_ec_rw(const mbedtls_pk_context pk) { switch (mbedtls_pk_get_type(&pk)) { case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); default: return NULL; } } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) static inline mbedtls_ecp_group_id mbedtls_pk_get_ec_group_id(const mbedtls_pk_context *pk) { mbedtls_ecp_group_id id; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t opaque_key_type; psa_ecc_family_t curve; if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { return MBEDTLS_ECP_DP_NONE; } opaque_key_type = psa_get_key_type(&opaque_attrs); curve = PSA_KEY_TYPE_ECC_GET_FAMILY(opaque_key_type); id = mbedtls_ecc_group_from_psa(curve, psa_get_key_bits(&opaque_attrs)); psa_reset_key_attributes(&opaque_attrs); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits); #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ id = mbedtls_pk_ec_ro(*pk)->grp.id; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } return id; } /* Helper for Montgomery curves */ #if defined(MBEDTLS_ECP_HAVE_CURVE25519) || defined(MBEDTLS_ECP_HAVE_CURVE448) #define MBEDTLS_PK_HAVE_RFC8410_CURVES #endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */ #define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \ ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448)) static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk) { mbedtls_ecp_group_id id = mbedtls_pk_get_ec_group_id(pk); return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id); } /* * Set the group used by this key. * * [in/out] pk: in: must have been pk_setup() to an ECC type * out: will have group (curve) information set * [in] grp_in: a supported group ID (not NONE) */ int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id); /* * Set the private key material * * [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group(). * out: will have the private key set. * [in] key, key_len: the raw private key (no ASN.1 wrapping). */ int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len); /* * Set the public key. * * [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group(). * out: will have the public key set. * [in] pub, pub_len: the raw public key (an ECPoint). * * Return: * - 0 on success; * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid * but not supported; * - another error code otherwise. */ int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len); /* * Derive a public key from its private counterpart. * Computationally intensive, only use when public key is not available. * * [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key(). * out: will have the public key set. * [in] prv, prv_len: the raw private key (see note below). * [in] f_rng, p_rng: RNG function and context. * * Note: the private key information is always available from pk, * however for convenience the serialized version is also passed, * as it's available at each calling site, and useful in some configs * (as otherwise we would have to re-serialize it from the pk context). * * There are three implementations of this function: * 1. MBEDTLS_PK_USE_PSA_EC_DATA, * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA, * 3. not MBEDTLS_USE_PSA_CRYPTO. */ int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk, const unsigned char *prv, size_t prv_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Helper for (deterministic) ECDSA */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_DETERMINISTIC_ECDSA #else #define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_ECDSA #endif #if defined(MBEDTLS_TEST_HOOKS) MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #endif #if defined(MBEDTLS_FS_IO) int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); #endif #endif /* MBEDTLS_PK_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pk_wrap.c000066400000000000000000001466411464416617300231570ustar00rootroot00000000000000/* * Public Key abstraction layer: wrapper functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_PK_C) #include "pk_wrap.h" #include "pk_internal.h" #include "mbedtls/error.h" #include "mbedtls/psa_util.h" /* Even if RSA not activated, for the sake of RSA-alt */ #include "mbedtls/rsa.h" #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_ECDSA_C) #include "mbedtls/ecdsa.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa_util_internal.h" #include "psa/crypto.h" #include "mbedtls/psa_util.h" #if defined(MBEDTLS_RSA_C) #include "pkwrite.h" #include "rsa_internal.h" #endif #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) #include "mbedtls/asn1write.h" #include "mbedtls/asn1.h" #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include "mbedtls/platform.h" #include #include #include #if defined(MBEDTLS_RSA_C) static int rsa_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_RSA || type == MBEDTLS_PK_RSASSA_PSS; } static size_t rsa_get_bitlen(mbedtls_pk_context *pk) { const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx; return mbedtls_rsa_get_bitlen(rsa); } #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status; int key_len; unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; unsigned char *p = buf + sizeof(buf); psa_algorithm_t psa_alg_md; size_t rsa_len = mbedtls_rsa_get_len(rsa); #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg)); } else { psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); } if (sig_len < rsa_len) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p); if (key_len <= 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, psa_alg_md); psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len, sig, sig_len); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; size_t rsa_len = mbedtls_rsa_get_len(rsa); #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif if (sig_len < rsa_len) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, (unsigned int) hash_len, hash, sig)) != 0) { return ret; } /* The buffer contains a valid signature followed by extra data. * We have a special error code for that so that so that callers can * use mbedtls_pk_verify() to check "Does the buffer start with a * valid signature?" and not just "Does the buffer contain a valid * signature?". */ if (sig_len > rsa_len) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg, mbedtls_rsa_context *rsa_ctx, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status; int key_len; unsigned char *buf = NULL; unsigned char *p; buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); if (buf == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES; *sig_len = mbedtls_rsa_get_len(rsa_ctx); if (sig_size < *sig_len) { mbedtls_free(buf); return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p); if (key_len <= 0) { mbedtls_free(buf); return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); status = psa_import_key(&attributes, buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_sign_hash(key_id, alg, hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: mbedtls_free(buf); status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { ((void) f_rng); ((void) p_rng); psa_algorithm_t psa_md_alg; psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); if (psa_md_alg == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_algorithm_t psa_alg; if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) { psa_alg = PSA_ALG_RSA_PSS(psa_md_alg); } else { psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg); } return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len, sig, sig_size, sig_len); } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; #if SIZE_MAX > UINT_MAX if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif *sig_len = mbedtls_rsa_get_len(rsa); if (sig_size < *sig_len) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_algorithm_t psa_md_alg, decrypt_alg; psa_status_t status; int key_len; unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; unsigned char *p = buf + sizeof(buf); ((void) f_rng); ((void) p_rng); if (ilen != mbedtls_rsa_get_len(rsa)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } key_len = mbedtls_rsa_write_key(rsa, buf, &p); if (key_len <= 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa)); decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg); } else { decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT; } psa_set_key_algorithm(&attributes, decrypt_alg); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_asymmetric_decrypt(key_id, decrypt_alg, input, ilen, NULL, 0, output, osize, olen); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; if (ilen != mbedtls_rsa_get_len(rsa)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, olen, input, output, osize); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int rsa_encrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_algorithm_t psa_md_alg, psa_encrypt_alg; psa_status_t status; int key_len; unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; unsigned char *p = buf + sizeof(buf); ((void) f_rng); ((void) p_rng); if (mbedtls_rsa_get_len(rsa) > osize) { return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p); if (key_len <= 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) { psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa)); psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg); } else { psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT; } psa_set_key_algorithm(&attributes, psa_encrypt_alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg, input, ilen, NULL, 0, output, osize, olen); if (status != PSA_SUCCESS) { ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_encrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; *olen = mbedtls_rsa_get_len(rsa); if (*olen > osize) { return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, ilen, input, output); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ static int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { (void) f_rng; (void) p_rng; return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx, (const mbedtls_rsa_context *) prv->pk_ctx); } static void *rsa_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); if (ctx != NULL) { mbedtls_rsa_init((mbedtls_rsa_context *) ctx); } return ctx; } static void rsa_free_wrap(void *ctx) { mbedtls_rsa_free((mbedtls_rsa_context *) ctx); mbedtls_free(ctx); } static void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) { #if defined(MBEDTLS_RSA_ALT) /* Not supported */ (void) pk; (void) items; #else mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; items->type = MBEDTLS_PK_DEBUG_MPI; items->name = "rsa.N"; items->value = &(rsa->N); items++; items->type = MBEDTLS_PK_DEBUG_MPI; items->name = "rsa.E"; items->value = &(rsa->E); #endif } const mbedtls_pk_info_t mbedtls_rsa_info = { .type = MBEDTLS_PK_RSA, .name = "RSA", .get_bitlen = rsa_get_bitlen, .can_do = rsa_can_do, .verify_func = rsa_verify_wrap, .sign_func = rsa_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = rsa_decrypt_wrap, .encrypt_func = rsa_encrypt_wrap, .check_pair_func = rsa_check_pair_wrap, .ctx_alloc_func = rsa_alloc_wrap, .ctx_free_func = rsa_free_wrap, .debug_func = rsa_debug, }; #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Generic EC key */ static int eckey_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH || type == MBEDTLS_PK_ECDSA; } static size_t eckey_get_bitlen(mbedtls_pk_context *pk) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) return pk->ec_bits; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; return ecp->grp.pbits; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Common helper for ECDSA verify using PSA functions. */ static int ecdsa_verify_psa(unsigned char *key, size_t key_len, psa_ecc_family_t curve, size_t curve_bits, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits); size_t converted_sig_len; unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; unsigned char *p; psa_status_t status; if (curve == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); psa_set_key_algorithm(&attributes, psa_sig_md); status = psa_import_key(&attributes, key, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } if (signature_len > sizeof(extracted_sig)) { ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; goto cleanup; } p = (unsigned char *) sig; ret = mbedtls_ecdsa_der_to_raw(curve_bits, p, sig_len, extracted_sig, sizeof(extracted_sig), &converted_sig_len); if (ret != 0) { goto cleanup; } if (converted_sig_len != signature_len) { ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; goto cleanup; } status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len, extracted_sig, signature_len); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); goto cleanup; } ret = 0; cleanup: status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } static int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { (void) md_alg; unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; size_t key_len; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; psa_ecc_family_t curve; size_t curve_bits; psa_status_t status; status = psa_get_key_attributes(pk->priv_id, &key_attr); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr)); curve_bits = psa_get_key_bits(&key_attr); psa_reset_key_attributes(&key_attr); status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } return ecdsa_verify_psa(key, key_len, curve, curve_bits, hash, hash_len, sig, sig_len); } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { (void) md_alg; psa_ecc_family_t curve = pk->ec_family; size_t curve_bits = pk->ec_bits; return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits, hash, hash_len, sig, sig_len); } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { (void) md_alg; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ctx = pk->pk_ctx; unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t key_len; size_t curve_bits; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &key_len, key, sizeof(key)); if (ret != 0) { return ret; } return ecdsa_verify_psa(key, key_len, curve, curve_bits, hash, hash_len, sig, sig_len); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #else /* MBEDTLS_USE_PSA_CRYPTO */ static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) md_alg); ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx, hash, hash_len, sig, sig_len); if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Common helper for ECDSA sign using PSA functions. * Instead of extracting key's properties in order to check which kind of ECDSA * signature it supports, we try both deterministic and non-deterministic. */ static int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; size_t key_bits = 0; status = psa_get_key_attributes(key_id, &key_attr); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } key_bits = psa_get_key_bits(&key_attr); psa_reset_key_attributes(&key_attr); status = psa_sign_hash(key_id, PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)), hash, hash_len, sig, sig_size, sig_len); if (status == PSA_SUCCESS) { goto done; } else if (status != PSA_ERROR_NOT_PERMITTED) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } status = psa_sign_hash(key_id, PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)), hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); } done: ret = mbedtls_ecdsa_raw_to_der(key_bits, sig, *sig_len, sig, sig_size, sig_len); return ret; } static int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { ((void) f_rng); ((void) p_rng); return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size, sig_len); } #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up * using the same function. */ #define ecdsa_sign_wrap ecdsa_opaque_sign_wrap #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_status_t status; mbedtls_ecp_keypair *ctx = pk->pk_ctx; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; size_t curve_bits; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); size_t key_len = PSA_BITS_TO_BYTES(curve_bits); psa_algorithm_t psa_hash = mbedtls_md_psa_alg_from_type(md_alg); psa_algorithm_t psa_sig_md = MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(psa_hash); ((void) f_rng); ((void) p_rng); if (curve == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (key_len > sizeof(buf)) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len); if (ret != 0) { goto cleanup; } psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); psa_set_key_algorithm(&attributes, psa_sig_md); status = psa_import_key(&attributes, buf, key_len, &key_id); if (status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); goto cleanup; } ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len); cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); status = psa_destroy_key(key_id); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_PK_TO_MBEDTLS_ERR(status); } return ret; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #else /* MBEDTLS_USE_PSA_CRYPTO */ static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* Forward declarations */ static int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx); static int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx); /* * Restart context for ECDSA operations with ECKEY context * * We need to store an actual ECDSA context, as we need to pass the same to * the underlying ecdsa function, so we can't create it on the fly every time. */ typedef struct { mbedtls_ecdsa_restart_ctx ecdsa_rs; mbedtls_ecdsa_context ecdsa_ctx; } eckey_restart_ctx; static void *eckey_rs_alloc(void) { eckey_restart_ctx *rs_ctx; void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx)); if (ctx != NULL) { rs_ctx = ctx; mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs); mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx); } return ctx; } static void eckey_rs_free(void *ctx) { eckey_restart_ctx *rs_ctx; if (ctx == NULL) { return; } rs_ctx = ctx; mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs); mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx); mbedtls_free(ctx); } static int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; eckey_restart_ctx *rs = rs_ctx; /* Should never happen */ if (rs == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* set up our own sub-context if needed (that is, on first run) */ if (rs->ecdsa_ctx.grp.pbits == 0) { MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); } MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk, md_alg, hash, hash_len, sig, sig_len, &rs->ecdsa_rs)); cleanup: return ret; } static int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; eckey_restart_ctx *rs = rs_ctx; /* Should never happen */ if (rs == NULL) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } /* set up our own sub-context if needed (that is, on first run) */ if (rs->ecdsa_ctx.grp.pbits == 0) { MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); } MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, &rs->ecdsa_rs)); cleanup: return ret; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t prv_key_len; mbedtls_svc_key_id_t key_id = prv->priv_id; status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), &prv_key_len); ret = PSA_PK_TO_MBEDTLS_ERR(status); if (ret != 0) { return ret; } if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return 0; } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t prv_key_len; psa_status_t destruction_status; mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; size_t pub_key_len; size_t curve_bits; const psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits); const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits); if (curve == 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d, prv_key_buf, curve_bytes); if (ret != 0) { mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); return ret; } status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id); mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); ret = PSA_PK_TO_MBEDTLS_ERR(status); if (ret != 0) { return ret; } // From now on prv_key_buf is used to store the public key of prv. status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), &prv_key_len); ret = PSA_PK_TO_MBEDTLS_ERR(status); destruction_status = psa_destroy_key(key_id); if (ret != 0) { return ret; } else if (destruction_status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(destruction_status); } ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp, &mbedtls_pk_ec_rw(*pub)->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &pub_key_len, pub_key_buf, sizeof(pub_key_buf)); if (ret != 0) { return ret; } if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return 0; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { (void) f_rng; (void) p_rng; return eckey_check_pair_psa(pub, prv); } #else /* MBEDTLS_USE_PSA_CRYPTO */ static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx, (const mbedtls_ecp_keypair *) prv->pk_ctx, f_rng, p_rng); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) /* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up * using the same function. */ #define ecdsa_opaque_check_pair_wrap eckey_check_pair_wrap #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { psa_status_t status; uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; size_t exp_pub_key_len = 0; uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; size_t pub_key_len = 0; int ret; (void) f_rng; (void) p_rng; status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key), &exp_pub_key_len); if (status != PSA_SUCCESS) { ret = psa_pk_status_to_mbedtls(status); return ret; } ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp), &(mbedtls_pk_ec_ro(*pub)->Q), MBEDTLS_ECP_PF_UNCOMPRESSED, &pub_key_len, pub_key, sizeof(pub_key)); if (ret != 0) { return ret; } if ((exp_pub_key_len != pub_key_len) || memcmp(exp_pub_key, pub_key, exp_pub_key_len)) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } return 0; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) static void *eckey_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); if (ctx != NULL) { mbedtls_ecp_keypair_init(ctx); } return ctx; } static void eckey_free_wrap(void *ctx) { mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ static void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) items->type = MBEDTLS_PK_DEBUG_PSA_EC; items->name = "eckey.Q"; items->value = pk; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; items->type = MBEDTLS_PK_DEBUG_ECP; items->name = "eckey.Q"; items->value = &(ecp->Q); #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ } const mbedtls_pk_info_t mbedtls_eckey_info = { .type = MBEDTLS_PK_ECKEY, .name = "EC", .get_bitlen = eckey_get_bitlen, .can_do = eckey_can_do, #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .verify_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .sign_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = eckey_verify_rs_wrap, .sign_rs_func = eckey_sign_rs_wrap, .rs_alloc_func = eckey_rs_alloc, .rs_free_func = eckey_rs_free, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = eckey_check_pair_wrap, #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) .ctx_alloc_func = NULL, .ctx_free_func = NULL, #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ .ctx_alloc_func = eckey_alloc_wrap, .ctx_free_func = eckey_free_wrap, #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ .debug_func = eckey_debug, }; /* * EC key restricted to ECDH */ static int eckeydh_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH; } const mbedtls_pk_info_t mbedtls_eckeydh_info = { .type = MBEDTLS_PK_ECKEY_DH, .name = "EC_DH", .get_bitlen = eckey_get_bitlen, /* Same underlying key structure */ .can_do = eckeydh_can_do, .verify_func = NULL, .sign_func = NULL, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = eckey_check_pair_wrap, #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) .ctx_alloc_func = NULL, .ctx_free_func = NULL, #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ .ctx_alloc_func = eckey_alloc_wrap, /* Same underlying key structure */ .ctx_free_func = eckey_free_wrap, /* Same underlying key structure */ #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ .debug_func = eckey_debug, /* Same underlying key structure */ }; #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) static int ecdsa_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECDSA; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) static int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) md_alg); ret = mbedtls_ecdsa_read_signature_restartable( (mbedtls_ecdsa_context *) pk->pk_ctx, hash, hash_len, sig, sig_len, (mbedtls_ecdsa_restart_ctx *) rs_ctx); if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; } return ret; } static int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx) { return mbedtls_ecdsa_write_signature_restartable( (mbedtls_ecdsa_context *) pk->pk_ctx, md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, (mbedtls_ecdsa_restart_ctx *) rs_ctx); } static void *ecdsa_rs_alloc(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); if (ctx != NULL) { mbedtls_ecdsa_restart_init(ctx); } return ctx; } static void ecdsa_rs_free(void *ctx) { mbedtls_ecdsa_restart_free(ctx); mbedtls_free(ctx); } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ const mbedtls_pk_info_t mbedtls_ecdsa_info = { .type = MBEDTLS_PK_ECDSA, .name = "ECDSA", .get_bitlen = eckey_get_bitlen, /* Compatible key structures */ .can_do = ecdsa_can_do, #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .verify_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ #else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ .sign_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = ecdsa_verify_rs_wrap, .sign_rs_func = ecdsa_sign_rs_wrap, .rs_alloc_func = ecdsa_rs_alloc, .rs_free_func = ecdsa_rs_free, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = eckey_check_pair_wrap, /* Compatible key structures */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) .ctx_alloc_func = NULL, .ctx_free_func = NULL, #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ .ctx_alloc_func = eckey_alloc_wrap, /* Compatible key structures */ .ctx_free_func = eckey_free_wrap, /* Compatible key structures */ #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ .debug_func = eckey_debug, /* Compatible key structures */ }; #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* * Support for alternative RSA-private implementations */ static int rsa_alt_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_RSA; } static size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk) { const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; return 8 * rsa_alt->key_len_func(rsa_alt->key); } static int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; #if SIZE_MAX > UINT_MAX if (UINT_MAX < hash_len) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } #endif *sig_len = rsa_alt->key_len_func(rsa_alt->key); if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } if (*sig_len > sig_size) { return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; } return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, md_alg, (unsigned int) hash_len, hash, sig); } static int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; ((void) f_rng); ((void) p_rng); if (ilen != rsa_alt->key_len_func(rsa_alt->key)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return rsa_alt->decrypt_func(rsa_alt->key, olen, input, output, osize); } #if defined(MBEDTLS_RSA_C) static int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; unsigned char hash[32]; size_t sig_len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } memset(hash, 0x2a, sizeof(hash)); if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE, hash, sizeof(hash), sig, sizeof(sig), &sig_len, f_rng, p_rng)) != 0) { return ret; } if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE, hash, sizeof(hash), sig, sig_len) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return 0; } #endif /* MBEDTLS_RSA_C */ static void *rsa_alt_alloc_wrap(void) { void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context)); if (ctx != NULL) { memset(ctx, 0, sizeof(mbedtls_rsa_alt_context)); } return ctx; } static void rsa_alt_free_wrap(void *ctx) { mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context)); } const mbedtls_pk_info_t mbedtls_rsa_alt_info = { .type = MBEDTLS_PK_RSA_ALT, .name = "RSA-alt", .get_bitlen = rsa_alt_get_bitlen, .can_do = rsa_alt_can_do, .verify_func = NULL, .sign_func = rsa_alt_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = rsa_alt_decrypt_wrap, .encrypt_func = NULL, #if defined(MBEDTLS_RSA_C) .check_pair_func = rsa_alt_check_pair, #else .check_pair_func = NULL, #endif .ctx_alloc_func = rsa_alt_alloc_wrap, .ctx_free_func = rsa_alt_free_wrap, .debug_func = NULL, }; #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static size_t opaque_get_bitlen(mbedtls_pk_context *pk) { size_t bits; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) { return 0; } bits = psa_get_key_bits(&attributes); psa_reset_key_attributes(&attributes); return bits; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) static int ecdsa_opaque_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECDSA; } const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = { .type = MBEDTLS_PK_OPAQUE, .name = "Opaque", .get_bitlen = opaque_get_bitlen, .can_do = ecdsa_opaque_can_do, #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) .verify_func = ecdsa_opaque_verify_wrap, #else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ .verify_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) .sign_func = ecdsa_opaque_sign_wrap, #else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ .sign_func = NULL, #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ .decrypt_func = NULL, .encrypt_func = NULL, .check_pair_func = ecdsa_opaque_check_pair_wrap, .ctx_alloc_func = NULL, .ctx_free_func = NULL, .debug_func = NULL, }; #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ static int rsa_opaque_can_do(mbedtls_pk_type_t type) { return type == MBEDTLS_PK_RSA || type == MBEDTLS_PK_RSASSA_PSS; } #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) static int rsa_opaque_decrypt(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; psa_key_type_t type; psa_status_t status; /* PSA has its own RNG */ (void) f_rng; (void) p_rng; status = psa_get_key_attributes(pk->priv_id, &attributes); if (status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(status); } type = psa_get_key_type(&attributes); alg = psa_get_key_algorithm(&attributes); psa_reset_key_attributes(&attributes); if (!PSA_KEY_TYPE_IS_RSA(type)) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } status = psa_asymmetric_decrypt(pk->priv_id, alg, input, ilen, NULL, 0, output, osize, olen); if (status != PSA_SUCCESS) { return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } return 0; } #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ static int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_RSA_C) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; psa_key_type_t type; psa_status_t status; /* PSA has its own RNG */ (void) f_rng; (void) p_rng; status = psa_get_key_attributes(pk->priv_id, &attributes); if (status != PSA_SUCCESS) { return PSA_PK_TO_MBEDTLS_ERR(status); } type = psa_get_key_type(&attributes); alg = psa_get_key_algorithm(&attributes); psa_reset_key_attributes(&attributes); if (PSA_KEY_TYPE_IS_RSA(type)) { alg = (alg & ~PSA_ALG_HASH_MASK) | mbedtls_md_psa_alg_from_type(md_alg); } else { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, sig, sig_size, sig_len); if (status != PSA_SUCCESS) { if (PSA_KEY_TYPE_IS_RSA(type)) { return PSA_PK_RSA_TO_MBEDTLS_ERR(status); } else { return PSA_PK_TO_MBEDTLS_ERR(status); } } return 0; #else /* !MBEDTLS_RSA_C */ ((void) pk); ((void) md_alg); ((void) hash); ((void) hash_len); ((void) sig); ((void) sig_size); ((void) sig_len); ((void) f_rng); ((void) p_rng); return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; #endif /* !MBEDTLS_RSA_C */ } const mbedtls_pk_info_t mbedtls_rsa_opaque_info = { .type = MBEDTLS_PK_OPAQUE, .name = "Opaque", .get_bitlen = opaque_get_bitlen, .can_do = rsa_opaque_can_do, .verify_func = NULL, .sign_func = rsa_opaque_sign_wrap, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) .verify_rs_func = NULL, .sign_rs_func = NULL, .rs_alloc_func = NULL, .rs_free_func = NULL, #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) .decrypt_func = rsa_opaque_decrypt, #else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ .decrypt_func = NULL, #endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ .encrypt_func = NULL, .check_pair_func = NULL, .ctx_alloc_func = NULL, .ctx_free_func = NULL, .debug_func = NULL, }; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pk_wrap.h000066400000000000000000000112371464416617300231540ustar00rootroot00000000000000/** * \file pk_wrap.h * * \brief Public Key abstraction layer: wrapper functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_WRAP_H #define MBEDTLS_PK_WRAP_H #include "mbedtls/build_info.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif struct mbedtls_pk_info_t { /** Public key type */ mbedtls_pk_type_t type; /** Type name */ const char *name; /** Get key size in bits */ size_t (*get_bitlen)(mbedtls_pk_context *pk); /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ int (*can_do)(mbedtls_pk_type_t type); /** Verify signature */ int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len); /** Make signature */ int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Verify signature (restartable) */ int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, void *rs_ctx); /** Make signature (restartable) */ int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Decrypt message */ int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Encrypt message */ int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Check public-private key pair */ int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** Allocate a new context */ void * (*ctx_alloc_func)(void); /** Free the given context */ void (*ctx_free_func)(void *ctx); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Allocate the restart context */ void *(*rs_alloc_func)(void); /** Free the restart context */ void (*rs_free_func)(void *rs_ctx); #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Interface with the debug module */ void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items); }; #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) /* Container for RSA-alt */ typedef struct { void *key; mbedtls_pk_rsa_alt_decrypt_func decrypt_func; mbedtls_pk_rsa_alt_sign_func sign_func; mbedtls_pk_rsa_alt_key_len_func key_len_func; } mbedtls_rsa_alt_context; #endif #if defined(MBEDTLS_RSA_C) extern const mbedtls_pk_info_t mbedtls_rsa_info; #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) extern const mbedtls_pk_info_t mbedtls_eckey_info; extern const mbedtls_pk_info_t mbedtls_eckeydh_info; #endif #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) extern const mbedtls_pk_info_t mbedtls_ecdsa_info; #endif #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info; extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info; #if defined(MBEDTLS_RSA_C) int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md, mbedtls_rsa_context *rsa_ctx, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t sig_size, size_t *sig_len); #endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_PK_WRAP_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pkcs12.c000066400000000000000000000323561464416617300226140ustar00rootroot00000000000000/* * PKCS#12 Personal Information Exchange Syntax * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 * * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn */ #include "common.h" #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #include "mbedtls/asn1.h" #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif /* MBEDTLS_CIPHER_C */ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_DES_C) #include "mbedtls/des.h" #endif #include "psa_util_internal.h" #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char **p = ¶ms->p; const unsigned char *end = params->p + params->len; /* * pkcs-12PbeParams ::= SEQUENCE { * salt OCTET STRING, * iterations INTEGER * } * */ if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } if ((ret = mbedtls_asn1_get_tag(p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret); } salt->p = *p; *p += salt->len; if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret); } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } #define PKCS12_MAX_PWDLEN 128 static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, unsigned char *key, size_t keylen, unsigned char *iv, size_t ivlen) { int ret, iterations = 0; mbedtls_asn1_buf salt; size_t i; unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; if (pwdlen > PKCS12_MAX_PWDLEN) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } memset(&salt, 0, sizeof(mbedtls_asn1_buf)); memset(&unipwd, 0, sizeof(unipwd)); if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt, &iterations)) != 0) { return ret; } for (i = 0; i < pwdlen; i++) { unipwd[i * 2 + 1] = pwd[i]; } if ((ret = mbedtls_pkcs12_derivation(key, keylen, unipwd, pwdlen * 2 + 2, salt.p, salt.len, md_type, MBEDTLS_PKCS12_DERIVE_KEY, iterations)) != 0) { return ret; } if (iv == NULL || ivlen == 0) { return 0; } if ((ret = mbedtls_pkcs12_derivation(iv, ivlen, unipwd, pwdlen * 2 + 2, salt.p, salt.len, md_type, MBEDTLS_PKCS12_DERIVE_IV, iterations)) != 0) { return ret; } return 0; } #undef PKCS12_MAX_PWDLEN #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output, size_t output_size, size_t *output_len); #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output) { size_t output_len = 0; /* We assume caller of the function is providing a big enough output buffer * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees * for the output size actually being correct. */ return mbedtls_pkcs12_pbe_ext(pbe_params, mode, cipher_type, md_type, pwd, pwdlen, data, len, output, SIZE_MAX, &output_len); } #endif int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode, mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t len, unsigned char *output, size_t output_size, size_t *output_len) { int ret, keylen = 0; unsigned char key[32]; unsigned char iv[16]; const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_context_t cipher_ctx; size_t iv_len = 0; size_t finish_olen = 0; unsigned int padlen = 0; if (pwd == NULL && pwdlen != 0) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (cipher_info == NULL) { return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; } keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { if (output_size < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } if (mode == MBEDTLS_PKCS12_PBE_ENCRYPT) { padlen = cipher_info->block_size - (len % cipher_info->block_size); if (output_size < (len + padlen)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } iv_len = mbedtls_cipher_info_get_iv_size(cipher_info); if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen, key, keylen, iv, iv_len)) != 0) { return ret; } mbedtls_cipher_init(&cipher_ctx); if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { goto exit; } if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode)) != 0) { goto exit; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) { /* PKCS12 uses CBC with PKCS7 padding */ mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) /* For historical reasons, when decrypting, this function works when * decrypting even when support for PKCS7 padding is disabled. In this * case, it ignores the padding, and so will never report a * password mismatch. */ if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) { padding = MBEDTLS_PADDING_NONE; } #endif if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { goto exit; } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen); if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) { ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; } *output_len += finish_olen; exit: mbedtls_platform_zeroize(key, sizeof(key)); mbedtls_platform_zeroize(iv, sizeof(iv)); mbedtls_cipher_free(&cipher_ctx); return ret; } #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ static void pkcs12_fill_buffer(unsigned char *data, size_t data_len, const unsigned char *filler, size_t fill_len) { unsigned char *p = data; size_t use_len; if (filler != NULL && fill_len != 0) { while (data_len > 0) { use_len = (data_len > fill_len) ? fill_len : data_len; memcpy(p, filler, use_len); p += use_len; data_len -= use_len; } } else { /* If either of the above are not true then clearly there is nothing * that this function can do. The function should *not* be called * under either of those circumstances, as you could end up with an * incorrect output but for safety's sake, leaving the check in as * otherwise we could end up with memory corruption.*/ } } static int calculate_hashes(mbedtls_md_type_t md_type, int iterations, unsigned char *diversifier, unsigned char *salt_block, unsigned char *pwd_block, unsigned char *hash_output, int use_salt, int use_password, size_t hlen, size_t v) { int ret = -1; size_t i; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; md_info = mbedtls_md_info_from_type(md_type); if (md_info == NULL) { return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { return ret; } // Calculate hash( diversifier || salt_block || pwd_block ) if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) { goto exit; } if (use_salt != 0) { if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) { goto exit; } } if (use_password != 0) { if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) { goto exit; } } if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) { goto exit; } // Perform remaining ( iterations - 1 ) recursive hash calculations for (i = 1; i < (size_t) iterations; i++) { if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output)) != 0) { goto exit; } } exit: mbedtls_md_free(&md_ctx); return ret; } int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen, const unsigned char *pwd, size_t pwdlen, const unsigned char *salt, size_t saltlen, mbedtls_md_type_t md_type, int id, int iterations) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int j; unsigned char diversifier[128]; unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 }; unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; unsigned char *p; unsigned char c; int use_password = 0; int use_salt = 0; size_t hlen, use_len, v, i; // This version only allows max of 64 bytes of password or salt if (datalen > 128 || pwdlen > 64 || saltlen > 64) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } if (pwd == NULL && pwdlen != 0) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } if (salt == NULL && saltlen != 0) { return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA; } use_password = (pwd && pwdlen != 0); use_salt = (salt && saltlen != 0); hlen = mbedtls_md_get_size_from_type(md_type); if (hlen <= 32) { v = 64; } else { v = 128; } memset(diversifier, (unsigned char) id, v); if (use_salt != 0) { pkcs12_fill_buffer(salt_block, v, salt, saltlen); } if (use_password != 0) { pkcs12_fill_buffer(pwd_block, v, pwd, pwdlen); } p = data; while (datalen > 0) { if (calculate_hashes(md_type, iterations, diversifier, salt_block, pwd_block, hash_output, use_salt, use_password, hlen, v) != 0) { goto exit; } use_len = (datalen > hlen) ? hlen : datalen; memcpy(p, hash_output, use_len); datalen -= use_len; p += use_len; if (datalen == 0) { break; } // Concatenating copies of hash_output into hash_block (B) pkcs12_fill_buffer(hash_block, v, hash_output, hlen); // B += 1 for (i = v; i > 0; i--) { if (++hash_block[i - 1] != 0) { break; } } if (use_salt != 0) { // salt_block += B c = 0; for (i = v; i > 0; i--) { j = salt_block[i - 1] + hash_block[i - 1] + c; c = MBEDTLS_BYTE_1(j); salt_block[i - 1] = MBEDTLS_BYTE_0(j); } } if (use_password != 0) { // pwd_block += B c = 0; for (i = v; i > 0; i--) { j = pwd_block[i - 1] + hash_block[i - 1] + c; c = MBEDTLS_BYTE_1(j); pwd_block[i - 1] = MBEDTLS_BYTE_0(j); } } } ret = 0; exit: mbedtls_platform_zeroize(salt_block, sizeof(salt_block)); mbedtls_platform_zeroize(pwd_block, sizeof(pwd_block)); mbedtls_platform_zeroize(hash_block, sizeof(hash_block)); mbedtls_platform_zeroize(hash_output, sizeof(hash_output)); return ret; } #endif /* MBEDTLS_PKCS12_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pkcs5.c000066400000000000000000000361771464416617300225430ustar00rootroot00000000000000/** * \file pkcs5.c * * \brief PKCS#5 functions * * \author Mathias Olsson * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * PKCS#5 includes PBKDF2 and more * * http://tools.ietf.org/html/rfc2898 (Specification) * http://tools.ietf.org/html/rfc6070 (Test vectors) */ #include "common.h" #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #include "mbedtls/error.h" #if defined(MBEDTLS_ASN1_PARSE_C) #include "mbedtls/asn1.h" #if defined(MBEDTLS_CIPHER_C) #include "mbedtls/cipher.h" #endif /* MBEDTLS_CIPHER_C */ #include "mbedtls/oid.h" #endif /* MBEDTLS_ASN1_PARSE_C */ #include #include "mbedtls/platform.h" #include "psa_util_internal.h" #if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C) static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params, mbedtls_asn1_buf *salt, int *iterations, int *keylen, mbedtls_md_type_t *md_type) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf prf_alg_oid; unsigned char *p = params->p; const unsigned char *end = params->p + params->len; if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } /* * PBKDF2-params ::= SEQUENCE { * salt OCTET STRING, * iterationCount INTEGER, * keyLength INTEGER OPTIONAL * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 * } * */ if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } salt->p = p; p += salt->len; if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } if (p == end) { return 0; } if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) { if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } } if (p == end) { return 0; } if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output, size_t output_size, size_t *output_len); #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output) { size_t output_len = 0; /* We assume caller of the function is providing a big enough output buffer * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees * for the output size actually being correct. */ return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data, datalen, output, SIZE_MAX, &output_len); } #endif int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode, const unsigned char *pwd, size_t pwdlen, const unsigned char *data, size_t datalen, unsigned char *output, size_t output_size, size_t *output_len) { int ret, iterations = 0, keylen = 0; unsigned char *p, *end; mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; mbedtls_asn1_buf salt; mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; unsigned char key[32], iv[32]; const mbedtls_cipher_info_t *cipher_info; mbedtls_cipher_type_t cipher_alg; mbedtls_cipher_context_t cipher_ctx; unsigned int padlen = 0; p = pbe_params->p; end = p + pbe_params->len; /* * PBES2-params ::= SEQUENCE { * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} * } */ if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid, &kdf_alg_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } // Only PBKDF2 supported at the moment // if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params, &salt, &iterations, &keylen, &md_type)) != 0) { return ret; } if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid, &enc_scheme_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); } if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } cipher_info = mbedtls_cipher_info_from_type(cipher_alg); if (cipher_info == NULL) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } /* * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored * since it is optional and we don't know if it was set or not */ keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) { return MBEDTLS_ERR_PKCS5_INVALID_FORMAT; } if (mode == MBEDTLS_PKCS5_DECRYPT) { if (output_size < datalen) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } if (mode == MBEDTLS_PKCS5_ENCRYPT) { padlen = cipher_info->block_size - (datalen % cipher_info->block_size); if (output_size < (datalen + padlen)) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } } mbedtls_cipher_init(&cipher_ctx); memcpy(iv, enc_scheme_params.p, enc_scheme_params.len); if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p, salt.len, iterations, keylen, key)) != 0) { goto exit; } if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) { goto exit; } if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode)) != 0) { goto exit; } #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) { /* PKCS5 uses CBC with PKCS7 padding (which is the same as * "PKCS5 padding" except that it's typically only called PKCS5 * with 64-bit-block ciphers). */ mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7; #if !defined(MBEDTLS_CIPHER_PADDING_PKCS7) /* For historical reasons, when decrypting, this function works when * decrypting even when support for PKCS7 padding is disabled. In this * case, it ignores the padding, and so will never report a * password mismatch. */ if (mode == MBEDTLS_DECRYPT) { padding = MBEDTLS_PADDING_NONE; } #endif if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) { goto exit; } } #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len, data, datalen, output, output_len)) != 0) { ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; } exit: mbedtls_cipher_free(&cipher_ctx); return ret; } #endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */ static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int i; unsigned char md1[MBEDTLS_MD_MAX_SIZE]; unsigned char work[MBEDTLS_MD_MAX_SIZE]; unsigned char md_size = mbedtls_md_get_size(ctx->md_info); size_t use_len; unsigned char *out_p = output; unsigned char counter[4]; memset(counter, 0, 4); counter[3] = 1; #if UINT_MAX > 0xFFFFFFFF if (iteration_count > 0xFFFFFFFF) { return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA; } #endif if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) { return ret; } while (key_length) { // U1 ends up in work // if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { goto cleanup; } memcpy(md1, work, md_size); for (i = 1; i < iteration_count; i++) { // U2 ends up in md1 // if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) { goto cleanup; } if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) { goto cleanup; } // U1 xor U2 // mbedtls_xor(work, work, md1, md_size); } use_len = (key_length < md_size) ? key_length : md_size; memcpy(out_p, work, use_len); key_length -= (uint32_t) use_len; out_p += use_len; for (i = 4; i > 0; i--) { if (++counter[i - 1] != 0) { break; } } } cleanup: /* Zeroise buffers to clear sensitive data from memory. */ mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE); mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE); return ret; } #if !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output) { return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count, key_length, output); } #endif int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg, const unsigned char *password, size_t plen, const unsigned char *salt, size_t slen, unsigned int iteration_count, uint32_t key_length, unsigned char *output) { mbedtls_md_context_t md_ctx; const mbedtls_md_info_t *md_info = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { goto exit; } ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen, iteration_count, key_length, output); exit: mbedtls_md_free(&md_ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) #if !defined(MBEDTLS_MD_CAN_SHA1) int mbedtls_pkcs5_self_test(int verbose) { if (verbose != 0) { mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n"); } return 0; } #else #define MAX_TESTS 6 static const size_t plen_test_data[MAX_TESTS] = { 8, 8, 8, 24, 9 }; static const unsigned char password_test_data[MAX_TESTS][32] = { "password", "password", "password", "passwordPASSWORDpassword", "pass\0word", }; static const size_t slen_test_data[MAX_TESTS] = { 4, 4, 4, 36, 5 }; static const unsigned char salt_test_data[MAX_TESTS][40] = { "salt", "salt", "salt", "saltSALTsaltSALTsaltSALTsaltSALTsalt", "sa\0lt", }; static const uint32_t it_cnt_test_data[MAX_TESTS] = { 1, 2, 4096, 4096, 4096 }; static const uint32_t key_len_test_data[MAX_TESTS] = { 20, 20, 20, 25, 16 }; static const unsigned char result_key_test_data[MAX_TESTS][32] = { { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6 }, { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57 }, { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, 0x65, 0xa4, 0x29, 0xc1 }, { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, 0x38 }, { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, }; int mbedtls_pkcs5_self_test(int verbose) { int ret, i; unsigned char key[64]; for (i = 0; i < MAX_TESTS; i++) { if (verbose != 0) { mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i); } ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i], plen_test_data[i], salt_test_data[i], slen_test_data[i], it_cnt_test_data[i], key_len_test_data[i], key); if (ret != 0 || memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto exit; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } exit: return ret; } #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_PKCS5_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pkcs7.c000066400000000000000000000543111464416617300225330ustar00rootroot00000000000000/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "mbedtls/build_info.h" #if defined(MBEDTLS_PKCS7_C) #include "mbedtls/pkcs7.h" #include "x509_internal.h" #include "mbedtls/asn1.h" #include "mbedtls/x509_crt.h" #include "mbedtls/x509_crl.h" #include "mbedtls/oid.h" #include "mbedtls/error.h" #if defined(MBEDTLS_FS_IO) #include #include #endif #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) #include #endif /** * Initializes the mbedtls_pkcs7 structure. */ void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7) { memset(pkcs7, 0, sizeof(*pkcs7)); } static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end, size_t *len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } else if ((size_t) (end - *p) != *len) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return ret; } /** * version Version * Version ::= INTEGER **/ static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_asn1_get_int(p, end, ver); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret); } /* If version != 1, return invalid version */ if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) { ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION; } return ret; } /** * ContentInfo ::= SEQUENCE { * contentType ContentType, * content * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } **/ static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end, unsigned char **seq_end, mbedtls_pkcs7_buf *pkcs7) { size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *start = *p; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { *p = start; return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } *seq_end = *p + len; ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID); if (ret != 0) { *p = start; return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } pkcs7->tag = MBEDTLS_ASN1_OID; pkcs7->len = len; pkcs7->p = *p; *p += len; return ret; } /** * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * This is from x509.h **/ static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end, mbedtls_x509_buf *alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); } return ret; } /** * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier **/ static int pkcs7_get_digest_algorithm_set(unsigned char **p, unsigned char *end, mbedtls_x509_buf *alg) { size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); } end = *p + len; ret = mbedtls_asn1_get_alg_null(p, end, alg); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret); } /** For now, it assumes there is only one digest algorithm specified **/ if (*p != end) { return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } return 0; } /** * certificates :: SET OF ExtendedCertificateOrCertificate, * ExtendedCertificateOrCertificate ::= CHOICE { * certificate Certificate -- x509, * extendedCertificate[0] IMPLICIT ExtendedCertificate } * Return number of certificates added to the signed data, * 0 or higher is valid. * Return negative error code for failure. **/ static int pkcs7_get_certificates(unsigned char **p, unsigned char *end, mbedtls_x509_crt *certs) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len1 = 0; size_t len2 = 0; unsigned char *end_set, *end_cert, *start; ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return 0; } if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); } start = *p; end_set = *p + len1; ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret); } end_cert = *p + len2; /* * This is to verify that there is only one signer certificate. It seems it is * not easy to differentiate between the chain vs different signer's certificate. * So, we support only the root certificate and the single signer. * The behaviour would be improved with addition of multiple signer support. */ if (end_cert != end_set) { return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) { return MBEDTLS_ERR_PKCS7_INVALID_CERT; } *p = end_cert; /* * Since in this version we strictly support single certificate, and reaching * here implies we have parsed successfully, we return 1. */ return 1; } /** * EncryptedDigest ::= OCTET STRING **/ static int pkcs7_get_signature(unsigned char **p, unsigned char *end, mbedtls_pkcs7_buf *signature) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING); if (ret != 0) { return ret; } signature->tag = MBEDTLS_ASN1_OCTET_STRING; signature->len = len; signature->p = *p; *p = *p + len; return 0; } static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer) { mbedtls_x509_name *name_cur; mbedtls_x509_name *name_prv; if (signer == NULL) { return; } name_cur = signer->issuer.next; while (name_cur != NULL) { name_prv = name_cur; name_cur = name_cur->next; mbedtls_free(name_prv); } signer->issuer.next = NULL; } /** * SignerInfo ::= SEQUENCE { * version Version; * issuerAndSerialNumber IssuerAndSerialNumber, * digestAlgorithm DigestAlgorithmIdentifier, * authenticatedAttributes * [0] IMPLICIT Attributes OPTIONAL, * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, * encryptedDigest EncryptedDigest, * unauthenticatedAttributes * [1] IMPLICIT Attributes OPTIONAL, * Returns 0 if the signerInfo is valid. * Return negative error code for failure. * Structure must not contain vales for authenticatedAttributes * and unauthenticatedAttributes. **/ static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end, mbedtls_pkcs7_signer_info *signer, mbedtls_x509_buf *alg) { unsigned char *end_signer, *end_issuer_and_sn; int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (asn1_ret != 0) { goto out; } end_signer = *p + len; ret = pkcs7_get_version(p, end_signer, &signer->version); if (ret != 0) { goto out; } asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (asn1_ret != 0) { goto out; } end_issuer_and_sn = *p + len; /* Parsing IssuerAndSerialNumber */ signer->issuer_raw.p = *p; asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (asn1_ret != 0) { goto out; } ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer); if (ret != 0) { goto out; } signer->issuer_raw.len = (size_t) (*p - signer->issuer_raw.p); ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial); if (ret != 0) { goto out; } /* ensure no extra or missing bytes */ if (*p != end_issuer_and_sn) { ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; goto out; } ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier); if (ret != 0) { goto out; } /* Check that the digest algorithm used matches the one provided earlier */ if (signer->alg_identifier.tag != alg->tag || signer->alg_identifier.len != alg->len || memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) { ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; goto out; } /* Assume authenticatedAttributes is nonexistent */ ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier); if (ret != 0) { goto out; } ret = pkcs7_get_signature(p, end_signer, &signer->sig); if (ret != 0) { goto out; } /* Do not permit any unauthenticated attributes */ if (*p != end_signer) { ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO; } out: if (asn1_ret != 0 || ret != 0) { pkcs7_free_signer_info(signer); ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, asn1_ret); } return ret; } /** * SignerInfos ::= SET of SignerInfo * Return number of signers added to the signed data, * 0 or higher is valid. * Return negative error code for failure. **/ static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end, mbedtls_pkcs7_signer_info *signers_set, mbedtls_x509_buf *digest_alg) { unsigned char *end_set; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int count = 0; size_t len = 0; ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret); } /* Detect zero signers */ if (len == 0) { return 0; } end_set = *p + len; ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg); if (ret != 0) { return ret; } count++; mbedtls_pkcs7_signer_info *prev = signers_set; while (*p != end_set) { mbedtls_pkcs7_signer_info *signer = mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info)); if (!signer) { ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; goto cleanup; } ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg); if (ret != 0) { mbedtls_free(signer); goto cleanup; } prev->next = signer; prev = signer; count++; } return count; cleanup: pkcs7_free_signer_info(signers_set); mbedtls_pkcs7_signer_info *signer = signers_set->next; while (signer != NULL) { prev = signer; signer = signer->next; pkcs7_free_signer_info(prev); mbedtls_free(prev); } signers_set->next = NULL; return ret; } /** * SignedData ::= SEQUENCE { * version Version, * digestAlgorithms DigestAlgorithmIdentifiers, * contentInfo ContentInfo, * certificates * [0] IMPLICIT ExtendedCertificatesAndCertificates * OPTIONAL, * crls * [0] IMPLICIT CertificateRevocationLists OPTIONAL, * signerInfos SignerInfos } */ static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen, mbedtls_pkcs7_signed_data *signed_data) { unsigned char *p = buf; unsigned char *end = buf + buflen; unsigned char *end_content_info = NULL; size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); } if (p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* Get version of signed data */ ret = pkcs7_get_version(&p, end, &signed_data->version); if (ret != 0) { return ret; } /* Get digest algorithm */ ret = pkcs7_get_digest_algorithm_set(&p, end, &signed_data->digest_alg_identifiers); if (ret != 0) { return ret; } ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg); if (ret != 0) { return MBEDTLS_ERR_PKCS7_INVALID_ALG; } mbedtls_pkcs7_buf content_type; memset(&content_type, 0, sizeof(content_type)); ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type); if (ret != 0) { return ret; } if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) { return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO; } if (p != end_content_info) { /* Determine if valid content is present */ ret = mbedtls_asn1_get_tag(&p, end_content_info, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } p += len; if (p != end_content_info) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret); } /* Valid content is present - this is not supported */ return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } /* Look for certificates, there may or may not be any */ mbedtls_x509_crt_init(&signed_data->certs); ret = pkcs7_get_certificates(&p, end, &signed_data->certs); if (ret < 0) { return ret; } signed_data->no_of_certs = ret; /* * Currently CRLs are not supported. If CRL exist, the parsing will fail * at next step of getting signers info and return error as invalid * signer info. */ signed_data->no_of_crls = 0; /* Get signers info */ ret = pkcs7_get_signers_info_set(&p, end, &signed_data->signers, &signed_data->digest_alg_identifiers); if (ret < 0) { return ret; } signed_data->no_of_signers = ret; /* Don't permit trailing data */ if (p != end) { return MBEDTLS_ERR_PKCS7_INVALID_FORMAT; } return 0; } int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf, const size_t buflen) { unsigned char *p; unsigned char *end; size_t len = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (pkcs7 == NULL) { return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } /* make an internal copy of the buffer for parsing */ pkcs7->raw.p = p = mbedtls_calloc(1, buflen); if (pkcs7->raw.p == NULL) { ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED; goto out; } memcpy(p, buf, buflen); pkcs7->raw.len = buflen; end = p + buflen; ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret); goto out; } if ((size_t) (end - p) != len) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); goto out; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { goto out; } p = pkcs7->raw.p; len = buflen; goto try_data; } if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) { /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */ if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len) || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) { /* OID is valid according to the spec, but unsupported */ ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE; } else { /* OID is invalid according to the spec */ ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } goto out; } p += len; ret = pkcs7_get_next_content_len(&p, end, &len); if (ret != 0) { goto out; } /* ensure no extra/missing data */ if (p + len != end) { ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; goto out; } try_data: ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data); if (ret != 0) { goto out; } ret = MBEDTLS_PKCS7_SIGNED_DATA; out: if (ret < 0) { mbedtls_pkcs7_free(pkcs7); } return ret; } static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *data, size_t datalen, const int is_data_hash) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *hash; mbedtls_pk_context pk_cxt = cert->pk; const mbedtls_md_info_t *md_info; mbedtls_md_type_t md_alg; mbedtls_pkcs7_signer_info *signer; if (pkcs7->signed_data.no_of_signers == 0) { return MBEDTLS_ERR_PKCS7_INVALID_CERT; } if (mbedtls_x509_time_is_past(&cert->valid_to) || mbedtls_x509_time_is_future(&cert->valid_from)) { return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID; } ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg); if (ret != 0) { return ret; } md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1); if (hash == NULL) { return MBEDTLS_ERR_PKCS7_ALLOC_FAILED; } /* BEGIN must free hash before jumping out */ if (is_data_hash) { if (datalen != mbedtls_md_get_size(md_info)) { ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } else { memcpy(hash, data, datalen); } } else { ret = mbedtls_md(md_info, data, datalen, hash); } if (ret != 0) { mbedtls_free(hash); return MBEDTLS_ERR_PKCS7_VERIFY_FAIL; } /* assume failure */ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL; /* * Potential TODOs * Currently we iterate over all signers and return success if any of them * verify. * * However, we could make this better by checking against the certificate's * identification and SignerIdentifier fields first. That would also allow * us to distinguish between 'no signature for key' and 'signature for key * failed to validate'. */ for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) { ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash, mbedtls_md_get_size(md_info), signer->sig.p, signer->sig.len); if (ret == 0) { break; } } mbedtls_free(hash); /* END must free hash before jumping out */ return ret; } int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *data, size_t datalen) { if (data == NULL) { return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0); } int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7, const mbedtls_x509_crt *cert, const unsigned char *hash, size_t hashlen) { if (hash == NULL) { return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA; } return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1); } /* * Unallocate all pkcs7 data */ void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7) { mbedtls_pkcs7_signer_info *signer_cur; mbedtls_pkcs7_signer_info *signer_prev; if (pkcs7 == NULL || pkcs7->raw.p == NULL) { return; } mbedtls_free(pkcs7->raw.p); mbedtls_x509_crt_free(&pkcs7->signed_data.certs); mbedtls_x509_crl_free(&pkcs7->signed_data.crl); signer_cur = pkcs7->signed_data.signers.next; pkcs7_free_signer_info(&pkcs7->signed_data.signers); while (signer_cur != NULL) { signer_prev = signer_cur; signer_cur = signer_prev->next; pkcs7_free_signer_info(signer_prev); mbedtls_free(signer_prev); } pkcs7->raw.p = NULL; } #endif optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pkparse.c000066400000000000000000001247571464416617300231650ustar00rootroot00000000000000/* * Public Key layer for parsing key files and structures * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_PARSE_C) #include "mbedtls/pk.h" #include "mbedtls/asn1.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" #include "mbedtls/error.h" #include "mbedtls/ecp.h" #include "pk_internal.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" #include "psa/crypto.h" #endif /* Key types */ #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "rsa_internal.h" #endif /* Extended formats */ #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #endif #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /*********************************************************************** * * Low-level ECC parsing: optional support for SpecifiedECDomain * * There are two functions here that are used by the rest of the code: * - pk_ecc_tag_is_speficied_ec_domain() * - pk_ecc_group_id_from_specified() * * All the other functions are internal to this section. * * The two "public" functions have a dummy variant provided * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an * abstraction layer for this macro, which should not appear outside * this section. * **********************************************************************/ #if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED) /* See the "real" version for documentation */ static int pk_ecc_tag_is_specified_ec_domain(int tag) { (void) tag; return 0; } /* See the "real" version for documentation */ static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id *grp_id) { (void) params; (void) grp_id; return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } #else /* MBEDTLS_PK_PARSE_EC_EXTENDED */ /* * Tell if the passed tag might be the start of SpecifiedECDomain * (that is, a sequence). */ static int pk_ecc_tag_is_specified_ec_domain(int tag) { return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with * pk_ecc_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), * fieldID FieldID {{FieldTypes}}, * curve Curve, * base ECPoint, * order INTEGER, * cofactor INTEGER OPTIONAL, * hash HashAlgorithm OPTIONAL, * ... * } * * We only support prime-field as field type, and ignore hash and cofactor. */ static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = params->p; const unsigned char *const end = params->p + params->len; const unsigned char *end_field, *end_curve; size_t len; int ver; /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (ver < 1 || ver > 3) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field * fieldType FIELD-ID.&id({IOSet}), * parameters FIELD-ID.&Type({IOSet}{@fieldType}) * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } end_field = p + len; /* * FIELD-ID ::= TYPE-IDENTIFIER * FieldTypes FIELD-ID ::= { * { Prime-p IDENTIFIED BY prime-field } | * { Characteristic-two IDENTIFIED BY characteristic-two-field } * } * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } */ if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) { return ret; } if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } p += len; /* Prime-p ::= INTEGER -- Field of size p. */ if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } grp->pbits = mbedtls_mpi_bitlen(&grp->P); if (p != end_field) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Curve ::= SEQUENCE { * a FieldElement, * b FieldElement, * seed BIT STRING OPTIONAL * -- Shall be present if used in SpecifiedECDomain * -- with version equal to ecdpVer2 or ecdpVer3 * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } end_curve = p + len; /* * FieldElement ::= OCTET STRING * containing an integer in the case of a prime field */ if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } p += len; if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } p += len; /* Ignore seed BIT STRING OPTIONAL */ if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) { p += len; } if (p != end_curve) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * ECPoint ::= OCTET STRING */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G, (const unsigned char *) p, len)) != 0) { /* * If we can't read the point because it's compressed, cheat by * reading only the X coordinate and the parity bit of Y. */ if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || (p[0] != 0x02 && p[0] != 0x03) || len != mbedtls_mpi_size(&grp->P) + 1 || mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } } p += len; /* * order INTEGER */ if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } grp->nbits = mbedtls_mpi_bitlen(&grp->N); /* * Allow optional elements by purposefully not enforcing p == end here. */ return 0; } /* * Find the group id associated with an (almost filled) group as generated by * pk_group_from_specified(), or return an error if unknown. */ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) { int ret = 0; mbedtls_ecp_group ref; const mbedtls_ecp_group_id *id; mbedtls_ecp_group_init(&ref); for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { /* Load the group associated to that id */ mbedtls_ecp_group_free(&ref); MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); /* Compare to the group we were given, starting with easy tests */ if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && /* For Y we may only know the parity bit, so compare only that */ mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { break; } } cleanup: mbedtls_ecp_group_free(&ref); *grp_id = *id; if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) { ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; } return ret; } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID */ static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id *grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group grp; mbedtls_ecp_group_init(&grp); if ((ret = pk_group_from_specified(params, &grp)) != 0) { goto cleanup; } ret = pk_group_id_from_group(&grp, grp_id); cleanup: /* The API respecting lifecycle for mbedtls_ecp_group struct is * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the * temporary grp breaks that flow and it's members are populated * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() * which is assuming a group populated by _setup() may not clean-up * properly -> Manually free it's members. */ mbedtls_mpi_free(&grp.N); mbedtls_mpi_free(&grp.P); mbedtls_mpi_free(&grp.A); mbedtls_mpi_free(&grp.B); mbedtls_ecp_point_free(&grp.G); return ret; } #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ /*********************************************************************** * * Unsorted (yet!) from this point on until the next section header * **********************************************************************/ /* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf * * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL * } */ static int pk_get_ecparams(unsigned char **p, const unsigned char *end, mbedtls_asn1_buf *params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (end - *p < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } /* Acceptable tags: OID for namedCurve, or specifiedECDomain */ params->tag = **p; if (params->tag != MBEDTLS_ASN1_OID && !pk_ecc_tag_is_specified_ec_domain(params->tag)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } params->p = *p; *p += params->len; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Use EC parameters to initialise an EC group * * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL */ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_group_id grp_id; if (params->tag == MBEDTLS_ASN1_OID) { if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) { return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; } } else { ret = pk_ecc_group_id_from_specified(params, &grp_id); if (ret != 0) { return ret; } } return mbedtls_pk_ecc_set_group(pk, grp_id); } #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) /* * Load an RFC8410 EC key, which doesn't have any parameters */ static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id grp_id, mbedtls_pk_context *pk) { if (params->tag != 0 || params->len != 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } return mbedtls_pk_ecc_set_group(pk, grp_id); } /* * Parse an RFC 8410 encoded private EC key * * CurvePrivateKey ::= OCTET STRING */ static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk, unsigned char *key, size_t keylen, const unsigned char *end, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (key + len != end) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* * Load the private key */ ret = mbedtls_pk_ecc_set_key(pk, key, len); if (ret != 0) { return ret; } /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys, * which never contain a public key. As such, derive the public key * unconditionally. */ if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) { return ret; } return 0; } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Get a PK algorithm identifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ static int pk_get_pk_alg(unsigned char **p, const unsigned char *end, mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, mbedtls_ecp_group_id *ec_grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_asn1_buf alg_oid; memset(params, 0, sizeof(mbedtls_asn1_buf)); if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); } ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id); if (ret == 0) { *pk_alg = MBEDTLS_PK_ECKEY; } } #else (void) ec_grp_id; #endif if (ret != 0) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } /* * No parameters with RSA (only for EC) */ if (*pk_alg == MBEDTLS_PK_RSA && ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || params->len != 0)) { return MBEDTLS_ERR_PK_INVALID_ALG; } return 0; } /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; mbedtls_asn1_buf alg_params; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; const mbedtls_pk_info_t *pk_info; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = *p + len; if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) { return ret; } if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { return ret; } #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA) { ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p)); if (ret == 0) { /* On success all the input has been consumed by the parsing function. */ *p += end - *p; } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) && (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) { /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */ ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); } else { ret = MBEDTLS_ERR_PK_INVALID_PUBKEY; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk); } else #endif { ret = pk_use_ecparams(&alg_params, pk); } if (ret == 0) { ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p)); *p += end - *p; } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; if (ret == 0 && *p != end) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if (ret != 0) { mbedtls_pk_free(pk); } return ret; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Parse a SEC1 encoded private EC key */ static int pk_parse_key_sec1_der(mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int version, pubkey_done; size_t len, d_len; mbedtls_asn1_buf params = { 0, 0, NULL }; unsigned char *p = (unsigned char *) key; unsigned char *d; unsigned char *end = p + keylen; unsigned char *end2; /* * RFC 5915, or SEC1 Appendix C.4 * * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), * privateKey OCTET STRING, * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, * publicKey [1] BIT STRING OPTIONAL * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = p + len; if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (version != 1) { return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } /* Keep a reference to the position fo the private key. It will be used * later in this function. */ d = p; d_len = len; p += len; pubkey_done = 0; if (p != end) { /* * Is 'parameters' present? */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || (ret = pk_use_ecparams(¶ms, pk)) != 0) { return ret; } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } } /* * Load the private key */ ret = mbedtls_pk_ecc_set_key(pk, d, d_len); if (ret != 0) { return ret; } if (p != end) { /* * Is 'publickey' present? If not, or if we can't read it (eg because it * is compressed), create it from the private key. */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { end2 = p + len; if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (p + len != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) { pubkey_done = 1; } else { /* * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above * is if the point format is not recognized. */ if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } } if (!pubkey_done) { if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) { return ret; } } return 0; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /*********************************************************************** * * PKCS#8 parsing functions * **********************************************************************/ /* * Parse an unencrypted PKCS#8 encoded private key * * Notes: * * - This function does not own the key buffer. It is the * responsibility of the caller to take care of zeroizing * and freeing it after use. * * - The function is responsible for freeing the provided * PK context on failure. * */ static int pk_parse_key_pkcs8_unencrypted_der( mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, version; size_t len; mbedtls_asn1_buf params; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; const mbedtls_pk_info_t *pk_info; #if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) (void) f_rng; (void) p_rng; #endif /* * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) * * PrivateKeyInfo ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL } * * Version ::= INTEGER * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier * PrivateKey ::= OCTET STRING * * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = p + len; if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (version != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); } if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) { return ret; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if (len < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { return ret; } #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA) { if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) { mbedtls_pk_free(pk); return ret; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { if ((ret = pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 || (ret = pk_parse_key_rfc8410_der(pk, p, len, end, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); return ret; } } else #endif { if ((ret = pk_use_ecparams(¶ms, pk)) != 0 || (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); return ret; } } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; end = p + len; if (end != (key + keylen)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse an encrypted PKCS#8 encoded private key * * To save space, the decryption happens in-place on the given key buffer. * Also, while this function may modify the keybuffer, it doesn't own it, * and instead it is the responsibility of the caller to zeroize and properly * free it after use. * */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( mbedtls_pk_context *pk, unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, decrypted = 0; size_t len; unsigned char *buf; unsigned char *p, *end; mbedtls_asn1_buf pbe_alg_oid, pbe_params; #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) mbedtls_cipher_type_t cipher_alg; mbedtls_md_type_t md_alg; #endif size_t outlen = 0; p = key; end = p + keylen; if (pwdlen == 0) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; } /* * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) * * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData * } * * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * * EncryptedData ::= OCTET STRING * * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo * */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } end = p + len; if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); } buf = p; /* * Decrypt EncryptedData with appropriate PBE */ #if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, cipher_alg, md_alg, pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } return ret; } decrypted = 1; } else #endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C) if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } return ret; } decrypted = 1; } else #endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */ { ((void) pwd); } if (decrypted == 0) { return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng); } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ /*********************************************************************** * * Top-level functions, with format auto-discovery * **********************************************************************/ /* * Parse a private key */ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_info_t *pk_info; #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; #endif if (keylen == 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA, key, pwd, pwdlen, &len); } if (ret == 0) { pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), pem.buf, pem.buflen)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PRIVATE_KEY_EC, PEM_END_PRIVATE_KEY_EC, key, pwd, pwdlen, &len); } if (ret == 0) { pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || (ret = pk_parse_key_sec1_der(pk, pem.buf, pem.buflen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8, key, NULL, 0, &len); } if (ret == 0) { if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, pem.buf, pem.buflen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8, PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8, key, NULL, 0, &len); } if (ret == 0) { if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, pwd, pwdlen, f_rng, p_rng)) != 0) { mbedtls_pk_free(pk); } mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else ((void) pwd); ((void) pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ /* * At this point we only know it's not a PEM formatted key. Could be any * of the known DER encoded private key formats * * We try the different DER format parsers to see if one passes without * error */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) if (pwdlen != 0) { unsigned char *key_copy; if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } memcpy(key_copy, key, keylen); ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, pwd, pwdlen, f_rng, p_rng); mbedtls_zeroize_and_free(key_copy, keylen); } if (ret == 0) { return 0; } mbedtls_pk_free(pk); mbedtls_pk_init(pk); if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { return ret; } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); if (ret == 0) { return 0; } mbedtls_pk_free(pk); mbedtls_pk_init(pk); #if defined(MBEDTLS_RSA_C) pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (mbedtls_pk_setup(pk, pk_info) == 0 && mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) { return 0; } mbedtls_pk_free(pk); mbedtls_pk_init(pk); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); if (mbedtls_pk_setup(pk, pk_info) == 0 && pk_parse_key_sec1_der(pk, key, keylen, f_rng, p_rng) == 0) { return 0; } mbedtls_pk_free(pk); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't, * it is ok to leave the PK context initialized but not * freed: It is the caller's responsibility to call pk_init() * before calling this function, and to call pk_free() * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C * isn't, this leads to mbedtls_pk_free() being called * twice, once here and once by the caller, but this is * also ok and in line with the mbedtls_pk_free() calls * on failed PEM parsing attempts. */ return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } /* * Parse a public key */ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p; #if defined(MBEDTLS_RSA_C) const mbedtls_pk_info_t *pk_info; #endif #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; #endif if (keylen == 0) { return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; } #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_init(&pem); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA, key, NULL, 0, &len); } if (ret == 0) { p = pem.buf; if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { mbedtls_pem_free(&pem); return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { mbedtls_pem_free(&pem); return ret; } if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) { mbedtls_pk_free(ctx); } mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { mbedtls_pem_free(&pem); return ret; } #endif /* MBEDTLS_RSA_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (key[keylen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, key, NULL, 0, &len); } if (ret == 0) { /* * Was PEM encoded */ p = pem.buf; ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); mbedtls_pem_free(&pem); return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { mbedtls_pem_free(&pem); return ret; } mbedtls_pem_free(&pem); #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_RSA_C) if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; } if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { return ret; } p = (unsigned char *) key; ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen); if (ret == 0) { return ret; } mbedtls_pk_free(ctx); if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return ret; } #endif /* MBEDTLS_RSA_C */ p = (unsigned char *) key; ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); return ret; } /*********************************************************************** * * Top-level functions, with filesystem support * **********************************************************************/ #if defined(MBEDTLS_FS_IO) /* * Load all data from a file into a given buffer. * * The file is expected to contain either PEM or DER encoded data. * A terminating null byte is always appended. It is included in the announced * length only if the data looks like it is PEM encoded. */ int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) { FILE *f; long size; if ((f = fopen(path, "rb")) == NULL) { return MBEDTLS_ERR_PK_FILE_IO_ERROR; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(f, NULL); fseek(f, 0, SEEK_END); if ((size = ftell(f)) == -1) { fclose(f); return MBEDTLS_ERR_PK_FILE_IO_ERROR; } fseek(f, 0, SEEK_SET); *n = (size_t) size; if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { fclose(f); return MBEDTLS_ERR_PK_ALLOC_FAILED; } if (fread(*buf, 1, *n, f) != *n) { fclose(f); mbedtls_zeroize_and_free(*buf, *n); return MBEDTLS_ERR_PK_FILE_IO_ERROR; } fclose(f); (*buf)[*n] = '\0'; if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { ++*n; } return 0; } /* * Load and parse a private key */ int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, const char *pwd, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } if (pwd == NULL) { ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); } else { ret = mbedtls_pk_parse_key(ctx, buf, n, (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); } mbedtls_zeroize_and_free(buf, n); return ret; } /* * Load and parse a public key */ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_pk_parse_public_key(ctx, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pkwrite.c000066400000000000000000000475041464416617300231770ustar00rootroot00000000000000/* * Public Key layer for writing key files and structures * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_WRITE_C) #include "mbedtls/pk.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "pk_internal.h" #include #if defined(MBEDTLS_ECP_C) #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "pk_internal.h" #endif #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS) #include "pkwrite.h" #endif #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_RSA_C) #include "rsa_internal.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #endif #include "mbedtls/platform.h" /* Helpers for properly sizing buffers aimed at holding public keys or * key-pairs based on build symbols. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH #elif defined(MBEDTLS_USE_PSA_CRYPTO) #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH #else #define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES #endif /****************************************************************************** * Internal functions for RSA keys. ******************************************************************************/ #if defined(MBEDTLS_RSA_C) static int pk_write_rsa_der(unsigned char **p, unsigned char *buf, const mbedtls_pk_context *pk) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; size_t len = 0, tmp_len = 0; if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } *p -= tmp_len; memcpy(*p, tmp, tmp_len); len += tmp_len; mbedtls_platform_zeroize(tmp, sizeof(tmp)); return (int) len; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p); } #endif /* MBEDTLS_RSA_C */ /****************************************************************************** * Internal functions for EC keys. ******************************************************************************/ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t len = 0; uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } } else { len = pk->pub_raw_len; memcpy(buf, pk->pub_raw, len); } if (*p < start || (size_t) (*p - start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *p -= len; memcpy(*p, buf, len); return (int) len; } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t len = 0; unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE]; mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } *p -= len; memcpy(*p, buf, len); return (int) len; } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &len, buf, sizeof(buf))) != 0) { return ret; } } if (*p < start || (size_t) (*p - start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *p -= len; memcpy(*p, buf, len); return (int) len; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ /* * privateKey OCTET STRING -- always of length ceil(log2(n)/8) */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) static int pk_write_ec_private(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t byte_length; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; psa_status_t status; if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); return ret; } } else { status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); goto exit; } } ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); exit: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ static int pk_write_ec_private(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t byte_length; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); if (status != PSA_SUCCESS) { ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); return ret; } } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ { mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); byte_length = (ec->grp.pbits + 7) / 8; ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp)); if (ret != 0) { goto exit; } } ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); exit: mbedtls_platform_zeroize(tmp, sizeof(tmp)); return ret; } #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ /* * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * } */ static int pk_write_ec_param(unsigned char **p, unsigned char *start, mbedtls_ecp_group_id grp_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; const char *oid; size_t oid_len; if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); return (int) len; } #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) /* * RFC8410 section 7 * * OneAsymmetricKey ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL, * ..., * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]], * ... * } * ... * CurvePrivateKey ::= OCTET STRING */ static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf, const mbedtls_pk_context *pk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; size_t oid_len = 0; const char *oid; mbedtls_ecp_group_id grp_id; /* privateKey */ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING)); grp_id = mbedtls_pk_get_ec_group_id(pk); /* privateKeyAlgorithm */ if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0)); /* version */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ /* * RFC 5915, or SEC1 Appendix C.4 * * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), * privateKey OCTET STRING, * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, * publicKey [1] BIT STRING OPTIONAL * } */ static int pk_write_ec_der(unsigned char **p, unsigned char *buf, const mbedtls_pk_context *pk) { size_t len = 0; int ret; size_t pub_len = 0, par_len = 0; mbedtls_ecp_group_id grp_id; /* publicKey */ MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk)); if (*p - buf < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } (*p)--; **p = 0; pub_len += 1; MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)); len += pub_len; /* parameters */ grp_id = mbedtls_pk_get_ec_group_id(pk); MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id)); MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len)); MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)); len += par_len; /* privateKey */ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); /* version */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /****************************************************************************** * Internal functions for Opaque keys. ******************************************************************************/ #if defined(MBEDTLS_USE_PSA_CRYPTO) static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *pk) { size_t buffer_size; size_t len = 0; if (*p < start) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } buffer_size = (size_t) (*p - start); if (psa_export_public_key(pk->priv_id, start, buffer_size, &len) != PSA_SUCCESS) { return MBEDTLS_ERR_PK_BAD_INPUT_DATA; } *p -= len; memmove(*p, start, len); return (int) len; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /****************************************************************************** * Generic helpers ******************************************************************************/ /* Extend the public mbedtls_pk_get_type() by getting key type also in case of * opaque keys. */ static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk) { mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk); #if defined(MBEDTLS_USE_PSA_CRYPTO) if (pk_type == MBEDTLS_PK_OPAQUE) { psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t opaque_key_type; if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { return MBEDTLS_PK_NONE; } opaque_key_type = psa_get_key_type(&opaque_attrs); psa_reset_key_attributes(&opaque_attrs); if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) { return MBEDTLS_PK_ECKEY; } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) { return MBEDTLS_PK_RSA; } else { return MBEDTLS_PK_NONE; } } else #endif return pk_type; } /****************************************************************************** * Public functions for writing private/public DER keys. ******************************************************************************/ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, const mbedtls_pk_context *key) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; #if defined(MBEDTLS_RSA_C) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p)); } else #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key)); } else #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key)); } else #endif /* MBEDTLS_USE_PSA_CRYPTO */ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; return (int) len; } int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *c; int has_par = 1; size_t len = 0, par_len = 0, oid_len = 0; mbedtls_pk_type_t pk_type; const char *oid = NULL; if (size == 0) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } c = buf + size; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); if (c - buf < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ *--c = 0; len += 1; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); pk_type = pk_get_type_ext(key); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key); if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len); if (ret != 0) { return ret; } has_par = 0; } else { MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id)); } } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* At this point oid_len is not null only for EC Montgomery keys. */ if (oid_len == 0) { ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len); if (ret != 0) { return ret; } } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len, par_len, has_par)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { unsigned char *c; if (size == 0) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } c = buf + size; #if defined(MBEDTLS_RSA_C) if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { return pk_write_rsa_der(&c, buf, key); } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) if (mbedtls_pk_is_rfc8410(key)) { return pk_write_ec_rfc8410_der(&c, buf, key); } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ return pk_write_ec_der(&c, buf, key); } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; } /****************************************************************************** * Public functions for wrinting private/public PEM keys. ******************************************************************************/ #if defined(MBEDTLS_PEM_WRITE_C) #define PUB_DER_MAX_BYTES \ (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) #define PRV_DER_MAX_BYTES \ (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *output_buf = NULL; output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES); if (output_buf == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } size_t olen = 0; if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, PUB_DER_MAX_BYTES)) < 0) { goto cleanup; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n", output_buf + PUB_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { goto cleanup; } ret = 0; cleanup: mbedtls_free(output_buf); return ret; } int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *output_buf = NULL; output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES); if (output_buf == NULL) { return MBEDTLS_ERR_PK_ALLOC_FAILED; } const char *begin, *end; size_t olen = 0; if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) { goto cleanup; } #if defined(MBEDTLS_RSA_C) if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) { begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n"; end = PEM_END_PRIVATE_KEY_RSA "\n"; } else #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) { if (mbedtls_pk_is_rfc8410(key)) { begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n"; end = PEM_END_PRIVATE_KEY_PKCS8 "\n"; } else { begin = PEM_BEGIN_PRIVATE_KEY_EC "\n"; end = PEM_END_PRIVATE_KEY_EC "\n"; } } else #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ { ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; goto cleanup; } if ((ret = mbedtls_pem_write_buffer(begin, end, output_buf + PRV_DER_MAX_BYTES - ret, ret, buf, size, &olen)) != 0) { goto cleanup; } ret = 0; cleanup: mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES); return ret; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/pkwrite.h000066400000000000000000000110641464416617300231740ustar00rootroot00000000000000/** * \file pkwrite.h * * \brief Internal defines shared by the PK write module */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PK_WRITE_H #define MBEDTLS_PK_WRITE_H #include "mbedtls/build_info.h" #include "mbedtls/pk.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Max sizes of key per types. Shown as tag + len (+ content). */ #if defined(MBEDTLS_RSA_C) /* * RSA public keys: * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 * algorithm AlgorithmIdentifier, 1 + 1 (sequence) * + 1 + 1 + 9 (rsa oid) * + 1 + 1 (params null) * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) * RSAPublicKey ::= SEQUENCE { 1 + 3 * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 * } */ #define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) /* * RSA private keys: * RSAPrivateKey ::= SEQUENCE { 1 + 3 * version Version, 1 + 1 + 1 * modulus INTEGER, 1 + 3 + MPI_MAX + 1 * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) * } */ #define MBEDTLS_MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \ MBEDTLS_MPI_MAX_SIZE % 2) #define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + 5 * MBEDTLS_MPI_MAX_SIZE_2) #else /* MBEDTLS_RSA_C */ #define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES 0 #define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES 0 #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Find the maximum number of bytes necessary to store an EC point. When USE_PSA * is defined this means looking for the maximum between PSA and built-in * supported curves. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #define MBEDTLS_PK_MAX_ECC_BYTES (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \ MBEDTLS_ECP_MAX_BYTES ? \ PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \ MBEDTLS_ECP_MAX_BYTES) #else /* MBEDTLS_USE_PSA_CRYPTO */ #define MBEDTLS_PK_MAX_ECC_BYTES MBEDTLS_ECP_MAX_BYTES #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * EC public keys: * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 * algorithm AlgorithmIdentifier, 1 + 1 (sequence) * + 1 + 1 + 7 (ec oid) * + 1 + 1 + 9 (namedCurve oid) * subjectPublicKey BIT STRING 1 + 2 + 1 [1] * + 1 (point format) [1] * + 2 * ECP_MAX (coords) [1] * } */ #define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_PK_MAX_ECC_BYTES) /* * EC private keys: * ECPrivateKey ::= SEQUENCE { 1 + 2 * version INTEGER , 1 + 1 + 1 * privateKey OCTET STRING, 1 + 1 + ECP_MAX * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above * } */ #define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_PK_MAX_ECC_BYTES) #else /* MBEDTLS_PK_HAVE_ECC_KEYS */ #define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES 0 #define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES 0 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Define the maximum available public key DER length based on the supported * key types (EC and/or RSA). */ #if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) #define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES #else #define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES #endif #endif /* MBEDTLS_PK_WRITE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/platform.c000066400000000000000000000252531464416617300233330ustar00rootroot00000000000000/* * Platform abstraction layer * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" /* The compile time configuration of memory allocation via the macros * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime * configuration via mbedtls_platform_set_calloc_free(). So, omit everything * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ #if defined(MBEDTLS_PLATFORM_MEMORY) && \ !(defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ defined(MBEDTLS_PLATFORM_FREE_MACRO)) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) static void *platform_calloc_uninit(size_t n, size_t size) { ((void) n); ((void) size); return NULL; } #define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit #endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ #if !defined(MBEDTLS_PLATFORM_STD_FREE) static void platform_free_uninit(void *ptr) { ((void) ptr); } #define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit #endif /* !MBEDTLS_PLATFORM_STD_FREE */ static void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC; static void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE; void *mbedtls_calloc(size_t nmemb, size_t size) { return (*mbedtls_calloc_func)(nmemb, size); } void mbedtls_free(void *ptr) { (*mbedtls_free_func)(ptr); } int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), void (*free_func)(void *)) { mbedtls_calloc_func = calloc_func; mbedtls_free_func = free_func; return 0; } #endif /* MBEDTLS_PLATFORM_MEMORY && !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) #include int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; va_list argp; va_start(argp, fmt); ret = mbedtls_vsnprintf(s, n, fmt, argp); va_end(argp); return ret; } #endif #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_snprintf_uninit(char *s, size_t n, const char *format, ...) { ((void) s); ((void) n); ((void) format); return 0; } #define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit #endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...) = MBEDTLS_PLATFORM_STD_SNPRINTF; int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, const char *format, ...)) { mbedtls_snprintf = snprintf_func; return 0; } #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) #include int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Avoid calling the invalid parameter handler by checking ourselves */ if (s == NULL || n == 0 || fmt == NULL) { return -1; } #if defined(_TRUNCATE) ret = vsnprintf_s(s, n, _TRUNCATE, fmt, arg); #else ret = vsnprintf(s, n, fmt, arg); if (ret < 0 || (size_t) ret == n) { s[n-1] = '\0'; ret = -1; } #endif return ret; } #endif #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_vsnprintf_uninit(char *s, size_t n, const char *format, va_list arg) { ((void) s); ((void) n); ((void) format); ((void) arg); return -1; } #define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit #endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF; int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, const char *format, va_list arg)) { mbedtls_vsnprintf = vsnprintf_func; return 0; } #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_PRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_printf_uninit(const char *format, ...) { ((void) format); return 0; } #define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit #endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ int (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF; int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)) { mbedtls_printf = printf_func; return 0; } #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_fprintf_uninit(FILE *stream, const char *format, ...) { ((void) stream); ((void) format); return 0; } #define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit #endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ int (*mbedtls_fprintf)(FILE *, const char *, ...) = MBEDTLS_PLATFORM_STD_FPRINTF; int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...)) { mbedtls_fprintf = fprintf_func; return 0; } #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) #if !defined(MBEDTLS_PLATFORM_STD_SETBUF) /* * Make dummy function to prevent NULL pointer dereferences */ static void platform_setbuf_uninit(FILE *stream, char *buf) { ((void) stream); ((void) buf); } #define MBEDTLS_PLATFORM_STD_SETBUF platform_setbuf_uninit #endif /* !MBEDTLS_PLATFORM_STD_SETBUF */ void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF; int mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf)) { mbedtls_setbuf = setbuf_func; return 0; } #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) #if !defined(MBEDTLS_PLATFORM_STD_EXIT) /* * Make dummy function to prevent NULL pointer dereferences */ static void platform_exit_uninit(int status) { ((void) status); } #define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit #endif /* !MBEDTLS_PLATFORM_STD_EXIT */ void (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT; int mbedtls_platform_set_exit(void (*exit_func)(int status)) { mbedtls_exit = exit_func; return 0; } #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ #if defined(MBEDTLS_HAVE_TIME) #if defined(MBEDTLS_PLATFORM_TIME_ALT) #if !defined(MBEDTLS_PLATFORM_STD_TIME) /* * Make dummy function to prevent NULL pointer dereferences */ static mbedtls_time_t platform_time_uninit(mbedtls_time_t *timer) { ((void) timer); return 0; } #define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit #endif /* !MBEDTLS_PLATFORM_STD_TIME */ mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME; int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *timer)) { mbedtls_time = time_func; return 0; } #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_ENTROPY_NV_SEED) #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) /* Default implementations for the platform independent seed functions use * standard libc file functions to read from and write to a pre-defined filename */ int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len) { FILE *file; size_t n; if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb")) == NULL) { return -1; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(file, NULL); if ((n = fread(buf, 1, buf_len, file)) != buf_len) { fclose(file); mbedtls_platform_zeroize(buf, buf_len); return -1; } fclose(file); return (int) n; } int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len) { FILE *file; size_t n; if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w")) == NULL) { return -1; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(file, NULL); if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) { fclose(file); return -1; } fclose(file); return (int) n; } #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_nv_seed_read_uninit(unsigned char *buf, size_t buf_len) { ((void) buf); ((void) buf_len); return -1; } #define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) /* * Make dummy function to prevent NULL pointer dereferences */ static int platform_nv_seed_write_uninit(unsigned char *buf, size_t buf_len) { ((void) buf); ((void) buf_len); return -1; } #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) = MBEDTLS_PLATFORM_STD_NV_SEED_READ; int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) = MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; int mbedtls_platform_set_nv_seed( int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len), int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len)) { mbedtls_nv_seed_read = nv_seed_read_func; mbedtls_nv_seed_write = nv_seed_write_func; return 0; } #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) /* * Placeholder platform setup that does nothing by default */ int mbedtls_platform_setup(mbedtls_platform_context *ctx) { (void) ctx; return 0; } /* * Placeholder platform teardown that does nothing by default */ void mbedtls_platform_teardown(mbedtls_platform_context *ctx) { (void) ctx; } #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ #endif /* MBEDTLS_PLATFORM_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/platform_util.c000066400000000000000000000211511464416617300243610ustar00rootroot00000000000000/* * Common and shared functions used by multiple modules in the Mbed TLS * library. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Ensure gmtime_r is available even with -std=c99; must be defined before * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms * except OpenBSD, where it stops us accessing explicit_bzero. */ #if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__) #define _POSIX_C_SOURCE 200112L #endif #if !defined(_GNU_SOURCE) /* Clang requires this to get support for explicit_bzero */ #define _GNU_SOURCE #endif #include "common.h" #include "mbedtls/platform_util.h" #include "mbedtls/platform.h" #include "mbedtls/threading.h" #include #ifndef __STDC_WANT_LIB_EXT1__ #define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */ #endif #include #if defined(_WIN32) #include #endif // Detect platforms known to support explicit_bzero() #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25) #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 #elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__) #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1 #endif #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) #undef HAVE_MEMORY_SANITIZER #if defined(__has_feature) #if __has_feature(memory_sanitizer) #include #define HAVE_MEMORY_SANITIZER #endif #endif /* * Where possible, we try to detect the presence of a platform-provided * secure memset, such as explicit_bzero(), that is safe against being optimized * out, and use that. * * For other platforms, we provide an implementation that aims not to be * optimized out by the compiler. * * This implementation for mbedtls_platform_zeroize() was inspired from Colin * Percival's blog article at: * * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html * * It uses a volatile function pointer to the standard memset(). Because the * pointer is volatile the compiler expects it to change at * any time and will not optimize out the call that could potentially perform * other operations on the input buffer instead of just setting it to 0. * Nevertheless, as pointed out by davidtgoldblatt on Hacker News * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for * details), optimizations of the following form are still possible: * * if (memset_func != memset) * memset_func(buf, 0, len); * * Note that it is extremely difficult to guarantee that * the memset() call will not be optimized out by aggressive compilers * in a portable way. For this reason, Mbed TLS also provides the configuration * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure * mbedtls_platform_zeroize() to use a suitable implementation for their * platform and needs. */ #if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \ !defined(__IAR_SYSTEMS_ICC__)) \ && !defined(_WIN32) static void *(*const volatile memset_func)(void *, int, size_t) = memset; #endif void mbedtls_platform_zeroize(void *buf, size_t len) { if (len > 0) { #if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) explicit_bzero(buf, len); #if defined(HAVE_MEMORY_SANITIZER) /* You'd think that Msan would recognize explicit_bzero() as * equivalent to bzero(), but it actually doesn't on several * platforms, including Linux (Ubuntu 20.04). * https://github.com/google/sanitizers/issues/1507 * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa */ __msan_unpoison(buf, len); #endif #elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__) memset_s(buf, len, 0, len); #elif defined(_WIN32) SecureZeroMemory(buf, len); #else memset_func(buf, 0, len); #endif #if defined(__GNUC__) /* For clang and recent gcc, pretend that we have some assembly that reads the * zero'd memory as an additional protection against being optimised away. */ #if defined(__clang__) || (__GNUC__ >= 10) #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wvla" #elif defined(MBEDTLS_COMPILER_IS_GCC) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvla" #endif asm volatile ("" : : "m" (*(char (*)[len]) buf) :); #if defined(__clang__) #pragma clang diagnostic pop #elif defined(MBEDTLS_COMPILER_IS_GCC) #pragma GCC diagnostic pop #endif #endif #endif } } #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ void mbedtls_zeroize_and_free(void *buf, size_t len) { if (buf != NULL) { mbedtls_platform_zeroize(buf, len); } mbedtls_free(buf); } #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) #include #if !defined(_WIN32) && (defined(unix) || \ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ defined(__MACH__)) || defined__midipix__) #include #endif /* !_WIN32 && (unix || __unix || __unix__ || * (__APPLE__ && __MACH__) || __midipix__) */ #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L)) /* * This is a convenience shorthand macro to avoid checking the long * preprocessor conditions above. Ideally, we could expose this macro in * platform_util.h and simply use it in platform_util.c, threading.c and * threading.h. However, this macro is not part of the Mbed TLS public API, so * we keep it private by only defining it in this file */ #if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \ (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) #define PLATFORM_UTIL_USE_GMTIME #endif #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, struct tm *tm_buf) { #if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME) #if defined(__STDC_LIB_EXT1__) return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf; #else /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */ return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL; #endif #elif !defined(PLATFORM_UTIL_USE_GMTIME) return gmtime_r(tt, tm_buf); #else struct tm *lt; #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) { return NULL; } #endif /* MBEDTLS_THREADING_C */ lt = gmtime(tt); if (lt != NULL) { memcpy(tm_buf, lt, sizeof(struct tm)); } #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) { return NULL; } #endif /* MBEDTLS_THREADING_C */ return (lt == NULL) ? NULL : tm_buf; #endif /* _WIN32 && !EFIX64 && !EFI32 */ } #endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_TEST_HOOKS) void (*mbedtls_test_hook_test_fail)(const char *, int, const char *); #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT) #include #if !defined(_WIN32) && \ (defined(unix) || defined(__unix) || defined(__unix__) || \ (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__)) #include #endif \ /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */ #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__) mbedtls_ms_time_t mbedtls_ms_time(void) { int ret; struct timespec tv; mbedtls_ms_time_t current_ms; #if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__) ret = clock_gettime(CLOCK_BOOTTIME, &tv); #else ret = clock_gettime(CLOCK_MONOTONIC, &tv); #endif if (ret) { return time(NULL) * 1000; } current_ms = tv.tv_sec; return current_ms*1000 + tv.tv_nsec / 1000000; } #elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \ defined(__MINGW32__) || defined(_WIN64) #include mbedtls_ms_time_t mbedtls_ms_time(void) { FILETIME ct; mbedtls_ms_time_t current_ms; GetSystemTimeAsFileTime(&ct); current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime + ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000; return current_ms; } #else #error "No mbedtls_ms_time available" #endif #endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/poly1305.c000066400000000000000000000341611464416617300230010ustar00rootroot00000000000000/** * \file poly1305.c * * \brief Poly1305 authentication algorithm. * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_POLY1305_C) #include "mbedtls/poly1305.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_POLY1305_ALT) #define POLY1305_BLOCK_SIZE_BYTES (16U) /* * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. * However we provided an alternative for platforms without such a multiplier. */ #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) static uint64_t mul64(uint32_t a, uint32_t b) { /* a = al + 2**16 ah, b = bl + 2**16 bh */ const uint16_t al = (uint16_t) a; const uint16_t bl = (uint16_t) b; const uint16_t ah = a >> 16; const uint16_t bh = b >> 16; /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ const uint32_t lo = (uint32_t) al * bl; const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh; const uint32_t hi = (uint32_t) ah * bh; return lo + (me << 16) + ((uint64_t) hi << 32); } #else static inline uint64_t mul64(uint32_t a, uint32_t b) { return (uint64_t) a * b; } #endif /** * \brief Process blocks with Poly1305. * * \param ctx The Poly1305 context. * \param nblocks Number of blocks to process. Note that this * function only processes full blocks. * \param input Buffer containing the input block(s). * \param needs_padding Set to 0 if the padding bit has already been * applied to the input data before calling this * function. Otherwise, set this parameter to 1. */ static void poly1305_process(mbedtls_poly1305_context *ctx, size_t nblocks, const unsigned char *input, uint32_t needs_padding) { uint64_t d0, d1, d2, d3; uint32_t acc0, acc1, acc2, acc3, acc4; uint32_t r0, r1, r2, r3; uint32_t rs1, rs2, rs3; size_t offset = 0U; size_t i; r0 = ctx->r[0]; r1 = ctx->r[1]; r2 = ctx->r[2]; r3 = ctx->r[3]; rs1 = r1 + (r1 >> 2U); rs2 = r2 + (r2 >> 2U); rs3 = r3 + (r3 >> 2U); acc0 = ctx->acc[0]; acc1 = ctx->acc[1]; acc2 = ctx->acc[2]; acc3 = ctx->acc[3]; acc4 = ctx->acc[4]; /* Process full blocks */ for (i = 0U; i < nblocks; i++) { /* The input block is treated as a 128-bit little-endian integer */ d0 = MBEDTLS_GET_UINT32_LE(input, offset + 0); d1 = MBEDTLS_GET_UINT32_LE(input, offset + 4); d2 = MBEDTLS_GET_UINT32_LE(input, offset + 8); d3 = MBEDTLS_GET_UINT32_LE(input, offset + 12); /* Compute: acc += (padded) block as a 130-bit integer */ d0 += (uint64_t) acc0; d1 += (uint64_t) acc1 + (d0 >> 32U); d2 += (uint64_t) acc2 + (d1 >> 32U); d3 += (uint64_t) acc3 + (d2 >> 32U); acc0 = (uint32_t) d0; acc1 = (uint32_t) d1; acc2 = (uint32_t) d2; acc3 = (uint32_t) d3; acc4 += (uint32_t) (d3 >> 32U) + needs_padding; /* Compute: acc *= r */ d0 = mul64(acc0, r0) + mul64(acc1, rs3) + mul64(acc2, rs2) + mul64(acc3, rs1); d1 = mul64(acc0, r1) + mul64(acc1, r0) + mul64(acc2, rs3) + mul64(acc3, rs2) + mul64(acc4, rs1); d2 = mul64(acc0, r2) + mul64(acc1, r1) + mul64(acc2, r0) + mul64(acc3, rs3) + mul64(acc4, rs2); d3 = mul64(acc0, r3) + mul64(acc1, r2) + mul64(acc2, r1) + mul64(acc3, r0) + mul64(acc4, rs3); acc4 *= r0; /* Compute: acc %= (2^130 - 5) (partial remainder) */ d1 += (d0 >> 32); d2 += (d1 >> 32); d3 += (d2 >> 32); acc0 = (uint32_t) d0; acc1 = (uint32_t) d1; acc2 = (uint32_t) d2; acc3 = (uint32_t) d3; acc4 = (uint32_t) (d3 >> 32) + acc4; d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU); acc4 &= 3U; acc0 = (uint32_t) d0; d0 = (uint64_t) acc1 + (d0 >> 32U); acc1 = (uint32_t) d0; d0 = (uint64_t) acc2 + (d0 >> 32U); acc2 = (uint32_t) d0; d0 = (uint64_t) acc3 + (d0 >> 32U); acc3 = (uint32_t) d0; d0 = (uint64_t) acc4 + (d0 >> 32U); acc4 = (uint32_t) d0; offset += POLY1305_BLOCK_SIZE_BYTES; } ctx->acc[0] = acc0; ctx->acc[1] = acc1; ctx->acc[2] = acc2; ctx->acc[3] = acc3; ctx->acc[4] = acc4; } /** * \brief Compute the Poly1305 MAC * * \param ctx The Poly1305 context. * \param mac The buffer to where the MAC is written. Must be * big enough to contain the 16-byte MAC. */ static void poly1305_compute_mac(const mbedtls_poly1305_context *ctx, unsigned char mac[16]) { uint64_t d; uint32_t g0, g1, g2, g3, g4; uint32_t acc0, acc1, acc2, acc3, acc4; uint32_t mask; uint32_t mask_inv; acc0 = ctx->acc[0]; acc1 = ctx->acc[1]; acc2 = ctx->acc[2]; acc3 = ctx->acc[3]; acc4 = ctx->acc[4]; /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. * We do this by calculating acc - (2^130 - 5), then checking if * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) */ /* Calculate acc + -(2^130 - 5) */ d = ((uint64_t) acc0 + 5U); g0 = (uint32_t) d; d = ((uint64_t) acc1 + (d >> 32)); g1 = (uint32_t) d; d = ((uint64_t) acc2 + (d >> 32)); g2 = (uint32_t) d; d = ((uint64_t) acc3 + (d >> 32)); g3 = (uint32_t) d; g4 = acc4 + (uint32_t) (d >> 32U); /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ mask = (uint32_t) 0U - (g4 >> 2U); mask_inv = ~mask; /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ acc0 = (acc0 & mask_inv) | (g0 & mask); acc1 = (acc1 & mask_inv) | (g1 & mask); acc2 = (acc2 & mask_inv) | (g2 & mask); acc3 = (acc3 & mask_inv) | (g3 & mask); /* Add 's' */ d = (uint64_t) acc0 + ctx->s[0]; acc0 = (uint32_t) d; d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U); acc1 = (uint32_t) d; d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U); acc2 = (uint32_t) d; acc3 += ctx->s[3] + (uint32_t) (d >> 32U); /* Compute MAC (128 least significant bits of the accumulator) */ MBEDTLS_PUT_UINT32_LE(acc0, mac, 0); MBEDTLS_PUT_UINT32_LE(acc1, mac, 4); MBEDTLS_PUT_UINT32_LE(acc2, mac, 8); MBEDTLS_PUT_UINT32_LE(acc3, mac, 12); } void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx) { mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); } void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context)); } int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx, const unsigned char key[32]) { /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0) & 0x0FFFFFFFU; ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4) & 0x0FFFFFFCU; ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8) & 0x0FFFFFFCU; ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU; ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16); ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20); ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24); ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28); /* Initial accumulator state */ ctx->acc[0] = 0U; ctx->acc[1] = 0U; ctx->acc[2] = 0U; ctx->acc[3] = 0U; ctx->acc[4] = 0U; /* Queue initially empty */ mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue)); ctx->queue_len = 0U; return 0; } int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx, const unsigned char *input, size_t ilen) { size_t offset = 0U; size_t remaining = ilen; size_t queue_free_len; size_t nblocks; if ((remaining > 0U) && (ctx->queue_len > 0U)) { queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); if (ilen < queue_free_len) { /* Not enough data to complete the block. * Store this data with the other leftovers. */ memcpy(&ctx->queue[ctx->queue_len], input, ilen); ctx->queue_len += ilen; remaining = 0U; } else { /* Enough data to produce a complete block */ memcpy(&ctx->queue[ctx->queue_len], input, queue_free_len); ctx->queue_len = 0U; poly1305_process(ctx, 1U, ctx->queue, 1U); /* add padding bit */ offset += queue_free_len; remaining -= queue_free_len; } } if (remaining >= POLY1305_BLOCK_SIZE_BYTES) { nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; poly1305_process(ctx, nblocks, &input[offset], 1U); offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; remaining %= POLY1305_BLOCK_SIZE_BYTES; } if (remaining > 0U) { /* Store partial block */ ctx->queue_len = remaining; memcpy(ctx->queue, &input[offset], remaining); } return 0; } int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx, unsigned char mac[16]) { /* Process any leftover data */ if (ctx->queue_len > 0U) { /* Add padding bit */ ctx->queue[ctx->queue_len] = 1U; ctx->queue_len++; /* Pad with zeroes */ memset(&ctx->queue[ctx->queue_len], 0, POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len); poly1305_process(ctx, 1U, /* Process 1 block */ ctx->queue, 0U); /* Already padded above */ } poly1305_compute_mac(ctx, mac); return 0; } int mbedtls_poly1305_mac(const unsigned char key[32], const unsigned char *input, size_t ilen, unsigned char mac[16]) { mbedtls_poly1305_context ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_poly1305_init(&ctx); ret = mbedtls_poly1305_starts(&ctx, key); if (ret != 0) { goto cleanup; } ret = mbedtls_poly1305_update(&ctx, input, ilen); if (ret != 0) { goto cleanup; } ret = mbedtls_poly1305_finish(&ctx, mac); cleanup: mbedtls_poly1305_free(&ctx); return ret; } #endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_keys[2][32] = { { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b }, { 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 } }; static const unsigned char test_data[2][127] = { { 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70 }, { 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e } }; static const size_t test_data_len[2] = { 34U, 127U }; static const unsigned char test_mac[2][16] = { { 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 }, { 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 } }; /* Make sure no other definition is already present. */ #undef ASSERT #define ASSERT(cond, args) \ do \ { \ if (!(cond)) \ { \ if (verbose != 0) \ mbedtls_printf args; \ \ return -1; \ } \ } \ while (0) int mbedtls_poly1305_self_test(int verbose) { unsigned char mac[16]; unsigned i; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; for (i = 0U; i < 2U; i++) { if (verbose != 0) { mbedtls_printf(" Poly1305 test %u ", i); } ret = mbedtls_poly1305_mac(test_keys[i], test_data[i], test_data_len[i], mac); ASSERT(0 == ret, ("error code: %i\n", ret)); ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failed (mac)\n")); if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_POLY1305_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto.c000066400000000000000000011512351464416617300236730ustar00rootroot00000000000000/* * PSA crypto layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "psa_crypto_core_common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) #include "check_crypto_config.h" #endif #include "psa/crypto.h" #include "psa/crypto_values.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_invasive.h" #include "psa_crypto_driver_wrappers.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_ecp.h" #include "psa_crypto_ffdh.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_rsa.h" #include "psa_crypto_ecp.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif #include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently * stored keys. */ #include "psa_crypto_storage.h" #include "psa_crypto_random_impl.h" #include #include #include "mbedtls/platform.h" #include "mbedtls/aes.h" #include "mbedtls/asn1.h" #include "mbedtls/asn1write.h" #include "mbedtls/bignum.h" #include "mbedtls/camellia.h" #include "mbedtls/chacha20.h" #include "mbedtls/chachapoly.h" #include "mbedtls/cipher.h" #include "mbedtls/ccm.h" #include "mbedtls/cmac.h" #include "mbedtls/constant_time.h" #include "mbedtls/des.h" #include "mbedtls/ecdh.h" #include "mbedtls/ecp.h" #include "mbedtls/entropy.h" #include "mbedtls/error.h" #include "mbedtls/gcm.h" #include "mbedtls/md5.h" #include "mbedtls/pk.h" #include "pk_wrap.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "mbedtls/ripemd160.h" #include "mbedtls/rsa.h" #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" #include "mbedtls/sha512.h" #include "mbedtls/psa_util.h" #include "mbedtls/threading.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) #define BUILTIN_ALG_ANY_HKDF 1 #endif /****************************************************************/ /* Global data, support functions and library management */ /****************************************************************/ static int key_type_is_raw_bytes(psa_key_type_t type) { return PSA_KEY_TYPE_IS_UNSTRUCTURED(type); } /* Values for psa_global_data_t::rng_state */ #define RNG_NOT_INITIALIZED 0 #define RNG_INITIALIZED 1 #define RNG_SEEDED 2 /* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized * variables as arguments. */ typedef enum { PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1, PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS, PSA_CRYPTO_SUBSYSTEM_RNG, PSA_CRYPTO_SUBSYSTEM_TRANSACTION, } mbedtls_psa_crypto_subsystem; /* Initialization flags for global_data::initialized */ #define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED 0x01 #define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED 0x02 #define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED 0x04 #define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED ( \ PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \ PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \ PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) typedef struct { uint8_t initialized; uint8_t rng_state; mbedtls_psa_random_context_t rng; } psa_global_data_t; static psa_global_data_t global_data; static uint8_t psa_get_initialized(void) { uint8_t initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = global_data.rng_state == RNG_SEEDED; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return initialized; } static uint8_t psa_get_drivers_initialized(void) { uint8_t initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return initialized; } #define GUARD_MODULE_INITIALIZED \ if (psa_get_initialized() == 0) \ return PSA_ERROR_BAD_STATE; #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) /* Declare a local copy of an input buffer and a variable that will be used * to store a pointer to the start of the buffer. * * Note: This macro must be called before any operations which may jump to * the exit label, so that the local input copy object is safe to be freed. * * Assumptions: * - input is the name of a pointer to the buffer to be copied * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope * - input_copy_name is a name that is unused in the current scope */ #define LOCAL_INPUT_DECLARE(input, input_copy_name) \ psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \ const uint8_t *input_copy_name = NULL; /* Allocate a copy of the buffer input and set the pointer input_copy to * point to the start of the copy. * * Assumptions: * - psa_status_t status exists * - An exit label is declared * - input is the name of a pointer to the buffer to be copied * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called */ #define LOCAL_INPUT_ALLOC(input, length, input_copy) \ status = psa_crypto_local_input_alloc(input, length, \ &LOCAL_INPUT_COPY_OF_##input); \ if (status != PSA_SUCCESS) { \ goto exit; \ } \ input_copy = LOCAL_INPUT_COPY_OF_##input.buffer; /* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC() * * Assumptions: * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC() * - input is the name of the original buffer that was copied */ #define LOCAL_INPUT_FREE(input, input_copy) \ input_copy = NULL; \ psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input); /* Declare a local copy of an output buffer and a variable that will be used * to store a pointer to the start of the buffer. * * Note: This macro must be called before any operations which may jump to * the exit label, so that the local output copy object is safe to be freed. * * Assumptions: * - output is the name of a pointer to the buffer to be copied * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope * - output_copy_name is a name that is unused in the current scope */ #define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \ uint8_t *output_copy_name = NULL; /* Allocate a copy of the buffer output and set the pointer output_copy to * point to the start of the copy. * * Assumptions: * - psa_status_t status exists * - An exit label is declared * - output is the name of a pointer to the buffer to be copied * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called */ #define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ status = psa_crypto_local_output_alloc(output, length, \ &LOCAL_OUTPUT_COPY_OF_##output); \ if (status != PSA_SUCCESS) { \ goto exit; \ } \ output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer; /* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC() * after first copying back its contents to the original buffer. * * Assumptions: * - psa_status_t status exists * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC() * - output is the name of the original buffer that was copied */ #define LOCAL_OUTPUT_FREE(output, output_copy) \ output_copy = NULL; \ do { \ psa_status_t local_output_status; \ local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \ if (local_output_status != PSA_SUCCESS) { \ /* Since this error case is an internal error, it's more serious than \ * any existing error code and so it's fine to overwrite the existing \ * status. */ \ status = local_output_status; \ } \ } while (0) #else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #define LOCAL_INPUT_DECLARE(input, input_copy_name) \ const uint8_t *input_copy_name = NULL; #define LOCAL_INPUT_ALLOC(input, length, input_copy) \ input_copy = input; #define LOCAL_INPUT_FREE(input, input_copy) \ input_copy = NULL; #define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \ uint8_t *output_copy_name = NULL; #define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \ output_copy = output; #define LOCAL_OUTPUT_FREE(output, output_copy) \ output_copy = NULL; #endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ int psa_can_do_hash(psa_algorithm_t hash_alg) { (void) hash_alg; return psa_get_drivers_initialized(); } int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg) { (void) key_type; (void) cipher_alg; return psa_get_drivers_initialized(); } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) static int psa_is_dh_key_size_valid(size_t bits) { switch (bits) { #if defined(PSA_WANT_DH_RFC7919_2048) case 2048: return 1; #endif /* PSA_WANT_DH_RFC7919_2048 */ #if defined(PSA_WANT_DH_RFC7919_3072) case 3072: return 1; #endif /* PSA_WANT_DH_RFC7919_3072 */ #if defined(PSA_WANT_DH_RFC7919_4096) case 4096: return 1; #endif /* PSA_WANT_DH_RFC7919_4096 */ #if defined(PSA_WANT_DH_RFC7919_6144) case 6144: return 1; #endif /* PSA_WANT_DH_RFC7919_6144 */ #if defined(PSA_WANT_DH_RFC7919_8192) case 8192: return 1; #endif /* PSA_WANT_DH_RFC7919_8192 */ default: return 0; } } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */ psa_status_t mbedtls_to_psa_error(int ret) { /* Mbed TLS error codes can combine a high-level error code and a * low-level error code. The low-level error usually reflects the * root cause better, so dispatch on that preferably. */ int low_level_ret = -(-ret & 0x007f); switch (low_level_ret != 0 ? low_level_ret : ret) { case 0: return PSA_SUCCESS; #if defined(MBEDTLS_AES_C) case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_AES_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; #endif #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C) case MBEDTLS_ERR_ASN1_OUT_OF_DATA: case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: case MBEDTLS_ERR_ASN1_INVALID_LENGTH: case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: case MBEDTLS_ERR_ASN1_INVALID_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_ASN1_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; #endif #if defined(MBEDTLS_CAMELLIA_C) case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; #endif #if defined(MBEDTLS_CCM_C) case MBEDTLS_ERR_CCM_BAD_INPUT: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CCM_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; #endif #if defined(MBEDTLS_CHACHA20_C) case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; #endif #if defined(MBEDTLS_CHACHAPOLY_C) case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: return PSA_ERROR_BAD_STATE; case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; #endif #if defined(MBEDTLS_CIPHER_C) case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_CIPHER_INVALID_PADDING: return PSA_ERROR_INVALID_PADDING; case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_CIPHER_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: return PSA_ERROR_CORRUPTION_DETECTED; #endif #if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) || \ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)) /* Only check CTR_DRBG error codes if underlying mbedtls_xxx * functions are passed a CTR_DRBG instance. */ case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif #if defined(MBEDTLS_DES_C) case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: return PSA_ERROR_NOT_SUPPORTED; #endif case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; #if defined(MBEDTLS_GCM_C) case MBEDTLS_ERR_GCM_AUTH_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_GCM_BAD_INPUT: return PSA_ERROR_INVALID_ARGUMENT; #endif #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \ defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx * functions are passed a HMAC_DRBG instance. */ case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG: case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR: return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif #if defined(MBEDTLS_MD_LIGHT) case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_MD_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MD_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; #if defined(MBEDTLS_FS_IO) case MBEDTLS_ERR_MD_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; #endif #endif #if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_FS_IO) case MBEDTLS_ERR_MPI_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; #endif case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_INVALID_CHARACTER: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_MPI_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; #endif #if defined(MBEDTLS_PK_C) case MBEDTLS_ERR_PK_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_PK_TYPE_MISMATCH: case MBEDTLS_ERR_PK_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \ defined(MBEDTLS_PSA_ITS_FILE_C) case MBEDTLS_ERR_PK_FILE_IO_ERROR: return PSA_ERROR_STORAGE_FAILURE; #endif case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: return PSA_ERROR_NOT_PERMITTED; case MBEDTLS_ERR_PK_INVALID_PUBKEY: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_PK_INVALID_ALG: case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; #endif case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: return PSA_ERROR_HARDWARE_FAILURE; case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: return PSA_ERROR_NOT_SUPPORTED; #if defined(MBEDTLS_RSA_C) case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_RSA_INVALID_PADDING: return PSA_ERROR_INVALID_PADDING; case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: return PSA_ERROR_HARDWARE_FAILURE; case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_RSA_PUBLIC_FAILED: case MBEDTLS_ERR_RSA_PRIVATE_FAILED: return PSA_ERROR_CORRUPTION_DETECTED; case MBEDTLS_ERR_RSA_VERIFY_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_RSA_RNG_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; #endif #if defined(MBEDTLS_ECP_LIGHT) case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_INVALID_KEY: return PSA_ERROR_INVALID_ARGUMENT; case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: case MBEDTLS_ERR_ECP_VERIFY_FAILED: return PSA_ERROR_INVALID_SIGNATURE; case MBEDTLS_ERR_ECP_ALLOC_FAILED: return PSA_ERROR_INSUFFICIENT_MEMORY; case MBEDTLS_ERR_ECP_RANDOM_FAILED: return PSA_ERROR_INSUFFICIENT_ENTROPY; #if defined(MBEDTLS_ECP_RESTARTABLE) case MBEDTLS_ERR_ECP_IN_PROGRESS: return PSA_OPERATION_INCOMPLETE; #endif #endif case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: return PSA_ERROR_CORRUPTION_DETECTED; default: return PSA_ERROR_GENERIC_ERROR; } } /** * \brief For output buffers which contain "tags" * (outputs that may be checked for validity like * hashes, MACs and signatures), fill the unused * part of the output buffer (the whole buffer on * error, the trailing part on success) with * something that isn't a valid tag (barring an * attack on the tag and deliberately-crafted * input), in case the caller doesn't check the * return status properly. * * \param output_buffer Pointer to buffer to wipe. May not be NULL * unless \p output_buffer_size is zero. * \param status Status of function called to generate * output_buffer originally * \param output_buffer_size Size of output buffer. If zero, \p output_buffer * could be NULL. * \param output_buffer_length Length of data written to output_buffer, must be * less than \p output_buffer_size */ static void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status, size_t output_buffer_size, size_t output_buffer_length) { size_t offset = 0; if (output_buffer_size == 0) { /* If output_buffer_size is 0 then we have nothing to do. We must not call memset because output_buffer may be NULL in this case */ return; } if (status == PSA_SUCCESS) { offset = output_buffer_length; } memset(output_buffer + offset, '!', output_buffer_size - offset); } psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, size_t bits) { /* Check that the bit size is acceptable for the key type */ switch (type) { case PSA_KEY_TYPE_RAW_DATA: case PSA_KEY_TYPE_HMAC: case PSA_KEY_TYPE_DERIVE: case PSA_KEY_TYPE_PASSWORD: case PSA_KEY_TYPE_PASSWORD_HASH: break; #if defined(PSA_WANT_KEY_TYPE_AES) case PSA_KEY_TYPE_AES: if (bits != 128 && bits != 192 && bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_ARIA) case PSA_KEY_TYPE_ARIA: if (bits != 128 && bits != 192 && bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_CAMELLIA) case PSA_KEY_TYPE_CAMELLIA: if (bits != 128 && bits != 192 && bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_DES) case PSA_KEY_TYPE_DES: if (bits != 64 && bits != 128 && bits != 192) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif #if defined(PSA_WANT_KEY_TYPE_CHACHA20) case PSA_KEY_TYPE_CHACHA20: if (bits != 256) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif default: return PSA_ERROR_NOT_SUPPORTED; } if (bits % 8 != 0) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } /** Check whether a given key type is valid for use with a given MAC algorithm * * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH * when called with the validated \p algorithm and \p key_type is well-defined. * * \param[in] algorithm The specific MAC algorithm (can be wildcard). * \param[in] key_type The key type of the key to be used with the * \p algorithm. * * \retval #PSA_SUCCESS * The \p key_type is valid for use with the \p algorithm * \retval #PSA_ERROR_INVALID_ARGUMENT * The \p key_type is not valid for use with the \p algorithm */ MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do( psa_algorithm_t algorithm, psa_key_type_t key_type) { if (PSA_ALG_IS_HMAC(algorithm)) { if (key_type == PSA_KEY_TYPE_HMAC) { return PSA_SUCCESS; } } if (PSA_ALG_IS_BLOCK_CIPHER_MAC(algorithm)) { /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher * key. */ if ((key_type & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) { /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and * the block length (larger than 1) for block ciphers. */ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1) { return PSA_SUCCESS; } } } return PSA_ERROR_INVALID_ARGUMENT; } psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, size_t buffer_length) { if (slot->key.data != NULL) { return PSA_ERROR_ALREADY_EXISTS; } slot->key.data = mbedtls_calloc(1, buffer_length); if (slot->key.data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } slot->key.bytes = buffer_length; return PSA_SUCCESS; } psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot, const uint8_t *data, size_t data_length) { psa_status_t status = psa_allocate_buffer_to_slot(slot, data_length); if (status != PSA_SUCCESS) { return status; } memcpy(slot->key.data, data, data_length); return PSA_SUCCESS; } psa_status_t psa_import_key_into_slot( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->type; /* zero-length keys are never supported. */ if (data_length == 0) { return PSA_ERROR_NOT_SUPPORTED; } if (key_type_is_raw_bytes(type)) { *bits = PSA_BYTES_TO_BITS(data_length); status = psa_validate_unstructured_key_bit_size(attributes->type, *bits); if (status != PSA_SUCCESS) { return status; } /* Copy the key material. */ memcpy(key_buffer, data, data_length); *key_buffer_length = data_length; (void) key_buffer_size; return PSA_SUCCESS; } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_DH(type)) { if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) { return PSA_ERROR_NOT_SUPPORTED; } return mbedtls_psa_ffdh_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_ECC(type)) { return mbedtls_psa_ecp_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ #if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) if (PSA_KEY_TYPE_IS_RSA(type)) { return mbedtls_psa_rsa_import_key(attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits); } #endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ } return PSA_ERROR_NOT_SUPPORTED; } /** Calculate the intersection of two algorithm usage policies. * * Return 0 (which allows no operation) on incompatibility. */ static psa_algorithm_t psa_key_policy_algorithm_intersection( psa_key_type_t key_type, psa_algorithm_t alg1, psa_algorithm_t alg2) { /* Common case: both sides actually specify the same policy. */ if (alg1 == alg2) { return alg1; } /* If the policies are from the same hash-and-sign family, check * if one is a wildcard. If so the other has the specific algorithm. */ if (PSA_ALG_IS_SIGN_HASH(alg1) && PSA_ALG_IS_SIGN_HASH(alg2) && (alg1 & ~PSA_ALG_HASH_MASK) == (alg2 & ~PSA_ALG_HASH_MASK)) { if (PSA_ALG_SIGN_GET_HASH(alg1) == PSA_ALG_ANY_HASH) { return alg2; } if (PSA_ALG_SIGN_GET_HASH(alg2) == PSA_ALG_ANY_HASH) { return alg1; } } /* If the policies are from the same AEAD family, check whether * one of them is a minimum-tag-length wildcard. Calculate the most * restrictive tag length. */ if (PSA_ALG_IS_AEAD(alg1) && PSA_ALG_IS_AEAD(alg2) && (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg1, 0) == PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg2, 0))) { size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg1); size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg2); size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; /* If both are wildcards, return most restrictive wildcard */ if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && ((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { return PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( alg1, restricted_len); } /* If only one is a wildcard, return specific algorithm if compatible. */ if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && (alg1_len <= alg2_len)) { return alg2; } if (((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) && (alg2_len <= alg1_len)) { return alg1; } } /* If the policies are from the same MAC family, check whether one * of them is a minimum-MAC-length policy. Calculate the most * restrictive tag length. */ if (PSA_ALG_IS_MAC(alg1) && PSA_ALG_IS_MAC(alg2) && (PSA_ALG_FULL_LENGTH_MAC(alg1) == PSA_ALG_FULL_LENGTH_MAC(alg2))) { /* Validate the combination of key type and algorithm. Since the base * algorithm of alg1 and alg2 are the same, we only need this once. */ if (PSA_SUCCESS != psa_mac_key_can_do(alg1, key_type)) { return 0; } /* Get the (exact or at-least) output lengths for both sides of the * requested intersection. None of the currently supported algorithms * have an output length dependent on the actual key size, so setting it * to a bogus value of 0 is currently OK. * * Note that for at-least-this-length wildcard algorithms, the output * length is set to the shortest allowed length, which allows us to * calculate the most restrictive tag length for the intersection. */ size_t alg1_len = PSA_MAC_LENGTH(key_type, 0, alg1); size_t alg2_len = PSA_MAC_LENGTH(key_type, 0, alg2); size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; /* If both are wildcards, return most restrictive wildcard */ if (((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) && ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { return PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg1, restricted_len); } /* If only one is an at-least-this-length policy, the intersection would * be the other (fixed-length) policy as long as said fixed length is * equal to or larger than the shortest allowed length. */ if ((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { return (alg1_len <= alg2_len) ? alg2 : 0; } if ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { return (alg2_len <= alg1_len) ? alg1 : 0; } /* If none of them are wildcards, check whether they define the same tag * length. This is still possible here when one is default-length and * the other specific-length. Ensure to always return the * specific-length version for the intersection. */ if (alg1_len == alg2_len) { return PSA_ALG_TRUNCATED_MAC(alg1, alg1_len); } } /* If the policies are incompatible, allow nothing. */ return 0; } static int psa_key_algorithm_permits(psa_key_type_t key_type, psa_algorithm_t policy_alg, psa_algorithm_t requested_alg) { /* Common case: the policy only allows requested_alg. */ if (requested_alg == policy_alg) { return 1; } /* If policy_alg is a hash-and-sign with a wildcard for the hash, * and requested_alg is the same hash-and-sign family with any hash, * then requested_alg is compliant with policy_alg. */ if (PSA_ALG_IS_SIGN_HASH(requested_alg) && PSA_ALG_SIGN_GET_HASH(policy_alg) == PSA_ALG_ANY_HASH) { return (policy_alg & ~PSA_ALG_HASH_MASK) == (requested_alg & ~PSA_ALG_HASH_MASK); } /* If policy_alg is a wildcard AEAD algorithm of the same base as * the requested algorithm, check the requested tag length to be * equal-length or longer than the wildcard-specified length. */ if (PSA_ALG_IS_AEAD(policy_alg) && PSA_ALG_IS_AEAD(requested_alg) && (PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, 0) == PSA_ALG_AEAD_WITH_SHORTENED_TAG(requested_alg, 0)) && ((policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) { return PSA_ALG_AEAD_GET_TAG_LENGTH(policy_alg) <= PSA_ALG_AEAD_GET_TAG_LENGTH(requested_alg); } /* If policy_alg is a MAC algorithm of the same base as the requested * algorithm, check whether their MAC lengths are compatible. */ if (PSA_ALG_IS_MAC(policy_alg) && PSA_ALG_IS_MAC(requested_alg) && (PSA_ALG_FULL_LENGTH_MAC(policy_alg) == PSA_ALG_FULL_LENGTH_MAC(requested_alg))) { /* Validate the combination of key type and algorithm. Since the policy * and requested algorithms are the same, we only need this once. */ if (PSA_SUCCESS != psa_mac_key_can_do(policy_alg, key_type)) { return 0; } /* Get both the requested output length for the algorithm which is to be * verified, and the default output length for the base algorithm. * Note that none of the currently supported algorithms have an output * length dependent on actual key size, so setting it to a bogus value * of 0 is currently OK. */ size_t requested_output_length = PSA_MAC_LENGTH( key_type, 0, requested_alg); size_t default_output_length = PSA_MAC_LENGTH( key_type, 0, PSA_ALG_FULL_LENGTH_MAC(requested_alg)); /* If the policy is default-length, only allow an algorithm with * a declared exact-length matching the default. */ if (PSA_MAC_TRUNCATED_LENGTH(policy_alg) == 0) { return requested_output_length == default_output_length; } /* If the requested algorithm is default-length, allow it if the policy * length exactly matches the default length. */ if (PSA_MAC_TRUNCATED_LENGTH(requested_alg) == 0 && PSA_MAC_TRUNCATED_LENGTH(policy_alg) == default_output_length) { return 1; } /* If policy_alg is an at-least-this-length wildcard MAC algorithm, * check for the requested MAC length to be equal to or longer than the * minimum allowed length. */ if ((policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) { return PSA_MAC_TRUNCATED_LENGTH(policy_alg) <= requested_output_length; } } /* If policy_alg is a generic key agreement operation, then using it for * a key derivation with that key agreement should also be allowed. This * behaviour is expected to be defined in a future specification version. */ if (PSA_ALG_IS_RAW_KEY_AGREEMENT(policy_alg) && PSA_ALG_IS_KEY_AGREEMENT(requested_alg)) { return PSA_ALG_KEY_AGREEMENT_GET_BASE(requested_alg) == policy_alg; } /* If it isn't explicitly permitted, it's forbidden. */ return 0; } /** Test whether a policy permits an algorithm. * * The caller must test usage flags separately. * * \note This function requires providing the key type for which the policy is * being validated, since some algorithm policy definitions (e.g. MAC) * have different properties depending on what kind of cipher it is * combined with. * * \retval PSA_SUCCESS When \p alg is a specific algorithm * allowed by the \p policy. * \retval PSA_ERROR_INVALID_ARGUMENT When \p alg is not a specific algorithm * \retval PSA_ERROR_NOT_PERMITTED When \p alg is a specific algorithm, but * the \p policy does not allow it. */ static psa_status_t psa_key_policy_permits(const psa_key_policy_t *policy, psa_key_type_t key_type, psa_algorithm_t alg) { /* '0' is not a valid algorithm */ if (alg == 0) { return PSA_ERROR_INVALID_ARGUMENT; } /* A requested algorithm cannot be a wildcard. */ if (PSA_ALG_IS_WILDCARD(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } if (psa_key_algorithm_permits(key_type, policy->alg, alg) || psa_key_algorithm_permits(key_type, policy->alg2, alg)) { return PSA_SUCCESS; } else { return PSA_ERROR_NOT_PERMITTED; } } /** Restrict a key policy based on a constraint. * * \note This function requires providing the key type for which the policy is * being restricted, since some algorithm policy definitions (e.g. MAC) * have different properties depending on what kind of cipher it is * combined with. * * \param[in] key_type The key type for which to restrict the policy * \param[in,out] policy The policy to restrict. * \param[in] constraint The policy constraint to apply. * * \retval #PSA_SUCCESS * \c *policy contains the intersection of the original value of * \c *policy and \c *constraint. * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key_type, \c *policy and \c *constraint are incompatible. * \c *policy is unchanged. */ static psa_status_t psa_restrict_key_policy( psa_key_type_t key_type, psa_key_policy_t *policy, const psa_key_policy_t *constraint) { psa_algorithm_t intersection_alg = psa_key_policy_algorithm_intersection(key_type, policy->alg, constraint->alg); psa_algorithm_t intersection_alg2 = psa_key_policy_algorithm_intersection(key_type, policy->alg2, constraint->alg2); if (intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0) { return PSA_ERROR_INVALID_ARGUMENT; } if (intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0) { return PSA_ERROR_INVALID_ARGUMENT; } policy->usage &= constraint->usage; policy->alg = intersection_alg; policy->alg2 = intersection_alg2; return PSA_SUCCESS; } /** Get the description of a key given its identifier and policy constraints * and lock it. * * The key must have allow all the usage flags set in \p usage. If \p alg is * nonzero, the key must allow operations with this algorithm. If \p alg is * zero, the algorithm is not checked. * * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * * On success, the returned key slot has been registered for reading. * It is the responsibility of the caller to then unregister * once they have finished reading the contents of the slot. * The caller unregisters by calling psa_unregister_read() or * psa_unregister_read_under_mutex(). psa_unregister_read() must be called * if and only if the caller already holds the global key slot mutex * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates * the unregister with mutex lock and unlock operations. */ static psa_status_t psa_get_and_lock_key_slot_with_policy( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; status = psa_get_and_lock_key_slot(key, p_slot); if (status != PSA_SUCCESS) { return status; } slot = *p_slot; /* Enforce that usage policy for the key slot contains all the flags * required by the usage parameter. There is one exception: public * keys can always be exported, so we treat public key objects as * if they had the export flag. */ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { usage &= ~PSA_KEY_USAGE_EXPORT; } if ((slot->attr.policy.usage & usage) != usage) { status = PSA_ERROR_NOT_PERMITTED; goto error; } /* Enforce that the usage policy permits the requested algorithm. */ if (alg != 0) { status = psa_key_policy_permits(&slot->attr.policy, slot->attr.type, alg); if (status != PSA_SUCCESS) { goto error; } } return PSA_SUCCESS; error: *p_slot = NULL; psa_unregister_read_under_mutex(slot); return status; } /** Get a key slot containing a transparent key and lock it. * * A transparent key is a key for which the key material is directly * available, as opposed to a key in a secure element and/or to be used * by a secure element. * * This is a temporary function that may be used instead of * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support * for a cryptographic operation. * * On success, the returned key slot has been registered for reading. * It is the responsibility of the caller to then unregister * once they have finished reading the contents of the slot. * The caller unregisters by calling psa_unregister_read() or * psa_unregister_read_under_mutex(). psa_unregister_read() must be called * if and only if the caller already holds the global key slot mutex * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates * psa_unregister_read() with mutex lock and unlock operations. */ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg) { psa_status_t status = psa_get_and_lock_key_slot_with_policy(key, p_slot, usage, alg); if (status != PSA_SUCCESS) { return status; } if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) { psa_unregister_read_under_mutex(*p_slot); *p_slot = NULL; return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) { if (slot->key.data != NULL) { mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes); } slot->key.data = NULL; slot->key.bytes = 0; return PSA_SUCCESS; } /** Completely wipe a slot in memory, including its policy. * Persistent storage is not affected. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot) { psa_status_t status = psa_remove_key_data_from_memory(slot); /* * As the return error code may not be handled in case of multiple errors, * do our best to report an unexpected amount of registered readers or * an unexpected state. * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for * wiping. * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the * function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ switch (slot->state) { case PSA_SLOT_FULL: /* In this state psa_wipe_key_slot() must only be called if the * caller is the last reader. */ case PSA_SLOT_PENDING_DELETION: /* In this state psa_wipe_key_slot() must only be called if the * caller is the last reader. */ if (slot->registered_readers != 1) { MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 1); status = PSA_ERROR_CORRUPTION_DETECTED; } break; case PSA_SLOT_FILLING: /* In this state registered_readers must be 0. */ if (slot->registered_readers != 0) { MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->registered_readers == 0); status = PSA_ERROR_CORRUPTION_DETECTED; } break; case PSA_SLOT_EMPTY: /* The slot is already empty, it cannot be wiped. */ MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY); status = PSA_ERROR_CORRUPTION_DETECTED; break; default: /* The slot's state is invalid. */ status = PSA_ERROR_CORRUPTION_DETECTED; } /* Multipart operations may still be using the key. This is safe * because all multipart operation objects are independent from * the key slot: if they need to access the key after the setup * phase, they have a copy of the key. Note that this means that * key material can linger until all operations are completed. */ /* At this point, key material and other type-specific content has * been wiped. Clear remaining metadata. We can call memset and not * zeroize because the metadata is not particularly sensitive. * This memset also sets the slot's state to PSA_SLOT_EMPTY. */ memset(slot, 0, sizeof(*slot)); return status; } psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key) { psa_key_slot_t *slot; psa_status_t status; /* status of the last operation */ psa_status_t overall_status = PSA_SUCCESS; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_se_drv_table_entry_t *driver; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if (mbedtls_svc_key_id_is_null(key)) { return PSA_SUCCESS; } /* * Get the description of the key in a key slot, and register to read it. * In the case of a persistent key, this will load the key description * from persistent memory if not done yet. * We cannot avoid this loading as without it we don't know if * the key is operated by an SE or not and this information is needed by * the current implementation. */ status = psa_get_and_lock_key_slot(key, &slot); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_THREADING_C) /* We cannot unlock between setting the state to PENDING_DELETION * and destroying the key in storage, as otherwise another thread * could load the key into a new slot and the key will not be * fully destroyed. */ PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); if (slot->state == PSA_SLOT_PENDING_DELETION) { /* Another thread has destroyed the key between us locking the slot * and us gaining the mutex. Unregister from the slot, * and report that the key does not exist. */ status = psa_unregister_read(slot); PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status; } #endif /* Set the key slot containing the key description's state to * PENDING_DELETION. This stops new operations from registering * to read the slot. Current readers can safely continue to access * the key within the slot; the last registered reader will * automatically wipe the slot when they call psa_unregister_read(). * If the key is persistent, we can now delete the copy of the key * from memory. If the key is opaque, we require the driver to * deal with the deletion. */ overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL, PSA_SLOT_PENDING_DELETION); if (overall_status != PSA_SUCCESS) { goto exit; } if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) { /* Refuse the destruction of a read-only key (which may or may not work * if we attempt it, depending on whether the key is merely read-only * by policy or actually physically read-only). * Just do the best we can, which is to wipe the copy in memory * (done in this function's cleanup code). */ overall_status = PSA_ERROR_NOT_PERMITTED; goto exit; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) driver = psa_get_se_driver_entry(slot->attr.lifetime); if (driver != NULL) { /* For a key in a secure element, we need to do three things: * remove the key file in internal storage, destroy the * key inside the secure element, and update the driver's * persistent data. Start a transaction that will encompass these * three actions. */ psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_DESTROY_KEY); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number(slot); psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction(); if (status != PSA_SUCCESS) { (void) psa_crypto_stop_transaction(); /* We should still try to destroy the key in the secure * element and the key metadata in storage. This is especially * important if the error is that the storage is full. * But how to do it exactly without risking an inconsistent * state after a reset? * https://github.com/ARMmbed/mbed-crypto/issues/215 */ overall_status = status; goto exit; } status = psa_destroy_se_key(driver, psa_key_slot_get_slot_number(slot)); if (overall_status == PSA_SUCCESS) { overall_status = status; } } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { /* Destroy the copy of the persistent key from storage. * The slot will still hold a copy of the key until the last reader * unregisters. */ status = psa_destroy_persistent_key(slot->attr.id); if (overall_status == PSA_SUCCESS) { overall_status = status; } } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (driver != NULL) { status = psa_save_se_persistent_data(driver); if (overall_status == PSA_SUCCESS) { overall_status = status; } status = psa_crypto_stop_transaction(); if (overall_status == PSA_SUCCESS) { overall_status = status; } } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ exit: /* Unregister from reading the slot. If we are the last active reader * then this will wipe the slot. */ status = psa_unregister_read(slot); /* Prioritize CORRUPTION_DETECTED from unregistering over * a storage error. */ if (status != PSA_SUCCESS) { overall_status = status; } #if defined(MBEDTLS_THREADING_C) /* Don't overwrite existing errors if the unlock fails. */ status = overall_status; PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return overall_status; } /** Retrieve all the publicly-accessible attributes of a key. */ psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, psa_key_attributes_t *attributes) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; psa_reset_key_attributes(attributes); status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0); if (status != PSA_SUCCESS) { return status; } *attributes = slot->attr; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) { psa_set_key_slot_number(attributes, psa_key_slot_get_slot_number(slot)); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ return psa_unregister_read_under_mutex(slot); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_status_t psa_get_key_slot_number( const psa_key_attributes_t *attributes, psa_key_slot_number_t *slot_number) { if (attributes->has_slot_number) { *slot_number = attributes->slot_number; return PSA_SUCCESS; } else { return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ static psa_status_t psa_export_key_buffer_internal(const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { if (key_buffer_size > data_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(data, key_buffer, key_buffer_size); memset(data + key_buffer_size, 0, data_size - key_buffer_size); *data_length = key_buffer_size; return PSA_SUCCESS; } psa_status_t psa_export_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_key_type_t type = attributes->type; if (key_type_is_raw_bytes(type) || PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) || PSA_KEY_TYPE_IS_DH(type)) { return psa_export_key_buffer_internal( key_buffer, key_buffer_size, data, data_size, data_length); } else { /* This shouldn't happen in the reference implementation, but it is valid for a special-purpose implementation to omit support for exporting certain key types. */ return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t psa_export_key(mbedtls_svc_key_id_t key, uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ if (data_size == 0) { return PSA_ERROR_BUFFER_TOO_SMALL; } /* Set the key to empty now, so that even when there are errors, we always * set data_length to a value between 0 and data_size. On error, setting * the key to empty is a good choice because an empty key representation is * unlikely to be accepted anywhere. */ *data_length = 0; /* Export requires the EXPORT flag. There is an exception for public keys, * which don't require any flag, but * psa_get_and_lock_key_slot_with_policy() takes care of this. */ status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_EXPORT, 0); if (status != PSA_SUCCESS) { return status; } LOCAL_OUTPUT_ALLOC(data_external, data_size, data); status = psa_driver_wrapper_export_key(&slot->attr, slot->key.data, slot->key.bytes, data, data_size, data_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_export_public_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_key_type_t type = attributes->type; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) || PSA_KEY_TYPE_IS_DH(type))) { /* Exporting public -> public */ return psa_export_key_buffer_internal( key_buffer, key_buffer_size, data, data_size, data_length); } else if (PSA_KEY_TYPE_IS_RSA(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) return mbedtls_psa_rsa_export_public_key(attributes, key_buffer, key_buffer_size, data, data_size, data_length); #else /* We don't know how to convert a private RSA key to public. */ return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ } else if (PSA_KEY_TYPE_IS_ECC(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) return mbedtls_psa_ecp_export_public_key(attributes, key_buffer, key_buffer_size, data, data_size, data_length); #else /* We don't know how to convert a private ECC key to public */ return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ } else if (PSA_KEY_TYPE_IS_DH(type)) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) return mbedtls_psa_ffdh_export_public_key(attributes, key_buffer, key_buffer_size, data, data_size, data_length); #else return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */ } else { (void) key_buffer; (void) key_buffer_size; (void) data; (void) data_size; (void) data_length; return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, uint8_t *data_external, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_OUTPUT_DECLARE(data_external, data); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ if (data_size == 0) { return PSA_ERROR_BUFFER_TOO_SMALL; } /* Set the key to empty now, so that even when there are errors, we always * set data_length to a value between 0 and data_size. On error, setting * the key to empty is a good choice because an empty key representation is * unlikely to be accepted anywhere. */ *data_length = 0; /* Exporting a public key doesn't require a usage flag. */ status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0); if (status != PSA_SUCCESS) { return status; } LOCAL_OUTPUT_ALLOC(data_external, data_size, data); if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_driver_wrapper_export_public_key( &slot->attr, slot->key.data, slot->key.bytes, data, data_size, data_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_OUTPUT_FREE(data_external, data); return (status == PSA_SUCCESS) ? unlock_status : status; } /** Validate that a key policy is internally well-formed. * * This function only rejects invalid policies. It does not validate the * consistency of the policy with respect to other attributes of the key * such as the key type. */ static psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy) { if ((policy->usage & ~(PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_DERIVATION | PSA_KEY_USAGE_DERIVE)) != 0) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } /** Validate the internal consistency of key attributes. * * This function only rejects invalid attribute values. If does not * validate the consistency of the attributes with any key data that may * be involved in the creation of the key. * * Call this function early in the key creation process. * * \param[in] attributes Key attributes for the new key. * \param[out] p_drv On any return, the driver for the key, if any. * NULL for a transparent key. * */ static psa_status_t psa_validate_key_attributes( const psa_key_attributes_t *attributes, psa_se_drv_table_entry_t **p_drv) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_lifetime_t lifetime = psa_get_key_lifetime(attributes); mbedtls_svc_key_id_t key = psa_get_key_id(attributes); status = psa_validate_key_location(lifetime, p_drv); if (status != PSA_SUCCESS) { return status; } status = psa_validate_key_persistence(lifetime); if (status != PSA_SUCCESS) { return status; } if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key) != 0) { return PSA_ERROR_INVALID_ARGUMENT; } } else { if (!psa_is_valid_key_id(psa_get_key_id(attributes), 0)) { return PSA_ERROR_INVALID_ARGUMENT; } } status = psa_validate_key_policy(&attributes->policy); if (status != PSA_SUCCESS) { return status; } /* Refuse to create overly large keys. * Note that this doesn't trigger on import if the attributes don't * explicitly specify a size (so psa_get_key_bits returns 0), so * psa_import_key() needs its own checks. */ if (psa_get_key_bits(attributes) > PSA_MAX_KEY_BITS) { return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } /** Prepare a key slot to receive key material. * * This function allocates a key slot and sets its metadata. * * If this function fails, call psa_fail_key_creation(). * * This function is intended to be used as follows: * -# Call psa_start_key_creation() to allocate a key slot, prepare * it with the specified attributes, and in case of a volatile key assign it * a volatile key identifier. * -# Populate the slot with the key material. * -# Call psa_finish_key_creation() to finalize the creation of the slot. * In case of failure at any step, stop the sequence and call * psa_fail_key_creation(). * * On success, the key slot's state is PSA_SLOT_FILLING. * It is the responsibility of the caller to change the slot's state to * PSA_SLOT_EMPTY/FULL once key creation has finished. * * \param method An identification of the calling function. * \param[in] attributes Key attributes for the new key. * \param[out] p_slot On success, a pointer to the prepared slot. * \param[out] p_drv On any return, the driver for the key, if any. * NULL for a transparent key. * * \retval #PSA_SUCCESS * The key slot is ready to receive key material. * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. */ static psa_status_t psa_start_key_creation( psa_key_creation_method_t method, const psa_key_attributes_t *attributes, psa_key_slot_t **p_slot, psa_se_drv_table_entry_t **p_drv) { psa_status_t status; psa_key_id_t volatile_key_id; psa_key_slot_t *slot; (void) method; *p_drv = NULL; status = psa_validate_key_attributes(attributes, p_drv); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_reserve_free_key_slot(&volatile_key_id, p_slot); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif if (status != PSA_SUCCESS) { return status; } slot = *p_slot; /* We're storing the declared bit-size of the key. It's up to each * creation mechanism to verify that this information is correct. * It's automatically correct for mechanisms that use the bit-size as * an input (generate, device) but not for those where the bit-size * is optional (import, copy). In case of a volatile key, assign it the * volatile key identifier associated to the slot returned to contain its * definition. */ slot->attr = *attributes; if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { #if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) slot->attr.id = volatile_key_id; #else slot->attr.id.key_id = volatile_key_id; #endif } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things * when creating or registering a persistent key: * create the key file in internal storage, create the * key inside the secure element, and update the driver's * persistent data. This is done by starting a transaction that will * encompass these three actions. * For registering a volatile key, we just need to find an appropriate * slot number inside the SE. Since the key is designated volatile, creating * a transaction is not required. */ /* The first thing to do is to find a slot number for the new key. * We save the slot number in persistent storage as part of the * transaction data. It will be needed to recover if the power * fails during the key creation process, to clean up on the secure * element side after restarting. Obtaining a slot number from the * secure element driver updates its persistent state, but we do not yet * save the driver's persistent state, so that if the power fails, * we can roll back to a state where the key doesn't exist. */ if (*p_drv != NULL) { psa_key_slot_number_t slot_number; status = psa_find_se_slot_for_key(attributes, method, *p_drv, &slot_number); if (status != PSA_SUCCESS) { return status; } if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) { psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = slot_number; psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction(); if (status != PSA_SUCCESS) { (void) psa_crypto_stop_transaction(); return status; } } status = psa_copy_key_material_into_slot( slot, (uint8_t *) (&slot_number), sizeof(slot_number)); } if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) { /* Key registration only makes sense with a secure element. */ return PSA_ERROR_INVALID_ARGUMENT; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ return PSA_SUCCESS; } /** Finalize the creation of a key once its key material has been set. * * This entails writing the key to persistent storage. * * If this function fails, call psa_fail_key_creation(). * See the documentation of psa_start_key_creation() for the intended use * of this function. * * If the finalization succeeds, the function sets the key slot's state to * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the * key creation process. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, * or NULL for a transparent key. * \param[out] key On success, identifier of the key. Note that the * key identifier is also stored in the key slot. * * \retval #PSA_SUCCESS * The key was successfully created. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. */ static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot, psa_se_drv_table_entry_t *driver, mbedtls_svc_key_id_t *key) { psa_status_t status = PSA_SUCCESS; (void) slot; (void) driver; #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (driver != NULL) { psa_se_key_data_storage_t data; psa_key_slot_number_t slot_number = psa_key_slot_get_slot_number(slot); MBEDTLS_STATIC_ASSERT(sizeof(slot_number) == sizeof(data.slot_number), "Slot number size does not match psa_se_key_data_storage_t"); memcpy(&data.slot_number, &slot_number, sizeof(slot_number)); status = psa_save_persistent_key(&slot->attr, (uint8_t *) &data, sizeof(data)); } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ { /* Key material is saved in export representation in the slot, so * just pass the slot buffer for storage. */ status = psa_save_persistent_key(&slot->attr, slot->key.data, slot->key.bytes); } } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Finish the transaction for a key creation. This does not * happen when registering an existing key. Detect this case * by checking whether a transaction is in progress (actual * creation of a persistent key in a secure element requires a transaction, * but registration or volatile key creation doesn't use one). */ if (driver != NULL && psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY) { status = psa_save_se_persistent_data(driver); if (status != PSA_SUCCESS) { psa_destroy_persistent_key(slot->attr.id); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } status = psa_crypto_stop_transaction(); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if (status == PSA_SUCCESS) { *key = slot->attr.id; status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING, PSA_SLOT_FULL); if (status != PSA_SUCCESS) { *key = MBEDTLS_SVC_KEY_ID_INIT; } } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } /** Abort the creation of a key. * * You may call this function after calling psa_start_key_creation(), * or after psa_finish_key_creation() fails. In other circumstances, this * function may not clean up persistent storage. * See the documentation of psa_start_key_creation() for the intended use * of this function. Sets the slot's state to PSA_SLOT_EMPTY. * * \param[in,out] slot Pointer to the slot with key material. * \param[in] driver The secure element driver for the key, * or NULL for a transparent key. */ static void psa_fail_key_creation(psa_key_slot_t *slot, psa_se_drv_table_entry_t *driver) { (void) driver; if (slot == NULL) { return; } #if defined(MBEDTLS_THREADING_C) /* If the lock operation fails we still wipe the slot. * Operations will no longer work after a failed lock, * but we still need to wipe the slot of confidential data. */ mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex); #endif #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* TODO: If the key has already been created in the secure * element, and the failure happened later (when saving metadata * to internal storage), we need to destroy the key in the secure * element. * https://github.com/ARMmbed/mbed-crypto/issues/217 */ /* Abort the ongoing transaction if any (there may not be one if * the creation process failed before starting one, or if the * key creation is a registration of a key in a secure element). * Earlier functions must already have done what it takes to undo any * partial creation. All that's left is to update the transaction data * itself. */ (void) psa_crypto_stop_transaction(); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_wipe_key_slot(slot); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex); #endif } /** Validate optional attributes during key creation. * * Some key attributes are optional during key creation. If they are * specified in the attributes structure, check that they are consistent * with the data in the slot. * * This function should be called near the end of key creation, after * the slot in memory is fully populated but before saving persistent data. */ static psa_status_t psa_validate_optional_attributes( const psa_key_slot_t *slot, const psa_key_attributes_t *attributes) { if (attributes->type != 0) { if (attributes->type != slot->attr.type) { return PSA_ERROR_INVALID_ARGUMENT; } } if (attributes->bits != 0) { if (attributes->bits != slot->attr.bits) { return PSA_ERROR_INVALID_ARGUMENT; } } return PSA_SUCCESS; } psa_status_t psa_import_key(const psa_key_attributes_t *attributes, const uint8_t *data_external, size_t data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; LOCAL_INPUT_DECLARE(data_external, data); psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; size_t bits; size_t storage_size = data_length; *key = MBEDTLS_SVC_KEY_ID_INIT; /* Reject zero-length symmetric keys (including raw data key objects). * This also rejects any key which might be encoded as an empty string, * which is never valid. */ if (data_length == 0) { return PSA_ERROR_INVALID_ARGUMENT; } /* Ensure that the bytes-to-bits conversion cannot overflow. */ if (data_length > SIZE_MAX / 8) { return PSA_ERROR_NOT_SUPPORTED; } LOCAL_INPUT_ALLOC(data_external, data_length, data); status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes, &slot, &driver); if (status != PSA_SUCCESS) { goto exit; } /* In the case of a transparent key or an opaque key stored in local * storage ( thus not in the case of importing a key in a secure element * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a * buffer to hold the imported key material. */ if (slot->key.data == NULL) { if (psa_key_lifetime_is_external(attributes->lifetime)) { status = psa_driver_wrapper_get_key_buffer_size_from_key_data( attributes, data, data_length, &storage_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_allocate_buffer_to_slot(slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } } bits = slot->attr.bits; status = psa_driver_wrapper_import_key(attributes, data, data_length, slot->key.data, slot->key.bytes, &slot->key.bytes, &bits); if (status != PSA_SUCCESS) { goto exit; } if (slot->attr.bits == 0) { slot->attr.bits = (psa_key_bits_t) bits; } else if (bits != slot->attr.bits) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Enforce a size limit, and in particular ensure that the bit * size fits in its representation type.*/ if (bits > PSA_MAX_KEY_BITS) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = psa_validate_optional_attributes(slot, attributes); if (status != PSA_SUCCESS) { goto exit; } status = psa_finish_key_creation(slot, driver, key); exit: LOCAL_INPUT_FREE(data_external, data); if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } return status; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) psa_status_t mbedtls_psa_register_se_key( const psa_key_attributes_t *attributes) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; /* Leaving attributes unspecified is not currently supported. * It could make sense to query the key type and size from the * secure element, but not all secure elements support this * and the driver HAL doesn't currently support it. */ if (psa_get_key_type(attributes) == PSA_KEY_TYPE_NONE) { return PSA_ERROR_NOT_SUPPORTED; } if (psa_get_key_bits(attributes) == 0) { return PSA_ERROR_NOT_SUPPORTED; } status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes, &slot, &driver); if (status != PSA_SUCCESS) { goto exit; } status = psa_finish_key_creation(slot, driver, &key); exit: if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } /* Registration doesn't keep the key in RAM. */ psa_close_key(key); return status; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, const psa_key_attributes_t *specified_attributes, mbedtls_svc_key_id_t *target_key) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *source_slot = NULL; psa_key_slot_t *target_slot = NULL; psa_key_attributes_t actual_attributes = *specified_attributes; psa_se_drv_table_entry_t *driver = NULL; size_t storage_size = 0; *target_key = MBEDTLS_SVC_KEY_ID_INIT; status = psa_get_and_lock_key_slot_with_policy( source_key, &source_slot, PSA_KEY_USAGE_COPY, 0); if (status != PSA_SUCCESS) { goto exit; } status = psa_validate_optional_attributes(source_slot, specified_attributes); if (status != PSA_SUCCESS) { goto exit; } /* The target key type and number of bits have been validated by * psa_validate_optional_attributes() to be either equal to zero or * equal to the ones of the source key. So it is safe to inherit * them from the source key now." * */ actual_attributes.bits = source_slot->attr.bits; actual_attributes.type = source_slot->attr.type; status = psa_restrict_key_policy(source_slot->attr.type, &actual_attributes.policy, &source_slot->attr.policy); if (status != PSA_SUCCESS) { goto exit; } status = psa_start_key_creation(PSA_KEY_CREATION_COPY, &actual_attributes, &target_slot, &driver); if (status != PSA_SUCCESS) { goto exit; } if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) != PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) { /* * If the source and target keys are stored in different locations, * the source key would need to be exported as plaintext and re-imported * in the other location. This has security implications which have not * been fully mapped. For now, this can be achieved through * appropriate API invocations from the application, if needed. * */ status = PSA_ERROR_NOT_SUPPORTED; goto exit; } /* * When the source and target keys are within the same location, * - For transparent keys it is a blind copy without any driver invocation, * - For opaque keys this translates to an invocation of the drivers' * copy_key entry point through the dispatch layer. * */ if (psa_key_lifetime_is_external(actual_attributes.lifetime)) { status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes, &storage_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_allocate_buffer_to_slot(target_slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_copy_key(&actual_attributes, source_slot->key.data, source_slot->key.bytes, target_slot->key.data, target_slot->key.bytes, &target_slot->key.bytes); if (status != PSA_SUCCESS) { goto exit; } } else { status = psa_copy_key_material_into_slot(target_slot, source_slot->key.data, source_slot->key.bytes); if (status != PSA_SUCCESS) { goto exit; } } status = psa_finish_key_creation(target_slot, driver, target_key); exit: if (status != PSA_SUCCESS) { psa_fail_key_creation(target_slot, driver); } unlock_status = psa_unregister_read_under_mutex(source_slot); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Message digests */ /****************************************************************/ psa_status_t psa_hash_abort(psa_hash_operation_t *operation) { /* Aborting a non-active operation is allowed */ if (operation->id == 0) { return PSA_SUCCESS; } psa_status_t status = psa_driver_wrapper_hash_abort(operation); operation->id = 0; return status; } psa_status_t psa_hash_setup(psa_hash_operation_t *operation, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!PSA_ALG_IS_HASH(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only * directly zeroes the int-sized dummy member of the context union. */ memset(&operation->ctx, 0, sizeof(operation->ctx)); status = psa_driver_wrapper_hash_setup(operation, alg); exit: if (status != PSA_SUCCESS) { psa_hash_abort(operation); } return status; } psa_status_t psa_hash_update(psa_hash_operation_t *operation, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } /* Don't require hash implementations to behave correctly on a * zero-length input, which may have an invalid pointer. */ if (input_length == 0) { return PSA_SUCCESS; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_hash_update(operation, input, input_length); exit: if (status != PSA_SUCCESS) { psa_hash_abort(operation); } LOCAL_INPUT_FREE(input_external, input); return status; } static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *hash_length = 0; if (operation->id == 0) { return PSA_ERROR_BAD_STATE; } status = psa_driver_wrapper_hash_finish( operation, hash, hash_size, hash_length); psa_hash_abort(operation); return status; } psa_status_t psa_hash_finish(psa_hash_operation_t *operation, uint8_t *hash_external, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(hash_external, hash); LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); status = psa_hash_finish_internal(operation, hash, hash_size, hash_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_OUTPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_verify(psa_hash_operation_t *operation, const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(hash_external, hash); status = psa_hash_finish_internal( operation, actual_hash, sizeof(actual_hash), &actual_hash_length); if (status != PSA_SUCCESS) { goto exit; } if (actual_hash_length != hash_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } exit: mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); if (status != PSA_SUCCESS) { psa_hash_abort(operation); } LOCAL_INPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_compute(psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *hash_external, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(hash_external, hash); *hash_length = 0; if (!PSA_ALG_IS_HASH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash); status = psa_driver_wrapper_hash_compute(alg, input, input_length, hash, hash_size, hash_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_compare(psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *hash_external, size_t hash_length) { uint8_t actual_hash[PSA_HASH_MAX_SIZE]; size_t actual_hash_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(hash_external, hash); if (!PSA_ALG_IS_HASH(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; return status; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_hash_compute( alg, input, input_length, actual_hash, sizeof(actual_hash), &actual_hash_length); if (status != PSA_SUCCESS) { goto exit; } if (actual_hash_length != hash_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } exit: mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash)); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(hash_external, hash); return status; } psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation) { if (source_operation->id == 0 || target_operation->id != 0) { return PSA_ERROR_BAD_STATE; } psa_status_t status = psa_driver_wrapper_hash_clone(source_operation, target_operation); if (status != PSA_SUCCESS) { psa_hash_abort(target_operation); } return status; } /****************************************************************/ /* MAC */ /****************************************************************/ psa_status_t psa_mac_abort(psa_mac_operation_t *operation) { /* Aborting a non-active operation is allowed */ if (operation->id == 0) { return PSA_SUCCESS; } psa_status_t status = psa_driver_wrapper_mac_abort(operation); operation->mac_size = 0; operation->is_sign = 0; operation->id = 0; return status; } static psa_status_t psa_mac_finalize_alg_and_key_validation( psa_algorithm_t alg, const psa_key_attributes_t *attributes, uint8_t *mac_size) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t key_type = psa_get_key_type(attributes); size_t key_bits = psa_get_key_bits(attributes); if (!PSA_ALG_IS_MAC(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } /* Validate the combination of key type and algorithm */ status = psa_mac_key_can_do(alg, key_type); if (status != PSA_SUCCESS) { return status; } /* Get the output length for the algorithm and key combination */ *mac_size = PSA_MAC_LENGTH(key_type, key_bits, alg); if (*mac_size < 4) { /* A very short MAC is too short for security since it can be * brute-forced. Ancient protocols with 32-bit MACs do exist, * so we make this our minimum, even though 32 bits is still * too small for security. */ return PSA_ERROR_NOT_SUPPORTED; } if (*mac_size > PSA_MAC_LENGTH(key_type, key_bits, PSA_ALG_FULL_LENGTH_MAC(alg))) { /* It's impossible to "truncate" to a larger length than the full length * of the algorithm. */ return PSA_ERROR_INVALID_ARGUMENT; } if (*mac_size > PSA_MAC_MAX_SIZE) { /* PSA_MAC_LENGTH returns the correct length even for a MAC algorithm * that is disabled in the compile-time configuration. The result can * therefore be larger than PSA_MAC_MAX_SIZE, which does take the * configuration into account. In this case, force a return of * PSA_ERROR_NOT_SUPPORTED here. Otherwise psa_mac_verify(), or * psa_mac_compute(mac_size=PSA_MAC_MAX_SIZE), would return * PSA_ERROR_BUFFER_TOO_SMALL for an unsupported algorithm whose MAC size * is larger than PSA_MAC_MAX_SIZE, which is misleading and which breaks * systematically generated tests. */ return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, int is_sign) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; /* A context must be freshly initialized before it can be set up. */ if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, &operation->mac_size); if (status != PSA_SUCCESS) { goto exit; } operation->is_sign = is_sign; /* Dispatch the MAC setup call with validated input */ if (is_sign) { status = psa_driver_wrapper_mac_sign_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_mac_verify_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } exit: if (status != PSA_SUCCESS) { psa_mac_abort(operation); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_mac_setup(operation, key, alg, 1); } psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_mac_setup(operation, key, alg, 0); } psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; return status; } /* Don't require hash implementations to behave correctly on a * zero-length input, which may have an invalid pointer. */ if (input_length == 0) { status = PSA_SUCCESS; return status; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_mac_update(operation, input, input_length); if (status != PSA_SUCCESS) { psa_mac_abort(operation); } #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); return status; } psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac_external, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(mac_external, mac); LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!operation->is_sign) { status = PSA_ERROR_BAD_STATE; goto exit; } /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL) * once all the error checks are done. */ if (operation->mac_size == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (mac_size < operation->mac_size) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_driver_wrapper_mac_sign_finish(operation, mac, operation->mac_size, mac_length); exit: /* In case of success, set the potential excess room in the output buffer * to an invalid value, to avoid potentially leaking a longer MAC. * In case of error, set the output length and content to a safe default, * such that in case the caller misses an error check, the output would be * an unachievable MAC. */ if (status != PSA_SUCCESS) { *mac_length = mac_size; operation->mac_size = 0; } if (mac != NULL) { psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); } abort_status = psa_mac_abort(operation); LOCAL_OUTPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(mac_external, mac); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->is_sign) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->mac_size != mac_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); status = psa_driver_wrapper_mac_verify_finish(operation, mac, mac_length); exit: abort_status = psa_mac_abort(operation); LOCAL_INPUT_FREE(mac_external, mac); return status == PSA_SUCCESS ? abort_status : status; } static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length, int is_sign) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; uint8_t operation_mac_size = 0; status = psa_get_and_lock_key_slot_with_policy( key, &slot, is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr, &operation_mac_size); if (status != PSA_SUCCESS) { goto exit; } if (mac_size < operation_mac_size) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_driver_wrapper_mac_compute( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, mac, operation_mac_size, mac_length); exit: /* In case of success, set the potential excess room in the output buffer * to an invalid value, to avoid potentially leaking a longer MAC. * In case of error, set the output length and content to a safe default, * such that in case the caller misses an error check, the output would be * an unachievable MAC. */ if (status != PSA_SUCCESS) { *mac_length = mac_size; operation_mac_size = 0; } psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length); unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *mac_external, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(mac_external, mac); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac); status = psa_mac_compute_internal(key, alg, input, input_length, mac, mac_size, mac_length, 1); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(mac_external, mac); return status; } psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *mac_external, size_t mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t actual_mac[PSA_MAC_MAX_SIZE]; size_t actual_mac_length; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(mac_external, mac); LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_mac_compute_internal(key, alg, input, input_length, actual_mac, sizeof(actual_mac), &actual_mac_length, 0); if (status != PSA_SUCCESS) { goto exit; } if (mac_length != actual_mac_length) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } LOCAL_INPUT_ALLOC(mac_external, mac_length, mac); if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } exit: mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(mac_external, mac); return status; } /****************************************************************/ /* Asymmetric cryptography */ /****************************************************************/ static psa_status_t psa_sign_verify_check_alg(int input_is_message, psa_algorithm_t alg) { if (input_is_message) { if (!PSA_ALG_IS_SIGN_MESSAGE(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } if (PSA_ALG_IS_SIGN_HASH(alg)) { if (!PSA_ALG_IS_HASH(PSA_ALG_SIGN_GET_HASH(alg))) { return PSA_ERROR_INVALID_ARGUMENT; } } } else { if (!PSA_ALG_IS_SIGN_HASH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } } return PSA_SUCCESS; } static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key, int input_is_message, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; *signature_length = 0; status = psa_sign_verify_check_alg(input_is_message, alg); if (status != PSA_SUCCESS) { return status; } /* Immediately reject a zero-length signature buffer. This guarantees * that signature must be a valid pointer. (On the other hand, the input * buffer can in principle be empty since it doesn't actually have * to be a hash.) */ if (signature_size == 0) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_SIGN_HASH, alg); if (status != PSA_SUCCESS) { goto exit; } if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (input_is_message) { status = psa_driver_wrapper_sign_message( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_size, signature_length); } else { status = psa_driver_wrapper_sign_hash( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_size, signature_length); } exit: psa_wipe_tag_output_buffer(signature, status, signature_size, *signature_length); unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key, int input_is_message, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; status = psa_sign_verify_check_alg(input_is_message, alg); if (status != PSA_SUCCESS) { return status; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE : PSA_KEY_USAGE_VERIFY_HASH, alg); if (status != PSA_SUCCESS) { return status; } if (input_is_message) { status = psa_driver_wrapper_verify_message( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_length); } else { status = psa_driver_wrapper_verify_hash( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, signature, signature_length); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_sign_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (PSA_ALG_IS_SIGN_HASH(alg)) { size_t hash_length; uint8_t hash[PSA_HASH_MAX_SIZE]; status = psa_driver_wrapper_hash_compute( PSA_ALG_SIGN_GET_HASH(alg), input, input_length, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return status; } return psa_driver_wrapper_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); } return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_sign_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *signature_external, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); status = psa_sign_internal(key, 1, alg, input, input_length, signature, signature_size, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(signature_external, signature); return status; } psa_status_t psa_verify_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (PSA_ALG_IS_SIGN_HASH(alg)) { size_t hash_length; uint8_t hash[PSA_HASH_MAX_SIZE]; status = psa_driver_wrapper_hash_compute( PSA_ALG_SIGN_GET_HASH(alg), input, input_length, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return status; } return psa_driver_wrapper_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); } return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_verify_message(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); status = psa_verify_internal(key, 1, alg, input, input_length, signature, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(signature_external, signature); return status; } psa_status_t psa_sign_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_RSA_PSS(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) return mbedtls_psa_rsa_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { if (PSA_ALG_IS_ECDSA(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) return mbedtls_psa_ecdsa_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } (void) key_buffer; (void) key_buffer_size; (void) hash; (void) hash_length; (void) signature; (void) signature_size; (void) signature_length; return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length, uint8_t *signature_external, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(hash_external, hash); LOCAL_OUTPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); status = psa_sign_internal(key, 0, alg, hash, hash_length, signature, signature_size, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(hash_external, hash); LOCAL_OUTPUT_FREE(signature_external, signature); return status; } psa_status_t psa_verify_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_RSA_PSS(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) return mbedtls_psa_rsa_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) { if (PSA_ALG_IS_ECDSA(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) return mbedtls_psa_ecdsa_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { return PSA_ERROR_INVALID_ARGUMENT; } } (void) key_buffer; (void) key_buffer_size; (void) hash; (void) hash_length; (void) signature; (void) signature_length; return PSA_ERROR_NOT_SUPPORTED; } psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length, const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(hash_external, hash); LOCAL_INPUT_DECLARE(signature_external, signature); LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); status = psa_verify_internal(key, 0, alg, hash, hash_length, signature, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(hash_external, hash); LOCAL_INPUT_FREE(signature_external, signature); return status; } psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *salt_external, size_t salt_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(salt_external, salt); LOCAL_OUTPUT_DECLARE(output_external, output); (void) input; (void) input_length; (void) salt; (void) output; (void) output_size; *output_length = 0; if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { return status; } if (!(PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type) || PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type))) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_asymmetric_encrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, salt, salt_length, output, output_size, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(salt_external, salt); LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, const uint8_t *salt_external, size_t salt_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_DECLARE(salt_external, salt); LOCAL_OUTPUT_DECLARE(output_external, output); (void) input; (void) input_length; (void) salt; (void) output; (void) output_size; *output_length = 0; if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { return status; } if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_INPUT_ALLOC(salt_external, salt_length, salt); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_asymmetric_decrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, salt, salt_length, output, output_size, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(input_external, input); LOCAL_INPUT_FREE(salt_external, salt); LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Asymmetric interruptible cryptography */ /****************************************************************/ static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED; void psa_interruptible_set_max_ops(uint32_t max_ops) { psa_interruptible_max_ops = max_ops; } uint32_t psa_interruptible_get_max_ops(void) { return psa_interruptible_max_ops; } uint32_t psa_sign_hash_get_num_ops( const psa_sign_hash_interruptible_operation_t *operation) { return operation->num_ops; } uint32_t psa_verify_hash_get_num_ops( const psa_verify_hash_interruptible_operation_t *operation) { return operation->num_ops; } static psa_status_t psa_sign_hash_abort_internal( psa_sign_hash_interruptible_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_driver_wrapper_sign_hash_abort(operation); operation->id = 0; /* Do not clear either the error_occurred or num_ops elements here as they * only want to be cleared by the application calling abort, not by abort * being called at completion of an operation. */ return status; } psa_status_t psa_sign_hash_start( psa_sign_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(hash_external, hash); /* Check that start has not been previously called, or operation has not * previously errored. */ if (operation->id != 0 || operation->error_occurred) { return PSA_ERROR_BAD_STATE; } status = psa_sign_verify_check_alg(0, alg); if (status != PSA_SUCCESS) { operation->error_occurred = 1; return status; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_SIGN_HASH, alg); if (status != PSA_SUCCESS) { goto exit; } if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); /* Ensure ops count gets reset, in case of operation re-use. */ operation->num_ops = 0; status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr, slot->key.data, slot->key.bytes, alg, hash, hash_length); exit: if (status != PSA_SUCCESS) { operation->error_occurred = 1; psa_sign_hash_abort_internal(operation); } unlock_status = psa_unregister_read_under_mutex(slot); if (unlock_status != PSA_SUCCESS) { operation->error_occurred = 1; } LOCAL_INPUT_FREE(hash_external, hash); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_sign_hash_complete( psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature_external, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(signature_external, signature); *signature_length = 0; /* Check that start has been called first, and that operation has not * previously errored. */ if (operation->id == 0 || operation->error_occurred) { status = PSA_ERROR_BAD_STATE; goto exit; } /* Immediately reject a zero-length signature buffer. This guarantees that * signature must be a valid pointer. */ if (signature_size == 0) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature); status = psa_driver_wrapper_sign_hash_complete(operation, signature, signature_size, signature_length); /* Update ops count with work done. */ operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation); exit: if (signature != NULL) { psa_wipe_tag_output_buffer(signature, status, signature_size, *signature_length); } if (status != PSA_OPERATION_INCOMPLETE) { if (status != PSA_SUCCESS) { operation->error_occurred = 1; } psa_sign_hash_abort_internal(operation); } LOCAL_OUTPUT_FREE(signature_external, signature); return status; } psa_status_t psa_sign_hash_abort( psa_sign_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_sign_hash_abort_internal(operation); /* We clear the number of ops done here, so that it is not cleared when * the operation fails or succeeds, only on manual abort. */ operation->num_ops = 0; /* Likewise, failure state. */ operation->error_occurred = 0; return status; } static psa_status_t psa_verify_hash_abort_internal( psa_verify_hash_interruptible_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_driver_wrapper_verify_hash_abort(operation); operation->id = 0; /* Do not clear either the error_occurred or num_ops elements here as they * only want to be cleared by the application calling abort, not by abort * being called at completion of an operation. */ return status; } psa_status_t psa_verify_hash_start( psa_verify_hash_interruptible_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *hash_external, size_t hash_length, const uint8_t *signature_external, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(hash_external, hash); LOCAL_INPUT_DECLARE(signature_external, signature); /* Check that start has not been previously called, or operation has not * previously errored. */ if (operation->id != 0 || operation->error_occurred) { return PSA_ERROR_BAD_STATE; } status = psa_sign_verify_check_alg(0, alg); if (status != PSA_SUCCESS) { operation->error_occurred = 1; return status; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg); if (status != PSA_SUCCESS) { operation->error_occurred = 1; return status; } LOCAL_INPUT_ALLOC(hash_external, hash_length, hash); LOCAL_INPUT_ALLOC(signature_external, signature_length, signature); /* Ensure ops count gets reset, in case of operation re-use. */ operation->num_ops = 0; status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr, slot->key.data, slot->key.bytes, alg, hash, hash_length, signature, signature_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif if (status != PSA_SUCCESS) { operation->error_occurred = 1; psa_verify_hash_abort_internal(operation); } unlock_status = psa_unregister_read_under_mutex(slot); if (unlock_status != PSA_SUCCESS) { operation->error_occurred = 1; } LOCAL_INPUT_FREE(hash_external, hash); LOCAL_INPUT_FREE(signature_external, signature); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_verify_hash_complete( psa_verify_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Check that start has been called first, and that operation has not * previously errored. */ if (operation->id == 0 || operation->error_occurred) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_driver_wrapper_verify_hash_complete(operation); /* Update ops count with work done. */ operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops( operation); exit: if (status != PSA_OPERATION_INCOMPLETE) { if (status != PSA_SUCCESS) { operation->error_occurred = 1; } psa_verify_hash_abort_internal(operation); } return status; } psa_status_t psa_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_verify_hash_abort_internal(operation); /* We clear the number of ops done here, so that it is not cleared when * the operation fails or succeeds, only on manual abort. */ operation->num_ops = 0; /* Likewise, failure state. */ operation->error_occurred = 0; return status; } /****************************************************************/ /* Asymmetric interruptible cryptography internal */ /* implementations */ /****************************************************************/ void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) /* Internal implementation uses zero to indicate infinite number max ops, * therefore avoid this value, and set to minimum possible. */ if (max_ops == 0) { max_ops = 1; } mbedtls_ecp_set_max_ops(max_ops); #else (void) max_ops; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } uint32_t mbedtls_psa_sign_hash_get_num_ops( const mbedtls_psa_sign_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) return operation->num_ops; #else (void) operation; return 0; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } uint32_t mbedtls_psa_verify_hash_get_num_ops( const mbedtls_psa_verify_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) return operation->num_ops; #else (void) operation; return 0; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_sign_hash_start( mbedtls_psa_sign_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t required_hash_length; if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { return PSA_ERROR_NOT_SUPPORTED; } if (!PSA_ALG_IS_ECDSA(alg)) { return PSA_ERROR_NOT_SUPPORTED; } #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_restart_init(&operation->restart_ctx); /* Ensure num_ops is zero'ed in case of context re-use. */ operation->num_ops = 0; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &operation->ctx); if (status != PSA_SUCCESS) { return status; } operation->coordinate_bytes = PSA_BITS_TO_BYTES( operation->ctx->grp.nbits); psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg); operation->alg = alg; /* We only need to store the same length of hash as the private key size * here, it would be truncated by the internal implementation anyway. */ required_hash_length = (hash_length < operation->coordinate_bytes ? hash_length : operation->coordinate_bytes); if (required_hash_length > sizeof(operation->hash)) { /* Shouldn't happen, but better safe than sorry. */ return PSA_ERROR_CORRUPTION_DETECTED; } memcpy(operation->hash, hash, required_hash_length); operation->hash_length = required_hash_length; return PSA_SUCCESS; #else (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; (void) hash; (void) hash_length; (void) status; (void) required_hash_length; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_sign_hash_complete( mbedtls_psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi r; mbedtls_mpi s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); /* Ensure max_ops is set to the current value (or default). */ mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); if (signature_size < 2 * operation->coordinate_bytes) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) status = mbedtls_to_psa_error( mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp, &r, &s, &operation->ctx->d, operation->hash, operation->hash_length, operation->md_alg, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, &operation->restart_ctx)); #else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ status = PSA_ERROR_NOT_SUPPORTED; goto exit; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { status = mbedtls_to_psa_error( mbedtls_ecdsa_sign_restartable(&operation->ctx->grp, &r, &s, &operation->ctx->d, operation->hash, operation->hash_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, &operation->restart_ctx)); } /* Hide the fact that the restart context only holds a delta of number of * ops done during the last operation, not an absolute value. */ operation->num_ops += operation->restart_ctx.ecp.ops_done; if (status == PSA_SUCCESS) { status = mbedtls_to_psa_error( mbedtls_mpi_write_binary(&r, signature, operation->coordinate_bytes) ); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_mpi_write_binary(&s, signature + operation->coordinate_bytes, operation->coordinate_bytes) ); if (status != PSA_SUCCESS) { goto exit; } *signature_length = operation->coordinate_bytes * 2; status = PSA_SUCCESS; } exit: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); return status; #else (void) operation; (void) signature; (void) signature_size; (void) signature_length; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_sign_hash_abort( mbedtls_psa_sign_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) if (operation->ctx) { mbedtls_ecdsa_free(operation->ctx); mbedtls_free(operation->ctx); operation->ctx = NULL; } mbedtls_ecdsa_restart_free(&operation->restart_ctx); operation->num_ops = 0; return PSA_SUCCESS; #else (void) operation; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_verify_hash_start( mbedtls_psa_verify_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t coordinate_bytes = 0; size_t required_hash_length = 0; if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) { return PSA_ERROR_NOT_SUPPORTED; } if (!PSA_ALG_IS_ECDSA(alg)) { return PSA_ERROR_NOT_SUPPORTED; } #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecdsa_restart_init(&operation->restart_ctx); mbedtls_mpi_init(&operation->r); mbedtls_mpi_init(&operation->s); /* Ensure num_ops is zero'ed in case of context re-use. */ operation->num_ops = 0; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &operation->ctx); if (status != PSA_SUCCESS) { return status; } coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits); if (signature_length != 2 * coordinate_bytes) { return PSA_ERROR_INVALID_SIGNATURE; } status = mbedtls_to_psa_error( mbedtls_mpi_read_binary(&operation->r, signature, coordinate_bytes)); if (status != PSA_SUCCESS) { return status; } status = mbedtls_to_psa_error( mbedtls_mpi_read_binary(&operation->s, signature + coordinate_bytes, coordinate_bytes)); if (status != PSA_SUCCESS) { return status; } status = mbedtls_psa_ecp_load_public_part(operation->ctx); if (status != PSA_SUCCESS) { return status; } /* We only need to store the same length of hash as the private key size * here, it would be truncated by the internal implementation anyway. */ required_hash_length = (hash_length < coordinate_bytes ? hash_length : coordinate_bytes); if (required_hash_length > sizeof(operation->hash)) { /* Shouldn't happen, but better safe than sorry. */ return PSA_ERROR_CORRUPTION_DETECTED; } memcpy(operation->hash, hash, required_hash_length); operation->hash_length = required_hash_length; return PSA_SUCCESS; #else (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; (void) hash; (void) hash_length; (void) signature; (void) signature_length; (void) status; (void) coordinate_bytes; (void) required_hash_length; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_verify_hash_complete( mbedtls_psa_verify_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Ensure max_ops is set to the current value (or default). */ mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops()); status = mbedtls_to_psa_error( mbedtls_ecdsa_verify_restartable(&operation->ctx->grp, operation->hash, operation->hash_length, &operation->ctx->Q, &operation->r, &operation->s, &operation->restart_ctx)); /* Hide the fact that the restart context only holds a delta of number of * ops done during the last operation, not an absolute value. */ operation->num_ops += operation->restart_ctx.ecp.ops_done; return status; #else (void) operation; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } psa_status_t mbedtls_psa_verify_hash_abort( mbedtls_psa_verify_hash_interruptible_operation_t *operation) { #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \ defined(MBEDTLS_ECP_RESTARTABLE) if (operation->ctx) { mbedtls_ecdsa_free(operation->ctx); mbedtls_free(operation->ctx); operation->ctx = NULL; } mbedtls_ecdsa_restart_free(&operation->restart_ctx); operation->num_ops = 0; mbedtls_mpi_free(&operation->r); mbedtls_mpi_free(&operation->s); return PSA_SUCCESS; #else (void) operation; return PSA_ERROR_NOT_SUPPORTED; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) && * defined( MBEDTLS_ECP_RESTARTABLE ) */ } static psa_status_t psa_generate_random_internal(uint8_t *output, size_t output_size) { GUARD_MODULE_INITIALIZED; #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) psa_status_t status; size_t output_length = 0; status = mbedtls_psa_external_get_random(&global_data.rng, output, output_size, &output_length); if (status != PSA_SUCCESS) { return status; } /* Breaking up a request into smaller chunks is currently not supported * for the external RNG interface. */ if (output_length != output_size) { return PSA_ERROR_INSUFFICIENT_ENTROPY; } return PSA_SUCCESS; #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ while (output_size > 0) { int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; size_t request_size = (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? MBEDTLS_PSA_RANDOM_MAX_REQUEST : output_size); #if defined(MBEDTLS_CTR_DRBG_C) ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size); #elif defined(MBEDTLS_HMAC_DRBG_C) ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size); #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ if (ret != 0) { return mbedtls_to_psa_error(ret); } output_size -= request_size; output += request_size; } return PSA_SUCCESS; #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /****************************************************************/ /* Symmetric cryptography */ /****************************************************************/ static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, mbedtls_operation_t cipher_operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT); /* A context must be freshly initialized before it can be set up. */ if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg); if (status != PSA_SUCCESS) { goto exit; } /* Initialize the operation struct members, except for id. The id member * is used to indicate to psa_cipher_abort that there are resources to free, * so we only set it (in the driver wrapper) after resources have been * allocated/initialized. */ operation->iv_set = 0; if (alg == PSA_ALG_ECB_NO_PADDING) { operation->iv_required = 0; } else { operation->iv_required = 1; } operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); /* Try doing the operation through a driver before using software fallback. */ if (cipher_operation == MBEDTLS_ENCRYPT) { status = psa_driver_wrapper_cipher_encrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_cipher_decrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } exit: if (status != PSA_SUCCESS) { psa_cipher_abort(operation); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT); } psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT); } psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, uint8_t *iv_external, size_t iv_size, size_t *iv_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t default_iv_length = 0; LOCAL_OUTPUT_DECLARE(iv_external, iv); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_set || !operation->iv_required) { status = PSA_ERROR_BAD_STATE; goto exit; } default_iv_length = operation->default_iv_length; if (iv_size < default_iv_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { status = PSA_ERROR_GENERIC_ERROR; goto exit; } LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv); status = psa_generate_random_internal(iv, default_iv_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_cipher_set_iv(operation, iv, default_iv_length); exit: if (status == PSA_SUCCESS) { *iv_length = default_iv_length; operation->iv_set = 1; } else { *iv_length = 0; psa_cipher_abort(operation); if (iv != NULL) { mbedtls_platform_zeroize(iv, default_iv_length); } } LOCAL_OUTPUT_FREE(iv_external, iv); return status; } psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, const uint8_t *iv_external, size_t iv_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(iv_external, iv); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_set || !operation->iv_required) { status = PSA_ERROR_BAD_STATE; goto exit; } if (iv_length > PSA_CIPHER_IV_MAX_SIZE) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(iv_external, iv_length, iv); status = psa_driver_wrapper_cipher_set_iv(operation, iv, iv_length); exit: if (status == PSA_SUCCESS) { operation->iv_set = 1; } else { psa_cipher_abort(operation); } LOCAL_INPUT_FREE(iv_external, iv); return status; } psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_required && !operation->iv_set) { status = PSA_ERROR_BAD_STATE; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_update(operation, input, input_length, output, output_size, output_length); exit: if (status != PSA_SUCCESS) { psa_cipher_abort(operation); } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; LOCAL_OUTPUT_DECLARE(output_external, output); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->iv_required && !operation->iv_set) { status = PSA_ERROR_BAD_STATE; goto exit; } LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_finish(operation, output, output_size, output_length); exit: if (status == PSA_SUCCESS) { status = psa_cipher_abort(operation); } else { *output_length = 0; (void) psa_cipher_abort(operation); } LOCAL_OUTPUT_FREE(output_external, output); return status; } psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) { if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } psa_driver_wrapper_cipher_abort(operation); operation->id = 0; operation->iv_set = 0; operation->iv_required = 0; return PSA_SUCCESS; } psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; size_t default_iv_length = 0; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { goto exit; } default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg); if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) { status = PSA_ERROR_GENERIC_ERROR; goto exit; } if (default_iv_length > 0) { if (output_size < default_iv_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_generate_random_internal(local_iv, default_iv_length); if (status != PSA_SUCCESS) { goto exit; } } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_encrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, local_iv, default_iv_length, input, input_length, psa_crypto_buffer_offset(output, default_iv_length), output_size - default_iv_length, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); if (status == PSA_SUCCESS) { status = unlock_status; } if (status == PSA_SUCCESS) { if (default_iv_length > 0) { memcpy(output, local_iv, default_iv_length); } *output_length += default_iv_length; } else { *output_length = 0; } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); if (!PSA_ALG_IS_CIPHER(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { goto exit; } if (alg == PSA_ALG_CCM_STAR_NO_TAG && input_length < PSA_BLOCK_CIPHER_BLOCK_LENGTH(slot->attr.type)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } else if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_cipher_decrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, input, input_length, output, output_size, output_length); exit: unlock_status = psa_unregister_read_under_mutex(slot); if (status == PSA_SUCCESS) { status = unlock_status; } if (status != PSA_SUCCESS) { *output_length = 0; } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } /****************************************************************/ /* AEAD */ /****************************************************************/ /* Helper function to get the base algorithm from its variants. */ static psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg) { return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg); } /* Helper function to perform common nonce length checks. */ static psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg, size_t nonce_length) { psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg); switch (base_alg) { #if defined(PSA_WANT_ALG_GCM) case PSA_ALG_GCM: /* Not checking max nonce size here as GCM spec allows almost * arbitrarily large nonces. Please note that we do not generally * recommend the usage of nonces of greater length than * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter * size, which can then lead to collisions if you encrypt a very * large number of messages.*/ if (nonce_length != 0) { return PSA_SUCCESS; } break; #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CCM) case PSA_ALG_CCM: if (nonce_length >= 7 && nonce_length <= 13) { return PSA_SUCCESS; } break; #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) case PSA_ALG_CHACHA20_POLY1305: if (nonce_length == 12) { return PSA_SUCCESS; } else if (nonce_length == 8) { return PSA_ERROR_NOT_SUPPORTED; } break; #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ default: (void) nonce_length; return PSA_ERROR_NOT_SUPPORTED; } return PSA_ERROR_INVALID_ARGUMENT; } static psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg) { if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce_external, size_t nonce_length, const uint8_t *additional_data_external, size_t additional_data_length, const uint8_t *plaintext_external, size_t plaintext_length, uint8_t *ciphertext_external, size_t ciphertext_size, size_t *ciphertext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(nonce_external, nonce); LOCAL_INPUT_DECLARE(additional_data_external, additional_data); LOCAL_INPUT_DECLARE(plaintext_external, plaintext); LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); *ciphertext_length = 0; status = psa_aead_check_algorithm(alg); if (status != PSA_SUCCESS) { return status; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg); if (status != PSA_SUCCESS) { return status; } LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext); LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); status = psa_aead_check_nonce_length(alg, nonce_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_aead_encrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length); if (status != PSA_SUCCESS && ciphertext_size != 0) { memset(ciphertext, 0, ciphertext_size); } exit: LOCAL_INPUT_FREE(nonce_external, nonce); LOCAL_INPUT_FREE(additional_data_external, additional_data); LOCAL_INPUT_FREE(plaintext_external, plaintext); LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); psa_unregister_read_under_mutex(slot); return status; } psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, psa_algorithm_t alg, const uint8_t *nonce_external, size_t nonce_length, const uint8_t *additional_data_external, size_t additional_data_length, const uint8_t *ciphertext_external, size_t ciphertext_length, uint8_t *plaintext_external, size_t plaintext_size, size_t *plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(nonce_external, nonce); LOCAL_INPUT_DECLARE(additional_data_external, additional_data); LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext); LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); *plaintext_length = 0; status = psa_aead_check_algorithm(alg); if (status != PSA_SUCCESS) { return status; } status = psa_get_and_lock_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DECRYPT, alg); if (status != PSA_SUCCESS) { return status; } LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data); LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext); LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); status = psa_aead_check_nonce_length(alg, nonce_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_aead_decrypt( &slot->attr, slot->key.data, slot->key.bytes, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length); if (status != PSA_SUCCESS && plaintext_size != 0) { memset(plaintext, 0, plaintext_size); } exit: LOCAL_INPUT_FREE(nonce_external, nonce); LOCAL_INPUT_FREE(additional_data_external, additional_data); LOCAL_INPUT_FREE(ciphertext_external, ciphertext); LOCAL_OUTPUT_FREE(plaintext_external, plaintext); psa_unregister_read_under_mutex(slot); return status; } static psa_status_t psa_validate_tag_length(psa_algorithm_t alg) { const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { #if defined(PSA_WANT_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/ if (tag_len < 4 || tag_len > 16 || tag_len % 2) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */ if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): /* We only support the default tag length. */ if (tag_len != 16) { return PSA_ERROR_INVALID_ARGUMENT; } break; #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ default: (void) tag_len; return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } /* Set the key for a multipart authenticated operation. */ static psa_status_t psa_aead_setup(psa_aead_operation_t *operation, int is_encrypt, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; psa_key_usage_t key_usage = 0; status = psa_aead_check_algorithm(alg); if (status != PSA_SUCCESS) { goto exit; } if (operation->id != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->nonce_set || operation->lengths_set || operation->ad_started || operation->body_started) { status = PSA_ERROR_BAD_STATE; goto exit; } if (is_encrypt) { key_usage = PSA_KEY_USAGE_ENCRYPT; } else { key_usage = PSA_KEY_USAGE_DECRYPT; } status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage, alg); if (status != PSA_SUCCESS) { goto exit; } if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) { goto exit; } if (is_encrypt) { status = psa_driver_wrapper_aead_encrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } else { status = psa_driver_wrapper_aead_decrypt_setup(operation, &slot->attr, slot->key.data, slot->key.bytes, alg); } if (status != PSA_SUCCESS) { goto exit; } operation->key_type = psa_get_key_type(&slot->attr); exit: unlock_status = psa_unregister_read_under_mutex(slot); if (status == PSA_SUCCESS) { status = unlock_status; operation->alg = psa_aead_get_base_algorithm(alg); operation->is_encrypt = is_encrypt; } else { psa_aead_abort(operation); } return status; } /* Set the key for a multipart authenticated encryption operation. */ psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_aead_setup(operation, 1, key, alg); } /* Set the key for a multipart authenticated decryption operation. */ psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, mbedtls_svc_key_id_t key, psa_algorithm_t alg) { return psa_aead_setup(operation, 0, key, alg); } static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->nonce_set) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_aead_check_nonce_length(operation->alg, nonce_length); if (status != PSA_SUCCESS) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_driver_wrapper_aead_set_nonce(operation, nonce, nonce_length); exit: if (status == PSA_SUCCESS) { operation->nonce_set = 1; } else { psa_aead_abort(operation); } return status; } /* Generate a random nonce / IV for multipart AEAD operation */ psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, uint8_t *nonce_external, size_t nonce_size, size_t *nonce_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE]; size_t required_nonce_size = 0; LOCAL_OUTPUT_DECLARE(nonce_external, nonce); LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce); *nonce_length = 0; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->nonce_set || !operation->is_encrypt) { status = PSA_ERROR_BAD_STATE; goto exit; } /* For CCM, this size may not be correct according to the PSA * specification. The PSA Crypto 1.0.1 specification states: * * CCM encodes the plaintext length pLen in L octets, with L the smallest * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes. * * However this restriction that L has to be the smallest integer is not * applied in practice, and it is not implementable here since the * plaintext length may or may not be known at this time. */ required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type, operation->alg); if (nonce_size < required_nonce_size) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } status = psa_generate_random_internal(local_nonce, required_nonce_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_aead_set_nonce_internal(operation, local_nonce, required_nonce_size); exit: if (status == PSA_SUCCESS) { memcpy(nonce, local_nonce, required_nonce_size); *nonce_length = required_nonce_size; } else { psa_aead_abort(operation); } LOCAL_OUTPUT_FREE(nonce_external, nonce); return status; } /* Set the nonce for a multipart authenticated encryption or decryption operation.*/ psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, const uint8_t *nonce_external, size_t nonce_length) { psa_status_t status; LOCAL_INPUT_DECLARE(nonce_external, nonce); LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce); status = psa_aead_set_nonce_internal(operation, nonce, nonce_length); /* Exit label is only needed for buffer copying, prevent unused warnings. */ #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(nonce_external, nonce); return status; } /* Declare the lengths of the message and additional data for multipart AEAD. */ psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->lengths_set || operation->ad_started || operation->body_started) { status = PSA_ERROR_BAD_STATE; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_GCM) case PSA_ALG_GCM: /* Lengths can only be too large for GCM if size_t is bigger than 32 * bits. Without the guard this code will generate warnings on 32bit * builds. */ #if SIZE_MAX > UINT32_MAX if (((uint64_t) ad_length) >> 61 != 0 || ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } #endif break; #endif /* PSA_WANT_ALG_GCM */ #if defined(PSA_WANT_ALG_CCM) case PSA_ALG_CCM: if (ad_length > 0xFF00) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } break; #endif /* PSA_WANT_ALG_CCM */ #if defined(PSA_WANT_ALG_CHACHA20_POLY1305) case PSA_ALG_CHACHA20_POLY1305: /* No length restrictions for ChaChaPoly. */ break; #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ default: break; } status = psa_driver_wrapper_aead_set_lengths(operation, ad_length, plaintext_length); exit: if (status == PSA_SUCCESS) { operation->ad_remaining = ad_length; operation->body_remaining = plaintext_length; operation->lengths_set = 1; } else { psa_aead_abort(operation); } return status; } /* Pass additional data to an active multipart AEAD operation. */ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_INPUT_ALLOC(input_external, input_length, input); if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!operation->nonce_set || operation->body_started) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->lengths_set) { if (operation->ad_remaining < input_length) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } operation->ad_remaining -= input_length; } #if defined(PSA_WANT_ALG_CCM) else if (operation->alg == PSA_ALG_CCM) { status = PSA_ERROR_BAD_STATE; goto exit; } #endif /* PSA_WANT_ALG_CCM */ status = psa_driver_wrapper_aead_update_ad(operation, input, input_length); exit: if (status == PSA_SUCCESS) { operation->ad_started = 1; } else { psa_aead_abort(operation); } LOCAL_INPUT_FREE(input_external, input); return status; } /* Encrypt or decrypt a message fragment in an active multipart AEAD operation.*/ psa_status_t psa_aead_update(psa_aead_operation_t *operation, const uint8_t *input_external, size_t input_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(input_external, input); LOCAL_OUTPUT_DECLARE(output_external, output); LOCAL_INPUT_ALLOC(input_external, input_length, input); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); *output_length = 0; if (operation->id == 0) { status = PSA_ERROR_BAD_STATE; goto exit; } if (!operation->nonce_set) { status = PSA_ERROR_BAD_STATE; goto exit; } if (operation->lengths_set) { /* Additional data length was supplied, but not all the additional data was supplied.*/ if (operation->ad_remaining != 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Too much data provided. */ if (operation->body_remaining < input_length) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } operation->body_remaining -= input_length; } #if defined(PSA_WANT_ALG_CCM) else if (operation->alg == PSA_ALG_CCM) { status = PSA_ERROR_BAD_STATE; goto exit; } #endif /* PSA_WANT_ALG_CCM */ status = psa_driver_wrapper_aead_update(operation, input, input_length, output, output_size, output_length); exit: if (status == PSA_SUCCESS) { operation->body_started = 1; } else { psa_aead_abort(operation); } LOCAL_INPUT_FREE(input_external, input); LOCAL_OUTPUT_FREE(output_external, output); return status; } static psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation) { if (operation->id == 0 || !operation->nonce_set) { return PSA_ERROR_BAD_STATE; } if (operation->lengths_set && (operation->ad_remaining != 0 || operation->body_remaining != 0)) { return PSA_ERROR_INVALID_ARGUMENT; } return PSA_SUCCESS; } /* Finish encrypting a message in a multipart AEAD operation. */ psa_status_t psa_aead_finish(psa_aead_operation_t *operation, uint8_t *ciphertext_external, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag_external, size_t tag_size, size_t *tag_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext); LOCAL_OUTPUT_DECLARE(tag_external, tag); LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext); LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag); *ciphertext_length = 0; *tag_length = tag_size; status = psa_aead_final_checks(operation); if (status != PSA_SUCCESS) { goto exit; } if (!operation->is_encrypt) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_driver_wrapper_aead_finish(operation, ciphertext, ciphertext_size, ciphertext_length, tag, tag_size, tag_length); exit: /* In case the operation fails and the user fails to check for failure or * the zero tag size, make sure the tag is set to something implausible. * Even if the operation succeeds, make sure we clear the rest of the * buffer to prevent potential leakage of anything previously placed in * the same buffer.*/ psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length); psa_aead_abort(operation); LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext); LOCAL_OUTPUT_FREE(tag_external, tag); return status; } /* Finish authenticating and decrypting a message in a multipart AEAD operation.*/ psa_status_t psa_aead_verify(psa_aead_operation_t *operation, uint8_t *plaintext_external, size_t plaintext_size, size_t *plaintext_length, const uint8_t *tag_external, size_t tag_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext); LOCAL_INPUT_DECLARE(tag_external, tag); LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext); LOCAL_INPUT_ALLOC(tag_external, tag_length, tag); *plaintext_length = 0; status = psa_aead_final_checks(operation); if (status != PSA_SUCCESS) { goto exit; } if (operation->is_encrypt) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_driver_wrapper_aead_verify(operation, plaintext, plaintext_size, plaintext_length, tag, tag_length); exit: psa_aead_abort(operation); LOCAL_OUTPUT_FREE(plaintext_external, plaintext); LOCAL_INPUT_FREE(tag_external, tag); return status; } /* Abort an AEAD operation. */ psa_status_t psa_aead_abort(psa_aead_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->id == 0) { /* The object has (apparently) been initialized but it is not (yet) * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } status = psa_driver_wrapper_aead_abort(operation); memset(operation, 0, sizeof(*operation)); return status; } /****************************************************************/ /* Generators */ /****************************************************************/ #if defined(BUILTIN_ALG_ANY_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \ defined(PSA_HAVE_SOFT_PBKDF2) #define AT_LEAST_ONE_BUILTIN_KDF #endif /* At least one builtin KDF */ #if defined(BUILTIN_ALG_ANY_HKDF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_key_derivation_start_hmac( psa_mac_operation_t *operation, psa_algorithm_t hash_alg, const uint8_t *hmac_key, size_t hmac_key_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); operation->is_sign = 1; operation->mac_size = PSA_HASH_LENGTH(hash_alg); status = psa_driver_wrapper_mac_sign_setup(operation, &attributes, hmac_key, hmac_key_length, PSA_ALG_HMAC(hash_alg)); psa_reset_key_attributes(&attributes); return status; } #endif /* KDF algorithms reliant on HMAC */ #define HKDF_STATE_INIT 0 /* no input yet */ #define HKDF_STATE_STARTED 1 /* got salt */ #define HKDF_STATE_KEYED 2 /* got key */ #define HKDF_STATE_OUTPUT 3 /* output started */ static psa_algorithm_t psa_key_derivation_get_kdf_alg( const psa_key_derivation_operation_t *operation) { if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg); } else { return operation->alg; } } psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation) { psa_status_t status = PSA_SUCCESS; psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); if (kdf_alg == 0) { /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ } else #if defined(BUILTIN_ALG_ANY_HKDF) if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { mbedtls_free(operation->ctx.hkdf.info); status = psa_mac_abort(&operation->ctx.hkdf.hmac); } else #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { if (operation->ctx.tls12_prf.secret != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret, operation->ctx.tls12_prf.secret_length); } if (operation->ctx.tls12_prf.seed != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed, operation->ctx.tls12_prf.seed_length); } if (operation->ctx.tls12_prf.label != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label, operation->ctx.tls12_prf.label_length); } #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (operation->ctx.tls12_prf.other_secret != NULL) { mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret, operation->ctx.tls12_prf.other_secret_length); } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ status = PSA_SUCCESS; /* We leave the fields Ai and output_block to be erased safely by the * mbedtls_platform_zeroize() in the end of this function. */ } else #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data, sizeof(operation->ctx.tls12_ecjpake_to_pms.data)); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */ #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { if (operation->ctx.pbkdf2.salt != NULL) { mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt, operation->ctx.pbkdf2.salt_length); } status = PSA_SUCCESS; } else #endif /* defined(PSA_HAVE_SOFT_PBKDF2) */ { status = PSA_ERROR_BAD_STATE; } mbedtls_platform_zeroize(operation, sizeof(*operation)); return status; } psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, size_t *capacity) { if (operation->alg == 0) { /* This is a blank key derivation operation. */ return PSA_ERROR_BAD_STATE; } *capacity = operation->capacity; return PSA_SUCCESS; } psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation, size_t capacity) { if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } if (capacity > operation->capacity) { return PSA_ERROR_INVALID_ARGUMENT; } operation->capacity = capacity; return PSA_SUCCESS; } #if defined(BUILTIN_ALG_ANY_HKDF) /* Read some bytes from an HKDF-based operation. */ static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf, psa_algorithm_t kdf_alg, uint8_t *output, size_t output_length) { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); size_t hmac_output_length; psa_status_t status; #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff; #else const uint8_t last_block = 0xff; #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ if (hkdf->state < HKDF_STATE_KEYED || (!hkdf->info_set #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ )) { return PSA_ERROR_BAD_STATE; } hkdf->state = HKDF_STATE_OUTPUT; while (output_length != 0) { /* Copy what remains of the current block */ uint8_t n = hash_length - hkdf->offset_in_block; if (n > output_length) { n = (uint8_t) output_length; } memcpy(output, hkdf->output_block + hkdf->offset_in_block, n); output += n; output_length -= n; hkdf->offset_in_block += n; if (output_length == 0) { break; } /* We can't be wanting more output after the last block, otherwise * the capacity check in psa_key_derivation_output_bytes() would have * prevented this call. It could happen only if the operation * object was corrupted or if this function is called directly * inside the library. */ if (hkdf->block_number == last_block) { return PSA_ERROR_BAD_STATE; } /* We need a new block */ ++hkdf->block_number; hkdf->offset_in_block = 0; status = psa_key_derivation_start_hmac(&hkdf->hmac, hash_alg, hkdf->prk, hash_length); if (status != PSA_SUCCESS) { return status; } if (hkdf->block_number != 1) { status = psa_mac_update(&hkdf->hmac, hkdf->output_block, hash_length); if (status != PSA_SUCCESS) { return status; } } status = psa_mac_update(&hkdf->hmac, hkdf->info, hkdf->info_length); if (status != PSA_SUCCESS) { return status; } status = psa_mac_update(&hkdf->hmac, &hkdf->block_number, 1); if (status != PSA_SUCCESS) { return status; } status = psa_mac_sign_finish(&hkdf->hmac, hkdf->output_block, sizeof(hkdf->output_block), &hmac_output_length); if (status != PSA_SUCCESS) { return status; } } return PSA_SUCCESS; } #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( psa_tls12_prf_key_derivation_t *tls12_prf, psa_algorithm_t alg) { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg); uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT; size_t hmac_output_length; psa_status_t status, cleanup_status; /* We can't be wanting more output after block 0xff, otherwise * the capacity check in psa_key_derivation_output_bytes() would have * prevented this call. It could happen only if the operation * object was corrupted or if this function is called directly * inside the library. */ if (tls12_prf->block_number == 0xff) { return PSA_ERROR_CORRUPTION_DETECTED; } /* We need a new block */ ++tls12_prf->block_number; tls12_prf->left_in_block = hash_length; /* Recall the definition of the TLS-1.2-PRF from RFC 5246: * * PRF(secret, label, seed) = P_(secret, label + seed) * * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + * HMAC_hash(secret, A(2) + seed) + * HMAC_hash(secret, A(3) + seed) + ... * * A(0) = seed * A(i) = HMAC_hash(secret, A(i-1)) * * The `psa_tls12_prf_key_derivation` structure saves the block * `HMAC_hash(secret, A(i) + seed)` from which the output * is currently extracted as `output_block` and where i is * `block_number`. */ status = psa_key_derivation_start_hmac(&hmac, hash_alg, tls12_prf->secret, tls12_prf->secret_length); if (status != PSA_SUCCESS) { goto cleanup; } /* Calculate A(i) where i = tls12_prf->block_number. */ if (tls12_prf->block_number == 1) { /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads * the variable seed and in this instance means it in the context of the * P_hash function, where seed = label + seed.) */ status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); if (status != PSA_SUCCESS) { goto cleanup; } } else { /* A(i) = HMAC_hash(secret, A(i-1)) */ status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); if (status != PSA_SUCCESS) { goto cleanup; } } status = psa_mac_sign_finish(&hmac, tls12_prf->Ai, hash_length, &hmac_output_length); if (hmac_output_length != hash_length) { status = PSA_ERROR_CORRUPTION_DETECTED; } if (status != PSA_SUCCESS) { goto cleanup; } /* Calculate HMAC_hash(secret, A(i) + label + seed). */ status = psa_key_derivation_start_hmac(&hmac, hash_alg, tls12_prf->secret, tls12_prf->secret_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_sign_finish(&hmac, tls12_prf->output_block, hash_length, &hmac_output_length); if (status != PSA_SUCCESS) { goto cleanup; } cleanup: cleanup_status = psa_mac_abort(&hmac); if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) { status = cleanup_status; } return status; } static psa_status_t psa_key_derivation_tls12_prf_read( psa_tls12_prf_key_derivation_t *tls12_prf, psa_algorithm_t alg, uint8_t *output, size_t output_length) { psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg); uint8_t hash_length = PSA_HASH_LENGTH(hash_alg); psa_status_t status; uint8_t offset, length; switch (tls12_prf->state) { case PSA_TLS12_PRF_STATE_LABEL_SET: tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT; break; case PSA_TLS12_PRF_STATE_OUTPUT: break; default: return PSA_ERROR_BAD_STATE; } while (output_length != 0) { /* Check if we have fully processed the current block. */ if (tls12_prf->left_in_block == 0) { status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf, alg); if (status != PSA_SUCCESS) { return status; } continue; } if (tls12_prf->left_in_block > output_length) { length = (uint8_t) output_length; } else { length = tls12_prf->left_in_block; } offset = hash_length - tls12_prf->left_in_block; memcpy(output, tls12_prf->output_block + offset, length); output += length; output_length -= length; tls12_prf->left_in_block -= length; } return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read( psa_tls12_ecjpake_to_pms_t *ecjpake, uint8_t *output, size_t output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t output_size = 0; if (output_length != 32) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length, &output_size); if (status != PSA_SUCCESS) { return status; } if (output_size != output_length) { return PSA_ERROR_GENERIC_ERROR; } return PSA_SUCCESS; } #endif #if defined(PSA_HAVE_SOFT_PBKDF2) static psa_status_t psa_key_derivation_pbkdf2_generate_block( psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t prf_alg, uint8_t prf_output_length, psa_key_attributes_t *attributes) { psa_status_t status; psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT; size_t mac_output_length; uint8_t U_i[PSA_MAC_MAX_SIZE]; uint8_t *U_accumulator = pbkdf2->output_block; uint64_t i; uint8_t block_counter[4]; mac_operation.is_sign = 1; mac_operation.mac_size = prf_output_length; MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0); status = psa_driver_wrapper_mac_sign_setup(&mac_operation, attributes, pbkdf2->password, pbkdf2->password_length, prf_alg); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter)); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i), &mac_output_length); if (status != PSA_SUCCESS) { goto cleanup; } if (mac_output_length != prf_output_length) { status = PSA_ERROR_CORRUPTION_DETECTED; goto cleanup; } memcpy(U_accumulator, U_i, prf_output_length); for (i = 1; i < pbkdf2->input_cost; i++) { /* We are passing prf_output_length as mac_size because the driver * function directly sets mac_output_length as mac_size upon success. * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ status = psa_driver_wrapper_mac_compute(attributes, pbkdf2->password, pbkdf2->password_length, prf_alg, U_i, prf_output_length, U_i, prf_output_length, &mac_output_length); if (status != PSA_SUCCESS) { goto cleanup; } mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length); } cleanup: /* Zeroise buffers to clear sensitive data from memory. */ mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE); return status; } static psa_status_t psa_key_derivation_pbkdf2_read( psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t kdf_alg, uint8_t *output, size_t output_length) { psa_status_t status; psa_algorithm_t prf_alg; uint8_t prf_output_length; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length)); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg)); prf_output_length = PSA_HASH_LENGTH(prf_alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { prf_alg = PSA_ALG_CMAC; prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); } else { return PSA_ERROR_INVALID_ARGUMENT; } switch (pbkdf2->state) { case PSA_PBKDF2_STATE_PASSWORD_SET: /* Initially we need a new block so bytes_used is equal to block size*/ pbkdf2->bytes_used = prf_output_length; pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT; break; case PSA_PBKDF2_STATE_OUTPUT: break; default: return PSA_ERROR_BAD_STATE; } while (output_length != 0) { uint8_t n = prf_output_length - pbkdf2->bytes_used; if (n > output_length) { n = (uint8_t) output_length; } memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n); output += n; output_length -= n; pbkdf2->bytes_used += n; if (output_length == 0) { break; } /* We need a new block */ pbkdf2->bytes_used = 0; pbkdf2->block_number++; status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg, prf_output_length, &attributes); if (status != PSA_SUCCESS) { return status; } } return PSA_SUCCESS; } #endif /* PSA_HAVE_SOFT_PBKDF2 */ psa_status_t psa_key_derivation_output_bytes( psa_key_derivation_operation_t *operation, uint8_t *output_external, size_t output_length) { psa_status_t status; LOCAL_OUTPUT_DECLARE(output_external, output); psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); if (operation->alg == 0) { /* This is a blank operation. */ return PSA_ERROR_BAD_STATE; } if (output_length == 0 && operation->capacity == 0) { /* Edge case: this is a finished operation, and 0 bytes * were requested. The right error in this case could * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return * INSUFFICIENT_CAPACITY, which is right for a finished * operation, for consistency with the case when * output_length > 0. */ return PSA_ERROR_INSUFFICIENT_DATA; } LOCAL_OUTPUT_ALLOC(output_external, output_length, output); if (output_length > operation->capacity) { operation->capacity = 0; /* Go through the error path to wipe all confidential data now * that the operation object is useless. */ status = PSA_ERROR_INSUFFICIENT_DATA; goto exit; } operation->capacity -= output_length; #if defined(BUILTIN_ALG_ANY_HKDF) if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg, output, output_length); } else #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PRF(kdf_alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf, kdf_alg, output, output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { status = psa_key_derivation_tls12_ecjpake_to_pms_read( &operation->ctx.tls12_ecjpake_to_pms, output, output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg, output, output_length); } else #endif /* PSA_HAVE_SOFT_PBKDF2 */ { (void) kdf_alg; status = PSA_ERROR_BAD_STATE; LOCAL_OUTPUT_FREE(output_external, output); return status; } exit: if (status != PSA_SUCCESS) { /* Preserve the algorithm upon errors, but clear all sensitive state. * This allows us to differentiate between exhausted operations and * blank operations, so we can return PSA_ERROR_BAD_STATE on blank * operations. */ psa_algorithm_t alg = operation->alg; psa_key_derivation_abort(operation); operation->alg = alg; if (output != NULL) { memset(output, '!', output_length); } } LOCAL_OUTPUT_FREE(output_external, output); return status; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) static void psa_des_set_key_parity(uint8_t *data, size_t data_size) { if (data_size >= 8) { mbedtls_des_key_set_parity(data); } if (data_size >= 16) { mbedtls_des_key_set_parity(data + 8); } if (data_size >= 24) { mbedtls_des_key_set_parity(data + 16); } } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ /* * ECC keys on a Weierstrass elliptic curve require the generation * of a private key which is an integer * in the range [1, N - 1], where N is the boundary of the private key domain: * N is the prime p for Diffie-Hellman, or the order of the * curve’s base point for ECC. * * Let m be the bit size of N, such that 2^m > N >= 2^(m-1). * This function generates the private key using the following process: * * 1. Draw a byte string of length ceiling(m/8) bytes. * 2. If m is not a multiple of 8, set the most significant * (8 * ceiling(m/8) - m) bits of the first byte in the string to zero. * 3. Convert the string to integer k by decoding it as a big-endian byte string. * 4. If k > N - 2, discard the result and return to step 1. * 5. Output k + 1 as the private key. * * This method allows compliance to NIST standards, specifically the methods titled * Key-Pair Generation by Testing Candidates in the following publications: * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment * Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for * Diffie-Hellman keys. * * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature * Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys. * * Note: Function allocates memory for *data buffer, so given *data should be * always NULL. */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( psa_key_slot_t *slot, size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data ) { unsigned key_out_of_range = 1; mbedtls_mpi k; mbedtls_mpi diff_N_2; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t m; size_t m_bytes; mbedtls_mpi_init(&k); mbedtls_mpi_init(&diff_N_2); psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type); mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_from_psa(curve, bits); if (grp_id == MBEDTLS_ECP_DP_NONE) { ret = MBEDTLS_ERR_ASN1_INVALID_DATA; goto cleanup; } mbedtls_ecp_group ecp_group; mbedtls_ecp_group_init(&ecp_group); MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id)); /* N is the boundary of the private key domain (ecp_group.N). */ /* Let m be the bit size of N. */ m = ecp_group.nbits; m_bytes = PSA_BITS_TO_BYTES(m); /* Calculate N - 2 - it will be needed later. */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2)); /* Note: This function is always called with *data == NULL and it * allocates memory for the data buffer. */ *data = mbedtls_calloc(1, m_bytes); if (*data == NULL) { ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; goto cleanup; } while (key_out_of_range) { /* 1. Draw a byte string of length ceiling(m/8) bytes. */ if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) { goto cleanup; } /* 2. If m is not a multiple of 8 */ if (m % 8 != 0) { /* Set the most significant * (8 * ceiling(m/8) - m) bits of the first byte in * the string to zero. */ uint8_t clear_bit_mask = (1 << (m % 8)) - 1; (*data)[0] &= clear_bit_mask; } /* 3. Convert the string to integer k by decoding it as a * big-endian byte string. */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes)); /* 4. If k > N - 2, discard the result and return to step 1. * Result of comparison is returned. When it indicates error * then this function is called again. */ MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range)); } /* 5. Output k + 1 as the private key. */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes)); cleanup: if (ret != 0) { status = mbedtls_to_psa_error(ret); } if (status != PSA_SUCCESS) { mbedtls_free(*data); *data = NULL; } mbedtls_mpi_free(&k); mbedtls_mpi_free(&diff_N_2); return status; } /* ECC keys on a Montgomery elliptic curve draws a byte string whose length * is determined by the curve, and sets the mandatory bits accordingly. That is: * * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits): * draw a 32-byte string and process it as specified in * Elliptic Curves for Security [RFC7748] §5. * * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits): * draw a 56-byte string and process it as specified in [RFC7748] §5. * * Note: Function allocates memory for *data buffer, so given *data should be * always NULL. */ static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data ) { size_t output_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; switch (bits) { case 255: output_length = 32; break; case 448: output_length = 56; break; default: return PSA_ERROR_INVALID_ARGUMENT; break; } *data = mbedtls_calloc(1, output_length); if (*data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } status = psa_key_derivation_output_bytes(operation, *data, output_length); if (status != PSA_SUCCESS) { return status; } switch (bits) { case 255: (*data)[0] &= 248; (*data)[31] &= 127; (*data)[31] |= 64; break; case 448: (*data)[0] &= 252; (*data)[55] |= 128; break; default: return PSA_ERROR_CORRUPTION_DETECTED; break; } return status; } #else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper( psa_key_slot_t *slot, size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data) { (void) slot; (void) bits; (void) operation; (void) data; return PSA_ERROR_NOT_SUPPORTED; } static psa_status_t psa_generate_derived_ecc_key_montgomery_helper( size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data) { (void) bits; (void) operation; (void) data; return PSA_ERROR_NOT_SUPPORTED; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ #endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */ static psa_status_t psa_generate_derived_key_internal( psa_key_slot_t *slot, size_t bits, psa_key_derivation_operation_t *operation) { uint8_t *data = NULL; size_t bytes = PSA_BITS_TO_BYTES(bits); size_t storage_size = bytes; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) { return PSA_ERROR_INVALID_ARGUMENT; } #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) { psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type); if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) { /* Weierstrass elliptic curve */ status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data); if (status != PSA_SUCCESS) { goto exit; } } else { /* Montgomery elliptic curve */ status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data); if (status != PSA_SUCCESS) { goto exit; } } } else #endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */ if (key_type_is_raw_bytes(slot->attr.type)) { if (bits % 8 != 0) { return PSA_ERROR_INVALID_ARGUMENT; } data = mbedtls_calloc(1, bytes); if (data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } status = psa_key_derivation_output_bytes(operation, data, bytes); if (status != PSA_SUCCESS) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) if (slot->attr.type == PSA_KEY_TYPE_DES) { psa_des_set_key_parity(data, bytes); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */ } else { return PSA_ERROR_NOT_SUPPORTED; } slot->attr.bits = (psa_key_bits_t) bits; if (psa_key_lifetime_is_external(slot->attr.lifetime)) { status = psa_driver_wrapper_get_key_buffer_size(&slot->attr, &storage_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_allocate_buffer_to_slot(slot, storage_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_driver_wrapper_import_key(&slot->attr, data, bytes, slot->key.data, slot->key.bytes, &slot->key.bytes, &bits); if (bits != slot->attr.bits) { status = PSA_ERROR_INVALID_ARGUMENT; } exit: mbedtls_free(data); return status; } static const psa_key_production_parameters_t default_production_parameters = PSA_KEY_PRODUCTION_PARAMETERS_INIT; int psa_key_production_parameters_are_default( const psa_key_production_parameters_t *params, size_t params_data_length) { if (params->flags != 0) { return 0; } if (params_data_length != 0) { return 0; } return 1; } psa_status_t psa_key_derivation_output_key_ext( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; *key = MBEDTLS_SVC_KEY_ID_INIT; /* Reject any attempt to create a zero-length key so that we don't * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ if (psa_get_key_bits(attributes) == 0) { return PSA_ERROR_INVALID_ARGUMENT; } if (!psa_key_production_parameters_are_default(params, params_data_length)) { return PSA_ERROR_INVALID_ARGUMENT; } if (operation->alg == PSA_ALG_NONE) { return PSA_ERROR_BAD_STATE; } if (!operation->can_output_key) { return PSA_ERROR_NOT_PERMITTED; } status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes, &slot, &driver); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if (driver != NULL) { /* Deriving a key in a secure element is not implemented yet. */ status = PSA_ERROR_NOT_SUPPORTED; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if (status == PSA_SUCCESS) { status = psa_generate_derived_key_internal(slot, attributes->bits, operation); } if (status == PSA_SUCCESS) { status = psa_finish_key_creation(slot, driver, key); } if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } return status; } psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, psa_key_derivation_operation_t *operation, mbedtls_svc_key_id_t *key) { return psa_key_derivation_output_key_ext(attributes, operation, &default_production_parameters, 0, key); } /****************************************************************/ /* Key derivation */ /****************************************************************/ #if defined(AT_LEAST_ONE_BUILTIN_KDF) static int is_kdf_alg_supported(psa_algorithm_t kdf_alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) if (PSA_ALG_IS_HKDF(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { return 1; } #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { return 1; } #endif return 0; } static psa_status_t psa_hash_try_support(psa_algorithm_t alg) { psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; psa_status_t status = psa_hash_setup(&operation, alg); psa_hash_abort(&operation); return status; } static psa_status_t psa_key_derivation_set_maximum_capacity( psa_key_derivation_operation_t *operation, psa_algorithm_t kdf_alg) { #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256); return PSA_SUCCESS; } #endif #if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { #if (SIZE_MAX > UINT32_MAX) operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH( PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); #else operation->capacity = SIZE_MAX; #endif return PSA_SUCCESS; } #endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */ /* After this point, if kdf_alg is not valid then value of hash_alg may be * invalid or meaningless but it does not affect this function */ psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg); size_t hash_size = PSA_HASH_LENGTH(hash_alg); if (hash_size == 0) { return PSA_ERROR_NOT_SUPPORTED; } /* Make sure that hash_alg is a supported hash algorithm. Otherwise * we might fail later, which is somewhat unfriendly and potentially * risk-prone. */ psa_status_t status = psa_hash_try_support(hash_alg); if (status != PSA_SUCCESS) { return status; } #if defined(PSA_WANT_ALG_HKDF) if (PSA_ALG_IS_HKDF(kdf_alg)) { operation->capacity = 255 * hash_size; } else #endif #if defined(PSA_WANT_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { operation->capacity = hash_size; } else #endif #if defined(PSA_WANT_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { operation->capacity = 255 * hash_size; } else #endif #if defined(PSA_WANT_ALG_TLS12_PRF) if (PSA_ALG_IS_TLS12_PRF(kdf_alg) && (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { operation->capacity = SIZE_MAX; } else #endif #if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) && (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) { /* Master Secret is always 48 bytes * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */ operation->capacity = 48U; } else #endif #if defined(PSA_WANT_ALG_PBKDF2_HMAC) if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { #if (SIZE_MAX > UINT32_MAX) operation->capacity = UINT32_MAX * hash_size; #else operation->capacity = SIZE_MAX; #endif } else #endif /* PSA_WANT_ALG_PBKDF2_HMAC */ { (void) hash_size; status = PSA_ERROR_NOT_SUPPORTED; } return status; } static psa_status_t psa_key_derivation_setup_kdf( psa_key_derivation_operation_t *operation, psa_algorithm_t kdf_alg) { /* Make sure that operation->ctx is properly zero-initialised. (Macro * initialisers for this union leave some bytes unspecified.) */ memset(&operation->ctx, 0, sizeof(operation->ctx)); /* Make sure that kdf_alg is a supported key derivation algorithm. */ if (!is_kdf_alg_supported(kdf_alg)) { return PSA_ERROR_NOT_SUPPORTED; } psa_status_t status = psa_key_derivation_set_maximum_capacity(operation, kdf_alg); return status; } static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg) { #if defined(PSA_WANT_ALG_ECDH) if (alg == PSA_ALG_ECDH) { return PSA_SUCCESS; } #endif #if defined(PSA_WANT_ALG_FFDH) if (alg == PSA_ALG_FFDH) { return PSA_SUCCESS; } #endif (void) alg; return PSA_ERROR_NOT_SUPPORTED; } static int psa_key_derivation_allows_free_form_secret_input( psa_algorithm_t kdf_alg) { #if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { return 0; } #endif (void) kdf_alg; return 1; } #endif /* AT_LEAST_ONE_BUILTIN_KDF */ psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, psa_algorithm_t alg) { psa_status_t status; if (operation->alg != 0) { return PSA_ERROR_BAD_STATE; } if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) { #if defined(AT_LEAST_ONE_BUILTIN_KDF) psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg); psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg); status = psa_key_agreement_try_support(ka_alg); if (status != PSA_SUCCESS) { return status; } if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_key_derivation_setup_kdf(operation, kdf_alg); #else return PSA_ERROR_NOT_SUPPORTED; #endif /* AT_LEAST_ONE_BUILTIN_KDF */ } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) { #if defined(AT_LEAST_ONE_BUILTIN_KDF) status = psa_key_derivation_setup_kdf(operation, alg); #else return PSA_ERROR_NOT_SUPPORTED; #endif /* AT_LEAST_ONE_BUILTIN_KDF */ } else { return PSA_ERROR_INVALID_ARGUMENT; } if (status == PSA_SUCCESS) { operation->alg = alg; } return status; } #if defined(BUILTIN_ALG_ANY_HKDF) static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf, psa_algorithm_t kdf_alg, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); psa_status_t status; switch (step) { case PSA_KEY_DERIVATION_INPUT_SALT: #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ if (hkdf->state != HKDF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } else { status = psa_key_derivation_start_hmac(&hkdf->hmac, hash_alg, data, data_length); if (status != PSA_SUCCESS) { return status; } hkdf->state = HKDF_STATE_STARTED; return PSA_SUCCESS; } case PSA_KEY_DERIVATION_INPUT_SECRET: #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { /* We shouldn't be in different state as HKDF_EXPAND only allows * two inputs: SECRET (this case) and INFO which does not modify * the state. It could happen only if the hkdf * object was corrupted. */ if (hkdf->state != HKDF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } /* Allow only input that fits expected prk size */ if (data_length != PSA_HASH_LENGTH(hash_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } memcpy(hkdf->prk, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */ { /* HKDF: If no salt was provided, use an empty salt. * HKDF-EXTRACT: salt is mandatory. */ if (hkdf->state == HKDF_STATE_INIT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { return PSA_ERROR_BAD_STATE; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ status = psa_key_derivation_start_hmac(&hkdf->hmac, hash_alg, NULL, 0); if (status != PSA_SUCCESS) { return status; } hkdf->state = HKDF_STATE_STARTED; } if (hkdf->state != HKDF_STATE_STARTED) { return PSA_ERROR_BAD_STATE; } status = psa_mac_update(&hkdf->hmac, data, data_length); if (status != PSA_SUCCESS) { return status; } status = psa_mac_sign_finish(&hkdf->hmac, hkdf->prk, sizeof(hkdf->prk), &data_length); if (status != PSA_SUCCESS) { return status; } } hkdf->state = HKDF_STATE_KEYED; hkdf->block_number = 0; #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { /* The only block of output is the PRK. */ memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg)); hkdf->offset_in_block = 0; } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ { /* Block 0 is empty, and the next block will be * generated by psa_key_derivation_hkdf_read(). */ hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg); } return PSA_SUCCESS; case PSA_KEY_DERIVATION_INPUT_INFO: #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) { return PSA_ERROR_INVALID_ARGUMENT; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND) if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) && hkdf->state == HKDF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */ if (hkdf->state == HKDF_STATE_OUTPUT) { return PSA_ERROR_BAD_STATE; } if (hkdf->info_set) { return PSA_ERROR_BAD_STATE; } hkdf->info_length = data_length; if (data_length != 0) { hkdf->info = mbedtls_calloc(1, data_length); if (hkdf->info == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(hkdf->info, data, data_length); } hkdf->info_set = 1; return PSA_SUCCESS; default: return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_INIT) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->seed = mbedtls_calloc(1, data_length); if (prf->seed == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->seed, data, data_length); prf->seed_length = data_length; } prf->state = PSA_TLS12_PRF_STATE_SEED_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET && prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->secret = mbedtls_calloc(1, data_length); if (prf->secret == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->secret, data, data_length); prf->secret_length = data_length; } prf->state = PSA_TLS12_PRF_STATE_KEY_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->label = mbedtls_calloc(1, data_length); if (prf->label == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->label, data, data_length); prf->label_length = data_length; } prf->state = PSA_TLS12_PRF_STATE_LABEL_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SEED: return psa_tls12_prf_set_seed(prf, data, data_length); case PSA_KEY_DERIVATION_INPUT_SECRET: return psa_tls12_prf_set_key(prf, data, data_length); case PSA_KEY_DERIVATION_INPUT_LABEL: return psa_tls12_prf_set_label(prf, data, data_length); default: return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) static psa_status_t psa_tls12_prf_psk_to_ms_set_key( psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { psa_status_t status; const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ? 4 + data_length + prf->other_secret_length : 4 + 2 * data_length); if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) { return PSA_ERROR_INVALID_ARGUMENT; } uint8_t *pms = mbedtls_calloc(1, pms_len); if (pms == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } uint8_t *cur = pms; /* pure-PSK: * Quoting RFC 4279, Section 2: * * The premaster secret is formed as follows: if the PSK is N octets * long, concatenate a uint16 with the value N, N zero octets, a second * uint16 with the value N, and the PSK itself. * * mixed-PSK: * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as * follows: concatenate a uint16 with the length of the other secret, * the other secret itself, uint16 with the length of PSK, and the * PSK itself. * For details please check: * - RFC 4279, Section 4 for the definition of RSA-PSK, * - RFC 4279, Section 3 for the definition of DHE-PSK, * - RFC 5489 for the definition of ECDHE-PSK. */ if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) { *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length); *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length); if (prf->other_secret_length != 0) { memcpy(cur, prf->other_secret, prf->other_secret_length); mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length); cur += prf->other_secret_length; } } else { *cur++ = MBEDTLS_BYTE_1(data_length); *cur++ = MBEDTLS_BYTE_0(data_length); memset(cur, 0, data_length); cur += data_length; } *cur++ = MBEDTLS_BYTE_1(data_length); *cur++ = MBEDTLS_BYTE_0(data_length); memcpy(cur, data, data_length); cur += data_length; status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms)); mbedtls_zeroize_and_free(pms, pms_len); return status; } static psa_status_t psa_tls12_prf_psk_to_ms_set_other_key( psa_tls12_prf_key_derivation_t *prf, const uint8_t *data, size_t data_length) { if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) { return PSA_ERROR_BAD_STATE; } if (data_length != 0) { prf->other_secret = mbedtls_calloc(1, data_length); if (prf->other_secret == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(prf->other_secret, data, data_length); prf->other_secret_length = data_length; } else { prf->other_secret_length = 0; } prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET; return PSA_SUCCESS; } static psa_status_t psa_tls12_prf_psk_to_ms_input( psa_tls12_prf_key_derivation_t *prf, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SECRET: return psa_tls12_prf_psk_to_ms_set_key(prf, data, data_length); break; case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: return psa_tls12_prf_psk_to_ms_set_other_key(prf, data, data_length); break; default: return psa_tls12_prf_input(prf, step, data, data_length); break; } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) static psa_status_t psa_tls12_ecjpake_to_pms_input( psa_tls12_ecjpake_to_pms_t *ecjpake, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE || step != PSA_KEY_DERIVATION_INPUT_SECRET) { return PSA_ERROR_INVALID_ARGUMENT; } /* Check if the passed point is in an uncompressed form */ if (data[0] != 0x04) { return PSA_ERROR_INVALID_ARGUMENT; } /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */ memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_HAVE_SOFT_PBKDF2) static psa_status_t psa_pbkdf2_set_input_cost( psa_pbkdf2_key_derivation_t *pbkdf2, psa_key_derivation_step_t step, uint64_t data) { if (step != PSA_KEY_DERIVATION_INPUT_COST) { return PSA_ERROR_INVALID_ARGUMENT; } if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) { return PSA_ERROR_BAD_STATE; } if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) { return PSA_ERROR_NOT_SUPPORTED; } if (data == 0) { return PSA_ERROR_INVALID_ARGUMENT; } pbkdf2->input_cost = data; pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET; return PSA_SUCCESS; } static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2, const uint8_t *data, size_t data_length) { if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) { pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET; } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) { /* Appending to existing salt. No state change. */ } else { return PSA_ERROR_BAD_STATE; } if (data_length == 0) { /* Appending an empty string, nothing to do. */ } else { uint8_t *next_salt; next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length); if (next_salt == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } if (pbkdf2->salt_length != 0) { memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length); } memcpy(next_salt + pbkdf2->salt_length, data, data_length); pbkdf2->salt_length += data_length; mbedtls_free(pbkdf2->salt); pbkdf2->salt = next_salt; } return PSA_SUCCESS; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg, const uint8_t *input, size_t input_len, uint8_t *output, size_t *output_len) { psa_status_t status = PSA_SUCCESS; if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) { return psa_hash_compute(hash_alg, input, input_len, output, PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len); } else if (input_len > 0) { memcpy(output, input, input_len); } *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) static psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input, size_t input_len, uint8_t *output, size_t *output_len) { psa_status_t status = PSA_SUCCESS; if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t zeros[16] = { 0 }; psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros))); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as * mac_size as the driver function sets mac_output_length = mac_size * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */ status = psa_driver_wrapper_mac_compute(&attributes, zeros, sizeof(zeros), PSA_ALG_CMAC, input, input_len, output, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC), output_len); } else { memcpy(output, input, input_len); *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t kdf_alg, const uint8_t *data, size_t data_length) { psa_status_t status = PSA_SUCCESS; if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) { return PSA_ERROR_BAD_STATE; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC) if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) { psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg); status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length, pbkdf2->password, &pbkdf2->password_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128) if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) { status = psa_pbkdf2_cmac_set_password(data, data_length, pbkdf2->password, &pbkdf2->password_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */ { return PSA_ERROR_INVALID_ARGUMENT; } pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET; return status; } static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2, psa_algorithm_t kdf_alg, psa_key_derivation_step_t step, const uint8_t *data, size_t data_length) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SALT: return psa_pbkdf2_set_salt(pbkdf2, data, data_length); case PSA_KEY_DERIVATION_INPUT_PASSWORD: return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length); default: return PSA_ERROR_INVALID_ARGUMENT; } } #endif /* PSA_HAVE_SOFT_PBKDF2 */ /** Check whether the given key type is acceptable for the given * input step of a key derivation. * * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. * Both secret and non-secret inputs can alternatively have the type * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning * that the input was passed as a buffer rather than via a key object. */ static int psa_key_derivation_check_input_type( psa_key_derivation_step_t step, psa_key_type_t key_type) { switch (step) { case PSA_KEY_DERIVATION_INPUT_SECRET: if (key_type == PSA_KEY_TYPE_DERIVE) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET: if (key_type == PSA_KEY_TYPE_DERIVE) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; case PSA_KEY_DERIVATION_INPUT_LABEL: case PSA_KEY_DERIVATION_INPUT_SALT: case PSA_KEY_DERIVATION_INPUT_INFO: case PSA_KEY_DERIVATION_INPUT_SEED: if (key_type == PSA_KEY_TYPE_RAW_DATA) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; case PSA_KEY_DERIVATION_INPUT_PASSWORD: if (key_type == PSA_KEY_TYPE_PASSWORD) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_DERIVE) { return PSA_SUCCESS; } if (key_type == PSA_KEY_TYPE_NONE) { return PSA_SUCCESS; } break; } return PSA_ERROR_INVALID_ARGUMENT; } static psa_status_t psa_key_derivation_input_internal( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, psa_key_type_t key_type, const uint8_t *data, size_t data_length) { psa_status_t status; psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); status = psa_key_derivation_check_input_type(step, key_type); if (status != PSA_SUCCESS) { goto exit; } #if defined(BUILTIN_ALG_ANY_HKDF) if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) { status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg, step, data, data_length); } else #endif /* BUILTIN_ALG_ANY_HKDF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) { status = psa_tls12_prf_input(&operation->ctx.tls12_prf, step, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) { status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf, step, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { status = psa_tls12_ecjpake_to_pms_input( &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */ #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg, step, data, data_length); } else #endif /* PSA_HAVE_SOFT_PBKDF2 */ { /* This can't happen unless the operation object was not initialized */ (void) data; (void) data_length; (void) kdf_alg; return PSA_ERROR_BAD_STATE; } exit: if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } return status; } static psa_status_t psa_key_derivation_input_integer_internal( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, uint64_t value) { psa_status_t status; psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation); #if defined(PSA_HAVE_SOFT_PBKDF2) if (PSA_ALG_IS_PBKDF2(kdf_alg)) { status = psa_pbkdf2_set_input_cost( &operation->ctx.pbkdf2, step, value); } else #endif /* PSA_HAVE_SOFT_PBKDF2 */ { (void) step; (void) value; (void) kdf_alg; status = PSA_ERROR_INVALID_ARGUMENT; } if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } return status; } psa_status_t psa_key_derivation_input_bytes( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, const uint8_t *data_external, size_t data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(data_external, data); LOCAL_INPUT_ALLOC(data_external, data_length, data); status = psa_key_derivation_input_internal(operation, step, PSA_KEY_TYPE_NONE, data, data_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_INPUT_FREE(data_external, data); return status; } psa_status_t psa_key_derivation_input_integer( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, uint64_t value) { return psa_key_derivation_input_integer_internal(operation, step, value); } psa_status_t psa_key_derivation_input_key( psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t key) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; status = psa_get_and_lock_transparent_key_slot_with_policy( key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); return status; } /* Passing a key object as a SECRET or PASSWORD input unlocks the * permission to output to a key object. */ if (step == PSA_KEY_DERIVATION_INPUT_SECRET || step == PSA_KEY_DERIVATION_INPUT_PASSWORD) { operation->can_output_key = 1; } status = psa_key_derivation_input_internal(operation, step, slot->attr.type, slot->key.data, slot->key.bytes); unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Key agreement */ /****************************************************************/ psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) case PSA_ALG_ECDH: return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length); #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) case PSA_ALG_FFDH: return mbedtls_psa_ffdh_key_agreement(attributes, peer_key, peer_key_length, key_buffer, key_buffer_size, shared_secret, shared_secret_size, shared_secret_length); #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ default: (void) attributes; (void) key_buffer; (void) key_buffer_size; (void) peer_key; (void) peer_key_length; (void) shared_secret; (void) shared_secret_size; (void) shared_secret_length; return PSA_ERROR_NOT_SUPPORTED; } } /** Internal function for raw key agreement * Calls the driver wrapper which will hand off key agreement task * to the driver's implementation if a driver is present. * Fallback specified in the driver wrapper is built-in raw key agreement * (psa_key_agreement_raw_builtin). */ static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg, psa_key_slot_t *private_key, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { return PSA_ERROR_NOT_SUPPORTED; } return psa_driver_wrapper_key_agreement(&private_key->attr, private_key->key.data, private_key->key.bytes, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length); } /* Note that if this function fails, you must call psa_key_derivation_abort() * to potentially free embedded data structures and wipe confidential data. */ static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, psa_key_slot_t *private_key, const uint8_t *peer_key, size_t peer_key_length) { psa_status_t status; uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 }; size_t shared_secret_length = 0; psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg); /* Step 1: run the secret agreement algorithm to generate the shared * secret. */ status = psa_key_agreement_raw_internal(ka_alg, private_key, peer_key, peer_key_length, shared_secret, sizeof(shared_secret), &shared_secret_length); if (status != PSA_SUCCESS) { goto exit; } /* Step 2: set up the key derivation to generate key material from * the shared secret. A shared secret is permitted wherever a key * of type DERIVE is permitted. */ status = psa_key_derivation_input_internal(operation, step, PSA_KEY_TYPE_DERIVE, shared_secret, shared_secret_length); exit: mbedtls_platform_zeroize(shared_secret, shared_secret_length); return status; } psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation, psa_key_derivation_step_t step, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key_external, size_t peer_key_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; LOCAL_INPUT_DECLARE(peer_key_external, peer_key); if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_get_and_lock_transparent_key_slot_with_policy( private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); if (status != PSA_SUCCESS) { return status; } LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); status = psa_key_agreement_internal(operation, step, slot, peer_key, peer_key_length); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif if (status != PSA_SUCCESS) { psa_key_derivation_abort(operation); } else { /* If a private key has been added as SECRET, we allow the derived * key material to be used as a key in PSA Crypto. */ if (step == PSA_KEY_DERIVATION_INPUT_SECRET) { operation->can_output_key = 1; } } unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(peer_key_external, peer_key); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, mbedtls_svc_key_id_t private_key, const uint8_t *peer_key_external, size_t peer_key_length, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; size_t expected_length; LOCAL_INPUT_DECLARE(peer_key_external, peer_key); LOCAL_OUTPUT_DECLARE(output_external, output); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } status = psa_get_and_lock_transparent_key_slot_with_policy( private_key, &slot, PSA_KEY_USAGE_DERIVE, alg); if (status != PSA_SUCCESS) { goto exit; } /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound * for the output size. The PSA specification only guarantees that this * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...), * but it might be nice to allow smaller buffers if the output fits. * At the time of writing this comment, with only ECDH implemented, * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot. * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily * be exact for it as well. */ expected_length = PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits); if (output_size < expected_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key); status = psa_key_agreement_raw_internal(alg, slot, peer_key, peer_key_length, output, output_size, output_length); exit: /* Check for successful allocation of output, * with an unsuccessful status. */ if (output != NULL && status != PSA_SUCCESS) { /* If an error happens and is not handled properly, the output * may be used as a key to protect sensitive data. Arrange for such * a key to be random, which is likely to result in decryption or * verification errors. This is better than filling the buffer with * some constant data such as zeros, which would result in the data * being protected with a reproducible, easily knowable key. */ psa_generate_random_internal(output, output_size); *output_length = output_size; } if (output == NULL) { /* output allocation failed. */ *output_length = 0; } unlock_status = psa_unregister_read_under_mutex(slot); LOCAL_INPUT_FREE(peer_key_external, peer_key); LOCAL_OUTPUT_FREE(output_external, output); return (status == PSA_SUCCESS) ? unlock_status : status; } /****************************************************************/ /* Random generation */ /****************************************************************/ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) #include "entropy_poll.h" #endif /** Initialize the PSA random generator. * * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling * this function if mutexes are enabled. */ static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng) { #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) memset(rng, 0, sizeof(*rng)); #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ /* Set default configuration if * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ if (rng->entropy_init == NULL) { rng->entropy_init = mbedtls_entropy_init; } if (rng->entropy_free == NULL) { rng->entropy_free = mbedtls_entropy_free; } rng->entropy_init(&rng->entropy); #if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) /* The PSA entropy injection feature depends on using NV seed as an entropy * source. Add NV seed as an entropy source for PSA entropy injection. */ mbedtls_entropy_add_source(&rng->entropy, mbedtls_nv_seed_poll, NULL, MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG); #endif mbedtls_psa_drbg_init(&rng->drbg); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /** Deinitialize the PSA random generator. * * Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling * this function if mutexes are enabled. */ static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng) { #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) memset(rng, 0, sizeof(*rng)); #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ mbedtls_psa_drbg_free(&rng->drbg); rng->entropy_free(&rng->entropy); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /** Seed the PSA random generator. */ static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng) { #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /* Do nothing: the external RNG seeds itself. */ (void) rng; return PSA_SUCCESS; #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ const unsigned char drbg_seed[] = "PSA"; int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy, drbg_seed, sizeof(drbg_seed) - 1); return mbedtls_to_psa_error(ret); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } psa_status_t psa_generate_random(uint8_t *output_external, size_t output_size) { psa_status_t status; LOCAL_OUTPUT_DECLARE(output_external, output); LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_generate_random_internal(output, output_size); #if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) exit: #endif LOCAL_OUTPUT_FREE(output_external, output); return status; } #if defined(MBEDTLS_PSA_INJECT_ENTROPY) psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size) { if (psa_get_initialized()) { return PSA_ERROR_NOT_PERMITTED; } if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) || (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) || (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) { return PSA_ERROR_INVALID_ARGUMENT; } return mbedtls_psa_storage_inject_entropy(seed, seed_size); } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ /** Validate the key type and size for key generation * * \param type The key type * \param bits The number of bits of the key * * \retval #PSA_SUCCESS * The key type and size are valid. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size in bits of the key is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The type and/or the size in bits of the key or the combination of * the two is not supported. */ static psa_status_t psa_validate_key_type_and_size_for_key_generation( psa_key_type_t type, size_t bits) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (key_type_is_raw_bytes(type)) { status = psa_validate_unstructured_key_bit_size(type, bits); if (status != PSA_SUCCESS) { return status; } } else #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { return PSA_ERROR_NOT_SUPPORTED; } if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) { return PSA_ERROR_NOT_SUPPORTED; } /* Accept only byte-aligned keys, for the same reasons as * in psa_import_rsa_key(). */ if (bits % 8 != 0) { return PSA_ERROR_NOT_SUPPORTED; } } else #endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ #if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { /* To avoid empty block, return successfully here. */ return PSA_SUCCESS; } else #endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ #if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { if (psa_is_dh_key_size_valid(bits) == 0) { return PSA_ERROR_NOT_SUPPORTED; } } else #endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ { return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } psa_status_t psa_generate_key_internal( const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->type; /* Only used for RSA */ (void) params; (void) params_data_length; if (key_type_is_raw_bytes(type)) { status = psa_generate_random_internal(key_buffer, key_buffer_size); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) if (type == PSA_KEY_TYPE_DES) { psa_des_set_key_parity(key_buffer, key_buffer_size); } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ } else #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { return mbedtls_psa_rsa_generate_key(attributes, params, params_data_length, key_buffer, key_buffer_size, key_buffer_length); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { return mbedtls_psa_ecp_generate_key(attributes, key_buffer, key_buffer_size, key_buffer_length); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) { return mbedtls_psa_ffdh_generate_key(attributes, key_buffer, key_buffer_size, key_buffer_length); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */ { (void) key_buffer_length; return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, mbedtls_svc_key_id_t *key) { psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; size_t key_buffer_size; *key = MBEDTLS_SVC_KEY_ID_INIT; /* Reject any attempt to create a zero-length key so that we don't * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ if (psa_get_key_bits(attributes) == 0) { return PSA_ERROR_INVALID_ARGUMENT; } /* Reject any attempt to create a public key. */ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) { return PSA_ERROR_INVALID_ARGUMENT; } #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { if (params->flags != 0) { return PSA_ERROR_INVALID_ARGUMENT; } } else #endif if (!psa_key_production_parameters_are_default(params, params_data_length)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes, &slot, &driver); if (status != PSA_SUCCESS) { goto exit; } /* In the case of a transparent key or an opaque key stored in local * storage ( thus not in the case of generating a key in a secure element * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a * buffer to hold the generated key material. */ if (slot->key.data == NULL) { if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) == PSA_KEY_LOCATION_LOCAL_STORAGE) { status = psa_validate_key_type_and_size_for_key_generation( attributes->type, attributes->bits); if (status != PSA_SUCCESS) { goto exit; } key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( attributes->type, attributes->bits); } else { status = psa_driver_wrapper_get_key_buffer_size( attributes, &key_buffer_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_allocate_buffer_to_slot(slot, key_buffer_size); if (status != PSA_SUCCESS) { goto exit; } } status = psa_driver_wrapper_generate_key(attributes, params, params_data_length, slot->key.data, slot->key.bytes, &slot->key.bytes); if (status != PSA_SUCCESS) { psa_remove_key_data_from_memory(slot); } exit: if (status == PSA_SUCCESS) { status = psa_finish_key_creation(slot, driver, key); } if (status != PSA_SUCCESS) { psa_fail_key_creation(slot, driver); } return status; } psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, mbedtls_svc_key_id_t *key) { return psa_generate_key_ext(attributes, &default_production_parameters, 0, key); } /****************************************************************/ /* Module setup */ /****************************************************************/ #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void (* entropy_init)(mbedtls_entropy_context *ctx), void (* entropy_free)(mbedtls_entropy_context *ctx)) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ if (global_data.rng_state != RNG_NOT_INITIALIZED) { status = PSA_ERROR_BAD_STATE; } else { global_data.rng.entropy_init = entropy_init; global_data.rng.entropy_free = entropy_free; status = PSA_SUCCESS; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return status; } #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ void mbedtls_psa_crypto_free(void) { #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ /* Nothing to do to free transaction. */ if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) { global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; } if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) { psa_wipe_all_key_slots(); global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ if (global_data.rng_state != RNG_NOT_INITIALIZED) { mbedtls_psa_random_free(&global_data.rng); } global_data.rng_state = RNG_NOT_INITIALIZED; mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ /* Terminate drivers */ if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) { psa_driver_wrapper_free(); global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ } #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) /** Recover a transaction that was interrupted by a power failure. * * This function is called during initialization, before psa_crypto_init() * returns. If this function returns a failure status, the initialization * fails. */ static psa_status_t psa_crypto_recover_transaction( const psa_crypto_transaction_t *transaction) { switch (transaction->unknown.type) { case PSA_CRYPTO_TRANSACTION_CREATE_KEY: case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: /* TODO - fall through to the failure case until this * is implemented. * https://github.com/ARMmbed/mbed-crypto/issues/218 */ default: /* We found an unsupported transaction in the storage. * We don't know what state the storage is in. Give up. */ return PSA_ERROR_DATA_INVALID; } } #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem) { psa_status_t status = PSA_SUCCESS; uint8_t driver_wrappers_initialized = 0; switch (subsystem) { case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) { /* Init drivers */ status = psa_driver_wrapper_init(); /* Drivers need shutdown regardless of startup errors. */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) { status = psa_initialize_key_slots(); /* Need to wipe keys even if initialization fails. */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; case PSA_CRYPTO_SUBSYSTEM_RNG: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ driver_wrappers_initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ /* Need to use separate mutex here, as initialisation can require * testing of init flags, which requires locking the global data * mutex. */ #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ /* Initialize and seed the random generator. */ if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) { mbedtls_psa_random_init(&global_data.rng); global_data.rng_state = RNG_INITIALIZED; status = mbedtls_psa_random_seed(&global_data.rng); if (status == PSA_SUCCESS) { global_data.rng_state = RNG_SEEDED; } } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_rngdata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; case PSA_CRYPTO_SUBSYSTEM_TRANSACTION: #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) { #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) status = psa_crypto_load_transaction(); if (status == PSA_SUCCESS) { status = psa_crypto_recover_transaction(&psa_crypto_transaction); if (status == PSA_SUCCESS) { global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; } status = psa_crypto_stop_transaction(); } else if (status == PSA_ERROR_DOES_NOT_EXIST) { /* There's no transaction to complete. It's all good. */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; status = PSA_SUCCESS; } #else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED; status = PSA_SUCCESS; #endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */ } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock( &mbedtls_threading_psa_globaldata_mutex)); #endif /* defined(MBEDTLS_THREADING_C) */ break; default: status = PSA_ERROR_CORRUPTION_DETECTED; } /* Exit label only required when using threading macros. */ #if defined(MBEDTLS_THREADING_C) exit: #endif /* defined(MBEDTLS_THREADING_C) */ return status; } psa_status_t psa_crypto_init(void) { psa_status_t status; /* Double initialization is explicitly allowed. Early out if everything is * done. */ if (psa_get_initialized()) { return PSA_SUCCESS; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION); exit: if (status != PSA_SUCCESS) { mbedtls_psa_crypto_free(); } return status; } #if defined(PSA_WANT_ALG_SOME_PAKE) psa_status_t psa_crypto_driver_pake_get_password_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *password_len) { if (inputs->password_len == 0) { return PSA_ERROR_BAD_STATE; } *password_len = inputs->password_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_password( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *buffer, size_t buffer_size, size_t *buffer_length) { if (inputs->password_len == 0) { return PSA_ERROR_BAD_STATE; } if (buffer_size < inputs->password_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(buffer, inputs->password, inputs->password_len); *buffer_length = inputs->password_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_user_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *user_len) { if (inputs->user_len == 0) { return PSA_ERROR_BAD_STATE; } *user_len = inputs->user_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_user( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *user_id, size_t user_id_size, size_t *user_id_len) { if (inputs->user_len == 0) { return PSA_ERROR_BAD_STATE; } if (user_id_size < inputs->user_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(user_id, inputs->user, inputs->user_len); *user_id_len = inputs->user_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_peer_len( const psa_crypto_driver_pake_inputs_t *inputs, size_t *peer_len) { if (inputs->peer_len == 0) { return PSA_ERROR_BAD_STATE; } *peer_len = inputs->peer_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_peer( const psa_crypto_driver_pake_inputs_t *inputs, uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length) { if (inputs->peer_len == 0) { return PSA_ERROR_BAD_STATE; } if (peer_id_size < inputs->peer_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(peer_id, inputs->peer, inputs->peer_len); *peer_id_length = inputs->peer_len; return PSA_SUCCESS; } psa_status_t psa_crypto_driver_pake_get_cipher_suite( const psa_crypto_driver_pake_inputs_t *inputs, psa_pake_cipher_suite_t *cipher_suite) { if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) { return PSA_ERROR_BAD_STATE; } *cipher_suite = inputs->cipher_suite; return PSA_SUCCESS; } psa_status_t psa_pake_setup( psa_pake_operation_t *operation, const psa_pake_cipher_suite_t *cipher_suite) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) { status = PSA_ERROR_BAD_STATE; goto exit; } if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 || PSA_ALG_IS_HASH(cipher_suite->hash) == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } memset(&operation->data.inputs, 0, sizeof(operation->data.inputs)); operation->alg = cipher_suite->algorithm; operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, cipher_suite->bits); operation->data.inputs.cipher_suite = *cipher_suite; #if defined(PSA_WANT_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { psa_jpake_computation_stage_t *computation_stage = &operation->computation_stage.jpake; memset(computation_stage, 0, sizeof(*computation_stage)); computation_stage->step = PSA_PAKE_STEP_KEY_SHARE; } else #endif /* PSA_WANT_ALG_JPAKE */ { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS; return PSA_SUCCESS; exit: psa_pake_abort(operation); return status; } psa_status_t psa_pake_set_password_key( psa_pake_operation_t *operation, mbedtls_svc_key_id_t password) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot = NULL; psa_key_type_t type; if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } status = psa_get_and_lock_key_slot_with_policy(password, &slot, PSA_KEY_USAGE_DERIVE, operation->alg); if (status != PSA_SUCCESS) { goto exit; } type = psa_get_key_type(&slot->attr); if (type != PSA_KEY_TYPE_PASSWORD && type != PSA_KEY_TYPE_PASSWORD_HASH) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes); if (operation->data.inputs.password == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes); operation->data.inputs.password_len = slot->key.bytes; operation->data.inputs.attributes = slot->attr; exit: if (status != PSA_SUCCESS) { psa_pake_abort(operation); } unlock_status = psa_unregister_read_under_mutex(slot); return (status == PSA_SUCCESS) ? unlock_status : status; } psa_status_t psa_pake_set_user( psa_pake_operation_t *operation, const uint8_t *user_id_external, size_t user_id_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(user_id_external, user_id); if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } if (user_id_len == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (operation->data.inputs.user_len != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } operation->data.inputs.user = mbedtls_calloc(1, user_id_len); if (operation->data.inputs.user == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id); memcpy(operation->data.inputs.user, user_id, user_id_len); operation->data.inputs.user_len = user_id_len; status = PSA_SUCCESS; exit: LOCAL_INPUT_FREE(user_id_external, user_id); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_set_peer( psa_pake_operation_t *operation, const uint8_t *peer_id_external, size_t peer_id_len) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; LOCAL_INPUT_DECLARE(peer_id_external, peer_id); if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } if (peer_id_len == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (operation->data.inputs.peer_len != 0) { status = PSA_ERROR_BAD_STATE; goto exit; } operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len); if (operation->data.inputs.peer == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto exit; } LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id); memcpy(operation->data.inputs.peer, peer_id, peer_id_len); operation->data.inputs.peer_len = peer_id_len; status = PSA_SUCCESS; exit: LOCAL_INPUT_FREE(peer_id_external, peer_id); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_set_role( psa_pake_operation_t *operation, psa_pake_role_t role) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = PSA_ERROR_BAD_STATE; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: if (role == PSA_PAKE_ROLE_NONE) { return PSA_SUCCESS; } status = PSA_ERROR_INVALID_ARGUMENT; break; #endif default: (void) role; status = PSA_ERROR_NOT_SUPPORTED; goto exit; } exit: psa_pake_abort(operation); return status; } /* Auxiliary function to convert core computation stage to single driver step. */ #if defined(PSA_WANT_ALG_JPAKE) static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step( psa_jpake_computation_stage_t *stage) { psa_crypto_driver_pake_step_t key_share_step; if (stage->round == PSA_JPAKE_FIRST) { int is_x1; if (stage->io_mode == PSA_JPAKE_OUTPUT) { is_x1 = (stage->outputs < 1); } else { is_x1 = (stage->inputs < 1); } key_share_step = is_x1 ? PSA_JPAKE_X1_STEP_KEY_SHARE : PSA_JPAKE_X2_STEP_KEY_SHARE; } else if (stage->round == PSA_JPAKE_SECOND) { key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ? PSA_JPAKE_X2S_STEP_KEY_SHARE : PSA_JPAKE_X4S_STEP_KEY_SHARE; } else { return PSA_JPAKE_STEP_INVALID; } return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE); } #endif /* PSA_WANT_ALG_JPAKE */ static psa_status_t psa_pake_complete_inputs( psa_pake_operation_t *operation) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Create copy of the inputs on stack as inputs share memory with the driver context which will be setup by the driver. */ psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs; if (inputs.password_len == 0) { return PSA_ERROR_BAD_STATE; } if (operation->alg == PSA_ALG_JPAKE) { if (inputs.user_len == 0 || inputs.peer_len == 0) { return PSA_ERROR_BAD_STATE; } } /* Clear driver context */ mbedtls_platform_zeroize(&operation->data, sizeof(operation->data)); status = psa_driver_wrapper_pake_setup(operation, &inputs); /* Driver is responsible for creating its own copy of the password. */ mbedtls_zeroize_and_free(inputs.password, inputs.password_len); /* User and peer are translated to role. */ mbedtls_free(inputs.user); mbedtls_free(inputs.peer); if (status == PSA_SUCCESS) { #if defined(PSA_WANT_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION; } else #endif /* PSA_WANT_ALG_JPAKE */ { status = PSA_ERROR_NOT_SUPPORTED; } } return status; } #if defined(PSA_WANT_ALG_JPAKE) static psa_status_t psa_jpake_prologue( psa_pake_operation_t *operation, psa_pake_step_t step, psa_jpake_io_mode_t io_mode) { if (step != PSA_PAKE_STEP_KEY_SHARE && step != PSA_PAKE_STEP_ZK_PUBLIC && step != PSA_PAKE_STEP_ZK_PROOF) { return PSA_ERROR_INVALID_ARGUMENT; } psa_jpake_computation_stage_t *computation_stage = &operation->computation_stage.jpake; if (computation_stage->round != PSA_JPAKE_FIRST && computation_stage->round != PSA_JPAKE_SECOND) { return PSA_ERROR_BAD_STATE; } /* Check that the step we are given is the one we were expecting */ if (step != computation_stage->step) { return PSA_ERROR_BAD_STATE; } if (step == PSA_PAKE_STEP_KEY_SHARE && computation_stage->inputs == 0 && computation_stage->outputs == 0) { /* Start of the round, so function decides whether we are inputting * or outputting */ computation_stage->io_mode = io_mode; } else if (computation_stage->io_mode != io_mode) { /* Middle of the round so the mode we are in must match the function * called by the user */ return PSA_ERROR_BAD_STATE; } return PSA_SUCCESS; } static psa_status_t psa_jpake_epilogue( psa_pake_operation_t *operation, psa_jpake_io_mode_t io_mode) { psa_jpake_computation_stage_t *stage = &operation->computation_stage.jpake; if (stage->step == PSA_PAKE_STEP_ZK_PROOF) { /* End of an input/output */ if (io_mode == PSA_JPAKE_INPUT) { stage->inputs++; if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) { stage->io_mode = PSA_JPAKE_OUTPUT; } } if (io_mode == PSA_JPAKE_OUTPUT) { stage->outputs++; if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { stage->io_mode = PSA_JPAKE_INPUT; } } if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) && stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) { /* End of a round, move to the next round */ stage->inputs = 0; stage->outputs = 0; stage->round++; } stage->step = PSA_PAKE_STEP_KEY_SHARE; } else { stage->step++; } return PSA_SUCCESS; } #endif /* PSA_WANT_ALG_JPAKE */ psa_status_t psa_pake_output( psa_pake_operation_t *operation, psa_pake_step_t step, uint8_t *output_external, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; LOCAL_OUTPUT_DECLARE(output_external, output); *output_length = 0; if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = psa_pake_complete_inputs(operation); if (status != PSA_SUCCESS) { goto exit; } } if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = PSA_ERROR_BAD_STATE; goto exit; } if (output_size == 0) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT); if (status != PSA_SUCCESS) { goto exit; } driver_step = convert_jpake_computation_stage_to_driver_step( &operation->computation_stage.jpake); break; #endif /* PSA_WANT_ALG_JPAKE */ default: (void) step; status = PSA_ERROR_NOT_SUPPORTED; goto exit; } LOCAL_OUTPUT_ALLOC(output_external, output_size, output); status = psa_driver_wrapper_pake_output(operation, driver_step, output, output_size, output_length); if (status != PSA_SUCCESS) { goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT); if (status != PSA_SUCCESS) { goto exit; } break; #endif /* PSA_WANT_ALG_JPAKE */ default: status = PSA_ERROR_NOT_SUPPORTED; goto exit; } exit: LOCAL_OUTPUT_FREE(output_external, output); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_input( psa_pake_operation_t *operation, psa_pake_step_t step, const uint8_t *input_external, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID; const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg, operation->primitive, step); LOCAL_INPUT_DECLARE(input_external, input); if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { status = psa_pake_complete_inputs(operation); if (status != PSA_SUCCESS) { goto exit; } } if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = PSA_ERROR_BAD_STATE; goto exit; } if (input_length == 0 || input_length > max_input_length) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT); if (status != PSA_SUCCESS) { goto exit; } driver_step = convert_jpake_computation_stage_to_driver_step( &operation->computation_stage.jpake); break; #endif /* PSA_WANT_ALG_JPAKE */ default: (void) step; status = PSA_ERROR_NOT_SUPPORTED; goto exit; } LOCAL_INPUT_ALLOC(input_external, input_length, input); status = psa_driver_wrapper_pake_input(operation, driver_step, input, input_length); if (status != PSA_SUCCESS) { goto exit; } switch (operation->alg) { #if defined(PSA_WANT_ALG_JPAKE) case PSA_ALG_JPAKE: status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT); if (status != PSA_SUCCESS) { goto exit; } break; #endif /* PSA_WANT_ALG_JPAKE */ default: status = PSA_ERROR_NOT_SUPPORTED; goto exit; } exit: LOCAL_INPUT_FREE(input_external, input); if (status != PSA_SUCCESS) { psa_pake_abort(operation); } return status; } psa_status_t psa_pake_get_implicit_key( psa_pake_operation_t *operation, psa_key_derivation_operation_t *output) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]; size_t shared_key_len = 0; if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = PSA_ERROR_BAD_STATE; goto exit; } #if defined(PSA_WANT_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { psa_jpake_computation_stage_t *computation_stage = &operation->computation_stage.jpake; if (computation_stage->round != PSA_JPAKE_FINISHED) { status = PSA_ERROR_BAD_STATE; goto exit; } } else #endif /* PSA_WANT_ALG_JPAKE */ { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = psa_driver_wrapper_pake_get_implicit_key(operation, shared_key, sizeof(shared_key), &shared_key_len); if (status != PSA_SUCCESS) { goto exit; } status = psa_key_derivation_input_bytes(output, PSA_KEY_DERIVATION_INPUT_SECRET, shared_key, shared_key_len); mbedtls_platform_zeroize(shared_key, sizeof(shared_key)); exit: abort_status = psa_pake_abort(operation); return status == PSA_SUCCESS ? abort_status : status; } psa_status_t psa_pake_abort( psa_pake_operation_t *operation) { psa_status_t status = PSA_SUCCESS; if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) { status = psa_driver_wrapper_pake_abort(operation); } if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) { if (operation->data.inputs.password != NULL) { mbedtls_zeroize_and_free(operation->data.inputs.password, operation->data.inputs.password_len); } if (operation->data.inputs.user != NULL) { mbedtls_free(operation->data.inputs.user); } if (operation->data.inputs.peer != NULL) { mbedtls_free(operation->data.inputs.peer); } } memset(operation, 0, sizeof(psa_pake_operation_t)); return status; } #endif /* PSA_WANT_ALG_SOME_PAKE */ /* Memory copying test hooks. These are called before input copy, after input * copy, before output copy and after output copy, respectively. * They are used by memory-poisoning tests to temporarily unpoison buffers * while they are copied. */ #if defined(MBEDTLS_TEST_HOOKS) void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL; void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL; void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL; void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL; #endif /** Copy from an input buffer to a local copy. * * \param[in] input Pointer to input buffer. * \param[in] input_len Length of the input buffer. * \param[out] input_copy Pointer to a local copy in which to store the input data. * \param[out] input_copy_len Length of the local copy buffer. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_CORRUPTION_DETECTED, if the local * copy is too small to hold contents of the * input buffer. */ MBEDTLS_STATIC_TESTABLE psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, uint8_t *input_copy, size_t input_copy_len) { if (input_len > input_copy_len) { return PSA_ERROR_CORRUPTION_DETECTED; } #if defined(MBEDTLS_TEST_HOOKS) if (psa_input_pre_copy_hook != NULL) { psa_input_pre_copy_hook(input, input_len); } #endif if (input_len > 0) { memcpy(input_copy, input, input_len); } #if defined(MBEDTLS_TEST_HOOKS) if (psa_input_post_copy_hook != NULL) { psa_input_post_copy_hook(input, input_len); } #endif return PSA_SUCCESS; } /** Copy from a local output buffer into a user-supplied one. * * \param[in] output_copy Pointer to a local buffer containing the output. * \param[in] output_copy_len Length of the local buffer. * \param[out] output Pointer to user-supplied output buffer. * \param[out] output_len Length of the user-supplied output buffer. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_BUFFER_TOO_SMALL, if the * user-supplied output buffer is too small to * hold the contents of the local buffer. */ MBEDTLS_STATIC_TESTABLE psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, uint8_t *output, size_t output_len) { if (output_len < output_copy_len) { return PSA_ERROR_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_TEST_HOOKS) if (psa_output_pre_copy_hook != NULL) { psa_output_pre_copy_hook(output, output_len); } #endif if (output_copy_len > 0) { memcpy(output, output_copy, output_copy_len); } #if defined(MBEDTLS_TEST_HOOKS) if (psa_output_post_copy_hook != NULL) { psa_output_post_copy_hook(output, output_len); } #endif return PSA_SUCCESS; } psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, psa_crypto_local_input_t *local_input) { psa_status_t status; *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT; if (input_len == 0) { return PSA_SUCCESS; } local_input->buffer = mbedtls_calloc(input_len, 1); if (local_input->buffer == NULL) { /* Since we dealt with the zero-length case above, we know that * a NULL return value means a failure of allocation. */ return PSA_ERROR_INSUFFICIENT_MEMORY; } /* From now on, we must free local_input->buffer on error. */ local_input->length = input_len; status = psa_crypto_copy_input(input, input_len, local_input->buffer, local_input->length); if (status != PSA_SUCCESS) { goto error; } return PSA_SUCCESS; error: mbedtls_free(local_input->buffer); local_input->buffer = NULL; local_input->length = 0; return status; } void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input) { mbedtls_free(local_input->buffer); local_input->buffer = NULL; local_input->length = 0; } psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, psa_crypto_local_output_t *local_output) { *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; if (output_len == 0) { return PSA_SUCCESS; } local_output->buffer = mbedtls_calloc(output_len, 1); if (local_output->buffer == NULL) { /* Since we dealt with the zero-length case above, we know that * a NULL return value means a failure of allocation. */ return PSA_ERROR_INSUFFICIENT_MEMORY; } local_output->length = output_len; local_output->original = output; return PSA_SUCCESS; } psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output) { psa_status_t status; if (local_output->buffer == NULL) { local_output->length = 0; return PSA_SUCCESS; } if (local_output->original == NULL) { /* We have an internal copy but nothing to copy back to. */ return PSA_ERROR_CORRUPTION_DETECTED; } status = psa_crypto_copy_output(local_output->buffer, local_output->length, local_output->original, local_output->length); if (status != PSA_SUCCESS) { return status; } mbedtls_free(local_output->buffer); local_output->buffer = NULL; local_output->length = 0; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_aead.c000066400000000000000000000544261464416617300246500ustar00rootroot00000000000000/* * PSA AEAD entry points */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include "psa_crypto_aead.h" #include "psa_crypto_core.h" #include "psa_crypto_cipher.h" #include #include "mbedtls/platform.h" #include "mbedtls/ccm.h" #include "mbedtls/chachapoly.h" #include "mbedtls/cipher.h" #include "mbedtls/gcm.h" #include "mbedtls/error.h" static psa_status_t psa_aead_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_cipher_id_t cipher_id; mbedtls_cipher_mode_t mode; size_t key_bits = attributes->bits; (void) key_buffer_size; status = mbedtls_cipher_values_from_psa(alg, attributes->type, &key_bits, &mode, &cipher_id); if (status != PSA_SUCCESS) { return status; } switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): operation->alg = PSA_ALG_CCM; /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. * The call to mbedtls_ccm_encrypt_and_tag or * mbedtls_ccm_auth_decrypt will validate the tag length. */ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_ccm_init(&operation->ctx.ccm); status = mbedtls_to_psa_error( mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id, key_buffer, (unsigned int) key_bits)); if (status != PSA_SUCCESS) { return status; } break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): operation->alg = PSA_ALG_GCM; /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. * The call to mbedtls_gcm_crypt_and_tag or * mbedtls_gcm_auth_decrypt will validate the tag length. */ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_gcm_init(&operation->ctx.gcm); status = mbedtls_to_psa_error( mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id, key_buffer, (unsigned int) key_bits)); if (status != PSA_SUCCESS) { return status; } break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): operation->alg = PSA_ALG_CHACHA20_POLY1305; /* We only support the default tag length. */ if (alg != PSA_ALG_CHACHA20_POLY1305) { return PSA_ERROR_NOT_SUPPORTED; } mbedtls_chachapoly_init(&operation->ctx.chachapoly); status = mbedtls_to_psa_error( mbedtls_chachapoly_setkey(&operation->ctx.chachapoly, key_buffer)); if (status != PSA_SUCCESS) { return status; } break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ default: (void) status; (void) key_buffer; return PSA_ERROR_NOT_SUPPORTED; } operation->key_type = psa_get_key_type(attributes); operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg); return PSA_SUCCESS; } psa_status_t mbedtls_psa_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; uint8_t *tag; status = psa_aead_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } /* For all currently supported modes, the tag is at the end of the * ciphertext. */ if (ciphertext_size < (plaintext_length + operation.tag_length)) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } tag = ciphertext + plaintext_length; #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation.alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm, plaintext_length, nonce, nonce_length, additional_data, additional_data_length, plaintext, ciphertext, tag, operation.tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation.alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm, MBEDTLS_GCM_ENCRYPT, plaintext_length, nonce, nonce_length, additional_data, additional_data_length, plaintext, ciphertext, operation.tag_length, tag)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { if (operation.tag_length != 16) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = mbedtls_to_psa_error( mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly, plaintext_length, nonce, additional_data, additional_data_length, plaintext, ciphertext, tag)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) tag; (void) nonce; (void) nonce_length; (void) additional_data; (void) additional_data_length; (void) plaintext; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { *ciphertext_length = plaintext_length + operation.tag_length; } exit: mbedtls_psa_aead_abort(&operation); return status; } /* Locate the tag in a ciphertext buffer containing the encrypted data * followed by the tag. Return the length of the part preceding the tag in * *plaintext_length. This is the size of the plaintext in modes where * the encrypted data has the same size as the plaintext, such as * CCM and GCM. */ static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length, const uint8_t *ciphertext, size_t ciphertext_length, size_t plaintext_size, const uint8_t **p_tag) { size_t payload_length; if (tag_length > ciphertext_length) { return PSA_ERROR_INVALID_ARGUMENT; } payload_length = ciphertext_length - tag_length; if (payload_length > plaintext_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } *p_tag = ciphertext + payload_length; return PSA_SUCCESS; } psa_status_t mbedtls_psa_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; const uint8_t *tag = NULL; status = psa_aead_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_aead_unpadded_locate_tag(operation.tag_length, ciphertext, ciphertext_length, plaintext_size, &tag); if (status != PSA_SUCCESS) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation.alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_auth_decrypt(&operation.ctx.ccm, ciphertext_length - operation.tag_length, nonce, nonce_length, additional_data, additional_data_length, ciphertext, plaintext, tag, operation.tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation.alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_auth_decrypt(&operation.ctx.gcm, ciphertext_length - operation.tag_length, nonce, nonce_length, additional_data, additional_data_length, tag, operation.tag_length, ciphertext, plaintext)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation.alg == PSA_ALG_CHACHA20_POLY1305) { if (operation.tag_length != 16) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = mbedtls_to_psa_error( mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly, ciphertext_length - operation.tag_length, nonce, additional_data, additional_data_length, tag, ciphertext, plaintext)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) nonce; (void) nonce_length; (void) additional_data; (void) additional_data_length; (void) plaintext; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { *plaintext_length = ciphertext_length - operation.tag_length; } exit: mbedtls_psa_aead_abort(&operation); if (status == PSA_SUCCESS) { *plaintext_length = ciphertext_length - operation.tag_length; } return status; } /* Set the key and algorithm for a multipart authenticated encryption * operation. */ psa_status_t mbedtls_psa_aead_encrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_aead_setup(operation, attributes, key_buffer, key_buffer_size, alg); if (status == PSA_SUCCESS) { operation->is_encrypt = 1; } return status; } /* Set the key and algorithm for a multipart authenticated decryption * operation. */ psa_status_t mbedtls_psa_aead_decrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_aead_setup(operation, attributes, key_buffer, key_buffer_size, alg); if (status == PSA_SUCCESS) { operation->is_encrypt = 0; } return status; } /* Set a nonce for the multipart AEAD operation*/ psa_status_t mbedtls_psa_aead_set_nonce( mbedtls_psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_starts(&operation->ctx.gcm, operation->is_encrypt ? MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, nonce, nonce_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_starts(&operation->ctx.ccm, operation->is_encrypt ? MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, nonce, nonce_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to * allocate a buffer in the operation, copy the nonce to it and pad * it, so for now check the nonce is 12 bytes, as * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the * passed in buffer. */ if (nonce_length != 12) { return PSA_ERROR_INVALID_ARGUMENT; } status = mbedtls_to_psa_error( mbedtls_chachapoly_starts(&operation->ctx.chachapoly, nonce, operation->is_encrypt ? MBEDTLS_CHACHAPOLY_ENCRYPT : MBEDTLS_CHACHAPOLY_DECRYPT)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) operation; (void) nonce; (void) nonce_length; return PSA_ERROR_NOT_SUPPORTED; } return status; } /* Declare the lengths of the message and additional data for AEAD. */ psa_status_t mbedtls_psa_aead_set_lengths( mbedtls_psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { return mbedtls_to_psa_error( mbedtls_ccm_set_lengths(&operation->ctx.ccm, ad_length, plaintext_length, operation->tag_length)); } #else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ (void) operation; (void) ad_length; (void) plaintext_length; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ return PSA_SUCCESS; } /* Pass additional data to an active multipart AEAD operation. */ psa_status_t mbedtls_psa_aead_update_ad( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { status = mbedtls_to_psa_error( mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { status = mbedtls_to_psa_error( mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) operation; (void) input; (void) input_length; return PSA_ERROR_NOT_SUPPORTED; } return status; } /* Encrypt or decrypt a message fragment in an active multipart AEAD * operation.*/ psa_status_t mbedtls_psa_aead_update( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { size_t update_output_length; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; update_output_length = input_length; #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_update(&operation->ctx.gcm, input, input_length, output, output_size, &update_output_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { if (output_size < input_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_ccm_update(&operation->ctx.ccm, input, input_length, output, output_size, &update_output_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { if (output_size < input_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_chachapoly_update(&operation->ctx.chachapoly, input_length, input, output)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) operation; (void) input; (void) output; (void) output_size; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { *output_length = update_output_length; } return status; } /* Finish encrypting a message in a multipart AEAD operation. */ psa_status_t mbedtls_psa_aead_finish( mbedtls_psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t finish_output_size = 0; if (tag_size < operation->tag_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) if (operation->alg == PSA_ALG_GCM) { status = mbedtls_to_psa_error( mbedtls_gcm_finish(&operation->ctx.gcm, ciphertext, ciphertext_size, ciphertext_length, tag, operation->tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) if (operation->alg == PSA_ALG_CCM) { /* tag must be big enough to store a tag of size passed into set * lengths. */ if (tag_size < operation->tag_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_ccm_finish(&operation->ctx.ccm, tag, operation->tag_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) if (operation->alg == PSA_ALG_CHACHA20_POLY1305) { /* Belt and braces. Although the above tag_size check should have * already done this, if we later start supporting smaller tag sizes * for chachapoly, then passing a tag buffer smaller than 16 into here * could cause a buffer overflow, so better safe than sorry. */ if (tag_size < 16) { return PSA_ERROR_BUFFER_TOO_SMALL; } status = mbedtls_to_psa_error( mbedtls_chachapoly_finish(&operation->ctx.chachapoly, tag)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ { (void) ciphertext; (void) ciphertext_size; (void) ciphertext_length; (void) tag; (void) tag_size; (void) tag_length; return PSA_ERROR_NOT_SUPPORTED; } if (status == PSA_SUCCESS) { /* This will be zero for all supported algorithms currently, but left * here for future support. */ *ciphertext_length = finish_output_size; *tag_length = operation->tag_length; } return status; } /* Abort an AEAD operation */ psa_status_t mbedtls_psa_aead_abort( mbedtls_psa_aead_operation_t *operation) { switch (operation->alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_CCM: mbedtls_ccm_free(&operation->ctx.ccm); break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_GCM: mbedtls_gcm_free(&operation->ctx.gcm); break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_CHACHA20_POLY1305: mbedtls_chachapoly_free(&operation->ctx.chachapoly); break; #endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ } operation->is_encrypt = 0; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_aead.h000066400000000000000000000565271464416617300246610ustar00rootroot00000000000000/* * PSA AEAD driver entry points */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_AEAD_H #define PSA_CRYPTO_AEAD_H #include /** * \brief Process an authenticated encryption operation. * * \note The signature of this function is that of a PSA driver * aead_encrypt entry point. This function behaves as an aead_encrypt * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The AEAD algorithm to compute. * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the nonce buffer in bytes. This must * be appropriate for the selected algorithm. * The default nonce size is * PSA_AEAD_NONCE_LENGTH(key_type, alg) where * key_type is the type of key. * \param[in] additional_data Additional data that will be authenticated * but not encrypted. * \param additional_data_length Size of additional_data in bytes. * \param[in] plaintext Data that will be authenticated and encrypted. * \param plaintext_length Size of plaintext in bytes. * \param[out] ciphertext Output buffer for the authenticated and * encrypted data. The additional data is not * part of this output. For algorithms where the * encrypted data and the authentication tag are * defined as separate outputs, the * authentication tag is appended to the * encrypted data. * \param ciphertext_size Size of the ciphertext buffer in bytes. This * must be appropriate for the selected algorithm * and key: * - A sufficient output size is * PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, * plaintext_length) where key_type is the type * of key. * - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( * plaintext_length) evaluates to the maximum * ciphertext size of any supported AEAD * encryption. * \param[out] ciphertext_length On success, the size of the output in the * ciphertext buffer. * * \retval #PSA_SUCCESS Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * ciphertext_size is too small. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length); /** * \brief Process an authenticated decryption operation. * * \note The signature of this function is that of a PSA driver * aead_decrypt entry point. This function behaves as an aead_decrypt * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The AEAD algorithm to compute. * \param[in] nonce Nonce or IV to use. * \param nonce_length Size of the nonce buffer in bytes. This must * be appropriate for the selected algorithm. * The default nonce size is * PSA_AEAD_NONCE_LENGTH(key_type, alg) where * key_type is the type of key. * \param[in] additional_data Additional data that has been authenticated * but not encrypted. * \param additional_data_length Size of additional_data in bytes. * \param[in] ciphertext Data that has been authenticated and * encrypted. For algorithms where the encrypted * data and the authentication tag are defined * as separate inputs, the buffer contains * encrypted data followed by the authentication * tag. * \param ciphertext_length Size of ciphertext in bytes. * \param[out] plaintext Output buffer for the decrypted data. * \param plaintext_size Size of the plaintext buffer in bytes. This * must be appropriate for the selected algorithm * and key: * - A sufficient output size is * PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, * ciphertext_length) where key_type is the * type of key. * - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE( * ciphertext_length) evaluates to the maximum * plaintext size of any supported AEAD * decryption. * \param[out] plaintext_length On success, the size of the output in the * plaintext buffer. * * \retval #PSA_SUCCESS Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The cipher is not authentic. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * plaintext_size is too small. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length); /** Set the key for a multipart authenticated encryption operation. * * \note The signature of this function is that of a PSA driver * aead_encrypt_setup entry point. This function behaves as an * aead_encrypt_setup entry point as defined in the PSA driver interface * specification for transparent drivers. * * If an error occurs at any step after a call to * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a * call to mbedtls_psa_aead_abort(). The PSA core may call * mbedtls_psa_aead_abort() at any time after the operation has been * initialized, and is required to when the operation is no longer needed. * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #mbedtls_psa_aead_operation_t and not yet in * use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. It must be consistent with the size in bits recorded in \p attributes. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * An invalid block length was supplied. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Failed to allocate memory for key material */ psa_status_t mbedtls_psa_aead_encrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set the key for a multipart authenticated decryption operation. * * \note The signature of this function is that of a PSA driver * aead_decrypt_setup entry point. This function behaves as an * aead_decrypt_setup entry point as defined in the PSA driver interface * specification for transparent drivers. * * If an error occurs at any step after a call to * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a * call to mbedtls_psa_aead_abort(). The PSA core may call * mbedtls_psa_aead_abort() at any time after the operation has been * initialized, and is required to when the operation is no longer needed. * * \param[in,out] operation The operation object to set up. It must have * been initialized as per the documentation for * #mbedtls_psa_aead_operation_t and not yet in * use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. It must be consistent with the size in bits recorded in \p attributes. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * An invalid block length was supplied. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Failed to allocate memory for key material */ psa_status_t mbedtls_psa_aead_decrypt_setup( mbedtls_psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set the nonce for an authenticated encryption or decryption operation. * * \note The signature of this function is that of a PSA driver aead_set_nonce * entry point. This function behaves as an aead_set_nonce entry point as * defined in the PSA driver interface specification for transparent * drivers. * * This function sets the nonce for the authenticated * encryption or decryption operation. * * The PSA core calls mbedtls_psa_aead_encrypt_setup() or * mbedtls_psa_aead_decrypt_setup() before calling this function. * * If this function returns an error status, the PSA core will call * mbedtls_psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[in] nonce Buffer containing the nonce to use. * \param nonce_length Size of the nonce in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p nonce is not acceptable for the chosen algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * Algorithm previously set is not supported in this configuration of * the library. */ psa_status_t mbedtls_psa_aead_set_nonce( mbedtls_psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length); /** Declare the lengths of the message and additional data for AEAD. * * \note The signature of this function is that of a PSA driver aead_set_lengths * entry point. This function behaves as an aead_set_lengths entry point * as defined in the PSA driver interface specification for transparent * drivers. * * The PSA core calls this function before calling mbedtls_psa_aead_update_ad() * or mbedtls_psa_aead_update() if the algorithm for the operation requires it. * If the algorithm does not require it, calling this function is optional, but * if this function is called then the implementation must enforce the lengths. * * The PSA core may call this function before or after setting the nonce with * mbedtls_psa_aead_set_nonce(). * * - For #PSA_ALG_CCM, calling this function is required. * - For the other AEAD algorithms defined in this specification, calling * this function is not required. * * If this function returns an error status, the PSA core calls * mbedtls_psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param ad_length Size of the non-encrypted additional * authenticated data in bytes. * \param plaintext_length Size of the plaintext to encrypt in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_ARGUMENT * At least one of the lengths is not acceptable for the chosen * algorithm. * \retval #PSA_ERROR_NOT_SUPPORTED * Algorithm previously set is not supported in this configuration of * the library. */ psa_status_t mbedtls_psa_aead_set_lengths( mbedtls_psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length); /** Pass additional data to an active AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_update_ad entry point. This function behaves as an aead_update_ad * entry point as defined in the PSA driver interface specification for * transparent drivers. * * Additional data is authenticated, but not encrypted. * * The PSA core can call this function multiple times to pass successive * fragments of the additional data. It will not call this function after * passing data to encrypt or decrypt with mbedtls_psa_aead_update(). * * Before calling this function, the PSA core will: * 1. Call either mbedtls_psa_aead_encrypt_setup() or * mbedtls_psa_aead_decrypt_setup(). * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). * * If this function returns an error status, the PSA core will call * mbedtls_psa_aead_abort(). * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the fragment of * additional data. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * Algorithm previously set is not supported in this configuration of * the library. */ psa_status_t mbedtls_psa_aead_update_ad( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length); /** Encrypt or decrypt a message fragment in an active AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_update entry point. This function behaves as an aead_update entry * point as defined in the PSA driver interface specification for * transparent drivers. * * Before calling this function, the PSA core will: * 1. Call either mbedtls_psa_aead_encrypt_setup() or * mbedtls_psa_aead_decrypt_setup(). The choice of setup function * determines whether this function encrypts or decrypts its input. * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). * 3. Call mbedtls_psa_aead_update_ad() to pass all the additional data. * * If this function returns an error status, the PSA core will call * mbedtls_psa_aead_abort(). * * This function does not require the input to be aligned to any * particular block boundary. If the implementation can only process * a whole block at a time, it must consume all the input provided, but * it may delay the end of the corresponding output until a subsequent * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides * sufficient input. The amount of data that can be delayed in this way is * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. * * \param[in,out] operation Active AEAD operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, * \c alg, \p input_length) where * \c key_type is the type of key and \c alg is * the algorithm that were used to set up the * operation. * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p * input_length) evaluates to the maximum * output size of any supported AEAD * algorithm. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS * Success. * * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to * determine the required buffer size. */ psa_status_t mbedtls_psa_aead_update( mbedtls_psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting a message in an AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_finish entry point. This function behaves as an aead_finish entry * point as defined in the PSA driver interface specification for * transparent drivers. * * The operation must have been set up by the PSA core with * mbedtls_psa_aead_encrypt_setup(). * * This function finishes the authentication of the additional data * formed by concatenating the inputs passed to preceding calls to * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the * inputs passed to preceding calls to mbedtls_psa_aead_update(). * * This function has two output buffers: * - \p ciphertext contains trailing ciphertext that was buffered from * preceding calls to mbedtls_psa_aead_update(). * - \p tag contains the authentication tag. * * Whether or not this function returns successfully, the PSA core subsequently * calls mbedtls_psa_aead_abort() to deactivate the operation. * * \param[in,out] operation Active AEAD operation. * \param[out] ciphertext Buffer where the last part of the ciphertext * is to be written. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - A sufficient output size is * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, * \c alg) where \c key_type is the type of key * and \c alg is the algorithm that were used to * set up the operation. * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to * the maximum output size of any supported AEAD * algorithm. * \param[out] ciphertext_length On success, the number of bytes of * returned ciphertext. * \param[out] tag Buffer where the authentication tag is * to be written. * \param tag_size Size of the \p tag buffer in bytes. * This must be appropriate for the selected * algorithm and key: * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c * key_type, \c key_bits, \c alg) where * \c key_type and \c key_bits are the type and * bit-size of the key, and \c alg are the * algorithm that were used in the call to * mbedtls_psa_aead_encrypt_setup(). * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the * maximum tag size of any supported AEAD * algorithm. * \param[out] tag_length On success, the number of bytes * that make up the returned tag. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p tag buffer is too small. * #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or * #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag * buffer size. */ psa_status_t mbedtls_psa_aead_finish( mbedtls_psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length); /** Abort an AEAD operation. * * \note The signature of this function is that of a PSA driver * aead_abort entry point. This function behaves as an aead_abort entry * point as defined in the PSA driver interface specification for * transparent drivers. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by the PSA core by it calling * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again. * * The PSA core may call this function any time after the operation object has * been initialized as described in #mbedtls_psa_aead_operation_t. * * In particular, calling mbedtls_psa_aead_abort() after the operation has been * terminated by a call to mbedtls_psa_aead_abort() or * mbedtls_psa_aead_finish() is safe and has no effect. * * \param[in,out] operation Initialized AEAD operation. * * \retval #PSA_SUCCESS * Success. */ psa_status_t mbedtls_psa_aead_abort( mbedtls_psa_aead_operation_t *operation); #endif /* PSA_CRYPTO_AEAD_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.c000066400000000000000000000553361464416617300252310ustar00rootroot00000000000000/* * PSA cipher driver entry points */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_random_impl.h" #include "mbedtls/cipher.h" #include "mbedtls/error.h" #include /* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols * are enabled, but it does not provide any compatibility check between them * (i.e. if the specified key works with the specified algorithm). This helper * function is meant to provide this support. * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it * requires CIPHER_C to be enabled. */ static psa_status_t mbedtls_cipher_validate_values( psa_algorithm_t alg, psa_key_type_t key_type) { /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to eliminate bits of the logic below. */ #if !defined(PSA_WANT_KEY_TYPE_AES) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES); #endif #if !defined(PSA_WANT_KEY_TYPE_ARIA) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA); #endif #if !defined(PSA_WANT_KEY_TYPE_CAMELLIA) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA); #endif #if !defined(PSA_WANT_KEY_TYPE_CHACHA20) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20); #endif #if !defined(PSA_WANT_KEY_TYPE_DES) MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES); #endif #if !defined(PSA_WANT_ALG_CCM) MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0)); #endif #if !defined(PSA_WANT_ALG_GCM) MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0)); #endif #if !defined(PSA_WANT_ALG_STREAM_CIPHER) MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER); #endif #if !defined(PSA_WANT_ALG_CHACHA20_POLY1305) MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)); #endif #if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG); #endif #if !defined(PSA_WANT_ALG_CTR) MBEDTLS_ASSUME(alg != PSA_ALG_CTR); #endif #if !defined(PSA_WANT_ALG_CFB) MBEDTLS_ASSUME(alg != PSA_ALG_CFB); #endif #if !defined(PSA_WANT_ALG_OFB) MBEDTLS_ASSUME(alg != PSA_ALG_OFB); #endif #if !defined(PSA_WANT_ALG_XTS) MBEDTLS_ASSUME(alg != PSA_ALG_XTS); #endif #if !defined(PSA_WANT_ALG_ECB_NO_PADDING) MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING); #endif #if !defined(PSA_WANT_ALG_CBC_NO_PADDING) MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING); #endif #if !defined(PSA_WANT_ALG_CBC_PKCS7) MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7); #endif #if !defined(PSA_WANT_ALG_CMAC) MBEDTLS_ASSUME(alg != PSA_ALG_CMAC); #endif if (alg == PSA_ALG_STREAM_CIPHER || alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) { if (key_type == PSA_KEY_TYPE_CHACHA20) { return PSA_SUCCESS; } } if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) || alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) || alg == PSA_ALG_CCM_STAR_NO_TAG) { if (key_type == PSA_KEY_TYPE_AES || key_type == PSA_KEY_TYPE_ARIA || key_type == PSA_KEY_TYPE_CAMELLIA) { return PSA_SUCCESS; } } if (alg == PSA_ALG_CTR || alg == PSA_ALG_CFB || alg == PSA_ALG_OFB || alg == PSA_ALG_XTS || alg == PSA_ALG_ECB_NO_PADDING || alg == PSA_ALG_CBC_NO_PADDING || alg == PSA_ALG_CBC_PKCS7 || alg == PSA_ALG_CMAC) { if (key_type == PSA_KEY_TYPE_AES || key_type == PSA_KEY_TYPE_ARIA || key_type == PSA_KEY_TYPE_DES || key_type == PSA_KEY_TYPE_CAMELLIA) { return PSA_SUCCESS; } } return PSA_ERROR_NOT_SUPPORTED; } psa_status_t mbedtls_cipher_values_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t *key_bits, mbedtls_cipher_mode_t *mode, mbedtls_cipher_id_t *cipher_id) { mbedtls_cipher_id_t cipher_id_tmp; /* Only DES modifies key_bits */ #if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) (void) key_bits; #endif if (PSA_ALG_IS_AEAD(alg)) { alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0); } if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) { switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) case PSA_ALG_STREAM_CIPHER: *mode = MBEDTLS_MODE_STREAM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) case PSA_ALG_CTR: *mode = MBEDTLS_MODE_CTR; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) case PSA_ALG_CFB: *mode = MBEDTLS_MODE_CFB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) case PSA_ALG_OFB: *mode = MBEDTLS_MODE_OFB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) case PSA_ALG_ECB_NO_PADDING: *mode = MBEDTLS_MODE_ECB; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) case PSA_ALG_CBC_NO_PADDING: *mode = MBEDTLS_MODE_CBC; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) case PSA_ALG_CBC_PKCS7: *mode = MBEDTLS_MODE_CBC; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) case PSA_ALG_CCM_STAR_NO_TAG: *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0): *mode = MBEDTLS_MODE_CCM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0): *mode = MBEDTLS_MODE_GCM; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0): *mode = MBEDTLS_MODE_CHACHAPOLY; break; #endif default: return PSA_ERROR_NOT_SUPPORTED; } } else if (alg == PSA_ALG_CMAC) { *mode = MBEDTLS_MODE_ECB; } else { return PSA_ERROR_NOT_SUPPORTED; } switch (key_type) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES) case PSA_KEY_TYPE_AES: cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA) case PSA_KEY_TYPE_ARIA: cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) case PSA_KEY_TYPE_DES: /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, * and 192 for three-key Triple-DES. */ if (*key_bits == 64) { cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; } else { cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; } /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, * but two-key Triple-DES is functionally three-key Triple-DES * with K1=K3, so that's how we present it to mbedtls. */ if (*key_bits == 128) { *key_bits = 192; } break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA) case PSA_KEY_TYPE_CAMELLIA: cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; break; #endif #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) case PSA_KEY_TYPE_CHACHA20: cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; break; #endif default: return PSA_ERROR_NOT_SUPPORTED; } if (cipher_id != NULL) { *cipher_id = cipher_id_tmp; } return mbedtls_cipher_validate_values(alg, key_type); } #if defined(MBEDTLS_CIPHER_C) const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, mbedtls_cipher_id_t *cipher_id) { mbedtls_cipher_mode_t mode; psa_status_t status; mbedtls_cipher_id_t cipher_id_tmp; status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp); if (status != PSA_SUCCESS) { return NULL; } if (cipher_id != NULL) { *cipher_id = cipher_id_tmp; } return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode); } #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) static psa_status_t psa_cipher_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, mbedtls_operation_t cipher_operation) { int ret = 0; size_t key_bits; const mbedtls_cipher_info_t *cipher_info = NULL; psa_key_type_t key_type = attributes->type; (void) key_buffer_size; mbedtls_cipher_init(&operation->ctx.cipher); operation->alg = alg; key_bits = attributes->bits; cipher_info = mbedtls_cipher_info_from_psa(alg, key_type, key_bits, NULL); if (cipher_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info); if (ret != 0) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) { /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ uint8_t keys[24]; memcpy(keys, key_buffer, 16); memcpy(keys + 16, key_buffer, 8); ret = mbedtls_cipher_setkey(&operation->ctx.cipher, keys, 192, cipher_operation); } else #endif { ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer, (int) key_bits, cipher_operation); } if (ret != 0) { goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) switch (alg) { case PSA_ALG_CBC_NO_PADDING: ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher, MBEDTLS_PADDING_NONE); break; case PSA_ALG_CBC_PKCS7: ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher, MBEDTLS_PADDING_PKCS7); break; default: /* The algorithm doesn't involve padding. */ ret = 0; break; } if (ret != 0) { goto exit; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */ operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 : PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type)); operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg); exit: return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_cipher_encrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_cipher_setup(operation, attributes, key_buffer, key_buffer_size, alg, MBEDTLS_ENCRYPT); } psa_status_t mbedtls_psa_cipher_decrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_cipher_setup(operation, attributes, key_buffer, key_buffer_size, alg, MBEDTLS_DECRYPT); } psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length) { if (iv_length != operation->iv_length) { return PSA_ERROR_INVALID_ARGUMENT; } return mbedtls_to_psa_error( mbedtls_cipher_set_iv(&operation->ctx.cipher, iv, iv_length)); } #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) /** Process input for which the algorithm is set to ECB mode. * * This requires manual processing, since the PSA API is defined as being * able to process arbitrary-length calls to psa_cipher_update() with ECB mode, * but the underlying mbedtls_cipher_update only takes full blocks. * * \param ctx The mbedtls cipher context to use. It must have been * set up for ECB. * \param[in] input The input plaintext or ciphertext to process. * \param input_length The number of bytes to process from \p input. * This does not need to be aligned to a block boundary. * If there is a partial block at the end of the input, * it is stored in \p ctx for future processing. * \param output The buffer where the output is written. It must be * at least `BS * floor((p + input_length) / BS)` bytes * long, where `p` is the number of bytes in the * unprocessed partial block in \p ctx (with * `0 <= p <= BS - 1`) and `BS` is the block size. * \param output_length On success, the number of bytes written to \p output. * \c 0 on error. * * \return #PSA_SUCCESS or an error from a hardware accelerator */ static psa_status_t psa_cipher_update_ecb( mbedtls_cipher_context_t *ctx, const uint8_t *input, size_t input_length, uint8_t *output, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info); size_t internal_output_length = 0; *output_length = 0; if (input_length == 0) { status = PSA_SUCCESS; goto exit; } if (ctx->unprocessed_len > 0) { /* Fill up to block size, and run the block if there's a full one. */ size_t bytes_to_copy = block_size - ctx->unprocessed_len; if (input_length < bytes_to_copy) { bytes_to_copy = input_length; } memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, bytes_to_copy); input_length -= bytes_to_copy; input += bytes_to_copy; ctx->unprocessed_len += bytes_to_copy; if (ctx->unprocessed_len == block_size) { status = mbedtls_to_psa_error( mbedtls_cipher_update(ctx, ctx->unprocessed_data, block_size, output, &internal_output_length)); if (status != PSA_SUCCESS) { goto exit; } output += internal_output_length; *output_length += internal_output_length; ctx->unprocessed_len = 0; } } while (input_length >= block_size) { /* Run all full blocks we have, one by one */ status = mbedtls_to_psa_error( mbedtls_cipher_update(ctx, input, block_size, output, &internal_output_length)); if (status != PSA_SUCCESS) { goto exit; } input_length -= block_size; input += block_size; output += internal_output_length; *output_length += internal_output_length; } if (input_length > 0) { /* Save unprocessed bytes for later processing */ memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input, input_length); ctx->unprocessed_len += input_length; } status = PSA_SUCCESS; exit: return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ psa_status_t mbedtls_psa_cipher_update( mbedtls_psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t expected_output_size; if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) { /* Take the unprocessed partial block left over from previous * update calls, if any, plus the input to this call. Remove * the last partial block, if any. You get the data that will be * output in this call. */ expected_output_size = (operation->ctx.cipher.unprocessed_len + input_length) / operation->block_length * operation->block_length; } else { expected_output_size = input_length; } if (output_size < expected_output_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) if (operation->alg == PSA_ALG_ECB_NO_PADDING) { /* mbedtls_cipher_update has an API inconsistency: it will only * process a single block at a time in ECB mode. Abstract away that * inconsistency here to match the PSA API behaviour. */ status = psa_cipher_update_ecb(&operation->ctx.cipher, input, input_length, output, output_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */ if (input_length == 0) { /* There is no input, nothing to be done */ *output_length = 0; status = PSA_SUCCESS; } else { status = mbedtls_to_psa_error( mbedtls_cipher_update(&operation->ctx.cipher, input, input_length, output, output_length)); if (*output_length > output_size) { return PSA_ERROR_CORRUPTION_DETECTED; } } return status; } psa_status_t mbedtls_psa_cipher_finish( mbedtls_psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; if (operation->ctx.cipher.unprocessed_len != 0) { if (operation->alg == PSA_ALG_ECB_NO_PADDING || operation->alg == PSA_ALG_CBC_NO_PADDING) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } } status = mbedtls_to_psa_error( mbedtls_cipher_finish(&operation->ctx.cipher, temp_output_buffer, output_length)); if (status != PSA_SUCCESS) { goto exit; } if (*output_length == 0) { ; /* Nothing to copy. Note that output may be NULL in this case. */ } else if (output_size >= *output_length) { memcpy(output, temp_output_buffer, *output_length); } else { status = PSA_ERROR_BUFFER_TOO_SMALL; } exit: mbedtls_platform_zeroize(temp_output_buffer, sizeof(temp_output_buffer)); return status; } psa_status_t mbedtls_psa_cipher_abort( mbedtls_psa_cipher_operation_t *operation) { /* Sanity check (shouldn't happen: operation->alg should * always have been initialized to a valid value). */ if (!PSA_ALG_IS_CIPHER(operation->alg)) { return PSA_ERROR_BAD_STATE; } mbedtls_cipher_free(&operation->ctx.cipher); return PSA_SUCCESS; } psa_status_t mbedtls_psa_cipher_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *iv, size_t iv_length, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; size_t update_output_length, finish_output_length; status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } if (iv_length > 0) { status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length); if (status != PSA_SUCCESS) { goto exit; } } status = mbedtls_psa_cipher_update(&operation, input, input_length, output, output_size, &update_output_length); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_cipher_finish( &operation, mbedtls_buffer_offset(output, update_output_length), output_size - update_output_length, &finish_output_length); if (status != PSA_SUCCESS) { goto exit; } *output_length = update_output_length + finish_output_length; exit: if (status == PSA_SUCCESS) { status = mbedtls_psa_cipher_abort(&operation); } else { mbedtls_psa_cipher_abort(&operation); } return status; } psa_status_t mbedtls_psa_cipher_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; size_t olength, accumulated_length; status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } if (operation.iv_length > 0) { status = mbedtls_psa_cipher_set_iv(&operation, input, operation.iv_length); if (status != PSA_SUCCESS) { goto exit; } } status = mbedtls_psa_cipher_update( &operation, mbedtls_buffer_offset_const(input, operation.iv_length), input_length - operation.iv_length, output, output_size, &olength); if (status != PSA_SUCCESS) { goto exit; } accumulated_length = olength; status = mbedtls_psa_cipher_finish( &operation, mbedtls_buffer_offset(output, accumulated_length), output_size - accumulated_length, &olength); if (status != PSA_SUCCESS) { goto exit; } *output_length = accumulated_length + olength; exit: if (status == PSA_SUCCESS) { status = mbedtls_psa_cipher_abort(&operation); } else { mbedtls_psa_cipher_abort(&operation); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.h000066400000000000000000000363351464416617300252340ustar00rootroot00000000000000/* * PSA cipher driver entry points and associated auxiliary functions */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CIPHER_H #define PSA_CRYPTO_CIPHER_H #include #include /** Get Mbed TLS cipher information given the cipher algorithm PSA identifier * as well as the PSA type and size of the key to be used with the cipher * algorithm. * * \param[in] alg PSA cipher algorithm identifier * \param[in] key_type PSA key type * \param[in,out] key_bits Size of the key in bits. The value provided in input * might be updated if necessary. * \param[out] mode Mbed TLS cipher mode * \param[out] cipher_id Mbed TLS cipher algorithm identifier * * \return On success \c PSA_SUCCESS is returned and key_bits, mode and cipher_id * are properly updated. * \c PSA_ERROR_NOT_SUPPORTED is returned if the cipher algorithm is not * supported. */ psa_status_t mbedtls_cipher_values_from_psa(psa_algorithm_t alg, psa_key_type_t key_type, size_t *key_bits, mbedtls_cipher_mode_t *mode, mbedtls_cipher_id_t *cipher_id); #if defined(MBEDTLS_CIPHER_C) /** Get Mbed TLS cipher information given the cipher algorithm PSA identifier * as well as the PSA type and size of the key to be used with the cipher * algorithm. * * \param alg PSA cipher algorithm identifier * \param key_type PSA key type * \param key_bits Size of the key in bits * \param[out] cipher_id Mbed TLS cipher algorithm identifier * * \return The Mbed TLS cipher information of the cipher algorithm. * \c NULL if the PSA cipher algorithm is not supported. */ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, mbedtls_cipher_id_t *cipher_id); #endif /* MBEDTLS_CIPHER_C */ /** * \brief Set the key for a multipart symmetric encryption operation. * * \note The signature of this function is that of a PSA driver * cipher_encrypt_setup entry point. This function behaves as a * cipher_encrypt_setup entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation The operation object to set up. It has been * initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_cipher_encrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** * \brief Set the key for a multipart symmetric decryption operation. * * \note The signature of this function is that of a PSA driver * cipher_decrypt_setup entry point. This function behaves as a * cipher_decrypt_setup entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation The operation object to set up. It has been * initialized as per the documentation for * #psa_cipher_operation_t and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_cipher_decrypt_setup( mbedtls_psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set the IV for a symmetric encryption or decryption operation. * * This function sets the IV (initialization vector), nonce * or initial counter value for the encryption or decryption operation. * * \note The signature of this function is that of a PSA driver * cipher_set_iv entry point. This function behaves as a * cipher_set_iv entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active cipher operation. * \param[in] iv Buffer containing the IV to use. * \param[in] iv_length Size of the IV in bytes. It is guaranteed by * the core to be less or equal to * PSA_CIPHER_IV_MAX_SIZE. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_cipher_set_iv( mbedtls_psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length); /** Encrypt or decrypt a message fragment in an active cipher operation. * * \note The signature of this function is that of a PSA driver * cipher_update entry point. This function behaves as a * cipher_update entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active cipher operation. * \param[in] input Buffer containing the message fragment to * encrypt or decrypt. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_cipher_update( mbedtls_psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Finish encrypting or decrypting a message in a cipher operation. * * \note The signature of this function is that of a PSA driver * cipher_finish entry point. This function behaves as a * cipher_finish entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active cipher operation. * \param[out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_cipher_finish( mbedtls_psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); /** Abort a cipher operation. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation. * * \note The signature of this function is that of a PSA driver * cipher_abort entry point. This function behaves as a * cipher_abort entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Initialized cipher operation. * * \retval #PSA_SUCCESS \emptydescription */ psa_status_t mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t *operation); /** Encrypt a message using a symmetric cipher. * * \note The signature of this function is that of a PSA driver * cipher_encrypt entry point. This function behaves as a * cipher_encrypt entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] iv Buffer containing the IV for encryption. The * IV has been generated by the core. * \param[in] iv_length Size of the \p iv in bytes. * \param[in] input Buffer containing the message to encrypt. * \param[in] input_length Size of the \p input buffer in bytes. * \param[in,out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes that make up * the returned output. Initialized to zero * by the core. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size \p iv_length is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. */ psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *iv, size_t iv_length, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); /** Decrypt a message using a symmetric cipher. * * \note The signature of this function is that of a PSA driver * cipher_decrypt entry point. This function behaves as a * cipher_decrypt entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg The cipher algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_CIPHER(\p alg) is true). * \param[in] input Buffer containing the iv and the ciphertext. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param[in] output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes that make up * the returned output. Initialized to zero * by the core. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. * The total input size passed to this operation is not valid for * this particular algorithm. For example, the algorithm is a based * on block cipher and requires a whole number of blocks, but the * total input size is not a multiple of the block size. * \retval #PSA_ERROR_INVALID_PADDING * This is a decryption operation for an algorithm that includes * padding, and the ciphertext does not contain valid padding. */ psa_status_t mbedtls_psa_cipher_decrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length); #endif /* PSA_CRYPTO_CIPHER_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_client.c000066400000000000000000000006621464416617300252250ustar00rootroot00000000000000/* * PSA crypto client code */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #include "psa/crypto.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include #include "mbedtls/platform.h" void psa_reset_key_attributes(psa_key_attributes_t *attributes) { memset(attributes, 0, sizeof(*attributes)); } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_core.h000066400000000000000000001237131464416617300247070ustar00rootroot00000000000000/* * PSA crypto core internal interfaces */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CORE_H #define PSA_CRYPTO_CORE_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #include "psa/crypto.h" #include "psa/crypto_se_driver.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif /** * Tell if PSA is ready for this hash. * * \note For now, only checks the state of the driver subsystem, * not the algorithm. Might do more in the future. * * \param hash_alg The hash algorithm (ignored for now). * * \return 1 if the driver subsytem is ready, 0 otherwise. */ int psa_can_do_hash(psa_algorithm_t hash_alg); /** * Tell if PSA is ready for this cipher. * * \note For now, only checks the state of the driver subsystem, * not the algorithm. Might do more in the future. * * \param cipher_alg The cipher algorithm (ignored for now). * * \return 1 if the driver subsytem is ready, 0 otherwise. */ int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg); typedef enum { PSA_SLOT_EMPTY = 0, PSA_SLOT_FILLING, PSA_SLOT_FULL, PSA_SLOT_PENDING_DELETION, } psa_key_slot_state_t; /** The data structure representing a key slot, containing key material * and metadata for one key. */ typedef struct { psa_key_attributes_t attr; /* * The current state of the key slot, as described in * docs/architecture/psa-thread-safety/psa-thread-safety.md. * * Library functions can modify the state of a key slot by calling * psa_key_slot_state_transition. * * The state variable is used to help determine whether library functions * which operate on the slot succeed. For example, psa_finish_key_creation, * which transfers the state of a slot from PSA_SLOT_FILLING to * PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED * if the state of the slot is not PSA_SLOT_FILLING. * * Library functions which traverse the array of key slots only consider * slots that are in a suitable state for the function. * For example, psa_get_and_lock_key_slot_in_memory, which finds a slot * containing a given key ID, will only check slots whose state variable is * PSA_SLOT_FULL. */ psa_key_slot_state_t state; /* * Number of functions registered as reading the material in the key slot. * * Library functions must not write directly to registered_readers * * A function must call psa_register_read(slot) before reading the current * contents of the slot for an operation. * They then must call psa_unregister_read(slot) once they have finished * reading the current contents of the slot. If the key slot mutex is not * held (when mutexes are enabled), this call must be done via a call to * psa_unregister_read_under_mutex(slot). * A function must call psa_key_slot_has_readers(slot) to check if * the slot is in use for reading. * * This counter is used to prevent resetting the key slot while the library * may access it. For example, such control is needed in the following * scenarios: * . In case of key slot starvation, all key slots contain the description * of a key, and the library asks for the description of a persistent * key not present in the key slots, the key slots currently accessed by * the library cannot be reclaimed to free a key slot to load the * persistent key. * . In case of a multi-threaded application where one thread asks to close * or purge or destroy a key while it is in use by the library through * another thread. */ size_t registered_readers; /* Dynamically allocated key data buffer. * Format as specified in psa_export_key(). */ struct key_data { uint8_t *data; size_t bytes; } key; } psa_key_slot_t; #if defined(MBEDTLS_THREADING_C) /** Perform a mutex operation and return immediately upon failure. * * Returns PSA_ERROR_SERVICE_FAILURE if the operation fails * and status was PSA_SUCCESS. * * Assumptions: * psa_status_t status exists. * f is a mutex operation which returns 0 upon success. */ #define PSA_THREADING_CHK_RET(f) \ do \ { \ if ((f) != 0) { \ if (status == PSA_SUCCESS) { \ return PSA_ERROR_SERVICE_FAILURE; \ } \ return status; \ } \ } while (0); /** Perform a mutex operation and goto exit on failure. * * Sets status to PSA_ERROR_SERVICE_FAILURE if status was PSA_SUCCESS. * * Assumptions: * psa_status_t status exists. * Label exit: exists. * f is a mutex operation which returns 0 upon success. */ #define PSA_THREADING_CHK_GOTO_EXIT(f) \ do \ { \ if ((f) != 0) { \ if (status == PSA_SUCCESS) { \ status = PSA_ERROR_SERVICE_FAILURE; \ } \ goto exit; \ } \ } while (0); #endif /** Test whether a key slot has any registered readers. * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in] slot The key slot to test. * * \return 1 if the slot has any registered readers, 0 otherwise. */ static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot) { return slot->registered_readers > 0; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** Get the SE slot number of a key from the key slot storing its description. * * \param[in] slot The key slot to query. This must be a key slot storing * the description of a key of a dynamically registered * secure element, otherwise the behaviour is undefined. */ static inline psa_key_slot_number_t psa_key_slot_get_slot_number( const psa_key_slot_t *slot) { return *((psa_key_slot_number_t *) (slot->key.data)); } #endif /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. * Sets the slot's state to PSA_SLOT_EMPTY. * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in,out] slot The key slot to wipe. * * \retval #PSA_SUCCESS * The slot has been successfully wiped. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and * the amount of registered readers was not equal to 1. Or, * the slot's state was PSA_SLOT_EMPTY. Or, * the slot's state was PSA_SLOT_FILLING, and the amount * of registered readers was not equal to 0. */ psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot); /** Try to allocate a buffer to an empty key slot. * * \param[in,out] slot Key slot to attach buffer to. * \param[in] buffer_length Requested size of the buffer. * * \retval #PSA_SUCCESS * The buffer has been successfully allocated. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Not enough memory was available for allocation. * \retval #PSA_ERROR_ALREADY_EXISTS * Trying to allocate a buffer to a non-empty key slot. */ psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, size_t buffer_length); /** Wipe key data from a slot. Preserves metadata such as the policy. */ psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot); /** Copy key data (in export format) into an empty key slot. * * This function assumes that the slot does not contain * any key material yet. On failure, the slot content is unchanged. * * \param[in,out] slot Key slot to copy the key into. * \param[in] data Buffer containing the key material. * \param data_length Size of the key buffer. * * \retval #PSA_SUCCESS * The key has been copied successfully. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * Not enough memory was available for allocation of the * copy buffer. * \retval #PSA_ERROR_ALREADY_EXISTS * There was other key material already present in the slot. */ psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot, const uint8_t *data, size_t data_length); /** Convert an Mbed TLS error code to a PSA error code * * \note This function is provided solely for the convenience of * Mbed TLS and may be removed at any time without notice. * * \param ret An Mbed TLS-thrown error code * * \return The corresponding PSA error code */ psa_status_t mbedtls_to_psa_error(int ret); /** Import a key in binary format. * * \note The signature of this function is that of a PSA driver * import_key entry point. This function behaves as an import_key * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer to contain the key data in output * format upon successful return. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS The key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t psa_import_key_into_slot( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); /** Export a key in binary format * * \note The signature of this function is that of a PSA driver export_key * entry point. This function behaves as an export_key entry point as * defined in the PSA driver interface specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_export_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** Export a public key or the public part of a key pair in binary format. * * \note The signature of this function is that of a PSA driver * export_public_key entry point. This function behaves as an * export_public_key entry point as defined in the PSA driver interface * specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The public key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_export_public_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** Whether a key production parameters structure is the default. * * Calls to a key generation driver with non-default production parameters * require a driver supporting custom production parameters. * * \param[in] params The key production parameters to check. * \param params_data_length Size of `params->data` in bytes. */ int psa_key_production_parameters_are_default( const psa_key_production_parameters_t *params, size_t params_data_length); /** * \brief Generate a key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the key to generate. * \param[in] params The production parameters from * psa_generate_key_ext(). * \param params_data_length The size of `params->data` in bytes. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was generated successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED * Key size in bits or type not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign a message with a private key. For hash-and-sign algorithms, * this includes the hashing step. * * \note The signature of this function is that of a PSA driver * sign_message entry point. This function behaves as a sign_message * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \note This function will call the driver for psa_sign_hash * and go through driver dispatch again. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] input The input message to sign. * \param[in] input_length Size of the \p input buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of the key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t psa_sign_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** Verify the signature of a message with a public key, using * a hash-and-sign verification algorithm. * * \note The signature of this function is that of a PSA driver * verify_message entry point. This function behaves as a verify_message * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \note This function will call the driver for psa_verify_hash * and go through driver dispatch again. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] input The message whose signature is to be verified. * \param[in] input_length Size of the \p input buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_verify_message_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length); /** Sign an already-calculated hash with a private key. * * \note The signature of this function is that of a PSA driver * sign_hash entry point. This function behaves as a sign_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash or message to sign. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of the key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t psa_sign_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify the signature a hash or short message using a public key. * * \note The signature of this function is that of a PSA driver * verify_hash entry point. This function behaves as a verify_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash or message whose signature is to be * verified. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t psa_verify_hash_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Validate the key bit size for unstructured keys. * * \note Check that the bit size is acceptable for a given key type for * unstructured keys. * * \param[in] type The key type * \param[in] bits The number of bits of the key * * \retval #PSA_SUCCESS * The key type and size are valid. * \retval #PSA_ERROR_INVALID_ARGUMENT * The size in bits of the key is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED * The type and/or the size in bits of the key or the combination of * the two is not supported. */ psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type, size_t bits); /** Perform a key agreement and return the raw shared secret, using built-in raw key agreement functions. * * \note The signature of this function is that of a PSA driver * key_agreement entry point. This function behaves as a key_agreement * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the private key * context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in * bytes. * \param[in] alg A key agreement algorithm that is * compatible with the type of the key. * \param[in] peer_key The buffer containing the key context * of the peer's public key. * \param[in] peer_key_length Size of the \p peer_key buffer in * bytes. * \param[out] shared_secret The buffer to which the shared secret * is to be written. * \param[in] shared_secret_size Size of the \p shared_secret buffer in * bytes. * \param[out] shared_secret_length On success, the number of bytes that make * up the returned shared secret. * \retval #PSA_SUCCESS * Success. Shared secret successfully calculated. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a key agreement algorithm, or * \p private_key is not compatible with \p alg, * or \p peer_key is not valid for \p alg or not compatible with * \p private_key. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p shared_secret_size is too small * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_BAD_STATE \emptydescription */ psa_status_t psa_key_agreement_raw_builtin( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length); /** * \brief Set the maximum number of ops allowed to be executed by an * interruptible function in a single call. * * \note The signature of this function is that of a PSA driver * interruptible_set_max_ops entry point. This function behaves as an * interruptible_set_max_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in] max_ops The maximum number of ops to be executed in a * single call, this can be a number from 0 to * #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0 * is obviously the least amount of work done per * call. */ void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops); /** * \brief Get the maximum number of ops allowed to be executed by an * interruptible function in a single call. * * \note The signature of this function is that of a PSA driver * interruptible_get_max_ops entry point. This function behaves as an * interruptible_get_max_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \return Maximum number of ops allowed to be executed * by an interruptible function in a single call. */ uint32_t mbedtls_psa_interruptible_get_max_ops(void); /** * \brief Get the number of ops that a hash signing operation has taken for the * previous call. If no call or work has taken place, this will return * zero. * * \note The signature of this function is that of a PSA driver * sign_hash_get_num_ops entry point. This function behaves as an * sign_hash_get_num_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \return Number of ops that were completed * in the last call to \c * mbedtls_psa_sign_hash_complete(). */ uint32_t mbedtls_psa_sign_hash_get_num_ops( const mbedtls_psa_sign_hash_interruptible_operation_t *operation); /** * \brief Get the number of ops that a hash verification operation has taken for * the previous call. If no call or work has taken place, this will * return zero. * * \note The signature of this function is that of a PSA driver * verify_hash_get_num_ops entry point. This function behaves as an * verify_hash_get_num_ops entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param operation The \c * mbedtls_psa_verify_hash_interruptible_operation_t * to use. This must be initialized first. * * \return Number of ops that were completed * in the last call to \c * mbedtls_psa_verify_hash_complete(). */ uint32_t mbedtls_psa_verify_hash_get_num_ops( const mbedtls_psa_verify_hash_interruptible_operation_t *operation); /** * \brief Start signing a hash or short message with a private key, in an * interruptible manner. * * \note The signature of this function is that of a PSA driver * sign_hash_start entry point. This function behaves as a * sign_hash_start entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash or message to sign. * \param hash_length Size of the \p hash buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - call \c psa_sign_hash_complete() * with the same context to complete the operation * \retval #PSA_ERROR_INVALID_ARGUMENT * An unsupported, incorrectly formatted or incorrect type of key was * used. * \retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations * are currently supported, or the key type is currently unsupported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There was insufficient memory to load the key representation. */ psa_status_t mbedtls_psa_sign_hash_start( mbedtls_psa_sign_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length); /** * \brief Continue and eventually complete the action of signing a hash or * short message with a private key, in an interruptible manner. * * \note The signature of this function is that of a PSA driver * sign_hash_complete entry point. This function behaves as a * sign_hash_complete entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \param[out] signature Buffer where the signature is to be written. * \param signature_size Size of the \p signature buffer in bytes. This * must be appropriate for the selected * algorithm and key. * \param[out] signature_length On success, the number of bytes that make up * the returned signature value. * * \retval #PSA_SUCCESS * Operation completed successfully * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(), there is still work to be done, * please call this function again with the same operation object. * * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t mbedtls_psa_sign_hash_complete( mbedtls_psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Abort a sign hash operation. * * \note The signature of this function is that of a PSA driver sign_hash_abort * entry point. This function behaves as a sign_hash_abort entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to abort. * * \retval #PSA_SUCCESS * The operation was aborted successfully. */ psa_status_t mbedtls_psa_sign_hash_abort( mbedtls_psa_sign_hash_interruptible_operation_t *operation); /** * \brief Start reading and verifying a hash or short message, in an * interruptible manner. * * \note The signature of this function is that of a PSA driver * verify_hash_start entry point. This function behaves as a * verify_hash_start entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_verify_hash_interruptible_operation_t * to use. This must be initialized first. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * the type of the key. * \param[in] hash The hash whose signature is to be verified. * \param hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The operation started successfully - call \c psa_sign_hash_complete() * with the same context to complete the operation * \retval #PSA_ERROR_INVALID_ARGUMENT * An unsupported or incorrect type of key was used. * \retval #PSA_ERROR_NOT_SUPPORTED * Either no internal interruptible operations are currently supported, * or the key type is currently unsupported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There was insufficient memory either to load the key representation, * or to prepare the operation. */ psa_status_t mbedtls_psa_verify_hash_start( mbedtls_psa_verify_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Continue and eventually complete the action of signing a hash or * short message with a private key, in an interruptible manner. * * \note The signature of this function is that of a PSA driver * sign_hash_complete entry point. This function behaves as a * sign_hash_complete entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_sign_hash_interruptible_operation_t * to use. This must be initialized first. * * \retval #PSA_SUCCESS * Operation completed successfully, and the passed signature is valid. * * \retval #PSA_OPERATION_INCOMPLETE * Operation was interrupted due to the setting of \c * psa_interruptible_set_max_ops(), there is still work to be done, * please call this function again with the same operation object. * * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_verify_hash_complete( mbedtls_psa_verify_hash_interruptible_operation_t *operation); /** * \brief Abort a verify signed hash operation. * * \note The signature of this function is that of a PSA driver * verify_hash_abort entry point. This function behaves as a * verify_hash_abort entry point as defined in the PSA driver interface * specification for transparent drivers. * * \param[in] operation The \c * mbedtls_psa_verify_hash_interruptible_operation_t * to abort. * * \retval #PSA_SUCCESS * The operation was aborted successfully. */ psa_status_t mbedtls_psa_verify_hash_abort( mbedtls_psa_verify_hash_interruptible_operation_t *operation); typedef struct psa_crypto_local_input_s { uint8_t *buffer; size_t length; } psa_crypto_local_input_t; #define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 }) /** Allocate a local copy of an input buffer and copy the contents into it. * * \param[in] input Pointer to input buffer. * \param[in] input_len Length of the input buffer. * \param[out] local_input Pointer to a psa_crypto_local_input_t struct * containing a local input copy. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of * the buffer cannot be allocated. */ psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len, psa_crypto_local_input_t *local_input); /** Free a local copy of an input buffer. * * \param[in] local_input Pointer to a psa_crypto_local_input_t struct * populated by a previous call to * psa_crypto_local_input_alloc(). */ void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input); typedef struct psa_crypto_local_output_s { uint8_t *original; uint8_t *buffer; size_t length; } psa_crypto_local_output_t; #define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 }) /** Allocate a local copy of an output buffer. * * \note This does not copy any data from the original * output buffer but only allocates a buffer * whose contents will be copied back to the * original in a future call to * psa_crypto_local_output_free(). * * \param[in] output Pointer to output buffer. * \param[in] output_len Length of the output buffer. * \param[out] local_output Pointer to a psa_crypto_local_output_t struct to * populate with the local output copy. * \return #PSA_SUCCESS, if the buffer was successfully * copied. * \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of * the buffer cannot be allocated. */ psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len, psa_crypto_local_output_t *local_output); /** Copy from a local copy of an output buffer back to the original, then * free the local copy. * * \param[in] local_output Pointer to a psa_crypto_local_output_t struct * populated by a previous call to * psa_crypto_local_output_alloc(). * \return #PSA_SUCCESS, if the local output was * successfully copied back to the original. * \return #PSA_ERROR_CORRUPTION_DETECTED, if the output * could not be copied back to the original. */ psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output); #endif /* PSA_CRYPTO_CORE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_core_common.h000066400000000000000000000033521464416617300262530ustar00rootroot00000000000000/** * \file psa_crypto_core_common.h * * \brief Utility macros for internal use in the PSA cryptography core. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_CORE_COMMON_H #define PSA_CRYPTO_CORE_COMMON_H /** Return an offset into a buffer. * * This is just the addition of an offset to a pointer, except that this * function also accepts an offset of 0 into a buffer whose pointer is null. * (`p + n` has undefined behavior when `p` is null, even when `n == 0`. * A null pointer is a valid buffer pointer when the size is 0, for example * as the result of `malloc(0)` on some platforms.) * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline unsigned char *psa_crypto_buffer_offset( unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } /** Return an offset into a read-only buffer. * * Similar to mbedtls_buffer_offset(), but for const pointers. * * \param p Pointer to a buffer of at least n bytes. * This may be \p NULL if \p n is zero. * \param n An offset in bytes. * \return Pointer to offset \p n in the buffer \p p. * Note that this is only a valid pointer if the size of the * buffer is at least \p n + 1. */ static inline const unsigned char *psa_crypto_buffer_offset_const( const unsigned char *p, size_t n) { return p == NULL ? NULL : p + n; } #endif /* PSA_CRYPTO_CORE_COMMON_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers.h000066400000000000000000003230111464416617300271660ustar00rootroot00000000000000/* * Functions to delegate cryptographic operations to an available * and appropriate accelerator. * Warning: This file is now auto-generated. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* BEGIN-common headers */ #include "common.h" #include "psa_crypto_aead.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_pake.h" #include "psa_crypto_rsa.h" #include "mbedtls/platform.h" #include "mbedtls/constant_time.h" /* END-common headers */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* BEGIN-driver headers */ /* Headers for mbedtls_test opaque driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for mbedtls_test transparent driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for p256 transparent driver */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" #endif /* END-driver headers */ /* Auto-generated values depending on which drivers are registered. * ID 0 is reserved for unallocated operations. * ID 1 is reserved for the Mbed TLS software driver. */ /* BEGIN-driver id definition */ #define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) #define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) #define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) #define P256_TRANSPARENT_DRIVER_ID (4) /* END-driver id */ /* BEGIN-Common Macro definitions */ /* END-Common Macro definitions */ /* Support the 'old' SE interface when asked to */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style * SE driver is present, to avoid unused argument errors at compile time. */ #ifndef PSA_CRYPTO_DRIVER_PRESENT #define PSA_CRYPTO_DRIVER_PRESENT #endif #include "psa_crypto_se.h" #endif static inline psa_status_t psa_driver_wrapper_init( void ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) status = psa_init_all_se_drivers( ); if( status != PSA_SUCCESS ) return( status ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_init( ); if( status != PSA_SUCCESS ) return( status ); status = mbedtls_test_opaque_init( ); if( status != PSA_SUCCESS ) return( status ); #endif (void) status; return( PSA_SUCCESS ); } static inline void psa_driver_wrapper_free( void ) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Unregister all secure element drivers, so that we restart from * a pristine state. */ psa_unregister_all_se_drivers( ); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(PSA_CRYPTO_DRIVER_TEST) mbedtls_test_transparent_free( ); mbedtls_test_opaque_free( ); #endif } /* Start delegation functions */ static inline psa_status_t psa_driver_wrapper_sign_message( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *signature, size_t signature_size, size_t *signature_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_sign_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_size, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ break; /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_signature_sign_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_size, signature_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; break; } return( psa_sign_message_builtin( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_size, signature_length ) ); } static inline psa_status_t psa_driver_wrapper_verify_message( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *signature, size_t signature_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_verify_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ break; /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_signature_verify_message( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_length ) ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; break; } return( psa_verify_message_builtin( attributes, key_buffer, key_buffer_size, alg, input, input_length, signature, signature_length ) ); } static inline psa_status_t psa_driver_wrapper_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length ) { /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( drv->asymmetric == NULL || drv->asymmetric->p_sign == NULL ) { /* Key is defined in SE, but we have no way to exercise it */ return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->asymmetric->p_sign( drv_context, *( (psa_key_slot_number_t *)key_buffer ), alg, hash, hash_length, signature, signature_size, signature_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( psa_sign_hash_builtin( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_signature_sign_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_size, signature_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length ) { /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( drv->asymmetric == NULL || drv->asymmetric->p_verify == NULL ) { /* Key is defined in SE, but we have no way to exercise it */ return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->asymmetric->p_verify( drv_context, *( (psa_key_slot_number_t *)key_buffer ), alg, hash, hash_length, signature, signature_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_signature_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) && PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ return( psa_verify_hash_builtin( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_signature_verify_hash( attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline uint32_t psa_driver_wrapper_sign_hash_get_num_ops( psa_sign_hash_interruptible_operation_t *operation ) { switch( operation->id ) { /* If uninitialised, return 0, as no work can have been done. */ case 0: return 0; case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return(mbedtls_psa_sign_hash_get_num_ops(&operation->ctx.mbedtls_ctx)); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } /* Can't happen (see discussion in #8271) */ return 0; } static inline uint32_t psa_driver_wrapper_verify_hash_get_num_ops( psa_verify_hash_interruptible_operation_t *operation ) { switch( operation->id ) { /* If uninitialised, return 0, as no work can have been done. */ case 0: return 0; case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return (mbedtls_psa_verify_hash_get_num_ops(&operation->ctx.mbedtls_ctx)); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } /* Can't happen (see discussion in #8271) */ return 0; } static inline psa_status_t psa_driver_wrapper_sign_hash_start( psa_sign_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ /* Declared with fallback == true */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_sign_hash_start( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg, hash, hash_length ); break; /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } return( status ); } static inline psa_status_t psa_driver_wrapper_sign_hash_complete( psa_sign_hash_interruptible_operation_t *operation, uint8_t *signature, size_t signature_size, size_t *signature_length ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_sign_hash_complete( &operation->ctx.mbedtls_ctx, signature, signature_size, signature_length ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } ( void ) signature; ( void ) signature_size; ( void ) signature_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_sign_hash_abort( psa_sign_hash_interruptible_operation_t *operation ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_sign_hash_abort( &operation->ctx.mbedtls_ctx ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_verify_hash_start( psa_verify_hash_interruptible_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ /* Declared with fallback == true */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_verify_hash_start( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length ); break; /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } return( status ); } static inline psa_status_t psa_driver_wrapper_verify_hash_complete( psa_verify_hash_interruptible_operation_t *operation ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_verify_hash_complete( &operation->ctx.mbedtls_ctx ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_verify_hash_abort( psa_verify_hash_interruptible_operation_t *operation ) { switch( operation->id ) { case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_verify_hash_abort( &operation->ctx.mbedtls_ctx ) ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) /* Add test driver tests here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } /** Calculate the key buffer size required to store the key material of a key * associated with an opaque driver from input key data. * * \param[in] attributes The key attributes * \param[in] data The input key data. * \param[in] data_length The input data length. * \param[out] key_buffer_size Minimum buffer size to contain the key material. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription */ static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, size_t *key_buffer_size ) { psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); psa_key_type_t key_type = psa_get_key_type(attributes); *key_buffer_size = 0; switch( location ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: *key_buffer_size = mbedtls_test_opaque_size_function( key_type, PSA_BYTES_TO_BITS( data_length ) ); return( ( *key_buffer_size != 0 ) ? PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: (void)key_type; (void)data; (void)data_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); #if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) int is_default_production = psa_key_production_parameters_are_default(params, params_data_length); if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production ) { /* We don't support passing custom production parameters * to drivers yet. */ return PSA_ERROR_NOT_SUPPORTED; } #else int is_default_production = 1; (void) is_default_production; #endif /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { size_t pubkey_length = 0; /* We don't support this feature yet */ if( drv->key_management == NULL || drv->key_management->p_generate == NULL ) { /* Key is defined as being in SE, but we have no way to generate it */ return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_generate( drv_context, *( (psa_key_slot_number_t *)key_buffer ), attributes, NULL, 0, &pubkey_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) /* Transparent drivers are limited to generating asymmetric keys. */ /* We don't support passing custom production parameters * to drivers yet. */ if( PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type(attributes) ) && is_default_production ) { /* Cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_generate_key( attributes, key_buffer, key_buffer_size, key_buffer_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && psa_get_key_type(attributes) == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_generate_key( attributes, key_buffer, key_buffer_size, key_buffer_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) break; } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ } #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Software fallback */ status = psa_generate_key_internal( attributes, params, params_data_length, key_buffer, key_buffer_size, key_buffer_length ); break; /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_generate_key( attributes, key_buffer, key_buffer_size, key_buffer_length ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } return( status ); } static inline psa_status_t psa_driver_wrapper_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( drv->key_management == NULL || drv->key_management->p_import == NULL ) return( PSA_ERROR_NOT_SUPPORTED ); /* The driver should set the number of key bits, however in * case it doesn't, we initialize bits to an invalid value. */ *bits = PSA_MAX_KEY_BITS + 1; status = drv->key_management->p_import( drv_context, *( (psa_key_slot_number_t *)key_buffer ), attributes, data, data_length, bits ); if( status != PSA_SUCCESS ) return( status ); if( (*bits) > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); return( PSA_SUCCESS ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) status = mbedtls_test_transparent_import_key (attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) status = p256_transparent_import_key (attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( psa_import_key_into_slot( attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_import_key (attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, bits )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_export_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export == NULL ) ) { return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_export( drv_context, *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: return( psa_export_key_internal( attributes, key_buffer, key_buffer_size, data, data_size, data_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_export_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ return( status ); } } static inline psa_status_t psa_driver_wrapper_copy_key( psa_key_attributes_t *attributes, const uint8_t *source_key, size_t source_key_length, uint8_t *target_key_buffer, size_t target_key_buffer_size, size_t *target_key_buffer_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { /* Copying to a secure element is not implemented yet. */ return( PSA_ERROR_NOT_SUPPORTED ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_copy_key (attributes, source_key, source_key_length, target_key_buffer, target_key_buffer_size, target_key_buffer_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void)source_key; (void)source_key_length; (void)target_key_buffer; (void)target_key_buffer_size; (void)target_key_buffer_length; status = PSA_ERROR_INVALID_ARGUMENT; } return( status ); } /* * Cipher functions */ static inline psa_status_t psa_driver_wrapper_cipher_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *iv, size_t iv_length, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_encrypt( attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) return( mbedtls_psa_cipher_encrypt( attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length ) ); #else return( PSA_ERROR_NOT_SUPPORTED ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_cipher_encrypt( attributes, key_buffer, key_buffer_size, alg, iv, iv_length, input, input_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)iv; (void)iv_length; (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) return( mbedtls_psa_cipher_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length ) ); #else return( PSA_ERROR_NOT_SUPPORTED ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_cipher_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_encrypt_setup( psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_encrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_cipher_encrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_cipher_encrypt_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)operation; (void)key_buffer; (void)key_buffer_size; (void)alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_decrypt_setup( psa_cipher_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_cipher_decrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_cipher_decrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; return( status ); #else /* MBEDTLS_PSA_BUILTIN_CIPHER */ return( PSA_ERROR_NOT_SUPPORTED ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_cipher_decrypt_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)operation; (void)key_buffer; (void)key_buffer_size; (void)alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_cipher_set_iv( psa_cipher_operation_t *operation, const uint8_t *iv, size_t iv_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_set_iv( &operation->ctx.mbedtls_ctx, iv, iv_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_cipher_set_iv( &operation->ctx.transparent_test_driver_ctx, iv, iv_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_cipher_set_iv( &operation->ctx.opaque_test_driver_ctx, iv, iv_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)iv; (void)iv_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_cipher_update( psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_update( &operation->ctx.mbedtls_ctx, input, input_length, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_cipher_update( &operation->ctx.transparent_test_driver_ctx, input, input_length, output, output_size, output_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_cipher_update( &operation->ctx.opaque_test_driver_ctx, input, input_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_cipher_finish( psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_finish( &operation->ctx.mbedtls_ctx, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_cipher_finish( &operation->ctx.transparent_test_driver_ctx, output, output_size, output_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_cipher_finish( &operation->ctx.opaque_test_driver_ctx, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_cipher_abort( psa_cipher_operation_t *operation ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_CIPHER) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_cipher_abort( &operation->ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: status = mbedtls_test_transparent_cipher_abort( &operation->ctx.transparent_test_driver_ctx ); mbedtls_platform_zeroize( &operation->ctx.transparent_test_driver_ctx, sizeof( operation->ctx.transparent_test_driver_ctx ) ); return( status ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: status = mbedtls_test_opaque_cipher_abort( &operation->ctx.opaque_test_driver_ctx ); mbedtls_platform_zeroize( &operation->ctx.opaque_test_driver_ctx, sizeof( operation->ctx.opaque_test_driver_ctx ) ); return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } /* * Hashing functions */ static inline psa_status_t psa_driver_wrapper_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Try accelerators first */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_hash_compute( alg, input, input_length, hash, hash_size, hash_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* If software fallback is compiled in, try fallback */ #if defined(MBEDTLS_PSA_BUILTIN_HASH) status = mbedtls_psa_hash_compute( alg, input, input_length, hash, hash_size, hash_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif (void) status; (void) alg; (void) input; (void) input_length; (void) hash; (void) hash_size; (void) hash_length; return( PSA_ERROR_NOT_SUPPORTED ); } static inline psa_status_t psa_driver_wrapper_hash_setup( psa_hash_operation_t *operation, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Try setup on accelerators first */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_hash_setup( &operation->ctx.test_driver_ctx, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* If software fallback is compiled in, try fallback */ #if defined(MBEDTLS_PSA_BUILTIN_HASH) status = mbedtls_psa_hash_setup( &operation->ctx.mbedtls_ctx, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* Nothing left to try if we fall through here */ (void) status; (void) operation; (void) alg; return( PSA_ERROR_NOT_SUPPORTED ); } static inline psa_status_t psa_driver_wrapper_hash_clone( const psa_hash_operation_t *source_operation, psa_hash_operation_t *target_operation ) { switch( source_operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; return( mbedtls_psa_hash_clone( &source_operation->ctx.mbedtls_ctx, &target_operation->ctx.mbedtls_ctx ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: target_operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; return( mbedtls_test_transparent_hash_clone( &source_operation->ctx.test_driver_ctx, &target_operation->ctx.test_driver_ctx ) ); #endif default: (void) target_operation; return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_hash_update( psa_hash_operation_t *operation, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_hash_update( &operation->ctx.mbedtls_ctx, input, input_length ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_hash_update( &operation->ctx.test_driver_ctx, input, input_length ) ); #endif default: (void) input; (void) input_length; return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_hash_finish( psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_hash_finish( &operation->ctx.mbedtls_ctx, hash, hash_size, hash_length ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_hash_finish( &operation->ctx.test_driver_ctx, hash, hash_size, hash_length ) ); #endif default: (void) hash; (void) hash_size; (void) hash_length; return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_hash_abort( psa_hash_operation_t *operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_HASH) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_hash_abort( &operation->ctx.mbedtls_ctx ) ); #endif #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_hash_abort( &operation->ctx.test_driver_ctx ) ); #endif default: return( PSA_ERROR_BAD_STATE ); } } static inline psa_status_t psa_driver_wrapper_aead_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *plaintext, size_t plaintext_length, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_aead_encrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( mbedtls_psa_aead_encrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, plaintext, plaintext_length, ciphertext, ciphertext_size, ciphertext_length ) ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, const uint8_t *additional_data, size_t additional_data_length, const uint8_t *ciphertext, size_t ciphertext_length, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_aead_decrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( mbedtls_psa_aead_decrypt( attributes, key_buffer, key_buffer_size, alg, nonce, nonce_length, additional_data, additional_data_length, ciphertext, ciphertext_length, plaintext, plaintext_size, plaintext_length ) ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_encrypt_setup( psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; status = mbedtls_test_transparent_aead_encrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_aead_encrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); return( status ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_decrypt_setup( psa_aead_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; status = mbedtls_test_transparent_aead_decrypt_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; status = mbedtls_psa_aead_decrypt_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); return( status ); /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_aead_set_nonce( psa_aead_operation_t *operation, const uint8_t *nonce, size_t nonce_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx, nonce, nonce_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_set_nonce( &operation->ctx.transparent_test_driver_ctx, nonce, nonce_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)nonce; (void)nonce_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_set_lengths( psa_aead_operation_t *operation, size_t ad_length, size_t plaintext_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx, ad_length, plaintext_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_set_lengths( &operation->ctx.transparent_test_driver_ctx, ad_length, plaintext_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)ad_length; (void)plaintext_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_update_ad( psa_aead_operation_t *operation, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx, input, input_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_update_ad( &operation->ctx.transparent_test_driver_ctx, input, input_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)input; (void)input_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_update( psa_aead_operation_t *operation, const uint8_t *input, size_t input_length, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx, input, input_length, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_update( &operation->ctx.transparent_test_driver_ctx, input, input_length, output, output_size, output_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)input; (void)input_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_finish( psa_aead_operation_t *operation, uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length, uint8_t *tag, size_t tag_size, size_t *tag_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, ciphertext, ciphertext_size, ciphertext_length, tag, tag_size, tag_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_finish( &operation->ctx.transparent_test_driver_ctx, ciphertext, ciphertext_size, ciphertext_length, tag, tag_size, tag_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)ciphertext; (void)ciphertext_size; (void)ciphertext_length; (void)tag; (void)tag_size; (void)tag_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_verify( psa_aead_operation_t *operation, uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length, const uint8_t *tag, size_t tag_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE]; size_t check_tag_length; status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, plaintext, plaintext_size, plaintext_length, check_tag, sizeof( check_tag ), &check_tag_length ); if( status == PSA_SUCCESS ) { if( tag_length != check_tag_length || mbedtls_ct_memcmp( tag, check_tag, tag_length ) != 0 ) status = PSA_ERROR_INVALID_SIGNATURE; } mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) ); return( status ); } #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_verify( &operation->ctx.transparent_test_driver_ctx, plaintext, plaintext_size, plaintext_length, tag, tag_length ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } (void)plaintext; (void)plaintext_size; (void)plaintext_length; (void)tag; (void)tag_length; return( PSA_ERROR_INVALID_ARGUMENT ); } static inline psa_status_t psa_driver_wrapper_aead_abort( psa_aead_operation_t *operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_AEAD) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_AEAD */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_aead_abort( &operation->ctx.transparent_test_driver_ctx ) ); /* Add cases for opaque driver here */ #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } return( PSA_ERROR_INVALID_ARGUMENT ); } /* * MAC functions */ static inline psa_status_t psa_driver_wrapper_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_mac_compute( attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_mac_compute( attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_mac_compute( attributes, key_buffer, key_buffer_size, alg, input, input_length, mac, mac_size, mac_length ); return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void) key_buffer; (void) key_buffer_size; (void) alg; (void) input; (void) input_length; (void) mac; (void) mac_size; (void) mac_length; (void) status; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_sign_setup( psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_mac_sign_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_mac_sign_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void) status; (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_verify_setup( psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_mac_verify_setup( &operation->ctx.transparent_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_MAC) /* Fell through, meaning no accelerator supports this operation */ status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ return( PSA_ERROR_NOT_SUPPORTED ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: status = mbedtls_test_opaque_mac_verify_setup( &operation->ctx.opaque_test_driver_ctx, attributes, key_buffer, key_buffer_size, alg ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID; return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void) status; (void) operation; (void) key_buffer; (void) key_buffer_size; (void) alg; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_update( psa_mac_operation_t *operation, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx, input, input_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_update( &operation->ctx.transparent_test_driver_ctx, input, input_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_update( &operation->ctx.opaque_test_driver_ctx, input, input_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) input; (void) input_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_sign_finish( psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx, mac, mac_size, mac_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_sign_finish( &operation->ctx.transparent_test_driver_ctx, mac, mac_size, mac_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_sign_finish( &operation->ctx.opaque_test_driver_ctx, mac, mac_size, mac_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) mac; (void) mac_size; (void) mac_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_verify_finish( psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx, mac, mac_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_verify_finish( &operation->ctx.transparent_test_driver_ctx, mac, mac_length ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_verify_finish( &operation->ctx.opaque_test_driver_ctx, mac, mac_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) mac; (void) mac_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_mac_abort( psa_mac_operation_t *operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_MAC) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_MAC */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_mac_abort( &operation->ctx.transparent_test_driver_ctx ) ); case MBEDTLS_TEST_OPAQUE_DRIVER_ID: return( mbedtls_test_opaque_mac_abort( &operation->ctx.opaque_test_driver_ctx ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: return( PSA_ERROR_INVALID_ARGUMENT ); } } /* * Asymmetric cryptography */ static inline psa_status_t psa_driver_wrapper_asymmetric_encrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_asymmetric_encrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ return( mbedtls_psa_asymmetric_encrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_asymmetric_encrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)input; (void)input_length; (void)salt; (void)salt_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_asymmetric_decrypt( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_asymmetric_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ return( mbedtls_psa_asymmetric_decrypt( attributes, key_buffer, key_buffer_size, alg,input, input_length, salt, salt_length, output, output_size, output_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_asymmetric_decrypt( attributes, key_buffer, key_buffer_size, alg, input, input_length, salt, salt_length, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ (void)status; (void)key_buffer; (void)key_buffer_size; (void)alg; (void)input; (void)input_length; (void)salt; (void)salt_length; (void)output; (void)output_size; (void)output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_key_agreement( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_key_agreement( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) && PSA_ALG_IS_ECDH(alg) && PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 && psa_get_key_bits(attributes) == 256 ) { status = p256_transparent_key_agreement( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ); if( status != PSA_ERROR_NOT_SUPPORTED) return( status ); } #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Software Fallback */ status = psa_key_agreement_raw_builtin( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ); return( status ); #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: return( mbedtls_test_opaque_key_agreement( attributes, key_buffer, key_buffer_size, alg, peer_key, peer_key_length, shared_secret, shared_secret_size, shared_secret_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) attributes; (void) key_buffer; (void) key_buffer_size; (void) peer_key; (void) peer_key_length; (void) shared_secret; (void) shared_secret_size; (void) shared_secret_length; return( PSA_ERROR_NOT_SUPPORTED ); } } static inline psa_status_t psa_driver_wrapper_pake_setup( psa_pake_operation_t *operation, const psa_crypto_driver_pake_inputs_t *inputs ) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( &inputs->attributes ) ); switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ status = PSA_ERROR_NOT_SUPPORTED; #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = mbedtls_test_transparent_pake_setup( &operation->data.ctx.transparent_test_driver_ctx, inputs ); if( status == PSA_SUCCESS ) operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID; /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ #if defined(MBEDTLS_PSA_BUILTIN_PAKE) status = mbedtls_psa_pake_setup( &operation->data.ctx.mbedtls_ctx, inputs ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; #endif return status; /* Add cases for opaque driver here */ default: /* Key is declared with a lifetime not known to us */ (void)operation; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_output( psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_output( &operation->data.ctx.mbedtls_ctx, step, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_output( &operation->data.ctx.transparent_test_driver_ctx, step, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) step; (void) output; (void) output_size; (void) output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_input( psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_input( &operation->data.ctx.mbedtls_ctx, step, input, input_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_input( &operation->data.ctx.transparent_test_driver_ctx, step, input, input_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) step; (void) input; (void) input_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_get_implicit_key( psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_get_implicit_key( &operation->data.ctx.mbedtls_ctx, output, output_size, output_length ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_get_implicit_key( &operation->data.ctx.transparent_test_driver_ctx, output, output_size, output_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) output; (void) output_size; (void) output_length; return( PSA_ERROR_INVALID_ARGUMENT ); } } static inline psa_status_t psa_driver_wrapper_pake_abort( psa_pake_operation_t * operation ) { switch( operation->id ) { #if defined(MBEDTLS_PSA_BUILTIN_PAKE) case PSA_CRYPTO_MBED_TLS_DRIVER_ID: return( mbedtls_psa_pake_abort( &operation->data.ctx.mbedtls_ctx ) ); #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID: return( mbedtls_test_transparent_pake_abort( &operation->data.ctx.transparent_test_driver_ctx ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: return( PSA_ERROR_INVALID_ARGUMENT ); } } #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.c000066400000000000000000000202551464416617300312300ustar00rootroot00000000000000/* * Functions to delegate cryptographic operations to an available * and appropriate accelerator. * Warning: This file is now auto-generated. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* BEGIN-common headers */ #include "common.h" #include "psa_crypto_aead.h" #include "psa_crypto_cipher.h" #include "psa_crypto_core.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_hash.h" #include "psa_crypto_mac.h" #include "psa_crypto_pake.h" #include "psa_crypto_rsa.h" #include "mbedtls/platform.h" /* END-common headers */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* BEGIN-driver headers */ /* Headers for mbedtls_test opaque driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for mbedtls_test transparent driver */ #if defined(PSA_CRYPTO_DRIVER_TEST) #include "test/drivers/test_driver.h" #endif /* Headers for p256 transparent driver */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) #include "../3rdparty/p256-m/p256-m_driver_entrypoints.h" #endif /* END-driver headers */ /* Auto-generated values depending on which drivers are registered. * ID 0 is reserved for unallocated operations. * ID 1 is reserved for the Mbed TLS software driver. */ /* BEGIN-driver id definition */ #define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) #define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2) #define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3) #define P256_TRANSPARENT_DRIVER_ID (4) /* END-driver id */ /* BEGIN-Common Macro definitions */ /* END-Common Macro definitions */ /* Support the 'old' SE interface when asked to */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style * SE driver is present, to avoid unused argument errors at compile time. */ #ifndef PSA_CRYPTO_DRIVER_PRESENT #define PSA_CRYPTO_DRIVER_PRESENT #endif #include "psa_crypto_se.h" #endif /** Get the key buffer size required to store the key material of a key * associated with an opaque driver. * * \param[in] attributes The key attributes. * \param[out] key_buffer_size Minimum buffer size to contain the key material * * \retval #PSA_SUCCESS * The minimum size for a buffer to contain the key material has been * returned successfully. * \retval #PSA_ERROR_NOT_SUPPORTED * The type and/or the size in bits of the key or the combination of * the two is not supported. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is declared with a lifetime not known to us. */ psa_status_t psa_driver_wrapper_get_key_buffer_size( const psa_key_attributes_t *attributes, size_t *key_buffer_size ) { psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); psa_key_type_t key_type = psa_get_key_type(attributes); size_t key_bits = psa_get_key_bits(attributes); *key_buffer_size = 0; switch( location ) { #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LOCATION: #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) /* Emulate property 'builtin_key_size' */ if( psa_key_id_is_builtin( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( attributes ) ) ) ) { *key_buffer_size = sizeof( psa_drv_slot_number_t ); return( PSA_SUCCESS ); } #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ *key_buffer_size = mbedtls_test_opaque_size_function( key_type, key_bits ); return( ( *key_buffer_size != 0 ) ? PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_TEST */ default: (void)key_type; (void)key_bits; return( PSA_ERROR_INVALID_ARGUMENT ); } } psa_status_t psa_driver_wrapper_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); /* Try dynamically-registered SE interface first */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) ) { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export_public == NULL ) ) { return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_export_public( drv_context, *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) status = mbedtls_test_transparent_export_public_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) ) status = p256_transparent_export_public_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length ); if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ return( psa_export_public_key_internal( attributes, key_buffer, key_buffer_size, data, data_size, data_length ) ); /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_export_public_key (attributes, key_buffer, key_buffer_size, data, data_size, data_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ return( status ); } } psa_status_t psa_driver_wrapper_get_builtin_key( psa_drv_slot_number_t slot_number, psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) ); switch( location ) { #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if (defined(PSA_CRYPTO_DRIVER_TEST) ) case 0x7fffff: return( mbedtls_test_opaque_get_builtin_key (slot_number, attributes, key_buffer, key_buffer_size, key_buffer_length )); #endif #endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: (void) slot_number; (void) key_buffer; (void) key_buffer_size; (void) key_buffer_length; return( PSA_ERROR_DOES_NOT_EXIST ); } } #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.h000066400000000000000000000017561464416617300312420ustar00rootroot00000000000000/* * Function signatures for functionality that can be provided by * cryptographic accelerators. */ /* Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H #define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H #include "psa/crypto.h" #include "psa/crypto_driver_common.h" psa_status_t psa_driver_wrapper_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); psa_status_t psa_driver_wrapper_get_key_buffer_size( const psa_key_attributes_t *attributes, size_t *key_buffer_size); psa_status_t psa_driver_wrapper_get_builtin_key( psa_drv_slot_number_t slot_number, psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */ /* End of automatically generated file. */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.c000066400000000000000000000472431464416617300245240ustar00rootroot00000000000000/* * PSA ECP layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_ecp.h" #include "psa_crypto_random_impl.h" #include "mbedtls/psa_util.h" #include #include #include "mbedtls/platform.h" #include #include #include #include #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) /* Helper function to verify if the provided EC's family and key bit size are valid. * * Note: "bits" parameter is used both as input and output and it might be updated * in case provided input value is not multiple of 8 ("sloppy" bits). */ static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits) { switch (family) { case PSA_ECC_FAMILY_SECP_R1: switch (*bits) { case 192: case 224: case 256: case 384: case 521: return PSA_SUCCESS; case 528: *bits = 521; return PSA_SUCCESS; } break; case PSA_ECC_FAMILY_BRAINPOOL_P_R1: switch (*bits) { case 256: case 384: case 512: return PSA_SUCCESS; } break; case PSA_ECC_FAMILY_MONTGOMERY: switch (*bits) { case 448: case 255: return PSA_SUCCESS; case 256: *bits = 255; return PSA_SUCCESS; } break; case PSA_ECC_FAMILY_SECP_K1: switch (*bits) { case 192: /* secp224k1 is not and will not be supported in PSA (#3541). */ case 256: return PSA_SUCCESS; } break; } return PSA_ERROR_INVALID_ARGUMENT; } psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, size_t curve_bits, const uint8_t *data, size_t data_length, mbedtls_ecp_keypair **p_ecp) { mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; psa_status_t status; mbedtls_ecp_keypair *ecp = NULL; size_t curve_bytes = data_length; int explicit_bits = (curve_bits != 0); if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) && PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) { /* A Weierstrass public key is represented as: * - The byte 0x04; * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. * So its data length is 2m+1 where m is the curve size in bits. */ if ((data_length & 1) == 0) { return PSA_ERROR_INVALID_ARGUMENT; } curve_bytes = data_length / 2; /* Montgomery public keys are represented in compressed format, meaning * their curve_bytes is equal to the amount of input. */ /* Private keys are represented in uncompressed private random integer * format, meaning their curve_bytes is equal to the amount of input. */ } if (explicit_bits) { /* With an explicit bit-size, the data must have the matching length. */ if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) { return PSA_ERROR_INVALID_ARGUMENT; } } else { /* We need to infer the bit-size from the data. Since the only * information we have is the length in bytes, the value of curve_bits * at this stage is rounded up to the nearest multiple of 8. */ curve_bits = PSA_BYTES_TO_BITS(curve_bytes); } /* Allocate and initialize a key representation. */ ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); if (ecp == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } mbedtls_ecp_keypair_init(ecp); status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits); if (status != PSA_SUCCESS) { goto exit; } /* Load the group. */ grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), curve_bits); if (grp_id == MBEDTLS_ECP_DP_NONE) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = mbedtls_to_psa_error( mbedtls_ecp_group_load(&ecp->grp, grp_id)); if (status != PSA_SUCCESS) { goto exit; } /* Load the key material. */ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { /* Load the public value. */ status = mbedtls_to_psa_error( mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q, data, data_length)); if (status != PSA_SUCCESS) { goto exit; } /* Check that the point is on the curve. */ status = mbedtls_to_psa_error( mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q)); if (status != PSA_SUCCESS) { goto exit; } } else { /* Load and validate the secret value. */ status = mbedtls_to_psa_error( mbedtls_ecp_read_key(ecp->grp.id, ecp, data, data_length)); if (status != PSA_SUCCESS) { goto exit; } } *p_ecp = ecp; exit: if (status != PSA_SUCCESS) { mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); } return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) psa_status_t mbedtls_psa_ecp_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { psa_status_t status; mbedtls_ecp_keypair *ecp = NULL; /* Parse input */ status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, data, data_length, &ecp); if (status != PSA_SUCCESS) { goto exit; } if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) == PSA_ECC_FAMILY_MONTGOMERY) { *bits = ecp->grp.nbits + 1; } else { *bits = ecp->grp.nbits; } /* Re-export the data to PSA export format. There is currently no support * for other input formats then the export format, so this is a 1-1 * copy operation. */ status = mbedtls_psa_ecp_export_key(attributes->type, ecp, key_buffer, key_buffer_size, key_buffer_length); exit: /* Always free the PK object (will also free contained ECP context) */ mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, mbedtls_ecp_keypair *ecp, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { /* Check whether the public part is loaded */ if (mbedtls_ecp_is_zero(&ecp->Q)) { /* Calculate the public key */ status = mbedtls_to_psa_error( mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); if (status != PSA_SUCCESS) { return status; } } status = mbedtls_to_psa_error( mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, data_length, data, data_size)); if (status != PSA_SUCCESS) { memset(data, 0, data_size); } return status; } else { status = mbedtls_to_psa_error( mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size)); return status; } } psa_status_t mbedtls_psa_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; status = mbedtls_psa_ecp_load_representation( attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } status = mbedtls_psa_ecp_export_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)), ecp, data, data_size, data_length); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) psa_status_t mbedtls_psa_ecp_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->type); mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_from_psa(curve, attributes->bits); const mbedtls_ecp_curve_info *curve_info = mbedtls_ecp_curve_info_from_grp_id(grp_id); mbedtls_ecp_keypair ecp; if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } mbedtls_ecp_keypair_init(&ecp); ret = mbedtls_ecp_gen_key(grp_id, &ecp, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { mbedtls_ecp_keypair_free(&ecp); return mbedtls_to_psa_error(ret); } status = mbedtls_to_psa_error( mbedtls_ecp_write_key_ext(&ecp, key_buffer_length, key_buffer, key_buffer_size)); mbedtls_ecp_keypair_free(&ecp); return status; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */ /****************************************************************/ /* ECDSA sign/verify */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) psa_status_t mbedtls_psa_ecdsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t curve_bytes; mbedtls_mpi r, s; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if (signature_size < 2 * curve_bytes) { ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; goto cleanup; } if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext( &ecp->grp, &r, &s, &ecp->d, hash, hash_length, md_alg, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); #else ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; goto cleanup; #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ } else { (void) alg; MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d, hash, hash_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); } MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r, signature, curve_bytes)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s, signature + curve_bytes, curve_bytes)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); if (ret == 0) { *signature_length = 2 * curve_bytes; } mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp) { int ret = 0; /* Check whether the public part is loaded. If not, load it. */ if (mbedtls_ecp_is_zero(&ecp->Q)) { ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); } return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_ecdsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_ecp_keypair *ecp = NULL; size_t curve_bytes; mbedtls_mpi r, s; (void) alg; status = mbedtls_psa_ecp_load_representation(attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if (signature_length != 2 * curve_bytes) { status = PSA_ERROR_INVALID_SIGNATURE; goto cleanup; } status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r, signature, curve_bytes)); if (status != PSA_SUCCESS) { goto cleanup; } status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s, signature + curve_bytes, curve_bytes)); if (status != PSA_SUCCESS) { goto cleanup; } status = mbedtls_psa_ecp_load_public_part(ecp); if (status != PSA_SUCCESS) { goto cleanup; } status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash, hash_length, &ecp->Q, &r, &s)); cleanup: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ /****************************************************************/ /* ECDH Key Agreement */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) psa_status_t mbedtls_psa_key_agreement_ecdh( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { psa_status_t status; if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) || !PSA_ALG_IS_ECDH(alg)) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_ecp_keypair *ecp = NULL; status = mbedtls_psa_ecp_load_representation( attributes->type, attributes->bits, key_buffer, key_buffer_size, &ecp); if (status != PSA_SUCCESS) { return status; } mbedtls_ecp_keypair *their_key = NULL; mbedtls_ecdh_context ecdh; size_t bits = 0; psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits); mbedtls_ecdh_init(&ecdh); status = mbedtls_psa_ecp_load_representation( PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), bits, peer_key, peer_key_length, &their_key); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS)); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS)); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_to_psa_error( mbedtls_ecdh_calc_secret(&ecdh, shared_secret_length, shared_secret, shared_secret_size, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); if (status != PSA_SUCCESS) { goto exit; } if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) { status = PSA_ERROR_CORRUPTION_DETECTED; } exit: if (status != PSA_SUCCESS) { mbedtls_platform_zeroize(shared_secret, shared_secret_size); } mbedtls_ecdh_free(&ecdh); mbedtls_ecp_keypair_free(their_key); mbedtls_free(their_key); mbedtls_ecp_keypair_free(ecp); mbedtls_free(ecp); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.h000066400000000000000000000311071464416617300245210ustar00rootroot00000000000000/* * PSA ECP layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ECP_H #define PSA_CRYPTO_ECP_H #include #include /** Load the contents of a key buffer into an internal ECP representation * * \param[in] type The type of key contained in \p data. * \param[in] curve_bits The nominal bit-size of the curve. * It must be consistent with the representation * passed in \p data. * This can be 0, in which case the bit-size * is inferred from \p data_length (which is possible * for all key types and representation formats * formats that are currently supported or will * be in the foreseeable future). * \param[in] data The buffer from which to load the representation. * \param[in] data_length The size in bytes of \p data. * \param[out] p_ecp Returns a pointer to an ECP context on success. * The caller is responsible for freeing both the * contents of the context and the context itself * when done. */ psa_status_t mbedtls_psa_ecp_load_representation(psa_key_type_t type, size_t curve_bits, const uint8_t *data, size_t data_length, mbedtls_ecp_keypair **p_ecp); /** Load the public part of an internal ECP, if required. * * \param ecp The ECP context to load the public part for. * * \return PSA_SUCCESS on success, otherwise an MPI error. */ psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp); /** Import an ECP key in binary format. * * \note The signature of this function is that of a PSA driver * import_key entry point. This function behaves as an import_key * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer containing the key data in output * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS The ECP key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ecp_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); /** Export an ECP key to export representation * * \param[in] type The type of key (public/private) to export * \param[in] ecp The internal ECP representation from which to export * \param[out] data The buffer to export to * \param[in] data_size The length of the buffer to export to * \param[out] data_length The amount of bytes written to \p data */ psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type, mbedtls_ecp_keypair *ecp, uint8_t *data, size_t data_size, size_t *data_length); /** Export an ECP public key or the public part of an ECP key pair in binary * format. * * \note The signature of this function is that of a PSA driver * export_public_key entry point. This function behaves as an * export_public_key entry point as defined in the PSA driver interface * specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The ECP public key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Generate an ECP key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the ECP key to generate. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was successfully generated. * \retval #PSA_ERROR_NOT_SUPPORTED * Key length or type not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t mbedtls_psa_ecp_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign an already-calculated hash with ECDSA. * * \note The signature of this function is that of a PSA driver * sign_hash entry point. This function behaves as a sign_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the ECC key to use for the * operation. * \param[in] key_buffer The buffer containing the ECC key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg Randomized or deterministic ECDSA algorithm. * \param[in] hash The hash or message to sign. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_ECC_KEY_PAIR, \c key_bits, * \p alg) where \c key_bits is the bit-size of the ECC key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t mbedtls_psa_ecdsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify an ECDSA hash or short message signature. * * \note The signature of this function is that of a PSA driver * verify_hash entry point. This function behaves as a verify_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the ECC key to use for the * operation. * \param[in] key_buffer The buffer containing the ECC key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg Randomized or deterministic ECDSA algorithm. * \param[in] hash The hash or message whose signature is to be * verified. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_ecdsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** Perform a key agreement and return the raw ECDH shared secret. * * \note The signature of this function is that of a PSA driver * key_agreement entry point. This function behaves as a key_agreement * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the private key * context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in * bytes. * \param[in] alg A key agreement algorithm that is * compatible with the type of the key. * \param[in] peer_key The buffer containing the key context * of the peer's public key. * \param[in] peer_key_length Size of the \p peer_key buffer in * bytes. * \param[out] shared_secret The buffer to which the shared secret * is to be written. * \param[in] shared_secret_size Size of the \p shared_secret buffer in * bytes. * \param[out] shared_secret_length On success, the number of bytes that make * up the returned shared secret. * \retval #PSA_SUCCESS * Success. Shared secret successfully calculated. * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT * \p alg is not a key agreement algorithm, or * \p private_key is not compatible with \p alg, * or \p peer_key is not valid for \p alg or not compatible with * \p private_key. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p shared_secret_size is too small * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not a supported key agreement algorithm. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_key_agreement_ecdh( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length); #endif /* PSA_CRYPTO_ECP_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.c000066400000000000000000000251271464416617300246610ustar00rootroot00000000000000/* * PSA FFDH layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) /* This header is only needed because it defines * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module * only uses bignum functions for arithmetic. */ #include #include #include "psa_crypto_core.h" #include "psa_crypto_ffdh.h" #include "psa_crypto_random_impl.h" #include "mbedtls/platform.h" #include "mbedtls/error.h" #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size, mbedtls_mpi *P, mbedtls_mpi *G) { const unsigned char *dhm_P = NULL; const unsigned char *dhm_G = NULL; size_t dhm_size_P = 0; size_t dhm_size_G = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (P == NULL && G == NULL) { return PSA_ERROR_INVALID_ARGUMENT; } #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) static const unsigned char dhm_P_2048[] = MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN; static const unsigned char dhm_G_2048[] = MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) static const unsigned char dhm_P_3072[] = MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN; static const unsigned char dhm_G_3072[] = MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) static const unsigned char dhm_P_4096[] = MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN; static const unsigned char dhm_G_4096[] = MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) static const unsigned char dhm_P_6144[] = MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN; static const unsigned char dhm_G_6144[] = MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) static const unsigned char dhm_P_8192[] = MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN; static const unsigned char dhm_G_8192[] = MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ switch (key_size) { #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048) case sizeof(dhm_P_2048): dhm_P = dhm_P_2048; dhm_G = dhm_G_2048; dhm_size_P = sizeof(dhm_P_2048); dhm_size_G = sizeof(dhm_G_2048); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072) case sizeof(dhm_P_3072): dhm_P = dhm_P_3072; dhm_G = dhm_G_3072; dhm_size_P = sizeof(dhm_P_3072); dhm_size_G = sizeof(dhm_G_3072); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096) case sizeof(dhm_P_4096): dhm_P = dhm_P_4096; dhm_G = dhm_G_4096; dhm_size_P = sizeof(dhm_P_4096); dhm_size_G = sizeof(dhm_G_4096); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144) case sizeof(dhm_P_6144): dhm_P = dhm_P_6144; dhm_G = dhm_G_6144; dhm_size_P = sizeof(dhm_P_6144); dhm_size_G = sizeof(dhm_G_6144); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */ #if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192) case sizeof(dhm_P_8192): dhm_P = dhm_P_8192; dhm_G = dhm_G_8192; dhm_size_P = sizeof(dhm_P_8192); dhm_size_G = sizeof(dhm_G_8192); break; #endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */ default: return PSA_ERROR_INVALID_ARGUMENT; } if (P != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P, dhm_size_P)); } if (G != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G, dhm_size_G)); } cleanup: if (ret != 0) { return mbedtls_to_psa_error(ret); } return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY || MBEDTLS_PSA_BUILTIN_ALG_FFDH */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) psa_status_t mbedtls_psa_ffdh_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi GX, G, X, P; psa_key_type_t type = attributes->type; if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) { if (key_buffer_size > data_size) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(data, key_buffer, key_buffer_size); memset(data + key_buffer_size, 0, data_size - key_buffer_size); *data_length = key_buffer_size; return PSA_SUCCESS; } mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G); mbedtls_mpi_init(&X); mbedtls_mpi_init(&P); size_t key_len = PSA_BITS_TO_BYTES(attributes->bits); status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G); if (status != PSA_SUCCESS) { goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, key_buffer_size)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len)); *data_length = key_len; ret = 0; cleanup: mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX); if (status == PSA_SUCCESS && ret != 0) { status = mbedtls_to_psa_error(ret); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT || MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) psa_status_t mbedtls_psa_ffdh_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { mbedtls_mpi X, P; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_init(&P); mbedtls_mpi_init(&X); (void) attributes; status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL); if (status != PSA_SUCCESS) { goto cleanup; } /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their secret exponent from the range [2, P-2]. Select random value in range [3, P-1] and decrease it by 1. */ MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size)); *key_buffer_length = key_buffer_size; cleanup: mbedtls_mpi_free(&P); mbedtls_mpi_free(&X); if (status == PSA_SUCCESS && ret != 0) { return mbedtls_to_psa_error(ret); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) psa_status_t mbedtls_psa_ffdh_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { (void) attributes; if (key_buffer_size < data_length) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(key_buffer, data, data_length); *key_buffer_length = data_length; *bits = PSA_BYTES_TO_BITS(data_length); return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH) psa_status_t mbedtls_psa_ffdh_key_agreement( const psa_key_attributes_t *attributes, const uint8_t *peer_key, size_t peer_key_length, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_mpi P, G, X, GY, K; const size_t calculated_shared_secret_size = peer_key_length; if (peer_key_length != key_buffer_size || calculated_shared_secret_size > shared_secret_size) { return PSA_ERROR_INVALID_ARGUMENT; } if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) { return PSA_ERROR_INVALID_ARGUMENT; } mbedtls_mpi_init(&P); mbedtls_mpi_init(&G); mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY); mbedtls_mpi_init(&K); status = mbedtls_psa_ffdh_set_prime_generator( PSA_BITS_TO_BYTES(attributes->bits), &P, &G); if (status != PSA_SUCCESS) { goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer, key_buffer_size)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key, peer_key_length)); /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret, calculated_shared_secret_size)); *shared_secret_length = calculated_shared_secret_size; ret = 0; cleanup: mbedtls_mpi_free(&P); mbedtls_mpi_free(&G); mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY); mbedtls_mpi_free(&K); if (status == PSA_SUCCESS && ret != 0) { status = mbedtls_to_psa_error(ret); } return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.h000066400000000000000000000124001464416617300246540ustar00rootroot00000000000000/* * PSA FFDH layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_FFDH_H #define PSA_CRYPTO_FFDH_H #include /** Perform a key agreement and return the FFDH shared secret. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] peer_key The buffer containing the key context * of the peer's public key. * \param[in] peer_key_length Size of the \p peer_key buffer in * bytes. * \param[in] key_buffer The buffer containing the private key * context. * \param[in] key_buffer_size Size of the \p key_buffer buffer in * bytes. * \param[out] shared_secret The buffer to which the shared secret * is to be written. * \param[in] shared_secret_size Size of the \p shared_secret buffer in * bytes. * \param[out] shared_secret_length On success, the number of bytes that make * up the returned shared secret. * \retval #PSA_SUCCESS * Success. Shared secret successfully calculated. * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key_buffer_size, \p peer_key_length, \p shared_secret_size * do not match * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ffdh_key_agreement( const psa_key_attributes_t *attributes, const uint8_t *peer_key, size_t peer_key_length, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *shared_secret, size_t shared_secret_size, size_t *shared_secret_length); /** Export a public key or the public part of a DH key pair in binary format. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data * * \retval #PSA_SUCCESS The public key was exported successfully. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ffdh_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Generate DH key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the key to generate. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was generated successfully. * \retval #PSA_ERROR_NOT_SUPPORTED * Key size in bits is invalid. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_ffdh_generate_key( const psa_key_attributes_t *attributes, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** * \brief Import DH key. * * \note The signature of the function is that of a PSA driver import_key * entry point. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer containing the key data in output * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS * The key was generated successfully. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t mbedtls_psa_ffdh_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); #endif /* PSA_CRYPTO_FFDH_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_hash.c000066400000000000000000000353021464416617300246710ustar00rootroot00000000000000/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_hash.h" #include #include #if defined(MBEDTLS_PSA_BUILTIN_HASH) psa_status_t mbedtls_psa_hash_abort( mbedtls_psa_hash_operation_t *operation) { switch (operation->alg) { case 0: /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ break; #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_free(&operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_free(&operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_free(&operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_free(&operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_free(&operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_free(&operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_free(&operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) mbedtls_sha3_free(&operation->ctx.sha3); break; #endif default: return PSA_ERROR_BAD_STATE; } operation->alg = 0; return PSA_SUCCESS; } psa_status_t mbedtls_psa_hash_setup( mbedtls_psa_hash_operation_t *operation, psa_algorithm_t alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->alg != 0) { return PSA_ERROR_BAD_STATE; } switch (alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_init(&operation->ctx.md5); ret = mbedtls_md5_starts(&operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_init(&operation->ctx.ripemd160); ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_init(&operation->ctx.sha1); ret = mbedtls_sha1_starts(&operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_init(&operation->ctx.sha256); ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_init(&operation->ctx.sha256); ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_init(&operation->ctx.sha512); ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_init(&operation->ctx.sha512); ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: mbedtls_sha3_init(&operation->ctx.sha3); ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512); break; #endif default: return PSA_ALG_IS_HASH(alg) ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT; } if (ret == 0) { operation->alg = alg; } else { mbedtls_psa_hash_abort(operation); } return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_hash_clone( const mbedtls_psa_hash_operation_t *source_operation, mbedtls_psa_hash_operation_t *target_operation) { switch (source_operation->alg) { case 0: return PSA_ERROR_BAD_STATE; #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_clone(&target_operation->ctx.md5, &source_operation->ctx.md5); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160, &source_operation->ctx.ripemd160); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_clone(&target_operation->ctx.sha1, &source_operation->ctx.sha1); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_clone(&target_operation->ctx.sha256, &source_operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_clone(&target_operation->ctx.sha256, &source_operation->ctx.sha256); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) mbedtls_sha3_clone(&target_operation->ctx.sha3, &source_operation->ctx.sha3); break; #endif default: (void) source_operation; (void) target_operation; return PSA_ERROR_NOT_SUPPORTED; } target_operation->alg = source_operation->alg; return PSA_SUCCESS; } psa_status_t mbedtls_psa_hash_update( mbedtls_psa_hash_operation_t *operation, const uint8_t *input, size_t input_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (operation->alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: ret = mbedtls_md5_update(&operation->ctx.md5, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: ret = mbedtls_sha1_update(&operation->ctx.sha1, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: ret = mbedtls_sha256_update(&operation->ctx.sha256, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: ret = mbedtls_sha256_update(&operation->ctx.sha256, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: ret = mbedtls_sha512_update(&operation->ctx.sha512, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: ret = mbedtls_sha512_update(&operation->ctx.sha512, input, input_length); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) ret = mbedtls_sha3_update(&operation->ctx.sha3, input, input_length); break; #endif default: (void) input; (void) input_length; return PSA_ERROR_BAD_STATE; } return mbedtls_to_psa_error(ret); } psa_status_t mbedtls_psa_hash_finish( mbedtls_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg); /* Fill the output buffer with something that isn't a valid hash * (barring an attack on the hash and deliberately-crafted input), * in case the caller doesn't check the return status properly. */ *hash_length = hash_size; /* If hash_size is 0 then hash may be NULL and then the * call to memset would have undefined behavior. */ if (hash_size != 0) { memset(hash, '!', hash_size); } if (hash_size < actual_hash_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } switch (operation->alg) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) case PSA_ALG_MD5: ret = mbedtls_md5_finish(&operation->ctx.md5, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash); break; #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) case PSA_ALG_SHA3_224: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) case PSA_ALG_SHA3_256: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) case PSA_ALG_SHA3_384: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) case PSA_ALG_SHA3_512: #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512) ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size); break; #endif default: (void) hash; return PSA_ERROR_BAD_STATE; } status = mbedtls_to_psa_error(ret); exit: if (status == PSA_SUCCESS) { *hash_length = actual_hash_length; } return status; } psa_status_t mbedtls_psa_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; *hash_length = hash_size; status = mbedtls_psa_hash_setup(&operation, alg); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_hash_update(&operation, input, input_length); if (status != PSA_SUCCESS) { goto exit; } status = mbedtls_psa_hash_finish(&operation, hash, hash_size, hash_length); if (status != PSA_SUCCESS) { goto exit; } exit: abort_status = mbedtls_psa_hash_abort(&operation); if (status == PSA_SUCCESS) { return abort_status; } else { return status; } } #endif /* MBEDTLS_PSA_BUILTIN_HASH */ #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_hash.h000066400000000000000000000216341464416617300247010ustar00rootroot00000000000000/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_HASH_H #define PSA_CRYPTO_HASH_H #include /** Calculate the hash (digest) of a message using Mbed TLS routines. * * \note The signature of this function is that of a PSA driver hash_compute * entry point. This function behaves as a hash_compute entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * \param[in] input Buffer containing the message to hash. * \param input_length Size of the \p input buffer in bytes. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\p alg). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p hash_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Set up a multipart hash operation using Mbed TLS routines. * * \note The signature of this function is that of a PSA driver hash_setup * entry point. This function behaves as a hash_setup entry point as * defined in the PSA driver interface specification for transparent * drivers. * * If an error occurs at any step after a call to mbedtls_psa_hash_setup(), the * operation will need to be reset by a call to mbedtls_psa_hash_abort(). The * core may call mbedtls_psa_hash_abort() at any time after the operation * has been initialized. * * After a successful call to mbedtls_psa_hash_setup(), the core must * eventually terminate the operation. The following events terminate an * operation: * - A successful call to mbedtls_psa_hash_finish() or mbedtls_psa_hash_verify(). * - A call to mbedtls_psa_hash_abort(). * * \param[in,out] operation The operation object to set up. It must have * been initialized to all-zero and not yet be in use. * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_HASH(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_setup( mbedtls_psa_hash_operation_t *operation, psa_algorithm_t alg); /** Clone an Mbed TLS hash operation. * * \note The signature of this function is that of a PSA driver hash_clone * entry point. This function behaves as a hash_clone entry point as * defined in the PSA driver interface specification for transparent * drivers. * * This function copies the state of an ongoing hash operation to * a new operation object. In other words, this function is equivalent * to calling mbedtls_psa_hash_setup() on \p target_operation with the same * algorithm that \p source_operation was set up for, then * mbedtls_psa_hash_update() on \p target_operation with the same input that * that was passed to \p source_operation. After this function returns, the * two objects are independent, i.e. subsequent calls involving one of * the objects do not affect the other object. * * \param[in] source_operation The active hash operation to clone. * \param[in,out] target_operation The operation object to set up. * It must be initialized but not active. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BAD_STATE * The \p source_operation state is not valid (it must be active). * \retval #PSA_ERROR_BAD_STATE * The \p target_operation state is not valid (it must be inactive). * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_hash_clone( const mbedtls_psa_hash_operation_t *source_operation, mbedtls_psa_hash_operation_t *target_operation); /** Add a message fragment to a multipart Mbed TLS hash operation. * * \note The signature of this function is that of a PSA driver hash_update * entry point. This function behaves as a hash_update entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The application must call mbedtls_psa_hash_setup() before calling this function. * * If this function returns an error status, the operation enters an error * state and must be aborted by calling mbedtls_psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[in] input Buffer containing the message fragment to hash. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_update( mbedtls_psa_hash_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the Mbed TLS-calculated hash of a message. * * \note The signature of this function is that of a PSA driver hash_finish * entry point. This function behaves as a hash_finish entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The application must call mbedtls_psa_hash_setup() before calling this function. * This function calculates the hash of the message formed by concatenating * the inputs passed to preceding calls to mbedtls_psa_hash_update(). * * When this function returns successfully, the operation becomes inactive. * If this function returns an error status, the operation enters an error * state and must be aborted by calling mbedtls_psa_hash_abort(). * * \param[in,out] operation Active hash operation. * \param[out] hash Buffer where the hash is to be written. * \param hash_size Size of the \p hash buffer in bytes. * \param[out] hash_length On success, the number of bytes * that make up the hash value. This is always * #PSA_HASH_LENGTH(\c alg) where \c alg is the * hash algorithm that is calculated. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p hash buffer is too small. You can determine a * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) * where \c alg is the hash algorithm that is calculated. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_finish( mbedtls_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length); /** Abort an Mbed TLS hash operation. * * \note The signature of this function is that of a PSA driver hash_abort * entry point. This function behaves as a hash_abort entry point as * defined in the PSA driver interface specification for transparent * drivers. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * mbedtls_psa_hash_setup() again. * * You may call this function any time after the operation object has * been initialized by one of the methods described in #psa_hash_operation_t. * * In particular, calling mbedtls_psa_hash_abort() after the operation has been * terminated by a call to mbedtls_psa_hash_abort(), mbedtls_psa_hash_finish() or * mbedtls_psa_hash_verify() is safe and has no effect. * * \param[in,out] operation Initialized hash operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_hash_abort( mbedtls_psa_hash_operation_t *operation); #endif /* PSA_CRYPTO_HASH_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_invasive.h000066400000000000000000000072011464416617300255740ustar00rootroot00000000000000/** * \file psa_crypto_invasive.h * * \brief PSA cryptography module: invasive interfaces for test only. * * The interfaces in this file are intended for testing purposes only. * They MUST NOT be made available to clients over IPC in integrations * with isolation, and they SHOULD NOT be made available in library * integrations except when building the library for testing. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_INVASIVE_H #define PSA_CRYPTO_INVASIVE_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #include "psa/crypto.h" #include "common.h" #include "mbedtls/entropy.h" #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** \brief Configure entropy sources. * * This function may only be called before a call to psa_crypto_init(), * or after a call to mbedtls_psa_crypto_free() and before any * subsequent call to psa_crypto_init(). * * This function is only intended for test purposes. The functionality * it provides is also useful for system integrators, but * system integrators should configure entropy drivers instead of * breaking through to the Mbed TLS API. * * \param entropy_init Function to initialize the entropy context * and set up the desired entropy sources. * It is called by psa_crypto_init(). * By default this is mbedtls_entropy_init(). * This function cannot report failures directly. * To indicate a failure, set the entropy context * to a state where mbedtls_entropy_func() will * return an error. * \param entropy_free Function to free the entropy context * and associated resources. * It is called by mbedtls_psa_crypto_free(). * By default this is mbedtls_entropy_free(). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_PERMITTED * The caller does not have the permission to configure * entropy sources. * \retval #PSA_ERROR_BAD_STATE * The library has already been initialized. */ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void (* entropy_init)(mbedtls_entropy_context *ctx), void (* entropy_free)(mbedtls_entropy_context *ctx)); #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) psa_status_t psa_mac_key_can_do( psa_algorithm_t algorithm, psa_key_type_t key_type); psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len, uint8_t *input_copy, size_t input_copy_len); psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len, uint8_t *output, size_t output_len); /* * Test hooks to use for memory unpoisoning/poisoning in copy functions. */ extern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len); extern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len); extern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len); extern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len); #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */ #endif /* PSA_CRYPTO_INVASIVE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_its.h000066400000000000000000000145641464416617300245610ustar00rootroot00000000000000/** \file psa_crypto_its.h * \brief Interface of trusted storage that crypto is built on. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_ITS_H #define PSA_CRYPTO_ITS_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** \brief Flags used when creating a data entry */ typedef uint32_t psa_storage_create_flags_t; /** \brief A type for UIDs used for identifying data */ typedef uint64_t psa_storage_uid_t; #define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ #define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ /** * \brief A container for metadata associated with a specific uid */ struct psa_storage_info_t { uint32_t size; /**< The size of the data associated with a uid **/ psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ }; /** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ #define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) #define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ #define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ /** * \brief create a new or modify an existing uid/value pair * * \param[in] uid the identifier for the data * \param[in] data_length The size in bytes of the data in `p_data` * \param[in] p_data A buffer containing the data * \param[in] create_flags The flags that the data will be stored with * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE * \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid * \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) * is invalid, for example is `NULL` or references memory the caller cannot access */ psa_status_t psa_its_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags); /** * \brief Retrieve the value associated with a provided uid * * \param[in] uid The uid value * \param[in] data_offset The starting offset of the data requested * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) * \param[out] p_data The buffer where the data will be placed upon successful completion * \param[out] p_data_length The amount of data returned in the p_data buffer * * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) * is invalid. For example is `NULL` or references memory the caller cannot access. * In addition, this can also happen if an invalid offset was provided. */ psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data, size_t *p_data_length); /** * \brief Retrieve the metadata about the provided uid * * \param[in] uid The uid value * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) * is invalid, for example is `NULL` or references memory the caller cannot access */ psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info); /** * \brief Remove the provided key and its associated data from the storage * * \param[in] uid The uid value * * \return A status indicating the success/failure of the operation * * \retval #PSA_SUCCESS The operation completed successfully * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) */ psa_status_t psa_its_remove(psa_storage_uid_t uid); #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_ITS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_mac.c000066400000000000000000000352601464416617300245110ustar00rootroot00000000000000/* * PSA MAC layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_cipher.h" #include "psa_crypto_mac.h" #include #include #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) static psa_status_t psa_hmac_abort_internal( mbedtls_psa_hmac_operation_t *hmac) { mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad)); return psa_hash_abort(&hmac->hash_ctx); } static psa_status_t psa_hmac_setup_internal( mbedtls_psa_hmac_operation_t *hmac, const uint8_t *key, size_t key_length, psa_algorithm_t hash_alg) { uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; size_t i; size_t hash_size = PSA_HASH_LENGTH(hash_alg); size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); psa_status_t status; hmac->alg = hash_alg; /* Sanity checks on block_size, to guarantee that there won't be a buffer * overflow below. This should never trigger if the hash algorithm * is implemented correctly. */ /* The size checks against the ipad and opad buffers cannot be written * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` * because that triggers -Wlogical-op on GCC 7.3. */ if (block_size > sizeof(ipad)) { return PSA_ERROR_NOT_SUPPORTED; } if (block_size > sizeof(hmac->opad)) { return PSA_ERROR_NOT_SUPPORTED; } if (block_size < hash_size) { return PSA_ERROR_NOT_SUPPORTED; } if (key_length > block_size) { status = psa_hash_compute(hash_alg, key, key_length, ipad, sizeof(ipad), &key_length); if (status != PSA_SUCCESS) { goto cleanup; } } /* A 0-length key is not commonly used in HMAC when used as a MAC, * but it is permitted. It is common when HMAC is used in HKDF, for * example. Don't call `memcpy` in the 0-length because `key` could be * an invalid pointer which would make the behavior undefined. */ else if (key_length != 0) { memcpy(ipad, key, key_length); } /* ipad contains the key followed by garbage. Xor and fill with 0x36 * to create the ipad value. */ for (i = 0; i < key_length; i++) { ipad[i] ^= 0x36; } memset(ipad + key_length, 0x36, block_size - key_length); /* Copy the key material from ipad to opad, flipping the requisite bits, * and filling the rest of opad with the requisite constant. */ for (i = 0; i < key_length; i++) { hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; } memset(hmac->opad + key_length, 0x5C, block_size - key_length); status = psa_hash_setup(&hmac->hash_ctx, hash_alg); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_hash_update(&hmac->hash_ctx, ipad, block_size); cleanup: mbedtls_platform_zeroize(ipad, sizeof(ipad)); return status; } static psa_status_t psa_hmac_update_internal( mbedtls_psa_hmac_operation_t *hmac, const uint8_t *data, size_t data_length) { return psa_hash_update(&hmac->hash_ctx, data, data_length); } static psa_status_t psa_hmac_finish_internal( mbedtls_psa_hmac_operation_t *hmac, uint8_t *mac, size_t mac_size) { uint8_t tmp[PSA_HASH_MAX_SIZE]; psa_algorithm_t hash_alg = hmac->alg; size_t hash_size = 0; size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); psa_status_t status; status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size); if (status != PSA_SUCCESS) { return status; } /* From here on, tmp needs to be wiped. */ status = psa_hash_setup(&hmac->hash_ctx, hash_alg); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size); if (status != PSA_SUCCESS) { goto exit; } memcpy(mac, tmp, mac_size); exit: mbedtls_platform_zeroize(tmp, hash_size); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(PSA_WANT_KEY_TYPE_DES) /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept * to do CMAC with pure DES, so return NOT_SUPPORTED here. */ if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES && (psa_get_key_bits(attributes) == 64 || psa_get_key_bits(attributes) == 128)) { return PSA_ERROR_NOT_SUPPORTED; } #endif const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_psa( PSA_ALG_CMAC, psa_get_key_type(attributes), psa_get_key_bits(attributes), NULL); if (cipher_info == NULL) { return PSA_ERROR_NOT_SUPPORTED; } ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info); if (ret != 0) { goto exit; } ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac, key_buffer, psa_get_key_bits(attributes)); exit: return mbedtls_to_psa_error(ret); } #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) /* Initialize this driver's MAC operation structure. Once this function has been * called, mbedtls_psa_mac_abort can run and will do the right thing. */ static psa_status_t mac_init( mbedtls_psa_mac_operation_t *operation, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; operation->alg = alg; #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { mbedtls_cipher_init(&operation->ctx.cmac); status = PSA_SUCCESS; } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { /* We'll set up the hash operation later in psa_hmac_setup_internal. */ operation->ctx.hmac.alg = 0; status = PSA_SUCCESS; } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { (void) operation; status = PSA_ERROR_NOT_SUPPORTED; } if (status != PSA_SUCCESS) { memset(operation, 0, sizeof(*operation)); } return status; } psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation) { if (operation->alg == 0) { /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ return PSA_SUCCESS; } else #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { mbedtls_cipher_free(&operation->ctx.cmac); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { psa_hmac_abort_internal(&operation->ctx.hmac); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { /* Sanity check (shouldn't happen: operation->alg should * always have been initialized to a valid value). */ goto bad_state; } operation->alg = 0; return PSA_SUCCESS; bad_state: /* If abort is called on an uninitialized object, we can't trust * anything. Wipe the object in case it contains confidential data. * This may result in a memory leak if a pointer gets overwritten, * but it's too late to do anything about this. */ memset(operation, 0, sizeof(*operation)); return PSA_ERROR_BAD_STATE; } static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->alg != 0) { return PSA_ERROR_BAD_STATE; } status = mac_init(operation, alg); if (status != PSA_SUCCESS) { return status; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) { /* Key buffer size for CMAC is dictated by the key bits set on the * attributes, and previously validated by the core on key import. */ (void) key_buffer_size; status = cmac_setup(operation, attributes, key_buffer); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(alg)) { status = psa_hmac_setup_internal(&operation->ctx.hmac, key_buffer, key_buffer_size, PSA_ALG_HMAC_GET_HASH(alg)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { (void) attributes; (void) key_buffer; (void) key_buffer_size; status = PSA_ERROR_NOT_SUPPORTED; } if (status != PSA_SUCCESS) { mbedtls_psa_mac_abort(operation); } return status; } psa_status_t mbedtls_psa_mac_sign_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_mac_setup(operation, attributes, key_buffer, key_buffer_size, alg); } psa_status_t mbedtls_psa_mac_verify_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg) { return psa_mac_setup(operation, attributes, key_buffer, key_buffer_size, alg); } psa_status_t mbedtls_psa_mac_update( mbedtls_psa_mac_operation_t *operation, const uint8_t *input, size_t input_length) { if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { return mbedtls_to_psa_error( mbedtls_cipher_cmac_update(&operation->ctx.cmac, input, input_length)); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { return psa_hmac_update_internal(&operation->ctx.hmac, input, input_length); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { /* This shouldn't happen if `operation` was initialized by * a setup function. */ (void) input; (void) input_length; return PSA_ERROR_BAD_STATE; } } static psa_status_t psa_mac_finish_internal( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) { uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE]; int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp); if (ret == 0) { memcpy(mac, tmp, mac_size); } mbedtls_platform_zeroize(tmp, sizeof(tmp)); return mbedtls_to_psa_error(ret); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) if (PSA_ALG_IS_HMAC(operation->alg)) { return psa_hmac_finish_internal(&operation->ctx.hmac, mac, mac_size); } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ { /* This shouldn't happen if `operation` was initialized by * a setup function. */ (void) operation; (void) mac; (void) mac_size; return PSA_ERROR_BAD_STATE; } } psa_status_t mbedtls_psa_mac_sign_finish( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } status = psa_mac_finish_internal(operation, mac, mac_size); if (status == PSA_SUCCESS) { *mac_length = mac_size; } return status; } psa_status_t mbedtls_psa_mac_verify_finish( mbedtls_psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length) { uint8_t actual_mac[PSA_MAC_MAX_SIZE]; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (operation->alg == 0) { return PSA_ERROR_BAD_STATE; } /* Consistency check: requested MAC length fits our local buffer */ if (mac_length > sizeof(actual_mac)) { return PSA_ERROR_INVALID_ARGUMENT; } status = psa_mac_finish_internal(operation, actual_mac, mac_length); if (status != PSA_SUCCESS) { goto cleanup; } if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) { status = PSA_ERROR_INVALID_SIGNATURE; } cleanup: mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac)); return status; } psa_status_t mbedtls_psa_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT; status = psa_mac_setup(&operation, attributes, key_buffer, key_buffer_size, alg); if (status != PSA_SUCCESS) { goto exit; } if (input_length > 0) { status = mbedtls_psa_mac_update(&operation, input, input_length); if (status != PSA_SUCCESS) { goto exit; } } status = psa_mac_finish_internal(&operation, mac, mac_size); if (status == PSA_SUCCESS) { *mac_length = mac_size; } exit: mbedtls_psa_mac_abort(&operation); return status; } #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */ #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_mac.h000066400000000000000000000267651464416617300245300ustar00rootroot00000000000000/* * PSA MAC layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_MAC_H #define PSA_CRYPTO_MAC_H #include /** Calculate the MAC (message authentication code) of a message using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_compute * entry point. This function behaves as a mac_compute entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key to use for * computing the MAC. This buffer contains the key * in export representation as defined by * psa_export_key() (i.e. the raw key bytes). * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * \param[in] input Buffer containing the input message. * \param input_length Size of the \p input buffer in bytes. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Size of the \p mac buffer in bytes. * \param[out] mac_length On success, the number of bytes * that make up the MAC value. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * \p mac_size is too small * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_compute( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Set up a multipart MAC calculation operation using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_sign_setup * entry point. This function behaves as a mac_sign_setup entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in,out] operation The operation object to set up. It must have * been initialized and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key to use for * computing the MAC. This buffer contains the key * in export representation as defined by * psa_export_key() (i.e. the raw key bytes). * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive). */ psa_status_t mbedtls_psa_mac_sign_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Set up a multipart MAC verification operation using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_verify_setup * entry point. This function behaves as a mac_verify_setup entry point as * defined in the PSA driver interface specification for transparent * drivers. * * \param[in,out] operation The operation object to set up. It must have * been initialized and not yet in use. * \param[in] attributes The attributes of the key to use for the * operation. * \param[in] key_buffer The buffer containing the key to use for * computing the MAC. This buffer contains the key * in export representation as defined by * psa_export_key() (i.e. the raw key bytes). * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(\p alg) is true). * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be inactive). */ psa_status_t mbedtls_psa_mac_verify_setup( mbedtls_psa_mac_operation_t *operation, const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg); /** Add a message fragment to a multipart MAC operation using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_update * entry point. This function behaves as a mac_update entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The PSA core calls mbedtls_psa_mac_sign_setup() or * mbedtls_psa_mac_verify_setup() before calling this function. * * If this function returns an error status, the PSA core aborts the * operation by calling mbedtls_psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] input Buffer containing the message fragment to add to * the MAC calculation. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_update( mbedtls_psa_mac_operation_t *operation, const uint8_t *input, size_t input_length); /** Finish the calculation of the MAC of a message using Mbed TLS. * * \note The signature of this function is that of a PSA driver mac_sign_finish * entry point. This function behaves as a mac_sign_finish entry point as * defined in the PSA driver interface specification for transparent * drivers. * * The PSA core calls mbedtls_psa_mac_sign_setup() before calling this function. * This function calculates the MAC of the message formed by concatenating * the inputs passed to preceding calls to mbedtls_psa_mac_update(). * * Whether this function returns successfully or not, the PSA core subsequently * aborts the operation by calling mbedtls_psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[out] mac Buffer where the MAC value is to be written. * \param mac_size Output size requested for the MAC algorithm. The PSA * core guarantees this is a valid MAC length for the * algorithm and key combination passed to * mbedtls_psa_mac_sign_setup(). It also guarantees the * \p mac buffer is large enough to contain the * requested output size. * \param[out] mac_length On success, the number of bytes output to buffer * \p mac, which will be equal to the requested length * \p mac_size. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac sign * operation). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p mac buffer is too small. A sufficient buffer size * can be determined by calling PSA_MAC_LENGTH(). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_sign_finish( mbedtls_psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length); /** Finish the calculation of the MAC of a message and compare it with * an expected value using Mbed TLS. * * \note The signature of this function is that of a PSA driver * mac_verify_finish entry point. This function behaves as a * mac_verify_finish entry point as defined in the PSA driver interface * specification for transparent drivers. * * The PSA core calls mbedtls_psa_mac_verify_setup() before calling this * function. This function calculates the MAC of the message formed by * concatenating the inputs passed to preceding calls to * mbedtls_psa_mac_update(). It then compares the calculated MAC with the * expected MAC passed as a parameter to this function. * * Whether this function returns successfully or not, the PSA core subsequently * aborts the operation by calling mbedtls_psa_mac_abort(). * * \param[in,out] operation Active MAC operation. * \param[in] mac Buffer containing the expected MAC value. * \param mac_length Length in bytes of the expected MAC value. The PSA * core guarantees that this length is a valid MAC * length for the algorithm and key combination passed * to mbedtls_psa_mac_verify_setup(). * * \retval #PSA_SUCCESS * The expected MAC is identical to the actual MAC of the message. * \retval #PSA_ERROR_INVALID_SIGNATURE * The MAC of the message was calculated successfully, but it * differs from the expected MAC. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be an active mac verify * operation). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_verify_finish( mbedtls_psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length); /** Abort a MAC operation using Mbed TLS. * * Aborting an operation frees all associated resources except for the * \p operation structure itself. Once aborted, the operation object * can be reused for another operation by calling * mbedtls_psa_mac_sign_setup() or mbedtls_psa_mac_verify_setup() again. * * The PSA core may call this function any time after the operation object has * been initialized by one of the methods described in * #mbedtls_psa_mac_operation_t. * * In particular, calling mbedtls_psa_mac_abort() after the operation has been * terminated by a call to mbedtls_psa_mac_abort(), * mbedtls_psa_mac_sign_finish() or mbedtls_psa_mac_verify_finish() is safe and * has no effect. * * \param[in,out] operation Initialized MAC operation. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_mac_abort( mbedtls_psa_mac_operation_t *operation); #endif /* PSA_CRYPTO_MAC_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_pake.c000066400000000000000000000501521464416617300246660ustar00rootroot00000000000000/* * PSA PAKE layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa_crypto_core.h" #include "psa_crypto_pake.h" #include "psa_crypto_slot_management.h" #include #include "psa_util_internal.h" #include #include #include /* * State sequence: * * psa_pake_setup() * | * |-- In any order: * | | psa_pake_set_password_key() * | | psa_pake_set_user() * | | psa_pake_set_peer() * | | psa_pake_set_role() * | * |--- In any order: (First round input before or after first round output) * | | * | |------ In Order * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) * | | * | |------ In Order: * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) * | * |--- In any order: (Second round input before or after second round output) * | | * | |------ In Order * | | | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC) * | | | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF) * | | * | |------ In Order: * | | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC) * | | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF) * | * psa_pake_get_implicit_key() * psa_pake_abort() */ /* * Possible sequence of calls to implementation: * * |--- In any order: * | | * | |------ In Order * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF) * | | * | |------ In Order: * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE) * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC) * | | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF) * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE) * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC) * | | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF) * | * |--- In any order: * | | * | |------ In Order * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC) * | | | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF) * | | * | |------ In Order: * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE) * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC) * | | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF) */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) static psa_status_t mbedtls_ecjpake_to_psa_error(int ret) { switch (ret) { case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: case MBEDTLS_ERR_ECP_INVALID_KEY: case MBEDTLS_ERR_ECP_VERIFY_FAILED: return PSA_ERROR_DATA_INVALID; case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: return PSA_ERROR_BUFFER_TOO_SMALL; case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: return PSA_ERROR_NOT_SUPPORTED; case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: return PSA_ERROR_CORRUPTION_DETECTED; default: return PSA_ERROR_GENERIC_ERROR; } } #endif #if defined(MBEDTLS_PSA_BUILTIN_PAKE) #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ecjpake_init(&operation->ctx.jpake); ret = mbedtls_ecjpake_setup(&operation->ctx.jpake, operation->role, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, operation->password, operation->password_len); mbedtls_platform_zeroize(operation->password, operation->password_len); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } return PSA_SUCCESS; } #endif /* The only two JPAKE user/peer identifiers supported in built-in implementation. */ static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, const psa_crypto_driver_pake_inputs_t *inputs) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t user_len = 0, peer_len = 0, password_len = 0; uint8_t *peer = NULL, *user = NULL; size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0; psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); status = psa_crypto_driver_pake_get_password_len(inputs, &password_len); if (status != PSA_SUCCESS) { return status; } status = psa_crypto_driver_pake_get_user_len(inputs, &user_len); if (status != PSA_SUCCESS) { return status; } status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len); if (status != PSA_SUCCESS) { return status; } status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite); if (status != PSA_SUCCESS) { return status; } operation->password = mbedtls_calloc(1, password_len); if (operation->password == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } user = mbedtls_calloc(1, user_len); if (user == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } peer = mbedtls_calloc(1, peer_len); if (peer == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } status = psa_crypto_driver_pake_get_password(inputs, operation->password, password_len, &actual_password_len); if (status != PSA_SUCCESS) { goto error; } status = psa_crypto_driver_pake_get_user(inputs, user, user_len, &actual_user_len); if (status != PSA_SUCCESS) { goto error; } status = psa_crypto_driver_pake_get_peer(inputs, peer, peer_len, &actual_peer_len); if (status != PSA_SUCCESS) { goto error; } operation->password_len = actual_password_len; operation->alg = cipher_suite.algorithm; #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) if (cipher_suite.algorithm == PSA_ALG_JPAKE) { if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC || cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 || cipher_suite.bits != 256 || cipher_suite.hash != PSA_ALG_SHA_256) { status = PSA_ERROR_NOT_SUPPORTED; goto error; } const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length if (actual_user_len != user_peer_len || actual_peer_len != user_peer_len) { status = PSA_ERROR_NOT_SUPPORTED; goto error; } if (memcmp(user, jpake_client_id, actual_user_len) == 0 && memcmp(peer, jpake_server_id, actual_peer_len) == 0) { operation->role = MBEDTLS_ECJPAKE_CLIENT; } else if (memcmp(user, jpake_server_id, actual_user_len) == 0 && memcmp(peer, jpake_client_id, actual_peer_len) == 0) { operation->role = MBEDTLS_ECJPAKE_SERVER; } else { status = PSA_ERROR_NOT_SUPPORTED; goto error; } operation->buffer_length = 0; operation->buffer_offset = 0; status = psa_pake_ecjpake_setup(operation); if (status != PSA_SUCCESS) { goto error; } /* Role has been set, release user/peer buffers. */ mbedtls_free(user); mbedtls_free(peer); return PSA_SUCCESS; } else #else (void) operation; (void) inputs; #endif { status = PSA_ERROR_NOT_SUPPORTED; } error: mbedtls_free(user); mbedtls_free(peer); /* In case of failure of the setup of a multipart operation, the PSA driver interface * specifies that the core does not call any other driver entry point thus does not * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean * up like freeing the memory that may have been allocated to store the password. */ mbedtls_psa_pake_abort(operation); return status; } static psa_status_t mbedtls_psa_pake_output_internal( mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t length; (void) step; // Unused parameter #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) /* * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different * handling of output sequencing. * * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data * at once, on the other side the PSA CRYPTO PAKE api requires * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be * retrieved in sequence. * * In order to achieve API compatibility, the whole X1+X2 or X2S steps * data is stored in an intermediate buffer at first step output call, * and data is sliced down by parsing the ECPoint records in order * to return the right parts on each step. */ if (operation->alg == PSA_ALG_JPAKE) { /* Initialize & write round on KEY_SHARE sequences */ if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) { ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake, operation->buffer, sizeof(operation->buffer), &operation->buffer_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } operation->buffer_offset = 0; } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) { ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake, operation->buffer, sizeof(operation->buffer), &operation->buffer_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } operation->buffer_offset = 0; } /* * mbedtls_ecjpake_write_round_xxx() outputs thing in the format * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is * that the data for each step is prepended with a length byte, and * then they're concatenated. Additionally, the server's second round * output is prepended with a 3-bytes ECParameters structure. * * In PSA, we output each step separately, and don't prepend the * output with a length byte, even less a curve identifier, as that * information is already available. */ if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE && operation->role == MBEDTLS_ECJPAKE_SERVER) { /* Skip ECParameters, with is 3 bytes (RFC 8422) */ operation->buffer_offset += 3; } /* Read the length byte then move past it to the data */ length = operation->buffer[operation->buffer_offset]; operation->buffer_offset += 1; if (operation->buffer_offset + length > operation->buffer_length) { return PSA_ERROR_DATA_CORRUPT; } if (output_size < length) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(output, operation->buffer + operation->buffer_offset, length); *output_length = length; operation->buffer_offset += length; /* Reset buffer after ZK_PROOF sequence */ if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) || (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) { mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; operation->buffer_offset = 0; } return PSA_SUCCESS; } else #else (void) step; (void) output; (void) output_size; (void) output_length; #endif { return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = mbedtls_psa_pake_output_internal( operation, step, output, output_size, output_length); return status; } static psa_status_t mbedtls_psa_pake_input_internal( mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; (void) step; // Unused parameter #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) /* * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different * handling of input sequencing. * * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data * at once as input, on the other side the PSA CRYPTO PAKE api requires * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be * given in sequence. * * In order to achieve API compatibility, each X1+X2 or X4S step data * is stored sequentially in an intermediate buffer and given to the * Mbed TLS JPAKE API on the last step. * * This causes any input error to be only detected on the last step. */ if (operation->alg == PSA_ALG_JPAKE) { /* * Copy input to local buffer and format it as the Mbed TLS API * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7. * The summary is that the data for each step is prepended with a * length byte, and then they're concatenated. Additionally, the * server's second round output is prepended with a 3-bytes * ECParameters structure - which means we have to prepend that when * we're a client. */ if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE && operation->role == MBEDTLS_ECJPAKE_CLIENT) { /* We only support secp256r1. */ /* This is the ECParameters structure defined by RFC 8422. */ unsigned char ecparameters[3] = { 3, /* named_curve */ 0, 23 /* secp256r1 */ }; if (operation->buffer_length + sizeof(ecparameters) > sizeof(operation->buffer)) { return PSA_ERROR_BUFFER_TOO_SMALL; } memcpy(operation->buffer + operation->buffer_length, ecparameters, sizeof(ecparameters)); operation->buffer_length += sizeof(ecparameters); } /* * The core checks that input_length is smaller than * PSA_PAKE_INPUT_MAX_SIZE. * Thus no risk of integer overflow here. */ if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) { return PSA_ERROR_BUFFER_TOO_SMALL; } /* Write the length byte */ operation->buffer[operation->buffer_length] = (uint8_t) input_length; operation->buffer_length += 1; /* Finally copy the data */ memcpy(operation->buffer + operation->buffer_length, input, input_length); operation->buffer_length += input_length; /* Load buffer at each last round ZK_PROOF */ if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) { ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake, operation->buffer, operation->buffer_length); mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) { ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake, operation->buffer, operation->buffer_length); mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } } return PSA_SUCCESS; } else #else (void) step; (void) input; (void) input_length; #endif { return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length) { psa_status_t status = mbedtls_psa_pake_input_internal( operation, step, input, input_length); return status; } psa_status_t mbedtls_psa_pake_get_implicit_key( mbedtls_psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake, output, output_size, output_length, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE); if (ret != 0) { return mbedtls_ecjpake_to_psa_error(ret); } return PSA_SUCCESS; } else #else (void) output; #endif { return PSA_ERROR_NOT_SUPPORTED; } } psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation) { mbedtls_zeroize_and_free(operation->password, operation->password_len); operation->password = NULL; operation->password_len = 0; #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE) if (operation->alg == PSA_ALG_JPAKE) { operation->role = MBEDTLS_ECJPAKE_NONE; mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer)); operation->buffer_length = 0; operation->buffer_offset = 0; mbedtls_ecjpake_free(&operation->ctx.jpake); } #endif operation->alg = PSA_ALG_NONE; return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_BUILTIN_PAKE */ #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_pake.h000066400000000000000000000161331464416617300246740ustar00rootroot00000000000000/* * PSA PAKE layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_PAKE_H #define PSA_CRYPTO_PAKE_H #include /** Set the session information for a password-authenticated key exchange. * * \note The signature of this function is that of a PSA driver * pake_setup entry point. This function behaves as a pake_setup * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in,out] operation The operation object to set up. It must have * been initialized but not set up yet. * \param[in] inputs Inputs required for PAKE operation (role, password, * key lifetime, cipher suite) * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * The algorithm in \p cipher_suite is not a supported PAKE algorithm, * or the PAKE primitive in \p cipher_suite is not supported or not * compatible with the PAKE algorithm, or the hash algorithm in * \p cipher_suite is not supported or not compatible with the PAKE * algorithm and primitive. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation, const psa_crypto_driver_pake_inputs_t *inputs); /** Get output for a step of a password-authenticated key exchange. * * \note The signature of this function is that of a PSA driver * pake_output entry point. This function behaves as a pake_output * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in,out] operation Active PAKE operation. * \param step The step of the algorithm for which the output is * requested. * \param[out] output Buffer where the output is to be written in the * format appropriate for this driver \p step. Refer to * the documentation of psa_crypto_driver_pake_step_t for * more information. * \param output_size Size of the \p output buffer in bytes. This must * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p * primitive, \p step) where \p alg and * \p primitive are the PAKE algorithm and primitive * in the operation's cipher suite, and \p step is * the output step. * * \param[out] output_length On success, the number of bytes of the returned * output. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, uint8_t *output, size_t output_size, size_t *output_length); /** Provide input for a step of a password-authenticated key exchange. * * \note The signature of this function is that of a PSA driver * pake_input entry point. This function behaves as a pake_input * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \note The core checks that input_length is smaller than PSA_PAKE_INPUT_MAX_SIZE. * * \param[in,out] operation Active PAKE operation. * \param step The driver step for which the input is provided. * \param[in] input Buffer containing the input in the format * appropriate for this \p step. Refer to the * documentation of psa_crypto_driver_pake_step_t * for more information. * \param input_length Size of the \p input buffer in bytes. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_SIGNATURE * The verification fails for a zero-knowledge input step. * \retval #PSA_ERROR_INVALID_ARGUMENT * the \p input is not valid for the \p operation's algorithm, cipher suite * or \p step. * \retval #PSA_ERROR_NOT_SUPPORTED * the \p input is not supported for the \p operation's algorithm, cipher * suite or \p step. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation, psa_crypto_driver_pake_step_t step, const uint8_t *input, size_t input_length); /** Get implicitly confirmed shared secret from a PAKE. * * \note The signature of this function is that of a PSA driver * pake_get_implicit_key entry point. This function behaves as a * pake_get_implicit_key entry point as defined in the PSA driver * interface specification for transparent drivers. * * \param[in,out] operation Active PAKE operation. * \param[out] output Output buffer for implicit key. * \param output_size Size of the output buffer in bytes. * \param[out] output_length On success, the number of bytes of the implicit key. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * Input from a PAKE is not supported by the algorithm in the \p output * key derivation operation. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t mbedtls_psa_pake_get_implicit_key( mbedtls_psa_pake_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); /** Abort a PAKE operation. * * \note The signature of this function is that of a PSA driver * pake_abort entry point. This function behaves as a pake_abort * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in,out] operation The operation to abort. * * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation); #endif /* PSA_CRYPTO_PAKE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_random_impl.h000066400000000000000000000105121464416617300262500ustar00rootroot00000000000000/** \file psa_crypto_random_impl.h * * \brief PSA crypto random generator implementation abstraction. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_RANDOM_IMPL_H #define PSA_CRYPTO_RANDOM_IMPL_H #include "psa_util_internal.h" #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t; #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #include "mbedtls/entropy.h" /* Choose a DRBG based on configuration and availability */ #if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) #include "mbedtls/hmac_drbg.h" #elif defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #elif defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #if defined(MBEDTLS_MD_CAN_SHA512) && defined(MBEDTLS_MD_CAN_SHA256) #include #if SIZE_MAX > 0xffffffff /* Looks like a 64-bit system, so prefer SHA-512. */ #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 #else /* Looks like a 32-bit system, so prefer SHA-256. */ #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 #endif #elif defined(MBEDTLS_MD_CAN_SHA512) #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 #elif defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 #else #error "No hash algorithm available for HMAC_DBRG." #endif #else /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ #error "No DRBG module available for the psa_crypto module." #endif /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/ #if defined(MBEDTLS_CTR_DRBG_C) #include "mbedtls/ctr_drbg.h" #elif defined(MBEDTLS_HMAC_DRBG_C) #include "mbedtls/hmac_drbg.h" #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ /* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */ #if defined(MBEDTLS_CTR_DRBG_C) #define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST #elif defined(MBEDTLS_HMAC_DRBG_C) #define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST #endif #if defined(MBEDTLS_CTR_DRBG_C) typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; #elif defined(MBEDTLS_HMAC_DRBG_C) typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; #endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */ typedef struct { void (* entropy_init)(mbedtls_entropy_context *ctx); void (* entropy_free)(mbedtls_entropy_context *ctx); mbedtls_entropy_context entropy; mbedtls_psa_drbg_context_t drbg; } mbedtls_psa_random_context_t; /** Initialize the PSA DRBG. * * \param p_rng Pointer to the Mbed TLS DRBG state. */ static inline void mbedtls_psa_drbg_init(mbedtls_psa_drbg_context_t *p_rng) { #if defined(MBEDTLS_CTR_DRBG_C) mbedtls_ctr_drbg_init(p_rng); #elif defined(MBEDTLS_HMAC_DRBG_C) mbedtls_hmac_drbg_init(p_rng); #endif } /** Deinitialize the PSA DRBG. * * \param p_rng Pointer to the Mbed TLS DRBG state. */ static inline void mbedtls_psa_drbg_free(mbedtls_psa_drbg_context_t *p_rng) { #if defined(MBEDTLS_CTR_DRBG_C) mbedtls_ctr_drbg_free(p_rng); #elif defined(MBEDTLS_HMAC_DRBG_C) mbedtls_hmac_drbg_free(p_rng); #endif } /** Seed the PSA DRBG. * * \param entropy An entropy context to read the seed from. * \param custom The personalization string. * This can be \c NULL, in which case the personalization * string is empty regardless of the value of \p len. * \param len The length of the personalization string. * * \return \c 0 on success. * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure. */ static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx, mbedtls_entropy_context *entropy, const unsigned char *custom, size_t len) { #if defined(MBEDTLS_CTR_DRBG_C) return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len); #elif defined(MBEDTLS_HMAC_DRBG_C) const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE); return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len); #endif } #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #endif /* PSA_CRYPTO_RANDOM_IMPL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.c000066400000000000000000000630571464416617300245430ustar00rootroot00000000000000/* * PSA RSA layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include #include "psa/crypto_values.h" #include "psa_crypto_core.h" #include "psa_crypto_random_impl.h" #include "psa_crypto_rsa.h" #include "psa_crypto_hash.h" #include "mbedtls/psa_util.h" #include #include #include "mbedtls/platform.h" #include #include #include "rsa_internal.h" #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) /* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes * that are not a multiple of 8) well. For example, there is only * mbedtls_rsa_get_len(), which returns a number of bytes, and no * way to return the exact bit size of a key. * To keep things simple, reject non-byte-aligned key sizes. */ static psa_status_t psa_check_rsa_key_byte_aligned( const mbedtls_rsa_context *rsa) { mbedtls_mpi n; psa_status_t status; mbedtls_mpi_init(&n); status = mbedtls_to_psa_error( mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL)); if (status == PSA_SUCCESS) { if (mbedtls_mpi_bitlen(&n) % 8 != 0) { status = PSA_ERROR_NOT_SUPPORTED; } } mbedtls_mpi_free(&n); return status; } psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type, const uint8_t *data, size_t data_length, mbedtls_rsa_context **p_rsa) { psa_status_t status; size_t bits; *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); if (*p_rsa == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } mbedtls_rsa_init(*p_rsa); /* Parse the data. */ if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length)); } else { status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length)); } if (status != PSA_SUCCESS) { goto exit; } /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS * supports non-byte-aligned key sizes, but not well. For example, * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa)); if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) { status = PSA_ERROR_NOT_SUPPORTED; goto exit; } status = psa_check_rsa_key_byte_aligned(*p_rsa); if (status != PSA_SUCCESS) { goto exit; } exit: return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ #if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) psa_status_t mbedtls_psa_rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits) { psa_status_t status; mbedtls_rsa_context *rsa = NULL; /* Parse input */ status = mbedtls_psa_rsa_load_representation(attributes->type, data, data_length, &rsa); if (status != PSA_SUCCESS) { goto exit; } *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa)); /* Re-export the data to PSA export format, such that we can store export * representation in the key slot. Export representation in case of RSA is * the smallest representation that's allowed as input, so a straight-up * allocation of the same size as the input buffer will be large enough. */ status = mbedtls_psa_rsa_export_key(attributes->type, rsa, key_buffer, key_buffer_size, key_buffer_length); exit: /* Always free the RSA object */ mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, size_t data_size, size_t *data_length) { int ret; uint8_t *end = data + data_size; /* PSA Crypto API defines the format of an RSA key as a DER-encoded * representation of the non-encrypted PKCS#1 RSAPrivateKey for a * private key and of the RFC3279 RSAPublicKey for a public key. */ if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) { ret = mbedtls_rsa_write_key(rsa, data, &end); } else { ret = mbedtls_rsa_write_pubkey(rsa, data, &end); } if (ret < 0) { /* Clean up in case pk_write failed halfway through. */ memset(data, 0, data_size); return mbedtls_to_psa_error(ret); } /* The mbedtls_pk_xxx functions write to the end of the buffer. * Move the data to the beginning and erase remaining data * at the original location. */ if (2 * (size_t) ret <= data_size) { memcpy(data, data + data_size - ret, ret); memset(data + data_size - ret, 0, ret); } else if ((size_t) ret < data_size) { memmove(data, data + data_size - ret, ret); memset(data + ret, 0, data_size - ret); } *data_length = ret; return PSA_SUCCESS; } psa_status_t mbedtls_psa_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation( attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { return status; } status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY, rsa, data, data_size, data_length); mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes, size_t e_length, int *exponent) { size_t i; uint32_t acc = 0; /* Mbed TLS encodes the public exponent as an int. For simplicity, only * support values that fit in a 32-bit integer, which is larger than * int on just about every platform anyway. */ if (e_length > sizeof(acc)) { return PSA_ERROR_NOT_SUPPORTED; } for (i = 0; i < e_length; i++) { acc = (acc << 8) | e_bytes[i]; } if (acc > INT_MAX) { return PSA_ERROR_NOT_SUPPORTED; } *exponent = acc; return PSA_SUCCESS; } psa_status_t mbedtls_psa_rsa_generate_key( const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length) { psa_status_t status; mbedtls_rsa_context rsa; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int exponent = 65537; if (params_data_length != 0) { status = psa_rsa_read_exponent(params->data, params_data_length, &exponent); if (status != PSA_SUCCESS) { return status; } } mbedtls_rsa_init(&rsa); ret = mbedtls_rsa_gen_key(&rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, (unsigned int) attributes->bits, exponent); if (ret != 0) { return mbedtls_to_psa_error(ret); } status = mbedtls_psa_rsa_export_key(attributes->type, &rsa, key_buffer, key_buffer_size, key_buffer_length); mbedtls_rsa_free(&rsa); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */ /****************************************************************/ /* Sign/verify hashes */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) /* Decode the hash algorithm from alg and store the mbedtls encoding in * md_alg. Verify that the hash length is acceptable. */ static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg, size_t hash_length, mbedtls_md_type_t *md_alg) { psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); *md_alg = mbedtls_md_type_from_psa_alg(hash_alg); /* The Mbed TLS RSA module uses an unsigned int for hash length * parameters. Validate that it fits so that we don't risk an * overflow later. */ #if SIZE_MAX > UINT_MAX if (hash_length > UINT_MAX) { return PSA_ERROR_INVALID_ARGUMENT; } #endif /* For signatures using a hash, the hash length must be correct. */ if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) { if (*md_alg == MBEDTLS_MD_NONE) { return PSA_ERROR_NOT_SUPPORTED; } if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) { return PSA_ERROR_INVALID_ARGUMENT; } } return PSA_SUCCESS; } psa_status_t mbedtls_psa_rsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { return status; } status = psa_rsa_decode_md_type(alg, hash_length, &md_alg); if (status != PSA_SUCCESS) { goto exit; } if (signature_size < mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); if (ret == 0) { ret = mbedtls_rsa_pkcs1_sign(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, md_alg, (unsigned int) hash_length, hash, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) if (PSA_ALG_IS_RSA_PSS(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); if (ret == 0) { ret = mbedtls_rsa_rsassa_pss_sign(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, MBEDTLS_MD_NONE, (unsigned int) hash_length, hash, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } if (ret == 0) { *signature_length = mbedtls_rsa_get_len(rsa); } status = mbedtls_to_psa_error(ret); exit: mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) static int rsa_pss_expected_salt_len(psa_algorithm_t alg, const mbedtls_rsa_context *rsa, size_t hash_length) { if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) { return MBEDTLS_RSA_SALT_LEN_ANY; } /* Otherwise: standard salt length, i.e. largest possible salt length * up to the hash length. */ int klen = (int) mbedtls_rsa_get_len(rsa); // known to fit int hlen = (int) hash_length; // known to fit int room = klen - 2 - hlen; if (room < 0) { return 0; // there is no valid signature in this case anyway } else if (room > hlen) { return hlen; } else { return room; } } #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ psa_status_t mbedtls_psa_rsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_rsa_context *rsa = NULL; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_alg; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto exit; } status = psa_rsa_decode_md_type(alg, hash_length, &md_alg); if (status != PSA_SUCCESS) { goto exit; } if (signature_length != mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_INVALID_SIGNATURE; goto exit; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); if (ret == 0) { ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, (unsigned int) hash_length, hash, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) if (PSA_ALG_IS_RSA_PSS(alg)) { ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); if (ret == 0) { int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length); ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa, md_alg, (unsigned) hash_length, hash, md_alg, slen, signature); } } else #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } /* Mbed TLS distinguishes "invalid padding" from "valid padding but * the rest of the signature is invalid". This has little use in * practice and PSA doesn't report this distinction. */ status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ? PSA_ERROR_INVALID_SIGNATURE : mbedtls_to_psa_error(ret); exit: mbedtls_rsa_free(rsa); mbedtls_free(rsa); return status; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ /****************************************************************/ /* Asymmetric cryptography */ /****************************************************************/ #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) static int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg, mbedtls_rsa_context *rsa) { psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg); mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg); /* Just to get the error status right, as rsa_set_padding() doesn't * distinguish between "bad RSA algorithm" and "unknown hash". */ if (mbedtls_md_info_from_type(md_alg) == NULL) { return PSA_ERROR_NOT_SUPPORTED; } return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg); } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; (void) key_buffer; (void) key_buffer_size; (void) input; (void) input_length; (void) salt; (void) salt_length; (void) output; (void) output_size; (void) output_length; if (PSA_KEY_TYPE_IS_RSA(attributes->type)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto rsa_exit; } if (output_size < mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto rsa_exit; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) status = mbedtls_to_psa_error( mbedtls_rsa_pkcs1_encrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, input_length, input, output)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ } else if (PSA_ALG_IS_RSA_OAEP(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) status = mbedtls_to_psa_error( psa_rsa_oaep_set_padding_mode(alg, rsa)); if (status != PSA_SUCCESS) { goto rsa_exit; } status = mbedtls_to_psa_error( mbedtls_rsa_rsaes_oaep_encrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, salt, salt_length, input_length, input, output)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ } else { status = PSA_ERROR_INVALID_ARGUMENT; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) rsa_exit: if (status == PSA_SUCCESS) { *output_length = mbedtls_rsa_get_len(rsa); } mbedtls_rsa_free(rsa); mbedtls_free(rsa); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ } else { status = PSA_ERROR_NOT_SUPPORTED; } return status; } psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; (void) key_buffer; (void) key_buffer_size; (void) input; (void) input_length; (void) salt; (void) salt_length; (void) output; (void) output_size; (void) output_length; *output_length = 0; if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) mbedtls_rsa_context *rsa = NULL; status = mbedtls_psa_rsa_load_representation(attributes->type, key_buffer, key_buffer_size, &rsa); if (status != PSA_SUCCESS) { goto rsa_exit; } if (input_length != mbedtls_rsa_get_len(rsa)) { status = PSA_ERROR_INVALID_ARGUMENT; goto rsa_exit; } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) status = mbedtls_to_psa_error( mbedtls_rsa_pkcs1_decrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, output_length, input, output, output_size)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ } else if (PSA_ALG_IS_RSA_OAEP(alg)) { #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) status = mbedtls_to_psa_error( psa_rsa_oaep_set_padding_mode(alg, rsa)); if (status != PSA_SUCCESS) { goto rsa_exit; } status = mbedtls_to_psa_error( mbedtls_rsa_rsaes_oaep_decrypt(rsa, mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, salt, salt_length, output_length, input, output, output_size)); #else status = PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ } else { status = PSA_ERROR_INVALID_ARGUMENT; } #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) rsa_exit: mbedtls_rsa_free(rsa); mbedtls_free(rsa); #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ } else { status = PSA_ERROR_NOT_SUPPORTED; } return status; } #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.h000066400000000000000000000403731464416617300245440ustar00rootroot00000000000000/* * PSA RSA layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_RSA_H #define PSA_CRYPTO_RSA_H #include #include /** Load the contents of a key buffer into an internal RSA representation * * \param[in] type The type of key contained in \p data. * \param[in] data The buffer from which to load the representation. * \param[in] data_length The size in bytes of \p data. * \param[out] p_rsa Returns a pointer to an RSA context on success. * The caller is responsible for freeing both the * contents of the context and the context itself * when done. */ psa_status_t mbedtls_psa_rsa_load_representation(psa_key_type_t type, const uint8_t *data, size_t data_length, mbedtls_rsa_context **p_rsa); /** Import an RSA key in binary format. * * \note The signature of this function is that of a PSA driver * import_key entry point. This function behaves as an import_key * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes for the key to import. * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. * \param[out] key_buffer The buffer containing the key data in output * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. * \param[out] bits The key size in number of bits. * * \retval #PSA_SUCCESS The RSA key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription */ psa_status_t mbedtls_psa_rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits); /** Export an RSA key to export representation * * \param[in] type The type of key (public/private) to export * \param[in] rsa The internal RSA representation from which to export * \param[out] data The buffer to export to * \param[in] data_size The length of the buffer to export to * \param[out] data_length The amount of bytes written to \p data */ psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, size_t data_size, size_t *data_length); /** Export a public RSA key or the public part of an RSA key pair in binary * format. * * \note The signature of this function is that of a PSA driver * export_public_key entry point. This function behaves as an * export_public_key entry point as defined in the PSA driver interface * specification. * * \param[in] attributes The attributes for the key to export. * \param[in] key_buffer Material or context of the key to export. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[out] data Buffer where the key data is to be written. * \param[in] data_size Size of the \p data buffer in bytes. * \param[out] data_length On success, the number of bytes written in * \p data. * * \retval #PSA_SUCCESS The RSA public key was exported successfully. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length); /** * \brief Generate an RSA key. * * \note The signature of the function is that of a PSA driver generate_key * entry point. * * \param[in] attributes The attributes for the RSA key to generate. * \param[in] params Production parameters for the key * generation. This function only uses * `params->data`, * which contains the public exponent. * This can be a null pointer if * \c params_data_length is 0. * \param params_data_length Length of `params->data` in bytes. * This can be 0, in which case the * public exponent will be 65537. * \param[out] key_buffer Buffer where the key data is to be written. * \param[in] key_buffer_size Size of \p key_buffer in bytes. * \param[out] key_buffer_length On success, the number of bytes written in * \p key_buffer. * * \retval #PSA_SUCCESS * The key was successfully generated. * \retval #PSA_ERROR_NOT_SUPPORTED * Key length or type not supported. * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of \p key_buffer is too small. */ psa_status_t mbedtls_psa_rsa_generate_key( const psa_key_attributes_t *attributes, const psa_key_production_parameters_t *params, size_t params_data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length); /** Sign an already-calculated hash with an RSA private key. * * \note The signature of this function is that of a PSA driver * sign_hash entry point. This function behaves as a sign_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the RSA key to use for the * operation. * \param[in] key_buffer The buffer containing the RSA key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * an RSA key. * \param[in] hash The hash or message to sign. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[out] signature Buffer where the signature is to be written. * \param[in] signature_size Size of the \p signature buffer in bytes. * \param[out] signature_length On success, the number of bytes * that make up the returned signature value. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p signature buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits, * \p alg) where \c key_bits is the bit-size of the RSA key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription */ psa_status_t mbedtls_psa_rsa_sign_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, uint8_t *signature, size_t signature_size, size_t *signature_length); /** * \brief Verify the signature a hash or short message using a public RSA key. * * \note The signature of this function is that of a PSA driver * verify_hash entry point. This function behaves as a verify_hash * entry point as defined in the PSA driver interface specification for * transparent drivers. * * \param[in] attributes The attributes of the RSA key to use for the * operation. * \param[in] key_buffer The buffer containing the RSA key context. * format. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] alg A signature algorithm that is compatible with * an RSA key. * \param[in] hash The hash or message whose signature is to be * verified. * \param[in] hash_length Size of the \p hash buffer in bytes. * \param[in] signature Buffer containing the signature to verify. * \param[in] signature_length Size of the \p signature buffer in bytes. * * \retval #PSA_SUCCESS * The signature is valid. * \retval #PSA_ERROR_INVALID_SIGNATURE * The calculation was performed successfully, but the passed * signature is not a valid signature. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription */ psa_status_t mbedtls_psa_rsa_verify_hash( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); /** * \brief Encrypt a short message with a public key. * * \param attributes The attributes for the key to import. * \param key_buffer Buffer where the key data is to be written. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the encrypted message is to * be written. * \param output_size Size of the \p output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); /** * \brief Decrypt a short message with a private key. * * \param attributes The attributes for the key to import. * \param key_buffer Buffer where the key data is to be written. * \param key_buffer_size Size of the \p key_buffer buffer in bytes. * \param[in] input The message to decrypt. * \param input_length Size of the \p input buffer in bytes. * \param[in] salt A salt or label, if supported by the * encryption algorithm. * If the algorithm does not support a * salt, pass \c NULL. * If the algorithm supports an optional * salt and you do not want to pass a salt, * pass \c NULL. * * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is * supported. * \param salt_length Size of the \p salt buffer in bytes. * If \p salt is \c NULL, pass 0. * \param[out] output Buffer where the decrypted message is to * be written. * \param output_size Size of the \c output buffer in bytes. * \param[out] output_length On success, the number of bytes * that make up the returned output. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. You can * determine a sufficient buffer size by calling * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) * where \c key_type and \c key_bits are the type and bit-size * respectively of \p key. * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription * \retval #PSA_ERROR_INVALID_PADDING \emptydescription * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. */ psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input, size_t input_length, const uint8_t *salt, size_t salt_length, uint8_t *output, size_t output_size, size_t *output_length); #endif /* PSA_CRYPTO_RSA_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_se.c000066400000000000000000000277601464416617300243660ustar00rootroot00000000000000/* * PSA crypto support for secure element drivers */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include #include #include "psa/crypto_se_driver.h" #include "psa_crypto_se.h" #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "psa_crypto_its.h" #else /* Native ITS implementation */ #include "psa/error.h" #include "psa/internal_trusted_storage.h" #endif #include "mbedtls/platform.h" /****************************************************************/ /* Driver lookup */ /****************************************************************/ /* This structure is identical to psa_drv_se_context_t declared in * `crypto_se_driver.h`, except that some parts are writable here * (non-const, or pointer to non-const). */ typedef struct { void *persistent_data; size_t persistent_data_size; uintptr_t transient_data; } psa_drv_se_internal_context_t; struct psa_se_drv_table_entry_s { psa_key_location_t location; const psa_drv_se_t *methods; union { psa_drv_se_internal_context_t internal; psa_drv_se_context_t context; } u; }; static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; psa_se_drv_table_entry_t *psa_get_se_driver_entry( psa_key_lifetime_t lifetime) { size_t i; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime); /* In the driver table, location=0 means an entry that isn't used. * No driver has a location of 0 because it's a reserved value * (which designates transparent keys). Make sure we never return * a driver entry for location 0. */ if (location == 0) { return NULL; } for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { if (driver_table[i].location == location) { return &driver_table[i]; } } return NULL; } const psa_drv_se_t *psa_get_se_driver_methods( const psa_se_drv_table_entry_t *driver) { return driver->methods; } psa_drv_se_context_t *psa_get_se_driver_context( psa_se_drv_table_entry_t *driver) { return &driver->u.context; } int psa_get_se_driver(psa_key_lifetime_t lifetime, const psa_drv_se_t **p_methods, psa_drv_se_context_t **p_drv_context) { psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); if (p_methods != NULL) { *p_methods = (driver ? driver->methods : NULL); } if (p_drv_context != NULL) { *p_drv_context = (driver ? &driver->u.context : NULL); } return driver != NULL; } /****************************************************************/ /* Persistent data management */ /****************************************************************/ static psa_status_t psa_get_se_driver_its_file_uid( const psa_se_drv_table_entry_t *driver, psa_storage_uid_t *uid) { if (driver->location > PSA_MAX_SE_LOCATION) { return PSA_ERROR_NOT_SUPPORTED; } /* ITS file sizes are limited to 32 bits. */ if (driver->u.internal.persistent_data_size > UINT32_MAX) { return PSA_ERROR_NOT_SUPPORTED; } /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; return PSA_SUCCESS; } psa_status_t psa_load_se_persistent_data( const psa_se_drv_table_entry_t *driver) { psa_status_t status; psa_storage_uid_t uid; size_t length; status = psa_get_se_driver_its_file_uid(driver, &uid); if (status != PSA_SUCCESS) { return status; } /* Read the amount of persistent data that the driver requests. * If the data in storage is larger, it is truncated. If the data * in storage is smaller, silently keep what is already at the end * of the output buffer. */ /* psa_get_se_driver_its_file_uid ensures that the size_t * persistent_data_size is in range, but compilers don't know that, * so cast to reassure them. */ return psa_its_get(uid, 0, (uint32_t) driver->u.internal.persistent_data_size, driver->u.internal.persistent_data, &length); } psa_status_t psa_save_se_persistent_data( const psa_se_drv_table_entry_t *driver) { psa_status_t status; psa_storage_uid_t uid; status = psa_get_se_driver_its_file_uid(driver, &uid); if (status != PSA_SUCCESS) { return status; } /* psa_get_se_driver_its_file_uid ensures that the size_t * persistent_data_size is in range, but compilers don't know that, * so cast to reassure them. */ return psa_its_set(uid, (uint32_t) driver->u.internal.persistent_data_size, driver->u.internal.persistent_data, 0); } psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location) { psa_storage_uid_t uid; if (location > PSA_MAX_SE_LOCATION) { return PSA_ERROR_NOT_SUPPORTED; } uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location; return psa_its_remove(uid); } psa_status_t psa_find_se_slot_for_key( const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_se_drv_table_entry_t *driver, psa_key_slot_number_t *slot_number) { psa_status_t status; psa_key_location_t key_location = PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes)); /* If the location is wrong, it's a bug in the library. */ if (driver->location != key_location) { return PSA_ERROR_CORRUPTION_DETECTED; } /* If the driver doesn't support key creation in any way, give up now. */ if (driver->methods->key_management == NULL) { return PSA_ERROR_NOT_SUPPORTED; } if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) { /* The application wants to use a specific slot. Allow it if * the driver supports it. On a system with isolation, * the crypto service must check that the application is * permitted to request this slot. */ psa_drv_se_validate_slot_number_t p_validate_slot_number = driver->methods->key_management->p_validate_slot_number; if (p_validate_slot_number == NULL) { return PSA_ERROR_NOT_SUPPORTED; } status = p_validate_slot_number(&driver->u.context, driver->u.internal.persistent_data, attributes, method, *slot_number); } else if (method == PSA_KEY_CREATION_REGISTER) { /* The application didn't specify a slot number. This doesn't * make sense when registering a slot. */ return PSA_ERROR_INVALID_ARGUMENT; } else { /* The application didn't tell us which slot to use. Let the driver * choose. This is the normal case. */ psa_drv_se_allocate_key_t p_allocate = driver->methods->key_management->p_allocate; if (p_allocate == NULL) { return PSA_ERROR_NOT_SUPPORTED; } status = p_allocate(&driver->u.context, driver->u.internal.persistent_data, attributes, method, slot_number); } return status; } psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver, psa_key_slot_number_t slot_number) { psa_status_t status; psa_status_t storage_status; /* Normally a missing method would mean that the action is not * supported. But psa_destroy_key() is not supposed to return * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should * be able to destroy it. The only use case for a driver that * does not have a way to destroy keys at all is if the keys are * locked in a read-only state: we can use the keys but not * destroy them. Hence, if the driver doesn't support destroying * keys, it's really a lack of permission. */ if (driver->methods->key_management == NULL || driver->methods->key_management->p_destroy == NULL) { return PSA_ERROR_NOT_PERMITTED; } status = driver->methods->key_management->p_destroy( &driver->u.context, driver->u.internal.persistent_data, slot_number); storage_status = psa_save_se_persistent_data(driver); return status == PSA_SUCCESS ? storage_status : status; } psa_status_t psa_init_all_se_drivers(void) { size_t i; for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { psa_se_drv_table_entry_t *driver = &driver_table[i]; if (driver->location == 0) { continue; /* skipping unused entry */ } const psa_drv_se_t *methods = psa_get_se_driver_methods(driver); if (methods->p_init != NULL) { psa_status_t status = methods->p_init( &driver->u.context, driver->u.internal.persistent_data, driver->location); if (status != PSA_SUCCESS) { return status; } status = psa_save_se_persistent_data(driver); if (status != PSA_SUCCESS) { return status; } } } return PSA_SUCCESS; } /****************************************************************/ /* Driver registration */ /****************************************************************/ psa_status_t psa_register_se_driver( psa_key_location_t location, const psa_drv_se_t *methods) { size_t i; psa_status_t status; if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) { return PSA_ERROR_NOT_SUPPORTED; } /* Driver table entries are 0-initialized. 0 is not a valid driver * location because it means a transparent key. */ MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0, "Secure element support requires 0 to mean a local key"); if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) { return PSA_ERROR_INVALID_ARGUMENT; } if (location > PSA_MAX_SE_LOCATION) { return PSA_ERROR_NOT_SUPPORTED; } for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { if (driver_table[i].location == 0) { break; } /* Check that location isn't already in use up to the first free * entry. Since entries are created in order and never deleted, * there can't be a used entry after the first free entry. */ if (driver_table[i].location == location) { return PSA_ERROR_ALREADY_EXISTS; } } if (i == PSA_MAX_SE_DRIVERS) { return PSA_ERROR_INSUFFICIENT_MEMORY; } driver_table[i].location = location; driver_table[i].methods = methods; driver_table[i].u.internal.persistent_data_size = methods->persistent_data_size; if (methods->persistent_data_size != 0) { driver_table[i].u.internal.persistent_data = mbedtls_calloc(1, methods->persistent_data_size); if (driver_table[i].u.internal.persistent_data == NULL) { status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } /* Load the driver's persistent data. On first use, the persistent * data does not exist in storage, and is initialized to * all-bits-zero by the calloc call just above. */ status = psa_load_se_persistent_data(&driver_table[i]); if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) { goto error; } } return PSA_SUCCESS; error: memset(&driver_table[i], 0, sizeof(driver_table[i])); return status; } void psa_unregister_all_se_drivers(void) { size_t i; for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) { if (driver_table[i].u.internal.persistent_data != NULL) { mbedtls_free(driver_table[i].u.internal.persistent_data); } } memset(driver_table, 0, sizeof(driver_table)); } /****************************************************************/ /* The end */ /****************************************************************/ #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_se.h000066400000000000000000000151331464416617300243620ustar00rootroot00000000000000/* * PSA crypto support for secure element drivers */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SE_H #define PSA_CRYPTO_SE_H /* * Include the build-time configuration information header. Here, we do not * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which * is basically just an alias to it. This is to ease the maintenance of the * TF-PSA-Crypto repository which has a different build system and * configuration. */ #include "psa/build_info.h" #include "psa/crypto.h" #include "psa/crypto_se_driver.h" /** The maximum location value that this implementation supports * for a secure element. * * This is not a characteristic that each PSA implementation has, but a * limitation of the current implementation due to the constraints imposed * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. * * The minimum location value for a secure element is 1, like on any * PSA implementation (0 means a transparent key). */ #define PSA_MAX_SE_LOCATION 255 /** The base of the range of ITS file identifiers for secure element * driver persistent data. * * We use a slice of the implementation reserved range 0xffff0000..0xffffffff, * specifically the range 0xfffffe00..0xfffffeff. The length of this range * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE * which doesn't have a driver. */ #define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ((psa_key_id_t) 0xfffffe00) /** The maximum number of registered secure element driver locations. */ #define PSA_MAX_SE_DRIVERS 4 /** Unregister all secure element drivers. * * \warning Do not call this function while the library is in the initialized * state. This function is only intended to be called at the end * of mbedtls_psa_crypto_free(). */ void psa_unregister_all_se_drivers(void); /** Initialize all secure element drivers. * * Called from psa_crypto_init(). */ psa_status_t psa_init_all_se_drivers(void); /** A structure that describes a registered secure element driver. * * A secure element driver table entry contains a pointer to the * driver's method table as well as the driver context structure. */ typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t; /** Return the secure element driver information for a lifetime value. * * \param lifetime The lifetime value to query. * \param[out] p_methods On output, if there is a driver, * \c *methods points to its method table. * Otherwise \c *methods is \c NULL. * \param[out] p_drv_context On output, if there is a driver, * \c *drv_context points to its context * structure. * Otherwise \c *drv_context is \c NULL. * * \retval 1 * \p lifetime corresponds to a registered driver. * \retval 0 * \p lifetime does not correspond to a registered driver. */ int psa_get_se_driver(psa_key_lifetime_t lifetime, const psa_drv_se_t **p_methods, psa_drv_se_context_t **p_drv_context); /** Return the secure element driver table entry for a lifetime value. * * \param lifetime The lifetime value to query. * * \return The driver table entry for \p lifetime, or * \p NULL if \p lifetime does not correspond to a registered driver. */ psa_se_drv_table_entry_t *psa_get_se_driver_entry( psa_key_lifetime_t lifetime); /** Return the method table for a secure element driver. * * \param[in] driver The driver table entry to access, or \c NULL. * * \return The driver's method table. * \c NULL if \p driver is \c NULL. */ const psa_drv_se_t *psa_get_se_driver_methods( const psa_se_drv_table_entry_t *driver); /** Return the context of a secure element driver. * * \param[in] driver The driver table entry to access, or \c NULL. * * \return A pointer to the driver context. * \c NULL if \p driver is \c NULL. */ psa_drv_se_context_t *psa_get_se_driver_context( psa_se_drv_table_entry_t *driver); /** Find a free slot for a key that is to be created. * * This function calls the relevant method in the driver to find a suitable * slot for a key with the given attributes. * * \param[in] attributes Metadata about the key that is about to be created. * \param[in] driver The driver table entry to query. * \param[out] slot_number On success, a slot number that is free in this * secure element. */ psa_status_t psa_find_se_slot_for_key( const psa_key_attributes_t *attributes, psa_key_creation_method_t method, psa_se_drv_table_entry_t *driver, psa_key_slot_number_t *slot_number); /** Destroy a key in a secure element. * * This function calls the relevant driver method to destroy a key * and updates the driver's persistent data. */ psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver, psa_key_slot_number_t slot_number); /** Load the persistent data of a secure element driver. * * \param driver The driver table entry containing the persistent * data to load from storage. * * \return #PSA_SUCCESS * \return #PSA_ERROR_NOT_SUPPORTED * \return #PSA_ERROR_DOES_NOT_EXIST * \return #PSA_ERROR_STORAGE_FAILURE * \return #PSA_ERROR_DATA_CORRUPT * \return #PSA_ERROR_INVALID_ARGUMENT */ psa_status_t psa_load_se_persistent_data( const psa_se_drv_table_entry_t *driver); /** Save the persistent data of a secure element driver. * * \param[in] driver The driver table entry containing the persistent * data to save to storage. * * \return #PSA_SUCCESS * \return #PSA_ERROR_NOT_SUPPORTED * \return #PSA_ERROR_NOT_PERMITTED * \return #PSA_ERROR_NOT_SUPPORTED * \return #PSA_ERROR_INSUFFICIENT_STORAGE * \return #PSA_ERROR_STORAGE_FAILURE * \return #PSA_ERROR_INVALID_ARGUMENT */ psa_status_t psa_save_se_persistent_data( const psa_se_drv_table_entry_t *driver); /** Destroy the persistent data of a secure element driver. * * This is currently only used for testing. * * \param[in] location The location identifier for the driver whose * persistent data is to be erased. */ psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location); /** The storage representation of a key whose data is in a secure element. */ typedef struct { uint8_t slot_number[sizeof(psa_key_slot_number_t)]; } psa_se_key_data_storage_t; #endif /* PSA_CRYPTO_SE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.c000066400000000000000000000540121464416617300271220ustar00rootroot00000000000000/* * PSA crypto layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_C) #include "psa/crypto.h" #include "psa_crypto_core.h" #include "psa_crypto_driver_wrappers_no_static.h" #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif #include #include #include "mbedtls/platform.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif typedef struct { psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT]; uint8_t key_slots_initialized; } psa_global_data_t; static psa_global_data_t global_data; static uint8_t psa_get_key_slots_initialized(void) { uint8_t initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ initialized = global_data.key_slots_initialized; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex); #endif /* defined(MBEDTLS_THREADING_C) */ return initialized; } int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok) { psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); if ((PSA_KEY_ID_USER_MIN <= key_id) && (key_id <= PSA_KEY_ID_USER_MAX)) { return 1; } if (vendor_ok && (PSA_KEY_ID_VENDOR_MIN <= key_id) && (key_id <= PSA_KEY_ID_VENDOR_MAX)) { return 1; } return 0; } /** Get the description in memory of a key given its identifier and lock it. * * The descriptions of volatile keys and loaded persistent keys are * stored in key slots. This function returns a pointer to the key slot * containing the description of a key given its identifier. * * The function searches the key slots containing the description of the key * with \p key identifier. The function does only read accesses to the key * slots. The function does not load any persistent key thus does not access * any storage. * * For volatile key identifiers, only one key slot is queried as a volatile * key with identifier key_id can only be stored in slot of index * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ). * * On success, the function locks the key slot. It is the responsibility of * the caller to unlock the key slot when it does not access it anymore. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the * key slot containing the description of the key * identified by \p key. * * \retval #PSA_SUCCESS * The pointer to the key slot containing the description of the key * identified by \p key was returned. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid key identifier. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no key with key identifier \p key in the key slots. */ static psa_status_t psa_get_and_lock_key_slot_in_memory( mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); size_t slot_idx; psa_key_slot_t *slot = NULL; if (psa_key_id_is_volatile(key_id)) { slot = &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN]; /* Check if both the PSA key identifier key_id and the owner * identifier of key match those of the key slot. */ if ((slot->state == PSA_SLOT_FULL) && (mbedtls_svc_key_id_equal(key, slot->attr.id))) { status = PSA_SUCCESS; } else { status = PSA_ERROR_DOES_NOT_EXIST; } } else { if (!psa_is_valid_key_id(key, 1)) { return PSA_ERROR_INVALID_HANDLE; } for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { slot = &global_data.key_slots[slot_idx]; /* Only consider slots which are in a full state. */ if ((slot->state == PSA_SLOT_FULL) && (mbedtls_svc_key_id_equal(key, slot->attr.id))) { break; } } status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ? PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; } if (status == PSA_SUCCESS) { status = psa_register_read(slot); if (status == PSA_SUCCESS) { *p_slot = slot; } } return status; } psa_status_t psa_initialize_key_slots(void) { /* Nothing to do: program startup and psa_wipe_all_key_slots() both * guarantee that the key slots are initialized to all-zero, which * means that all the key slots are in a valid, empty state. The global * data mutex is already held when calling this function, so no need to * lock it here, to set the flag. */ global_data.key_slots_initialized = 1; return PSA_SUCCESS; } void psa_wipe_all_key_slots(void) { size_t slot_idx; for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; slot->registered_readers = 1; slot->state = PSA_SLOT_PENDING_DELETION; (void) psa_wipe_key_slot(slot); } /* The global data mutex is already held when calling this function. */ global_data.key_slots_initialized = 0; } psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t slot_idx; psa_key_slot_t *selected_slot, *unused_persistent_key_slot; if (!psa_get_key_slots_initialized()) { status = PSA_ERROR_BAD_STATE; goto error; } selected_slot = unused_persistent_key_slot = NULL; for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; if (slot->state == PSA_SLOT_EMPTY) { selected_slot = slot; break; } if ((unused_persistent_key_slot == NULL) && (slot->state == PSA_SLOT_FULL) && (!psa_key_slot_has_readers(slot)) && (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) { unused_persistent_key_slot = slot; } } /* * If there is no unused key slot and there is at least one unlocked key * slot containing the description of a persistent key, recycle the first * such key slot we encountered. If we later need to operate on the * persistent key we are evicting now, we will reload its description from * storage. */ if ((selected_slot == NULL) && (unused_persistent_key_slot != NULL)) { selected_slot = unused_persistent_key_slot; psa_register_read(selected_slot); status = psa_wipe_key_slot(selected_slot); if (status != PSA_SUCCESS) { goto error; } } if (selected_slot != NULL) { status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY, PSA_SLOT_FILLING); if (status != PSA_SUCCESS) { goto error; } *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + ((psa_key_id_t) (selected_slot - global_data.key_slots)); *p_slot = selected_slot; return PSA_SUCCESS; } status = PSA_ERROR_INSUFFICIENT_MEMORY; error: *p_slot = NULL; *volatile_key_id = 0; return status; } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot) { psa_status_t status = PSA_SUCCESS; uint8_t *key_data = NULL; size_t key_data_length = 0; status = psa_load_persistent_key(&slot->attr, &key_data, &key_data_length); if (status != PSA_SUCCESS) { goto exit; } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Special handling is required for loading keys associated with a * dynamically registered SE interface. */ const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) { psa_se_key_data_storage_t *data; if (key_data_length != sizeof(*data)) { status = PSA_ERROR_DATA_INVALID; goto exit; } data = (psa_se_key_data_storage_t *) key_data; status = psa_copy_key_material_into_slot( slot, data->slot_number, sizeof(data->slot_number)); goto exit; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ status = psa_copy_key_material_into_slot(slot, key_data, key_data_length); if (status != PSA_SUCCESS) { goto exit; } exit: psa_free_persistent_key_data(key_data, key_data_length); return status; } #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE; psa_drv_slot_number_t slot_number = 0; size_t key_buffer_size = 0; size_t key_buffer_length = 0; if (!psa_key_id_is_builtin( MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) { return PSA_ERROR_DOES_NOT_EXIST; } /* Check the platform function to see whether this key actually exists */ status = mbedtls_psa_platform_get_builtin_key( slot->attr.id, &lifetime, &slot_number); if (status != PSA_SUCCESS) { return status; } /* Set required key attributes to ensure get_builtin_key can retrieve the * full attributes. */ psa_set_key_id(&attributes, slot->attr.id); psa_set_key_lifetime(&attributes, lifetime); /* Get the full key attributes from the driver in order to be able to * calculate the required buffer size. */ status = psa_driver_wrapper_get_builtin_key( slot_number, &attributes, NULL, 0, NULL); if (status != PSA_ERROR_BUFFER_TOO_SMALL) { /* Builtin keys cannot be defined by the attributes alone */ if (status == PSA_SUCCESS) { status = PSA_ERROR_CORRUPTION_DETECTED; } return status; } /* If the key should exist according to the platform, then ask the driver * what its expected size is. */ status = psa_driver_wrapper_get_key_buffer_size(&attributes, &key_buffer_size); if (status != PSA_SUCCESS) { return status; } /* Allocate a buffer of the required size and load the builtin key directly * into the (now properly sized) slot buffer. */ status = psa_allocate_buffer_to_slot(slot, key_buffer_size); if (status != PSA_SUCCESS) { return status; } status = psa_driver_wrapper_get_builtin_key( slot_number, &attributes, slot->key.data, slot->key.bytes, &key_buffer_length); if (status != PSA_SUCCESS) { goto exit; } /* Copy actual key length and core attributes into the slot on success */ slot->key.bytes = key_buffer_length; slot->attr = attributes; exit: if (status != PSA_SUCCESS) { psa_remove_key_data_from_memory(slot); } return status; } #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *p_slot = NULL; if (!psa_get_key_slots_initialized()) { return PSA_ERROR_BAD_STATE; } #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; /* If the key is persistent and not loaded, we cannot unlock the mutex * between checking if the key is loaded and setting the slot as FULL, * as otherwise another thread may load and then destroy the key * in the meantime. */ PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif /* * On success, the pointer to the slot is passed directly to the caller * thus no need to unlock the key slot here. */ status = psa_get_and_lock_key_slot_in_memory(key, p_slot); if (status != PSA_ERROR_DOES_NOT_EXIST) { #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } /* Loading keys from storage requires support for such a mechanism */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) psa_key_id_t volatile_key_id; status = psa_reserve_free_key_slot(&volatile_key_id, p_slot); if (status != PSA_SUCCESS) { #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } (*p_slot)->attr.id = key; (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; status = PSA_ERROR_DOES_NOT_EXIST; #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) /* Load keys in the 'builtin' range through their own interface */ status = psa_load_builtin_key_into_slot(*p_slot); #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (status == PSA_ERROR_DOES_NOT_EXIST) { status = psa_load_persistent_key_into_slot(*p_slot); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ if (status != PSA_SUCCESS) { psa_wipe_key_slot(*p_slot); if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } } else { /* Add implicit usage flags. */ psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage); psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING, PSA_SLOT_FULL); status = psa_register_read(*p_slot); } #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ status = PSA_ERROR_INVALID_HANDLE; #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } psa_status_t psa_unregister_read(psa_key_slot_t *slot) { if (slot == NULL) { return PSA_SUCCESS; } if ((slot->state != PSA_SLOT_FULL) && (slot->state != PSA_SLOT_PENDING_DELETION)) { return PSA_ERROR_CORRUPTION_DETECTED; } /* If we are the last reader and the slot is marked for deletion, * we must wipe the slot here. */ if ((slot->state == PSA_SLOT_PENDING_DELETION) && (slot->registered_readers == 1)) { return psa_wipe_key_slot(slot); } if (psa_key_slot_has_readers(slot)) { slot->registered_readers--; return PSA_SUCCESS; } /* * As the return error code may not be handled in case of multiple errors, * do our best to report if there are no registered readers. Assert with * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers: * if the MBEDTLS_TEST_HOOKS configuration option is enabled and * the function is called as part of the execution of a test suite, the * execution of the test suite is stopped in error if the assertion fails. */ MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot)); return PSA_ERROR_CORRUPTION_DETECTED; } psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_unregister_read(slot); #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, psa_se_drv_table_entry_t **p_drv) { if (psa_key_lifetime_is_external(lifetime)) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* Check whether a driver is registered against this lifetime */ psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime); if (driver != NULL) { if (p_drv != NULL) { *p_drv = driver; } return PSA_SUCCESS; } #else /* MBEDTLS_PSA_CRYPTO_SE_C */ (void) p_drv; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ /* Key location for external keys gets checked by the wrapper */ return PSA_SUCCESS; } else { /* Local/internal keys are always valid */ return PSA_SUCCESS; } } psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime) { if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) { /* Volatile keys are always supported */ return PSA_SUCCESS; } else { /* Persistent keys require storage support */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) { return PSA_ERROR_INVALID_ARGUMENT; } else { return PSA_SUCCESS; } #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ return PSA_ERROR_NOT_SUPPORTED; #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ } } psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle) { #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) psa_status_t status; psa_key_slot_t *slot; status = psa_get_and_lock_key_slot(key, &slot); if (status != PSA_SUCCESS) { *handle = PSA_KEY_HANDLE_INIT; if (status == PSA_ERROR_INVALID_HANDLE) { status = PSA_ERROR_DOES_NOT_EXIST; } return status; } *handle = key; return psa_unregister_read_under_mutex(slot); #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ (void) key; *handle = PSA_KEY_HANDLE_INIT; return PSA_ERROR_NOT_SUPPORTED; #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ } psa_status_t psa_close_key(psa_key_handle_t handle) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; if (psa_key_handle_is_null(handle)) { return PSA_SUCCESS; } #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_get_and_lock_key_slot_in_memory(handle, &slot); if (status != PSA_SUCCESS) { if (status == PSA_ERROR_DOES_NOT_EXIST) { status = PSA_ERROR_INVALID_HANDLE; } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } if (slot->registered_readers == 1) { status = psa_wipe_key_slot(slot); } else { status = psa_unregister_read(slot); } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } psa_status_t psa_purge_key(mbedtls_svc_key_id_t key) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; #if defined(MBEDTLS_THREADING_C) /* We need to set status as success, otherwise CORRUPTION_DETECTED * would be returned if the lock fails. */ status = PSA_SUCCESS; PSA_THREADING_CHK_RET(mbedtls_mutex_lock( &mbedtls_threading_key_slot_mutex)); #endif status = psa_get_and_lock_key_slot_in_memory(key, &slot); if (status != PSA_SUCCESS) { #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) && (slot->registered_readers == 1)) { status = psa_wipe_key_slot(slot); } else { status = psa_unregister_read(slot); } #if defined(MBEDTLS_THREADING_C) PSA_THREADING_CHK_RET(mbedtls_mutex_unlock( &mbedtls_threading_key_slot_mutex)); #endif return status; } void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats) { size_t slot_idx; memset(stats, 0, sizeof(*stats)); for (slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++) { const psa_key_slot_t *slot = &global_data.key_slots[slot_idx]; if (psa_key_slot_has_readers(slot)) { ++stats->locked_slots; } if (slot->state == PSA_SLOT_EMPTY) { ++stats->empty_slots; continue; } if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) { ++stats->volatile_slots; } else { psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id); ++stats->persistent_slots; if (id > stats->max_open_internal_key_id) { stats->max_open_internal_key_id = id; } } if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) != PSA_KEY_LOCATION_LOCAL_STORAGE) { psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id); ++stats->external_slots; if (id > stats->max_open_external_key_id) { stats->max_open_external_key_id = id; } } } } #endif /* MBEDTLS_PSA_CRYPTO_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.h000066400000000000000000000250611464416617300271310ustar00rootroot00000000000000/* * PSA crypto layer on top of Mbed TLS crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H #define PSA_CRYPTO_SLOT_MANAGEMENT_H #include "psa/crypto.h" #include "psa_crypto_core.h" #include "psa_crypto_se.h" /** Range of volatile key identifiers. * * The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation * range of key identifiers are reserved for volatile key identifiers. * A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the * index of the key slot containing the volatile key definition. */ /** The minimum value for a volatile key identifier. */ #define PSA_KEY_ID_VOLATILE_MIN (PSA_KEY_ID_VENDOR_MAX - \ MBEDTLS_PSA_KEY_SLOT_COUNT + 1) /** The maximum value for a volatile key identifier. */ #define PSA_KEY_ID_VOLATILE_MAX PSA_KEY_ID_VENDOR_MAX /** Test whether a key identifier is a volatile key identifier. * * \param key_id Key identifier to test. * * \retval 1 * The key identifier is a volatile key identifier. * \retval 0 * The key identifier is not a volatile key identifier. */ static inline int psa_key_id_is_volatile(psa_key_id_t key_id) { return (key_id >= PSA_KEY_ID_VOLATILE_MIN) && (key_id <= PSA_KEY_ID_VOLATILE_MAX); } /** Get the description of a key given its identifier and lock it. * * The descriptions of volatile keys and loaded persistent keys are stored in * key slots. This function returns a pointer to the key slot containing the * description of a key given its identifier. * * In case of a persistent key, the function loads the description of the key * into a key slot if not already done. * * On success, the returned key slot has been registered for reading. * It is the responsibility of the caller to call psa_unregister_read(slot) * when they have finished reading the contents of the slot. * * \param key Key identifier to query. * \param[out] p_slot On success, `*p_slot` contains a pointer to the * key slot containing the description of the key * identified by \p key. * * \retval #PSA_SUCCESS * \p *p_slot contains a pointer to the key slot containing the * description of the key identified by \p key. * The key slot counter has been incremented. * \retval #PSA_ERROR_BAD_STATE * The library has not been initialized. * \retval #PSA_ERROR_INVALID_HANDLE * \p key is not a valid key identifier. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \p key is a persistent key identifier. The implementation does not * have sufficient resources to load the persistent key. This can be * due to a lack of empty key slot, or available memory. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no key with key identifier \p key. * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot); /** Initialize the key slot structures. * * \retval #PSA_SUCCESS * Currently this function always succeeds. */ psa_status_t psa_initialize_key_slots(void); /** Delete all data from key slots in memory. * This function is not thread safe, it wipes every key slot regardless of * state and reader count. It should only be called when no slot is in use. * * This does not affect persistent storage. */ void psa_wipe_all_key_slots(void); /** Find a free key slot and reserve it to be filled with a key. * * This function finds a key slot that is free, * sets its state to PSA_SLOT_FILLING and then returns the slot. * * On success, the key slot's state is PSA_SLOT_FILLING. * It is the responsibility of the caller to change the slot's state to * PSA_SLOT_EMPTY/FULL once key creation has finished. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[out] volatile_key_id On success, volatile key identifier * associated to the returned slot. * \param[out] p_slot On success, a pointer to the slot. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * There were no free key slots. * \retval #PSA_ERROR_BAD_STATE \emptydescription * \retval #PSA_ERROR_CORRUPTION_DETECTED * This function attempted to operate on a key slot which was in an * unexpected state. */ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, psa_key_slot_t **p_slot); /** Change the state of a key slot. * * This function changes the state of the key slot from expected_state to * new state. If the state of the slot was not expected_state, the state is * unchanged. * * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in] slot The key slot. * \param[in] expected_state The current state of the slot. * \param[in] new_state The new state of the slot. * * \retval #PSA_SUCCESS The key slot's state variable is new_state. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was not expected_state. */ static inline psa_status_t psa_key_slot_state_transition( psa_key_slot_t *slot, psa_key_slot_state_t expected_state, psa_key_slot_state_t new_state) { if (slot->state != expected_state) { return PSA_ERROR_CORRUPTION_DETECTED; } slot->state = new_state; return PSA_SUCCESS; } /** Register as a reader of a key slot. * * This function increments the key slot registered reader counter by one. * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \param[in] slot The key slot. * * \retval #PSA_SUCCESS The key slot registered reader counter was incremented. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The reader counter already reached its maximum value and was not * increased, or the slot's state was not PSA_SLOT_FULL. */ static inline psa_status_t psa_register_read(psa_key_slot_t *slot) { if ((slot->state != PSA_SLOT_FULL) || (slot->registered_readers >= SIZE_MAX)) { return PSA_ERROR_CORRUPTION_DETECTED; } slot->registered_readers++; return PSA_SUCCESS; } /** Unregister from reading a key slot. * * This function decrements the key slot registered reader counter by one. * If the state of the slot is PSA_SLOT_PENDING_DELETION, * and there is only one registered reader (the caller), * this function will call psa_wipe_key_slot(). * If multi-threading is enabled, the caller must hold the * global key slot mutex. * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns * successfully without doing anything in that case. * * \param[in] slot The key slot. * \retval #PSA_SUCCESS * \p slot is NULL or the key slot reader counter has been * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was neither PSA_SLOT_FULL nor * PSA_SLOT_PENDING_DELETION. * Or a wipe was attempted and the slot's state was not * PSA_SLOT_PENDING_DELETION. * Or registered_readers was equal to 0. */ psa_status_t psa_unregister_read(psa_key_slot_t *slot); /** Wrap a call to psa_unregister_read in the global key slot mutex. * * If threading is disabled, this simply calls psa_unregister_read. * * \note To ease the handling of errors in retrieving a key slot * a NULL input pointer is valid, and the function returns * successfully without doing anything in that case. * * \param[in] slot The key slot. * \retval #PSA_SUCCESS * \p slot is NULL or the key slot reader counter has been * decremented (and potentially wiped) successfully. * \retval #PSA_ERROR_CORRUPTION_DETECTED * The slot's state was neither PSA_SLOT_FULL nor * PSA_SLOT_PENDING_DELETION. * Or a wipe was attempted and the slot's state was not * PSA_SLOT_PENDING_DELETION. * Or registered_readers was equal to 0. */ psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot); /** Test whether a lifetime designates a key in an external cryptoprocessor. * * \param lifetime The lifetime to test. * * \retval 1 * The lifetime designates an external key. There should be a * registered driver for this lifetime, otherwise the key cannot * be created or manipulated. * \retval 0 * The lifetime designates a key that is volatile or in internal * storage. */ static inline int psa_key_lifetime_is_external(psa_key_lifetime_t lifetime) { return PSA_KEY_LIFETIME_GET_LOCATION(lifetime) != PSA_KEY_LOCATION_LOCAL_STORAGE; } /** Validate a key's location. * * This function checks whether the key's attributes point to a location that * is known to the PSA Core, and returns the driver function table if the key * is to be found in an external location. * * \param[in] lifetime The key lifetime attribute. * \param[out] p_drv On success, when a key is located in external * storage, returns a pointer to the driver table * associated with the key's storage location. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription */ psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, psa_se_drv_table_entry_t **p_drv); /** Validate the persistence of a key. * * \param[in] lifetime The key lifetime attribute. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys * are not supported. */ psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime); /** Validate a key identifier. * * \param[in] key The key identifier. * \param[in] vendor_ok Non-zero to indicate that key identifiers in the * vendor range are allowed, volatile key identifiers * excepted \c 0 otherwise. * * \retval <> 0 if the key identifier is valid, 0 otherwise. */ int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok); #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_storage.c000066400000000000000000000375221464416617300254200ustar00rootroot00000000000000/* * PSA persistent key storage */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) #include #include #include "psa/crypto.h" #include "psa_crypto_storage.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "psa_crypto_its.h" #else /* Native ITS implementation */ #include "psa/error.h" #include "psa/internal_trusted_storage.h" #endif #include "mbedtls/platform.h" /****************************************************************/ /* Key storage */ /****************************************************************/ /* Determine a file name (ITS file identifier) for the given key identifier. * The file name must be distinct from any file that is used for a purpose * other than storing a key. Currently, the only such file is the random seed * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is * 0xFFFFFF52. */ static psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key) { #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) /* Encode the owner in the upper 32 bits. This means that if * owner values are nonzero (as they are on a PSA platform), * no key file will ever have a value less than 0x100000000, so * the whole range 0..0xffffffff is available for non-key files. */ uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key); return ((uint64_t) unsigned_owner_id << 32) | MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key); #else /* Use the key id directly as a file name. * psa_is_key_id_valid() in psa_crypto_slot_management.c * is responsible for ensuring that key identifiers do not have a * value that is reserved for non-key files. */ return key; #endif } /** * \brief Load persistent data for the given key slot number. * * This function reads data from a storage backend and returns the data in a * buffer. * * \param key Persistent identifier of the key to be loaded. This * should be an occupied storage location. * \param[out] data Buffer where the data is to be written. * \param data_size Size of the \c data buffer in bytes. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription */ static psa_status_t psa_crypto_storage_load( const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size) { psa_status_t status; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; size_t data_length = 0; status = psa_its_get_info(data_identifier, &data_identifier_info); if (status != PSA_SUCCESS) { return status; } status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length); if (data_size != data_length) { return PSA_ERROR_DATA_INVALID; } return status; } int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key) { psa_status_t ret; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; ret = psa_its_get_info(data_identifier, &data_identifier_info); if (ret == PSA_ERROR_DOES_NOT_EXIST) { return 0; } return 1; } /** * \brief Store persistent data for the given key slot number. * * This function stores the given data buffer to a persistent storage. * * \param key Persistent identifier of the key to be stored. This * should be an unoccupied storage location. * \param[in] data Buffer containing the data to be stored. * \param data_length The number of bytes * that make up the data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key, const uint8_t *data, size_t data_length) { psa_status_t status; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; if (psa_is_key_present_in_storage(key) == 1) { return PSA_ERROR_ALREADY_EXISTS; } status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0); if (status != PSA_SUCCESS) { return PSA_ERROR_DATA_INVALID; } status = psa_its_get_info(data_identifier, &data_identifier_info); if (status != PSA_SUCCESS) { goto exit; } if (data_identifier_info.size != data_length) { status = PSA_ERROR_DATA_INVALID; goto exit; } exit: if (status != PSA_SUCCESS) { /* Remove the file in case we managed to create it but something * went wrong. It's ok if the file doesn't exist. If the file exists * but the removal fails, we're already reporting an error so there's * nothing else we can do. */ (void) psa_its_remove(data_identifier); } return status; } psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key) { psa_status_t ret; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; ret = psa_its_get_info(data_identifier, &data_identifier_info); if (ret == PSA_ERROR_DOES_NOT_EXIST) { return PSA_SUCCESS; } if (psa_its_remove(data_identifier) != PSA_SUCCESS) { return PSA_ERROR_DATA_INVALID; } ret = psa_its_get_info(data_identifier, &data_identifier_info); if (ret != PSA_ERROR_DOES_NOT_EXIST) { return PSA_ERROR_DATA_INVALID; } return PSA_SUCCESS; } /** * \brief Get data length for given key slot number. * * \param key Persistent identifier whose stored data length * is to be obtained. * \param[out] data_length The number of bytes that make up the data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ static psa_status_t psa_crypto_storage_get_data_length( const mbedtls_svc_key_id_t key, size_t *data_length) { psa_status_t status; psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key); struct psa_storage_info_t data_identifier_info; status = psa_its_get_info(data_identifier, &data_identifier_info); if (status != PSA_SUCCESS) { return status; } *data_length = (size_t) data_identifier_info.size; return PSA_SUCCESS; } /** * Persistent key storage magic header. */ #define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" #define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER)) typedef struct { uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; uint8_t version[4]; uint8_t lifetime[sizeof(psa_key_lifetime_t)]; uint8_t type[2]; uint8_t bits[2]; uint8_t policy[sizeof(psa_key_policy_t)]; uint8_t data_len[4]; uint8_t key_data[]; } psa_persistent_key_storage_format; void psa_format_key_data_for_storage(const uint8_t *data, const size_t data_length, const psa_key_attributes_t *attr, uint8_t *storage_data) { psa_persistent_key_storage_format *storage_format = (psa_persistent_key_storage_format *) storage_data; memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH); MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0); MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0); MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0); MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0); MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0); MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t)); MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t)); MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0); memcpy(storage_format->key_data, data, data_length); } static psa_status_t check_magic_header(const uint8_t *data) { if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) { return PSA_ERROR_DATA_INVALID; } return PSA_SUCCESS; } psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, psa_key_attributes_t *attr) { psa_status_t status; const psa_persistent_key_storage_format *storage_format = (const psa_persistent_key_storage_format *) storage_data; uint32_t version; if (storage_data_length < sizeof(*storage_format)) { return PSA_ERROR_DATA_INVALID; } status = check_magic_header(storage_data); if (status != PSA_SUCCESS) { return status; } version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0); if (version != 0) { return PSA_ERROR_DATA_INVALID; } *key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0); if (*key_data_length > (storage_data_length - sizeof(*storage_format)) || *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { return PSA_ERROR_DATA_INVALID; } if (*key_data_length == 0) { *key_data = NULL; } else { *key_data = mbedtls_calloc(1, *key_data_length); if (*key_data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } memcpy(*key_data, storage_format->key_data, *key_data_length); } attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0); attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0); attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0); attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0); attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t)); attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t)); return PSA_SUCCESS; } psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, const uint8_t *data, const size_t data_length) { size_t storage_data_length; uint8_t *storage_data; psa_status_t status; /* All keys saved to persistent storage always have a key context */ if (data == NULL || data_length == 0) { return PSA_ERROR_INVALID_ARGUMENT; } if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) { return PSA_ERROR_INSUFFICIENT_STORAGE; } storage_data_length = data_length + sizeof(psa_persistent_key_storage_format); storage_data = mbedtls_calloc(1, storage_data_length); if (storage_data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } psa_format_key_data_for_storage(data, data_length, attr, storage_data); status = psa_crypto_storage_store(attr->id, storage_data, storage_data_length); mbedtls_zeroize_and_free(storage_data, storage_data_length); return status; } void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length) { mbedtls_zeroize_and_free(key_data, key_data_length); } psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, uint8_t **data, size_t *data_length) { psa_status_t status = PSA_SUCCESS; uint8_t *loaded_data; size_t storage_data_length = 0; mbedtls_svc_key_id_t key = attr->id; status = psa_crypto_storage_get_data_length(key, &storage_data_length); if (status != PSA_SUCCESS) { return status; } loaded_data = mbedtls_calloc(1, storage_data_length); if (loaded_data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } status = psa_crypto_storage_load(key, loaded_data, storage_data_length); if (status != PSA_SUCCESS) { goto exit; } status = psa_parse_key_data_from_storage(loaded_data, storage_data_length, data, data_length, attr); /* All keys saved to persistent storage always have a key context */ if (status == PSA_SUCCESS && (*data == NULL || *data_length == 0)) { status = PSA_ERROR_STORAGE_FAILURE; } exit: mbedtls_zeroize_and_free(loaded_data, storage_data_length); return status; } /****************************************************************/ /* Transactions */ /****************************************************************/ #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) psa_crypto_transaction_t psa_crypto_transaction; psa_status_t psa_crypto_save_transaction(void) { struct psa_storage_info_t p_info; psa_status_t status; status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info); if (status == PSA_SUCCESS) { /* This shouldn't happen: we're trying to start a transaction while * there is still a transaction that hasn't been replayed. */ return PSA_ERROR_CORRUPTION_DETECTED; } else if (status != PSA_ERROR_DOES_NOT_EXIST) { return status; } return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID, sizeof(psa_crypto_transaction), &psa_crypto_transaction, 0); } psa_status_t psa_crypto_load_transaction(void) { psa_status_t status; size_t length; status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0, sizeof(psa_crypto_transaction), &psa_crypto_transaction, &length); if (status != PSA_SUCCESS) { return status; } if (length != sizeof(psa_crypto_transaction)) { return PSA_ERROR_DATA_INVALID; } return PSA_SUCCESS; } psa_status_t psa_crypto_stop_transaction(void) { psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID); /* Whether or not updating the storage succeeded, the transaction is * finished now. It's too late to go back, so zero out the in-memory * data. */ memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction)); return status; } #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ /****************************************************************/ /* Random generator state */ /****************************************************************/ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed, size_t seed_size) { psa_status_t status; struct psa_storage_info_t p_info; status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info); if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */ status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0); } else if (PSA_SUCCESS == status) { /* You should not be here. Seed needs to be injected only once */ status = PSA_ERROR_NOT_PERMITTED; } return status; } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ /****************************************************************/ /* The end */ /****************************************************************/ #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_crypto_storage.h000066400000000000000000000355171464416617300254270ustar00rootroot00000000000000/** * \file psa_crypto_storage.h * * \brief PSA cryptography module: Mbed TLS key storage */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef PSA_CRYPTO_STORAGE_H #define PSA_CRYPTO_STORAGE_H #ifdef __cplusplus extern "C" { #endif #include "psa/crypto.h" #include "psa/crypto_se_driver.h" #include #include /* Limit the maximum key size in storage. This should have no effect * since the key size is limited in memory. */ #define PSA_CRYPTO_MAX_STORAGE_SIZE (PSA_BITS_TO_BYTES(PSA_MAX_KEY_BITS)) /* Sanity check: a file size must fit in 32 bits. Allow a generous * 64kB of metadata. */ #if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 #error "PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000" #endif /** The maximum permitted persistent slot number. * * In Mbed Crypto 0.1.0b: * - Using the file backend, all key ids are ok except 0. * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the * device's random seed (if this feature is enabled). * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used. * * Since we need to preserve the random seed, avoid using that key slot. * Reserve a whole range of key slots just in case something else comes up. * * This limitation will probably become moot when we implement client * separation for key storage. */ #define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX /** * \brief Checks if persistent data is stored for the given key slot number * * This function checks if any key data or metadata exists for the key slot in * the persistent storage. * * \param key Persistent identifier to check. * * \retval 0 * No persistent data present for slot number * \retval 1 * Persistent data present for slot number */ int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key); /** * \brief Format key data and metadata and save to a location for given key * slot. * * This function formats the key data and metadata and saves it to a * persistent storage backend. The storage location corresponding to the * key slot must be empty, otherwise this function will fail. This function * should be called after loading the key into an internal slot to ensure the * persistent key is not saved into a storage location corresponding to an * already occupied non-persistent key, as well as ensuring the key data is * validated. * * Note: This function will only succeed for key buffers which are not * empty. If passed a NULL pointer or zero-length, the function will fail * with #PSA_ERROR_INVALID_ARGUMENT. * * \param[in] attr The attributes of the key to save. * The key identifier field in the attributes * determines the key's location. * \param[in] data Buffer containing the key data. * \param data_length The number of bytes that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr, const uint8_t *data, const size_t data_length); /** * \brief Parses key data and metadata and load persistent key for given * key slot number. * * This function reads from a storage backend, parses the key data and * metadata and writes them to the appropriate output parameters. * * Note: This function allocates a buffer and returns a pointer to it through * the data parameter. On successful return, the pointer is guaranteed to be * valid and the buffer contains at least one byte of data. * psa_free_persistent_key_data() must be called on the data buffer * afterwards to zeroize and free this buffer. * * \param[in,out] attr On input, the key identifier field identifies * the key to load. Other fields are ignored. * On success, the attribute structure contains * the key metadata that was loaded from storage. * \param[out] data Pointer to an allocated key data buffer on return. * \param[out] data_length The number of bytes that make up the key data. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription */ psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr, uint8_t **data, size_t *data_length); /** * \brief Remove persistent data for the given key slot number. * * \param key Persistent identifier of the key to remove * from persistent storage. * * \retval #PSA_SUCCESS * The key was successfully removed, * or the key did not exist. * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key); /** * \brief Free the temporary buffer allocated by psa_load_persistent_key(). * * This function must be called at some point after psa_load_persistent_key() * to zeroize and free the memory allocated to the buffer in that function. * * \param key_data Buffer for the key data. * \param key_data_length Size of the key data buffer. * */ void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length); /** * \brief Formats key data and metadata for persistent storage * * \param[in] data Buffer containing the key data. * \param data_length Length of the key data buffer. * \param[in] attr The core attributes of the key. * \param[out] storage_data Output buffer for the formatted data. * */ void psa_format_key_data_for_storage(const uint8_t *data, const size_t data_length, const psa_key_attributes_t *attr, uint8_t *storage_data); /** * \brief Parses persistent storage data into key data and metadata * * \param[in] storage_data Buffer for the storage data. * \param storage_data_length Length of the storage data buffer * \param[out] key_data On output, pointer to a newly allocated buffer * containing the key data. This must be freed * using psa_free_persistent_key_data() * \param[out] key_data_length Length of the key data buffer * \param[out] attr On success, the attribute structure is filled * with the loaded key metadata. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription */ psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, psa_key_attributes_t *attr); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** This symbol is defined if transaction support is required. */ #define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS 1 #endif #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) /** The type of transaction that is in progress. */ /* This is an integer type rather than an enum for two reasons: to support * unknown values when loading a transaction file, and to ensure that the * type has a known size. */ typedef uint16_t psa_crypto_transaction_type_t; /** No transaction is in progress. * * This has the value 0, so zero-initialization sets a transaction's type to * this value. */ #define PSA_CRYPTO_TRANSACTION_NONE ((psa_crypto_transaction_type_t) 0x0000) /** A key creation transaction. * * This is only used for keys in an external cryptoprocessor (secure element). * Keys in RAM or in internal storage are created atomically in storage * (simple file creation), so they do not need a transaction mechanism. */ #define PSA_CRYPTO_TRANSACTION_CREATE_KEY ((psa_crypto_transaction_type_t) 0x0001) /** A key destruction transaction. * * This is only used for keys in an external cryptoprocessor (secure element). * Keys in RAM or in internal storage are destroyed atomically in storage * (simple file deletion), so they do not need a transaction mechanism. */ #define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ((psa_crypto_transaction_type_t) 0x0002) /** Transaction data. * * This type is designed to be serialized by writing the memory representation * and reading it back on the same device. * * \note The transaction mechanism is not thread-safe. There can only be one * single active transaction at a time. * The transaction object is #psa_crypto_transaction. * * \note If an API call starts a transaction, it must complete this transaction * before returning to the application. * * The lifetime of a transaction is the following (note that only one * transaction may be active at a time): * * -# Call psa_crypto_prepare_transaction() to initialize the transaction * object in memory and declare the type of transaction that is starting. * -# Fill in the type-specific fields of #psa_crypto_transaction. * -# Call psa_crypto_save_transaction() to start the transaction. This * saves the transaction data to internal storage. * -# Perform the work of the transaction by modifying files, contacting * external entities, or whatever needs doing. Note that the transaction * may be interrupted by a power failure, so you need to have a way * recover from interruptions either by undoing what has been done * so far or by resuming where you left off. * -# If there are intermediate stages in the transaction, update * the fields of #psa_crypto_transaction and call * psa_crypto_save_transaction() again when each stage is reached. * -# When the transaction is over, call psa_crypto_stop_transaction() to * remove the transaction data in storage and in memory. * * If the system crashes while a transaction is in progress, psa_crypto_init() * calls psa_crypto_load_transaction() and takes care of completing or * rewinding the transaction. This is done in psa_crypto_recover_transaction() * in psa_crypto.c. If you add a new type of transaction, be * sure to add code for it in psa_crypto_recover_transaction(). */ typedef union { /* Each element of this union must have the following properties * to facilitate serialization and deserialization: * * - The element is a struct. * - The first field of the struct is `psa_crypto_transaction_type_t type`. * - Elements of the struct are arranged such a way that there is * no padding. */ struct psa_crypto_transaction_unknown_s { psa_crypto_transaction_type_t type; uint16_t unused1; uint32_t unused2; uint64_t unused3; uint64_t unused4; } unknown; /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ struct psa_crypto_transaction_key_s { psa_crypto_transaction_type_t type; uint16_t unused1; psa_key_lifetime_t lifetime; psa_key_slot_number_t slot; mbedtls_svc_key_id_t id; } key; } psa_crypto_transaction_t; /** The single active transaction. */ extern psa_crypto_transaction_t psa_crypto_transaction; /** Prepare for a transaction. * * There must not be an ongoing transaction. * * \param type The type of transaction to start. */ static inline void psa_crypto_prepare_transaction( psa_crypto_transaction_type_t type) { psa_crypto_transaction.unknown.type = type; } /** Save the transaction data to storage. * * You may call this function multiple times during a transaction to * atomically update the transaction state. * * \retval #PSA_SUCCESS \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription */ psa_status_t psa_crypto_save_transaction(void); /** Load the transaction data from storage, if any. * * This function is meant to be called from psa_crypto_init() to recover * in case a transaction was interrupted by a system crash. * * \retval #PSA_SUCCESS * The data about the ongoing transaction has been loaded to * #psa_crypto_transaction. * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no ongoing transaction. * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_DATA_INVALID \emptydescription * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription */ psa_status_t psa_crypto_load_transaction(void); /** Indicate that the current transaction is finished. * * Call this function at the very end of transaction processing. * This function does not "commit" or "abort" the transaction: the storage * subsystem has no concept of "commit" and "abort", just saving and * removing the transaction information in storage. * * This function erases the transaction data in storage (if any) and * resets the transaction data in memory. * * \retval #PSA_SUCCESS * There was transaction data in storage. * \retval #PSA_ERROR_DOES_NOT_EXIST * There was no transaction data in storage. * \retval #PSA_ERROR_STORAGE_FAILURE * It was impossible to determine whether there was transaction data * in storage, or the transaction data could not be erased. */ psa_status_t psa_crypto_stop_transaction(void); /** The ITS file identifier for the transaction data. * * 0xffffffNN = special file; 0x74 = 't' for transaction. */ #define PSA_CRYPTO_ITS_TRANSACTION_UID ((psa_key_id_t) 0xffffff74) #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) /** Backend side of mbedtls_psa_inject_entropy(). * * This function stores the supplied data into the entropy seed file. * * \retval #PSA_SUCCESS * Success * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription * \retval #PSA_ERROR_NOT_PERMITTED * The entropy seed file already exists. */ psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed, size_t seed_size); #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ #ifdef __cplusplus } #endif #endif /* PSA_CRYPTO_STORAGE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_its_file.c000066400000000000000000000162311464416617300241440ustar00rootroot00000000000000/* * PSA ITS simulator over stdio files. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PSA_ITS_FILE_C) #include "mbedtls/platform.h" #if defined(_WIN32) #include #endif #include "psa_crypto_its.h" #include #include #include #include #if !defined(PSA_ITS_STORAGE_PREFIX) #define PSA_ITS_STORAGE_PREFIX "" #endif #define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x" #define PSA_ITS_STORAGE_SUFFIX ".psa_its" #define PSA_ITS_STORAGE_FILENAME_LENGTH \ (sizeof(PSA_ITS_STORAGE_PREFIX) - 1 + /*prefix without terminating 0*/ \ 16 + /*UID (64-bit number in hex)*/ \ sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 + /*suffix without terminating 0*/ \ 1 /*terminating null byte*/) #define PSA_ITS_STORAGE_TEMP \ PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX /* The maximum value of psa_storage_info_t.size */ #define PSA_ITS_MAX_SIZE 0xffffffff #define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" #define PSA_ITS_MAGIC_LENGTH 8 /* As rename fails on Windows if the new filepath already exists, * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. * Returns 0 on success, nonzero on failure. */ #if defined(_WIN32) #define rename_replace_existing(oldpath, newpath) \ (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) #else #define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath) #endif typedef struct { uint8_t magic[PSA_ITS_MAGIC_LENGTH]; uint8_t size[sizeof(uint32_t)]; uint8_t flags[sizeof(psa_storage_create_flags_t)]; } psa_its_file_header_t; static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename) { /* Break up the UID into two 32-bit pieces so as not to rely on * long long support in snprintf. */ mbedtls_snprintf(filename, PSA_ITS_STORAGE_FILENAME_LENGTH, "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", PSA_ITS_STORAGE_PREFIX, (unsigned) (uid >> 32), (unsigned) (uid & 0xffffffff), PSA_ITS_STORAGE_SUFFIX); } static psa_status_t psa_its_read_file(psa_storage_uid_t uid, struct psa_storage_info_t *p_info, FILE **p_stream) { char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; psa_its_file_header_t header; size_t n; *p_stream = NULL; psa_its_fill_filename(uid, filename); *p_stream = fopen(filename, "rb"); if (*p_stream == NULL) { return PSA_ERROR_DOES_NOT_EXIST; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(*p_stream, NULL); n = fread(&header, 1, sizeof(header), *p_stream); if (n != sizeof(header)) { return PSA_ERROR_DATA_CORRUPT; } if (memcmp(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH) != 0) { return PSA_ERROR_DATA_CORRUPT; } p_info->size = MBEDTLS_GET_UINT32_LE(header.size, 0); p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0); return PSA_SUCCESS; } psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) { psa_status_t status; FILE *stream = NULL; status = psa_its_read_file(uid, p_info, &stream); if (stream != NULL) { fclose(stream); } return status; } psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data, size_t *p_data_length) { psa_status_t status; FILE *stream = NULL; size_t n; struct psa_storage_info_t info; status = psa_its_read_file(uid, &info, &stream); if (status != PSA_SUCCESS) { goto exit; } status = PSA_ERROR_INVALID_ARGUMENT; if (data_offset + data_length < data_offset) { goto exit; } #if SIZE_MAX < 0xffffffff if (data_offset + data_length > SIZE_MAX) { goto exit; } #endif if (data_offset + data_length > info.size) { goto exit; } status = PSA_ERROR_STORAGE_FAILURE; #if LONG_MAX < 0xffffffff while (data_offset > LONG_MAX) { if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) { goto exit; } data_offset -= LONG_MAX; } #endif if (fseek(stream, data_offset, SEEK_CUR) != 0) { goto exit; } n = fread(p_data, 1, data_length, stream); if (n != data_length) { goto exit; } status = PSA_SUCCESS; if (p_data_length != NULL) { *p_data_length = n; } exit: if (stream != NULL) { fclose(stream); } return status; } psa_status_t psa_its_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) { if (uid == 0) { return PSA_ERROR_INVALID_HANDLE; } psa_status_t status = PSA_ERROR_STORAGE_FAILURE; char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; FILE *stream = NULL; psa_its_file_header_t header; size_t n; memcpy(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH); MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0); MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0); psa_its_fill_filename(uid, filename); stream = fopen(PSA_ITS_STORAGE_TEMP, "wb"); if (stream == NULL) { goto exit; } /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ mbedtls_setbuf(stream, NULL); status = PSA_ERROR_INSUFFICIENT_STORAGE; n = fwrite(&header, 1, sizeof(header), stream); if (n != sizeof(header)) { goto exit; } if (data_length != 0) { n = fwrite(p_data, 1, data_length, stream); if (n != data_length) { goto exit; } } status = PSA_SUCCESS; exit: if (stream != NULL) { int ret = fclose(stream); if (status == PSA_SUCCESS && ret != 0) { status = PSA_ERROR_INSUFFICIENT_STORAGE; } } if (status == PSA_SUCCESS) { if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) { status = PSA_ERROR_STORAGE_FAILURE; } } /* The temporary file may still exist, but only in failure cases where * we're already reporting an error. So there's nothing we can do on * failure. If the function succeeded, and in some error cases, the * temporary file doesn't exist and so remove() is expected to fail. * Thus we just ignore the return status of remove(). */ (void) remove(PSA_ITS_STORAGE_TEMP); return status; } psa_status_t psa_its_remove(psa_storage_uid_t uid) { char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; FILE *stream; psa_its_fill_filename(uid, filename); stream = fopen(filename, "rb"); if (stream == NULL) { return PSA_ERROR_DOES_NOT_EXIST; } fclose(stream); if (remove(filename) != 0) { return PSA_ERROR_STORAGE_FAILURE; } return PSA_SUCCESS; } #endif /* MBEDTLS_PSA_ITS_FILE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_util.c000066400000000000000000000500141464416617300233200ustar00rootroot00000000000000/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" /* This is needed for MBEDTLS_ERR_XXX macros */ #include #if defined(MBEDTLS_ASN1_WRITE_C) #include #include #endif #include "psa_util_internal.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) #include #if defined(MBEDTLS_MD_LIGHT) #include #endif #if defined(MBEDTLS_LMS_C) #include #endif #if defined(MBEDTLS_SSL_TLS_C) && \ (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) #include #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) #include #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) #include #endif #if defined(MBEDTLS_PK_C) #include #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) #include #endif #include /* PSA_SUCCESS is kept at the top of each error table since * it's the most common status when everything functions properly. */ #if defined(MBEDTLS_MD_LIGHT) const mbedtls_error_pair_t psa_to_md_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_MD_BAD_INPUT_DATA }, { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_MD_ALLOC_FAILED } }; #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) const mbedtls_error_pair_t psa_to_cipher_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA }, { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_CIPHER_ALLOC_FAILED } }; #endif #if defined(MBEDTLS_LMS_C) const mbedtls_error_pair_t psa_to_lms_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_LMS_BAD_INPUT_DATA } }; #endif #if defined(MBEDTLS_SSL_TLS_C) && \ (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) const mbedtls_error_pair_t psa_to_ssl_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_INSUFFICIENT_MEMORY, MBEDTLS_ERR_SSL_ALLOC_FAILED }, { PSA_ERROR_NOT_SUPPORTED, MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE }, { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_SSL_INVALID_MAC }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_SSL_BAD_INPUT_DATA }, { PSA_ERROR_BAD_STATE, MBEDTLS_ERR_SSL_INTERNAL_ERROR }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL } }; #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) const mbedtls_error_pair_t psa_to_pk_rsa_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_RSA_BAD_INPUT_DATA }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE }, { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_RSA_RNG_FAILED }, { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_RSA_VERIFY_FAILED }, { PSA_ERROR_INVALID_PADDING, MBEDTLS_ERR_RSA_INVALID_PADDING } }; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] = { { PSA_SUCCESS, 0 }, { PSA_ERROR_NOT_PERMITTED, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_ARGUMENT, MBEDTLS_ERR_ECP_BAD_INPUT_DATA }, { PSA_ERROR_INVALID_HANDLE, MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE }, { PSA_ERROR_BUFFER_TOO_SMALL, MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL }, { PSA_ERROR_INSUFFICIENT_ENTROPY, MBEDTLS_ERR_ECP_RANDOM_FAILED }, { PSA_ERROR_INVALID_SIGNATURE, MBEDTLS_ERR_ECP_VERIFY_FAILED } }; #endif int psa_generic_status_to_mbedtls(psa_status_t status) { switch (status) { case PSA_SUCCESS: return 0; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; case PSA_ERROR_CORRUPTION_DETECTED: return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; case PSA_ERROR_COMMUNICATION_FAILURE: case PSA_ERROR_HARDWARE_FAILURE: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; case PSA_ERROR_NOT_PERMITTED: default: return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } } int psa_status_to_mbedtls(psa_status_t status, const mbedtls_error_pair_t *local_translations, size_t local_errors_num, int (*fallback_f)(psa_status_t)) { for (size_t i = 0; i < local_errors_num; i++) { if (status == local_translations[i].psa_status) { return local_translations[i].mbedtls_error; } } return fallback_f(status); } #if defined(MBEDTLS_PK_C) int psa_pk_status_to_mbedtls(psa_status_t status) { switch (status) { case PSA_ERROR_INVALID_HANDLE: return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; case PSA_ERROR_INVALID_ARGUMENT: return MBEDTLS_ERR_PK_INVALID_ALG; case PSA_ERROR_NOT_PERMITTED: return MBEDTLS_ERR_PK_TYPE_MISMATCH; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_PK_ALLOC_FAILED; case PSA_ERROR_BAD_STATE: return MBEDTLS_ERR_PK_BAD_INPUT_DATA; case PSA_ERROR_DATA_CORRUPT: case PSA_ERROR_DATA_INVALID: case PSA_ERROR_STORAGE_FAILURE: return MBEDTLS_ERR_PK_FILE_IO_ERROR; default: return psa_generic_status_to_mbedtls(status); } } #endif /* MBEDTLS_PK_C */ /****************************************************************/ /* Key management */ /****************************************************************/ #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid, size_t *bits) { switch (grpid) { #if defined(MBEDTLS_ECP_HAVE_SECP192R1) case MBEDTLS_ECP_DP_SECP192R1: *bits = 192; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP224R1) case MBEDTLS_ECP_DP_SECP224R1: *bits = 224; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP256R1) case MBEDTLS_ECP_DP_SECP256R1: *bits = 256; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) case MBEDTLS_ECP_DP_SECP384R1: *bits = 384; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP521R1) case MBEDTLS_ECP_DP_SECP521R1: *bits = 521; return PSA_ECC_FAMILY_SECP_R1; #endif #if defined(MBEDTLS_ECP_HAVE_BP256R1) case MBEDTLS_ECP_DP_BP256R1: *bits = 256; return PSA_ECC_FAMILY_BRAINPOOL_P_R1; #endif #if defined(MBEDTLS_ECP_HAVE_BP384R1) case MBEDTLS_ECP_DP_BP384R1: *bits = 384; return PSA_ECC_FAMILY_BRAINPOOL_P_R1; #endif #if defined(MBEDTLS_ECP_HAVE_BP512R1) case MBEDTLS_ECP_DP_BP512R1: *bits = 512; return PSA_ECC_FAMILY_BRAINPOOL_P_R1; #endif #if defined(MBEDTLS_ECP_HAVE_CURVE25519) case MBEDTLS_ECP_DP_CURVE25519: *bits = 255; return PSA_ECC_FAMILY_MONTGOMERY; #endif #if defined(MBEDTLS_ECP_HAVE_SECP192K1) case MBEDTLS_ECP_DP_SECP192K1: *bits = 192; return PSA_ECC_FAMILY_SECP_K1; #endif #if defined(MBEDTLS_ECP_HAVE_SECP224K1) /* secp224k1 is not and will not be supported in PSA (#3541). */ #endif #if defined(MBEDTLS_ECP_HAVE_SECP256K1) case MBEDTLS_ECP_DP_SECP256K1: *bits = 256; return PSA_ECC_FAMILY_SECP_K1; #endif #if defined(MBEDTLS_ECP_HAVE_CURVE448) case MBEDTLS_ECP_DP_CURVE448: *bits = 448; return PSA_ECC_FAMILY_MONTGOMERY; #endif default: *bits = 0; return 0; } } mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family, size_t bits) { switch (family) { case PSA_ECC_FAMILY_SECP_R1: switch (bits) { #if defined(PSA_WANT_ECC_SECP_R1_192) case 192: return MBEDTLS_ECP_DP_SECP192R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_224) case 224: return MBEDTLS_ECP_DP_SECP224R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_256) case 256: return MBEDTLS_ECP_DP_SECP256R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_384) case 384: return MBEDTLS_ECP_DP_SECP384R1; #endif #if defined(PSA_WANT_ECC_SECP_R1_521) case 521: return MBEDTLS_ECP_DP_SECP521R1; #endif } break; case PSA_ECC_FAMILY_BRAINPOOL_P_R1: switch (bits) { #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) case 256: return MBEDTLS_ECP_DP_BP256R1; #endif #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) case 384: return MBEDTLS_ECP_DP_BP384R1; #endif #if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) case 512: return MBEDTLS_ECP_DP_BP512R1; #endif } break; case PSA_ECC_FAMILY_MONTGOMERY: switch (bits) { #if defined(PSA_WANT_ECC_MONTGOMERY_255) case 255: return MBEDTLS_ECP_DP_CURVE25519; #endif #if defined(PSA_WANT_ECC_MONTGOMERY_448) case 448: return MBEDTLS_ECP_DP_CURVE448; #endif } break; case PSA_ECC_FAMILY_SECP_K1: switch (bits) { #if defined(PSA_WANT_ECC_SECP_K1_192) case 192: return MBEDTLS_ECP_DP_SECP192K1; #endif #if defined(PSA_WANT_ECC_SECP_K1_224) /* secp224k1 is not and will not be supported in PSA (#3541). */ #endif #if defined(PSA_WANT_ECC_SECP_K1_256) case 256: return MBEDTLS_ECP_DP_SECP256K1; #endif } break; } return MBEDTLS_ECP_DP_NONE; } #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ /* Wrapper function allowing the classic API to use the PSA RNG. * * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls * `psa_generate_random(...)`. The state parameter is ignored since the * PSA API doesn't support passing an explicit state. */ int mbedtls_psa_get_random(void *p_rng, unsigned char *output, size_t output_size) { /* This function takes a pointer to the RNG state because that's what * classic mbedtls functions using an RNG expect. The PSA RNG manages * its own state internally and doesn't let the caller access that state. * So we just ignore the state parameter, and in practice we'll pass * NULL. */ (void) p_rng; psa_status_t status = psa_generate_random(output, output_size); if (status == PSA_SUCCESS) { return 0; } else { return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; } } #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) /** * \brief Convert a single raw coordinate to DER ASN.1 format. The output der * buffer is filled backward (i.e. starting from its end). * * \param raw_buf Buffer containing the raw coordinate to be * converted. * \param raw_len Length of raw_buf in bytes. This must be > 0. * \param der_buf_start Pointer to the beginning of the buffer which * will be filled with the DER converted data. * \param der_buf_end End of the buffer used to store the DER output. * * \return On success, the amount of data (in bytes) written to * the DER buffer. * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der * buffer is too small to contain all the converted data. * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw * coordinate is null (i.e. all zeros). * * \warning Raw and der buffer must not be overlapping. */ static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len, unsigned char *der_buf_start, unsigned char *der_buf_end) { unsigned char *p = der_buf_end; int len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* ASN.1 DER encoding requires minimal length, so skip leading 0s. * Provided input MPIs should not be 0, but as a failsafe measure, still * detect that and return error in case. */ while (*raw_buf == 0x00) { ++raw_buf; --raw_len; if (raw_len == 0) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } } len = (int) raw_len; /* Copy the raw coordinate to the end of der_buf. */ if ((p - der_buf_start) < len) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } p -= len; memcpy(p, raw_buf, len); /* If MSb is 1, ASN.1 requires that we prepend a 0. */ if (*p & 0x80) { if ((p - der_buf_start) < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } --p; *p = 0x00; ++len; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER)); return len; } int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len, unsigned char *der, size_t der_size, size_t *der_len) { unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; const size_t coordinate_len = PSA_BITS_TO_BYTES(bits); size_t len = 0; unsigned char *p = der + der_size; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (raw_len != (2 * coordinate_len)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } /* Since raw and der buffers might overlap, dump r and s before starting * the conversion. */ memcpy(r, raw, coordinate_len); memcpy(s, raw + coordinate_len, coordinate_len); /* der buffer will initially be written starting from its end so we pick s * first and then r. */ ret = convert_raw_to_der_single_int(s, coordinate_len, der, p); if (ret < 0) { return ret; } p -= ret; len += ret; ret = convert_raw_to_der_single_int(r, coordinate_len, der, p); if (ret < 0) { return ret; } p -= ret; len += ret; /* Add ASN.1 header (len + tag). */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* memmove the content of der buffer to its beginnig. */ memmove(der, p, len); *der_len = len; return 0; } /** * \brief Convert a single integer from ASN.1 DER format to raw. * * \param der Buffer containing the DER integer value to be * converted. * \param der_len Length of the der buffer in bytes. * \param raw Output buffer that will be filled with the * converted data. This should be at least * coordinate_size bytes and it must be zeroed before * calling this function. * \param coordinate_size Size (in bytes) of a single coordinate in raw * format. * * \return On success, the amount of DER data parsed from the * provided der buffer. * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag * is missing in the der buffer. * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer * is null (i.e. all zeros) or if the output raw buffer * is too small to contain the converted raw value. * * \warning Der and raw buffers must not be overlapping. */ static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len, unsigned char *raw, size_t coordinate_size) { unsigned char *p = der; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t unpadded_len, padding_len = 0; /* Get the length of ASN.1 element (i.e. the integer we need to parse). */ ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len, MBEDTLS_ASN1_INTEGER); if (ret != 0) { return ret; } /* It's invalid to have: * - unpadded_len == 0. * - MSb set without a leading 0x00 (leading 0x00 is checked below). */ if (((unpadded_len == 0) || (*p & 0x80) != 0)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } /* Skip possible leading zero */ if (*p == 0x00) { p++; unpadded_len--; /* It is not allowed to have more than 1 leading zero. * Ignore the case in which unpadded_len = 0 because that's a 0 encoded * in ASN.1 format (i.e. 020100). */ if ((unpadded_len > 0) && (*p == 0x00)) { return MBEDTLS_ERR_ASN1_INVALID_DATA; } } if (unpadded_len > coordinate_size) { /* Parsed number is longer than the maximum expected value. */ return MBEDTLS_ERR_ASN1_INVALID_DATA; } padding_len = coordinate_size - unpadded_len; /* raw buffer was already zeroed by the calling function so zero-padding * operation is skipped here. */ memcpy(raw + padding_len, p, unpadded_len); p += unpadded_len; return (int) (p - der); } int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len, unsigned char *raw, size_t raw_size, size_t *raw_len) { unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; unsigned char *p = (unsigned char *) der; size_t data_len; size_t coordinate_size = PSA_BITS_TO_BYTES(bits); int ret; /* The output raw buffer should be at least twice the size of a raw * coordinate in order to store r and s. */ if (raw_size < coordinate_size * 2) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } /* Check that the provided input DER buffer has the right header. */ ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return ret; } memset(raw_tmp, 0, 2 * coordinate_size); /* Extract r */ ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size); if (ret < 0) { return ret; } p += ret; data_len -= ret; /* Extract s */ ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size, coordinate_size); if (ret < 0) { return ret; } p += ret; data_len -= ret; /* Check that we consumed all the input der data. */ if ((size_t) (p - der) != der_len) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } memcpy(raw, raw_tmp, 2 * coordinate_size); *raw_len = 2 * coordinate_size; return 0; } #endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/psa_util_internal.h000066400000000000000000000070571464416617300252320ustar00rootroot00000000000000/** * \file psa_util_internal.h * * \brief Internal utility functions for use of PSA Crypto. */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_PSA_UTIL_INTERNAL_H #define MBEDTLS_PSA_UTIL_INTERNAL_H /* Include the public header so that users only need one include. */ #include "mbedtls/psa_util.h" #include "psa/crypto.h" #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) /************************************************************************* * FFDH ************************************************************************/ #define MBEDTLS_PSA_MAX_FFDH_PUBKEY_LENGTH \ PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) /************************************************************************* * ECC ************************************************************************/ #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \ PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) #define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \ PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) /************************************************************************* * Error translation ************************************************************************/ typedef struct { /* Error codes used by PSA crypto are in -255..-128, fitting in 16 bits. */ int16_t psa_status; /* Error codes used by Mbed TLS are in one of the ranges * -127..-1 (low-level) or -32767..-4096 (high-level with a low-level * code optionally added), fitting in 16 bits. */ int16_t mbedtls_error; } mbedtls_error_pair_t; #if defined(MBEDTLS_MD_LIGHT) extern const mbedtls_error_pair_t psa_to_md_errors[4]; #endif #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA) extern const mbedtls_error_pair_t psa_to_cipher_errors[4]; #endif #if defined(MBEDTLS_LMS_C) extern const mbedtls_error_pair_t psa_to_lms_errors[3]; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) extern const mbedtls_error_pair_t psa_to_ssl_errors[7]; #endif #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8]; #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7]; #endif /* Generic fallback function for error translation, * when the received state was not module-specific. */ int psa_generic_status_to_mbedtls(psa_status_t status); /* This function iterates over provided local error translations, * and if no match was found - calls the fallback error translation function. */ int psa_status_to_mbedtls(psa_status_t status, const mbedtls_error_pair_t *local_translations, size_t local_errors_num, int (*fallback_f)(psa_status_t)); /* The second out of three-stage error handling functions of the pk module, * acts as a fallback after RSA / ECDSA error translation, and if no match * is found, it itself calls psa_generic_status_to_mbedtls. */ int psa_pk_status_to_mbedtls(psa_status_t status); /* Utility macro to shorten the defines of error translator in modules. */ #define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f) \ psa_status_to_mbedtls(status, error_list, \ sizeof(error_list)/sizeof(error_list[0]), \ fallback_f) #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ripemd160.c000066400000000000000000000375311464416617300232200ustar00rootroot00000000000000/* * RIPE MD-160 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The RIPEMD-160 algorithm was designed by RIPE in 1996 * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 */ #include "common.h" #if defined(MBEDTLS_RIPEMD160_C) #include "mbedtls/ripemd160.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_RIPEMD160_ALT) void mbedtls_ripemd160_init(mbedtls_ripemd160_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ripemd160_context)); } void mbedtls_ripemd160_free(mbedtls_ripemd160_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ripemd160_context)); } void mbedtls_ripemd160_clone(mbedtls_ripemd160_context *dst, const mbedtls_ripemd160_context *src) { *dst = *src; } /* * RIPEMD-160 context setup */ int mbedtls_ripemd160_starts(mbedtls_ripemd160_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; return 0; } #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) /* * Process one block */ int mbedtls_internal_ripemd160_process(mbedtls_ripemd160_context *ctx, const unsigned char data[64]) { struct { uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; } local; local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0); local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4); local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8); local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12); local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16); local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20); local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24); local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28); local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32); local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36); local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40); local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44); local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48); local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52); local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56); local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60); local.A = local.Ap = ctx->state[0]; local.B = local.Bp = ctx->state[1]; local.C = local.Cp = ctx->state[2]; local.D = local.Dp = ctx->state[3]; local.E = local.Ep = ctx->state[4]; #define F1(x, y, z) ((x) ^ (y) ^ (z)) #define F2(x, y, z) (((x) & (y)) | (~(x) & (z))) #define F3(x, y, z) (((x) | ~(y)) ^ (z)) #define F4(x, y, z) (((x) & (z)) | ((y) & ~(z))) #define F5(x, y, z) ((x) ^ ((y) | ~(z))) #define S(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define P(a, b, c, d, e, r, s, f, k) \ do \ { \ (a) += f((b), (c), (d)) + local.X[r] + (k); \ (a) = S((a), (s)) + (e); \ (c) = S((c), 10); \ } while (0) #define P2(a, b, c, d, e, r, s, rp, sp) \ do \ { \ P((a), (b), (c), (d), (e), (r), (s), F, K); \ P(a ## p, b ## p, c ## p, d ## p, e ## p, \ (rp), (sp), Fp, Kp); \ } while (0) #define F F1 #define K 0x00000000 #define Fp F5 #define Kp 0x50A28BE6 P2(local.A, local.B, local.C, local.D, local.E, 0, 11, 5, 8); P2(local.E, local.A, local.B, local.C, local.D, 1, 14, 14, 9); P2(local.D, local.E, local.A, local.B, local.C, 2, 15, 7, 9); P2(local.C, local.D, local.E, local.A, local.B, 3, 12, 0, 11); P2(local.B, local.C, local.D, local.E, local.A, 4, 5, 9, 13); P2(local.A, local.B, local.C, local.D, local.E, 5, 8, 2, 15); P2(local.E, local.A, local.B, local.C, local.D, 6, 7, 11, 15); P2(local.D, local.E, local.A, local.B, local.C, 7, 9, 4, 5); P2(local.C, local.D, local.E, local.A, local.B, 8, 11, 13, 7); P2(local.B, local.C, local.D, local.E, local.A, 9, 13, 6, 7); P2(local.A, local.B, local.C, local.D, local.E, 10, 14, 15, 8); P2(local.E, local.A, local.B, local.C, local.D, 11, 15, 8, 11); P2(local.D, local.E, local.A, local.B, local.C, 12, 6, 1, 14); P2(local.C, local.D, local.E, local.A, local.B, 13, 7, 10, 14); P2(local.B, local.C, local.D, local.E, local.A, 14, 9, 3, 12); P2(local.A, local.B, local.C, local.D, local.E, 15, 8, 12, 6); #undef F #undef K #undef Fp #undef Kp #define F F2 #define K 0x5A827999 #define Fp F4 #define Kp 0x5C4DD124 P2(local.E, local.A, local.B, local.C, local.D, 7, 7, 6, 9); P2(local.D, local.E, local.A, local.B, local.C, 4, 6, 11, 13); P2(local.C, local.D, local.E, local.A, local.B, 13, 8, 3, 15); P2(local.B, local.C, local.D, local.E, local.A, 1, 13, 7, 7); P2(local.A, local.B, local.C, local.D, local.E, 10, 11, 0, 12); P2(local.E, local.A, local.B, local.C, local.D, 6, 9, 13, 8); P2(local.D, local.E, local.A, local.B, local.C, 15, 7, 5, 9); P2(local.C, local.D, local.E, local.A, local.B, 3, 15, 10, 11); P2(local.B, local.C, local.D, local.E, local.A, 12, 7, 14, 7); P2(local.A, local.B, local.C, local.D, local.E, 0, 12, 15, 7); P2(local.E, local.A, local.B, local.C, local.D, 9, 15, 8, 12); P2(local.D, local.E, local.A, local.B, local.C, 5, 9, 12, 7); P2(local.C, local.D, local.E, local.A, local.B, 2, 11, 4, 6); P2(local.B, local.C, local.D, local.E, local.A, 14, 7, 9, 15); P2(local.A, local.B, local.C, local.D, local.E, 11, 13, 1, 13); P2(local.E, local.A, local.B, local.C, local.D, 8, 12, 2, 11); #undef F #undef K #undef Fp #undef Kp #define F F3 #define K 0x6ED9EBA1 #define Fp F3 #define Kp 0x6D703EF3 P2(local.D, local.E, local.A, local.B, local.C, 3, 11, 15, 9); P2(local.C, local.D, local.E, local.A, local.B, 10, 13, 5, 7); P2(local.B, local.C, local.D, local.E, local.A, 14, 6, 1, 15); P2(local.A, local.B, local.C, local.D, local.E, 4, 7, 3, 11); P2(local.E, local.A, local.B, local.C, local.D, 9, 14, 7, 8); P2(local.D, local.E, local.A, local.B, local.C, 15, 9, 14, 6); P2(local.C, local.D, local.E, local.A, local.B, 8, 13, 6, 6); P2(local.B, local.C, local.D, local.E, local.A, 1, 15, 9, 14); P2(local.A, local.B, local.C, local.D, local.E, 2, 14, 11, 12); P2(local.E, local.A, local.B, local.C, local.D, 7, 8, 8, 13); P2(local.D, local.E, local.A, local.B, local.C, 0, 13, 12, 5); P2(local.C, local.D, local.E, local.A, local.B, 6, 6, 2, 14); P2(local.B, local.C, local.D, local.E, local.A, 13, 5, 10, 13); P2(local.A, local.B, local.C, local.D, local.E, 11, 12, 0, 13); P2(local.E, local.A, local.B, local.C, local.D, 5, 7, 4, 7); P2(local.D, local.E, local.A, local.B, local.C, 12, 5, 13, 5); #undef F #undef K #undef Fp #undef Kp #define F F4 #define K 0x8F1BBCDC #define Fp F2 #define Kp 0x7A6D76E9 P2(local.C, local.D, local.E, local.A, local.B, 1, 11, 8, 15); P2(local.B, local.C, local.D, local.E, local.A, 9, 12, 6, 5); P2(local.A, local.B, local.C, local.D, local.E, 11, 14, 4, 8); P2(local.E, local.A, local.B, local.C, local.D, 10, 15, 1, 11); P2(local.D, local.E, local.A, local.B, local.C, 0, 14, 3, 14); P2(local.C, local.D, local.E, local.A, local.B, 8, 15, 11, 14); P2(local.B, local.C, local.D, local.E, local.A, 12, 9, 15, 6); P2(local.A, local.B, local.C, local.D, local.E, 4, 8, 0, 14); P2(local.E, local.A, local.B, local.C, local.D, 13, 9, 5, 6); P2(local.D, local.E, local.A, local.B, local.C, 3, 14, 12, 9); P2(local.C, local.D, local.E, local.A, local.B, 7, 5, 2, 12); P2(local.B, local.C, local.D, local.E, local.A, 15, 6, 13, 9); P2(local.A, local.B, local.C, local.D, local.E, 14, 8, 9, 12); P2(local.E, local.A, local.B, local.C, local.D, 5, 6, 7, 5); P2(local.D, local.E, local.A, local.B, local.C, 6, 5, 10, 15); P2(local.C, local.D, local.E, local.A, local.B, 2, 12, 14, 8); #undef F #undef K #undef Fp #undef Kp #define F F5 #define K 0xA953FD4E #define Fp F1 #define Kp 0x00000000 P2(local.B, local.C, local.D, local.E, local.A, 4, 9, 12, 8); P2(local.A, local.B, local.C, local.D, local.E, 0, 15, 15, 5); P2(local.E, local.A, local.B, local.C, local.D, 5, 5, 10, 12); P2(local.D, local.E, local.A, local.B, local.C, 9, 11, 4, 9); P2(local.C, local.D, local.E, local.A, local.B, 7, 6, 1, 12); P2(local.B, local.C, local.D, local.E, local.A, 12, 8, 5, 5); P2(local.A, local.B, local.C, local.D, local.E, 2, 13, 8, 14); P2(local.E, local.A, local.B, local.C, local.D, 10, 12, 7, 6); P2(local.D, local.E, local.A, local.B, local.C, 14, 5, 6, 8); P2(local.C, local.D, local.E, local.A, local.B, 1, 12, 2, 13); P2(local.B, local.C, local.D, local.E, local.A, 3, 13, 13, 6); P2(local.A, local.B, local.C, local.D, local.E, 8, 14, 14, 5); P2(local.E, local.A, local.B, local.C, local.D, 11, 11, 0, 15); P2(local.D, local.E, local.A, local.B, local.C, 6, 8, 3, 13); P2(local.C, local.D, local.E, local.A, local.B, 15, 5, 9, 11); P2(local.B, local.C, local.D, local.E, local.A, 13, 6, 11, 11); #undef F #undef K #undef Fp #undef Kp local.C = ctx->state[1] + local.C + local.Dp; ctx->state[1] = ctx->state[2] + local.D + local.Ep; ctx->state[2] = ctx->state[3] + local.E + local.Ap; ctx->state[3] = ctx->state[4] + local.A + local.Bp; ctx->state[4] = ctx->state[0] + local.B + local.Cp; ctx->state[0] = local.C; /* Zeroise variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ /* * RIPEMD-160 process buffer */ int mbedtls_ripemd160_update(mbedtls_ripemd160_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_ripemd160_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= 64) { if ((ret = mbedtls_internal_ripemd160_process(ctx, input)) != 0) { return ret; } input += 64; ilen -= 64; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } static const unsigned char ripemd160_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * RIPEMD-160 final digest */ int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_LE(low, msglen, 0); MBEDTLS_PUT_UINT32_LE(high, msglen, 4); last = ctx->total[0] & 0x3F; padn = (last < 56) ? (56 - last) : (120 - last); ret = mbedtls_ripemd160_update(ctx, ripemd160_padding, padn); if (ret != 0) { goto exit; } ret = mbedtls_ripemd160_update(ctx, msglen, 8); if (ret != 0) { goto exit; } MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_LE(ctx->state[4], output, 16); ret = 0; exit: mbedtls_ripemd160_free(ctx); return ret; } #endif /* ! MBEDTLS_RIPEMD160_ALT */ /* * output = RIPEMD-160( input buffer ) */ int mbedtls_ripemd160(const unsigned char *input, size_t ilen, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ripemd160_context ctx; mbedtls_ripemd160_init(&ctx); if ((ret = mbedtls_ripemd160_starts(&ctx)) != 0) { goto exit; } if ((ret = mbedtls_ripemd160_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_ripemd160_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_ripemd160_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * Test vectors from the RIPEMD-160 paper and * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC */ #define TESTS 8 static const unsigned char ripemd160_test_str[TESTS][81] = { { "" }, { "a" }, { "abc" }, { "message digest" }, { "abcdefghijklmnopqrstuvwxyz" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }, }; static const size_t ripemd160_test_strlen[TESTS] = { 0, 1, 3, 14, 26, 56, 62, 80 }; static const unsigned char ripemd160_test_md[TESTS][20] = { { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, }; /* * Checkup routine */ int mbedtls_ripemd160_self_test(int verbose) { int i, ret = 0; unsigned char output[20]; memset(output, 0, sizeof(output)); for (i = 0; i < TESTS; i++) { if (verbose != 0) { mbedtls_printf(" RIPEMD-160 test #%d: ", i + 1); } ret = mbedtls_ripemd160(ripemd160_test_str[i], ripemd160_test_strlen[i], output); if (ret != 0) { goto fail; } if (memcmp(output, ripemd160_test_md[i], 20) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } return 0; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_RIPEMD160_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/rsa.c000066400000000000000000002704761464416617300223050ustar00rootroot00000000000000/* * The RSA public-key cryptosystem * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The following sources were referenced in the design of this implementation * of the RSA algorithm: * * [1] A method for obtaining digital signatures and public-key cryptosystems * R Rivest, A Shamir, and L Adleman * http://people.csail.mit.edu/rivest/pubs.html#RSA78 * * [2] Handbook of Applied Cryptography - 1997, Chapter 8 * Menezes, van Oorschot and Vanstone * * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and * Stefan Mangard * https://arxiv.org/abs/1702.08719v2 * */ #include "common.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "bignum_core.h" #include "rsa_alt_helpers.h" #include "rsa_internal.h" #include "mbedtls/oid.h" #include "mbedtls/asn1write.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include "md_psa.h" #include #if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #include "mbedtls/platform.h" #include /* * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. * * The value zero is: * - never a valid value for an RSA parameter * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). * * Since values can't be omitted in PKCS#1, passing a zero value to * rsa_complete() would be incorrect, so reject zero values early. */ static int asn1_get_nonzero_mpi(unsigned char **p, const unsigned char *end, mbedtls_mpi *X) { int ret; ret = mbedtls_asn1_get_mpi(p, end, X); if (ret != 0) { return ret; } if (mbedtls_mpi_cmp_int(X, 0) == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return 0; } int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen) { int ret, version; size_t len; unsigned char *p, *end; mbedtls_mpi T; mbedtls_mpi_init(&T); p = (unsigned char *) key; end = p + keylen; /* * This function parses the RSAPrivateKey (PKCS#1) * * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER, -- (inverse of q) mod p * otherPrimeInfos OtherPrimeInfos OPTIONAL * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if (end != p + len) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { return ret; } if (version != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Import N */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, NULL, NULL)) != 0) { goto cleanup; } /* Import E */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, NULL, &T)) != 0) { goto cleanup; } /* Import D */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, &T, NULL)) != 0) { goto cleanup; } /* Import P */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, NULL, NULL)) != 0) { goto cleanup; } /* Import Q */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, NULL, NULL)) != 0) { goto cleanup; } #if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) /* * The RSA CRT parameters DP, DQ and QP are nominally redundant, in * that they can be easily recomputed from D, P and Q. However by * parsing them from the PKCS1 structure it is possible to avoid * recalculating them which both reduces the overhead of loading * RSA private keys into memory and also avoids side channels which * can arise when computing those values, since all of D, P, and Q * are secret. See https://eprint.iacr.org/2020/055 for a * description of one such attack. */ /* Import DP */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { goto cleanup; } /* Import DQ */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { goto cleanup; } /* Import QP */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { goto cleanup; } #else /* Verify existence of the CRT params */ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { goto cleanup; } #endif /* rsa_complete() doesn't complete anything with the default * implementation but is still called: * - for the benefit of alternative implementation that may want to * pre-compute stuff beyond what's provided (eg Montgomery factors) * - as is also sanity-checks the key * * Furthermore, we also check the public part for consistency with * mbedtls_pk_parse_pubkey(), as it includes size minima for example. */ if ((ret = mbedtls_rsa_complete(rsa)) != 0 || (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { goto cleanup; } if (p != end) { ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } cleanup: mbedtls_mpi_free(&T); if (ret != 0) { mbedtls_rsa_free(rsa); } return ret; } int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen) { unsigned char *p = (unsigned char *) key; unsigned char *end = (unsigned char *) (key + keylen); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return ret; } if (end != p + len) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Import N */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { return ret; } if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0, NULL, 0, NULL, 0)) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } p += len; /* Import E */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { return ret; } if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, NULL, 0, p, len)) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } p += len; if (mbedtls_rsa_complete(rsa) != 0 || mbedtls_rsa_check_pubkey(rsa) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (p != end) { return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p) { size_t len = 0; int ret; mbedtls_mpi T; /* Temporary holding the exported parameters */ /* * Export the parameters one after another to avoid simultaneous copies. */ mbedtls_mpi_init(&T); /* Export QP */ if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export DQ */ if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export DP */ if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export Q */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export P */ if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export D */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export E */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export N */ if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; end_of_export: mbedtls_mpi_free(&T); if (ret < 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } /* * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; mbedtls_mpi T; mbedtls_mpi_init(&T); /* Export E */ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; /* Export N */ if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { goto end_of_export; } len += ret; end_of_export: mbedtls_mpi_free(&T); if (ret < 0) { return ret; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) /** This function performs the unpadding part of a PKCS#1 v1.5 decryption * operation (EME-PKCS1-v1_5 decoding). * * \note The return value from this function is a sensitive value * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING * is often a situation that an attacker can provoke and leaking which * one is the result is precisely the information the attacker wants. * * \param input The input buffer which is the payload inside PKCS#1v1.5 * encryption padding, called the "encoded message EM" * by the terminology. * \param ilen The length of the payload in the \p input buffer. * \param output The buffer for the payload, called "message M" by the * PKCS#1 terminology. This must be a writable buffer of * length \p output_max_len bytes. * \param olen The address at which to store the length of * the payload. This must not be \c NULL. * \param output_max_len The length in bytes of the output buffer \p output. * * \return \c 0 on success. * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE * The output buffer is too small for the unpadded payload. * \return #MBEDTLS_ERR_RSA_INVALID_PADDING * The input doesn't contain properly formatted padding. */ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, size_t ilen, unsigned char *output, size_t output_max_len, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, plaintext_max_size; /* The following variables take sensitive values: their value must * not leak into the observable behavior of the function other than * the designated outputs (output, olen, return value). Otherwise * this would open the execution of the function to * side-channel-based variants of the Bleichenbacher padding oracle * attack. Potential side channels include overall timing, memory * access patterns (especially visible to an adversary who has access * to a shared memory cache), and branches (especially visible to * an adversary who has access to a shared code cache or to a shared * branch predictor). */ size_t pad_count = 0; mbedtls_ct_condition_t bad; mbedtls_ct_condition_t pad_done; size_t plaintext_size = 0; mbedtls_ct_condition_t output_too_large; plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11 : output_max_len; /* Check and get padding length in constant time and constant * memory trace. The first byte must be 0. */ bad = mbedtls_ct_bool(input[0]); /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 * where PS must be at least 8 nonzero bytes. */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(input[1], MBEDTLS_RSA_CRYPT)); /* Read the whole buffer. Set pad_done to nonzero if we find * the 0x00 byte and remember the padding length in pad_count. */ pad_done = MBEDTLS_CT_FALSE; for (i = 2; i < ilen; i++) { mbedtls_ct_condition_t found = mbedtls_ct_uint_eq(input[i], 0); pad_done = mbedtls_ct_bool_or(pad_done, found); pad_count += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); } /* If pad_done is still zero, there's no data, only unfinished padding. */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_not(pad_done)); /* There must be at least 8 bytes of padding. */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_gt(8, pad_count)); /* If the padding is valid, set plaintext_size to the number of * remaining bytes after stripping the padding. If the padding * is invalid, avoid leaking this fact through the size of the * output: use the maximum message size that fits in the output * buffer. Do it without branches to avoid leaking the padding * validity through timing. RSA keys are small enough that all the * size_t values involved fit in unsigned int. */ plaintext_size = mbedtls_ct_uint_if( bad, (unsigned) plaintext_max_size, (unsigned) (ilen - pad_count - 3)); /* Set output_too_large to 0 if the plaintext fits in the output * buffer and to 1 otherwise. */ output_too_large = mbedtls_ct_uint_gt(plaintext_size, plaintext_max_size); /* Set ret without branches to avoid timing attacks. Return: * - INVALID_PADDING if the padding is bad (bad != 0). * - OUTPUT_TOO_LARGE if the padding is good but the decrypted * plaintext does not fit in the output buffer. * - 0 if the padding is correct. */ ret = mbedtls_ct_error_if( bad, MBEDTLS_ERR_RSA_INVALID_PADDING, mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ); /* If the padding is bad or the plaintext is too large, zero the * data that we're about to copy to the output buffer. * We need to copy the same amount of data * from the same buffer whether the padding is good or not to * avoid leaking the padding validity through overall timing or * through memory or cache access patterns. */ mbedtls_ct_zeroize_if(mbedtls_ct_bool_or(bad, output_too_large), input + 11, ilen - 11); /* If the plaintext is too large, truncate it to the buffer size. * Copy anyway to avoid revealing the length through timing, because * revealing the length is as bad as revealing the padding validity * for a Bleichenbacher attack. */ plaintext_size = mbedtls_ct_uint_if(output_too_large, (unsigned) plaintext_max_size, (unsigned) plaintext_size); /* Move the plaintext to the leftmost position where it can start in * the working buffer, i.e. make it start plaintext_max_size from * the end of the buffer. Do this with a memory access trace that * does not depend on the plaintext size. After this move, the * starting location of the plaintext is no longer sensitive * information. */ mbedtls_ct_memmove_left(input + ilen - plaintext_max_size, plaintext_max_size, plaintext_max_size - plaintext_size); /* Finally copy the decrypted plaintext plus trailing zeros into the output * buffer. If output_max_len is 0, then output may be an invalid pointer * and the result of memcpy() would be undefined; prevent undefined * behavior making sure to depend only on output_max_len (the size of the * user-provided output buffer), which is independent from plaintext * length, validity of padding, success of the decryption, and other * secrets. */ if (output_max_len != 0) { memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size); } /* Report the amount of data we copied to the output buffer. In case * of errors (bad padding or output too large), the value of *olen * when this function returns is not specified. Making it equivalent * to the good case limits the risks of leaking the padding validity. */ *olen = plaintext_size; return ret; } #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ #if !defined(MBEDTLS_RSA_ALT) int mbedtls_rsa_import(mbedtls_rsa_context *ctx, const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((N != NULL && (ret = mbedtls_mpi_copy(&ctx->N, N)) != 0) || (P != NULL && (ret = mbedtls_mpi_copy(&ctx->P, P)) != 0) || (Q != NULL && (ret = mbedtls_mpi_copy(&ctx->Q, Q)) != 0) || (D != NULL && (ret = mbedtls_mpi_copy(&ctx->D, D)) != 0) || (E != NULL && (ret = mbedtls_mpi_copy(&ctx->E, E)) != 0)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } if (N != NULL) { ctx->len = mbedtls_mpi_size(&ctx->N); } return 0; } int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx, unsigned char const *N, size_t N_len, unsigned char const *P, size_t P_len, unsigned char const *Q, size_t Q_len, unsigned char const *D, size_t D_len, unsigned char const *E, size_t E_len) { int ret = 0; if (N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->N, N, N_len)); ctx->len = mbedtls_mpi_size(&ctx->N); } if (P != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->P, P, P_len)); } if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->Q, Q, Q_len)); } if (D != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->D, D, D_len)); } if (E != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->E, E, E_len)); } cleanup: if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } return 0; } /* * Checks whether the context fields are set in such a way * that the RSA primitives will be able to execute without error. * It does *not* make guarantees for consistency of the parameters. */ static int rsa_check_context(mbedtls_rsa_context const *ctx, int is_priv, int blinding_needed) { #if !defined(MBEDTLS_RSA_NO_CRT) /* blinding_needed is only used for NO_CRT to decide whether * P,Q need to be present or not. */ ((void) blinding_needed); #endif if (ctx->len != mbedtls_mpi_size(&ctx->N) || ctx->len > MBEDTLS_MPI_MAX_SIZE) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * 1. Modular exponentiation needs positive, odd moduli. */ /* Modular exponentiation wrt. N is always used for * RSA public key operations. */ if (mbedtls_mpi_cmp_int(&ctx->N, 0) <= 0 || mbedtls_mpi_get_bit(&ctx->N, 0) == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if !defined(MBEDTLS_RSA_NO_CRT) /* Modular exponentiation for P and Q is only * used for private key operations and if CRT * is used. */ if (is_priv && (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 || mbedtls_mpi_get_bit(&ctx->P, 0) == 0 || mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0 || mbedtls_mpi_get_bit(&ctx->Q, 0) == 0)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif /* !MBEDTLS_RSA_NO_CRT */ /* * 2. Exponents must be positive */ /* Always need E for public key operations */ if (mbedtls_mpi_cmp_int(&ctx->E, 0) <= 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if defined(MBEDTLS_RSA_NO_CRT) /* For private key operations, use D or DP & DQ * as (unblinded) exponents. */ if (is_priv && mbedtls_mpi_cmp_int(&ctx->D, 0) <= 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #else if (is_priv && (mbedtls_mpi_cmp_int(&ctx->DP, 0) <= 0 || mbedtls_mpi_cmp_int(&ctx->DQ, 0) <= 0)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif /* MBEDTLS_RSA_NO_CRT */ /* Blinding shouldn't make exponents negative either, * so check that P, Q >= 1 if that hasn't yet been * done as part of 1. */ #if defined(MBEDTLS_RSA_NO_CRT) if (is_priv && blinding_needed && (mbedtls_mpi_cmp_int(&ctx->P, 0) <= 0 || mbedtls_mpi_cmp_int(&ctx->Q, 0) <= 0)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif /* It wouldn't lead to an error if it wasn't satisfied, * but check for QP >= 1 nonetheless. */ #if !defined(MBEDTLS_RSA_NO_CRT) if (is_priv && mbedtls_mpi_cmp_int(&ctx->QP, 0) <= 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #endif return 0; } int mbedtls_rsa_complete(mbedtls_rsa_context *ctx) { int ret = 0; int have_N, have_P, have_Q, have_D, have_E; #if !defined(MBEDTLS_RSA_NO_CRT) int have_DP, have_DQ, have_QP; #endif int n_missing, pq_missing, d_missing, is_pub, is_priv; have_N = (mbedtls_mpi_cmp_int(&ctx->N, 0) != 0); have_P = (mbedtls_mpi_cmp_int(&ctx->P, 0) != 0); have_Q = (mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0); have_D = (mbedtls_mpi_cmp_int(&ctx->D, 0) != 0); have_E = (mbedtls_mpi_cmp_int(&ctx->E, 0) != 0); #if !defined(MBEDTLS_RSA_NO_CRT) have_DP = (mbedtls_mpi_cmp_int(&ctx->DP, 0) != 0); have_DQ = (mbedtls_mpi_cmp_int(&ctx->DQ, 0) != 0); have_QP = (mbedtls_mpi_cmp_int(&ctx->QP, 0) != 0); #endif /* * Check whether provided parameters are enough * to deduce all others. The following incomplete * parameter sets for private keys are supported: * * (1) P, Q missing. * (2) D and potentially N missing. * */ n_missing = have_P && have_Q && have_D && have_E; pq_missing = have_N && !have_P && !have_Q && have_D && have_E; d_missing = have_P && have_Q && !have_D && have_E; is_pub = have_N && !have_P && !have_Q && !have_D && have_E; /* These three alternatives are mutually exclusive */ is_priv = n_missing || pq_missing || d_missing; if (!is_priv && !is_pub) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Step 1: Deduce N if P, Q are provided. */ if (!have_N && have_P && have_Q) { if ((ret = mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } ctx->len = mbedtls_mpi_size(&ctx->N); } /* * Step 2: Deduce and verify all remaining core parameters. */ if (pq_missing) { ret = mbedtls_rsa_deduce_primes(&ctx->N, &ctx->E, &ctx->D, &ctx->P, &ctx->Q); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } } else if (d_missing) { if ((ret = mbedtls_rsa_deduce_private_exponent(&ctx->P, &ctx->Q, &ctx->E, &ctx->D)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } } /* * Step 3: Deduce all additional parameters specific * to our current RSA implementation. */ #if !defined(MBEDTLS_RSA_NO_CRT) if (is_priv && !(have_DP && have_DQ && have_QP)) { ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } } #endif /* MBEDTLS_RSA_NO_CRT */ /* * Step 3: Basic sanity checks */ return rsa_check_context(ctx, is_priv, 1); } int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx, unsigned char *N, size_t N_len, unsigned char *P, size_t P_len, unsigned char *Q, size_t Q_len, unsigned char *D, size_t D_len, unsigned char *E, size_t E_len) { int ret = 0; int is_priv; /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->E, 0) != 0; if (!is_priv) { /* If we're trying to export private parameters for a public key, * something must be wrong. */ if (P != NULL || Q != NULL || D != NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } if (N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->N, N, N_len)); } if (P != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->P, P, P_len)); } if (Q != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->Q, Q, Q_len)); } if (D != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->D, D, D_len)); } if (E != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->E, E, E_len)); } cleanup: return ret; } int mbedtls_rsa_export(const mbedtls_rsa_context *ctx, mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, mbedtls_mpi *D, mbedtls_mpi *E) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->E, 0) != 0; if (!is_priv) { /* If we're trying to export private parameters for a public key, * something must be wrong. */ if (P != NULL || Q != NULL || D != NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } /* Export all requested core parameters. */ if ((N != NULL && (ret = mbedtls_mpi_copy(N, &ctx->N)) != 0) || (P != NULL && (ret = mbedtls_mpi_copy(P, &ctx->P)) != 0) || (Q != NULL && (ret = mbedtls_mpi_copy(Q, &ctx->Q)) != 0) || (D != NULL && (ret = mbedtls_mpi_copy(D, &ctx->D)) != 0) || (E != NULL && (ret = mbedtls_mpi_copy(E, &ctx->E)) != 0)) { return ret; } return 0; } /* * Export CRT parameters * This must also be implemented if CRT is not used, for being able to * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt * can be used in this case. */ int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int is_priv; /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int(&ctx->N, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->P, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->Q, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->D, 0) != 0 && mbedtls_mpi_cmp_int(&ctx->E, 0) != 0; if (!is_priv) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if !defined(MBEDTLS_RSA_NO_CRT) /* Export all requested blinding parameters. */ if ((DP != NULL && (ret = mbedtls_mpi_copy(DP, &ctx->DP)) != 0) || (DQ != NULL && (ret = mbedtls_mpi_copy(DQ, &ctx->DQ)) != 0) || (QP != NULL && (ret = mbedtls_mpi_copy(QP, &ctx->QP)) != 0)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } #else if ((ret = mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D, DP, DQ, QP)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret); } #endif return 0; } /* * Initialize an RSA context */ void mbedtls_rsa_init(mbedtls_rsa_context *ctx) { memset(ctx, 0, sizeof(mbedtls_rsa_context)); ctx->padding = MBEDTLS_RSA_PKCS_V15; ctx->hash_id = MBEDTLS_MD_NONE; #if defined(MBEDTLS_THREADING_C) /* Set ctx->ver to nonzero to indicate that the mutex has been * initialized and will need to be freed. */ ctx->ver = 1; mbedtls_mutex_init(&ctx->mutex); #endif } /* * Set padding for an existing RSA context */ int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding, mbedtls_md_type_t hash_id) { switch (padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: break; #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: break; #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } #if defined(MBEDTLS_PKCS1_V21) if ((padding == MBEDTLS_RSA_PKCS_V21) && (hash_id != MBEDTLS_MD_NONE)) { /* Just make sure this hash is supported in this build. */ if (mbedtls_md_info_from_type(hash_id) == NULL) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #endif /* MBEDTLS_PKCS1_V21 */ ctx->padding = padding; ctx->hash_id = hash_id; return 0; } /* * Get padding mode of initialized RSA context */ int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx) { return ctx->padding; } /* * Get hash identifier of mbedtls_md_type_t type */ int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx) { return ctx->hash_id; } /* * Get length in bits of RSA modulus */ size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx) { return mbedtls_mpi_bitlen(&ctx->N); } /* * Get length in bytes of RSA modulus */ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx) { return ctx->len; } #if defined(MBEDTLS_GENPRIME) /* * Generate an RSA keypair * * This generation method follows the RSA key pair generation procedure of * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. */ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi H, G, L; int prime_quality = 0; /* * If the modulus is 1024 bit long or shorter, then the security strength of * the RSA algorithm is less than or equal to 80 bits and therefore an error * rate of 2^-80 is sufficient. */ if (nbits > 1024) { prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; } mbedtls_mpi_init(&H); mbedtls_mpi_init(&G); mbedtls_mpi_init(&L); if (exponent < 3 || nbits % 2 != 0) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } if (nbits < MBEDTLS_RSA_GEN_KEY_MIN_BITS) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } /* * find primes P and Q with Q < P so that: * 1. |P-Q| > 2^( nbits / 2 - 100 ) * 2. GCD( E, (P-1)*(Q-1) ) == 1 * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) */ MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->E, exponent)); do { MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->P, nbits >> 1, prime_quality, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_gen_prime(&ctx->Q, nbits >> 1, prime_quality, f_rng, p_rng)); /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&H, &ctx->P, &ctx->Q)); if (mbedtls_mpi_bitlen(&H) <= ((nbits >= 200) ? ((nbits >> 1) - 99) : 0)) { continue; } /* not required by any standards, but some users rely on the fact that P > Q */ if (H.s < 0) { mbedtls_mpi_swap(&ctx->P, &ctx->Q); } /* Temporarily replace P,Q by P-1, Q-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->P, &ctx->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&ctx->Q, &ctx->Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&H, &ctx->P, &ctx->Q)); /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->E, &H)); if (mbedtls_mpi_cmp_int(&G, 1) != 0) { continue; } /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(&G, &ctx->P, &ctx->Q)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&L, NULL, &H, &G)); MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->D, &ctx->E, &L)); if (mbedtls_mpi_bitlen(&ctx->D) <= ((nbits + 1) / 2)) { // (FIPS 186-4 §B.3.1 criterion 3(a)) continue; } break; } while (1); /* Restore P,Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->P, &ctx->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&ctx->Q, &ctx->Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)); ctx->len = mbedtls_mpi_size(&ctx->N); #if !defined(MBEDTLS_RSA_NO_CRT) /* * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MBEDTLS_MPI_CHK(mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP)); #endif /* MBEDTLS_RSA_NO_CRT */ /* Double-check */ MBEDTLS_MPI_CHK(mbedtls_rsa_check_privkey(ctx)); cleanup: mbedtls_mpi_free(&H); mbedtls_mpi_free(&G); mbedtls_mpi_free(&L); if (ret != 0) { mbedtls_rsa_free(ctx); if ((-ret & ~0x7f) == 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret); } return ret; } return 0; } #endif /* MBEDTLS_GENPRIME */ /* * Check a public RSA key */ int mbedtls_rsa_check_pubkey(const mbedtls_rsa_context *ctx) { if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_mpi_bitlen(&ctx->N) < 128) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_mpi_get_bit(&ctx->E, 0) == 0 || mbedtls_mpi_bitlen(&ctx->E) < 2 || mbedtls_mpi_cmp_mpi(&ctx->E, &ctx->N) >= 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return 0; } /* * Check for the consistency of all fields in an RSA private key context */ int mbedtls_rsa_check_privkey(const mbedtls_rsa_context *ctx) { if (mbedtls_rsa_check_pubkey(ctx) != 0 || rsa_check_context(ctx, 1 /* private */, 1 /* blinding */) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_rsa_validate_params(&ctx->N, &ctx->P, &ctx->Q, &ctx->D, &ctx->E, NULL, NULL) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } #if !defined(MBEDTLS_RSA_NO_CRT) else if (mbedtls_rsa_validate_crt(&ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } #endif return 0; } /* * Check if contexts holding a public and private key match */ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv) { if (mbedtls_rsa_check_pubkey(pub) != 0 || mbedtls_rsa_check_privkey(prv) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } if (mbedtls_mpi_cmp_mpi(&pub->N, &prv->N) != 0 || mbedtls_mpi_cmp_mpi(&pub->E, &prv->E) != 0) { return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return 0; } /* * Do an RSA public key operation */ int mbedtls_rsa_public(mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; mbedtls_mpi T; if (rsa_check_context(ctx, 0 /* public */, 0 /* no blinding */)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mbedtls_mpi_init(&T); #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len)); if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN)); MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif mbedtls_mpi_free(&T); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret); } return 0; } /* * Generate or update blinding values, see section 10 of: * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer * Berlin Heidelberg, 1996. p. 104-113. */ static int rsa_prepare_blinding(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret, count = 0; mbedtls_mpi R; mbedtls_mpi_init(&R); if (ctx->Vf.p != NULL) { /* We already have blinding values, just update them by squaring */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->N)); goto cleanup; } /* Unblinding value: Vf = random number, invertible mod N */ do { if (count++ > 10) { ret = MBEDTLS_ERR_RSA_RNG_FAILED; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->Vf, ctx->len - 1, f_rng, p_rng)); /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, ctx->len - 1, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vf, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); /* At this point, Vi is invertible mod N if and only if both Vf and R * are invertible mod N. If one of them isn't, we don't need to know * which one, we just loop and choose new values for both of them. * (Each iteration succeeds with overwhelming probability.) */ ret = mbedtls_mpi_inv_mod(&ctx->Vi, &ctx->Vi, &ctx->N); if (ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) { goto cleanup; } } while (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE); /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->N)); /* Blinding value: Vi = Vf^(-e) mod N * (Vi already contains Vf^-1 at this point) */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN)); cleanup: mbedtls_mpi_free(&R); return ret; } /* * Unblind * T = T * Vf mod N */ static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p); const size_t nlimbs = N->n; const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs); mbedtls_mpi RR, M_T; mbedtls_mpi_init(&RR); mbedtls_mpi_init(&M_T); MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs)); MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs)); /* T = T * Vf mod N * Reminder: montmul(A, B, N) = A * B * R^-1 mod N * Usually both operands are multiplied by R mod N beforehand (by calling * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka * "in the Montgomery domain"). Here we only multiply one operand by R mod * N, so the result is directly what we want - no need to call * `from_mont_rep()` on it. */ mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p); mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p); cleanup: mbedtls_mpi_free(&RR); mbedtls_mpi_free(&M_T); return ret; } /* * Exponent blinding supposed to prevent side-channel attacks using multiple * traces of measurements to recover the RSA key. The more collisions are there, * the more bits of the key can be recovered. See [3]. * * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) * observations on average. * * For example with 28 byte blinding to achieve 2 collisions the adversary has * to make 2^112 observations on average. * * (With the currently (as of 2017 April) known best algorithms breaking 2048 * bit RSA requires approximately as much time as trying out 2^112 random keys. * Thus in this sense with 28 byte blinding the security is not reduced by * side-channel attacks like the one in [3]) * * This countermeasure does not help if the key recovery is possible with a * single trace. */ #define RSA_EXPONENT_BLINDING 28 /* * Do an RSA private key operation */ int mbedtls_rsa_private(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; /* Temporary holding the result */ mbedtls_mpi T; /* Temporaries holding P-1, Q-1 and the * exponent blinding factor, respectively. */ mbedtls_mpi P1, Q1, R; #if !defined(MBEDTLS_RSA_NO_CRT) /* Temporaries holding the results mod p resp. mod q. */ mbedtls_mpi TP, TQ; /* Temporaries holding the blinded exponents for * the mod p resp. mod q computation (if used). */ mbedtls_mpi DP_blind, DQ_blind; #else /* Temporary holding the blinded exponent (if used). */ mbedtls_mpi D_blind; #endif /* MBEDTLS_RSA_NO_CRT */ /* Temporaries holding the initial input and the double * checked result; should be the same in the end. */ mbedtls_mpi input_blinded, check_result_blinded; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (rsa_check_context(ctx, 1 /* private key checks */, 1 /* blinding on */) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif /* MPI Initialization */ mbedtls_mpi_init(&T); mbedtls_mpi_init(&P1); mbedtls_mpi_init(&Q1); mbedtls_mpi_init(&R); #if defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_init(&D_blind); #else mbedtls_mpi_init(&DP_blind); mbedtls_mpi_init(&DQ_blind); #endif #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ); #endif mbedtls_mpi_init(&input_blinded); mbedtls_mpi_init(&check_result_blinded); /* End of MPI initialization */ MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&T, input, ctx->len)); if (mbedtls_mpi_cmp_mpi(&T, &ctx->N) >= 0) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } /* * Blinding * T = T * Vi mod N */ MBEDTLS_MPI_CHK(rsa_prepare_blinding(ctx, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T)); /* * Exponent blinding */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&P1, &ctx->P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&Q1, &ctx->Q, 1)); #if defined(MBEDTLS_RSA_NO_CRT) /* * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D)); #else /* * DP_blind = ( P - 1 ) * R + DP */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DP_blind, &P1, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind, &ctx->DP)); /* * DQ_blind = ( Q - 1 ) * R + DQ */ MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&R, RSA_EXPONENT_BLINDING, f_rng, p_rng)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind, &ctx->DQ)); #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN)); #else /* * Faster decryption using the CRT * * TP = input ^ dP mod P * TQ = input ^ dQ mod Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP)); MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ)); /* * T = (TP - TQ) * (Q^-1 mod P) mod P */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&T, &TP, &TQ)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->QP)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &TP, &ctx->P)); /* * T = TQ + T * Q */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&TP, &T, &ctx->Q)); MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP)); #endif /* MBEDTLS_RSA_NO_CRT */ /* Verify the result to prevent glitching attacks. */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E, &ctx->N, &ctx->RN)); if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) { ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; goto cleanup; } /* * Unblind * T = T * Vf mod N */ MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N)); olen = ctx->len; MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen)); cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif mbedtls_mpi_free(&P1); mbedtls_mpi_free(&Q1); mbedtls_mpi_free(&R); #if defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_free(&D_blind); #else mbedtls_mpi_free(&DP_blind); mbedtls_mpi_free(&DQ_blind); #endif mbedtls_mpi_free(&T); #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ); #endif mbedtls_mpi_free(&check_result_blinded); mbedtls_mpi_free(&input_blinded); if (ret != 0 && ret >= -0x007f) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret); } return ret; } #if defined(MBEDTLS_PKCS1_V21) /** * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. * * \param dst buffer to mask * \param dlen length of destination buffer * \param src source of the mask generation * \param slen length of the source buffer * \param md_alg message digest to use */ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src, size_t slen, mbedtls_md_type_t md_alg) { unsigned char counter[4]; unsigned char *p; unsigned int hlen; size_t i, use_len; unsigned char mask[MBEDTLS_MD_MAX_SIZE]; int ret = 0; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; mbedtls_md_init(&md_ctx); md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { goto exit; } hlen = mbedtls_md_get_size(md_info); memset(mask, 0, sizeof(mask)); memset(counter, 0, 4); /* Generate and apply dbMask */ p = dst; while (dlen > 0) { use_len = hlen; if (dlen < hlen) { use_len = dlen; } if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, src, slen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, counter, 4)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) { goto exit; } for (i = 0; i < use_len; ++i) { *p++ ^= mask[i]; } counter[3]++; dlen -= use_len; } exit: mbedtls_platform_zeroize(mask, sizeof(mask)); mbedtls_md_free(&md_ctx); return ret; } /** * Generate Hash(M') as in RFC 8017 page 43 points 5 and 6. * * \param hash the input hash * \param hlen length of the input hash * \param salt the input salt * \param slen length of the input salt * \param out the output buffer - must be large enough for \p md_alg * \param md_alg message digest to use */ static int hash_mprime(const unsigned char *hash, size_t hlen, const unsigned char *salt, size_t slen, unsigned char *out, mbedtls_md_type_t md_alg) { const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; mbedtls_md_context_t md_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mbedtls_md_init(&md_ctx); if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) { goto exit; } if ((ret = mbedtls_md_starts(&md_ctx)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, zeros, sizeof(zeros))) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, hash, hlen)) != 0) { goto exit; } if ((ret = mbedtls_md_update(&md_ctx, salt, slen)) != 0) { goto exit; } if ((ret = mbedtls_md_finish(&md_ctx, out)) != 0) { goto exit; } exit: mbedtls_md_free(&md_ctx); return ret; } /** * Compute a hash. * * \param md_alg algorithm to use * \param input input message to hash * \param ilen input length * \param output the output buffer - must be large enough for \p md_alg */ static int compute_hash(mbedtls_md_type_t md_alg, const unsigned char *input, size_t ilen, unsigned char *output) { const mbedtls_md_info_t *md_info; md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return mbedtls_md(md_info, input, ilen, output); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V21) /* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function */ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t ilen, const unsigned char *input, unsigned char *output) { size_t olen; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = output; unsigned int hlen; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } olen = ctx->len; /* first comparison checks for overflow */ if (ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } memset(output, 0, olen); *p++ = 0; /* Generate a random octet string seed */ if ((ret = f_rng(p_rng, p, hlen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } p += hlen; /* Construct DB */ ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, p); if (ret != 0) { return ret; } p += hlen; p += olen - 2 * hlen - 2 - ilen; *p++ = 1; if (ilen != 0) { memcpy(p, input, ilen); } /* maskedDB: Apply dbMask to DB */ if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen, (mbedtls_md_type_t) ctx->hash_id)) != 0) { return ret; } /* maskedSeed: Apply seedMask to seed */ if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1, (mbedtls_md_type_t) ctx->hash_id)) != 0) { return ret; } return mbedtls_rsa_public(ctx, output, output); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function */ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output) { size_t nb_pad, olen; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = output; olen = ctx->len; /* first comparison checks for overflow */ if (ilen + 11 < ilen || olen < ilen + 11) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad = olen - 3 - ilen; *p++ = 0; if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } *p++ = MBEDTLS_RSA_CRYPT; while (nb_pad-- > 0) { int rng_dl = 100; do { ret = f_rng(p_rng, p, 1); } while (*p == 0 && --rng_dl && ret == 0); /* Check if RNG failed to generate data */ if (rng_dl == 0 || ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } p++; } *p++ = 0; if (ilen != 0) { memcpy(p, input, ilen); } return mbedtls_rsa_public(ctx, output, output); } #endif /* MBEDTLS_PKCS1_V15 */ /* * Add the message padding, then do an RSA operation */ int mbedtls_rsa_pkcs1_encrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t ilen, const unsigned char *input, unsigned char *output) { switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsaes_pkcs1_v15_encrypt(ctx, f_rng, p_rng, ilen, input, output); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsaes_oaep_encrypt(ctx, f_rng, p_rng, NULL, 0, ilen, input, output); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #if defined(MBEDTLS_PKCS1_V21) /* * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function */ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *label, size_t label_len, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen, i, pad_len; unsigned char *p; mbedtls_ct_condition_t bad, in_padding; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; /* * Parameters sanity checks */ if (ctx->padding != MBEDTLS_RSA_PKCS_V21) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } ilen = ctx->len; if (ilen < 16 || ilen > sizeof(buf)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } // checking for integer underflow if (2 * hlen + 2 > ilen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * RSA operation */ if( ctx->P.n == 0 ) ret = mbedtls_rsa_private( ctx, NULL, NULL, input, buf ); else ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); if (ret != 0) { goto cleanup; } /* * Unmask data and generate lHash */ /* seed: Apply seedMask to maskedSeed */ if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, (mbedtls_md_type_t) ctx->hash_id)) != 0 || /* DB: Apply dbMask to maskedDB */ (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, (mbedtls_md_type_t) ctx->hash_id)) != 0) { goto cleanup; } /* Generate lHash */ ret = compute_hash((mbedtls_md_type_t) ctx->hash_id, label, label_len, lhash); if (ret != 0) { goto cleanup; } /* * Check contents, in "constant-time" */ p = buf; bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */ p += hlen; /* Skip seed */ /* Check lHash */ bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(mbedtls_ct_memcmp(lhash, p, hlen))); p += hlen; /* Get zero-padding len, but always read till end of buffer * (minus one, for the 01 byte) */ pad_len = 0; in_padding = MBEDTLS_CT_TRUE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0)); pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1); } p += pad_len; bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01)); /* * The only information "leaked" is whether the padding was correct or not * (eg, no data is copied if it was not correct). This meets the * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between * the different error conditions. */ if (bad != MBEDTLS_CT_FALSE) { ret = MBEDTLS_ERR_RSA_INVALID_PADDING; goto cleanup; } if (ilen - ((size_t) (p - buf)) > output_max_len) { ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; goto cleanup; } *olen = ilen - ((size_t) (p - buf)); if (*olen != 0) { memcpy(output, p, *olen); } ret = 0; cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(lhash, sizeof(lhash)); return ret; } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function */ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; ilen = ctx->len; if (ctx->padding != MBEDTLS_RSA_PKCS_V15) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (ilen < 16 || ilen > sizeof(buf)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } ret = mbedtls_rsa_private(ctx, f_rng, p_rng, input, buf); if (ret != 0) { goto cleanup; } ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding(buf, ilen, output, output_max_len, olen); cleanup: mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Do an RSA operation, then remove the message padding */ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, size_t *olen, const unsigned char *input, unsigned char *output, size_t output_max_len) { switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsaes_pkcs1_v15_decrypt(ctx, f_rng, p_rng, olen, input, output, output_max_len); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsaes_oaep_decrypt(ctx, f_rng, p_rng, NULL, 0, olen, input, output, output_max_len); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #if defined(MBEDTLS_PKCS1_V21) static int rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig) { size_t olen; unsigned char *p = sig; unsigned char *salt = NULL; size_t slen, min_slen, hlen, offset = 0; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t msb; mbedtls_md_type_t hash_id; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (f_rng == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } olen = ctx->len; if (md_alg != MBEDTLS_MD_NONE) { /* Gather length of hash to sign */ size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg); if (exp_hashlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (hashlen != exp_hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } hash_id = (mbedtls_md_type_t) ctx->hash_id; if (hash_id == MBEDTLS_MD_NONE) { hash_id = md_alg; } hlen = mbedtls_md_get_size_from_type(hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) { /* Calculate the largest possible salt length, up to the hash size. * Normally this is the hash length, which is the maximum salt length * according to FIPS 185-4 §5.5 (e) and common practice. If there is not * enough room, use the maximum salt length that fits. The constraint is * that the hash length plus the salt length plus 2 bytes must be at most * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 * (PKCS#1 v2.2) §9.1.1 step 3. */ min_slen = hlen - 2; if (olen < hlen + min_slen + 2) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } else if (olen >= hlen + hlen + 2) { slen = hlen; } else { slen = olen - hlen - 2; } } else if ((saltlen < 0) || (saltlen + hlen + 2 > olen)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } else { slen = (size_t) saltlen; } memset(sig, 0, olen); /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ msb = mbedtls_mpi_bitlen(&ctx->N) - 1; p += olen - hlen - slen - 2; *p++ = 0x01; /* Generate salt of length slen in place in the encoded message */ salt = p; if ((ret = f_rng(p_rng, salt, slen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_RNG_FAILED, ret); } p += slen; /* Generate H = Hash( M' ) */ ret = hash_mprime(hash, hashlen, salt, slen, p, hash_id); if (ret != 0) { return ret; } /* Compensate for boundary condition when applying mask */ if (msb % 8 == 0) { offset = 1; } /* maskedDB: Apply dbMask to DB */ ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, hash_id); if (ret != 0) { return ret; } msb = mbedtls_mpi_bitlen(&ctx->N) - 1; sig[0] &= 0xFF >> (olen * 8 - msb); p += hlen; *p++ = 0xBC; if (ctx->P.n == 0) return mbedtls_rsa_private(ctx, NULL, NULL, sig, sig); return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig); } static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig) { if (ctx->padding != MBEDTLS_RSA_PKCS_V21) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen, sig); } int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); } /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with * the option to pass in the salt length. */ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, int saltlen, unsigned char *sig) { return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen, sig); } /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function */ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { return rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function */ /* Construct a PKCS v1.5 encoding of a hashed message * * This is used both for signature generation and verification. * * Parameters: * - md_alg: Identifies the hash algorithm used to generate the given hash; * MBEDTLS_MD_NONE if raw data is signed. * - hashlen: Length of hash. Must match md_alg if that's not NONE. * - hash: Buffer containing the hashed message or the raw data. * - dst_len: Length of the encoded message. * - dst: Buffer to hold the encoded message. * * Assumptions: * - hash has size hashlen. * - dst points to a buffer of size at least dst_len. * */ static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, size_t dst_len, unsigned char *dst) { size_t oid_size = 0; size_t nb_pad = dst_len; unsigned char *p = dst; const char *oid = NULL; /* Are we signing hashed or raw data? */ if (md_alg != MBEDTLS_MD_NONE) { unsigned char md_size = mbedtls_md_get_size_from_type(md_alg); if (md_size == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (hashlen != md_size) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Double-check that 8 + hashlen + oid_size can be used as a * 1-byte ASN.1 length encoding and that there's no overflow. */ if (8 + hashlen + oid_size >= 0x80 || 10 + hashlen < hashlen || 10 + hashlen + oid_size < 10 + hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Static bounds check: * - Need 10 bytes for five tag-length pairs. * (Insist on 1-byte length encodings to protect against variants of * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) * - Need hashlen bytes for hash * - Need oid_size bytes for hash alg OID. */ if (nb_pad < 10 + hashlen + oid_size) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad -= 10 + hashlen + oid_size; } else { if (nb_pad < hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad -= hashlen; } /* Need space for signature header and padding delimiter (3 bytes), * and 8 bytes for the minimal padding */ if (nb_pad < 3 + 8) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } nb_pad -= 3; /* Now nb_pad is the amount of memory to be filled * with padding, and at least 8 bytes long. */ /* Write signature header and padding */ *p++ = 0; *p++ = MBEDTLS_RSA_SIGN; memset(p, 0xFF, nb_pad); p += nb_pad; *p++ = 0; /* Are we signing raw data? */ if (md_alg == MBEDTLS_MD_NONE) { memcpy(p, hash, hashlen); return 0; } /* Signing hashed data, add corresponding ASN.1 structure * * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest } * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * Digest ::= OCTET STRING * * Schematic: * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] * TAG-NULL + LEN [ NULL ] ] * TAG-OCTET + LEN [ HASH ] ] */ *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; *p++ = (unsigned char) (0x08 + oid_size + hashlen); *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; *p++ = (unsigned char) (0x04 + oid_size); *p++ = MBEDTLS_ASN1_OID; *p++ = (unsigned char) oid_size; memcpy(p, oid, oid_size); p += oid_size; *p++ = MBEDTLS_ASN1_NULL; *p++ = 0x00; *p++ = MBEDTLS_ASN1_OCTET_STRING; *p++ = (unsigned char) hashlen; memcpy(p, hash, hashlen); p += hashlen; /* Just a sanity-check, should be automatic * after the initial bounds check. */ if (p != dst + dst_len) { mbedtls_platform_zeroize(dst, dst_len); return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } return 0; } /* * Do an RSA operation to sign the message digest */ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *sig_try = NULL, *verif = NULL; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (ctx->padding != MBEDTLS_RSA_PKCS_V15) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Prepare PKCS1-v1.5 encoding (padding and hash identifier) */ if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, ctx->len, sig)) != 0) { return ret; } /* Private key operation * * In order to prevent Lenstra's attack, make the signature in a * temporary buffer and check it before returning it. */ sig_try = mbedtls_calloc(1, ctx->len); if (sig_try == NULL) { return MBEDTLS_ERR_MPI_ALLOC_FAILED; } verif = mbedtls_calloc(1, ctx->len); if (verif == NULL) { mbedtls_free(sig_try); return MBEDTLS_ERR_MPI_ALLOC_FAILED; } MBEDTLS_MPI_CHK(mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig_try)); MBEDTLS_MPI_CHK(mbedtls_rsa_public(ctx, sig_try, verif)); if (mbedtls_ct_memcmp(verif, sig, ctx->len) != 0) { ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; goto cleanup; } memcpy(sig, sig_try, ctx->len); cleanup: mbedtls_zeroize_and_free(sig_try, ctx->len); mbedtls_zeroize_and_free(verif, ctx->len); if (ret != 0) { memset(sig, '!', ctx->len); } return ret; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Do an RSA operation to sign the message digest */ int mbedtls_rsa_pkcs1_sign(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig) { if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsassa_pkcs1_v15_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, sig); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsassa_pss_sign(ctx, f_rng, p_rng, md_alg, hashlen, hash, sig); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } #if defined(MBEDTLS_PKCS1_V21) /* * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, mbedtls_md_type_t mgf1_hash_id, int expected_salt_len, const unsigned char *sig) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t siglen; unsigned char *p; unsigned char *hash_start; unsigned char result[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; size_t observed_salt_len, msb; unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 }; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } siglen = ctx->len; if (siglen < 16 || siglen > sizeof(buf)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } ret = mbedtls_rsa_public(ctx, sig, buf); if (ret != 0) { return ret; } p = buf; if (buf[siglen - 1] != 0xBC) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } if (md_alg != MBEDTLS_MD_NONE) { /* Gather length of hash to sign */ size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg); if (exp_hashlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } if (hashlen != exp_hashlen) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } } hlen = mbedtls_md_get_size_from_type(mgf1_hash_id); if (hlen == 0) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* * Note: EMSA-PSS verification is over the length of N - 1 bits */ msb = mbedtls_mpi_bitlen(&ctx->N) - 1; if (buf[0] >> (8 - siglen * 8 + msb)) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } /* Compensate for boundary condition when applying mask */ if (msb % 8 == 0) { p++; siglen -= 1; } if (siglen < hlen + 2) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } hash_start = p + siglen - hlen - 1; ret = mgf_mask(p, siglen - hlen - 1, hash_start, hlen, mgf1_hash_id); if (ret != 0) { return ret; } buf[0] &= 0xFF >> (siglen * 8 - msb); while (p < hash_start - 1 && *p == 0) { p++; } if (*p++ != 0x01) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } observed_salt_len = (size_t) (hash_start - p); if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && observed_salt_len != (size_t) expected_salt_len) { return MBEDTLS_ERR_RSA_INVALID_PADDING; } /* * Generate H = Hash( M' ) */ ret = hash_mprime(hash, hashlen, p, observed_salt_len, result, mgf1_hash_id); if (ret != 0) { return ret; } if (FTMN_CALLEE_DONE_MEMCMP(memcmp, hash_start, result, hlen) != 0) { return MBEDTLS_ERR_RSA_VERIFY_FAILED; } return 0; } /* * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function */ int mbedtls_rsa_rsassa_pss_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { mbedtls_md_type_t mgf1_hash_id; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } mgf1_hash_id = (ctx->hash_id != MBEDTLS_MD_NONE) ? (mbedtls_md_type_t) ctx->hash_id : md_alg; return mbedtls_rsa_rsassa_pss_verify_ext(ctx, md_alg, hashlen, hash, mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, sig); } #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PKCS1_V15) /* * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function */ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { int ret = 0; size_t sig_len; unsigned char *encoded = NULL, *encoded_expected = NULL; if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } sig_len = ctx->len; /* * Prepare expected PKCS1 v1.5 encoding of hash. */ if ((encoded = mbedtls_calloc(1, sig_len)) == NULL || (encoded_expected = mbedtls_calloc(1, sig_len)) == NULL) { ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; goto cleanup; } if ((ret = rsa_rsassa_pkcs1_v15_encode(md_alg, hashlen, hash, sig_len, encoded_expected)) != 0) { goto cleanup; } /* * Apply RSA primitive to get what should be PKCS1 encoded hash. */ ret = mbedtls_rsa_public(ctx, sig, encoded); if (ret != 0) { goto cleanup; } /* * Compare */ if ((ret = FTMN_CALLEE_DONE_MEMCMP(mbedtls_ct_memcmp, encoded, encoded_expected, sig_len )) != 0) { ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; goto cleanup; } cleanup: if (encoded != NULL) { mbedtls_zeroize_and_free(encoded, sig_len); } if (encoded_expected != NULL) { mbedtls_zeroize_and_free(encoded_expected, sig_len); } return ret; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Do an RSA operation and check the message digest */ int mbedtls_rsa_pkcs1_verify(mbedtls_rsa_context *ctx, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, const unsigned char *sig) { if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) { return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; } switch (ctx->padding) { #if defined(MBEDTLS_PKCS1_V15) case MBEDTLS_RSA_PKCS_V15: return mbedtls_rsa_rsassa_pkcs1_v15_verify(ctx, md_alg, hashlen, hash, sig); #endif #if defined(MBEDTLS_PKCS1_V21) case MBEDTLS_RSA_PKCS_V21: return mbedtls_rsa_rsassa_pss_verify(ctx, md_alg, hashlen, hash, sig); #endif default: return MBEDTLS_ERR_RSA_INVALID_PADDING; } } /* * Copy the components of an RSA key */ int mbedtls_rsa_copy(mbedtls_rsa_context *dst, const mbedtls_rsa_context *src) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; dst->len = src->len; MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->N, &src->N)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->E, &src->E)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->D, &src->D)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->P, &src->P)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Q, &src->Q)); #if !defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DP, &src->DP)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->DQ, &src->DQ)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->QP, &src->QP)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RP, &src->RP)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RQ, &src->RQ)); #endif MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->RN, &src->RN)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vi, &src->Vi)); MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&dst->Vf, &src->Vf)); dst->padding = src->padding; dst->hash_id = src->hash_id; cleanup: if (ret != 0) { mbedtls_rsa_free(dst); } return ret; } /* * Free the components of an RSA key */ void mbedtls_rsa_free(mbedtls_rsa_context *ctx) { if (ctx == NULL) { return; } mbedtls_mpi_free(&ctx->Vi); mbedtls_mpi_free(&ctx->Vf); mbedtls_mpi_free(&ctx->RN); mbedtls_mpi_free(&ctx->D); mbedtls_mpi_free(&ctx->Q); mbedtls_mpi_free(&ctx->P); mbedtls_mpi_free(&ctx->E); mbedtls_mpi_free(&ctx->N); #if !defined(MBEDTLS_RSA_NO_CRT) mbedtls_mpi_free(&ctx->RQ); mbedtls_mpi_free(&ctx->RP); mbedtls_mpi_free(&ctx->QP); mbedtls_mpi_free(&ctx->DQ); mbedtls_mpi_free(&ctx->DP); #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_THREADING_C) /* Free the mutex, but only if it hasn't been freed already. */ if (ctx->ver != 0) { mbedtls_mutex_free(&ctx->mutex); ctx->ver = 0; } #endif } #endif /* !MBEDTLS_RSA_ALT */ #if defined(MBEDTLS_SELF_TEST) /* * Example RSA-1024 keypair, for test purposes */ #define KEY_LEN 128 #define RSA_N "9292758453063D803DD603D5E777D788" \ "8ED1D5BF35786190FA2F23EBC0848AEA" \ "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ "7130B9CED7ACDF54CFC7555AC14EEBAB" \ "93A89813FBF3C4F8066D2D800F7C38A8" \ "1AE31942917403FF4946B0A83D3D3E05" \ "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ "5E94BB77B07507233A0BC7BAC8F90F79" #define RSA_E "10001" #define RSA_D "24BF6185468786FDD303083D25E64EFC" \ "66CA472BC44D253102F8B4A9D3BFA750" \ "91386C0077937FE33FA3252D28855837" \ "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ "DF79C5CE07EE72C7F123142198164234" \ "CABB724CF78B8173B9F880FC86322407" \ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ "071513A1E85B5DFA031F21ECAE91A34D" #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ "2C01CAD19EA484A87EA4377637E75500" \ "FCB2005C5C7DD6EC4AC023CDA285D796" \ "C3D9E75E1EFC42488BB4F1D13AC30A57" #define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ "E211C2B9E5DB1ED0BF61D0D9899620F4" \ "910E4168387E3C30AA1E00C339A79508" \ "8452DD96A9A5EA5D9DCA68DA636032AF" #define PT_LEN 24 #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" #if defined(MBEDTLS_PKCS1_V15) static int myrand(void *rng_state, unsigned char *output, size_t len) { #if !defined(__OpenBSD__) && !defined(__NetBSD__) size_t i; if (rng_state != NULL) { rng_state = NULL; } for (i = 0; i < len; ++i) { output[i] = rand(); } #else if (rng_state != NULL) { rng_state = NULL; } arc4random_buf(output, len); #endif /* !OpenBSD && !NetBSD */ return 0; } #endif /* MBEDTLS_PKCS1_V15 */ /* * Checkup routine */ int mbedtls_rsa_self_test(int verbose) { int ret = 0; #if defined(MBEDTLS_PKCS1_V15) size_t len; mbedtls_rsa_context rsa; unsigned char rsa_plaintext[PT_LEN]; unsigned char rsa_decrypted[PT_LEN]; unsigned char rsa_ciphertext[KEY_LEN]; #if defined(MBEDTLS_MD_CAN_SHA1) unsigned char sha1sum[20]; #endif mbedtls_mpi K; mbedtls_mpi_init(&K); mbedtls_rsa_init(&rsa); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_N)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, &K, NULL, NULL, NULL, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_P)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, &K, NULL, NULL, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_Q)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, &K, NULL, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_D)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, &K, NULL)); MBEDTLS_MPI_CHK(mbedtls_mpi_read_string(&K, 16, RSA_E)); MBEDTLS_MPI_CHK(mbedtls_rsa_import(&rsa, NULL, NULL, NULL, NULL, &K)); MBEDTLS_MPI_CHK(mbedtls_rsa_complete(&rsa)); if (verbose != 0) { mbedtls_printf(" RSA key validation: "); } if (mbedtls_rsa_check_pubkey(&rsa) != 0 || mbedtls_rsa_check_privkey(&rsa) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n PKCS#1 encryption : "); } memcpy(rsa_plaintext, RSA_PT, PT_LEN); if (mbedtls_rsa_pkcs1_encrypt(&rsa, myrand, NULL, PT_LEN, rsa_plaintext, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n PKCS#1 decryption : "); } if (mbedtls_rsa_pkcs1_decrypt(&rsa, myrand, NULL, &len, rsa_ciphertext, rsa_decrypted, sizeof(rsa_decrypted)) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (memcmp(rsa_decrypted, rsa_plaintext, len) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } #if defined(MBEDTLS_MD_CAN_SHA1) if (verbose != 0) { mbedtls_printf(" PKCS#1 data sign : "); } if (mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), rsa_plaintext, PT_LEN, sha1sum) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } return 1; } if (mbedtls_rsa_pkcs1_sign(&rsa, myrand, NULL, MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n PKCS#1 sig. verify: "); } if (mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA1, 20, sha1sum, rsa_ciphertext) != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } ret = 1; goto cleanup; } if (verbose != 0) { mbedtls_printf("passed\n"); } #endif /* MBEDTLS_MD_CAN_SHA1 */ if (verbose != 0) { mbedtls_printf("\n"); } cleanup: mbedtls_mpi_free(&K); mbedtls_rsa_free(&rsa); #else /* MBEDTLS_PKCS1_V15 */ ((void) verbose); #endif /* MBEDTLS_PKCS1_V15 */ return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_RSA_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c000066400000000000000000000324721464416617300246570ustar00rootroot00000000000000/* * Helper functions for the RSA module * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #include "common.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #include "mbedtls/bignum.h" #include "rsa_alt_helpers.h" /* * Compute RSA prime factors from public and private exponents * * Summary of algorithm: * Setting F := lcm(P-1,Q-1), the idea is as follows: * * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime * factors of N. * * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same * construction still applies since (-)^K is the identity on the set of * roots of 1 in Z/NZ. * * The public and private key primitives (-)^E and (-)^D are mutually inverse * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. * Splitting L = 2^t * K with K odd, we have * * DE - 1 = FL = (F/2) * (2^(t+1)) * K, * * so (F / 2) * K is among the numbers * * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord * * where ord is the order of 2 in (DE - 1). * We can therefore iterate through these numbers apply the construction * of (a) and (b) above to attempt to factor N. * */ int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E, mbedtls_mpi const *D, mbedtls_mpi *P, mbedtls_mpi *Q) { int ret = 0; uint16_t attempt; /* Number of current attempt */ uint16_t iter; /* Number of squares computed in the current attempt */ uint16_t order; /* Order of 2 in DE - 1 */ mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ mbedtls_mpi K; /* Temporary holding the current candidate */ const unsigned char primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 }; const size_t num_primes = sizeof(primes) / sizeof(*primes); if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(N, 0) <= 0 || mbedtls_mpi_cmp_int(D, 1) <= 0 || mbedtls_mpi_cmp_mpi(D, N) >= 0 || mbedtls_mpi_cmp_int(E, 1) <= 0 || mbedtls_mpi_cmp_mpi(E, N) >= 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } /* * Initializations and temporary changes */ mbedtls_mpi_init(&K); mbedtls_mpi_init(&T); /* T := DE - 1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D, E)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1)); if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } /* After this operation, T holds the largest odd divisor of DE - 1. */ MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order)); /* * Actual work */ /* Skip trying 2 if N == 1 mod 8 */ attempt = 0; if (N->p[0] % 8 == 1) { attempt = 1; } for (; attempt < num_primes; ++attempt) { MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt])); /* Check if gcd(K,N) = 1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N)); if (mbedtls_mpi_cmp_int(P, 1) != 0) { continue; } /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... * and check whether they have nontrivial GCD with N. */ MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N, Q /* temporarily use Q for storing Montgomery * multiplication helper values */)); for (iter = 1; iter <= order; ++iter) { /* If we reach 1 prematurely, there's no point * in continuing to square K */ if (mbedtls_mpi_cmp_int(&K, 1) == 0) { break; } MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N)); if (mbedtls_mpi_cmp_int(P, 1) == 1 && mbedtls_mpi_cmp_mpi(P, N) == -1) { /* * Have found a nontrivial divisor P of N. * Set Q := N / P. */ MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P)); goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N)); } /* * If we get here, then either we prematurely aborted the loop because * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must * be 1 if D,E,N were consistent. * Check if that's the case and abort if not, to avoid very long, * yet eventually failing, computations if N,D,E were not sane. */ if (mbedtls_mpi_cmp_int(&K, 1) != 0) { break; } } ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; cleanup: mbedtls_mpi_free(&K); mbedtls_mpi_free(&T); return ret; } /* * Given P, Q and the public exponent E, deduce D. * This is essentially a modular inversion. */ int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, mbedtls_mpi const *Q, mbedtls_mpi const *E, mbedtls_mpi *D) { int ret = 0; mbedtls_mpi K, L; if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } if (mbedtls_mpi_cmp_int(P, 1) <= 0 || mbedtls_mpi_cmp_int(Q, 1) <= 0 || mbedtls_mpi_cmp_int(E, 0) == 0) { return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; } mbedtls_mpi_init(&K); mbedtls_mpi_init(&L); /* Temporarily put K := P-1 and L := Q-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1)); /* Temporarily put D := gcd(P-1, Q-1) */ MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L)); /* K := LCM(P-1, Q-1) */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L)); MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D)); /* Compute modular inverse of E in LCM(P-1, Q-1) */ MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K)); cleanup: mbedtls_mpi_free(&K); mbedtls_mpi_free(&L); return ret; } int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP) { int ret = 0; mbedtls_mpi K; mbedtls_mpi_init(&K); /* DP = D mod P-1 */ if (DP != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K)); } /* DQ = D mod Q-1 */ if (DQ != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K)); } /* QP = Q^{-1} mod P */ if (QP != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P)); } cleanup: mbedtls_mpi_free(&K); return ret; } /* * Check that core RSA parameters are sane. */ int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 0; mbedtls_mpi K, L; mbedtls_mpi_init(&K); mbedtls_mpi_init(&L); /* * Step 1: If PRNG provided, check that P and Q are prime */ #if defined(MBEDTLS_GENPRIME) /* * When generating keys, the strongest security we support aims for an error * rate of at most 2^-100 and we are aiming for the same certainty here as * well. */ if (f_rng != NULL && P != NULL && (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } if (f_rng != NULL && Q != NULL && (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } #else ((void) f_rng); ((void) p_rng); #endif /* MBEDTLS_GENPRIME */ /* * Step 2: Check that 1 < N = P * Q */ if (P != NULL && Q != NULL && N != NULL) { MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q)); if (mbedtls_mpi_cmp_int(N, 1) <= 0 || mbedtls_mpi_cmp_mpi(&K, N) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* * Step 3: Check and 1 < D, E < N if present. */ if (N != NULL && D != NULL && E != NULL) { if (mbedtls_mpi_cmp_int(D, 1) <= 0 || mbedtls_mpi_cmp_int(E, 1) <= 0 || mbedtls_mpi_cmp_mpi(D, N) >= 0 || mbedtls_mpi_cmp_mpi(E, N) >= 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* * Step 4: Check that D, E are inverse modulo P-1 and Q-1 */ if (P != NULL && Q != NULL && D != NULL && E != NULL) { if (mbedtls_mpi_cmp_int(P, 1) <= 0 || mbedtls_mpi_cmp_int(Q, 1) <= 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } /* Compute DE-1 mod P-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L)); if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } /* Compute DE-1 mod Q-1 */ MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L)); if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } cleanup: mbedtls_mpi_free(&K); mbedtls_mpi_free(&L); /* Wrap MPI error codes by RSA check failure error code */ if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) { ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } return ret; } /* * Check that RSA CRT parameters are in accordance with core parameters. */ int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *DP, const mbedtls_mpi *DQ, const mbedtls_mpi *QP) { int ret = 0; mbedtls_mpi K, L; mbedtls_mpi_init(&K); mbedtls_mpi_init(&L); /* Check that DP - D == 0 mod P - 1 */ if (DP != NULL) { if (P == NULL) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); if (mbedtls_mpi_cmp_int(&L, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* Check that DQ - D == 0 mod Q - 1 */ if (DQ != NULL) { if (Q == NULL) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K)); if (mbedtls_mpi_cmp_int(&L, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } /* Check that QP * Q - 1 == 0 mod P */ if (QP != NULL) { if (P == NULL || Q == NULL) { ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; goto cleanup; } MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q)); MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P)); if (mbedtls_mpi_cmp_int(&K, 0) != 0) { ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; goto cleanup; } } cleanup: /* Wrap MPI error codes by RSA check failure error code */ if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) { ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; } mbedtls_mpi_free(&K); mbedtls_mpi_free(&L); return ret; } #endif /* MBEDTLS_RSA_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h000066400000000000000000000201611464416617300246540ustar00rootroot00000000000000/** * \file rsa_alt_helpers.h * * \brief Context-independent RSA helper functions * * This module declares some RSA-related helper functions useful when * implementing the RSA interface. These functions are provided in a separate * compilation unit in order to make it easy for designers of alternative RSA * implementations to use them in their own code, as it is conceived that the * functionality they provide will be necessary for most complete * implementations. * * End-users of Mbed TLS who are not providing their own alternative RSA * implementations should not use these functions directly, and should instead * use only the functions declared in rsa.h. * * The interface provided by this module will be maintained through LTS (Long * Term Support) branches of Mbed TLS, but may otherwise be subject to change, * and must be considered an internal interface of the library. * * There are two classes of helper functions: * * (1) Parameter-generating helpers. These are: * - mbedtls_rsa_deduce_primes * - mbedtls_rsa_deduce_private_exponent * - mbedtls_rsa_deduce_crt * Each of these functions takes a set of core RSA parameters and * generates some other, or CRT related parameters. * * (2) Parameter-checking helpers. These are: * - mbedtls_rsa_validate_params * - mbedtls_rsa_validate_crt * They take a set of core or CRT related RSA parameters and check their * validity. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_ALT_HELPERS_H #define MBEDTLS_RSA_ALT_HELPERS_H #include "mbedtls/build_info.h" #include "mbedtls/bignum.h" #ifdef __cplusplus extern "C" { #endif /** * \brief Compute RSA prime moduli P, Q from public modulus N=PQ * and a pair of private and public key. * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param N RSA modulus N = PQ, with P, Q to be found * \param E RSA public exponent * \param D RSA private exponent * \param P Pointer to MPI holding first prime factor of N on success * \param Q Pointer to MPI holding second prime factor of N on success * * \return * - 0 if successful. In this case, P and Q constitute a * factorization of N. * - A non-zero error code otherwise. * * \note It is neither checked that P, Q are prime nor that * D, E are modular inverses wrt. P-1 and Q-1. For that, * use the helper function \c mbedtls_rsa_validate_params. * */ int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N, mbedtls_mpi const *E, mbedtls_mpi const *D, mbedtls_mpi *P, mbedtls_mpi *Q); /** * \brief Compute RSA private exponent from * prime moduli and public key. * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param P First prime factor of RSA modulus * \param Q Second prime factor of RSA modulus * \param E RSA public exponent * \param D Pointer to MPI holding the private exponent on success. * * \return * - 0 if successful. In this case, D is set to a simultaneous * modular inverse of E modulo both P-1 and Q-1. * - A non-zero error code otherwise. * * \note This function does not check whether P and Q are primes. * */ int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P, mbedtls_mpi const *Q, mbedtls_mpi const *E, mbedtls_mpi *D); /** * \brief Generate RSA-CRT parameters * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param P First prime factor of N * \param Q Second prime factor of N * \param D RSA private exponent * \param DP Output variable for D modulo P-1 * \param DQ Output variable for D modulo Q-1 * \param QP Output variable for the modular inverse of Q modulo P. * * \return 0 on success, non-zero error code otherwise. * * \note This function does not check whether P, Q are * prime and whether D is a valid private exponent. * */ int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP); /** * \brief Check validity of core RSA parameters * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param N RSA modulus N = PQ * \param P First prime factor of N * \param Q Second prime factor of N * \param D RSA private exponent * \param E RSA public exponent * \param f_rng PRNG to be used for primality check, or NULL * \param p_rng PRNG context for f_rng, or NULL * * \return * - 0 if the following conditions are satisfied * if all relevant parameters are provided: * - P prime if f_rng != NULL (%) * - Q prime if f_rng != NULL (%) * - 1 < N = P * Q * - 1 < D, E < N * - D and E are modular inverses modulo P-1 and Q-1 * (%) This is only done if MBEDTLS_GENPRIME is defined. * - A non-zero error code otherwise. * * \note The function can be used with a restricted set of arguments * to perform specific checks only. E.g., calling it with * (-,P,-,-,-) and a PRNG amounts to a primality check for P. */ int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *E, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); /** * \brief Check validity of RSA CRT parameters * * \note This is a 'static' helper function not operating on * an RSA context. Alternative implementations need not * overwrite it. * * \param P First prime factor of RSA modulus * \param Q Second prime factor of RSA modulus * \param D RSA private exponent * \param DP MPI to check for D modulo P-1 * \param DQ MPI to check for D modulo P-1 * \param QP MPI to check for the modular inverse of Q modulo P. * * \return * - 0 if the following conditions are satisfied: * - D = DP mod P-1 if P, D, DP != NULL * - Q = DQ mod P-1 if P, D, DQ != NULL * - QP = Q^-1 mod P if P, Q, QP != NULL * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, * potentially including \c MBEDTLS_ERR_MPI_XXX if some * MPI calculations failed. * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient * data was provided to check DP, DQ or QP. * * \note The function can be used with a restricted set of arguments * to perform specific checks only. E.g., calling it with the * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. */ int mbedtls_rsa_validate_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q, const mbedtls_mpi *D, const mbedtls_mpi *DP, const mbedtls_mpi *DQ, const mbedtls_mpi *QP); #ifdef __cplusplus } #endif #endif /* rsa_alt_helpers.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/rsa_internal.h000066400000000000000000000122661464416617300241750ustar00rootroot00000000000000/** * \file rsa_internal.h * * \brief Internal-only RSA public-key cryptosystem API. * * This file declares RSA-related functions that are to be used * only from within the Mbed TLS library itself. * */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_RSA_INTERNAL_H #define MBEDTLS_RSA_INTERNAL_H #include "mbedtls/rsa.h" #include "mbedtls/asn1.h" /** * \brief Parse a PKCS#1 (ASN.1) encoded private RSA key. * * \param rsa The RSA context where parsed data will be stored. * \param key The buffer that contains the key. * \param keylen The length of the key buffer in bytes. * * \return 0 on success. * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors. * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while * parsing data. * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the * provided key fail. */ int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen); /** * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key. * * \param rsa The RSA context where parsed data will be stored. * \param key The buffer that contains the key. * \param keylen The length of the key buffer in bytes. * * \return 0 on success. * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors. * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while * parsing data. * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the * provided key fail. */ int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen); /** * \brief Write a PKCS#1 (ASN.1) encoded private RSA key. * * \param rsa The RSA context which contains the data to be written. * \param start Beginning of the buffer that will be filled with the * private key. * \param p End of the buffer that will be filled with the private key. * On successful return, the referenced pointer will be * updated in order to point to the beginning of written data. * * \return On success, the number of bytes written to the output buffer * (i.e. a value > 0). * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not * contain a valid key pair. * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the * output buffer. * * \note The output buffer is filled backward, i.e. starting from its * end and moving toward its start. */ int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p); /** * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key. * * \param rsa The RSA context which contains the data to be written. * \param start Beginning of the buffer that will be filled with the * private key. * \param p End of the buffer that will be filled with the private key. * On successful return, the referenced pointer will be * updated in order to point to the beginning of written data. * * \return On success, the number of bytes written to the output buffer * (i.e. a value > 0). * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not * contain a valid public key. * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the * output buffer. * * \note The output buffer is filled backward, i.e. starting from its * end and moving toward its start. */ int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start, unsigned char **p); #if defined(MBEDTLS_PKCS1_V21) /** * \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign(). * The only difference between them is that this function is more flexible * on the parameters of \p ctx that are set with \c mbedtls_rsa_set_padding(). * * \note Compared to its counterpart, this function: * - does not check the padding setting of \p ctx. * - allows the hash_id of \p ctx to be MBEDTLS_MD_NONE, * in which case it uses \p md_alg as the hash_id. * * \note Refer to \c mbedtls_rsa_rsassa_pss_sign() for a description * of the functioning and parameters of this function. */ int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash, unsigned char *sig); #endif /* MBEDTLS_PKCS1_V21 */ #endif /* rsa_internal.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/sha1.c000066400000000000000000000335551464416617300223470ustar00rootroot00000000000000/* * FIPS-180-1 compliant SHA-1 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-1 standard was published by NIST in 1993. * * http://www.itl.nist.gov/fipspubs/fip180-1.htm */ #include "common.h" #if defined(MBEDTLS_SHA1_C) #include "mbedtls/sha1.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if !defined(MBEDTLS_SHA1_ALT) void mbedtls_sha1_init(mbedtls_sha1_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha1_context)); } void mbedtls_sha1_free(mbedtls_sha1_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha1_context)); } void mbedtls_sha1_clone(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src) { *dst = *src; } /* * SHA-1 context setup */ int mbedtls_sha1_starts(mbedtls_sha1_context *ctx) { ctx->total[0] = 0; ctx->total[1] = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; return 0; } #if !defined(MBEDTLS_SHA1_PROCESS_ALT) int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64]) { struct { uint32_t temp, W[16], A, B, C, D, E; } local; local.W[0] = MBEDTLS_GET_UINT32_BE(data, 0); local.W[1] = MBEDTLS_GET_UINT32_BE(data, 4); local.W[2] = MBEDTLS_GET_UINT32_BE(data, 8); local.W[3] = MBEDTLS_GET_UINT32_BE(data, 12); local.W[4] = MBEDTLS_GET_UINT32_BE(data, 16); local.W[5] = MBEDTLS_GET_UINT32_BE(data, 20); local.W[6] = MBEDTLS_GET_UINT32_BE(data, 24); local.W[7] = MBEDTLS_GET_UINT32_BE(data, 28); local.W[8] = MBEDTLS_GET_UINT32_BE(data, 32); local.W[9] = MBEDTLS_GET_UINT32_BE(data, 36); local.W[10] = MBEDTLS_GET_UINT32_BE(data, 40); local.W[11] = MBEDTLS_GET_UINT32_BE(data, 44); local.W[12] = MBEDTLS_GET_UINT32_BE(data, 48); local.W[13] = MBEDTLS_GET_UINT32_BE(data, 52); local.W[14] = MBEDTLS_GET_UINT32_BE(data, 56); local.W[15] = MBEDTLS_GET_UINT32_BE(data, 60); #define S(x, n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) #define R(t) \ ( \ local.temp = local.W[((t) - 3) & 0x0F] ^ \ local.W[((t) - 8) & 0x0F] ^ \ local.W[((t) - 14) & 0x0F] ^ \ local.W[(t) & 0x0F], \ (local.W[(t) & 0x0F] = S(local.temp, 1)) \ ) #define P(a, b, c, d, e, x) \ do \ { \ (e) += S((a), 5) + F((b), (c), (d)) + K + (x); \ (b) = S((b), 30); \ } while (0) local.A = ctx->state[0]; local.B = ctx->state[1]; local.C = ctx->state[2]; local.D = ctx->state[3]; local.E = ctx->state[4]; #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define K 0x5A827999 P(local.A, local.B, local.C, local.D, local.E, local.W[0]); P(local.E, local.A, local.B, local.C, local.D, local.W[1]); P(local.D, local.E, local.A, local.B, local.C, local.W[2]); P(local.C, local.D, local.E, local.A, local.B, local.W[3]); P(local.B, local.C, local.D, local.E, local.A, local.W[4]); P(local.A, local.B, local.C, local.D, local.E, local.W[5]); P(local.E, local.A, local.B, local.C, local.D, local.W[6]); P(local.D, local.E, local.A, local.B, local.C, local.W[7]); P(local.C, local.D, local.E, local.A, local.B, local.W[8]); P(local.B, local.C, local.D, local.E, local.A, local.W[9]); P(local.A, local.B, local.C, local.D, local.E, local.W[10]); P(local.E, local.A, local.B, local.C, local.D, local.W[11]); P(local.D, local.E, local.A, local.B, local.C, local.W[12]); P(local.C, local.D, local.E, local.A, local.B, local.W[13]); P(local.B, local.C, local.D, local.E, local.A, local.W[14]); P(local.A, local.B, local.C, local.D, local.E, local.W[15]); P(local.E, local.A, local.B, local.C, local.D, R(16)); P(local.D, local.E, local.A, local.B, local.C, R(17)); P(local.C, local.D, local.E, local.A, local.B, R(18)); P(local.B, local.C, local.D, local.E, local.A, R(19)); #undef K #undef F #define F(x, y, z) ((x) ^ (y) ^ (z)) #define K 0x6ED9EBA1 P(local.A, local.B, local.C, local.D, local.E, R(20)); P(local.E, local.A, local.B, local.C, local.D, R(21)); P(local.D, local.E, local.A, local.B, local.C, R(22)); P(local.C, local.D, local.E, local.A, local.B, R(23)); P(local.B, local.C, local.D, local.E, local.A, R(24)); P(local.A, local.B, local.C, local.D, local.E, R(25)); P(local.E, local.A, local.B, local.C, local.D, R(26)); P(local.D, local.E, local.A, local.B, local.C, R(27)); P(local.C, local.D, local.E, local.A, local.B, R(28)); P(local.B, local.C, local.D, local.E, local.A, R(29)); P(local.A, local.B, local.C, local.D, local.E, R(30)); P(local.E, local.A, local.B, local.C, local.D, R(31)); P(local.D, local.E, local.A, local.B, local.C, R(32)); P(local.C, local.D, local.E, local.A, local.B, R(33)); P(local.B, local.C, local.D, local.E, local.A, R(34)); P(local.A, local.B, local.C, local.D, local.E, R(35)); P(local.E, local.A, local.B, local.C, local.D, R(36)); P(local.D, local.E, local.A, local.B, local.C, R(37)); P(local.C, local.D, local.E, local.A, local.B, R(38)); P(local.B, local.C, local.D, local.E, local.A, R(39)); #undef K #undef F #define F(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) #define K 0x8F1BBCDC P(local.A, local.B, local.C, local.D, local.E, R(40)); P(local.E, local.A, local.B, local.C, local.D, R(41)); P(local.D, local.E, local.A, local.B, local.C, R(42)); P(local.C, local.D, local.E, local.A, local.B, R(43)); P(local.B, local.C, local.D, local.E, local.A, R(44)); P(local.A, local.B, local.C, local.D, local.E, R(45)); P(local.E, local.A, local.B, local.C, local.D, R(46)); P(local.D, local.E, local.A, local.B, local.C, R(47)); P(local.C, local.D, local.E, local.A, local.B, R(48)); P(local.B, local.C, local.D, local.E, local.A, R(49)); P(local.A, local.B, local.C, local.D, local.E, R(50)); P(local.E, local.A, local.B, local.C, local.D, R(51)); P(local.D, local.E, local.A, local.B, local.C, R(52)); P(local.C, local.D, local.E, local.A, local.B, R(53)); P(local.B, local.C, local.D, local.E, local.A, R(54)); P(local.A, local.B, local.C, local.D, local.E, R(55)); P(local.E, local.A, local.B, local.C, local.D, R(56)); P(local.D, local.E, local.A, local.B, local.C, R(57)); P(local.C, local.D, local.E, local.A, local.B, R(58)); P(local.B, local.C, local.D, local.E, local.A, R(59)); #undef K #undef F #define F(x, y, z) ((x) ^ (y) ^ (z)) #define K 0xCA62C1D6 P(local.A, local.B, local.C, local.D, local.E, R(60)); P(local.E, local.A, local.B, local.C, local.D, R(61)); P(local.D, local.E, local.A, local.B, local.C, R(62)); P(local.C, local.D, local.E, local.A, local.B, R(63)); P(local.B, local.C, local.D, local.E, local.A, R(64)); P(local.A, local.B, local.C, local.D, local.E, R(65)); P(local.E, local.A, local.B, local.C, local.D, R(66)); P(local.D, local.E, local.A, local.B, local.C, R(67)); P(local.C, local.D, local.E, local.A, local.B, R(68)); P(local.B, local.C, local.D, local.E, local.A, R(69)); P(local.A, local.B, local.C, local.D, local.E, R(70)); P(local.E, local.A, local.B, local.C, local.D, R(71)); P(local.D, local.E, local.A, local.B, local.C, R(72)); P(local.C, local.D, local.E, local.A, local.B, R(73)); P(local.B, local.C, local.D, local.E, local.A, R(74)); P(local.A, local.B, local.C, local.D, local.E, R(75)); P(local.E, local.A, local.B, local.C, local.D, R(76)); P(local.D, local.E, local.A, local.B, local.C, R(77)); P(local.C, local.D, local.E, local.A, local.B, R(78)); P(local.B, local.C, local.D, local.E, local.A, R(79)); #undef K #undef F ctx->state[0] += local.A; ctx->state[1] += local.B; ctx->state[2] += local.C; ctx->state[3] += local.D; ctx->state[4] += local.E; /* Zeroise buffers and variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_SHA1_PROCESS_ALT */ /* * SHA-1 process buffer */ int mbedtls_sha1_update(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = 64 - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= 64) { if ((ret = mbedtls_internal_sha1_process(ctx, input)) != 0) { return ret; } input += 64; ilen -= 64; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * SHA-1 final digest */ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ used = ctx->total[0] & 0x3F; ctx->buffer[used++] = 0x80; if (used <= 56) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, 64 - used); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 56); } /* * Add message length */ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56); MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ MBEDTLS_PUT_UINT32_BE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_BE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_BE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16); ret = 0; exit: mbedtls_sha1_free(ctx); return ret; } #endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ int mbedtls_sha1(const unsigned char *input, size_t ilen, unsigned char output[20]) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha1_context ctx; mbedtls_sha1_init(&ctx); if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { goto exit; } if ((ret = mbedtls_sha1_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha1_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha1_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-1 test vectors */ static const unsigned char sha1_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; static const size_t sha1_test_buflen[3] = { 3, 56, 1000 }; static const unsigned char sha1_test_sum[3][20] = { { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } }; /* * Checkup routine */ int mbedtls_sha1_self_test(int verbose) { int i, j, buflen, ret = 0; unsigned char buf[1024]; unsigned char sha1sum[20]; mbedtls_sha1_context ctx; mbedtls_sha1_init(&ctx); /* * SHA-1 */ for (i = 0; i < 3; i++) { if (verbose != 0) { mbedtls_printf(" SHA-1 test #%d: ", i + 1); } if ((ret = mbedtls_sha1_starts(&ctx)) != 0) { goto fail; } if (i == 2) { memset(buf, 'a', buflen = 1000); for (j = 0; j < 1000; j++) { ret = mbedtls_sha1_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { ret = mbedtls_sha1_update(&ctx, sha1_test_buf[i], sha1_test_buflen[i]); if (ret != 0) { goto fail; } } if ((ret = mbedtls_sha1_finish(&ctx, sha1sum)) != 0) { goto fail; } if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } goto exit; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } exit: mbedtls_sha1_free(&ctx); return ret; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA1_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/sha256.c000066400000000000000000000725561464416617300225270ustar00rootroot00000000000000/* * FIPS-180-2 compliant SHA-256 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. * * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ #if defined(__clang__) && (__clang_major__ >= 4) /* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if, * but that is defined by build_info.h, and we need this block to happen first. */ #if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A') #if __ARM_ARCH >= 8 #define MBEDTLS_SHA256_ARCH_IS_ARMV8_A #endif #endif #if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO) /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. * * The intrinsic declaration are guarded by predefined ACLE macros in clang: * these are normally only enabled by the -march option on the command line. * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_CRYPTO 1 /* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions * * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it * for older compilers. */ #define __ARM_FEATURE_SHA2 1 #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG #endif #endif /* defined(__clang__) && (__clang_major__ >= 4) */ /* Ensure that SIG_SETMASK is defined when -std=c99 is used. */ #define _GNU_SOURCE #include "common.h" #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C) #include "mbedtls/sha256.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #include "mbedtls/platform.h" #if defined(MBEDTLS_ARCH_IS_ARMV8_A) # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) # if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) # warning "Target does not support NEON instructions" # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT # else # error "Target does not support NEON instructions" # endif # endif # endif # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) /* *INDENT-OFF* */ # if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) # if defined(__ARMCOMPILER_VERSION) # if __ARMCOMPILER_VERSION <= 6090000 # error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # endif # pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(__clang__) # if __clang_major__ < 4 # error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # endif # pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # elif defined(__GNUC__) /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some * intrinsics are missing. Missing intrinsics could be worked around. */ # if __GNUC__ < 6 # error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # else # pragma GCC push_options # pragma GCC target ("arch=armv8-a+crypto") # define MBEDTLS_POP_TARGET_PRAGMA # endif # else # error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*" # endif # endif /* *INDENT-ON* */ # endif # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) # if defined(__unix__) # if defined(__linux__) /* Our preferred method of detection is getauxval() */ # include /* These are not always defined via sys/auxv.h */ # if !defined(HWCAP_SHA2) # define HWCAP_SHA2 (1 << 6) # endif # if !defined(HWCAP2_SHA2) # define HWCAP2_SHA2 (1 << 3) # endif # endif /* Use SIGILL on Unix, and fall back to it on Linux */ # include # endif # endif #elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) /* * Capability detection code comes early, so we can disable * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found */ #if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2) static int mbedtls_a64_crypto_sha256_determine_support(void) { return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0; } #elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2) static int mbedtls_a64_crypto_sha256_determine_support(void) { return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0; } #elif defined(__APPLE__) static int mbedtls_a64_crypto_sha256_determine_support(void) { return 1; } #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) #define WIN32_LEAN_AND_MEAN #include #include static int mbedtls_a64_crypto_sha256_determine_support(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; } #elif defined(__unix__) && defined(SIG_SETMASK) /* Detection with SIGILL, setjmp() and longjmp() */ #include #include static jmp_buf return_from_sigill; /* * Armv8-A SHA256 support detection via SIGILL */ static void sigill_handler(int signal) { (void) signal; longjmp(return_from_sigill, 1); } static int mbedtls_a64_crypto_sha256_determine_support(void) { struct sigaction old_action, new_action; sigset_t old_mask; if (sigprocmask(0, NULL, &old_mask)) { return 0; } sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; new_action.sa_handler = sigill_handler; sigaction(SIGILL, &new_action, &old_action); static int ret = 0; if (setjmp(return_from_sigill) == 0) { /* First return only */ /* If this traps, we will return a second time from setjmp() with 1 */ #if defined(MBEDTLS_ARCH_IS_ARM64) asm volatile ("sha256h q0, q0, v0.4s" : : : "v0"); #else asm volatile ("sha256h.32 q0, q0, q0" : : : "q0"); #endif ret = 1; } sigaction(SIGILL, &old_action, NULL); sigprocmask(SIG_SETMASK, &old_mask, NULL); return ret; } #else #warning "No mechanism to detect ARMV8_CRYPTO found, using C code only" #undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */ #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ #if !defined(MBEDTLS_SHA256_ALT) #define SHA256_BLOCK_SIZE 64 void mbedtls_sha256_init(mbedtls_sha256_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha256_context)); } void mbedtls_sha256_free(mbedtls_sha256_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context)); } void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src) { *dst = *src; } /* * SHA-256 context setup */ int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224) { #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) if (is224 != 0 && is224 != 1) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA256_C) if (is224 != 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA224_C only */ if (is224 == 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #endif ctx->total[0] = 0; ctx->total[1] = 0; if (is224 == 0) { #if defined(MBEDTLS_SHA256_C) ctx->state[0] = 0x6A09E667; ctx->state[1] = 0xBB67AE85; ctx->state[2] = 0x3C6EF372; ctx->state[3] = 0xA54FF53A; ctx->state[4] = 0x510E527F; ctx->state[5] = 0x9B05688C; ctx->state[6] = 0x1F83D9AB; ctx->state[7] = 0x5BE0CD19; #endif } else { #if defined(MBEDTLS_SHA224_C) ctx->state[0] = 0xC1059ED8; ctx->state[1] = 0x367CD507; ctx->state[2] = 0x3070DD17; ctx->state[3] = 0xF70E5939; ctx->state[4] = 0xFFC00B31; ctx->state[5] = 0x68581511; ctx->state[6] = 0x64F98FA7; ctx->state[7] = 0xBEFA4FA4; #endif } #if defined(MBEDTLS_SHA224_C) ctx->is224 = is224; #endif return 0; } #if !defined(MBEDTLS_SHA256_PROCESS_ALT) static const uint32_t K[] = { 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, }; #endif #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) # define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many # define mbedtls_internal_sha256_process_a64_crypto mbedtls_internal_sha256_process #endif static size_t mbedtls_internal_sha256_process_many_a64_crypto( mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) { uint32x4_t abcd = vld1q_u32(&ctx->state[0]); uint32x4_t efgh = vld1q_u32(&ctx->state[4]); size_t processed = 0; for (; len >= SHA256_BLOCK_SIZE; processed += SHA256_BLOCK_SIZE, msg += SHA256_BLOCK_SIZE, len -= SHA256_BLOCK_SIZE) { uint32x4_t tmp, abcd_prev; uint32x4_t abcd_orig = abcd; uint32x4_t efgh_orig = efgh; uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0)); uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1)); uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2)); uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3)); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */ /* Untested on BE */ sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0))); sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1))); sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2))); sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3))); #endif /* Rounds 0 to 3 */ tmp = vaddq_u32(sched0, vld1q_u32(&K[0])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds 4 to 7 */ tmp = vaddq_u32(sched1, vld1q_u32(&K[4])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds 8 to 11 */ tmp = vaddq_u32(sched2, vld1q_u32(&K[8])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds 12 to 15 */ tmp = vaddq_u32(sched3, vld1q_u32(&K[12])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); for (int t = 16; t < 64; t += 16) { /* Rounds t to t + 3 */ sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3); tmp = vaddq_u32(sched0, vld1q_u32(&K[t])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds t + 4 to t + 7 */ sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0); tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds t + 8 to t + 11 */ sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1); tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); /* Rounds t + 12 to t + 15 */ sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2); tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12])); abcd_prev = abcd; abcd = vsha256hq_u32(abcd_prev, efgh, tmp); efgh = vsha256h2q_u32(efgh, abcd_prev, tmp); } abcd = vaddq_u32(abcd, abcd_orig); efgh = vaddq_u32(efgh, efgh_orig); } vst1q_u32(&ctx->state[0], abcd); vst1q_u32(&ctx->state[4], efgh); return processed; } #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and Armv8-A * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() */ static #endif int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_SIZE]) { return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data, SHA256_BLOCK_SIZE) == SHA256_BLOCK_SIZE) ? 0 : -1; } #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many #define mbedtls_internal_sha256_process_c mbedtls_internal_sha256_process #endif #if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \ !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) #define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n)) #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n)))) #define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) #define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) #define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) #define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define R(t) \ ( \ local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ S0(local.W[(t) - 15]) + local.W[(t) - 16] \ ) #define P(a, b, c, d, e, f, g, h, x, K) \ do \ { \ local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \ local.temp2 = S2(a) + F0((a), (b), (c)); \ (d) += local.temp1; (h) = local.temp1 + local.temp2; \ } while (0) #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and Armv8 * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process() */ static #endif int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_SIZE]) { struct { uint32_t temp1, temp2, W[64]; uint32_t A[8]; } local; unsigned int i; for (i = 0; i < 8; i++) { local.A[i] = ctx->state[i]; } #if defined(MBEDTLS_SHA256_SMALLER) for (i = 0; i < 64; i++) { if (i < 16) { local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i); } else { R(i); } P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i]); local.temp1 = local.A[7]; local.A[7] = local.A[6]; local.A[6] = local.A[5]; local.A[5] = local.A[4]; local.A[4] = local.A[3]; local.A[3] = local.A[2]; local.A[2] = local.A[1]; local.A[1] = local.A[0]; local.A[0] = local.temp1; } #else /* MBEDTLS_SHA256_SMALLER */ for (i = 0; i < 16; i++) { local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i); } for (i = 0; i < 16; i += 8) { P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]); P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]); P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]); P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]); P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]); P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]); P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]); P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]); } for (i = 16; i < 64; i += 8) { P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]); P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]); P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]); P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]); P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]); P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]); P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]); P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]); } #endif /* MBEDTLS_SHA256_SMALLER */ for (i = 0; i < 8; i++) { ctx->state[i] += local.A[i]; } /* Zeroise buffers and variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) static size_t mbedtls_internal_sha256_process_many_c( mbedtls_sha256_context *ctx, const uint8_t *data, size_t len) { size_t processed = 0; while (len >= SHA256_BLOCK_SIZE) { if (mbedtls_internal_sha256_process_c(ctx, data) != 0) { return 0; } data += SHA256_BLOCK_SIZE; len -= SHA256_BLOCK_SIZE; processed += SHA256_BLOCK_SIZE; } return processed; } #endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) static int mbedtls_a64_crypto_sha256_has_support(void) { static int done = 0; static int supported = 0; if (!done) { supported = mbedtls_a64_crypto_sha256_determine_support(); done = 1; } return supported; } static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len) { if (mbedtls_a64_crypto_sha256_has_support()) { return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len); } else { return mbedtls_internal_sha256_process_many_c(ctx, msg, len); } } int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[SHA256_BLOCK_SIZE]) { if (mbedtls_a64_crypto_sha256_has_support()) { return mbedtls_internal_sha256_process_a64_crypto(ctx, data); } else { return mbedtls_internal_sha256_process_c(ctx, data); } } #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ /* * SHA-256 process buffer */ int mbedtls_sha256_update(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; uint32_t left; if (ilen == 0) { return 0; } left = ctx->total[0] & 0x3F; fill = SHA256_BLOCK_SIZE - left; ctx->total[0] += (uint32_t) ilen; ctx->total[0] &= 0xFFFFFFFF; if (ctx->total[0] < (uint32_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= SHA256_BLOCK_SIZE) { size_t processed = mbedtls_internal_sha256_process_many(ctx, input, ilen); if (processed < SHA256_BLOCK_SIZE) { return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } input += processed; ilen -= processed; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * SHA-256 final digest */ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t used; uint32_t high, low; int truncated = 0; /* * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ used = ctx->total[0] & 0x3F; ctx->buffer[used++] = 0x80; if (used <= 56) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 56 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 56); } /* * Add message length */ high = (ctx->total[0] >> 29) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56); MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60); if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ MBEDTLS_PUT_UINT32_BE(ctx->state[0], output, 0); MBEDTLS_PUT_UINT32_BE(ctx->state[1], output, 4); MBEDTLS_PUT_UINT32_BE(ctx->state[2], output, 8); MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12); MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16); MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20); MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24); #if defined(MBEDTLS_SHA224_C) truncated = ctx->is224; #endif if (!truncated) { MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28); } ret = 0; exit: mbedtls_sha256_free(ctx); return ret; } #endif /* !MBEDTLS_SHA256_ALT */ /* * output = SHA-256( input buffer ) */ int mbedtls_sha256(const unsigned char *input, size_t ilen, unsigned char *output, int is224) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha256_context ctx; #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) if (is224 != 0 && is224 != 1) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA256_C) if (is224 != 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA224_C only */ if (is224 == 0) { return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA; } #endif mbedtls_sha256_init(&ctx); if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { goto exit; } if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha256_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ static const unsigned char sha_test_buf[3][57] = { { "abc" }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { "" } }; static const size_t sha_test_buflen[3] = { 3, 56, 1000 }; typedef const unsigned char (sha_test_sum_t)[32]; /* * SHA-224 test vectors */ #if defined(MBEDTLS_SHA224_C) static sha_test_sum_t sha224_test_sum[] = { { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, 0xE3, 0x6C, 0x9D, 0xA7 }, { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, 0x52, 0x52, 0x25, 0x25 }, { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, 0x4E, 0xE7, 0xAD, 0x67 } }; #endif /* * SHA-256 test vectors */ #if defined(MBEDTLS_SHA256_C) static sha_test_sum_t sha256_test_sum[] = { { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } }; #endif /* * Checkup routine */ static int mbedtls_sha256_common_self_test(int verbose, int is224) { int i, buflen, ret = 0; unsigned char *buf; unsigned char sha256sum[32]; mbedtls_sha256_context ctx; #if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C) sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum; #elif defined(MBEDTLS_SHA256_C) sha_test_sum_t *sha_test_sum = sha256_test_sum; #else sha_test_sum_t *sha_test_sum = sha224_test_sum; #endif buf = mbedtls_calloc(1024, sizeof(unsigned char)); if (NULL == buf) { if (verbose != 0) { mbedtls_printf("Buffer allocation failed\n"); } return 1; } mbedtls_sha256_init(&ctx); for (i = 0; i < 3; i++) { if (verbose != 0) { mbedtls_printf(" SHA-%d test #%d: ", 256 - is224 * 32, i + 1); } if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) { goto fail; } if (i == 2) { memset(buf, 'a', buflen = 1000); for (int j = 0; j < 1000; j++) { ret = mbedtls_sha256_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { ret = mbedtls_sha256_update(&ctx, sha_test_buf[i], sha_test_buflen[i]); if (ret != 0) { goto fail; } } if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) { goto fail; } if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } goto exit; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } exit: mbedtls_sha256_free(&ctx); mbedtls_free(buf); return ret; } #if defined(MBEDTLS_SHA256_C) int mbedtls_sha256_self_test(int verbose) { return mbedtls_sha256_common_self_test(verbose, 0); } #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA224_C) int mbedtls_sha224_self_test(int verbose) { return mbedtls_sha256_common_self_test(verbose, 1); } #endif /* MBEDTLS_SHA224_C */ #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/sha3.c000066400000000000000000000533361464416617300223500ustar00rootroot00000000000000/* * FIPS-202 compliant SHA3 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-3 Secure Hash Standard was published by NIST in 2015. * * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf */ #include "common.h" #if defined(MBEDTLS_SHA3_C) /* * These macros select manually unrolled implementations of parts of the main permutation function. * * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot * from manually unrolling at higher optimisation levels. * * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and * x86-64. */ #if !defined(MBEDTLS_SHA3_THETA_UNROLL) #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names #endif #if !defined(MBEDTLS_SHA3_CHI_UNROLL) #if defined(__OPTIMIZE_SIZE__) #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names #else #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names #endif #endif #if !defined(MBEDTLS_SHA3_PI_UNROLL) #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names #endif #if !defined(MBEDTLS_SHA3_RHO_UNROLL) #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names #endif #include "mbedtls/sha3.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #include #if defined(MBEDTLS_SELF_TEST) #include "mbedtls/platform.h" #endif /* MBEDTLS_SELF_TEST */ #define XOR_BYTE 0x6 /* Precomputed masks for the iota transform. * * Each round uses a 64-bit mask value. In each mask values, only * bits whose position is of the form 2^k-1 can be set, thus only * 7 of 64 bits of the mask need to be known for each mask value. * * We use a compressed encoding of the mask where bits 63, 31 and 15 * are moved to bits 4-6. This allows us to make each mask value * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with * perhaps a little variation due to alignment). Decompressing this * requires a little code, but much less than the savings on the table. * * The impact on performance depends on the platform and compiler. * There's a bit more computation, but less memory bandwidth. A quick * benchmark on x86_64 shows a 7% speed improvement with GCC and a * 5% speed penalty with Clang, compared to the naive uint64_t[24] table. * YMMV. */ /* Helper macro to set the values of the higher bits in unused low positions */ #define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4) static const uint8_t iota_r_packed[24] = { H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00, H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09, H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a, H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03, H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08, }; #undef H static const uint32_t rho[6] = { 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832 }; static const uint32_t pi[6] = { 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916 }; #define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right #define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \ } while (0) #define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3))) #define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0) /* The permutation function. */ static void keccak_f1600(mbedtls_sha3_context *ctx) { uint64_t lane[5]; uint64_t *s = ctx->state; int i; for (int round = 0; round < 24; round++) { uint64_t t; /* Theta */ #if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names for (i = 0; i < 5; i++) { lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; } for (i = 0; i < 5; i++) { t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63); s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t; } #else lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; t = lane[4] ^ ROTR64(lane[1], 63); s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; t = lane[0] ^ ROTR64(lane[2], 63); s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; t = lane[1] ^ ROTR64(lane[3], 63); s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; t = lane[2] ^ ROTR64(lane[4], 63); s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; t = lane[3] ^ ROTR64(lane[0], 63); s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; #endif /* Rho */ for (i = 1; i < 25; i += 4) { uint32_t r = rho[(i - 1) >> 2]; #if MBEDTLS_SHA3_RHO_UNROLL == 0 for (int j = i; j < i + 4; j++) { uint8_t r8 = (uint8_t) (r >> 24); r <<= 8; s[j] = ROTR64(s[j], r8); } #else s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r)); s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r)); s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r)); s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r)); #endif } /* Pi */ t = s[1]; #if MBEDTLS_SHA3_PI_UNROLL == 0 for (i = 0; i < 24; i += 4) { uint32_t p = pi[i >> 2]; for (unsigned j = 0; j < 4; j++) { SWAP(s[p & 0xff], t); p >>= 8; } } #else uint32_t p = pi[0]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[1]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[2]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[3]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[4]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); p = pi[5]; SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); #endif /* Chi */ #if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names for (i = 0; i <= 20; i += 5) { lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2]; lane[3] = s[i + 3]; lane[4] = s[i + 4]; s[i + 0] ^= (~lane[1]) & lane[2]; s[i + 1] ^= (~lane[2]) & lane[3]; s[i + 2] ^= (~lane[3]) & lane[4]; s[i + 3] ^= (~lane[4]) & lane[0]; s[i + 4] ^= (~lane[0]) & lane[1]; } #else lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4]; s[0] ^= (~lane[1]) & lane[2]; s[1] ^= (~lane[2]) & lane[3]; s[2] ^= (~lane[3]) & lane[4]; s[3] ^= (~lane[4]) & lane[0]; s[4] ^= (~lane[0]) & lane[1]; lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9]; s[5] ^= (~lane[1]) & lane[2]; s[6] ^= (~lane[2]) & lane[3]; s[7] ^= (~lane[3]) & lane[4]; s[8] ^= (~lane[4]) & lane[0]; s[9] ^= (~lane[0]) & lane[1]; lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14]; s[10] ^= (~lane[1]) & lane[2]; s[11] ^= (~lane[2]) & lane[3]; s[12] ^= (~lane[3]) & lane[4]; s[13] ^= (~lane[4]) & lane[0]; s[14] ^= (~lane[0]) & lane[1]; lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19]; s[15] ^= (~lane[1]) & lane[2]; s[16] ^= (~lane[2]) & lane[3]; s[17] ^= (~lane[3]) & lane[4]; s[18] ^= (~lane[4]) & lane[0]; s[19] ^= (~lane[0]) & lane[1]; lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24]; s[20] ^= (~lane[1]) & lane[2]; s[21] ^= (~lane[2]) & lane[3]; s[22] ^= (~lane[3]) & lane[4]; s[23] ^= (~lane[4]) & lane[0]; s[24] ^= (~lane[0]) & lane[1]; #endif /* Iota */ /* Decompress the round masks (see definition of rc) */ s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 | (iota_r_packed[round] & 0x20ull) << 26 | (iota_r_packed[round] & 0x10ull) << 11 | (iota_r_packed[round] & 0x8f)); } } void mbedtls_sha3_init(mbedtls_sha3_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha3_context)); } void mbedtls_sha3_free(mbedtls_sha3_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context)); } void mbedtls_sha3_clone(mbedtls_sha3_context *dst, const mbedtls_sha3_context *src) { *dst = *src; } /* * SHA-3 context setup */ int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id) { switch (id) { case MBEDTLS_SHA3_224: ctx->olen = 224 / 8; ctx->max_block_size = 1152 / 8; break; case MBEDTLS_SHA3_256: ctx->olen = 256 / 8; ctx->max_block_size = 1088 / 8; break; case MBEDTLS_SHA3_384: ctx->olen = 384 / 8; ctx->max_block_size = 832 / 8; break; case MBEDTLS_SHA3_512: ctx->olen = 512 / 8; ctx->max_block_size = 576 / 8; break; default: return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; } memset(ctx->state, 0, sizeof(ctx->state)); ctx->index = 0; return 0; } /* * SHA-3 process buffer */ int mbedtls_sha3_update(mbedtls_sha3_context *ctx, const uint8_t *input, size_t ilen) { if (ilen >= 8) { // 8-byte align index int align_bytes = 8 - (ctx->index % 8); if (align_bytes) { for (; align_bytes > 0; align_bytes--) { ABSORB(ctx, ctx->index, *input++); ilen--; ctx->index++; } if ((ctx->index = ctx->index % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } // process input in 8-byte chunks while (ilen >= 8) { ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0)); input += 8; ilen -= 8; if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } } // handle remaining bytes while (ilen-- > 0) { ABSORB(ctx, ctx->index, *input++); if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } return 0; } int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, uint8_t *output, size_t olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Catch SHA-3 families, with fixed output length */ if (ctx->olen > 0) { if (ctx->olen > olen) { ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; goto exit; } olen = ctx->olen; } ABSORB(ctx, ctx->index, XOR_BYTE); ABSORB(ctx, ctx->max_block_size - 1, 0x80); keccak_f1600(ctx); ctx->index = 0; while (olen-- > 0) { *output++ = SQUEEZE(ctx, ctx->index); if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { keccak_f1600(ctx); } } ret = 0; exit: mbedtls_sha3_free(ctx); return ret; } /* * output = SHA-3( input buffer ) */ int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, size_t ilen, uint8_t *output, size_t olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha3_context ctx; mbedtls_sha3_init(&ctx); /* Sanity checks are performed in every mbedtls_sha3_xxx() */ if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) { goto exit; } if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) { goto exit; } exit: mbedtls_sha3_free(&ctx); return ret; } /**************** Self-tests ****************/ #if defined(MBEDTLS_SELF_TEST) static const unsigned char test_data[2][4] = { "", "abc", }; static const size_t test_data_len[2] = { 0, /* "" */ 3 /* "abc" */ }; static const unsigned char test_hash_sha3_224[2][28] = { { /* "" */ 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7, 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB, 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F, 0x5B, 0x5A, 0x6B, 0xC7 }, { /* "abc" */ 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A, 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F, 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD, 0x73, 0xB4, 0x6F, 0xDF } }; static const unsigned char test_hash_sha3_256[2][32] = { { /* "" */ 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66, 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62, 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA, 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A }, { /* "abc" */ 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2, 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD, 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B, 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32 } }; static const unsigned char test_hash_sha3_384[2][48] = { { /* "" */ 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D, 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85, 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61, 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A, 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47, 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04 }, { /* "abc" */ 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9, 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D, 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25, 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2, 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5, 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25 } }; static const unsigned char test_hash_sha3_512[2][64] = { { /* "" */ 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5, 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E, 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59, 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6, 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C, 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58, 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3, 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26 }, { /* "abc" */ 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A, 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E, 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D, 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E, 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9, 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40, 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5, 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0 } }; static const unsigned char long_kat_hash_sha3_224[28] = { 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E, 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C, 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7, 0xA7, 0xFD, 0x65, 0x3C }; static const unsigned char long_kat_hash_sha3_256[32] = { 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34, 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6, 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99, 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1 }; static const unsigned char long_kat_hash_sha3_384[48] = { 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53, 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD, 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E, 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84, 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42, 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40 }; static const unsigned char long_kat_hash_sha3_512[64] = { 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB, 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E, 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF, 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59, 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE, 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66, 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E, 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87 }; static int mbedtls_sha3_kat_test(int verbose, const char *type_name, mbedtls_sha3_id id, int test_num) { uint8_t hash[64]; int result; result = mbedtls_sha3(id, test_data[test_num], test_data_len[test_num], hash, sizeof(hash)); if (result != 0) { if (verbose != 0) { mbedtls_printf(" %s test %d error code: %d\n", type_name, test_num, result); } return result; } switch (id) { case MBEDTLS_SHA3_224: result = memcmp(hash, test_hash_sha3_224[test_num], 28); break; case MBEDTLS_SHA3_256: result = memcmp(hash, test_hash_sha3_256[test_num], 32); break; case MBEDTLS_SHA3_384: result = memcmp(hash, test_hash_sha3_384[test_num], 48); break; case MBEDTLS_SHA3_512: result = memcmp(hash, test_hash_sha3_512[test_num], 64); break; default: break; } if (0 != result) { if (verbose != 0) { mbedtls_printf(" %s test %d failed\n", type_name, test_num); } return -1; } if (verbose != 0) { mbedtls_printf(" %s test %d passed\n", type_name, test_num); } return 0; } static int mbedtls_sha3_long_kat_test(int verbose, const char *type_name, mbedtls_sha3_id id) { mbedtls_sha3_context ctx; unsigned char buffer[1000]; unsigned char hash[64]; int result = 0; memset(buffer, 'a', 1000); if (verbose != 0) { mbedtls_printf(" %s long KAT test ", type_name); } mbedtls_sha3_init(&ctx); result = mbedtls_sha3_starts(&ctx, id); if (result != 0) { if (verbose != 0) { mbedtls_printf("setup failed\n "); } } /* Process 1,000,000 (one million) 'a' characters */ for (int i = 0; i < 1000; i++) { result = mbedtls_sha3_update(&ctx, buffer, 1000); if (result != 0) { if (verbose != 0) { mbedtls_printf("update error code: %i\n", result); } goto cleanup; } } result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash)); if (result != 0) { if (verbose != 0) { mbedtls_printf("finish error code: %d\n", result); } goto cleanup; } switch (id) { case MBEDTLS_SHA3_224: result = memcmp(hash, long_kat_hash_sha3_224, 28); break; case MBEDTLS_SHA3_256: result = memcmp(hash, long_kat_hash_sha3_256, 32); break; case MBEDTLS_SHA3_384: result = memcmp(hash, long_kat_hash_sha3_384, 48); break; case MBEDTLS_SHA3_512: result = memcmp(hash, long_kat_hash_sha3_512, 64); break; default: break; } if (result != 0) { if (verbose != 0) { mbedtls_printf("failed\n"); } } if (verbose != 0) { mbedtls_printf("passed\n"); } cleanup: mbedtls_sha3_free(&ctx); return result; } int mbedtls_sha3_self_test(int verbose) { int i; /* SHA-3 Known Answer Tests (KAT) */ for (i = 0; i < 2; i++) { if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-224", MBEDTLS_SHA3_224, i)) { return 1; } if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-256", MBEDTLS_SHA3_256, i)) { return 1; } if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-384", MBEDTLS_SHA3_384, i)) { return 1; } if (0 != mbedtls_sha3_kat_test(verbose, "SHA3-512", MBEDTLS_SHA3_512, i)) { return 1; } } /* SHA-3 long KAT tests */ if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-224", MBEDTLS_SHA3_224)) { return 1; } if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-256", MBEDTLS_SHA3_256)) { return 1; } if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-384", MBEDTLS_SHA3_384)) { return 1; } if (0 != mbedtls_sha3_long_kat_test(verbose, "SHA3-512", MBEDTLS_SHA3_512)) { return 1; } if (verbose != 0) { mbedtls_printf("\n"); } return 0; } #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA3_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/sha512.c000066400000000000000000001112071464416617300225050ustar00rootroot00000000000000/* * FIPS-180-2 compliant SHA-384/512 implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The SHA-512 Secure Hash Standard was published by NIST in 2002. * * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ #if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \ defined(__clang__) && __clang_major__ >= 7 /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. * * The intrinsic declaration are guarded by predefined ACLE macros in clang: * these are normally only enabled by the -march option on the command line. * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_SHA512 1 #define MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG #endif #include "common.h" #if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C) #include "mbedtls/sha512.h" #include "mbedtls/platform_util.h" #include "mbedtls/error.h" #if defined(_MSC_VER) || defined(__WATCOMC__) #define UL64(x) x##ui64 #else #define UL64(x) x##ULL #endif #include #include "mbedtls/platform.h" #if defined(__aarch64__) # if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) /* *INDENT-OFF* */ # if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) # error "Target does not support NEON instructions" # endif /* * Best performance comes from most recent compilers, with intrinsics and -O3. * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12). * * GCC < 8 won't work at all (lacks the sha512 instructions) * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512 * * Clang < 7 won't work at all (lacks the sha512 instructions) * Clang 7-12 don't have intrinsics (but we work around that with inline * assembler) or __ARM_FEATURE_SHA512 * Clang == 13.0.0 same as clang 12 (only seen on macOS) * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics */ # if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG) /* Test Clang first, as it defines __GNUC__ */ # if defined(__ARMCOMPILER_VERSION) # if __ARMCOMPILER_VERSION < 6090000 # error "A more recent armclang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # elif __ARMCOMPILER_VERSION == 6090000 # error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # else # pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # endif # elif defined(__clang__) # if __clang_major__ < 7 # error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # else # pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function) # define MBEDTLS_POP_TARGET_PRAGMA # endif # elif defined(__GNUC__) # if __GNUC__ < 8 # error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # else # pragma GCC push_options # pragma GCC target ("arch=armv8.2-a+sha3") # define MBEDTLS_POP_TARGET_PRAGMA # endif # else # error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*" # endif # endif /* *INDENT-ON* */ # endif # if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) # if defined(__unix__) # if defined(__linux__) /* Our preferred method of detection is getauxval() */ # include # if !defined(HWCAP_SHA512) /* The same header that declares getauxval() should provide the HWCAP_xxx * constants to analyze its return value. However, the libc may be too * old to have the constant that we need. So if it's missing, assume that * the value is the same one used by the Linux kernel ABI. */ # define HWCAP_SHA512 (1 << 21) # endif # endif /* Use SIGILL on Unix, and fall back to it on Linux */ # include # endif # endif #elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) # undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY # undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) /* * Capability detection code comes early, so we can disable * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found */ #if defined(HWCAP_SHA512) static int mbedtls_a64_crypto_sha512_determine_support(void) { return (getauxval(AT_HWCAP) & HWCAP_SHA512) ? 1 : 0; } #elif defined(__APPLE__) #include #include static int mbedtls_a64_crypto_sha512_determine_support(void) { int value = 0; size_t value_len = sizeof(value); int ret = sysctlbyname("hw.optional.armv8_2_sha512", &value, &value_len, NULL, 0); return ret == 0 && value != 0; } #elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) /* * As of March 2022, there don't appear to be any PF_ARM_V8_* flags * available to pass to IsProcessorFeaturePresent() to check for * SHA-512 support. So we fall back to the C code only. */ #if defined(_MSC_VER) #pragma message "No mechanism to detect A64_CRYPTO found, using C code only" #else #warning "No mechanism to detect A64_CRYPTO found, using C code only" #endif #elif defined(__unix__) && defined(SIG_SETMASK) /* Detection with SIGILL, setjmp() and longjmp() */ #include #include static jmp_buf return_from_sigill; /* * A64 SHA512 support detection via SIGILL */ static void sigill_handler(int signal) { (void) signal; longjmp(return_from_sigill, 1); } static int mbedtls_a64_crypto_sha512_determine_support(void) { struct sigaction old_action, new_action; sigset_t old_mask; if (sigprocmask(0, NULL, &old_mask)) { return 0; } sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; new_action.sa_handler = sigill_handler; sigaction(SIGILL, &new_action, &old_action); static int ret = 0; if (setjmp(return_from_sigill) == 0) { /* First return only */ /* If this traps, we will return a second time from setjmp() with 1 */ asm ("sha512h q0, q0, v0.2d" : : : "v0"); ret = 1; } sigaction(SIGILL, &old_action, NULL); sigprocmask(SIG_SETMASK, &old_mask, NULL); return ret; } #else #warning "No mechanism to detect A64_CRYPTO found, using C code only" #undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT #endif /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */ #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ #if !defined(MBEDTLS_SHA512_ALT) #define SHA512_BLOCK_SIZE 128 #if defined(MBEDTLS_SHA512_SMALLER) static void sha512_put_uint64_be(uint64_t n, unsigned char *b, uint8_t i) { MBEDTLS_PUT_UINT64_BE(n, b, i); } #else #define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE #endif /* MBEDTLS_SHA512_SMALLER */ void mbedtls_sha512_init(mbedtls_sha512_context *ctx) { memset(ctx, 0, sizeof(mbedtls_sha512_context)); } void mbedtls_sha512_free(mbedtls_sha512_context *ctx) { if (ctx == NULL) { return; } mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha512_context)); } void mbedtls_sha512_clone(mbedtls_sha512_context *dst, const mbedtls_sha512_context *src) { *dst = *src; } /* * SHA-512 context setup */ int mbedtls_sha512_starts(mbedtls_sha512_context *ctx, int is384) { #if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) if (is384 != 0 && is384 != 1) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA512_C) if (is384 != 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA384_C only */ if (is384 == 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #endif ctx->total[0] = 0; ctx->total[1] = 0; if (is384 == 0) { #if defined(MBEDTLS_SHA512_C) ctx->state[0] = UL64(0x6A09E667F3BCC908); ctx->state[1] = UL64(0xBB67AE8584CAA73B); ctx->state[2] = UL64(0x3C6EF372FE94F82B); ctx->state[3] = UL64(0xA54FF53A5F1D36F1); ctx->state[4] = UL64(0x510E527FADE682D1); ctx->state[5] = UL64(0x9B05688C2B3E6C1F); ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); ctx->state[7] = UL64(0x5BE0CD19137E2179); #endif /* MBEDTLS_SHA512_C */ } else { #if defined(MBEDTLS_SHA384_C) ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); ctx->state[1] = UL64(0x629A292A367CD507); ctx->state[2] = UL64(0x9159015A3070DD17); ctx->state[3] = UL64(0x152FECD8F70E5939); ctx->state[4] = UL64(0x67332667FFC00B31); ctx->state[5] = UL64(0x8EB44A8768581511); ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); ctx->state[7] = UL64(0x47B5481DBEFA4FA4); #endif /* MBEDTLS_SHA384_C */ } #if defined(MBEDTLS_SHA384_C) ctx->is384 = is384; #endif return 0; } #if !defined(MBEDTLS_SHA512_PROCESS_ALT) /* * Round constants */ static const uint64_t K[80] = { UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) }; #endif #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) # define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many # define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process #endif /* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY, * under the MIT licence; dual-licensed as Apache 2 with his kind permission. */ #if defined(__clang__) && \ (__clang_major__ < 13 || \ (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0)) static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y) { asm ("sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y)); return x; } static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) { asm ("sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z)); return x; } static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) { asm ("sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); return x; } static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z) { asm ("sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z)); return x; } #endif /* __clang__ etc */ static size_t mbedtls_internal_sha512_process_many_a64_crypto( mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len) { uint64x2_t ab = vld1q_u64(&ctx->state[0]); uint64x2_t cd = vld1q_u64(&ctx->state[2]); uint64x2_t ef = vld1q_u64(&ctx->state[4]); uint64x2_t gh = vld1q_u64(&ctx->state[6]); size_t processed = 0; for (; len >= SHA512_BLOCK_SIZE; processed += SHA512_BLOCK_SIZE, msg += SHA512_BLOCK_SIZE, len -= SHA512_BLOCK_SIZE) { uint64x2_t initial_sum, sum, intermed; uint64x2_t ab_orig = ab; uint64x2_t cd_orig = cd; uint64x2_t ef_orig = ef; uint64x2_t gh_orig = gh; uint64x2_t s0 = (uint64x2_t) vld1q_u8(msg + 16 * 0); uint64x2_t s1 = (uint64x2_t) vld1q_u8(msg + 16 * 1); uint64x2_t s2 = (uint64x2_t) vld1q_u8(msg + 16 * 2); uint64x2_t s3 = (uint64x2_t) vld1q_u8(msg + 16 * 3); uint64x2_t s4 = (uint64x2_t) vld1q_u8(msg + 16 * 4); uint64x2_t s5 = (uint64x2_t) vld1q_u8(msg + 16 * 5); uint64x2_t s6 = (uint64x2_t) vld1q_u8(msg + 16 * 6); uint64x2_t s7 = (uint64x2_t) vld1q_u8(msg + 16 * 7); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */ s0 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s0))); s1 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s1))); s2 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s2))); s3 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s3))); s4 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s4))); s5 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s5))); s6 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s6))); s7 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(s7))); #endif /* Rounds 0 and 1 */ initial_sum = vaddq_u64(s0, vld1q_u64(&K[0])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds 2 and 3 */ initial_sum = vaddq_u64(s1, vld1q_u64(&K[2])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds 4 and 5 */ initial_sum = vaddq_u64(s2, vld1q_u64(&K[4])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds 6 and 7 */ initial_sum = vaddq_u64(s3, vld1q_u64(&K[6])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); /* Rounds 8 and 9 */ initial_sum = vaddq_u64(s4, vld1q_u64(&K[8])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds 10 and 11 */ initial_sum = vaddq_u64(s5, vld1q_u64(&K[10])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds 12 and 13 */ initial_sum = vaddq_u64(s6, vld1q_u64(&K[12])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds 14 and 15 */ initial_sum = vaddq_u64(s7, vld1q_u64(&K[14])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); for (unsigned int t = 16; t < 80; t += 16) { /* Rounds t and t + 1 */ s0 = vsha512su1q_u64(vsha512su0q_u64(s0, s1), s7, vextq_u64(s4, s5, 1)); initial_sum = vaddq_u64(s0, vld1q_u64(&K[t])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds t + 2 and t + 3 */ s1 = vsha512su1q_u64(vsha512su0q_u64(s1, s2), s0, vextq_u64(s5, s6, 1)); initial_sum = vaddq_u64(s1, vld1q_u64(&K[t + 2])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds t + 4 and t + 5 */ s2 = vsha512su1q_u64(vsha512su0q_u64(s2, s3), s1, vextq_u64(s6, s7, 1)); initial_sum = vaddq_u64(s2, vld1q_u64(&K[t + 4])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds t + 6 and t + 7 */ s3 = vsha512su1q_u64(vsha512su0q_u64(s3, s4), s2, vextq_u64(s7, s0, 1)); initial_sum = vaddq_u64(s3, vld1q_u64(&K[t + 6])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); /* Rounds t + 8 and t + 9 */ s4 = vsha512su1q_u64(vsha512su0q_u64(s4, s5), s3, vextq_u64(s0, s1, 1)); initial_sum = vaddq_u64(s4, vld1q_u64(&K[t + 8])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), gh); intermed = vsha512hq_u64(sum, vextq_u64(ef, gh, 1), vextq_u64(cd, ef, 1)); gh = vsha512h2q_u64(intermed, cd, ab); cd = vaddq_u64(cd, intermed); /* Rounds t + 10 and t + 11 */ s5 = vsha512su1q_u64(vsha512su0q_u64(s5, s6), s4, vextq_u64(s1, s2, 1)); initial_sum = vaddq_u64(s5, vld1q_u64(&K[t + 10])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ef); intermed = vsha512hq_u64(sum, vextq_u64(cd, ef, 1), vextq_u64(ab, cd, 1)); ef = vsha512h2q_u64(intermed, ab, gh); ab = vaddq_u64(ab, intermed); /* Rounds t + 12 and t + 13 */ s6 = vsha512su1q_u64(vsha512su0q_u64(s6, s7), s5, vextq_u64(s2, s3, 1)); initial_sum = vaddq_u64(s6, vld1q_u64(&K[t + 12])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), cd); intermed = vsha512hq_u64(sum, vextq_u64(ab, cd, 1), vextq_u64(gh, ab, 1)); cd = vsha512h2q_u64(intermed, gh, ef); gh = vaddq_u64(gh, intermed); /* Rounds t + 14 and t + 15 */ s7 = vsha512su1q_u64(vsha512su0q_u64(s7, s0), s6, vextq_u64(s3, s4, 1)); initial_sum = vaddq_u64(s7, vld1q_u64(&K[t + 14])); sum = vaddq_u64(vextq_u64(initial_sum, initial_sum, 1), ab); intermed = vsha512hq_u64(sum, vextq_u64(gh, ab, 1), vextq_u64(ef, gh, 1)); ab = vsha512h2q_u64(intermed, ef, cd); ef = vaddq_u64(ef, intermed); } ab = vaddq_u64(ab, ab_orig); cd = vaddq_u64(cd, cd_orig); ef = vaddq_u64(ef, ef_orig); gh = vaddq_u64(gh, gh_orig); } vst1q_u64(&ctx->state[0], ab); vst1q_u64(&ctx->state[2], cd); vst1q_u64(&ctx->state[4], ef); vst1q_u64(&ctx->state[6], gh); return processed; } #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and A64 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() */ static #endif int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_SIZE]) { return (mbedtls_internal_sha512_process_many_a64_crypto(ctx, data, SHA512_BLOCK_SIZE) == SHA512_BLOCK_SIZE) ? 0 : -1; } #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_POP_TARGET_PRAGMA) #if defined(__clang__) #pragma clang attribute pop #elif defined(__GNUC__) #pragma GCC pop_options #endif #undef MBEDTLS_POP_TARGET_PRAGMA #endif #if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) #define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many #define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process #endif #if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) /* * This function is for internal use only if we are building both C and A64 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process() */ static #endif int mbedtls_internal_sha512_process_c(mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_SIZE]) { int i; struct { uint64_t temp1, temp2, W[80]; uint64_t A[8]; } local; #define SHR(x, n) ((x) >> (n)) #define ROTR(x, n) (SHR((x), (n)) | ((x) << (64 - (n)))) #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) #define S1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6)) #define S2(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39)) #define S3(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41)) #define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y)))) #define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) #define P(a, b, c, d, e, f, g, h, x, K) \ do \ { \ local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \ local.temp2 = S2(a) + F0((a), (b), (c)); \ (d) += local.temp1; (h) = local.temp1 + local.temp2; \ } while (0) for (i = 0; i < 8; i++) { local.A[i] = ctx->state[i]; } #if defined(MBEDTLS_SHA512_SMALLER) for (i = 0; i < 80; i++) { if (i < 16) { local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3); } else { local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + S0(local.W[i - 15]) + local.W[i - 16]; } P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i]); local.temp1 = local.A[7]; local.A[7] = local.A[6]; local.A[6] = local.A[5]; local.A[5] = local.A[4]; local.A[4] = local.A[3]; local.A[3] = local.A[2]; local.A[2] = local.A[1]; local.A[1] = local.A[0]; local.A[0] = local.temp1; } #else /* MBEDTLS_SHA512_SMALLER */ for (i = 0; i < 16; i++) { local.W[i] = MBEDTLS_GET_UINT64_BE(data, i << 3); } for (; i < 80; i++) { local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + S0(local.W[i - 15]) + local.W[i - 16]; } i = 0; do { P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i]); i++; P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.W[i], K[i]); i++; P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.W[i], K[i]); i++; P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.W[i], K[i]); i++; P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.W[i], K[i]); i++; P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.W[i], K[i]); i++; P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.W[i], K[i]); i++; P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.W[i], K[i]); i++; } while (i < 80); #endif /* MBEDTLS_SHA512_SMALLER */ for (i = 0; i < 8; i++) { ctx->state[i] += local.A[i]; } /* Zeroise buffers and variables to clear sensitive data from memory. */ mbedtls_platform_zeroize(&local, sizeof(local)); return 0; } #endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) static size_t mbedtls_internal_sha512_process_many_c( mbedtls_sha512_context *ctx, const uint8_t *data, size_t len) { size_t processed = 0; while (len >= SHA512_BLOCK_SIZE) { if (mbedtls_internal_sha512_process_c(ctx, data) != 0) { return 0; } data += SHA512_BLOCK_SIZE; len -= SHA512_BLOCK_SIZE; processed += SHA512_BLOCK_SIZE; } return processed; } #endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) static int mbedtls_a64_crypto_sha512_has_support(void) { static int done = 0; static int supported = 0; if (!done) { supported = mbedtls_a64_crypto_sha512_determine_support(); done = 1; } return supported; } static size_t mbedtls_internal_sha512_process_many(mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len) { if (mbedtls_a64_crypto_sha512_has_support()) { return mbedtls_internal_sha512_process_many_a64_crypto(ctx, msg, len); } else { return mbedtls_internal_sha512_process_many_c(ctx, msg, len); } } int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned char data[SHA512_BLOCK_SIZE]) { if (mbedtls_a64_crypto_sha512_has_support()) { return mbedtls_internal_sha512_process_a64_crypto(ctx, data); } else { return mbedtls_internal_sha512_process_c(ctx, data); } } #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ /* * SHA-512 process buffer */ int mbedtls_sha512_update(mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t fill; unsigned int left; if (ilen == 0) { return 0; } left = (unsigned int) (ctx->total[0] & 0x7F); fill = SHA512_BLOCK_SIZE - left; ctx->total[0] += (uint64_t) ilen; if (ctx->total[0] < (uint64_t) ilen) { ctx->total[1]++; } if (left && ilen >= fill) { memcpy((void *) (ctx->buffer + left), input, fill); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { return ret; } input += fill; ilen -= fill; left = 0; } while (ilen >= SHA512_BLOCK_SIZE) { size_t processed = mbedtls_internal_sha512_process_many(ctx, input, ilen); if (processed < SHA512_BLOCK_SIZE) { return MBEDTLS_ERR_ERROR_GENERIC_ERROR; } input += processed; ilen -= processed; } if (ilen > 0) { memcpy((void *) (ctx->buffer + left), input, ilen); } return 0; } /* * SHA-512 final digest */ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx, unsigned char *output) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned used; uint64_t high, low; int truncated = 0; /* * Add padding: 0x80 then 0x00 until 16 bytes remain for the length */ used = ctx->total[0] & 0x7F; ctx->buffer[used++] = 0x80; if (used <= 112) { /* Enough room for padding + length in current block */ memset(ctx->buffer + used, 0, 112 - used); } else { /* We'll need an extra block */ memset(ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { goto exit; } memset(ctx->buffer, 0, 112); } /* * Add message length */ high = (ctx->total[0] >> 61) | (ctx->total[1] << 3); low = (ctx->total[0] << 3); sha512_put_uint64_be(high, ctx->buffer, 112); sha512_put_uint64_be(low, ctx->buffer, 120); if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) { goto exit; } /* * Output final state */ sha512_put_uint64_be(ctx->state[0], output, 0); sha512_put_uint64_be(ctx->state[1], output, 8); sha512_put_uint64_be(ctx->state[2], output, 16); sha512_put_uint64_be(ctx->state[3], output, 24); sha512_put_uint64_be(ctx->state[4], output, 32); sha512_put_uint64_be(ctx->state[5], output, 40); #if defined(MBEDTLS_SHA384_C) truncated = ctx->is384; #endif if (!truncated) { sha512_put_uint64_be(ctx->state[6], output, 48); sha512_put_uint64_be(ctx->state[7], output, 56); } ret = 0; exit: mbedtls_sha512_free(ctx); return ret; } #endif /* !MBEDTLS_SHA512_ALT */ /* * output = SHA-512( input buffer ) */ int mbedtls_sha512(const unsigned char *input, size_t ilen, unsigned char *output, int is384) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_sha512_context ctx; #if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) if (is384 != 0 && is384 != 1) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #elif defined(MBEDTLS_SHA512_C) if (is384 != 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #else /* defined MBEDTLS_SHA384_C only */ if (is384 == 0) { return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA; } #endif mbedtls_sha512_init(&ctx); if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { goto exit; } if ((ret = mbedtls_sha512_update(&ctx, input, ilen)) != 0) { goto exit; } if ((ret = mbedtls_sha512_finish(&ctx, output)) != 0) { goto exit; } exit: mbedtls_sha512_free(&ctx); return ret; } #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors */ static const unsigned char sha_test_buf[3][113] = { { "abc" }, { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, { "" } }; static const size_t sha_test_buflen[3] = { 3, 112, 1000 }; typedef const unsigned char (sha_test_sum_t)[64]; /* * SHA-384 test vectors */ #if defined(MBEDTLS_SHA384_C) static sha_test_sum_t sha384_test_sum[] = { { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 } }; #endif /* MBEDTLS_SHA384_C */ /* * SHA-512 test vectors */ #if defined(MBEDTLS_SHA512_C) static sha_test_sum_t sha512_test_sum[] = { { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } }; #endif /* MBEDTLS_SHA512_C */ static int mbedtls_sha512_common_self_test(int verbose, int is384) { int i, buflen, ret = 0; unsigned char *buf; unsigned char sha512sum[64]; mbedtls_sha512_context ctx; #if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C) sha_test_sum_t *sha_test_sum = (is384) ? sha384_test_sum : sha512_test_sum; #elif defined(MBEDTLS_SHA512_C) sha_test_sum_t *sha_test_sum = sha512_test_sum; #else sha_test_sum_t *sha_test_sum = sha384_test_sum; #endif buf = mbedtls_calloc(1024, sizeof(unsigned char)); if (NULL == buf) { if (verbose != 0) { mbedtls_printf("Buffer allocation failed\n"); } return 1; } mbedtls_sha512_init(&ctx); for (i = 0; i < 3; i++) { if (verbose != 0) { mbedtls_printf(" SHA-%d test #%d: ", 512 - is384 * 128, i + 1); } if ((ret = mbedtls_sha512_starts(&ctx, is384)) != 0) { goto fail; } if (i == 2) { memset(buf, 'a', buflen = 1000); for (int j = 0; j < 1000; j++) { ret = mbedtls_sha512_update(&ctx, buf, buflen); if (ret != 0) { goto fail; } } } else { ret = mbedtls_sha512_update(&ctx, sha_test_buf[i], sha_test_buflen[i]); if (ret != 0) { goto fail; } } if ((ret = mbedtls_sha512_finish(&ctx, sha512sum)) != 0) { goto fail; } if (memcmp(sha512sum, sha_test_sum[i], 64 - is384 * 16) != 0) { ret = 1; goto fail; } if (verbose != 0) { mbedtls_printf("passed\n"); } } if (verbose != 0) { mbedtls_printf("\n"); } goto exit; fail: if (verbose != 0) { mbedtls_printf("failed\n"); } exit: mbedtls_sha512_free(&ctx); mbedtls_free(buf); return ret; } #if defined(MBEDTLS_SHA512_C) int mbedtls_sha512_self_test(int verbose) { return mbedtls_sha512_common_self_test(verbose, 0); } #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_SHA384_C) int mbedtls_sha384_self_test(int verbose) { return mbedtls_sha512_common_self_test(verbose, 1); } #endif /* MBEDTLS_SHA384_C */ #undef ARRAY_LENGTH #endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_cache.c000066400000000000000000000251021464416617300234240ustar00rootroot00000000000000/* * SSL session cache implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * These session callbacks use a simple chained list * to store and retrieve the session information. */ #include "common.h" #if defined(MBEDTLS_SSL_CACHE_C) #include "mbedtls/platform.h" #include "mbedtls/ssl_cache.h" #include "ssl_misc.h" #include "mbedtls/error.h" #include void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache) { memset(cache, 0, sizeof(mbedtls_ssl_cache_context)); cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&cache->mutex); #endif } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_cache_entry **dst) { int ret = MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND; #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t = mbedtls_time(NULL); #endif mbedtls_ssl_cache_entry *cur; for (cur = cache->chain; cur != NULL; cur = cur->next) { #if defined(MBEDTLS_HAVE_TIME) if (cache->timeout != 0 && (int) (t - cur->timestamp) > cache->timeout) { continue; } #endif if (session_id_len != cur->session_id_len || memcmp(session_id, cur->session_id, cur->session_id_len) != 0) { continue; } break; } if (cur != NULL) { *dst = cur; ret = 0; } return ret; } int mbedtls_ssl_cache_get(void *data, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_entry *entry; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { return ret; } #endif ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); if (ret != 0) { goto exit; } ret = mbedtls_ssl_session_load(session, entry->session, entry->session_len); if (ret != 0) { goto exit; } ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* zeroize a cache entry */ static void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry) { if (entry == NULL) { return; } /* zeroize and free session structure */ if (entry->session != NULL) { mbedtls_zeroize_and_free(entry->session, entry->session_len); } /* zeroize the whole entry structure */ mbedtls_platform_zeroize(entry, sizeof(mbedtls_ssl_cache_entry)); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache, unsigned char const *session_id, size_t session_id_len, mbedtls_ssl_cache_entry **dst) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t = mbedtls_time(NULL), oldest = 0; #endif /* MBEDTLS_HAVE_TIME */ mbedtls_ssl_cache_entry *old = NULL; int count = 0; mbedtls_ssl_cache_entry *cur, *last; /* Check 1: Is there already an entry with the given session ID? * * If yes, overwrite it. * * If not, `count` will hold the size of the session cache * at the end of this loop, and `last` will point to the last * entry, both of which will be used later. */ last = NULL; for (cur = cache->chain; cur != NULL; cur = cur->next) { count++; if (session_id_len == cur->session_id_len && memcmp(session_id, cur->session_id, cur->session_id_len) == 0) { goto found; } last = cur; } /* Check 2: Is there an outdated entry in the cache? * * If so, overwrite it. * * If not, remember the oldest entry in `old` for later. */ #if defined(MBEDTLS_HAVE_TIME) for (cur = cache->chain; cur != NULL; cur = cur->next) { if (cache->timeout != 0 && (int) (t - cur->timestamp) > cache->timeout) { goto found; } if (oldest == 0 || cur->timestamp < oldest) { oldest = cur->timestamp; old = cur; } } #endif /* MBEDTLS_HAVE_TIME */ /* Check 3: Is there free space in the cache? */ if (count < cache->max_entries) { /* Create new entry */ cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry)); if (cur == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* Append to the end of the linked list. */ if (last == NULL) { cache->chain = cur; } else { last->next = cur; } goto found; } /* Last resort: The cache is full and doesn't contain any outdated * elements. In this case, we evict the oldest one, judged by timestamp * (if present) or cache-order. */ #if defined(MBEDTLS_HAVE_TIME) if (old == NULL) { /* This should only happen on an ill-configured cache * with max_entries == 0. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* MBEDTLS_HAVE_TIME */ /* Reuse first entry in chain, but move to last place. */ if (cache->chain == NULL) { /* This should never happen */ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } old = cache->chain; cache->chain = old->next; old->next = NULL; last->next = old; #endif /* MBEDTLS_HAVE_TIME */ /* Now `old` points to the oldest entry to be overwritten. */ cur = old; found: /* If we're reusing an entry, free it first. */ if (cur->session != NULL) { /* `ssl_cache_entry_zeroize` would break the chain, * so we reuse `old` to record `next` temporarily. */ old = cur->next; ssl_cache_entry_zeroize(cur); cur->next = old; } #if defined(MBEDTLS_HAVE_TIME) cur->timestamp = t; #endif *dst = cur; return 0; } int mbedtls_ssl_cache_set(void *data, unsigned char const *session_id, size_t session_id_len, const mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_entry *cur; size_t session_serialized_len = 0; unsigned char *session_serialized = NULL; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { return ret; } #endif ret = ssl_cache_pick_writing_slot(cache, session_id, session_id_len, &cur); if (ret != 0) { goto exit; } /* Check how much space we need to serialize the session * and allocate a sufficiently large buffer. */ ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len); if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { goto exit; } session_serialized = mbedtls_calloc(1, session_serialized_len); if (session_serialized == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } /* Now serialize the session into the allocated buffer. */ ret = mbedtls_ssl_session_save(session, session_serialized, session_serialized_len, &session_serialized_len); if (ret != 0) { goto exit; } if (session_id_len > sizeof(cur->session_id)) { ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; goto exit; } cur->session_id_len = session_id_len; memcpy(cur->session_id, session_id, session_id_len); cur->session = session_serialized; cur->session_len = session_serialized_len; session_serialized = NULL; ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif if (session_serialized != NULL) { mbedtls_zeroize_and_free(session_serialized, session_serialized_len); session_serialized = NULL; } return ret; } int mbedtls_ssl_cache_remove(void *data, unsigned char const *session_id, size_t session_id_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; mbedtls_ssl_cache_entry *entry; mbedtls_ssl_cache_entry *prev; #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&cache->mutex)) != 0) { return ret; } #endif ret = ssl_cache_find_entry(cache, session_id, session_id_len, &entry); /* No valid entry found, exit with success */ if (ret != 0) { ret = 0; goto exit; } /* Now we remove the entry from the chain */ if (entry == cache->chain) { cache->chain = entry->next; goto free; } for (prev = cache->chain; prev->next != NULL; prev = prev->next) { if (prev->next == entry) { prev->next = entry->next; break; } } free: ssl_cache_entry_zeroize(entry); mbedtls_free(entry); ret = 0; exit: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&cache->mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } #if defined(MBEDTLS_HAVE_TIME) void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout) { if (timeout < 0) { timeout = 0; } cache->timeout = timeout; } #endif /* MBEDTLS_HAVE_TIME */ void mbedtls_ssl_cache_set_max_entries(mbedtls_ssl_cache_context *cache, int max) { if (max < 0) { max = 0; } cache->max_entries = max; } void mbedtls_ssl_cache_free(mbedtls_ssl_cache_context *cache) { mbedtls_ssl_cache_entry *cur, *prv; cur = cache->chain; while (cur != NULL) { prv = cur; cur = cur->next; ssl_cache_entry_zeroize(prv); mbedtls_free(prv); } #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&cache->mutex); #endif cache->chain = NULL; } #endif /* MBEDTLS_SSL_CACHE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c000066400000000000000000002476031464416617300251040ustar00rootroot00000000000000/** * \file ssl_ciphersuites.c * * \brief SSL ciphersuites for Mbed TLS * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/platform.h" #include "mbedtls/ssl_ciphersuites.h" #include "mbedtls/ssl.h" #include "ssl_misc.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" #endif #include /* * Ordered from most preferred to least preferred in terms of security. * * Current rule (except weak and null which come last): * 1. By key exchange: * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK * 2. By key length and cipher: * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 * 4. By hash function used when relevant * 5. By key exchange/auth again: EC > non-EC */ static const int ciphersuite_preference[] = { #if defined(MBEDTLS_SSL_CIPHERSUITES) MBEDTLS_SSL_CIPHERSUITES, #else #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* TLS 1.3 ciphersuites */ MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS1_3_AES_256_GCM_SHA384, MBEDTLS_TLS1_3_AES_128_GCM_SHA256, MBEDTLS_TLS1_3_AES_128_CCM_SHA256, MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* Chacha-Poly ephemeral suites */ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* All AES-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, /* All CAMELLIA-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, /* All ARIA-256 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, /* All AES-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, /* All CAMELLIA-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, /* All ARIA-128 ephemeral suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, /* The PSK ephemeral suites */ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, /* The ECJPAKE suite */ MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, /* All AES-256 suites */ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_WITH_AES_256_CCM, MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, /* All CAMELLIA-256 suites */ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, /* All ARIA-256 suites */ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, /* All AES-128 suites */ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_AES_128_CCM, MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, /* All CAMELLIA-128 suites */ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, /* All ARIA-128 suites */ MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, /* The RSA PSK suites */ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, /* The PSK suites */ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM, MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, /* NULL suites */ MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, MBEDTLS_TLS_RSA_WITH_NULL_SHA256, MBEDTLS_TLS_RSA_WITH_NULL_SHA, MBEDTLS_TLS_RSA_WITH_NULL_MD5, MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, MBEDTLS_TLS_PSK_WITH_NULL_SHA384, MBEDTLS_TLS_PSK_WITH_NULL_SHA256, MBEDTLS_TLS_PSK_WITH_NULL_SHA, #endif /* MBEDTLS_SSL_CIPHERSUITES */ 0 }; static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CCM) && defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, "TLS1-3-AES-128-CCM-8-SHA256", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, "TLS1-3-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ 0, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 }, #endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && \ defined(MBEDTLS_MD_CAN_SHA256) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA384) && \ defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA384) && \ defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_MD_CAN_SHA1) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_SSL_HAVE_CBC) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #endif /* MBEDTLS_SSL_HAVE_AES */ #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) #if defined(MBEDTLS_SSL_HAVE_CBC) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_CBC */ #if defined(MBEDTLS_SSL_HAVE_GCM) #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_SSL_HAVE_GCM */ #endif /* MBEDTLS_SSL_HAVE_CAMELLIA */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_SSL_HAVE_AES) #if defined(MBEDTLS_SSL_HAVE_CCM) { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, MBEDTLS_CIPHERSUITE_SHORT_TAG, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_SSL_HAVE_CCM */ #endif /* MBEDTLS_SSL_HAVE_AES */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) #if defined(MBEDTLS_MD_CAN_MD5) { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_MD_CAN_SHA1) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA1 */ #if defined(MBEDTLS_MD_CAN_SHA256) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if defined(MBEDTLS_MD_CAN_SHA384) { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, MBEDTLS_CIPHERSUITE_WEAK, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif /* MBEDTLS_MD_CAN_SHA384 */ #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #if defined(MBEDTLS_SSL_HAVE_ARIA) #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA384)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #if (defined(MBEDTLS_SSL_HAVE_CBC) && \ defined(MBEDTLS_MD_CAN_SHA256)) { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, 0, MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 }, #endif #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #endif /* MBEDTLS_SSL_HAVE_ARIA */ { 0, "", MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, 0, 0, 0 } }; #if defined(MBEDTLS_SSL_CIPHERSUITES) const int *mbedtls_ssl_list_ciphersuites(void) { return ciphersuite_preference; } #else #define MAX_CIPHERSUITES sizeof(ciphersuite_definitions) / \ sizeof(ciphersuite_definitions[0]) static int supported_ciphersuites[MAX_CIPHERSUITES]; static int supported_init = 0; MBEDTLS_CHECK_RETURN_CRITICAL static int ciphersuite_is_removed(const mbedtls_ssl_ciphersuite_t *cs_info) { (void) cs_info; return 0; } const int *mbedtls_ssl_list_ciphersuites(void) { /* * On initial call filter out all ciphersuites not supported by current * build based on presence in the ciphersuite_definitions. */ if (supported_init == 0) { const int *p; int *q; for (p = ciphersuite_preference, q = supported_ciphersuites; *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; p++) { const mbedtls_ssl_ciphersuite_t *cs_info; if ((cs_info = mbedtls_ssl_ciphersuite_from_id(*p)) != NULL && !ciphersuite_is_removed(cs_info)) { *(q++) = *p; } } *q = 0; supported_init = 1; } return supported_ciphersuites; } #endif /* MBEDTLS_SSL_CIPHERSUITES */ const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name) { const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; if (NULL == ciphersuite_name) { return NULL; } while (cur->id != 0) { if (0 == strcmp(cur->name, ciphersuite_name)) { return cur; } cur++; } return NULL; } const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite) { const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; while (cur->id != 0) { if (cur->id == ciphersuite) { return cur; } cur++; } return NULL; } const char *mbedtls_ssl_get_ciphersuite_name(const int ciphersuite_id) { const mbedtls_ssl_ciphersuite_t *cur; cur = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); if (cur == NULL) { return "unknown"; } return cur->name; } int mbedtls_ssl_get_ciphersuite_id(const char *ciphersuite_name) { const mbedtls_ssl_ciphersuite_t *cur; cur = mbedtls_ssl_ciphersuite_from_string(ciphersuite_name); if (cur == NULL) { return 0; } return cur->id; } size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t key_type; psa_algorithm_t alg; size_t key_bits; status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) info->cipher, info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16, &alg, &key_type, &key_bits); if (status != PSA_SUCCESS) { return 0; } return key_bits; #else const mbedtls_cipher_info_t * const cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) info->cipher); return mbedtls_cipher_info_get_key_bitlen(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_PK_C) mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return MBEDTLS_PK_RSA; case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return MBEDTLS_PK_ECDSA; case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return MBEDTLS_PK_ECKEY; default: return MBEDTLS_PK_NONE; } } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return PSA_ALG_RSA_PKCS1V15_CRYPT; case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: return PSA_ALG_RSA_PKCS1V15_SIGN( mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac)); case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac)); case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return PSA_ALG_ECDH; default: return PSA_ALG_NONE; } } psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return PSA_KEY_USAGE_DECRYPT; case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return PSA_KEY_USAGE_SIGN_HASH; case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return PSA_KEY_USAGE_DERIVE; default: return 0; } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: return MBEDTLS_PK_RSA; case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return MBEDTLS_PK_ECDSA; default: return MBEDTLS_PK_NONE; } } #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECJPAKE: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || * MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || * MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) { switch (info->key_exchange) { case MBEDTLS_KEY_EXCHANGE_PSK: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_TLS_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_ciphersuites_internal.h000066400000000000000000000115151464416617300267740ustar00rootroot00000000000000/** * \file ssl_ciphersuites_internal.h * * \brief Internal part of the public "ssl_ciphersuites.h". */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H #define MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H #include "mbedtls/pk.h" #if defined(MBEDTLS_PK_C) mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info); psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info); #endif /* MBEDTLS_PK_C */ int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info); int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECJPAKE: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_PSK: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return 1; default: return 0; } } static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return 1; default: return 0; } } #if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info) { switch (info->MBEDTLS_PRIVATE(key_exchange)) { case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: return 1; default: return 0; } } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #endif /* MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_client.c000066400000000000000000001035131464416617300236420ustar00rootroot00000000000000/* * TLS 1.2 and 1.3 client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2) #include #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "ssl_client.h" #include "ssl_misc.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hostname_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t hostname_len; *olen = 0; if (ssl->hostname == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding server name extension: %s", ssl->hostname)); hostname_len = strlen(ssl->hostname); MBEDTLS_SSL_CHK_BUF_PTR(p, end, hostname_len + 9); /* * Sect. 3, RFC 6066 (TLS Extensions Definitions) * * In order to provide any of the server names, clients MAY include an * extension of type "server_name" in the (extended) client hello. The * "extension_data" field of this extension SHALL contain * "ServerNameList" where: * * struct { * NameType name_type; * select (name_type) { * case host_name: HostName; * } name; * } ServerName; * * enum { * host_name(0), (255) * } NameType; * * opaque HostName<1..2^16-1>; * * struct { * ServerName server_name_list<1..2^16-1> * } ServerNameList; * */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SERVERNAME, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(hostname_len + 5, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(hostname_len + 3, p, 0); p += 2; *p++ = MBEDTLS_BYTE_0(MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME); MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); p += 2; memcpy(p, ssl->hostname, hostname_len); *olen = hostname_len + 9; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SERVERNAME); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) /* * ssl_write_alpn_ext() * * Structure of the application_layer_protocol_negotiation extension in * ClientHello: * * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; *out_len = 0; if (ssl->conf->alpn_list == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding alpn extension")); /* Check we have enough space for the extension type (2 bytes), the * extension length (2 bytes) and the protocol_name_list length (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); /* Skip writing extension and list length for now */ p += 6; /* * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; */ for (const char **cur = ssl->conf->alpn_list; *cur != NULL; cur++) { /* * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of * protocol names is less than 255. */ size_t protocol_name_len = strlen(*cur); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + protocol_name_len); *p++ = (unsigned char) protocol_name_len; memcpy(p, *cur, protocol_name_len); p += protocol_name_len; } *out_len = (size_t) (p - buf); /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4); /* Extension length = *out_len - 2 (ext_type) - 2 (ext_len) */ MBEDTLS_PUT_UINT16_BE(*out_len - 4, buf, 2); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* * Function for writing a supported groups (TLS 1.3) or supported elliptic * curves (TLS 1.2) extension. * * The "extension_data" field of a supported groups extension contains a * "NamedGroupList" value (TLS 1.3 RFC8446): * enum { * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), * x25519(0x001D), x448(0x001E), * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), * ffdhe6144(0x0103), ffdhe8192(0x0104), * ffdhe_private_use(0x01FC..0x01FF), * ecdhe_private_use(0xFE00..0xFEFF), * (0xFFFF) * } NamedGroup; * struct { * NamedGroup named_group_list<2..2^16-1>; * } NamedGroupList; * * The "extension_data" field of a supported elliptic curves extension contains * a "NamedCurveList" value (TLS 1.2 RFC 8422): * enum { * deprecated(1..22), * secp256r1 (23), secp384r1 (24), secp521r1 (25), * x25519(29), x448(30), * reserved (0xFE00..0xFEFF), * deprecated(0xFF01..0xFF02), * (0xFFFF) * } NamedCurve; * struct { * NamedCurve named_curve_list<2..2^16-1> * } NamedCurveList; * * The TLS 1.3 supported groups extension was defined to be a compatible * generalization of the TLS 1.2 supported elliptic curves extension. They both * share the same extension identifier. * */ #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1 #define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG 2 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, int flags, size_t *out_len) { unsigned char *p = buf; unsigned char *named_group_list; /* Start of named_group_list */ size_t named_group_list_len; /* Length of named_group_list */ const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_groups extension")); /* Check if we have space for header and length fields: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - named_group_list_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; named_group_list = p; if (group_list == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *group_list != 0; group_list++) { int propose_group = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("got supported group(%04x)", *group_list)); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list) && (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != MBEDTLS_ECP_DP_NONE)) { propose_group = 1; } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { propose_group = 1; } #endif } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) if ((flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG) && mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list) && (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) != MBEDTLS_ECP_DP_NONE)) { propose_group = 1; } #endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC */ if (propose_group) { MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(*group_list, p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("NamedGroup: %s ( %x )", mbedtls_ssl_named_group_to_str(*group_list), *group_list)); } } /* Length of named_group_list */ named_group_list_len = (size_t) (p - named_group_list); if (named_group_list_len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("No group available.")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Write extension_type */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0); /* Write extension_data_length */ MBEDTLS_PUT_UINT16_BE(named_group_list_len + 2, buf, 2); /* Write length of named_group_list */ MBEDTLS_PUT_UINT16_BE(named_group_list_len, buf, 4); MBEDTLS_SSL_DEBUG_BUF(3, "Supported groups extension", buf + 4, named_group_list_len + 2); *out_len = (size_t) (p - buf); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_SUPPORTED_GROUPS); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC || MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_hello_cipher_suites( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, int *tls12_uses_ec, size_t *out_len) { unsigned char *p = buf; const int *ciphersuite_list; unsigned char *cipher_suites; /* Start of the cipher_suites list */ size_t cipher_suites_len; *tls12_uses_ec = 0; *out_len = 0; /* * Ciphersuite list * * This is a list of the symmetric cipher options supported by * the client, specifically the record protection algorithm * ( including secret key length ) and a hash to be used with * HKDF, in descending order of client preference. */ ciphersuite_list = ssl->conf->ciphersuite_list; /* Check there is space for the cipher suite list length (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p += 2; /* Write cipher_suites * CipherSuite cipher_suites<2..2^16-2>; */ cipher_suites = p; for (size_t i = 0; ciphersuite_list[i] != 0; i++) { int cipher_suite = ciphersuite_list[i]; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); if (mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, ssl->handshake->min_tls_version, ssl->tls_version) != 0) { continue; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info); #endif MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, add ciphersuite: %04x, %s", (unsigned int) cipher_suite, ciphersuite_info->name)); /* Check there is space for the cipher suite identifier (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(cipher_suite, p, 0); p += 2; } /* * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ int renegotiating = 0; #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); #endif if (!renegotiating) { MBEDTLS_SSL_DEBUG_MSG(3, ("adding EMPTY_RENEGOTIATION_INFO_SCSV")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0); p += 2; } /* Write the cipher_suites length in number of bytes */ cipher_suites_len = (size_t) (p - cipher_suites); MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", cipher_suites_len/2)); /* Output the total length of cipher_suites field. */ *out_len = (size_t) (p - buf); return 0; } /* * Structure of the TLS 1.3 ClientHello message: * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 * Random random; * opaque legacy_session_id<0..32>; * CipherSuite cipher_suites<2..2^16-2>; * opaque legacy_compression_methods<1..2^8-1>; * Extension extensions<8..2^16-1>; * } ClientHello; * * Structure of the (D)TLS 1.2 ClientHello message: * * struct { * ProtocolVersion client_version; * Random random; * SessionID session_id; * opaque cookie<0..2^8-1>; // DTLS 1.2 ONLY * CipherSuite cipher_suites<2..2^16-2>; * CompressionMethod compression_methods<1..2^8-1>; * select (extensions_present) { * case false: * struct {}; * case true: * Extension extensions<0..2^16-1>; * }; * } ClientHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, size_t *binders_len) { int ret; mbedtls_ssl_handshake_params *handshake = ssl->handshake; unsigned char *p = buf; unsigned char *p_extensions_len; /* Pointer to extensions length */ size_t output_len; /* Length of buffer used by function */ size_t extensions_len; /* Length of the list of extensions*/ int tls12_uses_ec = 0; *out_len = 0; *binders_len = 0; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) unsigned char propose_tls12 = (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) && (MBEDTLS_SSL_VERSION_TLS1_2 <= ssl->tls_version); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) unsigned char propose_tls13 = (handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3) && (MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version); #endif /* * Write client_version (TLS 1.2) or legacy_version (TLS 1.3) * * In all cases this is the TLS 1.2 version. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); mbedtls_ssl_write_version(p, ssl->conf->transport, MBEDTLS_SSL_VERSION_TLS1_2); p += 2; /* ... * Random random; * ... * * The random bytes have been prepared by ssl_prepare_client_hello() into * the handshake->randbytes buffer and are copied here into the output * buffer. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); memcpy(p, handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; /* TLS 1.2: * ... * SessionID session_id; * ... * with * opaque SessionID<0..32>; * * TLS 1.3: * ... * opaque legacy_session_id<0..32>; * ... * * The (legacy) session identifier bytes have been prepared by * ssl_prepare_client_hello() into the ssl->session_negotiate->id buffer * and are copied here into the output buffer. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, ssl->session_negotiate->id_len + 1); *p++ = (unsigned char) ssl->session_negotiate->id_len; memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len); p += ssl->session_negotiate->id_len; MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len); /* DTLS 1.2 ONLY * ... * opaque cookie<0..2^8-1>; * ... */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t cookie_len = 0; #else uint16_t cookie_len = 0; #endif /* !MBEDTLS_SSL_PROTO_TLS1_3 */ if (handshake->cookie != NULL) { MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", handshake->cookie, handshake->cookie_len); cookie_len = handshake->cookie_len; } MBEDTLS_SSL_CHK_BUF_PTR(p, end, cookie_len + 1); *p++ = (unsigned char) cookie_len; if (cookie_len > 0) { memcpy(p, handshake->cookie, cookie_len); p += cookie_len; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ /* Write cipher_suites */ ret = ssl_write_client_hello_cipher_suites(ssl, p, end, &tls12_uses_ec, &output_len); if (ret != 0) { return ret; } p += output_len; /* Write legacy_compression_methods (TLS 1.3) or * compression_methods (TLS 1.2) * * For every TLS 1.3 ClientHello, this vector MUST contain exactly * one byte set to zero, which corresponds to the 'null' compression * method in prior versions of TLS. * * For TLS 1.2 ClientHello, for security reasons we do not support * compression anymore, thus also just the 'null' compression method. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); *p++ = 1; *p++ = MBEDTLS_SSL_COMPRESS_NULL; /* Write extensions */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Keeping track of the included extensions */ handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; #endif /* First write extensions, then the total length */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /* Write server name extension */ ret = ssl_write_hostname_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) ret = ssl_write_alpn_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (propose_tls13) { ret = mbedtls_ssl_tls13_write_client_hello_exts(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) { int ssl_write_supported_groups_ext_flags = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { ssl_write_supported_groups_ext_flags |= SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG; } #endif #if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) if (propose_tls12 && tls12_uses_ec) { ssl_write_supported_groups_ext_flags |= SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG; } #endif if (ssl_write_supported_groups_ext_flags != 0) { ret = ssl_write_supported_groups_ext(ssl, p, end, ssl_write_supported_groups_ext_flags, &output_len); if (ret != 0) { return ret; } p += output_len; } } #endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC || MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) int write_sig_alg_ext = 0; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) write_sig_alg_ext = write_sig_alg_ext || (propose_tls13 && mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl)); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) write_sig_alg_ext = write_sig_alg_ext || propose_tls12; #endif if (write_sig_alg_ext) { ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (propose_tls12) { ret = mbedtls_ssl_tls12_write_client_hello_exts(ssl, p, end, tls12_uses_ec, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* The "pre_shared_key" extension (RFC 8446 Section 4.2.11) * MUST be the last extension in the ClientHello. */ if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) { ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( ssl, p, end, &output_len, binders_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ /* Write the length of the list of extensions. */ extensions_len = (size_t) (p - p_extensions_len) - 2; if (extensions_len == 0) { p = p_extensions_len; } else { MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, total extension length: %" \ MBEDTLS_PRINTF_SIZET, extensions_len)); MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p_extensions_len, extensions_len); } *out_len = (size_t) (p - buf); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_generate_random(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *randbytes = ssl->handshake->randbytes; size_t gmt_unix_time_len = 0; /* * Generate the random bytes * * TLS 1.2 case: * struct { * uint32 gmt_unix_time; * opaque random_bytes[28]; * } Random; * * TLS 1.3 case: * opaque Random[32]; */ if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t gmt_unix_time = mbedtls_time(NULL); MBEDTLS_PUT_UINT32_BE(gmt_unix_time, randbytes, 0); gmt_unix_time_len = 4; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, (long long) gmt_unix_time)); #endif /* MBEDTLS_HAVE_TIME */ } ret = ssl->conf->f_rng(ssl->conf->p_rng, randbytes + gmt_unix_time_len, MBEDTLS_CLIENT_HELLO_RANDOM_LEN - gmt_unix_time_len); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl) { int ret; size_t session_id_len; mbedtls_ssl_session *session_negotiate = ssl->session_negotiate; if (session_negotiate == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_HAVE_TIME) /* Check if a tls13 ticket has been configured. */ if (ssl->handshake->resume != 0 && session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && session_negotiate->ticket != NULL) { mbedtls_ms_time_t now = mbedtls_ms_time(); mbedtls_ms_time_t age = now - session_negotiate->ticket_reception_time; if (age < 0 || age > (mbedtls_ms_time_t) session_negotiate->ticket_lifetime * 1000) { /* Without valid ticket, disable session resumption.*/ MBEDTLS_SSL_DEBUG_MSG( 3, ("Ticket expired, disable session resumption")); ssl->handshake->resume = 0; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_HAVE_TIME */ /* Bet on the highest configured version if we are not in a TLS 1.2 * renegotiation or session resumption. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { ssl->handshake->min_tls_version = ssl->tls_version; } else #endif { if (ssl->handshake->resume) { ssl->tls_version = session_negotiate->tls_version; ssl->handshake->min_tls_version = ssl->tls_version; } else { ssl->handshake->min_tls_version = ssl->conf->min_tls_version; } } /* * Generate the random bytes, except when responding to a verify request * where we MUST reuse the previously generated random bytes * (RFC 6347 4.2.1). */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->handshake->cookie == NULL)) #endif { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (!ssl->handshake->hello_retry_request_flag) #endif { ret = ssl_generate_random(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret); return ret; } } } /* * Prepare session identifier. At that point, the length of the session * identifier in the SSL context `ssl->session_negotiate->id_len` is equal * to zero, except in the case of a TLS 1.2 session renegotiation or * session resumption. */ session_id_len = session_negotiate->id_len; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { if (session_id_len < 16 || session_id_len > 32 || #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || #endif ssl->handshake->resume == 0) { session_id_len = 0; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) /* * RFC 5077 section 3.4: "When presenting a ticket, the client MAY * generate and include a Session ID in the TLS ClientHello." */ int renegotiating = 0; #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { renegotiating = 1; } #endif if (!renegotiating) { if ((session_negotiate->ticket != NULL) && (session_negotiate->ticket_len != 0)) { session_id_len = 32; } } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* * Create a legacy session identifier for the purpose of middlebox * compatibility only if one has not been created already, which is * the case if we are here for the TLS 1.3 second ClientHello. * * Versions of TLS before TLS 1.3 supported a "session resumption" * feature which has been merged with pre-shared keys in TLS 1.3 * version. A client which has a cached session ID set by a pre-TLS 1.3 * server SHOULD set this field to that value. In compatibility mode, * this field MUST be non-empty, so a client not offering a pre-TLS 1.3 * session MUST generate a new 32-byte value. This value need not be * random but SHOULD be unpredictable to avoid implementations fixating * on a specific value (also known as ossification). Otherwise, it MUST * be set as a zero-length vector ( i.e., a zero-valued single byte * length field ). */ session_id_len = 32; } #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ if (session_id_len != session_negotiate->id_len) { session_negotiate->id_len = session_id_len; if (session_id_len > 0) { ret = ssl->conf->f_rng(ssl->conf->p_rng, session_negotiate->id, session_id_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "creating session id failed", ret); return ret; } } } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && ssl->handshake->resume) { int hostname_mismatch = ssl->hostname != NULL || session_negotiate->hostname != NULL; if (ssl->hostname != NULL && session_negotiate->hostname != NULL) { hostname_mismatch = strcmp( ssl->hostname, session_negotiate->hostname) != 0; } if (hostname_mismatch) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Hostname mismatch the session ticket, " "disable session resumption.")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } else { return mbedtls_ssl_session_set_hostname(session_negotiate, ssl->hostname); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SERVER_NAME_INDICATION */ return 0; } /* * Write ClientHello handshake message. * Handler for MBEDTLS_SSL_CLIENT_HELLO */ int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl) { int ret = 0; unsigned char *buf; size_t buf_len, msg_len, binders_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client hello")); MBEDTLS_SSL_PROC_CHK(ssl_prepare_client_hello(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_write_client_hello_body(ssl, buf, buf + buf_len, &msg_len, &binders_len)); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_msglen = msg_len + 4; mbedtls_ssl_send_flight_completed(ssl); /* * The two functions below may try to send data on the network and * can return with the MBEDTLS_ERR_SSL_WANT_READ error code when they * fail to do so and the transmission has to be retried later. In that * case as in fatal error cases, we return immediately. But we must have * set the handshake state to the next state at that point to ensure * that we will not write and send again a ClientHello when we * eventually succeed in sending the pending data. */ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_DTLS */ { ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, msg_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_add_hs_hdr_to_checksum", ret); return ret; } ret = ssl->handshake->update_checksum(ssl, buf, msg_len - binders_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (binders_len > 0) { MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( ssl, buf + msg_len - binders_len, buf + msg_len)); ret = ssl->handshake->update_checksum(ssl, buf + msg_len - binders_len, binders_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, msg_len)); /* * Set next state. Note that if TLS 1.3 is proposed, this may be * overwritten by mbedtls_ssl_tls13_finalize_client_hello(). */ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && MBEDTLS_SSL_VERSION_TLS1_3 <= ssl->tls_version) { ret = mbedtls_ssl_tls13_finalize_client_hello(ssl); } #endif } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_CLIENT_HELLO, ssl->handshake->sent_extensions); #endif cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello")); return ret; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_CLI_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_client.h000066400000000000000000000006731464416617300236520ustar00rootroot00000000000000/** * TLS 1.2 and 1.3 client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_CLIENT_H #define MBEDTLS_SSL_CLIENT_H #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "ssl_misc.h" #endif #include MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_CLIENT_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_cookie.c000066400000000000000000000246601464416617300236420ustar00rootroot00000000000000/* * DTLS cookie callbacks implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * These session callbacks use a simple chained list * to store and retrieve the session information. */ #include "common.h" #if defined(MBEDTLS_SSL_COOKIE_C) #include "mbedtls/platform.h" #include "mbedtls/ssl_cookie.h" #include "ssl_misc.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* * If DTLS is in use, then at least one of SHA-256 or SHA-384 is * available. Try SHA-256 first as 384 wastes resources */ #if defined(MBEDTLS_MD_CAN_SHA256) #define COOKIE_MD MBEDTLS_MD_SHA256 #define COOKIE_MD_OUTLEN 32 #define COOKIE_HMAC_LEN 28 #elif defined(MBEDTLS_MD_CAN_SHA384) #define COOKIE_MD MBEDTLS_MD_SHA384 #define COOKIE_MD_OUTLEN 48 #define COOKIE_HMAC_LEN 28 #else #error "DTLS hello verify needs SHA-256 or SHA-384" #endif /* * Cookies are formed of a 4-bytes timestamp (or serial number) and * an HMAC of timestamp and client ID. */ #define COOKIE_LEN (4 + COOKIE_HMAC_LEN) void mbedtls_ssl_cookie_init(mbedtls_ssl_cookie_ctx *ctx) { #if defined(MBEDTLS_USE_PSA_CRYPTO) ctx->psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_md_init(&ctx->hmac_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_HAVE_TIME) ctx->serial = 0; #endif ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; #if !defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long delay) { ctx->timeout = delay; } void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(ctx->psa_hmac_key); #else mbedtls_md_free(&ctx->hmac_ctx); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_cookie_ctx)); } int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_algorithm_t alg; (void) f_rng; (void) p_rng; alg = mbedtls_md_psa_alg_from_type(COOKIE_MD); if (alg == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ctx->psa_hmac_alg = PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(alg), COOKIE_HMAC_LEN); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_SIGN_MESSAGE); psa_set_key_algorithm(&attributes, ctx->psa_hmac_alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(COOKIE_MD_OUTLEN)); if ((status = psa_generate_key(&attributes, &ctx->psa_hmac_key)) != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char key[COOKIE_MD_OUTLEN]; if ((ret = f_rng(p_rng, key, sizeof(key))) != 0) { return ret; } ret = mbedtls_md_setup(&ctx->hmac_ctx, mbedtls_md_info_from_type(COOKIE_MD), 1); if (ret != 0) { return ret; } ret = mbedtls_md_hmac_starts(&ctx->hmac_ctx, key, sizeof(key)); if (ret != 0) { return ret; } mbedtls_platform_zeroize(key, sizeof(key)); #endif /* MBEDTLS_USE_PSA_CRYPTO */ return 0; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* * Generate the HMAC part of a cookie */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_hmac(mbedtls_md_context_t *hmac_ctx, const unsigned char time[4], unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { unsigned char hmac_out[COOKIE_MD_OUTLEN]; MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_HMAC_LEN); if (mbedtls_md_hmac_reset(hmac_ctx) != 0 || mbedtls_md_hmac_update(hmac_ctx, time, 4) != 0 || mbedtls_md_hmac_update(hmac_ctx, cli_id, cli_id_len) != 0 || mbedtls_md_hmac_finish(hmac_ctx, hmac_out) != 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(*p, hmac_out, COOKIE_HMAC_LEN); *p += COOKIE_HMAC_LEN; return 0; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ /* * Generate cookie for DTLS ClientHello verification */ int mbedtls_ssl_cookie_write(void *p_ctx, unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t sign_mac_length = 0; #endif int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; unsigned long t; if (ctx == NULL || cli_id == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_CHK_BUF_PTR(*p, end, COOKIE_LEN); #if defined(MBEDTLS_HAVE_TIME) t = (unsigned long) mbedtls_time(NULL); #else t = ctx->serial++; #endif MBEDTLS_PUT_UINT32_BE(t, *p, 0); *p += 4; #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key, ctx->psa_hmac_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, *p - 4, 4); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, cli_id, cli_id_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN, &sign_mac_length); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } *p += COOKIE_HMAC_LEN; ret = 0; #else #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); } #endif ret = ssl_cookie_hmac(&ctx->hmac_ctx, *p - 4, p, end, cli_id, cli_id_len); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, MBEDTLS_ERR_THREADING_MUTEX_ERROR); } #endif #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) exit: status = psa_mac_abort(&operation); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return ret; } /* * Check a cookie */ int mbedtls_ssl_cookie_check(void *p_ctx, const unsigned char *cookie, size_t cookie_len, const unsigned char *cli_id, size_t cli_id_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #else unsigned char ref_hmac[COOKIE_HMAC_LEN]; unsigned char *p = ref_hmac; #endif int ret = 0; mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; unsigned long cur_time, cookie_time; if (ctx == NULL || cli_id == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (cookie_len != COOKIE_LEN) { return -1; } #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key, ctx->psa_hmac_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, cookie, 4); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_update(&operation, cli_id, cli_id_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_verify_finish(&operation, cookie + 4, COOKIE_HMAC_LEN); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } ret = 0; #else #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret); } #endif if (ssl_cookie_hmac(&ctx->hmac_ctx, cookie, &p, p + sizeof(ref_hmac), cli_id, cli_id_len) != 0) { ret = -1; } #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_SSL_INTERNAL_ERROR, MBEDTLS_ERR_THREADING_MUTEX_ERROR); } #endif if (ret != 0) { goto exit; } if (mbedtls_ct_memcmp(cookie + 4, ref_hmac, sizeof(ref_hmac)) != 0) { ret = -1; goto exit; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_HAVE_TIME) cur_time = (unsigned long) mbedtls_time(NULL); #else cur_time = ctx->serial; #endif cookie_time = (unsigned long) MBEDTLS_GET_UINT32_BE(cookie, 0); if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) { ret = -1; goto exit; } exit: #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_abort(&operation); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #else mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac)); #endif /* MBEDTLS_USE_PSA_CRYPTO */ return ret; } #endif /* MBEDTLS_SSL_COOKIE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h000066400000000000000000000060221464416617300251760ustar00rootroot00000000000000/** * \file ssl_debug_helpers.h * * \brief Automatically generated helper functions for debugging */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_DEBUG_HELPERS_H #define MBEDTLS_SSL_DEBUG_HELPERS_H #include "common.h" #if defined(MBEDTLS_DEBUG_C) #include "mbedtls/ssl.h" #include "ssl_misc.h" const char *mbedtls_ssl_states_str(mbedtls_ssl_states in); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in); const char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in); #endif const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in); const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in); const char *mbedtls_ssl_key_export_type_str(mbedtls_ssl_key_export_type in); const char *mbedtls_ssl_sig_alg_to_str(uint16_t in); const char *mbedtls_ssl_named_group_to_str(uint16_t in); const char *mbedtls_ssl_get_extension_name(unsigned int extension_type); void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, uint32_t extensions_mask, const char *extra); void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, unsigned int extension_type, const char *extra_msg0, const char *extra_msg1); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, int level, const char *file, int line, unsigned int flags); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extensions_mask) \ mbedtls_ssl_print_extensions(ssl, level, __FILE__, __LINE__, \ hs_msg_type, extensions_mask, NULL) #define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) \ mbedtls_ssl_print_extension(ssl, level, __FILE__, __LINE__, \ hs_msg_type, extension_type, \ extra, NULL) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) \ mbedtls_ssl_print_ticket_flags(ssl, level, __FILE__, __LINE__, flags) #endif #else #define MBEDTLS_SSL_PRINT_EXTS(level, hs_msg_type, extension_mask) #define MBEDTLS_SSL_PRINT_EXT(level, hs_msg_type, extension_type, extra) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_PRINT_TICKET_FLAGS(level, flags) #endif #endif /* MBEDTLS_DEBUG_C */ #endif /* MBEDTLS_SSL_DEBUG_HELPERS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c000066400000000000000000000225751464416617300272220ustar00rootroot00000000000000/* Automatically generated by generate_ssl_debug_helpers.py. DO NOT EDIT. */ /** * \file ssl_debug_helpers_generated.c * * \brief Automatically generated helper functions for debugging */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later * */ #include "common.h" #if defined(MBEDTLS_DEBUG_C) #include "ssl_debug_helpers.h" const char *mbedtls_ssl_named_group_to_str( uint16_t in ) { switch( in ) { case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1: return "secp192k1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1: return "secp192r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1: return "secp224k1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1: return "secp224r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1: return "secp256k1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1: return "secp256r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1: return "secp384r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1: return "secp521r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1: return "bp256r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1: return "bp384r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1: return "bp512r1"; case MBEDTLS_SSL_IANA_TLS_GROUP_X25519: return "x25519"; case MBEDTLS_SSL_IANA_TLS_GROUP_X448: return "x448"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: return "ffdhe2048"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: return "ffdhe3072"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: return "ffdhe4096"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: return "ffdhe6144"; case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: return "ffdhe8192"; }; return "UNKOWN"; } const char *mbedtls_ssl_sig_alg_to_str( uint16_t in ) { switch( in ) { case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: return "rsa_pkcs1_sha256"; case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: return "rsa_pkcs1_sha384"; case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: return "rsa_pkcs1_sha512"; case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: return "ecdsa_secp256r1_sha256"; case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: return "ecdsa_secp384r1_sha384"; case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: return "ecdsa_secp521r1_sha512"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: return "rsa_pss_rsae_sha256"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: return "rsa_pss_rsae_sha384"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: return "rsa_pss_rsae_sha512"; case MBEDTLS_TLS1_3_SIG_ED25519: return "ed25519"; case MBEDTLS_TLS1_3_SIG_ED448: return "ed448"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256: return "rsa_pss_pss_sha256"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384: return "rsa_pss_pss_sha384"; case MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512: return "rsa_pss_pss_sha512"; case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1: return "rsa_pkcs1_sha1"; case MBEDTLS_TLS1_3_SIG_ECDSA_SHA1: return "ecdsa_sha1"; case MBEDTLS_TLS1_3_SIG_NONE: return "none"; }; return "UNKNOWN"; } const char *mbedtls_ssl_states_str( mbedtls_ssl_states in ) { switch (in) { case MBEDTLS_SSL_HELLO_REQUEST: return "MBEDTLS_SSL_HELLO_REQUEST"; case MBEDTLS_SSL_CLIENT_HELLO: return "MBEDTLS_SSL_CLIENT_HELLO"; case MBEDTLS_SSL_SERVER_HELLO: return "MBEDTLS_SSL_SERVER_HELLO"; case MBEDTLS_SSL_SERVER_CERTIFICATE: return "MBEDTLS_SSL_SERVER_CERTIFICATE"; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: return "MBEDTLS_SSL_SERVER_KEY_EXCHANGE"; case MBEDTLS_SSL_CERTIFICATE_REQUEST: return "MBEDTLS_SSL_CERTIFICATE_REQUEST"; case MBEDTLS_SSL_SERVER_HELLO_DONE: return "MBEDTLS_SSL_SERVER_HELLO_DONE"; case MBEDTLS_SSL_CLIENT_CERTIFICATE: return "MBEDTLS_SSL_CLIENT_CERTIFICATE"; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: return "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE"; case MBEDTLS_SSL_CERTIFICATE_VERIFY: return "MBEDTLS_SSL_CERTIFICATE_VERIFY"; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: return "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC"; case MBEDTLS_SSL_CLIENT_FINISHED: return "MBEDTLS_SSL_CLIENT_FINISHED"; case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: return "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC"; case MBEDTLS_SSL_SERVER_FINISHED: return "MBEDTLS_SSL_SERVER_FINISHED"; case MBEDTLS_SSL_FLUSH_BUFFERS: return "MBEDTLS_SSL_FLUSH_BUFFERS"; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: return "MBEDTLS_SSL_HANDSHAKE_WRAPUP"; case MBEDTLS_SSL_NEW_SESSION_TICKET: return "MBEDTLS_SSL_NEW_SESSION_TICKET"; case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: return "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT"; case MBEDTLS_SSL_HELLO_RETRY_REQUEST: return "MBEDTLS_SSL_HELLO_RETRY_REQUEST"; case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: return "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS"; case MBEDTLS_SSL_END_OF_EARLY_DATA: return "MBEDTLS_SSL_END_OF_EARLY_DATA"; case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: return "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY"; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: return "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED"; case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: return "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO"; case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: return "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO"; case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: return "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO"; case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: return "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST"; case MBEDTLS_SSL_HANDSHAKE_OVER: return "MBEDTLS_SSL_HANDSHAKE_OVER"; case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET"; case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH"; default: return "UNKNOWN_VALUE"; } } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) const char *mbedtls_ssl_early_data_status_str( mbedtls_ssl_early_data_status in ) { switch (in) { case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED: return "MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED"; case MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED: return "MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED"; case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED: return "MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED"; default: return "UNKNOWN_VALUE"; } } #endif /* defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) */ const char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in ) { switch (in) { case MBEDTLS_SSL_VERSION_UNKNOWN: return "MBEDTLS_SSL_VERSION_UNKNOWN"; case MBEDTLS_SSL_VERSION_TLS1_2: return "MBEDTLS_SSL_VERSION_TLS1_2"; case MBEDTLS_SSL_VERSION_TLS1_3: return "MBEDTLS_SSL_VERSION_TLS1_3"; default: return "UNKNOWN_VALUE"; } } const char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in ) { switch (in) { case MBEDTLS_SSL_TLS_PRF_NONE: return "MBEDTLS_SSL_TLS_PRF_NONE"; case MBEDTLS_SSL_TLS_PRF_SHA384: return "MBEDTLS_SSL_TLS_PRF_SHA384"; case MBEDTLS_SSL_TLS_PRF_SHA256: return "MBEDTLS_SSL_TLS_PRF_SHA256"; case MBEDTLS_SSL_HKDF_EXPAND_SHA384: return "MBEDTLS_SSL_HKDF_EXPAND_SHA384"; case MBEDTLS_SSL_HKDF_EXPAND_SHA256: return "MBEDTLS_SSL_HKDF_EXPAND_SHA256"; default: return "UNKNOWN_VALUE"; } } const char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in ) { switch (in) { case MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET"; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET"; case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET: return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET"; #endif default: return "UNKNOWN_VALUE"; } } #endif /* MBEDTLS_DEBUG_C */ /* End of automatically generated file. */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_misc.h000066400000000000000000003431071464416617300233310ustar00rootroot00000000000000/** * \file ssl_misc.h * * \brief Internal functions shared by the SSL modules */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_MISC_H #define MBEDTLS_SSL_MISC_H #include "mbedtls/build_info.h" #include "mbedtls/error.h" #include "mbedtls/ssl.h" #include "mbedtls/cipher.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "psa/crypto.h" #include "psa_util_internal.h" #endif #if defined(MBEDTLS_MD_CAN_MD5) #include "mbedtls/md5.h" #endif #if defined(MBEDTLS_MD_CAN_SHA1) #include "mbedtls/sha1.h" #endif #if defined(MBEDTLS_MD_CAN_SHA256) #include "mbedtls/sha256.h" #endif #if defined(MBEDTLS_MD_CAN_SHA512) #include "mbedtls/sha512.h" #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ !defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/ecjpake.h" #endif #include "mbedtls/pk.h" #include "ssl_ciphersuites_internal.h" #include "x509_internal.h" #include "pk_internal.h" #include "common.h" /* Shorthand for restartable ECC */ #if defined(MBEDTLS_ECP_RESTARTABLE) && \ defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) #define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED #endif #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ #define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ #define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ /* Faked handshake message identity for HelloRetryRequest. */ #define MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST (-MBEDTLS_SSL_HS_SERVER_HELLO) /* * Internal identity of handshake extensions */ #define MBEDTLS_SSL_EXT_ID_UNRECOGNIZED 0 #define MBEDTLS_SSL_EXT_ID_SERVERNAME 1 #define MBEDTLS_SSL_EXT_ID_SERVERNAME_HOSTNAME 1 #define MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH 2 #define MBEDTLS_SSL_EXT_ID_STATUS_REQUEST 3 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS 4 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_ELLIPTIC_CURVES 4 #define MBEDTLS_SSL_EXT_ID_SIG_ALG 5 #define MBEDTLS_SSL_EXT_ID_USE_SRTP 6 #define MBEDTLS_SSL_EXT_ID_HEARTBEAT 7 #define MBEDTLS_SSL_EXT_ID_ALPN 8 #define MBEDTLS_SSL_EXT_ID_SCT 9 #define MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE 10 #define MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE 11 #define MBEDTLS_SSL_EXT_ID_PADDING 12 #define MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY 13 #define MBEDTLS_SSL_EXT_ID_EARLY_DATA 14 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS 15 #define MBEDTLS_SSL_EXT_ID_COOKIE 16 #define MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES 17 #define MBEDTLS_SSL_EXT_ID_CERT_AUTH 18 #define MBEDTLS_SSL_EXT_ID_OID_FILTERS 19 #define MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH 20 #define MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT 21 #define MBEDTLS_SSL_EXT_ID_KEY_SHARE 22 #define MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC 23 #define MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS 24 #define MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC 25 #define MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET 26 #define MBEDTLS_SSL_EXT_ID_SESSION_TICKET 27 #define MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT 28 /* Utility for translating IANA extension type. */ uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type); uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type); /* Macros used to define mask constants */ #define MBEDTLS_SSL_EXT_MASK(id) (1ULL << (MBEDTLS_SSL_EXT_ID_##id)) /* Reset value of extension mask */ #define MBEDTLS_SSL_EXT_MASK_NONE 0 /* In messages containing extension requests, we should ignore unrecognized * extensions. In messages containing extension responses, unrecognized * extensions should result in handshake abortion. Messages containing * extension requests include ClientHello, CertificateRequest and * NewSessionTicket. Messages containing extension responses include * ServerHello, HelloRetryRequest, EncryptedExtensions and Certificate. * * RFC 8446 section 4.1.3 * * The ServerHello MUST only include extensions which are required to establish * the cryptographic context and negotiate the protocol version. * * RFC 8446 section 4.2 * * If an implementation receives an extension which it recognizes and which is * not specified for the message in which it appears, it MUST abort the handshake * with an "illegal_parameter" alert. */ /* Extensions that are not recognized by TLS 1.3 */ #define MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED \ (MBEDTLS_SSL_EXT_MASK(SUPPORTED_POINT_FORMATS) | \ MBEDTLS_SSL_EXT_MASK(ENCRYPT_THEN_MAC) | \ MBEDTLS_SSL_EXT_MASK(EXTENDED_MASTER_SECRET) | \ MBEDTLS_SSL_EXT_MASK(SESSION_TICKET) | \ MBEDTLS_SSL_EXT_MASK(TRUNCATED_HMAC) | \ MBEDTLS_SSL_EXT_MASK(UNRECOGNIZED)) /* RFC 8446 section 4.2. Allowed extensions for ClientHello */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH \ (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ MBEDTLS_SSL_EXT_MASK(ALPN) | \ MBEDTLS_SSL_EXT_MASK(SCT) | \ MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(PADDING) | \ MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES) | \ MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ MBEDTLS_SSL_EXT_MASK(COOKIE) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS) | \ MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ MBEDTLS_SSL_EXT_MASK(POST_HANDSHAKE_AUTH) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT) | \ MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) /* RFC 8446 section 4.2. Allowed extensions for EncryptedExtensions */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE \ (MBEDTLS_SSL_EXT_MASK(SERVERNAME) | \ MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | \ MBEDTLS_SSL_EXT_MASK(USE_SRTP) | \ MBEDTLS_SSL_EXT_MASK(HEARTBEAT) | \ MBEDTLS_SSL_EXT_MASK(ALPN) | \ MBEDTLS_SSL_EXT_MASK(CLI_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(SERV_CERT_TYPE) | \ MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) /* RFC 8446 section 4.2. Allowed extensions for CertificateRequest */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR \ (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG) | \ MBEDTLS_SSL_EXT_MASK(SCT) | \ MBEDTLS_SSL_EXT_MASK(CERT_AUTH) | \ MBEDTLS_SSL_EXT_MASK(OID_FILTERS) | \ MBEDTLS_SSL_EXT_MASK(SIG_ALG_CERT) | \ MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) /* RFC 8446 section 4.2. Allowed extensions for Certificate */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT \ (MBEDTLS_SSL_EXT_MASK(STATUS_REQUEST) | \ MBEDTLS_SSL_EXT_MASK(SCT)) /* RFC 8446 section 4.2. Allowed extensions for ServerHello */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH \ (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) /* RFC 8446 section 4.2. Allowed extensions for HelloRetryRequest */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR \ (MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | \ MBEDTLS_SSL_EXT_MASK(COOKIE) | \ MBEDTLS_SSL_EXT_MASK(SUPPORTED_VERSIONS)) /* RFC 8446 section 4.2. Allowed extensions for NewSessionTicket */ #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST \ (MBEDTLS_SSL_EXT_MASK(EARLY_DATA) | \ MBEDTLS_SSL_TLS1_3_EXT_MASK_UNRECOGNIZED) /* * Helper macros for function call with return check. */ /* * Exit when return non-zero value */ #define MBEDTLS_SSL_PROC_CHK(f) \ do { \ ret = (f); \ if (ret != 0) \ { \ goto cleanup; \ } \ } while (0) /* * Exit when return negative value */ #define MBEDTLS_SSL_PROC_CHK_NEG(f) \ do { \ ret = (f); \ if (ret < 0) \ { \ goto cleanup; \ } \ } while (0) /* * DTLS retransmission states, see RFC 6347 4.2.4 * * The SENDING state is merged in PREPARING for initial sends, * but is distinct for resends. * * Note: initial state is wrong for server, but is not used anyway. */ #define MBEDTLS_SSL_RETRANS_PREPARING 0 #define MBEDTLS_SSL_RETRANS_SENDING 1 #define MBEDTLS_SSL_RETRANS_WAITING 2 #define MBEDTLS_SSL_RETRANS_FINISHED 3 /* * Allow extra bytes for record, authentication and encryption overhead: * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256). */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* This macro determines whether CBC is supported. */ #if defined(MBEDTLS_SSL_HAVE_CBC) && \ (defined(MBEDTLS_SSL_HAVE_AES) || \ defined(MBEDTLS_SSL_HAVE_CAMELLIA) || \ defined(MBEDTLS_SSL_HAVE_ARIA)) #define MBEDTLS_SSL_SOME_SUITES_USE_CBC #endif /* This macro determines whether a ciphersuite using a * stream cipher can be used. */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) #define MBEDTLS_SSL_SOME_SUITES_USE_STREAM #endif /* This macro determines whether the CBC construct used in TLS 1.2 is supported. */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) #define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \ defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) #define MBEDTLS_SSL_SOME_SUITES_USE_MAC #endif /* This macro determines whether a ciphersuite uses Encrypt-then-MAC with CBC */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) #define MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) /* Ciphersuites using HMAC */ #if defined(MBEDTLS_MD_CAN_SHA384) #define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ #elif defined(MBEDTLS_MD_CAN_SHA256) #define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ #else #define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ #endif #else /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ #define MBEDTLS_SSL_MAC_ADD 16 #endif #if defined(MBEDTLS_SSL_HAVE_CBC) #define MBEDTLS_SSL_PADDING_ADD 256 #else #define MBEDTLS_SSL_PADDING_ADD 0 #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY #else #define MBEDTLS_SSL_MAX_CID_EXPANSION 0 #endif #define MBEDTLS_SSL_PAYLOAD_OVERHEAD (MBEDTLS_MAX_IV_LENGTH + \ MBEDTLS_SSL_MAC_ADD + \ MBEDTLS_SSL_PADDING_ADD + \ MBEDTLS_SSL_MAX_CID_EXPANSION \ ) #define MBEDTLS_SSL_IN_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ (MBEDTLS_SSL_IN_CONTENT_LEN)) #define MBEDTLS_SSL_OUT_PAYLOAD_LEN (MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ (MBEDTLS_SSL_OUT_CONTENT_LEN)) /* The maximum number of buffered handshake messages. */ #define MBEDTLS_SSL_MAX_BUFFERED_HS 4 /* Maximum length we can advertise as our max content length for RFC 6066 max_fragment_length extension negotiation purposes (the lesser of both sizes, if they are unequal.) */ #define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ ? (MBEDTLS_SSL_OUT_CONTENT_LEN) \ : (MBEDTLS_SSL_IN_CONTENT_LEN) \ ) /* Maximum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ #define MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN 65534 /* Minimum size in bytes of list in signature algorithms ext., RFC 5246/8446 */ #define MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN 2 /* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ #define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 #define MBEDTLS_RECEIVED_SIG_ALGS_SIZE 20 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #define MBEDTLS_TLS_SIG_NONE MBEDTLS_TLS1_3_SIG_NONE #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #define MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(sig, hash) ((hash << 8) | sig) #define MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg & 0xFF) #define MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(alg) (alg >> 8) #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* * Check that we obey the standard's message size bounds */ #if MBEDTLS_SSL_IN_CONTENT_LEN > 16384 #error "Bad configuration - incoming record content too large." #endif #if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384 #error "Bad configuration - outgoing record content too large." #endif #if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048 #error "Bad configuration - incoming protected record payload too large." #endif #if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN + 2048 #error "Bad configuration - outgoing protected record payload too large." #endif /* Calculate buffer sizes */ /* Note: Even though the TLS record header is only 5 bytes long, we're internally using 8 bytes to store the implicit sequence number. */ #define MBEDTLS_SSL_HEADER_LEN 13 #if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_IN_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN)) #else #define MBEDTLS_SSL_IN_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_IN_PAYLOAD_LEN) \ + (MBEDTLS_SSL_CID_IN_LEN_MAX)) #endif #if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define MBEDTLS_SSL_OUT_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN)) #else #define MBEDTLS_SSL_OUT_BUFFER_LEN \ ((MBEDTLS_SSL_HEADER_LEN) + (MBEDTLS_SSL_OUT_PAYLOAD_LEN) \ + (MBEDTLS_SSL_CID_OUT_LEN_MAX)) #endif #define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32 #define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Return the maximum fragment length (payload, in bytes) for * the output buffer. For the client, this is the configured * value. For the server, it is the minimum of two - the * configured value and the negotiated one. * * \sa mbedtls_ssl_conf_max_frag_len() * \sa mbedtls_ssl_get_max_out_record_payload() * * \param ssl SSL context * * \return Current maximum fragment length for the output buffer. */ size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl); /** * \brief Return the maximum fragment length (payload, in bytes) for * the input buffer. This is the negotiated maximum fragment * length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN. * If it is not defined either, the value is 2^14. This function * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). * * \sa mbedtls_ssl_conf_max_frag_len() * \sa mbedtls_ssl_get_max_in_record_payload() * * \param ssl SSL context * * \return Current maximum fragment length for the output buffer. */ size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) /** * \brief Get the size limit in bytes for the protected outgoing records * as defined in RFC 8449 * * \param ssl SSL context * * \return The size limit in bytes for the protected outgoing * records as defined in RFC 8449. */ size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) static inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx) { #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) return mbedtls_ssl_get_output_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + MBEDTLS_SSL_CID_OUT_LEN_MAX; #else return mbedtls_ssl_get_output_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; #endif } static inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx) { #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) return mbedtls_ssl_get_input_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + MBEDTLS_SSL_CID_IN_LEN_MAX; #else return mbedtls_ssl_get_input_max_frag_len(ctx) + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; #endif } #endif /* * TLS extension flags (for extensions with outgoing ServerHello content * that need it (e.g. for RENEGOTIATION_INFO the server already knows because * of state of the renegotiation flag, so no indicator is required) */ #define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) /** * \brief This function checks if the remaining size in a buffer is * greater or equal than a needed space. * * \param cur Pointer to the current position in the buffer. * \param end Pointer to one past the end of the buffer. * \param need Needed space in bytes. * * \return Zero if the needed space is available in the buffer, non-zero * otherwise. */ #if !defined(MBEDTLS_TEST_HOOKS) static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, const uint8_t *end, size_t need) { return (cur > end) || (need > (size_t) (end - cur)); } #else typedef struct { const uint8_t *cur; const uint8_t *end; size_t need; } mbedtls_ssl_chk_buf_ptr_args; void mbedtls_ssl_set_chk_buf_ptr_fail_args( const uint8_t *cur, const uint8_t *end, size_t need); void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args); static inline int mbedtls_ssl_chk_buf_ptr(const uint8_t *cur, const uint8_t *end, size_t need) { if ((cur > end) || (need > (size_t) (end - cur))) { mbedtls_ssl_set_chk_buf_ptr_fail_args(cur, end, need); return 1; } return 0; } #endif /* MBEDTLS_TEST_HOOKS */ /** * \brief This macro checks if the remaining size in a buffer is * greater or equal than a needed space. If it is not the case, * it returns an SSL_BUFFER_TOO_SMALL error. * * \param cur Pointer to the current position in the buffer. * \param end Pointer to one past the end of the buffer. * \param need Needed space in bytes. * */ #define MBEDTLS_SSL_CHK_BUF_PTR(cur, end, need) \ do { \ if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ { \ return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; \ } \ } while (0) /** * \brief This macro checks if the remaining length in an input buffer is * greater or equal than a needed length. If it is not the case, it * returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a * #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message. * * This is a function-like macro. It is guaranteed to evaluate each * argument exactly once. * * \param cur Pointer to the current position in the buffer. * \param end Pointer to one past the end of the buffer. * \param need Needed length in bytes. * */ #define MBEDTLS_SSL_CHK_BUF_READ_PTR(cur, end, need) \ do { \ if (mbedtls_ssl_chk_buf_ptr((cur), (end), (need)) != 0) \ { \ MBEDTLS_SSL_DEBUG_MSG(1, \ ("missing input data in %s", __func__)); \ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \ MBEDTLS_ERR_SSL_DECODE_ERROR); \ return MBEDTLS_ERR_SSL_DECODE_ERROR; \ } \ } while (0) #ifdef __cplusplus extern "C" { #endif typedef int mbedtls_ssl_tls_prf_cb(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); /* cipher.h exports the maximum IV, key and block length from * all ciphers enabled in the config, regardless of whether those * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled * in the default configuration and uses 64 Byte keys, but it is * not used for record protection in SSL/TLS. * * In order to prevent unnecessary inflation of key structures, * we introduce SSL-specific variants of the max-{key,block,IV} * macros here which are meant to only take those ciphers into * account which can be negotiated in SSL/TLS. * * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH * in cipher.h are rough overapproximations of the real maxima, here * we content ourselves with replicating those overapproximations * for the maximum block and IV length, and excluding XTS from the * computation of the maximum key length. */ #define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 #define MBEDTLS_SSL_MAX_IV_LENGTH 16 #define MBEDTLS_SSL_MAX_KEY_LENGTH 32 /** * \brief The data structure holding the cryptographic material (key and IV) * used for record protection in TLS 1.3. */ struct mbedtls_ssl_key_set { /*! The key for client->server records. */ unsigned char client_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; /*! The key for server->client records. */ unsigned char server_write_key[MBEDTLS_SSL_MAX_KEY_LENGTH]; /*! The IV for client->server records. */ unsigned char client_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; /*! The IV for server->client records. */ unsigned char server_write_iv[MBEDTLS_SSL_MAX_IV_LENGTH]; size_t key_len; /*!< The length of client_write_key and * server_write_key, in Bytes. */ size_t iv_len; /*!< The length of client_write_iv and * server_write_iv, in Bytes. */ }; typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; typedef struct { unsigned char binder_key[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char client_early_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char early_exporter_master_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } mbedtls_ssl_tls13_early_secrets; typedef struct { unsigned char client_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char server_handshake_traffic_secret[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } mbedtls_ssl_tls13_handshake_secrets; /* * This structure contains the parameters only needed during handshake. */ struct mbedtls_ssl_handshake_params { /* Frequently-used boolean or byte fields (placed early to take * advantage of smaller code size for indirect access on Arm Thumb) */ uint8_t resume; /*!< session resume indicator*/ uint8_t cli_exts; /*!< client extension presence*/ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) uint8_t sni_authmode; /*!< authmode from SNI callback */ #endif #if defined(MBEDTLS_SSL_SRV_C) /* Flag indicating if a CertificateRequest message has been sent * to the client or not. */ uint8_t certificate_request_sent; #if defined(MBEDTLS_SSL_EARLY_DATA) /* Flag indicating if the server has accepted early data or not. */ uint8_t early_data_accepted; #endif #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) uint8_t new_session_ticket; /*!< use NewSessionTicket? */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_CLI_C) /** Minimum TLS version to be negotiated. * * It is set up in the ClientHello writing preparation stage and used * throughout the ClientHello writing. Not relevant anymore as soon as * the protocol version has been negotiated thus as soon as the * ServerHello is received. * For a fresh handshake not linked to any previous handshake, it is * equal to the configured minimum minor version to be negotiated. When * renegotiating or resuming a session, it is equal to the previously * negotiated minor version. * * There is no maximum TLS version field in this handshake context. * From the start of the handshake, we need to define a current protocol * version for the record layer which we define as the maximum TLS * version to be negotiated. The `tls_version` field of the SSL context is * used to store this maximum value until it contains the actual * negotiated value. */ mbedtls_ssl_protocol_version min_tls_version; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) uint8_t extended_ms; /*!< use Extended Master Secret? */ #endif #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) uint8_t async_in_progress; /*!< an asynchronous operation is in progress */ #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned char retransmit_state; /*!< Retransmission state */ #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) unsigned char group_list_heap_allocated; unsigned char sig_algs_heap_allocated; #endif #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) uint8_t ecrs_enabled; /*!< Handshake supports EC restart? */ enum { /* this complements ssl->state with info on intra-state operations */ ssl_ecrs_none = 0, /*!< nothing going on (yet) */ ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ } ecrs_state; /*!< current (or last) operation */ mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ size_t ecrs_n; /*!< place for saving a length */ #endif mbedtls_ssl_ciphersuite_t const *ciphersuite_info; MBEDTLS_CHECK_RETURN_CRITICAL int (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); MBEDTLS_CHECK_RETURN_CRITICAL int (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); MBEDTLS_CHECK_RETURN_CRITICAL int (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); mbedtls_ssl_tls_prf_cb *tls_prf; /* * Handshake specific crypto variables */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t key_exchange_mode; /*!< Selected key exchange mode */ /** * Flag indicating if, in the course of the current handshake, an * HelloRetryRequest message has been sent by the server or received by * the client (<> 0) or not (0). */ uint8_t hello_retry_request_flag; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /** * Flag indicating if, in the course of the current handshake, a dummy * change_cipher_spec (CCS) record has already been sent. Used to send only * one CCS per handshake while not complicating the handshake state * transitions for that purpose. */ uint8_t ccs_sent; #endif #if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */ #endif /** selected_group of key_share extension in HelloRetryRequest message. */ uint16_t hrr_selected_group; #if defined(MBEDTLS_SSL_SESSION_TICKETS) uint16_t new_session_tickets_count; /*!< number of session tickets */ #endif #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) uint16_t received_sig_algs[MBEDTLS_RECEIVED_SIG_ALGS_SIZE]; #endif #if !defined(MBEDTLS_DEPRECATED_REMOVED) const uint16_t *group_list; const uint16_t *sig_algs; #endif #if defined(MBEDTLS_DHM_C) mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ #endif #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED) psa_key_type_t xxdh_psa_type; size_t xxdh_psa_bits; mbedtls_svc_key_id_t xxdh_psa_privkey; uint8_t xxdh_psa_privkey_is_external; unsigned char xxdh_psa_peerkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; size_t xxdh_psa_peerkey_len; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_pake_operation_t psa_pake_ctx; /*!< EC J-PAKE key exchange */ mbedtls_svc_key_id_t psa_pake_password; uint8_t psa_pake_ctx_is_ok; #else mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ size_t ecjpake_cache_len; /*!< Length of cached data */ #endif #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) uint16_t *curves_tls_id; /*!< List of TLS IDs of supported elliptic curves */ #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ uint8_t psk_opaque_is_internal; #else unsigned char *psk; /*!< PSK from the callback */ size_t psk_len; /*!< Length of PSK from callback */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ uint16_t selected_identity; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ struct { size_t total_bytes_buffered; /*!< Cumulative size of heap allocated * buffers used for message buffering. */ uint8_t seen_ccs; /*!< Indicates if a CCS message has * been seen in the current flight. */ struct mbedtls_ssl_hs_buffer { unsigned is_valid : 1; unsigned is_fragmented : 1; unsigned is_complete : 1; unsigned char *data; size_t data_len; } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; struct { unsigned char *data; size_t len; unsigned epoch; } future_record; } buffering; #if defined(MBEDTLS_SSL_CLI_C) && \ (defined(MBEDTLS_SSL_PROTO_DTLS) || \ defined(MBEDTLS_SSL_PROTO_TLS1_3)) unsigned char *cookie; /*!< HelloVerifyRequest cookie for DTLS * HelloRetryRequest cookie for TLS 1.3 */ #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) /* RFC 6347 page 15 ... opaque cookie<0..2^8-1>; ... */ uint8_t cookie_len; #else /* RFC 8446 page 39 ... opaque cookie<0..2^16-1>; ... If TLS1_3 is enabled, the max length is 2^16 - 1 */ uint16_t cookie_len; /*!< DTLS: HelloVerifyRequest cookie length * TLS1_3: HelloRetryRequest cookie length */ #endif #endif /* MBEDTLS_SSL_CLI_C && ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_DTLS) unsigned char cookie_verify_result; /*!< Srv: flag for sending a cookie */ #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ uint32_t retransmit_timeout; /*!< Current value of timeout */ mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ unsigned char *cur_msg_p; /*!< Position in current message */ unsigned int in_flight_start_seq; /*!< Minimum message sequence in the flight being received */ mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for resending messages */ unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Alternative record epoch/counter for resending messages */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* The state of CID configuration in this handshake. */ uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension * has been negotiated. Possible values are * #MBEDTLS_SSL_CID_ENABLED and * #MBEDTLS_SSL_CID_DISABLED. */ unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; /*! The peer's CID */ uint8_t peer_cid_len; /*!< The length of * \c peer_cid. */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Checksum contexts */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_operation_t fin_sha256_psa; #else mbedtls_md_context_t fin_sha256; #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_operation_t fin_sha384_psa; #else mbedtls_md_context_t fin_sha384; #endif #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint16_t offered_group_id; /* The NamedGroup value for the group * that is being used for ephemeral * key exchange. * * On the client: Defaults to the first * entry in the client's group list, * but can be overwritten by the HRR. */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_CLI_C) uint8_t client_auth; /*!< used to check if CertificateRequest has been received from server side. If CertificateRequest has been received, Certificate and CertificateVerify should be sent to server */ #endif /* MBEDTLS_SSL_CLI_C */ /* * State-local variables used during the processing * of a specific handshake state. */ union { /* Outgoing Finished message */ struct { uint8_t preparation_done; /* Buffer holding digest of the handshake up to * but excluding the outgoing finished message. */ unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t digest_len; } finished_out; /* Incoming Finished message */ struct { uint8_t preparation_done; /* Buffer holding digest of the handshake up to but * excluding the peer's incoming finished message. */ unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t digest_len; } finished_in; } state_local; /* End of state-local variables. */ unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; /*!< random bytes */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; /*!< premaster secret */ size_t pmslen; /*!< premaster length */ #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) uint32_t sent_extensions; /*!< extensions sent by endpoint */ uint32_t received_extensions; /*!< extensions received by endpoint */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) unsigned char certificate_request_context_len; unsigned char *certificate_request_context; #endif /** TLS 1.3 transform for encrypted handshake messages. */ mbedtls_ssl_transform *transform_handshake; union { unsigned char early[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE]; unsigned char app[MBEDTLS_TLS1_3_MD_MAX_SIZE]; } tls13_master_secrets; mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets; #if defined(MBEDTLS_SSL_EARLY_DATA) /** TLS 1.3 transform for early data and handshake messages. */ mbedtls_ssl_transform *transform_earlydata; #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /** Asynchronous operation context. This field is meant for use by the * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, * mbedtls_ssl_config::f_async_decrypt_start, * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). * The library does not use it internally. */ void *user_async_ctx; #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const unsigned char *sni_name; /*!< raw SNI */ size_t sni_name_len; /*!< raw SNI len */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) const mbedtls_x509_crt *dn_hints; /*!< acceptable client cert issuers */ #endif #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ }; typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; /* * Representation of decryption/encryption transformations on records * * There are the following general types of record transformations: * - Stream transformations (TLS versions == 1.2 only) * Transformation adding a MAC and applying a stream-cipher * to the authenticated message. * - CBC block cipher transformations ([D]TLS versions == 1.2 only) * For TLS 1.2, no IV is generated at key extraction time, but every * encrypted record is explicitly prefixed by the IV with which it was * encrypted. * - AEAD transformations ([D]TLS versions == 1.2 only) * These come in two fundamentally different versions, the first one * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. * In the first transformation, the IV to be used for a record is obtained * as the concatenation of an explicit, static 4-byte IV and the 8-byte * record sequence number, and explicitly prepending this sequence number * to the encrypted record. In contrast, in the second transformation * the IV is obtained by XOR'ing a static IV obtained at key extraction * time with the 8-byte record sequence number, without prepending the * latter to the encrypted record. * * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext * which allows to add flexible length padding and to hide a record's true * content type. * * In addition to type and version, the following parameters are relevant: * - The symmetric cipher algorithm to be used. * - The (static) encryption/decryption keys for the cipher. * - For stream/CBC, the type of message digest to be used. * - For stream/CBC, (static) encryption/decryption keys for the digest. * - For AEAD transformations, the size (potentially 0) of an explicit, * random initialization vector placed in encrypted records. * - For some transformations (currently AEAD) an implicit IV. It is static * and (if present) is combined with the explicit IV in a transformation- * -dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). * - For stream/CBC, a flag determining the order of encryption and MAC. * - The details of the transformation depend on the SSL/TLS version. * - The length of the authentication tag. * * The struct below refines this abstract view as follows: * - The cipher underlying the transformation is managed in * cipher contexts cipher_ctx_{enc/dec}, which must have the * same cipher type. The mode of these cipher contexts determines * the type of the transformation in the sense above: e.g., if * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM * then the transformation has type CBC resp. AEAD. * - The cipher keys are never stored explicitly but * are maintained within cipher_ctx_{enc/dec}. * - For stream/CBC transformations, the message digest contexts * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts * are unused for AEAD transformations. * - For stream/CBC transformations, the MAC keys are not stored explicitly * but maintained within md_ctx_{enc/dec}. * - The mac_enc and mac_dec fields are unused for EAD transformations. * - For transformations using an implicit IV maintained within * the transformation context, its contents are stored within * iv_{enc/dec}. * - The value of ivlen indicates the length of the IV. * This is redundant in case of stream/CBC transformations * which always use 0 resp. the cipher's block length as the * IV length, but is needed for AEAD ciphers and may be * different from the underlying cipher's block length * in this case. * - The field fixed_ivlen is nonzero for AEAD transformations only * and indicates the length of the static part of the IV which is * constant throughout the communication, and which is stored in * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. * - tls_version denotes the 2-byte TLS version * - For stream/CBC transformations, maclen denotes the length of the * authentication tag, while taglen is unused and 0. * - For AEAD transformations, taglen denotes the length of the * authentication tag, while maclen is unused and 0. * - For CBC transformations, encrypt_then_mac determines the * order of encryption and authentication. This field is unused * in other transformations. * */ struct mbedtls_ssl_transform { /* * Session specific crypto layer */ size_t minlen; /*!< min. ciphertext length */ size_t ivlen; /*!< IV length */ size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ size_t maclen; /*!< MAC(CBC) len */ size_t taglen; /*!< TAG(AEAD) len */ unsigned char iv_enc[16]; /*!< IV (encryption) */ unsigned char iv_dec[16]; /*!< IV (decryption) */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t psa_mac_enc; /*!< MAC (encryption) */ mbedtls_svc_key_id_t psa_mac_dec; /*!< MAC (decryption) */ psa_algorithm_t psa_mac_alg; /*!< psa MAC algorithm */ #else mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) int encrypt_then_mac; /*!< flag for EtM activation */ #endif #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ mbedtls_ssl_protocol_version tls_version; #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_svc_key_id_t psa_key_enc; /*!< psa encryption key */ mbedtls_svc_key_id_t psa_key_dec; /*!< psa decryption key */ psa_algorithm_t psa_alg; /*!< psa algorithm */ #else mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) uint8_t in_cid_len; uint8_t out_cid_len; unsigned char in_cid[MBEDTLS_SSL_CID_IN_LEN_MAX]; unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /* We need the Hello random bytes in order to re-derive keys from the * Master Secret and other session info, * see ssl_tls12_populate_transform() */ unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; /*!< ServerHello.random+ClientHello.random */ #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ }; /* * Return 1 if the transform uses an AEAD cipher, 0 otherwise. * Equivalently, return 0 if a separate MAC is used, 1 otherwise. */ static inline int mbedtls_ssl_transform_uses_aead( const mbedtls_ssl_transform *transform) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) return transform->maclen == 0 && transform->taglen != 0; #else (void) transform; return 1; #endif } /* * Internal representation of record frames * * Instances come in two flavors: * (1) Encrypted * These always have data_offset = 0 * (2) Unencrypted * These have data_offset set to the amount of * pre-expansion during record protection. Concretely, * this is the length of the fixed part of the explicit IV * used for encryption, or 0 if no explicit IV is used * (e.g. for stream ciphers). * * The reason for the data_offset in the unencrypted case * is to allow for in-place conversion of an unencrypted to * an encrypted record. If the offset wasn't included, the * encrypted content would need to be shifted afterwards to * make space for the fixed IV. * */ #if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX #define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX #else #define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX #endif typedef struct { uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /* In TLS: The implicit record sequence number. * In DTLS: The 2-byte epoch followed by * the 6-byte sequence number. * This is stored as a raw big endian byte array * as opposed to a uint64_t because we rarely * need to perform arithmetic on this, but do * need it as a Byte array for the purpose of * MAC computations. */ uint8_t type; /* The record content type. */ uint8_t ver[2]; /* SSL/TLS version as present on the wire. * Convert to internal presentation of versions * using mbedtls_ssl_read_version() and * mbedtls_ssl_write_version(). * Keep wire-format for MAC computations. */ unsigned char *buf; /* Memory buffer enclosing the record content */ size_t buf_len; /* Buffer length */ size_t data_offset; /* Offset of record content */ size_t data_len; /* Length of record content */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) uint8_t cid_len; /* Length of the CID (0 if not present) */ unsigned char cid[MBEDTLS_SSL_CID_LEN_MAX]; /* The CID */ #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ } mbedtls_record; #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * List of certificate + private key pairs */ struct mbedtls_ssl_key_cert { mbedtls_x509_crt *cert; /*!< cert */ mbedtls_pk_context *key; /*!< private key */ mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ }; #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_PROTO_DTLS) /* * List of handshake messages kept around for resending */ struct mbedtls_ssl_flight_item { unsigned char *p; /*!< message, including handshake headers */ size_t len; /*!< length of p */ unsigned char type; /*!< type of the message: handshake or CCS */ mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ }; #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.2 specific extensions of the ClientHello message. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the extensions * \param[in] end End address of the buffer where to write the extensions * \param uses_ec Whether one proposed ciphersuite uses an elliptic curve * (<> 0) or not ( 0 ). * \param[out] out_len Length of the data written into the buffer \p buf */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, int uses_ec, size_t *out_len); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /** * \brief Find the preferred hash for a given signature algorithm. * * \param[in] ssl SSL context * \param[in] sig_alg A signature algorithm identifier as defined in the * TLS 1.2 SignatureAlgorithm enumeration. * * \return The preferred hash algorithm for \p sig_alg. It is a hash algorithm * identifier as defined in the TLS 1.2 HashAlgorithm enumeration. */ unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( mbedtls_ssl_context *ssl, unsigned int sig_alg); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /** * \brief Free referenced items in an SSL transform context and clear * memory * * \param transform SSL transform context */ void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform); /** * \brief Free referenced items in an SSL handshake context and clear * memory * * \param ssl SSL context */ void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl); /* set inbound transform of ssl context */ void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform); /* set outbound transform of ssl context */ void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl); void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl); static inline void mbedtls_ssl_handshake_set_state(mbedtls_ssl_context *ssl, mbedtls_ssl_states state) { ssl->state = (int) state; } MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl); /** * \brief Update record layer * * This function roughly separates the implementation * of the logic of (D)TLS from the implementation * of the secure transport. * * \param ssl The SSL context to use. * \param update_hs_digest This indicates if the handshake digest * should be automatically updated in case * a handshake message is found. * * \return 0 or non-zero error code. * * \note A clarification on what is called 'record layer' here * is in order, as many sensible definitions are possible: * * The record layer takes as input an untrusted underlying * transport (stream or datagram) and transforms it into * a serially multiplexed, secure transport, which * conceptually provides the following: * * (1) Three datagram based, content-agnostic transports * for handshake, alert and CCS messages. * (2) One stream- or datagram-based transport * for application data. * (3) Functionality for changing the underlying transform * securing the contents. * * The interface to this functionality is given as follows: * * a Updating * [Currently implemented by mbedtls_ssl_read_record] * * Check if and on which of the four 'ports' data is pending: * Nothing, a controlling datagram of type (1), or application * data (2). In any case data is present, internal buffers * provide access to the data for the user to process it. * Consumption of type (1) datagrams is done automatically * on the next update, invalidating that the internal buffers * for previous datagrams, while consumption of application * data (2) is user-controlled. * * b Reading of application data * [Currently manual adaption of ssl->in_offt pointer] * * As mentioned in the last paragraph, consumption of data * is different from the automatic consumption of control * datagrams (1) because application data is treated as a stream. * * c Tracking availability of application data * [Currently manually through decreasing ssl->in_msglen] * * For efficiency and to retain datagram semantics for * application data in case of DTLS, the record layer * provides functionality for checking how much application * data is still available in the internal buffer. * * d Changing the transformation securing the communication. * * Given an opaque implementation of the record layer in the * above sense, it should be possible to implement the logic * of (D)TLS on top of it without the need to know anything * about the record layer's internals. This is done e.g. * in all the handshake handling functions, and in the * application data reading function mbedtls_ssl_read. * * \note The above tries to give a conceptual picture of the * record layer, but the current implementation deviates * from it in some places. For example, our implementation of * the update functionality through mbedtls_ssl_read_record * discards datagrams depending on the current state, which * wouldn't fall under the record layer's responsibility * following the above definition. * */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, unsigned update_hs_digest); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want); /* * Write handshake message header */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type, unsigned char **buf, size_t *buf_len); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, int update_checksum, int force_flush); static inline int mbedtls_ssl_write_handshake_msg(mbedtls_ssl_context *ssl) { return mbedtls_ssl_write_handshake_msg_ext(ssl, 1 /* update checksum */, 1 /* force flush */); } /* * Write handshake message tail */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, size_t buf_len, size_t msg_len); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl); void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info); /* * Update checksum of handshake messages. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char const *msg, size_t msg_len); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, size_t total_hs_len); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) #if !defined(MBEDTLS_USE_PSA_CRYPTO) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex); #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_SSL_CLI_C) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf); #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) /** * Get the first defined opaque PSK by order of precedence: * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK * callback * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() * Return an opaque PSK */ static inline mbedtls_svc_key_id_t mbedtls_ssl_get_opaque_psk( const mbedtls_ssl_context *ssl) { if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { return ssl->handshake->psk_opaque; } if (!mbedtls_svc_key_id_is_null(ssl->conf->psk_opaque)) { return ssl->conf->psk_opaque; } return MBEDTLS_SVC_KEY_ID_INIT; } #else /** * Get the first defined PSK by order of precedence: * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback * 2. static PSK configured by \c mbedtls_ssl_conf_psk() * Return a code and update the pair (PSK, PSK length) passed to this function */ static inline int mbedtls_ssl_get_psk(const mbedtls_ssl_context *ssl, const unsigned char **psk, size_t *psk_len) { if (ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0) { *psk = ssl->handshake->psk; *psk_len = ssl->handshake->psk_len; } else if (ssl->conf->psk != NULL && ssl->conf->psk_len > 0) { *psk = ssl->conf->psk; *psk_len = ssl->conf->psk_len; } else { *psk = NULL; *psk_len = 0; return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_PK_C) unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk); unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type); mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig); #endif mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash); unsigned char mbedtls_ssl_hash_from_md_alg(int md); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md); #endif MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id); #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id); #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /** * \brief Return PSA EC info for the specified TLS ID. * * \param tls_id The TLS ID to look for * \param type If the TLD ID is supported, then proper \c psa_key_type_t * value is returned here. Can be NULL. * \param bits If the TLD ID is supported, then proper bit size is returned * here. Can be NULL. * \return PSA_SUCCESS if the TLS ID is supported, * PSA_ERROR_NOT_SUPPORTED otherwise * * \note If either \c family or \c bits parameters are NULL, then * the corresponding value is not returned. * The function can be called with both parameters as NULL * simply to check if a specific TLS ID is supported. */ int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, psa_key_type_t *type, size_t *bits); /** * \brief Return \c mbedtls_ecp_group_id for the specified TLS ID. * * \param tls_id The TLS ID to look for * \return Proper \c mbedtls_ecp_group_id if the TLS ID is supported, * or MBEDTLS_ECP_DP_NONE otherwise */ mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id); /** * \brief Return TLS ID for the specified \c mbedtls_ecp_group_id. * * \param grp_id The \c mbedtls_ecp_group_id ID to look for * \return Proper TLS ID if the \c mbedtls_ecp_group_id is supported, * or 0 otherwise */ uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id); #if defined(MBEDTLS_DEBUG_C) /** * \brief Return EC's name for the specified TLS ID. * * \param tls_id The TLS ID to look for * \return A pointer to a const string with the proper name. If TLS * ID is not supported, a NULL pointer is returned instead. */ const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id); #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value (const uint16_t srtp_profile_value) { switch (srtp_profile_value) { case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: return srtp_profile_value; default: break; } return MBEDTLS_TLS_SRTP_UNSET; } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) static inline mbedtls_pk_context *mbedtls_ssl_own_key(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert; if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { key_cert = ssl->handshake->key_cert; } else { key_cert = ssl->conf->key_cert; } return key_cert == NULL ? NULL : key_cert->key; } static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert; if (ssl->handshake != NULL && ssl->handshake->key_cert != NULL) { key_cert = ssl->handshake->key_cert; } else { key_cert = ssl->conf->key_cert; } return key_cert == NULL ? NULL : key_cert->cert; } /* * Check usage of a certificate wrt extensions: * keyUsage, extendedKeyUsage (later), and nSCertType (later). * * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we * check a cert we received from them)! * * Return 0 if everything is OK, -1 if not. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, const mbedtls_ssl_ciphersuite_t *ciphersuite, int cert_endpoint, uint32_t *flags); #endif /* MBEDTLS_X509_CRT_PARSE_C */ void mbedtls_ssl_write_version(unsigned char version[2], int transport, mbedtls_ssl_protocol_version tls_version); uint16_t mbedtls_ssl_read_version(const unsigned char version[2], int transport); static inline size_t mbedtls_ssl_in_hdr_len(const mbedtls_ssl_context *ssl) { #if !defined(MBEDTLS_SSL_PROTO_DTLS) ((void) ssl); #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 13; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { return 5; } } static inline size_t mbedtls_ssl_out_hdr_len(const mbedtls_ssl_context *ssl) { return (size_t) (ssl->out_iv - ssl->out_hdr); } static inline size_t mbedtls_ssl_hs_hdr_len(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 12; } #else ((void) ssl); #endif return 4; } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl); void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_resend(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl); #endif /* Visible for testing purposes only */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl); void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl); #endif MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #ifdef __cplusplus } #endif void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec); /* Length of the "epoch" field in the record header */ static inline size_t mbedtls_ssl_ep_len(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 2; } #else ((void) ssl); #endif return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_PROTO_DTLS */ void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl); void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl); void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform); void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial); void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, int partial); /* * Send pending alert */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl); /* * Set pending fatal alert flag. */ void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, unsigned char alert_type, int alert_reason); /* Alias of mbedtls_ssl_pend_fatal_alert */ #define MBEDTLS_SSL_PEND_FATAL_ALERT(type, user_return_value) \ mbedtls_ssl_pend_fatal_alert(ssl, type, user_return_value) #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl); #endif void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl); void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl); void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight); #endif /* MBEDTLS_SSL_PROTO_DTLS */ /** * ssl utils functions for checking configuration. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) static inline int mbedtls_ssl_conf_is_tls13_only(const mbedtls_ssl_config *conf) { return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static inline int mbedtls_ssl_conf_is_tls12_only(const mbedtls_ssl_config *conf) { return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_2; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ static inline int mbedtls_ssl_conf_is_tls13_enabled(const mbedtls_ssl_config *conf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_3 && conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3; #else ((void) conf); return 0; #endif } static inline int mbedtls_ssl_conf_is_tls12_enabled(const mbedtls_ssl_config *conf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) return conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 && conf->max_tls_version >= MBEDTLS_SSL_VERSION_TLS1_2; #else ((void) conf); return 0; #endif } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_config *conf) { return conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ MBEDTLS_SERVER_HELLO_RANDOM_LEN]; MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl); void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl); /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.3 specific extensions of the ClientHello message. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the extensions * \param[in] end End address of the buffer where to write the extensions * \param[out] out_len Length of the data written into the buffer \p buf */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len); /** * \brief TLS 1.3 client side state machine entry * * \param ssl SSL context */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl); /** * \brief TLS 1.3 server side state machine entry * * \param ssl SSL context */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl); /* * Helper functions around key exchange modes. */ static inline int mbedtls_ssl_conf_tls13_is_kex_mode_enabled(mbedtls_ssl_context *ssl, int kex_mode_mask) { return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0; } static inline int mbedtls_ssl_conf_tls13_is_psk_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); } static inline int mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); } static inline int mbedtls_ssl_conf_tls13_is_ephemeral_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); } static inline int mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); } static inline int mbedtls_ssl_conf_tls13_is_some_psk_enabled(mbedtls_ssl_context *ssl) { return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); } #if defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /** * Given a list of key exchange modes, check if at least one of them is * supported by peer. * * \param[in] ssl SSL context * \param kex_modes_mask Mask of the key exchange modes to check * * \return Non-zero if at least one of the key exchange modes is supported by * the peer, otherwise \c 0. */ static inline int mbedtls_ssl_tls13_is_kex_mode_supported(mbedtls_ssl_context *ssl, int kex_modes_mask) { return (ssl->handshake->tls13_kex_modes & kex_modes_mask) != 0; } static inline int mbedtls_ssl_tls13_is_psk_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK); } static inline int mbedtls_ssl_tls13_is_psk_ephemeral_supported( mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL); } static inline int mbedtls_ssl_tls13_is_ephemeral_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL); } static inline int mbedtls_ssl_tls13_is_some_ephemeral_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); } static inline int mbedtls_ssl_tls13_is_some_psk_supported(mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_is_kex_mode_supported(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ /* * Helper functions for extensions checking. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_check_received_extension( mbedtls_ssl_context *ssl, int hs_msg_type, unsigned int received_extension_type, uint32_t hs_msg_allowed_extensions_mask); static inline void mbedtls_ssl_tls13_set_hs_sent_ext_mask( mbedtls_ssl_context *ssl, unsigned int extension_type) { ssl->handshake->sent_extensions |= mbedtls_ssl_get_extension_mask(extension_type); } /* * Helper functions to check the selected key exchange mode. */ static inline int mbedtls_ssl_tls13_key_exchange_mode_check( mbedtls_ssl_context *ssl, int kex_mask) { return (ssl->handshake->key_exchange_mode & kex_mask) != 0; } static inline int mbedtls_ssl_tls13_key_exchange_mode_with_psk( mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL); } static inline int mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral( mbedtls_ssl_context *ssl) { return mbedtls_ssl_tls13_key_exchange_mode_check(ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL); } /* * Fetch TLS 1.3 handshake message header */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char **buf, size_t *buf_len); /** * \brief Detect if a list of extensions contains a supported_versions * extension or not. * * \param[in] ssl SSL context * \param[in] buf Address of the first byte of the extensions vector. * \param[in] end End of the buffer containing the list of extensions. * \param[out] supported_versions_data If the extension is present, address of * its first byte of data, NULL otherwise. * \param[out] supported_versions_data_end If the extension is present, address * of the first byte immediately * following the extension data, NULL * otherwise. * \return 0 if the list of extensions does not contain a supported_versions * extension. * \return 1 if the list of extensions contains a supported_versions * extension. * \return A negative value if an error occurred while parsing the * extensions. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, const unsigned char **supported_versions_data, const unsigned char **supported_versions_data_end); /* * Handler of TLS 1.3 server certificate message */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * Handler of TLS 1.3 write Certificate message */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl); /* * Handler of TLS 1.3 write Certificate Verify message */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Generic handler of Certificate Verify */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl); /* * Write of dummy-CCS's for middlebox compatibility */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl); #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( mbedtls_ssl_context *ssl, uint16_t named_group, unsigned char *buf, unsigned char *end, size_t *out_len); #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ #if defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, int in_new_session_ticket, unsigned char *buf, const unsigned char *end, size_t *out_len); int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl, size_t early_data_len); typedef enum { /* * The client has not sent the first ClientHello yet, the negotiation of early * data has not started yet. */ MBEDTLS_SSL_EARLY_DATA_STATE_IDLE, /* * In its ClientHello, the client has not included an early data indication * extension. */ MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT, /* * The client has sent an early data indication extension in its first * ClientHello, it has not received the response (ServerHello or * HelloRetryRequest) from the server yet. The transform to protect early data * is not set either as for middlebox compatibility a dummy CCS may have to be * sent in clear. Early data cannot be sent to the server yet. */ MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT, /* * The client has sent an early data indication extension in its first * ClientHello, it has not received the response (ServerHello or * HelloRetryRequest) from the server yet. The transform to protect early data * has been set and early data can be written now. */ MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, /* * The client has indicated the use of early data and the server has accepted * it. */ MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED, /* * The client has indicated the use of early data but the server has rejected * it. */ MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED, /* * The client has sent an early data indication extension in its first * ClientHello, the server has accepted them and the client has received the * server Finished message. It cannot send early data to the server anymore. */ MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED, } mbedtls_ssl_early_data_state; #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* * Write Signature Algorithm extension */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len); /* * Parse TLS Signature Algorithm extension */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* Get handshake transcript */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, const mbedtls_md_type_t md, unsigned char *dst, size_t dst_len, size_t *olen); /* * Return supported groups. * * In future, invocations can be changed to ssl->conf->group_list * when mbedtls_ssl_conf_curves() is deleted. * * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked. * */ static inline const void *mbedtls_ssl_get_groups(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C) return ssl->conf->group_list; #else if ((ssl->handshake != NULL) && (ssl->handshake->group_list != NULL)) { return ssl->handshake->group_list; } else { return ssl->conf->group_list; } #endif } /* * Helper functions for NamedGroup. */ static inline int mbedtls_ssl_tls12_named_group_is_ecdhe(uint16_t named_group) { /* * RFC 8422 section 5.1.1 */ return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448 || /* Below deprecated curves should be removed with notice to users */ named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1; } static inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group) { return named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 || named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448; } static inline int mbedtls_ssl_tls13_named_group_is_ffdh(uint16_t named_group) { return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 && named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192; } static inline int mbedtls_ssl_named_group_is_offered( const mbedtls_ssl_context *ssl, uint16_t named_group) { const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); if (group_list == NULL) { return 0; } for (; *group_list != 0; group_list++) { if (*group_list == named_group) { return 1; } } return 0; } static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) { if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) != MBEDTLS_ECP_DP_NONE) { return 1; } } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) { return 1; } #endif #if !defined(PSA_WANT_ALG_ECDH) && !defined(PSA_WANT_ALG_FFDH) (void) named_group; #endif return 0; } /* * Return supported signature algorithms. * * In future, invocations can be changed to ssl->conf->sig_algs when * mbedtls_ssl_conf_sig_hashes() is deleted. * * ssl->handshake->sig_algs is either a translation of sig_hashes to IANA TLS * signature algorithm identifiers when mbedtls_ssl_conf_sig_hashes() has been * used, or a pointer to ssl->conf->sig_algs when mbedtls_ssl_conf_sig_algs() has * been more recently invoked. * */ static inline const void *mbedtls_ssl_get_sig_algs( const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) if (ssl->handshake != NULL && ssl->handshake->sig_algs_heap_allocated == 1 && ssl->handshake->sig_algs != NULL) { return ssl->handshake->sig_algs; } #endif return ssl->conf->sig_algs; #else /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ ((void) ssl); return NULL; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) static inline int mbedtls_ssl_sig_alg_is_received(const mbedtls_ssl_context *ssl, uint16_t own_sig_alg) { const uint16_t *sig_alg = ssl->handshake->received_sig_algs; if (sig_alg == NULL) { return 0; } for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { if (*sig_alg == own_sig_alg) { return 1; } } return 0; } static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( const uint16_t sig_alg) { switch (sig_alg) { #if defined(MBEDTLS_PK_CAN_ECDSA_SOME) #if defined(PSA_WANT_ALG_SHA_256) && defined(PSA_WANT_ECC_SECP_R1_256) case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: break; #endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(PSA_WANT_ALG_SHA_384) && defined(PSA_WANT_ECC_SECP_R1_384) case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: break; #endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(PSA_WANT_ALG_SHA_512) && defined(PSA_WANT_ECC_SECP_R1_521) case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: break; #endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ #if defined(MBEDTLS_PKCS1_V21) #if defined(PSA_WANT_ALG_SHA_256) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: break; #endif /* PSA_WANT_ALG_SHA_256 */ #if defined(PSA_WANT_ALG_SHA_384) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: break; #endif /* PSA_WANT_ALG_SHA_384 */ #if defined(PSA_WANT_ALG_SHA_512) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: break; #endif /* PSA_WANT_ALG_SHA_512 */ #endif /* MBEDTLS_PKCS1_V21 */ default: return 0; } return 1; } static inline int mbedtls_ssl_tls13_sig_alg_is_supported( const uint16_t sig_alg) { switch (sig_alg) { #if defined(MBEDTLS_PKCS1_V15) #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: break; #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: break; #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: break; #endif /* MBEDTLS_MD_CAN_SHA512 */ #endif /* MBEDTLS_PKCS1_V15 */ default: return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported( sig_alg); } return 1; } MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, mbedtls_pk_context *key); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) static inline int mbedtls_ssl_sig_alg_is_offered(const mbedtls_ssl_context *ssl, uint16_t proposed_sig_alg) { const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); if (sig_alg == NULL) { return 0; } for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { if (*sig_alg == proposed_sig_alg) { return 1; } } return 0; } static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( uint16_t sig_alg, mbedtls_pk_type_t *pk_type, mbedtls_md_type_t *md_alg) { *pk_type = mbedtls_ssl_pk_alg_from_sig(sig_alg & 0xff); *md_alg = mbedtls_ssl_md_alg_from_hash((sig_alg >> 8) & 0xff); if (*pk_type != MBEDTLS_PK_NONE && *md_alg != MBEDTLS_MD_NONE) { return 0; } switch (sig_alg) { #if defined(MBEDTLS_PKCS1_V21) #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: *md_alg = MBEDTLS_MD_SHA256; *pk_type = MBEDTLS_PK_RSASSA_PSS; break; #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: *md_alg = MBEDTLS_MD_SHA384; *pk_type = MBEDTLS_PK_RSASSA_PSS; break; #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: *md_alg = MBEDTLS_MD_SHA512; *pk_type = MBEDTLS_PK_RSASSA_PSS; break; #endif /* MBEDTLS_MD_CAN_SHA512 */ #endif /* MBEDTLS_PKCS1_V21 */ default: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return 0; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static inline int mbedtls_ssl_tls12_sig_alg_is_supported( const uint16_t sig_alg) { /* High byte is hash */ unsigned char hash = MBEDTLS_BYTE_1(sig_alg); unsigned char sig = MBEDTLS_BYTE_0(sig_alg); switch (hash) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_SSL_HASH_MD5: break; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_SSL_HASH_SHA1: break; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_SSL_HASH_SHA224: break; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_HASH_SHA256: break; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_HASH_SHA384: break; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_SSL_HASH_SHA512: break; #endif default: return 0; } switch (sig) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_SSL_SIG_RSA: break; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) case MBEDTLS_SSL_SIG_ECDSA: break; #endif default: return 0; } return 1; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ static inline int mbedtls_ssl_sig_alg_is_supported( const mbedtls_ssl_context *ssl, const uint16_t sig_alg) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { return mbedtls_ssl_tls12_sig_alg_is_supported(sig_alg); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { return mbedtls_ssl_tls13_sig_alg_is_supported(sig_alg); } #endif ((void) ssl); ((void) sig_alg); return 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Corresponding PSA algorithm for MBEDTLS_CIPHER_NULL. * Same value is used for PSA_ALG_CATEGORY_CIPHER, hence it is * guaranteed to not be a valid PSA algorithm identifier. */ #define MBEDTLS_SSL_NULL_CIPHER 0x04000000 /** * \brief Translate mbedtls cipher type/taglen pair to psa: * algorithm, key type and key size. * * \param mbedtls_cipher_type [in] given mbedtls cipher type * \param taglen [in] given tag length * 0 - default tag length * \param alg [out] corresponding PSA alg * There is no corresponding PSA * alg for MBEDTLS_CIPHER_NULL, so * in this case MBEDTLS_SSL_NULL_CIPHER * is returned via this parameter * \param key_type [out] corresponding PSA key type * \param key_size [out] corresponding PSA key size * * \return PSA_SUCCESS on success or PSA_ERROR_NOT_SUPPORTED if * conversion is not supported. */ psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, size_t taglen, psa_algorithm_t *alg, psa_key_type_t *key_type, size_t *key_size); #if !defined(MBEDTLS_DEPRECATED_REMOVED) /** * \brief Convert given PSA status to mbedtls error code. * * \param status [in] given PSA status * * \return corresponding mbedtls error code */ static inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status) { switch (status) { case PSA_SUCCESS: return 0; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_SSL_ALLOC_FAILED; case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; case PSA_ERROR_INVALID_SIGNATURE: return MBEDTLS_ERR_SSL_INVALID_MAC; case PSA_ERROR_INVALID_ARGUMENT: return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; case PSA_ERROR_BAD_STATE: return MBEDTLS_ERR_SSL_INTERNAL_ERROR; case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; default: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) typedef enum { MBEDTLS_ECJPAKE_ROUND_ONE, MBEDTLS_ECJPAKE_ROUND_TWO } mbedtls_ecjpake_rounds_t; /** * \brief Parse the provided input buffer for getting the first round * of key exchange. This code is common between server and client * * \param pake_ctx [in] the PAKE's operation/context structure * \param buf [in] input buffer to parse * \param len [in] length of the input buffer * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or * MBEDTLS_ECJPAKE_ROUND_TWO * * \return 0 on success or a negative error code in case of failure */ int mbedtls_psa_ecjpake_read_round( psa_pake_operation_t *pake_ctx, const unsigned char *buf, size_t len, mbedtls_ecjpake_rounds_t round); /** * \brief Write the first round of key exchange into the provided output * buffer. This code is common between server and client * * \param pake_ctx [in] the PAKE's operation/context structure * \param buf [out] the output buffer in which data will be written to * \param len [in] length of the output buffer * \param olen [out] the length of the data really written on the buffer * \param round [in] either MBEDTLS_ECJPAKE_ROUND_ONE or * MBEDTLS_ECJPAKE_ROUND_TWO * * \return 0 on success or a negative error code in case of failure */ int mbedtls_psa_ecjpake_write_round( psa_pake_operation_t *pake_ctx, unsigned char *buf, size_t len, size_t *olen, mbedtls_ecjpake_rounds_t round); #endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO /** * \brief TLS record protection modes */ typedef enum { MBEDTLS_SSL_MODE_STREAM = 0, MBEDTLS_SSL_MODE_CBC, MBEDTLS_SSL_MODE_CBC_ETM, MBEDTLS_SSL_MODE_AEAD } mbedtls_ssl_mode_t; mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( const mbedtls_ssl_transform *transform); #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( int encrypt_then_mac, const mbedtls_ssl_ciphersuite_t *suite); #else mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( const mbedtls_ssl_ciphersuite_t *suite); #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t buf_len); #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ static inline int mbedtls_ssl_tls13_cipher_suite_is_offered( mbedtls_ssl_context *ssl, int cipher_suite) { const int *ciphersuite_list = ssl->conf->ciphersuite_list; /* Check whether we have offered this ciphersuite */ for (size_t i = 0; ciphersuite_list[i] != 0; i++) { if (ciphersuite_list[i] == cipher_suite) { return 1; } } return 0; } /** * \brief Validate cipher suite against config in SSL context. * * \param ssl SSL context * \param suite_info Cipher suite to validate * \param min_tls_version Minimal TLS version to accept a cipher suite * \param max_tls_version Maximal TLS version to accept a cipher suite * * \return 0 if valid, negative value otherwise. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_validate_ciphersuite( const mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *suite_info, mbedtls_ssl_protocol_version min_tls_version, mbedtls_ssl_protocol_version max_tls_version); #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) #define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2) #define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64) /* As defined in RFC 8449 */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len); #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len); #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_TEST_HOOKS) int mbedtls_ssl_check_dtls_clihlo_cookie( mbedtls_ssl_context *ssl, const unsigned char *cli_id, size_t cli_id_len, const unsigned char *in, size_t in_len, unsigned char *obuf, size_t buf_len, size_t *olen); #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.3 specific Pre-Shared key extension. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the extension * \param[in] end End address of the buffer where to write the extension * \param[out] out_len Length in bytes of the Pre-Shared key extension: data * written into the buffer \p buf by this function plus * the length of the binders to be written. * \param[out] binders_len Length of the binders to be written at the end of * the extension. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, size_t *binders_len); /** * \brief Given an SSL context and its associated configuration, write the TLS * 1.3 specific Pre-Shared key extension binders at the end of the * ClientHello. * * \param[in] ssl SSL context * \param[in] buf Base address of the buffer where to write the binders * \param[in] end End address of the buffer where to write the binders */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end); #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ defined(MBEDTLS_SSL_CLI_C) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, const char *hostname); #endif #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \ defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session, const char *alpn); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800) static inline unsigned int mbedtls_ssl_tls13_session_get_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { return session->ticket_flags & (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); } /** * Check if at least one of the given flags is set in * the session ticket. See the definition of * `MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK` to get all * permitted flags. */ static inline int mbedtls_ssl_tls13_session_ticket_has_flags( mbedtls_ssl_session *session, unsigned int flags) { return mbedtls_ssl_tls13_session_get_ticket_flags(session, flags) != 0; } static inline int mbedtls_ssl_tls13_session_ticket_allow_psk( mbedtls_ssl_session *session) { return mbedtls_ssl_tls13_session_ticket_has_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION); } static inline int mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral( mbedtls_ssl_session *session) { return mbedtls_ssl_tls13_session_ticket_has_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION); } static inline unsigned int mbedtls_ssl_tls13_session_ticket_allow_early_data( mbedtls_ssl_session *session) { return mbedtls_ssl_tls13_session_ticket_has_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); } static inline void mbedtls_ssl_tls13_session_set_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); } static inline void mbedtls_ssl_tls13_session_clear_ticket_flags( mbedtls_ssl_session *session, unsigned int flags) { session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl); #endif #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) /** Compute the HMAC of variable-length data with constant flow. * * This function computes the HMAC of the concatenation of \p add_data and \p * data, and does with a code flow and memory access pattern that does not * depend on \p data_len_secret, but only on \p min_data_len and \p * max_data_len. In particular, this function always reads exactly \p * max_data_len bytes from \p data. * * \param ctx The HMAC context. It must have keys configured * with mbedtls_md_hmac_starts() and use one of the * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. * It is reset using mbedtls_md_hmac_reset() after * the computation is complete to prepare for the * next computation. * \param add_data The first part of the message whose HMAC is being * calculated. This must point to a readable buffer * of \p add_data_len bytes. * \param add_data_len The length of \p add_data in bytes. * \param data The buffer containing the second part of the * message. This must point to a readable buffer * of \p max_data_len bytes. * \param data_len_secret The length of the data to process in \p data. * This must be no less than \p min_data_len and no * greater than \p max_data_len. * \param min_data_len The minimal length of the second part of the * message, read from \p data. * \param max_data_len The maximal length of the second part of the * message, read from \p data. * \param output The HMAC will be written here. This must point to * a writable buffer of sufficient size to hold the * HMAC value. * * \retval 0 on success. * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED * The hardware accelerator failed. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, psa_algorithm_t mac_alg, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output); #else int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output); #endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ #endif /* MBEDTLS_TEST_HOOKS && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) */ #endif /* ssl_misc.h */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_msg.c000066400000000000000000006732721464416617300231700ustar00rootroot00000000000000/* * Generic SSL/TLS messaging layer functions * (record layer + retransmission state machine) * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * http://www.ietf.org/rfc/rfc2246.txt * http://www.ietf.org/rfc/rfc4346.txt */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/version.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa_util_internal.h" #include "psa/crypto.h" #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/oid.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(PSA_WANT_ALG_SHA_384) #define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384) #elif defined(PSA_WANT_ALG_SHA_256) #define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256) #else /* See check_config.h */ #define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1) #endif MBEDTLS_STATIC_TESTABLE int mbedtls_ct_hmac(mbedtls_svc_key_id_t key, psa_algorithm_t mac_alg, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output) { /* * This function breaks the HMAC abstraction and uses psa_hash_clone() * extension in order to get constant-flow behaviour. * * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means * concatenation, and okey/ikey are the XOR of the key with some fixed bit * patterns (see RFC 2104, sec. 2). * * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by * hashing up to minlen, then cloning the context, and for each byte up * to maxlen finishing up the hash computation, keeping only the * correct result. * * Then we only need to compute HASH(okey + inner_hash) and we're done. */ psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg); const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg); unsigned char key_buf[MAX_HASH_BLOCK_LENGTH]; const size_t hash_size = PSA_HASH_LENGTH(hash_alg); psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; size_t hash_length; unsigned char aux_out[PSA_HASH_MAX_SIZE]; psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT; size_t offset; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t mac_key_length; size_t i; #define PSA_CHK(func_call) \ do { \ status = (func_call); \ if (status != PSA_SUCCESS) \ goto cleanup; \ } while (0) /* Export MAC key * We assume key length is always exactly the output size * which is never more than the block size, thus we use block_size * as the key buffer size. */ PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length)); /* Calculate ikey */ for (i = 0; i < mac_key_length; i++) { key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36); } for (; i < block_size; ++i) { key_buf[i] = 0x36; } PSA_CHK(psa_hash_setup(&operation, hash_alg)); /* Now compute inner_hash = HASH(ikey + msg) */ PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); PSA_CHK(psa_hash_update(&operation, add_data, add_data_len)); PSA_CHK(psa_hash_update(&operation, data, min_data_len)); /* Fill the hash buffer in advance with something that is * not a valid hash (barring an attack on the hash and * deliberately-crafted input), in case the caller doesn't * check the return status properly. */ memset(output, '!', hash_size); /* For each possible length, compute the hash up to that point */ for (offset = min_data_len; offset <= max_data_len; offset++) { PSA_CHK(psa_hash_clone(&operation, &aux_operation)); PSA_CHK(psa_hash_finish(&aux_operation, aux_out, PSA_HASH_MAX_SIZE, &hash_length)); /* Keep only the correct inner_hash in the output buffer */ mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret), output, aux_out, NULL, hash_size); if (offset < max_data_len) { PSA_CHK(psa_hash_update(&operation, data + offset, 1)); } } /* Abort current operation to prepare for final operation */ PSA_CHK(psa_hash_abort(&operation)); /* Calculate okey */ for (i = 0; i < mac_key_length; i++) { key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C); } for (; i < block_size; ++i) { key_buf[i] = 0x5C; } /* Now compute HASH(okey + inner_hash) */ PSA_CHK(psa_hash_setup(&operation, hash_alg)); PSA_CHK(psa_hash_update(&operation, key_buf, block_size)); PSA_CHK(psa_hash_update(&operation, output, hash_size)); PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length)); #undef PSA_CHK cleanup: mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH); mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE); psa_hash_abort(&operation); psa_hash_abort(&aux_operation); return PSA_TO_MBEDTLS_ERR(status); } #undef MAX_HASH_BLOCK_LENGTH #else MBEDTLS_STATIC_TESTABLE int mbedtls_ct_hmac(mbedtls_md_context_t *ctx, const unsigned char *add_data, size_t add_data_len, const unsigned char *data, size_t data_len_secret, size_t min_data_len, size_t max_data_len, unsigned char *output) { /* * This function breaks the HMAC abstraction and uses the md_clone() * extension to the MD API in order to get constant-flow behaviour. * * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means * concatenation, and okey/ikey are the XOR of the key with some fixed bit * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. * * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to * minlen, then cloning the context, and for each byte up to maxlen * finishing up the hash computation, keeping only the correct result. * * Then we only need to compute HASH(okey + inner_hash) and we're done. */ const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info); /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5, * all of which have the same block size except SHA-384. */ const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; const unsigned char * const ikey = ctx->hmac_ctx; const unsigned char * const okey = ikey + block_size; const size_t hash_size = mbedtls_md_get_size(ctx->md_info); unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; mbedtls_md_context_t aux; size_t offset; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_init(&aux); #define MD_CHK(func_call) \ do { \ ret = (func_call); \ if (ret != 0) \ goto cleanup; \ } while (0) MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0)); /* After hmac_start() of hmac_reset(), ikey has already been hashed, * so we can start directly with the message */ MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len)); MD_CHK(mbedtls_md_update(ctx, data, min_data_len)); /* Fill the hash buffer in advance with something that is * not a valid hash (barring an attack on the hash and * deliberately-crafted input), in case the caller doesn't * check the return status properly. */ memset(output, '!', hash_size); /* For each possible length, compute the hash up to that point */ for (offset = min_data_len; offset <= max_data_len; offset++) { MD_CHK(mbedtls_md_clone(&aux, ctx)); MD_CHK(mbedtls_md_finish(&aux, aux_out)); /* Keep only the correct inner_hash in the output buffer */ mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret), output, aux_out, NULL, hash_size); if (offset < max_data_len) { MD_CHK(mbedtls_md_update(ctx, data + offset, 1)); } } /* The context needs to finish() before it starts() again */ MD_CHK(mbedtls_md_finish(ctx, aux_out)); /* Now compute HASH(okey + inner_hash) */ MD_CHK(mbedtls_md_starts(ctx)); MD_CHK(mbedtls_md_update(ctx, okey, block_size)); MD_CHK(mbedtls_md_update(ctx, output, hash_size)); MD_CHK(mbedtls_md_finish(ctx, output)); /* Done, get ready for next time */ MD_CHK(mbedtls_md_hmac_reset(ctx)); #undef MD_CHK cleanup: mbedtls_md_free(&aux); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl); /* * Start a timer. * Passing millisecs = 0 cancels a running timer. */ void mbedtls_ssl_set_timer(mbedtls_ssl_context *ssl, uint32_t millisecs) { if (ssl->f_set_timer == NULL) { return; } MBEDTLS_SSL_DEBUG_MSG(3, ("set_timer to %d ms", (int) millisecs)); ssl->f_set_timer(ssl->p_timer, millisecs / 4, millisecs); } /* * Return -1 is timer is expired, 0 if it isn't. */ int mbedtls_ssl_check_timer(mbedtls_ssl_context *ssl) { if (ssl->f_get_timer == NULL) { return 0; } if (ssl->f_get_timer(ssl->p_timer) == 2) { MBEDTLS_SSL_DEBUG_MSG(3, ("timer expired")); return -1; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t len, mbedtls_record *rec); int mbedtls_ssl_check_record(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t buflen) { int ret = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("=> mbedtls_ssl_check_record")); MBEDTLS_SSL_DEBUG_BUF(3, "record buffer", buf, buflen); /* We don't support record checking in TLS because * there doesn't seem to be a usecase for it. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM) { ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; goto exit; } #if defined(MBEDTLS_SSL_PROTO_DTLS) else { mbedtls_record rec; ret = ssl_parse_record_header(ssl, buf, buflen, &rec); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(3, "ssl_parse_record_header", ret); goto exit; } if (ssl->transform_in != NULL) { ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in, &rec); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(3, "mbedtls_ssl_decrypt_buf", ret); goto exit; } } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ exit: /* On success, we have decrypted the buffer in-place, so make * sure we don't leak any plaintext data. */ mbedtls_platform_zeroize(buf, buflen); /* For the purpose of this API, treat messages with unexpected CID * as well as such from future epochs as unexpected. */ if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) { ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } MBEDTLS_SSL_DEBUG_MSG(1, ("<= mbedtls_ssl_check_record")); return ret; } #define SSL_DONT_FORCE_FLUSH 0 #define SSL_FORCE_FLUSH 1 #if defined(MBEDTLS_SSL_PROTO_DTLS) /* Forward declarations for functions related to message buffering. */ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, uint8_t slot); static void ssl_free_buffered_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_future_record(mbedtls_ssl_context *ssl, mbedtls_record const *rec); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl); static size_t ssl_get_maximum_datagram_size(mbedtls_ssl_context const *ssl) { size_t mtu = mbedtls_ssl_get_current_mtu(ssl); #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len; #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif if (mtu != 0 && mtu < out_buf_len) { return mtu; } return out_buf_len; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_remaining_space_in_datagram(mbedtls_ssl_context const *ssl) { size_t const bytes_written = ssl->out_left; size_t const mtu = ssl_get_maximum_datagram_size(ssl); /* Double-check that the write-index hasn't gone * past what we can transmit in a single datagram. */ if (bytes_written > mtu) { /* Should never happen... */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return (int) (mtu - bytes_written); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_remaining_payload_in_datagram(mbedtls_ssl_context const *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t remaining, expansion; size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl); if (max_len > mfl) { max_len = mfl; } /* By the standard (RFC 6066 Sect. 4), the MFL extension * only limits the maximum record payload size, so in theory * we would be allowed to pack multiple records of payload size * MFL into a single datagram. However, this would mean that there's * no way to explicitly communicate MTU restrictions to the peer. * * The following reduction of max_len makes sure that we never * write datagrams larger than MFL + Record Expansion Overhead. */ if (max_len <= ssl->out_left) { return 0; } max_len -= ssl->out_left; #endif ret = ssl_get_remaining_space_in_datagram(ssl); if (ret < 0) { return ret; } remaining = (size_t) ret; ret = mbedtls_ssl_get_record_expansion(ssl); if (ret < 0) { return ret; } expansion = (size_t) ret; if (remaining <= expansion) { return 0; } remaining -= expansion; if (remaining >= max_len) { remaining = max_len; } return (int) remaining; } /* * Double the retransmit timeout value, within the allowed range, * returning -1 if the maximum value has already been reached. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_double_retransmit_timeout(mbedtls_ssl_context *ssl) { uint32_t new_timeout; if (ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max) { return -1; } /* Implement the final paragraph of RFC 6347 section 4.1.1.1 * in the following way: after the initial transmission and a first * retransmission, back off to a temporary estimated MTU of 508 bytes. * This value is guaranteed to be deliverable (if not guaranteed to be * delivered) of any compliant IPv4 (and IPv6) network, and should work * on most non-IP stacks too. */ if (ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min) { ssl->handshake->mtu = 508; MBEDTLS_SSL_DEBUG_MSG(2, ("mtu autoreduction to %d bytes", ssl->handshake->mtu)); } new_timeout = 2 * ssl->handshake->retransmit_timeout; /* Avoid arithmetic overflow and range overflow */ if (new_timeout < ssl->handshake->retransmit_timeout || new_timeout > ssl->conf->hs_timeout_max) { new_timeout = ssl->conf->hs_timeout_max; } ssl->handshake->retransmit_timeout = new_timeout; MBEDTLS_SSL_DEBUG_MSG(3, ("update timeout value to %lu millisecs", (unsigned long) ssl->handshake->retransmit_timeout)); return 0; } static void ssl_reset_retransmit_timeout(mbedtls_ssl_context *ssl) { ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; MBEDTLS_SSL_DEBUG_MSG(3, ("update timeout value to %lu millisecs", (unsigned long) ssl->handshake->retransmit_timeout)); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Encryption/decryption functions */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3) static size_t ssl_compute_padding_length(size_t len, size_t granularity) { return (granularity - (len + 1) % granularity) % granularity; } /* This functions transforms a (D)TLS plaintext fragment and a record content * type into an instance of the (D)TLSInnerPlaintext structure. This is used * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect * a record's content type. * * struct { * opaque content[DTLSPlaintext.length]; * ContentType real_type; * uint8 zeros[length_of_padding]; * } (D)TLSInnerPlaintext; * * Input: * - `content`: The beginning of the buffer holding the * plaintext to be wrapped. * - `*content_size`: The length of the plaintext in Bytes. * - `max_len`: The number of Bytes available starting from * `content`. This must be `>= *content_size`. * - `rec_type`: The desired record content type. * * Output: * - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure. * - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure. * * Returns: * - `0` on success. * - A negative error code if `max_len` didn't offer enough space * for the expansion. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_build_inner_plaintext(unsigned char *content, size_t *content_size, size_t remaining, uint8_t rec_type, size_t pad) { size_t len = *content_size; /* Write real content type */ if (remaining == 0) { return -1; } content[len] = rec_type; len++; remaining--; if (remaining < pad) { return -1; } memset(content + len, 0, pad); len += pad; remaining -= pad; *content_size = len; return 0; } /* This function parses a (D)TLSInnerPlaintext structure. * See ssl_build_inner_plaintext() for details. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_inner_plaintext(unsigned char const *content, size_t *content_size, uint8_t *rec_type) { size_t remaining = *content_size; /* Determine length of padding by skipping zeroes from the back. */ do { if (remaining == 0) { return -1; } remaining--; } while (content[remaining] == 0); *content_size = remaining; *rec_type = content[remaining]; return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */ /* The size of the `add_data` structure depends on various * factors, namely * * 1) CID functionality disabled * * additional_data = * 8: seq_num + * 1: type + * 2: version + * 2: length of inner plaintext + * * size = 13 bytes * * 2) CID functionality based on RFC 9146 enabled * * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length * = 23 + CID-length * * 3) CID functionality based on legacy CID version according to draft-ietf-tls-dtls-connection-id-05 * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 * * size = 13 + 1 + CID-length * * More information about the CID usage: * * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the * size of the additional data structure is calculated as: * * additional_data = * 8: seq_num + * 1: tls12_cid + * 2: DTLSCipherText.version + * n: cid + * 1: cid_length + * 2: length_of_DTLSInnerPlaintext * * Per RFC 9146 the size of the add_data structure is calculated as: * * additional_data = * 8: seq_num_placeholder + * 1: tls12_cid + * 1: cid_length + * 1: tls12_cid + * 2: DTLSCiphertext.version + * 2: epoch + * 6: sequence_number + * n: cid + * 2: length_of_DTLSInnerPlaintext * */ static void ssl_extract_add_data_from_record(unsigned char *add_data, size_t *add_data_len, mbedtls_record *rec, mbedtls_ssl_protocol_version tls_version, size_t taglen) { /* Several types of ciphers have been defined for use with TLS and DTLS, * and the MAC calculations for those ciphers differ slightly. Further * variants were added when the CID functionality was added with RFC 9146. * This implementations also considers the use of a legacy version of the * CID specification published in draft-ietf-tls-dtls-connection-id-05, * which is used in deployments. * * We will distinguish between the non-CID and the CID cases below. * * --- Non-CID cases --- * * Quoting RFC 5246 (TLS 1.2): * * additional_data = seq_num + TLSCompressed.type + * TLSCompressed.version + TLSCompressed.length; * * For TLS 1.3, the record sequence number is dropped from the AAD * and encoded within the nonce of the AEAD operation instead. * Moreover, the additional data involves the length of the TLS * ciphertext, not the TLS plaintext as in earlier versions. * Quoting RFC 8446 (TLS 1.3): * * additional_data = TLSCiphertext.opaque_type || * TLSCiphertext.legacy_record_version || * TLSCiphertext.length * * We pass the tag length to this function in order to compute the * ciphertext length from the inner plaintext length rec->data_len via * * TLSCiphertext.length = TLSInnerPlaintext.length + taglen. * * --- CID cases --- * * RFC 9146 uses a common pattern when constructing the data * passed into a MAC / AEAD cipher. * * Data concatenation for MACs used with block ciphers with * Encrypt-then-MAC Processing (with CID): * * data = seq_num_placeholder + * tls12_cid + * cid_length + * tls12_cid + * DTLSCiphertext.version + * epoch + * sequence_number + * cid + * DTLSCiphertext.length + * IV + * ENC(content + padding + padding_length) * * Data concatenation for MACs used with block ciphers (with CID): * * data = seq_num_placeholder + * tls12_cid + * cid_length + * tls12_cid + * DTLSCiphertext.version + * epoch + * sequence_number + * cid + * length_of_DTLSInnerPlaintext + * DTLSInnerPlaintext.content + * DTLSInnerPlaintext.real_type + * DTLSInnerPlaintext.zeros * * AEAD ciphers use the following additional data calculation (with CIDs): * * additional_data = seq_num_placeholder + * tls12_cid + * cid_length + * tls12_cid + * DTLSCiphertext.version + * epoch + * sequence_number + * cid + * length_of_DTLSInnerPlaintext * * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use) * defines the additional data calculation as follows: * * additional_data = seq_num + * tls12_cid + * DTLSCipherText.version + * cid + * cid_length + * length_of_DTLSInnerPlaintext */ unsigned char *cur = add_data; size_t ad_len_field = rec->data_len; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* In TLS 1.3, the AAD contains the length of the TLSCiphertext, * which differs from the length of the TLSInnerPlaintext * by the length of the authentication tag. */ ad_len_field += taglen; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ { ((void) tls_version); ((void) taglen); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 if (rec->cid_len != 0) { // seq_num_placeholder memcpy(cur, seq_num_placeholder, sizeof(seq_num_placeholder)); cur += sizeof(seq_num_placeholder); // tls12_cid type *cur = rec->type; cur++; // cid_length *cur = rec->cid_len; cur++; } else #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ { // epoch + sequence number memcpy(cur, rec->ctr, sizeof(rec->ctr)); cur += sizeof(rec->ctr); } } // type *cur = rec->type; cur++; // version memcpy(cur, rec->ver, sizeof(rec->ver)); cur += sizeof(rec->ver); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1 if (rec->cid_len != 0) { // CID memcpy(cur, rec->cid, rec->cid_len); cur += rec->cid_len; // cid_length *cur = rec->cid_len; cur++; // length of inner plaintext MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } else #elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0 if (rec->cid_len != 0) { // epoch + sequence number memcpy(cur, rec->ctr, sizeof(rec->ctr)); cur += sizeof(rec->ctr); // CID memcpy(cur, rec->cid, rec->cid_len); cur += rec->cid_len; // length of inner plaintext MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } else #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ { MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0); cur += 2; } *add_data_len = (size_t) (cur - add_data); } #if defined(MBEDTLS_SSL_HAVE_AEAD) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_transform_aead_dynamic_iv_is_explicit( mbedtls_ssl_transform const *transform) { return transform->ivlen != transform->fixed_ivlen; } /* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV ) * * Concretely, this occurs in two variants: * * a) Fixed and dynamic IV lengths add up to total IV length, giving * IV = fixed_iv || dynamic_iv * * This variant is used in TLS 1.2 when used with GCM or CCM. * * b) Fixed IV lengths matches total IV length, giving * IV = fixed_iv XOR ( 0 || dynamic_iv ) * * This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly. * * See also the documentation of mbedtls_ssl_transform. * * This function has the precondition that * * dst_iv_len >= max( fixed_iv_len, dynamic_iv_len ) * * which has to be ensured by the caller. If this precondition * violated, the behavior of this function is undefined. */ static void ssl_build_record_nonce(unsigned char *dst_iv, size_t dst_iv_len, unsigned char const *fixed_iv, size_t fixed_iv_len, unsigned char const *dynamic_iv, size_t dynamic_iv_len) { /* Start with Fixed IV || 0 */ memset(dst_iv, 0, dst_iv_len); memcpy(dst_iv, fixed_iv, fixed_iv_len); dst_iv += dst_iv_len - dynamic_iv_len; mbedtls_xor(dst_iv, dst_iv, dynamic_iv, dynamic_iv_len); } #endif /* MBEDTLS_SSL_HAVE_AEAD */ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { mbedtls_ssl_mode_t ssl_mode; int auth_done = 0; unsigned char *data; /* For an explanation of the additional data length see * the description of ssl_extract_add_data_from_record(). */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX]; #else unsigned char add_data[13]; #endif size_t add_data_len; size_t post_avail; /* The SSL context is only used for debugging purposes! */ #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif /* The PRNG is used for dynamic IV generation that's used * for CBC transformations in TLS 1.2. */ #if !(defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2)) ((void) f_rng); ((void) p_rng); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> encrypt buf")); if (transform == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("no transform provided to encrypt_buf")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (rec == NULL || rec->buf == NULL || rec->buf_len < rec->data_offset || rec->buf_len - rec->data_offset < rec->data_len #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || rec->cid_len != 0 #endif ) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad record structure provided to encrypt_buf")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); data = rec->buf + rec->data_offset; post_avail = rec->buf_len - (rec->data_len + rec->data_offset); MBEDTLS_SSL_DEBUG_BUF(4, "before encrypt: output payload", data, rec->data_len); if (rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record content %" MBEDTLS_PRINTF_SIZET " too large, maximum %" MBEDTLS_PRINTF_SIZET, rec->data_len, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* The following two code paths implement the (D)TLSInnerPlaintext * structure present in TLS 1.3 and DTLS 1.2 + CID. * * See ssl_build_inner_plaintext() for more information. * * Note that this changes `rec->data_len`, and hence * `post_avail` needs to be recalculated afterwards. * * Note also that the two code paths cannot occur simultaneously * since they apply to different versions of the protocol. There * is hence no risk of double-addition of the inner plaintext. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { size_t padding = ssl_compute_padding_length(rec->data_len, MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY); if (ssl_build_inner_plaintext(data, &rec->data_len, post_avail, rec->type, padding) != 0) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* * Add CID information */ rec->cid_len = transform->out_cid_len; memcpy(rec->cid, transform->out_cid, transform->out_cid_len); MBEDTLS_SSL_DEBUG_BUF(3, "CID", rec->cid, rec->cid_len); if (rec->cid_len != 0) { size_t padding = ssl_compute_padding_length(rec->data_len, MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY); /* * Wrap plaintext into DTLSInnerPlaintext structure. * See ssl_build_inner_plaintext() for more information. * * Note that this changes `rec->data_len`, and hence * `post_avail` needs to be recalculated afterwards. */ if (ssl_build_inner_plaintext(data, &rec->data_len, post_avail, rec->type, padding) != 0) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } rec->type = MBEDTLS_SSL_MSG_CID; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ post_avail = rec->buf_len - (rec->data_len + rec->data_offset); /* * Add MAC before if needed */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || ssl_mode == MBEDTLS_SSL_MODE_CBC) { if (post_avail < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) unsigned char mac[MBEDTLS_SSL_MAC_ADD]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t sign_mac_length = 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, transform->psa_mac_alg); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } status = psa_mac_update(&operation, add_data, add_data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } status = psa_mac_update(&operation, data, rec->data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, &sign_mac_length); if (status != PSA_SUCCESS) { goto hmac_failed_etm_disabled; } #else ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data, add_data_len); if (ret != 0) { goto hmac_failed_etm_disabled; } ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len); if (ret != 0) { goto hmac_failed_etm_disabled; } ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac); if (ret != 0) { goto hmac_failed_etm_disabled; } ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc); if (ret != 0) { goto hmac_failed_etm_disabled; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ memcpy(data + rec->data_len, mac, transform->maclen); #endif MBEDTLS_SSL_DEBUG_BUF(4, "computed mac", data + rec->data_len, transform->maclen); rec->data_len += transform->maclen; post_avail -= transform->maclen; auth_done++; hmac_failed_etm_disabled: mbedtls_platform_zeroize(mac, transform->maclen); #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = PSA_TO_MBEDTLS_ERR(status); status = psa_mac_abort(&operation); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_hmac_xxx", ret); return ret; } } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* * Encrypt */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including %d bytes of padding", rec->data_len, 0)); /* The only supported stream cipher is "NULL", * so there's nothing to do here.*/ } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ #if defined(MBEDTLS_SSL_HAVE_AEAD) if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { unsigned char iv[12]; unsigned char *dynamic_iv; size_t dynamic_iv_len; int dynamic_iv_is_explicit = ssl_transform_aead_dynamic_iv_is_explicit(transform); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif /* MBEDTLS_USE_PSA_CRYPTO */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Check that there's space for the authentication tag. */ if (post_avail < transform->taglen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* * Build nonce for AEAD encryption. * * Note: In the case of CCM and GCM in TLS 1.2, the dynamic * part of the IV is prepended to the ciphertext and * can be chosen freely - in particular, it need not * agree with the record sequence number. * However, since ChaChaPoly as well as all AEAD modes * in TLS 1.3 use the record sequence number as the * dynamic part of the nonce, we uniformly use the * record sequence number here in all cases. */ dynamic_iv = rec->ctr; dynamic_iv_len = sizeof(rec->ctr); ssl_build_record_nonce(iv, sizeof(iv), transform->iv_enc, transform->fixed_ivlen, dynamic_iv, dynamic_iv_len); /* * Build additional data for AEAD encryption. * This depends on the TLS version. */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); MBEDTLS_SSL_DEBUG_BUF(4, "IV used (internal)", iv, transform->ivlen); MBEDTLS_SSL_DEBUG_BUF(4, "IV used (transmitted)", dynamic_iv, dynamic_iv_is_explicit ? dynamic_iv_len : 0); MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD", add_data, add_data_len); MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including 0 bytes of padding", rec->data_len)); /* * Encrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_aead_encrypt(transform->psa_key_enc, transform->psa_alg, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len, data, rec->buf_len - (data - rec->buf), &rec->data_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_encrypt_buf", ret); return ret; } #else if ((ret = mbedtls_cipher_auth_encrypt_ext(&transform->cipher_ctx_enc, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len, /* src */ data, rec->buf_len - (size_t) (data - rec->buf), /* dst */ &rec->data_len, transform->taglen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_encrypt_ext", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_BUF(4, "after encrypt: tag", data + rec->data_len - transform->taglen, transform->taglen); /* Account for authentication tag. */ post_avail -= transform->taglen; /* * Prefix record content with dynamic IV in case it is explicit. */ if (dynamic_iv_is_explicit != 0) { if (rec->data_offset < dynamic_iv_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } memcpy(data - dynamic_iv_len, dynamic_iv, dynamic_iv_len); rec->data_offset -= dynamic_iv_len; rec->data_len += dynamic_iv_len; } auth_done++; } else #endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC || ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t padlen, i; size_t olen; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t part_len; psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Currently we're always using minimal padding * (up to 255 bytes would be allowed). */ padlen = transform->ivlen - (rec->data_len + 1) % transform->ivlen; if (padlen == transform->ivlen) { padlen = 0; } /* Check there's enough space in the buffer for the padding. */ if (post_avail < padlen + 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } for (i = 0; i <= padlen; i++) { data[rec->data_len + i] = (unsigned char) padlen; } rec->data_len += padlen + 1; post_avail -= padlen + 1; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Prepend per-record IV for block cipher in TLS v1.2 as per * Method 1 (6.2.3.2. in RFC4346 and RFC5246) */ if (f_rng == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("No PRNG provided to encrypt_record routine")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (rec->data_offset < transform->ivlen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* * Generate IV */ ret = f_rng(p_rng, transform->iv_enc, transform->ivlen); if (ret != 0) { return ret; } memcpy(data - transform->ivlen, transform->iv_enc, transform->ivlen); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_SSL_DEBUG_MSG(3, ("before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " "including %" MBEDTLS_PRINTF_SIZET " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding", rec->data_len, transform->ivlen, padlen + 1)); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_cipher_encrypt_setup(&cipher_op, transform->psa_key_enc, transform->psa_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_encrypt_setup", ret); return ret; } status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); return ret; } status = psa_cipher_update(&cipher_op, data, rec->data_len, data, rec->data_len, &olen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); return ret; } status = psa_cipher_finish(&cipher_op, data + olen, rec->data_len - olen, &part_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); return ret; } olen += part_len; #else if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_enc, transform->iv_enc, transform->ivlen, data, rec->data_len, data, &olen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (rec->data_len != olen) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } data -= transform->ivlen; rec->data_offset -= transform->ivlen; rec->data_len += transform->ivlen; #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (auth_done == 0) { unsigned char mac[MBEDTLS_SSL_MAC_ADD]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; size_t sign_mac_length = 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* MAC(MAC_write_key, add_data, IV, ENC(content + padding + padding_length)) */ if (post_avail < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Buffer provided for encrypted record not large enough")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, add_data_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_sign_setup(&operation, transform->psa_mac_enc, transform->psa_mac_alg); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, add_data, add_data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, data, rec->data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_sign_finish(&operation, mac, MBEDTLS_SSL_MAC_ADD, &sign_mac_length); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } #else ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, add_data, add_data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_update(&transform->md_ctx_enc, data, rec->data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_finish(&transform->md_ctx_enc, mac); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_reset(&transform->md_ctx_enc); if (ret != 0) { goto hmac_failed_etm_enabled; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ memcpy(data + rec->data_len, mac, transform->maclen); rec->data_len += transform->maclen; post_avail -= transform->maclen; auth_done++; hmac_failed_etm_enabled: mbedtls_platform_zeroize(mac, transform->maclen); #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = PSA_TO_MBEDTLS_ERR(status); status = psa_mac_abort(&operation); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "HMAC calculation failed", ret); return ret; } } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Make extra sure authentication was performed, exactly once */ if (auth_done != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= encrypt buf")); return 0; } int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl, mbedtls_ssl_transform *transform, mbedtls_record *rec) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_SSL_HAVE_AEAD) size_t olen; #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_SSL_HAVE_AEAD */ mbedtls_ssl_mode_t ssl_mode; int ret; int auth_done = 0; #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) size_t padlen = 0; mbedtls_ct_condition_t correct = MBEDTLS_CT_TRUE; #endif unsigned char *data; /* For an explanation of the additional data length see * the description of ssl_extract_add_data_from_record(). */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX]; #else unsigned char add_data[13]; #endif size_t add_data_len; #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> decrypt buf")); if (rec == NULL || rec->buf == NULL || rec->buf_len < rec->data_offset || rec->buf_len - rec->data_offset < rec->data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad record structure provided to decrypt_buf")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } data = rec->buf + rec->data_offset; ssl_mode = mbedtls_ssl_get_mode_from_transform(transform); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* * Match record's CID with incoming CID. */ if (rec->cid_len != transform->in_cid_len || memcmp(rec->cid, transform->in_cid, rec->cid_len) != 0) { return MBEDTLS_ERR_SSL_UNEXPECTED_CID; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { if (rec->data_len < transform->maclen) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record too short for MAC:" " %" MBEDTLS_PRINTF_SIZET " < %" MBEDTLS_PRINTF_SIZET, rec->data_len, transform->maclen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } /* The only supported stream cipher is "NULL", * so there's no encryption to do here.*/ } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ #if defined(MBEDTLS_SSL_HAVE_AEAD) if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { unsigned char iv[12]; unsigned char *dynamic_iv; size_t dynamic_iv_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Extract dynamic part of nonce for AEAD decryption. * * Note: In the case of CCM and GCM in TLS 1.2, the dynamic * part of the IV is prepended to the ciphertext and * can be chosen freely - in particular, it need not * agree with the record sequence number. */ dynamic_iv_len = sizeof(rec->ctr); if (ssl_transform_aead_dynamic_iv_is_explicit(transform) == 1) { if (rec->data_len < dynamic_iv_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ", rec->data_len, dynamic_iv_len)); return MBEDTLS_ERR_SSL_INVALID_MAC; } dynamic_iv = data; data += dynamic_iv_len; rec->data_offset += dynamic_iv_len; rec->data_len -= dynamic_iv_len; } else { dynamic_iv = rec->ctr; } /* Check that there's space for the authentication tag. */ if (rec->data_len < transform->taglen) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ", rec->data_len, transform->taglen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } rec->data_len -= transform->taglen; /* * Prepare nonce from dynamic and static parts. */ ssl_build_record_nonce(iv, sizeof(iv), transform->iv_dec, transform->fixed_ivlen, dynamic_iv, dynamic_iv_len); /* * Build additional data for AEAD encryption. * This depends on the TLS version. */ ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); MBEDTLS_SSL_DEBUG_BUF(4, "additional data used for AEAD", add_data, add_data_len); /* Because of the check above, we know that there are * explicit_iv_len Bytes preceding data, and taglen * bytes following data + data_len. This justifies * the debug message and the invocation of * mbedtls_cipher_auth_decrypt_ext() below. */ MBEDTLS_SSL_DEBUG_BUF(4, "IV used", iv, transform->ivlen); MBEDTLS_SSL_DEBUG_BUF(4, "TAG used", data + rec->data_len, transform->taglen); /* * Decrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_aead_decrypt(transform->psa_key_dec, transform->psa_alg, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len + transform->taglen, data, rec->buf_len - (data - rec->buf), &olen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_aead_decrypt", ret); return ret; } #else if ((ret = mbedtls_cipher_auth_decrypt_ext (&transform->cipher_ctx_dec, iv, transform->ivlen, add_data, add_data_len, data, rec->data_len + transform->taglen, /* src */ data, rec->buf_len - (size_t) (data - rec->buf), &olen, /* dst */ transform->taglen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_decrypt_ext", ret); if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { return MBEDTLS_ERR_SSL_INVALID_MAC; } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ auth_done++; /* Double-check that AEAD decryption doesn't change content length. */ if (olen != rec->data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } else #endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC || ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { size_t minlen = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t part_len; psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Check immediate ciphertext sanity */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The ciphertext is prefixed with the CBC IV. */ minlen += transform->ivlen; #endif /* Size considerations: * * - The CBC cipher text must not be empty and hence * at least of size transform->ivlen. * * Together with the potential IV-prefix, this explains * the first of the two checks below. * * - The record must contain a MAC, either in plain or * encrypted, depending on whether Encrypt-then-MAC * is used or not. * - If it is, the message contains the IV-prefix, * the CBC ciphertext, and the MAC. * - If it is not, the padded plaintext, and hence * the CBC ciphertext, has at least length maclen + 1 * because there is at least the padding length byte. * * As the CBC ciphertext is not empty, both cases give the * lower bound minlen + maclen + 1 on the record size, which * we test for in the second check below. */ if (rec->data_len < minlen + transform->ivlen || rec->data_len < minlen + transform->maclen + 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET "), maclen (%" MBEDTLS_PRINTF_SIZET ") " "+ 1 ) ( + expl IV )", rec->data_len, transform->ivlen, transform->maclen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } /* * Authenticate before decrypt if enabled */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; #else unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG(3, ("using encrypt then mac")); /* Update data_len in tandem with add_data. * * The subtraction is safe because of the previous check * data_len >= minlen + maclen + 1. * * Afterwards, we know that data + data_len is followed by at * least maclen Bytes, which justifies the call to * mbedtls_ct_memcmp() below. * * Further, we still know that data_len > minlen */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); /* Calculate expected MAC. */ MBEDTLS_SSL_DEBUG_BUF(4, "MAC'd meta-data", add_data, add_data_len); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_mac_verify_setup(&operation, transform->psa_mac_dec, transform->psa_mac_alg); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, add_data, add_data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } status = psa_mac_update(&operation, data, rec->data_len); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } /* Compare expected MAC with MAC at the end of the record. */ status = psa_mac_verify_finish(&operation, data + rec->data_len, transform->maclen); if (status != PSA_SUCCESS) { goto hmac_failed_etm_enabled; } #else ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, add_data, add_data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_update(&transform->md_ctx_dec, data, rec->data_len); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_finish(&transform->md_ctx_dec, mac_expect); if (ret != 0) { goto hmac_failed_etm_enabled; } ret = mbedtls_md_hmac_reset(&transform->md_ctx_dec); if (ret != 0) { goto hmac_failed_etm_enabled; } MBEDTLS_SSL_DEBUG_BUF(4, "message mac", data + rec->data_len, transform->maclen); MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect, transform->maclen); /* Compare expected MAC with MAC at the end of the record. */ if (mbedtls_ct_memcmp(data + rec->data_len, mac_expect, transform->maclen) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match")); ret = MBEDTLS_ERR_SSL_INVALID_MAC; goto hmac_failed_etm_enabled; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ auth_done++; hmac_failed_etm_enabled: #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = PSA_TO_MBEDTLS_ERR(status); status = psa_mac_abort(&operation); if (ret == 0 && status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } #else mbedtls_platform_zeroize(mac_expect, transform->maclen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { if (ret != MBEDTLS_ERR_SSL_INVALID_MAC) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_hmac_xxx", ret); } return ret; } } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ /* * Check length sanity */ /* We know from above that data_len > minlen >= 0, * so the following check in particular implies that * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ if (rec->data_len % transform->ivlen != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0", rec->data_len, transform->ivlen)); return MBEDTLS_ERR_SSL_INVALID_MAC; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Initialize for prepended IV for block cipher in TLS v1.2 */ /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ memcpy(transform->iv_dec, data, transform->ivlen); data += transform->ivlen; rec->data_offset += transform->ivlen; rec->data_len -= transform->ivlen; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_cipher_decrypt_setup(&cipher_op, transform->psa_key_dec, transform->psa_alg); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_decrypt_setup", ret); return ret; } status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret); return ret; } status = psa_cipher_update(&cipher_op, data, rec->data_len, data, rec->data_len, &olen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret); return ret; } status = psa_cipher_finish(&cipher_op, data + olen, rec->data_len - olen, &part_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret); return ret; } olen += part_len; #else if ((ret = mbedtls_cipher_crypt(&transform->cipher_ctx_dec, transform->iv_dec, transform->ivlen, data, rec->data_len, data, &olen)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_crypt", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Double-check that length hasn't changed during decryption. */ if (rec->data_len != olen) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Safe since data_len >= minlen + maclen + 1, so after having * subtracted at most minlen and maclen up to this point, * data_len > 0 (because of data_len % ivlen == 0, it's actually * >= ivlen ). */ padlen = data[rec->data_len - 1]; if (auth_done == 1) { const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge( rec->data_len, padlen + 1); correct = mbedtls_ct_bool_and(ge, correct); padlen = mbedtls_ct_size_if_else_0(ge, padlen); } else { #if defined(MBEDTLS_SSL_DEBUG_ALL) if (rec->data_len < transform->maclen + padlen + 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("msglen (%" MBEDTLS_PRINTF_SIZET ") < maclen (%" MBEDTLS_PRINTF_SIZET ") + padlen (%" MBEDTLS_PRINTF_SIZET ")", rec->data_len, transform->maclen, padlen + 1)); } #endif const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge( rec->data_len, transform->maclen + padlen + 1); correct = mbedtls_ct_bool_and(ge, correct); padlen = mbedtls_ct_size_if_else_0(ge, padlen); } padlen++; /* Regardless of the validity of the padding, * we have data_len >= padlen here. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* The padding check involves a series of up to 256 * consecutive memory reads at the end of the record * plaintext buffer. In order to hide the length and * validity of the padding, always perform exactly * `min(256,plaintext_len)` reads (but take into account * only the last `padlen` bytes for the padding check). */ size_t pad_count = 0; volatile unsigned char * const check = data; /* Index of first padding byte; it has been ensured above * that the subtraction is safe. */ size_t const padding_idx = rec->data_len - padlen; size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; size_t const start_idx = rec->data_len - num_checks; size_t idx; for (idx = start_idx; idx < rec->data_len; idx++) { /* pad_count += (idx >= padding_idx) && * (check[idx] == padlen - 1); */ const mbedtls_ct_condition_t a = mbedtls_ct_uint_ge(idx, padding_idx); size_t increment = mbedtls_ct_size_if_else_0(a, 1); const mbedtls_ct_condition_t b = mbedtls_ct_uint_eq(check[idx], padlen - 1); increment = mbedtls_ct_size_if_else_0(b, increment); pad_count += increment; } correct = mbedtls_ct_bool_and(mbedtls_ct_uint_eq(pad_count, padlen), correct); #if defined(MBEDTLS_SSL_DEBUG_ALL) if (padlen > 0 && correct == MBEDTLS_CT_FALSE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected")); } #endif padlen = mbedtls_ct_size_if_else_0(correct, padlen); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* If the padding was found to be invalid, padlen == 0 * and the subtraction is safe. If the padding was found valid, * padlen hasn't been changed and the previous assertion * data_len >= padlen still holds. */ rec->data_len -= padlen; } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF(4, "raw buffer after decryption", data, rec->data_len); #endif /* * Authenticate if not done yet. * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (auth_done == 0) { unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 }; unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 }; /* For CBC+MAC, If the initial value of padlen was such that * data_len < maclen + padlen + 1, then padlen * got reset to 1, and the initial check * data_len >= minlen + maclen + 1 * guarantees that at this point we still * have at least data_len >= maclen. * * If the initial value of padlen was such that * data_len >= maclen + padlen + 1, then we have * subtracted either padlen + 1 (if the padding was correct) * or 0 (if the padding was incorrect) since then, * hence data_len >= maclen in any case. * * For stream ciphers, we checked above that * data_len >= maclen. */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record(add_data, &add_data_len, rec, transform->tls_version, transform->taglen); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * The next two sizes are the minimum and maximum values of * data_len over all padlen values. * * They're independent of padlen, since we previously did * data_len -= padlen. * * Note that max_len + maclen is never more than the buffer * length, as we previously did in_msglen -= maclen too. */ const size_t max_len = rec->data_len + padlen; const size_t min_len = (max_len > 256) ? max_len - 256 : 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = mbedtls_ct_hmac(transform->psa_mac_dec, transform->psa_mac_alg, add_data, add_data_len, data, rec->data_len, min_len, max_len, mac_expect); #else ret = mbedtls_ct_hmac(&transform->md_ctx_dec, add_data, add_data_len, data, rec->data_len, min_len, max_len, mac_expect); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ct_hmac", ret); goto hmac_failed_etm_disabled; } mbedtls_ct_memcpy_offset(mac_peer, data, rec->data_len, min_len, max_len, transform->maclen); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_BUF(4, "expected mac", mac_expect, transform->maclen); MBEDTLS_SSL_DEBUG_BUF(4, "message mac", mac_peer, transform->maclen); #endif if (mbedtls_ct_memcmp(mac_peer, mac_expect, transform->maclen) != 0) { #if defined(MBEDTLS_SSL_DEBUG_ALL) MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match")); #endif correct = MBEDTLS_CT_FALSE; } auth_done++; hmac_failed_etm_disabled: mbedtls_platform_zeroize(mac_peer, transform->maclen); mbedtls_platform_zeroize(mac_expect, transform->maclen); if (ret != 0) { return ret; } } /* * Finally check the correct flag */ if (correct == MBEDTLS_CT_FALSE) { return MBEDTLS_ERR_SSL_INVALID_MAC; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ /* Make extra sure authentication was performed, exactly once */ if (auth_done != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (transform->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* Remove inner padding and infer true content type. */ ret = ssl_parse_inner_plaintext(data, &rec->data_len, &rec->type); if (ret != 0) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (rec->cid_len != 0) { ret = ssl_parse_inner_plaintext(data, &rec->data_len, &rec->type); if (ret != 0) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= decrypt buf")); return 0; } #undef MAC_NONE #undef MAC_PLAINTEXT #undef MAC_CIPHERTEXT /* * Fill the input message buffer by appending data to it. * The amount of data already fetched is in ssl->in_left. * * If we return 0, is it guaranteed that (at least) nb_want bytes are * available (from this read and/or a previous one). Otherwise, an error code * is returned (possibly EOF or WANT_READ). * * With stream transport (TLS) on success ssl->in_left == nb_want, but * with datagram transport (DTLS) on success ssl->in_left >= nb_want, * since we always read a whole datagram at once. * * For DTLS, it is up to the caller to set ssl->next_record_offset when * they're done reading a record. */ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> fetch input")); if (ssl->f_recv == NULL && ssl->f_recv_timeout == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() ")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (nb_want > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) { MBEDTLS_SSL_DEBUG_MSG(1, ("requesting more data than fits")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { uint32_t timeout; /* * The point is, we need to always read a full datagram at once, so we * sometimes read more then requested, and handle the additional data. * It could be the rest of the current record (while fetching the * header) and/or some other records in the same datagram. */ /* * Move to the next record in the already read datagram if applicable */ if (ssl->next_record_offset != 0) { if (ssl->in_left < ssl->next_record_offset) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->in_left -= ssl->next_record_offset; if (ssl->in_left != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("next record in same datagram, offset: %" MBEDTLS_PRINTF_SIZET, ssl->next_record_offset)); memmove(ssl->in_hdr, ssl->in_hdr + ssl->next_record_offset, ssl->in_left); } ssl->next_record_offset = 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET ", nb_want: %" MBEDTLS_PRINTF_SIZET, ssl->in_left, nb_want)); /* * Done if we already have enough data. */ if (nb_want <= ssl->in_left) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= fetch input")); return 0; } /* * A record can't be split across datagrams. If we need to read but * are not at the beginning of a new record, the caller did something * wrong. */ if (ssl->in_left != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Don't even try to read if time's out already. * This avoids by-passing the timer when repeatedly receiving messages * that will end up being dropped. */ if (mbedtls_ssl_check_timer(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("timer has expired")); ret = MBEDTLS_ERR_SSL_TIMEOUT; } else { len = in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf); if (mbedtls_ssl_is_handshake_over(ssl) == 0) { timeout = ssl->handshake->retransmit_timeout; } else { timeout = ssl->conf->read_timeout; } MBEDTLS_SSL_DEBUG_MSG(3, ("f_recv_timeout: %lu ms", (unsigned long) timeout)); if (ssl->f_recv_timeout != NULL) { ret = ssl->f_recv_timeout(ssl->p_bio, ssl->in_hdr, len, timeout); } else { ret = ssl->f_recv(ssl->p_bio, ssl->in_hdr, len); } MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_recv(_timeout)", ret); if (ret == 0) { return MBEDTLS_ERR_SSL_CONN_EOF; } } if (ret == MBEDTLS_ERR_SSL_TIMEOUT) { MBEDTLS_SSL_DEBUG_MSG(2, ("timeout")); mbedtls_ssl_set_timer(ssl, 0); if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { if (ssl_double_retransmit_timeout(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake timeout")); return MBEDTLS_ERR_SSL_TIMEOUT; } if ((ret = mbedtls_ssl_resend(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend", ret); return ret; } return MBEDTLS_ERR_SSL_WANT_READ; } #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend_hello_request", ret); return ret; } return MBEDTLS_ERR_SSL_WANT_READ; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ } if (ret < 0) { return ret; } ssl->in_left = ret; } else #endif { MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET ", nb_want: %" MBEDTLS_PRINTF_SIZET, ssl->in_left, nb_want)); while (ssl->in_left < nb_want) { len = nb_want - ssl->in_left; if (mbedtls_ssl_check_timer(ssl) != 0) { ret = MBEDTLS_ERR_SSL_TIMEOUT; } else { if (ssl->f_recv_timeout != NULL) { ret = ssl->f_recv_timeout(ssl->p_bio, ssl->in_hdr + ssl->in_left, len, ssl->conf->read_timeout); } else { ret = ssl->f_recv(ssl->p_bio, ssl->in_hdr + ssl->in_left, len); } } MBEDTLS_SSL_DEBUG_MSG(2, ("in_left: %" MBEDTLS_PRINTF_SIZET ", nb_want: %" MBEDTLS_PRINTF_SIZET, ssl->in_left, nb_want)); MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_recv(_timeout)", ret); if (ret == 0) { return MBEDTLS_ERR_SSL_CONN_EOF; } if (ret < 0) { return ret; } if ((size_t) ret > len) { MBEDTLS_SSL_DEBUG_MSG(1, ("f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested", ret, len)); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->in_left += ret; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= fetch input")); return 0; } /* * Flush any data not yet written */ int mbedtls_ssl_flush_output(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; MBEDTLS_SSL_DEBUG_MSG(2, ("=> flush output")); if (ssl->f_send == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Bad usage of mbedtls_ssl_set_bio() ")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Avoid incrementing counter if data is flushed */ if (ssl->out_left == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= flush output")); return 0; } while (ssl->out_left > 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("message length: %" MBEDTLS_PRINTF_SIZET ", out_left: %" MBEDTLS_PRINTF_SIZET, mbedtls_ssl_out_hdr_len(ssl) + ssl->out_msglen, ssl->out_left)); buf = ssl->out_hdr - ssl->out_left; ret = ssl->f_send(ssl->p_bio, buf, ssl->out_left); MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_send", ret); if (ret <= 0) { return ret; } if ((size_t) ret > ssl->out_left) { MBEDTLS_SSL_DEBUG_MSG(1, ("f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent", ret, ssl->out_left)); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->out_left -= ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_hdr = ssl->out_buf; } else #endif { ssl->out_hdr = ssl->out_buf + 8; } mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); MBEDTLS_SSL_DEBUG_MSG(2, ("<= flush output")); return 0; } /* * Functions to handle the DTLS retransmission state machine */ #if defined(MBEDTLS_SSL_PROTO_DTLS) /* * Append current handshake message to current outgoing flight */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_flight_append(mbedtls_ssl_context *ssl) { mbedtls_ssl_flight_item *msg; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_flight_append")); MBEDTLS_SSL_DEBUG_BUF(4, "message appended to flight", ssl->out_msg, ssl->out_msglen); /* Allocate space for current message */ if ((msg = mbedtls_calloc(1, sizeof(mbedtls_ssl_flight_item))) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", sizeof(mbedtls_ssl_flight_item))); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } if ((msg->p = mbedtls_calloc(1, ssl->out_msglen)) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", ssl->out_msglen)); mbedtls_free(msg); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* Copy current handshake message with headers */ memcpy(msg->p, ssl->out_msg, ssl->out_msglen); msg->len = ssl->out_msglen; msg->type = ssl->out_msgtype; msg->next = NULL; /* Append to the current flight */ if (ssl->handshake->flight == NULL) { ssl->handshake->flight = msg; } else { mbedtls_ssl_flight_item *cur = ssl->handshake->flight; while (cur->next != NULL) { cur = cur->next; } cur->next = msg; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_flight_append")); return 0; } /* * Free the current flight of handshake messages */ void mbedtls_ssl_flight_free(mbedtls_ssl_flight_item *flight) { mbedtls_ssl_flight_item *cur = flight; mbedtls_ssl_flight_item *next; while (cur != NULL) { next = cur->next; mbedtls_free(cur->p); mbedtls_free(cur); cur = next; } } /* * Swap transform_out and out_ctr with the alternative ones */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_swap_epochs(mbedtls_ssl_context *ssl) { mbedtls_ssl_transform *tmp_transform; unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; if (ssl->transform_out == ssl->handshake->alt_transform_out) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip swap epochs")); return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("swap epochs")); /* Swap transforms */ tmp_transform = ssl->transform_out; ssl->transform_out = ssl->handshake->alt_transform_out; ssl->handshake->alt_transform_out = tmp_transform; /* Swap epoch + sequence_number */ memcpy(tmp_out_ctr, ssl->cur_out_ctr, sizeof(tmp_out_ctr)); memcpy(ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, sizeof(ssl->cur_out_ctr)); memcpy(ssl->handshake->alt_out_ctr, tmp_out_ctr, sizeof(ssl->handshake->alt_out_ctr)); /* Adjust to the newly activated transform */ mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); return 0; } /* * Retransmit the current flight of messages. */ int mbedtls_ssl_resend(mbedtls_ssl_context *ssl) { int ret = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_resend")); ret = mbedtls_ssl_flight_transmit(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_resend")); return ret; } /* * Transmit or retransmit the current flight of messages. * * Need to remember the current message in case flush_output returns * WANT_WRITE, causing us to exit this function and come back later. * This function must be called until state is no longer SENDING. */ int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_flight_transmit")); if (ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING) { MBEDTLS_SSL_DEBUG_MSG(2, ("initialise flight transmission")); ssl->handshake->cur_msg = ssl->handshake->flight; ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; ret = ssl_swap_epochs(ssl); if (ret != 0) { return ret; } ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; } while (ssl->handshake->cur_msg != NULL) { size_t max_frag_len; const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; int const is_finished = (cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && cur->p[0] == MBEDTLS_SSL_HS_FINISHED); int const force_flush = ssl->disable_datagram_packing == 1 ? SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. * Must be done before copying, may change out_msg pointer */ if (is_finished && ssl->handshake->cur_msg_p == (cur->p + 12)) { MBEDTLS_SSL_DEBUG_MSG(2, ("swap epochs to send finished message")); ret = ssl_swap_epochs(ssl); if (ret != 0) { return ret; } } ret = ssl_get_remaining_payload_in_datagram(ssl); if (ret < 0) { return ret; } max_frag_len = (size_t) ret; /* CCS is copied as is, while HS messages may need fragmentation */ if (cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { if (max_frag_len == 0) { if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } continue; } memcpy(ssl->out_msg, cur->p, cur->len); ssl->out_msglen = cur->len; ssl->out_msgtype = cur->type; /* Update position inside current message */ ssl->handshake->cur_msg_p += cur->len; } else { const unsigned char * const p = ssl->handshake->cur_msg_p; const size_t hs_len = cur->len - 12; const size_t frag_off = (size_t) (p - (cur->p + 12)); const size_t rem_len = hs_len - frag_off; size_t cur_hs_frag_len, max_hs_frag_len; if ((max_frag_len < 12) || (max_frag_len == 12 && hs_len != 0)) { if (is_finished) { ret = ssl_swap_epochs(ssl); if (ret != 0) { return ret; } } if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } continue; } max_hs_frag_len = max_frag_len - 12; cur_hs_frag_len = rem_len > max_hs_frag_len ? max_hs_frag_len : rem_len; if (frag_off == 0 && cur_hs_frag_len != hs_len) { MBEDTLS_SSL_DEBUG_MSG(2, ("fragmenting handshake message (%u > %u)", (unsigned) cur_hs_frag_len, (unsigned) max_hs_frag_len)); } /* Messages are stored with handshake headers as if not fragmented, * copy beginning of headers then fill fragmentation fields. * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ memcpy(ssl->out_msg, cur->p, 6); ssl->out_msg[6] = MBEDTLS_BYTE_2(frag_off); ssl->out_msg[7] = MBEDTLS_BYTE_1(frag_off); ssl->out_msg[8] = MBEDTLS_BYTE_0(frag_off); ssl->out_msg[9] = MBEDTLS_BYTE_2(cur_hs_frag_len); ssl->out_msg[10] = MBEDTLS_BYTE_1(cur_hs_frag_len); ssl->out_msg[11] = MBEDTLS_BYTE_0(cur_hs_frag_len); MBEDTLS_SSL_DEBUG_BUF(3, "handshake header", ssl->out_msg, 12); /* Copy the handshake message content and set records fields */ memcpy(ssl->out_msg + 12, p, cur_hs_frag_len); ssl->out_msglen = cur_hs_frag_len + 12; ssl->out_msgtype = cur->type; /* Update position inside current message */ ssl->handshake->cur_msg_p += cur_hs_frag_len; } /* If done with the current message move to the next one if any */ if (ssl->handshake->cur_msg_p >= cur->p + cur->len) { if (cur->next != NULL) { ssl->handshake->cur_msg = cur->next; ssl->handshake->cur_msg_p = cur->next->p + 12; } else { ssl->handshake->cur_msg = NULL; ssl->handshake->cur_msg_p = NULL; } } /* Actually send the message out */ if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret); return ret; } } if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } /* Update state and set timer */ if (mbedtls_ssl_is_handshake_over(ssl) == 1) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout); } MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_flight_transmit")); return 0; } /* * To be called when the last message of an incoming flight is received. */ void mbedtls_ssl_recv_flight_completed(mbedtls_ssl_context *ssl) { /* We won't need to resend that one any more */ mbedtls_ssl_flight_free(ssl->handshake->flight); ssl->handshake->flight = NULL; ssl->handshake->cur_msg = NULL; /* The next incoming flight will start with this msg_seq */ ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; /* We don't want to remember CCS's across flight boundaries. */ ssl->handshake->buffering.seen_ccs = 0; /* Clear future message buffering structure. */ mbedtls_ssl_buffering_free(ssl); /* Cancel timer */ mbedtls_ssl_set_timer(ssl, 0); if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; } } /* * To be called when the last message of an outgoing flight is send. */ void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl) { ssl_reset_retransmit_timeout(ssl); mbedtls_ssl_set_timer(ssl, ssl->handshake->retransmit_timeout); if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Handshake layer functions */ int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type, unsigned char **buf, size_t *buf_len) { /* * Reserve 4 bytes for handshake header. ( Section 4,RFC 8446 ) * ... * HandshakeType msg_type; * uint24 length; * ... */ *buf = ssl->out_msg + 4; *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = hs_type; return 0; } /* * Write (DTLS: or queue) current handshake (including CCS) message. * * - fill in handshake headers * - update handshake checksum * - DTLS: save message for resending * - then pass to the record layer * * DTLS: except for HelloRequest, messages are only queued, and will only be * actually sent when calling flight_transmit() or resend(). * * Inputs: * - ssl->out_msglen: 4 + actual handshake message len * (4 is the size of handshake headers for TLS) * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) * - ssl->out_msg + 4: the handshake message body * * Outputs, ie state before passing to flight_append() or write_record(): * - ssl->out_msglen: the length of the record contents * (including handshake headers but excluding record headers) * - ssl->out_msg: the record contents (handshake headers + content) */ int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl, int update_checksum, int force_flush) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const size_t hs_len = ssl->out_msglen - 4; const unsigned char hs_type = ssl->out_msg[0]; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write handshake message")); /* * Sanity checks */ if (ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Whenever we send anything different from a * HelloRequest we should be in a handshake - double check. */ if (!(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST) && ssl->handshake == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* Double-check that we did not exceed the bounds * of the outgoing record buffer. * This should never fail as the various message * writing functions must obey the bounds of the * outgoing record buffer, but better be safe. * * Note: We deliberately do not check for the MTU or MFL here. */ if (ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Record too large: " "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET, ssl->out_msglen, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Fill handshake headers */ if (ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { ssl->out_msg[1] = MBEDTLS_BYTE_2(hs_len); ssl->out_msg[2] = MBEDTLS_BYTE_1(hs_len); ssl->out_msg[3] = MBEDTLS_BYTE_0(hs_len); /* * DTLS has additional fields in the Handshake layer, * between the length field and the actual payload: * uint16 message_seq; * uint24 fragment_offset; * uint24 fragment_length; */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Make room for the additional DTLS fields */ if (MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS handshake message too large: " "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET, hs_len, (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - 12))); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memmove(ssl->out_msg + 12, ssl->out_msg + 4, hs_len); ssl->out_msglen += 8; /* Write message_seq and update it, except for HelloRequest */ if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST) { MBEDTLS_PUT_UINT16_BE(ssl->handshake->out_msg_seq, ssl->out_msg, 4); ++(ssl->handshake->out_msg_seq); } else { ssl->out_msg[4] = 0; ssl->out_msg[5] = 0; } /* Handshake hashes are computed without fragmentation, * so set frag_offset = 0 and frag_len = hs_len for now */ memset(ssl->out_msg + 6, 0x00, 3); memcpy(ssl->out_msg + 9, ssl->out_msg + 1, 3); } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Update running hashes of handshake messages seen */ if (hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0) { ret = ssl->handshake->update_checksum(ssl, ssl->out_msg, ssl->out_msglen); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } } } /* Either send now, or just save to be sent (and resent) later */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && !(ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST)) { if ((ret = ssl_flight_append(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_flight_append", ret); return ret; } } else #endif { if ((ret = mbedtls_ssl_write_record(ssl, force_flush)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_record", ret); return ret; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write handshake message")); return 0; } int mbedtls_ssl_finish_handshake_msg(mbedtls_ssl_context *ssl, size_t buf_len, size_t msg_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t msg_with_header_len; ((void) buf_len); /* Add reserved 4 bytes for handshake header */ msg_with_header_len = msg_len + 4; ssl->out_msglen = msg_with_header_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_handshake_msg_ext(ssl, 0, 0)); cleanup: return ret; } /* * Record layer functions */ /* * Write current record. * * Uses: * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) * - ssl->out_msglen: length of the record content (excl headers) * - ssl->out_msg: record content */ int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush) { int ret, done = 0; size_t len = ssl->out_msglen; int flush = force_flush; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write record")); if (!done) { unsigned i; size_t protected_record_size; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len; #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif /* Skip writing the record content type to after the encryption, * as it may change when using the CID extension. */ mbedtls_ssl_protocol_version tls_ver = ssl->tls_version; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* TLS 1.3 still uses the TLS 1.2 version identifier * for backwards compatibility. */ if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) { tls_ver = MBEDTLS_SSL_VERSION_TLS1_2; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport, tls_ver); memcpy(ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); MBEDTLS_PUT_UINT16_BE(len, ssl->out_len, 0); if (ssl->transform_out != NULL) { mbedtls_record rec; rec.buf = ssl->out_iv; rec.buf_len = out_buf_len - (size_t) (ssl->out_iv - ssl->out_buf); rec.data_len = ssl->out_msglen; rec.data_offset = (size_t) (ssl->out_msg - rec.buf); memcpy(&rec.ctr[0], ssl->out_ctr, sizeof(rec.ctr)); mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_ver); rec.type = ssl->out_msgtype; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* The CID is set by mbedtls_ssl_encrypt_buf(). */ rec.cid_len = 0; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ if ((ret = mbedtls_ssl_encrypt_buf(ssl, ssl->transform_out, &rec, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_encrypt_buf", ret); return ret; } if (rec.data_offset != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Update the record content type and CID. */ ssl->out_msgtype = rec.type; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) memcpy(ssl->out_cid, rec.cid, rec.cid_len); #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_msglen = len = rec.data_len; MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->out_len, 0); } protected_record_size = len + mbedtls_ssl_out_hdr_len(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) /* In case of DTLS, double-check that we don't exceed * the remaining space in the datagram. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ret = ssl_get_remaining_space_in_datagram(ssl); if (ret < 0) { return ret; } if (protected_record_size > (size_t) ret) { /* Should never happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Now write the potentially updated record content type. */ ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; MBEDTLS_SSL_DEBUG_MSG(3, ("output record: msgtype = %u, " "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET, ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], len)); MBEDTLS_SSL_DEBUG_BUF(4, "output record sent to network", ssl->out_hdr, protected_record_size); ssl->out_left += protected_record_size; ssl->out_hdr += protected_record_size; mbedtls_ssl_update_out_pointers(ssl, ssl->transform_out); for (i = 8; i > mbedtls_ssl_ep_len(ssl); i--) { if (++ssl->cur_out_ctr[i - 1] != 0) { break; } } /* The loop goes to its end if the counter is wrapping */ if (i == mbedtls_ssl_ep_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("outgoing message counter would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && flush == SSL_DONT_FORCE_FLUSH) { size_t remaining; ret = ssl_get_remaining_payload_in_datagram(ssl); if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_remaining_payload_in_datagram", ret); return ret; } remaining = (size_t) ret; if (remaining == 0) { flush = SSL_FORCE_FLUSH; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Still %u bytes available in current datagram", (unsigned) remaining)); } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if ((flush == SSL_FORCE_FLUSH) && (ret = mbedtls_ssl_flush_output(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write record")); return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl) { if (ssl->in_msglen < ssl->in_hslen || memcmp(ssl->in_msg + 6, "\0\0\0", 3) != 0 || memcmp(ssl->in_msg + 9, ssl->in_msg + 1, 3) != 0) { return 1; } return 0; } static uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl) { return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); } static uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl) { return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_hs_header(mbedtls_ssl_context const *ssl) { uint32_t msg_len, frag_off, frag_len; msg_len = ssl_get_hs_total_len(ssl); frag_off = ssl_get_hs_frag_off(ssl); frag_len = ssl_get_hs_frag_len(ssl); if (frag_off > msg_len) { return -1; } if (frag_len > msg_len - frag_off) { return -1; } if (frag_len + 12 > ssl->in_msglen) { return -1; } return 0; } /* * Mark bits in bitmask (used for DTLS HS reassembly) */ static void ssl_bitmask_set(unsigned char *mask, size_t offset, size_t len) { unsigned int start_bits, end_bits; start_bits = 8 - (offset % 8); if (start_bits != 8) { size_t first_byte_idx = offset / 8; /* Special case */ if (len <= start_bits) { for (; len != 0; len--) { mask[first_byte_idx] |= 1 << (start_bits - len); } /* Avoid potential issues with offset or len becoming invalid */ return; } offset += start_bits; /* Now offset % 8 == 0 */ len -= start_bits; for (; start_bits != 0; start_bits--) { mask[first_byte_idx] |= 1 << (start_bits - 1); } } end_bits = len % 8; if (end_bits != 0) { size_t last_byte_idx = (offset + len) / 8; len -= end_bits; /* Now len % 8 == 0 */ for (; end_bits != 0; end_bits--) { mask[last_byte_idx] |= 1 << (8 - end_bits); } } memset(mask + offset / 8, 0xFF, len / 8); } /* * Check that bitmask is full */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_bitmask_check(unsigned char *mask, size_t len) { size_t i; for (i = 0; i < len / 8; i++) { if (mask[i] != 0xFF) { return -1; } } for (i = 0; i < len % 8; i++) { if ((mask[len / 8] & (1 << (7 - i))) == 0) { return -1; } } return 0; } /* msg_len does not include the handshake header */ static size_t ssl_get_reassembly_buffer_size(size_t msg_len, unsigned add_bitmap) { size_t alloc_len; alloc_len = 12; /* Handshake header */ alloc_len += msg_len; /* Content buffer */ if (add_bitmap) { alloc_len += msg_len / 8 + (msg_len % 8 != 0); /* Bitmap */ } return alloc_len; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl) { return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); } int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl) { if (ssl->in_msglen < mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake message too short: %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } ssl->in_hslen = mbedtls_ssl_hs_hdr_len(ssl) + ssl_get_hs_total_len(ssl); MBEDTLS_SSL_DEBUG_MSG(3, ("handshake message: msglen =" " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen)); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); if (ssl_check_hs_header(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid handshake header")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } if (ssl->handshake != NULL && ((mbedtls_ssl_is_handshake_over(ssl) == 0 && recv_msg_seq != ssl->handshake->in_msg_seq) || (mbedtls_ssl_is_handshake_over(ssl) == 1 && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO))) { if (recv_msg_seq > ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(2, ( "received future handshake message of sequence number %u (next %u)", recv_msg_seq, ssl->handshake->in_msg_seq)); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } /* Retransmit only on last message from previous flight, to avoid * too many retransmissions. * Besides, No sane server ever retransmits HelloVerifyRequest */ if (recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) { MBEDTLS_SSL_DEBUG_MSG(2, ("received message from last flight, " "message_seq = %u, start_of_flight = %u", recv_msg_seq, ssl->handshake->in_flight_start_seq)); if ((ret = mbedtls_ssl_resend(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend", ret); return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("dropping out-of-sequence message: " "message_seq = %u, expected = %u", recv_msg_seq, ssl->handshake->in_msg_seq)); } return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } /* Wait until message completion to increment in_msg_seq */ /* Message reassembly is handled alongside buffering of future * messages; the commonality is that both handshake fragments and * future messages cannot be forwarded immediately to the * handshake logic layer. */ if (ssl_hs_is_proper_fragment(ssl) == 1) { MBEDTLS_SSL_DEBUG_MSG(2, ("found fragmented DTLS handshake message")); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* With TLS we don't handle fragmentation (for now) */ if (ssl->in_msglen < ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("TLS handshake fragmentation not supported")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return 0; } int mbedtls_ssl_update_handshake_status(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (mbedtls_ssl_is_handshake_over(ssl) == 0 && hs != NULL) { ret = ssl->handshake->update_checksum(ssl, ssl->in_msg, ssl->in_hslen); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } } /* Handshake message is complete, increment counter */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake != NULL) { unsigned offset; mbedtls_ssl_hs_buffer *hs_buf; /* Increment handshake sequence number */ hs->in_msg_seq++; /* * Clear up handshake buffering and reassembly structure. */ /* Free first entry */ ssl_buffering_free_slot(ssl, 0); /* Shift all other entries */ for (offset = 0, hs_buf = &hs->buffering.hs[0]; offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++, hs_buf++) { *hs_buf = *(hs_buf + 1); } /* Create a fresh last entry */ memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); } #endif return 0; } /* * DTLS anti-replay: RFC 6347 4.1.2.6 * * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). * Bit n is set iff record number in_window_top - n has been seen. * * Usually, in_window_top is the last record number seen and the lsb of * in_window is set. The only exception is the initial state (record number 0 * not seen yet). */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) void mbedtls_ssl_dtls_replay_reset(mbedtls_ssl_context *ssl) { ssl->in_window_top = 0; ssl->in_window = 0; } static inline uint64_t ssl_load_six_bytes(unsigned char *buf) { return ((uint64_t) buf[0] << 40) | ((uint64_t) buf[1] << 32) | ((uint64_t) buf[2] << 24) | ((uint64_t) buf[3] << 16) | ((uint64_t) buf[4] << 8) | ((uint64_t) buf[5]); } MBEDTLS_CHECK_RETURN_CRITICAL static int mbedtls_ssl_dtls_record_replay_check(mbedtls_ssl_context *ssl, uint8_t *record_in_ctr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *original_in_ctr; // save original in_ctr original_in_ctr = ssl->in_ctr; // use counter from record ssl->in_ctr = record_in_ctr; ret = mbedtls_ssl_dtls_replay_check((mbedtls_ssl_context const *) ssl); // restore the counter ssl->in_ctr = original_in_ctr; return ret; } /* * Return 0 if sequence number is acceptable, -1 otherwise */ int mbedtls_ssl_dtls_replay_check(mbedtls_ssl_context const *ssl) { uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2); uint64_t bit; if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) { return 0; } if (rec_seqnum > ssl->in_window_top) { return 0; } bit = ssl->in_window_top - rec_seqnum; if (bit >= 64) { return -1; } if ((ssl->in_window & ((uint64_t) 1 << bit)) != 0) { return -1; } return 0; } /* * Update replay window on new validated record */ void mbedtls_ssl_dtls_replay_update(mbedtls_ssl_context *ssl) { uint64_t rec_seqnum = ssl_load_six_bytes(ssl->in_ctr + 2); if (ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED) { return; } if (rec_seqnum > ssl->in_window_top) { /* Update window_top and the contents of the window */ uint64_t shift = rec_seqnum - ssl->in_window_top; if (shift >= 64) { ssl->in_window = 1; } else { ssl->in_window <<= shift; ssl->in_window |= 1; } ssl->in_window_top = rec_seqnum; } else { /* Mark that number as seen in the current window */ uint64_t bit = ssl->in_window_top - rec_seqnum; if (bit < 64) { /* Always true, but be extra sure */ ssl->in_window |= (uint64_t) 1 << bit; } } } #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) /* * Check if a datagram looks like a ClientHello with a valid cookie, * and if it doesn't, generate a HelloVerifyRequest message. * Both input and output include full DTLS headers. * * - if cookie is valid, return 0 * - if ClientHello looks superficially valid but cookie is not, * fill obuf and set olen, then * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED * - otherwise return a specific error code */ MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_check_dtls_clihlo_cookie( mbedtls_ssl_context *ssl, const unsigned char *cli_id, size_t cli_id_len, const unsigned char *in, size_t in_len, unsigned char *obuf, size_t buf_len, size_t *olen) { size_t sid_len, cookie_len, epoch, fragment_offset; unsigned char *p; /* * Structure of ClientHello with record and handshake headers, * and expected values. We don't need to check a lot, more checks will be * done when actually parsing the ClientHello - skipping those checks * avoids code duplication and does not make cookie forging any easier. * * 0-0 ContentType type; copied, must be handshake * 1-2 ProtocolVersion version; copied * 3-4 uint16 epoch; copied, must be 0 * 5-10 uint48 sequence_number; copied * 11-12 uint16 length; (ignored) * * 13-13 HandshakeType msg_type; (ignored) * 14-16 uint24 length; (ignored) * 17-18 uint16 message_seq; copied * 19-21 uint24 fragment_offset; copied, must be 0 * 22-24 uint24 fragment_length; (ignored) * * 25-26 ProtocolVersion client_version; (ignored) * 27-58 Random random; (ignored) * 59-xx SessionID session_id; 1 byte len + sid_len content * 60+ opaque cookie<0..2^8-1>; 1 byte len + content * ... * * Minimum length is 61 bytes. */ MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: in_len=%u", (unsigned) in_len)); MBEDTLS_SSL_DEBUG_BUF(4, "cli_id", cli_id, cli_id_len); if (in_len < 61) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: record too short")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } epoch = MBEDTLS_GET_UINT16_BE(in, 3); fragment_offset = MBEDTLS_GET_UINT24_BE(in, 19); if (in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 || fragment_offset != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: not a good ClientHello")); MBEDTLS_SSL_DEBUG_MSG(4, (" type=%u epoch=%u fragment_offset=%u", in[0], (unsigned) epoch, (unsigned) fragment_offset)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } sid_len = in[59]; if (59 + 1 + sid_len + 1 > in_len) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: sid_len=%u > %u", (unsigned) sid_len, (unsigned) in_len - 61)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "sid received from network", in + 60, sid_len); cookie_len = in[60 + sid_len]; if (59 + 1 + sid_len + 1 + cookie_len > in_len) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: cookie_len=%u > %u", (unsigned) cookie_len, (unsigned) (in_len - sid_len - 61))); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "cookie received from network", in + sid_len + 61, cookie_len); if (ssl->conf->f_cookie_check(ssl->conf->p_cookie, in + sid_len + 61, cookie_len, cli_id, cli_id_len) == 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("check cookie: valid")); return 0; } /* * If we get here, we've got an invalid cookie, let's prepare HVR. * * 0-0 ContentType type; copied * 1-2 ProtocolVersion version; copied * 3-4 uint16 epoch; copied * 5-10 uint48 sequence_number; copied * 11-12 uint16 length; olen - 13 * * 13-13 HandshakeType msg_type; hello_verify_request * 14-16 uint24 length; olen - 25 * 17-18 uint16 message_seq; copied * 19-21 uint24 fragment_offset; copied * 22-24 uint24 fragment_length; olen - 25 * * 25-26 ProtocolVersion server_version; 0xfe 0xff * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie * * Minimum length is 28. */ if (buf_len < 28) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* Copy most fields and adapt others */ memcpy(obuf, in, 25); obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; obuf[25] = 0xfe; obuf[26] = 0xff; /* Generate and write actual cookie */ p = obuf + 28; if (ssl->conf->f_cookie_write(ssl->conf->p_cookie, &p, obuf + buf_len, cli_id, cli_id_len) != 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } *olen = (size_t) (p - obuf); /* Go back and fill length fields */ obuf[27] = (unsigned char) (*olen - 28); obuf[14] = obuf[22] = MBEDTLS_BYTE_2(*olen - 25); obuf[15] = obuf[23] = MBEDTLS_BYTE_1(*olen - 25); obuf[16] = obuf[24] = MBEDTLS_BYTE_0(*olen - 25); MBEDTLS_PUT_UINT16_BE(*olen - 13, obuf, 11); return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; } /* * Handle possible client reconnect with the same UDP quadruplet * (RFC 6347 Section 4.2.8). * * Called by ssl_parse_record_header() in case we receive an epoch 0 record * that looks like a ClientHello. * * - if the input looks like a ClientHello without cookies, * send back HelloVerifyRequest, then return 0 * - if the input looks like a ClientHello with a valid cookie, * reset the session of the current context, and * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT * - if anything goes wrong, return a specific error code * * This function is called (through ssl_check_client_reconnect()) when an * unexpected record is found in ssl_get_next_record(), which will discard the * record if we return 0, and bubble up the return value otherwise (this * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected * errors, and is the right thing to do in both cases). */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (ssl->conf->f_cookie_write == NULL || ssl->conf->f_cookie_check == NULL) { /* If we can't use cookies to verify reachability of the peer, * drop the record. */ MBEDTLS_SSL_DEBUG_MSG(1, ("no cookie callbacks, " "can't check reconnect validity")); return 0; } ret = mbedtls_ssl_check_dtls_clihlo_cookie( ssl, ssl->cli_id, ssl->cli_id_len, ssl->in_buf, ssl->in_left, ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len); MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret); if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { int send_ret; MBEDTLS_SSL_DEBUG_MSG(1, ("sending HelloVerifyRequest")); MBEDTLS_SSL_DEBUG_BUF(4, "output record sent to network", ssl->out_buf, len); /* Don't check write errors as we can't do anything here. * If the error is permanent we'll catch it later, * if it's not, then hopefully it'll work next time. */ send_ret = ssl->f_send(ssl->p_bio, ssl->out_buf, len); MBEDTLS_SSL_DEBUG_RET(2, "ssl->f_send", send_ret); (void) send_ret; return 0; } if (ret == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("cookie is valid, resetting context")); if ((ret = mbedtls_ssl_session_reset_int(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "reset", ret); return ret; } return MBEDTLS_ERR_SSL_CLIENT_RECONNECT; } return ret; } #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_record_type(uint8_t record_type) { if (record_type != MBEDTLS_SSL_MSG_HANDSHAKE && record_type != MBEDTLS_SSL_MSG_ALERT && record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } return 0; } /* * ContentType type; * ProtocolVersion version; * uint16 epoch; // DTLS only * uint48 sequence_number; // DTLS only * uint16 length; * * Return 0 if header looks sane (and, for DTLS, the record is expected) * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. * * With DTLS, mbedtls_ssl_read_record() will: * 1. proceed with the record if this function returns 0 * 2. drop only the current record if this function returns UNEXPECTED_RECORD * 3. return CLIENT_RECONNECT if this function return that value * 4. drop the whole datagram if this function returns anything else. * Point 2 is needed when the peer is resending, and we have already received * the first record from a datagram but are still waiting for the others. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_record_header(mbedtls_ssl_context const *ssl, unsigned char *buf, size_t len, mbedtls_record *rec) { mbedtls_ssl_protocol_version tls_version; size_t const rec_hdr_type_offset = 0; size_t const rec_hdr_type_len = 1; size_t const rec_hdr_version_offset = rec_hdr_type_offset + rec_hdr_type_len; size_t const rec_hdr_version_len = 2; size_t const rec_hdr_ctr_len = 8; #if defined(MBEDTLS_SSL_PROTO_DTLS) uint32_t rec_epoch; size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + rec_hdr_version_len; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; size_t rec_hdr_cid_len = 0; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ size_t rec_hdr_len_offset; /* To be determined */ size_t const rec_hdr_len_len = 2; /* * Check minimum lengths for record header. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; } if (len < rec_hdr_len_offset + rec_hdr_len_len) { MBEDTLS_SSL_DEBUG_MSG(1, ( "datagram of length %u too small to hold DTLS record header of length %u", (unsigned) len, (unsigned) (rec_hdr_len_len + rec_hdr_len_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* * Parse and validate record content type */ rec->type = buf[rec_hdr_type_offset]; /* Check record content type */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) rec->cid_len = 0; if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->conf->cid_len != 0 && rec->type == MBEDTLS_SSL_MSG_CID) { /* Shift pointers to account for record header including CID * struct { * ContentType outer_type = tls12_cid; * ProtocolVersion version; * uint16 epoch; * uint48 sequence_number; * opaque cid[cid_length]; // Additional field compared to * // default DTLS record format * uint16 length; * opaque enc_content[DTLSCiphertext.length]; * } DTLSCiphertext; */ /* So far, we only support static CID lengths * fixed in the configuration. */ rec_hdr_cid_len = ssl->conf->cid_len; rec_hdr_len_offset += rec_hdr_cid_len; if (len < rec_hdr_len_offset + rec_hdr_len_len) { MBEDTLS_SSL_DEBUG_MSG(1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", (unsigned) len, (unsigned) (rec_hdr_len_offset + rec_hdr_len_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* configured CID len is guaranteed at most 255, see * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ rec->cid_len = (uint8_t) rec_hdr_cid_len; memcpy(rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len); } else #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ { if (ssl_check_record_type(rec->type)) { MBEDTLS_SSL_DEBUG_MSG(1, ("unknown record type %u", (unsigned) rec->type)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } } /* * Parse and validate record version */ rec->ver[0] = buf[rec_hdr_version_offset + 0]; rec->ver[1] = buf[rec_hdr_version_offset + 1]; tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version( buf + rec_hdr_version_offset, ssl->conf->transport); if (tls_version > ssl->conf->max_tls_version) { MBEDTLS_SSL_DEBUG_MSG(1, ("TLS version mismatch: got %u, expected max %u", (unsigned) tls_version, (unsigned) ssl->conf->max_tls_version)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* * Parse/Copy record sequence number. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Copy explicit record sequence number from input buffer. */ memcpy(&rec->ctr[0], buf + rec_hdr_ctr_offset, rec_hdr_ctr_len); } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { /* Copy implicit record sequence number from SSL context structure. */ memcpy(&rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len); } /* * Parse record length. */ rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; rec->data_len = MBEDTLS_GET_UINT16_BE(buf, rec_hdr_len_offset); MBEDTLS_SSL_DEBUG_BUF(4, "input record header", buf, rec->data_offset); MBEDTLS_SSL_DEBUG_MSG(3, ("input record: msgtype = %u, " "version = [0x%x], msglen = %" MBEDTLS_PRINTF_SIZET, rec->type, (unsigned) tls_version, rec->data_len)); rec->buf = buf; rec->buf_len = rec->data_offset + rec->data_len; if (rec->data_len == 0) { return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* * DTLS-related tests. * Check epoch before checking length constraint because * the latter varies with the epoch. E.g., if a ChangeCipherSpec * message gets duplicated before the corresponding Finished message, * the second ChangeCipherSpec should be discarded because it belongs * to an old epoch, but not because its length is shorter than * the minimum record length for packets using the new record transform. * Note that these two kinds of failures are handled differently, * as an unexpected record is silently skipped but an invalid * record leads to the entire datagram being dropped. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { rec_epoch = MBEDTLS_GET_UINT16_BE(rec->ctr, 0); /* Check that the datagram is large enough to contain a record * of the advertised length. */ if (len < rec->data_offset + rec->data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ( "Datagram of length %u too small to contain record of advertised length %u.", (unsigned) len, (unsigned) (rec->data_offset + rec->data_len))); return MBEDTLS_ERR_SSL_INVALID_RECORD; } /* Records from other, non-matching epochs are silently discarded. * (The case of same-port Client reconnects must be considered in * the caller). */ if (rec_epoch != ssl->in_epoch) { MBEDTLS_SSL_DEBUG_MSG(1, ("record from another epoch: " "expected %u, received %lu", ssl->in_epoch, (unsigned long) rec_epoch)); /* Records from the next epoch are considered for buffering * (concretely: early Finished messages). */ if (rec_epoch == (unsigned) ssl->in_epoch + 1) { MBEDTLS_SSL_DEBUG_MSG(2, ("Consider record for buffering")); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) /* For records from the correct epoch, check whether their * sequence number has been seen before. */ else if (mbedtls_ssl_dtls_record_replay_check((mbedtls_ssl_context *) ssl, &rec->ctr[0]) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record")); return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } #endif } #endif /* MBEDTLS_SSL_PROTO_DTLS */ return 0; } #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl) { unsigned int rec_epoch = MBEDTLS_GET_UINT16_BE(ssl->in_ctr, 0); /* * Check for an epoch 0 ClientHello. We can't use in_msg here to * access the first byte of record content (handshake type), as we * have an active transform (possibly iv_len != 0), so use the * fact that the record header len is 13 instead. */ if (rec_epoch == 0 && ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && mbedtls_ssl_is_handshake_over(ssl) == 1 && ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_left > 13 && ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("possible client reconnect " "from the same port")); return ssl_handle_possible_reconnect(ssl); } return 0; } #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ /* * If applicable, decrypt record content */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_record_content(mbedtls_ssl_context *ssl, mbedtls_record *rec) { int ret, done = 0; MBEDTLS_SSL_DEBUG_BUF(4, "input record from network", rec->buf, rec->buf_len); /* * In TLS 1.3, always treat ChangeCipherSpec records * as unencrypted. The only thing we do with them is * check the length and content and ignore them. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->transform_in != NULL && ssl->transform_in->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { if (rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { done = 1; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (!done && ssl->transform_in != NULL) { unsigned char const old_msg_type = rec->type; if ((ret = mbedtls_ssl_decrypt_buf(ssl, ssl->transform_in, rec)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_decrypt_buf", ret); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) /* * Although the server rejected early data, it might receive early * data as long as it has not received the client Finished message. * It is encrypted with early keys and should be ignored as stated * in section 4.2.10 of RFC 8446: * * "Ignore the extension and return a regular 1-RTT response. The * server then skips past early data by attempting to deprotect * received records using the handshake traffic key, discarding * records which fail deprotection (up to the configured * max_early_data_size). Once a record is deprotected successfully, * it is treated as the start of the client's second flight and the * server proceeds as with an ordinary 1-RTT handshake." */ if ((old_msg_type == MBEDTLS_SSL_MSG_APPLICATION_DATA) && (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) { MBEDTLS_SSL_DEBUG_MSG( 3, ("EarlyData: deprotect and discard app data records.")); ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len); if (ret != 0) { return ret; } ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && ssl->conf->ignore_unexpected_cid == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) { MBEDTLS_SSL_DEBUG_MSG(3, ("ignoring unexpected CID")); ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * The decryption of the record failed, no reason to ignore it, * return in error with the decryption error code. */ return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) /* * If the server were discarding protected records that it fails to * deprotect because it has rejected early data, as we have just * deprotected successfully a record, the server has to resume normal * operation and fail the connection if the deprotection of a record * fails. */ if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD) { ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ if (old_msg_type != rec->type) { MBEDTLS_SSL_DEBUG_MSG(4, ("record type after decrypt (before %d): %d", old_msg_type, rec->type)); } MBEDTLS_SSL_DEBUG_BUF(4, "input payload after decrypt", rec->buf + rec->data_offset, rec->data_len); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* We have already checked the record content type * in ssl_parse_record_header(), failing or silently * dropping the record in the case of an unknown type. * * Since with the use of CIDs, the record content type * might change during decryption, re-check the record * content type, but treat a failure as fatal this time. */ if (ssl_check_record_type(rec->type)) { MBEDTLS_SSL_DEBUG_MSG(1, ("unknown record type")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ if (rec->data_len == 0) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA) { /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ MBEDTLS_SSL_DEBUG_MSG(1, ("invalid zero-length message type: %d", ssl->in_msgtype)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ ssl->nb_zero++; /* * Three or more empty messages may be a DoS attack * (excessive CPU consumption). */ if (ssl->nb_zero > 3) { MBEDTLS_SSL_DEBUG_MSG(1, ("received four consecutive empty " "messages, possible DoS attack")); /* Treat the records as if they were not properly authenticated, * thereby failing the connection if we see more than allowed * by the configured bad MAC threshold. */ return MBEDTLS_ERR_SSL_INVALID_MAC; } } else { ssl->nb_zero = 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ; /* in_ctr read from peer, not maintained internally */ } else #endif { unsigned i; for (i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; i > mbedtls_ssl_ep_len(ssl); i--) { if (++ssl->in_ctr[i - 1] != 0) { break; } } /* The loop goes to its end iff the counter is wrapping */ if (i == mbedtls_ssl_ep_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("incoming message counter would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) /* * Although the server rejected early data because it needed to send an * HelloRetryRequest message, it might receive early data as long as it has * not received the client Finished message. * The early data is encrypted with early keys and should be ignored as * stated in section 4.2.10 of RFC 8446 (second case): * * "The server then ignores early data by skipping all records with an * external content type of "application_data" (indicating that they are * encrypted), up to the configured max_early_data_size. Ignore application * data message before 2nd ClientHello when early_data was received in 1st * ClientHello." */ if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) { if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) { ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len); if (ret != 0) { return ret; } MBEDTLS_SSL_DEBUG_MSG( 3, ("EarlyData: Ignore application message before 2nd ClientHello")); return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) { ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; } } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_dtls_replay_update(ssl); } #endif /* Check actual (decrypted) record content length against * configured maximum. */ if (rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad message length")); return MBEDTLS_ERR_SSL_INVALID_RECORD; } return 0; } /* * Read a record. * * Silently ignore non-fatal alert (and for DTLS, invalid records as well, * RFC 6347 4.1.2.7) and continue reading until a valid record is found. * */ /* Helper functions for mbedtls_ssl_read_record(). */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_consume_current_message(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_next_record(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl); int mbedtls_ssl_read_record(mbedtls_ssl_context *ssl, unsigned update_hs_digest) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> read record")); if (ssl->keep_current_message == 0) { do { ret = ssl_consume_current_message(ssl); if (ret != 0) { return ret; } if (ssl_record_is_in_progress(ssl) == 0) { int dtls_have_buffered = 0; #if defined(MBEDTLS_SSL_PROTO_DTLS) /* We only check for buffered messages if the * current datagram is fully consumed. */ if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl_next_record_is_in_datagram(ssl) == 0) { if (ssl_load_buffered_message(ssl) == 0) { dtls_have_buffered = 1; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if (dtls_have_buffered == 0) { ret = ssl_get_next_record(ssl); if (ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) { continue; } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_get_next_record"), ret); return ret; } } } ret = mbedtls_ssl_handle_message_type(ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) { /* Buffer future message */ ret = ssl_buffer_message(ssl); if (ret != 0) { return ret; } ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ } while (MBEDTLS_ERR_SSL_NON_FATAL == ret || MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_handle_message_type"), ret); return ret; } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && update_hs_digest == 1) { ret = mbedtls_ssl_update_handshake_status(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); return ret; } } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("reuse previously read message")); ssl->keep_current_message = 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= read record")); return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl) { if (ssl->in_left > ssl->next_record_offset) { return 1; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_message(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; mbedtls_ssl_hs_buffer *hs_buf; int ret = 0; if (hs == NULL) { return -1; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_load_buffered_message")); if (ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) { /* Check if we have seen a ChangeCipherSpec before. * If yes, synthesize a CCS record. */ if (!hs->buffering.seen_ccs) { MBEDTLS_SSL_DEBUG_MSG(2, ("CCS not seen in the current flight")); ret = -1; goto exit; } MBEDTLS_SSL_DEBUG_MSG(2, ("Injecting buffered CCS message")); ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; ssl->in_msglen = 1; ssl->in_msg[0] = 1; /* As long as they are equal, the exact value doesn't matter. */ ssl->in_left = 0; ssl->next_record_offset = 0; hs->buffering.seen_ccs = 0; goto exit; } #if defined(MBEDTLS_DEBUG_C) /* Debug only */ { unsigned offset; for (offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { hs_buf = &hs->buffering.hs[offset]; if (hs_buf->is_valid == 1) { MBEDTLS_SSL_DEBUG_MSG(2, ("Future message with sequence number %u %s buffered.", hs->in_msg_seq + offset, hs_buf->is_complete ? "fully" : "partially")); } } } #endif /* MBEDTLS_DEBUG_C */ /* Check if we have buffered and/or fully reassembled the * next handshake message. */ hs_buf = &hs->buffering.hs[0]; if ((hs_buf->is_valid == 1) && (hs_buf->is_complete == 1)) { /* Synthesize a record containing the buffered HS message. */ size_t msg_len = MBEDTLS_GET_UINT24_BE(hs_buf->data, 1); /* Double-check that we haven't accidentally buffered * a message that doesn't fit into the input buffer. */ if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("Next handshake message has been buffered - load")); MBEDTLS_SSL_DEBUG_BUF(3, "Buffered handshake message (incl. header)", hs_buf->data, msg_len + 12); ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->in_hslen = msg_len + 12; ssl->in_msglen = msg_len + 12; memcpy(ssl->in_msg, hs_buf->data, ssl->in_hslen); ret = 0; goto exit; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Next handshake message %u not or only partially bufffered", hs->in_msg_seq)); } ret = -1; exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_load_buffered_message")); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_make_space(mbedtls_ssl_context *ssl, size_t desired) { int offset; mbedtls_ssl_handshake_params * const hs = ssl->handshake; MBEDTLS_SSL_DEBUG_MSG(2, ("Attempt to free buffered messages to have %u bytes available", (unsigned) desired)); /* Get rid of future records epoch first, if such exist. */ ssl_free_buffered_record(ssl); /* Check if we have enough space available now. */ if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { MBEDTLS_SSL_DEBUG_MSG(2, ("Enough space available after freeing future epoch record")); return 0; } /* We don't have enough space to buffer the next expected handshake * message. Remove buffers used for future messages to gain space, * starting with the most distant one. */ for (offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; offset >= 0; offset--) { MBEDTLS_SSL_DEBUG_MSG(2, ( "Free buffering slot %d to make space for reassembly of next handshake message", offset)); ssl_buffering_free_slot(ssl, (uint8_t) offset); /* Check if we have enough space available now. */ if (desired <= (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { MBEDTLS_SSL_DEBUG_MSG(2, ("Enough space available after freeing buffered HS messages")); return 0; } } return -1; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_message(mbedtls_ssl_context *ssl) { int ret = 0; mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (hs == NULL) { return 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_buffer_message")); switch (ssl->in_msgtype) { case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: MBEDTLS_SSL_DEBUG_MSG(2, ("Remember CCS message")); hs->buffering.seen_ccs = 1; break; case MBEDTLS_SSL_MSG_HANDSHAKE: { unsigned recv_msg_seq_offset; unsigned recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); mbedtls_ssl_hs_buffer *hs_buf; size_t msg_len = ssl->in_hslen - 12; /* We should never receive an old handshake * message - double-check nonetheless. */ if (recv_msg_seq < ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; if (recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS) { /* Silently ignore -- message too far in the future */ MBEDTLS_SSL_DEBUG_MSG(2, ("Ignore future HS message with sequence number %u, " "buffering window %u - %u", recv_msg_seq, ssl->handshake->in_msg_seq, ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1)); goto exit; } MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering HS message with sequence number %u, offset %u ", recv_msg_seq, recv_msg_seq_offset)); hs_buf = &hs->buffering.hs[recv_msg_seq_offset]; /* Check if the buffering for this seq nr has already commenced. */ if (!hs_buf->is_valid) { size_t reassembly_buf_sz; hs_buf->is_fragmented = (ssl_hs_is_proper_fragment(ssl) == 1); /* We copy the message back into the input buffer * after reassembly, so check that it's not too large. * This is an implementation-specific limitation * and not one from the standard, hence it is not * checked in ssl_check_hs_header(). */ if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) { /* Ignore message */ goto exit; } /* Check if we have enough space to buffer the message. */ if (hs->buffering.total_bytes_buffered > MBEDTLS_SSL_DTLS_MAX_BUFFERING) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } reassembly_buf_sz = ssl_get_reassembly_buffer_size(msg_len, hs_buf->is_fragmented); if (reassembly_buf_sz > (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { if (recv_msg_seq_offset > 0) { /* If we can't buffer a future message because * of space limitations -- ignore. */ MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future message of size %" MBEDTLS_PRINTF_SIZET " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- ignore\n", msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); goto exit; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future message of size %" MBEDTLS_PRINTF_SIZET " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- attempt to make space by freeing buffered future messages\n", msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); } if (ssl_buffer_make_space(ssl, reassembly_buf_sz) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed" " the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- fail\n", msg_len, reassembly_buf_sz, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; goto exit; } } MBEDTLS_SSL_DEBUG_MSG(2, ("initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET, msg_len)); hs_buf->data = mbedtls_calloc(1, reassembly_buf_sz); if (hs_buf->data == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } hs_buf->data_len = reassembly_buf_sz; /* Prepare final header: copy msg_type, length and message_seq, * then add standardised fragment_offset and fragment_length */ memcpy(hs_buf->data, ssl->in_msg, 6); memset(hs_buf->data + 6, 0, 3); memcpy(hs_buf->data + 9, hs_buf->data + 1, 3); hs_buf->is_valid = 1; hs->buffering.total_bytes_buffered += reassembly_buf_sz; } else { /* Make sure msg_type and length are consistent */ if (memcmp(hs_buf->data, ssl->in_msg, 4) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("Fragment header mismatch - ignore")); /* Ignore */ goto exit; } } if (!hs_buf->is_complete) { size_t frag_len, frag_off; unsigned char * const msg = hs_buf->data + 12; /* * Check and copy current fragment */ /* Validation of header fields already done in * mbedtls_ssl_prepare_handshake_record(). */ frag_off = ssl_get_hs_frag_off(ssl); frag_len = ssl_get_hs_frag_len(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("adding fragment, offset = %" MBEDTLS_PRINTF_SIZET ", length = %" MBEDTLS_PRINTF_SIZET, frag_off, frag_len)); memcpy(msg + frag_off, ssl->in_msg + 12, frag_len); if (hs_buf->is_fragmented) { unsigned char * const bitmask = msg + msg_len; ssl_bitmask_set(bitmask, frag_off, frag_len); hs_buf->is_complete = (ssl_bitmask_check(bitmask, msg_len) == 0); } else { hs_buf->is_complete = 1; } MBEDTLS_SSL_DEBUG_MSG(2, ("message %scomplete", hs_buf->is_complete ? "" : "not yet ")); } break; } default: /* We don't buffer other types of messages. */ break; } exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_buffer_message")); return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_consume_current_message(mbedtls_ssl_context *ssl) { /* * Consume last content-layer message and potentially * update in_msglen which keeps track of the contents' * consumption state. * * (1) Handshake messages: * Remove last handshake message, move content * and adapt in_msglen. * * (2) Alert messages: * Consume whole record content, in_msglen = 0. * * (3) Change cipher spec: * Consume whole record content, in_msglen = 0. * * (4) Application data: * Don't do anything - the record layer provides * the application data as a stream transport * and consumes through mbedtls_ssl_read only. * */ /* Case (1): Handshake messages */ if (ssl->in_hslen != 0) { /* Hard assertion to be sure that no application data * is in flight, as corrupting ssl->in_msglen during * ssl->in_offt != NULL is fatal. */ if (ssl->in_offt != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Get next Handshake message in the current record */ /* Notes: * (1) in_hslen is not necessarily the size of the * current handshake content: If DTLS handshake * fragmentation is used, that's the fragment * size instead. Using the total handshake message * size here is faulty and should be changed at * some point. * (2) While it doesn't seem to cause problems, one * has to be very careful not to assume that in_hslen * is always <= in_msglen in a sensible communication. * Again, it's wrong for DTLS handshake fragmentation. * The following check is therefore mandatory, and * should not be treated as a silently corrected assertion. * Additionally, ssl->in_hslen might be arbitrarily out of * bounds after handling a DTLS message with an unexpected * sequence number, see mbedtls_ssl_prepare_handshake_record. */ if (ssl->in_hslen < ssl->in_msglen) { ssl->in_msglen -= ssl->in_hslen; memmove(ssl->in_msg, ssl->in_msg + ssl->in_hslen, ssl->in_msglen); MBEDTLS_SSL_DEBUG_BUF(4, "remaining content in record", ssl->in_msg, ssl->in_msglen); } else { ssl->in_msglen = 0; } ssl->in_hslen = 0; } /* Case (4): Application data */ else if (ssl->in_offt != NULL) { return 0; } /* Everything else (CCS & Alerts) */ else { ssl->in_msglen = 0; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_record_is_in_progress(mbedtls_ssl_context *ssl) { if (ssl->in_msglen > 0) { return 1; } return 0; } #if defined(MBEDTLS_SSL_PROTO_DTLS) static void ssl_free_buffered_record(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (hs == NULL) { return; } if (hs->buffering.future_record.data != NULL) { hs->buffering.total_bytes_buffered -= hs->buffering.future_record.len; mbedtls_free(hs->buffering.future_record.data); hs->buffering.future_record.data = NULL; } } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_load_buffered_record(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; unsigned char *rec; size_t rec_len; unsigned rec_epoch; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 0; } if (hs == NULL) { return 0; } rec = hs->buffering.future_record.data; rec_len = hs->buffering.future_record.len; rec_epoch = hs->buffering.future_record.epoch; if (rec == NULL) { return 0; } /* Only consider loading future records if the * input buffer is empty. */ if (ssl_next_record_is_in_datagram(ssl) == 1) { return 0; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_load_buffered_record")); if (rec_epoch != ssl->in_epoch) { MBEDTLS_SSL_DEBUG_MSG(2, ("Buffered record not from current epoch.")); goto exit; } MBEDTLS_SSL_DEBUG_MSG(2, ("Found buffered record from current epoch - load")); /* Double-check that the record is not too large */ if (rec_len > in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf)) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(ssl->in_hdr, rec, rec_len); ssl->in_left = rec_len; ssl->next_record_offset = 0; ssl_free_buffered_record(ssl); exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_load_buffered_record")); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_buffer_future_record(mbedtls_ssl_context *ssl, mbedtls_record const *rec) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; /* Don't buffer future records outside handshakes. */ if (hs == NULL) { return 0; } /* Only buffer handshake records (we are only interested * in Finished messages). */ if (rec->type != MBEDTLS_SSL_MSG_HANDSHAKE) { return 0; } /* Don't buffer more than one future epoch record. */ if (hs->buffering.future_record.data != NULL) { return 0; } /* Don't buffer record if there's not enough buffering space remaining. */ if (rec->buf_len > (MBEDTLS_SSL_DTLS_MAX_BUFFERING - hs->buffering.total_bytes_buffered)) { MBEDTLS_SSL_DEBUG_MSG(2, ("Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET " (already %" MBEDTLS_PRINTF_SIZET " bytes buffered) -- ignore\n", rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, hs->buffering.total_bytes_buffered)); return 0; } /* Buffer record */ MBEDTLS_SSL_DEBUG_MSG(2, ("Buffer record from epoch %u", ssl->in_epoch + 1U)); MBEDTLS_SSL_DEBUG_BUF(3, "Buffered record", rec->buf, rec->buf_len); /* ssl_parse_record_header() only considers records * of the next epoch as candidates for buffering. */ hs->buffering.future_record.epoch = ssl->in_epoch + 1; hs->buffering.future_record.len = rec->buf_len; hs->buffering.future_record.data = mbedtls_calloc(1, hs->buffering.future_record.len); if (hs->buffering.future_record.data == NULL) { /* If we run out of RAM trying to buffer a * record from the next epoch, just ignore. */ return 0; } memcpy(hs->buffering.future_record.data, rec->buf, rec->buf_len); hs->buffering.total_bytes_buffered += rec->buf_len; return 0; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_next_record(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_record rec; #if defined(MBEDTLS_SSL_PROTO_DTLS) /* We might have buffered a future record; if so, * and if the epoch matches now, load it. * On success, this call will set ssl->in_left to * the length of the buffered record, so that * the calls to ssl_fetch_input() below will * essentially be no-ops. */ ret = ssl_load_buffered_record(ssl); if (ret != 0) { return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* Ensure that we have enough space available for the default form * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, * with no space for CIDs counted in). */ ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } ret = ssl_parse_record_header(ssl, ssl->in_hdr, ssl->in_left, &rec); if (ret != 0) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { if (ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE) { ret = ssl_buffer_future_record(ssl, &rec); if (ret != 0) { return ret; } /* Fall through to handling of unexpected records */ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) { #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) /* Reset in pointers to default state for TLS/DTLS records, * assuming no CID and no offset between record content and * record plaintext. */ mbedtls_ssl_update_in_pointers(ssl); /* Setup internal message pointers from record structure. */ ssl->in_msgtype = rec.type; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_len = ssl->in_cid + rec.cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_msg = ssl->in_len + 2; ssl->in_msglen = rec.data_len; ret = ssl_check_client_reconnect(ssl); MBEDTLS_SSL_DEBUG_RET(2, "ssl_check_client_reconnect", ret); if (ret != 0) { return ret; } #endif /* Skip unexpected record (but not whole datagram) */ ssl->next_record_offset = rec.buf_len; MBEDTLS_SSL_DEBUG_MSG(1, ("discarding unexpected record " "(header)")); } else { /* Skip invalid record and the rest of the datagram */ ssl->next_record_offset = 0; ssl->in_left = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("discarding invalid record " "(header)")); } /* Get next record */ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } else #endif { return ret; } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Remember offset of next record within datagram. */ ssl->next_record_offset = rec.buf_len; if (ssl->next_record_offset < ssl->in_left) { MBEDTLS_SSL_DEBUG_MSG(3, ("more than one record within datagram")); } } else #endif { /* * Fetch record contents from underlying transport. */ ret = mbedtls_ssl_fetch_input(ssl, rec.buf_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } ssl->in_left = 0; } /* * Decrypt record contents. */ if ((ret = ssl_prepare_record_content(ssl, &rec)) != 0) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Silently discard invalid records */ if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { /* Except when waiting for Finished as a bad mac here * probably means something went wrong in the handshake * (eg wrong psk used, mitm downgrade attempt, etc.) */ if (ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || ssl->state == MBEDTLS_SSL_SERVER_FINISHED) { #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); } #endif return ret; } if (ssl->conf->badmac_limit != 0 && ++ssl->badmac_seen >= ssl->conf->badmac_limit) { MBEDTLS_SSL_DEBUG_MSG(1, ("too many records with bad MAC")); return MBEDTLS_ERR_SSL_INVALID_MAC; } /* As above, invalid records cause * dismissal of the whole datagram. */ ssl->next_record_offset = 0; ssl->in_left = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("discarding invalid record (mac)")); return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; } return ret; } else #endif { /* Error out (and send alert) on invalid records */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); } #endif return ret; } } /* Reset in pointers to default state for TLS/DTLS records, * assuming no CID and no offset between record content and * record plaintext. */ mbedtls_ssl_update_in_pointers(ssl); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_len = ssl->in_cid + rec.cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_len + 2; /* The record content type may change during decryption, * so re-read it. */ ssl->in_msgtype = rec.type; /* Also update the input buffer, because unfortunately * the server-side ssl_parse_client_hello() reparses the * record header when receiving a ClientHello initiating * a renegotiation. */ ssl->in_hdr[0] = rec.type; ssl->in_msg = rec.buf + rec.data_offset; ssl->in_msglen = rec.data_len; MBEDTLS_PUT_UINT16_BE(rec.data_len, ssl->in_len, 0); return 0; } int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * Handle particular types of records */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { if ((ret = mbedtls_ssl_prepare_handshake_record(ssl)) != 0) { return ret; } } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { if (ssl->in_msglen != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } if (ssl->in_msg[0] != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid CCS message, content: %02x", ssl->in_msg[0])); return MBEDTLS_ERR_SSL_INVALID_RECORD; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC) { if (ssl->handshake == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("dropping ChangeCipherSpec outside handshake")); return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; } MBEDTLS_SSL_DEBUG_MSG(1, ("received out-of-order ChangeCipherSpec - remember")); return MBEDTLS_ERR_SSL_EARLY_MESSAGE; } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) MBEDTLS_SSL_DEBUG_MSG(1, ("Ignore ChangeCipherSpec in TLS 1.3 compatibility mode")); return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; #else MBEDTLS_SSL_DEBUG_MSG(1, ("ChangeCipherSpec invalid in TLS 1.3 without compatibility mode")); return MBEDTLS_ERR_SSL_INVALID_RECORD; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) { if (ssl->in_msglen != 2) { /* Note: Standard allows for more than one 2 byte alert to be packed in a single message, but Mbed TLS doesn't currently support this. */ MBEDTLS_SSL_DEBUG_MSG(1, ("invalid alert message, len: %" MBEDTLS_PRINTF_SIZET, ssl->in_msglen)); return MBEDTLS_ERR_SSL_INVALID_RECORD; } MBEDTLS_SSL_DEBUG_MSG(2, ("got an alert message, type: [%u:%u]", ssl->in_msg[0], ssl->in_msg[1])); /* * Ignore non-fatal alerts, except close_notify and no_renegotiation */ if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL) { MBEDTLS_SSL_DEBUG_MSG(1, ("is a fatal alert message (msg %d)", ssl->in_msg[1])); return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; } if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY) { MBEDTLS_SSL_DEBUG_MSG(2, ("is a close notify message")); return MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY; } #if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) if (ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION) { MBEDTLS_SSL_DEBUG_MSG(2, ("is a no renegotiation alert")); /* Will be handled when trying to parse ServerHello */ return 0; } #endif /* Silently ignore: fetch new message */ return MBEDTLS_ERR_SSL_NON_FATAL; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* Drop unexpected ApplicationData records, * except at the beginning of renegotiations */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && mbedtls_ssl_is_handshake_over(ssl) == 0 #if defined(MBEDTLS_SSL_RENEGOTIATION) && !(ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->state == MBEDTLS_SSL_SERVER_HELLO) #endif ) { MBEDTLS_SSL_DEBUG_MSG(1, ("dropping unexpected ApplicationData")); return MBEDTLS_ERR_SSL_NON_FATAL; } if (ssl->handshake != NULL && mbedtls_ssl_is_handshake_over(ssl) == 1) { mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ return 0; } int mbedtls_ssl_send_fatal_handshake_failure(mbedtls_ssl_context *ssl) { return mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); } int mbedtls_ssl_send_alert_message(mbedtls_ssl_context *ssl, unsigned char level, unsigned char message) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->out_left != 0) { return mbedtls_ssl_flush_output(ssl); } MBEDTLS_SSL_DEBUG_MSG(2, ("=> send alert message")); MBEDTLS_SSL_DEBUG_MSG(3, ("send alert level=%u message=%u", level, message)); ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; ssl->out_msglen = 2; ssl->out_msg[0] = level; ssl->out_msg[1] = message; if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= send alert message")); return 0; } int mbedtls_ssl_write_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; ssl->out_msglen = 1; ssl->out_msg[0] = 1; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec")); return 0; } int mbedtls_ssl_parse_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse change cipher spec")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad change cipher spec message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* CCS records are only accepted if they have length 1 and content '1', * so we don't need to check this here. */ /* * Switch to our negotiated transform and session parameters for inbound * data. */ MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for inbound data")); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform_in = ssl->transform_negotiate; #endif ssl->session_in = ssl->session_negotiate; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) mbedtls_ssl_dtls_replay_reset(ssl); #endif /* Increment epoch */ if (++ssl->in_epoch == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap")); /* This is highly unlikely to happen for legitimate reasons, so treat it as an attack and don't send an alert. */ return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); mbedtls_ssl_update_in_pointers(ssl); ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse change cipher spec")); return 0; } /* Once ssl->out_hdr as the address of the beginning of the * next outgoing record is set, deduce the other pointers. * * Note: For TLS, we save the implicit record sequence number * (entering MAC computation) in the 8 bytes before ssl->out_hdr, * and the caller has to make sure there's space for this. */ static size_t ssl_transform_get_explicit_iv_len( mbedtls_ssl_transform const *transform) { return transform->ivlen - transform->fixed_ivlen; } void mbedtls_ssl_update_out_pointers(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_ctr = ssl->out_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->out_len = ssl->out_cid; if (transform != NULL) { ssl->out_len += transform->out_cid_len; } #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->out_iv = ssl->out_len + 2; } else #endif { ssl->out_len = ssl->out_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->out_cid = ssl->out_len; #endif ssl->out_iv = ssl->out_hdr + 5; } ssl->out_msg = ssl->out_iv; /* Adjust out_msg to make space for explicit IV, if used. */ if (transform != NULL) { ssl->out_msg += ssl_transform_get_explicit_iv_len(transform); } } /* Once ssl->in_hdr as the address of the beginning of the * next incoming record is set, deduce the other pointers. * * Note: For TLS, we save the implicit record sequence number * (entering MAC computation) in the 8 bytes before ssl->in_hdr, * and the caller has to make sure there's space for this. */ void mbedtls_ssl_update_in_pointers(mbedtls_ssl_context *ssl) { /* This function sets the pointers to match the case * of unprotected TLS/DTLS records, with both ssl->in_iv * and ssl->in_msg pointing to the beginning of the record * content. * * When decrypting a protected record, ssl->in_msg * will be shifted to point to the beginning of the * record plaintext. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* This sets the header pointers to match records * without CID. When we receive a record containing * a CID, the fields are shifted accordingly in * ssl_parse_record_header(). */ ssl->in_ctr = ssl->in_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->in_len = ssl->in_cid; /* Default: no CID */ #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ ssl->in_iv = ssl->in_len + 2; } else #endif { ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; ssl->in_len = ssl->in_hdr + 3; #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl->in_cid = ssl->in_len; #endif ssl->in_iv = ssl->in_hdr + 5; } /* This will be adjusted at record decryption time. */ ssl->in_msg = ssl->in_iv; } /* * Setup an SSL context */ void mbedtls_ssl_reset_in_out_pointers(mbedtls_ssl_context *ssl) { /* Set the incoming and outgoing record pointers. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->out_hdr = ssl->out_buf; ssl->in_hdr = ssl->in_buf; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ { ssl->out_ctr = ssl->out_buf; ssl->out_hdr = ssl->out_buf + 8; ssl->in_hdr = ssl->in_buf + 8; } /* Derive other internal pointers. */ mbedtls_ssl_update_out_pointers(ssl, NULL /* no transform enabled */); mbedtls_ssl_update_in_pointers(ssl); } /* * SSL get accessors */ size_t mbedtls_ssl_get_bytes_avail(const mbedtls_ssl_context *ssl) { return ssl->in_offt == NULL ? 0 : ssl->in_msglen; } int mbedtls_ssl_check_pending(const mbedtls_ssl_context *ssl) { /* * Case A: We're currently holding back * a message for further processing. */ if (ssl->keep_current_message == 1) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: record held back for processing")); return 1; } /* * Case B: Further records are pending in the current datagram. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->in_left > ssl->next_record_offset) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: more records within current datagram")); return 1; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Case C: A handshake message is being processed. */ if (ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: more handshake messages within current record")); return 1; } /* * Case D: An application data message is being processed */ if (ssl->in_offt != NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: application data record is being processed")); return 1; } /* * In all other cases, the rest of the message can be dropped. * As in ssl_get_next_record, this needs to be adapted if * we implement support for multiple alerts in single records. */ MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_check_pending: nothing pending")); return 0; } int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl) { size_t transform_expansion = 0; const mbedtls_ssl_transform *transform = ssl->transform_out; unsigned block_size; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t key_type; #endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t out_hdr_len = mbedtls_ssl_out_hdr_len(ssl); if (transform == NULL) { return (int) out_hdr_len; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (transform->psa_alg == PSA_ALG_GCM || transform->psa_alg == PSA_ALG_CCM || transform->psa_alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 8) || transform->psa_alg == PSA_ALG_CHACHA20_POLY1305 || transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) { transform_expansion = transform->minlen; } else if (transform->psa_alg == PSA_ALG_CBC_NO_PADDING) { (void) psa_get_key_attributes(transform->psa_key_enc, &attr); key_type = psa_get_key_type(&attr); block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); /* Expansion due to the addition of the MAC. */ transform_expansion += transform->maclen; /* Expansion due to the addition of CBC padding; * Theoretically up to 256 bytes, but we never use * more than the block size of the underlying cipher. */ transform_expansion += block_size; /* For TLS 1.2 or higher, an explicit IV is added * after the record header. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) transform_expansion += block_size; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ } else { MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported psa_alg spotted in mbedtls_ssl_get_record_expansion()")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else switch (mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc)) { case MBEDTLS_MODE_GCM: case MBEDTLS_MODE_CCM: case MBEDTLS_MODE_CHACHAPOLY: case MBEDTLS_MODE_STREAM: transform_expansion = transform->minlen; break; case MBEDTLS_MODE_CBC: block_size = mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc); /* Expansion due to the addition of the MAC. */ transform_expansion += transform->maclen; /* Expansion due to the addition of CBC padding; * Theoretically up to 256 bytes, but we never use * more than the block size of the underlying cipher. */ transform_expansion += block_size; /* For TLS 1.2 or higher, an explicit IV is added * after the record header. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) transform_expansion += block_size; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ break; default: MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if (transform->out_cid_len != 0) { transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ return (int) (out_hdr_len + transform_expansion); } #if defined(MBEDTLS_SSL_RENEGOTIATION) /* * Check record counters and renegotiate if they're above the limit. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl) { size_t ep_len = mbedtls_ssl_ep_len(ssl); int in_ctr_cmp; int out_ctr_cmp; if (mbedtls_ssl_is_handshake_over(ssl) == 0 || ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED) { return 0; } in_ctr_cmp = memcmp(ssl->in_ctr + ep_len, &ssl->conf->renego_period[ep_len], MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len); out_ctr_cmp = memcmp(&ssl->cur_out_ctr[ep_len], &ssl->conf->renego_period[ep_len], sizeof(ssl->cur_out_ctr) - ep_len); if (in_ctr_cmp <= 0 && out_ctr_cmp <= 0) { return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("record counter limit reached: renegotiate")); return mbedtls_ssl_renegotiate(ssl); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl) { if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) || (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET)) { return 0; } ssl->keep_current_message = 1; MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); return MBEDTLS_ERR_SSL_WANT_READ; } #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message")); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { int ret = ssl_tls13_check_new_session_ticket(ssl); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ /* Fail in all other cases. */ return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* This function is called from mbedtls_ssl_read() when a handshake message is * received after the initial handshake. In this context, handshake messages * may only be sent for the purpose of initiating renegotiations. * * This function is introduced as a separate helper since the handling * of post-handshake handshake messages changes significantly in TLS 1.3, * and having a helper function allows to distinguish between TLS <= 1.2 and * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read(). */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * - For client-side, expect SERVER_HELLO_REQUEST. * - For server-side, expect CLIENT_HELLO. * - Fail (TLS) or silently drop record (DTLS) in other cases. */ #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && (ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl))) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not HelloRequest)")); /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 0; } #endif return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("handshake received (not ClientHello)")); /* With DTLS, drop the packet (probably from last handshake) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return 0; } #endif return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_RENEGOTIATION) /* Determine whether renegotiation attempt should be accepted */ if (!(ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION))) { /* * Accept renegotiation request */ /* DTLS clients need to know renego is server-initiated */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; } #endif ret = mbedtls_ssl_start_renegotiation(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret); return ret; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { /* * Refuse renegotiation */ MBEDTLS_SSL_DEBUG_MSG(3, ("refusing renegotiation, sending alert")); if ((ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_WARNING, MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION)) != 0) { return ret; } } return 0; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl) { /* Check protocol version and dispatch accordingly. */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { return ssl_tls13_handle_hs_message_post_handshake(ssl); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { return ssl_tls12_handle_hs_message_post_handshake(ssl); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* Should never happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * brief Read at most 'len' application data bytes from the input * buffer. * * param ssl SSL context: * - First byte of application data not read yet in the input * buffer located at address `in_offt`. * - The number of bytes of data not read yet is `in_msglen`. * param buf buffer that will hold the data * param len maximum number of bytes to read * * note The function updates the fields `in_offt` and `in_msglen` * according to the number of bytes read. * * return The number of bytes read. */ static int ssl_read_application_data( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { size_t n = (len < ssl->in_msglen) ? len : ssl->in_msglen; if (len != 0) { memcpy(buf, ssl->in_offt, n); ssl->in_msglen -= n; } /* Zeroising the plaintext buffer to erase unused application data from the memory. */ mbedtls_platform_zeroize(ssl->in_offt, n); if (ssl->in_msglen == 0) { /* all bytes consumed */ ssl->in_offt = NULL; ssl->keep_current_message = 0; } else { /* more data available */ ssl->in_offt += n; } return (int) n; } /* * Receive application data decrypted from the SSL layer */ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> read")); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } if (ssl->handshake != NULL && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { return ret; } } } #endif /* * Check if renegotiation is necessary and/or handshake is * in process. If yes, perform/continue, and fall through * if an unexpected packet is received while the client * is waiting for the ServerHello. * * (There is no equivalent to the last condition on * the server-side as it is not treated as within * a handshake while waiting for the ClientHello * after a renegotiation request.) */ #if defined(MBEDTLS_SSL_RENEGOTIATION) ret = ssl_check_ctr_renegotiate(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret); return ret; } #endif if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake(ssl); if (ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } /* Loop as long as no application data record is available */ while (ssl->in_offt == NULL) { /* Start timer if not already running */ if (ssl->f_get_timer != NULL && ssl->f_get_timer(ssl->p_timer) == -1) { mbedtls_ssl_set_timer(ssl, ssl->conf->read_timeout); } if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { if (ret == MBEDTLS_ERR_SSL_CONN_EOF) { return 0; } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msglen == 0 && ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) { /* * OpenSSL sends empty messages to randomize the IV */ if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { if (ret == MBEDTLS_ERR_SSL_CONN_EOF) { return 0; } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) { ret = ssl_handle_hs_message_post_handshake(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_handle_hs_message_post_handshake", ret); return ret; } /* At this point, we don't know whether the renegotiation triggered * by the post-handshake message has been completed or not. The cases * to consider are the following: * 1) The renegotiation is complete. In this case, no new record * has been read yet. * 2) The renegotiation is incomplete because the client received * an application data record while awaiting the ServerHello. * 3) The renegotiation is incomplete because the client received * a non-handshake, non-application data message while awaiting * the ServerHello. * * In each of these cases, looping will be the proper action: * - For 1), the next iteration will read a new record and check * if it's application data. * - For 2), the loop condition isn't satisfied as application data * is present, hence continue is the same as break * - For 3), the loop condition is satisfied and read_record * will re-deliver the message that was held back by the client * when expecting the ServerHello. */ continue; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if (ssl->conf->renego_max_records >= 0) { if (++ssl->renego_records_seen > ssl->conf->renego_max_records) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation requested, " "but not honored by client")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } } } #endif /* MBEDTLS_SSL_RENEGOTIATION */ /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ if (ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT) { MBEDTLS_SSL_DEBUG_MSG(2, ("ignoring non-fatal non-closure alert")); return MBEDTLS_ERR_SSL_WANT_READ; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad application data message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } ssl->in_offt = ssl->in_msg; /* We're going to return something now, cancel timer, * except if handshake (renegotiation) is in progress */ if (mbedtls_ssl_is_handshake_over(ssl) == 1) { mbedtls_ssl_set_timer(ssl, 0); } #if defined(MBEDTLS_SSL_PROTO_DTLS) /* If we requested renego but received AppData, resend HelloRequest. * Do it now, after setting in_offt, to avoid taking this branch * again if ssl_write_hello_request() returns WANT_WRITE */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if ((ret = mbedtls_ssl_resend_hello_request(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_resend_hello_request", ret); return ret; } } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ } ret = ssl_read_application_data(ssl, buf, len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= read")); return ret; } #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { if (ssl == NULL || (ssl->conf == NULL)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * The server may receive early data only while waiting for the End of * Early Data handshake message. */ if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) || (ssl->in_offt == NULL)) { return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA; } return ssl_read_application_data(ssl, buf, len); } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */ /* * Send application data to be encrypted by the SSL layer, taking care of max * fragment length and buffer size. * * According to RFC 5246 Section 6.2.1: * * Zero-length fragments of Application data MAY be sent as they are * potentially useful as a traffic analysis countermeasure. * * Therefore, it is possible that the input message length is 0 and the * corresponding return code is 0 on success. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_real(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = mbedtls_ssl_get_max_out_record_payload(ssl); const size_t max_len = (size_t) ret; if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_max_out_record_payload", ret); return ret; } if (len > max_len) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("fragment larger than the (negotiated) " "maximum fragment length: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, len, max_len)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } else #endif len = max_len; } if (ssl->out_left != 0) { /* * The user has previously tried to send the data and * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially * written. In this case, we expect the high-level write function * (e.g. mbedtls_ssl_write()) to be called with the same parameters */ if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); return ret; } } else { /* * The user is trying to send a message the first time, so we need to * copy the data into the internal buffers and setup the data structure * to keep track of partial writes */ ssl->out_msglen = len; ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; if (len > 0) { memcpy(ssl->out_msg, buf, len); } if ((ret = mbedtls_ssl_write_record(ssl, SSL_FORCE_FLUSH)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_record", ret); return ret; } } return (int) len; } /* * Write application data (public-facing wrapper) */ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write")); if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_RENEGOTIATION) if ((ret = ssl_check_ctr_renegotiate(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_check_ctr_renegotiate", ret); return ret; } #endif if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } ret = ssl_write_real(ssl, buf, len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write")); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const struct mbedtls_ssl_config *conf; uint32_t remaining; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data")); if (ssl == NULL || (conf = ssl->conf) == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) || (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } /* * If we are at the beginning of the handshake, the early data state being * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just * enough to be able to send early data if possible. That way, we can * guarantee that when starting the handshake with this function we will * send at least one record of early data. Note that when the state is * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data * as the early data outbound transform has not been set as we may have to * first send a dummy CCS in clear. */ if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) || (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) { while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) || (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) { ret = mbedtls_ssl_handshake_step(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret); return ret; } ret = mbedtls_ssl_flush_output(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret); return ret; } } remaining = ssl->session_negotiate->max_early_data_size; } else { /* * If we are past the point where we can send early data or we have * already reached the maximum early data size, return immediatly. * Otherwise, progress the handshake as much as possible to not delay * it too much. If we reach a point where we can still send early data, * then we will send some. */ if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) && (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } remaining = ssl->session_negotiate->max_early_data_size - ssl->total_early_data_size; if (remaining == 0) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } ret = mbedtls_ssl_handshake(ssl); if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) && (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) || (remaining == 0)) { return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA; } if (len > remaining) { len = remaining; } ret = ssl_write_real(ssl, buf, len); if (ret >= 0) { ssl->total_early_data_size += ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret)); return ret; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */ /* * Notify the peer that the connection is being closed */ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> write close notify")); if (mbedtls_ssl_is_handshake_over(ssl) == 1) { if ((ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_WARNING, MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_send_alert_message", ret); return ret; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write close notify")); return 0; } void mbedtls_ssl_transform_free(mbedtls_ssl_transform *transform) { if (transform == NULL) { return; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(transform->psa_key_enc); psa_destroy_key(transform->psa_key_dec); #else mbedtls_cipher_free(&transform->cipher_ctx_enc); mbedtls_cipher_free(&transform->cipher_ctx_dec); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(transform->psa_mac_enc); psa_destroy_key(transform->psa_mac_dec); #else mbedtls_md_free(&transform->md_ctx_enc); mbedtls_md_free(&transform->md_ctx_dec); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif mbedtls_platform_zeroize(transform, sizeof(mbedtls_ssl_transform)); } void mbedtls_ssl_set_inbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform) { ssl->transform_in = transform; memset(ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); } void mbedtls_ssl_set_outbound_transform(mbedtls_ssl_context *ssl, mbedtls_ssl_transform *transform) { ssl->transform_out = transform; memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_buffering_free(mbedtls_ssl_context *ssl) { unsigned offset; mbedtls_ssl_handshake_params * const hs = ssl->handshake; if (hs == NULL) { return; } ssl_free_buffered_record(ssl); for (offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++) { ssl_buffering_free_slot(ssl, offset); } } static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl, uint8_t slot) { mbedtls_ssl_handshake_params * const hs = ssl->handshake; mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; if (slot >= MBEDTLS_SSL_MAX_BUFFERED_HS) { return; } if (hs_buf->is_valid == 1) { hs->buffering.total_bytes_buffered -= hs_buf->data_len; mbedtls_zeroize_and_free(hs_buf->data, hs_buf->data_len); memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer)); } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ /* * Convert version numbers to/from wire format * and, for DTLS, to/from TLS equivalent. * * For TLS this is the identity. * For DTLS, map as follows, then use 1's complement (v -> ~v): * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) * DTLS 1.0 is stored as TLS 1.1 internally */ void mbedtls_ssl_write_version(unsigned char version[2], int transport, mbedtls_ssl_protocol_version tls_version) { uint16_t tls_version_formatted; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { tls_version_formatted = ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201)); } else #else ((void) transport); #endif { tls_version_formatted = (uint16_t) tls_version; } MBEDTLS_PUT_UINT16_BE(tls_version_formatted, version, 0); } uint16_t mbedtls_ssl_read_version(const unsigned char version[2], int transport) { uint16_t tls_version = MBEDTLS_GET_UINT16_BE(version, 0); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { tls_version = ~(tls_version - (tls_version == 0xfeff ? 0x0202 : 0x0201)); } #else ((void) transport); #endif return tls_version; } /* * Send pending fatal alert. * 0, No alert message. * !0, if mbedtls_ssl_send_alert_message() returned in error, the error code it * returned, ssl->alert_reason otherwise. */ int mbedtls_ssl_handle_pending_alert(mbedtls_ssl_context *ssl) { int ret; /* No pending alert, return success*/ if (ssl->send_alert == 0) { return 0; } ret = mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, ssl->alert_type); /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE, * do not clear the alert to be able to send it later. */ if (ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ssl->send_alert = 0; } if (ret != 0) { return ret; } return ssl->alert_reason; } /* * Set pending fatal alert flag. */ void mbedtls_ssl_pend_fatal_alert(mbedtls_ssl_context *ssl, unsigned char alert_type, int alert_reason) { ssl->send_alert = 1; ssl->alert_type = alert_type; ssl->alert_reason = alert_reason; } #endif /* MBEDTLS_SSL_TLS_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_ticket.c000066400000000000000000000407561464416617300236600ustar00rootroot00000000000000/* * TLS server tickets callbacks implementation * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_TICKET_C) #include "mbedtls/platform.h" #include "ssl_misc.h" #include "mbedtls/ssl_ticket.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* * Initialize context */ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx) { memset(ctx, 0, sizeof(mbedtls_ssl_ticket_context)); #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_init(&ctx->mutex); #endif } #define MAX_KEY_BYTES MBEDTLS_SSL_TICKET_MAX_KEY_BYTES #define TICKET_KEY_NAME_BYTES MBEDTLS_SSL_TICKET_KEY_NAME_BYTES #define TICKET_IV_BYTES 12 #define TICKET_CRYPT_LEN_BYTES 2 #define TICKET_AUTH_TAG_BYTES 16 #define TICKET_MIN_LEN (TICKET_KEY_NAME_BYTES + \ TICKET_IV_BYTES + \ TICKET_CRYPT_LEN_BYTES + \ TICKET_AUTH_TAG_BYTES) #define TICKET_ADD_DATA_LEN (TICKET_KEY_NAME_BYTES + \ TICKET_IV_BYTES + \ TICKET_CRYPT_LEN_BYTES) /* * Generate/update a key */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx, unsigned char index) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MAX_KEY_BYTES] = { 0 }; mbedtls_ssl_ticket_key *key = ctx->keys + index; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; #endif #if defined(MBEDTLS_HAVE_TIME) key->generation_time = mbedtls_time(NULL); #endif /* The lifetime of a key is the configured lifetime of the tickets when * the key is created. */ key->lifetime = ctx->ticket_lifetime; if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) { return ret; } if ((ret = ctx->f_rng(ctx->p_rng, buf, sizeof(buf))) != 0) { return ret; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, key->alg); psa_set_key_type(&attributes, key->key_type); psa_set_key_bits(&attributes, key->key_bits); ret = PSA_TO_MBEDTLS_ERR( psa_import_key(&attributes, buf, PSA_BITS_TO_BYTES(key->key_bits), &key->key)); #else /* With GCM and CCM, same context can encrypt & decrypt */ ret = mbedtls_cipher_setkey(&key->ctx, buf, mbedtls_cipher_get_key_bitlen(&key->ctx), MBEDTLS_ENCRYPT); #endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } /* * Rotate/generate keys if necessary */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx) { #if !defined(MBEDTLS_HAVE_TIME) ((void) ctx); #else mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active; if (key->lifetime != 0) { mbedtls_time_t current_time = mbedtls_time(NULL); mbedtls_time_t key_time = key->generation_time; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif if (current_time >= key_time && (uint64_t) (current_time - key_time) < key->lifetime) { return 0; } ctx->active = 1 - ctx->active; #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return ssl_ticket_gen_key(ctx, ctx->active); } else #endif /* MBEDTLS_HAVE_TIME */ return 0; } /* * Rotate active session ticket encryption key */ int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx, const unsigned char *name, size_t nlength, const unsigned char *k, size_t klength, uint32_t lifetime) { const unsigned char idx = 1 - ctx->active; mbedtls_ssl_ticket_key * const key = ctx->keys + idx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; const size_t bitlen = key->key_bits; #else const int bitlen = mbedtls_cipher_get_key_bitlen(&key->ctx); #endif if (nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t) bitlen) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); return ret; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); psa_set_key_algorithm(&attributes, key->alg); psa_set_key_type(&attributes, key->key_type); psa_set_key_bits(&attributes, key->key_bits); if ((status = psa_import_key(&attributes, k, PSA_BITS_TO_BYTES(key->key_bits), &key->key)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); return ret; } #else ret = mbedtls_cipher_setkey(&key->ctx, k, bitlen, MBEDTLS_ENCRYPT); if (ret != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ ctx->active = idx; ctx->ticket_lifetime = lifetime; memcpy(key->name, name, TICKET_KEY_NAME_BYTES); #if defined(MBEDTLS_HAVE_TIME) key->generation_time = mbedtls_time(NULL); #endif key->lifetime = lifetime; return 0; } /* * Setup context for actual use */ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_cipher_type_t cipher, uint32_t lifetime) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t key_bits; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t alg; psa_key_type_t key_type; #else const mbedtls_cipher_info_t *cipher_info; #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (mbedtls_ssl_cipher_to_psa(cipher, TICKET_AUTH_TAG_BYTES, &alg, &key_type, &key_bits) != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (PSA_ALG_IS_AEAD(alg) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #else cipher_info = mbedtls_cipher_info_from_type(cipher); if (mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_GCM && mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CCM && mbedtls_cipher_info_get_mode(cipher_info) != MBEDTLS_MODE_CHACHAPOLY) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } key_bits = mbedtls_cipher_info_get_key_bitlen(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (key_bits > 8 * MAX_KEY_BYTES) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ctx->f_rng = f_rng; ctx->p_rng = p_rng; ctx->ticket_lifetime = lifetime; #if defined(MBEDTLS_USE_PSA_CRYPTO) ctx->keys[0].alg = alg; ctx->keys[0].key_type = key_type; ctx->keys[0].key_bits = key_bits; ctx->keys[1].alg = alg; ctx->keys[1].key_type = key_type; ctx->keys[1].key_bits = key_bits; #else if ((ret = mbedtls_cipher_setup(&ctx->keys[0].ctx, cipher_info)) != 0) { return ret; } if ((ret = mbedtls_cipher_setup(&ctx->keys[1].ctx, cipher_info)) != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = ssl_ticket_gen_key(ctx, 0)) != 0 || (ret = ssl_ticket_gen_key(ctx, 1)) != 0) { return ret; } return 0; } /* * Create session ticket, with the following structure: * * struct { * opaque key_name[4]; * opaque iv[12]; * opaque encrypted_state<0..2^16-1>; * opaque tag[16]; * } ticket; * * The key_name, iv, and length of encrypted_state are the additional * authenticated data. */ int mbedtls_ssl_ticket_write(void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, const unsigned char *end, size_t *tlen, uint32_t *ticket_lifetime) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_key *key; unsigned char *key_name = start; unsigned char *iv = start + TICKET_KEY_NAME_BYTES; unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; size_t clear_len, ciph_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif *tlen = 0; if (ctx == NULL || ctx->f_rng == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, * in addition to session itself, that will be checked when writing it. */ MBEDTLS_SSL_CHK_BUF_PTR(start, end, TICKET_MIN_LEN); #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif if ((ret = ssl_ticket_update_keys(ctx)) != 0) { goto cleanup; } key = &ctx->keys[ctx->active]; *ticket_lifetime = key->lifetime; memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES); if ((ret = ctx->f_rng(ctx->p_rng, iv, TICKET_IV_BYTES)) != 0) { goto cleanup; } /* Dump session state */ if ((ret = mbedtls_ssl_session_save(session, state, (size_t) (end - state), &clear_len)) != 0 || (unsigned long) clear_len > 65535) { goto cleanup; } MBEDTLS_PUT_UINT16_BE(clear_len, state_len_bytes, 0); /* Encrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_aead_encrypt(key->key, key->alg, iv, TICKET_IV_BYTES, key_name, TICKET_ADD_DATA_LEN, state, clear_len, state, end - state, &ciph_len)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto cleanup; } #else if ((ret = mbedtls_cipher_auth_encrypt_ext(&key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ key_name, TICKET_ADD_DATA_LEN, state, clear_len, state, (size_t) (end - state), &ciph_len, TICKET_AUTH_TAG_BYTES)) != 0) { goto cleanup; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (ciph_len != clear_len + TICKET_AUTH_TAG_BYTES) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES; cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Select key based on name */ static mbedtls_ssl_ticket_key *ssl_ticket_select_key( mbedtls_ssl_ticket_context *ctx, const unsigned char name[4]) { unsigned char i; for (i = 0; i < sizeof(ctx->keys) / sizeof(*ctx->keys); i++) { if (memcmp(name, ctx->keys[i].name, 4) == 0) { return &ctx->keys[i]; } } return NULL; } /* * Load session ticket (see mbedtls_ssl_ticket_write for structure) */ int mbedtls_ssl_ticket_parse(void *p_ticket, mbedtls_ssl_session *session, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_ticket_context *ctx = p_ticket; mbedtls_ssl_ticket_key *key; unsigned char *key_name = buf; unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; unsigned char *enc_len_p = iv + TICKET_IV_BYTES; unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; size_t enc_len, clear_len; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif if (ctx == NULL || ctx->f_rng == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (len < TICKET_MIN_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { return ret; } #endif if ((ret = ssl_ticket_update_keys(ctx)) != 0) { goto cleanup; } enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0); if (len != TICKET_MIN_LEN + enc_len) { ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; goto cleanup; } /* Select key */ if ((key = ssl_ticket_select_key(ctx, key_name)) == NULL) { /* We can't know for sure but this is a likely option unless we're * under attack - this is only informative anyway */ ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; goto cleanup; } /* Decrypt and authenticate */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = psa_aead_decrypt(key->key, key->alg, iv, TICKET_IV_BYTES, key_name, TICKET_ADD_DATA_LEN, ticket, enc_len + TICKET_AUTH_TAG_BYTES, ticket, enc_len, &clear_len)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto cleanup; } #else if ((ret = mbedtls_cipher_auth_decrypt_ext(&key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ key_name, TICKET_ADD_DATA_LEN, ticket, enc_len + TICKET_AUTH_TAG_BYTES, ticket, enc_len, &clear_len, TICKET_AUTH_TAG_BYTES)) != 0) { if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) { ret = MBEDTLS_ERR_SSL_INVALID_MAC; } goto cleanup; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (clear_len != enc_len) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } /* Actually load session */ if ((ret = mbedtls_ssl_session_load(session, ticket, clear_len)) != 0) { goto cleanup; } #if defined(MBEDTLS_HAVE_TIME) mbedtls_ms_time_t ticket_creation_time, ticket_age; mbedtls_ms_time_t ticket_lifetime = (mbedtls_ms_time_t) key->lifetime * 1000; ret = mbedtls_ssl_session_get_ticket_creation_time(session, &ticket_creation_time); if (ret != 0) { goto cleanup; } ticket_age = mbedtls_ms_time() - ticket_creation_time; if (ticket_age < 0 || ticket_age > ticket_lifetime) { ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; goto cleanup; } #endif cleanup: #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif return ret; } /* * Free context */ void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key(ctx->keys[0].key); psa_destroy_key(ctx->keys[1].key); #else mbedtls_cipher_free(&ctx->keys[0].ctx); mbedtls_cipher_free(&ctx->keys[1].ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free(&ctx->mutex); #endif mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ssl_ticket_context)); } #endif /* MBEDTLS_SSL_TICKET_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls.c000066400000000000000000011713451464416617300231770ustar00rootroot00000000000000/* * TLS shared functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * http://www.ietf.org/rfc/rfc2246.txt * http://www.ietf.org/rfc/rfc4346.txt */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_client.h" #include "ssl_debug_helpers.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "mbedtls/version.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "mbedtls/psa_util.h" #include "md_psa.h" #include "psa_util_internal.h" #include "psa/crypto.h" #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/oid.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define local translating functions to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif #if defined(MBEDTLS_TEST_HOOKS) static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args; void mbedtls_ssl_set_chk_buf_ptr_fail_args( const uint8_t *cur, const uint8_t *end, size_t need) { chk_buf_ptr_fail_args.cur = cur; chk_buf_ptr_fail_args.end = end; chk_buf_ptr_fail_args.need = need; } void mbedtls_ssl_reset_chk_buf_ptr_fail_args(void) { memset(&chk_buf_ptr_fail_args, 0, sizeof(chk_buf_ptr_fail_args)); } int mbedtls_ssl_cmp_chk_buf_ptr_fail_args(mbedtls_ssl_chk_buf_ptr_args *args) { return (chk_buf_ptr_fail_args.cur != args->cur) || (chk_buf_ptr_fail_args.end != args->end) || (chk_buf_ptr_fail_args.need != args->need); } #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_SSL_PROTO_DTLS) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* Top-level Connection ID API */ int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len, int ignore_other_cid) { if (len > MBEDTLS_SSL_CID_IN_LEN_MAX) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL && ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->ignore_unexpected_cid = ignore_other_cid; conf->cid_len = len; return 0; } int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl, int enable, unsigned char const *own_cid, size_t own_cid_len) { if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->negotiate_cid = enable; if (enable == MBEDTLS_SSL_CID_DISABLED) { MBEDTLS_SSL_DEBUG_MSG(3, ("Disable use of CID extension.")); return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("Enable use of CID extension.")); MBEDTLS_SSL_DEBUG_BUF(3, "Own CID", own_cid, own_cid_len); if (own_cid_len != ssl->conf->cid_len) { MBEDTLS_SSL_DEBUG_MSG(3, ("CID length %u does not match CID length %u in config", (unsigned) own_cid_len, (unsigned) ssl->conf->cid_len)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->own_cid, own_cid, own_cid_len); /* Truncation is not an issue here because * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */ ssl->own_cid_len = (uint8_t) own_cid_len; return 0; } int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], size_t *own_cid_len) { *enabled = MBEDTLS_SSL_CID_DISABLED; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We report MBEDTLS_SSL_CID_DISABLED in case the CID length is * zero as this is indistinguishable from not requesting to use * the CID extension. */ if (ssl->own_cid_len == 0 || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { return 0; } if (own_cid_len != NULL) { *own_cid_len = ssl->own_cid_len; if (own_cid != NULL) { memcpy(own_cid, ssl->own_cid, ssl->own_cid_len); } } *enabled = MBEDTLS_SSL_CID_ENABLED; return 0; } int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl, int *enabled, unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX], size_t *peer_cid_len) { *enabled = MBEDTLS_SSL_CID_DISABLED; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions * were used, but client and server requested the empty CID. * This is indistinguishable from not using the CID extension * in the first place. */ if (ssl->transform_in->in_cid_len == 0 && ssl->transform_in->out_cid_len == 0) { return 0; } if (peer_cid_len != NULL) { *peer_cid_len = ssl->transform_in->out_cid_len; if (peer_cid != NULL) { memcpy(peer_cid, ssl->transform_in->out_cid, ssl->transform_in->out_cid_len); } } *enabled = MBEDTLS_SSL_CID_ENABLED; return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /* * Convert max_fragment_length codes to length. * RFC 6066 says: * enum{ * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) * } MaxFragmentLength; * and we add 0 -> extension unused */ static unsigned int ssl_mfl_code_to_length(int mfl) { switch (mfl) { case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN; case MBEDTLS_SSL_MAX_FRAG_LEN_512: return 512; case MBEDTLS_SSL_MAX_FRAG_LEN_1024: return 1024; case MBEDTLS_SSL_MAX_FRAG_LEN_2048: return 2048; case MBEDTLS_SSL_MAX_FRAG_LEN_4096: return 4096; default: return MBEDTLS_TLS_EXT_ADV_CONTENT_LEN; } } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src) { mbedtls_ssl_session_free(dst); memcpy(dst, src, sizeof(mbedtls_ssl_session)); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) dst->ticket = NULL; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) dst->hostname = NULL; #endif #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \ defined(MBEDTLS_SSL_EARLY_DATA) dst->ticket_alpn = NULL; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (src->peer_cert != NULL) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; dst->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (dst->peer_cert == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } mbedtls_x509_crt_init(dst->peer_cert); if ((ret = mbedtls_x509_crt_parse_der(dst->peer_cert, src->peer_cert->raw.p, src->peer_cert->raw.len)) != 0) { mbedtls_free(dst->peer_cert); dst->peer_cert = NULL; return ret; } } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (src->peer_cert_digest != NULL) { dst->peer_cert_digest = mbedtls_calloc(1, src->peer_cert_digest_len); if (dst->peer_cert_digest == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(dst->peer_cert_digest, src->peer_cert_digest, src->peer_cert_digest_len); dst->peer_cert_digest_type = src->peer_cert_digest_type; dst->peer_cert_digest_len = src->peer_cert_digest_len; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \ defined(MBEDTLS_SSL_EARLY_DATA) { int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if (src->ticket != NULL) { dst->ticket = mbedtls_calloc(1, src->ticket_len); if (dst->ticket == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(dst->ticket, src->ticket, src->ticket_len); } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (src->endpoint == MBEDTLS_SSL_IS_CLIENT) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_session_set_hostname(dst, src->hostname); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ return 0; } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old) { unsigned char *resized_buffer = mbedtls_calloc(1, len_new); if (resized_buffer == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } /* We want to copy len_new bytes when downsizing the buffer, and * len_old bytes when upsizing, so we choose the smaller of two sizes, * to fit one buffer into another. Size checks, ensuring that no data is * lost, are done outside of this function. */ memcpy(resized_buffer, *buffer, (len_new < *len_old) ? len_new : *len_old); mbedtls_zeroize_and_free(*buffer, *len_old); *buffer = resized_buffer; *len_old = len_new; return 0; } static void handle_buffer_resizing(mbedtls_ssl_context *ssl, int downsizing, size_t in_buf_new_len, size_t out_buf_new_len) { int modified = 0; size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0; size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0; if (ssl->in_buf != NULL) { written_in = ssl->in_msg - ssl->in_buf; iv_offset_in = ssl->in_iv - ssl->in_buf; len_offset_in = ssl->in_len - ssl->in_buf; if (downsizing ? ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len : ssl->in_buf_len < in_buf_new_len) { if (resize_buffer(&ssl->in_buf, in_buf_new_len, &ssl->in_buf_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("input buffer resizing failed - out of memory")); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET, in_buf_new_len)); modified = 1; } } } if (ssl->out_buf != NULL) { written_out = ssl->out_msg - ssl->out_buf; iv_offset_out = ssl->out_iv - ssl->out_buf; len_offset_out = ssl->out_len - ssl->out_buf; if (downsizing ? ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len : ssl->out_buf_len < out_buf_new_len) { if (resize_buffer(&ssl->out_buf, out_buf_new_len, &ssl->out_buf_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("output buffer resizing failed - out of memory")); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET, out_buf_new_len)); modified = 1; } } } if (modified) { /* Update pointers here to avoid doing it twice. */ mbedtls_ssl_reset_in_out_pointers(ssl); /* Fields below might not be properly updated with record * splitting or with CID, so they are manually updated here. */ ssl->out_msg = ssl->out_buf + written_out; ssl->out_len = ssl->out_buf + len_offset_out; ssl->out_iv = ssl->out_buf + iv_offset_out; ssl->in_msg = ssl->in_buf + written_in; ssl->in_len = ssl->in_buf + len_offset_in; ssl->in_iv = ssl->in_buf + iv_offset_in; } } #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) typedef int (*tls_prf_fn)(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id); #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* Type for the TLS PRF */ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, const unsigned char *, size_t, unsigned char *, size_t); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, int ciphersuite, const unsigned char master[48], #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ssl_tls_prf_t tls_prf, const unsigned char randbytes[64], mbedtls_ssl_protocol_version tls_version, unsigned endpoint, const mbedtls_ssl_context *ssl); #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha256(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *); static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int); #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha384(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen); static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *); static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int); #endif /* MBEDTLS_MD_CAN_SHA384*/ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t); #if defined(MBEDTLS_MD_CAN_SHA256) static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t); #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t); #endif /* MBEDTLS_MD_CAN_SHA384*/ int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { mbedtls_ssl_tls_prf_cb *tls_prf = NULL; switch (prf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_TLS_PRF_SHA384: tls_prf = tls_prf_sha384; break; #endif /* MBEDTLS_MD_CAN_SHA384*/ #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_TLS_PRF_SHA256: tls_prf = tls_prf_sha256; break; #endif /* MBEDTLS_MD_CAN_SHA256*/ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ default: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return tls_prf(secret, slen, label, random, rlen, dstbuf, dlen); } #if defined(MBEDTLS_X509_CRT_PARSE_C) static void ssl_clear_peer_cert(mbedtls_ssl_session *session) { #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (session->peer_cert != NULL) { mbedtls_x509_crt_free(session->peer_cert); mbedtls_free(session->peer_cert); session->peer_cert = NULL; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (session->peer_cert_digest != NULL) { /* Zeroization is not necessary. */ mbedtls_free(session->peer_cert_digest); session->peer_cert_digest = NULL; session->peer_cert_digest_type = MBEDTLS_MD_NONE; session->peer_cert_digest_len = 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } #endif /* MBEDTLS_X509_CRT_PARSE_C */ uint32_t mbedtls_ssl_get_extension_id(unsigned int extension_type) { switch (extension_type) { case MBEDTLS_TLS_EXT_SERVERNAME: return MBEDTLS_SSL_EXT_ID_SERVERNAME; case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: return MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH; case MBEDTLS_TLS_EXT_STATUS_REQUEST: return MBEDTLS_SSL_EXT_ID_STATUS_REQUEST; case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: return MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS; case MBEDTLS_TLS_EXT_SIG_ALG: return MBEDTLS_SSL_EXT_ID_SIG_ALG; case MBEDTLS_TLS_EXT_USE_SRTP: return MBEDTLS_SSL_EXT_ID_USE_SRTP; case MBEDTLS_TLS_EXT_HEARTBEAT: return MBEDTLS_SSL_EXT_ID_HEARTBEAT; case MBEDTLS_TLS_EXT_ALPN: return MBEDTLS_SSL_EXT_ID_ALPN; case MBEDTLS_TLS_EXT_SCT: return MBEDTLS_SSL_EXT_ID_SCT; case MBEDTLS_TLS_EXT_CLI_CERT_TYPE: return MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE; case MBEDTLS_TLS_EXT_SERV_CERT_TYPE: return MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE; case MBEDTLS_TLS_EXT_PADDING: return MBEDTLS_SSL_EXT_ID_PADDING; case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: return MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY; case MBEDTLS_TLS_EXT_EARLY_DATA: return MBEDTLS_SSL_EXT_ID_EARLY_DATA; case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: return MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS; case MBEDTLS_TLS_EXT_COOKIE: return MBEDTLS_SSL_EXT_ID_COOKIE; case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: return MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES; case MBEDTLS_TLS_EXT_CERT_AUTH: return MBEDTLS_SSL_EXT_ID_CERT_AUTH; case MBEDTLS_TLS_EXT_OID_FILTERS: return MBEDTLS_SSL_EXT_ID_OID_FILTERS; case MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH: return MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH; case MBEDTLS_TLS_EXT_SIG_ALG_CERT: return MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT; case MBEDTLS_TLS_EXT_KEY_SHARE: return MBEDTLS_SSL_EXT_ID_KEY_SHARE; case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: return MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC; case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: return MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS; case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: return MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC; case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: return MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET; case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: return MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT; case MBEDTLS_TLS_EXT_SESSION_TICKET: return MBEDTLS_SSL_EXT_ID_SESSION_TICKET; } return MBEDTLS_SSL_EXT_ID_UNRECOGNIZED; } uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type) { return 1 << mbedtls_ssl_get_extension_id(extension_type); } #if defined(MBEDTLS_DEBUG_C) static const char *extension_name_table[] = { [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = "unrecognized", [MBEDTLS_SSL_EXT_ID_SERVERNAME] = "server_name", [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = "max_fragment_length", [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = "status_request", [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = "supported_groups", [MBEDTLS_SSL_EXT_ID_SIG_ALG] = "signature_algorithms", [MBEDTLS_SSL_EXT_ID_USE_SRTP] = "use_srtp", [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = "heartbeat", [MBEDTLS_SSL_EXT_ID_ALPN] = "application_layer_protocol_negotiation", [MBEDTLS_SSL_EXT_ID_SCT] = "signed_certificate_timestamp", [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = "client_certificate_type", [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = "server_certificate_type", [MBEDTLS_SSL_EXT_ID_PADDING] = "padding", [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = "pre_shared_key", [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = "early_data", [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = "supported_versions", [MBEDTLS_SSL_EXT_ID_COOKIE] = "cookie", [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = "psk_key_exchange_modes", [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = "certificate_authorities", [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = "oid_filters", [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = "post_handshake_auth", [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = "signature_algorithms_cert", [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = "key_share", [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = "truncated_hmac", [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = "supported_point_formats", [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = "encrypt_then_mac", [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = "extended_master_secret", [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = "session_ticket", [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit" }; static const unsigned int extension_type_table[] = { [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff, [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME, [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, [MBEDTLS_SSL_EXT_ID_STATUS_REQUEST] = MBEDTLS_TLS_EXT_STATUS_REQUEST, [MBEDTLS_SSL_EXT_ID_SUPPORTED_GROUPS] = MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, [MBEDTLS_SSL_EXT_ID_SIG_ALG] = MBEDTLS_TLS_EXT_SIG_ALG, [MBEDTLS_SSL_EXT_ID_USE_SRTP] = MBEDTLS_TLS_EXT_USE_SRTP, [MBEDTLS_SSL_EXT_ID_HEARTBEAT] = MBEDTLS_TLS_EXT_HEARTBEAT, [MBEDTLS_SSL_EXT_ID_ALPN] = MBEDTLS_TLS_EXT_ALPN, [MBEDTLS_SSL_EXT_ID_SCT] = MBEDTLS_TLS_EXT_SCT, [MBEDTLS_SSL_EXT_ID_CLI_CERT_TYPE] = MBEDTLS_TLS_EXT_CLI_CERT_TYPE, [MBEDTLS_SSL_EXT_ID_SERV_CERT_TYPE] = MBEDTLS_TLS_EXT_SERV_CERT_TYPE, [MBEDTLS_SSL_EXT_ID_PADDING] = MBEDTLS_TLS_EXT_PADDING, [MBEDTLS_SSL_EXT_ID_PRE_SHARED_KEY] = MBEDTLS_TLS_EXT_PRE_SHARED_KEY, [MBEDTLS_SSL_EXT_ID_EARLY_DATA] = MBEDTLS_TLS_EXT_EARLY_DATA, [MBEDTLS_SSL_EXT_ID_SUPPORTED_VERSIONS] = MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, [MBEDTLS_SSL_EXT_ID_COOKIE] = MBEDTLS_TLS_EXT_COOKIE, [MBEDTLS_SSL_EXT_ID_PSK_KEY_EXCHANGE_MODES] = MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, [MBEDTLS_SSL_EXT_ID_CERT_AUTH] = MBEDTLS_TLS_EXT_CERT_AUTH, [MBEDTLS_SSL_EXT_ID_OID_FILTERS] = MBEDTLS_TLS_EXT_OID_FILTERS, [MBEDTLS_SSL_EXT_ID_POST_HANDSHAKE_AUTH] = MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH, [MBEDTLS_SSL_EXT_ID_SIG_ALG_CERT] = MBEDTLS_TLS_EXT_SIG_ALG_CERT, [MBEDTLS_SSL_EXT_ID_KEY_SHARE] = MBEDTLS_TLS_EXT_KEY_SHARE, [MBEDTLS_SSL_EXT_ID_TRUNCATED_HMAC] = MBEDTLS_TLS_EXT_TRUNCATED_HMAC, [MBEDTLS_SSL_EXT_ID_SUPPORTED_POINT_FORMATS] = MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, [MBEDTLS_SSL_EXT_ID_ENCRYPT_THEN_MAC] = MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, [MBEDTLS_SSL_EXT_ID_EXTENDED_MASTER_SECRET] = MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, [MBEDTLS_SSL_EXT_ID_SESSION_TICKET] = MBEDTLS_TLS_EXT_SESSION_TICKET, [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT }; const char *mbedtls_ssl_get_extension_name(unsigned int extension_type) { return extension_name_table[ mbedtls_ssl_get_extension_id(extension_type)]; } static const char *ssl_tls13_get_hs_msg_name(int hs_msg_type) { switch (hs_msg_type) { case MBEDTLS_SSL_HS_CLIENT_HELLO: return "ClientHello"; case MBEDTLS_SSL_HS_SERVER_HELLO: return "ServerHello"; case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: return "HelloRetryRequest"; case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: return "NewSessionTicket"; case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: return "EncryptedExtensions"; case MBEDTLS_SSL_HS_CERTIFICATE: return "Certificate"; case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: return "CertificateRequest"; } return "Unknown"; } void mbedtls_ssl_print_extension(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, unsigned int extension_type, const char *extra_msg0, const char *extra_msg1) { const char *extra_msg; if (extra_msg0 && extra_msg1) { mbedtls_debug_print_msg( ssl, level, file, line, "%s: %s(%u) extension %s %s.", ssl_tls13_get_hs_msg_name(hs_msg_type), mbedtls_ssl_get_extension_name(extension_type), extension_type, extra_msg0, extra_msg1); return; } extra_msg = extra_msg0 ? extra_msg0 : extra_msg1; if (extra_msg) { mbedtls_debug_print_msg( ssl, level, file, line, "%s: %s(%u) extension %s.", ssl_tls13_get_hs_msg_name(hs_msg_type), mbedtls_ssl_get_extension_name(extension_type), extension_type, extra_msg); return; } mbedtls_debug_print_msg( ssl, level, file, line, "%s: %s(%u) extension.", ssl_tls13_get_hs_msg_name(hs_msg_type), mbedtls_ssl_get_extension_name(extension_type), extension_type); } void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl, int level, const char *file, int line, int hs_msg_type, uint32_t extensions_mask, const char *extra) { for (unsigned i = 0; i < sizeof(extension_name_table) / sizeof(extension_name_table[0]); i++) { mbedtls_ssl_print_extension( ssl, level, file, line, hs_msg_type, extension_type_table[i], extensions_mask & (1 << i) ? "exists" : "does not exist", extra); } } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) static const char *ticket_flag_name_table[] = { [0] = "ALLOW_PSK_RESUMPTION", [2] = "ALLOW_PSK_EPHEMERAL_RESUMPTION", [3] = "ALLOW_EARLY_DATA", }; void mbedtls_ssl_print_ticket_flags(const mbedtls_ssl_context *ssl, int level, const char *file, int line, unsigned int flags) { size_t i; mbedtls_debug_print_msg(ssl, level, file, line, "print ticket_flags (0x%02x)", flags); flags = flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK; for (i = 0; i < ARRAY_LENGTH(ticket_flag_name_table); i++) { if ((flags & (1 << i))) { mbedtls_debug_print_msg(ssl, level, file, line, "- %s is set.", ticket_flag_name_table[i]); } } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */ #endif /* MBEDTLS_DEBUG_C */ void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info) { ((void) ciphersuite_info); #if defined(MBEDTLS_MD_CAN_SHA384) if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) { ssl->handshake->update_checksum = ssl_update_checksum_sha384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) { ssl->handshake->update_checksum = ssl_update_checksum_sha256; } else #endif { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return; } } int mbedtls_ssl_add_hs_hdr_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, size_t total_hs_len) { unsigned char hs_hdr[4]; /* Build HS header for checksum update. */ hs_hdr[0] = MBEDTLS_BYTE_0(hs_type); hs_hdr[1] = MBEDTLS_BYTE_2(total_hs_len); hs_hdr[2] = MBEDTLS_BYTE_1(total_hs_len); hs_hdr[3] = MBEDTLS_BYTE_0(total_hs_len); return ssl->handshake->update_checksum(ssl, hs_hdr, sizeof(hs_hdr)); } int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char const *msg, size_t msg_len) { int ret; ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, hs_type, msg_len); if (ret != 0) { return ret; } return ssl->handshake->update_checksum(ssl, msg, msg_len); } int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_MD_CAN_SHA256) || \ defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif #else /* SHA-256 or SHA-384 */ ((void) ssl); #endif /* SHA-256 or SHA-384 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_abort(&ssl->handshake->fin_sha256_psa); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else mbedtls_md_free(&ssl->handshake->fin_sha256); mbedtls_md_init(&ssl->handshake->fin_sha256); ret = mbedtls_md_setup(&ssl->handshake->fin_sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); if (ret != 0) { return ret; } ret = mbedtls_md_starts(&ssl->handshake->fin_sha256); if (ret != 0) { return ret; } #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_abort(&ssl->handshake->fin_sha384_psa); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else mbedtls_md_free(&ssl->handshake->fin_sha384); mbedtls_md_init(&ssl->handshake->fin_sha384); ret = mbedtls_md_setup(&ssl->handshake->fin_sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); if (ret != 0) { return ret; } ret = mbedtls_md_starts(&ssl->handshake->fin_sha384); if (ret != 0) { return ret; } #endif #endif return 0; } static int ssl_update_checksum_start(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_MD_CAN_SHA256) || \ defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif #else /* SHA-256 or SHA-384 */ ((void) ssl); (void) buf; (void) len; #endif /* SHA-256 or SHA-384 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); if (ret != 0) { return ret; } #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len); if (status != PSA_SUCCESS) { return mbedtls_md_error_from_psa(status); } #else ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); if (ret != 0) { return ret; } #endif #endif return 0; } #if defined(MBEDTLS_MD_CAN_SHA256) static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return mbedtls_md_error_from_psa(psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len)); #else return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len); #endif } #endif #if defined(MBEDTLS_MD_CAN_SHA384) static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return mbedtls_md_error_from_psa(psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len)); #else return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len); #endif } #endif static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake) { memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params)); #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) handshake->fin_sha256_psa = psa_hash_operation_init(); #else mbedtls_md_init(&handshake->fin_sha256); #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) handshake->fin_sha384_psa = psa_hash_operation_init(); #else mbedtls_md_init(&handshake->fin_sha384); #endif #endif handshake->update_checksum = ssl_update_checksum_start; #if defined(MBEDTLS_DHM_C) mbedtls_dhm_init(&handshake->dhm_ctx); #endif #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) mbedtls_ecdh_init(&handshake->ecdh_ctx); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) handshake->psa_pake_ctx = psa_pake_operation_init(); handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_ecjpake_init(&handshake->ecjpake_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) handshake->ecjpake_cache = NULL; handshake->ecjpake_cache_len = 0; #endif #endif #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_init(&handshake->ecrs_ctx); #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_pk_init(&handshake->peer_pubkey); #endif } void mbedtls_ssl_transform_init(mbedtls_ssl_transform *transform) { memset(transform, 0, sizeof(mbedtls_ssl_transform)); #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT; transform->psa_key_dec = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_cipher_init(&transform->cipher_ctx_enc); mbedtls_cipher_init(&transform->cipher_ctx_dec); #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_mac_enc = MBEDTLS_SVC_KEY_ID_INIT; transform->psa_mac_dec = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_md_init(&transform->md_ctx_enc); mbedtls_md_init(&transform->md_ctx_dec); #endif #endif } void mbedtls_ssl_session_init(mbedtls_ssl_session *session) { memset(session, 0, sizeof(mbedtls_ssl_session)); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_handshake_init(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Clear old handshake information if present */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->transform_negotiate) { mbedtls_ssl_transform_free(ssl->transform_negotiate); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ if (ssl->session_negotiate) { mbedtls_ssl_session_free(ssl->session_negotiate); } if (ssl->handshake) { mbedtls_ssl_handshake_free(ssl); } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Either the pointers are now NULL or cleared properly and can be freed. * Now allocate missing structures. */ if (ssl->transform_negotiate == NULL) { ssl->transform_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ if (ssl->session_negotiate == NULL) { ssl->session_negotiate = mbedtls_calloc(1, sizeof(mbedtls_ssl_session)); } if (ssl->handshake == NULL) { ssl->handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_handshake_params)); } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) /* If the buffers are too small - reallocate */ handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, MBEDTLS_SSL_OUT_BUFFER_LEN); #endif /* All pointers should exist and can be directly freed without issue */ if (ssl->handshake == NULL || #if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform_negotiate == NULL || #endif ssl->session_negotiate == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc() of ssl sub-contexts failed")); mbedtls_free(ssl->handshake); ssl->handshake = NULL; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_free(ssl->transform_negotiate); ssl->transform_negotiate = NULL; #endif mbedtls_free(ssl->session_negotiate); ssl->session_negotiate = NULL; return MBEDTLS_ERR_SSL_ALLOC_FAILED; } #if defined(MBEDTLS_SSL_EARLY_DATA) #if defined(MBEDTLS_SSL_CLI_C) ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE; #endif #if defined(MBEDTLS_SSL_SRV_C) ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD; #endif ssl->total_early_data_size = 0; #endif /* MBEDTLS_SSL_EARLY_DATA */ /* Initialize structures */ mbedtls_ssl_session_init(ssl->session_negotiate); ssl_handshake_params_init(ssl->handshake); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_ssl_transform_init(ssl->transform_negotiate); #endif /* Setup handshake checksums */ ret = mbedtls_ssl_reset_checksum(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) ssl->handshake->new_session_tickets_count = ssl->conf->new_session_tickets_count; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->handshake->alt_transform_out = ssl->transform_out; if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; } else { ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; } mbedtls_ssl_set_timer(ssl, 0); } #endif /* * curve_list is translated to IANA TLS group identifiers here because * mbedtls_ssl_conf_curves returns void and so can't return * any error codes. */ #if defined(MBEDTLS_ECP_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /* Heap allocate and translate curve_list from internal to IANA group ids */ if (ssl->conf->curve_list != NULL) { size_t length; const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list; for (length = 0; (curve_list[length] != MBEDTLS_ECP_DP_NONE); length++) { } /* Leave room for zero termination */ uint16_t *group_list = mbedtls_calloc(length + 1, sizeof(uint16_t)); if (group_list == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } for (size_t i = 0; i < length; i++) { uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( curve_list[i]); if (tls_id == 0) { mbedtls_free(group_list); return MBEDTLS_ERR_SSL_BAD_CONFIG; } group_list[i] = tls_id; } group_list[length] = 0; ssl->handshake->group_list = group_list; ssl->handshake->group_list_heap_allocated = 1; } else { ssl->handshake->group_list = ssl->conf->group_list; ssl->handshake->group_list_heap_allocated = 0; } #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* Heap allocate and translate sig_hashes from internal hash identifiers to signature algorithms IANA identifiers. */ if (mbedtls_ssl_conf_is_tls12_only(ssl->conf) && ssl->conf->sig_hashes != NULL) { const int *md; const int *sig_hashes = ssl->conf->sig_hashes; size_t sig_algs_len = 0; uint16_t *p; MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN <= (SIZE_MAX - (2 * sizeof(uint16_t))), "MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN too big"); for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) { continue; } #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) sig_algs_len += sizeof(uint16_t); #endif #if defined(MBEDTLS_RSA_C) sig_algs_len += sizeof(uint16_t); #endif if (sig_algs_len > MBEDTLS_SSL_MAX_SIG_ALG_LIST_LEN) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } } if (sig_algs_len < MBEDTLS_SSL_MIN_SIG_ALG_LIST_LEN) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } ssl->handshake->sig_algs = mbedtls_calloc(1, sig_algs_len + sizeof(uint16_t)); if (ssl->handshake->sig_algs == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } p = (uint16_t *) ssl->handshake->sig_algs; for (md = sig_hashes; *md != MBEDTLS_MD_NONE; md++) { unsigned char hash = mbedtls_ssl_hash_from_md_alg(*md); if (hash == MBEDTLS_SSL_HASH_NONE) { continue; } #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA); p++; #endif #if defined(MBEDTLS_RSA_C) *p = ((hash << 8) | MBEDTLS_SSL_SIG_RSA); p++; #endif } *p = MBEDTLS_TLS_SIG_NONE; ssl->handshake->sig_algs_heap_allocated = 1; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ { ssl->handshake->sig_algs_heap_allocated = 0; } #endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ return 0; } #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) /* Dummy cookie callbacks for defaults */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_write_dummy(void *ctx, unsigned char **p, unsigned char *end, const unsigned char *cli_id, size_t cli_id_len) { ((void) ctx); ((void) p); ((void) end); ((void) cli_id); ((void) cli_id_len); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_cookie_check_dummy(void *ctx, const unsigned char *cookie, size_t cookie_len, const unsigned char *cli_id, size_t cli_id_len) { ((void) ctx); ((void) cookie); ((void) cookie_len); ((void) cli_id); ((void) cli_id_len); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ /* * Initialize an SSL context */ void mbedtls_ssl_init(mbedtls_ssl_context *ssl) { memset(ssl, 0, sizeof(mbedtls_ssl_context)); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_version_check(const mbedtls_ssl_context *ssl) { const mbedtls_ssl_config *conf = ssl->conf; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (mbedtls_ssl_conf_is_tls13_only(conf)) { if (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS 1.3 is not yet supported.")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls13 only.")); return 0; } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (mbedtls_ssl_conf_is_tls12_only(conf)) { MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is tls12 only.")); return 0; } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) if (mbedtls_ssl_conf_is_hybrid_tls12_tls13(conf)) { if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS not yet supported in Hybrid TLS 1.3 + TLS 1.2")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is TLS 1.3 or TLS 1.2.")); return 0; } #endif MBEDTLS_SSL_DEBUG_MSG(1, ("The SSL configuration is invalid.")); return MBEDTLS_ERR_SSL_BAD_CONFIG; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_check(const mbedtls_ssl_context *ssl) { int ret; ret = ssl_conf_version_check(ssl); if (ret != 0) { return ret; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* RFC 8446 section 4.4.3 * * If the verification fails, the receiver MUST terminate the handshake with * a "decrypt_error" alert. * * If the client is configured as TLS 1.3 only with optional verify, return * bad config. * */ if (mbedtls_ssl_conf_tls13_is_ephemeral_enabled( (mbedtls_ssl_context *) ssl) && ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Optional verify auth mode " "is not available for TLS 1.3 client")); return MBEDTLS_ERR_SSL_BAD_CONFIG; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (ssl->conf->f_rng == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided")); return MBEDTLS_ERR_SSL_NO_RNG; } /* Space for further checks */ return 0; } /* * Setup an SSL context */ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl, const mbedtls_ssl_config *conf) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; ssl->conf = conf; if ((ret = ssl_conf_check(ssl)) != 0) { return ret; } ssl->tls_version = ssl->conf->max_tls_version; /* * Prepare base structures */ /* Set to NULL in case of an error condition */ ssl->out_buf = NULL; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->in_buf_len = in_buf_len; #endif ssl->in_buf = mbedtls_calloc(1, in_buf_len); if (ssl->in_buf == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len)); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto error; } #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->out_buf_len = out_buf_len; #endif ssl->out_buf = mbedtls_calloc(1, out_buf_len); if (ssl->out_buf == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len)); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto error; } mbedtls_ssl_reset_in_out_pointers(ssl); #if defined(MBEDTLS_SSL_DTLS_SRTP) memset(&ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info)); #endif if ((ret = ssl_handshake_init(ssl)) != 0) { goto error; } return 0; error: mbedtls_free(ssl->in_buf); mbedtls_free(ssl->out_buf); ssl->conf = NULL; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) ssl->in_buf_len = 0; ssl->out_buf_len = 0; #endif ssl->in_buf = NULL; ssl->out_buf = NULL; ssl->in_hdr = NULL; ssl->in_ctr = NULL; ssl->in_len = NULL; ssl->in_iv = NULL; ssl->in_msg = NULL; ssl->out_hdr = NULL; ssl->out_ctr = NULL; ssl->out_len = NULL; ssl->out_iv = NULL; ssl->out_msg = NULL; return ret; } /* * Reset an initialized and used SSL context for re-use while retaining * all application-set variables, function pointers and data. * * If partial is non-zero, keep data in the input buffer and client ID. * (Use when a DTLS client reconnects from the same port.) */ void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl, int partial) { #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; size_t out_buf_len = ssl->out_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif #if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C) partial = 0; #endif /* Cancel any possibly running timer */ mbedtls_ssl_set_timer(ssl, 0); mbedtls_ssl_reset_in_out_pointers(ssl); /* Reset incoming message parsing */ ssl->in_offt = NULL; ssl->nb_zero = 0; ssl->in_msgtype = 0; ssl->in_msglen = 0; ssl->in_hslen = 0; ssl->keep_current_message = 0; ssl->transform_in = NULL; #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->next_record_offset = 0; ssl->in_epoch = 0; #endif /* Keep current datagram if partial == 1 */ if (partial == 0) { ssl->in_left = 0; memset(ssl->in_buf, 0, in_buf_len); } ssl->send_alert = 0; /* Reset outgoing message writing */ ssl->out_msgtype = 0; ssl->out_msglen = 0; ssl->out_left = 0; memset(ssl->out_buf, 0, out_buf_len); memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); ssl->transform_out = NULL; #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) mbedtls_ssl_dtls_replay_reset(ssl); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->transform) { mbedtls_ssl_transform_free(ssl->transform); mbedtls_free(ssl->transform); ssl->transform = NULL; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_transform_free(ssl->transform_application); mbedtls_free(ssl->transform_application); ssl->transform_application = NULL; if (ssl->handshake != NULL) { #if defined(MBEDTLS_SSL_EARLY_DATA) mbedtls_ssl_transform_free(ssl->handshake->transform_earlydata); mbedtls_free(ssl->handshake->transform_earlydata); ssl->handshake->transform_earlydata = NULL; #endif mbedtls_ssl_transform_free(ssl->handshake->transform_handshake); mbedtls_free(ssl->handshake->transform_handshake); ssl->handshake->transform_handshake = NULL; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ } int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ssl->state = MBEDTLS_SSL_HELLO_REQUEST; ssl->tls_version = ssl->conf->max_tls_version; mbedtls_ssl_session_reset_msg_layer(ssl, partial); /* Reset renegotiation state */ #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; ssl->renego_records_seen = 0; ssl->verify_data_len = 0; memset(ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); memset(ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN); #endif ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; ssl->session_in = NULL; ssl->session_out = NULL; if (ssl->session) { mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); ssl->session = NULL; } #if defined(MBEDTLS_SSL_ALPN) ssl->alpn_chosen = NULL; #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) int free_cli_id = 1; #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) free_cli_id = (partial == 0); #endif if (free_cli_id) { mbedtls_free(ssl->cli_id); ssl->cli_id = NULL; ssl->cli_id_len = 0; } #endif if ((ret = ssl_handshake_init(ssl)) != 0) { return ret; } return 0; } /* * Reset an initialized and used SSL context for re-use while retaining * all application-set variables, function pointers and data. */ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl) { return mbedtls_ssl_session_reset_int(ssl, 0); } /* * SSL set accessors */ void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint) { conf->endpoint = endpoint; } void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport) { conf->transport = transport; } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) void mbedtls_ssl_conf_dtls_anti_replay(mbedtls_ssl_config *conf, char mode) { conf->anti_replay = mode; } #endif void mbedtls_ssl_conf_dtls_badmac_limit(mbedtls_ssl_config *conf, unsigned limit) { conf->badmac_limit = limit; } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_set_datagram_packing(mbedtls_ssl_context *ssl, unsigned allow_packing) { ssl->disable_datagram_packing = !allow_packing; } void mbedtls_ssl_conf_handshake_timeout(mbedtls_ssl_config *conf, uint32_t min, uint32_t max) { conf->hs_timeout_min = min; conf->hs_timeout_max = max; } #endif void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode) { conf->authmode = authmode; } #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_conf_verify(mbedtls_ssl_config *conf, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { conf->f_vrfy = f_vrfy; conf->p_vrfy = p_vrfy; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ void mbedtls_ssl_conf_rng(mbedtls_ssl_config *conf, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { conf->f_rng = f_rng; conf->p_rng = p_rng; } void mbedtls_ssl_conf_dbg(mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg) { conf->f_dbg = f_dbg; conf->p_dbg = p_dbg; } void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl, void *p_bio, mbedtls_ssl_send_t *f_send, mbedtls_ssl_recv_t *f_recv, mbedtls_ssl_recv_timeout_t *f_recv_timeout) { ssl->p_bio = p_bio; ssl->f_send = f_send; ssl->f_recv = f_recv; ssl->f_recv_timeout = f_recv_timeout; } #if defined(MBEDTLS_SSL_PROTO_DTLS) void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu) { ssl->mtu = mtu; } #endif void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout) { conf->read_timeout = timeout; } void mbedtls_ssl_set_timer_cb(mbedtls_ssl_context *ssl, void *p_timer, mbedtls_ssl_set_timer_t *f_set_timer, mbedtls_ssl_get_timer_t *f_get_timer) { ssl->p_timer = p_timer; ssl->f_set_timer = f_set_timer; ssl->f_get_timer = f_get_timer; /* Make sure we start with no timer running */ mbedtls_ssl_set_timer(ssl, 0); } #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf, void *p_cache, mbedtls_ssl_cache_get_t *f_get_cache, mbedtls_ssl_cache_set_t *f_set_cache) { conf->p_cache = p_cache; conf->f_get_cache = f_get_cache; conf->f_set_cache = f_set_cache; } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || session == NULL || ssl->session_negotiate == NULL || ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->handshake->resume == 1) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); if (mbedtls_ssl_validate_ciphersuite( ssl, ciphersuite_info, MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3) != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("%d is not a valid TLS 1.3 ciphersuite.", session->ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if ((ret = mbedtls_ssl_session_copy(ssl->session_negotiate, session)) != 0) { return ret; } ssl->handshake->resume = 1; return 0; } #endif /* MBEDTLS_SSL_CLI_C */ void mbedtls_ssl_conf_ciphersuites(mbedtls_ssl_config *conf, const int *ciphersuites) { conf->ciphersuite_list = ciphersuites; } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf, const int kex_modes) { conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; } #if defined(MBEDTLS_SSL_EARLY_DATA) void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf, int early_data_enabled) { conf->early_data_enabled = early_data_enabled; } #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_max_early_data_size( mbedtls_ssl_config *conf, uint32_t max_early_data_size) { conf->max_early_data_size = max_early_data_size; } #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_conf_cert_profile(mbedtls_ssl_config *conf, const mbedtls_x509_crt_profile *profile) { conf->cert_profile = profile; } static void ssl_key_cert_free(mbedtls_ssl_key_cert *key_cert) { mbedtls_ssl_key_cert *cur = key_cert, *next; while (cur != NULL) { next = cur->next; mbedtls_free(cur); cur = next; } } /* Append a new keycert entry to a (possibly empty) list */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_append_key_cert(mbedtls_ssl_key_cert **head, mbedtls_x509_crt *cert, mbedtls_pk_context *key) { mbedtls_ssl_key_cert *new_cert; if (cert == NULL) { /* Free list if cert is null */ ssl_key_cert_free(*head); *head = NULL; return 0; } new_cert = mbedtls_calloc(1, sizeof(mbedtls_ssl_key_cert)); if (new_cert == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } new_cert->cert = cert; new_cert->key = key; new_cert->next = NULL; /* Update head if the list was null, else add to the end */ if (*head == NULL) { *head = new_cert; } else { mbedtls_ssl_key_cert *cur = *head; while (cur->next != NULL) { cur = cur->next; } cur->next = new_cert; } return 0; } int mbedtls_ssl_conf_own_cert(mbedtls_ssl_config *conf, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key) { return ssl_append_key_cert(&conf->key_cert, own_cert, pk_key); } void mbedtls_ssl_conf_ca_chain(mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl) { conf->ca_chain = ca_chain; conf->ca_crl = ca_crl; #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() * cannot be used together. */ conf->f_ca_cb = NULL; conf->p_ca_cb = NULL; #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) void mbedtls_ssl_conf_ca_cb(mbedtls_ssl_config *conf, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb) { conf->f_ca_cb = f_ca_cb; conf->p_ca_cb = p_ca_cb; /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() * cannot be used together. */ conf->ca_chain = NULL; conf->ca_crl = NULL; } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl, size_t *name_len) { *name_len = ssl->handshake->sni_name_len; return ssl->handshake->sni_name; } int mbedtls_ssl_set_hs_own_cert(mbedtls_ssl_context *ssl, mbedtls_x509_crt *own_cert, mbedtls_pk_context *pk_key) { return ssl_append_key_cert(&ssl->handshake->sni_key_cert, own_cert, pk_key); } void mbedtls_ssl_set_hs_ca_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl) { ssl->handshake->sni_ca_chain = ca_chain; ssl->handshake->sni_ca_crl = ca_crl; } #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) void mbedtls_ssl_set_hs_dn_hints(mbedtls_ssl_context *ssl, const mbedtls_x509_crt *crt) { ssl->handshake->dn_hints = crt; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ void mbedtls_ssl_set_hs_authmode(mbedtls_ssl_context *ssl, int authmode) { ssl->handshake->sni_authmode = authmode; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_X509_CRT_PARSE_C) void mbedtls_ssl_set_verify(mbedtls_ssl_context *ssl, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { ssl->f_vrfy = f_vrfy; ssl->p_vrfy = p_vrfy; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' }; static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' }; static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common( mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t pwd) { psa_status_t status; psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); const uint8_t *user = NULL; size_t user_len = 0; const uint8_t *peer = NULL; size_t peer_len = 0; psa_pake_cs_set_algorithm(&cipher_suite, PSA_ALG_JPAKE); psa_pake_cs_set_primitive(&cipher_suite, PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256)); psa_pake_cs_set_hash(&cipher_suite, PSA_ALG_SHA_256); status = psa_pake_setup(&ssl->handshake->psa_pake_ctx, &cipher_suite); if (status != PSA_SUCCESS) { return status; } if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { user = jpake_server_id; user_len = sizeof(jpake_server_id); peer = jpake_client_id; peer_len = sizeof(jpake_client_id); } else { user = jpake_client_id; user_len = sizeof(jpake_client_id); peer = jpake_server_id; peer_len = sizeof(jpake_server_id); } status = psa_pake_set_user(&ssl->handshake->psa_pake_ctx, user, user_len); if (status != PSA_SUCCESS) { return status; } status = psa_pake_set_peer(&ssl->handshake->psa_pake_ctx, peer, peer_len); if (status != PSA_SUCCESS) { return status; } status = psa_pake_set_password_key(&ssl->handshake->psa_pake_ctx, pwd); if (status != PSA_SUCCESS) { return status; } ssl->handshake->psa_pake_ctx_is_ok = 1; return PSA_SUCCESS; } int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status; if (ssl->handshake == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Empty password is not valid */ if ((pw == NULL) || (pw_len == 0)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&attributes, PSA_ALG_JPAKE); psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD); status = psa_import_key(&attributes, pw, pw_len, &ssl->handshake->psa_pake_password); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, ssl->handshake->psa_pake_password); if (status != PSA_SUCCESS) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } return 0; } int mbedtls_ssl_set_hs_ecjpake_password_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t pwd) { psa_status_t status; if (ssl->handshake == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (mbedtls_svc_key_id_is_null(pwd)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } status = mbedtls_ssl_set_hs_ecjpake_password_common(ssl, pwd); if (status != PSA_SUCCESS) { psa_pake_abort(&ssl->handshake->psa_pake_ctx); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } return 0; } #else /* MBEDTLS_USE_PSA_CRYPTO */ int mbedtls_ssl_set_hs_ecjpake_password(mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len) { mbedtls_ecjpake_role role; if (ssl->handshake == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Empty password is not valid */ if ((pw == NULL) || (pw_len == 0)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { role = MBEDTLS_ECJPAKE_SERVER; } else { role = MBEDTLS_ECJPAKE_CLIENT; } return mbedtls_ecjpake_setup(&ssl->handshake->ecjpake_ctx, role, MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw, pw_len); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf) { if (conf->psk_identity == NULL || conf->psk_identity_len == 0) { return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { return 1; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL && conf->psk_len != 0) { return 1; } return 0; } static void ssl_conf_remove_psk(mbedtls_ssl_config *conf) { /* Remove reference to existing PSK, if any. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { /* The maintenance of the PSK key slot is the * user's responsibility. */ conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL) { mbedtls_zeroize_and_free(conf->psk, conf->psk_len); conf->psk = NULL; conf->psk_len = 0; } /* Remove reference to PSK identity, if any. */ if (conf->psk_identity != NULL) { mbedtls_free(conf->psk_identity); conf->psk_identity = NULL; conf->psk_identity_len = 0; } } /* This function assumes that PSK identity in the SSL config is unset. * It checks that the provided identity is well-formed and attempts * to make a copy of it in the SSL config. * On failure, the PSK identity in the config remains unset. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf, unsigned char const *psk_identity, size_t psk_identity_len) { /* Identity len will be encoded on two bytes */ if (psk_identity == NULL || psk_identity_len == 0 || (psk_identity_len >> 16) != 0 || psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->psk_identity = mbedtls_calloc(1, psk_identity_len); if (conf->psk_identity == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } conf->psk_identity_len = psk_identity_len; memcpy(conf->psk_identity, psk_identity, conf->psk_identity_len); return 0; } int mbedtls_ssl_conf_psk(mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, const unsigned char *psk_identity, size_t psk_identity_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* We currently only support one PSK, raw or opaque. */ if (mbedtls_ssl_conf_has_static_psk(conf)) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } /* Check and set raw PSK */ if (psk == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (psk_len == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (psk_len > MBEDTLS_PSK_MAX_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if ((conf->psk = mbedtls_calloc(1, psk_len)) == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } conf->psk_len = psk_len; memcpy(conf->psk, psk, conf->psk_len); /* Check and set PSK Identity */ ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len); if (ret != 0) { ssl_conf_remove_psk(conf); } return ret; } static void ssl_remove_psk(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { /* The maintenance of the external PSK key slot is the * user's responsibility. */ if (ssl->handshake->psk_opaque_is_internal) { psa_destroy_key(ssl->handshake->psk_opaque); ssl->handshake->psk_opaque_is_internal = 0; } ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #else if (ssl->handshake->psk != NULL) { mbedtls_zeroize_and_free(ssl->handshake->psk, ssl->handshake->psk_len); ssl->handshake->psk_len = 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } int mbedtls_ssl_set_hs_psk(mbedtls_ssl_context *ssl, const unsigned char *psk, size_t psk_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t key_attributes = psa_key_attributes_init(); psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_algorithm_t alg = PSA_ALG_NONE; mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (psk == NULL || ssl->handshake == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (psk_len > MBEDTLS_PSK_MAX_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_remove_psk(ssl); #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); } else { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); } psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { alg = PSA_ALG_HKDF_EXTRACT(PSA_ALG_ANY_HASH); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); status = psa_import_key(&key_attributes, psk, psk_len, &key); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } /* Allow calling psa_destroy_key() on psk remove */ ssl->handshake->psk_opaque_is_internal = 1; return mbedtls_ssl_set_hs_psk_opaque(ssl, key); #else if ((ssl->handshake->psk = mbedtls_calloc(1, psk_len)) == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } ssl->handshake->psk_len = psk_len; memcpy(ssl->handshake->psk, psk, ssl->handshake->psk_len); return 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_conf_psk_opaque(mbedtls_ssl_config *conf, mbedtls_svc_key_id_t psk, const unsigned char *psk_identity, size_t psk_identity_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* We currently only support one PSK, raw or opaque. */ if (mbedtls_ssl_conf_has_static_psk(conf)) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } /* Check and set opaque PSK */ if (mbedtls_svc_key_id_is_null(psk)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->psk_opaque = psk; /* Check and set PSK Identity */ ret = ssl_conf_set_psk_identity(conf, psk_identity, psk_identity_len); if (ret != 0) { ssl_conf_remove_psk(conf); } return ret; } int mbedtls_ssl_set_hs_psk_opaque(mbedtls_ssl_context *ssl, mbedtls_svc_key_id_t psk) { if ((mbedtls_svc_key_id_is_null(psk)) || (ssl->handshake == NULL)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_remove_psk(ssl); ssl->handshake->psk_opaque = psk; return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_psk_cb(mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_psk) { conf->f_psk = f_psk; conf->p_psk = p_psk; } #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( psa_algorithm_t alg) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (alg == PSA_ALG_CBC_NO_PADDING) { return MBEDTLS_SSL_MODE_CBC; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ if (PSA_ALG_IS_AEAD(alg)) { return MBEDTLS_SSL_MODE_AEAD; } return MBEDTLS_SSL_MODE_STREAM; } #else /* MBEDTLS_USE_PSA_CRYPTO */ static mbedtls_ssl_mode_t mbedtls_ssl_get_base_mode( mbedtls_cipher_mode_t mode) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (mode == MBEDTLS_MODE_CBC) { return MBEDTLS_SSL_MODE_CBC; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ #if defined(MBEDTLS_GCM_C) || \ defined(MBEDTLS_CCM_C) || \ defined(MBEDTLS_CHACHAPOLY_C) if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM || mode == MBEDTLS_MODE_CHACHAPOLY) { return MBEDTLS_SSL_MODE_AEAD; } #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ return MBEDTLS_SSL_MODE_STREAM; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ static mbedtls_ssl_mode_t mbedtls_ssl_get_actual_mode( mbedtls_ssl_mode_t base_mode, int encrypt_then_mac) { #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) if (encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && base_mode == MBEDTLS_SSL_MODE_CBC) { return MBEDTLS_SSL_MODE_CBC_ETM; } #else (void) encrypt_then_mac; #endif return base_mode; } mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_transform( const mbedtls_ssl_transform *transform) { mbedtls_ssl_mode_t base_mode = mbedtls_ssl_get_base_mode( #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_alg #else mbedtls_cipher_get_cipher_mode(&transform->cipher_ctx_enc) #endif ); int encrypt_then_mac = 0; #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) encrypt_then_mac = transform->encrypt_then_mac; #endif return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); } mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite( #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ const mbedtls_ssl_ciphersuite_t *suite) { mbedtls_ssl_mode_t base_mode = MBEDTLS_SSL_MODE_STREAM; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; psa_algorithm_t alg; psa_key_type_t type; size_t size; status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) suite->cipher, 0, &alg, &type, &size); if (status == PSA_SUCCESS) { base_mode = mbedtls_ssl_get_base_mode(alg); } #else const mbedtls_cipher_info_t *cipher = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) suite->cipher); if (cipher != NULL) { base_mode = mbedtls_ssl_get_base_mode( mbedtls_cipher_info_get_mode(cipher)); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac = 0; #endif return mbedtls_ssl_get_actual_mode(base_mode, encrypt_then_mac); } #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type, size_t taglen, psa_algorithm_t *alg, psa_key_type_t *key_type, size_t *key_size) { #if !defined(MBEDTLS_SSL_HAVE_CCM) (void) taglen; #endif switch (mbedtls_cipher_type) { #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_AES_128_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_AES; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_AES_128_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_AES_128_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_AES_192_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_AES_192_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_AES_256_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_AES; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_AES_256_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_AES_256_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_AES; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_ARIA_128_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_ARIA_128_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_ARIA_128_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_ARIA_192_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_ARIA_192_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_ARIA_256_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_ARIA_256_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_ARIA_256_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_ARIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_CAMELLIA_128_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_CAMELLIA_128_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_CAMELLIA_128_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 128; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_CAMELLIA_192_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_CAMELLIA_192_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 192; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC) case MBEDTLS_CIPHER_CAMELLIA_256_CBC: *alg = PSA_ALG_CBC_NO_PADDING; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM) case MBEDTLS_CIPHER_CAMELLIA_256_CCM: *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM) case MBEDTLS_CIPHER_CAMELLIA_256_GCM: *alg = PSA_ALG_GCM; *key_type = PSA_KEY_TYPE_CAMELLIA; *key_size = 256; break; #endif #if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) case MBEDTLS_CIPHER_CHACHA20_POLY1305: *alg = PSA_ALG_CHACHA20_POLY1305; *key_type = PSA_KEY_TYPE_CHACHA20; *key_size = 256; break; #endif case MBEDTLS_CIPHER_NULL: *alg = MBEDTLS_SSL_NULL_CIPHER; *key_type = 0; *key_size = 0; break; default: return PSA_ERROR_NOT_SUPPORTED; } return PSA_SUCCESS; } #endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) int mbedtls_ssl_conf_dh_param_bin(mbedtls_ssl_config *conf, const unsigned char *dhm_P, size_t P_len, const unsigned char *dhm_G, size_t G_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); if ((ret = mbedtls_mpi_read_binary(&conf->dhm_P, dhm_P, P_len)) != 0 || (ret = mbedtls_mpi_read_binary(&conf->dhm_G, dhm_G, G_len)) != 0) { mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); return ret; } return 0; } int mbedtls_ssl_conf_dh_param_ctx(mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); if ((ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_P, &conf->dhm_P)) != 0 || (ret = mbedtls_dhm_get_value(dhm_ctx, MBEDTLS_DHM_PARAM_G, &conf->dhm_G)) != 0) { mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); return ret; } return 0; } #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) /* * Set the minimum length for Diffie-Hellman parameters */ void mbedtls_ssl_conf_dhm_min_bitlen(mbedtls_ssl_config *conf, unsigned int bitlen) { conf->dhm_min_bitlen = bitlen; } #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) && defined(MBEDTLS_SSL_PROTO_TLS1_2) /* * Set allowed/preferred hashes for handshake signatures */ void mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf, const int *hashes) { conf->sig_hashes = hashes; } #endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */ /* Configure allowed signature algorithms for handshake */ void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf, const uint16_t *sig_algs) { #if !defined(MBEDTLS_DEPRECATED_REMOVED) conf->sig_hashes = NULL; #endif /* !MBEDTLS_DEPRECATED_REMOVED */ conf->sig_algs = sig_algs; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) #if !defined(MBEDTLS_DEPRECATED_REMOVED) /* * Set the allowed elliptic curves * * mbedtls_ssl_setup() takes the provided list * and translates it to a list of IANA TLS group identifiers, * stored in ssl->handshake->group_list. * */ void mbedtls_ssl_conf_curves(mbedtls_ssl_config *conf, const mbedtls_ecp_group_id *curve_list) { conf->curve_list = curve_list; conf->group_list = NULL; } #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_ECP_C */ /* * Set the allowed groups */ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf, const uint16_t *group_list) { #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) conf->curve_list = NULL; #endif conf->group_list = group_list; } #if defined(MBEDTLS_X509_CRT_PARSE_C) int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname) { /* Initialize to suppress unnecessary compiler warning */ size_t hostname_len = 0; /* Check if new hostname is valid before * making any change to current one */ if (hostname != NULL) { hostname_len = strlen(hostname); if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } /* Now it's clear that we will overwrite the old hostname, * so we can free it safely */ if (ssl->hostname != NULL) { mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); } /* Passing NULL as hostname shall clear the old one */ if (hostname == NULL) { ssl->hostname = NULL; } else { ssl->hostname = mbedtls_calloc(1, hostname_len + 1); if (ssl->hostname == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->hostname, hostname, hostname_len); ssl->hostname[hostname_len] = '\0'; } return 0; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) void mbedtls_ssl_conf_sni(mbedtls_ssl_config *conf, int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), void *p_sni) { conf->f_sni = f_sni; conf->p_sni = p_sni; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) int mbedtls_ssl_conf_alpn_protocols(mbedtls_ssl_config *conf, const char **protos) { size_t cur_len, tot_len; const char **p; /* * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings * MUST NOT be truncated." * We check lengths now rather than later. */ tot_len = 0; for (p = protos; *p != NULL; p++) { cur_len = strlen(*p); tot_len += cur_len; if ((cur_len == 0) || (cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) || (tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } conf->alpn_list = protos; return 0; } const char *mbedtls_ssl_get_alpn_protocol(const mbedtls_ssl_context *ssl) { return ssl->alpn_chosen; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) void mbedtls_ssl_conf_srtp_mki_value_supported(mbedtls_ssl_config *conf, int support_mki_value) { conf->dtls_srtp_mki_support = support_mki_value; } int mbedtls_ssl_dtls_srtp_set_mki_value(mbedtls_ssl_context *ssl, unsigned char *mki_value, uint16_t mki_len) { if (mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } memcpy(ssl->dtls_srtp_info.mki_value, mki_value, mki_len); ssl->dtls_srtp_info.mki_len = mki_len; return 0; } int mbedtls_ssl_conf_dtls_srtp_protection_profiles(mbedtls_ssl_config *conf, const mbedtls_ssl_srtp_profile *profiles) { const mbedtls_ssl_srtp_profile *p; size_t list_size = 0; /* check the profiles list: all entry must be valid, * its size cannot be more than the total number of supported profiles, currently 4 */ for (p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; p++) { if (mbedtls_ssl_check_srtp_profile_value(*p) != MBEDTLS_TLS_SRTP_UNSET) { list_size++; } else { /* unsupported value, stop parsing and set the size to an error value */ list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; } } if (list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH) { conf->dtls_srtp_profile_list = NULL; conf->dtls_srtp_profile_list_len = 0; return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->dtls_srtp_profile_list = profiles; conf->dtls_srtp_profile_list_len = list_size; return 0; } void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl, mbedtls_dtls_srtp_info *dtls_srtp_info) { dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; /* do not copy the mki value if there is no chosen profile */ if (dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { dtls_srtp_info->mki_len = 0; } else { dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; memcpy(dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } } #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor) { conf->max_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor); } void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor) { conf->min_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor); } #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_SSL_SRV_C) void mbedtls_ssl_conf_cert_req_ca_list(mbedtls_ssl_config *conf, char cert_req_ca_list) { conf->cert_req_ca_list = cert_req_ca_list; } #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) void mbedtls_ssl_conf_encrypt_then_mac(mbedtls_ssl_config *conf, char etm) { conf->encrypt_then_mac = etm; } #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) void mbedtls_ssl_conf_extended_master_secret(mbedtls_ssl_config *conf, char ems) { conf->extended_ms = ems; } #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_code) { if (mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || ssl_mfl_code_to_length(mfl_code) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } conf->mfl_code = mfl_code; return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ void mbedtls_ssl_conf_legacy_renegotiation(mbedtls_ssl_config *conf, int allow_legacy) { conf->allow_legacy_renegotiation = allow_legacy; } #if defined(MBEDTLS_SSL_RENEGOTIATION) void mbedtls_ssl_conf_renegotiation(mbedtls_ssl_config *conf, int renegotiation) { conf->disable_renegotiation = renegotiation; } void mbedtls_ssl_conf_renegotiation_enforced(mbedtls_ssl_config *conf, int max_records) { conf->renego_max_records = max_records; } void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf, const unsigned char period[8]) { memcpy(conf->renego_period, period, 8); } #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets) { conf->session_tickets = use_tickets; } #endif #if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS) void mbedtls_ssl_conf_new_session_tickets(mbedtls_ssl_config *conf, uint16_t num_tickets) { conf->new_session_tickets_count = num_tickets; } #endif void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf, mbedtls_ssl_ticket_write_t *f_ticket_write, mbedtls_ssl_ticket_parse_t *f_ticket_parse, void *p_ticket) { conf->f_ticket_write = f_ticket_write; conf->f_ticket_parse = f_ticket_parse; conf->p_ticket = p_ticket; } #endif #endif /* MBEDTLS_SSL_SESSION_TICKETS */ void mbedtls_ssl_set_export_keys_cb(mbedtls_ssl_context *ssl, mbedtls_ssl_export_keys_t *f_export_keys, void *p_export_keys) { ssl->f_export_keys = f_export_keys; ssl->p_export_keys = p_export_keys; } #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, mbedtls_ssl_async_sign_t *f_async_sign, mbedtls_ssl_async_decrypt_t *f_async_decrypt, mbedtls_ssl_async_resume_t *f_async_resume, mbedtls_ssl_async_cancel_t *f_async_cancel, void *async_config_data) { conf->f_async_sign_start = f_async_sign; conf->f_async_decrypt_start = f_async_decrypt; conf->f_async_resume = f_async_resume; conf->f_async_cancel = f_async_cancel; conf->p_async_config_data = async_config_data; } void *mbedtls_ssl_conf_get_async_config_data(const mbedtls_ssl_config *conf) { return conf->p_async_config_data; } void *mbedtls_ssl_get_async_operation_data(const mbedtls_ssl_context *ssl) { if (ssl->handshake == NULL) { return NULL; } else { return ssl->handshake->user_async_ctx; } } void mbedtls_ssl_set_async_operation_data(mbedtls_ssl_context *ssl, void *ctx) { if (ssl->handshake != NULL) { ssl->handshake->user_async_ctx = ctx; } } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* * SSL get accessors */ uint32_t mbedtls_ssl_get_verify_result(const mbedtls_ssl_context *ssl) { if (ssl->session != NULL) { return ssl->session->verify_result; } if (ssl->session_negotiate != NULL) { return ssl->session_negotiate->verify_result; } return 0xFFFFFFFF; } int mbedtls_ssl_get_ciphersuite_id_from_ssl(const mbedtls_ssl_context *ssl) { if (ssl == NULL || ssl->session == NULL) { return 0; } return ssl->session->ciphersuite; } const char *mbedtls_ssl_get_ciphersuite(const mbedtls_ssl_context *ssl) { if (ssl == NULL || ssl->session == NULL) { return NULL; } return mbedtls_ssl_get_ciphersuite_name(ssl->session->ciphersuite); } const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { switch (ssl->tls_version) { case MBEDTLS_SSL_VERSION_TLS1_2: return "DTLSv1.2"; default: return "unknown (DTLS)"; } } #endif switch (ssl->tls_version) { case MBEDTLS_SSL_VERSION_TLS1_2: return "TLSv1.2"; case MBEDTLS_SSL_VERSION_TLS1_3: return "TLSv1.3"; default: return "unknown"; } } #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl) { const size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; size_t record_size_limit = max_len; if (ssl->session != NULL && ssl->session->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN && ssl->session->record_size_limit < max_len) { record_size_limit = ssl->session->record_size_limit; } // TODO: this is currently untested /* During a handshake, use the value being negotiated */ if (ssl->session_negotiate != NULL && ssl->session_negotiate->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN && ssl->session_negotiate->record_size_limit < max_len) { record_size_limit = ssl->session_negotiate->record_size_limit; } return record_size_limit; } #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl) { size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; size_t read_mfl; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) { return ssl_mfl_code_to_length(ssl->conf->mfl_code); } #endif /* Check if a smaller max length was negotiated */ if (ssl->session_out != NULL) { read_mfl = ssl_mfl_code_to_length(ssl->session_out->mfl_code); if (read_mfl < max_len) { max_len = read_mfl; } } /* During a handshake, use the value being negotiated */ if (ssl->session_negotiate != NULL) { read_mfl = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); if (read_mfl < max_len) { max_len = read_mfl; } } return max_len; } size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl) { size_t max_len; /* * Assume mfl_code is correct since it was checked when set */ max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code); /* Check if a smaller max length was negotiated */ if (ssl->session_out != NULL && ssl_mfl_code_to_length(ssl->session_out->mfl_code) < max_len) { max_len = ssl_mfl_code_to_length(ssl->session_out->mfl_code); } /* During a handshake, use the value being negotiated */ if (ssl->session_negotiate != NULL && ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code) < max_len) { max_len = ssl_mfl_code_to_length(ssl->session_negotiate->mfl_code); } return max_len; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl) { /* Return unlimited mtu for client hello messages to avoid fragmentation. */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && (ssl->state == MBEDTLS_SSL_CLIENT_HELLO || ssl->state == MBEDTLS_SSL_SERVER_HELLO)) { return 0; } if (ssl->handshake == NULL || ssl->handshake->mtu == 0) { return ssl->mtu; } if (ssl->mtu == 0) { return ssl->handshake->mtu; } return ssl->mtu < ssl->handshake->mtu ? ssl->mtu : ssl->handshake->mtu; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl) { size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && \ !defined(MBEDTLS_SSL_PROTO_DTLS) (void) ssl; #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl); if (max_len > mfl) { max_len = mfl; } #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) const size_t record_size_limit = mbedtls_ssl_get_output_record_size_limit(ssl); if (max_len > record_size_limit) { max_len = record_size_limit; } #endif if (ssl->transform_out != NULL && ssl->transform_out->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* * In TLS 1.3 case, when records are protected, `max_len` as computed * above is the maximum length of the TLSInnerPlaintext structure that * along the plaintext payload contains the inner content type (one byte) * and some zero padding. Given the algorithm used for padding * in mbedtls_ssl_encrypt_buf(), compute the maximum length for * the plaintext payload. Round down to a multiple of * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY and * subtract 1. */ max_len = ((max_len / MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) - 1; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (mbedtls_ssl_get_current_mtu(ssl) != 0) { const size_t mtu = mbedtls_ssl_get_current_mtu(ssl); const int ret = mbedtls_ssl_get_record_expansion(ssl); const size_t overhead = (size_t) ret; if (ret < 0) { return ret; } if (mtu <= overhead) { MBEDTLS_SSL_DEBUG_MSG(1, ("MTU too low for record expansion")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } if (max_len > mtu - overhead) { max_len = mtu - overhead; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ !defined(MBEDTLS_SSL_PROTO_DTLS) && \ !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) ((void) ssl); #endif return (int) max_len; } int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl) { size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) (void) ssl; #endif #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) const size_t mfl = mbedtls_ssl_get_input_max_frag_len(ssl); if (max_len > mfl) { max_len = mfl; } #endif return (int) max_len; } #if defined(MBEDTLS_X509_CRT_PARSE_C) const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl) { if (ssl == NULL || ssl->session == NULL) { return NULL; } #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) return ssl->session->peer_cert; #else return NULL; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst) { int ret; if (ssl == NULL || dst == NULL || ssl->session == NULL || ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer * idempotent: Each session can only be exported once. * * (This is in preparation for TLS 1.3 support where we will * need the ability to export multiple sessions (aka tickets), * which will be achieved by calling mbedtls_ssl_get_session() * multiple times until it fails.) * * Check whether we have already exported the current session, * and fail if so. */ if (ssl->session->exported == 1) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } ret = mbedtls_ssl_session_copy(dst, ssl->session); if (ret != 0) { return ret; } /* Remember that we've exported the session. */ ssl->session->exported = 1; return 0; } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) /* Serialization of TLS 1.2 sessions * * For more detail, see the description of ssl_session_save(). */ static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len) { unsigned char *p = buf; size_t used = 0; #if defined(MBEDTLS_HAVE_TIME) uint64_t start; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Time */ #if defined(MBEDTLS_HAVE_TIME) used += 8; if (used <= buf_len) { start = (uint64_t) session->start; MBEDTLS_PUT_UINT64_BE(start, p, 0); p += 8; } #endif /* MBEDTLS_HAVE_TIME */ /* * Basic mandatory fields */ used += 1 /* id_len */ + sizeof(session->id) + sizeof(session->master) + 4; /* verify_result */ if (used <= buf_len) { *p++ = MBEDTLS_BYTE_0(session->id_len); memcpy(p, session->id, 32); p += 32; memcpy(p, session->master, 48); p += 48; MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0); p += 4; } /* * Peer's end-entity certificate */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (session->peer_cert == NULL) { cert_len = 0; } else { cert_len = session->peer_cert->raw.len; } used += 3 + cert_len; if (used <= buf_len) { *p++ = MBEDTLS_BYTE_2(cert_len); *p++ = MBEDTLS_BYTE_1(cert_len); *p++ = MBEDTLS_BYTE_0(cert_len); if (session->peer_cert != NULL) { memcpy(p, session->peer_cert->raw.p, cert_len); p += cert_len; } } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (session->peer_cert_digest != NULL) { used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; if (used <= buf_len) { *p++ = (unsigned char) session->peer_cert_digest_type; *p++ = (unsigned char) session->peer_cert_digest_len; memcpy(p, session->peer_cert_digest, session->peer_cert_digest_len); p += session->peer_cert_digest_len; } } else { used += 2; if (used <= buf_len) { *p++ = (unsigned char) MBEDTLS_MD_NONE; *p++ = 0; } } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Session ticket if any, plus associated data */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ if (used <= buf_len) { *p++ = MBEDTLS_BYTE_2(session->ticket_len); *p++ = MBEDTLS_BYTE_1(session->ticket_len); *p++ = MBEDTLS_BYTE_0(session->ticket_len); if (session->ticket != NULL) { memcpy(p, session->ticket, session->ticket_len); p += session->ticket_len; } MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); p += 4; } } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { used += 8; if (used <= buf_len) { MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0); p += 8; } } #endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * Misc extension-related info */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) used += 1; if (used <= buf_len) { *p++ = session->mfl_code; } #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) used += 1; if (used <= buf_len) { *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac); } #endif return used; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_HAVE_TIME) uint64_t start; #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ const unsigned char *p = buf; const unsigned char * const end = buf + len; /* * Time */ #if defined(MBEDTLS_HAVE_TIME) if (8 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } start = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; session->start = (time_t) start; #endif /* MBEDTLS_HAVE_TIME */ /* * Basic mandatory fields */ if (1 + 32 + 48 + 4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->id_len = *p++; memcpy(session->id, p, 32); p += 32; memcpy(session->master, p, 48); p += 48; session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; /* Immediately clear invalid pointer values that have been read, in case * we exit early before we replaced them with valid ones. */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) session->peer_cert = NULL; #else session->peer_cert_digest = NULL; #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) session->ticket = NULL; #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ /* * Peer certificate */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* Deserialize CRT from the end of the ticket. */ if (3 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } cert_len = MBEDTLS_GET_UINT24_BE(p, 0); p += 3; if (cert_len != 0) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (cert_len > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (session->peer_cert == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } mbedtls_x509_crt_init(session->peer_cert); if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert, p, cert_len)) != 0) { mbedtls_x509_crt_free(session->peer_cert); mbedtls_free(session->peer_cert); session->peer_cert = NULL; return ret; } p += cert_len; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Deserialize CRT digest from the end of the ticket. */ if (2 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; session->peer_cert_digest_len = (size_t) *p++; if (session->peer_cert_digest_len != 0) { const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(session->peer_cert_digest_type); if (md_info == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (session->peer_cert_digest_len > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->peer_cert_digest = mbedtls_calloc(1, session->peer_cert_digest_len); if (session->peer_cert_digest == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->peer_cert_digest, p, session->peer_cert_digest_len); p += session->peer_cert_digest_len; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Session ticket and associated data */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { if (3 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0); p += 3; if (session->ticket_len != 0) { if (session->ticket_len > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket = mbedtls_calloc(1, session->ticket_len); if (session->ticket == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->ticket, p, session->ticket_len); p += session->ticket_len; } if (4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { if (8 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; } #endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * Misc extension-related info */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) if (1 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->mfl_code = *p++; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (1 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->encrypt_then_mac = *p++; #endif /* Done, should have consumed entire buffer */ if (p != end) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return 0; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* Serialization of TLS 1.3 sessions: * * For more detail, see the description of ssl_session_save(). */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; #if defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) size_t hostname_len = (session->hostname == NULL) ? 0 : strlen(session->hostname) + 1; #endif #if defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) const size_t alpn_len = (session->ticket_alpn == NULL) ? 0 : strlen(session->ticket_alpn) + 1; #endif size_t needed = 4 /* ticket_age_add */ + 1 /* ticket_flags */ + 1; /* resumption_key length */ *olen = 0; if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } needed += session->resumption_key_len; /* resumption_key */ #if defined(MBEDTLS_SSL_EARLY_DATA) needed += 4; /* max_early_data_size */ #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) needed += 2; /* record_size_limit */ #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_HAVE_TIME) needed += 8; /* ticket_creation_time or ticket_reception_time */ #endif #if defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) needed += 2 /* alpn_len */ + alpn_len; /* alpn */ #endif } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) needed += 2 /* hostname_len */ + hostname_len; /* hostname */ #endif needed += 4 /* ticket_lifetime */ + 2; /* ticket_len */ /* Check size_t overflow */ if (session->ticket_len > SIZE_MAX - needed) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } needed += session->ticket_len; /* ticket */ } #endif /* MBEDTLS_SSL_CLI_C */ *olen = needed; if (needed > buf_len) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0); p[4] = session->ticket_flags; /* save resumption_key */ p[5] = session->resumption_key_len; p += 6; memcpy(p, session->resumption_key, session->resumption_key_len); p += session->resumption_key_len; #if defined(MBEDTLS_SSL_EARLY_DATA) MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0); p += 4; #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0); p += 2; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_HAVE_TIME) MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0); p += 8; #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0); p += 2; if (alpn_len > 0) { /* save chosen alpn */ memcpy(p, session->ticket_alpn, alpn_len); p += alpn_len; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0); p += 2; if (hostname_len > 0) { /* save host name */ memcpy(p, session->hostname, hostname_len); p += hostname_len; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_HAVE_TIME) MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0); p += 8; #endif MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0); p += 4; MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0); p += 2; if (session->ticket != NULL && session->ticket_len > 0) { memcpy(p, session->ticket, session->ticket_len); p += session->ticket_len; } } #endif /* MBEDTLS_SSL_CLI_C */ return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char *end = buf + len; if (end - p < 6) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0); session->ticket_flags = p[4]; /* load resumption_key */ session->resumption_key_len = p[5]; p += 6; if (end - p < session->resumption_key_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (sizeof(session->resumption_key) < session->resumption_key_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(session->resumption_key, p, session->resumption_key_len); p += session->resumption_key_len; #if defined(MBEDTLS_SSL_EARLY_DATA) if (end - p < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; #endif #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_HAVE_TIME) if (end - p < 8) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) size_t alpn_len; if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } alpn_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (end - p < (long int) alpn_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (alpn_len > 0) { int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p); if (ret != 0) { return ret; } p += alpn_len; } #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) size_t hostname_len; /* load host name */ if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } hostname_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (end - p < (long int) hostname_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (hostname_len > 0) { session->hostname = mbedtls_calloc(1, hostname_len); if (session->hostname == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->hostname, p, hostname_len); p += hostname_len; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_HAVE_TIME) if (end - p < 8) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; #endif if (end - p < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (end - p < (long int) session->ticket_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (session->ticket_len > 0) { session->ticket = mbedtls_calloc(1, session->ticket_len); if (session->ticket == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->ticket, p, session->ticket_len); p += session->ticket_len; } } #endif /* MBEDTLS_SSL_CLI_C */ return 0; } #else /* MBEDTLS_SSL_SESSION_TICKETS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { ((void) session); ((void) buf); ((void) buf_len); *olen = 0; return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } static int ssl_tls13_session_load(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len) { ((void) session); ((void) buf); ((void) buf_len); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* !MBEDTLS_SSL_SESSION_TICKETS */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Define ticket header determining Mbed TLS version * and structure of the ticket. */ /* * Define bitflag determining compile-time settings influencing * structure of serialized SSL sessions. */ #if defined(MBEDTLS_HAVE_TIME) #define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) #define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0 #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) #define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) #define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #define SSL_SERIALIZED_SESSION_CONFIG_SNI 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_SNI 0 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_EARLY_DATA) #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 0 #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \ defined(MBEDTLS_SSL_EARLY_DATA) #define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0 #endif /* MBEDTLS_SSL_ALPN */ #define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 #define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 #define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 #define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 4 #define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 5 #define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 6 #define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT 7 #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT 8 #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT 9 #define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT 10 #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ ((uint16_t) ( \ (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \ SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \ SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_SNI << SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \ SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \ SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \ (SSL_SERIALIZED_SESSION_CONFIG_ALPN << \ SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT))) static const unsigned char ssl_serialized_session_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), }; /* * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) * * TLS 1.2 session: * * struct { * #if defined(MBEDTLS_SSL_SESSION_TICKETS) * opaque ticket<0..2^24-1>; // length 0 means no ticket * uint32 ticket_lifetime; * #endif * } ClientOnlyData; * * struct { * #if defined(MBEDTLS_HAVE_TIME) * uint64 start_time; * #endif * uint8 session_id_len; // at most 32 * opaque session_id[32]; * opaque master[48]; // fixed length in the standard * uint32 verify_result; * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert * #else * uint8 peer_cert_digest_type; * opaque peer_cert_digest<0..2^8-1> * #endif * select (endpoint) { * case client: ClientOnlyData; * case server: uint64 ticket_creation_time; * }; * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) * uint8 mfl_code; // up to 255 according to standard * #endif * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) * uint8 encrypt_then_mac; // 0 or 1 * #endif * } serialized_session_tls12; * * * TLS 1.3 Session: * * struct { * #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) * opaque hostname<0..2^16-1>; * #endif * #if defined(MBEDTLS_HAVE_TIME) * uint64 ticket_reception_time; * #endif * uint32 ticket_lifetime; * opaque ticket<1..2^16-1>; * } ClientOnlyData; * * struct { * uint32 ticket_age_add; * uint8 ticket_flags; * opaque resumption_key<0..255>; * #if defined(MBEDTLS_SSL_EARLY_DATA) * uint32 max_early_data_size; * #endif * #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) * uint16 record_size_limit; * #endif * select ( endpoint ) { * case client: ClientOnlyData; * case server: * #if defined(MBEDTLS_HAVE_TIME) * uint64 ticket_creation_time; * #endif * #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) * opaque ticket_alpn<0..256>; * #endif * }; * } serialized_session_tls13; * * * SSL session: * * struct { * * opaque mbedtls_version[3]; // library version: major, minor, patch * opaque session_format[2]; // library-version specific 16-bit field * // determining the format of the remaining * // serialized data. * * Note: When updating the format, remember to keep * these version+format bytes. * * // In this version, `session_format` determines * // the setting of those compile-time * // configuration options which influence * // the structure of mbedtls_ssl_session. * * uint8_t minor_ver; // Protocol minor version. Possible values: * // - TLS 1.2 (0x0303) * // - TLS 1.3 (0x0304) * uint8_t endpoint; * uint16_t ciphersuite; * * select (serialized_session.tls_version) { * * case MBEDTLS_SSL_VERSION_TLS1_2: * serialized_session_tls12 data; * case MBEDTLS_SSL_VERSION_TLS1_3: * serialized_session_tls13 data; * * }; * * } serialized_session; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_session_save(const mbedtls_ssl_session *session, unsigned char omit_header, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; size_t used = 0; size_t remaining_len; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) size_t out_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif if (session == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (!omit_header) { /* * Add Mbed TLS version identifier */ used += sizeof(ssl_serialized_session_header); if (used <= buf_len) { memcpy(p, ssl_serialized_session_header, sizeof(ssl_serialized_session_header)); p += sizeof(ssl_serialized_session_header); } } /* * TLS version identifier, endpoint, ciphersuite */ used += 1 /* TLS version */ + 1 /* endpoint */ + 2; /* ciphersuite */ if (used <= buf_len) { *p++ = MBEDTLS_BYTE_0(session->tls_version); *p++ = session->endpoint; MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0); p += 2; } /* Forward to version-specific serialization routine. */ remaining_len = (buf_len >= used) ? buf_len - used : 0; switch (session->tls_version) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) case MBEDTLS_SSL_VERSION_TLS1_2: used += ssl_tls12_session_save(session, p, remaining_len); break; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) case MBEDTLS_SSL_VERSION_TLS1_3: ret = ssl_tls13_session_save(session, p, remaining_len, &out_len); if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { return ret; } used += out_len; break; #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ default: return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } *olen = used; if (used > buf_len) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } return 0; } /* * Public wrapper for ssl_session_save() */ int mbedtls_ssl_session_save(const mbedtls_ssl_session *session, unsigned char *buf, size_t buf_len, size_t *olen) { return ssl_session_save(session, 0, buf, buf_len, olen); } /* * Deserialize session, see mbedtls_ssl_session_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error, and has an extra option omit_header. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_session_load(mbedtls_ssl_session *session, unsigned char omit_header, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char * const end = buf + len; size_t remaining_len; if (session == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (!omit_header) { /* * Check Mbed TLS version identifier */ if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (memcmp(p, ssl_serialized_session_header, sizeof(ssl_serialized_session_header)) != 0) { return MBEDTLS_ERR_SSL_VERSION_MISMATCH; } p += sizeof(ssl_serialized_session_header); } /* * TLS version identifier, endpoint, ciphersuite */ if (4 > (size_t) (end - p)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++); session->endpoint = *p++; session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Dispatch according to TLS version. */ remaining_len = (size_t) (end - p); switch (session->tls_version) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) case MBEDTLS_SSL_VERSION_TLS1_2: return ssl_tls12_session_load(session, p, remaining_len); #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) case MBEDTLS_SSL_VERSION_TLS1_3: return ssl_tls13_session_load(session, p, remaining_len); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ default: return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } /* * Deserialize session: public wrapper for error cleaning */ int mbedtls_ssl_session_load(mbedtls_ssl_session *session, const unsigned char *buf, size_t len) { int ret = ssl_session_load(session, 0, buf, len); if (ret != 0) { mbedtls_ssl_session_free(session); } return ret; } /* * Perform a single step of the SSL handshake */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * We may have not been able to send to the peer all the handshake data * that were written into the output buffer by the previous handshake step, * if the write to the network callback returned with the * #MBEDTLS_ERR_SSL_WANT_WRITE error code. * We proceed to the next handshake step only when all data from the * previous one have been sent to the peer, thus we make sure that this is * the case here by calling `mbedtls_ssl_flush_output()`. The function may * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case * we have to wait before to go ahead. * In the case of TLS 1.3, handshake step handlers do not send data to the * peer. Data are only sent here and through * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an * alert occurred. */ if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) { return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) { if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { return ret; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ return ret; } int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl == NULL || ssl->conf == NULL || ssl->handshake == NULL || ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ret = ssl_prepare_handshake_step(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_handle_pending_alert(ssl); if (ret != 0) { goto cleanup; } /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or * MBEDTLS_SSL_IS_SERVER, this is the return code we give */ ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s", mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state))); switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; ret = 0; break; case MBEDTLS_SSL_CLIENT_HELLO: ret = mbedtls_ssl_write_client_hello(ssl); break; default: #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { ret = mbedtls_ssl_tls13_handshake_client_step(ssl); } else { ret = mbedtls_ssl_handshake_client_step(ssl); } #elif defined(MBEDTLS_SSL_PROTO_TLS1_2) ret = mbedtls_ssl_handshake_client_step(ssl); #else ret = mbedtls_ssl_tls13_handshake_client_step(ssl); #endif } } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { ret = mbedtls_ssl_tls13_handshake_server_step(ssl); } else { ret = mbedtls_ssl_handshake_server_step(ssl); } #elif defined(MBEDTLS_SSL_PROTO_TLS1_2) ret = mbedtls_ssl_handshake_server_step(ssl); #else ret = mbedtls_ssl_tls13_handshake_server_step(ssl); #endif } #endif /* MBEDTLS_SSL_SRV_C */ if (ret != 0) { /* handshake_step return error. And it is same * with alert_reason. */ if (ssl->send_alert) { ret = mbedtls_ssl_handle_pending_alert(ssl); goto cleanup; } } cleanup: return ret; } /* * Perform the SSL handshake */ int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl) { int ret = 0; /* Sanity checks */ if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) { MBEDTLS_SSL_DEBUG_MSG(1, ("You must use " "mbedtls_ssl_set_timer_cb() for DTLS")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake")); /* Main handshake loop */ while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) { ret = mbedtls_ssl_handshake_step(ssl); if (ret != 0) { break; } } MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake")); return ret; } #if defined(MBEDTLS_SSL_RENEGOTIATION) #if defined(MBEDTLS_SSL_SRV_C) /* * Write HelloRequest to request renegotiation on server */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request")); ssl->out_msglen = 4; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request")); return 0; } #endif /* MBEDTLS_SSL_SRV_C */ /* * Actually renegotiate current connection, triggered by either: * - any side: calling mbedtls_ssl_renegotiate(), * - client: receiving a HelloRequest during mbedtls_ssl_read(), * - server: receiving any handshake message on server during mbedtls_ssl_read() after * the initial handshake is completed. * If the handshake doesn't complete due to waiting for I/O, it will continue * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. */ int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate")); if ((ret = ssl_handshake_init(ssl)) != 0) { return ret; } /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and * the ServerHello will have message_seq = 1" */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) { if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { ssl->handshake->out_msg_seq = 1; } else { ssl->handshake->in_msg_seq = 1; } } #endif ssl->state = MBEDTLS_SSL_HELLO_REQUEST; ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate")); return 0; } /* * Renegotiate current connection on client, * or request renegotiation on server */ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; if (ssl == NULL || ssl->conf == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if defined(MBEDTLS_SSL_SRV_C) /* On server, just send the request */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { if (mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; /* Did we already try/start sending HelloRequest? */ if (ssl->out_left != 0) { return mbedtls_ssl_flush_output(ssl); } return ssl_write_hello_request(ssl); } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) /* * On client, either start the renegotiation process or, * if already in progress, continue the handshake */ if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { if (mbedtls_ssl_is_handshake_over(ssl) == 0) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret); return ret; } } else { if ((ret = mbedtls_ssl_handshake(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret); return ret; } } #endif /* MBEDTLS_SSL_CLI_C */ return ret; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; if (handshake == NULL) { return; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) #if !defined(MBEDTLS_DEPRECATED_REMOVED) if (ssl->handshake->group_list_heap_allocated) { mbedtls_free((void *) handshake->group_list); } handshake->group_list = NULL; #endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if !defined(MBEDTLS_DEPRECATED_REMOVED) if (ssl->handshake->sig_algs_heap_allocated) { mbedtls_free((void *) handshake->sig_algs); } handshake->sig_algs = NULL; #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (ssl->handshake->certificate_request_context) { mbedtls_free((void *) handshake->certificate_request_context); } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) { ssl->conf->f_async_cancel(ssl); handshake->async_in_progress = 0; } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_abort(&handshake->fin_sha256_psa); #else mbedtls_md_free(&handshake->fin_sha256); #endif #endif #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_abort(&handshake->fin_sha384_psa); #else mbedtls_md_free(&handshake->fin_sha384); #endif #endif #if defined(MBEDTLS_DHM_C) mbedtls_dhm_free(&handshake->dhm_ctx); #endif #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) mbedtls_ecdh_free(&handshake->ecdh_ctx); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_pake_abort(&handshake->psa_pake_ctx); /* * Opaque keys are not stored in the handshake's data and it's the user * responsibility to destroy them. Clear ones, instead, are created by * the TLS library and should be destroyed at the same level */ if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) { psa_destroy_key(handshake->psa_pake_password); } handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_ecjpake_free(&handshake->ecjpake_ctx); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_CLI_C) mbedtls_free(handshake->ecjpake_cache); handshake->ecjpake_cache = NULL; handshake->ecjpake_cache_len = 0; #endif #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /* explicit void pointer cast for buggy MS compiler */ mbedtls_free((void *) handshake->curves_tls_id); #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { /* The maintenance of the external PSK key slot is the * user's responsibility. */ if (ssl->handshake->psk_opaque_is_internal) { psa_destroy_key(ssl->handshake->psk_opaque); ssl->handshake->psk_opaque_is_internal = 0; } ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #else if (handshake->psk != NULL) { mbedtls_zeroize_and_free(handshake->psk, handshake->psk_len); } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /* * Free only the linked list wrapper, not the keys themselves * since the belong to the SNI callback */ ssl_key_cert_free(handshake->sni_key_cert); #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx); if (handshake->ecrs_peer_cert != NULL) { mbedtls_x509_crt_free(handshake->ecrs_peer_cert); mbedtls_free(handshake->ecrs_peer_cert); } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) mbedtls_pk_free(&handshake->peer_pubkey); #endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #if defined(MBEDTLS_SSL_CLI_C) && \ (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3)) mbedtls_free(handshake->cookie); #endif /* MBEDTLS_SSL_CLI_C && ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_ssl_flight_free(handshake->flight); mbedtls_ssl_buffering_free(ssl); #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED) if (handshake->xxdh_psa_privkey_is_external == 0) { psa_destroy_key(handshake->xxdh_psa_privkey); } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_transform_free(handshake->transform_handshake); mbedtls_free(handshake->transform_handshake); #if defined(MBEDTLS_SSL_EARLY_DATA) mbedtls_ssl_transform_free(handshake->transform_earlydata); mbedtls_free(handshake->transform_earlydata); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) /* If the buffers are too big - reallocate. Because of the way Mbed TLS * processes datagrams and the fact that a datagram is allowed to have * several records in it, it is possible that the I/O buffers are not * empty at this stage */ handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl), mbedtls_ssl_get_output_buflen(ssl)); #endif /* mbedtls_platform_zeroize MUST be last one in this function */ mbedtls_platform_zeroize(handshake, sizeof(mbedtls_ssl_handshake_params)); } void mbedtls_ssl_session_free(mbedtls_ssl_session *session) { if (session == NULL) { return; } #if defined(MBEDTLS_X509_CRT_PARSE_C) ssl_clear_peer_cert(session); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) mbedtls_free(session->hostname); #endif mbedtls_free(session->ticket); #endif #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \ defined(MBEDTLS_SSL_SRV_C) mbedtls_free(session->ticket_alpn); #endif mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session)); } #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u #else #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u #else #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_ALPN) #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u #else #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u #endif /* MBEDTLS_SSL_ALPN */ #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 #define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 #define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 #define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ ((uint32_t) ( \ (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \ SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \ (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \ SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \ (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \ SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \ (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \ 0u)) static const unsigned char ssl_serialized_context_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG), MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG), }; /* * Serialize a full SSL context * * The format of the serialized data is: * (in the presentation language of TLS, RFC 8446 section 3) * * // header * opaque mbedtls_version[3]; // major, minor, patch * opaque context_format[5]; // version-specific field determining * // the format of the remaining * // serialized data. * Note: When updating the format, remember to keep these * version+format bytes. (We may make their size part of the API.) * * // session sub-structure * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() * // transform sub-structure * uint8 random[64]; // ServerHello.random+ClientHello.random * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use * // fields from ssl_context * uint32 badmac_seen; // DTLS: number of records with failing MAC * uint64 in_window_top; // DTLS: last validated record seq_num * uint64 in_window; // DTLS: bitmask for replay protection * uint8 disable_datagram_packing; // DTLS: only one record per datagram * uint64 cur_out_ctr; // Record layer: outgoing sequence number * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol * * Note that many fields of the ssl_context or sub-structures are not * serialized, as they fall in one of the following categories: * * 1. forced value (eg in_left must be 0) * 2. pointer to dynamically-allocated memory (eg session, transform) * 3. value can be re-derived from other data (eg session keys from MS) * 4. value was temporary (eg content of input buffer) * 5. value will be provided by the user again (eg I/O callbacks and context) */ int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl, unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *p = buf; size_t used = 0; size_t session_len; int ret = 0; /* * Enforce usage restrictions, see "return BAD_INPUT_DATA" in * this function's documentation. * * These are due to assumptions/limitations in the implementation. Some of * them are likely to stay (no handshake in progress) some might go away * (only DTLS) but are currently used to simplify the implementation. */ /* The initial handshake must be over */ if (mbedtls_ssl_is_handshake_over(ssl) == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->handshake != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Double-check that sub-structures are indeed ready */ if (ssl->transform == NULL || ssl->session == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* There must be no pending incoming or outgoing data */ if (mbedtls_ssl_check_pending(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (ssl->out_left != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Protocol must be DTLS, not TLS */ if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Version must be 1.2 */ if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* We must be using an AEAD ciphersuite */ if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Renegotiation must not be enabled */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) { MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* * Version and format identifier */ used += sizeof(ssl_serialized_context_header); if (used <= buf_len) { memcpy(p, ssl_serialized_context_header, sizeof(ssl_serialized_context_header)); p += sizeof(ssl_serialized_context_header); } /* * Session (length + data) */ ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len); if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) { return ret; } used += 4 + session_len; if (used <= buf_len) { MBEDTLS_PUT_UINT32_BE(session_len, p, 0); p += 4; ret = ssl_session_save(ssl->session, 1, p, session_len, &session_len); if (ret != 0) { return ret; } p += session_len; } /* * Transform */ used += sizeof(ssl->transform->randbytes); if (used <= buf_len) { memcpy(p, ssl->transform->randbytes, sizeof(ssl->transform->randbytes)); p += sizeof(ssl->transform->randbytes); } #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) used += 2U + ssl->transform->in_cid_len + ssl->transform->out_cid_len; if (used <= buf_len) { *p++ = ssl->transform->in_cid_len; memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len); p += ssl->transform->in_cid_len; *p++ = ssl->transform->out_cid_len; memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len); p += ssl->transform->out_cid_len; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * Saved fields from top-level ssl_context structure */ used += 4; if (used <= buf_len) { MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0); p += 4; } #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) used += 16; if (used <= buf_len) { MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0); p += 8; MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0); p += 8; } #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_PROTO_DTLS) used += 1; if (used <= buf_len) { *p++ = ssl->disable_datagram_packing; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; if (used <= buf_len) { memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN); p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; } #if defined(MBEDTLS_SSL_PROTO_DTLS) used += 2; if (used <= buf_len) { MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0); p += 2; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) { const uint8_t alpn_len = ssl->alpn_chosen ? (uint8_t) strlen(ssl->alpn_chosen) : 0; used += 1 + alpn_len; if (used <= buf_len) { *p++ = alpn_len; if (ssl->alpn_chosen != NULL) { memcpy(p, ssl->alpn_chosen, alpn_len); p += alpn_len; } } } #endif /* MBEDTLS_SSL_ALPN */ /* * Done */ *olen = used; if (used > buf_len) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used); return mbedtls_ssl_session_reset_int(ssl, 0); } /* * Deserialize context, see mbedtls_ssl_context_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_context_load(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char * const end = buf + len; size_t session_len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_SSL_PROTO_TLS1_2) tls_prf_fn prf_func = NULL; #endif /* * The context should have been freshly setup or reset. * Give the user an error in case of obvious misuse. * (Checking session is useful because it won't be NULL if we're * renegotiating, or if the user mistakenly loaded a session first.) */ if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST || ssl->session != NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * We can't check that the config matches the initial one, but we can at * least check it matches the requirements for serializing. */ if ( #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || #endif ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 || ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 ) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len); /* * Check version identifier */ if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } if (memcmp(p, ssl_serialized_context_header, sizeof(ssl_serialized_context_header)) != 0) { return MBEDTLS_ERR_SSL_VERSION_MISMATCH; } p += sizeof(ssl_serialized_context_header); /* * Session */ if ((size_t) (end - p) < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } session_len = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; /* This has been allocated by ssl_handshake_init(), called by * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ ssl->session = ssl->session_negotiate; ssl->session_in = ssl->session; ssl->session_out = ssl->session; ssl->session_negotiate = NULL; if ((size_t) (end - p) < session_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ret = ssl_session_load(ssl->session, 1, p, session_len); if (ret != 0) { mbedtls_ssl_session_free(ssl->session); return ret; } p += session_len; /* * Transform */ /* This has been allocated by ssl_handshake_init(), called by * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) ssl->transform = ssl->transform_negotiate; ssl->transform_in = ssl->transform; ssl->transform_out = ssl->transform; ssl->transform_negotiate = NULL; #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite); if (prf_func == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* Read random bytes and populate structure */ if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ret = ssl_tls12_populate_transform(ssl->transform, ssl->session->ciphersuite, ssl->session->master, #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl->session->encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ prf_func, p, /* currently pointing to randbytes */ MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */ ssl->conf->endpoint, ssl); if (ret != 0) { return ret; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ p += sizeof(ssl->transform->randbytes); #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* Read connection IDs and store them */ if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->transform->in_cid_len = *p++; if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len); p += ssl->transform->in_cid_len; ssl->transform->out_cid_len = *p++; if ((size_t) (end - p) < ssl->transform->out_cid_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len); p += ssl->transform->out_cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * Saved fields from top-level ssl_context structure */ if ((size_t) (end - p) < 4) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->badmac_seen = MBEDTLS_GET_UINT32_BE(p, 0); p += 4; #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if ((size_t) (end - p) < 16) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->in_window_top = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; ssl->in_window = MBEDTLS_GET_UINT64_BE(p, 0); p += 8; #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->disable_datagram_packing = *p++; #endif /* MBEDTLS_SSL_PROTO_DTLS */ if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr)); p += sizeof(ssl->cur_out_ctr); #if defined(MBEDTLS_SSL_PROTO_DTLS) if ((size_t) (end - p) < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl->mtu = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) { uint8_t alpn_len; const char **cur; if ((size_t) (end - p) < 1) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } alpn_len = *p++; if (alpn_len != 0 && ssl->conf->alpn_list != NULL) { /* alpn_chosen should point to an item in the configured list */ for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) { if (strlen(*cur) == alpn_len && memcmp(p, *cur, alpn_len) == 0) { ssl->alpn_chosen = *cur; break; } } } /* can only happen on conf mismatch */ if (alpn_len != 0 && ssl->alpn_chosen == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } p += alpn_len; } #endif /* MBEDTLS_SSL_ALPN */ /* * Forced fields from top-level ssl_context structure * * Most of them already set to the correct value by mbedtls_ssl_init() and * mbedtls_ssl_reset(), so we only need to set the remaining ones. */ ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; /* Adjust pointers for header fields of outgoing records to * the given transform, accounting for explicit IV and CID. */ mbedtls_ssl_update_out_pointers(ssl, ssl->transform); #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->in_epoch = 1; #endif /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, * which we don't want - otherwise we'd end up freeing the wrong transform * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() * inappropriately. */ if (ssl->handshake != NULL) { mbedtls_ssl_handshake_free(ssl); mbedtls_free(ssl->handshake); ssl->handshake = NULL; } /* * Done - should have consumed entire buffer */ if (p != end) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return 0; } /* * Deserialize context: public wrapper for error cleaning */ int mbedtls_ssl_context_load(mbedtls_ssl_context *context, const unsigned char *buf, size_t len) { int ret = ssl_context_load(context, buf, len); if (ret != 0) { mbedtls_ssl_free(context); } return ret; } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* * Free an SSL context */ void mbedtls_ssl_free(mbedtls_ssl_context *ssl) { if (ssl == NULL) { return; } MBEDTLS_SSL_DEBUG_MSG(2, ("=> free")); if (ssl->out_buf != NULL) { #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len; #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; #endif mbedtls_zeroize_and_free(ssl->out_buf, out_buf_len); ssl->out_buf = NULL; } if (ssl->in_buf != NULL) { #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t in_buf_len = ssl->in_buf_len; #else size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; #endif mbedtls_zeroize_and_free(ssl->in_buf, in_buf_len); ssl->in_buf = NULL; } if (ssl->transform) { mbedtls_ssl_transform_free(ssl->transform); mbedtls_free(ssl->transform); } if (ssl->handshake) { mbedtls_ssl_handshake_free(ssl); mbedtls_free(ssl->handshake); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) mbedtls_ssl_transform_free(ssl->transform_negotiate); mbedtls_free(ssl->transform_negotiate); #endif mbedtls_ssl_session_free(ssl->session_negotiate); mbedtls_free(ssl->session_negotiate); } #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_transform_free(ssl->transform_application); mbedtls_free(ssl->transform_application); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (ssl->session) { mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); } #if defined(MBEDTLS_X509_CRT_PARSE_C) if (ssl->hostname != NULL) { mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname)); } #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) mbedtls_free(ssl->cli_id); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= free")); /* Actually clear after last debug message */ mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context)); } /* * Initialize mbedtls_ssl_config */ void mbedtls_ssl_config_init(mbedtls_ssl_config *conf) { memset(conf, 0, sizeof(mbedtls_ssl_config)); } /* The selection should be the same as mbedtls_x509_crt_profile_default in * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters: * curves with a lower resource usage come first. * See the documentation of mbedtls_ssl_conf_curves() for what we promise * about this list. */ static const uint16_t ssl_preset_default_groups[] = { #if defined(MBEDTLS_ECP_HAVE_CURVE25519) MBEDTLS_SSL_IANA_TLS_GROUP_X25519, #endif #if defined(MBEDTLS_ECP_HAVE_SECP256R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, #endif #if defined(MBEDTLS_ECP_HAVE_CURVE448) MBEDTLS_SSL_IANA_TLS_GROUP_X448, #endif #if defined(MBEDTLS_ECP_HAVE_SECP521R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, #endif #if defined(MBEDTLS_ECP_HAVE_BP256R1) MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, #endif #if defined(MBEDTLS_ECP_HAVE_BP384R1) MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, #endif #if defined(MBEDTLS_ECP_HAVE_BP512R1) MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, #endif #if defined(PSA_WANT_ALG_FFDH) MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144, MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192, #endif MBEDTLS_SSL_IANA_TLS_GROUP_NONE }; static const int ssl_preset_suiteb_ciphersuites[] = { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 0 }; #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* NOTICE: * For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following * rules SHOULD be upheld. * - No duplicate entries. * - But if there is a good reason, do not change the order of the algorithms. * - ssl_tls12_preset* is for TLS 1.2 use only. * - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes. */ static const uint16_t ssl_preset_default_sig_algs[] = { #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA256) && \ defined(PSA_WANT_ECC_SECP_R1_256) MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA384) && \ defined(PSA_WANT_ECC_SECP_R1_384) MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA512) && \ defined(PSA_WANT_ECC_SECP_R1_521) MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512) #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, #endif #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, #endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, #endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, #endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */ MBEDTLS_TLS_SIG_NONE }; /* NOTICE: see above */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static uint16_t ssl_tls12_preset_default_sig_algs[] = { #if defined(MBEDTLS_MD_CAN_SHA512) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512), #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512, #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512), #endif #endif /* MBEDTLS_MD_CAN_SHA512 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384, #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), #endif #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256), #endif #endif /* MBEDTLS_MD_CAN_SHA256 */ MBEDTLS_TLS_SIG_NONE }; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ /* NOTICE: see above */ static const uint16_t ssl_preset_suiteb_sig_algs[] = { #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA256) && \ defined(MBEDTLS_ECP_HAVE_SECP256R1) MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \ defined(MBEDTLS_MD_CAN_SHA384) && \ defined(MBEDTLS_ECP_HAVE_SECP384R1) MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384) #endif MBEDTLS_TLS_SIG_NONE }; /* NOTICE: see above */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = { #if defined(MBEDTLS_MD_CAN_SHA256) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), #endif #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), #endif #endif /* MBEDTLS_MD_CAN_SHA384 */ MBEDTLS_TLS_SIG_NONE }; #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ static const uint16_t ssl_preset_suiteb_groups[] = { #if defined(MBEDTLS_ECP_HAVE_SECP256R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, #endif MBEDTLS_SSL_IANA_TLS_GROUP_NONE }; #if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs` * to make sure there are no duplicated signature algorithm entries. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_no_sig_alg_duplication(const uint16_t *sig_algs) { size_t i, j; int ret = 0; for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { for (j = 0; j < i; j++) { if (sig_algs[i] != sig_algs[j]) { continue; } mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n", sig_algs[i], j, i); ret = -1; } } return ret; } #endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* * Load default in mbedtls_ssl_config */ int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf, int endpoint, int transport, int preset) { #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #endif #if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) { mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) { mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) { mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) { mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n"); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ /* Use the functions here so that they are covered in tests, * but otherwise access member directly for efficiency */ mbedtls_ssl_conf_endpoint(conf, endpoint); mbedtls_ssl_conf_transport(conf, transport); /* * Things that are common to all presets */ #if defined(MBEDTLS_SSL_CLI_C) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; #if defined(MBEDTLS_SSL_SESSION_TICKETS) conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; #endif } #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) conf->f_cookie_write = ssl_cookie_write_dummy; conf->f_cookie_check = ssl_cookie_check_dummy; #endif #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; #endif #if defined(MBEDTLS_SSL_SRV_C) conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER; #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; memset(conf->renego_period, 0x00, 2); memset(conf->renego_period + 2, 0xFF, 6); #endif #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) if (endpoint == MBEDTLS_SSL_IS_SERVER) { const unsigned char dhm_p[] = MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; const unsigned char dhm_g[] = MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; if ((ret = mbedtls_ssl_conf_dh_param_bin(conf, dhm_p, sizeof(dhm_p), dhm_g, sizeof(dhm_g))) != 0) { return ret; } } #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #if defined(MBEDTLS_SSL_EARLY_DATA) mbedtls_ssl_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED); #if defined(MBEDTLS_SSL_SRV_C) mbedtls_ssl_conf_max_early_data_size(conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE); #endif #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_conf_new_session_tickets( conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS); #endif /* * Allow all TLS 1.3 key exchange modes by default. */ conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; #else return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; #endif } else { #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; #elif defined(MBEDTLS_SSL_PROTO_TLS1_3) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3; #elif defined(MBEDTLS_SSL_PROTO_TLS1_2) conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2; #else return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; #endif } /* * Preset-specific defaults */ switch (preset) { /* * NSA Suite B */ case MBEDTLS_SSL_PRESET_SUITEB: conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites; #if defined(MBEDTLS_X509_CRT_PARSE_C) conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (mbedtls_ssl_conf_is_tls12_only(conf)) { conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ conf->sig_algs = ssl_preset_suiteb_sig_algs; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) conf->curve_list = NULL; #endif conf->group_list = ssl_preset_suiteb_groups; break; /* * Default */ default: conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites(); #if defined(MBEDTLS_X509_CRT_PARSE_C) conf->cert_profile = &mbedtls_x509_crt_profile_default; #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (mbedtls_ssl_conf_is_tls12_only(conf)) { conf->sig_algs = ssl_tls12_preset_default_sig_algs; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ conf->sig_algs = ssl_preset_default_sig_algs; #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) conf->curve_list = NULL; #endif conf->group_list = ssl_preset_default_groups; #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) conf->dhm_min_bitlen = 1024; #endif } return 0; } /* * Free mbedtls_ssl_config */ void mbedtls_ssl_config_free(mbedtls_ssl_config *conf) { #if defined(MBEDTLS_DHM_C) mbedtls_mpi_free(&conf->dhm_P); mbedtls_mpi_free(&conf->dhm_G); #endif #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL) { mbedtls_zeroize_and_free(conf->psk, conf->psk_len); conf->psk = NULL; conf->psk_len = 0; } if (conf->psk_identity != NULL) { mbedtls_zeroize_and_free(conf->psk_identity, conf->psk_identity_len); conf->psk_identity = NULL; conf->psk_identity_len = 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) ssl_key_cert_free(conf->key_cert); #endif mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config)); } #if defined(MBEDTLS_PK_C) && \ (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)) /* * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX */ unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk) { #if defined(MBEDTLS_RSA_C) if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) { return MBEDTLS_SSL_SIG_RSA; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) { return MBEDTLS_SSL_SIG_ECDSA; } #endif return MBEDTLS_SSL_SIG_ANON; } unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type) { switch (type) { case MBEDTLS_PK_RSA: return MBEDTLS_SSL_SIG_RSA; case MBEDTLS_PK_ECDSA: case MBEDTLS_PK_ECKEY: return MBEDTLS_SSL_SIG_ECDSA; default: return MBEDTLS_SSL_SIG_ANON; } } mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig) { switch (sig) { #if defined(MBEDTLS_RSA_C) case MBEDTLS_SSL_SIG_RSA: return MBEDTLS_PK_RSA; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) case MBEDTLS_SSL_SIG_ECDSA: return MBEDTLS_PK_ECDSA; #endif default: return MBEDTLS_PK_NONE; } } #endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED ) */ /* * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX */ mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash) { switch (hash) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_SSL_HASH_MD5: return MBEDTLS_MD_MD5; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_SSL_HASH_SHA1: return MBEDTLS_MD_SHA1; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_SSL_HASH_SHA224: return MBEDTLS_MD_SHA224; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_HASH_SHA256: return MBEDTLS_MD_SHA256; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_HASH_SHA384: return MBEDTLS_MD_SHA384; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_SSL_HASH_SHA512: return MBEDTLS_MD_SHA512; #endif default: return MBEDTLS_MD_NONE; } } /* * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX */ unsigned char mbedtls_ssl_hash_from_md_alg(int md) { switch (md) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_MD_MD5: return MBEDTLS_SSL_HASH_MD5; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_MD_SHA1: return MBEDTLS_SSL_HASH_SHA1; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_MD_SHA224: return MBEDTLS_SSL_HASH_SHA224; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return MBEDTLS_SSL_HASH_SHA256; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return MBEDTLS_SSL_HASH_SHA384; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_MD_SHA512: return MBEDTLS_SSL_HASH_SHA512; #endif default: return MBEDTLS_SSL_HASH_NONE; } } /* * Check if a curve proposed by the peer is in our list. * Return 0 if we're willing to use it, -1 otherwise. */ int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id) { const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); if (group_list == NULL) { return -1; } for (; *group_list != 0; group_list++) { if (*group_list == tls_id) { return 0; } } return -1; } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id. */ int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id) { uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { return -1; } return mbedtls_ssl_check_curve_tls_id(ssl, tls_id); } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ static const struct { uint16_t tls_id; mbedtls_ecp_group_id ecp_group_id; psa_ecc_family_t psa_family; uint16_t bits; } tls_id_match_table[] = { #if defined(MBEDTLS_ECP_HAVE_SECP521R1) { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 }, #endif #if defined(MBEDTLS_ECP_HAVE_BP512R1) { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP384R1) { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 }, #endif #if defined(MBEDTLS_ECP_HAVE_BP384R1) { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP256R1) { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP256K1) { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 }, #endif #if defined(MBEDTLS_ECP_HAVE_BP256R1) { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP224R1) { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP224K1) { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP192R1) { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 }, #endif #if defined(MBEDTLS_ECP_HAVE_SECP192K1) { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 }, #endif #if defined(MBEDTLS_ECP_HAVE_CURVE25519) { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 }, #endif #if defined(MBEDTLS_ECP_HAVE_CURVE448) { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 }, #endif { 0, MBEDTLS_ECP_DP_NONE, 0, 0 }, }; int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id, psa_key_type_t *type, size_t *bits) { for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { if (tls_id_match_table[i].tls_id == tls_id) { if (type != NULL) { *type = PSA_KEY_TYPE_ECC_KEY_PAIR(tls_id_match_table[i].psa_family); } if (bits != NULL) { *bits = tls_id_match_table[i].bits; } return PSA_SUCCESS; } } return PSA_ERROR_NOT_SUPPORTED; } mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id) { for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) { if (tls_id_match_table[i].tls_id == tls_id) { return tls_id_match_table[i].ecp_group_id; } } return MBEDTLS_ECP_DP_NONE; } uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id) { for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE; i++) { if (tls_id_match_table[i].ecp_group_id == grp_id) { return tls_id_match_table[i].tls_id; } } return 0; } #if defined(MBEDTLS_DEBUG_C) static const struct { uint16_t tls_id; const char *name; } tls_id_curve_name_table[] = { { MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, "secp521r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, "brainpoolP512r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, "secp384r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, "brainpoolP384r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, "secp256r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1, "secp256k1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, "brainpoolP256r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1, "secp224r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1, "secp224k1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1, "secp192r1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1, "secp192k1" }, { MBEDTLS_SSL_IANA_TLS_GROUP_X25519, "x25519" }, { MBEDTLS_SSL_IANA_TLS_GROUP_X448, "x448" }, { 0, NULL }, }; const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id) { for (int i = 0; tls_id_curve_name_table[i].tls_id != 0; i++) { if (tls_id_curve_name_table[i].tls_id == tls_id) { return tls_id_curve_name_table[i].name; } } return NULL; } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert, const mbedtls_ssl_ciphersuite_t *ciphersuite, int cert_endpoint, uint32_t *flags) { int ret = 0; unsigned int usage = 0; const char *ext_oid; size_t ext_len; if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) { /* Server part of the key exchange */ switch (ciphersuite->key_exchange) { case MBEDTLS_KEY_EXCHANGE_RSA: case MBEDTLS_KEY_EXCHANGE_RSA_PSK: usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; break; case MBEDTLS_KEY_EXCHANGE_DHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; break; case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: usage = MBEDTLS_X509_KU_KEY_AGREEMENT; break; /* Don't use default: we want warnings when adding new values */ case MBEDTLS_KEY_EXCHANGE_NONE: case MBEDTLS_KEY_EXCHANGE_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_ECJPAKE: usage = 0; } } else { /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; } if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) { *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; ret = -1; } if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) { ext_oid = MBEDTLS_OID_SERVER_AUTH; ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH); } else { ext_oid = MBEDTLS_OID_CLIENT_AUTH; ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH); } if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) { *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; ret = -1; } return ret; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, const mbedtls_md_type_t md, unsigned char *dst, size_t dst_len, size_t *olen) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_hash_operation_t *hash_operation_to_clone; psa_hash_operation_t hash_operation = psa_hash_operation_init(); *olen = 0; switch (md) { #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: hash_operation_to_clone = &ssl->handshake->fin_sha384_psa; break; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: hash_operation_to_clone = &ssl->handshake->fin_sha256_psa; break; #endif default: goto exit; } status = psa_hash_clone(hash_operation_to_clone, &hash_operation); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&hash_operation, dst, dst_len, olen); if (status != PSA_SUCCESS) { goto exit; } exit: #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ssl; #endif return PSA_TO_MBEDTLS_ERR(status); } #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *olen) { int ret; mbedtls_md_context_t sha384; if (dst_len < 48) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } mbedtls_md_init(&sha384); ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384); if (ret != 0) { goto exit; } if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); goto exit; } *olen = 48; exit: mbedtls_md_free(&sha384); return ret; } #endif /* MBEDTLS_MD_CAN_SHA384 */ #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *olen) { int ret; mbedtls_md_context_t sha256; if (dst_len < 32) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } mbedtls_md_init(&sha256); ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256); if (ret != 0) { goto exit; } if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); goto exit; } *olen = 32; exit: mbedtls_md_free(&sha256); return ret; } #endif /* MBEDTLS_MD_CAN_SHA256 */ int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl, const mbedtls_md_type_t md, unsigned char *dst, size_t dst_len, size_t *olen) { switch (md) { #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen); #endif /* MBEDTLS_MD_CAN_SHA384*/ #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen); #endif /* MBEDTLS_MD_CAN_SHA256*/ default: #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ssl; (void) dst; (void) dst_len; (void) olen; #endif break; } return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* mbedtls_ssl_parse_sig_alg_ext() * * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` * value (TLS 1.3 RFC8446): * enum { * .... * ecdsa_secp256r1_sha256( 0x0403 ), * ecdsa_secp384r1_sha384( 0x0503 ), * ecdsa_secp521r1_sha512( 0x0603 ), * .... * } SignatureScheme; * * struct { * SignatureScheme supported_signature_algorithms<2..2^16-2>; * } SignatureSchemeList; * * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` * value (TLS 1.2 RFC5246): * enum { * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), * sha512(6), (255) * } HashAlgorithm; * * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } * SignatureAlgorithm; * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * SignatureAndHashAlgorithm * supported_signature_algorithms<2..2^16-2>; * * The TLS 1.3 signature algorithm extension was defined to be a compatible * generalization of the TLS 1.2 signature algorithm extension. * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by * `SignatureScheme` field of TLS 1.3 * */ int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t supported_sig_algs_len = 0; const unsigned char *supported_sig_algs_end; uint16_t sig_alg; uint32_t common_idx = 0; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; memset(ssl->handshake->received_sig_algs, 0, sizeof(ssl->handshake->received_sig_algs)); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len); supported_sig_algs_end = p + supported_sig_algs_len; while (p < supported_sig_algs_end) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2); sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s", sig_alg, mbedtls_ssl_sig_alg_to_str(sig_alg))); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 && (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) && mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) { continue; } #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s", mbedtls_ssl_sig_alg_to_str(sig_alg))); if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) { ssl->handshake->received_sig_algs[common_idx] = sig_alg; common_idx += 1; } } /* Check that we consumed all the message. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("Signature algorithms extension length misaligned")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (common_idx == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE; return 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_USE_PSA_CRYPTO) static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation, mbedtls_svc_key_id_t key, psa_algorithm_t alg, const unsigned char *raw_psk, size_t raw_psk_length, const unsigned char *seed, size_t seed_length, const unsigned char *label, size_t label_length, const unsigned char *other_secret, size_t other_secret_length, size_t capacity) { psa_status_t status; status = psa_key_derivation_setup(derivation, alg); if (status != PSA_SUCCESS) { return status; } if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) { status = psa_key_derivation_input_bytes(derivation, PSA_KEY_DERIVATION_INPUT_SEED, seed, seed_length); if (status != PSA_SUCCESS) { return status; } if (other_secret != NULL) { status = psa_key_derivation_input_bytes(derivation, PSA_KEY_DERIVATION_INPUT_OTHER_SECRET, other_secret, other_secret_length); if (status != PSA_SUCCESS) { return status; } } if (mbedtls_svc_key_id_is_null(key)) { status = psa_key_derivation_input_bytes( derivation, PSA_KEY_DERIVATION_INPUT_SECRET, raw_psk, raw_psk_length); } else { status = psa_key_derivation_input_key( derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key); } if (status != PSA_SUCCESS) { return status; } status = psa_key_derivation_input_bytes(derivation, PSA_KEY_DERIVATION_INPUT_LABEL, label, label_length); if (status != PSA_SUCCESS) { return status; } } else { return PSA_ERROR_NOT_SUPPORTED; } status = psa_key_derivation_set_capacity(derivation, capacity); if (status != PSA_SUCCESS) { return status; } return PSA_SUCCESS; } #if defined(PSA_WANT_ALG_SHA_384) || \ defined(PSA_WANT_ALG_SHA_256) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_generic(mbedtls_md_type_t md_type, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { psa_status_t status; psa_algorithm_t alg; mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; if (md_type == MBEDTLS_MD_SHA384) { alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); } else { alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); } /* Normally a "secret" should be long enough to be impossible to * find by brute force, and in particular should not be empty. But * this PRF is also used to derive an IV, in particular in EAP-TLS, * and for this use case it makes sense to have a 0-length "secret". * Since the key API doesn't allow importing a key of length 0, * keep master_key=0, which setup_psa_key_derivation() understands * to mean a 0-length "secret" input. */ if (slen != 0) { psa_key_attributes_t key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE); status = psa_import_key(&key_attributes, secret, slen, &master_key); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } } status = setup_psa_key_derivation(&derivation, master_key, alg, NULL, 0, random, rlen, (unsigned char const *) label, (size_t) strlen(label), NULL, 0, dlen); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); psa_destroy_key(master_key); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); psa_destroy_key(master_key); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_abort(&derivation); if (status != PSA_SUCCESS) { psa_destroy_key(master_key); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } if (!mbedtls_svc_key_id_is_null(master_key)) { status = psa_destroy_key(master_key); } if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } return 0; } #endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */ #else /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_C) && \ (defined(MBEDTLS_MD_CAN_SHA256) || \ defined(MBEDTLS_MD_CAN_SHA384)) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_generic(mbedtls_md_type_t md_type, const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { size_t nb; size_t i, j, k, md_len; unsigned char *tmp; size_t tmp_len = 0; unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; const mbedtls_md_info_t *md_info; mbedtls_md_context_t md_ctx; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_init(&md_ctx); if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } md_len = mbedtls_md_get_size(md_info); tmp_len = md_len + strlen(label) + rlen; tmp = mbedtls_calloc(1, tmp_len); if (tmp == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } nb = strlen(label); memcpy(tmp + md_len, label, nb); memcpy(tmp + md_len + nb, random, rlen); nb += rlen; /* * Compute P_(secret, label + random)[0..dlen] */ if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) { goto exit; } ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&md_ctx, tmp); if (ret != 0) { goto exit; } for (i = 0; i < dlen; i += md_len) { ret = mbedtls_md_hmac_reset(&md_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&md_ctx, h_i); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_reset(&md_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len); if (ret != 0) { goto exit; } ret = mbedtls_md_hmac_finish(&md_ctx, tmp); if (ret != 0) { goto exit; } k = (i + md_len > dlen) ? dlen % md_len : md_len; for (j = 0; j < k; j++) { dstbuf[i + j] = h_i[j]; } } exit: mbedtls_md_free(&md_ctx); if (tmp != NULL) { mbedtls_platform_zeroize(tmp, tmp_len); } mbedtls_platform_zeroize(h_i, sizeof(h_i)); mbedtls_free(tmp); return ret; } #endif /* MBEDTLS_MD_C && ( MBEDTLS_MD_CAN_SHA256 || MBEDTLS_MD_CAN_SHA384 ) */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha256(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen, label, random, rlen, dstbuf, dlen); } #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_CHECK_RETURN_CRITICAL static int tls_prf_sha384(const unsigned char *secret, size_t slen, const char *label, const unsigned char *random, size_t rlen, unsigned char *dstbuf, size_t dlen) { return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen, label, random, rlen, dstbuf, dlen); } #endif /* MBEDTLS_MD_CAN_SHA384*/ /* * Set appropriate PRF function and other SSL / TLS1.2 functions * * Inputs: * - hash associated with the ciphersuite (only used by TLS 1.2) * * Outputs: * - the tls_prf, calc_verify and calc_finished members of handshake structure */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake, mbedtls_md_type_t hash) { #if defined(MBEDTLS_MD_CAN_SHA384) if (hash == MBEDTLS_MD_SHA384) { handshake->tls_prf = tls_prf_sha384; handshake->calc_verify = ssl_calc_verify_tls_sha384; handshake->calc_finished = ssl_calc_finished_tls_sha384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) { (void) hash; handshake->tls_prf = tls_prf_sha256; handshake->calc_verify = ssl_calc_verify_tls_sha256; handshake->calc_finished = ssl_calc_finished_tls_sha256; } #else { (void) handshake; (void) hash; return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif return 0; } /* * Compute master secret if needed * * Parameters: * [in/out] handshake * [in] resume, premaster, extended_ms, calc_verify, tls_prf * (PSA-PSK) ciphersuite_info, psk_opaque * [out] premaster (cleared) * [out] master * [in] ssl: optionally used for debugging, EMS and PSA-PSK * debug: conf->f_dbg, conf->p_dbg * EMS: passed to calc_verify (debug + session_negotiate) * PSA-PSA: conf */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake, unsigned char *master, const mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* cf. RFC 5246, Section 8.1: * "The master secret is always exactly 48 bytes in length." */ size_t const master_secret_len = 48; #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) unsigned char session_hash[48]; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ /* The label for the KDF used for key expansion. * This is either "master secret" or "extended master secret" * depending on whether the Extended Master Secret extension * is used. */ char const *lbl = "master secret"; /* The seed for the KDF used for key expansion. * - If the Extended Master Secret extension is not used, * this is ClientHello.Random + ServerHello.Random * (see Sect. 8.1 in RFC 5246). * - If the Extended Master Secret extension is used, * this is the transcript of the handshake so far. * (see Sect. 4 in RFC 7627). */ unsigned char const *seed = handshake->randbytes; size_t seed_len = 64; #if !defined(MBEDTLS_DEBUG_C) && \ !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; #endif if (handshake->resume != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)")); return 0; } #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { lbl = "extended master secret"; seed = session_hash; ret = handshake->calc_verify(ssl, session_hash, &seed_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret); } MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret", session_hash, seed_len); } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) { /* Perform PSK-to-MS expansion in a single step. */ psa_status_t status; psa_algorithm_t alg; mbedtls_svc_key_id_t psk; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; mbedtls_md_type_t hash_alg = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion")); psk = mbedtls_ssl_get_opaque_psk(ssl); if (hash_alg == MBEDTLS_MD_SHA384) { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); } else { alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); } size_t other_secret_len = 0; unsigned char *other_secret = NULL; switch (handshake->ciphersuite_info->key_exchange) { /* Provide other secret. * Other secret is stored in premaster, where first 2 bytes hold the * length of the other key. */ case MBEDTLS_KEY_EXCHANGE_RSA_PSK: /* For RSA-PSK other key length is always 48 bytes. */ other_secret_len = 48; other_secret = handshake->premaster + 2; break; case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: case MBEDTLS_KEY_EXCHANGE_DHE_PSK: other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0); other_secret = handshake->premaster + 2; break; default: break; } status = setup_psa_key_derivation(&derivation, psk, alg, ssl->conf->psk, ssl->conf->psk_len, seed, seed_len, (unsigned char const *) lbl, (size_t) strlen(lbl), other_secret, other_secret_len, master_secret_len); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_output_bytes(&derivation, master, master_secret_len); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_abort(&derivation); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } } else #endif { #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { psa_status_t status; psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE")); handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE; status = psa_key_derivation_setup(&derivation, alg); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_set_capacity(&derivation, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx, &derivation); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_output_bytes(&derivation, handshake->premaster, handshake->pmslen); if (status != PSA_SUCCESS) { psa_key_derivation_abort(&derivation); return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } status = psa_key_derivation_abort(&derivation); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } } #endif ret = handshake->tls_prf(handshake->premaster, handshake->pmslen, lbl, seed, seed_len, master, master_secret_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret", handshake->premaster, handshake->pmslen); mbedtls_platform_zeroize(handshake->premaster, sizeof(handshake->premaster)); } return 0; } int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys")); /* Set PRF, calc_verify and calc_finished function pointers */ ret = ssl_set_handshake_prfs(ssl->handshake, (mbedtls_md_type_t) ciphersuite_info->mac); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret); return ret; } /* Compute master secret if needed */ ret = ssl_compute_master(ssl->handshake, ssl->session_negotiate->master, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret); return ret; } /* Swap the client and server random values: * - MS derivation wanted client+server (RFC 5246 8.1) * - key derivation wants server+client (RFC 5246 6.3) */ { unsigned char tmp[64]; memcpy(tmp, ssl->handshake->randbytes, 64); memcpy(ssl->handshake->randbytes, tmp + 32, 32); memcpy(ssl->handshake->randbytes + 32, tmp, 32); mbedtls_platform_zeroize(tmp, sizeof(tmp)); } /* Populate transform structure */ ret = ssl_tls12_populate_transform(ssl->transform_negotiate, ssl->session_negotiate->ciphersuite, ssl->session_negotiate->master, #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl->session_negotiate->encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ssl->handshake->tls_prf, ssl->handshake->randbytes, ssl->tls_version, ssl->conf->endpoint, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret); return ret; } /* We no longer need Server/ClientHello.random values */ mbedtls_platform_zeroize(ssl->handshake->randbytes, sizeof(ssl->handshake->randbytes)); MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys")); return 0; } int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md) { switch (md) { #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_SSL_HASH_SHA384: ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; break; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_SSL_HASH_SHA256: ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; break; #endif default: return -1; } #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ssl; #endif return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) static int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl, const psa_hash_operation_t *hs_op, size_t buffer_size, unsigned char *hash, size_t *hlen) { psa_status_t status; psa_hash_operation_t cloned_op = psa_hash_operation_init(); #if !defined(MBEDTLS_DEBUG_C) (void) ssl; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify")); status = psa_hash_clone(hs_op, &cloned_op); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&cloned_op, hash, buffer_size, hlen); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen); MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify")); exit: psa_hash_abort(&cloned_op); return mbedtls_md_error_from_psa(status); } #else static int ssl_calc_verify_tls_legacy(const mbedtls_ssl_context *ssl, const mbedtls_md_context_t *hs_ctx, unsigned char *hash, size_t *hlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_context_t cloned_ctx; mbedtls_md_init(&cloned_ctx); #if !defined(MBEDTLS_DEBUG_C) (void) ssl; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify")); ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&cloned_ctx, hs_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_finish(&cloned_ctx, hash); if (ret != 0) { goto exit; } *hlen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(hs_ctx)); MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen); MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify")); exit: mbedtls_md_free(&cloned_ctx); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_MD_CAN_SHA256) int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hlen) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha256_psa, 32, hash, hlen); #else return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha256, hash, hlen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_MD_CAN_SHA256 */ #if defined(MBEDTLS_MD_CAN_SHA384) int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hlen) { #if defined(MBEDTLS_USE_PSA_CRYPTO) return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha384_psa, 48, hash, hlen); #else return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha384, hash, hlen); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_MD_CAN_SHA384 */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex) { unsigned char *p = ssl->handshake->premaster; unsigned char *end = p + sizeof(ssl->handshake->premaster); const unsigned char *psk = NULL; size_t psk_len = 0; int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len); if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) { /* * This should never happen because the existence of a PSK is always * checked before calling this function. * * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with * the shared secret without PSK. */ if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } /* * PMS = struct { * opaque other_secret<0..2^16-1>; * opaque psk<0..2^16-1>; * }; * with "other_secret" depending on the particular key exchange */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) { if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); p += 2; if (end < p || (size_t) (end - p) < psk_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memset(p, 0, psk_len); p += psk_len; } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { /* * other_secret already set by the ClientKeyExchange message, * and is 48 bytes long */ if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } *p++ = 0; *p++ = 48; p += 48; } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Write length only when we know the actual value */ if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, p + 2, (size_t) (end - (p + 2)), &len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(len, p, 0); p += 2 + len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t zlen; if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen, p + 2, (size_t) (end - (p + 2)), ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(zlen, p, 0); p += 2 + zlen; MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* opaque psk<0..2^16-1>; */ if (end - p < 2) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT16_BE(psk_len, p, 0); p += 2; if (end < p || (size_t) (end - p) < psk_len) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } memcpy(p, psk, psk_len); p += psk_len; ssl->handshake->pmslen = (size_t) (p - ssl->handshake->premaster); return 0; } #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_request(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_PROTO_DTLS) int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl) { /* If renegotiation is not enforced, retransmit until we would reach max * timeout if we were using the usual handshake doubling scheme */ if (ssl->conf->renego_max_records < 0) { uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; unsigned char doublings = 1; while (ratio != 0) { ++doublings; ratio >>= 1; } if (++ssl->renego_records_seen > doublings) { MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request")); return 0; } } return ssl_write_hello_request(ssl); } #endif #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ /* * Handshake functions */ #if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* No certificate support -> dummy functions */ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* Some certificate support -> implement write and parse */ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t i, n; const mbedtls_x509_crt *crt; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); ssl->state++; return 0; } #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { if (ssl->handshake->client_auth == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate")); ssl->state++; return 0; } } #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { if (mbedtls_ssl_own_cert(ssl) == NULL) { /* Should never happen because we shouldn't have picked the * ciphersuite if we don't have a certificate. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } #endif MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl)); /* * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 6 length of all certs * 7 . 9 length of cert. 1 * 10 . n-1 peer certificate * n . n+2 length of cert. 2 * n+3 . ... upper level cert, etc. */ i = 7; crt = mbedtls_ssl_own_cert(ssl); while (crt != NULL) { n = crt->raw.len; if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) { MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN)); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl->out_msg[i] = MBEDTLS_BYTE_2(n); ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n); ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n); i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n); i += n; crt = crt->next; } ssl->out_msg[4] = MBEDTLS_BYTE_2(i - 7); ssl->out_msg[5] = MBEDTLS_BYTE_1(i - 7); ssl->out_msg[6] = MBEDTLS_BYTE_0(i - 7); ssl->out_msglen = i; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); return ret; } #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, unsigned char *crt_buf, size_t crt_buf_len) { mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; if (peer_crt == NULL) { return -1; } if (peer_crt->raw.len != crt_buf_len) { return -1; } return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len); } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl, unsigned char *crt_buf, size_t crt_buf_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char const * const peer_cert_digest = ssl->session->peer_cert_digest; mbedtls_md_type_t const peer_cert_digest_type = ssl->session->peer_cert_digest_type; mbedtls_md_info_t const * const digest_info = mbedtls_md_info_from_type(peer_cert_digest_type); unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; size_t digest_len; if (peer_cert_digest == NULL || digest_info == NULL) { return -1; } digest_len = mbedtls_md_get_size(digest_info); if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) { return -1; } ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest); if (ret != 0) { return -1; } return memcmp(tmp_digest, peer_cert_digest, digest_len); } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ /* * Once the certificate message is read, parse it into a cert chain and * perform basic checks, but leave actual verification to the caller */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl, mbedtls_x509_crt *chain) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) int crt_cnt = 0; #endif size_t i, n; uint8_t alert; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } i = mbedtls_ssl_hs_hdr_len(ssl); /* * Same message structure as in mbedtls_ssl_write_certificate() */ n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1); if (ssl->in_msg[i] != 0 || ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ i += 3; /* Iterate through and parse the CRTs in the provided chain. */ while (i < ssl->in_hslen) { /* Check that there's room for the next CRT's length fields. */ if (i + 3 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* In theory, the CRT can be up to 2**24 Bytes, but we don't support * anything beyond 2**16 ~ 64K. */ if (ssl->in_msg[i] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } /* Read length of the next CRT in the chain. */ n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1); i += 3; if (n < 128 || i + n > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check if we're handling the first CRT in the chain. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) if (crt_cnt++ == 0 && ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { /* During client-side renegotiation, check that the server's * end-CRTs hasn't changed compared to the initial handshake, * mitigating the triple handshake attack. On success, reuse * the original end-CRT instead of parsing it again. */ MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation")); if (ssl_check_peer_crt_unchanged(ssl, &ssl->in_msg[i], n) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } /* Now we can safely free the original chain. */ ssl_clear_peer_cert(ssl->session); } #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ /* Parse the next certificate in the chain. */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n); #else /* If we don't need to store the CRT chain permanently, parse * it in-place from the input buffer instead of making a copy. */ ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n); #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ switch (ret) { case 0: /*ok*/ case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: /* Ignore certificate with an unknown algorithm: maybe a prior certificate was already trusted. */ break; case MBEDTLS_ERR_X509_ALLOC_FAILED: alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; goto crt_parse_der_failed; case MBEDTLS_ERR_X509_UNKNOWN_VERSION: alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; goto crt_parse_der_failed; default: alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; crt_parse_der_failed: mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; } i += n; } MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain); return 0; } #if defined(MBEDTLS_SSL_SRV_C) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl) { if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { return -1; } if (ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len(ssl) && ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); return 0; } return -1; } #endif /* MBEDTLS_SSL_SRV_C */ /* Check if a certificate message is expected. * Return either * - SSL_CERTIFICATE_EXPECTED, or * - SSL_CERTIFICATE_SKIP * indicating whether a Certificate message is expected or not. */ #define SSL_CERTIFICATE_EXPECTED 0 #define SSL_CERTIFICATE_SKIP 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl, int authmode) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) { return SSL_CERTIFICATE_SKIP; } #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { return SSL_CERTIFICATE_SKIP; } if (authmode == MBEDTLS_SSL_VERIFY_NONE) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; return SSL_CERTIFICATE_SKIP; } } #else ((void) authmode); #endif /* MBEDTLS_SSL_SRV_C */ return SSL_CERTIFICATE_EXPECTED; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl, int authmode, mbedtls_x509_crt *chain, void *rs_ctx) { int ret = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; int have_ca_chain = 0; int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); void *p_vrfy; if (authmode == MBEDTLS_SSL_VERIFY_NONE) { return 0; } if (ssl->f_vrfy != NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback")); f_vrfy = ssl->f_vrfy; p_vrfy = ssl->p_vrfy; } else { MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback")); f_vrfy = ssl->conf->f_vrfy; p_vrfy = ssl->conf->p_vrfy; } /* * Main check: verify certificate */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) if (ssl->conf->f_ca_cb != NULL) { ((void) rs_ctx); have_ca_chain = 1; MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification")); ret = mbedtls_x509_crt_verify_with_ca_cb( chain, ssl->conf->f_ca_cb, ssl->conf->p_ca_cb, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, f_vrfy, p_vrfy); } else #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ { mbedtls_x509_crt *ca_chain; mbedtls_x509_crl *ca_crl; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_ca_chain != NULL) { ca_chain = ssl->handshake->sni_ca_chain; ca_crl = ssl->handshake->sni_ca_crl; } else #endif { ca_chain = ssl->conf->ca_chain; ca_crl = ssl->conf->ca_crl; } if (ca_chain != NULL) { have_ca_chain = 1; } ret = mbedtls_x509_crt_verify_restartable( chain, ca_chain, ca_crl, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, f_vrfy, p_vrfy, rs_ctx); } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif /* * Secondary checks: always done, but change 'ret' only if it was 0 */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) { const mbedtls_pk_context *pk = &chain->pk; /* If certificate uses an EC key, make sure the curve is OK. * This is a public key, so it can't be opaque, so can_do() is a good * enough check to ensure pk_ec() is safe to use here. */ if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) { /* and in the unlikely case the above assumption no longer holds * we are making sure that pk_ec() here does not return a NULL */ mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk); if (grp_id == MBEDTLS_ECP_DP_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid group ID")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)")); if (ret == 0) { ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } } } } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ if (mbedtls_ssl_check_cert_usage(chain, ciphersuite_info, !ssl->conf->endpoint, &ssl->session_negotiate->verify_result) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); if (ret == 0) { ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } } /* mbedtls_x509_crt_verify_with_profile is supposed to report a * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, * with details encoded in the verification flags. All other kinds * of error codes, including those from the user provided f_vrfy * functions, are treated as fatal and lead to a failure of * ssl_parse_certificate even if verification was optional. */ if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) { ret = 0; } if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; } if (ret != 0) { uint8_t alert; /* The certificate may have been rejected for several reasons. Pick one and send the corresponding alert. Which alert to send may be a subject of debate in some cases. */ if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) { alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) { alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) { alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; } else { alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; } mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert); } #if defined(MBEDTLS_DEBUG_C) if (ssl->session_negotiate->verify_result != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", (unsigned int) ssl->session_negotiate->verify_result)); } else { MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); } #endif /* MBEDTLS_DEBUG_C */ return ret; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl, unsigned char *start, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Remember digest of the peer's end-CRT. */ ssl->session_negotiate->peer_cert_digest = mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN); if (ssl->session_negotiate->peer_cert_digest == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed", MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } ret = mbedtls_md(mbedtls_md_info_from_type( MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE), start, len, ssl->session_negotiate->peer_cert_digest); ssl->session_negotiate->peer_cert_digest_type = MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; ssl->session_negotiate->peer_cert_digest_len = MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl, unsigned char *start, size_t len) { unsigned char *end = start + len; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* Make a copy of the peer's raw public key. */ mbedtls_pk_init(&ssl->handshake->peer_pubkey); ret = mbedtls_pk_parse_subpubkey(&start, end, &ssl->handshake->peer_pubkey); if (ret != 0) { /* We should have parsed the public key before. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl) { int ret = 0; int crt_expected; #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ? ssl->handshake->sni_authmode : ssl->conf->authmode; #else const int authmode = ssl->conf->authmode; #endif void *rs_ctx = NULL; mbedtls_x509_crt *chain = NULL; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); crt_expected = ssl_parse_certificate_coordinate(ssl, authmode); if (crt_expected == SSL_CERTIFICATE_SKIP) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate")); goto exit; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) { chain = ssl->handshake->ecrs_peer_cert; ssl->handshake->ecrs_peer_cert = NULL; goto crt_verify; } #endif if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { /* mbedtls_ssl_read_record may have sent an alert already. We let it decide whether to alert. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); goto exit; } #if defined(MBEDTLS_SSL_SRV_C) if (ssl_srv_check_client_no_crt_notification(ssl) == 0) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) { ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; } goto exit; } #endif /* MBEDTLS_SSL_SRV_C */ /* Clear existing peer CRT structure in case we tried to * reuse a session but it failed, and allocate a new one. */ ssl_clear_peer_cert(ssl->session_negotiate); chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (chain == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", sizeof(mbedtls_x509_crt))); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto exit; } mbedtls_x509_crt_init(chain); ret = ssl_parse_certificate_chain(ssl, chain); if (ret != 0) { goto exit; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; } crt_verify: if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx; } #endif ret = ssl_parse_certificate_verify(ssl, authmode, chain, rs_ctx); if (ret != 0) { goto exit; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) { unsigned char *crt_start, *pk_start; size_t crt_len, pk_len; /* We parse the CRT chain without copying, so * these pointers point into the input buffer, * and are hence still valid after freeing the * CRT chain. */ crt_start = chain->raw.p; crt_len = chain->raw.len; pk_start = chain->pk_raw.p; pk_len = chain->pk_raw.len; /* Free the CRT structures before computing * digest and copying the peer's public key. */ mbedtls_x509_crt_free(chain); mbedtls_free(chain); chain = NULL; ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len); if (ret != 0) { goto exit; } ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len); if (ret != 0) { goto exit; } } #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Pass ownership to session structure. */ ssl->session_negotiate->peer_cert = chain; chain = NULL; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); exit: if (ret == 0) { ssl->state++; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) { ssl->handshake->ecrs_peer_cert = chain; chain = NULL; } #endif if (chain != NULL) { mbedtls_x509_crt_free(chain); mbedtls_free(chain); } return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ static int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx, unsigned char *padbuf, size_t hlen, unsigned char *buf, int from) { unsigned int len = 12; const char *sender; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status; psa_hash_operation_t *hs_op = ctx; psa_hash_operation_t cloned_op = PSA_HASH_OPERATION_INIT; size_t hash_size; #else int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_context_t *hs_ctx = ctx; mbedtls_md_context_t cloned_ctx; mbedtls_md_init(&cloned_ctx); #endif mbedtls_ssl_session *session = ssl->session_negotiate; if (!session) { session = ssl->session; } sender = (from == MBEDTLS_SSL_IS_CLIENT) ? "client finished" : "server finished"; #if defined(MBEDTLS_USE_PSA_CRYPTO) MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls")); status = psa_hash_clone(hs_op, &cloned_op); if (status != PSA_SUCCESS) { goto exit; } status = psa_hash_finish(&cloned_op, padbuf, hlen, &hash_size); if (status != PSA_SUCCESS) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, hlen); #else MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls")); ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0); if (ret != 0) { goto exit; } ret = mbedtls_md_clone(&cloned_ctx, hs_ctx); if (ret != 0) { goto exit; } ret = mbedtls_md_finish(&cloned_ctx, padbuf); if (ret != 0) { goto exit; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_BUF(4, "finished output", padbuf, hlen); /* * TLSv1.2: * hash = PRF( master, finished_label, * Hash( handshake ) )[0.11] */ ssl->handshake->tls_prf(session->master, 48, sender, padbuf, hlen, buf, len); MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len); mbedtls_platform_zeroize(padbuf, hlen); MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished")); exit: #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_hash_abort(&cloned_op); return mbedtls_md_error_from_psa(status); #else mbedtls_md_free(&cloned_ctx); return ret; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #if defined(MBEDTLS_MD_CAN_SHA256) static int ssl_calc_finished_tls_sha256( mbedtls_ssl_context *ssl, unsigned char *buf, int from) { unsigned char padbuf[32]; return ssl_calc_finished_tls_generic(ssl, #if defined(MBEDTLS_USE_PSA_CRYPTO) &ssl->handshake->fin_sha256_psa, #else &ssl->handshake->fin_sha256, #endif padbuf, sizeof(padbuf), buf, from); } #endif /* MBEDTLS_MD_CAN_SHA256*/ #if defined(MBEDTLS_MD_CAN_SHA384) static int ssl_calc_finished_tls_sha384( mbedtls_ssl_context *ssl, unsigned char *buf, int from) { unsigned char padbuf[48]; return ssl_calc_finished_tls_generic(ssl, #if defined(MBEDTLS_USE_PSA_CRYPTO) &ssl->handshake->fin_sha384_psa, #else &ssl->handshake->fin_sha384, #endif padbuf, sizeof(padbuf), buf, from); } #endif /* MBEDTLS_MD_CAN_SHA384*/ void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free")); /* * Free our handshake params */ mbedtls_ssl_handshake_free(ssl); mbedtls_free(ssl->handshake); ssl->handshake = NULL; /* * Free the previous transform and switch in the current one */ if (ssl->transform) { mbedtls_ssl_transform_free(ssl->transform); mbedtls_free(ssl->transform); } ssl->transform = ssl->transform_negotiate; ssl->transform_negotiate = NULL; MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free")); } void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl) { int resume = ssl->handshake->resume; MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; ssl->renego_records_seen = 0; } #endif /* * Free the previous session and switch in the current one */ if (ssl->session) { #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) /* RFC 7366 3.1: keep the EtM state */ ssl->session_negotiate->encrypt_then_mac = ssl->session->encrypt_then_mac; #endif mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); } ssl->session = ssl->session_negotiate; ssl->session_negotiate = NULL; /* * Add cache entry */ if (ssl->conf->f_set_cache != NULL && ssl->session->id_len != 0 && resume == 0) { if (ssl->conf->f_set_cache(ssl->conf->p_cache, ssl->session->id, ssl->session->id_len, ssl->session) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session")); } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->flight != NULL) { /* Cancel handshake timer */ mbedtls_ssl_set_timer(ssl, 0); /* Keep last flight around in case we need to resend it: * we need the handshake and transform structures for that */ MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform")); } else #endif mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl); ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); } int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl) { int ret; unsigned int hash_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished")); mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate); ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); } /* * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites * may define some other value. Currently (early 2016), no defined * ciphersuite does this (and this is unlikely to change as activity has * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. */ hash_len = 12; #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->verify_data_len = hash_len; memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len); #endif ssl->out_msglen = 4 + hash_len; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; /* * In case of session resuming, invert the client and server * ChangeCipherSpec messages order. */ if (ssl->handshake->resume != 0) { #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; } #endif #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; } #endif } else { ssl->state++; } /* * Switch to our negotiated transform and session parameters for outbound * data. */ MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data")); #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { unsigned char i; /* Remember current epoch settings for resending */ ssl->handshake->alt_transform_out = ssl->transform_out; memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, sizeof(ssl->handshake->alt_out_ctr)); /* Set sequence_number to zero */ memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2); /* Increment epoch */ for (i = 2; i > 0; i--) { if (++ssl->cur_out_ctr[i - 1] != 0) { break; } } /* The loop goes to its end iff the counter is wrapping */ if (i == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap")); return MBEDTLS_ERR_SSL_COUNTER_WRAPPING; } } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr)); ssl->transform_out = ssl->transform_negotiate; ssl->session_out = ssl->session_negotiate; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_send_flight_completed(ssl); } #endif if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished")); return 0; } #define SSL_MAX_HASH_LEN 12 int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned int hash_len = 12; unsigned char buf[SSL_MAX_HASH_LEN]; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished")); ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret); } if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); goto exit; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; goto exit; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; goto exit; } if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); ret = MBEDTLS_ERR_SSL_DECODE_ERROR; goto exit; } if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), buf, hash_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; goto exit; } #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->verify_data_len = hash_len; memcpy(ssl->peer_verify_data, buf, hash_len); #endif if (ssl->handshake->resume != 0) { #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; } #endif #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; } #endif } else { ssl->state++; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_recv_flight_completed(ssl); } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished")); exit: mbedtls_platform_zeroize(buf, hash_len); return ret; } #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /* * Helper to get TLS 1.2 PRF from ciphersuite * (Duplicates bits of logic from ssl_set_handshake_prfs().) */ static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id) { const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id); #if defined(MBEDTLS_MD_CAN_SHA384) if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) { return tls_prf_sha384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) { if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) { return tls_prf_sha256; } } #endif #if !defined(MBEDTLS_MD_CAN_SHA384) && \ !defined(MBEDTLS_MD_CAN_SHA256) (void) ciphersuite_info; #endif return NULL; } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf) { ((void) tls_prf); #if defined(MBEDTLS_MD_CAN_SHA384) if (tls_prf == tls_prf_sha384) { return MBEDTLS_SSL_TLS_PRF_SHA384; } else #endif #if defined(MBEDTLS_MD_CAN_SHA256) if (tls_prf == tls_prf_sha256) { return MBEDTLS_SSL_TLS_PRF_SHA256; } else #endif return MBEDTLS_SSL_TLS_PRF_NONE; } /* * Populate a transform structure with session keys and all the other * necessary information. * * Parameters: * - [in/out]: transform: structure to populate * [in] must be just initialised with mbedtls_ssl_transform_init() * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() * - [in] ciphersuite * - [in] master * - [in] encrypt_then_mac * - [in] tls_prf: pointer to PRF to use for key derivation * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random * - [in] tls_version: TLS version * - [in] endpoint: client or server * - [in] ssl: used for: * - ssl->conf->{f,p}_export_keys * [in] optionally used for: * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, int ciphersuite, const unsigned char master[48], #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) int encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ssl_tls_prf_t tls_prf, const unsigned char randbytes[64], mbedtls_ssl_protocol_version tls_version, unsigned endpoint, const mbedtls_ssl_context *ssl) { int ret = 0; unsigned char keyblk[256]; unsigned char *key1; unsigned char *key2; unsigned char *mac_enc; unsigned char *mac_dec; size_t mac_key_len = 0; size_t iv_copy_len; size_t keylen; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; mbedtls_ssl_mode_t ssl_mode; #if !defined(MBEDTLS_USE_PSA_CRYPTO) const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_type_t key_type; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; psa_algorithm_t mac_alg = 0; size_t key_bits; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; #endif /* * Some data just needs copying into the structure */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) transform->encrypt_then_mac = encrypt_then_mac; #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ transform->tls_version = tls_version; #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes)); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_3) if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) { /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform * generation separate. This should never happen. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ /* * Get various info structures */ ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); if (ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite( #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) encrypt_then_mac, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ ciphersuite_info); if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { transform->taglen = ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, transform->taglen, &alg, &key_type, &key_bits)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret); goto end; } #else cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) ciphersuite_info->cipher); if (cipher_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", ciphersuite_info->cipher)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) mac_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); if (mac_alg == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md_psa_alg_from_type for %u not found", (unsigned) ciphersuite_info->mac)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #else md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ciphersuite_info->mac); if (md_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found", (unsigned) ciphersuite_info->mac)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) /* Copy own and peer's CID if the use of the CID * extension has been negotiated. */ if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) { MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform")); transform->in_cid_len = ssl->own_cid_len; memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len); MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid, transform->in_cid_len); transform->out_cid_len = ssl->handshake->peer_cid_len; memcpy(transform->out_cid, ssl->handshake->peer_cid, ssl->handshake->peer_cid_len); MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid, transform->out_cid_len); } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* * Compute key block using the PRF */ ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "prf", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s", mbedtls_ssl_get_ciphersuite_name(ciphersuite))); MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48); MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64); MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256); /* * Determine the appropriate key, IV and MAC length. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) keylen = PSA_BITS_TO_BYTES(key_bits); #else keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; #endif #if defined(MBEDTLS_SSL_HAVE_AEAD) if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) { size_t explicit_ivlen; transform->maclen = 0; mac_key_len = 0; /* All modes haves 96-bit IVs, but the length of the static parts vary * with mode and version: * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes * (to be concatenated with a dynamically chosen IV of 8 Bytes) * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record * sequence number). */ transform->ivlen = 12; int is_chachapoly = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20); #else is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CHACHAPOLY); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (is_chachapoly) { transform->fixed_ivlen = 12; } else { transform->fixed_ivlen = 4; } /* Minimum length of encrypted record */ explicit_ivlen = transform->ivlen - transform->fixed_ivlen; transform->minlen = explicit_ivlen + transform->taglen; } else #endif /* MBEDTLS_SSL_HAVE_AEAD */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_STREAM || ssl_mode == MBEDTLS_SSL_MODE_CBC || ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type); #else size_t block_size = mbedtls_cipher_info_get_block_size(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Get MAC length */ mac_key_len = PSA_HASH_LENGTH(mac_alg); #else /* Initialize HMAC contexts */ if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 || (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret); goto end; } /* Get MAC length */ mac_key_len = mbedtls_md_get_size(md_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ transform->maclen = mac_key_len; /* IV length */ #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg); #else transform->ivlen = mbedtls_cipher_info_get_iv_size(cipher_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Minimum length */ if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) { transform->minlen = transform->maclen; } else { /* * GenericBlockCipher: * 1. if EtM is in use: one block plus MAC * otherwise: * first multiple of blocklen greater than maclen * 2. IV */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) { transform->minlen = transform->maclen + block_size; } else #endif { transform->minlen = transform->maclen + block_size - transform->maclen % block_size; } if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { transform->minlen += transform->ivlen; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto end; } } } else #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u", (unsigned) keylen, (unsigned) transform->minlen, (unsigned) transform->ivlen, (unsigned) transform->maclen)); /* * Finally setup the cipher contexts, IVs and MAC secrets. */ #if defined(MBEDTLS_SSL_CLI_C) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { key1 = keyblk + mac_key_len * 2; key2 = keyblk + mac_key_len * 2 + keylen; mac_enc = keyblk; mac_dec = keyblk + mac_key_len; iv_copy_len = (transform->fixed_ivlen) ? transform->fixed_ivlen : transform->ivlen; memcpy(transform->iv_enc, key2 + keylen, iv_copy_len); memcpy(transform->iv_dec, key2 + keylen + iv_copy_len, iv_copy_len); } else #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) if (endpoint == MBEDTLS_SSL_IS_SERVER) { key1 = keyblk + mac_key_len * 2 + keylen; key2 = keyblk + mac_key_len * 2; mac_enc = keyblk + mac_key_len; mac_dec = keyblk; iv_copy_len = (transform->fixed_ivlen) ? transform->fixed_ivlen : transform->ivlen; memcpy(transform->iv_dec, key1 + keylen, iv_copy_len); memcpy(transform->iv_enc, key1 + keylen + iv_copy_len, iv_copy_len); } else #endif /* MBEDTLS_SSL_SRV_C */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto end; } if (ssl->f_export_keys != NULL) { ssl->f_export_keys(ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET, master, 48, randbytes + 32, randbytes, tls_prf_get_type(tls_prf)); } #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_alg = alg; if (alg != MBEDTLS_SSL_NULL_CIPHER) { psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); if ((status = psa_import_key(&attributes, key1, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_enc)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status); ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); goto end; } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); if ((status = psa_import_key(&attributes, key2, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_dec)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret); goto end; } } #else if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); goto end; } if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); goto end; } if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_ENCRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); goto end; } if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_DECRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); goto end; } #if defined(MBEDTLS_CIPHER_MODE_CBC) if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) { if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc, MBEDTLS_PADDING_NONE)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); goto end; } if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec, MBEDTLS_PADDING_NONE)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret); goto end; } } #endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) /* For HMAC-based ciphersuites, initialize the HMAC transforms. For AEAD-based ciphersuites, there is nothing to do here. */ if (mac_key_len != 0) { #if defined(MBEDTLS_USE_PSA_CRYPTO) transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg)); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); if ((status = psa_import_key(&attributes, mac_enc, mac_key_len, &transform->psa_mac_enc)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); goto end; } if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) || ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING) #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) #endif )) { /* mbedtls_ct_hmac() requires the key to be exportable */ psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH); } else { psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); } if ((status = psa_import_key(&attributes, mac_dec, mac_key_len, &transform->psa_mac_dec)) != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret); goto end; } #else ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len); if (ret != 0) { goto end; } ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len); if (ret != 0) { goto end; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ ((void) mac_dec); ((void) mac_enc); end: mbedtls_platform_zeroize(keyblk, sizeof(keyblk)); return ret; } #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_psa_ecjpake_read_round( psa_pake_operation_t *pake_ctx, const unsigned char *buf, size_t len, mbedtls_ecjpake_rounds_t round) { psa_status_t status; size_t input_offset = 0; /* * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice * At round two perform a single cycle */ unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; for (; remaining_steps > 0; remaining_steps--) { for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; step <= PSA_PAKE_STEP_ZK_PROOF; ++step) { /* Length is stored at the first byte */ size_t length = buf[input_offset]; input_offset += 1; if (input_offset + length > len) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } status = psa_pake_input(pake_ctx, step, buf + input_offset, length); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } input_offset += length; } } if (input_offset != len) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return 0; } int mbedtls_psa_ecjpake_write_round( psa_pake_operation_t *pake_ctx, unsigned char *buf, size_t len, size_t *olen, mbedtls_ecjpake_rounds_t round) { psa_status_t status; size_t output_offset = 0; size_t output_len; /* * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice * At round two perform a single cycle */ unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1; for (; remaining_steps > 0; remaining_steps--) { for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE; step <= PSA_PAKE_STEP_ZK_PROOF; ++step) { /* * For each step, prepend 1 byte with the length of the data as * given by psa_pake_output(). */ status = psa_pake_output(pake_ctx, step, buf + output_offset + 1, len - output_offset - 1, &output_len); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } *(buf + output_offset) = (uint8_t) output_len; output_offset += output_len + 1; } } *olen = output_offset; return 0; } #endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO #if defined(MBEDTLS_USE_PSA_CRYPTO) int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg) { psa_status_t status; psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(md_alg); MBEDTLS_SSL_DEBUG_MSG(3, ("Perform PSA-based computation of digest of ServerKeyExchange")); if ((status = psa_hash_setup(&hash_operation, hash_alg)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_setup", status); goto exit; } if ((status = psa_hash_update(&hash_operation, ssl->handshake->randbytes, 64)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status); goto exit; } if ((status = psa_hash_update(&hash_operation, data, data_len)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status); goto exit; } if ((status = psa_hash_finish(&hash_operation, hash, PSA_HASH_MAX_SIZE, hashlen)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_finish", status); goto exit; } exit: if (status != PSA_SUCCESS) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); switch (status) { case PSA_ERROR_NOT_SUPPORTED: return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */ case PSA_ERROR_BUFFER_TOO_SMALL: return MBEDTLS_ERR_MD_BAD_INPUT_DATA; case PSA_ERROR_INSUFFICIENT_MEMORY: return MBEDTLS_ERR_MD_ALLOC_FAILED; default: return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } } return 0; } #else int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl, unsigned char *hash, size_t *hashlen, unsigned char *data, size_t data_len, mbedtls_md_type_t md_alg) { int ret = 0; mbedtls_md_context_t ctx; const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); *hashlen = mbedtls_md_get_size(md_info); MBEDTLS_SSL_DEBUG_MSG(3, ("Perform mbedtls-based computation of digest of ServerKeyExchange")); mbedtls_md_init(&ctx); /* * digitally-signed struct { * opaque client_random[32]; * opaque server_random[32]; * ServerDHParams params; * }; */ if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret); goto exit; } if ((ret = mbedtls_md_starts(&ctx)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_starts", ret); goto exit; } if ((ret = mbedtls_md_update(&ctx, ssl->handshake->randbytes, 64)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret); goto exit; } if ((ret = mbedtls_md_update(&ctx, data, data_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret); goto exit; } if ((ret = mbedtls_md_finish(&ctx, hash)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret); goto exit; } exit: mbedtls_md_free(&ctx); if (ret != 0) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); } return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* Find the preferred hash for a given signature algorithm. */ unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( mbedtls_ssl_context *ssl, unsigned int sig_alg) { unsigned int i; uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; if (sig_alg == MBEDTLS_SSL_SIG_ANON) { return MBEDTLS_SSL_HASH_NONE; } for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) { unsigned int hash_alg_received = MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG( received_sig_algs[i]); unsigned int sig_alg_received = MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG( received_sig_algs[i]); mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash((unsigned char) hash_alg_received); if (md_alg == MBEDTLS_MD_NONE) { continue; } if (sig_alg == sig_alg_received) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) { psa_algorithm_t psa_hash_alg = mbedtls_md_psa_alg_from_type(md_alg); if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA && !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, PSA_ALG_ECDSA(psa_hash_alg), PSA_KEY_USAGE_SIGN_HASH)) { continue; } if (sig_alg_received == MBEDTLS_SSL_SIG_RSA && !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key, PSA_ALG_RSA_PKCS1V15_SIGN( psa_hash_alg), PSA_KEY_USAGE_SIGN_HASH)) { continue; } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return hash_alg_received; } } return MBEDTLS_SSL_HASH_NONE; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ int mbedtls_ssl_validate_ciphersuite( const mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *suite_info, mbedtls_ssl_protocol_version min_tls_version, mbedtls_ssl_protocol_version max_tls_version) { (void) ssl; if (suite_info == NULL) { return -1; } if ((suite_info->min_tls_version > max_tls_version) || (suite_info->max_tls_version < min_tls_version)) { return -1; } #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && ssl->handshake->psa_pake_ctx_is_ok != 1) #else if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) #endif /* MBEDTLS_USE_PSA_CRYPTO */ { return -1; } #endif /* Don't suggest PSK-based ciphersuite if no PSK is available. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) && mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { return -1; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ return 0; } #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) /* * Function for writing a signature algorithm extension. * * The `extension_data` field of signature algorithm contains a `SignatureSchemeList` * value (TLS 1.3 RFC8446): * enum { * .... * ecdsa_secp256r1_sha256( 0x0403 ), * ecdsa_secp384r1_sha384( 0x0503 ), * ecdsa_secp521r1_sha512( 0x0603 ), * .... * } SignatureScheme; * * struct { * SignatureScheme supported_signature_algorithms<2..2^16-2>; * } SignatureSchemeList; * * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm` * value (TLS 1.2 RFC5246): * enum { * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), * sha512(6), (255) * } HashAlgorithm; * * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } * SignatureAlgorithm; * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * SignatureAndHashAlgorithm * supported_signature_algorithms<2..2^16-2>; * * The TLS 1.3 signature algorithm extension was defined to be a compatible * generalization of the TLS 1.2 signature algorithm extension. * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by * `SignatureScheme` field of TLS 1.3 * */ int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */ size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */ *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("adding signature_algorithms extension")); /* Check if we have space for header and length field: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - supported_signature_algorithms_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; /* * Write supported_signature_algorithms */ supported_sig_alg = p; const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); if (sig_alg == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { MBEDTLS_SSL_DEBUG_MSG(3, ("got signature scheme [%x] %s", *sig_alg, mbedtls_ssl_sig_alg_to_str(*sig_alg))); if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { continue; } MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("sent signature scheme [%x] %s", *sig_alg, mbedtls_ssl_sig_alg_to_str(*sig_alg))); } /* Length of supported_signature_algorithms */ supported_sig_alg_len = (size_t) (p - supported_sig_alg); if (supported_sig_alg_len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("No signature algorithms defined.")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SIG_ALG, buf, 0); MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2); MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4); *out_len = (size_t) (p - buf); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG); #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ return 0; } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) /* * mbedtls_ssl_parse_server_name_ext * * Structure of server_name extension: * * enum { * host_name(0), (255) * } NameType; * opaque HostName<1..2^16-1>; * * struct { * NameType name_type; * select (name_type) { * case host_name: HostName; * } name; * } ServerName; * struct { * ServerName server_name_list<1..2^16-1> * } ServerNameList; */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; size_t server_name_list_len, hostname_len; const unsigned char *server_name_list_end; MBEDTLS_SSL_DEBUG_MSG(3, ("parse ServerName extension")); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); server_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, server_name_list_len); server_name_list_end = p + server_name_list_len; while (p < server_name_list_end) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, 3); hostname_len = MBEDTLS_GET_UINT16_BE(p, 1); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, server_name_list_end, hostname_len + 3); if (p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME) { /* sni_name is intended to be used only during the parsing of the * ClientHello message (it is reset to NULL before the end of * the message parsing). Thus it is ok to just point to the * reception buffer and not make a copy of it. */ ssl->handshake->sni_name = p + 3; ssl->handshake->sni_name_len = hostname_len; if (ssl->conf->f_sni == NULL) { return 0; } ret = ssl->conf->f_sni(ssl->conf->p_sni, ssl, p + 3, hostname_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_sni_wrapper", ret); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME, MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME); return MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME; } return 0; } p += hostname_len + 3; } return 0; } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t protocol_name_list_len; const unsigned char *protocol_name_list; const unsigned char *protocol_name_list_end; size_t protocol_name_len; /* If ALPN not configured, just ignore the extension */ if (ssl->conf->alpn_list == NULL) { return 0; } /* * RFC7301, section 3.1 * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; */ /* * protocol_name_list_len 2 bytes * protocol_name_len 1 bytes * protocol_name >=1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); protocol_name_list = p; protocol_name_list_end = p + protocol_name_list_len; /* Validate peer's list (lengths) */ while (p < protocol_name_list_end) { protocol_name_len = *p++; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len); if (protocol_name_len == 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += protocol_name_len; } /* Use our order of preference */ for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { size_t const alpn_len = strlen(*alpn); p = protocol_name_list; while (p < protocol_name_list_end) { protocol_name_len = *p++; if (protocol_name_len == alpn_len && memcmp(p, *alpn, alpn_len) == 0) { ssl->alpn_chosen = *alpn; return 0; } p += protocol_name_len; } } /* If we get here, no match was found */ MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL, MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL); return MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL; } int mbedtls_ssl_write_alpn_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; size_t protocol_name_len; *out_len = 0; if (ssl->alpn_chosen == NULL) { return 0; } protocol_name_len = strlen(ssl->alpn_chosen); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7 + protocol_name_len); MBEDTLS_SSL_DEBUG_MSG(3, ("server side, adding alpn extension")); /* * 0 . 1 ext identifier * 2 . 3 ext length * 4 . 5 protocol list length * 6 . 6 protocol name length * 7 . 7+n protocol name */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ALPN, p, 0); *out_len = 7 + protocol_name_len; MBEDTLS_PUT_UINT16_BE(protocol_name_len + 3, p, 2); MBEDTLS_PUT_UINT16_BE(protocol_name_len + 1, p, 4); /* Note: the length of the chosen protocol has been checked to be less * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`. */ p[6] = MBEDTLS_BYTE_0(protocol_name_len); memcpy(p + 7, ssl->alpn_chosen, protocol_name_len); #if defined(MBEDTLS_SSL_PROTO_TLS1_3) mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_ALPN); #endif return 0; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ defined(MBEDTLS_SSL_CLI_C) int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session, const char *hostname) { /* Initialize to suppress unnecessary compiler warning */ size_t hostname_len = 0; /* Check if new hostname is valid before * making any change to current one */ if (hostname != NULL) { hostname_len = strlen(hostname); if (hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } /* Now it's clear that we will overwrite the old hostname, * so we can free it safely */ if (session->hostname != NULL) { mbedtls_zeroize_and_free(session->hostname, strlen(session->hostname)); } /* Passing NULL as hostname shall clear the old one */ if (hostname == NULL) { session->hostname = NULL; } else { session->hostname = mbedtls_calloc(1, hostname_len + 1); if (session->hostname == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->hostname, hostname, hostname_len); } return 0; } #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \ defined(MBEDTLS_SSL_ALPN) int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session, const char *alpn) { size_t alpn_len = 0; if (alpn != NULL) { alpn_len = strlen(alpn); if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } } if (session->ticket_alpn != NULL) { mbedtls_zeroize_and_free(session->ticket_alpn, strlen(session->ticket_alpn)); session->ticket_alpn = NULL; } if (alpn != NULL) { session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1); if (session->ticket_alpn == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(session->ticket_alpn, alpn, alpn_len); } return 0; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */ #endif /* MBEDTLS_SSL_TLS_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c000066400000000000000000004003061464416617300246670ustar00rootroot00000000000000/* * TLS client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_client.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/constant_time.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa_util_internal.h" #include "psa/crypto.h" #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include #include #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) #include "mbedtls/platform_util.h" #endif #if defined(MBEDTLS_SSL_RENEGOTIATION) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; /* We're always including a TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the * initial ClientHello, in which case also adding the renegotiation * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding renegotiation extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + ssl->verify_data_len); /* * Secure renegotiation */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0); p += 2; *p++ = 0x00; *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len + 1); *p++ = MBEDTLS_BYTE_0(ssl->verify_data_len); memcpy(p, ssl->own_verify_data, ssl->verify_data_len); *olen = 5 + ssl->verify_data_len; return 0; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; (void) ssl; /* ssl used for debugging only */ *olen = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported_point_formats extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0); p += 2; *p++ = 0x00; *p++ = 2; *p++ = 1; *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; *olen = 6; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t kkpp_len = 0; *olen = 0; /* Skip costly extension if we can't use EC J-PAKE anyway */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (ssl->handshake->psa_pake_ctx_is_ok != 1) { return 0; } #else if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) { return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding ecjpake_kkpp extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0); p += 2; /* * We may need to send ClientHello multiple times for Hello verification. * We don't want to compute fresh values every time (both for performance * and consistency reasons), so cache the extension content. */ if (ssl->handshake->ecjpake_cache == NULL || ssl->handshake->ecjpake_cache_len == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("generating new ecjpake parameters")); #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, p + 2, end - p - 2, &kkpp_len, MBEDTLS_ECJPAKE_ROUND_ONE); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return ret; } #else ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx, p + 2, end - p - 2, &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ ssl->handshake->ecjpake_cache = mbedtls_calloc(1, kkpp_len); if (ssl->handshake->ecjpake_cache == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("allocation failed")); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->handshake->ecjpake_cache, p + 2, kkpp_len); ssl->handshake->ecjpake_cache_len = kkpp_len; } else { MBEDTLS_SSL_DEBUG_MSG(3, ("re-using cached ecjpake parameters")); kkpp_len = ssl->handshake->ecjpake_cache_len; MBEDTLS_SSL_CHK_BUF_PTR(p + 2, end, kkpp_len); memcpy(p + 2, ssl->handshake->ecjpake_cache, kkpp_len); } MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); p += 2; *olen = kkpp_len + 4; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_cid_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t ext_len; /* * struct { * opaque cid<0..2^8-1>; * } ConnectionId; */ *olen = 0; if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding CID extension")); /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX * which is at most 255, so the increment cannot overflow. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, (unsigned) (ssl->own_cid_len + 5)); /* Add extension ID + size */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0); p += 2; ext_len = (size_t) ssl->own_cid_len + 1; MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2; *p++ = (uint8_t) ssl->own_cid_len; memcpy(p, ssl->own_cid, ssl->own_cid_len); *olen = ssl->own_cid_len + 5; return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding max_fragment_length extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0); p += 2; *p++ = 0x00; *p++ = 1; *p++ = ssl->conf->mfl_code; *olen = 5; return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding encrypt_then_mac extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; return 0; } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; *olen = 0; if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding extended_master_secret extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; return 0; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t tlen = ssl->session_negotiate->ticket_len; *olen = 0; if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding session ticket extension")); /* The addition is safe here since the ticket length is 16 bit. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + tlen); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(tlen, p, 0); p += 2; *olen = 4; if (ssl->session_negotiate->ticket == NULL || tlen == 0) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen)); memcpy(p, ssl->session_negotiate->ticket, tlen); *olen += tlen; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *olen) { unsigned char *p = buf; size_t protection_profiles_index = 0, ext_len = 0; uint16_t mki_len = 0, profile_value = 0; *olen = 0; if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->conf->dtls_srtp_profile_list == NULL) || (ssl->conf->dtls_srtp_profile_list_len == 0)) { return 0; } /* RFC 5764 section 4.1.1 * uint8 SRTPProtectionProfile[2]; * * struct { * SRTPProtectionProfiles SRTPProtectionProfiles; * opaque srtp_mki<0..255>; * } UseSRTPData; * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; */ if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) { mki_len = ssl->dtls_srtp_info.mki_len; } /* Extension length = 2 bytes for profiles length, * ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ), * 1 byte for srtp_mki vector length and the mki_len value */ ext_len = 2 + 2 * (ssl->conf->dtls_srtp_profile_list_len) + 1 + mki_len; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding use_srtp extension")); /* Check there is room in the buffer for the extension + 4 bytes * - the extension tag (2 bytes) * - the extension length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, ext_len + 4); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, p, 0); p += 2; MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2; /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */ /* micro-optimization: * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH * which is lower than 127, so the upper byte of the length is always 0 * For the documentation, the more generic code is left in comments * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len ) * >> 8 ) & 0xFF ); */ *p++ = 0; *p++ = MBEDTLS_BYTE_0(2 * ssl->conf->dtls_srtp_profile_list_len); for (protection_profiles_index = 0; protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len; protection_profiles_index++) { profile_value = mbedtls_ssl_check_srtp_profile_value (ssl->conf->dtls_srtp_profile_list[protection_profiles_index]); if (profile_value != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_write_use_srtp_ext, add profile: %04x", profile_value)); MBEDTLS_PUT_UINT16_BE(profile_value, p, 0); p += 2; } else { /* * Note: we shall never arrive here as protection profiles * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, " "illegal DTLS-SRTP protection profile %d", ssl->conf->dtls_srtp_profile_list[protection_profiles_index] )); return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } } *p++ = mki_len & 0xFF; if (mki_len != 0) { memcpy(p, ssl->dtls_srtp_info.mki_value, mki_len); /* * Increment p to point to the current position. */ p += mki_len; MBEDTLS_SSL_DEBUG_BUF(3, "sending mki", ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } /* * total extension length: extension type (2 bytes) * + extension length (2 bytes) * + protection profile length (2 bytes) * + 2 * number of protection profiles * + srtp_mki vector length(1 byte) * + mki value */ *olen = p - buf; return 0; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, int uses_ec, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t ext_len = 0; (void) ssl; (void) end; (void) uses_ec; (void) ret; (void) ext_len; *out_len = 0; /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if ((ret = ssl_write_renegotiation_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_renegotiation_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (uses_ec) { if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_supported_point_formats_ext", ret); return ret; } p += ext_len; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if ((ret = ssl_write_ecjpake_kkpp_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_ecjpake_kkpp_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) if ((ret = ssl_write_cid_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_cid_ext", ret); return ret; } p += ext_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) if ((ret = ssl_write_max_fragment_length_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_max_fragment_length_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) if ((ret = ssl_write_encrypt_then_mac_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_encrypt_then_mac_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if ((ret = ssl_write_extended_ms_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_extended_ms_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) if ((ret = ssl_write_use_srtp_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_use_srtp_ext", ret); return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) if ((ret = ssl_write_session_ticket_ext(ssl, p, end, &ext_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_write_session_ticket_ext", ret); return ret; } p += ext_len; #endif *out_len = (size_t) (p - buf); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { /* Check verify-data in constant-time. The length OTOH is no secret */ if (len != 1 + ssl->verify_data_len * 2 || buf[0] != ssl->verify_data_len * 2 || mbedtls_ct_memcmp(buf + 1, ssl->own_verify_data, ssl->verify_data_len) != 0 || mbedtls_ct_memcmp(buf + 1 + ssl->verify_data_len, ssl->peer_verify_data, ssl->verify_data_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { if (len != 1 || buf[0] != 0x00) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-zero length renegotiation info")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; } return 0; } #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { /* * server should use the extension only if we did, * and if so the server's value should match ours (and len is always 1) */ if (ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || len != 1 || buf[0] != ssl->conf->mfl_code) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching max fragment length extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t peer_cid_len; if ( /* CID extension only makes sense in DTLS */ ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || /* The server must only send the CID extension if we have offered it. */ ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension unexpected")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } if (len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } peer_cid_len = *buf++; len--; if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (len != peer_cid_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("CID extension invalid")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; memcpy(ssl->handshake->peer_cid, buf, peer_cid_len); MBEDTLS_SSL_DEBUG_MSG(3, ("Use of CID extension negotiated")); MBEDTLS_SSL_DEBUG_BUF(3, "Server CID", buf, peer_cid_len); return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching encrypt-then-MAC extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; return 0; } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching extended master secret extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; return 0; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching session ticket extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } ((void) buf); ssl->handshake->new_session_ticket = 1; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_size; const unsigned char *p; if (len == 0 || (size_t) (buf[0] + 1) != len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = buf[0]; p = buf + 1; while (list_size > 0) { if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || p[0] == MBEDTLS_ECP_PF_COMPRESSED) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) ssl->handshake->ecdh_ctx.point_format = p[0]; #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, p[0]); #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0])); return 0; } list_size--; p++; } MBEDTLS_SSL_DEBUG_MSG(1, ("no point format in common")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl->handshake->ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_ECJPAKE) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension")); return 0; } /* If we got here, we no longer need our cached extension */ mbedtls_free(ssl->handshake->ecjpake_cache); ssl->handshake->ecjpake_cache = NULL; ssl->handshake->ecjpake_cache_len = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, buf, len, MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } return 0; #else if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx, buf, len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } return 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_len, name_len; const char **p; /* If we didn't send it, the server shouldn't send it */ if (ssl->conf->alpn_list == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching ALPN extension")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } /* * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; * * the "ProtocolNameList" MUST contain exactly one "ProtocolName" */ /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ if (len < 4) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_len = MBEDTLS_GET_UINT16_BE(buf, 0); if (list_len != len - 2) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } name_len = buf[2]; if (name_len != list_len - 1) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check that the server chosen protocol was in our list and save it */ for (p = ssl->conf->alpn_list; *p != NULL; p++) { if (name_len == strlen(*p) && memcmp(buf + 3, *p, name_len) == 0) { ssl->alpn_chosen = *p; return 0; } } MBEDTLS_SSL_DEBUG_MSG(1, ("ALPN extension: no matching protocol")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET; size_t i, mki_len = 0; uint16_t server_protection_profile_value = 0; /* If use_srtp is not configured, just ignore the extension */ if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->conf->dtls_srtp_profile_list == NULL) || (ssl->conf->dtls_srtp_profile_list_len == 0)) { return 0; } /* RFC 5764 section 4.1.1 * uint8 SRTPProtectionProfile[2]; * * struct { * SRTPProtectionProfiles SRTPProtectionProfiles; * opaque srtp_mki<0..255>; * } UseSRTPData; * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; * */ if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) { mki_len = ssl->dtls_srtp_info.mki_len; } /* * Length is 5 + optional mki_value : one protection profile length (2 bytes) * + protection profile (2 bytes) * + mki_len(1 byte) * and optional srtp_mki */ if ((len < 5) || (len != (buf[4] + 5u))) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * get the server protection profile */ /* * protection profile length must be 0x0002 as we must have only * one protection profile in server Hello */ if ((buf[0] != 0) || (buf[1] != 2)) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } server_protection_profile_value = (buf[2] << 8) | buf[3]; server_protection = mbedtls_ssl_check_srtp_profile_value( server_protection_profile_value); if (server_protection != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( server_protection))); } ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; /* * Check we have the server profile in our list */ for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) { if (server_protection == ssl->conf->dtls_srtp_profile_list[i]) { ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( server_protection))); break; } } /* If no match was found : server problem, it shall never answer with incompatible profile */ if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* If server does not use mki in its reply, make sure the client won't keep * one as negotiated */ if (len == 5) { ssl->dtls_srtp_info.mki_len = 0; } /* * RFC5764: * If the client detects a nonzero-length MKI in the server's response * that is different than the one the client offered, then the client * MUST abort the handshake and SHOULD send an invalid_parameter alert. */ if (len > 5 && (buf[4] != mki_len || (memcmp(ssl->dtls_srtp_info.mki_value, &buf[5], mki_len)))) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_DEBUG_C) if (len > 5) { MBEDTLS_SSL_DEBUG_BUF(3, "received mki", ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } #endif return 0; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Parse HelloVerifyRequest. Only called after verifying the HS type. */ #if defined(MBEDTLS_SSL_PROTO_DTLS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_hello_verify_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); uint16_t dtls_legacy_version; #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) uint8_t cookie_len; #else uint16_t cookie_len; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse hello verify request")); /* Check that there is enough room for: * - 2 bytes of version * - 1 byte of cookie_len */ if (mbedtls_ssl_hs_hdr_len(ssl) + 3 > ssl->in_msglen) { MBEDTLS_SSL_DEBUG_MSG(1, ("incoming HelloVerifyRequest message is too short")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * struct { * ProtocolVersion server_version; * opaque cookie<0..2^8-1>; * } HelloVerifyRequest; */ MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); dtls_legacy_version = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* * Since the RFC is not clear on this point, accept DTLS 1.0 (0xfeff) * The DTLS 1.3 (current draft) renames ProtocolVersion server_version to * legacy_version and locks the value of legacy_version to 0xfefd (DTLS 1.2) */ if (dtls_legacy_version != 0xfefd && dtls_legacy_version != 0xfeff) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server version")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } cookie_len = *p++; if ((ssl->in_msg + ssl->in_msglen) - p < cookie_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("cookie length does not match incoming message size")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "cookie", p, cookie_len); mbedtls_free(ssl->handshake->cookie); ssl->handshake->cookie = mbedtls_calloc(1, cookie_len); if (ssl->handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed (%d bytes)", cookie_len)); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->handshake->cookie, p, cookie_len); ssl->handshake->cookie_len = cookie_len; /* Start over at ClientHello */ ssl->state = MBEDTLS_SSL_CLIENT_HELLO; ret = mbedtls_ssl_reset_checksum(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_reset_checksum"), ret); return ret; } mbedtls_ssl_recv_flight_completed(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse hello verify request")); return 0; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello(mbedtls_ssl_context *ssl) { int ret, i; size_t n; size_t ext_len; unsigned char *buf, *ext; unsigned char comp; #if defined(MBEDTLS_SSL_RENEGOTIATION) int renegotiation_info_seen = 0; #endif int handshake_failure = 0; const mbedtls_ssl_ciphersuite_t *suite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server hello")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } buf = ssl->in_msg; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { ssl->renego_records_seen++; if (ssl->conf->renego_max_records >= 0 && ssl->renego_records_seen > ssl->conf->renego_max_records) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation requested, but not honored by server")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } MBEDTLS_SSL_DEBUG_MSG(1, ("non-handshake message during renegotiation")); ssl->keep_current_message = 1; return MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { if (buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST) { MBEDTLS_SSL_DEBUG_MSG(2, ("received hello verify request")); MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello")); return ssl_parse_hello_verify_request(ssl); } else { /* We made it through the verification process */ mbedtls_free(ssl->handshake->cookie); ssl->handshake->cookie = NULL; ssl->handshake->cookie_len = 0; } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ if (ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len(ssl) || buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * 0 . 1 server_version * 2 . 33 random (maybe including 4 bytes of Unix time) * 34 . 34 session_id length = n * 35 . 34+n session_id * 35+n . 36+n cipher_suite * 37+n . 37+n compression_method * * 38+n . 39+n extensions length (optional) * 40+n . .. extensions */ buf += mbedtls_ssl_hs_hdr_len(ssl); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", buf, 2); ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf, ssl->conf->transport); ssl->session_negotiate->tls_version = ssl->tls_version; ssl->session_negotiate->endpoint = ssl->conf->endpoint; if (ssl->tls_version < ssl->conf->min_tls_version || ssl->tls_version > ssl->conf->max_tls_version) { MBEDTLS_SSL_DEBUG_MSG(1, ( "server version out of bounds - min: [0x%x], server: [0x%x], max: [0x%x]", (unsigned) ssl->conf->min_tls_version, (unsigned) ssl->tls_version, (unsigned) ssl->conf->max_tls_version)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %lu", ((unsigned long) buf[2] << 24) | ((unsigned long) buf[3] << 16) | ((unsigned long) buf[4] << 8) | ((unsigned long) buf[5]))); memcpy(ssl->handshake->randbytes + 32, buf + 2, 32); n = buf[34]; MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", buf + 2, 32); if (n > 32) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ssl->in_hslen > mbedtls_ssl_hs_hdr_len(ssl) + 39 + n) { ext_len = MBEDTLS_GET_UINT16_BE(buf, 38 + n); if ((ext_len > 0 && ext_len < 4) || ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 40 + n + ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } else if (ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl) + 38 + n) { ext_len = 0; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* ciphersuite (used later) */ i = (int) MBEDTLS_GET_UINT16_BE(buf, n + 35); /* * Read and check compression */ comp = buf[37 + n]; if (comp != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("server hello, bad compression: %d", comp)); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } /* * Initialize update checksum functions */ ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(i); if (ssl->handshake->ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %04x not found", (unsigned int) i)); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } mbedtls_ssl_optimize_checksum(ssl, ssl->handshake->ciphersuite_info); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n)); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, session id", buf + 35, n); /* * Check if the session can be resumed */ if (ssl->handshake->resume == 0 || n == 0 || #if defined(MBEDTLS_SSL_RENEGOTIATION) ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || #endif ssl->session_negotiate->ciphersuite != i || ssl->session_negotiate->id_len != n || memcmp(ssl->session_negotiate->id, buf + 35, n) != 0) { ssl->state++; ssl->handshake->resume = 0; #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif ssl->session_negotiate->ciphersuite = i; ssl->session_negotiate->id_len = n; memcpy(ssl->session_negotiate->id, buf + 35, n); } else { ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; } MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed", ssl->handshake->resume ? "a" : "no")); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %04x", (unsigned) i)); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: %d", buf[37 + n])); /* * Perform cipher suite validation in same way as in ssl_write_client_hello. */ i = 0; while (1) { if (ssl->conf->ciphersuite_list[i] == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (ssl->conf->ciphersuite_list[i++] == ssl->session_negotiate->ciphersuite) { break; } } suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); if (mbedtls_ssl_validate_ciphersuite(ssl, suite_info, ssl->tls_version, ssl->tls_version) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s", suite_info->name)); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) { ssl->handshake->ecrs_enabled = 1; } #endif if (comp != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ext = buf + 40 + n; MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len)); while (ext_len) { unsigned int ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); unsigned int ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); if (ext_size + 4 > ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } switch (ext_id) { case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: MBEDTLS_SSL_DEBUG_MSG(3, ("found renegotiation extension")); #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiation_info_seen = 1; #endif if ((ret = ssl_parse_renegotiation_info(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: MBEDTLS_SSL_DEBUG_MSG(3, ("found max_fragment_length extension")); if ((ret = ssl_parse_max_fragment_length_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) case MBEDTLS_TLS_EXT_CID: MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension")); if ((ret = ssl_parse_cid_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: MBEDTLS_SSL_DEBUG_MSG(3, ("found encrypt_then_mac extension")); if ((ret = ssl_parse_encrypt_then_mac_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: MBEDTLS_SSL_DEBUG_MSG(3, ("found extended_master_secret extension")); if ((ret = ssl_parse_extended_ms_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_TLS_EXT_SESSION_TICKET: MBEDTLS_SSL_DEBUG_MSG(3, ("found session_ticket extension")); if ((ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported_point_formats extension")); if ((ret = ssl_parse_supported_point_formats_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: MBEDTLS_SSL_DEBUG_MSG(3, ("found ecjpake_kkpp extension")); if ((ret = ssl_parse_ecjpake_kkpp(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); if ((ret = ssl_parse_alpn_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_SRTP) case MBEDTLS_TLS_EXT_USE_SRTP: MBEDTLS_SSL_DEBUG_MSG(3, ("found use_srtp extension")); if ((ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_SRTP */ default: MBEDTLS_SSL_DEBUG_MSG(3, ("unknown extension found: %u (ignoring)", ext_id)); } ext_len -= 4 + ext_size; ext += 4 + ext_size; if (ext_len > 0 && ext_len < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } /* * mbedtls_ssl_derive_keys() has to be called after the parsing of the * extensions. It sets the transform data for the resumed session which in * case of DTLS includes the server CID extracted from the CID extension. */ if (ssl->handshake->resume) { if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return ret; } } /* * Renegotiation security checks */ if (ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation, breaking off handshake")); handshake_failure = 1; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && renegotiation_info_seen == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension missing (secure)")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation not allowed")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && renegotiation_info_seen == 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension present (legacy)")); handshake_failure = 1; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ if (handshake_failure == 1) { mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello")); return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_dh_params(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t dhm_actual_bitlen; /* * Ephemeral DH parameters: * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ if ((ret = mbedtls_dhm_read_params(&ssl->handshake->dhm_ctx, p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(2, ("mbedtls_dhm_read_params"), ret); return ret; } dhm_actual_bitlen = mbedtls_dhm_get_bitlen(&ssl->handshake->dhm_ctx); if (dhm_actual_bitlen < ssl->conf->dhm_min_bitlen) { MBEDTLS_SSL_DEBUG_MSG(1, ("DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u", dhm_actual_bitlen, ssl->conf->dhm_min_bitlen)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: G ", &ssl->handshake->dhm_ctx.G); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { uint16_t tls_id; size_t ecpoint_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; size_t ec_bits = 0; /* * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; * * 1 curve_type (must be "named_curve") * 2..3 NamedCurve * 4 ECPoint.len * 5+ ECPoint contents */ if (end - *p < 4) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* First byte is curve_type; only named_curve is handled */ if (*(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Next two bytes are the namedcurve value */ tls_id = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; /* Check it's a curve we offered */ if (mbedtls_ssl_check_curve_tls_id(ssl, tls_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("bad server key exchange message (ECDHE curve): %u", (unsigned) tls_id)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Convert EC's TLS ID to PSA key type. */ if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } handshake->xxdh_psa_type = key_type; handshake->xxdh_psa_bits = ec_bits; /* Keep a copy of the peer's public key */ ecpoint_len = *(*p)++; if ((size_t) (end - *p) < ecpoint_len) { return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } memcpy(handshake->xxdh_psa_peerkey, *p, ecpoint_len); handshake->xxdh_psa_peerkey_len = ecpoint_len; *p += ecpoint_len; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #else #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_server_ecdh_params(const mbedtls_ssl_context *ssl) { uint16_t tls_id; mbedtls_ecp_group_id grp_id; #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) grp_id = ssl->handshake->ecdh_ctx.grp.id; #else grp_id = ssl->handshake->ecdh_ctx.grp_id; #endif tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s", mbedtls_ssl_get_curve_name_from_tls_id(tls_id))); if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { return -1; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; /* * Ephemeral ECDH parameters: * * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ if ((ret = mbedtls_ecdh_read_params(&ssl->handshake->ecdh_ctx, (const unsigned char **) p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_read_params"), ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } if (ssl_check_server_ecdh_params(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (ECDHE curve)")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #endif /* !MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl, unsigned char **p, unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; uint16_t len; ((void) ssl); /* * PSK parameters: * * opaque psk_identity_hint<0..2^16-1>; */ if (end - (*p) < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (psk_identity_hint length)")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } len = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (end - (*p) < len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message (psk_identity_hint length)")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Note: we currently ignore the PSK identity hint, as we only allow one * PSK to be provisioned on the client. This could be changed later if * someone needs that feature. */ *p += len; ret = 0; return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) /* * Generate a pre-master secret and encrypt it with the server's RSA key */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_encrypted_pms(mbedtls_ssl_context *ssl, size_t offset, size_t *olen, size_t pms_offset) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len_bytes = 2; unsigned char *p = ssl->handshake->premaster + pms_offset; mbedtls_pk_context *peer_pk; if (offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small for encrypted pms")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } /* * Generate (part of) the pre-master as * struct { * ProtocolVersion client_version; * opaque random[46]; * } PreMasterSecret; */ mbedtls_ssl_write_version(p, ssl->conf->transport, MBEDTLS_SSL_VERSION_TLS1_2); if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p + 2, 46)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); return ret; } ssl->handshake->pmslen = 48; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* * Now write it out, encrypted */ if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_RSA)) { MBEDTLS_SSL_DEBUG_MSG(1, ("certificate key type mismatch")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } if ((ret = mbedtls_pk_encrypt(peer_pk, p, ssl->handshake->pmslen, ssl->out_msg + offset + len_bytes, olen, MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_rsa_pkcs1_encrypt", ret); return ret; } if (len_bytes == 2) { MBEDTLS_PUT_UINT16_BE(*olen, ssl->out_msg, offset); *olen += 2; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it. */ mbedtls_pk_free(peer_pk); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_pk_context *peer_pk; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* This is a public key, so it can't be opaque, so can_do() is a good * enough check to ensure pk_ec() is safe to use below. */ if (!mbedtls_pk_can_do(peer_pk, MBEDTLS_PK_ECKEY)) { MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) const mbedtls_ecp_keypair *peer_key = mbedtls_pk_ec_ro(*peer_pk); #endif /* !defined(MBEDTLS_PK_USE_PSA_EC_DATA) */ #if defined(MBEDTLS_USE_PSA_CRYPTO) uint16_t tls_id = 0; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(peer_pk); if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("ECC group %u not suported", grp_id)); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* If the above conversion to TLS ID was fine, then also this one will be, so there is no need to check the return value here */ mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, &ssl->handshake->xxdh_psa_bits); ssl->handshake->xxdh_psa_type = key_type; /* Store peer's public key in psa format. */ #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) memcpy(ssl->handshake->xxdh_psa_peerkey, peer_pk->pub_raw, peer_pk->pub_raw_len); ssl->handshake->xxdh_psa_peerkey_len = peer_pk->pub_raw_len; ret = 0; #else /* MBEDTLS_PK_USE_PSA_EC_DATA */ size_t olen = 0; ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, ssl->handshake->xxdh_psa_peerkey, sizeof(ssl->handshake->xxdh_psa_peerkey)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret); return ret; } ssl->handshake->xxdh_psa_peerkey_len = olen; #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ #else /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, peer_key, MBEDTLS_ECDH_THEIRS)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret); return ret; } if (ssl_check_server_ecdh_params(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)")); return MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it, * so that more RAM is available for upcoming expensive * operations like ECDHE. */ mbedtls_pk_free(peer_pk); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; unsigned char *p = NULL, *end = NULL; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server key exchange")); #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange")); ssl->state++; return 0; } ((void) p); ((void) end); #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { if ((ret = ssl_get_ecdh_params_from_cert(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_ecdh_params_from_cert", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse server key exchange")); ssl->state++; return 0; } ((void) p); ((void) end); #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing) { goto start_processing; } #endif if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server * doesn't use a psk_identity_hint */ if (ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE) { if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { /* Current message is probably either * CertificateRequest or ServerHelloDone */ ssl->keep_current_message = 1; goto exit; } MBEDTLS_SSL_DEBUG_MSG(1, ("server key exchange message must not be skipped")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; } start_processing: #endif p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); end = ssl->in_msg + ssl->in_hslen; MBEDTLS_SSL_DEBUG_BUF(3, "server key exchange", p, (size_t) (end - p)); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { if (ssl_parse_server_psk_hint(ssl, &p, end) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } /* FALLTHROUGH */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { ; /* nothing more to do */ } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { if (ssl_parse_server_dh_params(ssl, &p, end) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA) { if (ssl_parse_server_ecdh_params(ssl, &p, end) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * The first 3 bytes are: * [0] MBEDTLS_ECP_TLS_NAMED_CURVE * [1, 2] elliptic curve's TLS ID * * However since we only support secp256r1 for now, we check only * that TLS ID here */ uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE(p, 1); uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( MBEDTLS_ECP_DP_SECP256R1); if (exp_tls_id == 0) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } if ((*p != MBEDTLS_ECP_TLS_NAMED_CURVE) || (read_tls_id != exp_tls_id)) { return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += 3; if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, p, end - p, MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #else ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx, p, end - p); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) { size_t sig_len, hashlen; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); size_t params_len = (size_t) (p - params); void *rs_ctx = NULL; uint16_t sig_alg; mbedtls_pk_context *peer_pk; #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* * Handle the digitally-signed structure */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); sig_alg = MBEDTLS_GET_UINT16_BE(p, 0); if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( sig_alg, &pk_alg, &md_alg) != 0 && !mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg) && !mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += 2; if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * Read signature */ if (p > end - 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } sig_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; if (p != end - sig_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "signature", p, sig_len); /* * Compute the hash that has been signed */ if (md_alg != MBEDTLS_MD_NONE) { ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen, params, params_len, md_alg); if (ret != 0) { return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen); /* * Verify signature */ if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server key exchange message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx.pk; } #endif #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { mbedtls_pk_rsassa_pss_options rsassa_pss_options; rsassa_pss_options.mgf1_hash_id = md_alg; rsassa_pss_options.expected_salt_len = mbedtls_md_get_size_from_type(md_alg); if (rsassa_pss_options.expected_salt_len == 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_pk_verify_ext(pk_alg, &rsassa_pss_options, peer_pk, md_alg, hash, hashlen, p, sig_len); } else #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ ret = mbedtls_pk_verify_restartable(peer_pk, md_alg, hash, hashlen, p, sig_len, rs_ctx); if (ret != 0) { int send_alert_msg = 1; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) send_alert_msg = (ret != MBEDTLS_ERR_ECP_IN_PROGRESS); #endif if (send_alert_msg) { mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR); } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* We don't need the peer's public key anymore. Free it, * so that more RAM is available for upcoming expensive * operations like ECDHE. */ mbedtls_pk_free(peer_pk); #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ exit: ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server key exchange")); return 0; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t n = 0; size_t cert_type_len = 0, dn_len = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; size_t sig_alg_len; #if defined(MBEDTLS_DEBUG_C) unsigned char *sig_alg; unsigned char *dn; #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate request")); ssl->state++; return 0; } if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } ssl->state++; ssl->handshake->client_auth = (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST); MBEDTLS_SSL_DEBUG_MSG(3, ("got %s certificate request", ssl->handshake->client_auth ? "a" : "no")); if (ssl->handshake->client_auth == 0) { /* Current message is probably the ServerHelloDone */ ssl->keep_current_message = 1; goto exit; } /* * struct { * ClientCertificateType certificate_types<1..2^8-1>; * SignatureAndHashAlgorithm * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only * DistinguishedName certificate_authorities<0..2^16-1>; * } CertificateRequest; * * Since we only support a single certificate on clients, let's just * ignore all the information that's supposed to help us pick a * certificate. * * We could check that our certificate matches the request, and bail out * if it doesn't, but it's simpler to just send the certificate anyway, * and give the server the opportunity to decide if it should terminate * the connection when it doesn't like our certificate. * * Same goes for the hash in TLS 1.2's signature_algorithms: at this * point we only have one hash available (see comments in * write_certificate_verify), so let's just use what we have. * * However, we still minimally parse the message to check it is at least * superficially sane. */ buf = ssl->in_msg; /* certificate_types */ if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } cert_type_len = buf[mbedtls_ssl_hs_hdr_len(ssl)]; n = cert_type_len; /* * In the subsequent code there are two paths that read from buf: * * the length of the signature algorithms field (if minor version of * SSL is 3), * * distinguished name length otherwise. * Both reach at most the index: * ...hdr_len + 2 + n, * therefore the buffer length at this point must be greater than that * regardless of the actual code path. */ if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 2 + n) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* supported_signature_algorithms */ sig_alg_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n); /* * The furthest access in buf is in the loop few lines below: * sig_alg[i + 1], * where: * sig_alg = buf + ...hdr_len + 3 + n, * max(i) = sig_alg_len - 1. * Therefore the furthest access is: * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], * which reduces to: * buf[...hdr_len + 3 + n + sig_alg_len], * which is one less than we need the buf to be. */ if (ssl->in_hslen <= mbedtls_ssl_hs_hdr_len(ssl) + 3 + n + sig_alg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if defined(MBEDTLS_DEBUG_C) sig_alg = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n; for (size_t i = 0; i < sig_alg_len; i += 2) { MBEDTLS_SSL_DEBUG_MSG(3, ("Supported Signature Algorithm found: %02x %02x", sig_alg[i], sig_alg[i + 1])); } #endif n += 2 + sig_alg_len; /* certificate_authorities */ dn_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n); n += dn_len; if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 3 + n) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if defined(MBEDTLS_DEBUG_C) dn = buf + mbedtls_ssl_hs_hdr_len(ssl) + 3 + n - dn_len; for (size_t i = 0, dni_len = 0; i < dn_len; i += 2 + dni_len) { unsigned char *p = dn + i + 2; mbedtls_x509_name name; size_t asn1_len; char s[MBEDTLS_X509_MAX_DN_NAME_SIZE]; memset(&name, 0, sizeof(name)); dni_len = MBEDTLS_GET_UINT16_BE(dn + i, 0); if (dni_len > dn_len - i - 2 || mbedtls_asn1_get_tag(&p, p + dni_len, &asn1_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0 || mbedtls_x509_get_name(&p, p + asn1_len, &name) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate request message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("DN hint: %.*s", mbedtls_x509_dn_gets(s, sizeof(s), &name), s)); mbedtls_asn1_free_named_data_list_shallow(name.next); } #endif exit: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_server_hello_done(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse server hello done")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) || ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello done message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->state++; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_recv_flight_completed(ssl); } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse server hello done")); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t header_len; size_t content_len; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write client key exchange")); #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) { /* * DHM key exchange -- send G^X mod P */ content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); MBEDTLS_PUT_UINT16_BE(content_len, ssl->out_msg, 4); header_len = 6; ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), &ssl->out_msg[header_len], content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret); return ret; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: X ", &ssl->handshake->dhm_ctx.X); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GX", &ssl->handshake->dhm_ctx.GX); if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, ssl->handshake->premaster, MBEDTLS_PREMASTER_SIZE, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; header_len = 4; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); /* * Generate EC private key for ECDHE exchange. */ /* The master secret is obtained from the shared ECDH secret by * applying the TLS 1.2 PRF with a specific salt and label. While * the PSA Crypto API encourages combining key agreement schemes * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not * yet support the provisioning of salt + label to the KDF. * For the time being, we therefore need to split the computation * of the ECDH secret and the application of the TLS 1.2 PRF. */ key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } /* Export the public part of the ECDH private key from PSA. * The export format is an ECPoint structure as expected by TLS, * but we just need to add a length byte before that. */ unsigned char *own_pubkey = ssl->out_msg + header_len + 1; unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t own_pubkey_max_len = (size_t) (end - own_pubkey); size_t own_pubkey_len; status = psa_export_public_key(handshake->xxdh_psa_privkey, own_pubkey, own_pubkey_max_len, &own_pubkey_len); if (status != PSA_SUCCESS) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } ssl->out_msg[header_len] = (unsigned char) own_pubkey_len; content_len = own_pubkey_len + 1; /* The ECDH secret is the premaster secret used for key derivation. */ /* Compute ECDH shared secret. */ status = psa_raw_key_agreement(PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, ssl->handshake->premaster, sizeof(ssl->handshake->premaster), &ssl->handshake->pmslen); destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS || destruction_status != PSA_SUCCESS) { return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } #else /* * ECDH key exchange -- send client public value */ header_len = 4; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { if (ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret) { goto ecdh_calc_secret; } mbedtls_ecdh_enable_restart(&ssl->handshake->ecdh_ctx); } #endif ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx, &content_len, &ssl->out_msg[header_len], 1000, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_public", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_n = content_len; ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; } ecdh_calc_secret: if (ssl->handshake->ecrs_enabled) { content_len = ssl->handshake->ecrs_n; } #endif if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, MBEDTLS_MPI_MAX_SIZE, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* * opaque psk_identity<0..2^16-1>; */ if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the * ciphersuites we offered, so this should never happen. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* uint16 to store content length */ const size_t content_len_size = 2; header_len = 4; if (header_len + content_len_size + ssl->conf->psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } unsigned char *p = ssl->out_msg + header_len; *p++ = MBEDTLS_BYTE_1(ssl->conf->psk_identity_len); *p++ = MBEDTLS_BYTE_0(ssl->conf->psk_identity_len); header_len += content_len_size; memcpy(p, ssl->conf->psk_identity, ssl->conf->psk_identity_len); p += ssl->conf->psk_identity_len; header_len += ssl->conf->psk_identity_len; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); /* * Generate EC private key for ECDHE exchange. */ /* The master secret is obtained from the shared ECDH secret by * applying the TLS 1.2 PRF with a specific salt and label. While * the PSA Crypto API encourages combining key agreement schemes * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not * yet support the provisioning of salt + label to the KDF. * For the time being, we therefore need to split the computation * of the ECDH secret and the application of the TLS 1.2 PRF. */ key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } /* Export the public part of the ECDH private key from PSA. * The export format is an ECPoint structure as expected by TLS, * but we just need to add a length byte before that. */ unsigned char *own_pubkey = p + 1; unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t own_pubkey_max_len = (size_t) (end - own_pubkey); size_t own_pubkey_len = 0; status = psa_export_public_key(handshake->xxdh_psa_privkey, own_pubkey, own_pubkey_max_len, &own_pubkey_len); if (status != PSA_SUCCESS) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return PSA_TO_MBEDTLS_ERR(status); } *p = (unsigned char) own_pubkey_len; content_len = own_pubkey_len + 1; /* As RFC 5489 section 2, the premaster secret is formed as follows: * - a uint16 containing the length (in octets) of the ECDH computation * - the octet string produced by the ECDH computation * - a uint16 containing the length (in octets) of the PSK * - the PSK itself */ unsigned char *pms = ssl->handshake->premaster; const unsigned char * const pms_end = pms + sizeof(ssl->handshake->premaster); /* uint16 to store length (in octets) of the ECDH computation */ const size_t zlen_size = 2; size_t zlen = 0; /* Perform ECDH computation after the uint16 reserved for the length */ status = psa_raw_key_agreement(PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, pms + zlen_size, pms_end - (pms + zlen_size), &zlen); destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } else if (destruction_status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(destruction_status); } /* Write the ECDH computation length before the ECDH computation */ MBEDTLS_PUT_UINT16_BE(zlen, pms, 0); pms += zlen_size + zlen; } else #endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if (mbedtls_ssl_ciphersuite_uses_psk(ciphersuite_info)) { /* * opaque psk_identity<0..2^16-1>; */ if (mbedtls_ssl_conf_has_static_psk(ssl->conf) == 0) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the * ciphersuites we offered, so this should never happen. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } header_len = 4; content_len = ssl->conf->psk_identity_len; if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len); ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len); memcpy(ssl->out_msg + header_len, ssl->conf->psk_identity, ssl->conf->psk_identity_len); header_len += ssl->conf->psk_identity_len; #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) { content_len = 0; } else #endif #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { if ((ret = ssl_write_encrypted_pms(ssl, header_len, &content_len, 2)) != 0) { return ret; } } else #endif #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { /* * ClientDiffieHellmanPublic public (DHM send G^X mod P) */ content_len = mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx); if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("psk identity or DHM size too long or SSL buffer too short")); return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } ssl->out_msg[header_len++] = MBEDTLS_BYTE_1(content_len); ssl->out_msg[header_len++] = MBEDTLS_BYTE_0(content_len); ret = mbedtls_dhm_make_public(&ssl->handshake->dhm_ctx, (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), &ssl->out_msg[header_len], content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_public", ret); return ret; } #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *pms = ssl->handshake->premaster; unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); size_t pms_len; /* Write length only when we know the actual value */ if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, pms + 2, pms_end - (pms + 2), &pms_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0); pms += 2 + pms_len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); #endif } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { /* * ClientECDiffieHellmanPublic public; */ ret = mbedtls_ecdh_make_public(&ssl->handshake->ecdh_ctx, &content_len, &ssl->out_msg[header_len], MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_public", ret); return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); } else #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) { header_len = 4; if ((ret = ssl_write_encrypted_pms(ssl, header_len, &content_len, 0)) != 0) { return ret; } } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { header_len = 4; #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *out_p = ssl->out_msg + header_len; unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len; ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, out_p, end_p - out_p, &content_len, MBEDTLS_ECJPAKE_ROUND_TWO); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return ret; } #else ret = mbedtls_ecjpake_write_round_two(&ssl->handshake->ecjpake_ctx, ssl->out_msg + header_len, MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, &content_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_two", ret); return ret; } ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx, ssl->handshake->premaster, 32, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ { ((void) ciphersuite_info); MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->out_msglen = header_len + content_len; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client key exchange")); return 0; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; size_t n = 0, offset = 0; unsigned char hash[48]; unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; size_t hashlen; void *rs_ctx = NULL; #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf); #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf); #endif MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled && ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign) { goto sign; } #endif if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; } if (ssl->handshake->client_auth == 0 || mbedtls_ssl_own_cert(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate verify")); ssl->state++; return 0; } if (mbedtls_ssl_own_key(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no private key for certificate")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } /* * Make a signature of the handshake digests */ #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; } sign: #endif ret = ssl->handshake->calc_verify(ssl, hash, &hashlen); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); return ret; } /* * digitally-signed struct { * opaque handshake_messages[handshake_messages_length]; * }; * * Taking shortcut here. We assume that the server always allows the * PRF Hash function and has sent it in the allowed signature * algorithms list received in the Certificate Request message. * * Until we encounter a server that does not, we will take this * shortcut. * * Reason: Otherwise we should have running hashes for SHA512 and * SHA224 in order to satisfy 'weird' needs from the server * side. */ if (ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384) { md_alg = MBEDTLS_MD_SHA384; ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; } else { md_alg = MBEDTLS_MD_SHA256; ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; } ssl->out_msg[5] = mbedtls_ssl_sig_from_pk(mbedtls_ssl_own_key(ssl)); /* Info from md_alg will be used instead */ hashlen = 0; offset = 2; #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ssl->handshake->ecrs_enabled) { rs_ctx = &ssl->handshake->ecrs_ctx.pk; } #endif if ((ret = mbedtls_pk_sign_restartable(mbedtls_ssl_own_key(ssl), md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, out_buf_len - 6 - offset, &n, ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret); #if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; } #endif return ret; } MBEDTLS_PUT_UINT16_BE(n, ssl->out_msg, offset + 4); ssl->out_msglen = 6 + n + offset; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify")); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t lifetime; size_t ticket_len; unsigned char *ticket; const unsigned char *msg; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * struct { * uint32 ticket_lifetime_hint; * opaque ticket<0..2^16-1>; * } NewSessionTicket; * * 0 . 3 ticket_lifetime_hint * 4 . 5 ticket_len (n) * 6 . 5+n ticket content */ if (ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); lifetime = MBEDTLS_GET_UINT32_BE(msg, 0); ticket_len = MBEDTLS_GET_UINT16_BE(msg, 4); if (ticket_len + 6 + mbedtls_ssl_hs_hdr_len(ssl) != ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len)); /* We're not waiting for a NewSessionTicket message any more */ ssl->handshake->new_session_ticket = 0; ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; /* * Zero-length ticket means the server changed his mind and doesn't want * to send a ticket after all, so just forget it */ if (ticket_len == 0) { return 0; } if (ssl->session != NULL && ssl->session->ticket != NULL) { mbedtls_zeroize_and_free(ssl->session->ticket, ssl->session->ticket_len); ssl->session->ticket = NULL; ssl->session->ticket_len = 0; } mbedtls_zeroize_and_free(ssl->session_negotiate->ticket, ssl->session_negotiate->ticket_len); ssl->session_negotiate->ticket = NULL; ssl->session_negotiate->ticket_len = 0; if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ticket, msg + 6, ticket_len); ssl->session_negotiate->ticket = ticket; ssl->session_negotiate->ticket_len = ticket_len; ssl->session_negotiate->ticket_lifetime = lifetime; /* * RFC 5077 section 3.4: * "If the client receives a session ticket from the server, then it * discards any Session ID that was sent in the ServerHello." */ MBEDTLS_SSL_DEBUG_MSG(3, ("ticket in use, discarding session id")); ssl->session_negotiate->id_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket")); return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * SSL handshake -- client side -- single step */ int mbedtls_ssl_handshake_client_step(mbedtls_ssl_context *ssl) { int ret = 0; /* Change state now, so that it is right in mbedtls_ssl_read_record(), used * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && ssl->handshake->new_session_ticket != 0) { ssl->state = MBEDTLS_SSL_NEW_SESSION_TICKET; } #endif switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; break; /* * ==> ClientHello */ case MBEDTLS_SSL_CLIENT_HELLO: ret = mbedtls_ssl_write_client_hello(ssl); break; /* * <== ServerHello * Certificate * ( ServerKeyExchange ) * ( CertificateRequest ) * ServerHelloDone */ case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_parse_server_hello(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = mbedtls_ssl_parse_certificate(ssl); break; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: ret = ssl_parse_server_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_parse_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_HELLO_DONE: ret = ssl_parse_server_hello_done(ssl); break; /* * ==> ( Certificate/Alert ) * ClientKeyExchange * ( CertificateVerify ) * ChangeCipherSpec * Finished */ case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_write_certificate(ssl); break; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: ret = ssl_write_client_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_write_certificate_verify(ssl); break; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_write_change_cipher_spec(ssl); break; case MBEDTLS_SSL_CLIENT_FINISHED: ret = mbedtls_ssl_write_finished(ssl); break; /* * <== ( NewSessionTicket ) * ChangeCipherSpec * Finished */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_NEW_SESSION_TICKET: ret = ssl_parse_new_session_ticket(ssl); break; #endif case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_parse_change_cipher_spec(ssl); break; case MBEDTLS_SSL_SERVER_FINISHED: ret = mbedtls_ssl_parse_finished(ssl); break; case MBEDTLS_SSL_FLUSH_BUFFERS: MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: mbedtls_ssl_handshake_wrapup(ssl); break; default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return ret; } #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_2 */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c000066400000000000000000004720161464416617300247260ustar00rootroot00000000000000/* * TLS server-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2) #include "mbedtls/platform.h" #include "mbedtls/ssl.h" #include "ssl_misc.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform_util.h" #include "constant_time_internal.h" #include "mbedtls/constant_time.h" #include #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif #endif #if defined(MBEDTLS_ECP_C) #include "mbedtls/ecp.h" #endif #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) int mbedtls_ssl_set_client_transport_id(mbedtls_ssl_context *ssl, const unsigned char *info, size_t ilen) { if (ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } mbedtls_free(ssl->cli_id); if ((ssl->cli_id = mbedtls_calloc(1, ilen)) == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ssl->cli_id, info, ilen); ssl->cli_id_len = ilen; return 0; } void mbedtls_ssl_conf_dtls_cookies(mbedtls_ssl_config *conf, mbedtls_ssl_cookie_write_t *f_cookie_write, mbedtls_ssl_cookie_check_t *f_cookie_check, void *p_cookie) { conf->f_cookie_write = f_cookie_write; conf->f_cookie_check = f_cookie_check; conf->p_cookie = p_cookie; } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_conf_has_psk_or_cb(mbedtls_ssl_config const *conf) { if (conf->f_psk != NULL) { return 1; } if (conf->psk_identity_len == 0 || conf->psk_identity == NULL) { return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) { return 1; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (conf->psk != NULL && conf->psk_len != 0) { return 1; } return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { /* Check verify-data in constant-time. The length OTOH is no secret */ if (len != 1 + ssl->verify_data_len || buf[0] != ssl->verify_data_len || mbedtls_ct_memcmp(buf + 1, ssl->peer_verify_data, ssl->verify_data_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-matching renegotiation info")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { if (len != 1 || buf[0] != 0x0) { MBEDTLS_SSL_DEBUG_MSG(1, ("non-zero length renegotiation info")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; } return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) /* * Function for parsing a supported groups (TLS 1.3) or supported elliptic * curves (TLS 1.2) extension. * * The "extension_data" field of a supported groups extension contains a * "NamedGroupList" value (TLS 1.3 RFC8446): * enum { * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), * x25519(0x001D), x448(0x001E), * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), * ffdhe6144(0x0103), ffdhe8192(0x0104), * ffdhe_private_use(0x01FC..0x01FF), * ecdhe_private_use(0xFE00..0xFEFF), * (0xFFFF) * } NamedGroup; * struct { * NamedGroup named_group_list<2..2^16-1>; * } NamedGroupList; * * The "extension_data" field of a supported elliptic curves extension contains * a "NamedCurveList" value (TLS 1.2 RFC 8422): * enum { * deprecated(1..22), * secp256r1 (23), secp384r1 (24), secp521r1 (25), * x25519(29), x448(30), * reserved (0xFE00..0xFEFF), * deprecated(0xFF01..0xFF02), * (0xFFFF) * } NamedCurve; * struct { * NamedCurve named_curve_list<2..2^16-1> * } NamedCurveList; * * The TLS 1.3 supported groups extension was defined to be a compatible * generalization of the TLS 1.2 supported elliptic curves extension. They both * share the same extension identifier. * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_size, our_size; const unsigned char *p; uint16_t *curves_tls_id; if (len < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = MBEDTLS_GET_UINT16_BE(buf, 0); if (list_size + 2 != len || list_size % 2 != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Should never happen unless client duplicates the extension */ if (ssl->handshake->curves_tls_id != NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* Don't allow our peer to make us allocate too much memory, * and leave room for a final 0 */ our_size = list_size / 2 + 1; if (our_size > MBEDTLS_ECP_DP_MAX) { our_size = MBEDTLS_ECP_DP_MAX; } if ((curves_tls_id = mbedtls_calloc(our_size, sizeof(*curves_tls_id))) == NULL) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } ssl->handshake->curves_tls_id = curves_tls_id; p = buf + 2; while (list_size > 0 && our_size > 1) { uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE(p, 0); if (mbedtls_ssl_get_ecp_group_id_from_tls_id(curr_tls_id) != MBEDTLS_ECP_DP_NONE) { *curves_tls_id++ = curr_tls_id; our_size--; } list_size -= 2; p += 2; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t list_size; const unsigned char *p; if (len == 0 || (size_t) (buf[0] + 1) != len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } list_size = buf[0]; p = buf + 1; while (list_size > 0) { if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || p[0] == MBEDTLS_ECP_PF_COMPRESSED) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) ssl->handshake->ecdh_ctx.point_format = p[0]; #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */ #if !defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx, p[0]); #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(4, ("point format selected: %d", p[0])); return 0; } list_size--; p++; } return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_ecjpake_kkpp(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) if (ssl->handshake->psa_pake_ctx_is_ok != 1) #else if (mbedtls_ecjpake_check(&ssl->handshake->ecjpake_ctx) != 0) #endif /* MBEDTLS_USE_PSA_CRYPTO */ { MBEDTLS_SSL_DEBUG_MSG(3, ("skip ecjpake kkpp extension")); return 0; } #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, buf, len, MBEDTLS_ECJPAKE_ROUND_ONE)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round one", ret); mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return ret; } #else if ((ret = mbedtls_ecjpake_read_round_one(&ssl->handshake->ecjpake_ctx, buf, len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_one", ret); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Only mark the extension as OK when we're sure it is */ ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_max_fragment_length_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->session_negotiate->mfl_code = buf[0]; return 0; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_cid_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { size_t peer_cid_len; /* CID extension only makes sense in DTLS */ if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * struct { * opaque cid<0..2^8-1>; * } ConnectionId; */ if (len < 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } peer_cid_len = *buf++; len--; if (len != peer_cid_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Ignore CID if the user has disabled its use. */ if (ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED) { /* Leave ssl->handshake->cid_in_use in its default * value of MBEDTLS_SSL_CID_DISABLED. */ MBEDTLS_SSL_DEBUG_MSG(3, ("Client sent CID extension, but CID disabled")); return 0; } if (peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; memcpy(ssl->handshake->peer_cid, buf, peer_cid_len); MBEDTLS_SSL_DEBUG_MSG(3, ("Use of CID extension negotiated")); MBEDTLS_SSL_DEBUG_BUF(3, "Client CID", buf, peer_cid_len); return 0; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ((void) buf); if (ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; } return 0; } #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_extended_ms_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { if (len != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ((void) buf); if (ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) { ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; } return 0; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session session; mbedtls_ssl_session_init(&session); if (ssl->conf->f_ticket_parse == NULL || ssl->conf->f_ticket_write == NULL) { return 0; } /* Remember the client asked us to send a new ticket */ ssl->handshake->new_session_ticket = 1; MBEDTLS_SSL_DEBUG_MSG(3, ("ticket length: %" MBEDTLS_PRINTF_SIZET, len)); if (len == 0) { return 0; } #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket rejected: renegotiating")); return 0; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ /* * Failures are ok: just ignore the ticket and proceed. */ if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, &session, buf, len)) != 0) { mbedtls_ssl_session_free(&session); if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic")); } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired")); } else { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_parse", ret); } return 0; } /* * Keep the session ID sent by the client, since we MUST send it back to * inform them we're accepting the ticket (RFC 5077 section 3.4) */ session.id_len = ssl->session_negotiate->id_len; memcpy(&session.id, ssl->session_negotiate->id, session.id_len); mbedtls_ssl_session_free(ssl->session_negotiate); memcpy(ssl->session_negotiate, &session, sizeof(mbedtls_ssl_session)); /* Zeroize instead of free as we copied the content */ mbedtls_platform_zeroize(&session, sizeof(mbedtls_ssl_session)); MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from ticket")); ssl->handshake->resume = 1; /* Don't send a new ticket after all, this one is OK */ ssl->handshake->new_session_ticket = 0; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_DTLS_SRTP) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET; size_t i, j; size_t profile_length; uint16_t mki_length; /*! 2 bytes for profile length and 1 byte for mki len */ const size_t size_of_lengths = 3; /* If use_srtp is not configured, just ignore the extension */ if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->conf->dtls_srtp_profile_list == NULL) || (ssl->conf->dtls_srtp_profile_list_len == 0)) { return 0; } /* RFC5764 section 4.1.1 * uint8 SRTPProtectionProfile[2]; * * struct { * SRTPProtectionProfiles SRTPProtectionProfiles; * opaque srtp_mki<0..255>; * } UseSRTPData; * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; */ /* * Min length is 5: at least one protection profile(2 bytes) * and length(2 bytes) + srtp_mki length(1 byte) * Check here that we have at least 2 bytes of protection profiles length * and one of srtp_mki length */ if (len < size_of_lengths) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; /* first 2 bytes are protection profile length(in bytes) */ profile_length = (buf[0] << 8) | buf[1]; buf += 2; /* The profile length cannot be bigger than input buffer size - lengths fields */ if (profile_length > len - size_of_lengths || profile_length % 2 != 0) { /* profiles are 2 bytes long, so the length must be even */ mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * parse the extension list values are defined in * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml */ for (j = 0; j < profile_length; j += 2) { uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1]; client_protection = mbedtls_ssl_check_srtp_profile_value(protection_profile_value); if (client_protection != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_SSL_DEBUG_MSG(3, ("found srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( client_protection))); } else { continue; } /* check if suggested profile is in our list */ for (i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) { if (client_protection == ssl->conf->dtls_srtp_profile_list[i]) { ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; MBEDTLS_SSL_DEBUG_MSG(3, ("selected srtp profile: %s", mbedtls_ssl_get_srtp_profile_as_string( client_protection))); break; } } if (ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET) { break; } } buf += profile_length; /* buf points to the mki length */ mki_length = *buf; buf++; if (mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH || mki_length + profile_length + size_of_lengths != len) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Parse the mki only if present and mki is supported locally */ if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED && mki_length > 0) { ssl->dtls_srtp_info.mki_len = mki_length; memcpy(ssl->dtls_srtp_info.mki_value, buf, mki_length); MBEDTLS_SSL_DEBUG_BUF(3, "using mki", ssl->dtls_srtp_info.mki_value, ssl->dtls_srtp_info.mki_len); } return 0; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ /* * Auxiliary functions for ServerHello parsing and related actions */ #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * Return 0 if the given key uses one of the acceptable curves, -1 otherwise */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_check_key_curve(mbedtls_pk_context *pk, uint16_t *curves_tls_id) { uint16_t *curr_tls_id = curves_tls_id; mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk); mbedtls_ecp_group_id curr_grp_id; while (*curr_tls_id != 0) { curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); if (curr_grp_id == grp_id) { return 0; } curr_tls_id++; } return -1; } #endif /* MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED */ /* * Try picking a certificate for this ciphersuite, * return 0 on success and -1 on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_pick_cert(mbedtls_ssl_context *ssl, const mbedtls_ssl_ciphersuite_t *ciphersuite_info) { mbedtls_ssl_key_cert *cur, *list; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(ciphersuite_info); psa_key_usage_t pk_usage = mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(ciphersuite_info); #else mbedtls_pk_type_t pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); #endif /* MBEDTLS_USE_PSA_CRYPTO */ uint32_t flags; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_key_cert != NULL) { list = ssl->handshake->sni_key_cert; } else #endif list = ssl->conf->key_cert; int pk_alg_is_none = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) pk_alg_is_none = (pk_alg == PSA_ALG_NONE); #else pk_alg_is_none = (pk_alg == MBEDTLS_PK_NONE); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (pk_alg_is_none) { return 0; } MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite requires certificate")); if (list == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate")); return -1; } for (cur = list; cur != NULL; cur = cur->next) { flags = 0; MBEDTLS_SSL_DEBUG_CRT(3, "candidate certificate chain, certificate", cur->cert); int key_type_matches = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) key_type_matches = ((ssl->conf->f_async_sign_start != NULL || ssl->conf->f_async_decrypt_start != NULL || mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)) && mbedtls_pk_can_do_ext(&cur->cert->pk, pk_alg, pk_usage)); #else key_type_matches = ( mbedtls_pk_can_do_ext(cur->key, pk_alg, pk_usage)); #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #else key_type_matches = mbedtls_pk_can_do(&cur->cert->pk, pk_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (!key_type_matches) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: key type")); continue; } /* * This avoids sending the client a cert it'll reject based on * keyUsage or other extensions. * * It also allows the user to provision different certificates for * different uses based on keyUsage, eg if they want to avoid signing * and decrypting with the same RSA key. */ if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info, MBEDTLS_SSL_IS_SERVER, &flags) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: " "(extended) key usage extension")); continue; } #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) if (pk_alg == MBEDTLS_PK_ECDSA && ssl_check_key_curve(&cur->cert->pk, ssl->handshake->curves_tls_id) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: elliptic curve")); continue; } #endif /* If we get there, we got a winner */ break; } /* Do not update ssl->handshake->key_cert unless there is a match */ if (cur != NULL) { ssl->handshake->key_cert = cur; MBEDTLS_SSL_DEBUG_CRT(3, "selected certificate chain, certificate", ssl->handshake->key_cert->cert); return 0; } return -1; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* * Check if a given ciphersuite is suitable for use with our config/keys/etc * Sets ciphersuite_info only if the suite matches. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id, const mbedtls_ssl_ciphersuite_t **ciphersuite_info) { const mbedtls_ssl_ciphersuite_t *suite_info; #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_pk_type_t sig_type; #endif suite_info = mbedtls_ssl_ciphersuite_from_id(suite_id); if (suite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("trying ciphersuite: %#04x (%s)", (unsigned int) suite_id, suite_info->name)); if (suite_info->min_tls_version > ssl->tls_version || suite_info->max_tls_version < ssl->tls_version) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: version")); return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && (ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK) == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: ecjpake " "not configured or ext missing")); return 0; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ec(suite_info) && (ssl->handshake->curves_tls_id == NULL || ssl->handshake->curves_tls_id[0] == 0)) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: " "no common elliptic curve")); return 0; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) /* If the ciphersuite requires a pre-shared key and we don't * have one, skip it now rather than failing later */ if (mbedtls_ssl_ciphersuite_uses_psk(suite_info) && ssl_conf_has_psk_or_cb(ssl->conf) == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no pre-shared key")); return 0; } #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) /* * Final check: if ciphersuite requires us to have a * certificate/key of a particular type: * - select the appropriate certificate if we have one, or * - try the next ciphersuite if we don't * This must be done last since we modify the key_cert list. */ if (ssl_pick_cert(ssl, suite_info) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: " "no suitable certificate")); return 0; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* If the ciphersuite requires signing, check whether * a suitable hash algorithm is present. */ sig_type = mbedtls_ssl_get_ciphersuite_sig_alg(suite_info); if (sig_type != MBEDTLS_PK_NONE && mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( ssl, mbedtls_ssl_sig_from_pk_alg(sig_type)) == MBEDTLS_SSL_HASH_NONE) { MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite mismatch: no suitable hash algorithm " "for signature algorithm %u", (unsigned) sig_type)); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ *ciphersuite_info = suite_info; return 0; } /* This function doesn't alert on errors that happen early during ClientHello parsing because they might indicate that the client is not talking SSL/TLS at all and would not understand our alert. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_hello(mbedtls_ssl_context *ssl) { int ret, got_common_suite; size_t i, j; size_t ciph_offset, comp_offset, ext_offset; size_t msg_len, ciph_len, sess_len, comp_len, ext_len; #if defined(MBEDTLS_SSL_PROTO_DTLS) size_t cookie_offset, cookie_len; #endif unsigned char *buf, *p, *ext; #if defined(MBEDTLS_SSL_RENEGOTIATION) int renegotiation_info_seen = 0; #endif int handshake_failure = 0; const int *ciphersuites; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; /* If there is no signature-algorithm extension present, * we need to fall back to the default values for allowed * signature-hash pairs. */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) int sig_hash_alg_ext_present = 0; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); int renegotiating; #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) read_record_header: #endif /* * If renegotiating, then the input was read with mbedtls_ssl_read_record(), * otherwise read it ourselves manually in order to support SSLv2 * ClientHello, which doesn't use the same record layer format. * Otherwise in a scenario of TLS 1.3/TLS 1.2 version negotiation, the * ClientHello has been already fully fetched by the TLS 1.3 code and the * flag ssl->keep_current_message is raised. */ renegotiating = 0; #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE); #endif if (!renegotiating && !ssl->keep_current_message) { if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) { /* No alert on a read error. */ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } } buf = ssl->in_hdr; MBEDTLS_SSL_DEBUG_BUF(4, "record header", buf, mbedtls_ssl_in_hdr_len(ssl)); /* * TLS Client Hello * * Record layer: * 0 . 0 message type * 1 . 2 protocol version * 3 . 11 DTLS: epoch + record sequence number * 3 . 4 message length */ MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message type: %d", buf[0])); if (buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d", MBEDTLS_GET_UINT16_BE(ssl->in_len, 0))); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]", buf[1], buf[2])); /* For DTLS if this is the initial handshake, remember the client sequence * number to use it in our next message (RFC 6347 4.2.1) */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM #if defined(MBEDTLS_SSL_RENEGOTIATION) && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE #endif ) { /* Epoch should be 0 for initial handshakes */ if (ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } memcpy(&ssl->cur_out_ctr[2], ssl->in_ctr + 2, sizeof(ssl->cur_out_ctr) - 2); #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) if (mbedtls_ssl_dtls_replay_check(ssl) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("replayed record, discarding")); ssl->next_record_offset = 0; ssl->in_left = 0; goto read_record_header; } /* No MAC to check yet, so we can update right now */ mbedtls_ssl_dtls_replay_update(ssl); #endif } #endif /* MBEDTLS_SSL_PROTO_DTLS */ msg_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { /* Set by mbedtls_ssl_read_record() */ msg_len = ssl->in_hslen; } else #endif { if (ssl->keep_current_message) { ssl->keep_current_message = 0; } else { if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if ((ret = mbedtls_ssl_fetch_input(ssl, mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret); return ret; } /* Done reading this record, get ready for the next one */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl); } else #endif ssl->in_left = 0; } } buf = ssl->in_msg; MBEDTLS_SSL_DEBUG_BUF(4, "record contents", buf, msg_len); ret = ssl->handshake->update_checksum(ssl, buf, msg_len); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } /* * Handshake layer: * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 5 DTLS only: message sequence number * 6 . 8 DTLS only: fragment offset * 9 . 11 DTLS only: fragment length */ if (msg_len < mbedtls_ssl_hs_hdr_len(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake type: %d", buf[0])); if (buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } { size_t handshake_len = MBEDTLS_GET_UINT24_BE(buf, 1); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, handshake len.: %u", (unsigned) handshake_len)); /* The record layer has a record size limit of 2^14 - 1 and * fragmentation is not supported, so buf[1] should be zero. */ if (buf[1] != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != 0", (unsigned) buf[1])); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* We don't support fragmentation of ClientHello (yet?) */ if (msg_len != mbedtls_ssl_hs_hdr_len(ssl) + handshake_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message: %u != %u + %u", (unsigned) msg_len, (unsigned) mbedtls_ssl_hs_hdr_len(ssl), (unsigned) handshake_len)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { /* * Copy the client's handshake message_seq on initial handshakes, * check sequence number on renego. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { /* This couldn't be done in ssl_prepare_handshake_record() */ unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); if (cli_msg_seq != ssl->handshake->in_msg_seq) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: " "%u (expected %u)", cli_msg_seq, ssl->handshake->in_msg_seq)); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->handshake->in_msg_seq++; } else #endif { unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4); ssl->handshake->out_msg_seq = cli_msg_seq; ssl->handshake->in_msg_seq = cli_msg_seq + 1; } { /* * For now we don't support fragmentation, so make sure * fragment_offset == 0 and fragment_length == length */ size_t fragment_offset, fragment_length, length; fragment_offset = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6); fragment_length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9); length = MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1); MBEDTLS_SSL_DEBUG_MSG( 4, ("fragment_offset=%u fragment_length=%u length=%u", (unsigned) fragment_offset, (unsigned) fragment_length, (unsigned) length)); if (fragment_offset != 0 || length != fragment_length) { MBEDTLS_SSL_DEBUG_MSG(1, ("ClientHello fragmentation not supported")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } } } #endif /* MBEDTLS_SSL_PROTO_DTLS */ buf += mbedtls_ssl_hs_hdr_len(ssl); msg_len -= mbedtls_ssl_hs_hdr_len(ssl); /* * ClientHello layout: * 0 . 1 protocol version * 2 . 33 random bytes (starting with 4 bytes of Unix time) * 34 . 34 session id length (1 byte) * 35 . 34+x session id, where x = session id length from byte 34 * 35+x . 35+x DTLS only: cookie length (1 byte) * 36+x . .. DTLS only: cookie * .. . .. ciphersuite list length (2 bytes) * .. . .. ciphersuite list * .. . .. compression alg. list length (1 byte) * .. . .. compression alg. list * .. . .. extensions length (2 bytes, optional) * .. . .. extensions (optional) */ /* * Minimal length (with everything empty and extensions omitted) is * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can * read at least up to session id length without worrying. */ if (msg_len < 38) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Check and save the protocol version */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, version", buf, 2); ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf, ssl->conf->transport); ssl->session_negotiate->tls_version = ssl->tls_version; ssl->session_negotiate->endpoint = ssl->conf->endpoint; if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } /* * Save client random (inc. Unix time) */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", buf + 2, 32); memcpy(ssl->handshake->randbytes, buf + 2, 32); /* * Check the session ID length and save session ID */ sess_len = buf[34]; if (sess_len > sizeof(ssl->session_negotiate->id) || sess_len + 34 + 2 > msg_len) { /* 2 for cipherlist length field */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", buf + 35, sess_len); ssl->session_negotiate->id_len = sess_len; memset(ssl->session_negotiate->id, 0, sizeof(ssl->session_negotiate->id)); memcpy(ssl->session_negotiate->id, buf + 35, ssl->session_negotiate->id_len); /* * Check the cookie length and content */ #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { cookie_offset = 35 + sess_len; cookie_len = buf[cookie_offset]; if (cookie_offset + 1 + cookie_len + 2 > msg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", buf + cookie_offset + 1, cookie_len); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) if (ssl->conf->f_cookie_check != NULL #if defined(MBEDTLS_SSL_RENEGOTIATION) && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE #endif ) { if (ssl->conf->f_cookie_check(ssl->conf->p_cookie, buf + cookie_offset + 1, cookie_len, ssl->cli_id, ssl->cli_id_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification failed")); ssl->handshake->cookie_verify_result = 1; } else { MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification passed")); ssl->handshake->cookie_verify_result = 0; } } else #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ { /* We know we didn't send a cookie, so it should be empty */ if (cookie_len != 0) { /* This may be an attacker's probe, so don't send an alert */ MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MSG(2, ("cookie verification skipped")); } /* * Check the ciphersuitelist length (will be parsed later) */ ciph_offset = cookie_offset + 1 + cookie_len; } else #endif /* MBEDTLS_SSL_PROTO_DTLS */ ciph_offset = 35 + sess_len; ciph_len = MBEDTLS_GET_UINT16_BE(buf, ciph_offset); if (ciph_len < 2 || ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ (ciph_len % 2) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist", buf + ciph_offset + 2, ciph_len); /* * Check the compression algorithm's length. * The list contents are ignored because implementing * MBEDTLS_SSL_COMPRESS_NULL is mandatory and is the only * option supported by Mbed TLS. */ comp_offset = ciph_offset + 2 + ciph_len; comp_len = buf[comp_offset]; if (comp_len < 1 || comp_len > 16 || comp_len + comp_offset + 1 > msg_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, compression", buf + comp_offset + 1, comp_len); /* * Check the extension length */ ext_offset = comp_offset + 1 + comp_len; if (msg_len > ext_offset) { if (msg_len < ext_offset + 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ext_len = MBEDTLS_GET_UINT16_BE(buf, ext_offset); if (msg_len != ext_offset + 2 + ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } } else { ext_len = 0; } ext = buf + ext_offset + 2; MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", ext, ext_len); while (ext_len != 0) { unsigned int ext_id; unsigned int ext_size; if (ext_len < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ext_id = MBEDTLS_GET_UINT16_BE(ext, 0); ext_size = MBEDTLS_GET_UINT16_BE(ext, 2); if (ext_size + 4 > ext_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } switch (ext_id) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) case MBEDTLS_TLS_EXT_SERVERNAME: MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); ret = mbedtls_ssl_parse_server_name_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: MBEDTLS_SSL_DEBUG_MSG(3, ("found renegotiation extension")); #if defined(MBEDTLS_SSL_RENEGOTIATION) renegotiation_info_seen = 1; #endif ret = ssl_parse_renegotiation_info(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); ret = mbedtls_ssl_parse_sig_alg_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } sig_hash_alg_ext_present = 1; break; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported elliptic curves extension")); ret = ssl_parse_supported_groups_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported point formats extension")); ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; ret = ssl_parse_supported_point_formats(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: MBEDTLS_SSL_DEBUG_MSG(3, ("found ecjpake kkpp extension")); ret = ssl_parse_ecjpake_kkpp(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: MBEDTLS_SSL_DEBUG_MSG(3, ("found max fragment length extension")); ret = ssl_parse_max_fragment_length_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) case MBEDTLS_TLS_EXT_CID: MBEDTLS_SSL_DEBUG_MSG(3, ("found CID extension")); ret = ssl_parse_cid_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: MBEDTLS_SSL_DEBUG_MSG(3, ("found encrypt then mac extension")); ret = ssl_parse_encrypt_then_mac_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: MBEDTLS_SSL_DEBUG_MSG(3, ("found extended master secret extension")); ret = ssl_parse_extended_ms_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_TLS_EXT_SESSION_TICKET: MBEDTLS_SSL_DEBUG_MSG(3, ("found session ticket extension")); ret = ssl_parse_session_ticket_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); ret = mbedtls_ssl_parse_alpn_ext(ssl, ext + 4, ext + 4 + ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_DTLS_SRTP) case MBEDTLS_TLS_EXT_USE_SRTP: MBEDTLS_SSL_DEBUG_MSG(3, ("found use_srtp extension")); ret = ssl_parse_use_srtp_ext(ssl, ext + 4, ext_size); if (ret != 0) { return ret; } break; #endif /* MBEDTLS_SSL_DTLS_SRTP */ default: MBEDTLS_SSL_DEBUG_MSG(3, ("unknown extension found: %u (ignoring)", ext_id)); } ext_len -= 4 + ext_size; ext += 4 + ext_size; } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) /* * Try to fall back to default hash SHA1 if the client * hasn't provided any preferred signature-hash combinations. */ if (!sig_hash_alg_ext_present) { uint16_t *received_sig_algs = ssl->handshake->received_sig_algs; const uint16_t default_sig_algs[] = { #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA1), #endif #if defined(MBEDTLS_RSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA1), #endif MBEDTLS_TLS_SIG_NONE }; MBEDTLS_STATIC_ASSERT(sizeof(default_sig_algs) / sizeof(default_sig_algs[0]) <= MBEDTLS_RECEIVED_SIG_ALGS_SIZE, "default_sig_algs is too big"); memcpy(received_sig_algs, default_sig_algs, sizeof(default_sig_algs)); } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ /* * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */ for (i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2) { if (p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO) { MBEDTLS_SSL_DEBUG_MSG(3, ("received TLS_EMPTY_RENEGOTIATION_INFO ")); #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) { MBEDTLS_SSL_DEBUG_MSG(1, ("received RENEGOTIATION SCSV " "during renegotiation")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; break; } } /* * Renegotiation security checks */ if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation, breaking off handshake")); handshake_failure = 1; } #if defined(MBEDTLS_SSL_RENEGOTIATION) else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && renegotiation_info_seen == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension missing (secure)")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) { MBEDTLS_SSL_DEBUG_MSG(1, ("legacy renegotiation not allowed")); handshake_failure = 1; } else if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && renegotiation_info_seen == 1) { MBEDTLS_SSL_DEBUG_MSG(1, ("renegotiation_info extension present (legacy)")); handshake_failure = 1; } #endif /* MBEDTLS_SSL_RENEGOTIATION */ if (handshake_failure == 1) { mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* * Server certification selection (after processing TLS extensions) */ if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); return ret; } #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) ssl->handshake->sni_name = NULL; ssl->handshake->sni_name_len = 0; #endif /* * Search for a matching ciphersuite * (At the end because we need information from the EC-based extensions * and certificate from the SNI callback triggered by the SNI extension * or certificate from server certificate selection callback.) */ got_common_suite = 0; ciphersuites = ssl->conf->ciphersuite_list; ciphersuite_info = NULL; if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) { for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { for (i = 0; ciphersuites[i] != 0; i++) { if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { continue; } got_common_suite = 1; if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], &ciphersuite_info)) != 0) { return ret; } if (ciphersuite_info != NULL) { goto have_ciphersuite; } } } } else { for (i = 0; ciphersuites[i] != 0; i++) { for (j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2) { if (MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i]) { continue; } got_common_suite = 1; if ((ret = ssl_ciphersuite_match(ssl, ciphersuites[i], &ciphersuite_info)) != 0) { return ret; } if (ciphersuite_info != NULL) { goto have_ciphersuite; } } } } if (got_common_suite) { MBEDTLS_SSL_DEBUG_MSG(1, ("got ciphersuites in common, " "but none of them usable")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("got no ciphersuites in common")); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } have_ciphersuite: MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %s", ciphersuite_info->name)); ssl->session_negotiate->ciphersuite = ciphersuites[i]; ssl->handshake->ciphersuite_info = ciphersuite_info; ssl->state++; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_recv_flight_completed(ssl); } #endif /* Debugging-only output for testsuite */ #if defined(MBEDTLS_DEBUG_C) && \ defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg(ciphersuite_info); if (sig_alg != MBEDTLS_PK_NONE) { unsigned int sig_hash = mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello v3, signature_algorithm ext: %u", sig_hash)); } else { MBEDTLS_SSL_DEBUG_MSG(3, ("no hash algorithm for signature algorithm " "%u - should not happen", (unsigned) sig_alg)); } #endif MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello")); return 0; } #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) static void ssl_write_cid_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; size_t ext_len; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; /* Skip writing the extension if we don't want to use it or if * the client hasn't offered it. */ if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED) { return; } /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX * which is at most 255, so the increment cannot overflow. */ if (end < p || (size_t) (end - p) < (unsigned) (ssl->own_cid_len + 5)) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding CID extension")); /* * struct { * opaque cid<0..2^8-1>; * } ConnectionId; */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_CID, p, 0); p += 2; ext_len = (size_t) ssl->own_cid_len + 1; MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2; *p++ = (uint8_t) ssl->own_cid_len; memcpy(p, ssl->own_cid, ssl->own_cid_len); *olen = ssl->own_cid_len + 5; } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) static void ssl_write_encrypt_then_mac_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; const mbedtls_ssl_ciphersuite_t *suite = NULL; /* * RFC 7366: "If a server receives an encrypt-then-MAC request extension * from a client and then selects a stream or Authenticated Encryption * with Associated Data (AEAD) ciphersuite, it MUST NOT send an * encrypt-then-MAC response extension back to the client." */ suite = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); if (suite == NULL) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; } else { mbedtls_ssl_mode_t ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite( ssl->session_negotiate->encrypt_then_mac, suite); if (ssl_mode != MBEDTLS_SSL_MODE_CBC_ETM) { ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED; } } if (ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding encrypt then mac extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; } #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) static void ssl_write_extended_ms_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding extended master secret " "extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; } #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) static void ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->handshake->new_session_ticket == 0) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding session ticket extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0); p += 2; *p++ = 0x00; *p++ = 0x00; *olen = 4; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ static void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, secure renegotiation extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0); p += 2; #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { *p++ = 0x00; *p++ = (ssl->verify_data_len * 2 + 1) & 0xFF; *p++ = ssl->verify_data_len * 2 & 0xFF; memcpy(p, ssl->peer_verify_data, ssl->verify_data_len); p += ssl->verify_data_len; memcpy(p, ssl->own_verify_data, ssl->verify_data_len); p += ssl->verify_data_len; } else #endif /* MBEDTLS_SSL_RENEGOTIATION */ { *p++ = 0x00; *p++ = 0x01; *p++ = 0x00; } *olen = (size_t) (p - buf); } #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) static void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; if (ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, max_fragment_length extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0); p += 2; *p++ = 0x00; *p++ = 1; *p++ = ssl->session_negotiate->mfl_code; *olen = 5; } #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { unsigned char *p = buf; ((void) ssl); if ((ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT) == 0) { *olen = 0; return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, supported_point_formats extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0); p += 2; *p++ = 0x00; *p++ = 2; *p++ = 1; *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; *olen = 6; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; size_t kkpp_len; *olen = 0; /* Skip costly computation if not needed */ if (ssl->handshake->ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_ECJPAKE) { return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, ecjpake kkpp extension")); if (end - p < 4) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return; } MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0); p += 2; #if defined(MBEDTLS_USE_PSA_CRYPTO) ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, p + 2, (size_t) (end - p - 2), &kkpp_len, MBEDTLS_ECJPAKE_ROUND_ONE); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return; } #else ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx, p + 2, (size_t) (end - p - 2), &kkpp_len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret); return; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_PUT_UINT16_BE(kkpp_len, p, 0); p += 2; *olen = kkpp_len + 4; } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_DTLS_SRTP) && defined(MBEDTLS_SSL_PROTO_DTLS) static void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl, unsigned char *buf, size_t *olen) { size_t mki_len = 0, ext_len = 0; uint16_t profile_value = 0; const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; *olen = 0; if ((ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) || (ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET)) { return; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding use_srtp extension")); if (ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED) { mki_len = ssl->dtls_srtp_info.mki_len; } /* The extension total size is 9 bytes : * - 2 bytes for the extension tag * - 2 bytes for the total size * - 2 bytes for the protection profile length * - 2 bytes for the protection profile * - 1 byte for the mki length * + the actual mki length * Check we have enough room in the output buffer */ if ((size_t) (end - buf) < mki_len + 9) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return; } /* extension */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0); /* * total length 5 and mki value: only one profile(2 bytes) * and length(2 bytes) and srtp_mki ) */ ext_len = 5 + mki_len; MBEDTLS_PUT_UINT16_BE(ext_len, buf, 2); /* protection profile length: 2 */ buf[4] = 0x00; buf[5] = 0x02; profile_value = mbedtls_ssl_check_srtp_profile_value( ssl->dtls_srtp_info.chosen_dtls_srtp_profile); if (profile_value != MBEDTLS_TLS_SRTP_UNSET) { MBEDTLS_PUT_UINT16_BE(profile_value, buf, 6); } else { MBEDTLS_SSL_DEBUG_MSG(1, ("use_srtp extension invalid profile")); return; } buf[8] = mki_len & 0xFF; memcpy(&buf[9], ssl->dtls_srtp_info.mki_value, mki_len); *olen = 9 + mki_len; } #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = ssl->out_msg + 4; unsigned char *cookie_len_byte; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello verify request")); /* * struct { * ProtocolVersion server_version; * opaque cookie<0..2^8-1>; * } HelloVerifyRequest; */ /* The RFC is not clear on this point, but sending the actual negotiated * version looks like the most interoperable thing to do. */ mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version); MBEDTLS_SSL_DEBUG_BUF(3, "server version", p, 2); p += 2; /* If we get here, f_cookie_check is not null */ if (ssl->conf->f_cookie_write == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("inconsistent cookie callbacks")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Skip length byte until we know the length */ cookie_len_byte = p++; if ((ret = ssl->conf->f_cookie_write(ssl->conf->p_cookie, &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, ssl->cli_id, ssl->cli_id_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_cookie_write", ret); return ret; } *cookie_len_byte = (unsigned char) (p - (cookie_len_byte + 1)); MBEDTLS_SSL_DEBUG_BUF(3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte); ssl->out_msglen = (size_t) (p - ssl->out_msg); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello verify request")); return 0; } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ static void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl) { int ret; mbedtls_ssl_session session_tmp; mbedtls_ssl_session * const session = ssl->session_negotiate; /* Resume is 0 by default, see ssl_handshake_init(). * It may be already set to 1 by ssl_parse_session_ticket_ext(). */ if (ssl->handshake->resume == 1) { return; } if (session->id_len == 0) { return; } if (ssl->conf->f_get_cache == NULL) { return; } #if defined(MBEDTLS_SSL_RENEGOTIATION) if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) { return; } #endif mbedtls_ssl_session_init(&session_tmp); ret = ssl->conf->f_get_cache(ssl->conf->p_cache, session->id, session->id_len, &session_tmp); if (ret != 0) { goto exit; } if (session->ciphersuite != session_tmp.ciphersuite) { /* Mismatch between cached and negotiated session */ goto exit; } /* Move semantics */ mbedtls_ssl_session_free(session); *session = session_tmp; memset(&session_tmp, 0, sizeof(session_tmp)); MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from cache")); ssl->handshake->resume = 1; exit: mbedtls_ssl_session_free(&session_tmp); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_hello(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_time_t t; #endif int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen, ext_len = 0, n; unsigned char *buf, *p; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello")); #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && ssl->handshake->cookie_verify_result != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("client hello was not authenticated")); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); return ssl_write_hello_verify_request(ssl); } #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ /* * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 5 protocol version * 6 . 9 UNIX time() * 10 . 37 random bytes */ buf = ssl->out_msg; p = buf + 4; mbedtls_ssl_write_version(p, ssl->conf->transport, ssl->tls_version); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen version: [%d:%d]", buf[4], buf[5])); #if defined(MBEDTLS_HAVE_TIME) t = mbedtls_time(NULL); MBEDTLS_PUT_UINT32_BE(t, p, 0); p += 4; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, current time: %" MBEDTLS_PRINTF_LONGLONG, (long long) t)); #else if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 4)) != 0) { return ret; } p += 4; #endif /* MBEDTLS_HAVE_TIME */ if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 20)) != 0) { return ret; } p += 20; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) /* * RFC 8446 * TLS 1.3 has a downgrade protection mechanism embedded in the server's * random value. TLS 1.3 servers which negotiate TLS 1.2 or below in * response to a ClientHello MUST set the last 8 bytes of their Random * value specially in their ServerHello. */ if (mbedtls_ssl_conf_is_tls13_enabled(ssl->conf)) { static const unsigned char magic_tls12_downgrade_string[] = { 'D', 'O', 'W', 'N', 'G', 'R', 'D', 1 }; MBEDTLS_STATIC_ASSERT( sizeof(magic_tls12_downgrade_string) == 8, "magic_tls12_downgrade_string does not have the expected size"); memcpy(p, magic_tls12_downgrade_string, sizeof(magic_tls12_downgrade_string)); } else #endif { if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 8)) != 0) { return ret; } } p += 8; memcpy(ssl->handshake->randbytes + 32, buf + 6, 32); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", buf + 6, 32); ssl_handle_id_based_session_resumption(ssl); if (ssl->handshake->resume == 0) { /* * New session, create a new session id, * unless we're about to issue a session ticket */ ssl->state++; #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->handshake->new_session_ticket != 0) { ssl->session_negotiate->id_len = n = 0; memset(ssl->session_negotiate->id, 0, 32); } else #endif /* MBEDTLS_SSL_SESSION_TICKETS */ { ssl->session_negotiate->id_len = n = 32; if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, ssl->session_negotiate->id, n)) != 0) { return ret; } } } else { /* * Resuming a session */ n = ssl->session_negotiate->id_len; ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } } /* * 38 . 38 session id length * 39 . 38+n session id * 39+n . 40+n chosen ciphersuite * 41+n . 41+n chosen compression alg. * 42+n . 43+n extensions length * 44+n . 43+n+m extensions */ *p++ = (unsigned char) ssl->session_negotiate->id_len; memcpy(p, ssl->session_negotiate->id, ssl->session_negotiate->id_len); p += ssl->session_negotiate->id_len; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n)); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, session id", buf + 39, n); MBEDTLS_SSL_DEBUG_MSG(3, ("%s session has been resumed", ssl->handshake->resume ? "a" : "no")); MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); p += 2; *p++ = MBEDTLS_BYTE_0(MBEDTLS_SSL_COMPRESS_NULL); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s", mbedtls_ssl_get_ciphersuite_name(ssl->session_negotiate->ciphersuite))); MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, compress alg.: 0x%02X", (unsigned int) MBEDTLS_SSL_COMPRESS_NULL)); /* * First write extensions, then the total length */ ssl_write_renegotiation_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ssl_write_max_fragment_length_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) ssl_write_cid_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM) ssl_write_encrypt_then_mac_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) ssl_write_extended_ms_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) ssl_write_session_ticket_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) const mbedtls_ssl_ciphersuite_t *suite = mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite); if (suite != NULL && mbedtls_ssl_ciphersuite_uses_ec(suite)) { ssl_write_supported_point_formats_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; } #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ssl_write_ecjpake_kkpp_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif #if defined(MBEDTLS_SSL_ALPN) unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4; if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen)) != 0) { return ret; } ext_len += olen; #endif #if defined(MBEDTLS_SSL_DTLS_SRTP) ssl_write_use_srtp_ext(ssl, p + 2 + ext_len, &olen); ext_len += olen; #endif MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len)); if (ext_len > 0) { MBEDTLS_PUT_UINT16_BE(ext_len, p, 0); p += 2 + ext_len; } ssl->out_msglen = (size_t) (p - buf); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; ret = mbedtls_ssl_write_handshake_msg(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); return ret; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; uint16_t dn_size, total_dn_size; /* excluding length bytes */ size_t ct_len, sa_len; /* including length bytes */ unsigned char *buf, *p; const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; const mbedtls_x509_crt *crt; int authmode; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); ssl->state++; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { authmode = ssl->handshake->sni_authmode; } else #endif authmode = ssl->conf->authmode; if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info) || authmode == MBEDTLS_SSL_VERIFY_NONE) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); return 0; } /* * 0 . 0 handshake type * 1 . 3 handshake length * 4 . 4 cert type count * 5 .. m-1 cert types * m .. m+1 sig alg length (TLS 1.2 only) * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) * n .. n+1 length of all DNs * n+2 .. n+3 length of DN 1 * n+4 .. ... Distinguished Name #1 * ... .. ... length of DN 2, etc. */ buf = ssl->out_msg; p = buf + 4; /* * Supported certificate types * * ClientCertificateType certificate_types<1..2^8-1>; * enum { (255) } ClientCertificateType; */ ct_len = 0; #if defined(MBEDTLS_RSA_C) p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; #endif p[0] = (unsigned char) ct_len++; p += ct_len; sa_len = 0; /* * Add signature_algorithms for verify (TLS 1.2) * * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * enum { (255) } HashAlgorithm; * enum { (255) } SignatureAlgorithm; */ const uint16_t *sig_alg = mbedtls_ssl_get_sig_algs(ssl); if (sig_alg == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *sig_alg != MBEDTLS_TLS_SIG_NONE; sig_alg++) { unsigned char hash = MBEDTLS_BYTE_1(*sig_alg); if (mbedtls_ssl_set_calc_verify_md(ssl, hash)) { continue; } if (!mbedtls_ssl_sig_alg_is_supported(ssl, *sig_alg)) { continue; } /* Write elements at offsets starting from 1 (offset 0 is for the * length). Thus the offset of each element is the length of the * partial list including that element. */ sa_len += 2; MBEDTLS_PUT_UINT16_BE(*sig_alg, p, sa_len); } /* Fill in list length. */ MBEDTLS_PUT_UINT16_BE(sa_len, p, 0); sa_len += 2; p += sa_len; /* * DistinguishedName certificate_authorities<0..2^16-1>; * opaque DistinguishedName<1..2^16-1>; */ p += 2; total_dn_size = 0; if (ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED) { /* NOTE: If trusted certificates are provisioned * via a CA callback (configured through * `mbedtls_ssl_conf_ca_cb()`, then the * CertificateRequest is currently left empty. */ #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->dn_hints != NULL) { crt = ssl->handshake->dn_hints; } else #endif if (ssl->conf->dn_hints != NULL) { crt = ssl->conf->dn_hints; } else #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_ca_chain != NULL) { crt = ssl->handshake->sni_ca_chain; } else #endif crt = ssl->conf->ca_chain; while (crt != NULL && crt->version != 0) { /* It follows from RFC 5280 A.1 that this length * can be represented in at most 11 bits. */ dn_size = (uint16_t) crt->subject_raw.len; if (end < p || (size_t) (end - p) < 2 + (size_t) dn_size) { MBEDTLS_SSL_DEBUG_MSG(1, ("skipping CAs: buffer too short")); break; } MBEDTLS_PUT_UINT16_BE(dn_size, p, 0); p += 2; memcpy(p, crt->subject_raw.p, dn_size); p += dn_size; MBEDTLS_SSL_DEBUG_BUF(3, "requested DN", p - dn_size, dn_size); total_dn_size += (unsigned short) (2 + dn_size); crt = crt->next; } } ssl->out_msglen = (size_t) (p - buf); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len); ret = mbedtls_ssl_write_handshake_msg(ssl); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)) #if defined(MBEDTLS_USE_PSA_CRYPTO) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_pk_context *pk; mbedtls_pk_type_t pk_type; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; unsigned char buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)]; size_t key_len; #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) uint16_t tls_id = 0; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; mbedtls_ecp_group_id grp_id; mbedtls_ecp_keypair *key; #endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */ pk = mbedtls_ssl_own_key(ssl); if (pk == NULL) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } pk_type = mbedtls_pk_get_type(pk); switch (pk_type) { case MBEDTLS_PK_OPAQUE: #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) { return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } /* Get the attributes of the key previously parsed by PK module in * order to extract its type and length (in bits). */ status = psa_get_key_attributes(pk->priv_id, &key_attributes); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes); ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes); if (pk_type == MBEDTLS_PK_OPAQUE) { /* Opaque key is created by the user (externally from Mbed TLS) * so we assume it already has the right algorithm and flags * set. Just copy its ID as reference. */ ssl->handshake->xxdh_psa_privkey = pk->priv_id; ssl->handshake->xxdh_psa_privkey_is_external = 1; } else { /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK * module and only have ECDSA capabilities. Since we need * them for ECDH later, we export and then re-import them with * proper flags and algorithm. Of course We also set key's type * and bits that we just got above. */ key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type)); psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits); status = psa_export_key(pk->priv_id, buf, sizeof(buf), &key_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_import_key(&key_attributes, buf, key_len, &ssl->handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } /* Set this key as owned by the TLS library: it will be its duty * to clear it exit. */ ssl->handshake->xxdh_psa_privkey_is_external = 0; } ret = 0; break; #if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECDSA: key = mbedtls_pk_ec_rw(*pk); grp_id = mbedtls_pk_get_ec_group_id(pk); if (grp_id == MBEDTLS_ECP_DP_NONE) { return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; } tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id); if (tls_id == 0) { /* This elliptic curve is not supported */ return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* If the above conversion to TLS ID was fine, then also this one will be, so there is no need to check the return value here */ mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type, &ssl->handshake->xxdh_psa_bits); ssl->handshake->xxdh_psa_type = key_type; key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type)); psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits); ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf)); if (ret != 0) { mbedtls_platform_zeroize(buf, sizeof(buf)); break; } status = psa_import_key(&key_attributes, buf, key_len, &ssl->handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); mbedtls_platform_zeroize(buf, sizeof(buf)); break; } mbedtls_platform_zeroize(buf, sizeof(buf)); ret = 0; break; #endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */ default: ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } exit: psa_reset_key_attributes(&key_attributes); mbedtls_platform_zeroize(buf, sizeof(buf)); return ret; } #else /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl); if (private_key == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no server private key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_ECKEY)) { MBEDTLS_SSL_DEBUG_MSG(1, ("server key not ECDH capable")); return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH; } if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, mbedtls_pk_ec_ro(*mbedtls_ssl_own_key(ssl)), MBEDTLS_ECDH_OURS)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret); return ret; } return 0; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_resume_server_key_exchange(mbedtls_ssl_context *ssl, size_t *signature_len) { /* Append the signature to ssl->out_msg, leaving 2 bytes for the * signature length which will be added in ssl_write_server_key_exchange * after the call to ssl_prepare_server_key_exchange. * ssl_write_server_key_exchange also takes care of incrementing * ssl->out_msglen. */ unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; size_t sig_max_len = (ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN - sig_start); int ret = ssl->conf->f_async_resume(ssl, sig_start, signature_len, sig_max_len); if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { ssl->handshake->async_in_progress = 0; mbedtls_ssl_set_async_operation_data(ssl, NULL); } MBEDTLS_SSL_DEBUG_RET(2, "ssl_resume_server_key_exchange", ret); return ret; } #endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ /* Prepare the ServerKeyExchange message, up to and including * calculating the signature if any, but excluding formatting the * signature and sending the message. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl, size_t *signature_len) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) unsigned char *dig_signed = NULL; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ (void) ciphersuite_info; /* unused in some configurations */ #if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) (void) signature_len; #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf); #else size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf); #endif #endif ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ /* * * Part 1: Provide key exchange parameters for chosen ciphersuite. * */ /* * - ECJPAKE key exchanges */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *out_p = ssl->out_msg + ssl->out_msglen; unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen; size_t output_offset = 0; size_t output_len = 0; /* * The first 3 bytes are: * [0] MBEDTLS_ECP_TLS_NAMED_CURVE * [1, 2] elliptic curve's TLS ID * * However since we only support secp256r1 for now, we hardcode its * TLS ID here */ uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( MBEDTLS_ECP_DP_SECP256R1); if (tls_id == 0) { return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE; MBEDTLS_PUT_UINT16_BE(tls_id, out_p, 1); output_offset += 3; ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx, out_p + output_offset, end_p - out_p - output_offset, &output_len, MBEDTLS_ECJPAKE_ROUND_TWO); if (ret != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_output", ret); return ret; } output_offset += output_len; ssl->out_msglen += output_offset; #else size_t len = 0; ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, ssl->out_msg + ssl->out_msglen, MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_two", ret); return ret; } ssl->out_msglen += len; #endif /* MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ /* * For (EC)DHE key exchanges with PSK, parameters are prefixed by support * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, * we use empty support identity hints here. **/ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { ssl->out_msg[ssl->out_msglen++] = 0x00; ssl->out_msg[ssl->out_msglen++] = 0x00; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ /* * - DHE key exchanges */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_dhe(ciphersuite_info)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; if (ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("no DH parameters set")); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * Ephemeral DH parameters: * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ if ((ret = mbedtls_dhm_set_group(&ssl->handshake->dhm_ctx, &ssl->conf->dhm_P, &ssl->conf->dhm_G)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_set_group", ret); return ret; } if ((ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, (int) mbedtls_dhm_get_len(&ssl->handshake->dhm_ctx), ssl->out_msg + ssl->out_msglen, &len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_make_params", ret); return ret; } #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif ssl->out_msglen += len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: X ", &ssl->handshake->dhm_ctx.X); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: P ", &ssl->handshake->dhm_ctx.P); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: G ", &ssl->handshake->dhm_ctx.G); MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GX", &ssl->handshake->dhm_ctx.GX); } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */ /* * - ECDHE key exchanges */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ecdhe(ciphersuite_info)) { /* * Ephemeral ECDH parameters: * * struct { * ECParameters curve_params; * ECPoint public; * } ServerECDHParams; */ uint16_t *curr_tls_id = ssl->handshake->curves_tls_id; const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* Match our preference list against the offered curves */ if ((group_list == NULL) || (curr_tls_id == NULL)) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *group_list != 0; group_list++) { for (curr_tls_id = ssl->handshake->curves_tls_id; *curr_tls_id != 0; curr_tls_id++) { if (*curr_tls_id == *group_list) { goto curve_matching_done; } } } curve_matching_done: if (*curr_tls_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching curve for ECDHE")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_MSG(2, ("ECDHE curve: %s", mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id))); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_key_attributes_t key_attributes; mbedtls_ssl_handshake_params *handshake = ssl->handshake; uint8_t *p = ssl->out_msg + ssl->out_msglen; const size_t header_size = 4; // curve_type(1), namedcurve(2), // data length(1) const size_t data_length_size = 1; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; size_t ec_bits = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation.")); /* Convert EC's TLS ID to PSA key type. */ if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id, &key_type, &ec_bits) == PSA_ERROR_NOT_SUPPORTED) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid ecc group parse.")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } handshake->xxdh_psa_type = key_type; handshake->xxdh_psa_bits = ec_bits; key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* * ECParameters curve_params * * First byte is curve_type, always named_curve */ *p++ = MBEDTLS_ECP_TLS_NAMED_CURVE; /* * Next two bytes are the namedcurve value */ MBEDTLS_PUT_UINT16_BE(*curr_tls_id, p, 0); p += 2; /* Generate ECDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); return ret; } /* * ECPoint public * * First byte is data length. * It will be filled later. p holds now the data length location. */ /* Export the public part of the ECDH private key from PSA. * Make one byte space for the length. */ unsigned char *own_pubkey = p + data_length_size; size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - (own_pubkey - ssl->out_msg)); status = psa_export_public_key(handshake->xxdh_psa_privkey, own_pubkey, own_pubkey_max_len, &len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); (void) psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } /* Store the length of the exported public key. */ *p = (uint8_t) len; /* Determine full message length. */ len += header_size; #else mbedtls_ecp_group_id curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id(*curr_tls_id); if ((ret = mbedtls_ecdh_setup(&ssl->handshake->ecdh_ctx, curr_grp_id)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecp_group_load", ret); return ret; } if ((ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, ssl->out_msg + ssl->out_msglen, MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_make_params", ret); return ret; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Q); #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) dig_signed = ssl->out_msg + ssl->out_msglen; #endif ssl->out_msglen += len; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ /* * * Part 2: For key exchanges involving the server signing the * exchange parameters, compute and add the signature here. * */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) { if (dig_signed == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } size_t dig_signed_len = (size_t) (ssl->out_msg + ssl->out_msglen - dig_signed); size_t hashlen = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * 2.1: Choose hash algorithm: * For TLS 1.2, obey signature-hash-algorithm extension * to choose appropriate hash. */ mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info); unsigned char sig_hash = (unsigned char) mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg( ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg)); mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash); /* For TLS 1.2, obey signature-hash-algorithm extension * (RFC 5246, Sec. 7.4.1.4.1). */ if (sig_alg == MBEDTLS_PK_NONE || md_alg == MBEDTLS_MD_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); /* (... because we choose a cipher suite * only if there is a matching hash.) */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("pick hash algorithm %u for signing", (unsigned) md_alg)); /* * 2.2: Compute the hash to be signed */ if (md_alg != MBEDTLS_MD_NONE) { ret = mbedtls_ssl_get_key_exchange_md_tls1_2(ssl, hash, &hashlen, dig_signed, dig_signed_len, md_alg); if (ret != 0) { return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "parameters hash", hash, hashlen); /* * 2.3: Compute and add the signature */ /* * We need to specify signature and hash algorithm explicitly through * a prefix to the signature. * * struct { * HashAlgorithm hash; * SignatureAlgorithm signature; * } SignatureAndHashAlgorithm; * * struct { * SignatureAndHashAlgorithm algorithm; * opaque signature<0..2^16-1>; * } DigitallySigned; * */ ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_hash_from_md_alg(md_alg); ssl->out_msg[ssl->out_msglen++] = mbedtls_ssl_sig_from_pk_alg(sig_alg); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_sign_start != NULL) { ret = ssl->conf->f_async_sign_start(ssl, mbedtls_ssl_own_cert(ssl), md_alg, hash, hashlen); switch (ret) { case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: /* act as if f_async_sign was null */ break; case 0: ssl->handshake->async_in_progress = 1; return ssl_resume_server_key_exchange(ssl, signature_len); case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: ssl->handshake->async_in_progress = 1; return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS; default: MBEDTLS_SSL_DEBUG_RET(1, "f_async_sign_start", ret); return ret; } } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if (mbedtls_ssl_own_key(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no private key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } /* Append the signature to ssl->out_msg, leaving 2 bytes for the * signature length which will be added in ssl_write_server_key_exchange * after the call to ssl_prepare_server_key_exchange. * ssl_write_server_key_exchange also takes care of incrementing * ssl->out_msglen. */ if ((ret = mbedtls_pk_sign(mbedtls_ssl_own_key(ssl), md_alg, hash, hashlen, ssl->out_msg + ssl->out_msglen + 2, out_buf_len - ssl->out_msglen - 2, signature_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_sign", ret); return ret; } } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ return 0; } /* Prepare the ServerKeyExchange message and send it. For ciphersuites * that do not include a ServerKeyExchange message, do nothing. Either * way, if successful, move on to the next step in the SSL state * machine. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t signature_len = 0; #if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server key exchange")); #if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) /* Extract static ECDH parameters and abort if ServerKeyExchange * is not needed. */ if (mbedtls_ssl_ciphersuite_no_pfs(ciphersuite_info)) { /* For suites involving ECDH, extract DH parameters * from certificate at this point. */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) if (mbedtls_ssl_ciphersuite_uses_ecdh(ciphersuite_info)) { ret = ssl_get_ecdh_params_from_cert(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_get_ecdh_params_from_cert", ret); return ret; } } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ /* Key exchanges not involving ephemeral keys don't use * ServerKeyExchange, so end here. */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write server key exchange")); ssl->state++; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ defined(MBEDTLS_SSL_ASYNC_PRIVATE) /* If we have already prepared the message and there is an ongoing * signature operation, resume signing. */ if (ssl->handshake->async_in_progress != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("resuming signature operation")); ret = ssl_resume_server_key_exchange(ssl, &signature_len); } else #endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ { /* ServerKeyExchange is needed. Prepare the message. */ ret = ssl_prepare_server_key_exchange(ssl, &signature_len); } if (ret != 0) { /* If we're starting to write a new message, set ssl->out_msglen * to 0. But if we're resuming after an asynchronous message, * out_msglen is the amount of data written so far and mst be * preserved. */ if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server key exchange (pending)")); } else { ssl->out_msglen = 0; } return ret; } /* If there is a signature, write its length. * ssl_prepare_server_key_exchange already wrote the signature * itself at its proper place in the output buffer. */ #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) if (signature_len != 0) { ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1(signature_len); ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0(signature_len); MBEDTLS_SSL_DEBUG_BUF(3, "my signature", ssl->out_msg + ssl->out_msglen, signature_len); /* Skip over the already-written signature */ ssl->out_msglen += signature_len; } #endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ /* Add header and send. */ ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; ssl->state++; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server key exchange")); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_server_hello_done(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello done")); ssl->out_msglen = 4; ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; ssl->state++; #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) { mbedtls_ssl_send_flight_completed(ssl); } #endif if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } #if defined(MBEDTLS_SSL_PROTO_DTLS) if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret); return ret; } #endif /* MBEDTLS_SSL_PROTO_DTLS */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello done")); return 0; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t n; /* * Receive G^Y mod P, premaster = (G^Y)^X mod P */ if (*p + 2 > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } n = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (*p + n > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if ((ret = mbedtls_dhm_read_public(&ssl->handshake->dhm_ctx, *p, n)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_read_public", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } *p += n; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: GY", &ssl->handshake->dhm_ctx.GY); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_resume_decrypt_pms(mbedtls_ssl_context *ssl, unsigned char *peer_pms, size_t *peer_pmslen, size_t peer_pmssize) { int ret = ssl->conf->f_async_resume(ssl, peer_pms, peer_pmslen, peer_pmssize); if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { ssl->handshake->async_in_progress = 0; mbedtls_ssl_set_async_operation_data(ssl, NULL); } MBEDTLS_SSL_DEBUG_RET(2, "ssl_decrypt_encrypted_pms", ret); return ret; } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_decrypt_encrypted_pms(mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, unsigned char *peer_pms, size_t *peer_pmslen, size_t peer_pmssize) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *own_cert = mbedtls_ssl_own_cert(ssl); if (own_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no local certificate")); return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; } mbedtls_pk_context *public_key = &own_cert->pk; mbedtls_pk_context *private_key = mbedtls_ssl_own_key(ssl); size_t len = mbedtls_pk_get_len(public_key); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) /* If we have already started decoding the message and there is an ongoing * decryption operation, resume signing. */ if (ssl->handshake->async_in_progress != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("resuming decryption operation")); return ssl_resume_decrypt_pms(ssl, peer_pms, peer_pmslen, peer_pmssize); } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ /* * Prepare to decrypt the premaster using own private RSA key */ if (p + 2 > end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (*p++ != MBEDTLS_BYTE_1(len) || *p++ != MBEDTLS_BYTE_0(len)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (p + len != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Decrypt the premaster secret */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->conf->f_async_decrypt_start != NULL) { ret = ssl->conf->f_async_decrypt_start(ssl, mbedtls_ssl_own_cert(ssl), p, len); switch (ret) { case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: /* act as if f_async_decrypt_start was null */ break; case 0: ssl->handshake->async_in_progress = 1; return ssl_resume_decrypt_pms(ssl, peer_pms, peer_pmslen, peer_pmssize); case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: ssl->handshake->async_in_progress = 1; return MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS; default: MBEDTLS_SSL_DEBUG_RET(1, "f_async_decrypt_start", ret); return ret; } } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if (!mbedtls_pk_can_do(private_key, MBEDTLS_PK_RSA)) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no RSA private key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } ret = mbedtls_pk_decrypt(private_key, p, len, peer_pms, peer_pmslen, peer_pmssize, ssl->conf->f_rng, ssl->conf->p_rng); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl, const unsigned char *p, const unsigned char *end, size_t pms_offset) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *pms = ssl->handshake->premaster + pms_offset; unsigned char ver[2]; unsigned char fake_pms[48], peer_pms[48]; size_t peer_pmslen; mbedtls_ct_condition_t diff; /* In case of a failure in decryption, the decryption may write less than * 2 bytes of output, but we always read the first two bytes. It doesn't * matter in the end because diff will be nonzero in that case due to * ret being nonzero, and we only care whether diff is 0. * But do initialize peer_pms and peer_pmslen for robustness anyway. This * also makes memory analyzers happy (don't access uninitialized memory, * even if it's an unsigned char). */ peer_pms[0] = peer_pms[1] = ~0; peer_pmslen = 0; ret = ssl_decrypt_encrypted_pms(ssl, p, end, peer_pms, &peer_pmslen, sizeof(peer_pms)); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) { return ret; } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ mbedtls_ssl_write_version(ver, ssl->conf->transport, ssl->session_negotiate->tls_version); /* Avoid data-dependent branches while checking for invalid * padding, to protect against timing-based Bleichenbacher-type * attacks. */ diff = mbedtls_ct_bool(ret); diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pmslen, 48)); diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[0], ver[0])); diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[1], ver[1])); /* * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding * must not cause the connection to end immediately; instead, send a * bad_record_mac later in the handshake. * To protect against timing-based variants of the attack, we must * not have any branch that depends on whether the decryption was * successful. In particular, always generate the fake premaster secret, * regardless of whether it will ultimately influence the output or not. */ ret = ssl->conf->f_rng(ssl->conf->p_rng, fake_pms, sizeof(fake_pms)); if (ret != 0) { /* It's ok to abort on an RNG failure, since this does not reveal * anything about the RSA decryption. */ return ret; } #if defined(MBEDTLS_SSL_DEBUG_ALL) if (diff != MBEDTLS_CT_FALSE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); } #endif if (sizeof(ssl->handshake->premaster) < pms_offset || sizeof(ssl->handshake->premaster) - pms_offset < 48) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ssl->handshake->pmslen = 48; /* Set pms to either the true or the fake PMS, without * data-dependent branches. */ mbedtls_ct_memcpy_if(diff, pms, fake_pms, peer_pms, ssl->handshake->pmslen); return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char **p, const unsigned char *end) { int ret = 0; uint16_t n; if (ssl_conf_has_psk_or_cb(ssl->conf) == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no pre-shared key")); return MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED; } /* * Receive client pre-shared key identity name */ if (end - *p < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } n = MBEDTLS_GET_UINT16_BE(*p, 0); *p += 2; if (n == 0 || n > end - *p) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if (ssl->conf->f_psk != NULL) { if (ssl->conf->f_psk(ssl->conf->p_psk, ssl, *p, n) != 0) { ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } } else { /* Identity is not a big secret since clients send it in the clear, * but treat it carefully anyway, just in case */ if (n != ssl->conf->psk_identity_len || mbedtls_ct_memcmp(ssl->conf->psk_identity, *p, n) != 0) { ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } } if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) { MBEDTLS_SSL_DEBUG_BUF(3, "Unknown PSK identity", *p, n); mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY); return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } *p += n; return 0; } #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; unsigned char *p, *end; ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client key exchange")); #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ (defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)) if ((ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) && (ssl->handshake->async_in_progress != 0)) { /* We've already read a record and there is an asynchronous * operation in progress to decrypt it. So skip reading the * record. */ MBEDTLS_SSL_DEBUG_MSG(3, ("will resume decryption of previously-read record")); } else #endif if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } p = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl); end = ssl->in_msg + ssl->in_hslen; if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA) { if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_dh_public"), ret); return ret; } if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, ssl->handshake->premaster, MBEDTLS_PREMASTER_SIZE, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t data_len = (size_t) (*p++); size_t buf_len = (size_t) (end - p); psa_status_t status = PSA_ERROR_GENERIC_ERROR; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_DEBUG_MSG(3, ("Read the peer's public key.")); /* * We must have at least two bytes (1 for length, at least 1 for data) */ if (buf_len < 2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length: %" MBEDTLS_PRINTF_SIZET, buf_len)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } if (data_len < 1 || data_len > buf_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, data_len, buf_len)); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Store peer's ECDH public key. */ if (data_len > sizeof(handshake->xxdh_psa_peerkey)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %" MBEDTLS_PRINTF_SIZET " > %" MBEDTLS_PRINTF_SIZET, data_len, sizeof(handshake->xxdh_psa_peerkey))); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } memcpy(handshake->xxdh_psa_peerkey, p, data_len); handshake->xxdh_psa_peerkey_len = data_len; /* Compute ECDH shared secret. */ status = psa_raw_key_agreement( PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, handshake->premaster, sizeof(handshake->premaster), &handshake->pmslen); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); if (handshake->xxdh_psa_privkey_is_external == 0) { (void) psa_destroy_key(handshake->xxdh_psa_privkey); } handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } if (handshake->xxdh_psa_privkey_is_external == 0) { status = psa_destroy_key(handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); return ret; } } handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; #else if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, p, (size_t) (end - p))) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, MBEDTLS_MPI_MAX_SIZE, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_Z); #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK) { if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) { #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) if (ssl->handshake->async_in_progress != 0) { /* There is an asynchronous operation in progress to * decrypt the encrypted premaster secret, so skip * directly to resuming this operation. */ MBEDTLS_SSL_DEBUG_MSG(3, ("PSK identity already parsed")); /* Update p to skip the PSK identity. ssl_parse_encrypted_pms * won't actually use it, but maintain p anyway for robustness. */ p += ssl->conf->psk_identity_len + 2; } else #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 2)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_encrypted_pms"), ret); return ret; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK) { if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if ((ret = ssl_parse_client_dh_public(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_dh_public"), ret); return ret; } if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } #if defined(MBEDTLS_USE_PSA_CRYPTO) unsigned char *pms = ssl->handshake->premaster; unsigned char *pms_end = pms + sizeof(ssl->handshake->premaster); size_t pms_len; /* Write length only when we know the actual value */ if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx, pms + 2, pms_end - (pms + 2), &pms_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret); return ret; } MBEDTLS_PUT_UINT16_BE(pms_len, pms, 0); pms += 2 + pms_len; MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K); #else if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED; uint8_t ecpoint_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return ret; } /* Keep a copy of the peer's public key */ if (p >= end) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_DECODE_ERROR; } ecpoint_len = *(p++); if ((size_t) (end - p) < ecpoint_len) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* When FFDH is enabled, the array handshake->xxdh_psa_peer_key size takes into account the sizes of the FFDH keys which are at least 2048 bits. The size of the array is thus greater than 256 bytes which is greater than any possible value of ecpoint_len (type uint8_t) and the check below can be skipped.*/ #if !defined(PSA_WANT_ALG_FFDH) if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) { psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #else MBEDTLS_STATIC_ASSERT(sizeof(handshake->xxdh_psa_peerkey) >= UINT8_MAX, "peer key buffer too small"); #endif memcpy(handshake->xxdh_psa_peerkey, p, ecpoint_len); handshake->xxdh_psa_peerkey_len = ecpoint_len; p += ecpoint_len; /* As RFC 5489 section 2, the premaster secret is formed as follows: * - a uint16 containing the length (in octets) of the ECDH computation * - the octet string produced by the ECDH computation * - a uint16 containing the length (in octets) of the PSK * - the PSK itself */ unsigned char *psm = ssl->handshake->premaster; const unsigned char * const psm_end = psm + sizeof(ssl->handshake->premaster); /* uint16 to store length (in octets) of the ECDH computation */ const size_t zlen_size = 2; size_t zlen = 0; /* Compute ECDH shared secret. */ status = psa_raw_key_agreement(PSA_ALG_ECDH, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, psm + zlen_size, psm_end - (psm + zlen_size), &zlen); destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey); handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } else if (destruction_status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(destruction_status); } /* Write the ECDH computation length before the ECDH computation */ MBEDTLS_PUT_UINT16_BE(zlen, psm, 0); psm += zlen_size + zlen; #else /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret); return ret; } if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx, p, (size_t) (end - p))) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx, MBEDTLS_DEBUG_ECDH_QP); if ((ret = mbedtls_ssl_psk_derive_premaster(ssl, (mbedtls_key_exchange_type_t) ciphersuite_info-> key_exchange)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA) { if ((ret = ssl_parse_encrypted_pms(ssl, p, end, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_parse_encrypted_pms_secret"), ret); return ret; } } else #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) { #if defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_psa_ecjpake_read_round( &ssl->handshake->psa_pake_ctx, p, (size_t) (end - p), MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) { psa_destroy_key(ssl->handshake->psa_pake_password); psa_pake_abort(&ssl->handshake->psa_pake_ctx); MBEDTLS_SSL_DEBUG_RET(1, "psa_pake_input round two", ret); return ret; } #else ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx, p, (size_t) (end - p)); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ecjpake_derive_secret(&ssl->handshake->ecjpake_ctx, ssl->handshake->premaster, 32, &ssl->handshake->pmslen, ssl->conf->f_rng, ssl->conf->p_rng); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_derive_secret", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ } else #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if ((ret = mbedtls_ssl_derive_keys(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_derive_keys", ret); return ret; } ssl->state++; MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client key exchange")); return 0; } #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t i, sig_len; unsigned char hash[48]; unsigned char *hash_start = hash; size_t hashlen; mbedtls_pk_type_t pk_alg; mbedtls_md_type_t md_alg; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; mbedtls_pk_context *peer_pk; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); if (!mbedtls_ssl_ciphersuite_cert_req_allowed(ciphersuite_info)) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if (ssl->session_negotiate->peer_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert_digest == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate verify")); ssl->state++; return 0; } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Read the message without adding it to the checksum */ ret = mbedtls_ssl_read_record(ssl, 0 /* no checksum update */); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_read_record"), ret); return ret; } ssl->state++; /* Process the message contents */ if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } i = mbedtls_ssl_hs_hdr_len(ssl); #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) peer_pk = &ssl->handshake->peer_pubkey; #else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if (ssl->session_negotiate->peer_cert == NULL) { /* Should never happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } peer_pk = &ssl->session_negotiate->peer_cert->pk; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* * struct { * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only * opaque signature<0..2^16-1>; * } DigitallySigned; */ if (i + 2 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Hash */ md_alg = mbedtls_ssl_md_alg_from_hash(ssl->in_msg[i]); if (md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md(ssl, ssl->in_msg[i])) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" " for verify message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if !defined(MBEDTLS_MD_SHA1) if (MBEDTLS_MD_SHA1 == md_alg) { hash_start += 16; } #endif /* Info from md_alg will be used instead */ hashlen = 0; i++; /* * Signature */ if ((pk_alg = mbedtls_ssl_pk_alg_from_sig(ssl->in_msg[i])) == MBEDTLS_PK_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer not adhering to requested sig_alg" " for verify message")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * Check the certificate's key type matches the signature alg */ if (!mbedtls_pk_can_do(peer_pk, pk_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("sig_alg doesn't match cert key")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } i++; if (i + 2 > ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } sig_len = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i); i += 2; if (i + sig_len != ssl->in_hslen) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate verify message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Calculate hash and verify signature */ { size_t dummy_hlen; ret = ssl->handshake->calc_verify(ssl, hash, &dummy_hlen); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("calc_verify"), ret); return ret; } } if ((ret = mbedtls_pk_verify(peer_pk, md_alg, hash_start, hashlen, ssl->in_msg + i, sig_len)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify", ret); return ret; } ret = mbedtls_ssl_update_handshake_status(ssl); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_update_handshake_status"), ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); return ret; } #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t tlen; uint32_t lifetime; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write new session ticket")); ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; /* * struct { * uint32 ticket_lifetime_hint; * opaque ticket<0..2^16-1>; * } NewSessionTicket; * * 4 . 7 ticket_lifetime_hint (0 = unspecified) * 8 . 9 ticket_len (n) * 10 . 9+n ticket content */ #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time(); #endif if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, ssl->session_negotiate, ssl->out_msg + 10, ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &tlen, &lifetime)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret); tlen = 0; } MBEDTLS_PUT_UINT32_BE(lifetime, ssl->out_msg, 4); MBEDTLS_PUT_UINT16_BE(tlen, ssl->out_msg, 8); ssl->out_msglen = 10 + tlen; /* * Morally equivalent to updating ssl->state, but NewSessionTicket and * ChangeCipherSpec share the same state. */ ssl->handshake->new_session_ticket = 0; if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * SSL handshake -- server side -- single step */ int mbedtls_ssl_handshake_server_step(mbedtls_ssl_context *ssl) { int ret = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("server state: %d", ssl->state)); switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: ssl->state = MBEDTLS_SSL_CLIENT_HELLO; break; /* * <== ClientHello */ case MBEDTLS_SSL_CLIENT_HELLO: ret = ssl_parse_client_hello(ssl); break; #if defined(MBEDTLS_SSL_PROTO_DTLS) case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED; #endif /* * ==> ServerHello * Certificate * ( ServerKeyExchange ) * ( CertificateRequest ) * ServerHelloDone */ case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_write_server_hello(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = mbedtls_ssl_write_certificate(ssl); break; case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: ret = ssl_write_server_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_write_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_HELLO_DONE: ret = ssl_write_server_hello_done(ssl); break; /* * <== ( Certificate/Alert ) * ClientKeyExchange * ( CertificateVerify ) * ChangeCipherSpec * Finished */ case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_parse_certificate(ssl); break; case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: ret = ssl_parse_client_key_exchange(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_parse_certificate_verify(ssl); break; case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: ret = mbedtls_ssl_parse_change_cipher_spec(ssl); break; case MBEDTLS_SSL_CLIENT_FINISHED: ret = mbedtls_ssl_parse_finished(ssl); break; /* * ==> ( NewSessionTicket ) * ChangeCipherSpec * Finished */ case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl->handshake->new_session_ticket != 0) { ret = ssl_write_new_session_ticket(ssl); } else #endif ret = mbedtls_ssl_write_change_cipher_spec(ssl); break; case MBEDTLS_SSL_SERVER_FINISHED: ret = mbedtls_ssl_write_finished(ssl); break; case MBEDTLS_SSL_FLUSH_BUFFERS: MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: mbedtls_ssl_handshake_wrapup(ssl); break; default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return ret; } void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order) { conf->respect_cli_pref = order; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_2 */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c000066400000000000000000003222621464416617300246740ustar00rootroot00000000000000/* * TLS 1.3 client-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) #include #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "ssl_misc.h" #include "ssl_client.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" #include "mbedtls/psa_util.h" #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif /* Write extensions */ /* * ssl_tls13_write_supported_versions_ext(): * * struct { * ProtocolVersion versions<2..254>; * } SupportedVersions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_supported_versions_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; unsigned char versions_len = (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) ? 4 : 2; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding supported versions extension")); /* Check if we have space to write the extension: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - versions_length (1 byte ) * - versions (2 or 4 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 5 + versions_len); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0); MBEDTLS_PUT_UINT16_BE(versions_len + 1, p, 2); p += 4; /* Length of versions */ *p++ = versions_len; /* Write values of supported versions. * They are defined by the configuration. * Currently, we advertise only TLS 1.3 or both TLS 1.3 and TLS 1.2. */ mbedtls_ssl_write_version(p, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERSION_TLS1_3); MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:4]")); if (ssl->handshake->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2) { mbedtls_ssl_write_version(p + 2, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERSION_TLS1_2); MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [3:3]")); } *out_len = 5 + versions_len; mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { ((void) ssl); MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); if (mbedtls_ssl_read_version(buf, ssl->conf->transport) != MBEDTLS_SSL_VERSION_TLS1_3) { MBEDTLS_SSL_DEBUG_MSG(1, ("unexpected version")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } if (&buf[2] != end) { MBEDTLS_SSL_DEBUG_MSG( 1, ("supported_versions ext data length incorrect")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } return 0; } #if defined(MBEDTLS_SSL_ALPN) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_alpn_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len) { const unsigned char *p = buf; const unsigned char *end = buf + len; size_t protocol_name_list_len, protocol_name_len; const unsigned char *protocol_name_list_end; /* If we didn't send it, the server shouldn't send it */ if (ssl->conf->alpn_list == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * opaque ProtocolName<1..2^8-1>; * * struct { * ProtocolName protocol_name_list<2..2^16-1> * } ProtocolNameList; * * the "ProtocolNameList" MUST contain exactly one "ProtocolName" */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); protocol_name_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, protocol_name_list_len); protocol_name_list_end = p + protocol_name_list_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, 1); protocol_name_len = *p++; /* Check that the server chosen protocol was in our list and save it */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, protocol_name_list_end, protocol_name_len); for (const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++) { if (protocol_name_len == strlen(*alpn) && memcmp(p, *alpn, protocol_name_len) == 0) { ssl->alpn_chosen = *alpn; return 0; } } return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #endif /* MBEDTLS_SSL_ALPN */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl) { uint16_t group_id = ssl->handshake->offered_group_id; if (group_id == 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) || mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Destroy generated private key. */ status = psa_destroy_key(ssl->handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); return ret; } ssl->handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; return 0; } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ if (0 /* other KEMs? */) { /* Do something */ } return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * Functions for writing key_share extension. */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl, uint16_t *group_id) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); /* Pick first available ECDHE group compatible with TLS 1.3 */ if (group_list == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } for (; *group_list != 0; group_list++) { #if defined(PSA_WANT_ALG_ECDH) if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( *group_list, NULL, NULL) == PSA_SUCCESS) && mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { *group_id = *group_list; return 0; } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { *group_id = *group_list; return 0; } #endif } #else ((void) ssl); ((void) group_id); #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ return ret; } /* * ssl_tls13_write_key_share_ext * * Structure of key_share extension in ClientHello: * * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; * struct { * KeyShareEntry client_shares<0..2^16-1>; * } KeyShareClientHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; unsigned char *client_shares; /* Start of client_shares */ size_t client_shares_len; /* Length of client_shares */ uint16_t group_id; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; *out_len = 0; /* Check if we have space for header and length fields: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - client_shares_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; MBEDTLS_SSL_DEBUG_MSG(3, ("client hello: adding key share extension")); /* HRR could already have requested something else. */ group_id = ssl->handshake->offered_group_id; if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) && !mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl, &group_id)); } /* * Dispatch to type-specific key generation function. * * So far, we're only supporting ECDHE. With the introduction * of PQC KEMs, we'll want to have multiple branches, one per * type of KEM, and dispatch to the corresponding crypto. And * only one key share entry is allowed. */ client_shares = p; #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) || mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) { /* Pointer to group */ unsigned char *group = p; /* Length of key_exchange */ size_t key_exchange_len = 0; /* Check there is space for header of KeyShareEntry * - group (2 bytes) * - key_exchange_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); p += 4; ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( ssl, group_id, p, end, &key_exchange_len); p += key_exchange_len; if (ret != 0) { return ret; } /* Write group */ MBEDTLS_PUT_UINT16_BE(group_id, group, 0); /* Write key_exchange_length */ MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2); } else #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ if (0 /* other KEMs? */) { /* Do something */ } else { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Length of client_shares */ client_shares_len = p - client_shares; if (client_shares_len == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("No key share defined.")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Write extension_type */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); /* Write extension_data_length */ MBEDTLS_PUT_UINT16_BE(client_shares_len + 2, buf, 2); /* Write client_shares_length */ MBEDTLS_PUT_UINT16_BE(client_shares_len, buf, 4); /* Update offered_group_id field */ ssl->handshake->offered_group_id = group_id; /* Output the total length of key_share extension. */ *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, key_share extension", buf, *out_len); mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); cleanup: return ret; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ /* * ssl_tls13_parse_hrr_key_share_ext() * Parse key_share extension in Hello Retry Request * * struct { * NamedGroup selected_group; * } KeyShareHelloRetryRequest; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) const unsigned char *p = buf; int selected_group; int found = 0; const uint16_t *group_list = mbedtls_ssl_get_groups(ssl); if (group_list == NULL) { return MBEDTLS_ERR_SSL_BAD_CONFIG; } MBEDTLS_SSL_DEBUG_BUF(3, "key_share extension", p, end - buf); /* Read selected_group */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); selected_group = MBEDTLS_GET_UINT16_BE(p, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("selected_group ( %d )", selected_group)); /* Upon receipt of this extension in a HelloRetryRequest, the client * MUST first verify that the selected_group field corresponds to a * group which was provided in the "supported_groups" extension in the * original ClientHello. * The supported_group was based on the info in ssl->conf->group_list. * * If the server provided a key share that was not sent in the ClientHello * then the client MUST abort the handshake with an "illegal_parameter" alert. */ for (; *group_list != 0; group_list++) { #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) { if ((mbedtls_ssl_get_psa_curve_info_from_tls_id( *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) || *group_list != selected_group) { found = 1; break; } } #endif /* PSA_WANT_ALG_ECDH */ #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) { found = 1; break; } #endif /* PSA_WANT_ALG_FFDH */ } /* Client MUST verify that the selected_group field does not * correspond to a group which was provided in the "key_share" * extension in the original ClientHello. If the server sent an * HRR message with a key share already provided in the * ClientHello then the client MUST abort the handshake with * an "illegal_parameter" alert. */ if (found == 0 || selected_group == ssl->handshake->offered_group_id) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid key share in HRR")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* Remember server's preference for next ClientHello */ ssl->handshake->offered_group_id = selected_group; return 0; #else /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ (void) ssl; (void) buf; (void) end; return MBEDTLS_ERR_SSL_BAD_CONFIG; #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ } /* * ssl_tls13_parse_key_share_ext() * Parse key_share extension in Server Hello * * struct { * KeyShareEntry server_share; * } KeyShareServerHello; * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; uint16_t group, offered_group; /* ... * NamedGroup group; (2 bytes) * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); group = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check that the chosen group matches the one we offered. */ offered_group = ssl->handshake->offered_group_id; if (offered_group != group) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Invalid server key share, our group %u, their group %u", (unsigned) offered_group, (unsigned) group)); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) || mbedtls_ssl_tls13_named_group_is_ffdh(group)) { MBEDTLS_SSL_DEBUG_MSG(2, ("DHE group name: %s", mbedtls_ssl_named_group_to_str(group))); ret = mbedtls_ssl_tls13_read_public_xxdhe_share(ssl, p, end - p); if (ret != 0) { return ret; } } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ if (0 /* other KEMs? */) { /* Do something */ } else { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return ret; } /* * ssl_tls13_parse_cookie_ext() * Parse cookie extension in Hello Retry Request * * struct { * opaque cookie<1..2^16-1>; * } Cookie; * * When sending a HelloRetryRequest, the server MAY provide a "cookie" * extension to the client (this is an exception to the usual rule that * the only extensions that may be sent are those that appear in the * ClientHello). When sending the new ClientHello, the client MUST copy * the contents of the extension received in the HelloRetryRequest into * a "cookie" extension in the new ClientHello. Clients MUST NOT use * cookies in their initial ClientHello in subsequent connections. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_cookie_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { uint16_t cookie_len; const unsigned char *p = buf; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Retrieve length field of cookie */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); cookie_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cookie_len); MBEDTLS_SSL_DEBUG_BUF(3, "cookie extension", p, cookie_len); mbedtls_free(handshake->cookie); handshake->cookie_len = 0; handshake->cookie = mbedtls_calloc(1, cookie_len); if (handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc failed ( %ud bytes )", cookie_len)); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(handshake->cookie, p, cookie_len); handshake->cookie_len = cookie_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_cookie_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; *out_len = 0; mbedtls_ssl_handshake_params *handshake = ssl->handshake; if (handshake->cookie == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("no cookie to send; skip extension")); return 0; } MBEDTLS_SSL_DEBUG_BUF(3, "client hello, cookie", handshake->cookie, handshake->cookie_len); MBEDTLS_SSL_CHK_BUF_PTR(p, end, handshake->cookie_len + 6); MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding cookie extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_COOKIE, p, 0); MBEDTLS_PUT_UINT16_BE(handshake->cookie_len + 2, p, 2); MBEDTLS_PUT_UINT16_BE(handshake->cookie_len, p, 4); p += 6; /* Cookie */ memcpy(p, handshake->cookie, handshake->cookie_len); *out_len = handshake->cookie_len + 6; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_COOKIE); return 0; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* * ssl_tls13_write_psk_key_exchange_modes_ext() structure: * * enum { psk_ke( 0 ), psk_dhe_ke( 1 ), ( 255 ) } PskKeyExchangeMode; * * struct { * PskKeyExchangeMode ke_modes<1..255>; * } PskKeyExchangeModes; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { unsigned char *p = buf; int ke_modes_len = 0; ((void) ke_modes_len); *out_len = 0; /* Skip writing extension if no PSK key exchange mode * is enabled in the config. */ if (!mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip psk_key_exchange_modes extension")); return 0; } /* Require 7 bytes of data, otherwise fail, * even if extension might be shorter. */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 7); MBEDTLS_SSL_DEBUG_MSG( 3, ("client hello, adding psk_key_exchange_modes extension")); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES, p, 0); /* Skip extension length (2 bytes) and * ke_modes length (1 byte) for now. */ p += 5; if (mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl)) { *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE; ke_modes_len++; MBEDTLS_SSL_DEBUG_MSG(4, ("Adding PSK-ECDHE key exchange mode")); } if (mbedtls_ssl_conf_tls13_is_psk_enabled(ssl)) { *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE; ke_modes_len++; MBEDTLS_SSL_DEBUG_MSG(4, ("Adding pure PSK key exchange mode")); } /* Now write the extension and ke_modes length */ MBEDTLS_PUT_UINT16_BE(ke_modes_len + 1, buf, 2); buf[4] = ke_modes_len; *out_len = p - buf; mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES); return 0; } static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL; ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); if (ciphersuite_info != NULL) { return mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); } return PSA_ALG_NONE; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl) { mbedtls_ssl_session *session = ssl->session_negotiate; return ssl->handshake->resume && session != NULL && session->ticket != NULL && mbedtls_ssl_conf_tls13_is_kex_mode_enabled( ssl, mbedtls_ssl_tls13_session_get_ticket_flags( session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL)); } #if defined(MBEDTLS_SSL_EARLY_DATA) static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl) { mbedtls_ssl_session *session = ssl->session_negotiate; return ssl->handshake->resume && session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 && mbedtls_ssl_tls13_session_ticket_allow_early_data(session) && mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite); } #endif MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_ticket_get_identity(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **identity, size_t *identity_len) { mbedtls_ssl_session *session = ssl->session_negotiate; if (!ssl_tls13_has_configured_ticket(ssl)) { return -1; } *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); *identity = session->ticket; *identity_len = session->ticket_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_ticket_get_psk(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **psk, size_t *psk_len) { mbedtls_ssl_session *session = ssl->session_negotiate; if (!ssl_tls13_has_configured_ticket(ssl)) { return -1; } *hash_alg = ssl_tls13_get_ciphersuite_hash_alg(session->ciphersuite); *psk = session->resumption_key; *psk_len = session->resumption_key_len; return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_psk_get_identity(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **identity, size_t *identity_len) { if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { return -1; } *hash_alg = PSA_ALG_SHA_256; *identity = ssl->conf->psk_identity; *identity_len = ssl->conf->psk_identity_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_psk_get_psk(mbedtls_ssl_context *ssl, psa_algorithm_t *hash_alg, const unsigned char **psk, size_t *psk_len) { if (!mbedtls_ssl_conf_has_static_psk(ssl->conf)) { return -1; } *hash_alg = PSA_ALG_SHA_256; *psk = ssl->conf->psk; *psk_len = ssl->conf->psk_len; return 0; } static int ssl_tls13_get_configured_psk_count(mbedtls_ssl_context *ssl) { int configured_psk_count = 0; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl_tls13_has_configured_ticket(ssl)) { MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket is configured")); configured_psk_count++; } #endif if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { MBEDTLS_SSL_DEBUG_MSG(3, ("PSK is configured")); configured_psk_count++; } return configured_psk_count; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_identity(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, const unsigned char *identity, size_t identity_len, uint32_t obfuscated_ticket_age, size_t *out_len) { ((void) ssl); *out_len = 0; /* * - identity_len (2 bytes) * - identity (psk_identity_len bytes) * - obfuscated_ticket_age (4 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6 + identity_len); MBEDTLS_PUT_UINT16_BE(identity_len, buf, 0); memcpy(buf + 2, identity, identity_len); MBEDTLS_PUT_UINT32_BE(obfuscated_ticket_age, buf, 2 + identity_len); MBEDTLS_SSL_DEBUG_BUF(4, "write identity", buf, 6 + identity_len); *out_len = 6 + identity_len; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_binder(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, int psk_type, psa_algorithm_t hash_alg, const unsigned char *psk, size_t psk_len, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char binder_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len = 0; *out_len = 0; binder_len = PSA_HASH_LENGTH(hash_alg); /* * - binder_len (1 bytes) * - binder (binder_len bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1 + binder_len); buf[0] = binder_len; /* Get current state of handshake transcript. */ ret = mbedtls_ssl_get_handshake_transcript( ssl, mbedtls_md_type_from_psa_alg(hash_alg), transcript, sizeof(transcript), &transcript_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_create_psk_binder(ssl, hash_alg, psk, psk_len, psk_type, transcript, buf + 1); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_create_psk_binder", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "write binder", buf, 1 + binder_len); *out_len = 1 + binder_len; return 0; } /* * mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext() structure: * * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * struct { * PskIdentity identities<7..2^16-1>; * PskBinderEntry binders<33..2^16-1>; * } OfferedPsks; * * struct { * select (Handshake.msg_type) { * case client_hello: OfferedPsks; * ... * }; * } PreSharedKeyExtension; * */ int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, size_t *binders_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int configured_psk_count = 0; unsigned char *p = buf; psa_algorithm_t hash_alg = PSA_ALG_NONE; const unsigned char *identity; size_t identity_len; size_t l_binders_len = 0; size_t output_len; *out_len = 0; *binders_len = 0; /* Check if we have any PSKs to offer. If no, skip pre_shared_key */ configured_psk_count = ssl_tls13_get_configured_psk_count(ssl); if (configured_psk_count == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("skip pre_shared_key extensions")); return 0; } MBEDTLS_SSL_DEBUG_MSG(4, ("Pre-configured PSK number = %d", configured_psk_count)); /* Check if we have space to write the extension, binders included. * - extension_type (2 bytes) * - extension_data_len (2 bytes) * - identities_len (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); p += 6; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl_tls13_ticket_get_identity( ssl, &hash_alg, &identity, &identity_len) == 0) { #if defined(MBEDTLS_HAVE_TIME) mbedtls_ms_time_t now = mbedtls_ms_time(); mbedtls_ssl_session *session = ssl->session_negotiate; /* The ticket age has been checked to be smaller than the * `ticket_lifetime` in ssl_prepare_client_hello() which is smaller than * 7 days (enforced in ssl_tls13_parse_new_session_ticket()) . Thus the * cast to `uint32_t` of the ticket age is safe. */ uint32_t obfuscated_ticket_age = (uint32_t) (now - session->ticket_reception_time); obfuscated_ticket_age += session->ticket_age_add; ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, obfuscated_ticket_age, &output_len); #else ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0, &output_len); #endif /* MBEDTLS_HAVE_TIME */ if (ret != 0) { return ret; } p += output_len; l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ if (ssl_tls13_psk_get_identity( ssl, &hash_alg, &identity, &identity_len) == 0) { ret = ssl_tls13_write_identity(ssl, p, end, identity, identity_len, 0, &output_len); if (ret != 0) { return ret; } p += output_len; l_binders_len += 1 + PSA_HASH_LENGTH(hash_alg); } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding pre_shared_key extension, " "omitting PSK binder list")); /* Take into account the two bytes for the length of the binders. */ l_binders_len += 2; /* Check if there is enough space for binders */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, l_binders_len); /* * - extension_type (2 bytes) * - extension_data_len (2 bytes) * - identities_len (2 bytes) */ MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, buf, 0); MBEDTLS_PUT_UINT16_BE(p - buf - 4 + l_binders_len, buf, 2); MBEDTLS_PUT_UINT16_BE(p - buf - 6, buf, 4); *out_len = (p - buf) + l_binders_len; *binders_len = l_binders_len; MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key identities", buf, p - buf); return 0; } int mbedtls_ssl_tls13_write_binders_of_pre_shared_key_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; psa_algorithm_t hash_alg = PSA_ALG_NONE; const unsigned char *psk; size_t psk_len; size_t output_len; /* Check if we have space to write binders_len. * - binders_len (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p += 2; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { ret = ssl_tls13_write_binder(ssl, p, end, MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION, hash_alg, psk, psk_len, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ if (ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len) == 0) { ret = ssl_tls13_write_binder(ssl, p, end, MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL, hash_alg, psk, psk_len, &output_len); if (ret != 0) { return ret; } p += output_len; } MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, adding PSK binder list.")); /* * - binders_len (2 bytes) */ MBEDTLS_PUT_UINT16_BE(p - buf - 2, buf, 0); MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key binders", buf, p - buf); mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); return 0; } /* * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * struct { * * select (Handshake.msg_type) { * ... * case server_hello: uint16 selected_identity; * }; * * } PreSharedKeyExtension; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int selected_identity; const unsigned char *psk; size_t psk_len; psa_algorithm_t hash_alg; MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 2); selected_identity = MBEDTLS_GET_UINT16_BE(buf, 0); ssl->handshake->selected_identity = (uint16_t) selected_identity; MBEDTLS_SSL_DEBUG_MSG(3, ("selected_identity = %d", selected_identity)); if (selected_identity >= ssl_tls13_get_configured_psk_count(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid PSK identity.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (selected_identity == 0 && ssl_tls13_has_configured_ticket(ssl)) { ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); } else #endif if (mbedtls_ssl_conf_has_static_psk(ssl->conf)) { ret = ssl_tls13_psk_get_psk(ssl, &hash_alg, &psk, &psk_len); } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (ret != 0) { return ret; } if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac) != hash_alg) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Invalid ciphersuite for external psk.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t ext_len; *out_len = 0; /* Write supported_versions extension * * Supported Versions Extension is mandatory with TLS 1.3. */ ret = ssl_tls13_write_supported_versions_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; /* Echo the cookie if the server provided one in its preceding * HelloRetryRequest message. */ ret = ssl_tls13_write_cookie_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) ret = mbedtls_ssl_tls13_write_record_size_limit_ext( ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; #endif #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; } #endif #if defined(MBEDTLS_SSL_EARLY_DATA) /* In the first ClientHello, write the early data indication extension if * necessary and update the early data state. * If an HRR has been received and thus we are currently writing the * second ClientHello, the second ClientHello must not contain an early * data extension and the early data state must stay as it is: * MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or * MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED. */ if (!ssl->handshake->hello_retry_request_flag) { if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) && ssl_tls13_early_data_has_valid_ticket(ssl) && ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) { ret = mbedtls_ssl_tls13_write_early_data_ext( ssl, 0, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT; } else { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT; } } #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* For PSK-based key exchange we need the pre_shared_key extension * and the psk_key_exchange_modes extension. * * The pre_shared_key extension MUST be the last extension in the * ClientHello. Servers MUST check that it is the last extension and * otherwise fail the handshake with an "illegal_parameter" alert. * * Add the psk_key_exchange_modes extension. */ ret = ssl_tls13_write_psk_key_exchange_modes_ext(ssl, p, end, &ext_len); if (ret != 0) { return ret; } p += ext_len; #endif *out_len = p - buf; return 0; } int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl) { ((void) ssl); #if defined(MBEDTLS_SSL_EARLY_DATA) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_algorithm_t hash_alg = PSA_ALG_NONE; const unsigned char *psk; size_t psk_len; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Set hs psk for early data when writing the first psk")); ret = ssl_tls13_ticket_get_psk(ssl, &hash_alg, &psk, &psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_ticket_get_psk", ret); return ret; } ret = mbedtls_ssl_set_hs_psk(ssl, psk, psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } /* * Early data are going to be encrypted using the ciphersuite * associated with the pre-shared key used for the handshake. * Note that if the server rejects early data, the handshake * based on the pre-shared key may complete successfully * with a selected ciphersuite different from the ciphersuite * associated with the pre-shared key. Only the hashes of the * two ciphersuites have to be the same. In that case, the * encrypted handshake data and application data are * encrypted using a different ciphersuite than the one used for * the rejected early data. */ ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite); ssl->handshake->ciphersuite_info = ciphersuite_info; /* Enable psk and psk_ephemeral to make stage early happy */ ssl->handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; /* Start the TLS 1.3 key schedule: * Set the PSK and derive early secret. */ ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); return ret; } /* Derive early data key material */ ret = mbedtls_ssl_tls13_compute_early_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_early_transform", ret); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO); #else MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to early data keys for outbound traffic")); mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_earlydata); ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE; #endif } #endif /* MBEDTLS_SSL_EARLY_DATA */ return 0; } /* * Functions for parsing and processing Server Hello */ /** * \brief Detect if the ServerHello contains a supported_versions extension * or not. * * \param[in] ssl SSL context * \param[in] buf Buffer containing the ServerHello message * \param[in] end End of the buffer containing the ServerHello message * * \return 0 if the ServerHello does not contain a supported_versions extension * \return 1 if the ServerHello contains a supported_versions extension * \return A negative value if an error occurred while parsing the ServerHello. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_is_supported_versions_ext_present( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t legacy_session_id_echo_len; const unsigned char *supported_versions_data; const unsigned char *supported_versions_data_end; /* * Check there is enough data to access the legacy_session_id_echo vector * length: * - legacy_version 2 bytes * - random MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes * - legacy_session_id_echo length 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 3); p += MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2; legacy_session_id_echo_len = *p; /* * Jump to the extensions, jumping over: * - legacy_session_id_echo (legacy_session_id_echo_len + 1) bytes * - cipher_suite 2 bytes * - legacy_compression_method 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4); p += legacy_session_id_echo_len + 4; return mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( ssl, p, end, &supported_versions_data, &supported_versions_data_end); } /* Returns a negative value on failure, and otherwise * - 1 if the last eight bytes of the ServerHello random bytes indicate that * the server is TLS 1.3 capable but negotiating TLS 1.2 or below. * - 0 otherwise */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_is_downgrade_negotiation(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* First seven bytes of the magic downgrade strings, see RFC 8446 4.1.3 */ static const unsigned char magic_downgrade_string[] = { 0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44 }; const unsigned char *last_eight_bytes_of_random; unsigned char last_byte_of_random; MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 2); last_eight_bytes_of_random = buf + 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN - 8; if (memcmp(last_eight_bytes_of_random, magic_downgrade_string, sizeof(magic_downgrade_string)) == 0) { last_byte_of_random = last_eight_bytes_of_random[7]; return last_byte_of_random == 0 || last_byte_of_random == 1; } return 0; } /* Returns a negative value on failure, and otherwise * - SSL_SERVER_HELLO or * - SSL_SERVER_HELLO_HRR * to indicate which message is expected and to be parsed next. */ #define SSL_SERVER_HELLO 0 #define SSL_SERVER_HELLO_HRR 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* Check whether this message is a HelloRetryRequest ( HRR ) message. * * Server Hello and HRR are only distinguished by Random set to the * special value of the SHA-256 of "HelloRetryRequest". * * struct { * ProtocolVersion legacy_version = 0x0303; * Random random; * opaque legacy_session_id_echo<0..32>; * CipherSuite cipher_suite; * uint8 legacy_compression_method = 0; * Extension extensions<6..2^16-1>; * } ServerHello; * */ MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)); if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic, sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) { return SSL_SERVER_HELLO_HRR; } return SSL_SERVER_HELLO; } /* * Returns a negative value on failure, and otherwise * - SSL_SERVER_HELLO or * - SSL_SERVER_HELLO_HRR or * - SSL_SERVER_HELLO_TLS1_2 */ #define SSL_SERVER_HELLO_TLS1_2 2 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_is_supported_versions_ext_present( ssl, buf, end)); if (ret == 0) { MBEDTLS_SSL_PROC_CHK_NEG( ssl_tls13_is_downgrade_negotiation(ssl, buf, end)); /* If the server is negotiating TLS 1.2 or below and: * . we did not propose TLS 1.2 or * . the server responded it is TLS 1.3 capable but negotiating a lower * version of the protocol and thus we are under downgrade attack * abort the handshake with an "illegal parameter" alert. */ if (handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } /* * Version 1.2 of the protocol has been negotiated, set the * ssl->keep_current_message flag for the ServerHello to be kept and * parsed as a TLS 1.2 ServerHello. We also change ssl->tls_version to * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step() * will dispatch to the TLS 1.2 state machine. */ ssl->keep_current_message = 1; ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, (size_t) (end - buf))); if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { ret = ssl_tls13_reset_key_share(ssl); if (ret != 0) { return ret; } } return SSL_SERVER_HELLO_TLS1_2; } ssl->session_negotiate->tls_version = ssl->tls_version; ssl->session_negotiate->endpoint = ssl->conf->endpoint; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; ret = ssl_server_hello_is_hrr(ssl, buf, end); switch (ret) { case SSL_SERVER_HELLO: MBEDTLS_SSL_DEBUG_MSG(2, ("received ServerHello message")); break; case SSL_SERVER_HELLO_HRR: MBEDTLS_SSL_DEBUG_MSG(2, ("received HelloRetryRequest message")); /* If a client receives a second HelloRetryRequest in the same * connection (i.e., where the ClientHello was itself in response * to a HelloRetryRequest), it MUST abort the handshake with an * "unexpected_message" alert. */ if (handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * Clients must abort the handshake with an "illegal_parameter" * alert if the HelloRetryRequest would not result in any change * in the ClientHello. * In a PSK only key exchange that what we expect. */ if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Unexpected HRR in pure PSK key exchange.")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } handshake->hello_retry_request_flag = 1; break; } cleanup: return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_check_server_hello_session_id_echo(mbedtls_ssl_context *ssl, const unsigned char **buf, const unsigned char *end) { const unsigned char *p = *buf; size_t legacy_session_id_echo_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); legacy_session_id_echo_len = *p++; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len); /* legacy_session_id_echo */ if (ssl->session_negotiate->id_len != legacy_session_id_echo_len || memcmp(ssl->session_negotiate->id, p, legacy_session_id_echo_len) != 0) { MBEDTLS_SSL_DEBUG_BUF(3, "Expected Session ID", ssl->session_negotiate->id, ssl->session_negotiate->id_len); MBEDTLS_SSL_DEBUG_BUF(3, "Received Session ID", p, legacy_session_id_echo_len); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += legacy_session_id_echo_len; *buf = p; MBEDTLS_SSL_DEBUG_BUF(3, "Session ID", ssl->session_negotiate->id, ssl->session_negotiate->id_len); return 0; } /* Parse ServerHello message and configure context * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * Random random; * opaque legacy_session_id_echo<0..32>; * CipherSuite cipher_suite; * uint8 legacy_compression_method = 0; * Extension extensions<6..2^16-1>; * } ServerHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, int is_hrr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; mbedtls_ssl_handshake_params *handshake = ssl->handshake; size_t extensions_len; const unsigned char *extensions_end; uint16_t cipher_suite; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; int fatal_alert = 0; uint32_t allowed_extensions_mask; int hs_msg_type = is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : MBEDTLS_SSL_HS_SERVER_HELLO; /* * Check there is space for minimal fields * * - legacy_version ( 2 bytes) * - random (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes) * - legacy_session_id_echo ( 1 byte ), minimum size * - cipher_suite ( 2 bytes) * - legacy_compression_method ( 1 byte ) */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6); MBEDTLS_SSL_DEBUG_BUF(4, "server hello", p, end - p); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", p, 2); /* ... * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * ... * with ProtocolVersion defined as: * uint16 ProtocolVersion; */ if (mbedtls_ssl_read_version(p, ssl->conf->transport) != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; goto cleanup; } p += 2; /* ... * Random random; * ... * with Random defined as: * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; */ if (!is_hrr) { memcpy(&handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); } p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; /* ... * opaque legacy_session_id_echo<0..32>; * ... */ if (ssl_tls13_check_server_hello_session_id_echo(ssl, &p, end) != 0) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; goto cleanup; } /* ... * CipherSuite cipher_suite; * ... * with CipherSuite defined as: * uint8 CipherSuite[2]; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); /* * Check whether this ciphersuite is valid and offered. */ if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, ssl->tls_version, ssl->tls_version) != 0) || !mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } /* * If we received an HRR before and that the proposed selected * ciphersuite in this server hello is not the same as the one * proposed in the HRR, we abort the handshake and send an * "illegal_parameter" alert. */ else if ((!is_hrr) && handshake->hello_retry_request_flag && (cipher_suite != ssl->session_negotiate->ciphersuite)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; } if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { MBEDTLS_SSL_DEBUG_MSG(1, ("invalid ciphersuite(%04x) parameter", cipher_suite)); goto cleanup; } /* Configure ciphersuites */ mbedtls_ssl_optimize_checksum(ssl, ciphersuite_info); handshake->ciphersuite_info = ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: ( %04x ) - %s", cipher_suite, ciphersuite_info->name)); #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif /* MBEDTLS_HAVE_TIME */ /* ... * uint8 legacy_compression_method = 0; * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); if (p[0] != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER; goto cleanup; } p++; /* ... * Extension extensions<6..2^16-1>; * ... * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check extensions do not go beyond the buffer of data. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; MBEDTLS_SSL_DEBUG_BUF(3, "server hello extensions", p, extensions_len); handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; allowed_extensions_mask = is_hrr ? MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_HRR : MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_SH; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; const unsigned char *extension_data_end; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); extension_data_end = p + extension_data_len; ret = mbedtls_ssl_tls13_check_received_extension( ssl, hs_msg_type, extension_type, allowed_extensions_mask); if (ret != 0) { return ret; } switch (extension_type) { case MBEDTLS_TLS_EXT_COOKIE: ret = ssl_tls13_parse_cookie_ext(ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_parse_cookie_ext", ret); goto cleanup; } break; case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: ret = ssl_tls13_parse_supported_versions_ext(ssl, p, extension_data_end); if (ret != 0) { goto cleanup; } break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); if ((ret = ssl_tls13_parse_server_pre_shared_key_ext( ssl, p, extension_data_end)) != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("ssl_tls13_parse_server_pre_shared_key_ext"), ret); return ret; } break; #endif case MBEDTLS_TLS_EXT_KEY_SHARE: MBEDTLS_SSL_DEBUG_MSG(3, ("found key_shares extension")); if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) { fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT; goto cleanup; } if (is_hrr) { ret = ssl_tls13_parse_hrr_key_share_ext(ssl, p, extension_data_end); } else { ret = ssl_tls13_parse_key_share_ext(ssl, p, extension_data_end); } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_parse_key_share_ext", ret); goto cleanup; } break; default: ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, hs_msg_type, handshake->received_extensions); cleanup: if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); ret = MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } else if (fatal_alert == MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); ret = MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } return ret; } #if defined(MBEDTLS_DEBUG_C) static const char *ssl_tls13_get_kex_mode_str(int mode) { switch (mode) { case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK: return "psk"; case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL: return "ephemeral"; case MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL: return "psk_ephemeral"; default: return "unknown mode"; } } #endif /* MBEDTLS_DEBUG_C */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Determine the key exchange mode: * 1) If both the pre_shared_key and key_share extensions were received * then the key exchange mode is PSK with EPHEMERAL. * 2) If only the pre_shared_key extension was received then the key * exchange mode is PSK-only. * 3) If only the key_share extension was received then the key * exchange mode is EPHEMERAL-only. */ switch (handshake->received_extensions & (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) { /* Only the pre_shared_key extension was received */ case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY): handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; break; /* Only the key_share extension was received */ case MBEDTLS_SSL_EXT_MASK(KEY_SHARE): handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; break; /* Both the pre_shared_key and key_share extensions were received */ case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE)): handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; break; /* Neither pre_shared_key nor key_share extension was received */ default: MBEDTLS_SSL_DEBUG_MSG(1, ("Unknown key exchange.")); ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; goto cleanup; } if (!mbedtls_ssl_conf_tls13_is_kex_mode_enabled( ssl, handshake->key_exchange_mode)) { ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; MBEDTLS_SSL_DEBUG_MSG( 2, ("Key exchange mode(%s) is not supported.", ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); goto cleanup; } MBEDTLS_SSL_DEBUG_MSG( 3, ("Selected key exchange mode: %s", ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode))); /* Start the TLS 1.3 key scheduling if not already done. * * If we proposed early data then we have already derived an * early secret using the selected PSK and its associated hash. * It means that if the negotiated key exchange mode is psk or * psk_ephemeral, we have already correctly computed the * early secret and thus we do not do it again. In all other * cases we compute it here. */ #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT || handshake->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL) #endif { ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_key_schedule_stage_early", ret); goto cleanup; } } ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_compute_handshake_transform", ret); goto cleanup; } mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake); MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic")); ssl->session_in = ssl->session_negotiate; cleanup: if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); } return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session_reset_msg_layer(ssl, 0); /* * We are going to re-generate a shared secret corresponding to the group * selected by the server, which is different from the group for which we * generated a shared secret in the first client hello. * Thus, reset the shared secret. */ ret = ssl_tls13_reset_key_share(ssl); if (ret != 0) { return ret; } ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id; #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED; } #endif return 0; } /* * Wait and parse ServerHello handshake message. * Handler for MBEDTLS_SSL_SERVER_HELLO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf = NULL; size_t buf_len = 0; int is_hrr = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len); if (ret < 0) { goto cleanup; } else { is_hrr = (ret == SSL_SERVER_HELLO_HRR); } if (ret == SSL_SERVER_HELLO_TLS1_2) { ret = 0; goto cleanup; } MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_server_hello(ssl, buf, buf + buf_len, is_hrr)); if (is_hrr) { MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl)); } MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, buf_len)); if (is_hrr) { MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl)); #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* If not offering early data, the client sends a dummy CCS record * immediately before its second flight. This may either be before * its second ClientHello or before its encrypted handshake flight. */ mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } else { MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_server_hello(ssl)); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); } cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= %s ( %s )", __func__, is_hrr ? "HelloRetryRequest" : "ServerHello")); return ret; } /* * * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS * * The EncryptedExtensions message contains any extensions which * should be protected, i.e., any which are not needed to establish * the cryptographic context. */ /* Parse EncryptedExtensions message * struct { * Extension extensions<0..2^16-1>; * } EncryptedExtensions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = 0; size_t extensions_len; const unsigned char *p = buf; const unsigned char *extensions_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; MBEDTLS_SSL_DEBUG_BUF(3, "encrypted extensions", p, extensions_len); handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; /* * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_EE); if (ret != 0) { return ret; } switch (extension_type) { #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); if ((ret = ssl_tls13_parse_alpn_ext( ssl, p, (size_t) extension_data_len)) != 0) { return ret; } break; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_TLS_EXT_EARLY_DATA: if (extension_data_len != 0) { /* The message must be empty. */ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); ret = mbedtls_ssl_tls13_parse_record_size_limit_ext( ssl, p, p + extension_data_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret); return ret; } break; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, extension_type, "( ignored )"); break; } p += extension_data_len; } if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) && (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH))) { MBEDTLS_SSL_DEBUG_MSG(3, ( "Record size limit extension cannot be used with max fragment length extension")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, handshake->received_extensions); /* Check that we consumed all the message. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("EncryptedExtension lengths misaligned")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl) { int ret; unsigned char *buf; size_t buf_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf, &buf_len)); /* Process the message contents */ MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len)); #if defined(MBEDTLS_SSL_EARLY_DATA) if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { /* RFC8446 4.2.11 * If the server supplies an "early_data" extension, the * client MUST verify that the server's selected_identity * is 0. If any other value is returned, the client MUST * abort the handshake with an "illegal_parameter" alert. * * RFC 8446 4.2.10 * In order to accept early data, the server MUST have accepted a PSK * cipher suite and selected the first key offered in the client's * "pre_shared_key" extension. In addition, it MUST verify that the * following values are the same as those associated with the * selected PSK: * - The TLS version number * - The selected cipher suite * - The selected ALPN [RFC7301] protocol, if any * * The server has sent an early data extension in its Encrypted * Extension message thus accepted to receive early data. We * check here that the additional constraints on the handshake * parameters, when early data are exchanged, are met, * namely: * - a PSK has been selected for the handshake * - the selected PSK for the handshake was the first one proposed * by the client. * - the selected ciphersuite for the handshake is the ciphersuite * associated with the selected PSK. */ if ((!mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) || handshake->selected_identity != 0 || handshake->ciphersuite_info->id != ssl->session_negotiate->ciphersuite) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED; } else if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED; } #endif /* * In case the client has proposed a PSK associated with a ticket, * `ssl->session_negotiate->ciphersuite` still contains at this point the * identifier of the ciphersuite associated with the ticket. This is that * way because, if an exchange of early data is agreed upon, we need * it to check that the ciphersuite selected for the handshake is the * ticket ciphersuite (see above). This information is not needed * anymore thus we can now set it to the identifier of the ciphersuite * used in this session under negotiation. */ ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, buf_len)); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); } #else ((void) ssl); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); #endif cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse encrypted extensions")); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) /* * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA * * RFC 8446 section 4.5 * * struct {} EndOfEarlyData; * * If the server sent an "early_data" extension in EncryptedExtensions, the * client MUST send an EndOfEarlyData message after receiving the server * Finished. Otherwise, the client MUST NOT send an EndOfEarlyData message. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_end_of_early_data(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf = NULL; size_t buf_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write EndOfEarlyData")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_hdr_to_checksum( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, 0)); MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_finish_handshake_msg(ssl, buf_len, 0)); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write EndOfEarlyData")); return ret; } int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl) { if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) || (!mbedtls_ssl_is_handshake_over(ssl))) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } switch (ssl->early_data_state) { case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT: return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED; break; case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED: return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED; break; case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED: return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED; break; default: return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } } #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * STATE HANDLING: CertificateRequest * */ #define SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST 0 #define SSL_CERTIFICATE_REQUEST_SKIP 1 /* Coordination: * Deals with the ambiguity of not knowing if a CertificateRequest * will be sent. Returns a negative code on failure, or * - SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST * - SSL_CERTIFICATE_REQUEST_SKIP * indicating if a Certificate Request is expected or not. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } ssl->keep_current_message = 1; if ((ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE) && (ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST)) { MBEDTLS_SSL_DEBUG_MSG(3, ("got a certificate request")); return SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST; } MBEDTLS_SSL_DEBUG_MSG(3, ("got no certificate request")); return SSL_CERTIFICATE_REQUEST_SKIP; } /* * ssl_tls13_parse_certificate_request() * Parse certificate request * struct { * opaque certificate_request_context<0..2^8-1>; * Extension extensions<2..2^16-1>; * } CertificateRequest; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_certificate_request(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; size_t certificate_request_context_len = 0; size_t extensions_len = 0; const unsigned char *extensions_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* ... * opaque certificate_request_context<0..2^8-1> * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); certificate_request_context_len = (size_t) p[0]; p += 1; if (certificate_request_context_len > 0) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_request_context_len); MBEDTLS_SSL_DEBUG_BUF(3, "Certificate Request Context", p, certificate_request_context_len); handshake->certificate_request_context = mbedtls_calloc(1, certificate_request_context_len); if (handshake->certificate_request_context == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small")); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(handshake->certificate_request_context, p, certificate_request_context_len); p += certificate_request_context_len; } /* ... * Extension extensions<2..2^16-1>; * ... */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CR); if (ret != 0) { return ret; } switch (extension_type) { case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature algorithms extension")); ret = mbedtls_ssl_parse_sig_alg_ext(ssl, p, p + extension_data_len); if (ret != 0) { return ret; } break; default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, handshake->received_extensions); /* Check that we consumed all the message. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("CertificateRequest misaligned")); goto decode_error; } /* RFC 8446 section 4.3.2 * * The "signature_algorithms" extension MUST be specified */ if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(SIG_ALG)) == 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithms extension found")); goto decode_error; } ssl->handshake->client_auth = 1; return 0; decode_error: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* * Handler for MBEDTLS_SSL_CERTIFICATE_REQUEST */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate request")); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); if (ret == SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST) { unsigned char *buf; size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request( ssl, buf, buf + buf_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, buf_len)); } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { ret = 0; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate request")); return ret; } /* * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_server_certificate(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_process_certificate(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); return 0; } /* * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Handler for MBEDTLS_SSL_SERVER_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_process_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_application_transform(ssl); if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) { ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED; mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); } else #endif /* MBEDTLS_SSL_EARLY_DATA */ { #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ } return 0; } /* * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_client_certificate(mbedtls_ssl_context *ssl) { int non_empty_certificate_msg = 0; MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake traffic keys for outbound traffic")); mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (ssl->handshake->client_auth) { int ret = mbedtls_ssl_tls13_write_certificate(ssl); if (ret != 0) { return ret; } if (mbedtls_ssl_own_cert(ssl) != NULL) { non_empty_certificate_msg = 1; } } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate")); } #endif if (non_empty_certificate_msg) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip write certificate verify")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); } return 0; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_client_certificate_verify(mbedtls_ssl_context *ssl) { int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); } return ret; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Handler for MBEDTLS_SSL_CLIENT_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_write_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret); return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_FLUSH_BUFFERS); return 0; } /* * Handler for MBEDTLS_SSL_FLUSH_BUFFERS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_flush_buffers(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); return 0; } /* * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) { mbedtls_ssl_tls13_handshake_wrapup(ssl); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); return 0; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) #if defined(MBEDTLS_SSL_EARLY_DATA) /* From RFC 8446 section 4.2.10 * * struct { * select (Handshake.msg_type) { * case new_session_ticket: uint32 max_early_data_size; * ... * }; * } EarlyDataIndication; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_new_session_ticket_early_data_ext( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { mbedtls_ssl_session *session = ssl->session; MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 4); session->max_early_data_size = MBEDTLS_GET_UINT32_BE(buf, 0); mbedtls_ssl_tls13_session_set_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); MBEDTLS_SSL_DEBUG_MSG( 3, ("received max_early_data_size: %u", (unsigned int) session->max_early_data_size)); return 0; } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; const unsigned char *p = buf; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < end) { unsigned int extension_type; size_t extension_data_len; int ret; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_NST); if (ret != 0) { return ret; } switch (extension_type) { #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_TLS_EXT_EARLY_DATA: ret = ssl_tls13_parse_new_session_ticket_early_data_ext( ssl, p, p + extension_data_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_new_session_ticket_early_data_ext", ret); } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, handshake->received_extensions); return 0; } /* * From RFC8446, page 74 * * struct { * uint32 ticket_lifetime; * uint32 ticket_age_add; * opaque ticket_nonce<0..255>; * opaque ticket<1..2^16-1>; * Extension extensions<0..2^16-2>; * } NewSessionTicket; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, unsigned char **ticket_nonce, size_t *ticket_nonce_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; mbedtls_ssl_session *session = ssl->session; size_t ticket_len; unsigned char *ticket; size_t extensions_len; *ticket_nonce = NULL; *ticket_nonce_len = 0; /* * ticket_lifetime 4 bytes * ticket_age_add 4 bytes * ticket_nonce_len 1 byte */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 9); session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u", (unsigned int) session->ticket_lifetime)); if (session->ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) { MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime exceeds 7 days.")); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", (unsigned int) session->ticket_age_add)); *ticket_nonce_len = p[8]; p += 9; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, *ticket_nonce_len); *ticket_nonce = p; MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", *ticket_nonce, *ticket_nonce_len); p += *ticket_nonce_len; /* Ticket */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); ticket_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ticket_len); MBEDTLS_SSL_DEBUG_BUF(3, "received ticket", p, ticket_len); /* Check if we previously received a ticket already. */ if (session->ticket != NULL || session->ticket_len > 0) { mbedtls_free(session->ticket); session->ticket = NULL; session->ticket_len = 0; } if ((ticket = mbedtls_calloc(1, ticket_len)) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ticket alloc failed")); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ticket, p, ticket_len); p += ticket_len; session->ticket = ticket; session->ticket_len = ticket_len; /* Clear all flags in ticket_flags */ mbedtls_ssl_tls13_session_clear_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); MBEDTLS_SSL_DEBUG_BUF(3, "ticket extension", p, extensions_len); ret = ssl_tls13_parse_new_session_ticket_exts(ssl, p, p + extensions_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_parse_new_session_ticket_exts", ret); return ret; } return 0; } /* Non negative return values for ssl_tls13_postprocess_new_session_ticket(). * - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the * application that a valid ticket has been received. * - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the * connection alive but we do not signal the ticket to the application. */ #define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0 #define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl, unsigned char *ticket_nonce, size_t ticket_nonce_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session *session = ssl->session; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; psa_algorithm_t psa_hash_alg; int hash_length; if (session->ticket_lifetime == 0) { return POSTPROCESS_NEW_SESSION_TICKET_DISCARD; } #if defined(MBEDTLS_HAVE_TIME) /* Store ticket creation time */ session->ticket_reception_time = mbedtls_ms_time(); #endif ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite); if (ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_length = PSA_HASH_LENGTH(psa_hash_alg); if (hash_length == -1 || (size_t) hash_length > sizeof(session->resumption_key)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", session->app_secrets.resumption_master_secret, hash_length); /* Compute resumption key * * HKDF-Expand-Label( resumption_master_secret, * "resumption", ticket_nonce, Hash.length ) */ ret = mbedtls_ssl_tls13_hkdf_expand_label( psa_hash_alg, session->app_secrets.resumption_master_secret, hash_length, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), ticket_nonce, ticket_nonce_len, session->resumption_key, hash_length); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(2, "Creating the ticket-resumed PSK failed", ret); return ret; } session->resumption_key_len = hash_length; MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", session->resumption_key, session->resumption_key_len); /* Set ticket_flags depends on the selected key exchange modes */ mbedtls_ssl_tls13_session_set_ticket_flags( session, ssl->conf->tls13_kex_modes); MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL; } /* * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len; unsigned char *ticket_nonce; size_t ticket_nonce_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse new session ticket")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, &buf, &buf_len)); /* * We are about to update (maybe only partially) ticket data thus block * any session export for the time being. */ ssl->session->exported = 1; MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket( ssl, buf, buf + buf_len, &ticket_nonce, &ticket_nonce_len)); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket( ssl, ticket_nonce, ticket_nonce_len)); switch (ret) { case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL: /* * All good, we have received a new valid ticket, session data can * be exported now and we signal the ticket to the application. */ ssl->session->exported = 0; ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET; break; case POSTPROCESS_NEW_SESSION_TICKET_DISCARD: ret = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("Discard new session ticket")); break; default: ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse new session ticket")); return ret; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl) { int ret = 0; switch (ssl->state) { case MBEDTLS_SSL_HELLO_REQUEST: mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; case MBEDTLS_SSL_CLIENT_HELLO: ret = mbedtls_ssl_write_client_hello(ssl); break; case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_tls13_process_server_hello(ssl); break; case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: ret = ssl_tls13_process_encrypted_extensions(ssl); break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_tls13_process_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = ssl_tls13_process_server_certificate(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_tls13_process_certificate_verify(ssl); break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ case MBEDTLS_SSL_SERVER_FINISHED: ret = ssl_tls13_process_server_finished(ssl); break; #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_END_OF_EARLY_DATA: ret = ssl_tls13_write_end_of_early_data(ssl); break; #endif case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = ssl_tls13_write_client_certificate(ssl); break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: ret = ssl_tls13_write_client_certificate_verify(ssl); break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ case MBEDTLS_SSL_CLIENT_FINISHED: ret = ssl_tls13_write_client_finished(ssl); break; case MBEDTLS_SSL_FLUSH_BUFFERS: ret = ssl_tls13_flush_buffers(ssl); break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: ret = ssl_tls13_handshake_wrapup(ssl); break; /* * Injection of dummy-CCS's for middlebox compatibility */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret != 0) { break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); break; case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret != 0) { break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); break; #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to early data keys for outbound traffic")); mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_earlydata); ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE; } break; #endif /* MBEDTLS_SSL_EARLY_DATA */ #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: ret = ssl_tls13_process_new_session_ticket(ssl); break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } return ret; } #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_TLS1_3 */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c000066400000000000000000001755571464416617300250470ustar00rootroot00000000000000/* * TLS 1.3 functionality shared between client and server * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_TLS_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) #include #include "mbedtls/error.h" #include "debug_internal.h" #include "mbedtls/oid.h" #include "mbedtls/platform.h" #include "mbedtls/constant_time.h" #include "psa/crypto.h" #include "mbedtls/psa_util.h" #include "ssl_misc.h" #include "ssl_tls13_invasive.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" #include "psa/crypto.h" #include "psa_util_internal.h" #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #endif const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[ MBEDTLS_SERVER_HELLO_RANDOM_LEN] = { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C }; int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type, unsigned char **buf, size_t *buf_len) { int ret; if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); goto cleanup; } if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || ssl->in_msg[0] != hs_type) { MBEDTLS_SSL_DEBUG_MSG(1, ("Receive unexpected handshake message.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; goto cleanup; } /* * Jump handshake header (4 bytes, see Section 4 of RFC 8446). * ... * HandshakeType msg_type; * uint24 length; * ... */ *buf = ssl->in_msg + 4; *buf_len = ssl->in_hslen - 4; cleanup: return ret; } int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, const unsigned char **supported_versions_data, const unsigned char **supported_versions_data_end) { const unsigned char *p = buf; size_t extensions_len; const unsigned char *extensions_end; *supported_versions_data = NULL; *supported_versions_data_end = NULL; /* Case of no extension */ if (p == end) { return 0; } /* ... * Extension extensions; * ... * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check extensions do not go beyond the buffer of data. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) { *supported_versions_data = p; *supported_versions_data_end = p + extension_data_len; return 1; } p += extension_data_len; } return 0; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * STATE HANDLING: Read CertificateVerify */ /* Macro to express the maximum length of the verify structure. * * The structure is computed per TLS 1.3 specification as: * - 64 bytes of octet 32, * - 33 bytes for the context string * (which is either "TLS 1.3, client CertificateVerify" * or "TLS 1.3, server CertificateVerify"), * - 1 byte for the octet 0x0, which serves as a separator, * - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate) * (depending on the size of the transcript_hash) * * This results in a total size of * - 130 bytes for a SHA256-based transcript hash, or * (64 + 33 + 1 + 32 bytes) * - 146 bytes for a SHA384-based transcript hash. * (64 + 33 + 1 + 48 bytes) * */ #define SSL_VERIFY_STRUCT_MAX_SIZE (64 + \ 33 + \ 1 + \ MBEDTLS_TLS1_3_MD_MAX_SIZE \ ) /* * The ssl_tls13_create_verify_structure() creates the verify structure. * As input, it requires the transcript hash. * * The caller has to ensure that the buffer has size at least * SSL_VERIFY_STRUCT_MAX_SIZE bytes. */ static void ssl_tls13_create_verify_structure(const unsigned char *transcript_hash, size_t transcript_hash_len, unsigned char *verify_buffer, size_t *verify_buffer_len, int from) { size_t idx; /* RFC 8446, Section 4.4.3: * * The digital signature [in the CertificateVerify message] is then * computed over the concatenation of: * - A string that consists of octet 32 (0x20) repeated 64 times * - The context string * - A single 0 byte which serves as the separator * - The content to be signed */ memset(verify_buffer, 0x20, 64); idx = 64; if (from == MBEDTLS_SSL_IS_CLIENT) { memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv)); idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv); } else { /* from == MBEDTLS_SSL_IS_SERVER */ memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv)); idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv); } verify_buffer[idx++] = 0x0; memcpy(verify_buffer + idx, transcript_hash, transcript_hash_len); idx += transcript_hash_len; *verify_buffer_len = idx; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end, const unsigned char *verify_buffer, size_t verify_buffer_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; uint16_t algorithm; size_t signature_len; mbedtls_pk_type_t sig_alg; mbedtls_md_type_t md_alg; psa_algorithm_t hash_alg = PSA_ALG_NONE; unsigned char verify_hash[PSA_HASH_MAX_SIZE]; size_t verify_hash_len; void const *options = NULL; #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_pk_rsassa_pss_options rsassa_pss_options; #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ /* * struct { * SignatureScheme algorithm; * opaque signature<0..2^16-1>; * } CertificateVerify; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); algorithm = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* RFC 8446 section 4.4.3 * * If the CertificateVerify message is sent by a server, the signature * algorithm MUST be one offered in the client's "signature_algorithms" * extension unless no valid certificate chain can be produced without * unsupported algorithms * * RFC 8446 section 4.4.2.2 * * If the client cannot construct an acceptable chain using the provided * certificates and decides to abort the handshake, then it MUST abort the * handshake with an appropriate certificate-related alert * (by default, "unsupported_certificate"). * * Check if algorithm is an offered signature algorithm. */ if (!mbedtls_ssl_sig_alg_is_offered(ssl, algorithm)) { /* algorithm not in offered signature algorithms list */ MBEDTLS_SSL_DEBUG_MSG(1, ("Received signature algorithm(%04x) is not " "offered.", (unsigned int) algorithm)); goto error; } if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( algorithm, &sig_alg, &md_alg) != 0) { goto error; } hash_alg = mbedtls_md_psa_alg_from_type(md_alg); if (hash_alg == 0) { goto error; } MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate Verify: Signature algorithm ( %04x )", (unsigned int) algorithm)); /* * Check the certificate's key type matches the signature alg */ if (!mbedtls_pk_can_do(&ssl->session_negotiate->peer_cert->pk, sig_alg)) { MBEDTLS_SSL_DEBUG_MSG(1, ("signature algorithm doesn't match cert key")); goto error; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); signature_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, signature_len); status = psa_hash_compute(hash_alg, verify_buffer, verify_buffer_len, verify_hash, sizeof(verify_hash), &verify_hash_len); if (status != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET(1, "hash computation PSA error", status); goto error; } MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (sig_alg == MBEDTLS_PK_RSASSA_PSS) { rsassa_pss_options.mgf1_hash_id = md_alg; rsassa_pss_options.expected_salt_len = PSA_HASH_LENGTH(hash_alg); options = (const void *) &rsassa_pss_options; } #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ if ((ret = mbedtls_pk_verify_ext(sig_alg, options, &ssl->session_negotiate->peer_cert->pk, md_alg, verify_hash, verify_hash_len, p, signature_len)) == 0) { return 0; } MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_pk_verify_ext", ret); error: /* RFC 8446 section 4.4.3 * * If the verification fails, the receiver MUST terminate the handshake * with a "decrypt_error" alert. */ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; size_t verify_buffer_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; unsigned char *buf; size_t buf_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify")); MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); /* Need to calculate the hash of the transcript first * before reading the message since otherwise it gets * included in the transcript */ ret = mbedtls_ssl_get_handshake_transcript( ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, MBEDTLS_ERR_SSL_INTERNAL_ERROR); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", transcript, transcript_len); /* Create verify structure */ ssl_tls13_create_verify_structure(transcript, transcript_len, verify_buffer, &verify_buffer_len, (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT); /* Process the message contents */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify( ssl, buf, buf + buf_len, verify_buffer, verify_buffer_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf, buf_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate verify")); MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_process_certificate_verify", ret); return ret; #else ((void) ssl); MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ } /* * * STATE HANDLING: Incoming Certificate. * */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* * Structure of Certificate message: * * enum { * X509(0), * RawPublicKey(2), * (255) * } CertificateType; * * struct { * select (certificate_type) { * case RawPublicKey: * * From RFC 7250 ASN.1_subjectPublicKeyInfo * * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; * case X509: * opaque cert_data<1..2^24-1>; * }; * Extension extensions<0..2^16-1>; * } CertificateEntry; * * struct { * opaque certificate_request_context<0..2^8-1>; * CertificateEntry certificate_list<0..2^24-1>; * } Certificate; * */ /* Parse certificate chain send by the server. */ MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t certificate_request_context_len = 0; size_t certificate_list_len = 0; const unsigned char *p = buf; const unsigned char *certificate_list_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 4); certificate_request_context_len = p[0]; certificate_list_len = MBEDTLS_GET_UINT24_BE(p, 1); p += 4; /* In theory, the certificate list can be up to 2^24 Bytes, but we don't * support anything beyond 2^16 = 64K. */ if ((certificate_request_context_len != 0) || (certificate_list_len >= 0x10000)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* In case we tried to reuse a session but it failed */ if (ssl->session_negotiate->peer_cert != NULL) { mbedtls_x509_crt_free(ssl->session_negotiate->peer_cert); mbedtls_free(ssl->session_negotiate->peer_cert); } if (certificate_list_len == 0) { ssl->session_negotiate->peer_cert = NULL; ret = 0; goto exit; } if ((ssl->session_negotiate->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt))) == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed", sizeof(mbedtls_x509_crt))); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, MBEDTLS_ERR_SSL_ALLOC_FAILED); return MBEDTLS_ERR_SSL_ALLOC_FAILED; } mbedtls_x509_crt_init(ssl->session_negotiate->peer_cert); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, certificate_list_len); certificate_list_end = p + certificate_list_len; while (p < certificate_list_end) { size_t cert_data_len, extensions_len; const unsigned char *extensions_end; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 3); cert_data_len = MBEDTLS_GET_UINT24_BE(p, 0); p += 3; /* In theory, the CRT can be up to 2^24 Bytes, but we don't support * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code, * check that we have a minimum of 128 bytes of data, this is not * clear why we need that though. */ if ((cert_data_len < 128) || (cert_data_len >= 0x10000)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, cert_data_len); ret = mbedtls_x509_crt_parse_der(ssl->session_negotiate->peer_cert, p, cert_data_len); switch (ret) { case 0: /*ok*/ break; case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: /* Ignore certificate with an unknown algorithm: maybe a prior certificate was already trusted. */ break; case MBEDTLS_ERR_X509_ALLOC_FAILED: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, MBEDTLS_ERR_X509_ALLOC_FAILED); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; case MBEDTLS_ERR_X509_UNKNOWN_VERSION: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, MBEDTLS_ERR_X509_UNKNOWN_VERSION); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; default: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret); MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret); return ret; } p += cert_data_len; /* Certificate extensions length */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, 2); extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, certificate_list_end, extensions_len); extensions_end = p + extensions_len; handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; /* * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_CERTIFICATE, extension_type, MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CT); if (ret != 0) { return ret; } switch (extension_type) { default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_CERTIFICATE, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CERTIFICATE, handshake->received_extensions); } exit: /* Check that all the message is consumed. */ if (p != end) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad Certificate message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", ssl->session_negotiate->peer_cert); return ret; } #else MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_STATIC_TESTABLE int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { ((void) ssl); ((void) buf); ((void) end); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* Validate certificate chain sent by the server. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) { int ret = 0; int authmode = MBEDTLS_SSL_VERIFY_REQUIRED; mbedtls_x509_crt *ca_chain; mbedtls_x509_crl *ca_crl; const char *ext_oid; size_t ext_len; uint32_t verify_result = 0; /* If SNI was used, overwrite authentication mode * from the configuration. */ #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { authmode = ssl->handshake->sni_authmode; } else #endif authmode = ssl->conf->authmode; } #endif /* * If the peer hasn't sent a certificate ( i.e. it sent * an empty certificate chain ), this is reflected in the peer CRT * structure being unset. * Check for that and handle it depending on the * authentication mode. */ if (ssl->session_negotiate->peer_cert == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate")); #if defined(MBEDTLS_SSL_SRV_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) { /* The client was asked for a certificate but didn't send * one. The client should know what's going on, so we * don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) { return 0; } else { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_NO_CERT, MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE); return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; } } #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT, MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE); return MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE; } #endif /* MBEDTLS_SSL_CLI_C */ } #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_ca_chain != NULL) { ca_chain = ssl->handshake->sni_ca_chain; ca_crl = ssl->handshake->sni_ca_crl; } else #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ { ca_chain = ssl->conf->ca_chain; ca_crl = ssl->conf->ca_crl; } /* * Main check: verify certificate */ ret = mbedtls_x509_crt_verify_with_profile( ssl->session_negotiate->peer_cert, ca_chain, ca_crl, ssl->conf->cert_profile, ssl->hostname, &verify_result, ssl->conf->f_vrfy, ssl->conf->p_vrfy); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret); } /* * Secondary checks: always done, but change 'ret' only if it was 0 */ if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) { ext_oid = MBEDTLS_OID_SERVER_AUTH; ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH); } else { ext_oid = MBEDTLS_OID_CLIENT_AUTH; ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH); } if ((mbedtls_x509_crt_check_key_usage( ssl->session_negotiate->peer_cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0) || (mbedtls_x509_crt_check_extended_key_usage( ssl->session_negotiate->peer_cert, ext_oid, ext_len) != 0)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)")); if (ret == 0) { ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; } } /* mbedtls_x509_crt_verify_with_profile is supposed to report a * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, * with details encoded in the verification flags. All other kinds * of error codes, including those from the user provided f_vrfy * functions, are treated as fatal and lead to a failure of * mbedtls_ssl_tls13_parse_certificate even if verification was optional. */ if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) { ret = 0; } if (ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) { MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain")); ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; } if (ret != 0) { /* The certificate may have been rejected for several reasons. Pick one and send the corresponding alert. Which alert to send may be a subject of debate in some cases. */ if (verify_result & MBEDTLS_X509_BADCERT_OTHER) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret); } else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret); } else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE | MBEDTLS_X509_BADCERT_EXT_KEY_USAGE | MBEDTLS_X509_BADCERT_NS_CERT_TYPE | MBEDTLS_X509_BADCERT_BAD_PK | MBEDTLS_X509_BADCERT_BAD_KEY)) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret); } else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret); } else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret); } else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret); } else { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret); } } #if defined(MBEDTLS_DEBUG_C) if (verify_result != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x", (unsigned int) verify_result)); } else { MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear")); } #endif /* MBEDTLS_DEBUG_C */ ssl->session_negotiate->verify_result = verify_result; return ret; } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl) { ((void) ssl); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate")); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) unsigned char *buf; size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len)); /* Parse the certificate chain sent by the peer. */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_parse_certificate(ssl, buf, buf + buf_len)); /* Validate the certificate chain and set the verification results. */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, buf_len)); cleanup: #else /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ (void) ssl; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate")); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) /* * enum { * X509(0), * RawPublicKey(2), * (255) * } CertificateType; * * struct { * select (certificate_type) { * case RawPublicKey: * // From RFC 7250 ASN.1_subjectPublicKeyInfo * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; * * case X509: * opaque cert_data<1..2^24-1>; * }; * Extension extensions<0..2^16-1>; * } CertificateEntry; * * struct { * opaque certificate_request_context<0..2^8-1>; * CertificateEntry certificate_list<0..2^24-1>; * } Certificate; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { const mbedtls_x509_crt *crt = mbedtls_ssl_own_cert(ssl); unsigned char *p = buf; unsigned char *certificate_request_context = ssl->handshake->certificate_request_context; unsigned char certificate_request_context_len = ssl->handshake->certificate_request_context_len; unsigned char *p_certificate_list_len; /* ... * opaque certificate_request_context<0..2^8-1>; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, certificate_request_context_len + 1); *p++ = certificate_request_context_len; if (certificate_request_context_len > 0) { memcpy(p, certificate_request_context, certificate_request_context_len); p += certificate_request_context_len; } /* ... * CertificateEntry certificate_list<0..2^24-1>; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); p_certificate_list_len = p; p += 3; MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", crt); while (crt != NULL) { size_t cert_data_len = crt->raw.len; MBEDTLS_SSL_CHK_BUF_PTR(p, end, cert_data_len + 3 + 2); MBEDTLS_PUT_UINT24_BE(cert_data_len, p, 0); p += 3; memcpy(p, crt->raw.p, cert_data_len); p += cert_data_len; crt = crt->next; /* Currently, we don't have any certificate extensions defined. * Hence, we are sending an empty extension with length zero. */ MBEDTLS_PUT_UINT16_BE(0, p, 0); p += 2; } MBEDTLS_PUT_UINT24_BE(p - p_certificate_list_len - 3, p_certificate_list_len, 0); *out_len = p - buf; MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_CERTIFICATE, ssl->handshake->sent_extensions); return 0; } int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl) { int ret; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate")); return ret; } /* * STATE HANDLING: Output Certificate Verify */ int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg, mbedtls_pk_context *key) { mbedtls_pk_type_t pk_type = (mbedtls_pk_type_t) mbedtls_ssl_sig_from_pk(key); size_t key_size = mbedtls_pk_get_bitlen(key); switch (pk_type) { case MBEDTLS_SSL_SIG_ECDSA: switch (key_size) { case 256: return sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256; case 384: return sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384; case 521: return sig_alg == MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512; default: break; } break; case MBEDTLS_SSL_SIG_RSA: switch (sig_alg) { case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: /* Intentional fallthrough */ case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: /* Intentional fallthrough */ case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: return 1; default: break; } break; default: break; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; mbedtls_pk_context *own_key; unsigned char handshake_hash[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t handshake_hash_len; unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; size_t verify_buffer_len; uint16_t *sig_alg = ssl->handshake->received_sig_algs; size_t signature_len = 0; *out_len = 0; own_key = mbedtls_ssl_own_key(ssl); if (own_key == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ssl_get_handshake_transcript( ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac, handshake_hash, sizeof(handshake_hash), &handshake_hash_len); if (ret != 0) { return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "handshake hash", handshake_hash, handshake_hash_len); ssl_tls13_create_verify_structure(handshake_hash, handshake_hash_len, verify_buffer, &verify_buffer_len, ssl->conf->endpoint); /* * struct { * SignatureScheme algorithm; * opaque signature<0..2^16-1>; * } CertificateVerify; */ /* Check there is space for the algorithm identifier (2 bytes) and the * signature length (2 bytes). */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4); for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; mbedtls_pk_type_t pk_type = MBEDTLS_PK_NONE; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; psa_algorithm_t psa_algorithm = PSA_ALG_NONE; unsigned char verify_hash[PSA_HASH_MAX_SIZE]; size_t verify_hash_len; if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { continue; } if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { continue; } if (!mbedtls_ssl_tls13_check_sig_alg_cert_key_match(*sig_alg, own_key)) { continue; } if (mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg( *sig_alg, &pk_type, &md_alg) != 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Hash verify buffer with indicated hash function */ psa_algorithm = mbedtls_md_psa_alg_from_type(md_alg); status = psa_hash_compute(psa_algorithm, verify_buffer, verify_buffer_len, verify_hash, sizeof(verify_hash), &verify_hash_len); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len); if ((ret = mbedtls_pk_sign_ext(pk_type, own_key, md_alg, verify_hash, verify_hash_len, p + 4, (size_t) (end - (p + 4)), &signature_len, ssl->conf->f_rng, ssl->conf->p_rng)) != 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature failed with %s", mbedtls_ssl_sig_alg_to_str(*sig_alg))); MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_pk_sign_ext", ret); /* The signature failed. This is possible if the private key * was not suitable for the signature operation as purposely we * did not check its suitability completely. Let's try with * another signature algorithm. */ continue; } MBEDTLS_SSL_DEBUG_MSG(2, ("CertificateVerify signature with %s", mbedtls_ssl_sig_alg_to_str(*sig_alg))); break; } if (*sig_alg == MBEDTLS_TLS1_3_SIG_NONE) { MBEDTLS_SSL_DEBUG_MSG(1, ("no suitable signature algorithm")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_PUT_UINT16_BE(*sig_alg, p, 0); MBEDTLS_PUT_UINT16_BE(signature_len, p, 2); *out_len = 4 + signature_len; return 0; } int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) { int ret = 0; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate verify")); return ret; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * * STATE HANDLING: Incoming Finished message. */ /* * Implementation */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl) { int ret; ret = mbedtls_ssl_tls13_calculate_verify_data( ssl, ssl->handshake->state_local.finished_in.digest, sizeof(ssl->handshake->state_local.finished_in.digest), &ssl->handshake->state_local.finished_in.digest_len, ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_calculate_verify_data", ret); return ret; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_finished_message(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* * struct { * opaque verify_data[Hash.length]; * } Finished; */ const unsigned char *expected_verify_data = ssl->handshake->state_local.finished_in.digest; size_t expected_verify_data_len = ssl->handshake->state_local.finished_in.digest_len; /* Structural validation */ if ((size_t) (end - buf) != expected_verify_data_len) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (self-computed):", expected_verify_data, expected_verify_data_len); MBEDTLS_SSL_DEBUG_BUF(4, "verify_data (received message):", buf, expected_verify_data_len); /* Semantic validation */ if (mbedtls_ct_memcmp(buf, expected_verify_data, expected_verify_data_len) != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } return 0; } int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); /* Preprocessing step: Compute handshake digest */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message( ssl, buf, buf + buf_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_FINISHED, buf, buf_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished message")); return ret; } /* * * STATE HANDLING: Write and send Finished message. * */ /* * Implement */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_finished_message(mbedtls_ssl_context *ssl) { int ret; /* Compute transcript of handshake up to now. */ ret = mbedtls_ssl_tls13_calculate_verify_data(ssl, ssl->handshake->state_local.finished_out.digest, sizeof(ssl->handshake->state_local.finished_out. digest), &ssl->handshake->state_local.finished_out.digest_len, ssl->conf->endpoint); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "calculate_verify_data failed", ret); return ret; } return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_finished_message_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len; /* * struct { * opaque verify_data[Hash.length]; * } Finished; */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, verify_data_len); memcpy(buf, ssl->handshake->state_local.finished_out.digest, verify_data_len); *out_len = verify_data_len; return 0; } /* Main entry point: orchestrates the other functions */ int mbedtls_ssl_tls13_write_finished_message(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished message")); MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_finished_message(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_finished_message_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl, MBEDTLS_SSL_HS_FINISHED, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished message")); return ret; } void mbedtls_ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup")); MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for inbound traffic")); mbedtls_ssl_set_inbound_transform(ssl, ssl->transform_application); MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to application keys for outbound traffic")); mbedtls_ssl_set_outbound_transform(ssl, ssl->transform_application); /* * Free the previous session and switch to the current one. */ if (ssl->session) { mbedtls_ssl_session_free(ssl->session); mbedtls_free(ssl->session); } ssl->session = ssl->session_negotiate; ssl->session_negotiate = NULL; MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup")); } /* * * STATE HANDLING: Write ChangeCipherSpec * */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_change_cipher_spec_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen) { ((void) ssl); MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 1); buf[0] = 1; *olen = 1; return 0; } int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec")); /* Only one CCS to send. */ if (ssl->handshake->ccs_sent) { ret = 0; goto cleanup; } /* Write CCS message */ MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body( ssl, ssl->out_msg, ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, &ssl->out_msglen)); ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; /* Dispatch message */ MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0)); ssl->handshake->ccs_sent = 1; cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec")); return ret; } #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ /* Early Data Indication Extension * * struct { * select ( Handshake.msg_type ) { * case new_session_ticket: uint32 max_early_data_size; * case client_hello: Empty; * case encrypted_extensions: Empty; * }; * } EarlyDataIndication; */ #if defined(MBEDTLS_SSL_EARLY_DATA) int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl, int in_new_session_ticket, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; #if defined(MBEDTLS_SSL_SRV_C) const size_t needed = in_new_session_ticket ? 8 : 4; #else const size_t needed = 4; ((void) in_new_session_ticket); #endif *out_len = 0; MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0); MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2); #if defined(MBEDTLS_SSL_SRV_C) if (in_new_session_ticket) { MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4); MBEDTLS_SSL_DEBUG_MSG( 4, ("Sent max_early_data_size=%u", (unsigned int) ssl->conf->max_early_data_size)); } #endif *out_len = needed; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA); return 0; } #if defined(MBEDTLS_SSL_SRV_C) int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl, size_t early_data_len) { /* * This function should be called only while an handshake is in progress * and thus a session under negotiation. Add a sanity check to detect a * misuse. */ if (ssl->session_negotiate == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* RFC 8446 section 4.6.1 * * A server receiving more than max_early_data_size bytes of 0-RTT data * SHOULD terminate the connection with an "unexpected_message" alert. * Note that if it is still possible to send early_data_len bytes of early * data, it means that early_data_len is smaller than max_early_data_size * (type uint32_t) and can fit in an uint32_t. We use this further * down. */ if (early_data_len > (ssl->session_negotiate->max_early_data_size - ssl->total_early_data_size)) { MBEDTLS_SSL_DEBUG_MSG( 2, ("EarlyData: Too much early data received, %u + %" MBEDTLS_PRINTF_SIZET " > %u", ssl->total_early_data_size, early_data_len, ssl->session_negotiate->max_early_data_size)); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } /* * early_data_len has been checked to be less than max_early_data_size * that is uint32_t. Its cast to an uint32_t below is thus safe. We need * the cast to appease some compilers. */ ssl->total_early_data_size += (uint32_t) early_data_len; return 0; } #endif /* MBEDTLS_SSL_SRV_C */ #endif /* MBEDTLS_SSL_EARLY_DATA */ /* Reset SSL context and update hash for handling HRR. * * Replace Transcript-Hash(X) by * Transcript-Hash( message_hash || * 00 00 Hash.length || * X ) * A few states of the handshake are preserved, including: * - session ID * - session ticket * - negotiated ciphersuite */ int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char hash_transcript[PSA_HASH_MAX_SIZE + 4]; size_t hash_len; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(3, ("Reset SSL session for HRR")); ret = mbedtls_ssl_get_handshake_transcript(ssl, (mbedtls_md_type_t) ciphersuite_info->mac, hash_transcript + 4, PSA_HASH_MAX_SIZE, &hash_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); return ret; } hash_transcript[0] = MBEDTLS_SSL_HS_MESSAGE_HASH; hash_transcript[1] = 0; hash_transcript[2] = 0; hash_transcript[3] = (unsigned char) hash_len; hash_len += 4; MBEDTLS_SSL_DEBUG_BUF(4, "Truncated handshake transcript", hash_transcript, hash_len); /* Reset running hash and replace it with a hash of the transcript */ ret = mbedtls_ssl_reset_checksum(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_checksum", ret); return ret; } ret = ssl->handshake->update_checksum(ssl, hash_transcript, hash_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "update_checksum", ret); return ret; } return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t buf_len) { uint8_t *p = (uint8_t *) buf; const uint8_t *end = buf + buf_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; /* Check if key size is consistent with given buffer length. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len); /* Store peer's ECDH/FFDH public key. */ if (peerkey_len > sizeof(handshake->xxdh_psa_peerkey)) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %u > %" MBEDTLS_PRINTF_SIZET, (unsigned) peerkey_len, sizeof(handshake->xxdh_psa_peerkey))); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } memcpy(handshake->xxdh_psa_peerkey, p, peerkey_len); handshake->xxdh_psa_peerkey_len = peerkey_len; return 0; } #if defined(PSA_WANT_ALG_FFDH) static psa_status_t mbedtls_ssl_get_psa_ffdh_info_from_tls_id( uint16_t tls_id, size_t *bits, psa_key_type_t *key_type) { switch (tls_id) { #if defined(PSA_WANT_DH_RFC7919_2048) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048: *bits = 2048; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_2048 */ #if defined(PSA_WANT_DH_RFC7919_3072) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072: *bits = 3072; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_3072 */ #if defined(PSA_WANT_DH_RFC7919_4096) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096: *bits = 4096; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_4096 */ #if defined(PSA_WANT_DH_RFC7919_6144) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144: *bits = 6144; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_6144 */ #if defined(PSA_WANT_DH_RFC7919_8192) case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192: *bits = 8192; *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919); return PSA_SUCCESS; #endif /* PSA_WANT_DH_RFC7919_8192 */ default: return PSA_ERROR_NOT_SUPPORTED; } } #endif /* PSA_WANT_ALG_FFDH */ int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( mbedtls_ssl_context *ssl, uint16_t named_group, unsigned char *buf, unsigned char *end, size_t *out_len) { psa_status_t status = PSA_ERROR_GENERIC_ERROR; int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; psa_key_attributes_t key_attributes; size_t own_pubkey_len; mbedtls_ssl_handshake_params *handshake = ssl->handshake; size_t bits = 0; psa_key_type_t key_type = PSA_KEY_TYPE_NONE; psa_algorithm_t alg = PSA_ALG_NONE; size_t buf_size = (size_t) (end - buf); MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH/FFDH computation.")); /* Convert EC's TLS ID to PSA key type. */ #if defined(PSA_WANT_ALG_ECDH) if (mbedtls_ssl_get_psa_curve_info_from_tls_id( named_group, &key_type, &bits) == PSA_SUCCESS) { alg = PSA_ALG_ECDH; } #endif #if defined(PSA_WANT_ALG_FFDH) if (mbedtls_ssl_get_psa_ffdh_info_from_tls_id(named_group, &bits, &key_type) == PSA_SUCCESS) { alg = PSA_ALG_FFDH; } #endif if (key_type == PSA_KEY_TYPE_NONE) { return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } if (buf_size < PSA_BITS_TO_BYTES(bits)) { return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; } handshake->xxdh_psa_type = key_type; ssl->handshake->xxdh_psa_bits = bits; key_attributes = psa_key_attributes_init(); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, handshake->xxdh_psa_type); psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits); /* Generate ECDH/FFDH private key. */ status = psa_generate_key(&key_attributes, &handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret); return ret; } /* Export the public part of the ECDH/FFDH private key from PSA. */ status = psa_export_public_key(handshake->xxdh_psa_privkey, buf, buf_size, &own_pubkey_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret); return ret; } *out_len = own_pubkey_len; return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ /* RFC 8446 section 4.2 * * If an implementation receives an extension which it recognizes and which is * not specified for the message in which it appears, it MUST abort the handshake * with an "illegal_parameter" alert. * */ int mbedtls_ssl_tls13_check_received_extension( mbedtls_ssl_context *ssl, int hs_msg_type, unsigned int received_extension_type, uint32_t hs_msg_allowed_extensions_mask) { uint32_t extension_mask = mbedtls_ssl_get_extension_mask( received_extension_type); MBEDTLS_SSL_PRINT_EXT( 3, hs_msg_type, received_extension_type, "received"); if ((extension_mask & hs_msg_allowed_extensions_mask) == 0) { MBEDTLS_SSL_PRINT_EXT( 3, hs_msg_type, received_extension_type, "is illegal"); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->handshake->received_extensions |= extension_mask; /* * If it is a message containing extension responses, check that we * previously sent the extension. */ switch (hs_msg_type) { case MBEDTLS_SSL_HS_SERVER_HELLO: case MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST: case MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS: case MBEDTLS_SSL_HS_CERTIFICATE: /* Check if the received extension is sent by peer message.*/ if ((ssl->handshake->sent_extensions & extension_mask) != 0) { return 0; } break; default: return 0; } MBEDTLS_SSL_PRINT_EXT( 3, hs_msg_type, received_extension_type, "is unsupported"); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION); return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION; } #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) /* RFC 8449, section 4: * * The ExtensionData of the "record_size_limit" extension is * RecordSizeLimit: * uint16 RecordSizeLimit; */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; uint16_t record_size_limit; const size_t extension_data_len = end - buf; if (extension_data_len != MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) { MBEDTLS_SSL_DEBUG_MSG(2, ("record_size_limit extension has invalid length: %" MBEDTLS_PRINTF_SIZET " Bytes", extension_data_len)); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0); MBEDTLS_SSL_DEBUG_MSG(2, ("RecordSizeLimit: %u Bytes", record_size_limit)); /* RFC 8449, section 4: * * Endpoints MUST NOT send a "record_size_limit" extension with a value * smaller than 64. An endpoint MUST treat receipt of a smaller value * as a fatal error and generate an "illegal_parameter" alert. */ if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) { MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid record size limit : %u Bytes", record_size_limit)); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } ssl->session_negotiate->record_size_limit = record_size_limit; return 0; } MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { unsigned char *p = buf; *out_len = 0; MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_IN_CONTENT_LEN >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN, "MBEDTLS_SSL_IN_CONTENT_LEN is less than the " "minimum record size limit"); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT, p, 0); MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH, p, 2); MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_IN_CONTENT_LEN, p, 4); *out_len = 6; MBEDTLS_SSL_DEBUG_MSG(2, ("Sent RecordSizeLimit: %d Bytes", MBEDTLS_SSL_IN_CONTENT_LEN)); mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT); return 0; } #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h000066400000000000000000000011451464416617300252410ustar00rootroot00000000000000/* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_SSL_TLS13_INVASIVE_H #define MBEDTLS_SSL_TLS13_INVASIVE_H #include "common.h" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "psa/crypto.h" #if defined(MBEDTLS_TEST_HOOKS) int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end); #endif /* MBEDTLS_TEST_HOOKS */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_TLS13_INVASIVE_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c000066400000000000000000001763021464416617300243730ustar00rootroot00000000000000/* * TLS 1.3 key schedule * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #include #include #include "mbedtls/hkdf.h" #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "ssl_misc.h" #include "ssl_tls13_keys.h" #include "ssl_tls13_invasive.h" #include "psa/crypto.h" #include "mbedtls/psa_util.h" /* Define a local translating function to save code size by not using too many * arguments in each translating place. */ static int local_err_translation(psa_status_t status) { return psa_status_to_mbedtls(status, psa_to_ssl_errors, ARRAY_LENGTH(psa_to_ssl_errors), psa_generic_status_to_mbedtls); } #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status) #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ .name = string, struct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_labels = { /* This seems to work in C, despite the string literal being one * character too long due to the 0-termination. */ MBEDTLS_SSL_TLS1_3_LABEL_LIST }; #undef MBEDTLS_SSL_TLS1_3_LABEL /* * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule. * * The HkdfLabel is specified in RFC 8446 as follows: * * struct HkdfLabel { * uint16 length; // Length of expanded key material * opaque label<7..255>; // Always prefixed by "tls13 " * opaque context<0..255>; // Usually a communication transcript hash * }; * * Parameters: * - desired_length: Length of expanded key material * Even though the standard allows expansion to up to * 2**16 Bytes, TLS 1.3 never uses expansion to more than * 255 Bytes, so we require `desired_length` to be at most * 255. This allows us to save a few Bytes of code by * hardcoding the writing of the high bytes. * - (label, label_len): label + label length, without "tls13 " prefix * The label length MUST be less than or equal to * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN * It is the caller's responsibility to ensure this. * All (label, label length) pairs used in TLS 1.3 * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). * - (ctx, ctx_len): context + context length * The context length MUST be less than or equal to * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN * It is the caller's responsibility to ensure this. * - dst: Target buffer for HkdfLabel structure, * This MUST be a writable buffer of size * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. * - dst_len: Pointer at which to store the actual length of * the HkdfLabel structure on success. */ static const char tls13_label_prefix[6] = "tls13 "; #define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(label_len, context_len) \ (2 /* expansion length */ \ + 1 /* label length */ \ + label_len \ + 1 /* context length */ \ + context_len) #define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ sizeof(tls13_label_prefix) + \ MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) static void ssl_tls13_hkdf_encode_label( size_t desired_length, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, unsigned char *dst, size_t *dst_len) { size_t total_label_len = sizeof(tls13_label_prefix) + label_len; size_t total_hkdf_lbl_len = SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(total_label_len, ctx_len); unsigned char *p = dst; /* Add the size of the expanded key material. * We're hardcoding the high byte to 0 here assuming that we never use * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ #if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 #error "The implementation of ssl_tls13_hkdf_encode_label() is not fit for the \ value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" #endif *p++ = 0; *p++ = MBEDTLS_BYTE_0(desired_length); /* Add label incl. prefix */ *p++ = MBEDTLS_BYTE_0(total_label_len); memcpy(p, tls13_label_prefix, sizeof(tls13_label_prefix)); p += sizeof(tls13_label_prefix); memcpy(p, label, label_len); p += label_len; /* Add context value */ *p++ = MBEDTLS_BYTE_0(ctx_len); if (ctx_len != 0) { memcpy(p, ctx, ctx_len); } /* Return total length to the caller. */ *dst_len = total_hkdf_lbl_len; } int mbedtls_ssl_tls13_hkdf_expand_label( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, unsigned char *buf, size_t buf_len) { unsigned char hkdf_label[SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN]; size_t hkdf_label_len = 0; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; if (label_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN) { /* Should never happen since this is an internal * function, and we know statically which labels * are allowed. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN) { /* Should not happen, as above. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN) { /* Should not happen, as above. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } ssl_tls13_hkdf_encode_label(buf_len, label, label_len, ctx, ctx_len, hkdf_label, &hkdf_label_len); status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXPAND(hash_alg)); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, secret, secret_len); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_label, hkdf_label_len); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_output_bytes(&operation, buf, buf_len); if (status != PSA_SUCCESS) { goto cleanup; } cleanup: abort_status = psa_key_derivation_abort(&operation); status = (status == PSA_SUCCESS ? abort_status : status); mbedtls_platform_zeroize(hkdf_label, hkdf_label_len); return PSA_TO_MBEDTLS_ERR(status); } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_make_traffic_key( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, unsigned char *key, size_t key_len, unsigned char *iv, size_t iv_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, secret, secret_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(key), NULL, 0, key, key_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, secret, secret_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(iv), NULL, 0, iv, iv_len); return ret; } /* * The traffic keying material is generated from the following inputs: * * - One secret value per sender. * - A purpose value indicating the specific value being generated * - The desired lengths of key and IV. * * The expansion itself is based on HKDF: * * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length ) * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length ) * * [sender] denotes the sending side and the Secret value is provided * by the function caller. Note that we generate server and client side * keys in a single function call. */ int mbedtls_ssl_tls13_make_traffic_keys( psa_algorithm_t hash_alg, const unsigned char *client_secret, const unsigned char *server_secret, size_t secret_len, size_t key_len, size_t iv_len, mbedtls_ssl_key_set *keys) { int ret = 0; ret = ssl_tls13_make_traffic_key( hash_alg, client_secret, secret_len, keys->client_write_key, key_len, keys->client_write_iv, iv_len); if (ret != 0) { return ret; } ret = ssl_tls13_make_traffic_key( hash_alg, server_secret, secret_len, keys->server_write_key, key_len, keys->server_write_iv, iv_len); if (ret != 0) { return ret; } keys->key_len = key_len; keys->iv_len = iv_len; return 0; } int mbedtls_ssl_tls13_derive_secret( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, int ctx_hashed, unsigned char *dstbuf, size_t dstbuf_len) { int ret; unsigned char hashed_context[PSA_HASH_MAX_SIZE]; if (ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED) { psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context, PSA_HASH_LENGTH(hash_alg), &ctx_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); return ret; } } else { if (ctx_len > sizeof(hashed_context)) { /* This should never happen since this function is internal * and the code sets `ctx_hashed` correctly. * Let's double-check nonetheless to not run at the risk * of getting a stack overflow. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(hashed_context, ctx, ctx_len); } return mbedtls_ssl_tls13_hkdf_expand_label(hash_alg, secret, secret_len, label, label_len, hashed_context, ctx_len, dstbuf, dstbuf_len); } int mbedtls_ssl_tls13_evolve_secret( psa_algorithm_t hash_alg, const unsigned char *secret_old, const unsigned char *input, size_t input_len, unsigned char *secret_new) { int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; size_t hlen; unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 }; const unsigned char all_zeroes_input[MBEDTLS_TLS1_3_MD_MAX_SIZE] = { 0 }; const unsigned char *l_input = NULL; size_t l_input_len; psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } hlen = PSA_HASH_LENGTH(hash_alg); /* For non-initial runs, call Derive-Secret( ., "derived", "") * on the old secret. */ if (secret_old != NULL) { ret = mbedtls_ssl_tls13_derive_secret( hash_alg, secret_old, hlen, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(derived), NULL, 0, /* context */ MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, tmp_secret, hlen); if (ret != 0) { goto cleanup; } } ret = 0; if (input != NULL && input_len != 0) { l_input = input; l_input_len = input_len; } else { l_input = all_zeroes_input; l_input_len = hlen; } status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF_EXTRACT(hash_alg)); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, tmp_secret, hlen); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, l_input, l_input_len); if (status != PSA_SUCCESS) { goto cleanup; } status = psa_key_derivation_output_bytes(&operation, secret_new, PSA_HASH_LENGTH(hash_alg)); if (status != PSA_SUCCESS) { goto cleanup; } cleanup: abort_status = psa_key_derivation_abort(&operation); status = (status == PSA_SUCCESS ? abort_status : status); ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret); mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret)); return ret; } int mbedtls_ssl_tls13_derive_early_secrets( psa_algorithm_t hash_alg, unsigned char const *early_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_early_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * 0 * | * v * PSK -> HKDF-Extract = Early Secret * | * +-----> Derive-Secret(., "c e traffic", ClientHello) * | = client_early_traffic_secret * | * +-----> Derive-Secret(., "e exp master", ClientHello) * | = early_exporter_master_secret * v */ /* Create client_early_traffic_secret */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->client_early_traffic_secret, hash_len); if (ret != 0) { return ret; } /* Create early exporter */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->early_exporter_master_secret, hash_len); if (ret != 0) { return ret; } return 0; } int mbedtls_ssl_tls13_derive_handshake_secrets( psa_algorithm_t hash_alg, unsigned char const *handshake_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_handshake_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * * Handshake Secret * | * +-----> Derive-Secret( ., "c hs traffic", * | ClientHello...ServerHello ) * | = client_handshake_traffic_secret * | * +-----> Derive-Secret( ., "s hs traffic", * | ClientHello...ServerHello ) * | = server_handshake_traffic_secret * */ /* * Compute client_handshake_traffic_secret with * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello ) */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, handshake_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->client_handshake_traffic_secret, hash_len); if (ret != 0) { return ret; } /* * Compute server_handshake_traffic_secret with * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello ) */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, handshake_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->server_handshake_traffic_secret, hash_len); if (ret != 0) { return ret; } return 0; } int mbedtls_ssl_tls13_derive_application_secrets( psa_algorithm_t hash_alg, unsigned char const *application_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* Generate {client,server}_application_traffic_secret_0 * * Master Secret * | * +-----> Derive-Secret( ., "c ap traffic", * | ClientHello...server Finished ) * | = client_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "s ap traffic", * | ClientHello...Server Finished ) * | = server_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "exp master", * | ClientHello...server Finished) * | = exporter_master_secret * */ ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->client_application_traffic_secret_N, hash_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->server_application_traffic_secret_N, hash_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->exporter_master_secret, hash_len); if (ret != 0) { return ret; } return 0; } /* Generate resumption_master_secret for use with the ticket exchange. * * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets() * because it uses the transcript hash up to and including ClientFinished. */ int mbedtls_ssl_tls13_derive_resumption_master_secret( psa_algorithm_t hash_alg, unsigned char const *application_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived) { int ret; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } ret = mbedtls_ssl_tls13_derive_secret( hash_alg, application_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master), transcript, transcript_len, MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, derived->resumption_master_secret, hash_len); if (ret != 0) { return ret; } return 0; } /** * \brief Transition into application stage of TLS 1.3 key schedule. * * The TLS 1.3 key schedule can be viewed as a simple state machine * with states Initial -> Early -> Handshake -> Application, and * this function represents the Handshake -> Application transition. * * In the handshake stage, ssl_tls13_generate_application_keys() * can be used to derive the handshake traffic keys. * * \param ssl The SSL context to operate on. This must be in key schedule * stage \c Handshake. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type( (mbedtls_md_type_t) handshake->ciphersuite_info->mac); /* * Compute MasterSecret */ ret = mbedtls_ssl_tls13_evolve_secret( hash_alg, handshake->tls13_master_secrets.handshake, NULL, 0, handshake->tls13_master_secrets.app); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF( 4, "Master secret", handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg)); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_calc_finished_core(psa_algorithm_t hash_alg, unsigned char const *base_key, unsigned char const *transcript, unsigned char *dst, size_t *dst_len) { mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t hash_len = PSA_HASH_LENGTH(hash_alg); unsigned char finished_key[PSA_MAC_MAX_SIZE]; int ret; psa_algorithm_t alg; /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* TLS 1.3 Finished message * * struct { * opaque verify_data[Hash.length]; * } Finished; * * verify_data = * HMAC( finished_key, * Hash( Handshake Context + * Certificate* + * CertificateVerify* ) * ) * * finished_key = * HKDF-Expand-Label( BaseKey, "finished", "", Hash.length ) */ ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, base_key, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(finished), NULL, 0, finished_key, hash_len); if (ret != 0) { goto exit; } alg = PSA_ALG_HMAC(hash_alg); psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); status = psa_import_key(&attributes, finished_key, hash_len, &key); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); goto exit; } status = psa_mac_compute(key, alg, transcript, hash_len, dst, hash_len, dst_len); ret = PSA_TO_MBEDTLS_ERR(status); exit: status = psa_destroy_key(key); if (ret == 0) { ret = PSA_TO_MBEDTLS_ERR(status); } mbedtls_platform_zeroize(finished_key, sizeof(finished_key)); return ret; } int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *actual_len, int from) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; unsigned char *base_key = NULL; size_t base_key_len = 0; mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &ssl->handshake->tls13_hs_secrets; mbedtls_md_type_t const md_type = (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac; psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type( (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac); size_t const hash_len = PSA_HASH_LENGTH(hash_alg); MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_tls13_calculate_verify_data")); if (from == MBEDTLS_SSL_IS_CLIENT) { base_key = tls13_hs_secrets->client_handshake_traffic_secret; base_key_len = sizeof(tls13_hs_secrets->client_handshake_traffic_secret); } else { base_key = tls13_hs_secrets->server_handshake_traffic_secret; base_key_len = sizeof(tls13_hs_secrets->server_handshake_traffic_secret); } if (dst_len < hash_len) { ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; goto exit; } ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); goto exit; } MBEDTLS_SSL_DEBUG_BUF(4, "handshake hash", transcript, transcript_len); ret = ssl_tls13_calc_finished_core(hash_alg, base_key, transcript, dst, actual_len); if (ret != 0) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "verify_data for finished message", dst, hash_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= mbedtls_ssl_tls13_calculate_verify_data")); exit: /* Erase handshake secrets */ mbedtls_platform_zeroize(base_key, base_key_len); mbedtls_platform_zeroize(transcript, sizeof(transcript)); return ret; } int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, const psa_algorithm_t hash_alg, unsigned char const *psk, size_t psk_len, int psk_type, unsigned char const *transcript, unsigned char *result) { int ret = 0; unsigned char binder_key[PSA_MAC_MAX_SIZE]; unsigned char early_secret[PSA_MAC_MAX_SIZE]; size_t const hash_len = PSA_HASH_LENGTH(hash_alg); size_t actual_len; #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif /* We should never call this function with an unknown hash, * but add an assertion anyway. */ if (!PSA_ALG_IS_HASH(hash_alg)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* * 0 * | * v * PSK -> HKDF-Extract = Early Secret * | * +-----> Derive-Secret(., "ext binder" | "res binder", "") * | = binder_key * v */ ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, /* Old secret */ psk, psk_len, /* Input */ early_secret); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); goto exit; } MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_create_psk_binder", early_secret, hash_len); if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder), NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, binder_key, hash_len); MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'res binder'")); } else { ret = mbedtls_ssl_tls13_derive_secret( hash_alg, early_secret, hash_len, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder), NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, binder_key, hash_len); MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'ext binder'")); } if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_secret", ret); goto exit; } /* * The binding_value is computed in the same way as the Finished message * but with the BaseKey being the binder_key. */ ret = ssl_tls13_calc_finished_core(hash_alg, binder_key, transcript, result, &actual_len); if (ret != 0) { goto exit; } MBEDTLS_SSL_DEBUG_BUF(3, "psk binder", result, actual_len); exit: mbedtls_platform_zeroize(early_secret, sizeof(early_secret)); mbedtls_platform_zeroize(binder_key, sizeof(binder_key)); return ret; } int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform, int endpoint, int ciphersuite, mbedtls_ssl_key_set const *traffic_keys, mbedtls_ssl_context *ssl /* DEBUG ONLY */) { #if !defined(MBEDTLS_USE_PSA_CRYPTO) int ret; mbedtls_cipher_info_t const *cipher_info; #endif /* MBEDTLS_USE_PSA_CRYPTO */ const mbedtls_ssl_ciphersuite_t *ciphersuite_info; unsigned char const *key_enc; unsigned char const *iv_enc; unsigned char const *key_dec; unsigned char const *iv_dec; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_type_t key_type; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_algorithm_t alg; size_t key_bits; psa_status_t status = PSA_SUCCESS; #endif #if !defined(MBEDTLS_DEBUG_C) ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; #endif ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite); if (ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found", ciphersuite)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } #if !defined(MBEDTLS_USE_PSA_CRYPTO) cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher); if (cipher_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found", ciphersuite_info->cipher)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } /* * Setup cipher contexts in target transform */ if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); return ret; } if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec, cipher_info)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_SSL_SRV_C) if (endpoint == MBEDTLS_SSL_IS_SERVER) { key_enc = traffic_keys->server_write_key; key_dec = traffic_keys->client_write_key; iv_enc = traffic_keys->server_write_iv; iv_dec = traffic_keys->client_write_iv; } else #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_CLI_C) if (endpoint == MBEDTLS_SSL_IS_CLIENT) { key_enc = traffic_keys->client_write_key; key_dec = traffic_keys->server_write_key; iv_enc = traffic_keys->client_write_iv; iv_dec = traffic_keys->server_write_iv; } else #endif /* MBEDTLS_SSL_CLI_C */ { /* should not happen */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(transform->iv_enc, iv_enc, traffic_keys->iv_len); memcpy(transform->iv_dec, iv_dec, traffic_keys->iv_len); #if !defined(MBEDTLS_USE_PSA_CRYPTO) if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key_enc, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_ENCRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); return ret; } if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key_dec, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info), MBEDTLS_DECRYPT)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret); return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Setup other fields in SSL transform */ if ((ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) != 0) { transform->taglen = 8; } else { transform->taglen = 16; } transform->ivlen = traffic_keys->iv_len; transform->maclen = 0; transform->fixed_ivlen = transform->ivlen; transform->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; /* We add the true record content type (1 Byte) to the plaintext and * then pad to the configured granularity. The minimum length of the * type-extended and padded plaintext is therefore the padding * granularity. */ transform->minlen = transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY; #if defined(MBEDTLS_USE_PSA_CRYPTO) /* * Setup psa keys and alg */ if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, transform->taglen, &alg, &key_type, &key_bits)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status)); return PSA_TO_MBEDTLS_ERR(status); } transform->psa_alg = alg; if (alg != MBEDTLS_SSL_NULL_CIPHER) { psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&attributes, alg); psa_set_key_type(&attributes, key_type); if ((status = psa_import_key(&attributes, key_enc, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_enc)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET( 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); return PSA_TO_MBEDTLS_ERR(status); } psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); if ((status = psa_import_key(&attributes, key_dec, PSA_BITS_TO_BYTES(key_bits), &transform->psa_key_dec)) != PSA_SUCCESS) { MBEDTLS_SSL_DEBUG_RET( 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); return PSA_TO_MBEDTLS_ERR(status); } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_get_cipher_key_info( const mbedtls_ssl_ciphersuite_t *ciphersuite_info, size_t *key_len, size_t *iv_len) { psa_key_type_t key_type; psa_algorithm_t alg; size_t taglen; size_t key_bits; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; if (ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG) { taglen = 8; } else { taglen = 16; } status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, taglen, &alg, &key_type, &key_bits); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } *key_len = PSA_BITS_TO_BYTES(key_bits); /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */ *iv_len = 12; return 0; } #if defined(MBEDTLS_SSL_EARLY_DATA) /* * ssl_tls13_generate_early_key() generates the key necessary for protecting * the early application data and handshake messages as described in section 7 * of RFC 8446. * * NOTE: Only one key is generated, the key for the traffic from the client to * the server. The TLS 1.3 specification does not define a secret and thus * a key for server early traffic. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl, mbedtls_ssl_key_set *traffic_keys) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; psa_algorithm_t hash_alg; size_t hash_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; size_t key_len = 0; size_t iv_len = 0; mbedtls_ssl_tls13_early_secrets tls13_early_secrets; mbedtls_ssl_handshake_params *handshake = ssl->handshake; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_early_key")); ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); goto cleanup; } md_type = (mbedtls_md_type_t) ciphersuite_info->mac; hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_len = PSA_HASH_LENGTH(hash_alg); ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); goto cleanup; } ret = mbedtls_ssl_tls13_derive_early_secrets( hash_alg, handshake->tls13_master_secrets.early, transcript, transcript_len, &tls13_early_secrets); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_early_secrets", ret); goto cleanup; } MBEDTLS_SSL_DEBUG_BUF( 4, "Client early traffic secret", tls13_early_secrets.client_early_traffic_secret, hash_len); /* * Export client handshake traffic secret */ if (ssl->f_export_keys != NULL) { ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, tls13_early_secrets.client_early_traffic_secret, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); } ret = ssl_tls13_make_traffic_key( hash_alg, tls13_early_secrets.client_early_traffic_secret, hash_len, traffic_keys->client_write_key, key_len, traffic_keys->client_write_iv, iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_make_traffic_key", ret); goto cleanup; } traffic_keys->key_len = key_len; traffic_keys->iv_len = iv_len; MBEDTLS_SSL_DEBUG_BUF(4, "client early write_key", traffic_keys->client_write_key, traffic_keys->key_len); MBEDTLS_SSL_DEBUG_BUF(4, "client early write_iv", traffic_keys->client_write_iv, traffic_keys->iv_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_early_key")); cleanup: /* Erase early secrets and transcript */ mbedtls_platform_zeroize( &tls13_early_secrets, sizeof(mbedtls_ssl_tls13_early_secrets)); mbedtls_platform_zeroize(transcript, sizeof(transcript)); return ret; } int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_key_set traffic_keys; mbedtls_ssl_transform *transform_earlydata = NULL; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Next evolution in key schedule: Establish early_data secret and * key material. */ ret = ssl_tls13_generate_early_key(ssl, &traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_early_key", ret); goto cleanup; } transform_earlydata = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); if (transform_earlydata == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto cleanup; } ret = mbedtls_ssl_tls13_populate_transform( transform_earlydata, ssl->conf->endpoint, handshake->ciphersuite_info->id, &traffic_keys, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); goto cleanup; } handshake->transform_earlydata = transform_earlydata; cleanup: mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); if (ret != 0) { mbedtls_free(transform_earlydata); } return ret; } #endif /* MBEDTLS_SSL_EARLY_DATA */ int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; psa_algorithm_t hash_alg; mbedtls_ssl_handshake_params *handshake = ssl->handshake; unsigned char *psk = NULL; size_t psk_len = 0; if (handshake->ciphersuite_info == NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("cipher suite info not found")); return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_export_handshake_psk", ret); return ret; } } #endif ret = mbedtls_ssl_tls13_evolve_secret(hash_alg, NULL, psk, psk_len, handshake->tls13_master_secrets.early); #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) mbedtls_free((void *) psk); #endif if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "mbedtls_ssl_tls13_key_schedule_stage_early", handshake->tls13_master_secrets.early, PSA_HASH_LENGTH(hash_alg)); return 0; } /** * \brief Compute TLS 1.3 handshake traffic keys. * * ssl_tls13_generate_handshake_keys() generates keys necessary for * protecting the handshake messages, as described in Section 7 of * RFC 8446. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Handshake, see * ssl_tls13_key_schedule_stage_handshake(). * \param traffic_keys The address at which to store the handshake traffic * keys. This must be writable but may be uninitialized. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl, mbedtls_ssl_key_set *traffic_keys) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; psa_algorithm_t hash_alg; size_t hash_len; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; size_t key_len = 0; size_t iv_len = 0; mbedtls_ssl_handshake_params *handshake = ssl->handshake; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_handshake_keys")); ret = ssl_tls13_get_cipher_key_info(ciphersuite_info, &key_len, &iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); return ret; } md_type = (mbedtls_md_type_t) ciphersuite_info->mac; hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_len = PSA_HASH_LENGTH(hash_alg); ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_get_handshake_transcript", ret); return ret; } ret = mbedtls_ssl_tls13_derive_handshake_secrets( hash_alg, handshake->tls13_master_secrets.handshake, transcript, transcript_len, tls13_hs_secrets); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_handshake_secrets", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "Client handshake traffic secret", tls13_hs_secrets->client_handshake_traffic_secret, hash_len); MBEDTLS_SSL_DEBUG_BUF(4, "Server handshake traffic secret", tls13_hs_secrets->server_handshake_traffic_secret, hash_len); /* * Export client handshake traffic secret */ if (ssl->f_export_keys != NULL) { ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, tls13_hs_secrets->client_handshake_traffic_secret, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, tls13_hs_secrets->server_handshake_traffic_secret, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */); } ret = mbedtls_ssl_tls13_make_traffic_keys( hash_alg, tls13_hs_secrets->client_handshake_traffic_secret, tls13_hs_secrets->server_handshake_traffic_secret, hash_len, key_len, iv_len, traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); goto exit; } MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_key", traffic_keys->client_write_key, traffic_keys->key_len); MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_key", traffic_keys->server_write_key, traffic_keys->key_len); MBEDTLS_SSL_DEBUG_BUF(4, "client_handshake write_iv", traffic_keys->client_write_iv, traffic_keys->iv_len); MBEDTLS_SSL_DEBUG_BUF(4, "server_handshake write_iv", traffic_keys->server_write_iv, traffic_keys->iv_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_generate_handshake_keys")); exit: return ret; } /** * \brief Transition into handshake stage of TLS 1.3 key schedule. * * The TLS 1.3 key schedule can be viewed as a simple state machine * with states Initial -> Early -> Handshake -> Application, and * this function represents the Early -> Handshake transition. * * In the handshake stage, ssl_tls13_generate_handshake_keys() * can be used to derive the handshake traffic keys. * * \param ssl The SSL context to operate on. This must be in key schedule * stage \c Early. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type( (mbedtls_md_type_t) handshake->ciphersuite_info->mac); unsigned char *shared_secret = NULL; size_t shared_secret_len = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* * Compute ECDHE secret used to compute the handshake secret from which * client_handshake_traffic_secret and server_handshake_traffic_secret * are derived in the handshake secret derivation stage. */ if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) || mbedtls_ssl_tls13_named_group_is_ffdh(handshake->offered_group_id)) { #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) psa_algorithm_t alg = mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ? PSA_ALG_ECDH : PSA_ALG_FFDH; /* Compute ECDH shared secret. */ psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; status = psa_get_key_attributes(handshake->xxdh_psa_privkey, &key_attributes); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); } shared_secret_len = PSA_BITS_TO_BYTES( psa_get_key_bits(&key_attributes)); shared_secret = mbedtls_calloc(1, shared_secret_len); if (shared_secret == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } status = psa_raw_key_agreement( alg, handshake->xxdh_psa_privkey, handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len, shared_secret, shared_secret_len, &shared_secret_len); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret); goto cleanup; } status = psa_destroy_key(handshake->xxdh_psa_privkey); if (status != PSA_SUCCESS) { ret = PSA_TO_MBEDTLS_ERR(status); MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret); goto cleanup; } handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ } else { MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported.")); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ /* * Compute the Handshake Secret */ ret = mbedtls_ssl_tls13_evolve_secret( hash_alg, handshake->tls13_master_secrets.early, shared_secret, shared_secret_len, handshake->tls13_master_secrets.handshake); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret); goto cleanup; } MBEDTLS_SSL_DEBUG_BUF(4, "Handshake secret", handshake->tls13_master_secrets.handshake, PSA_HASH_LENGTH(hash_alg)); cleanup: if (shared_secret != NULL) { mbedtls_zeroize_and_free(shared_secret, shared_secret_len); } return ret; } /** * \brief Compute TLS 1.3 application traffic keys. * * ssl_tls13_generate_application_keys() generates application traffic * keys, since any record following a 1-RTT Finished message MUST be * encrypted under the application traffic key. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Application, see * ssl_tls13_key_schedule_stage_application(). * \param traffic_keys The address at which to store the application traffic * keys. This must be writable but may be uninitialized. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_application_keys( mbedtls_ssl_context *ssl, mbedtls_ssl_key_set *traffic_keys) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Address at which to store the application secrets */ mbedtls_ssl_tls13_application_secrets * const app_secrets = &ssl->session_negotiate->app_secrets; /* Holding the transcript up to and including the ServerFinished */ unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; /* Variables relating to the hash for the chosen ciphersuite. */ mbedtls_md_type_t md_type; psa_algorithm_t hash_alg; size_t hash_len; /* Variables relating to the cipher for the chosen ciphersuite. */ size_t key_len = 0, iv_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive application traffic keys")); /* Extract basic information about hash and ciphersuite */ ret = ssl_tls13_get_cipher_key_info(handshake->ciphersuite_info, &key_len, &iv_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_get_cipher_key_info", ret); goto cleanup; } md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac); hash_len = PSA_HASH_LENGTH(hash_alg); /* Compute current handshake transcript. It's the caller's responsibility * to call this at the right time, that is, after the ServerFinished. */ ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { goto cleanup; } /* Compute application secrets from master secret and transcript hash. */ ret = mbedtls_ssl_tls13_derive_application_secrets( hash_alg, handshake->tls13_master_secrets.app, transcript, transcript_len, app_secrets); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_application_secrets", ret); goto cleanup; } /* Derive first epoch of IV + Key for application traffic. */ ret = mbedtls_ssl_tls13_make_traffic_keys( hash_alg, app_secrets->client_application_traffic_secret_N, app_secrets->server_application_traffic_secret_N, hash_len, key_len, iv_len, traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret); goto cleanup; } MBEDTLS_SSL_DEBUG_BUF(4, "Client application traffic secret", app_secrets->client_application_traffic_secret_N, hash_len); MBEDTLS_SSL_DEBUG_BUF(4, "Server application traffic secret", app_secrets->server_application_traffic_secret_N, hash_len); /* * Export client/server application traffic secret 0 */ if (ssl->f_export_keys != NULL) { ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, app_secrets->client_application_traffic_secret_N, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by a new constant for TLS 1.3! */); ssl->f_export_keys( ssl->p_export_keys, MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, app_secrets->server_application_traffic_secret_N, hash_len, handshake->randbytes, handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN, MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by a new constant for TLS 1.3! */); } MBEDTLS_SSL_DEBUG_BUF(4, "client application_write_key:", traffic_keys->client_write_key, key_len); MBEDTLS_SSL_DEBUG_BUF(4, "server application write key", traffic_keys->server_write_key, key_len); MBEDTLS_SSL_DEBUG_BUF(4, "client application write IV", traffic_keys->client_write_iv, iv_len); MBEDTLS_SSL_DEBUG_BUF(4, "server application write IV", traffic_keys->server_write_iv, iv_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive application traffic keys")); cleanup: /* randbytes is not used again */ mbedtls_platform_zeroize(ssl->handshake->randbytes, sizeof(ssl->handshake->randbytes)); mbedtls_platform_zeroize(transcript, sizeof(transcript)); return ret; } int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_key_set traffic_keys; mbedtls_ssl_transform *transform_handshake = NULL; mbedtls_ssl_handshake_params *handshake = ssl->handshake; /* Compute handshake secret */ ret = ssl_tls13_key_schedule_stage_handshake(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_master_secret", ret); goto cleanup; } /* Next evolution in key schedule: Establish handshake secret and * key material. */ ret = ssl_tls13_generate_handshake_keys(ssl, &traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_handshake_keys", ret); goto cleanup; } transform_handshake = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); if (transform_handshake == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto cleanup; } ret = mbedtls_ssl_tls13_populate_transform( transform_handshake, ssl->conf->endpoint, handshake->ciphersuite_info->id, &traffic_keys, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); goto cleanup; } handshake->transform_handshake = transform_handshake; cleanup: mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); if (ret != 0) { mbedtls_free(transform_handshake); } return ret; } int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_md_type_t md_type; mbedtls_ssl_handshake_params *handshake = ssl->handshake; unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; size_t transcript_len; MBEDTLS_SSL_DEBUG_MSG( 2, ("=> mbedtls_ssl_tls13_compute_resumption_master_secret")); md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac; ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type, transcript, sizeof(transcript), &transcript_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_derive_resumption_master_secret( mbedtls_md_psa_alg_from_type(md_type), handshake->tls13_master_secrets.app, transcript, transcript_len, &ssl->session_negotiate->app_secrets); if (ret != 0) { return ret; } /* Erase master secrets */ mbedtls_platform_zeroize(&handshake->tls13_master_secrets, sizeof(handshake->tls13_master_secrets)); MBEDTLS_SSL_DEBUG_BUF( 4, "Resumption master secret", ssl->session_negotiate->app_secrets.resumption_master_secret, PSA_HASH_LENGTH(mbedtls_md_psa_alg_from_type(md_type))); MBEDTLS_SSL_DEBUG_MSG( 2, ("<= mbedtls_ssl_tls13_compute_resumption_master_secret")); return 0; } int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_key_set traffic_keys; mbedtls_ssl_transform *transform_application = NULL; ret = ssl_tls13_key_schedule_stage_application(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_key_schedule_stage_application", ret); goto cleanup; } ret = ssl_tls13_generate_application_keys(ssl, &traffic_keys); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_generate_application_keys", ret); goto cleanup; } transform_application = mbedtls_calloc(1, sizeof(mbedtls_ssl_transform)); if (transform_application == NULL) { ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; goto cleanup; } ret = mbedtls_ssl_tls13_populate_transform( transform_application, ssl->conf->endpoint, ssl->handshake->ciphersuite_info->id, &traffic_keys, ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_populate_transform", ret); goto cleanup; } ssl->transform_application = transform_application; cleanup: mbedtls_platform_zeroize(&traffic_keys, sizeof(traffic_keys)); if (ret != 0) { mbedtls_free(transform_application); } return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, unsigned char **psk, size_t *psk_len) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; *psk_len = 0; *psk = NULL; if (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes); if (status != PSA_SUCCESS) { return PSA_TO_MBEDTLS_ERR(status); } *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes)); *psk = mbedtls_calloc(1, *psk_len); if (*psk == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } status = psa_export_key(ssl->handshake->psk_opaque, (uint8_t *) *psk, *psk_len, psk_len); if (status != PSA_SUCCESS) { mbedtls_free((void *) *psk); *psk = NULL; return PSA_TO_MBEDTLS_ERR(status); } return 0; #else *psk = ssl->handshake->psk; *psk_len = ssl->handshake->psk_len; if (*psk == NULL) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return 0; #endif /* !MBEDTLS_USE_PSA_CRYPTO */ } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h000066400000000000000000000675721464416617300244100ustar00rootroot00000000000000/* * TLS 1.3 key schedule * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H) #define MBEDTLS_SSL_TLS1_3_KEYS_H /* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at * the point of use. See e.g. the definition of mbedtls_ssl_tls13_labels_union * below. */ #define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ MBEDTLS_SSL_TLS1_3_LABEL(finished, "finished") \ MBEDTLS_SSL_TLS1_3_LABEL(resumption, "resumption") \ MBEDTLS_SSL_TLS1_3_LABEL(traffic_upd, "traffic upd") \ MBEDTLS_SSL_TLS1_3_LABEL(exporter, "exporter") \ MBEDTLS_SSL_TLS1_3_LABEL(key, "key") \ MBEDTLS_SSL_TLS1_3_LABEL(iv, "iv") \ MBEDTLS_SSL_TLS1_3_LABEL(c_hs_traffic, "c hs traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(c_ap_traffic, "c ap traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(c_e_traffic, "c e traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(s_hs_traffic, "s hs traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(s_ap_traffic, "s ap traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(s_e_traffic, "s e traffic") \ MBEDTLS_SSL_TLS1_3_LABEL(e_exp_master, "e exp master") \ MBEDTLS_SSL_TLS1_3_LABEL(res_master, "res master") \ MBEDTLS_SSL_TLS1_3_LABEL(exp_master, "exp master") \ MBEDTLS_SSL_TLS1_3_LABEL(ext_binder, "ext binder") \ MBEDTLS_SSL_TLS1_3_LABEL(res_binder, "res binder") \ MBEDTLS_SSL_TLS1_3_LABEL(derived, "derived") \ MBEDTLS_SSL_TLS1_3_LABEL(client_cv, "TLS 1.3, client CertificateVerify") \ MBEDTLS_SSL_TLS1_3_LABEL(server_cv, "TLS 1.3, server CertificateVerify") #define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 #define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 #define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL 0 #define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ const unsigned char name [sizeof(string) - 1]; union mbedtls_ssl_tls13_labels_union { MBEDTLS_SSL_TLS1_3_LABEL_LIST }; struct mbedtls_ssl_tls13_labels_struct { MBEDTLS_SSL_TLS1_3_LABEL_LIST }; #undef MBEDTLS_SSL_TLS1_3_LABEL extern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels; #define MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) \ sizeof(mbedtls_ssl_tls13_labels.LABEL) #define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(LABEL) \ mbedtls_ssl_tls13_labels.LABEL, \ MBEDTLS_SSL_TLS1_3_LBL_LEN(LABEL) #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ sizeof(union mbedtls_ssl_tls13_labels_union) /* The maximum length of HKDF contexts used in the TLS 1.3 standard. * Since contexts are always hashes of message transcripts, this can * be approximated from above by the maximum hash size. */ #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ PSA_HASH_MAX_SIZE /* Maximum desired length for expanded key material generated * by HKDF-Expand-Label. * * Warning: If this ever needs to be increased, the implementation * ssl_tls13_hkdf_encode_label() in ssl_tls13_keys.c needs to be * adjusted since it currently assumes that HKDF key expansion * is never used with more than 255 Bytes of output. */ #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 /** * \brief The \c HKDF-Expand-Label function from * the TLS 1.3 standard RFC 8446. * * * HKDF-Expand-Label( Secret, Label, Context, Length ) = * HKDF-Expand( Secret, HkdfLabel, Length ) * * * \param hash_alg The identifier for the hash algorithm to use. * \param secret The \c Secret argument to \c HKDF-Expand-Label. * This must be a readable buffer of length * \p secret_len Bytes. * \param secret_len The length of \p secret in Bytes. * \param label The \c Label argument to \c HKDF-Expand-Label. * This must be a readable buffer of length * \p label_len Bytes. * \param label_len The length of \p label in Bytes. * \param ctx The \c Context argument to \c HKDF-Expand-Label. * This must be a readable buffer of length \p ctx_len Bytes. * \param ctx_len The length of \p context in Bytes. * \param buf The destination buffer to hold the expanded secret. * This must be a writable buffer of length \p buf_len Bytes. * \param buf_len The desired size of the expanded secret in Bytes. * * \returns \c 0 on success. * \return A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_hkdf_expand_label( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, unsigned char *buf, size_t buf_len); /** * \brief This function is part of the TLS 1.3 key schedule. * It extracts key and IV for the actual client/server traffic * from the client/server traffic secrets. * * From RFC 8446: * * * [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) * [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)* * * * \param hash_alg The identifier for the hash algorithm to be used * for the HKDF-based expansion of the secret. * \param client_secret The client traffic secret. * This must be a readable buffer of size * \p secret_len Bytes * \param server_secret The server traffic secret. * This must be a readable buffer of size * \p secret_len Bytes * \param secret_len Length of the secrets \p client_secret and * \p server_secret in Bytes. * \param key_len The desired length of the key to be extracted in Bytes. * \param iv_len The desired length of the IV to be extracted in Bytes. * \param keys The address of the structure holding the generated * keys and IVs. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_make_traffic_keys( psa_algorithm_t hash_alg, const unsigned char *client_secret, const unsigned char *server_secret, size_t secret_len, size_t key_len, size_t iv_len, mbedtls_ssl_key_set *keys); /** * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. * * * Derive-Secret( Secret, Label, Messages ) = * HKDF-Expand-Label( Secret, Label, * Hash( Messages ), * Hash.Length ) ) * * * \param hash_alg The identifier for the hash function used for the * applications of HKDF. * \param secret The \c Secret argument to the \c Derive-Secret function. * This must be a readable buffer of length * \p secret_len Bytes. * \param secret_len The length of \p secret in Bytes. * \param label The \c Label argument to the \c Derive-Secret function. * This must be a readable buffer of length * \p label_len Bytes. * \param label_len The length of \p label in Bytes. * \param ctx The hash of the \c Messages argument to the * \c Derive-Secret function, or the \c Messages argument * itself, depending on \p ctx_hashed. * \param ctx_len The length of \p ctx in Bytes. * \param ctx_hashed This indicates whether the \p ctx contains the hash of * the \c Messages argument in the application of the * \c Derive-Secret function * (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether * it is the content of \c Messages itself, in which case * the function takes care of the hashing * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). * \param dstbuf The target buffer to write the output of * \c Derive-Secret to. This must be a writable buffer of * size \p dtsbuf_len Bytes. * \param dstbuf_len The length of \p dstbuf in Bytes. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_secret( psa_algorithm_t hash_alg, const unsigned char *secret, size_t secret_len, const unsigned char *label, size_t label_len, const unsigned char *ctx, size_t ctx_len, int ctx_hashed, unsigned char *dstbuf, size_t dstbuf_len); /** * \brief Derive TLS 1.3 early data key material from early secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels. * * * Early Secret * | * +-----> Derive-Secret(., "c e traffic", ClientHello) * | = client_early_traffic_secret * | * +-----> Derive-Secret(., "e exp master", ClientHello) * . = early_exporter_master_secret * . * . * * * \note To obtain the actual key and IV for the early data traffic, * the client secret derived by this function need to be * further processed by mbedtls_ssl_tls13_make_traffic_keys(). * * \note The binder key, which is also generated from the early secret, * is omitted here. Its calculation is part of the separate routine * mbedtls_ssl_tls13_create_psk_binder(). * * \param hash_alg The hash algorithm associated with the PSK for which * early data key material is being derived. * \param early_secret The early secret from which the early data key material * should be derived. This must be a readable buffer whose * length is the digest size of the hash algorithm * represented by \p md_size. * \param transcript The transcript of the handshake so far, calculated with * respect to \p hash_alg. This must be a readable buffer * whose length is the digest size of the hash algorithm * represented by \p md_size. * \param derived The address of the structure in which to store * the early data key material. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_early_secrets( psa_algorithm_t hash_alg, unsigned char const *early_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_early_secrets *derived); /** * \brief Derive TLS 1.3 handshake key material from the handshake secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels from the standard. * * * Handshake Secret * | * +-----> Derive-Secret( ., "c hs traffic", * | ClientHello...ServerHello ) * | = client_handshake_traffic_secret * | * +-----> Derive-Secret( ., "s hs traffic", * . ClientHello...ServerHello ) * . = server_handshake_traffic_secret * . * * * \note To obtain the actual key and IV for the encrypted handshake traffic, * the client and server secret derived by this function need to be * further processed by mbedtls_ssl_tls13_make_traffic_keys(). * * \param hash_alg The hash algorithm associated with the ciphersuite * that's being used for the connection. * \param handshake_secret The handshake secret from which the handshake key * material should be derived. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param transcript The transcript of the handshake so far, calculated * with respect to \p hash_alg. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param derived The address of the structure in which to * store the handshake key material. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_handshake_secrets( psa_algorithm_t hash_alg, unsigned char const *handshake_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_handshake_secrets *derived); /** * \brief Derive TLS 1.3 application key material from the master secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels from the standard. * * * Master Secret * | * +-----> Derive-Secret( ., "c ap traffic", * | ClientHello...server Finished ) * | = client_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "s ap traffic", * | ClientHello...Server Finished ) * | = server_application_traffic_secret_0 * | * +-----> Derive-Secret( ., "exp master", * . ClientHello...server Finished) * . = exporter_master_secret * . * * * \note To obtain the actual key and IV for the (0-th) application traffic, * the client and server secret derived by this function need to be * further processed by mbedtls_ssl_tls13_make_traffic_keys(). * * \param hash_alg The hash algorithm associated with the ciphersuite * that's being used for the connection. * \param master_secret The master secret from which the application key * material should be derived. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param transcript The transcript of the handshake up to and including * the ServerFinished message, calculated with respect * to \p hash_alg. This must be a readable buffer whose * length is the digest size of the hash algorithm * represented by \p hash_alg. * \param derived The address of the structure in which to * store the application key material. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_application_secrets( psa_algorithm_t hash_alg, unsigned char const *master_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived); /** * \brief Derive TLS 1.3 resumption master secret from the master secret. * * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() * with the appropriate labels from the standard. * * \param hash_alg The hash algorithm used in the application for which * key material is being derived. * \param application_secret The application secret from which the resumption master * secret should be derived. This must be a readable * buffer whose length is the digest size of the hash * algorithm represented by \p md_size. * \param transcript The transcript of the handshake up to and including * the ClientFinished message, calculated with respect * to \p hash_alg. This must be a readable buffer whose * length is the digest size of the hash algorithm * represented by \p hash_alg. * \param transcript_len The length of \p transcript in Bytes. * \param derived The address of the structure in which to * store the resumption master secret. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_derive_resumption_master_secret( psa_algorithm_t hash_alg, unsigned char const *application_secret, unsigned char const *transcript, size_t transcript_len, mbedtls_ssl_tls13_application_secrets *derived); /** * \brief Compute the next secret in the TLS 1.3 key schedule * * The TLS 1.3 key schedule proceeds as follows to compute * the three main secrets during the handshake: The early * secret for early data, the handshake secret for all * other encrypted handshake messages, and the master * secret for all application traffic. * * * 0 * | * v * PSK -> HKDF-Extract = Early Secret * | * v * Derive-Secret( ., "derived", "" ) * | * v * (EC)DHE -> HKDF-Extract = Handshake Secret * | * v * Derive-Secret( ., "derived", "" ) * | * v * 0 -> HKDF-Extract = Master Secret * * * Each of the three secrets in turn is the basis for further * key derivations, such as the derivation of traffic keys and IVs; * see e.g. mbedtls_ssl_tls13_make_traffic_keys(). * * This function implements one step in this evolution of secrets: * * * old_secret * | * v * Derive-Secret( ., "derived", "" ) * | * v * input -> HKDF-Extract = new_secret * * * \param hash_alg The identifier for the hash function used for the * applications of HKDF. * \param secret_old The address of the buffer holding the old secret * on function entry. If not \c NULL, this must be a * readable buffer whose size matches the output size * of the hash function represented by \p hash_alg. * If \c NULL, an all \c 0 array will be used instead. * \param input The address of the buffer holding the additional * input for the key derivation (e.g., the PSK or the * ephemeral (EC)DH secret). If not \c NULL, this must be * a readable buffer whose size \p input_len Bytes. * If \c NULL, an all \c 0 array will be used instead. * \param input_len The length of \p input in Bytes. * \param secret_new The address of the buffer holding the new secret * on function exit. This must be a writable buffer * whose size matches the output size of the hash * function represented by \p hash_alg. * This may be the same as \p secret_old. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_evolve_secret( psa_algorithm_t hash_alg, const unsigned char *secret_old, const unsigned char *input, size_t input_len, unsigned char *secret_new); /** * \brief Calculate a TLS 1.3 PSK binder. * * \param ssl The SSL context. This is used for debugging only and may * be \c NULL if MBEDTLS_DEBUG_C is disabled. * \param hash_alg The hash algorithm associated to the PSK \p psk. * \param psk The buffer holding the PSK for which to create a binder. * \param psk_len The size of \p psk in bytes. * \param psk_type This indicates whether the PSK \p psk is externally * provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a * resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION). * \param transcript The handshake transcript up to the point where the * PSK binder calculation happens. This must be readable, * and its size must be equal to the digest size of * the hash algorithm represented by \p hash_alg. * \param result The address at which to store the PSK binder on success. * This must be writable, and its size must be equal to the * digest size of the hash algorithm represented by * \p hash_alg. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl, const psa_algorithm_t hash_alg, unsigned char const *psk, size_t psk_len, int psk_type, unsigned char const *transcript, unsigned char *result); /** * \bref Setup an SSL transform structure representing the * record protection mechanism used by TLS 1.3 * * \param transform The SSL transform structure to be created. This must have * been initialized through mbedtls_ssl_transform_init() and * not used in any other way prior to calling this function. * In particular, this function does not clean up the * transform structure prior to installing the new keys. * \param endpoint Indicates whether the transform is for the client * (value #MBEDTLS_SSL_IS_CLIENT) or the server * (value #MBEDTLS_SSL_IS_SERVER). * \param ciphersuite The numerical identifier for the ciphersuite to use. * This must be one of the identifiers listed in * ssl_ciphersuites.h. * \param traffic_keys The key material to use. No reference is stored in * the SSL transform being generated, and the caller * should destroy the key material afterwards. * \param ssl (Debug-only) The SSL context to use for debug output * in case of failure. This parameter is only needed if * #MBEDTLS_DEBUG_C is set, and is ignored otherwise. * * \return \c 0 on success. In this case, \p transform is ready to * be used with mbedtls_ssl_transform_decrypt() and * mbedtls_ssl_transform_encrypt(). * \return A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform, int endpoint, int ciphersuite, mbedtls_ssl_key_set const *traffic_keys, mbedtls_ssl_context *ssl); /* * TLS 1.3 key schedule evolutions * * Early -> Handshake -> Application * * Small wrappers around mbedtls_ssl_tls13_evolve_secret(). */ /** * \brief Begin TLS 1.3 key schedule by calculating early secret. * * The TLS 1.3 key schedule can be viewed as a simple state machine * with states Initial -> Early -> Handshake -> Application, and * this function represents the Initial -> Early transition. * * \param ssl The SSL context to operate on. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl); /** * \brief Compute TLS 1.3 resumption master secret. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Application, see * mbedtls_ssl_tls13_key_schedule_stage_application(). * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl); /** * \brief Calculate the verify_data value for the client or server TLS 1.3 * Finished message. * * \param ssl The SSL context to operate on. This must be in * key schedule stage \c Handshake, see * mbedtls_ssl_tls13_key_schedule_stage_application(). * \param dst The address at which to write the verify_data value. * \param dst_len The size of \p dst in bytes. * \param actual_len The address at which to store the amount of data * actually written to \p dst upon success. * \param which The message to calculate the `verify_data` for: * - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message * - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message * * \note Both client and server call this function twice, once to * generate their own Finished message, and once to verify the * peer's Finished message. * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl, unsigned char *dst, size_t dst_len, size_t *actual_len, int which); #if defined(MBEDTLS_SSL_EARLY_DATA) /** * \brief Compute TLS 1.3 early transform * * \param ssl The SSL context to operate on. * * \returns \c 0 on success. * \returns A negative error code on failure. * * \warning The function does not compute the early master secret. Call * mbedtls_ssl_tls13_key_schedule_stage_early() before to * call this function to generate the early master secret. * \note For a client/server endpoint, the function computes only the * encryption/decryption part of the transform as the decryption/ * encryption part is not defined by the specification (no early * traffic from the server to the client). */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_early_transform(mbedtls_ssl_context *ssl); #endif /* MBEDTLS_SSL_EARLY_DATA */ /** * \brief Compute TLS 1.3 handshake transform * * \param ssl The SSL context to operate on. The early secret must have been * computed. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_handshake_transform(mbedtls_ssl_context *ssl); /** * \brief Compute TLS 1.3 application transform * * \param ssl The SSL context to operate on. The early secret must have been * computed. * * \returns \c 0 on success. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_compute_application_transform(mbedtls_ssl_context *ssl); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /** * \brief Export TLS 1.3 PSK from handshake context * * \param[in] ssl The SSL context to operate on. * \param[out] psk PSK output pointer. * \param[out] psk_len Length of PSK. * * \returns \c 0 if there is a configured PSK and it was exported * successfully. * \returns A negative error code on failure. */ MBEDTLS_CHECK_RETURN_CRITICAL int mbedtls_ssl_tls13_export_handshake_psk(mbedtls_ssl_context *ssl, unsigned char **psk, size_t *psk_len); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c000066400000000000000000003675661464416617300247440ustar00rootroot00000000000000/* * TLS 1.3 server-side functions * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3) #include "debug_internal.h" #include "mbedtls/error.h" #include "mbedtls/platform.h" #include "mbedtls/constant_time.h" #include "mbedtls/oid.h" #include "mbedtls/psa_util.h" #include "ssl_misc.h" #include "ssl_tls13_keys.h" #include "ssl_debug_helpers.h" static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite( mbedtls_ssl_context *ssl, unsigned int cipher_suite) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info; if (!mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, cipher_suite)) { return NULL; } ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(cipher_suite); if ((mbedtls_ssl_validate_ciphersuite(ssl, ciphersuite_info, ssl->tls_version, ssl->tls_version) != 0)) { return NULL; } return ciphersuite_info; } static void ssl_tls13_select_ciphersuite( mbedtls_ssl_context *ssl, const unsigned char *cipher_suites, const unsigned char *cipher_suites_end, int psk_ciphersuite_id, psa_algorithm_t psk_hash_alg, const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info) { *selected_ciphersuite_info = NULL; /* * In a compliant ClientHello the byte-length of the list of ciphersuites * is even and this function relies on this fact. This should have been * checked in the main ClientHello parsing function. Double check here. */ if ((cipher_suites_end - cipher_suites) & 1) { return; } for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) { /* * "cipher_suites_end - p is even" is an invariant of the loop. As * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it * is thus safe to read two bytes. */ uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0); const mbedtls_ssl_ciphersuite_t *info = ssl_tls13_validate_peer_ciphersuite(ssl, id); if (info == NULL) { continue; } /* * If a valid PSK ciphersuite identifier has been passed in, we want * an exact match. */ if (psk_ciphersuite_id != 0) { if (id != psk_ciphersuite_id) { continue; } } else if (psk_hash_alg != PSA_ALG_NONE) { if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) != psk_hash_alg) { continue; } } *selected_ciphersuite_info = info; return; } MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%x", (unsigned) psk_ciphersuite_id, psk_hash_alg)); } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* From RFC 8446: * * enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode; * struct { * PskKeyExchangeMode ke_modes<1..255>; * } PskKeyExchangeModes; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t ke_modes_len; int ke_modes = 0; /* Read ke_modes length (1 Byte) */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); ke_modes_len = *p++; /* Currently, there are only two PSK modes, so even without looking * at the content, something's wrong if the list has more than 2 items. */ if (ke_modes_len > 2) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, ke_modes_len); while (ke_modes_len-- != 0) { switch (*p++) { case MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE: ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK KEX MODE")); break; case MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE: ke_modes |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; MBEDTLS_SSL_DEBUG_MSG(3, ("Found PSK_EPHEMERAL KEX MODE")); break; default: MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } } ssl->handshake->tls13_kex_modes = ke_modes; return 0; } /* * Non-error return values of * ssl_tls13_offered_psks_check_identity_match_ticket() and * ssl_tls13_offered_psks_check_identity_match(). They are positive to * not collide with error codes that are negative. Zero * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated * up by the callers of this function as a generic success condition. * * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means * that the pre-shared-key identity matches that of a ticket or an externally- * provisioned pre-shared-key. We have thus been able to retrieve the * attributes of the pre-shared-key but at least one of them does not meet * some criteria and the pre-shared-key cannot be used. For example, a ticket * is expired or its version is not TLS 1.3. Note eventually that the return * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have * anything to do with binder check. A binder check is done only when a * suitable pre-shared-key has been selected and only for that selected * pre-shared-key: if the binder check fails, we fail the handshake and we do * not try to find another pre-shared-key for which the binder check would * succeed as recommended by the specification. */ #define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2 #define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1 #define SSL_TLS1_3_PSK_IDENTITY_MATCH 0 #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl); MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_offered_psks_check_identity_match_ticket( mbedtls_ssl_context *ssl, const unsigned char *identity, size_t identity_len, uint32_t obfuscated_ticket_age, mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *ticket_buffer; #if defined(MBEDTLS_HAVE_TIME) mbedtls_ms_time_t now; mbedtls_ms_time_t server_age; uint32_t client_age; mbedtls_ms_time_t age_diff; #endif ((void) obfuscated_ticket_age); MBEDTLS_SSL_DEBUG_MSG(2, ("=> check_identity_match_ticket")); /* Ticket parser is not configured, Skip */ if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) { return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } /* We create a copy of the encrypted ticket since the ticket parsing * function is allowed to use its input buffer as an output buffer * (in-place decryption). We do, however, need the original buffer for * computing the PSK binder value. */ ticket_buffer = mbedtls_calloc(1, identity_len); if (ticket_buffer == NULL) { return MBEDTLS_ERR_SSL_ALLOC_FAILED; } memcpy(ticket_buffer, identity, identity_len); ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket, session, ticket_buffer, identity_len); switch (ret) { case 0: ret = SSL_TLS1_3_PSK_IDENTITY_MATCH; break; case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED: MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired")); ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; break; case MBEDTLS_ERR_SSL_INVALID_MAC: MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic")); ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; break; default: MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret); ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } /* We delete the temporary buffer */ mbedtls_free(ticket_buffer); if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { goto exit; } /* * The identity matches that of a ticket. Now check that it has suitable * attributes and bet it will not be the case. */ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) { MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3.")); goto exit; } #if defined(MBEDTLS_HAVE_TIME) now = mbedtls_ms_time(); if (now < session->ticket_creation_time) { MBEDTLS_SSL_DEBUG_MSG( 3, ("Invalid ticket creation time ( now = %" MBEDTLS_PRINTF_MS_TIME ", creation_time = %" MBEDTLS_PRINTF_MS_TIME " )", now, session->ticket_creation_time)); goto exit; } server_age = now - session->ticket_creation_time; /* RFC 8446 section 4.6.1 * * Servers MUST NOT use any value greater than 604800 seconds (7 days). * * RFC 8446 section 4.2.11.1 * * Clients MUST NOT attempt to use tickets which have ages greater than * the "ticket_lifetime" value which was provided with the ticket. * */ if (server_age > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME * 1000) { MBEDTLS_SSL_DEBUG_MSG( 3, ("Ticket age exceeds limitation ticket_age = %" MBEDTLS_PRINTF_MS_TIME, server_age)); goto exit; } /* RFC 8446 section 4.2.10 * * For PSKs provisioned via NewSessionTicket, a server MUST validate that * the ticket age for the selected PSK identity (computed by subtracting * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is * within a small tolerance of the time since the ticket was issued. * * NOTE: The typical accuracy of an RTC crystal is ±100 to ±20 parts per * million (360 to 72 milliseconds per hour). Default tolerance * window is 6s, thus in the worst case clients and servers must * sync up their system time every 6000/360/2~=8 hours. */ client_age = obfuscated_ticket_age - session->ticket_age_add; age_diff = server_age - (mbedtls_ms_time_t) client_age; if (age_diff < -MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE || age_diff > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) { MBEDTLS_SSL_DEBUG_MSG( 3, ("Ticket age outside tolerance window ( diff = %" MBEDTLS_PRINTF_MS_TIME ")", age_diff)); goto exit; } #endif /* MBEDTLS_HAVE_TIME */ /* * All good, we have found a suitable ticket. */ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH; exit: if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { mbedtls_ssl_session_free(session); } MBEDTLS_SSL_DEBUG_MSG(2, ("<= check_identity_match_ticket")); return ret; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_offered_psks_check_identity_match( mbedtls_ssl_context *ssl, const unsigned char *identity, size_t identity_len, uint32_t obfuscated_ticket_age, int *psk_type, mbedtls_ssl_session *session) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ((void) session); ((void) obfuscated_ticket_age); *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL; MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len); #if defined(MBEDTLS_SSL_SESSION_TICKETS) ret = ssl_tls13_offered_psks_check_identity_match_ticket( ssl, identity, identity_len, obfuscated_ticket_age, session); if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) { *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION; ret = mbedtls_ssl_set_hs_psk(ssl, session->resumption_key, session->resumption_key_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(4, "Ticket-resumed PSK:", session->resumption_key, session->resumption_key_len); MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u", (unsigned) obfuscated_ticket_age)); return SSL_TLS1_3_PSK_IDENTITY_MATCH; } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) { return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* Check identity with external configured function */ if (ssl->conf->f_psk != NULL) { if (ssl->conf->f_psk( ssl->conf->p_psk, ssl, identity, identity_len) == 0) { return SSL_TLS1_3_PSK_IDENTITY_MATCH; } return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len); /* Check identity with pre-configured psk */ if (ssl->conf->psk_identity != NULL && identity_len == ssl->conf->psk_identity_len && mbedtls_ct_memcmp(ssl->conf->psk_identity, identity, identity_len) == 0) { ret = mbedtls_ssl_set_hs_psk(ssl, ssl->conf->psk, ssl->conf->psk_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret); return ret; } return SSL_TLS1_3_PSK_IDENTITY_MATCH; } return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH; } /* * Non-error return values of ssl_tls13_offered_psks_check_binder_match(). * They are positive to not collide with error codes that are negative. Zero * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up * by the callers of this function as a generic success condition. */ #define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1 #define SSL_TLS1_3_BINDER_MATCH 0 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_offered_psks_check_binder_match( mbedtls_ssl_context *ssl, const unsigned char *binder, size_t binder_len, int psk_type, psa_algorithm_t psk_hash_alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char transcript[PSA_HASH_MAX_SIZE]; size_t transcript_len; unsigned char *psk; size_t psk_len; unsigned char server_computed_binder[PSA_HASH_MAX_SIZE]; if (binder_len != PSA_HASH_LENGTH(psk_hash_alg)) { return SSL_TLS1_3_BINDER_DOES_NOT_MATCH; } /* Get current state of handshake transcript. */ ret = mbedtls_ssl_get_handshake_transcript( ssl, mbedtls_md_type_from_psa_alg(psk_hash_alg), transcript, sizeof(transcript), &transcript_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_create_psk_binder(ssl, psk_hash_alg, psk, psk_len, psk_type, transcript, server_computed_binder); #if defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_free((void *) psk); #endif if (ret != 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("PSK binder calculation failed.")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( computed ): ", server_computed_binder, transcript_len); MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len); if (mbedtls_ct_memcmp(server_computed_binder, binder, PSA_HASH_LENGTH(psk_hash_alg)) == 0) { return SSL_TLS1_3_BINDER_MATCH; } mbedtls_platform_zeroize(server_computed_binder, sizeof(server_computed_binder)); return SSL_TLS1_3_BINDER_DOES_NOT_MATCH; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst, const mbedtls_ssl_session *src) { dst->ticket_age_add = src->ticket_age_add; dst->ticket_flags = src->ticket_flags; dst->resumption_key_len = src->resumption_key_len; if (src->resumption_key_len == 0) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len); #if defined(MBEDTLS_SSL_EARLY_DATA) dst->max_early_data_size = src->max_early_data_size; #if defined(MBEDTLS_SSL_ALPN) int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn); if (ret != 0) { return ret; } #endif /* MBEDTLS_SSL_ALPN */ #endif /* MBEDTLS_SSL_EARLY_DATA*/ return 0; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ struct psk_attributes { int type; int key_exchange_mode; const mbedtls_ssl_ciphersuite_t *ciphersuite_info; }; #define PSK_ATTRIBUTES_INIT { 0, 0, NULL } /* Parser for pre_shared_key extension in client hello * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * struct { * PskIdentity identities<7..2^16-1>; * PskBinderEntry binders<33..2^16-1>; * } OfferedPsks; * * struct { * select (Handshake.msg_type) { * case client_hello: OfferedPsks; * .... * }; * } PreSharedKeyExtension; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_pre_shared_key_ext( mbedtls_ssl_context *ssl, const unsigned char *pre_shared_key_ext, const unsigned char *pre_shared_key_ext_end, const unsigned char *ciphersuites, const unsigned char *ciphersuites_end, struct psk_attributes *psk) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *identities = pre_shared_key_ext; const unsigned char *p_identity_len; size_t identities_len; const unsigned char *identities_end; const unsigned char *binders; const unsigned char *p_binder_len; size_t binders_len; const unsigned char *binders_end; int matched_identity = -1; int identity_id = -1; MBEDTLS_SSL_DEBUG_BUF(3, "pre_shared_key extension", pre_shared_key_ext, pre_shared_key_ext_end - pre_shared_key_ext); /* identities_len 2 bytes * identities_data >= 7 bytes */ MBEDTLS_SSL_CHK_BUF_READ_PTR(identities, pre_shared_key_ext_end, 7 + 2); identities_len = MBEDTLS_GET_UINT16_BE(identities, 0); p_identity_len = identities + 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, pre_shared_key_ext_end, identities_len); identities_end = p_identity_len + identities_len; /* binders_len 2 bytes * binders >= 33 bytes */ binders = identities_end; MBEDTLS_SSL_CHK_BUF_READ_PTR(binders, pre_shared_key_ext_end, 33 + 2); binders_len = MBEDTLS_GET_UINT16_BE(binders, 0); p_binder_len = binders + 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, pre_shared_key_ext_end, binders_len); binders_end = p_binder_len + binders_len; ret = ssl->handshake->update_checksum(ssl, pre_shared_key_ext, identities_end - pre_shared_key_ext); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } while (p_identity_len < identities_end && p_binder_len < binders_end) { const unsigned char *identity; size_t identity_len; uint32_t obfuscated_ticket_age; const unsigned char *binder; size_t binder_len; int psk_ciphersuite_id; psa_algorithm_t psk_hash_alg; int allowed_key_exchange_modes; #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_session session; mbedtls_ssl_session_init(&session); #endif MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4); identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0); identity = p_identity_len + 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(identity, identities_end, identity_len + 4); obfuscated_ticket_age = MBEDTLS_GET_UINT32_BE(identity, identity_len); p_identity_len += identity_len + 6; MBEDTLS_SSL_CHK_BUF_READ_PTR(p_binder_len, binders_end, 1 + 32); binder_len = *p_binder_len; binder = p_binder_len + 1; MBEDTLS_SSL_CHK_BUF_READ_PTR(binder, binders_end, binder_len); p_binder_len += binder_len + 1; identity_id++; if (matched_identity != -1) { continue; } ret = ssl_tls13_offered_psks_check_identity_match( ssl, identity, identity_len, obfuscated_ticket_age, &psk->type, &session); if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) { continue; } MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity")); switch (psk->type) { case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL: psk_ciphersuite_id = 0; psk_hash_alg = PSA_ALG_SHA_256; allowed_key_exchange_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; break; #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION: psk_ciphersuite_id = session.ciphersuite; psk_hash_alg = PSA_ALG_NONE; ssl->session_negotiate->ticket_flags = session.ticket_flags; allowed_key_exchange_modes = session.ticket_flags & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL; break; #endif default: return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE; if ((allowed_key_exchange_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) && ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) { psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; } else if ((allowed_key_exchange_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) && ssl_tls13_key_exchange_is_psk_available(ssl)) { psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; } if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) { MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable PSK key exchange mode")); continue; } ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end, psk_ciphersuite_id, psk_hash_alg, &psk->ciphersuite_info); if (psk->ciphersuite_info == NULL) { #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_session_free(&session); #endif /* * We consider finding a ciphersuite suitable for the PSK as part * of the validation of its binder. Thus if we do not find one, we * abort the handshake with a decrypt_error alert. */ MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ret = ssl_tls13_offered_psks_check_binder_match( ssl, binder, binder_len, psk->type, mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac)); if (ret != SSL_TLS1_3_BINDER_MATCH) { /* For security reasons, the handshake should be aborted when we * fail to validate a binder value. See RFC 8446 section 4.2.11.2 * and appendix E.6. */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_session_free(&session); #endif MBEDTLS_SSL_DEBUG_MSG(3, ("Invalid binder.")); MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_offered_psks_check_binder_match", ret); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return ret; } matched_identity = identity_id; #if defined(MBEDTLS_SSL_SESSION_TICKETS) if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate, &session); mbedtls_ssl_session_free(&session); if (ret != 0) { return ret; } } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ } if (p_identity_len != identities_end || p_binder_len != binders_end) { MBEDTLS_SSL_DEBUG_MSG(3, ("pre_shared_key extension decode error")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Update the handshake transcript with the binder list. */ ret = ssl->handshake->update_checksum( ssl, identities_end, (size_t) (binders_end - identities_end)); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } if (matched_identity == -1) { MBEDTLS_SSL_DEBUG_MSG(3, ("No usable PSK or ticket.")); return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; } ssl->handshake->selected_identity = (uint16_t) matched_identity; MBEDTLS_SSL_DEBUG_MSG(3, ("Pre shared key found")); return 0; } /* * struct { * select ( Handshake.msg_type ) { * .... * case server_hello: * uint16 selected_identity; * } * } PreSharedKeyExtension; */ static int ssl_tls13_write_server_pre_shared_key_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *olen) { unsigned char *p = (unsigned char *) buf; *olen = 0; int not_using_psk = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) not_using_psk = (mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)); #else not_using_psk = (ssl->handshake->psk == NULL); #endif if (not_using_psk) { /* We shouldn't have called this extension writer unless we've * chosen to use a PSK. */ return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding pre_shared_key extension")); MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_PRE_SHARED_KEY, p, 0); MBEDTLS_PUT_UINT16_BE(2, p, 2); MBEDTLS_PUT_UINT16_BE(ssl->handshake->selected_identity, p, 4); *olen = 6; MBEDTLS_SSL_DEBUG_MSG(4, ("sent selected_identity: %u", ssl->handshake->selected_identity)); mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_PRE_SHARED_KEY); return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ /* From RFC 8446: * struct { * ProtocolVersion versions<2..254>; * } SupportedVersions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t versions_len; const unsigned char *versions_end; uint16_t tls_version; int found_supported_version = 0; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1); versions_len = p[0]; p += 1; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, versions_len); versions_end = p + versions_len; while (p < versions_end) { MBEDTLS_SSL_CHK_BUF_READ_PTR(p, versions_end, 2); tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport); p += 2; if (MBEDTLS_SSL_VERSION_TLS1_3 == tls_version) { found_supported_version = 1; break; } if ((MBEDTLS_SSL_VERSION_TLS1_2 == tls_version) && mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { found_supported_version = 1; break; } } if (!found_supported_version) { MBEDTLS_SSL_DEBUG_MSG(1, ("No supported version found.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version: [%04x]", (unsigned int) tls_version)); return (int) tls_version; } #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) /* * * From RFC 8446: * enum { * ... (0xFFFF) * } NamedGroup; * struct { * NamedGroup named_group_list<2..2^16-1>; * } NamedGroupList; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { const unsigned char *p = buf; size_t named_group_list_len; const unsigned char *named_group_list_end; MBEDTLS_SSL_DEBUG_BUF(3, "supported_groups extension", p, end - buf); MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); named_group_list_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, named_group_list_len); named_group_list_end = p + named_group_list_len; ssl->handshake->hrr_selected_group = 0; while (p < named_group_list_end) { uint16_t named_group; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, named_group_list_end, 2); named_group = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(2, ("got named group: %s(%04x)", mbedtls_ssl_named_group_to_str(named_group), named_group)); if (!mbedtls_ssl_named_group_is_offered(ssl, named_group) || !mbedtls_ssl_named_group_is_supported(named_group) || ssl->handshake->hrr_selected_group != 0) { continue; } MBEDTLS_SSL_DEBUG_MSG(2, ("add named group %s(%04x) into received list.", mbedtls_ssl_named_group_to_str(named_group), named_group)); ssl->handshake->hrr_selected_group = named_group; } return 0; } #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */ #define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) /* * ssl_tls13_parse_key_shares_ext() verifies whether the information in the * extension is correct and stores the first acceptable key share and its * associated group. * * Possible return values are: * - 0: Successful processing of the client provided key share extension. * - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by * the client does not match a group supported by the server. A * HelloRetryRequest will be needed. * - A negative value for fatal errors. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char const *p = buf; unsigned char const *client_shares_end; size_t client_shares_len; /* From RFC 8446: * * struct { * KeyShareEntry client_shares<0..2^16-1>; * } KeyShareClientHello; * */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2); client_shares_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, client_shares_len); ssl->handshake->offered_group_id = 0; client_shares_end = p + client_shares_len; /* We try to find a suitable key share entry and copy it to the * handshake context. Later, we have to find out whether we can do * something with the provided key share or whether we have to * dismiss it and send a HelloRetryRequest message. */ while (p < client_shares_end) { uint16_t group; size_t key_exchange_len; const unsigned char *key_exchange; /* * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, 4); group = MBEDTLS_GET_UINT16_BE(p, 0); key_exchange_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; key_exchange = p; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, client_shares_end, key_exchange_len); p += key_exchange_len; /* Continue parsing even if we have already found a match, * for input validation purposes. */ if (!mbedtls_ssl_named_group_is_offered(ssl, group) || !mbedtls_ssl_named_group_is_supported(group) || ssl->handshake->offered_group_id != 0) { continue; } /* * ECDHE and FFDHE groups are supported */ if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) || mbedtls_ssl_tls13_named_group_is_ffdh(group)) { MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH/FFDH group: %s (%04x)", mbedtls_ssl_named_group_to_str(group), group)); ret = mbedtls_ssl_tls13_read_public_xxdhe_share( ssl, key_exchange - 2, key_exchange_len + 2); if (ret != 0) { return ret; } } else { MBEDTLS_SSL_DEBUG_MSG(4, ("Unrecognized NamedGroup %u", (unsigned) group)); continue; } ssl->handshake->offered_group_id = group; } if (ssl->handshake->offered_group_id == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching key share")); return SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH; } return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl, int exts_mask) { int masked = ssl->handshake->received_extensions & exts_mask; return masked == exts_mask; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange( mbedtls_ssl_context *ssl) { return ssl_tls13_client_hello_has_exts( ssl, MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | MBEDTLS_SSL_EXT_MASK(SIG_ALG)); } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts_for_psk_key_exchange( mbedtls_ssl_context *ssl) { return ssl_tls13_client_hello_has_exts( ssl, MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange( mbedtls_ssl_context *ssl) { return ssl_tls13_client_hello_has_exts( ssl, MBEDTLS_SSL_EXT_MASK(SUPPORTED_GROUPS) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE) | MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)); } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) && mbedtls_ssl_tls13_is_psk_supported(ssl) && ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl); #else ((void) ssl); return 0; #endif } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) && mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) && ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl); #else ((void) ssl); return 0; #endif } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_key_exchange_is_ephemeral_available(mbedtls_ssl_context *ssl) { #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) return mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl) && ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl); #else ((void) ssl); return 0; #endif } #if defined(MBEDTLS_X509_CRT_PARSE_C) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) static psa_algorithm_t ssl_tls13_iana_sig_alg_to_psa_alg(uint16_t sig_alg) { switch (sig_alg) { case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: return PSA_ALG_ECDSA(PSA_ALG_SHA_256); case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: return PSA_ALG_ECDSA(PSA_ALG_SHA_384); case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: return PSA_ALG_ECDSA(PSA_ALG_SHA_512); case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: return PSA_ALG_RSA_PSS(PSA_ALG_SHA_256); case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384: return PSA_ALG_RSA_PSS(PSA_ALG_SHA_384); case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512: return PSA_ALG_RSA_PSS(PSA_ALG_SHA_512); case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256: return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256); case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384: return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_384); case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512: return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512); default: return PSA_ALG_NONE; } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* * Pick best ( private key, certificate chain ) pair based on the signature * algorithms supported by the client. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl) { mbedtls_ssl_key_cert *key_cert, *key_cert_list; const uint16_t *sig_alg = ssl->handshake->received_sig_algs; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_key_cert != NULL) { key_cert_list = ssl->handshake->sni_key_cert; } else #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ key_cert_list = ssl->conf->key_cert; if (key_cert_list == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("server has no certificate")); return -1; } for (; *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++) { if (!mbedtls_ssl_sig_alg_is_offered(ssl, *sig_alg)) { continue; } if (!mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(*sig_alg)) { continue; } for (key_cert = key_cert_list; key_cert != NULL; key_cert = key_cert->next) { #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t psa_alg = PSA_ALG_NONE; #endif /* MBEDTLS_USE_PSA_CRYPTO */ MBEDTLS_SSL_DEBUG_CRT(3, "certificate (chain) candidate", key_cert->cert); /* * This avoids sending the client a cert it'll reject based on * keyUsage or other extensions. */ if (mbedtls_x509_crt_check_key_usage( key_cert->cert, MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0 || mbedtls_x509_crt_check_extended_key_usage( key_cert->cert, MBEDTLS_OID_SERVER_AUTH, MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH)) != 0) { MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: " "(extended) key usage extension")); continue; } MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_tls13_pick_key_cert:" "check signature algorithm %s [%04x]", mbedtls_ssl_sig_alg_to_str(*sig_alg), *sig_alg)); #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_alg = ssl_tls13_iana_sig_alg_to_psa_alg(*sig_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (mbedtls_ssl_tls13_check_sig_alg_cert_key_match( *sig_alg, &key_cert->cert->pk) #if defined(MBEDTLS_USE_PSA_CRYPTO) && psa_alg != PSA_ALG_NONE && mbedtls_pk_can_do_ext(&key_cert->cert->pk, psa_alg, PSA_KEY_USAGE_SIGN_HASH) == 1 #endif /* MBEDTLS_USE_PSA_CRYPTO */ ) { ssl->handshake->key_cert = key_cert; MBEDTLS_SSL_DEBUG_MSG(3, ("ssl_tls13_pick_key_cert:" "selected signature algorithm" " %s [%04x]", mbedtls_ssl_sig_alg_to_str(*sig_alg), *sig_alg)); MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate (chain)", ssl->handshake->key_cert->cert); return 0; } } } MBEDTLS_SSL_DEBUG_MSG(2, ("ssl_tls13_pick_key_cert:" "no suitable certificate found")); return -1; } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * * STATE HANDLING: ClientHello * * There are three possible classes of outcomes when parsing the ClientHello: * * 1) The ClientHello was well-formed and matched the server's configuration. * * In this case, the server progresses to sending its ServerHello. * * 2) The ClientHello was well-formed but didn't match the server's * configuration. * * For example, the client might not have offered a key share which * the server supports, or the server might require a cookie. * * In this case, the server sends a HelloRetryRequest. * * 3) The ClientHello was ill-formed * * In this case, we abort the handshake. * */ /* * Structure of this message: * * uint16 ProtocolVersion; * opaque Random[32]; * uint8 CipherSuite[2]; // Cryptographic suite selector * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 * Random random; * opaque legacy_session_id<0..32>; * CipherSuite cipher_suites<2..2^16-2>; * opaque legacy_compression_methods<1..2^8-1>; * Extension extensions<8..2^16-1>; * } ClientHello; */ #define SSL_CLIENT_HELLO_OK 0 #define SSL_CLIENT_HELLO_HRR_REQUIRED 1 #define SSL_CLIENT_HELLO_TLS1_2 2 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned char *p = buf; const unsigned char *random; size_t legacy_session_id_len; const unsigned char *legacy_session_id; size_t cipher_suites_len; const unsigned char *cipher_suites; const unsigned char *cipher_suites_end; size_t extensions_len; const unsigned char *extensions_end; const unsigned char *supported_versions_data; const unsigned char *supported_versions_data_end; mbedtls_ssl_handshake_params *handshake = ssl->handshake; int hrr_required = 0; int no_usable_share_for_key_agreement = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) int got_psk = 0; struct psk_attributes psk = PSK_ATTRIBUTES_INIT; const unsigned char *pre_shared_key_ext = NULL; const unsigned char *pre_shared_key_ext_end = NULL; #endif /* * ClientHello layout: * 0 . 1 protocol version * 2 . 33 random bytes * 34 . 34 session id length ( 1 byte ) * 35 . 34+x session id * .. . .. ciphersuite list length ( 2 bytes ) * .. . .. ciphersuite list * .. . .. compression alg. list length ( 1 byte ) * .. . .. compression alg. list * .. . .. extensions length ( 2 bytes, optional ) * .. . .. extensions ( optional ) */ /* * Minimal length ( with everything empty and extensions omitted ) is * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can * read at least up to session id length without worrying. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 38); /* ... * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * ... * with ProtocolVersion defined as: * uint16 ProtocolVersion; */ if (mbedtls_ssl_read_version(p, ssl->conf->transport) != MBEDTLS_SSL_VERSION_TLS1_2) { MBEDTLS_SSL_DEBUG_MSG(1, ("Unsupported version of TLS.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } p += 2; /* ... * Random random; * ... * with Random defined as: * opaque Random[32]; */ random = p; p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; /* ... * opaque legacy_session_id<0..32>; * ... */ legacy_session_id_len = *(p++); legacy_session_id = p; /* * Check we have enough data for the legacy session identifier * and the ciphersuite list length. */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2); p += legacy_session_id_len; /* ... * CipherSuite cipher_suites<2..2^16-2>; * ... * with CipherSuite defined as: * uint8 CipherSuite[2]; */ cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; cipher_suites = p; /* * The length of the ciphersuite list has to be even. */ if (cipher_suites_len & 1) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } /* Check we have enough data for the ciphersuite list, the legacy * compression methods and the length of the extensions. * * cipher_suites cipher_suites_len bytes * legacy_compression_methods 2 bytes * extensions_len 2 bytes */ MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 2 + 2); p += cipher_suites_len; cipher_suites_end = p; /* * Search for the supported versions extension and parse it to determine * if the client supports TLS 1.3. */ ret = mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts( ssl, p + 2, end, &supported_versions_data, &supported_versions_data_end); if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts"), ret); return ret; } if (ret == 0) { return SSL_CLIENT_HELLO_TLS1_2; } if (ret == 1) { ret = ssl_tls13_parse_supported_versions_ext(ssl, supported_versions_data, supported_versions_data_end); if (ret < 0) { MBEDTLS_SSL_DEBUG_RET(1, ("ssl_tls13_parse_supported_versions_ext"), ret); return ret; } /* * The supported versions extension was parsed successfully as the * value returned by ssl_tls13_parse_supported_versions_ext() is * positive. The return value is then equal to * MBEDTLS_SSL_VERSION_TLS1_2 or MBEDTLS_SSL_VERSION_TLS1_3, defining * the TLS version to negotiate. */ if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) { return SSL_CLIENT_HELLO_TLS1_2; } } /* * We negotiate TLS 1.3. */ ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3; ssl->session_negotiate->endpoint = ssl->conf->endpoint; /* * We are negotiating the version 1.3 of the protocol. Do what we have * postponed: copy of the client random bytes, copy of the legacy session * identifier and selection of the TLS 1.3 cipher suite. */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes", random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); memcpy(&handshake->randbytes[0], random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN); if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message")); return MBEDTLS_ERR_SSL_DECODE_ERROR; } ssl->session_negotiate->id_len = legacy_session_id_len; MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id", legacy_session_id, legacy_session_id_len); memcpy(&ssl->session_negotiate->id[0], legacy_session_id, legacy_session_id_len); /* * Search for a matching ciphersuite */ MBEDTLS_SSL_DEBUG_BUF(3, "client hello, list of cipher suites", cipher_suites, cipher_suites_len); ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end, 0, PSA_ALG_NONE, &handshake->ciphersuite_info); if (handshake->ciphersuite_info == NULL) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id; MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s", ((unsigned) handshake->ciphersuite_info->id), handshake->ciphersuite_info->name)); /* ... * opaque legacy_compression_methods<1..2^8-1>; * ... */ if (p[0] != 1 || p[1] != MBEDTLS_SSL_COMPRESS_NULL) { MBEDTLS_SSL_DEBUG_MSG(1, ("bad legacy compression method")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } p += 2; /* ... * Extension extensions<8..2^16-1>; * ... * with Extension defined as: * struct { * ExtensionType extension_type; * opaque extension_data<0..2^16-1>; * } Extension; */ extensions_len = MBEDTLS_GET_UINT16_BE(p, 0); p += 2; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len); extensions_end = p + extensions_len; MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p, extensions_len); handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE; while (p < extensions_end) { unsigned int extension_type; size_t extension_data_len; const unsigned char *extension_data_end; uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH; if (ssl->handshake->hello_retry_request_flag) { /* Do not accept early data extension in 2nd ClientHello */ allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA); } /* RFC 8446, section 4.2.11 * * The "pre_shared_key" extension MUST be the last extension in the * ClientHello (this facilitates implementation as described below). * Servers MUST check that it is the last extension and otherwise fail * the handshake with an "illegal_parameter" alert. */ if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { MBEDTLS_SSL_DEBUG_MSG( 3, ("pre_shared_key is not last extension.")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4); extension_type = MBEDTLS_GET_UINT16_BE(p, 0); extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2); p += 4; MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len); extension_data_end = p + extension_data_len; ret = mbedtls_ssl_tls13_check_received_extension( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type, allowed_exts); if (ret != 0) { return ret; } switch (extension_type) { #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) case MBEDTLS_TLS_EXT_SERVERNAME: MBEDTLS_SSL_DEBUG_MSG(3, ("found ServerName extension")); ret = mbedtls_ssl_parse_server_name_ext(ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_parse_servername_ext", ret); return ret; } break; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension")); /* Supported Groups Extension * * When sent by the client, the "supported_groups" extension * indicates the named groups which the client supports, * ordered from most preferred to least preferred. */ ret = ssl_tls13_parse_supported_groups_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_supported_groups_ext", ret); return ret; } break; #endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH*/ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) case MBEDTLS_TLS_EXT_KEY_SHARE: MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension")); /* * Key Share Extension * * When sent by the client, the "key_share" extension * contains the endpoint's cryptographic parameters for * ECDHE/DHE key establishment methods. */ ret = ssl_tls13_parse_key_shares_ext( ssl, p, extension_data_end); if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) { MBEDTLS_SSL_DEBUG_MSG(2, ("No usable share for key agreement.")); no_usable_share_for_key_agreement = 1; } if (ret < 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_key_shares_ext", ret); return ret; } break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: /* Already parsed */ break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES: MBEDTLS_SSL_DEBUG_MSG( 3, ("found psk key exchange modes extension")); ret = ssl_tls13_parse_key_exchange_modes_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_key_exchange_modes_ext", ret); return ret; } break; #endif case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: MBEDTLS_SSL_DEBUG_MSG(3, ("found pre_shared_key extension")); if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PSK_KEY_EXCHANGE_MODES)) == 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* Delay processing of the PSK identity once we have * found out which algorithms to use. We keep a pointer * to the buffer and the size for later processing. */ pre_shared_key_ext = p; pre_shared_key_ext_end = extension_data_end; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ break; #if defined(MBEDTLS_SSL_ALPN) case MBEDTLS_TLS_EXT_ALPN: MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension")); ret = mbedtls_ssl_parse_alpn_ext(ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("mbedtls_ssl_parse_alpn_ext"), ret); return ret; } break; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_TLS_EXT_SIG_ALG: MBEDTLS_SSL_DEBUG_MSG(3, ("found signature_algorithms extension")); ret = mbedtls_ssl_parse_sig_alg_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_parse_sig_alg_ext", ret); return ret; } break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT: MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension")); ret = mbedtls_ssl_tls13_parse_record_size_limit_ext( ssl, p, extension_data_end); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret); return ret; } break; #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ default: MBEDTLS_SSL_PRINT_EXT( 3, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type, "( ignored )"); break; } p += extension_data_len; } MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO, handshake->received_extensions); ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, p - buf); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* Update checksum with either * - The entire content of the CH message, if no PSK extension is present * - The content up to but excluding the PSK extension, if present. * Always parse the pre-shared-key extension when present in the * ClientHello even if some pre-requisites for PSK key exchange modes are * not met. That way we always validate the syntax of the extension. */ if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) { ret = handshake->update_checksum(ssl, buf, pre_shared_key_ext - buf); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } ret = ssl_tls13_parse_pre_shared_key_ext(ssl, pre_shared_key_ext, pre_shared_key_ext_end, cipher_suites, cipher_suites_end, &psk); if (ret == 0) { got_psk = 1; } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_parse_pre_shared_key_ext", ret); return ret; } } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */ { ret = handshake->update_checksum(ssl, buf, p - buf); if (0 != ret) { MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret); return ret; } } /* * Determine the key exchange algorithm to use. * There are three types of key exchanges supported in TLS 1.3: * - (EC)DH with ECDSA, * - (EC)DH with PSK, * - plain PSK. * * The PSK-based key exchanges may additionally be used with 0-RTT. * * Our built-in order of preference is * 1 ) (EC)DHE-PSK Mode ( psk_ephemeral ) * 2 ) Certificate Mode ( ephemeral ) * 3 ) Plain PSK Mode ( psk ) */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (got_psk && (psk.key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) { handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral")); } else #endif if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) { handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral")); } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) else if (got_psk && (psk.key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) { handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk")); } #endif else { MBEDTLS_SSL_DEBUG_MSG( 1, ("ClientHello message misses mandatory extensions.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (handshake->key_exchange_mode & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) { handshake->ciphersuite_info = psk.ciphersuite_info; ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id; MBEDTLS_SSL_DEBUG_MSG(2, ("Select PSK ciphersuite: %04x - %s", ((unsigned) psk.ciphersuite_info->id), psk.ciphersuite_info->name)); if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) { handshake->resume = 1; } } #endif if (handshake->key_exchange_mode != MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) { hrr_required = (no_usable_share_for_key_agreement != 0); } mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info); return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK; } #if defined(MBEDTLS_SSL_EARLY_DATA) static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl) { mbedtls_ssl_handshake_params *handshake = ssl->handshake; if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, feature disabled in server configuration.")); return -1; } if (!handshake->resume) { /* We currently support early data only in the case of PSKs established via a NewSessionTicket message thus in the case of a session resumption. */ MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, not a session resumption.")); return -1; } /* RFC 8446 4.2.10 * * In order to accept early data, the server MUST have accepted a PSK cipher * suite and selected the first key offered in the client's "pre_shared_key" * extension. In addition, it MUST verify that the following values are the * same as those associated with the selected PSK: * - The TLS version number * - The selected cipher suite * - The selected ALPN [RFC7301] protocol, if any * * NOTE: * - The TLS version number is checked in * ssl_tls13_offered_psks_check_identity_match_ticket(). */ if (handshake->selected_identity != 0) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, the selected key in " "`pre_shared_key` is not the first one.")); return -1; } if (handshake->ciphersuite_info->id != ssl->session_negotiate->ciphersuite) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, the selected ciphersuite is not the one " "of the selected pre-shared key.")); return -1; } if (!mbedtls_ssl_tls13_session_ticket_allow_early_data(ssl->session_negotiate)) { MBEDTLS_SSL_DEBUG_MSG( 1, ("EarlyData: rejected, early_data not allowed in ticket " "permission bits.")); return -1; } #if defined(MBEDTLS_SSL_ALPN) const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl); size_t alpn_len; if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) { return 0; } if (alpn != NULL) { alpn_len = strlen(alpn); } if (alpn == NULL || ssl->session_negotiate->ticket_alpn == NULL || alpn_len != strlen(ssl->session_negotiate->ticket_alpn) || (memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) { MBEDTLS_SSL_DEBUG_MSG(1, ("EarlyData: rejected, the selected ALPN is different " "from the one associated with the pre-shared key.")); return -1; } #endif return 0; } #endif /* MBEDTLS_SSL_EARLY_DATA */ /* Update the handshake state machine */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl, int hrr_required) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* * Server certificate selection */ if (ssl->conf->f_cert_cb && (ret = ssl->conf->f_cert_cb(ssl)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_cert_cb", ret); return ret; } #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) ssl->handshake->sni_name = NULL; ssl->handshake->sni_name_len = 0; #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ ret = mbedtls_ssl_tls13_key_schedule_stage_early(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls1_3_key_schedule_stage_early", ret); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) { ssl->handshake->early_data_accepted = (!hrr_required) && (ssl_tls13_check_early_data_requirements(ssl) == 0); if (ssl->handshake->early_data_accepted) { ret = mbedtls_ssl_tls13_compute_early_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_early_transform", ret); return ret; } } else { ssl->discard_early_data_record = hrr_required ? MBEDTLS_SSL_EARLY_DATA_DISCARD : MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD; } } #else ((void) hrr_required); #endif /* MBEDTLS_SSL_EARLY_DATA */ return 0; } /* * Main entry point from the state machine; orchestrates the otherfunctions. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf = NULL; size_t buflen = 0; int parse_client_hello_ret; MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, &buf, &buflen)); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf, buf + buflen)); parse_client_hello_ret = ret; /* Store positive return value of * parse_client_hello, * as negative error codes are handled * by MBEDTLS_SSL_PROC_CHK_NEG. */ /* * Version 1.2 of the protocol has to be used for the handshake. * If TLS 1.2 is not supported, abort the handshake. Otherwise, set the * ssl->keep_current_message flag for the ClientHello to be kept and parsed * as a TLS 1.2 ClientHello. We also change ssl->tls_version to * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step() * will dispatch to the TLS 1.2 state machine. */ if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) { /* Check if server supports TLS 1.2 */ if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) { MBEDTLS_SSL_DEBUG_MSG( 1, ("TLS 1.2 not supported.")); MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION); return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION; } ssl->keep_current_message = 1; ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2; return 0; } MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_client_hello(ssl, parse_client_hello_ret == SSL_CLIENT_HELLO_HRR_REQUIRED)); if (SSL_CLIENT_HELLO_OK == parse_client_hello_ret) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST); } cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse client hello")); return ret; } /* * Handler for MBEDTLS_SSL_SERVER_HELLO */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *server_randbytes = ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN; if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes, MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "f_rng", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", server_randbytes, MBEDTLS_SERVER_HELLO_RANDOM_LEN); #if defined(MBEDTLS_HAVE_TIME) ssl->session_negotiate->start = mbedtls_time(NULL); #endif /* MBEDTLS_HAVE_TIME */ return ret; } /* * ssl_tls13_write_server_hello_supported_versions_ext (): * * struct { * ProtocolVersion selected_version; * } SupportedVersions; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_hello_supported_versions_ext( mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, write selected version")); /* Check if we have space to write the extension: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - selected_version (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, buf, 0); MBEDTLS_PUT_UINT16_BE(2, buf, 2); mbedtls_ssl_write_version(buf + 4, ssl->conf->transport, ssl->tls_version); MBEDTLS_SSL_DEBUG_MSG(3, ("supported version: [%04x]", ssl->tls_version)); *out_len = 6; mbedtls_ssl_tls13_set_hs_sent_ext_mask( ssl, MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS); return 0; } /* Generate and export a single key share. For hybrid KEMs, this can * be called multiple times with the different components of the hybrid. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl, uint16_t named_group, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; *out_len = 0; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group) || mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) { ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange( ssl, named_group, buf, end, out_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange", ret); return ret; } } else #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */ if (0 /* Other kinds of KEMs */) { } else { ((void) ssl); ((void) named_group); ((void) buf); ((void) end); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; } return ret; } /* * ssl_tls13_write_key_share_ext * * Structure of key_share extension in ServerHello: * * struct { * NamedGroup group; * opaque key_exchange<1..2^16-1>; * } KeyShareEntry; * struct { * KeyShareEntry server_share; * } KeyShareServerHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; uint16_t group = ssl->handshake->offered_group_id; unsigned char *server_share = buf + 4; size_t key_exchange_length; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, adding key share extension")); MBEDTLS_SSL_DEBUG_MSG(2, ("server hello, write selected_group: %s (%04x)", mbedtls_ssl_named_group_to_str(group), group)); /* Check if we have space for header and length fields: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - group (2 bytes) * - key_exchange_length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 8); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, p, 0); MBEDTLS_PUT_UINT16_BE(group, server_share, 0); p += 8; /* When we introduce PQC-ECDHE hybrids, we'll want to call this * function multiple times. */ ret = ssl_tls13_generate_and_write_key_share( ssl, group, server_share + 4, end, &key_exchange_length); if (ret != 0) { return ret; } p += key_exchange_length; MBEDTLS_PUT_UINT16_BE(key_exchange_length, server_share + 2, 0); MBEDTLS_PUT_UINT16_BE(p - server_share, buf, 2); *out_len = p - buf; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_hrr_key_share_ext(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { uint16_t selected_group = ssl->handshake->hrr_selected_group; /* key_share Extension * * struct { * select (Handshake.msg_type) { * ... * case hello_retry_request: * NamedGroup selected_group; * ... * }; * } KeyShare; */ *out_len = 0; /* * For a pure PSK key exchange, there is no group to agree upon. The purpose * of the HRR is then to transmit a cookie to force the client to demonstrate * reachability at their apparent network address (primarily useful for DTLS). */ if (!mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { return 0; } /* We should only send the key_share extension if the client's initial * key share was not acceptable. */ if (ssl->handshake->offered_group_id != 0) { MBEDTLS_SSL_DEBUG_MSG(4, ("Skip key_share extension in HRR")); return 0; } if (selected_group == 0) { MBEDTLS_SSL_DEBUG_MSG(1, ("no matching named group found")); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* Check if we have enough space: * - extension_type (2 bytes) * - extension_data_length (2 bytes) * - selected_group (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(buf, end, 6); MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0); MBEDTLS_PUT_UINT16_BE(2, buf, 2); MBEDTLS_PUT_UINT16_BE(selected_group, buf, 4); MBEDTLS_SSL_DEBUG_MSG(3, ("HRR selected_group: %s (%x)", mbedtls_ssl_named_group_to_str(selected_group), selected_group)); *out_len = 6; mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE); return 0; } /* * Structure of ServerHello message: * * struct { * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 * Random random; * opaque legacy_session_id_echo<0..32>; * CipherSuite cipher_suite; * uint8 legacy_compression_method = 0; * Extension extensions<6..2^16-1>; * } ServerHello; */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_hello_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, int is_hrr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; unsigned char *p_extensions_len; size_t output_len; *out_len = 0; ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; /* ... * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 * ... * with ProtocolVersion defined as: * uint16 ProtocolVersion; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(0x0303, p, 0); p += 2; /* ... * Random random; * ... * with Random defined as: * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN); if (is_hrr) { memcpy(p, mbedtls_ssl_tls13_hello_retry_request_magic, MBEDTLS_SERVER_HELLO_RANDOM_LEN); } else { memcpy(p, &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], MBEDTLS_SERVER_HELLO_RANDOM_LEN); } MBEDTLS_SSL_DEBUG_BUF(3, "server hello, random bytes", p, MBEDTLS_SERVER_HELLO_RANDOM_LEN); p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; /* ... * opaque legacy_session_id_echo<0..32>; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1 + ssl->session_negotiate->id_len); *p++ = (unsigned char) ssl->session_negotiate->id_len; if (ssl->session_negotiate->id_len > 0) { memcpy(p, &ssl->session_negotiate->id[0], ssl->session_negotiate->id_len); p += ssl->session_negotiate->id_len; MBEDTLS_SSL_DEBUG_BUF(3, "session id", ssl->session_negotiate->id, ssl->session_negotiate->id_len); } /* ... * CipherSuite cipher_suite; * ... * with CipherSuite defined as: * uint8 CipherSuite[2]; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); MBEDTLS_PUT_UINT16_BE(ssl->session_negotiate->ciphersuite, p, 0); p += 2; MBEDTLS_SSL_DEBUG_MSG(3, ("server hello, chosen ciphersuite: %s ( id=%d )", mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite), ssl->session_negotiate->ciphersuite)); /* ... * uint8 legacy_compression_method = 0; * ... */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 1); *p++ = MBEDTLS_SSL_COMPRESS_NULL; /* ... * Extension extensions<6..2^16-1>; * ... * struct { * ExtensionType extension_type; (2 bytes) * opaque extension_data<0..2^16-1>; * } Extension; */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; if ((ret = ssl_tls13_write_server_hello_supported_versions_ext( ssl, p, end, &output_len)) != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_server_hello_supported_versions_ext", ret); return ret; } p += output_len; if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) { if (is_hrr) { ret = ssl_tls13_write_hrr_key_share_ext(ssl, p, end, &output_len); } else { ret = ssl_tls13_write_key_share_ext(ssl, p, end, &output_len); } if (ret != 0) { return ret; } p += output_len; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) if (!is_hrr && mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { ret = ssl_tls13_write_server_pre_shared_key_ext(ssl, p, end, &output_len); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_server_pre_shared_key_ext", ret); return ret; } p += output_len; } #endif MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); MBEDTLS_SSL_DEBUG_BUF(4, "server hello extensions", p_extensions_len, p - p_extensions_len); *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(3, "server hello", buf, *out_len); MBEDTLS_SSL_PRINT_EXTS( 3, is_hrr ? MBEDTLS_SSL_TLS1_3_HS_HELLO_RETRY_REQUEST : MBEDTLS_SSL_HS_SERVER_HELLO, ssl->handshake->sent_extensions); return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_finalize_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_compute_handshake_transform(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_compute_handshake_transform", ret); return ret; } return ret; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write server hello")); MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, buf + buf_len, &msg_len, 0)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_finalize_server_hello(ssl)); #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* The server sends a dummy change_cipher_spec record immediately * after its first handshake message. This may either be after * a ServerHello or a HelloRetryRequest. */ mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write server hello")); return ret; } /* * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl->handshake->hello_retry_request_flag) { MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } /* * Create stateless transcript hash for HRR */ MBEDTLS_SSL_DEBUG_MSG(4, ("Reset transcript for HRR")); ret = mbedtls_ssl_reset_transcript_for_hrr(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_reset_transcript_for_hrr", ret); return ret; } mbedtls_ssl_session_reset_msg_layer(ssl, 0); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello retry request")); MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_hello_retry_request(ssl)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf, buf + buf_len, &msg_len, 1)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len, msg_len)); ssl->handshake->hello_retry_request_flag = 1; #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) /* The server sends a dummy change_cipher_spec record immediately * after its first handshake message. This may either be after * a ServerHello or a HelloRetryRequest. */ mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST); #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello retry request")); return ret; } /* * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS */ /* * struct { * Extension extensions<0..2 ^ 16 - 1>; * } EncryptedExtensions; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t extensions_len = 0; unsigned char *p_extensions_len; size_t output_len; *out_len = 0; MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; ((void) ssl); ((void) ret); ((void) output_len); #if defined(MBEDTLS_SSL_ALPN) ret = mbedtls_ssl_write_alpn_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->handshake->early_data_accepted) { ret = mbedtls_ssl_tls13_write_early_data_ext( ssl, 0, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) { ret = mbedtls_ssl_tls13_write_record_size_limit_ext( ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; } #endif extensions_len = (p - p_extensions_len) - 2; MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0); *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(4, "encrypted extensions", buf, *out_len); MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, ssl->handshake->sent_extensions); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *buf; size_t buf_len, msg_len; mbedtls_ssl_set_outbound_transform(ssl, ssl->handshake->transform_handshake); MBEDTLS_SSL_DEBUG_MSG( 3, ("switching to handshake transform for outbound data")); MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions")); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST); } #else mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); #endif cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write encrypted extensions")); return ret; } #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) #define SSL_CERTIFICATE_REQUEST_SEND_REQUEST 0 #define SSL_CERTIFICATE_REQUEST_SKIP 1 /* Coordination: * Check whether a CertificateRequest message should be written. * Returns a negative code on failure, or * - SSL_CERTIFICATE_REQUEST_SEND_REQUEST * - SSL_CERTIFICATE_REQUEST_SKIP * indicating if the writing of the CertificateRequest * should be skipped or not. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_certificate_request_coordinate(mbedtls_ssl_context *ssl) { int authmode; #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) { authmode = ssl->handshake->sni_authmode; } else #endif authmode = ssl->conf->authmode; if (authmode == MBEDTLS_SSL_VERIFY_NONE) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; return SSL_CERTIFICATE_REQUEST_SKIP; } ssl->handshake->certificate_request_sent = 1; return SSL_CERTIFICATE_REQUEST_SEND_REQUEST; } /* * struct { * opaque certificate_request_context<0..2^8-1>; * Extension extensions<2..2^16-1>; * } CertificateRequest; * */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_request_body(mbedtls_ssl_context *ssl, unsigned char *buf, const unsigned char *end, size_t *out_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; size_t output_len = 0; unsigned char *p_extensions_len; *out_len = 0; /* Check if we have enough space: * - certificate_request_context (1 byte) * - extensions length (2 bytes) */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 3); /* * Write certificate_request_context */ /* * We use a zero length context for the normal handshake * messages. For post-authentication handshake messages * this request context would be set to a non-zero value. */ *p++ = 0x0; /* * Write extensions */ /* The extensions must contain the signature_algorithms. */ p_extensions_len = p; p += 2; ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len); if (ret != 0) { return ret; } p += output_len; MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); *out_len = p - buf; MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, ssl->handshake->sent_extensions); return 0; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate request")); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_certificate_request_coordinate(ssl)); if (ret == SSL_CERTIFICATE_REQUEST_SEND_REQUEST) { unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body( ssl, buf, buf + buf_len, &msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len)); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) { MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate request")); ret = 0; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_CERTIFICATE); cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate request")); return ret; } /* * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_certificate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; #if defined(MBEDTLS_X509_CRT_PARSE_C) if ((ssl_tls13_pick_key_cert(ssl) != 0) || mbedtls_ssl_own_cert(ssl) == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("No certificate available.")); MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ ret = mbedtls_ssl_tls13_write_certificate(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY); return 0; } /* * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl) { int ret = mbedtls_ssl_tls13_write_certificate_verify(ssl); if (ret != 0) { return ret; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_FINISHED); return 0; } #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * RFC 8446 section A.2 * * | Send ServerHello * | K_send = handshake * | Send EncryptedExtensions * | [Send CertificateRequest] * Can send | [Send Certificate + CertificateVerify] * app data | Send Finished * after --> | K_send = application * here +--------+--------+ * No 0-RTT | | 0-RTT * | | * K_recv = handshake | | K_recv = early data * [Skip decrypt errors] | +------> WAIT_EOED -+ * | | Recv | | Recv EndOfEarlyData * | | early data | | K_recv = handshake * | +------------+ | * | | * +> WAIT_FLIGHT2 <--------+ * | * +--------+--------+ * No auth | | Client auth * | | * | v * | WAIT_CERT * | Recv | | Recv Certificate * | empty | v * | Certificate | WAIT_CV * | | | Recv * | v | CertificateVerify * +-> WAIT_FINISHED <---+ * | Recv Finished * * * The following function handles the state changes after WAIT_FLIGHT2 in the * above diagram. We are not going to receive early data related messages * anymore, prepare to receive the first handshake message of the client * second flight. */ static void ssl_tls13_prepare_for_handshake_second_flight( mbedtls_ssl_context *ssl) { if (ssl->handshake->certificate_request_sent) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate")); MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED); } } /* * Handler for MBEDTLS_SSL_SERVER_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_write_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_application_transform(ssl); if (ret != 0) { MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE); return ret; } #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->handshake->early_data_accepted) { /* See RFC 8446 section A.2 for more information */ MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to early keys for inbound traffic. " "( K_recv = early data )")); mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_earlydata); mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA); return 0; } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to handshake keys for inbound traffic " "( K_recv = handshake )")); mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake); ssl_tls13_prepare_for_handshake_second_flight(ssl); return 0; } #if defined(MBEDTLS_SSL_EARLY_DATA) /* * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA */ #define SSL_GOT_END_OF_EARLY_DATA 0 #define SSL_GOT_EARLY_DATA 1 /* Coordination: * Deals with the ambiguity of not knowing if the next message is an * EndOfEarlyData message or an application message containing early data. * Returns a negative code on failure, or * - SSL_GOT_END_OF_EARLY_DATA * - SSL_GOT_EARLY_DATA * indicating which message is received. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_end_of_early_data_coordinate(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) { MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret); return ret; } ssl->keep_current_message = 1; if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && ssl->in_msg[0] == MBEDTLS_SSL_HS_END_OF_EARLY_DATA) { MBEDTLS_SSL_DEBUG_MSG(3, ("Received an end_of_early_data message.")); return SSL_GOT_END_OF_EARLY_DATA; } if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) { if (ssl->in_offt == NULL) { MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data")); /* Set the reading pointer */ ssl->in_offt = ssl->in_msg; ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen); if (ret != 0) { return ret; } } return SSL_GOT_EARLY_DATA; } MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE); return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; } MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_parse_end_of_early_data(mbedtls_ssl_context *ssl, const unsigned char *buf, const unsigned char *end) { /* RFC 8446 section 4.5 * * struct {} EndOfEarlyData; */ if (buf != end) { MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, MBEDTLS_ERR_SSL_DECODE_ERROR); return MBEDTLS_ERR_SSL_DECODE_ERROR; } return 0; } /* * RFC 8446 section A.2 * * | Send ServerHello * | K_send = handshake * | Send EncryptedExtensions * | [Send CertificateRequest] * Can send | [Send Certificate + CertificateVerify] * app data | Send Finished * after --> | K_send = application * here +--------+--------+ * No 0-RTT | | 0-RTT * | | * K_recv = handshake | | K_recv = early data * [Skip decrypt errors] | +------> WAIT_EOED -+ * | | Recv | | Recv EndOfEarlyData * | | early data | | K_recv = handshake * | +------------+ | * | | * +> WAIT_FLIGHT2 <--------+ * | * +--------+--------+ * No auth | | Client auth * | | * | v * | WAIT_CERT * | Recv | | Recv Certificate * | empty | v * | Certificate | WAIT_CV * | | | Recv * | v | CertificateVerify * +-> WAIT_FINISHED <---+ * | Recv Finished * * The function handles actions and state changes from 0-RTT to WAIT_FLIGHT2 in * the above diagram. */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_process_end_of_early_data")); MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_end_of_early_data_coordinate(ssl)); if (ret == SSL_GOT_END_OF_EARLY_DATA) { unsigned char *buf; size_t buf_len; MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data( ssl, buf, buf + buf_len)); MBEDTLS_SSL_DEBUG_MSG( 1, ("Switch to handshake keys for inbound traffic" "( K_recv = handshake )")); mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA, buf, buf_len)); ssl_tls13_prepare_for_handshake_second_flight(ssl); } else if (ret == SSL_GOT_EARLY_DATA) { ret = MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA; goto cleanup; } else { MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen")); ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; goto cleanup; } cleanup: MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_process_end_of_early_data")); return ret; } #endif /* MBEDTLS_SSL_EARLY_DATA */ /* * Handler for MBEDTLS_SSL_CLIENT_FINISHED */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_ssl_tls13_process_finished_message(ssl); if (ret != 0) { return ret; } ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_compute_resumption_master_secret", ret); } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP); return 0; } /* * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl) { MBEDTLS_SSL_DEBUG_MSG(2, ("handshake: done")); mbedtls_ssl_tls13_handshake_wrapup(ssl); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) /* TODO: Remove the check of SOME_PSK_ENABLED since SESSION_TICKETS requires * SOME_PSK_ENABLED to be enabled. Here is just to make CI happy. It is * expected to be resolved with issue#6395. */ /* Sent NewSessionTicket message only when client supports PSK */ if (mbedtls_ssl_tls13_is_some_psk_supported(ssl)) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); } else #endif { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); } return 0; } /* * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ #define SSL_NEW_SESSION_TICKET_SKIP 0 #define SSL_NEW_SESSION_TICKET_WRITE 1 MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ssl) { /* Check whether the use of session tickets is enabled */ if (ssl->conf->f_ticket_write == NULL) { MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," " callback is not set")); return SSL_NEW_SESSION_TICKET_SKIP; } if (ssl->conf->new_session_tickets_count == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: disabled," " configured count is zero")); return SSL_NEW_SESSION_TICKET_SKIP; } if (ssl->handshake->new_session_tickets_count == 0) { MBEDTLS_SSL_DEBUG_MSG(2, ("NewSessionTicket: all tickets have " "been sent.")); return SSL_NEW_SESSION_TICKET_SKIP; } return SSL_NEW_SESSION_TICKET_WRITE; } #if defined(MBEDTLS_SSL_SESSION_TICKETS) MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl, unsigned char *ticket_nonce, size_t ticket_nonce_size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_ssl_session *session = ssl->session; mbedtls_ssl_ciphersuite_t *ciphersuite_info; psa_algorithm_t psa_hash_alg; int hash_length; MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg")); /* Set ticket_flags depends on the advertised psk key exchange mode */ mbedtls_ssl_tls13_session_clear_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK); #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED) mbedtls_ssl_tls13_session_set_ticket_flags( session, ssl->handshake->tls13_kex_modes); #endif #if defined(MBEDTLS_SSL_EARLY_DATA) if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED && ssl->conf->max_early_data_size > 0) { mbedtls_ssl_tls13_session_set_ticket_flags( session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA); session->max_early_data_size = ssl->conf->max_early_data_size; } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags); #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) if (session->ticket_alpn == NULL) { ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen); if (ret != 0) { return ret; } } #endif /* Generate ticket_age_add */ if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, (unsigned char *) &session->ticket_age_add, sizeof(session->ticket_age_add)) != 0)) { MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_age_add", ret); return ret; } MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", (unsigned int) session->ticket_age_add)); /* Generate ticket_nonce */ ret = ssl->conf->f_rng(ssl->conf->p_rng, ticket_nonce, ticket_nonce_size); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "generate_ticket_nonce", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "ticket_nonce:", ticket_nonce, ticket_nonce_size); ciphersuite_info = (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info; psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac); hash_length = PSA_HASH_LENGTH(psa_hash_alg); if (hash_length == -1 || (size_t) hash_length > sizeof(session->resumption_key)) { return MBEDTLS_ERR_SSL_INTERNAL_ERROR; } /* In this code the psk key length equals the length of the hash */ session->resumption_key_len = hash_length; session->ciphersuite = ciphersuite_info->id; /* Compute resumption key * * HKDF-Expand-Label( resumption_master_secret, * "resumption", ticket_nonce, Hash.length ) */ ret = mbedtls_ssl_tls13_hkdf_expand_label( psa_hash_alg, session->app_secrets.resumption_master_secret, hash_length, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(resumption), ticket_nonce, ticket_nonce_size, session->resumption_key, hash_length); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(2, "Creating the ticket-resumed PSK failed", ret); return ret; } MBEDTLS_SSL_DEBUG_BUF(3, "Ticket-resumed PSK", session->resumption_key, session->resumption_key_len); MBEDTLS_SSL_DEBUG_BUF(3, "resumption_master_secret", session->app_secrets.resumption_master_secret, hash_length); return 0; } /* This function creates a NewSessionTicket message in the following format: * * struct { * uint32 ticket_lifetime; * uint32 ticket_age_add; * opaque ticket_nonce<0..255>; * opaque ticket<1..2^16-1>; * Extension extensions<0..2^16-2>; * } NewSessionTicket; * * The ticket inside the NewSessionTicket message is an encrypted container * carrying the necessary information so that the server is later able to * re-start the communication. * * The following fields are placed inside the ticket by the * f_ticket_write() function: * * - creation time (ticket_creation_time) * - flags (ticket_flags) * - age add (ticket_age_add) * - key (resumption_key) * - key length (resumption_key_len) * - ciphersuite (ciphersuite) * - max_early_data_size (max_early_data_size) */ MBEDTLS_CHECK_RETURN_CRITICAL static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl, unsigned char *buf, unsigned char *end, size_t *out_len, unsigned char *ticket_nonce, size_t ticket_nonce_size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p = buf; mbedtls_ssl_session *session = ssl->session; size_t ticket_len; uint32_t ticket_lifetime; unsigned char *p_extensions_len; *out_len = 0; MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg")); /* * ticket_lifetime 4 bytes * ticket_age_add 4 bytes * ticket_nonce 1 + ticket_nonce_size bytes * ticket >=2 bytes */ MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2); /* Generate ticket and ticket_lifetime */ #if defined(MBEDTLS_HAVE_TIME) session->ticket_creation_time = mbedtls_ms_time(); #endif ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket, session, p + 9 + ticket_nonce_size + 2, end, &ticket_len, &ticket_lifetime); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret); return ret; } /* RFC 8446 section 4.6.1 * * ticket_lifetime: Indicates the lifetime in seconds as a 32-bit * unsigned integer in network byte order from the time of ticket * issuance. Servers MUST NOT use any value greater than * 604800 seconds (7 days) ... */ if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) { MBEDTLS_SSL_DEBUG_MSG( 1, ("Ticket lifetime (%u) is greater than 7 days.", (unsigned int) ticket_lifetime)); return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u", (unsigned int) ticket_lifetime)); /* Write ticket_age_add */ MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 4); MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_age_add: %u", (unsigned int) session->ticket_age_add)); /* Write ticket_nonce */ p[8] = (unsigned char) ticket_nonce_size; if (ticket_nonce_size > 0) { memcpy(p + 9, ticket_nonce, ticket_nonce_size); } p += 9 + ticket_nonce_size; /* Write ticket */ MBEDTLS_PUT_UINT16_BE(ticket_len, p, 0); p += 2; MBEDTLS_SSL_DEBUG_BUF(4, "ticket", p, ticket_len); p += ticket_len; /* Ticket Extensions * * Extension extensions<0..2^16-2>; */ ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE; MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2); p_extensions_len = p; p += 2; #if defined(MBEDTLS_SSL_EARLY_DATA) if (mbedtls_ssl_tls13_session_ticket_allow_early_data(session)) { size_t output_len; if ((ret = mbedtls_ssl_tls13_write_early_data_ext( ssl, 1, p, end, &output_len)) != 0) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_write_early_data_ext", ret); return ret; } p += output_len; } else { MBEDTLS_SSL_DEBUG_MSG( 4, ("early_data not allowed, " "skip early_data extension in NewSessionTicket")); } #endif /* MBEDTLS_SSL_EARLY_DATA */ MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0); *out_len = p - buf; MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len); MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket")); MBEDTLS_SSL_PRINT_EXTS( 3, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, ssl->handshake->sent_extensions); return 0; } /* * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET */ static int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_write_new_session_ticket_coordinate(ssl)); if (ret == SSL_NEW_SESSION_TICKET_WRITE) { unsigned char ticket_nonce[MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH]; unsigned char *buf; size_t buf_len, msg_len; MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket( ssl, ticket_nonce, sizeof(ticket_nonce))); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg( ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET, &buf, &buf_len)); MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body( ssl, buf, buf + buf_len, &msg_len, ticket_nonce, sizeof(ticket_nonce))); MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg( ssl, buf_len, msg_len)); /* Limit session tickets count to one when resumption connection. * * See document of mbedtls_ssl_conf_new_session_tickets. */ if (ssl->handshake->resume == 1) { ssl->handshake->new_session_tickets_count = 0; } else { ssl->handshake->new_session_tickets_count--; } mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH); } else { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); } cleanup: return ret; } #endif /* MBEDTLS_SSL_SESSION_TICKETS */ /* * TLS 1.3 State Machine -- server side */ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL) { return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; } MBEDTLS_SSL_DEBUG_MSG(2, ("tls13 server state: %s(%d)", mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state), ssl->state)); switch (ssl->state) { /* start state */ case MBEDTLS_SSL_HELLO_REQUEST: mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); ret = 0; break; case MBEDTLS_SSL_CLIENT_HELLO: ret = ssl_tls13_process_client_hello(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_process_client_hello", ret); } break; case MBEDTLS_SSL_HELLO_RETRY_REQUEST: ret = ssl_tls13_write_hello_retry_request(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_hello_retry_request", ret); return ret; } break; case MBEDTLS_SSL_SERVER_HELLO: ret = ssl_tls13_write_server_hello(ssl); break; case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: ret = ssl_tls13_write_encrypted_extensions(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_encrypted_extensions", ret); return ret; } break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CERTIFICATE_REQUEST: ret = ssl_tls13_write_certificate_request(ssl); break; case MBEDTLS_SSL_SERVER_CERTIFICATE: ret = ssl_tls13_write_server_certificate(ssl); break; case MBEDTLS_SSL_CERTIFICATE_VERIFY: ret = ssl_tls13_write_certificate_verify(ssl); break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ /* * Injection of dummy-CCS's for middlebox compatibility */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO); } break; case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO: ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl); if (ret != 0) { break; } mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS); break; #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ case MBEDTLS_SSL_SERVER_FINISHED: ret = ssl_tls13_write_server_finished(ssl); break; #if defined(MBEDTLS_SSL_EARLY_DATA) case MBEDTLS_SSL_END_OF_EARLY_DATA: ret = ssl_tls13_process_end_of_early_data(ssl); break; #endif /* MBEDTLS_SSL_EARLY_DATA */ case MBEDTLS_SSL_CLIENT_FINISHED: ret = ssl_tls13_process_client_finished(ssl); break; case MBEDTLS_SSL_HANDSHAKE_WRAPUP: ret = ssl_tls13_handshake_wrapup(ssl); break; #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) case MBEDTLS_SSL_CLIENT_CERTIFICATE: ret = mbedtls_ssl_tls13_process_certificate(ssl); if (ret == 0) { if (ssl->session_negotiate->peer_cert != NULL) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY); } else { MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify")); mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED); } } break; case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY: ret = mbedtls_ssl_tls13_process_certificate_verify(ssl); if (ret == 0) { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED); } break; #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET: ret = ssl_tls13_write_new_session_ticket(ssl); if (ret != 0) { MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls13_write_new_session_ticket ", ret); } break; case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH: /* This state is necessary to do the flush of the New Session * Ticket message written in MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET * as part of ssl_prepare_handshake_step. */ ret = 0; if (ssl->handshake->new_session_tickets_count == 0) { mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER); } else { mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET); } break; #endif /* MBEDTLS_SSL_SESSION_TICKETS */ default: MBEDTLS_SSL_DEBUG_MSG(1, ("invalid state %d", ssl->state)); return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; } return ret; } #endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_TLS1_3 */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/threading.c000066400000000000000000000143531464416617300234530ustar00rootroot00000000000000/* * Threading abstraction layer * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * Ensure gmtime_r is available even with -std=c99; must be defined before * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms. */ #if !defined(_POSIX_C_SOURCE) #define _POSIX_C_SOURCE 200112L #endif #include "common.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) #if !defined(_WIN32) && (defined(unix) || \ defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ defined(__MACH__))) #include #endif /* !_WIN32 && (unix || __unix || __unix__ || * (__APPLE__ && __MACH__)) */ #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L)) /* * This is a convenience shorthand macro to avoid checking the long * preprocessor conditions above. Ideally, we could expose this macro in * platform_util.h and simply use it in platform_util.c, threading.c and * threading.h. However, this macro is not part of the Mbed TLS public API, so * we keep it private by only defining it in this file */ #if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) #define THREADING_USE_GMTIME #endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_THREADING_PTHREAD) static void threading_mutex_init_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return; } /* One problem here is that calling lock on a pthread mutex without first * having initialised it is undefined behaviour. Obviously we cannot check * this here in a thread safe manner without a significant performance * hit, so state transitions are checked in tests only via the state * variable. Please make sure any new mutex that gets added is exercised in * tests; see tests/src/threading_helpers.c for more details. */ (void) pthread_mutex_init(&mutex->mutex, NULL); } static void threading_mutex_free_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return; } (void) pthread_mutex_destroy(&mutex->mutex); } static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } if (pthread_mutex_lock(&mutex->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } return 0; } static int threading_mutex_unlock_pthread(mbedtls_threading_mutex_t *mutex) { if (mutex == NULL) { return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } if (pthread_mutex_unlock(&mutex->mutex) != 0) { return MBEDTLS_ERR_THREADING_MUTEX_ERROR; } return 0; } void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_init_pthread; void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_free_pthread; int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_lock_pthread; int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_unlock_pthread; /* * With pthreads we can statically initialize mutexes */ #define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } #endif /* MBEDTLS_THREADING_PTHREAD */ #if defined(MBEDTLS_THREADING_ALT) static int threading_mutex_fail(mbedtls_threading_mutex_t *mutex) { ((void) mutex); return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA; } static void threading_mutex_dummy(mbedtls_threading_mutex_t *mutex) { ((void) mutex); return; } void (*mbedtls_mutex_init)(mbedtls_threading_mutex_t *) = threading_mutex_dummy; void (*mbedtls_mutex_free)(mbedtls_threading_mutex_t *) = threading_mutex_dummy; int (*mbedtls_mutex_lock)(mbedtls_threading_mutex_t *) = threading_mutex_fail; int (*mbedtls_mutex_unlock)(mbedtls_threading_mutex_t *) = threading_mutex_fail; /* * Set functions pointers and initialize global mutexes */ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *), void (*mutex_free)(mbedtls_threading_mutex_t *), int (*mutex_lock)(mbedtls_threading_mutex_t *), int (*mutex_unlock)(mbedtls_threading_mutex_t *)) { mbedtls_mutex_init = mutex_init; mbedtls_mutex_free = mutex_free; mbedtls_mutex_lock = mutex_lock; mbedtls_mutex_unlock = mutex_unlock; #if defined(MBEDTLS_FS_IO) mbedtls_mutex_init(&mbedtls_threading_readdir_mutex); #endif #if defined(THREADING_USE_GMTIME) mbedtls_mutex_init(&mbedtls_threading_gmtime_mutex); #endif #if defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex); mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex); mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex); #endif } /* * Free global mutexes */ void mbedtls_threading_free_alt(void) { #if defined(MBEDTLS_FS_IO) mbedtls_mutex_free(&mbedtls_threading_readdir_mutex); #endif #if defined(THREADING_USE_GMTIME) mbedtls_mutex_free(&mbedtls_threading_gmtime_mutex); #endif #if defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex); mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex); mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex); #endif } #endif /* MBEDTLS_THREADING_ALT */ /* * Define global mutexes */ #ifndef MUTEX_INIT #define MUTEX_INIT #endif #if defined(MBEDTLS_FS_IO) mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; #endif #if defined(THREADING_USE_GMTIME) mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; #endif #if defined(MBEDTLS_PSA_CRYPTO_C) mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT; mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT; #endif #endif /* MBEDTLS_THREADING_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/timing.c000066400000000000000000000076041464416617300227760ustar00rootroot00000000000000/* * Portable interface to the CPU cycle counter * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_TIMING_C) #include "mbedtls/timing.h" #if !defined(MBEDTLS_TIMING_ALT) #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__HAIKU__) && !defined(__midipix__) #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h" #endif #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #include struct _hr_time { LARGE_INTEGER start; }; #else #include #include #include /* time.h should be included independently of MBEDTLS_HAVE_TIME. If the * platform matches the ifdefs above, it will be used. */ #include #include struct _hr_time { struct timeval start; }; #endif /* _WIN32 && !EFIX64 && !EFI32 */ /** * \brief Return the elapsed time in milliseconds * * \warning May change without notice * * \param val points to a timer structure * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. * * \return Elapsed time since the previous reset in ms. When * restarting, this is always 0. * * \note To initialize a timer, call this function with reset=1. * * Determining the elapsed time and resetting the timer is not * atomic on all platforms, so after the sequence * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = * get_timer(0) }` the value time1+time2 is only approximately * the delay since the first reset. */ #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { struct _hr_time *t = (struct _hr_time *) val; if (reset) { QueryPerformanceCounter(&t->start); return 0; } else { unsigned long delta; LARGE_INTEGER now, hfreq; QueryPerformanceCounter(&now); QueryPerformanceFrequency(&hfreq); delta = (unsigned long) ((now.QuadPart - t->start.QuadPart) * 1000ul / hfreq.QuadPart); return delta; } } #else /* _WIN32 && !EFIX64 && !EFI32 */ unsigned long mbedtls_timing_get_timer(struct mbedtls_timing_hr_time *val, int reset) { struct _hr_time *t = (struct _hr_time *) val; if (reset) { gettimeofday(&t->start, NULL); return 0; } else { unsigned long delta; struct timeval now; gettimeofday(&now, NULL); delta = (now.tv_sec - t->start.tv_sec) * 1000ul + (now.tv_usec - t->start.tv_usec) / 1000; return delta; } } #endif /* _WIN32 && !EFIX64 && !EFI32 */ /* * Set delays to watch */ void mbedtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) { mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; ctx->int_ms = int_ms; ctx->fin_ms = fin_ms; if (fin_ms != 0) { (void) mbedtls_timing_get_timer(&ctx->timer, 1); } } /* * Get number of delays expired */ int mbedtls_timing_get_delay(void *data) { mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; unsigned long elapsed_ms; if (ctx->fin_ms == 0) { return -1; } elapsed_ms = mbedtls_timing_get_timer(&ctx->timer, 0); if (elapsed_ms >= ctx->fin_ms) { return 2; } if (elapsed_ms >= ctx->int_ms) { return 1; } return 0; } /* * Get the final delay. */ uint32_t mbedtls_timing_get_final_delay( const mbedtls_timing_delay_context *data) { return data->fin_ms; } #endif /* !MBEDTLS_TIMING_ALT */ #endif /* MBEDTLS_TIMING_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/version.c000066400000000000000000000012061464416617300231640ustar00rootroot00000000000000/* * Version information * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_VERSION_C) #include "mbedtls/version.h" #include unsigned int mbedtls_version_get_number(void) { return MBEDTLS_VERSION_NUMBER; } void mbedtls_version_get_string(char *string) { memcpy(string, MBEDTLS_VERSION_STRING, sizeof(MBEDTLS_VERSION_STRING)); } void mbedtls_version_get_string_full(char *string) { memcpy(string, MBEDTLS_VERSION_STRING_FULL, sizeof(MBEDTLS_VERSION_STRING_FULL)); } #endif /* MBEDTLS_VERSION_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/version_features.c000066400000000000000000000765411464416617300251000ustar00rootroot00000000000000/* * Version feature information * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_VERSION_C) #include "mbedtls/version.h" #include static const char * const features[] = { #if defined(MBEDTLS_VERSION_FEATURES) #if defined(MBEDTLS_HAVE_ASM) "HAVE_ASM", //no-check-names #endif /* MBEDTLS_HAVE_ASM */ #if defined(MBEDTLS_NO_UDBL_DIVISION) "NO_UDBL_DIVISION", //no-check-names #endif /* MBEDTLS_NO_UDBL_DIVISION */ #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) "NO_64BIT_MULTIPLICATION", //no-check-names #endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */ #if defined(MBEDTLS_HAVE_SSE2) "HAVE_SSE2", //no-check-names #endif /* MBEDTLS_HAVE_SSE2 */ #if defined(MBEDTLS_HAVE_TIME) "HAVE_TIME", //no-check-names #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_HAVE_TIME_DATE) "HAVE_TIME_DATE", //no-check-names #endif /* MBEDTLS_HAVE_TIME_DATE */ #if defined(MBEDTLS_PLATFORM_MEMORY) "PLATFORM_MEMORY", //no-check-names #endif /* MBEDTLS_PLATFORM_MEMORY */ #if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) "PLATFORM_NO_STD_FUNCTIONS", //no-check-names #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ #if defined(MBEDTLS_PLATFORM_SETBUF_ALT) "PLATFORM_SETBUF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */ #if defined(MBEDTLS_PLATFORM_EXIT_ALT) "PLATFORM_EXIT_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ #if defined(MBEDTLS_PLATFORM_TIME_ALT) "PLATFORM_TIME_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_TIME_ALT */ #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) "PLATFORM_FPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) "PLATFORM_PRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) "PLATFORM_SNPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) "PLATFORM_VSNPRINTF_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) "PLATFORM_NV_SEED_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ #if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) "PLATFORM_SETUP_TEARDOWN_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ #if defined(MBEDTLS_PLATFORM_MS_TIME_ALT) "PLATFORM_MS_TIME_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_MS_TIME_ALT */ #if defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) "PLATFORM_GMTIME_R_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */ #if defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) "PLATFORM_ZEROIZE_ALT", //no-check-names #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ #if defined(MBEDTLS_DEPRECATED_WARNING) "DEPRECATED_WARNING", //no-check-names #endif /* MBEDTLS_DEPRECATED_WARNING */ #if defined(MBEDTLS_DEPRECATED_REMOVED) "DEPRECATED_REMOVED", //no-check-names #endif /* MBEDTLS_DEPRECATED_REMOVED */ #if defined(MBEDTLS_TIMING_ALT) "TIMING_ALT", //no-check-names #endif /* MBEDTLS_TIMING_ALT */ #if defined(MBEDTLS_AES_ALT) "AES_ALT", //no-check-names #endif /* MBEDTLS_AES_ALT */ #if defined(MBEDTLS_ARIA_ALT) "ARIA_ALT", //no-check-names #endif /* MBEDTLS_ARIA_ALT */ #if defined(MBEDTLS_CAMELLIA_ALT) "CAMELLIA_ALT", //no-check-names #endif /* MBEDTLS_CAMELLIA_ALT */ #if defined(MBEDTLS_CCM_ALT) "CCM_ALT", //no-check-names #endif /* MBEDTLS_CCM_ALT */ #if defined(MBEDTLS_CHACHA20_ALT) "CHACHA20_ALT", //no-check-names #endif /* MBEDTLS_CHACHA20_ALT */ #if defined(MBEDTLS_CHACHAPOLY_ALT) "CHACHAPOLY_ALT", //no-check-names #endif /* MBEDTLS_CHACHAPOLY_ALT */ #if defined(MBEDTLS_CMAC_ALT) "CMAC_ALT", //no-check-names #endif /* MBEDTLS_CMAC_ALT */ #if defined(MBEDTLS_DES_ALT) "DES_ALT", //no-check-names #endif /* MBEDTLS_DES_ALT */ #if defined(MBEDTLS_DHM_ALT) "DHM_ALT", //no-check-names #endif /* MBEDTLS_DHM_ALT */ #if defined(MBEDTLS_ECJPAKE_ALT) "ECJPAKE_ALT", //no-check-names #endif /* MBEDTLS_ECJPAKE_ALT */ #if defined(MBEDTLS_GCM_ALT) "GCM_ALT", //no-check-names #endif /* MBEDTLS_GCM_ALT */ #if defined(MBEDTLS_NIST_KW_ALT) "NIST_KW_ALT", //no-check-names #endif /* MBEDTLS_NIST_KW_ALT */ #if defined(MBEDTLS_MD5_ALT) "MD5_ALT", //no-check-names #endif /* MBEDTLS_MD5_ALT */ #if defined(MBEDTLS_POLY1305_ALT) "POLY1305_ALT", //no-check-names #endif /* MBEDTLS_POLY1305_ALT */ #if defined(MBEDTLS_RIPEMD160_ALT) "RIPEMD160_ALT", //no-check-names #endif /* MBEDTLS_RIPEMD160_ALT */ #if defined(MBEDTLS_RSA_ALT) "RSA_ALT", //no-check-names #endif /* MBEDTLS_RSA_ALT */ #if defined(MBEDTLS_SHA1_ALT) "SHA1_ALT", //no-check-names #endif /* MBEDTLS_SHA1_ALT */ #if defined(MBEDTLS_SHA256_ALT) "SHA256_ALT", //no-check-names #endif /* MBEDTLS_SHA256_ALT */ #if defined(MBEDTLS_SHA512_ALT) "SHA512_ALT", //no-check-names #endif /* MBEDTLS_SHA512_ALT */ #if defined(MBEDTLS_ECP_ALT) "ECP_ALT", //no-check-names #endif /* MBEDTLS_ECP_ALT */ #if defined(MBEDTLS_MD5_PROCESS_ALT) "MD5_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_MD5_PROCESS_ALT */ #if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) "RIPEMD160_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ #if defined(MBEDTLS_SHA1_PROCESS_ALT) "SHA1_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA1_PROCESS_ALT */ #if defined(MBEDTLS_SHA256_PROCESS_ALT) "SHA256_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA256_PROCESS_ALT */ #if defined(MBEDTLS_SHA512_PROCESS_ALT) "SHA512_PROCESS_ALT", //no-check-names #endif /* MBEDTLS_SHA512_PROCESS_ALT */ #if defined(MBEDTLS_DES_SETKEY_ALT) "DES_SETKEY_ALT", //no-check-names #endif /* MBEDTLS_DES_SETKEY_ALT */ #if defined(MBEDTLS_DES_CRYPT_ECB_ALT) "DES_CRYPT_ECB_ALT", //no-check-names #endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ #if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) "DES3_CRYPT_ECB_ALT", //no-check-names #endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ #if defined(MBEDTLS_AES_SETKEY_ENC_ALT) "AES_SETKEY_ENC_ALT", //no-check-names #endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ #if defined(MBEDTLS_AES_SETKEY_DEC_ALT) "AES_SETKEY_DEC_ALT", //no-check-names #endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ #if defined(MBEDTLS_AES_ENCRYPT_ALT) "AES_ENCRYPT_ALT", //no-check-names #endif /* MBEDTLS_AES_ENCRYPT_ALT */ #if defined(MBEDTLS_AES_DECRYPT_ALT) "AES_DECRYPT_ALT", //no-check-names #endif /* MBEDTLS_AES_DECRYPT_ALT */ #if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) "ECDH_GEN_PUBLIC_ALT", //no-check-names #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */ #if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) "ECDH_COMPUTE_SHARED_ALT", //no-check-names #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ #if defined(MBEDTLS_ECDSA_VERIFY_ALT) "ECDSA_VERIFY_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ #if defined(MBEDTLS_ECDSA_SIGN_ALT) "ECDSA_SIGN_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_SIGN_ALT */ #if defined(MBEDTLS_ECDSA_GENKEY_ALT) "ECDSA_GENKEY_ALT", //no-check-names #endif /* MBEDTLS_ECDSA_GENKEY_ALT */ #if defined(MBEDTLS_ECP_INTERNAL_ALT) "ECP_INTERNAL_ALT", //no-check-names #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_NO_FALLBACK) "ECP_NO_FALLBACK", //no-check-names #endif /* MBEDTLS_ECP_NO_FALLBACK */ #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) "ECP_RANDOMIZE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) "ECP_ADD_MIXED_ALT", //no-check-names #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) "ECP_DOUBLE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) "ECP_NORMALIZE_JAC_MANY_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) "ECP_NORMALIZE_JAC_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) "ECP_DOUBLE_ADD_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) "ECP_RANDOMIZE_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) "ECP_NORMALIZE_MXZ_ALT", //no-check-names #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) "ENTROPY_HARDWARE_ALT", //no-check-names #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #if defined(MBEDTLS_AES_ROM_TABLES) "AES_ROM_TABLES", //no-check-names #endif /* MBEDTLS_AES_ROM_TABLES */ #if defined(MBEDTLS_AES_FEWER_TABLES) "AES_FEWER_TABLES", //no-check-names #endif /* MBEDTLS_AES_FEWER_TABLES */ #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) "AES_ONLY_128_BIT_KEY_LENGTH", //no-check-names #endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ #if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) "AES_USE_HARDWARE_ONLY", //no-check-names #endif /* MBEDTLS_AES_USE_HARDWARE_ONLY */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) "CAMELLIA_SMALL_MEMORY", //no-check-names #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ #if defined(MBEDTLS_CHECK_RETURN_WARNING) "CHECK_RETURN_WARNING", //no-check-names #endif /* MBEDTLS_CHECK_RETURN_WARNING */ #if defined(MBEDTLS_CIPHER_MODE_CBC) "CIPHER_MODE_CBC", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CBC */ #if defined(MBEDTLS_CIPHER_MODE_CFB) "CIPHER_MODE_CFB", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CFB */ #if defined(MBEDTLS_CIPHER_MODE_CTR) "CIPHER_MODE_CTR", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_CTR */ #if defined(MBEDTLS_CIPHER_MODE_OFB) "CIPHER_MODE_OFB", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_OFB */ #if defined(MBEDTLS_CIPHER_MODE_XTS) "CIPHER_MODE_XTS", //no-check-names #endif /* MBEDTLS_CIPHER_MODE_XTS */ #if defined(MBEDTLS_CIPHER_NULL_CIPHER) "CIPHER_NULL_CIPHER", //no-check-names #endif /* MBEDTLS_CIPHER_NULL_CIPHER */ #if defined(MBEDTLS_CIPHER_PADDING_PKCS7) "CIPHER_PADDING_PKCS7", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) "CIPHER_PADDING_ONE_AND_ZEROS", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) "CIPHER_PADDING_ZEROS_AND_LEN", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) "CIPHER_PADDING_ZEROS", //no-check-names #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) "CTR_DRBG_USE_128_BIT_KEY", //no-check-names #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) "ECDH_VARIANT_EVEREST_ENABLED", //no-check-names #endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) "ECP_DP_SECP192R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) "ECP_DP_SECP224R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) "ECP_DP_SECP256R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) "ECP_DP_SECP384R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) "ECP_DP_SECP521R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) "ECP_DP_SECP192K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) "ECP_DP_SECP224K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) "ECP_DP_SECP256K1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) "ECP_DP_BP256R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) "ECP_DP_BP384R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) "ECP_DP_BP512R1_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) "ECP_DP_CURVE25519_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) "ECP_DP_CURVE448_ENABLED", //no-check-names #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ #if defined(MBEDTLS_ECP_NIST_OPTIM) "ECP_NIST_OPTIM", //no-check-names #endif /* MBEDTLS_ECP_NIST_OPTIM */ #if defined(MBEDTLS_ECP_RESTARTABLE) "ECP_RESTARTABLE", //no-check-names #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_WITH_MPI_UINT) "ECP_WITH_MPI_UINT", //no-check-names #endif /* MBEDTLS_ECP_WITH_MPI_UINT */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) "ECDSA_DETERMINISTIC", //no-check-names #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) "KEY_EXCHANGE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) "KEY_EXCHANGE_DHE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) "KEY_EXCHANGE_ECDHE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) "KEY_EXCHANGE_RSA_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) "KEY_EXCHANGE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) "KEY_EXCHANGE_DHE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) "KEY_EXCHANGE_ECDHE_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) "KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) "KEY_EXCHANGE_ECDH_ECDSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) "KEY_EXCHANGE_ECDH_RSA_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) "KEY_EXCHANGE_ECJPAKE_ENABLED", //no-check-names #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) "PK_PARSE_EC_EXTENDED", //no-check-names #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ #if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) "PK_PARSE_EC_COMPRESSED", //no-check-names #endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ #if defined(MBEDTLS_ERROR_STRERROR_DUMMY) "ERROR_STRERROR_DUMMY", //no-check-names #endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ #if defined(MBEDTLS_GENPRIME) "GENPRIME", //no-check-names #endif /* MBEDTLS_GENPRIME */ #if defined(MBEDTLS_FS_IO) "FS_IO", //no-check-names #endif /* MBEDTLS_FS_IO */ #if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) "NO_DEFAULT_ENTROPY_SOURCES", //no-check-names #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ #if defined(MBEDTLS_NO_PLATFORM_ENTROPY) "NO_PLATFORM_ENTROPY", //no-check-names #endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ #if defined(MBEDTLS_ENTROPY_FORCE_SHA256) "ENTROPY_FORCE_SHA256", //no-check-names #endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ #if defined(MBEDTLS_ENTROPY_NV_SEED) "ENTROPY_NV_SEED", //no-check-names #endif /* MBEDTLS_ENTROPY_NV_SEED */ #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) "PSA_CRYPTO_KEY_ID_ENCODES_OWNER", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ #if defined(MBEDTLS_MEMORY_DEBUG) "MEMORY_DEBUG", //no-check-names #endif /* MBEDTLS_MEMORY_DEBUG */ #if defined(MBEDTLS_MEMORY_BACKTRACE) "MEMORY_BACKTRACE", //no-check-names #endif /* MBEDTLS_MEMORY_BACKTRACE */ #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) "PK_RSA_ALT_SUPPORT", //no-check-names #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #if defined(MBEDTLS_PKCS1_V15) "PKCS1_V15", //no-check-names #endif /* MBEDTLS_PKCS1_V15 */ #if defined(MBEDTLS_PKCS1_V21) "PKCS1_V21", //no-check-names #endif /* MBEDTLS_PKCS1_V21 */ #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) "PSA_CRYPTO_BUILTIN_KEYS", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ #if defined(MBEDTLS_PSA_CRYPTO_CLIENT) "PSA_CRYPTO_CLIENT", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) "PSA_CRYPTO_EXTERNAL_RNG", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #if defined(MBEDTLS_PSA_CRYPTO_SPM) "PSA_CRYPTO_SPM", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_SPM */ #if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) "PSA_P256M_DRIVER_ENABLED", //no-check-names #endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) "PSA_INJECT_ENTROPY", //no-check-names #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ #if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) "PSA_ASSUME_EXCLUSIVE_BUFFERS", //no-check-names #endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */ #if defined(MBEDTLS_RSA_NO_CRT) "RSA_NO_CRT", //no-check-names #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_SELF_TEST) "SELF_TEST", //no-check-names #endif /* MBEDTLS_SELF_TEST */ #if defined(MBEDTLS_SHA256_SMALLER) "SHA256_SMALLER", //no-check-names #endif /* MBEDTLS_SHA256_SMALLER */ #if defined(MBEDTLS_SHA512_SMALLER) "SHA512_SMALLER", //no-check-names #endif /* MBEDTLS_SHA512_SMALLER */ #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) "SSL_ALL_ALERT_MESSAGES", //no-check-names #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) "SSL_DTLS_CONNECTION_ID", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) "SSL_DTLS_CONNECTION_ID_COMPAT", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) "SSL_ASYNC_PRIVATE", //no-check-names #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) "SSL_CONTEXT_SERIALIZATION", //no-check-names #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "SSL_DEBUG_ALL", //no-check-names #endif /* MBEDTLS_SSL_DEBUG_ALL */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) "SSL_ENCRYPT_THEN_MAC", //no-check-names #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) "SSL_EXTENDED_MASTER_SECRET", //no-check-names #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) "SSL_KEEP_PEER_CERTIFICATE", //no-check-names #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #if defined(MBEDTLS_SSL_RENEGOTIATION) "SSL_RENEGOTIATION", //no-check-names #endif /* MBEDTLS_SSL_RENEGOTIATION */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) "SSL_MAX_FRAGMENT_LENGTH", //no-check-names #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) "SSL_RECORD_SIZE_LIMIT", //no-check-names #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) "SSL_PROTO_TLS1_2", //no-check-names #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) "SSL_PROTO_TLS1_3", //no-check-names #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) "SSL_TLS1_3_COMPATIBILITY_MODE", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) "SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED", //no-check-names #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */ #if defined(MBEDTLS_SSL_EARLY_DATA) "SSL_EARLY_DATA", //no-check-names #endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_SSL_PROTO_DTLS) "SSL_PROTO_DTLS", //no-check-names #endif /* MBEDTLS_SSL_PROTO_DTLS */ #if defined(MBEDTLS_SSL_ALPN) "SSL_ALPN", //no-check-names #endif /* MBEDTLS_SSL_ALPN */ #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) "SSL_DTLS_ANTI_REPLAY", //no-check-names #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) "SSL_DTLS_HELLO_VERIFY", //no-check-names #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ #if defined(MBEDTLS_SSL_DTLS_SRTP) "SSL_DTLS_SRTP", //no-check-names #endif /* MBEDTLS_SSL_DTLS_SRTP */ #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) "SSL_DTLS_CLIENT_PORT_REUSE", //no-check-names #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) "SSL_SESSION_TICKETS", //no-check-names #endif /* MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) "SSL_SERVER_NAME_INDICATION", //no-check-names #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) "SSL_VARIABLE_BUFFER_LENGTH", //no-check-names #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) "TEST_CONSTANT_FLOW_MEMSAN", //no-check-names #endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ #if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) "TEST_CONSTANT_FLOW_VALGRIND", //no-check-names #endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ #if defined(MBEDTLS_TEST_HOOKS) "TEST_HOOKS", //no-check-names #endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_THREADING_ALT) "THREADING_ALT", //no-check-names #endif /* MBEDTLS_THREADING_ALT */ #if defined(MBEDTLS_THREADING_PTHREAD) "THREADING_PTHREAD", //no-check-names #endif /* MBEDTLS_THREADING_PTHREAD */ #if defined(MBEDTLS_USE_PSA_CRYPTO) "USE_PSA_CRYPTO", //no-check-names #endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_CONFIG) "PSA_CRYPTO_CONFIG", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ #if defined(MBEDTLS_VERSION_FEATURES) "VERSION_FEATURES", //no-check-names #endif /* MBEDTLS_VERSION_FEATURES */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) "X509_TRUSTED_CERTIFICATE_CALLBACK", //no-check-names #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #if defined(MBEDTLS_X509_REMOVE_INFO) "X509_REMOVE_INFO", //no-check-names #endif /* MBEDTLS_X509_REMOVE_INFO */ #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) "X509_RSASSA_PSS_SUPPORT", //no-check-names #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ #if defined(MBEDTLS_AESNI_C) "AESNI_C", //no-check-names #endif /* MBEDTLS_AESNI_C */ #if defined(MBEDTLS_AESCE_C) "AESCE_C", //no-check-names #endif /* MBEDTLS_AESCE_C */ #if defined(MBEDTLS_AES_C) "AES_C", //no-check-names #endif /* MBEDTLS_AES_C */ #if defined(MBEDTLS_ASN1_PARSE_C) "ASN1_PARSE_C", //no-check-names #endif /* MBEDTLS_ASN1_PARSE_C */ #if defined(MBEDTLS_ASN1_WRITE_C) "ASN1_WRITE_C", //no-check-names #endif /* MBEDTLS_ASN1_WRITE_C */ #if defined(MBEDTLS_BASE64_C) "BASE64_C", //no-check-names #endif /* MBEDTLS_BASE64_C */ #if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) "BLOCK_CIPHER_NO_DECRYPT", //no-check-names #endif /* MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */ #if defined(MBEDTLS_BIGNUM_C) "BIGNUM_C", //no-check-names #endif /* MBEDTLS_BIGNUM_C */ #if defined(MBEDTLS_CAMELLIA_C) "CAMELLIA_C", //no-check-names #endif /* MBEDTLS_CAMELLIA_C */ #if defined(MBEDTLS_ARIA_C) "ARIA_C", //no-check-names #endif /* MBEDTLS_ARIA_C */ #if defined(MBEDTLS_CCM_C) "CCM_C", //no-check-names #endif /* MBEDTLS_CCM_C */ #if defined(MBEDTLS_CHACHA20_C) "CHACHA20_C", //no-check-names #endif /* MBEDTLS_CHACHA20_C */ #if defined(MBEDTLS_CHACHAPOLY_C) "CHACHAPOLY_C", //no-check-names #endif /* MBEDTLS_CHACHAPOLY_C */ #if defined(MBEDTLS_CIPHER_C) "CIPHER_C", //no-check-names #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_CMAC_C) "CMAC_C", //no-check-names #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_CTR_DRBG_C) "CTR_DRBG_C", //no-check-names #endif /* MBEDTLS_CTR_DRBG_C */ #if defined(MBEDTLS_DEBUG_C) "DEBUG_C", //no-check-names #endif /* MBEDTLS_DEBUG_C */ #if defined(MBEDTLS_DES_C) "DES_C", //no-check-names #endif /* MBEDTLS_DES_C */ #if defined(MBEDTLS_DHM_C) "DHM_C", //no-check-names #endif /* MBEDTLS_DHM_C */ #if defined(MBEDTLS_ECDH_C) "ECDH_C", //no-check-names #endif /* MBEDTLS_ECDH_C */ #if defined(MBEDTLS_ECDSA_C) "ECDSA_C", //no-check-names #endif /* MBEDTLS_ECDSA_C */ #if defined(MBEDTLS_ECJPAKE_C) "ECJPAKE_C", //no-check-names #endif /* MBEDTLS_ECJPAKE_C */ #if defined(MBEDTLS_ECP_C) "ECP_C", //no-check-names #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_ENTROPY_C) "ENTROPY_C", //no-check-names #endif /* MBEDTLS_ENTROPY_C */ #if defined(MBEDTLS_ERROR_C) "ERROR_C", //no-check-names #endif /* MBEDTLS_ERROR_C */ #if defined(MBEDTLS_GCM_C) "GCM_C", //no-check-names #endif /* MBEDTLS_GCM_C */ #if defined(MBEDTLS_GCM_LARGE_TABLE) "GCM_LARGE_TABLE", //no-check-names #endif /* MBEDTLS_GCM_LARGE_TABLE */ #if defined(MBEDTLS_HKDF_C) "HKDF_C", //no-check-names #endif /* MBEDTLS_HKDF_C */ #if defined(MBEDTLS_HMAC_DRBG_C) "HMAC_DRBG_C", //no-check-names #endif /* MBEDTLS_HMAC_DRBG_C */ #if defined(MBEDTLS_LMS_C) "LMS_C", //no-check-names #endif /* MBEDTLS_LMS_C */ #if defined(MBEDTLS_LMS_PRIVATE) "LMS_PRIVATE", //no-check-names #endif /* MBEDTLS_LMS_PRIVATE */ #if defined(MBEDTLS_NIST_KW_C) "NIST_KW_C", //no-check-names #endif /* MBEDTLS_NIST_KW_C */ #if defined(MBEDTLS_MD_C) "MD_C", //no-check-names #endif /* MBEDTLS_MD_C */ #if defined(MBEDTLS_MD5_C) "MD5_C", //no-check-names #endif /* MBEDTLS_MD5_C */ #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) "MEMORY_BUFFER_ALLOC_C", //no-check-names #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ #if defined(MBEDTLS_NET_C) "NET_C", //no-check-names #endif /* MBEDTLS_NET_C */ #if defined(MBEDTLS_OID_C) "OID_C", //no-check-names #endif /* MBEDTLS_OID_C */ #if defined(MBEDTLS_PADLOCK_C) "PADLOCK_C", //no-check-names #endif /* MBEDTLS_PADLOCK_C */ #if defined(MBEDTLS_PEM_PARSE_C) "PEM_PARSE_C", //no-check-names #endif /* MBEDTLS_PEM_PARSE_C */ #if defined(MBEDTLS_PEM_WRITE_C) "PEM_WRITE_C", //no-check-names #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_PK_C) "PK_C", //no-check-names #endif /* MBEDTLS_PK_C */ #if defined(MBEDTLS_PK_PARSE_C) "PK_PARSE_C", //no-check-names #endif /* MBEDTLS_PK_PARSE_C */ #if defined(MBEDTLS_PK_WRITE_C) "PK_WRITE_C", //no-check-names #endif /* MBEDTLS_PK_WRITE_C */ #if defined(MBEDTLS_PKCS5_C) "PKCS5_C", //no-check-names #endif /* MBEDTLS_PKCS5_C */ #if defined(MBEDTLS_PKCS7_C) "PKCS7_C", //no-check-names #endif /* MBEDTLS_PKCS7_C */ #if defined(MBEDTLS_PKCS12_C) "PKCS12_C", //no-check-names #endif /* MBEDTLS_PKCS12_C */ #if defined(MBEDTLS_PLATFORM_C) "PLATFORM_C", //no-check-names #endif /* MBEDTLS_PLATFORM_C */ #if defined(MBEDTLS_POLY1305_C) "POLY1305_C", //no-check-names #endif /* MBEDTLS_POLY1305_C */ #if defined(MBEDTLS_PSA_CRYPTO_C) "PSA_CRYPTO_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_C */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) "PSA_CRYPTO_SE_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) "PSA_CRYPTO_STORAGE_C", //no-check-names #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ #if defined(MBEDTLS_PSA_ITS_FILE_C) "PSA_ITS_FILE_C", //no-check-names #endif /* MBEDTLS_PSA_ITS_FILE_C */ #if defined(MBEDTLS_RIPEMD160_C) "RIPEMD160_C", //no-check-names #endif /* MBEDTLS_RIPEMD160_C */ #if defined(MBEDTLS_RSA_C) "RSA_C", //no-check-names #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_SHA1_C) "SHA1_C", //no-check-names #endif /* MBEDTLS_SHA1_C */ #if defined(MBEDTLS_SHA224_C) "SHA224_C", //no-check-names #endif /* MBEDTLS_SHA224_C */ #if defined(MBEDTLS_SHA256_C) "SHA256_C", //no-check-names #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) "SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT", //no-check-names #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */ #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) "SHA256_USE_A64_CRYPTO_IF_PRESENT", //no-check-names #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */ #if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) "SHA256_USE_ARMV8_A_CRYPTO_ONLY", //no-check-names #endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) "SHA256_USE_A64_CRYPTO_ONLY", //no-check-names #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SHA384_C) "SHA384_C", //no-check-names #endif /* MBEDTLS_SHA384_C */ #if defined(MBEDTLS_SHA512_C) "SHA512_C", //no-check-names #endif /* MBEDTLS_SHA512_C */ #if defined(MBEDTLS_SHA3_C) "SHA3_C", //no-check-names #endif /* MBEDTLS_SHA3_C */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) "SHA512_USE_A64_CRYPTO_IF_PRESENT", //no-check-names #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */ #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) "SHA512_USE_A64_CRYPTO_ONLY", //no-check-names #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */ #if defined(MBEDTLS_SSL_CACHE_C) "SSL_CACHE_C", //no-check-names #endif /* MBEDTLS_SSL_CACHE_C */ #if defined(MBEDTLS_SSL_COOKIE_C) "SSL_COOKIE_C", //no-check-names #endif /* MBEDTLS_SSL_COOKIE_C */ #if defined(MBEDTLS_SSL_TICKET_C) "SSL_TICKET_C", //no-check-names #endif /* MBEDTLS_SSL_TICKET_C */ #if defined(MBEDTLS_SSL_CLI_C) "SSL_CLI_C", //no-check-names #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) "SSL_SRV_C", //no-check-names #endif /* MBEDTLS_SSL_SRV_C */ #if defined(MBEDTLS_SSL_TLS_C) "SSL_TLS_C", //no-check-names #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_THREADING_C) "THREADING_C", //no-check-names #endif /* MBEDTLS_THREADING_C */ #if defined(MBEDTLS_TIMING_C) "TIMING_C", //no-check-names #endif /* MBEDTLS_TIMING_C */ #if defined(MBEDTLS_VERSION_C) "VERSION_C", //no-check-names #endif /* MBEDTLS_VERSION_C */ #if defined(MBEDTLS_X509_USE_C) "X509_USE_C", //no-check-names #endif /* MBEDTLS_X509_USE_C */ #if defined(MBEDTLS_X509_CRT_PARSE_C) "X509_CRT_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_X509_CRL_PARSE_C) "X509_CRL_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CRL_PARSE_C */ #if defined(MBEDTLS_X509_CSR_PARSE_C) "X509_CSR_PARSE_C", //no-check-names #endif /* MBEDTLS_X509_CSR_PARSE_C */ #if defined(MBEDTLS_X509_CREATE_C) "X509_CREATE_C", //no-check-names #endif /* MBEDTLS_X509_CREATE_C */ #if defined(MBEDTLS_X509_CRT_WRITE_C) "X509_CRT_WRITE_C", //no-check-names #endif /* MBEDTLS_X509_CRT_WRITE_C */ #if defined(MBEDTLS_X509_CSR_WRITE_C) "X509_CSR_WRITE_C", //no-check-names #endif /* MBEDTLS_X509_CSR_WRITE_C */ #endif /* MBEDTLS_VERSION_FEATURES */ NULL }; int mbedtls_version_check_feature(const char *feature) { const char * const *idx = features; if (*idx == NULL) { return -2; } if (feature == NULL) { return -1; } if (strncmp(feature, "MBEDTLS_", 8)) { return -1; } feature += 8; while (*idx != NULL) { if (!strcmp(*idx, feature)) { return 0; } idx++; } return -1; } #endif /* MBEDTLS_VERSION_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509.c000066400000000000000000001602231464416617300222110ustar00rootroot00000000000000/* * X.509 common functions for parsing and verification * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_USE_C) #include "x509_internal.h" #include "mbedtls/asn1.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/asn1write.h" #include "mbedtls/platform.h" #if defined(MBEDTLS_HAVE_TIME) #include "mbedtls/platform_time.h" #endif #if defined(MBEDTLS_HAVE_TIME_DATE) #include "mbedtls/platform_util.h" #include #endif #define CHECK(code) \ do { \ if ((ret = (code)) != 0) { \ return ret; \ } \ } while (0) #define CHECK_RANGE(min, max, val) \ do { \ if ((val) < (min) || (val) > (max)) { \ return ret; \ } \ } while (0) /* * CertificateSerialNumber ::= INTEGER */ int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) && **p != MBEDTLS_ASN1_INTEGER) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } serial->tag = *(*p)++; if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret); } serial->p = *p; *p += serial->len; return 0; } /* Get an algorithm identifier without parameters (eg for signatures) * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } return 0; } /* * Parse an algorithm identifier with (optional) parameters */ int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg, mbedtls_x509_buf *params) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } return 0; } /* * Convert md type to string */ #if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) { switch (md_alg) { #if defined(MBEDTLS_MD_CAN_MD5) case MBEDTLS_MD_MD5: return "MD5"; #endif #if defined(MBEDTLS_MD_CAN_SHA1) case MBEDTLS_MD_SHA1: return "SHA1"; #endif #if defined(MBEDTLS_MD_CAN_SHA224) case MBEDTLS_MD_SHA224: return "SHA224"; #endif #if defined(MBEDTLS_MD_CAN_SHA256) case MBEDTLS_MD_SHA256: return "SHA256"; #endif #if defined(MBEDTLS_MD_CAN_SHA384) case MBEDTLS_MD_SHA384: return "SHA384"; #endif #if defined(MBEDTLS_MD_CAN_SHA512) case MBEDTLS_MD_SHA512: return "SHA512"; #endif #if defined(MBEDTLS_MD_CAN_RIPEMD160) case MBEDTLS_MD_RIPEMD160: return "RIPEMD160"; #endif case MBEDTLS_MD_NONE: return NULL; default: return NULL; } } #endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */ #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) /* * HashAlgorithm ::= AlgorithmIdentifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * * For HashAlgorithm, parameters MUST be NULL or absent. */ static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p; const unsigned char *end; mbedtls_x509_buf md_oid; size_t len; /* Make sure we got a SEQUENCE and setup bounds */ if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } p = alg->p; end = p + alg->len; if (p >= end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } /* Parse md_oid */ md_oid.tag = *p; if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } md_oid.p = p; p += md_oid.len; /* Get md_alg from md_oid */ if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } /* Make sure params is absent of NULL */ if (p == end) { return 0; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * RSASSA-PSS-params ::= SEQUENCE { * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, * saltLength [2] INTEGER DEFAULT 20, * trailerField [3] INTEGER DEFAULT 1 } * -- Note that the tags in this Sequence are explicit. * * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other * option. Enforce this at parsing time. */ int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, int *salt_len) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char *p; const unsigned char *end, *end2; size_t len; mbedtls_x509_buf alg_id, alg_params; /* First set everything to defaults */ *md_alg = MBEDTLS_MD_SHA1; *mgf_md = MBEDTLS_MD_SHA1; *salt_len = 20; /* Make sure params is a SEQUENCE and setup bounds */ if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } p = (unsigned char *) params->p; end = p + params->len; if (p == end) { return 0; } /* * HashAlgorithm */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { end2 = p + len; /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) { return ret; } if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p == end) { return 0; } /* * MaskGenAlgorithm */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { end2 = p + len; /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) { return ret; } /* Only MFG1 is recognised for now */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, MBEDTLS_ERR_OID_NOT_FOUND); } /* Parse HashAlgorithm */ if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) { return ret; } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p == end) { return 0; } /* * salt_len */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2)) == 0) { end2 = p + len; if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p == end) { return 0; } /* * trailer_field (if present, must be 1) */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3)) == 0) { int trailer_field; end2 = p + len; if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end2) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if (trailer_field != 1) { return MBEDTLS_ERR_X509_INVALID_ALG; } } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); } if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ /* * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_get_attr_type_value(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; mbedtls_x509_buf *oid; mbedtls_x509_buf *val; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); } end = *p + len; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } oid = &cur->oid; oid->tag = **p; if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); } oid->p = *p; *p += oid->len; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && **p != MBEDTLS_ASN1_BIT_STRING) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } val = &cur->val; val->tag = *(*p)++; if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); } val->p = *p; *p += val->len; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } cur->next = NULL; return 0; } /* * Name ::= CHOICE { -- only one possibility for now -- * rdnSequence RDNSequence } * * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType * * The data structure is optimized for the common case where each RDN has only * one element, which is represented as a list of AttributeTypeAndValue. * For the general case we still use a flat list, but we mark elements of the * same set so that they are "merged" together in the functions that consume * this list, eg mbedtls_x509_dn_gets(). * * On success, this function may allocate a linked list starting at cur->next * that must later be free'd by the caller using mbedtls_free(). In error * cases, this function frees all allocated memory internally and the caller * has no freeing responsibilities. */ int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t set_len; const unsigned char *end_set; mbedtls_x509_name *head = cur; /* don't use recursion, we'd risk stack overflow if not optimized */ while (1) { /* * parse SET */ if ((ret = mbedtls_asn1_get_tag(p, end, &set_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); goto error; } end_set = *p + set_len; while (1) { if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { goto error; } if (*p == end_set) { break; } /* Mark this item as being no the only one in a set */ cur->next_merged = 1; cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); if (cur->next == NULL) { ret = MBEDTLS_ERR_X509_ALLOC_FAILED; goto error; } cur = cur->next; } /* * continue until end of SEQUENCE is reached */ if (*p == end) { return 0; } cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); if (cur->next == NULL) { ret = MBEDTLS_ERR_X509_ALLOC_FAILED; goto error; } cur = cur->next; } error: /* Skip the first element as we did not allocate it */ mbedtls_asn1_free_named_data_list_shallow(head->next); head->next = NULL; return ret; } static int x509_date_is_valid(const mbedtls_x509_time *t) { unsigned int month_days; unsigned int year; switch (t->mon) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: month_days = 31; break; case 4: case 6: case 9: case 11: month_days = 30; break; case 2: year = (unsigned int) t->year; month_days = ((year & 3) || (!(year % 100) && (year % 400))) ? 28 : 29; break; default: return MBEDTLS_ERR_X509_INVALID_DATE; } if ((unsigned int) (t->day - 1) >= month_days || /* (1 - days in month) */ /* (unsigned int) (t->mon - 1) >= 12 || */ /* (1 - 12) checked above */ (unsigned int) t->year > 9999 || /* (0 - 9999) */ (unsigned int) t->hour > 23 || /* (0 - 23) */ (unsigned int) t->min > 59 || /* (0 - 59) */ (unsigned int) t->sec > 59) { /* (0 - 59) */ return MBEDTLS_ERR_X509_INVALID_DATE; } return 0; } static int x509_parse2_int(const unsigned char *p) { uint32_t d1 = p[0] - '0'; uint32_t d2 = p[1] - '0'; return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1; } /* * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) * field. */ static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm, size_t yearlen) { int x; /* * Parse year, month, day, hour, minute, second */ tm->year = x509_parse2_int(p); if (tm->year < 0) { return MBEDTLS_ERR_X509_INVALID_DATE; } if (4 == yearlen) { x = tm->year * 100; p += 2; tm->year = x509_parse2_int(p); if (tm->year < 0) { return MBEDTLS_ERR_X509_INVALID_DATE; } } else { x = (tm->year < 50) ? 2000 : 1900; } tm->year += x; tm->mon = x509_parse2_int(p + 2); tm->day = x509_parse2_int(p + 4); tm->hour = x509_parse2_int(p + 6); tm->min = x509_parse2_int(p + 8); tm->sec = x509_parse2_int(p + 10); return x509_date_is_valid(tm); } /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime } */ int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, mbedtls_x509_time *tm) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len, year_len; unsigned char tag; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } tag = **p; if (tag == MBEDTLS_ASN1_UTC_TIME) { year_len = 2; } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) { year_len = 4; } else { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } (*p)++; ret = mbedtls_asn1_get_len(p, end, &len); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); } /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */ if (len != year_len + 10 && !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) { return MBEDTLS_ERR_X509_INVALID_DATE; } (*p) += len; return x509_parse_time(*p - len, tm, year_len); } int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; int tag_type; if ((end - *p) < 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, MBEDTLS_ERR_ASN1_OUT_OF_DATA); } tag_type = **p; if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret); } sig->tag = tag_type; sig->len = len; sig->p = *p; *p += len; return 0; } /* * Get signature algorithm from alg OID and optional parameters */ int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, void **sig_opts) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (*sig_opts != NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret); } #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) { mbedtls_pk_rsassa_pss_options *pss_opts; pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options)); if (pss_opts == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } ret = mbedtls_x509_get_rsassa_pss_params(sig_params, md_alg, &pss_opts->mgf1_hash_id, &pss_opts->expected_salt_len); if (ret != 0) { mbedtls_free(pss_opts); return ret; } *sig_opts = (void *) pss_opts; } else #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ { /* Make sure parameters are absent or NULL */ if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) || sig_params->len != 0) { return MBEDTLS_ERR_X509_INVALID_ALG; } } return 0; } /* * X.509 Extensions (No parsing of extensions, pointer should * be either manually updated or extensions should be parsed!) */ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Extension structure use EXPLICIT tagging. That is, the actual * `Extensions` structure is wrapped by a tag-length pair using * the respective context-specific tag. */ ret = mbedtls_asn1_get_tag(p, end, &ext->len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; ext->p = *p; end = *p + ext->len; /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (end != *p + len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } static char nibble_to_hex_digit(int i) { return (i < 10) ? (i + '0') : (i - 10 + 'A'); } /* * Store the name in printable form into buf; no more * than size characters will be written */ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start; /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/ unsigned char asn1_tag_len_buf[6]; unsigned char *asn1_len_p; unsigned char c, merge = 0; const mbedtls_x509_name *name; const char *short_name = NULL; char lowbits, highbits; char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; int print_hexstring; memset(s, 0, sizeof(s)); name = dn; p = buf; n = size; while (name != NULL) { if (!name->oid.p) { name = name->next; continue; } if (name != dn) { ret = mbedtls_snprintf(p, n, merge ? " + " : ", "); MBEDTLS_X509_SAFE_SNPRINTF; } print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) && (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) && (name->val.tag != MBEDTLS_ASN1_IA5_STRING); if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) { ret = mbedtls_snprintf(p, n, "%s=", short_name); } else { if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) { n -= ret; p += ret; ret = mbedtls_snprintf(p, n, "="); print_hexstring = 1; } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } else { ret = mbedtls_snprintf(p, n, "\?\?="); } } MBEDTLS_X509_SAFE_SNPRINTF; if (print_hexstring) { s[0] = '#'; asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf); if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } asn1_len_size = ret; if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) { return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; } asn1_tag_size = ret; asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size; for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } c = asn1_tag_len_buf[asn1_tag_len_buf_start+i]; lowbits = (c & 0x0F); highbits = c >> 4; s[j++] = nibble_to_hex_digit(highbits); s[j++] = nibble_to_hex_digit(lowbits); } for (i = 0; i < name->val.len; i++) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } c = name->val.p[i]; lowbits = (c & 0x0F); highbits = c >> 4; s[j++] = nibble_to_hex_digit(highbits); s[j++] = nibble_to_hex_digit(lowbits); } } else { for (i = 0, j = 0; i < name->val.len; i++, j++) { if (j >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } c = name->val.p[i]; // Special characters requiring escaping, RFC 4514 Section 2.4 if (c == '\0') { return MBEDTLS_ERR_X509_INVALID_NAME; } else { if (strchr(",=+<>;\"\\", c) || ((i == 0) && strchr("# ", c)) || ((i == name->val.len-1) && (c == ' '))) { if (j + 1 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } s[j++] = '\\'; } } if (c < 32 || c >= 127) { if (j + 3 >= sizeof(s) - 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } s[j++] = '\\'; lowbits = (c & 0x0F); highbits = c >> 4; s[j++] = nibble_to_hex_digit(highbits); s[j] = nibble_to_hex_digit(lowbits); } else { s[j] = c; } } } s[j] = '\0'; ret = mbedtls_snprintf(p, n, "%s", s); MBEDTLS_X509_SAFE_SNPRINTF; merge = name->next_merged; name = name->next; } return (int) (size - n); } /* * Store the serial in printable form into buf; no more * than size characters will be written */ int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i, n, nr; char *p; p = buf; n = size; nr = (serial->len <= 32) ? serial->len : 28; for (i = 0; i < nr; i++) { if (i == 0 && nr > 1 && serial->p[i] == 0x0) { continue; } ret = mbedtls_snprintf(p, n, "%02X%s", serial->p[i], (i < nr - 1) ? ":" : ""); MBEDTLS_X509_SAFE_SNPRINTF; } if (nr != serial->len) { ret = mbedtls_snprintf(p, n, "...."); MBEDTLS_X509_SAFE_SNPRINTF; } return (int) (size - n); } #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Helper for writing signature algorithms */ int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const void *sig_opts) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; char *p = buf; size_t n = size; const char *desc = NULL; ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc); if (ret != 0) { ret = mbedtls_snprintf(p, n, "???"); } else { ret = mbedtls_snprintf(p, n, "%s", desc); } MBEDTLS_X509_SAFE_SNPRINTF; #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { const mbedtls_pk_rsassa_pss_options *pss_opts; pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; const char *name = md_type_to_string(md_alg); const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", name ? name : "???", mgf_name ? mgf_name : "???", (unsigned int) pss_opts->expected_salt_len); MBEDTLS_X509_SAFE_SNPRINTF; } #else ((void) pk_alg); ((void) md_alg); ((void) sig_opts); #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Helper for writing "RSA key size", "EC key size", etc */ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) { char *p = buf; size_t n = buf_size; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; ret = mbedtls_snprintf(p, n, "%s key size", name); MBEDTLS_X509_SAFE_SNPRINTF; return 0; } int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2) { int x; x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) - ((t2->year << 9) | (t2->mon << 5) | (t2->day))); if (x != 0) { return x; } x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) - ((t2->hour << 12) | (t2->min << 6) | (t2->sec))); return x; } #if defined(MBEDTLS_HAVE_TIME_DATE) int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now) { struct tm tm; if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) { return -1; } now->year = tm.tm_year + 1900; now->mon = tm.tm_mon + 1; now->day = tm.tm_mday; now->hour = tm.tm_hour; now->min = tm.tm_min; now->sec = tm.tm_sec; return 0; } static int x509_get_current_time(mbedtls_x509_time *now) { return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now); } int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { mbedtls_x509_time now; if (x509_get_current_time(&now) != 0) { return 1; } return mbedtls_x509_time_cmp(to, &now) < 0; } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) { mbedtls_x509_time now; if (x509_get_current_time(&now) != 0) { return 1; } return mbedtls_x509_time_cmp(from, &now) > 0; } #else /* MBEDTLS_HAVE_TIME_DATE */ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) { ((void) to); return 0; } int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) { ((void) from); return 0; } #endif /* MBEDTLS_HAVE_TIME_DATE */ /* Common functions for parsing CRT and CSR. */ #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C) /* * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * HardwareModuleName ::= SEQUENCE { * hwType OBJECT IDENTIFIER, * hwSerialNum OCTET STRING } * * NOTE: we currently only parse and use otherName of type HwModuleName, * as defined in RFC 4108. */ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, mbedtls_x509_san_other_name *other_name) { int ret = 0; size_t len; unsigned char *p = subject_alt_name->p; const unsigned char *end = p + subject_alt_name->len; mbedtls_x509_buf cur_oid; if ((subject_alt_name->tag & (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { /* * The given subject alternative name is not of type "othername". */ return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } cur_oid.tag = MBEDTLS_ASN1_OID; cur_oid.p = p; cur_oid.len = len; /* * Only HwModuleName is currently supported. */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } other_name->type_id = cur_oid; p += len; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (end != p + len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (end != p + len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; other_name->value.hardware_module_name.oid.p = p; other_name->value.hardware_module_name.oid.len = len; p += len; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; other_name->value.hardware_module_name.val.p = p; other_name->value.hardware_module_name.val.len = len; p += len; if (p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* Check mbedtls_x509_get_subject_alt_name for detailed description. * * In some cases while parsing subject alternative names the sequence tag is optional * (e.g. CertSerialNumber). This function is designed to handle such case. */ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t tag_len; mbedtls_asn1_sequence *cur = subject_alt_name; while (*p < end) { mbedtls_x509_subject_alternative_name tmp_san_name; mbedtls_x509_buf tmp_san_buf; memset(&tmp_san_name, 0, sizeof(tmp_san_name)); tmp_san_buf.tag = **p; (*p)++; if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } tmp_san_buf.p = *p; tmp_san_buf.len = tag_len; if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != MBEDTLS_ASN1_CONTEXT_SPECIFIC) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } /* * Check that the SAN is structured correctly by parsing it. * The SAN structure is discarded afterwards. */ ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name); /* * In case the extension is malformed, return an error, * and clear the allocated sequences. */ if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { mbedtls_asn1_sequence_free(subject_alt_name->next); subject_alt_name->next = NULL; return ret; } mbedtls_x509_free_subject_alt_name(&tmp_san_name); /* Allocate and assign next pointer */ if (cur->buf.p != NULL) { if (cur->next != NULL) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); if (cur->next == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_ALLOC_FAILED); } cur = cur->next; } cur->buf = tmp_san_buf; *p += tmp_san_buf.len; } /* Set final sequence entry's next pointer to NULL */ cur->next = NULL; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * SubjectAltName ::= GeneralNames * * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName * * GeneralName ::= CHOICE { * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER } * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * EDIPartyName ::= SEQUENCE { * nameAssigner [0] DirectoryString OPTIONAL, * partyName [1] DirectoryString } * * We list all types, but use the following GeneralName types from RFC 5280: * "dnsName", "uniformResourceIdentifier" and "hardware_module_name" * of type "otherName", as defined in RFC 4108. */ int mbedtls_x509_get_subject_alt_name(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* Get main sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name); } int mbedtls_x509_get_ns_cert_type(unsigned char **p, const unsigned char *end, unsigned char *ns_cert_type) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_bitstring bs = { 0, 0, NULL }; if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* A bitstring with no flags set is still technically valid, as it will mean that the certificate has no designated purpose at the time of creation. */ if (bs.len == 0) { *ns_cert_type = 0; return 0; } if (bs.len != 1) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } /* Get actual bitstring */ *ns_cert_type = *bs.p; return 0; } int mbedtls_x509_get_key_usage(unsigned char **p, const unsigned char *end, unsigned int *key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; mbedtls_x509_bitstring bs = { 0, 0, NULL }; if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* A bitstring with no flags set is still technically valid, as it will mean that the certificate has no designated purpose at the time of creation. */ if (bs.len == 0) { *key_usage = 0; return 0; } /* Get actual bitstring */ *key_usage = 0; for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { *key_usage |= (unsigned int) bs.p[i] << (8*i); } return 0; } int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf, mbedtls_x509_subject_alternative_name *san) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (san_buf->tag & (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) { /* * otherName */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): { mbedtls_x509_san_other_name other_name; ret = x509_get_other_name(san_buf, &other_name); if (ret != 0) { return ret; } memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_OTHER_NAME; memcpy(&san->san.other_name, &other_name, sizeof(other_name)); } break; /* * uniformResourceIdentifier */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } break; /* * dNSName */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_DNS_NAME; memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } break; /* * IP address */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_IP_ADDRESS; // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported if (san_buf->len == 4 || san_buf->len == 16) { memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } else { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } } break; /* * rfc822Name */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME): { memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_RFC822_NAME; memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); } break; /* * directoryName */ case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME): { size_t name_len; unsigned char *p = san_buf->p; memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME; ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return ret; } if ((ret = mbedtls_x509_get_name(&p, p + name_len, &san->san.directory_name)) != 0) { return ret; } } break; /* * Type not supported */ default: return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } return 0; } void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san) { if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) { mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next); } } #if !defined(MBEDTLS_X509_REMOVE_INFO) int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, const mbedtls_x509_sequence *subject_alt_name, const char *prefix) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t i; size_t n = *size; char *p = *buf; const mbedtls_x509_sequence *cur = subject_alt_name; mbedtls_x509_subject_alternative_name san; int parse_ret; while (cur != NULL) { memset(&san, 0, sizeof(san)); parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); if (parse_ret != 0) { if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { ret = mbedtls_snprintf(p, n, "\n%s ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; } else { ret = mbedtls_snprintf(p, n, "\n%s ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; } cur = cur->next; continue; } switch (san.type) { /* * otherName */ case MBEDTLS_X509_SAN_OTHER_NAME: { mbedtls_x509_san_other_name *other_name = &san.san.other_name; ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &other_name->type_id) == 0) { ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_oid_get_numeric_string(p, n, &other_name->value.hardware_module_name.oid); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) { ret = mbedtls_snprintf(p, n, "%02X", other_name->value.hardware_module_name.val.p[i]); MBEDTLS_X509_SAFE_SNPRINTF; } }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ } break; /* * uniformResourceIdentifier */ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: { ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if (san.san.unstructured_name.len >= n) { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); p += san.san.unstructured_name.len; n -= san.san.unstructured_name.len; } break; /* * dNSName * RFC822 Name */ case MBEDTLS_X509_SAN_DNS_NAME: case MBEDTLS_X509_SAN_RFC822_NAME: { const char *dns_name = "dNSName"; const char *rfc822_name = "rfc822Name"; ret = mbedtls_snprintf(p, n, "\n%s %s : ", prefix, san.type == MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name); MBEDTLS_X509_SAFE_SNPRINTF; if (san.san.unstructured_name.len >= n) { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); p += san.san.unstructured_name.len; n -= san.san.unstructured_name.len; } break; /* * iPAddress */ case MBEDTLS_X509_SAN_IP_ADDRESS: { ret = mbedtls_snprintf(p, n, "\n%s %s : ", prefix, "iPAddress"); MBEDTLS_X509_SAFE_SNPRINTF; if (san.san.unstructured_name.len >= n) { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } unsigned char *ip = san.san.unstructured_name.p; // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported if (san.san.unstructured_name.len == 4) { ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); MBEDTLS_X509_SAFE_SNPRINTF; } else if (san.san.unstructured_name.len == 16) { ret = mbedtls_snprintf(p, n, "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X", ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13], ip[14], ip[15]); MBEDTLS_X509_SAFE_SNPRINTF; } else { if (n > 0) { *p = '\0'; } return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } } break; /* * directoryName */ case MBEDTLS_X509_SAN_DIRECTORY_NAME: { ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix); if (ret < 0 || (size_t) ret >= n) { mbedtls_x509_free_subject_alt_name(&san); } MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name); if (ret < 0) { mbedtls_x509_free_subject_alt_name(&san); if (n > 0) { *p = '\0'; } return ret; } p += ret; n -= ret; } break; /* * Type not supported, skip item. */ default: ret = mbedtls_snprintf(p, n, "\n%s ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; break; } /* So far memory is freed only in the case of directoryName * parsing succeeding, as mbedtls_x509_get_name allocates memory. */ mbedtls_x509_free_subject_alt_name(&san); cur = cur->next; } *p = '\0'; *size = n; *buf = p; return 0; } #define PRINT_ITEM(i) \ do { \ ret = mbedtls_snprintf(p, n, "%s" i, sep); \ MBEDTLS_X509_SAFE_SNPRINTF; \ sep = ", "; \ } while (0) #define CERT_TYPE(type, name) \ do { \ if (ns_cert_type & (type)) { \ PRINT_ITEM(name); \ } \ } while (0) int mbedtls_x509_info_cert_type(char **buf, size_t *size, unsigned char ns_cert_type) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n = *size; char *p = *buf; const char *sep = ""; CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); *size = n; *buf = p; return 0; } #define KEY_USAGE(code, name) \ do { \ if ((key_usage) & (code)) { \ PRINT_ITEM(name); \ } \ } while (0) int mbedtls_x509_info_key_usage(char **buf, size_t *size, unsigned int key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n = *size; char *p = *buf; const char *sep = ""; KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); *size = n; *buf = p; return 0; } #endif /* MBEDTLS_X509_REMOVE_INFO */ #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */ #endif /* MBEDTLS_X509_USE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509_create.c000066400000000000000000000465331464416617300235430ustar00rootroot00000000000000/* * X.509 base functions for creating certificates / CSRs * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_X509_CREATE_C) #include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include #include "mbedtls/platform.h" #include "mbedtls/asn1.h" /* Structure linking OIDs for X.509 DN AttributeTypes to their * string representations and default string encodings used by Mbed TLS. */ typedef struct { const char *name; /* String representation of AttributeType, e.g. * "CN" or "emailAddress". */ size_t name_len; /* Length of 'name', without trailing 0 byte. */ const char *oid; /* String representation of OID of AttributeType, * as per RFC 5280, Appendix A.1. encoded as per * X.690 */ int default_tag; /* The default character encoding used for the * given attribute type, e.g. * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ } x509_attr_descriptor_t; #define ADD_STRLEN(s) s, sizeof(s) - 1 /* X.509 DN attributes from RFC 5280, Appendix A.1. */ static const x509_attr_descriptor_t x509_attrs[] = { { ADD_STRLEN("CN"), MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("commonName"), MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("C"), MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("countryName"), MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("O"), MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("organizationName"), MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("L"), MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("locality"), MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("R"), MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, { ADD_STRLEN("OU"), MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("organizationalUnitName"), MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("ST"), MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("stateOrProvinceName"), MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("emailAddress"), MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, { ADD_STRLEN("serialNumber"), MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("postalAddress"), MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("postalCode"), MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("dnQualifier"), MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, { ADD_STRLEN("title"), MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("surName"), MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("SN"), MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("givenName"), MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("GN"), MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("initials"), MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("pseudonym"), MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("generationQualifier"), MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, { ADD_STRLEN("domainComponent"), MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, { ADD_STRLEN("DC"), MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, { NULL, 0, NULL, MBEDTLS_ASN1_NULL } }; static const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name, size_t name_len) { const x509_attr_descriptor_t *cur; for (cur = x509_attrs; cur->name != NULL; cur++) { if (cur->name_len == name_len && strncmp(cur->name, name, name_len) == 0) { break; } } if (cur->name == NULL) { return NULL; } return cur; } static int hex_to_int(char c) { return ('0' <= c && c <= '9') ? (c - '0') : ('a' <= c && c <= 'f') ? (c - 'a' + 10) : ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1; } static int hexpair_to_int(const char *hexpair) { int n1 = hex_to_int(*hexpair); int n2 = hex_to_int(*(hexpair + 1)); if (n1 != -1 && n2 != -1) { return (n1 << 4) | n2; } else { return -1; } } static int parse_attribute_value_string(const char *s, int len, unsigned char *data, size_t *data_len) { const char *c; const char *end = s + len; unsigned char *d = data; int n; for (c = s; c < end; c++) { if (*c == '\\') { c++; /* Check for valid escaped characters as per RFC 4514 Section 3 */ if (c + 1 < end && (n = hexpair_to_int(c)) != -1) { if (n == 0) { return MBEDTLS_ERR_X509_INVALID_NAME; } *(d++) = n; c++; } else if (c < end && strchr(" ,=+<>#;\"\\", *c)) { *(d++) = *c; } else { return MBEDTLS_ERR_X509_INVALID_NAME; } } else { *(d++) = *c; } if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) { return MBEDTLS_ERR_X509_INVALID_NAME; } } *data_len = (size_t) (d - data); return 0; } /** Parse a hexstring containing a DER-encoded string. * * \param s A string of \p len bytes hexadecimal digits. * \param len Number of bytes to read from \p s. * \param data Output buffer of size \p data_size. * On success, it contains the payload that's DER-encoded * in the input (content without the tag and length). * If the DER tag is a string tag, the payload is guaranteed * not to contain null bytes. * \param data_size Length of the \p data buffer. * \param data_len On success, the length of the parsed string. * It is guaranteed to be less than * #MBEDTLS_X509_MAX_DN_NAME_SIZE. * \param tag The ASN.1 tag that the payload in \p data is encoded in. * * \retval 0 on success. * \retval #MBEDTLS_ERR_X509_INVALID_NAME if \p s does not contain * a valid hexstring, * or if the decoded hexstring is not valid DER, * or if the payload does not fit in \p data, * or if the payload is more than * #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes, * of if \p *tag is an ASN.1 string tag and the payload * contains a null byte. * \retval #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory. */ static int parse_attribute_value_hex_der_encoded(const char *s, size_t len, unsigned char *data, size_t data_size, size_t *data_len, int *tag) { /* Step 1: preliminary length checks. */ /* Each byte is encoded by exactly two hexadecimal digits. */ if (len % 2 != 0) { /* Odd number of hex digits */ return MBEDTLS_ERR_X509_INVALID_NAME; } size_t const der_length = len / 2; if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) { /* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE * (after subtracting the ASN.1 tag and length). Reject this early * to avoid allocating a large intermediate buffer. */ return MBEDTLS_ERR_X509_INVALID_NAME; } if (der_length < 1) { /* Avoid empty-buffer shenanigans. A valid DER encoding is never * empty. */ return MBEDTLS_ERR_X509_INVALID_NAME; } /* Step 2: Decode the hex string into an intermediate buffer. */ unsigned char *der = mbedtls_calloc(1, der_length); if (der == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } /* Beyond this point, der needs to be freed on exit. */ for (size_t i = 0; i < der_length; i++) { int c = hexpair_to_int(s + 2 * i); if (c < 0) { goto error; } der[i] = c; } /* Step 3: decode the DER. */ /* We've checked that der_length >= 1 above. */ *tag = der[0]; { unsigned char *p = der + 1; if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) { goto error; } /* Now p points to the first byte of the payload inside der, * and *data_len is the length of the payload. */ /* Step 4: payload validation */ if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) { goto error; } /* Strings must not contain null bytes. */ if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) { for (size_t i = 0; i < *data_len; i++) { if (p[i] == 0) { goto error; } } } /* Step 5: output the payload. */ if (*data_len > data_size) { goto error; } memcpy(data, p, *data_len); } mbedtls_free(der); return 0; error: mbedtls_free(der); return MBEDTLS_ERR_X509_INVALID_NAME; } int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name) { int ret = MBEDTLS_ERR_X509_INVALID_NAME; int parse_ret = 0; const char *s = name, *c = s; const char *end = s + strlen(s); mbedtls_asn1_buf oid = { .p = NULL, .len = 0, .tag = MBEDTLS_ASN1_NULL }; const x509_attr_descriptor_t *attr_descr = NULL; int in_attr_type = 1; int tag; int numericoid = 0; unsigned char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; size_t data_len = 0; /* Clear existing chain if present */ mbedtls_asn1_free_named_data_list(head); while (c <= end) { if (in_attr_type && *c == '=') { if ((attr_descr = x509_attr_descr_from_name(s, (size_t) (c - s))) == NULL) { if ((mbedtls_oid_from_numeric_string(&oid, s, (size_t) (c - s))) != 0) { return MBEDTLS_ERR_X509_INVALID_NAME; } else { numericoid = 1; } } else { oid.len = strlen(attr_descr->oid); oid.p = mbedtls_calloc(1, oid.len); memcpy(oid.p, attr_descr->oid, oid.len); numericoid = 0; } s = c + 1; in_attr_type = 0; } if (!in_attr_type && ((*c == ',' && *(c-1) != '\\') || c == end)) { if (s == c) { mbedtls_free(oid.p); return MBEDTLS_ERR_X509_INVALID_NAME; } else if (*s == '#') { /* We know that c >= s (loop invariant) and c != s (in this * else branch), hence c - s - 1 >= 0. */ parse_ret = parse_attribute_value_hex_der_encoded( s + 1, (size_t) (c - s) - 1, data, sizeof(data), &data_len, &tag); if (parse_ret != 0) { mbedtls_free(oid.p); return parse_ret; } } else { if (numericoid) { mbedtls_free(oid.p); return MBEDTLS_ERR_X509_INVALID_NAME; } else { if ((parse_ret = parse_attribute_value_string(s, (int) (c - s), data, &data_len)) != 0) { mbedtls_free(oid.p); return parse_ret; } tag = attr_descr->default_tag; } } mbedtls_asn1_named_data *cur = mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len, (unsigned char *) data, data_len); mbedtls_free(oid.p); oid.p = NULL; if (cur == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } // set tagType cur->val.tag = tag; while (c < end && *(c + 1) == ' ') { c++; } s = c + 1; in_attr_type = 1; /* Successfully parsed one name, update ret to success */ ret = 0; } c++; } if (oid.p != NULL) { mbedtls_free(oid.p); } return ret; } /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved * to store the critical boolean for us */ int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len) { mbedtls_asn1_named_data *cur; if (val_len > (SIZE_MAX - 1)) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len, NULL, val_len + 1)) == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } cur->val.p[0] = critical; memcpy(cur->val.p + 1, val, val_len); return 0; } /* * RelativeDistinguishedName ::= * SET OF AttributeTypeAndValue * * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue } * * AttributeType ::= OBJECT IDENTIFIER * * AttributeValue ::= ANY DEFINED BY AttributeType */ static int x509_write_name(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *cur_name) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; const char *oid = (const char *) cur_name->oid.p; size_t oid_len = cur_name->oid.len; const unsigned char *name = cur_name->val.p; size_t name_len = cur_name->val.len; // Write correct string tag and value MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tagged_string(p, start, cur_name->val.tag, (const char *) name, name_len)); // Write OID // MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); return (int) len; } int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; mbedtls_asn1_named_data *cur = first; while (cur != NULL) { MBEDTLS_ASN1_CHK_ADD(len, x509_write_name(p, start, cur)); cur = cur->next; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, unsigned char *sig, size_t size, mbedtls_pk_type_t pk_alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; int write_null_par; size_t len = 0; if (*p < start || (size_t) (*p - start) < size) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } len = size; (*p) -= len; memcpy(*p, sig, len); if (*p - start < 1) { return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; } *--(*p) = 0; len += 1; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING)); // Write OID // if (pk_alg == MBEDTLS_PK_ECDSA) { /* * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and * https://www.rfc-editor.org/rfc/rfc5758#section-3. */ write_null_par = 0; } else { write_null_par = 1; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, 0, write_null_par)); return (int) len; } static int x509_write_extension(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *ext) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->val.p + 1, ext->val.len - 1)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->val.len - 1)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING)); if (ext->val.p[0] != 0) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(p, start, 1)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, ext->oid.p, ext->oid.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, ext->oid.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING * -- contains the DER encoding of an ASN.1 value * -- corresponding to the extension type identified * -- by extnID * } */ int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; mbedtls_asn1_named_data *cur_ext = first; while (cur_ext != NULL) { MBEDTLS_ASN1_CHK_ADD(len, x509_write_extension(p, start, cur_ext)); cur_ext = cur_ext->next; } return (int) len; } #endif /* MBEDTLS_X509_CREATE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509_crl.c000066400000000000000000000507601464416617300230550ustar00rootroot00000000000000/* * X.509 Certificate Revocation List (CRL) parsing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_CRL_PARSE_C) #include "mbedtls/x509_crl.h" #include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/platform.h" #if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #include #else #include #endif #endif #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include #endif /* * Version ::= INTEGER { v1(0), v2(1) } */ static int x509_crl_get_version(unsigned char **p, const unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { *ver = 0; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); } return 0; } /* * X.509 CRL v2 extensions * * We currently don't parse any extension's content, but we do check that the * list of extensions is well-formed and abort on critical extensions (that * are unsupported as we don't support any extension so far) */ static int x509_get_crl_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (*p == end) { return 0; } /* * crlExtensions [0] EXPLICIT Extensions OPTIONAL * -- if present, version MUST be v2 */ if ((ret = mbedtls_x509_get_ext(p, end, ext, 0)) != 0) { return ret; } end = ext->p + ext->len; while (*p < end) { /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING } */ int is_critical = 0; const unsigned char *end_ext_data; size_t len; /* Get enclosing sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_data = *p + len; /* Get OID (currently ignored) */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } *p += len; /* Get optional critical */ if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Data should be octet string type */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Ignore data so far and just check its length */ *p += len; if (*p != end_ext_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* Abort on (unsupported) critical extensions */ if (is_critical) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * X.509 CRL v2 entry extensions (no extensions parsed yet.) */ static int x509_get_crl_entry_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* OPTIONAL */ if (end <= *p) { return 0; } ext->tag = **p; ext->p = *p; /* * Get CRL-entry extension sequence header * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 */ if ((ret = mbedtls_asn1_get_tag(p, end, &ext->len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { ext->p = NULL; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end = *p + ext->len; if (end != *p + ext->len) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } while (*p < end) { if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } *p += len; } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * X.509 CRL Entries */ static int x509_get_entries(unsigned char **p, const unsigned char *end, mbedtls_x509_crl_entry *entry) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t entry_len; mbedtls_x509_crl_entry *cur_entry = entry; if (*p == end) { return 0; } if ((ret = mbedtls_asn1_get_tag(p, end, &entry_len, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return 0; } return ret; } end = *p + entry_len; while (*p < end) { size_t len2; const unsigned char *end2; cur_entry->raw.tag = **p; if ((ret = mbedtls_asn1_get_tag(p, end, &len2, MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED)) != 0) { return ret; } cur_entry->raw.p = *p; cur_entry->raw.len = len2; end2 = *p + len2; if ((ret = mbedtls_x509_get_serial(p, end2, &cur_entry->serial)) != 0) { return ret; } if ((ret = mbedtls_x509_get_time(p, end2, &cur_entry->revocation_date)) != 0) { return ret; } if ((ret = x509_get_crl_entry_ext(p, end2, &cur_entry->entry_ext)) != 0) { return ret; } if (*p < end) { cur_entry->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl_entry)); if (cur_entry->next == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } cur_entry = cur_entry->next; } } return 0; } /* * Parse one CRLs in DER format and append it to the chained list */ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p = NULL, *end = NULL; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; mbedtls_x509_crl *crl = chain; /* * Check for valid input */ if (crl == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); /* * Add new CRL on the end of the chain if needed. */ while (crl->version != 0 && crl->next != NULL) { crl = crl->next; } if (crl->version != 0 && crl->next == NULL) { crl->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crl)); if (crl->next == NULL) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_ALLOC_FAILED; } mbedtls_x509_crl_init(crl->next); crl = crl->next; } /* * Copy raw DER-encoded CRL */ if (buflen == 0) { return MBEDTLS_ERR_X509_INVALID_FORMAT; } p = mbedtls_calloc(1, buflen); if (p == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } memcpy(p, buf, buflen); crl->raw.p = p; crl->raw.len = buflen; end = p + buflen; /* * CertificateList ::= SEQUENCE { * tbsCertList TBSCertList, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_INVALID_FORMAT; } if (len != (size_t) (end - p)) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * TBSCertList ::= SEQUENCE { */ crl->tbs.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = p + len; crl->tbs.len = (size_t) (end - crl->tbs.p); /* * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } * -- if present, MUST be v2 * * signature AlgorithmIdentifier */ if ((ret = x509_crl_get_version(&p, end, &crl->version)) != 0 || (ret = mbedtls_x509_get_alg(&p, end, &crl->sig_oid, &sig_params1)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if (crl->version < 0 || crl->version > 1) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_UNKNOWN_VERSION; } crl->version++; if ((ret = mbedtls_x509_get_sig_alg(&crl->sig_oid, &sig_params1, &crl->sig_md, &crl->sig_pk, &crl->sig_opts)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG; } /* * issuer Name */ crl->issuer_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = mbedtls_x509_get_name(&p, p + len, &crl->issuer)) != 0) { mbedtls_x509_crl_free(crl); return ret; } crl->issuer_raw.len = (size_t) (p - crl->issuer_raw.p); /* * thisUpdate Time * nextUpdate Time OPTIONAL */ if ((ret = mbedtls_x509_get_time(&p, end, &crl->this_update)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if ((ret = mbedtls_x509_get_time(&p, end, &crl->next_update)) != 0) { if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) && ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_OUT_OF_DATA))) { mbedtls_x509_crl_free(crl); return ret; } } /* * revokedCertificates SEQUENCE OF SEQUENCE { * userCertificate CertificateSerialNumber, * revocationDate Time, * crlEntryExtensions Extensions OPTIONAL * -- if present, MUST be v2 * } OPTIONAL */ if ((ret = x509_get_entries(&p, end, &crl->entry)) != 0) { mbedtls_x509_crl_free(crl); return ret; } /* * crlExtensions EXPLICIT Extensions OPTIONAL * -- if present, MUST be v2 */ if (crl->version == 2) { ret = x509_get_crl_ext(&p, end, &crl->crl_ext); if (ret != 0) { mbedtls_x509_crl_free(crl); return ret; } } if (p != end) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } end = crl->raw.p + crl->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if (crl->sig_oid.len != sig_oid2.len || memcmp(crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len) != 0 || sig_params1.len != sig_params2.len || (sig_params1.len != 0 && memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERR_X509_SIG_MISMATCH; } if ((ret = mbedtls_x509_get_sig(&p, end, &crl->sig)) != 0) { mbedtls_x509_crl_free(crl); return ret; } if (p != end) { mbedtls_x509_crl_free(crl); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse one or more CRLs and add them to the chained list */ int mbedtls_x509_crl_parse(mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen) { #if defined(MBEDTLS_PEM_PARSE_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t use_len = 0; mbedtls_pem_context pem; int is_pem = 0; if (chain == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } do { mbedtls_pem_init(&pem); // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated // string if (buflen == 0 || buf[buflen - 1] != '\0') { ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; } else { ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN X509 CRL-----", "-----END X509 CRL-----", buf, NULL, 0, &use_len); } if (ret == 0) { /* * Was PEM encoded */ is_pem = 1; buflen -= use_len; buf += use_len; if ((ret = mbedtls_x509_crl_parse_der(chain, pem.buf, pem.buflen)) != 0) { mbedtls_pem_free(&pem); return ret; } } else if (is_pem) { mbedtls_pem_free(&pem); return ret; } mbedtls_pem_free(&pem); } /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. * And a valid CRL cannot be less than 1 byte anyway. */ while (is_pem && buflen > 1); if (is_pem) { return 0; } else #endif /* MBEDTLS_PEM_PARSE_C */ return mbedtls_x509_crl_parse_der(chain, buf, buflen); } #if defined(MBEDTLS_FS_IO) /* * Load one or more CRLs and add them to the chained list */ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_x509_crl_parse(chain, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) /* * Return an informational string about the certificate. */ #define BEFORE_COLON 14 #define BC "14" /* * Return an informational string about the CRL. */ int mbedtls_x509_crl_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crl *crl) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; char *p; const mbedtls_x509_crl_entry *entry; p = buf; n = size; ret = mbedtls_snprintf(p, n, "%sCRL version : %d", prefix, crl->version); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &crl->issuer); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sthis update : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crl->this_update.year, crl->this_update.mon, crl->this_update.day, crl->this_update.hour, crl->this_update.min, crl->this_update.sec); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%snext update : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crl->next_update.year, crl->next_update.mon, crl->next_update.day, crl->next_update.hour, crl->next_update.min, crl->next_update.sec); MBEDTLS_X509_SAFE_SNPRINTF; entry = &crl->entry; ret = mbedtls_snprintf(p, n, "\n%sRevoked certificates:", prefix); MBEDTLS_X509_SAFE_SNPRINTF; while (entry != NULL && entry->raw.len != 0) { ret = mbedtls_snprintf(p, n, "\n%sserial number: ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_serial_gets(p, n, &entry->serial); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, " revocation date: " \ "%04d-%02d-%02d %02d:%02d:%02d", entry->revocation_date.year, entry->revocation_date.mon, entry->revocation_date.day, entry->revocation_date.hour, entry->revocation_date.min, entry->revocation_date.sec); MBEDTLS_X509_SAFE_SNPRINTF; entry = entry->next; } ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_sig_alg_gets(p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, crl->sig_opts); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n"); MBEDTLS_X509_SAFE_SNPRINTF; return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Initialize a CRL chain */ void mbedtls_x509_crl_init(mbedtls_x509_crl *crl) { memset(crl, 0, sizeof(mbedtls_x509_crl)); } /* * Unallocate all CRL data */ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl) { mbedtls_x509_crl *crl_cur = crl; mbedtls_x509_crl *crl_prv; mbedtls_x509_crl_entry *entry_cur; mbedtls_x509_crl_entry *entry_prv; while (crl_cur != NULL) { #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(crl_cur->sig_opts); #endif mbedtls_asn1_free_named_data_list_shallow(crl_cur->issuer.next); entry_cur = crl_cur->entry.next; while (entry_cur != NULL) { entry_prv = entry_cur; entry_cur = entry_cur->next; mbedtls_zeroize_and_free(entry_prv, sizeof(mbedtls_x509_crl_entry)); } if (crl_cur->raw.p != NULL) { mbedtls_zeroize_and_free(crl_cur->raw.p, crl_cur->raw.len); } crl_prv = crl_cur; crl_cur = crl_cur->next; mbedtls_platform_zeroize(crl_prv, sizeof(mbedtls_x509_crl)); if (crl_prv != crl) { mbedtls_free(crl_prv); } } } #endif /* MBEDTLS_X509_CRL_PARSE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509_crt.c000066400000000000000000003127161464416617300230670ustar00rootroot00000000000000/* * X.509 certificate parsing and verification * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf * * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf */ #include "common.h" #if defined(MBEDTLS_X509_CRT_PARSE_C) #include "mbedtls/x509_crt.h" #include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include "pk_internal.h" #include "mbedtls/platform.h" #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif #if defined(MBEDTLS_HAVE_TIME) #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) #define WIN32_LEAN_AND_MEAN #include #else #include #endif #endif #if defined(MBEDTLS_FS_IO) #include #if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) #include #include #if defined(__MBED__) #include #else #include #endif /* __MBED__ */ #include #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif /* * Item in a verification chain: cert and flags for it */ typedef struct { mbedtls_x509_crt *crt; uint32_t flags; } x509_crt_verify_chain_item; /* * Max size of verification chain: end-entity + intermediates + trusted root */ #define X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) /* Default profile. Do not remove items unless there are serious security * concerns. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { /* Hashes from SHA-256 and above. Note that this selection * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 0xFFFFFFF, /* Any PK alg */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Curves at or above 128-bit security level. Note that this selection * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | 0, #else /* MBEDTLS_PK_HAVE_ECC_KEYS */ 0, #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 2048, }; /* Next-generation profile. Currently identical to the default, but may * be tightened at any time. */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = { /* Hashes from SHA-256 and above. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 0xFFFFFFF, /* Any PK alg */ #if defined(MBEDTLS_ECP_C) /* Curves at or above 128-bit security level. */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1), #else 0, #endif 2048, }; /* * NSA Suite B Profile */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = { /* Only SHA-256 and 384 */ MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384), /* Only ECDSA */ MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) | MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* Only NIST P-256 and P-384 */ MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), #else /* MBEDTLS_PK_HAVE_ECC_KEYS */ 0, #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ 0, }; /* * Empty / all-forbidden profile */ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = { 0, 0, 0, (uint32_t) -1, }; /* * Check md_alg against profile * Return 0 if md_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, mbedtls_md_type_t md_alg) { if (md_alg == MBEDTLS_MD_NONE) { return -1; } if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) { return 0; } return -1; } /* * Check pk_alg against profile * Return 0 if pk_alg is acceptable for this profile, -1 otherwise */ static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, mbedtls_pk_type_t pk_alg) { if (pk_alg == MBEDTLS_PK_NONE) { return -1; } if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) { return 0; } return -1; } /* * Check key against profile * Return 0 if pk is acceptable for this profile, -1 otherwise */ static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, const mbedtls_pk_context *pk) { const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk); #if defined(MBEDTLS_RSA_C) if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) { if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) { return 0; } return -1; } #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) if (pk_alg == MBEDTLS_PK_ECDSA || pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { const mbedtls_ecp_group_id gid = mbedtls_pk_get_ec_group_id(pk); if (gid == MBEDTLS_ECP_DP_NONE) { return -1; } if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) { return 0; } return -1; } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ return -1; } /* * Like memcmp, but case-insensitive and always returns -1 if different */ static int x509_memcasecmp(const void *s1, const void *s2, size_t len) { size_t i; unsigned char diff; const unsigned char *n1 = s1, *n2 = s2; for (i = 0; i < len; i++) { diff = n1[i] ^ n2[i]; if (diff == 0) { continue; } if (diff == 32 && ((n1[i] >= 'a' && n1[i] <= 'z') || (n1[i] >= 'A' && n1[i] <= 'Z'))) { continue; } return -1; } return 0; } /* * Return 0 if name matches wildcard, -1 otherwise */ static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name) { size_t i; size_t cn_idx = 0, cn_len = strlen(cn); /* We can't have a match if there is no wildcard to match */ if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') { return -1; } for (i = 0; i < cn_len; ++i) { if (cn[i] == '.') { cn_idx = i; break; } } if (cn_idx == 0) { return -1; } if (cn_len - cn_idx == name->len - 1 && x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) { return 0; } return -1; } /* * Compare two X.509 strings, case-insensitive, and allowing for some encoding * variations (but not all). * * Return 0 if equal, -1 otherwise. */ static int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b) { if (a->tag == b->tag && a->len == b->len && memcmp(a->p, b->p, b->len) == 0) { return 0; } if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && a->len == b->len && x509_memcasecmp(a->p, b->p, b->len) == 0) { return 0; } return -1; } /* * Compare two X.509 Names (aka rdnSequence). * * See RFC 5280 section 7.1, though we don't implement the whole algorithm: * we sometimes return unequal when the full algorithm would return equal, * but never the other way. (In particular, we don't do Unicode normalisation * or space folding.) * * Return 0 if equal, -1 otherwise. */ static int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b) { /* Avoid recursion, it might not be optimised by the compiler */ while (a != NULL || b != NULL) { if (a == NULL || b == NULL) { return -1; } /* type */ if (a->oid.tag != b->oid.tag || a->oid.len != b->oid.len || memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) { return -1; } /* value */ if (x509_string_cmp(&a->val, &b->val) != 0) { return -1; } /* structure of the list of sets */ if (a->next_merged != b->next_merged) { return -1; } a = a->next; b = b->next; } /* a == NULL == b */ return 0; } /* * Reset (init or clear) a verify_chain */ static void x509_crt_verify_chain_reset( mbedtls_x509_crt_verify_chain *ver_chain) { size_t i; for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) { ver_chain->items[i].crt = NULL; ver_chain->items[i].flags = (uint32_t) -1; } ver_chain->len = 0; #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) ver_chain->trust_ca_cb_result = NULL; #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ static int x509_get_version(unsigned char **p, const unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { *ver = 0; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = *p + len; if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ static int x509_get_dates(unsigned char **p, const unsigned char *end, mbedtls_x509_time *from, mbedtls_x509_time *to) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); } end = *p + len; if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) { return ret; } if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) { return ret; } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * X.509 v2/v3 unique identifier (not parsed) */ static int x509_get_uid(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *uid, int n) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if (*p == end) { return 0; } uid->tag = **p; if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } uid->p = *p; *p += uid->len; return 0; } static int x509_get_basic_constraints(unsigned char **p, const unsigned char *end, int *ca_istrue, int *max_pathlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; /* * BasicConstraints ::= SEQUENCE { * cA BOOLEAN DEFAULT FALSE, * pathLenConstraint INTEGER (0..MAX) OPTIONAL } */ *ca_istrue = 0; /* DEFAULT FALSE */ *max_pathlen = 0; /* endless */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p == end) { return 0; } if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { ret = mbedtls_asn1_get_int(p, end, ca_istrue); } if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*ca_istrue != 0) { *ca_istrue = 1; } } if (*p == end) { return 0; } if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer * overflow, which is an undefined behavior. */ if (*max_pathlen == INT_MAX) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } (*max_pathlen)++; return 0; } /* * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId * * KeyPurposeId ::= OBJECT IDENTIFIER */ static int x509_get_ext_key_usage(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *ext_key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Sequence length must be >= 1 */ if (ext_key_usage->buf.p == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH); } return 0; } /* * SubjectKeyIdentifier ::= KeyIdentifier * * KeyIdentifier ::= OCTET STRING */ static int x509_get_subject_key_id(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *subject_key_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0u; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } subject_key_id->len = len; subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING; subject_key_id->p = *p; *p += len; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * AuthorityKeyIdentifier ::= SEQUENCE { * keyIdentifier [0] KeyIdentifier OPTIONAL, * authorityCertIssuer [1] GeneralNames OPTIONAL, * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } * * KeyIdentifier ::= OCTET STRING */ static int x509_get_authority_key_id(unsigned char **p, unsigned char *end, mbedtls_x509_authority *authority_key_id) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0u; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC); /* KeyIdentifier is an OPTIONAL field */ if (ret == 0) { authority_key_id->keyIdentifier.len = len; authority_key_id->keyIdentifier.p = *p; /* Setting tag of the keyIdentfier intentionally to 0x04. * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL), * its tag with the content is the payload of on OCTET STRING primitive */ authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; *p += len; } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p < end) { /* Getting authorityCertIssuer using the required specific class tag [1] */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1)) != 0) { /* authorityCertIssuer and authorityCertSerialNumber MUST both be present or both be absent. At this point we expect to have both. */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* "end" also includes the CertSerialNumber field so "len" shall be used */ ret = mbedtls_x509_get_subject_alt_name_ext(p, (*p+len), &authority_key_id->authorityCertIssuer); if (ret != 0) { return ret; } /* Getting authorityCertSerialNumber using the required specific class tag [2] */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } authority_key_id->authorityCertSerialNumber.len = len; authority_key_id->authorityCertSerialNumber.p = *p; authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER; *p += len; } if (*p != end) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } return 0; } /* * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } * * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } * * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation * * PolicyInformation ::= SEQUENCE { * policyIdentifier CertPolicyId, * policyQualifiers SEQUENCE SIZE (1..MAX) OF * PolicyQualifierInfo OPTIONAL } * * CertPolicyId ::= OBJECT IDENTIFIER * * PolicyQualifierInfo ::= SEQUENCE { * policyQualifierId PolicyQualifierId, * qualifier ANY DEFINED BY policyQualifierId } * * -- policyQualifierIds for Internet policy qualifiers * * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } * * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) * * Qualifier ::= CHOICE { * cPSuri CPSuri, * userNotice UserNotice } * * CPSuri ::= IA5String * * UserNotice ::= SEQUENCE { * noticeRef NoticeReference OPTIONAL, * explicitText DisplayText OPTIONAL } * * NoticeReference ::= SEQUENCE { * organization DisplayText, * noticeNumbers SEQUENCE OF INTEGER } * * DisplayText ::= CHOICE { * ia5String IA5String (SIZE (1..200)), * visibleString VisibleString (SIZE (1..200)), * bmpString BMPString (SIZE (1..200)), * utf8String UTF8String (SIZE (1..200)) } * * NOTE: we only parse and use anyPolicy without qualifiers at this point * as defined in RFC 5280. */ static int x509_get_certificate_policies(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *certificate_policies) { int ret, parse_ret = 0; size_t len; mbedtls_asn1_buf *buf; mbedtls_asn1_sequence *cur = certificate_policies; /* Get main sequence tag */ ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); if (ret != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if (*p + len != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Cannot be an empty sequence. */ if (len == 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } while (*p < end) { mbedtls_x509_buf policy_oid; const unsigned char *policy_end; /* * Get the policy sequence */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } policy_end = *p + len; if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } policy_oid.tag = MBEDTLS_ASN1_OID; policy_oid.len = len; policy_oid.p = *p; /* * Only AnyPolicy is currently supported when enforcing policy. */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) { /* * Set the parsing return code but continue parsing, in case this * extension is critical. */ parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } /* Allocate and assign next pointer */ if (cur->buf.p != NULL) { if (cur->next != NULL) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); if (cur->next == NULL) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_ALLOC_FAILED); } cur = cur->next; } buf = &(cur->buf); buf->tag = policy_oid.tag; buf->p = policy_oid.p; buf->len = policy_oid.len; *p += len; /* * If there is an optional qualifier, then *p < policy_end * Check the Qualifier len to verify it doesn't exceed policy_end. */ if (*p < policy_end) { if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* * Skip the optional policy qualifiers. */ *p += len; } if (*p != policy_end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } /* Set final sequence entry's next pointer to NULL */ cur->next = NULL; if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return parse_ret; } /* * X.509 v3 extensions * */ static int x509_get_crt_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_crt *crt, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; if (*p == end) { return 0; } if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) { return ret; } end = crt->v3_ext.p + crt->v3_ext.len; while (*p < end) { /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING } */ mbedtls_x509_buf extn_oid = { 0, 0, NULL }; int is_critical = 0; /* DEFAULT FALSE */ int ext_type = 0; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_data = *p + len; /* Get extension ID */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } extn_oid.tag = MBEDTLS_ASN1_OID; extn_oid.p = *p; *p += extn_oid.len; /* Get optional critical */ if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Data should be octet string type */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } start_ext_octet = *p; end_ext_octet = *p + len; if (end_ext_octet != end_ext_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Detect supported extensions */ ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); if (ret != 0) { /* Give the callback (if any) a chance to handle the extension */ if (cb != NULL) { ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet); if (ret != 0 && is_critical) { return ret; } *p = end_ext_octet; continue; } /* No parser found, skip extension */ *p = end_ext_octet; if (is_critical) { /* Data is marked as critical: fail */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } continue; } /* Forbid repeated extensions */ if ((crt->ext_types & ext_type) != 0) { return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } crt->ext_types |= ext_type; switch (ext_type) { case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: /* Parse basic constraints */ if ((ret = x509_get_basic_constraints(p, end_ext_octet, &crt->ca_istrue, &crt->max_pathlen)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_KEY_USAGE: /* Parse key usage */ if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet, &crt->key_usage)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: /* Parse extended key usage */ if ((ret = x509_get_ext_key_usage(p, end_ext_octet, &crt->ext_key_usage)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER: /* Parse subject key identifier */ if ((ret = x509_get_subject_key_id(p, end_ext_data, &crt->subject_key_id)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER: /* Parse authority key identifier */ if ((ret = x509_get_authority_key_id(p, end_ext_octet, &crt->authority_key_id)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: /* Parse subject alt name * SubjectAltName ::= GeneralNames */ if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet, &crt->subject_alt_names)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_NS_CERT_TYPE: /* Parse netscape certificate type */ if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet, &crt->ns_cert_type)) != 0) { return ret; } break; case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: /* Parse certificate policies type */ if ((ret = x509_get_certificate_policies(p, end_ext_octet, &crt->certificate_policies)) != 0) { /* Give the callback (if any) a chance to handle the extension * if it contains unsupported policies */ if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && cb(p_ctx, crt, &extn_oid, is_critical, start_ext_octet, end_ext_octet) == 0) { break; } if (is_critical) { return ret; } else /* * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we * cannot interpret or enforce the policy. However, it is up to * the user to choose how to enforce the policies, * unless the extension is critical. */ if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { return ret; } } break; default: /* * If this is a non-critical extension, which the oid layer * supports, but there isn't an x509 parser for it, * skip the extension. */ if (is_critical) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } else { *p = end_ext_octet; } } } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse and fill a single X.509 certificate in DER format */ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p, *end, *crt_end; mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); /* * Check for valid input */ if (crt == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } /* Use the original buffer until we figure out actual length. */ p = (unsigned char *) buf; len = buflen; end = p + len; /* * Certificate ::= SEQUENCE { * tbsCertificate TBSCertificate, * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERR_X509_INVALID_FORMAT; } end = crt_end = p + len; crt->raw.len = (size_t) (crt_end - buf); if (make_copy != 0) { /* Create and populate a new buffer for the raw field. */ crt->raw.p = p = mbedtls_calloc(1, crt->raw.len); if (crt->raw.p == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } memcpy(crt->raw.p, buf, crt->raw.len); crt->own_buffer = 1; p += crt->raw.len - len; end = crt_end = p + len; } else { crt->raw.p = (unsigned char *) buf; crt->own_buffer = 0; } /* * TBSCertificate ::= SEQUENCE { */ crt->tbs.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = p + len; crt->tbs.len = (size_t) (end - crt->tbs.p); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } * * CertificateSerialNumber ::= INTEGER * * signature AlgorithmIdentifier */ if ((ret = x509_get_version(&p, end, &crt->version)) != 0 || (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 || (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid, &sig_params1)) != 0) { mbedtls_x509_crt_free(crt); return ret; } if (crt->version < 0 || crt->version > 2) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERR_X509_UNKNOWN_VERSION; } crt->version++; if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1, &crt->sig_md, &crt->sig_pk, &crt->sig_opts)) != 0) { mbedtls_x509_crt_free(crt); return ret; } /* * issuer Name */ crt->issuer_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) { mbedtls_x509_crt_free(crt); return ret; } crt->issuer_raw.len = (size_t) (p - crt->issuer_raw.p); /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } * */ if ((ret = x509_get_dates(&p, end, &crt->valid_from, &crt->valid_to)) != 0) { mbedtls_x509_crt_free(crt); return ret; } /* * subject Name */ crt->subject_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) { mbedtls_x509_crt_free(crt); return ret; } crt->subject_raw.len = (size_t) (p - crt->subject_raw.p); /* * SubjectPublicKeyInfo */ crt->pk_raw.p = p; if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) { mbedtls_x509_crt_free(crt); return ret; } crt->pk_raw.len = (size_t) (p - crt->pk_raw.p); /* * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, * -- If present, version shall be v2 or v3 * extensions [3] EXPLICIT Extensions OPTIONAL * -- If present, version shall be v3 */ if (crt->version == 2 || crt->version == 3) { ret = x509_get_uid(&p, end, &crt->issuer_id, 1); if (ret != 0) { mbedtls_x509_crt_free(crt); return ret; } } if (crt->version == 2 || crt->version == 3) { ret = x509_get_uid(&p, end, &crt->subject_id, 2); if (ret != 0) { mbedtls_x509_crt_free(crt); return ret; } } if (crt->version == 3) { ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx); if (ret != 0) { mbedtls_x509_crt_free(crt); return ret; } } if (p != end) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } end = crt_end; /* * } * -- end of TBSCertificate * * signatureAlgorithm AlgorithmIdentifier, * signatureValue BIT STRING */ if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { mbedtls_x509_crt_free(crt); return ret; } if (crt->sig_oid.len != sig_oid2.len || memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 || sig_params1.tag != sig_params2.tag || sig_params1.len != sig_params2.len || (sig_params1.len != 0 && memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERR_X509_SIG_MISMATCH; } if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) { mbedtls_x509_crt_free(crt); return ret; } if (p != end) { mbedtls_x509_crt_free(crt); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse one X.509 certificate in DER format from a buffer and add them to a * chained list */ static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *crt = chain, *prev = NULL; /* * Check for valid input */ if (crt == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } while (crt->version != 0 && crt->next != NULL) { prev = crt; crt = crt->next; } /* * Add new certificate on the end of the chain if needed. */ if (crt->version != 0 && crt->next == NULL) { crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); if (crt->next == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } prev = crt; mbedtls_x509_crt_init(crt->next); crt = crt->next; } ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx); if (ret != 0) { if (prev) { prev->next = NULL; } if (crt != chain) { mbedtls_free(crt); } return ret; } return 0; } int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen) { return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL); } int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen, int make_copy, mbedtls_x509_crt_ext_cb_t cb, void *p_ctx) { return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx); } int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen) { return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL); } /* * Parse one or more PEM certificates from a buffer and add them to the chained * list */ int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen) { #if defined(MBEDTLS_PEM_PARSE_C) int success = 0, first_error = 0, total_failed = 0; int buf_format = MBEDTLS_X509_FORMAT_DER; #endif /* * Check for valid input */ if (chain == NULL || buf == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } /* * Determine buffer content. Buffer contains either one DER certificate or * one or more PEM certificates. */ #if defined(MBEDTLS_PEM_PARSE_C) if (buflen != 0 && buf[buflen - 1] == '\0' && strstr((const char *) buf, "-----BEGIN CERTIFICATE-----") != NULL) { buf_format = MBEDTLS_X509_FORMAT_PEM; } if (buf_format == MBEDTLS_X509_FORMAT_DER) { return mbedtls_x509_crt_parse_der(chain, buf, buflen); } #else return mbedtls_x509_crt_parse_der(chain, buf, buflen); #endif #if defined(MBEDTLS_PEM_PARSE_C) if (buf_format == MBEDTLS_X509_FORMAT_PEM) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_pem_context pem; /* 1 rather than 0 since the terminating NULL byte is counted in */ while (buflen > 1) { size_t use_len; mbedtls_pem_init(&pem); /* If we get there, we know the string is null-terminated */ ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----", buf, NULL, 0, &use_len); if (ret == 0) { /* * Was PEM encoded */ buflen -= use_len; buf += use_len; } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) { return ret; } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { mbedtls_pem_free(&pem); /* * PEM header and footer were found */ buflen -= use_len; buf += use_len; if (first_error == 0) { first_error = ret; } total_failed++; continue; } else { break; } ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen); mbedtls_pem_free(&pem); if (ret != 0) { /* * Quit parsing on a memory error */ if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) { return ret; } if (first_error == 0) { first_error = ret; } total_failed++; continue; } success = 1; } } if (success) { return total_failed; } else if (first_error) { return first_error; } else { return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT; } #endif /* MBEDTLS_PEM_PARSE_C */ } #if defined(MBEDTLS_FS_IO) /* * Load one or more certificates and add them to the chained list */ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_x509_crt_parse(chain, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) { int ret = 0; #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) int w_ret; WCHAR szDir[MAX_PATH]; char filename[MAX_PATH]; char *p; size_t len = strlen(path); WIN32_FIND_DATAW file_data; HANDLE hFind; if (len > MAX_PATH - 3) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } memset(szDir, 0, sizeof(szDir)); memset(filename, 0, MAX_PATH); memcpy(filename, path, len); filename[len++] = '\\'; p = filename + len; filename[len++] = '*'; /* * Note this function uses the code page CP_ACP which is the system default * ANSI codepage. The input string is always described in BYTES and the * output length is described in WCHARs. */ w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir, MAX_PATH - 3); if (w_ret == 0) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } hFind = FindFirstFileW(szDir, &file_data); if (hFind == INVALID_HANDLE_VALUE) { return MBEDTLS_ERR_X509_FILE_IO_ERROR; } len = MAX_PATH - len; do { memset(p, 0, len); if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; } w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, -1, p, (int) len, NULL, NULL); if (w_ret == 0) { ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; goto cleanup; } w_ret = mbedtls_x509_crt_parse_file(chain, filename); if (w_ret < 0) { ret++; } else { ret += w_ret; } } while (FindNextFileW(hFind, &file_data) != 0); if (GetLastError() != ERROR_NO_MORE_FILES) { ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; } cleanup: FindClose(hFind); #else /* _WIN32 */ int t_ret; int snp_ret; struct stat sb; struct dirent *entry; char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; DIR *dir = opendir(path); if (dir == NULL) { return MBEDTLS_ERR_X509_FILE_IO_ERROR; } #if defined(MBEDTLS_THREADING_C) if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) { closedir(dir); return ret; } #endif /* MBEDTLS_THREADING_C */ memset(&sb, 0, sizeof(sb)); while ((entry = readdir(dir)) != NULL) { snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name), "%s/%s", path, entry->d_name); if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) { ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; goto cleanup; } else if (stat(entry_name, &sb) == -1) { if (errno == ENOENT) { /* Broken symbolic link - ignore this entry. stat(2) will return this error for either (a) a dangling symlink or (b) a missing file. Given that we have just obtained the filename from readdir, assume that it does exist and therefore treat this as a dangling symlink. */ continue; } else { /* Some other file error; report the error. */ ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; goto cleanup; } } if (!S_ISREG(sb.st_mode)) { continue; } // Ignore parse errors // t_ret = mbedtls_x509_crt_parse_file(chain, entry_name); if (t_ret < 0) { ret++; } else { ret += t_ret; } } cleanup: closedir(dir); #if defined(MBEDTLS_THREADING_C) if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) { ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } #endif /* MBEDTLS_THREADING_C */ #endif /* _WIN32 */ return ret; } #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) #define PRINT_ITEM(i) \ do { \ ret = mbedtls_snprintf(p, n, "%s" i, sep); \ MBEDTLS_X509_SAFE_SNPRINTF; \ sep = ", "; \ } while (0) #define CERT_TYPE(type, name) \ do { \ if (ns_cert_type & (type)) { \ PRINT_ITEM(name); \ } \ } while (0) #define KEY_USAGE(code, name) \ do { \ if (key_usage & (code)) { \ PRINT_ITEM(name); \ } \ } while (0) static int x509_info_ext_key_usage(char **buf, size_t *size, const mbedtls_x509_sequence *extended_key_usage) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *desc; size_t n = *size; char *p = *buf; const mbedtls_x509_sequence *cur = extended_key_usage; const char *sep = ""; while (cur != NULL) { if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) { desc = "???"; } ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); MBEDTLS_X509_SAFE_SNPRINTF; sep = ", "; cur = cur->next; } *size = n; *buf = p; return 0; } static int x509_info_cert_policies(char **buf, size_t *size, const mbedtls_x509_sequence *certificate_policies) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *desc; size_t n = *size; char *p = *buf; const mbedtls_x509_sequence *cur = certificate_policies; const char *sep = ""; while (cur != NULL) { if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) { desc = "???"; } ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); MBEDTLS_X509_SAFE_SNPRINTF; sep = ", "; cur = cur->next; } *size = n; *buf = p; return 0; } /* * Return an informational string about the certificate. */ #define BEFORE_COLON 18 #define BC "18" int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_crt *crt) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; char *p; char key_size_str[BEFORE_COLON]; p = buf; n = size; if (NULL == crt) { ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n"); MBEDTLS_X509_SAFE_SNPRINTF; return (int) (size - n); } ret = mbedtls_snprintf(p, n, "%scert. version : %d\n", prefix, crt->version); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "%sserial number : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_serial_gets(p, n, &crt->serial); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &crt->issuer); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &crt->subject); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sissued on : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crt->valid_from.year, crt->valid_from.mon, crt->valid_from.day, crt->valid_from.hour, crt->valid_from.min, crt->valid_from.sec); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%sexpires on : " \ "%04d-%02d-%02d %02d:%02d:%02d", prefix, crt->valid_to.year, crt->valid_to.mon, crt->valid_to.day, crt->valid_to.hour, crt->valid_to.min, crt->valid_to.sec); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk, crt->sig_md, crt->sig_opts); MBEDTLS_X509_SAFE_SNPRINTF; /* Key size */ if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON, mbedtls_pk_get_name(&crt->pk))) != 0) { return ret; } ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, (int) mbedtls_pk_get_bitlen(&crt->pk)); MBEDTLS_X509_SAFE_SNPRINTF; /* * Optional extensions */ if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) { ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix, crt->ca_istrue ? "true" : "false"); MBEDTLS_X509_SAFE_SNPRINTF; if (crt->max_pathlen > 0) { ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1); MBEDTLS_X509_SAFE_SNPRINTF; } } if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, &crt->subject_alt_names, prefix)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) { ret = mbedtls_snprintf(p, n, "\n%sext key usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = x509_info_ext_key_usage(&p, &n, &crt->ext_key_usage)) != 0) { return ret; } } if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) { ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = x509_info_cert_policies(&p, &n, &crt->certificate_policies)) != 0) { return ret; } } ret = mbedtls_snprintf(p, n, "\n"); MBEDTLS_X509_SAFE_SNPRINTF; return (int) (size - n); } struct x509_crt_verify_string { int code; const char *string; }; #define X509_CRT_ERROR_INFO(err, err_str, info) { err, info }, static const struct x509_crt_verify_string x509_crt_verify_strings[] = { MBEDTLS_X509_CRT_ERROR_INFO_LIST { 0, NULL } }; #undef X509_CRT_ERROR_INFO int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, uint32_t flags) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const struct x509_crt_verify_string *cur; char *p = buf; size_t n = size; for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) { if ((flags & cur->code) == 0) { continue; } ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string); MBEDTLS_X509_SAFE_SNPRINTF; flags ^= cur->code; } if (flags != 0) { ret = mbedtls_snprintf(p, n, "%sUnknown reason " "(this should not happen)\n", prefix); MBEDTLS_X509_SAFE_SNPRINTF; } return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, unsigned int usage) { unsigned int usage_must, usage_may; unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY | MBEDTLS_X509_KU_DECIPHER_ONLY; if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) { return 0; } usage_must = usage & ~may_mask; if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } usage_may = usage & may_mask; if (((crt->key_usage & may_mask) | usage_may) != usage_may) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } return 0; } int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, const char *usage_oid, size_t usage_len) { const mbedtls_x509_sequence *cur; /* Extension is not mandatory, absent means no restriction */ if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) { return 0; } /* * Look for the requested usage (or wildcard ANY) in our list */ for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) { const mbedtls_x509_buf *cur_oid = &cur->buf; if (cur_oid->len == usage_len && memcmp(cur_oid->p, usage_oid, usage_len) == 0) { return 0; } if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) { return 0; } } return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } #if defined(MBEDTLS_X509_CRL_PARSE_C) /* * Return 1 if the certificate is revoked, or 0 otherwise. */ int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl) { const mbedtls_x509_crl_entry *cur = &crl->entry; while (cur != NULL && cur->serial.len != 0) { if (crt->serial.len == cur->serial.len && memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) { return 1; } cur = cur->next; } return 0; } /* * Check that the given certificate is not revoked according to the CRL. * Skip validation if no CRL for the given CA is present. */ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, mbedtls_x509_crl *crl_list, const mbedtls_x509_crt_profile *profile, const mbedtls_x509_time *now) { int flags = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t psa_algorithm; #else const mbedtls_md_info_t *md_info; #endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t hash_length; if (ca == NULL) { return flags; } while (crl_list != NULL) { if (crl_list->version == 0 || x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) { crl_list = crl_list->next; continue; } /* * Check if the CA is configured to sign CRLs */ if (mbedtls_x509_crt_check_key_usage(ca, MBEDTLS_X509_KU_CRL_SIGN) != 0) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } /* * Check if CRL is correctly signed by the trusted CA */ if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_MD; } if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { flags |= MBEDTLS_X509_BADCRL_BAD_PK; } #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md); if (psa_hash_compute(psa_algorithm, crl_list->tbs.p, crl_list->tbs.len, hash, sizeof(hash), &hash_length) != PSA_SUCCESS) { /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } #else md_info = mbedtls_md_info_from_type(crl_list->sig_md); hash_length = mbedtls_md_get_size(md_info); if (mbedtls_md(md_info, crl_list->tbs.p, crl_list->tbs.len, hash) != 0) { /* Note: this can't happen except after an internal error */ flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if (x509_profile_check_key(profile, &ca->pk) != 0) { flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk, crl_list->sig_md, hash, hash_length, crl_list->sig.p, crl_list->sig.len) != 0) { flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; break; } #if defined(MBEDTLS_HAVE_TIME_DATE) /* * Check for validity of CRL (Do not drop out) */ if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) { flags |= MBEDTLS_X509_BADCRL_EXPIRED; } if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) { flags |= MBEDTLS_X509_BADCRL_FUTURE; } #else ((void) now); #endif /* * Check if certificate is revoked */ if (mbedtls_x509_crt_is_revoked(crt, crl_list)) { flags |= MBEDTLS_X509_BADCERT_REVOKED; break; } crl_list = crl_list->next; } return flags; } #endif /* MBEDTLS_X509_CRL_PARSE_C */ /* * Check the signature of a certificate by its parent */ static int x509_crt_check_signature(const mbedtls_x509_crt *child, mbedtls_x509_crt *parent, mbedtls_x509_crt_restart_ctx *rs_ctx) { size_t hash_len; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if !defined(MBEDTLS_USE_PSA_CRYPTO) const mbedtls_md_info_t *md_info; md_info = mbedtls_md_info_from_type(child->sig_md); hash_len = mbedtls_md_get_size(md_info); /* Note: hash errors can happen only after an internal error */ if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) { return -1; } #else psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md); psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; status = psa_hash_compute(hash_alg, child->tbs.p, child->tbs.len, hash, sizeof(hash), &hash_len); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Skip expensive computation on obvious mismatch */ if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) { return -1; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) { return mbedtls_pk_verify_restartable(&parent->pk, child->sig_md, hash, hash_len, child->sig.p, child->sig.len, &rs_ctx->pk); } #else (void) rs_ctx; #endif return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk, child->sig_md, hash, hash_len, child->sig.p, child->sig.len); } /* * Check if 'parent' is a suitable parent (signing CA) for 'child'. * Return 0 if yes, -1 if not. * * top means parent is a locally-trusted certificate */ static int x509_crt_check_parent(const mbedtls_x509_crt *child, const mbedtls_x509_crt *parent, int top) { int need_ca_bit; /* Parent must be the issuer */ if (x509_name_cmp(&child->issuer, &parent->subject) != 0) { return -1; } /* Parent must have the basicConstraints CA bit set as a general rule */ need_ca_bit = 1; /* Exception: v1/v2 certificates that are locally trusted. */ if (top && parent->version < 3) { need_ca_bit = 0; } if (need_ca_bit && !parent->ca_istrue) { return -1; } if (need_ca_bit && mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { return -1; } return 0; } /* * Find a suitable parent for child in candidates, or return NULL. * * Here suitable is defined as: * 1. subject name matches child's issuer * 2. if necessary, the CA bit is set and key usage allows signing certs * 3. for trusted roots, the signature is correct * (for intermediates, the signature is checked and the result reported) * 4. pathlen constraints are satisfied * * If there's a suitable candidate which is also time-valid, return the first * such. Otherwise, return the first suitable candidate (or NULL if there is * none). * * The rationale for this rule is that someone could have a list of trusted * roots with two versions on the same root with different validity periods. * (At least one user reported having such a list and wanted it to just work.) * The reason we don't just require time-validity is that generally there is * only one version, and if it's expired we want the flags to state that * rather than NOT_TRUSTED, as would be the case if we required it here. * * The rationale for rule 3 (signature for trusted roots) is that users might * have two versions of the same CA with different keys in their list, and the * way we select the correct one is by checking the signature (as we don't * rely on key identifier extensions). (This is one way users might choose to * handle key rollover, another relies on self-issued certs, see [SIRO].) * * Arguments: * - [in] child: certificate for which we're looking for a parent * - [in] candidates: chained list of potential parents * - [out] r_parent: parent found (or NULL) * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top * of the chain, 0 otherwise * - [in] path_cnt: number of intermediates seen so far * - [in] self_cnt: number of self-signed intermediates seen so far * (will never be greater than path_cnt) * - [in-out] rs_ctx: context for restarting operations * * Return value: * - 0 on success * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise */ static int x509_crt_find_parent_in( mbedtls_x509_crt *child, mbedtls_x509_crt *candidates, mbedtls_x509_crt **r_parent, int *r_signature_is_good, int top, unsigned path_cnt, unsigned self_cnt, mbedtls_x509_crt_restart_ctx *rs_ctx, const mbedtls_x509_time *now) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *parent, *fallback_parent; int signature_is_good = 0, fallback_signature_is_good; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* did we have something in progress? */ if (rs_ctx != NULL && rs_ctx->parent != NULL) { /* restore saved state */ parent = rs_ctx->parent; fallback_parent = rs_ctx->fallback_parent; fallback_signature_is_good = rs_ctx->fallback_signature_is_good; /* clear saved state */ rs_ctx->parent = NULL; rs_ctx->fallback_parent = NULL; rs_ctx->fallback_signature_is_good = 0; /* resume where we left */ goto check_signature; } #endif fallback_parent = NULL; fallback_signature_is_good = 0; for (parent = candidates; parent != NULL; parent = parent->next) { /* basic parenting skills (name, CA bit, key usage) */ if (x509_crt_check_parent(child, parent, top) != 0) { continue; } /* +1 because stored max_pathlen is 1 higher that the actual value */ if (parent->max_pathlen > 0 && (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) { continue; } /* Signature */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) check_signature: #endif ret = x509_crt_check_signature(child, parent, rs_ctx); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { /* save state */ rs_ctx->parent = parent; rs_ctx->fallback_parent = fallback_parent; rs_ctx->fallback_signature_is_good = fallback_signature_is_good; return ret; } #else (void) ret; #endif signature_is_good = ret == 0; if (top && !signature_is_good) { continue; } #if defined(MBEDTLS_HAVE_TIME_DATE) /* optional time check */ if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 || /* past */ mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) { /* future */ if (fallback_parent == NULL) { fallback_parent = parent; fallback_signature_is_good = signature_is_good; } continue; } #else ((void) now); #endif *r_parent = parent; *r_signature_is_good = signature_is_good; break; } if (parent == NULL) { *r_parent = fallback_parent; *r_signature_is_good = fallback_signature_is_good; } return 0; } /* * Find a parent in trusted CAs or the provided chain, or return NULL. * * Searches in trusted CAs first, and return the first suitable parent found * (see find_parent_in() for definition of suitable). * * Arguments: * - [in] child: certificate for which we're looking for a parent, followed * by a chain of possible intermediates * - [in] trust_ca: list of locally trusted certificates * - [out] parent: parent found (or NULL) * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) * - [in] self_cnt: number of self-signed certs in the chain so far * (will always be no greater than path_cnt) * - [in-out] rs_ctx: context for restarting operations * * Return value: * - 0 on success * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise */ static int x509_crt_find_parent( mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, mbedtls_x509_crt **parent, int *parent_is_trusted, int *signature_is_good, unsigned path_cnt, unsigned self_cnt, mbedtls_x509_crt_restart_ctx *rs_ctx, const mbedtls_x509_time *now) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_x509_crt *search_list; *parent_is_trusted = 1; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* restore then clear saved state if we have some stored */ if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) { *parent_is_trusted = rs_ctx->parent_is_trusted; rs_ctx->parent_is_trusted = -1; } #endif while (1) { search_list = *parent_is_trusted ? trust_ca : child->next; ret = x509_crt_find_parent_in(child, search_list, parent, signature_is_good, *parent_is_trusted, path_cnt, self_cnt, rs_ctx, now); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { /* save state */ rs_ctx->parent_is_trusted = *parent_is_trusted; return ret; } #else (void) ret; #endif /* stop here if found or already in second iteration */ if (*parent != NULL || *parent_is_trusted == 0) { break; } /* prepare second iteration */ *parent_is_trusted = 0; } /* extra precaution against mistakes in the caller */ if (*parent == NULL) { *parent_is_trusted = 0; *signature_is_good = 0; } return 0; } /* * Check if an end-entity certificate is locally trusted * * Currently we require such certificates to be self-signed (actually only * check for self-issued as self-signatures are not checked) */ static int x509_crt_check_ee_locally_trusted( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca) { mbedtls_x509_crt *cur; /* must be self-issued */ if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) { return -1; } /* look for an exact match with trusted cert */ for (cur = trust_ca; cur != NULL; cur = cur->next) { if (crt->raw.len == cur->raw.len && memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) { return 0; } } /* too bad */ return -1; } /* * Build and verify a certificate chain * * Given a peer-provided list of certificates EE, C1, ..., Cn and * a list of trusted certs R1, ... Rp, try to build and verify a chain * EE, Ci1, ... Ciq [, Rj] * such that every cert in the chain is a child of the next one, * jumping to a trusted root as early as possible. * * Verify that chain and return it with flags for all issues found. * * Special cases: * - EE == Rj -> return a one-element list containing it * - EE, Ci1, ..., Ciq cannot be continued with a trusted root * -> return that chain with NOT_TRUSTED set on Ciq * * Tests for (aspects of) this function should include at least: * - trusted EE * - EE -> trusted root * - EE -> intermediate CA -> trusted root * - if relevant: EE untrusted * - if relevant: EE -> intermediate, untrusted * with the aspect under test checked at each relevant level (EE, int, root). * For some aspects longer chains are required, but usually length 2 is * enough (but length 1 is not in general). * * Arguments: * - [in] crt: the cert list EE, C1, ..., Cn * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() * - [out] ver_chain: the built and verified chain * Only valid when return value is 0, may contain garbage otherwise! * Restart note: need not be the same when calling again to resume. * - [in-out] rs_ctx: context for restarting operations * * Return value: * - non-zero if the chain could not be fully built and examined * - 0 is the chain was successfully built and examined, * even if it was found to be invalid */ static int x509_crt_verify_chain( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, mbedtls_x509_crt_verify_chain *ver_chain, mbedtls_x509_crt_restart_ctx *rs_ctx) { /* Don't initialize any of those variables here, so that the compiler can * catch potential issues with jumping ahead when restarting */ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; uint32_t *flags; mbedtls_x509_crt_verify_chain_item *cur; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; int parent_is_trusted; int child_is_trusted; int signature_is_good; unsigned self_cnt; mbedtls_x509_crt *cur_trust_ca = NULL; mbedtls_x509_time now; #if defined(MBEDTLS_HAVE_TIME_DATE) if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) { return MBEDTLS_ERR_X509_FATAL_ERROR; } #endif #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* resume if we had an operation in progress */ if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) { /* restore saved state */ *ver_chain = rs_ctx->ver_chain; /* struct copy */ self_cnt = rs_ctx->self_cnt; /* restore derived state */ cur = &ver_chain->items[ver_chain->len - 1]; child = cur->crt; flags = &cur->flags; goto find_parent; } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ child = crt; self_cnt = 0; parent_is_trusted = 0; child_is_trusted = 0; while (1) { /* Add certificate to the verification chain */ cur = &ver_chain->items[ver_chain->len]; cur->crt = child; cur->flags = 0; ver_chain->len++; flags = &cur->flags; #if defined(MBEDTLS_HAVE_TIME_DATE) /* Check time-validity (all certificates) */ if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) { *flags |= MBEDTLS_X509_BADCERT_EXPIRED; } if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) { *flags |= MBEDTLS_X509_BADCERT_FUTURE; } #endif /* Stop here for trusted roots (but not for trusted EE certs) */ if (child_is_trusted) { return 0; } /* Check signature algorithm: MD & PK algs */ if (x509_profile_check_md_alg(profile, child->sig_md) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_MD; } if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_PK; } /* Special case: EE certs that are locally trusted */ if (ver_chain->len == 1 && x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) { return 0; } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) find_parent: #endif /* Obtain list of potential trusted signers from CA callback, * or use statically provided list. */ #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) if (f_ca_cb != NULL) { mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result); mbedtls_free(ver_chain->trust_ca_cb_result); ver_chain->trust_ca_cb_result = NULL; ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result); if (ret != 0) { return MBEDTLS_ERR_X509_FATAL_ERROR; } cur_trust_ca = ver_chain->trust_ca_cb_result; } else #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ { ((void) f_ca_cb); ((void) p_ca_cb); cur_trust_ca = trust_ca; } /* Look for a parent in trusted CAs or up the chain */ ret = x509_crt_find_parent(child, cur_trust_ca, &parent, &parent_is_trusted, &signature_is_good, ver_chain->len - 1, self_cnt, rs_ctx, &now); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { /* save state */ rs_ctx->in_progress = x509_crt_rs_find_parent; rs_ctx->self_cnt = self_cnt; rs_ctx->ver_chain = *ver_chain; /* struct copy */ return ret; } #else (void) ret; #endif /* No parent? We're done here */ if (parent == NULL) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; return 0; } /* Count intermediate self-issued (not necessarily self-signed) certs. * These can occur with some strategies for key rollover, see [SIRO], * and should be excluded from max_pathlen checks. */ if (ver_chain->len != 1 && x509_name_cmp(&child->issuer, &child->subject) == 0) { self_cnt++; } /* path_cnt is 0 for the first intermediate CA, * and if parent is trusted it's not an intermediate CA */ if (!parent_is_trusted && ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) { /* return immediately to avoid overflow the chain array */ return MBEDTLS_ERR_X509_FATAL_ERROR; } /* signature was checked while searching parent */ if (!signature_is_good) { *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; } /* check size of signing key */ if (x509_profile_check_key(profile, &parent->pk) != 0) { *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } #if defined(MBEDTLS_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the given crt */ *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now); #else (void) ca_crl; #endif /* prepare for next iteration */ child = parent; parent = NULL; child_is_trusted = parent_is_trusted; signature_is_good = 0; } } #ifdef _WIN32 #ifdef _MSC_VER #pragma comment(lib, "ws2_32.lib") #include #include #elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600 #include #include #else /* inet_pton() is not supported, fallback to software version */ #define MBEDTLS_TEST_SW_INET_PTON #endif #elif defined(__sun) /* Solaris requires -lsocket -lnsl for inet_pton() */ #elif defined(__has_include) #if __has_include() #include #endif #if __has_include() #include #endif #endif /* Use whether or not AF_INET6 is defined to indicate whether or not to use * the platform inet_pton() or a local implementation (below). The local * implementation may be used even in cases where the platform provides * inet_pton(), e.g. when there are different includes required and/or the * platform implementation requires dependencies on additional libraries. * Specifically, Windows requires custom includes and additional link * dependencies, and Solaris requires additional link dependencies. * Also, as a coarse heuristic, use the local implementation if the compiler * does not support __has_include(), or if the definition of AF_INET6 is not * provided by headers included (or not) via __has_include() above. * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names * despite having a platform that has inet_pton. */ #if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names /* Definition located further below to possibly reduce compiler inlining */ static int x509_inet_pton_ipv4(const char *src, void *dst); #define li_cton(c, n) \ (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) static int x509_inet_pton_ipv6(const char *src, void *dst) { const unsigned char *p = (const unsigned char *) src; int nonzero_groups = 0, num_digits, zero_group_start = -1; uint16_t addr[8]; do { /* note: allows excess leading 0's, e.g. 1:0002:3:... */ uint16_t group = num_digits = 0; for (uint8_t digit; num_digits < 4; num_digits++) { if (li_cton(*p, digit) == 0) { break; } group = (group << 4) | digit; p++; } if (num_digits != 0) { MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups); nonzero_groups++; if (*p == '\0') { break; } else if (*p == '.') { /* Don't accept IPv4 too early or late */ if ((nonzero_groups == 0 && zero_group_start == -1) || nonzero_groups >= 7) { break; } /* Walk back to prior ':', then parse as IPv4-mapped */ int steps = 4; do { p--; steps--; } while (*p != ':' && steps > 0); if (*p != ':') { break; } p++; nonzero_groups--; if (x509_inet_pton_ipv4((const char *) p, addr + nonzero_groups) != 0) { break; } nonzero_groups += 2; p = (const unsigned char *) ""; break; } else if (*p != ':') { return -1; } } else { /* Don't accept a second zero group or an invalid delimiter */ if (zero_group_start != -1 || *p != ':') { return -1; } zero_group_start = nonzero_groups; /* Accept a zero group at start, but it has to be a double colon */ if (zero_group_start == 0 && *++p != ':') { return -1; } if (p[1] == '\0') { ++p; break; } } ++p; } while (nonzero_groups < 8); if (*p != '\0') { return -1; } if (zero_group_start != -1) { if (nonzero_groups > 6) { return -1; } int zero_groups = 8 - nonzero_groups; int groups_after_zero = nonzero_groups - zero_group_start; /* Move the non-zero part to after the zeroes */ if (groups_after_zero) { memmove(addr + zero_group_start + zero_groups, addr + zero_group_start, groups_after_zero * sizeof(*addr)); } memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr)); } else { if (nonzero_groups != 8) { return -1; } } memcpy(dst, addr, sizeof(addr)); return 0; } static int x509_inet_pton_ipv4(const char *src, void *dst) { const unsigned char *p = (const unsigned char *) src; uint8_t *res = (uint8_t *) dst; uint8_t digit, num_digits = 0; uint8_t num_octets = 0; uint16_t octet; do { octet = num_digits = 0; do { digit = *p - '0'; if (digit > 9) { break; } /* Don't allow leading zeroes. These might mean octal format, * which this implementation does not support. */ if (octet == 0 && num_digits > 0) { return -1; } octet = octet * 10 + digit; num_digits++; p++; } while (num_digits < 3); if (octet >= 256 || num_digits > 3 || num_digits == 0) { return -1; } *res++ = (uint8_t) octet; num_octets++; } while (num_octets < 4 && *p++ == '.'); return num_octets == 4 && *p == '\0' ? 0 : -1; } #else static int x509_inet_pton_ipv6(const char *src, void *dst) { return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1; } static int x509_inet_pton_ipv4(const char *src, void *dst) { return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1; } #endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) { return strchr(cn, ':') == NULL ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0 : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0; } /* * Check for CN match */ static int x509_crt_check_cn(const mbedtls_x509_buf *name, const char *cn, size_t cn_len) { /* try exact match */ if (name->len == cn_len && x509_memcasecmp(cn, name->p, cn_len) == 0) { return 0; } /* try wildcard match */ if (x509_check_wildcard(cn, name) == 0) { return 0; } return -1; } static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { uint32_t ip[4]; cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip); if (cn_len == 0) { return -1; } for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { const unsigned char san_type = (unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK; if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS && cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) { return 0; } } return -1; } static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { const unsigned char san_type = (unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK; if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER && cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) { return 0; } } return -1; } /* * Check for SAN match, see RFC 5280 Section 4.2.1.6 */ static int x509_crt_check_san(const mbedtls_x509_sequence *san, const char *cn, size_t cn_len) { int san_ip = 0; int san_uri = 0; /* Prioritize DNS name over other subtypes due to popularity */ for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) { case MBEDTLS_X509_SAN_DNS_NAME: if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) { return 0; } break; case MBEDTLS_X509_SAN_IP_ADDRESS: san_ip = 1; break; case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: san_uri = 1; break; /* (We may handle other types here later.) */ default: /* Unrecognized type */ break; } } if (san_ip) { if (x509_crt_check_san_ip(san, cn, cn_len) == 0) { return 0; } } if (san_uri) { if (x509_crt_check_san_uri(san, cn, cn_len) == 0) { return 0; } } return -1; } /* * Verify the requested CN - only call this if cn is not NULL! */ static void x509_crt_verify_name(const mbedtls_x509_crt *crt, const char *cn, uint32_t *flags) { const mbedtls_x509_name *name; size_t cn_len = strlen(cn); if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) { return; } } else { for (name = &crt->subject; name != NULL; name = name->next) { if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && x509_crt_check_cn(&name->val, cn, cn_len) == 0) { return; } } } *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } /* * Merge the flags for all certs in the chain, after calling callback */ static int x509_crt_merge_flags_with_cb( uint32_t *flags, const mbedtls_x509_crt_verify_chain *ver_chain, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned i; uint32_t cur_flags; const mbedtls_x509_crt_verify_chain_item *cur; for (i = ver_chain->len; i != 0; --i) { cur = &ver_chain->items[i-1]; cur_flags = cur->flags; if (NULL != f_vrfy) { if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) { return ret; } } *flags |= cur_flags; } return 0; } /* * Verify the certificate validity, with profile, restartable version * * This function: * - checks the requested CN (if any) * - checks the type and size of the EE cert's key, * as that isn't done as part of chain building/verification currently * - builds and verifies the chain * - then calls the callback and merges the flags * * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the * verification routine to search for trusted signers, and CRLs will * be disabled. Otherwise, `trust_ca` will be used as the static list * of trusted signers, and `ca_crl` will be use as the static list * of CRLs. */ static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; mbedtls_pk_type_t pk_type; mbedtls_x509_crt_verify_chain ver_chain; uint32_t ee_flags; *flags = 0; ee_flags = 0; x509_crt_verify_chain_reset(&ver_chain); if (profile == NULL) { ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; goto exit; } /* check name if requested */ if (cn != NULL) { x509_crt_verify_name(crt, cn, &ee_flags); } /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type(&crt->pk); if (x509_profile_check_pk_alg(profile, pk_type) != 0) { ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; } if (x509_profile_check_key(profile, &crt->pk) != 0) { ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; } /* Check the chain */ ret = x509_crt_verify_chain(crt, trust_ca, ca_crl, f_ca_cb, p_ca_cb, profile, &ver_chain, rs_ctx); if (ret != 0) { goto exit; } /* Merge end-entity flags */ ver_chain.items[0].flags |= ee_flags; /* Build final flags, calling callback on the way if any */ ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy); exit: #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result); mbedtls_free(ver_chain.trust_ca_cb_result); ver_chain.trust_ca_cb_result = NULL; #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { mbedtls_x509_crt_restart_free(rs_ctx); } #endif /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by * the SSL module for authmode optional, but non-zero return from the * callback means a fatal error so it shouldn't be ignored */ if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { ret = MBEDTLS_ERR_X509_FATAL_ERROR; } if (ret != 0) { *flags = (uint32_t) -1; return ret; } if (*flags != 0) { return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; } return 0; } /* * Verify the certificate validity (default profile, not restartable) */ int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy, NULL); } /* * Verify the certificate validity (user-chosen profile, not restartable) */ int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, NULL); } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* * Verify the certificate validity (user-chosen profile, CA callback, * not restartable). */ int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL, f_ca_cb, p_ca_cb, profile, cn, flags, f_vrfy, p_vrfy, NULL); } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx) { return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, rs_ctx); } /* * Initialize a certificate chain */ void mbedtls_x509_crt_init(mbedtls_x509_crt *crt) { memset(crt, 0, sizeof(mbedtls_x509_crt)); } /* * Unallocate all certificate data */ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) { mbedtls_x509_crt *cert_cur = crt; mbedtls_x509_crt *cert_prv; while (cert_cur != NULL) { mbedtls_pk_free(&cert_cur->pk); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(cert_cur->sig_opts); #endif mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next); mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next); mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next); mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next); mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next); mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next); if (cert_cur->raw.p != NULL && cert_cur->own_buffer) { mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len); } cert_prv = cert_cur; cert_cur = cert_cur->next; mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt)); if (cert_prv != crt) { mbedtls_free(cert_prv); } } } #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx) { mbedtls_pk_restart_init(&ctx->pk); ctx->parent = NULL; ctx->fallback_parent = NULL; ctx->fallback_signature_is_good = 0; ctx->parent_is_trusted = -1; ctx->in_progress = x509_crt_rs_none; ctx->self_cnt = 0; x509_crt_verify_chain_reset(&ctx->ver_chain); } /* * Free the components of a restart context */ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx) { if (ctx == NULL) { return; } mbedtls_pk_restart_free(&ctx->pk); mbedtls_x509_crt_restart_init(ctx); } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt) { if ((crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) != 0) { return crt->MBEDTLS_PRIVATE(ca_istrue); } return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; } #endif /* MBEDTLS_X509_CRT_PARSE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509_csr.c000066400000000000000000000465341464416617300230700ustar00rootroot00000000000000/* * X.509 Certificate Signing Request (CSR) parsing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * The ITU-T X.509 standard defines a certificate format for PKI. * * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) * * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */ #include "common.h" #if defined(MBEDTLS_X509_CSR_PARSE_C) #include "mbedtls/x509_csr.h" #include "x509_internal.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #include #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/platform.h" #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) #include #endif /* * Version ::= INTEGER { v1(0) } */ static int x509_csr_get_version(unsigned char **p, const unsigned char *end, int *ver) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { *ver = 0; return 0; } return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); } return 0; } /* * Parse CSR extension requests in DER format */ static int x509_csr_parse_extensions(mbedtls_x509_csr *csr, unsigned char **p, const unsigned char *end, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *end_ext_data, *end_ext_octet; while (*p < end) { mbedtls_x509_buf extn_oid = { 0, 0, NULL }; int is_critical = 0; /* DEFAULT FALSE */ int ext_type = 0; /* Read sequence tag */ if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_data = *p + len; /* Get extension ID */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } extn_oid.tag = MBEDTLS_ASN1_OID; extn_oid.p = *p; *p += extn_oid.len; /* Get optional critical */ if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } /* Data should be octet string type */ if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_ext_octet = *p + len; if (end_ext_octet != end_ext_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * Detect supported extensions and skip unsupported extensions */ ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); if (ret != 0) { /* Give the callback (if any) a chance to handle the extension */ if (cb != NULL) { ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet); if (ret != 0 && is_critical) { return ret; } *p = end_ext_octet; continue; } /* No parser found, skip extension */ *p = end_ext_octet; if (is_critical) { /* Data is marked as critical: fail */ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); } continue; } /* Forbid repeated extensions */ if ((csr->ext_types & ext_type) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_DATA); } csr->ext_types |= ext_type; switch (ext_type) { case MBEDTLS_X509_EXT_KEY_USAGE: /* Parse key usage */ if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data, &csr->key_usage)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: /* Parse subject alt name */ if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data, &csr->subject_alt_names)) != 0) { return ret; } break; case MBEDTLS_X509_EXT_NS_CERT_TYPE: /* Parse netscape certificate type */ if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data, &csr->ns_cert_type)) != 0) { return ret; } break; default: /* * If this is a non-critical extension, which the oid layer * supports, but there isn't an x509 parser for it, * skip the extension. */ if (is_critical) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } else { *p = end_ext_octet; } } } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse CSR attributes in DER format */ static int x509_csr_parse_attributes(mbedtls_x509_csr *csr, const unsigned char *start, const unsigned char *end, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { int ret; size_t len; unsigned char *end_attr_data; unsigned char **p = (unsigned char **) &start; while (*p < end) { mbedtls_x509_buf attr_oid = { 0, 0, NULL }; if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } end_attr_data = *p + len; /* Get attribute ID */ if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len, MBEDTLS_ASN1_OID)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } attr_oid.tag = MBEDTLS_ASN1_OID; attr_oid.p = *p; *p += attr_oid.len; /* Check that this is an extension-request attribute */ if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) { if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); } if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) { return ret; } if (*p != end_attr_data) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } } *p = end_attr_data; } if (*p != end) { return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse a CSR in DER format */ static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len; unsigned char *p, *end; mbedtls_x509_buf sig_params; memset(&sig_params, 0, sizeof(mbedtls_x509_buf)); /* * Check for valid input */ if (csr == NULL || buf == NULL || buflen == 0) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } mbedtls_x509_csr_init(csr); /* * first copy the raw DER data */ p = mbedtls_calloc(1, len = buflen); if (p == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } memcpy(p, buf, buflen); csr->raw.p = p; csr->raw.len = len; end = p + len; /* * CertificationRequest ::= SEQUENCE { * certificationRequestInfo CertificationRequestInfo, * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING * } */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERR_X509_INVALID_FORMAT; } if (len != (size_t) (end - p)) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } /* * CertificationRequestInfo ::= SEQUENCE { */ csr->cri.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } end = p + len; csr->cri.len = (size_t) (end - csr->cri.p); /* * Version ::= INTEGER { v1(0) } */ if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) { mbedtls_x509_csr_free(csr); return ret; } if (csr->version != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERR_X509_UNKNOWN_VERSION; } csr->version++; /* * subject Name */ csr->subject_raw.p = p; if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) { mbedtls_x509_csr_free(csr); return ret; } csr->subject_raw.len = (size_t) (p - csr->subject_raw.p); /* * subjectPKInfo SubjectPublicKeyInfo */ if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) { mbedtls_x509_csr_free(csr); return ret; } /* * attributes [0] Attributes * * The list of possible attributes is open-ended, though RFC 2985 * (PKCS#9) defines a few in section 5.4. We currently don't support any, * so we just ignore them. This is a safe thing to do as the worst thing * that could happen is that we issue a certificate that does not match * the requester's expectations - this cannot cause a violation of our * signature policies. */ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); } if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) { mbedtls_x509_csr_free(csr); return ret; } p += len; end = csr->raw.p + csr->raw.len; /* * signatureAlgorithm AlgorithmIdentifier, * signature BIT STRING */ if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) { mbedtls_x509_csr_free(csr); return ret; } if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params, &csr->sig_md, &csr->sig_pk, &csr->sig_opts)) != 0) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG; } if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) { mbedtls_x509_csr_free(csr); return ret; } if (p != end) { mbedtls_x509_csr_free(csr); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); } return 0; } /* * Parse a CSR in DER format */ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen) { return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL); } /* * Parse a CSR in DER format with callback for unknown extensions */ int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen, mbedtls_x509_csr_ext_cb_t cb, void *p_ctx) { return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx); } /* * Parse a CSR, allowing for PEM or raw DER encoding */ int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen) { #if defined(MBEDTLS_PEM_PARSE_C) int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t use_len; mbedtls_pem_context pem; #endif /* * Check for valid input */ if (csr == NULL || buf == NULL || buflen == 0) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } #if defined(MBEDTLS_PEM_PARSE_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if (buf[buflen - 1] == '\0') { mbedtls_pem_init(&pem); ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN CERTIFICATE REQUEST-----", "-----END CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len); if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN NEW CERTIFICATE REQUEST-----", "-----END NEW CERTIFICATE REQUEST-----", buf, NULL, 0, &use_len); } if (ret == 0) { /* * Was PEM encoded, parse the result */ ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen); } mbedtls_pem_free(&pem); if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { return ret; } } #endif /* MBEDTLS_PEM_PARSE_C */ return mbedtls_x509_csr_parse_der(csr, buf, buflen); } #if defined(MBEDTLS_FS_IO) /* * Load a CSR into the structure */ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; unsigned char *buf; if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { return ret; } ret = mbedtls_x509_csr_parse(csr, buf, n); mbedtls_zeroize_and_free(buf, n); return ret; } #endif /* MBEDTLS_FS_IO */ #if !defined(MBEDTLS_X509_REMOVE_INFO) #define BEFORE_COLON 14 #define BC "14" /* * Return an informational string about the CSR. */ int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix, const mbedtls_x509_csr *csr) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t n; char *p; char key_size_str[BEFORE_COLON]; p = buf; n = size; ret = mbedtls_snprintf(p, n, "%sCSR version : %d", prefix, csr->version); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_dn_gets(p, n, &csr->subject); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, csr->sig_opts); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON, mbedtls_pk_get_name(&csr->pk))) != 0) { return ret; } ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, (int) mbedtls_pk_get_bitlen(&csr->pk)); MBEDTLS_X509_SAFE_SNPRINTF; /* * Optional extensions */ if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, &csr->subject_alt_names, prefix)) != 0) { return ret; } } if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) { return ret; } } if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); MBEDTLS_X509_SAFE_SNPRINTF; if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) { return ret; } } if (csr->ext_types != 0) { ret = mbedtls_snprintf(p, n, "\n"); MBEDTLS_X509_SAFE_SNPRINTF; } return (int) (size - n); } #endif /* MBEDTLS_X509_REMOVE_INFO */ /* * Initialize a CSR */ void mbedtls_x509_csr_init(mbedtls_x509_csr *csr) { memset(csr, 0, sizeof(mbedtls_x509_csr)); } /* * Unallocate all CSR data */ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr) { if (csr == NULL) { return; } mbedtls_pk_free(&csr->pk); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) mbedtls_free(csr->sig_opts); #endif mbedtls_asn1_free_named_data_list_shallow(csr->subject.next); mbedtls_asn1_sequence_free(csr->subject_alt_names.next); if (csr->raw.p != NULL) { mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len); } mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr)); } #endif /* MBEDTLS_X509_CSR_PARSE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509_internal.h000066400000000000000000000103521464416617300241070ustar00rootroot00000000000000/** * \file x509.h * * \brief Internal part of the public "x509.h". */ /* * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #ifndef MBEDTLS_X509_INTERNAL_H #define MBEDTLS_X509_INTERNAL_H #include "mbedtls/private_access.h" #include "mbedtls/build_info.h" #include "mbedtls/x509.h" #include "mbedtls/asn1.h" #include "pk_internal.h" #if defined(MBEDTLS_RSA_C) #include "mbedtls/rsa.h" #endif int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, mbedtls_x509_name *cur); int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg); int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *alg, mbedtls_x509_buf *params); #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, int *salt_len); #endif int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig); int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, void **sig_opts); int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, mbedtls_x509_time *t); int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *serial); int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *ext, int tag); #if !defined(MBEDTLS_X509_REMOVE_INFO) int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, const void *sig_opts); #endif int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name); int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len); int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first); int mbedtls_x509_write_names(unsigned char **p, unsigned char *start, mbedtls_asn1_named_data *first); int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start, const char *oid, size_t oid_len, unsigned char *sig, size_t size, mbedtls_pk_type_t pk_alg); int mbedtls_x509_get_ns_cert_type(unsigned char **p, const unsigned char *end, unsigned char *ns_cert_type); int mbedtls_x509_get_key_usage(unsigned char **p, const unsigned char *end, unsigned int *key_usage); int mbedtls_x509_get_subject_alt_name(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name); int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p, const unsigned char *end, mbedtls_x509_sequence *subject_alt_name); int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size, const mbedtls_x509_sequence *subject_alt_name, const char *prefix); int mbedtls_x509_info_cert_type(char **buf, size_t *size, unsigned char ns_cert_type); int mbedtls_x509_info_key_usage(char **buf, size_t *size, unsigned int key_usage); int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, const mbedtls_x509_san_list *san_list); #endif /* MBEDTLS_X509_INTERNAL_H */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509write.c000066400000000000000000000155521464416617300232700ustar00rootroot00000000000000/* * X.509 internal, common functions for writing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C) #include "mbedtls/x509_crt.h" #include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include #include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "mbedtls/psa_util.h" #include "md_psa.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #define CHECK_OVERFLOW_ADD(a, b) \ do \ { \ if (a > SIZE_MAX - (b)) \ { \ return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \ } \ a += b; \ } while (0) int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions, const mbedtls_x509_san_list *san_list) { int ret = 0; const mbedtls_x509_san_list *cur; unsigned char *buf; unsigned char *p; size_t len; size_t buflen = 0; /* Determine the maximum size of the SubjectAltName list */ for (cur = san_list; cur != NULL; cur = cur->next) { /* Calculate size of the required buffer */ switch (cur->node.type) { case MBEDTLS_X509_SAN_DNS_NAME: case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: case MBEDTLS_X509_SAN_IP_ADDRESS: case MBEDTLS_X509_SAN_RFC822_NAME: /* length of value for each name entry, * maximum 4 bytes for the length field, * 1 byte for the tag/type. */ CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len); CHECK_OVERFLOW_ADD(buflen, 4 + 1); break; case MBEDTLS_X509_SAN_DIRECTORY_NAME: { const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name; while (chunk != NULL) { // Max 4 bytes for length, +1 for tag, // additional 4 max for length, +1 for tag. // See x509_write_name for more information. CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1); CHECK_OVERFLOW_ADD(buflen, chunk->oid.len); CHECK_OVERFLOW_ADD(buflen, chunk->val.len); chunk = chunk->next; } CHECK_OVERFLOW_ADD(buflen, 4 + 1); break; } default: /* Not supported - return. */ return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } } /* Add the extra length field and tag */ CHECK_OVERFLOW_ADD(buflen, 4 + 1); /* Allocate buffer */ buf = mbedtls_calloc(1, buflen); if (buf == NULL) { return MBEDTLS_ERR_ASN1_ALLOC_FAILED; } p = buf + buflen; /* Write ASN.1-based structure */ cur = san_list; len = 0; while (cur != NULL) { size_t single_san_len = 0; switch (cur->node.type) { case MBEDTLS_X509_SAN_DNS_NAME: case MBEDTLS_X509_SAN_RFC822_NAME: case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: case MBEDTLS_X509_SAN_IP_ADDRESS: { const unsigned char *unstructured_name = (const unsigned char *) cur->node.san.unstructured_name.p; size_t unstructured_name_len = cur->node.san.unstructured_name.len; MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_raw_buffer( &p, buf, unstructured_name, unstructured_name_len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len( &p, buf, unstructured_name_len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_tag( &p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); } break; case MBEDTLS_X509_SAN_DIRECTORY_NAME: MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_x509_write_names(&p, buf, (mbedtls_asn1_named_data *) & cur->node .san.directory_name)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len(&p, buf, single_san_len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_X509_SAN_DIRECTORY_NAME)); break; default: /* Error out on an unsupported SAN */ ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; goto cleanup; } cur = cur->next; /* check for overflow */ if (len > SIZE_MAX - single_san_len) { ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; goto cleanup; } len += single_san_len; } MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); ret = mbedtls_x509_set_extension(extensions, MBEDTLS_OID_SUBJECT_ALT_NAME, MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), 0, buf + buflen - len, len); /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list * was incorrectly calculated and memory is corrupted. */ if (p < buf) { ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; } cleanup: mbedtls_free(buf); return ret; } #endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509write_crt.c000066400000000000000000000604141464416617300241350ustar00rootroot00000000000000/* * X.509 certificate writing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * - certificates: RFC 5280, updated by RFC 6818 * - CSRs: PKCS#10 v1.7 aka RFC 2986 * - attributes: PKCS#9 v2.0 aka RFC 2985 */ #include "common.h" #if defined(MBEDTLS_X509_CRT_WRITE_C) #include "mbedtls/x509_crt.h" #include "x509_internal.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform.h" #include "mbedtls/platform_util.h" #include "mbedtls/md.h" #include #include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif /* MBEDTLS_PEM_WRITE_C */ #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx) { memset(ctx, 0, sizeof(mbedtls_x509write_cert)); ctx->version = MBEDTLS_X509_CRT_VERSION_3; } void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx) { mbedtls_asn1_free_named_data_list(&ctx->subject); mbedtls_asn1_free_named_data_list(&ctx->issuer); mbedtls_asn1_free_named_data_list(&ctx->extensions); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert)); } void mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx, int version) { ctx->version = version; } void mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg) { ctx->md_alg = md_alg; } void mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key) { ctx->subject_key = key; } void mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx, mbedtls_pk_context *key) { ctx->issuer_key = key; } int mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx, const char *subject_name) { return mbedtls_x509_string_to_names(&ctx->subject, subject_name); } int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx, const char *issuer_name) { return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name); } #if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) int mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial) { int ret; size_t tmp_len; /* Ensure that the MPI value fits into the buffer */ tmp_len = mbedtls_mpi_size(serial); if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } ctx->serial_len = tmp_len; ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len); if (ret < 0) { return ret; } return 0; } #endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED int mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx, unsigned char *serial, size_t serial_len) { if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } ctx->serial_len = serial_len; memcpy(ctx->serial, serial, serial_len); return 0; } int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *not_before, const char *not_after) { if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || strlen(not_after) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN); strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN); ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; return 0; } int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx, const mbedtls_x509_san_list *san_list) { return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); } int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len) { return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, critical, val, val_len); } int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx, int is_ca, int max_pathlen) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[9]; unsigned char *c = buf + sizeof(buf); size_t len = 0; memset(buf, 0, sizeof(buf)); if (is_ca && max_pathlen > 127) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } if (is_ca) { if (max_pathlen >= 0) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, max_pathlen)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS), is_ca, buf + sizeof(buf) - len, len); } #if defined(MBEDTLS_MD_CAN_SHA1) static int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx, int is_ca, unsigned char tag) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ unsigned char *c = buf + sizeof(buf); size_t len = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; size_t hash_length; #endif /* MBEDTLS_USE_PSA_CRYPTO */ memset(buf, 0, sizeof(buf)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, is_ca ? ctx->issuer_key : ctx->subject_key)); #if defined(MBEDTLS_USE_PSA_CRYPTO) status = psa_hash_compute(PSA_ALG_SHA_1, buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20, 20, &hash_length); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20); if (ret != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ c = buf + sizeof(buf) - 20; len = 20; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag)); if (is_ca) { // writes AuthorityKeyIdentifier sequence MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); } if (is_ca) { return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER), 0, buf + sizeof(buf) - len, len); } else { return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER), 0, buf + sizeof(buf) - len, len); } } int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx) { return mbedtls_x509write_crt_set_key_identifier(ctx, 0, MBEDTLS_ASN1_OCTET_STRING); } int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx) { return mbedtls_x509write_crt_set_key_identifier(ctx, 1, (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0)); } #endif /* MBEDTLS_MD_CAN_SHA1 */ int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx, unsigned int key_usage) { unsigned char buf[5] = { 0 }, ku[2] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT | MBEDTLS_X509_KU_DATA_ENCIPHERMENT | MBEDTLS_X509_KU_KEY_AGREEMENT | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_ENCIPHER_ONLY | MBEDTLS_X509_KU_DECIPHER_ONLY; /* Check that nothing other than the allowed flags is set */ if ((key_usage & ~allowed_bits) != 0) { return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; } c = buf + 5; MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0); ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9); if (ret < 0) { return ret; } else if (ret < 3 || ret > 5) { return MBEDTLS_ERR_X509_INVALID_FORMAT; } ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 1, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, const mbedtls_asn1_sequence *exts) { unsigned char buf[256]; unsigned char *c = buf + sizeof(buf); int ret; size_t len = 0; const mbedtls_asn1_sequence *last_ext = NULL; const mbedtls_asn1_sequence *ext; memset(buf, 0, sizeof(buf)); /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */ if (exts == NULL) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } /* Iterate over exts backwards, so we write them out in the requested order */ while (last_ext != exts) { for (ext = exts; ext->next != last_ext; ext = ext->next) { } if (ext->buf.tag != MBEDTLS_ASN1_OID) { return MBEDTLS_ERR_X509_BAD_INPUT_DATA; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID)); last_ext = ext; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE), 1, c, len); } int mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx, unsigned char ns_cert_type) { unsigned char buf[4] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; c = buf + 4; ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); if (ret < 3 || ret > 4) { return ret; } ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 0, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } static int x509_write_time(unsigned char **p, unsigned char *start, const char *t, size_t size) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t len = 0; /* * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */ if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) t + 2, size - 2)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_UTC_TIME)); } else { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, (const unsigned char *) t, size)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_GENERALIZED_TIME)); } return (int) len; } int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; size_t hash_length = 0; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_algorithm_t psa_algorithm; #endif /* MBEDTLS_USE_PSA_CRYPTO */ size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; int write_sig_null_par; /* * Prepare data to be signed at the end of the target buffer */ c = buf + size; /* Signature algorithm needed in TBS, and later for actual signature */ /* There's no direct way of extracting a signature algorithm * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) { pk_alg = MBEDTLS_PK_RSA; } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) { pk_alg = MBEDTLS_PK_ECDSA; } else { return MBEDTLS_ERR_X509_INVALID_ALG; } if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len)) != 0) { return ret; } /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ /* Only for v3 */ if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, ctx->extensions)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3)); } /* * SubjectPublicKeyInfo */ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->subject_key, buf, (size_t) (c - buf))); c -= pub_len; len += pub_len; /* * Subject ::= Name */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->subject)); /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ sub_len = 0; MBEDTLS_ASN1_CHK_ADD(sub_len, x509_write_time(&c, buf, ctx->not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN)); MBEDTLS_ASN1_CHK_ADD(sub_len, x509_write_time(&c, buf, ctx->not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN)); len += sub_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* * Issuer ::= Name */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->issuer)); /* * Signature ::= AlgorithmIdentifier */ if (pk_alg == MBEDTLS_PK_ECDSA) { /* * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and * https://www.rfc-editor.org/rfc/rfc5758#section-3. */ write_sig_null_par = 0; } else { write_sig_null_par = 1; } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, sig_oid, strlen(sig_oid), 0, write_sig_null_par)); /* * Serial ::= INTEGER * * Written data is: * - "ctx->serial_len" bytes for the raw serial buffer * - if MSb of "serial" is 1, then prepend an extra 0x00 byte * - 1 byte for the length * - 1 byte for the TAG */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ctx->serial, ctx->serial_len)); if (*c & 0x80) { if (c - buf < 1) { return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; } *(--c) = 0x0; len++; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ctx->serial_len + 1)); } else { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ctx->serial_len)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_INTEGER)); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ /* Can be omitted for v1 */ if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) { sub_len = 0; MBEDTLS_ASN1_CHK_ADD(sub_len, mbedtls_asn1_write_int(&c, buf, ctx->version)); len += sub_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* * Make signature */ /* Compute hash of CRT. */ #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg); status = psa_hash_compute(psa_algorithm, c, len, hash, sizeof(hash), &hash_length); if (status != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash)) != 0) { return ret; } #endif /* MBEDTLS_USE_PSA_CRYPTO */ if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg, hash, hash_length, sig, sizeof(sig), &sig_len, f_rng, p_rng)) != 0) { return ret; } /* Move CRT to the front of the buffer to have space * for the signature. */ memmove(buf, c, len); c = buf + len; /* Add signature at the end of the buffer, * making sure that it doesn't underflow * into the CRT buffer. */ c2 = buf + size; MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c, sig_oid, sig_oid_len, sig, sig_len, pk_alg)); /* * Memory layout after this step: * * buf c=buf+len c2 buf+size * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] */ /* Move raw CRT to just before the signature. */ c = c2 - len; memmove(c, buf, len); len += sig_and_oid_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); return (int) len; } #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" #define PEM_END_CRT "-----END CERTIFICATE-----\n" #if defined(MBEDTLS_PEM_WRITE_C) int mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen; if ((ret = mbedtls_x509write_crt_der(crt, buf, size, f_rng, p_rng)) < 0) { return ret; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT, buf + size - ret, ret, buf, size, &olen)) != 0) { return ret; } return 0; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CRT_WRITE_C */ optee_os-4.3.0/lib/libmbedtls/mbedtls/library/x509write_csr.c000066400000000000000000000252531464416617300241360ustar00rootroot00000000000000/* * X.509 Certificate Signing Request writing * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ /* * References: * - CSRs: PKCS#10 v1.7 aka RFC 2986 * - attributes: PKCS#9 v2.0 aka RFC 2985 */ #include "common.h" #if defined(MBEDTLS_X509_CSR_WRITE_C) #include "x509_internal.h" #include "mbedtls/x509_csr.h" #include "mbedtls/asn1write.h" #include "mbedtls/error.h" #include "mbedtls/oid.h" #include "mbedtls/platform_util.h" #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" #include "psa_util_internal.h" #include "mbedtls/psa_util.h" #endif /* MBEDTLS_USE_PSA_CRYPTO */ #include #include #if defined(MBEDTLS_PEM_WRITE_C) #include "mbedtls/pem.h" #endif #include "mbedtls/platform.h" void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) { memset(ctx, 0, sizeof(mbedtls_x509write_csr)); } void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) { mbedtls_asn1_free_named_data_list(&ctx->subject); mbedtls_asn1_free_named_data_list(&ctx->extensions); mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); } void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) { ctx->md_alg = md_alg; } void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) { ctx->key = key; } int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, const char *subject_name) { return mbedtls_x509_string_to_names(&ctx->subject, subject_name); } int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, const char *oid, size_t oid_len, int critical, const unsigned char *val, size_t val_len) { return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, critical, val, val_len); } int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, const mbedtls_x509_san_list *san_list) { return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); } int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) { unsigned char buf[4] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; c = buf + 4; ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); if (ret < 3 || ret > 4) { return ret; } ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), 0, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, unsigned char ns_cert_type) { unsigned char buf[4] = { 0 }; unsigned char *c; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; c = buf + 4; ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); if (ret < 3 || ret > 4) { return ret; } ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), 0, c, (size_t) ret); if (ret != 0) { return ret; } return 0; } static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, unsigned char *sig, size_t sig_size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; mbedtls_pk_type_t pk_alg; #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t hash_len; psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg); #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Write the CSR backwards starting from the end of buf */ c = buf + size; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, ctx->extensions)); if (len) { MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid( &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); } MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, buf, (size_t) (c - buf))); c -= pub_len; len += pub_len; /* * Subject ::= Name */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->subject)); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* * Sign the written CSR data into the sig buffer * Note: hash errors can happen only after an internal error */ #if defined(MBEDTLS_USE_PSA_CRYPTO) if (psa_hash_compute(hash_alg, c, len, hash, sizeof(hash), &hash_len) != PSA_SUCCESS) { return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; } #else /* MBEDTLS_USE_PSA_CRYPTO */ ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); if (ret != 0) { return ret; } #endif if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, sig, sig_size, &sig_len, f_rng, p_rng)) != 0) { return ret; } if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { pk_alg = MBEDTLS_PK_RSA; } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { pk_alg = MBEDTLS_PK_ECDSA; } else { return MBEDTLS_ERR_X509_INVALID_ALG; } if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len)) != 0) { return ret; } /* * Move the written CSR data to the start of buf to create space for * writing the signature into buf. */ memmove(buf, c, len); /* * Write sig and its OID into buf backwards from the end of buf. * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. */ c2 = buf + size; MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, sig, sig_len, pk_alg)); /* * Compact the space between the CSR data and signature by moving the * CSR data to the start of the signature. */ c2 -= len; memmove(c2, buf, len); /* ASN encode the total size and tag the CSR data with it. */ len += sig_and_oid_len; MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); /* Zero the unused bytes at the start of buf */ memset(buf, 0, (size_t) (c2 - buf)); return (int) len; } int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret; unsigned char *sig; if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { return MBEDTLS_ERR_X509_ALLOC_FAILED; } ret = x509write_csr_der_internal(ctx, buf, size, sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, f_rng, p_rng); mbedtls_free(sig); return ret; } #define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" #define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" #if defined(MBEDTLS_PEM_WRITE_C) int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t olen = 0; if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, f_rng, p_rng)) < 0) { return ret; } if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, buf + size - ret, ret, buf, size, &olen)) != 0) { return ret; } return 0; } #endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_X509_CSR_WRITE_C */ optee_os-4.3.0/lib/libmbedtls/sub.mk000066400000000000000000000102351464416617300173610ustar00rootroot00000000000000global-incdirs-y += include global-incdirs-y += mbedtls/include # OBJS_CRYPTO from make file SRCS_CRYPTO := ifneq ($(sm),core) SRCS_CRYPTO += aes.c SRCS_CRYPTO += aesce.c SRCS_CRYPTO += aesni.c SRCS_CRYPTO += aria.c SRCS_CRYPTO += asn1parse.c SRCS_CRYPTO += asn1write.c SRCS_CRYPTO += base64.c SRCS_CRYPTO += bignum.c SRCS_CRYPTO += bignum_core.c SRCS_CRYPTO += bignum_mod_raw.c SRCS_CRYPTO += camellia.c SRCS_CRYPTO += ccm.c SRCS_CRYPTO += block_cipher.c SRCS_CRYPTO += chacha20.c SRCS_CRYPTO += chachapoly.c SRCS_CRYPTO += cipher.c SRCS_CRYPTO += cipher_wrap.c SRCS_CRYPTO += cmac.c SRCS_CRYPTO += constant_time.c SRCS_CRYPTO += ctr_drbg.c SRCS_CRYPTO += des.c SRCS_CRYPTO += dhm.c SRCS_CRYPTO += ecdh.c SRCS_CRYPTO += ecdsa.c SRCS_CRYPTO += ecjpake.c SRCS_CRYPTO += ecp.c SRCS_CRYPTO += ecp_curves.c SRCS_CRYPTO += ecp_curves_new.c SRCS_CRYPTO += entropy.c SRCS_CRYPTO += entropy_poll.c SRCS_CRYPTO += error.c SRCS_CRYPTO += gcm.c SRCS_CRYPTO += hkdf.c SRCS_CRYPTO += hmac_drbg.c SRCS_CRYPTO += lmots.c SRCS_CRYPTO += lms.c SRCS_CRYPTO += md.c SRCS_CRYPTO += md5.c SRCS_CRYPTO += memory_buffer_alloc.c SRCS_CRYPTO += nist_kw.c SRCS_CRYPTO += oid.c SRCS_CRYPTO += padlock.c SRCS_CRYPTO += pem.c SRCS_CRYPTO += pk.c SRCS_CRYPTO += pk_ecc.c SRCS_CRYPTO += pk_wrap.c SRCS_CRYPTO += pkcs7.c SRCS_CRYPTO += pkcs12.c SRCS_CRYPTO += pkcs5.c SRCS_CRYPTO += pkparse.c SRCS_CRYPTO += pkwrite.c SRCS_CRYPTO += platform.c SRCS_CRYPTO += platform_util.c SRCS_CRYPTO += poly1305.c SRCS_CRYPTO += ripemd160.c SRCS_CRYPTO += rsa.c SRCS_CRYPTO += rsa_alt_helpers.c SRCS_CRYPTO += sha1.c SRCS_CRYPTO += sha256.c SRCS_CRYPTO += sha3.c SRCS_CRYPTO += sha512.c SRCS_CRYPTO += threading.c SRCS_CRYPTO += timing.c SRCS_CRYPTO += version.c SRCS_CRYPTO += version_features.c else SRCS_CRYPTO += aes.c SRCS_CRYPTO += aesni.c SRCS_CRYPTO += asn1parse.c SRCS_CRYPTO += asn1write.c SRCS_CRYPTO += bignum.c SRCS_CRYPTO += bignum_core.c SRCS_CRYPTO += bignum_mod_raw.c SRCS_CRYPTO += cipher.c SRCS_CRYPTO += cipher_wrap.c SRCS_CRYPTO += cmac.c SRCS_CRYPTO += constant_time.c SRCS_CRYPTO += ctr_drbg.c SRCS_CRYPTO += des.c SRCS_CRYPTO += dhm.c SRCS_CRYPTO += ecdh.c SRCS_CRYPTO += ecdsa.c SRCS_CRYPTO += ecp.c SRCS_CRYPTO += ecp_curves.c SRCS_CRYPTO += ecp_curves_new.c SRCS_CRYPTO += md.c SRCS_CRYPTO += md5.c SRCS_CRYPTO += oid.c SRCS_CRYPTO += pk.c SRCS_CRYPTO += pk_ecc.c SRCS_CRYPTO += pk_wrap.c SRCS_CRYPTO += platform.c SRCS_CRYPTO += platform_util.c SRCS_CRYPTO += rsa.c SRCS_CRYPTO += rsa_alt_helpers.c SRCS_CRYPTO += sha1.c SRCS_CRYPTO += sha256.c SRCS_CRYPTO += sha3.c SRCS_CRYPTO += sha512.c endif # OBJS_X509 SRCS_X509 := SRCS_X509 += x509.c SRCS_X509 += x509_create.c SRCS_X509 += x509_crl.c SRCS_X509 += x509_crt.c SRCS_X509 += x509_csr.c SRCS_X509 += x509write.c SRCS_X509 += x509write_crt.c SRCS_X509 += x509write_csr.c # OBJS_TLS SRCS_TLS := SRCS_TLS += debug.c SRCS_TLS += net_sockets.c SRCS_TLS += ssl_cache.c SRCS_TLS += ssl_client.c SRCS_TLS += ssl_ciphersuites.c SRCS_TLS += ssl_cookie.c SRCS_TLS += ssl_debug_helpers_generated.c SRCS_TLS += ssl_ticket.c SRCS_TLS += ssl_tls.c SRCS_TLS += ssl_tls12_client.c SRCS_TLS += ssl_tls12_server.c SRCS_TLS += ssl_tls13_client.c SRCS_TLS += ssl_tls13_generic.c SRCS_TLS += ssl_tls13_server.c # OBJS_PSA SRCS_PSA := SRCS_PSA += psa_crypto_aead.c SRCS_PSA += psa_crypto.c SRCS_PSA += psa_crypto_cipher.c SRCS_PSA += psa_crypto_client.c SRCS_PSA += psa_crypto_driver_wrappers_no_static.c SRCS_PSA += psa_crypto_ecp.c SRCS_PSA += psa_crypto_ffdh.c SRCS_PSA += psa_crypto_hash.c SRCS_PSA += psa_crypto_mac.c SRCS_PSA += psa_crypto_pake.c SRCS_PSA += psa_crypto_rsa.c SRCS_PSA += psa_crypto_se.c SRCS_PSA += psa_crypto_slot_management.c SRCS_PSA += psa_crypto_storage.c SRCS_PSA += psa_its_file.c SRCS_PSA += psa_util.c srcs-y += $(addprefix mbedtls/library/, $(SRCS_CRYPTO)) srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_X509)) srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_TLS)) srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_PSA)) cflags-lib-y += -Wno-redundant-decls cflags-lib-y += -Wno-switch-default cflags-lib-y += -Wno-declaration-after-statement cflags-lib-y += -Wno-unused-function ifeq ($(CFG_CRYPTOLIB_NAME_mbedtls),y) subdirs-$(sm-core) += core endif optee_os-4.3.0/lib/libunw/000077500000000000000000000000001464416617300154155ustar00rootroot00000000000000optee_os-4.3.0/lib/libunw/include/000077500000000000000000000000001464416617300170405ustar00rootroot00000000000000optee_os-4.3.0/lib/libunw/include/unw/000077500000000000000000000000001464416617300176515ustar00rootroot00000000000000optee_os-4.3.0/lib/libunw/include/unw/unwind.h000066400000000000000000000105741464416617300213350ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND MIT-CMU) */ /*- * Copyright (c) 2023 Andes Technology Corporation * Copyright (c) 2015-2019, Linaro Limited * Copyright (c) 2000, 2001 Ben Harris * Copyright (c) 1996 Scott K. Stevens * * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * $FreeBSD$ */ #ifndef UNW_UNWIND_H #define UNW_UNWIND_H #include #include /* The state of the unwind process (32-bit mode) */ struct unwind_state_arm32 { uint32_t registers[16]; uint32_t start_pc; vaddr_t insn; unsigned int entries; unsigned int byte; uint16_t update_mask; }; #ifdef CFG_UNWIND /* * Unwind a 32-bit stack. * @stack, @stack_size: the bottom of the stack and its size, respectively. * Returns false when there is nothing more to unwind. */ bool unwind_stack_arm32(struct unwind_state_arm32 *state, vaddr_t stack, size_t stack_size); void print_stack_arm32(struct unwind_state_arm32 *state, vaddr_t stack, size_t stack_size); #else static inline bool unwind_stack_arm32(struct unwind_state_arm32 *state __unused, vaddr_t stack __unused, size_t stack_size __unused) { return false; } static inline void print_stack_arm32(struct unwind_state_arm32 *state __unused, vaddr_t stack __unused, size_t stack_size __unused) { } #endif /* * External helper function. Must be implemented by the caller of the 32-bit * stack unwinding functions. */ bool find_exidx(vaddr_t addr, vaddr_t *idx_start, vaddr_t *idx_end); /* The state of the unwind process (64-bit mode) */ struct unwind_state_arm64 { uint64_t fp; uint64_t sp; uint64_t pc; }; #if defined(ARM64) && defined(CFG_UNWIND) /* * Unwind a 64-bit stack. * @stack, @stack_size: the bottom of the stack and its size, respectively. * Returns false when there is nothing more to unwind. */ bool unwind_stack_arm64(struct unwind_state_arm64 *state, vaddr_t stack, size_t stack_size); void print_stack_arm64(struct unwind_state_arm64 *state, vaddr_t stack, size_t stack_size); #else static inline bool unwind_stack_arm64(struct unwind_state_arm64 *state __unused, vaddr_t stack __unused, size_t stack_size __unused) { return false; } static inline void print_stack_arm64(struct unwind_state_arm64 *state __unused, vaddr_t stack __unused, size_t stack_size __unused) { } #endif /* The state of the unwind process */ struct unwind_state_riscv { unsigned long fp; unsigned long pc; }; #if (defined(RV32) || defined(RV64)) && defined(CFG_UNWIND) /* * Unwind stack. * @stack, @stack_size: the bottom of the stack and its size, respectively. * Returns false when there is nothing more to unwind. */ bool unwind_stack_riscv(struct unwind_state_riscv *state, vaddr_t stack, size_t stack_size); void print_stack_riscv(struct unwind_state_riscv *state, vaddr_t stack, size_t stack_size); #else static inline bool unwind_stack_riscv(struct unwind_state_riscv *state __unused, vaddr_t stack __unused, size_t stack_size __unused) { return false; } static inline void print_stack_riscv(struct unwind_state_riscv *state __unused, vaddr_t stack __unused, size_t stack_size __unused) { } #endif /* * External helper function optionally implemented by the caller of the 64-bit * stack unwinding functions. */ void ftrace_map_lr(uint64_t *lr); /* Strip out PAuth tags from LR content if applicable */ void pauth_strip_pac(uint64_t *lr); #endif /*UNW_UNWIND_H*/ optee_os-4.3.0/lib/libunw/sub.mk000066400000000000000000000003111464416617300165320ustar00rootroot00000000000000global-incdirs-y += include ifeq ($(CFG_UNWIND),y) ifeq (arm,$(ARCH)) srcs-y += unwind_arm32.c endif srcs-$(CFG_ARM64_$(sm)) += unwind_arm64.c ifeq (riscv,$(ARCH)) srcs-y += unwind_riscv.c endif endif optee_os-4.3.0/lib/libunw/unwind_arm32.c000066400000000000000000000255621464416617300201030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2015-2019 Linaro Limited * Copyright 2013-2014 Andrew Turner. * Copyright 2013-2014 Ian Lepore. * Copyright 2013-2014 Rui Paulo. * Copyright 2013 Eitan Adler. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include /* The register names */ #define FP 11 #define SP 13 #define LR 14 #define PC 15 /* * Definitions for the instruction interpreter. * * The ARM EABI specifies how to perform the frame unwinding in the * Exception Handling ABI for the ARM Architecture document. To perform * the unwind we need to know the initial frame pointer, stack pointer, * link register and program counter. We then find the entry within the * index table that points to the function the program counter is within. * This gives us either a list of three instructions to process, a 31-bit * relative offset to a table of instructions, or a value telling us * we can't unwind any further. * * When we have the instructions to process we need to decode them * following table 4 in section 9.3. This describes a collection of bit * patterns to encode that steps to take to update the stack pointer and * link register to the correct values at the start of the function. */ /* A special case when we are unable to unwind past this function */ #define EXIDX_CANTUNWIND 1 /* * Entry types. * These are the only entry types that have been seen in the kernel. */ #define ENTRY_MASK 0xff000000 #define ENTRY_ARM_SU16 0x80000000 #define ENTRY_ARM_LU16 0x81000000 /* Instruction masks. */ #define INSN_VSP_MASK 0xc0 #define INSN_VSP_SIZE_MASK 0x3f #define INSN_STD_MASK 0xf0 #define INSN_STD_DATA_MASK 0x0f #define INSN_POP_TYPE_MASK 0x08 #define INSN_POP_COUNT_MASK 0x07 #define INSN_VSP_LARGE_INC_MASK 0xff /* Instruction definitions */ #define INSN_VSP_INC 0x00 #define INSN_VSP_DEC 0x40 #define INSN_POP_MASKED 0x80 #define INSN_VSP_REG 0x90 #define INSN_POP_COUNT 0xa0 #define INSN_FINISH 0xb0 #define INSN_POP_REGS 0xb1 #define INSN_VSP_LARGE_INC 0xb2 /* An item in the exception index table */ struct unwind_idx { uint32_t offset; uint32_t insn; }; static bool copy_in(void *dst, const void *src, size_t n) { memcpy(dst, src, n); return true; } /* Expand a 31-bit signed value to a 32-bit signed value */ static int32_t expand_prel31(uint32_t prel31) { return prel31 | SHIFT_U32(prel31 & BIT32(30), 1); } /* * Perform a binary search of the index table to find the function * with the largest address that does not exceed addr. */ static struct unwind_idx *find_index(uint32_t addr) { vaddr_t idx_start = 0; vaddr_t idx_end = 0; unsigned int min = 0; unsigned int mid = 0; unsigned int max = 0; struct unwind_idx *start = NULL; struct unwind_idx *item = NULL; int32_t prel31_addr = 0; vaddr_t func_addr = 0; if (!find_exidx(addr, &idx_start, &idx_end)) return NULL; start = (struct unwind_idx *)idx_start; min = 0; max = (idx_end - idx_start) / sizeof(struct unwind_idx); while (min != max) { mid = min + (max - min + 1) / 2; item = &start[mid]; prel31_addr = expand_prel31(item->offset); func_addr = (vaddr_t)&item->offset + prel31_addr; if (func_addr <= addr) min = mid; else max = mid - 1; } return &start[min]; } /* Reads the next byte from the instruction list */ static bool unwind_exec_read_byte(struct unwind_state_arm32 *state, uint32_t *ret_insn) { uint32_t insn; if (!copy_in(&insn, (void *)state->insn, sizeof(insn))) return false; /* Read the unwind instruction */ *ret_insn = (insn >> (state->byte * 8)) & 0xff; /* Update the location of the next instruction */ if (state->byte == 0) { state->byte = 3; state->insn += sizeof(uint32_t); state->entries--; } else { state->byte--; } return true; } static bool pop_vsp(uint32_t *reg, vaddr_t *vsp, vaddr_t stack, size_t stack_size) { if (*vsp < stack) return false; if (*vsp + sizeof(*reg) > stack + stack_size) return false; if (!copy_in(reg, (void *)*vsp, sizeof(*reg))) return false; (*vsp) += sizeof(*reg); return true; } /* Executes the next instruction on the list */ static bool unwind_exec_insn(struct unwind_state_arm32 *state, vaddr_t stack, size_t stack_size) { uint32_t insn; vaddr_t vsp = state->registers[SP]; int update_vsp = 0; /* Read the next instruction */ if (!unwind_exec_read_byte(state, &insn)) return false; if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) { state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4; } else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) { state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4; } else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) { uint32_t mask; unsigned int reg; /* Load the mask */ if (!unwind_exec_read_byte(state, &mask)) return false; mask |= (insn & INSN_STD_DATA_MASK) << 8; /* We have a refuse to unwind instruction */ if (mask == 0) return false; /* Update SP */ update_vsp = 1; /* Load the registers */ for (reg = 4; mask && reg < 16; mask >>= 1, reg++) { if (mask & 1) { if (!pop_vsp(&state->registers[reg], &vsp, stack, stack_size)) return false; state->update_mask |= 1 << reg; /* If we have updated SP kep its value */ if (reg == SP) update_vsp = 0; } } } else if ((insn & INSN_STD_MASK) == INSN_VSP_REG && ((insn & INSN_STD_DATA_MASK) != 13) && ((insn & INSN_STD_DATA_MASK) != 15)) { /* sp = register */ state->registers[SP] = state->registers[insn & INSN_STD_DATA_MASK]; } else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) { unsigned int count, reg; /* Read how many registers to load */ count = insn & INSN_POP_COUNT_MASK; /* Update sp */ update_vsp = 1; /* Pop the registers */ for (reg = 4; reg <= 4 + count; reg++) { if (!pop_vsp(&state->registers[reg], &vsp, stack, stack_size)) return false; state->update_mask |= 1 << reg; } /* Check if we are in the pop r14 version */ if ((insn & INSN_POP_TYPE_MASK) != 0) { if (!pop_vsp(&state->registers[14], &vsp, stack, stack_size)) return false; } } else if (insn == INSN_FINISH) { /* Stop processing */ state->entries = 0; } else if (insn == INSN_POP_REGS) { uint32_t mask; unsigned int reg; if (!unwind_exec_read_byte(state, &mask)) return false; if (mask == 0 || (mask & 0xf0) != 0) return false; /* Update SP */ update_vsp = 1; /* Load the registers */ for (reg = 0; mask && reg < 4; mask >>= 1, reg++) { if (mask & 1) { if (!pop_vsp(&state->registers[reg], &vsp, stack, stack_size)) return false; state->update_mask |= 1 << reg; } } } else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) { uint32_t uleb128; /* Read the increment value */ if (!unwind_exec_read_byte(state, &uleb128)) return false; state->registers[SP] += 0x204 + (uleb128 << 2); } else { /* We hit a new instruction that needs to be implemented */ DMSG("Unhandled instruction %.2x", insn); return false; } if (update_vsp) state->registers[SP] = vsp; return true; } /* Performs the unwind of a function */ static bool unwind_tab(struct unwind_state_arm32 *state, vaddr_t stack, size_t stack_size) { uint32_t entry; uint32_t insn; /* Set PC to a known value */ state->registers[PC] = 0; if (!copy_in(&insn, (void *)state->insn, sizeof(insn))) { DMSG("Bad insn addr %p", (void *)state->insn); return true; } /* Read the personality */ entry = insn & ENTRY_MASK; if (entry == ENTRY_ARM_SU16) { state->byte = 2; state->entries = 1; } else if (entry == ENTRY_ARM_LU16) { state->byte = 1; state->entries = ((insn >> 16) & 0xFF) + 1; } else { DMSG("Unknown entry: %x", entry); return true; } while (state->entries > 0) { if (!unwind_exec_insn(state, stack, stack_size)) return true; } /* * The program counter was not updated, load it from the link register. */ if (state->registers[PC] == 0) { state->registers[PC] = state->registers[LR]; /* * If the program counter changed, flag it in the update mask. */ if (state->start_pc != state->registers[PC]) state->update_mask |= 1 << PC; } return false; } bool unwind_stack_arm32(struct unwind_state_arm32 *state, vaddr_t stack, size_t stack_size) { struct unwind_idx *index; bool finished; /* Reset the mask of updated registers */ state->update_mask = 0; /* The pc value is correct and will be overwritten, save it */ state->start_pc = state->registers[PC]; /* * Find the item to run. Subtract 2 from PC to make sure that we're * still inside the calling function in case a __no_return function * (typically panic()) is called unconditionally and may cause LR and * thus this PC to point into the next and entirely unrelated function. */ index = find_index(state->start_pc - 2); if (!index) return false; finished = false; if (index->insn != EXIDX_CANTUNWIND) { if (index->insn & (1U << 31)) { /* The data is within the instruction */ state->insn = (vaddr_t)&index->insn; } else { /* A prel31 offset to the unwind table */ state->insn = (vaddr_t)&index->insn + expand_prel31(index->insn); } /* Run the unwind function */ finished = unwind_tab(state, stack, stack_size); } /* This is the top of the stack, finish */ if (index->insn == EXIDX_CANTUNWIND) finished = true; return !finished; } void print_stack_arm32(struct unwind_state_arm32 *state, vaddr_t stack, size_t stack_size) { trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); do { trace_printf_helper_raw(TRACE_ERROR, true, " 0x%08" PRIx32, state->registers[PC]); } while (unwind_stack_arm32(state, stack, stack_size)); } optee_os-4.3.0/lib/libunw/unwind_arm64.c000066400000000000000000000054631464416617300201060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /*- * Copyright (c) 2015-2019 Linaro Limited * Copyright (c) 2015 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under * the sponsorship of the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include void __weak ftrace_map_lr(uint64_t *lr __unused) {} void __weak pauth_strip_pac(uint64_t *lr __unused) {} static bool copy_in_reg(uint64_t *reg, vaddr_t addr) { memcpy(reg, (void *)addr, sizeof(*reg)); return true; } bool unwind_stack_arm64(struct unwind_state_arm64 *frame, vaddr_t stack, size_t stack_size) { vaddr_t fp = frame->fp; if (fp < stack) return false; if (fp + sizeof(uint64_t) * 3 > stack + stack_size) return false; frame->sp = fp + 0x10; /* FP to previous frame (X29) */ if (!copy_in_reg(&frame->fp, fp)) return false; if (!frame->fp) return false; /* LR (X30) */ if (!copy_in_reg(&frame->pc, fp + 8)) return false; pauth_strip_pac(&frame->pc); ftrace_map_lr(&frame->pc); frame->pc -= 4; return true; } void print_stack_arm64(struct unwind_state_arm64 *state, vaddr_t stack, size_t stack_size) { vaddr_t va = 0; int width = 8; trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); ftrace_map_lr(&state->pc); do { va = memtag_strip_tag_vaddr((void *)state->pc); trace_printf_helper_raw(TRACE_ERROR, true, " 0x%0*"PRIxVA, width, va); } while (unwind_stack_arm64(state, stack, stack_size)); } optee_os-4.3.0/lib/libunw/unwind_riscv.c000066400000000000000000000037561464416617300203060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /*- * Copyright (c) 2023 Andes Technology Corporation * Copyright (c) 2015-2019 Linaro Limited * Copyright (c) 2015 The FreeBSD Foundation */ #include #include #include #include #include #include void __weak ftrace_map_lr(uint64_t *lr __unused) { } bool unwind_stack_riscv(struct unwind_state_riscv *frame, vaddr_t stack, size_t stack_size) { vaddr_t fp = frame->fp; struct unwind_state_riscv *caller_state = NULL; if (fp < stack) return false; if (fp > stack + stack_size) return false; /* * | ..... | ^ unwind upwards * | ..... | | * +=============+ <--+ | +======= caller FP ==========+ * | RA | | | * +-------------+ | | * | caller FP | ---|-+ ^ * +-------------+ | caller stack frame * | ..... | | v * | ..... | | * | ..... | | * +=============+ | +== caller SP / trapped FP ==+ * | RA | | * +-------------+ | * | caller FP | ---+ ^ * +-------------+ trapped stack frame * | ..... | v * | ..... | * | ..... | * +=============+ +======== trapped SP ========+ * | * | grow downwards * V */ /* Get caller FP and RA */ caller_state = (struct unwind_state_riscv *)fp - 1; frame->fp = caller_state->fp; frame->pc = caller_state->pc; ftrace_map_lr(&frame->pc); frame->pc -= 4; return true; } void print_stack_riscv(struct unwind_state_riscv *state, vaddr_t stack, size_t stack_size) { int width = sizeof(unsigned long); trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:"); ftrace_map_lr(&state->pc); do { trace_printf_helper_raw(TRACE_ERROR, true, " 0x%0*"PRIxVA, width, state->pc); } while (unwind_stack_riscv(state, stack, stack_size)); } optee_os-4.3.0/lib/libutee/000077500000000000000000000000001464416617300155465ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/abort.c000066400000000000000000000004701464416617300170220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include void abort(void) { printf("Abort!\n"); _utee_panic(0); /* Not reached */ while (1) ; } optee_os-4.3.0/lib/libutee/arch/000077500000000000000000000000001464416617300164635ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/arch/arm/000077500000000000000000000000001464416617300172425ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/arch/arm/arm32_user_sysreg.txt000066400000000000000000000007001464416617300233560ustar00rootroot00000000000000# Format of file # # lines beginning with '@' will be printed as additional comments @ Based on register description in @ ARM Architecture Reference Manual @ ARMv7-A and ARMv7-R edition @ Issue C.c @ @ B8.2 Generic Timer registers summary CNTFRQ c14 0 c0 0 RW Counter Frequency register CNTPCT - 0 c14 - RO Physical Count register CNTVCT - 1 c14 - RO Virtual Count register optee_os-4.3.0/lib/libutee/arch/arm/gprof/000077500000000000000000000000001464416617300203575ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/arch/arm/gprof/gmon.h000066400000000000000000000150301464416617300214670ustar00rootroot00000000000000/* SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) */ /* * Copyright (c) 2016, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * This file is adapted from glibc' gmon/sys/gmon.h. *- * Copyright (c) 1982, 1986, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * See gmon_out.h for gmon.out format. */ #ifndef GMON_H #define GMON_H #include #include /* Exported by the TA linker script */ extern uint8_t __text_start[]; extern uint8_t __text_end[]; void __mcount_internal(unsigned long frompc, unsigned long selfpc); /* * Histogram counters are unsigned shorts (according to the kernel). */ #define HISTCOUNTER unsigned short /* * Fraction of text space to allocate for histogram counters here, 1/2 */ #define HISTFRACTION 2 /* * Fraction of text space to allocate for from hash buckets. * The value of HASHFRACTION is based on the minimum number of bytes * of separation between two subroutine call points in the object code. * Given MIN_SUBR_SEPARATION bytes of separation the value of * HASHFRACTION is calculated as: * * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); * * For example, on the VAX, the shortest two call sequence is: * * calls $0,(r0) * calls $0,(r0) * * which is separated by only three bytes, thus HASHFRACTION is * calculated as: * * HASHFRACTION = 3 / (2 * 2 - 1) = 1 * * Note that the division above rounds down, thus if MIN_SUBR_FRACTION * is less than three, this algorithm will not work! * * In practice, however, call instructions are rarely at a minimal * distance. Hence, we will define HASHFRACTION to be 2 across all * architectures. This saves a reasonable amount of space for * profiling data structures without (in practice) sacrificing * any granularity. */ #define HASHFRACTION 2 /* * Percent of text space to allocate for tostructs. * This is a heuristic; we will fail with a warning when profiling programs * with a very large number of very small functions, but that's * normally OK. * 2 is probably still a good value for normal programs. * Profiling a test case with 64000 small functions will work if * you raise this value to 3 and link statically (which bloats the * text size, thus raising the number of arcs expected by the heuristic). */ #define ARCDENSITY 3 /* * Always allocate at least this many tostructs. This * hides the inadequacy of the ARCDENSITY heuristic, at least * for small programs. */ #define MINARCS 50 /* * The type used to represent indices into gmonparam.tos[]. */ #define ARCINDEX unsigned long /* * Maximum number of arcs we want to allow. * Used to be max representable value of ARCINDEX minus 2, but now * that ARCINDEX is a long, that's too large; we don't really want * to allow a 48 gigabyte table. * The old value of 1<<16 wasn't high enough in practice for large C++ * programs; will 1<<20 be adequate for long? FIXME */ #define MAXARCS (1 << 20) struct tostruct { unsigned long selfpc; long count; ARCINDEX link; }; /* * A raw arc, with pointers to the calling site and the called site and a * count. */ struct rawarc { unsigned long raw_frompc; unsigned long raw_selfpc; long raw_count; }; /* * The profiling data structures are housed in this structure. */ struct gmonparam { long int state; unsigned short *kcount; unsigned long kcountsize; ARCINDEX *froms; unsigned long fromssize; struct tostruct *tos; unsigned long tossize; unsigned long tolimit; unsigned long lowpc; unsigned long highpc; unsigned long textsize; unsigned long hashfraction; long log_hashfraction; /* */ uint32_t prof_rate; /* PC sampling frequency */ }; /* * Possible states of profiling. */ #define GMON_PROF_ON 0 #define GMON_PROF_BUSY 1 #define GMON_PROF_ERROR 2 #define GMON_PROF_OFF 3 #define GMON_PROF_OFF_EXITING 4 #endif /* GMON_H */ optee_os-4.3.0/lib/libutee/arch/arm/gprof/gmon_out.h000066400000000000000000000112531464416617300223610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * gmon.out file format * * This file is adapted from glibc's gmon/sys/gmon_out.h * Although gmon/sys/gmon_out.h is covered by the LGPL v2.1 license or later * as stated below, please note the following: * (https://www.gnu.org/licenses/lgpl-3.0.en.html#section3) * * "3. Object Code Incorporating Material from Library Header Files. * The object code form of an Application may incorporate material from a * header file that is part of the Library. You may convey such object code * under terms of your choice, provided that, if the incorporated material * is not limited to numerical parameters, data structure layouts and * accessors, or small macros, inline functions and templates (ten or fewer * lines in length), you do both of the following: [...]" * * The code below is indeed limited to data structure layouts. */ /* * Copyright (C) 1996-2016 Free Software Foundation, Inc. * This file is part of the GNU C Library. * Contributed by David Mosberger . * * The GNU C Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The GNU C Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the GNU C Library; if not, see * . */ /* * This file specifies the format of gmon.out files. It should have * as few external dependencies as possible as it is going to be included * in many different programs. That is, minimize the number of #include's. * * A gmon.out file consists of a header (defined by gmon_hdr) followed by * a sequence of records. Each record starts with a one-byte tag * identifying the type of records, followed by records specific data. */ #ifndef GMON_OUT_H #define GMON_OUT_H #define GMON_MAGIC "gmon" /* magic cookie */ #define GMON_VERSION 1 /* version number */ /* * Raw header as it appears on file (without padding). This header * always comes first in gmon.out and is then followed by a series * records defined below. * Virtual addresses are stored as uintptr_t, gprof knows which size to expect * because the executable file is provided. */ struct gmon_hdr { char cookie[4]; int32_t version; char spare[3 * 4]; } __packed; /* types of records in this file: */ enum gmon_record_tag { GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2 }; struct gmon_hist_hdr { uintptr_t low_pc; /* base pc address of sample buffer */ uintptr_t high_pc; /* max pc address of sampled buffer */ uint32_t hist_size; /* size of sample buffer */ uint32_t prof_rate; /* profiling clock rate */ char dimen[15]; /* phys. dim., usually "seconds" */ char dimen_abbrev; /* usually 's' for "seconds" */ } __packed; struct gmon_cg_arc_record { uintptr_t from_pc; /* address within caller's body */ uintptr_t self_pc; /* address within callee's body */ int32_t count; /* number of arc traversals */ } __packed; #endif /* GMON_OUT_H */ optee_os-4.3.0/lib/libutee/arch/arm/gprof/gprof.c000066400000000000000000000300011464416617300216320ustar00rootroot00000000000000// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) /* * Copyright (c) 2016, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Portions of this file are adapted from glibc: * gmon/gmon.c * gmon/mcount.c * *- * Copyright (c) 1983, 1992, 1993, 2011 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "gmon.h" #include "gmon_out.h" #include "gprof_pta.h" static void *gprof_buf; static size_t gprof_buf_len; #if defined(ARM32) #define MCOUNT_SYM __gnu_mcount_nc #elif defined(ARM64) #define MCOUNT_SYM _mcount #endif static void dummy(void) {} void (*MCOUNT_SYM)(void) __weak = dummy; static bool ta_instrumented(void) { /* * Return true if the mcount function is called somewhere (and therefore * profiling should be initialized). * Since gprof is not supported with shared libraries, checking if * mcount is called is the same as checking if it is present in the * TA binary, because the function would be eliminated at link time if * not used. */ return dummy != MCOUNT_SYM; } #undef MCOUNT_SYM static void *gprof_alloc(size_t len) { assert(!gprof_buf); gprof_buf = tee_map_zi(len, TEE_MEMORY_ACCESS_ANY_OWNER); gprof_buf_len = len; return gprof_buf; } static struct gmonparam _gmonparam = { GMON_PROF_OFF }; static uint32_t _gprof_file_id; /* File id returned by tee-supplicant */ static int _gprof_s_scale; #define SCALE_1_TO_1 0x10000L /* Adjust PC so that gprof can locate it in the TA ELF file */ static unsigned long __noprof adjust_pc(unsigned long pc) { return pc - (unsigned long)__text_start + sizeof(struct ta_head); } void __utee_gprof_init(void) { unsigned long lowpc; unsigned long highpc; struct gmonparam *p = &_gmonparam; size_t bufsize; TEE_Result res; char *cp; if (!ta_instrumented()) return; lowpc = adjust_pc((unsigned long)__text_start); highpc = adjust_pc((unsigned long)__text_end); /* * Round lowpc and highpc to multiples of the density we're using * so the rest of the scaling (here and in gprof) stays in ints. */ p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); p->textsize = p->highpc - p->lowpc; p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); p->hashfraction = HASHFRACTION; p->log_hashfraction = -1; /* * The following test must be kept in sync with the corresponding * test in __mcount_internal */ if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { /* * If HASHFRACTION is a power of two, mcount can use shifting * instead of integer division. Precompute shift amount. */ p->log_hashfraction = __builtin_ffs(p->hashfraction * sizeof(*p->froms)) - 1; } p->fromssize = p->textsize / HASHFRACTION; p->tolimit = p->textsize * ARCDENSITY / 100; if (p->tolimit < MINARCS) p->tolimit = MINARCS; else if (p->tolimit > MAXARCS) p->tolimit = MAXARCS; p->tossize = p->tolimit * sizeof(struct tostruct); bufsize = p->kcountsize + p->fromssize + p->tossize; IMSG("gprof: initializing"); DMSG("TA text size: %zu, gprof buffer size: %zu", __text_end - __text_start, bufsize); cp = gprof_alloc(bufsize); if (!cp) { EMSG("gprof: could not allocate profiling buffer"); p->tos = NULL; p->state = GMON_PROF_ERROR; return; } p->tos = (struct tostruct *)cp; cp += p->tossize; p->kcount = (HISTCOUNTER *)cp; cp += p->kcountsize; p->froms = (ARCINDEX *)cp; p->tos[0].link = 0; if (p->kcountsize < p->textsize) _gprof_s_scale = ((float)p->kcountsize / p->textsize) * SCALE_1_TO_1; else _gprof_s_scale = SCALE_1_TO_1; res = __pta_gprof_pc_sampling_start(p->kcount, p->kcountsize, p->lowpc + ((unsigned long)__text_start - sizeof(struct ta_head)), _gprof_s_scale); if (res != TEE_SUCCESS) EMSG("gprof: could not start PC sampling (0x%08x)", res); p->state = GMON_PROF_ON; } static void _gprof_write_buf(void *buf, size_t size) { TEE_Result res; res = __pta_gprof_send(buf, size, &_gprof_file_id); if (res != TEE_SUCCESS) EMSG("gprof: could not send gprof data (0x%08x)", res); } static void _gprof_write_header(void) { struct gmon_hdr ghdr; size_t size = sizeof(struct gmon_hdr); memcpy(&ghdr.cookie[0], GMON_MAGIC, sizeof(ghdr.cookie)); ghdr.version = GMON_VERSION; memset(ghdr.spare, '\0', sizeof(ghdr.spare)); _gprof_write_buf(&ghdr, size); } static void _gprof_write_hist(void) { struct out_record { uint8_t tag; struct gmon_hist_hdr hist_hdr; } __packed out = { .tag = GMON_TAG_TIME_HIST, .hist_hdr = { .low_pc = _gmonparam.lowpc, .high_pc = _gmonparam.highpc, .hist_size = _gmonparam.kcountsize/sizeof(HISTCOUNTER), .prof_rate = _gmonparam.prof_rate, .dimen = "seconds", .dimen_abbrev = 's', } }; _gprof_write_buf(&out, sizeof(out)); _gprof_write_buf(_gmonparam.kcount, _gmonparam.kcountsize); } static void _gprof_write_call_graph(void) { #define NARCS_PER_WRITE 16 struct out_record { uint8_t tag; uint8_t data[sizeof(struct gmon_cg_arc_record)]; } out[NARCS_PER_WRITE]; struct gmon_cg_arc_record arc; ARCINDEX from_index, to_index; unsigned long from_len; unsigned long frompc; int nfilled = 0; from_len = _gmonparam.fromssize / sizeof(*_gmonparam.froms); for (from_index = 0; from_index < from_len; ++from_index) { if (_gmonparam.froms[from_index] == 0) continue; frompc = _gmonparam.lowpc; frompc += (from_index * _gmonparam.hashfraction * sizeof(*_gmonparam.froms)); for (to_index = _gmonparam.froms[from_index]; to_index != 0; to_index = _gmonparam.tos[to_index].link) { arc.from_pc = frompc; arc.self_pc = _gmonparam.tos[to_index].selfpc; arc.count = _gmonparam.tos[to_index].count; out[nfilled].tag = GMON_TAG_CG_ARC; memcpy(out[nfilled].data, &arc, sizeof(arc)); if (++nfilled == NARCS_PER_WRITE) { _gprof_write_buf(out, sizeof(out)); nfilled = 0; } } } if (nfilled > 0) _gprof_write_buf(out, nfilled * sizeof(out[0])); } /* Stop profiling and send profile data in gmon.out format to Normal World */ void __utee_gprof_fini(void) { TEE_Result res; if (_gmonparam.state != GMON_PROF_ON) return; /* Stop call graph tracing */ _gmonparam.state = GMON_PROF_OFF_EXITING; /* Stop TA sampling */ res = __pta_gprof_pc_sampling_stop(&_gmonparam.prof_rate); _gprof_write_header(); if (res == TEE_SUCCESS) _gprof_write_hist(); _gprof_write_call_graph(); __pta_gprof_fini(); if (gprof_buf) { res = tee_unmap(gprof_buf, gprof_buf_len); assert(!res); gprof_buf = NULL; } } /* * Called from the assembly stub (_mcount or __gnu_mcount_nc). * * __mcount_internal updates data structures that represent traversals of the * program's call graph edges. frompc and selfpc are the return * address and function address that represents the given call graph edge. */ void __noprof __mcount_internal(unsigned long frompc, unsigned long selfpc) { ARCINDEX *frompcindex; struct tostruct *top, *prevtop; struct gmonparam *p; ARCINDEX toindex; int i; p = &_gmonparam; /* * Check that we are profiling and that we aren't recursively invoked. */ if (p->state != GMON_PROF_ON) return; p->state = GMON_PROF_BUSY; frompc = adjust_pc(frompc); selfpc = adjust_pc(selfpc); /* Check that frompcindex is a reasonable pc value. */ frompc -= p->lowpc; if (frompc > p->textsize) goto done; /* Note: keep in sync. with the initialization function above */ if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { /* Avoid integer divide if possible */ i = frompc >> p->log_hashfraction; } else { i = frompc / (p->hashfraction * sizeof(*p->froms)); } frompcindex = &p->froms[i]; toindex = *frompcindex; if (toindex == 0) { /* First time traversing this arc */ toindex = ++p->tos[0].link; if (toindex >= p->tolimit) { /* Halt further profiling */ goto overflow; } *frompcindex = toindex; top = &p->tos[toindex]; top->selfpc = selfpc; top->count = 1; top->link = 0; goto done; } top = &p->tos[toindex]; if (top->selfpc == selfpc) { /* Arc at front of chain; usual case */ top->count++; goto done; } /* * Have to go looking down chain for it. * top points to what we are looking at, * prevtop points to previous top. * we know it is not at the head of the chain. */ for (;;) { if (top->link == 0) { /* * top is end of the chain and none of the chain * had top->selfpc == selfpc. * so we allocate a new tostruct * and link it to the head of the chain. */ toindex = ++p->tos[0].link; if (toindex >= p->tolimit) goto overflow; top = &p->tos[toindex]; top->selfpc = selfpc; top->count = 1; top->link = *frompcindex; *frompcindex = toindex; goto done; } /* * Otherwise, check the next arc on the chain. */ prevtop = top; top = &p->tos[top->link]; if (top->selfpc == selfpc) { /* * There it is. Increment its count, move it to the * head of the chain. */ top->count++; toindex = prevtop->link; prevtop->link = top->link; top->link = *frompcindex; *frompcindex = toindex; goto done; } } done: p->state = GMON_PROF_ON; return; overflow: p->state = GMON_PROF_ERROR; } optee_os-4.3.0/lib/libutee/arch/arm/gprof/gprof_pta.c000066400000000000000000000044651464416617300225150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016, Linaro Limited */ #include #include #include #include "gprof_pta.h" static TEE_TASessionHandle sess = TEE_HANDLE_NULL; static TEE_Result invoke_gprof_pta(uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { static const TEE_UUID core_uuid = PTA_GPROF_UUID; TEE_Result res; if (!sess) { res = TEE_OpenTASession(&core_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, NULL); if (res != TEE_SUCCESS) return res; } res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, param_types, params, NULL); return res; } TEE_Result __pta_gprof_send(void *buf, size_t len, uint32_t *id) { TEE_Param params[TEE_NUM_PARAMS]; uint32_t param_types; TEE_Result res; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); params[0].value.a = *id; params[1].memref.buffer = buf; params[1].memref.size = len; res = invoke_gprof_pta(PTA_GPROF_SEND, param_types, params); if (res == TEE_SUCCESS) *id = params[0].value.a; return res; } TEE_Result __pta_gprof_pc_sampling_start(void *buf, size_t len, size_t offset, size_t scale) { TEE_Param params[TEE_NUM_PARAMS]; uint32_t param_types; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); params[0].memref.buffer = buf; params[0].memref.size = len; params[1].value.a = offset; params[1].value.b = scale; return invoke_gprof_pta(PTA_GPROF_START_PC_SAMPLING, param_types, params); } TEE_Result __pta_gprof_pc_sampling_stop(uint32_t *rate) { TEE_Param params[TEE_NUM_PARAMS]; uint32_t param_types; TEE_Result res; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); res = invoke_gprof_pta(PTA_GPROF_STOP_PC_SAMPLING, param_types, params); if (res != TEE_SUCCESS) return res; if (rate) *rate = params[0].value.a; return res; } void __pta_gprof_fini(void) { if (sess) TEE_CloseTASession(sess); } optee_os-4.3.0/lib/libutee/arch/arm/gprof/gprof_pta.h000066400000000000000000000007671464416617300225230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __GPROF_PTA_H #define __GPROF_PTA_H #include #include #include #include TEE_Result __pta_gprof_send(void *buf, size_t len, uint32_t *id); TEE_Result __pta_gprof_pc_sampling_start(void *buf, size_t len, size_t offset, size_t scale); TEE_Result __pta_gprof_pc_sampling_stop(uint32_t *rate); void __pta_gprof_fini(void); #endif /* __GPROF_PTA_H */ optee_os-4.3.0/lib/libutee/arch/arm/gprof/sub.mk000066400000000000000000000002411464416617300214760ustar00rootroot00000000000000cppflags-y += -I$(sub-dir)/../../.. srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c srcs-$(CFG_TA_GPROF_SUPPORT) += gprof_pta.c cflags-remove-gprof.c-y += -Wcast-align optee_os-4.3.0/lib/libutee/arch/arm/sub.mk000066400000000000000000000003021464416617300203570ustar00rootroot00000000000000cppflags-y += -I$(sub-dir)/../.. srcs-$(CFG_ARM32_$(sm)) += utee_syscalls_a32.S srcs-$(CFG_ARM64_$(sm)) += utee_syscalls_a64.S ifneq ($(sm),ldelf) subdirs-y += gprof endif #$(sm-$(sm)-is-ld) optee_os-4.3.0/lib/libutee/arch/arm/utee_syscalls_a32.S000066400000000000000000000025211464416617300227120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include .section .note.GNU-stack,"",%progbits .section .text .balign 4 .code 32 .macro UTEE_SYSCALL name, scn, num_args FUNC \name , : push {r5-r7,lr} UNWIND( .save {r5-r7,lr}) #if defined(CFG_SYSCALL_WRAPPERS_MCOUNT) && !defined(__LDELF__) .if \scn != TEE_SCN_RETURN mov ip, sp push {r0-r4, fp, ip} add fp, ip, #16 push {lr} bl __gnu_mcount_nc pop {r0-r4, fp, ip} mov sp, ip .endif #endif mov r7, #(\scn) .if \num_args > TEE_SVC_MAX_ARGS .error "Too many arguments for syscall" .endif .if \num_args <= 4 @ No arguments passed on stack mov r6, #0 .else @ Tell number of arguments passed on the stack mov r6, #(\num_args - 4) @ Point just before the push (4 registers) above on the first argument add r5, sp, #(4 * 4) .endif svc #0 pop {r5-r7,pc} END_FUNC \name .endm FUNC _utee_panic, : push {r0-r11, lr} UNWIND( .save {r0-r11, lr}) mov lr, pc push {lr} UNWIND( .save {lr}) mov r1, sp bl __utee_panic /* Not reached */ END_FUNC _utee_panic #include optee_os-4.3.0/lib/libutee/arch/arm/utee_syscalls_a64.S000066400000000000000000000020021464416617300227110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #include #include .section .text .macro UTEE_SYSCALL name, scn, num_args FUNC \name , : .if \num_args > TEE_SVC_MAX_ARGS || \num_args > 8 .error "Too many arguments for syscall" .endif #if defined(CFG_SYSCALL_WRAPPERS_MCOUNT) && !defined(__LDELF__) .if \scn != TEE_SCN_RETURN stp x29, x30, [sp, #-80]! mov x29, sp stp x0, x1, [sp, #16] stp x2, x3, [sp, #32] stp x4, x5, [sp, #48] stp x6, x7, [sp, #64] mov x0, x30 bl _mcount ldp x0, x1, [sp, #16] ldp x2, x3, [sp, #32] ldp x4, x5, [sp, #48] ldp x6, x7, [sp, #64] ldp x29, x30, [sp], #80 .endif #endif mov x8, #(\scn) svc #0 ret END_FUNC \name .endm FUNC _utee_panic, : stp x29, x30, [sp, #-16]! mov x1, sp bl __utee_panic /* Not reached */ END_FUNC _utee_panic #include BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/lib/libutee/arch/riscv/000077500000000000000000000000001464416617300176115ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/arch/riscv/sub.mk000066400000000000000000000000771464416617300207370ustar00rootroot00000000000000cppflags-y += -I$(sub-dir)/../.. srcs-y += utee_syscalls_rv.S optee_os-4.3.0/lib/libutee/arch/riscv/utee_syscalls_rv.S000066400000000000000000000016701464416617300233270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation * Copyright 2022 Beijing ESWIN Computing Technology Co., Ltd. */ #include #include .section .text .macro UTEE_SYSCALL name, scn, num_args FUNC \name , : .if \num_args > TEE_SVC_MAX_ARGS || \num_args > 8 .error "Too many arguments for syscall" .endif li t0, \scn li t1, \num_args ecall ret END_FUNC \name .endm FUNC _utee_panic, : /* The stack pointer is always kept 16-byte aligned */ add sp, sp, -16 /* Save return address and frame pointer to stack */ #if defined(RV32) sw s0, 8(sp) sw ra, 12(sp) #elif defined(RV64) sd s0, 0(sp) sd ra, 8(sp) #endif /* Assign a1 as stack pointer for scall_save_panic_stack() */ mv a1, sp /* Use tail call here because we will not return from it */ tail __utee_panic /* Not reached */ END_FUNC _utee_panic #include optee_os-4.3.0/lib/libutee/assert.c000066400000000000000000000011531464416617300172130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include void _assert_log(const char *expr __maybe_unused, const char *file __maybe_unused, const int line __maybe_unused, const char *func __maybe_unused) { EMSG_RAW("assertion '%s' failed at %s:%d in %s()", expr, file, line, func); } void __noreturn _assert_break(void) { _utee_panic(TEE_ERROR_GENERIC); /* Not reached */ while (1) ; } optee_os-4.3.0/lib/libutee/base64.c000066400000000000000000000044631464416617300170050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #include "base64.h" static const char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; size_t _base64_enc_len(size_t size) { return 4 * ((size + 2) / 3) + 1; } bool _base64_enc(const void *data, size_t dlen, char *buf, size_t *blen) { size_t n = 0; size_t boffs = 0; const unsigned char *d = data; n = _base64_enc_len(dlen); if (*blen < n) { *blen = n; return false; } for (n = 0; n < dlen; n += 3) { uint32_t igrp; igrp = d[n]; igrp <<= 8; if ((n + 1) < dlen) igrp |= d[n + 1]; igrp <<= 8; if ((n + 2) < dlen) igrp |= d[n + 2]; buf[boffs] = base64_table[(igrp >> 18) & 0x3f]; buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f]; if ((n + 1) < dlen) buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f]; else buf[boffs + 2] = '='; if ((n + 2) < dlen) buf[boffs + 3] = base64_table[igrp & 0x3f]; else buf[boffs + 3] = '='; boffs += 4; } buf[boffs++] = '\0'; *blen = boffs; return true; } static bool get_idx(char ch, uint8_t *idx) { size_t n = 0; for (n = 0; base64_table[n] != '\0'; n++) { if (ch == base64_table[n]) { *idx = n; return true; } } return false; } bool _base64_dec(const char *data, size_t size, void *buf, size_t *blen) { bool ret = false; size_t n = 0; uint8_t idx = 0; uint8_t *b = buf; size_t m = 0; size_t s = 0; uint8_t byte = 0; for (n = 0; n < size && data[n] != '\0'; n++) { if (data[n] == '=') break; /* Reached pad characters, we're done */ if (!get_idx(data[n], &idx)) continue; switch (s) { case 0: byte = idx << 2; s++; break; case 1: if (b && m < *blen) b[m] = byte | (idx >> 4); m++; byte = (idx & 0xf) << 4; s++; break; case 2: if (b && m < *blen) b[m] = byte | (idx >> 2); m++; byte = (idx & 0x3) << 6; s++; break; case 3: if (b && m < *blen) b[m] = byte | idx; m++; s = 0; break; default: return false; /* "Can't happen" */ } } /* * We don't detect if input was bad, but that's OK with the spec. * We expect that each fully extracted byte is stored in output buffer. */ ret = (!m && !*blen) || (b && (m <= *blen)); *blen = m; return ret; } optee_os-4.3.0/lib/libutee/base64.h000066400000000000000000000006411464416617300170040ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef BASE64_H #define BASE64_H #include #include #include bool _base64_enc(const void *data, size_t size, char *buf, size_t *blen); bool _base64_dec(const char *data, size_t size, void *buf, size_t *blen); size_t _base64_enc_len(size_t size); #endif /* BASE64_H */ optee_os-4.3.0/lib/libutee/include/000077500000000000000000000000001464416617300171715ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/include/__tee_ipsocket.h000066400000000000000000000005171464416617300223210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef ____TEE_IPSOCKET_H #define ____TEE_IPSOCKET_H typedef enum TEE_ipSocket_ipVersion_e { TEE_IP_VERSION_DC = 0, /* don’t care */ TEE_IP_VERSION_4 = 1, TEE_IP_VERSION_6 = 2 } TEE_ipSocket_ipVersion; #endif /*____TEE_IPSOCKET_H*/ optee_os-4.3.0/lib/libutee/include/__tee_isocket_defines.h000066400000000000000000000011151464416617300236310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef ____TEE_ISOCKET_DEFINES_H #define ____TEE_ISOCKET_DEFINES_H #define TEE_ISOCKET_VERSION 0x01000000 #define TEE_ISOCKET_ERROR_PROTOCOL 0xF1007001 #define TEE_ISOCKET_ERROR_REMOTE_CLOSED 0xF1007002 #define TEE_ISOCKET_ERROR_TIMEOUT 0xF1007003 #define TEE_ISOCKET_ERROR_OUT_OF_RESOURCES 0xF1007004 #define TEE_ISOCKET_ERROR_LARGE_BUFFER 0xF1007005 #define TEE_ISOCKET_WARNING_PROTOCOL 0xF1007006 #define TEE_ISOCKET_ERROR_HOSTNAME 0xF1007007 #endif /*____TEE_ISOCKET_DEFINES_H*/ optee_os-4.3.0/lib/libutee/include/__tee_tcpsocket_defines.h000066400000000000000000000005631464416617300241750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef ____TEE_TCPSOCKET_DEFINES_H #define ____TEE_TCPSOCKET_DEFINES_H /* Protocol identifier */ #define TEE_ISOCKET_PROTOCOLID_TCP 0x65 /* Instance specific errors */ #define TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1010002 #endif /*____TEE_TCPSOCKET_DEFINES_H*/ optee_os-4.3.0/lib/libutee/include/__tee_tcpsocket_defines_extensions.h000066400000000000000000000005721464416617300264540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H #define ____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H /* Instance and implementation specific ioctl functions */ #define TEE_TCP_SET_RECVBUF 0x65f00000 #define TEE_TCP_SET_SENDBUF 0x65f00001 #endif /*____TEE_TCPSOCKET_DEFINES_EXTENSIONS_H*/ optee_os-4.3.0/lib/libutee/include/__tee_udpsocket_defines.h000066400000000000000000000007531464416617300242000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef ____TEE_UDPSOCKET_DEFINES_H #define ____TEE_UDPSOCKET_DEFINES_H /* Protocol identifier */ #define TEE_ISOCKET_PROTOCOLID_UDP 0x66 /* Instance specific errors */ #define TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND 0xF1020002 /* Instance specific ioctl functions */ #define TEE_UDP_CHANGEADDR 0x66000001 #define TEE_UDP_CHANGEPORT 0x66000002 #endif /*____TEE_UDPSOCKET_DEFINES_H*/ optee_os-4.3.0/lib/libutee/include/arm64_user_sysreg.h000066400000000000000000000021001464416617300227160ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef ARM64_USER_SYSREG_H #define ARM64_USER_SYSREG_H #include #include /* * Templates for register read/write functions based on mrs/msr */ #define DEFINE_REG_READ_FUNC_(reg, type, asmreg) \ static inline __noprof type read_##reg(void) \ { \ uint64_t val64 = 0; \ \ asm volatile("mrs %0, " #asmreg : "=r" (val64)); \ return val64; \ } #define DEFINE_REG_WRITE_FUNC_(reg, type, asmreg) \ static inline __noprof void write_##reg(type val) \ { \ uint64_t val64 = val; \ \ asm volatile("msr " #asmreg ", %0" : : "r" (val64)); \ } /* ARM Generic timer functions */ DEFINE_REG_READ_FUNC_(cntfrq, uint32_t, cntfrq_el0) DEFINE_REG_READ_FUNC_(cntpct, uint64_t, cntpct_el0) DEFINE_REG_READ_FUNC_(cntvct, uint64_t, cntvct_el0) DEFINE_REG_READ_FUNC_(tpidr_el0, uint64_t, tpidr_el0) DEFINE_REG_WRITE_FUNC_(tpidr_el0, uint64_t, tpidr_el0) DEFINE_REG_READ_FUNC_(dczid_el0, uint64_t, dczid_el0) #endif /*ARM64_USER_SYSREG_H*/ optee_os-4.3.0/lib/libutee/include/arm_user_sysreg.h000066400000000000000000000010501464416617300225470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef ARM_USER_SYSREG_H #define ARM_USER_SYSREG_H #include #ifdef ARM32 #include #endif #ifdef ARM64 #include #endif #ifndef __ASSEMBLER__ static inline __noprof void isb(void) { asm volatile ("isb"); } static inline __noprof uint64_t barrier_read_counter_timer(void) { isb(); #ifdef CFG_CORE_SEL2_SPMC return read_cntvct(); #else return read_cntpct(); #endif } #endif #endif /*ARM_USER_SYSREG_H*/ optee_os-4.3.0/lib/libutee/include/elf.h000066400000000000000000000033571464416617300201200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #ifndef _ELF_H_ #define _ELF_H_ #if defined(ARM32) || defined(RV32) #include typedef Elf32_Addr Elf_Addr; typedef Elf32_Half Elf_Half; typedef Elf32_Off Elf_Off; typedef Elf32_Sword Elf_Sword; typedef Elf32_Word Elf_Word; typedef Elf32_Lword Elf_Lword; typedef Elf32_Hashelt Elf_Hashelt; typedef Elf32_Size Elf_Size; typedef Elf32_Ssize Elf_Ssize; typedef Elf32_Ehdr Elf_Ehdr; typedef Elf32_Shdr Elf_Shdr; typedef Elf32_Phdr Elf_Phdr; typedef Elf32_Dyn Elf_Dyn; typedef Elf32_Rel Elf_Rel; typedef Elf32_Rela Elf_Rela; typedef Elf32_Move Elf_Move; typedef Elf32_Cap Elf_Cap; typedef Elf32_Sym Elf_Sym; typedef Elf32_Verdef Elf_Verdef; typedef Elf32_Verdaux Elf_Verdaux; typedef Elf32_Verneed Elf_Verneed; typedef Elf32_Vernaux Elf_Vernaux; typedef Elf32_Syminfo Elf_Syminfo; #elif defined(ARM64) || defined(RV64) #include typedef Elf64_Addr Elf_Addr; typedef Elf64_Half Elf_Half; typedef Elf64_Off Elf_Off; typedef Elf64_Sword Elf_Sword; typedef Elf64_Sxword Elf_Sxword; typedef Elf64_Word Elf_Word; typedef Elf64_Lword Elf_Lword; typedef Elf64_Xword Elf_Xword; typedef Elf64_Hashelt Elf_Hashelt; typedef Elf64_Size Elf_Size; typedef Elf64_Ssize Elf_Ssize; typedef Elf64_Ehdr Elf_Ehdr; typedef Elf64_Shdr Elf_Shdr; typedef Elf64_Phdr Elf_Phdr; typedef Elf64_Dyn Elf_Dyn; typedef Elf64_Rel Elf_Rel; typedef Elf64_Rela Elf_Rela; typedef Elf64_Move Elf_Move; typedef Elf64_Cap Elf_Cap; typedef Elf64_Sym Elf_Sym; typedef Elf64_Verdef Elf_Verdef; typedef Elf64_Verdaux Elf_Verdaux; typedef Elf64_Verneed Elf_Verneed; typedef Elf64_Vernaux Elf_Vernaux; typedef Elf64_Syminfo Elf_Syminfo; #else #error Unknown architecture #endif #endif /* _ELF_H_ */ optee_os-4.3.0/lib/libutee/include/elf32.h000066400000000000000000000160071464416617300202610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /*- * Copyright (c) 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_ELF32_H_ #define _SYS_ELF32_H_ 1 #include #include /* * ELF definitions common to all 32-bit architectures. */ typedef uint32_t Elf32_Addr; typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; typedef int32_t Elf32_Sword; typedef uint32_t Elf32_Word; typedef uint64_t Elf32_Lword; typedef Elf32_Word Elf32_Hashelt; /* Non-standard class-dependent datatype used for abstraction. */ typedef Elf32_Word Elf32_Size; typedef Elf32_Sword Elf32_Ssize; /* * ELF header. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf32_Half e_type; /* File type. */ Elf32_Half e_machine; /* Machine architecture. */ Elf32_Word e_version; /* ELF format version. */ Elf32_Addr e_entry; /* Entry point. */ Elf32_Off e_phoff; /* Program header file offset. */ Elf32_Off e_shoff; /* Section header file offset. */ Elf32_Word e_flags; /* Architecture-specific flags. */ Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ Elf32_Half e_phentsize; /* Size of program header entry. */ Elf32_Half e_phnum; /* Number of program header entries. */ Elf32_Half e_shentsize; /* Size of section header entry. */ Elf32_Half e_shnum; /* Number of section header entries. */ Elf32_Half e_shstrndx; /* Section name strings section. */ } Elf32_Ehdr; /* * Section header. */ typedef struct { Elf32_Word sh_name; /* Section name (index into the section header string table). */ Elf32_Word sh_type; /* Section type. */ Elf32_Word sh_flags; /* Section flags. */ Elf32_Addr sh_addr; /* Address in memory image. */ Elf32_Off sh_offset; /* Offset in file. */ Elf32_Word sh_size; /* Size in bytes. */ Elf32_Word sh_link; /* Index of a related section. */ Elf32_Word sh_info; /* Depends on section type. */ Elf32_Word sh_addralign; /* Alignment in bytes. */ Elf32_Word sh_entsize; /* Size of each entry in section. */ } Elf32_Shdr; /* * Program header. */ typedef struct { Elf32_Word p_type; /* Entry type. */ Elf32_Off p_offset; /* File offset of contents. */ Elf32_Addr p_vaddr; /* Virtual address in memory image. */ Elf32_Addr p_paddr; /* Physical address (not used). */ Elf32_Word p_filesz; /* Size of contents in file. */ Elf32_Word p_memsz; /* Size of contents in memory. */ Elf32_Word p_flags; /* Access permission flags. */ Elf32_Word p_align; /* Alignment in memory and file. */ } Elf32_Phdr; /* * Dynamic structure. The ".dynamic" section contains an array of them. */ typedef struct { Elf32_Sword d_tag; /* Entry type. */ union { Elf32_Word d_val; /* Integer value. */ Elf32_Addr d_ptr; /* Address value. */ } d_un; } Elf32_Dyn; /* * Relocation entries. */ /* Relocations that don't need an addend field. */ typedef struct { Elf32_Addr r_offset; /* Location to be relocated. */ Elf32_Word r_info; /* Relocation type and symbol index. */ } Elf32_Rel; /* Relocations that need an addend field. */ typedef struct { Elf32_Addr r_offset; /* Location to be relocated. */ Elf32_Word r_info; /* Relocation type and symbol index. */ Elf32_Sword r_addend; /* Addend. */ } Elf32_Rela; /* Macros for accessing the fields of r_info. */ #define ELF32_R_SYM(info) ((info) >> 8) #define ELF32_R_TYPE(info) ((unsigned char)(info)) /* Macro for constructing r_info from field values. */ #define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) /* * Note entry header */ typedef Elf_Note Elf32_Nhdr; /* * Move entry */ typedef struct { Elf32_Lword m_value; /* symbol value */ Elf32_Word m_info; /* size + index */ Elf32_Word m_poffset; /* symbol offset */ Elf32_Half m_repeat; /* repeat count */ Elf32_Half m_stride; /* stride info */ } Elf32_Move; /* * The macros compose and decompose values for Move.r_info * * sym = ELF32_M_SYM(M.m_info) * size = ELF32_M_SIZE(M.m_info) * M.m_info = ELF32_M_INFO(sym, size) */ #define ELF32_M_SYM(info) ((info)>>8) #define ELF32_M_SIZE(info) ((unsigned char)(info)) #define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) /* * Hardware/Software capabilities entry */ typedef struct { Elf32_Word c_tag; /* how to interpret value */ union { Elf32_Word c_val; Elf32_Addr c_ptr; } c_un; } Elf32_Cap; /* * Symbol table entries. */ typedef struct { Elf32_Word st_name; /* String table index of name. */ Elf32_Addr st_value; /* Symbol value. */ Elf32_Word st_size; /* Size of associated object. */ unsigned char st_info; /* Type and binding information. */ unsigned char st_other; /* Reserved (not used). */ Elf32_Half st_shndx; /* Section index of symbol. */ } Elf32_Sym; /* Macros for accessing the fields of st_info. */ #define ELF32_ST_BIND(info) ((info) >> 4) #define ELF32_ST_TYPE(info) ((info) & 0xf) /* Macro for constructing st_info from field values. */ #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) /* Macro for accessing the fields of st_other. */ #define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) /* Structures used by Sun & GNU symbol versioning. */ typedef struct { Elf32_Half vd_version; Elf32_Half vd_flags; Elf32_Half vd_ndx; Elf32_Half vd_cnt; Elf32_Word vd_hash; Elf32_Word vd_aux; Elf32_Word vd_next; } Elf32_Verdef; typedef struct { Elf32_Word vda_name; Elf32_Word vda_next; } Elf32_Verdaux; typedef struct { Elf32_Half vn_version; Elf32_Half vn_cnt; Elf32_Word vn_file; Elf32_Word vn_aux; Elf32_Word vn_next; } Elf32_Verneed; typedef struct { Elf32_Word vna_hash; Elf32_Half vna_flags; Elf32_Half vna_other; Elf32_Word vna_name; Elf32_Word vna_next; } Elf32_Vernaux; typedef Elf32_Half Elf32_Versym; typedef struct { Elf32_Half si_boundto; /* direct bindings - symbol bound to */ Elf32_Half si_flags; /* per symbol flags */ } Elf32_Syminfo; #endif /* !_SYS_ELF32_H_ */ optee_os-4.3.0/lib/libutee/include/elf64.h000066400000000000000000000164751464416617300202770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /*- * Copyright (c) 1996-1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_ELF64_H_ #define _SYS_ELF64_H_ 1 #include #include /* * ELF definitions common to all 64-bit architectures. */ typedef uint64_t Elf64_Addr; typedef uint16_t Elf64_Half; typedef uint64_t Elf64_Off; typedef int32_t Elf64_Sword; typedef int64_t Elf64_Sxword; typedef uint32_t Elf64_Word; typedef uint64_t Elf64_Lword; typedef uint64_t Elf64_Xword; /* * Types of dynamic symbol hash table bucket and chain elements. * * This is inconsistent among 64 bit architectures, so a machine dependent * typedef is required. */ typedef Elf64_Word Elf64_Hashelt; /* Non-standard class-dependent datatype used for abstraction. */ typedef Elf64_Xword Elf64_Size; typedef Elf64_Sxword Elf64_Ssize; /* * ELF header. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* File identification. */ Elf64_Half e_type; /* File type. */ Elf64_Half e_machine; /* Machine architecture. */ Elf64_Word e_version; /* ELF format version. */ Elf64_Addr e_entry; /* Entry point. */ Elf64_Off e_phoff; /* Program header file offset. */ Elf64_Off e_shoff; /* Section header file offset. */ Elf64_Word e_flags; /* Architecture-specific flags. */ Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ Elf64_Half e_phentsize; /* Size of program header entry. */ Elf64_Half e_phnum; /* Number of program header entries. */ Elf64_Half e_shentsize; /* Size of section header entry. */ Elf64_Half e_shnum; /* Number of section header entries. */ Elf64_Half e_shstrndx; /* Section name strings section. */ } Elf64_Ehdr; /* * Section header. */ typedef struct { Elf64_Word sh_name; /* Section name (index into the section header string table). */ Elf64_Word sh_type; /* Section type. */ Elf64_Xword sh_flags; /* Section flags. */ Elf64_Addr sh_addr; /* Address in memory image. */ Elf64_Off sh_offset; /* Offset in file. */ Elf64_Xword sh_size; /* Size in bytes. */ Elf64_Word sh_link; /* Index of a related section. */ Elf64_Word sh_info; /* Depends on section type. */ Elf64_Xword sh_addralign; /* Alignment in bytes. */ Elf64_Xword sh_entsize; /* Size of each entry in section. */ } Elf64_Shdr; /* * Program header. */ typedef struct { Elf64_Word p_type; /* Entry type. */ Elf64_Word p_flags; /* Access permission flags. */ Elf64_Off p_offset; /* File offset of contents. */ Elf64_Addr p_vaddr; /* Virtual address in memory image. */ Elf64_Addr p_paddr; /* Physical address (not used). */ Elf64_Xword p_filesz; /* Size of contents in file. */ Elf64_Xword p_memsz; /* Size of contents in memory. */ Elf64_Xword p_align; /* Alignment in memory and file. */ } Elf64_Phdr; /* * Dynamic structure. The ".dynamic" section contains an array of them. */ typedef struct { Elf64_Sxword d_tag; /* Entry type. */ union { Elf64_Xword d_val; /* Integer value. */ Elf64_Addr d_ptr; /* Address value. */ } d_un; } Elf64_Dyn; /* * Relocation entries. */ /* Relocations that don't need an addend field. */ typedef struct { Elf64_Addr r_offset; /* Location to be relocated. */ Elf64_Xword r_info; /* Relocation type and symbol index. */ } Elf64_Rel; /* Relocations that need an addend field. */ typedef struct { Elf64_Addr r_offset; /* Location to be relocated. */ Elf64_Xword r_info; /* Relocation type and symbol index. */ Elf64_Sxword r_addend; /* Addend. */ } Elf64_Rela; /* Macros for accessing the fields of r_info. */ #define ELF64_R_SYM(info) ((info) >> 32) #define ELF64_R_TYPE(info) ((info) & 0xffffffffL) /* Macro for constructing r_info from field values. */ #define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) #define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) #define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) #define ELF64_R_TYPE_INFO(data, type) \ (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) /* * Note entry header */ typedef Elf_Note Elf64_Nhdr; /* * Move entry */ typedef struct { Elf64_Lword m_value; /* symbol value */ Elf64_Xword m_info; /* size + index */ Elf64_Xword m_poffset; /* symbol offset */ Elf64_Half m_repeat; /* repeat count */ Elf64_Half m_stride; /* stride info */ } Elf64_Move; #define ELF64_M_SYM(info) ((info)>>8) #define ELF64_M_SIZE(info) ((unsigned char)(info)) #define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) /* * Hardware/Software capabilities entry */ typedef struct { Elf64_Xword c_tag; /* how to interpret value */ union { Elf64_Xword c_val; Elf64_Addr c_ptr; } c_un; } Elf64_Cap; /* * Symbol table entries. */ typedef struct { Elf64_Word st_name; /* String table index of name. */ unsigned char st_info; /* Type and binding information. */ unsigned char st_other; /* Reserved (not used). */ Elf64_Half st_shndx; /* Section index of symbol. */ Elf64_Addr st_value; /* Symbol value. */ Elf64_Xword st_size; /* Size of associated object. */ } Elf64_Sym; /* Macros for accessing the fields of st_info. */ #define ELF64_ST_BIND(info) ((info) >> 4) #define ELF64_ST_TYPE(info) ((info) & 0xf) /* Macro for constructing st_info from field values. */ #define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) /* Macro for accessing the fields of st_other. */ #define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) /* Structures used by Sun & GNU-style symbol versioning. */ typedef struct { Elf64_Half vd_version; Elf64_Half vd_flags; Elf64_Half vd_ndx; Elf64_Half vd_cnt; Elf64_Word vd_hash; Elf64_Word vd_aux; Elf64_Word vd_next; } Elf64_Verdef; typedef struct { Elf64_Word vda_name; Elf64_Word vda_next; } Elf64_Verdaux; typedef struct { Elf64_Half vn_version; Elf64_Half vn_cnt; Elf64_Word vn_file; Elf64_Word vn_aux; Elf64_Word vn_next; } Elf64_Verneed; typedef struct { Elf64_Word vna_hash; Elf64_Half vna_flags; Elf64_Half vna_other; Elf64_Word vna_name; Elf64_Word vna_next; } Elf64_Vernaux; typedef Elf64_Half Elf64_Versym; typedef struct { Elf64_Half si_boundto; /* direct bindings - symbol bound to */ Elf64_Half si_flags; /* per symbol flags */ } Elf64_Syminfo; #endif /* !_SYS_ELF64_H_ */ optee_os-4.3.0/lib/libutee/include/elf_common.h000066400000000000000000001272151464416617300214700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /*- * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien * Copyright (c) 1998 John D. Polstra. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_ELF_COMMON_H_ #define _SYS_ELF_COMMON_H_ 1 #include /* * ELF definitions that are independent of architecture or word size. */ #ifndef __ASSEMBLER__ /* * Note header. The ".note" section contains an array of notes. Each * begins with this header, aligned to a word boundary. Immediately * following the note header is n_namesz bytes of name, padded to the * next word boundary. Then comes n_descsz bytes of descriptor, again * padded to a word boundary. The values of n_namesz and n_descsz do * not include the padding. */ typedef struct { uint32_t n_namesz; /* Length of name. */ uint32_t n_descsz; /* Length of descriptor. */ uint32_t n_type; /* Type of this note. */ } Elf_Note; /* * The header for GNU-style hash sections. */ typedef struct { uint32_t gh_nbuckets; /* Number of hash buckets. */ uint32_t gh_symndx; /* First visible symbol in .dynsym. */ uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ uint32_t gh_shift2; /* Bloom filter shift count. */ } Elf_GNU_Hash_Header; /* * Program Property Array */ typedef struct { uint32_t pr_type; uint32_t pr_datasz; } Elf_Prop; #endif /*__ASSEMBLER__*/ /* Indexes into the e_ident array. Keep synced with http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ #define EI_MAG0 0 /* Magic number, byte 0. */ #define EI_MAG1 1 /* Magic number, byte 1. */ #define EI_MAG2 2 /* Magic number, byte 2. */ #define EI_MAG3 3 /* Magic number, byte 3. */ #define EI_CLASS 4 /* Class of machine. */ #define EI_DATA 5 /* Data format. */ #define EI_VERSION 6 /* ELF format version. */ #define EI_OSABI 7 /* Operating system / ABI identification */ #define EI_ABIVERSION 8 /* ABI version */ #define OLD_EI_BRAND 8 /* Start of architecture identification. */ #define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ #define EI_NIDENT 16 /* Size of e_ident array. */ /* Values for the magic number bytes. */ #define ELFMAG0 0x7f #define ELFMAG1 'E' #define ELFMAG2 'L' #define ELFMAG3 'F' #define ELFMAG "\177ELF" /* magic string */ #define SELFMAG 4 /* magic string size */ /* Values for e_ident[EI_VERSION] and e_version. */ #define EV_NONE 0 #define EV_CURRENT 1 /* Values for e_ident[EI_CLASS]. */ #define ELFCLASSNONE 0 /* Unknown class. */ #define ELFCLASS32 1 /* 32-bit architecture. */ #define ELFCLASS64 2 /* 64-bit architecture. */ /* Values for e_ident[EI_DATA]. */ #define ELFDATANONE 0 /* Unknown data format. */ #define ELFDATA2LSB 1 /* 2's complement little-endian. */ #define ELFDATA2MSB 2 /* 2's complement big-endian. */ /* Values for e_ident[EI_OSABI]. */ #define ELFOSABI_NONE 0 /* UNIX System V ABI */ #define ELFOSABI_HPUX 1 /* HP-UX operating system */ #define ELFOSABI_NETBSD 2 /* NetBSD */ #define ELFOSABI_LINUX 3 /* GNU/Linux */ #define ELFOSABI_HURD 4 /* GNU/Hurd */ #define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ #define ELFOSABI_SOLARIS 6 /* Solaris */ #define ELFOSABI_AIX 7 /* AIX */ #define ELFOSABI_IRIX 8 /* IRIX */ #define ELFOSABI_FREEBSD 9 /* FreeBSD */ #define ELFOSABI_TRU64 10 /* TRU64 UNIX */ #define ELFOSABI_MODESTO 11 /* Novell Modesto */ #define ELFOSABI_OPENBSD 12 /* OpenBSD */ #define ELFOSABI_OPENVMS 13 /* Open VMS */ #define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ #define ELFOSABI_AROS 15 /* Amiga Research OS */ #define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ #define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ #define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ /* e_ident */ #define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ (ehdr).e_ident[EI_MAG3] == ELFMAG3) /* Values for e_type. */ #define ET_NONE 0 /* Unknown type. */ #define ET_REL 1 /* Relocatable. */ #define ET_EXEC 2 /* Executable. */ #define ET_DYN 3 /* Shared object. */ #define ET_CORE 4 /* Core file. */ #define ET_LOOS 0xfe00 /* First operating system specific. */ #define ET_HIOS 0xfeff /* Last operating system-specific. */ #define ET_LOPROC 0xff00 /* First processor-specific. */ #define ET_HIPROC 0xffff /* Last processor-specific. */ /* Values for e_machine. */ #define EM_NONE 0 /* Unknown machine. */ #define EM_M32 1 /* AT&T WE32100. */ #define EM_SPARC 2 /* Sun SPARC. */ #define EM_386 3 /* Intel i386. */ #define EM_68K 4 /* Motorola 68000. */ #define EM_88K 5 /* Motorola 88000. */ #define EM_860 7 /* Intel i860. */ #define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ #define EM_S370 9 /* IBM System/370. */ #define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ #define EM_PARISC 15 /* HP PA-RISC. */ #define EM_VPP500 17 /* Fujitsu VPP500. */ #define EM_SPARC32PLUS 18 /* SPARC v8plus. */ #define EM_960 19 /* Intel 80960. */ #define EM_PPC 20 /* PowerPC 32-bit. */ #define EM_PPC64 21 /* PowerPC 64-bit. */ #define EM_S390 22 /* IBM System/390. */ #define EM_V800 36 /* NEC V800. */ #define EM_FR20 37 /* Fujitsu FR20. */ #define EM_RH32 38 /* TRW RH-32. */ #define EM_RCE 39 /* Motorola RCE. */ #define EM_ARM 40 /* ARM. */ #define EM_SH 42 /* Hitachi SH. */ #define EM_SPARCV9 43 /* SPARC v9 64-bit. */ #define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ #define EM_ARC 45 /* Argonaut RISC Core. */ #define EM_H8_300 46 /* Hitachi H8/300. */ #define EM_H8_300H 47 /* Hitachi H8/300H. */ #define EM_H8S 48 /* Hitachi H8S. */ #define EM_H8_500 49 /* Hitachi H8/500. */ #define EM_IA_64 50 /* Intel IA-64 Processor. */ #define EM_MIPS_X 51 /* Stanford MIPS-X. */ #define EM_COLDFIRE 52 /* Motorola ColdFire. */ #define EM_68HC12 53 /* Motorola M68HC12. */ #define EM_MMA 54 /* Fujitsu MMA. */ #define EM_PCP 55 /* Siemens PCP. */ #define EM_NCPU 56 /* Sony nCPU. */ #define EM_NDR1 57 /* Denso NDR1 microprocessor. */ #define EM_STARCORE 58 /* Motorola Star*Core processor. */ #define EM_ME16 59 /* Toyota ME16 processor. */ #define EM_ST100 60 /* STMicroelectronics ST100 processor. */ #define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ #define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ #define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ #define EM_PDSP 63 /* Sony DSP Processor. */ #define EM_FX66 66 /* Siemens FX66 microcontroller. */ #define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 microcontroller. */ #define EM_ST7 68 /* STmicroelectronics ST7 8-bit microcontroller. */ #define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ #define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ #define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ #define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ #define EM_SVX 73 /* Silicon Graphics SVx. */ #define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ #define EM_VAX 75 /* Digital VAX. */ #define EM_CRIS 76 /* Axis Communications 32-bit embedded processor. */ #define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor. */ #define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ #define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ #define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ #define EM_HUANY 81 /* Harvard University machine-independent object files. */ #define EM_PRISM 82 /* SiTera Prism. */ #define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ #define EM_FR30 84 /* Fujitsu FR30. */ #define EM_D10V 85 /* Mitsubishi D10V. */ #define EM_D30V 86 /* Mitsubishi D30V. */ #define EM_V850 87 /* NEC v850. */ #define EM_M32R 88 /* Mitsubishi M32R. */ #define EM_MN10300 89 /* Matsushita MN10300. */ #define EM_MN10200 90 /* Matsushita MN10200. */ #define EM_PJ 91 /* picoJava. */ #define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ #define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ #define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ #define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ #define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor. */ #define EM_NS32K 97 /* National Semiconductor 32000 series. */ #define EM_TPC 98 /* Tenor Network TPC processor. */ #define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ #define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ #define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ #define EM_MAX 102 /* MAX Processor. */ #define EM_CR 103 /* National Semiconductor CompactRISC microprocessor. */ #define EM_F2MC16 104 /* Fujitsu F2MC16. */ #define EM_MSP430 105 /* Texas Instruments embedded microcontroller msp430. */ #define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ #define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ #define EM_SEP 108 /* Sharp embedded microprocessor. */ #define EM_ARCA 109 /* Arca RISC Microprocessor. */ #define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */ #define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ #define EM_RISCV 243 /* RISC-V */ /* Non-standard or deprecated. */ #define EM_486 6 /* Intel i486. */ #define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ #define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ #define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ /* e_flags for EM_ARM */ #define EF_ARM_ABI_UNKNOWN 0x00000000 #define EF_ARM_ABI_V5 0x05000000 /* ABI version 5 */ #define EF_ARM_ABIMASK 0xFF000000 #define EF_ARM_BE8 0x00800000 #define EF_ARM_ABI_FLOAT_HARD 0x00000400 /* ABI version 5 and later */ #define EF_ARM_ABI_FLOAT_SOFT 0x00000200 /* ABI version 5 and later */ /* Special section indexes. */ #define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ #define SHN_LORESERVE 0xff00 /* First of reserved range. */ #define SHN_LOPROC 0xff00 /* First processor-specific. */ #define SHN_HIPROC 0xff1f /* Last processor-specific. */ #define SHN_LOOS 0xff20 /* First operating system-specific. */ #define SHN_HIOS 0xff3f /* Last operating system-specific. */ #define SHN_ABS 0xfff1 /* Absolute values. */ #define SHN_COMMON 0xfff2 /* Common data. */ #define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ #define SHN_HIRESERVE 0xffff /* Last of reserved range. */ /* sh_type */ #define SHT_NULL 0 /* inactive */ #define SHT_PROGBITS 1 /* program defined information */ #define SHT_SYMTAB 2 /* symbol table section */ #define SHT_STRTAB 3 /* string table section */ #define SHT_RELA 4 /* relocation section with addends */ #define SHT_HASH 5 /* symbol hash table section */ #define SHT_DYNAMIC 6 /* dynamic section */ #define SHT_NOTE 7 /* note section */ #define SHT_NOBITS 8 /* no space section */ #define SHT_REL 9 /* relocation section - no addends */ #define SHT_SHLIB 10 /* reserved - purpose unknown */ #define SHT_DYNSYM 11 /* dynamic symbol table section */ #define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ #define SHT_FINI_ARRAY 15 /* Termination function pointers. */ #define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ #define SHT_GROUP 17 /* Section group. */ #define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ #define SHT_LOOS 0x60000000 /* First of OS specific semantics */ #define SHT_LOSUNW 0x6ffffff4 #define SHT_SUNW_dof 0x6ffffff4 #define SHT_SUNW_cap 0x6ffffff5 #define SHT_SUNW_SIGNATURE 0x6ffffff6 #define SHT_GNU_HASH 0x6ffffff6 #define SHT_GNU_LIBLIST 0x6ffffff7 #define SHT_SUNW_ANNOTATE 0x6ffffff7 #define SHT_SUNW_DEBUGSTR 0x6ffffff8 #define SHT_SUNW_DEBUG 0x6ffffff9 #define SHT_SUNW_move 0x6ffffffa #define SHT_SUNW_COMDAT 0x6ffffffb #define SHT_SUNW_syminfo 0x6ffffffc #define SHT_SUNW_verdef 0x6ffffffd #define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ #define SHT_SUNW_verneed 0x6ffffffe #define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ #define SHT_SUNW_versym 0x6fffffff #define SHT_GNU_versym 0x6fffffff /* Symbol version table */ #define SHT_HISUNW 0x6fffffff #define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ #define SHT_LOPROC 0x70000000 /* reserved range for processor */ #define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ #define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ #define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map. */ #define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes. */ #define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ #define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ #define SHT_MIPS_REGINFO 0x70000006 #define SHT_MIPS_OPTIONS 0x7000000d #define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ #define SHT_HIPROC 0x7fffffff /* specific section header types */ #define SHT_LOUSER 0x80000000 /* reserved range for application */ #define SHT_HIUSER 0xffffffff /* specific indexes */ /* Flags for sh_flags. */ #define SHF_WRITE 0x1 /* Section contains writable data. */ #define SHF_ALLOC 0x2 /* Section occupies memory. */ #define SHF_EXECINSTR 0x4 /* Section contains instructions. */ #define SHF_MERGE 0x10 /* Section may be merged. */ #define SHF_STRINGS 0x20 /* Section contains strings. */ #define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ #define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ #define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ #define SHF_GROUP 0x200 /* Member of section group. */ #define SHF_TLS 0x400 /* Section contains TLS data. */ #define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ #define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ /* Values for p_type. */ #define PT_NULL 0 /* Unused entry. */ #define PT_LOAD 1 /* Loadable segment. */ #define PT_DYNAMIC 2 /* Dynamic linking information segment. */ #define PT_INTERP 3 /* Pathname of interpreter. */ #define PT_NOTE 4 /* Auxiliary information. */ #define PT_SHLIB 5 /* Reserved (not used). */ #define PT_PHDR 6 /* Location of program header itself. */ #define PT_TLS 7 /* Thread local storage segment */ #define PT_LOOS 0x60000000 /* First OS-specific. */ #define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ #define PT_GNU_EH_FRAME 0x6474e550 #define PT_GNU_STACK 0x6474e551 #define PT_GNU_RELRO 0x6474e552 #define PT_GNU_PROPERTY 0x6474e553 #define PT_LOSUNW 0x6ffffffa #define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ #define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ #define PT_SUNWDTRACE 0x6ffffffc /* private */ #define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ #define PT_HISUNW 0x6fffffff #define PT_HIOS 0x6fffffff /* Last OS-specific. */ #define PT_LOPROC 0x70000000 /* First processor-specific type. */ #define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ #define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ /* Values for p_flags. */ #define PF_X 0x1 /* Executable. */ #define PF_W 0x2 /* Writable. */ #define PF_R 0x4 /* Readable. */ #define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ #define PF_MASKPROC 0xf0000000 /* Processor-specific. */ /* Extended program header index. */ #define PN_XNUM 0xffff /* Values for d_tag. */ #define DT_NULL 0 /* Terminating entry. */ #define DT_NEEDED 1 /* String table offset of a needed shared library. */ #define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ #define DT_PLTGOT 3 /* Processor-dependent address. */ #define DT_HASH 4 /* Address of symbol hash table. */ #define DT_STRTAB 5 /* Address of string table. */ #define DT_SYMTAB 6 /* Address of symbol table. */ #define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ #define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ #define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ #define DT_STRSZ 10 /* Size of string table. */ #define DT_SYMENT 11 /* Size of each symbol table entry. */ #define DT_INIT 12 /* Address of initialization function. */ #define DT_FINI 13 /* Address of finalization function. */ #define DT_SONAME 14 /* String table offset of shared object name. */ #define DT_RPATH 15 /* String table offset of library path. [sup] */ #define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ #define DT_REL 17 /* Address of ElfNN_Rel relocations. */ #define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ #define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ #define DT_PLTREL 20 /* Type of relocation used for PLT. */ #define DT_DEBUG 21 /* Reserved (not used). */ #define DT_TEXTREL 22 /* Indicates there may be relocations in non-writable segments. [sup] */ #define DT_JMPREL 23 /* Address of PLT relocations. */ #define DT_BIND_NOW 24 /* [sup] */ #define DT_INIT_ARRAY 25 /* Address of the array of pointers to initialization functions */ #define DT_FINI_ARRAY 26 /* Address of the array of pointers to termination functions */ #define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of initialization functions. */ #define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of termination functions. */ #define DT_RUNPATH 29 /* String table offset of a null-terminated library search path string. */ #define DT_FLAGS 30 /* Object specific flag values. */ #define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING and less than DT_LOOS follow the rules for the interpretation of the d_un union as follows: even == 'd_ptr', odd == 'd_val' or none */ #define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to pre-initialization functions. */ #define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of pre-initialization functions. */ #define DT_MAXPOSTAGS 34 /* number of positive tags */ #define DT_LOOS 0x6000000d /* First OS-specific */ #define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ #define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ #define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ #define DT_SUNW_CAP 0x60000010 /* hardware/software */ #define DT_HIOS 0x6ffff000 /* Last OS-specific */ /* * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the * Dyn.d_un.d_val field of the Elf*_Dyn structure. */ #define DT_VALRNGLO 0x6ffffd00 #define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ #define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ #define DT_MOVEENT 0x6ffffdfa /* move table entry size */ #define DT_MOVESZ 0x6ffffdfb /* move table size */ #define DT_FEATURE_1 0x6ffffdfc /* feature holder */ #define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ /* the following DT_* entry. */ /* See DF_P1_* definitions */ #define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ #define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ #define DT_VALRNGHI 0x6ffffdff /* * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. * * If any adjustment is made to the ELF object after it has been * built, these entries will need to be adjusted. */ #define DT_ADDRRNGLO 0x6ffffe00 #define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ #define DT_CONFIG 0x6ffffefa /* configuration information */ #define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ #define DT_AUDIT 0x6ffffefc /* object auditing */ #define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ #define DT_MOVETAB 0x6ffffefe /* move table */ #define DT_SYMINFO 0x6ffffeff /* syminfo table */ #define DT_ADDRRNGHI 0x6ffffeff #define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ #define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ #define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ #define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ #define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ #define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ #define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ #define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ #define DT_LOPROC 0x70000000 /* First processor-specific type. */ #define DT_DEPRECATED_SPARC_REGISTER 0x7000001 #define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ #define DT_USED 0x7ffffffe /* ignored - same as needed */ #define DT_FILTER 0x7fffffff /* shared library filter name */ #define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ /* Values for DT_FLAGS */ #define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may make reference to the $ORIGIN substitution string */ #define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ #define DF_TEXTREL 0x0004 /* Indicates there may be relocations in non-writable segments. */ #define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should process all relocations for the object containing this entry before transferring control to the program. */ #define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or executable contains code using a static thread-local storage scheme. */ /* Values for DT_FLAGS_1 */ #define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ #define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ #define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ #define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ #define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ #define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ #define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ #define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ /* Note section names */ #define ELF_NOTE_FREEBSD "FreeBSD" #define ELF_NOTE_NETBSD "NetBSD" #define ELF_NOTE_SOLARIS "SUNW Solaris" #define ELF_NOTE_GNU "GNU" /* Values for n_type. Used in core files. */ #define NT_PRSTATUS 1 /* Process status. */ #define NT_FPREGSET 2 /* Floating point registers. */ #define NT_PRPSINFO 3 /* Process state info. */ #define NT_THRMISC 7 /* Thread miscellaneous info. */ #define NT_PROCSTAT_PROC 8 /* Procstat proc data. */ #define NT_PROCSTAT_FILES 9 /* Procstat files data. */ #define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ #define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */ #define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */ #define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ #define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ #define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ #define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ /* GNU note types. */ #define NT_GNU_ABI_TAG 1 #define NT_GNU_HWCAP 2 #define NT_GNU_BUILD_ID 3 #define NT_GNU_GOLD_VERSION 4 #define NT_GNU_PROPERTY_TYPE_0 5 #define GNU_PROPERTY_LOPROC 0xc0000000 #define GNU_PROPERTY_HIPROC 0xdfffffff #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 0x00000001 #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 0x00000002 #define GNU_PROPERTY_X86_FEATURE_1_AND 0xc0000002 /* Symbol Binding - ELFNN_ST_BIND - st_info */ #define STB_LOCAL 0 /* Local symbol */ #define STB_GLOBAL 1 /* Global symbol */ #define STB_WEAK 2 /* like global - lower precedence */ #define STB_LOOS 10 /* Reserved range for operating system */ #define STB_HIOS 12 /* specific semantics. */ #define STB_LOPROC 13 /* reserved range for processor */ #define STB_HIPROC 15 /* specific semantics. */ /* Symbol type - ELFNN_ST_TYPE - st_info */ #define STT_NOTYPE 0 /* Unspecified type. */ #define STT_OBJECT 1 /* Data object. */ #define STT_FUNC 2 /* Function. */ #define STT_SECTION 3 /* Section. */ #define STT_FILE 4 /* Source file. */ #define STT_COMMON 5 /* Uninitialized common block. */ #define STT_TLS 6 /* TLS object. */ #define STT_NUM 7 #define STT_LOOS 10 /* Reserved range for operating system */ #define STT_GNU_IFUNC 10 #define STT_HIOS 12 /* specific semantics. */ #define STT_LOPROC 13 /* reserved range for processor */ #define STT_HIPROC 15 /* specific semantics. */ /* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ #define STV_DEFAULT 0x0 /* Default visibility (see binding). */ #define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ #define STV_HIDDEN 0x2 /* Not visible. */ #define STV_PROTECTED 0x3 /* Visible but not preemptible. */ #define STV_EXPORTED 0x4 #define STV_SINGLETON 0x5 #define STV_ELIMINATE 0x6 /* Special symbol table indexes. */ #define STN_UNDEF 0 /* Undefined symbol index. */ /* Symbol versioning flags. */ #define VER_DEF_CURRENT 1 #define VER_DEF_IDX(x) VER_NDX(x) #define VER_FLG_BASE 0x01 #define VER_FLG_WEAK 0x02 #define VER_NEED_CURRENT 1 #define VER_NEED_WEAK (1u << 15) #define VER_NEED_HIDDEN VER_NDX_HIDDEN #define VER_NEED_IDX(x) VER_NDX(x) #define VER_NDX_LOCAL 0 #define VER_NDX_GLOBAL 1 #define VER_NDX_GIVEN 2 #define VER_NDX_HIDDEN (1u << 15) #define VER_NDX(x) ((x) & ~(1u << 15)) #define CA_SUNW_NULL 0 #define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ #define CA_SUNW_SF_1 2 /* first software capabilities entry */ /* * Syminfo flag values */ #define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ /* to object containing defn. */ #define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ #define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ #define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ /* lazily-loaded */ #define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ /* object containing defn. */ #define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ /* directly bind to this symbol */ #define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ #define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ /* * Syminfo.si_boundto values. */ #define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ #define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ #define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ #define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ #define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ /* * Syminfo version values. */ #define SYMINFO_NONE 0 /* Syminfo version */ #define SYMINFO_CURRENT 1 #define SYMINFO_NUM 2 /* * Relocation types. * * All machine architectures are defined here to allow tools on one to * handle others. */ #define R_386_NONE 0 /* No relocation. */ #define R_386_32 1 /* Add symbol value. */ #define R_386_PC32 2 /* Add PC-relative symbol value. */ #define R_386_GOT32 3 /* Add PC-relative GOT offset. */ #define R_386_PLT32 4 /* Add PC-relative PLT offset. */ #define R_386_COPY 5 /* Copy data from shared object. */ #define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ #define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ #define R_386_RELATIVE 8 /* Add load address of shared object. */ #define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ #define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ #define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ #define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ #define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ #define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ #define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ #define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ #define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ #define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ #define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ #define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ #define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ #define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ #define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ #define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ #define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ #define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ #define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ #define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ #define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ #define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ #define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ #define R_RISCV_NONE 0 /* No relocation. */ #define R_RISCV_64 2 /* 64-bit relocation. */ #define R_RISCV_RELATIVE 3 /* Adjust a link address (A) to its load address (B + A). */ #define R_RISCV_JUMP_SLOT 5 /* Indicates the symbol associated with a PLT entry. */ #define R_AARCH64_NONE 0 /* No relocation. */ #define R_AARCH64_ABS64 257 #define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address. */ #define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address. */ #define R_AARCH64_RELATIVE 1027 /* Add load address of shared object. */ #define R_AARCH64_TLS_TPREL 1030 /* Offset of the TLS block in the TCB */ #define R_AARCH64_TLSDESC 1031 /* TLS descriptor to be filled */ #define R_ARM_NONE 0 /* No relocation. */ #define R_ARM_PC24 1 #define R_ARM_ABS32 2 #define R_ARM_REL32 3 #define R_ARM_PC13 4 #define R_ARM_ABS16 5 #define R_ARM_ABS12 6 #define R_ARM_THM_ABS5 7 #define R_ARM_ABS8 8 #define R_ARM_SBREL32 9 #define R_ARM_THM_PC22 10 #define R_ARM_THM_PC8 11 #define R_ARM_AMP_VCALL9 12 #define R_ARM_SWI24 13 #define R_ARM_THM_SWI8 14 #define R_ARM_XPC25 15 #define R_ARM_THM_XPC22 16 /* TLS relocations */ #define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ #define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ #define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ #define R_ARM_COPY 20 /* Copy data from shared object. */ #define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ #define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ #define R_ARM_RELATIVE 23 /* Add load address of shared object. */ #define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ #define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ #define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ #define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ #define R_ARM_GNU_VTENTRY 100 #define R_ARM_GNU_VTINHERIT 101 #define R_ARM_RSBREL32 250 #define R_ARM_THM_RPC22 251 #define R_ARM_RREL32 252 #define R_ARM_RABS32 253 #define R_ARM_RPC24 254 #define R_ARM_RBASE 255 /* Name Value Field Calculation */ #define R_IA_64_NONE 0 /* None */ #define R_IA_64_IMM14 0x21 /* immediate14 S + A */ #define R_IA_64_IMM22 0x22 /* immediate22 S + A */ #define R_IA_64_IMM64 0x23 /* immediate64 S + A */ #define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ #define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ #define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ #define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ #define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ #define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ #define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ #define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ #define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ #define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ #define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ #define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ #define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ #define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ #define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ #define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ #define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ #define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ #define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ #define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ #define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ #define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ #define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ #define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ #define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ #define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ #define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ #define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ #define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ #define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ #define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ #define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ #define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ #define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ #define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ #define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ #define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ #define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ #define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ #define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ #define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ #define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ #define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ #define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ #define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ #define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ #define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ #define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ #define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ #define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ #define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ #define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ #define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ #define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ #define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ #define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ #define R_IA_64_SUB 0x85 /* immediate64 A - S */ #define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ #define R_IA_64_LDXMOV 0x87 /* immediate22 special */ #define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ #define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ #define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ #define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ #define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ #define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ #define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ #define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ #define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ #define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ #define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ #define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ #define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ #define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ #define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ #define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ #define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ #define R_MIPS_NONE 0 /* No reloc */ #define R_MIPS_16 1 /* Direct 16 bit */ #define R_MIPS_32 2 /* Direct 32 bit */ #define R_MIPS_REL32 3 /* PC relative 32 bit */ #define R_MIPS_26 4 /* Direct 26 bit shifted */ #define R_MIPS_HI16 5 /* High 16 bit */ #define R_MIPS_LO16 6 /* Low 16 bit */ #define R_MIPS_GPREL16 7 /* GP relative 16 bit */ #define R_MIPS_LITERAL 8 /* 16 bit literal entry */ #define R_MIPS_GOT16 9 /* 16 bit GOT entry */ #define R_MIPS_PC16 10 /* PC relative 16 bit */ #define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ #define R_MIPS_GPREL32 12 /* GP relative 32 bit */ #define R_MIPS_64 18 /* Direct 64 bit */ #define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ #define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ #define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ #define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ #define R_PPC_NONE 0 /* No relocation. */ #define R_PPC_ADDR32 1 #define R_PPC_ADDR24 2 #define R_PPC_ADDR16 3 #define R_PPC_ADDR16_LO 4 #define R_PPC_ADDR16_HI 5 #define R_PPC_ADDR16_HA 6 #define R_PPC_ADDR14 7 #define R_PPC_ADDR14_BRTAKEN 8 #define R_PPC_ADDR14_BRNTAKEN 9 #define R_PPC_REL24 10 #define R_PPC_REL14 11 #define R_PPC_REL14_BRTAKEN 12 #define R_PPC_REL14_BRNTAKEN 13 #define R_PPC_GOT16 14 #define R_PPC_GOT16_LO 15 #define R_PPC_GOT16_HI 16 #define R_PPC_GOT16_HA 17 #define R_PPC_PLTREL24 18 #define R_PPC_COPY 19 #define R_PPC_GLOB_DAT 20 #define R_PPC_JMP_SLOT 21 #define R_PPC_RELATIVE 22 #define R_PPC_LOCAL24PC 23 #define R_PPC_UADDR32 24 #define R_PPC_UADDR16 25 #define R_PPC_REL32 26 #define R_PPC_PLT32 27 #define R_PPC_PLTREL32 28 #define R_PPC_PLT16_LO 29 #define R_PPC_PLT16_HI 30 #define R_PPC_PLT16_HA 31 #define R_PPC_SDAREL16 32 #define R_PPC_SECTOFF 33 #define R_PPC_SECTOFF_LO 34 #define R_PPC_SECTOFF_HI 35 #define R_PPC_SECTOFF_HA 36 /* * 64-bit relocations */ #define R_PPC64_ADDR64 38 #define R_PPC64_ADDR16_HIGHER 39 #define R_PPC64_ADDR16_HIGHERA 40 #define R_PPC64_ADDR16_HIGHEST 41 #define R_PPC64_ADDR16_HIGHESTA 42 #define R_PPC64_UADDR64 43 #define R_PPC64_REL64 44 #define R_PPC64_PLT64 45 #define R_PPC64_PLTREL64 46 #define R_PPC64_TOC16 47 #define R_PPC64_TOC16_LO 48 #define R_PPC64_TOC16_HI 49 #define R_PPC64_TOC16_HA 50 #define R_PPC64_TOC 51 #define R_PPC64_DTPMOD64 68 #define R_PPC64_TPREL64 73 #define R_PPC64_DTPREL64 78 /* * TLS relocations */ #define R_PPC_TLS 67 #define R_PPC_DTPMOD32 68 #define R_PPC_TPREL16 69 #define R_PPC_TPREL16_LO 70 #define R_PPC_TPREL16_HI 71 #define R_PPC_TPREL16_HA 72 #define R_PPC_TPREL32 73 #define R_PPC_DTPREL16 74 #define R_PPC_DTPREL16_LO 75 #define R_PPC_DTPREL16_HI 76 #define R_PPC_DTPREL16_HA 77 #define R_PPC_DTPREL32 78 #define R_PPC_GOT_TLSGD16 79 #define R_PPC_GOT_TLSGD16_LO 80 #define R_PPC_GOT_TLSGD16_HI 81 #define R_PPC_GOT_TLSGD16_HA 82 #define R_PPC_GOT_TLSLD16 83 #define R_PPC_GOT_TLSLD16_LO 84 #define R_PPC_GOT_TLSLD16_HI 85 #define R_PPC_GOT_TLSLD16_HA 86 #define R_PPC_GOT_TPREL16 87 #define R_PPC_GOT_TPREL16_LO 88 #define R_PPC_GOT_TPREL16_HI 89 #define R_PPC_GOT_TPREL16_HA 90 /* * The remaining relocs are from the Embedded ELF ABI, and are not in the * SVR4 ELF ABI. */ #define R_PPC_EMB_NADDR32 101 #define R_PPC_EMB_NADDR16 102 #define R_PPC_EMB_NADDR16_LO 103 #define R_PPC_EMB_NADDR16_HI 104 #define R_PPC_EMB_NADDR16_HA 105 #define R_PPC_EMB_SDAI16 106 #define R_PPC_EMB_SDA2I16 107 #define R_PPC_EMB_SDA2REL 108 #define R_PPC_EMB_SDA21 109 #define R_PPC_EMB_MRKREF 110 #define R_PPC_EMB_RELSEC16 111 #define R_PPC_EMB_RELST_LO 112 #define R_PPC_EMB_RELST_HI 113 #define R_PPC_EMB_RELST_HA 114 #define R_PPC_EMB_BIT_FLD 115 #define R_PPC_EMB_RELSDA 116 #define R_SPARC_NONE 0 #define R_SPARC_8 1 #define R_SPARC_16 2 #define R_SPARC_32 3 #define R_SPARC_DISP8 4 #define R_SPARC_DISP16 5 #define R_SPARC_DISP32 6 #define R_SPARC_WDISP30 7 #define R_SPARC_WDISP22 8 #define R_SPARC_HI22 9 #define R_SPARC_22 10 #define R_SPARC_13 11 #define R_SPARC_LO10 12 #define R_SPARC_GOT10 13 #define R_SPARC_GOT13 14 #define R_SPARC_GOT22 15 #define R_SPARC_PC10 16 #define R_SPARC_PC22 17 #define R_SPARC_WPLT30 18 #define R_SPARC_COPY 19 #define R_SPARC_GLOB_DAT 20 #define R_SPARC_JMP_SLOT 21 #define R_SPARC_RELATIVE 22 #define R_SPARC_UA32 23 #define R_SPARC_PLT32 24 #define R_SPARC_HIPLT22 25 #define R_SPARC_LOPLT10 26 #define R_SPARC_PCPLT32 27 #define R_SPARC_PCPLT22 28 #define R_SPARC_PCPLT10 29 #define R_SPARC_10 30 #define R_SPARC_11 31 #define R_SPARC_64 32 #define R_SPARC_OLO10 33 #define R_SPARC_HH22 34 #define R_SPARC_HM10 35 #define R_SPARC_LM22 36 #define R_SPARC_PC_HH22 37 #define R_SPARC_PC_HM10 38 #define R_SPARC_PC_LM22 39 #define R_SPARC_WDISP16 40 #define R_SPARC_WDISP19 41 #define R_SPARC_GLOB_JMP 42 #define R_SPARC_7 43 #define R_SPARC_5 44 #define R_SPARC_6 45 #define R_SPARC_DISP64 46 #define R_SPARC_PLT64 47 #define R_SPARC_HIX22 48 #define R_SPARC_LOX10 49 #define R_SPARC_H44 50 #define R_SPARC_M44 51 #define R_SPARC_L44 52 #define R_SPARC_REGISTER 53 #define R_SPARC_UA64 54 #define R_SPARC_UA16 55 #define R_SPARC_TLS_GD_HI22 56 #define R_SPARC_TLS_GD_LO10 57 #define R_SPARC_TLS_GD_ADD 58 #define R_SPARC_TLS_GD_CALL 59 #define R_SPARC_TLS_LDM_HI22 60 #define R_SPARC_TLS_LDM_LO10 61 #define R_SPARC_TLS_LDM_ADD 62 #define R_SPARC_TLS_LDM_CALL 63 #define R_SPARC_TLS_LDO_HIX22 64 #define R_SPARC_TLS_LDO_LOX10 65 #define R_SPARC_TLS_LDO_ADD 66 #define R_SPARC_TLS_IE_HI22 67 #define R_SPARC_TLS_IE_LO10 68 #define R_SPARC_TLS_IE_LD 69 #define R_SPARC_TLS_IE_LDX 70 #define R_SPARC_TLS_IE_ADD 71 #define R_SPARC_TLS_LE_HIX22 72 #define R_SPARC_TLS_LE_LOX10 73 #define R_SPARC_TLS_DTPMOD32 74 #define R_SPARC_TLS_DTPMOD64 75 #define R_SPARC_TLS_DTPOFF32 76 #define R_SPARC_TLS_DTPOFF64 77 #define R_SPARC_TLS_TPOFF32 78 #define R_SPARC_TLS_TPOFF64 79 #define R_X86_64_NONE 0 /* No relocation. */ #define R_X86_64_64 1 /* Add 64 bit symbol value. */ #define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ #define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ #define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ #define R_X86_64_COPY 5 /* Copy data from shared object. */ #define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ #define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ #define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ #define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ #define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ #define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ #define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ #define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ #define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ #define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ #define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ #define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ #define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ #define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ #define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ #define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ #define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ #define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ #define R_X86_64_IRELATIVE 37 #endif /* !_SYS_ELF_COMMON_H_ */ optee_os-4.3.0/lib/libutee/include/k3/000077500000000000000000000000001464416617300175065ustar00rootroot00000000000000optee_os-4.3.0/lib/libutee/include/k3/otp_keywriting_ta.h000066400000000000000000000027701464416617300234270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Texas Instruments System Control Interface Driver * * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ * Manorit Chawdhry */ #ifndef __K3_OTP_KEYWRITING_TA_H__ #define __K3_OTP_KEYWRITING_TA_H__ /* UUID of the trusted application */ #define PTA_K3_OTP_KEYWRITING_UUID \ { 0xacc50f40, 0x0613, 0x4abd, \ { 0x8d, 0xfe, 0xa9, 0x64, 0xcb, 0x74, 0xeb, 0x69} } #define PTA_K3_OTP_KEYWRITING_NAME "pta_k3_otp.ta" /* * TA_OTP_KEYWRITING_CMD_READ_MMR - Read an extended OTP bit * param[0] (value/input) 32-bit MMR index * param[1] (value/output) OTP value written in efuse * param[2] unused * param[3] unused */ #define TA_OTP_KEYWRITING_CMD_READ_MMR 0 /* * TA_OTP_KEYWRITING_CMD_WRITE_ROW - Write into extended OTP row * param[0] (value/input) Row index * param[1].a (value/input) Value to be written * param[1].b (value/input) Mask for the value * param[2] unused * param[3] unused */ #define TA_OTP_KEYWRITING_CMD_WRITE_ROW 1 /* * TA_OTP_KEYWRITING_CMD_LOCK_ROW - Lock an extended OTP row * param[0].a (value/input) Row index * param[0].b (value/input) * BIT(0) - soft_lock * BIT(1) - hw_read_lock * BIT(2) - hw_write_lock * param[1] unused * param[2] unused * param[3] unused */ #define TA_OTP_KEYWRITING_CMD_LOCK_ROW 2 #define K3_OTP_KEYWRITING_SOFT_LOCK BIT(0) #define K3_OTP_KEYWRITING_HW_READ_LOCK BIT(1) #define K3_OTP_KEYWRITING_HW_WRITE_LOCK BIT(2) #endif /* __K3_OTP_KEYWRITING_TA_H__ */ optee_os-4.3.0/lib/libutee/include/link.h000066400000000000000000000013121464416617300202740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2012 The Android Open Source Project */ #ifndef _LINK_H_ #define _LINK_H_ #include #include struct dl_phdr_info { Elf_Addr dlpi_addr; /* module relocation base */ const char *dlpi_name; /* module name */ const Elf_Phdr *dlpi_phdr; /* pointer to module's phdr */ Elf_Half dlpi_phnum; /* number of entries in phdr */ unsigned long long dlpi_adds; /* total # of loads */ unsigned long long dlpi_subs; /* total # of unloads */ size_t dlpi_tls_modid; void *dlpi_tls_data; }; int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data); #endif /* _LINK_H_ */ optee_os-4.3.0/lib/libutee/include/pta_apdu.h000066400000000000000000000027501464416617300211430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (C) 2021, Foundries Limited * Author: Jorge Ramirez */ #ifndef __PTA_APDU_H #define __PTA_APDU_H #define PTA_APDU_UUID { 0x3f3eb880, 0x3639, 0x11ec, \ { 0x9b, 0x9d, 0x0f, 0x3f, 0xc9, 0x46, 0x8f, 0x50 } } /* * ADPU based communication with the Secure Element * * [in] value[0].a Use APDU TXRX hints: PTA_APDU_TXRX_CASE_* * [in] memref[1].buffer APDU header. * [in] memref[1].size APDU header length. * [in] memref[2].buffer request (APDU raw frame). * [in] memref[2].size request length. * [out] memref[3].buffer response (APDU raw frame). * [out] memref[3].size response length. * * Result: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented * TEE_ERROR_GENERIC - Invoke command failure */ #define PTA_CMD_TXRX_APDU_RAW_FRAME 0 /* * Type identifier for the APDU message as described by Smart Card Standard * ISO7816-4 about ADPU message bodies decoding convention: * * https://cardwerk.com/smart-card-standard-iso7816-4-section-5-basic-organizations/#chap5_3_2 */ #define PTA_APDU_TXRX_CASE_NO_HINT 0 #define PTA_APDU_TXRX_CASE_1 1 #define PTA_APDU_TXRX_CASE_2 2 #define PTA_APDU_TXRX_CASE_2E 3 #define PTA_APDU_TXRX_CASE_3 4 #define PTA_APDU_TXRX_CASE_3E 5 #define PTA_APDU_TXRX_CASE_4 6 #define PTA_APDU_TXRX_CASE_4E 7 #endif /* __PTA_APDU_H */ optee_os-4.3.0/lib/libutee/include/pta_attestation.h000066400000000000000000000100551464416617300225460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2021, Huawei Technologies Co., Ltd */ /* * Provide remote attestation services */ #ifndef __PTA_ATTESTATION_H #define __PTA_ATTESTATION_H #define PTA_ATTESTATION_UUID { 0x39800861, 0x182a, 0x4720, \ { 0x9b, 0x67, 0x2b, 0xcd, 0x62, 0x2b, 0xc0, 0xb5 } } /* * Get the RSA public key that should be used to verify the values returned by * other commands. * * [out] memref[0] Public key exponent in big endian order * [out] memref[1] Modulus in big endian order * [out] value[2] Signature algorithm used by other commands. * Currently always * TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256. * * Return codes: * TEE_SUCCESS * TEE_ERROR_GENERIC - Internal error * TEE_ERROR_SHORT_BUFFER - One or both buffers are too small, required size * is provided in memref[i].size */ #define PTA_ATTESTATION_GET_PUBKEY 0x0 /* * Return the digest found in the header of a Trusted Application binary or a * Trusted Shared library * * [in] memref[0] UUID of the TA or shared library * [in] memref[1] Nonce (random non-NULL, non-empty buffer of any * size to prevent replay attacks) * [out] memref[2] Output buffer. Receives the signed digest. * - The first 32 bytes are the digest itself (from * the TA signed header: struct shdr::hash) * - The following bytes are a signature: * SIG(SHA256(Nonce | digest)) * - The algorithm is * TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 with a salt * length of 32. * - The key pair is generated internally and stored * in secure storage. The public key can be * retrieved with command PTA_ATTESTATION_GET_PUBKEY * (typically during device provisioning). * Given that the sigature length is equal to the * RSA modulus size in bytes, the output buffer size * should be at least (digest size + modulus size) * bytes. For example, for a 32-byte SHA256 digest and * 2048 bit key (256 bytes) the minimum buffer size is * 288 bytes. * * Return codes: * TEE_SUCCESS * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required */ #define PTA_ATTESTATION_GET_TA_SHDR_DIGEST 0x1 /* * Return a signed hash for a running user space TA, which must be the caller * of this PTA. It is a runtime measurement of the memory pages that contain * immutable data (code and read-only data). * * [in] memref[0] Nonce * [out] memref[1] SHA256 hash of the TA memory followed by a * signature. See PTA_ATTESTATION_GET_TA_HDR_DIGEST * for a description of the signature. * * Return codes: * TEE_SUCCESS * TEE_ERROR_ACCESS_DENIED - Caller is not a user space TA * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required */ #define PTA_ATTESTATION_HASH_TA_MEMORY 0x2 /* * Return a signed hash of the TEE OS (kernel) memory. It is a runtime * measurement of the memory pages that contain immutable data (code and * read-only data). * * [in] memref[0] Nonce * [out] memref[1] SHA256 hash of the TEE memory followed by a * signature. See PTA_ATTESTATION_GET_TA_HDR_DIGEST * for a description of the signature. * * Return codes: * TEE_SUCCESS * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required */ #define PTA_ATTESTATION_HASH_TEE_MEMORY 0x3 #endif /* __PTA_ATTESTATION_H */ optee_os-4.3.0/lib/libutee/include/pta_device.h000066400000000000000000000013631464416617300214500ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2019, Linaro Limited */ /* * Enumerate the pseudo TAs that have the TA_FLAG_DEVICE_ENUM flag enabled. */ #ifndef __PTA_DEVICE_H #define __PTA_DEVICE_H #define PTA_DEVICE_UUID { 0x7011a688, 0xddde, 0x4053, \ { 0xa5, 0xa9, 0x7b, 0x3c, 0x4d, 0xdf, 0x13, 0xb8 } } /* * Get device UUIDs * * [out] memref[0] Array of device UUIDs * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_SHORT_BUFFER - Output buffer size less than required */ #define PTA_CMD_GET_DEVICES 0x0 /* before tee-supplicant run */ #define PTA_CMD_GET_DEVICES_SUPP 0x1 /* after tee-supplicant run */ #endif /* __PTA_DEVICE_H */ optee_os-4.3.0/lib/libutee/include/pta_gprof.h000066400000000000000000000020721464416617300213240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __PTA_GPROF_H #define __PTA_GPROF_H /* * Interface to the gprof pseudo-TA, which is used by libutee to control TA * profiling and forward data to tee-supplicant. */ #define PTA_GPROF_UUID { 0x2f6e0d48, 0xc574, 0x426d, { \ 0x82, 0x4e, 0x40, 0x19, 0x8c, 0xde, 0x5c, 0xac } } /* * Send TA profiling data (gmon.out format) to tee-supplicant * Data may be sent in several chunks: first set id to 0, then re-use the * allocated value in subsequent calls. * * [in/out] value[0].a: id * [in] memref[1]: profiling data */ #define PTA_GPROF_SEND 0 /* * Start PC sampling of a user TA session * * [in/out] memref[0]: sampling buffer * [in] value[1].a: offset: the lowest PC value in the TA * [in] value[1].b: scale: histogram scaling factor */ #define PTA_GPROF_START_PC_SAMPLING 1 /* * Stop PC sampling of a user TA session and retrieve data * * [out] value[0].a: sampling frequency */ #define PTA_GPROF_STOP_PC_SAMPLING 2 #endif /* __PTA_GPROF_H */ optee_os-4.3.0/lib/libutee/include/pta_imx_dek_blob.h000066400000000000000000000006321464416617300226250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2019 NXP * * brief PTA DEK Blob interface identification. */ #ifndef __PTA_IMX_DEK_BLOB_H__ #define __PTA_IMX_DEK_BLOB_H__ #define PTA_DEK_BLOB_UUID {0xef477737, 0x0db1, 0x4a9d, \ {0x84, 0x37, 0xf2, 0xf5, 0x35, 0xc0, 0xbd, 0x92} } /* HAB DEK Blob encapsulation */ #define PTA_IMX_DEK_BLOB_CMD_GENERATE 0 #endif /* __PTA_IMX_DEK_BLOB_H__ */ optee_os-4.3.0/lib/libutee/include/pta_imx_digprog.h000066400000000000000000000004311464416617300225140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP */ #ifndef __PTA_IMX_DIGPROG_H__ #define __PTA_IMX_DIGPROG_H__ #define PTA_DIGPROG_UUID { 0xbfdbe409, 0x3302, 0x4abf, \ { 0x99, 0xbc, 0x5f, 0x62, 0x32, 0x26, 0xa7, 0x39 } } #endif /* __PTA_IMX_DIGPROG_H__ */ optee_os-4.3.0/lib/libutee/include/pta_imx_manufacturing_protection.h000066400000000000000000000017401464416617300261760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2018-2019, 2023 NXP */ #ifndef PTA_IMX_MANUFACTURING_PROTECTION_H #define PTA_IMX_MANUFACTURING_PROTECTION_H #define PTA_MANUFACT_PROTEC_UUID { 0x83268b7c, 0x85e3, 0x11e8, \ { 0xad, 0xc0, 0xfa, 0x7a, 0xe0, 0x1b, 0xbe, 0xbc} } /* * Sign the given message with the manufacturing protection private key * * [in] memref[0].buffer Message buffer * [in] memref[0].size Message size * [out] memref[1].buffer Signature buffer * [out] memref[1].size Signature size * [out] memref[2].buffer MPMR buffer * [out] memref[2].size MPMR size */ #define PTA_IMX_MP_CMD_SIGNATURE_MPMR 0 /* * Get the manufacturing protection public key * * [out] memref[0].buffer Public key buffer * [out] memref[0].size Public key size * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_IMX_MP_CMD_GET_PUBLIC_KEY 1 #endif /* PTA_IMX_MANUFACTURING_PROTECTION_H */ optee_os-4.3.0/lib/libutee/include/pta_imx_ocotp.h000066400000000000000000000016601464416617300222120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2021 NXP */ #ifndef __PTA_IMX_OCOTP_H__ #define __PTA_IMX_OCOTP_H__ #define PTA_OCOTP_UUID { 0x9abdf255, 0xd8fa, 0x40de, \ { 0x8f, 0x60, 0x4d, 0x0b, 0x27, 0x92, 0x7b, 0x7d } } /** * Read chip UID * * [out] memref[0].buffer Output buffer to store UID * [out] memref[0].size Size of the UID (64 bits) * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input parameter * TEE_ERROR_GENERIC - UID not available */ #define PTA_OCOTP_CMD_CHIP_UID 0 /* * Read chip OTP fuse * * [in] params[0].value.a Fuse bank number * [in] params[0].value.b Fuse word number * [out] params[1].value.a Fuse value * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input parameter * TEE_ERROR_BUSY - OCOTP not available */ #define PTA_OCOTP_CMD_READ_FUSE 1 #endif /* __PTA_IMX_OCOTP_H__ */ optee_os-4.3.0/lib/libutee/include/pta_invoke_tests.h000066400000000000000000000057521464416617300227340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __PTA_INVOKE_TESTS_H #define __PTA_INVOKE_TESTS_H #define PTA_INVOKE_TESTS_UUID \ { 0xd96a5b40, 0xc3e5, 0x21e3, \ { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } /* Trace some hello string. Parameters are not used/checked. */ #define PTA_INVOKE_TESTS_CMD_TRACE 0 /* * Types of parameter drives the test sequences: * - test on value parameters * - test on SHM memory reference parameters * - test on SDP memory reference parameters */ #define PTA_INVOKE_TESTS_CMD_PARAMS 1 /* Run some core internal tests. Parameters are not used/checked. */ #define PTA_INVOKE_TESTS_CMD_SELF_TESTS 2 /* * Secure data path: check that PTA can copy data from non-secure shared memory * to SDP secure memory * * [in] memref[0] source (non-secure shared memory) * [out] memref[1] destination (SDP secure memory) */ #define PTA_INVOKE_TESTS_CMD_COPY_NSEC_TO_SEC 3 /* * Secure data path: check that PTA can read data from SDP secure memory and * write it back. Data are processed so that client check the expected * read/write sequence succeed. * * [in/out] memref[0] SDP secure buffer to read from and write to */ #define PTA_INVOKE_TESTS_CMD_READ_MODIFY_SEC 4 /* * Secure data path: check that PTA can copy data from SDP secure memory to * non-secure shared memory * * [in] memref[0] source (SDP secure memory) * [out] memref[1] destination (non-secure shared memory) */ #define PTA_INVOKE_TESTS_CMD_COPY_SEC_TO_NSEC 5 /* * Tests FS hash-tree corner cases in error handling */ #define PTA_INVOKE_TESTS_CMD_FS_HTREE 6 /* * Tests mutex * * [in] value[0].a Test function PTA_MUTEX_TEST_* * [in] value[0].b delay number * [out] value[1].a before lock concurency * [out] value[1].b during lock concurency */ #define PTA_MUTEX_TEST_WRITER 0 #define PTA_MUTEX_TEST_READER 1 #define PTA_INVOKE_TESTS_CMD_MUTEX 7 /* * Tests lock dependency checking algorithm */ #define PTA_INVOKE_TESTS_CMD_LOCKDEP 8 /* * These values should match the ones in * optee_test/ta/aes_perf/include/ta_aes_perf.h */ #define PTA_INVOKE_TESTS_AES_ECB 0 #define PTA_INVOKE_TESTS_AES_CBC 1 #define PTA_INVOKE_TESTS_AES_CTR 2 #define PTA_INVOKE_TESTS_AES_XTS 3 #define PTA_INVOKE_TESTS_AES_GCM 4 /* * AES performance tests * * [in] value[0].a Top 16 bits Decrypt, low 16 bits key size in bits * [in] value[0].b AES mode, one of * PTA_INVOKE_TESTS_AES_{ECB_NOPAD,CBC_NOPAD,CTR,XTS,GCM} * [in] value[1].a repetition count * [in] value[1].b unit size * [in] memref[2] In buffer * [in] memref[3] Out buffer */ #define PTA_INVOKE_TEST_CMD_AES_PERF 9 /* * NULL memory reference parameter * * [in/out] memref[0] NULL memory reference of size zero */ #define PTA_INVOKE_TESTS_CMD_MEMREF_NULL 10 /* * Retrieve results of the dt_driver framework internal test */ #define PTA_INVOKE_TESTS_CMD_DT_DRIVER_TESTS 11 #endif /*__PTA_INVOKE_TESTS_H*/ optee_os-4.3.0/lib/libutee/include/pta_rng.h000066400000000000000000000022141464416617300207730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2018, Linaro Limited */ #ifndef __PTA_RNG_H #define __PTA_RNG_H #define PTA_RNG_UUID { 0xab7a617c, 0xb8e7, 0x4d8f, \ { 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64 } } #define TEE_ERROR_HEALTH_TEST_FAIL 0x00000001 /* * PTA_CMD_GET_ENTROPY - Get Entropy from RNG using Thermal Sensor * * [in/out] memref[0] - Entropy buffer memory reference * param[1] unused * param[2] unused * param[3] unused * * Result: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed */ #define PTA_CMD_GET_ENTROPY 0x0 /* * PTA_CMD_GET_RNG_INFO - Get RNG information * * [out] value[0].a - RNG data-rate in bytes per second * [out] value[0].b - Quality/Entropy per 1024 bit of data * param[1] unused * param[2] unused * param[3] unused * * Result: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_CMD_GET_RNG_INFO 0x1 #endif /* __PTA_RNG_H */ optee_os-4.3.0/lib/libutee/include/pta_rtc.h000066400000000000000000000047551464416617300210110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022, Microchip */ #ifndef __PTA_RTC_H #define __PTA_RTC_H #include #define PTA_RTC_UUID { 0xf389f8c8, 0x845f, 0x496c, \ { 0x8b, 0xbe, 0xd6, 0x4b, 0xd2, 0x4c, 0x92, 0xfd } } #define PTA_RTC_INFO_VERSION 0x1 /* * RTC provides set/get offset and thus command PTA_CMD_RTC_GET_OFFSET and * PTA_CMD_RTC_SET_OFFSET might be called */ #define PTA_RTC_FEATURE_CORRECTION BIT(0) struct pta_rtc_time { uint32_t tm_sec; uint32_t tm_min; uint32_t tm_hour; uint32_t tm_mday; uint32_t tm_mon; uint32_t tm_year; uint32_t tm_wday; }; /* * struct pta_rtc_info - RTC service information * @version - 1st 64bit cell, version of the structure: PTA_RTC_INFO_VERSION * @features - 64bit flag mask related to PTA_RTC_FEATURE_* * @range_min - Minima time reference the RTC can be programmed to * @range_max - Maxima time reference the RTC can reach */ struct pta_rtc_info { uint64_t version; uint64_t features; struct pta_rtc_time range_min; struct pta_rtc_time range_max; }; /* * PTA_CMD_RTC_GET_INFO - Get RTC information * * [out] memref[0] RTC buffer memory reference containing a struct * pta_rtc_info * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_CMD_RTC_GET_INFO 0x0 /* * PTA_CMD_RTC_GET_TIME - Get time from RTC * * [out] memref[0] RTC buffer memory reference containing a struct * pta_rtc_time * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_CMD_RTC_GET_TIME 0x1 /* * PTA_CMD_RTC_SET_TIME - Set time from RTC * * [in] memref[0] RTC buffer memory reference containing a struct * pta_rtc_time to be used as RTC time * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_CMD_RTC_SET_TIME 0x2 /* * PTA_CMD_RTC_GET_OFFSET - Get RTC offset * * [out] value[0].a RTC offset (signed 32bit value) * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_CMD_RTC_GET_OFFSET 0x3 /* * PTA_CMD_RTC_SET_OFFSET - Set RTC offset * * [in] value[0].a RTC offset to be set (signed 32bit value) * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_CMD_RTC_SET_OFFSET 0x4 #endif /* __PTA_RTC_H */ optee_os-4.3.0/lib/libutee/include/pta_scmi_client.h000066400000000000000000000050741464416617300225050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019-2021, Linaro Limited */ #ifndef PTA_SCMI_CLIENT_H #define PTA_SCMI_CLIENT_H #define PTA_SCMI_UUID { 0xa8cfe406, 0xd4f5, 0x4a2e, \ { 0x9f, 0x8d, 0xa2, 0x5d, 0xc7, 0x54, 0xc0, 0x99 } } #define PTA_SCMI_NAME "PTA-SCMI" /* * PTA_SCMI_CMD_CAPABILITIES - Get channel capabilities * * [out] value[0].a: Capabilities bit mask (PTA_SCMI_CAPS_*) * [out] value[0].b: Extended capabilities or 0 */ #define PTA_SCMI_CMD_CAPABILITIES 0 /* * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL - Process SCMI message in SMT buffer * * [in] value[0].a: Channel handle * * Shared memory used for SCMI message/response exhange is expected * already identified and bound to channel handle in both SCMI agent * and SCMI server (OP-TEE) parts. * The memory uses SMT header to carry SCMI meta-data (protocol ID and * protocol message ID). */ #define PTA_SCMI_CMD_PROCESS_SMT_CHANNEL 1 /* * PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE - Process SCMI message in * SMT buffer pointed by memref parameters * * [in] value[0].a: Channel handle * [in/out] memref[1]: Message/response buffer (SMT and SCMI payload) * * Shared memory used for SCMI message/response is a SMT buffer * referenced by param[1]. It shall be 128 bytes large to fit response * payload whatever message playload size. * The memory uses SMT header to carry SCMI meta-data (protocol ID and * protocol message ID). */ #define PTA_SCMI_CMD_PROCESS_SMT_CHANNEL_MESSAGE 2 /* * PTA_SCMI_CMD_GET_CHANNEL_HANDLE - Get handle for an SCMI channel * * Get a handle for the SCMI channel. This handle value is to be passed * as argument to some commands as PTA_SCMI_CMD_PROCESS_*. * * [in] value[0].a: Channel identifier or 0 if no assigned ID * [in] value[0].b: Requested capabilities mask (PTA_SCMI_CAPS_*) * [out] value[0].a: Returned channel handle */ #define PTA_SCMI_CMD_GET_CHANNEL_HANDLE 3 /* * PTA_SCMI_CMD_PROCESS_MSG_CHANNEL - Process SCMI message in a MSG * buffer pointed by memref parameters * * [in] value[0].a: Channel handle * [in] memref[1]: Input message shared buffer * [out] memref[2]: Output message shared buffer */ #define PTA_SCMI_CMD_PROCESS_MSG_CHANNEL 4 /* * Capabilities */ /* Channel supports shared memory using the SMT header protocol */ #define PTA_SCMI_CAPS_SMT_HEADER BIT32(0) /* Channel supports shared memory using the MSG header protocol */ #define PTA_SCMI_CAPS_MSG_HEADER BIT32(1) /* Mask of defined capabilities */ #define PTA_SCMI_CAPS_MASK GENMASK_32(1, 0) #endif /* SCMI_PTA_SCMI_CLIENT_H */ optee_os-4.3.0/lib/libutee/include/pta_scp03.h000066400000000000000000000015401464416617300211360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (C) 2020, Foundries Limited */ #ifndef __PTA_SCP03_H #define __PTA_SCP03_H #define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \ { 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } } /* * Enable SCP03 support on the SE * * [in] value[0].a Use session keys PTA_SCP03_SESSION_* * * Result: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_NOT_IMPLEMENTED - Invoke command not implemented * TEE_ERROR_GENERIC - Invoke command failure */ #define PTA_CMD_ENABLE_SCP03 0 /* Enable the session using the current keys in the Secure Element */ #define PTA_SCP03_SESSION_CURRENT_KEYS 0 /* Enable the session after replacing the current keys in the Secure Element */ #define PTA_SCP03_SESSION_ROTATE_KEYS 1 #endif /* __PTA_SCP03_H */ optee_os-4.3.0/lib/libutee/include/pta_secstor_ta_mgmt.h000066400000000000000000000010131464416617300233730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017, Linaro Limited */ #ifndef __PTA_SECSTOR_TA_MGMT_H #define __PTA_SECSTOR_TA_MGMT_H /* * Bootstrap (install initial) Trusted Application or Secure Domain into * secure storage from a signed binary. * * [in] memref[0]: signed binary */ #define PTA_SECSTOR_TA_MGMT_BOOTSTRAP 0 #define PTA_SECSTOR_TA_MGMT_UUID { 0x6e256cba, 0xfc4d, 0x4941, { \ 0xad, 0x09, 0x2c, 0xa1, 0x86, 0x03, 0x42, \ 0xdd } } #endif /*__PTA_SECSTOR_TA_MGMT_H*/ optee_os-4.3.0/lib/libutee/include/pta_socket.h000066400000000000000000000022431464416617300214770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #ifndef __PTA_SOCKET #define __PTA_SOCKET #define PTA_SOCKET_UUID { 0x3b996a7d, 0x2c2b, 0x4a49, { \ 0xa8, 0x96, 0xe1, 0xfb, 0x57, 0x66, 0xd2, 0xf4 } } /* * [in] value[0].a ip version TEE_IP_VERSION_* from tee_ipsocket.h * [in] value[0].b server port number * [in] memref[1] server address * [in] value[2].a protocol, TEE_ISOCKET_PROTOCOLID_* * [out] value[3].a socket handle */ #define PTA_SOCKET_OPEN 1 /* * [in] value[0].a socket handle */ #define PTA_SOCKET_CLOSE 2 #define PTA_SOCKET_TIMEOUT_NONBLOCKING 0 #define PTA_SOCKET_TIMEOUT_BLOCKING 0xffffffff /* * [in] value[0].a socket handle * [in] value[0].b timeout ms or TEE_TIMEOUT_INFINITE * [in] memref[1] buffer to transmit * [out] value[2].a number of transmitted bytes */ #define PTA_SOCKET_SEND 3 /* * [in] value[0].a socket handle * [in] value[0].b timeout ms or TEE_TIMEOUT_INFINITE * [out] memref[1] buffer */ #define PTA_SOCKET_RECV 4 /* * [in] value[0].a socket handle * [in] value[0].b ioctl command * [in/out] memref[1] buffer */ #define PTA_SOCKET_IOCTL 5 #endif /*__PTA_SOCKET*/ optee_os-4.3.0/lib/libutee/include/pta_stats.h000066400000000000000000000056551464416617300213570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, STMicroelectronics * Copyright (C) 2022, Microchip */ #ifndef __PTA_STATS_H #define __PTA_STATS_H #include #include #define STATS_UUID \ { 0xd96a5b40, 0xe2c7, 0xb1af, \ { 0x87, 0x94, 0x10, 0x02, 0xa5, 0xd5, 0xc6, 0x1b } } /* * STATS_CMD_PAGER_STATS - Get statistics on pager * * [out] value[0].a Number of unlocked pages * [out] value[0].b Page pool size * [out] value[1].a R/O faults since last stats dump * [out] value[1].b R/W faults since last stats dump * [out] value[2].a Hidden faults since last stats dump * [out] value[2].b Zi pages released since last stats dump */ #define STATS_CMD_PAGER_STATS 0 /* * STATS_CMD_ALLOC_STATS - Get statistics on core heap allocations * * [in] value[0].a ID of allocator(s) to get stats from (ALLOC_ID_*) * [out] memref[0] Array of struct pta_stats_alloc instances */ #define STATS_CMD_ALLOC_STATS 1 #define ALLOC_ID_ALL 0 /* All allocators */ #define ALLOC_ID_HEAP 1 /* Core heap allocator */ #define ALLOC_ID_PUBLIC_DDR 2 /* Public DDR allocator (deprecated) */ #define ALLOC_ID_TA_RAM 3 /* TA_RAM allocator */ #define ALLOC_ID_NEXUS_HEAP 4 /* Nexus heap allocator */ #define STATS_NB_POOLS 5 #define TEE_ALLOCATOR_DESC_LENGTH 32 struct pta_stats_alloc { char desc[TEE_ALLOCATOR_DESC_LENGTH]; uint32_t allocated; /* Bytes currently allocated */ uint32_t max_allocated; /* Tracks max value of allocated */ uint32_t size; /* Total size for this allocator */ uint32_t num_alloc_fail; /* Number of failed alloc requests */ uint32_t biggest_alloc_fail; /* Size of biggest failed alloc */ uint32_t biggest_alloc_fail_used; /* Alloc bytes when above occurred */ }; /* * STATS_CMD_MEMLEAK_STATS - Print memory leakage info to console */ #define STATS_CMD_MEMLEAK_STATS 2 /* * STATS_CMD_TA_STATS - Get information on TA instances * * [out] memref[0] Array of struct pta_stats_ta per loaded TA */ #define STATS_CMD_TA_STATS 3 struct pta_stats_ta { TEE_UUID uuid; uint32_t panicked; /* True if TA has panicked */ uint32_t sess_num; /* Number of opened session */ struct pta_stats_alloc heap; }; /* * STATS_CMD_GET_TIME - Get both REE time and TEE time * * [out] value[0].a REE time as seen by OP-TEE in seconds * [out] value[0].b REE time as seen by OP-TEE, milliseconds part * [out] value[1].a TEE system time in seconds * [out] value[1].b TEE system time, milliseconds part */ #define STATS_CMD_GET_TIME 4 /* * STATS_CMD_PRINT_DRIVER_INFO - Print device drivers information to console * * [in] value[0].a Target driver, one of STATS_DRIVER_TYPE_* */ #define STATS_CMD_PRINT_DRIVER_INFO 5 #define STATS_DRIVER_TYPE_CLOCK 0 #define STATS_DRIVER_TYPE_REGULATOR 1 #endif /*__PTA_STATS_H*/ optee_os-4.3.0/lib/libutee/include/pta_stm32mp_bsec.h000066400000000000000000000051251464416617300225120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2022, STMicroelectronics - All Rights Reserved */ #ifndef __PTA_STM32MP_BSEC_H #define __PTA_STM32MP_BSEC_H #define PTA_BSEC_UUID { 0x94cf71ad, 0x80e6, 0x40b5, \ { 0xa7, 0xc6, 0x3d, 0xc5, 0x01, 0xeb, 0x28, 0x03 } } /** * Read OTP memory * * [in] value[0].a OTP start offset in byte * [in] value[0].b Access type, see PTA_BSEC_TYPE_* * [out] memref[1].buffer Output buffer to store read values * [out] memref[1].size Size of OTP to be read * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller */ #define PTA_BSEC_CMD_READ_OTP 0x0 /** * Write OTP memory * * [in] value[0].a OTP start offset in byte * [in] value[0].b Access type (0 : shadow, * 1 : fuse, 2 : lock) * [in] memref[1].buffer Input buffer to read values * [in] memref[1].size Size of OTP to be written * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param * TEE_ERROR_ACCESS_DENIED - OTP not accessible by caller */ #define PTA_BSEC_CMD_WRITE_OTP 0x1 /** * Get BSEC state * Return the chip security level by reading the BSEC state * * [out] value[0].a One of PTA_BSEC_STATE_* * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect input param */ #define PTA_BSEC_CMD_GET_STATE 0x3 enum stm32_bsec_pta_sec_state { PTA_BSEC_STATE_SEC_OPEN = 0, PTA_BSEC_STATE_SEC_CLOSE = 1, PTA_BSEC_STATE_INVALID = 3 }; /* * Access types identifiers for PTA_BSEC_CMD_READ_OTP and * PTA_BSEC_CMD_WRITE_OTP = value[in].b. * * PTA_BSEC_SHADOW_ACCESS Access OTP shadow memory * PTA_BSEC_FUSE_ACCESS Access OTP fuse memory * PTA_BSEC_LOCKS_ACCESS Access OTP locks. The locks value read/written * in memref[1] 32bit words are related to bit flag * masks PTA_BSEC_LOCK_*. */ #define PTA_BSEC_SHADOW_ACCESS 0 #define PTA_BSEC_FUSE_ACCESS 1 #define PTA_BSEC_LOCKS_ACCESS 2 /* * PTA_BSEC_LOCK_* - Bit mask of OTP locks in memref[1] * * PTA_BSEC_LOCK_PERM Fuse programming permanent lock * PTA_BSEC_LOCK_SHADOW_R Shadow programming (from fuse) lock * PTA_BSEC_LOCK_SHADOW_W Shadow memory write lock * PTA_BSEC_LOCK_SHADOW_P Fuse programming sticky lock * PTA_BSEC_LOCK_ERROR Flag indicating an error in lock access */ #define PTA_BSEC_LOCK_PERM BIT(30) #define PTA_BSEC_LOCK_SHADOW_R BIT(29) #define PTA_BSEC_LOCK_SHADOW_W BIT(28) #define PTA_BSEC_LOCK_SHADOW_P BIT(27) #define PTA_BSEC_LOCK_ERROR BIT(26) #endif /* __PTA_STM32MP_BSEC_H */ optee_os-4.3.0/lib/libutee/include/pta_system.h000066400000000000000000000144761464416617300215460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2019, Linaro Limited * Copyright (c) 2020, Open Mobile Platform LLC */ #ifndef __PTA_SYSTEM_H #define __PTA_SYSTEM_H #include /* * Interface to the pseudo TA, which is provides misc. auxiliary services, * extending existing GlobalPlatform Core API */ #define PTA_SYSTEM_UUID { 0x3a2f8978, 0x5dc0, 0x11e8, { \ 0x9c, 0x2d, 0xfa, 0x7a, 0xe0, 0x1b, 0xbe, 0xbc } } /* * Having keys with too few bits impose a potential security risk, hence set a * lower bound of 128 bits. */ #define TA_DERIVED_KEY_MIN_SIZE 16 /* Same value as max in huk_subkey_derive */ #define TA_DERIVED_KEY_MAX_SIZE 32 #define TA_DERIVED_EXTRA_DATA_MAX_SIZE 1024 /* * Add (re-seed) caller-provided entropy to the RNG pool. Keymaster * implementations need to securely mix the provided entropy into their pool, * which also must contain internally-generated entropy from a hardware random * number generator. * * [in] memref[0]: entropy input data */ #define PTA_SYSTEM_ADD_RNG_ENTROPY 0 /* * Derives a device and TA unique key. The caller can also provide extra data * that will be mixed together with existing device unique properties. If no * extra data is provided, then the derived key will only use device unique * properties and caller TA UUID. * * [in] params[0].memref.buffer Buffer for extra data * [in] params[0].memref.size Size of extra data (max 1024 bytes) * [out] params[1].memref.buffer Buffer for the derived key * [out] params[1].memref.size Size of the derived key (16 to 32 bytes) */ #define PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY 1 /* Memory can be shared with other TAs */ #define PTA_SYSTEM_MAP_FLAG_SHAREABLE BIT32(0) /* Read/write memory */ #define PTA_SYSTEM_MAP_FLAG_WRITEABLE BIT32(1) /* Executable memory */ #define PTA_SYSTEM_MAP_FLAG_EXECUTABLE BIT32(2) /* * Map zero initialized memory * * [in] value[0].a: Number of bytes * [in] value[0].b: Flags, 0 or PTA_SYSTEM_MAP_FLAG_SHAREABLE * [out] value[1].a: Address upper 32-bits * [out] value[1].b: Address lower 32-bits * [in] value[2].a: Extra pad before memory range * [in] value[2].b: Extra pad after memory range */ #define PTA_SYSTEM_MAP_ZI 2 /* * Unmap memory * * [in] value[0].a: Number of bytes * [in] value[0].b: Must be 0 * [in] value[1].a: Address upper 32-bits * [in] value[1].b: Address lower 32-bits */ #define PTA_SYSTEM_UNMAP 3 /* * Find and opens an TA binary and return a handle * * [in] memref[0]: UUID of TA binary * [out] value[1].a: Handle to TA binary * [out] value[1].b: 0 */ #define PTA_SYSTEM_OPEN_TA_BINARY 4 /* * Close an TA binary handle * * When a TA is done mapping new parts of an TA binary it closes the handle * to free resources, established mappings remains. * * [in] value[1].a: Handle to TA binary * [in] value[1].b: Must be 0 * * Returns TEE_SUCCESS if the TA binary was verified successfully. */ #define PTA_SYSTEM_CLOSE_TA_BINARY 5 /* * Map segment of TA binary * * Different parts of an TA binary file needs different permissions. * Read-write mapped parts are private to the TA, while read-only (which * includes execute) mapped parts are shared with other TAs. This is * transparent to the TA. If the supplied address in value[3] is 0 a * suitable address is selected, else it will either be mapped at that * address of an error is returned. * * [in] value[0].a: Handle to TA binary * [in] value[0].b: Flags, PTA_SYSTEM_MAP_FLAG_* * [in] value[1].a: Offset into TA binary, must be page aligned * [in] value[1].b: Number of bytes, the last page will be zero * extended if not page aligned * [in/out] value[2].a: Address upper 32-bits * [in/out] value[2].b: Address lower 32-bits * [in] value[3].a: Extra pad before memory range * [in] value[3].b: Extra pad after memory range */ #define PTA_SYSTEM_MAP_TA_BINARY 6 /* * Copy a memory range from TA binary * * [in] value[0].a: Handle to TA binary * [in] value[0].b: Offset into TA binary * [out] memref[1]: Destination */ #define PTA_SYSTEM_COPY_FROM_TA_BINARY 7 /* * Set memory protection * * [in] value[0].a: Number of bytes * [in] value[0].b: Flags, PTA_SYSTEM_MAP_FLAG_* * [in] value[1].a: Address upper 32-bits * [in] value[1].b: Address lower 32-bits */ #define PTA_SYSTEM_SET_PROT 8 /* * Remap a segment of a TA mapping * * Moves an already mapped segment of a TA to a new address. If the * supplied new address is 0 a suitable address is selected, else it will * either be mapped at that address or an error is returned. * * [in] value[0].a: Number of bytes, must match length rounded up to * closest page of original mapping * [in] value[0].b: Must be 0 * [in] value[1].a: Old address upper 32-bits * [in] value[1].b: Old address lower 32-bits * [in/out] value[2].a: New address upper 32-bits * [in/out] value[2].b: New address lower 32-bits * [in] value[3].a: Extra pad before memory range * [in] value[3].b: Extra pad after memory range */ #define PTA_SYSTEM_REMAP 9 /* * Load a shared library * * [in] memref[0]: the UUID of the shared library (@filename) * [in] value[1].a: @flags, must be (RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE) * * Used by: (libdl) dlopen(const char *filename, int flags) */ #define PTA_SYSTEM_DLOPEN 10 /* * Resolve a symbol in a previously loaded shared library or in the whole TA * * [in] memref[0]: the UUID of the shared library, or the nil UUID to * search the whole TA * [in] memref[1]: symbol name (@symbol) * [out] value[2]: address of the symbol or NULL * * Used by: (libdl) dlsym(void *handle, const char *symbol) */ #define PTA_SYSTEM_DLSYM 11 /* * Retrieves a copy of the TPM Event log held in secure memory. * * [out] memref[0]: Pointer to the buffer where to store the event log. */ #define PTA_SYSTEM_GET_TPM_EVENT_LOG 12 /* * Invoke a tee-supplicant's plugin * * [in] memref[0] uuid of the plugin (TEE_UUID) * [in] value[1].a command for the plugin * [in] value[1].b sub_command for the plugin * [in/out] memref[2] additional data for the plugin * [out] value[3].a output length of data */ #define PTA_SYSTEM_SUPP_PLUGIN_INVOKE 13 #endif /* __PTA_SYSTEM_H */ optee_os-4.3.0/lib/libutee/include/pta_widevine.h000066400000000000000000000021711464416617300220210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023, The ChromiumOS Authors */ #ifndef __PTA_WIDEVINE_H #define __PTA_WIDEVINE_H /* * Interface to the widevine pseudo-TA, which is used for passing parameters * for widevine TA. */ #define PTA_WIDEVINE_UUID \ { \ 0x721f4da9, 0xda05, 0x40d4, \ { \ 0xa1, 0xa3, 0x83, 0x77, 0xc1, 0xe0, 0x8b, 0x0a \ } \ } /* * PTA_WIDEVINE_GET_TPM_PUBKEY - Get Widevine TPM public key * PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY - Get Widevine private key * * [out] memref[0] Retrieved key data * * Return codes: * TEE_SUCCESS - Invoke command success * TEE_ERROR_BAD_PARAMETERS - Incorrect parameters * TEE_ERROR_SHORT_BUFFER - Output buffer size is too small * TEE_ERROR_NO_DATA - Requested data not available */ #define PTA_WIDEVINE_GET_TPM_PUBKEY 0 #define PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY 1 #endif /* __PTA_WIDEVINE_H */ optee_os-4.3.0/lib/libutee/include/remoteproc_pta.h000066400000000000000000000110561464416617300223700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, STMicroelectronics */ #ifndef __REMOTEPROC_PTA_H #define __REMOTEPROC_PTA_H #include #include /* * Interface to the pseudo TA which provides platform implementation * of the remote processor management */ #define PTA_RPROC_UUID { 0x54af4a68, 0x19be, 0x40d7, \ { 0xbb, 0xe6, 0x89, 0x50, 0x35, 0x0a, 0x87, 0x44 } } /* Hardware capability: firmware format */ #define PTA_RPROC_HWCAP_FMT_ELF BIT32(0) /* Hardware capability: image protection method */ /* The platform supports load of segment with hash protection */ #define PTA_RPROC_HWCAP_PROT_HASH_TABLE BIT32(0) /** * struct rproc_pta_key_info - public key information * @algo: Algorithm, defined by public key algorithms TEE_ALG_* * @info_size: Byte size of @info * @info: Append key information data */ struct rproc_pta_key_info { uint32_t algo; uint32_t info_size; uint8_t info[]; }; static inline size_t rproc_pta_keyinfo_size(struct rproc_pta_key_info *keyinf) { size_t s = 0; if (!keyinf || ADD_OVERFLOW(sizeof(*keyinf), keyinf->info_size, &s)) return 0; return s; } /* * Platform capabilities. * * Get Platform firmware loader service capabilities. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [out] params[1].value.a: Firmware format (PTA_RPROC_HWCAP_FMT_*) * [out] params[2].value.a: Image protection method (PTA_RPROC_HWCAP_PROT_*) */ #define PTA_RPROC_HW_CAPABILITIES 1 /* * Firmware loading. * * Optional service to implement only in case of proprietary format. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [in] params[1].memref: Loadable firmware image */ #define PTA_RPROC_FIRMWARE_LOAD 2 /* * Load a segment with a SHA256 hash. * * This command is used when the platform secure memory is too constrained to * save the whole firmware image. Upon segment load, a successful completion * ensures the loaded image complies with the provided hash. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [in] params[1].memref: Section data to load * [in] params[2].value.a: 32bit LSB load device segment address * [in] params[2].value.b: 32bit MSB load device segment address * [in] params[3].memref: Expected hash (SHA256) of the payload */ #define PTA_RPROC_LOAD_SEGMENT_SHA256 3 /* * Memory set. * * Fill a remote device memory with requested value. this is used for instance * to clear a memory on the remote firmware load. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [in] params[1].value.a: 32bit LSB device memory address * [in] params[1].value.b: 32bit MSB device memory address * [in] params[2].value.a: 32bit LSB device memory size * [in] params[2].value.b: 32bit MSB device memory size * [in] params[3].value.a: Byte value to be set */ #define PTA_RPROC_SET_MEMORY 4 /* * Firmware start. * * Start up a successfully loaded remote processor firmware. * * [in] params[0].value.a: Unique 32bit remote processor identifier */ #define PTA_RPROC_FIRMWARE_START 5 /* * Firmware stop. * * Stop of the remote processor firmware and release/clean resources. * After the command successful completion, remote processor firmware must be * reloaded prior being started again. * * [in] params[0].value.a: Unique 32bit remote processor identifier */ #define PTA_RPROC_FIRMWARE_STOP 6 /* * Firmware device to physical address conversion. * * Convert the physical address corresponding to an address got from the * firmware address layout. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [in] params[1].value.a: 32bit LSB Device memory address * [in] params[1].value.b: 32bit MSB Device memory address * [in] params[2].value.a: 32bit LSB Device memory size * [in] params[2].value.b: 32bit MSB Device memory size * [out] params[3].value.a: 32bit LSB converted physical address * [out] params[3].value.b: 32bit MSB converted physical address */ #define PTA_RPROC_FIRMWARE_DA_TO_PA 7 /* * Verify the firmware digest against a signature * * Return TEE_SUCCESS if the signature is verified, * TEE_ERROR_SIGNATURE_INVALID when signature is not valid, * another error code for other error cases. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [in] params[1].memref: Key information (refer to @rproc_pta_key_info) * [in] params[2].memref: Digest of the firmware authenticated data * [in] params[3].memref: Signature of the firmware authenticated data */ #define PTA_RPROC_VERIFY_DIGEST 8 #endif /* __REMOTEPROC_PTA_H */ optee_os-4.3.0/lib/libutee/include/riscv_user_sysreg.h000066400000000000000000000021261464416617300231230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation */ #ifndef RISCV_USER_SYSREG_H #define RISCV_USER_SYSREG_H #include #define read_csr(csr) \ ({ \ register unsigned long v; \ asm volatile ("csrr %0, " #csr : "=r"(v) : : "memory"); \ v; \ }) static inline __noprof uint64_t read_time(void) { uint64_t time = 0; uint32_t hi __maybe_unused = 0; uint32_t lo __maybe_unused = 0; #ifdef RV32 do { hi = read_csr(timeh); lo = read_csr(time); } while (hi != read_csr(timeh)); time = SHIFT_U64(hi, 32) | lo; #else /*RV64*/ time = read_csr(time); #endif /*RV32*/ return time; } /* These barriers need to enforce ordering on both devices and memory. */ static inline __noprof void mb(void) { asm volatile ("fence" : : : "memory"); } static inline __noprof uint64_t barrier_read_counter_timer(void) { mb(); /* Get timer value after pending operations have completed */ return read_time(); } static inline __noprof uint32_t read_cntfrq(void) { return CFG_RISCV_MTIME_RATE; } #endif /* RISCV_USER_SYSREG_H */ optee_os-4.3.0/lib/libutee/include/rng_pta_client.h000066400000000000000000000004261464416617300223340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2018-2022, Linaro Limited * * This header file is deprecated and kept for backward compatibility. */ #ifndef __RNG_PTA_CLIENT_H #define __RNG_PTA_CLIENT_H #include #endif /* __RNG_PTA_CLIENT_H */ optee_os-4.3.0/lib/libutee/include/tee_api.h000066400000000000000000000003141464416617300207460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef TEE_API_H #define TEE_API_H #include #endif /* TEE_API_H */ optee_os-4.3.0/lib/libutee/include/tee_api_compat.h000066400000000000000000000112161464416617300223140ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Linaro Limited */ #ifndef __TEE_API_COMPAT_H #define __TEE_API_COMPAT_H /* * This function will be called from TA_OpenSessionEntryPoint() in * user_ta_header.c (if compiled with __OPTEE_CORE_API_COMPAT_1_1), the * compatibility entry function is passed as a function pointer in @fp. * This is needed since libutee is never compiled with * __OPTEE_CORE_API_COMPAT_1_1, but we still need a way to call the * compatibility function __GP11_TA_InvokeCommandEntryPoint(), but only * when __OPTEE_CORE_API_COMPAT_1_1 is defined. */ TEE_Result __ta_open_sess(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], void **sess_ctx, TEE_Result (*fp)(uint32_t, __GP11_TEE_Param [TEE_NUM_PARAMS], void **)); /* * Same as for __ta_open_sess_func(), except that @fp now is a pointer to * __GP11_TA_InvokeCommandEntryPoint(). */ TEE_Result __ta_invoke_cmd(void *sess_ctx, uint32_t cmd_id, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], TEE_Result (*fp)(void *, uint32_t, uint32_t, __GP11_TEE_Param [TEE_NUM_PARAMS])); #if __OPTEE_CORE_API_COMPAT_1_1 /* Types */ #define TEE_Attribute __GP11_TEE_Attribute #define TEE_ObjectInfo __GP11_TEE_ObjectInfo #define TEE_Param __GP11_TEE_Param /* Functions */ #define TA_InvokeCommandEntryPoint __GP11_TA_InvokeCommandEntryPoint #define TA_OpenSessionEntryPoint __GP11_TA_OpenSessionEntryPoint #define TEE_AEDecryptFinal __GP11_TEE_AEDecryptFinal #define TEE_AEEncryptFinal __GP11_TEE_AEEncryptFinal #define TEE_AEInit __GP11_TEE_AEInit #define TEE_AEUpdateAAD __GP11_TEE_AEUpdateAAD #define TEE_AEUpdate __GP11_TEE_AEUpdate #define TEE_AllocateTransientObject __GP11_TEE_AllocateTransientObject #define TEE_AsymmetricDecrypt __GP11_TEE_AsymmetricDecrypt #define TEE_AsymmetricEncrypt __GP11_TEE_AsymmetricEncrypt #define TEE_AsymmetricSignDigest __GP11_TEE_AsymmetricSignDigest #define TEE_AsymmetricVerifyDigest __GP11_TEE_AsymmetricVerifyDigest #define TEE_BigIntConvertFromOctetString __GP11_TEE_BigIntConvertFromOctetString #define TEE_BigIntConvertToOctetString __GP11_TEE_BigIntConvertToOctetString #define TEE_BigIntFMMContextSizeInU32 __GP11_TEE_BigIntFMMContextSizeInU32 #define TEE_BigIntFMMSizeInU32 __GP11_TEE_BigIntFMMSizeInU32 #define TEE_BigIntInitFMMContext __GP11_TEE_BigIntInitFMMContext #define TEE_BigIntInitFMM __GP11_TEE_BigIntInitFMM #define TEE_BigIntShiftRight __GP11_TEE_BigIntShiftRight #define TEE_CheckMemoryAccessRights __GP11_TEE_CheckMemoryAccessRights #define TEE_CipherDoFinal __GP11_TEE_CipherDoFinal #define TEE_CipherInit __GP11_TEE_CipherInit #define TEE_CipherUpdate __GP11_TEE_CipherUpdate #define TEE_CreatePersistentObject __GP11_TEE_CreatePersistentObject #define TEE_DeriveKey __GP11_TEE_DeriveKey #define TEE_DigestDoFinal __GP11_TEE_DigestDoFinal #define TEE_DigestUpdate __GP11_TEE_DigestUpdate #define TEE_FreeOperation __GP11_TEE_FreeOperation #define TEE_GenerateKey __GP11_TEE_GenerateKey #define TEE_GenerateRandom __GP11_TEE_GenerateRandom #define TEE_GetNextPersistentObject __GP11_TEE_GetNextPersistentObject #define TEE_GetObjectBufferAttribute __GP11_TEE_GetObjectBufferAttribute #define TEE_GetObjectInfo1 __GP11_TEE_GetObjectInfo1 #define TEE_GetObjectInfo __GP11_TEE_GetObjectInfo #define TEE_GetOperationInfoMultiple __GP11_TEE_GetOperationInfoMultiple #define TEE_GetPropertyAsBinaryBlock __GP11_TEE_GetPropertyAsBinaryBlock #define TEE_GetPropertyAsString __GP11_TEE_GetPropertyAsString #define TEE_GetPropertyName __GP11_TEE_GetPropertyName #define TEE_InitRefAttribute __GP11_TEE_InitRefAttribute #define TEE_InitValueAttribute __GP11_TEE_InitValueAttribute #define TEE_InvokeTACommand __GP11_TEE_InvokeTACommand #define TEE_MACCompareFinal __GP11_TEE_MACCompareFinal #define TEE_MACComputeFinal __GP11_TEE_MACComputeFinal #define TEE_MACInit __GP11_TEE_MACInit #define TEE_MACUpdate __GP11_TEE_MACUpdate #define TEE_Malloc __GP11_TEE_Malloc #define TEE_MemCompare __GP11_TEE_MemCompare #define TEE_MemFill __GP11_TEE_MemFill #define TEE_MemMove __GP11_TEE_MemMove #define TEE_OpenPersistentObject __GP11_TEE_OpenPersistentObject #define TEE_OpenTASession __GP11_TEE_OpenTASession #define TEE_PopulateTransientObject __GP11_TEE_PopulateTransientObject #define TEE_ReadObjectData __GP11_TEE_ReadObjectData #define TEE_Realloc __GP11_TEE_Realloc #define TEE_RenamePersistentObject __GP11_TEE_RenamePersistentObject #define TEE_SeekObjectData __GP11_TEE_SeekObjectData #define TEE_SetOperationKey2 __GP11_TEE_SetOperationKey2 #define TEE_SetOperationKey __GP11_TEE_SetOperationKey #define TEE_TruncateObjectData __GP11_TEE_TruncateObjectData #define TEE_WriteObjectData __GP11_TEE_WriteObjectData #endif #endif /*__TEE_API_COMPAT_H*/ optee_os-4.3.0/lib/libutee/include/tee_api_defines.h000066400000000000000000001015671464416617300224570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2022, Linaro Limited */ /* Based on GP TEE Internal Core API Specification Version 1.3.1 */ #ifndef TEE_API_DEFINES_H #define TEE_API_DEFINES_H #define TEE_CORE_API_MAJOR_VERSION 1U #define TEE_CORE_API_MINOR_VERSION 3U #define TEE_CORE_API_MAINTENANCE_VERSION 1U #define TEE_CORE_API_VERSION \ ((TEE_CORE_API_MAJOR_VERSION << 24) | \ (TEE_CORE_API_MINOR_VERSION << 16) | \ (TEE_CORE_API_MAINTENANCE_VERSION << 8)) #define TEE_CORE_API_1_3_1 /* * Below follows the GP defined way of letting a TA define that it wants an * API compatible with version 1.1 or the latest. An alternative approach * is to set __OPTEE_CORE_API_COMPAT_1_1, but that's an OP-TEE extension. * * The GP specs (>= 1.2) requires that only APIs defined in the indicated * version SHALL be made available when using this mechanism. However, that * is far beyond what ordinary standards requires as they permit * extensions. With this, in OP-TEE, extensions and new API that doesn't * interfere with the selected version of the standard will be permitted. */ #if defined(TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION) && \ !defined(TEE_CORE_API_REQUIRED_MINOR_VERSION) #error "Required TEE_CORE_API_REQUIRED_MINOR_VERSION undefined" #endif #if defined(TEE_CORE_API_REQUIRED_MINOR_VERSION) && \ !defined(TEE_CORE_API_REQUIRED_MAJOR_VERSION) #error "Required TEE_CORE_API_REQUIRED_MAJOR_VERSION undefined" #endif #if defined(TEE_CORE_API_REQUIRED_MAJOR_VERSION) #if TEE_CORE_API_REQUIRED_MAJOR_VERSION != 1 && \ TEE_CORE_API_REQUIRED_MAJOR_VERSION != 0 #error "Required major version not supported" #endif #ifdef TEE_CORE_API_REQUIRED_MINOR_VERSION #if TEE_CORE_API_REQUIRED_MINOR_VERSION == 1 #define __OPTEE_CORE_API_COMPAT_1_1 1 #else #error "Required minor version not supported" #endif #if defined(TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION) && \ TEE_CORE_API_REQUIRED_MAINTENANCE_VERSION != 0 #error "Required maintenance version not supported" #endif #endif #endif /* * For backwards compatibility with v1.1 as provided by up to OP-TEE * version 3.19.0, define __OPTEE_CORE_API_COMPAT_1_1 to 1. * * Some versions of the GP specs have introduced backwards incompatible * changes. For example the v1.0: * * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, * const void *chunk, uint32_t chunkLen, * void *hash, uint32_t *hashLen); * * Was changed in v1.1.1 to this: * * TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, * const void *chunk, size_t chunkLen, * void *hash, size_t *hashLen); * * Note the type change for "hashLen", a source of problem especially on * platforms where size_t is a 64-bit unsigned integer. * * As a way of allowing older TAs to be compiled with a newer version of * the API we can turn off or hide different incompatible changes. New * features which are not interfering with older versions of the API are * not disabled. So by enabling __OPTEE_CORE_API_COMPAT_1_1 will not result * in pure 1.1 API, it will be a hybrid API that should work with most TAs * not yet updated to the new API. * * Backwards compatibility is provided by duplicating all functions that * has changed since v1.1. The original function is given a "__GP11_" * prefix and preprocessor macros are used to let a legacy TA use the old * function instead. The same principle applies to defined types. */ #ifndef __OPTEE_CORE_API_COMPAT_1_1 #define __OPTEE_CORE_API_COMPAT_1_1 0 #endif #define TEE_HANDLE_NULL 0 #define TEE_TIMEOUT_INFINITE 0xFFFFFFFF /* API Error Codes */ #define TEE_SUCCESS 0x00000000 #define TEE_ERROR_CORRUPT_OBJECT 0xF0100001 #define TEE_ERROR_CORRUPT_OBJECT_2 0xF0100002 #define TEE_ERROR_STORAGE_NOT_AVAILABLE 0xF0100003 #define TEE_ERROR_STORAGE_NOT_AVAILABLE_2 0xF0100004 #define TEE_ERROR_UNSUPPORTED_VERSION 0xF0100005 #define TEE_ERROR_CIPHERTEXT_INVALID 0xF0100006 #define TEE_ERROR_GENERIC 0xFFFF0000 #define TEE_ERROR_ACCESS_DENIED 0xFFFF0001 #define TEE_ERROR_CANCEL 0xFFFF0002 #define TEE_ERROR_ACCESS_CONFLICT 0xFFFF0003 #define TEE_ERROR_EXCESS_DATA 0xFFFF0004 #define TEE_ERROR_BAD_FORMAT 0xFFFF0005 #define TEE_ERROR_BAD_PARAMETERS 0xFFFF0006 #define TEE_ERROR_BAD_STATE 0xFFFF0007 #define TEE_ERROR_ITEM_NOT_FOUND 0xFFFF0008 #define TEE_ERROR_NOT_IMPLEMENTED 0xFFFF0009 #define TEE_ERROR_NOT_SUPPORTED 0xFFFF000A #define TEE_ERROR_NO_DATA 0xFFFF000B #define TEE_ERROR_OUT_OF_MEMORY 0xFFFF000C #define TEE_ERROR_BUSY 0xFFFF000D #define TEE_ERROR_COMMUNICATION 0xFFFF000E #define TEE_ERROR_SECURITY 0xFFFF000F #define TEE_ERROR_SHORT_BUFFER 0xFFFF0010 #define TEE_ERROR_EXTERNAL_CANCEL 0xFFFF0011 #define TEE_ERROR_TIMEOUT 0xFFFF3001 #define TEE_ERROR_OVERFLOW 0xFFFF300F #define TEE_ERROR_TARGET_DEAD 0xFFFF3024 #define TEE_ERROR_STORAGE_NO_SPACE 0xFFFF3041 #define TEE_ERROR_MAC_INVALID 0xFFFF3071 #define TEE_ERROR_SIGNATURE_INVALID 0xFFFF3072 #define TEE_ERROR_TIME_NOT_SET 0xFFFF5000 #define TEE_ERROR_TIME_NEEDS_RESET 0xFFFF5001 /* Parameter Type Constants */ #define TEE_PARAM_TYPE_NONE 0 #define TEE_PARAM_TYPE_VALUE_INPUT 1 #define TEE_PARAM_TYPE_VALUE_OUTPUT 2 #define TEE_PARAM_TYPE_VALUE_INOUT 3 #define TEE_PARAM_TYPE_MEMREF_INPUT 5 #define TEE_PARAM_TYPE_MEMREF_OUTPUT 6 #define TEE_PARAM_TYPE_MEMREF_INOUT 7 /* Login Type Constants */ #define TEE_LOGIN_PUBLIC 0x00000000 #define TEE_LOGIN_USER 0x00000001 #define TEE_LOGIN_GROUP 0x00000002 #define TEE_LOGIN_APPLICATION 0x00000004 #define TEE_LOGIN_APPLICATION_USER 0x00000005 #define TEE_LOGIN_APPLICATION_GROUP 0x00000006 #define TEE_LOGIN_TRUSTED_APP 0xF0000000 /* Origin Code Constants */ #define TEE_ORIGIN_API 0x00000001 #define TEE_ORIGIN_COMMS 0x00000002 #define TEE_ORIGIN_TEE 0x00000003 #define TEE_ORIGIN_TRUSTED_APP 0x00000004 /* Property Sets pseudo handles */ #define TEE_PROPSET_TEE_IMPLEMENTATION (TEE_PropSetHandle)0xFFFFFFFD #define TEE_PROPSET_CURRENT_CLIENT (TEE_PropSetHandle)0xFFFFFFFE #define TEE_PROPSET_CURRENT_TA (TEE_PropSetHandle)0xFFFFFFFF /* Memory Access Rights Constants */ #define TEE_MEMORY_ACCESS_READ 0x00000001 #define TEE_MEMORY_ACCESS_WRITE 0x00000002 #define TEE_MEMORY_ACCESS_ANY_OWNER 0x00000004 /* Memory Management Constant */ #define TEE_MALLOC_FILL_ZERO 0x00000000 #define TEE_MALLOC_NO_FILL 0x00000001 #define TEE_MALLOC_NO_SHARE 0x00000002 /* TEE_Whence Constants */ #define TEE_DATA_SEEK_SET 0x00000000 #define TEE_DATA_SEEK_CUR 0x00000001 #define TEE_DATA_SEEK_END 0x00000002 #define TEE_WHENCE_ILLEGAL_VALUE 0x7FFFFFFF /* TEE_OperationMode Values */ #define TEE_MODE_ENCRYPT 0x00000000 #define TEE_MODE_DECRYPT 0x00000001 #define TEE_MODE_SIGN 0x00000002 #define TEE_MODE_VERIFY 0x00000003 #define TEE_MODE_MAC 0x00000004 #define TEE_MODE_DIGEST 0x00000005 #define TEE_MODE_DERIVE 0x00000006 #define TEE_MODE_ILLEGAL_VALUE 0x7FFFFFFF /* Other constants */ #define TEE_STORAGE_PRIVATE 0x00000001 #define TEE_DATA_FLAG_ACCESS_READ 0x00000001 #define TEE_DATA_FLAG_ACCESS_WRITE 0x00000002 #define TEE_DATA_FLAG_ACCESS_WRITE_META 0x00000004 #define TEE_DATA_FLAG_SHARE_READ 0x00000010 #define TEE_DATA_FLAG_SHARE_WRITE 0x00000020 #define TEE_DATA_FLAG_OVERWRITE 0x00000400 #define TEE_DATA_MAX_POSITION 0xFFFFFFFF #define TEE_OBJECT_ID_MAX_LEN 64 #define TEE_USAGE_EXTRACTABLE 0x00000001 #define TEE_USAGE_ENCRYPT 0x00000002 #define TEE_USAGE_DECRYPT 0x00000004 #define TEE_USAGE_MAC 0x00000008 #define TEE_USAGE_SIGN 0x00000010 #define TEE_USAGE_VERIFY 0x00000020 #define TEE_USAGE_DERIVE 0x00000040 #define TEE_HANDLE_FLAG_PERSISTENT 0x00010000 #define TEE_HANDLE_FLAG_INITIALIZED 0x00020000 #define TEE_HANDLE_FLAG_KEY_SET 0x00040000 #define TEE_HANDLE_FLAG_EXPECT_TWO_KEYS 0x00080000 #define TEE_HANDLE_FLAG_EXTRACTING 0x00100000 #define TEE_OPERATION_CIPHER 1 #define TEE_OPERATION_MAC 3 #define TEE_OPERATION_AE 4 #define TEE_OPERATION_DIGEST 5 #define TEE_OPERATION_ASYMMETRIC_CIPHER 6 #define TEE_OPERATION_ASYMMETRIC_SIGNATURE 7 #define TEE_OPERATION_KEY_DERIVATION 8 #define TEE_OPERATION_STATE_INITIAL 0x00000000 #define TEE_OPERATION_STATE_ACTIVE 0x00000001 #define TEE_OPERATION_STATE_EXTRACTING 0x00000002 /* Algorithm Identifiers */ #define TEE_ALG_AES_ECB_NOPAD 0x10000010 #define TEE_ALG_AES_CBC_NOPAD 0x10000110 #define TEE_ALG_AES_CTR 0x10000210 #define TEE_ALG_AES_CTS 0x10000310 #define TEE_ALG_AES_XTS 0x10000410 #define TEE_ALG_AES_CBC_MAC_NOPAD 0x30000110 #define TEE_ALG_AES_CBC_MAC_PKCS5 0x30000510 #define TEE_ALG_AES_CMAC 0x30000610 #define TEE_ALG_AES_CCM 0x40000710 #define TEE_ALG_AES_GCM 0x40000810 #define TEE_ALG_DES_ECB_NOPAD 0x10000011 #define TEE_ALG_DES_CBC_NOPAD 0x10000111 #define TEE_ALG_DES_CBC_MAC_NOPAD 0x30000111 #define TEE_ALG_DES_CBC_MAC_PKCS5 0x30000511 #define TEE_ALG_DES3_ECB_NOPAD 0x10000013 #define TEE_ALG_DES3_CBC_NOPAD 0x10000113 #define TEE_ALG_DES3_CBC_MAC_NOPAD 0x30000113 #define TEE_ALG_DES3_CBC_MAC_PKCS5 0x30000513 #define TEE_ALG_SM4_ECB_NOPAD 0x10000014 #define TEE_ALG_SM4_CBC_NOPAD 0x10000114 #define TEE_ALG_SM4_CTR 0x10000214 #define TEE_ALG_RSASSA_PKCS1_V1_5_MD5 0x70001830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 0x70002830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 0x70003830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 0x70004830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 0x70005830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 0x70006830 #define TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1 0x7000F830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_224 0x70008830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_256 0x70009830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_384 0x7000A830 #define TEE_ALG_RSASSA_PKCS1_V1_5_SHA3_512 0x7000B830 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 0x70212930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 0x70313930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 0x70414930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 0x70515930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 0x70616930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_224 0x70818930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_256 0x70919930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_384 0x70A1A930 #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA3_512 0x70B1B930 #define TEE_ALG_RSAES_PKCS1_V1_5 0x60000130 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1 0x60210230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224 0x60310230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256 0x60410230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384 0x60510230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512 0x60610230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_224 0x60810230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_256 0x60910230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_384 0x60A10230 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA3_512 0x60B10230 #define TEE_ALG_RSA_NOPAD 0x60000030 #define TEE_ALG_DSA_SHA1 0x70002131 #define TEE_ALG_DSA_SHA224 0x70003131 #define TEE_ALG_DSA_SHA256 0x70004131 #define TEE_ALG_DSA_SHA3_224 0x70008131 #define TEE_ALG_DSA_SHA3_256 0x70009131 #define TEE_ALG_DSA_SHA3_384 0x7000A131 #define TEE_ALG_DSA_SHA3_512 0x7000B131 #define TEE_ALG_SM2_DSA_SM3 0x70006045 #define TEE_ALG_DH_DERIVE_SHARED_SECRET 0x80000032 #define TEE_ALG_SM2_KEP 0x60000045 #define TEE_ALG_MD5 0x50000001 #define TEE_ALG_SHA1 0x50000002 #define TEE_ALG_SHA224 0x50000003 #define TEE_ALG_SHA256 0x50000004 #define TEE_ALG_SHA384 0x50000005 #define TEE_ALG_SHA512 0x50000006 #define TEE_ALG_SHA3_224 0x50000008 #define TEE_ALG_SHA3_256 0x50000009 #define TEE_ALG_SHA3_384 0x5000000A #define TEE_ALG_SHA3_512 0x5000000B #define TEE_ALG_MD5SHA1 0x5000000F #define TEE_ALG_HMAC_MD5 0x30000001 #define TEE_ALG_HMAC_SHA1 0x30000002 #define TEE_ALG_HMAC_SHA224 0x30000003 #define TEE_ALG_HMAC_SHA256 0x30000004 #define TEE_ALG_HMAC_SHA384 0x30000005 #define TEE_ALG_HMAC_SHA512 0x30000006 #define TEE_ALG_HMAC_SM3 0x30000007 #define TEE_ALG_HMAC_SHA3_224 0x30000008 #define TEE_ALG_HMAC_SHA3_256 0x30000009 #define TEE_ALG_HMAC_SHA3_384 0x3000000A #define TEE_ALG_HMAC_SHA3_512 0x3000000B /* * These are used in the OP-TEE ABI, due to an inconsistency in the v1.1 * specification the wrong values we assumed and now we're stuck with those. * * In GP Internal Core API v1.1 * "Table 6-12: Structure of Algorithm Identifier" * indicates ECDSA have the algorithm "0x41" and ECDH "0x42" * whereas * "Table 6-11: List of Algorithm Identifiers" defines * TEE_ALG_ECDSA_P192 as 0x70001042 * * We chose to define __OPTEE_TEE_ALG_ECDSA_P192 as 0x70001041 and so on * to conform to table 6-12. */ #define __OPTEE_ALG_ECDSA_P192 0x70001041 #define __OPTEE_ALG_ECDSA_P224 0x70002041 #define __OPTEE_ALG_ECDSA_P256 0x70003041 #define __OPTEE_ALG_ECDSA_P384 0x70004041 #define __OPTEE_ALG_ECDSA_P521 0x70005041 #define __OPTEE_ALG_ECDH_P192 0x80001042 #define __OPTEE_ALG_ECDH_P224 0x80002042 #define __OPTEE_ALG_ECDH_P256 0x80003042 #define __OPTEE_ALG_ECDH_P384 0x80004042 #define __OPTEE_ALG_ECDH_P521 0x80005042 /* TEE_ALG_ECDSA_P* and TEE_ALG_ECDH_P* are deprecated */ #define TEE_ALG_ECDSA_P192 TEE_ALG_ECDSA_SHA1 #define TEE_ALG_ECDSA_P224 TEE_ALG_ECDSA_SHA224 #define TEE_ALG_ECDSA_P256 TEE_ALG_ECDSA_SHA256 #define TEE_ALG_ECDSA_P384 TEE_ALG_ECDSA_SHA384 #define TEE_ALG_ECDSA_P521 TEE_ALG_ECDSA_SHA512 #define TEE_ALG_ECDH_P192 TEE_ALG_ECDH_DERIVE_SHARED_SECRET #define TEE_ALG_ECDH_P224 TEE_ALG_ECDH_DERIVE_SHARED_SECRET #define TEE_ALG_ECDH_P256 TEE_ALG_ECDH_DERIVE_SHARED_SECRET #define TEE_ALG_ECDH_P384 TEE_ALG_ECDH_DERIVE_SHARED_SECRET #define TEE_ALG_ECDH_P521 TEE_ALG_ECDH_DERIVE_SHARED_SECRET #define TEE_ALG_ECDH_DERIVE_SHARED_SECRET 0x80000042 #define TEE_ALG_ECDSA_SHA1 0x70001042 #define TEE_ALG_ECDSA_SHA224 0x70002042 #define TEE_ALG_ECDSA_SHA256 0x70003042 #define TEE_ALG_ECDSA_SHA384 0x70004042 #define TEE_ALG_ECDSA_SHA512 0x70005042 #define TEE_ALG_ECDSA_SHA3_224 0x70006042 #define TEE_ALG_ECDSA_SHA3_256 0x70007042 #define TEE_ALG_ECDSA_SHA3_384 0x70008042 #define TEE_ALG_ECDSA_SHA3_512 0x70009042 #define TEE_ALG_ED25519 0x70006043 #define TEE_ALG_ED448 0x70006044 #define TEE_ALG_SM2_PKE 0x80000046 #define TEE_ALG_HKDF 0x80000047 #define TEE_ALG_SM3 0x50000007 #define TEE_ALG_X25519 0x80000044 #define TEE_ALG_X448 0x80000045 #define TEE_ALG_SM4_ECB_PKCS5 0x10000015 #define TEE_ALG_SM4_CBC_PKCS5 0x10000115 #define TEE_ALG_ILLEGAL_VALUE 0xEFFFFFFF #define TEE_ALG_SHA3_224 0x50000008 #define TEE_ALG_SHA3_256 0x50000009 #define TEE_ALG_SHA3_384 0x5000000A #define TEE_ALG_SHA3_512 0x5000000B #define TEE_ALG_SHAKE128 0x50000101 #define TEE_ALG_SHAKE256 0x50000102 /* Object Types */ #define TEE_TYPE_AES 0xA0000010 #define TEE_TYPE_DES 0xA0000011 #define TEE_TYPE_DES3 0xA0000013 #define TEE_TYPE_SM4 0xA0000014 #define TEE_TYPE_HMAC_MD5 0xA0000001 #define TEE_TYPE_HMAC_SHA1 0xA0000002 #define TEE_TYPE_HMAC_SHA224 0xA0000003 #define TEE_TYPE_HMAC_SHA256 0xA0000004 #define TEE_TYPE_HMAC_SHA384 0xA0000005 #define TEE_TYPE_HMAC_SHA512 0xA0000006 #define TEE_TYPE_HMAC_SM3 0xA0000007 #define TEE_TYPE_HMAC_SHA3_224 0xA0000008 #define TEE_TYPE_HMAC_SHA3_256 0xA0000009 #define TEE_TYPE_HMAC_SHA3_384 0xA000000A #define TEE_TYPE_HMAC_SHA3_512 0xA000000B #define TEE_TYPE_RSA_PUBLIC_KEY 0xA0000030 #define TEE_TYPE_RSA_KEYPAIR 0xA1000030 #define TEE_TYPE_DSA_PUBLIC_KEY 0xA0000031 #define TEE_TYPE_DSA_KEYPAIR 0xA1000031 #define TEE_TYPE_DH_KEYPAIR 0xA1000032 #define TEE_TYPE_ECDSA_PUBLIC_KEY 0xA0000041 #define TEE_TYPE_ECDSA_KEYPAIR 0xA1000041 #define TEE_TYPE_ECDH_PUBLIC_KEY 0xA0000042 #define TEE_TYPE_ECDH_KEYPAIR 0xA1000042 #define TEE_TYPE_ED25519_PUBLIC_KEY 0xA0000043 #define TEE_TYPE_ED25519_KEYPAIR 0xA1000043 #define TEE_TYPE_ED448_PUBLIC_KEY 0xA0000048 #define TEE_TYPE_ED448_KEYPAIR 0xA1000048 #define TEE_TYPE_X448_PUBLIC_KEY 0xA0000049 #define TEE_TYPE_X448_KEYPAIR 0xA1000049 #define TEE_TYPE_SM2_DSA_PUBLIC_KEY 0xA0000045 #define TEE_TYPE_SM2_DSA_KEYPAIR 0xA1000045 #define TEE_TYPE_SM2_KEP_PUBLIC_KEY 0xA0000046 #define TEE_TYPE_SM2_KEP_KEYPAIR 0xA1000046 #define TEE_TYPE_SM2_PKE_PUBLIC_KEY 0xA0000047 #define TEE_TYPE_SM2_PKE_KEYPAIR 0xA1000047 #define TEE_TYPE_HKDF 0xA000004A #define TEE_TYPE_GENERIC_SECRET 0xA0000000 #define TEE_TYPE_CORRUPTED_OBJECT 0xA00000BE #define TEE_TYPE_DATA 0xA00000BF #define TEE_TYPE_X25519_PUBLIC_KEY 0xA0000044 #define TEE_TYPE_X25519_KEYPAIR 0xA1000044 #define TEE_TYPE_ILLEGAL_VALUE 0xEFFFFFFF /* List of Object or Operation Attributes */ #define TEE_ATTR_SECRET_VALUE 0xC0000000 #define TEE_ATTR_RSA_MODULUS 0xD0000130 #define TEE_ATTR_RSA_PUBLIC_EXPONENT 0xD0000230 #define TEE_ATTR_RSA_PRIVATE_EXPONENT 0xC0000330 #define TEE_ATTR_RSA_PRIME1 0xC0000430 #define TEE_ATTR_RSA_PRIME2 0xC0000530 #define TEE_ATTR_RSA_EXPONENT1 0xC0000630 #define TEE_ATTR_RSA_EXPONENT2 0xC0000730 #define TEE_ATTR_RSA_COEFFICIENT 0xC0000830 #define TEE_ATTR_DSA_PRIME 0xD0001031 #define TEE_ATTR_DSA_SUBPRIME 0xD0001131 #define TEE_ATTR_DSA_BASE 0xD0001231 #define TEE_ATTR_DSA_PUBLIC_VALUE 0xD0000131 #define TEE_ATTR_DSA_PRIVATE_VALUE 0xC0000231 #define TEE_ATTR_DH_PRIME 0xD0001032 #define TEE_ATTR_DH_SUBPRIME 0xD0001132 #define TEE_ATTR_DH_BASE 0xD0001232 #define TEE_ATTR_DH_X_BITS 0xF0001332 #define TEE_ATTR_DH_PUBLIC_VALUE 0xD0000132 #define TEE_ATTR_DH_PRIVATE_VALUE 0xC0000232 #define TEE_ATTR_RSA_OAEP_LABEL 0xD0000930 #define TEE_ATTR_RSA_OAEP_MGF_HASH 0xD0000931 #define TEE_ATTR_RSA_PSS_SALT_LENGTH 0xF0000A30 #define TEE_ATTR_ECC_PUBLIC_VALUE_X 0xD0000141 #define TEE_ATTR_ECC_PUBLIC_VALUE_Y 0xD0000241 #define TEE_ATTR_ECC_PRIVATE_VALUE 0xC0000341 #define TEE_ATTR_ECC_CURVE 0xF0000441 #define TEE_ATTR_SM2_ID_INITIATOR 0xD0000446 #define TEE_ATTR_SM2_ID_RESPONDER 0xD0000546 #define TEE_ATTR_SM2_KEP_USER 0xF0000646 #define TEE_ATTR_SM2_KEP_CONFIRMATION_IN 0xD0000746 #define TEE_ATTR_SM2_KEP_CONFIRMATION_OUT 0xD0000846 /* * Commit 5b385b3f835d ("core: crypto: add support for SM2 KEP") defined by * mistake the wrong values for these two. OP-TEE recognizes these two as * alternative IDs in parallel with the correct official values when * supplied as parameters when deriving a key using the TEE_ALG_SM2_KEP * algorithm. */ #define __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X 0xD0000946 #define __OPTEE_SM2_KEP_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y 0xD0000A46 #define TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_X 0xD0000146 #define TEE_ATTR_ECC_EPHEMERAL_PUBLIC_VALUE_Y 0xD0000246 #define TEE_ATTR_EDDSA_CTX 0xD0000643 #define TEE_ATTR_ED25519_PUBLIC_VALUE 0xD0000743 #define TEE_ATTR_ED25519_PRIVATE_VALUE 0xC0000843 #define TEE_ATTR_X25519_PUBLIC_VALUE 0xD0000944 #define TEE_ATTR_X25519_PRIVATE_VALUE 0xC0000A44 #define TEE_ATTR_EDDSA_PREHASH 0xF0000004 #define TEE_ATTR_X448_PUBLIC_VALUE 0xD0000A45 #define TEE_ATTR_X448_PRIVATE_VALUE 0xC0000A46 #define TEE_ATTR_HKDF_SALT 0xD0000946 #define TEE_ATTR_HKDF_INFO 0xD0000A46 #define TEE_ATTR_HKDF_HASH_ALGORITHM 0xF0000B46 #define TEE_ATTR_KDF_KEY_SIZE 0xF0000C46 #define TEE_ATTR_FLAG_PUBLIC (1 << 28) #define TEE_ATTR_FLAG_VALUE (1 << 29) /* * Deprecated, but kept for backwards compatibility * * Be careful with GPD TEE Internal API specification v1.0 where table 6-12 * defines BIT [28] with the right meaning whereas sections 5.4.3 and 5.4.4 * falsely describe a reversed bit flag value meaning. */ #define TEE_ATTR_BIT_PROTECTED TEE_ATTR_FLAG_PUBLIC #define TEE_ATTR_BIT_VALUE TEE_ATTR_FLAG_VALUE /* List of Supported ECC Curves */ #define TEE_CRYPTO_ELEMENT_NONE 0x00000000 #define TEE_ECC_CURVE_NIST_P192 0x00000001 #define TEE_ECC_CURVE_NIST_P224 0x00000002 #define TEE_ECC_CURVE_NIST_P256 0x00000003 #define TEE_ECC_CURVE_NIST_P384 0x00000004 #define TEE_ECC_CURVE_NIST_P521 0x00000005 #define TEE_ECC_CURVE_25519 0x00000300 #define TEE_ECC_CURVE_SM2 0x00000400 /* Panicked Functions Identification */ /* TA Interface */ #define TEE_PANIC_ID_TA_CLOSESESSIONENTRYPOINT 0x00000101 #define TEE_PANIC_ID_TA_CREATEENTRYPOINT 0x00000102 #define TEE_PANIC_ID_TA_DESTROYENTRYPOINT 0x00000103 #define TEE_PANIC_ID_TA_INVOKECOMMANDENTRYPOINT 0x00000104 #define TEE_PANIC_ID_TA_OPENSESSIONENTRYPOINT 0x00000105 /* Property Access */ #define TEE_PANIC_ID_TEE_ALLOCATEPROPERTYENUMERATOR 0x00000201 #define TEE_PANIC_ID_TEE_FREEPROPERTYENUMERATOR 0x00000202 #define TEE_PANIC_ID_TEE_GETNEXTPROPERTY 0x00000203 #define TEE_PANIC_ID_TEE_GETPROPERTYASBINARYBLOCK 0x00000204 #define TEE_PANIC_ID_TEE_GETPROPERTYASBOOL 0x00000205 #define TEE_PANIC_ID_TEE_GETPROPERTYASIDENTITY 0x00000206 #define TEE_PANIC_ID_TEE_GETPROPERTYASSTRING 0x00000207 #define TEE_PANIC_ID_TEE_GETPROPERTYASU32 0x00000208 #define TEE_PANIC_ID_TEE_GETPROPERTYASUUID 0x00000209 #define TEE_PANIC_ID_TEE_GETPROPERTYNAME 0x0000020A #define TEE_PANIC_ID_TEE_RESETPROPERTYENUMERATOR 0x0000020B #define TEE_PANIC_ID_TEE_STARTPROPERTYENUMERATOR 0x0000020C /* Panic Function */ #define TEE_PANIC_ID_TEE_PANIC 0x00000301 /* Internal Client API */ #define TEE_PANIC_ID_TEE_CLOSETASESSION 0x00000401 #define TEE_PANIC_ID_TEE_INVOKETACOMMAND 0x00000402 #define TEE_PANIC_ID_TEE_OPENTASESSION 0x00000403 /* Cancellation */ #define TEE_PANIC_ID_TEE_GETCANCELLATIONFLAG 0x00000501 #define TEE_PANIC_ID_TEE_MASKCANCELLATION 0x00000502 #define TEE_PANIC_ID_TEE_UNMASKCANCELLATION 0x00000503 /* Memory Management */ #define TEE_PANIC_ID_TEE_CHECKMEMORYACCESSRIGHTS 0x00000601 #define TEE_PANIC_ID_TEE_FREE 0x00000602 #define TEE_PANIC_ID_TEE_GETINSTANCEDATA 0x00000603 #define TEE_PANIC_ID_TEE_MALLOC 0x00000604 #define TEE_PANIC_ID_TEE_MEMCOMPARE 0x00000605 #define TEE_PANIC_ID_TEE_MEMFILL 0x00000606 #define TEE_PANIC_ID_TEE_MEMMOVE 0x00000607 #define TEE_PANIC_ID_TEE_REALLOC 0x00000608 #define TEE_PANIC_ID_TEE_SETINSTANCEDATA 0x00000609 /* Generic Object */ #define TEE_PANIC_ID_TEE_CLOSEOBJECT 0x00000701 #define TEE_PANIC_ID_TEE_GETOBJECTBUFFERATTRIBUTE 0x00000702 /* deprecated */ #define TEE_PANIC_ID_TEE_GETOBJECTINFO 0x00000703 #define TEE_PANIC_ID_TEE_GETOBJECTVALUEATTRIBUTE 0x00000704 /* deprecated */ #define TEE_PANIC_ID_TEE_RESTRICTOBJECTUSAGE 0x00000705 #define TEE_PANIC_ID_TEE_GETOBJECTINFO1 0x00000706 #define TEE_PANIC_ID_TEE_RESTRICTOBJECTUSAGE1 0x00000707 /* Transient Object */ #define TEE_PANIC_ID_TEE_ALLOCATETRANSIENTOBJECT 0x00000801 /* deprecated */ #define TEE_PANIC_ID_TEE_COPYOBJECTATTRIBUTES 0x00000802 #define TEE_PANIC_ID_TEE_FREETRANSIENTOBJECT 0x00000803 #define TEE_PANIC_ID_TEE_GENERATEKEY 0x00000804 #define TEE_PANIC_ID_TEE_INITREFATTRIBUTE 0x00000805 #define TEE_PANIC_ID_TEE_INITVALUEATTRIBUTE 0x00000806 #define TEE_PANIC_ID_TEE_POPULATETRANSIENTOBJECT 0x00000807 #define TEE_PANIC_ID_TEE_RESETTRANSIENTOBJECT 0x00000808 #define TEE_PANIC_ID_TEE_COPYOBJECTATTRIBUTES1 0x00000809 /* Persistent Object */ /* deprecated */ #define TEE_PANIC_ID_TEE_CLOSEANDDELETEPERSISTENTOBJECT 0x00000901 #define TEE_PANIC_ID_TEE_CREATEPERSISTENTOBJECT 0x00000902 #define TEE_PANIC_ID_TEE_OPENPERSISTENTOBJECT 0x00000903 #define TEE_PANIC_ID_TEE_RENAMEPERSISTENTOBJECT 0x00000904 #define TEE_PANIC_ID_TEE_CLOSEANDDELETEPERSISTENTOBJECT1 0x00000905 /* Persistent Object Enumeration */ #define TEE_PANIC_ID_TEE_ALLOCATEPERSISTENTOBJECTENUMERATOR 0x00000A01 #define TEE_PANIC_ID_TEE_FREEPERSISTENTOBJECTENUMERATOR 0x00000A02 #define TEE_PANIC_ID_TEE_GETNEXTPERSISTENTOBJECT 0x00000A03 #define TEE_PANIC_ID_TEE_RESETPERSISTENTOBJECTENUMERATOR 0x00000A04 #define TEE_PANIC_ID_TEE_STARTPERSISTENTOBJECTENUMERATOR 0x00000A05 /* Data Stream Access */ #define TEE_PANIC_ID_TEE_READOBJECTDATA 0x00000B01 #define TEE_PANIC_ID_TEE_SEEKOBJECTDATA 0x00000B02 #define TEE_PANIC_ID_TEE_TRUNCATEOBJECTDATA 0x00000B03 #define TEE_PANIC_ID_TEE_WRITEOBJECTDATA 0x00000B04 /* Generic Operation */ #define TEE_PANIC_ID_TEE_ALLOCATEOPERATION 0x00000C01 #define TEE_PANIC_ID_TEE_COPYOPERATION 0x00000C02 #define TEE_PANIC_ID_TEE_FREEOPERATION 0x00000C03 #define TEE_PANIC_ID_TEE_GETOPERATIONINFO 0x00000C04 #define TEE_PANIC_ID_TEE_RESETOPERATION 0x00000C05 #define TEE_PANIC_ID_TEE_SETOPERATIONKEY 0x00000C06 #define TEE_PANIC_ID_TEE_SETOPERATIONKEY2 0x00000C07 #define TEE_PANIC_ID_TEE_GETOPERATIONINFOMULTIPLE 0x00000C08 /* Message Digest */ #define TEE_PANIC_ID_TEE_DIGESTDOFINAL 0x00000D01 #define TEE_PANIC_ID_TEE_DIGESTUPDATE 0x00000D02 /* Symmetric Cipher */ #define TEE_PANIC_ID_TEE_CIPHERDOFINAL 0x00000E01 #define TEE_PANIC_ID_TEE_CIPHERINIT 0x00000E02 #define TEE_PANIC_ID_TEE_CIPHERUPDATE 0x00000E03 /* MAC */ #define TEE_PANIC_ID_TEE_MACCOMPAREFINAL 0x00000F01 #define TEE_PANIC_ID_TEE_MACCOMPUTEFINAL 0x00000F02 #define TEE_PANIC_ID_TEE_MACINIT 0x00000F03 #define TEE_PANIC_ID_TEE_MACUPDATE 0x00000F04 /* Authenticated Encryption */ #define TEE_PANIC_ID_TEE_AEDECRYPTFINAL 0x00001001 #define TEE_PANIC_ID_TEE_AEENCRYPTFINAL 0x00001002 #define TEE_PANIC_ID_TEE_AEINIT 0x00001003 #define TEE_PANIC_ID_TEE_AEUPDATE 0x00001004 #define TEE_PANIC_ID_TEE_AEUPDATEAAD 0x00001005 /* Asymmetric */ #define TEE_PANIC_ID_TEE_ASYMMETRICDECRYPT 0x00001101 #define TEE_PANIC_ID_TEE_ASYMMETRICENCRYPT 0x00001102 #define TEE_PANIC_ID_TEE_ASYMMETRICSIGNDIGEST 0x00001103 #define TEE_PANIC_ID_TEE_ASYMMETRICVERIFYDIGEST 0x00001104 /* Key Derivation */ #define TEE_PANIC_ID_TEE_DERIVEKEY 0x00001201 /* Random Data Generation */ #define TEE_PANIC_ID_TEE_GENERATERANDOM 0x00001301 /* Time */ #define TEE_PANIC_ID_TEE_GETREETIME 0x00001401 #define TEE_PANIC_ID_TEE_GETSYSTEMTIME 0x00001402 #define TEE_PANIC_ID_TEE_GETTAPERSISTENTTIME 0x00001403 #define TEE_PANIC_ID_TEE_SETTAPERSISTENTTIME 0x00001404 #define TEE_PANIC_ID_TEE_WAIT 0x00001405 /* Memory Allocation and Size of Objects */ #define TEE_PANIC_ID_TEE_BIGINTFMMCONTEXTSIZEINU32 0x00001501 #define TEE_PANIC_ID_TEE_BIGINTFMMSIZEINU32 0x00001502 /* Initialization */ #define TEE_PANIC_ID_TEE_BIGINTINIT 0x00001601 #define TEE_PANIC_ID_TEE_BIGINTINITFMM 0x00001602 #define TEE_PANIC_ID_TEE_BIGINTINITFMMCONTEXT 0x00001603 /* Converter */ #define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMOCTETSTRING 0x00001701 #define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMS32 0x00001702 #define TEE_PANIC_ID_TEE_BIGINTCONVERTTOOCTETSTRING 0x00001703 #define TEE_PANIC_ID_TEE_BIGINTCONVERTTOS32 0x00001704 /* Logical Operation */ #define TEE_PANIC_ID_TEE_BIGINTCMP 0x00001801 #define TEE_PANIC_ID_TEE_BIGINTCMPS32 0x00001802 #define TEE_PANIC_ID_TEE_BIGINTGETBIT 0x00001803 #define TEE_PANIC_ID_TEE_BIGINTGETBITCOUNT 0x00001804 #define TEE_PANIC_ID_TEE_BIGINTSHIFTRIGHT 0x00001805 /* Basic Arithmetic */ #define TEE_PANIC_ID_TEE_BIGINTADD 0x00001901 #define TEE_PANIC_ID_TEE_BIGINTDIV 0x00001902 #define TEE_PANIC_ID_TEE_BIGINTMUL 0x00001903 #define TEE_PANIC_ID_TEE_BIGINTNEG 0x00001904 #define TEE_PANIC_ID_TEE_BIGINTSQUARE 0x00001905 #define TEE_PANIC_ID_TEE_BIGINTSUB 0x00001906 /* Modular Arithmetic */ #define TEE_PANIC_ID_TEE_BIGINTADDMOD 0x00001A01 #define TEE_PANIC_ID_TEE_BIGINTINVMOD 0x00001A02 #define TEE_PANIC_ID_TEE_BIGINTMOD 0x00001A03 #define TEE_PANIC_ID_TEE_BIGINTMULMOD 0x00001A04 #define TEE_PANIC_ID_TEE_BIGINTSQUAREMOD 0x00001A05 #define TEE_PANIC_ID_TEE_BIGINTSUBMOD 0x00001A06 /* Other Arithmetic */ #define TEE_PANIC_ID_TEE_BIGINTCOMPUTEEXTENDEDGCD 0x00001B01 #define TEE_PANIC_ID_TEE_BIGINTISPROBABLEPRIME 0x00001B02 #define TEE_PANIC_ID_TEE_BIGINTRELATIVEPRIME 0x00001B03 /* Fast Modular Multiplication */ #define TEE_PANIC_ID_TEE_BIGINTCOMPUTEFMM 0x00001C01 #define TEE_PANIC_ID_TEE_BIGINTCONVERTFROMFMM 0x00001C02 #define TEE_PANIC_ID_TEE_BIGINTCONVERTTOFMM 0x00001C03 /* * The macro TEE_PARAM_TYPES can be used to construct a value that you can * compare against an incoming paramTypes to check the type of all the * parameters in one comparison, like in the following example: * if (paramTypes != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, * TEE_PARAM_TYPE_MEMREF_OUPUT, * TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) { * return TEE_ERROR_BAD_PARAMETERS; * } */ #define TEE_PARAM_TYPES(t0,t1,t2,t3) \ ((t0) | ((t1) << 4) | ((t2) << 8) | ((t3) << 12)) /* * The macro TEE_PARAM_TYPE_GET can be used to extract the type of a given * parameter from paramTypes if you need more fine-grained type checking. */ #define TEE_PARAM_TYPE_GET(t, i) ((((uint32_t)t) >> ((i)*4)) & 0xF) /* * The macro TEE_PARAM_TYPE_SET can be used to load the type of a given * parameter from paramTypes without specifying all types (TEE_PARAM_TYPES) */ #define TEE_PARAM_TYPE_SET(t, i) (((uint32_t)(t) & 0xF) << ((i)*4)) /* Not specified in the standard */ #define TEE_NUM_PARAMS 4 /* TEE Arithmetical APIs */ #define TEE_BigIntSizeInU32(n) ((((n)+31)/32)+2) #endif /* TEE_API_DEFINES_H */ optee_os-4.3.0/lib/libutee/include/tee_api_defines_extensions.h000066400000000000000000000104461464416617300247310ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2021, Linaro Limited * Copyright (c) 2021, SumUp Services GmbH */ #ifndef TEE_API_DEFINES_EXTENSIONS_H #define TEE_API_DEFINES_EXTENSIONS_H /* * RSA signatures with MD5 hash * Values prefixed with vendor ID bit31 with by TEE bitfields IDs */ #define TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5 0xF0111930 #define TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5 0xF0110230 /* * API extended result codes as per TEE_Result IDs defined in GPD TEE * Internal Core API specification v1.1: * * 0x70000000 - 0x7FFFFFFF: Reserved for implementation-specific return * code providing non-error information * 0x80000000 - 0x8FFFFFFF: Reserved for implementation-specific errors * * TEE_ERROR_DEFER_DRIVER_INIT - Device driver failed to initialize because * the driver depends on a device not yet initialized. */ #define TEE_ERROR_DEFER_DRIVER_INIT 0x80000000 /* * TEE_ERROR_NODE_DISABLED - Device driver failed to initialize because it is * not allocated for TEE environment. */ #define TEE_ERROR_NODE_DISABLED 0x80000001 /* * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) */ #define TEE_ALG_HKDF_MD5_DERIVE_KEY 0x800010C0 #define TEE_ALG_HKDF_SHA1_DERIVE_KEY 0x800020C0 #define TEE_ALG_HKDF_SHA224_DERIVE_KEY 0x800030C0 #define TEE_ALG_HKDF_SHA256_DERIVE_KEY 0x800040C0 #define TEE_ALG_HKDF_SHA384_DERIVE_KEY 0x800050C0 #define TEE_ALG_HKDF_SHA512_DERIVE_KEY 0x800060C0 #define TEE_TYPE_HKDF_IKM 0xA10000C0 #define TEE_ATTR_HKDF_IKM 0xC00001C0 /* * There is a name clash with the official attributes TEE_ATTR_HKDF_SALT * and TEE_ATTR_HKDF_INFO so define these alternative ID. */ #define __OPTEE_TEE_ATTR_HKDF_SALT 0xD00002C0 #define __OPTEE_ATTR_HKDF_INFO 0xD00003C0 #define TEE_ATTR_HKDF_OKM_LENGTH 0xF00004C0 /* * Concatenation Key Derivation Function (Concat KDF) * NIST SP 800-56A section 5.8.1 */ #define TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY 0x800020C1 #define TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY 0x800030C1 #define TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY 0x800040C1 #define TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY 0x800050C1 #define TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY 0x800060C1 #define TEE_TYPE_CONCAT_KDF_Z 0xA10000C1 #define TEE_ATTR_CONCAT_KDF_Z 0xC00001C1 #define TEE_ATTR_CONCAT_KDF_OTHER_INFO 0xD00002C1 #define TEE_ATTR_CONCAT_KDF_DKM_LENGTH 0xF00003C1 /* * PKCS #5 v2.0 Key Derivation Function 2 (PBKDF2) * RFC 2898 section 5.2 * https://www.ietf.org/rfc/rfc2898.txt */ #define TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY 0x800020C2 #define TEE_TYPE_PBKDF2_PASSWORD 0xA10000C2 #define TEE_ATTR_PBKDF2_PASSWORD 0xC00001C2 #define TEE_ATTR_PBKDF2_SALT 0xD00002C2 #define TEE_ATTR_PBKDF2_ITERATION_COUNT 0xF00003C2 #define TEE_ATTR_PBKDF2_DKM_LENGTH 0xF00004C2 /* * PKCS#1 v1.5 RSASSA pre-hashed sign/verify */ #define TEE_ALG_RSASSA_PKCS1_V1_5 0xF0000830 /* * TDEA CMAC (NIST SP800-38B) */ #define TEE_ALG_DES3_CMAC 0xF0000613 /* * SM4-XTS */ #define TEE_ALG_SM4_XTS 0xF0000414 /* * Implementation-specific object storage constants */ /* Storage is provided by the Rich Execution Environment (REE) */ #define TEE_STORAGE_PRIVATE_REE 0x80000000 /* Storage is the Replay Protected Memory Block partition of an eMMC device */ #define TEE_STORAGE_PRIVATE_RPMB 0x80000100 /* Was TEE_STORAGE_PRIVATE_SQL, which isn't supported any longer */ #define TEE_STORAGE_PRIVATE_SQL_RESERVED 0x80000200 /* * Extension of "Memory Access Rights Constants" * #define TEE_MEMORY_ACCESS_READ 0x00000001 * #define TEE_MEMORY_ACCESS_WRITE 0x00000002 * #define TEE_MEMORY_ACCESS_ANY_OWNER 0x00000004 * * TEE_MEMORY_ACCESS_NONSECURE : if set TEE_CheckMemoryAccessRights() * successfully returns only if target vmem range is mapped non-secure. * * TEE_MEMORY_ACCESS_SECURE : if set TEE_CheckMemoryAccessRights() * successfully returns only if target vmem range is mapped secure. */ #define TEE_MEMORY_ACCESS_NONSECURE 0x10000000 #define TEE_MEMORY_ACCESS_SECURE 0x20000000 /* * Implementation-specific login types */ /* Private login method for REE kernel clients */ #define TEE_LOGIN_REE_KERNEL 0x80000000 #endif /* TEE_API_DEFINES_EXTENSIONS_H */ optee_os-4.3.0/lib/libutee/include/tee_api_types.h000066400000000000000000000113061464416617300221750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* Based on GP TEE Internal API Specification Version 0.11 */ #ifndef TEE_API_TYPES_H #define TEE_API_TYPES_H #include #include #include #include #include /* * Common Definitions */ typedef uint32_t TEE_Result; typedef struct { uint32_t timeLow; uint16_t timeMid; uint16_t timeHiAndVersion; uint8_t clockSeqAndNode[8]; } TEE_UUID; /* * The TEE_Identity structure defines the full identity of a Client: * - login is one of the TEE_LOGIN_XXX constants * - uuid contains the client UUID or Nil if not applicable */ typedef struct { uint32_t login; TEE_UUID uuid; } TEE_Identity; /* * This union describes one parameter passed by the Trusted Core Framework * to the entry points TA_OpenSessionEntryPoint or * TA_InvokeCommandEntryPoint or by the TA to the functions * TEE_OpenTASession or TEE_InvokeTACommand. * * Which of the field value or memref to select is determined by the * parameter type specified in the argument paramTypes passed to the entry * point. */ typedef union { struct { void *buffer; size_t size; } memref; struct { uint32_t a; uint32_t b; } value; } TEE_Param; typedef union { struct { void *buffer; uint32_t size; } memref; struct { uint32_t a; uint32_t b; } value; } __GP11_TEE_Param; /* * The type of opaque handles on TA Session. These handles are returned by * the function TEE_OpenTASession. */ typedef struct __TEE_TASessionHandle *TEE_TASessionHandle; /* * The type of opaque handles on property sets or enumerators. These * handles are either one of the pseudo handles TEE_PROPSET_XXX or are * returned by the function TEE_AllocatePropertyEnumerator. */ typedef struct __TEE_PropSetHandle *TEE_PropSetHandle; typedef struct __TEE_ObjectHandle *TEE_ObjectHandle; typedef struct __TEE_ObjectEnumHandle *TEE_ObjectEnumHandle; typedef struct __TEE_OperationHandle *TEE_OperationHandle; /* * Storage Definitions */ typedef uint32_t TEE_ObjectType; typedef struct { uint32_t objectType; uint32_t objectSize; uint32_t maxObjectSize; uint32_t objectUsage; size_t dataSize; size_t dataPosition; uint32_t handleFlags; } TEE_ObjectInfo; typedef struct { uint32_t objectType; __extension__ union { uint32_t keySize; /* used in 1.1 spec */ uint32_t objectSize; /* used in 1.1.1 spec */ }; __extension__ union { uint32_t maxKeySize; /* used in 1.1 spec */ uint32_t maxObjectSize; /* used in 1.1.1 spec */ }; uint32_t objectUsage; uint32_t dataSize; uint32_t dataPosition; uint32_t handleFlags; } __GP11_TEE_ObjectInfo; typedef uint32_t TEE_Whence; typedef struct { uint32_t attributeID; union { struct { void *buffer; size_t length; } ref; struct { uint32_t a, b; } value; } content; } TEE_Attribute; typedef struct { uint32_t attributeID; union { struct { void *buffer; uint32_t length; } ref; struct { uint32_t a, b; } value; } content; } __GP11_TEE_Attribute; /* Cryptographic Operations API */ typedef uint32_t TEE_OperationMode; typedef struct { uint32_t algorithm; uint32_t operationClass; uint32_t mode; uint32_t digestLength; uint32_t maxKeySize; uint32_t keySize; uint32_t requiredKeyUsage; uint32_t handleState; } TEE_OperationInfo; typedef struct { uint32_t keySize; uint32_t requiredKeyUsage; } TEE_OperationInfoKey; typedef struct { uint32_t algorithm; uint32_t operationClass; uint32_t mode; uint32_t digestLength; uint32_t maxKeySize; uint32_t handleState; uint32_t operationState; uint32_t numberOfKeys; TEE_OperationInfoKey keyInformation[]; } TEE_OperationInfoMultiple; /* Time & Date API */ typedef struct { uint32_t seconds; uint32_t millis; } TEE_Time; /* TEE Arithmetical APIs */ typedef uint32_t TEE_BigInt; typedef uint32_t TEE_BigIntFMM; typedef uint32_t TEE_BigIntFMMContext __aligned(__alignof__(void *)); /* Tee Secure Element APIs */ typedef struct __TEE_SEServiceHandle *TEE_SEServiceHandle; typedef struct __TEE_SEReaderHandle *TEE_SEReaderHandle; typedef struct __TEE_SESessionHandle *TEE_SESessionHandle; typedef struct __TEE_SEChannelHandle *TEE_SEChannelHandle; typedef struct { bool sePresent; bool teeOnly; bool selectResponseEnable; } TEE_SEReaderProperties; typedef struct { uint8_t *buffer; size_t bufferLen; } TEE_SEAID; /* Other definitions */ typedef uint32_t TEE_ErrorOrigin; typedef void *TEE_Session; #define TEE_MEM_INPUT 0x00000001 #define TEE_MEM_OUTPUT 0x00000002 #define TEE_MEMREF_0_USED 0x00000001 #define TEE_MEMREF_1_USED 0x00000002 #define TEE_MEMREF_2_USED 0x00000004 #define TEE_MEMREF_3_USED 0x00000008 #define TEE_SE_READER_NAME_MAX 20 #endif /* TEE_API_TYPES_H */ optee_os-4.3.0/lib/libutee/include/tee_arith_internal.h000066400000000000000000000024221464416617300232020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef GUARD_TEE_MATHAPI_H #define GUARD_TEE_MATHAPI_H #include /* for size_t */ #include /* for uint32_t and friends */ #include /* for bool (!) */ /************************************************************* * * MACRO DEFINITIONS * *************************************************************/ /*------------------------------------------------------------ * * How functions are exported * */ #define TEE_MATHAPI_EXPORT /*------------------------------------------------------------ * * Define IN, OUT, INBUF and OUTBUF to keep format from the spec. * */ #define IN const #define OUT #define INOUT #define INBUF const #define OUTBUF /************************************************************* * * MEMORY ALLOCATION AND SIZE * *************************************************************/ /************************************************************* * * INITIALIZATION FUNCTIONS * *************************************************************/ /* * !!! This function must be called before you do anything else !!! * NOTE: Not part of the spec */ TEE_MATHAPI_EXPORT void _TEE_MathAPI_Init(void); #endif optee_os-4.3.0/lib/libutee/include/tee_internal_api.h000066400000000000000000000763331464416617300226600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* Based on GP TEE Internal API Specification Version 0.27 */ #ifndef TEE_INTERNAL_API_H #define TEE_INTERNAL_API_H #ifdef __TEE_API_COMPAT_H #error " must not be included before " #endif #include #include #include #include #include /* Property access functions */ TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, const char *name, char *valueBuffer, size_t *valueBufferLen); TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, const char *name, char *valueBuffer, uint32_t *valueBufferLen); TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, const char *name, bool *value); TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, const char *name, uint32_t *value); TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator, const char *name, uint64_t *value); TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, const char *name, void *valueBuffer, size_t *valueBufferLen); TEE_Result __GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, const char *name, void *valueBuffer, uint32_t *valueBufferLen); TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, const char *name, TEE_UUID *value); TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, const char *name, TEE_Identity *value); TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator); void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator); void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, TEE_PropSetHandle propSet); void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator); TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, void *nameBuffer, size_t *nameBufferLen); TEE_Result __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator, void *nameBuffer, uint32_t *nameBufferLen); TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator); /* System API - Misc */ void TEE_Panic(TEE_Result panicCode); /* System API - Internal Client API */ TEE_Result TEE_OpenTASession(const TEE_UUID *destination, uint32_t cancellationRequestTimeout, uint32_t paramTypes, TEE_Param params[TEE_NUM_PARAMS], TEE_TASessionHandle *session, uint32_t *returnOrigin); TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, uint32_t cancellationRequestTimeout, uint32_t paramTypes, __GP11_TEE_Param params[TEE_NUM_PARAMS], TEE_TASessionHandle *session, uint32_t *returnOrigin); void TEE_CloseTASession(TEE_TASessionHandle session); TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, uint32_t cancellationRequestTimeout, uint32_t commandID, uint32_t paramTypes, TEE_Param params[TEE_NUM_PARAMS], uint32_t *returnOrigin); TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, uint32_t cancellationRequestTimeout, uint32_t commandID, uint32_t paramTypes, __GP11_TEE_Param params[TEE_NUM_PARAMS], uint32_t *returnOrigin); /* System API - Cancellations */ bool TEE_GetCancellationFlag(void); bool TEE_UnmaskCancellation(void); bool TEE_MaskCancellation(void); /* System API - Memory Management */ TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, size_t size); TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, uint32_t size); void TEE_SetInstanceData(const void *instanceData); const void *TEE_GetInstanceData(void); void *TEE_Malloc(size_t size, uint32_t hint); void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint); void *TEE_Realloc(void *buffer, size_t newSize); void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize); void TEE_Free(void *buffer); void *TEE_MemMove(void *dest, const void *src, size_t size); void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size); /* * Note: TEE_MemCompare() has a constant-time implementation (execution time * does not depend on buffer content but only on buffer size). It is the main * difference with memcmp(). */ int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size); int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size); void TEE_MemFill(void *buff, uint32_t x, size_t size); void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size); /* Data and Key Storage API - Generic Object Functions */ void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo); void __GP11_TEE_GetObjectInfo(TEE_ObjectHandle object, __GP11_TEE_ObjectInfo *objectInfo); TEE_Result TEE_GetObjectInfo1(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo); TEE_Result __GP11_TEE_GetObjectInfo1(TEE_ObjectHandle object, __GP11_TEE_ObjectInfo *objectInfo); void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage); TEE_Result TEE_RestrictObjectUsage1(TEE_ObjectHandle object, uint32_t objectUsage); TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, uint32_t attributeID, void *buffer, size_t *size); TEE_Result __GP11_TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, uint32_t attributeID, void *buffer, uint32_t *size); TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, uint32_t attributeID, uint32_t *a, uint32_t *b); void TEE_CloseObject(TEE_ObjectHandle object); /* Data and Key Storage API - Transient Object Functions */ TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType, uint32_t maxObjectSize, TEE_ObjectHandle *object); TEE_Result __GP11_TEE_AllocateTransientObject(TEE_ObjectType objectType, uint32_t maxKeySize, TEE_ObjectHandle *object); void TEE_FreeTransientObject(TEE_ObjectHandle object); void TEE_ResetTransientObject(TEE_ObjectHandle object); TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, const TEE_Attribute *attrs, uint32_t attrCount); TEE_Result __GP11_TEE_PopulateTransientObject(TEE_ObjectHandle object, const __GP11_TEE_Attribute *attrs, uint32_t attrCount); void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID, const void *buffer, size_t length); void __GP11_TEE_InitRefAttribute(__GP11_TEE_Attribute *attr, uint32_t attributeID, const void *buffer, uint32_t length); void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID, uint32_t a, uint32_t b); void __GP11_TEE_InitValueAttribute(__GP11_TEE_Attribute *attr, uint32_t attributeID, uint32_t a, uint32_t b); void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, TEE_ObjectHandle srcObject); TEE_Result TEE_CopyObjectAttributes1(TEE_ObjectHandle destObject, TEE_ObjectHandle srcObject); TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, const TEE_Attribute *params, uint32_t paramCount); TEE_Result __GP11_TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, const __GP11_TEE_Attribute *params, uint32_t paramCount); /* Data and Key Storage API - Persistent Object Functions */ TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle *object); TEE_Result __GP11_TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, uint32_t objectIDLen, uint32_t flags, TEE_ObjectHandle *object); TEE_Result TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, const void *initialData, size_t initialDataLen, TEE_ObjectHandle *object); TEE_Result __GP11_TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, uint32_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, const void *initialData, uint32_t initialDataLen, TEE_ObjectHandle *object); void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object); TEE_Result TEE_CloseAndDeletePersistentObject1(TEE_ObjectHandle object); TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, const void *newObjectID, size_t newObjectIDLen); TEE_Result __GP11_TEE_RenamePersistentObject(TEE_ObjectHandle object, const void *newObjectID, uint32_t newObjectIDLen); TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle * objectEnumerator); void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator); TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator, uint32_t storageID); TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, TEE_ObjectInfo *objectInfo, void *objectID, size_t *objectIDLen); TEE_Result __GP11_TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, __GP11_TEE_ObjectInfo *objectInfo, void *objectID, uint32_t *objectIDLen); /* Data and Key Storage API - Data Stream Access Functions */ TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, size_t size, size_t *count); TEE_Result __GP11_TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, uint32_t size, uint32_t *count); TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, const void *buffer, size_t size); TEE_Result __GP11_TEE_WriteObjectData(TEE_ObjectHandle object, const void *buffer, uint32_t size); TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, size_t size); TEE_Result __GP11_TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size); TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, intmax_t offset, TEE_Whence whence); TEE_Result __GP11_TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, TEE_Whence whence); /* Cryptographic Operations API - Generic Operation Functions */ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, uint32_t algorithm, uint32_t mode, uint32_t maxKeySize); void TEE_FreeOperation(TEE_OperationHandle operation); void __GP11_TEE_FreeOperation(TEE_OperationHandle operation); void TEE_GetOperationInfo(TEE_OperationHandle operation, TEE_OperationInfo *operationInfo); TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, TEE_OperationInfoMultiple *operationInfoMultiple, size_t *operationSize); TEE_Result __GP11_TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, TEE_OperationInfoMultiple *info, uint32_t *operationSize); void TEE_ResetOperation(TEE_OperationHandle operation); TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, TEE_ObjectHandle key); TEE_Result __GP11_TEE_SetOperationKey(TEE_OperationHandle operation, TEE_ObjectHandle key); TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, TEE_ObjectHandle key1, TEE_ObjectHandle key2); TEE_Result __GP11_TEE_SetOperationKey2(TEE_OperationHandle operation, TEE_ObjectHandle key1, TEE_ObjectHandle key2); void TEE_CopyOperation(TEE_OperationHandle dstOperation, TEE_OperationHandle srcOperation); TEE_Result TEE_IsAlgorithmSupported(uint32_t algId, uint32_t element); /* Cryptographic Operations API - Message Digest Functions */ void TEE_DigestUpdate(TEE_OperationHandle operation, const void *chunk, size_t chunkSize); void __GP11_TEE_DigestUpdate(TEE_OperationHandle operation, const void *chunk, uint32_t chunkSize); TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, size_t chunkLen, void *hash, size_t *hashLen); TEE_Result __GP11_TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, uint32_t chunkLen, void *hash, uint32_t *hashLen); TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, void *hash, size_t *hashLen); /* Cryptographic Operations API - Symmetric Cipher Functions */ void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, size_t IVLen); void __GP11_TEE_CipherInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen); TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen); TEE_Result __GP11_TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen); TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen); TEE_Result __GP11_TEE_CipherDoFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen); /* Cryptographic Operations API - MAC Functions */ void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen); void __GP11_TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen); void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, size_t chunkSize); void __GP11_TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, uint32_t chunkSize); TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, const void *message, size_t messageLen, void *mac, size_t *macLen); TEE_Result __GP11_TEE_MACComputeFinal(TEE_OperationHandle operation, const void *message, uint32_t messageLen, void *mac, uint32_t *macLen); TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, const void *message, size_t messageLen, const void *mac, size_t macLen); TEE_Result __GP11_TEE_MACCompareFinal(TEE_OperationHandle operation, const void *message, uint32_t messageLen, const void *mac, uint32_t macLen); /* Cryptographic Operations API - Authenticated Encryption Functions */ TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, size_t nonceLen, uint32_t tagLen, size_t AADLen, size_t payloadLen); TEE_Result __GP11_TEE_AEInit(TEE_OperationHandle operation, const void *nonce, uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen, uint32_t payloadLen); void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, size_t AADdataLen); void __GP11_TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, uint32_t AADdataLen); TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen); TEE_Result __GP11_TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen); TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen, void *tag, size_t *tagLen); TEE_Result __GP11_TEE_AEEncryptFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen, void *tag, uint32_t *tagLen); TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen, void *tag, size_t tagLen); TEE_Result __GP11_TEE_AEDecryptFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen, void *tag, uint32_t tagLen); /* Cryptographic Operations API - Asymmetric Functions */ TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *srcData, size_t srcLen, void *destData, size_t *destLen); TEE_Result __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen); TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *srcData, size_t srcLen, void *destData, size_t *destLen); TEE_Result __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen); TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *digest, size_t digestLen, void *signature, size_t *signatureLen); TEE_Result __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *digest, uint32_t digestLen, void *signature, uint32_t *signatureLen); TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *digest, size_t digestLen, const void *signature, size_t signatureLen); TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *digest, uint32_t digestLen, const void *signature, uint32_t signatureLen); /* Cryptographic Operations API - Key Derivation Functions */ void TEE_DeriveKey(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, TEE_ObjectHandle derivedKey); void __GP11_TEE_DeriveKey(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, TEE_ObjectHandle derivedKey); /* Cryptographic Operations API - Random Number Generation Functions */ void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen); void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen); /* Date & Time API */ void TEE_GetSystemTime(TEE_Time *time); TEE_Result TEE_Wait(uint32_t timeout); TEE_Result TEE_GetTAPersistentTime(TEE_Time *time); TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time); void TEE_GetREETime(TEE_Time *time); /* TEE Arithmetical API - Memory allocation and size of objects */ size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits); uint32_t __GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits); size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits); uint32_t __GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits); /* TEE Arithmetical API - Initialization functions */ void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len); void __GP11_TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len); void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, size_t len, const TEE_BigInt *modulus); void __GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, uint32_t len, const TEE_BigInt *modulus); TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context, size_t len, const TEE_BigInt *modulus); void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len); void __GP11_TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len); /* TEE Arithmetical API - Converter functions */ TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, size_t bufferLen, int32_t sign); TEE_Result __GP11_TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, uint32_t bufferLen, int32_t sign); TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, size_t *bufferLen, const TEE_BigInt *bigInt); TEE_Result __GP11_TEE_BigIntConvertToOctetString(uint8_t *buffer, uint32_t *bufferLen, const TEE_BigInt *bigInt); void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal); TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src); /* TEE Arithmetical API - Logical operations */ int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2); int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal); void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits); void __GP11_TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, uint32_t bits); bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex); uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src); TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value); TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src); TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, const TEE_BigInt *src); void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2); void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2); void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *op); void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2); void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op); void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, const TEE_BigInt *op1, const TEE_BigInt *op2); /* TEE Arithmetical API - Modular arithmetic operations */ void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n); void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n); void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n); void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n); void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n); void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n); TEE_Result TEE_BigIntExpMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n, const TEE_BigIntFMMContext *context); /* TEE Arithmetical API - Other arithmetic operations */ bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2); void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, TEE_BigInt *v, const TEE_BigInt *op1, const TEE_BigInt *op2); int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, uint32_t confidenceLevel); /* TEE Arithmetical API - Fast modular multiplication operations */ void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, const TEE_BigInt *n, const TEE_BigIntFMMContext *context); void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, const TEE_BigInt *n, const TEE_BigIntFMMContext *context); void TEE_BigIntFMMConvertToBigInt(TEE_BigInt *dest, const TEE_BigIntFMM *src, const TEE_BigInt *n, const TEE_BigIntFMMContext *context); void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, const TEE_BigIntFMM *op2, const TEE_BigInt *n, const TEE_BigIntFMMContext *context); #define TA_EXPORT /* * TA Interface * * Each Trusted Application must provide the Implementation with a number * of functions, collectively called the “TA interface”. These functions * are the entry points called by the Trusted Core Framework to create the * instance, notify the instance that a new client is connecting, notify * the instance when the client invokes a command, etc. * * Trusted Application Entry Points: */ /* * The function TA_CreateEntryPoint is the Trusted Application's * constructor, which the Framework calls when it creates a new instance of * the Trusted Application. To register instance data, the implementation * of this constructor can use either global variables or the function * TEE_InstanceSetData. * * Return Value: * - TEE_SUCCESS: if the instance is successfully created, the function * must return TEE_SUCCESS. * - Any other value: if any other code is returned the instance is not * created, and no other entry points of this instance will be called. * The Framework MUST reclaim all resources and dereference all objects * related to the creation of the instance. * * If this entry point was called as a result of a client opening a * session, the error code is returned to the client and the session is * not opened. */ TEE_Result TA_EXPORT TA_CreateEntryPoint(void); /* * The function TA_DestroyEntryPoint is the Trusted Application‟s * destructor, which the Framework calls when the instance is being * destroyed. * * When the function TA_DestroyEntryPoint is called, the Framework * guarantees that no client session is currently open. Once the call to * TA_DestroyEntryPoint has been completed, no other entry point of this * instance will ever be called. * * Note that when this function is called, all resources opened by the * instance are still available. It is only after the function returns that * the Implementation MUST start automatically reclaiming resources left * opened. * * Return Value: * This function can return no success or error code. After this function * returns the Implementation MUST consider the instance destroyed and * reclaims all resources left open by the instance. */ void TA_EXPORT TA_DestroyEntryPoint(void); /* * The Framework calls the function TA_OpenSessionEntryPoint when a client * requests to open a session with the Trusted Application. The open * session request may result in a new Trusted Application instance being * created as defined in section 4.5. * * The client can specify parameters in an open operation which are passed * to the Trusted Application instance in the arguments paramTypes and * params. These arguments can also be used by the Trusted Application * instance to transfer response data back to the client. See section 4.3.6 * for a specification of how to handle the operation parameters. * * If this function returns TEE_SUCCESS, the client is connected to a * Trusted Application instance and can invoke Trusted Application * commands. When the client disconnects, the Framework will eventually * call the TA_CloseSessionEntryPoint entry point. * * If the function returns any error, the Framework rejects the connection * and returns the error code and the current content of the parameters the * client. The return origin is then set to TEE_ORIGIN_TRUSTED_APP. * * The Trusted Application instance can register a session data pointer by * setting *psessionContext. The value of this pointer is not interpreted * by the Framework, and is simply passed back to other TA_ functions * within this session. Note that *sessionContext may be set with a pointer * to a memory allocated by the Trusted Application instance or with * anything else, like an integer, a handle etc. The Framework will not * automatically free *sessionContext when the session is closed; the * Trusted Application instance is responsible for freeing memory if * required. * * During the call to TA_OpenSessionEntryPoint the client may request to * cancel the operation. See section 4.10 for more details on * cancellations. If the call to TA_OpenSessionEntryPoint returns * TEE_SUCCESS, the client must consider the session as successfully opened * and explicitly close it if necessary. * * Parameters: * - paramTypes: the types of the four parameters. * - params: a pointer to an array of four parameters. * - sessionContext: A pointer to a variable that can be filled by the * Trusted Application instance with an opaque void* data pointer * * Return Value: * - TEE_SUCCESS if the session is successfully opened. * - Any other value if the session could not be open. * o The error code may be one of the pre-defined codes, or may be a new * error code defined by the Trusted Application implementation itself. */ TEE_Result TA_EXPORT TA_OpenSessionEntryPoint(uint32_t paramTypes, TEE_Param params[TEE_NUM_PARAMS], void **sessionContext); TEE_Result TA_EXPORT __GP11_TA_OpenSessionEntryPoint(uint32_t paramTypes, __GP11_TEE_Param params[TEE_NUM_PARAMS], void **sessionContext); /* * The Framework calls this function to close a client session. During the * call to this function the implementation can use any session functions. * * The Trusted Application implementation is responsible for freeing any * resources consumed by the session being closed. Note that the Trusted * Application cannot refuse to close a session, but can hold the closing * until it returns from TA_CloseSessionEntryPoint. This is why this * function cannot return an error code. * * Parameters: * - sessionContext: The value of the void* opaque data pointer set by the * Trusted Application in the function TA_OpenSessionEntryPoint for this * session. */ void TA_EXPORT TA_CloseSessionEntryPoint(void *sessionContext); /* * The Framework calls this function when the client invokes a command * within the given session. * * The Trusted Application can access the parameters sent by the client * through the paramTypes and params arguments. It can also use these * arguments to transfer response data back to the client. * * During the call to TA_InvokeCommandEntryPoint the client may request to * cancel the operation. * * A command is always invoked within the context of a client session. * Thus, any session function can be called by the command implementation. * * Parameter: * - sessionContext: The value of the void* opaque data pointer set by the * Trusted Application in the function TA_OpenSessionEntryPoint. * - commandID: A Trusted Application-specific code that identifies the * command to be invoked. * - paramTypes: the types of the four parameters. * - params: a pointer to an array of four parameters. * * Return Value: * - TEE_SUCCESS: if the command is successfully executed, the function * must return this value. * - Any other value: if the invocation of the command fails for any * reason. * o The error code may be one of the pre-defined codes, or may be a new * error code defined by the Trusted Application implementation itself. */ TEE_Result TA_EXPORT TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID, uint32_t paramTypes, TEE_Param params[TEE_NUM_PARAMS]); TEE_Result TA_EXPORT __GP11_TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID, uint32_t paramTypes, __GP11_TEE_Param params[TEE_NUM_PARAMS]); /* * Matching Client Functions <--> TA Functions * * TEE_OpenSession or TEE_OpenTASession: * If a new Trusted Application instance is needed to handle the session, * TA_CreateEntryPoint is called. * Then, TA_OpenSessionEntryPoint is called. * * TEE_InvokeCommand or TEE_InvokeTACommand: * TA_InvokeCommandEntryPoint is called. * * TEE_CloseSession or TEE_CloseTASession: * TA_CloseSessionEntryPoint is called. * For a multi-instance TA or for a single-instance, non keep-alive TA, if * the session closed was the last session on the instance, then * TA_DestroyEntryPoint is called. Otherwise, the instance is kept until * the TEE shuts down. */ #include #endif /*TEE_INTERNAL_API_H*/ optee_os-4.3.0/lib/libutee/include/tee_internal_api_extensions.h000066400000000000000000000051001464416617300251170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Open Mobile Platform LLC */ #ifndef TEE_INTERNAL_API_EXTENSIONS_H #define TEE_INTERNAL_API_EXTENSIONS_H /* trace support */ #include #include #include #include void tee_user_mem_mark_heap(void); size_t tee_user_mem_check_heap(void); /* Hint implementation defines */ #define TEE_USER_MEM_HINT_NO_FILL_ZERO 0x80000000 /* * Cache maintenance support (TA requires the CACHE_MAINTENANCE property) * * TEE_CacheClean() Write back to memory any dirty data cache lines. The line * is marked as not dirty. The valid bit is unchanged. * * TEE_CacheFlush() Purges any valid data cache lines. Any dirty cache lines * are first written back to memory, then the cache line is * invalidated. * * TEE_CacheInvalidate() Invalidate any valid data cache lines. Any dirty line * are not written back to memory. */ TEE_Result TEE_CacheClean(char *buf, size_t len); TEE_Result TEE_CacheFlush(char *buf, size_t len); TEE_Result TEE_CacheInvalidate(char *buf, size_t len); /* * tee_map_zi() - Map zero initialized memory * @len: Number of bytes * @flags: 0 or TEE_MEMORY_ACCESS_ANY_OWNER to allow sharing with other TAs * * Returns valid pointer on success or NULL on error. */ void *tee_map_zi(size_t len, uint32_t flags); /* * tee_unmap() - Unmap previously mapped memory * @buf: Buffer * @len: Number of bytes * * Note that supplied @buf and @len has to match exactly what has * previously been returned by tee_map_zi(). * * Return TEE_SUCCESS on success or TEE_ERRROR_* on failure. */ TEE_Result tee_unmap(void *buf, size_t len); /* * Convert a UUID string @s into a TEE_UUID @uuid * Expected format for @s is: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx * 'x' being any hexadecimal digit (0-9a-fA-F) */ TEE_Result tee_uuid_from_str(TEE_UUID *uuid, const char *s); /* * tee_invoke_supp_plugin() - invoke a tee-supplicant's plugin * @uuid: uuid of the plugin * @cmd: command for the plugin * @sub_cmd: subcommand for the plugin * @buf: data [for/from] the plugin [in/out] * @len: length of the input buf * @outlen: pointer to length of the output data (if they will be used) * * Return TEE_SUCCESS on success or TEE_ERRROR_* on failure. */ TEE_Result tee_invoke_supp_plugin(const TEE_UUID *uuid, uint32_t cmd, uint32_t sub_cmd, void *buf, size_t len, size_t *outlen); #endif optee_os-4.3.0/lib/libutee/include/tee_isocket.h000066400000000000000000000015561464416617300216470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef __TEE_ISOCKET_H #define __TEE_ISOCKET_H #include #include #include <__tee_isocket_defines.h> typedef void *TEE_iSocketHandle; typedef const struct TEE_iSocket_s { uint32_t TEE_iSocketVersion; uint8_t protocolID; TEE_Result (*open)(TEE_iSocketHandle *ctx, void *setup, uint32_t *protocolError); TEE_Result (*close)(TEE_iSocketHandle ctx); TEE_Result (*send)(TEE_iSocketHandle ctx, const void *buf, uint32_t *length, uint32_t timeout); TEE_Result (*recv)(TEE_iSocketHandle ctx, void *buf, uint32_t *length, uint32_t timeout); uint32_t (*error)(TEE_iSocketHandle ctx); TEE_Result (*ioctl)(TEE_iSocketHandle ctx, uint32_t commandCode, void *buf, uint32_t *length); } TEE_iSocket; #endif /*__TEE_ISOCKET_H*/ optee_os-4.3.0/lib/libutee/include/tee_syscall_numbers.h000066400000000000000000000063161464416617300234120ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef TEE_SYSCALL_NUMBERS_H #define TEE_SYSCALL_NUMBERS_H #define TEE_SCN_RETURN 0 #define TEE_SCN_LOG 1 #define TEE_SCN_PANIC 2 #define TEE_SCN_GET_PROPERTY 3 #define TEE_SCN_GET_PROPERTY_NAME_TO_INDEX 4 #define TEE_SCN_OPEN_TA_SESSION 5 #define TEE_SCN_CLOSE_TA_SESSION 6 #define TEE_SCN_INVOKE_TA_COMMAND 7 #define TEE_SCN_CHECK_ACCESS_RIGHTS 8 #define TEE_SCN_GET_CANCELLATION_FLAG 9 #define TEE_SCN_UNMASK_CANCELLATION 10 #define TEE_SCN_MASK_CANCELLATION 11 #define TEE_SCN_WAIT 12 #define TEE_SCN_GET_TIME 13 #define TEE_SCN_SET_TA_TIME 14 #define TEE_SCN_CRYP_STATE_ALLOC 15 #define TEE_SCN_CRYP_STATE_COPY 16 #define TEE_SCN_CRYP_STATE_FREE 17 #define TEE_SCN_HASH_INIT 18 #define TEE_SCN_HASH_UPDATE 19 #define TEE_SCN_HASH_FINAL 20 #define TEE_SCN_CIPHER_INIT 21 #define TEE_SCN_CIPHER_UPDATE 22 #define TEE_SCN_CIPHER_FINAL 23 #define TEE_SCN_CRYP_OBJ_GET_INFO 24 #define TEE_SCN_CRYP_OBJ_RESTRICT_USAGE 25 #define TEE_SCN_CRYP_OBJ_GET_ATTR 26 #define TEE_SCN_CRYP_OBJ_ALLOC 27 #define TEE_SCN_CRYP_OBJ_CLOSE 28 #define TEE_SCN_CRYP_OBJ_RESET 29 #define TEE_SCN_CRYP_OBJ_POPULATE 30 #define TEE_SCN_CRYP_OBJ_COPY 31 #define TEE_SCN_CRYP_DERIVE_KEY 32 #define TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE 33 #define TEE_SCN_AUTHENC_INIT 34 #define TEE_SCN_AUTHENC_UPDATE_AAD 35 #define TEE_SCN_AUTHENC_UPDATE_PAYLOAD 36 #define TEE_SCN_AUTHENC_ENC_FINAL 37 #define TEE_SCN_AUTHENC_DEC_FINAL 38 #define TEE_SCN_ASYMM_OPERATE 39 #define TEE_SCN_ASYMM_VERIFY 40 #define TEE_SCN_STORAGE_OBJ_OPEN 41 #define TEE_SCN_STORAGE_OBJ_CREATE 42 #define TEE_SCN_STORAGE_OBJ_DEL 43 #define TEE_SCN_STORAGE_OBJ_RENAME 44 #define TEE_SCN_STORAGE_ENUM_ALLOC 45 #define TEE_SCN_STORAGE_ENUM_FREE 46 #define TEE_SCN_STORAGE_ENUM_RESET 47 #define TEE_SCN_STORAGE_ENUM_START 48 #define TEE_SCN_STORAGE_ENUM_NEXT 49 #define TEE_SCN_STORAGE_OBJ_READ 50 #define TEE_SCN_STORAGE_OBJ_WRITE 51 #define TEE_SCN_STORAGE_OBJ_TRUNC 52 #define TEE_SCN_STORAGE_OBJ_SEEK 53 #define TEE_SCN_CRYP_OBJ_GENERATE_KEY 54 /* Deprecated Secure Element API syscalls return TEE_ERROR_NOT_SUPPORTED */ #define TEE_SCN_SE_SERVICE_OPEN__DEPRECATED 55 #define TEE_SCN_SE_SERVICE_CLOSE__DEPRECATED 56 #define TEE_SCN_SE_SERVICE_GET_READERS__DEPRECATED 57 #define TEE_SCN_SE_READER_GET_PROP__DEPRECATED 58 #define TEE_SCN_SE_READER_GET_NAME__DEPRECATED 59 #define TEE_SCN_SE_READER_OPEN_SESSION__DEPRECATED 60 #define TEE_SCN_SE_READER_CLOSE_SESSIONS__DEPRECATED 61 #define TEE_SCN_SE_SESSION_IS_CLOSED__DEPRECATED 62 #define TEE_SCN_SE_SESSION_GET_ATR__DEPRECATED 63 #define TEE_SCN_SE_SESSION_OPEN_CHANNEL__DEPRECATED 64 #define TEE_SCN_SE_SESSION_CLOSE__DEPRECATED 65 #define TEE_SCN_SE_CHANNEL_SELECT_NEXT__DEPRECATED 66 #define TEE_SCN_SE_CHANNEL_GET_SELECT_RESP__DEPRECATED 67 #define TEE_SCN_SE_CHANNEL_TRANSMIT__DEPRECATED 68 #define TEE_SCN_SE_CHANNEL_CLOSE__DEPRECATED 69 /* End of deprecated Secure Element API syscalls */ #define TEE_SCN_CACHE_OPERATION 70 #define TEE_SCN_MAX 70 /* Maximum number of allowed arguments for a syscall */ #define TEE_SVC_MAX_ARGS 8 #endif /* TEE_SYSCALL_NUMBERS_H */ optee_os-4.3.0/lib/libutee/include/tee_ta_api.h000066400000000000000000000004001464416617300214260ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* Based on GP TEE Internal API Specification Version 0.22 */ #ifndef TEE_TA_API_H #define TEE_TA_API_H #include #endif optee_os-4.3.0/lib/libutee/include/tee_tcpsocket.h000066400000000000000000000007031464416617300221760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef __TEE_TCPSOCKET_H #define __TEE_TCPSOCKET_H #include #include <__tee_ipsocket.h> #include <__tee_tcpsocket_defines.h> typedef struct TEE_tcpSocket_Setup_s { TEE_ipSocket_ipVersion ipVersion; char *server_addr; uint16_t server_port; } TEE_tcpSocket_Setup; extern TEE_iSocket *const TEE_tcpSocket; #endif /*__TEE_TCPSOCKET_H*/ optee_os-4.3.0/lib/libutee/include/tee_udpsocket.h000066400000000000000000000007031464416617300222000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef __TEE_UDPSOCKET_H #define __TEE_UDPSOCKET_H #include #include <__tee_ipsocket.h> #include <__tee_udpsocket_defines.h> typedef struct TEE_udpSocket_Setup_s { TEE_ipSocket_ipVersion ipVersion; char *server_addr; uint16_t server_port; } TEE_udpSocket_Setup; extern TEE_iSocket *const TEE_udpSocket; #endif /*__TEE_UDPSOCKET_H*/ optee_os-4.3.0/lib/libutee/include/user_ta_header.h000066400000000000000000000112101464416617300223070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2018, Linaro Limited. */ #ifndef USER_TA_HEADER_H #define USER_TA_HEADER_H #include #include #define TA_FLAG_USER_MODE 0 /* Deprecated, was BIT32(0) */ #define TA_FLAG_EXEC_DDR 0 /* Deprecated, was BIT32(1) */ #define TA_FLAG_SINGLE_INSTANCE BIT32(2) #define TA_FLAG_MULTI_SESSION BIT32(3) #define TA_FLAG_INSTANCE_KEEP_ALIVE BIT32(4) /* remains after last close */ #define TA_FLAG_SECURE_DATA_PATH BIT32(5) /* accesses SDP memory */ #define TA_FLAG_REMAP_SUPPORT 0 /* Deprecated, was BIT32(6) */ #define TA_FLAG_CACHE_MAINTENANCE BIT32(7) /* use cache flush syscall */ /* * TA instance can execute multiple sessions concurrently * (pseudo-TAs only). */ #define TA_FLAG_CONCURRENT BIT32(8) /* * Device enumeration is done in two stages by the normal world, first * before the tee-supplicant has started and then once more when the * tee-supplicant is started. The flags below control if the TA should * be reported in the first or second or case. */ #define TA_FLAG_DEVICE_ENUM BIT32(9) /* without tee-supplicant */ #define TA_FLAG_DEVICE_ENUM_SUPP BIT32(10) /* with tee-supplicant */ /* See also "gpd.ta.doesNotCloseHandleOnCorruptObject" */ #define TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT \ BIT32(11) #define TA_FLAGS_MASK GENMASK_32(11, 0) struct ta_head { TEE_UUID uuid; uint32_t stack_size; uint32_t flags; uint64_t depr_entry; }; #if defined(CFG_FTRACE_SUPPORT) #define FTRACE_RETFUNC_DEPTH 50 union compat_ptr { uint64_t ptr64; struct { uint32_t lo; uint32_t hi; } ptr32; }; struct __ftrace_info { union compat_ptr buf_start; union compat_ptr buf_end; union compat_ptr ret_ptr; }; struct ftrace_buf { uint64_t ret_func_ptr; /* __ftrace_return pointer */ uint64_t ret_stack[FTRACE_RETFUNC_DEPTH]; /* Return stack */ uint32_t ret_idx; /* Return stack index */ uint32_t lr_idx; /* lr index used for stack unwinding */ uint64_t begin_time[FTRACE_RETFUNC_DEPTH]; /* Timestamp */ uint64_t suspend_time; /* Suspend timestamp */ uint32_t curr_idx; /* Current entry in the (circular) buffer */ uint32_t max_size; /* Max allowed size of ftrace buffer */ uint32_t head_off; /* Ftrace buffer header offset */ uint32_t buf_off; /* Ftrace buffer offset */ bool syscall_trace_enabled; /* Some syscalls are never traced */ bool syscall_trace_suspended; /* By foreign interrupt or RPC */ bool overflow; /* Circular buffer has wrapped */ }; /* Defined by the linker script */ extern struct ftrace_buf __ftrace_buf_start; extern uint8_t __ftrace_buf_end[]; unsigned long ftrace_return(void); void __ftrace_return(void); #endif void __utee_call_elf_init_fn(void); void __utee_call_elf_fini_fn(void); void __utee_tcb_init(void); /* * Information about the ELF objects loaded by the application */ struct __elf_phdr_info { uint32_t reserved; uint16_t count; uint8_t reserved2; char zero; struct dl_phdr_info *dlpi; /* @count entries */ }; /* 32-bit variant for a 64-bit ldelf to access a 32-bit TA */ struct __elf_phdr_info32 { uint32_t reserved; uint16_t count; uint8_t reserved2; char zero; uint32_t dlpi; }; extern struct __elf_phdr_info __elf_phdr_info; #define TA_PROP_STR_SINGLE_INSTANCE "gpd.ta.singleInstance" #define TA_PROP_STR_MULTI_SESSION "gpd.ta.multiSession" #define TA_PROP_STR_KEEP_ALIVE "gpd.ta.instanceKeepAlive" #define TA_PROP_STR_DATA_SIZE "gpd.ta.dataSize" #define TA_PROP_STR_STACK_SIZE "gpd.ta.stackSize" #define TA_PROP_STR_VERSION "gpd.ta.version" #define TA_PROP_STR_DESCRIPTION "gpd.ta.description" #define TA_PROP_STR_ENDIAN "gpd.ta.endian" #define TA_PROP_STR_DOES_NOT_CLOSE_HANDLE_ON_CORRUPT_OBJECT \ "gpd.ta.doesNotCloseHandleOnCorruptObject" enum user_ta_prop_type { USER_TA_PROP_TYPE_BOOL, /* bool */ USER_TA_PROP_TYPE_U32, /* uint32_t */ USER_TA_PROP_TYPE_UUID, /* TEE_UUID */ USER_TA_PROP_TYPE_IDENTITY, /* TEE_Identity */ USER_TA_PROP_TYPE_STRING, /* zero terminated string of char */ USER_TA_PROP_TYPE_BINARY_BLOCK, /* zero terminated base64 coded string */ USER_TA_PROP_TYPE_U64, /* uint64_t */ USER_TA_PROP_TYPE_INVALID, /* invalid value */ }; struct user_ta_property { const char *name; enum user_ta_prop_type type; const void *value; }; extern const struct user_ta_property ta_props[]; extern const size_t ta_num_props; extern uint8_t __ta_no_share_heap[]; extern const size_t __ta_no_share_heap_size; /* Needed by TEE_CheckMemoryAccessRights() */ extern uint32_t ta_param_types; extern TEE_Param ta_params[TEE_NUM_PARAMS]; extern struct malloc_ctx *__ta_no_share_malloc_ctx; int tahead_get_trace_level(void); #endif /* USER_TA_HEADER_H */ optee_os-4.3.0/lib/libutee/include/utee_defines.h000066400000000000000000000271511464416617300220070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2021, SumUp Services GmbH */ #ifndef UTEE_DEFINES_H #define UTEE_DEFINES_H #include #include #include #include /* * Copied from TEE Internal API specificaion v1.0 table 6-9 "Structure of * Algorithm Identifier". */ #define TEE_MAIN_ALGO_MD5 0x01 #define TEE_MAIN_ALGO_SHA1 0x02 #define TEE_MAIN_ALGO_SHA224 0x03 #define TEE_MAIN_ALGO_SHA256 0x04 #define TEE_MAIN_ALGO_SHA384 0x05 #define TEE_MAIN_ALGO_SHA512 0x06 #define TEE_MAIN_ALGO_SM3 0x07 #define TEE_MAIN_ALGO_SHA3_224 0x08 #define TEE_MAIN_ALGO_SHA3_256 0x09 #define TEE_MAIN_ALGO_SHA3_384 0x0A #define TEE_MAIN_ALGO_SHA3_512 0x0B #define TEE_MAIN_ALGO_AES 0x10 #define TEE_MAIN_ALGO_DES 0x11 #define TEE_MAIN_ALGO_DES2 0x12 #define TEE_MAIN_ALGO_DES3 0x13 #define TEE_MAIN_ALGO_SM4 0x14 /* Not in v1.2, extrapolated */ #define TEE_MAIN_ALGO_RSA 0x30 #define TEE_MAIN_ALGO_DSA 0x31 #define TEE_MAIN_ALGO_DH 0x32 #define TEE_MAIN_ALGO_ECDSA 0x41 #define TEE_MAIN_ALGO_ECDH 0x42 #define TEE_MAIN_ALGO_ED25519 0x43 #define TEE_MAIN_ALGO_SM2_DSA_SM3 0x45 /* Not in v1.2 spec */ #define TEE_MAIN_ALGO_SM2_KEP 0x46 /* Not in v1.2 spec */ #define TEE_MAIN_ALGO_SM2_PKE 0x47 /* Not in v1.2 spec */ #define TEE_MAIN_ALGO_HKDF 0xC0 /* OP-TEE extension */ #define TEE_MAIN_ALGO_CONCAT_KDF 0xC1 /* OP-TEE extension */ #define TEE_MAIN_ALGO_PBKDF2 0xC2 /* OP-TEE extension */ #define TEE_MAIN_ALGO_X25519 0x44 /* Not in v1.2 spec */ #define TEE_MAIN_ALGO_SHAKE128 0xC3 /* OP-TEE extension */ #define TEE_MAIN_ALGO_SHAKE256 0xC4 /* OP-TEE extension */ #define TEE_MAIN_ALGO_X448 0x49 #define TEE_CHAIN_MODE_ECB_NOPAD 0x0 #define TEE_CHAIN_MODE_CBC_NOPAD 0x1 #define TEE_CHAIN_MODE_CTR 0x2 #define TEE_CHAIN_MODE_CTS 0x3 #define TEE_CHAIN_MODE_XTS 0x4 #define TEE_CHAIN_MODE_CBC_MAC_PKCS5 0x5 #define TEE_CHAIN_MODE_CMAC 0x6 #define TEE_CHAIN_MODE_CCM 0x7 #define TEE_CHAIN_MODE_GCM 0x8 #define TEE_CHAIN_MODE_PKCS1_PSS_MGF1 0x9 /* ??? */ static inline uint32_t __tee_alg_get_class(uint32_t algo) { if (algo == TEE_ALG_SM2_PKE) return TEE_OPERATION_ASYMMETRIC_CIPHER; if (algo == TEE_ALG_SM2_KEP) return TEE_OPERATION_KEY_DERIVATION; if (algo == TEE_ALG_RSASSA_PKCS1_V1_5) return TEE_OPERATION_ASYMMETRIC_SIGNATURE; if (algo == TEE_ALG_DES3_CMAC) return TEE_OPERATION_MAC; if (algo == TEE_ALG_SM4_XTS) return TEE_OPERATION_CIPHER; if (algo == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5) return TEE_OPERATION_ASYMMETRIC_SIGNATURE; if (algo == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5) return TEE_OPERATION_ASYMMETRIC_CIPHER; return (algo >> 28) & 0xF; /* Bits [31:28] */ } #define TEE_ALG_GET_CLASS(algo) __tee_alg_get_class(algo) static inline uint32_t __tee_alg_get_main_alg(uint32_t algo) { switch (algo) { case TEE_ALG_SM2_PKE: return TEE_MAIN_ALGO_SM2_PKE; case TEE_ALG_SM2_KEP: return TEE_MAIN_ALGO_SM2_KEP; case TEE_ALG_X25519: return TEE_MAIN_ALGO_X25519; case TEE_ALG_ED25519: return TEE_MAIN_ALGO_ED25519; case TEE_ALG_ECDSA_SHA1: case TEE_ALG_ECDSA_SHA224: case TEE_ALG_ECDSA_SHA256: case TEE_ALG_ECDSA_SHA384: case TEE_ALG_ECDSA_SHA512: return TEE_MAIN_ALGO_ECDSA; case TEE_ALG_HKDF: return TEE_MAIN_ALGO_HKDF; case TEE_ALG_SHAKE128: return TEE_MAIN_ALGO_SHAKE128; case TEE_ALG_SHAKE256: return TEE_MAIN_ALGO_SHAKE256; case TEE_ALG_X448: return TEE_MAIN_ALGO_X448; default: break; } return algo & 0xff; } #define TEE_ALG_GET_MAIN_ALG(algo) __tee_alg_get_main_alg(algo) /* Bits [11:8] */ #define TEE_ALG_GET_CHAIN_MODE(algo) (((algo) >> 8) & 0xF) /* * Value not defined in the GP spec, and not used as bits 15-12 of any TEE_ALG* * value. TEE_ALG_SM2_DSA_SM3 has value 0x6 for bits 15-12 which would yield the * SHA512 digest if we were to apply the bit masks that were valid up to the TEE * Internal Core API v1.1. */ #define __TEE_MAIN_HASH_SM3 0x7 static inline uint32_t __tee_alg_get_digest_hash(uint32_t algo) { if (algo == TEE_ALG_SM2_DSA_SM3) return __TEE_MAIN_HASH_SM3; /* Bits [15:12] */ return (algo >> 12) & 0xF; } #define TEE_ALG_GET_DIGEST_HASH(algo) __tee_alg_get_digest_hash(algo) /* Bits [23:20] */ #define TEE_ALG_GET_INTERNAL_HASH(algo) (((algo) >> 20) & 0x7) static inline uint32_t __tee_alg_get_key_type(uint32_t algo, bool with_priv) { uint32_t key_type = 0xA0000000 | TEE_ALG_GET_MAIN_ALG(algo); if (with_priv) key_type |= 0x01000000; return key_type; } #define TEE_ALG_GET_KEY_TYPE(algo, with_private_key) \ __tee_alg_get_key_type(algo, with_private_key) static inline uint32_t __tee_alg_hash_algo(uint32_t main_hash) { if (main_hash == __TEE_MAIN_HASH_SM3) return TEE_ALG_SM3; return (TEE_OPERATION_DIGEST << 28) | main_hash; } /* Return hash algorithm based on main hash */ #define TEE_ALG_HASH_ALGO(main_hash) __tee_alg_hash_algo(main_hash) /* Extract internal hash and return hash algorithm */ #define TEE_INTERNAL_HASH_TO_ALGO(algo) \ TEE_ALG_HASH_ALGO(TEE_ALG_GET_INTERNAL_HASH(algo)) /* Extract digest hash and return hash algorithm */ #define TEE_DIGEST_HASH_TO_ALGO(algo) \ TEE_ALG_HASH_ALGO(TEE_ALG_GET_DIGEST_HASH(algo)) /* Return HMAC algorithm based on main hash */ #define TEE_ALG_HMAC_ALGO(main_hash) \ (TEE_OPERATION_MAC << 28 | (main_hash)) #define TEE_AES_BLOCK_SIZE 16UL #define TEE_DES_BLOCK_SIZE 8UL #define TEE_SM4_BLOCK_SIZE 16UL #define TEE_AES_MAX_KEY_SIZE 32UL /* SHA-512 */ #ifndef TEE_MD5_HASH_SIZE typedef enum { TEE_MD5_HASH_SIZE = 16, TEE_SHA1_HASH_SIZE = 20, TEE_SHA224_HASH_SIZE = 28, TEE_SHA256_HASH_SIZE = 32, TEE_SM3_HASH_SIZE = 32, TEE_SHA384_HASH_SIZE = 48, TEE_SHA512_HASH_SIZE = 64, TEE_MD5SHA1_HASH_SIZE = (TEE_MD5_HASH_SIZE + TEE_SHA1_HASH_SIZE), TEE_MAX_HASH_SIZE = 64, } t_hash_size; #endif #define TEE_MAC_SIZE_AES_CBC_MAC_NOPAD #define TEE_MAC_SIZE_AES_CBC_MAC_PKCS5 #define TEE_MAC_SIZE_AES_CMAC #define TEE_MAC_SIZE_DES_CBC_MAC_PKCS5 static inline size_t __tee_alg_get_digest_size(uint32_t algo) { switch (algo) { case TEE_ALG_MD5: case TEE_ALG_HMAC_MD5: return TEE_MD5_HASH_SIZE; case TEE_ALG_SHA1: case TEE_ALG_HMAC_SHA1: case TEE_ALG_DSA_SHA1: case TEE_ALG_ECDSA_SHA1: return TEE_SHA1_HASH_SIZE; case TEE_ALG_SHA224: case TEE_ALG_SHA3_224: case TEE_ALG_HMAC_SHA224: case TEE_ALG_HMAC_SHA3_224: case TEE_ALG_DSA_SHA224: case TEE_ALG_ECDSA_SHA224: return TEE_SHA224_HASH_SIZE; case TEE_ALG_SHA256: case TEE_ALG_SHA3_256: case TEE_ALG_HMAC_SHA256: case TEE_ALG_HMAC_SHA3_256: case TEE_ALG_DSA_SHA256: case TEE_ALG_ECDSA_SHA256: return TEE_SHA256_HASH_SIZE; case TEE_ALG_SHA384: case TEE_ALG_SHA3_384: case TEE_ALG_HMAC_SHA384: case TEE_ALG_HMAC_SHA3_384: case TEE_ALG_ECDSA_SHA384: return TEE_SHA384_HASH_SIZE; case TEE_ALG_SHA512: case TEE_ALG_SHA3_512: case TEE_ALG_HMAC_SHA512: case TEE_ALG_HMAC_SHA3_512: case TEE_ALG_ECDSA_SHA512: return TEE_SHA512_HASH_SIZE; case TEE_ALG_SM3: case TEE_ALG_HMAC_SM3: return TEE_SM3_HASH_SIZE; case TEE_ALG_AES_CBC_MAC_NOPAD: case TEE_ALG_AES_CBC_MAC_PKCS5: case TEE_ALG_AES_CMAC: return TEE_AES_BLOCK_SIZE; case TEE_ALG_DES_CBC_MAC_NOPAD: case TEE_ALG_DES_CBC_MAC_PKCS5: case TEE_ALG_DES3_CBC_MAC_NOPAD: case TEE_ALG_DES3_CBC_MAC_PKCS5: case TEE_ALG_DES3_CMAC: return TEE_DES_BLOCK_SIZE; default: return 0; } } /* Return algorithm digest size */ #define TEE_ALG_GET_DIGEST_SIZE(algo) __tee_alg_get_digest_size(algo) /* * Bit indicating that the attribute is a value attribute * See TEE Internal API specificaion v1.0 table 6-12 "Partial Structure of * Attribute Identifier" */ #ifdef __compiler_bswap64 #define TEE_U64_BSWAP(x) __compiler_bswap64((x)) #else #define TEE_U64_BSWAP(x) ((uint64_t)( \ (((uint64_t)(x) & UINT64_C(0xff00000000000000ULL)) >> 56) | \ (((uint64_t)(x) & UINT64_C(0x00ff000000000000ULL)) >> 40) | \ (((uint64_t)(x) & UINT64_C(0x0000ff0000000000ULL)) >> 24) | \ (((uint64_t)(x) & UINT64_C(0x000000ff00000000ULL)) >> 8) | \ (((uint64_t)(x) & UINT64_C(0x00000000ff000000ULL)) << 8) | \ (((uint64_t)(x) & UINT64_C(0x0000000000ff0000ULL)) << 24) | \ (((uint64_t)(x) & UINT64_C(0x000000000000ff00ULL)) << 40) | \ (((uint64_t)(x) & UINT64_C(0x00000000000000ffULL)) << 56))) #endif #ifdef __compiler_bswap32 #define TEE_U32_BSWAP(x) __compiler_bswap32((x)) #else #define TEE_U32_BSWAP(x) ((uint32_t)( \ (((uint32_t)(x) & UINT32_C(0xff000000)) >> 24) | \ (((uint32_t)(x) & UINT32_C(0x00ff0000)) >> 8) | \ (((uint32_t)(x) & UINT32_C(0x0000ff00)) << 8) | \ (((uint32_t)(x) & UINT32_C(0x000000ff)) << 24))) #endif #ifdef __compiler_bswap16 #define TEE_U16_BSWAP(x) __compiler_bswap16((x)) #else #define TEE_U16_BSWAP(x) ((uint16_t)( \ (((uint16_t)(x) & UINT16_C(0xff00)) >> 8) | \ (((uint16_t)(x) & UINT16_C(0x00ff)) << 8))) #endif /* If we we're on a big endian platform we'll have to update these */ #define TEE_U64_FROM_LITTLE_ENDIAN(x) ((uint64_t)(x)) #define TEE_U32_FROM_LITTLE_ENDIAN(x) ((uint32_t)(x)) #define TEE_U16_FROM_LITTLE_ENDIAN(x) ((uint16_t)(x)) #define TEE_U64_TO_LITTLE_ENDIAN(x) ((uint64_t)(x)) #define TEE_U32_TO_LITTLE_ENDIAN(x) ((uint32_t)(x)) #define TEE_U16_TO_LITTLE_ENDIAN(x) ((uint16_t)(x)) #define TEE_U64_FROM_BIG_ENDIAN(x) TEE_U64_BSWAP(x) #define TEE_U32_FROM_BIG_ENDIAN(x) TEE_U32_BSWAP(x) #define TEE_U16_FROM_BIG_ENDIAN(x) TEE_U16_BSWAP(x) #define TEE_U64_TO_BIG_ENDIAN(x) TEE_U64_BSWAP(x) #define TEE_U32_TO_BIG_ENDIAN(x) TEE_U32_BSWAP(x) #define TEE_U16_TO_BIG_ENDIAN(x) TEE_U16_BSWAP(x) #define TEE_TIME_MILLIS_BASE 1000 #define TEE_TIME_LT(t1, t2) \ (((t1).seconds == (t2).seconds) ? \ ((t1).millis < (t2).millis) : \ ((t1).seconds < (t2).seconds)) #define TEE_TIME_LE(t1, t2) \ (((t1).seconds == (t2).seconds) ? \ ((t1).millis <= (t2).millis) : \ ((t1).seconds <= (t2).seconds)) #define TEE_TIME_ADD(t1, t2, dst) do { \ (dst).seconds = (t1).seconds + (t2).seconds; \ (dst).millis = (t1).millis + (t2).millis; \ if ((dst).millis >= TEE_TIME_MILLIS_BASE) { \ (dst).seconds++; \ (dst).millis -= TEE_TIME_MILLIS_BASE; \ } \ } while (0) #define TEE_TIME_SUB(t1, t2, dst) do { \ (dst).seconds = (t1).seconds - (t2).seconds; \ if ((t1).millis < (t2).millis) { \ (dst).seconds--; \ (dst).millis = (t1).millis + TEE_TIME_MILLIS_BASE - (t2).millis;\ } else { \ (dst).millis = (t1).millis - (t2).millis; \ } \ } while (0) /* ------------------------------------------------------------ */ /* OTP mapping */ /* ------------------------------------------------------------ */ #define HW_UNIQUE_KEY_WORD1 (8) #define HW_UNIQUE_KEY_LENGTH (16) #define HW_UNIQUE_KEY_WORD2 (HW_UNIQUE_KEY_WORD1 + 1) #define HW_UNIQUE_KEY_WORD3 (HW_UNIQUE_KEY_WORD1 + 2) #define HW_UNIQUE_KEY_WORD4 (HW_UNIQUE_KEY_WORD1 + 3) #define UTEE_SE_READER_PRESENT (1 << 0) #define UTEE_SE_READER_TEE_ONLY (1 << 1) #define UTEE_SE_READER_SELECT_RESPONE_ENABLE (1 << 2) #endif /* UTEE_DEFINES_H */ optee_os-4.3.0/lib/libutee/include/utee_syscalls.h000066400000000000000000000202271464416617300222240ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef UTEE_SYSCALLS_H #define UTEE_SYSCALLS_H #include #include #include #include #include #include /* * Arguments must use the native register width, unless it's a signed * argument then it must be a 32-bit value instead to avoid problems with * sign extension. To keep it simple, only use pointers, int32_t, unsigned * long and size_t. Pointers may only point structures or types based on * fixed width integer types. Only exception are buffers with opaque data. * * Return values should not use a fixed width larger than 32 bits, unsigned * long and pointers are OK though. * * Members in structs on the other hand should only use fixed width integer * types; uint32_t, uint64_t etc. To keep it simple, use uint64_t for all * length fields. */ void _utee_return(unsigned long ret) __noreturn; void _utee_log(const void *buf, size_t len); /* This is not __noreturn because AArch32 stack unwinding fails otherwise */ void _utee_panic(unsigned long code); /* prop_set is TEE_PROPSET_xxx*/ TEE_Result _utee_get_property(unsigned long prop_set, unsigned long index, void *name, uint32_t *name_len, void *buf, uint32_t *blen, uint32_t *prop_type); TEE_Result _utee_get_property_name_to_index(unsigned long prop_set, const void *name, unsigned long name_len, uint32_t *index); /* sess has type TEE_TASessionHandle */ TEE_Result _utee_open_ta_session(const TEE_UUID *dest, unsigned long cancel_req_to, struct utee_params *params, uint32_t *sess, uint32_t *ret_orig); /* sess has type TEE_TASessionHandle */ TEE_Result _utee_close_ta_session(unsigned long sess); /* sess has type TEE_TASessionHandle */ TEE_Result _utee_invoke_ta_command(unsigned long sess, unsigned long cancel_req_to, unsigned long cmd_id, struct utee_params *params, uint32_t *ret_orig); TEE_Result _utee_check_access_rights(uint32_t flags, const void *buf, size_t len); /* cancel has type bool */ TEE_Result _utee_get_cancellation_flag(uint32_t *cancel); /* old_mask has type bool */ TEE_Result _utee_unmask_cancellation(uint32_t *old_mask); /* old_mask has type bool */ TEE_Result _utee_mask_cancellation(uint32_t *old_mask); TEE_Result _utee_wait(unsigned long timeout); /* cat has type enum _utee_time_category */ TEE_Result _utee_get_time(unsigned long cat, TEE_Time *time); TEE_Result _utee_set_ta_time(const TEE_Time *time); TEE_Result _utee_cryp_state_alloc(unsigned long algo, unsigned long op_mode, unsigned long key1, unsigned long key2, uint32_t *state); TEE_Result _utee_cryp_state_copy(unsigned long dst, unsigned long src); TEE_Result _utee_cryp_state_free(unsigned long state); /* iv and iv_len are ignored for some algorithms */ TEE_Result _utee_hash_init(unsigned long state, const void *iv, size_t iv_len); TEE_Result _utee_hash_update(unsigned long state, const void *chunk, size_t chunk_size); TEE_Result _utee_hash_final(unsigned long state, const void *chunk, size_t chunk_size, void *hash, uint64_t *hash_len); TEE_Result _utee_cipher_init(unsigned long state, const void *iv, size_t iv_len); TEE_Result _utee_cipher_update(unsigned long state, const void *src, size_t src_len, void *dest, uint64_t *dest_len); TEE_Result _utee_cipher_final(unsigned long state, const void *src, size_t src_len, void *dest, uint64_t *dest_len); /* Generic Object Functions */ TEE_Result _utee_cryp_obj_get_info(unsigned long obj, struct utee_object_info *info); TEE_Result _utee_cryp_obj_restrict_usage(unsigned long obj, unsigned long usage); TEE_Result _utee_cryp_obj_get_attr(unsigned long obj, unsigned long attr_id, void *buffer, uint64_t *size); /* Transient Object Functions */ /* type has type TEE_ObjectType */ TEE_Result _utee_cryp_obj_alloc(unsigned long type, unsigned long max_size, uint32_t *obj); TEE_Result _utee_cryp_obj_close(unsigned long obj); TEE_Result _utee_cryp_obj_reset(unsigned long obj); TEE_Result _utee_cryp_obj_populate(unsigned long obj, struct utee_attribute *attrs, unsigned long attr_count); TEE_Result _utee_cryp_obj_copy(unsigned long dst_obj, unsigned long src_obj); TEE_Result _utee_cryp_obj_generate_key(unsigned long obj, unsigned long key_size, const struct utee_attribute *params, unsigned long param_count); TEE_Result _utee_cryp_derive_key(unsigned long state, const struct utee_attribute *params, unsigned long param_count, unsigned long derived_key); TEE_Result _utee_cryp_random_number_generate(void *buf, size_t blen); TEE_Result _utee_authenc_init(unsigned long state, const void *nonce, size_t nonce_len, size_t tag_len, size_t aad_len, size_t payload_len); TEE_Result _utee_authenc_update_aad(unsigned long state, const void *aad_data, size_t aad_data_len); TEE_Result _utee_authenc_update_payload(unsigned long state, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len); TEE_Result _utee_authenc_enc_final(unsigned long state, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len, void *tag, uint64_t *tag_len); TEE_Result _utee_authenc_dec_final(unsigned long state, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len, const void *tag, size_t tag_len); TEE_Result _utee_asymm_operate(unsigned long state, const struct utee_attribute *params, unsigned long num_params, const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len); TEE_Result _utee_asymm_verify(unsigned long state, const struct utee_attribute *params, unsigned long num_params, const void *data, size_t data_len, const void *sig, size_t sig_len); /* Persistant Object Functions */ /* obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_open(unsigned long storage_id, const void *object_id, size_t object_id_len, unsigned long flags, uint32_t *obj); /* * attr is of type TEE_ObjectHandle * obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_create(unsigned long storage_id, const void *object_id, size_t object_id_len, unsigned long flags, unsigned long attr, const void *data, size_t len, uint32_t *obj); /* obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_del(unsigned long obj); /* obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_rename(unsigned long obj, const void *new_obj_id, size_t new_obj_id_len); /* Persistent Object Enumeration Functions */ /* obj_enum is of type TEE_ObjectEnumHandle */ TEE_Result _utee_storage_alloc_enum(uint32_t *obj_enum); /* obj_enum is of type TEE_ObjectEnumHandle */ TEE_Result _utee_storage_free_enum(unsigned long obj_enum); /* obj_enum is of type TEE_ObjectEnumHandle */ TEE_Result _utee_storage_reset_enum(unsigned long obj_enum); /* obj_enum is of type TEE_ObjectEnumHandle */ TEE_Result _utee_storage_start_enum(unsigned long obj_enum, unsigned long storage_id); /* obj_enum is of type TEE_ObjectEnumHandle */ TEE_Result _utee_storage_next_enum(unsigned long obj_enum, struct utee_object_info *info, void *obj_id, uint64_t *len); /* Data Stream Access Functions */ /* obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_read(unsigned long obj, void *data, size_t len, uint64_t *count); /* obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_write(unsigned long obj, const void *data, size_t len); /* obj is of type TEE_ObjectHandle */ TEE_Result _utee_storage_obj_trunc(unsigned long obj, size_t len); /* obj is of type TEE_ObjectHandle */ /* whence is of type TEE_Whence */ TEE_Result _utee_storage_obj_seek(unsigned long obj, int32_t offset, unsigned long whence); /* op is of type enum _utee_cache_operation */ TEE_Result _utee_cache_operation(void *va, size_t l, unsigned long op); TEE_Result _utee_gprof_send(void *buf, size_t size, uint32_t *id); #endif /* UTEE_SYSCALLS_H */ optee_os-4.3.0/lib/libutee/include/utee_syscalls_asm.S000066400000000000000000000103721464416617300230370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited * Copyright (c) 2014, STMicroelectronics International N.V. */ UTEE_SYSCALL _utee_return, TEE_SCN_RETURN, 1 UTEE_SYSCALL _utee_log, TEE_SCN_LOG, 2 UTEE_SYSCALL __utee_panic, TEE_SCN_PANIC, 2 UTEE_SYSCALL _utee_get_property, TEE_SCN_GET_PROPERTY, 7 UTEE_SYSCALL _utee_get_property_name_to_index, \ TEE_SCN_GET_PROPERTY_NAME_TO_INDEX, 4 UTEE_SYSCALL _utee_open_ta_session, TEE_SCN_OPEN_TA_SESSION, 5 UTEE_SYSCALL _utee_close_ta_session, TEE_SCN_CLOSE_TA_SESSION, 1 UTEE_SYSCALL _utee_invoke_ta_command, TEE_SCN_INVOKE_TA_COMMAND, 5 UTEE_SYSCALL _utee_get_cancellation_flag, \ TEE_SCN_GET_CANCELLATION_FLAG, 1 UTEE_SYSCALL _utee_check_access_rights, TEE_SCN_CHECK_ACCESS_RIGHTS, 3 UTEE_SYSCALL _utee_unmask_cancellation, TEE_SCN_UNMASK_CANCELLATION, 1 UTEE_SYSCALL _utee_mask_cancellation, TEE_SCN_MASK_CANCELLATION, 1 UTEE_SYSCALL _utee_wait, TEE_SCN_WAIT, 1 UTEE_SYSCALL _utee_get_time, TEE_SCN_GET_TIME, 2 UTEE_SYSCALL _utee_set_ta_time, TEE_SCN_SET_TA_TIME, 1 UTEE_SYSCALL _utee_cryp_state_alloc, TEE_SCN_CRYP_STATE_ALLOC, 5 UTEE_SYSCALL _utee_cryp_state_copy, TEE_SCN_CRYP_STATE_COPY, 2 UTEE_SYSCALL _utee_cryp_state_free, TEE_SCN_CRYP_STATE_FREE, 1 UTEE_SYSCALL _utee_hash_init, TEE_SCN_HASH_INIT, 3 UTEE_SYSCALL _utee_hash_update, TEE_SCN_HASH_UPDATE, 3 UTEE_SYSCALL _utee_hash_final, TEE_SCN_HASH_FINAL, 5 UTEE_SYSCALL _utee_cipher_init, TEE_SCN_CIPHER_INIT, 3 UTEE_SYSCALL _utee_cipher_update, TEE_SCN_CIPHER_UPDATE, 5 UTEE_SYSCALL _utee_cipher_final, TEE_SCN_CIPHER_FINAL, 5 UTEE_SYSCALL _utee_cryp_obj_get_info, TEE_SCN_CRYP_OBJ_GET_INFO, 2 UTEE_SYSCALL _utee_cryp_obj_restrict_usage, \ TEE_SCN_CRYP_OBJ_RESTRICT_USAGE, 2 UTEE_SYSCALL _utee_cryp_obj_get_attr, TEE_SCN_CRYP_OBJ_GET_ATTR, 4 UTEE_SYSCALL _utee_cryp_obj_alloc, TEE_SCN_CRYP_OBJ_ALLOC, 3 UTEE_SYSCALL _utee_cryp_obj_close, TEE_SCN_CRYP_OBJ_CLOSE, 1 UTEE_SYSCALL _utee_cryp_obj_reset, TEE_SCN_CRYP_OBJ_RESET, 1 UTEE_SYSCALL _utee_cryp_obj_populate, TEE_SCN_CRYP_OBJ_POPULATE, 3 UTEE_SYSCALL _utee_cryp_obj_copy, TEE_SCN_CRYP_OBJ_COPY, 2 UTEE_SYSCALL _utee_cryp_derive_key, TEE_SCN_CRYP_DERIVE_KEY, 4 UTEE_SYSCALL _utee_cryp_random_number_generate, \ TEE_SCN_CRYP_RANDOM_NUMBER_GENERATE, 2 UTEE_SYSCALL _utee_authenc_init, TEE_SCN_AUTHENC_INIT, 6 UTEE_SYSCALL _utee_authenc_update_aad, TEE_SCN_AUTHENC_UPDATE_AAD, 3 UTEE_SYSCALL _utee_authenc_update_payload, \ TEE_SCN_AUTHENC_UPDATE_PAYLOAD, 5 UTEE_SYSCALL _utee_authenc_enc_final, TEE_SCN_AUTHENC_ENC_FINAL, 7 UTEE_SYSCALL _utee_authenc_dec_final, TEE_SCN_AUTHENC_DEC_FINAL, 7 UTEE_SYSCALL _utee_asymm_operate, TEE_SCN_ASYMM_OPERATE, 7 UTEE_SYSCALL _utee_asymm_verify, TEE_SCN_ASYMM_VERIFY, 7 UTEE_SYSCALL _utee_storage_obj_open, TEE_SCN_STORAGE_OBJ_OPEN, 5 UTEE_SYSCALL _utee_storage_obj_create, TEE_SCN_STORAGE_OBJ_CREATE, 8 UTEE_SYSCALL _utee_storage_obj_del, TEE_SCN_STORAGE_OBJ_DEL, 1 UTEE_SYSCALL _utee_storage_obj_rename, TEE_SCN_STORAGE_OBJ_RENAME, 3 UTEE_SYSCALL _utee_storage_alloc_enum, TEE_SCN_STORAGE_ENUM_ALLOC, 1 UTEE_SYSCALL _utee_storage_free_enum, TEE_SCN_STORAGE_ENUM_FREE, 1 UTEE_SYSCALL _utee_storage_reset_enum, TEE_SCN_STORAGE_ENUM_RESET, 1 UTEE_SYSCALL _utee_storage_start_enum, TEE_SCN_STORAGE_ENUM_START, 2 UTEE_SYSCALL _utee_storage_next_enum, TEE_SCN_STORAGE_ENUM_NEXT, 4 UTEE_SYSCALL _utee_storage_obj_read, TEE_SCN_STORAGE_OBJ_READ, 4 UTEE_SYSCALL _utee_storage_obj_write, TEE_SCN_STORAGE_OBJ_WRITE, 3 UTEE_SYSCALL _utee_storage_obj_trunc, TEE_SCN_STORAGE_OBJ_TRUNC, 2 UTEE_SYSCALL _utee_storage_obj_seek, TEE_SCN_STORAGE_OBJ_SEEK, 3 UTEE_SYSCALL _utee_cryp_obj_generate_key, \ TEE_SCN_CRYP_OBJ_GENERATE_KEY, 4 UTEE_SYSCALL _utee_cache_operation, TEE_SCN_CACHE_OPERATION, 3 optee_os-4.3.0/lib/libutee/include/utee_types.h000066400000000000000000000032611464416617300215320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef UTEE_TYPES_H #define UTEE_TYPES_H #include #include enum utee_time_category { UTEE_TIME_CAT_SYSTEM = 0, UTEE_TIME_CAT_TA_PERSISTENT, UTEE_TIME_CAT_REE }; enum utee_entry_func { UTEE_ENTRY_FUNC_OPEN_SESSION = 0, UTEE_ENTRY_FUNC_CLOSE_SESSION, UTEE_ENTRY_FUNC_INVOKE_COMMAND, /* * UTEE_ENTRY_FUNC_DUMP_MEMSTATS * [out] value[0].a Byte size currently allocated * [out] value[0].b Max bytes allocated since stats reset * [out] value[1].a Pool byte size * [out] value[1].b Number of failed allocation requests * [out] value[2].a Biggest byte size which allocation failed * [out] value[2].b Biggest byte size which allocation succeeded */ UTEE_ENTRY_FUNC_DUMP_MEMSTATS, }; /* * Cache operation types. * Used when extensions TEE_CacheClean() / TEE_CacheFlush() / * TEE_CacheInvalidate() are used */ enum utee_cache_operation { TEE_CACHECLEAN = 0, TEE_CACHEFLUSH, TEE_CACHEINVALIDATE, }; struct utee_params { uint64_t types; /* vals[n * 2] corresponds to either value.a or memref.buffer * vals[n * 2 + ] corresponds to either value.b or memref.size * when converting to/from struct tee_ta_param */ uint64_t vals[TEE_NUM_PARAMS * 2]; }; struct utee_attribute { uint64_t a; /* also serves as a pointer for references */ uint64_t b; /* also serves as a length for references */ uint32_t attribute_id; }; struct utee_object_info { uint32_t obj_type; uint32_t obj_size; uint32_t max_obj_size; uint32_t obj_usage; uint32_t data_size; uint32_t data_pos; uint32_t handle_flags; }; #endif /* UTEE_TYPES_H */ optee_os-4.3.0/lib/libutee/sub.mk000066400000000000000000000011301464416617300166630ustar00rootroot00000000000000global-incdirs-y += include srcs-y += abort.c srcs-y += assert.c srcs-y += tee_uuid_from_str.c srcs-y += trace_ext.c ifneq ($(sm),ldelf) srcs-y += base64.c srcs-y += tee_api.c srcs-y += tee_api_arith_mpi.c cppflags-tee_api_arith_mpi.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS srcs-y += tee_api_objects.c srcs-y += tee_api_operations.c srcs-y += tee_api_panic.c srcs-y += tee_api_property.c srcs-y += tee_socket_pta.c srcs-y += tee_system_pta.c srcs-y += tee_tcpudp_socket.c srcs-y += tcb.c srcs-y += user_ta_entry.c srcs-y += user_ta_entry_compat.c endif #ifneq ($(sm),ldelf) subdirs-y += arch/$(ARCH) optee_os-4.3.0/lib/libutee/tcb.c000066400000000000000000000137171464416617300164730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ /* * Support for Thread-Local Storage (TLS) ABIs for ARMv7/Aarch32 and Aarch64. * * TAs are currently single-threaded, so the only benefit of implementing these * ABIs is to support toolchains that need them even when the target program is * single-threaded. Such as, the g++ compiler from the GCC toolchain targeting a * "Posix thread" Linux runtime, which OP-TEE has been using for quite some time * (arm-linux-gnueabihf-* and aarch64-linux-gnu-*). This allows building C++ TAs * without having to build a specific toolchain with --disable-threads. * * This implementation is based on [1]. * * - "TLS data structures variant 1" (section 3): the AArch64 compiler uses the * TPIDR_EL0 to access TLS data directly. This assumes a specific layout for * the TCB, and (for shared objects) the use of R_AARCH64_TLS_TPREL * relocations. * - The "General Dynamic access model" (section 4.1): the ARMv7/Aarch32 * compiler inserts calls to the __tls_get_addr() function which has to be * implemented by the runtime library. The function takes a module ID and an * offset parameter, which are provided thanks to R_ARM_TLS_DTPMOD32 and * R_ARM_TLS_DTPOFF32 relocations. * * In addition, dl_iterate_phdr() is implemented here, because it is used by the * g++ Aarch64 exception handling and it does use the TCB to provide TLS * information to the caller. * * [1] "ELF Handling For Thread-Local Storage" * https://www.akkadia.org/drepper/tls.pdf */ #include #include #include #include #include #include #include "user_ta_header.h" /* DTV - Dynamic Thread Vector * * Maintains an array of pointers to TLS data for each module in the TCB. Each * module that has a TLS segment has an entry (and consequently, some space in * the tcb_head::tls buffer). The index is the "module ID". * dtv[0].size is the number of elements in the vector * dtv[1].tls points to TLS for the main executable (may be NULL) * tls[2 .. (size-1)] are for shared libraries */ union dtv { unsigned long size; uint8_t *tls; }; #define DTV_SIZE(size) (sizeof(union dtv) + (size)) /* Thread Control Block */ struct tcb_head { /* Two words are reserved as per the "TLS variant 1" ABI */ union dtv *dtv; unsigned long reserved; /* * The rest of the structure contains the TLS blocks for each ELF module * having a PT_TLS segment. Each block is a copy of the .tdata section * plus some zero-initialized space for .tbss. */ uint8_t tls[]; }; /* * Since TAs are single threaded, only one TCB is needed. This would need to * change if multi-threading is introduced. */ static struct tcb_head *_tcb; static size_t _tls_size; #define TCB_SIZE(tls_size) (sizeof(*_tcb) + (tls_size)) /* * Initialize or update the TCB. * Called on application initialization and when additional shared objects are * loaded via dlopen(). */ void __utee_tcb_init(void) { struct dl_phdr_info *dlpi = NULL; const Elf_Phdr *phdr = NULL; size_t total_size = 0; size_t size = 0; size_t i = 0; size_t j = 0; /* Compute the size needed for all the TLS blocks */ for (i = 0; i < __elf_phdr_info.count; i++) { dlpi = __elf_phdr_info.dlpi + i; for (j = 0; j < dlpi->dlpi_phnum; j++) { phdr = dlpi->dlpi_phdr + j; if (phdr->p_type == PT_TLS) { total_size += phdr->p_memsz; break; } } } /* ELF modules currently cannot be unmapped */ assert(total_size >= _tls_size); if (total_size == _tls_size) return; /* (Re-)allocate the TCB */ _tcb = realloc(_tcb, TCB_SIZE(total_size)); if (!_tcb) { EMSG("TCB allocation failed (%zu bytes)", TCB_SIZE(total_size)); abort(); } /* (Re-)allocate the DTV. + 1 since dtv[0] holds the size */ size = DTV_SIZE((__elf_phdr_info.count + 1) * sizeof(union dtv)); _tcb->dtv = realloc(_tcb->dtv, size); if (!_tcb->dtv) { EMSG("DTV allocation failed (%zu bytes)", size); abort(); } /* Copy TLS data to the TCB */ size = 0; for (i = 0; i < __elf_phdr_info.count; i++) { dlpi = __elf_phdr_info.dlpi + i; for (j = 0; j < dlpi->dlpi_phnum; j++) { phdr = dlpi->dlpi_phdr + j; if (phdr->p_type != PT_TLS) continue; if (size + phdr->p_memsz <= _tls_size) { /* Already copied */ break; } _tcb->dtv[i + 1].tls = _tcb->tls + size; /* Copy .tdata */ memcpy(_tcb->tls + size, (void *)(dlpi->dlpi_addr + phdr->p_vaddr), phdr->p_filesz); /* Initialize .tbss */ memset(_tcb->tls + size + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); size += phdr->p_memsz; } } _tcb->dtv[0].size = i; _tls_size = total_size; #ifdef ARM64 /* * Aarch64 ABI requirement: the thread pointer shall point to the * thread's TCB. ARMv7 and Aarch32 access the TCB via _tls_get_addr(). */ write_tpidr_el0((vaddr_t)_tcb); #endif } struct tls_index { unsigned long module; unsigned long offset; }; void *__tls_get_addr(struct tls_index *ti); void *__tls_get_addr(struct tls_index *ti) { return _tcb->dtv[ti->module].tls + ti->offset; } int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data) { struct dl_phdr_info *dlpi = NULL; size_t id = 0; size_t i = 0; int st = 0; /* * dlpi_tls_data is thread-specific so if we were to support * multi-threading, we would need one copy of struct dl_phdr_info per * thread. Could be a pre-allocated area, or could be allocated on the * heap. Doing the latter here so that it would at least work if/when we * add thread support. Further optimization can always come later. */ dlpi = calloc(1, sizeof(*dlpi)); if (!dlpi) { EMSG("dl_phdr_info allocation failed"); abort(); } for (i = 0; i < __elf_phdr_info.count; i++) { memcpy(dlpi, __elf_phdr_info.dlpi + i, sizeof(*dlpi)); dlpi->dlpi_tls_data = NULL; id = dlpi->dlpi_tls_modid; if (id) dlpi->dlpi_tls_data = _tcb->dtv[id].tls; st = callback(dlpi, sizeof(*dlpi), data); } free(dlpi); return st; } optee_os-4.3.0/lib/libutee/tee_api.c000066400000000000000000000452311464416617300173250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include "tee_api_private.h" /* * return a known non-NULL invalid pointer when the * requested size is zero */ #define TEE_NULL_SIZED_VA ((void *)1) #define TEE_NULL_SIZED_NO_SHARE_VA ((void *)2) /* * Workaround build error in Teaclave TrustZone SDK * * These are supposed to be provided by ta/arch/arm/user_ta_header.c, but * Teaclave TrustZone SDK seems to roll their own in Rust. */ uint8_t __ta_no_share_heap[0] __weak; const size_t __ta_no_share_heap_size __weak; struct malloc_ctx *__ta_no_share_malloc_ctx __weak; static const void *tee_api_instance_data; /* System API - Internal Client API */ static void copy_param(struct utee_params *up, uint32_t param_types, const TEE_Param params[TEE_NUM_PARAMS]) { size_t n = 0; uint64_t a = 0; uint64_t b = 0; up->types = param_types; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(up->types, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_INOUT: a = params[n].value.a; b = params[n].value.b; break; case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: case TEE_PARAM_TYPE_MEMREF_INPUT: a = (vaddr_t)params[n].memref.buffer; b = params[n].memref.size; break; default: a = 0; b = 0; } up->vals[n * 2] = a; up->vals[n * 2 + 1] = b; } } static void copy_gp11_param(struct utee_params *up, uint32_t param_types, const __GP11_TEE_Param params[TEE_NUM_PARAMS]) { size_t n = 0; uint64_t a = 0; uint64_t b = 0; up->types = param_types; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(up->types, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_INOUT: a = params[n].value.a; b = params[n].value.b; break; case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: case TEE_PARAM_TYPE_MEMREF_INPUT: a = (vaddr_t)params[n].memref.buffer; b = params[n].memref.size; break; default: a = 0; b = 0; } up->vals[n * 2] = a; up->vals[n * 2 + 1] = b; } } static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf, size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS]) { size_t n = 0; uint8_t *tb = NULL; size_t tbl = 0; size_t tmp_align = sizeof(vaddr_t) * 2; bool is_tmp_mem[TEE_NUM_PARAMS] = { false }; void *b = NULL; size_t s = 0; const uint32_t flags = TEE_MEMORY_ACCESS_READ; /* * If a memory parameter points to TA private memory we need to * allocate a temporary buffer to avoid exposing the memory * directly to the called TA. */ *tmp_buf = NULL; *tmp_len = 0; for (n = 0; n < TEE_NUM_PARAMS; n++) { tmp_va[n] = NULL; switch (TEE_PARAM_TYPE_GET(up->types, n)) { case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: b = (void *)(vaddr_t)up->vals[n * 2]; s = up->vals[n * 2 + 1]; /* * We're only allocating temporary memory if the * buffer is completely within TA memory. If it's * NULL, empty, partially outside or completely * outside TA memory there's nothing more we need * to do here. If there's security/permissions * problem we'll get an error in the * invoke_command/open_session below. */ if (b && s && !TEE_CheckMemoryAccessRights(flags, b, s)) { is_tmp_mem[n] = true; tbl += ROUNDUP(s, tmp_align); } break; default: break; } } if (tbl) { tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER); if (!tb) return TEE_ERROR_OUT_OF_MEMORY; *tmp_buf = tb; *tmp_len = tbl; } for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(up->types, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: case TEE_PARAM_TYPE_MEMREF_INPUT: if (!is_tmp_mem[n]) break; s = up->vals[n * 2 + 1]; b = (void *)(vaddr_t)up->vals[n * 2]; tmp_va[n] = tb; tb += ROUNDUP(s, tmp_align); up->vals[n * 2] = (vaddr_t)tmp_va[n]; if (TEE_PARAM_TYPE_GET(up->types, n) != TEE_PARAM_TYPE_MEMREF_OUTPUT) memcpy(tmp_va[n], b, s); break; default: break; } } return TEE_SUCCESS; } static void update_out_param(TEE_Param params[TEE_NUM_PARAMS], void *tmp_va[TEE_NUM_PARAMS], const struct utee_params *up) { size_t n; uint32_t types = up->types; for (n = 0; n < TEE_NUM_PARAMS; n++) { uintptr_t a = up->vals[n * 2]; uintptr_t b = up->vals[n * 2 + 1]; switch (TEE_PARAM_TYPE_GET(types, n)) { case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: params[n].value.a = a; params[n].value.b = b; break; case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: if (tmp_va[n]) memcpy(params[n].memref.buffer, tmp_va[n], MIN(b, params[n].memref.size)); params[n].memref.size = b; break; default: break; } } } static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS], void *tmp_va[TEE_NUM_PARAMS], const struct utee_params *up) { size_t n = 0; uint32_t types = up->types; for (n = 0; n < TEE_NUM_PARAMS; n++) { uintptr_t a = up->vals[n * 2]; uintptr_t b = up->vals[n * 2 + 1]; switch (TEE_PARAM_TYPE_GET(types, n)) { case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: params[n].value.a = a; params[n].value.b = b; break; case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: if (tmp_va[n]) memcpy(params[n].memref.buffer, tmp_va[n], MIN(b, params[n].memref.size)); params[n].memref.size = b; break; default: break; } } } static bool bufs_intersect(void *buf1, size_t sz1, void *buf2, size_t sz2) { vaddr_t b1 = (vaddr_t)buf1; vaddr_t b2 = (vaddr_t)buf2; vaddr_t e1 = b1 + sz1 - 1; vaddr_t e2 = b2 + sz2 - 1; if (!sz1 || !sz2) return false; if (e1 < b2 || e2 < b1) return false; return true; } static TEE_Result check_mem_access_rights_params(uint32_t flags, void *buf, size_t len) { size_t n = 0; for (n = 0; n < TEE_NUM_PARAMS; n++) { uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; switch (TEE_PARAM_TYPE_GET(ta_param_types, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: f |= TEE_MEMORY_ACCESS_WRITE; fallthrough; case TEE_PARAM_TYPE_MEMREF_INPUT: f |= TEE_MEMORY_ACCESS_READ; if (bufs_intersect(buf, len, ta_params[n].memref.buffer, ta_params[n].memref.size)) { if ((flags & f) != flags) return TEE_ERROR_ACCESS_DENIED; } break; default: break; } } return TEE_SUCCESS; } static bool buf_overlaps_no_share_heap(void *buf, size_t size) { struct malloc_ctx *ctx = __ta_no_share_malloc_ctx; return ctx && raw_malloc_buffer_overlaps_heap(ctx, buf, size); } static void check_invoke_param(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { size_t n = 0; for (n = 0; n < TEE_NUM_PARAMS; n++) { uint32_t f = TEE_MEMORY_ACCESS_ANY_OWNER; void *buf = params[n].memref.buffer; size_t size = params[n].memref.size; switch (TEE_PARAM_TYPE_GET(pt, n)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: f |= TEE_MEMORY_ACCESS_WRITE; fallthrough; case TEE_PARAM_TYPE_MEMREF_INPUT: f |= TEE_MEMORY_ACCESS_READ; if (check_mem_access_rights_params(f, buf, size)) TEE_Panic(0); if (buf_overlaps_no_share_heap(buf, size)) TEE_Panic(0); break; default: break; } } } TEE_Result TEE_OpenTASession(const TEE_UUID *destination, uint32_t cancellationRequestTimeout, uint32_t paramTypes, TEE_Param params[TEE_NUM_PARAMS], TEE_TASessionHandle *session, uint32_t *returnOrigin) { TEE_Result res = TEE_SUCCESS; struct utee_params up = { }; uint32_t s = 0; void *tmp_buf = NULL; size_t tmp_len = 0; void *tmp_va[TEE_NUM_PARAMS] = { NULL }; if (paramTypes) { __utee_check_inout_annotation(params, sizeof(TEE_Param) * TEE_NUM_PARAMS); check_invoke_param(paramTypes, params); } __utee_check_out_annotation(session, sizeof(*session)); copy_param(&up, paramTypes, params); res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); if (res) goto out; res = _utee_open_ta_session(destination, cancellationRequestTimeout, &up, &s, returnOrigin); update_out_param(params, tmp_va, &up); if (tmp_buf) { TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); if (res2) TEE_Panic(res2); } out: /* * Specification says that *session must hold TEE_HANDLE_NULL is * TEE_SUCCESS isn't returned. Set it here explicitly in case * the syscall fails before out parameters has been updated. */ if (res != TEE_SUCCESS) s = TEE_HANDLE_NULL; *session = (TEE_TASessionHandle)(uintptr_t)s; return res; } TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination, uint32_t cancellationRequestTimeout, uint32_t paramTypes, __GP11_TEE_Param params[TEE_NUM_PARAMS], TEE_TASessionHandle *session, uint32_t *returnOrigin) { TEE_Result res = TEE_SUCCESS; struct utee_params up = { }; uint32_t s = 0; void *tmp_buf = NULL; size_t tmp_len = 0; void *tmp_va[TEE_NUM_PARAMS] = { NULL }; if (paramTypes) __utee_check_inout_annotation(params, sizeof(__GP11_TEE_Param) * TEE_NUM_PARAMS); __utee_check_out_annotation(session, sizeof(*session)); copy_gp11_param(&up, paramTypes, params); res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); if (res) goto out; res = _utee_open_ta_session(destination, cancellationRequestTimeout, &up, &s, returnOrigin); update_out_gp11_param(params, tmp_va, &up); if (tmp_buf) { TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); if (res2) TEE_Panic(res2); } out: /* * Specification says that *session must hold TEE_HANDLE_NULL if * TEE_SUCCESS isn't returned. Set it here explicitly in case * the syscall fails before out parameters has been updated. */ if (res != TEE_SUCCESS) s = TEE_HANDLE_NULL; *session = (TEE_TASessionHandle)(uintptr_t)s; return res; } void TEE_CloseTASession(TEE_TASessionHandle session) { if (session != TEE_HANDLE_NULL) { TEE_Result res = _utee_close_ta_session((uintptr_t)session); if (res != TEE_SUCCESS) TEE_Panic(res); } } TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session, uint32_t cancellationRequestTimeout, uint32_t commandID, uint32_t paramTypes, TEE_Param params[TEE_NUM_PARAMS], uint32_t *returnOrigin) { TEE_Result res = TEE_SUCCESS; uint32_t ret_origin = TEE_ORIGIN_TEE; struct utee_params up = { }; void *tmp_buf = NULL; size_t tmp_len = 0; void *tmp_va[TEE_NUM_PARAMS] = { NULL }; if (paramTypes) { __utee_check_inout_annotation(params, sizeof(TEE_Param) * TEE_NUM_PARAMS); check_invoke_param(paramTypes, params); } if (returnOrigin) __utee_check_out_annotation(returnOrigin, sizeof(*returnOrigin)); copy_param(&up, paramTypes, params); res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); if (res) goto out; res = _utee_invoke_ta_command((uintptr_t)session, cancellationRequestTimeout, commandID, &up, &ret_origin); update_out_param(params, tmp_va, &up); if (tmp_buf) { TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); if (res2) TEE_Panic(res2); } out: if (returnOrigin != NULL) *returnOrigin = ret_origin; if (ret_origin == TEE_ORIGIN_TRUSTED_APP) return res; if (res != TEE_SUCCESS && res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_TARGET_DEAD) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session, uint32_t cancellationRequestTimeout, uint32_t commandID, uint32_t paramTypes, __GP11_TEE_Param params[TEE_NUM_PARAMS], uint32_t *returnOrigin) { TEE_Result res = TEE_SUCCESS; uint32_t ret_origin = TEE_ORIGIN_TEE; struct utee_params up = { }; void *tmp_buf = NULL; size_t tmp_len = 0; void *tmp_va[TEE_NUM_PARAMS] = { NULL }; if (paramTypes) __utee_check_inout_annotation(params, sizeof(__GP11_TEE_Param) * TEE_NUM_PARAMS); if (returnOrigin) __utee_check_out_annotation(returnOrigin, sizeof(*returnOrigin)); copy_gp11_param(&up, paramTypes, params); res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va); if (res) goto out; res = _utee_invoke_ta_command((uintptr_t)session, cancellationRequestTimeout, commandID, &up, &ret_origin); update_out_gp11_param(params, tmp_va, &up); if (tmp_buf) { TEE_Result res2 = tee_unmap(tmp_buf, tmp_len); if (res2) TEE_Panic(res2); } out: if (returnOrigin) *returnOrigin = ret_origin; if (ret_origin == TEE_ORIGIN_TRUSTED_APP) return res; if (res != TEE_SUCCESS && res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_TARGET_DEAD) TEE_Panic(res); return res; } /* System API - Cancellations */ bool TEE_GetCancellationFlag(void) { uint32_t c; TEE_Result res = _utee_get_cancellation_flag(&c); if (res != TEE_SUCCESS) c = 0; return !!c; } bool TEE_UnmaskCancellation(void) { uint32_t old_mask; TEE_Result res = _utee_unmask_cancellation(&old_mask); if (res != TEE_SUCCESS) TEE_Panic(res); return !!old_mask; } bool TEE_MaskCancellation(void) { uint32_t old_mask; TEE_Result res = _utee_mask_cancellation(&old_mask); if (res != TEE_SUCCESS) TEE_Panic(res); return !!old_mask; } /* System API - Memory Management */ TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, size_t size) { uint32_t flags = accessFlags; if (!size) return TEE_SUCCESS; /* * Check access rights against memory mapping. If this check is * OK the size can't cause an overflow when added with buffer. */ if (_utee_check_access_rights(accessFlags, buffer, size)) return TEE_ERROR_ACCESS_DENIED; /* * Check access rights against input parameters. * * Clear eventual extension flags like TEE_MEMORY_ACCESS_NONSECURE * and TEE_MEMORY_ACCESS_SECURE. */ flags &= TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; if (check_mem_access_rights_params(flags, buffer, size)) return TEE_ERROR_ACCESS_DENIED; if (malloc_buffer_overlaps_heap(buffer, size) && !malloc_buffer_is_within_alloced(buffer, size)) return TEE_ERROR_ACCESS_DENIED; return TEE_SUCCESS; } TEE_Result __GP11_TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer, uint32_t size) { return TEE_CheckMemoryAccessRights(accessFlags, buffer, size); } void TEE_SetInstanceData(const void *instanceData) { tee_api_instance_data = instanceData; } const void *TEE_GetInstanceData(void) { return tee_api_instance_data; } void *TEE_MemMove(void *dest, const void *src, size_t size) { return memmove(dest, src, size); } void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size) { return TEE_MemMove(dest, src, size); } int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size) { return consttime_memcmp(buffer1, buffer2, size); } int32_t __GP11_TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size) { return TEE_MemCompare(buffer1, buffer2, size); } void TEE_MemFill(void *buff, uint32_t x, size_t size) { memset(buff, x, size); } void __GP11_TEE_MemFill(void *buff, uint32_t x, uint32_t size) { TEE_MemFill(buff, x, size); } /* Date & Time API */ void TEE_GetSystemTime(TEE_Time *time) { TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time); if (res != TEE_SUCCESS) TEE_Panic(res); } TEE_Result TEE_Wait(uint32_t timeout) { TEE_Result res = _utee_wait(timeout); if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL) TEE_Panic(res); return res; } TEE_Result TEE_GetTAPersistentTime(TEE_Time *time) { TEE_Result res; res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time); if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) { time->seconds = 0; time->millis = 0; } if (res != TEE_SUCCESS && res != TEE_ERROR_TIME_NOT_SET && res != TEE_ERROR_TIME_NEEDS_RESET && res != TEE_ERROR_OVERFLOW && res != TEE_ERROR_OUT_OF_MEMORY) TEE_Panic(res); return res; } TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time) { TEE_Result res; res = _utee_set_ta_time(time); if (res != TEE_SUCCESS && res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_STORAGE_NO_SPACE) TEE_Panic(res); return res; } void TEE_GetREETime(TEE_Time *time) { TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time); if (res != TEE_SUCCESS) TEE_Panic(res); } void *TEE_Malloc(size_t len, uint32_t hint) { switch (hint) { case TEE_MALLOC_FILL_ZERO: if (!len) return TEE_NULL_SIZED_VA; return calloc(1, len); case TEE_MALLOC_NO_FILL: TEE_Panic(0); break; case TEE_MALLOC_NO_SHARE: if (!len) return TEE_NULL_SIZED_NO_SHARE_VA; if (!__ta_no_share_malloc_ctx) return NULL; return raw_calloc(0, 0, 1, len, __ta_no_share_malloc_ctx); case TEE_MALLOC_NO_FILL | TEE_MALLOC_NO_SHARE: if (!len) return TEE_NULL_SIZED_NO_SHARE_VA; if (!__ta_no_share_malloc_ctx) return NULL; return raw_malloc(0, 0, len, __ta_no_share_malloc_ctx); case TEE_USER_MEM_HINT_NO_FILL_ZERO: if (!len) return TEE_NULL_SIZED_VA; return malloc(len); default: break; } EMSG("Invalid hint %#" PRIx32, hint); return NULL; } void *__GP11_TEE_Malloc(uint32_t size, uint32_t hint) { return TEE_Malloc(size, hint); } static bool addr_is_in_no_share_heap(void *p) { return buf_overlaps_no_share_heap(p, 1); } void *TEE_Realloc(void *buffer, size_t newSize) { if (!newSize) { void *ret = NULL; if (addr_is_in_no_share_heap(buffer)) ret = TEE_NULL_SIZED_NO_SHARE_VA; else ret = TEE_NULL_SIZED_VA; TEE_Free(buffer); return ret; } if (buffer == TEE_NULL_SIZED_VA) return calloc(1, newSize); if (buffer == TEE_NULL_SIZED_NO_SHARE_VA) { if (!__ta_no_share_malloc_ctx) return NULL; return raw_calloc(0, 0, 1, newSize, __ta_no_share_malloc_ctx); } if (addr_is_in_no_share_heap(buffer)) return raw_realloc(buffer, 0, 0, newSize, __ta_no_share_malloc_ctx); else return realloc(buffer, newSize); } void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize) { return TEE_Realloc(buffer, newSize); } void TEE_Free(void *buffer) { if (buffer != TEE_NULL_SIZED_VA && buffer != TEE_NULL_SIZED_NO_SHARE_VA) { if (addr_is_in_no_share_heap(buffer)) raw_free(buffer, __ta_no_share_malloc_ctx, false); else free(buffer); } } /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */ TEE_Result TEE_CacheClean(char *buf, size_t len) { return _utee_cache_operation(buf, len, TEE_CACHECLEAN); } TEE_Result TEE_CacheFlush(char *buf, size_t len) { return _utee_cache_operation(buf, len, TEE_CACHEFLUSH); } TEE_Result TEE_CacheInvalidate(char *buf, size_t len) { return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE); } optee_os-4.3.0/lib/libutee/tee_api_arith_mpi.c000066400000000000000000000547201464416617300213640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro limited */ #include #include #include #include #include #include #include #include #include #include #define MPI_MEMPOOL_SIZE (14 * 1024) static void __noreturn api_panic(const char *func, int line, const char *msg) { printf("Panic function %s, line %d: %s\n", func, line, msg); TEE_Panic(0xB16127 /*BIGINT*/); while (1) ; /* Panic will crash the thread */ } #define API_PANIC(x) api_panic(__func__, __LINE__, x) static void __noreturn mpi_panic(const char *func, int line, int rc) { printf("Panic function %s, line %d, code %d\n", func, line, rc); TEE_Panic(0xB16127 /*BIGINT*/); while (1) ; /* Panic will crash the thread */ } #define MPI_CHECK(x) do { \ int _rc = (x); \ \ if (_rc) \ mpi_panic(__func__, __LINE__, _rc); \ } while (0) void _TEE_MathAPI_Init(void) { static uint8_t data[MPI_MEMPOOL_SIZE] __aligned(MEMPOOL_ALIGN); mbedtls_mpi_mempool = mempool_alloc_pool(data, sizeof(data), NULL); if (!mbedtls_mpi_mempool) API_PANIC("Failed to initialize memory pool"); } struct bigint_hdr { int32_t sign; uint16_t alloc_size; uint16_t nblimbs; }; #define BIGINT_HDR_SIZE_IN_U32 2 static TEE_Result copy_mpi_to_bigint(mbedtls_mpi *mpi, TEE_BigInt *bigInt) { struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; size_t n = mpi->n; /* Trim of eventual insignificant zeroes */ while (n && !mpi->p[n - 1]) n--; if (hdr->alloc_size < n) return TEE_ERROR_OVERFLOW; hdr->nblimbs = n; hdr->sign = mpi->s; memcpy(hdr + 1, mpi->p, mpi->n * sizeof(mbedtls_mpi_uint)); return TEE_SUCCESS; } /* * Initializes a MPI. * * A temporary MPI is allocated and if a bigInt is supplied the MPI is * initialized with the value of the bigInt. */ static void get_mpi(mbedtls_mpi *mpi, const TEE_BigInt *bigInt) { /* * The way the GP spec is defining the bignums it's * difficult/tricky to do it using 64-bit arithmetics given that * we'd need 64-bit alignment of the data as well. */ COMPILE_TIME_ASSERT(sizeof(mbedtls_mpi_uint) == sizeof(uint32_t)); /* * The struct bigint_hdr is the overhead added to the bigint and * is required to take exactly 2 uint32_t. */ COMPILE_TIME_ASSERT(sizeof(struct bigint_hdr) == sizeof(uint32_t) * BIGINT_HDR_SIZE_IN_U32); mbedtls_mpi_init_mempool(mpi); if (bigInt) { const struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; const mbedtls_mpi_uint *p = (const mbedtls_mpi_uint *)(hdr + 1); size_t n = hdr->nblimbs; /* Trim of eventual insignificant zeroes */ while (n && !p[n - 1]) n--; MPI_CHECK(mbedtls_mpi_grow(mpi, n)); mpi->s = hdr->sign; memcpy(mpi->p, p, n * sizeof(mbedtls_mpi_uint)); } } void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len) { struct bigint_hdr *hdr = (struct bigint_hdr *)bigInt; static_assert(MBEDTLS_MPI_MAX_LIMBS + BIGINT_HDR_SIZE_IN_U32 >= CFG_TA_BIGNUM_MAX_BITS / 32); memset(bigInt, 0, len * sizeof(uint32_t)); hdr->sign = 1; /* "gpd.tee.arith.maxBigIntSize" is assigned CFG_TA_BIGNUM_MAX_BITS */ if (len > CFG_TA_BIGNUM_MAX_BITS / 4) API_PANIC("Too large bigint"); hdr->alloc_size = len - BIGINT_HDR_SIZE_IN_U32; } void __GP11_TEE_BigIntInit(TEE_BigInt *bigInt, uint32_t len) { TEE_BigIntInit(bigInt, len); } TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, size_t bufferLen, int32_t sign) { TEE_Result res; mbedtls_mpi mpi_dest; get_mpi(&mpi_dest, NULL); if (mbedtls_mpi_read_binary(&mpi_dest, buffer, bufferLen)) res = TEE_ERROR_OVERFLOW; else res = TEE_SUCCESS; if (sign < 0) mpi_dest.s = -1; if (!res) res = copy_mpi_to_bigint(&mpi_dest, dest); mbedtls_mpi_free(&mpi_dest); return res; } TEE_Result __GP11_TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, uint32_t bufferLen, int32_t sign) { return TEE_BigIntConvertFromOctetString(dest, buffer, bufferLen, sign); } TEE_Result TEE_BigIntConvertToOctetString(uint8_t *buffer, size_t *bufferLen, const TEE_BigInt *bigInt) { TEE_Result res = TEE_SUCCESS; mbedtls_mpi mpi; size_t sz; get_mpi(&mpi, bigInt); sz = mbedtls_mpi_size(&mpi); if (sz <= *bufferLen) MPI_CHECK(mbedtls_mpi_write_binary(&mpi, buffer, sz)); else res = TEE_ERROR_SHORT_BUFFER; *bufferLen = sz; mbedtls_mpi_free(&mpi); return res; } TEE_Result __GP11_TEE_BigIntConvertToOctetString(uint8_t *buffer, uint32_t *bufferLen, const TEE_BigInt *bigInt) { TEE_Result res = TEE_SUCCESS; size_t l = *bufferLen; res = TEE_BigIntConvertToOctetString(buffer, &l, bigInt); *bufferLen = l; return res; } void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal) { mbedtls_mpi mpi; get_mpi(&mpi, dest); MPI_CHECK(mbedtls_mpi_lset(&mpi, shortVal)); MPI_CHECK(copy_mpi_to_bigint(&mpi, dest)); mbedtls_mpi_free(&mpi); } TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src) { TEE_Result res = TEE_SUCCESS; mbedtls_mpi mpi; uint32_t v; get_mpi(&mpi, src); if (mbedtls_mpi_write_binary(&mpi, (void *)&v, sizeof(v))) { res = TEE_ERROR_OVERFLOW; goto out; } if (mpi.s > 0) { if (ADD_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) res = TEE_ERROR_OVERFLOW; } else { if (SUB_OVERFLOW(0, TEE_U32_FROM_BIG_ENDIAN(v), dest)) res = TEE_ERROR_OVERFLOW; } out: mbedtls_mpi_free(&mpi); return res; } int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2) { mbedtls_mpi mpi1; mbedtls_mpi mpi2; int32_t rc; get_mpi(&mpi1, op1); get_mpi(&mpi2, op2); rc = mbedtls_mpi_cmp_mpi(&mpi1, &mpi2); mbedtls_mpi_free(&mpi1); mbedtls_mpi_free(&mpi2); return rc; } int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal) { mbedtls_mpi mpi; int32_t rc; get_mpi(&mpi, op); rc = mbedtls_mpi_cmp_int(&mpi, shortVal); mbedtls_mpi_free(&mpi); return rc; } void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits) { mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op; get_mpi(&mpi_dest, dest); if (dest == op) { MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); goto out; } get_mpi(&mpi_op, op); if (mbedtls_mpi_size(&mpi_dest) >= mbedtls_mpi_size(&mpi_op)) { MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_op)); MPI_CHECK(mbedtls_mpi_shift_r(&mpi_dest, bits)); } else { mbedtls_mpi mpi_t; get_mpi(&mpi_t, NULL); /* * We're using a temporary buffer to avoid the corner case * where destination is unexpectedly overflowed by up to * @bits number of bits. */ MPI_CHECK(mbedtls_mpi_copy(&mpi_t, &mpi_op)); MPI_CHECK(mbedtls_mpi_shift_r(&mpi_t, bits)); MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_t)); mbedtls_mpi_free(&mpi_t); } mbedtls_mpi_free(&mpi_op); out: MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); } void __GP11_TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, uint32_t bits) { TEE_BigIntShiftRight(dest, op, bits); } bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex) { bool rc; mbedtls_mpi mpi; get_mpi(&mpi, src); rc = mbedtls_mpi_get_bit(&mpi, bitIndex); mbedtls_mpi_free(&mpi); return rc; } uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src) { uint32_t rc; mbedtls_mpi mpi; get_mpi(&mpi, src); rc = mbedtls_mpi_bitlen(&mpi); mbedtls_mpi_free(&mpi); return rc; } TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value) { TEE_Result res = TEE_SUCCESS; mbedtls_mpi mpi = { }; int rc = 0; get_mpi(&mpi, op); rc = mbedtls_mpi_set_bit(&mpi, bitIndex, value); if (rc) res = TEE_ERROR_OVERFLOW; else res = copy_mpi_to_bigint(&mpi, op); mbedtls_mpi_free(&mpi); return res; } TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src) { const struct bigint_hdr *src_hdr = (struct bigint_hdr *)src; struct bigint_hdr *dst_hdr = (struct bigint_hdr *)dest; if (dst_hdr == src_hdr) return TEE_SUCCESS; if (dst_hdr->alloc_size < src_hdr->nblimbs) return TEE_ERROR_OVERFLOW; dst_hdr->nblimbs = src_hdr->nblimbs; dst_hdr->sign = src_hdr->sign; memcpy(dst_hdr + 1, src_hdr + 1, src_hdr->nblimbs * sizeof(uint32_t)); return TEE_SUCCESS; } TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, const TEE_BigInt *src) { TEE_Result res = TEE_BigIntAssign(dest, src); if (!res) ((struct bigint_hdr *)dest)->sign = 1; return res; } static void bigint_binary(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)) { mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_dest, dest); if (op1 == dest) pop1 = &mpi_dest; else get_mpi(&mpi_op1, op1); if (op2 == dest) pop2 = &mpi_dest; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); MPI_CHECK(func(&mpi_dest, pop1, pop2)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); } static void bigint_binary_mod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n, int (*func)(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B)) { mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi mpi_n; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; mbedtls_mpi mpi_t; if (TEE_BigIntCmpS32(n, 2) < 0) API_PANIC("Modulus is too short"); get_mpi(&mpi_dest, dest); get_mpi(&mpi_n, n); if (op1 == dest) pop1 = &mpi_dest; else get_mpi(&mpi_op1, op1); if (op2 == dest) pop2 = &mpi_dest; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); get_mpi(&mpi_t, NULL); MPI_CHECK(func(&mpi_t, pop1, pop2)); MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dest, &mpi_t, &mpi_n)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); mbedtls_mpi_free(&mpi_t); mbedtls_mpi_free(&mpi_n); } void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2) { bigint_binary(dest, op1, op2, mbedtls_mpi_add_mpi); } void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2) { bigint_binary(dest, op1, op2, mbedtls_mpi_sub_mpi); } void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *src) { mbedtls_mpi mpi_dest; get_mpi(&mpi_dest, dest); if (dest != src) { mbedtls_mpi mpi_src; get_mpi(&mpi_src, src); MPI_CHECK(mbedtls_mpi_copy(&mpi_dest, &mpi_src)); mbedtls_mpi_free(&mpi_src); } mpi_dest.s *= -1; MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); } void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2) { size_t bs1 = TEE_BigIntGetBitCount(op1); size_t bs2 = TEE_BigIntGetBitCount(op2); size_t s = TEE_BigIntSizeInU32(bs1) + TEE_BigIntSizeInU32(bs2); TEE_BigInt zero[TEE_BigIntSizeInU32(1)] = { 0 }; TEE_BigInt *tmp = NULL; tmp = mempool_alloc(mbedtls_mpi_mempool, sizeof(uint32_t) * s); if (!tmp) TEE_Panic(TEE_ERROR_OUT_OF_MEMORY); TEE_BigIntInit(tmp, s); TEE_BigIntInit(zero, TEE_BigIntSizeInU32(1)); bigint_binary(tmp, op1, op2, mbedtls_mpi_mul_mpi); TEE_BigIntAdd(dest, tmp, zero); mempool_free(mbedtls_mpi_mempool, tmp); } void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op) { TEE_BigIntMul(dest, op, op); } void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, const TEE_BigInt *op1, const TEE_BigInt *op2) { mbedtls_mpi mpi_dest_q; mbedtls_mpi mpi_dest_r; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_dest_q, dest_q); get_mpi(&mpi_dest_r, dest_r); if (op1 == dest_q) pop1 = &mpi_dest_q; else if (op1 == dest_r) pop1 = &mpi_dest_r; else get_mpi(&mpi_op1, op1); if (op2 == dest_q) pop2 = &mpi_dest_q; else if (op2 == dest_r) pop2 = &mpi_dest_r; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); MPI_CHECK(mbedtls_mpi_div_mpi(&mpi_dest_q, &mpi_dest_r, pop1, pop2)); if (dest_q) MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_q, dest_q)); if (dest_r) MPI_CHECK(copy_mpi_to_bigint(&mpi_dest_r, dest_r)); mbedtls_mpi_free(&mpi_dest_q); mbedtls_mpi_free(&mpi_dest_r); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); } void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n) { if (TEE_BigIntCmpS32(n, 2) < 0) API_PANIC("Modulus is too short"); bigint_binary(dest, op, n, mbedtls_mpi_mod_mpi); } void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n) { bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_add_mpi); } void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n) { bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_sub_mpi); } void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n) { bigint_binary_mod(dest, op1, op2, n, mbedtls_mpi_mul_mpi); } void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n) { TEE_BigIntMulMod(dest, op, op, n); } void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n) { mbedtls_mpi mpi_dest; mbedtls_mpi mpi_op; mbedtls_mpi mpi_n; mbedtls_mpi *pop = &mpi_op; if (TEE_BigIntCmpS32(n, 2) < 0 || TEE_BigIntCmpS32(op, 0) == 0) API_PANIC("too small modulus or trying to invert zero"); get_mpi(&mpi_dest, dest); get_mpi(&mpi_n, n); if (op == dest) pop = &mpi_dest; else get_mpi(&mpi_op, op); MPI_CHECK(mbedtls_mpi_inv_mod(&mpi_dest, pop, &mpi_n)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); mbedtls_mpi_free(&mpi_dest); mbedtls_mpi_free(&mpi_n); if (pop == &mpi_op) mbedtls_mpi_free(&mpi_op); } bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2) { bool rc; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop2 = &mpi_op2; mbedtls_mpi gcd; get_mpi(&mpi_op1, op1); if (op2 == op1) pop2 = &mpi_op1; else get_mpi(&mpi_op2, op2); get_mpi(&gcd, NULL); MPI_CHECK(mbedtls_mpi_gcd(&gcd, &mpi_op1, &mpi_op2)); rc = !mbedtls_mpi_cmp_int(&gcd, 1); mbedtls_mpi_free(&gcd); mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); return rc; } static bool mpi_is_odd(mbedtls_mpi *x) { return mbedtls_mpi_get_bit(x, 0); } static bool mpi_is_even(mbedtls_mpi *x) { return !mpi_is_odd(x); } TEE_Result TEE_BigIntExpMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n, const TEE_BigIntFMMContext *context __unused) { TEE_Result res = TEE_SUCCESS; mbedtls_mpi mpi_dest = { }; mbedtls_mpi mpi_op1 = { }; mbedtls_mpi mpi_op2 = { }; mbedtls_mpi mpi_n = { }; mbedtls_mpi *pop1 = &mpi_op1; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_dest, dest); get_mpi(&mpi_n, n); if (op1 == dest) pop1 = &mpi_dest; else get_mpi(&mpi_op1, op1); if (op2 == dest) pop2 = &mpi_dest; else if (op2 == op1) pop2 = pop1; else get_mpi(&mpi_op2, op2); if (mbedtls_mpi_cmp_int(&mpi_n, 2) <= 0) API_PANIC("too small modulus"); if (!mpi_is_odd(&mpi_n)) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } MPI_CHECK(mbedtls_mpi_exp_mod(&mpi_dest, pop1, pop2, &mpi_n, NULL)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dest, dest)); out: mbedtls_mpi_free(&mpi_dest); mbedtls_mpi_free(&mpi_n); if (pop1 == &mpi_op1) mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); return res; } static void mpi_egcd(mbedtls_mpi *gcd, mbedtls_mpi *a, mbedtls_mpi *b, mbedtls_mpi *x_in, mbedtls_mpi *y_in) { mbedtls_mpi_uint k; mbedtls_mpi A; mbedtls_mpi B; mbedtls_mpi C; mbedtls_mpi D; mbedtls_mpi x; mbedtls_mpi y; mbedtls_mpi u; get_mpi(&A, NULL); get_mpi(&B, NULL); get_mpi(&C, NULL); get_mpi(&D, NULL); get_mpi(&x, NULL); get_mpi(&y, NULL); get_mpi(&u, NULL); /* have y < x from assumption */ if (!mbedtls_mpi_cmp_int(y_in, 0)) { MPI_CHECK(mbedtls_mpi_lset(a, 1)); MPI_CHECK(mbedtls_mpi_lset(b, 0)); MPI_CHECK(mbedtls_mpi_copy(gcd, x_in)); goto out; } MPI_CHECK(mbedtls_mpi_copy(&x, x_in)); MPI_CHECK(mbedtls_mpi_copy(&y, y_in)); k = 0; while (mpi_is_even(&x) && mpi_is_even(&y)) { k++; MPI_CHECK(mbedtls_mpi_shift_r(&x, 1)); MPI_CHECK(mbedtls_mpi_shift_r(&y, 1)); } MPI_CHECK(mbedtls_mpi_copy(&u, &x)); MPI_CHECK(mbedtls_mpi_copy(gcd, &y)); MPI_CHECK(mbedtls_mpi_lset(&A, 1)); MPI_CHECK(mbedtls_mpi_lset(&B, 0)); MPI_CHECK(mbedtls_mpi_lset(&C, 0)); MPI_CHECK(mbedtls_mpi_lset(&D, 1)); while (mbedtls_mpi_cmp_int(&u, 0)) { while (mpi_is_even(&u)) { MPI_CHECK(mbedtls_mpi_shift_r(&u, 1)); if (mpi_is_odd(&A) || mpi_is_odd(&B)) { MPI_CHECK(mbedtls_mpi_add_mpi(&A, &A, &y)); MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &x)); } MPI_CHECK(mbedtls_mpi_shift_r(&A, 1)); MPI_CHECK(mbedtls_mpi_shift_r(&B, 1)); } while (mpi_is_even(gcd)) { MPI_CHECK(mbedtls_mpi_shift_r(gcd, 1)); if (mpi_is_odd(&C) || mpi_is_odd(&D)) { MPI_CHECK(mbedtls_mpi_add_mpi(&C, &C, &y)); MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &x)); } MPI_CHECK(mbedtls_mpi_shift_r(&C, 1)); MPI_CHECK(mbedtls_mpi_shift_r(&D, 1)); } if (mbedtls_mpi_cmp_mpi(&u, gcd) >= 0) { MPI_CHECK(mbedtls_mpi_sub_mpi(&u, &u, gcd)); MPI_CHECK(mbedtls_mpi_sub_mpi(&A, &A, &C)); MPI_CHECK(mbedtls_mpi_sub_mpi(&B, &B, &D)); } else { MPI_CHECK(mbedtls_mpi_sub_mpi(gcd, gcd, &u)); MPI_CHECK(mbedtls_mpi_sub_mpi(&C, &C, &A)); MPI_CHECK(mbedtls_mpi_sub_mpi(&D, &D, &B)); } } MPI_CHECK(mbedtls_mpi_copy(a, &C)); MPI_CHECK(mbedtls_mpi_copy(b, &D)); MPI_CHECK(mbedtls_mpi_shift_l(gcd, k)); out: mbedtls_mpi_free(&A); mbedtls_mpi_free(&B); mbedtls_mpi_free(&C); mbedtls_mpi_free(&D); mbedtls_mpi_free(&x); mbedtls_mpi_free(&y); mbedtls_mpi_free(&u); } void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, TEE_BigInt *v, const TEE_BigInt *op1, const TEE_BigInt *op2) { mbedtls_mpi mpi_gcd_res; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi *pop2 = &mpi_op2; get_mpi(&mpi_gcd_res, gcd); get_mpi(&mpi_op1, op1); if (op2 == op1) pop2 = &mpi_op1; else get_mpi(&mpi_op2, op2); if (!u && !v) { MPI_CHECK(mbedtls_mpi_gcd(&mpi_gcd_res, &mpi_op1, pop2)); } else { mbedtls_mpi mpi_u; mbedtls_mpi mpi_v; int8_t s1 = mpi_op1.s; int8_t s2 = pop2->s; int cmp; mpi_op1.s = 1; pop2->s = 1; get_mpi(&mpi_u, u); get_mpi(&mpi_v, v); cmp = mbedtls_mpi_cmp_abs(&mpi_op1, pop2); if (cmp == 0) { MPI_CHECK(mbedtls_mpi_copy(&mpi_gcd_res, &mpi_op1)); MPI_CHECK(mbedtls_mpi_lset(&mpi_u, 1)); MPI_CHECK(mbedtls_mpi_lset(&mpi_v, 0)); } else if (cmp > 0) { mpi_egcd(&mpi_gcd_res, &mpi_u, &mpi_v, &mpi_op1, pop2); } else { mpi_egcd(&mpi_gcd_res, &mpi_v, &mpi_u, pop2, &mpi_op1); } mpi_u.s *= s1; mpi_v.s *= s2; MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u)); MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v)); mbedtls_mpi_free(&mpi_u); mbedtls_mpi_free(&mpi_v); } MPI_CHECK(copy_mpi_to_bigint(&mpi_gcd_res, gcd)); mbedtls_mpi_free(&mpi_gcd_res); mbedtls_mpi_free(&mpi_op1); if (pop2 == &mpi_op2) mbedtls_mpi_free(&mpi_op2); } static int rng_read(void *ignored __unused, unsigned char *buf, size_t blen) { if (_utee_cryp_random_number_generate(buf, blen)) return MBEDTLS_ERR_MPI_FILE_IO_ERROR; return 0; } int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, uint32_t confidenceLevel) { int rc; mbedtls_mpi mpi_op; get_mpi(&mpi_op, op); rc = mbedtls_mpi_is_prime_ext(&mpi_op, MAX(confidenceLevel, 80U), rng_read, NULL); mbedtls_mpi_free(&mpi_op); if (rc) return 0; return 1; } /* * Not so fast FMM implementation based on the normal big int functions. * * Note that these functions (along with all the other functions in this * file) only are used directly by the TA doing bigint arithmetics on its * own. Performance of RSA operations in TEE Internal API are not affected * by this. */ void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len) { TEE_BigIntInit(bigIntFMM, len); } void __GP11_TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, uint32_t len) { TEE_BigIntInitFMM(bigIntFMM, len); } void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context __unused, size_t len __unused, const TEE_BigInt *modulus __unused) { } void __GP11_TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, uint32_t len, const TEE_BigInt *modulus) { TEE_BigIntInitFMMContext(context, len, modulus); } TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context __unused, size_t len __unused, const TEE_BigInt *modulus __unused) { return TEE_SUCCESS; } size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits) { return TEE_BigIntSizeInU32(modulusSizeInBits); } uint32_t __GP11_TEE_BigIntFMMSizeInU32(uint32_t modulusSizeInBits) { return TEE_BigIntFMMSizeInU32(modulusSizeInBits); } size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits __unused) { /* Return something larger than 0 to keep malloc() and friends happy */ return 1; } uint32_t __GP11_TEE_BigIntFMMContextSizeInU32(uint32_t modulusSizeInBits) { return TEE_BigIntFMMContextSizeInU32(modulusSizeInBits); } void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, const TEE_BigInt *n, const TEE_BigIntFMMContext *context __unused) { TEE_BigIntMod(dest, src, n); } void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, const TEE_BigInt *n __unused, const TEE_BigIntFMMContext *context __unused) { mbedtls_mpi mpi_dst; mbedtls_mpi mpi_src; get_mpi(&mpi_dst, dest); get_mpi(&mpi_src, src); MPI_CHECK(mbedtls_mpi_copy(&mpi_dst, &mpi_src)); MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest)); mbedtls_mpi_free(&mpi_dst); mbedtls_mpi_free(&mpi_src); } void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, const TEE_BigIntFMM *op2, const TEE_BigInt *n, const TEE_BigIntFMMContext *context __unused) { mbedtls_mpi mpi_dst; mbedtls_mpi mpi_op1; mbedtls_mpi mpi_op2; mbedtls_mpi mpi_n; mbedtls_mpi mpi_t; get_mpi(&mpi_dst, dest); get_mpi(&mpi_op1, op1); get_mpi(&mpi_op2, op2); get_mpi(&mpi_n, n); get_mpi(&mpi_t, NULL); MPI_CHECK(mbedtls_mpi_mul_mpi(&mpi_t, &mpi_op1, &mpi_op2)); MPI_CHECK(mbedtls_mpi_mod_mpi(&mpi_dst, &mpi_t, &mpi_n)); mbedtls_mpi_free(&mpi_t); mbedtls_mpi_free(&mpi_n); mbedtls_mpi_free(&mpi_op2); mbedtls_mpi_free(&mpi_op1); MPI_CHECK(copy_mpi_to_bigint(&mpi_dst, dest)); mbedtls_mpi_free(&mpi_dst); } optee_os-4.3.0/lib/libutee/tee_api_objects.c000066400000000000000000000637771464416617300210550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include "tee_api_private.h" #define TEE_USAGE_DEFAULT 0xffffffff void __utee_from_attr(struct utee_attribute *ua, const TEE_Attribute *attrs, uint32_t attr_count) { size_t n; for (n = 0; n < attr_count; n++) { ua[n].attribute_id = attrs[n].attributeID; if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { ua[n].a = attrs[n].content.value.a; ua[n].b = attrs[n].content.value.b; } else { ua[n].a = (uintptr_t)attrs[n].content.ref.buffer; ua[n].b = attrs[n].content.ref.length; } } } void __utee_from_gp11_attr(struct utee_attribute *ua, const __GP11_TEE_Attribute *attrs, uint32_t attr_count) { size_t n = 0; for (n = 0; n < attr_count; n++) { ua[n].attribute_id = attrs[n].attributeID; if (attrs[n].attributeID & TEE_ATTR_FLAG_VALUE) { ua[n].a = attrs[n].content.value.a; ua[n].b = attrs[n].content.value.b; } else { ua[n].a = (uintptr_t)attrs[n].content.ref.buffer; ua[n].b = attrs[n].content.ref.length; } } } /* Data and Key Storage API - Generic Object Functions */ /* * Use of this function is deprecated * new code SHOULD use the TEE_GetObjectInfo1 function instead * These functions will be removed at some future major revision of * this specification */ void TEE_GetObjectInfo(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) TEE_Panic(res); if (info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) { objectInfo->objectSize = 0; objectInfo->maxObjectSize = 0; objectInfo->objectUsage = 0; objectInfo->dataSize = 0; objectInfo->dataPosition = 0; objectInfo->handleFlags = 0; } else { objectInfo->objectType = info.obj_type; objectInfo->objectSize = info.obj_size; objectInfo->maxObjectSize = info.max_obj_size; objectInfo->objectUsage = info.obj_usage; objectInfo->dataSize = info.data_size; objectInfo->dataPosition = info.data_pos; objectInfo->handleFlags = info.handle_flags; } } void __GP11_TEE_GetObjectInfo(TEE_ObjectHandle object, __GP11_TEE_ObjectInfo *objectInfo) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) TEE_Panic(res); if (info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) { objectInfo->keySize = 0; objectInfo->maxKeySize = 0; objectInfo->objectUsage = 0; objectInfo->dataSize = 0; objectInfo->dataPosition = 0; objectInfo->handleFlags = 0; } else { objectInfo->objectType = info.obj_type; objectInfo->keySize = info.obj_size; objectInfo->maxKeySize = info.max_obj_size; objectInfo->objectUsage = info.obj_usage; objectInfo->dataSize = info.data_size; objectInfo->dataPosition = info.data_pos; objectInfo->handleFlags = info.handle_flags; } } TEE_Result TEE_GetObjectInfo1(TEE_ObjectHandle object, TEE_ObjectInfo *objectInfo) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); objectInfo->objectType = info.obj_type; objectInfo->objectSize = info.obj_size; objectInfo->maxObjectSize = info.max_obj_size; objectInfo->objectUsage = info.obj_usage; objectInfo->dataSize = info.data_size; objectInfo->dataPosition = info.data_pos; objectInfo->handleFlags = info.handle_flags; return res; } TEE_Result __GP11_TEE_GetObjectInfo1(TEE_ObjectHandle object, __GP11_TEE_ObjectInfo *objectInfo) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); objectInfo->objectType = info.obj_type; objectInfo->keySize = info.obj_size; objectInfo->maxKeySize = info.max_obj_size; objectInfo->objectUsage = info.obj_usage; objectInfo->dataSize = info.data_size; objectInfo->dataPosition = info.data_pos; objectInfo->handleFlags = info.handle_flags; return res; } /* * Use of this function is deprecated * new code SHOULD use the TEE_RestrictObjectUsage1 function instead * These functions will be removed at some future major revision of * this specification */ void TEE_RestrictObjectUsage(TEE_ObjectHandle object, uint32_t objectUsage) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) return; res = TEE_RestrictObjectUsage1(object, objectUsage); if (res != TEE_SUCCESS) TEE_Panic(res); } TEE_Result TEE_RestrictObjectUsage1(TEE_ObjectHandle object, uint32_t objectUsage) { TEE_Result res; res = _utee_cryp_obj_restrict_usage((unsigned long)object, objectUsage); if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, uint32_t attributeID, void *buffer, size_t *size) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; uint64_t sz = 0; __utee_check_inout_annotation(size, sizeof(*size)); res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) goto exit; /* This function only supports reference attributes */ if ((attributeID & TEE_ATTR_FLAG_VALUE)) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } sz = *size; res = _utee_cryp_obj_get_attr((unsigned long)object, attributeID, buffer, &sz); *size = sz; exit: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_GetObjectBufferAttribute(TEE_ObjectHandle object, uint32_t attributeID, void *buffer, uint32_t *size) { TEE_Result res = TEE_SUCCESS; size_t l = 0; __utee_check_inout_annotation(size, sizeof(*size)); l = *size; res = TEE_GetObjectBufferAttribute(object, attributeID, buffer, &l); *size = l; return res; } TEE_Result TEE_GetObjectValueAttribute(TEE_ObjectHandle object, uint32_t attributeID, uint32_t *a, uint32_t *b) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; uint32_t buf[2]; uint64_t size = sizeof(buf); if (a) __utee_check_out_annotation(a, sizeof(*a)); if (b) __utee_check_out_annotation(b, sizeof(*b)); res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) goto exit; /* This function only supports value attributes */ if (!(attributeID & TEE_ATTR_FLAG_VALUE)) { res = TEE_ERROR_BAD_PARAMETERS; goto exit; } res = _utee_cryp_obj_get_attr((unsigned long)object, attributeID, buf, &size); exit: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); if (size != sizeof(buf)) TEE_Panic(0); if (res == TEE_SUCCESS) { if (a) *a = buf[0]; if (b) *b = buf[1]; } return res; } void TEE_CloseObject(TEE_ObjectHandle object) { TEE_Result res; if (object == TEE_HANDLE_NULL) return; res = _utee_cryp_obj_close((unsigned long)object); if (res != TEE_SUCCESS) TEE_Panic(res); } /* Data and Key Storage API - Transient Object Functions */ TEE_Result TEE_AllocateTransientObject(TEE_ObjectType objectType, uint32_t maxObjectSize, TEE_ObjectHandle *object) { if (objectType == TEE_TYPE_DATA) return TEE_ERROR_NOT_SUPPORTED; return __GP11_TEE_AllocateTransientObject(objectType, maxObjectSize, object); } TEE_Result __GP11_TEE_AllocateTransientObject(TEE_ObjectType objectType, uint32_t maxKeySize, TEE_ObjectHandle *object) { TEE_Result res; uint32_t obj; __utee_check_out_annotation(object, sizeof(*object)); res = _utee_cryp_obj_alloc(objectType, maxKeySize, &obj); if (res != TEE_SUCCESS && res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_NOT_SUPPORTED) TEE_Panic(res); if (res == TEE_SUCCESS) *object = (TEE_ObjectHandle)(uintptr_t)obj; return res; } void TEE_FreeTransientObject(TEE_ObjectHandle object) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; if (object == TEE_HANDLE_NULL) return; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) TEE_Panic(res); if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) TEE_Panic(0); res = _utee_cryp_obj_close((unsigned long)object); if (res != TEE_SUCCESS) TEE_Panic(res); } void TEE_ResetTransientObject(TEE_ObjectHandle object) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; if (object == TEE_HANDLE_NULL) return; res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) TEE_Panic(res); if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) TEE_Panic(0); res = _utee_cryp_obj_reset((unsigned long)object); if (res != TEE_SUCCESS) TEE_Panic(res); } TEE_Result TEE_PopulateTransientObject(TEE_ObjectHandle object, const TEE_Attribute *attrs, uint32_t attrCount) { struct utee_attribute ua[attrCount]; struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; __utee_check_attr_in_annotation(attrs, attrCount); res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) TEE_Panic(res); /* Must be a transient object */ if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) TEE_Panic(0); /* Must not be initialized already */ if ((info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) TEE_Panic(0); __utee_from_attr(ua, attrs, attrCount); res = _utee_cryp_obj_populate((unsigned long)object, ua, attrCount); if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_PopulateTransientObject(TEE_ObjectHandle object, const __GP11_TEE_Attribute *attrs, uint32_t attrCount) { struct utee_attribute ua[attrCount]; struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; __utee_check_gp11_attr_in_annotation(attrs, attrCount); res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) TEE_Panic(res); /* Must be a transient object */ if ((info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT) != 0) TEE_Panic(0); /* Must not be initialized already */ if ((info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) TEE_Panic(0); __utee_from_gp11_attr(ua, attrs, attrCount); res = _utee_cryp_obj_populate((unsigned long)object, ua, attrCount); if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) TEE_Panic(res); return res; } void TEE_InitRefAttribute(TEE_Attribute *attr, uint32_t attributeID, const void *buffer, size_t length) { __utee_check_out_annotation(attr, sizeof(*attr)); if ((attributeID & TEE_ATTR_FLAG_VALUE) != 0) TEE_Panic(0); attr->attributeID = attributeID; attr->content.ref.buffer = (void *)buffer; attr->content.ref.length = length; } void __GP11_TEE_InitRefAttribute(__GP11_TEE_Attribute *attr, uint32_t attributeID, const void *buffer, uint32_t length) { __utee_check_out_annotation(attr, sizeof(*attr)); if ((attributeID & TEE_ATTR_FLAG_VALUE) != 0) TEE_Panic(0); attr->attributeID = attributeID; attr->content.ref.buffer = (void *)buffer; attr->content.ref.length = length; } void TEE_InitValueAttribute(TEE_Attribute *attr, uint32_t attributeID, uint32_t a, uint32_t b) { __utee_check_out_annotation(attr, sizeof(*attr)); if ((attributeID & TEE_ATTR_FLAG_VALUE) == 0) TEE_Panic(0); attr->attributeID = attributeID; attr->content.value.a = a; attr->content.value.b = b; } void __GP11_TEE_InitValueAttribute(__GP11_TEE_Attribute *attr, uint32_t attributeID, uint32_t a, uint32_t b) { __utee_check_out_annotation(attr, sizeof(*attr)); if ((attributeID & TEE_ATTR_FLAG_VALUE) == 0) TEE_Panic(0); attr->attributeID = attributeID; attr->content.value.a = a; attr->content.value.b = b; } /* * Use of this function is deprecated * new code SHOULD use the TEE_CopyObjectAttributes1 function instead * These functions will be removed at some future major revision of * this specification */ void TEE_CopyObjectAttributes(TEE_ObjectHandle destObject, TEE_ObjectHandle srcObject) { struct utee_object_info src_info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)srcObject, &src_info); if (src_info.obj_type == TEE_TYPE_CORRUPTED_OBJECT) return; res = TEE_CopyObjectAttributes1(destObject, srcObject); if (res != TEE_SUCCESS) TEE_Panic(res); } TEE_Result TEE_CopyObjectAttributes1(TEE_ObjectHandle destObject, TEE_ObjectHandle srcObject) { struct utee_object_info dst_info = { }; struct utee_object_info src_info = { }; TEE_Result res = TEE_SUCCESS; res = _utee_cryp_obj_get_info((unsigned long)destObject, &dst_info); if (res != TEE_SUCCESS) goto exit; res = _utee_cryp_obj_get_info((unsigned long)srcObject, &src_info); if (res != TEE_SUCCESS) goto exit; if (!(src_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED)) TEE_Panic(0); if ((dst_info.handle_flags & TEE_HANDLE_FLAG_PERSISTENT)) TEE_Panic(0); if ((dst_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED)) TEE_Panic(0); res = _utee_cryp_obj_copy((unsigned long)destObject, (unsigned long)srcObject); exit: if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, const TEE_Attribute *params, uint32_t paramCount) { TEE_Result res; struct utee_attribute ua[paramCount]; __utee_check_attr_in_annotation(params, paramCount); __utee_from_attr(ua, params, paramCount); res = _utee_cryp_obj_generate_key((unsigned long)object, keySize, ua, paramCount); if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_GenerateKey(TEE_ObjectHandle object, uint32_t keySize, const __GP11_TEE_Attribute *params, uint32_t paramCount) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; __utee_check_gp11_attr_in_annotation(params, paramCount); __utee_from_gp11_attr(ua, params, paramCount); res = _utee_cryp_obj_generate_key((unsigned long)object, keySize, ua, paramCount); if (res != TEE_SUCCESS && res != TEE_ERROR_BAD_PARAMETERS) TEE_Panic(res); return res; } /* Data and Key Storage API - Persistent Object Functions */ TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle *object) { TEE_Result res; uint32_t obj; __utee_check_out_annotation(object, sizeof(*object)); res = _utee_storage_obj_open(storageID, objectID, objectIDLen, flags, &obj); if (res == TEE_SUCCESS) *object = (TEE_ObjectHandle)(uintptr_t)obj; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_ACCESS_CONFLICT && res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); if (res != TEE_SUCCESS) *object = TEE_HANDLE_NULL; return res; } TEE_Result __GP11_TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, uint32_t objectIDLen, uint32_t flags, TEE_ObjectHandle *object) { return TEE_OpenPersistentObject(storageID, objectID, objectIDLen, flags, object); } TEE_Result TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, const void *initialData, size_t initialDataLen, TEE_ObjectHandle *object) { TEE_Result res = TEE_SUCCESS; uint32_t *obj_ptr = NULL; uint32_t obj = 0; if (object) { __utee_check_out_annotation(object, sizeof(*object)); obj_ptr = &obj; } res = _utee_storage_obj_create(storageID, objectID, objectIDLen, flags, (unsigned long)attributes, initialData, initialDataLen, obj_ptr); if (res == TEE_SUCCESS && object) *object = (TEE_ObjectHandle)(uintptr_t)obj; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_ACCESS_CONFLICT && res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_STORAGE_NO_SPACE && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); if (res != TEE_SUCCESS && object) *object = TEE_HANDLE_NULL; return res; } TEE_Result __GP11_TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, uint32_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, const void *initialData, uint32_t initialDataLen, TEE_ObjectHandle *object) { __utee_check_out_annotation(object, sizeof(*object)); return TEE_CreatePersistentObject(storageID, objectID, objectIDLen, flags, attributes, initialData, initialDataLen, object); } /* * Use of this function is deprecated * new code SHOULD use the TEE_CloseAndDeletePersistentObject1 function instead * These functions will be removed at some future major revision of * this specification */ void TEE_CloseAndDeletePersistentObject(TEE_ObjectHandle object) { TEE_Result res; if (object == TEE_HANDLE_NULL) return; res = TEE_CloseAndDeletePersistentObject1(object); if (res != TEE_SUCCESS) TEE_Panic(0); } TEE_Result TEE_CloseAndDeletePersistentObject1(TEE_ObjectHandle object) { TEE_Result res; if (object == TEE_HANDLE_NULL) return TEE_SUCCESS; res = _utee_storage_obj_del((unsigned long)object); if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result TEE_RenamePersistentObject(TEE_ObjectHandle object, const void *newObjectID, size_t newObjectIDLen) { TEE_Result res; if (object == TEE_HANDLE_NULL) { res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } res = _utee_storage_obj_rename((unsigned long)object, newObjectID, newObjectIDLen); out: if (res != TEE_SUCCESS && res != TEE_ERROR_ACCESS_CONFLICT && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_RenamePersistentObject(TEE_ObjectHandle object, const void *newObjectID, uint32_t newObjectIDLen) { return TEE_RenamePersistentObject(object, newObjectID, newObjectIDLen); } TEE_Result TEE_AllocatePersistentObjectEnumerator(TEE_ObjectEnumHandle * objectEnumerator) { TEE_Result res; uint32_t oe; __utee_check_out_annotation(objectEnumerator, sizeof(*objectEnumerator)); res = _utee_storage_alloc_enum(&oe); if (res != TEE_SUCCESS) oe = TEE_HANDLE_NULL; *objectEnumerator = (TEE_ObjectEnumHandle)(uintptr_t)oe; if (res != TEE_SUCCESS && res != TEE_ERROR_ACCESS_CONFLICT) TEE_Panic(res); return res; } void TEE_FreePersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) { TEE_Result res; if (objectEnumerator == TEE_HANDLE_NULL) return; res = _utee_storage_free_enum((unsigned long)objectEnumerator); if (res != TEE_SUCCESS) TEE_Panic(res); } void TEE_ResetPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator) { TEE_Result res; if (objectEnumerator == TEE_HANDLE_NULL) return; res = _utee_storage_reset_enum((unsigned long)objectEnumerator); if (res != TEE_SUCCESS) TEE_Panic(res); } TEE_Result TEE_StartPersistentObjectEnumerator(TEE_ObjectEnumHandle objectEnumerator, uint32_t storageID) { TEE_Result res; res = _utee_storage_start_enum((unsigned long)objectEnumerator, storageID); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, TEE_ObjectInfo *objectInfo, void *objectID, size_t *objectIDLen) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; uint64_t len = 0; if (objectInfo) __utee_check_out_annotation(objectInfo, sizeof(*objectInfo)); __utee_check_out_annotation(objectIDLen, sizeof(*objectIDLen)); if (!objectID) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } len = *objectIDLen; res = _utee_storage_next_enum((unsigned long)objectEnumerator, &info, objectID, &len); if (objectInfo) { objectInfo->objectType = info.obj_type; objectInfo->objectSize = info.obj_size; objectInfo->maxObjectSize = info.max_obj_size; objectInfo->objectUsage = info.obj_usage; objectInfo->dataSize = info.data_size; objectInfo->dataPosition = info.data_pos; objectInfo->handleFlags = info.handle_flags; } *objectIDLen = len; out: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_GetNextPersistentObject(TEE_ObjectEnumHandle objectEnumerator, __GP11_TEE_ObjectInfo *objectInfo, void *objectID, uint32_t *objectIDLen) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; uint64_t len = 0; if (objectInfo) __utee_check_out_annotation(objectInfo, sizeof(*objectInfo)); __utee_check_out_annotation(objectIDLen, sizeof(*objectIDLen)); if (!objectID) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } len = *objectIDLen; res = _utee_storage_next_enum((unsigned long)objectEnumerator, &info, objectID, &len); if (objectInfo) { objectInfo->objectType = info.obj_type; objectInfo->keySize = info.obj_size; objectInfo->maxKeySize = info.max_obj_size; objectInfo->objectUsage = info.obj_usage; objectInfo->dataSize = info.data_size; objectInfo->dataPosition = info.data_pos; objectInfo->handleFlags = info.handle_flags; } *objectIDLen = len; out: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } /* Data and Key Storage API - Data Stream Access Functions */ TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, size_t size, size_t *count) { TEE_Result res; uint64_t cnt64; if (object == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_out_annotation(count, sizeof(*count)); cnt64 = *count; res = _utee_storage_obj_read((unsigned long)object, buffer, size, &cnt64); *count = cnt64; out: if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer, uint32_t size, uint32_t *count) { TEE_Result res = TEE_SUCCESS; size_t cnt = 0; __utee_check_out_annotation(count, sizeof(*count)); cnt = *count; res = TEE_ReadObjectData(object, buffer, size, &cnt); *count = cnt; return res; } TEE_Result TEE_WriteObjectData(TEE_ObjectHandle object, const void *buffer, size_t size) { TEE_Result res; if (object == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (size > TEE_DATA_MAX_POSITION) { res = TEE_ERROR_OVERFLOW; goto out; } res = _utee_storage_obj_write((unsigned long)object, buffer, size); out: if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NO_SPACE && res != TEE_ERROR_OVERFLOW && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_WriteObjectData(TEE_ObjectHandle object, const void *buffer, uint32_t size) { return TEE_WriteObjectData(object, buffer, size); } TEE_Result TEE_TruncateObjectData(TEE_ObjectHandle object, size_t size) { TEE_Result res; if (object == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = _utee_storage_obj_trunc((unsigned long)object, size); out: if (res != TEE_SUCCESS && res != TEE_ERROR_STORAGE_NO_SPACE && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_TruncateObjectData(TEE_ObjectHandle object, uint32_t size) { return TEE_TruncateObjectData(object, size); } TEE_Result TEE_SeekObjectData(TEE_ObjectHandle object, intmax_t offset, TEE_Whence whence) { struct utee_object_info info = { }; TEE_Result res = TEE_SUCCESS; if (object == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = _utee_cryp_obj_get_info((unsigned long)object, &info); if (res != TEE_SUCCESS) goto out; switch (whence) { case TEE_DATA_SEEK_SET: if (offset > 0 && (uint32_t)offset > TEE_DATA_MAX_POSITION) { res = TEE_ERROR_OVERFLOW; goto out; } break; case TEE_DATA_SEEK_CUR: if (offset > 0 && ((uint32_t)offset + info.data_pos > TEE_DATA_MAX_POSITION || (uint32_t)offset + info.data_pos < info.data_pos)) { res = TEE_ERROR_OVERFLOW; goto out; } break; case TEE_DATA_SEEK_END: if (offset > 0 && ((uint32_t)offset + info.data_size > TEE_DATA_MAX_POSITION || (uint32_t)offset + info.data_size < info.data_size)) { res = TEE_ERROR_OVERFLOW; goto out; } break; default: res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } res = _utee_storage_obj_seek((unsigned long)object, offset, whence); out: if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_SeekObjectData(TEE_ObjectHandle object, int32_t offset, TEE_Whence whence) { return TEE_SeekObjectData(object, offset, whence); } optee_os-4.3.0/lib/libutee/tee_api_operations.c000066400000000000000000002135421464416617300215720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2021, SumUp Services GmbH */ #include #include #include #include #include #include #include #include #include #include #include #include "tee_api_private.h" struct __TEE_OperationHandle { TEE_OperationInfo info; TEE_ObjectHandle key1; TEE_ObjectHandle key2; uint32_t operationState;/* Operation state : INITIAL or ACTIVE */ /* * buffer to collect complete blocks or to keep a complete digest * for TEE_DigestExtract(). */ uint8_t *buffer; bool buffer_two_blocks; /* True if two blocks need to be buffered */ size_t block_size; /* Block size of cipher */ size_t buffer_offs; /* Offset in buffer */ uint32_t state; /* Handle to state in TEE Core */ }; /* Cryptographic Operations API - Generic Operation Functions */ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation, uint32_t algorithm, uint32_t mode, uint32_t maxKeySize) { TEE_Result res; TEE_OperationHandle op = TEE_HANDLE_NULL; uint32_t handle_state = 0; size_t block_size = 1; uint32_t req_key_usage; bool with_private_key = false; bool buffer_two_blocks = false; if (!operation) TEE_Panic(0); if (algorithm == TEE_ALG_AES_XTS || algorithm == TEE_ALG_SM2_KEP || algorithm == TEE_ALG_SM4_XTS) handle_state = TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; /* Check algorithm max key size */ switch (algorithm) { case TEE_ALG_DSA_SHA1: if (maxKeySize < 512) return TEE_ERROR_NOT_SUPPORTED; if (maxKeySize > 1024) return TEE_ERROR_NOT_SUPPORTED; if (maxKeySize % 64 != 0) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_DSA_SHA224: if (maxKeySize != 2048) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_DSA_SHA256: if (maxKeySize != 2048 && maxKeySize != 3072) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ECDSA_SHA1: case __OPTEE_ALG_ECDSA_P192: case __OPTEE_ALG_ECDH_P192: if (maxKeySize != 192) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ECDSA_SHA224: case __OPTEE_ALG_ECDSA_P224: case __OPTEE_ALG_ECDH_P224: if (maxKeySize != 224) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ECDSA_SHA256: case __OPTEE_ALG_ECDSA_P256: case __OPTEE_ALG_ECDH_P256: case TEE_ALG_SM2_PKE: case TEE_ALG_SM2_DSA_SM3: if (maxKeySize != 256) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_SM2_KEP: /* Two 256-bit keys */ if (maxKeySize != 512) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ECDSA_SHA384: case __OPTEE_ALG_ECDSA_P384: case __OPTEE_ALG_ECDH_P384: if (maxKeySize != 384) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ECDSA_SHA512: case __OPTEE_ALG_ECDSA_P521: case __OPTEE_ALG_ECDH_P521: if (maxKeySize != 521) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ECDH_DERIVE_SHARED_SECRET: if (maxKeySize > 521) return TEE_ERROR_NOT_SUPPORTED; break; case TEE_ALG_ED25519: case TEE_ALG_X25519: if (maxKeySize != 256) return TEE_ERROR_NOT_SUPPORTED; break; default: break; } /* Check algorithm mode */ switch (algorithm) { case TEE_ALG_AES_CTS: case TEE_ALG_AES_XTS: case TEE_ALG_SM4_XTS: buffer_two_blocks = true; fallthrough; case TEE_ALG_AES_ECB_NOPAD: case TEE_ALG_AES_CBC_NOPAD: case TEE_ALG_AES_CCM: case TEE_ALG_DES_ECB_NOPAD: case TEE_ALG_DES_CBC_NOPAD: case TEE_ALG_DES3_ECB_NOPAD: case TEE_ALG_DES3_CBC_NOPAD: case TEE_ALG_SM4_ECB_NOPAD: case TEE_ALG_SM4_CBC_NOPAD: case TEE_ALG_SM4_CTR: if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_AES) block_size = TEE_AES_BLOCK_SIZE; else if (TEE_ALG_GET_MAIN_ALG(algorithm) == TEE_MAIN_ALGO_SM4) block_size = TEE_SM4_BLOCK_SIZE; else block_size = TEE_DES_BLOCK_SIZE; fallthrough; case TEE_ALG_AES_CTR: case TEE_ALG_AES_GCM: if (mode == TEE_MODE_ENCRYPT) req_key_usage = TEE_USAGE_ENCRYPT; else if (mode == TEE_MODE_DECRYPT) req_key_usage = TEE_USAGE_DECRYPT; else return TEE_ERROR_NOT_SUPPORTED; break; #if defined(CFG_CRYPTO_RSASSA_NA1) case TEE_ALG_RSASSA_PKCS1_V1_5: #endif case TEE_ALG_RSASSA_PKCS1_V1_5_MD5: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384: case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: case TEE_ALG_DSA_SHA1: case TEE_ALG_DSA_SHA224: case TEE_ALG_DSA_SHA256: case TEE_ALG_ECDSA_SHA1: case TEE_ALG_ECDSA_SHA224: case TEE_ALG_ECDSA_SHA256: case TEE_ALG_ECDSA_SHA384: case TEE_ALG_ECDSA_SHA512: case __OPTEE_ALG_ECDSA_P192: case __OPTEE_ALG_ECDSA_P224: case __OPTEE_ALG_ECDSA_P256: case __OPTEE_ALG_ECDSA_P384: case __OPTEE_ALG_ECDSA_P521: case TEE_ALG_SM2_DSA_SM3: case TEE_ALG_ED25519: if (mode == TEE_MODE_SIGN) { with_private_key = true; req_key_usage = TEE_USAGE_SIGN; } else if (mode == TEE_MODE_VERIFY) { req_key_usage = TEE_USAGE_VERIFY; } else { return TEE_ERROR_NOT_SUPPORTED; } break; case TEE_ALG_RSAES_PKCS1_V1_5: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384: case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512: case TEE_ALG_SM2_PKE: if (mode == TEE_MODE_ENCRYPT) { req_key_usage = TEE_USAGE_ENCRYPT; } else if (mode == TEE_MODE_DECRYPT) { with_private_key = true; req_key_usage = TEE_USAGE_DECRYPT; } else { return TEE_ERROR_NOT_SUPPORTED; } break; case TEE_ALG_RSA_NOPAD: if (mode == TEE_MODE_ENCRYPT) { req_key_usage = TEE_USAGE_ENCRYPT | TEE_USAGE_VERIFY; } else if (mode == TEE_MODE_DECRYPT) { with_private_key = true; req_key_usage = TEE_USAGE_DECRYPT | TEE_USAGE_SIGN; } else { return TEE_ERROR_NOT_SUPPORTED; } break; case TEE_ALG_DH_DERIVE_SHARED_SECRET: case TEE_ALG_ECDH_DERIVE_SHARED_SECRET: case __OPTEE_ALG_ECDH_P192: case __OPTEE_ALG_ECDH_P224: case __OPTEE_ALG_ECDH_P256: case __OPTEE_ALG_ECDH_P384: case __OPTEE_ALG_ECDH_P521: case TEE_ALG_HKDF_MD5_DERIVE_KEY: case TEE_ALG_HKDF_SHA1_DERIVE_KEY: case TEE_ALG_HKDF_SHA224_DERIVE_KEY: case TEE_ALG_HKDF_SHA256_DERIVE_KEY: case TEE_ALG_HKDF_SHA384_DERIVE_KEY: case TEE_ALG_HKDF_SHA512_DERIVE_KEY: case TEE_ALG_CONCAT_KDF_SHA1_DERIVE_KEY: case TEE_ALG_CONCAT_KDF_SHA224_DERIVE_KEY: case TEE_ALG_CONCAT_KDF_SHA256_DERIVE_KEY: case TEE_ALG_CONCAT_KDF_SHA384_DERIVE_KEY: case TEE_ALG_CONCAT_KDF_SHA512_DERIVE_KEY: case TEE_ALG_PBKDF2_HMAC_SHA1_DERIVE_KEY: case TEE_ALG_SM2_KEP: case TEE_ALG_X25519: if (mode != TEE_MODE_DERIVE) return TEE_ERROR_NOT_SUPPORTED; with_private_key = true; req_key_usage = TEE_USAGE_DERIVE; break; case TEE_ALG_MD5: case TEE_ALG_SHA1: case TEE_ALG_SHA224: case TEE_ALG_SHA256: case TEE_ALG_SHA384: case TEE_ALG_SHA512: case TEE_ALG_SHA3_224: case TEE_ALG_SHA3_256: case TEE_ALG_SHA3_384: case TEE_ALG_SHA3_512: case TEE_ALG_SHAKE128: case TEE_ALG_SHAKE256: case TEE_ALG_SM3: if (mode != TEE_MODE_DIGEST) return TEE_ERROR_NOT_SUPPORTED; /* v1.1: flags always set for digest operations */ handle_state |= TEE_HANDLE_FLAG_KEY_SET; req_key_usage = 0; break; case TEE_ALG_DES_CBC_MAC_NOPAD: case TEE_ALG_AES_CBC_MAC_NOPAD: case TEE_ALG_AES_CBC_MAC_PKCS5: case TEE_ALG_AES_CMAC: case TEE_ALG_DES_CBC_MAC_PKCS5: case TEE_ALG_DES3_CBC_MAC_NOPAD: case TEE_ALG_DES3_CBC_MAC_PKCS5: case TEE_ALG_DES3_CMAC: case TEE_ALG_HMAC_MD5: case TEE_ALG_HMAC_SHA1: case TEE_ALG_HMAC_SHA224: case TEE_ALG_HMAC_SHA256: case TEE_ALG_HMAC_SHA384: case TEE_ALG_HMAC_SHA512: case TEE_ALG_HMAC_SHA3_224: case TEE_ALG_HMAC_SHA3_256: case TEE_ALG_HMAC_SHA3_384: case TEE_ALG_HMAC_SHA3_512: case TEE_ALG_HMAC_SM3: if (mode != TEE_MODE_MAC) return TEE_ERROR_NOT_SUPPORTED; req_key_usage = TEE_USAGE_MAC; break; default: return TEE_ERROR_NOT_SUPPORTED; } op = TEE_Malloc(sizeof(*op), TEE_MALLOC_FILL_ZERO); if (!op) return TEE_ERROR_OUT_OF_MEMORY; op->info.algorithm = algorithm; op->info.operationClass = TEE_ALG_GET_CLASS(algorithm); #ifdef CFG_CRYPTO_RSASSA_NA1 if (algorithm == TEE_ALG_RSASSA_PKCS1_V1_5) op->info.operationClass = TEE_OPERATION_ASYMMETRIC_SIGNATURE; #endif op->info.mode = mode; op->info.digestLength = TEE_ALG_GET_DIGEST_SIZE(algorithm); op->info.maxKeySize = maxKeySize; op->info.requiredKeyUsage = req_key_usage; op->info.handleState = handle_state; /* * Needed to buffer the digest if TEE_DigestExtract() doesn't * retrieve the entire digest in one go. */ if (op->info.operationClass == TEE_OPERATION_DIGEST) block_size = op->info.digestLength; if (block_size > 1) { size_t buffer_size = block_size; if (buffer_two_blocks) buffer_size *= 2; op->buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (op->buffer == NULL) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } } op->block_size = block_size; op->buffer_two_blocks = buffer_two_blocks; if (TEE_ALG_GET_CLASS(algorithm) != TEE_OPERATION_DIGEST) { uint32_t mks = maxKeySize; TEE_ObjectType key_type = TEE_ALG_GET_KEY_TYPE(algorithm, with_private_key); /* * If two keys are expected the max key size is the sum of * the size of both keys. */ if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) mks /= 2; res = TEE_AllocateTransientObject(key_type, mks, &op->key1); if (res != TEE_SUCCESS) goto out; if (op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { res = TEE_AllocateTransientObject(key_type, mks, &op->key2); if (res != TEE_SUCCESS) goto out; } } res = _utee_cryp_state_alloc(algorithm, mode, (unsigned long)op->key1, (unsigned long)op->key2, &op->state); if (res != TEE_SUCCESS) goto out; /* * Initialize digest operations * Other multi-stage operations initialized w/ TEE_xxxInit functions * Non-applicable on asymmetric operations */ if (TEE_ALG_GET_CLASS(algorithm) == TEE_OPERATION_DIGEST) { res = _utee_hash_init(op->state, NULL, 0); if (res != TEE_SUCCESS) goto out; /* v1.1: flags always set for digest operations */ op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; } op->operationState = TEE_OPERATION_STATE_INITIAL; *operation = op; out: if (res != TEE_SUCCESS) { if (res != TEE_ERROR_OUT_OF_MEMORY && res != TEE_ERROR_NOT_SUPPORTED) TEE_Panic(res); if (op) { if (op->state) { TEE_FreeOperation(op); } else { TEE_Free(op->buffer); TEE_FreeTransientObject(op->key1); TEE_FreeTransientObject(op->key2); TEE_Free(op); } } } return res; } void TEE_FreeOperation(TEE_OperationHandle operation) { TEE_Result res; if (operation == TEE_HANDLE_NULL) return; /* * Note that keys should not be freed here, since they are * claimed by the operation they will be freed by * utee_cryp_state_free(). */ res = _utee_cryp_state_free(operation->state); if (res != TEE_SUCCESS) TEE_Panic(res); TEE_Free(operation->buffer); TEE_Free(operation); } void __GP11_TEE_FreeOperation(TEE_OperationHandle operation) { if (operation == TEE_HANDLE_NULL) TEE_Panic(0); TEE_FreeOperation(operation); } void TEE_GetOperationInfo(TEE_OperationHandle operation, TEE_OperationInfo *operationInfo) { if (operation == TEE_HANDLE_NULL) TEE_Panic(0); __utee_check_out_annotation(operationInfo, sizeof(*operationInfo)); *operationInfo = operation->info; if (operationInfo->handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) { operationInfo->keySize = 0; operationInfo->requiredKeyUsage = 0; } } TEE_Result TEE_GetOperationInfoMultiple(TEE_OperationHandle op, TEE_OperationInfoMultiple *op_info, size_t *size) { TEE_Result res = TEE_SUCCESS; TEE_ObjectInfo kinfo = { }; size_t max_key_count = 0; bool two_keys = false; if (op == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_outbuf_annotation(op_info, size); if (*size < sizeof(*op_info)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } max_key_count = (*size - sizeof(*op_info)) / sizeof(TEE_OperationInfoKey); TEE_MemFill(op_info, 0, *size); /* Two keys flag (TEE_ALG_AES_XTS only) */ two_keys = op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS; if (op->info.mode == TEE_MODE_DIGEST) { op_info->numberOfKeys = 0; } else if (!two_keys) { if (max_key_count < 1) { res = TEE_ERROR_SHORT_BUFFER; goto out; } res = TEE_GetObjectInfo1(op->key1, &kinfo); /* Key1 is not a valid handle, "can't happen". */ if (res) goto out; op_info->keyInformation[0].keySize = kinfo.objectSize; op_info->keyInformation[0].requiredKeyUsage = op->info.requiredKeyUsage; op_info->numberOfKeys = 1; } else { if (max_key_count < 2) { res = TEE_ERROR_SHORT_BUFFER; goto out; } res = TEE_GetObjectInfo1(op->key1, &kinfo); /* Key1 is not a valid handle, "can't happen". */ if (res) goto out; op_info->keyInformation[0].keySize = kinfo.objectSize; op_info->keyInformation[0].requiredKeyUsage = op->info.requiredKeyUsage; res = TEE_GetObjectInfo1(op->key2, &kinfo); /* Key2 is not a valid handle, "can't happen". */ if (res) goto out; op_info->keyInformation[1].keySize = kinfo.objectSize; op_info->keyInformation[1].requiredKeyUsage = op->info.requiredKeyUsage; op_info->numberOfKeys = 2; } op_info->algorithm = op->info.algorithm; op_info->operationClass = op->info.operationClass; op_info->mode = op->info.mode; op_info->digestLength = op->info.digestLength; op_info->maxKeySize = op->info.maxKeySize; op_info->handleState = op->info.handleState; op_info->operationState = op->operationState; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_GetOperationInfoMultiple(TEE_OperationHandle operation, TEE_OperationInfoMultiple *info, uint32_t *operationSize) { TEE_Result res = TEE_SUCCESS; size_t s = 0; __utee_check_gp11_outbuf_annotation(info, operationSize); s = *operationSize; res = TEE_GetOperationInfoMultiple(operation, info, &s); *operationSize = s; return res; } static void reset_operation_state(TEE_OperationHandle op) { op->operationState = TEE_OPERATION_STATE_INITIAL; if (op->info.operationClass == TEE_OPERATION_DIGEST) { TEE_Result res = _utee_hash_init(op->state, NULL, 0); if (res != TEE_SUCCESS) TEE_Panic(res); op->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; } else { op->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; } } void TEE_ResetOperation(TEE_OperationHandle operation) { if (operation == TEE_HANDLE_NULL) TEE_Panic(0); if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET)) TEE_Panic(0); reset_operation_state(operation); } TEE_Result TEE_SetOperationKey(TEE_OperationHandle operation, TEE_ObjectHandle key) { TEE_Result res; uint32_t key_size = 0; TEE_ObjectInfo key_info; if (operation == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (key == TEE_HANDLE_NULL) { /* Operation key cleared */ TEE_ResetTransientObject(operation->key1); operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; if (operation->operationState != TEE_OPERATION_STATE_INITIAL) reset_operation_state(operation); return TEE_SUCCESS; } /* No key for digest operation */ if (operation->info.operationClass == TEE_OPERATION_DIGEST) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* Two keys flag not expected (TEE_ALG_AES_XTS excluded) */ if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) != 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = TEE_GetObjectInfo1(key, &key_info); /* Key is not a valid handle */ if (res != TEE_SUCCESS) goto out; /* Supplied key has to meet required usage */ if ((key_info.objectUsage & operation->info.requiredKeyUsage) != operation->info.requiredKeyUsage) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.maxKeySize < key_info.objectSize) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } key_size = key_info.objectSize; TEE_ResetTransientObject(operation->key1); operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; res = TEE_CopyObjectAttributes1(operation->key1, key); if (res != TEE_SUCCESS) goto out; operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; operation->info.keySize = key_size; if (operation->operationState != TEE_OPERATION_STATE_INITIAL) reset_operation_state(operation); out: if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_STORAGE_NOT_AVAILABLE) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_SetOperationKey(TEE_OperationHandle operation, TEE_ObjectHandle key) { if (operation == TEE_HANDLE_NULL || operation->operationState != TEE_OPERATION_STATE_INITIAL) TEE_Panic(0); return TEE_SetOperationKey(operation, key); } static TEE_Result set_operation_key2(TEE_OperationHandle operation, TEE_ObjectHandle key1, TEE_ObjectHandle key2) { TEE_Result res; uint32_t key_size = 0; TEE_ObjectInfo key_info1; TEE_ObjectInfo key_info2; if (operation == TEE_HANDLE_NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Key1/Key2 and/or are not initialized and * Either both keys are NULL or both are not NULL */ if (!key1 && !key2) { /* Clear the keys */ TEE_ResetTransientObject(operation->key1); TEE_ResetTransientObject(operation->key2); operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; if (operation->operationState != TEE_OPERATION_STATE_INITIAL) reset_operation_state(operation); return TEE_SUCCESS; } else if (!key1 || !key2) { /* Both keys are obviously not valid. */ res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* No key for digest operation */ if (operation->info.operationClass == TEE_OPERATION_DIGEST) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* Two keys flag expected (TEE_ALG_AES_XTS and TEE_ALG_SM2_KEP only) */ if ((operation->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = TEE_GetObjectInfo1(key1, &key_info1); /* Key1 is not a valid handle */ if (res != TEE_SUCCESS) goto out; /* Supplied key has to meet required usage */ if ((key_info1.objectUsage & operation->info. requiredKeyUsage) != operation->info.requiredKeyUsage) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = TEE_GetObjectInfo1(key2, &key_info2); /* Key2 is not a valid handle */ if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) res = TEE_ERROR_CORRUPT_OBJECT_2; goto out; } /* Supplied key has to meet required usage */ if ((key_info2.objectUsage & operation->info. requiredKeyUsage) != operation->info.requiredKeyUsage) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * All the multi key algorithm currently supported requires the keys to * be of equal size. */ if (key_info1.objectSize != key_info2.objectSize) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.maxKeySize < key_info1.objectSize) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Odd that only the size of one key should be reported while * size of two key are used when allocating the operation. */ key_size = key_info1.objectSize; TEE_ResetTransientObject(operation->key1); TEE_ResetTransientObject(operation->key2); operation->info.handleState &= ~TEE_HANDLE_FLAG_KEY_SET; res = TEE_CopyObjectAttributes1(operation->key1, key1); if (res != TEE_SUCCESS) goto out; res = TEE_CopyObjectAttributes1(operation->key2, key2); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_CORRUPT_OBJECT) res = TEE_ERROR_CORRUPT_OBJECT_2; goto out; } operation->info.handleState |= TEE_HANDLE_FLAG_KEY_SET; operation->info.keySize = key_size; if (operation->operationState != TEE_OPERATION_STATE_INITIAL) reset_operation_state(operation); out: if (res != TEE_SUCCESS && res != TEE_ERROR_CORRUPT_OBJECT && res != TEE_ERROR_CORRUPT_OBJECT_2 && res != TEE_ERROR_STORAGE_NOT_AVAILABLE && res != TEE_ERROR_STORAGE_NOT_AVAILABLE_2) TEE_Panic(res); return res; } TEE_Result TEE_SetOperationKey2(TEE_OperationHandle operation, TEE_ObjectHandle key1, TEE_ObjectHandle key2) { if (operation != TEE_HANDLE_NULL && key1 && key1 == key2) return TEE_ERROR_SECURITY; return set_operation_key2(operation, key1, key2); } TEE_Result __GP11_TEE_SetOperationKey2(TEE_OperationHandle operation, TEE_ObjectHandle key1, TEE_ObjectHandle key2) { if (operation == TEE_HANDLE_NULL || operation->operationState != TEE_OPERATION_STATE_INITIAL) TEE_Panic(0); return set_operation_key2(operation, key1, key2); } void TEE_CopyOperation(TEE_OperationHandle dst_op, TEE_OperationHandle src_op) { TEE_Result res; if (dst_op == TEE_HANDLE_NULL || src_op == TEE_HANDLE_NULL) TEE_Panic(0); if (dst_op->info.algorithm != src_op->info.algorithm) TEE_Panic(0); if (dst_op->info.mode != src_op->info.mode) TEE_Panic(0); if (src_op->info.operationClass != TEE_OPERATION_DIGEST) { TEE_ObjectHandle key1 = TEE_HANDLE_NULL; TEE_ObjectHandle key2 = TEE_HANDLE_NULL; if (src_op->info.handleState & TEE_HANDLE_FLAG_KEY_SET) { key1 = src_op->key1; key2 = src_op->key2; } if ((src_op->info.handleState & TEE_HANDLE_FLAG_EXPECT_TWO_KEYS) == 0) { TEE_SetOperationKey(dst_op, key1); } else { TEE_SetOperationKey2(dst_op, key1, key2); } } dst_op->info.handleState = src_op->info.handleState; dst_op->info.keySize = src_op->info.keySize; dst_op->info.digestLength = src_op->info.digestLength; dst_op->operationState = src_op->operationState; if (dst_op->buffer_two_blocks != src_op->buffer_two_blocks || dst_op->block_size != src_op->block_size) TEE_Panic(0); if (dst_op->buffer != NULL) { size_t sz = src_op->block_size; if (src_op->buffer == NULL) TEE_Panic(0); if (src_op->buffer_two_blocks) sz *= 2; memcpy(dst_op->buffer, src_op->buffer, sz); dst_op->buffer_offs = src_op->buffer_offs; } else if (src_op->buffer != NULL) { TEE_Panic(0); } res = _utee_cryp_state_copy(dst_op->state, src_op->state); if (res != TEE_SUCCESS) TEE_Panic(res); } /* Cryptographic Operations API - Message Digest Functions */ static void init_hash_operation(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) { TEE_Result res; /* * Note : IV and IVLen are never used in current implementation * This is why coherent values of IV and IVLen are not checked */ res = _utee_hash_init(operation->state, IV, IVLen); if (res != TEE_SUCCESS) TEE_Panic(res); operation->buffer_offs = 0; operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; } void TEE_DigestUpdate(TEE_OperationHandle operation, const void *chunk, size_t chunkSize) { TEE_Result res = TEE_ERROR_GENERIC; if (operation == TEE_HANDLE_NULL || operation->info.operationClass != TEE_OPERATION_DIGEST) TEE_Panic(0); operation->operationState = TEE_OPERATION_STATE_ACTIVE; res = _utee_hash_update(operation->state, chunk, chunkSize); if (res != TEE_SUCCESS) TEE_Panic(res); } void __GP11_TEE_DigestUpdate(TEE_OperationHandle operation, const void *chunk, uint32_t chunkSize) { return TEE_DigestUpdate(operation, chunk, chunkSize); } TEE_Result TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, size_t chunkLen, void *hash, size_t *hashLen) { TEE_Result res = TEE_SUCCESS; uint64_t hl = 0; size_t len = 0; if ((operation == TEE_HANDLE_NULL) || (!chunk && chunkLen) || (operation->info.operationClass != TEE_OPERATION_DIGEST)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING && chunkLen) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_inout_annotation(hashLen, sizeof(*hashLen)); if (operation->operationState == TEE_OPERATION_STATE_EXTRACTING && operation->buffer) { /* * This is not an Extendable-Output Function and we have * already started extracting */ len = MIN(operation->block_size - operation->buffer_offs, *hashLen); memcpy(hash, operation->buffer + operation->buffer_offs, len); *hashLen = len; } else { hl = *hashLen; res = _utee_hash_final(operation->state, chunk, chunkLen, hash, &hl); *hashLen = hl; if (res) goto out; } /* Reset operation state */ init_hash_operation(operation, NULL, 0); operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_DigestDoFinal(TEE_OperationHandle operation, const void *chunk, uint32_t chunkLen, void *hash, uint32_t *hashLen) { TEE_Result res = TEE_SUCCESS; size_t l = 0; __utee_check_inout_annotation(hashLen, sizeof(*hashLen)); l = *hashLen; res = TEE_DigestDoFinal(operation, chunk, chunkLen, hash, &l); *hashLen = l; return res; } TEE_Result TEE_DigestExtract(TEE_OperationHandle operation, void *hash, size_t *hashLen) { TEE_Result res = TEE_SUCCESS; uint64_t hl = 0; size_t len = 0; if (operation == TEE_HANDLE_NULL || operation->info.operationClass != TEE_OPERATION_DIGEST) TEE_Panic(0); __utee_check_inout_annotation(hashLen, sizeof(*hashLen)); if (!operation->buffer) { /* This is an Extendable-Output Function */ operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING; operation->operationState = TEE_OPERATION_STATE_EXTRACTING; hl = *hashLen; res = _utee_hash_final(operation->state, NULL, 0, hash, &hl); if (res) TEE_Panic(0); *hashLen = hl; return TEE_SUCCESS; } if (operation->operationState != TEE_OPERATION_STATE_EXTRACTING) { hl = operation->block_size; res = _utee_hash_final(operation->state, NULL, 0, operation->buffer, &hl); if (res) TEE_Panic(0); if (hl != operation->block_size) TEE_Panic(0); assert(!operation->buffer_offs); operation->info.handleState |= TEE_HANDLE_FLAG_EXTRACTING; operation->operationState = TEE_OPERATION_STATE_EXTRACTING; } len = MIN(operation->block_size - operation->buffer_offs, *hashLen); memcpy(hash, operation->buffer + operation->buffer_offs, len); *hashLen = len; operation->buffer_offs += len; return TEE_SUCCESS; } /* Cryptographic Operations API - Symmetric Cipher Functions */ void TEE_CipherInit(TEE_OperationHandle operation, const void *IV, size_t IVLen) { TEE_Result res; if (operation == TEE_HANDLE_NULL) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_CIPHER) TEE_Panic(0); if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || !(operation->key1)) TEE_Panic(0); if (operation->operationState != TEE_OPERATION_STATE_INITIAL) TEE_ResetOperation(operation); if (IV && IVLen) { if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD) TEE_Panic(0); } operation->operationState = TEE_OPERATION_STATE_ACTIVE; res = _utee_cipher_init(operation->state, IV, IVLen); if (res != TEE_SUCCESS) TEE_Panic(res); operation->buffer_offs = 0; operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; } void __GP11_TEE_CipherInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) { return TEE_CipherInit(operation, IV, IVLen); } static TEE_Result tee_buffer_update( TEE_OperationHandle op, TEE_Result(*update_func)(unsigned long state, const void *src, size_t slen, void *dst, uint64_t *dlen), const void *src_data, size_t src_len, void *dest_data, uint64_t *dest_len) { TEE_Result res; const uint8_t *src = src_data; size_t slen = src_len; uint8_t *dst = dest_data; size_t dlen = *dest_len; size_t acc_dlen = 0; uint64_t tmp_dlen; size_t l; size_t buffer_size; size_t buffer_left; if (!src) { if (slen) TEE_Panic(0); goto out; } if (op->buffer_two_blocks) { buffer_size = op->block_size * 2; buffer_left = 1; } else { buffer_size = op->block_size; buffer_left = 0; } if (op->buffer_offs > 0) { /* Fill up complete block */ if (op->buffer_offs < op->block_size) l = MIN(slen, op->block_size - op->buffer_offs); else l = MIN(slen, buffer_size - op->buffer_offs); memcpy(op->buffer + op->buffer_offs, src, l); op->buffer_offs += l; src += l; slen -= l; if ((op->buffer_offs % op->block_size) != 0) goto out; /* Nothing left to do */ } /* If we can feed from buffer */ if ((op->buffer_offs > 0) && ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) { l = ROUNDUP(op->buffer_offs + slen - buffer_size, op->block_size); l = MIN(op->buffer_offs, l); /* * If we're buffering only a single block, process it * immediately. */ if (!op->buffer_two_blocks) l = op->block_size; tmp_dlen = dlen; res = update_func(op->state, op->buffer, l, dst, &tmp_dlen); if (res != TEE_SUCCESS) TEE_Panic(res); dst += tmp_dlen; dlen -= tmp_dlen; acc_dlen += tmp_dlen; op->buffer_offs -= l; if (op->buffer_offs > 0) { /* * Slen is small enough to be contained in rest buffer. */ memcpy(op->buffer, op->buffer + l, buffer_size - l); memcpy(op->buffer + op->buffer_offs, src, slen); op->buffer_offs += slen; goto out; /* Nothing left to do */ } } if (slen >= (buffer_size + buffer_left)) { /* Buffer is empty, feed as much as possible from src */ if (op->buffer_two_blocks) l = ROUNDUP(slen - buffer_size, op->block_size); else l = ROUNDUP(slen - buffer_size + 1, op->block_size); tmp_dlen = dlen; res = update_func(op->state, src, l, dst, &tmp_dlen); if (res != TEE_SUCCESS) TEE_Panic(res); src += l; slen -= l; dst += tmp_dlen; dlen -= tmp_dlen; acc_dlen += tmp_dlen; } /* Slen is small enough to be contained in buffer. */ memcpy(op->buffer + op->buffer_offs, src, slen); op->buffer_offs += slen; out: *dest_len = acc_dlen; return TEE_SUCCESS; } TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { TEE_Result res; size_t req_dlen; uint64_t dl; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (operation->info.operationClass != TEE_OPERATION_CIPHER) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (!srcData && !srcLen) { *destLen = 0; res = TEE_SUCCESS; goto out; } /* Calculate required dlen */ if (operation->block_size > 1) { req_dlen = ((operation->buffer_offs + srcLen) / operation->block_size) * operation->block_size; } else { req_dlen = srcLen; } if (operation->buffer_two_blocks) { if (operation->buffer_offs + srcLen > operation->block_size * 2) { req_dlen = operation->buffer_offs + srcLen - operation->block_size * 2; req_dlen = ROUNDUP(req_dlen, operation->block_size); } else { req_dlen = 0; } } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; goto out; } dl = *destLen; if (operation->block_size > 1) { res = tee_buffer_update(operation, _utee_cipher_update, srcData, srcLen, destData, &dl); } else { if (srcLen > 0) { res = _utee_cipher_update(operation->state, srcData, srcLen, destData, &dl); } else { res = TEE_SUCCESS; dl = 0; } } *destLen = dl; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res = TEE_SUCCESS; size_t dl = 0; __utee_check_inout_annotation(destLen, sizeof(*destLen)); dl = *destLen; res = TEE_CipherUpdate(operation, srcData, srcLen, destData, &dl); *destLen = dl; return res; } TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { TEE_Result res = TEE_SUCCESS; uint8_t *dst = destData; size_t acc_dlen = 0; uint64_t tmp_dlen = 0; size_t req_dlen = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (destLen) __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (operation->info.operationClass != TEE_OPERATION_CIPHER) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Check that the final block doesn't require padding for those * algorithms that requires client to supply padding. */ if (operation->info.algorithm == TEE_ALG_AES_ECB_NOPAD || operation->info.algorithm == TEE_ALG_AES_CBC_NOPAD || operation->info.algorithm == TEE_ALG_DES_ECB_NOPAD || operation->info.algorithm == TEE_ALG_DES_CBC_NOPAD || operation->info.algorithm == TEE_ALG_DES3_ECB_NOPAD || operation->info.algorithm == TEE_ALG_DES3_CBC_NOPAD || operation->info.algorithm == TEE_ALG_SM4_ECB_NOPAD || operation->info.algorithm == TEE_ALG_SM4_CBC_NOPAD) { if (((operation->buffer_offs + srcLen) % operation->block_size) != 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ if (operation->block_size > 1) { req_dlen = operation->buffer_offs + srcLen; } else { req_dlen = srcLen; } if (destLen) tmp_dlen = *destLen; if (tmp_dlen < req_dlen) { if (destLen) *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; goto out; } if (operation->block_size > 1) { if (srcLen) { res = tee_buffer_update(operation, _utee_cipher_update, srcData, srcLen, dst, &tmp_dlen); if (res != TEE_SUCCESS) goto out; dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; } res = _utee_cipher_final(operation->state, operation->buffer, operation->buffer_offs, dst, &tmp_dlen); } else { res = _utee_cipher_final(operation->state, srcData, srcLen, dst, &tmp_dlen); } if (res != TEE_SUCCESS) goto out; acc_dlen += tmp_dlen; if (destLen) *destLen = acc_dlen; operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_CipherDoFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res = TEE_SUCCESS; size_t dl = 0; if (destLen) { __utee_check_inout_annotation(destLen, sizeof(*destLen)); dl = *destLen; } res = TEE_CipherDoFinal(operation, srcData, srcLen, destData, &dl); if (destLen) *destLen = dl; return res; } /* Cryptographic Operations API - MAC Functions */ void TEE_MACInit(TEE_OperationHandle operation, const void *IV, size_t IVLen) { if (operation == TEE_HANDLE_NULL) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_MAC) TEE_Panic(0); if (!(operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) || !(operation->key1)) TEE_Panic(0); if (operation->operationState != TEE_OPERATION_STATE_INITIAL) TEE_ResetOperation(operation); operation->operationState = TEE_OPERATION_STATE_ACTIVE; init_hash_operation(operation, IV, IVLen); } void __GP11_TEE_MACInit(TEE_OperationHandle operation, const void *IV, uint32_t IVLen) { return TEE_MACInit(operation, IV, IVLen); } void TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, size_t chunkSize) { TEE_Result res; if (operation == TEE_HANDLE_NULL || (chunk == NULL && chunkSize != 0)) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_MAC) TEE_Panic(0); if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) TEE_Panic(0); res = _utee_hash_update(operation->state, chunk, chunkSize); if (res != TEE_SUCCESS) TEE_Panic(res); } void __GP11_TEE_MACUpdate(TEE_OperationHandle operation, const void *chunk, uint32_t chunkSize) { return TEE_MACUpdate(operation, chunk, chunkSize); } TEE_Result TEE_MACComputeFinal(TEE_OperationHandle operation, const void *message, size_t messageLen, void *mac, size_t *macLen) { TEE_Result res; uint64_t ml; if (operation == TEE_HANDLE_NULL || (!message && messageLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_inout_annotation(macLen, sizeof(*macLen)); if (operation->info.operationClass != TEE_OPERATION_MAC) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } ml = *macLen; res = _utee_hash_final(operation->state, message, messageLen, mac, &ml); *macLen = ml; if (res != TEE_SUCCESS) goto out; operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_MACComputeFinal(TEE_OperationHandle operation, const void *message, uint32_t messageLen, void *mac, uint32_t *macLen) { TEE_Result res = TEE_SUCCESS; size_t ml = 0; __utee_check_inout_annotation(macLen, sizeof(*macLen)); ml = *macLen; res = TEE_MACComputeFinal(operation, message, messageLen, mac, &ml); *macLen = ml; return res; } TEE_Result TEE_MACCompareFinal(TEE_OperationHandle operation, const void *message, size_t messageLen, const void *mac, size_t macLen) { TEE_Result res; uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 }; size_t computed_mac_size = TEE_MAX_HASH_SIZE; if (operation->info.operationClass != TEE_OPERATION_MAC) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState != TEE_OPERATION_STATE_ACTIVE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = TEE_MACComputeFinal(operation, message, messageLen, computed_mac, &computed_mac_size); if (res != TEE_SUCCESS) goto out; if (computed_mac_size != macLen) { res = TEE_ERROR_MAC_INVALID; goto out; } if (consttime_memcmp(mac, computed_mac, computed_mac_size) != 0) { res = TEE_ERROR_MAC_INVALID; goto out; } operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_MAC_INVALID) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_MACCompareFinal(TEE_OperationHandle operation, const void *message, uint32_t messageLen, const void *mac, uint32_t macLen) { return TEE_MACCompareFinal(operation, message, messageLen, mac, macLen); } /* Cryptographic Operations API - Authenticated Encryption Functions */ TEE_Result TEE_AEInit(TEE_OperationHandle operation, const void *nonce, size_t nonceLen, uint32_t tagLen, size_t AADLen, size_t payloadLen) { TEE_Result res; if (operation == TEE_HANDLE_NULL || nonce == NULL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (operation->operationState != TEE_OPERATION_STATE_INITIAL) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * AES-CCM tag len is specified by AES-CCM spec and handled in TEE Core * in the implementation. But AES-GCM spec doesn't specify the tag len * according to the same principle so we have to check here instead to * be GP compliant. */ if (operation->info.algorithm == TEE_ALG_AES_GCM) { /* * From GP spec: For AES-GCM, can be 128, 120, 112, 104, or 96 */ if (tagLen < 96 || tagLen > 128 || (tagLen % 8 != 0)) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } } res = _utee_authenc_init(operation->state, nonce, nonceLen, tagLen / 8, AADLen, payloadLen); if (res != TEE_SUCCESS) goto out; operation->info.digestLength = tagLen / 8; operation->buffer_offs = 0; operation->info.handleState |= TEE_HANDLE_FLAG_INITIALIZED; out: if (res != TEE_SUCCESS && res != TEE_ERROR_NOT_SUPPORTED) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AEInit(TEE_OperationHandle operation, const void *nonce, uint32_t nonceLen, uint32_t tagLen, uint32_t AADLen, uint32_t payloadLen) { return TEE_AEInit(operation, nonce, nonceLen, tagLen, AADLen, payloadLen); } void TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, size_t AADdataLen) { TEE_Result res = TEE_SUCCESS; if (operation == TEE_HANDLE_NULL || (!AADdata && AADdataLen)) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_AE) TEE_Panic(0); if (operation->operationState != TEE_OPERATION_STATE_INITIAL) TEE_Panic(0); if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen); if (res != TEE_SUCCESS) TEE_Panic(res); } void __GP11_TEE_AEUpdateAAD(TEE_OperationHandle operation, const void *AADdata, uint32_t AADdataLen) { TEE_Result res = TEE_SUCCESS; if (operation == TEE_HANDLE_NULL || (AADdata == NULL && AADdataLen != 0)) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_AE) TEE_Panic(0); if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) TEE_Panic(0); res = _utee_authenc_update_aad(operation->state, AADdata, AADdataLen); operation->operationState = TEE_OPERATION_STATE_ACTIVE; if (res != TEE_SUCCESS) TEE_Panic(res); } static TEE_Result ae_update_helper(TEE_OperationHandle operation, const void *src, size_t slen, void *dst, size_t *dlen) { TEE_Result res = TEE_SUCCESS; size_t req_dlen = 0; uint64_t dl = 0; if (!src && !slen) { *dlen = 0; return TEE_SUCCESS; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ if (operation->block_size > 1) { req_dlen = ROUNDDOWN(operation->buffer_offs + slen, operation->block_size); } else { req_dlen = slen; } dl = *dlen; if (dl < req_dlen) { *dlen = req_dlen; return TEE_ERROR_SHORT_BUFFER; } if (operation->block_size > 1) { res = tee_buffer_update(operation, _utee_authenc_update_payload, src, slen, dst, &dl); } else { if (slen > 0) { res = _utee_authenc_update_payload(operation->state, src, slen, dst, &dl); } else { dl = 0; res = TEE_SUCCESS; } } if (!res) *dlen = dl; return res; } TEE_Result TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { TEE_Result res = TEE_SUCCESS; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_outbuf_annotation(destData, destLen); if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = ae_update_helper(operation, srcData, srcLen, destData, destLen); if (res != TEE_ERROR_SHORT_BUFFER && srcLen) operation->operationState = TEE_OPERATION_STATE_ACTIVE; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AEUpdate(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res = TEE_SUCCESS; size_t dl = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_gp11_outbuf_annotation(destData, destLen); if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } dl = *destLen; res = ae_update_helper(operation, srcData, srcLen, destData, &dl); *destLen = dl; if (res != TEE_SUCCESS) goto out; operation->operationState = TEE_OPERATION_STATE_ACTIVE; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result TEE_AEEncryptFinal(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen, void *tag, size_t *tagLen) { TEE_Result res = TEE_SUCCESS; uint8_t *dst = destData; size_t acc_dlen = 0; uint64_t tmp_dlen = 0; size_t req_dlen = 0; uint64_t tl = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_inout_annotation(destLen, sizeof(*destLen)); __utee_check_inout_annotation(tagLen, sizeof(*tagLen)); if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. * * Need to check this before update_payload since sync would be lost if * we return short buffer after that. */ res = TEE_ERROR_GENERIC; req_dlen = operation->buffer_offs + srcLen; if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; } if (*tagLen < operation->info.digestLength) { *tagLen = operation->info.digestLength; res = TEE_ERROR_SHORT_BUFFER; } if (res == TEE_ERROR_SHORT_BUFFER) goto out; tl = *tagLen; tmp_dlen = *destLen - acc_dlen; if (operation->block_size > 1) { res = tee_buffer_update(operation, _utee_authenc_update_payload, srcData, srcLen, dst, &tmp_dlen); if (res != TEE_SUCCESS) goto out; dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; res = _utee_authenc_enc_final(operation->state, operation->buffer, operation->buffer_offs, dst, &tmp_dlen, tag, &tl); } else { res = _utee_authenc_enc_final(operation->state, srcData, srcLen, dst, &tmp_dlen, tag, &tl); } *tagLen = tl; if (res != TEE_SUCCESS) goto out; acc_dlen += tmp_dlen; *destLen = acc_dlen; operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AEEncryptFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen, void *tag, uint32_t *tagLen) { TEE_Result res = TEE_SUCCESS; size_t dl = 0; size_t tl = 0; __utee_check_inout_annotation(destLen, sizeof(*destLen)); __utee_check_inout_annotation(tagLen, sizeof(*tagLen)); dl = *destLen; tl = *tagLen; res = TEE_AEEncryptFinal(operation, srcData, srcLen, destData, &dl, tag, &tl); *destLen = dl; *tagLen = tl; return res; } TEE_Result TEE_AEDecryptFinal(TEE_OperationHandle operation, const void *srcData, size_t srcLen, void *destData, size_t *destLen, void *tag, size_t tagLen) { TEE_Result res = TEE_SUCCESS; uint8_t *dst = destData; size_t acc_dlen = 0; uint64_t tmp_dlen = 0; size_t req_dlen = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (operation->info.operationClass != TEE_OPERATION_AE) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if ((operation->info.handleState & TEE_HANDLE_FLAG_INITIALIZED) == 0) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* * Check that required destLen is big enough before starting to feed * data to the algorithm. Errors during feeding of data are fatal as we * can't restore sync with this API. */ req_dlen = operation->buffer_offs + srcLen; if (*destLen < req_dlen) { *destLen = req_dlen; res = TEE_ERROR_SHORT_BUFFER; goto out; } tmp_dlen = *destLen - acc_dlen; if (operation->block_size > 1) { res = tee_buffer_update(operation, _utee_authenc_update_payload, srcData, srcLen, dst, &tmp_dlen); if (res != TEE_SUCCESS) goto out; dst += tmp_dlen; acc_dlen += tmp_dlen; tmp_dlen = *destLen - acc_dlen; res = _utee_authenc_dec_final(operation->state, operation->buffer, operation->buffer_offs, dst, &tmp_dlen, tag, tagLen); } else { res = _utee_authenc_dec_final(operation->state, srcData, srcLen, dst, &tmp_dlen, tag, tagLen); } if (res != TEE_SUCCESS) goto out; /* Supplied tagLen should match what we initiated with */ if (tagLen != operation->info.digestLength) res = TEE_ERROR_MAC_INVALID; acc_dlen += tmp_dlen; *destLen = acc_dlen; operation->info.handleState &= ~TEE_HANDLE_FLAG_INITIALIZED; operation->operationState = TEE_OPERATION_STATE_INITIAL; out: if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_MAC_INVALID) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AEDecryptFinal(TEE_OperationHandle operation, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen, void *tag, uint32_t tagLen) { TEE_Result res = TEE_SUCCESS; size_t dl = 0; __utee_check_inout_annotation(destLen, sizeof(*destLen)); dl = *destLen; res = TEE_AEDecryptFinal(operation, srcData, srcLen, destData, &dl, tag, tagLen); *destLen = dl; return res; } /* Cryptographic Operations API - Asymmetric Functions */ TEE_Result TEE_AsymmetricEncrypt(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; uint64_t dl = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) TEE_Panic(0); __utee_check_attr_in_annotation(params, paramCount); __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) TEE_Panic(0); if (operation->info.mode != TEE_MODE_ENCRYPT) TEE_Panic(0); __utee_from_attr(ua, params, paramCount); dl = *destLen; res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, srcLen, destData, &dl); *destLen = dl; if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_BAD_PARAMETERS && res != TEE_ERROR_CIPHERTEXT_INVALID && res != TEE_ERROR_NOT_SUPPORTED) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AsymmetricEncrypt(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; uint64_t dl = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) TEE_Panic(0); __utee_check_gp11_attr_in_annotation(params, paramCount); __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) TEE_Panic(0); if (operation->info.mode != TEE_MODE_ENCRYPT) TEE_Panic(0); __utee_from_gp11_attr(ua, params, paramCount); dl = *destLen; res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, srcLen, destData, &dl); *destLen = dl; if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_BAD_PARAMETERS) TEE_Panic(res); return res; } TEE_Result TEE_AsymmetricDecrypt(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *srcData, size_t srcLen, void *destData, size_t *destLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; uint64_t dl = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) TEE_Panic(0); __utee_check_attr_in_annotation(params, paramCount); __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) TEE_Panic(0); if (operation->info.mode != TEE_MODE_DECRYPT) TEE_Panic(0); __utee_from_attr(ua, params, paramCount); dl = *destLen; res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, srcLen, destData, &dl); *destLen = dl; if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_BAD_PARAMETERS && res != TEE_ERROR_CIPHERTEXT_INVALID && res != TEE_ERROR_NOT_SUPPORTED) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AsymmetricDecrypt(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *srcData, uint32_t srcLen, void *destData, uint32_t *destLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; uint64_t dl = 0; if (operation == TEE_HANDLE_NULL || (!srcData && srcLen)) TEE_Panic(0); __utee_check_gp11_attr_in_annotation(params, paramCount); __utee_check_inout_annotation(destLen, sizeof(*destLen)); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_CIPHER) TEE_Panic(0); if (operation->info.mode != TEE_MODE_DECRYPT) TEE_Panic(0); __utee_from_gp11_attr(ua, params, paramCount); dl = *destLen; res = _utee_asymm_operate(operation->state, ua, paramCount, srcData, srcLen, destData, &dl); *destLen = dl; if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER && res != TEE_ERROR_BAD_PARAMETERS) TEE_Panic(res); return res; } TEE_Result TEE_AsymmetricSignDigest(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *digest, size_t digestLen, void *signature, size_t *signatureLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; uint64_t sl = 0; if (operation == TEE_HANDLE_NULL || (!digest && digestLen)) TEE_Panic(0); __utee_check_attr_in_annotation(params, paramCount); __utee_check_inout_annotation(signatureLen, sizeof(*signatureLen)); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) TEE_Panic(0); if (operation->info.mode != TEE_MODE_SIGN) TEE_Panic(0); __utee_from_attr(ua, params, paramCount); sl = *signatureLen; res = _utee_asymm_operate(operation->state, ua, paramCount, digest, digestLen, signature, &sl); *signatureLen = sl; if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AsymmetricSignDigest(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *digest, uint32_t digestLen, void *signature, uint32_t *signatureLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; uint64_t sl = 0; if (operation == TEE_HANDLE_NULL || (!digest && digestLen)) TEE_Panic(0); __utee_check_gp11_attr_in_annotation(params, paramCount); __utee_check_inout_annotation(signatureLen, sizeof(*signatureLen)); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) TEE_Panic(0); if (operation->info.mode != TEE_MODE_SIGN) TEE_Panic(0); __utee_from_gp11_attr(ua, params, paramCount); sl = *signatureLen; res = _utee_asymm_operate(operation->state, ua, paramCount, digest, digestLen, signature, &sl); *signatureLen = sl; if (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(res); return res; } TEE_Result TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, const void *digest, size_t digestLen, const void *signature, size_t signatureLen) { TEE_Result res; struct utee_attribute ua[paramCount]; if (operation == TEE_HANDLE_NULL || (digest == NULL && digestLen != 0) || (signature == NULL && signatureLen != 0)) TEE_Panic(0); __utee_check_attr_in_annotation(params, paramCount); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) TEE_Panic(0); if (operation->info.mode != TEE_MODE_VERIFY) TEE_Panic(0); __utee_from_attr(ua, params, paramCount); res = _utee_asymm_verify(operation->state, ua, paramCount, digest, digestLen, signature, signatureLen); if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) TEE_Panic(res); return res; } TEE_Result __GP11_TEE_AsymmetricVerifyDigest(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, const void *digest, uint32_t digestLen, const void *signature, uint32_t signatureLen) { TEE_Result res = TEE_SUCCESS; struct utee_attribute ua[paramCount]; if (operation == TEE_HANDLE_NULL || (!digest && digestLen) || (!signature && signatureLen)) TEE_Panic(0); __utee_check_gp11_attr_in_annotation(params, paramCount); if (!operation->key1) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_ASYMMETRIC_SIGNATURE) TEE_Panic(0); if (operation->info.mode != TEE_MODE_VERIFY) TEE_Panic(0); __utee_from_gp11_attr(ua, params, paramCount); res = _utee_asymm_verify(operation->state, ua, paramCount, digest, digestLen, signature, signatureLen); if (res != TEE_SUCCESS && res != TEE_ERROR_SIGNATURE_INVALID) TEE_Panic(res); return res; } /* Cryptographic Operations API - Key Derivation Functions */ void TEE_DeriveKey(TEE_OperationHandle operation, const TEE_Attribute *params, uint32_t paramCount, TEE_ObjectHandle derivedKey) { struct utee_attribute ua[paramCount]; struct utee_object_info key_info = { }; TEE_Result res = TEE_SUCCESS; if (operation == TEE_HANDLE_NULL || derivedKey == 0) TEE_Panic(0); __utee_check_attr_in_annotation(params, paramCount); if (TEE_ALG_GET_CLASS(operation->info.algorithm) != TEE_OPERATION_KEY_DERIVATION) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) TEE_Panic(0); if (!operation->key1) TEE_Panic(0); if (operation->info.mode != TEE_MODE_DERIVE) TEE_Panic(0); if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) TEE_Panic(0); res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info); if (res != TEE_SUCCESS) TEE_Panic(res); if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET) TEE_Panic(0); if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) TEE_Panic(0); __utee_from_attr(ua, params, paramCount); res = _utee_cryp_derive_key(operation->state, ua, paramCount, (unsigned long)derivedKey); if (res != TEE_SUCCESS) TEE_Panic(res); } void __GP11_TEE_DeriveKey(TEE_OperationHandle operation, const __GP11_TEE_Attribute *params, uint32_t paramCount, TEE_ObjectHandle derivedKey) { struct utee_attribute ua[paramCount]; struct utee_object_info key_info = { }; TEE_Result res = TEE_SUCCESS; if (operation == TEE_HANDLE_NULL || derivedKey == 0) TEE_Panic(0); __utee_check_gp11_attr_in_annotation(params, paramCount); if (TEE_ALG_GET_CLASS(operation->info.algorithm) != TEE_OPERATION_KEY_DERIVATION) TEE_Panic(0); if (operation->info.operationClass != TEE_OPERATION_KEY_DERIVATION) TEE_Panic(0); if (!operation->key1) TEE_Panic(0); if (operation->info.mode != TEE_MODE_DERIVE) TEE_Panic(0); if ((operation->info.handleState & TEE_HANDLE_FLAG_KEY_SET) == 0) TEE_Panic(0); res = _utee_cryp_obj_get_info((unsigned long)derivedKey, &key_info); if (res != TEE_SUCCESS) TEE_Panic(res); if (key_info.obj_type != TEE_TYPE_GENERIC_SECRET) TEE_Panic(0); if ((key_info.handle_flags & TEE_HANDLE_FLAG_INITIALIZED) != 0) TEE_Panic(0); __utee_from_gp11_attr(ua, params, paramCount); res = _utee_cryp_derive_key(operation->state, ua, paramCount, (unsigned long)derivedKey); if (res != TEE_SUCCESS) TEE_Panic(res); } /* Cryptographic Operations API - Random Number Generation Functions */ void TEE_GenerateRandom(void *randomBuffer, size_t randomBufferLen) { TEE_Result res; res = _utee_cryp_random_number_generate(randomBuffer, randomBufferLen); if (res != TEE_SUCCESS) TEE_Panic(res); } void __GP11_TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen) { TEE_GenerateRandom(randomBuffer, randomBufferLen); } int rand(void) { int rc; TEE_GenerateRandom(&rc, sizeof(rc)); /* * RAND_MAX is the larges int, INT_MAX which is all bits but the * highest bit set. */ return rc & RAND_MAX; } TEE_Result TEE_IsAlgorithmSupported(uint32_t alg, uint32_t element) { if (IS_ENABLED(CFG_CRYPTO_AES)) { if (IS_ENABLED(CFG_CRYPTO_ECB)) { if (alg == TEE_ALG_AES_ECB_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CBC)) { if (alg == TEE_ALG_AES_CBC_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CTR)) { if (alg == TEE_ALG_AES_CTR) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CTS)) { if (alg == TEE_ALG_AES_CTS) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_XTS)) { if (alg == TEE_ALG_AES_XTS) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) { if (alg == TEE_ALG_AES_CBC_MAC_NOPAD || alg == TEE_ALG_AES_CBC_MAC_PKCS5) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CMAC)) { if (alg == TEE_ALG_AES_CMAC) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CCM)) { if (alg == TEE_ALG_AES_CCM) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_GCM)) { if (alg == TEE_ALG_AES_GCM) goto check_element_none; } } if (IS_ENABLED(CFG_CRYPTO_DES)) { if (IS_ENABLED(CFG_CRYPTO_ECB)) { if (alg == TEE_ALG_DES_ECB_NOPAD || alg == TEE_ALG_DES3_ECB_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CBC)) { if (alg == TEE_ALG_DES_CBC_NOPAD || alg == TEE_ALG_DES3_CBC_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CBC_MAC)) { if (alg == TEE_ALG_DES_CBC_MAC_NOPAD || alg == TEE_ALG_DES_CBC_MAC_PKCS5 || alg == TEE_ALG_DES3_CBC_MAC_NOPAD || alg == TEE_ALG_DES3_CBC_MAC_PKCS5) goto check_element_none; } } if (IS_ENABLED(CFG_CRYPTO_MD5)) { if (alg == TEE_ALG_MD5) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA1)) { if (alg == TEE_ALG_SHA1) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA224)) { if (alg == TEE_ALG_SHA224) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA256)) { if (alg == TEE_ALG_SHA256) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA384)) { if (alg == TEE_ALG_SHA384) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA512)) { if (alg == TEE_ALG_SHA512) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) { if (alg == TEE_ALG_SHA3_224) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) { if (alg == TEE_ALG_SHA3_256) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) { if (alg == TEE_ALG_SHA3_384) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) { if (alg == TEE_ALG_SHA3_512) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) { if (alg == TEE_ALG_MD5SHA1) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_HMAC)) { if (IS_ENABLED(CFG_CRYPTO_MD5)) { if (alg == TEE_ALG_HMAC_MD5) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA1)) { if (alg == TEE_ALG_HMAC_SHA1) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA224)) { if (alg == TEE_ALG_HMAC_SHA224) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA256)) { if (alg == TEE_ALG_HMAC_SHA256) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA384)) { if (alg == TEE_ALG_HMAC_SHA384) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA512)) { if (alg == TEE_ALG_HMAC_SHA512) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_224)) { if (alg == TEE_ALG_HMAC_SHA3_224) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_256)) { if (alg == TEE_ALG_HMAC_SHA3_256) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_384)) { if (alg == TEE_ALG_HMAC_SHA3_384) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA3_512)) { if (alg == TEE_ALG_HMAC_SHA3_512) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SM3)) { if (alg == TEE_ALG_HMAC_SM3) goto check_element_none; } } if (IS_ENABLED(CFG_CRYPTO_SM3)) { if (alg == TEE_ALG_SM3) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SM4)) { if (IS_ENABLED(CFG_CRYPTO_ECB)) { if (alg == TEE_ALG_SM4_ECB_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CBC)) { if (alg == TEE_ALG_SM4_CBC_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_CTR)) { if (alg == TEE_ALG_SM4_CTR) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_XTS)) { if (alg == TEE_ALG_SM4_XTS) goto check_element_none; } } if (IS_ENABLED(CFG_CRYPTO_RSA)) { if (IS_ENABLED(CFG_CRYPTO_MD5)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5 || alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5 || alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA1)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA1 || alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1 || alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_MD5) && IS_ENABLED(CFG_CRYPTO_SHA1)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_MD5SHA1) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA224)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA224 || alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224 || alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA256)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 || alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256 || alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA384)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA384 || alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384 || alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA512)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5_SHA512 || alg == TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512 || alg == TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_RSASSA_NA1)) { if (alg == TEE_ALG_RSASSA_PKCS1_V1_5) goto check_element_none; } if (alg == TEE_ALG_RSA_NOPAD) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_DSA)) { if (IS_ENABLED(CFG_CRYPTO_SHA1)) { if (alg == TEE_ALG_DSA_SHA1) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA224)) { if (alg == TEE_ALG_DSA_SHA224) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_SHA256)) { if (alg == TEE_ALG_DSA_SHA256) goto check_element_none; } } if (IS_ENABLED(CFG_CRYPTO_DH)) { if (alg == TEE_ALG_DH_DERIVE_SHARED_SECRET) goto check_element_none; } if (IS_ENABLED(CFG_CRYPTO_ECC)) { if ((alg == __OPTEE_ALG_ECDH_P192 || alg == __OPTEE_ALG_ECDSA_P192 || alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || alg == TEE_ALG_ECDSA_SHA1) && element == TEE_ECC_CURVE_NIST_P192) return TEE_SUCCESS; if ((alg == __OPTEE_ALG_ECDH_P224 || alg == __OPTEE_ALG_ECDSA_P224 || alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || alg == TEE_ALG_ECDSA_SHA224) && element == TEE_ECC_CURVE_NIST_P224) return TEE_SUCCESS; if ((alg == __OPTEE_ALG_ECDH_P256 || alg == __OPTEE_ALG_ECDSA_P256 || alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || alg == TEE_ALG_ECDSA_SHA256) && element == TEE_ECC_CURVE_NIST_P256) return TEE_SUCCESS; if ((alg == __OPTEE_ALG_ECDH_P384 || alg == __OPTEE_ALG_ECDSA_P384 || alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || alg == TEE_ALG_ECDSA_SHA384) && element == TEE_ECC_CURVE_NIST_P384) return TEE_SUCCESS; if ((alg == __OPTEE_ALG_ECDH_P521 || alg == __OPTEE_ALG_ECDSA_P521 || alg == TEE_ALG_ECDH_DERIVE_SHARED_SECRET || alg == TEE_ALG_ECDSA_SHA512) && element == TEE_ECC_CURVE_NIST_P521) return TEE_SUCCESS; } if (IS_ENABLED(CFG_CRYPTO_SM2_DSA)) { if (alg == TEE_ALG_SM2_DSA_SM3 && element == TEE_ECC_CURVE_SM2) return TEE_SUCCESS; } if (IS_ENABLED(CFG_CRYPTO_SM2_KEP)) { if (alg == TEE_ALG_SM2_KEP && element == TEE_ECC_CURVE_SM2) return TEE_SUCCESS; } if (IS_ENABLED(CFG_CRYPTO_SM2_PKE)) { if (alg == TEE_ALG_SM2_PKE && element == TEE_ECC_CURVE_SM2) return TEE_SUCCESS; } if (IS_ENABLED(CFG_CRYPTO_X25519)) { if (alg == TEE_ALG_X25519 && element == TEE_ECC_CURVE_25519) return TEE_SUCCESS; } if (IS_ENABLED(CFG_CRYPTO_ED25519)) { if (alg == TEE_ALG_ED25519 && element == TEE_ECC_CURVE_25519) return TEE_SUCCESS; } return TEE_ERROR_NOT_SUPPORTED; check_element_none: if (element == TEE_CRYPTO_ELEMENT_NONE) return TEE_SUCCESS; return TEE_ERROR_NOT_SUPPORTED; } optee_os-4.3.0/lib/libutee/tee_api_panic.c000066400000000000000000000052441464416617300204770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Linaro Limited */ #include #include #include #include #include #include "tee_api_private.h" #define ACCESS_RW (TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_WRITE) #define ACCESS_W_ANY (TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER) #define ACCESS_R TEE_MEMORY_ACCESS_READ #define ACCESS_W TEE_MEMORY_ACCESS_WRITE /* System API - Misc */ void TEE_Panic(TEE_Result panicCode) { _utee_panic(panicCode); #ifdef __COVERITY__ __coverity_panic__(); #endif } static void check_res(const char *msg __maybe_unused, TEE_Result res) { if (res) { DMSG("%s: error %#"PRIx32, msg, res); TEE_Panic(0); } } static TEE_Result check_access(uint32_t flags, void *buf, size_t len) { if (!len) return TEE_SUCCESS; if (!buf) return TEE_ERROR_SECURITY; if (IS_ENABLED(CFG_TA_STRICT_ANNOTATION_CHECKS)) return TEE_CheckMemoryAccessRights(flags, buf, len); return TEE_SUCCESS; } void __utee_check_outbuf_annotation(void *buf, size_t *len) { check_res("[outbuf] len", check_access(ACCESS_RW, len, sizeof(*len))); check_res("[outbuf] buf", check_access(ACCESS_W_ANY, buf, *len)); } void __utee_check_gp11_outbuf_annotation(void *buf, uint32_t *len) { check_res("[outbuf] len", check_access(ACCESS_RW, len, sizeof(*len))); check_res("[outbuf] buf", check_access(ACCESS_W_ANY, buf, *len)); } void __utee_check_instring_annotation(const char *buf) { check_res("[instring]", check_access(ACCESS_R, (char *)buf, strlen(buf) + 1)); } void __utee_check_outstring_annotation(char *buf, size_t *len) { check_res("[outstring] len", check_access(ACCESS_RW, len, sizeof(*len))); check_res("[outstring] buf", check_access(ACCESS_W_ANY, buf, *len)); } void __utee_check_gp11_outstring_annotation(char *buf, uint32_t *len) { check_res("[outstring] len", check_access(ACCESS_RW, len, sizeof(*len))); check_res("[outstring] buf", check_access(ACCESS_W_ANY, buf, *len)); } void __utee_check_out_annotation(void *buf, const size_t len) { check_res("[out]", check_access(ACCESS_W, buf, len)); } void __utee_check_attr_in_annotation(const TEE_Attribute *attr, size_t count) { check_res("[in] attr", check_access(ACCESS_R, (void *)attr, sizeof(*attr) * count)); } void __utee_check_gp11_attr_in_annotation(const __GP11_TEE_Attribute *attr, size_t count) { check_res("[in] attr", check_access(ACCESS_R, (void *)attr, sizeof(*attr) * count)); } void __utee_check_inout_annotation(void *buf, const size_t len) { check_res("[inout]", check_access(ACCESS_RW, buf, len)); } optee_os-4.3.0/lib/libutee/tee_api_private.h000066400000000000000000000030411464416617300210550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2020, Linaro Limited */ #ifndef TEE_API_PRIVATE #define TEE_API_PRIVATE #include #include void __utee_from_attr(struct utee_attribute *ua, const TEE_Attribute *attrs, uint32_t attr_count); void __utee_from_gp11_attr(struct utee_attribute *ua, const __GP11_TEE_Attribute *attrs, uint32_t attr_count); TEE_Result __utee_entry(unsigned long func, unsigned long session_id, struct utee_params *up, unsigned long cmd_id); #if defined(CFG_TA_GPROF_SUPPORT) void __utee_gprof_init(void); void __utee_gprof_fini(void); #else static inline void __utee_gprof_init(void) {} static inline void __utee_gprof_fini(void) {} #endif /* * The functions help checking that the pointers comply with the parameters * annotation as described in the spec. Any descrepency results in a panic * of the TA. */ void __utee_check_out_annotation(void *buf, const size_t len); void __utee_check_inout_annotation(void *buf, const size_t len); void __utee_check_attr_in_annotation(const TEE_Attribute *attr, size_t count); void __utee_check_gp11_attr_in_annotation(const __GP11_TEE_Attribute *attr, size_t count); void __utee_check_outbuf_annotation(void *buf, size_t *len); void __utee_check_gp11_outbuf_annotation(void *buf, uint32_t *len); void __utee_check_instring_annotation(const char *buf); void __utee_check_outstring_annotation(char *buf, size_t *len); void __utee_check_gp11_outstring_annotation(char *buf, uint32_t *len); #endif /*TEE_API_PRIVATE*/ optee_os-4.3.0/lib/libutee/tee_api_property.c000066400000000000000000000357141464416617300212760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "base64.h" #include "string_ext.h" #include "tee_api_private.h" #define PROP_STR_MAX 80 #define PROP_ENUMERATOR_NOT_STARTED 0xffffffff struct prop_enumerator { uint32_t idx; /* current index */ TEE_PropSetHandle prop_set; /* part of TEE_PROPSET_xxx */ }; const struct user_ta_property tee_props[] = { { "gpd.tee.arith.maxBigIntSize", USER_TA_PROP_TYPE_U32, &(const uint32_t){CFG_TA_BIGNUM_MAX_BITS} }, { "gpd.tee.sockets.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){TEE_ISOCKET_VERSION} }, { "gpd.tee.sockets.tcp.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){TEE_ISOCKET_VERSION} }, { "gpd.tee.internalCore.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){TEE_CORE_API_VERSION} }, }; static TEE_Result propset_get(TEE_PropSetHandle h, const struct user_ta_property **eps, size_t *eps_len) { if (h == TEE_PROPSET_CURRENT_TA) { *eps = ta_props; *eps_len = ta_num_props; } else if (h == TEE_PROPSET_CURRENT_CLIENT) { *eps = NULL; *eps_len = 0; } else if (h == TEE_PROPSET_TEE_IMPLEMENTATION) { *eps = tee_props; *eps_len = ARRAY_SIZE(tee_props); } else { return TEE_ERROR_ITEM_NOT_FOUND; } return TEE_SUCCESS; } static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep, enum user_ta_prop_type *type, void *buf, uint32_t *len) { size_t l; *type = ep->type; switch (*type) { case USER_TA_PROP_TYPE_BOOL: l = sizeof(bool); break; case USER_TA_PROP_TYPE_U32: l = sizeof(uint32_t); break; case USER_TA_PROP_TYPE_U64: l = sizeof(uint64_t); break; case USER_TA_PROP_TYPE_UUID: l = sizeof(TEE_UUID); break; case USER_TA_PROP_TYPE_IDENTITY: l = sizeof(TEE_Identity); break; case USER_TA_PROP_TYPE_STRING: /* take the leading 0 into account */ l = strlen(ep->value) + 1; break; case USER_TA_PROP_TYPE_BINARY_BLOCK: /* * in case of TA property, a binary block is provided as a * string, which is base64 encoded. We must first decode it, * without taking into account the zero termination of the * string */ l = *len; if (!_base64_dec(ep->value, strlen(ep->value), buf, &l) && l <= *len) return TEE_ERROR_GENERIC; if (*len < l) { *len = l; return TEE_ERROR_SHORT_BUFFER; } *len = l; return TEE_SUCCESS; default: return TEE_ERROR_GENERIC; } if (*len < l) { *len = l; return TEE_ERROR_SHORT_BUFFER; } *len = l; memcpy(buf, ep->value, l); return TEE_SUCCESS; } static bool is_propset_pseudo_handle(TEE_PropSetHandle h) { return h == TEE_PROPSET_CURRENT_TA || h == TEE_PROPSET_CURRENT_CLIENT || h == TEE_PROPSET_TEE_IMPLEMENTATION; } static TEE_Result propget_get_property(TEE_PropSetHandle h, const char *name, enum user_ta_prop_type *type, void *buf, uint32_t *len) { TEE_Result res; const struct user_ta_property *eps; size_t eps_len; uint32_t prop_type; uint32_t index; if (is_propset_pseudo_handle(h)) { size_t n; res = propset_get(h, &eps, &eps_len); if (res != TEE_SUCCESS) return res; for (n = 0; n < eps_len; n++) { if (!strcmp(name, eps[n].name)) return propget_get_ext_prop(eps + n, type, buf, len); } /* get the index from the name */ res = _utee_get_property_name_to_index((unsigned long)h, name, strlen(name) + 1, &index); if (res != TEE_SUCCESS) return res; res = _utee_get_property((unsigned long)h, index, NULL, NULL, buf, len, &prop_type); } else { struct prop_enumerator *pe = (struct prop_enumerator *)h; uint32_t idx = pe->idx; if (idx == PROP_ENUMERATOR_NOT_STARTED) return TEE_ERROR_ITEM_NOT_FOUND; res = propset_get(pe->prop_set, &eps, &eps_len); if (res != TEE_SUCCESS) return res; if (idx < eps_len) return propget_get_ext_prop(eps + idx, type, buf, len); idx -= eps_len; res = _utee_get_property((unsigned long)pe->prop_set, idx, NULL, NULL, buf, len, &prop_type); if (res == TEE_ERROR_ITEM_NOT_FOUND) res = TEE_ERROR_BAD_PARAMETERS; } *type = prop_type; return res; } TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, const char *name, char *value, size_t *value_len) { TEE_Result res = TEE_ERROR_GENERIC; size_t l = 0; enum user_ta_prop_type type = USER_TA_PROP_TYPE_INVALID; void *tmp_buf = 0; uint32_t tmp_len = 0; uint32_t uint32_val = 0; bool bool_val = false; TEE_Identity *p_identity_val = NULL; if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_outstring_annotation(value, value_len); tmp_len = *value_len; if (tmp_len < sizeof(TEE_Identity)) tmp_len = sizeof(TEE_Identity); tmp_buf = TEE_Malloc(tmp_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!tmp_buf) { res = TEE_ERROR_OUT_OF_MEMORY; goto out; } res = propget_get_property(propsetOrEnumerator, name, &type, tmp_buf, &tmp_len); if (res != TEE_SUCCESS) { if (res == TEE_ERROR_SHORT_BUFFER) { if (type == USER_TA_PROP_TYPE_BINARY_BLOCK) { /* * in this case, we must enlarge the buffer * with the size of the of the base64 encoded * see base64_enc() function */ tmp_len = _base64_enc_len(tmp_len); } *value_len = tmp_len; } goto out; } switch (type) { case USER_TA_PROP_TYPE_BOOL: bool_val = *((bool *)tmp_buf); l = strlcpy(value, (bool_val ? "true" : "false"), *value_len); break; case USER_TA_PROP_TYPE_U32: uint32_val = *((uint32_t *)tmp_buf); l = snprintf(value, *value_len, "%u", uint32_val); break; case USER_TA_PROP_TYPE_UUID: l = snprintk(value, *value_len, "%pUl", tmp_buf); break; case USER_TA_PROP_TYPE_IDENTITY: p_identity_val = ((TEE_Identity *)tmp_buf); l = snprintk(value, *value_len, "%u:%pUl", p_identity_val->login, (void *)(&(p_identity_val->uuid))); break; case USER_TA_PROP_TYPE_STRING: l = strlcpy(value, tmp_buf, *value_len); break; case USER_TA_PROP_TYPE_BINARY_BLOCK: l = *value_len; /* l includes the zero-termination */ if (!_base64_enc(tmp_buf, tmp_len, value, &l) && l <= *value_len) { res = TEE_ERROR_GENERIC; goto out; } l--; /* remove the zero-termination that is added later */ break; default: res = TEE_ERROR_BAD_FORMAT; goto out; } l++; /* include zero termination */ if (l > *value_len) res = TEE_ERROR_SHORT_BUFFER; *value_len = l; out: if (tmp_buf) TEE_Free(tmp_buf); if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(0); return res; } TEE_Result __GP11_TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator, const char *name, char *valueBuffer, uint32_t *valueBufferLen) { TEE_Result res = TEE_SUCCESS; size_t l = 0; __utee_check_gp11_outstring_annotation(valueBuffer, valueBufferLen); l = *valueBufferLen; res = TEE_GetPropertyAsString(propsetOrEnumerator, name, valueBuffer, &l); *valueBufferLen = l; return res; } TEE_Result TEE_GetPropertyAsBool(TEE_PropSetHandle propsetOrEnumerator, const char *name, bool *value) { TEE_Result res; enum user_ta_prop_type type; uint32_t bool_len = sizeof(bool); if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_out_annotation(value, sizeof(*value)); type = USER_TA_PROP_TYPE_BOOL; res = propget_get_property(propsetOrEnumerator, name, &type, value, &bool_len); if (type != USER_TA_PROP_TYPE_BOOL) res = TEE_ERROR_BAD_FORMAT; if (res != TEE_SUCCESS) goto out; out: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_BAD_FORMAT) TEE_Panic(0); return res; } TEE_Result TEE_GetPropertyAsU32(TEE_PropSetHandle propsetOrEnumerator, const char *name, uint32_t *value) { TEE_Result res; enum user_ta_prop_type type; uint32_t uint32_len = sizeof(uint32_t); if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_out_annotation(value, sizeof(*value)); type = USER_TA_PROP_TYPE_U32; res = propget_get_property(propsetOrEnumerator, name, &type, value, &uint32_len); if (type != USER_TA_PROP_TYPE_U32) res = TEE_ERROR_BAD_FORMAT; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_BAD_FORMAT) TEE_Panic(0); return res; } TEE_Result TEE_GetPropertyAsU64(TEE_PropSetHandle propsetOrEnumerator, const char *name, uint64_t *value) { TEE_Result res; enum user_ta_prop_type type; uint32_t uint64_len = sizeof(*value); if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_out_annotation(value, sizeof(*value)); type = USER_TA_PROP_TYPE_U64; res = propget_get_property(propsetOrEnumerator, name, &type, value, &uint64_len); if (type != USER_TA_PROP_TYPE_U64) res = TEE_ERROR_BAD_FORMAT; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_BAD_FORMAT) TEE_Panic(0); return res; } TEE_Result __GP11_TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, const char *name, void *value, uint32_t *value_len) { TEE_Result res = TEE_SUCCESS; enum user_ta_prop_type type = USER_TA_PROP_TYPE_BOOL; if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_gp11_outbuf_annotation(value, value_len); type = USER_TA_PROP_TYPE_BINARY_BLOCK; res = propget_get_property(propsetOrEnumerator, name, &type, value, value_len); if (type != USER_TA_PROP_TYPE_BINARY_BLOCK) res = TEE_ERROR_BAD_FORMAT; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_BAD_FORMAT && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(0); return res; } TEE_Result TEE_GetPropertyAsBinaryBlock(TEE_PropSetHandle propsetOrEnumerator, const char *name, void *value, size_t *value_len) { TEE_Result res = TEE_SUCCESS; uint32_t l = 0; __utee_check_outbuf_annotation(value, value_len); l = *value_len; res = __GP11_TEE_GetPropertyAsBinaryBlock(propsetOrEnumerator, name, value, &l); *value_len = l; return res; } TEE_Result TEE_GetPropertyAsUUID(TEE_PropSetHandle propsetOrEnumerator, const char *name, TEE_UUID *value) { TEE_Result res; enum user_ta_prop_type type; uint32_t uuid_len = sizeof(TEE_UUID); if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_out_annotation(value, sizeof(*value)); type = USER_TA_PROP_TYPE_UUID; res = propget_get_property(propsetOrEnumerator, name, &type, value, &uuid_len); if (type != USER_TA_PROP_TYPE_UUID) res = TEE_ERROR_BAD_FORMAT; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_BAD_FORMAT) TEE_Panic(0); return res; } TEE_Result TEE_GetPropertyAsIdentity(TEE_PropSetHandle propsetOrEnumerator, const char *name, TEE_Identity *value) { TEE_Result res; enum user_ta_prop_type type; uint32_t identity_len = sizeof(TEE_Identity); if (is_propset_pseudo_handle(propsetOrEnumerator)) __utee_check_instring_annotation(name); __utee_check_out_annotation(value, sizeof(*value)); type = USER_TA_PROP_TYPE_IDENTITY; res = propget_get_property(propsetOrEnumerator, name, &type, value, &identity_len); if (type != USER_TA_PROP_TYPE_IDENTITY) res = TEE_ERROR_BAD_FORMAT; if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_BAD_FORMAT) TEE_Panic(0); return res; } TEE_Result TEE_AllocatePropertyEnumerator(TEE_PropSetHandle *enumerator) { TEE_Result res; struct prop_enumerator *pe; __utee_check_out_annotation(enumerator, sizeof(*enumerator)); pe = TEE_Malloc(sizeof(struct prop_enumerator), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (pe == NULL) { res = TEE_ERROR_OUT_OF_MEMORY; goto err; } *enumerator = (TEE_PropSetHandle) pe; TEE_ResetPropertyEnumerator(*enumerator); goto out; err: if (res == TEE_ERROR_OUT_OF_MEMORY) return res; TEE_Panic(0); out: return TEE_SUCCESS; } void TEE_ResetPropertyEnumerator(TEE_PropSetHandle enumerator) { struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; pe->idx = PROP_ENUMERATOR_NOT_STARTED; } void TEE_FreePropertyEnumerator(TEE_PropSetHandle enumerator) { struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; TEE_Free(pe); } void TEE_StartPropertyEnumerator(TEE_PropSetHandle enumerator, TEE_PropSetHandle propSet) { struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; if (!pe) return; pe->idx = 0; pe->prop_set = propSet; } TEE_Result __GP11_TEE_GetPropertyName(TEE_PropSetHandle enumerator, void *name, uint32_t *name_len) { TEE_Result res; struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; const struct user_ta_property *eps; size_t eps_len; const char *str; size_t bufferlen; if (!pe) { res = TEE_ERROR_BAD_PARAMETERS; goto err; } __utee_check_gp11_outstring_annotation(name, name_len); bufferlen = *name_len; res = propset_get(pe->prop_set, &eps, &eps_len); if (res != TEE_SUCCESS) goto err; if (pe->idx < eps_len) { str = eps[pe->idx].name; bufferlen = strlcpy(name, str, *name_len) + 1; if (bufferlen > *name_len) res = TEE_ERROR_SHORT_BUFFER; *name_len = bufferlen; } else { res = _utee_get_property((unsigned long)pe->prop_set, pe->idx - eps_len, name, name_len, NULL, NULL, NULL); if (res != TEE_SUCCESS) goto err; } err: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND && res != TEE_ERROR_SHORT_BUFFER) TEE_Panic(0); return res; } TEE_Result TEE_GetPropertyName(TEE_PropSetHandle enumerator, void *nameBuffer, size_t *nameBufferLen) { TEE_Result res = TEE_SUCCESS; uint32_t l = 0; __utee_check_outstring_annotation(nameBuffer, nameBufferLen); l = *nameBufferLen; res = __GP11_TEE_GetPropertyName(enumerator, nameBuffer, &l); *nameBufferLen = l; return res; } TEE_Result TEE_GetNextProperty(TEE_PropSetHandle enumerator) { TEE_Result res; struct prop_enumerator *pe = (struct prop_enumerator *)enumerator; uint32_t next_idx; const struct user_ta_property *eps; size_t eps_len; if (!pe) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } if (pe->idx == PROP_ENUMERATOR_NOT_STARTED) { res = TEE_ERROR_ITEM_NOT_FOUND; goto out; } res = propset_get(pe->prop_set, &eps, &eps_len); if (res != TEE_SUCCESS) goto out; next_idx = pe->idx + 1; pe->idx = next_idx; if (next_idx < eps_len) res = TEE_SUCCESS; else res = _utee_get_property((unsigned long)pe->prop_set, next_idx - eps_len, NULL, NULL, NULL, NULL, NULL); out: if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) TEE_Panic(0); return res; } optee_os-4.3.0/lib/libutee/tee_socket_private.h000066400000000000000000000015261464416617300216020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2017, Linaro Limited */ #ifndef __TEE_SOCKET_PRIVATE_H #define __TEE_SOCKET_PRIVATE_H #include #include <__tee_ipsocket.h> static inline uint8_t __tee_socket_ioctl_cmd_to_proto(uint32_t cmd_code) { return cmd_code >> 24; } TEE_Result __tee_socket_pta_open(TEE_ipSocket_ipVersion ip_vers, const char *addr, uint16_t port, uint32_t protocol, uint32_t *handle); TEE_Result __tee_socket_pta_close(uint32_t handle); TEE_Result __tee_socket_pta_send(uint32_t handle, const void *buf, uint32_t *len, uint32_t timeout); TEE_Result __tee_socket_pta_recv(uint32_t handle, void *buf, uint32_t *len, uint32_t timeout); TEE_Result __tee_socket_pta_ioctl(uint32_t handle, uint32_t command, void *buf, uint32_t *len); #endif /*__TEE_SOCKET_PRIVATE_H*/ optee_os-4.3.0/lib/libutee/tee_socket_pta.c000066400000000000000000000100171464416617300207020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2017, Linaro Limited */ #include #include #include #include <__tee_tcpsocket_defines.h> #include <__tee_udpsocket_defines.h> #include "tee_socket_private.h" static TEE_Result invoke_socket_pta(uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { static TEE_TASessionHandle sess = TEE_HANDLE_NULL; static const TEE_UUID socket_uuid = PTA_SOCKET_UUID; if (sess == TEE_HANDLE_NULL) { TEE_Result res = TEE_OpenTASession(&socket_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, NULL); if (res != TEE_SUCCESS) return res; } return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, param_types, params, NULL); } TEE_Result __tee_socket_pta_open(TEE_ipSocket_ipVersion ip_vers, const char *addr, uint16_t port, uint32_t protocol, uint32_t *handle) { TEE_Result res; uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT); memset(params, 0, sizeof(params)); switch (ip_vers) { case TEE_IP_VERSION_DC: case TEE_IP_VERSION_4: case TEE_IP_VERSION_6: params[0].value.a = ip_vers; break; default: return TEE_ERROR_BAD_PARAMETERS; } params[0].value.b = port; if (!addr) return TEE_ERROR_BAD_PARAMETERS; params[1].memref.buffer = (void *)addr; params[1].memref.size = strlen(addr) + 1; switch (protocol) { case TEE_ISOCKET_PROTOCOLID_TCP: case TEE_ISOCKET_PROTOCOLID_UDP: params[2].value.a = protocol; break; default: return TEE_ERROR_BAD_PARAMETERS; } res = invoke_socket_pta(PTA_SOCKET_OPEN, param_types, params); if (res == TEE_SUCCESS) *handle = params[3].value.a; return res; } TEE_Result __tee_socket_pta_close(uint32_t handle) { uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); params[0].value.a = handle; return invoke_socket_pta(PTA_SOCKET_CLOSE, param_types, params); } TEE_Result __tee_socket_pta_send(uint32_t handle, const void *buf, uint32_t *len, uint32_t timeout) { TEE_Result res; uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); params[0].value.a = handle; params[0].value.b = timeout; params[1].memref.buffer = (void *)buf; params[1].memref.size = *len; res = invoke_socket_pta(PTA_SOCKET_SEND, param_types, params); *len = params[2].value.a; return res; } TEE_Result __tee_socket_pta_recv(uint32_t handle, void *buf, uint32_t *len, uint32_t timeout) { TEE_Result res; uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); params[0].value.a = handle; params[0].value.b = timeout; params[1].memref.buffer = buf; params[1].memref.size = *len; res = invoke_socket_pta(PTA_SOCKET_RECV, param_types, params); *len = params[1].memref.size; return res; } TEE_Result __tee_socket_pta_ioctl(uint32_t handle, uint32_t command, void *buf, uint32_t *len) { TEE_Result res; uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); memset(params, 0, sizeof(params)); params[0].value.a = handle; params[0].value.b = command; params[1].memref.buffer = buf; params[1].memref.size = *len; res = invoke_socket_pta(PTA_SOCKET_IOCTL, param_types, params); *len = params[1].memref.size; return res; } optee_os-4.3.0/lib/libutee/tee_system_pta.c000066400000000000000000000056111464416617300207420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited * Copyright (c) 2020, Open Mobile Platform LLC */ #include #include #include #include #include #include static TEE_Result invoke_system_pta(uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { static TEE_TASessionHandle sess = TEE_HANDLE_NULL; static const TEE_UUID uuid = PTA_SYSTEM_UUID; if (sess == TEE_HANDLE_NULL) { TEE_Result res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, NULL); if (res) return res; } return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, cmd_id, param_types, params, NULL); } void *tee_map_zi(size_t len, uint32_t flags) { uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE); TEE_Param params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_SUCCESS; params[0].value.a = len; if (params[0].value.a != len) return NULL; switch (flags) { case 0: break; case TEE_MEMORY_ACCESS_ANY_OWNER: params[0].value.b = PTA_SYSTEM_MAP_FLAG_SHAREABLE; break; default: return NULL; } res = invoke_system_pta(PTA_SYSTEM_MAP_ZI, param_types, params); if (res) return NULL; return (void *)(vaddr_t)reg_pair_to_64(params[1].value.a, params[1].value.b); } TEE_Result tee_unmap(void *buf, size_t len) { TEE_Result res = TEE_SUCCESS; uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param params[TEE_NUM_PARAMS] = { }; params[0].value.a = len; reg_pair_from_64((vaddr_t)buf, ¶ms[1].value.a, ¶ms[1].value.b); res = invoke_system_pta(PTA_SYSTEM_UNMAP, param_types, params); if (res) EMSG("Invoke PTA_SYSTEM_UNMAP: buf %p, len %#zx", buf, len); return res; } TEE_Result tee_invoke_supp_plugin(const TEE_UUID *uuid, uint32_t cmd, uint32_t sub_cmd, void *buf, size_t len, size_t *outlen) { TEE_Result res = TEE_SUCCESS; uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_VALUE_OUTPUT); TEE_Param params[TEE_NUM_PARAMS] = { }; if (!uuid || (len && !buf) || (!len && buf)) return TEE_ERROR_BAD_PARAMETERS; params[0].memref.buffer = (void *)uuid; params[0].memref.size = sizeof(TEE_UUID); params[1].value.a = cmd; params[1].value.b = sub_cmd; params[2].memref.buffer = buf; params[2].memref.size = len; res = invoke_system_pta(PTA_SYSTEM_SUPP_PLUGIN_INVOKE, param_types, params); if (res) EMSG("Invoke tee-supplicant's plugin failed: %#"PRIx32, res); if (outlen) *outlen = params[3].value.a; return res; } optee_os-4.3.0/lib/libutee/tee_tcpudp_socket.c000066400000000000000000000122371464416617300214230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2016-2017, Linaro Limited */ #include #include #include #include #include <__tee_tcpsocket_defines_extensions.h> #include #include "tee_socket_private.h" struct socket_ctx { uint32_t handle; uint32_t proto_error; }; static TEE_Result tcp_open(TEE_iSocketHandle *ctx, void *setup, uint32_t *proto_error) { TEE_Result res; struct socket_ctx *sock_ctx; TEE_tcpSocket_Setup *tcp_setup = setup; if (!ctx || !setup || !proto_error) TEE_Panic(0); *proto_error = TEE_SUCCESS; sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); if (!sock_ctx) return TEE_ERROR_OUT_OF_MEMORY; res = __tee_socket_pta_open(tcp_setup->ipVersion, tcp_setup->server_addr, tcp_setup->server_port, TEE_ISOCKET_PROTOCOLID_TCP, &sock_ctx->handle); if (res != TEE_SUCCESS) { TEE_Free(sock_ctx); sock_ctx = NULL; } *ctx = (TEE_iSocketHandle)sock_ctx; switch (res) { case TEE_ISOCKET_ERROR_HOSTNAME: *proto_error = res; return TEE_ISOCKET_ERROR_PROTOCOL; case TEE_ISOCKET_TCP_WARNING_UNKNOWN_OUT_OF_BAND: *proto_error = res; return TEE_ISOCKET_WARNING_PROTOCOL; default: return res; } } static TEE_Result udp_open(TEE_iSocketHandle *ctx, void *setup, uint32_t *proto_error) { TEE_Result res; struct socket_ctx *sock_ctx; TEE_udpSocket_Setup *udp_setup = setup; if (!ctx || !setup || !proto_error) TEE_Panic(0); *proto_error = TEE_SUCCESS; sock_ctx = TEE_Malloc(sizeof(*sock_ctx), TEE_MALLOC_FILL_ZERO); if (!sock_ctx) return TEE_ERROR_OUT_OF_MEMORY; res = __tee_socket_pta_open(udp_setup->ipVersion, udp_setup->server_addr, udp_setup->server_port, TEE_ISOCKET_PROTOCOLID_UDP, &sock_ctx->handle); if (res != TEE_SUCCESS) { TEE_Free(sock_ctx); sock_ctx = NULL; } *ctx = (TEE_iSocketHandle)sock_ctx; switch (res) { case TEE_ISOCKET_ERROR_HOSTNAME: *proto_error = res; return TEE_ISOCKET_ERROR_PROTOCOL; case TEE_ISOCKET_UDP_WARNING_UNKNOWN_OUT_OF_BAND: *proto_error = res; return TEE_ISOCKET_WARNING_PROTOCOL; default: return res; } } static TEE_Result sock_close(TEE_iSocketHandle ctx) { TEE_Result res; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL) return TEE_SUCCESS; res = __tee_socket_pta_close(sock_ctx->handle); TEE_Free(sock_ctx); return res; } static TEE_Result sock_send(TEE_iSocketHandle ctx, const void *buf, uint32_t *length, uint32_t timeout) { TEE_Result res; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !buf || !length) TEE_Panic(0); res = __tee_socket_pta_send(sock_ctx->handle, buf, length, timeout); sock_ctx->proto_error = res; return res; } static TEE_Result sock_recv(TEE_iSocketHandle ctx, void *buf, uint32_t *length, uint32_t timeout) { TEE_Result res; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) TEE_Panic(0); res = __tee_socket_pta_recv(sock_ctx->handle, buf, length, timeout); sock_ctx->proto_error = res; return res; } static uint32_t sock_error(TEE_iSocketHandle ctx) { struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL) TEE_Panic(0); return sock_ctx->proto_error; } static TEE_Result tcp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, void *buf, uint32_t *length) { TEE_Result res = TEE_ERROR_GENERIC; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) TEE_Panic(0); if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) return TEE_SUCCESS; switch (commandCode) { case TEE_TCP_SET_RECVBUF: case TEE_TCP_SET_SENDBUF: res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, buf, length); break; default: TEE_Panic(0); } sock_ctx->proto_error = res; return res; } static TEE_Result udp_ioctl(TEE_iSocketHandle ctx, uint32_t commandCode, void *buf, uint32_t *length) { TEE_Result res = TEE_ERROR_GENERIC; struct socket_ctx *sock_ctx = (struct socket_ctx *)ctx; if (ctx == TEE_HANDLE_NULL || !length || (!buf && *length)) TEE_Panic(0); if (__tee_socket_ioctl_cmd_to_proto(commandCode) == 0) return TEE_SUCCESS; switch (commandCode) { case TEE_UDP_CHANGEADDR: case TEE_UDP_CHANGEPORT: res = __tee_socket_pta_ioctl(sock_ctx->handle, commandCode, buf, length); break; default: TEE_Panic(0); } sock_ctx->proto_error = res; return res; } static TEE_iSocket tcp_socket_instance = { .TEE_iSocketVersion = TEE_ISOCKET_VERSION, .protocolID = TEE_ISOCKET_PROTOCOLID_TCP, .open = tcp_open, .close = sock_close, .send = sock_send, .recv = sock_recv, .error = sock_error, .ioctl = tcp_ioctl, }; static TEE_iSocket udp_socket_instance = { .TEE_iSocketVersion = TEE_ISOCKET_VERSION, .protocolID = TEE_ISOCKET_PROTOCOLID_UDP, .open = udp_open, .close = sock_close, .send = sock_send, .recv = sock_recv, .error = sock_error, .ioctl = udp_ioctl, }; TEE_iSocket *const TEE_tcpSocket = &tcp_socket_instance; TEE_iSocket *const TEE_udpSocket = &udp_socket_instance; optee_os-4.3.0/lib/libutee/tee_uuid_from_str.c000066400000000000000000000025101464416617300214260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, Linaro Limited */ #include #include #include #include #include static int hex(char c) { char lc = tolower(c); if (isdigit(lc)) return lc - '0'; if (isxdigit(lc)) return lc - 'a' + 10; return -1; } static uint32_t parse_hex(const char *s, size_t nchars, uint32_t *res) { uint32_t v = 0; size_t n = 0; int c = 0; for (n = 0; n < nchars; n++) { c = hex(s[n]); if (c == -1) { *res = TEE_ERROR_BAD_FORMAT; goto out; } v = (v << 4) + c; } *res = TEE_SUCCESS; out: return v; } TEE_Result tee_uuid_from_str(TEE_UUID *uuid, const char *s) { TEE_Result res = TEE_SUCCESS; TEE_UUID u = { }; const char *p = s; size_t i = 0; if (!p || strnlen(p, 37) != 36) return TEE_ERROR_BAD_FORMAT; if (p[8] != '-' || p[13] != '-' || p[18] != '-' || p[23] != '-') return TEE_ERROR_BAD_FORMAT; u.timeLow = parse_hex(p, 8, &res); if (res) goto out; p += 9; u.timeMid = parse_hex(p, 4, &res); if (res) goto out; p += 5; u.timeHiAndVersion = parse_hex(p, 4, &res); if (res) goto out; p += 5; for (i = 0; i < 8; i++) { u.clockSeqAndNode[i] = parse_hex(p, 2, &res); if (res) goto out; if (i == 1) p += 3; else p += 2; } *uuid = u; out: return res; } optee_os-4.3.0/lib/libutee/trace_ext.c000066400000000000000000000031761464416617300176770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Arm Limited */ #include #include #include #include #include #include #include #ifdef __LDELF__ #include #endif #if TRACE_LEVEL > 0 void trace_ext_puts(const char *str) { #ifdef __LDELF__ _ldelf_log(str, strlen(str)); #else _utee_log(str, strlen(str)); #endif } int trace_ext_get_thread_id(void) { return -1; } /* * printf and puts - stdio printf support * * 'printf()' and 'puts()' traces have the 'info' trace level. */ int printf(const char *fmt, ...) { char to_format[MAX_PRINT_SIZE]; va_list ap; int s; if (trace_get_level() < TRACE_PRINTF_LEVEL) return 0; va_start(ap, fmt); s = vsnprintf(to_format, sizeof(to_format), fmt, ap); va_end(ap); if (s < 0) return s; trace_ext_puts(to_format); return s; } int puts(const char *str) { if (trace_get_level() >= TRACE_PRINTF_LEVEL) { trace_ext_puts(str); trace_ext_puts("\n"); } return 1; } int putchar(int c) { char str[2] = { (char)c, '\0' }; if (trace_get_level() >= TRACE_PRINTF_LEVEL) trace_ext_puts(str); /* * From the putchar() man page: * "fputc(), putc() and putchar() return the character written as an * unsigned char cast to an int or EOF on error." */ return (int)(unsigned char)c; } #else void trace_ext_puts(const char *str __unused) { } int printf(const char *fmt __unused, ...) { return 0; } int puts(const char *str __unused) { return 0; } int putchar(int c) { return (int)(unsigned char)c; } #endif optee_os-4.3.0/lib/libutee/user_ta_entry.c000066400000000000000000000245151464416617300206040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2022, Linaro Limited. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tee_api_private.h" struct ta_session { uint32_t session_id; void *session_ctx; TAILQ_ENTRY(ta_session) link; }; static TAILQ_HEAD(ta_sessions, ta_session) ta_sessions = TAILQ_HEAD_INITIALIZER(ta_sessions); static bool init_done; /* From user_ta_header.c, built within TA */ extern uint8_t ta_heap[]; extern const size_t ta_heap_size; extern struct ta_head ta_head; uint32_t ta_param_types; TEE_Param ta_params[TEE_NUM_PARAMS]; struct malloc_ctx *__ta_no_share_malloc_ctx; struct __elf_phdr_info __elf_phdr_info; struct phdr_info { struct dl_phdr_info info; TAILQ_ENTRY(phdr_info) link; }; static TAILQ_HEAD(phdr_info_head, phdr_info) __phdr_info_head = TAILQ_HEAD_INITIALIZER(__phdr_info_head); /* * Keep track of how many modules have been initialized so that subsequent * dlopen() calls will not run the same initializers again */ static size_t _num_mod_init; static int _init_iterate_phdr_cb(struct dl_phdr_info *info, size_t size __unused, void *data) { struct phdr_info *qe = NULL; size_t *count = data; qe = malloc(sizeof(*qe)); if (!qe) { EMSG("init/fini: out of memory"); abort(); } qe->info = *info; TAILQ_INSERT_TAIL(&__phdr_info_head, qe, link); (*count)++; return 0; } static void _get_fn_array(struct dl_phdr_info *info, Elf_Sword tag_a, Elf_Sword tag_s, void (***fn)(void), size_t *num_fn) { const Elf_Phdr *phdr = NULL; Elf_Dyn *dyn = NULL; size_t num_dyn = 0; size_t i = 0; size_t j = 0; for (i = 0; i < info->dlpi_phnum; i++) { phdr = info->dlpi_phdr + i; if (phdr->p_type != PT_DYNAMIC) continue; num_dyn = phdr->p_memsz / sizeof(Elf_Dyn); dyn = (Elf_Dyn *)(phdr->p_vaddr + info->dlpi_addr); for (j = 0; j < num_dyn; j++) { if (*fn && *num_fn) break; if (dyn->d_tag == DT_NULL) { break; } else if (dyn->d_tag == tag_a) { *fn = (void (**)(void))(dyn->d_un.d_ptr + info->dlpi_addr); } else if (dyn->d_tag == tag_s) { *num_fn = dyn->d_un.d_val / sizeof(Elf_Addr); } dyn++; } } } void __utee_call_elf_init_fn(void) { void (**fn)(void) = NULL; size_t num_mod = 0; size_t num_fn = 0; size_t mod = 0; size_t i = 0; struct phdr_info *qe = NULL; struct phdr_info *qe2 = NULL; dl_iterate_phdr(_init_iterate_phdr_cb, &num_mod); /* Reverse order: dependencies first */ TAILQ_FOREACH_REVERSE(qe, &__phdr_info_head, phdr_info_head, link) { if (mod == num_mod - _num_mod_init) break; _get_fn_array(&qe->info, DT_INIT_ARRAY, DT_INIT_ARRAYSZ, &fn, &num_fn); for (i = 0; i < num_fn; i++) fn[i](); fn = NULL; num_fn = 0; mod++; } _num_mod_init += mod; TAILQ_FOREACH_SAFE(qe, &__phdr_info_head, link, qe2) { TAILQ_REMOVE(&__phdr_info_head, qe, link); free(qe); } } static int _fini_iterate_phdr_cb(struct dl_phdr_info *info, size_t size __unused, void *data __unused) { void (**fn)(void) = NULL; size_t num_fn = 0; size_t i = 0; _get_fn_array(info, DT_FINI_ARRAY, DT_FINI_ARRAYSZ, &fn, &num_fn); for (i = 1; i <= num_fn; i++) fn[num_fn - i](); return 0; } void __utee_call_elf_fini_fn(void) { dl_iterate_phdr(_fini_iterate_phdr_cb, NULL); } static unsigned int get_memtag_implementation(void) { const char *s = "org.trustedfirmware.optee.cpu.feat_memtag_implemented"; uint32_t v = 0; if (TEE_GetPropertyAsU32(TEE_PROPSET_TEE_IMPLEMENTATION, s, &v)) return 0; return v; } static TEE_Result init_instance(void) { trace_set_level(tahead_get_trace_level()); __utee_gprof_init(); malloc_add_pool(ta_heap, ta_heap_size); if (__ta_no_share_heap_size) { __ta_no_share_malloc_ctx = malloc(raw_malloc_get_ctx_size()); if (__ta_no_share_malloc_ctx) { raw_malloc_init_ctx(__ta_no_share_malloc_ctx); raw_malloc_add_pool(__ta_no_share_malloc_ctx, __ta_no_share_heap, __ta_no_share_heap_size); } } memtag_init_ops(get_memtag_implementation()); _TEE_MathAPI_Init(); __utee_tcb_init(); __utee_call_elf_init_fn(); return TA_CreateEntryPoint(); } static void uninit_instance(void) { __utee_gprof_fini(); TA_DestroyEntryPoint(); __utee_call_elf_fini_fn(); } static void ta_header_save_params(uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS]) { ta_param_types = param_types; if (params) memcpy(ta_params, params, sizeof(ta_params)); else memset(ta_params, 0, sizeof(ta_params)); } static struct ta_session *ta_header_get_session(uint32_t session_id) { struct ta_session *itr; TAILQ_FOREACH(itr, &ta_sessions, link) { if (itr->session_id == session_id) return itr; } return NULL; } static TEE_Result ta_header_add_session(uint32_t session_id) { struct ta_session *itr = ta_header_get_session(session_id); TEE_Result res; if (itr) return TEE_SUCCESS; if (!init_done) { init_done = true; res = init_instance(); if (res) return res; } itr = TEE_Malloc(sizeof(struct ta_session), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!itr) return TEE_ERROR_OUT_OF_MEMORY; itr->session_id = session_id; itr->session_ctx = 0; TAILQ_INSERT_TAIL(&ta_sessions, itr, link); return TEE_SUCCESS; } static void ta_header_remove_session(uint32_t session_id) { struct ta_session *itr; bool keep_alive; TAILQ_FOREACH(itr, &ta_sessions, link) { if (itr->session_id == session_id) { TAILQ_REMOVE(&ta_sessions, itr, link); TEE_Free(itr); keep_alive = (ta_head.flags & TA_FLAG_SINGLE_INSTANCE) && (ta_head.flags & TA_FLAG_INSTANCE_KEEP_ALIVE); if (TAILQ_EMPTY(&ta_sessions) && !keep_alive) uninit_instance(); return; } } } static void to_utee_params(struct utee_params *up, uint32_t param_types, const TEE_Param params[TEE_NUM_PARAMS]) { size_t n = 0; up->types = param_types; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(param_types, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: up->vals[n * 2] = params[n].value.a; up->vals[n * 2 + 1] = params[n].value.b; break; case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: up->vals[n * 2] = (uintptr_t)params[n].memref.buffer; up->vals[n * 2 + 1] = params[n].memref.size; break; default: up->vals[n * 2] = 0; up->vals[n * 2 + 1] = 0; break; } } } static void from_utee_params(TEE_Param params[TEE_NUM_PARAMS], uint32_t *param_types, const struct utee_params *up) { size_t n; uint32_t types = up->types; for (n = 0; n < TEE_NUM_PARAMS; n++) { uintptr_t a = up->vals[n * 2]; uintptr_t b = up->vals[n * 2 + 1]; switch (TEE_PARAM_TYPE_GET(types, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: params[n].value.a = a; params[n].value.b = b; break; case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: params[n].memref.buffer = (void *)a; params[n].memref.size = b; break; default: break; } } if (param_types) *param_types = types; } static TEE_Result entry_open_session(unsigned long session_id, struct utee_params *up) { TEE_Result res; struct ta_session *session; uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; res = ta_header_add_session(session_id); if (res != TEE_SUCCESS) return res; session = ta_header_get_session(session_id); if (!session) return TEE_ERROR_BAD_STATE; from_utee_params(params, ¶m_types, up); ta_header_save_params(param_types, params); res = TA_OpenSessionEntryPoint(param_types, params, &session->session_ctx); to_utee_params(up, param_types, params); if (res != TEE_SUCCESS) ta_header_remove_session(session_id); return res; } static TEE_Result entry_close_session(unsigned long session_id) { struct ta_session *session = ta_header_get_session(session_id); if (!session) return TEE_ERROR_BAD_STATE; TA_CloseSessionEntryPoint(session->session_ctx); ta_header_remove_session(session_id); return TEE_SUCCESS; } static TEE_Result entry_invoke_command(unsigned long session_id, struct utee_params *up, unsigned long cmd_id) { TEE_Result res; uint32_t param_types; TEE_Param params[TEE_NUM_PARAMS]; struct ta_session *session = ta_header_get_session(session_id); if (!session) return TEE_ERROR_BAD_STATE; from_utee_params(params, ¶m_types, up); ta_header_save_params(param_types, params); res = TA_InvokeCommandEntryPoint(session->session_ctx, cmd_id, param_types, params); to_utee_params(up, param_types, params); return res; } #if defined(CFG_TA_STATS) static TEE_Result entry_dump_memstats(unsigned long session_id __unused, struct utee_params *up) { uint32_t param_types = 0; TEE_Param params[TEE_NUM_PARAMS] = { }; struct pta_stats_alloc stats = { }; from_utee_params(params, ¶m_types, up); ta_header_save_params(param_types, params); if (TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE) != param_types) return TEE_ERROR_BAD_PARAMETERS; malloc_get_stats(&stats); params[0].value.a = stats.allocated; params[0].value.b = stats.max_allocated; params[1].value.a = stats.size; params[1].value.b = stats.num_alloc_fail; params[2].value.a = stats.biggest_alloc_fail; params[2].value.b = stats.biggest_alloc_fail_used; to_utee_params(up, param_types, params); return TEE_SUCCESS; } #endif TEE_Result __utee_entry(unsigned long func, unsigned long session_id, struct utee_params *up, unsigned long cmd_id) { TEE_Result res; switch (func) { case UTEE_ENTRY_FUNC_OPEN_SESSION: res = entry_open_session(session_id, up); break; case UTEE_ENTRY_FUNC_CLOSE_SESSION: res = entry_close_session(session_id); break; case UTEE_ENTRY_FUNC_INVOKE_COMMAND: res = entry_invoke_command(session_id, up, cmd_id); break; #if defined(CFG_TA_STATS) case UTEE_ENTRY_FUNC_DUMP_MEMSTATS: res = entry_dump_memstats(session_id, up); break; #endif default: res = TEE_ERROR_NOT_SUPPORTED; break; } ta_header_save_params(0, NULL); return res; } optee_os-4.3.0/lib/libutee/user_ta_entry_compat.c000066400000000000000000000052401464416617300221410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2022, Linaro Limited. */ #include #include static void to_gp11_param(uint32_t pt, const TEE_Param params[TEE_NUM_PARAMS], __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS]) { size_t n = 0; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(pt, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: gp11_params[n].value.a = params[n].value.a; gp11_params[n].value.b = params[n].value.b; break; case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: gp11_params[n].memref.buffer = params[n].memref.buffer; gp11_params[n].memref.size = params[n].memref.size; break; default: break; } } } static void from_gp11_param(uint32_t pt, const __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS], TEE_Param params[TEE_NUM_PARAMS]) { size_t n = 0; for (n = 0; n < TEE_NUM_PARAMS; n++) { switch (TEE_PARAM_TYPE_GET(pt, n)) { case TEE_PARAM_TYPE_VALUE_INPUT: case TEE_PARAM_TYPE_VALUE_OUTPUT: case TEE_PARAM_TYPE_VALUE_INOUT: params[n].value.a = gp11_params[n].value.a; params[n].value.b = gp11_params[n].value.b; break; case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: params[n].memref.buffer = gp11_params[n].memref.buffer; params[n].memref.size = gp11_params[n].memref.size; break; default: break; } } } /* * Legacy TAs will due to macros define __GP11_TA_OpenSessionEntryPoint() * instead so call that function instead. */ TEE_Result __ta_open_sess(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], void **sess_ctx, TEE_Result (*fp)(uint32_t, __GP11_TEE_Param [TEE_NUM_PARAMS], void **)) { __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_SUCCESS; to_gp11_param(pt, params, gp11_params); res = fp(pt, gp11_params, sess_ctx); from_gp11_param(pt, gp11_params, params); return res; } /* * Legacy TAs will due to macros define __GP11_TA_InvokeCommandEntryPoint() * instead so call that function instead. */ TEE_Result __ta_invoke_cmd(void *sess_ctx, uint32_t cmd_id, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], TEE_Result (*fp)(void *, uint32_t, uint32_t, __GP11_TEE_Param [TEE_NUM_PARAMS])) { __GP11_TEE_Param gp11_params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_SUCCESS; to_gp11_param(pt, params, gp11_params); res = fp(sess_ctx, cmd_id, pt, gp11_params); from_gp11_param(pt, gp11_params, params); return res; } optee_os-4.3.0/lib/libutils/000077500000000000000000000000001464416617300157445ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/000077500000000000000000000000001464416617300165445ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/arch/000077500000000000000000000000001464416617300174615ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/arch/arm/000077500000000000000000000000001464416617300202405ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/arch/arm/aeabi_unwind.c000066400000000000000000000004651464416617300230360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017, Linaro Limited */ void __aeabi_unwind_cpp_pr0(void); void __aeabi_unwind_cpp_pr0(void) { } void __aeabi_unwind_cpp_pr1(void); void __aeabi_unwind_cpp_pr1(void) { } void __aeabi_unwind_cpp_pr2(void); void __aeabi_unwind_cpp_pr2(void) { } optee_os-4.3.0/lib/libutils/ext/arch/arm/atomic_a32.S000066400000000000000000000010201464416617300222760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2016, Linaro Limited */ #include .section .note.GNU-stack,"",%progbits /* uint32_t atomic_inc32(uint32_t *v); */ FUNC atomic_inc32 , : ldrex r1, [r0] add r1, r1, #1 strex r2, r1, [r0] cmp r2, #0 bne atomic_inc32 mov r0, r1 bx lr END_FUNC atomic_inc32 /* uint32_t atomic_dec32(uint32_t *v); */ FUNC atomic_dec32 , : ldrex r1, [r0] sub r1, r1, #1 strex r2, r1, [r0] cmp r2, #0 bne atomic_dec32 mov r0, r1 bx lr END_FUNC atomic_dec32 optee_os-4.3.0/lib/libutils/ext/arch/arm/atomic_a64.S000066400000000000000000000010531464416617300223110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015-2016, Linaro Limited */ #include /* uint32_t atomic_inc32(uint32_t *v); */ FUNC atomic_inc32 , : ldaxr w1, [x0] add w1, w1, #1 stxr w2, w1, [x0] cmp w2, #0 bne atomic_inc32 mov w0, w1 ret END_FUNC atomic_inc32 /* uint32_t atomic_dec32(uint32_t *v); */ FUNC atomic_dec32 , : ldaxr w1, [x0] sub w1, w1, #1 stxr w2, w1, [x0] cmp w2, #0 bne atomic_dec32 mov w0, w1 ret END_FUNC atomic_dec32 BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/lib/libutils/ext/arch/arm/auxval.c000066400000000000000000000003631464416617300217060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, EPAM Systems */ #include unsigned long int __getauxval (unsigned long int type); unsigned long int __getauxval (unsigned long int type __unused) { return 0; } optee_os-4.3.0/lib/libutils/ext/arch/arm/mcount_a32.S000066400000000000000000000032721464416617300223420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #include #if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) .section .note.GNU-stack,"",%progbits /* * Convert return address to call site address by subtracting the size of the * mcount call instruction (blx __gnu_mcount_nc). */ .macro mcount_adj_pc rd, rn bic \rd, \rn, #1 /* Clear thumb bit if present */ sub \rd, \rd, #4 .endm /* * With the -pg option, GCC (4.4+) inserts a call to __gnu_mcount_nc into * every function prologue. * The caller of the instrumented function can be determined from the lr value * stored on the top of the stack. The callee, i.e. the instrumented function * itself, is determined from the current value of lr. Then we call: * void __mcount_internal(void *frompc, void *selfpc); */ FUNC __gnu_mcount_nc, : UNWIND( .cantunwind) stmdb sp!, {r0-r3, lr} #if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__) ldr r0, [sp, #20] /* lr of instrumented func */ mcount_adj_pc r0, r0 mcount_adj_pc r1, lr /* instrumented func */ bl __mcount_internal #endif #ifdef CFG_FTRACE_SUPPORT /* Get instrumented function's pc value */ ldr r0, [sp, #16] mcount_adj_pc r0, r0 /* Get instrumented function's lr address pointer */ sub r1, fp, #4 bl ftrace_enter #endif ldmia sp!, {r0-r3, ip, lr} bx ip END_FUNC __gnu_mcount_nc #ifdef CFG_FTRACE_SUPPORT FUNC __ftrace_return, : /* save return value regs */ stmdb sp!, {r0-r3} /* get return address of parent func */ bl ftrace_return mov lr, r0 /* restore return value regs */ ldmia sp!, {r0-r3} bx lr END_FUNC __ftrace_return #endif #endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ optee_os-4.3.0/lib/libutils/ext/arch/arm/mcount_a64.S000066400000000000000000000036271464416617300223530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016, Linaro Limited */ #include #if defined(CFG_TA_GPROF_SUPPORT) || defined(CFG_FTRACE_SUPPORT) /* * Convert return address to call site address by subtracting the size of one * instruction. */ .macro adjust_pc rd, rn sub \rd, \rn, #4 .endm /* Get instrumented function's pc value */ .macro get_pc reg ldr \reg, [x29, #8] sub \reg, \reg, #4 .endm /* Get instrumented function's lr address pointer */ .macro get_lr_addr reg ldr \reg, [x29] add \reg, \reg, #8 .endm /* * void _mcount(void *return_address) * @return_address: return address to instrumented function * * With the -pg option, the compiler inserts a call to _mcount into * every function prologue. * x0 contains the value of lr (x30) before the call, that is the return * address to the caller of the instrumented function. The callee, i.e. the * instrumented function itself, is determined from the current value of x30. * Then we call: * void __mcount_internal(void *frompc, void *selfpc); */ FUNC _mcount, : stp x29, x30, [sp, #-16]! mov x29, sp #if defined(CFG_TA_GPROF_SUPPORT) && !defined(__KERNEL__) adjust_pc x0, x0 adjust_pc x1, x30 bl __mcount_internal #endif #ifdef CFG_FTRACE_SUPPORT get_pc x0 get_lr_addr x1 bl ftrace_enter #endif ldp x29, x30, [sp], #16 ret END_FUNC _mcount #ifdef CFG_FTRACE_SUPPORT FUNC __ftrace_return, : /* Save return value regs */ sub sp, sp, #64 stp x0, x1, [sp] stp x2, x3, [sp, #16] stp x4, x5, [sp, #32] stp x6, x7, [sp, #48] /* Get return address of parent func */ bl ftrace_return mov x30, x0 /* Restore return value regs */ ldp x0, x1, [sp] ldp x2, x3, [sp, #16] ldp x4, x5, [sp, #32] ldp x6, x7, [sp, #48] add sp, sp, #64 ret END_FUNC __ftrace_return #endif #endif /* CFG_TA_GPROF_SUPPORT || CFG_FTRACE_SUPPORT */ BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/lib/libutils/ext/arch/arm/memtag.c000066400000000000000000000077561464416617300216750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #include #include #include #if MEMTAG_IS_ENABLED /* This is for AArch64 only, MTE is only available in this mode */ static unsigned int dczid_block_size(void) { return SHIFT_U32(4U, read_dczid_el0() & 0xf); } static bool data_zero_prohibited(void) { #ifdef __KERNEL__ return false; #else return read_dczid_el0() & BIT(4); #endif } static void dc_gzva(uint64_t va) { asm volatile ("dc gzva, %0" : : "r" (va)); } static void dc_gva(uint64_t va) { asm volatile ("dc gva, %0" : : "r" (va)); } static vaddr_t stg_and_advance(vaddr_t va) { asm volatile("stg %0, [%0], #16" : "+r"(va) : : "memory"); return va; } static void *insert_random_tag(void *addr) { asm volatile("irg %0, %0" : "+r"(addr) : : ); return addr; } static void *load_tag(void *addr) { asm volatile("ldg %0, [%0]" : "+r"(addr) : : ); return addr; } static void set_tags_dc_gva(vaddr_t va, size_t size, size_t dcsz) { do { dc_gva(va); va += dcsz; size -= dcsz; } while (size); } static void clear_mem_dc_gzva(vaddr_t va, size_t size, size_t dcsz) { do { dc_gzva(va); va += dcsz; size -= dcsz; } while (size); } static void *set_tags_helper(void *addr, size_t size) { vaddr_t va = (vaddr_t)addr; vaddr_t end = va + size; assert(!(va & MEMTAG_GRANULE_MASK)); assert(!(size & MEMTAG_GRANULE_MASK)); while (va < end) va = stg_and_advance(va); return addr; } static void *set_tags_dc_helper(void *addr, size_t size) { size_t dcsz = dczid_block_size(); vaddr_t va = (vaddr_t)addr; size_t mask = dcsz - 1; size_t s = 0; if (va & mask) { s = MIN(dcsz - (va & mask), size); set_tags_helper((void *)va, s); va += s; size -= s; } s = size & ~mask; if (s) { set_tags_dc_gva(va, s, dcsz); va += s; size -= s; } if (size) set_tags_helper((void *)va, size); return addr; } static void *set_tags_dc(void *addr, size_t size, uint8_t tag) { return set_tags_dc_helper(memtag_insert_tag(addr, tag), size); } static void *set_random_tags_dc(void *addr, size_t size) { return set_tags_dc_helper(insert_random_tag(addr), size); } static void *set_tags(void *addr, size_t size, uint8_t tag) { return set_tags_helper(memtag_insert_tag(addr, tag), size); } static void *set_random_tags(void *addr, size_t size) { return set_tags_helper(insert_random_tag(addr), size); } static void clear_mem(void *va, size_t size) { set_tags(va, size, 0); memset(memtag_strip_tag(va), 0, size); } static void clear_mem_dc(void *addr, size_t size) { size_t dcsz = dczid_block_size(); vaddr_t va = (vaddr_t)addr; size_t mask = dcsz - 1; size_t s = 0; if (va & mask) { s = MIN(dcsz - (va & mask), size); clear_mem((void *)va, s); va += s; size -= s; } s = size & ~mask; if (s) { clear_mem_dc_gzva(va, s, dcsz); va += s; size -= s; } if (size) clear_mem((void *)va, size); } static uint8_t read_tag(const void *addr) { return memtag_get_tag(load_tag((void *)addr)); } static const struct __memtag_ops ops_dc_enabled = { .set_tags = set_tags_dc, .set_random_tags = set_random_tags_dc, .clear_mem = clear_mem_dc, .read_tag = read_tag, }; static const struct __memtag_ops ops_enabled = { .set_tags = set_tags, .set_random_tags = set_random_tags, .clear_mem = clear_mem, .read_tag = read_tag, }; const struct __memtag_ops __memtag_ops_disabled = { .set_tags = __memtag_disabled_set_tags, .set_random_tags = __memtag_disabled_set_random_tags, .clear_mem = __memtag_disabled_clear_mem, .read_tag = __memtag_disabled_read_tag, }; const struct __memtag_ops *__memtag_ops = &__memtag_ops_disabled; void memtag_init_ops(unsigned int memtag_impl) { if (memtag_impl >= 2) { /* * Data zero is always available for S-EL1 if MTE is * enabled, but for S-EL0 it may depend on configuration. */ if (data_zero_prohibited()) __memtag_ops = &ops_enabled; else __memtag_ops = &ops_dc_enabled; } else { __memtag_ops = &__memtag_ops_disabled; } } #endif optee_os-4.3.0/lib/libutils/ext/arch/arm/sub.mk000066400000000000000000000004761464416617300213710ustar00rootroot00000000000000ifeq ($(CFG_UNWIND),y) srcs-$(CFG_ARM32_$(sm)) += aeabi_unwind.c endif srcs-$(CFG_ARM32_$(sm)) += atomic_a32.S srcs-$(CFG_ARM64_$(sm)) += atomic_a64.S srcs-y += auxval.c ifneq ($(sm),ldelf) # TA, core srcs-$(CFG_ARM32_$(sm)) += mcount_a32.S srcs-$(CFG_ARM64_$(sm)) += mcount_a64.S endif srcs-$(CFG_MEMTAG) += memtag.c optee_os-4.3.0/lib/libutils/ext/arch/riscv/000077500000000000000000000000001464416617300206075ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/arch/riscv/atomic_rv.S000066400000000000000000000006051464416617300227170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright 2022-2023 NXP */ #include /* uint32_t atomic_inc32(uint32_t *v); */ FUNC atomic_inc32 , : li a1, 1 amoadd.w.aqrl a2, a1, (a0) add a0, a1, a2 ret END_FUNC atomic_inc32 /* uint32_t atomic_dec32(uint32_t *v); */ FUNC atomic_dec32 , : li a1, -1 amoadd.w.aqrl a2, a1, (a0) add a0, a1, a2 ret END_FUNC atomic_dec32 optee_os-4.3.0/lib/libutils/ext/arch/riscv/mcount_rv.S000066400000000000000000000050411464416617300227470ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation * Copyright (c) 2016, Linaro Limited */ #include #if defined(CFG_FTRACE_SUPPORT) /* * Convert return address to call site address by subtracting the size of one * instruction. */ .macro adjust_pc rd, rn addi \rd, \rn, -4 .endm #ifdef RV32 /* Get instrumented function's pc value */ .macro get_pc reg LDR \reg, REGOFF(3)(sp) addi \reg, \reg, -4 .endm /* Get instrumented function's ra address pointer */ .macro get_ra_addr reg LDR \reg, REGOFF(2)(sp) addi \reg, \reg, -4 .endm #else /* RV64 */ /* Get instrumented function's pc value */ .macro get_pc reg LDR \reg, REGOFF(1)(sp) addi \reg, \reg, -4 .endm /* Get instrumented function's ra address pointer */ .macro get_ra_addr reg LDR \reg, REGOFF(0)(sp) addi \reg, \reg, -8 .endm #endif /* RV32 */ /* * void _mcount(void *return_address) * @return_address: return address to instrumented function * * With the -pg option, the compiler inserts a call to _mcount into * every function prologue. * a0 contains the value of ra before the call, that is the return * address to the caller of the instrumented function. The callee, i.e. the * instrumented function itself, is determined from the current value of ra. * Then we call: * void __mcount_internal(void *frompc, void *selfpc); */ FUNC _mcount, : addi sp, sp, -16 /* Save ra and s0(fp) onto stack */ #ifdef RV32 STR ra, REGOFF(3)(sp) STR s0, REGOFF(2)(sp) #else STR ra, REGOFF(1)(sp) STR s0, REGOFF(0)(sp) #endif /* Setup frame pointer */ addi s0, sp, 16 #ifdef CFG_FTRACE_SUPPORT get_pc a0 get_ra_addr a1 call ftrace_enter #endif /* Restore ra and s0(fp) from stack */ #ifdef RV32 LDR s0, REGOFF(2)(sp) LDR ra, REGOFF(3)(sp) #else LDR s0, REGOFF(0)(sp) LDR ra, REGOFF(1)(sp) #endif addi sp, sp, 16 ret END_FUNC _mcount #ifdef CFG_FTRACE_SUPPORT FUNC __ftrace_return, : /* Save return value regs */ addi sp, sp, -REGOFF(8) STR a0, REGOFF(0)(sp) STR a1, REGOFF(1)(sp) STR a2, REGOFF(2)(sp) STR a3, REGOFF(3)(sp) STR a4, REGOFF(4)(sp) STR a5, REGOFF(5)(sp) STR a6, REGOFF(6)(sp) STR a7, REGOFF(7)(sp) /* Get return address of parent func */ call ftrace_return mv ra, a0 /* Restore return value regs */ LDR a0, REGOFF(0)(sp) LDR a1, REGOFF(1)(sp) LDR a2, REGOFF(2)(sp) LDR a3, REGOFF(3)(sp) LDR a4, REGOFF(4)(sp) LDR a5, REGOFF(5)(sp) LDR a6, REGOFF(6)(sp) LDR a7, REGOFF(7)(sp) addi sp, sp, REGOFF(8) ret END_FUNC __ftrace_return #endif #endif /* CFG_FTRACE_SUPPORT */ optee_os-4.3.0/lib/libutils/ext/arch/riscv/sub.mk000066400000000000000000000001201464416617300217220ustar00rootroot00000000000000srcs-y+= atomic_rv.S ifneq ($(sm),ldelf) # TA, core srcs-y += mcount_rv.S endif optee_os-4.3.0/lib/libutils/ext/consttime_memcmp.c000066400000000000000000000041061464416617300222540ustar00rootroot00000000000000// SPDX-License-Identifier: ISC /* * Copyright (C) 2019 Linaro Limited * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include /* Making a portable memcmp that has no internal branches and loops always * once for every byte without early-out shortcut has a few challenges. * * Inspired by 'timingsafe_memcmp()' from the BSD system and * https://github.com/libressl-portable/openbsd/blob/master/src/lib/libc/string/timingsafe_memcmp.c * * Sadly, that one is not portable C: It makes assumptions on the representation * of negative integers and assumes sign-preserving right-shift of negative * signed values. This is a rewrite from scratch that should not suffer from * such issues. * * 2015-12-12, J. Perlinger (perlinger-at-ntp-dot-org) */ int consttime_memcmp(const void *p1, const void *p2, size_t nb) { const unsigned char *ucp1 = p1; const unsigned char *ucp2 = p2; unsigned int isLT = 0u; unsigned int isGT = 0u; volatile unsigned int mask = (1u << CHAR_BIT); for (/*NOP*/; 0 != nb; --nb, ++ucp1, ++ucp2) { isLT |= mask & ((unsigned int)*ucp1 - (unsigned int)*ucp2); isGT |= mask & ((unsigned int)*ucp2 - (unsigned int)*ucp1); mask &= ~(isLT | isGT); } return (int)(isGT >> CHAR_BIT) - (int)(isLT >> CHAR_BIT); } optee_os-4.3.0/lib/libutils/ext/fault_mitigation.c000066400000000000000000000065201464416617300222520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2022, Linaro Limited */ #include #include #ifndef __KERNEL__ struct ftmn_func_arg *__ftmn_global_func_arg; #endif /* * These functions can be implemented in assembly if needed. They would * provide the same API but an implementation more resilient to fault * injections. * * For now there is no need since it's enough with the single redundancy * provided just by having these function implemented separately from where * they are used. */ unsigned long __weak ___ftmn_return_res(struct ftmn_check *check, unsigned long steps, unsigned long res) { if (check->steps != steps) FTMN_PANIC(); if ((check->res ^ FTMN_DEFAULT_HASH) != res) FTMN_PANIC(); return res; } void __weak ___ftmn_expect_state(struct ftmn_check *check, enum ftmn_incr incr, unsigned long steps, unsigned long res) { if ((check->res ^ FTMN_DEFAULT_HASH) != res) FTMN_PANIC(); if (check->steps != steps) FTMN_PANIC(); check->steps += incr; } void __weak ___ftmn_callee_done(struct ftmn_func_arg *arg, unsigned long my_hash, unsigned long res) { arg->hash ^= my_hash; arg->res = arg->hash ^ res; } void __weak ___ftmn_callee_done_not_zero(struct ftmn_func_arg *arg, unsigned long my_hash, unsigned long res) { if (res == 0) FTMN_PANIC(); arg->hash ^= my_hash; arg->res = arg->hash ^ res; } void __weak ___ftmn_callee_done_memcmp(struct ftmn_func_arg *arg, unsigned long my_hash, int res, ftmn_memcmp_t my_memcmp, const void *p1, const void *p2, size_t nb) { int res2 = 0; if (!nb) FTMN_PANIC(); res2 = my_memcmp(p1, p2, nb); if (res2 != res) FTMN_PANIC(); arg->hash ^= my_hash; arg->res = arg->hash ^ res; } void __weak ___ftmn_callee_done_check(struct ftmn_func_arg *arg, unsigned long my_hash, struct ftmn_check *check, enum ftmn_incr incr, unsigned long steps, unsigned long res) { if ((check->res ^ FTMN_DEFAULT_HASH) != res) FTMN_PANIC(); if (check->steps != steps) FTMN_PANIC(); check->steps += incr; if (arg) { arg->hash ^= my_hash; arg->res = check->res ^ FTMN_DEFAULT_HASH ^ arg->hash; } } void ___ftmn_callee_update_not_zero(struct ftmn_func_arg *arg, unsigned long res) { if (!res) FTMN_PANIC(); arg->res = arg->hash ^ res; } void __weak ___ftmn_copy_linked_call_res(struct ftmn_check *check, enum ftmn_incr incr, struct ftmn_func_arg *arg, unsigned long res) { if ((arg->res ^ arg->hash) != res) FTMN_PANIC(); check->res = res ^ FTMN_DEFAULT_HASH; check->steps += incr; } void __weak ___ftmn_set_check_res(struct ftmn_check *check, enum ftmn_incr incr, unsigned long res) { check->steps += incr; check->res = res ^ FTMN_DEFAULT_HASH; } void __weak ___ftmn_set_check_res_not_zero(struct ftmn_check *check, enum ftmn_incr incr, unsigned long res) { if (!res) FTMN_PANIC(); check->steps += incr; check->res = res ^ FTMN_DEFAULT_HASH; } void __weak ___ftmn_set_check_res_memcmp(struct ftmn_check *check, enum ftmn_incr incr, int res, ftmn_memcmp_t my_memcmp, const void *p1, const void *p2, size_t nb) { int res2 = 0; if (!nb) FTMN_PANIC(); res2 = my_memcmp(p1, p2, nb); if (res2 != res) FTMN_PANIC(); check->steps += incr; check->res = FTMN_DEFAULT_HASH ^ res; } optee_os-4.3.0/lib/libutils/ext/ftrace/000077500000000000000000000000001464416617300200105ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/ftrace/ftrace.c000066400000000000000000000064751464416617300214340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019, Linaro Limited */ /* * APIs defined in this file are required to use __noprof attribute to * avoid any circular dependency during profiling. So this requirement * prohibits these APIs to use standard library APIs as those can be * profiled too. */ #include #include #include #if defined(__KERNEL__) #if defined(ARM32) || defined(ARM64) #include #elif defined(RV32) || defined(RV64) #include #endif #include #include #include #include #else #if defined(ARM32) || defined(ARM64) #include #elif defined(RV32) || defined(RV64) #include #endif #include #include #endif #include "ftrace.h" static __noprof struct ftrace_buf *get_fbuf(void) { #if defined(__KERNEL__) short int ct = thread_get_id_may_fail(); struct ts_session *s = NULL; struct thread_specific_data *tsd = NULL; if (ct == -1) return NULL; if (!(core_mmu_user_va_range_is_defined() && core_mmu_user_mapping_is_active())) return NULL; tsd = thread_get_tsd(); s = TAILQ_FIRST(&tsd->sess_stack); if (!s || tsd->ctx != s->ctx) return NULL; if (!is_ta_ctx(s->ctx) || to_ta_ctx(s->ctx)->panicked) return NULL; if (s->fbuf && s->fbuf->syscall_trace_enabled && !s->fbuf->syscall_trace_suspended) return s->fbuf; else return NULL; #else return &__ftrace_buf_start; #endif } static void __noprof add_elem(struct ftrace_buf *fbuf, uint8_t level, uint64_t val) { uint64_t *elem = NULL; size_t idx = fbuf->curr_idx; /* Make sure the topmost byte doesn't contain useful information */ assert(!(val >> 56)); elem = (uint64_t *)((vaddr_t)fbuf + fbuf->buf_off) + idx; *elem = SHIFT_U64(level, 56) | val; idx++; if ((idx + 1) * sizeof(*elem) > fbuf->max_size) { idx = 0; fbuf->overflow = true; } fbuf->curr_idx = idx; } void __noprof ftrace_enter(unsigned long pc, unsigned long *lr) { uint64_t now = barrier_read_counter_timer(); struct ftrace_buf *fbuf = get_fbuf(); if (!fbuf || !fbuf->buf_off || !fbuf->max_size) return; add_elem(fbuf, fbuf->ret_idx + 1, pc); if (fbuf->ret_idx < FTRACE_RETFUNC_DEPTH) { fbuf->ret_stack[fbuf->ret_idx] = *lr; fbuf->begin_time[fbuf->ret_idx] = now; fbuf->ret_idx++; } else { /* * This scenario isn't expected as function call depth * shouldn't be more than FTRACE_RETFUNC_DEPTH. */ #if defined(__KERNEL__) panic(); #else _utee_panic(0); #endif } *lr = (unsigned long)&__ftrace_return; } unsigned long __noprof ftrace_return(void) { uint64_t now = barrier_read_counter_timer(); struct ftrace_buf *fbuf = get_fbuf(); uint64_t start = 0; uint64_t elapsed = 0; /* Check for valid return index */ if (!fbuf || !fbuf->ret_idx || fbuf->ret_idx > FTRACE_RETFUNC_DEPTH) return 0; fbuf->ret_idx--; start = fbuf->begin_time[fbuf->ret_idx]; elapsed = (now - start) * 1000000000 / read_cntfrq(); add_elem(fbuf, 0, elapsed); return fbuf->ret_stack[fbuf->ret_idx]; } #if !defined(__KERNEL__) void __noprof ftrace_longjmp(unsigned int *ret_idx) { while (__ftrace_buf_start.ret_idx > *ret_idx) ftrace_return(); } void __noprof ftrace_setjmp(unsigned int *ret_idx) { *ret_idx = __ftrace_buf_start.ret_idx; } #endif optee_os-4.3.0/lib/libutils/ext/ftrace/ftrace.h000066400000000000000000000003141464416617300214230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2019, Linaro Limited */ #ifndef FTRACE_H #define FTRACE_H void ftrace_enter(unsigned long pc, unsigned long *lr); #endif /* FTRACE_H */ optee_os-4.3.0/lib/libutils/ext/ftrace/sub.mk000066400000000000000000000001611464416617300211300ustar00rootroot00000000000000cppflags-y += -I$(sub-dir)/../../.. ifneq ($(sm),ldelf) # TA, core srcs-$(CFG_FTRACE_SUPPORT) += ftrace.c endif optee_os-4.3.0/lib/libutils/ext/include/000077500000000000000000000000001464416617300201675ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/ext/include/arm64_bti.S000066400000000000000000000017201464416617300221020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2021, Linaro Limited */ #include /* * This macro emits a program property note section identifying * architecture features which require special handling, mainly for * use in assembly files in the libraries linked with TA's. */ .macro emit_aarch64_feature_1_and, feat .pushsection .note.gnu.property, "a" .align 3 .long 2f - 1f /* n_namesz */ .long 6f - 3f /* n_desc_sz */ .long NT_GNU_PROPERTY_TYPE_0 /* n_type */ 1: .string "GNU" /* name */ 2: .align 3 3: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND /* pr_type */ .long 5f - 4f /* pr_datasz */ 4: /* * This is described with an array of char in the Linux API * spec but the text and all other usage (including binutils, * clang and GCC) treat this as a 32 bit value so no swizzling * is required for big endian. */ .long \feat /* property */ 5: .align 3 6: .popsection .endm optee_os-4.3.0/lib/libutils/ext/include/asm.S000066400000000000000000000033041464416617300210730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2020, Linaro Limited */ #if defined(__aarch64__) #include #elif defined(__riscv) #include #endif #if defined(__aarch64__) && ((defined(__KERNEL__) && defined(CFG_CORE_BTI)) || \ (!defined(__KERNEL__) && defined(CFG_TA_BTI))) #define BTI(...) __VA_ARGS__ #else #define BTI(...) #endif #if defined(CFG_UNWIND) && defined(__arm__) #define UNWIND(...) __VA_ARGS__ #else #define UNWIND(...) #endif .macro FUNC name colon section=default align=4 _bti=default .ifc \section\(),default .section .text.\name .else .section \section , "ax" , %progbits .endif .global \name .type \name , %function .balign \align \name \colon UNWIND( .fnstart) .ifc \_bti\(),default BTI( bti c) .endif .endm .macro LOCAL_FUNC name colon section=default align=4 _bti=default .ifc \section\(),default .section .text.\name .else .section \section , "ax" , %progbits .endif .type \name , %function .balign \align \name \colon UNWIND( .fnstart) .ifc \_bti\(),default BTI( bti c) .endif .endm .macro WEAK_FUNC name colon section=default align=4 _bti=default .ifc \section\(),default .section .text.\name .else .section \section , "ax" , %progbits .endif .weak \name .type \name , %function .balign \align \name \colon UNWIND( .fnstart) .ifc \_bti\(),default BTI( bti c) .endif .endm .macro END_FUNC name UNWIND( .fnend) .size \name , .-\name .endm .macro DATA name colon .global \name .type \name , %object \name \colon .endm .macro LOCAL_DATA name colon .type \name , %object \name \colon .endm .macro END_DATA name .size \name , .-\name .endm optee_os-4.3.0/lib/libutils/ext/include/atomic.h000066400000000000000000000025331464416617300216170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2016-2019, Linaro Limited */ #ifndef __ATOMIC_H #define __ATOMIC_H #include #include uint32_t atomic_inc32(volatile uint32_t *v); uint32_t atomic_dec32(volatile uint32_t *v); static inline bool atomic_cas_uint(unsigned int *p, unsigned int *oval, unsigned int nval) { return __compiler_compare_and_swap(p, oval, nval); } static inline bool atomic_cas_u32(uint32_t *p, uint32_t *oval, uint32_t nval) { return __compiler_compare_and_swap(p, oval, nval); } static inline int atomic_load_int(int *p) { return __compiler_atomic_load(p); } static inline short int atomic_load_short(short int *p) { return __compiler_atomic_load(p); } static inline unsigned int atomic_load_uint(unsigned int *p) { return __compiler_atomic_load(p); } static inline uint32_t atomic_load_u32(const uint32_t *p) { return __compiler_atomic_load(p); } static inline void atomic_store_int(int *p, int val) { __compiler_atomic_store(p, val); } static inline void atomic_store_short(short int *p, short int val) { __compiler_atomic_store(p, val); } static inline void atomic_store_uint(unsigned int *p, unsigned int val) { __compiler_atomic_store(p, val); } static inline void atomic_store_u32(uint32_t *p, uint32_t val) { __compiler_atomic_store(p, val); } #endif /*__ATOMIC_H*/ optee_os-4.3.0/lib/libutils/ext/include/bitstring.h000066400000000000000000000123051464416617300223460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Paul Vixie. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SYS_BITSTRING_H_ #define _SYS_BITSTRING_H_ typedef unsigned char bitstr_t; /* internal macros */ /* byte of the bitstring bit is in */ #define _bit_byte(bit) \ ((bit) >> 3) /* mask for the bit within its byte */ #define _bit_mask(bit) \ (1 << ((bit)&0x7)) /* external macros */ /* bytes in a bitstring of nbits bits */ #define bitstr_size(nbits) \ (((nbits) + 7) >> 3) /* allocate a bitstring */ #define bit_alloc(nbits) \ (bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t)) /* allocate a bitstring on the stack */ #define bit_decl(name, nbits) \ ((name)[bitstr_size(nbits)]) /* is bit N of bitstring name set? */ #define bit_test(name, bit) \ ((name)[_bit_byte(bit)] & _bit_mask(bit)) /* set bit N of bitstring name */ #define bit_set(name, bit) \ ((name)[_bit_byte(bit)] |= _bit_mask(bit)) /* clear bit N of bitstring name */ #define bit_clear(name, bit) \ ((name)[_bit_byte(bit)] &= ~_bit_mask(bit)) /* clear bits start ... stop in bitstring */ #define bit_nclear(name, start, stop) do { \ register bitstr_t *_name = (name); \ register int _start = (start), _stop = (stop); \ register int _startbyte = _bit_byte(_start); \ register int _stopbyte = _bit_byte(_stop); \ if (_startbyte == _stopbyte) { \ _name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \ (0xff << ((_stop&0x7) + 1))); \ } else { \ _name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \ while (++_startbyte < _stopbyte) \ _name[_startbyte] = 0; \ _name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \ } \ } while (0) /* set bits start ... stop in bitstring */ #define bit_nset(name, start, stop) do { \ register bitstr_t *_name = (name); \ register int _start = (start), _stop = (stop); \ register int _startbyte = _bit_byte(_start); \ register int _stopbyte = _bit_byte(_stop); \ if (_startbyte == _stopbyte) { \ _name[_startbyte] |= ((0xff << (_start&0x7)) & \ (0xff >> (7 - (_stop&0x7)))); \ } else { \ _name[_startbyte] |= 0xff << ((_start)&0x7); \ while (++_startbyte < _stopbyte) \ _name[_startbyte] = 0xff; \ _name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \ } \ } while (0) /* find first bit clear in name */ #define bit_ffc(name, nbits, value) do { \ register bitstr_t *_name = (name); \ register int _byte, _nbits = (nbits); \ register int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \ if (_nbits > 0) \ for (_byte = 0; _byte <= _stopbyte; ++_byte) \ if (_name[_byte] != 0xff) { \ bitstr_t _lb; \ _value = _byte << 3; \ for (_lb = _name[_byte]; (_lb&0x1); \ ++_value, _lb >>= 1); \ break; \ } \ if (_value >= nbits) \ _value = -1; \ *(value) = _value; \ } while (0) /* find first bit set in name */ #define bit_ffs_from(name, nbits, startbit, value) do { \ bitstr_t *_name = (name); \ int _byte = 0; \ int _nbits = (nbits); \ int _startbyte = _bit_byte(startbit); \ int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \ bitstr_t _test_bit_mask = 0xff << ((startbit) % 8); \ \ if (_nbits > 0) { \ for (_byte = _startbyte; _byte <= _stopbyte; ++_byte) { \ if (_name[_byte] & _test_bit_mask) { \ bitstr_t _lb = 0; \ \ _value = _byte << 3; \ for (_lb = _name[_byte] & _test_bit_mask; \ !(_lb&0x1); ++_value, _lb >>= 1) \ ; \ break; \ } \ _test_bit_mask = 0xff; \ } \ } \ if (_value >= nbits) \ _value = -1; \ *(value) = _value; \ } while (0) #define bit_ffs(name, nbits, value) \ bit_ffs_from((name), (nbits), 0, (value)) #endif /* !_SYS_BITSTRING_H_ */ optee_os-4.3.0/lib/libutils/ext/include/compiler.h000066400000000000000000000233261464416617300221600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef COMPILER_H #define COMPILER_H /* * Macros that should be used instead of using __attribute__ directly to * ease portability and make the code easier to read. * * Some of the defines below is known to sometimes cause conflicts when * this file is included from xtest in normal world. It is assumed that * the conflicting defines has the same meaning in that environment. * Surrounding the troublesome defines with #ifndef should be enough. */ #define __deprecated __attribute__((deprecated)) #ifndef __packed #define __packed __attribute__((packed)) #endif #define __weak __attribute__((weak)) #define __alias(x) __attribute__((alias(x))) #ifndef __noreturn #define __noreturn __attribute__((__noreturn__)) #endif #define __pure __attribute__((pure)) #define __aligned(x) __attribute__((aligned(x))) #define __printf(a, b) __attribute__((format(printf, a, b))) #define __noinline __attribute__((noinline)) #define __attr_const __attribute__((__const__)) #ifndef __unused #define __unused __attribute__((unused)) #endif #define __maybe_unused __attribute__((unused)) #ifndef __used #define __used __attribute__((__used__)) #endif #define __must_check __attribute__((warn_unused_result)) #define __cold __attribute__((__cold__)) #define __section(x) __attribute__((section(x))) #define __data __section(".data") #define __bss __section(".bss") #ifdef __clang__ #define __SECTION_FLAGS_RODATA #else /* * Override sections flags/type generated by the C compiler to make sure they * are: "a",%progbits (thus creating an allocatable, non-writeable, non- * executable data section). * The trailing COMMENT_CHAR comments out the flags generated by the compiler. * This avoids a harmless warning with GCC. */ #if defined(__aarch64__) || defined(__arm__) #define COMMENT_CHAR "//" #else #define COMMENT_CHAR "#" #endif #define __SECTION_FLAGS_RODATA ",\"a\",%progbits " COMMENT_CHAR #endif #define __rodata __section(".rodata" __SECTION_FLAGS_RODATA) #define __rodata_dummy __section(".rodata.dummy" __SECTION_FLAGS_RODATA) #define __rodata_unpaged(x) \ __section(".rodata.__unpaged." x __SECTION_FLAGS_RODATA) #ifdef CFG_CORE_ASLR #define __relrodata_unpaged(x) __section(".data.rel.ro.__unpaged." x) #else #define __relrodata_unpaged(x) __rodata_unpaged(x) #endif #ifdef CFG_NS_VIRTUALIZATION #define __nex_bss __section(".nex_bss") #define __nex_data __section(".nex_data") #else /* CFG_NS_VIRTUALIZATION */ #define __nex_bss #define __nex_data #endif /* CFG_NS_VIRTUALIZATION */ #define __noprof __attribute__((no_instrument_function)) #define __nostackcheck __attribute__((no_instrument_function)) #define __compiler_bswap64(x) __builtin_bswap64((x)) #define __compiler_bswap32(x) __builtin_bswap32((x)) #define __compiler_bswap16(x) __builtin_bswap16((x)) #define __GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + \ __GNUC_PATCHLEVEL__) #if __GCC_VERSION >= 50100 && !defined(__CHECKER__) #define __HAVE_BUILTIN_OVERFLOW 1 #endif #if __GCC_VERSION >= 90100 && !defined(__CHECKER__) #define __HAVE_SINGLE_ARGUMENT_STATIC_ASSERT 1 #endif #ifdef __HAVE_BUILTIN_OVERFLOW #define __compiler_add_overflow(a, b, res) \ __builtin_add_overflow((a), (b), (res)) #define __compiler_sub_overflow(a, b, res) \ __builtin_sub_overflow((a), (b), (res)) #define __compiler_mul_overflow(a, b, res) \ __builtin_mul_overflow((a), (b), (res)) #else /*!__HAVE_BUILTIN_OVERFLOW*/ /* * Copied/inspired from https://www.fefe.de/intof.html */ #define __INTOF_ASSIGN(dest, src) (__extension__({ \ typeof(src) __intof_x = (src); \ typeof(dest) __intof_y = __intof_x; \ (((uintmax_t)__intof_x == (uintmax_t)__intof_y) && \ ((__intof_x < 1) == (__intof_y < 1)) ? \ (void)((dest) = __intof_y) , 0 : 1); \ })) #define __INTOF_ADD(c, a, b) (__extension__({ \ typeof(a) __intofa_a = (a); \ typeof(b) __intofa_b = (b); \ intmax_t __intofa_a_signed = __intofa_a; \ uintmax_t __intofa_a_unsigned = __intofa_a; \ intmax_t __intofa_b_signed = __intofa_b; \ uintmax_t __intofa_b_unsigned = __intofa_b; \ \ __intofa_b < 1 ? \ __intofa_a < 1 ? \ ((INTMAX_MIN - __intofa_b_signed <= \ __intofa_a_signed)) ? \ __INTOF_ASSIGN((c), __intofa_a_signed + \ __intofa_b_signed) : 1 \ : \ ((__intofa_a_unsigned >= (uintmax_t)-__intofa_b) ? \ __INTOF_ASSIGN((c), __intofa_a_unsigned + \ __intofa_b_signed) \ : \ __INTOF_ASSIGN((c), \ (intmax_t)(__intofa_a_unsigned + \ __intofa_b_signed))) \ : \ __intofa_a < 1 ? \ ((__intofa_b_unsigned >= (uintmax_t)-__intofa_a) ? \ __INTOF_ASSIGN((c), __intofa_a_signed + \ __intofa_b_unsigned) \ : \ __INTOF_ASSIGN((c), \ (intmax_t)(__intofa_a_signed + \ __intofa_b_unsigned))) \ : \ ((UINTMAX_MAX - __intofa_b_unsigned >= \ __intofa_a_unsigned) ? \ __INTOF_ASSIGN((c), __intofa_a_unsigned + \ __intofa_b_unsigned) : 1); \ })) #define __INTOF_SUB(c, a, b) (__extension__({ \ typeof(a) __intofs_a = a; \ typeof(b) __intofs_b = b; \ intmax_t __intofs_a_signed = __intofs_a; \ uintmax_t __intofs_a_unsigned = __intofs_a; \ intmax_t __intofs_b_signed = __intofs_b; \ uintmax_t __intofs_b_unsigned = __intofs_b; \ \ __intofs_b < 1 ? \ __intofs_a < 1 ? \ ((INTMAX_MAX + __intofs_b_signed >= \ __intofs_a_signed) ? \ __INTOF_ASSIGN((c), __intofs_a_signed - \ __intofs_b_signed) : 1) \ : \ (((uintmax_t)(UINTMAX_MAX + __intofs_b_signed) >= \ __intofs_a_unsigned) ? \ __INTOF_ASSIGN((c), __intofs_a - \ __intofs_b) : 1) \ : \ __intofs_a < 1 ? \ (((intmax_t)(INTMAX_MIN + __intofs_b) <= \ __intofs_a_signed) ? \ __INTOF_ASSIGN((c), \ (intmax_t)(__intofs_a_signed - \ __intofs_b_unsigned)) : 1) \ : \ ((__intofs_b_unsigned <= __intofs_a_unsigned) ? \ __INTOF_ASSIGN((c), __intofs_a_unsigned - \ __intofs_b_unsigned) \ : \ __INTOF_ASSIGN((c), \ (intmax_t)(__intofs_a_unsigned - \ __intofs_b_unsigned))); \ })) /* * Dealing with detecting overflow in multiplication of integers. * * First step is to remove two corner cases with the minum signed integer * which can't be represented as a positive integer + sign. * Multiply with 0 or 1 can't overflow, no checking needed of the operation, * only if it can be assigned to the result. * * After the corner cases are eliminated we convert the two factors to * positive unsigned values, keeping track of the original in another * variable which is used at the end to determine the sign of the product. * * The two terms (a and b) are divided into upper and lower half (x1 upper * and x0 lower), so the product is: * ((a1 << hshift) + a0) * ((b1 << hshift) + b0) * which also is: * ((a1 * b1) << (hshift * 2)) + (T1) * ((a1 * b0 + a0 * b1) << hshift) + (T2) * (a0 * b0) (T3) * * From this we can tell and (a1 * b1) has to be 0 or we'll overflow, that * is, at least one of a1 or b1 has to be 0. Once this has been checked the * addition: ((a1 * b0) << hshift) + ((a0 * b1) << hshift) * isn't an addition as one of the terms will be 0. * * Since each factor in: (a0 * b0) * only uses half the capicity of the underlaying type it can't overflow * * The addition of T2 and T3 can overflow so we use __INTOF_ADD() to * perform that addition. If the addition succeeds without overflow the * result is assigned the required sign and checked for overflow again. */ #define __intof_mul_negate ((__intof_oa < 1) != (__intof_ob < 1)) #define __intof_mul_hshift (sizeof(uintmax_t) * 8 / 2) #define __intof_mul_hmask (UINTMAX_MAX >> __intof_mul_hshift) #define __intof_mul_a0 ((uintmax_t)(__intof_a) >> __intof_mul_hshift) #define __intof_mul_b0 ((uintmax_t)(__intof_b) >> __intof_mul_hshift) #define __intof_mul_a1 ((uintmax_t)(__intof_a) & __intof_mul_hmask) #define __intof_mul_b1 ((uintmax_t)(__intof_b) & __intof_mul_hmask) #define __intof_mul_t (__intof_mul_a1 * __intof_mul_b0 + \ __intof_mul_a0 * __intof_mul_b1) #define __INTOF_MUL(c, a, b) (__extension__({ \ typeof(a) __intof_oa = (a); \ typeof(a) __intof_a = __intof_oa < 1 ? -__intof_oa : __intof_oa; \ typeof(b) __intof_ob = (b); \ typeof(b) __intof_b = __intof_ob < 1 ? -__intof_ob : __intof_ob; \ typeof(c) __intof_c; \ \ __intof_oa == 0 || __intof_ob == 0 || \ __intof_oa == 1 || __intof_ob == 1 ? \ __INTOF_ASSIGN((c), __intof_oa * __intof_ob) : \ (__intof_mul_a0 && __intof_mul_b0) || \ __intof_mul_t > __intof_mul_hmask ? 1 : \ __INTOF_ADD((__intof_c), __intof_mul_t << __intof_mul_hshift, \ __intof_mul_a1 * __intof_mul_b1) ? 1 : \ __intof_mul_negate ? __INTOF_ASSIGN((c), -__intof_c) : \ __INTOF_ASSIGN((c), __intof_c); \ })) #define __compiler_add_overflow(a, b, res) __INTOF_ADD(*(res), (a), (b)) #define __compiler_sub_overflow(a, b, res) __INTOF_SUB(*(res), (a), (b)) #define __compiler_mul_overflow(a, b, res) __INTOF_MUL(*(res), (a), (b)) #endif /*!__HAVE_BUILTIN_OVERFLOW*/ #define __compiler_compare_and_swap(p, oval, nval) \ __atomic_compare_exchange_n((p), (oval), (nval), true, \ __ATOMIC_ACQUIRE, __ATOMIC_RELAXED) \ #define __compiler_atomic_load(p) __atomic_load_n((p), __ATOMIC_RELAXED) #define __compiler_atomic_store(p, val) \ __atomic_store_n((p), (val), __ATOMIC_RELAXED) #define barrier() asm volatile ("" : : : "memory") #ifndef __has_attribute #define __has_attribute(x) 0 #endif #if __has_attribute(__fallthrough__) #define fallthrough __attribute__((__fallthrough__)) #else #define fallthrough do {} while (0) /* fallthrough */ #endif #ifndef __clang__ #define __no_stackprot __attribute__((__optimize__ ("-fno-stack-protector"))) #else #define __no_stackprot #endif #define __inhibit_loop_to_libcall \ __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns"))) #endif /*COMPILER_H*/ optee_os-4.3.0/lib/libutils/ext/include/config.h000066400000000000000000000046031464416617300216100ustar00rootroot00000000000000/* SPDX-License-Identifier: Apache-2.0 */ /* * Copyright (c) 2017 Intel Corporation * */ #ifndef __CONFIG_H_ #define __CONFIG_H_ /** * @brief Check for macro definition in compiler-visible expressions * * This trick was pioneered in Linux as the config_enabled() macro. * The madness has the effect of taking a macro value that may be * defined to "1" (e.g. CONFIG_MYFEATURE), or may not be defined at * all and turning it into a literal expression that can be used at * "runtime". That is, it works similarly to * "defined(CONFIG_MYFEATURE)" does except that it is an expansion * that can exist in a standard expression and be seen by the compiler * and optimizer. Thus much ifdef usage can be replaced with cleaner * expressions like: * * if (IS_ENABLED(CONFIG_MYFEATURE)) * myfeature_enable(); * * INTERNAL * First pass just to expand any existing macros, we need the macro * value to be e.g. a literal "1" at expansion time in the next macro, * not "(1)", etc... Standard recursive expansion does not work. */ #define IS_ENABLED(config_macro) Z_IS_ENABLED1(config_macro) /** * @brief As IS_ENABLED() but to be used with _CFG_* internal switches * to avoid triggering false positives with checkpatch. */ #define IS_ENABLED2(config_macro) IS_ENABLED(config_macro) /* Now stick on a "_XXXX" prefix, it will now be "_XXXX1" if config_macro * is "1", or just "_XXXX" if it's undefined. * ENABLED: Z_IS_ENABLED2(_XXXX1) * DISABLED Z_IS_ENABLED2(_XXXX) */ #define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro) /* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string * with a trailing comma), so it has the effect of making this a * two-argument tuple to the preprocessor only in the case where the * value is defined to "1" * ENABLED: _YYYY, <--- note comma! * DISABLED: _XXXX */ #define _XXXX1 _YYYY, /* Then we append an extra argument to fool the gcc preprocessor into * accepting it as a varargs macro. * arg1 arg2 arg3 * ENABLED: Z_IS_ENABLED3(_YYYY, 1, 0) * DISABLED Z_IS_ENABLED3(_XXXX 1, 0) */ #define Z_IS_ENABLED2(one_or_two_args) \ Z_IS_ENABLED3(one_or_two_args true, false) /* And our second argument is thus now cooked to be 1 in the case * where the value is defined to 1, and 0 if not: */ #define Z_IS_ENABLED3(ignore_this, val, ...) val #endif // __CONFIG_H_ optee_os-4.3.0/lib/libutils/ext/include/confine_array_index.h000066400000000000000000000127241464416617300243540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* Copyright (c) 2020 Linaro Limited */ // Copyright 2019 The Fuchsia Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /* * Content of LICENSE file mentioned above: Copyright 2019 The Fuchsia Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef FBL_CONFINE_ARRAY_INDEX_H_ #define FBL_CONFINE_ARRAY_INDEX_H_ #include // confine_array_index() bounds-checks and sanitizes an array index safely in the presence of // speculative execution information leak bugs such as Spectre V1. confine_array_index() always // returns a sanitized index, even in speculative-path execution. // // Callers need to combine confine_array_index with a conventional bounds check; the bounds // check will return any necessary errors in the nonspeculative path, confine_array_index will // confine indexes in the speculative path. // // Use: // confine_array_index() returns |index|, if it is < size, or 0 if |index| is >= size. // // Example (may leak table1 contents): // 1: int lookup3(size_t index) { // 2: if (index >= table1_size) { // 3: return -1; // 4: } // 5: size_t index2 = table1[index]; // 6: return table2[index2]; // 7: } // // Converted: // // 1: int lookup3(size_t index) { // 2: if (index >= table1_size) { // 3: return -1; // 4: } // 5: size_t safe_index = confine_array_index(index, table1_size); // 6: size_t index2 = table1[safe_index]; // 7: return table2[index2]; // 8: } #ifdef __aarch64__ static inline size_t confine_array_index(size_t index, size_t size) { size_t safe_index; // Use a conditional select and a CSDB barrier to enforce validation of |index|. // See "Cache Speculation Side-channels" whitepaper, section "Software Mitigation". // "" The combination of both a conditional select/conditional move and the new barrier are // sufficient to address this problem on ALL Arm implementations... "" asm( "cmp %1, %2\n" // %1 holds the unsanitized index "csel %0, %1, xzr, lo\n" // Select index or zero based on carry (%1 within range) "hint #20\n" // csdb : "=r"(safe_index) : "r"(index), "r"(size) : "cc"); return safe_index; } #endif #ifdef __arm__ static inline size_t confine_array_index(size_t index, size_t size) { size_t ret_val = index; /* * For the ARMv7/AArch32 case we're basing the select and barrier * code on __load_no_speculate1() in as we * lack the csel instruction. */ #ifdef __thumb2__ asm volatile ( ".syntax unified\n" "cmp %0, %1\n" "it cs\n" #ifdef __clang__ #pragma clang diagnostic push /* Avoid 'deprecated instruction in IT block [-Werror,-Winline-asm]' */ #pragma clang diagnostic ignored "-Winline-asm" #endif "movcs %0, #0\n" #ifdef __clang__ #pragma clang diagnostic pop #endif ".inst.n 0xf3af\t@ CSDB\n" ".inst.n 0x8014\t@ CSDB" : "+r" (ret_val) : "r" (size) : "cc"); #else asm volatile ( ".syntax unified\n" "cmp %0, %1\n" /* %0 holds the unsanitized index */ "movcs %0, #0\n" ".inst 0xe320f014\t@ CSDB" : "+r" (ret_val) : "r" (size) : "cc"); #endif return ret_val; } #endif /* __arm__ */ #ifdef __x86_64__ static inline size_t confine_array_index(size_t index, size_t size) { size_t safe_index = 0; // Use a conditional move to enforce validation of |index|. // The conditional move has a data dependency on the result of a comparison and cannot // execute until the comparison is resolved. // See "Software Techniques for Managing Speculation on AMD Processors", Mitigation V1-2. // See "Analyzing potential bounds check bypass vulnerabilities", Revision 002, // Section 5.2 Bounds clipping __asm__( "cmp %1, %2\n" "cmova %1, %0\n" // Select between $0 and |index| : "+r"(safe_index) : "r"(index), "r"(size) : "cc"); return safe_index; } #endif #ifdef __riscv static inline size_t confine_array_index(size_t index, size_t size) { /* * The naive C implementation without protection * against side-channel attacks. */ if (index < size) return index; return 0; } #endif #endif // FBL_CONFINE_ARRAY_INDEX_H_ optee_os-4.3.0/lib/libutils/ext/include/fault_mitigation.h000066400000000000000000000560021464416617300237020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Linaro Limited */ #ifndef __FAULT_MITIGATION_H #define __FAULT_MITIGATION_H #include #include #include #include #ifdef __KERNEL__ #include #include #else #include #endif /* * Fault migitigation helpers to make successful Hardware Fault Attacks * harder to achieve. The paper [1] by Riscure gives background to the * problem. * * These helpers aim to make it hard for a single glitch attack to succeed * while the protected function or one of the ftmn_*() functions are * executed. * * To have something to work with we assume that a single glitch may affect * a few instructions in sequence to do nothing or to corrupt the content * of a few registers. * * Using the terminology from [1] we are implementing the following patterns: * 3 FAULT.VALUE.CHECK * 5 FAULT.DECISION.CHECK * 9 FAULT.FLOW.CONTROL * * Additionally are the following patterns also acknowledged with a few * comments: * 1. FAULT.CONSTANT.CODING * Zero is normally a success code in OP-TEE so special functions are * added to record anything but a zero result. * 8. FAULT.NESTED.CHECK * The linked calls performed by for instance FTMN_CALL_FUNC() addresses * this by relying on the called function to update a state in * struct ftmn_func_arg which is checked when the function has returned. * 11. FAULT.PENALTY * This is implicit since we're normally trying to protect things post * boot and booting takes quite some time. * * [1] https://web.archive.org/web/20220616035354/https://www.riscure.com/uploads/2020/05/Riscure_Whitepaper_Fault_Mitigation_Patterns_final.pdf */ #include #include /* * struct ftmn_check - track current checked state * @steps: accumulated checkpoints * @res: last stored result or return value * * While a function is executed it can update its state as a way of keeping * track of important passages inside the function. When the function * returns with for instance ftmn_return_res() it is checked that the * accumulated state matches the expected state. * * @res is xored with FTMN_DEFAULT_HASH in order to retrieve the saved * result or return value. */ struct ftmn_check { unsigned long steps; unsigned long res; }; /* * struct ftmn_func_arg - track a called function * @hash: xor bitmask * @res: stored result xored with @hash * * When the call of a function is tracked @hash is initialized to hash of * caller xored with hash of called function. Before the called function * updates @res it first xors @hash with its own hash, which is supposed to * restore @hash to the hash of the calling function. This allows the * calling function to confirm that the correct function has been called. */ struct ftmn_func_arg { unsigned long hash; unsigned long res; }; /* * struct ftmn - link a tracked call chain * @check: local checked state * @arg: argument for the next called tracked function * @saved_arg: pointer to an optional argument passed to this function * @arg_pp: cached return value from __ftmn_get_tsd_func_arg_pp() * @my_hash: the hash of the calling function * @called_hash:the hash of the called function * * In order to maintain the linked call chain of tracked functions the * struct ftmn_func_arg passed to this function is saved in @saved_arg * before updating the argument pointer with @arg. */ struct ftmn { struct ftmn_check check; struct ftmn_func_arg arg; struct ftmn_func_arg *saved_arg; struct ftmn_func_arg **arg_pp; unsigned long my_hash; unsigned long called_hash; }; /* * enum ftmn_incr - increase counter values * * Prime numbers to be used when increasing the accumulated state. * Different increase counters can be used to keep apart different * checkpoints. */ enum ftmn_incr { FTMN_INCR0 = 7873, FTMN_INCR1 = 7877, FTMN_INCR2 = 7879, FTMN_INCR3 = 7883, FTMN_INCR4 = 7901, FTMN_INCR5 = 7907, FTMN_INCR_RESERVED = 7919, }; typedef int (*ftmn_memcmp_t)(const void *p1, const void *p2, size_t nb); /* The default hash used when xoring the result in struct ftmn_check */ #ifdef __ILP32__ #define FTMN_DEFAULT_HASH 0x9c478bf6UL #else #define FTMN_DEFAULT_HASH 0xc478bf63e9500cb5UL #endif /* * FTMN_PANIC() - FTMN specific panic function * * This function is called whenever the FTMN function detects an * inconsistency. An inconsistency is able to occur if the system is * subject to a fault injection attack, in this case doing a panic() isn't * an extreme measure. */ #ifdef __KERNEL__ #define FTMN_PANIC() panic(); #else #define FTMN_PANIC() TEE_Panic(0); #endif #define __FTMN_MAX_FUNC_NAME_LEN 256 #define __FTMN_FUNC_BYTE(f, o, l) ((o) < (l) ? (uint8_t)(f)[(o)] : 0) #ifdef __ILP32__ #define __FTMN_GET_FUNC_U32(f, o, l) \ (SHIFT_U32(__FTMN_FUNC_BYTE((f), (o), (l)), 0) | \ SHIFT_U32(__FTMN_FUNC_BYTE((f), (o) + 1, (l)), 8) | \ SHIFT_U32(__FTMN_FUNC_BYTE((f), (o) + 2, (l)), 16) | \ SHIFT_U32(__FTMN_FUNC_BYTE((f), (o) + 3, (l)), 24)) #define __FTMN_FUNC_HASH64(f, o, l) \ (__FTMN_GET_FUNC_U32((f), (o), (l)) ^ \ __FTMN_GET_FUNC_U32((f), (o) + 4, (l))) #define __FTMN_FUNC_HASH32(f, o, l) \ (__FTMN_FUNC_HASH64((f), (o), (l)) ^ \ __FTMN_FUNC_HASH64((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 16, (l))) #else #define __FTMN_GET_FUNC_U64(f, o, l) \ (SHIFT_U64(__FTMN_FUNC_BYTE((f), (o), (l)), 0) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 1, (l)), 8) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 2, (l)), 16) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 3, (l)), 24) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 4, (l)), 32) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 5, (l)), 40) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 6, (l)), 48) | \ SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 7, (l)), 56)) #define __FTMN_FUNC_HASH32(f, o, l) \ (__FTMN_GET_FUNC_U64((f), (o), (l)) ^ \ __FTMN_GET_FUNC_U64((f), (o) + 8, (l))) #endif #define __FTMN_FUNC_HASH16(f, o, l) \ (__FTMN_FUNC_HASH32((f), (o), (l)) ^ \ __FTMN_FUNC_HASH32((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 16, (l))) #define __FTMN_FUNC_HASH8(f, o, l) \ (__FTMN_FUNC_HASH16((f), (o), (l)) ^ \ __FTMN_FUNC_HASH16((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 8, (l))) #define __FTMN_FUNC_HASH4(f, o, l) \ (__FTMN_FUNC_HASH8((f), (o), (l)) ^ \ __FTMN_FUNC_HASH8((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 4, (l))) #define __FTMN_FUNC_HASH2(f, l) \ (__FTMN_FUNC_HASH4(f, 0, l) ^ \ __FTMN_FUNC_HASH4(f, __FTMN_MAX_FUNC_NAME_LEN / 2, l)) #define __FTMN_FUNC_HASH(f, l) (unsigned long)__FTMN_FUNC_HASH2((f), (l)) #define __ftmn_step_count_1(c0) ((c0) * FTMN_INCR0) #define __ftmn_step_count_2(c0, c1) \ (__ftmn_step_count_1(c0) + (c1) * FTMN_INCR1) #define __ftmn_step_count_3(c0, c1, c2) \ (__ftmn_step_count_2(c0, c1) + (c2) * FTMN_INCR2) #define __ftmn_step_count_4(c0, c1, c2, c3) \ (__ftmn_step_count_3(c0, c1, c2) + (c3) * FTMN_INCR3) #define __ftmn_step_count_5(c0, c1, c2, c3, c4) \ (__ftmn_step_count_4(c0, c1, c2, c3) + (c4) * FTMN_INCR4) #define __ftmn_step_count_6(c0, c1, c2, c3, c4, c5) \ (__ftmn_step_count_5(c0, c1, c2, c3, c4) + (c5) * FTMN_INCR5) #define ___ftmn_args_count(_0, _1, _2, _3, _4, _5, x, ...) x #define __ftmn_args_count(...) \ ___ftmn_args_count(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0) #define ___ftmn_step_count(count, ...) __ftmn_step_count_ ## count(__VA_ARGS__) #define __ftmn_step_count(count, ...) ___ftmn_step_count(count, __VA_ARGS__) unsigned long ___ftmn_return_res(struct ftmn_check *check, unsigned long steps, unsigned long res); void ___ftmn_expect_state(struct ftmn_check *check, enum ftmn_incr incr, unsigned long steps, unsigned long res); void ___ftmn_callee_done(struct ftmn_func_arg *arg, unsigned long my_hash, unsigned long res); void ___ftmn_callee_done_not_zero(struct ftmn_func_arg *arg, unsigned long my_hash, unsigned long res); void ___ftmn_callee_done_memcmp(struct ftmn_func_arg *arg, unsigned long my_hash, int res, ftmn_memcmp_t my_memcmp, const void *p1, const void *p2, size_t nb); void ___ftmn_callee_done_check(struct ftmn_func_arg *arg, unsigned long my_hash, struct ftmn_check *check, enum ftmn_incr incr, unsigned long steps, unsigned long res); void ___ftmn_callee_update_not_zero(struct ftmn_func_arg *arg, unsigned long res); void ___ftmn_set_check_res(struct ftmn_check *check, enum ftmn_incr incr, unsigned long res); void ___ftmn_set_check_res_not_zero(struct ftmn_check *check, enum ftmn_incr incr, unsigned long res); void ___ftmn_set_check_res_memcmp(struct ftmn_check *check, enum ftmn_incr incr, int res, ftmn_memcmp_t my_memcmp, const void *p1, const void *p2, size_t nb); void ___ftmn_copy_linked_call_res(struct ftmn_check *check, enum ftmn_incr incr, struct ftmn_func_arg *arg, unsigned long res); #ifndef __KERNEL__ extern struct ftmn_func_arg *__ftmn_global_func_arg; #endif static inline struct ftmn_func_arg **__ftmn_get_tsd_func_arg_pp(void) { #if defined(CFG_FAULT_MITIGATION) && defined(__KERNEL__) if (thread_get_id_may_fail() >= 0) return &thread_get_tsd()->ftmn_arg; else return &thread_get_core_local()->ftmn_arg; #elif defined(CFG_FAULT_MITIGATION) return &__ftmn_global_func_arg; #else return NULL; #endif } static inline struct ftmn_func_arg *__ftmn_get_tsd_func_arg(void) { struct ftmn_func_arg **pp = __ftmn_get_tsd_func_arg_pp(); if (!pp) return NULL; return *pp; } static inline void __ftmn_push_linked_call(struct ftmn *ftmn, unsigned long my_hash, unsigned long called_hash) { struct ftmn_func_arg **arg_pp = __ftmn_get_tsd_func_arg_pp(); if (arg_pp) { ftmn->arg_pp = arg_pp; ftmn->my_hash = my_hash; ftmn->called_hash = called_hash; ftmn->saved_arg = *ftmn->arg_pp; *ftmn->arg_pp = &ftmn->arg; ftmn->arg.hash = my_hash; } } static inline void __ftmn_pop_linked_call(struct ftmn *ftmn) { if (ftmn->arg_pp) *ftmn->arg_pp = ftmn->saved_arg; } static inline void __ftmn_copy_linked_call_res(struct ftmn *f, enum ftmn_incr incr, unsigned long res) { if (f->arg_pp) { assert(f->arg.hash == (f->my_hash ^ f->called_hash)); assert(&f->arg == *f->arg_pp); assert((f->arg.hash ^ f->arg.res) == res); ___ftmn_copy_linked_call_res(&f->check, incr, &f->arg, res); } } static inline void __ftmn_calle_swap_hash(struct ftmn_func_arg *arg, unsigned long my_old_hash, unsigned long my_new_hash) { if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) arg->hash ^= my_old_hash ^ my_new_hash; } static inline void __ftmn_callee_done(struct ftmn_func_arg *arg, unsigned long my_hash, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) ___ftmn_callee_done(arg, my_hash, res); } static inline void __ftmn_callee_done_not_zero(struct ftmn_func_arg *arg, unsigned long hash, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) ___ftmn_callee_done_not_zero(arg, hash, res); } static inline int __ftmn_callee_done_memcmp(struct ftmn_func_arg *arg, unsigned long hash, ftmn_memcmp_t my_memcmp, const void *p1, const void *p2, size_t nb) { int res = my_memcmp(p1, p2, nb); if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) ___ftmn_callee_done_memcmp(arg, hash, res, my_memcmp, p1, p2, nb); return res; } static inline void __ftmn_callee_done_check(struct ftmn *ftmn, unsigned long my_hash, enum ftmn_incr incr, unsigned long steps, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION)) ___ftmn_callee_done_check(__ftmn_get_tsd_func_arg(), my_hash, &ftmn->check, incr, steps, res); } static inline void __ftmn_callee_update_not_zero(struct ftmn_func_arg *arg, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION) && arg) ___ftmn_callee_update_not_zero(arg, res); } static inline void __ftmn_set_check_res(struct ftmn *ftmn, enum ftmn_incr incr, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION)) ___ftmn_set_check_res(&ftmn->check, incr, res); } static inline void __ftmn_set_check_res_not_zero(struct ftmn *ftmn, enum ftmn_incr incr, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION)) ___ftmn_set_check_res_not_zero(&ftmn->check, incr, res); } /* * FTMN_FUNC_HASH() - "hash" a function name * * Function names are "hashed" into an unsigned long. The "hashing" is done * by xoring each 32/64 bit word of the function name producing a bit * pattern that should be mostly unique for each function. Only the first * 256 characters of the name are used when xoring as this is expected to * be optimized to be calculated when compiling the source code in order to * minimize the overhead. */ #define FTMN_FUNC_HASH(name) __FTMN_FUNC_HASH(name, sizeof(name)) /* * FTMN_PUSH_LINKED_CALL() - push call into a linked call chain * @ftmn: The local struct ftmn * @called_func_hash: The hash of the called function * * Inserts a call into a linked call chain or starts a new call chain if * the passed struct ftmn_func_arg pointer was NULL. * * Each FTMN_PUSH_LINKED_CALL() is supposed to be matched by a * FTMN_POP_LINKED_CALL(). */ #define FTMN_PUSH_LINKED_CALL(ftmn, called_func_hash) \ __ftmn_push_linked_call((ftmn), FTMN_FUNC_HASH(__func__), \ (called_func_hash)) /* * FTMN_SET_CHECK_RES_FROM_CALL() - copy the result from a linked call * @ftmn: The struct ftmn used during the linked call * @incr: Value to increase the checked state with * @res: Returned result to be match against the saved/copied result * * This macro is called just after a checked linked function has returned. * The return value from the function is copied from the struct ftmn_func_arg * passed to the called function into the local checked state. The checked * state is increased with @incr. @res is checked against the saved result * of the called function. */ #define FTMN_SET_CHECK_RES_FROM_CALL(ftmn, incr, res) \ __ftmn_copy_linked_call_res((ftmn), (incr), (res)) /* * FTMN_POP_LINKED_CALL() - remove a call from a linked call chain * @ftmn: The local struct ftmn * * Supposed to match a call to FTMN_PUSH_LINKED_CALL() */ #define FTMN_POP_LINKED_CALL(ftmn) __ftmn_pop_linked_call((ftmn)) /* * FTMN_CALL_FUNC() - Do a linked call to a function * @res: Variable to be assigned the result of the called function * @ftmn: The local struct ftmn * @incr: Value to increase the checked state with * @func: Function to be called * @...: Arguments to pass to @func * * This macro can be used to make a linked call to another function, the * callee. This macro depends on the callee to always update the struct * ftmn_func_arg (part of struct ftmn) even when returning an error. * * Note that in the cases where the callee may skip updating the struct * ftmn_func_arg this macro cannot be used as * FTMN_SET_CHECK_RES_FROM_CALL() would cause a panic due to mismatching * return value and saved result. */ #define FTMN_CALL_FUNC(res, ftmn, incr, func, ...) \ do { \ FTMN_PUSH_LINKED_CALL((ftmn), FTMN_FUNC_HASH(#func)); \ (res) = func(__VA_ARGS__); \ FTMN_SET_CHECK_RES_FROM_CALL((ftmn), (incr), (res)); \ FTMN_POP_LINKED_CALL((ftmn)); \ } while (0) /* * FTMN_CALLEE_DONE() - Record result of callee * @res: Result or return value * * The passed result will be stored in the struct ftmn_func_arg struct * supplied by the caller. This function must only be called once by the * callee. * * Note that this function is somewhat dangerous as any passed value will * be stored so if the value has been tampered with there is no additional * redundant checks to rely on. */ #define FTMN_CALLEE_DONE(res) \ __ftmn_callee_done(__ftmn_get_tsd_func_arg(), \ FTMN_FUNC_HASH(__func__), (res)) /* * FTMN_CALLEE_DONE_NOT_ZERO() - Record non-zero result of callee * @res: Result or return value * * The passed result will be stored in the struct ftmn_func_arg struct * supplied by the caller. This function must only be called once by the * callee. * * Note that this function is somewhat dangerous as any passed value will * be stored so if the value has been tampered with there is no additional * redundant checks to rely on. However, there are extra checks against * unintentionally storing a zero which often is interpreted as a * successful return value. */ #define FTMN_CALLEE_DONE_NOT_ZERO(res) \ __ftmn_callee_done_not_zero(__ftmn_get_tsd_func_arg(), \ FTMN_FUNC_HASH(__func__), (res)) /* * FTMN_CALLEE_DONE_CHECK() - Record result of callee with checked state * @ftmn: The local struct ftmn * @incr: Value to increase the checked state with * @exp_steps: Expected recorded checkpoints * @res: Result or return value * * The passed result will be stored in the struct ftmn_func_arg struct * supplied by the caller. This function must only be called once by the * callee. * * @res is double checked against the value stored in local checked state. * @exp_steps is checked against the locate checked state. The local * checked state is increased by @incr. */ #define FTMN_CALLEE_DONE_CHECK(ftmn, incr, exp_steps, res) \ __ftmn_callee_done_check((ftmn), FTMN_FUNC_HASH(__func__), \ (incr), (exp_steps), (res)) /* * FTMN_CALLEE_DONE_MEMCMP() - Record result of memcmp() in a callee * @my_memcmp: Function pointer of custom memcmp() * @p1: Pointer to first buffer * @p2: Pointer to second buffer * @nb: Number of bytes * * The result from the mem compare is saved in the local checked state. * This function must only be called once by the callee. */ #define FTMN_CALLEE_DONE_MEMCMP(my_memcmp, p1, p2, nb) \ __ftmn_callee_done_memcmp(__ftmn_get_tsd_func_arg(), \ FTMN_FUNC_HASH(__func__), (my_memcmp), \ (p1), (p2), (nb)) /* * FTMN_CALLEE_UPDATE_NOT_ZERO() - Update the result of a callee with a * non-zero value * @res: Result or return value * * The passed result will be stored in the struct ftmn_func_arg struct * supplied by the caller. This function can be called any number of times * by the callee, provided that one of the FTMN_CALLEE_DONE_XXX() functions * has been called first. * * Note that this function is somewhat dangerous as any passed value will * be stored so if the value has been tampered with there is no additional * redundant checks to rely on. However, there are extra checks against * unintentionally storing a zero which often is interpreted as a * successful return value. */ #define FTMN_CALLEE_UPDATE_NOT_ZERO(res) \ __ftmn_callee_update_not_zero(__ftmn_get_tsd_func_arg(), res) /* * FTMN_CALLEE_SWAP_HASH() - Remove old hash and add new hash * @my_old_hash: The old hash to remove * * This macro replaces the old expected function hash with the hash of the * current function. * * If a function is called using an alias the caller uses the hash of the * alias not the real function name. This hash is recoded in the field * "hash" in struct ftmn_func_arg which can be found with * __ftmn_get_tsd_func_arg(). * * The FTMN_CALLE_* functions only work with the real function name so the * old hash must be removed and replaced with the new for the calling * function to be able to verify the result. */ #define FTMN_CALLEE_SWAP_HASH(my_old_hash) \ __ftmn_calle_swap_hash(__ftmn_get_tsd_func_arg(), \ (my_old_hash), FTMN_FUNC_HASH(__func__)) /* * FTMN_SET_CHECK_RES() - Records a result in local checked state * @ftmn: The local struct ftmn * @incr: Value to increase the checked state with * @res: Result or return value * * Note that this function is somewhat dangerous as any passed value will * be stored so if the value has been tampered with there is no additional * redundant checks to rely on. */ #define FTMN_SET_CHECK_RES(ftmn, incr, res) \ __ftmn_set_check_res((ftmn), (incr), (res)) /* * FTMN_SET_CHECK_RES_NOT_ZERO() - Records a non-zero result in local checked * state * @ftmn: The local struct ftmn * @incr: Value to increase the checked state with * @res: Result or return value * * Note that this function is somewhat dangerous as any passed value will * be stored so if the value has been tampered with there is no additional * redundant checks to rely on. However, there are extra checks against * unintentionally storing a zero which often is interpreted as a * successful return value. */ #define FTMN_SET_CHECK_RES_NOT_ZERO(ftmn, incr, res) \ __ftmn_set_check_res_not_zero((ftmn), (incr), (res)) static inline int ftmn_set_check_res_memcmp(struct ftmn *ftmn, enum ftmn_incr incr, ftmn_memcmp_t my_memcmp, const void *p1, const void *p2, size_t nb) { int res = my_memcmp(p1, p2, nb); if (IS_ENABLED(CFG_FAULT_MITIGATION)) ___ftmn_set_check_res_memcmp(&ftmn->check, incr, res, my_memcmp, p1, p2, nb); return res; } /* * FTMN_STEP_COUNT() - Calculate total step count * * Takes variable number of arguments, up to a total of 6. Where arg0 * is the number of times the counter has been increased by FTMN_INCR0, * arg1 FTMN_INCR1 and so on. */ #define FTMN_STEP_COUNT(...) \ __ftmn_step_count(__ftmn_args_count(__VA_ARGS__), __VA_ARGS__) /* * ftmn_checkpoint() - Add a checkpoint * @ftmn: The local struct ftmn * @incr: Value to increase the checked state with * * Adds a checkpoint by increasing the internal checked state. This * can be checked at a later point in the calling function, for instance * with ftmn_return_res(). */ static inline void ftmn_checkpoint(struct ftmn *ftmn, enum ftmn_incr incr) { if (IS_ENABLED(CFG_FAULT_MITIGATION)) { /* * The purpose of the barriers is to prevent the compiler * from optimizing this increase to some other location * in the calling function. */ barrier(); ftmn->check.steps += incr; barrier(); } } /* * ftmn_expect_state() - Check expected state * @ftmn: The local struct ftmn * @incr: Value to increase the checked state with * @steps: Expected accumulated steps * @res: Expected saved result or return value * * This is a more advanced version of ftmn_checkpoint() which before * increasing the accumulated steps first checks the accumulated steps and * saved result or return value. */ static inline void ftmn_expect_state(struct ftmn *ftmn, enum ftmn_incr incr, unsigned long steps, unsigned long res) { if (IS_ENABLED(CFG_FAULT_MITIGATION)) { assert((ftmn->check.res ^ FTMN_DEFAULT_HASH) == res); assert(ftmn->check.steps == steps); ___ftmn_expect_state(&ftmn->check, incr, steps, res); } } /* * ftmn_return_res() - Check and return result * @ftmn: The local struct ftmn * @steps: Expected accumulated steps * @res: Expected saved result or return value * * Checks that the internal accumulated state matches the supplied @steps * and that the saved result or return value matches the supplied one. * * Returns @res. */ static inline unsigned long ftmn_return_res(struct ftmn *ftmn, unsigned long steps, unsigned long res) { /* * We're expecting that the compiler does a tail call optimization * allowing ___ftmn_return_res() to have full control over the * returned value. Thus trying to reduce the window where the * return value can be tampered with. */ if (IS_ENABLED(CFG_FAULT_MITIGATION)) { assert((ftmn->check.res ^ FTMN_DEFAULT_HASH) == res); assert(ftmn->check.steps == steps); return ___ftmn_return_res(&ftmn->check, steps, res); } return res; } #endif /*__FAULT_MITIGATION_H*/ optee_os-4.3.0/lib/libutils/ext/include/mempool.h000066400000000000000000000044051464416617300220130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __MEMPOOL_H #define __MEMPOOL_H #include /* * Memory pool for large temporary memory allocations that must not fail. * With the first allocation from an unused (idle or free) pool the pool * becomes reserved for that particular thread, until all allocations are * freed again. In order to avoid dead-lock and ease code review it is good * practise to free everything allocated by a certain function before * returning. */ /* * struct mempool_item - internal struct to keep track of an item */ struct mempool_item { size_t size; ssize_t prev_item_offset; ssize_t next_item_offset; }; struct mempool; #define MEMPOOL_ALIGN __alignof__(long) #if defined(__KERNEL__) /* * System wide memory pool for large temporary memory allocation. */ extern struct mempool *mempool_default; #endif /* * mempool_alloc_pool() - Allocate a new memory pool * @data: a block of memory to carve out items from, must * have an alignment of MEMPOOL_ALIGN. * @size: size fo the block of memory * @release_mem: function to call when the pool has been emptied, * ignored if NULL. * returns a pointer to a valid pool on success or NULL on failure. */ struct mempool *mempool_alloc_pool(void *data, size_t size, void (*release_mem)(void *ptr, size_t size)); /* * mempool_alloc() - Allocate an item from a memory pool * @pool: A memory pool created with mempool_alloc_pool() * @size: Size in bytes of the item to allocate * return a valid pointer on success or NULL on failure. */ void *mempool_alloc(struct mempool *pool, size_t size); /* * mempool_calloc() - Allocate and zero initialize an array of elements from a * memory pool * @pool: A memory pool created with mempool_alloc_pool() * @nmemb: Number of elements in the array * @size: Size in bytes of each element in the array * return a valid pointer on success or NULL on failure. */ void *mempool_calloc(struct mempool *pool, size_t nmemb, size_t size); /* * mempool_free() - Frees a previously allocated item * @pool: A memory pool create with mempool_alloc_pool() * @ptr: A pointer to a previously allocated item */ void mempool_free(struct mempool *pool, void *ptr); #endif /*__MEMPOOL_H*/ optee_os-4.3.0/lib/libutils/ext/include/memtag.h000066400000000000000000000124541464416617300216200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2022, Linaro Limited */ #ifndef __MEMTAG_H #define __MEMTAG_H #include #include #include #include #if defined(CFG_MEMTAG) && defined(__aarch64__) #define MEMTAG_IS_ENABLED 1 #define MEMTAG_TAG_SHIFT 56 #define MEMTAG_TAG_WIDTH 4 #define MEMTAG_TAG_MASK (BIT(MEMTAG_TAG_WIDTH) - 1) #define MEMTAG_GRANULE_SIZE 16 #else #define MEMTAG_IS_ENABLED 0 #define MEMTAG_GRANULE_SIZE 1 #define MEMTAG_TAG_WIDTH 0 #endif #define MEMTAG_GRANULE_MASK (MEMTAG_GRANULE_SIZE - 1) struct __memtag_ops { void *(*set_tags)(void *addr, size_t size, uint8_t tag); void *(*set_random_tags)(void *addr, size_t size); void (*clear_mem)(void *addr, size_t size); uint8_t (*read_tag)(const void *addr); }; extern const struct __memtag_ops __memtag_ops_disabled; extern const struct __memtag_ops *__memtag_ops; static inline void *__memtag_disabled_set_tags(void *addr, size_t size __unused, uint8_t tag __unused) { return addr; } static inline void *__memtag_disabled_set_random_tags(void *addr, size_t size __unused) { return addr; } static inline void __memtag_disabled_clear_mem(void *addr, size_t size) { memset(addr, 0, size); } static inline uint8_t __memtag_disabled_read_tag(const void *addr __unused) { return 0; } /* * memtag_set_tags() - Tag a memory range * @addr: Start of memory range * @size: Size of memory range * @tag: Tag to use * * The memory range is updated with the supplied tag. An eventual tag * already present in the upper bits of the address in @addr is ignored. * * @addr and @size must be aligned/multiple of MEMTAG_GRANULE_SIZE. * * Returns an address with the new tag inserted to be used to access this * memory area. */ static inline void *memtag_set_tags(void *addr, size_t size, uint8_t tag) { #if MEMTAG_IS_ENABLED return __memtag_ops->set_tags(addr, size, tag); #else return __memtag_disabled_set_tags(addr, size, tag); #endif } /* * memtag_set_random_tags() - Tag a memory range with a random tag * @addr: Start of memory range * @size: Size of memory range * * The memory range is updated with a randomly generated tag. An eventual * tag already present in the upper bits of the address in @addr is * ignored. * * @addr and @size must be aligned/multiple of MEMTAG_GRANULE_SIZE. * * Returns an address with the new tag inserted to be used to access this * memory area. */ static inline void *memtag_set_random_tags(void *addr, size_t size) { #if MEMTAG_IS_ENABLED return __memtag_ops->set_random_tags(addr, size); #else return __memtag_disabled_set_random_tags(addr, size); #endif } static inline void memtag_clear_mem(void *addr, size_t size) { #if MEMTAG_IS_ENABLED __memtag_ops->clear_mem(addr, size); #else __memtag_disabled_clear_mem(addr, size); #endif } /* * memtag_strip_tag_vaddr() - Removes an eventual tag from an address * @addr: Address to strip * * Returns a vaddr_t without an eventual tag. */ static inline vaddr_t memtag_strip_tag_vaddr(const void *addr) { vaddr_t va = (vaddr_t)addr; #if MEMTAG_IS_ENABLED va &= ~SHIFT_U64(MEMTAG_TAG_MASK, MEMTAG_TAG_SHIFT); #endif return va; } /* * memtag_strip_tag_const() - Removes an eventual tag from an address * @addr: Address to strip * * Returns the address without an eventual tag. */ static inline const void *memtag_strip_tag_const(const void *addr) { return (const void *)memtag_strip_tag_vaddr(addr); } /* * memtag_strip_tag() - Removes an eventual tag from an address * @addr: Address to strip * * Returns the address without an eventual tag. */ static inline void *memtag_strip_tag(void *addr) { return (void *)memtag_strip_tag_vaddr(addr); } /* * memtag_insert_tag_vaddr() - Inserts a tag into an address * @addr: Address to transform * @tag: Tag to insert * * Returns the address with the new tag inserted. */ static inline vaddr_t memtag_insert_tag_vaddr(vaddr_t addr, uint8_t tag __maybe_unused) { vaddr_t va = memtag_strip_tag_vaddr((void *)addr); #if MEMTAG_IS_ENABLED va |= SHIFT_U64(tag, MEMTAG_TAG_SHIFT); #endif return va; } /* * memtag_insert_tag() - Inserts a tag into an address * @addr: Address to transform * @tag: Tag to insert * * Returns the address with the new tag inserted. */ static inline void *memtag_insert_tag(void *addr, uint8_t tag) { return (void *)memtag_insert_tag_vaddr((vaddr_t)addr, tag); } /* * memtag_get_tag() - Extract a tag from an address * @addr: Address with an eventual tag * * Returns the extracted tag. */ static inline uint8_t memtag_get_tag(const void *addr __maybe_unused) { #if MEMTAG_IS_ENABLED uint64_t va = (vaddr_t)addr; return (va >> MEMTAG_TAG_SHIFT) & MEMTAG_TAG_MASK; #else return 0; #endif } static inline uint8_t memtag_read_tag(const void *addr) { #if MEMTAG_IS_ENABLED return __memtag_ops->read_tag(addr); #else return __memtag_disabled_read_tag(addr); #endif } static inline void memtag_assert_tag(const void *addr __maybe_unused) { assert(memtag_get_tag(addr) == memtag_read_tag(addr)); } #if MEMTAG_IS_ENABLED void memtag_init_ops(unsigned int memtag_impl); #else static inline void memtag_init_ops(unsigned int memtag_impl __unused) { } #endif static inline bool memtag_is_enabled(void) { #if MEMTAG_IS_ENABLED return __memtag_ops != &__memtag_ops_disabled; #else return false; #endif } #endif /*__MEMTAG_H*/ optee_os-4.3.0/lib/libutils/ext/include/printk.h000066400000000000000000000014631464416617300216530ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015 Linaro Limited */ /* * This file provides extensions to the standard snprintf() and vsnprintf() * functions. These 'k' variants support additional formats. */ #ifndef PRINTK_H #define PRINTK_H #include #include #include int snprintk(char *str, size_t size, const char *fmt, ...) __attribute__((__format__(__printf__, 3, 4))); int vsnprintk(char *str, size_t size, const char *fmt, va_list ap) __attribute__((__format__(__printf__, 3, 0))); int __vsnprintf(char *str, size_t size, const char *fmt, va_list ap, bool ext) __attribute__((__format__(__printf__, 3, 0))); int __vsprintf(char *bf, const char *fmt, va_list ap) __attribute__((__format__(__printf__, 2, 0))); #endif /* PRINTK_H */ optee_os-4.3.0/lib/libutils/ext/include/riscv.S000066400000000000000000000004521464416617300214420ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation */ #if __riscv_xlen == 32 #define STR sw #define LDR lw #define REGOFF(x) ((x) * 4) #elif __riscv_xlen == 64 #define STR sd #define LDR ld #define REGOFF(x) ((x) * 8) #endif optee_os-4.3.0/lib/libutils/ext/include/speculation_barrier.h000066400000000000000000000577331464416617300244130ustar00rootroot00000000000000/* SPDX-License-Identifier: BSL-1.0 */ /* Copyright (c) 2017 Arm Limited. All rights reserved. Boost Software License - Version 1.0 - August 17th, 2003 Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef __HAVE_LOAD_NO_SPECULATE #define load_no_speculate(__ptr, __low, __high) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __builtin_load_no_speculate (__ptr_once, __low, __high, \ 0, __ptr_once); \ })) #define load_no_speculate_fail(__ptr, __low, __high, __failval) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __builtin_load_no_speculate (__ptr_once, __low, __high, \ __failval, __ptr_once); \ })) #define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ (__builtin_load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) #else #ifdef __GNUC__ #define __UNUSED __attribute__((unused)) #else #define __UNUSED #endif #ifdef __aarch64__ #define __load_no_speculate1(__ptr, __low, __high, __failval, \ __cmpptr, __w, __sz) \ (__extension__ ({ \ __typeof__ (0 + (*(__ptr))) __nln_val; \ /* This typecasting is required to ensure correct handling of upper \ bits of failval, to ensure a clean return from the CSEL below. */ \ __typeof__(*(__ptr)) __fv \ = (__typeof__(*(__ptr)))(unsigned long long) (__failval); \ /* If __high is explicitly NULL, we must not emit the \ upper-bound comparison. We need to cast __high to an \ unsigned long long before handing it to __builtin_constant_p to \ ensure that clang/llvm correctly detects NULL as a constant if it \ is defined as (void*) 0. */ \ if (__builtin_constant_p ((unsigned long long)__high) \ && __high == ((void *)0)) \ { \ __asm__ volatile ( \ "cmp\t%[__c], %[__l]\n\t" \ "bcc\t.ns%=\n\t" \ "ldr" __sz "\t%" __w "[__v], %[__p]\n" \ ".ns%=:\n\t" \ "csel\t%" __w "[__v], %" __w "[__v], %" __w "[__f], cs\n\t" \ "hint\t#0x14 // CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&r" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)), \ /* The value to return if the condition check fails. */ \ [__f] "rZ" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ else \ { \ __asm__ volatile ( \ "cmp\t%[__c], %[__l]\n\t" \ "ccmp\t%[__c], %[__h], 2, cs\n\t" \ "bcs\t.ns%=\n\t" \ "ldr" __sz "\t%" __w "[__v], %[__p]\n" \ ".ns%=:\n\t" \ "csel\t%" __w "[__v], %" __w "[__v], %" __w "[__f], cc\n\t" \ "hint\t#0x14 // CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&r" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ [__h] "r" (__high), \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)), \ /* The value to return if the condition check fails. */ \ [__f] "rZ" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ (__typeof__ (*(__ptr))) __nln_val; \ })) #define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nl_val; \ \ switch (sizeof(*(__ptr))) { \ case 1: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "w", "b"); \ break; \ case 2: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "w", "h"); \ break; \ case 4: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "w", ""); \ break; \ case 8: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "x", ""); \ break; \ default: \ { \ char __static_assert_no_speculate_load_size_too_big \ [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ break; \ } \ } \ \ (__typeof__ (*(__ptr))) __nl_val; \ })) #define load_no_speculate(__ptr, __low, __high) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ })) #define load_no_speculate_fail(__ptr, __low, __high, __failval) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __load_no_speculate (__ptr_once, __low, __high, \ __failval, __ptr_once); \ })) #define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) /* AArch32 support for ARM and Thumb-2. Thumb-1 is not supported. */ #elif defined (__ARM_32BIT_STATE) && (defined (__thumb2__) || !defined (__thumb__)) #ifdef __thumb2__ /* Thumb2 case. */ #define __load_no_speculate1(__ptr, __low, __high, __failval, \ __cmpptr, __sz) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nln_val; \ __typeof__(*(__ptr)) __fv \ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ /* If __high is explicitly NULL, we must not emit the \ upper-bound comparison. We need to cast __high to an \ unsigned long before handing it to __builtin_constant_p to \ ensure that clang/llvm correctly detects NULL as a constant if it \ is defined as (void*) 0. */ \ if (__builtin_constant_p ((unsigned long)__high) \ && __high == ((void *)0)) \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "bcc\t.ns%=\n\t" \ "ldr" __sz "\t%[__v], %[__p]\n" \ ".ns%=:\n\t" \ "it\tcc\n\t" \ "movcc\t%[__v], %[__f]\n\t" \ ".inst.n 0xf3af\t@ CSDB\n\t" \ ".inst.n 0x8014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&l" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)), \ /* The value to return if the condition check fails. */ \ [__f] "r" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ else \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "it\tcs\n\t" \ "cmpcs\t%[__h], %[__c]\n\t" \ "bls\t.ns%=\n\t" \ "ldr" __sz "\t%[__v], %[__p]\n" \ ".ns%=:\n\t" \ "it\tls\n\t" \ "movls\t%[__v], %[__f]\n\t" \ ".inst.n 0xf3af\t@ CSDB\n\t" \ ".inst.n 0x8014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&l" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ [__h] "r" (__high), \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)), \ /* The value to return if the condition check fails. */ \ [__f] "r" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ (__typeof__ (*(__ptr))) __nln_val; \ })) \ \ /* Double-word version. */ #define __load_no_speculate2(__ptr, __low, __high, __failval, \ __cmpptr) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nln_val; \ __typeof__(*(__ptr)) __fv \ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ /* If __high is explicitly NULL, we must not emit the \ upper-bound comparison. We need to cast __high to an \ unsigned long before handing it to __builtin_constant_p to \ ensure that clang/llvm correctly detects NULL as a constant if it \ is defined as (void*) 0. */ \ if (__builtin_constant_p ((unsigned long)__high) \ && __high == ((void *)0)) \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "bcc\t.ns%=\n\t" \ "ldr\t%Q[__v], [%[__p]]\n\t" \ "ldr\t%R[__v], [%[__p], #4]\n" \ ".ns%=:\n\t" \ "it\tcc\n\t" \ "movcc\t%Q[__v], %Q[__f]\n\t" \ "it\tcc\n\t" \ "movcc\t%R[__v], %R[__f]\n\t" \ ".inst.n 0xf3af\t@ CSDB\n\t" \ ".inst.n 0x8014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&l" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ /* The memory location from which we will load. */ \ [__p] "r" (__ptr), \ /* The value to return if the condition check fails. */ \ [__f] "r" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ else \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "it\tcs\n\t" \ "cmpcs\t%[__h], %[__c]\n\t" \ "bls\t.ns%=\n\t" \ "ldr\t%Q[__v], [%[__p]]\n\t" \ "ldr\t%R[__v], [%[__p], #4]\n" \ ".ns%=:\n\t" \ "it\tls\n\t" \ "movls\t%Q[__v], %Q[__f]\n\t" \ "it\tls\n\t" \ "movls\t%R[__v], %R[__f]\n\t" \ ".inst.n 0xf3af\t@ CSDB\n\t" \ ".inst.n 0x8014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&l" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ [__h] "r" (__high), \ /* The memory location from which we will load. */ \ [__p] "r" (__ptr), \ /* The value to return if the condition check fails. */ \ [__f] "r" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ (__typeof__ (*(__ptr))) __nln_val; \ })) #else /* ARM case. */ #define __load_no_speculate1(__ptr, __low, __high, __failval, \ __cmpptr, __sz) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nln_val; \ __typeof__(*(__ptr)) __fv \ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ /* If __high is explicitly NULL, we must not emit the \ upper-bound comparison. We need to cast __high to an \ unsigned long before handing it to __builtin_constant_p to \ ensure that clang/llvm correctly detects NULL as a constant if it \ is defined as (void*) 0. */ \ if (__builtin_constant_p ((unsigned long)__high) \ && __high == ((void *)0)) \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "ldr" __sz "cs\t%[__v], %[__p]\n\t" \ "movcc\t%[__v], %[__f]\n\t" \ ".inst 0xe320f014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&r" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)), \ /* The value to return if the condition check fails. */ \ [__f] "rKI" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ else \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "cmpcs\t%[__h], %[__c]\n\t" \ "ldr" __sz "hi\t%[__v], %[__p]\n\t" \ "movls\t%[__v], %[__f]\n\t" \ ".inst 0xe320f014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&r" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ [__h] "r" (__high), \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)), \ /* The value to return if the condition check fails. */ \ [__f] "rKI" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ (__typeof__ (*(__ptr))) __nln_val; \ })) /* Double-word version. */ #define __load_no_speculate2(__ptr, __low, __high, __failval, \ __cmpptr) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nln_val; \ __typeof__(*(__ptr)) __fv \ = (__typeof__(*(__ptr)))(unsigned long) (__failval); \ /* If __high is explicitly NULL, we must not emit the \ upper-bound comparison. We need to cast __high to an \ unsigned long before handing it to __builtin_constant_p to \ ensure that clang/llvm correctly detects NULL as a constant if it \ is defined as (void*) 0. */ \ if (__builtin_constant_p ((unsigned long)__high) \ && __high == ((void *)0)) \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "ldrcs\t%Q[__v], [%[__p]]\n\t" \ "ldrcs\t%R[__v], [%[__p], #4]\n\t" \ "movcc\t%Q[__v], %Q[__f]\n\t" \ "movcc\t%R[__v], %R[__f]\n\t" \ ".inst 0xe320f014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&r" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ /* The memory location from which we will load. */ \ [__p] "r" (__ptr), \ /* The value to return if the condition check fails. */ \ [__f] "r" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ else \ { \ __asm__ volatile ( \ ".syntax unified\n\t" \ "cmp\t%[__c], %[__l]\n\t" \ "cmpcs\t%[__h], %[__c]\n\t" \ "ldrhi\t%Q[__v], [%[__p]]\n\t" \ "ldrhi\t%R[__v], [%[__p], #4]\n\t" \ "movls\t%Q[__v], %Q[__f]\n\t" \ "movls\t%R[__v], %R[__f]\n\t" \ ".inst 0xe320f014\t@ CSDB" \ /* The value we have loaded, or failval if the condition check \ fails. */ \ : [__v] "=&r" (__nln_val) \ /* The pointer we wish to use for comparisons, and the low and \ high bounds to use in that comparison. Note that this need \ not be the same as the pointer from which we will load. */ \ : [__c] "r" (__cmpptr), [__l] "r" (__low), \ [__h] "r" (__high), \ /* The memory location from which we will load. */ \ [__p] "r" (__ptr), \ /* The value to return if the condition check fails. */ \ [__f] "r" (__fv) \ /* We always clobber the condition codes. */ \ : "cc"); \ } \ (__typeof__ (*(__ptr))) __nln_val; \ })) #endif // __thumb2__ /* Common to ARM and Thumb2. */ #define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nl_val; \ \ switch (sizeof(*(__ptr))) { \ case 1: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "b"); \ break; \ case 2: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "h"); \ break; \ case 4: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, ""); \ break; \ case 8: \ __nl_val = __load_no_speculate2 (__ptr, __low, __high, \ __failval, __cmpptr); \ break; \ default: \ { \ char __static_assert_no_speculate_load_size_too_big \ [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ break; \ } \ } \ \ (__typeof__ (*(__ptr))) __nl_val; \ })) #define load_no_speculate(__ptr, __low, __high) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ })) #define load_no_speculate_fail(__ptr, __low, __high, __failval) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __load_no_speculate (__ptr_once, __low, __high, \ __failval, __ptr_once); \ })) #define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) #elif defined(RV32) || defined(RV64) #define __load_no_speculate1(__ptr, __low, __high, __failval, __cmpptr, __sz) \ (__extension__ ({ \ __typeof__ (0 + (*(__ptr))) __nln_val; \ asm volatile ( \ "fence\trw,rw\n\t" \ "fence.i\n\t" \ "fence\tr,r\n\t" \ "l" __sz "\t%[__v], %[__p]\n" \ /* The value we have loaded. */ \ : [__v] "=&r" (__nln_val) \ : \ /* The memory location from which we will load. */ \ [__p] "m" (*(__ptr)) \ : ); \ (__typeof__ (*(__ptr))) __nln_val; \ })) #define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr) \ (__extension__ ({ \ __typeof__ (0 + *(__ptr)) __nl_val; \ \ switch (sizeof(*(__ptr))) { \ case 1: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "b"); \ break; \ case 2: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "h"); \ break; \ case 4: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "w"); \ break; \ case 8: \ __nl_val = __load_no_speculate1 (__ptr, __low, __high, \ __failval, __cmpptr, "d"); \ break; \ default: \ { \ char __static_assert_no_speculate_load_size_too_big \ [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED; \ break; \ } \ } \ \ (__typeof__ (*(__ptr))) __nl_val; \ })) #define load_no_speculate(__ptr, __low, __high) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once); \ })) #define load_no_speculate_fail(__ptr, __low, __high, __failval) \ (__extension__ ({ \ __typeof__ ((__ptr)) __ptr_once = (__ptr); \ __load_no_speculate (__ptr_once, __low, __high, __failval, __ptr_once); \ })) #define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \ (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr)) #else #error "No fallback provided for load_no_speculate" #endif #endif optee_os-4.3.0/lib/libutils/ext/include/stdlib_ext.h000066400000000000000000000005551464416617300225060ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ /* * This file provides extensions to functions defined in */ #ifndef __STDLIB_EXT_H #define __STDLIB_EXT_H #include /* Overwrite buffer with a fixed pattern and free it. @ptr may be NULL. */ void free_wipe(void *ptr); #endif /* __STDLIB_EXT_H */ optee_os-4.3.0/lib/libutils/ext/include/string_ext.h000066400000000000000000000034201464416617300225250ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* * This file provides extensions for functions not defined in */ #ifndef __STRING_EXT_H #define __STRING_EXT_H #include #include /* * Copy src to string dst of siz size. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t size); size_t strlcat(char *dst, const char *src, size_t size); /* A constant-time version of memcmp() */ int consttime_memcmp(const void *p1, const void *p2, size_t nb); /* Deprecated. For backward compatibility. */ static inline int buf_compare_ct(const void *s1, const void *s2, size_t n) { return consttime_memcmp(s1, s2, n); } /* Variant of strdup() that uses nex_malloc() instead of malloc() */ char *nex_strdup(const char *s); /* * Like memset(s, 0, count) but prevents the compiler from optimizing the call * away. Such "dead store elimination" optimizations typically occur when * clearing a *local* variable that is not used after it is cleared; but * link-time optimization (LTO) can also trigger code elimination in other * circumstances. See "Dead Store Elimination (Still) Considered Harmful" [1] * for details and examples (and note that the Cland compiler enables LTO by * default!). * * [1] https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf * * Practically speaking: * * - Use memzero_explicit() to *clear* (as opposed to initialize) *sensitive* * data (such as keys, passwords, cryptographic state); * - Otherwise, use memset(). */ void memzero_explicit(void *s, size_t count); #endif /* __STRING_EXT_H */ optee_os-4.3.0/lib/libutils/ext/include/trace.h000066400000000000000000000104551464416617300214430ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef TRACE_H #define TRACE_H #include #include #include #include #include #define MAX_PRINT_SIZE 256 #define MAX_FUNC_PRINT_SIZE 32 #ifndef TRACE_LEVEL #define TRACE_LEVEL TRACE_MAX #endif /* * Symbols provided by the entity that uses this API. */ extern int trace_level; extern const char trace_ext_prefix[]; void trace_ext_puts(const char *str); int trace_ext_get_thread_id(void); int trace_ext_get_core_id(void); int trace_ext_get_guest_id(void); void trace_set_level(int level); int trace_get_level(void); void plat_trace_ext_puts(const char *str); /* Internal functions used by the macros below */ void trace_vprintf(const char *func, int line, int level, bool level_ok, const char *fmt, va_list args) __printf(5, 0); void trace_printf(const char *func, int line, int level, bool level_ok, const char *fmt, ...) __printf(5, 6); #define trace_printf_helper(level, level_ok, ...) \ trace_printf(__func__, __LINE__, (level), (level_ok), \ __VA_ARGS__) /* Formatted trace tagged with level independent */ #if (TRACE_LEVEL <= 0) #define MSG(...) (void)0 #else #define MSG(...) trace_printf_helper(0, false, __VA_ARGS__) #endif /* Formatted trace tagged with TRACE_ERROR level */ #if (TRACE_LEVEL < TRACE_ERROR) #define EMSG(...) (void)0 #else #define EMSG(...) trace_printf_helper(TRACE_ERROR, true, __VA_ARGS__) #endif /* Formatted trace tagged with TRACE_INFO level */ #if (TRACE_LEVEL < TRACE_INFO) #define IMSG(...) (void)0 #else #define IMSG(...) trace_printf_helper(TRACE_INFO, true, __VA_ARGS__) #endif /* Formatted trace tagged with TRACE_DEBUG level */ #if (TRACE_LEVEL < TRACE_DEBUG) #define DMSG(...) (void)0 #else #define DMSG(...) trace_printf_helper(TRACE_DEBUG, true, __VA_ARGS__) #endif /* Formatted trace tagged with TRACE_FLOW level */ #if (TRACE_LEVEL < TRACE_FLOW) #define FMSG(...) (void)0 #else #define FMSG(...) trace_printf_helper(TRACE_FLOW, true, __VA_ARGS__) #endif /* Formatted trace tagged with TRACE_FLOW level and prefix with '> ' */ #define INMSG(...) FMSG("> " __VA_ARGS__) /* Formatted trace tagged with TRACE_FLOW level and prefix with '< ' */ #define OUTMSG(...) FMSG("< " __VA_ARGS__) /* Formatted trace tagged with TRACE_FLOW level and prefix with '< ' and print * an error message if r != 0 */ #define OUTRMSG(r) \ do { \ OUTMSG("r=[%x]", r); \ return r; \ } while (0) void dhex_dump(const char *function, int line, int level, const void *buf, int len); #if (TRACE_LEVEL < TRACE_DEBUG) #define DHEXDUMP(buf, len) (void)0 #else #define DHEXDUMP(buf, len) dhex_dump(__func__, __LINE__, TRACE_DEBUG, \ buf, len) #endif /* Trace api without trace formatting */ #define trace_printf_helper_raw(level, level_ok, ...) \ trace_printf(NULL, 0, (level), (level_ok), __VA_ARGS__) /* No formatted trace tagged with level independent */ #if (TRACE_LEVEL <= 0) #define MSG_RAW(...) (void)0 #else #define MSG_RAW(...) trace_printf_helper_raw(0, false, __VA_ARGS__) #endif /* No formatted trace tagged with TRACE_ERROR level */ #if (TRACE_LEVEL < TRACE_ERROR) #define EMSG_RAW(...) (void)0 #else #define EMSG_RAW(...) trace_printf_helper_raw(TRACE_ERROR, true, __VA_ARGS__) #endif /* No formatted trace tagged with TRACE_INFO level */ #if (TRACE_LEVEL < TRACE_INFO) #define IMSG_RAW(...) (void)0 #else #define IMSG_RAW(...) trace_printf_helper_raw(TRACE_INFO, true, __VA_ARGS__) #endif /* No formatted trace tagged with TRACE_DEBUG level */ #if (TRACE_LEVEL < TRACE_DEBUG) #define DMSG_RAW(...) (void)0 #else #define DMSG_RAW(...) trace_printf_helper_raw(TRACE_DEBUG, true, __VA_ARGS__) #endif /* No formatted trace tagged with TRACE_FLOW level */ #if (TRACE_LEVEL < TRACE_FLOW) #define FMSG_RAW(...) (void)0 #else #define FMSG_RAW(...) trace_printf_helper_raw(TRACE_FLOW, true, __VA_ARGS__) #endif #if (TRACE_LEVEL <= 0) #define SMSG(...) (void)0 #else /* * Synchronised flushed trace, an Always message straight to HW trace IP. * Current only supported inside OP-TEE kernel, will be just like an EMSG() * in another context. */ #define SMSG(...) \ trace_printf(__func__, __LINE__, TRACE_ERROR, true, __VA_ARGS__) #endif /* TRACE_LEVEL */ #endif /* TRACE_H */ optee_os-4.3.0/lib/libutils/ext/include/trace_levels.h000066400000000000000000000017201464416617300230100ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef TRACE_LEVELS_H #define TRACE_LEVELS_H /* * Trace levels. * * ALWAYS is used when you always want a print to be seen, but it is not always * an error. * * ERROR is used when some kind of error has happened, this is most likely the * print you will use most of the time when you report some kind of error. * * INFO is used when you want to print some 'normal' text to the user. * This is the default level. * * DEBUG is used to print extra information to enter deeply in the module. * * FLOW is used to print the execution flox, typically the in/out of functions. * */ #define TRACE_MIN 0 #define TRACE_ERROR 1 #define TRACE_INFO 2 #define TRACE_DEBUG 3 #define TRACE_FLOW 4 #define TRACE_MAX TRACE_FLOW /* Trace level of the casual printf */ #define TRACE_PRINTF_LEVEL TRACE_ERROR #endif /*TRACE_LEVELS_H*/ optee_os-4.3.0/lib/libutils/ext/include/types_ext.h000066400000000000000000000015241464416617300223660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TYPES_EXT_H #define __TYPES_EXT_H #include #include #include #include #include typedef uintptr_t uaddr_t; #define PRIxUA PRIxPTR typedef uintptr_t vaddr_t; #define PRIxVA PRIxPTR #if defined(__ILP32__) && defined(CFG_CORE_LARGE_PHYS_ADDR) typedef uint64_t paddr_t; typedef uint64_t paddr_size_t; #define PRIxPA PRIx64 #define PRIxPASZ PRIx64 #define __SIZEOF_PADDR__ 8 #else typedef uintptr_t paddr_t; typedef uintptr_t paddr_size_t; #define PRIxPA PRIxPTR #define PRIxPASZ PRIxPTR #define __SIZEOF_PADDR__ __SIZEOF_POINTER__ #endif #define PRIxVA_WIDTH ((int)(sizeof(vaddr_t) * 2)) #define PRIxPA_WIDTH ((int)(sizeof(paddr_t) * 2)) #endif /* __TYPES_EXT_H */ optee_os-4.3.0/lib/libutils/ext/include/util.h000066400000000000000000000135121464416617300213170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef UTIL_H #define UTIL_H #include #include #define SIZE_4K UINTPTR_C(0x1000) #define SIZE_1M UINTPTR_C(0x100000) #define SIZE_2M UINTPTR_C(0x200000) #define SIZE_4M UINTPTR_C(0x400000) #define SIZE_8M UINTPTR_C(0x800000) #define SIZE_2G UINTPTR_C(0x80000000) #ifndef MAX #ifndef __ASSEMBLER__ #define MAX(a, b) \ (__extension__({ __typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ _a > _b ? _a : _b; })) #define MIN(a, b) \ (__extension__({ __typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ _a < _b ? _a : _b; })) #else #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #endif /* * In some particular conditions MAX and MIN macros fail to * build from C source file implmentation. In such case one * need to use MAX_UNSAFE/MIN_UNSAFE instead. */ #define MAX_UNSAFE(a, b) (((a) > (b)) ? (a) : (b)) #define MIN_UNSAFE(a, b) (((a) < (b)) ? (a) : (b)) #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif #ifndef __ASSEMBLER__ /* Round up the even multiple of size, size has to be a multiple of 2 */ #define ROUNDUP(v, size) (((v) + ((__typeof__(v))(size) - 1)) & \ ~((__typeof__(v))(size) - 1)) #define ROUNDUP_OVERFLOW(v, size, res) (__extension__({ \ typeof(*(res)) __roundup_tmp = 0; \ typeof(v) __roundup_mask = (typeof(v))(size) - 1; \ \ ADD_OVERFLOW((v), __roundup_mask, &__roundup_tmp) ? 1 : \ ((void)(*(res) = __roundup_tmp & ~__roundup_mask), 0); \ })) /* * Rounds up to the nearest multiple of y and then divides by y. Safe * against overflow, y has to be a multiple of 2. * * This macro is intended to be used to convert from "number of bytes" to * "number of pages" or similar units. Example: * num_pages = ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE); */ #define ROUNDUP_DIV(x, y) (__extension__({ \ typeof(x) __roundup_x = (x); \ typeof(y) __roundup_mask = (typeof(x))(y) - 1; \ \ (__roundup_x / (y)) + (__roundup_x & __roundup_mask ? 1 : 0); \ })) /* Round down the even multiple of size, size has to be a multiple of 2 */ #define ROUNDDOWN(v, size) ((v) & ~((__typeof__(v))(size) - 1)) /* * Round up the result of x / y to the nearest upper integer if result is not * already an integer. */ #define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) /* Unsigned integer division with nearest rounding variant */ #define UDIV_ROUND_NEAREST(x, y) \ (__extension__ ({ __typeof__(x) _x = (x); \ __typeof__(y) _y = (y); \ (_x + (_y / 2)) / _y; })) #else #define ROUNDUP(x, y) ((((x) + (y) - 1) / (y)) * (y)) #define ROUNDDOWN(x, y) (((x) / (y)) * (y)) #define UDIV_ROUND_NEAREST(x, y) (((x) + ((y) / 2)) / (y)) #endif /* x has to be of an unsigned type */ #define IS_POWER_OF_TWO(x) (((x) != 0) && (((x) & (~(x) + 1)) == (x))) #define IS_ALIGNED(x, a) (((x) & ((a) - 1)) == 0) #define IS_ALIGNED_WITH_TYPE(x, type) \ (__extension__({ \ type __is_aligned_y; \ IS_ALIGNED((uintptr_t)(x), __alignof__(__is_aligned_y)); \ })) #define TO_STR(x) _TO_STR(x) #define _TO_STR(x) #x #define CONCAT(x, y) _CONCAT(x, y) #define _CONCAT(x, y) x##y #define container_of(ptr, type, member) \ (__extension__({ \ const typeof(((type *)0)->member) *__ptr = (ptr); \ (type *)((unsigned long)(__ptr) - offsetof(type, member)); \ })) #define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) #ifdef __ASSEMBLER__ #define BIT32(nr) (1 << (nr)) #define BIT64(nr) (1 << (nr)) #define SHIFT_U32(v, shift) ((v) << (shift)) #define SHIFT_U64(v, shift) ((v) << (shift)) #else #define BIT32(nr) (UINT32_C(1) << (nr)) #define BIT64(nr) (UINT64_C(1) << (nr)) #define SHIFT_U32(v, shift) ((uint32_t)(v) << (shift)) #define SHIFT_U64(v, shift) ((uint64_t)(v) << (shift)) #endif #define BIT(nr) BIT32(nr) /* * Create a contiguous bitmask starting at bit position @l and ending at * position @h. For example * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. */ #define GENMASK_32(h, l) \ ((UINT32_C(0xffffffff) << (l)) & \ (UINT32_C(0xffffffff) >> (32 - 1 - (h)))) #define GENMASK_64(h, l) \ (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) /* * Checking overflow for addition, subtraction and multiplication. Result * of operation is stored in res which is a pointer to some kind of * integer. * * The macros return true if an overflow occurred and *res is undefined. */ #define ADD_OVERFLOW(a, b, res) __compiler_add_overflow((a), (b), (res)) #define SUB_OVERFLOW(a, b, res) __compiler_sub_overflow((a), (b), (res)) #define MUL_OVERFLOW(a, b, res) __compiler_mul_overflow((a), (b), (res)) /* Return a signed +1, 0 or -1 value based on data comparison */ #define CMP_TRILEAN(a, b) \ (__extension__({ \ __typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ \ _a > _b ? 1 : _a < _b ? -1 : 0; \ })) #ifndef __ASSEMBLER__ static inline uint64_t reg_pair_to_64(uint32_t reg0, uint32_t reg1) { return (uint64_t)reg0 << 32 | reg1; } static inline uint32_t high32_from_64(uint64_t val) { return val >> 32; } static inline uint32_t low32_from_64(uint64_t val) { return val; } static inline void reg_pair_from_64(uint64_t val, uint32_t *reg0, uint32_t *reg1) { *reg0 = high32_from_64(val); *reg1 = low32_from_64(val); } /* Get and set bit fields */ static inline uint32_t get_field_u32(uint32_t reg, uint32_t mask) { return (reg & mask) / (mask & ~(mask - 1)); } static inline uint32_t set_field_u32(uint32_t reg, uint32_t mask, uint32_t val) { return (reg & ~mask) | (val * (mask & ~(mask - 1))); } static inline uint64_t get_field_u64(uint64_t reg, uint64_t mask) { return (reg & mask) / (mask & ~(mask - 1)); } static inline uint64_t set_field_u64(uint64_t reg, uint64_t mask, uint64_t val) { return (reg & ~mask) | (val * (mask & ~(mask - 1))); } #endif #endif /*UTIL_H*/ optee_os-4.3.0/lib/libutils/ext/mempool.c000066400000000000000000000114731464416617300203660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2018-2019, Linaro Limited */ #include #include #include #include #include #include #include #if defined(__KERNEL__) #include #include #endif /* * Allocation of temporary memory buffers which are used in a stack like * fashion. One exmaple is when a Big Number is needed for a temporary * variable in a Big Number computation: Big Number operations (add,...), * crypto algorithms (rsa, ecc,,...). * * The allocation algorithm takes memory buffers from a pool, * characterized by (cf. struct mempool): * - the total size (in bytes) of the pool * - the offset of the last item allocated in the pool (struct * mempool_item). This offset is -1 is nothing is allocated yet. * * Each item consists of (struct mempool_item) * - the size of the item * - the offsets, in the pool, of the previous and next items * * The allocation allocates an item for a given size. * The allocation is performed in the pool after the last * allocated items. This means: * - the heap is never used. * - there is no assumption on the size of the allocated memory buffers. Only * the size of the pool will limit the allocation. * - a constant time allocation and free as there is no list scan * - but a potentially fragmented memory as the allocation does not take into * account "holes" in the pool (allocation is performed after the last * allocated variable). Indeed, this interface is supposed to be used * with stack like allocations to avoid this issue. This means that * allocated items: * - should have a short life cycle * - if an item A is allocated before another item B, then A should be * released after B. * So the potential fragmentation is mitigated. */ struct mempool { size_t size; /* size of the memory pool, in bytes */ vaddr_t data; struct malloc_ctx *mctx; #ifdef CFG_MEMPOOL_REPORT_LAST_OFFSET size_t max_allocated; #endif #if defined(__KERNEL__) void (*release_mem)(void *ptr, size_t size); struct recursive_mutex mu; #endif }; #if defined(__KERNEL__) struct mempool *mempool_default; #endif static void init_mpool(struct mempool *pool) { size_t sz = pool->size - raw_malloc_get_ctx_size(); vaddr_t v = ROUNDDOWN(pool->data + sz, sizeof(long) * 2); /* * v is the placed as close to the end of the data pool as possible * where the struct malloc_ctx can be placed. This location is selected * as an optimization for the pager case to get better data * locality since raw_malloc() starts to allocate from the end of * the supplied data pool. */ assert(v > pool->data); pool->mctx = (struct malloc_ctx *)v; raw_malloc_init_ctx(pool->mctx); raw_malloc_add_pool(pool->mctx, (void *)pool->data, v - pool->data); } static void get_pool(struct mempool *pool __maybe_unused) { #if defined(__KERNEL__) mutex_lock_recursive(&pool->mu); if (!pool->mctx) init_mpool(pool); #endif } static void put_pool(struct mempool *pool __maybe_unused) { #if defined(__KERNEL__) if (mutex_get_recursive_lock_depth(&pool->mu) == 1) { /* * As the refcount is about to become 0 there should be no items * left */ if (pool->release_mem) { pool->mctx = NULL; pool->release_mem((void *)pool->data, pool->size); } } mutex_unlock_recursive(&pool->mu); #endif } struct mempool * mempool_alloc_pool(void *data, size_t size, void (*release_mem)(void *ptr, size_t size) __maybe_unused) { struct mempool *pool = calloc(1, sizeof(*pool)); COMPILE_TIME_ASSERT(MEMPOOL_ALIGN >= __alignof__(struct mempool_item)); assert(!((vaddr_t)data & (MEMPOOL_ALIGN - 1))); if (pool) { pool->size = size; pool->data = (vaddr_t)data; #if defined(__KERNEL__) pool->release_mem = release_mem; mutex_init_recursive(&pool->mu); #else init_mpool(pool); #endif } return pool; } void *mempool_alloc(struct mempool *pool, size_t size) { void *p = NULL; get_pool(pool); p = raw_malloc(0, 0, size, pool->mctx); if (p) { #ifdef CFG_MEMPOOL_REPORT_LAST_OFFSET struct pta_stats_alloc stats = { }; raw_malloc_get_stats(pool->mctx, &stats); if (stats.max_allocated > pool->max_allocated) { pool->max_allocated = stats.max_allocated; DMSG("Max memory usage increased to %zu", pool->max_allocated); } #endif return p; } EMSG("Failed to allocate %zu bytes, please tune the pool size", size); put_pool(pool); return NULL; } void *mempool_calloc(struct mempool *pool, size_t nmemb, size_t size) { size_t sz; void *p; if (MUL_OVERFLOW(nmemb, size, &sz)) return NULL; p = mempool_alloc(pool, sz); if (p) memset(p, 0, sz); return p; } void mempool_free(struct mempool *pool, void *ptr) { if (ptr) { raw_free(ptr, pool->mctx, false /*!wipe*/); put_pool(pool); } } optee_os-4.3.0/lib/libutils/ext/memzero_explicit.c000066400000000000000000000011451464416617300222700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019 Linaro Limited */ #include #include /* * This method prevents dead store elimination, which could happen in case * link-time optimization (LTO) is used. * See "Dead Store Elimination (Still) Considered Harmful" [1] section 3.3.3. * * [1] * http://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf */ static volatile void * (*memset_func)(void *, int, size_t) = (volatile void * (*)(void *, int, size_t))&memset; void memzero_explicit(void *s, size_t count) { memset_func(s, 0, count); } optee_os-4.3.0/lib/libutils/ext/nex_strdup.c000066400000000000000000000004241464416617300211030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018 EPAM Systems */ #include #include #include char *nex_strdup(const char *s) { size_t l = strlen(s) + 1; char *p = nex_malloc(l); if (p) memcpy(p, s, l); return p; } optee_os-4.3.0/lib/libutils/ext/pthread_stubs.c000066400000000000000000000006401464416617300215570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2023, Linaro Limited */ #include #define pthread_mutex_t void int pthread_mutex_lock(pthread_mutex_t *mutex __unused); int pthread_mutex_unlock(pthread_mutex_t *mutex __unused); int __weak pthread_mutex_lock(pthread_mutex_t *mutex __unused) { return 0; } int __weak pthread_mutex_unlock(pthread_mutex_t *mutex __unused) { return 0; } optee_os-4.3.0/lib/libutils/ext/snprintk.c000066400000000000000000000410711464416617300205630ustar00rootroot00000000000000// SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause) /* * Imported from NetBSD 5.1 with modifications to make it a vsnprintf(3) * function */ /* $NetBSD: subr_prf.c,v 1.156 2014/08/15 11:05:35 apb Exp $ */ /*- * Copyright (c) 1986, 1988, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 * * Copyright (c) 2015 Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include /* flags for kprintf */ #define TOCONS 0x0001 /* to the console */ #define TOTTY 0x0002 /* to the process' tty */ #define TOLOG 0x0004 /* to the kernel message buffer */ #define TOBUFONLY 0x0008 /* to the buffer (only) [for snprintk] */ #define TODDB 0x0010 /* to ddb console */ #define NOLOCK 0x1000 /* don't acquire a tty lock */ /* max size buffer kprintf needs to print a UUID */ #define KPRINTF_BUFSIZE 37 /* * The following macro is used to remove const cast-away warnings * from gcc -Wcast-qual; it should be used with caution because it * can hide valid errors; in particular most valid uses are in * situations where the API requires it, not to cast away string * constants. We don't use *intptr_t on purpose here and we are * explicit about unsigned long so that we don't have additional * dependencies. */ #define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) #define putchar(c, flags, tty) \ do { (void)(c); (void)(flags); (void)(tty); } while(0) static int kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap, bool ext); static const char hexdigits[] = "0123456789abcdef"; static const char HEXDIGITS[] = "0123456789ABCDEF"; /* * snprintk: print a message to a buffer. Same as snprintf but supports * format extensions. */ int snprintk(char *bf, size_t size, const char *fmt, ...) { int retval; va_list ap; va_start(ap, fmt); retval = vsnprintk(bf, size, fmt, ap); va_end(ap); return retval; } /* * vsnprintk: print a message to a buffer [already have va_list] * Same as vsnprintf but supports format extensions. */ int vsnprintk(char *bf, size_t size, const char *fmt, va_list ap) { return __vsnprintf(bf, size, fmt, ap, true); } int __vsnprintf(char *bf, size_t size, const char *fmt, va_list ap, bool ext) { int retval; char *p; p = bf + size; retval = kprintf(fmt, TOBUFONLY, &p, bf, ap, ext); if (bf && size > 0) { /* nul terminate */ if (size <= (size_t)retval) bf[size - 1] = '\0'; else bf[retval] = '\0'; } return retval; } int __vsprintf(char *bf, const char *fmt, va_list ap) { return kprintf(fmt, TOBUFONLY, NULL, bf, ap, false); } /* * kprintf: scaled down version of printf(3). * * this version based on vfprintf() from libc which was derived from * software contributed to Berkeley by Chris Torek. * */ /* * macros for converting digits to letters and vice versa */ #define to_digit(c) ((c) - '0') #define is_digit(c) ((unsigned)to_digit(c) <= 9) #define to_char(n) ((n) + '0') /* * flags used during conversion. */ #define ALT 0x001 /* alternate form */ #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ #define LADJUST 0x004 /* left adjustment */ #define LONGDBL 0x008 /* long double; unimplemented */ #define LONGINT 0x010 /* long integer */ #define QUADINT 0x020 /* quad integer */ #define SHORTINT 0x040 /* short integer */ #define MAXINT 0x080 /* intmax_t */ #define PTRINT 0x100 /* intptr_t */ #define SIZEINT 0x200 /* size_t */ #define ZEROPAD 0x400 /* zero (as opposed to blank) pad */ #define FPT 0x800 /* Floating point number */ /* * To extend shorts properly, we need both signed and unsigned * argument extraction methods. */ #define SARG() \ (flags&MAXINT ? va_arg(ap, intmax_t) : \ flags&PTRINT ? va_arg(ap, intptr_t) : \ flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \ flags&QUADINT ? va_arg(ap, int64_t) : \ flags&LONGINT ? va_arg(ap, long) : \ flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ (long)va_arg(ap, int)) #define UARG() \ (flags&MAXINT ? va_arg(ap, uintmax_t) : \ flags&PTRINT ? va_arg(ap, uintptr_t) : \ flags&SIZEINT ? va_arg(ap, size_t) : \ flags&QUADINT ? va_arg(ap, uint64_t) : \ flags&LONGINT ? va_arg(ap, unsigned long) : \ flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \ (unsigned long)va_arg(ap, unsigned int)) #define KPRINTF_PUTCHAR(C) { \ if (oflags == TOBUFONLY) { \ if (sbuf && ((vp == NULL) || (sbuf < tailp))) \ *sbuf++ = (C); \ } else { \ putchar((C), oflags, vp); \ } \ } static int uuid2str(char *dst, size_t size, void *ptr) { struct { uint32_t lo; uint16_t mid; uint16_t hi_ver; uint8_t seq_n[8]; } *uuid = ptr; return snprintk(dst, size, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid->lo, uuid->mid, uuid->hi_ver, uuid->seq_n[0], uuid->seq_n[1], uuid->seq_n[2], uuid->seq_n[3], uuid->seq_n[4], uuid->seq_n[5], uuid->seq_n[6], uuid->seq_n[7]); } /* * Guts of kernel printf. Note, we already expect to be in a mutex! */ static int kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap, bool ext) { const char *fmt; /* format string */ int ch; /* character from fmt */ int n; /* handy integer (short term usage) */ char *cp; /* handy char pointer (short term usage) */ int flags; /* flags as above */ int ret; /* return value accumulator */ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ uint64_t _uquad; /* integer arguments %[diouxX] */ enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ int dprec; /* a copy of prec if [diouxX], 0 otherwise */ int realsz; /* field size expanded by dprec */ int size; /* size of converted field or string */ const char *xdigs; /* digits for [xX] conversion */ char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX], possibly %pUl */ char *tailp; /* tail pointer for snprintk */ if (oflags == TOBUFONLY && (vp != NULL)) tailp = *(char **)vp; else tailp = NULL; cp = NULL; /* XXX: shutup gcc */ size = 0; /* XXX: shutup gcc */ fmt = fmt0; ret = 0; xdigs = NULL; /* XXX: shut up gcc warning */ /* * Scan the format for conversions (`%' character). */ for (;;) { for (; *fmt != '%' && *fmt; fmt++) { ret++; KPRINTF_PUTCHAR(*fmt); } if (*fmt == 0) goto done; fmt++; /* skip over '%' */ flags = 0; dprec = 0; width = 0; prec = -1; sign = '\0'; rflag: ch = *fmt++; reswitch: switch (ch) { case ' ': /* * ``If the space and + flags both appear, the space * flag will be ignored.'' * -- ANSI X3J11 */ if (!sign) sign = ' '; goto rflag; case '#': flags |= ALT; goto rflag; case '*': /* * ``A negative field width argument is taken as a * - flag followed by a positive field width.'' * -- ANSI X3J11 * They don't exclude field widths read from args. */ if ((width = va_arg(ap, int)) >= 0) goto rflag; width = -width; fallthrough; case '-': flags |= LADJUST; goto rflag; case '+': sign = '+'; goto rflag; case '.': if ((ch = *fmt++) == '*') { n = va_arg(ap, int); prec = n < 0 ? -1 : n; goto rflag; } n = 0; while (is_digit(ch)) { n = 10 * n + to_digit(ch); ch = *fmt++; } prec = n < 0 ? -1 : n; goto reswitch; case '0': /* * ``Note that 0 is taken as a flag, not as the * beginning of a field width.'' * -- ANSI X3J11 */ flags |= ZEROPAD; goto rflag; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n = 10 * n + to_digit(ch); ch = *fmt++; } while (is_digit(ch)); width = n; goto reswitch; case 'h': flags |= SHORTINT; goto rflag; case 'j': flags |= MAXINT; goto rflag; case 'l': if (*fmt == 'l') { fmt++; flags |= QUADINT; } else { flags |= LONGINT; } goto rflag; case 'q': flags |= QUADINT; goto rflag; case 't': flags |= PTRINT; goto rflag; case 'z': flags |= SIZEINT; goto rflag; case 'c': *(cp = bf) = va_arg(ap, int); size = 1; sign = '\0'; break; case 'D': flags |= LONGINT; fallthrough; case 'd': case 'i': _uquad = SARG(); if ((int64_t)_uquad < 0) { _uquad = -_uquad; sign = '-'; } base = DEC; goto number; case 'n': if (flags & MAXINT) *va_arg(ap, intmax_t *) = ret; else if (flags & PTRINT) *va_arg(ap, intptr_t *) = ret; else if (flags & SIZEINT) *va_arg(ap, ssize_t *) = ret; else if (flags & QUADINT) *va_arg(ap, int64_t *) = ret; else if (flags & LONGINT) *va_arg(ap, long *) = ret; else if (flags & SHORTINT) *va_arg(ap, short *) = ret; else *va_arg(ap, int *) = ret; continue; /* no output */ case 'O': flags |= LONGINT; fallthrough; case 'o': _uquad = UARG(); base = OCT; goto nosign; case 'p': if (ext && *fmt == 'U' && *(fmt+1) == 'l') { /* * Non-standard format available in [v]snprintk * only */ fmt += 2; size = uuid2str(bf, sizeof(bf), va_arg(ap, void *)); cp = bf; sign = '\0'; break; } /* * ``The argument shall be a pointer to void. The * value of the pointer is converted to a sequence * of printable characters, in an implementation- * defined manner.'' * -- ANSI X3J11 */ /* NOSTRICT */ _uquad = (unsigned long)va_arg(ap, void *); base = HEX; xdigs = hexdigits; flags |= HEXPREFIX; ch = 'x'; goto nosign; case 's': if ((cp = va_arg(ap, char *)) == NULL) /*XXXUNCONST*/ cp = __UNCONST("(null)"); if (prec >= 0) { /* * can't use strlen; can only look for the * NUL in the first `prec' characters, and * strlen() will go further. */ char *p = memchr(cp, 0, prec); if (p != NULL) { size = p - cp; if (size > prec) size = prec; } else size = prec; } else size = strlen(cp); sign = '\0'; break; case 'U': flags |= LONGINT; fallthrough; case 'u': _uquad = UARG(); base = DEC; goto nosign; case 'X': xdigs = HEXDIGITS; goto hex; case 'x': xdigs = hexdigits; hex: _uquad = UARG(); base = HEX; /* leading 0x/X only if non-zero */ if (flags & ALT && _uquad != 0) flags |= HEXPREFIX; /* unsigned conversions */ nosign: sign = '\0'; /* * ``... diouXx conversions ... if a precision is * specified, the 0 flag will be ignored.'' * -- ANSI X3J11 */ number: if ((dprec = prec) >= 0) flags &= ~ZEROPAD; /* * ``The result of converting a zero value with an * explicit precision of zero is no characters.'' * -- ANSI X3J11 */ cp = bf + KPRINTF_BUFSIZE; if (_uquad != 0 || prec != 0) { /* * Unsigned mod is hard, and unsigned mod * by a constant is easier than that by * a variable; hence this switch. */ switch (base) { case OCT: do { *--cp = to_char(_uquad & 7); _uquad >>= 3; } while (_uquad); /* handle octal leading 0 */ if (flags & ALT && *cp != '0') *--cp = '0'; break; case DEC: /* many numbers are 1 digit */ while (_uquad >= 10) { *--cp = to_char(_uquad % 10); _uquad /= 10; } *--cp = to_char(_uquad); break; case HEX: do { *--cp = xdigs[_uquad & 15]; _uquad >>= 4; } while (_uquad); break; default: /*XXXUNCONST*/ cp = __UNCONST("bug in kprintf: bad base"); size = strlen(cp); goto skipsize; } } size = bf + KPRINTF_BUFSIZE - cp; skipsize: break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; /* pretend it was %c with argument ch */ cp = bf; *cp = ch; size = 1; sign = '\0'; break; } /* * All reasonable formats wind up here. At this point, `cp' * points to a string which (if not flags&LADJUST) should be * padded out to `width' places. If flags&ZEROPAD, it should * first be prefixed by any sign or other prefix; otherwise, * it should be blank padded before the prefix is emitted. * After any left-hand padding and prefixing, emit zeroes * required by a decimal [diouxX] precision, then print the * string proper, then emit zeroes required by any leftover * floating precision; finally, if LADJUST, pad with blanks. * * Compute actual size, so we know how much to pad. * size excludes decimal prec; realsz includes it. */ realsz = dprec > size ? dprec : size; if (sign) realsz++; else if (flags & HEXPREFIX) realsz+= 2; /* adjust ret */ ret += width > realsz ? width : realsz; /* right-adjusting blank padding */ if ((flags & (LADJUST|ZEROPAD)) == 0) { n = width - realsz; while (n-- > 0) KPRINTF_PUTCHAR(' '); } /* prefix */ if (sign) { KPRINTF_PUTCHAR(sign); } else if (flags & HEXPREFIX) { KPRINTF_PUTCHAR('0'); KPRINTF_PUTCHAR(ch); } /* right-adjusting zero padding */ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) { n = width - realsz; while (n-- > 0) KPRINTF_PUTCHAR('0'); } /* leading zeroes from decimal precision */ n = dprec - size; while (n-- > 0) KPRINTF_PUTCHAR('0'); /* the string or number proper */ for (; size--; cp++) KPRINTF_PUTCHAR(*cp); /* left-adjusting padding (always blank) */ if (flags & LADJUST) { n = width - realsz; while (n-- > 0) KPRINTF_PUTCHAR(' '); } } done: if ((oflags == TOBUFONLY) && (vp != NULL)) *(char **)vp = sbuf; return ret; } optee_os-4.3.0/lib/libutils/ext/strlcat.c000066400000000000000000000052321464416617300203660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* This file is copied from newlib-1.19 */ /* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include /* #include */ size_t strlen(const char *s); /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return dlen + strlen(s); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return dlen + (s - src); /* count does not include NUL */ } optee_os-4.3.0/lib/libutils/ext/strlcpy.c000066400000000000000000000047621464416617300204210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* This file is copied from newlib-1.19 */ /* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char *rcsid = "$OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return s - src - 1; /* count does not include NUL */ } optee_os-4.3.0/lib/libutils/ext/sub.mk000066400000000000000000000005341464416617300176700ustar00rootroot00000000000000global-incdirs-y += include srcs-y += snprintk.c srcs-y += strlcat.c srcs-y += strlcpy.c srcs-y += trace.c srcs-y += mempool.c srcs-y += nex_strdup.c srcs-y += consttime_memcmp.c srcs-y += memzero_explicit.c srcs-y += fault_mitigation.c ifneq (,$(filter ta_%,$(sm))) srcs-y += pthread_stubs.c endif subdirs-y += arch/$(ARCH) subdirs-y += ftrace optee_os-4.3.0/lib/libutils/ext/trace.c000066400000000000000000000142411464416617300200100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #if defined(__KERNEL__) #include #endif #include #include #include #include #include #include #include #if (TRACE_LEVEL < TRACE_MIN) || (TRACE_LEVEL > TRACE_MAX) #error "Invalid value of TRACE_LEVEL" #endif #if (TRACE_LEVEL >= TRACE_ERROR) void trace_set_level(int level) { if (((int)level >= TRACE_MIN) && (level <= TRACE_MAX)) trace_level = level; else trace_level = TRACE_MAX; } int trace_get_level(void) { return trace_level; } static char trace_level_to_string(int level, bool level_ok) { /* * U = Unused * E = Error * I = Information * D = Debug * F = Flow */ static const char lvl_strs[] = { 'U', 'E', 'I', 'D', 'F' }; int l = 0; if (!level_ok) return 'M'; if ((level >= TRACE_MIN) && (level <= TRACE_MAX)) l = level; return lvl_strs[l]; } static int print_thread_id(char *buf, size_t bs) { #if CFG_NUM_THREADS > 100 int num_thread_digits = 3; #elif CFG_NUM_THREADS > 10 int num_thread_digits = 2; #else int num_thread_digits = 1; #endif int thread_id = trace_ext_get_thread_id(); if (thread_id >= 0) return snprintk(buf, bs, "%0*d ", num_thread_digits, thread_id); else return snprintk(buf, bs, "%*s ", num_thread_digits, ""); } #if defined(__KERNEL__) static int print_core_id(char *buf, size_t bs) { #if CFG_TEE_CORE_NB_CORE > 100 const int num_digits = 3; const char qm[] = "???"; #elif CFG_TEE_CORE_NB_CORE > 10 const int num_digits = 2; const char qm[] = "??"; #else const int num_digits = 1; const char qm[] = "?"; #endif int core_id = trace_ext_get_core_id(); if (core_id >= 0) return snprintk(buf, bs, "%0*u ", num_digits, core_id); else return snprintk(buf, bs, "%s ", qm); } static int print_guest_id(char *buf, size_t bs) { if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) return snprintk(buf, bs, "%d ", trace_ext_get_guest_id()); else return 0; } #else /* defined(__KERNEL__) */ static int print_core_id(char *buf __unused, size_t bs __unused) { return 0; } static int print_guest_id(char *buf __unused, size_t bs __unused) { return 0; } #endif /* Format trace of user ta. Inline with kernel ta */ void trace_printf(const char *function, int line, int level, bool level_ok, const char *fmt, ...) { va_list ap; va_start(ap, fmt); trace_vprintf(function, line, level, level_ok, fmt, ap); va_end(ap); } void trace_vprintf(const char *function, int line, int level, bool level_ok, const char *fmt, va_list ap) { char buf[MAX_PRINT_SIZE]; size_t boffs = 0; int res; if (level_ok && level > trace_level) return; /* Print the type of message */ res = snprintk(buf, sizeof(buf), "%c/", trace_level_to_string(level, level_ok)); if (res < 0) return; boffs += res; /* Print the location, i.e., TEE core or TA */ res = snprintk(buf + boffs, sizeof(buf) - boffs, "%s:", trace_ext_prefix); if (res < 0) return; boffs += res; if (level_ok && (BIT(level) & CFG_MSG_LONG_PREFIX_MASK)) { /* Print the current guest ID or 0 for Nexus */ res = print_guest_id(buf + boffs, sizeof(buf) - boffs); if (res < 0) return; boffs += res; /* Print the core ID if in atomic context */ res = print_core_id(buf + boffs, sizeof(buf) - boffs); if (res < 0) return; boffs += res; /* Print the Thread ID */ res = print_thread_id(buf + boffs, sizeof(buf) - boffs); if (res < 0) return; boffs += res; if (function) { res = snprintk(buf + boffs, sizeof(buf) - boffs, "%s:%d ", function, line); if (res < 0) return; boffs += res; } } else { /* Add space after location info */ if (boffs >= sizeof(buf) - 1) return; buf[boffs++] = ' '; buf[boffs] = 0; } res = vsnprintk(buf + boffs, sizeof(buf) - boffs, fmt, ap); if (res > 0) boffs += res; if (boffs >= (sizeof(buf) - 1)) boffs = sizeof(buf) - 2; buf[boffs] = '\n'; while (boffs && buf[boffs] == '\n') boffs--; boffs++; buf[boffs + 1] = '\0'; trace_ext_puts(buf); } #else /* * In case we have a zero or negative trace level when compiling optee_os, we * have to add stubs to trace functions in case they are used with TA having a * non-zero trace level */ void trace_set_level(int level __unused) { } int trace_get_level(void) { return 0; } void trace_printf(const char *function __unused, int line __unused, int level __unused, bool level_ok __unused, const char *fmt __unused, ...) { } #endif #if (TRACE_LEVEL >= TRACE_DEBUG) struct strbuf { char buf[MAX_PRINT_SIZE]; char *ptr; }; static int __printf(2, 3) append(struct strbuf *sbuf, const char *fmt, ...) { int left; int len; va_list ap; if (sbuf->ptr == NULL) sbuf->ptr = sbuf->buf; left = sizeof(sbuf->buf) - (sbuf->ptr - sbuf->buf); va_start(ap, fmt); len = vsnprintk(sbuf->ptr, left, fmt, ap); va_end(ap); if (len < 0) { /* Format error */ return 0; } if (len >= left) { /* Output was truncated */ return 0; } sbuf->ptr += MIN(left, len); return 1; } void dhex_dump(const char *function, int line, int level, const void *buf, int len) { int i; int ok; struct strbuf sbuf; char *in = (char *)buf; if (level <= trace_level) { sbuf.ptr = NULL; for (i = 0; i < len; i++) { if ((i % 16) == 0) { ok = append(&sbuf, "%0*" PRIxVA " ", PRIxVA_WIDTH, (vaddr_t)(in + i)); if (!ok) goto err; } ok = append(&sbuf, "%02x ", in[i]); if (!ok) goto err; if ((i % 16) == 7) { ok = append(&sbuf, " "); if (!ok) goto err; } else if ((i % 16) == 15) { trace_printf(function, line, level, true, "%s", sbuf.buf); sbuf.ptr = NULL; } } if (sbuf.ptr) { /* Buffer is not empty: flush it */ trace_printf(function, line, level, true, "%s", sbuf.buf); } } return; err: DMSG("Hex dump error"); } #else /* * In case we have trace level less than debug when compiling optee_os, we have * to add stubs to trace functions in case they are used with TA having a * a higher trace level */ void dhex_dump(const char *function __unused, int line __unused, int level __unused, const void *buf __unused, int len __unused) { } #endif optee_os-4.3.0/lib/libutils/isoc/000077500000000000000000000000001464416617300167015ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/000077500000000000000000000000001464416617300176165ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/000077500000000000000000000000001464416617300203755ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod.c000066400000000000000000000100301464416617300241420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* * Form ABI specifications: * int __aeabi_idiv(int numerator, int denominator); * unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); * * typedef struct { int quot; int rem; } idiv_return; * typedef struct { unsigned quot; unsigned rem; } uidiv_return; * * __value_in_regs idiv_return __aeabi_idivmod(int numerator, * int *denominator); * __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator, * unsigned denominator); */ #include /* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */ struct qr { unsigned q; /* computed quotient */ unsigned r; /* computed remainder */ unsigned q_n; /* specficies if quotient shall be negative */ unsigned r_n; /* specficies if remainder shall be negative */ }; static void uint_div_qr(unsigned numerator, unsigned denominator, struct qr *qr); /* returns in R0 and R1 by tail calling an asm function */ unsigned __aeabi_uidivmod(unsigned numerator, unsigned denominator); unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); /* returns in R0 and R1 by tail calling an asm function */ signed __aeabi_idivmod(signed numerator, signed denominator); signed __aeabi_idiv(signed numerator, signed denominator); /* * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator) * Numerator and Denominator are received in R0 and R1. * Where __ste_idivmod_ret_t is returned in R0 and R1. * * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator, * unsigned denominator) * Numerator and Denominator are received in R0 and R1. * Where __ste_uidivmod_ret_t is returned in R0 and R1. */ #ifdef __GNUC__ signed ret_idivmod_values(signed quotient, signed remainder); unsigned ret_uidivmod_values(unsigned quotient, unsigned remainder); #else #error "Compiler not supported" #endif static void division_qr(unsigned n, unsigned p, struct qr *qr) { unsigned i = 1, q = 0; if (p == 0) { qr->r = 0xFFFFFFFF; /* division by 0 */ return; } while ((p >> 31) == 0) { i = i << 1; /* count the max division steps */ p = p << 1; /* increase p until it has maximum size*/ } while (i > 0) { q = q << 1; /* write bit in q at index (size-1) */ if (n >= p) { n -= p; q++; } p = p >> 1; /* decrease p */ i = i >> 1; /* decrease remaining size in q */ } qr->r = n; qr->q = q; } static void uint_div_qr(unsigned numerator, unsigned denominator, struct qr *qr) { division_qr(numerator, denominator, qr); /* negate quotient and/or remainder according to requester */ if (qr->q_n) qr->q = -qr->q; if (qr->r_n) qr->r = -qr->r; } unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator) { struct qr qr = { .q_n = 0, .r_n = 0 }; uint_div_qr(numerator, denominator, &qr); return qr.q; } unsigned __no_stackprot __aeabi_uidivmod(unsigned numerator, unsigned denominator) { struct qr qr = { .q_n = 0, .r_n = 0 }; uint_div_qr(numerator, denominator, &qr); return ret_uidivmod_values(qr.q, qr.r); } signed __aeabi_idiv(signed numerator, signed denominator) { struct qr qr = { .q_n = 0, .r_n = 0 }; if (((numerator < 0) && (denominator > 0)) || ((numerator > 0) && (denominator < 0))) qr.q_n = 1; /* quotient shall be negate */ if (numerator < 0) { numerator = -numerator; qr.r_n = 1; /* remainder shall be negate */ } if (denominator < 0) denominator = -denominator; uint_div_qr(numerator, denominator, &qr); return qr.q; } signed __no_stackprot __aeabi_idivmod(signed numerator, signed denominator) { struct qr qr = { .q_n = 0, .r_n = 0 }; if (((numerator < 0) && (denominator > 0)) || ((numerator > 0) && (denominator < 0))) qr.q_n = 1; /* quotient shall be negate */ if (numerator < 0) { numerator = -numerator; qr.r_n = 1; /* remainder shall be negate */ } if (denominator < 0) denominator = -denominator; uint_div_qr(numerator, denominator, &qr); return ret_idivmod_values(qr.q, qr.r); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/arm32_aeabi_divmod_a32.S000066400000000000000000000010701464416617300245730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include .section .note.GNU-stack,"",%progbits /* * signed ret_idivmod_values(signed quot, signed rem); * return quotient and remaining the EABI way (regs r0,r1) */ FUNC ret_idivmod_values , : bx lr END_FUNC ret_idivmod_values /* * unsigned ret_uidivmod_values(unsigned quot, unsigned rem); * return quotient and remaining the EABI way (regs r0,r1) */ FUNC ret_uidivmod_values , : bx lr END_FUNC ret_uidivmod_values optee_os-4.3.0/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod.c000066400000000000000000000046721464416617300243350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, STMicroelectronics International N.V. */ /* struct lqr - stores qutient/remainder to handle divmod EABI interfaces. */ struct lqr { unsigned long long q; /* computed quotient */ unsigned long long r; /* computed remainder */ unsigned q_n; /* specficies if quotient shall be negative */ unsigned r_n; /* specficies if remainder shall be negative */ }; static void ul_div_qr(unsigned long long numerator, unsigned long long denominator, struct lqr *qr); static void division_lqr(unsigned long long n, unsigned long long p, struct lqr *qr) { unsigned long long i = 1, q = 0; if (p == 0) { qr->r = 0xFFFFFFFFFFFFFFFFULL; /* division by 0 */ return; } while ((p >> 63) == 0) { i = i << 1; /* count the max division steps */ p = p << 1; /* increase p until it has maximum size*/ } while (i > 0) { q = q << 1; /* write bit in q at index (size-1) */ if (n >= p) { n -= p; q++; } p = p >> 1; /* decrease p */ i = i >> 1; /* decrease remaining size in q */ } qr->r = n; qr->q = q; } static void ul_div_qr(unsigned long long numerator, unsigned long long denominator, struct lqr *qr) { division_lqr(numerator, denominator, qr); /* negate quotient and/or remainder according to requester */ if (qr->q_n) qr->q = -qr->q; if (qr->r_n) qr->r = -qr->r; } struct asm_ulqr { unsigned long long v0; unsigned long long v1; }; /* called from assembly function __aeabi_uldivmod */ void __ul_divmod(struct asm_ulqr *asm_ulqr); void __ul_divmod(struct asm_ulqr *asm_ulqr) { unsigned long long numerator = asm_ulqr->v0; unsigned long long denominator = asm_ulqr->v1; struct lqr qr = { .q_n = 0, .r_n = 0 }; ul_div_qr(numerator, denominator, &qr); asm_ulqr->v0 = qr.q; asm_ulqr->v1 = qr.r; } struct asm_lqr { long long v0; long long v1; }; /* called from assembly function __aeabi_ldivmod */ void __l_divmod(struct asm_lqr *asm_lqr); void __l_divmod(struct asm_lqr *asm_lqr) { long long numerator = asm_lqr->v0; long long denominator = asm_lqr->v1; struct lqr qr = { .q_n = 0, .r_n = 0 }; if (((numerator < 0) && (denominator > 0)) || ((numerator > 0) && (denominator < 0))) qr.q_n = 1; /* quotient shall be negate */ if (numerator < 0) { numerator = -numerator; qr.r_n = 1; /* remainder shall be negate */ } if (denominator < 0) denominator = -denominator; ul_div_qr(numerator, denominator, &qr); asm_lqr->v0 = qr.q; asm_lqr->v1 = qr.r; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/arm32_aeabi_ldivmod_a32.S000066400000000000000000000012621464416617300247520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2015, Linaro Limited */ #include .section .note.GNU-stack,"",%progbits /* * __value_in_regs lldiv_t __aeabi_ldivmod( long long n, long long d) */ FUNC __aeabi_ldivmod , : push {ip, lr} UNWIND( .save {ip, lr}) push {r0-r3} UNWIND( .save {r0-r3}) mov r0, sp bl __l_divmod pop {r0-r3} pop {ip, pc} END_FUNC __aeabi_ldivmod /* * __value_in_regs ulldiv_t __aeabi_uldivmod( * unsigned long long n, unsigned long long d) */ FUNC __aeabi_uldivmod , : push {ip, lr} UNWIND( .save {ip, lr}) push {r0-r3} UNWIND( .save {r0-r3}) mov r0, sp bl __ul_divmod pop {r0-r3} pop {ip, pc} END_FUNC __aeabi_uldivmod optee_os-4.3.0/lib/libutils/isoc/arch/arm/arm32_aeabi_shift.c000066400000000000000000000016751464416617300240140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ union dword { unsigned long long dw; unsigned long w[2]; }; long long __aeabi_llsl(long long a, int shift); long long __aeabi_llsl(long long a, int shift) { union dword dword = { .dw = a }; unsigned long hi = dword.w[1]; unsigned long lo = dword.w[0]; if (shift >= 32) { hi = lo << (shift - 32); lo = 0; } else if (shift > 0) { hi = (hi << shift) | (lo >> (32 - shift)); lo = lo << shift; } dword.w[1] = hi; dword.w[0] = lo; return dword.dw; } long long __aeabi_llsr(long long a, int shift); long long __aeabi_llsr(long long a, int shift) { union dword dword = { .dw = a }; unsigned long hi = dword.w[1]; unsigned long lo = dword.w[0]; if (shift >= 32) { lo = hi >> (shift - 32); hi = 0; } else if (shift > 0) { lo = (lo >> shift) | (hi << (32 - shift)); hi = hi >> shift; } dword.w[1] = hi; dword.w[0] = lo; return dword.dw; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/arm32_aeabi_softfloat.c000066400000000000000000000136451464416617300247000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include "platform.h" #include /* * On ARM32 EABI defines both a soft-float ABI and a hard-float ABI, * hard-float is basically a super set of soft-float. Hard-float requires * all the support routines provided for soft-float, but the compiler may * choose to optimize to not use some of them. * * The AEABI functions uses soft-float calling convention even if the * functions are compiled for hard-float. So where float and double would * have been expected we use aeabi_float_t and aeabi_double_t respectively * instead. */ typedef unsigned aeabi_float_t; typedef unsigned long long aeabi_double_t; /* * Helpers to convert between float32 and aeabi_float_t, and float64 and * aeabi_double_t used by the AEABI functions below. */ static aeabi_float_t f32_to_f(float32_t val) { union { float32_t from; aeabi_float_t to; } res = { .from = val }; return res.to; } static float32_t f32_from_f(aeabi_float_t val) { union { aeabi_float_t from; float32_t to; } res = { .from = val }; return res.to; } static aeabi_double_t f64_to_d(float64_t val) { union { float64_t from; aeabi_double_t to; } res = { .from = val }; return res.to; } static float64_t f64_from_d(aeabi_double_t val) { union { aeabi_double_t from; float64_t to; } res = { .from = val }; return res.to; } /* * From ARM Run-time ABI for ARM Architecture * ARM IHI 0043D, current through ABI release 2.09 * * 4.1.2 The floating-point helper functions */ /* * Table 2, Standard aeabi_double_t precision floating-point arithmetic helper * functions */ aeabi_double_t __aeabi_dadd(aeabi_double_t a, aeabi_double_t b) { return f64_to_d(f64_add(f64_from_d(a), f64_from_d(b))); } aeabi_double_t __aeabi_ddiv(aeabi_double_t a, aeabi_double_t b) { return f64_to_d(f64_div(f64_from_d(a), f64_from_d(b))); } aeabi_double_t __aeabi_dmul(aeabi_double_t a, aeabi_double_t b) { return f64_to_d(f64_mul(f64_from_d(a), f64_from_d(b))); } aeabi_double_t __aeabi_drsub(aeabi_double_t a, aeabi_double_t b) { return f64_to_d(f64_sub(f64_from_d(b), f64_from_d(a))); } aeabi_double_t __aeabi_dsub(aeabi_double_t a, aeabi_double_t b) { return f64_to_d(f64_sub(f64_from_d(a), f64_from_d(b))); } /* * Table 3, double precision floating-point comparison helper functions */ int __aeabi_dcmpeq(aeabi_double_t a, aeabi_double_t b) { return f64_eq(f64_from_d(a), f64_from_d(b)); } int __aeabi_dcmplt(aeabi_double_t a, aeabi_double_t b) { return f64_lt(f64_from_d(a), f64_from_d(b)); } int __aeabi_dcmple(aeabi_double_t a, aeabi_double_t b) { return f64_le(f64_from_d(a), f64_from_d(b)); } int __aeabi_dcmpge(aeabi_double_t a, aeabi_double_t b) { return f64_le(f64_from_d(b), f64_from_d(a)); } int __aeabi_dcmpgt(aeabi_double_t a, aeabi_double_t b) { return f64_lt(f64_from_d(b), f64_from_d(a)); } /* * Table 4, Standard single precision floating-point arithmetic helper * functions */ aeabi_float_t __aeabi_fadd(aeabi_float_t a, aeabi_float_t b) { return f32_to_f(f32_add(f32_from_f(a), f32_from_f(b))); } aeabi_float_t __aeabi_fdiv(aeabi_float_t a, aeabi_float_t b) { return f32_to_f(f32_div(f32_from_f(a), f32_from_f(b))); } aeabi_float_t __aeabi_fmul(aeabi_float_t a, aeabi_float_t b) { return f32_to_f(f32_mul(f32_from_f(a), f32_from_f(b))); } aeabi_float_t __aeabi_frsub(aeabi_float_t a, aeabi_float_t b) { return f32_to_f(f32_sub(f32_from_f(b), f32_from_f(a))); } aeabi_float_t __aeabi_fsub(aeabi_float_t a, aeabi_float_t b) { return f32_to_f(f32_sub(f32_from_f(a), f32_from_f(b))); } /* * Table 5, Standard single precision floating-point comparison helper * functions */ int __aeabi_fcmpeq(aeabi_float_t a, aeabi_float_t b) { return f32_eq(f32_from_f(a), f32_from_f(b)); } int __aeabi_fcmplt(aeabi_float_t a, aeabi_float_t b) { return f32_lt(f32_from_f(a), f32_from_f(b)); } int __aeabi_fcmple(aeabi_float_t a, aeabi_float_t b) { return f32_le(f32_from_f(a), f32_from_f(b)); } int __aeabi_fcmpge(aeabi_float_t a, aeabi_float_t b) { return f32_le(f32_from_f(b), f32_from_f(a)); } int __aeabi_fcmpgt(aeabi_float_t a, aeabi_float_t b) { return f32_lt(f32_from_f(b), f32_from_f(a)); } /* * Table 6, Standard floating-point to integer conversions */ int __aeabi_d2iz(aeabi_double_t a) { return f64_to_i32_r_minMag(f64_from_d(a), false); } unsigned __aeabi_d2uiz(aeabi_double_t a) { return f64_to_ui32_r_minMag(f64_from_d(a), false); } long long __aeabi_d2lz(aeabi_double_t a) { return f64_to_i64_r_minMag(f64_from_d(a), false); } unsigned long long __aeabi_d2ulz(aeabi_double_t a) { return f64_to_ui64_r_minMag(f64_from_d(a), false); } int __aeabi_f2iz(aeabi_float_t a) { return f32_to_i32_r_minMag(f32_from_f(a), false); } unsigned __aeabi_f2uiz(aeabi_float_t a) { return f32_to_ui32_r_minMag(f32_from_f(a), false); } long long __aeabi_f2lz(aeabi_float_t a) { return f32_to_i64_r_minMag(f32_from_f(a), false); } unsigned long long __aeabi_f2ulz(aeabi_float_t a) { return f32_to_ui64_r_minMag(f32_from_f(a), false); } /* * Table 7, Standard conversions between floating types */ aeabi_float_t __aeabi_d2f(aeabi_double_t a) { return f32_to_f(f64_to_f32(f64_from_d(a))); } aeabi_double_t __aeabi_f2d(aeabi_float_t a) { return f64_to_d(f32_to_f64(f32_from_f(a))); } /* * Table 8, Standard integer to floating-point conversions */ aeabi_double_t __aeabi_i2d(int a) { return f64_to_d(i32_to_f64(a)); } aeabi_double_t __aeabi_ui2d(unsigned a) { return f64_to_d(ui32_to_f64(a)); } aeabi_double_t __aeabi_l2d(long long a) { return f64_to_d(i64_to_f64(a)); } aeabi_double_t __aeabi_ul2d(unsigned long long a) { return f64_to_d(ui64_to_f64(a)); } aeabi_float_t __aeabi_i2f(int a) { return f32_to_f(i32_to_f32(a)); } aeabi_float_t __aeabi_ui2f(unsigned a) { return f32_to_f(ui32_to_f32(a)); } aeabi_float_t __aeabi_l2f(long long a) { return f32_to_f(i64_to_f32(a)); } aeabi_float_t __aeabi_ul2f(unsigned long long a) { return f32_to_f(ui64_to_f32(a)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/setjmp_a32.S000066400000000000000000000165521464416617300225010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* This is a simple version of setjmp and longjmp. Nick Clifton, Cygnus Solutions, 13 June 1997. */ /* ANSI concatenation macros. */ #define CONCAT(a, b) CONCAT2(a, b) #define CONCAT2(a, b) a##b #ifndef __USER_LABEL_PREFIX__ #error __USER_LABEL_PREFIX__ not defined #endif #define SYM(x) CONCAT (__USER_LABEL_PREFIX__, x) #ifdef __ELF__ #define TYPE(x) .type SYM(x),function #define SIZE(x) .size SYM(x), . - SYM(x) #else #define TYPE(x) #define SIZE(x) #endif .section .note.GNU-stack,"",%progbits /* Arm/Thumb interworking support: The interworking scheme expects functions to use a BX instruction to return control to their parent. Since we need this code to work in both interworked and non-interworked environments as well as with older processors which do not have the BX instruction we do the following: Test the return address. If the bottom bit is clear perform an "old style" function exit. (We know that we are in ARM mode and returning to an ARM mode caller). Otherwise use the BX instruction to perform the function exit. We know that we will never attempt to perform the BX instruction on an older processor, because that kind of processor will never be interworked, and a return address with the bottom bit set will never be generated. In addition, we do not actually assemble the BX instruction as this would require us to tell the assembler that the processor is an ARM7TDMI and it would store this information in the binary. We want this binary to be able to be linked with binaries compiled for older processors however, so we do not want such information stored there. If we are running using the APCS-26 convention however, then we never test the bottom bit, because this is part of the processor status. Instead we just do a normal return, since we know that we cannot be returning to a Thumb caller - the Thumb does not support APCS-26. Function entry is much simpler. If we are compiling for the Thumb we just switch into ARM mode and then drop through into the rest of the function. The function exit code will take care of the restore to Thumb mode. For Thumb-2 do everything in Thumb mode. */ #if defined(__ARM_ARCH_6M__) /* ARMv6-M has to be implemented in Thumb mode. */ .thumb .thumb_func .globl SYM (setjmp) TYPE (setjmp) SYM (setjmp): /* Save registers in jump buffer. */ stmia r0!, {r4, r5, r6, r7} mov r1, r8 mov r2, r9 mov r3, r10 mov r4, fp mov r5, sp mov r6, lr stmia r0!, {r1, r2, r3, r4, r5, r6} sub r0, r0, #40 /* Restore callee-saved low regs. */ ldmia r0!, {r4, r5, r6, r7} /* Return zero. */ mov r0, #0 bx lr .thumb_func .globl SYM (longjmp) TYPE (longjmp) SYM (longjmp): /* Restore High regs. */ add r0, r0, #16 ldmia r0!, {r2, r3, r4, r5, r6} mov r8, r2 mov r9, r3 mov r10, r4 mov fp, r5 mov sp, r6 ldmia r0!, {r3} /* lr */ /* Restore low regs. */ sub r0, r0, #40 ldmia r0!, {r4, r5, r6, r7} /* Return the result argument, or 1 if it is zero. */ mov r0, r1 bne 1f mov r0, #1 1: bx r3 #else #ifdef __APCS_26__ #define RET movs pc, lr #elif defined(__thumb2__) #define RET bx lr #else #define RET tst lr, #1; \ moveq pc, lr ; \ .word 0xe12fff1e /* bx lr */ #endif #ifdef __thumb2__ .macro COND where when i\where \when .endm #else .macro COND where when .endm #endif #if defined(__thumb2__) .syntax unified .macro MODE .thumb .thumb_func .endm .macro PROLOGUE name .endm #elif defined(__thumb__) #define MODE .thumb_func .macro PROLOGUE name .code 16 bx pc nop .code 32 SYM (.arm_start_of.\name): .endm #else /* Arm */ #define MODE .code 32 .macro PROLOGUE name .endm #endif .macro FUNC_START name .text .align 2 MODE .globl SYM (\name) TYPE (\name) SYM (\name): PROLOGUE \name .endm .macro FUNC_END name RET SIZE (\name) .endm /* -------------------------------------------------------------------- int setjmp (jmp_buf); -------------------------------------------------------------------- */ FUNC_START setjmp /* Save all the callee-preserved registers into the jump buffer. */ #ifdef __thumb2__ mov ip, sp stmea a1!, { v1-v7, fp, ip, lr } #else stmea a1!, { v1-v7, fp, ip} str sp, [a1], #4 str lr, [a1], #4 #endif #if 0 /* Simulator does not cope with FP instructions yet. */ #ifndef __SOFTFP__ /* Save the floating point registers. */ sfmea f4, 4, [a1] #endif #endif #ifdef CFG_FTRACE_SUPPORT stmdb sp!, { lr } /* * As ftrace is supported in ARM mode only, so hardcode jmp_buf * offset used to save ftrace return index. */ add a1, a1, #48 bl ftrace_setjmp ldmia sp!, { lr } #endif /* When setting up the jump buffer return 0. */ mov a1, #0 FUNC_END setjmp /* -------------------------------------------------------------------- volatile void longjmp (jmp_buf, int); -------------------------------------------------------------------- */ FUNC_START longjmp /* If we have stack extension code it ought to be handled here. */ #ifdef CFG_FTRACE_SUPPORT stmdb sp!, { a1, a2, lr } /* * As ftrace is supported in ARM mode only, so hardcode jmp_buf * offset used to restore ftrace return stack. */ add a1, a1, #92 bl ftrace_longjmp ldmia sp!, { a1, a2, lr } #endif /* Restore the registers, retrieving the state when setjmp() was called. */ #ifdef __thumb2__ ldmfd a1!, { v1-v7, fp, ip, lr } mov sp, ip #else ldmfd a1!, { v1-v7, fp, ip } ldr sp, [a1], #4 ldr lr, [a1], #4 #endif #if 0 /* Simulator does not cope with FP instructions yet. */ #ifndef __SOFTFP__ /* Restore floating point registers as well. */ lfmfd f4, 4, [a1] #endif #endif /* Put the return value into the integer result register. But if it is zero then return 1 instead. */ movs a1, a2 #ifdef __thumb2__ it eq #endif moveq a1, #1 FUNC_END longjmp #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/setjmp_a64.S000066400000000000000000000062421464416617300225010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* Copyright (c) 2011, 2012 ARM Ltd All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the company may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #define GPR_LAYOUT \ REG_PAIR (x19, x20, 0); \ REG_PAIR (x21, x22, 16); \ REG_PAIR (x23, x24, 32); \ REG_PAIR (x25, x26, 48); \ REG_PAIR (x27, x28, 64); \ REG_PAIR (x29, x30, 80); \ REG_ONE (x16, 96) #define FPR_LAYOUT \ REG_PAIR ( d8, d9, 112); \ REG_PAIR (d10, d11, 128); \ REG_PAIR (d12, d13, 144); \ REG_PAIR (d14, d15, 160); // int setjmp (jmp_buf) .global setjmp .type setjmp, %function setjmp: BTI( bti c) mov x16, sp #define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS] #define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS] GPR_LAYOUT FPR_LAYOUT #ifdef CFG_FTRACE_SUPPORT stp x29, x30, [sp, #-16]! mov x29, sp add x0, x0, #104 bl ftrace_setjmp ldp x29, x30, [sp], #16 #endif #undef REG_PAIR #undef REG_ONE mov w0, #0 ret .size setjmp, .-setjmp // void longjmp (jmp_buf, int) __attribute__ ((noreturn)) .global longjmp .type longjmp, %function longjmp: BTI( bti c) #define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS] #define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS] #ifdef CFG_FTRACE_SUPPORT stp x0, x1, [sp, #-16]! stp x29, x30, [sp, #-16]! mov x29, sp add x0, x0, #104 bl ftrace_longjmp ldp x29, x30, [sp], #16 ldp x0, x1, [sp], #16 #endif GPR_LAYOUT FPR_LAYOUT #undef REG_PAIR #undef REG_ONE mov sp, x16 cmp w1, #0 cinc w0, w1, eq /* * clang has a bug and doesn't insert bti after setjmp * causing BTI ecxception. Remove this when the bug is fixed. * https://bugs.llvm.org/show_bug.cgi?id=49544 */ #if defined(__clang__) && defined(CFG_TA_BTI) ret #else // use br not ret, as ret is guaranteed to mispredict br x30 #endif .size longjmp, .-longjmp BTI(emit_aarch64_feature_1_and GNU_PROPERTY_AARCH64_FEATURE_1_BTI) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/000077500000000000000000000000001464416617300223765ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/COPYING.txt000066400000000000000000000032701464416617300242510ustar00rootroot00000000000000 License for Berkeley SoftFloat Release 3a John R. Hauser 2015 October 23 The following applies to the whole of SoftFloat Release 3a as well as to each source file individually. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/README.html000066400000000000000000000023451464416617300242250ustar00rootroot00000000000000 Berkeley SoftFloat Package Overview

Package Overview for Berkeley SoftFloat Release 3a

John R. Hauser
2015 October 23

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

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

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

optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/README.txt000066400000000000000000000014351464416617300240770ustar00rootroot00000000000000 Package Overview for Berkeley SoftFloat Release 3a John R. Hauser 2015 October 23 Berkeley SoftFloat is a software implementation of binary floating-point that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat is distributed in the form of C source code. Building the SoftFloat sources generates a library file (typically "softfloat.a" or "libsoftfloat.a") containing the floating-point subroutines. The SoftFloat package is documented in the following files in the "doc" subdirectory: SoftFloat.html Documentation for using the SoftFloat functions. SoftFloat-source.html Documentation for building SoftFloat. SoftFloat-history.html History of the major changes to SoftFloat. Other files in the package comprise the source code for SoftFloat. optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/arm32_include/000077500000000000000000000000001464416617300250255ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/arm32_include/platform.h000066400000000000000000000036641464416617300270330ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header template is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #define LITTLEENDIAN 1 #define INLINE static inline #define SOFTFLOAT_FAST_DIV64TO32 #define SOFTFLOAT_FAST_INT64 optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/000077500000000000000000000000001464416617300234755ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/000077500000000000000000000000001464416617300255045ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/Makefile000066400000000000000000000172471464416617300271570ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic # Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR = ../../source SPECIALIZE_TYPE = 8086 SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = rm -f C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include COMPILE_C = \ gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ $(C_INCLUDES) -O2 -o $@ MAKELIB = ar crs $@ OBJ = .o LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_compare96M$(OBJ) \ s_compare128M$(OBJ) \ s_shortShiftLeft64To96M$(OBJ) \ s_shortShiftLeftM$(OBJ) \ s_shiftLeftM$(OBJ) \ s_shortShiftRightM$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJamM$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJamM$(OBJ) \ s_shiftRightM$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_addM$(OBJ) \ s_addCarryM$(OBJ) \ s_addComplCarryM$(OBJ) \ s_negXM$(OBJ) \ s_sub1XM$(OBJ) \ s_subM$(OBJ) \ s_mul64To128M$(OBJ) \ s_mul128MTo256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ s_remStepMBy32$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80MToCommonNaN$(OBJ) \ s_commonNaNToExtF80M$(OBJ) \ s_propagateNaNExtF80M$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128MToCommonNaN$(OBJ) \ s_commonNaNToF128M$(OBJ) \ s_propagateNaNF128M$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackMToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackMToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ s_compareNonnormExtF80M$(OBJ) \ s_isNaNF128M$(OBJ) \ s_tryPropagateNaNF128M$(OBJ) \ s_invalidF128M$(OBJ) \ s_shiftNormSigF128M$(OBJ) \ s_roundPackMToF128M$(OBJ) \ s_normRoundPackMToF128M$(OBJ) \ s_addF128M$(OBJ) \ s_mulAddF128M$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-GCC/platform.h000066400000000000000000000042621464416617300275050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define INLINE extern inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/000077500000000000000000000000001464416617300262165ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/Makefile000066400000000000000000000172531464416617300276660ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic # Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR = ../../source SPECIALIZE_TYPE = 8086-SSE SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = rm -f C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include COMPILE_C = \ gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ $(C_INCLUDES) -O2 -o $@ MAKELIB = ar crs $@ OBJ = .o LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_compare96M$(OBJ) \ s_compare128M$(OBJ) \ s_shortShiftLeft64To96M$(OBJ) \ s_shortShiftLeftM$(OBJ) \ s_shiftLeftM$(OBJ) \ s_shortShiftRightM$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJamM$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJamM$(OBJ) \ s_shiftRightM$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_addM$(OBJ) \ s_addCarryM$(OBJ) \ s_addComplCarryM$(OBJ) \ s_negXM$(OBJ) \ s_sub1XM$(OBJ) \ s_subM$(OBJ) \ s_mul64To128M$(OBJ) \ s_mul128MTo256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ s_remStepMBy32$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80MToCommonNaN$(OBJ) \ s_commonNaNToExtF80M$(OBJ) \ s_propagateNaNExtF80M$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128MToCommonNaN$(OBJ) \ s_commonNaNToF128M$(OBJ) \ s_propagateNaNF128M$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackMToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackMToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ s_compareNonnormExtF80M$(OBJ) \ s_isNaNF128M$(OBJ) \ s_tryPropagateNaNF128M$(OBJ) \ s_invalidF128M$(OBJ) \ s_shiftNormSigF128M$(OBJ) \ s_roundPackMToF128M$(OBJ) \ s_normRoundPackMToF128M$(OBJ) \ s_addF128M$(OBJ) \ s_mulAddF128M$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-386-SSE2-GCC/platform.h000066400000000000000000000042621464416617300302170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define INLINE extern inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/000077500000000000000000000000001464416617300261225ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/Makefile000066400000000000000000000222411464416617300275630ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic # Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR = ../../source SPECIALIZE_TYPE = 8086-SSE SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = rm -f C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include COMPILE_C = \ gcc -c -Werror-implicit-function-declaration -DSOFTFLOAT_FAST_INT64 \ $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ MAKELIB = ar crs $@ OBJ = .o LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_eq128$(OBJ) \ s_le128$(OBJ) \ s_lt128$(OBJ) \ s_shortShiftLeft128$(OBJ) \ s_shortShiftRight128$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJam64Extra$(OBJ) \ s_shortShiftRightJam128$(OBJ) \ s_shortShiftRightJam128Extra$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJam64Extra$(OBJ) \ s_shiftRightJam128$(OBJ) \ s_shiftRightJam128Extra$(OBJ) \ s_shiftRightJam256M$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_add128$(OBJ) \ s_add256M$(OBJ) \ s_sub128$(OBJ) \ s_sub256M$(OBJ) \ s_mul64ByShifted32To128$(OBJ) \ s_mul64To128$(OBJ) \ s_mul128By32$(OBJ) \ s_mul128To256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80UIToCommonNaN$(OBJ) \ s_commonNaNToExtF80UI$(OBJ) \ s_propagateNaNExtF80UI$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128UIToCommonNaN$(OBJ) \ s_commonNaNToF128UI$(OBJ) \ s_propagateNaNF128UI$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ s_subMagsExtF80$(OBJ) \ s_normSubnormalF128Sig$(OBJ) \ s_roundPackToF128$(OBJ) \ s_normRoundPackToF128$(OBJ) \ s_addMagsF128$(OBJ) \ s_subMagsF128$(OBJ) \ s_mulAddF128$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80_to_ui32$(OBJ) \ extF80_to_ui64$(OBJ) \ extF80_to_i32$(OBJ) \ extF80_to_i64$(OBJ) \ extF80_to_ui32_r_minMag$(OBJ) \ extF80_to_ui64_r_minMag$(OBJ) \ extF80_to_i32_r_minMag$(OBJ) \ extF80_to_i64_r_minMag$(OBJ) \ extF80_to_f32$(OBJ) \ extF80_to_f64$(OBJ) \ extF80_to_f128$(OBJ) \ extF80_roundToInt$(OBJ) \ extF80_add$(OBJ) \ extF80_sub$(OBJ) \ extF80_mul$(OBJ) \ extF80_div$(OBJ) \ extF80_rem$(OBJ) \ extF80_sqrt$(OBJ) \ extF80_eq$(OBJ) \ extF80_le$(OBJ) \ extF80_lt$(OBJ) \ extF80_eq_signaling$(OBJ) \ extF80_le_quiet$(OBJ) \ extF80_lt_quiet$(OBJ) \ extF80_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128_to_ui32$(OBJ) \ f128_to_ui64$(OBJ) \ f128_to_i32$(OBJ) \ f128_to_i64$(OBJ) \ f128_to_ui32_r_minMag$(OBJ) \ f128_to_ui64_r_minMag$(OBJ) \ f128_to_i32_r_minMag$(OBJ) \ f128_to_i64_r_minMag$(OBJ) \ f128_to_f32$(OBJ) \ f128_to_extF80$(OBJ) \ f128_to_f64$(OBJ) \ f128_roundToInt$(OBJ) \ f128_add$(OBJ) \ f128_sub$(OBJ) \ f128_mul$(OBJ) \ f128_mulAdd$(OBJ) \ f128_div$(OBJ) \ f128_rem$(OBJ) \ f128_sqrt$(OBJ) \ f128_eq$(OBJ) \ f128_le$(OBJ) \ f128_lt$(OBJ) \ f128_eq_signaling$(OBJ) \ f128_le_quiet$(OBJ) \ f128_lt_quiet$(OBJ) \ f128_isSignalingNaN$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Linux-x86_64-GCC/platform.h000066400000000000000000000042621464416617300301230ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define INLINE extern inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/000077500000000000000000000000001464416617300253565ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/Makefile000066400000000000000000000172471464416617300270310ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic # Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR = ../../source SPECIALIZE_TYPE = 8086 SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = rm -f C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include COMPILE_C = \ gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ $(C_INCLUDES) -O2 -o $@ MAKELIB = ar crs $@ OBJ = .o LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_compare96M$(OBJ) \ s_compare128M$(OBJ) \ s_shortShiftLeft64To96M$(OBJ) \ s_shortShiftLeftM$(OBJ) \ s_shiftLeftM$(OBJ) \ s_shortShiftRightM$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJamM$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJamM$(OBJ) \ s_shiftRightM$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_addM$(OBJ) \ s_addCarryM$(OBJ) \ s_addComplCarryM$(OBJ) \ s_negXM$(OBJ) \ s_sub1XM$(OBJ) \ s_subM$(OBJ) \ s_mul64To128M$(OBJ) \ s_mul128MTo256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ s_remStepMBy32$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80MToCommonNaN$(OBJ) \ s_commonNaNToExtF80M$(OBJ) \ s_propagateNaNExtF80M$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128MToCommonNaN$(OBJ) \ s_commonNaNToF128M$(OBJ) \ s_propagateNaNF128M$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackMToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackMToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ s_compareNonnormExtF80M$(OBJ) \ s_isNaNF128M$(OBJ) \ s_tryPropagateNaNF128M$(OBJ) \ s_invalidF128M$(OBJ) \ s_shiftNormSigF128M$(OBJ) \ s_roundPackMToF128M$(OBJ) \ s_normRoundPackMToF128M$(OBJ) \ s_addF128M$(OBJ) \ s_mulAddF128M$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win32-MinGW/platform.h000066400000000000000000000042621464416617300273570ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define INLINE extern inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/000077500000000000000000000000001464416617300260705ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/Makefile000066400000000000000000000172531464416617300275400ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic # Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR = ../../source SPECIALIZE_TYPE = 8086-SSE SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = rm -f C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include COMPILE_C = \ gcc -c -Werror-implicit-function-declaration $(SOFTFLOAT_OPTS) \ $(C_INCLUDES) -O2 -o $@ MAKELIB = ar crs $@ OBJ = .o LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_compare96M$(OBJ) \ s_compare128M$(OBJ) \ s_shortShiftLeft64To96M$(OBJ) \ s_shortShiftLeftM$(OBJ) \ s_shiftLeftM$(OBJ) \ s_shortShiftRightM$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJamM$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJamM$(OBJ) \ s_shiftRightM$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_addM$(OBJ) \ s_addCarryM$(OBJ) \ s_addComplCarryM$(OBJ) \ s_negXM$(OBJ) \ s_sub1XM$(OBJ) \ s_subM$(OBJ) \ s_mul64To128M$(OBJ) \ s_mul128MTo256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ s_remStepMBy32$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80MToCommonNaN$(OBJ) \ s_commonNaNToExtF80M$(OBJ) \ s_propagateNaNExtF80M$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128MToCommonNaN$(OBJ) \ s_commonNaNToF128M$(OBJ) \ s_propagateNaNF128M$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackMToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackMToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ s_compareNonnormExtF80M$(OBJ) \ s_isNaNF128M$(OBJ) \ s_tryPropagateNaNF128M$(OBJ) \ s_invalidF128M$(OBJ) \ s_shiftNormSigF128M$(OBJ) \ s_roundPackMToF128M$(OBJ) \ s_normRoundPackMToF128M$(OBJ) \ s_addF128M$(OBJ) \ s_mulAddF128M$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win32-SSE2-MinGW/platform.h000066400000000000000000000042621464416617300300710ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define INLINE extern inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/000077500000000000000000000000001464416617300260015ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/Makefile000066400000000000000000000223071464416617300274450ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile is part of the SoftFloat IEEE Floating-Point Arithmetic # Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= SOURCE_DIR = ../../source SPECIALIZE_TYPE = 8086-SSE SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 DELETE = rm -f C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include COMPILE_C = \ x86_64-w64-mingw32-gcc -c -Werror-implicit-function-declaration \ -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ MAKELIB = x86_64-w64-mingw32-ar crs $@ OBJ = .o LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_eq128$(OBJ) \ s_le128$(OBJ) \ s_lt128$(OBJ) \ s_shortShiftLeft128$(OBJ) \ s_shortShiftRight128$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJam64Extra$(OBJ) \ s_shortShiftRightJam128$(OBJ) \ s_shortShiftRightJam128Extra$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJam64Extra$(OBJ) \ s_shiftRightJam128$(OBJ) \ s_shiftRightJam128Extra$(OBJ) \ s_shiftRightJam256M$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_add128$(OBJ) \ s_add256M$(OBJ) \ s_sub128$(OBJ) \ s_sub256M$(OBJ) \ s_mul64ByShifted32To128$(OBJ) \ s_mul64To128$(OBJ) \ s_mul128By32$(OBJ) \ s_mul128To256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80UIToCommonNaN$(OBJ) \ s_commonNaNToExtF80UI$(OBJ) \ s_propagateNaNExtF80UI$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128UIToCommonNaN$(OBJ) \ s_commonNaNToF128UI$(OBJ) \ s_propagateNaNF128UI$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ s_subMagsExtF80$(OBJ) \ s_normSubnormalF128Sig$(OBJ) \ s_roundPackToF128$(OBJ) \ s_normRoundPackToF128$(OBJ) \ s_addMagsF128$(OBJ) \ s_subMagsF128$(OBJ) \ s_mulAddF128$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80_to_ui32$(OBJ) \ extF80_to_ui64$(OBJ) \ extF80_to_i32$(OBJ) \ extF80_to_i64$(OBJ) \ extF80_to_ui32_r_minMag$(OBJ) \ extF80_to_ui64_r_minMag$(OBJ) \ extF80_to_i32_r_minMag$(OBJ) \ extF80_to_i64_r_minMag$(OBJ) \ extF80_to_f32$(OBJ) \ extF80_to_f64$(OBJ) \ extF80_to_f128$(OBJ) \ extF80_roundToInt$(OBJ) \ extF80_add$(OBJ) \ extF80_sub$(OBJ) \ extF80_mul$(OBJ) \ extF80_div$(OBJ) \ extF80_rem$(OBJ) \ extF80_sqrt$(OBJ) \ extF80_eq$(OBJ) \ extF80_le$(OBJ) \ extF80_lt$(OBJ) \ extF80_eq_signaling$(OBJ) \ extF80_le_quiet$(OBJ) \ extF80_lt_quiet$(OBJ) \ extF80_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128_to_ui32$(OBJ) \ f128_to_ui64$(OBJ) \ f128_to_i32$(OBJ) \ f128_to_i64$(OBJ) \ f128_to_ui32_r_minMag$(OBJ) \ f128_to_ui64_r_minMag$(OBJ) \ f128_to_i32_r_minMag$(OBJ) \ f128_to_i64_r_minMag$(OBJ) \ f128_to_f32$(OBJ) \ f128_to_extF80$(OBJ) \ f128_to_f64$(OBJ) \ f128_roundToInt$(OBJ) \ f128_add$(OBJ) \ f128_sub$(OBJ) \ f128_mul$(OBJ) \ f128_mulAdd$(OBJ) \ f128_div$(OBJ) \ f128_rem$(OBJ) \ f128_sqrt$(OBJ) \ f128_eq$(OBJ) \ f128_le$(OBJ) \ f128_lt$(OBJ) \ f128_eq_signaling$(OBJ) \ f128_le_quiet$(OBJ) \ f128_lt_quiet$(OBJ) \ f128_isSignalingNaN$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/Win64-MinGW-w64/platform.h000066400000000000000000000042621464416617300300020ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define INLINE extern inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/000077500000000000000000000000001464416617300267275ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/Makefile000066400000000000000000000223401464416617300303700ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile template is part of the SoftFloat IEEE Floating-Point # Arithmetic Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= # Edit lines marked with `==>'. See "SoftFloat-source.html". ==> SOURCE_DIR = ../../source ==> SPECIALIZE_TYPE = 8086 ==> SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 ==> DELETE = rm -f ==> C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include ==> COMPILE_C = \ ==> cc -c -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ ==> MAKELIB = ar crs $@ ==> OBJ = .o ==> LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_eq128$(OBJ) \ s_le128$(OBJ) \ s_lt128$(OBJ) \ s_shortShiftLeft128$(OBJ) \ s_shortShiftRight128$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJam64Extra$(OBJ) \ s_shortShiftRightJam128$(OBJ) \ s_shortShiftRightJam128Extra$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJam64Extra$(OBJ) \ s_shiftRightJam128$(OBJ) \ s_shiftRightJam128Extra$(OBJ) \ s_shiftRightJam256M$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_add128$(OBJ) \ s_add256M$(OBJ) \ s_sub128$(OBJ) \ s_sub256M$(OBJ) \ s_mul64ByShifted32To128$(OBJ) \ s_mul64To128$(OBJ) \ s_mul128By32$(OBJ) \ s_mul128To256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80UIToCommonNaN$(OBJ) \ s_commonNaNToExtF80UI$(OBJ) \ s_propagateNaNExtF80UI$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128UIToCommonNaN$(OBJ) \ s_commonNaNToF128UI$(OBJ) \ s_propagateNaNF128UI$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_normSubnormalExtF80Sig$(OBJ) \ s_roundPackToExtF80$(OBJ) \ s_normRoundPackToExtF80$(OBJ) \ s_addMagsExtF80$(OBJ) \ s_subMagsExtF80$(OBJ) \ s_normSubnormalF128Sig$(OBJ) \ s_roundPackToF128$(OBJ) \ s_normRoundPackToF128$(OBJ) \ s_addMagsF128$(OBJ) \ s_subMagsF128$(OBJ) \ s_mulAddF128$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80_to_ui32$(OBJ) \ extF80_to_ui64$(OBJ) \ extF80_to_i32$(OBJ) \ extF80_to_i64$(OBJ) \ extF80_to_ui32_r_minMag$(OBJ) \ extF80_to_ui64_r_minMag$(OBJ) \ extF80_to_i32_r_minMag$(OBJ) \ extF80_to_i64_r_minMag$(OBJ) \ extF80_to_f32$(OBJ) \ extF80_to_f64$(OBJ) \ extF80_to_f128$(OBJ) \ extF80_roundToInt$(OBJ) \ extF80_add$(OBJ) \ extF80_sub$(OBJ) \ extF80_mul$(OBJ) \ extF80_div$(OBJ) \ extF80_rem$(OBJ) \ extF80_sqrt$(OBJ) \ extF80_eq$(OBJ) \ extF80_le$(OBJ) \ extF80_lt$(OBJ) \ extF80_eq_signaling$(OBJ) \ extF80_le_quiet$(OBJ) \ extF80_lt_quiet$(OBJ) \ extF80_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128_to_ui32$(OBJ) \ f128_to_ui64$(OBJ) \ f128_to_i32$(OBJ) \ f128_to_i64$(OBJ) \ f128_to_ui32_r_minMag$(OBJ) \ f128_to_ui64_r_minMag$(OBJ) \ f128_to_i32_r_minMag$(OBJ) \ f128_to_i64_r_minMag$(OBJ) \ f128_to_f32$(OBJ) \ f128_to_extF80$(OBJ) \ f128_to_f64$(OBJ) \ f128_roundToInt$(OBJ) \ f128_add$(OBJ) \ f128_sub$(OBJ) \ f128_mul$(OBJ) \ f128_mulAdd$(OBJ) \ f128_div$(OBJ) \ f128_rem$(OBJ) \ f128_sqrt$(OBJ) \ f128_eq$(OBJ) \ f128_le$(OBJ) \ f128_lt$(OBJ) \ f128_eq_signaling$(OBJ) \ f128_le_quiet$(OBJ) \ f128_lt_quiet$(OBJ) \ f128_isSignalingNaN$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/template-FAST_INT64/platform.h000066400000000000000000000043671464416617300307360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header template is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ // Edit lines marked with `==>'. See "SoftFloat-source.html". /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ ==> #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ ==> #define INLINE inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/000077500000000000000000000000001464416617300275255ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/Makefile000066400000000000000000000173421464416617300311740ustar00rootroot00000000000000# SPDX-License-Identifier: BSD-3-Clause #============================================================================= # # This Makefile template is part of the SoftFloat IEEE Floating-Point # Arithmetic Package, Release 3a, by John R. Hauser. # # Copyright 2011, 2012, 2013, 2014 The Regents of the University of # California. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #============================================================================= # Edit lines marked with `==>'. See "SoftFloat-source.html". ==> SOURCE_DIR = ../../source ==> SPECIALIZE_TYPE = 8086 ==> SOFTFLOAT_OPTS = -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV64TO32 ==> DELETE = rm -f ==> C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include ==> COMPILE_C = cc -c $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@ ==> MAKELIB = ar crs $@ ==> OBJ = .o ==> LIB = .a .PHONY: all all: softfloat$(LIB) OBJS_PRIMITIVES = \ s_compare96M$(OBJ) \ s_compare128M$(OBJ) \ s_shortShiftLeft64To96M$(OBJ) \ s_shortShiftLeftM$(OBJ) \ s_shiftLeftM$(OBJ) \ s_shortShiftRightM$(OBJ) \ s_shortShiftRightJam64$(OBJ) \ s_shortShiftRightJamM$(OBJ) \ s_shiftRightJam32$(OBJ) \ s_shiftRightJam64$(OBJ) \ s_shiftRightJamM$(OBJ) \ s_shiftRightM$(OBJ) \ s_countLeadingZeros8$(OBJ) \ s_countLeadingZeros32$(OBJ) \ s_countLeadingZeros64$(OBJ) \ s_addM$(OBJ) \ s_addCarryM$(OBJ) \ s_addComplCarryM$(OBJ) \ s_negXM$(OBJ) \ s_sub1XM$(OBJ) \ s_subM$(OBJ) \ s_mul64To128M$(OBJ) \ s_mul128MTo256M$(OBJ) \ s_approxRecip32_1$(OBJ) \ s_approxRecipSqrt32_1$(OBJ) \ s_remStepMBy32$(OBJ) \ OBJS_SPECIALIZE = \ softfloat_raiseFlags$(OBJ) \ s_f32UIToCommonNaN$(OBJ) \ s_commonNaNToF32UI$(OBJ) \ s_propagateNaNF32UI$(OBJ) \ s_f64UIToCommonNaN$(OBJ) \ s_commonNaNToF64UI$(OBJ) \ s_propagateNaNF64UI$(OBJ) \ extF80M_isSignalingNaN$(OBJ) \ s_extF80MToCommonNaN$(OBJ) \ s_commonNaNToExtF80M$(OBJ) \ s_propagateNaNExtF80M$(OBJ) \ f128M_isSignalingNaN$(OBJ) \ s_f128MToCommonNaN$(OBJ) \ s_commonNaNToF128M$(OBJ) \ s_propagateNaNF128M$(OBJ) \ OBJS_OTHERS = \ s_roundPackToUI32$(OBJ) \ s_roundPackMToUI64$(OBJ) \ s_roundPackToI32$(OBJ) \ s_roundPackMToI64$(OBJ) \ s_normSubnormalF32Sig$(OBJ) \ s_roundPackToF32$(OBJ) \ s_normRoundPackToF32$(OBJ) \ s_addMagsF32$(OBJ) \ s_subMagsF32$(OBJ) \ s_mulAddF32$(OBJ) \ s_normSubnormalF64Sig$(OBJ) \ s_roundPackToF64$(OBJ) \ s_normRoundPackToF64$(OBJ) \ s_addMagsF64$(OBJ) \ s_subMagsF64$(OBJ) \ s_mulAddF64$(OBJ) \ s_tryPropagateNaNExtF80M$(OBJ) \ s_invalidExtF80M$(OBJ) \ s_normExtF80SigM$(OBJ) \ s_roundPackMToExtF80M$(OBJ) \ s_normRoundPackMToExtF80M$(OBJ) \ s_addExtF80M$(OBJ) \ s_compareNonnormExtF80M$(OBJ) \ s_isNaNF128M$(OBJ) \ s_tryPropagateNaNF128M$(OBJ) \ s_invalidF128M$(OBJ) \ s_shiftNormSigF128M$(OBJ) \ s_roundPackMToF128M$(OBJ) \ s_normRoundPackMToF128M$(OBJ) \ s_addF128M$(OBJ) \ s_mulAddF128M$(OBJ) \ softfloat_state$(OBJ) \ ui32_to_f32$(OBJ) \ ui32_to_f64$(OBJ) \ ui32_to_extF80M$(OBJ) \ ui32_to_f128M$(OBJ) \ ui64_to_f32$(OBJ) \ ui64_to_f64$(OBJ) \ ui64_to_extF80M$(OBJ) \ ui64_to_f128M$(OBJ) \ i32_to_f32$(OBJ) \ i32_to_f64$(OBJ) \ i32_to_extF80M$(OBJ) \ i32_to_f128M$(OBJ) \ i64_to_f32$(OBJ) \ i64_to_f64$(OBJ) \ i64_to_extF80M$(OBJ) \ i64_to_f128M$(OBJ) \ f32_to_ui32$(OBJ) \ f32_to_ui64$(OBJ) \ f32_to_i32$(OBJ) \ f32_to_i64$(OBJ) \ f32_to_ui32_r_minMag$(OBJ) \ f32_to_ui64_r_minMag$(OBJ) \ f32_to_i32_r_minMag$(OBJ) \ f32_to_i64_r_minMag$(OBJ) \ f32_to_f64$(OBJ) \ f32_to_extF80M$(OBJ) \ f32_to_f128M$(OBJ) \ f32_roundToInt$(OBJ) \ f32_add$(OBJ) \ f32_sub$(OBJ) \ f32_mul$(OBJ) \ f32_mulAdd$(OBJ) \ f32_div$(OBJ) \ f32_rem$(OBJ) \ f32_sqrt$(OBJ) \ f32_eq$(OBJ) \ f32_le$(OBJ) \ f32_lt$(OBJ) \ f32_eq_signaling$(OBJ) \ f32_le_quiet$(OBJ) \ f32_lt_quiet$(OBJ) \ f32_isSignalingNaN$(OBJ) \ f64_to_ui32$(OBJ) \ f64_to_ui64$(OBJ) \ f64_to_i32$(OBJ) \ f64_to_i64$(OBJ) \ f64_to_ui32_r_minMag$(OBJ) \ f64_to_ui64_r_minMag$(OBJ) \ f64_to_i32_r_minMag$(OBJ) \ f64_to_i64_r_minMag$(OBJ) \ f64_to_f32$(OBJ) \ f64_to_extF80M$(OBJ) \ f64_to_f128M$(OBJ) \ f64_roundToInt$(OBJ) \ f64_add$(OBJ) \ f64_sub$(OBJ) \ f64_mul$(OBJ) \ f64_mulAdd$(OBJ) \ f64_div$(OBJ) \ f64_rem$(OBJ) \ f64_sqrt$(OBJ) \ f64_eq$(OBJ) \ f64_le$(OBJ) \ f64_lt$(OBJ) \ f64_eq_signaling$(OBJ) \ f64_le_quiet$(OBJ) \ f64_lt_quiet$(OBJ) \ f64_isSignalingNaN$(OBJ) \ extF80M_to_ui32$(OBJ) \ extF80M_to_ui64$(OBJ) \ extF80M_to_i32$(OBJ) \ extF80M_to_i64$(OBJ) \ extF80M_to_ui32_r_minMag$(OBJ) \ extF80M_to_ui64_r_minMag$(OBJ) \ extF80M_to_i32_r_minMag$(OBJ) \ extF80M_to_i64_r_minMag$(OBJ) \ extF80M_to_f32$(OBJ) \ extF80M_to_f64$(OBJ) \ extF80M_to_f128M$(OBJ) \ extF80M_roundToInt$(OBJ) \ extF80M_add$(OBJ) \ extF80M_sub$(OBJ) \ extF80M_mul$(OBJ) \ extF80M_div$(OBJ) \ extF80M_rem$(OBJ) \ extF80M_sqrt$(OBJ) \ extF80M_eq$(OBJ) \ extF80M_le$(OBJ) \ extF80M_lt$(OBJ) \ extF80M_eq_signaling$(OBJ) \ extF80M_le_quiet$(OBJ) \ extF80M_lt_quiet$(OBJ) \ f128M_to_ui32$(OBJ) \ f128M_to_ui64$(OBJ) \ f128M_to_i32$(OBJ) \ f128M_to_i64$(OBJ) \ f128M_to_ui32_r_minMag$(OBJ) \ f128M_to_ui64_r_minMag$(OBJ) \ f128M_to_i32_r_minMag$(OBJ) \ f128M_to_i64_r_minMag$(OBJ) \ f128M_to_f32$(OBJ) \ f128M_to_f64$(OBJ) \ f128M_to_extF80M$(OBJ) \ f128M_roundToInt$(OBJ) \ f128M_add$(OBJ) \ f128M_sub$(OBJ) \ f128M_mul$(OBJ) \ f128M_mulAdd$(OBJ) \ f128M_div$(OBJ) \ f128M_rem$(OBJ) \ f128M_sqrt$(OBJ) \ f128M_eq$(OBJ) \ f128M_le$(OBJ) \ f128M_lt$(OBJ) \ f128M_eq_signaling$(OBJ) \ f128M_le_quiet$(OBJ) \ f128M_lt_quiet$(OBJ) \ OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS) $(OBJS_ALL): \ platform.h $(SOURCE_DIR)/include/primitiveTypes.h \ $(SOURCE_DIR)/include/primitives.h $(OBJS_SPECIALIZE) $(OBJS_OTHERS): \ $(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \ $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \ $(SOURCE_DIR)/include/softfloat.h $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c $(COMPILE_C) $(SOURCE_DIR)/$*.c $(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c $(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c softfloat$(LIB): $(OBJS_ALL) $(DELETE) $@ $(MAKELIB) $^ .PHONY: clean clean: $(DELETE) $(OBJS_ALL) softfloat$(LIB) optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/build/template-not-FAST_INT64/platform.h000066400000000000000000000043671464416617300315340ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header template is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ // Edit lines marked with `==>'. See "SoftFloat-source.html". /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ ==> #define LITTLEENDIAN 1 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ ==> #define INLINE inline optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/doc/000077500000000000000000000000001464416617300231435ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-history.html000066400000000000000000000064031464416617300274340ustar00rootroot00000000000000 Berkeley SoftFloat History

History of Berkeley SoftFloat, to Release 3a

John R. Hauser
2015 October 23

Release 3a (2015 October)

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

Release 3 (2015 February)

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

Release 2c (2015 January)

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

Release 2b (2002 May)

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

Release 2a (1998 December)

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

Release 2 (1997 June)

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

Release 1a (1996 July)

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

Release 1 (1996 July)

  • Original release, based on work done for the International Computer Science Institute (ICSI) in Berkeley, California.
optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat-source.html000066400000000000000000000517501464416617300272400ustar00rootroot00000000000000 Berkeley SoftFloat Source Documentation

Berkeley SoftFloat Release 3a: Source Documentation

John R. Hauser
2015 October 23

Contents

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

1. Introduction

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

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

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

2. Limitations

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

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

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

3. Acknowledgments and License

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

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

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

Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution.

  3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

4. SoftFloat Package Directory Structure

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

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

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

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

As supplied, each target directory contains two files:

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

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

5. Issues for Porting SoftFloat to a New Target

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

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

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

5.2. Specializing Floating-Point Behavior

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

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

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

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

5.3. Macros for Build Options

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

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

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

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

5.4. Adapting a Template Target Directory

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

5.5. Target-Specific Optimization of Primitive Functions

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

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

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

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

6. Testing SoftFloat

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

7. Providing SoftFloat as a Common Library for Applications

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

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

8. Contact Information

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

optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/doc/SoftFloat.html000066400000000000000000001432631464416617300257430ustar00rootroot00000000000000 Berkeley SoftFloat Library Interface

Berkeley SoftFloat Release 3a: Library Interface

John R. Hauser
2015 October 23

Contents

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

1. Introduction

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

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

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

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

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

2. Limitations

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

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

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

3. Acknowledgments and License

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

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

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

Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution.

  3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

4. Types and Functions

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

4.1. Boolean and Integer Types

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

uint16_t
uint32_t
uint64_t
int32_t
int64_t
uint_fast8_t
uint_fast32_t
uint_fast64_t

4.2. Floating-Point Types

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

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

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

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

4.3. Supported Floating-Point Functions

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

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

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

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

4.4. Non-canonical Representations in extFloat80_t

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

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

4.5. Conventions for Passing Arguments and Results

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

float64_t f64_add( float64_t, float64_t );

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

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

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

float128_t f128_add( float128_t, float128_t );

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

5. Reserved Names

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

6. Mode Variables

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

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

6.1. Rounding Mode

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

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

6.2. Underflow Detection

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

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

6.3. Rounding Precision for the 80-Bit Extended Format

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

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

7. Exceptions and Exception Flags

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

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

An individual exception flag can be cleared with the statement

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

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

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

8. Function Details

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

f32 indicates float32_t, passed by value
f64 indicates float64_t, passed by value
extF80M    indicates extFloat80_t, passed indirectly via pointers
extF80 indicates extFloat80_t, passed by value
f128M indicates float128_t, passed indirectly via pointers
f128 indicates float128_t, passed by value
The circumstances under which values of floating-point types extFloat80_t and float128_t may be passed either by value or indirectly via pointers was discussed earlier in section 4.5, Conventions for Passing Arguments and Results.

8.1. Conversions from Integer to Floating-Point

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

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

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

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

8.2. Conversions from Floating-Point to Integer

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

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

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

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

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

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

8.3. Conversions Among Floating-Point Types

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

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

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

8.4. Basic Arithmetic Functions

The following basic arithmetic functions are provided:

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

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

8.5. Fused Multiply-Add Functions

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

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

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

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

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

8.6. Remainder Functions

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

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

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

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

8.7. Round-to-Integer Functions

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

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

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

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

8.8. Comparison Functions

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

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

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

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

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

8.9. Signaling NaN Test Functions

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

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

8.10. Raise-Exception Function

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

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

9. Changes from SoftFloat Release 2

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

9.1. Name Changes

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

old name, Release 2: new name, Release 3:
float32 float32_t
float64 float64_t
floatx80 extFloat80_t
float128 float128_t
float_rounding_mode softfloat_roundingMode
float_round_nearest_even softfloat_round_near_even
float_round_to_zero softfloat_round_minMag
float_round_down softfloat_round_min
float_round_up softfloat_round_max
float_detect_tininess softfloat_detectTininess
float_tininess_before_rounding     softfloat_tininess_beforeRounding
float_tininess_after_rounding softfloat_tininess_afterRounding
floatx80_rounding_precision extF80_roundingPrecision
float_exception_flags softfloat_exceptionFlags
float_flag_inexact softfloat_flag_inexact
float_flag_underflow softfloat_flag_underflow
float_flag_overflow softfloat_flag_overflow
float_flag_divbyzero softfloat_flag_infinite
float_flag_invalid softfloat_flag_invalid
float_raise softfloat_raise

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

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

9.2. Changes to Function Arguments

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

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

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

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

9.3. Added Capabilities

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

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

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

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

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

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

9.4. Better Compatibility with the C Language

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

9.5. New Organization as a Library

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

9.6. Optimization Gains (and Losses)

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

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

10. Future Directions

The following improvements are anticipated for future releases of SoftFloat:

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

11. Contact Information

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

optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/000077500000000000000000000000001464416617300236765ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/000077500000000000000000000000001464416617300247335ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/extF80M_isSignalingNaN.c000066400000000000000000000046421464416617300312240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "softfloat.h" /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool extF80M_isSignalingNaN( const extFloat80_t *aPtr ) { const struct extFloat80M *aSPtr; uint64_t uiA0; aSPtr = (const struct extFloat80M *) aPtr; if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false; uiA0 = aSPtr->signif; return ! (uiA0 & UINT64_C( 0x4000000000000000 )) && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/f128M_isSignalingNaN.c000066400000000000000000000047711464416617300306310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "primitives.h" #include "softfloat.h" /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool f128M_isSignalingNaN( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false; return ((uiA96 & 0x00007FFF) != 0) || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80M.c000066400000000000000000000046701464416617300306740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | `zSPtr'. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToExtF80M( const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) { zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF ); zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToExtF80UI.c000066400000000000000000000047051464416617300310140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) { struct uint128 uiZ; uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF; uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128M.c000066400000000000000000000051221464416617300302670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument | `zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ) { softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr ); zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF128UI.c000066400000000000000000000047301464416617300304140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) { struct uint128 uiZ; uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 ); uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 ); return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF32UI.c000066400000000000000000000045121464416617300303240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ) { return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_commonNaNToF64UI.c000066400000000000000000000045621464416617300303360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ) { return (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 ) | aPtr->v64>>12; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80MToCommonNaN.c000066400000000000000000000052561464416617300306750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is | a NaN, converts this NaN to the common NaN form, and stores the resulting | common NaN at the location pointed to by `zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80MToCommonNaN( const struct extFloat80M *aSPtr, struct commonNaN *zPtr ) { if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = signExtF80UI64( aSPtr->signExp ); zPtr->v64 = aSPtr->signif<<1; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_extF80UIToCommonNaN.c000066400000000000000000000052561464416617300310160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of an 80-bit extended floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80UIToCommonNaN( uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = uiA64>>15; zPtr->v64 = uiA0<<1; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128MToCommonNaN.c000066400000000000000000000054771464416617300303040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, | converts this NaN to the common NaN form, and stores the resulting common | NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, | the invalid exception is raised. Argument `aWPtr' points to an array of | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ) { if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = aWPtr[indexWordHi( 4 )]>>31; softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f128UIToCommonNaN.c000066400000000000000000000054341464416617300304160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of a 128-bit floating-point NaN, converts this NaN to | the common NaN form, and stores the resulting common NaN at the location | pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ void softfloat_f128UIToCommonNaN( uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) { struct uint128 NaNSig; if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 ); zPtr->sign = uiA64>>63; zPtr->v64 = NaNSig.v64; zPtr->v0 = NaNSig.v0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f32UIToCommonNaN.c000066400000000000000000000051121464416617300303210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ) { if ( softfloat_isSigNaNF32UI( uiA ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = uiA>>31; zPtr->v64 = (uint_fast64_t) uiA<<41; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_f64UIToCommonNaN.c000066400000000000000000000050721464416617300303330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ) { if ( softfloat_isSigNaNF64UI( uiA ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = uiA>>63; zPtr->v64 = uiA<<12; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80M.c000066400000000000000000000077761464416617300310750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values | pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result | at the location pointed to by `zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr ) { bool isSigNaNA; const struct extFloat80M *sPtr; bool isSigNaNB; uint_fast16_t uiB64; uint64_t uiB0; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiMagA64, uiMagB64; isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ); sPtr = aSPtr; if ( ! bSPtr ) { if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); goto copy; } isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr ); if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { uiB64 = bSPtr->signExp; if ( isSigNaNB ) goto returnLargerUIMag; uiB0 = bSPtr->signif; if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB; goto copy; } else { uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy; goto copyB; } } uiB64 = bSPtr->signExp; returnLargerUIMag: uiA64 = aSPtr->signExp; uiMagA64 = uiA64 & 0x7FFF; uiMagB64 = uiB64 & 0x7FFF; if ( uiMagA64 < uiMagB64 ) goto copyB; if ( uiMagB64 < uiMagA64 ) goto copy; uiA0 = aSPtr->signif; uiB0 = bSPtr->signif; if ( uiA0 < uiB0 ) goto copyB; if ( uiB0 < uiA0 ) goto copy; if ( uiA64 < uiB64 ) goto copy; copyB: sPtr = bSPtr; copy: zSPtr->signExp = sPtr->signExp; zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNExtF80UI.c000066400000000000000000000106211464416617300311750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as an 80-bit extended floating-point value, and likewise interpreting | the unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 80-bit extended floating-point value, and assuming at least on of these | floating-point values is a NaN, returns the bit pattern of the combined NaN | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNExtF80UI( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0 ) { bool isSigNaNA, isSigNaNB; uint_fast64_t uiNonsigA0, uiNonsigB0; uint_fast16_t uiMagA64, uiMagB64; struct uint128 uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 ); isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 ); uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB; goto returnA; } else { if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA; goto returnB; } } returnLargerMag: uiMagA64 = uiA64 & 0x7FFF; uiMagB64 = uiB64 & 0x7FFF; if ( uiMagA64 < uiMagB64 ) goto returnB; if ( uiMagB64 < uiMagA64 ) goto returnA; if ( uiNonsigA0 < uiNonsigB0 ) goto returnB; if ( uiNonsigB0 < uiNonsigA0 ) goto returnA; if ( uiA64 < uiB64 ) goto returnA; returnB: uiZ.v64 = uiB64; uiZ.v0 = uiNonsigB0; return uiZ; returnA: uiZ.v64 = uiA64; uiZ.v0 = uiNonsigA0; return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128M.c000066400000000000000000000064251464416617300304650ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by | `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location | pointed to by `zWPtr'. If either original floating-point value is a | signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', | and `zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) { bool isSigNaNA; const uint32_t *ptr; ptr = aWPtr; isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr ); if ( isSigNaNA || (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr )) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) goto copy; } if ( ! softfloat_isNaNF128M( aWPtr ) ) ptr = bWPtr; copy: zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000; zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )]; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF128UI.c000066400000000000000000000063241464416617300306040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as a 128-bit floating-point value, and likewise interpreting the | unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 128-bit floating-point value, and assuming at least on of these floating- | point values is a NaN, returns the bit pattern of the combined NaN result. | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNF128UI( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0 ) { bool isSigNaNA; struct uint128 uiZ; isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 ); if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) goto returnNonsigA; } if ( isNaNF128UI( uiA64, uiA0 ) ) { returnNonsigA: uiZ.v64 = uiA64; uiZ.v0 = uiA0; } else { uiZ.v64 = uiB64; uiZ.v0 = uiB0; } uiZ.v64 |= UINT64_C( 0x0000800000000000 ); return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF32UI.c000066400000000000000000000053621464416617300305170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) { bool isSigNaNA; isSigNaNA = softfloat_isSigNaNF32UI( uiA ); if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) return uiA | 0x00400000; } return (isNaNF32UI( uiA ) ? uiA : uiB) | 0x00400000; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/s_propagateNaNF64UI.c000066400000000000000000000054321464416617300305220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) { bool isSigNaNA; isSigNaNA = softfloat_isSigNaNF64UI( uiA ); if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) return uiA | UINT64_C( 0x0008000000000000 ); } return (isNaNF64UI( uiA ) ? uiA : uiB) | UINT64_C( 0x0008000000000000 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/softfloat_raiseFlags.c000066400000000000000000000045771464416617300312550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include "platform.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Raises the exceptions specified by `flags'. Floating-point traps can be | defined here if desired. It is currently not possible for such a trap | to substitute a result value. If traps are not implemented, this routine | should be simply `softfloat_exceptionFlags |= flags;'. *----------------------------------------------------------------------------*/ void softfloat_raiseFlags( uint_fast8_t flags ) { softfloat_exceptionFlags |= flags; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/specialize.h000066400000000000000000000403611464416617300272400ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #ifndef specialize_h #define specialize_h 1 #include #include #include "softfloat_types.h" /*---------------------------------------------------------------------------- | Default value for `softfloat_detectTininess'. *----------------------------------------------------------------------------*/ #define init_detectTininess softfloat_tininess_afterRounding /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format | to another. *----------------------------------------------------------------------------*/ struct commonNaN { bool sign; #ifdef LITTLEENDIAN uint64_t v0, v64; #else uint64_t v64, v0; #endif }; /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF32UI 0xFFC00000 /*---------------------------------------------------------------------------- | Returns true when 32-bit unsigned integer `uiA' has the bit pattern of a | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer `uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF #define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating | 16-bit `uiA64' and 64-bit `uiA0' has the bit pattern of an 80-bit extended | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- | The following functions are needed only when `SOFTFLOAT_FAST_INT64' is | defined. *----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of an 80-bit extended floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80UIToCommonNaN( uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as an 80-bit extended floating-point value, and likewise interpreting | the unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 80-bit extended floating-point value, and assuming at least on of these | floating-point values is a NaN, returns the bit pattern of the combined NaN | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNExtF80UI( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0 ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) #define defaultNaNF128UI0 UINT64_C( 0 ) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating | 64-bit `uiA64' and 64-bit `uiA0' has the bit pattern of a 128-bit floating- | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of a 128-bit floating-point NaN, converts this NaN to | the common NaN form, and stores the resulting common NaN at the location | pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ void softfloat_f128UIToCommonNaN( uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as a 128-bit floating-point value, and likewise interpreting the | unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 128-bit floating-point value, and assuming at least on of these floating- | point values is a NaN, returns the bit pattern of the combined NaN result. | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNF128UI( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0 ); #else /*---------------------------------------------------------------------------- | The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not | defined. *----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is | a NaN, converts this NaN to the common NaN form, and stores the resulting | common NaN at the location pointed to by `zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80MToCommonNaN( const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | `zSPtr'. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToExtF80M( const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values | pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result | at the location pointed to by `zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 #define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, | converts this NaN to the common NaN form, and stores the resulting common | NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, | the invalid exception is raised. Argument `aWPtr' points to an array of | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument | `zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by | `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location | pointed to by `zWPtr'. If either original floating-point value is a | signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', | and `zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); #endif #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086-SSE/sub.mk000066400000000000000000000003351464416617300260560ustar00rootroot00000000000000srcs-y += softfloat_raiseFlags.c srcs-y += s_propagateNaNF32UI.c srcs-y += s_f32UIToCommonNaN.c srcs-y += s_commonNaNToF64UI.c srcs-y += s_f64UIToCommonNaN.c srcs-y += s_propagateNaNF64UI.c srcs-y += s_commonNaNToF32UI.c optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/000077500000000000000000000000001464416617300243035ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/extF80M_isSignalingNaN.c000066400000000000000000000046421464416617300305740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "softfloat.h" /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool extF80M_isSignalingNaN( const extFloat80_t *aPtr ) { const struct extFloat80M *aSPtr; uint64_t uiA0; aSPtr = (const struct extFloat80M *) aPtr; if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false; uiA0 = aSPtr->signif; return ! (uiA0 & UINT64_C( 0x4000000000000000 )) && (uiA0 & UINT64_C( 0x3FFFFFFFFFFFFFFF)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/f128M_isSignalingNaN.c000066400000000000000000000047711464416617300302010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "primitives.h" #include "softfloat.h" /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool f128M_isSignalingNaN( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; if ( (uiA96 & 0x7FFF8000) != 0x7FFF0000 ) return false; return ((uiA96 & 0x00007FFF) != 0) || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80M.c000066400000000000000000000046701464416617300302440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | `zSPtr'. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToExtF80M( const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) { zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF ); zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToExtF80UI.c000066400000000000000000000047051464416617300303640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ) { struct uint128 uiZ; uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF; uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1; return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128M.c000066400000000000000000000051221464416617300276370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument | `zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ) { softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr ); zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF128UI.c000066400000000000000000000047301464416617300277640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr ) { struct uint128 uiZ; uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 ); uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 ); return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF32UI.c000066400000000000000000000045121464416617300276740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ) { return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_commonNaNToF64UI.c000066400000000000000000000045621464416617300277060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ) { return (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 ) | aPtr->v64>>12; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80MToCommonNaN.c000066400000000000000000000052561464416617300302450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is | a NaN, converts this NaN to the common NaN form, and stores the resulting | common NaN at the location pointed to by `zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80MToCommonNaN( const struct extFloat80M *aSPtr, struct commonNaN *zPtr ) { if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = signExtF80UI64( aSPtr->signExp ); zPtr->v64 = aSPtr->signif<<1; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_extF80UIToCommonNaN.c000066400000000000000000000052561464416617300303660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of an 80-bit extended floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80UIToCommonNaN( uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = uiA64>>15; zPtr->v64 = uiA0<<1; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128MToCommonNaN.c000066400000000000000000000054771464416617300276540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, | converts this NaN to the common NaN form, and stores the resulting common | NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, | the invalid exception is raised. Argument `aWPtr' points to an array of | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ) { if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = aWPtr[indexWordHi( 4 )]>>31; softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f128UIToCommonNaN.c000066400000000000000000000054341464416617300277660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of a 128-bit floating-point NaN, converts this NaN to | the common NaN form, and stores the resulting common NaN at the location | pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ void softfloat_f128UIToCommonNaN( uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ) { struct uint128 NaNSig; if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 ); zPtr->sign = uiA64>>63; zPtr->v64 = NaNSig.v64; zPtr->v0 = NaNSig.v0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f32UIToCommonNaN.c000066400000000000000000000051121464416617300276710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ) { if ( softfloat_isSigNaNF32UI( uiA ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = uiA>>31; zPtr->v64 = (uint_fast64_t) uiA<<41; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_f64UIToCommonNaN.c000066400000000000000000000050721464416617300277030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ) { if ( softfloat_isSigNaNF64UI( uiA ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } zPtr->sign = uiA>>63; zPtr->v64 = uiA<<12; zPtr->v0 = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80M.c000066400000000000000000000077761464416617300304450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values | pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result | at the location pointed to by `zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr ) { bool isSigNaNA; const struct extFloat80M *sPtr; bool isSigNaNB; uint_fast16_t uiB64; uint64_t uiB0; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiMagA64, uiMagB64; isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ); sPtr = aSPtr; if ( ! bSPtr ) { if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); goto copy; } isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr ); if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { uiB64 = bSPtr->signExp; if ( isSigNaNB ) goto returnLargerUIMag; uiB0 = bSPtr->signif; if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB; goto copy; } else { uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy; goto copyB; } } uiB64 = bSPtr->signExp; returnLargerUIMag: uiA64 = aSPtr->signExp; uiMagA64 = uiA64 & 0x7FFF; uiMagB64 = uiB64 & 0x7FFF; if ( uiMagA64 < uiMagB64 ) goto copyB; if ( uiMagB64 < uiMagA64 ) goto copy; uiA0 = aSPtr->signif; uiB0 = bSPtr->signif; if ( uiA0 < uiB0 ) goto copyB; if ( uiB0 < uiA0 ) goto copy; if ( uiA64 < uiB64 ) goto copy; copyB: sPtr = bSPtr; copy: zSPtr->signExp = sPtr->signExp; zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNExtF80UI.c000066400000000000000000000106211464416617300305450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as an 80-bit extended floating-point value, and likewise interpreting | the unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 80-bit extended floating-point value, and assuming at least on of these | floating-point values is a NaN, returns the bit pattern of the combined NaN | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNExtF80UI( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0 ) { bool isSigNaNA, isSigNaNB; uint_fast64_t uiNonsigA0, uiNonsigB0; uint_fast16_t uiMagA64, uiMagB64; struct uint128 uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 ); isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 ); uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB; goto returnA; } else { if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA; goto returnB; } } returnLargerMag: uiMagA64 = uiA64 & 0x7FFF; uiMagB64 = uiB64 & 0x7FFF; if ( uiMagA64 < uiMagB64 ) goto returnB; if ( uiMagB64 < uiMagA64 ) goto returnA; if ( uiNonsigA0 < uiNonsigB0 ) goto returnB; if ( uiNonsigB0 < uiNonsigA0 ) goto returnA; if ( uiA64 < uiB64 ) goto returnA; returnB: uiZ.v64 = uiB64; uiZ.v0 = uiNonsigB0; return uiZ; returnA: uiZ.v64 = uiA64; uiZ.v0 = uiNonsigA0; return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128M.c000066400000000000000000000106501464416617300300300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by | `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location | pointed to by `zWPtr'. If either original floating-point value is a | signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', | and `zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) { bool isSigNaNA; const uint32_t *ptr; bool isSigNaNB; uint32_t uiA96, uiB96, wordMagA, wordMagB; isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr ); ptr = aWPtr; if ( ! bWPtr ) { if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid ); goto copy; } isSigNaNB = f128M_isSignalingNaN( (const float128_t *) bWPtr ); if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerUIMag; if ( softfloat_isNaNF128M( bWPtr ) ) goto copyB; goto copy; } else { if ( softfloat_isNaNF128M( aWPtr ) ) goto copy; goto copyB; } } returnLargerUIMag: uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; wordMagA = uiA96 & 0x7FFFFFFF; wordMagB = uiB96 & 0x7FFFFFFF; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; wordMagA = aWPtr[indexWord( 4, 2 )]; wordMagB = bWPtr[indexWord( 4, 2 )]; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; wordMagA = aWPtr[indexWord( 4, 1 )]; wordMagB = bWPtr[indexWord( 4, 1 )]; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; wordMagA = aWPtr[indexWord( 4, 0 )]; wordMagB = bWPtr[indexWord( 4, 0 )]; if ( wordMagA < wordMagB ) goto copyB; if ( wordMagB < wordMagA ) goto copy; if ( uiA96 < uiB96 ) goto copy; copyB: ptr = bWPtr; copy: zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000; zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )]; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF128UI.c000066400000000000000000000106321464416617300301510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as a 128-bit floating-point value, and likewise interpreting the | unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 128-bit floating-point value, and assuming at least on of these floating- | point values is a NaN, returns the bit pattern of the combined NaN result. | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNF128UI( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0 ) { bool isSigNaNA, isSigNaNB; uint_fast64_t uiNonsigA64, uiNonsigB64, uiMagA64, uiMagB64; struct uint128 uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 ); isSigNaNB = softfloat_isSigNaNF128UI( uiB64, uiB0 ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA64 = uiA64 | UINT64_C( 0x0000800000000000 ); uiNonsigB64 = uiB64 | UINT64_C( 0x0000800000000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; if ( isNaNF128UI( uiB64, uiB0 ) ) goto returnB; goto returnA; } else { if ( isNaNF128UI( uiA64, uiA0 ) ) goto returnA; goto returnB; } } returnLargerMag: uiMagA64 = uiNonsigA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); uiMagB64 = uiNonsigB64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( uiMagA64 < uiMagB64 ) goto returnB; if ( uiMagB64 < uiMagA64 ) goto returnA; if ( uiA0 < uiB0 ) goto returnB; if ( uiB0 < uiA0 ) goto returnA; if ( uiNonsigA64 < uiNonsigB64 ) goto returnA; returnB: uiZ.v64 = uiNonsigB64; uiZ.v0 = uiB0; return uiZ; returnA: uiZ.v64 = uiNonsigA64; uiZ.v0 = uiA0; return uiZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF32UI.c000066400000000000000000000073731464416617300300730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) { bool isSigNaNA, isSigNaNB; uint_fast32_t uiNonsigA, uiNonsigB, uiMagA, uiMagB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNF32UI( uiA ); isSigNaNB = softfloat_isSigNaNF32UI( uiB ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA = uiA | 0x00400000; uiNonsigB = uiB | 0x00400000; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; return isNaNF32UI( uiB ) ? uiNonsigB : uiNonsigA; } else { return isNaNF32UI( uiA ) ? uiNonsigA : uiNonsigB; } } returnLargerMag: uiMagA = uiNonsigA & 0x7FFFFFFF; uiMagB = uiNonsigB & 0x7FFFFFFF; if ( uiMagA < uiMagB ) return uiNonsigB; if ( uiMagB < uiMagA ) return uiNonsigA; return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/s_propagateNaNF64UI.c000066400000000000000000000075131464416617300300740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) { bool isSigNaNA, isSigNaNB; uint_fast64_t uiNonsigA, uiNonsigB, uiMagA, uiMagB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ isSigNaNA = softfloat_isSigNaNF64UI( uiA ); isSigNaNB = softfloat_isSigNaNF64UI( uiB ); /*------------------------------------------------------------------------ | Make NaNs non-signaling. *------------------------------------------------------------------------*/ uiNonsigA = uiA | UINT64_C( 0x0008000000000000 ); uiNonsigB = uiB | UINT64_C( 0x0008000000000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isSigNaNA | isSigNaNB ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( isSigNaNA ) { if ( isSigNaNB ) goto returnLargerMag; return isNaNF64UI( uiB ) ? uiNonsigB : uiNonsigA; } else { return isNaNF64UI( uiA ) ? uiNonsigA : uiNonsigB; } } returnLargerMag: uiMagA = uiNonsigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); uiMagB = uiNonsigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( uiMagA < uiMagB ) return uiNonsigB; if ( uiMagB < uiMagA ) return uiNonsigA; return (uiNonsigA < uiNonsigB) ? uiNonsigA : uiNonsigB; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/softfloat_raiseFlags.c000066400000000000000000000045771464416617300306250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include "platform.h" #include "softfloat.h" /*---------------------------------------------------------------------------- | Raises the exceptions specified by `flags'. Floating-point traps can be | defined here if desired. It is currently not possible for such a trap | to substitute a result value. If traps are not implemented, this routine | should be simply `softfloat_exceptionFlags |= flags;'. *----------------------------------------------------------------------------*/ void softfloat_raiseFlags( uint_fast8_t flags ) { softfloat_exceptionFlags |= flags; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/8086/specialize.h000066400000000000000000000403621464416617300266110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #ifndef specialize_h #define specialize_h 1 #include #include #include "softfloat_types.h" /*---------------------------------------------------------------------------- | Default value for `softfloat_detectTininess'. *----------------------------------------------------------------------------*/ #define init_detectTininess softfloat_tininess_afterRounding; /*---------------------------------------------------------------------------- | "Common NaN" structure, used to transfer NaN representations from one format | to another. *----------------------------------------------------------------------------*/ struct commonNaN { bool sign; #ifdef LITTLEENDIAN uint64_t v0, v64; #else uint64_t v64, v0; #endif }; /*---------------------------------------------------------------------------- | The bit pattern for a default generated 32-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF32UI 0xFFC00000 /*---------------------------------------------------------------------------- | Returns true when 32-bit unsigned integer `uiA' has the bit pattern of a | 32-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr ); /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 64-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 ) /*---------------------------------------------------------------------------- | Returns true when 64-bit unsigned integer `uiA' has the bit pattern of a | 64-bit floating-point signaling NaN. | Note: This macro evaluates its argument more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF ))) /*---------------------------------------------------------------------------- | Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr ); /*---------------------------------------------------------------------------- | Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- | point values, at least one of which is a NaN, returns the bit pattern of | the combined NaN result. If either `uiA' or `uiB' has the pattern of a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ uint_fast64_t softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 80-bit extended floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNExtF80UI64 0xFFFF #define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 ) /*---------------------------------------------------------------------------- | Returns true when the 80-bit unsigned integer formed from concatenating | 16-bit `uiA64' and 64-bit `uiA0' has the bit pattern of an 80-bit extended | floating-point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF ))) #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- | The following functions are needed only when `SOFTFLOAT_FAST_INT64' is | defined. *----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of an 80-bit extended floating-point NaN, converts | this NaN to the common NaN form, and stores the resulting common NaN at the | location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80UIToCommonNaN( uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and returns the bit pattern of this value as an unsigned | integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr ); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as an 80-bit extended floating-point value, and likewise interpreting | the unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 80-bit extended floating-point value, and assuming at least on of these | floating-point values is a NaN, returns the bit pattern of the combined NaN | result. If either original floating-point value is a signaling NaN, the | invalid exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNExtF80UI( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0 ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 ) #define defaultNaNF128UI0 UINT64_C( 0 ) /*---------------------------------------------------------------------------- | Returns true when the 128-bit unsigned integer formed from concatenating | 64-bit `uiA64' and 64-bit `uiA0' has the bit pattern of a 128-bit floating- | point signaling NaN. | Note: This macro evaluates its arguments more than once. *----------------------------------------------------------------------------*/ #define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF )))) /*---------------------------------------------------------------------------- | Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' | has the bit pattern of a 128-bit floating-point NaN, converts this NaN to | the common NaN form, and stores the resulting common NaN at the location | pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception | is raised. *----------------------------------------------------------------------------*/ void softfloat_f128UIToCommonNaN( uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and returns the bit pattern of this value as an unsigned integer. *----------------------------------------------------------------------------*/ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * ); /*---------------------------------------------------------------------------- | Interpreting the unsigned integer formed from concatenating `uiA64' and | `uiA0' as a 128-bit floating-point value, and likewise interpreting the | unsigned integer formed from concatenating `uiB64' and `uiB0' as another | 128-bit floating-point value, and assuming at least on of these floating- | point values is a NaN, returns the bit pattern of the combined NaN result. | If either original floating-point value is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ struct uint128 softfloat_propagateNaNF128UI( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0 ); #else /*---------------------------------------------------------------------------- | The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not | defined. *----------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------- | Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is | a NaN, converts this NaN to the common NaN form, and stores the resulting | common NaN at the location pointed to by `zPtr'. If the NaN is a signaling | NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_extF80MToCommonNaN( const struct extFloat80M *aSPtr, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into an 80-bit extended | floating-point NaN, and stores this NaN at the location pointed to by | `zSPtr'. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToExtF80M( const struct commonNaN *aPtr, struct extFloat80M *zSPtr ); /*---------------------------------------------------------------------------- | Assuming at least one of the two 80-bit extended floating-point values | pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result | at the location pointed to by `zSPtr'. If either original floating-point | value is a signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr ); /*---------------------------------------------------------------------------- | The bit pattern for a default generated 128-bit floating-point NaN. *----------------------------------------------------------------------------*/ #define defaultNaNF128UI96 0xFFFF8000 #define defaultNaNF128UI64 0 #define defaultNaNF128UI32 0 #define defaultNaNF128UI0 0 /*---------------------------------------------------------------------------- | Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN, | converts this NaN to the common NaN form, and stores the resulting common | NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN, | the invalid exception is raised. Argument `aWPtr' points to an array of | four 32-bit elements that concatenate in the platform's normal endian order | to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr ); /*---------------------------------------------------------------------------- | Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point | NaN, and stores this NaN at the location pointed to by `zWPtr'. Argument | `zWPtr' points to an array of four 32-bit elements that concatenate in the | platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr ); /*---------------------------------------------------------------------------- | Assuming at least one of the two 128-bit floating-point values pointed to by | `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location | pointed to by `zWPtr'. If either original floating-point value is a | signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr', | and `zWPtr' points to an array of four 32-bit elements that concatenate in | the platform's normal endian order to form a 128-bit floating-point value. *----------------------------------------------------------------------------*/ void softfloat_propagateNaNF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ); #endif #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_add.c000066400000000000000000000065241464416617300260540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_add( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) extFloat80_t (*magsFuncPtr)( uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); #endif aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; signA = signExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; signB = signExtF80UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { *zPtr = softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } else { *zPtr = softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_addMagsExtF80 : softfloat_subMagsExtF80; *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } #else void extF80M_add( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { softfloat_addExtF80M( (const struct extFloat80M *) aPtr, (const struct extFloat80M *) bPtr, (struct extFloat80M *) zPtr, false ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_div.c000066400000000000000000000157611464416617300261110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_div( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { *zPtr = extF80_div( *aPtr, *bPtr ); } #else void extF80M_div( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr, *bSPtr; struct extFloat80M *zSPtr; uint_fast16_t uiA64; int32_t expA; uint_fast16_t uiB64; int32_t expB; bool signZ; uint64_t sigA, x64; int32_t expZ; int shiftCount; uint32_t y[3], recip32, sigB[3]; int ix; uint32_t q, qs[2]; uint_fast16_t uiZ64; uint64_t uiZ0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; expA = expExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; expB = expExtF80UI64( uiB64 ); signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; if ( expA == 0x7FFF ) { if ( expB == 0x7FFF ) goto invalid; goto infinity; } goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sigA = aSPtr->signif; x64 = bSPtr->signif; if ( ! expB ) expB = 1; if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) { if ( ! x64 ) { if ( ! sigA ) goto invalid; softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } expB += softfloat_normExtF80SigM( &x64 ); } if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; expA += softfloat_normExtF80SigM( &sigA ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA - expB + 0x3FFF; shiftCount = 29; if ( sigA < x64 ) { --expZ; shiftCount = 30; } softfloat_shortShiftLeft64To96M( sigA, shiftCount, y ); recip32 = softfloat_approxRecip32_1( x64>>32 ); sigB[indexWord( 3, 0 )] = (uint32_t) x64<<30; x64 >>= 2; sigB[indexWord( 3, 2 )] = x64>>32; sigB[indexWord( 3, 1 )] = x64; ix = 2; for (;;) { x64 = (uint64_t) y[indexWordHi( 3 )] * recip32; q = (x64 + 0x80000000)>>32; --ix; if ( ix < 0 ) break; softfloat_remStep96MBy32( y, 29, sigB, q, y ); if ( y[indexWordHi( 3 )] & 0x80000000 ) { --q; softfloat_add96M( y, sigB, y ); } qs[ix] = q; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ((q + 1) & 0x3FFFFF) < 2 ) { softfloat_remStep96MBy32( y, 29, sigB, q, y ); if ( y[indexWordHi( 3 )] & 0x80000000 ) { --q; softfloat_add96M( y, sigB, y ); } else if ( softfloat_compare96M( sigB, y ) <= 0 ) { ++q; softfloat_sub96M( y, sigB, y ); } if ( y[indexWordLo( 3 )] || y[indexWord( 3, 1 )] || y[indexWord( 3, 2 )] ) { q |= 1; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ x64 = (uint64_t) q<<9; y[indexWord( 3, 0 )] = x64; x64 = ((uint64_t) qs[0]<<6) + (x64>>32); y[indexWord( 3, 1 )] = x64; y[indexWord( 3, 2 )] = (qs[1]<<3) + (x64>>32); softfloat_roundPackMToExtF80M( signZ, expZ, y, extF80_roundingPrecision, zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidExtF80M( zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infinity: uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signZ, 0 ); uiZ0 = 0; uiZ: zSPtr->signExp = uiZ64; zSPtr->signif = uiZ0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq.c000066400000000000000000000072631464416617300257320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { return extF80_eq( *aPtr, *bPtr ); } #else bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( uiA0 == uiB0 ) { return (uiA64 == uiB64) || ! uiA0; } else { if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return ! softfloat_compareNonnormExtF80M( aSPtr, bSPtr ); } return false; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_eq_signaling.c000066400000000000000000000070401464416617300277560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { return extF80_eq_signaling( *aPtr, *bPtr ); } #else bool extF80M_eq_signaling( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( uiA0 == uiB0 ) { return (uiA64 == uiB64) || ! uiA0; } else { if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return ! softfloat_compareNonnormExtF80M( aSPtr, bSPtr ); } return false; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le.c000066400000000000000000000102041464416617300257120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { return extF80_le( *aPtr, *bPtr ); } #else bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; bool signA, ltMags; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signExtF80UI64( uiA64 ); if ( (uiA64 ^ uiB64) & 0x8000 ) { /*-------------------------------------------------------------------- | Signs are different. *--------------------------------------------------------------------*/ return signA || ! (uiA0 | uiB0); } else { /*-------------------------------------------------------------------- | Signs are the same. *--------------------------------------------------------------------*/ if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) <= 0); } if ( uiA64 == uiB64 ) { if ( uiA0 == uiB0 ) return true; ltMags = (uiA0 < uiB0); } else { ltMags = (uiA64 < uiB64); } return signA ^ ltMags; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_le_quiet.c000066400000000000000000000105071464416617300271270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { return extF80_le_quiet( *aPtr, *bPtr ); } #else bool extF80M_le_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; bool signA, ltMags; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signExtF80UI64( uiA64 ); if ( (uiA64 ^ uiB64) & 0x8000 ) { /*-------------------------------------------------------------------- | Signs are different. *--------------------------------------------------------------------*/ return signA || ! (uiA0 | uiB0); } else { /*-------------------------------------------------------------------- | Signs are the same. *--------------------------------------------------------------------*/ if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) <= 0); } if ( uiA64 == uiB64 ) { if ( uiA0 == uiB0 ) return true; ltMags = (uiA0 < uiB0); } else { ltMags = (uiA64 < uiB64); } return signA ^ ltMags; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt.c000066400000000000000000000102111464416617300257270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { return extF80_lt( *aPtr, *bPtr ); } #else bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; bool signA, ltMags; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signExtF80UI64( uiA64 ); if ( (uiA64 ^ uiB64) & 0x8000 ) { /*-------------------------------------------------------------------- | Signs are different. *--------------------------------------------------------------------*/ return signA && ((uiA0 | uiB0) != 0); } else { /*-------------------------------------------------------------------- | Signs are the same. *--------------------------------------------------------------------*/ if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0); } if ( uiA64 == uiB64 ) { if ( uiA0 == uiB0 ) return false; ltMags = (uiA0 < uiB0); } else { ltMags = (uiA64 < uiB64); } return signA ^ ltMags; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_lt_quiet.c000066400000000000000000000105141464416617300271440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { return extF80_lt_quiet( *aPtr, *bPtr ); } #else bool extF80M_lt_quiet( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint64_t uiA0; uint_fast16_t uiB64; uint64_t uiB0; bool signA, ltMags; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signExtF80UI64( uiA64 ); if ( (uiA64 ^ uiB64) & 0x8000 ) { /*-------------------------------------------------------------------- | Signs are different. *--------------------------------------------------------------------*/ return signA && ((uiA0 | uiB0) != 0); } else { /*-------------------------------------------------------------------- | Signs are the same. *--------------------------------------------------------------------*/ if ( ! ((uiA0 & uiB0) & UINT64_C( 0x8000000000000000 )) ) { return (softfloat_compareNonnormExtF80M( aSPtr, bSPtr ) < 0); } if ( uiA64 == uiB64 ) { if ( uiA0 == uiB0 ) return false; ltMags = (uiA0 < uiB0); } else { ltMags = (uiA64 < uiB64); } return signA ^ ltMags; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_mul.c000066400000000000000000000122541464416617300261160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_mul( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { *zPtr = extF80_mul( *aPtr, *bPtr ); } #else void extF80M_mul( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr, *bSPtr; struct extFloat80M *zSPtr; uint_fast16_t uiA64; int32_t expA; uint_fast16_t uiB64; int32_t expB; bool signZ; uint_fast16_t exp, uiZ64; uint64_t uiZ0, sigA, sigB; int32_t expZ; uint32_t sigProd[4], *extSigZPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; expA = expExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; expB = expExtF80UI64( uiB64 ); signZ = signExtF80UI64( uiA64 ) ^ signExtF80UI64( uiB64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; if ( (! aSPtr->signif && (expA != 0x7FFF)) || (! bSPtr->signif && (expB != 0x7FFF)) ) { softfloat_invalidExtF80M( zSPtr ); return; } uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; sigA = aSPtr->signif; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; expA += softfloat_normExtF80SigM( &sigA ); } if ( ! expB ) expB = 1; sigB = bSPtr->signif; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigB ) goto zero; expB += softfloat_normExtF80SigM( &sigB ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FFE; softfloat_mul64To128M( sigA, sigB, sigProd ); if ( sigProd[indexWordLo( 4 )] ) sigProd[indexWord( 4, 1 )] |= 1; extSigZPtr = &sigProd[indexMultiwordHi( 4, 3 )]; if ( sigProd[indexWordHi( 4 )] < 0x80000000 ) { --expZ; softfloat_add96M( extSigZPtr, extSigZPtr, extSigZPtr ); } softfloat_roundPackMToExtF80M( signZ, expZ, extSigZPtr, extF80_roundingPrecision, zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signZ, 0 ); uiZ0 = 0; uiZ: zSPtr->signExp = uiZ64; zSPtr->signif = uiZ0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_rem.c000066400000000000000000000172011464416617300261010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_rem( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { *zPtr = extF80_rem( *aPtr, *bPtr ); } #else void extF80M_rem( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr, *bSPtr; struct extFloat80M *zSPtr; uint_fast16_t uiA64; int32_t expA, expB; uint64_t x64; bool signRem; uint64_t sigA; int32_t expDiff; uint32_t rem[3], x[3], sig32B, q, recip32, rem2[3], *remPtr, *altRemPtr; uint32_t *newRemPtr, wordMeanRem; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; expA = expExtF80UI64( uiA64 ); expB = expExtF80UI64( bSPtr->signExp ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; if ( expA == 0x7FFF ) goto invalid; /*-------------------------------------------------------------------- | If we get here, then argument b is an infinity and `expB' is 0x7FFF; | Doubling `expB' is an easy way to ensure that `expDiff' later is | less than -1, which will result in returning a canonicalized version | of argument a. *--------------------------------------------------------------------*/ expB += expB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) expB = 1; x64 = bSPtr->signif; if ( ! (x64 & UINT64_C( 0x8000000000000000 )) ) { if ( ! x64 ) goto invalid; expB += softfloat_normExtF80SigM( &x64 ); } signRem = signExtF80UI64( uiA64 ); if ( ! expA ) expA = 1; sigA = aSPtr->signif; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) { expA = 0; goto copyA; } expA += softfloat_normExtF80SigM( &sigA ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( expDiff < -1 ) goto copyA; rem[indexWord( 3, 2 )] = sigA>>34; rem[indexWord( 3, 1 )] = sigA>>2; rem[indexWord( 3, 0 )] = (uint32_t) sigA<<30; x[indexWord( 3, 0 )] = (uint32_t) x64<<30; sig32B = x64>>32; x64 >>= 2; x[indexWord( 3, 2 )] = x64>>32; x[indexWord( 3, 1 )] = x64; if ( expDiff < 1 ) { if ( expDiff ) { --expB; softfloat_add96M( x, x, x ); q = 0; } else { q = (softfloat_compare96M( x, rem ) <= 0); if ( q ) softfloat_sub96M( rem, x, rem ); } } else { recip32 = softfloat_approxRecip32_1( sig32B ); expDiff -= 30; for (;;) { x64 = (uint64_t) rem[indexWordHi( 3 )] * recip32; if ( expDiff < 0 ) break; q = (x64 + 0x80000000)>>32; softfloat_remStep96MBy32( rem, 29, x, q, rem ); if ( rem[indexWordHi( 3 )] & 0x80000000 ) { softfloat_add96M( rem, x, rem ); } expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -29 here.) *--------------------------------------------------------------------*/ q = (uint32_t) (x64>>32)>>(~expDiff & 31); softfloat_remStep96MBy32( rem, expDiff + 30, x, q, rem ); if ( rem[indexWordHi( 3 )] & 0x80000000 ) { remPtr = rem; altRemPtr = rem2; softfloat_add96M( remPtr, x, altRemPtr ); goto selectRem; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ remPtr = rem; altRemPtr = rem2; do { ++q; newRemPtr = altRemPtr; softfloat_sub96M( remPtr, x, newRemPtr ); altRemPtr = remPtr; remPtr = newRemPtr; } while ( ! (remPtr[indexWordHi( 3 )] & 0x80000000) ); selectRem: softfloat_add96M( remPtr, altRemPtr, x ); wordMeanRem = x[indexWordHi( 3 )]; if ( (wordMeanRem & 0x80000000) || (! wordMeanRem && (q & 1) && ! x[indexWord( 3, 0 )] && ! x[indexWord( 3, 1 )]) ) { remPtr = altRemPtr; } if ( remPtr[indexWordHi( 3 )] & 0x80000000 ) { signRem = ! signRem; softfloat_negX96M( remPtr ); } softfloat_normRoundPackMToExtF80M( signRem, expB + 2, remPtr, 80, zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidExtF80M( zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ copyA: if ( expA < 1 ) { sigA >>= 1 - expA; expA = 0; } zSPtr->signExp = packToExtF80UI64( signRem, expA ); zSPtr->signif = sigA; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_roundToInt.c000066400000000000000000000135031464416617300274240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_roundToInt( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact, extFloat80_t *zPtr ) { *zPtr = extF80_roundToInt( *aPtr, roundingMode, exact ); } #else void extF80M_roundToInt( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr; struct extFloat80M *zSPtr; uint_fast16_t uiA64, signUI64; int32_t exp; uint64_t sigA; uint_fast16_t uiZ64; uint64_t sigZ, lastBitMask, roundBitsMask; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); exp = expExtF80UI64( uiA64 ); sigA = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) { if ( ! sigA ) { uiZ64 = signUI64; sigZ = 0; goto uiZ; } exp += softfloat_normExtF80SigM( &sigA ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp <= 0x3FFE ) { if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; switch ( roundingMode ) { case softfloat_round_near_even: if ( ! (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FFE ) goto mag1; break; case softfloat_round_min: if ( signUI64 ) goto mag1; break; case softfloat_round_max: if ( ! signUI64 ) goto mag1; break; } uiZ64 = signUI64; sigZ = 0; goto uiZ; mag1: uiZ64 = signUI64 | 0x3FFF; sigZ = UINT64_C( 0x8000000000000000 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x403E <= exp ) { if ( exp == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr ); return; } sigZ = UINT64_C( 0x8000000000000000 ); } else { sigZ = sigA; } uiZ64 = signUI64 | exp; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ64 = signUI64 | exp; lastBitMask = (uint64_t) 1<<(0x403E - exp); roundBitsMask = lastBitMask - 1; sigZ = sigA; if ( roundingMode == softfloat_round_near_maxMag ) { sigZ += lastBitMask>>1; } else if ( roundingMode == softfloat_round_near_even ) { sigZ += lastBitMask>>1; if ( ! (sigZ & roundBitsMask) ) sigZ &= ~lastBitMask; } else if ( roundingMode != softfloat_round_minMag ) { if ( (signUI64 != 0) ^ (roundingMode == softfloat_round_max) ) { sigZ += roundBitsMask; } } sigZ &= ~roundBitsMask; if ( ! sigZ ) { ++uiZ64; sigZ = UINT64_C( 0x8000000000000000 ); } if ( exact && (sigZ != sigA) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } uiZ: zSPtr->signExp = uiZ64; zSPtr->signif = sigZ; return; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sqrt.c000066400000000000000000000156021464416617300263120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr ) { *zPtr = extF80_sqrt( *aPtr ); } #else void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr; struct extFloat80M *zSPtr; uint_fast16_t uiA64, signUI64; int32_t expA; uint64_t rem64; int32_t expZ; uint32_t rem[4], sig32A, recipSqrt32, sig32Z, q; uint64_t sig64Z, x64; uint32_t term[4], extSigZ[3]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); expA = expExtF80UI64( uiA64 ); rem64 = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( rem64 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_propagateNaNExtF80M( aSPtr, 0, zSPtr ); return; } if ( signUI64 ) goto invalid; rem64 = UINT64_C( 0x8000000000000000 ); goto copyA; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; if ( ! (rem64 & UINT64_C( 0x8000000000000000 )) ) { if ( ! rem64 ) { uiA64 = signUI64; goto copyA; } expA += softfloat_normExtF80SigM( &rem64 ); } if ( signUI64 ) goto invalid; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = ((expA - 0x3FFF)>>1) + 0x3FFF; expA &= 1; softfloat_shortShiftLeft64To96M( rem64, 30 - expA, &rem[indexMultiwordHi( 4, 3 )] ); sig32A = rem64>>32; recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; if ( expA ) sig32Z >>= 1; rem64 = ((uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )]) - (uint64_t) sig32Z * sig32Z; rem[indexWord( 4, 3 )] = rem64>>32; rem[indexWord( 4, 2 )] = rem64; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32; sig64Z = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<3); x64 = ((uint64_t) sig32Z<<32) + sig64Z; term[indexWord( 3, 2 )] = 0; term[indexWord( 3, 1 )] = x64>>32; term[indexWord( 3, 0 )] = x64; softfloat_remStep96MBy32( &rem[indexMultiwordHi( 4, 3 )], 29, term, q, &rem[indexMultiwordHi( 4, 3 )] ); rem64 = (uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = (((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32) + 2; x64 = (uint64_t) q<<7; extSigZ[indexWord( 3, 0 )] = x64; x64 = (sig64Z<<1) + (x64>>32); extSigZ[indexWord( 3, 2 )] = x64>>32; extSigZ[indexWord( 3, 1 )] = x64; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (q & 0xFFFFFF) <= 2 ) { q &= ~(uint32_t) 0xFFFF; extSigZ[indexWordLo( 3 )] = q<<7; x64 = sig64Z + (q>>27); term[indexWord( 4, 3 )] = 0; term[indexWord( 4, 2 )] = x64>>32; term[indexWord( 4, 1 )] = x64; term[indexWord( 4, 0 )] = q<<5; rem[indexWord( 4, 0 )] = 0; softfloat_remStep128MBy32( rem, 28, term, q, rem ); q = rem[indexWordHi( 4 )]; if ( q & 0x80000000 ) { softfloat_sub1X96M( extSigZ ); } else { if ( q || rem[indexWord( 4, 1 )] || rem[indexWord( 4, 2 )] ) { extSigZ[indexWordLo( 3 )] |= 1; } } } softfloat_roundPackMToExtF80M( 0, expZ, extSigZ, extF80_roundingPrecision, zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidExtF80M( zSPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ copyA: zSPtr->signExp = uiA64; zSPtr->signif = rem64; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_sub.c000066400000000000000000000065231464416617300261140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_sub( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { const struct extFloat80M *aSPtr, *bSPtr; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) extFloat80_t (*magsFuncPtr)( uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); #endif aSPtr = (const struct extFloat80M *) aPtr; bSPtr = (const struct extFloat80M *) bPtr; uiA64 = aSPtr->signExp; uiA0 = aSPtr->signif; signA = signExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; uiB0 = bSPtr->signif; signB = signExtF80UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { *zPtr = softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } else { *zPtr = softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_subMagsExtF80 : softfloat_addMagsExtF80; *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } #else void extF80M_sub( const extFloat80_t *aPtr, const extFloat80_t *bPtr, extFloat80_t *zPtr ) { softfloat_addExtF80M( (const struct extFloat80M *) aPtr, (const struct extFloat80M *) bPtr, (struct extFloat80M *) zPtr, true ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f128M.c000066400000000000000000000111661464416617300266210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) { *zPtr = extF80_to_f128( *aPtr ); } #else void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) { const struct extFloat80M *aSPtr; uint32_t *zWPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; struct commonNaN commonNaN; uint32_t uiZ96; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 0 )] = 0; if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); softfloat_commonNaNToF128M( &commonNaN, zWPtr ); return; } uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp ) --exp; if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { if ( ! sig ) { uiZ96 = packToF128UI96( sign, 0, 0 ); goto uiZ; } exp += softfloat_normExtF80SigM( &sig ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<17; sig >>= 15; zWPtr[indexWord( 4, 2 )] = sig; if ( exp < 0 ) { zWPtr[indexWordHi( 4 )] = sig>>32; softfloat_shiftRight96M( &zWPtr[indexMultiwordHi( 4, 3 )], -exp, &zWPtr[indexMultiwordHi( 4, 3 )] ); exp = 0; sig = (uint64_t) zWPtr[indexWordHi( 4 )]<<32; } zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, sig>>32 ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f32.c000066400000000000000000000100561464416617300264130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 float32_t extF80M_to_f32( const extFloat80_t *aPtr ) { return extF80_to_f32( *aPtr ); } #else float32_t extF80M_to_f32( const extFloat80_t *aPtr ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; struct commonNaN commonNaN; uint32_t uiZ, sig32; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { if ( ! sig ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } exp += softfloat_normExtF80SigM( &sig ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sig32 = softfloat_shortShiftRightJam64( sig, 33 ); exp -= 0x3F81; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF32( sign, exp, sig32 | 0x40000000 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_f64.c000066400000000000000000000101131464416617300264120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 float64_t extF80M_to_f64( const extFloat80_t *aPtr ) { return extF80_to_f64( *aPtr ); } #else float64_t extF80M_to_f64( const extFloat80_t *aPtr ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; struct commonNaN commonNaN; uint64_t uiZ; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80MToCommonNaN( aSPtr, &commonNaN ); uiZ = softfloat_commonNaNToF64UI( &commonNaN ); } else { uiZ = packToF64UI( sign, 0x7FF, 0 ); } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (sig & UINT64_C( 0x8000000000000000 )) ) { if ( ! sig ) { uiZ = packToF64UI( sign, 0, 0 ); goto uiZ; } exp += softfloat_normExtF80SigM( &sig ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sig = softfloat_shortShiftRightJam64( sig, 1 ); exp -= 0x3C01; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF64( sign, exp, sig | UINT64_C( 0x4000000000000000 ) ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: uZ.ui = uiZ; return uZ.f; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32.c000066400000000000000000000070671464416617300264260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast32_t extF80M_to_i32( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return extF80_to_i32( *aPtr, roundingMode, exact ); } #else int_fast32_t extF80M_to_i32( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; int32_t shiftCount; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) sign = 0; shiftCount = 0x4037 - exp; if ( shiftCount <= 0 ) { if ( sig>>32 ) goto invalid; if ( -32 < shiftCount ) { sig <<= -shiftCount; } else { if ( (uint32_t) sig ) goto invalid; } } else { sig = softfloat_shiftRightJam64( sig, shiftCount ); } return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i32_r_minMag.c000066400000000000000000000104651464416617300302330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact ) { return extF80_to_i32_r_minMag( *aPtr, exact ); } #else int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *aPtr, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp; uint64_t sig; int32_t shiftCount; bool raiseInexact; int32_t z; uint64_t shiftedSig; uint32_t absZ; union { uint32_t ui; int32_t i; } u; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! sig && (exp != 0x7FFF) ) return 0; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { raiseInexact = exact; z = 0; } else { raiseInexact = false; if ( shiftCount < 0 ) { if ( sig>>32 || (shiftCount <= -31) ) goto invalid; shiftedSig = (uint64_t) (uint32_t) sig<<-shiftCount; if ( shiftedSig>>32 ) goto invalid; absZ = shiftedSig; } else { shiftedSig = sig; if ( shiftCount ) shiftedSig >>= shiftCount; if ( shiftedSig>>32 ) goto invalid; absZ = shiftedSig; if ( exact && shiftCount ) { raiseInexact = ((uint64_t) absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast64_t extF80M_to_i64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return extF80_to_i64( *aPtr, roundingMode, exact ); } #else int_fast64_t extF80M_to_i64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; int32_t shiftCount; uint32_t extSig[3]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; extSig[indexWord( 3, 0 )] = 0; if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); return softfloat_roundPackMToI64( sign, extSig, roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_i64_r_minMag.c000066400000000000000000000103541464416617300302350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact ) { return extF80_to_i64_r_minMag( *aPtr, exact ); } #else int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *aPtr, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp; uint64_t sig; int32_t shiftCount; bool raiseInexact; int64_t z; uint64_t absZ; union { uint64_t ui; int64_t i; } u; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! sig && (exp != 0x7FFF) ) return 0; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { raiseInexact = exact; z = 0; } else { raiseInexact = false; if ( shiftCount < 0 ) { if ( shiftCount <= -63 ) goto invalid; shiftCount = -shiftCount; absZ = sig<>shiftCount != sig ) goto invalid; } else { absZ = sig; if ( shiftCount ) absZ >>= shiftCount; if ( exact && shiftCount ) { raiseInexact = (absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast32_t extF80M_to_ui32( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return extF80_to_ui32( *aPtr, roundingMode, exact ); } #else uint_fast32_t extF80M_to_ui32( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; bool sign; int32_t exp; uint64_t sig; int32_t shiftCount; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftCount = 0x4037 - exp; if ( shiftCount <= 0 ) { if ( sig>>32 ) goto invalid; if ( -32 < shiftCount ) { sig <<= -shiftCount; } else { if ( (uint32_t) sig ) goto invalid; } } else { sig = softfloat_shiftRightJam64( sig, shiftCount ); } return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui32_r_minMag.c000066400000000000000000000075361464416617300304250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact ) { return extF80_to_ui32_r_minMag( *aPtr, exact ); } #else uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *aPtr, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp; uint64_t sig; int32_t shiftCount; bool sign; uint64_t shiftedSig; uint32_t z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! sig && (exp != 0x7FFF) ) return 0; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; return 0; } sign = signExtF80UI64( uiA64 ); if ( shiftCount < 0 ) { if ( sign || sig>>32 || (shiftCount <= -31) ) goto invalid; shiftedSig = (uint64_t) (uint32_t) sig<<-shiftCount; if ( shiftedSig>>32 ) goto invalid; z = shiftedSig; } else { shiftedSig = sig; if ( shiftCount ) shiftedSig >>= shiftCount; if ( shiftedSig>>32 ) goto invalid; z = shiftedSig; if ( sign && z ) goto invalid; if ( exact && shiftCount && ((uint64_t) z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t extF80M_to_ui64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return extF80_to_ui64( *aPtr, roundingMode, exact ); } #else uint_fast64_t extF80M_to_ui64( const extFloat80_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp, shiftCount; bool sign; uint64_t sig; uint32_t extSig[3]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sign = signExtF80UI64( uiA64 ); sig = aSPtr->signif; extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; extSig[indexWord( 3, 0 )] = 0; if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80M_to_ui64_r_minMag.c000066400000000000000000000073351464416617300304270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact ) { return extF80_to_ui64_r_minMag( *aPtr, exact ); } #else uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *aPtr, bool exact ) { const struct extFloat80M *aSPtr; uint_fast16_t uiA64; int32_t exp; uint64_t sig; int32_t shiftCount; bool sign; uint64_t z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aSPtr = (const struct extFloat80M *) aPtr; uiA64 = aSPtr->signExp; exp = expExtF80UI64( uiA64 ); sig = aSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! sig && (exp != 0x7FFF) ) return 0; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; return 0; } sign = signExtF80UI64( uiA64 ); if ( shiftCount < 0 ) { if ( sign || (shiftCount <= -63) ) goto invalid; shiftCount = -shiftCount; z = sig<>shiftCount != sig ) goto invalid; } else { z = sig; if ( shiftCount ) z >>= shiftCount; if ( sign && z ) goto invalid; if ( exact && shiftCount && (z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t extF80_add( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) extFloat80_t (*magsFuncPtr)( uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); #endif uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; signB = signExtF80UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } else { return softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_addMagsExtF80 : softfloat_subMagsExtF80; return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_div.c000066400000000000000000000174421464416617300257720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t extF80_div( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; int_fast32_t expA; uint_fast64_t sigA; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; int_fast32_t expB; uint_fast64_t sigB; bool signZ; struct exp32_sig64 normExpSig; int_fast32_t expZ; struct uint128 rem; uint_fast32_t recip32; uint_fast64_t sigZ; int ix; uint_fast64_t q64; uint_fast32_t q; struct uint128 term; uint_fast64_t sigZExtra; struct uint128 uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); expA = expExtF80UI64( uiA64 ); sigA = uiA0; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; signB = signExtF80UI64( uiB64 ); expB = expExtF80UI64( uiB64 ); sigB = uiB0; signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; goto invalid; } goto infinity; } if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) expB = 1; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigB ) { if ( ! sigA ) goto invalid; softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); expB += normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); expA += normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA - expB + 0x3FFF; if ( sigA < sigB ) { --expZ; rem = softfloat_shortShiftLeft128( 0, sigA, 32 ); } else { rem = softfloat_shortShiftLeft128( 0, sigA, 31 ); } recip32 = softfloat_approxRecip32_1( sigB>>32 ); sigZ = 0; ix = 2; for (;;) { q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32; q = (q64 + 0x80000000)>>32; --ix; if ( ix < 0 ) break; rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul64ByShifted32To128( sigB, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { --q; rem = softfloat_add128( rem.v64, rem.v0, sigB>>32, sigB<<32 ); } sigZ = (sigZ<<29) + q; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ((q + 1) & 0x3FFFFF) < 2 ) { rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul64ByShifted32To128( sigB, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); term = softfloat_shortShiftLeft128( 0, sigB, 32 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { --q; rem = softfloat_add128( rem.v64, rem.v0, term.v64, term.v0 ); } else if ( softfloat_le128( term.v64, term.v0, rem.v64, rem.v0 ) ) { ++q; rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); } if ( rem.v64 | rem.v0 ) q |= 1; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sigZ = (sigZ<<6) + (q>>23); sigZExtra = (uint64_t) ((uint_fast64_t) q<<41); return softfloat_roundPackToExtF80( signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infinity: uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signZ, 0 ); uiZ0 = 0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq.c000066400000000000000000000053641464416617300256150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool extF80_eq( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return (uiA0 == uiB0) && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_eq_signaling.c000066400000000000000000000051151464416617300276420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool extF80_eq_signaling( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } return (uiA0 == uiB0) && ((uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & 0x7FFF))); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_isSignalingNaN.c000066400000000000000000000041531464416617300300470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool extF80_isSignalingNaN( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uA.f = a; return softfloat_isSigNaNExtF80UI( uA.s.signExp, uA.s.signif ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le.c000066400000000000000000000054631464416617300256100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool extF80_le( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signA, signB; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return (signA != signB) ? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) : ((uiA64 == uiB64) && (uiA0 == uiB0)) || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_le_quiet.c000066400000000000000000000057221464416617300270150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool extF80_le_quiet( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signA, signB; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return (signA != signB) ? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) : ((uiA64 == uiB64) && (uiA0 == uiB0)) || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt.c000066400000000000000000000054611464416617300256250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool extF80_lt( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signA, signB; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return (signA != signB) ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) : ((uiA64 != uiB64) || (uiA0 != uiB0)) && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_lt_quiet.c000066400000000000000000000057201464416617300270320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool extF80_lt_quiet( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signA, signB; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) || softfloat_isSigNaNExtF80UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ); return (signA != signB) ? signA && (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0) : ((uiA64 != uiB64) || (uiA0 != uiB0)) && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_mul.c000066400000000000000000000135511464416617300260020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t extF80_mul( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; int_fast32_t expA; uint_fast64_t sigA; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; int_fast32_t expB; uint_fast64_t sigB; bool signZ; uint_fast64_t magBits; struct exp32_sig64 normExpSig; int_fast32_t expZ; struct uint128 sig128Z, uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); expA = expExtF80UI64( uiA64 ); sigA = uiA0; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; signB = signExtF80UI64( uiB64 ); expB = expExtF80UI64( uiB64 ); sigB = uiB0; signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ) { goto propagateNaN; } magBits = expB | sigB; goto infArg; } if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; magBits = expA | sigA; goto infArg; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); expA += normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) expB = 1; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigB ) goto zero; normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); expB += normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FFE; sig128Z = softfloat_mul64To128( sigA, sigB ); if ( sig128Z.v64 < UINT64_C( 0x8000000000000000 ) ) { --expZ; sig128Z = softfloat_add128( sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 ); } return softfloat_roundPackToExtF80( signZ, expZ, sig128Z.v64, sig128Z.v0, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; } else { uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); } goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signZ, 0 ); uiZ0 = 0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_rem.c000066400000000000000000000211651464416617300257700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t extF80_rem( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; int_fast32_t expA; uint_fast64_t sigA; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; int_fast32_t expB; uint_fast64_t sigB; struct exp32_sig64 normExpSig; int_fast32_t expDiff; struct uint128 rem, shiftedSigB; uint_fast32_t q, recip32; uint_fast64_t q64; struct uint128 term, altRem, meanRem; bool signRem; struct uint128 uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); expA = expExtF80UI64( uiA64 ); sigA = uiA0; uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; signB = signExtF80UI64( uiB64 ); expB = expExtF80UI64( uiB64 ); sigB = uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) || ((expB == 0x7FFF) && (sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ) { goto propagateNaN; } goto invalid; } if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; /*-------------------------------------------------------------------- | Argument b is an infinity. Doubling `expB' is an easy way to ensure | that `expDiff' later is less than -1, which will result in returning | a canonicalized version of argument a. *--------------------------------------------------------------------*/ expB += expB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) expB = 1; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigB ) goto invalid; normExpSig = softfloat_normSubnormalExtF80Sig( sigB ); expB += normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) { expA = 0; goto copyA; } normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); expA += normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( expDiff < -1 ) goto copyA; rem = softfloat_shortShiftLeft128( 0, sigA, 32 ); shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 32 ); if ( expDiff < 1 ) { if ( expDiff ) { --expB; shiftedSigB = softfloat_shortShiftLeft128( 0, sigB, 33 ); q = 0; } else { q = (sigB <= sigA); if ( q ) { rem = softfloat_sub128( rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); } } } else { recip32 = softfloat_approxRecip32_1( sigB>>32 ); expDiff -= 30; for (;;) { q64 = (uint_fast64_t) (uint32_t) (rem.v64>>2) * recip32; if ( expDiff < 0 ) break; q = (q64 + 0x80000000)>>32; rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul64ByShifted32To128( sigB, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { rem = softfloat_add128( rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); } expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -29 here.) *--------------------------------------------------------------------*/ q = (uint32_t) (q64>>32)>>(~expDiff & 31); rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 ); term = softfloat_mul64ByShifted32To128( sigB, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { altRem = softfloat_add128( rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); goto selectRem; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ do { altRem = rem; ++q; rem = softfloat_sub128( rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0 ); } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ); selectRem: meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 ); if ( (meanRem.v64 & UINT64_C( 0x8000000000000000 )) || (! (meanRem.v64 | meanRem.v0) && (q & 1)) ) { rem = altRem; } signRem = signA; if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { signRem = ! signRem; rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 ); } return softfloat_normRoundPackToExtF80( signRem, expB + 32, rem.v64, rem.v0, 80 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ copyA: if ( expA < 1 ) { sigA >>= 1 - expA; expA = 0; } uiZ64 = packToExtF80UI64( signA, expA ); uiZ0 = sigA; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_roundToInt.c000066400000000000000000000126751464416617300273200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t extF80_roundToInt( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64, signUI64; int_fast32_t exp; uint_fast64_t sigA; uint_fast16_t uiZ64; uint_fast64_t sigZ; struct exp32_sig64 normExpSig; struct uint128 uiZ; uint_fast64_t lastBitMask, roundBitsMask; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; signUI64 = uiA64 & packToExtF80UI64( 1, 0 ); exp = expExtF80UI64( uiA64 ); sigA = uA.s.signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! (sigA & UINT64_C( 0x8000000000000000 )) && (exp != 0x7FFF) ) { if ( ! sigA ) { uiZ64 = signUI64; sigZ = 0; goto uiZ; } normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); exp += normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x403E <= exp ) { if ( exp == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { uiZ = softfloat_propagateNaNExtF80UI( uiA64, sigA, 0, 0 ); uiZ64 = uiZ.v64; sigZ = uiZ.v0; goto uiZ; } sigZ = UINT64_C( 0x8000000000000000 ); } else { sigZ = sigA; } uiZ64 = signUI64 | exp; goto uiZ; } if ( exp <= 0x3FFE ) { if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; switch ( roundingMode ) { case softfloat_round_near_even: if ( ! (sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FFE ) goto mag1; break; case softfloat_round_min: if ( signUI64 ) goto mag1; break; case softfloat_round_max: if ( ! signUI64 ) goto mag1; break; } uiZ64 = signUI64; sigZ = 0; goto uiZ; mag1: uiZ64 = signUI64 | 0x3FFF; sigZ = UINT64_C( 0x8000000000000000 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ64 = signUI64 | exp; lastBitMask = (uint_fast64_t) 1<<(0x403E - exp); roundBitsMask = lastBitMask - 1; sigZ = sigA; if ( roundingMode == softfloat_round_near_maxMag ) { sigZ += lastBitMask>>1; } else if ( roundingMode == softfloat_round_near_even ) { sigZ += lastBitMask>>1; if ( ! (sigZ & roundBitsMask) ) sigZ &= ~lastBitMask; } else if ( roundingMode != softfloat_round_minMag ) { if ( (signUI64 != 0) ^ (roundingMode == softfloat_round_max) ) { sigZ += roundBitsMask; } } sigZ &= ~roundBitsMask; if ( ! sigZ ) { ++uiZ64; sigZ = UINT64_C( 0x8000000000000000 ); } if ( exact && (sigZ != sigA) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = sigZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sqrt.c000066400000000000000000000156401464416617300261770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t extF80_sqrt( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; int_fast32_t expA; uint_fast64_t sigA; struct uint128 uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; struct exp32_sig64 normExpSig; int_fast32_t expZ; uint_fast32_t sig32A, recipSqrt32, sig32Z; struct uint128 rem; uint_fast64_t q, sigZ, x64; struct uint128 term; uint_fast64_t sigZExtra; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); expA = expExtF80UI64( uiA64 ); sigA = uiA0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, 0, 0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; goto uiZ; } if ( ! signA ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signA ) { if ( ! sigA ) goto zero; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalExtF80Sig( sigA ); expA += normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ | (`sig32Z' is guaranteed to be a lower bound on the square root of | `sig32A', which makes `sig32Z' also a lower bound on the square root of | `sigA'.) *------------------------------------------------------------------------*/ expZ = ((expA - 0x3FFF)>>1) + 0x3FFF; expA &= 1; sig32A = sigA>>32; recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; if ( expA ) { sig32Z >>= 1; rem = softfloat_shortShiftLeft128( 0, sigA, 61 ); } else { rem = softfloat_shortShiftLeft128( 0, sigA, 62 ); } rem.v64 -= (uint_fast64_t) sig32Z * sig32Z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = ((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32; sigZ = ((uint_fast64_t) sig32Z<<32) + (q<<3); x64 = ((uint_fast64_t) sig32Z<<32) + sigZ; term = softfloat_mul64ByShifted32To128( x64, q ); rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = (((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32) + 2; x64 = sigZ; sigZ = (sigZ<<1) + (q>>25); sigZExtra = (uint64_t) (q<<39); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (q & 0xFFFFFF) <= 2 ) { q &= ~(uint_fast64_t) 0xFFFF; sigZExtra = (uint64_t) (q<<39); term = softfloat_mul64ByShifted32To128( x64 + (q>>27), q ); x64 = (uint_fast64_t) (uint32_t) (q<<5) * (uint32_t) q; term = softfloat_add128( term.v64, term.v0, 0, x64 ); rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 28 ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { if ( ! sigZExtra ) --sigZ; --sigZExtra; } else { if ( rem.v64 | rem.v0 ) sigZExtra |= 1; } } return softfloat_roundPackToExtF80( 0, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ64 = packToExtF80UI64( signA, 0 ); uiZ0 = 0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_sub.c000066400000000000000000000057711464416617300260030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t extF80_sub( extFloat80_t a, extFloat80_t b ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool signA; union { struct extFloat80M s; extFloat80_t f; } uB; uint_fast16_t uiB64; uint_fast64_t uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) extFloat80_t (*magsFuncPtr)( uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); #endif uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; signA = signExtF80UI64( uiA64 ); uB.f = b; uiB64 = uB.s.signExp; uiB0 = uB.s.signif; signB = signExtF80UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_subMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } else { return softfloat_addMagsExtF80( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_subMagsExtF80 : softfloat_addMagsExtF80; return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f128.c000066400000000000000000000054521464416617300263700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t extF80_to_f128( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; uint_fast16_t exp; uint_fast64_t sig; struct commonNaN commonNaN; struct uint128 uiZ; bool sign; struct uint128 sig128; union ui128_f128 uZ; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; exp = expExtF80UI64( uiA64 ); sig = uiA0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ); if ( (exp == 0x7FFF) && sig ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { sign = signExtF80UI64( uiA64 ); sig128 = softfloat_shortShiftLeft128( 0, sig, 49 ); uiZ.v64 = packToF128UI64( sign, exp, sig128.v64 ); uiZ.v0 = sig128.v0; } uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f32.c000066400000000000000000000060611464416617300262770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t extF80_to_f32( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig; struct commonNaN commonNaN; uint_fast32_t uiZ, sig32; union ui32_f32 uZ; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uiA0; if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } sig32 = softfloat_shortShiftRightJam64( sig, 33 ); if ( ! (exp | sig32) ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } exp -= 0x3F81; if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF32( sign, exp, sig32 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_f64.c000066400000000000000000000060441464416617300263050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t extF80_to_f64( extFloat80_t a ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; uint_fast64_t uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig; struct commonNaN commonNaN; uint_fast64_t uiZ; union ui64_f64 uZ; uA.f = a; uiA64 = uA.s.signExp; uiA0 = uA.s.signif; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uiA0; if ( ! (exp | sig) ) { uiZ = packToF64UI( sign, 0, 0 ); goto uiZ; } if ( exp == 0x7FFF ) { if ( sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { softfloat_extF80UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF64UI( &commonNaN ); } else { uiZ = packToF64UI( sign, 0x7FF, 0 ); } goto uiZ; } sig = softfloat_shortShiftRightJam64( sig, 1 ); exp -= 0x3C01; if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF64( sign, exp, sig ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32.c000066400000000000000000000051151464416617300263010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t extF80_to_i32( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; if ( (exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) sign = 0; shiftCount = 0x4037 - exp; if ( shiftCount <= 0 ) shiftCount = 1; sig = softfloat_shiftRightJam64( sig, shiftCount ); return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i32_r_minMag.c000066400000000000000000000065131464416617300301150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t extF80_to_i32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; bool sign; int_fast32_t absZ; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signExtF80UI64( uiA64 ); if ( shiftCount < 33 ) { if ( (uiA64 == packToExtF80UI64( 1, 0x401E )) && (sig < UINT64_C( 0x8000000100000000 )) ) { if ( exact && (sig & UINT64_C( 0x00000000FFFFFFFF )) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ) { return 0x7FFFFFFF; } } return -0x7FFFFFFF - 1; } absZ = sig>>shiftCount; if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t extF80_to_i64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uint_fast64_t sigExtra; struct uint64_extra sig64Extra; uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( shiftCount <= 0 ) { if ( shiftCount ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sigExtra = 0; } else { sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; } return softfloat_roundPackToI64( sign, sig, sigExtra, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_i64_r_minMag.c000066400000000000000000000062511464416617300301210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t extF80_to_i64_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; bool sign; int_fast64_t absZ; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signExtF80UI64( uiA64 ); if ( shiftCount <= 0 ) { if ( (uiA64 != packToExtF80UI64( 1, 0x403E )) || (sig != UINT64_C( 0x8000000000000000 )) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FFF) && (sig & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ) { return INT64_C( 0x7FFFFFFFFFFFFFFF ); } } return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } absZ = sig>>shiftCount; if ( exact && (uint64_t) (sig<<(-shiftCount & 63)) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return sign ? -absZ : absZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32.c000066400000000000000000000050011464416617300264600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t extF80_to_ui32( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; bool sign; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uA.f = a; uiA64 = uA.s.signExp; sign = signExtF80UI64( uiA64 ); exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x4037 - exp; if ( shiftCount <= 0 ) shiftCount = 1; sig = softfloat_shiftRightJam64( sig, shiftCount ); return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui32_r_minMag.c000066400000000000000000000054031464416617300302770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uint_fast32_t z; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signExtF80UI64( uiA64 ) || (shiftCount < 32) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } z = sig>>shiftCount; if ( exact && ((uint_fast64_t) z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t extF80_to_ui64( extFloat80_t a, uint_fast8_t roundingMode, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp, shiftCount; bool sign; uint_fast64_t sig, sigExtra; struct uint64_extra sig64Extra; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); shiftCount = 0x403E - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sign = signExtF80UI64( uiA64 ); sig = uA.s.signif; sigExtra = 0; if ( shiftCount ) { sig64Extra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; } return softfloat_roundPackToUI64( sign, sig, sigExtra, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/extF80_to_ui64_r_minMag.c000066400000000000000000000054061464416617300303070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t a, bool exact ) { union { struct extFloat80M s; extFloat80_t f; } uA; uint_fast16_t uiA64; int_fast32_t exp; uint_fast64_t sig; int_fast32_t shiftCount; uint_fast64_t z; uA.f = a; uiA64 = uA.s.signExp; exp = expExtF80UI64( uiA64 ); sig = uA.s.signif; shiftCount = 0x403E - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signExtF80UI64( uiA64 ) || (shiftCount < 0) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } z = sig>>shiftCount; if ( exact && (z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { const uint64_t *aWPtr, *bWPtr; uint_fast64_t uiA64, uiA0; bool signA; uint_fast64_t uiB64, uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) float128_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); #endif aWPtr = (const uint64_t *) aPtr; bWPtr = (const uint64_t *) bPtr; uiA64 = aWPtr[indexWord( 2, 1 )]; uiA0 = aWPtr[indexWord( 2, 0 )]; signA = signF128UI64( uiA64 ); uiB64 = bWPtr[indexWord( 2, 1 )]; uiB0 = bWPtr[indexWord( 2, 0 )]; signB = signF128UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } else { *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128; *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } #else void f128M_add( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { softfloat_addF128M( (const uint32_t *) aPtr, (const uint32_t *) bPtr, (uint32_t *) zPtr, false ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_div.c000066400000000000000000000152471464416617300255120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { *zPtr = f128_div( *aPtr, *bPtr ); } #else void f128M_div( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t *zWPtr, uiA96; bool signA; int32_t expA; uint32_t uiB96; bool signB; int32_t expB; bool signZ; uint32_t y[5], sigB[4]; int32_t expZ; uint32_t recip32; int ix; uint64_t q64; uint32_t q, qs[3], uiZ96; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); expA = expF128UI96( uiA96 ); uiB96 = bWPtr[indexWordHi( 4 )]; signB = signF128UI96( uiB96 ); expB = expF128UI96( uiB96 ); signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; if ( expA == 0x7FFF ) { if ( expB == 0x7FFF ) goto invalid; goto infinity; } goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = softfloat_shiftNormSigF128M( aWPtr, 13, y ); expB = softfloat_shiftNormSigF128M( bWPtr, 13, sigB ); if ( expA == -128 ) { if ( expB == -128 ) goto invalid; goto zero; } if ( expB == -128 ) { softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA - expB + 0x3FFE; if ( softfloat_compare128M( y, sigB ) < 0 ) { --expZ; softfloat_add128M( y, y, y ); } recip32 = softfloat_approxRecip32_1( ((uint64_t) sigB[indexWord( 4, 3 )]<<32 | sigB[indexWord( 4, 2 )]) >>30 ); ix = 3; for (;;) { q64 = (uint64_t) y[indexWordHi( 4 )] * recip32; q = (q64 + 0x80000000)>>32; --ix; if ( ix < 0 ) break; softfloat_remStep128MBy32( y, 29, sigB, q, y ); if ( y[indexWordHi( 4 )] & 0x80000000 ) { --q; softfloat_add128M( y, sigB, y ); } qs[ix] = q; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ((q + 1) & 7) < 2 ) { softfloat_remStep128MBy32( y, 29, sigB, q, y ); if ( y[indexWordHi( 4 )] & 0x80000000 ) { --q; softfloat_add128M( y, sigB, y ); } else if ( softfloat_compare128M( sigB, y ) <= 0 ) { ++q; softfloat_sub128M( y, sigB, y ); } if ( y[indexWordLo( 4 )] || y[indexWord( 4, 1 )] || (y[indexWord( 4, 2 )] | y[indexWord( 4, 3 )]) ) { q |= 1; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q64 = (uint64_t) q<<28; y[indexWord( 5, 0 )] = q64; q64 = ((uint64_t) qs[0]<<25) + (q64>>32); y[indexWord( 5, 1 )] = q64; q64 = ((uint64_t) qs[1]<<22) + (q64>>32); y[indexWord( 5, 2 )] = q64; q64 = ((uint64_t) qs[2]<<19) + (q64>>32); y[indexWord( 5, 3 )] = q64; y[indexWord( 5, 4 )] = q64>>32; softfloat_roundPackMToF128M( signZ, expZ, y, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidF128M( zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infinity: uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 ); goto uiZ96; zero: uiZ96 = packToF128UI96( signZ, 0, 0 ); uiZ96: zWPtr[indexWordHi( 4 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq.c000066400000000000000000000070101464416617300253220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr ) { return f128_eq( *aPtr, *bPtr ); } #else bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t wordA, wordB, uiA96, uiB96; bool possibleOppositeZeros; uint32_t mashWord; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA != wordB ) goto false_checkSigNaNs; uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; possibleOppositeZeros = false; if ( uiA96 != uiB96 ) { possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0); if ( ! possibleOppositeZeros ) goto false_checkSigNaNs; } mashWord = wordA | wordB; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA != wordB ) goto false_checkSigNaNs; mashWord |= wordA | wordB; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; if ( wordA != wordB ) goto false_checkSigNaNs; if ( possibleOppositeZeros && ((mashWord | wordA | wordB) != 0) ) { goto false_checkSigNaNs; } if ( ! softfloat_isNaNF128M( aWPtr ) && ! softfloat_isNaNF128M( bWPtr ) ) { return true; } false_checkSigNaNs: if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) || f128M_isSignalingNaN( (const float128_t *) bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_eq_signaling.c000066400000000000000000000064311464416617300273630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr ) { return f128_eq_signaling( *aPtr, *bPtr ); } #else bool f128M_eq_signaling( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t wordA, wordB, uiA96, uiB96; bool possibleOppositeZeros; uint32_t mashWord; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA != wordB ) return false; uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; possibleOppositeZeros = false; if ( uiA96 != uiB96 ) { possibleOppositeZeros = (((uiA96 | uiB96) & 0x7FFFFFFF) == 0); if ( ! possibleOppositeZeros ) return false; } mashWord = wordA | wordB; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA != wordB ) return false; mashWord |= wordA | wordB; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return (wordA == wordB) && (! possibleOppositeZeros || ((mashWord | wordA | wordB) == 0)); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le.c000066400000000000000000000064141464416617300253240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool f128M_le( const float128_t *aPtr, const float128_t *bPtr ) { return f128_le( *aPtr, *bPtr ); } #else bool f128M_le( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t uiA96, uiB96; bool signA, signB; uint32_t wordA, wordB; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); signB = signF128UI96( uiB96 ); if ( signA != signB ) { if ( signA ) return true; if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return false; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA | wordB ) return false; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA | wordB ) return false; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return ((wordA | wordB) == 0); } if ( signA ) { aWPtr = (const uint32_t *) bPtr; bWPtr = (const uint32_t *) aPtr; } return (softfloat_compare128M( aWPtr, bWPtr ) <= 0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_le_quiet.c000066400000000000000000000066221464416617300265340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr ) { return f128_le_quiet( *aPtr, *bPtr ); } #else bool f128M_le_quiet( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t uiA96, uiB96; bool signA, signB; uint32_t wordA, wordB; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { if ( f128M_isSignalingNaN( aPtr ) || f128M_isSignalingNaN( bPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); signB = signF128UI96( uiB96 ); if ( signA != signB ) { if ( signA ) return true; if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return false; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA | wordB ) return false; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA | wordB ) return false; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return ((wordA | wordB) == 0); } if ( signA ) { aWPtr = (const uint32_t *) bPtr; bWPtr = (const uint32_t *) aPtr; } return (softfloat_compare128M( aWPtr, bWPtr ) <= 0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt.c000066400000000000000000000064111464416617300253400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr ) { return f128_lt( *aPtr, *bPtr ); } #else bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t uiA96, uiB96; bool signA, signB; uint32_t wordA, wordB; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); signB = signF128UI96( uiB96 ); if ( signA != signB ) { if ( signB ) return false; if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA | wordB ) return true; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA | wordB ) return true; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return ((wordA | wordB) != 0); } if ( signA ) { aWPtr = (const uint32_t *) bPtr; bWPtr = (const uint32_t *) aPtr; } return (softfloat_compare128M( aWPtr, bWPtr ) < 0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_lt_quiet.c000066400000000000000000000066171464416617300265570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 bool f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr ) { return f128_lt_quiet( *aPtr, *bPtr ); } #else bool f128M_lt_quiet( const float128_t *aPtr, const float128_t *bPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t uiA96, uiB96; bool signA, signB; uint32_t wordA, wordB; aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { if ( f128M_isSignalingNaN( aPtr ) || f128M_isSignalingNaN( bPtr ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } uiA96 = aWPtr[indexWordHi( 4 )]; uiB96 = bWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); signB = signF128UI96( uiB96 ); if ( signA != signB ) { if ( signB ) return false; if ( (uiA96 | uiB96) & 0x7FFFFFFF ) return true; wordA = aWPtr[indexWord( 4, 2 )]; wordB = bWPtr[indexWord( 4, 2 )]; if ( wordA | wordB ) return true; wordA = aWPtr[indexWord( 4, 1 )]; wordB = bWPtr[indexWord( 4, 1 )]; if ( wordA | wordB ) return true; wordA = aWPtr[indexWord( 4, 0 )]; wordB = bWPtr[indexWord( 4, 0 )]; return ((wordA | wordB) != 0); } if ( signA ) { aWPtr = (const uint32_t *) bPtr; bWPtr = (const uint32_t *) aPtr; } return (softfloat_compare128M( aWPtr, bWPtr ) < 0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mul.c000066400000000000000000000136031464416617300255170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { *zPtr = f128_mul( *aPtr, *bPtr ); } #else void f128M_mul( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t *zWPtr; uint32_t uiA96; int32_t expA; uint32_t uiB96; int32_t expB; bool signZ; const uint32_t *ptr; uint32_t uiZ96, sigA[4]; uint_fast8_t shiftCount; uint32_t sigB[4]; int32_t expZ; uint32_t sigProd[8], *extSigZPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; expA = expF128UI96( uiA96 ); uiB96 = bWPtr[indexWordHi( 4 )]; expB = expF128UI96( uiB96 ); signZ = signF128UI96( uiA96 ) ^ signF128UI96( uiB96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; ptr = aWPtr; if ( ! expA ) goto possiblyInvalid; if ( ! expB ) { ptr = bWPtr; possiblyInvalid: if ( ! fracF128UI96( ptr[indexWordHi( 4 )] ) && ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )] | ptr[indexWord( 4, 0 )]) ) { softfloat_invalidF128M( zWPtr ); return; } } uiZ96 = packToF128UI96( signZ, 0x7FFF, 0 ); goto uiZ96; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA ) { sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000; sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; } else { expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA ); if ( expA == -128 ) goto zero; } if ( expB ) { sigB[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000; sigB[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )]; sigB[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )]; sigB[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )]; } else { expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigB ); if ( expB == -128 ) goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x4000; softfloat_mul128MTo256M( sigA, sigB, sigProd ); if ( sigProd[indexWord( 8, 2 )] || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) ) { sigProd[indexWord( 8, 3 )] |= 1; } extSigZPtr = &sigProd[indexMultiwordHi( 8, 5 )]; shiftCount = 16; if ( extSigZPtr[indexWordHi( 5 )] & 2 ) { ++expZ; shiftCount = 15; } softfloat_shortShiftLeft160M( extSigZPtr, shiftCount, extSigZPtr ); softfloat_roundPackMToF128M( signZ, expZ, extSigZPtr, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ96 = packToF128UI96( signZ, 0, 0 ); uiZ96: zWPtr[indexWordHi( 4 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_mulAdd.c000066400000000000000000000056511464416617300261340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_mulAdd( const float128_t *aPtr, const float128_t *bPtr, const float128_t *cPtr, float128_t *zPtr ) { const uint64_t *aWPtr, *bWPtr, *cWPtr; uint_fast64_t uiA64, uiA0; uint_fast64_t uiB64, uiB0; uint_fast64_t uiC64, uiC0; aWPtr = (const uint64_t *) aPtr; bWPtr = (const uint64_t *) bPtr; cWPtr = (const uint64_t *) cPtr; uiA64 = aWPtr[indexWord( 2, 1 )]; uiA0 = aWPtr[indexWord( 2, 0 )]; uiB64 = bWPtr[indexWord( 2, 1 )]; uiB0 = bWPtr[indexWord( 2, 0 )]; uiC64 = cWPtr[indexWord( 2, 1 )]; uiC0 = cWPtr[indexWord( 2, 0 )]; *zPtr = softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 ); } #else void f128M_mulAdd( const float128_t *aPtr, const float128_t *bPtr, const float128_t *cPtr, float128_t *zPtr ) { softfloat_mulAddF128M( (const uint32_t *) aPtr, (const uint32_t *) bPtr, (const uint32_t *) cPtr, (uint32_t *) zPtr, 0 ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_rem.c000066400000000000000000000162371464416617300255130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { *zPtr = f128_rem( *aPtr, *bPtr ); } #else void f128M_rem( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { const uint32_t *aWPtr, *bWPtr; uint32_t *zWPtr, uiA96; int32_t expA, expB; uint32_t x[4], rem1[5], *remPtr; bool signRem; int32_t expDiff; uint32_t q, recip32; uint64_t q64; uint32_t rem2[5], *altRemPtr, *newRemPtr, wordMeanRem; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; bWPtr = (const uint32_t *) bPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; expA = expF128UI96( uiA96 ); expB = expF128UI96( bWPtr[indexWordHi( 4 )] ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; if ( expA == 0x7FFF ) goto invalid; goto copyA; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA < expB - 1 ) goto copyA; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expB = softfloat_shiftNormSigF128M( bWPtr, 13, x ); if ( expB == -128 ) goto invalid; remPtr = &rem1[indexMultiwordLo( 5, 4 )]; expA = softfloat_shiftNormSigF128M( aWPtr, 13, remPtr ); if ( expA == -128 ) goto copyA; signRem = signF128UI96( uiA96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( expDiff < 1 ) { if ( expDiff < -1 ) goto copyA; if ( expDiff ) { --expB; softfloat_add128M( x, x, x ); q = 0; } else { q = (softfloat_compare128M( x, remPtr ) <= 0); if ( q ) softfloat_sub128M( remPtr, x, remPtr ); } } else { recip32 = softfloat_approxRecip32_1( ((uint64_t) x[indexWord( 4, 3 )]<<32 | x[indexWord( 4, 2 )]) >>30 ); expDiff -= 30; for (;;) { q64 = (uint64_t) remPtr[indexWordHi( 4 )] * recip32; if ( expDiff < 0 ) break; q = (q64 + 0x80000000)>>32; softfloat_remStep128MBy32( remPtr, 29, x, q, remPtr ); if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) { softfloat_add128M( remPtr, x, remPtr ); } expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -29 here.) *--------------------------------------------------------------------*/ q = (uint32_t) (q64>>32)>>(~expDiff & 31); softfloat_remStep128MBy32( remPtr, expDiff + 30, x, q, remPtr ); if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) { altRemPtr = &rem2[indexMultiwordLo( 5, 4 )]; softfloat_add128M( remPtr, x, altRemPtr ); goto selectRem; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ altRemPtr = &rem2[indexMultiwordLo( 5, 4 )]; do { ++q; newRemPtr = altRemPtr; softfloat_sub128M( remPtr, x, newRemPtr ); altRemPtr = remPtr; remPtr = newRemPtr; } while ( ! (remPtr[indexWordHi( 4 )] & 0x80000000) ); selectRem: softfloat_add128M( remPtr, altRemPtr, x ); wordMeanRem = x[indexWordHi( 4 )]; if ( (wordMeanRem & 0x80000000) || (! wordMeanRem && (q & 1) && ! x[indexWord( 4, 0 )] && ! (x[indexWord( 4, 2 )] | x[indexWord( 4, 1 )])) ) { remPtr = altRemPtr; } if ( remPtr[indexWordHi( 4 )] & 0x80000000 ) { signRem = ! signRem; softfloat_negX128M( remPtr ); } remPtr -= indexMultiwordLo( 5, 4 ); remPtr[indexWordHi( 5 )] = 0; softfloat_normRoundPackMToF128M( signRem, expB + 18, remPtr, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidF128M( zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ copyA: zWPtr[indexWordHi( 4 )] = uiA96; zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_roundToInt.c000066400000000000000000000163441464416617300270340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_roundToInt( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact, float128_t *zPtr ) { *zPtr = f128_roundToInt( *aPtr, roundingMode, exact ); } #else void f128M_roundToInt( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact, float128_t *zPtr ) { const uint32_t *aWPtr; uint32_t *zWPtr; uint32_t ui96; int32_t exp; uint32_t sigExtra; bool sign; uint_fast8_t bitPos; bool roundNear; unsigned int index, lastIndex; bool extra; uint32_t wordA, bit, wordZ; uint_fast8_t carry; uint32_t extrasMask; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ ui96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( ui96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp < 0x3FFF ) { zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; sigExtra = aWPtr[indexWord( 4, 2 )]; if ( ! sigExtra ) { sigExtra = aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]; } if ( ! sigExtra && ! (ui96 & 0x7FFFFFFF) ) goto ui96; if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; sign = signF128UI96( ui96 ); switch ( roundingMode ) { case softfloat_round_near_even: if ( ! fracF128UI96( ui96 ) && ! sigExtra ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FFE ) goto mag1; break; case softfloat_round_min: if ( sign ) goto mag1; break; case softfloat_round_max: if ( ! sign ) goto mag1; break; } ui96 = packToF128UI96( sign, 0, 0 ); goto ui96; mag1: ui96 = packToF128UI96( sign, 0x3FFF, 0 ); goto ui96; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x406F <= exp ) { if ( (exp == 0x7FFF) && (fracF128UI96( ui96 ) || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )])) ) { softfloat_propagateNaNF128M( aWPtr, 0, zWPtr ); return; } zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; goto ui96; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ bitPos = 0x406F - exp; roundNear = (roundingMode == softfloat_round_near_maxMag) || (roundingMode == softfloat_round_near_even); bitPos -= roundNear; index = indexWordLo( 4 ); lastIndex = indexWordHi( 4 ); extra = 0; for (;;) { wordA = aWPtr[index]; if ( bitPos < 32 ) break; if ( wordA ) extra = 1; zWPtr[index] = 0; index += wordIncr; bitPos -= 32; } bit = (uint32_t) 1< #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr ) { *zPtr = f128_sqrt( *aPtr ); } #else void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr ) { const uint32_t *aWPtr; uint32_t *zWPtr; uint32_t uiA96; bool signA; int32_t rawExpA; uint32_t rem[6]; int32_t expA, expZ; uint64_t rem64; uint32_t sig32A, recipSqrt32, sig32Z, qs[3], q; uint64_t sig64Z, x64; uint32_t term[5], y[5], rem32; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; signA = signF128UI96( uiA96 ); rawExpA = expF128UI96( uiA96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( rawExpA == 0x7FFF ) { if ( fracF128UI96( uiA96 ) || (aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) ) { softfloat_propagateNaNF128M( aWPtr, 0, zWPtr ); return; } if ( ! signA ) goto copyA; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = softfloat_shiftNormSigF128M( aWPtr, 13 - (rawExpA & 1), rem ); if ( expA == -128 ) goto copyA; if ( signA ) goto invalid; /*------------------------------------------------------------------------ | (`sig32Z' is guaranteed to be a lower bound on the square root of | `sig32A', which makes `sig32Z' also a lower bound on the square root of | `sigA'.) *------------------------------------------------------------------------*/ expZ = ((expA - 0x3FFF)>>1) + 0x3FFE; expA &= 1; rem64 = (uint64_t) rem[indexWord( 4, 3 )]<<32 | rem[indexWord( 4, 2 )]; if ( expA ) { if ( ! rawExpA ) { softfloat_shortShiftRight128M( rem, 1, rem ); rem64 >>= 1; } sig32A = rem64>>29; } else { sig32A = rem64>>30; } recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; if ( expA ) sig32Z >>= 1; qs[2] = sig32Z; rem64 -= (uint64_t) sig32Z * sig32Z; rem[indexWord( 4, 3 )] = rem64>>32; rem[indexWord( 4, 2 )] = rem64; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32; qs[1] = q; sig64Z = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<3); x64 = ((uint64_t) sig32Z<<32) + sig64Z; term[indexWord( 4, 3 )] = 0; term[indexWord( 4, 2 )] = x64>>32; term[indexWord( 4, 1 )] = x64; term[indexWord( 4, 0 )] = 0; softfloat_remStep128MBy32( rem, 29, term, q, y ); rem64 = (uint64_t) y[indexWord( 4, 3 )]<<32 | y[indexWord( 4, 2 )]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = ((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32; sig64Z <<= 1; /*------------------------------------------------------------------------ | (Repeating this loop is a rare occurrence.) *------------------------------------------------------------------------*/ for (;;) { x64 = sig64Z + (q>>26); term[indexWord( 4, 2 )] = x64>>32; term[indexWord( 4, 1 )] = x64; term[indexWord( 4, 0 )] = q<<6; term[indexWord( 4, 3 )] = 0; softfloat_remStep128MBy32( y, 29, term, q, &rem[indexMultiwordHi( 6, 4 )] ); rem32 = rem[indexWordHi( 6 )]; if ( ! (rem32 & 0x80000000) ) break; --q; } qs[0] = q; rem64 = (uint64_t) rem32<<32 | rem[indexWord( 6, 4 )]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = (((uint32_t) (rem64>>2) * (uint64_t) recipSqrt32)>>32) + 2; x64 = (uint64_t) q<<27; y[indexWord( 5, 0 )] = x64; x64 = ((uint64_t) qs[0]<<24) + (x64>>32); y[indexWord( 5, 1 )] = x64; x64 = ((uint64_t) qs[1]<<21) + (x64>>32); y[indexWord( 5, 2 )] = x64; x64 = ((uint64_t) qs[2]<<18) + (x64>>32); y[indexWord( 5, 3 )] = x64; y[indexWord( 5, 4 )] = x64>>32; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (q & 0xF) <= 2 ) { q &= ~3; y[indexWordLo( 5 )] = q<<27; term[indexWord( 5, 4 )] = 0; term[indexWord( 5, 3 )] = 0; term[indexWord( 5, 2 )] = 0; term[indexWord( 5, 1 )] = q>>6; term[indexWord( 5, 0 )] = q<<26; softfloat_sub160M( y, term, term ); rem[indexWord( 6, 1 )] = 0; rem[indexWord( 6, 0 )] = 0; softfloat_remStep160MBy32( &rem[indexMultiwordLo( 6, 5 )], 14, term, q, &rem[indexMultiwordLo( 6, 5 )] ); rem32 = rem[indexWord( 6, 4 )]; if ( rem32 & 0x80000000 ) { softfloat_sub1X160M( y ); } else { if ( rem32 || rem[indexWord( 6, 0 )] || rem[indexWord( 6, 1 )] || (rem[indexWord( 6, 3 )] | rem[indexWord( 6, 2 )]) ) { y[indexWordLo( 5 )] |= 1; } } } softfloat_roundPackMToF128M( 0, expZ, y, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidF128M( zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ copyA: zWPtr[indexWordHi( 4 )] = uiA96; zWPtr[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_sub.c000066400000000000000000000064071464416617300255170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { const uint64_t *aWPtr, *bWPtr; uint_fast64_t uiA64, uiA0; bool signA; uint_fast64_t uiB64, uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) float128_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); #endif aWPtr = (const uint64_t *) aPtr; bWPtr = (const uint64_t *) bPtr; uiA64 = aWPtr[indexWord( 2, 1 )]; uiA0 = aWPtr[indexWord( 2, 0 )]; signA = signF128UI64( uiA64 ); uiB64 = bWPtr[indexWord( 2, 1 )]; uiB0 = bWPtr[indexWord( 2, 0 )]; signB = signF128UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { *zPtr = softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } else { *zPtr = softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128; *zPtr = (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } #else void f128M_sub( const float128_t *aPtr, const float128_t *bPtr, float128_t *zPtr ) { softfloat_addF128M( (const uint32_t *) aPtr, (const uint32_t *) bPtr, (uint32_t *) zPtr, true ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_extF80M.c000066400000000000000000000075051464416617300266230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr ) { *zPtr = f128_to_extF80( *aPtr ); } #else void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr ) { const uint32_t *aWPtr; struct extFloat80M *zSPtr; uint32_t uiA96; bool sign; int32_t exp; struct commonNaN commonNaN; uint32_t sig[4]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ aWPtr = (const uint32_t *) aPtr; zSPtr = (struct extFloat80M *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp == 0x7FFF ) { if ( softfloat_isNaNF128M( aWPtr ) ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); return; } zSPtr->signExp = packToExtF80UI64( sign, 0x7FFF ); zSPtr->signif = UINT64_C( 0x8000000000000000 ); return; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ exp = softfloat_shiftNormSigF128M( aWPtr, 15, sig ); if ( exp == -128 ) { zSPtr->signExp = packToExtF80UI64( sign, 0 ); zSPtr->signif = 0; return; } if ( sig[indexWord( 4, 0 )] ) sig[indexWord( 4, 1 )] |= 1; softfloat_roundPackMToExtF80M( sign, exp, &sig[indexMultiwordHi( 4, 3 )], 80, zSPtr ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f32.c000066400000000000000000000063541464416617300260230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 float32_t f128M_to_f32( const float128_t *aPtr ) { return f128_to_f32( *aPtr ); } #else float32_t f128M_to_f32( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint64_t sig64; struct commonNaN commonNaN; uint32_t uiZ, sig32; union ui32_f32 uZ; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )] | ((aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); if ( exp == 0x7FFF ) { if ( sig64 ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } sig32 = softfloat_shortShiftRightJam64( sig64, 18 ); if ( ! (exp | sig32) ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } exp -= 0x3F81; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF32( sign, exp, sig32 | 0x40000000 ); uiZ: uZ.ui = uiZ; return uZ.f; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_f64.c000066400000000000000000000065371464416617300260330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 float64_t f128M_to_f64( const float128_t *aPtr ) { return f128_to_f64( *aPtr ); } #else float64_t f128M_to_f64( const float128_t *aPtr ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint64_t sig64; struct commonNaN commonNaN; uint64_t uiZ; uint32_t sig32; union ui64_f64 uZ; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; if ( exp == 0x7FFF ) { if ( sig64 || aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) { softfloat_f128MToCommonNaN( aWPtr, &commonNaN ); uiZ = softfloat_commonNaNToF64UI( &commonNaN ); } else { uiZ = packToF64UI( sign, 0x7FF, 0 ); } goto uiZ; } sig32 = aWPtr[indexWord( 4, 1 )]; sig64 = sig64<<14 | sig32>>18; if ( (sig32 & 0x0003FFFF) || aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; if ( ! exp && ! sig64 ) { uiZ = packToF64UI( sign, 0, 0 ); goto uiZ; } exp -= 0x3C01; if ( sizeof (int_fast16_t) < sizeof (int32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF64( sign, exp, sig64 | UINT64_C( 0x4000000000000000 ) ); uiZ: uZ.ui = uiZ; return uZ.f; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32.c000066400000000000000000000060151464416617300260200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast32_t f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return f128_to_i32( *aPtr, roundingMode, exact ); } #else int_fast32_t f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint64_t sig64; bool notZeroSig0; int32_t shiftCount; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; notZeroSig0 = false; if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) { sig64 |= 1; notZeroSig0 = true; } if ( (exp == 0x7FFF) && (notZeroSig0 || sig64) ) sign = 0; if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); shiftCount = 0x4028 - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i32_r_minMag.c000066400000000000000000000064241464416617300276350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact ) { return f128_to_i32_r_minMag( *aPtr, exact ); } #else int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp; uint64_t sig64; int32_t shiftCount; uint32_t absZ, uiZ; union { uint32_t ui; int32_t i; } uZ; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; if ( exp < 0x3FFF ) { if ( exact && (exp | sig64) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( 0x401F <= exp ) goto invalid; shiftCount = 0x402F - exp; sig64 |= UINT64_C( 0x0001000000000000 ); absZ = sig64>>shiftCount; uiZ = sign ? -absZ : absZ; if ( uiZ>>31 != sign ) goto invalid; if ( exact && ((uint64_t) absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast64_t f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return f128_to_i64( *aPtr, roundingMode, exact ); } #else int_fast64_t f128M_to_i64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp; bool sign; uint32_t sig96; int32_t shiftCount; uint32_t sig[4]; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); sign = signF128UI96( uiA96 ); sig96 = fracF128UI96( uiA96 ); shiftCount = 0x404F - exp; if ( shiftCount < 17 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig96 || ( aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftCount, sig ); return softfloat_roundPackMToI64( sign, sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_i64_r_minMag.c000066400000000000000000000077001464416617300276400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 int_fast64_t f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact ) { return f128_to_i64_r_minMag( *aPtr, exact ); } #else int_fast64_t f128M_to_i64_r_minMag( const float128_t *aPtr, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; bool sign; int32_t exp, shiftCount; uint32_t sig96, sig[4]; uint64_t uiZ; union { uint64_t ui; int64_t i; } uZ; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; sign = signF128UI96( uiA96 ); exp = expF128UI96( uiA96 ); shiftCount = 0x403E - exp; if ( shiftCount < 0 ) goto invalid; if ( exact ) { sig96 = fracF128UI96( uiA96 ); if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftCount + 17, sig ); uiZ = (uint64_t) sig[indexWord( 4, 2 )]<<32 | sig[indexWord( 4, 1 )]; if ( uiZ>>63 && (! sign || (uiZ != UINT64_C( 0x8000000000000000 ))) ) { goto invalid; } if ( sig[indexWordLo( 4 )] ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { if ( 64 <= shiftCount ) return 0; uiZ = (uint64_t) fracF128UI96( uiA96 )<<47 | (uint64_t) aWPtr[indexWord( 4, 2 )]<<15 | aWPtr[indexWord( 4, 1 )]>>17; if ( shiftCount ) { uiZ |= UINT64_C( 0x8000000000000000 ); uiZ >>= shiftCount; } else { if ( uiZ || ! sign ) goto invalid; uiZ |= UINT64_C( 0x8000000000000000 ); } } if ( sign ) uiZ = -uiZ; uZ.ui = uiZ; return uZ.i; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return sign && ! softfloat_isNaNF128M( aWPtr ) ? -UINT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 : UINT64_C( 0x7FFFFFFFFFFFFFFF ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32.c000066400000000000000000000055541464416617300262140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast32_t f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return f128_to_ui32( *aPtr, roundingMode, exact ); } #else uint_fast32_t f128M_to_ui32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp; uint64_t sig64; int32_t shiftCount; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; shiftCount = 0x4028 - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToUI32( signF128UI96( uiA96 ), sig64, roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui32_r_minMag.c000066400000000000000000000061231464416617300300160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact ) { return f128_to_ui32_r_minMag( *aPtr, exact ); } #else uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *aPtr, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp; uint64_t sig64; int32_t shiftCount; uint32_t z; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); sig64 = (uint64_t) fracF128UI96( uiA96 )<<32 | aWPtr[indexWord( 4, 2 )]; if ( aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )] ) sig64 |= 1; shiftCount = 0x402F - exp; if ( 49 <= shiftCount ) { if ( exact && (exp | sig64) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF128UI96( uiA96 ) || (shiftCount < 17) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } sig64 |= UINT64_C( 0x0001000000000000 ); z = sig64>>shiftCount; if ( exact && ((uint64_t) z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { return f128_to_ui64( *aPtr, roundingMode, exact ); } #else uint_fast64_t f128M_to_ui64( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp, shiftCount; uint32_t sig96, sig[4]; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); shiftCount = 0x404F - exp; if ( shiftCount < 17 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sig96 = fracF128UI96( uiA96 ); if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftCount, sig ); return softfloat_roundPackMToUI64( signF128UI96( uiA96 ), sig + indexMultiwordLo( 4, 3 ), roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128M_to_ui64_r_minMag.c000066400000000000000000000070111464416617300300200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact ) { return f128_to_ui64_r_minMag( *aPtr, exact ); } #else uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *aPtr, bool exact ) { const uint32_t *aWPtr; uint32_t uiA96; int32_t exp, shiftCount; uint32_t sig96, sig[4]; uint64_t z; aWPtr = (const uint32_t *) aPtr; uiA96 = aWPtr[indexWordHi( 4 )]; exp = expF128UI96( uiA96 ); shiftCount = 0x403E - exp; if ( shiftCount < 0 ) goto invalid; if ( exact ) { sig96 = fracF128UI96( uiA96 ); if ( exp ) sig96 |= 0x00010000; sig[indexWord( 4, 3 )] = sig96; sig[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sig[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sig[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; softfloat_shiftRightJam128M( sig, shiftCount + 17, sig ); z = (uint64_t) sig[indexWord( 4, 2 )]<<32 | sig[indexWord( 4, 1 )]; if ( signF128UI96( uiA96 ) && z ) goto invalid; if ( sig[indexWordLo( 4 )] ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { if ( 64 <= shiftCount ) return 0; if ( signF128UI96( uiA96 ) ) goto invalid; z = UINT64_C( 0x8000000000000000 ) | (uint64_t) fracF128UI96( uiA96 )<<47 | (uint64_t) aWPtr[indexWord( 4, 2 )]<<15 | aWPtr[indexWord( 4, 1 )]>>17; z >>= shiftCount; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_add.c000066400000000000000000000055651464416617300253450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t f128_add( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) float128_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); #endif uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; signB = signF128UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } else { return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128; return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_div.c000066400000000000000000000172021464416617300253660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f128_div( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; int_fast32_t expA; struct uint128 sigA; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signB; int_fast32_t expB; struct uint128 sigB; bool signZ; struct exp32_sig128 normExpSig; int_fast32_t expZ; struct uint128 rem; uint_fast32_t recip32; int ix; uint_fast64_t q64; uint_fast32_t q; struct uint128 term; uint_fast32_t qs[3]; uint_fast64_t sigZExtra; struct uint128 sigZ, uiZ; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; signB = signF128UI64( uiB64 ); expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 ) goto propagateNaN; if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; goto invalid; } goto infinity; } if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! (sigB.v64 | sigB.v0) ) { if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid; softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! (sigA.v64 | sigA.v0) ) goto zero; normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA - expB + 0x3FFE; sigA.v64 |= UINT64_C( 0x0001000000000000 ); sigB.v64 |= UINT64_C( 0x0001000000000000 ); rem = sigA; if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) { --expZ; rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 ); } recip32 = softfloat_approxRecip32_1( sigB.v64>>17 ); ix = 3; for (;;) { q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32; q = (q64 + 0x80000000)>>32; --ix; if ( ix < 0 ) break; rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { --q; rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); } qs[ix] = q; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ((q + 1) & 7) < 2 ) { rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { --q; rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); } else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) { ++q; rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); } if ( rem.v64 | rem.v0 ) q |= 1; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sigZExtra = (uint64_t) ((uint_fast64_t) q<<60); term = softfloat_shortShiftLeft128( 0, qs[1], 54 ); sigZ = softfloat_add128( (uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4), term.v64, term.v0 ); return softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infinity: uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); goto uiZ0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ.v64 = packToF128UI64( signZ, 0, 0 ); uiZ0: uiZ.v0 = 0; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq.c000066400000000000000000000052531464416617300252140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f128_eq( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return (uiA0 == uiB0) && ( (uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_eq_signaling.c000066400000000000000000000050101464416617300272360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f128_eq_signaling( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } return (uiA0 == uiB0) && ( (uiA64 == uiB64) || (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_isSignalingNaN.c000066400000000000000000000041001464416617300274410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f128_isSignalingNaN( float128_t a ) { union ui128_f128 uA; uA.f = a; return softfloat_isSigNaNF128UI( uA.ui.v64, uA.ui.v0 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_le.c000066400000000000000000000053451464416617300252110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f128_le( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signA, signB; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF128UI64( uiA64 ); signB = signF128UI64( uiB64 ); return (signA != signB) ? signA || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0 | uiB0) : ((uiA64 == uiB64) && (uiA0 == uiB0)) || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_le_quiet.c000066400000000000000000000056301464416617300264150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f128_le_quiet( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signA, signB; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF128UI64( uiA64 ); signB = signF128UI64( uiB64 ); return (signA != signB) ? signA || ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0 | uiB0) : ((uiA64 == uiB64) && (uiA0 == uiB0)) || (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt.c000066400000000000000000000053411464416617300252240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f128_lt( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signA, signB; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF128UI64( uiA64 ); signB = signF128UI64( uiB64 ); return (signA != signB) ? signA && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0 | uiB0) : ((uiA64 != uiB64) || (uiA0 != uiB0)) && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_lt_quiet.c000066400000000000000000000056241464416617300264370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f128_lt_quiet( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signA, signB; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) { if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF128UI64( uiA64 ); signB = signF128UI64( uiB64 ); return (signA != signB) ? signA && (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0 | uiB0) : ((uiA64 != uiB64) || (uiA0 != uiB0)) && (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_mul.c000066400000000000000000000140161464416617300254010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f128_mul( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; int_fast32_t expA; struct uint128 sigA; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signB; int_fast32_t expB; struct uint128 sigB; bool signZ; uint_fast64_t magBits; struct exp32_sig128 normExpSig; int_fast32_t expZ; uint64_t sig256Z[4]; uint_fast64_t sigZExtra; struct uint128 sigZ; struct uint128_extra sig128Extra; struct uint128 uiZ; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; signB = signF128UI64( uiB64 ); expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) ) { goto propagateNaN; } magBits = expB | sigB.v64 | sigB.v0; goto infArg; } if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; magBits = expA | sigA.v64 | sigA.v0; goto infArg; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! (sigA.v64 | sigA.v0) ) goto zero; normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! (sigB.v64 | sigB.v0) ) goto zero; normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x4000; sigA.v64 |= UINT64_C( 0x0001000000000000 ); sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 ); softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z ); sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0); sigZ = softfloat_add128( sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )], sigA.v64, sigA.v0 ); if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) { ++expZ; sig128Extra = softfloat_shortShiftRightJam128Extra( sigZ.v64, sigZ.v0, sigZExtra, 1 ); sigZ = sig128Extra.v; sigZExtra = sig128Extra.extra; } return softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; goto uiZ; } uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); goto uiZ0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ.v64 = packToF128UI64( signZ, 0, 0 ); uiZ0: uiZ.v0 = 0; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_mulAdd.c000066400000000000000000000046041464416617300260140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t f128_mulAdd( float128_t a, float128_t b, float128_t c ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; union ui128_f128 uC; uint_fast64_t uiC64, uiC0; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; uC.f = c; uiC64 = uC.ui.v64; uiC0 = uC.ui.v0; return softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_rem.c000066400000000000000000000165731464416617300254010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f128_rem( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; int_fast32_t expA; struct uint128 sigA; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signB; int_fast32_t expB; struct uint128 sigB; struct exp32_sig128 normExpSig; struct uint128 rem; int_fast32_t expDiff; uint_fast32_t q, recip32; uint_fast64_t q64; struct uint128 term, altRem, meanRem; bool signRem; struct uint128 uiZ; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; signB = signF128UI64( uiB64 ); expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) ) { goto propagateNaN; } goto invalid; } if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; return a; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! (sigB.v64 | sigB.v0) ) goto invalid; normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! (sigA.v64 | sigA.v0) ) return a; normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sigA.v64 |= UINT64_C( 0x0001000000000000 ); sigB.v64 |= UINT64_C( 0x0001000000000000 ); rem = sigA; expDiff = expA - expB; if ( expDiff < 1 ) { if ( expDiff < -1 ) return a; if ( expDiff ) { --expB; sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 ); q = 0; } else { q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ); if ( q ) { rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); } } } else { recip32 = softfloat_approxRecip32_1( sigB.v64>>17 ); expDiff -= 30; for (;;) { q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32; if ( expDiff < 0 ) break; q = (q64 + 0x80000000)>>32; rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); } expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -29 here.) *--------------------------------------------------------------------*/ q = (uint32_t) (q64>>32)>>(~expDiff & 31); rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 ); term = softfloat_mul128By32( sigB.v64, sigB.v0, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); goto selectRem; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ do { altRem = rem; ++q; rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 ); } while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ); selectRem: meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 ); if ( (meanRem.v64 & UINT64_C( 0x8000000000000000 )) || (! (meanRem.v64 | meanRem.v0) && (q & 1)) ) { rem = altRem; } signRem = signA; if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) { signRem = ! signRem; rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 ); } return softfloat_normRoundPackToF128( signRem, expB - 1, rem.v64, rem.v0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_roundToInt.c000066400000000000000000000150321464416617300267100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f128_roundToInt( float128_t a, uint_fast8_t roundingMode, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; int_fast32_t exp; struct uint128 uiZ; uint_fast64_t lastBitMask, roundBitsMask; bool roundNearEven; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; exp = expF128UI64( uiA64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x402F <= exp ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( 0x406F <= exp ) { if ( (exp == 0x7FFF) && (fracF128UI64( uiA64 ) | uiA0) ) { uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 ); goto uiZ; } return a; } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ lastBitMask = (uint_fast64_t) 2<<(0x406E - exp); roundBitsMask = lastBitMask - 1; uiZ.v64 = uiA64; uiZ.v0 = uiA0; roundNearEven = (roundingMode == softfloat_round_near_even); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) ) { if ( exp == 0x402F ) { if ( UINT64_C( 0x8000000000000000 ) <= uiZ.v0 ) { ++uiZ.v64; if ( roundNearEven && (uiZ.v0 == UINT64_C( 0x8000000000000000 )) ) { uiZ.v64 &= ~1; } } } else { uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, lastBitMask>>1 ); if ( roundNearEven && ! (uiZ.v0 & roundBitsMask) ) { uiZ.v0 &= ~lastBitMask; } } } else if ( roundingMode != softfloat_round_minMag ) { if ( signF128UI64( uiZ.v64 ) ^ (roundingMode == softfloat_round_max) ) { uiZ = softfloat_add128( uiZ.v64, uiZ.v0, 0, roundBitsMask ); } } uiZ.v0 &= ~roundBitsMask; } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( exp < 0x3FFF ) { if ( ! ((uiA64 & UINT64_C( 0x7FFFFFFFFFFFFFFF )) | uiA0) ) { return a; } if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; uiZ.v64 = uiA64 & packToF128UI64( 1, 0, 0 ); uiZ.v0 = 0; switch ( roundingMode ) { case softfloat_round_near_even: if ( ! (fracF128UI64( uiA64 ) | uiA0) ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FFE ) uiZ.v64 |= packToF128UI64( 0, 0x3FFF, 0 ); break; case softfloat_round_min: if ( uiZ.v64 ) uiZ.v64 = packToF128UI64( 1, 0x3FFF, 0 ); break; case softfloat_round_max: if ( ! uiZ.v64 ) uiZ.v64 = packToF128UI64( 0, 0x3FFF, 0 ); break; } goto uiZ; } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ uiZ.v64 = uiA64; uiZ.v0 = 0; lastBitMask = (uint_fast64_t) 1<<(0x402F - exp); roundBitsMask = lastBitMask - 1; if ( roundingMode == softfloat_round_near_maxMag ) { uiZ.v64 += lastBitMask>>1; } else if ( roundingMode == softfloat_round_near_even ) { uiZ.v64 += lastBitMask>>1; if ( ! ((uiZ.v64 & roundBitsMask) | uiA0) ) { uiZ.v64 &= ~lastBitMask; } } else if ( roundingMode != softfloat_round_minMag ) { if ( signF128UI64( uiZ.v64 ) ^ (roundingMode == softfloat_round_max) ) { uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask; } } uiZ.v64 &= ~roundBitsMask; } if ( exact && ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_sqrt.c000066400000000000000000000203171464416617300255760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f128_sqrt( float128_t a ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; int_fast32_t expA; struct uint128 sigA, uiZ; struct exp32_sig128 normExpSig; int_fast32_t expZ; uint_fast32_t sig32A, recipSqrt32, sig32Z; struct uint128 rem; uint32_t qs[3]; uint_fast32_t q; uint_fast64_t x64, sig64Z; struct uint128 term, y; uint_fast64_t sigZExtra; struct uint128 sigZ; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 ) { uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, 0, 0 ); goto uiZ; } if ( ! signA ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signA ) { if ( ! (expA | sigA.v64 | sigA.v0) ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! (sigA.v64 | sigA.v0) ) return a; normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ | (`sig32Z' is guaranteed to be a lower bound on the square root of | `sig32A', which makes `sig32Z' also a lower bound on the square root of | `sigA'.) *------------------------------------------------------------------------*/ expZ = ((expA - 0x3FFF)>>1) + 0x3FFE; expA &= 1; sigA.v64 |= UINT64_C( 0x0001000000000000 ); sig32A = sigA.v64>>17; recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; if ( expA ) { sig32Z >>= 1; rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 12 ); } else { rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 13 ); } qs[2] = sig32Z; rem.v64 -= (uint_fast64_t) sig32Z * sig32Z; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = ((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32; qs[1] = q; x64 = (uint_fast64_t) sig32Z<<32; sig64Z = x64 + ((uint_fast64_t) q<<3); x64 += sig64Z; rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); term = softfloat_mul64ByShifted32To128( x64, q ); rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = ((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32; y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 ); sig64Z <<= 1; /*------------------------------------------------------------------------ | (Repeating this loop is a rare occurrence.) *------------------------------------------------------------------------*/ for (;;) { term = softfloat_shortShiftLeft128( 0, sig64Z, 32 ); term = softfloat_add128( term.v64, term.v0, 0, (uint_fast64_t) q<<6 ); term = softfloat_mul128By32( term.v64, term.v0, q ); rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 ); if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break; --q; } qs[0] = q; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ q = (((uint_fast64_t) (uint32_t) (rem.v64>>2) * recipSqrt32)>>32) + 2; sigZExtra = (uint64_t) ((uint_fast64_t) q<<59); term = softfloat_shortShiftLeft128( 0, qs[1], 53 ); sigZ = softfloat_add128( (uint_fast64_t) qs[2]<<18, ((uint_fast64_t) qs[0]<<24) + (q>>5), term.v64, term.v0 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (q & 0xF) <= 2 ) { q &= ~3; sigZExtra = (uint64_t) ((uint_fast64_t) q<<59); y = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, 6 ); y.v0 |= sigZExtra>>58; term = softfloat_sub128( y.v64, y.v0, 0, q ); y = softfloat_mul64ByShifted32To128( term.v0, q ); term = softfloat_mul64ByShifted32To128( term.v64, q ); term = softfloat_add128( term.v64, term.v0, 0, y.v64 ); rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 20 ); term = softfloat_sub128( term.v64, term.v0, rem.v64, rem.v0 ); /*-------------------------------------------------------------------- | The concatenation of `term' and `y.v0' is now the negative remainder | (3 words altogether). *--------------------------------------------------------------------*/ if ( term.v64 & UINT64_C( 0x8000000000000000 ) ) { sigZExtra |= 1; } else { if ( term.v64 | term.v0 | y.v0 ) { if ( sigZExtra ) { --sigZExtra; } else { sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 ); sigZExtra = ~0; } } } } return softfloat_roundPackToF128( 0, expZ, sigZ.v64, sigZ.v0, sigZExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_sub.c000066400000000000000000000055651464416617300254060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t f128_sub( float128_t a, float128_t b ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool signA; union ui128_f128 uB; uint_fast64_t uiB64, uiB0; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) float128_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); #endif uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; signA = signF128UI64( uiA64 ); uB.f = b; uiB64 = uB.ui.v64; uiB0 = uB.ui.v0; signB = signF128UI64( uiB64 ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_subMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } else { return softfloat_addMagsF128( uiA64, uiA0, uiB64, uiB0, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128; return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_extF80.c000066400000000000000000000067721464416617300263760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t f128_to_extF80( float128_t a ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64, sig0; struct commonNaN commonNaN; struct uint128 uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; struct exp32_sig128 normExpSig; struct uint128 sig128; union { struct extFloat80M s; extFloat80_t f; } uZ; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; if ( exp == 0x7FFF ) { if ( sig64 | sig0 ) { softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToExtF80UI( &commonNaN ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; } else { uiZ64 = packToExtF80UI64( sign, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); } goto uiZ; } if ( ! exp ) { if ( ! (sig64 | sig0) ) { uiZ64 = packToExtF80UI64( sign, 0 ); uiZ0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF128Sig( sig64, sig0 ); exp = normExpSig.exp; sig64 = normExpSig.sig.v64; sig0 = normExpSig.sig.v0; } else { sig64 |= UINT64_C( 0x0001000000000000 ); } sig128 = softfloat_shortShiftLeft128( sig64, sig0, 15 ); return softfloat_roundPackToExtF80( sign, exp, sig128.v64, sig128.v0, 80 ); uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f32.c000066400000000000000000000060041464416617300256760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f128_to_f32( float128_t a ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64; struct commonNaN commonNaN; uint_fast32_t uiZ, sig32; union ui32_f32 uZ; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); if ( exp == 0x7FFF ) { if ( sig64 ) { softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } sig32 = softfloat_shortShiftRightJam64( sig64, 18 ); if ( ! (exp | sig32) ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } exp -= 0x3F81; if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF32( sign, exp, sig32 | 0x40000000 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_f64.c000066400000000000000000000062011464416617300257020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f128_to_f64( float128_t a ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64, sig0; struct commonNaN commonNaN; uint_fast64_t uiZ; struct uint128 sig128; union ui64_f64 uZ; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; if ( exp == 0x7FFF ) { if ( sig64 | sig0 ) { softfloat_f128UIToCommonNaN( uiA64, uiA0, &commonNaN ); uiZ = softfloat_commonNaNToF64UI( &commonNaN ); } else { uiZ = packToF64UI( sign, 0x7FF, 0 ); } goto uiZ; } sig128 = softfloat_shortShiftLeft128( sig64, sig0, 14 ); sig64 = sig128.v64 | (sig128.v0 != 0); if ( ! (exp | sig64) ) { uiZ = packToF64UI( sign, 0, 0 ); goto uiZ; } exp -= 0x3C01; if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) { if ( exp < -0x1000 ) exp = -0x1000; } return softfloat_roundPackToF64( sign, exp, sig64 | UINT64_C( 0x4000000000000000 ) ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32.c000066400000000000000000000052411464416617300257030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t f128_to_i32( float128_t a, uint_fast8_t roundingMode, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64, sig0; int_fast32_t shiftCount; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; if ( (exp == 0x7FFF) && (sig64 | sig0) ) sign = 0; if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); sig64 |= (sig0 != 0); shiftCount = 0x4028 - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i32_r_minMag.c000066400000000000000000000063611464416617300275200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t f128_to_i32_r_minMag( float128_t a, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; int_fast32_t exp; uint_fast64_t sig64; int_fast32_t shiftCount; bool sign; int_fast32_t absZ; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); shiftCount = 0x402F - exp; if ( 49 <= shiftCount ) { if ( exact && (exp | sig64) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signF128UI64( uiA64 ); if ( shiftCount < 18 ) { if ( sign && (shiftCount == 17) && (sig64 < UINT64_C( 0x0000000000020000 )) ) { if ( exact && sig64 ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FFF) && sig64) ) return 0x7FFFFFFF; } return -0x7FFFFFFF - 1; } sig64 |= UINT64_C( 0x0001000000000000 ); absZ = sig64>>shiftCount; if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t f128_to_i64( float128_t a, uint_fast8_t roundingMode, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64, sig0; int_fast32_t shiftCount; struct uint128 sig128; struct uint64_extra sigExtra; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; shiftCount = 0x402F - exp; if ( shiftCount <= 0 ) { if ( shiftCount < -15 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FFF) && (sig64 | sig0)) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sig64 |= UINT64_C( 0x0001000000000000 ); if ( shiftCount ) { sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftCount ); sig64 = sig128.v64; sig0 = sig128.v0; } } else { if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftCount ); sig64 = sigExtra.v; sig0 = sigExtra.extra; } return softfloat_roundPackToI64( sign, sig64, sig0, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_i64_r_minMag.c000066400000000000000000000074231464416617300275250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t f128_to_i64_r_minMag( float128_t a, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64, sig0; int_fast32_t shiftCount; int_fast16_t negShiftCount; int_fast64_t absZ; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; shiftCount = 0x402F - exp; if ( shiftCount < 0 ) { if ( shiftCount < -14 ) { if ( (uiA64 == UINT64_C( 0xC03E000000000000 )) && (sig0 < UINT64_C( 0x0002000000000000 )) ) { if ( exact && sig0 ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FFF) && (sig64 | sig0)) ) { return UINT64_C( 0x7FFFFFFFFFFFFFFF ); } } return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sig64 |= UINT64_C( 0x0001000000000000 ); negShiftCount = -shiftCount; absZ = sig64<>(shiftCount & 63); if ( exact && (uint64_t) (sig0<>shiftCount; if ( exact && (sig0 || (absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t f128_to_ui32( float128_t a, uint_fast8_t roundingMode, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp; uint_fast64_t sig64, sig0; int_fast32_t shiftCount; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); sig64 |= (sig0 != 0); shiftCount = 0x4028 - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui32_r_minMag.c000066400000000000000000000055061464416617300277050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t f128_to_ui32_r_minMag( float128_t a, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; int_fast32_t exp; uint_fast64_t sig64; int_fast32_t shiftCount; uint_fast32_t z; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; exp = expF128UI64( uiA64 ); sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0); shiftCount = 0x402F - exp; if ( 49 <= shiftCount ) { if ( exact && (exp | sig64) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF128UI64( uiA64 ) || (shiftCount < 17) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } sig64 |= UINT64_C( 0x0001000000000000 ); z = sig64>>shiftCount; if ( exact && ((uint_fast64_t) z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t f128_to_ui64( float128_t a, uint_fast8_t roundingMode, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; bool sign; int_fast32_t exp, shiftCount; uint_fast64_t sig64, sig0; struct uint128 sig128; struct uint64_extra sigExtra; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; sign = signF128UI64( uiA64 ); exp = expF128UI64( uiA64 ); shiftCount = 0x402F - exp; if ( shiftCount <= 0 ) { if ( shiftCount < -15 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sig64 = fracF128UI64( uiA64 ) | UINT64_C( 0x0001000000000000 ); sig0 = uiA0; if ( shiftCount ) { sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftCount ); sig64 = sig128.v64; sig0 = sig128.v0; } } else { sig64 = fracF128UI64( uiA64 ); sig0 = uiA0; if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 ); sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftCount ); sig64 = sigExtra.v; sig0 = sigExtra.extra; } return softfloat_roundPackToUI64( sign, sig64, sig0, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f128_to_ui64_r_minMag.c000066400000000000000000000065311464416617300277110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t f128_to_ui64_r_minMag( float128_t a, bool exact ) { union ui128_f128 uA; uint_fast64_t uiA64, uiA0; int_fast32_t exp, shiftCount; uint_fast64_t sig64, sig0; int_fast16_t negShiftCount; uint_fast64_t z; uA.f = a; uiA64 = uA.ui.v64; uiA0 = uA.ui.v0; exp = expF128UI64( uiA64 ); shiftCount = 0x402F - exp; if ( shiftCount < 0 ) { if ( signF128UI64( uiA64 ) || (shiftCount < -15) ) goto invalid; sig64 = fracF128UI64( uiA64 ) | UINT64_C( 0x0001000000000000 ); sig0 = uiA0; negShiftCount = -shiftCount; z = sig64<>(shiftCount & 63); if ( exact && (uint64_t) (sig0<>shiftCount; if ( exact && (sig0 || (z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t f32_add( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; union ui32_f32 uB; uint_fast32_t uiB; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1) float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t, bool ); #endif uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF32UI( uiB ); #if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_addMagsF32( uiA, uiB, signA ); } else { return softfloat_subMagsF32( uiA, uiB, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_addMagsF32 : softfloat_subMagsF32; return (*magsFuncPtr)( uiA, uiB, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_div.c000066400000000000000000000143341464416617300253030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f32_div( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; int_fast16_t expA; uint_fast32_t sigA; union ui32_f32 uB; uint_fast32_t uiB; bool signB; int_fast16_t expB; uint_fast32_t sigB; bool signZ; struct exp16_sig32 normExpSig; int_fast16_t expZ; #ifdef SOFTFLOAT_FAST_DIV64TO32 uint_fast64_t sig64A; uint_fast32_t sigZ; #else uint_fast32_t sigZ; uint_fast64_t rem; #endif uint_fast32_t uiZ; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF32UI( uiB ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0xFF ) { if ( sigA ) goto propagateNaN; if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; goto invalid; } goto infinity; } if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! sigB ) { if ( ! (expA | sigA) ) goto invalid; softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } normExpSig = softfloat_normSubnormalF32Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA - expB + 0x7E; sigA |= 0x00800000; sigB |= 0x00800000; #ifdef SOFTFLOAT_FAST_DIV64TO32 if ( sigA < sigB ) { --expZ; sig64A = (uint_fast64_t) sigA<<31; } else { sig64A = (uint_fast64_t) sigA<<30; } sigZ = sig64A / sigB; if ( ! (sigZ & 0x3F) ) sigZ |= ((uint_fast64_t) sigB * sigZ != sig64A); #else if ( sigA < sigB ) { --expZ; sigA <<= 8; } else { sigA <<= 7; } sigB <<= 8; sigZ = ((uint_fast64_t) sigA * softfloat_approxRecip32_1( sigB ))>>32; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ sigZ += 2; if ( (sigZ & 0x3F) < 2 ) { sigZ &= ~3; #ifdef SOFTFLOAT_FAST_INT64 rem = ((uint_fast64_t) sigA<<31) - (uint_fast64_t) sigZ * sigB; #else rem = ((uint_fast64_t) sigA<<32) - (uint_fast64_t) (sigZ<<1) * sigB; #endif if ( rem & UINT64_C( 0x8000000000000000 ) ) { sigZ -= 4; } else { if ( rem ) sigZ |= 1; } } #endif return softfloat_roundPackToF32( signZ, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infinity: uiZ = packToF32UI( signZ, 0xFF, 0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ = packToF32UI( signZ, 0, 0 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq.c000066400000000000000000000047001464416617300251220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f32_eq( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_eq_signaling.c000066400000000000000000000044761464416617300271670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f32_eq_signaling( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } return (uiA == uiB) || ! (uint32_t) ((uiA | uiB)<<1); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_isSignalingNaN.c000066400000000000000000000040551464416617300273640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f32_isSignalingNaN( float32_t a ) { union ui32_f32 uA; uA.f = a; return softfloat_isSigNaNF32UI( uA.ui ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_le.c000066400000000000000000000047171464416617300251250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f32_le( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF32UI( uiA ); signB = signF32UI( uiB ); return (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1) : (uiA == uiB) || (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_le_quiet.c000066400000000000000000000051411464416617300263240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f32_le_quiet( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF32UI( uiA ); signB = signF32UI( uiB ); return (signA != signB) ? signA || ! (uint32_t) ((uiA | uiB)<<1) : (uiA == uiB) || (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt.c000066400000000000000000000047241464416617300251420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f32_lt( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF32UI( uiA ); signB = signF32UI( uiB ); return (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0) : (uiA != uiB) && (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_lt_quiet.c000066400000000000000000000051461464416617300263500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f32_lt_quiet( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF32UI( uiA ) || isNaNF32UI( uiB ) ) { if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF32UI( uiA ); signB = signF32UI( uiB ); return (signA != signB) ? signA && ((uint32_t) ((uiA | uiB)<<1) != 0) : (uiA != uiB) && (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_mul.c000066400000000000000000000076201464416617300253160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f32_mul( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; int_fast16_t expA; uint_fast32_t sigA; union ui32_f32 uB; uint_fast32_t uiB; bool signB; int_fast16_t expB; uint_fast32_t sigB; bool signZ; uint_fast32_t magBits; struct exp16_sig32 normExpSig; int_fast16_t expZ; uint_fast32_t sigZ, uiZ; union ui32_f32 uZ; uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF32UI( uiB ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); signZ = signA ^ signB; if ( expA == 0xFF ) { if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN; magBits = expB | sigB; goto infArg; } if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; magBits = expA | sigA; goto infArg; } if ( ! expA ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zero; normExpSig = softfloat_normSubnormalF32Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } expZ = expA + expB - 0x7F; sigA = (sigA | 0x00800000)<<7; sigB = (sigB | 0x00800000)<<8; sigZ = softfloat_shortShiftRightJam64( (uint_fast64_t) sigA * sigB, 32 ); if ( sigZ < 0x40000000 ) { --expZ; sigZ <<= 1; } return softfloat_roundPackToF32( signZ, expZ, sigZ ); propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); goto uiZ; infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; } else { uiZ = packToF32UI( signZ, 0xFF, 0 ); } goto uiZ; zero: uiZ = packToF32UI( signZ, 0, 0 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_mulAdd.c000066400000000000000000000043641464416617300257310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c ) { union ui32_f32 uA; uint_fast32_t uiA; union ui32_f32 uB; uint_fast32_t uiB; union ui32_f32 uC; uint_fast32_t uiC; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; uC.f = c; uiC = uC.ui; return softfloat_mulAddF32( uiA, uiB, uiC, 0 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_rem.c000066400000000000000000000143261464416617300253050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f32_rem( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; int_fast16_t expA; uint_fast32_t sigA; union ui32_f32 uB; uint_fast32_t uiB; int_fast16_t expB; uint_fast32_t sigB; struct exp16_sig32 normExpSig; uint32_t rem; int_fast16_t expDiff; uint32_t q, recip32, altRem, meanRem; bool signRem; uint_fast32_t uiZ; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); uB.f = b; uiB = uB.ui; expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0xFF ) { if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN; goto invalid; } if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; return a; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! sigB ) goto invalid; normExpSig = softfloat_normSubnormalF32Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! sigA ) return a; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ rem = sigA | 0x00800000; sigB |= 0x00800000; expDiff = expA - expB; if ( expDiff < 1 ) { if ( expDiff < -1 ) return a; sigB <<= 6; if ( expDiff ) { rem <<= 5; q = 0; } else { rem <<= 6; q = (sigB <= rem); if ( q ) rem -= sigB; } } else { recip32 = softfloat_approxRecip32_1( sigB<<8 ); /*-------------------------------------------------------------------- | Changing the shift of `rem' here requires also changing the initial | subtraction from `expDiff'. *--------------------------------------------------------------------*/ rem <<= 7; expDiff -= 31; /*-------------------------------------------------------------------- | The scale of `sigB' affects how many bits are obtained during each | cycle of the loop. Currently this is 29 bits per loop iteration, | which is believed to be the maximum possible. *--------------------------------------------------------------------*/ sigB <<= 6; for (;;) { q = (rem * (uint_fast64_t) recip32)>>32; if ( expDiff < 0 ) break; rem = -(q * (uint32_t) sigB); expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -30 here.) *--------------------------------------------------------------------*/ q >>= ~expDiff & 31; rem = (rem<<(expDiff + 30)) - q * (uint32_t) sigB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ do { altRem = rem; ++q; rem -= sigB; } while ( ! (rem & 0x80000000) ); meanRem = rem + altRem; if ( (meanRem & 0x80000000) || (! meanRem && (q & 1)) ) rem = altRem; signRem = signA; if ( 0x80000000 <= rem ) { signRem = ! signRem; rem = -rem; } return softfloat_normRoundPackToF32( signRem, expB, rem ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); goto uiZ; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_roundToInt.c000066400000000000000000000106031464416617300266210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f32_roundToInt( float32_t a, uint_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; int_fast16_t exp; uint_fast32_t uiZ, lastBitMask, roundBitsMask; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; exp = expF32UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp <= 0x7E ) { if ( ! (uint32_t) (uiA<<1) ) return a; if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; uiZ = uiA & packToF32UI( 1, 0, 0 ); switch ( roundingMode ) { case softfloat_round_near_even: if ( ! fracF32UI( uiA ) ) break; case softfloat_round_near_maxMag: if ( exp == 0x7E ) uiZ |= packToF32UI( 0, 0x7F, 0 ); break; case softfloat_round_min: if ( uiZ ) uiZ = packToF32UI( 1, 0x7F, 0 ); break; case softfloat_round_max: if ( ! uiZ ) uiZ = packToF32UI( 0, 0x7F, 0 ); break; } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x96 <= exp ) { if ( (exp == 0xFF) && fracF32UI( uiA ) ) { uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); goto uiZ; } return a; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ = uiA; lastBitMask = (uint_fast32_t) 1<<(0x96 - exp); roundBitsMask = lastBitMask - 1; if ( roundingMode == softfloat_round_near_maxMag ) { uiZ += lastBitMask>>1; } else if ( roundingMode == softfloat_round_near_even ) { uiZ += lastBitMask>>1; if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask; } else if ( roundingMode != softfloat_round_minMag ) { if ( signF32UI( uiZ ) ^ (roundingMode == softfloat_round_max) ) { uiZ += roundBitsMask; } } uiZ &= ~roundBitsMask; if ( exact && (uiZ != uiA) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_sqrt.c000066400000000000000000000110661464416617300255110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f32_sqrt( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; int_fast16_t expA; uint_fast32_t sigA, uiZ; struct exp16_sig32 normExpSig; int_fast16_t expZ; uint_fast32_t sigZ, shiftedSigZ; uint32_t negRem; union ui32_f32 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0xFF ) { if ( sigA ) { uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); goto uiZ; } if ( ! signA ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signA ) { if ( ! (expA | sigA) ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) return a; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = ((expA - 0x7F)>>1) + 0x7E; expA &= 1; sigA = (sigA | 0x00800000)<<8; sigZ = ((uint_fast64_t) sigA * softfloat_approxRecipSqrt32_1( expA, sigA )) >>32; if ( expA ) sigZ >>= 1; sigZ += 2; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (sigZ & 0x3F) < 2 ) { shiftedSigZ = sigZ>>2; negRem = shiftedSigZ * shiftedSigZ; sigZ = shiftedSigZ<<2; if ( negRem & 0x80000000 ) { sigZ |= 1; } else { if ( negRem ) --sigZ; } } return softfloat_roundPackToF32( 0, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_sub.c000066400000000000000000000052641464416617300253140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t f32_sub( float32_t a, float32_t b ) { union ui32_f32 uA; uint_fast32_t uiA; bool signA; union ui32_f32 uB; uint_fast32_t uiB; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 1) float32_t (*magsFuncPtr)( uint_fast32_t, uint_fast32_t, bool ); #endif uA.f = a; uiA = uA.ui; signA = signF32UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF32UI( uiB ); #if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_subMagsF32( uiA, uiB, signA ); } else { return softfloat_addMagsF32( uiA, uiB, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_subMagsF32 : softfloat_addMagsF32; return (*magsFuncPtr)( uiA, uiB, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80.c000066400000000000000000000063241464416617300263010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t f32_to_extF80( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; struct commonNaN commonNaN; struct uint128 uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; struct exp16_sig32 normExpSig; union { struct extFloat80M s; extFloat80_t f; } uZ; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( exp == 0xFF ) { if ( sig ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToExtF80UI( &commonNaN ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; } else { uiZ64 = packToExtF80UI64( sign, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ64 = packToExtF80UI64( sign, 0 ); uiZ0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF32Sig( sig ); exp = normExpSig.exp; sig = normExpSig.sig; } uiZ64 = packToExtF80UI64( sign, exp + 0x3F80 ); uiZ0 = (uint_fast64_t) (sig | 0x00800000)<<40; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_extF80M.c000066400000000000000000000064261464416617300264210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f32_to_extF80M( float32_t a, extFloat80_t *zPtr ) { *zPtr = f32_to_extF80( a ); } #else void f32_to_extF80M( float32_t a, extFloat80_t *zPtr ) { struct extFloat80M *zSPtr; union ui32_f32 uA; uint32_t uiA; bool sign; int_fast16_t exp; uint32_t sig; struct commonNaN commonNaN; uint_fast16_t uiZ64; uint64_t uiZ0; struct exp16_sig32 normExpSig; zSPtr = (struct extFloat80M *) zPtr; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( exp == 0xFF ) { if ( sig ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); return; } uiZ64 = packToExtF80UI64( sign, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ64 = packToExtF80UI64( sign, 0 ); uiZ0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF32Sig( sig ); exp = normExpSig.exp; sig = normExpSig.sig; } uiZ64 = packToExtF80UI64( sign, exp + 0x3F80 ); uiZ0 = UINT64_C( 0x8000000000000000 ) | (uint64_t) sig<<40; uiZ: zSPtr->signExp = uiZ64; zSPtr->signif = uiZ0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128.c000066400000000000000000000060121464416617300256750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f32_to_f128( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; struct commonNaN commonNaN; struct uint128 uiZ; struct exp16_sig32 normExpSig; union ui128_f128 uZ; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( exp == 0xFF ) { if ( sig ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ.v0 = 0; } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ.v64 = packToF128UI64( sign, 0, 0 ); uiZ.v0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF32Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) sig<<25 ); uiZ.v0 = 0; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f128M.c000066400000000000000000000064331464416617300260210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f32_to_f128M( float32_t a, float128_t *zPtr ) { *zPtr = f32_to_f128( a ); } #else void f32_to_f128M( float32_t a, float128_t *zPtr ) { uint32_t *zWPtr; union ui32_f32 uA; uint32_t uiA; bool sign; int_fast16_t exp; uint32_t sig, uiZ64; struct commonNaN commonNaN; uint32_t uiZ96; struct exp16_sig32 normExpSig; uint64_t sig64; zWPtr = (uint32_t *) zPtr; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); uiZ64 = 0; if ( exp == 0xFF ) { if ( sig ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); softfloat_commonNaNToF128M( &commonNaN, zWPtr ); return; } uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ96 = packToF128UI96( sign, 0, 0 ); goto uiZ; } normExpSig = softfloat_normSubnormalF32Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } sig64 = (uint64_t) sig<<25; uiZ96 = packToF128UI96( sign, exp + 0x3F80, sig64>>32 ); uiZ64 = sig64; uiZ: zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = uiZ64; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_f64.c000066400000000000000000000056521464416617300256250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f32_to_f64( float32_t a ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; struct commonNaN commonNaN; uint_fast64_t uiZ; struct exp16_sig32 normExpSig; union ui64_f64 uZ; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( exp == 0xFF ) { if ( sig ) { softfloat_f32UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF64UI( &commonNaN ); } else { uiZ = packToF64UI( sign, 0x7FF, 0 ); } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ = packToF64UI( sign, 0, 0 ); goto uiZ; } normExpSig = softfloat_normSubnormalF32Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) sig<<29 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32.c000066400000000000000000000051141464416617300256140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t f32_to_i32( float32_t a, uint_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; uint_fast64_t sig64; int_fast16_t shiftCount; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( (exp == 0xFF) && sig ) sign = 0; if ( exp ) sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<32; shiftCount = 0xAF - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i32_r_minMag.c000066400000000000000000000056411464416617300274320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; bool sign; int_fast32_t absZ; uA.f = a; uiA = uA.ui; exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0x9E - exp; if ( 32 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signF32UI( uiA ); if ( shiftCount <= 0 ) { if ( uiA != packToF32UI( 1, 0x9E, 0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0xFF) && sig) ) return 0x7FFFFFFF; } return -0x7FFFFFFF - 1; } sig = (sig | 0x00800000)<<8; absZ = sig>>shiftCount; if ( exact && ((uint_fast32_t) absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t f32_to_i64( float32_t a, uint_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t sig64, extra; struct uint64_extra sig64Extra; #else uint32_t extSig[3]; #endif uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0xFF) && sig) ) { return INT64_C( 0x7FFFFFFFFFFFFFFF ); } return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } if ( exp ) sig |= 0x00800000; #ifdef SOFTFLOAT_FAST_INT64 sig64 = (uint_fast64_t) sig<<40; extra = 0; if ( shiftCount ) { sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftCount ); sig64 = sig64Extra.v; extra = sig64Extra.extra; } return softfloat_roundPackToI64( sign, sig64, extra, roundingMode, exact ); #else extSig[indexWord( 3, 2 )] = sig<<8; extSig[indexWord( 3, 1 )] = 0; extSig[indexWord( 3, 0 )] = 0; if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); return softfloat_roundPackMToI64( sign, extSig, roundingMode, exact ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_i64_r_minMag.c000066400000000000000000000061151464416617300274340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; bool sign; uint_fast64_t sig64; int_fast64_t absZ; uA.f = a; uiA = uA.ui; exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signF32UI( uiA ); if ( shiftCount <= 0 ) { if ( uiA != packToF32UI( 1, 0xBE, 0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0xFF) && sig) ) { return INT64_C( 0x7FFFFFFFFFFFFFFF ); } } return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<40; absZ = sig64>>shiftCount; shiftCount = 40 - shiftCount; if ( exact && (shiftCount < 0) && (uint32_t) (sig<<(shiftCount & 31)) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return sign ? -absZ : absZ; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32.c000066400000000000000000000050451464416617300260040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t f32_to_ui32( float32_t a, uint_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; uint_fast64_t sig64; int_fast16_t shiftCount; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); if ( exp ) sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<32; shiftCount = 0xAF - exp; if ( 0 < shiftCount ) { sig64 = softfloat_shiftRightJam64( sig64, shiftCount ); } return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui32_r_minMag.c000066400000000000000000000053361464416617300276200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; uint_fast32_t z; uA.f = a; uiA = uA.ui; exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0x9E - exp; if ( 32 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF32UI( uiA ) || (shiftCount < 0) ) goto invalid; sig = (sig | 0x00800000)<<8; z = sig>>shiftCount; if ( exact && (z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; bool sign; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; uint_fast64_t sig64, extra; struct uint64_extra sig64Extra; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } if ( exp ) sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<40; extra = 0; if ( shiftCount ) { sig64Extra = softfloat_shiftRightJam64Extra( sig64, 0, shiftCount ); sig64 = sig64Extra.v; extra = sig64Extra.extra; } return softfloat_roundPackToUI64( sign, sig64, extra, roundingMode, exact ); } #else uint_fast64_t f32_to_ui64( float32_t a, uint_fast8_t roundingMode, bool exact ) { union ui32_f32 uA; uint32_t uiA; bool sign; int_fast16_t exp; uint32_t sig; int_fast16_t shiftCount; uint32_t extSig[3]; uA.f = a; uiA = uA.ui; sign = signF32UI( uiA ); exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( shiftCount < 0 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } if ( exp ) sig |= 0x00800000; extSig[indexWord( 3, 2 )] = sig<<8; extSig[indexWord( 3, 1 )] = 0; extSig[indexWord( 3, 0 )] = 0; if ( shiftCount ) softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f32_to_ui64_r_minMag.c000066400000000000000000000055311464416617300276220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact ) { union ui32_f32 uA; uint_fast32_t uiA; int_fast16_t exp; uint_fast32_t sig; int_fast16_t shiftCount; uint_fast64_t sig64, z; uA.f = a; uiA = uA.ui; exp = expF32UI( uiA ); sig = fracF32UI( uiA ); shiftCount = 0xBE - exp; if ( 64 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF32UI( uiA ) || (shiftCount < 0) ) goto invalid; sig |= 0x00800000; sig64 = (uint_fast64_t) sig<<40; z = sig64>>shiftCount; shiftCount = 40 - shiftCount; if ( exact && (shiftCount < 0) && (uint32_t) (sig<<(shiftCount & 31)) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_add.c000066400000000000000000000052641464416617300252600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t f64_add( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; bool signA; union ui64_f64 uB; uint_fast64_t uiB; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool ); #endif uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF64UI( uiB ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_addMagsF64( uiA, uiB, signA ); } else { return softfloat_subMagsF64( uiA, uiB, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_addMagsF64 : softfloat_subMagsF64; return (*magsFuncPtr)( uiA, uiB, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_div.c000066400000000000000000000145041464416617300253070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f64_div( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; bool signA; int_fast16_t expA; uint_fast64_t sigA; union ui64_f64 uB; uint_fast64_t uiB; bool signB; int_fast16_t expB; uint_fast64_t sigB; bool signZ; struct exp16_sig64 normExpSig; int_fast16_t expZ; uint32_t recip32, sig32Z, doubleTerm; uint_fast64_t rem; uint32_t q; uint_fast64_t sigZ; uint_fast64_t uiZ; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF64UI( uiB ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA ) goto propagateNaN; if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN; goto invalid; } goto infinity; } if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN; goto zero; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! sigB ) { if ( ! (expA | sigA) ) goto invalid; softfloat_raiseFlags( softfloat_flag_infinite ); goto infinity; } normExpSig = softfloat_normSubnormalF64Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA - expB + 0x3FE; sigA |= UINT64_C( 0x0010000000000000 ); sigB |= UINT64_C( 0x0010000000000000 ); if ( sigA < sigB ) { --expZ; sigA <<= 11; } else { sigA <<= 10; } sigB <<= 11; recip32 = softfloat_approxRecip32_1( sigB>>32 ) - 2; sig32Z = ((uint32_t) (sigA>>32) * (uint_fast64_t) recip32)>>32; doubleTerm = sig32Z<<1; rem = ((sigA - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); q = (((uint32_t) (rem>>32) * (uint_fast64_t) recip32)>>32) + 4; sigZ = ((uint_fast64_t) sig32Z<<32) + ((uint_fast64_t) q<<4); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (sigZ & 0x1FF) < 4<<4 ) { q &= ~7; sigZ &= ~(uint_fast64_t) 0x7F; doubleTerm = q<<1; rem = ((rem - (uint_fast64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) - (uint_fast64_t) doubleTerm * ((uint32_t) sigB>>4); if ( rem & UINT64_C( 0x8000000000000000 ) ) { sigZ -= 1<<7; } else { if ( rem ) sigZ |= 1; } } return softfloat_roundPackToF64( signZ, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infinity: uiZ = packToF64UI( signZ, 0x7FF, 0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ = packToF64UI( signZ, 0, 0 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq.c000066400000000000000000000047231464416617300251340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f64_eq( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_eq_signaling.c000066400000000000000000000045211464416617300271630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f64_eq_signaling( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } return (uiA == uiB) || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_isSignalingNaN.c000066400000000000000000000040551464416617300273710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f64_isSignalingNaN( float64_t a ) { union ui64_f64 uA; uA.f = a; return softfloat_isSigNaNF64UI( uA.ui ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_le.c000066400000000000000000000047561464416617300251350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f64_le( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF64UI( uiA ); signB = signF64UI( uiB ); return (signA != signB) ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) : (uiA == uiB) || (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_le_quiet.c000066400000000000000000000052001464416617300263250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f64_le_quiet( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF64UI( uiA ); signB = signF64UI( uiB ); return (signA != signB) ? signA || ! ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) : (uiA == uiB) || (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt.c000066400000000000000000000047541464416617300251520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" bool f64_lt( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return false; } signA = signF64UI( uiA ); signB = signF64UI( uiB ); return (signA != signB) ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) : (uiA != uiB) && (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_lt_quiet.c000066400000000000000000000051761464416617300263600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" bool f64_lt_quiet( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; bool signA, signB; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; if ( isNaNF64UI( uiA ) || isNaNF64UI( uiB ) ) { if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); } return false; } signA = signF64UI( uiA ); signB = signF64UI( uiB ); return (signA != signB) ? signA && ((uiA | uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF )) : (uiA != uiB) && (signA ^ (uiA < uiB)); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_mul.c000066400000000000000000000126371464416617300253270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f64_mul( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; bool signA; int_fast16_t expA; uint_fast64_t sigA; union ui64_f64 uB; uint_fast64_t uiB; bool signB; int_fast16_t expB; uint_fast64_t sigB; bool signZ; uint_fast64_t magBits; struct exp16_sig64 normExpSig; int_fast16_t expZ; #ifdef SOFTFLOAT_FAST_INT64 struct uint128 sig128Z; #else uint32_t sig128Z[4]; #endif uint_fast64_t sigZ, uiZ; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF64UI( uiB ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); signZ = signA ^ signB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; magBits = expB | sigB; goto infArg; } if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN; magBits = expA | sigA; goto infArg; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) goto zero; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zero; normExpSig = softfloat_normSubnormalF64Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FF; sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; #ifdef SOFTFLOAT_FAST_INT64 sig128Z = softfloat_mul64To128( sigA, sigB ); sigZ = sig128Z.v64 | (sig128Z.v0 != 0); #else softfloat_mul64To128M( sigA, sigB, sig128Z ); sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; #endif if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { --expZ; sigZ <<= 1; } return softfloat_roundPackToF64( signZ, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infArg: if ( ! magBits ) { softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; } else { uiZ = packToF64UI( signZ, 0x7FF, 0 ); } goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zero: uiZ = packToF64UI( signZ, 0, 0 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_mulAdd.c000066400000000000000000000043641464416617300257360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c ) { union ui64_f64 uA; uint_fast64_t uiA; union ui64_f64 uB; uint_fast64_t uiB; union ui64_f64 uC; uint_fast64_t uiC; uA.f = a; uiA = uA.ui; uB.f = b; uiB = uB.ui; uC.f = c; uiC = uC.ui; return softfloat_mulAddF64( uiA, uiB, uiC, 0 ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_rem.c000066400000000000000000000156741464416617300253210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f64_rem( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; bool signA; int_fast16_t expA; uint_fast64_t sigA; union ui64_f64 uB; uint_fast64_t uiB; int_fast16_t expB; uint_fast64_t sigB; struct exp16_sig64 normExpSig; uint64_t rem; int_fast16_t expDiff; uint32_t q, recip32; uint_fast64_t q64; uint64_t altRem, meanRem; bool signRem; uint_fast64_t uiZ; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); uB.f = b; uiB = uB.ui; expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN; goto invalid; } if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN; return a; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA < expB - 1 ) return a; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expB ) { if ( ! sigB ) goto invalid; normExpSig = softfloat_normSubnormalF64Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } if ( ! expA ) { if ( ! sigA ) return a; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ rem = sigA | UINT64_C( 0x0010000000000000 ); sigB |= UINT64_C( 0x0010000000000000 ); expDiff = expA - expB; if ( expDiff < 1 ) { if ( expDiff < -1 ) return a; sigB <<= 9; if ( expDiff ) { rem <<= 8; q = 0; } else { rem <<= 9; q = (sigB <= rem); if ( q ) rem -= sigB; } } else { recip32 = softfloat_approxRecip32_1( sigB>>21 ); /*-------------------------------------------------------------------- | Changing the shift of `rem' here requires also changing the initial | subtraction from `expDiff'. *--------------------------------------------------------------------*/ rem <<= 9; expDiff -= 30; /*-------------------------------------------------------------------- | The scale of `sigB' affects how many bits are obtained during each | cycle of the loop. Currently this is 29 bits per loop iteration, | the maximum possible. *--------------------------------------------------------------------*/ sigB <<= 9; for (;;) { q64 = (uint32_t) (rem>>32) * (uint_fast64_t) recip32; if ( expDiff < 0 ) break; q = (q64 + 0x80000000)>>32; #ifdef SOFTFLOAT_FAST_INT64 rem <<= 29; #else rem = (uint_fast64_t) (uint32_t) (rem>>3)<<32; #endif rem -= q * (uint64_t) sigB; if ( rem & UINT64_C( 0x8000000000000000 ) ) rem += sigB; expDiff -= 29; } /*-------------------------------------------------------------------- | (`expDiff' cannot be less than -29 here.) *--------------------------------------------------------------------*/ q = (uint32_t) (q64>>32)>>(~expDiff & 31); rem = (rem<<(expDiff + 30)) - q * (uint64_t) sigB; if ( rem & UINT64_C( 0x8000000000000000 ) ) { altRem = rem + sigB; goto selectRem; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ do { altRem = rem; ++q; rem -= sigB; } while ( ! (rem & UINT64_C( 0x8000000000000000 )) ); selectRem: meanRem = rem + altRem; if ( (meanRem & UINT64_C( 0x8000000000000000 )) || (! meanRem && (q & 1)) ) { rem = altRem; } signRem = signA; if ( rem & UINT64_C( 0x8000000000000000 ) ) { signRem = ! signRem; rem = -rem; } return softfloat_normRoundPackToF64( signRem, expB, rem ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); goto uiZ; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_roundToInt.c000066400000000000000000000106361464416617300266340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; int_fast16_t exp; uint_fast64_t uiZ, lastBitMask, roundBitsMask; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; exp = expF64UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( exp <= 0x3FE ) { if ( ! (uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) return a; if ( exact ) softfloat_exceptionFlags |= softfloat_flag_inexact; uiZ = uiA & packToF64UI( 1, 0, 0 ); switch ( roundingMode ) { case softfloat_round_near_even: if ( ! fracF64UI( uiA ) ) break; case softfloat_round_near_maxMag: if ( exp == 0x3FE ) uiZ |= packToF64UI( 0, 0x3FF, 0 ); break; case softfloat_round_min: if ( uiZ ) uiZ = packToF64UI( 1, 0x3FF, 0 ); break; case softfloat_round_max: if ( ! uiZ ) uiZ = packToF64UI( 0, 0x3FF, 0 ); break; } goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x433 <= exp ) { if ( (exp == 0x7FF) && fracF64UI( uiA ) ) { uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); goto uiZ; } return a; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ = uiA; lastBitMask = (uint_fast64_t) 1<<(0x433 - exp); roundBitsMask = lastBitMask - 1; if ( roundingMode == softfloat_round_near_maxMag ) { uiZ += lastBitMask>>1; } else if ( roundingMode == softfloat_round_near_even ) { uiZ += lastBitMask>>1; if ( ! (uiZ & roundBitsMask) ) uiZ &= ~lastBitMask; } else if ( roundingMode != softfloat_round_minMag ) { if ( signF64UI( uiZ ) ^ (roundingMode == softfloat_round_max) ) { uiZ += roundBitsMask; } } uiZ &= ~roundBitsMask; if ( exact && (uiZ != uiA) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_sqrt.c000066400000000000000000000121421464416617300255120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t f64_sqrt( float64_t a ) { union ui64_f64 uA; uint_fast64_t uiA; bool signA; int_fast16_t expA; uint_fast64_t sigA, uiZ; struct exp16_sig64 normExpSig; int_fast16_t expZ; uint32_t sig32A, recipSqrt32, sig32Z; uint_fast64_t rem; uint32_t q; uint_fast64_t sigZ, shiftedSigZ; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA ) { uiZ = softfloat_propagateNaNF64UI( uiA, 0 ); goto uiZ; } if ( ! signA ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signA ) { if ( ! (expA | sigA) ) return a; goto invalid; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) return a; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } /*------------------------------------------------------------------------ | (`sig32Z' is guaranteed to be a lower bound on the square root of | `sig32A', which makes `sig32Z' also a lower bound on the square root of | `sigA'.) *------------------------------------------------------------------------*/ expZ = ((expA - 0x3FF)>>1) + 0x3FE; expA &= 1; sigA |= UINT64_C( 0x0010000000000000 ); sig32A = sigA>>21; recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A ); sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32; if ( expA ) { sigA <<= 8; sig32Z >>= 1; } else { sigA <<= 9; } rem = sigA - (uint_fast64_t) sig32Z * sig32Z; q = ((uint32_t) (rem>>2) * (uint_fast64_t) recipSqrt32)>>32; sigZ = ((uint_fast64_t) sig32Z<<32 | 1<<5) + ((uint_fast64_t) q<<3); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (sigZ & 0x1FF) < 1<<5 ) { sigZ &= ~(uint_fast64_t) 0x3F; shiftedSigZ = sigZ>>6; rem = (sigA<<52) - shiftedSigZ * shiftedSigZ; if ( rem & UINT64_C( 0x8000000000000000 ) ) { --sigZ; } else { if ( rem ) sigZ |= 1; } } return softfloat_roundPackToF64( 0, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_sub.c000066400000000000000000000052641464416617300253210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t f64_sub( float64_t a, float64_t b ) { union ui64_f64 uA; uint_fast64_t uiA; bool signA; union ui64_f64 uB; uint_fast64_t uiB; bool signB; #if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2) float64_t (*magsFuncPtr)( uint_fast64_t, uint_fast64_t, bool ); #endif uA.f = a; uiA = uA.ui; signA = signF64UI( uiA ); uB.f = b; uiB = uB.ui; signB = signF64UI( uiB ); #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) if ( signA == signB ) { return softfloat_subMagsF64( uiA, uiB, signA ); } else { return softfloat_addMagsF64( uiA, uiB, signA ); } #else magsFuncPtr = (signA == signB) ? softfloat_subMagsF64 : softfloat_addMagsF64; return (*magsFuncPtr)( uiA, uiB, signA ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80.c000066400000000000000000000063311464416617300263040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t f64_to_extF80( float64_t a ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; struct commonNaN commonNaN; struct uint128 uiZ; uint_fast16_t uiZ64; uint_fast64_t uiZ0; struct exp16_sig64 normExpSig; union { struct extFloat80M s; extFloat80_t f; } uZ; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp == 0x7FF ) { if ( sig ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToExtF80UI( &commonNaN ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; } else { uiZ64 = packToExtF80UI64( sign, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ64 = packToExtF80UI64( sign, 0 ); uiZ0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF64Sig( sig ); exp = normExpSig.exp; sig = normExpSig.sig; } uiZ64 = packToExtF80UI64( sign, exp + 0x3C00 ); uiZ0 = (sig | UINT64_C( 0x0010000000000000 ))<<11; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_extF80M.c000066400000000000000000000064141464416617300264230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f64_to_extF80M( float64_t a, extFloat80_t *zPtr ) { *zPtr = f64_to_extF80( a ); } #else void f64_to_extF80M( float64_t a, extFloat80_t *zPtr ) { struct extFloat80M *zSPtr; union ui64_f64 uA; uint64_t uiA; bool sign; int_fast16_t exp; uint64_t sig; struct commonNaN commonNaN; uint_fast16_t uiZ64; uint64_t uiZ0; struct exp16_sig64 normExpSig; zSPtr = (struct extFloat80M *) zPtr; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp == 0x7FF ) { if ( sig ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); softfloat_commonNaNToExtF80M( &commonNaN, zSPtr ); return; } uiZ64 = packToExtF80UI64( sign, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ64 = packToExtF80UI64( sign, 0 ); uiZ0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF64Sig( sig ); exp = normExpSig.exp; sig = normExpSig.sig; } uiZ64 = packToExtF80UI64( sign, exp + 0x3C00 ); uiZ0 = UINT64_C( 0x8000000000000000 ) | sig<<11; uiZ: zSPtr->signExp = uiZ64; zSPtr->signif = uiZ0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128.c000066400000000000000000000061311464416617300257040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t f64_to_f128( float64_t a ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; struct commonNaN commonNaN; struct uint128 uiZ; struct exp16_sig64 normExpSig; struct uint128 sig128; union ui128_f128 uZ; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp == 0x7FF ) { if ( sig ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF128UI( &commonNaN ); } else { uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ.v0 = 0; } goto uiZ; } if ( ! exp ) { if ( ! sig ) { uiZ.v64 = packToF128UI64( sign, 0, 0 ); uiZ.v0 = 0; goto uiZ; } normExpSig = softfloat_normSubnormalF64Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } sig128 = softfloat_shortShiftLeft128( 0, sig, 60 ); uiZ.v64 = packToF128UI64( sign, exp + 0x3C00, sig128.v64 ); uiZ.v0 = sig128.v0; uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f128M.c000066400000000000000000000103671464416617300260270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void f64_to_f128M( float64_t a, float128_t *zPtr ) { *zPtr = f64_to_f128( a ); } #else void f64_to_f128M( float64_t a, float128_t *zPtr ) { uint32_t *zWPtr; union ui64_f64 uA; uint64_t uiA; bool sign; int_fast16_t exp; uint64_t sig; struct commonNaN commonNaN; uint32_t uiZ96; struct exp16_sig64 normExpSig; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr = (uint32_t *) zPtr; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 0 )] = 0; if ( exp == 0x7FF ) { if ( sig ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); softfloat_commonNaNToF128M( &commonNaN, zWPtr ); return; } uiZ96 = packToF128UI96( sign, 0x7FFF, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! exp ) { if ( ! sig ) { uiZ96 = packToF128UI96( sign, 0, 0 ); goto uiZ; } normExpSig = softfloat_normSubnormalF64Sig( sig ); exp = normExpSig.exp - 1; sig = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zWPtr[indexWord( 4, 1 )] = (uint32_t) sig<<28; sig >>= 4; zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp + 0x3C00, sig>>32 ); zWPtr[indexWord( 4, 2 )] = sig; return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiZ: zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_f32.c000066400000000000000000000054641464416617300256260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t f64_to_f32( float64_t a ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; struct commonNaN commonNaN; uint_fast32_t uiZ, sig32; union ui32_f32 uZ; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp == 0x7FF ) { if ( sig ) { softfloat_f64UIToCommonNaN( uiA, &commonNaN ); uiZ = softfloat_commonNaNToF32UI( &commonNaN ); } else { uiZ = packToF32UI( sign, 0xFF, 0 ); } goto uiZ; } sig32 = softfloat_shortShiftRightJam64( sig, 22 ); if ( ! (exp | sig32) ) { uiZ = packToF32UI( sign, 0, 0 ); goto uiZ; } return softfloat_roundPackToF32( sign, exp - 0x381, sig32 | 0x40000000 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32.c000066400000000000000000000050161464416617300256220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( (exp == 0x7FF) && sig ) sign = 0; if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x42C - exp; if ( 0 < shiftCount ) sig = softfloat_shiftRightJam64( sig, shiftCount ); return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i32_r_minMag.c000066400000000000000000000061661464416617300274420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; bool sign; int_fast32_t absZ; uA.f = a; uiA = uA.ui; exp = expF64UI( uiA ); sig = fracF64UI( uiA ); shiftCount = 0x433 - exp; if ( 53 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sign = signF64UI( uiA ); if ( shiftCount < 22 ) { if ( sign && (exp == 0x41E) && (sig < UINT64_C( 0x0000000000200000 )) ) { if ( exact && sig ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } else { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FF) && sig) ) return 0x7FFFFFFF; } return -0x7FFFFFFF - 1; } sig |= UINT64_C( 0x0010000000000000 ); absZ = sig>>shiftCount; if ( exact && ((uint_fast64_t) (uint_fast32_t) absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t f64_to_i64( float64_t a, uint_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; #ifdef SOFTFLOAT_FAST_INT64 struct uint64_extra sigExtra; #else uint32_t extSig[3]; #endif uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x433 - exp; #ifdef SOFTFLOAT_FAST_INT64 if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FF) && (sig != UINT64_C( 0x0010000000000000 ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sigExtra.v = sig<<-shiftCount; sigExtra.extra = 0; } else { sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); } return softfloat_roundPackToI64( sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); #else extSig[indexWord( 3, 0 )] = 0; if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return ! sign || ((exp == 0x7FF) && (sig != UINT64_C( 0x0010000000000000 ))) ? INT64_C( 0x7FFFFFFFFFFFFFFF ) : -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sig <<= -shiftCount; extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; } else { extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); } return softfloat_roundPackMToI64( sign, extSig, roundingMode, exact ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_i64_r_minMag.c000066400000000000000000000062671464416617300274510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; int_fast64_t absZ; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); shiftCount = 0x433 - exp; if ( shiftCount <= 0 ) { if ( shiftCount < -10 ) { if ( uiA != packToF64UI( 1, 0x43E, 0 ) ) { softfloat_raiseFlags( softfloat_flag_invalid ); if ( ! sign || ((exp == 0x7FF) && sig) ) { return INT64_C( 0x7FFFFFFFFFFFFFFF ); } } return -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; } sig |= UINT64_C( 0x0010000000000000 ); absZ = sig<<-shiftCount; } else { if ( 53 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } sig |= UINT64_C( 0x0010000000000000 ); absZ = sig>>shiftCount; if ( exact && (absZ< #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t f64_to_ui32( float64_t a, uint_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x42C - exp; if ( 0 < shiftCount ) sig = softfloat_shiftRightJam64( sig, shiftCount ); return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui32_r_minMag.c000066400000000000000000000053621464416617300276240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; uint_fast32_t z; uA.f = a; uiA = uA.ui; exp = expF64UI( uiA ); sig = fracF64UI( uiA ); shiftCount = 0x433 - exp; if ( 53 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF64UI( uiA ) || (shiftCount < 21) ) { softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } sig |= UINT64_C( 0x0010000000000000 ); z = sig>>shiftCount; if ( exact && ((uint_fast64_t) z< #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t f64_to_ui64( float64_t a, uint_fast8_t roundingMode, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; bool sign; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; #ifdef SOFTFLOAT_FAST_INT64 struct uint64_extra sigExtra; #else uint32_t extSig[3]; #endif uA.f = a; uiA = uA.ui; sign = signF64UI( uiA ); exp = expF64UI( uiA ); sig = fracF64UI( uiA ); if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); shiftCount = 0x433 - exp; #ifdef SOFTFLOAT_FAST_INT64 if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sigExtra.v = sig<<-shiftCount; sigExtra.extra = 0; } else { sigExtra = softfloat_shiftRightJam64Extra( sig, 0, shiftCount ); } return softfloat_roundPackToUI64( sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); #else extSig[indexWord( 3, 0 )] = 0; if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) { softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } sig <<= -shiftCount; extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; } else { extSig[indexWord( 3, 2 )] = sig>>32; extSig[indexWord( 3, 1 )] = sig; softfloat_shiftRightJam96M( extSig, shiftCount, extSig ); } return softfloat_roundPackMToUI64( sign, extSig, roundingMode, exact ); #endif } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/f64_to_ui64_r_minMag.c000066400000000000000000000056521464416617300276330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact ) { union ui64_f64 uA; uint_fast64_t uiA; int_fast16_t exp; uint_fast64_t sig; int_fast16_t shiftCount; uint_fast64_t z; uA.f = a; uiA = uA.ui; exp = expF64UI( uiA ); sig = fracF64UI( uiA ); shiftCount = 0x433 - exp; if ( 53 <= shiftCount ) { if ( exact && (exp | sig) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return 0; } if ( signF64UI( uiA ) ) goto invalid; if ( shiftCount <= 0 ) { if ( shiftCount < -11 ) goto invalid; z = (sig | UINT64_C( 0x0010000000000000 ))<<-shiftCount; } else { sig |= UINT64_C( 0x0010000000000000 ); z = sig>>shiftCount; if ( exact && (uint64_t) (sig<<(-shiftCount & 63)) ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80.c000066400000000000000000000047431464416617300263070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t i32_to_extF80( int32_t a ) { uint_fast16_t uiZ64; uint_fast32_t absA; bool sign; int_fast8_t shiftCount; union { struct extFloat80M s; extFloat80_t f; } uZ; uiZ64 = 0; absA = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; shiftCount = softfloat_countLeadingZeros32( absA ); uiZ64 = packToExtF80UI64( sign, 0x401E - shiftCount ); absA <<= shiftCount; } uZ.s.signExp = uiZ64; uZ.s.signif = (uint_fast64_t) absA<<32; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_extF80M.c000066400000000000000000000051531464416617300264200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void i32_to_extF80M( int32_t a, extFloat80_t *zPtr ) { *zPtr = i32_to_extF80( a ); } #else void i32_to_extF80M( int32_t a, extFloat80_t *zPtr ) { struct extFloat80M *zSPtr; uint_fast16_t uiZ64; uint64_t sigZ; bool sign; uint32_t absA; int_fast8_t shiftCount; zSPtr = (struct extFloat80M *) zPtr; uiZ64 = 0; sigZ = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint32_t) a : (uint32_t) a; shiftCount = softfloat_countLeadingZeros32( absA ); uiZ64 = packToExtF80UI64( sign, 0x401E - shiftCount ); sigZ = (uint64_t) (absA<signExp = uiZ64; zSPtr->signif = sigZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f128.c000066400000000000000000000046451464416617300257120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t i32_to_f128( int32_t a ) { uint_fast64_t uiZ64; bool sign; uint_fast32_t absA; int_fast8_t shiftCount; union ui128_f128 uZ; uiZ64 = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; shiftCount = softfloat_countLeadingZeros32( absA ) + 17; uiZ64 = packToF128UI64( sign, 0x402E - shiftCount, (uint_fast64_t) absA< #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void i32_to_f128M( int32_t a, float128_t *zPtr ) { *zPtr = i32_to_f128( a ); } #else void i32_to_f128M( int32_t a, float128_t *zPtr ) { uint32_t *zWPtr; uint32_t uiZ96, uiZ64; bool sign; uint32_t absA; int_fast8_t shiftCount; uint64_t normAbsA; zWPtr = (uint32_t *) zPtr; uiZ96 = 0; uiZ64 = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint32_t) a : (uint32_t) a; shiftCount = softfloat_countLeadingZeros32( absA ) + 17; normAbsA = (uint64_t) absA<>32 ); uiZ64 = normAbsA; } zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = uiZ64; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f32.c000066400000000000000000000044141464416617300256160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t i32_to_f32( int32_t a ) { bool sign; union ui32_f32 uZ; uint_fast32_t absA; sign = (a < 0); if ( ! (a & 0x7FFFFFFF) ) { uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0; return uZ.f; } absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; return softfloat_normRoundPackToF32( sign, 0x9C, absA ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i32_to_f64.c000066400000000000000000000046461464416617300256320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t i32_to_f64( int32_t a ) { uint_fast64_t uiZ; bool sign; uint_fast32_t absA; int_fast8_t shiftCount; union ui64_f64 uZ; if ( ! a ) { uiZ = 0; } else { sign = (a < 0); absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a; shiftCount = softfloat_countLeadingZeros32( absA ) + 21; uiZ = packToF64UI( sign, 0x432 - shiftCount, (uint_fast64_t) absA< #include #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t i64_to_extF80( int64_t a ) { uint_fast16_t uiZ64; uint_fast64_t absA; bool sign; int_fast8_t shiftCount; union { struct extFloat80M s; extFloat80_t f; } uZ; uiZ64 = 0; absA = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; shiftCount = softfloat_countLeadingZeros64( absA ); uiZ64 = packToExtF80UI64( sign, 0x403E - shiftCount ); absA <<= shiftCount; } uZ.s.signExp = uiZ64; uZ.s.signif = absA; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_extF80M.c000066400000000000000000000051321464416617300264220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void i64_to_extF80M( int64_t a, extFloat80_t *zPtr ) { *zPtr = i64_to_extF80( a ); } #else void i64_to_extF80M( int64_t a, extFloat80_t *zPtr ) { struct extFloat80M *zSPtr; uint_fast16_t uiZ64; uint64_t sigZ; bool sign; uint64_t absA; int_fast8_t shiftCount; zSPtr = (struct extFloat80M *) zPtr; uiZ64 = 0; sigZ = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint64_t) a : (uint64_t) a; shiftCount = softfloat_countLeadingZeros64( absA ); uiZ64 = packToExtF80UI64( sign, 0x403E - shiftCount ); sigZ = absA<signExp = uiZ64; zSPtr->signif = sigZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128.c000066400000000000000000000052401464416617300257070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t i64_to_f128( int64_t a ) { uint_fast64_t uiZ64, uiZ0; bool sign; uint_fast64_t absA; int_fast8_t shiftCount; struct uint128 zSig; union ui128_f128 uZ; if ( ! a ) { uiZ64 = 0; uiZ0 = 0; } else { sign = (a < 0); absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; shiftCount = softfloat_countLeadingZeros64( absA ) + 49; if ( 64 <= shiftCount ) { zSig.v64 = absA<<(shiftCount - 64); zSig.v0 = 0; } else { zSig = softfloat_shortShiftLeft128( 0, absA, shiftCount ); } uiZ64 = packToF128UI64( sign, 0x406E - shiftCount, zSig.v64 ); uiZ0 = zSig.v0; } uZ.ui.v64 = uiZ64; uZ.ui.v0 = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f128M.c000066400000000000000000000062001464416617300260210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void i64_to_f128M( int64_t a, float128_t *zPtr ) { *zPtr = i64_to_f128( a ); } #else void i64_to_f128M( int64_t a, float128_t *zPtr ) { uint32_t *zWPtr; uint32_t uiZ96, uiZ64; bool sign; uint64_t absA; uint_fast8_t shiftCount; uint32_t *ptr; zWPtr = (uint32_t *) zPtr; uiZ96 = 0; uiZ64 = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; if ( a ) { sign = (a < 0); absA = sign ? -(uint64_t) a : (uint64_t) a; shiftCount = softfloat_countLeadingZeros64( absA ) + 17; if ( shiftCount < 32 ) { ptr = zWPtr + indexMultiwordHi( 4, 3 ); ptr[indexWord( 3, 2 )] = 0; ptr[indexWord( 3, 1 )] = absA>>32; ptr[indexWord( 3, 0 )] = absA; softfloat_shortShiftLeft96M( ptr, shiftCount, ptr ); ptr[indexWordHi( 3 )] = packToF128UI96( sign, 0x404E - shiftCount, ptr[indexWordHi( 3 )] ); return; } absA <<= shiftCount - 32; uiZ96 = packToF128UI96( sign, 0x404E - shiftCount, absA>>32 ); uiZ64 = absA; } zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = uiZ64; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/i64_to_f32.c000066400000000000000000000052511464416617300256230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t i64_to_f32( int64_t a ) { bool sign; uint_fast64_t absA; int_fast8_t shiftCount; union ui32_f32 u; uint_fast32_t sig; sign = (a < 0); absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; shiftCount = softfloat_countLeadingZeros64( absA ) - 40; if ( 0 <= shiftCount ) { u.ui = a ? packToF32UI( sign, 0x95 - shiftCount, (uint_fast32_t) absA< #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t i64_to_f64( int64_t a ) { bool sign; union ui64_f64 uZ; uint_fast64_t absA; sign = (a < 0); if ( ! (a & UINT64_C( 0x7FFFFFFFFFFFFFFF )) ) { uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0; return uZ.f; } absA = sign ? -(uint_fast64_t) a : (uint_fast64_t) a; return softfloat_normRoundPackToF64( sign, 0x43C, absA ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/include/000077500000000000000000000000001464416617300253215ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/include/internals.h000066400000000000000000000230751464416617300275000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #ifndef internals_h #define internals_h 1 #include #include #include "primitives.h" #include "softfloat_types.h" union ui32_f32 { uint32_t ui; float32_t f; }; union ui64_f64 { uint64_t ui; float64_t f; }; #ifdef SOFTFLOAT_FAST_INT64 union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; union ui128_f128 { struct uint128 ui; float128_t f; }; #endif enum { softfloat_mulAdd_subC = 1, softfloat_mulAdd_subProd = 2 }; /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ uint_fast32_t softfloat_roundPackToUI32( bool, uint_fast64_t, uint_fast8_t, bool ); #ifdef SOFTFLOAT_FAST_INT64 uint_fast64_t softfloat_roundPackToUI64( bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); #else uint_fast64_t softfloat_roundPackMToUI64( bool, uint32_t *, uint_fast8_t, bool ); #endif int_fast32_t softfloat_roundPackToI32( bool, uint_fast64_t, uint_fast8_t, bool ); #ifdef SOFTFLOAT_FAST_INT64 int_fast64_t softfloat_roundPackToI64( bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); #else int_fast64_t softfloat_roundPackMToI64( bool, uint32_t *, uint_fast8_t, bool ); #endif /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define signF32UI( a ) ((bool) ((uint32_t) (a)>>31)) #define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF) #define fracF32UI( a ) ((a) & 0x007FFFFF) #define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) #define isNaNF32UI( a ) ((((a) & 0x7F800000) == 0x7F800000) && ((a) & 0x007FFFFF)) struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t, bool ); float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t, bool ); float32_t softfloat_mulAddF32( uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t ); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define signF64UI( a ) ((bool) ((uint64_t) (a)>>63)) #define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF) #define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )) #define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig))) #define isNaNF64UI( a ) ((((a) & UINT64_C( 0x7FF0000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))) struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); float64_t softfloat_mulAddF64( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15)) #define expExtF80UI64( a64 ) ((a64) & 0x7FFF) #define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp)) #define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))) #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); extFloat80_t softfloat_roundPackToExtF80( bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); extFloat80_t softfloat_normRoundPackToExtF80( bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); extFloat80_t softfloat_addMagsExtF80( uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); extFloat80_t softfloat_subMagsExtF80( uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63)) #define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF) #define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )) #define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64)) #define isNaNF128UI( a64, a0 ) ((((a64) & UINT64_C( 0x7FFF000000000000 )) == UINT64_C( 0x7FFF000000000000 )) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF )))) struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; struct exp32_sig128 softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); float128_t softfloat_roundPackToF128( bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t ); float128_t softfloat_normRoundPackToF128( bool, int_fast32_t, uint_fast64_t, uint_fast64_t ); float128_t softfloat_addMagsF128( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); float128_t softfloat_subMagsF128( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); float128_t softfloat_mulAddF128( uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); #else /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool softfloat_tryPropagateNaNExtF80M( const struct extFloat80M *, const struct extFloat80M *, struct extFloat80M * ); void softfloat_invalidExtF80M( struct extFloat80M * ); int softfloat_normExtF80SigM( uint64_t * ); void softfloat_roundPackMToExtF80M( bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); void softfloat_normRoundPackMToExtF80M( bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); void softfloat_addExtF80M( const struct extFloat80M *, const struct extFloat80M *, struct extFloat80M *, bool ); int softfloat_compareNonnormExtF80M( const struct extFloat80M *, const struct extFloat80M * ); /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ #define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31)) #define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF) #define fracF128UI96( a96 ) ((a96) & 0x0000FFFF) #define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96)) bool softfloat_isNaNF128M( const uint32_t * ); bool softfloat_tryPropagateNaNF128M( const uint32_t *, const uint32_t *, uint32_t * ); void softfloat_invalidF128M( uint32_t * ); int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * ); void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); void softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); void softfloat_mulAddF128M( const uint32_t *, const uint32_t *, const uint32_t *, uint32_t *, uint_fast8_t ); #endif #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/include/primitiveTypes.h000066400000000000000000000065611464416617300305370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #ifndef primitiveTypes_h #define primitiveTypes_h 1 #include #ifdef SOFTFLOAT_FAST_INT64 #ifdef LITTLEENDIAN struct uint128 { uint64_t v0, v64; }; struct uint64_extra { uint64_t extra, v; }; struct uint128_extra { uint64_t extra; struct uint128 v; }; #else struct uint128 { uint64_t v64, v0; }; struct uint64_extra { uint64_t v, extra; }; struct uint128_extra { struct uint128 v; uint64_t extra; }; #endif #endif /*---------------------------------------------------------------------------- | These macros are used to isolate the differences in word order between big- | endian and little-endian platforms. *----------------------------------------------------------------------------*/ #ifdef LITTLEENDIAN #define wordIncr 1 #define indexWord( total, n ) (n) #define indexWordHi( total ) ((total) - 1) #define indexWordLo( total ) 0 #define indexMultiword( total, m, n ) (n) #define indexMultiwordHi( total, n ) ((total) - (n)) #define indexMultiwordLo( total, n ) 0 #define indexMultiwordHiBut( total, n ) (n) #define indexMultiwordLoBut( total, n ) 0 #define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 } #else #define wordIncr -1 #define indexWord( total, n ) ((total) - 1 - (n)) #define indexWordHi( total ) 0 #define indexWordLo( total ) ((total) - 1) #define indexMultiword( total, m, n ) ((total) - 1 - (m)) #define indexMultiwordHi( total, n ) 0 #define indexMultiwordLo( total, n ) ((total) - (n)) #define indexMultiwordHiBut( total, n ) 0 #define indexMultiwordLoBut( total, n ) (n) #define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 } #endif #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/include/primitives.h000066400000000000000000001434661464416617300277030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #ifndef primitives_h #define primitives_h 1 #include #include #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJam64 /*---------------------------------------------------------------------------- | Shifts `a' right by the number of bits given in `count', which must be in | the range 1 to 63. If any nonzero bits are shifted off, they are "jammed" | into the least-significant bit of the shifted value by setting the least- | significant bit to 1. This shifted-and-jammed value is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t count ) { return a>>count | ((a & (((uint_fast64_t) 1<>count | ((uint32_t) (a<<(-count & 31)) != 0) : (a != 0); } #else uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t count ); #endif #endif #ifndef softfloat_shiftRightJam64 /*---------------------------------------------------------------------------- | Shifts `a' right by the number of bits given in `count', which must not | be zero. If any nonzero bits are shifted off, they are "jammed" into the | least-significant bit of the shifted value by setting the least-significant | bit to 1. This shifted-and-jammed value is returned. | The value of `count' can be arbitrarily large. In particular, if `count' | is greater than 64, the result will be either 0 or 1, depending on whether | `a' is zero or nonzero. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t count ) { return (count < 63) ? a>>count | ((uint64_t) (a<<(-count & 63)) != 0) : (a != 0); } #else uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t count ); #endif #endif /*---------------------------------------------------------------------------- | A constant table that translates an 8-bit unsigned integer (the array index) | into the number of leading 0 bits before the most-significant 1 of that | integer. For integer zero (index 0), the corresponding table element is 8. *----------------------------------------------------------------------------*/ extern const uint_least8_t softfloat_countLeadingZeros8[256]; #ifndef softfloat_countLeadingZeros32 /*---------------------------------------------------------------------------- | Returns the number of leading 0 bits before the most-significant 1 bit of | `a'. If `a' is zero, 32 is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) { uint_fast8_t count = 0; if ( a < 0x10000 ) { count = 16; a <<= 16; } if ( a < 0x1000000 ) { count += 8; a <<= 8; } count += softfloat_countLeadingZeros8[a>>24]; return count; } #else uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ); #endif #endif #ifndef softfloat_countLeadingZeros64 /*---------------------------------------------------------------------------- | Returns the number of leading 0 bits before the most-significant 1 bit of | `a'. If `a' is zero, 64 is returned. *----------------------------------------------------------------------------*/ uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ); #endif #ifndef softfloat_approxRecip32_1 /*---------------------------------------------------------------------------- | Returns an approximation to the reciprocal of the number represented by `a', | where `a' is interpreted as an unsigned fixed-point number with one integer | bit and 31 fraction bits. The `a' input must be "normalized", meaning that | its most-significant bit (bit 31) must be 1. Thus, if A is the value of | the fixed-point interpretation of `a', then 1 <= A < 2. The returned value | is interpreted as a pure unsigned fraction, having no integer bits and 32 | fraction bits. The approximation returned is never greater than the true | reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp | (units in the last place). *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_DIV64TO32 #define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a))) #else uint32_t softfloat_approxRecip32_1( uint32_t a ); #endif #endif #ifndef softfloat_approxRecipSqrt32_1 /*---------------------------------------------------------------------------- | Returns an approximation to the reciprocal of the square root of the number | represented by `a', where `a' is interpreted as an unsigned fixed-point | number either with one integer bit and 31 fraction bits or with two integer | bits and 30 fraction bits. The format of `a' is determined by `oddExpA', | which must be either 0 or 1. If `oddExpA' is 1, `a' is interpreted as | having one integer bit, and if `oddExpA' is 0, `a' is interpreted as having | two integer bits. The `a' input must be "normalized", meaning that its | most-significant bit (bit 31) must be 1. Thus, if A is the value of the | fixed-point interpretation of `a', it follows that 1 <= A < 2 when `oddExpA' | is 1, and 2 <= A < 4 when `oddExpA' is 0. | The returned value is interpreted as a pure unsigned fraction, having | no integer bits and 32 fraction bits. The approximation returned is never | greater than the true reciprocal 1/sqrt(A), and it differs from the true | reciprocal by at most 2.06 ulp (units in the last place). The approximation | returned is also always within the range 0.5 to 1; thus, the most- | significant bit of the result is always set. *----------------------------------------------------------------------------*/ uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ); #endif #ifdef SOFTFLOAT_FAST_INT64 /*---------------------------------------------------------------------------- | The following functions are needed only when `SOFTFLOAT_FAST_INT64' is | defined. *----------------------------------------------------------------------------*/ #ifndef softfloat_eq128 /*---------------------------------------------------------------------------- | Returns true if the 128-bit unsigned integer formed by concatenating `a64' | and `a0' is equal to the 128-bit unsigned integer formed by concatenating | `b64' and `b0'. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (1 <= INLINE_LEVEL) INLINE bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { return (a64 == b64) && (a0 == b0); } #else bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); #endif #endif #ifndef softfloat_le128 /*---------------------------------------------------------------------------- | Returns true if the 128-bit unsigned integer formed by concatenating `a64' | and `a0' is less than or equal to the 128-bit unsigned integer formed by | concatenating `b64' and `b0'. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } #else bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); #endif #endif #ifndef softfloat_lt128 /*---------------------------------------------------------------------------- | Returns true if the 128-bit unsigned integer formed by concatenating `a64' | and `a0' is less than the 128-bit unsigned integer formed by concatenating | `b64' and `b0'. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } #else bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); #endif #endif #ifndef softfloat_shortShiftLeft128 /*---------------------------------------------------------------------------- | Shifts the 128 bits formed by concatenating `a64' and `a0' left by the | number of bits given in `count', which must be in the range 1 to 63. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE struct uint128 softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t count ) { struct uint128 z; z.v64 = a64<>(-count & 63); z.v0 = a0<>count; z.v0 = a64<<(-count & 63) | a0>>count; return z; } #else struct uint128 softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t count ); #endif #endif #ifndef softfloat_shortShiftRightJam64Extra /*---------------------------------------------------------------------------- | This function is the same as `softfloat_shiftRightJam64Extra' (below), | except that `count' must be in the range 1 to 63. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE struct uint64_extra softfloat_shortShiftRightJam64Extra( uint64_t a, uint64_t extra, uint_fast8_t count ) { struct uint64_extra z; z.v = a>>count; z.extra = a<<(-count & 63) | (extra != 0); return z; } #else struct uint64_extra softfloat_shortShiftRightJam64Extra( uint64_t a, uint64_t extra, uint_fast8_t count ); #endif #endif #ifndef softfloat_shortShiftRightJam128 /*---------------------------------------------------------------------------- | Shifts the 128 bits formed by concatenating `a64' and `a0' right by the | number of bits given in `count', which must be in the range 1 to 63. If any | nonzero bits are shifted off, they are "jammed" into the least-significant | bit of the shifted value by setting the least-significant bit to 1. This | shifted-and-jammed value is returned. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE struct uint128 softfloat_shortShiftRightJam128( uint64_t a64, uint64_t a0, uint_fast8_t count ) { uint_fast8_t negCount = -count; struct uint128 z; z.v64 = a64>>count; z.v0 = a64<<(negCount & 63) | a0>>count | ((uint64_t) (a0<<(negCount & 63)) != 0); return z; } #else struct uint128 softfloat_shortShiftRightJam128( uint64_t a64, uint64_t a0, uint_fast8_t count ); #endif #endif #ifndef softfloat_shortShiftRightJam128Extra /*---------------------------------------------------------------------------- | This function is the same as `softfloat_shiftRightJam128Extra' (below), | except that `count' must be in the range 1 to 63. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE struct uint128_extra softfloat_shortShiftRightJam128Extra( uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t count ) { uint_fast8_t negCount = -count; struct uint128_extra z; z.v.v64 = a64>>count; z.v.v0 = a64<<(negCount & 63) | a0>>count; z.extra = a0<<(negCount & 63) | (extra != 0); return z; } #else struct uint128_extra softfloat_shortShiftRightJam128Extra( uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t count ); #endif #endif #ifndef softfloat_shiftRightJam64Extra /*---------------------------------------------------------------------------- | Shifts the 128 bits formed by concatenating `a' and `extra' right by 64 | _plus_ the number of bits given in `count', which must not be zero. This | shifted value is at most 64 nonzero bits and is returned in the `v' field | of the `struct uint64_extra' result. The 64-bit `extra' field of the result | contains a value formed as follows from the bits that were shifted off: The | _last_ bit shifted off is the most-significant bit of the `extra' field, and | the other 63 bits of the `extra' field are all zero if and only if _all_but_ | _the_last_ bits shifted off were all zero. | (This function makes more sense if `a' and `extra' are considered to form | an unsigned fixed-point number with binary point between `a' and `extra'. | This fixed-point value is shifted right by the number of bits given in | `count', and the integer part of this shifted value is returned in the `v' | field of the result. The fractional part of the shifted value is modified | as described above and returned in the `extra' field of the result.) *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) INLINE struct uint64_extra softfloat_shiftRightJam64Extra( uint64_t a, uint64_t extra, uint_fast32_t count ) { struct uint64_extra z; if ( count < 64 ) { z.v = a>>count; z.extra = a<<(-count & 63); } else { z.v = 0; z.extra = (count == 64) ? a : (a != 0); } z.extra |= (extra != 0); return z; } #else struct uint64_extra softfloat_shiftRightJam64Extra( uint64_t a, uint64_t extra, uint_fast32_t count ); #endif #endif #ifndef softfloat_shiftRightJam128 /*---------------------------------------------------------------------------- | Shifts the 128 bits formed by concatenating `a64' and `a0' right by the | number of bits given in `count', which must not be zero. If any nonzero | bits are shifted off, they are "jammed" into the least-significant bit of | the shifted value by setting the least-significant bit to 1. This shifted- | and-jammed value is returned. | The value of `count' can be arbitrarily large. In particular, if `count' | is greater than 128, the result will be either 0 or 1, depending on whether | the original 128 bits are all zeros. *----------------------------------------------------------------------------*/ struct uint128 softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t count ); #endif #ifndef softfloat_shiftRightJam128Extra /*---------------------------------------------------------------------------- | Shifts the 192 bits formed by concatenating `a64', `a0', and `extra' right | by 64 _plus_ the number of bits given in `count', which must not be zero. | This shifted value is at most 128 nonzero bits and is returned in the `v' | field of the `struct uint128_extra' result. The 64-bit `extra' field of the | result contains a value formed as follows from the bits that were shifted | off: The _last_ bit shifted off is the most-significant bit of the `extra' | field, and the other 63 bits of the `extra' field are all zero if and only | if _all_but_the_last_ bits shifted off were all zero. | (This function makes more sense if `a64', `a0', and `extra' are considered | to form an unsigned fixed-point number with binary point between `a0' and | `extra'. This fixed-point value is shifted right by the number of bits | given in `count', and the integer part of this shifted value is returned | in the `v' field of the result. The fractional part of the shifted value | is modified as described above and returned in the `extra' field of the | result.) *----------------------------------------------------------------------------*/ struct uint128_extra softfloat_shiftRightJam128Extra( uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t count ); #endif #ifndef softfloat_shiftRightJam256M /*---------------------------------------------------------------------------- | Shifts the 256-bit unsigned integer pointed to by `aPtr' right by the number | of bits given in `count', which must not be zero. If any nonzero bits are | shifted off, they are "jammed" into the least-significant bit of the shifted | value by setting the least-significant bit to 1. This shifted-and-jammed | value is stored at the location pointed to by `zPtr'. Each of `aPtr' and | `zPtr' points to an array of four 64-bit elements that concatenate in the | platform's normal endian order to form a 256-bit integer. | The value of `count' can be arbitrarily large. In particular, if `count' | is greater than 256, the stored result will be either 0 or 1, depending on | whether the original 256 bits are all zeros. *----------------------------------------------------------------------------*/ void softfloat_shiftRightJam256M( const uint64_t *aPtr, uint_fast32_t count, uint64_t *zPtr ); #endif #ifndef softfloat_add128 /*---------------------------------------------------------------------------- | Returns the sum of the 128-bit integer formed by concatenating `a64' and | `a0' and the 128-bit integer formed by concatenating `b64' and `b0'. The | addition is modulo 2^128, so any carry out is lost. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE struct uint128 softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { struct uint128 z; z.v0 = a0 + b0; z.v64 = a64 + b64 + (z.v0 < a0); return z; } #else struct uint128 softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); #endif #endif #ifndef softfloat_add256M /*---------------------------------------------------------------------------- | Adds the two 256-bit integers pointed to by `aPtr' and `bPtr'. The addition | is modulo 2^256, so any carry out is lost. The sum is stored at the | location pointed to by `zPtr'. Each of `aPtr', `bPtr', and `zPtr' points to | an array of four 64-bit elements that concatenate in the platform's normal | endian order to form a 256-bit integer. *----------------------------------------------------------------------------*/ void softfloat_add256M( const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); #endif #ifndef softfloat_sub128 /*---------------------------------------------------------------------------- | Returns the difference of the 128-bit integer formed by concatenating `a64' | and `a0' and the 128-bit integer formed by concatenating `b64' and `b0'. | The subtraction is modulo 2^128, so any borrow out (carry out) is lost. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE struct uint128 softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { struct uint128 z; z.v0 = a0 - b0; z.v64 = a64 - b64; z.v64 -= (a0 < b0); return z; } #else struct uint128 softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ); #endif #endif #ifndef softfloat_sub256M /*---------------------------------------------------------------------------- | Subtracts the 256-bit integer pointed to by `bPtr' from the 256-bit integer | pointed to by `aPtr'. The addition is modulo 2^256, so any borrow out | (carry out) is lost. The difference is stored at the location pointed to | by `zPtr'. Each of `aPtr', `bPtr', and `zPtr' points to an array of four | 64-bit elements that concatenate in the platform's normal endian order to | form a 256-bit integer. *----------------------------------------------------------------------------*/ void softfloat_sub256M( const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ); #endif #ifndef softfloat_mul64ByShifted32To128 /*---------------------------------------------------------------------------- | Returns the 128-bit product of `a', `b', and 2^32. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (3 <= INLINE_LEVEL) INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) { uint_fast64_t mid; struct uint128 z; mid = (uint_fast64_t) (uint32_t) a * b; z.v0 = mid<<32; z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); return z; } #else struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ); #endif #endif #ifndef softfloat_mul64To128 /*---------------------------------------------------------------------------- | Returns the 128-bit product of `a' and `b'. *----------------------------------------------------------------------------*/ struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ); #endif #ifndef softfloat_mul128By32 /*---------------------------------------------------------------------------- | Returns the product of the 128-bit integer formed by concatenating `a64' and | `a0', multiplied by `b'. The multiplication is modulo 2^128; any overflow | bits are discarded. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (4 <= INLINE_LEVEL) INLINE struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) { struct uint128 z; uint_fast64_t mid; uint_fast32_t carry; z.v0 = a0 * b; mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); return z; } #else struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ); #endif #endif #ifndef softfloat_mul128To256M /*---------------------------------------------------------------------------- | Multiplies the 128-bit unsigned integer formed by concatenating `a64' and | `a0' by the 128-bit unsigned integer formed by concatenating `b64' and | `b0'. The 256-bit product is stored at the location pointed to by `zPtr'. | Argument `zPtr' points to an array of four 64-bit elements that concatenate | in the platform's normal endian order to form a 256-bit integer. *----------------------------------------------------------------------------*/ void softfloat_mul128To256M( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ); #endif #else /*---------------------------------------------------------------------------- | The following functions are needed only when `SOFTFLOAT_FAST_INT64' is not | defined. *----------------------------------------------------------------------------*/ #ifndef softfloat_compare96M /*---------------------------------------------------------------------------- | Compares the two 96-bit unsigned integers pointed to by `aPtr' and `bPtr'. | Returns -1 if the first integer (A) is less than the second (B); returns 0 | if the two integers are equal; and returns +1 if the first integer (A) | is greater than the second (B). (The result is thus the signum of A - B.) | Each of `aPtr' and `bPtr' points to an array of three 32-bit elements that | concatenate in the platform's normal endian order to form a 96-bit integer. *----------------------------------------------------------------------------*/ int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ); #endif #ifndef softfloat_compare128M /*---------------------------------------------------------------------------- | Compares the two 128-bit unsigned integers pointed to by `aPtr' and `bPtr'. | Returns -1 if the first integer (A) is less than the second (B); returns 0 | if the two integers are equal; and returns +1 if the first integer (A) | is greater than the second (B). (The result is thus the signum of A - B.) | Each of `aPtr' and `bPtr' points to an array of four 32-bit elements that | concatenate in the platform's normal endian order to form a 128-bit integer. *----------------------------------------------------------------------------*/ int_fast8_t softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ); #endif #ifndef softfloat_shortShiftLeft64To96M /*---------------------------------------------------------------------------- | Extends `a' to 96 bits and shifts the value left by the number of bits given | in `count', which must be in the range 1 to 31. The result is stored at the | location pointed to by `zPtr'. Argument `zPtr' points to an array of three | 32-bit elements that concatenate in the platform's normal endian order to | form a 96-bit integer. *----------------------------------------------------------------------------*/ #if defined INLINE_LEVEL && (2 <= INLINE_LEVEL) INLINE void softfloat_shortShiftLeft64To96M( uint64_t a, uint_fast8_t count, uint32_t *zPtr ) { zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - count; zPtr[indexWord( 3, 2 )] = a>>32; zPtr[indexWord( 3, 1 )] = a; } #else void softfloat_shortShiftLeft64To96M( uint64_t a, uint_fast8_t count, uint32_t *zPtr ); #endif #endif #ifndef softfloat_shortShiftLeftM /*---------------------------------------------------------------------------- | Shifts the N-bit unsigned integer pointed to by `aPtr' left by the number | of bits given in `count', where N = `size_words' * 32. The value of `count' | must be in the range 1 to 31. Any nonzero bits shifted off are lost. The | shifted N-bit result is stored at the location pointed to by `zPtr'. Each | of `aPtr' and `zPtr' points to a `size_words'-long array of 32-bit elements | that concatenate in the platform's normal endian order to form an N-bit | integer. *----------------------------------------------------------------------------*/ void softfloat_shortShiftLeftM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ); #endif #ifndef softfloat_shortShiftLeft96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shortShiftLeftM' with | `size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_shortShiftLeft96M( aPtr, count, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, count, zPtr ) #endif #ifndef softfloat_shortShiftLeft128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shortShiftLeftM' with | `size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_shortShiftLeft128M( aPtr, count, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, count, zPtr ) #endif #ifndef softfloat_shortShiftLeft160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shortShiftLeftM' with | `size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_shortShiftLeft160M( aPtr, count, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftLeftM /*---------------------------------------------------------------------------- | Shifts the N-bit unsigned integer pointed to by `aPtr' left by the number | of bits given in `count', where N = `size_words' * 32. The value of `count' | must not be zero. Any nonzero bits shifted off are lost. The shifted | N-bit result is stored at the location pointed to by `zPtr'. Each of `aPtr' | and `zPtr' points to a `size_words'-long array of 32-bit elements that | concatenate in the platform's normal endian order to form an N-bit integer. | The value of `count' can be arbitrarily large. In particular, if `count' | is greater than N, the stored result will be 0. *----------------------------------------------------------------------------*/ void softfloat_shiftLeftM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t count, uint32_t *zPtr ); #endif #ifndef softfloat_shiftLeft96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftLeftM' with | `size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_shiftLeft96M( aPtr, count, zPtr ) softfloat_shiftLeftM( 3, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftLeft128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftLeftM' with | `size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_shiftLeft128M( aPtr, count, zPtr ) softfloat_shiftLeftM( 4, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftLeft160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftLeftM' with | `size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_shiftLeft160M( aPtr, count, zPtr ) softfloat_shiftLeftM( 5, aPtr, count, zPtr ) #endif #ifndef softfloat_shortShiftRightM /*---------------------------------------------------------------------------- | Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number | of bits given in `count', where N = `size_words' * 32. The value of `count' | must be in the range 1 to 31. Any nonzero bits shifted off are lost. The | shifted N-bit result is stored at the location pointed to by `zPtr'. Each | of `aPtr' and `zPtr' points to a `size_words'-long array of 32-bit elements | that concatenate in the platform's normal endian order to form an N-bit | integer. *----------------------------------------------------------------------------*/ void softfloat_shortShiftRightM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ); #endif #ifndef softfloat_shortShiftRight128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shortShiftRightM' with | `size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_shortShiftRight128M( aPtr, count, zPtr ) softfloat_shortShiftRightM( 4, aPtr, count, zPtr ) #endif #ifndef softfloat_shortShiftRight160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shortShiftRightM' with | `size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_shortShiftRight160M( aPtr, count, zPtr ) softfloat_shortShiftRightM( 5, aPtr, count, zPtr ) #endif #ifndef softfloat_shortShiftRightJamM /*---------------------------------------------------------------------------- | Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number | of bits given in `count', where N = `size_words' * 32. The value of `count' | must be in the range 1 to 31. If any nonzero bits are shifted off, they are | "jammed" into the least-significant bit of the shifted value by setting the | least-significant bit to 1. This shifted-and-jammed N-bit result is stored | at the location pointed to by `zPtr'. Each of `aPtr' and `zPtr' points | to a `size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ void softfloat_shortShiftRightJamM( uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * ); #endif #ifndef softfloat_shortShiftRightJam160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shortShiftRightJamM' with | `size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_shortShiftRightJam160M( aPtr, count, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftRightM /*---------------------------------------------------------------------------- | Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number | of bits given in `count', where N = `size_words' * 32. The value of `count' | must not be zero. Any nonzero bits shifted off are lost. The shifted | N-bit result is stored at the location pointed to by `zPtr'. Each of `aPtr' | and `zPtr' points to a `size_words'-long array of 32-bit elements that | concatenate in the platform's normal endian order to form an N-bit integer. | The value of `count' can be arbitrarily large. In particular, if `count' | is greater than N, the stored result will be 0. *----------------------------------------------------------------------------*/ void softfloat_shiftRightM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t count, uint32_t *zPtr ); #endif #ifndef softfloat_shiftRight96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftRightM' with | `size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_shiftRight96M( aPtr, count, zPtr ) softfloat_shiftRightM( 3, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftRightJamM /*---------------------------------------------------------------------------- | Shifts the N-bit unsigned integer pointed to by `aPtr' right by the number | of bits given in `count', where N = `size_words' * 32. The value of `count' | must not be zero. If any nonzero bits are shifted off, they are "jammed" | into the least-significant bit of the shifted value by setting the least- | significant bit to 1. This shifted-and-jammed N-bit result is stored | at the location pointed to by `zPtr'. Each of `aPtr' and `zPtr' points | to a `size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. | The value of `count' can be arbitrarily large. In particular, if `count' | is greater than N, the stored result will be either 0 or 1, depending on | whether the original N bits are all zeros. *----------------------------------------------------------------------------*/ void softfloat_shiftRightJamM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t count, uint32_t *zPtr ); #endif #ifndef softfloat_shiftRightJam96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftRightJamM' with | `size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_shiftRightJam96M( aPtr, count, zPtr ) softfloat_shiftRightJamM( 3, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftRightJam128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftRightJamM' with | `size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_shiftRightJam128M( aPtr, count, zPtr ) softfloat_shiftRightJamM( 4, aPtr, count, zPtr ) #endif #ifndef softfloat_shiftRightJam160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_shiftRightJamM' with | `size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_shiftRightJam160M( aPtr, count, zPtr ) softfloat_shiftRightJamM( 5, aPtr, count, zPtr ) #endif #ifndef softfloat_addM /*---------------------------------------------------------------------------- | Adds the two N-bit integers pointed to by `aPtr' and `bPtr', where N = | `size_words' * 32. The addition is modulo 2^N, so any carry out is lost. | The N-bit sum is stored at the location pointed to by `zPtr'. Each of | `aPtr', `bPtr', and `zPtr' points to a `size_words'-long array of 32-bit | elements that concatenate in the platform's normal endian order to form an | N-bit integer. *----------------------------------------------------------------------------*/ void softfloat_addM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); #endif #ifndef softfloat_add96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_addM' with `size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr ) #endif #ifndef softfloat_add128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_addM' with `size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr ) #endif #ifndef softfloat_add160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_addM' with `size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr ) #endif #ifndef softfloat_addCarryM /*---------------------------------------------------------------------------- | Adds the two N-bit unsigned integers pointed to by `aPtr' and `bPtr', where | N = `size_words' * 32, plus `carry', which must be either 0 or 1. The N-bit | sum (modulo 2^N) is stored at the location pointed to by `zPtr', and any | carry out is returned as the result. Each of `aPtr', `bPtr', and `zPtr' | points to a `size_words'-long array of 32-bit elements that concatenate in | the platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ uint_fast8_t softfloat_addCarryM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint_fast8_t carry, uint32_t *zPtr ); #endif #ifndef softfloat_addComplCarryM /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_addCarryM', except that | the value of the unsigned integer pointed to by `bPtr' is bit-wise completed | before the addition. *----------------------------------------------------------------------------*/ uint_fast8_t softfloat_addComplCarryM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint_fast8_t carry, uint32_t *zPtr ); #endif #ifndef softfloat_addComplCarry96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_addComplCarryM' with | `size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr ) #endif #ifndef softfloat_negXM /*---------------------------------------------------------------------------- | Replaces the N-bit unsigned integer pointed to by `zPtr' by the | 2s-complement of itself, where N = `size_words' * 32. Argument `zPtr' | points to a `size_words'-long array of 32-bit elements that concatenate in | the platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ); #endif #ifndef softfloat_negX96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_negXM' with `size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr ) #endif #ifndef softfloat_negX128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_negXM' with `size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr ) #endif #ifndef softfloat_negX160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_negXM' with `size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr ) #endif #ifndef softfloat_negX256M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_negXM' with `size_words' | = 8 (N = 256). *----------------------------------------------------------------------------*/ #define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr ) #endif #ifndef softfloat_sub1XM /*---------------------------------------------------------------------------- | Subtracts 1 from the N-bit integer pointed to by `zPtr', where N = | `size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry | out) is lost. Argument `zPtr' points to a `size_words'-long array of 32-bit | elements that concatenate in the platform's normal endian order to form an | N-bit integer. *----------------------------------------------------------------------------*/ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ); #endif #ifndef softfloat_sub1X96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_sub1XM' with `size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr ) #endif #ifndef softfloat_sub1X160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_sub1XM' with `size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr ) #endif #ifndef softfloat_subM /*---------------------------------------------------------------------------- | Subtracts the two N-bit integers pointed to by `aPtr' and `bPtr', where N = | `size_words' * 32. The subtraction is modulo 2^N, so any borrow out (carry | out) is lost. The N-bit difference is stored at the location pointed to by | `zPtr'. Each of `aPtr', `bPtr', and `zPtr' points to a `size_words'-long | array of 32-bit elements that concatenate in the platform's normal endian | order to form an N-bit integer. *----------------------------------------------------------------------------*/ void softfloat_subM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); #endif #ifndef softfloat_sub96M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_subM' with `size_words' | = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr ) #endif #ifndef softfloat_sub128M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_subM' with `size_words' | = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr ) #endif #ifndef softfloat_sub160M /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_subM' with `size_words' | = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr ) #endif #ifndef softfloat_mul64To128M /*---------------------------------------------------------------------------- | Multiplies `a' and `b' and stores the 128-bit product at the location | pointed to by `zPtr'. Argument `zPtr' points to an array of four 32-bit | elements that concatenate in the platform's normal endian order to form a | 128-bit integer. *----------------------------------------------------------------------------*/ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ); #endif #ifndef softfloat_mul128MTo256M /*---------------------------------------------------------------------------- | Multiplies the two 128-bit unsigned integers pointed to by `aPtr' and | `bPtr', and stores the 256-bit product at the location pointed to by `zPtr'. | Each of `aPtr' and `bPtr' points to an array of four 32-bit elements that | concatenate in the platform's normal endian order to form a 128-bit integer. | Argument `zPtr' points to an array of eight 32-bit elements that concatenate | to form a 256-bit integer. *----------------------------------------------------------------------------*/ void softfloat_mul128MTo256M( const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ); #endif #ifndef softfloat_remStepMBy32 /*---------------------------------------------------------------------------- | Performs a "remainder reduction step" as follows: Arguments `remPtr' and | `bPtr' both point to N-bit unsigned integers, where N = `size_words' * 32. | Defining R and B as the values of those integers, the expression (R<<`count') | - B * q is computed modulo 2^N, and the N-bit result is stored at the | location pointed to by `zPtr'. Each of `remPtr', `bPtr', and `zPtr' points | to a `size_words'-long array of 32-bit elements that concatenate in the | platform's normal endian order to form an N-bit integer. *----------------------------------------------------------------------------*/ void softfloat_remStepMBy32( uint_fast8_t size_words, const uint32_t *remPtr, uint_fast8_t count, const uint32_t *bPtr, uint32_t q, uint32_t *zPtr ); #endif #ifndef softfloat_remStep96MBy32 /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_remStepMBy32' with | `size_words' = 3 (N = 96). *----------------------------------------------------------------------------*/ #define softfloat_remStep96MBy32( remPtr, count, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, count, bPtr, q, zPtr ) #endif #ifndef softfloat_remStep128MBy32 /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_remStepMBy32' with | `size_words' = 4 (N = 128). *----------------------------------------------------------------------------*/ #define softfloat_remStep128MBy32( remPtr, count, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, count, bPtr, q, zPtr ) #endif #ifndef softfloat_remStep160MBy32 /*---------------------------------------------------------------------------- | This function or macro is the same as `softfloat_remStepMBy32' with | `size_words' = 5 (N = 160). *----------------------------------------------------------------------------*/ #define softfloat_remStep160MBy32( remPtr, count, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, count, bPtr, q, zPtr ) #endif #endif #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat.h000066400000000000000000000356221464416617300275030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ /*============================================================================ | Note: If SoftFloat is made available as a general library for programs to | use, it is strongly recommended that a platform-specific version of this | header, "softfloat.h", be created that folds in "softfloat_types.h" and that | eliminates all dependencies on compile-time macros. *============================================================================*/ #ifndef softfloat_h #define softfloat_h 1 #include #include #include "softfloat_types.h" /*---------------------------------------------------------------------------- | Software floating-point underflow tininess-detection mode. *----------------------------------------------------------------------------*/ extern uint_fast8_t softfloat_detectTininess; enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 }; /*---------------------------------------------------------------------------- | Software floating-point rounding mode. *----------------------------------------------------------------------------*/ extern uint_fast8_t softfloat_roundingMode; enum { softfloat_round_near_even = 0, softfloat_round_minMag = 1, softfloat_round_min = 2, softfloat_round_max = 3, softfloat_round_near_maxMag = 4 }; /*---------------------------------------------------------------------------- | Software floating-point exception flags. *----------------------------------------------------------------------------*/ extern uint_fast8_t softfloat_exceptionFlags; enum { softfloat_flag_inexact = 1, softfloat_flag_underflow = 2, softfloat_flag_overflow = 4, softfloat_flag_infinite = 8, softfloat_flag_invalid = 16 }; /*---------------------------------------------------------------------------- | Routine to raise any or all of the software floating-point exception flags. *----------------------------------------------------------------------------*/ void softfloat_raiseFlags( uint_fast8_t ); /*---------------------------------------------------------------------------- | Integer-to-floating-point conversion routines. *----------------------------------------------------------------------------*/ float32_t ui32_to_f32( uint32_t ); float64_t ui32_to_f64( uint32_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t ui32_to_extF80( uint32_t ); float128_t ui32_to_f128( uint32_t ); #endif void ui32_to_extF80M( uint32_t, extFloat80_t * ); void ui32_to_f128M( uint32_t, float128_t * ); float32_t ui64_to_f32( uint64_t ); float64_t ui64_to_f64( uint64_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t ui64_to_extF80( uint64_t ); float128_t ui64_to_f128( uint64_t ); #endif void ui64_to_extF80M( uint64_t, extFloat80_t * ); void ui64_to_f128M( uint64_t, float128_t * ); float32_t i32_to_f32( int32_t ); float64_t i32_to_f64( int32_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t i32_to_extF80( int32_t ); float128_t i32_to_f128( int32_t ); #endif void i32_to_extF80M( int32_t, extFloat80_t * ); void i32_to_f128M( int32_t, float128_t * ); float32_t i64_to_f32( int64_t ); float64_t i64_to_f64( int64_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t i64_to_extF80( int64_t ); float128_t i64_to_f128( int64_t ); #endif void i64_to_extF80M( int64_t, extFloat80_t * ); void i64_to_f128M( int64_t, float128_t * ); /*---------------------------------------------------------------------------- | 32-bit (single-precision) floating-point operations. *----------------------------------------------------------------------------*/ uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool ); uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool ); int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool ); int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool ); uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); float64_t f32_to_f64( float32_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t f32_to_extF80( float32_t ); float128_t f32_to_f128( float32_t ); #endif void f32_to_extF80M( float32_t, extFloat80_t * ); void f32_to_f128M( float32_t, float128_t * ); float32_t f32_roundToInt( float32_t, uint_fast8_t, bool ); float32_t f32_add( float32_t, float32_t ); float32_t f32_sub( float32_t, float32_t ); float32_t f32_mul( float32_t, float32_t ); float32_t f32_mulAdd( float32_t, float32_t, float32_t ); float32_t f32_div( float32_t, float32_t ); float32_t f32_rem( float32_t, float32_t ); float32_t f32_sqrt( float32_t ); bool f32_eq( float32_t, float32_t ); bool f32_le( float32_t, float32_t ); bool f32_lt( float32_t, float32_t ); bool f32_eq_signaling( float32_t, float32_t ); bool f32_le_quiet( float32_t, float32_t ); bool f32_lt_quiet( float32_t, float32_t ); bool f32_isSignalingNaN( float32_t ); /*---------------------------------------------------------------------------- | 64-bit (double-precision) floating-point operations. *----------------------------------------------------------------------------*/ uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool ); uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool ); int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool ); int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool ); uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); float32_t f64_to_f32( float64_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t f64_to_extF80( float64_t ); float128_t f64_to_f128( float64_t ); #endif void f64_to_extF80M( float64_t, extFloat80_t * ); void f64_to_f128M( float64_t, float128_t * ); float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); float64_t f64_add( float64_t, float64_t ); float64_t f64_sub( float64_t, float64_t ); float64_t f64_mul( float64_t, float64_t ); float64_t f64_mulAdd( float64_t, float64_t, float64_t ); float64_t f64_div( float64_t, float64_t ); float64_t f64_rem( float64_t, float64_t ); float64_t f64_sqrt( float64_t ); bool f64_eq( float64_t, float64_t ); bool f64_le( float64_t, float64_t ); bool f64_lt( float64_t, float64_t ); bool f64_eq_signaling( float64_t, float64_t ); bool f64_le_quiet( float64_t, float64_t ); bool f64_lt_quiet( float64_t, float64_t ); bool f64_isSignalingNaN( float64_t ); /*---------------------------------------------------------------------------- | Rounding precision for 80-bit extended double-precision floating-point. | Valid values are 32, 64, and 80. *----------------------------------------------------------------------------*/ extern uint_fast8_t extF80_roundingPrecision; /*---------------------------------------------------------------------------- | 80-bit extended double-precision floating-point operations. *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_INT64 uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool ); uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool ); int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool ); int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool ); uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool ); uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool ); int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool ); int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool ); float32_t extF80_to_f32( extFloat80_t ); float64_t extF80_to_f64( extFloat80_t ); float128_t extF80_to_f128( extFloat80_t ); extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool ); extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); extFloat80_t extF80_sqrt( extFloat80_t ); bool extF80_eq( extFloat80_t, extFloat80_t ); bool extF80_le( extFloat80_t, extFloat80_t ); bool extF80_lt( extFloat80_t, extFloat80_t ); bool extF80_eq_signaling( extFloat80_t, extFloat80_t ); bool extF80_le_quiet( extFloat80_t, extFloat80_t ); bool extF80_lt_quiet( extFloat80_t, extFloat80_t ); bool extF80_isSignalingNaN( extFloat80_t ); #endif uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool ); uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool ); int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool ); int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool ); uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool ); uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool ); int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool ); int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool ); float32_t extF80M_to_f32( const extFloat80_t * ); float64_t extF80M_to_f64( const extFloat80_t * ); void extF80M_to_f128M( const extFloat80_t *, float128_t * ); void extF80M_roundToInt( const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); bool extF80M_eq( const extFloat80_t *, const extFloat80_t * ); bool extF80M_le( const extFloat80_t *, const extFloat80_t * ); bool extF80M_lt( const extFloat80_t *, const extFloat80_t * ); bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); bool extF80M_isSignalingNaN( const extFloat80_t * ); /*---------------------------------------------------------------------------- | 128-bit (quadruple-precision) floating-point operations. *----------------------------------------------------------------------------*/ #ifdef SOFTFLOAT_FAST_INT64 uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool ); uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool ); int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool ); int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool ); uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool ); uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool ); int_fast32_t f128_to_i32_r_minMag( float128_t, bool ); int_fast64_t f128_to_i64_r_minMag( float128_t, bool ); float32_t f128_to_f32( float128_t ); float64_t f128_to_f64( float128_t ); extFloat80_t f128_to_extF80( float128_t ); float128_t f128_roundToInt( float128_t, uint_fast8_t, bool ); float128_t f128_add( float128_t, float128_t ); float128_t f128_sub( float128_t, float128_t ); float128_t f128_mul( float128_t, float128_t ); float128_t f128_mulAdd( float128_t, float128_t, float128_t ); float128_t f128_div( float128_t, float128_t ); float128_t f128_rem( float128_t, float128_t ); float128_t f128_sqrt( float128_t ); bool f128_eq( float128_t, float128_t ); bool f128_le( float128_t, float128_t ); bool f128_lt( float128_t, float128_t ); bool f128_eq_signaling( float128_t, float128_t ); bool f128_le_quiet( float128_t, float128_t ); bool f128_lt_quiet( float128_t, float128_t ); bool f128_isSignalingNaN( float128_t ); #endif uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool ); uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool ); int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool ); int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool ); uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool ); uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool ); int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool ); int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool ); float32_t f128M_to_f32( const float128_t * ); float64_t f128M_to_f64( const float128_t * ); void f128M_to_extF80M( const float128_t *, extFloat80_t * ); void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * ); void f128M_add( const float128_t *, const float128_t *, float128_t * ); void f128M_sub( const float128_t *, const float128_t *, float128_t * ); void f128M_mul( const float128_t *, const float128_t *, float128_t * ); void f128M_mulAdd( const float128_t *, const float128_t *, const float128_t *, float128_t * ); void f128M_div( const float128_t *, const float128_t *, float128_t * ); void f128M_rem( const float128_t *, const float128_t *, float128_t * ); void f128M_sqrt( const float128_t *, float128_t * ); bool f128M_eq( const float128_t *, const float128_t * ); bool f128M_le( const float128_t *, const float128_t * ); bool f128M_lt( const float128_t *, const float128_t * ); bool f128M_eq_signaling( const float128_t *, const float128_t * ); bool f128M_le_quiet( const float128_t *, const float128_t * ); bool f128M_lt_quiet( const float128_t *, const float128_t * ); bool f128M_isSignalingNaN( const float128_t * ); #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/include/softfloat_types.h000066400000000000000000000076621464416617300307320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /*============================================================================ This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #ifndef softfloat_types_h #define softfloat_types_h 1 #include /*---------------------------------------------------------------------------- | Types used to pass 32-bit, 64-bit, and 128-bit floating-point arguments and | results to/from functions. These types must be exactly 32 bits, 64 bits, | and 128 bits in size, respectively. Where a platform has "native" support | for IEEE-Standard floating-point formats, the types below may, if desired, | be defined as aliases for the native types (typically `float' and `double', | and possibly `long double'). *----------------------------------------------------------------------------*/ typedef struct { uint32_t v; } float32_t; typedef struct { uint64_t v; } float64_t; typedef struct { uint64_t v[2]; } float128_t; /*---------------------------------------------------------------------------- | The format of an 80-bit extended floating-point number in memory. This | structure must contain a 16-bit field named `signExp' and a 64-bit field | named `signif'. *----------------------------------------------------------------------------*/ #ifdef LITTLEENDIAN struct extFloat80M { uint64_t signif; uint16_t signExp; }; #else struct extFloat80M { uint16_t signExp; uint64_t signif; }; #endif /*---------------------------------------------------------------------------- | The type used to pass 80-bit extended floating-point arguments and | results to/from functions. This type must have size identical to | `struct extFloat80M'. Type `extFloat80_t' can be defined as an alias for | `struct extFloat80M'. Alternatively, if a platform has "native" support | for IEEE-Standard 80-bit extended floating-point, it may be possible, | if desired, to define `extFloat80_t' as an alias for the native type | (presumably either `long double' or a nonstandard compiler-intrinsic type). | In that case, the `signif' and `signExp' fields of `struct extFloat80M' | must align exactly with the locations in memory of the sign, exponent, and | significand of the native type. *----------------------------------------------------------------------------*/ typedef struct extFloat80M extFloat80_t; #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_add128.c000066400000000000000000000041501464416617300253470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_add128 struct uint128 softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { struct uint128 z; z.v0 = a0 + b0; z.v64 = a64 + b64 + (z.v0 < a0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_add256M.c000066400000000000000000000046111464416617300254700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_add256M void softfloat_add256M( const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ) { unsigned int index; uint_fast8_t carry; uint64_t wordA, wordZ; index = indexWordLo( 4 ); carry = 0; for (;;) { wordA = aPtr[index]; wordZ = wordA + bPtr[index] + carry; zPtr[index] = wordZ; if ( index == indexWordHi( 4 ) ) break; carry = carry ? (wordZ <= wordA) : (wordZ < wordA); index += wordIncr; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addCarryM.c000066400000000000000000000047721464416617300262440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_addCarryM uint_fast8_t softfloat_addCarryM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint_fast8_t carry, uint32_t *zPtr ) { unsigned int index, lastIndex; uint32_t wordA, wordZ; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); for (;;) { wordA = aPtr[index]; wordZ = wordA + bPtr[index] + carry; zPtr[index] = wordZ; carry = carry ? (wordZ <= wordA) : (wordZ < wordA); if ( index == lastIndex ) break; index += wordIncr; } return carry; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addComplCarryM.c000066400000000000000000000050051464416617300272250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_addComplCarryM uint_fast8_t softfloat_addComplCarryM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint_fast8_t carry, uint32_t *zPtr ) { unsigned int index, lastIndex; uint32_t wordA, wordZ; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); for (;;) { wordA = aPtr[index]; wordZ = wordA + ~bPtr[index] + carry; zPtr[index] = wordZ; carry = carry ? (wordZ <= wordA) : (wordZ < wordA); if ( index == lastIndex ) break; index += wordIncr; } return carry; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addExtF80M.c000066400000000000000000000160061464416617300261730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" void softfloat_addExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr, bool negateB ) { uint32_t uiA64; int32_t expA; uint32_t uiB64; int32_t expB; uint32_t uiZ64; bool signZ, signB; const struct extFloat80M *tempSPtr; uint64_t sigZ, sigB; void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); int32_t expDiff; uint32_t extSigX[3], sigZExtra; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; expA = expExtF80UI64( uiA64 ); uiB64 = bSPtr->signExp; expB = expExtF80UI64( uiB64 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNExtF80M( aSPtr, bSPtr, zSPtr ) ) return; uiZ64 = uiA64; if ( expB == 0x7FFF ) { uiZ64 = uiB64 ^ packToExtF80UI64( negateB, 0 ); if ( (expA == 0x7FFF) && (uiZ64 != uiA64) ) { softfloat_invalidExtF80M( zSPtr ); return; } } zSPtr->signExp = uiZ64; zSPtr->signif = UINT64_C( 0x8000000000000000 ); return; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signZ = signExtF80UI64( uiA64 ); signB = signExtF80UI64( uiB64 ) ^ negateB; negateB = (signZ != signB); if ( expA < expB ) { signZ = signB; expA = expB; expB = expExtF80UI64( uiA64 ); tempSPtr = aSPtr; aSPtr = bSPtr; bSPtr = tempSPtr; } if ( ! expB ) { expB = 1; if ( ! expA ) expA = 1; } sigZ = aSPtr->signif; sigB = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ roundPackRoutinePtr = softfloat_roundPackMToExtF80M; expDiff = expA - expB; if ( expDiff ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ extSigX[indexWord( 3, 2 )] = sigB>>32; extSigX[indexWord( 3, 1 )] = sigB; extSigX[indexWord( 3, 0 )] = 0; softfloat_shiftRightJam96M( extSigX, expDiff, extSigX ); sigB = (uint64_t) extSigX[indexWord( 3, 2 )]<<32 | extSigX[indexWord( 3, 1 )]; if ( negateB ) { sigZ -= sigB; sigZExtra = extSigX[indexWordLo( 3 )]; if ( sigZExtra ) { --sigZ; sigZExtra = -sigZExtra; } if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) { if ( sigZ & UINT64_C( 0x4000000000000000 ) ) { --expA; sigZ = sigZ<<1 | sigZExtra>>31; sigZExtra <<= 1; } else { roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M; } } } else { sigZ += sigB; if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto sigZ; sigZExtra = (uint32_t) sigZ<<31 | (extSigX[indexWordLo( 3 )] != 0); goto completeNormAfterAdd; } } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ sigZExtra = 0; if ( negateB ) { if ( sigZ < sigB ) { signZ = ! signZ; sigZ = sigB - sigZ; } else { sigZ -= sigB; if ( ! sigZ ) { signZ = (softfloat_roundingMode == softfloat_round_min); zSPtr->signExp = packToExtF80UI64( signZ, 0 ); zSPtr->signif = 0; return; } } roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M; } else { sigZ += sigB; if ( sigZ < sigB ) { sigZExtra = (uint32_t) sigZ<<31; completeNormAfterAdd: ++expA; sigZ = UINT64_C( 0x8000000000000000 ) | sigZ>>1; } else { if ( ! (sigZ & UINT64_C( 0x8000000000000000 )) ) { roundPackRoutinePtr = softfloat_normRoundPackMToExtF80M; } } } } extSigX[indexWord( 3, 0 )] = sigZExtra; sigZ: extSigX[indexWord( 3, 2 )] = sigZ>>32; extSigX[indexWord( 3, 1 )] = sigZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ roundPack: (*roundPackRoutinePtr)( signZ, expA, extSigX, extF80_roundingPrecision, zSPtr ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addF128M.c000066400000000000000000000176631464416617300256070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" void softfloat_addF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr, bool negateB ) { uint32_t uiA96; int32_t expA; uint32_t uiB96; int32_t expB; uint32_t uiZ96; bool signZ, signB; const uint32_t *tempPtr; uint32_t sig96A, sig96B; int32_t expDiff; uint_fast8_t (*addCarryMRoutinePtr)( uint_fast8_t, const uint32_t *, const uint32_t *, uint_fast8_t, uint32_t * ); uint32_t extSigZ[5], wordSigZ; uint_fast8_t carry; void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; expA = expF128UI96( uiA96 ); uiB96 = bWPtr[indexWordHi( 4 )]; expB = expF128UI96( uiB96 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) return; uiZ96 = uiA96; if ( expB == 0x7FFF ) { uiZ96 = uiB96 ^ packToF128UI96( negateB, 0, 0 ); if ( (expA == 0x7FFF) && (uiZ96 != uiA96) ) { softfloat_invalidF128M( zWPtr ); return; } } zWPtr[indexWordHi( 4 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; return; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signZ = signF128UI96( uiA96 ); signB = signF128UI96( uiB96 ) ^ negateB; negateB = (signZ != signB); if ( (uint32_t) (uiA96<<1) < (uint32_t) (uiB96<<1) ) { signZ = signB; expA = expB; expB = expF128UI96( uiA96 ); tempPtr = aWPtr; aWPtr = bWPtr; bWPtr = tempPtr; uiA96 = uiB96; uiB96 = bWPtr[indexWordHi( 4 )]; } sig96A = fracF128UI96( uiA96 ); sig96B = fracF128UI96( uiB96 ); if ( expA ) { --expA; sig96A |= 0x00010000; if ( expB ) { --expB; sig96B |= 0x00010000; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ addCarryMRoutinePtr = negateB ? softfloat_addComplCarryM : softfloat_addCarryM; expDiff = expA - expB; if ( expDiff ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ extSigZ[indexWordHi( 5 )] = sig96B; extSigZ[indexWord( 5, 3 )] = bWPtr[indexWord( 4, 2 )]; extSigZ[indexWord( 5, 2 )] = bWPtr[indexWord( 4, 1 )]; extSigZ[indexWord( 5, 1 )] = bWPtr[indexWord( 4, 0 )]; extSigZ[indexWord( 5, 0 )] = 0; softfloat_shiftRightJam160M( extSigZ, expDiff, extSigZ ); sig96B = extSigZ[indexWordHi( 5 )]; carry = 0; if ( negateB ) { sig96B = ~sig96B; wordSigZ = extSigZ[indexWordLo( 5 )]; extSigZ[indexWordLo( 5 )] = -wordSigZ; carry = ! wordSigZ; } carry = (*addCarryMRoutinePtr)( 3, &aWPtr[indexMultiwordLo( 4, 3 )], &extSigZ[indexMultiword( 5, 3, 1 )], carry, &extSigZ[indexMultiword( 5, 3, 1 )] ); wordSigZ = sig96A + sig96B + carry; } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ extSigZ[indexWordLo( 5 )] = 0; carry = (*addCarryMRoutinePtr)( 3, &aWPtr[indexMultiwordLo( 4, 3 )], &bWPtr[indexMultiwordLo( 4, 3 )], negateB, &extSigZ[indexMultiword( 5, 3, 1 )] ); if ( negateB ) { wordSigZ = sig96A + ~sig96B + carry; if ( wordSigZ & 0x80000000 ) { signZ = ! signZ; carry = softfloat_addComplCarry96M( &bWPtr[indexMultiwordLo( 4, 3 )], &aWPtr[indexMultiwordLo( 4, 3 )], 1, &extSigZ[indexMultiword( 5, 3, 1 )] ); wordSigZ = sig96B + ~sig96A + carry; } else { if ( ! wordSigZ && ! extSigZ[indexWord( 5, 3 )] && ! ( extSigZ[indexWord( 5, 2 )] | extSigZ[indexWord( 5, 1 )] | extSigZ[indexWord( 5, 0 )] ) ) { signZ = (softfloat_roundingMode == softfloat_round_min); zWPtr[indexWordHi( 4 )] = packToF128UI96( signZ, 0, 0 ); zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; return; } } } else { wordSigZ = sig96A + sig96B + carry; } } extSigZ[indexWordHi( 5 )] = wordSigZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ roundPackRoutinePtr = softfloat_normRoundPackMToF128M; if ( 0x00010000 <= wordSigZ ) { if ( 0x00020000 <= wordSigZ ) { ++expA; softfloat_shortShiftRightJam160M( extSigZ, 1, extSigZ ); } roundPackRoutinePtr = softfloat_roundPackMToF128M; } (*roundPackRoutinePtr)( signZ, expA, extSigZ, zWPtr ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addM.c000066400000000000000000000047441464416617300252420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_addM void softfloat_addM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ) { unsigned int index, lastIndex; uint_fast8_t carry; uint32_t wordA, wordZ; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); carry = 0; for (;;) { wordA = aPtr[index]; wordZ = wordA + bPtr[index] + carry; zPtr[index] = wordZ; if ( index == lastIndex ) break; carry = carry ? (wordZ <= wordA) : (wordZ < wordA); index += wordIncr; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsExtF80.c000066400000000000000000000130641464416617300266670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t softfloat_addMagsExtF80( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; uint_fast64_t sigA; int_fast32_t expB; uint_fast64_t sigB; int_fast32_t expDiff; uint_fast16_t uiZ64; uint_fast64_t uiZ0, sigZ, sigZExtra; struct exp32_sig64 normExpSig; int_fast32_t expZ; struct uint64_extra sig64Extra; struct uint128 uiZ; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expExtF80UI64( uiA64 ); sigA = uiA0; expB = expExtF80UI64( uiB64 ); sigB = uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( ! expDiff ) { if ( expA == 0x7FFF ) { if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { goto propagateNaN; } uiZ64 = uiA64; uiZ0 = uiA0; goto uiZ; } sigZ = sigA + sigB; sigZExtra = 0; if ( ! expA ) { normExpSig = softfloat_normSubnormalExtF80Sig( sigZ ); expZ = normExpSig.exp + 1; sigZ = normExpSig.sig; goto roundAndPack; } expZ = expA; goto shiftRight1; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expDiff < 0 ) { if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = packToExtF80UI64( signZ, 0x7FFF ); uiZ0 = uiB0; goto uiZ; } expZ = expB; if ( ! expA ) { ++expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig64Extra = softfloat_shiftRightJam64Extra( sigA, 0, -expDiff ); sigA = sig64Extra.v; sigZExtra = sig64Extra.extra; } else { if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = uiA64; uiZ0 = uiA0; goto uiZ; } expZ = expA; if ( ! expB ) { --expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig64Extra = softfloat_shiftRightJam64Extra( sigB, 0, expDiff ); sigB = sig64Extra.v; sigZExtra = sig64Extra.extra; } newlyAligned: sigZ = sigA + sigB; if ( sigZ & UINT64_C( 0x8000000000000000 ) ) goto roundAndPack; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftRight1: sig64Extra = softfloat_shortShiftRightJam64Extra( sigZ, sigZExtra, 1 ); sigZ = sig64Extra.v | UINT64_C( 0x8000000000000000 ); sigZExtra = sig64Extra.extra; ++expZ; roundAndPack: return softfloat_roundPackToExtF80( signZ, expZ, sigZ, sigZExtra, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF128.c000066400000000000000000000117261464416617300262740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" float128_t softfloat_addMagsF128( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; struct uint128 sigA; int_fast32_t expB; struct uint128 sigB; int_fast32_t expDiff; struct uint128 uiZ, sigZ; int_fast32_t expZ; uint_fast64_t sigZExtra; struct uint128_extra sig128Extra; union ui128_f128 uZ; expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; expDiff = expA - expB; if ( ! expDiff ) { if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN; uiZ.v64 = uiA64; uiZ.v0 = uiA0; goto uiZ; } sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ); if ( ! expA ) { uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 ); uiZ.v0 = sigZ.v0; goto uiZ; } expZ = expA; sigZ.v64 |= UINT64_C( 0x0002000000000000 ); sigZExtra = 0; goto shiftRight1; } if ( expDiff < 0 ) { if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); uiZ.v0 = 0; goto uiZ; } expZ = expB; if ( expA ) { sigA.v64 |= UINT64_C( 0x0001000000000000 ); } else { ++expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig128Extra = softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff ); sigA = sig128Extra.v; sigZExtra = sig128Extra.extra; } else { if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 ) goto propagateNaN; uiZ.v64 = uiA64; uiZ.v0 = uiA0; goto uiZ; } expZ = expA; if ( expB ) { sigB.v64 |= UINT64_C( 0x0001000000000000 ); } else { --expDiff; sigZExtra = 0; if ( ! expDiff ) goto newlyAligned; } sig128Extra = softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff ); sigB = sig128Extra.v; sigZExtra = sig128Extra.extra; } newlyAligned: sigZ = softfloat_add128( sigA.v64 | UINT64_C( 0x0001000000000000 ), sigA.v0, sigB.v64, sigB.v0 ); --expZ; if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack; ++expZ; shiftRight1: sig128Extra = softfloat_shortShiftRightJam128Extra( sigZ.v64, sigZ.v0, sigZExtra, 1 ); sigZ = sig128Extra.v; sigZExtra = sig128Extra.extra; roundAndPack: return softfloat_roundPackToF128( signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra ); propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF32.c000066400000000000000000000072401464416617300262020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" float32_t softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) { int_fast16_t expA; uint_fast32_t sigA; int_fast16_t expB; uint_fast32_t sigB; int_fast16_t expDiff; uint_fast32_t uiZ; int_fast16_t expZ; uint_fast32_t sigZ; union ui32_f32 uZ; expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); expDiff = expA - expB; sigA <<= 6; sigB <<= 6; if ( ! expDiff ) { if ( expA == 0xFF ) { if ( sigA | sigB ) goto propagateNaN; uiZ = uiA; goto uiZ; } if ( ! expA ) { uiZ = packToF32UI( signZ, 0, (uiA + uiB) & 0x7FFFFFFF ); goto uiZ; } expZ = expA; sigZ = 0x40000000 + sigA + sigB; } else { if ( expDiff < 0 ) { if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; uiZ = packToF32UI( signZ, 0xFF, 0 ); goto uiZ; } expZ = expB; sigA += expA ? 0x20000000 : sigA; sigA = softfloat_shiftRightJam32( sigA, -expDiff ); } else { if ( expA == 0xFF ) { if ( sigA ) goto propagateNaN; uiZ = uiA; goto uiZ; } expZ = expA; sigB += expB ? 0x20000000 : sigB; sigB = softfloat_shiftRightJam32( sigB, expDiff ); } sigZ = 0x20000000 + sigA + sigB; if ( sigZ < 0x40000000 ) { --expZ; sigZ <<= 1; } } return softfloat_roundPackToF32( signZ, expZ, sigZ ); propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_addMagsF64.c000066400000000000000000000075001464416617300262060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" float64_t softfloat_addMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) { int_fast16_t expA; uint_fast64_t sigA; int_fast16_t expB; uint_fast64_t sigB; int_fast16_t expDiff; uint_fast64_t uiZ; int_fast16_t expZ; uint_fast64_t sigZ; union ui64_f64 uZ; expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); expDiff = expA - expB; sigA <<= 9; sigB <<= 9; if ( ! expDiff ) { if ( expA == 0x7FF ) { if ( sigA | sigB ) goto propagateNaN; uiZ = uiA; goto uiZ; } if ( ! expA ) { uiZ = packToF64UI( signZ, 0, (uiA + uiB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); goto uiZ; } expZ = expA; sigZ = UINT64_C( 0x4000000000000000 ) + sigA + sigB; } else { if ( expDiff < 0 ) { if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN; uiZ = packToF64UI( signZ, 0x7FF, 0 ); goto uiZ; } expZ = expB; sigA += expA ? UINT64_C( 0x2000000000000000 ) : sigA; sigA = softfloat_shiftRightJam64( sigA, -expDiff ); } else { if ( expA == 0x7FF ) { if ( sigA ) goto propagateNaN; uiZ = uiA; goto uiZ; } expZ = expA; sigB += expB ? UINT64_C( 0x2000000000000000 ) : sigB; sigB = softfloat_shiftRightJam64( sigB, expDiff ); } sigZ = UINT64_C( 0x2000000000000000 ) + sigA + sigB; if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { --expZ; sigZ <<= 1; } } return softfloat_roundPackToF64( signZ, expZ, sigZ ); propagateNaN: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecip32_1.c000066400000000000000000000054621464416617300272540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_approxRecip32_1 uint32_t softfloat_approxRecip32_1( uint32_t a ) { int index; uint16_t eps; static const uint16_t k0s[] = { 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201, 0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417 }; static const uint16_t k1s[] = { 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA, 0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211 }; uint16_t r0; uint32_t delta0; uint_fast32_t r; uint32_t sqrDelta0; index = a>>27 & 0xF; eps = (uint16_t) (a>>11); r0 = k0s[index] - ((k1s[index] * (uint_fast32_t) eps)>>20); delta0 = ~(uint_fast32_t) ((r0 * (uint_fast64_t) a)>>7); r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) delta0)>>24); sqrDelta0 = ((uint_fast64_t) delta0 * delta0)>>32; r += ((uint32_t) r * (uint_fast64_t) sqrDelta0)>>48; return r; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_approxRecipSqrt32_1.c000066400000000000000000000061041464416617300301200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_approxRecipSqrt32_1 uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a ) { int index; uint16_t eps; static const uint16_t k0s[] = { 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29, 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1 }; static const uint16_t k1s[] = { 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6, 0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD }; uint16_t r0; uint_fast32_t ESqrR0; uint32_t delta0; uint_fast32_t r; uint32_t sqrDelta0; index = (a>>27 & 0xE) + oddExpA; eps = (uint16_t) (a>>12); r0 = k0s[index] - ((k1s[index] * (uint_fast32_t) eps)>>20); ESqrR0 = (uint_fast32_t) r0 * r0; if ( ! oddExpA ) ESqrR0 <<= 1; delta0 = ~(uint_fast32_t) (((uint32_t) ESqrR0 * (uint_fast64_t) a)>>23); r = ((uint_fast32_t) r0<<16) + ((r0 * (uint_fast64_t) delta0)>>25); sqrDelta0 = ((uint_fast64_t) delta0 * delta0)>>32; r += ((uint32_t) ((r>>1) + (r>>3) - ((uint_fast32_t) r0<<14)) * (uint_fast64_t) sqrDelta0) >>48; if ( ! (r & 0x80000000) ) r = 0x80000000; return r; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_compare128M.c000066400000000000000000000045451464416617300263720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_compare128M int_fast8_t softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr ) { unsigned int index, lastIndex; uint32_t wordA, wordB; index = indexWordHi( 4 ); lastIndex = indexWordLo( 4 ); for (;;) { wordA = aPtr[index]; wordB = bPtr[index]; if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1; if ( index == lastIndex ) break; index -= wordIncr; } return 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_compare96M.c000066400000000000000000000045431464416617300263140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_compare96M int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr ) { unsigned int index, lastIndex; uint32_t wordA, wordB; index = indexWordHi( 3 ); lastIndex = indexWordLo( 3 ); for (;;) { wordA = aPtr[index]; wordB = bPtr[index]; if ( wordA != wordB ) return (wordA < wordB) ? -1 : 1; if ( index == lastIndex ) break; index -= wordIncr; } return 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_compareNonnormExtF80M.c000066400000000000000000000104361464416617300304410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat_types.h" int softfloat_compareNonnormExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr ) { uint_fast16_t uiA64, uiB64; uint64_t sigA; bool signB; uint64_t sigB; int32_t expA, expB; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA64 = aSPtr->signExp; uiB64 = bSPtr->signExp; sigA = aSPtr->signif; signB = signExtF80UI64( uiB64 ); sigB = bSPtr->signif; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( (uiA64 ^ uiB64) & 0x8000 ) { if ( ! (sigA | sigB) ) return 0; goto resultFromSignB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expExtF80UI64( uiA64 ); expB = expExtF80UI64( uiB64 ); if ( expA == 0x7FFF ) { if (expB == 0x7FFF) return 0; signB = ! signB; goto resultFromSignB; } if ( expB == 0x7FFF ) { goto resultFromSignB; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) expA = 1; if ( ! (sigA & UINT64_C( 0x8000000000000000 )) ) { if ( sigA ) { expA += softfloat_normExtF80SigM( &sigA ); } else { expA = -128; } } if ( ! expB ) expB = 1; if ( ! (sigB & UINT64_C( 0x8000000000000000 )) ) { if ( sigB ) { expB += softfloat_normExtF80SigM( &sigB ); } else { expB = -128; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signB ) { if ( expA < expB ) return 1; if ( (expB < expA) || (sigB < sigA) ) return -1; } else { if ( expB < expA ) return 1; if ( (expA < expB) || (sigA < sigB) ) return -1; } return (sigA != sigB); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ resultFromSignB: return signB ? 1 : -1; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros32.c000066400000000000000000000044571464416617300302020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_countLeadingZeros32 #define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 #include "primitives.h" uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) { uint_fast8_t count; count = 0; if ( a < 0x10000 ) { count = 16; a <<= 16; } if ( a < 0x1000000 ) { count += 8; a <<= 8; } count += softfloat_countLeadingZeros8[a>>24]; return count; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros64.c000066400000000000000000000052031464416617300301750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_countLeadingZeros64 #define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 #include "primitives.h" uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ) { uint_fast8_t count; uint32_t a32; count = 0; a32 = a>>32; if ( ! a32 ) { count = 32; a32 = a; } /*------------------------------------------------------------------------ | From here, result is current count + count leading zeros of `a32'. *------------------------------------------------------------------------*/ if ( a32 < 0x10000 ) { count += 16; a32 <<= 16; } if ( a32 < 0x1000000 ) { count += 8; a32 <<= 8; } count += softfloat_countLeadingZeros8[a32>>24]; return count; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_countLeadingZeros8.c000066400000000000000000000053731464416617300301230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" const uint_least8_t softfloat_countLeadingZeros8[256] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_eq128.c000066400000000000000000000040361464416617300252270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #ifndef softfloat_eq128 bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { return (a64 == b64) && (a0 == b0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidExtF80M.c000066400000000000000000000041141464416617300270660ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include "platform.h" #include "specialize.h" #include "softfloat.h" void softfloat_invalidExtF80M( struct extFloat80M *zSPtr ) { softfloat_raiseFlags( softfloat_flag_invalid ); zSPtr->signExp = defaultNaNExtF80UI64; zSPtr->signif = defaultNaNExtF80UI0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_invalidF128M.c000066400000000000000000000043421464416617300264730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitives.h" #include "specialize.h" #include "softfloat.h" void softfloat_invalidF128M( uint32_t *zWPtr ) { softfloat_raiseFlags( softfloat_flag_invalid ); zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96; zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64; zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32; zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_isNaNF128M.c000066400000000000000000000046411464416617300260570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "primitives.h" /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ bool softfloat_isNaNF128M( const uint32_t *aWPtr ) { uint32_t uiA96; uiA96 = aWPtr[indexWordHi( 4 )]; if ( (uiA96 & 0x7FFF0000) != 0x7FFF0000 ) return false; return ((uiA96 & 0x0000FFFF) != 0) || ((aWPtr[indexWord( 4, 2 )] | aWPtr[indexWord( 4, 1 )] | aWPtr[indexWord( 4, 0 )]) != 0); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_le128.c000066400000000000000000000040571464416617300252250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #ifndef softfloat_le128 bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_lt128.c000066400000000000000000000040561464416617300252430ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #ifndef softfloat_lt128 bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128By32.c000066400000000000000000000044431464416617300260610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_mul128By32 struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b ) { struct uint128 z; uint_fast64_t mid; uint_fast32_t carry; z.v0 = a0 * b; mid = (uint_fast64_t) (uint32_t) (a0>>32) * b; carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid); z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128MTo256M.c000066400000000000000000000101241464416617300264040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_mul128MTo256M void softfloat_mul128MTo256M( const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ) { uint32_t *lastZPtr, wordB; uint64_t dwordProd; uint32_t wordZ; uint_fast8_t carry; bPtr += indexWordLo( 4 ); lastZPtr = zPtr + indexMultiwordHi( 8, 5 ); zPtr += indexMultiwordLo( 8, 5 ); wordB = *bPtr; dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB; zPtr[indexWord( 5, 0 )] = dwordProd; dwordProd = (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32); zPtr[indexWord( 5, 1 )] = dwordProd; dwordProd = (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32); zPtr[indexWord( 5, 2 )] = dwordProd; dwordProd = (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32); zPtr[indexWord( 5, 3 )] = dwordProd; zPtr[indexWord( 5, 4 )] = dwordProd>>32; do { bPtr += wordIncr; zPtr += wordIncr; wordB = *bPtr; dwordProd = (uint64_t) aPtr[indexWord( 4, 0 )] * wordB; wordZ = zPtr[indexWord( 5, 0 )] + (uint32_t) dwordProd; zPtr[indexWord( 5, 0 )] = wordZ; carry = (wordZ < (uint32_t) dwordProd); dwordProd = (uint64_t) aPtr[indexWord( 4, 1 )] * wordB + (dwordProd>>32); wordZ = zPtr[indexWord( 5, 1 )] + (uint32_t) dwordProd + carry; zPtr[indexWord( 5, 1 )] = wordZ; carry = carry ? (wordZ <= (uint32_t) dwordProd) : (wordZ < (uint32_t) dwordProd); dwordProd = (uint64_t) aPtr[indexWord( 4, 2 )] * wordB + (dwordProd>>32); wordZ = zPtr[indexWord( 5, 2 )] + (uint32_t) dwordProd + carry; zPtr[indexWord( 5, 2 )] = wordZ; carry = carry ? (wordZ <= (uint32_t) dwordProd) : (wordZ < (uint32_t) dwordProd); dwordProd = (uint64_t) aPtr[indexWord( 4, 3 )] * wordB + (dwordProd>>32); wordZ = zPtr[indexWord( 5, 3 )] + (uint32_t) dwordProd + carry; zPtr[indexWord( 5, 3 )] = wordZ; carry = carry ? (wordZ <= (uint32_t) dwordProd) : (wordZ < (uint32_t) dwordProd); zPtr[indexWord( 5, 4 )] = (dwordProd>>32) + carry; } while ( zPtr != lastZPtr ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mul128To256M.c000066400000000000000000000052551464416617300263000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_mul128To256M #define softfloat_mul128To256M softfloat_mul128To256M #include "primitives.h" void softfloat_mul128To256M( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr ) { struct uint128 p0, p64, p128; uint_fast64_t z64, z128, z192; p0 = softfloat_mul64To128( a0, b0 ); zPtr[indexWord( 4, 0 )] = p0.v0; p64 = softfloat_mul64To128( a64, b0 ); z64 = p64.v0 + p0.v64; z128 = p64.v64 + (z64 < p64.v0); p128 = softfloat_mul64To128( a64, b64 ); z128 += p128.v0; z192 = p128.v64 + (z128 < p128.v0); p64 = softfloat_mul64To128( a0, b64 ); z64 += p64.v0; zPtr[indexWord( 4, 1 )] = z64; p64.v64 += (z64 < p64.v0); z128 += p64.v64; zPtr[indexWord( 4, 2 )] = z128; zPtr[indexWord( 4, 3 )] = z192 + (z128 < p64.v64); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64ByShifted32To128.c000066400000000000000000000043051464416617300300420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_mul64ByShifted32To128 struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b ) { uint_fast64_t mid; struct uint128 z; mid = (uint_fast64_t) (uint32_t) a * b; z.v0 = mid<<32; z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128.c000066400000000000000000000046311464416617300260750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_mul64To128 struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) { uint32_t a32, a0, b32, b0; struct uint128 z; uint64_t mid1, mid; a32 = a>>32; a0 = a; b32 = b>>32; b0 = b; z.v0 = (uint_fast64_t) a0 * b0; mid1 = (uint_fast64_t) a32 * b0; mid = mid1 + (uint_fast64_t) a0 * b32; z.v64 = (uint_fast64_t) a32 * b32; z.v64 += (uint_fast64_t) (mid < mid1)<<32 | mid>>32; mid <<= 32; z.v0 += mid; z.v64 += (z.v0 < mid); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mul64To128M.c000066400000000000000000000047631464416617300262200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_mul64To128M void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr ) { uint32_t a32, a0, b32, b0; uint64_t z0, mid1, z64, mid; a32 = a>>32; a0 = a; b32 = b>>32; b0 = b; z0 = (uint64_t) a0 * b0; mid1 = (uint64_t) a32 * b0; mid = mid1 + (uint64_t) a0 * b32; z64 = (uint64_t) a32 * b32; z64 += (uint64_t) (mid < mid1)<<32 | mid>>32; mid <<= 32; z0 += mid; zPtr[indexWord( 4, 1 )] = z0>>32; zPtr[indexWord( 4, 0 )] = z0; z64 += (z0 < mid); zPtr[indexWord( 4, 3 )] = z64>>32; zPtr[indexWord( 4, 2 )] = z64; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128.c000066400000000000000000000324241464416617300261400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t softfloat_mulAddF128( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0, uint_fast64_t uiC64, uint_fast64_t uiC0, uint_fast8_t op ) { bool signA; int_fast32_t expA; struct uint128 sigA; bool signB; int_fast32_t expB; struct uint128 sigB; bool signC; int_fast32_t expC; struct uint128 sigC; bool signZ; uint_fast64_t magBits; struct uint128 uiZ; struct exp32_sig128 normExpSig; int_fast32_t expZ; uint64_t sig256Z[4]; struct uint128 sigZ; int_fast32_t shiftCount, expDiff; struct uint128 x128; uint64_t sig256C[4]; static uint64_t zero256[4] = INIT_UINTM4( 0, 0, 0, 0 ); uint_fast64_t sigZExtra, sig256Z0; union ui128_f128 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signF128UI64( uiA64 ); expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; signB = signF128UI64( uiB64 ); expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; signC = signF128UI64( uiC64 ) ^ (op == softfloat_mulAdd_subC); expC = expF128UI64( uiC64 ); sigC.v64 = fracF128UI64( uiC64 ); sigC.v0 = uiC0; signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FFF ) { if ( (sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0)) ) { goto propagateNaN_ABC; } magBits = expB | sigB.v64 | sigB.v0; goto infProdArg; } if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN_ABC; magBits = expA | sigA.v64 | sigA.v0; goto infProdArg; } if ( expC == 0x7FFF ) { if ( sigC.v64 | sigC.v0 ) { uiZ.v64 = 0; uiZ.v0 = 0; goto propagateNaN_ZC; } uiZ.v64 = uiC64; uiZ.v0 = uiC0; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! (sigA.v64 | sigA.v0) ) goto zeroProd; normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! (sigB.v64 | sigB.v0) ) goto zeroProd; normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FFE; sigA.v64 |= UINT64_C( 0x0001000000000000 ); sigB.v64 |= UINT64_C( 0x0001000000000000 ); sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 8 ); sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 15 ); softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z ); sigZ.v64 = sig256Z[indexWord( 4, 3 )]; sigZ.v0 = sig256Z[indexWord( 4, 2 )]; shiftCount = 0; if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) { --expZ; shiftCount = -1; } if ( ! expC ) { if ( ! (sigC.v64 | sigC.v0) ) { shiftCount += 8; goto sigZ; } normExpSig = softfloat_normSubnormalF128Sig( sigC.v64, sigC.v0 ); expC = normExpSig.exp; sigC = normExpSig.sig; } sigC.v64 |= UINT64_C( 0x0001000000000000 ); sigC = softfloat_shortShiftLeft128( sigC.v64, sigC.v0, 8 ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expZ - expC; if ( expDiff < 0 ) { expZ = expC; if ( (signZ == signC) || (expDiff < -1) ) { shiftCount -= expDiff; if ( shiftCount ) { sigZ = softfloat_shiftRightJam128( sigZ.v64, sigZ.v0, shiftCount ); } } else { if ( ! shiftCount ) { x128 = softfloat_shortShiftRight128( sig256Z[indexWord( 4, 1 )], sig256Z[indexWord( 4, 0 )], 1 ); sig256Z[indexWord( 4, 1 )] = (sigZ.v0<<63) | x128.v64; sig256Z[indexWord( 4, 0 )] = x128.v0; sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, 1 ); sig256Z[indexWord( 4, 3 )] = sigZ.v64; sig256Z[indexWord( 4, 2 )] = sigZ.v0; } } } else { if ( shiftCount ) softfloat_add256M( sig256Z, sig256Z, sig256Z ); if ( ! expDiff ) { sigZ.v64 = sig256Z[indexWord( 4, 3 )]; sigZ.v0 = sig256Z[indexWord( 4, 2 )]; } else { sig256C[indexWord( 4, 3 )] = sigC.v64; sig256C[indexWord( 4, 2 )] = sigC.v0; sig256C[indexWord( 4, 1 )] = 0; sig256C[indexWord( 4, 0 )] = 0; softfloat_shiftRightJam256M( sig256C, expDiff, sig256C ); } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ shiftCount = 8; if ( signZ == signC ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff <= 0 ) { sigZ = softfloat_add128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 ); } else { softfloat_add256M( sig256Z, sig256C, sig256Z ); sigZ.v64 = sig256Z[indexWord( 4, 3 )]; sigZ.v0 = sig256Z[indexWord( 4, 2 )]; } if ( sigZ.v64 & UINT64_C( 0x0200000000000000 ) ) { ++expZ; shiftCount = 9; } } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff < 0 ) { signZ = signC; if ( expDiff < -1 ) { sigZ = softfloat_sub128( sigC.v64, sigC.v0, sigZ.v64, sigZ.v0 ); sigZExtra = sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )]; if ( sigZExtra ) { sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 ); } if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) { --expZ; shiftCount = 7; } goto shiftRightRoundPack; } else { sig256C[indexWord( 4, 3 )] = sigC.v64; sig256C[indexWord( 4, 2 )] = sigC.v0; sig256C[indexWord( 4, 1 )] = 0; sig256C[indexWord( 4, 0 )] = 0; softfloat_sub256M( sig256C, sig256Z, sig256Z ); } } else if ( ! expDiff ) { sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, sigC.v64, sigC.v0 ); if ( ! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord( 4, 1 )] && ! sig256Z[indexWord( 4, 0 )] ) { goto completeCancellation; } sig256Z[indexWord( 4, 3 )] = sigZ.v64; sig256Z[indexWord( 4, 2 )] = sigZ.v0; if ( sigZ.v64 & UINT64_C( 0x8000000000000000 ) ) { signZ ^= 1; softfloat_sub256M( zero256, sig256Z, sig256Z ); } } else { softfloat_sub256M( sig256Z, sig256C, sig256Z ); if ( 1 < expDiff ) { sigZ.v64 = sig256Z[indexWord( 4, 3 )]; sigZ.v0 = sig256Z[indexWord( 4, 2 )]; if ( ! (sigZ.v64 & UINT64_C( 0x0100000000000000 )) ) { --expZ; shiftCount = 7; } goto sigZ; } } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ sigZ.v64 = sig256Z[indexWord( 4, 3 )]; sigZ.v0 = sig256Z[indexWord( 4, 2 )]; sigZExtra = sig256Z[indexWord( 4, 1 )]; sig256Z0 = sig256Z[indexWord( 4, 0 )]; if ( sigZ.v64 ) { if ( sig256Z0 ) sigZExtra |= 1; } else { expZ -= 64; sigZ.v64 = sigZ.v0; sigZ.v0 = sigZExtra; sigZExtra = sig256Z0; if ( ! sigZ.v64 ) { expZ -= 64; sigZ.v64 = sigZ.v0; sigZ.v0 = sigZExtra; sigZExtra = 0; if ( ! sigZ.v64 ) { expZ -= 64; sigZ.v64 = sigZ.v0; sigZ.v0 = 0; } } } shiftCount = softfloat_countLeadingZeros64( sigZ.v64 ); expZ += 7 - shiftCount; shiftCount = 15 - shiftCount; if ( 0 < shiftCount ) goto shiftRightRoundPack; if ( shiftCount ) { shiftCount = -shiftCount; sigZ = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, shiftCount ); x128 = softfloat_shortShiftLeft128( 0, sigZExtra, shiftCount ); sigZ.v0 |= x128.v64; sigZExtra = x128.v0; } goto roundPack; } sigZ: sigZExtra = sig256Z[indexWord( 4, 1 )] | sig256Z[indexWord( 4, 0 )]; shiftRightRoundPack: sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftCount)) | (sigZExtra != 0); sigZ = softfloat_shortShiftRight128( sigZ.v64, sigZ.v0, shiftCount ); roundPack: return softfloat_roundPackToF128( signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN_ABC: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); goto propagateNaN_ZC; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infProdArg: if ( magBits ) { uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 ); uiZ.v0 = 0; if ( expC != 0x7FFF ) goto uiZ; if ( sigC.v64 | sigC.v0 ) goto propagateNaN_ZC; if ( signZ == signC ) goto uiZ; } invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; propagateNaN_ZC: uiZ = softfloat_propagateNaNF128UI( uiZ.v64, uiZ.v0, uiC64, uiC0 ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zeroProd: uiZ.v64 = uiC64; uiZ.v0 = uiC0; if ( ! (expC | sigC.v64 | sigC.v0) && (signZ != signC) ) { completeCancellation: uiZ.v64 = packToF128UI64( softfloat_roundingMode == softfloat_round_min, 0, 0 ); uiZ.v0 = 0; } uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF128M.c000066400000000000000000000352071464416617300262570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" void softfloat_mulAddF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, const uint32_t *cWPtr, uint32_t *zWPtr, uint_fast8_t op ) { uint32_t uiA96; int32_t expA; uint32_t uiB96; int32_t expB; uint32_t uiC96; bool signC; int32_t expC; bool signProd, prodIsInfinite; uint32_t *ptr, uiZ96, sigA[4]; uint_fast8_t shiftCount; uint32_t sigX[5]; int32_t expProd; uint32_t sigProd[8], wordSig; bool doSub; uint_fast8_t (*addCarryMRoutinePtr)( uint_fast8_t, const uint32_t *, const uint32_t *, uint_fast8_t, uint32_t * ); int32_t expDiff; bool signZ; int32_t expZ; uint32_t *extSigPtr; uint_fast8_t carry; void (*roundPackRoutinePtr)( bool, int32_t, uint32_t *, uint32_t * ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ uiA96 = aWPtr[indexWordHi( 4 )]; expA = expF128UI96( uiA96 ); uiB96 = bWPtr[indexWordHi( 4 )]; expB = expF128UI96( uiB96 ); uiC96 = cWPtr[indexWordHi( 4 )]; signC = signF128UI96( uiC96 ) ^ (op == softfloat_mulAdd_subC); expC = expF128UI96( uiC96 ); signProd = signF128UI96( uiA96 ) ^ signF128UI96( uiB96 ) ^ (op == softfloat_mulAdd_subProd); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ prodIsInfinite = false; if ( (expA == 0x7FFF) || (expB == 0x7FFF) ) { if ( softfloat_tryPropagateNaNF128M( aWPtr, bWPtr, zWPtr ) ) { goto propagateNaN_ZC; } ptr = (uint32_t *) aWPtr; if ( ! (uint32_t) (uiA96<<1) ) goto possibleInvalidProd; if ( ! (uint32_t) (uiB96<<1) ) { ptr = (uint32_t *) bWPtr; possibleInvalidProd: if ( ! (ptr[indexWord( 4, 2 )] | ptr[indexWord( 4, 1 )] | ptr[indexWord( 4, 0 )]) ) { goto invalid; } } prodIsInfinite = true; } if ( expC == 0x7FFF ) { if ( fracF128UI96( uiC96 ) || (cWPtr[indexWord( 4, 2 )] | cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )]) ) { zWPtr[indexWordHi( 4 )] = 0; goto propagateNaN_ZC; } if ( prodIsInfinite && (signProd != signC) ) goto invalid; goto copyC; } if ( prodIsInfinite ) { uiZ96 = packToF128UI96( signProd, 0x7FFF, 0 ); goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA ) { sigA[indexWordHi( 4 )] = fracF128UI96( uiA96 ) | 0x00010000; sigA[indexWord( 4, 2 )] = aWPtr[indexWord( 4, 2 )]; sigA[indexWord( 4, 1 )] = aWPtr[indexWord( 4, 1 )]; sigA[indexWord( 4, 0 )] = aWPtr[indexWord( 4, 0 )]; } else { expA = softfloat_shiftNormSigF128M( aWPtr, 0, sigA ); if ( expA == -128 ) goto zeroProd; } if ( expB ) { sigX[indexWordHi( 4 )] = fracF128UI96( uiB96 ) | 0x00010000; sigX[indexWord( 4, 2 )] = bWPtr[indexWord( 4, 2 )]; sigX[indexWord( 4, 1 )] = bWPtr[indexWord( 4, 1 )]; sigX[indexWord( 4, 0 )] = bWPtr[indexWord( 4, 0 )]; } else { expB = softfloat_shiftNormSigF128M( bWPtr, 0, sigX ); if ( expB == -128 ) goto zeroProd; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expProd = expA + expB - 0x3FF0; softfloat_mul128MTo256M( sigA, sigX, sigProd ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ wordSig = fracF128UI96( uiC96 ); if ( expC ) { --expC; wordSig |= 0x00010000; } sigX[indexWordHi( 5 )] = wordSig; sigX[indexWord( 5, 3 )] = cWPtr[indexWord( 4, 2 )]; sigX[indexWord( 5, 2 )] = cWPtr[indexWord( 4, 1 )]; sigX[indexWord( 5, 1 )] = cWPtr[indexWord( 4, 0 )]; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ doSub = (signProd != signC); addCarryMRoutinePtr = doSub ? softfloat_addComplCarryM : softfloat_addCarryM; expDiff = expProd - expC; if ( expDiff <= 0 ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ signZ = signC; expZ = expC; if ( sigProd[indexWord( 8, 2 )] || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) ) { sigProd[indexWord( 8, 3 )] |= 1; } extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )]; if ( expDiff ) { softfloat_shiftRightJam160M( extSigPtr, -expDiff, extSigPtr ); } carry = 0; if ( doSub ) { wordSig = extSigPtr[indexWordLo( 5 )]; extSigPtr[indexWordLo( 5 )] = -wordSig; carry = ! wordSig; } (*addCarryMRoutinePtr)( 4, &sigX[indexMultiwordHi( 5, 4 )], extSigPtr + indexMultiwordHi( 5, 4 ), carry, extSigPtr + indexMultiwordHi( 5, 4 ) ); wordSig = extSigPtr[indexWordHi( 5 )]; if ( ! expZ ) { if ( wordSig & 0x80000000 ) { signZ = ! signZ; softfloat_negX160M( extSigPtr ); wordSig = extSigPtr[indexWordHi( 5 )]; } goto checkCancellation; } if ( wordSig < 0x00010000 ) { --expZ; softfloat_add160M( extSigPtr, extSigPtr, extSigPtr ); goto roundPack; } goto extSigReady_noCancellation; } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ signZ = signProd; expZ = expProd; sigX[indexWordLo( 5 )] = 0; expDiff -= 128; if ( 0 <= expDiff ) { /*---------------------------------------------------------------- *----------------------------------------------------------------*/ if ( expDiff ) softfloat_shiftRightJam160M( sigX, expDiff, sigX ); wordSig = sigX[indexWordLo( 5 )]; carry = 0; if ( doSub ) { carry = ! wordSig; wordSig = -wordSig; } carry = (*addCarryMRoutinePtr)( 4, &sigProd[indexMultiwordLo( 8, 4 )], &sigX[indexMultiwordHi( 5, 4 )], carry, &sigProd[indexMultiwordLo( 8, 4 )] ); sigProd[indexWord( 8, 2 )] |= wordSig; ptr = &sigProd[indexWord( 8, 4 )]; } else { /*---------------------------------------------------------------- *----------------------------------------------------------------*/ shiftCount = expDiff & 31; if ( shiftCount ) { softfloat_shortShiftRight160M( sigX, shiftCount, sigX ); } expDiff >>= 5; extSigPtr = &sigProd[indexMultiwordLo( 8, 5 )] - wordIncr + expDiff * -wordIncr; carry = (*addCarryMRoutinePtr)( 5, extSigPtr, sigX, doSub, extSigPtr ); if ( expDiff == -4 ) { /*------------------------------------------------------------ *------------------------------------------------------------*/ wordSig = sigProd[indexWordHi( 8 )]; if ( wordSig & 0x80000000 ) { signZ = ! signZ; softfloat_negX256M( sigProd ); wordSig = sigProd[indexWordHi( 8 )]; } /*------------------------------------------------------------ *------------------------------------------------------------*/ if ( wordSig ) goto expProdBigger_noWordShift; wordSig = sigProd[indexWord( 8, 6 )]; if ( 0x00040000 <= wordSig ) goto expProdBigger_noWordShift; expZ -= 32; extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )] - wordIncr; for (;;) { if ( wordSig ) break; wordSig = extSigPtr[indexWord( 5, 3 )]; if ( 0x00040000 <= wordSig ) break; expZ -= 32; extSigPtr -= wordIncr; if ( extSigPtr == &sigProd[indexMultiwordLo( 8, 5 )] ) { goto checkCancellation; } } /*------------------------------------------------------------ *------------------------------------------------------------*/ ptr = extSigPtr + indexWordLo( 5 ); do { ptr -= wordIncr; if ( *ptr ) { extSigPtr[indexWordLo( 5 )] |= 1; break; } } while ( ptr != &sigProd[indexWordLo( 8 )] ); wordSig = extSigPtr[indexWordHi( 5 )]; goto extSigReady; } ptr = extSigPtr + indexWordHi( 5 ) + wordIncr; } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( carry != doSub ) { if ( doSub ) { do { wordSig = *ptr; *ptr = wordSig - 1; ptr += wordIncr; } while ( ! wordSig ); } else { do { wordSig = *ptr + 1; *ptr = wordSig; ptr += wordIncr; } while ( ! wordSig ); } } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ expProdBigger_noWordShift: if ( sigProd[indexWord( 8, 2 )] || (sigProd[indexWord( 8, 1 )] | sigProd[indexWord( 8, 0 )]) ) { sigProd[indexWord( 8, 3 )] |= 1; } extSigPtr = &sigProd[indexMultiwordHi( 8, 5 )]; wordSig = extSigPtr[indexWordHi( 5 )]; } extSigReady: roundPackRoutinePtr = softfloat_normRoundPackMToF128M; if ( wordSig < 0x00010000 ) goto doRoundPack; extSigReady_noCancellation: if ( 0x00020000 <= wordSig ) { ++expZ; softfloat_shortShiftRightJam160M( extSigPtr, 1, extSigPtr ); } roundPack: roundPackRoutinePtr = softfloat_roundPackMToF128M; doRoundPack: (*roundPackRoutinePtr)( signZ, expZ, extSigPtr, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ invalid: softfloat_invalidF128M( zWPtr ); propagateNaN_ZC: softfloat_propagateNaNF128M( zWPtr, cWPtr, zWPtr ); return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zeroProd: if ( ! (uint32_t) (uiC96<<1) && (signProd != signC) && ! cWPtr[indexWord( 4, 2 )] && ! (cWPtr[indexWord( 4, 1 )] | cWPtr[indexWord( 4, 0 )]) ) { goto completeCancellation; } copyC: zWPtr[indexWordHi( 4 )] = uiC96; zWPtr[indexWord( 4, 2 )] = cWPtr[indexWord( 4, 2 )]; zWPtr[indexWord( 4, 1 )] = cWPtr[indexWord( 4, 1 )]; zWPtr[indexWord( 4, 0 )] = cWPtr[indexWord( 4, 0 )]; return; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ checkCancellation: if ( wordSig || (extSigPtr[indexWord( 5, 3 )] | extSigPtr[indexWord( 5, 2 )]) || (extSigPtr[indexWord( 5, 1 )] | extSigPtr[indexWord( 5, 0 )]) ) { goto extSigReady; } completeCancellation: uiZ96 = packToF128UI96( (softfloat_roundingMode == softfloat_round_min), 0, 0 ); uiZ: zWPtr[indexWordHi( 4 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_mulAddF32.c000066400000000000000000000150601464416617300260470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t softfloat_mulAddF32( uint_fast32_t uiA, uint_fast32_t uiB, uint_fast32_t uiC, uint_fast8_t op ) { bool signA; int_fast16_t expA; uint_fast32_t sigA; bool signB; int_fast16_t expB; uint_fast32_t sigB; bool signC; int_fast16_t expC; uint_fast32_t sigC; bool signProd; uint_fast32_t magBits, uiZ; struct exp16_sig32 normExpSig; int_fast16_t expProd; uint_fast64_t sigProd; bool signZ; int_fast16_t expZ; uint_fast32_t sigZ; int_fast16_t expDiff; uint_fast64_t sig64Z, sig64C; int_fast8_t shiftCount; union ui32_f32 uZ; signA = signF32UI( uiA ); expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); signB = signF32UI( uiB ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); signC = signF32UI( uiC ) ^ (op == softfloat_mulAdd_subC); expC = expF32UI( uiC ); sigC = fracF32UI( uiC ); signProd = signA ^ signB ^ (op == softfloat_mulAdd_subProd); if ( expA == 0xFF ) { if ( sigA || ((expB == 0xFF) && sigB) ) goto propagateNaN_ABC; magBits = expB | sigB; goto infProdArg; } if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN_ABC; magBits = expA | sigA; goto infProdArg; } if ( expC == 0xFF ) { if ( sigC ) { uiZ = 0; goto propagateNaN_ZC; } uiZ = uiC; goto uiZ; } if ( ! expA ) { if ( ! sigA ) goto zeroProd; normExpSig = softfloat_normSubnormalF32Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zeroProd; normExpSig = softfloat_normSubnormalF32Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } expProd = expA + expB - 0x7E; sigA = (sigA | 0x00800000)<<7; sigB = (sigB | 0x00800000)<<7; sigProd = (uint_fast64_t) sigA * sigB; if ( sigProd < UINT64_C( 0x2000000000000000 ) ) { --expProd; sigProd <<= 1; } signZ = signProd; if ( ! expC ) { if ( ! sigC ) { expZ = expProd - 1; sigZ = softfloat_shortShiftRightJam64( sigProd, 31 ); goto roundPack; } normExpSig = softfloat_normSubnormalF32Sig( sigC ); expC = normExpSig.exp; sigC = normExpSig.sig; } sigC = (sigC | 0x00800000)<<6; expDiff = expProd - expC; if ( signProd == signC ) { if ( expDiff <= 0 ) { expZ = expC; sigZ = sigC + softfloat_shiftRightJam64( sigProd, 32 - expDiff ); } else { expZ = expProd; sig64Z = sigProd + softfloat_shiftRightJam64( (uint_fast64_t) sigC<<32, expDiff ); sigZ = softfloat_shortShiftRightJam64( sig64Z, 32 ); } if ( sigZ < 0x40000000 ) { --expZ; sigZ <<= 1; } } else { sig64C = (uint_fast64_t) sigC<<32; if ( expDiff < 0 ) { signZ = signC; expZ = expC; sig64Z = sig64C - softfloat_shiftRightJam64( sigProd, -expDiff ); } else if ( ! expDiff ) { expZ = expProd; sig64Z = sigProd - sig64C; if ( ! sig64Z ) goto completeCancellation; if ( sig64Z & UINT64_C( 0x8000000000000000 ) ) { signZ ^= 1; sig64Z = -sig64Z; } } else { expZ = expProd; sig64Z = sigProd - softfloat_shiftRightJam64( sig64C, expDiff ); } shiftCount = softfloat_countLeadingZeros64( sig64Z ) - 1; expZ -= shiftCount; shiftCount -= 32; if ( shiftCount < 0 ) { sigZ = softfloat_shortShiftRightJam64( sig64Z, -shiftCount ); } else { sigZ = (uint_fast32_t) sig64Z< #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 float64_t softfloat_mulAddF64( uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) { bool signA; int_fast16_t expA; uint_fast64_t sigA; bool signB; int_fast16_t expB; uint_fast64_t sigB; bool signC; int_fast16_t expC; uint_fast64_t sigC; bool signZ; uint_fast64_t magBits, uiZ; struct exp16_sig64 normExpSig; int_fast16_t expZ; struct uint128 sig128Z; uint_fast64_t sigZ; int_fast16_t expDiff; struct uint128 sig128C; int_fast8_t shiftCount; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); signB = signF64UI( uiB ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); expC = expF64UI( uiC ); sigC = fracF64UI( uiC ); signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; magBits = expB | sigB; goto infProdArg; } if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN_ABC; magBits = expA | sigA; goto infProdArg; } if ( expC == 0x7FF ) { if ( sigC ) { uiZ = 0; goto propagateNaN_ZC; } uiZ = uiC; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) goto zeroProd; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zeroProd; normExpSig = softfloat_normSubnormalF64Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FE; sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<10; sig128Z = softfloat_mul64To128( sigA, sigB ); if ( sig128Z.v64 < UINT64_C( 0x2000000000000000 ) ) { --expZ; sig128Z = softfloat_add128( sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0 ); } if ( ! expC ) { if ( ! sigC ) { --expZ; sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); goto roundPack; } normExpSig = softfloat_normSubnormalF64Sig( sigC ); expC = normExpSig.exp; sigC = normExpSig.sig; } sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<9; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expZ - expC; if ( expDiff < 0 ) { expZ = expC; if ( (signZ == signC) || (expDiff < -1) ) { sig128Z.v64 = softfloat_shiftRightJam64( sig128Z.v64, -expDiff ); } else { sig128Z = softfloat_shortShiftRightJam128( sig128Z.v64, sig128Z.v0, 1 ); } } else if ( expDiff ) { sig128C = softfloat_shiftRightJam128( sigC, 0, expDiff ); } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signZ == signC ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff <= 0 ) { sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); } else { sig128Z = softfloat_add128( sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 ); sigZ = sig128Z.v64 | (sig128Z.v0 != 0); } if ( sigZ < UINT64_C( 0x4000000000000000 ) ) { --expZ; sigZ <<= 1; } } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff < 0 ) { signZ = signC; sig128Z = softfloat_sub128( sigC, 0, sig128Z.v64, sig128Z.v0 ); } else if ( ! expDiff ) { sig128Z.v64 = sig128Z.v64 - sigC; if ( ! (sig128Z.v64 | sig128Z.v0) ) goto completeCancellation; if ( sig128Z.v64 & UINT64_C( 0x8000000000000000 ) ) { signZ ^= 1; sig128Z = softfloat_sub128( 0, 0, sig128Z.v64, sig128Z.v0 ); } } else { sig128Z = softfloat_sub128( sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0 ); } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( ! sig128Z.v64 ) { expZ -= 64; sig128Z.v64 = sig128Z.v0; sig128Z.v0 = 0; } shiftCount = softfloat_countLeadingZeros64( sig128Z.v64 ) - 1; expZ -= shiftCount; if ( shiftCount < 0 ) { sigZ = softfloat_shortShiftRightJam64( sig128Z.v64, -shiftCount ); } else { sig128Z = softfloat_shortShiftLeft128( sig128Z.v64, sig128Z.v0, shiftCount ); sigZ = sig128Z.v64; } sigZ |= (sig128Z.v0 != 0); } roundPack: return softfloat_roundPackToF64( signZ, expZ, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN_ABC: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); goto propagateNaN_ZC; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infProdArg: if ( magBits ) { uiZ = packToF64UI( signZ, 0x7FF, 0 ); if ( expC != 0x7FF ) goto uiZ; if ( sigC ) goto propagateNaN_ZC; if ( signZ == signC ) goto uiZ; } invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; propagateNaN_ZC: uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zeroProd: uiZ = uiC; if ( ! (expC | sigC) && (signZ != signC) ) { completeCancellation: uiZ = packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); } uiZ: uZ.ui = uiZ; return uZ.f; } #else float64_t softfloat_mulAddF64( uint_fast64_t uiA, uint_fast64_t uiB, uint_fast64_t uiC, uint_fast8_t op ) { bool signA; int_fast16_t expA; uint64_t sigA; bool signB; int_fast16_t expB; uint64_t sigB; bool signC; int_fast16_t expC; uint64_t sigC; bool signZ; uint64_t magBits, uiZ; struct exp16_sig64 normExpSig; int_fast16_t expZ; uint32_t sig128Z[4]; uint64_t sigZ; int_fast16_t shiftCount, expDiff; uint32_t sig128C[4]; union ui64_f64 uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ signA = signF64UI( uiA ); expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); signB = signF64UI( uiB ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); signC = signF64UI( uiC ) ^ (op == softfloat_mulAdd_subC); expC = expF64UI( uiC ); sigC = fracF64UI( uiC ); signZ = signA ^ signB ^ (op == softfloat_mulAdd_subProd); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( expA == 0x7FF ) { if ( sigA || ((expB == 0x7FF) && sigB) ) goto propagateNaN_ABC; magBits = expB | sigB; goto infProdArg; } if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN_ABC; magBits = expA | sigA; goto infProdArg; } if ( expC == 0x7FF ) { if ( sigC ) { uiZ = 0; goto propagateNaN_ZC; } uiZ = uiC; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( ! expA ) { if ( ! sigA ) goto zeroProd; normExpSig = softfloat_normSubnormalF64Sig( sigA ); expA = normExpSig.exp; sigA = normExpSig.sig; } if ( ! expB ) { if ( ! sigB ) goto zeroProd; normExpSig = softfloat_normSubnormalF64Sig( sigB ); expB = normExpSig.exp; sigB = normExpSig.sig; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA + expB - 0x3FE; sigA = (sigA | UINT64_C( 0x0010000000000000 ))<<10; sigB = (sigB | UINT64_C( 0x0010000000000000 ))<<11; softfloat_mul64To128M( sigA, sigB, sig128Z ); sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; shiftCount = 0; if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { --expZ; shiftCount = -1; } if ( ! expC ) { if ( ! sigC ) { if ( shiftCount ) sigZ <<= 1; goto sigZ; } normExpSig = softfloat_normSubnormalF64Sig( sigC ); expC = normExpSig.exp; sigC = normExpSig.sig; } sigC = (sigC | UINT64_C( 0x0010000000000000 ))<<10; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expZ - expC; if ( expDiff < 0 ) { expZ = expC; if ( (signZ == signC) || (expDiff < -1) ) { shiftCount -= expDiff; if ( shiftCount) { sigZ = softfloat_shiftRightJam64( sigZ, shiftCount ); } } else { if ( ! shiftCount ) { softfloat_shortShiftRight128M( sig128Z, 1, sig128Z ); } } } else { if ( shiftCount ) softfloat_add128M( sig128Z, sig128Z, sig128Z ); if ( ! expDiff ) { sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; } else { sig128C[indexWord( 4, 3 )] = sigC>>32; sig128C[indexWord( 4, 2 )] = sigC; sig128C[indexWord( 4, 1 )] = 0; sig128C[indexWord( 4, 0 )] = 0; softfloat_shiftRightJam128M( sig128C, expDiff, sig128C ); } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( signZ == signC ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff <= 0 ) { sigZ += sigC; } else { softfloat_add128M( sig128Z, sig128C, sig128Z ); sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; } if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { ++expZ; sigZ = softfloat_shortShiftRightJam64( sigZ, 1 ); } } else { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( expDiff < 0 ) { signZ = signC; if ( expDiff < -1 ) { sigZ = sigC - sigZ; if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) { sigZ = (sigZ - 1) | 1; } if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { --expZ; sigZ <<= 1; } goto roundPack; } else { sig128C[indexWord( 4, 3 )] = sigC>>32; sig128C[indexWord( 4, 2 )] = sigC; sig128C[indexWord( 4, 1 )] = 0; sig128C[indexWord( 4, 0 )] = 0; softfloat_sub128M( sig128C, sig128Z, sig128Z ); } } else if ( ! expDiff ) { sigZ -= sigC; if ( ! sigZ && ! sig128Z[indexWord( 4, 1 )] && ! sig128Z[indexWord( 4, 0 )] ) { goto completeCancellation; } sig128Z[indexWord( 4, 3 )] = sigZ>>32; sig128Z[indexWord( 4, 2 )] = sigZ; if ( sigZ & UINT64_C( 0x8000000000000000 ) ) { signZ ^= 1; softfloat_negX128M( sig128Z ); } } else { softfloat_sub128M( sig128Z, sig128C, sig128Z ); if ( 1 < expDiff ) { sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; if ( ! (sigZ & UINT64_C( 0x4000000000000000 )) ) { --expZ; sigZ <<= 1; } goto sigZ; } } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ shiftCount = 0; sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; if ( ! sigZ ) { shiftCount = 64; sigZ = (uint64_t) sig128Z[indexWord( 4, 1 )]<<32 | sig128Z[indexWord( 4, 0 )]; } shiftCount += softfloat_countLeadingZeros64( sigZ ) - 1; if ( shiftCount ) { expZ -= shiftCount; softfloat_shiftLeft128M( sig128Z, shiftCount, sig128Z ); sigZ = (uint64_t) sig128Z[indexWord( 4, 3 )]<<32 | sig128Z[indexWord( 4, 2 )]; } } sigZ: if ( sig128Z[indexWord( 4, 1 )] || sig128Z[indexWord( 4, 0 )] ) sigZ |= 1; roundPack: return softfloat_roundPackToF64( signZ, expZ - 1, sigZ ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN_ABC: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); goto propagateNaN_ZC; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ infProdArg: if ( magBits ) { uiZ = packToF64UI( signZ, 0x7FF, 0 ); if ( expC != 0x7FF ) goto uiZ; if ( sigC ) goto propagateNaN_ZC; if ( signZ == signC ) goto uiZ; } invalid: softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; propagateNaN_ZC: uiZ = softfloat_propagateNaNF64UI( uiZ, uiC ); goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ zeroProd: uiZ = uiC; if ( ! (expC | sigC) && (signZ != signC) ) { completeCancellation: uiZ = packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); } uiZ: uZ.ui = uiZ; return uZ.f; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_negXM.c000066400000000000000000000045311464416617300254050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_negXM void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr ) { unsigned int index, lastIndex; uint_fast8_t carry; uint32_t word; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); carry = 1; for (;;) { word = ~zPtr[index] + carry; zPtr[index] = word; if ( index == lastIndex ) break; index += wordIncr; if ( word ) carry = 0; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_normExtF80SigM.c000066400000000000000000000041441464416617300270610ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" int softfloat_normExtF80SigM( uint64_t *sigPtr ) { uint64_t sig; int_fast8_t shiftCount; sig = *sigPtr; shiftCount = softfloat_countLeadingZeros64( sig ); *sigPtr = sig< #include #include "platform.h" #include "internals.h" void softfloat_normRoundPackMToExtF80M( bool sign, int32_t exp, uint32_t *extSigPtr, uint_fast8_t roundingPrecision, struct extFloat80M *zSPtr ) { int_fast16_t shiftCount; uint32_t wordSig; shiftCount = 0; wordSig = extSigPtr[indexWord( 3, 2 )]; if ( ! wordSig ) { shiftCount = 32; wordSig = extSigPtr[indexWord( 3, 1 )]; if ( ! wordSig ) { shiftCount = 64; wordSig = extSigPtr[indexWord( 3, 0 )]; if ( ! wordSig ) { zSPtr->signExp = packToExtF80UI64( sign, 0 ); zSPtr->signif = 0; return; } } } shiftCount += softfloat_countLeadingZeros32( wordSig ); if ( shiftCount ) { exp -= shiftCount; softfloat_shiftLeft96M( extSigPtr, shiftCount, extSigPtr ); } softfloat_roundPackMToExtF80M( sign, exp, extSigPtr, roundingPrecision, zSPtr ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackMToF128M.c000066400000000000000000000054141464416617300302500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" void softfloat_normRoundPackMToF128M( bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr ) { const uint32_t *ptr; int_fast16_t shiftCount; uint32_t wordSig; ptr = extSigPtr + indexWordHi( 5 ); shiftCount = 0; for (;;) { wordSig = *ptr; if ( wordSig ) break; shiftCount += 32; if ( 160 <= shiftCount ) { zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, 0, 0 ); zWPtr[indexWord( 4, 2 )] = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; return; } ptr -= wordIncr; } shiftCount += softfloat_countLeadingZeros32( wordSig ) - 15; if ( shiftCount ) { exp -= shiftCount; softfloat_shiftLeft160M( extSigPtr, shiftCount, extSigPtr ); } softfloat_roundPackMToF128M( sign, exp, extSigPtr, zWPtr ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToExtF80.c000066400000000000000000000050661464416617300304170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" extFloat80_t softfloat_normRoundPackToExtF80( bool sign, int_fast32_t exp, uint_fast64_t sig, uint_fast64_t sigExtra, uint_fast8_t roundingPrecision ) { int_fast8_t shiftCount; struct uint128 sig128; if ( ! sig ) { exp -= 64; sig = sigExtra; sigExtra = 0; } shiftCount = softfloat_countLeadingZeros64( sig ); exp -= shiftCount; if ( shiftCount ) { sig128 = softfloat_shortShiftLeft128( sig, sigExtra, shiftCount ); sig = sig128.v64; sigExtra = sig128.v0; } return softfloat_roundPackToExtF80( sign, exp, sig, sigExtra, roundingPrecision ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF128.c000066400000000000000000000060521464416617300300150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" float128_t softfloat_normRoundPackToF128( bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 ) { int_fast8_t shiftCount; struct uint128 sig128; union ui128_f128 uZ; uint_fast64_t sigExtra; struct uint128_extra sig128Extra; if ( ! sig64 ) { exp -= 64; sig64 = sig0; sig0 = 0; } shiftCount = softfloat_countLeadingZeros64( sig64 ) - 15; exp -= shiftCount; if ( 0 <= shiftCount ) { if ( shiftCount ) { sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftCount ); sig64 = sig128.v64; sig0 = sig128.v0; } if ( (uint32_t) exp < 0x7FFD ) { uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 ); uZ.ui.v0 = sig0; return uZ.f; } sigExtra = 0; } else { sig128Extra = softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftCount ); sig64 = sig128Extra.v.v64; sig0 = sig128Extra.v.v0; sigExtra = sig128Extra.extra; } return softfloat_roundPackToF128( sign, exp, sig64, sig0, sigExtra ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_normRoundPackToF32.c000066400000000000000000000045541464416617300277340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" float32_t softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) { int_fast8_t shiftCount; union ui32_f32 uZ; shiftCount = softfloat_countLeadingZeros32( sig ) - 1; exp -= shiftCount; if ( (7 <= shiftCount) && ((uint16_t) exp < 0xFD) ) { uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<(shiftCount - 7) ); return uZ.f; } else { return softfloat_roundPackToF32( sign, exp, sig< #include #include "platform.h" #include "internals.h" float64_t softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) { int_fast8_t shiftCount; union ui64_f64 uZ; shiftCount = softfloat_countLeadingZeros64( sig ) - 1; exp -= shiftCount; if ( (10 <= shiftCount) && ((uint16_t) exp < 0x7FD) ) { uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<(shiftCount - 10) ); return uZ.f; } else { return softfloat_roundPackToF64( sign, exp, sig< #include "platform.h" #include "internals.h" struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t sig ) { int_fast8_t shiftCount; struct exp32_sig64 z; shiftCount = softfloat_countLeadingZeros64( sig ); z.exp = -shiftCount; z.sig = sig< #include "platform.h" #include "internals.h" struct exp32_sig128 softfloat_normSubnormalF128Sig( uint_fast64_t sig64, uint_fast64_t sig0 ) { int_fast8_t shiftCount; struct exp32_sig128 z; if ( ! sig64 ) { shiftCount = softfloat_countLeadingZeros64( sig0 ) - 15; z.exp = -63 - shiftCount; if ( shiftCount < 0 ) { z.sig.v64 = sig0>>-shiftCount; z.sig.v0 = sig0<<(shiftCount & 63); } else { z.sig.v64 = sig0< #include "platform.h" #include "internals.h" int softfloat_normSubnormalF128SigM( uint32_t *sigPtr ) { const uint32_t *ptr; int_fast16_t shiftCount; uint32_t wordSig; ptr = sigPtr + indexWordHi( 4 ); shiftCount = 0; for (;;) { wordSig = *ptr; if ( wordSig ) break; shiftCount += 32; if ( 128 <= shiftCount ) return 1; ptr -= wordIncr; } shiftCount += softfloat_countLeadingZeros32( wordSig ) - 15; if ( shiftCount ) softfloat_shiftLeft128M( sigPtr, shiftCount, sigPtr ); return 1 - shiftCount; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_normSubnormalF32Sig.c000066400000000000000000000042021464416617300301360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) { int_fast8_t shiftCount; struct exp16_sig32 z; shiftCount = softfloat_countLeadingZeros32( sig ) - 8; z.exp = 1 - shiftCount; z.sig = sig< #include "platform.h" #include "internals.h" struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig ) { int_fast8_t shiftCount; struct exp16_sig64 z; shiftCount = softfloat_countLeadingZeros64( sig ) - 11; z.exp = 1 - shiftCount; z.sig = sig< #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_remStepMBy32 void softfloat_remStepMBy32( uint_fast8_t size_words, const uint32_t *remPtr, uint_fast8_t count, const uint32_t *bPtr, uint32_t q, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int index, lastIndex; uint64_t dwordProd; uint32_t wordRem, wordShiftedRem, wordProd; uint_fast8_t borrow; negCount = -count; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); dwordProd = (uint64_t) bPtr[index] * q; wordRem = remPtr[index]; wordShiftedRem = wordRem<>(negCount & 31); index += wordIncr; dwordProd = (uint64_t) bPtr[index] * q + (dwordProd>>32); wordRem = remPtr[index]; wordShiftedRem |= wordRem< #include #include "platform.h" #include "internals.h" #include "softfloat.h" void softfloat_roundPackMToExtF80M( bool sign, int32_t exp, uint32_t *extSigPtr, uint_fast8_t roundingPrecision, struct extFloat80M *zSPtr ) { uint_fast8_t roundingMode; bool roundNearEven; uint64_t sig, roundIncrement, roundMask, roundBits; bool isTiny; uint32_t sigExtra; bool doIncrement; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); sig = (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 | extSigPtr[indexWord( 3, 1 )]; if ( roundingPrecision == 80 ) goto precision80; if ( roundingPrecision == 64 ) { roundIncrement = UINT64_C( 0x0000000000000400 ); roundMask = UINT64_C( 0x00000000000007FF ); } else if ( roundingPrecision == 32 ) { roundIncrement = UINT64_C( 0x0000008000000000 ); roundMask = UINT64_C( 0x000000FFFFFFFFFF ); } else { goto precision80; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( extSigPtr[indexWordLo( 3 )] ) sig |= 1; if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? roundMask : 0; } roundBits = sig & roundMask; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x7FFD <= (uint32_t) (exp - 1) ) { if ( exp <= 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < 0) || (sig <= (uint64_t) (sig + roundIncrement)); sig = softfloat_shiftRightJam64( sig, 1 - exp ); roundBits = sig & roundMask; if ( roundBits ) { if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow ); softfloat_exceptionFlags |= softfloat_flag_inexact; } sig += roundIncrement; exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); roundIncrement = roundMask + 1; if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { roundMask |= roundIncrement; } sig &= ~roundMask; goto packReturn; } if ( (0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig)) ) { goto overflow; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; sig += roundIncrement; if ( sig < roundIncrement ) { ++exp; sig = UINT64_C( 0x8000000000000000 ); } roundIncrement = roundMask + 1; if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { roundMask |= roundIncrement; } sig &= ~roundMask; goto packReturn; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ precision80: sigExtra = extSigPtr[indexWordLo( 3 )]; doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( 0x7FFD <= (uint32_t) (exp - 1) ) { /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( exp <= 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < 0) || ! doIncrement || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF )); softfloat_shiftRightJam96M( extSigPtr, 1 - exp, extSigPtr ); sigExtra = extSigPtr[indexWordLo( 3 )]; if ( sigExtra ) { if ( isTiny ) softfloat_raiseFlags( softfloat_flag_underflow ); softfloat_exceptionFlags |= softfloat_flag_inexact; } doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } exp = 0; sig = (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 | extSigPtr[indexWord( 3, 1 )]; if ( doIncrement ) { ++sig; sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven); exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); } goto packReturn; } /*-------------------------------------------------------------------- *--------------------------------------------------------------------*/ if ( (0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF )) && doIncrement) ) { roundMask = 0; overflow: softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ) { exp = 0x7FFF; sig = UINT64_C( 0x8000000000000000 ); } else { exp = 0x7FFE; sig = ~roundMask; } goto packReturn; } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; if ( doIncrement ) { ++sig; if ( ! sig ) { ++exp; sig = UINT64_C( 0x8000000000000000 ); } else { sig &= ~(uint64_t) (! (sigExtra & 0x7FFFFFFF) & roundNearEven); } } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ packReturn: zSPtr->signExp = packToExtF80UI64( sign, exp ); zSPtr->signif = sig; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToF128M.c000066400000000000000000000141021464416617300274060ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" void softfloat_roundPackMToF128M( bool sign, int32_t exp, uint32_t *extSigPtr, uint32_t *zWPtr ) { uint_fast8_t roundingMode; bool roundNearEven; uint32_t sigExtra; bool doIncrement, isTiny; static const uint32_t maxSig[4] = INIT_UINTM4( 0x0001FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ); uint32_t ui, uj; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); sigExtra = extSigPtr[indexWordLo( 5 )]; doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( 0x7FFD <= (uint32_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || ! doIncrement || (softfloat_compare128M( extSigPtr + indexMultiwordHi( 5, 4 ), maxSig ) < 0); softfloat_shiftRightJam160M( extSigPtr, -exp, extSigPtr ); exp = 0; sigExtra = extSigPtr[indexWordLo( 5 )]; if ( isTiny && sigExtra ) { softfloat_raiseFlags( softfloat_flag_underflow ); } doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } } else if ( (0x7FFD < exp) || ((exp == 0x7FFD) && doIncrement && (softfloat_compare128M( extSigPtr + indexMultiwordHi( 5, 4 ), maxSig ) == 0)) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ) { ui = packToF128UI96( sign, 0x7FFF, 0 ); uj = 0; } else { ui = packToF128UI96( sign, 0x7FFE, 0x0000FFFF ); uj = 0xFFFFFFFF; } zWPtr[indexWordHi( 4 )] = ui; zWPtr[indexWord( 4, 2 )] = uj; zWPtr[indexWord( 4, 1 )] = uj; zWPtr[indexWord( 4, 0 )] = uj; return; } } if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; uj = extSigPtr[indexWord( 5, 1 )]; if ( doIncrement ) { ++uj; if ( uj ) { if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) uj &= ~1; zWPtr[indexWord( 4, 2 )] = extSigPtr[indexWord( 5, 3 )]; zWPtr[indexWord( 4, 1 )] = extSigPtr[indexWord( 5, 2 )]; zWPtr[indexWord( 4, 0 )] = uj; ui = extSigPtr[indexWordHi( 5 )]; } else { zWPtr[indexWord( 4, 0 )] = uj; ui = extSigPtr[indexWord( 5, 2 )] + 1; zWPtr[indexWord( 4, 1 )] = ui; uj = extSigPtr[indexWord( 5, 3 )]; if ( ui ) { zWPtr[indexWord( 4, 2 )] = uj; ui = extSigPtr[indexWordHi( 5 )]; } else { ++uj; zWPtr[indexWord( 4, 2 )] = uj; ui = extSigPtr[indexWordHi( 5 )]; if ( ! uj ) ++ui; } } } else { zWPtr[indexWord( 4, 0 )] = uj; ui = extSigPtr[indexWord( 5, 2 )]; zWPtr[indexWord( 4, 1 )] = ui; uj |= ui; ui = extSigPtr[indexWord( 5, 3 )]; zWPtr[indexWord( 4, 2 )] = ui; uj |= ui; ui = extSigPtr[indexWordHi( 5 )]; uj |= ui; if ( ! uj ) exp = 0; } zWPtr[indexWordHi( 4 )] = packToF128UI96( sign, exp, ui ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToI64.c000066400000000000000000000062531464416617300272230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t softfloat_roundPackMToI64( bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact ) { bool roundNearEven; uint32_t sigExtra; bool doIncrement; uint64_t sig; union { uint64_t ui; int64_t i; } uZ; int64_t z; roundNearEven = (roundingMode == softfloat_round_near_even); sigExtra = extSigPtr[indexWordLo( 3 )]; doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } sig = (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 | extSigPtr[indexWord( 3, 1 )]; if ( doIncrement ) { ++sig; if ( ! sig ) goto invalid; if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1; } uZ.ui = sign ? -sig : sig; z = uZ.i; if ( z && ((z < 0) ^ sign) ) goto invalid; if ( exact && sigExtra ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return sign ? -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 : INT64_C( 0x7FFFFFFFFFFFFFFF ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackMToUI64.c000066400000000000000000000060001464416617300273360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t softfloat_roundPackMToUI64( bool sign, uint32_t *extSigPtr, uint_fast8_t roundingMode, bool exact ) { bool roundNearEven; uint32_t sigExtra; bool doIncrement; uint64_t sig; roundNearEven = (roundingMode == softfloat_round_near_even); sigExtra = extSigPtr[indexWordLo( 3 )]; doIncrement = (0x80000000 <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } sig = (uint64_t) extSigPtr[indexWord( 3, 2 )]<<32 | extSigPtr[indexWord( 3, 1 )]; if ( doIncrement ) { ++sig; if ( ! sig ) goto invalid; if ( ! (sigExtra & 0x7FFFFFFF) && roundNearEven ) sig &= ~1; } if ( sign && sig ) goto invalid; if ( exact && sigExtra ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return sig; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToExtF80.c000066400000000000000000000173161464416617300275640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t softfloat_roundPackToExtF80( bool sign, int_fast32_t exp, uint_fast64_t sig, uint_fast64_t sigExtra, uint_fast8_t roundingPrecision ) { uint_fast8_t roundingMode; bool roundNearEven; uint_fast64_t roundIncrement, roundMask, roundBits; bool isTiny, doIncrement; struct uint64_extra sig64Extra; union { struct extFloat80M s; extFloat80_t f; } uZ; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); if ( roundingPrecision == 80 ) goto precision80; if ( roundingPrecision == 64 ) { roundIncrement = UINT64_C( 0x0000000000000400 ); roundMask = UINT64_C( 0x00000000000007FF ); } else if ( roundingPrecision == 32 ) { roundIncrement = UINT64_C( 0x0000008000000000 ); roundMask = UINT64_C( 0x000000FFFFFFFFFF ); } else { goto precision80; } sig |= (sigExtra != 0); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? roundMask : 0; } roundBits = sig & roundMask; if ( 0x7FFD <= (uint32_t) (exp - 1) ) { if ( exp <= 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < 0) || (sig <= (uint64_t) (sig + roundIncrement)); sig = softfloat_shiftRightJam64( sig, 1 - exp ); roundBits = sig & roundMask; if ( isTiny && roundBits ) { softfloat_raiseFlags( softfloat_flag_underflow ); } if ( roundBits ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } sig += roundIncrement; exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); roundIncrement = roundMask + 1; if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { roundMask |= roundIncrement; } sig &= ~roundMask; goto packReturn; } if ( (0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig)) ) { goto overflow; } } if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; sig = (uint64_t) (sig + roundIncrement); if ( sig < roundIncrement ) { ++exp; sig = UINT64_C( 0x8000000000000000 ); } roundIncrement = roundMask + 1; if ( roundNearEven && (roundBits<<1 == roundIncrement) ) { roundMask |= roundIncrement; } sig &= ~roundMask; if ( ! sig ) exp = 0; goto packReturn; precision80: doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( 0x7FFD <= (uint32_t) (exp - 1) ) { if ( exp <= 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < 0) || ! doIncrement || (sig < UINT64_C( 0xFFFFFFFFFFFFFFFF )); sig64Extra = softfloat_shiftRightJam64Extra( sig, sigExtra, 1 - exp ); sig = sig64Extra.v; sigExtra = sig64Extra.extra; if ( isTiny && sigExtra ) { softfloat_raiseFlags( softfloat_flag_underflow ); } if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } exp = 0; if ( doIncrement ) { ++sig; sig &= ~(uint_fast64_t) (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) & roundNearEven); exp = ((sig & UINT64_C( 0x8000000000000000 )) != 0); } goto packReturn; } if ( (0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C( 0xFFFFFFFFFFFFFFFF )) && doIncrement) ) { roundMask = 0; overflow: softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ) { exp = 0x7FFF; sig = UINT64_C( 0x8000000000000000 ); } else { exp = 0x7FFE; sig = ~roundMask; } goto packReturn; } } if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; if ( doIncrement ) { ++sig; if ( ! sig ) { ++exp; sig = UINT64_C( 0x8000000000000000 ); } else { sig &= ~(uint_fast64_t) (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) & roundNearEven); } } else { if ( ! sig ) exp = 0; } packReturn: uZ.s.signExp = packToExtF80UI64( sign, exp ); uZ.s.signif = sig; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF128.c000066400000000000000000000127541464416617300271670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t softfloat_roundPackToF128( bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0, uint_fast64_t sigExtra ) { uint_fast8_t roundingMode; bool roundNearEven, doIncrement, isTiny; struct uint128_extra sig128Extra; uint_fast64_t uiZ64, uiZ0; struct uint128 sig128; union ui128_f128 uZ; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( 0x7FFD <= (uint32_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || ! doIncrement || softfloat_lt128( sig64, sig0, UINT64_C( 0x0001FFFFFFFFFFFF ), UINT64_C( 0xFFFFFFFFFFFFFFFF ) ); sig128Extra = softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp ); sig64 = sig128Extra.v.v64; sig0 = sig128Extra.v.v0; sigExtra = sig128Extra.extra; exp = 0; if ( isTiny && sigExtra ) { softfloat_raiseFlags( softfloat_flag_underflow ); } doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } } else if ( (0x7FFD < exp) || ((exp == 0x7FFD) && softfloat_eq128( sig64, sig0, UINT64_C( 0x0001FFFFFFFFFFFF ), UINT64_C( 0xFFFFFFFFFFFFFFFF ) ) && doIncrement) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); if ( roundNearEven || (roundingMode == softfloat_round_near_maxMag) || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ) { uiZ64 = packToF128UI64( sign, 0x7FFF, 0 ); uiZ0 = 0; } else { uiZ64 = packToF128UI64( sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) ); uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF ); } goto uiZ; } } if ( sigExtra ) softfloat_exceptionFlags |= softfloat_flag_inexact; if ( doIncrement ) { sig128 = softfloat_add128( sig64, sig0, 0, 1 ); sig64 = sig128.v64; sig0 = sig128.v0 & ~(uint64_t) (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) & roundNearEven); } else { if ( ! (sig64 | sig0) ) exp = 0; } uiZ64 = packToF128UI64( sign, exp, sig64 ); uiZ0 = sig0; uiZ: uZ.ui.v64 = uiZ64; uZ.ui.v0 = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF32.c000066400000000000000000000071651464416617300271010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) { uint_fast8_t roundingMode; bool roundNearEven; uint_fast8_t roundIncrement, roundBits; bool isTiny; uint_fast32_t uiZ; union ui32_f32 uZ; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); roundIncrement = 0x40; if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x7F : 0; } roundBits = sig & 0x7F; if ( 0xFD <= (uint16_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || (sig + roundIncrement < 0x80000000); sig = softfloat_shiftRightJam32( sig, -exp ); exp = 0; roundBits = sig & 0x7F; if ( isTiny && roundBits ) { softfloat_raiseFlags( softfloat_flag_underflow ); } } else if ( (0xFD < exp) || (0x80000000 <= sig + roundIncrement) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); uiZ = packToF32UI( sign, 0xFF, 0 ) - ! roundIncrement; goto uiZ; } } if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; sig = (sig + roundIncrement)>>7; sig &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); uiZ = packToF32UI( sign, sig ? exp : 0, sig ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToF64.c000066400000000000000000000073131464416617300271010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t softfloat_roundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) { uint_fast8_t roundingMode; bool roundNearEven; uint_fast16_t roundIncrement, roundBits; bool isTiny; uint_fast64_t uiZ; union ui64_f64 uZ; roundingMode = softfloat_roundingMode; roundNearEven = (roundingMode == softfloat_round_near_even); roundIncrement = 0x200; if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x3FF : 0; } roundBits = sig & 0x3FF; if ( 0x7FD <= (uint16_t) exp ) { if ( exp < 0 ) { isTiny = (softfloat_detectTininess == softfloat_tininess_beforeRounding) || (exp < -1) || (sig + roundIncrement < UINT64_C( 0x8000000000000000 )); sig = softfloat_shiftRightJam64( sig, -exp ); exp = 0; roundBits = sig & 0x3FF; if ( isTiny && roundBits ) { softfloat_raiseFlags( softfloat_flag_underflow ); } } else if ( (0x7FD < exp) || (UINT64_C( 0x8000000000000000 ) <= sig + roundIncrement) ) { softfloat_raiseFlags( softfloat_flag_overflow | softfloat_flag_inexact ); uiZ = packToF64UI( sign, 0x7FF, 0 ) - ! roundIncrement; goto uiZ; } } if ( roundBits ) softfloat_exceptionFlags |= softfloat_flag_inexact; sig = (sig + roundIncrement)>>10; sig &= ~(uint_fast64_t) (! (roundBits ^ 0x200) & roundNearEven); uiZ = packToF64UI( sign, sig ? exp : 0, sig ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI32.c000066400000000000000000000060511464416617300270750ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast32_t softfloat_roundPackToI32( bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact ) { bool roundNearEven; uint_fast8_t roundIncrement, roundBits; uint_fast32_t sig32; union { uint32_t ui; int32_t i; } uZ; int_fast32_t z; roundNearEven = (roundingMode == softfloat_round_near_even); roundIncrement = 0x40; if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x7F : 0; } roundBits = sig & 0x7F; sig += roundIncrement; if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; sig32 = sig>>7; sig32 &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); uZ.ui = sign ? -sig32 : sig32; z = uZ.i; if ( z && ((z < 0) ^ sign) ) goto invalid; if ( exact && roundBits ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToI64.c000066400000000000000000000061741464416617300271100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" int_fast64_t softfloat_roundPackToI64( bool sign, uint_fast64_t sig, uint_fast64_t sigExtra, uint_fast8_t roundingMode, bool exact ) { bool roundNearEven, doIncrement; union { uint64_t ui; int64_t i; } uZ; int_fast64_t z; roundNearEven = (roundingMode == softfloat_round_near_even); doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( doIncrement ) { ++sig; if ( ! sig ) goto invalid; sig &= ~(uint_fast64_t) (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) & roundNearEven); } uZ.ui = sign ? -sig : sig; z = uZ.i; if ( z && ((z < 0) ^ sign) ) goto invalid; if ( exact && sigExtra ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return sign ? -INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 : INT64_C( 0x7FFFFFFFFFFFFFFF ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI32.c000066400000000000000000000056131464416617300272250ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast32_t softfloat_roundPackToUI32( bool sign, uint_fast64_t sig, uint_fast8_t roundingMode, bool exact ) { bool roundNearEven; uint_fast8_t roundIncrement, roundBits; uint_fast32_t z; roundNearEven = (roundingMode == softfloat_round_near_even); roundIncrement = 0x40; if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { roundIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x7F : 0; } roundBits = sig & 0x7F; sig += roundIncrement; if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; z = sig>>7; z &= ~(uint_fast32_t) (! (roundBits ^ 0x40) & roundNearEven); if ( sign && z ) goto invalid; if ( exact && roundBits ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return z; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return 0xFFFFFFFF; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_roundPackToUI64.c000066400000000000000000000057141464416617300272340ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "softfloat.h" uint_fast64_t softfloat_roundPackToUI64( bool sign, uint_fast64_t sig, uint_fast64_t sigExtra, uint_fast8_t roundingMode, bool exact ) { bool roundNearEven, doIncrement; roundNearEven = (roundingMode == softfloat_round_near_even); doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra); if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) { doIncrement = (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; } if ( doIncrement ) { ++sig; if ( ! sig ) goto invalid; sig &= ~(uint_fast64_t) (! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF )) & roundNearEven); } if ( sign && sig ) goto invalid; if ( exact && sigExtra ) { softfloat_exceptionFlags |= softfloat_flag_inexact; } return sig; invalid: softfloat_raiseFlags( softfloat_flag_invalid ); return UINT64_C( 0xFFFFFFFFFFFFFFFF ); } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftLeftM.c000066400000000000000000000061641464416617300264400ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_shiftLeftM #define softfloat_shiftLeftM softfloat_shiftLeftM #include "primitives.h" void softfloat_shiftLeftM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t count, uint32_t *zPtr ) { uint32_t wordCount; uint_fast8_t innerCount; uint32_t *destPtr; uint_fast8_t i; wordCount = count>>5; if ( wordCount < size_words ) { aPtr += indexMultiwordLoBut( size_words, wordCount ); innerCount = count & 31; if ( innerCount ) { softfloat_shortShiftLeftM( size_words - wordCount, aPtr, innerCount, zPtr + indexMultiwordHiBut( size_words, wordCount ) ); if ( ! wordCount ) return; } else { aPtr += indexWordHi( size_words - wordCount ); destPtr = zPtr + indexWordHi( size_words ); for ( i = size_words - wordCount; i; --i ) { *destPtr = *aPtr; aPtr -= wordIncr; destPtr -= wordIncr; } } zPtr += indexMultiwordLo( size_words, wordCount ); } else { wordCount = size_words; } do { *zPtr++ = 0; --wordCount; } while ( wordCount ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftNormSigF128M.c000066400000000000000000000057271464416617300274710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" int softfloat_shiftNormSigF128M( const uint32_t *wPtr, uint_fast8_t shiftCount, uint32_t *sigPtr ) { uint32_t wordSig; int32_t exp; uint32_t leadingBit; wordSig = wPtr[indexWordHi( 4 )]; exp = expF128UI96( wordSig ); if ( exp ) { softfloat_shortShiftLeft128M( wPtr, shiftCount, sigPtr ); leadingBit = 0x00010000< #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shiftRightJam128 struct uint128 softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t count ) { int_fast32_t negCount; struct uint128 z; if ( count < 64 ) { negCount = -count; z.v64 = a64>>count; z.v0 = a64<<(negCount & 63) | a0>>count | ((uint64_t) (a0<<(negCount & 63)) != 0); } else { z.v64 = 0; z.v0 = (count < 127) ? a64>>(count & 63) | (((a64 & (((uint_fast64_t) 1<<(count & 63)) - 1)) | a0) != 0) : ((a64 | a0) != 0); } return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam128Extra.c000066400000000000000000000053551464416617300303760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shiftRightJam128Extra struct uint128_extra softfloat_shiftRightJam128Extra( uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t count ) { int_fast32_t negCount; struct uint128_extra z; negCount = -count; if ( count < 64 ) { z.v.v64 = a64>>count; z.v.v0 = a64<<(negCount & 63) | a0>>count; z.extra = a0<<(negCount & 63); } else { z.v.v64 = 0; if ( count == 64 ) { z.v.v0 = a64; z.extra = a0; } else { extra |= a0; if ( count < 128 ) { z.v.v0 = a64>>(count & 63); z.extra = a64<<(negCount & 63); } else { z.v.v0 = 0; z.extra = (count == 128) ? a64 : (a64 != 0); } } } z.extra |= (extra != 0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam256M.c000066400000000000000000000077661464416617300275210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shiftRightJam256M static void softfloat_shortShiftRightJamM( uint_fast8_t size_words, const uint64_t *aPtr, uint_fast8_t count, uint64_t *zPtr ) { uint_fast8_t negCount; unsigned int index, lastIndex; uint64_t partWordZ, wordA; negCount = -count; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); wordA = aPtr[index]; partWordZ = wordA>>count; if ( partWordZ<>count; } zPtr[index] = partWordZ; } void softfloat_shiftRightJam256M( const uint64_t *aPtr, uint_fast32_t count, uint64_t *zPtr ) { uint64_t wordJam; uint_fast32_t wordCount; uint64_t *ptr; uint_fast8_t i, innerCount; wordJam = 0; wordCount = count>>6; if ( wordCount ) { if ( 4 < wordCount ) wordCount = 4; ptr = (uint64_t *) (aPtr + indexMultiwordLo( 4, wordCount )); i = wordCount; do { wordJam = *ptr++; if ( wordJam ) break; --i; } while ( i ); ptr = zPtr; } if ( wordCount < 4 ) { aPtr += indexMultiwordHiBut( 4, wordCount ); innerCount = count & 63; if ( innerCount ) { softfloat_shortShiftRightJamM( 4 - wordCount, aPtr, innerCount, zPtr + indexMultiwordLoBut( 4, wordCount ) ); if ( ! wordCount ) goto wordJam; } else { aPtr += indexWordLo( 4 - wordCount ); ptr = zPtr + indexWordLo( 4 ); for ( i = 4 - wordCount; i; --i ) { *ptr = *aPtr; aPtr += wordIncr; ptr += wordIncr; } } ptr = zPtr + indexMultiwordHi( 4, wordCount ); } do { *ptr++ = 0; --wordCount; } while ( wordCount ); wordJam: if ( wordJam ) zPtr[indexWordLo( 4 )] |= 1; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam32.c000066400000000000000000000041171464416617300272770ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_shiftRightJam32 uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t count ) { return (count < 31) ? a>>count | ((uint32_t) (a<<(-count & 31)) != 0) : (a != 0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64.c000066400000000000000000000041171464416617300273040ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_shiftRightJam64 uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t count ) { return (count < 63) ? a>>count | ((uint64_t) (a<<(-count & 63)) != 0) : (a != 0); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJam64Extra.c000066400000000000000000000044321464416617300303100ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shiftRightJam64Extra struct uint64_extra softfloat_shiftRightJam64Extra( uint64_t a, uint64_t extra, uint_fast32_t count ) { struct uint64_extra z; if ( count < 64 ) { z.v = a>>count; z.extra = a<<(-count & 63); } else { z.v = 0; z.extra = (count == 64) ? a : (a != 0); } z.extra |= (extra != 0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightJamM.c000066400000000000000000000067361464416617300272600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_shiftRightJamM #define softfloat_shiftRightJamM softfloat_shiftRightJamM #include "primitives.h" void softfloat_shiftRightJamM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t count, uint32_t *zPtr ) { uint32_t wordJam, wordCount, *ptr; uint_fast8_t i, innerCount; wordJam = 0; wordCount = count>>5; if ( wordCount ) { if ( size_words < wordCount ) wordCount = size_words; ptr = (uint32_t *) (aPtr + indexMultiwordLo( size_words, wordCount )); i = wordCount; do { wordJam = *ptr++; if ( wordJam ) break; --i; } while ( i ); ptr = zPtr; } if ( wordCount < size_words ) { aPtr += indexMultiwordHiBut( size_words, wordCount ); innerCount = count & 31; if ( innerCount ) { softfloat_shortShiftRightJamM( size_words - wordCount, aPtr, innerCount, zPtr + indexMultiwordLoBut( size_words, wordCount ) ); if ( ! wordCount ) goto wordJam; } else { aPtr += indexWordLo( size_words - wordCount ); ptr = zPtr + indexWordLo( size_words ); for ( i = size_words - wordCount; i; --i ) { *ptr = *aPtr; aPtr += wordIncr; ptr += wordIncr; } } ptr = zPtr + indexMultiwordHi( size_words, wordCount ); } do { *ptr++ = 0; --wordCount; } while ( wordCount ); wordJam: if ( wordJam ) zPtr[indexWordLo( size_words )] |= 1; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shiftRightM.c000066400000000000000000000061711464416617300266210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_shiftRightM #define softfloat_shiftRightM softfloat_shiftRightM #include "primitives.h" void softfloat_shiftRightM( uint_fast8_t size_words, const uint32_t *aPtr, uint32_t count, uint32_t *zPtr ) { uint32_t wordCount; uint_fast8_t innerCount; uint32_t *destPtr; uint_fast8_t i; wordCount = count>>5; if ( wordCount < size_words ) { aPtr += indexMultiwordHiBut( size_words, wordCount ); innerCount = count & 31; if ( innerCount ) { softfloat_shortShiftRightM( size_words - wordCount, aPtr, innerCount, zPtr + indexMultiwordLoBut( size_words, wordCount ) ); if ( ! wordCount ) return; } else { aPtr += indexWordLo( size_words - wordCount ); destPtr = zPtr + indexWordLo( size_words ); for ( i = size_words - wordCount; i; --i ) { *destPtr = *aPtr; aPtr += wordIncr; destPtr += wordIncr; } } zPtr += indexMultiwordHi( size_words, wordCount ); } else { wordCount = size_words; } do { *zPtr++ = 0; --wordCount; } while ( wordCount ); } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeft128.c000066400000000000000000000042001464416617300275630ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftLeft128 struct uint128 softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t count ) { struct uint128 z; z.v64 = a64<>(-count & 63); z.v0 = a0< #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftLeft64To96M void softfloat_shortShiftLeft64To96M( uint64_t a, uint_fast8_t count, uint32_t *zPtr ) { zPtr[indexWord( 3, 0 )] = (uint32_t) a<>= 32 - count; zPtr[indexWord( 3, 2 )] = a>>32; zPtr[indexWord( 3, 1 )] = a; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftLeftM.c000066400000000000000000000050241464416617300274520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftLeftM void softfloat_shortShiftLeftM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int index, lastIndex; uint32_t partWordZ, wordA; negCount = -count; index = indexWordHi( size_words ); lastIndex = indexWordLo( size_words ); partWordZ = aPtr[index]<>(negCount & 31); index -= wordIncr; partWordZ = wordA< #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRight128 struct uint128 softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t count ) { struct uint128 z; z.v64 = a64>>count; z.v0 = a64<<(-count & 63) | a0>>count; return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightExtendM.c000066400000000000000000000051341464416617300310070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightExtendM void softfloat_shortShiftRightExtendM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int indexA, lastIndexA; uint32_t partWordZ, wordA; negCount = -count; indexA = indexWordLo( size_words ); lastIndexA = indexWordHi( size_words ); zPtr += indexWordLo( size_words + 1 ); partWordZ = 0; for (;;) { wordA = aPtr[indexA]; *zPtr = wordA<<(negCount & 31) | partWordZ; zPtr += wordIncr; partWordZ = wordA>>count; if ( indexA == lastIndexA ) break; indexA += wordIncr; } *zPtr = partWordZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128.c000066400000000000000000000043771464416617300304150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJam128 struct uint128 softfloat_shortShiftRightJam128( uint64_t a64, uint64_t a0, uint_fast8_t count ) { int_fast8_t negCount; struct uint128 z; negCount = -count; z.v64 = a64>>count; z.v0 = a64<<(negCount & 63) | a0>>count | ((uint64_t) (a0<<(negCount & 63)) != 0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam128Extra.c000066400000000000000000000044361464416617300314150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJam128Extra struct uint128_extra softfloat_shortShiftRightJam128Extra( uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t count ) { uint_fast8_t negCount; struct uint128_extra z; negCount = -count; z.v.v64 = a64>>count; z.v.v0 = a64<<(negCount & 63) | a0>>count; z.extra = a0<<(negCount & 63) | (extra != 0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJam64.c000066400000000000000000000040631464416617300303240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #ifndef softfloat_shortShiftRightJam64 uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t count ) { return a>>count | ((a & (((uint_fast64_t) 1< #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJam64Extra struct uint64_extra softfloat_shortShiftRightJam64Extra( uint64_t a, uint64_t extra, uint_fast8_t count ) { struct uint64_extra z; z.v = a>>count; z.extra = a<<(-count & 63) | (extra != 0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightJamM.c000066400000000000000000000051441464416617300302700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightJamM void softfloat_shortShiftRightJamM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int index, lastIndex; uint32_t partWordZ, wordA; negCount = -count; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); wordA = aPtr[index]; partWordZ = wordA>>count; if ( partWordZ<>count; } zPtr[index] = partWordZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_shortShiftRightM.c000066400000000000000000000050261464416617300276370ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_shortShiftRightM void softfloat_shortShiftRightM( uint_fast8_t size_words, const uint32_t *aPtr, uint_fast8_t count, uint32_t *zPtr ) { uint_fast8_t negCount; unsigned int index, lastIndex; uint32_t partWordZ, wordA; negCount = -count; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); partWordZ = aPtr[index]>>count; while ( index != lastIndex ) { wordA = aPtr[index + wordIncr]; zPtr[index] = wordA<<(negCount & 31) | partWordZ; index += wordIncr; partWordZ = wordA>>count; } zPtr[index] = partWordZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_sub128.c000066400000000000000000000041461464416617300254150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_sub128 struct uint128 softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) { struct uint128 z; z.v0 = a0 - b0; z.v64 = a64 - b64 - (a0 < b0); return z; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_sub1XM.c000066400000000000000000000044361464416617300255120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_sub1XM void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr ) { unsigned int index, lastIndex; uint32_t wordA; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); for (;;) { wordA = zPtr[index]; zPtr[index] = wordA - 1; if ( wordA || (index == lastIndex) ) break; index += wordIncr; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_sub256M.c000066400000000000000000000046161464416617300255360ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_sub256M void softfloat_sub256M( const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr ) { unsigned int index; uint_fast8_t borrow; uint64_t wordA, wordB; index = indexWordLo( 4 ); borrow = 0; for (;;) { wordA = aPtr[index]; wordB = bPtr[index]; zPtr[index] = wordA - wordB - borrow; if ( index == indexWordHi( 4 ) ) break; borrow = borrow ? (wordA <= wordB) : (wordA < wordB); index += wordIncr; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_subM.c000066400000000000000000000047511464416617300253010ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "primitiveTypes.h" #ifndef softfloat_subM void softfloat_subM( uint_fast8_t size_words, const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr ) { unsigned int index, lastIndex; uint_fast8_t borrow; uint32_t wordA, wordB; index = indexWordLo( size_words ); lastIndex = indexWordHi( size_words ); borrow = 0; for (;;) { wordA = aPtr[index]; wordB = bPtr[index]; zPtr[index] = wordA - wordB - borrow; if ( index == lastIndex ) break; borrow = borrow ? (wordA <= wordB) : (wordA < wordB); index += wordIncr; } } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsExtF80.c000066400000000000000000000132561464416617300267330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" extFloat80_t softfloat_subMagsExtF80( uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; uint_fast64_t sigA; int_fast32_t expB; uint_fast64_t sigB; int_fast32_t expDiff; uint_fast16_t uiZ64; uint_fast64_t uiZ0; int_fast32_t expZ; uint_fast64_t sigExtra; struct uint128 sig128, uiZ; union { struct extFloat80M s; extFloat80_t f; } uZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expA = expExtF80UI64( uiA64 ); sigA = uiA0; expB = expExtF80UI64( uiB64 ); sigB = uiB0; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expDiff = expA - expB; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0x7FFF ) { if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { goto propagateNaN; } softfloat_raiseFlags( softfloat_flag_invalid ); uiZ64 = defaultNaNExtF80UI64; uiZ0 = defaultNaNExtF80UI0; goto uiZ; } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expZ = expA; if ( ! expZ ) expZ = 1; sigExtra = 0; if ( sigB < sigA ) goto aBigger; if ( sigA < sigB ) goto bBigger; uiZ64 = packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 ); uiZ0 = 0; goto uiZ; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expBBigger: if ( expB == 0x7FFF ) { if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = packToExtF80UI64( signZ ^ 1, 0x7FFF ); uiZ0 = UINT64_C( 0x8000000000000000 ); goto uiZ; } if ( ! expA ) { ++expDiff; sigExtra = 0; if ( ! expDiff ) goto newlyAlignedBBigger; } sig128 = softfloat_shiftRightJam128( sigA, 0, -expDiff ); sigA = sig128.v64; sigExtra = sig128.v0; newlyAlignedBBigger: expZ = expB; bBigger: signZ ^= 1; sig128 = softfloat_sub128( sigB, 0, sigA, sigExtra ); goto normRoundPack; /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ expABigger: if ( expA == 0x7FFF ) { if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; uiZ64 = uiA64; uiZ0 = uiA0; goto uiZ; } if ( ! expB ) { --expDiff; sigExtra = 0; if ( ! expDiff ) goto newlyAlignedABigger; } sig128 = softfloat_shiftRightJam128( sigB, 0, expDiff ); sigB = sig128.v64; sigExtra = sig128.v0; newlyAlignedABigger: expZ = expA; aBigger: sig128 = softfloat_sub128( sigA, 0, sigB, sigExtra ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ normRoundPack: return softfloat_normRoundPackToExtF80( signZ, expZ, sig128.v64, sig128.v0, extF80_roundingPrecision ); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ propagateNaN: uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); uiZ64 = uiZ.v64; uiZ0 = uiZ.v0; uiZ: uZ.s.signExp = uiZ64; uZ.s.signif = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF128.c000066400000000000000000000112511464416617300263260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float128_t softfloat_subMagsF128( uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0, bool signZ ) { int_fast32_t expA; struct uint128 sigA; int_fast32_t expB; struct uint128 sigB, sigZ; int_fast32_t expDiff, expZ; struct uint128 uiZ; union ui128_f128 uZ; expA = expF128UI64( uiA64 ); sigA.v64 = fracF128UI64( uiA64 ); sigA.v0 = uiA0; expB = expF128UI64( uiB64 ); sigB.v64 = fracF128UI64( uiB64 ); sigB.v0 = uiB0; sigA = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 4 ); sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 4 ); expDiff = expA - expB; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN; softfloat_raiseFlags( softfloat_flag_invalid ); uiZ.v64 = defaultNaNF128UI64; uiZ.v0 = defaultNaNF128UI0; goto uiZ; } expZ = expA; if ( ! expZ ) expZ = 1; if ( sigB.v64 < sigA.v64 ) goto aBigger; if ( sigA.v64 < sigB.v64 ) goto bBigger; if ( sigB.v0 < sigA.v0 ) goto aBigger; if ( sigA.v0 < sigB.v0 ) goto bBigger; uiZ.v64 = packToF128UI64( (softfloat_roundingMode == softfloat_round_min), 0, 0 ); uiZ.v0 = 0; goto uiZ; expBBigger: if ( expB == 0x7FFF ) { if ( sigB.v64 | sigB.v0 ) goto propagateNaN; uiZ.v64 = packToF128UI64( signZ ^ 1, 0x7FFF, 0 ); uiZ.v0 = 0; goto uiZ; } if ( expA ) { sigA.v64 |= UINT64_C( 0x0010000000000000 ); } else { ++expDiff; if ( ! expDiff ) goto newlyAlignedBBigger; } sigA = softfloat_shiftRightJam128( sigA.v64, sigA.v0, -expDiff ); newlyAlignedBBigger: expZ = expB; sigB.v64 |= UINT64_C( 0x0010000000000000 ); bBigger: signZ ^= 1; sigZ = softfloat_sub128( sigB.v64, sigB.v0, sigA.v64, sigA.v0 ); goto normRoundPack; expABigger: if ( expA == 0x7FFF ) { if ( sigA.v64 | sigA.v0 ) goto propagateNaN; uiZ.v64 = uiA64; uiZ.v0 = uiA0; goto uiZ; } if ( expB ) { sigB.v64 |= UINT64_C( 0x0010000000000000 ); } else { --expDiff; if ( ! expDiff ) goto newlyAlignedABigger; } sigB = softfloat_shiftRightJam128( sigB.v64, sigB.v0, expDiff ); newlyAlignedABigger: expZ = expA; sigA.v64 |= UINT64_C( 0x0010000000000000 ); aBigger: sigZ = softfloat_sub128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ); normRoundPack: return softfloat_normRoundPackToF128( signZ, expZ - 5, sigZ.v64, sigZ.v0 ); propagateNaN: uiZ = softfloat_propagateNaNF128UI( uiA64, uiA0, uiB64, uiB0 ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF32.c000066400000000000000000000073161464416617300262470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float32_t softfloat_subMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) { int_fast16_t expA; uint_fast32_t sigA; int_fast16_t expB; uint_fast32_t sigB; int_fast16_t expDiff; uint_fast32_t uiZ; int_fast16_t expZ; uint_fast32_t sigZ; union ui32_f32 uZ; expA = expF32UI( uiA ); sigA = fracF32UI( uiA ); expB = expF32UI( uiB ); sigB = fracF32UI( uiB ); expDiff = expA - expB; sigA <<= 7; sigB <<= 7; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0xFF ) { if ( sigA | sigB ) goto propagateNaN; softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF32UI; goto uiZ; } if ( ! expA ) { expA = 1; expB = 1; } if ( sigB < sigA ) goto aBigger; if ( sigA < sigB ) goto bBigger; uiZ = packToF32UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); goto uiZ; expBBigger: if ( expB == 0xFF ) { if ( sigB ) goto propagateNaN; uiZ = packToF32UI( signZ ^ 1, 0xFF, 0 ); goto uiZ; } sigA += expA ? 0x40000000 : sigA; sigA = softfloat_shiftRightJam32( sigA, -expDiff ); sigB |= 0x40000000; bBigger: signZ ^= 1; expZ = expB; sigZ = sigB - sigA; goto normRoundPack; expABigger: if ( expA == 0xFF ) { if ( sigA ) goto propagateNaN; uiZ = uiA; goto uiZ; } sigB += expB ? 0x40000000 : sigB; sigB = softfloat_shiftRightJam32( sigB, expDiff ); sigA |= 0x40000000; aBigger: expZ = expA; sigZ = sigA - sigB; normRoundPack: return softfloat_normRoundPackToF32( signZ, expZ - 1, sigZ ); propagateNaN: uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_subMagsF64.c000066400000000000000000000074441464416617300262560ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" float64_t softfloat_subMagsF64( uint_fast64_t uiA, uint_fast64_t uiB, bool signZ ) { int_fast16_t expA; uint_fast64_t sigA; int_fast16_t expB; uint_fast64_t sigB; int_fast16_t expDiff; uint_fast64_t uiZ; int_fast16_t expZ; uint_fast64_t sigZ; union ui64_f64 uZ; expA = expF64UI( uiA ); sigA = fracF64UI( uiA ); expB = expF64UI( uiB ); sigB = fracF64UI( uiB ); expDiff = expA - expB; sigA <<= 10; sigB <<= 10; if ( 0 < expDiff ) goto expABigger; if ( expDiff < 0 ) goto expBBigger; if ( expA == 0x7FF ) { if ( sigA | sigB ) goto propagateNaN; softfloat_raiseFlags( softfloat_flag_invalid ); uiZ = defaultNaNF64UI; goto uiZ; } if ( ! expA ) { expA = 1; expB = 1; } if ( sigB < sigA ) goto aBigger; if ( sigA < sigB ) goto bBigger; uiZ = packToF64UI( softfloat_roundingMode == softfloat_round_min, 0, 0 ); goto uiZ; expBBigger: if ( expB == 0x7FF ) { if ( sigB ) goto propagateNaN; uiZ = packToF64UI( signZ ^ 1, 0x7FF, 0 ); goto uiZ; } sigA += expA ? UINT64_C( 0x4000000000000000 ) : sigA; sigA = softfloat_shiftRightJam64( sigA, -expDiff ); sigB |= UINT64_C( 0x4000000000000000 ); bBigger: signZ ^= 1; expZ = expB; sigZ = sigB - sigA; goto normRoundPack; expABigger: if ( expA == 0x7FF ) { if ( sigA ) goto propagateNaN; uiZ = uiA; goto uiZ; } sigB += expB ? UINT64_C( 0x4000000000000000 ) : sigB; sigB = softfloat_shiftRightJam64( sigB, expDiff ); sigA |= UINT64_C( 0x4000000000000000 ); aBigger: expZ = expA; sigZ = sigA - sigB; normRoundPack: return softfloat_normRoundPackToF64( signZ, expZ - 1, sigZ ); propagateNaN: uiZ = softfloat_propagateNaNF64UI( uiA, uiB ); uiZ: uZ.ui = uiZ; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNExtF80M.c000066400000000000000000000046451464416617300305270ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" bool softfloat_tryPropagateNaNExtF80M( const struct extFloat80M *aSPtr, const struct extFloat80M *bSPtr, struct extFloat80M *zSPtr ) { uint_fast16_t ui64; uint64_t ui0; ui64 = aSPtr->signExp; ui0 = aSPtr->signif; if ( isNaNExtF80UI( ui64, ui0 ) ) goto propagateNaN; ui64 = bSPtr->signExp; ui0 = bSPtr->signif; if ( isNaNExtF80UI( ui64, ui0 ) ) goto propagateNaN; return false; propagateNaN: softfloat_propagateNaNExtF80M( aSPtr, bSPtr, zSPtr ); return true; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/s_tryPropagateNaNF128M.c000066400000000000000000000043211464416617300301200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include #include "platform.h" #include "internals.h" #include "specialize.h" bool softfloat_tryPropagateNaNF128M( const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr ) { if ( softfloat_isNaNF128M( aWPtr ) || softfloat_isNaNF128M( bWPtr ) ) { softfloat_propagateNaNF128M( aWPtr, bWPtr, zWPtr ); return true; } return false; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/softfloat_state.c000066400000000000000000000042031464416617300272420ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "specialize.h" #include "softfloat.h" uint_fast8_t softfloat_roundingMode = softfloat_round_near_even; uint_fast8_t softfloat_detectTininess = init_detectTininess; uint_fast8_t softfloat_exceptionFlags = 0; uint_fast8_t extF80_roundingPrecision = 80; optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/sub.mk000066400000000000000000000027701464416617300250260ustar00rootroot00000000000000incdirs-lib-y += include incdirs-lib-y += 8086-SSE subdirs-y += 8086-SSE cflags-y += -Wno-aggregate-return cflags-y += -Wno-sign-compare cflags-y += -Wno-missing-prototypes cflags-y += -Wno-missing-declarations srcs-y += f32_add.c srcs-y += f32_div.c srcs-y += f32_eq.c srcs-y += f32_le.c srcs-y += f32_lt.c srcs-y += f32_mul.c srcs-y += f32_sub.c srcs-y += f32_to_f64.c srcs-y += f32_to_i32_r_minMag.c srcs-y += f32_to_i64_r_minMag.c srcs-y += f32_to_ui32_r_minMag.c srcs-y += f32_to_ui64_r_minMag.c srcs-y += f64_add.c srcs-y += f64_div.c srcs-y += f64_eq.c srcs-y += f64_le.c srcs-y += f64_lt.c srcs-y += f64_mul.c srcs-y += f64_sub.c srcs-y += f64_to_f32.c srcs-y += f64_to_i32_r_minMag.c srcs-y += f64_to_i64_r_minMag.c srcs-y += f64_to_ui32_r_minMag.c srcs-y += f64_to_ui64_r_minMag.c srcs-y += i32_to_f32.c srcs-y += i32_to_f64.c srcs-y += i64_to_f32.c srcs-y += i64_to_f64.c srcs-y += ui32_to_f32.c srcs-y += ui32_to_f64.c srcs-y += ui64_to_f32.c srcs-y += ui64_to_f64.c srcs-y += s_subMagsF32.c srcs-y += s_subMagsF64.c srcs-y += s_addMagsF32.c srcs-y += s_addMagsF64.c srcs-y += s_normSubnormalF64Sig.c srcs-y += s_normSubnormalF32Sig.c srcs-y += s_roundPackToF32.c srcs-y += s_roundPackToF64.c srcs-y += s_shortShiftRightJam64.c srcs-y += s_shiftRightJam32.c srcs-y += s_normRoundPackToF32.c srcs-y += s_normRoundPackToF64.c srcs-y += s_shiftRightJam64.c srcs-y += s_countLeadingZeros8.c srcs-y += s_countLeadingZeros32.c srcs-y += s_countLeadingZeros64.c srcs-y += s_mul64To128.c srcs-y += softfloat_state.c optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80.c000066400000000000000000000044421464416617300264700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t ui32_to_extF80( uint32_t a ) { uint_fast16_t uiZ64; int_fast8_t shiftCount; union { struct extFloat80M s; extFloat80_t f; } uZ; uiZ64 = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros32( a ); uiZ64 = 0x401E - shiftCount; a <<= shiftCount; } uZ.s.signExp = uiZ64; uZ.s.signif = (uint_fast64_t) a<<32; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_extF80M.c000066400000000000000000000047711464416617300266120ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr ) { *zPtr = ui32_to_extF80( a ); } #else void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr ) { struct extFloat80M *zSPtr; uint_fast16_t uiZ64; uint64_t sigZ; int_fast8_t shiftCount; zSPtr = (struct extFloat80M *) zPtr; uiZ64 = 0; sigZ = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros32( a ); uiZ64 = packToExtF80UI64( 0, 0x401E - shiftCount ); sigZ = (uint64_t) (a<signExp = uiZ64; zSPtr->signif = sigZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f128.c000066400000000000000000000044411464416617300260710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t ui32_to_f128( uint32_t a ) { uint_fast64_t uiZ64; int_fast8_t shiftCount; union ui128_f128 uZ; uiZ64 = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros32( a ) + 17; uiZ64 = packToF128UI64( 0, 0x402E - shiftCount, (uint_fast64_t) a< #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void ui32_to_f128M( uint32_t a, float128_t *zPtr ) { *zPtr = ui32_to_f128( a ); } #else void ui32_to_f128M( uint32_t a, float128_t *zPtr ) { uint32_t *zWPtr, uiZ96, uiZ64; int_fast8_t shiftCount; uint64_t normA; zWPtr = (uint32_t *) zPtr; uiZ96 = 0; uiZ64 = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros32( a ) + 17; normA = (uint64_t) a<>32 ); uiZ64 = normA; } zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = uiZ64; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f32.c000066400000000000000000000043031464416617300260000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t ui32_to_f32( uint32_t a ) { union ui32_f32 uZ; if ( ! a ) { uZ.ui = 0; return uZ.f; } if ( a & 0x80000000 ) { return softfloat_roundPackToF32( 0, 0x9D, a>>1 | (a & 1) ); } else { return softfloat_normRoundPackToF32( 0, 0x9C, a ); } } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui32_to_f64.c000066400000000000000000000044151464416617300260110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t ui32_to_f64( uint32_t a ) { uint_fast64_t uiZ; int_fast8_t shiftCount; union ui64_f64 uZ; if ( ! a ) { uiZ = 0; } else { shiftCount = softfloat_countLeadingZeros32( a ) + 21; uiZ = packToF64UI( 0, 0x432 - shiftCount, (uint_fast64_t) a< #include "platform.h" #include "internals.h" #include "softfloat.h" extFloat80_t ui64_to_extF80( uint64_t a ) { uint_fast16_t uiZ64; int_fast8_t shiftCount; union { struct extFloat80M s; extFloat80_t f; } uZ; uiZ64 = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros64( a ); uiZ64 = 0x403E - shiftCount; a <<= shiftCount; } uZ.s.signExp = uiZ64; uZ.s.signif = a; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_extF80M.c000066400000000000000000000047501464416617300266140ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr ) { *zPtr = ui64_to_extF80( a ); } #else void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr ) { struct extFloat80M *zSPtr; uint_fast16_t uiZ64; uint64_t sigZ; int_fast8_t shiftCount; zSPtr = (struct extFloat80M *) zPtr; uiZ64 = 0; sigZ = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros64( a ); uiZ64 = packToExtF80UI64( 0, 0x403E - shiftCount ); sigZ = a<signExp = uiZ64; zSPtr->signif = sigZ; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128.c000066400000000000000000000050311464416617300260720ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float128_t ui64_to_f128( uint64_t a ) { uint_fast64_t uiZ64, uiZ0; int_fast8_t shiftCount; struct uint128 zSig; union ui128_f128 uZ; if ( ! a ) { uiZ64 = 0; uiZ0 = 0; } else { shiftCount = softfloat_countLeadingZeros64( a ) + 49; if ( 64 <= shiftCount ) { zSig.v64 = a<<(shiftCount - 64); zSig.v0 = 0; } else { zSig = softfloat_shortShiftLeft128( 0, a, shiftCount ); } uiZ64 = packToF128UI64( 0, 0x406E - shiftCount, zSig.v64 ); uiZ0 = zSig.v0; } uZ.ui.v64 = uiZ64; uZ.ui.v0 = uiZ0; return uZ.f; } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f128M.c000066400000000000000000000057621464416617300262220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" #ifdef SOFTFLOAT_FAST_INT64 void ui64_to_f128M( uint64_t a, float128_t *zPtr ) { *zPtr = ui64_to_f128( a ); } #else void ui64_to_f128M( uint64_t a, float128_t *zPtr ) { uint32_t *zWPtr, uiZ96, uiZ64; uint_fast8_t shiftCount; uint32_t *ptr; zWPtr = (uint32_t *) zPtr; uiZ96 = 0; uiZ64 = 0; zWPtr[indexWord( 4, 1 )] = 0; zWPtr[indexWord( 4, 0 )] = 0; if ( a ) { shiftCount = softfloat_countLeadingZeros64( a ) + 17; if ( shiftCount < 32 ) { ptr = zWPtr + indexMultiwordHi( 4, 3 ); ptr[indexWord( 3, 2 )] = 0; ptr[indexWord( 3, 1 )] = a>>32; ptr[indexWord( 3, 0 )] = a; softfloat_shortShiftLeft96M( ptr, shiftCount, ptr ); ptr[indexWordHi( 3 )] = packToF128UI96( 0, 0x404E - shiftCount, ptr[indexWordHi( 3 )] ); return; } a <<= shiftCount - 32; uiZ96 = packToF128UI96( 0, 0x404E - shiftCount, a>>32 ); uiZ64 = a; } zWPtr[indexWord( 4, 3 )] = uiZ96; zWPtr[indexWord( 4, 2 )] = uiZ64; } #endif optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/source/ui64_to_f32.c000066400000000000000000000047771464416617300260240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic Package, Release 3a, by John R. Hauser. Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include #include "platform.h" #include "internals.h" #include "softfloat.h" float32_t ui64_to_f32( uint64_t a ) { int_fast8_t shiftCount; union ui32_f32 u; uint_fast32_t sig; shiftCount = softfloat_countLeadingZeros64( a ) - 40; if ( 0 <= shiftCount ) { u.ui = a ? packToF32UI( 0, 0x95 - shiftCount, (uint_fast32_t) a< #include "platform.h" #include "internals.h" #include "softfloat.h" float64_t ui64_to_f64( uint64_t a ) { union ui64_f64 uZ; if ( ! a ) { uZ.ui = 0; return uZ.f; } if ( a & UINT64_C( 0x8000000000000000 ) ) { return softfloat_roundPackToF64( 0, 0x43D, softfloat_shortShiftRightJam64( a, 1 ) ); } else { return softfloat_normRoundPackToF64( 0, 0x43C, a ); } } optee_os-4.3.0/lib/libutils/isoc/arch/arm/softfloat/sub.mk000066400000000000000000000000641464416617300235200ustar00rootroot00000000000000incdirs-lib-y += arm32_include subdirs-y += source optee_os-4.3.0/lib/libutils/isoc/arch/arm/sub.mk000066400000000000000000000023141464416617300215170ustar00rootroot00000000000000# These files implements the__aeabi functions we need instead of # relying on libgcc or equivalent as we need implementations suitable # for bare metal. srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_divmod_a32.S srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_divmod.c srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_ldivmod_a32.S srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_ldivmod.c srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_shift.c # We would not like to profile __aeabi functions as these provide # internal implementations for "/ %" operations. Also, "/ %" operations # could be used inside profiling code which could create an incorrect # cyclic behaviour. cflags-remove-arm32_aeabi_divmod.c-y += -pg cflags-remove-arm32_aeabi_ldivmod.c-y += -pg cflags-remove-arm32_aeabi_shift.c-y += -pg srcs-$(CFG_ARM32_$(sm)) += setjmp_a32.S srcs-$(CFG_ARM64_$(sm)) += setjmp_a64.S ifeq ($(CFG_TA_FLOAT_SUPPORT),y) # Floating point is only supported for user TAs ifneq ($(sm),core) srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_softfloat.c cflags-arm32_aeabi_softfloat.c-y += -Wno-aggregate-return cflags-arm32_aeabi_softfloat.c-y += -Wno-missing-prototypes cflags-arm32_aeabi_softfloat.c-y += -Wno-missing-declarations subdirs-$(CFG_ARM32_$(sm)) += softfloat endif endif optee_os-4.3.0/lib/libutils/isoc/arch/riscv/000077500000000000000000000000001464416617300207445ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/arch/riscv/setjmp_rv.S000066400000000000000000000032541464416617300231050ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2023 Andes Technology Corporation * Copyright 2022-2023 NXP */ #include /* int setjmp (jmp_buf) */ FUNC setjmp , : STR s0, REGOFF(0)(a0) STR s1, REGOFF(1)(a0) STR s2, REGOFF(2)(a0) STR s3, REGOFF(3)(a0) STR s4, REGOFF(4)(a0) STR s5, REGOFF(5)(a0) STR s6, REGOFF(6)(a0) STR s7, REGOFF(7)(a0) STR s8, REGOFF(8)(a0) STR s9, REGOFF(9)(a0) STR s10, REGOFF(10)(a0) STR s11, REGOFF(11)(a0) STR ra, REGOFF(12)(a0) STR sp, REGOFF(13)(a0) #ifdef CFG_FTRACE_SUPPORT addi sp, sp, -16 #ifdef RV32 STR ra, REGOFF(3)(sp) STR s0, REGOFF(2)(sp) #else STR ra, REGOFF(1)(sp) STR s0, REGOFF(0)(sp) #endif addi s0, sp, 16 addi a0, a0, REGOFF(14) call ftrace_setjmp #ifdef RV32 LDR s0, REGOFF(2)(sp) LDR ra, REGOFF(3)(sp) #else LDR s0, REGOFF(0)(sp) LDR ra, REGOFF(1)(sp) #endif addi sp, sp, 16 #endif li a0, 0 ret END_FUNC setjmp /* void longjmp (jmp_buf, int) __attribute__ ((noreturn)) */ FUNC longjmp , : #ifdef CFG_FTRACE_SUPPORT addi sp, sp, -REGOFF(4) STR a0, REGOFF(0)(sp) STR a1, REGOFF(1)(sp) STR s0, REGOFF(2)(sp) STR ra, REGOFF(3)(sp) addi s0, sp, REGOFF(4) addi a0, a0, REGOFF(14) call ftrace_longjmp LDR a0, REGOFF(0)(sp) LDR a1, REGOFF(1)(sp) LDR s0, REGOFF(2)(sp) LDR ra, REGOFF(3)(sp) addi sp, sp, REGOFF(4) #endif LDR s0, REGOFF(0)(a0) LDR s1, REGOFF(1)(a0) LDR s2, REGOFF(2)(a0) LDR s3, REGOFF(3)(a0) LDR s4, REGOFF(4)(a0) LDR s5, REGOFF(5)(a0) LDR s6, REGOFF(6)(a0) LDR s7, REGOFF(7)(a0) LDR s8, REGOFF(8)(a0) LDR s9, REGOFF(9)(a0) LDR s10, REGOFF(10)(a0) LDR s11, REGOFF(11)(a0) LDR ra, REGOFF(12)(a0) LDR sp, REGOFF(13)(a0) seqz a0, a1 add a0, a0, a1 ret END_FUNC longjmp optee_os-4.3.0/lib/libutils/isoc/arch/riscv/sub.mk000066400000000000000000000000271464416617300220650ustar00rootroot00000000000000srcs-y += setjmp_rv.S optee_os-4.3.0/lib/libutils/isoc/bget.c000066400000000000000000001577171464416617300200100ustar00rootroot00000000000000/* B G E T Buffer allocator Designed and implemented in April of 1972 by John Walker, based on the Case Algol OPRO$ algorithm implemented in 1966. Reimplemented in 1975 by John Walker for the Interdata 70. Reimplemented in 1977 by John Walker for the Marinchip 9900. Reimplemented in 1982 by Duff Kurland for the Intel 8080. Portable C version implemented in September of 1990 by an older, wiser instance of the original implementor. Souped up and/or weighed down slightly shortly thereafter by Greg Lutz. AMIX edition, including the new compaction call-back option, prepared by John Walker in July of 1992. Bug in built-in test program fixed, ANSI compiler warnings eradicated, buffer pool validator implemented, and guaranteed repeatable test added by John Walker in October of 1995. This program is in the public domain. 1. This is the book of the generations of Adam. In the day that God created man, in the likeness of God made he him; 2. Male and female created he them; and blessed them, and called their name Adam, in the day when they were created. 3. And Adam lived an hundred and thirty years, and begat a son in his own likeness, and after his image; and called his name Seth: 4. And the days of Adam after he had begotten Seth were eight hundred years: and he begat sons and daughters: 5. And all the days that Adam lived were nine hundred and thirty years: and he died. 6. And Seth lived an hundred and five years, and begat Enos: 7. And Seth lived after he begat Enos eight hundred and seven years, and begat sons and daughters: 8. And all the days of Seth were nine hundred and twelve years: and he died. 9. And Enos lived ninety years, and begat Cainan: 10. And Enos lived after he begat Cainan eight hundred and fifteen years, and begat sons and daughters: 11. And all the days of Enos were nine hundred and five years: and he died. 12. And Cainan lived seventy years and begat Mahalaleel: 13. And Cainan lived after he begat Mahalaleel eight hundred and forty years, and begat sons and daughters: 14. And all the days of Cainan were nine hundred and ten years: and he died. 15. And Mahalaleel lived sixty and five years, and begat Jared: 16. And Mahalaleel lived after he begat Jared eight hundred and thirty years, and begat sons and daughters: 17. And all the days of Mahalaleel were eight hundred ninety and five years: and he died. 18. And Jared lived an hundred sixty and two years, and he begat Enoch: 19. And Jared lived after he begat Enoch eight hundred years, and begat sons and daughters: 20. And all the days of Jared were nine hundred sixty and two years: and he died. 21. And Enoch lived sixty and five years, and begat Methuselah: 22. And Enoch walked with God after he begat Methuselah three hundred years, and begat sons and daughters: 23. And all the days of Enoch were three hundred sixty and five years: 24. And Enoch walked with God: and he was not; for God took him. 25. And Methuselah lived an hundred eighty and seven years, and begat Lamech. 26. And Methuselah lived after he begat Lamech seven hundred eighty and two years, and begat sons and daughters: 27. And all the days of Methuselah were nine hundred sixty and nine years: and he died. 28. And Lamech lived an hundred eighty and two years, and begat a son: 29. And he called his name Noah, saying, This same shall comfort us concerning our work and toil of our hands, because of the ground which the LORD hath cursed. 30. And Lamech lived after he begat Noah five hundred ninety and five years, and begat sons and daughters: 31. And all the days of Lamech were seven hundred seventy and seven years: and he died. 32. And Noah was five hundred years old: and Noah begat Shem, Ham, and Japheth. And buffers begat buffers, and links begat links, and buffer pools begat links to chains of buffer pools containing buffers, and lo the buffers and links and pools of buffers and pools of links to chains of pools of buffers were fruitful and they multiplied and the Operating System looked down upon them and said that it was Good. INTRODUCTION ============ BGET is a comprehensive memory allocation package which is easily configured to the needs of an application. BGET is efficient in both the time needed to allocate and release buffers and in the memory overhead required for buffer pool management. It automatically consolidates contiguous space to minimise fragmentation. BGET is configured by compile-time definitions, Major options include: * A built-in test program to exercise BGET and demonstrate how the various functions are used. * Allocation by either the "first fit" or "best fit" method. * Wiping buffers at release time to catch code which references previously released storage. * Built-in routines to dump individual buffers or the entire buffer pool. * Retrieval of allocation and pool size statistics. * Quantisation of buffer sizes to a power of two to satisfy hardware alignment constraints. * Automatic pool compaction, growth, and shrinkage by means of call-backs to user defined functions. Applications of BGET can range from storage management in ROM-based embedded programs to providing the framework upon which a multitasking system incorporating garbage collection is constructed. BGET incorporates extensive internal consistency checking using the mechanism; all these checks can be turned off by compiling with NDEBUG defined, yielding a version of BGET with minimal size and maximum speed. The basic algorithm underlying BGET has withstood the test of time; more than 25 years have passed since the first implementation of this code. And yet, it is substantially more efficient than the native allocation schemes of many operating systems: the Macintosh and Microsoft Windows to name two, on which programs have obtained substantial speed-ups by layering BGET as an application level memory manager atop the underlying system's. BGET has been implemented on the largest mainframes and the lowest of microprocessors. It has served as the core for multitasking operating systems, multi-thread applications, embedded software in data network switching processors, and a host of C programs. And while it has accreted flexibility and additional options over the years, it remains fast, memory efficient, portable, and easy to integrate into your program. BGET IMPLEMENTATION ASSUMPTIONS =============================== BGET is written in as portable a dialect of C as possible. The only fundamental assumption about the underlying hardware architecture is that memory is allocated is a linear array which can be addressed as a vector of C "char" objects. On segmented address space architectures, this generally means that BGET should be used to allocate storage within a single segment (although some compilers simulate linear address spaces on segmented architectures). On segmented architectures, then, BGET buffer pools may not be larger than a segment, but since BGET allows any number of separate buffer pools, there is no limit on the total storage which can be managed, only on the largest individual object which can be allocated. Machines with a linear address architecture, such as the VAX, 680x0, Sparc, MIPS, or the Intel 80386 and above in native mode, may use BGET without restriction. GETTING STARTED WITH BGET ========================= Although BGET can be configured in a multitude of fashions, there are three basic ways of working with BGET. The functions mentioned below are documented in the following section. Please excuse the forward references which are made in the interest of providing a roadmap to guide you to the BGET functions you're likely to need. Embedded Applications --------------------- Embedded applications typically have a fixed area of memory dedicated to buffer allocation (often in a separate RAM address space distinct from the ROM that contains the executable code). To use BGET in such an environment, simply call bpool() with the start address and length of the buffer pool area in RAM, then allocate buffers with bget() and release them with brel(). Embedded applications with very limited RAM but abundant CPU speed may benefit by configuring BGET for BestFit allocation (which is usually not worth it in other environments). Malloc() Emulation ------------------ If the C library malloc() function is too slow, not present in your development environment (for example, an a native Windows or Macintosh program), or otherwise unsuitable, you can replace it with BGET. Initially define a buffer pool of an appropriate size with bpool()--usually obtained by making a call to the operating system's low-level memory allocator. Then allocate buffers with bget(), bgetz(), and bgetr() (the last two permit the allocation of buffers initialised to zero and [inefficient] re-allocation of existing buffers for compatibility with C library functions). Release buffers by calling brel(). If a buffer allocation request fails, obtain more storage from the underlying operating system, add it to the buffer pool by another call to bpool(), and continue execution. Automatic Storage Management ---------------------------- You can use BGET as your application's native memory manager and implement automatic storage pool expansion, contraction, and optionally application-specific memory compaction by compiling BGET with the BECtl variable defined, then calling bectl() and supplying functions for storage compaction, acquisition, and release, as well as a standard pool expansion increment. All of these functions are optional (although it doesn't make much sense to provide a release function without an acquisition function, does it?). Once the call-back functions have been defined with bectl(), you simply use bget() and brel() to allocate and release storage as before. You can supply an initial buffer pool with bpool() or rely on automatic allocation to acquire the entire pool. When a call on bget() cannot be satisfied, BGET first checks if a compaction function has been supplied. If so, it is called (with the space required to satisfy the allocation request and a sequence number to allow the compaction routine to be called successively without looping). If the compaction function is able to free any storage (it needn't know whether the storage it freed was adequate) it should return a nonzero value, whereupon BGET will retry the allocation request and, if it fails again, call the compaction function again with the next-higher sequence number. If the compaction function returns zero, indicating failure to free space, or no compaction function is defined, BGET next tests whether a non-NULL allocation function was supplied to bectl(). If so, that function is called with an argument indicating how many bytes of additional space are required. This will be the standard pool expansion increment supplied in the call to bectl() unless the original bget() call requested a buffer larger than this; buffers larger than the standard pool block can be managed "off the books" by BGET in this mode. If the allocation function succeeds in obtaining the storage, it returns a pointer to the new block and BGET expands the buffer pool; if it fails, the allocation request fails and returns NULL to the caller. If a non-NULL release function is supplied, expansion blocks which become totally empty are released to the global free pool by passing their addresses to the release function. Equipped with appropriate allocation, release, and compaction functions, BGET can be used as part of very sophisticated memory management strategies, including garbage collection. (Note, however, that BGET is *not* a garbage collector by itself, and that developing such a system requires much additional logic and careful design of the application's memory allocation strategy.) BGET FUNCTION DESCRIPTIONS ========================== Functions implemented in this file (some are enabled by certain of the optional settings below): void bpool(void *buffer, bufsize len); Create a buffer pool of bytes, using the storage starting at . You can call bpool() subsequently to contribute additional storage to the overall buffer pool. void *bget(bufsize size); Allocate a buffer of bytes. The address of the buffer is returned, or NULL if insufficient memory was available to allocate the buffer. void *bgetz(bufsize size); Allocate a buffer of bytes and clear it to all zeroes. The address of the buffer is returned, or NULL if insufficient memory was available to allocate the buffer. void *bgetr(void *buffer, bufsize newsize); Reallocate a buffer previously allocated by bget(), changing its size to and preserving all existing data. NULL is returned if insufficient memory is available to reallocate the buffer, in which case the original buffer remains intact. void brel(void *buf); Return the buffer , previously allocated by bget(), to the free space pool. void bectl(int (*compact)(bufsize sizereq, int sequence), void *(*acquire)(bufsize size), void (*release)(void *buf), bufsize pool_incr); Expansion control: specify functions through which the package may compact storage (or take other appropriate action) when an allocation request fails, and optionally automatically acquire storage for expansion blocks when necessary, and release such blocks when they become empty. If is non-NULL, whenever a buffer allocation request fails, the function will be called with arguments specifying the number of bytes (total buffer size, including header overhead) required to satisfy the allocation request, and a sequence number indicating the number of consecutive calls on attempting to satisfy this allocation request. The sequence number is 1 for the first call on for a given allocation request, and increments on subsequent calls, permitting the function to take increasingly dire measures in an attempt to free up storage. If the function returns a nonzero value, the allocation attempt is re-tried. If returns 0 (as it must if it isn't able to release any space or add storage to the buffer pool), the allocation request fails, which can trigger automatic pool expansion if the argument is non-NULL. At the time the function is called, the state of the buffer allocator is identical to that at the moment the allocation request was made; consequently, the function may call brel(), bpool(), bstats(), and/or directly manipulate the buffer pool in any manner which would be valid were the application in control. This does not, however, relieve the function of the need to ensure that whatever actions it takes do not change things underneath the application that made the allocation request. For example, a function that released a buffer in the process of being reallocated with bgetr() would lead to disaster. Implementing a safe and effective mechanism requires careful design of an application's memory architecture, and cannot generally be easily retrofitted into existing code. If is non-NULL, that function will be called whenever an allocation request fails. If the function succeeds in allocating the requested space and returns a pointer to the new area, allocation will proceed using the expanded buffer pool. If cannot obtain the requested space, it should return NULL and the entire allocation process will fail. specifies the normal expansion block size. Providing an function will cause subsequent bget() requests for buffers too large to be managed in the linked-block scheme (in other words, larger than minus the buffer overhead) to be satisfied directly by calls to the function. Automatic release of empty pool blocks will occur only if all pool blocks in the system are the size given by . void bstats(bufsize *curalloc, bufsize *totfree, bufsize *maxfree, long *nget, long *nrel); The amount of space currently allocated is stored into the variable pointed to by . The total free space (sum of all free blocks in the pool) is stored into the variable pointed to by , and the size of the largest single block in the free space pool is stored into the variable pointed to by . The variables pointed to by and are filled, respectively, with the number of successful (non-NULL return) bget() calls and the number of brel() calls. void bstatse(bufsize *pool_incr, long *npool, long *npget, long *nprel, long *ndget, long *ndrel); Extended statistics: The expansion block size will be stored into the variable pointed to by , or the negative thereof if automatic expansion block releases are disabled. The number of currently active pool blocks will be stored into the variable pointed to by . The variables pointed to by and will be filled with, respectively, the number of expansion block acquisitions and releases which have occurred. The variables pointed to by and will be filled with the number of bget() and brel() calls, respectively, managed through blocks directly allocated by the acquisition and release functions. void bufdump(void *buf); The buffer pointed to by is dumped on standard output. void bpoold(void *pool, int dumpalloc, int dumpfree); All buffers in the buffer pool , previously initialised by a call on bpool(), are listed in ascending memory address order. If is nonzero, the contents of allocated buffers are dumped; if is nonzero, the contents of free blocks are dumped. int bpoolv(void *pool); The named buffer pool, previously initialised by a call on bpool(), is validated for bad pointers, overwritten data, etc. If compiled with NDEBUG not defined, any error generates an assertion failure. Otherwise 1 is returned if the pool is valid, 0 if an error is found. BGET CONFIGURATION ================== */ /* * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* #define BGET_ENABLE_ALL_OPTIONS */ #ifdef BGET_ENABLE_OPTION #define TestProg 20000 /* Generate built-in test program if defined. The value specifies how many buffer allocation attempts the test program should make. */ #define SizeQuant 4 /* Buffer allocation size quantum: all buffers allocated are a multiple of this size. This MUST be a power of two. */ #define BufDump 1 /* Define this symbol to enable the bpoold() function which dumps the buffers in a buffer pool. */ #define BufValid 1 /* Define this symbol to enable the bpoolv() function for validating a buffer pool. */ #define DumpData 1 /* Define this symbol to enable the bufdump() function which allows dumping the contents of an allocated or free buffer. */ #define BufStats 1 /* Define this symbol to enable the bstats() function which calculates the total free space in the buffer pool, the largest available buffer, and the total space currently allocated. */ #define FreeWipe 1 /* Wipe free buffers to a guaranteed pattern of garbage to trip up miscreants who attempt to use pointers into released buffers. */ #define BestFit 1 /* Use a best fit algorithm when searching for space for an allocation request. This uses memory more efficiently, but allocation will be much slower. */ #define BECtl 1 /* Define this symbol to enable the bectl() function for automatic pool space control. */ #endif #include #include #ifdef lint #define NDEBUG /* Exits in asserts confuse lint */ /* LINTLIBRARY */ /* Don't complain about def, no ref */ extern char *sprintf(); /* Sun includes don't define sprintf */ #endif #include #include #ifdef BufDump /* BufDump implies DumpData */ #ifndef DumpData #define DumpData 1 #endif #endif #ifdef DumpData #include #endif #ifdef __KERNEL__ #ifdef CFG_CORE_BGET_BESTFIT #define BestFit 1 #endif #endif /* Declare the interface, including the requested buffer size type, bufsize. */ #include "bget.h" #define MemSize int /* Type for size arguments to memxxx() functions such as memcmp(). */ /* Queue links */ struct qlinks { struct bfhead *flink; /* Forward link */ struct bfhead *blink; /* Backward link */ }; /* Header in allocated and free buffers */ struct bhead { bufsize prevfree; /* Relative link back to previous free buffer in memory or 0 if previous buffer is allocated. */ bufsize bsize; /* Buffer size: positive if free, negative if allocated. */ }; #define BH(p) ((struct bhead *) (p)) /* Header in directly allocated buffers (by acqfcn) */ struct bdhead { bufsize tsize; /* Total size, including overhead */ bufsize offs; /* Offset from allocated buffer */ struct bhead bh; /* Common header */ }; #define BDH(p) ((struct bdhead *) (p)) /* Header in free buffers */ struct bfhead { struct bhead bh; /* Common allocated/free header */ struct qlinks ql; /* Links on free list */ }; #define BFH(p) ((struct bfhead *) (p)) /* Poolset definition */ struct bpoolset { struct bfhead freelist; #ifdef BufStats bufsize totalloc; /* Total space currently allocated */ long numget; /* Number of bget() calls */ long numrel; /* Number of brel() calls */ #ifdef BECtl long numpblk; /* Number of pool blocks */ long numpget; /* Number of block gets and rels */ long numprel; long numdget; /* Number of direct gets and rels */ long numdrel; #endif /* BECtl */ #endif /* BufStats */ #ifdef BECtl /* Automatic expansion block management functions */ int (*compfcn) _((bufsize sizereq, int sequence)); void *(*acqfcn) _((bufsize size)); void (*relfcn) _((void *buf)); bufsize exp_incr; /* Expansion block size */ bufsize pool_len; /* 0: no bpool calls have been made -1: not all pool blocks are the same size >0: (common) block size for all bpool calls made so far */ #endif }; /* Minimum allocation quantum: */ #define QLSize (sizeof(struct qlinks)) #define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize) #define V (void) /* To denote unwanted returned values */ /* End sentinel: value placed in bsize field of dummy block delimiting end of pool block. The most negative number which will fit in a bufsize, defined in a way that the compiler will accept. */ #define ESent ((bufsize) (-(((1L << (sizeof(bufsize) * 8 - 2)) - 1) * 2) - 2)) static bufsize buf_get_pos(struct bfhead *bf, bufsize align, bufsize hdr_size, bufsize size) { unsigned long buf = 0; bufsize pos = 0; if (bf->bh.bsize < size) return -1; /* * plus sizeof(struct bhead) and hdr_size since buf will follow just * after a struct bhead and an eventual extra header. */ buf = (unsigned long)bf + bf->bh.bsize - size + sizeof(struct bhead) + hdr_size; buf &= ~(align - 1); pos = buf - (unsigned long)bf - sizeof(struct bhead) - hdr_size; if (pos == 0) /* exact match */ return pos; if (pos >= SizeQ + sizeof(struct bhead)) /* room for an empty buffer */ return pos; return -1; } /* BGET -- Allocate a buffer. */ void *bget(requested_align, hdr_size, requested_size, poolset) bufsize requested_align; bufsize hdr_size; bufsize requested_size; struct bpoolset *poolset; { bufsize align = requested_align; bufsize size = requested_size; bufsize pos; struct bfhead *b; #ifdef BestFit struct bfhead *best; #endif void *buf; #ifdef BECtl int compactseq = 0; #endif assert(size > 0); COMPILE_TIME_ASSERT(BGET_HDR_QUANTUM == SizeQ); if (align < 0 || (align > 0 && !IS_POWER_OF_TWO((unsigned long)align))) return NULL; if (hdr_size % BGET_HDR_QUANTUM != 0) return NULL; if (size < SizeQ) { /* Need at least room for the */ size = SizeQ; /* queue links. */ } if (align < SizeQ) align = SizeQ; #ifdef SizeQuant #if SizeQuant > 1 if (ADD_OVERFLOW(size, SizeQuant - 1, &size)) return NULL; size = ROUNDDOWN(size, SizeQuant); #endif #endif /* Add overhead in allocated buffer to size required. */ if (ADD_OVERFLOW(size, sizeof(struct bhead), &size)) return NULL; if (ADD_OVERFLOW(size, hdr_size, &size)) return NULL; #ifdef BECtl /* If a compact function was provided in the call to bectl(), wrap a loop around the allocation process to allow compaction to intervene in case we don't find a suitable buffer in the chain. */ while (1) { #endif b = poolset->freelist.ql.flink; #ifdef BestFit best = &poolset->freelist; #endif /* Scan the free list searching for the first buffer big enough to hold the requested size buffer. */ #ifdef BestFit while (b != &poolset->freelist) { assert(b->bh.prevfree == 0); pos = buf_get_pos(b, align, hdr_size, size); if (pos >= 0) { if ((best == &poolset->freelist) || (b->bh.bsize < best->bh.bsize)) { best = b; } } b = b->ql.flink; /* Link to next buffer */ } b = best; #endif /* BestFit */ while (b != &poolset->freelist) { pos = buf_get_pos(b, align, hdr_size, size); if (pos >= 0) { struct bhead *b_alloc = BH((char *)b + pos); struct bhead *b_next = BH((char *)b + b->bh.bsize); assert(b_next->prevfree == b->bh.bsize); /* * Zero the back pointer in the next buffer in memory * to indicate that this buffer is allocated. */ b_next->prevfree = 0; assert(b->ql.blink->ql.flink == b); assert(b->ql.flink->ql.blink == b); if (pos == 0) { /* * Need to allocate from the beginning of this free block. * Unlink the block and mark it as allocated. */ b->ql.blink->ql.flink = b->ql.flink; b->ql.flink->ql.blink = b->ql.blink; /* Negate size to mark buffer allocated. */ b->bh.bsize = -b->bh.bsize; } else { /* * Carve out the memory allocation from the end of this * free block. Negative size to mark buffer allocated. */ b_alloc->bsize = -(b->bh.bsize - pos); b_alloc->prevfree = pos; b->bh.bsize = pos; } assert(b_alloc->bsize < 0); /* * At this point is b_alloc pointing to the allocated * buffer and b_next at the buffer following. b might be a * free block or a used block now. */ if (-b_alloc->bsize - size > SizeQ + sizeof(struct bhead)) { /* * b_alloc has too much unused memory at the * end we need to split the block and register that * last part as free. */ b = BFH((char *)b_alloc + size); b->bh.bsize = -b_alloc->bsize - size; b->bh.prevfree = 0; b_alloc->bsize += b->bh.bsize; assert(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); b->ql.flink = &poolset->freelist; b->ql.blink = poolset->freelist.ql.blink; poolset->freelist.ql.blink = b; b->ql.blink->ql.flink = b; assert(BH((char *)b + b->bh.bsize) == b_next); b_next->prevfree = b->bh.bsize; } #ifdef BufStats poolset->totalloc -= b_alloc->bsize; poolset->numget++; /* Increment number of bget() calls */ #endif buf = (char *)b_alloc + sizeof(struct bhead); return buf; } b = b->ql.flink; /* Link to next buffer */ } #ifdef BECtl /* We failed to find a buffer. If there's a compact function defined, notify it of the size requested. If it returns TRUE, try the allocation again. */ if ((poolset->compfcn == NULL) || (!(poolset->compfcn)(size, ++compactseq))) { break; } } /* No buffer available with requested size free. */ /* Don't give up yet -- look in the reserve supply. */ if (poolset->acqfcn != NULL) { if (size > exp_incr - sizeof(struct bfhead) - align) { /* Request is too large to fit in a single expansion block. Try to satisy it by a direct buffer acquisition. */ char *p; size += sizeof(struct bdhead) - sizeof(struct bhead); if (align > QLSize) size += align; p = poolset->acqfcn(size); if (p != NULL) { struct bdhead *bdh; if (align <= QLSize) { bdh = BDH(p); buf = bdh + 1; } else { unsigned long tp = (unsigned long)p; tp += sizeof(*bdh) + hdr_size + align; tp &= ~(align - 1); tp -= hdr_size; buf = (void *)tp; bdh = BDH((char *)buf - sizeof(*bdh)); } /* Mark the buffer special by setting the size field of its header to zero. */ bdh->bh.bsize = 0; bdh->bh.prevfree = 0; bdh->tsize = size; bdh->offs = (unsigned long)bdh - (unsigned long)p; #ifdef BufStats poolset->totalloc += size; poolset->numget++; /* Increment number of bget() calls */ poolset->numdget++; /* Direct bget() call count */ #endif return buf; } } else { /* Try to obtain a new expansion block */ void *newpool; if ((newpool = poolset->acqfcn((bufsize) exp_incr)) != NULL) { bpool(newpool, exp_incr, poolset); buf = bget(align, hdr_size, requested_size, pool); /* This can't, I say, can't get into a loop. */ return buf; } } } /* Still no buffer available */ #endif /* BECtl */ return NULL; } /* BGETZ -- Allocate a buffer and clear its contents to zero. We clear the entire contents of the buffer to zero, not just the region requested by the caller. */ void *bgetz(align, hdr_size, size, poolset) bufsize align; bufsize hdr_size; bufsize size; struct bpoolset *poolset; { char *buf = (char *) bget(align, hdr_size, size, poolset); if (buf != NULL) { struct bhead *b; bufsize rsize; b = BH(buf - sizeof(struct bhead)); rsize = -(b->bsize); if (rsize == 0) { struct bdhead *bd; bd = BDH(buf - sizeof(struct bdhead)); rsize = bd->tsize - sizeof(struct bdhead) - bd->offs; } else { rsize -= sizeof(struct bhead); } assert(rsize >= size); V memset_unchecked(buf, 0, (MemSize) rsize); } return ((void *) buf); } /* BGETR -- Reallocate a buffer. This is a minimal implementation, simply in terms of brel() and bget(). It could be enhanced to allow the buffer to grow into adjacent free blocks and to avoid moving data unnecessarily. */ void *bgetr(buf, align, hdr_size, size, poolset) void *buf; bufsize align; bufsize hdr_size; bufsize size; struct bpoolset *poolset; { void *nbuf; bufsize osize; /* Old size of buffer */ struct bhead *b; if ((nbuf = bget(align, hdr_size, size, poolset)) == NULL) { /* Acquire new buffer */ return NULL; } if (buf == NULL) { return nbuf; } b = BH(((char *) buf) - sizeof(struct bhead)); osize = -b->bsize; #ifdef BECtl if (osize == 0) { /* Buffer acquired directly through acqfcn. */ struct bdhead *bd; bd = BDH(((char *) buf) - sizeof(struct bdhead)); osize = bd->tsize - sizeof(struct bdhead) - bd->offs; } else #endif osize -= sizeof(struct bhead); assert(osize > 0); V memcpy_unchecked((char *) nbuf, (char *) buf, /* Copy the data */ (MemSize) ((size < osize) ? size : osize)); #ifndef __KERNEL__ /* User space reallocations are always zeroed */ if (size > osize) V memset_unchecked((char *) nbuf + osize, 0, size - osize); #endif brel(buf, poolset, false /* !wipe */); return nbuf; } /* BREL -- Release a buffer. */ void brel(buf, poolset, wipe) void *buf; struct bpoolset *poolset; int wipe; { struct bfhead *b, *bn; char *wipe_start; bufsize wipe_size; b = BFH(((char *) buf) - sizeof(struct bhead)); #ifdef BufStats poolset->numrel++; /* Increment number of brel() calls */ #endif assert(buf != NULL); #ifdef FreeWipe wipe = true; #endif #ifdef BECtl if (b->bh.bsize == 0) { /* Directly-acquired buffer? */ struct bdhead *bdh; bdh = BDH(((char *) buf) - sizeof(struct bdhead)); assert(b->bh.prevfree == 0); #ifdef BufStats poolset->totalloc -= bdh->tsize; assert(poolset->totalloc >= 0); poolset->numdrel++; /* Number of direct releases */ #endif /* BufStats */ if (wipe) { V memset_unchecked((char *) buf, 0x55, (MemSize) (bdh->tsize - sizeof(struct bdhead))); } assert(poolset->relfcn != NULL); poolset->relfcn((char *)buf - sizeof(struct bdhead) - bdh->offs); /* Release it directly. */ return; } #endif /* BECtl */ /* Buffer size must be negative, indicating that the buffer is allocated. */ if (b->bh.bsize >= 0) { bn = NULL; } assert(b->bh.bsize < 0); /* Back pointer in next buffer must be zero, indicating the same thing: */ assert(BH((char *) b - b->bh.bsize)->prevfree == 0); #ifdef BufStats poolset->totalloc += b->bh.bsize; assert(poolset->totalloc >= 0); #endif /* If the back link is nonzero, the previous buffer is free. */ if (b->bh.prevfree != 0) { /* The previous buffer is free. Consolidate this buffer with it by adding the length of this buffer to the previous free buffer. Note that we subtract the size in the buffer being released, since it's negative to indicate that the buffer is allocated. */ register bufsize size = b->bh.bsize; /* Only wipe the current buffer, including bfhead. */ wipe_start = (char *)b; wipe_size = -size; /* Make the previous buffer the one we're working on. */ assert(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree); b = BFH(((char *) b) - b->bh.prevfree); b->bh.bsize -= size; } else { /* The previous buffer isn't allocated. Insert this buffer on the free list as an isolated free block. */ assert(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); b->ql.flink = &poolset->freelist; b->ql.blink = poolset->freelist.ql.blink; poolset->freelist.ql.blink = b; b->ql.blink->ql.flink = b; b->bh.bsize = -b->bh.bsize; wipe_start = (char *)b + sizeof(struct bfhead); wipe_size = b->bh.bsize - sizeof(struct bfhead); } /* Now we look at the next buffer in memory, located by advancing from the start of this buffer by its size, to see if that buffer is free. If it is, we combine this buffer with the next one in memory, dechaining the second buffer from the free list. */ bn = BFH(((char *) b) + b->bh.bsize); if (bn->bh.bsize > 0) { /* The buffer is free. Remove it from the free list and add its size to that of our buffer. */ assert(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize); assert(bn->ql.blink->ql.flink == bn); assert(bn->ql.flink->ql.blink == bn); bn->ql.blink->ql.flink = bn->ql.flink; bn->ql.flink->ql.blink = bn->ql.blink; b->bh.bsize += bn->bh.bsize; /* Finally, advance to the buffer that follows the newly consolidated free block. We must set its backpointer to the head of the consolidated free block. We know the next block must be an allocated block because the process of recombination guarantees that two free blocks will never be contiguous in memory. */ bn = BFH(((char *) b) + b->bh.bsize); /* Only bfhead of next buffer needs to be wiped */ wipe_size += sizeof(struct bfhead); } if (wipe) { V memset_unchecked(wipe_start, 0x55, wipe_size); } assert(bn->bh.bsize < 0); /* The next buffer is allocated. Set the backpointer in it to point to this buffer; the previous free buffer in memory. */ bn->bh.prevfree = b->bh.bsize; #ifdef BECtl /* If a block-release function is defined, and this free buffer constitutes the entire block, release it. Note that pool_len is defined in such a way that the test will fail unless all pool blocks are the same size. */ if (poolset->relfcn != NULL && ((bufsize) b->bh.bsize) == (pool_len - sizeof(struct bhead))) { assert(b->bh.prevfree == 0); assert(BH((char *) b + b->bh.bsize)->bsize == ESent); assert(BH((char *) b + b->bh.bsize)->prevfree == b->bh.bsize); /* Unlink the buffer from the free list */ b->ql.blink->ql.flink = b->ql.flink; b->ql.flink->ql.blink = b->ql.blink; poolset->relfcn(b); #ifdef BufStats poolset->numprel++; /* Nr of expansion block releases */ poolset->numpblk--; /* Total number of blocks */ assert(numpblk == numpget - numprel); #endif /* BufStats */ } #endif /* BECtl */ } #ifdef BECtl /* BECTL -- Establish automatic pool expansion control */ void bectl(compact, acquire, release, pool_incr, poolset) int (*compact) _((bufsize sizereq, int sequence)); void *(*acquire) _((bufsize size)); void (*release) _((void *buf)); bufsize pool_incr; struct bpoolset *poolset; { poolset->compfcn = compact; poolset->acqfcn = acquire; poolset->relfcn = release; poolset->exp_incr = pool_incr; } #endif /* BPOOL -- Add a region of memory to the buffer pool. */ void bpool(buf, len, poolset) void *buf; bufsize len; struct bpoolset *poolset; { struct bfhead *b = BFH(buf); struct bhead *bn; #ifdef SizeQuant len &= ~(SizeQuant - 1); #endif #ifdef BECtl if (poolset->pool_len == 0) { pool_len = len; } else if (len != poolset->pool_len) { poolset->pool_len = -1; } #ifdef BufStats poolset->numpget++; /* Number of block acquisitions */ poolset->numpblk++; /* Number of blocks total */ assert(poolset->numpblk == poolset->numpget - poolset->numprel); #endif /* BufStats */ #endif /* BECtl */ /* Since the block is initially occupied by a single free buffer, it had better not be (much) larger than the largest buffer whose size we can store in bhead.bsize. */ assert(len - sizeof(struct bhead) <= -((bufsize) ESent + 1)); /* Clear the backpointer at the start of the block to indicate that there is no free block prior to this one. That blocks recombination when the first block in memory is released. */ b->bh.prevfree = 0; /* Chain the new block to the free list. */ assert(poolset->freelist.ql.blink->ql.flink == &poolset->freelist); assert(poolset->freelist.ql.flink->ql.blink == &poolset->freelist); b->ql.flink = &poolset->freelist; b->ql.blink = poolset->freelist.ql.blink; poolset->freelist.ql.blink = b; b->ql.blink->ql.flink = b; /* Create a dummy allocated buffer at the end of the pool. This dummy buffer is seen when a buffer at the end of the pool is released and blocks recombination of the last buffer with the dummy buffer at the end. The length in the dummy buffer is set to the largest negative number to denote the end of the pool for diagnostic routines (this specific value is not counted on by the actual allocation and release functions). */ len -= sizeof(struct bhead); b->bh.bsize = (bufsize) len; #ifdef FreeWipe V memset_unchecked(((char *) b) + sizeof(struct bfhead), 0x55, (MemSize) (len - sizeof(struct bfhead))); #endif bn = BH(((char *) b) + len); bn->prevfree = (bufsize) len; /* Definition of ESent assumes two's complement! */ assert((~0) == -1); bn->bsize = ESent; } #ifdef BufStats /* BSTATS -- Return buffer allocation free space statistics. */ void bstats(curalloc, totfree, maxfree, nget, nrel, poolset) bufsize *curalloc, *totfree, *maxfree; long *nget, *nrel; struct bpoolset *poolset; { struct bfhead *b = poolset->freelist.ql.flink; *nget = poolset->numget; *nrel = poolset->numrel; *curalloc = poolset->totalloc; *totfree = 0; *maxfree = -1; while (b != &poolset->freelist) { assert(b->bh.bsize > 0); *totfree += b->bh.bsize; if (b->bh.bsize > *maxfree) { *maxfree = b->bh.bsize; } b = b->ql.flink; /* Link to next buffer */ } } #ifdef BECtl /* BSTATSE -- Return extended statistics */ void bstatse(pool_incr, npool, npget, nprel, ndget, ndrel, poolset) bufsize *pool_incr; long *npool, *npget, *nprel, *ndget, *ndrel; struct bpoolset *poolset; { *pool_incr = (poolset->pool_len < 0) ? -poolset->exp_incr : poolset->exp_incr; *npool = poolset->numpblk; *npget = poolset->numpget; *nprel = poolset->numprel; *ndget = poolset->numdget; *ndrel = poolset->numdrel; } #endif /* BECtl */ #endif /* BufStats */ #ifdef DumpData /* BUFDUMP -- Dump the data in a buffer. This is called with the user data pointer, and backs up to the buffer header. It will dump either a free block or an allocated one. */ void bufdump(buf) void *buf; { struct bfhead *b; unsigned char *bdump; bufsize bdlen; b = BFH(((char *) buf) - sizeof(struct bhead)); assert(b->bh.bsize != 0); if (b->bh.bsize < 0) { bdump = (unsigned char *) buf; bdlen = (-b->bh.bsize) - sizeof(struct bhead); } else { bdump = (unsigned char *) (((char *) b) + sizeof(struct bfhead)); bdlen = b->bh.bsize - sizeof(struct bfhead); } while (bdlen > 0) { int i, dupes = 0; bufsize l = bdlen; char bhex[50], bascii[20]; if (l > 16) { l = 16; } for (i = 0; i < l; i++) { V snprintf(bhex + i * 3, sizeof(bhex) - i * 3, "%02X ", bdump[i]); bascii[i] = isprint(bdump[i]) ? bdump[i] : ' '; } bascii[i] = 0; V printf("%-48s %s\n", bhex, bascii); bdump += l; bdlen -= l; while ((bdlen > 16) && (memcmp((char *) (bdump - 16), (char *) bdump, 16) == 0)) { dupes++; bdump += 16; bdlen -= 16; } if (dupes > 1) { V printf( " (%d lines [%d bytes] identical to above line skipped)\n", dupes, dupes * 16); } else if (dupes == 1) { bdump -= 16; bdlen += 16; } } } #endif #ifdef BufDump /* BPOOLD -- Dump a buffer pool. The buffer headers are always listed. If DUMPALLOC is nonzero, the contents of allocated buffers are dumped. If DUMPFREE is nonzero, free blocks are dumped as well. If FreeWipe checking is enabled, free blocks which have been clobbered will always be dumped. */ void bpoold(buf, dumpalloc, dumpfree) void *buf; int dumpalloc, dumpfree; { struct bfhead *b = BFH(buf); while (b->bh.bsize != ESent) { bufsize bs = b->bh.bsize; if (bs < 0) { bs = -bs; V printf("Allocated buffer: size %6ld bytes.\n", (long) bs); if (dumpalloc) { bufdump((void *) (((char *) b) + sizeof(struct bhead))); } } else { char *lerr = ""; assert(bs > 0); if ((b->ql.blink->ql.flink != b) || (b->ql.flink->ql.blink != b)) { lerr = " (Bad free list links)"; } V printf("Free block: size %6ld bytes.%s\n", (long) bs, lerr); #ifdef FreeWipe lerr = ((char *) b) + sizeof(struct bfhead); if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) || (memcmp(lerr, lerr + 1, (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) { V printf( "(Contents of above free block have been overstored.)\n"); bufdump((void *) (((char *) b) + sizeof(struct bhead))); } else #endif if (dumpfree) { bufdump((void *) (((char *) b) + sizeof(struct bhead))); } } b = BFH(((char *) b) + bs); } } #endif /* BufDump */ #ifdef BufValid /* BPOOLV -- Validate a buffer pool. If NDEBUG isn't defined, any error generates an assertion failure. */ int bpoolv(buf) void *buf; { struct bfhead *b = BFH(buf); while (b->bh.bsize != ESent) { bufsize bs = b->bh.bsize; if (bs < 0) { bs = -bs; } else { const char *lerr = ""; assert(bs > 0); if (bs <= 0) { return 0; } if ((b->ql.blink->ql.flink != b) || (b->ql.flink->ql.blink != b)) { V printf("Free block: size %6ld bytes. (Bad free list links)\n", (long) bs); assert(0); return 0; } #ifdef FreeWipe lerr = ((char *) b) + sizeof(struct bfhead); if ((bs > sizeof(struct bfhead)) && ((*lerr != 0x55) || (memcmp(lerr, lerr + 1, (MemSize) (bs - (sizeof(struct bfhead) + 1))) != 0))) { V printf( "(Contents of above free block have been overstored.)\n"); bufdump((void *) (((char *) b) + sizeof(struct bhead))); assert(0); return 0; } #endif } b = BFH(((char *) b) + bs); } return 1; } #endif /* BufValid */ /***********************\ * * * Built-in test program * * * \***********************/ #if !defined(__KERNEL__) && !defined(__LDELF__) && defined(CFG_TA_BGET_TEST) #define TestProg 20000 #ifdef BECtl #define PoolSize 300000 /* Test buffer pool size */ #else #define PoolSize 50000 /* Test buffer pool size */ #endif #define ExpIncr 32768 /* Test expansion block size */ #define CompactTries 10 /* Maximum tries at compacting */ #define dumpAlloc 0 /* Dump allocated buffers ? */ #define dumpFree 0 /* Dump free buffers ? */ static char *bchain = NULL; /* Our private buffer chain */ static char *bp = NULL; /* Our initial buffer pool */ #ifdef UsingFloat #include #endif static unsigned long int next = 1; static void *(*mymalloc)(size_t size); static void (*myfree)(void *ptr); static struct bpoolset mypoolset = { .freelist = { .bh = { 0, 0}, .ql = { &mypoolset.freelist, &mypoolset.freelist}, } }; /* Return next random integer */ static int myrand(void) { next = next * 1103515245L + 12345; return (unsigned int) (next / 65536L) % 32768L; } /* Set seed for random generator */ static void mysrand(unsigned int seed) { next = seed; } /* STATS -- Edit statistics returned by bstats() or bstatse(). */ static void stats(const char *when __maybe_unused, struct bpoolset *poolset __maybe_unused) { #ifdef BufStats bufsize cural, totfree, maxfree; long nget, nfree; #endif #ifdef BECtl bufsize pincr; long totblocks, npget, nprel, ndget, ndrel; #endif #ifdef BufStats bstats(&cural, &totfree, &maxfree, &nget, &nfree, poolset); V printf( "%s: %ld gets, %ld releases. %ld in use, %ld free, largest = %ld\n", when, nget, nfree, (long) cural, (long) totfree, (long) maxfree); #endif #ifdef BECtl bstatse(&pincr, &totblocks, &npget, &nprel, &ndget, &ndrel, poolset); V printf( " Blocks: size = %ld, %ld (%ld bytes) in use, %ld gets, %ld frees\n", (long)pincr, totblocks, pincr * totblocks, npget, nprel); V printf(" %ld direct gets, %ld direct frees\n", ndget, ndrel); #endif /* BECtl */ } #ifdef BECtl static int protect = 0; /* Disable compaction during bgetr() */ /* BCOMPACT -- Compaction call-back function. */ static int bcompact(bsize, seq) bufsize bsize; int seq; { #ifdef CompactTries char *bc = bchain; int i = myrand() & 0x3; #ifdef COMPACTRACE V printf("Compaction requested. %ld bytes needed, sequence %d.\n", (long) bsize, seq); #endif if (protect || (seq > CompactTries)) { #ifdef COMPACTRACE V printf("Compaction gave up.\n"); #endif return 0; } /* Based on a random cast, release a random buffer in the list of allocated buffers. */ while (i > 0 && bc != NULL) { bc = *((char **) bc); i--; } if (bc != NULL) { char *fb; fb = *((char **) bc); if (fb != NULL) { *((char **) bc) = *((char **) fb); brel((void *) fb); return 1; } } #ifdef COMPACTRACE V printf("Compaction bailed out.\n"); #endif #endif /* CompactTries */ return 0; } /* BEXPAND -- Expand pool call-back function. */ static void *bexpand(size) bufsize size; { void *np = NULL; bufsize cural, totfree, maxfree; long nget, nfree; /* Don't expand beyond the total allocated size given by PoolSize. */ bstats(&cural, &totfree, &maxfree, &nget, &nfree); if (cural < PoolSize) { np = (void *) mymalloc((unsigned) size); } #ifdef EXPTRACE V printf("Expand pool by %ld -- %s.\n", (long) size, np == NULL ? "failed" : "succeeded"); #endif return np; } /* BSHRINK -- Shrink buffer pool call-back function. */ static void bshrink(buf) void *buf; { if (((char *) buf) == bp) { #ifdef EXPTRACE V printf("Initial pool released.\n"); #endif bp = NULL; } #ifdef EXPTRACE V printf("Shrink pool.\n"); #endif myfree((char *) buf); } #endif /* BECtl */ /* Restrict buffer requests to those large enough to contain our pointer and small enough for the CPU architecture. */ static bufsize blimit(bufsize bs) { if (bs < sizeof(char *)) { bs = sizeof(char *); } /* This is written out in this ugly fashion because the cool expression in sizeof(int) that auto-configured to any length int befuddled some compilers. */ if (sizeof(int) == 2) { if (bs > 32767) { bs = 32767; } } else { if (bs > 200000) { bs = 200000; } } return bs; } int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *)) { int i; #ifdef UsingFloat double x; #endif mymalloc = malloc_func; myfree = free_func; /* Seed the random number generator. If Repeatable is defined, we always use the same seed. Otherwise, we seed from the clock to shake things up from run to run. */ mysrand(1234); /* Compute x such that pow(x, p) ranges between 1 and 4*ExpIncr as p ranges from 0 to ExpIncr-1, with a concentration in the lower numbers. */ #ifdef UsingFloat x = 4.0 * ExpIncr; x = log(x); x = exp(log(4.0 * ExpIncr) / (ExpIncr - 1.0)); #endif #ifdef BECtl bectl(bcompact, bexpand, bshrink, (bufsize) ExpIncr, &mypoolset); bp = mymalloc(ExpIncr); assert(bp != NULL); bpool((void *) bp, (bufsize) ExpIncr); #else bp = mymalloc(PoolSize); assert(bp != NULL); bpool((void *) bp, (bufsize) PoolSize, &mypoolset); #endif stats("Create pool", &mypoolset); #ifdef BufValid V bpoolv((void *) bp); #endif #ifdef BufDump bpoold((void *) bp, dumpAlloc, dumpFree); #endif for (i = 0; i < TestProg; i++) { char *cb; #ifdef UsingFloat bufsize bs = pow(x, (double) (myrand() & (ExpIncr - 1))); #else bufsize bs = (myrand() & (ExpIncr * 4 - 1)) / (1 << (myrand() & 0x7)); #endif bufsize align = 0; bufsize hdr_size = 0; switch (rand() & 0x3) { case 1: align = 32; break; case 2: align = 64; break; case 3: align = 128; break; default: break; } hdr_size = (rand() & 0x3) * BGET_HDR_QUANTUM; assert(bs <= (((bufsize) 4) * ExpIncr)); bs = blimit(bs); if (myrand() & 0x400) { cb = (char *) bgetz(align, hdr_size, bs, &mypoolset); } else { cb = (char *) bget(align, hdr_size, bs, &mypoolset); } if (cb == NULL) { #ifdef EasyOut break; #else char *bc = bchain; if (bc != NULL) { char *fb; fb = *((char **) bc); if (fb != NULL) { *((char **) bc) = *((char **) fb); brel((void *) fb, &mypoolset, true/*wipe*/); } } continue; #endif } assert(!align || !(((unsigned long)cb + hdr_size) & (align - 1))); *((char **) cb) = (char *) bchain; bchain = cb; /* Based on a random cast, release a random buffer in the list of allocated buffers. */ if ((myrand() & 0x10) == 0) { char *bc = bchain; int j = myrand() & 0x3; while (j > 0 && bc != NULL) { bc = *((char **) bc); j--; } if (bc != NULL) { char *fb; fb = *((char **) bc); if (fb != NULL) { *((char **) bc) = *((char **) fb); brel((void *) fb, &mypoolset, true/*wipe*/); } } } /* Based on a random cast, reallocate a random buffer in the list to a random size */ if ((myrand() & 0x20) == 0) { char *bc = bchain; int j = myrand() & 0x3; while (j > 0 && bc != NULL) { bc = *((char **) bc); j--; } if (bc != NULL) { char *fb; fb = *((char **) bc); if (fb != NULL) { char *newb; #ifdef UsingFloat bs = pow(x, (double) (myrand() & (ExpIncr - 1))); #else bs = (rand() & (ExpIncr * 4 - 1)) / (1 << (rand() & 0x7)); #endif bs = blimit(bs); #ifdef BECtl protect = 1; /* Protect against compaction */ #endif newb = (char *) bgetr((void *) fb, align, hdr_size, bs, &mypoolset); #ifdef BECtl protect = 0; #endif if (newb != NULL) { assert(!align || !(((unsigned long)newb + hdr_size) & (align - 1))); *((char **) bc) = newb; } } } } } stats("\nAfter allocation", &mypoolset); if (bp != NULL) { #ifdef BufValid V bpoolv((void *) bp); #endif #ifdef BufDump bpoold((void *) bp, dumpAlloc, dumpFree); #endif } while (bchain != NULL) { char *buf = bchain; bchain = *((char **) buf); brel((void *) buf, &mypoolset, true/*wipe*/); } stats("\nAfter release", &mypoolset); #ifndef BECtl if (bp != NULL) { #ifdef BufValid V bpoolv((void *) bp); #endif #ifdef BufDump bpoold((void *) bp, dumpAlloc, dumpFree); #endif } #endif return 0; } #endif optee_os-4.3.0/lib/libutils/isoc/bget.doc000066400000000000000000000416031464416617300203150ustar00rootroot00000000000000 BGET -- Memory Allocator ========================== by John Walker http://www.fourmilab.ch/ BGET is a comprehensive memory allocation package which is easily configured to the needs of an application. BGET is efficient in both the time needed to allocate and release buffers and in the memory overhead required for buffer pool management. It automatically consolidates contiguous space to minimise fragmentation. BGET is configured by compile-time definitions, Major options include: * A built-in test program to exercise BGET and demonstrate how the various functions are used. * Allocation by either the "first fit" or "best fit" method. * Wiping buffers at release time to catch code which references previously released storage. * Built-in routines to dump individual buffers or the entire buffer pool. * Retrieval of allocation and pool size statistics. * Quantisation of buffer sizes to a power of two to satisfy hardware alignment constraints. * Automatic pool compaction, growth, and shrinkage by means of call-backs to user defined functions. Applications of BGET can range from storage management in ROM-based embedded programs to providing the framework upon which a multitasking system incorporating garbage collection is constructed. BGET incorporates extensive internal consistency checking using the mechanism; all these checks can be turned off by compiling with NDEBUG defined, yielding a version of BGET with minimal size and maximum speed. The basic algorithm underlying BGET has withstood the test of time; more than 25 years have passed since the first implementation of this code. And yet, it is substantially more efficient than the native allocation schemes of many operating systems: the Macintosh and Microsoft Windows to name two, on which programs have obtained substantial speed-ups by layering BGET as an application level memory manager atop the underlying system's. BGET has been implemented on the largest mainframes and the lowest of microprocessors. It has served as the core for multitasking operating systems, multi-thread applications, embedded software in data network switching processors, and a host of C programs. And while it has accreted flexibility and additional options over the years, it remains fast, memory efficient, portable, and easy to integrate into your program. BGET IMPLEMENTATION ASSUMPTIONS =============================== BGET is written in as portable a dialect of C as possible. The only fundamental assumption about the underlying hardware architecture is that memory is allocated is a linear array which can be addressed as a vector of C "char" objects. On segmented address space architectures, this generally means that BGET should be used to allocate storage within a single segment (although some compilers simulate linear address spaces on segmented architectures). On segmented architectures, then, BGET buffer pools may not be larger than a segment, but since BGET allows any number of separate buffer pools, there is no limit on the total storage which can be managed, only on the largest individual object which can be allocated. Machines with a linear address architecture, such as the VAX, 680x0, Sparc, MIPS, or the Intel 80386 and above in native mode, may use BGET without restriction. GETTING STARTED WITH BGET ========================= Although BGET can be configured in a multitude of fashions, there are three basic ways of working with BGET. The functions mentioned below are documented in the following section. Please excuse the forward references which are made in the interest of providing a roadmap to guide you to the BGET functions you're likely to need. Embedded Applications --------------------- Embedded applications typically have a fixed area of memory dedicated to buffer allocation (often in a separate RAM address space distinct from the ROM that contains the executable code). To use BGET in such an environment, simply call bpool() with the start address and length of the buffer pool area in RAM, then allocate buffers with bget() and release them with brel(). Embedded applications with very limited RAM but abundant CPU speed may benefit by configuring BGET for BestFit allocation (which is usually not worth it in other environments). Malloc() Emulation ------------------ If the C library malloc() function is too slow, not present in your development environment (for example, an a native Windows or Macintosh program), or otherwise unsuitable, you can replace it with BGET. Initially define a buffer pool of an appropriate size with bpool()--usually obtained by making a call to the operating system's low-level memory allocator. Then allocate buffers with bget(), bgetz(), and bgetr() (the last two permit the allocation of buffers initialised to zero and [inefficient] re-allocation of existing buffers for compatibility with C library functions). Release buffers by calling brel(). If a buffer allocation request fails, obtain more storage from the underlying operating system, add it to the buffer pool by another call to bpool(), and continue execution. Automatic Storage Management ---------------------------- You can use BGET as your application's native memory manager and implement automatic storage pool expansion, contraction, and optionally application-specific memory compaction by compiling BGET with the BECtl variable defined, then calling bectl() and supplying functions for storage compaction, acquisition, and release, as well as a standard pool expansion increment. All of these functions are optional (although it doesn't make much sense to provide a release function without an acquisition function, does it?). Once the call-back functions have been defined with bectl(), you simply use bget() and brel() to allocate and release storage as before. You can supply an initial buffer pool with bpool() or rely on automatic allocation to acquire the entire pool. When a call on bget() cannot be satisfied, BGET first checks if a compaction function has been supplied. If so, it is called (with the space required to satisfy the allocation request and a sequence number to allow the compaction routine to be called successively without looping). If the compaction function is able to free any storage (it needn't know whether the storage it freed was adequate) it should return a nonzero value, whereupon BGET will retry the allocation request and, if it fails again, call the compaction function again with the next-higher sequence number. If the compaction function returns zero, indicating failure to free space, or no compaction function is defined, BGET next tests whether a non-NULL allocation function was supplied to bectl(). If so, that function is called with an argument indicating how many bytes of additional space are required. This will be the standard pool expansion increment supplied in the call to bectl() unless the original bget() call requested a buffer larger than this; buffers larger than the standard pool block can be managed "off the books" by BGET in this mode. If the allocation function succeeds in obtaining the storage, it returns a pointer to the new block and BGET expands the buffer pool; if it fails, the allocation request fails and returns NULL to the caller. If a non-NULL release function is supplied, expansion blocks which become totally empty are released to the global free pool by passing their addresses to the release function. Equipped with appropriate allocation, release, and compaction functions, BGET can be used as part of very sophisticated memory management strategies, including garbage collection. (Note, however, that BGET is *not* a garbage collector by itself, and that developing such a system requires much additional logic and careful design of the application's memory allocation strategy.) BGET FUNCTION DESCRIPTIONS ========================== Functions implemented by BGET (some are enabled by certain of the optional settings below): void bpool(void *buffer, bufsize len); Create a buffer pool of bytes, using the storage starting at . You can call bpool() subsequently to contribute additional storage to the overall buffer pool. void *bget(bufsize size); Allocate a buffer of bytes. The address of the buffer is returned, or NULL if insufficient memory was available to allocate the buffer. void *bgetz(bufsize size); Allocate a buffer of bytes and clear it to all zeroes. The address of the buffer is returned, or NULL if insufficient memory was available to allocate the buffer. void *bgetr(void *buffer, bufsize newsize); Reallocate a buffer previously allocated by bget(), changing its size to and preserving all existing data. NULL is returned if insufficient memory is available to reallocate the buffer, in which case the original buffer remains intact. void brel(void *buf); Return the buffer , previously allocated by bget(), to the free space pool. void bectl(int (*compact)(bufsize sizereq, int sequence), void *(*acquire)(bufsize size), void (*release)(void *buf), bufsize pool_incr); Expansion control: specify functions through which the package may compact storage (or take other appropriate action) when an allocation request fails, and optionally automatically acquire storage for expansion blocks when necessary, and release such blocks when they become empty. If is non-NULL, whenever a buffer allocation request fails, the function will be called with arguments specifying the number of bytes (total buffer size, including header overhead) required to satisfy the allocation request, and a sequence number indicating the number of consecutive calls on attempting to satisfy this allocation request. The sequence number is 1 for the first call on for a given allocation request, and increments on subsequent calls, permitting the function to take increasingly dire measures in an attempt to free up storage. If the function returns a nonzero value, the allocation attempt is re-tried. If returns 0 (as it must if it isn't able to release any space or add storage to the buffer pool), the allocation request fails, which can trigger automatic pool expansion if the argument is non-NULL. At the time the function is called, the state of the buffer allocator is identical to that at the moment the allocation request was made; consequently, the function may call brel(), bpool(), bstats(), and/or directly manipulate the buffer pool in any manner which would be valid were the application in control. This does not, however, relieve the function of the need to ensure that whatever actions it takes do not change things underneath the application that made the allocation request. For example, a function that released a buffer in the process of being reallocated with bgetr() would lead to disaster. Implementing a safe and effective mechanism requires careful design of an application's memory architecture, and cannot generally be easily retrofitted into existing code. If is non-NULL, that function will be called whenever an allocation request fails. If the function succeeds in allocating the requested space and returns a pointer to the new area, allocation will proceed using the expanded buffer pool. If cannot obtain the requested space, it should return NULL and the entire allocation process will fail. specifies the normal expansion block size. Providing an function will cause subsequent bget() requests for buffers too large to be managed in the linked-block scheme (in other words, larger than minus the buffer overhead) to be satisfied directly by calls to the function. Automatic release of empty pool blocks will occur only if all pool blocks in the system are the size given by . void bstats(bufsize *curalloc, bufsize *totfree, bufsize *maxfree, long *nget, long *nrel); The amount of space currently allocated is stored into the variable pointed to by . The total free space (sum of all free blocks in the pool) is stored into the variable pointed to by , and the size of the largest single block in the free space pool is stored into the variable pointed to by . The variables pointed to by and are filled, respectively, with the number of successful (non-NULL return) bget() calls and the number of brel() calls. void bstatse(bufsize *pool_incr, long *npool, long *npget, long *nprel, long *ndget, long *ndrel); Extended statistics: The expansion block size will be stored into the variable pointed to by , or the negative thereof if automatic expansion block releases are disabled. The number of currently active pool blocks will be stored into the variable pointed to by . The variables pointed to by and will be filled with, respectively, the number of expansion block acquisitions and releases which have occurred. The variables pointed to by and will be filled with the number of bget() and brel() calls, respectively, managed through blocks directly allocated by the acquisition and release functions. void bufdump(void *buf); The buffer pointed to by is dumped on standard output. void bpoold(void *pool, int dumpalloc, int dumpfree); All buffers in the buffer pool , previously initialised by a call on bpool(), are listed in ascending memory address order. If is nonzero, the contents of allocated buffers are dumped; if is nonzero, the contents of free blocks are dumped. int bpoolv(void *pool); The named buffer pool, previously initialised by a call on bpool(), is validated for bad pointers, overwritten data, etc. If compiled with NDEBUG not defined, any error generates an assertion failure. Otherwise 1 is returned if the pool is valid, 0 if an error is found. BGET CONFIGURATION ================== #define TestProg 20000 /* Generate built-in test program if defined. The value specifies how many buffer allocation attempts the test program should make. */ #define SizeQuant 4 /* Buffer allocation size quantum: all buffers allocated are a multiple of this size. This MUST be a power of two. */ #define BufDump 1 /* Define this symbol to enable the bpoold() function which dumps the buffers in a buffer pool. */ #define BufValid 1 /* Define this symbol to enable the bpoolv() function for validating a buffer pool. */ #define DumpData 1 /* Define this symbol to enable the bufdump() function which allows dumping the contents of an allocated or free buffer. */ #define BufStats 1 /* Define this symbol to enable the bstats() function which calculates the total free space in the buffer pool, the largest available buffer, and the total space currently allocated. */ #define FreeWipe 1 /* Wipe free buffers to a guaranteed pattern of garbage to trip up miscreants who attempt to use pointers into released buffers. */ #define BestFit 1 /* Use a best fit algorithm when searching for space for an allocation request. This uses memory more efficiently, but allocation will be much slower. */ #define BECtl 1 /* Define this symbol to enable the bectl() function for automatic pool space control. */ optee_os-4.3.0/lib/libutils/isoc/bget.h000066400000000000000000000043661464416617300200040ustar00rootroot00000000000000/* * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL ST BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* Interface definitions for bget.c, the memory management package. */ #ifndef _ #ifdef PROTOTYPES #define _(x) x /* If compiler knows prototypes */ #else #define _(x) () /* It it doesn't */ #endif /* PROTOTYPES */ #endif #define BGET_HDR_QUANTUM (2 * sizeof(long)) typedef long bufsize; struct bpoolset; void bpool _((void *buffer, bufsize len, struct bpoolset *poolset)); void *bget _((bufsize align, bufsize hdr_size, bufsize size, struct bpoolset *poolset)); void *bgetz _((bufsize align, bufsize hdr_size, bufsize size, struct bpoolset *poolset)); void *bgetr _((void *buffer, bufsize align, bufsize hdr_size, bufsize newsize, struct bpoolset *poolset)); void brel _((void *buf, struct bpoolset *poolset, int wipe)); void bectl _((int (*compact)(bufsize sizereq, int sequence), void *(*acquire)(bufsize size), void (*release)(void *buf), bufsize pool_incr, struct bpoolset *poolset)); void bstats _((bufsize *curalloc, bufsize *totfree, bufsize *maxfree, long *nget, long *nrel, struct bpoolset *poolset)); void bstatse _((bufsize *pool_incr, long *npool, long *npget, long *nprel, long *ndget, long *ndrel, struct bpoolset *poolset)); void bufdump _((void *buf)); void bpoold _((void *pool, int dumpalloc, int dumpfree)); int bpoolv _((void *pool)); #if !defined(__KERNEL__) && !defined(__LDELF__) && defined(CFG_TA_BGET_TEST) int bget_main_test(void *(*malloc_func)(size_t), void (*free_func)(void *)); #endif optee_os-4.3.0/lib/libutils/isoc/bget_malloc.c000066400000000000000000000620221464416617300213170ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. * Copyright (c) 2022, Linaro Limited. */ #define PROTOTYPES /* * BGET CONFIGURATION * ================== */ /* #define BGET_ENABLE_ALL_OPTIONS */ #ifdef BGET_ENABLE_OPTION #define TestProg 20000 /* Generate built-in test program if defined. The value specifies how many buffer allocation attempts the test program should make. */ #endif #ifdef __LP64__ #define SizeQuant 16 #endif #ifdef __ILP32__ #define SizeQuant 8 #endif /* Buffer allocation size quantum: all buffers allocated are a multiple of this size. This MUST be a power of two. */ #ifdef BGET_ENABLE_OPTION #define BufDump 1 /* Define this symbol to enable the bpoold() function which dumps the buffers in a buffer pool. */ #define BufValid 1 /* Define this symbol to enable the bpoolv() function for validating a buffer pool. */ #define DumpData 1 /* Define this symbol to enable the bufdump() function which allows dumping the contents of an allocated or free buffer. */ #define BufStats 1 /* Define this symbol to enable the bstats() function which calculates the total free space in the buffer pool, the largest available buffer, and the total space currently allocated. */ #define FreeWipe 1 /* Wipe free buffers to a guaranteed pattern of garbage to trip up miscreants who attempt to use pointers into released buffers. */ #define BestFit 1 /* Use a best fit algorithm when searching for space for an allocation request. This uses memory more efficiently, but allocation will be much slower. */ #define BECtl 1 /* Define this symbol to enable the bectl() function for automatic pool space control. */ #endif #ifdef MEM_DEBUG #undef NDEBUG #define DumpData 1 #define BufValid 1 #define FreeWipe 1 #endif #ifdef CFG_WITH_STATS #define BufStats 1 #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__KERNEL__) /* Compiling for TEE Core */ #include #include #include static void *memset_unchecked(void *s, int c, size_t n) { return asan_memset_unchecked(s, c, n); } static __maybe_unused void *memcpy_unchecked(void *dst, const void *src, size_t n) { return asan_memcpy_unchecked(dst, src, n); } #else /*__KERNEL__*/ /* Compiling for TA */ static void *memset_unchecked(void *s, int c, size_t n) { return memset(s, c, n); } static __maybe_unused void *memcpy_unchecked(void *dst, const void *src, size_t n) { return memcpy(dst, src, n); } #endif /*__KERNEL__*/ #include "bget.c" /* this is ugly, but this is bget */ struct malloc_pool { void *buf; size_t len; }; struct malloc_ctx { struct bpoolset poolset; struct malloc_pool *pool; size_t pool_len; #ifdef BufStats struct pta_stats_alloc mstats; #endif #ifdef __KERNEL__ unsigned int spinlock; #endif }; #ifdef __KERNEL__ static uint32_t malloc_lock(struct malloc_ctx *ctx) { return cpu_spin_lock_xsave(&ctx->spinlock); } static void malloc_unlock(struct malloc_ctx *ctx, uint32_t exceptions) { cpu_spin_unlock_xrestore(&ctx->spinlock, exceptions); } #else /* __KERNEL__ */ static uint32_t malloc_lock(struct malloc_ctx *ctx __unused) { return 0; } static void malloc_unlock(struct malloc_ctx *ctx __unused, uint32_t exceptions __unused) { } #endif /* __KERNEL__ */ #define DEFINE_CTX(name) struct malloc_ctx name = \ { .poolset = { .freelist = { {0, 0}, \ {&name.poolset.freelist, \ &name.poolset.freelist}}}} static DEFINE_CTX(malloc_ctx); #ifdef CFG_NS_VIRTUALIZATION static __nex_data DEFINE_CTX(nex_malloc_ctx); #endif static void print_oom(size_t req_size __maybe_unused, void *ctx __maybe_unused) { #if defined(__KERNEL__) && defined(CFG_CORE_DUMP_OOM) EMSG("Memory allocation failed: size %zu context %p", req_size, ctx); print_kernel_stack(); #endif } /* Most of the stuff in this function is copied from bgetr() in bget.c */ static __maybe_unused bufsize bget_buf_size(void *buf) { bufsize osize; /* Old size of buffer */ struct bhead *b; b = BH(((char *)buf) - sizeof(struct bhead)); osize = -b->bsize; #ifdef BECtl if (osize == 0) { /* Buffer acquired directly through acqfcn. */ struct bdhead *bd; bd = BDH(((char *)buf) - sizeof(struct bdhead)); osize = bd->tsize - sizeof(struct bdhead) - bd->offs; } else #endif osize -= sizeof(struct bhead); assert(osize > 0); return osize; } static void *maybe_tag_buf(uint8_t *buf, size_t hdr_size, size_t requested_size) { if (!buf) return NULL; COMPILE_TIME_ASSERT(MEMTAG_GRANULE_SIZE <= SizeQuant); if (MEMTAG_IS_ENABLED) { size_t sz = ROUNDUP(requested_size, MEMTAG_GRANULE_SIZE); /* * Allocated buffer can be larger than requested when * allocating with memalign(), but we should never tag more * than allocated. */ assert(bget_buf_size(buf) >= sz + hdr_size); return memtag_set_random_tags(buf, sz + hdr_size); } #if defined(__KERNEL__) if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS)) asan_tag_access(buf, buf + hdr_size + requested_size); #endif return buf; } static void *maybe_untag_buf(void *buf) { if (!buf) return NULL; if (MEMTAG_IS_ENABLED) { size_t sz = 0; memtag_assert_tag(buf); /* Trying to catch double free early */ sz = bget_buf_size(memtag_strip_tag(buf)); return memtag_set_tags(buf, sz, 0); } #if defined(__KERNEL__) if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS)) asan_tag_heap_free(buf, (uint8_t *)buf + bget_buf_size(buf)); #endif return buf; } static void *strip_tag(void *buf) { if (MEMTAG_IS_ENABLED) return memtag_strip_tag(buf); return buf; } static void tag_asan_free(void *buf __maybe_unused, size_t len __maybe_unused) { #if defined(__KERNEL__) asan_tag_heap_free(buf, (uint8_t *)buf + len); #endif } #ifdef BufStats static void *raw_malloc_return_hook(void *p, size_t hdr_size, size_t requested_size, struct malloc_ctx *ctx) { if (ctx->poolset.totalloc > ctx->mstats.max_allocated) ctx->mstats.max_allocated = ctx->poolset.totalloc; if (!p) { ctx->mstats.num_alloc_fail++; print_oom(requested_size, ctx); if (requested_size > ctx->mstats.biggest_alloc_fail) { ctx->mstats.biggest_alloc_fail = requested_size; ctx->mstats.biggest_alloc_fail_used = ctx->poolset.totalloc; } } return maybe_tag_buf(p, hdr_size, MAX(SizeQuant, requested_size)); } static void gen_malloc_reset_stats(struct malloc_ctx *ctx) { uint32_t exceptions = malloc_lock(ctx); ctx->mstats.max_allocated = 0; ctx->mstats.num_alloc_fail = 0; ctx->mstats.biggest_alloc_fail = 0; ctx->mstats.biggest_alloc_fail_used = 0; malloc_unlock(ctx, exceptions); } void malloc_reset_stats(void) { gen_malloc_reset_stats(&malloc_ctx); } static void gen_malloc_get_stats(struct malloc_ctx *ctx, struct pta_stats_alloc *stats) { uint32_t exceptions = malloc_lock(ctx); raw_malloc_get_stats(ctx, stats); malloc_unlock(ctx, exceptions); } void malloc_get_stats(struct pta_stats_alloc *stats) { gen_malloc_get_stats(&malloc_ctx, stats); } #else /* BufStats */ static void *raw_malloc_return_hook(void *p, size_t hdr_size, size_t requested_size, struct malloc_ctx *ctx ) { if (!p) print_oom(requested_size, ctx); return maybe_tag_buf(p, hdr_size, MAX(SizeQuant, requested_size)); } #endif /* BufStats */ #ifdef BufValid static void raw_malloc_validate_pools(struct malloc_ctx *ctx) { size_t n; for (n = 0; n < ctx->pool_len; n++) bpoolv(ctx->pool[n].buf); } #else static void raw_malloc_validate_pools(struct malloc_ctx *ctx __unused) { } #endif struct bpool_iterator { struct bfhead *next_buf; size_t pool_idx; }; static void bpool_foreach_iterator_init(struct malloc_ctx *ctx, struct bpool_iterator *iterator) { iterator->pool_idx = 0; iterator->next_buf = BFH(ctx->pool[0].buf); } static bool bpool_foreach_pool(struct bpool_iterator *iterator, void **buf, size_t *len, bool *isfree) { struct bfhead *b = iterator->next_buf; bufsize bs = b->bh.bsize; if (bs == ESent) return false; if (bs < 0) { /* Allocated buffer */ bs = -bs; *isfree = false; } else { /* Free Buffer */ *isfree = true; /* Assert that the free list links are intact */ assert(b->ql.blink->ql.flink == b); assert(b->ql.flink->ql.blink == b); } *buf = (uint8_t *)b + sizeof(struct bhead); *len = bs - sizeof(struct bhead); iterator->next_buf = BFH((uint8_t *)b + bs); return true; } static bool bpool_foreach(struct malloc_ctx *ctx, struct bpool_iterator *iterator, void **buf) { while (true) { size_t len; bool isfree; if (bpool_foreach_pool(iterator, buf, &len, &isfree)) { if (isfree) continue; return true; } if ((iterator->pool_idx + 1) >= ctx->pool_len) return false; iterator->pool_idx++; iterator->next_buf = BFH(ctx->pool[iterator->pool_idx].buf); } } /* Convenience macro for looping over all allocated buffers */ #define BPOOL_FOREACH(ctx, iterator, bp) \ for (bpool_foreach_iterator_init((ctx),(iterator)); \ bpool_foreach((ctx),(iterator), (bp));) void *raw_memalign(size_t hdr_size, size_t ftr_size, size_t alignment, size_t pl_size, struct malloc_ctx *ctx) { void *ptr = NULL; bufsize s; if (!alignment || !IS_POWER_OF_TWO(alignment)) return NULL; raw_malloc_validate_pools(ctx); /* Compute total size, excluding the header */ if (ADD_OVERFLOW(pl_size, ftr_size, &s)) goto out; /* BGET doesn't like 0 sized allocations */ if (!s) s++; ptr = bget(alignment, hdr_size, s, &ctx->poolset); out: return raw_malloc_return_hook(ptr, hdr_size, pl_size, ctx); } void *raw_malloc(size_t hdr_size, size_t ftr_size, size_t pl_size, struct malloc_ctx *ctx) { /* * Note that we're feeding SizeQ as alignment, this is the smallest * alignment that bget() can use. */ return raw_memalign(hdr_size, ftr_size, SizeQ, pl_size, ctx); } void raw_free(void *ptr, struct malloc_ctx *ctx, bool wipe) { raw_malloc_validate_pools(ctx); if (ptr) brel(maybe_untag_buf(ptr), &ctx->poolset, wipe); } void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb, size_t pl_size, struct malloc_ctx *ctx) { void *ptr = NULL; bufsize s; raw_malloc_validate_pools(ctx); /* Compute total size, excluding hdr_size */ if (MUL_OVERFLOW(pl_nmemb, pl_size, &s)) goto out; if (ADD_OVERFLOW(s, ftr_size, &s)) goto out; /* BGET doesn't like 0 sized allocations */ if (!s) s++; ptr = bgetz(0, hdr_size, s, &ctx->poolset); out: return raw_malloc_return_hook(ptr, hdr_size, pl_nmemb * pl_size, ctx); } void *raw_realloc(void *ptr, size_t hdr_size, size_t ftr_size, size_t pl_size, struct malloc_ctx *ctx) { void *p = NULL; bufsize s; /* Compute total size */ if (ADD_OVERFLOW(pl_size, hdr_size, &s)) goto out; if (ADD_OVERFLOW(s, ftr_size, &s)) goto out; raw_malloc_validate_pools(ctx); /* BGET doesn't like 0 sized allocations */ if (!s) s++; p = bget(0, 0, s, &ctx->poolset); if (p && ptr) { void *old_ptr = maybe_untag_buf(ptr); bufsize old_sz = bget_buf_size(old_ptr); if (old_sz < s) { memcpy_unchecked(p, old_ptr, old_sz); #ifndef __KERNEL__ /* User space reallocations are always zeroed */ memset_unchecked((uint8_t *)p + old_sz, 0, s - old_sz); #endif } else { memcpy_unchecked(p, old_ptr, s); } brel(old_ptr, &ctx->poolset, false /*!wipe*/); } out: return raw_malloc_return_hook(p, hdr_size, pl_size, ctx); } #ifdef ENABLE_MDBG struct mdbg_hdr { const char *fname; uint16_t line; uint32_t pl_size; uint32_t magic; #if defined(ARM64) uint64_t pad; #endif }; #define MDBG_HEADER_MAGIC 0xadadadad #define MDBG_FOOTER_MAGIC 0xecececec static size_t mdbg_get_ftr_size(size_t pl_size) { size_t ftr_pad = ROUNDUP(pl_size, sizeof(uint32_t)) - pl_size; return ftr_pad + sizeof(uint32_t); } static uint32_t *mdbg_get_footer(struct mdbg_hdr *hdr) { uint32_t *footer; footer = (uint32_t *)((uint8_t *)(hdr + 1) + hdr->pl_size + mdbg_get_ftr_size(hdr->pl_size)); footer--; return strip_tag(footer); } static void mdbg_update_hdr(struct mdbg_hdr *hdr, const char *fname, int lineno, size_t pl_size) { uint32_t *footer; hdr->fname = fname; hdr->line = lineno; hdr->pl_size = pl_size; hdr->magic = MDBG_HEADER_MAGIC; footer = mdbg_get_footer(hdr); *footer = MDBG_FOOTER_MAGIC; } static void *gen_mdbg_malloc(struct malloc_ctx *ctx, const char *fname, int lineno, size_t size) { struct mdbg_hdr *hdr; uint32_t exceptions = malloc_lock(ctx); /* * Check struct mdbg_hdr works with BGET_HDR_QUANTUM. */ COMPILE_TIME_ASSERT((sizeof(struct mdbg_hdr) % BGET_HDR_QUANTUM) == 0); hdr = raw_malloc(sizeof(struct mdbg_hdr), mdbg_get_ftr_size(size), size, ctx); if (hdr) { mdbg_update_hdr(hdr, fname, lineno, size); hdr++; } malloc_unlock(ctx, exceptions); return hdr; } static void assert_header(struct mdbg_hdr *hdr __maybe_unused) { assert(hdr->magic == MDBG_HEADER_MAGIC); assert(*mdbg_get_footer(hdr) == MDBG_FOOTER_MAGIC); } static void gen_mdbg_free(struct malloc_ctx *ctx, void *ptr, bool wipe) { struct mdbg_hdr *hdr = ptr; if (hdr) { hdr--; assert_header(hdr); hdr->magic = 0; *mdbg_get_footer(hdr) = 0; raw_free(hdr, ctx, wipe); } } static void free_helper(void *ptr, bool wipe) { uint32_t exceptions = malloc_lock(&malloc_ctx); gen_mdbg_free(&malloc_ctx, ptr, wipe); malloc_unlock(&malloc_ctx, exceptions); } static void *gen_mdbg_calloc(struct malloc_ctx *ctx, const char *fname, int lineno, size_t nmemb, size_t size) { struct mdbg_hdr *hdr; uint32_t exceptions = malloc_lock(ctx); hdr = raw_calloc(sizeof(struct mdbg_hdr), mdbg_get_ftr_size(nmemb * size), nmemb, size, ctx); if (hdr) { mdbg_update_hdr(hdr, fname, lineno, nmemb * size); hdr++; } malloc_unlock(ctx, exceptions); return hdr; } static void *gen_mdbg_realloc_unlocked(struct malloc_ctx *ctx, const char *fname, int lineno, void *ptr, size_t size) { struct mdbg_hdr *hdr = ptr; if (hdr) { hdr--; assert_header(hdr); } hdr = raw_realloc(hdr, sizeof(struct mdbg_hdr), mdbg_get_ftr_size(size), size, ctx); if (hdr) { mdbg_update_hdr(hdr, fname, lineno, size); hdr++; } return hdr; } static void *gen_mdbg_realloc(struct malloc_ctx *ctx, const char *fname, int lineno, void *ptr, size_t size) { void *p; uint32_t exceptions = malloc_lock(ctx); p = gen_mdbg_realloc_unlocked(ctx, fname, lineno, ptr, size); malloc_unlock(ctx, exceptions); return p; } #define realloc_unlocked(ctx, ptr, size) \ gen_mdbg_realloc_unlocked(ctx, __FILE__, __LINE__, (ptr), (size)) static void *gen_mdbg_memalign(struct malloc_ctx *ctx, const char *fname, int lineno, size_t alignment, size_t size) { struct mdbg_hdr *hdr; uint32_t exceptions = malloc_lock(ctx); hdr = raw_memalign(sizeof(struct mdbg_hdr), mdbg_get_ftr_size(size), alignment, size, ctx); if (hdr) { mdbg_update_hdr(hdr, fname, lineno, size); hdr++; } malloc_unlock(ctx, exceptions); return hdr; } static void *get_payload_start_size(void *raw_buf, size_t *size) { struct mdbg_hdr *hdr = raw_buf; assert(bget_buf_size(hdr) >= hdr->pl_size); *size = hdr->pl_size; return hdr + 1; } static void gen_mdbg_check(struct malloc_ctx *ctx, int bufdump) { struct bpool_iterator itr; void *b; uint32_t exceptions = malloc_lock(ctx); raw_malloc_validate_pools(ctx); BPOOL_FOREACH(ctx, &itr, &b) { struct mdbg_hdr *hdr = (struct mdbg_hdr *)b; assert_header(hdr); if (bufdump > 0) { const char *fname = hdr->fname; if (!fname) fname = "unknown"; IMSG("buffer: %d bytes %s:%d", hdr->pl_size, fname, hdr->line); } } malloc_unlock(ctx, exceptions); } void *mdbg_malloc(const char *fname, int lineno, size_t size) { return gen_mdbg_malloc(&malloc_ctx, fname, lineno, size); } void *mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size) { return gen_mdbg_calloc(&malloc_ctx, fname, lineno, nmemb, size); } void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) { return gen_mdbg_realloc(&malloc_ctx, fname, lineno, ptr, size); } void *mdbg_memalign(const char *fname, int lineno, size_t alignment, size_t size) { return gen_mdbg_memalign(&malloc_ctx, fname, lineno, alignment, size); } #if __STDC_VERSION__ >= 201112L void *mdbg_aligned_alloc(const char *fname, int lineno, size_t alignment, size_t size) { if (size % alignment) return NULL; return gen_mdbg_memalign(&malloc_ctx, fname, lineno, alignment, size); } #endif /* __STDC_VERSION__ */ void mdbg_check(int bufdump) { gen_mdbg_check(&malloc_ctx, bufdump); } /* * Since malloc debug is enabled, malloc() and friends are redirected by macros * to mdbg_malloc() etc. * We still want to export the standard entry points in case they are referenced * by the application, either directly or via external libraries. */ #undef malloc void *malloc(size_t size) { return mdbg_malloc(__FILE__, __LINE__, size); } #undef calloc void *calloc(size_t nmemb, size_t size) { return mdbg_calloc(__FILE__, __LINE__, nmemb, size); } #undef realloc void *realloc(void *ptr, size_t size) { return mdbg_realloc(__FILE__, __LINE__, ptr, size); } #else /* ENABLE_MDBG */ void *malloc(size_t size) { void *p; uint32_t exceptions = malloc_lock(&malloc_ctx); p = raw_malloc(0, 0, size, &malloc_ctx); malloc_unlock(&malloc_ctx, exceptions); return p; } static void free_helper(void *ptr, bool wipe) { uint32_t exceptions = malloc_lock(&malloc_ctx); raw_free(ptr, &malloc_ctx, wipe); malloc_unlock(&malloc_ctx, exceptions); } void *calloc(size_t nmemb, size_t size) { void *p; uint32_t exceptions = malloc_lock(&malloc_ctx); p = raw_calloc(0, 0, nmemb, size, &malloc_ctx); malloc_unlock(&malloc_ctx, exceptions); return p; } static void *realloc_unlocked(struct malloc_ctx *ctx, void *ptr, size_t size) { return raw_realloc(ptr, 0, 0, size, ctx); } void *realloc(void *ptr, size_t size) { void *p; uint32_t exceptions = malloc_lock(&malloc_ctx); p = realloc_unlocked(&malloc_ctx, ptr, size); malloc_unlock(&malloc_ctx, exceptions); return p; } void *memalign(size_t alignment, size_t size) { void *p; uint32_t exceptions = malloc_lock(&malloc_ctx); p = raw_memalign(0, 0, alignment, size, &malloc_ctx); malloc_unlock(&malloc_ctx, exceptions); return p; } #if __STDC_VERSION__ >= 201112L void *aligned_alloc(size_t alignment, size_t size) { if (size % alignment) return NULL; return memalign(alignment, size); } #endif /* __STDC_VERSION__ */ static void *get_payload_start_size(void *ptr, size_t *size) { *size = bget_buf_size(ptr); return ptr; } #endif void free(void *ptr) { free_helper(ptr, false); } void free_wipe(void *ptr) { free_helper(ptr, true); } static void gen_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len) { uint32_t exceptions = malloc_lock(ctx); raw_malloc_add_pool(ctx, buf, len); malloc_unlock(ctx, exceptions); } static bool gen_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, void *buf, size_t len) { uint32_t exceptions = malloc_lock(ctx); bool ret = false; ret = raw_malloc_buffer_is_within_alloced(ctx, buf, len); malloc_unlock(ctx, exceptions); return ret; } static bool gen_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, void *buf, size_t len) { bool ret = false; uint32_t exceptions = malloc_lock(ctx); ret = raw_malloc_buffer_overlaps_heap(ctx, buf, len); malloc_unlock(ctx, exceptions); return ret; } size_t raw_malloc_get_ctx_size(void) { return sizeof(struct malloc_ctx); } void raw_malloc_init_ctx(struct malloc_ctx *ctx) { memset(ctx, 0, sizeof(*ctx)); ctx->poolset.freelist.ql.flink = &ctx->poolset.freelist; ctx->poolset.freelist.ql.blink = &ctx->poolset.freelist; } void raw_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len) { const size_t min_len = sizeof(struct bhead) + sizeof(struct bfhead); uintptr_t start = (uintptr_t)buf; uintptr_t end = start + len; void *p = NULL; size_t l = 0; start = ROUNDUP(start, SizeQuant); end = ROUNDDOWN(end, SizeQuant); if (start > end || (end - start) < min_len) { DMSG("Skipping too small pool"); return; } /* First pool requires a bigger size */ if (!ctx->pool_len && (end - start) < MALLOC_INITIAL_POOL_MIN_SIZE) { DMSG("Skipping too small initial pool"); return; } tag_asan_free((void *)start, end - start); bpool((void *)start, end - start, &ctx->poolset); l = ctx->pool_len + 1; p = realloc_unlocked(ctx, ctx->pool, sizeof(struct malloc_pool) * l); assert(p); ctx->pool = p; ctx->pool[ctx->pool_len].buf = (void *)start; ctx->pool[ctx->pool_len].len = end - start; #ifdef BufStats ctx->mstats.size += ctx->pool[ctx->pool_len].len; #endif ctx->pool_len = l; } bool raw_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, void *buf, size_t len) { uintptr_t buf_start = (uintptr_t)strip_tag(buf); uintptr_t buf_end = buf_start + len; size_t n = 0; raw_malloc_validate_pools(ctx); for (n = 0; n < ctx->pool_len; n++) { uintptr_t pool_start = (uintptr_t)strip_tag(ctx->pool[n].buf); uintptr_t pool_end = pool_start + ctx->pool[n].len; if (buf_start > buf_end || pool_start > pool_end) return true; /* Wrapping buffers, shouldn't happen */ if ((buf_start >= pool_start && buf_start < pool_end) || (buf_end > pool_start && buf_end < pool_end)) return true; } return false; } bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, void *buf, size_t len) { struct bpool_iterator itr = { }; void *b = NULL; uint8_t *start_buf = strip_tag(buf); uint8_t *end_buf = start_buf + len; raw_malloc_validate_pools(ctx); /* Check for wrapping */ if (start_buf > end_buf) return false; BPOOL_FOREACH(ctx, &itr, &b) { uint8_t *start_b = NULL; uint8_t *end_b = NULL; size_t s = 0; start_b = strip_tag(get_payload_start_size(b, &s)); end_b = start_b + s; if (start_buf >= start_b && end_buf <= end_b) return true; } return false; } #ifdef CFG_WITH_STATS void raw_malloc_get_stats(struct malloc_ctx *ctx, struct pta_stats_alloc *stats) { memcpy_unchecked(stats, &ctx->mstats, sizeof(*stats)); stats->allocated = ctx->poolset.totalloc; } #endif void malloc_add_pool(void *buf, size_t len) { gen_malloc_add_pool(&malloc_ctx, buf, len); } bool malloc_buffer_is_within_alloced(void *buf, size_t len) { return gen_malloc_buffer_is_within_alloced(&malloc_ctx, buf, len); } bool malloc_buffer_overlaps_heap(void *buf, size_t len) { return gen_malloc_buffer_overlaps_heap(&malloc_ctx, buf, len); } #ifdef CFG_NS_VIRTUALIZATION #ifndef ENABLE_MDBG void *nex_malloc(size_t size) { void *p; uint32_t exceptions = malloc_lock(&nex_malloc_ctx); p = raw_malloc(0, 0, size, &nex_malloc_ctx); malloc_unlock(&nex_malloc_ctx, exceptions); return p; } void *nex_calloc(size_t nmemb, size_t size) { void *p; uint32_t exceptions = malloc_lock(&nex_malloc_ctx); p = raw_calloc(0, 0, nmemb, size, &nex_malloc_ctx); malloc_unlock(&nex_malloc_ctx, exceptions); return p; } void *nex_realloc(void *ptr, size_t size) { void *p; uint32_t exceptions = malloc_lock(&nex_malloc_ctx); p = realloc_unlocked(&nex_malloc_ctx, ptr, size); malloc_unlock(&nex_malloc_ctx, exceptions); return p; } void *nex_memalign(size_t alignment, size_t size) { void *p; uint32_t exceptions = malloc_lock(&nex_malloc_ctx); p = raw_memalign(0, 0, alignment, size, &nex_malloc_ctx); malloc_unlock(&nex_malloc_ctx, exceptions); return p; } void nex_free(void *ptr) { uint32_t exceptions = malloc_lock(&nex_malloc_ctx); raw_free(ptr, &nex_malloc_ctx, false /* !wipe */); malloc_unlock(&nex_malloc_ctx, exceptions); } #else /* ENABLE_MDBG */ void *nex_mdbg_malloc(const char *fname, int lineno, size_t size) { return gen_mdbg_malloc(&nex_malloc_ctx, fname, lineno, size); } void *nex_mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size) { return gen_mdbg_calloc(&nex_malloc_ctx, fname, lineno, nmemb, size); } void *nex_mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size) { return gen_mdbg_realloc(&nex_malloc_ctx, fname, lineno, ptr, size); } void *nex_mdbg_memalign(const char *fname, int lineno, size_t alignment, size_t size) { return gen_mdbg_memalign(&nex_malloc_ctx, fname, lineno, alignment, size); } void nex_mdbg_check(int bufdump) { gen_mdbg_check(&nex_malloc_ctx, bufdump); } void nex_free(void *ptr) { uint32_t exceptions = malloc_lock(&nex_malloc_ctx); gen_mdbg_free(&nex_malloc_ctx, ptr, false /* !wipe */); malloc_unlock(&nex_malloc_ctx, exceptions); } #endif /* ENABLE_MDBG */ void nex_malloc_add_pool(void *buf, size_t len) { gen_malloc_add_pool(&nex_malloc_ctx, buf, len); } bool nex_malloc_buffer_is_within_alloced(void *buf, size_t len) { return gen_malloc_buffer_is_within_alloced(&nex_malloc_ctx, buf, len); } bool nex_malloc_buffer_overlaps_heap(void *buf, size_t len) { return gen_malloc_buffer_overlaps_heap(&nex_malloc_ctx, buf, len); } #ifdef BufStats void nex_malloc_reset_stats(void) { gen_malloc_reset_stats(&nex_malloc_ctx); } void nex_malloc_get_stats(struct pta_stats_alloc *stats) { gen_malloc_get_stats(&nex_malloc_ctx, stats); } #endif #endif optee_os-4.3.0/lib/libutils/isoc/fp.c000066400000000000000000000004321464416617300174510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #include struct _FILE { char dummy; }; static struct _FILE _fake_stdout; static struct _FILE _fake_stderr; FILE *stdout = &_fake_stdout; FILE *stderr = &_fake_stderr; optee_os-4.3.0/lib/libutils/isoc/fputc.c000066400000000000000000000003731464416617300201710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #include #include int fputc(int c, FILE *stream) { if (stream != stdout && stream != stderr) abort(); return putchar(c); } optee_os-4.3.0/lib/libutils/isoc/fputs.c000066400000000000000000000004411464416617300202050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #include #include #include int fputs(const char *s, FILE *stream) { if (stream != stdout && stream != stderr) abort(); trace_ext_puts(s); return 0; } optee_os-4.3.0/lib/libutils/isoc/fwrite.c000066400000000000000000000005721464416617300203510ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #include #include #include size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { int fd = 0; if (stream == stdout) fd = 1; else if (stream == stderr) fd = 2; else abort(); return write(fd, ptr, size * nmemb); } optee_os-4.3.0/lib/libutils/isoc/include/000077500000000000000000000000001464416617300203245ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/include/assert.h000066400000000000000000000043331464416617300220010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __ASSERT_H #define __ASSERT_H #include #include void __noreturn _assert_break(void); void _assert_log(const char *expr, const char *file, const int line, const char *func); static inline void __noreturn _assert_trap(const char *expr_str, const char *file, const int line, const char *func) { _assert_log(expr_str, file, line, func); _assert_break(); } static inline void _runtime_assert_trap(const char *expr_str, const char *file, const int line, const char *func) { volatile bool do_break = true; _assert_log(expr_str, file, line, func); if (do_break) _assert_break(); } /* * runtime_assert() behaves as assert() except that it doesn't tell the * compiler it will never return. This can be used to avoid the warning: * error: function might be candidate for attribute ‘noreturn’ */ #ifdef NDEBUG #define assert(expr) ((void)0) #define runtime_assert(expr) ((void)0) #else #define assert(expr) \ ((expr) ? (void)0 : _assert_trap(#expr, __FILE__, __LINE__, __func__)) #define runtime_assert(expr) \ ((expr) ? (void)0 : \ _runtime_assert_trap(#expr, __FILE__, __LINE__, __func__)) #endif /* This macro is deprecated, please use static_assert instead */ #define COMPILE_TIME_ASSERT(x) \ do { \ switch (0) { case 0: case ((x) ? 1: 0): default : break; } \ } while (0) #endif #if !defined(__cplusplus) || (__cplusplus < 201103L) #if defined(__HAVE_SINGLE_ARGUMENT_STATIC_ASSERT) #define static_assert _Static_assert #else /* * In gcc prior to 9.1 _Static_assert requires two arguments. To allow * passing a single argument to static_assert() add a workaround with * macros. */ #define ___args_count(_0, _1, x, ...) x #define __args_count(...) ___args_count(__VA_ARGS__, 2, 1, 0) #define __static_assert_1(expr) _Static_assert(expr, "") #define __static_assert_2(expr, msg) _Static_assert(expr, msg) #define ___static_assert(count, ...) __static_assert_ ## count(__VA_ARGS__) #define __static_assert(count, ...) ___static_assert(count, __VA_ARGS__) #define static_assert(...) \ __static_assert(__args_count(__VA_ARGS__), __VA_ARGS__) #endif #endif /* __ASSERT_H */ optee_os-4.3.0/lib/libutils/isoc/include/ctype.h000066400000000000000000000006311464416617300216210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018, Linaro Limited */ #ifndef __CTYPE_H #define __CTYPE_H int isalnum(int c); int isalpha(int c); int iscntrl(int c); int isdigit(int c); int isgraph(int c); int islower(int c); int isprint(int c); int ispunct(int c); int isspace(int c); int isupper(int c); int isxdigit(int c); int tolower(int c); int toupper(int c); #endif /*__CTYPE_H*/ optee_os-4.3.0/lib/libutils/isoc/include/inttypes.h000066400000000000000000000021431464416617300223540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __INTTYPES_H #define __INTTYPES_H #include #ifdef __ILP32__ #define __PRI64_PREFIX "ll" #endif #ifdef __LP64__ #define __PRI64_PREFIX "l" #endif #define __PRIPTR_PREFIX "l" #define PRId8 "d" #define PRId16 "d" #define PRId32 "d" #define PRId64 __PRI64_PREFIX "d" #define PRIdPTR __PRIPTR_PREFIX "d" #define PRIi8 "i" #define PRIi16 "i" #define PRIi32 "i" #define PRIi64 __PRI64_PREFIX "i" #define PRIiPTR __PRIPTR_PREFIX "i" #define PRIo8 "o" #define PRIo16 "o" #define PRIo32 "o" #define PRIo64 __PRI64_PREFIX "o" #define PRIoPTR __PRIPTR_PREFIX "o" #define PRIu8 "u" #define PRIu16 "u" #define PRIu32 "u" #define PRIu64 __PRI64_PREFIX "u" #define PRIuPTR __PRIPTR_PREFIX "u" #define PRIx8 "x" #define PRIx16 "x" #define PRIx32 "x" #define PRIx64 __PRI64_PREFIX "x" #define PRIxPTR __PRIPTR_PREFIX "x" #define PRIX8 "X" #define PRIX16 "X" #define PRIX32 "X" #define PRIX64 __PRI64_PREFIX "X" #define PRIXPTR __PRIPTR_PREFIX "X" #endif /*__INTTYPES_H*/ optee_os-4.3.0/lib/libutils/isoc/include/limits.h000066400000000000000000000020561464416617300220010ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __LIMITS_H #define __LIMITS_H #define CHAR_BIT __CHAR_BIT__ #ifdef __CHAR_UNSIGNED__ #define CHAR_MAX UCHAR_MAX #define CHAR_MIN 0 #else #define CHAR_MAX SCHAR_MAX #define CHAR_MIN SCHAR_MIN #endif #define INT_MAX __INT_MAX__ #define INT_MIN (-INT_MAX - 1) #define LONG_MAX __LONG_MAX__ #define LONG_MIN (-LONG_MAX - 1L) #define LLONG_MAX __LONG_LONG_MAX__ #define LLONG_MIN (-LLONG_MAX - 1LL) #define MB_LEN_MAX 1 #define SCHAR_MAX __SCHAR_MAX__ #define SCHAR_MIN (-SCHAR_MAX - 1) #define SHRT_MAX __SHRT_MAX__ #define SHRT_MIN (-SHRT_MAX - 1) #if __SCHAR_MAX__ == __INT_MAX__ #define UCHAR_MAX (SCHAR_MAX * 2U + 1U) #else #define UCHAR_MAX (SCHAR_MAX * 2 + 1) #endif #if __SHRT_MAX__ == __INT_MAX__ #define USHRT_MAX (SHRT_MAX * 2U + 1U) #else #define USHRT_MAX (SHRT_MAX * 2 + 1) #endif #define UINT_MAX (INT_MAX * 2U + 1U) #define ULONG_MAX (LONG_MAX * 2UL + 1UL) #define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) #endif /* __LIMITS_H */ optee_os-4.3.0/lib/libutils/isoc/include/malloc.h000066400000000000000000000117201464416617300217450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MALLOC_H #define __MALLOC_H #include #include #include /* * Due to bget implementation, the first memory pool registered shall have * a min size. Choose 1kB which is reasonable. */ #define MALLOC_INITIAL_POOL_MIN_SIZE 1024 void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); void *memalign(size_t alignment, size_t size); void free(void *ptr); #if __STDC_VERSION__ >= 201112L void *aligned_alloc(size_t alignment, size_t size); #endif #ifdef ENABLE_MDBG void *mdbg_malloc(const char *fname, int lineno, size_t size); void *mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size); void *mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size); void *mdbg_memalign(const char *fname, int lineno, size_t alignment, size_t size); #if __STDC_VERSION__ >= 201112L void *mdbg_aligned_alloc(const char *fname, int lineno, size_t alignment, size_t size); #endif void mdbg_check(int bufdump); #define malloc(size) mdbg_malloc(__FILE__, __LINE__, (size)) #define calloc(nmemb, size) \ mdbg_calloc(__FILE__, __LINE__, (nmemb), (size)) #define realloc(ptr, size) \ mdbg_realloc(__FILE__, __LINE__, (ptr), (size)) #define memalign(alignment, size) \ mdbg_memalign(__FILE__, __LINE__, (alignment), (size)) #if __STDC_VERSION__ >= 201112L #define aligned_alloc(alignment, size) \ mdbg_aligned_alloc(__FILE__, __LINE__, (alignment), (size)) #endif /* __STDC_VERSION__ */ #else #define mdbg_check(x) do { } while (0) #endif /* * Returns true if the supplied memory area is within a buffer * previously allocated (and not freed yet). * * Used internally by TAs */ bool malloc_buffer_is_within_alloced(void *buf, size_t len); /* * Returns true if the supplied memory area is overlapping the area used * for heap. * * Used internally by TAs */ bool malloc_buffer_overlaps_heap(void *buf, size_t len); /* * Adds a pool of memory to allocate from. */ void malloc_add_pool(void *buf, size_t len); #ifdef CFG_WITH_STATS /* Get/reset allocation statistics */ void malloc_get_stats(struct pta_stats_alloc *stats); void malloc_reset_stats(void); #endif /* CFG_WITH_STATS */ #ifdef CFG_NS_VIRTUALIZATION void nex_free(void *ptr); #ifdef ENABLE_MDBG void *nex_mdbg_malloc(const char *fname, int lineno, size_t size); void *nex_mdbg_calloc(const char *fname, int lineno, size_t nmemb, size_t size); void *nex_mdbg_realloc(const char *fname, int lineno, void *ptr, size_t size); void *nex_mdbg_memalign(const char *fname, int lineno, size_t alignment, size_t size); void nex_mdbg_check(int bufdump); #define nex_malloc(size) nex_mdbg_malloc(__FILE__, __LINE__, (size)) #define nex_calloc(nmemb, size) \ nex_mdbg_calloc(__FILE__, __LINE__, (nmemb), (size)) #define nex_realloc(ptr, size) \ nex_mdbg_realloc(__FILE__, __LINE__, (ptr), (size)) #define nex_memalign(alignment, size) \ nex_mdbg_memalign(__FILE__, __LINE__, (alignment), (size)) #else /* ENABLE_MDBG */ void *nex_malloc(size_t size); void *nex_calloc(size_t nmemb, size_t size); void *nex_realloc(void *ptr, size_t size); void *nex_memalign(size_t alignment, size_t size); #define nex_mdbg_check(x) do { } while (0) #endif /* ENABLE_MDBG */ bool nex_malloc_buffer_is_within_alloced(void *buf, size_t len); bool nex_malloc_buffer_overlaps_heap(void *buf, size_t len); void nex_malloc_add_pool(void *buf, size_t len); #ifdef CFG_WITH_STATS /* * Get/reset allocation statistics */ void nex_malloc_get_stats(struct pta_stats_alloc *stats); void nex_malloc_reset_stats(void); #endif /* CFG_WITH_STATS */ #else /* CFG_NS_VIRTUALIZATION */ #define nex_free(ptr) free(ptr) #define nex_malloc(size) malloc(size) #define nex_calloc(nmemb, size) calloc(nmemb, size) #define nex_realloc(ptr, size) realloc(ptr, size) #define nex_memalign(alignment, size) memalign(alignment, size) #endif /* CFG_NS_VIRTUALIZATION */ struct malloc_ctx; void *raw_memalign(size_t hdr_size, size_t ftr_size, size_t alignment, size_t pl_size, struct malloc_ctx *ctx); void *raw_malloc(size_t hdr_size, size_t ftr_size, size_t pl_size, struct malloc_ctx *ctx); void raw_free(void *ptr, struct malloc_ctx *ctx, bool wipe); void *raw_calloc(size_t hdr_size, size_t ftr_size, size_t pl_nmemb, size_t pl_size, struct malloc_ctx *ctx); void *raw_realloc(void *ptr, size_t hdr_size, size_t ftr_size, size_t pl_size, struct malloc_ctx *ctx); size_t raw_malloc_get_ctx_size(void); void raw_malloc_init_ctx(struct malloc_ctx *ctx); void raw_malloc_add_pool(struct malloc_ctx *ctx, void *buf, size_t len); bool raw_malloc_buffer_overlaps_heap(struct malloc_ctx *ctx, void *buf, size_t len); bool raw_malloc_buffer_is_within_alloced(struct malloc_ctx *ctx, void *buf, size_t len); #ifdef CFG_WITH_STATS void raw_malloc_get_stats(struct malloc_ctx *ctx, struct pta_stats_alloc *stats); #endif #endif /* __MALLOC_H */ optee_os-4.3.0/lib/libutils/isoc/include/memory.h000066400000000000000000000003011464416617300217770ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __MEMORY_H #define __MEMORY_H #include #endif /*__MEMORY_H*/ optee_os-4.3.0/lib/libutils/isoc/include/setjmp.h000066400000000000000000000050151464416617300220000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1994-2009 Red Hat, Inc. * Copyright (c) 2016, Linaro Limited * Copyright 2022-2023 NXP * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __SETJMP_H #define __SETJMP_H #include #if defined(ARM32) /* * All callee preserved registers: * v1 - v7, fp, ip, sp, lr, f4, f5, f6, f7 * One additional 32-bit value used in case ftrace * is enabled to restore ftrace return stack. */ #define _JBLEN 24 #define _JBTYPE int #endif #if defined(ARM64) #define _JBLEN 22 #define _JBTYPE long long #endif #if defined(RV64) || defined(RV32) /* * Callee preserved registers: * s0-s11, ra, sp * One additional value used in case ftrace * is enabled to restore ftrace return stack. */ #define _JBLEN 15 #define _JBTYPE unsigned long #endif #ifdef _JBLEN typedef _JBTYPE jmp_buf[_JBLEN]; #endif void __noreturn longjmp(jmp_buf env, int val); int setjmp(jmp_buf env); #ifdef CFG_FTRACE_SUPPORT void ftrace_longjmp(unsigned int *ret_idx); void ftrace_setjmp(unsigned int *ret_idx); #endif #endif /*__SETJMP_H*/ optee_os-4.3.0/lib/libutils/isoc/include/signal.h000066400000000000000000000002551464416617300217540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __SIGNAL_H #define __SIGNAL_H #endif /*__SIGNAL_H*/ optee_os-4.3.0/lib/libutils/isoc/include/stdint.h000066400000000000000000000117151464416617300220070ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include /* * This file provides what C99 standard requires in * 7.18 interger types */ #ifndef __STDINT_H #define __STDINT_H /* * If compiler supplies neither __ILP32__ or __LP64__, try to figure it out * here. */ #if !defined(__ILP32__) && !defined(__LP64__) #if defined(__SIZEOF_INT__) && defined(__SIZEOF_POINTER__) && \ defined(__SIZEOF_LONG__) #if __SIZEOF_INT__ == 4 && __SIZEOF_POINTER__ == 4 && __SIZEOF_LONG__ == 4 #define __ILP32__ 1 #endif #if __SIZEOF_INT__ == 4 && __SIZEOF_POINTER__ == 8 && __SIZEOF_LONG__ == 8 #define __LP64__ 1 #endif #endif #endif /* !defined(__ILP32__) && !defined(__LP64__) */ #if !defined(__ILP32__) && !defined(__LP64__) #error Neither __ILP32__ nor __LP64__ is defined #endif #ifndef __ASSEMBLER__ /* 7.18.1.1 Exact-width interger types */ #ifndef __int8_t_defined # define __int8_t_defined typedef signed char int8_t; typedef short int int16_t; typedef int int32_t; #ifdef __ILP32__ __extension__ typedef long long int int64_t; #endif /*__ILP32__*/ #ifdef __LP64__ typedef long int int64_t; #endif /*__LP64__*/ #endif /* Unsigned. */ typedef unsigned char uint8_t; typedef unsigned short int uint16_t; #ifndef __uint32_t_defined typedef unsigned int uint32_t; # define __uint32_t_defined #endif #ifdef __ILP32__ __extension__ typedef unsigned long long int uint64_t; #endif /*__ILP32__*/ #ifdef __LP64__ typedef unsigned long int uint64_t; #endif /*__LP64__*/ /* 7.18.1.2 Minimum-width integer types */ typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; /* 7.18.1.3 Fastest minimum-width integer types */ typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; /* 7.18.1.4 Integer types capable of holding object pointers */ typedef long intptr_t; typedef unsigned long uintptr_t; typedef int64_t intmax_t; typedef uint64_t uintmax_t; #endif /*__ASSEMBLER__*/ /* * 7.18.2 Limits of specified-width integer types */ /* 7.18.2.1 Limits of exact-width interger types */ #define INT8_MIN (-0x7f-1) #define INT16_MIN (-0x7fff-1) #define INT32_MIN (-0x7fffffff-1) #define INT64_MIN (-0x7fffffffffffffffL-1) #define INT8_MAX 0x7f #define INT16_MAX 0x7fff #define INT32_MAX 0x7fffffff #define INT64_MAX 0x7fffffffffffffffL #define UINT8_MAX 0xff #define UINT16_MAX 0xffff #define UINT32_MAX 0xffffffffU #define UINT64_MAX 0xffffffffffffffffUL /* 7.18.2.2 Limits of minimum-width integer types */ #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX /* 7.18.2.3 Limits of fastest minimum-width integer types */ #define INT_FAST8_MIN INT8_MIN #define INT_FAST16_MIN INT16_MIN #define INT_FAST32_MIN INT32_MIN #define INT_FAST64_MIN INT64_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX /* 7.18.2.4 Limits of integer types capable of holding object pointers */ #define INTPTR_MIN LONG_MIN #define INTPTR_MAX LONG_MAX #define UINTPTR_MAX ULONG_MAX /* 7.18.2.5 Limits of greatest-width integer types */ #define INTMAX_MAX INT64_MAX #define INTMAX_MIN INT64_MIN #define UINTMAX_MAX UINT64_MAX /* 7.18.3 Limits of other integer types */ #define SIZE_MAX ULONG_MAX /* * 7.18.4 Macros for integer constants */ #ifdef __ASSEMBLER__ #define U(v) v #define UL(v) v #define ULL(v) v #define L(v) v #define LL(v) v #else #define U(v) v ## U #define UL(v) v ## UL #define ULL(v) v ## ULL #define L(v) v ## L #define LL(v) v ## LL #endif /* 7.18.4.1 Macros for minimum-width integer constants */ #define INT8_C(v) v #define UINT8_C(v) v #define INT16_C(v) v #define UINT16_C(v) v #define INT32_C(v) v #define UINT32_C(v) U(v) #ifdef __ILP32__ #define INT64_C(v) LL(v) #define UINT64_C(v) ULL(v) #endif #ifdef __LP64__ #define INT64_C(v) L(v) #define UINT64_C(v) UL(v) #endif #define UINTPTR_C(v) UL(v) /* 7.18.4.2 Macros for greatest-width integer constants */ #define INTMAX_C(v) INT64_C(v) #define UINTMAX_C(v) UINT64_C(v) #endif /* __STDINT_H */ optee_os-4.3.0/lib/libutils/isoc/include/stdio.h000066400000000000000000000026231464416617300216220ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __STDIO_H #define __STDIO_H #include #include typedef struct _FILE FILE; int printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); /* sprintf() is unsafe and should not be used. Prefer snprintf(). */ int sprintf(char *str, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))) __attribute__ ((deprecated)); int snprintf(char *str, size_t size, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 3, 4))); int vsnprintf (char *str, size_t size, const char *fmt, va_list ap) __attribute__ ((__format__ (__printf__, 3, 0))); int __sprintf_chk(char *str, int flag, size_t slen, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 4, 5))); int puts(const char *str); int putchar(int c); #ifndef __KERNEL__ extern FILE *stdout; extern FILE *stderr; /* * The functions below send their output synchronously to the secure console. * They treat stdout and stderr the same, and will abort if stream is not one or * the other. */ int fputc(int c, FILE *stream); int fputs(const char *s, FILE *stream); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); #endif #endif /*__STDIO_H*/ optee_os-4.3.0/lib/libutils/isoc/include/stdlib.h000066400000000000000000000012771464416617300217650ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* * This file provides what C99 standard requires for in * 7.20.3 Memory management functions */ #ifndef __STDLIB_H #define __STDLIB_H #include #include #include void qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)); void abort(void) __noreturn; int abs(int i); /* The largest number returned by rand() */ #define RAND_MAX __INT_MAX__ int rand(void); unsigned long _strtoul (const char *nptr, char **endptr, int base); unsigned long strtoul (const char *s, char **ptr, int base); #endif /* __STDLIB_H */ optee_os-4.3.0/lib/libutils/isoc/include/string.h000066400000000000000000000021251464416617300220030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ /* * This file provides what C99 standard requires for * for some functions */ #ifndef __STRING_H #define __STRING_H #include #include void *memcpy(void *__restrict s1, const void *__restrict s2, size_t n); void *memmove(void *s1, const void *s2, size_t n); int memcmp(const void *s1, const void *s2, size_t n); void *memset(void *s, int c, size_t n); int strcmp(const char *s1, const char *s2); int strncmp(const char *s1, const char *s2, size_t n); size_t strlen(const char *s); size_t strnlen(const char *s, size_t n); char *strdup(const char *s); char *strndup(const char *s, size_t n); char *strchr(const char *s, int c); char *strstr(const char *big, const char *little); char *strcpy(char *dest, const char *src); char *strncpy(char *dest, const char *src, size_t n); char *strrchr(const char *s, int i); char *strtok_r(char *str, const char *delim, char **saveptr); void *memchr(const void *buf, int c, size_t length); #endif /* __STRING_H */ optee_os-4.3.0/lib/libutils/isoc/include/strings.h000066400000000000000000000003161464416617300221660ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #ifndef __STRINGS_H #define __STRINGS_H int bcmp(const void *s1, const void *s2, size_t n); #endif /*__STRINGS_H*/ optee_os-4.3.0/lib/libutils/isoc/include/sys/000077500000000000000000000000001464416617300211425ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/include/sys/cdefs.h000066400000000000000000000013051464416617300223760ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef SYS_CDEFS_H #define SYS_CDEFS_H /* * GCC 2.95 provides `__restrict' as an extension to C90 to support the * C99-specific `restrict' type qualifier. We happen to use `__restrict' as * a way to define the `restrict' type qualifier without disturbing older * software that is unaware of C99 keywords. */ #if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95) #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 || defined(lint) #define __restrict #else #define __restrict restrict #endif #endif #define __always_inline __attribute__((always_inline)) inline #endif /*SYS_CDEFS_H*/ optee_os-4.3.0/lib/libutils/isoc/include/sys/fcntl.h000066400000000000000000000011341464416617300224200ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved. */ #ifndef _SYS_FCNTL_H_ #define _SYS_FCNTL_H_ #define _FAPPEND 0x0008 /* append (writes guaranteed at the end) */ #define _FCREAT 0x0200 /* open with file create */ #define _FTRUNC 0x0400 /* open with truncation */ /* * Flag values for open(2) and fcntl(2) */ #define O_RDONLY 0 /* +1 == FREAD */ #define O_WRONLY 1 /* +1 == FWRITE */ #define O_RDWR 2 /* +1 == FREAD|FWRITE */ #define O_APPEND _FAPPEND #define O_CREAT _FCREAT #define O_TRUNC _FTRUNC #endif /* _SYS_FCNTL_H_ */ optee_os-4.3.0/lib/libutils/isoc/include/sys/queue.h000066400000000000000000000622671464416617300224540ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* $NetBSD: queue.h,v 1.49.6.1 2008/11/20 03:22:38 snj Exp $ */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ #ifndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ /*#include */ /* * This file defines five types of data structures: singly-linked lists, * lists, simple queues, tail queues, and circular queues. * * A singly-linked list is headed by a single forward pointer. The * elements are singly linked for minimum space and pointer manipulation * overhead at the expense of O(n) removal for arbitrary elements. New * elements can be added to the list after an existing element or at the * head of the list. Elements being removed from the head of the list * should use the explicit macro for this purpose for optimum * efficiency. A singly-linked list may only be traversed in the forward * direction. Singly-linked lists are ideal for applications with large * datasets and few or no removals or for implementing a LIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A simple queue is headed by a pair of pointers, one the head of the * list and the other to the tail of the list. The elements are singly * linked to save space, so elements can only be removed from the * head of the list. New elements can be added to the list after * an existing element, at the head of the list, or at the end of the * list. A simple queue may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * A circle queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the list. * A circle queue may be traversed in either direction, but has a more * complex end of list detection. * * For details on the use of these macros, see the queue(3) manual page. */ /* * List definitions. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List functions. */ #if defined(_KERNEL) && defined(QUEUEDEBUG) #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ if ((head)->lh_first && \ (head)->lh_first->field.le_prev != &(head)->lh_first) \ panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); #define QUEUEDEBUG_LIST_OP(elm, field) \ if ((elm)->field.le_next && \ (elm)->field.le_next->field.le_prev != \ &(elm)->field.le_next) \ panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ if (*(elm)->field.le_prev != (elm)) \ panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__); #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ (elm)->field.le_next = (void *)1L; \ (elm)->field.le_prev = (void *)1L; #else #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) #define QUEUEDEBUG_LIST_OP(elm, field) #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) #endif #define LIST_INIT(head) do { \ (head)->lh_first = NULL; \ } while (/* CONSTCOND */0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ QUEUEDEBUG_LIST_OP((listelm), field) \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (/* CONSTCOND */0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ QUEUEDEBUG_LIST_OP((listelm), field) \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (/* CONSTCOND */0) #define LIST_INSERT_HEAD(head, elm, field) do { \ QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (/* CONSTCOND */0) #define LIST_REMOVE(elm, field) do { \ QUEUEDEBUG_LIST_OP((elm), field) \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ } while (/* CONSTCOND */0) #define LIST_FOREACH(var, head, field) \ for ((var) = ((head)->lh_first); \ (var); \ (var) = ((var)->field.le_next)) /* * List access methods. */ #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) #define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) /* * Singly-linked List definitions. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List functions. */ #define SLIST_INIT(head) do { \ (head)->slh_first = NULL; \ } while (/* CONSTCOND */0) #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (/* CONSTCOND */0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (/* CONSTCOND */0) #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (/* CONSTCOND */0) #define SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = (head)->slh_first; \ while(curelm->field.sle_next != (elm)) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ } \ } while (/* CONSTCOND */0) #define SLIST_REMOVE_AFTER(slistelm, field) do { \ (slistelm)->field.sle_next = \ SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \ } while (/* CONSTCOND */0) #define SLIST_FOREACH(var, head, field) \ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) /* * Singly-linked List access methods. */ #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) /* * Singly-linked Tail queue declarations. */ #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first; /* first element */ \ struct type **stqh_last; /* addr of last next element */ \ } #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } /* * Singly-linked Tail queue functions. */ #define STAILQ_INIT(head) do { \ (head)->stqh_first = NULL; \ (head)->stqh_last = &(head)->stqh_first; \ } while (/* CONSTCOND */0) #define STAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ (head)->stqh_last = &(elm)->field.stqe_next; \ (head)->stqh_first = (elm); \ } while (/* CONSTCOND */0) #define STAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.stqe_next = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &(elm)->field.stqe_next; \ } while (/* CONSTCOND */0) #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ (head)->stqh_last = &(elm)->field.stqe_next; \ (listelm)->field.stqe_next = (elm); \ } while (/* CONSTCOND */0) #define STAILQ_REMOVE_HEAD(head, field) do { \ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ (head)->stqh_last = &(head)->stqh_first; \ } while (/* CONSTCOND */0) #define STAILQ_REMOVE(head, elm, type, field) do { \ if ((head)->stqh_first == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->stqh_first; \ while (curelm->field.stqe_next != (elm)) \ curelm = curelm->field.stqe_next; \ if ((curelm->field.stqe_next = \ curelm->field.stqe_next->field.stqe_next) == NULL) \ (head)->stqh_last = &(curelm)->field.stqe_next; \ } \ } while (/* CONSTCOND */0) #define STAILQ_REMOVE_AFTER(head, elm, field) do { \ if ((STAILQ_NEXT(elm, field) = \ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) #define STAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->stqh_first); \ (var); \ (var) = ((var)->field.stqe_next)) #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_INIT((head2)); \ } \ } while (/* CONSTCOND */0) /* * Singly-linked Tail queue access methods. */ #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define STAILQ_FIRST(head) ((head)->stqh_first) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) /* * Simple queue definitions. */ #define SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } #define SIMPLEQ_HEAD_INITIALIZER(head) \ { NULL, &(head).sqh_first } #define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } /* * Simple queue functions. */ #define SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (/* CONSTCOND */0) #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ (head)->sqh_first = (elm); \ } while (/* CONSTCOND */0) #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (/* CONSTCOND */0) #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ (head)->sqh_last = &(elm)->field.sqe_next; \ (listelm)->field.sqe_next = (elm); \ } while (/* CONSTCOND */0) #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ (head)->sqh_last = &(head)->sqh_first; \ } while (/* CONSTCOND */0) #define SIMPLEQ_REMOVE(head, elm, type, field) do { \ if ((head)->sqh_first == (elm)) { \ SIMPLEQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->sqh_first; \ while (curelm->field.sqe_next != (elm)) \ curelm = curelm->field.sqe_next; \ if ((curelm->field.sqe_next = \ curelm->field.sqe_next->field.sqe_next) == NULL) \ (head)->sqh_last = &(curelm)->field.sqe_next; \ } \ } while (/* CONSTCOND */0) #define SIMPLEQ_FOREACH(var, head, field) \ for ((var) = ((head)->sqh_first); \ (var); \ (var) = ((var)->field.sqe_next)) /* * Simple queue access methods. */ #define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) #define SIMPLEQ_FIRST(head) ((head)->sqh_first) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) /* * Tail queue definitions. */ #define _TAILQ_HEAD(name, type, qual) \ struct name { \ qual type *tqh_first; /* first element */ \ qual type *qual *tqh_last; /* addr of last next element */ \ } #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define _TAILQ_ENTRY(type, qual) \ struct { \ qual type *tqe_next; /* next element */ \ qual type *qual *tqe_prev; /* address of previous next element */\ } #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) /* * Tail queue functions. */ #if defined(_KERNEL) && defined(QUEUEDEBUG) #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ if ((head)->tqh_first && \ (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ if (*(head)->tqh_last != NULL) \ panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_OP(elm, field) \ if ((elm)->field.tqe_next && \ (elm)->field.tqe_next->field.tqe_prev != \ &(elm)->field.tqe_next) \ panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ if (*(elm)->field.tqe_prev != (elm)) \ panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ if ((elm)->field.tqe_next == NULL && \ (head)->tqh_last != &(elm)->field.tqe_next) \ panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \ (head), (elm), __FILE__, __LINE__); #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ (elm)->field.tqe_next = (void *)1L; \ (elm)->field.tqe_prev = (void *)1L; #else #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) #define QUEUEDEBUG_TAILQ_OP(elm, field) #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) #endif #define TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } while (/* CONSTCOND */0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (/* CONSTCOND */0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (/* CONSTCOND */0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ QUEUEDEBUG_TAILQ_OP((listelm), field) \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (/* CONSTCOND */0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ QUEUEDEBUG_TAILQ_OP((listelm), field) \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (/* CONSTCOND */0) #define TAILQ_REMOVE(head, elm, field) do { \ QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ QUEUEDEBUG_TAILQ_OP((elm), field) \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ } while (/* CONSTCOND */0) #define TAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->tqh_first); \ (var); \ (var) = ((var)->field.tqe_next)) #define TAILQ_FOREACH_SAFE(var, head, field, next) \ for ((var) = ((head)->tqh_first); \ (var) != NULL && ((next) = TAILQ_NEXT(var, field), 1); \ (var) = (next)) #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ (var); \ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ for ((var) = TAILQ_LAST((head), headname); \ (var) && ((prev) = TAILQ_PREV((var), headname, field), 1);\ (var) = (prev)) #define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \ TAILQ_INIT((head2)); \ } \ } while (/* CONSTCOND */0) /* * Tail queue access methods. */ #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) /* * Circular queue definitions. */ #if defined(_KERNEL) && defined(QUEUEDEBUG) #define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \ if ((head)->cqh_first != (void *)(head) && \ (head)->cqh_first->field.cqe_prev != (void *)(head)) \ panic("CIRCLEQ head forw %p %s:%d", (head), \ __FILE__, __LINE__); \ if ((head)->cqh_last != (void *)(head) && \ (head)->cqh_last->field.cqe_next != (void *)(head)) \ panic("CIRCLEQ head back %p %s:%d", (head), \ __FILE__, __LINE__); #define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \ if ((elm)->field.cqe_next == (void *)(head)) { \ if ((head)->cqh_last != (elm)) \ panic("CIRCLEQ elm last %p %s:%d", (elm), \ __FILE__, __LINE__); \ } else { \ if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \ panic("CIRCLEQ elm forw %p %s:%d", (elm), \ __FILE__, __LINE__); \ } \ if ((elm)->field.cqe_prev == (void *)(head)) { \ if ((head)->cqh_first != (elm)) \ panic("CIRCLEQ elm first %p %s:%d", (elm), \ __FILE__, __LINE__); \ } else { \ if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \ panic("CIRCLEQ elm prev %p %s:%d", (elm), \ __FILE__, __LINE__); \ } #define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \ (elm)->field.cqe_next = (void *)1L; \ (elm)->field.cqe_prev = (void *)1L; #else #define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) #define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) #define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) #endif #define CIRCLEQ_HEAD(name, type) \ struct name { \ struct type *cqh_first; /* first element */ \ struct type *cqh_last; /* last element */ \ } #define CIRCLEQ_HEAD_INITIALIZER(head) \ { (void *)&head, (void *)&head } #define CIRCLEQ_ENTRY(type) \ struct { \ struct type *cqe_next; /* next element */ \ struct type *cqe_prev; /* previous element */ \ } /* * Circular queue functions. */ #define CIRCLEQ_INIT(head) do { \ (head)->cqh_first = (void *)(head); \ (head)->cqh_last = (void *)(head); \ } while (/* CONSTCOND */0) #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ (elm)->field.cqe_prev = (listelm); \ if ((listelm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ (listelm)->field.cqe_next = (elm); \ } while (/* CONSTCOND */0) #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ (elm)->field.cqe_next = (listelm); \ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ if ((listelm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ (listelm)->field.cqe_prev = (elm); \ } while (/* CONSTCOND */0) #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ (elm)->field.cqe_next = (head)->cqh_first; \ (elm)->field.cqe_prev = (void *)(head); \ if ((head)->cqh_last == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (head)->cqh_first->field.cqe_prev = (elm); \ (head)->cqh_first = (elm); \ } while (/* CONSTCOND */0) #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ (elm)->field.cqe_next = (void *)(head); \ (elm)->field.cqe_prev = (head)->cqh_last; \ if ((head)->cqh_first == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (head)->cqh_last->field.cqe_next = (elm); \ (head)->cqh_last = (elm); \ } while (/* CONSTCOND */0) #define CIRCLEQ_REMOVE(head, elm, field) do { \ QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \ if ((elm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm)->field.cqe_prev; \ else \ (elm)->field.cqe_next->field.cqe_prev = \ (elm)->field.cqe_prev; \ if ((elm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm)->field.cqe_next; \ else \ (elm)->field.cqe_prev->field.cqe_next = \ (elm)->field.cqe_next; \ QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \ } while (/* CONSTCOND */0) #define CIRCLEQ_FOREACH(var, head, field) \ for ((var) = ((head)->cqh_first); \ (var) != (const void *)(head); \ (var) = ((var)->field.cqe_next)) #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ for ((var) = ((head)->cqh_last); \ (var) != (const void *)(head); \ (var) = ((var)->field.cqe_prev)) /* * Circular queue access methods. */ #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) #define CIRCLEQ_FIRST(head) ((head)->cqh_first) #define CIRCLEQ_LAST(head) ((head)->cqh_last) #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) #define CIRCLEQ_LOOP_NEXT(head, elm, field) \ (((elm)->field.cqe_next == (void *)(head)) \ ? ((head)->cqh_first) \ : (elm->field.cqe_next)) #define CIRCLEQ_LOOP_PREV(head, elm, field) \ (((elm)->field.cqe_prev == (void *)(head)) \ ? ((head)->cqh_last) \ : (elm->field.cqe_prev)) #endif /* !_SYS_QUEUE_H_ */ optee_os-4.3.0/lib/libutils/isoc/include/sys/types.h000066400000000000000000000003101464416617300224510ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef SYS_TYPES_H #define SYS_TYPES_H #include #endif /*SYS_TYPES_H*/ optee_os-4.3.0/lib/libutils/isoc/include/time.h000066400000000000000000000003511464416617300214320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __TIME_H #define __TIME_H #include #include typedef int64_t time_t; #endif /*__TIME_H*/ optee_os-4.3.0/lib/libutils/isoc/include/unistd.h000066400000000000000000000005741464416617300220110ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __UNISTD_H #define __UNISTD_H #include #include #define __ssize_t_defined typedef intptr_t ssize_t; /* @fd must be 1 or 2. Writes to the secure console. */ ssize_t write(int fd, const void *buf, size_t count); #endif /* __UNISTD_H */ optee_os-4.3.0/lib/libutils/isoc/include/wchar.h000066400000000000000000000002521464416617300216000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #ifndef __WCHAR_H #define __WCHAR_H #endif /*__WCHAR_H*/ optee_os-4.3.0/lib/libutils/isoc/isalnum.c000066400000000000000000000002351464416617300205150ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int isalnum(int c) { return isalpha(c) || isdigit(c); } optee_os-4.3.0/lib/libutils/isoc/isalpha.c000066400000000000000000000003321464416617300204640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include int isalpha(int c) { if (c >= 'A' && c <= 'Z') return 1; if (c >= 'a' && c <= 'z') return 1; return 0; } optee_os-4.3.0/lib/libutils/isoc/iscntrl.c000066400000000000000000000002531464416617300205230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int iscntrl(int c) { if (c < 0x20 || c == 0x7f) return 1; return 0; } optee_os-4.3.0/lib/libutils/isoc/isdigit.c000066400000000000000000000002631464416617300205020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include int isdigit(int c) { if (c >= '0' && c <= '9') return 1; return 0; } optee_os-4.3.0/lib/libutils/isoc/isgraph.c000066400000000000000000000002531464416617300205020ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int isgraph(int c) { if (c >= 0x21 && c < 0x7f) return 1; return 0; } optee_os-4.3.0/lib/libutils/isoc/islower.c000066400000000000000000000002301464416617300205240ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int islower(int c) { return (c >= 'a' && c <= 'z'); } optee_os-4.3.0/lib/libutils/isoc/isprint.c000066400000000000000000000002531464416617300205350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int isprint(int c) { if (c >= 0x20 && c < 0x7f) return 1; return 0; } optee_os-4.3.0/lib/libutils/isoc/ispunct.c000066400000000000000000000002361464416617300205330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int ispunct(int c) { return isgraph(c) && !isalnum(c); } optee_os-4.3.0/lib/libutils/isoc/isspace.c000066400000000000000000000002251464416617300204730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include int isspace(int c) { return (c == ' '); } optee_os-4.3.0/lib/libutils/isoc/isupper.c000066400000000000000000000002411464416617300205310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include int isupper(int c) { return (c >= 'A' && c <= 'Z'); } optee_os-4.3.0/lib/libutils/isoc/isxdigit.c000066400000000000000000000003701464416617300206710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018, Linaro Limited */ #include int isxdigit(int c) { if (isdigit(c)) return 1; if (c >= 'A' && c <= 'F') return 1; if (c >= 'a' && c <= 'f') return 1; return 0; } optee_os-4.3.0/lib/libutils/isoc/newlib/000077500000000000000000000000001464416617300201615ustar00rootroot00000000000000optee_os-4.3.0/lib/libutils/isoc/newlib/_ansi.h000066400000000000000000000076131464416617300214320ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Provide support for both ANSI and non-ANSI environments. */ /* Some ANSI environments are "broken" in the sense that __STDC__ cannot be relied upon to have it's intended meaning. Therefore we must use our own concoction: _HAVE_STDC. Always use _HAVE_STDC instead of __STDC__ in newlib sources! To get a strict ANSI C environment, define macro __STRICT_ANSI__. This will "comment out" the non-ANSI parts of the ANSI header files (non-ANSI header files aren't affected). */ #ifndef _ANSIDECL_H_ #define _ANSIDECL_H_ /*#include */ /*#include */ /* * First try to figure out whether we really are in an ANSI C environment. * This probably needs some work. Perhaps sys/config.h can be * prevailed upon to give us a clue. */ #ifdef __STDC__ #define _HAVE_STDC #endif #ifdef _HAVE_STDC #define _PTR void * #define _AND , #define _NOARGS void #define _CONST const #define _VOLATILE volatile #define _SIGNED signed #define _DOTS , ... #define _VOID void #ifdef __CYGWIN__ #define _EXFUN(name, proto) __cdecl name proto #define _EXPARM(name, proto) (* __cdecl name) proto #else #define _EXFUN(name, proto) name proto #define _EXPARM(name, proto) (* name) proto #endif #define _DEFUN(name, arglist, args) name(args) #define _DEFUN_VOID(name) name(_NOARGS) #define _CAST_VOID (void) #ifndef _LONG_DOUBLE #define _LONG_DOUBLE long double #endif #ifndef _PARAMS #define _PARAMS(paramlist) paramlist #endif #else #define _PTR char * #define _AND ; #define _NOARGS #define _CONST #define _VOLATILE #define _SIGNED #define _DOTS #define _VOID void #define _EXFUN(name, proto) name() #define _DEFUN(name, arglist, args) name arglist args; #define _DEFUN_VOID(name) name() #define _CAST_VOID #define _LONG_DOUBLE double #ifndef _PARAMS #define _PARAMS(paramlist) () #endif #endif /* Support gcc's __attribute__ facility. */ #ifdef __GNUC__ #define _ATTRIBUTE(attrs) __attribute__ (attrs) #else #define _ATTRIBUTE(attrs) #endif /* ISO C++. */ #ifdef __cplusplus #if !(defined(_BEGIN_STD_C) && defined(_END_STD_C)) #ifdef _HAVE_STD_CXX #define _BEGIN_STD_C namespace std { extern "C" { #define _END_STD_C } } #else #define _BEGIN_STD_C extern "C" { #define _END_STD_C } #endif #endif #else #define _BEGIN_STD_C #define _END_STD_C #endif #endif /* _ANSIDECL_H_ */ optee_os-4.3.0/lib/libutils/isoc/newlib/abs.c000066400000000000000000000044561464416617300211030ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---integer absolute value (magnitude) INDEX abs ANSI_SYNOPSIS #include int abs(int <[i]>); TRAD_SYNOPSIS #include int abs(<[i]>) int <[i]>; DESCRIPTION <> returns @tex $|x|$, @end tex the absolute value of <[i]> (also called the magnitude of <[i]>). That is, if <[i]> is negative, the result is the opposite of <[i]>, but if <[i]> is nonnegative the result is <[i]>. The similar function <> uses and returns <> rather than <> values. RETURNS The result is a nonnegative integer. PORTABILITY <> is ANSI. No supporting OS subroutines are required. */ #include "_ansi.h" #include int _DEFUN (abs, (i), int i) { return (i < 0) ? -i : i; } optee_os-4.3.0/lib/libutils/isoc/newlib/bcmp.c000066400000000000000000000014561464416617300212540ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* FUNCTION <>---compare two memory areas INDEX bcmp SYNOPSIS #include int bcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); DESCRIPTION This function compares not more than <[n]> bytes of the object pointed to by <[s1]> with the object pointed to by <[s2]>. This function is identical to <>. RETURNS The function returns an integer greater than, equal to or less than zero according to whether the object pointed to by <[s1]> is greater than, equal to or less than the object pointed to by <[s2]>. PORTABILITY <> requires no supporting OS subroutines. QUICKREF bcmp ansi pure */ #include #include int bcmp (const void *m1, const void *m2, size_t n) { return memcmp (m1, m2, n); } optee_os-4.3.0/lib/libutils/isoc/newlib/memchr.c000066400000000000000000000113211464416617300215760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---find character in memory INDEX memchr ANSI_SYNOPSIS #include void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>); TRAD_SYNOPSIS #include void *memchr(<[src]>, <[c]>, <[length]>) void *<[src]>; void *<[c]>; size_t <[length]>; DESCRIPTION This function searches memory starting at <<*<[src]>>> for the character <[c]>. The search only ends with the first occurrence of <[c]>, or after <[length]> characters; in particular, <> does not terminate the search. RETURNS If the character <[c]> is found within <[length]> characters of <<*<[src]>>>, a pointer to the character is returned. If <[c]> is not found, then <> is returned. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memchr ansi pure */ #include "_ansi.h" #include #include /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X) ((long)X & (sizeof(long) - 1)) /* How many bytes are loaded each iteration of the word copy loop. */ #define LBLOCKSIZE (sizeof(long)) /* Threshhold for punting to the bytewise iterator. */ #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) #else #if LONG_MAX == 9223372036854775807L /* Nonzero if X (a long int) contains a NULL byte. */ #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 0x8080808080808080UL) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif /* DETECTCHAR returns nonzero if (long)X contains the byte used to fill (long)MASK. */ #define DETECTCHAR(X, MASK) (DETECTNULL(X ^ MASK)) _PTR _DEFUN(memchr, (src_void, c, length), _CONST _PTR src_void _AND int c _AND size_t length) { _CONST unsigned char *src = (_CONST unsigned char *)src_void; unsigned char d = c; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long *asrc; unsigned long mask; int i; while (UNALIGNED(src)) { if (!length--) return NULL; if (*src == d) return (void *)src; src++; } if (!TOO_SMALL(length)) { /* If we get this far, we know that length is large and src is word-aligned. */ /* The fast code reads the source one word at a time and only performs the bytewise search on word-sized segments if they contain the search character, which is detected by XORing the word-sized segment with a word-sized block of the search character and then detecting for the presence of NUL in the result. */ asrc = (unsigned long *)src; mask = d << 8 | d; mask = mask << 16 | mask; for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) mask = (mask << i) | mask; while (length >= LBLOCKSIZE) { if (DETECTCHAR(*asrc, mask)) break; length -= LBLOCKSIZE; asrc++; } /* If there are fewer than LBLOCKSIZE characters left, then we resort to the bytewise loop. */ src = (unsigned char *)asrc; } #endif /* not PREFER_SIZE_OVER_SPEED */ while (length--) { if (*src == d) return (void *)src; src++; } return NULL; } optee_os-4.3.0/lib/libutils/isoc/newlib/memcmp.c000066400000000000000000000075221464416617300216110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---compare two memory areas INDEX memcmp ANSI_SYNOPSIS #include int memcmp(const void *<[s1]>, const void *<[s2]>, size_t <[n]>); TRAD_SYNOPSIS #include int memcmp(<[s1]>, <[s2]>, <[n]>) void *<[s1]>; void *<[s2]>; size_t <[n]>; DESCRIPTION This function compares not more than <[n]> characters of the object pointed to by <[s1]> with the object pointed to by <[s2]>. RETURNS The function returns an integer greater than, equal to or less than zero according to whether the object pointed to by <[s1]> is greater than, equal to or less than the object pointed to by <[s2]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memcmp ansi pure */ #include "_ansi.h" #include /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) /* How many bytes are copied each iteration of the word copy loop. */ #define LBLOCKSIZE (sizeof(long)) /* Threshhold for punting to the byte copier. */ #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) int _DEFUN(memcmp, (m1, m2, n), _CONST _PTR m1 _AND _CONST _PTR m2 _AND size_t n) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) unsigned char *s1 = (unsigned char *)m1; unsigned char *s2 = (unsigned char *)m2; while (n--) { if (*s1 != *s2) return *s1 - *s2; s1++; s2++; } return 0; #else unsigned char *s1 = (unsigned char *)m1; unsigned char *s2 = (unsigned char *)m2; unsigned long *a1; unsigned long *a2; /* If the size is too small, or either pointer is unaligned, then we punt to the byte compare loop. Hopefully this will not turn up in inner loops. */ if (!TOO_SMALL(n) && !UNALIGNED(s1, s2)) { /* * Otherwise, load and compare the blocks of memory one word at * a time. */ a1 = (unsigned long *)s1; a2 = (unsigned long *)s2; while (n >= LBLOCKSIZE) { if (*a1 != *a2) break; a1++; a2++; n -= LBLOCKSIZE; } /* check m mod LBLOCKSIZE remaining characters */ s1 = (unsigned char *)a1; s2 = (unsigned char *)a2; } while (n--) { if (*s1 != *s2) return *s1 - *s2; s1++; s2++; } return 0; #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/memcpy.c000066400000000000000000000077051464416617300216300ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---copy memory regions ANSI_SYNOPSIS #include void* memcpy(void *<[out]>, const void *<[in]>, size_t <[n]>); TRAD_SYNOPSIS #include void *memcpy(<[out]>, <[in]>, <[n]> void *<[out]>; void *<[in]>; size_t <[n]>; DESCRIPTION This function copies <[n]> bytes from the memory region pointed to by <[in]> to the memory region pointed to by <[out]>. If the regions overlap, the behavior is undefined. RETURNS <> returns a pointer to the first byte of the <[out]> region. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memcpy ansi pure */ #include "_ansi.h" #include /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) /* How many bytes are copied each iteration of the 4X unrolled loop. */ #define BIGBLOCKSIZE (sizeof(long) << 2) /* How many bytes are copied each iteration of the word copy loop. */ #define LITTLEBLOCKSIZE (sizeof(long)) /* Threshhold for punting to the byte copier. */ #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) _PTR _DEFUN(memcpy, (dst0, src0, len0), _PTR dst0 _AND _CONST _PTR src0 _AND size_t len0) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *dst = (char *)dst0; char *src = (char *)src0; _PTR save = dst0; while (len0--) *dst++ = *src++; return save; #else char *dst = dst0; _CONST char *src = src0; long *aligned_dst; _CONST long *aligned_src; /* If the size is small, or either SRC or DST is unaligned, then punt into the byte copy loop. This should be rare. */ if (!TOO_SMALL(len0) && !UNALIGNED(src, dst)) { aligned_dst = (long *)dst; aligned_src = (long *)src; /* Copy 4X long words at a time if possible. */ while (len0 >= BIGBLOCKSIZE) { *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; len0 -= BIGBLOCKSIZE; } /* Copy one long word at a time if possible. */ while (len0 >= LITTLEBLOCKSIZE) { *aligned_dst++ = *aligned_src++; len0 -= LITTLEBLOCKSIZE; } /* Pick up any residual with a byte copier. */ dst = (char *)aligned_dst; src = (char *)aligned_src; } while (len0--) *dst++ = *src++; return dst0; #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/memmove.c000066400000000000000000000110601464416617300217700ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---move possibly overlapping memory INDEX memmove ANSI_SYNOPSIS #include void *memmove(void *<[dst]>, const void *<[src]>, size_t <[length]>); TRAD_SYNOPSIS #include void *memmove(<[dst]>, <[src]>, <[length]>) void *<[dst]>; void *<[src]>; size_t <[length]>; DESCRIPTION This function moves <[length]> characters from the block of memory starting at <<*<[src]>>> to the memory starting at <<*<[dst]>>>. <> reproduces the characters correctly at <<*<[dst]>>> even if the two areas overlap. RETURNS The function returns <[dst]> as passed. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memmove ansi pure */ #include #include "_ansi.h" #include #include /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) /* How many bytes are copied each iteration of the 4X unrolled loop. */ #define BIGBLOCKSIZE (sizeof(long) << 2) /* How many bytes are copied each iteration of the word copy loop. */ #define LITTLEBLOCKSIZE (sizeof(long)) /* Threshhold for punting to the byte copier. */ #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE) /* SUPPRESS 20 */ _PTR _DEFUN(memmove, (dst_void, src_void, length), _PTR dst_void _AND _CONST _PTR src_void _AND size_t length) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *dst = dst_void; _CONST char *src = src_void; if (src < dst && dst < src + length) { /* Have to copy backwards */ src += length; dst += length; while (length--) *--dst = *--src; } else { while (length--) *dst++ = *src++; } return dst_void; #else char *dst = dst_void; _CONST char *src = src_void; long *aligned_dst; _CONST long *aligned_src; if (src < dst && dst < src + length) { /* Destructive overlap...have to copy backwards */ src += length; dst += length; while (length--) *--dst = *--src; } else { /* * Use optimizing algorithm for a non-destructive copy to * closely match memcpy. If the size is small or either SRC or * DST is unaligned, then punt into the byte copy loop. This * should be rare. */ if (!TOO_SMALL(length) && !UNALIGNED(src, dst)) { aligned_dst = (long *)dst; aligned_src = (long *)src; /* Copy 4X long words at a time if possible. */ while (length >= BIGBLOCKSIZE) { *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; *aligned_dst++ = *aligned_src++; length -= BIGBLOCKSIZE; } /* Copy one long word at a time if possible. */ while (length >= LITTLEBLOCKSIZE) { *aligned_dst++ = *aligned_src++; length -= LITTLEBLOCKSIZE; } /* Pick up any residual with a byte copier. */ dst = (char *)aligned_dst; src = (char *)aligned_src; } while (length--) *dst++ = *src++; } return dst_void; #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/memset.c000066400000000000000000000071051464416617300216220ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---set an area of memory INDEX memset ANSI_SYNOPSIS #include void *memset(void *<[dst]>, int <[c]>, size_t <[length]>); TRAD_SYNOPSIS #include void *memset(<[dst]>, <[c]>, <[length]>) void *<[dst]>; int <[c]>; size_t <[length]>; DESCRIPTION This function converts the argument <[c]> into an unsigned char and fills the first <[length]> characters of the array pointed to by <[dst]> to the value. RETURNS <> returns the value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF memset ansi pure */ #include "_ansi.h" #include #define LBLOCKSIZE (sizeof(long)) #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE) _PTR _DEFUN(memset, (m, c, n), _PTR m _AND int c _AND size_t n) { char *s = (char *)m; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) int i; unsigned long buffer; unsigned long *aligned_addr; unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an unsigned variable. */ while (UNALIGNED(s)) { if (n--) *s++ = (char)c; else return m; } if (!TOO_SMALL(n)) { /* * If we get this far, we know that n is large and s is * word-aligned. */ aligned_addr = (unsigned long *)s; /* Store D into each char sized location in BUFFER so that we can set large blocks quickly. */ buffer = (d << 8) | d; buffer |= (buffer << 16); for (i = 32; i < LBLOCKSIZE * 8; i <<= 1) buffer = (buffer << i) | buffer; /* Unroll the loop. */ while (n >= LBLOCKSIZE * 4) { *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; *aligned_addr++ = buffer; n -= 4 * LBLOCKSIZE; } while (n >= LBLOCKSIZE) { *aligned_addr++ = buffer; n -= LBLOCKSIZE; } /* Pick up the remainder with a bytewise loop. */ s = (char *)aligned_addr; } #endif /* not PREFER_SIZE_OVER_SPEED */ while (n--) *s++ = (char)c; return m; } optee_os-4.3.0/lib/libutils/isoc/newlib/str-two-way.h000066400000000000000000000360471464416617300225610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-3-Clause */ /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Byte-wise substring search, using the Two-Way algorithm. * Copyright (C) 2008, 2010 Eric Blake * Permission to use, copy, modify, and distribute this software * is freely granted, provided that this notice is preserved. */ /* Before including this file, you need to include , and define: RESULT_TYPE A macro that expands to the return type. AVAILABLE(h, h_l, j, n_l) A macro that returns nonzero if there are at least N_L bytes left starting at H[J]. H is 'unsigned char *', H_L, J, and N_L are 'size_t'; H_L is an lvalue. For NUL-terminated searches, H_L can be modified each iteration to avoid having to compute the end of H up front. For case-insensitivity, you may optionally define: CMP_FUNC(p1, p2, l) A macro that returns 0 iff the first L characters of P1 and P2 are equal. CANON_ELEMENT(c) A macro that canonicalizes an element right after it has been fetched from one of the two strings. The argument is an 'unsigned char'; the result must be an 'unsigned char' as well. This file undefines the macros documented above, and defines LONG_NEEDLE_THRESHOLD. */ #include #include /* We use the Two-Way string matching algorithm, which guarantees linear complexity with constant space. Additionally, for long needles, we also use a bad character shift table similar to the Boyer-Moore algorithm to achieve improved (potentially sub-linear) performance. See http://www-igm.univ-mlv.fr/~lecroq/string/node26.html#SECTION00260 and http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm */ /* Point at which computing a bad-byte shift table is likely to be worthwhile. Small needles should not compute a table, since it adds (1 << CHAR_BIT) + NEEDLE_LEN computations of preparation for a speedup no greater than a factor of NEEDLE_LEN. The larger the needle, the better the potential performance gain. On the other hand, on non-POSIX systems with CHAR_BIT larger than eight, the memory required for the table is prohibitive. */ #if CHAR_BIT < 10 # define LONG_NEEDLE_THRESHOLD 32U #else # define LONG_NEEDLE_THRESHOLD SIZE_MAX #endif #define MAX(a, b) ((a < b) ? (b) : (a)) #ifndef CANON_ELEMENT # define CANON_ELEMENT(c) c #endif #ifndef CMP_FUNC # define CMP_FUNC memcmp #endif /* Perform a critical factorization of NEEDLE, of length NEEDLE_LEN. Return the index of the first byte in the right half, and set *PERIOD to the global period of the right half. The global period of a string is the smallest index (possibly its length) at which all remaining bytes in the string are repetitions of the prefix (the last repetition may be a subset of the prefix). When NEEDLE is factored into two halves, a local period is the length of the smallest word that shares a suffix with the left half and shares a prefix with the right half. All factorizations of a non-empty NEEDLE have a local period of at least 1 and no greater than NEEDLE_LEN. A critical factorization has the property that the local period equals the global period. All strings have at least one critical factorization with the left half smaller than the global period. Given an ordered alphabet, a critical factorization can be computed in linear time, with 2 * NEEDLE_LEN comparisons, by computing the larger of two ordered maximal suffixes. The ordered maximal suffixes are determined by lexicographic comparison of periodicity. */ static size_t critical_factorization (const unsigned char *needle, size_t needle_len, size_t *period) { /* Index of last byte of left half, or SIZE_MAX. */ size_t max_suffix, max_suffix_rev; size_t j; /* Index into NEEDLE for current candidate suffix. */ size_t k; /* Offset into current period. */ size_t p; /* Intermediate period. */ unsigned char a, b; /* Current comparison bytes. */ /* Invariants: 0 <= j < NEEDLE_LEN - 1 -1 <= max_suffix{,_rev} < j (treating SIZE_MAX as if it were signed) min(max_suffix, max_suffix_rev) < global period of NEEDLE 1 <= p <= global period of NEEDLE p == global period of the substring NEEDLE[max_suffix{,_rev}+1...j] 1 <= k <= p */ /* Perform lexicographic search. */ max_suffix = SIZE_MAX; j = 0; k = p = 1; while (j + k < needle_len) { a = CANON_ELEMENT (needle[j + k]); b = CANON_ELEMENT (needle[(size_t)(max_suffix + k)]); if (a < b) { /* Suffix is smaller, period is entire prefix so far. */ j += k; k = 1; p = j - max_suffix; } else if (a == b) { /* Advance through repetition of the current period. */ if (k != p) ++k; else { j += p; k = 1; } } else /* b < a */ { /* Suffix is larger, start over from current location. */ max_suffix = j++; k = p = 1; } } *period = p; /* Perform reverse lexicographic search. */ max_suffix_rev = SIZE_MAX; j = 0; k = p = 1; while (j + k < needle_len) { a = CANON_ELEMENT (needle[j + k]); b = CANON_ELEMENT (needle[max_suffix_rev + k]); if (b < a) { /* Suffix is smaller, period is entire prefix so far. */ j += k; k = 1; p = j - max_suffix_rev; } else if (a == b) { /* Advance through repetition of the current period. */ if (k != p) ++k; else { j += p; k = 1; } } else /* a < b */ { /* Suffix is larger, start over from current location. */ max_suffix_rev = j++; k = p = 1; } } /* Choose the longer suffix. Return the first byte of the right half, rather than the last byte of the left half. */ if (max_suffix_rev + 1 < max_suffix + 1) return max_suffix + 1; *period = p; return max_suffix_rev + 1; } /* Return the first location of non-empty NEEDLE within HAYSTACK, or NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This method is optimized for NEEDLE_LEN < LONG_NEEDLE_THRESHOLD. Performance is guaranteed to be linear, with an initialization cost of 2 * NEEDLE_LEN comparisons. If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ static RETURN_TYPE two_way_short_needle (const unsigned char *haystack, size_t haystack_len, const unsigned char *needle, size_t needle_len) { size_t i; /* Index into current byte of NEEDLE. */ size_t j; /* Index into current window of HAYSTACK. */ size_t period; /* The period of the right half of needle. */ size_t suffix; /* The index of the right half of needle. */ /* Factor the needle into two halves, such that the left half is smaller than the global period, and the right half is periodic (with a period as large as NEEDLE_LEN - suffix). */ suffix = critical_factorization (needle, needle_len, &period); /* Perform the search. Each iteration compares the right half first. */ if (CMP_FUNC (needle, needle + period, suffix) == 0) { /* Entire needle is periodic; a mismatch can only advance by the period, so use memory to avoid rescanning known occurrences of the period. */ size_t memory = 0; j = 0; while (AVAILABLE (haystack, haystack_len, j, needle_len)) { /* Scan for matches in right half. */ i = MAX (suffix, memory); while (i < needle_len && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) ++i; if (needle_len <= i) { /* Scan for matches in left half. */ i = suffix - 1; while (memory < i + 1 && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) --i; if (i + 1 < memory + 1) return (RETURN_TYPE) (haystack + j); /* No match, so remember how many repetitions of period on the right half were scanned. */ j += period; memory = needle_len - period; } else { j += i - suffix + 1; memory = 0; } } } else { /* The two halves of needle are distinct; no extra memory is required, and any mismatch results in a maximal shift. */ period = MAX (suffix, needle_len - suffix) + 1; j = 0; while (AVAILABLE (haystack, haystack_len, j, needle_len)) { /* Scan for matches in right half. */ i = suffix; while (i < needle_len && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) ++i; if (needle_len <= i) { /* Scan for matches in left half. */ i = suffix - 1; while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) --i; if (i == SIZE_MAX) return (RETURN_TYPE) (haystack + j); j += period; } else j += i - suffix + 1; } } return NULL; } /* Return the first location of non-empty NEEDLE within HAYSTACK, or NULL. HAYSTACK_LEN is the minimum known length of HAYSTACK. This method is optimized for LONG_NEEDLE_THRESHOLD <= NEEDLE_LEN. Performance is guaranteed to be linear, with an initialization cost of 3 * NEEDLE_LEN + (1 << CHAR_BIT) operations. If AVAILABLE does not modify HAYSTACK_LEN (as in memmem), then at most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible. If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and sublinear performance is not possible. */ static RETURN_TYPE two_way_long_needle (const unsigned char *haystack, size_t haystack_len, const unsigned char *needle, size_t needle_len) { size_t i; /* Index into current byte of NEEDLE. */ size_t j; /* Index into current window of HAYSTACK. */ size_t period; /* The period of the right half of needle. */ size_t suffix; /* The index of the right half of needle. */ size_t shift_table[1U << CHAR_BIT]; /* See below. */ /* Factor the needle into two halves, such that the left half is smaller than the global period, and the right half is periodic (with a period as large as NEEDLE_LEN - suffix). */ suffix = critical_factorization (needle, needle_len, &period); /* Populate shift_table. For each possible byte value c, shift_table[c] is the distance from the last occurrence of c to the end of NEEDLE, or NEEDLE_LEN if c is absent from the NEEDLE. shift_table[NEEDLE[NEEDLE_LEN - 1]] contains the only 0. */ for (i = 0; i < 1U << CHAR_BIT; i++) shift_table[i] = needle_len; for (i = 0; i < needle_len; i++) shift_table[CANON_ELEMENT (needle[i])] = needle_len - i - 1; /* Perform the search. Each iteration compares the right half first. */ if (CMP_FUNC (needle, needle + period, suffix) == 0) { /* Entire needle is periodic; a mismatch can only advance by the period, so use memory to avoid rescanning known occurrences of the period. */ size_t memory = 0; size_t shift; j = 0; while (AVAILABLE (haystack, haystack_len, j, needle_len)) { /* Check the last byte first; if it does not match, then shift to the next possible match location. */ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; if (0 < shift) { if (memory && shift < period) { /* Since needle is periodic, but the last period has a byte out of place, there can be no match until after the mismatch. */ shift = needle_len - period; } memory = 0; j += shift; continue; } /* Scan for matches in right half. The last byte has already been matched, by virtue of the shift table. */ i = MAX (suffix, memory); while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) ++i; if (needle_len - 1 <= i) { /* Scan for matches in left half. */ i = suffix - 1; while (memory < i + 1 && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) --i; if (i + 1 < memory + 1) return (RETURN_TYPE) (haystack + j); /* No match, so remember how many repetitions of period on the right half were scanned. */ j += period; memory = needle_len - period; } else { j += i - suffix + 1; memory = 0; } } } else { /* The two halves of needle are distinct; no extra memory is required, and any mismatch results in a maximal shift. */ size_t shift; period = MAX (suffix, needle_len - suffix) + 1; j = 0; while (AVAILABLE (haystack, haystack_len, j, needle_len)) { /* Check the last byte first; if it does not match, then shift to the next possible match location. */ shift = shift_table[CANON_ELEMENT (haystack[j + needle_len - 1])]; if (0 < shift) { j += shift; continue; } /* Scan for matches in right half. The last byte has already been matched, by virtue of the shift table. */ i = suffix; while (i < needle_len - 1 && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) ++i; if (needle_len - 1 <= i) { /* Scan for matches in left half. */ i = suffix - 1; while (i != SIZE_MAX && (CANON_ELEMENT (needle[i]) == CANON_ELEMENT (haystack[i + j]))) --i; if (i == SIZE_MAX) return (RETURN_TYPE) (haystack + j); j += period; } else j += i - suffix + 1; } } return NULL; } #undef AVAILABLE #undef CANON_ELEMENT #undef CMP_FUNC #undef MAX #undef RETURN_TYPE optee_os-4.3.0/lib/libutils/isoc/newlib/strchr.c000066400000000000000000000107011464416617300216310ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---search for character in string INDEX strchr ANSI_SYNOPSIS #include char * strchr(const char *<[string]>, int <[c]>); TRAD_SYNOPSIS #include char * strchr(<[string]>, <[c]>); const char *<[string]>; int <[c]>; DESCRIPTION This function finds the first occurence of <[c]> (converted to a char) in the string pointed to by <[string]> (including the terminating null character). RETURNS Returns a pointer to the located character, or a null pointer if <[c]> does not occur in <[string]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strchr ansi pure */ #include #include #include "_ansi.h" /* Nonzero if X is not aligned on a "long" boundary. */ #define UNALIGNED(X) ((long)X & (sizeof (long) - 1)) /* How many bytes are loaded each iteration of the word copy loop. */ #define LBLOCKSIZE (sizeof (long)) #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) #else #if LONG_MAX == 9223372036854775807L /* Nonzero if X (a long int) contains a NULL byte. */ #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 0x8080808080808080UL) #else #error long int is not a 32bit or 64bit type. #endif #endif /* DETECTCHAR returns nonzero if (long)X contains the byte used to fill (long)MASK. */ #define DETECTCHAR(X,MASK) (DETECTNULL(X ^ MASK)) char * _DEFUN (strchr, (s1, i), _CONST char *s1 _AND int i) { _CONST unsigned char *s = (_CONST unsigned char *)s1; unsigned char c = i; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long mask,j; unsigned long *aligned_addr; /* Special case for finding 0. */ if (!c) { while (UNALIGNED (s)) { if (!*s) return (char *) s; s++; } /* Operate a word at a time. */ aligned_addr = (unsigned long *) s; while (!DETECTNULL (*aligned_addr)) aligned_addr++; /* Found the end of string. */ s = (const unsigned char *) aligned_addr; while (*s) s++; return (char *) s; } /* All other bytes. Align the pointer, then search a long at a time. */ while (UNALIGNED (s)) { if (!*s) return NULL; if (*s == c) return (char *) s; s++; } mask = c; for (j = 8; j < LBLOCKSIZE * 8; j <<= 1) mask = (mask << j) | mask; aligned_addr = (unsigned long *) s; while (!DETECTNULL (*aligned_addr) && !DETECTCHAR (*aligned_addr, mask)) aligned_addr++; /* The block of bytes currently pointed to by aligned_addr contains either a null or the target char, or both. We catch it using the bytewise search. */ s = (unsigned char *) aligned_addr; #endif /* not PREFER_SIZE_OVER_SPEED */ while (*s && *s != c) s++; if (*s == c) return (char *)s; return NULL; } optee_os-4.3.0/lib/libutils/isoc/newlib/strcmp.c000066400000000000000000000077141464416617300216460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* This file is copied from newlib-1.19 */ /* FUNCTION <>---character string compare INDEX strcmp ANSI_SYNOPSIS #include int strcmp(const char *<[a]>, const char *<[b]>); TRAD_SYNOPSIS #include int strcmp(<[a]>, <[b]>) char *<[a]>; char *<[b]>; DESCRIPTION <> compares the string at <[a]> to the string at <[b]>. RETURNS If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, <> returns a number greater than zero. If the two strings match, <> returns zero. If <<*<[a]>>> sorts lexicographically before <<*<[b]>>>, <> returns a number less than zero. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strcmp ansi pure */ #include "_ansi.h" #include #include /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof(long) - 1)) | ((long)Y & (sizeof(long) - 1))) /* DETECTNULL returns nonzero if (long)X contains a NULL byte. */ #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) #else #if LONG_MAX == 9223372036854775807L #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 0x8080808080808080UL) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif int _DEFUN(strcmp, (s1, s2), _CONST char *s1 _AND _CONST char *s2) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } return (*(unsigned char *)s1) - (*(unsigned char *)s2); #else unsigned long *a1; unsigned long *a2; /* If s1 or s2 are unaligned, then compare bytes. */ if (!UNALIGNED(s1, s2)) { /* * If s1 and s2 are word-aligned, compare them a word at a time. */ a1 = (unsigned long *)s1; a2 = (unsigned long *)s2; while (*a1 == *a2) { /* * To get here, *a1 == *a2, thus if we find a null in * *a1, then the strings must be equal, so return zero. */ if (DETECTNULL(*a1)) return 0; a1++; a2++; } /* * A difference was detected in last few bytes of s1, so search * bytewise. */ s1 = (char *)a1; s2 = (char *)a2; } while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } return (*(unsigned char *)s1) - (*(unsigned char *)s2); #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/strcpy.c000066400000000000000000000071401464416617300216530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---copy string INDEX strcpy ANSI_SYNOPSIS #include char *strcpy(char *<[dst]>, const char *<[src]>); TRAD_SYNOPSIS #include char *strcpy(<[dst]>, <[src]>) char *<[dst]>; char *<[src]>; DESCRIPTION <> copies the string pointed to by <[src]> (including the terminating null character) to the array pointed to by <[dst]>. RETURNS This function returns the initial value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strcpy ansi pure */ #include "_ansi.h" #include #include /*SUPPRESS 560*/ /*SUPPRESS 530*/ /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) #else #if LONG_MAX == 9223372036854775807L /* Nonzero if X (a long int) contains a NULL byte. */ #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif char* _DEFUN (strcpy, (dst0, src0), char *dst0 _AND _CONST char *src0) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *s = dst0; while (*dst0++ = *src0++) ; return s; #else char *dst = dst0; _CONST char *src = src0; long *aligned_dst; _CONST long *aligned_src; /* If SRC or DEST is unaligned, then copy bytes. */ if (!UNALIGNED (src, dst)) { aligned_dst = (long*)dst; aligned_src = (long*)src; /* SRC and DEST are both "long int" aligned, try to do "long int" sized copies. */ while (!DETECTNULL(*aligned_src)) { *aligned_dst++ = *aligned_src++; } dst = (char*)aligned_dst; src = (char*)aligned_src; } while ((*dst++ = *src++)) ; return dst0; #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/strlen.c000066400000000000000000000066731464416617300216500ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* This file is copied from newlib-1.19 */ /* FUNCTION <>---character string length INDEX strlen ANSI_SYNOPSIS #include size_t strlen(const char *<[str]>); TRAD_SYNOPSIS #include size_t strlen(<[str]>) char *<[src]>; DESCRIPTION The <> function works out the length of the string starting at <<*<[str]>>> by counting chararacters until it reaches a <> character. RETURNS <> returns the character count. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strlen ansi pure */ #include "_ansi.h" #include #include #define LBLOCKSIZE (sizeof(long)) #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1)) #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) #else #if LONG_MAX == 9223372036854775807L /* Nonzero if X (a long int) contains a NULL byte. */ #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 0x8080808080808080UL) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif size_t _DEFUN(strlen, (str), _CONST char *str) { _CONST char *start = str; #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) unsigned long *aligned_addr; /* Align the pointer, so we can search a word at a time. */ while (UNALIGNED(str)) { if (!*str) return str - start; str++; } /* If the string is word-aligned, we can check for the presence of a null in each word-sized block. */ aligned_addr = (unsigned long *)str; while (!DETECTNULL(*aligned_addr)) aligned_addr++; /* Once a null is detected, we check each byte in that block for a precise position of the null. */ str = (char *)aligned_addr; #endif /* not PREFER_SIZE_OVER_SPEED */ while (*str) str++; return str - start; } optee_os-4.3.0/lib/libutils/isoc/newlib/strncmp.c000066400000000000000000000106261464416617300220200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---character string compare INDEX strncmp ANSI_SYNOPSIS #include int strncmp(const char *<[a]>, const char * <[b]>, size_t <[length]>); TRAD_SYNOPSIS #include int strncmp(<[a]>, <[b]>, <[length]>) char *<[a]>; char *<[b]>; size_t <[length]> DESCRIPTION <> compares up to <[length]> characters from the string at <[a]> to the string at <[b]>. RETURNS If <<*<[a]>>> sorts lexicographically after <<*<[b]>>>, <> returns a number greater than zero. If the two strings are equivalent, <> returns zero. If <<*<[a]>>> sorts lexicographically before <<*<[b]>>>, <> returns a number less than zero. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strncmp ansi pure */ #include "_ansi.h" #include #include /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) /* DETECTNULL returns nonzero if (long)X contains a NULL byte. */ #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101L) & ~(X) & 0x80808080UL) #else #if LONG_MAX == 9223372036854775807L #define DETECTNULL(X) (((X) - 0x0101010101010101L) & ~(X) & \ 0x8080808080808080UL) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif int _DEFUN (strncmp, (s1, s2, n), _CONST char *s1 _AND _CONST char *s2 _AND size_t n) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) if (n == 0) return 0; while (n-- != 0 && *s1 == *s2) { if (n == 0 || *s1 == '\0') break; s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); #else unsigned long *a1; unsigned long *a2; if (n == 0) return 0; /* If s1 or s2 are unaligned, then compare bytes. */ if (!UNALIGNED (s1, s2)) { /* If s1 and s2 are word-aligned, compare them a word at a time. */ a1 = (unsigned long*)s1; a2 = (unsigned long*)s2; while (n >= sizeof (long) && *a1 == *a2) { n -= sizeof (long); /* If we've run out of bytes or hit a null, return zero since we already know *a1 == *a2. */ if (n == 0 || DETECTNULL (*a1)) return 0; a1++; a2++; } /* A difference was detected in last few bytes of s1, so search bytewise */ s1 = (char*)a1; s2 = (char*)a2; } while (n-- > 0 && *s1 == *s2) { /* If we've run out of bytes or hit a null, return zero since we already know *s1 == *s2. */ if (n == 0 || *s1 == '\0') return 0; s1++; s2++; } return (*(unsigned char *) s1) - (*(unsigned char *) s2); #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/strncpy.c000066400000000000000000000105441464416617300220330ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---counted copy string INDEX strncpy ANSI_SYNOPSIS #include char *strncpy(char *restrict <[dst]>, const char *restrict <[src]>, size_t <[length]>); TRAD_SYNOPSIS #include char *strncpy(<[dst]>, <[src]>, <[length]>) char *<[dst]>; char *<[src]>; size_t <[length]>; DESCRIPTION <> copies not more than <[length]> characters from the the string pointed to by <[src]> (including the terminating null character) to the array pointed to by <[dst]>. If the string pointed to by <[src]> is shorter than <[length]> characters, null characters are appended to the destination array until a total of <[length]> characters have been written. RETURNS This function returns the initial value of <[dst]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strncpy ansi pure */ #include "_ansi.h" #include #include /*SUPPRESS 560*/ /*SUPPRESS 530*/ /* Nonzero if either X or Y is not aligned on a "long" boundary. */ #define UNALIGNED(X, Y) \ (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1))) #if LONG_MAX == 2147483647L #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) #else #if LONG_MAX == 9223372036854775807L /* Nonzero if X (a long int) contains a NULL byte. */ #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) #else #error long int is not a 32bit or 64bit type. #endif #endif #ifndef DETECTNULL #error long int is not a 32bit or 64bit byte #endif #define TOO_SMALL(LEN) ((LEN) < sizeof (long)) char * _DEFUN (strncpy, (dst0, src0), char *__restrict dst0 _AND _CONST char *__restrict src0 _AND size_t count) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) char *dscan; _CONST char *sscan; dscan = dst0; sscan = src0; while (count > 0) { --count; if ((*dscan++ = *sscan++) == '\0') break; } while (count-- > 0) *dscan++ = '\0'; return dst0; #else char *dst = dst0; _CONST char *src = src0; long *aligned_dst; _CONST long *aligned_src; /* If SRC and DEST is aligned and count large enough, then copy words. */ if (!UNALIGNED (src, dst) && !TOO_SMALL (count)) { aligned_dst = (long*)dst; aligned_src = (long*)src; /* SRC and DEST are both "long int" aligned, try to do "long int" sized copies. */ while (count >= sizeof (long int) && !DETECTNULL(*aligned_src)) { count -= sizeof (long int); *aligned_dst++ = *aligned_src++; } dst = (char*)aligned_dst; src = (char*)aligned_src; } while (count > 0) { --count; if ((*dst++ = *src++) == '\0') break; } while (count-- > 0) *dst++ = '\0'; return dst0; #endif /* not PREFER_SIZE_OVER_SPEED */ } optee_os-4.3.0/lib/libutils/isoc/newlib/strnlen.c000066400000000000000000000046721464416617300220230ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---character string length INDEX strnlen ANSI_SYNOPSIS #include size_t strnlen(const char *<[str]>, size_t <[n]>); TRAD_SYNOPSIS #include size_t strnlen(<[str]>, <[n]>) char *<[src]>; size_t <[n]>; DESCRIPTION The <> function works out the length of the string starting at <<*<[str]>>> by counting chararacters until it reaches a NUL character or the maximum: <[n]> number of characters have been inspected. RETURNS <> returns the character count or <[n]>. PORTABILITY <> is a GNU extension. <> requires no supporting OS subroutines. */ #undef __STRICT_ANSI__ #include "_ansi.h" #include size_t _DEFUN (strnlen, (str, n), _CONST char *str _AND size_t n) { _CONST char *start = str; while (n-- > 0 && *str) str++; return str - start; } optee_os-4.3.0/lib/libutils/isoc/newlib/strrchr.c000066400000000000000000000050201464416617300220110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---reverse search for character in string INDEX strrchr ANSI_SYNOPSIS #include char * strrchr(const char *<[string]>, int <[c]>); TRAD_SYNOPSIS #include char * strrchr(<[string]>, <[c]>); char *<[string]>; int *<[c]>; DESCRIPTION This function finds the last occurence of <[c]> (converted to a char) in the string pointed to by <[string]> (including the terminating null character). RETURNS Returns a pointer to the located character, or a null pointer if <[c]> does not occur in <[string]>. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strrchr ansi pure */ #include "_ansi.h" #include char * _DEFUN (strrchr, (s, i), _CONST char *s _AND int i) { _CONST char *last = NULL; if (i) { while ((s=strchr(s, i))) { last = s; s++; } } else { last = strchr(s, i); } return (char *) last; } optee_os-4.3.0/lib/libutils/isoc/newlib/strstr.c000066400000000000000000000110561464416617300216710ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---find string segment INDEX strstr ANSI_SYNOPSIS #include char *strstr(const char *<[s1]>, const char *<[s2]>); TRAD_SYNOPSIS #include char *strstr(<[s1]>, <[s2]>) char *<[s1]>; char *<[s2]>; DESCRIPTION Locates the first occurrence in the string pointed to by <[s1]> of the sequence of characters in the string pointed to by <[s2]> (excluding the terminating null character). RETURNS Returns a pointer to the located string segment, or a null pointer if the string <[s2]> is not found. If <[s2]> points to a string with zero length, <[s1]> is returned. PORTABILITY <> is ANSI C. <> requires no supporting OS subroutines. QUICKREF strstr ansi pure */ #include "_ansi.h" #include #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) # define RETURN_TYPE char * # define AVAILABLE(h, h_l, j, n_l) \ (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ && ((h_l) = (j) + (n_l))) # include "str-two-way.h" #endif char * _DEFUN (strstr, (searchee, lookfor), _CONST char *searchee _AND _CONST char *lookfor) { #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__) /* Less code size, but quadratic performance in the worst case. */ if (*searchee == 0) { if (*lookfor) return (char *) NULL; return (char *) searchee; } while (*searchee) { size_t i; i = 0; while (1) { if (lookfor[i] == 0) { return (char *) searchee; } if (lookfor[i] != searchee[i]) { break; } i++; } searchee++; } return (char *) NULL; #else /* compilation for speed */ /* Larger code size, but guaranteed linear performance. */ const char *haystack = searchee; const char *needle = lookfor; size_t needle_len; /* Length of NEEDLE. */ size_t haystack_len; /* Known minimum length of HAYSTACK. */ int ok = 1; /* True if NEEDLE is prefix of HAYSTACK. */ /* Determine length of NEEDLE, and in the process, make sure HAYSTACK is at least as long (no point processing all of a long NEEDLE if HAYSTACK is too short). */ while (*haystack && *needle) ok &= *haystack++ == *needle++; if (*needle) return NULL; if (ok) return (char *) searchee; /* Reduce the size of haystack using strchr, since it has a smaller linear coefficient than the Two-Way algorithm. */ needle_len = needle - lookfor; haystack = strchr (searchee + 1, *lookfor); if (!haystack || needle_len == 1) return (char *) haystack; haystack_len = (haystack > searchee + needle_len ? 1 : needle_len + searchee - haystack); /* Perform the search. */ if (needle_len < LONG_NEEDLE_THRESHOLD) return two_way_short_needle ((const unsigned char *) haystack, haystack_len, (const unsigned char *) lookfor, needle_len); return two_way_long_needle ((const unsigned char *) haystack, haystack_len, (const unsigned char *) lookfor, needle_len); #endif /* compilation for speed */ } optee_os-4.3.0/lib/libutils/isoc/newlib/strtok_r.c000066400000000000000000000053071464416617300222010ustar00rootroot00000000000000/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include static char * __strtok_r (register char *s, register const char *delim, char **lasts, int skip_leading_delim) { register char *spanp; register int c, sc; char *tok; if (s == NULL && (s = *lasts) == NULL) return (NULL); /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). */ cont: c = *s++; for (spanp = (char *)delim; (sc = *spanp++) != 0;) { if (c == sc) { if (skip_leading_delim) { goto cont; } else { *lasts = s; s[-1] = 0; return (s - 1); } } } if (c == 0) { /* no non-delimiter characters */ *lasts = NULL; return (NULL); } tok = s - 1; /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL; we stop if we see that, too. */ for (;;) { c = *s++; spanp = (char *)delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *lasts = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } char * strtok_r (register char *__restrict s, register const char *__restrict delim, char **__restrict lasts) { return __strtok_r (s, delim, lasts, 1); } optee_os-4.3.0/lib/libutils/isoc/newlib/strtoul.c000066400000000000000000000174011464416617300220440ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* * Copyright (c) 1994-2009 Red Hat, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* FUNCTION <>---string to unsigned long INDEX strtoul INDEX _strtoul_r ANSI_SYNOPSIS #include unsigned long strtoul(const char *<[s]>, char **<[ptr]>, int <[base]>); unsigned long _strtoul(const char *<[s]>, char **<[ptr]>, int <[base]>); TRAD_SYNOPSIS #include unsigned long strtoul(<[s]>, <[ptr]>, <[base]>) char *<[s]>; char **<[ptr]>; int <[base]>; unsigned long _strtoul(<[s]>, <[ptr]>, <[base]>) char *<[s]>; char **<[ptr]>; int <[base]>; DESCRIPTION The function <> converts the string <<*<[s]>>> to an <>. First, it breaks down the string into three parts: leading whitespace, which is ignored; a subject string consisting of the digits meaningful in the radix specified by <[base]> (for example, <<0>> through <<7>> if the value of <[base]> is 8); and a trailing portion consisting of one or more unparseable characters, which always includes the terminating null character. Then, it attempts to convert the subject string into an unsigned long integer, and returns the result. If the value of <[base]> is zero, the subject string is expected to look like a normal C integer constant (save that no optional sign is permitted): a possible <<0x>> indicating hexadecimal radix, and a number. If <[base]> is between 2 and 36, the expected form of the subject is a sequence of digits (which may include letters, depending on the base) representing an integer in the radix specified by <[base]>. The letters <>--<> (or <>--<>) are used as digits valued from 10 to 35. If <[base]> is 16, a leading <<0x>> is permitted. The subject sequence is the longest initial sequence of the input string that has the expected form, starting with the first non-whitespace character. If the string is empty or consists entirely of whitespace, or if the first non-whitespace character is not a permissible digit, the subject string is empty. If the subject string is acceptable, and the value of <[base]> is zero, <> attempts to determine the radix from the input string. A string with a leading <<0x>> is treated as a hexadecimal value; a string with a leading <<0>> and no <> is treated as octal; all other strings are treated as decimal. If <[base]> is between 2 and 36, it is used as the conversion radix, as described above. Finally, a pointer to the first character past the converted subject string is stored in <[ptr]>, if <[ptr]> is not <>. If the subject string is empty (that is, if <<*>><[s]> does not start with a substring in acceptable form), no conversion is performed and the value of <[s]> is stored in <[ptr]> (if <[ptr]> is not <>). RETURNS <> returns the converted value, if any. If no conversion was made, <<0>> is returned. <> returns <> if the magnitude of the converted value is too large, and sets <> to <>. PORTABILITY <> is ANSI. <> requires no supporting OS subroutines. */ /* * Copyright (c) 1990 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "_ansi.h" #include #include #include /* * Convert a string to an unsigned long integer. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ unsigned long _DEFUN (_strtoul, (nptr, endptr, base), _CONST char *nptr _AND char **endptr _AND int base) { register const unsigned char *s = (const unsigned char *)nptr; register unsigned long acc; register int c; register unsigned long cutoff; register int neg = 0, any, cutlim; /* * See strtol for comments as to the logic used. */ do { c = *s++; } while (isspace(c)); if (c == '-') { neg = 1; c = *s++; } else if (c == '+') c = *s++; if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; for (acc = 0, any = 0;; c = *s++) { if (isdigit(c)) c -= '0'; else if (isalpha(c)) c -= isupper(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = ULONG_MAX; } else if (neg) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? (char *)s - 1 : nptr); return (acc); } #ifndef _REENT_ONLY unsigned long _DEFUN (strtoul, (s, ptr, base), _CONST char *s _AND char **ptr _AND int base) { return _strtoul (s, ptr, base); } #endif optee_os-4.3.0/lib/libutils/isoc/newlib/sub.mk000066400000000000000000000013201464416617300212770ustar00rootroot00000000000000cflags-y += -Wno-sign-compare cflags-y += -Wno-parentheses cflags-remove-y += -Wcast-align srcs-y += abs.c srcs-y += bcmp.c srcs-y += memchr.c srcs-y += memcmp.c srcs-y += memcpy.c ifeq (s,$(CFG_CC_OPT_LEVEL)) cflags-memcpy.c-y += -O2 endif cflags-memcpy.c-y += $(call cc-option,-fno-tree-loop-distribute-patterns) srcs-y += memmove.c cflags-memmove.c-y += $(call cc-option,-fno-tree-loop-distribute-patterns) srcs-y += memset.c cflags-memset.c-y += $(call cc-option,-fno-tree-loop-distribute-patterns) srcs-y += strchr.c srcs-y += strcmp.c srcs-y += strcpy.c srcs-y += strlen.c srcs-y += strncmp.c srcs-y += strncpy.c srcs-y += strnlen.c srcs-y += strrchr.c srcs-y += strstr.c srcs-y += strtoul.c srcs-y += strtok_r.c optee_os-4.3.0/lib/libutils/isoc/qsort.c000066400000000000000000000112361464416617300202200ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-3-Clause /* $OpenBSD: qsort.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *)); static __inline void swapfunc(char *, char *, int, int); #define min(a, b) (a) < (b) ? a : b /* * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". */ #define swapcode(TYPE, parmi, parmj, n) { \ long i = (n) / sizeof (TYPE); \ TYPE *pi = (TYPE *) (parmi); \ TYPE *pj = (TYPE *) (parmj); \ do { \ TYPE t = *pi; \ *pi++ = *pj; \ *pj++ = t; \ } while (--i > 0); \ } #define SWAPINIT(a, es) swaptype = (uintptr_t)a % sizeof(long) || \ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; static __inline void swapfunc(char *a, char *b, int n, int swaptype) { if (swaptype <= 1) swapcode(long, a, b, n) else swapcode(char, a, b, n) } #define swap(a, b) \ if (swaptype == 0) { \ long t = *(long *)(a); \ *(long *)(a) = *(long *)(b); \ *(long *)(b) = t; \ } else \ swapfunc(a, b, es, swaptype) #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) static __inline char * med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *)) { return cmp(a, b) < 0 ? (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); } void qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *)) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype, swap_cnt; char *a = aa; loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pm = (char *)a + (n / 2) * es; if (n > 7) { pl = (char *)a; pn = (char *)a + (n - 1) * es; if (n > 40) { d = (n / 8) * es; pl = med3(pl, pl + d, pl + 2 * d, cmp); pm = med3(pm - d, pm, pm + d, cmp); pn = med3(pn - 2 * d, pn - d, pn, cmp); } pm = med3(pl, pm, pn, cmp); } swap(a, pm); pa = pb = (char *)a + es; pc = pd = (char *)a + (n - 1) * es; for (;;) { while (pb <= pc && (r = cmp(pb, a)) <= 0) { if (r == 0) { swap_cnt = 1; swap(pa, pb); pa += es; } pb += es; } while (pb <= pc && (r = cmp(pc, a)) >= 0) { if (r == 0) { swap_cnt = 1; swap(pc, pd); pd -= es; } pc -= es; } if (pb > pc) break; swap(pb, pc); swap_cnt = 1; pb += es; pc -= es; } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; pl -= es) swap(pl, pl - es); return; } pn = (char *)a + n * es; r = min(pa - (char *)a, pb - pa); vecswap(a, pb - r, r); r = min(pd - pc, pn - pd - (int)es); vecswap(pb, pn - r, r); if ((r = pb - pa) > (int)es) qsort(a, r / es, es, cmp); if ((r = pd - pc) > (int)es) { /* Iterate rather than recurse to save stack space */ a = pn - r; n = r / es; goto loop; } /* qsort(pn - r, r / es, es, cmp);*/ } optee_os-4.3.0/lib/libutils/isoc/snprintf.c000066400000000000000000000006611464416617300207130ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include #include int snprintf(char *bf, size_t size, const char *fmt, ...) { int retval; va_list ap; va_start(ap, fmt); retval = __vsnprintf(bf, size, fmt, ap, false); va_end(ap); return retval; } int vsnprintf(char *bf, size_t size, const char *fmt, va_list ap) { return __vsnprintf(bf, size, fmt, ap, false); } optee_os-4.3.0/lib/libutils/isoc/sprintf.c000066400000000000000000000012071464416617300205320ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #include #include #include #include int sprintf(char *str, const char *fmt, ...) { int retval; va_list ap; va_start(ap, fmt); retval = __vsprintf(str, fmt, ap); va_end(ap); return retval; } int __sprintf_chk(char *str, int flag __unused, size_t slen, const char *fmt, ...) { int retval; va_list ap; if (slen == 0) abort(); va_start(ap, fmt); retval = __vsnprintf(str, slen, fmt, ap, false); va_end(ap); if (retval > 0 && (size_t)retval >= slen) abort(); return retval; } optee_os-4.3.0/lib/libutils/isoc/stack_check.c000066400000000000000000000011441464416617300213070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #if defined(__KERNEL__) # include # define PANIC() panic() #elif defined(__LDELF__) # include # define PANIC() _ldelf_panic(2) #else # include # define PANIC() _utee_panic(TEE_ERROR_OVERFLOW) #endif void *__stack_chk_guard __nex_data = (void *)0x00000aff; void __attribute__((noreturn)) __stack_chk_fail(void); void __stack_chk_fail(void) { EMSG_RAW("stack smashing detected"); while (1) PANIC(); } optee_os-4.3.0/lib/libutils/isoc/strdup.c000066400000000000000000000004161464416617300203670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include char *strdup(const char *s) { size_t l = strlen(s) + 1; char *p = malloc(l); if (p) memcpy(p, s, l); return p; } optee_os-4.3.0/lib/libutils/isoc/strndup.c000066400000000000000000000004711464416617300205460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include char *strndup(const char *s, size_t n) { size_t l = strnlen(s, n) + 1; char *p = malloc(l); if (p) { memcpy(p, s, l - 1); p[l - 1] = '\0'; } return p; } optee_os-4.3.0/lib/libutils/isoc/sub.mk000066400000000000000000000017011464416617300200220ustar00rootroot00000000000000global-incdirs-y += include srcs-y += bget_malloc.c cflags-remove-bget_malloc.c-y += -Wold-style-definition -Wredundant-decls cflags-bget_malloc.c-y += -Wno-sign-compare -Wno-cast-align cflags-bget_malloc.c-y += $(call cc-option,-Wno-deprecated-non-prototype) ifeq ($(sm),core) cflags-remove-bget_malloc.c-y += $(cflags_kasan) endif srcs-y += isdigit.c srcs-y += isxdigit.c srcs-y += qsort.c cflags-qsort.c-y += -Wno-inline cflags-remove-qsort.c-y += -Wcast-align srcs-y += sprintf.c srcs-y += snprintf.c srcs-y += stack_check.c srcs-y += strdup.c srcs-y += strndup.c srcs-y += tolower.c srcs-y += isalpha.c srcs-y += isspace.c srcs-y += isupper.c srcs-y += isalnum.c srcs-y += iscntrl.c srcs-y += isgraph.c srcs-y += islower.c srcs-y += isprint.c srcs-y += ispunct.c srcs-y += toupper.c ifneq (,$(filter ta_%,$(sm))) srcs-y += fp.c srcs-y += fputc.c srcs-y += fputs.c srcs-y += fwrite.c srcs-y += write.c endif subdirs-y += newlib subdirs-y += arch/$(ARCH) optee_os-4.3.0/lib/libutils/isoc/tolower.c000066400000000000000000000002771464416617300205460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2015, Linaro Limited */ #include int tolower(int c) { if (c >= 'A' && c <= 'Z') return c - 'A' + 'a'; return c; } optee_os-4.3.0/lib/libutils/isoc/toupper.c000066400000000000000000000002661464416617300205470ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2019, KAIST */ #include int toupper(int c) { if (c >= 'a' && c <= 'z') return c - 'a' + 'A'; return c; } optee_os-4.3.0/lib/libutils/isoc/write.c000066400000000000000000000004571464416617300202050ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2020, Huawei Technologies Co., Ltd */ #include #include #include ssize_t write(int fd, const void *buf, size_t count) { if (fd != 1 && fd != 2) abort(); return printf("%*s", (int)count, (char *)buf); } optee_os-4.3.0/lib/libutils/sub.mk000066400000000000000000000000731464416617300170660ustar00rootroot00000000000000subdirs-$(CFG_LIBUTILS_WITH_ISOC) += isoc subdirs-y += ext optee_os-4.3.0/mk/000077500000000000000000000000001464416617300137565ustar00rootroot00000000000000optee_os-4.3.0/mk/aosp_optee.mk000066400000000000000000000174101464416617300164500ustar00rootroot00000000000000########################################################## ## Common mk file used for Android to compile and ## ## integrate OP-TEE related components ## ## Following flags need to be defined in optee*.mk ## ## OPTEE_OS_DIR ## ## OPTEE_TA_TARGETS ## ## OPTEE_CFG_ARM64_CORE ## ## OPTEE_PLATFORM ## ## OPTEE_PLATFORM_FLAVOR ## ## OPTEE_EXTRA_FLAGS (optional) ## ## OPTEE_EXTRA_TA_FLAGS (optional) ## ## And BUILD_OPTEE_MK needs to be defined in optee*.mk ## ## to point to this file ## ## ## ## local_module needs to be defined before including ## ## this file to build TAs ## ## ## ########################################################## ########################################################## ## define common variables, like TA_DEV_KIT_DIR ## ########################################################## TOP_ROOT_ABS := $(realpath $(TOP)) PREBUILT_MAKE ?= prebuilts/build-tools/linux-x86/bin/make # we need this check because the Pie build does not have # this prebuilt make tool ifneq (,$(wildcard $(PREBUILT_MAKE))) # for master and versions which has prebuilt make HOST_MAKE := $(PREBUILT_MAKE) # The AOSP build tool is not the regular make, # that it adds -jN to $(MAKE), and that we should preserve # the flag or we would lose parallel build # The MAKE is redefined here in AOSP ckati: # https://android.googlesource.com/platform/build/kati/+/master/main.cc#100 ifneq (,$(filter -j%, $(MAKE))) HOST_MAKE += $(filter -j%, $(MAKE)) endif else # For P and old versions which does not have prebuilt make, # let's use MAKE as what we did before HOST_MAKE := $(MAKE) endif # OPTEE_OUT_DIR could be exported explicitly # if PRODUCT_OUT is not the default out directory in aosp workspace OPTEE_OUT_DIR ?= $(PRODUCT_OUT)/optee ABS_OPTEE_OUT_DIR ?= $(realpath $(PRODUCT_OUT))/optee OPTEE_TA_OUT_DIR ?= $(OPTEE_OUT_DIR)/ta ABS_OPTEE_TA_OUT_DIR ?= $(ABS_OPTEE_OUT_DIR)/ta # Set so that OP-TEE clients can find the installed dev-kit, which # depends on platform and its OP-TEE word-size. OPTEE_OS_OUT_DIR ?= $(OPTEE_OUT_DIR)/arm-plat-$(OPTEE_PLATFORM) ABS_OPTEE_OS_OUT_DIR := $(ABS_OPTEE_OUT_DIR)/arm-plat-$(OPTEE_PLATFORM) ifneq ($(local_optee_ta_target),) TA_TARGET := $(local_optee_ta_target) else TA_TARGET := $(OPTEE_TA_TARGETS) endif TA_DEV_KIT_DIR := $(OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) ABS_TA_DEV_KIT_DIR := $(ABS_OPTEE_OS_OUT_DIR)/export-$(TA_TARGET) CROSS_COMPILE64 ?= $(TOP_ROOT_ABS)/$(TARGET_TOOLS_PREFIX) CROSS_COMPILE_LINE := CROSS_COMPILE64="$(CROSS_COMPILE64)" ifneq ($(strip $($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX)),) CROSS_COMPILE32 ?= $(TOP_ROOT_ABS)/$($(combo_2nd_arch_prefix)TARGET_TOOLS_PREFIX) CROSS_COMPILE_LINE += CROSS_COMPILE32="$(CROSS_COMPILE32)" endif OPTEE_BIN := $(OPTEE_OS_OUT_DIR)/core/tee.bin $(OPTEE_BIN) : $(sort $(shell find -L $(OPTEE_OS_DIR))) OPTEE_TA_DEV_KIT_MK := $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk $(OPTEE_TA_DEV_KIT_MK) : $(sort $(shell find -L $(OPTEE_OS_DIR))) ########################################################### ## define making rules for $(OPTEE_BIN) target, and add ## ## condition check to make it only be defined once ## ## even though this mk file might be included multiple ## ## times. The process to generate $(OPTEE_BIN) file will ## ## generate the header files under ## ## $(TA_DEV_KIT_DIR)/host_include too. ## ## And the $(OPTEE_BIN) will be used as dependency for ## ## other projects ## ########################################################### ifneq (true,$(BUILD_OPTEE_OS_DEFINED)) BUILD_OPTEE_OS_DEFINED := true $(OPTEE_BIN): @echo "Start building optee_os..." +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ O=$(ABS_OPTEE_OS_OUT_DIR) \ CFG_USER_TA_TARGETS=$(OPTEE_TA_TARGETS) \ CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ PLATFORM=$(OPTEE_PLATFORM) \ PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ $(CROSS_COMPILE_LINE) \ $(OPTEE_EXTRA_FLAGS) @echo "Finished building optee_os..." endif ########################################################### ## similar to the $(OPTEE_BIN) target above, use condition ## check to make $(OPTEE_TA_DEV_KIT_MK) for different ta ## targets only be defined once ########################################################### ifeq ($(filter $(TA_TARGET),$(BUILD_TA_DEV_KIT_DEFINED)),) BUILD_TA_DEV_KIT_DEFINED := $(TA_TARGET) $(BUILD_TA_DEV_KIT_DEFINED) $(OPTEE_TA_DEV_KIT_MK): PRIVATE_TA_TARGET := $(TA_TARGET) $(OPTEE_TA_DEV_KIT_MK): @echo "Start building ta_dev_kit ($(PRIVATE_TA_TARGET))..." +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(OPTEE_OS_DIR) \ O=$(ABS_OPTEE_OS_OUT_DIR) \ CFG_USER_TA_TARGETS=$(PRIVATE_TA_TARGET) \ CFG_ARM64_core=$(OPTEE_CFG_ARM64_CORE) \ PLATFORM=$(OPTEE_PLATFORM) \ PLATFORM_FLAVOR=$(OPTEE_PLATFORM_FLAVOR) \ $(CROSS_COMPILE_LINE) \ $(OPTEE_EXTRA_FLAGS) ta_dev_kit @echo "Finished building ta_dev_kit ($(PRIVATE_TA_TARGET))..." endif ########################################################## ## Lines for building TAs automatically ## ## will only be included in Android.mk for TAs ## ## local_module: ## ## need to be defined before include for this ## ########################################################## ifneq (false,$(INCLUDE_FOR_BUILD_TA)) include $(CLEAR_VARS) define ta_class $(if $(filter %.ta,$1),EXECUTABLES,STATIC_LIBRARIES) endef LOCAL_MODULE := $(local_module) LOCAL_PREBUILT_MODULE_FILE := $(OPTEE_TA_OUT_DIR)/$(LOCAL_MODULE) LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/optee_armtz LOCAL_MODULE_CLASS := $(call ta_class,$(local_module)) LOCAL_MODULE_TAGS := optional LOCAL_REQUIRED_MODULES := $(local_module_deps) TA_TMP_DIR := $(addsuffix _$(TA_TARGET), $(subst /,_,$(LOCAL_PATH))) TA_TMP_FILE := $(OPTEE_TA_OUT_DIR)/$(TA_TMP_DIR)/$(LOCAL_MODULE) $(LOCAL_PREBUILT_MODULE_FILE): $(TA_TMP_FILE) @mkdir -p $(dir $@) cp -vf $< $@ TA_TMP_FILE_DEPS := ifneq ($(local_module_deps),) $(foreach dep, $(local_module_deps), $(eval TA_TMP_FILE_DEPS += $(call intermediates-dir-for,$(call ta_class,$(dep)),$(dep))/$(dep))) endif $(TA_TMP_FILE): $(TA_TMP_FILE_DEPS) $(TA_TMP_FILE): PRIVATE_TA_SRC_DIR := $(LOCAL_PATH) $(TA_TMP_FILE): PRIVATE_TA_TMP_FILE := $(TA_TMP_FILE) $(TA_TMP_FILE): PRIVATE_TA_TMP_DIR := $(TA_TMP_DIR) $(TA_TMP_FILE): PRIVATE_TA_DEV_KIT_DIR := $(ABS_TA_DEV_KIT_DIR) $(TA_TMP_FILE): $(OPTEE_TA_DEV_KIT_MK) @echo "Start building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..." +$(HOST_MAKE) -C $(TOP_ROOT_ABS)/$(PRIVATE_TA_SRC_DIR) O=$(ABS_OPTEE_TA_OUT_DIR)/$(PRIVATE_TA_TMP_DIR) \ TA_DEV_KIT_DIR=$(PRIVATE_TA_DEV_KIT_DIR) \ $(CROSS_COMPILE_LINE) \ $(OPTEE_EXTRA_TA_FLAGS) @echo "Finished building TA for $(PRIVATE_TA_SRC_DIR) $(PRIVATE_TA_TMP_FILE)..." include $(BUILD_PREBUILT) # To get ta elf files for early-ta, # copy them to $(PRODUCT_OUT)/unsigned/ on host ifeq ($(call ta_class,$(local_module)),EXECUTABLES) include $(CLEAR_VARS) LOCAL_MODULE := $(local_module).unsigned LOCAL_PREBUILT_MODULE_FILE := $(OPTEE_TA_OUT_DIR)/$(LOCAL_MODULE) LOCAL_MODULE_PATH := $(PRODUCT_OUT)/unsigned LOCAL_MODULE_CLASS := $(call ta_class,$(local_module)) LOCAL_MODULE_TAGS := optional TA_TMP_STRIPPED_ELF_FILE := $(patsubst %.ta,%.stripped.elf,$(TA_TMP_FILE)) $(TA_TMP_STRIPPED_ELF_FILE): $(TA_TMP_FILE) $(LOCAL_PREBUILT_MODULE_FILE): $(TA_TMP_STRIPPED_ELF_FILE) @mkdir -p $(dir $@) cp -vf $< $@ include $(BUILD_PREBUILT) endif # to get ta elf files for early-ta local_module_deps := local_optee_ta_target := endif optee_os-4.3.0/mk/cc-option.mk000066400000000000000000000020121464416617300161750ustar00rootroot00000000000000_cc-option-supported = $(if $(shell $(CC$(sm)) -Werror $(1) -c -x c /dev/null -o /dev/null 2>/dev/null >/dev/null || echo "Not supported"),,1) _cc-opt-cached-var-name = $(subst =,~,$(strip cached-cc-option-$(1)-$(subst $(empty) $(empty),,$(CC$(sm))))) define _cc-option $(eval _var_name := $(call _cc-opt-cached-var-name,$(1))) $(eval $(_var_name) := $(if $(filter $(origin $(_var_name)),undefined),$(call _cc-option-supported,$(1)),$($(_var_name)))) $(if $($(_var_name)),$(1),$(2)) endef cc-option = $(strip $(call _cc-option,$(1),$(2))) _ld-option-supported = $(if $(shell ($(LD$(sm)) -v $(1) 2>&1 || echo warning) | grep warning),,1) _ld-opt-cached-var-name = $(subst =,~,$(subst $(empty) $(empty),,$(strip cached-ld-option-$(1)-$(LD$(sm))))) define _ld-option $(eval _var_name := $(call _ld-opt-cached-var-name,$(1))) $(eval $(_var_name) := $(if $(filter $(origin $(_var_name)),undefined),$(call _ld-option-supported,$(1)),$($(_var_name)))) $(if $($(_var_name)),$(1),$(2)) endef ld-option = $(strip $(call _ld-option,$(1),$(2))) optee_os-4.3.0/mk/checkconf.mk000066400000000000000000000173031464416617300162360ustar00rootroot00000000000000# Generate/check/update a .h file to reflect the values of Makefile # variables # # Example usage (by default, check-conf-h will consider all CFG_* # and _CFG_* variables plus PLATFORM_*): # # path/to/conf.h: FORCE # $(call check-conf-h) # # Or, to include only the variables with the given prefix(es): # # path/to/crypto_config.h: FORCE # $(call check-conf-h,CFG_CRYPTO_ CRYPTO_) define check-conf-h $(q)set -e; \ $(cmd-echo-silent) ' CHK $@'; \ cnf='$(strip $(foreach var, \ $(call cfg-vars-by-prefix,$1), \ $(call cfg-make-define,$(var))))'; \ guardpath="$(patsubst $(out-dir)/%,%,$@)" \ guard="_`echo "$${guardpath}" | tr -- -/.+ _`_"; \ mkdir -p $(dir $@); \ echo "#ifndef $${guard}" >$@.tmp; \ echo "#define $${guard}" >>$@.tmp; \ echo -n "$${cnf}" | sed 's/_nl_ */\n/g' >>$@.tmp; \ echo "#endif" >>$@.tmp; \ $(call mv-if-changed,$@.tmp,$@) endef define check-conf-cmake $(q)set -e; \ $(cmd-echo-silent) ' CHK $@'; \ cnf='$(strip $(foreach var, \ $(call cfg-vars-by-prefix,$1), \ $(call cfg-cmake-set,$(var))))'; \ mkdir -p $(dir $@); \ echo "# auto-generated TEE configuration file" >$@.tmp; \ echo "# TEE version ${TEE_IMPL_VERSION}" >>$@.tmp; \ echo -n "$${cnf}" | sed 's/_nl_ */\n/g' >>$@.tmp; \ $(call mv-if-changed,$@.tmp,$@) endef define check-conf-mk $(q)set -e; \ $(cmd-echo-silent) ' CHK $@'; \ cnf='$(strip $(foreach var, \ $(call cfg-vars-by-prefix,CFG_), \ $(strip $(var)=$($(var))_nl_)))'; \ mkdir -p $(dir $@); \ echo "# auto-generated TEE configuration file" >$@.tmp; \ echo "# TEE version ${TEE_IMPL_VERSION}" >>$@.tmp; \ echo "ARCH=${ARCH}" >>$@.tmp; \ echo "PLATFORM=${PLATFORM}" >>$@.tmp; \ echo "PLATFORM_FLAVOR=${PLATFORM_FLAVOR}" >>$@.tmp; \ echo -n "$${cnf}" | sed 's/_nl_ */\n/g' >>$@.tmp; \ $(call mv-if-changed,$@.tmp,$@) endef define cfg-vars-by-prefix $(strip $(if $(1),$(call _cfg-vars-by-prefix,$(1)), $(call _cfg-vars-by-prefix,CFG_ _CFG_ PLATFORM_))) endef define _cfg-vars-by-prefix $(sort $(foreach prefix,$(1),$(filter $(prefix)%,$(.VARIABLES)))) endef # Convert a makefile variable to a #define # , n => # y => 1 # => define cfg-make-define $(strip $(if $(filter y,$($1)), #define $1 1_nl_, $(if $(filter xn x,x$($1)), /* $1 is not set */_nl_, #define $1 $($1)_nl_))) endef # Convert a makefile variable to a cmake set statement # , n => # => define cfg-cmake-set $(strip $(if $(filter xn x,x$($1)), # $1 is not set _nl_, set($1 $($1))_nl_)) endef # Returns 'y' if at least one variable is 'y', 'n' otherwise # Example: # FOO_OR_BAR := $(call cfg-one-enabled, FOO BAR) cfg-one-enabled = $(if $(filter y, $(foreach var,$(1),$($(var)))),y,n) # Returns 'y' if all variables are 'y', 'n' otherwise # Example: # FOO_AND_BAR := $(call cfg-all-enabled, FOO BAR) cfg-all-enabled = $(if $(strip $(1)),$(if $(call _cfg-all-enabled,$(1)),y,n),n) _cfg-all-enabled = \ $(strip \ $(if $(1), \ $(if $(filter y,$($(firstword $(1)))), \ $(call _cfg-all-enabled,$(filter-out $(firstword $(1)),$(1))), \ ), \ y \ ) \ ) # Disable a configuration variable if some dependency is disabled # Example: # $(eval $(call cfg-depends-all,FOO,BAR BAZ)) # Will set FOO to 'n' if it is initially 'y' and BAR or BAZ are not 'y' cfg-depends-all = \ $(strip \ $(if $(filter y, $($(1))), \ $(if $(filter y,$(call cfg-all-enabled,$(2))), \ , \ $(warning Warning: Disabling $(1) [requires $(strip $(2))]) \ override $(1) := n \ ) \ ) \ ) # Disable a configuration variable if all dependencies are disabled # Example: # $(eval $(call cfg-depends-one,FOO,BAR BAZ)) # Will set FOO to 'n' if it is initially 'y' and both BAR and BAZ are not 'y' cfg-depends-one = \ $(strip \ $(if $(filter y, $($(1))), \ $(if $(filter y,$(call cfg-one-enabled,$(2))), \ , \ $(warning Warning: Disabling $(1) [requires (one of) $(strip $(2))]) \ override $(1) := n \ ) \ ) \ ) # Enable all depend variables # Example: # $(eval $(call cfg-enable-all-depends,FOO,BAR BAZ)) # Will enable BAR and BAZ if FOO is initially 'y' cfg-enable-all-depends = \ $(strip \ $(if $(2), \ $(if $(filter y, $($(1))), \ $(if $(filter y,$($(firstword $(2)))), \ , \ $(warning Warning: Enabling $(firstword $(2)) [required by $(1)]) \ $(eval override $(firstword $(2)) := y) \ ) \ $(call cfg-enable-all-depends,$(1),$(filter-out $(firstword $(2)),$(2))), \ ) \ , \ ) \ ) # Check if a configuration variable has an acceptable value # Example: # $(call cfg-check-value,FOO,foo bar) # Will do nothing if $(CFG_FOO) is either foo or bar, and error out otherwise. cfg-check-value = \ $(if $(filter-out $(2),$(CFG_$(1))), \ $(error CFG_$(1) is set to '$(CFG_$(1))', valid values are: $(2))) # Set a variable or error out if it was previously set to a different value # The reason message (3rd parameter) is optional # Example: # $(call force,CFG_FOO,foo,required by CFG_BAR) define force $(eval $(call _force,$(strip $(1)),$(2),$(3))) endef define _force ifdef $(1) ifneq ($($(1)),$(2)) ifneq (,$(3)) _reason := $$(_empty) [$(3)] endif $$(error $(1) is set to '$($(1))' (from $(origin $(1))) but its value must be '$(2)'$$(_reason)) endif endif $(1) := $(2) endef optee_os-4.3.0/mk/clang.mk000066400000000000000000000042121464416617300153720ustar00rootroot00000000000000# CROSS_COMPILE_$(sm) is derived from CROSS_COMPILE/CROSS_COMPILE32/ # CROSS_COMPILE64 and indicates the target that should be passed to clang. Path # components are ignored, as well as any command before the compiler name (for # instance "/some/path/ccache /other/path/arm-linux-gnueabihf-"). # We try to extract any ccache command if present. clang-target := $(patsubst %-,%,$(notdir $(lastword $(CROSS_COMPILE_$(sm))))) ifeq ($(clang-target),aarch64-linux) clang-target := aarch64-linux-gnu endif ccache-cmd := $(if $(findstring ccache,$(CROSS_COMPILE_$(sm))),$(firstword $(CROSS_COMPILE_$(sm))) ,) CC$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)clang --target=$(clang-target) CXX$(sm) := false # Untested yet # Due to the absence of clang-cpp in AOSP's prebuilt version of clang, # use the equivalent command of 'clang -E' CPP$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)clang --target=$(clang-target) -E LD$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)ld.lld AR$(sm) := $(ccache-cmd)$(OPTEE_CLANG_COMPILER_PATH)llvm-ar NM$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-nm OBJCOPY$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-objcopy OBJDUMP$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-objdump READELF$(sm) := $(OPTEE_CLANG_COMPILER_PATH)llvm-readelf nostdinc$(sm) := -nostdinc -isystem $(shell $(CC$(sm)) \ -print-file-name=include 2> /dev/null) comp-cflags-warns-clang := -Wno-language-extension-token \ -Wno-gnu-zero-variadic-macro-arguments # Note, use the compiler runtime library (libclang_rt.builtins.*.a) instead of # libgcc for clang libgcc$(sm) := $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \ -rtlib=compiler-rt -print-libgcc-file-name 2> /dev/null) # Core ASLR relies on the executable being ready to run from its preferred load # address, because some symbols are used before the MMU is enabled and the # relocations are applied. ldflag-apply-dynamic-relocs := --apply-dynamic-relocs # Define these to something to discover accidental use CC := false CXX := false CPP := false LD := false AR := false NM := false OBJCOPY := false OBJDUMP := false READELF := false nostdinc := --bad-nostdinc-variable libgcc := --bad-libgcc-variable optee_os-4.3.0/mk/cleandirs.mk000066400000000000000000000026761464416617300162660ustar00rootroot00000000000000# Cleaning directories generated during a previous build, # a failed previous build or even no previous build. # Track build directories through 'cleanfiles'. define _enum-parent-dirs $(if $(1),$(1) $(if $(filter / ./,$(dir $(1))),,$(call enum-parent-dirs,$(dir $(1)))),) endef define enum-parent-dirs $(call _enum-parent-dirs,$(patsubst %/,%,$(1))) endef define _reverse $(if $(1),$(call _reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1)) endef # Returns the list of all existing output directories up to $(O) including all # intermediate levels, in depth first order so that rmdir can process them in # order. May return an empty string. # Example: if cleanfiles is "foo/a/file1 foo/b/c/d/file2" and O=foo, this will # return "foo/b/c/d foo/b/c foo/b foo/a" (assuming all exist). define cleandirs-for-rmdir $(eval _O:=$(if $(O),$(O),.))$(wildcard $(addprefix $(_O)/,$(call _reverse, $(sort $(foreach d,$(patsubst $(_O)/%,%,$(dir $(cleanfiles))), $(call enum-parent-dirs,$(d))))))) endef RMDIR := rmdir --ignore-fail-on-non-empty # Remove files with "rm -f". # Split (possibly huge) file list into more manageable lines # (200 files at a time), to minimize the odds of having: # "/bin/bash: Argument list too long" define do-rm-f $(call _do-rm-f, $(wordlist 1, 200, $(1))) \ $(eval _tail := $(wordlist 201, $(words $(1)), $(1))) $(if $(_tail), $(call do-rm-f, $(_tail))) endef define _do-rm-f ${q}rm -f $1 endef optee_os-4.3.0/mk/cleanvars.mk000066400000000000000000000003011464416617300162570ustar00rootroot00000000000000# Cleans all output variables from other make files to allow for a new start gen-srcs := spec-srcs := srcs := objs := libfiles := libdirs := libnames := libdeps := sm-$(sm) := incdirs := optee_os-4.3.0/mk/compile.mk000066400000000000000000000232471464416617300157470ustar00rootroot00000000000000# Input # # The output from mk/sub.mk # base-prefix # conf-file [optional] if set, all objects will depend on $(conf-file) # additional-compile-deps [optional] additional dependencies # # Output # # set objs # update cleanfiles # # Generates explicit rules for all objs objs := # Disable all builtin rules .SUFFIXES: comp-cflags$(sm) = -std=gnu11 comp-aflags$(sm) = comp-cppflags$(sm) = ifeq ($(CFG_WERROR),y) comp-cflags$(sm) += -Werror endif comp-cflags$(sm) += -fdiagnostics-show-option comp-cflags-warns-high = \ -Wall -Wcast-align \ -Werror-implicit-function-declaration -Wextra -Wfloat-equal \ -Wformat-nonliteral -Wformat-security -Wformat=2 -Winit-self \ -Wmissing-declarations -Wmissing-format-attribute \ -Wmissing-include-dirs -Wmissing-noreturn \ -Wmissing-prototypes -Wnested-externs -Wpointer-arith \ -Wshadow -Wstrict-prototypes -Wswitch-default \ -Wwrite-strings \ -Wno-missing-field-initializers -Wno-format-zero-length \ -Wno-c2x-extensions comp-cflags-warns-high += $(call cc-option,-Wpacked-not-aligned) comp-cflags-warns-high += $(call cc-option,-Waddress-of-packed-member) ifeq ($(CFG_WARN_DECL_AFTER_STATEMENT),y) comp-cflags-warns-high += $(call cc-option,-Wdeclaration-after-statement) endif comp-cflags-warns-medium = \ -Wredundant-decls comp-cflags-warns-low = \ -Wold-style-definition -Wstrict-aliasing=2 \ -Wundef comp-cflags-warns-1:= $(comp-cflags-warns-high) comp-cflags-warns-2:= $(comp-cflags-warns-1) $(comp-cflags-warns-medium) comp-cflags-warns-3:= $(comp-cflags-warns-2) $(comp-cflags-warns-low) WARNS ?= 3 comp-cflags$(sm) += $(comp-cflags-warns-$(WARNS)) \ $(comp-cflags-warns-$(COMPILER_$(sm))) CHECK ?= sparse .PHONY: FORCE .PHONY: FORCE-GENSRC$(sm) FORCE: FORCE-GENSRC$(sm): define process_srcs objs += $2 comp-dep-$2 := $$(dir $2).$$(notdir $2).d comp-cmd-file-$2:= $$(dir $2).$$(notdir $2).cmd comp-sm-$2 := $(sm) comp-lib-$2 := $(libname)-$(sm) cleanfiles := $$(cleanfiles) $$(comp-dep-$2) $$(comp-cmd-file-$2) $2 ifeq ($$(filter %.c,$1),$1) comp-q-$2 := CC # one trailing space comp-compiler-$2 := $$(CC$(sm)) comp-flags-$2 = $$(filter-out $$(CFLAGS_REMOVE) $$(cflags-remove) \ $$(cflags-remove-$$(comp-sm-$2)) \ $$(cflags-remove-$2), \ $$(CFLAGS$$(arch-bits-$$(comp-sm-$2))) $$(CFLAGS_WARNS) \ $$(comp-cflags$$(comp-sm-$2)) $$(cflags$$(comp-sm-$2)) \ $$(cflags-lib$$(comp-lib-$2)) $$(cflags-$2)) ifeq ($C,1) check-cmd-$2 = $(CHECK) $$(comp-cppflags-$2) $$< echo-check-$2 := $(cmd-echo-silent) echo-check-cmd-$2 = $(cmd-echo) $$(subst \",\\\",$$(check-cmd-$2)) endif else ifeq ($$(filter %.S,$1),$1) comp-q-$2 := AS # one trailing space comp-compiler-$2 := $$(CC$(sm)) comp-flags-$2 = $$(filter-out $$(AFLAGS_REMOVE) $$(aflags-remove) \ $$(aflags-remove-$$(comp-sm-$2)) \ $$(aflags-remove-$2), \ $$(AFLAGS) $$(comp-aflags$$(comp-sm-$2)) \ $$(aflags$$(comp-sm-$2)) $$(aflags-$2)) else ifeq ($$(filter %.cpp,$1),$1) comp-q-$2 := CXX comp-compiler-$2 := $$(CXX$(sm)) comp-flags-$2 = $$(filter-out $$(CXXFLAGS_REMOVE) $$(cxxflags-remove) \ $$(cxxflags-remove-$$(comp-sm-$2)) \ $$(cxxflags-remove-$2), \ $$(CXXFLAGS) $$(comp-cxxflags$$(comp-sm-$2)) \ $$(cxxflags$$(comp-sm-$2)) $$(cxxflags-$2)) else $$(error "Don't know what to do with $1") endif comp-cppflags-$2 = $$(filter-out $$(CPPFLAGS_REMOVE) $$(cppflags-remove) \ $$(cppflags-remove-$$(comp-sm-$2)) \ $$(cppflags-remove-$2), \ $$(nostdinc$$(comp-sm-$2)) $$(CPPFLAGS) \ $$(addprefix -I,$$(incdirs$$(comp-sm-$2))) \ $$(addprefix -I,$$(incdirs-lib$$(comp-lib-$2))) \ $$(addprefix -I,$$(incdirs-$2)) \ $$(cppflags$$(comp-sm-$2)) \ $$(cppflags-lib$$(comp-lib-$2)) $$(cppflags-$2)) \ -D__FILE_ID__=$$(subst -,_,$$(subst /,_,$$(subst .,_,$1))) comp-flags-$2 += -MD -MF $$(comp-dep-$2) -MT $$@ comp-flags-$2 += $$(comp-cppflags-$2) comp-cmd-$2 = $$(comp-compiler-$2) $$(comp-flags-$2) -c $$< -o $$@ comp-objcpy-cmd-$2 = $$(OBJCOPY$(sm)) \ --rename-section .rodata=.rodata.$1 \ --rename-section .rodata.str1.1=.rodata.str1.1.$1 \ $2 # Assign defaults if unassigned echo-check-$2 ?= true echo-check-cmd-$2 ?= true check-cmd-$2 ?= true -include $$(comp-cmd-file-$2) -include $$(comp-dep-$2) $2: $1 FORCE-GENSRC$(sm) # Check if any prerequisites are newer than the target and # check if command line has changed $$(if $$(strip $$(filter-out FORCE-GENSRC$(sm), $$?) \ $$(filter-out $$(comp-cmd-$2), $$(old-cmd-$2)) \ $$(filter-out $$(old-cmd-$2), $$(comp-cmd-$2))), \ @set -e ;\ mkdir -p $$(dir $2) ;\ $$(echo-check-$2) ' CHECK $$<' ;\ $$(echo-check-cmd-$2) ;\ $$(check-cmd-$2) ;\ $(cmd-echo-silent) ' $$(comp-q-$2) $$@' ;\ $(cmd-echo) $$(subst \",\\\",$$(comp-cmd-$2)) ;\ $$(comp-cmd-$2) ;\ $(cmd-echo) $$(comp-objcpy-cmd-$2) ;\ $$(comp-objcpy-cmd-$2) ;\ echo "old-cmd-$2 := $$(subst \",\\\",$$(comp-cmd-$2))" > \ $$(comp-cmd-file-$2) ;\ ) endef $(foreach f, $(srcs), $(eval $(call \ process_srcs,$(f),$(out-dir)/$(base-prefix)$$(basename $f).o))) # Handle generated source files, that is, files that are compiled from out-dir $(foreach f, $(gen-srcs), $(eval $(call process_srcs,$(f),$$(basename $f).o))) # Handle specified source files, that is, files that have a specified path # but where the object file should go into a specified out directory $(foreach f, $(spec-srcs), $(eval $(call \ process_srcs,$(f),$(spec-out-dir)/$$(notdir $$(basename $f)).o))) $(objs): $(conf-file) $(additional-compile-deps) define _gen-asm-defines-file # c-filename in $1 # h-filename in $2 # s-filename in $3 # Dependencies in $4 FORCE-GENSRC$(sm): $(2) comp-dep-$3 := $$(dir $3)$$(notdir $3).d comp-cmd-file-$3:= $$(dir $3)$$(notdir $3).cmd comp-sm-$3 := $(sm) cleanfiles := $$(cleanfiles) $$(comp-dep-$3) $$(comp-cmd-file-$3) $3 $2 comp-flags-$3 = $$(filter-out $$(CFLAGS_REMOVE) $$(cflags-remove) \ $$(cflags-remove-$$(comp-sm-$3)) \ $$(cflags-remove-$3), \ $$(CFLAGS) $$(CFLAGS_WARNS) \ $$(comp-cflags$$(comp-sm-$3)) $$(cflags$$(comp-sm-$3)) \ $$(cflags-lib$$(comp-lib-$3)) $$(cflags-$3)) comp-cppflags-$3 = $$(filter-out $$(CPPFLAGS_REMOVE) $$(cppflags-remove) \ $$(cppflags-remove-$$(comp-sm-$3)) \ $$(cppflags-remove-$3), \ $$(nostdinc$$(comp-sm-$3)) $$(CPPFLAGS) \ $$(addprefix -I,$$(incdirs$$(comp-sm-$3))) \ $$(addprefix -I,$$(incdirs-lib$$(comp-lib-$3))) \ $$(addprefix -I,$$(incdirs-$3)) \ $$(cppflags$$(comp-sm-$3)) \ $$(cppflags-lib$$(comp-lib-$3)) $$(cppflags-$3)) comp-flags-$3 += -MD -MF $$(comp-dep-$3) -MT $$@ comp-flags-$3 += $$(comp-cppflags-$3) comp-cmd-$3 = $$(CC$(sm)) $$(comp-flags-$3) -fverbose-asm -S $$< -o $$@ -include $$(comp-cmd-file-$3) -include $$(comp-dep-$3) $3: $1 $(conf-file) $(4) FORCE # Check if any prerequisites are newer than the target and # check if command line has changed $$(if $$(strip $$(filter-out FORCE, $$?) \ $$(filter-out $$(comp-cmd-$3), $$(old-cmd-$3)) \ $$(filter-out $$(old-cmd-$3), $$(comp-cmd-$3))), \ @set -e ;\ mkdir -p $$(dir $2) $$(dir $3) ;\ $(cmd-echo-silent) ' CC $$@'; \ $(cmd-echo) $$(subst \",\\\",$$(comp-cmd-$3)) ;\ $$(comp-cmd-$3) ;\ echo "old-cmd-$3 := $$(subst \",\\\",$$(comp-cmd-$3))" > \ $$(comp-cmd-file-$3) ;\ ) guard-$2 := $$(subst -,_,$$(subst .,_,$$(subst /,_,$$(subst +,_,$2)))) $(2): $(3) $(q)set -e; \ $(cmd-echo-silent) ' CHK $$@'; \ mkdir -p $$(dir $$@); \ echo "#ifndef $$(guard-$2)" >$$@.tmp; \ echo "#define $$(guard-$2)" >>$$@.tmp; \ sed -ne 's|^.*==>\([^ ]*\) [\$$$$#]*\([-0-9]*\) \([^@/]*\).*|#define \1\t\2\t/* \3*/|p' \ < $$< >>$$@.tmp; \ echo "#endif" >>$$@.tmp; \ $$(call mv-if-changed,$$@.tmp,$$@) endef define gen-asm-defines-file $(call _gen-asm-defines-file,$1,$2,$(dir $2).$(notdir $(2:.h=.s)),$(asm-defines-$(notdir $(1))-deps)) endef $(foreach f,$(asm-defines-files),$(eval $(call gen-asm-defines-file,$(f),$(out-dir)/$(sm)/include/generated/$(basename $(notdir $(f))).h))) # Device tree source file compilation DTC := dtc DTC_FLAGS += -I dts -O dtb DTC_FLAGS += -Wno-unit_address_vs_reg define gen-dtb-file # dts file path/name in $1 # dtb file path/name in $2 dtb-basename-$2 := $$(basename $$(notdir $2)) dtb-predts-$2 := $$(dir $2)$$(dtb-basename-$2).pre.dts dtb-predep-$2 := $$(dir $2).$$(dtb-basename-$2).pre.dts.d dtb-dep-$2 := $$(dir $2).$$(notdir $2).d dtb-cmd-file-$2 := $$(dir $2).$$(notdir $2).cmd cleanfiles := $$(cleanfiles) $2 \ $$(dtb-predts-$2) $$(dtb-predep-$2) \ $$(dtb-dep-$2) $$(dtb-cmd-file-$2) dtb-cppflags-$2 := -Icore/include/ -x assembler-with-cpp -Ulinux -Uunix \ -E -ffreestanding $$(CPPFLAGS) \ -MD -MF $$(dtb-predep-$2) -MT $2 dtb-dtcflags-$2 := $$(DTC_FLAGS) -d $$(dtb-dep-$2) -include $$(dtb-dep-$2) -include $$(dtb-predep-$2) -include $$(dtb-cmd-file-$2) dtb-precmd-$2 = $$(CPP$(sm)) $$(dtb-cppflags-$2) -o $$(dtb-predts-$2) $$< dtb-cmd-$2 = $$(DTC) $$(dtb-dtcflags-$2) -o $$@ $$(dtb-predts-$2) $2: $1 FORCE # Check if any prerequisites are newer than the target and # check if command line has changed $$(if $$(strip $$(filter-out FORCE, $$?) \ $$(filter-out $$(dtb-precmd-$2), $$(dtb-old-precmd-$2)) \ $$(filter-out $$(dtb-old-precmd-$2), $$(dtb-precmd-$2)) \ $$(filter-out $$(dtb-cmd-$2), $$(dtb-old-cmd-$2)) \ $$(filter-out $$(dtb-old-cmd-$2), $$(dtb-cmd-$2))), \ @set -e; \ mkdir -p $$(dir $2); \ $(cmd-echo-silent) ' CPP $$(dtb-predts-$2)'; \ $$(dtb-precmd-$2); \ $(cmd-echo-silent) ' DTC $$@'; \ $$(dtb-cmd-$2); \ echo "dtb-old-precmd-$2 := $$(subst \",\\\",$$(dtb-precmd-$2))" > \ $$(dtb-cmd-file-$2) ;\ echo "dtb-old-cmd-$2 := $$(subst \",\\\",$$(dtb-cmd-$2))" >> \ $$(dtb-cmd-file-$2) ;\ ) endef additional-compile-deps := optee_os-4.3.0/mk/config.mk000066400000000000000000001415221464416617300155610ustar00rootroot00000000000000# Default configuration values for OP-TEE core (all platforms). # # Platform-specific overrides are in core/arch/arm32/plat-*/conf.mk. # Some subsystem-specific defaults are not here but rather in */sub.mk. # # Configuration values may be assigned from multiple sources. # From higher to lower priority: # # 1. Make arguments ('make CFG_FOO=bar...') # 2. The file specified by $(CFG_OPTEE_CONFIG) (if defined) # 3. The environment ('CFG_FOO=bar make...') # 4. The platform-specific configuration file: core/arch/arm32/plat-*/conf.mk # 5. This file # 6. Subsystem-specific makefiles (*/sub.mk) # # Actual values used during the build are output to $(out-dir)/conf.mk # (CFG_* variables only). # Cross-compiler prefix and suffix ifeq ($(ARCH),arm) CROSS_COMPILE ?= arm-linux-gnueabihf- CROSS_COMPILE64 ?= aarch64-linux-gnu- endif ifeq ($(ARCH),riscv) CROSS_COMPILE ?= riscv-linux-gnu- CROSS_COMPILE64 ?= riscv64-linux-gnu- endif CROSS_COMPILE32 ?= $(CROSS_COMPILE) COMPILER ?= gcc # For convenience ifdef CFLAGS CFLAGS32 ?= $(CFLAGS) CFLAGS64 ?= $(CFLAGS) endif # Compiler warning level. # Supported values: undefined, 1, 2 and 3. 3 gives more warnings. WARNS ?= 3 # Path to the Python interpreter used by the build system. # This variable is set to the default python3 interpreter in the user's # path. But build environments that require more explicit control can # set the path to a specific interpreter through this variable. PYTHON3 ?= python3 # Define DEBUG=1 to compile without optimization (forces -O0) # DEBUG=1 ifeq ($(DEBUG),1) # For backwards compatibility $(call force,CFG_CC_OPT_LEVEL,0) $(call force,CFG_DEBUG_INFO,y) endif # CFG_CC_OPT_LEVEL sets compiler optimization level passed with -O directive. # Optimize for size by default, usually gives good performance too. CFG_CC_OPT_LEVEL ?= s # Enabling CFG_DEBUG_INFO makes debug information embedded in core. CFG_DEBUG_INFO ?= y # If y, enable debug features of the TEE core (assertions and lock checks # are enabled, panic and assert messages are more verbose, data and prefetch # aborts show a stack dump). When disabled, the NDEBUG directive is defined # so assertions are disabled. CFG_TEE_CORE_DEBUG ?= y # Log levels for the TEE core. Defines which core messages are displayed # on the secure console. Disabling core log (level set to 0) also disables # logs from the TAs. # 0: none # 1: error # 2: error + info # 3: error + info + debug # 4: error + info + debug + flow CFG_TEE_CORE_LOG_LEVEL ?= 2 # TA log level # If user-mode library libutils.a is built with CFG_TEE_TA_LOG_LEVEL=0, # TA tracing is disabled regardless of the value of CFG_TEE_TA_LOG_LEVEL # when the TA is built. CFG_TEE_TA_LOG_LEVEL ?= 1 # TA enablement # When defined to "y", TA traces are output according to # CFG_TEE_TA_LOG_LEVEL. Otherwise, they are not output at all CFG_TEE_CORE_TA_TRACE ?= y # If y, enable the memory leak detection feature in the bget memory allocator. # When this feature is enabled, calling mdbg_check(1) will print a list of all # the currently allocated buffers and the location of the allocation (file and # line number). # Note: make sure the log level is high enough for the messages to show up on # the secure console! For instance: # - To debug user-mode (TA) allocations: build OP-TEE *and* the TA with: # $ make CFG_TEE_TA_MALLOC_DEBUG=y CFG_TEE_TA_LOG_LEVEL=3 # - To debug TEE core allocations: build OP-TEE with: # $ make CFG_TEE_CORE_MALLOC_DEBUG=y CFG_TEE_CORE_LOG_LEVEL=3 CFG_TEE_CORE_MALLOC_DEBUG ?= n CFG_TEE_TA_MALLOC_DEBUG ?= n # Prints an error message and dumps the stack on failed memory allocations # using malloc() and friends. CFG_CORE_DUMP_OOM ?= $(CFG_TEE_CORE_MALLOC_DEBUG) # Mask to select which messages are prefixed with long debugging information # (severity, core ID, thread ID, component name, function name, line number) # based on the message level. If BIT(level) is set, the long prefix is shown. # Otherwise a short prefix is used (severity and component name only). # Levels: 0=none 1=error 2=info 3=debug 4=flow CFG_MSG_LONG_PREFIX_MASK ?= 0x1a # Number of threads CFG_NUM_THREADS ?= 2 # API implementation version CFG_TEE_API_VERSION ?= GPD-1.1-dev # Implementation description (implementation-dependent) CFG_TEE_IMPL_DESCR ?= OPTEE # Should OPTEE_SMC_CALL_GET_OS_REVISION return a build identifier to Normal # World? CFG_OS_REV_REPORTS_GIT_SHA1 ?= y # The following values are not extracted from the "git describe" output because # we might be outside of a Git environment, or the tree may have been cloned # with limited depth not including any tag, so there is really no guarantee # that TEE_IMPL_VERSION contains the major and minor revision numbers. CFG_OPTEE_REVISION_MAJOR ?= 4 CFG_OPTEE_REVISION_MINOR ?= 3 CFG_OPTEE_REVISION_EXTRA ?= # Trusted OS implementation version TEE_IMPL_VERSION ?= $(shell git describe --always --dirty=-dev 2>/dev/null || \ echo Unknown_$(CFG_OPTEE_REVISION_MAJOR).$(CFG_OPTEE_REVISION_MINOR))$(CFG_OPTEE_REVISION_EXTRA) # Trusted OS implementation manufacturer name CFG_TEE_MANUFACTURER ?= LINARO # Trusted firmware version CFG_TEE_FW_IMPL_VERSION ?= FW_IMPL_UNDEF # Trusted OS implementation manufacturer name CFG_TEE_FW_MANUFACTURER ?= FW_MAN_UNDEF # Rich Execution Environment (REE) file system support: normal world OS # provides the actual storage. # This is the default FS when enabled (i.e., the one used when # TEE_STORAGE_PRIVATE is passed to the trusted storage API) CFG_REE_FS ?= y # RPMB file system support CFG_RPMB_FS ?= n # Enable roll-back protection of REE file system using RPMB. # Roll-back protection only works if CFG_RPMB_FS = y. CFG_REE_FS_INTEGRITY_RPMB ?= $(CFG_RPMB_FS) $(eval $(call cfg-depends-all,CFG_REE_FS_INTEGRITY_RPMB,CFG_RPMB_FS)) # Device identifier used when CFG_RPMB_FS = y. # The exact meaning of this value is platform-dependent. On Linux, the # tee-supplicant process will open /dev/mmcblkrpmb CFG_RPMB_FS_DEV_ID ?= 0 # This config variable determines the number of entries read in from RPMB at # once whenever a function traverses the RPMB FS. Increasing the default value # has the following consequences: # - More memory required on heap. A single FAT entry currently has a size of # 256 bytes. # - Potentially significant speed-ups for RPMB I/O. Depending on how many # entries a function needs to traverse, the number of time-consuming RPMB # read-in operations can be reduced. # Chosing a proper value is both platform- (available memory) and use-case- # dependent (potential number of FAT fs entries), so overwrite in platform # config files CFG_RPMB_FS_RD_ENTRIES ?= 8 # Enables caching of FAT FS entries when set to a value greater than zero. # When enabled, the cache stores the first 'CFG_RPMB_FS_CACHE_ENTRIES' FAT FS # entries. The cache is populated when FAT FS entries are initially read in. # When traversing the FAT FS entries, we read from the cache instead of reading # in the entries from RPMB storage. Consequently, when a FAT FS entry is # written, the cache is updated. In scenarios where an estimate of the number # of FAT FS entries can be made, the cache may be specifically tailored to # store all entries. The caching can improve RPMB I/O at the cost # of additional memory. # Without caching, we temporarily require # CFG_RPMB_FS_RD_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory # while traversing the FAT FS (e.g. in read_fat). # For example 8*256 bytes = 2kB while in read_fat. # With caching, we constantly require up to # CFG_RPMB_FS_CACHE_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory # depending on how many elements are in the cache, and additional temporary # CFG_RPMB_FS_RD_ENTRIES*sizeof(struct rpmb_fat_entry) bytes of heap memory # in case the cache is too small to hold all elements when traversing. CFG_RPMB_FS_CACHE_ENTRIES ?= 0 # Print RPMB data frames sent to and received from the RPMB device CFG_RPMB_FS_DEBUG_DATA ?= n # Clear RPMB content at cold boot CFG_RPMB_RESET_FAT ?= n # Use a hard coded RPMB key instead of deriving it from the platform HUK CFG_RPMB_TESTKEY ?= n # Enables RPMB key programming by the TEE, in case the RPMB partition has not # been configured yet. # !!! Security warning !!! # Do *NOT* enable this in product builds, as doing so would allow the TEE to # leak the RPMB key. # This option is useful in the following situations: # - Testing # - RPMB key provisioning in a controlled environment (factory setup) CFG_RPMB_WRITE_KEY ?= n _CFG_WITH_SECURE_STORAGE := $(call cfg-one-enabled,CFG_REE_FS CFG_RPMB_FS) # Signing key for OP-TEE TA's # When performing external HSM signing for TA's TA_SIGN_KEY can be set to dummy # key and then set TA_PUBLIC_KEY to match public key from the HSM. # TA_PUBLIC_KEY's public key will be embedded into OP-TEE OS. TA_SIGN_KEY ?= keys/default_ta.pem TA_PUBLIC_KEY ?= $(TA_SIGN_KEY) # Subkeys is a complement to the normal TA_SIGN_KEY where a subkey is used # to verify a TA instead. To sign a TA using a previously prepared subkey # two new options are added, TA_SUBKEY_ARGS and TA_SUBKEY_DEPS. It is # typically used by assigning the following in the TA Makefile: # BINARY = # TA_SIGN_KEY = subkey.pem # TA_SUBKEY_ARGS = --subkey subkey.bin --name subkey_ta # TA_SUBKEY_DEPS = subkey.bin # See the documentation for more details on subkeys. # Include lib/libutils/isoc in the build? Most platforms need this, but some # may not because they obtain the isoc functions from elsewhere CFG_LIBUTILS_WITH_ISOC ?= y # Enables floating point support for user TAs # ARM32: EABI defines both a soft-float ABI and a hard-float ABI, # hard-float is basically a super set of soft-float. Hard-float # requires all the support routines provided for soft-float, but the # compiler may choose to optimize to not use some of them and use # the floating-point registers instead. # ARM64: EABI doesn't define a soft-float ABI, everything is hard-float (or # nothing with ` -mgeneral-regs-only`) # With CFG_TA_FLOAT_SUPPORT enabled TA code is free use floating point types CFG_TA_FLOAT_SUPPORT ?= y # Stack unwinding: print a stack dump to the console on core or TA abort, or # when a TA panics. # If CFG_UNWIND is enabled, both the kernel and user mode call stacks can be # unwound (not paged TAs, however). # Note that 32-bit ARM code needs unwind tables for this to work, so enabling # this option will increase the size of the 32-bit TEE binary by a few KB. # Similarly, TAs have to be compiled with -funwind-tables (default when the # option is set) otherwise they can't be unwound. # Warning: since the unwind sequence for user-mode (TA) code is implemented in # the privileged layer of OP-TEE, enabling this feature will weaken the # user/kernel isolation. Therefore it should be disabled in release builds. ifeq ($(CFG_TEE_CORE_DEBUG),y) CFG_UNWIND ?= y endif # Enable support for dynamically loaded user TAs CFG_WITH_USER_TA ?= y # Build user TAs included in this source tree CFG_BUILD_IN_TREE_TA ?= y # Choosing the architecture(s) of user-mode libraries (used by TAs) # # Platforms may define a list of supported architectures for user-mode code # by setting $(supported-ta-targets). Valid values are "ta_arm32", "ta_arm64", # "ta_arm32 ta_arm64" and "ta_arm64 ta_arm32". # $(supported-ta-targets) defaults to "ta_arm32" when the TEE core is 32-bits, # and "ta_arm32 ta_arm64" when it is 64-bits (that is, when CFG_ARM64_core=y). # The first entry in $(supported-ta-targets) has a special role, see # CFG_USER_TA_TARGET_ below. # # CFG_USER_TA_TARGETS may be defined to restrict $(supported-ta-targets) or # change the order of the values. # # The list of TA architectures is ultimately stored in $(ta-targets). # CFG_USER_TA_TARGET_ (for example, CFG_USER_TA_TARGET_avb), if # defined, selects the unique TA architecture mode for building the in-tree TA # . Can be either ta_arm32 or ta_arm64. # By default, in-tree TAs are built using the first architecture specified in # $(ta-targets). # Address Space Layout Randomization for user-mode Trusted Applications # # When this flag is enabled, the ELF loader will introduce a random offset # when mapping the application in user space. ASLR makes the exploitation of # memory corruption vulnerabilities more difficult. CFG_TA_ASLR ?= y # How much ASLR may shift the base address (in pages). The base address is # randomly shifted by an integer number of pages comprised between these two # values. Bigger ranges are more secure because they make the addresses harder # to guess at the expense of using more memory for the page tables. CFG_TA_ASLR_MIN_OFFSET_PAGES ?= 0 CFG_TA_ASLR_MAX_OFFSET_PAGES ?= 128 # Address Space Layout Randomization for TEE Core # # When this flag is enabled, the early init code will introduce a random # offset when mapping TEE Core. ASLR makes the exploitation of memory # corruption vulnerabilities more difficult. CFG_CORE_ASLR ?= y # Stack Protection for TEE Core # This flag enables the compiler stack protection mechanisms -fstack-protector. # It will check the stack canary value before returning from a function to # prevent buffer overflow attacks. Stack protector canary logic will be added # for vulnerable functions that contain: # - A character array larger than 8 bytes. # - An 8-bit integer array larger than 8 bytes. # - A call to alloca() with either a variable size or a constant size bigger # than 8 bytes. CFG_CORE_STACK_PROTECTOR ?= n # This enable stack protector flag -fstack-protector-strong. Stack protector # canary logic will be added for vulnerable functions that contain: # - An array of any size and type. # - A call to alloca(). # - A local variable that has its address taken. CFG_CORE_STACK_PROTECTOR_STRONG ?= y # This enable stack protector flag -fstack-protector-all. Stack protector canary # logic will be added to all functions regardless of their vulnerability. CFG_CORE_STACK_PROTECTOR_ALL ?= n # Stack Protection for TA CFG_TA_STACK_PROTECTOR ?= n CFG_TA_STACK_PROTECTOR_STRONG ?= y CFG_TA_STACK_PROTECTOR_ALL ?= n _CFG_CORE_STACK_PROTECTOR := $(call cfg-one-enabled, CFG_CORE_STACK_PROTECTOR \ CFG_CORE_STACK_PROTECTOR_STRONG \ CFG_CORE_STACK_PROTECTOR_ALL) _CFG_TA_STACK_PROTECTOR := $(call cfg-one-enabled, CFG_TA_STACK_PROTECTOR \ CFG_TA_STACK_PROTECTOR_STRONG \ CFG_TA_STACK_PROTECTOR_ALL) # Load user TAs from the REE filesystem via tee-supplicant CFG_REE_FS_TA ?= y # Pre-authentication of TA binaries loaded from the REE filesystem # # - If CFG_REE_FS_TA_BUFFERED=y: load TA binary into a temporary buffer in the # "Secure DDR" pool, check the signature, then process the file only if it is # valid. # - If disabled: hash the binaries as they are being processed and verify the # signature as a last step. CFG_REE_FS_TA_BUFFERED ?= n $(eval $(call cfg-depends-all,CFG_REE_FS_TA_BUFFERED,CFG_REE_FS_TA)) # When CFG_REE_FS=y: # Allow secure storage in the REE FS to be entirely deleted without causing # anti-rollback errors. That is, rm /data/tee/dirf.db or rm -rf /data/tee (or # whatever path is configured in tee-supplicant as CFG_TEE_FS_PARENT_PATH) # can be used to reset the secure storage to a clean, empty state. # Intended to be used for testing only since it weakens storage security. # Warning: If enabled for release build then it will break rollback protection # of TAs and the entire REE FS secure storage. CFG_REE_FS_ALLOW_RESET ?= n # Support for loading user TAs from a special section in the TEE binary. # Such TAs are available even before tee-supplicant is available (hence their # name), but note that many services exported to TAs may need tee-supplicant, # so early use is limited to a subset of the TEE Internal Core API (crypto...) # To use this feature, set EARLY_TA_PATHS to the paths to one or more TA ELF # file(s). For example: # $ make ... \ # EARLY_TA_PATHS="path/to/8aaaf200-2450-11e4-abe2-0002a5d5c51b.stripped.elf \ # path/to/cb3e5ba0-adf1-11e0-998b-0002a5d5c51b.stripped.elf" # Typical build steps: # $ make ta_dev_kit CFG_EARLY_TA=y # Create the dev kit (user mode libraries, # # headers, makefiles), ready to build TAs. # # CFG_EARLY_TA=y is optional, it prevents # # later library recompilations. # # $ make EARLY_TA_PATHS= # Build OP-TEE and embbed the TA(s) # # Another option is CFG_IN_TREE_EARLY_TAS which is used to point at # in-tree TAs. CFG_IN_TREE_EARLY_TAS is formatted as: # / # for instance avb/023f8f1a-292a-432b-8fc4-de8471358067 ifneq ($(EARLY_TA_PATHS)$(CFG_IN_TREE_EARLY_TAS),) $(call force,CFG_EARLY_TA,y) else CFG_EARLY_TA ?= n endif ifeq ($(CFG_EARLY_TA),y) $(call force,CFG_EMBEDDED_TS,y) endif ifneq ($(SP_PATHS),) $(call force,CFG_EMBEDDED_TS,y) else CFG_SECURE_PARTITION ?= n endif ifeq ($(CFG_SECURE_PARTITION),y) $(call force,CFG_EMBEDDED_TS,y) endif ifeq ($(CFG_EMBEDDED_TS),y) $(call force,CFG_ZLIB,y) endif # By default the early TAs are compressed in the TEE binary, it is possible to # not compress them with CFG_EARLY_TA_COMPRESS=n CFG_EARLY_TA_COMPRESS ?= y # Enable paging, requires SRAM, can't be enabled by default CFG_WITH_PAGER ?= n # Use the pager for user TAs CFG_PAGED_USER_TA ?= $(CFG_WITH_PAGER) # If paging of user TAs, that is, R/W paging default to enable paging of # TAG and IV in order to reduce heap usage. CFG_CORE_PAGE_TAG_AND_IV ?= $(CFG_PAGED_USER_TA) # Runtime lock dependency checker: ensures that a proper locking hierarchy is # used in the TEE core when acquiring and releasing mutexes. Any violation will # cause a panic as soon as the invalid locking condition is detected. If # CFG_UNWIND and CFG_LOCKDEP_RECORD_STACK are both enabled, the algorithm # records the call stacks when locks are taken, and prints them when a # potential deadlock is found. # Expect a significant performance impact when enabling this. CFG_LOCKDEP ?= n CFG_LOCKDEP_RECORD_STACK ?= y # BestFit algorithm in bget reduces the fragmentation of the heap when running # with the pager enabled or lockdep CFG_CORE_BGET_BESTFIT ?= $(call cfg-one-enabled, CFG_WITH_PAGER CFG_LOCKDEP) # Enable support for detected undefined behavior in C # Uses a lot of memory, can't be enabled by default CFG_CORE_SANITIZE_UNDEFINED ?= n # Enable Kernel Address sanitizer, has a huge performance impact, uses a # lot of memory and need platform specific adaptations, can't be enabled by # default CFG_CORE_SANITIZE_KADDRESS ?= n ifeq (y-y,$(CFG_CORE_SANITIZE_KADDRESS)-$(CFG_CORE_ASLR)) $(error CFG_CORE_SANITIZE_KADDRESS and CFG_CORE_ASLR are not compatible) endif # Add stack guards before/after stacks and periodically check them CFG_WITH_STACK_CANARIES ?= y # Use compiler instrumentation to troubleshoot stack overflows. # When enabled, most C functions check the stack pointer against the current # stack limits on entry and panic immediately if it is out of range. CFG_CORE_DEBUG_CHECK_STACKS ?= n # Use when the default stack allocations are not sufficient. CFG_STACK_THREAD_EXTRA ?= 0 CFG_STACK_TMP_EXTRA ?= 0 # Device Tree support # # When CFG_DT is enabled core embeds the FDT library (libfdt) allowing # device tree blob (DTB) parsing from the core. # # When CFG_DT is enabled, the TEE _start function expects to find # the address of a DTB in register X2/R2 provided by the early boot stage # or value 0 if boot stage provides no DTB. # # When CFG_EXTERNAL_DT is enabled, the external device tree ABI is implemented # and the external device tree is expected to be used/modified. Its value # defaults to CFG_DT. # # When CFG_MAP_EXT_DT_SECURE is enabled the external device tree is expected to # be in the secure memory. # # When CFG_EMBED_DTB is enabled, CFG_EMBED_DTB_SOURCE_FILE shall define the # relative path of a DTS file located in core/arch/$(ARCH)/dts. # The DTS file is compiled into a DTB file which content is embedded in a # read-only section of the core. ifneq ($(strip $(CFG_EMBED_DTB_SOURCE_FILE)),) CFG_EMBED_DTB ?= y endif ifeq ($(filter y,$(CFG_EMBED_DTB) $(CFG_CORE_SEL1_SPMC) $(CFG_CORE_SEL2_SPMC) \ $(CFG_CORE_EL3_SPMC)),y) $(call force,CFG_DT,y) endif CFG_EMBED_DTB ?= n CFG_DT ?= n CFG_EXTERNAL_DT ?= $(CFG_DT) CFG_MAP_EXT_DT_SECURE ?= n ifeq ($(CFG_MAP_EXT_DT_SECURE),y) $(call force,CFG_DT,y) endif # This option enables OP-TEE to support boot arguments handover via Transfer # List defined in Firmware Handoff specification. # Note: This is an experimental feature and incompatible ABI changes can be # expected. It should be off by default until Firmware Handoff specification # has a stable release. # This feature requires the support of Device Tree. CFG_TRANSFER_LIST ?= n ifeq ($(CFG_TRANSFER_LIST),y) $(call force,CFG_DT,y) $(call force,CFG_EXTERNAL_DT,y) $(call force,CFG_MAP_EXT_DT_SECURE,y) endif # Maximum size of the Device Tree Blob, has to be large enough to allow # editing of the supplied DTB. CFG_DTB_MAX_SIZE ?= 0x10000 # Maximum size of the init info data passed to Secure Partitions. CFG_SP_INIT_INFO_MAX_SIZE ?= 0x1000 # Device Tree Overlay support. # CFG_EXTERNAL_DTB_OVERLAY allows to append a DTB overlay into an existing # external DTB. The overlay is created when no valid DTB overlay is found. # CFG_GENERATE_DTB_OVERLAY allows to create a DTB overlay at external # DTB location. # External DTB location (physical address) is provided either by boot # argument arg2 or from CFG_DT_ADDR if defined. # A subsequent boot stage can then merge the generated overlay DTB into a main # DTB using the standard fdt_overlay_apply() method. CFG_EXTERNAL_DTB_OVERLAY ?= n CFG_GENERATE_DTB_OVERLAY ?= n ifeq (y-y,$(CFG_EXTERNAL_DTB_OVERLAY)-$(CFG_GENERATE_DTB_OVERLAY)) $(error CFG_EXTERNAL_DTB_OVERLAY and CFG_GENERATE_DTB_OVERLAY are exclusive) endif _CFG_USE_DTB_OVERLAY := $(call cfg-one-enabled,CFG_EXTERNAL_DTB_OVERLAY \ CFG_GENERATE_DTB_OVERLAY) # All embedded tests are supposed to be disabled by default, this flag # is used to control the default value of all other embedded tests CFG_ENABLE_EMBEDDED_TESTS ?= n # Enable core self tests and related pseudo TAs CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= $(CFG_ENABLE_EMBEDDED_TESTS) # Compiles bget_main_test() to be called from a test TA CFG_TA_BGET_TEST ?= $(CFG_ENABLE_EMBEDDED_TESTS) # CFG_DT_DRIVER_EMBEDDED_TEST when enabled embedded DT driver probing tests. # This also requires embedding a DTB with expected content. # Default disable CFG_DRIVERS_CLK_EARLY_PROBE to probe clocks as other drivers. # A probe deferral test mandates CFG_DRIVERS_DT_RECURSIVE_PROBE=n. CFG_DT_DRIVER_EMBEDDED_TEST ?= n ifeq ($(CFG_DT_DRIVER_EMBEDDED_TEST),y) CFG_DRIVERS_CLK ?= y CFG_DRIVERS_GPIO ?= y CFG_DRIVERS_RSTCTRL ?= y CFG_DRIVERS_CLK_EARLY_PROBE ?= n $(call force,CFG_DRIVERS_DT_RECURSIVE_PROBE,n,Mandated by CFG_DT_DRIVER_EMBEDDED_TEST) endif # CFG_WITH_STATS when enabled embeds PTA statistics service to allow non-secure # clients to retrieve debug and statistics information on core and loaded TAs. CFG_WITH_STATS ?= n # CFG_DRIVERS_DT_RECURSIVE_PROBE when enabled forces a recursive subnode # parsing in the embedded DTB for driver probing. The alternative is # an exploration based on compatible drivers found. It is default disabled. CFG_DRIVERS_DT_RECURSIVE_PROBE ?= n # This option enables OP-TEE to respond to SMP boot request: the Rich OS # issues this to request OP-TEE to release secondaries cores out of reset, # with specific core number and non-secure entry address. CFG_BOOT_SECONDARY_REQUEST ?= n # Default heap size for Core, 64 kB CFG_CORE_HEAP_SIZE ?= 65536 # Default size of nexus heap. 16 kB. Used only if CFG_NS_VIRTUALIZATION # is enabled CFG_CORE_NEX_HEAP_SIZE ?= 16384 # TA profiling. # When this option is enabled, OP-TEE can execute Trusted Applications # instrumented with GCC's -pg flag and will output profiling information # in gmon.out format to /tmp/gmon-.out (path is defined in # tee-supplicant) # Note: this does not work well with shared libraries at the moment for a # couple of reasons: # 1. The profiling code assumes a unique executable section in the TA VA space. # 2. The code used to detect at run time if the TA is intrumented assumes that # the TA is linked statically. CFG_TA_GPROF_SUPPORT ?= n # TA function tracing. # When this option is enabled, OP-TEE can execute Trusted Applications # instrumented with GCC's -pg flag and will output function tracing # information for all functions compiled with -pg to # /tmp/ftrace-.out (path is defined in tee-supplicant). CFG_FTRACE_SUPPORT ?= n # Core syscall function tracing. # When this option is enabled, OP-TEE core is instrumented with GCC's # -pg flag and will output syscall function graph in user TA ftrace # buffer CFG_SYSCALL_FTRACE ?= n $(call cfg-depends-all,CFG_SYSCALL_FTRACE,CFG_FTRACE_SUPPORT) # Enable to compile user TA libraries with profiling (-pg). # Depends on CFG_TA_GPROF_SUPPORT or CFG_FTRACE_SUPPORT. CFG_ULIBS_MCOUNT ?= n # Profiling/tracing of syscall wrapper (utee_*) CFG_SYSCALL_WRAPPERS_MCOUNT ?= $(CFG_ULIBS_MCOUNT) ifeq (y,$(filter y,$(CFG_ULIBS_MCOUNT) $(CFG_SYSCALL_WRAPPERS_MCOUNT))) ifeq (,$(filter y,$(CFG_TA_GPROF_SUPPORT) $(CFG_FTRACE_SUPPORT))) $(error Cannot instrument user libraries if user mode profiling is disabled) endif endif # Build libutee, libutils, libmbedtls as shared libraries. # - Static libraries are still generated when this is enabled, but TAs will use # the shared libraries unless explicitly linked with the -static flag. # - Shared libraries are made of two files: for example, libutee is # libutee.so and 527f1a47-b92c-4a74-95bd-72f19f4a6f74.ta. The '.so' file # is a totally standard shared object, and should be used to link against. # The '.ta' file is a signed version of the '.so' and should be installed # in the same way as TAs so that they can be found at runtime. CFG_ULIBS_SHARED ?= n ifeq (y-y,$(CFG_TA_GPROF_SUPPORT)-$(CFG_ULIBS_SHARED)) $(error CFG_TA_GPROF_SUPPORT and CFG_ULIBS_SHARED are currently incompatible) endif # CFG_GP_SOCKETS # Enable Global Platform Sockets support CFG_GP_SOCKETS ?= y # Enable Secure Data Path support in OP-TEE core (TA may be invoked with # invocation parameters referring to specific secure memories). CFG_SECURE_DATA_PATH ?= n # Enable storage for TAs in secure storage, depends on CFG_REE_FS=y # TA binaries are stored encrypted in the REE FS and are protected by # metadata in secure storage. CFG_SECSTOR_TA ?= $(call cfg-all-enabled,CFG_REE_FS CFG_WITH_USER_TA) $(eval $(call cfg-depends-all,CFG_SECSTOR_TA,CFG_REE_FS CFG_WITH_USER_TA)) # Enable the pseudo TA that managages TA storage in secure storage CFG_SECSTOR_TA_MGMT_PTA ?= $(call cfg-all-enabled,CFG_SECSTOR_TA) $(eval $(call cfg-depends-all,CFG_SECSTOR_TA_MGMT_PTA,CFG_SECSTOR_TA)) # Enable the pseudo TA for misc. auxilary services, extending existing # GlobalPlatform TEE Internal Core API (for example, re-seeding RNG entropy # pool etc...) CFG_SYSTEM_PTA ?= $(CFG_WITH_USER_TA) $(eval $(call cfg-depends-all,CFG_SYSTEM_PTA,CFG_WITH_USER_TA)) # Enable the pseudo TA for enumeration of TEE based devices for the normal # world OS. CFG_DEVICE_ENUM_PTA ?= y # The attestation pseudo TA provides an interface to request measurements of # a TA or the TEE binary. CFG_ATTESTATION_PTA ?= n $(eval $(call cfg-depends-all,CFG_ATTESTATION_PTA,_CFG_WITH_SECURE_STORAGE)) # RSA key size (in bits) for the attestation PTA. Must be at least 528 given # other algorithm parameters (RSA PSS with SHA-256 and 32-byte salt), but # note that such a low value is not secure. # See https://tools.ietf.org/html/rfc8017#section-8.1.1 and # https://tools.ietf.org/html/rfc8017#section-9.1.1 # emLen >= hlen + sLen + 2 = 32 + 32 + 2 = 66 # emLen = ceil((modBits - 1) / 8) => emLen is the key size in bytes CFG_ATTESTATION_PTA_KEY_SIZE ?= 3072 # Define the number of cores per cluster used in calculating core position. # The cluster number is shifted by this value and added to the core ID, # so its value represents log2(cores/cluster). # Default is 2**(2) = 4 cores per cluster. CFG_CORE_CLUSTER_SHIFT ?= 2 # Define the number of threads per core used in calculating processing # element's position. The core number is shifted by this value and added to # the thread ID, so its value represents log2(threads/core). # Default is 2**(0) = 1 threads per core. CFG_CORE_THREAD_SHIFT ?= 0 # Enable support for dynamic shared memory (shared memory anywhere in # non-secure memory). CFG_CORE_DYN_SHM ?= y # Enable support for reserved shared memory (shared memory in a carved out # memory area). CFG_CORE_RESERVED_SHM ?= y # Enables support for larger physical addresses, that is, it will define # paddr_t as a 64-bit type. CFG_CORE_LARGE_PHYS_ADDR ?= n # Define the maximum size, in bits, for big numbers in the Internal Core API # Arithmetical functions. This does *not* influence the key size that may be # manipulated through the Cryptographic API. # Set this to a lower value to reduce the TA memory footprint. CFG_TA_BIGNUM_MAX_BITS ?= 2048 # Not used since libmpa was removed. Force the values to catch build scripts # that would set = n. $(call force,CFG_TA_MBEDTLS_MPI,y) $(call force,CFG_TA_MBEDTLS,y) # Compile the TA library mbedTLS with self test functions, the functions # need to be called to test anything CFG_TA_MBEDTLS_SELF_TEST ?= y # By default use tomcrypt as the main crypto lib providing an implementation # for the API in # CFG_CRYPTOLIB_NAME is used as libname and # CFG_CRYPTOLIB_DIR is used as libdir when compiling the library # # It's also possible to configure to use mbedtls instead of tomcrypt. # Then the variables should be assigned as "CFG_CRYPTOLIB_NAME=mbedtls" and # "CFG_CRYPTOLIB_DIR=lib/libmbedtls" respectively. CFG_CRYPTOLIB_NAME ?= tomcrypt CFG_CRYPTOLIB_DIR ?= core/lib/libtomcrypt # Not used since libmpa was removed. Force the value to catch build scripts # that would set = n. $(call force,CFG_CORE_MBEDTLS_MPI,y) # When enabled, CFG_NS_VIRTUALIZATION embeds support for virtualization in # the non-secure world. OP-TEE will not work without a compatible hypervisor # in the non-secure world if this option is enabled. # # CFG_VIRTUALIZATION served the same purpose as CFG_NS_VIRTUALIZATION but is # deprecated as the configuration switch name was ambiguous regarding which # world has virtualization enabled. ifneq (undefined,$(flavor CFG_VIRTUALIZATION)) $(info WARNING: CFG_VIRTUALIZATION is deprecated, use CFG_NS_VIRTUALIZATION instead) CFG_NS_VIRTUALIZATION ?= $(CFG_VIRTUALIZATION) ifneq ($(CFG_NS_VIRTUALIZATION),$(CFG_VIRTUALIZATION)) $(error Inconsistent CFG_NS_VIRTUALIZATION=$(CFG_NS_VIRTUALIZATION) and CFG_VIRTUALIZATION=$(CFG_VIRTUALIZATION)) endif endif # CFG_VIRTUALIZATION defined CFG_NS_VIRTUALIZATION ?= n ifeq ($(CFG_NS_VIRTUALIZATION),y) $(call force,CFG_CORE_RODATA_NOEXEC,y) $(call force,CFG_CORE_RWDATA_NOEXEC,y) # Default number of virtual guests CFG_VIRT_GUEST_COUNT ?= 2 endif # Enables backwards compatible derivation of RPMB and SSK keys CFG_CORE_HUK_SUBKEY_COMPAT ?= y # Use SoC specific tee_otp_get_die_id() implementation for SSK key generation. # This option depends on CFG_CORE_HUK_SUBKEY_COMPAT=y. CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID ?= n # Compress and encode conf.mk into the TEE core, and show the encoded string on # boot (with severity TRACE_INFO). CFG_SHOW_CONF_ON_BOOT ?= n # Enables support for passing a TPM Event Log stored in secure memory # to a TA or FF-A SP, so a TPM Service could use it to extend any measurement # taken before the service was up and running. CFG_CORE_TPM_EVENT_LOG ?= n # When enabled, CFG_SCMI_MSG_DRIVERS embeds SCMI message drivers in the core. # Refer to the supported SCMI features embedded upon CFG_SCMI_MSG_* # # CFG_SCMI_MSG_CLOCK embeds SCMI clock protocol support. # CFG_SCMI_MSG_RESET_DOMAIN embeds SCMI reset domain protocol support. # CFG_SCMI_MSG_SMT embeds a SMT header in shared device memory buffers # CFG_SCMI_MSG_VOLTAGE_DOMAIN embeds SCMI voltage domain protocol support. # CFG_SCMI_MSG_SMT_FASTCALL_ENTRY embeds fastcall SMC entry with SMT memory # CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY embeds interrupt entry with SMT memory # CFG_SCMI_MSG_SMT_THREAD_ENTRY embeds threaded entry with SMT memory # CFG_SCMI_MSG_SHM_MSG embeds a MSG header in cached shared memory buffer CFG_SCMI_MSG_DRIVERS ?= n ifeq ($(CFG_SCMI_MSG_DRIVERS),y) CFG_SCMI_MSG_CLOCK ?= n CFG_SCMI_MSG_RESET_DOMAIN ?= n CFG_SCMI_MSG_SHM_MSG ?= n CFG_SCMI_MSG_SMT ?= n CFG_SCMI_MSG_SMT_FASTCALL_ENTRY ?= n CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY ?= n CFG_SCMI_MSG_SMT_THREAD_ENTRY ?= n CFG_SCMI_MSG_THREAD_ENTRY ?= n CFG_SCMI_MSG_VOLTAGE_DOMAIN ?= n $(eval $(call cfg-depends-all,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,CFG_SCMI_MSG_SMT)) $(eval $(call cfg-depends-all,CFG_SCMI_MSG_SMT_INTERRUPT_ENTRY,CFG_SCMI_MSG_SMT)) $(eval $(call cfg-depends-one,CFG_SCMI_MSG_SMT_THREAD_ENTRY,CFG_SCMI_MSG_SMT CFG_SCMI_MSG_SHM_MSG)) ifeq ($(CFG_SCMI_MSG_SMT),y) _CFG_SCMI_PTA_SMT_HEADER := y endif ifeq ($(CFG_SCMI_MSG_SHM_MSG),y) _CFG_SCMI_PTA_MSG_HEADER := y endif endif # CFG_SCMI_SCPFW, when enabled, embeds the reference SCMI server implementation # from SCP-firmware package as an built-in SCMI stack in core. This # configuration mandates target product identifier is configured with # CFG_SCMI_SCPFW_PRODUCT and the SCP-firmware source tree path with # CFG_SCP_FIRMWARE. CFG_SCMI_SCPFW ?= n ifeq ($(CFG_SCMI_SCPFW),y) $(call force,CFG_SCMI_PTA,y,Required by CFG_SCMI_SCPFW) ifeq (,$(CFG_SCMI_SCPFW_PRODUCT)) $(error CFG_SCMI_SCPFW=y requires CFG_SCMI_SCPFW_PRODUCT configuration) endif ifeq (,$(wildcard $(CFG_SCP_FIRMWARE)/CMakeLists.txt)) $(error CFG_SCMI_SCPFW=y requires CFG_SCP_FIRMWARE configuration) endif endif #CFG_SCMI_SCPFW ifeq ($(CFG_SCMI_MSG_DRIVERS)-$(CFG_SCMI_SCPFW),y-y) $(error CFG_SCMI_MSG_DRIVERS=y and CFG_SCMI_SCPFW=y are mutually exclusive) endif # When enabled, CFG_SCMI_MSG_USE_CLK embeds SCMI clocks registering services for # the platform SCMI server and implements the platform plat_scmi_clock_*() # functions. CFG_SCMI_MSG_USE_CLK ?= n $(eval $(call cfg-depends-all,CFG_SCMI_MSG_USE_CLK,CFG_DRIVERS_CLK CFG_SCMI_MSG_DRIVERS)) # Enable SCMI PTA interface for REE SCMI agents CFG_SCMI_PTA ?= n ifeq ($(CFG_SCMI_PTA),y) _CFG_SCMI_PTA_SMT_HEADER ?= n _CFG_SCMI_PTA_MSG_HEADER ?= n endif ifneq ($(CFG_STMM_PATH),) $(call force,CFG_WITH_STMM_SP,y) else CFG_WITH_STMM_SP ?= n endif ifeq ($(CFG_WITH_STMM_SP),y) $(call force,CFG_ZLIB,y) endif # When enabled checks that buffers passed to the GP Internal Core API # comply with the rules added as annotations as part of the definition of # the API. For example preventing buffers in non-secure shared memory when # not allowed. CFG_TA_STRICT_ANNOTATION_CHECKS ?= y # When enabled accepts the DES key sizes excluding parity bits as in # the GP Internal API Specification v1.0 CFG_COMPAT_GP10_DES ?= y # Defines a limit for many levels TAs may call each others. CFG_CORE_MAX_SYSCALL_RECURSION ?= 4 # Pseudo-TA to export hardware RNG output to Normal World # RNG characteristics are platform specific CFG_HWRNG_PTA ?= n ifeq ($(CFG_HWRNG_PTA),y) # Output rate of hw_get_random_bytes() in bytes per second, 0: not rate-limited CFG_HWRNG_RATE ?= 0 # Quality/entropy of hw_get_random_bytes() per 1024 bits of output data, in bits ifeq (,$(CFG_HWRNG_QUALITY)) $(error CFG_HWRNG_QUALITY not defined) endif endif # CFG_PREALLOC_RPC_CACHE, when enabled, makes core to preallocate # shared memory for each secure thread. When disabled, RPC shared # memory is released once the secure thread has completed is execution. ifeq ($(CFG_WITH_PAGER),y) CFG_PREALLOC_RPC_CACHE ?= n endif CFG_PREALLOC_RPC_CACHE ?= y # When enabled, CFG_DRIVERS_CLK embeds a clock framework in OP-TEE core. # This clock framework allows to describe clock tree and provides functions to # get and configure the clocks. # CFG_DRIVERS_CLK_DT embeds devicetree clock parsing support # CFG_DRIVERS_CLK_FIXED add support for "fixed-clock" compatible clocks # CFG_DRIVERS_CLK_EARLY_PROBE makes clocks probed at early_init initcall level. # CFG_DRIVERS_CLK_PRINT_TREE embeds a helper function to print the clock tree # state on OP-TEE core console with the debug trace level. CFG_DRIVERS_CLK ?= n CFG_DRIVERS_CLK_DT ?= $(call cfg-all-enabled,CFG_DRIVERS_CLK CFG_DT) CFG_DRIVERS_CLK_FIXED ?= $(CFG_DRIVERS_CLK_DT) CFG_DRIVERS_CLK_EARLY_PROBE ?= $(CFG_DRIVERS_CLK_DT) CFG_DRIVERS_CLK_PRINT_TREE ?= n $(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_DT,CFG_DRIVERS_CLK CFG_DT)) $(eval $(call cfg-depends-all,CFG_DRIVERS_CLK_FIXED,CFG_DRIVERS_CLK_DT)) # When enabled, CFG_DRIVERS_RSTCTRL embeds a reset controller framework in # OP-TEE core to provide reset controls on subsystems of the devices. CFG_DRIVERS_RSTCTRL ?= n # When enabled, CFG_DRIVERS_GPIO embeds a GPIO controller framework in # OP-TEE core to provide GPIO support for drivers. CFG_DRIVERS_GPIO ?= n # When enabled, CFG_DRIVERS_I2C provides I2C controller and devices support. CFG_DRIVERS_I2C ?= n # When enabled, CFG_DRIVERS_NVMEM provides a framework to register nvmem # providers and allow consumer drivers to get NVMEM cells using the Device Tree. CFG_DRIVERS_NVMEM ?= n # When enabled, CFG_DRIVERS_PINCTRL embeds a pin muxing controller framework in # OP-TEE core to provide drivers a way to apply pin muxing configurations based # on device-tree. CFG_DRIVERS_PINCTRL ?= n # When enabled, CFG_DRIVERS_REGULATOR embeds a voltage regulator framework in # OP-TEE core to provide drivers a common regulator interface and describe # the regulators dependencies using an embedded device tree. # # When enabled, CFG_REGULATOR_FIXED embeds a voltage regulator driver for # DT compatible "regulator-fixed" devices. # # When enabled, CFG_REGULATOR_GPIO embeds a voltage regulator driver for # DT compatible "regulator-gpio" devices. # # CFG_DRIVERS_REGULATOR_PRINT_TREE embeds a helper function to print the # regulator tree state on OP-TEE core console with the info trace level. CFG_DRIVERS_REGULATOR ?= n CFG_DRIVERS_REGULATOR_PRINT_TREE ?= n CFG_REGULATOR_FIXED ?= n CFG_REGULATOR_GPIO ?= n $(eval $(call cfg-enable-all-depends,CFG_REGULATOR_FIXED, \ CFG_DRIVERS_REGULATOR CFG_DT)) $(eval $(call cfg-enable-all-depends,CFG_REGULATOR_GPIO, \ CFG_DRIVERS_REGULATOR CFG_DT CFG_DRIVERS_GPIO)) # When enabled, CFG_INSECURE permits insecure configuration of OP-TEE core # and shows a print (info level) when booting up the device that # indicates that the board runs a standard developer configuration. # # A developer configuration doesn't necessarily have to be secure. The intention # is that the one making products based on OP-TEE should override this flag in # plat-xxx/conf.mk for the platform they're basing their products on after # they've finalized implementing stubbed functionality (see OP-TEE # documentation/Porting guidelines) as well as vendor specific security # configuration. # # CFG_WARN_INSECURE served the same purpose as CFG_INSECURE but is deprecated. ifneq (undefined,$(flavor CFG_WARN_INSECURE)) $(info WARNING: CFG_WARN_INSECURE is deprecated, use CFG_INSECURE instead) CFG_INSECURE ?= $(CFG_WARN_INSECURE) ifneq ($(CFG_INSECURE),$(CFG_WARN_INSECURE)) $(error Inconsistent CFG_INSECURE=$(CFG_INSECURE) and CFG_WARN_INSECURE=$(CFG_WARN_INSECURE)) endif endif # CFG_WARN_INSECURE defined CFG_INSECURE ?= y # Enables warnings for declarations mixed with statements CFG_WARN_DECL_AFTER_STATEMENT ?= y # Branch Target Identification (part of the ARMv8.5 Extensions) provides a # mechanism to limit the set of locations to which computed branch instructions # such as BR or BLR can jump. To make use of BTI in TEE core and ldelf on CPU's # that support it, enable this option. A GCC toolchain built with # --enable-standard-branch-protection is needed to use this option. CFG_CORE_BTI ?= n $(eval $(call cfg-depends-all,CFG_CORE_BTI,CFG_ARM64_core)) # To make use of BTI in user space libraries and TA's on CPU's that support it, # enable this option. CFG_TA_BTI ?= $(CFG_CORE_BTI) $(eval $(call cfg-depends-all,CFG_TA_BTI,CFG_ARM64_core)) ifeq (y-y,$(CFG_NS_VIRTUALIZATION)-$(call cfg-one-enabled, CFG_TA_BTI CFG_CORE_BTI)) $(error CFG_NS_VIRTUALIZATION and BTI are currently incompatible) endif ifeq (y-y,$(CFG_PAGED_USER_TA)-$(CFG_TA_BTI)) $(error CFG_PAGED_USER_TA and CFG_TA_BTI are currently incompatible) endif # Memory Tagging Extension (part of the ARMv8.5 Extensions) implements lock # and key access to memory. This is a hardware supported alternative to # CFG_CORE_SANITIZE_KADDRESS which covers both S-EL1 and S-EL0. CFG_MEMTAG ?= n $(eval $(call cfg-depends-all,CFG_MEMTAG,CFG_ARM64_core)) ifeq (y-y,$(CFG_CORE_SANITIZE_KADDRESS)-$(CFG_MEMTAG)) $(error CFG_CORE_SANITIZE_KADDRESS and CFG_MEMTAG are not compatible) endif ifeq (y-y,$(CFG_WITH_PAGER)-$(CFG_MEMTAG)) $(error CFG_WITH_PAGER and CFG_MEMTAG are not compatible) endif # Privileged Access Never (PAN, part of the ARMv8.1 Extensions) can be # used to restrict accesses to unprivileged memory from privileged mode. # For RISC-V architecture, CSR {m|s}status.SUM bit is used to implement PAN. CFG_PAN ?= n $(eval $(call cfg-depends-one,CFG_PAN,CFG_ARM64_core CFG_RV64_core CFG_RV32_core)) ifeq ($(filter y, $(CFG_CORE_SEL1_SPMC) $(CFG_CORE_SEL2_SPMC) \ $(CFG_CORE_EL3_SPMC)),y) # FF-A case, handled via the FF-A ABI CFG_CORE_ASYNC_NOTIF ?= y $(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,n) else # CFG_CORE_ASYNC_NOTIF is defined by the platform to enable support # for sending asynchronous notifications to normal world. # Interrupt ID must be configurged by the platform too. Currently is only # CFG_CORE_ASYNC_NOTIF_GIC_INTID defined. CFG_CORE_ASYNC_NOTIF ?= n $(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,$(CFG_CORE_ASYNC_NOTIF)) endif # Enable callout service CFG_CALLOUT ?= $(CFG_CORE_ASYNC_NOTIF) # Enable notification based test watchdog CFG_NOTIF_TEST_WD ?= $(CFG_ENABLE_EMBEDDED_TESTS) $(eval $(call cfg-depends-all,CFG_NOTIF_TEST_WD,CFG_CALLOUT \ CFG_CORE_ASYNC_NOTIF)) $(eval $(call cfg-enable-all-depends,CFG_MEMPOOL_REPORT_LAST_OFFSET, \ CFG_WITH_STATS)) # Pointer Authentication (part of ARMv8.3 Extensions) provides instructions # for signing and authenticating pointers against secret keys. These can # be used to mitigate ROP (Return oriented programming) attacks. This is # currently done by instructing the compiler to add paciasp/autiasp at the # begging and end of functions to sign and verify ELR. # # The CFG_CORE_PAUTH enables these instructions for the core parts # executing at EL1, with one secret key per thread and one secret key per # physical CPU. # # The CFG_TA_PAUTH option enables these instructions for TA's at EL0. When # this option is enabled, TEE core will initialize secret keys per TA. CFG_CORE_PAUTH ?= n CFG_TA_PAUTH ?= $(CFG_CORE_PAUTH) $(eval $(call cfg-depends-all,CFG_CORE_PAUTH,CFG_ARM64_core)) $(eval $(call cfg-depends-all,CFG_TA_PAUTH,CFG_ARM64_core)) ifeq (y-y,$(CFG_NS_VIRTUALIZATION)-$(CFG_CORE_PAUTH)) $(error CFG_NS_VIRTUALIZATION and CFG_CORE_PAUTH are currently incompatible) endif ifeq (y-y,$(CFG_NS_VIRTUALIZATION)-$(CFG_TA_PAUTH)) $(error CFG_NS_VIRTUALIZATION and CFG_TA_PAUTH are currently incompatible) endif ifeq (y-y,$(CFG_TA_GPROF_SUPPORT)-$(CFG_TA_PAUTH)) $(error CFG_TA_GPROF_SUPPORT and CFG_TA_PAUTH are currently incompatible) endif ifeq (y-y,$(CFG_FTRACE_SUPPORT)-$(CFG_TA_PAUTH)) $(error CFG_FTRACE_SUPPORT and CFG_TA_PAUTH are currently incompatible) endif # Enable support for generic watchdog registration # This watchdog will then be usable by non-secure world through SMC calls. CFG_WDT ?= n # Enable watchdog SMC handling compatible with arm-smc-wdt Linux driver CFG_WDT_SM_HANDLER ?= n $(eval $(call cfg-enable-all-depends,CFG_WDT_SM_HANDLER,CFG_WDT)) # When CFG_WDT_SM_HANDLER=y, SMC function ID 0x82003D06 default implements # arm-smc-wdt service. Platform can also override this ID with a platform # specific SMC function ID to access arm-smc-wdt service thanks to # optional config switch CFG_WDT_SM_HANDLER_ID. CFG_WDT_SM_HANDLER_ID ?= 0x82003D06 # Allow using the udelay/mdelay function for platforms without ARM generic timer # extension. When set to 'n', the plat_get_freq() function must be defined by # the platform code CFG_CORE_HAS_GENERIC_TIMER ?= y # Enable RTC API CFG_DRIVERS_RTC ?= n # Enable PTA for RTC access from non-secure world CFG_RTC_PTA ?= n # Enable the FF-A SPMC tests in xtests CFG_SPMC_TESTS ?= n # Allocate the translation tables needed to map the S-EL0 application # loaded CFG_CORE_PREALLOC_EL0_TBLS ?= n ifeq (y-y,$(CFG_CORE_PREALLOC_EL0_TBLS)-$(CFG_WITH_PAGER)) $(error "CFG_WITH_PAGER can't support CFG_CORE_PREALLOC_EL0_TBLS") endif # CFG_PGT_CACHE_ENTRIES defines the number of entries on the memory # mapping page table cache used for Trusted Application mapping. # CFG_PGT_CACHE_ENTRIES is ignored when CFG_CORE_PREALLOC_EL0_TBLS # is enabled. # # A proper value for CFG_PGT_CACHE_ENTRIES depends on many factors: # CFG_WITH_LPAE, CFG_TA_ASLR, size of TAs, size of memrefs passed # to TA, CFG_ULIBS_SHARED and possibly others. The default value # is based on the number of threads as an indicator on how large # the system might be. ifeq ($(CFG_NUM_THREADS),1) CFG_PGT_CACHE_ENTRIES ?= 4 endif ifeq ($(CFG_NUM_THREADS),2) ifneq ($(CFG_WITH_LPAE),y) CFG_PGT_CACHE_ENTRIES ?= 8 endif endif CFG_PGT_CACHE_ENTRIES ?= ($(CFG_NUM_THREADS) * 2) # User TA runtime context dump. # When this option is enabled, OP-TEE provides a debug method for # developer to dump user TA's runtime context, including TA's heap stats. # Developer can open a stats PTA session and then invoke command # STATS_CMD_TA_STATS to get the context of loaded TAs. CFG_TA_STATS ?= n # Enables best effort mitigations against fault injected when the hardware # is tampered with. Details in lib/libutils/ext/include/fault_mitigation.h CFG_FAULT_MITIGATION ?= y # Enables TEE Internal Core API v1.1 compatibility for in-tree TAs. Note # that this doesn't affect libutee itself, it's only the TAs compiled with # this set that are affected. Each out-of-tree must set this if to enable # compatibility with version v1.1 as the value of this variable is not # preserved in the TA dev-kit. CFG_TA_OPTEE_CORE_API_COMPAT_1_1 ?= n # Change supported HMAC key size range, from 64 to 1024. # This is needed to pass AOSP Keymaster VTS tests: # Link to tests : https://android.googlesource.com/platform/hardware/interfaces/+/master/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp # Module: VtsHalKeymasterV3_0TargetTest # Testcases: - PerInstance/SigningOperationsTest# # - PerInstance/NewKeyGenerationTest# # - PerInstance/ImportKeyTest# # - PerInstance/EncryptionOperationsTest# # - PerInstance/AttestationTest# # Note that this violates GP requirements of HMAC size range. CFG_HMAC_64_1024_RANGE ?= n # CFG_RSA_PUB_EXPONENT_3, when enabled, allows RSA public exponents in the # range 3 <= e < 2^256. This is needed to pass AOSP KeyMint VTS tests: # Link to tests: https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/security/keymint/aidl/vts/functional/KeyMintTest.cpp # Module: VtsAidlKeyMintTargetTest # Testcases: - PerInstance/EncryptionOperationsTest.RsaNoPaddingSuccess # When CFG_RSA_PUB_EXPONENT_3 is disabled, RSA public exponents must conform # to NIST SP800-56B recommendation and be in the range 65537 <= e < 2^256. CFG_RSA_PUB_EXPONENT_3 ?= n # Enable a hardware pbkdf2 function # By default use standard pbkdf2 implementation CFG_CRYPTO_HW_PBKDF2 ?= n $(eval $(call cfg-depends-all,CFG_CRYPTO_HW_PBKDF2,CFG_CRYPTO_PBKDF2)) # CFG_HALT_CORES_ON_PANIC, when enabled, makes any call to panic() halt the # other cores. The feature currently relies on GIC device to trap the other # cores using an SGI interrupt specified by CFG_HALT_CORES_ON_PANIC_SGI. CFG_HALT_CORES_ON_PANIC ?= n CFG_HALT_CORES_ON_PANIC_SGI ?= 15 $(eval $(call cfg-depends-all,CFG_HALT_CORES_ON_PANIC,CFG_GIC)) # Enable automatic discovery of maximal PA supported by the hardware and # use that. Provides easier configuration of virtual platforms where the # maximal PA can vary. CFG_AUTO_MAX_PA_BITS ?= n # CFG_DRIVERS_REMOTEPROC, when enabled, embeds support for remote processor # management including generic DT bindings for the configuration. CFG_DRIVERS_REMOTEPROC ?= n # CFG_REMOTEPROC_PTA, when enabled, embeds remote processor management PTA # service. CFG_REMOTEPROC_PTA ?= n # When enabled, CFG_WIDEVINE_HUK uses the widevine HUK provided by secure # DTB as OP-TEE HUK. CFG_WIDEVINE_HUK ?= n $(eval $(call cfg-depends-all,CFG_WIDEVINE_HUK,CFG_DT)) # When enabled, CFG_WIDEVINE_PTA embeds a PTA that exposes the keys under # DT node "/options/op-tee/widevine" to some specific TAs. CFG_WIDEVINE_PTA ?= n $(eval $(call cfg-depends-all,CFG_WIDEVINE_PTA,CFG_DT CFG_WIDEVINE_HUK)) # CFG_SEMIHOSTING_CONSOLE, when enabled, embeds a semihosting console driver. # When CFG_SEMIHOSTING_CONSOLE_FILE=NULL, OP-TEE console reads/writes # trace messages from/to the debug terminal of the semihosting host computer. # When CFG_SEMIHOSTING_CONSOLE_FILE="{your_log_file}", OP-TEE console # outputs trace messages to that file. Output to "optee.log" by default. CFG_SEMIHOSTING_CONSOLE ?= n ifeq ($(CFG_SEMIHOSTING_CONSOLE),y) $(call force,CFG_SEMIHOSTING,y) endif CFG_SEMIHOSTING_CONSOLE_FILE ?= "optee.log" ifeq ($(CFG_SEMIHOSTING_CONSOLE_FILE),) $(error CFG_SEMIHOSTING_CONSOLE_FILE cannot be empty) endif # Semihosting is a debugging mechanism that enables code running on an embedded # system (also called the target) to communicate with and use the I/O of the # host computer. CFG_SEMIHOSTING ?= n # CFG_FFA_CONSOLE, when enabled, embeds a FFA console driver. OP-TEE console # writes trace messages via FFA interface to the SPM (Secure Partition Manager) # like hafnium. CFG_FFA_CONSOLE ?= n optee_os-4.3.0/mk/gcc.mk000066400000000000000000000021741464416617300150470ustar00rootroot00000000000000 CC$(sm) := $(CROSS_COMPILE_$(sm))gcc CXX$(sm) := $(CROSS_COMPILE_$(sm))g++ CPP$(sm) := $(CROSS_COMPILE_$(sm))cpp LD$(sm) := $(CROSS_COMPILE_$(sm))ld.bfd AR$(sm) := $(CROSS_COMPILE_$(sm))ar NM$(sm) := $(CROSS_COMPILE_$(sm))nm OBJCOPY$(sm) := $(CROSS_COMPILE_$(sm))objcopy OBJDUMP$(sm) := $(CROSS_COMPILE_$(sm))objdump READELF$(sm) := $(CROSS_COMPILE_$(sm))readelf nostdinc$(sm) := -nostdinc -isystem $(shell $(CC$(sm)) \ -print-file-name=include 2> /dev/null) # Get location of libgcc from gcc libgcc$(sm) := $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \ -print-libgcc-file-name 2> /dev/null) libstdc++$(sm) := $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \ -print-file-name=libstdc++.a 2> /dev/null) libgcc_eh$(sm) := $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \ -print-file-name=libgcc_eh.a 2> /dev/null) # Define these to something to discover accidental use CC := false CXX := false CPP := false LD := false AR := false NM := false OBJCOPY := false OBJDUMP := false READELF := false nostdinc := --bad-nostdinc-variable libgcc := --bad-libgcc-variable optee_os-4.3.0/mk/lib.mk000066400000000000000000000063371464416617300150660ustar00rootroot00000000000000# Input # # libname the name of the lib # libdir directory of lib which also is used as input to # mk/subdir.mk # conf-file [optional] if set, all objects will depend on $(conf-file) # [if CFG_ULIBS_SHARED==y] # libuuid the UUID of the shared lib # libl other libraries this library depends on; used to generate the # proper link arguments (-Lxxx -lyyy) and to add dependencies # on the needed .so files # [endif] # # Output # # updated cleanfiles and # updated libfiles, libdirs, libnames and libdeps subdirs = $(libdir) include mk/subdir.mk ifeq ($(filter $(sm), core ldelf),) # TA ifeq ($(CFG_ULIBS_MCOUNT),y) cflags-lib$(libname)-$(sm) += -pg endif endif include mk/compile.mk lib-libfile := $(out-dir)/$(base-prefix)$(libdir)/lib$(libname).a ifeq ($(CFG_ULIBS_SHARED),y) lib-shlibfile := $(out-dir)/$(base-prefix)$(libdir)/lib$(libname).so lib-shlibstrippedfile := $(out-dir)/$(base-prefix)$(libdir)/lib$(libname).stripped.so lib-shlibtafile := $(out-dir)/$(base-prefix)$(libdir)/$(libuuid).ta lib-libuuidln := $(out-dir)/$(base-prefix)$(libdir)/$(libuuid).elf lib-shlibfile-$(libname)-$(sm) := $(lib-shlibfile) lib-libdir-$(libname)-$(sm) := $(out-dir)/$(base-prefix)$(libdir) lib-needed-so-files := $(foreach l,$(libl),$(lib-shlibfile-$(l)-$(sm))) lib-Ll-args := $(foreach l,$(libl),-L$(lib-libdir-$(l)-$(sm)) -l$(l)) endif cleanfiles := $(lib-libfile) $(lib-shlibfile) $(lib-shlibstrippedfile) $(lib-shlibtafile) $(lib-libuuidln) $(cleanfiles) libfiles := $(lib-libfile) $(lib-shlibfile) $(lib-shlibstrippedfile) $(lib-shlibtafile) $(lib-libuuidln) $(libfiles) libdirs := $(out-dir)/$(base-prefix)$(libdir) $(libdirs) ifneq (,$(objs)) libnames := $(libname) $(libnames) libdeps := $(lib-libfile) $(libdeps) endif SIGN = scripts/sign_encrypt.py TA_SIGN_KEY ?= keys/default_ta.pem define process-lib ifeq ($(lib-use-ld), y) $(lib-libfile): $(objs) @echo ' LD $$@' @mkdir -p $$(dir $$@) $$(q)$$(LD$(sm)) $(lib-ldflags) -o $$@ $$^ else $(lib-libfile): $(objs) @$(cmd-echo-silent) ' AR $$@' @mkdir -p $$(dir $$@) $$(q)rm -f $$@ && $$(AR$(sm)) rcs $$@ $$^ endif ifeq ($(CFG_ULIBS_SHARED),y) ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y) lib-ldflags$(lib-shlibfile) += $$(call ld-option,-z force-bti) --fatal-warnings endif $(lib-shlibfile): $(objs) $(lib-needed-so-files) @$(cmd-echo-silent) ' LD $$@' @mkdir -p $$(dir $$@) $$(q)$$(LD$(sm)) $(lib-ldflags) -shared -z max-page-size=4096 \ $(call ld-option,-z separate-loadable-segments) \ $$(lib-ldflags$(lib-shlibfile)) \ --soname=$(libuuid) -o $$@ $$(filter-out %.so,$$^) $(lib-Ll-args) $(lib-shlibstrippedfile): $(lib-shlibfile) @$(cmd-echo-silent) ' OBJCOPY $$@' $$(q)$$(OBJCOPY$(sm)) --strip-unneeded $$< $$@ $(lib-shlibtafile): $(lib-shlibstrippedfile) $(TA_SIGN_KEY) @$(cmd-echo-silent) ' SIGN $$@' $$(q)$$(PYTHON3) $$(SIGN) --key $(TA_SIGN_KEY) --uuid $(libuuid) --in $$< --out $$@ $(lib-libuuidln): $(lib-shlibfile) @$(cmd-echo-silent) ' LN $$@' $$(q)ln -sf lib$(libname).so $$@ endif endef #process-lib $(eval $(call process-lib)) $(objs): $(conf-file) # Clean residues from processing objs := libname := libuuid := lib-use-ld := lib-shlibfile := lib-shlibstrippedfile := lib-shlibtafile := lib-libuuidln := lib-needed-so-files := libl := optee_os-4.3.0/mk/macros.mk000066400000000000000000000003401464416617300155700ustar00rootroot00000000000000# Rename $1 to $2 only if file content differs. Otherwise just delete $1. define mv-if-changed if cmp -s $2 $1; then \ rm -f $1; \ else \ $(cmd-echo-silent) ' UPD $2'; \ mv $1 $2; \ fi endef optee_os-4.3.0/mk/subdir.mk000066400000000000000000000134041464416617300156010ustar00rootroot00000000000000# Input # # subdirs tells the subdirectories to descend # # Output # # set srcs gen-srcs # set cflags-$(oname) cflags-remove-$(oname) # cxxflags-$(oname) cxxflags-remove-$(oname) # aflags-$(oname) aflags-remove-$(oname) # cppflags-$(oname) cppflags-remove-$(oname) # incdirs-$(oname) # incdirs-lib$(libname)-$(sm) [if libname is defined] # cppflags-lib$(libname)-$(sm) [if libname is defined] # cflags-lib$(libname)-$(sm) [if libname is defined] # cxxflags-lib$(libname)-$(sm) [if libname is defined] # for each file found, oname is the name of the object file for corresponding # source file srcs := gen-srcs := asm-defines-files := uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) define process-subdir-srcs-y ifeq ($$(sub-dir),.) srcs += $1 oname := $(out-dir)/$(base-prefix)$(basename $1).o else ifneq ($(filter /%,$(1)),) # $1 is an absolute path - start with "/" srcs += $1 oname := $(out-dir)/$(base-prefix)$(basename $1).o else srcs += $(sub-dir)/$1 oname := $(out-dir)/$(base-prefix)$(basename $$(sub-dir)/$1).o endif endif cflags-$$(oname) := $$(cflags-y) $$(cflags-$(1)-y) cflags-remove-$$(oname) := $$(cflags-remove-y) \ $$(cflags-remove-$(1)-y) cxxflags-$$(oname) := $$(cxxflags-y) $$(cxxflags-$(1)-y) cxxflags-remove-$$(oname) := $$(cxxflags-remove-y) \ $$(cxxflags-remove-$(1)-y) cppflags-$$(oname) := $$(cppflags-y) $$(cppflags-$(1)-y) cppflags-remove-$$(oname) := $$(cppflags-remove-y) \ $$(cppflags-remove-$(1)-y) aflags-$$(oname) := $$(aflags-y) $$(aflags-$(1)-y) aflags-remove-$$(oname) := $$(aflags-remove-y) \ $$(aflags-remove-$(1)-y) incdirs-$$(oname) := $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y)) # Clear local filename specific variables to avoid accidental reuse # in another subdirectory cflags-$(1)-y := cflags-remove-$(1)-y := cflags-lib-y := cxxflags-$(1)-y := cxxflags-remove-$(1)-y := cxxflags-lib-y := cppflags-$(1)-y := cppflags-remove-$(1)-y := cppflags-lib-y := aflags-$(1)-y := aflags-remove-$(1)-y := incdirs-$(1)-y := fname := oname := endef #process-subdir-srcs-y define process-subdir-gensrcs-helper # $1 gensrc-y element # $2 full path and name of generated source file # $3 full path and name of object file compiled from source file # $4 full path to out directory # $5 y if $2 must be generated before $(sm) starts building (e.g., .h file) gen-srcs += $2 cleanfiles += $2 oname := $3 FORCE-GENSRC$(sm): $(if $(filter y,$5),$2,) $$(addprefix $4,$$(produce-additional-$1)): $2 subdir-$2 := $$(sub-dir) recipe-$2 := $$(recipe-$1) $2: $$(depends-$1) @$(cmd-echo-silent) ' GEN $2' $(q)mkdir -p $4 $(q)$$(recipe-$2) cflags-$$(oname) := $$(cflags-y) $$(cflags-$(1)-y) cflags-remove-$$(oname) := $$(cflags-remove-y) \ $$(cflags-remove-$(1)-y) cxxflags-$$(oname) := $$(cxxflags-y) $$(cxxflags-$(1)-y) cxxflags-remove-$$(oname) := $$(cxxflags-remove-y) \ $$(cxxflags-remove-$(1)-y) cppflags-$$(oname) := $$(cppflags-y) $$(cppflags-$(1)-y) cppflags-remove-$$(oname) := $$(cppflags-remove-y) \ $$(cppflags-remove-$(1)-y) aflags-$$(oname) := $$(aflags-y) $$(aflags-$(1)-y) aflags-remove-$$(oname) := $$(aflags-remove-y) \ $$(aflags-remove-$(1)-y) incdirs-$$(oname) := $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y)) # Clear local filename specific variables to avoid accidental reuse # in another subdirectory cflags-$(1)-y := cflags-remove-$(1)-y := cflags-lib-y := cxxflags-$(1)-y := cxxflags-remove-$(1)-y := cxxflags-lib-y := cppflags-$(1)-y := cppflags-remove-$(1)-y := cppflags-lib-y := aflags-$(1)-y := aflags-remove-$(1)-y := incdirs-$(1)-y := fname := oname := endef #process-subdir-gensrcs-helper define process-subdir-gensrcs-y $$(eval $$(call process-subdir-gensrcs-helper,$1,$(sub-dir-out)/$$(produce-$1),$(sub-dir-out)/$(basename $(produce-$1)).o,$(sub-dir-out),$(force-gensrc-$1))) endef #process-subdir-gensrcs-y define process-subdir-asm-defines-y asm-defines-files += $(sub-dir)/$1 endef #process-subdir-asm-defines-y define process-subdir sub-dir := $1 ifeq ($1,.) sub-dir-out := $(patsubst %/,%,$(out-dir)/$(base-prefix)) else sub-dir-out := $(out-dir)/$(base-prefix)$1 endif include $1/sub.mk sub-subdirs := $$(addprefix $1/,$$(subdirs-y)) $$(subdirs_ext-y) incdirs$(sm) := $(incdirs$(sm)) $$(addprefix $1/,$$(global-incdirs-y)) thissubdir-incdirs := $(out-dir)/$(base-prefix)$1 $$(addprefix $1/,$$(incdirs-y)) $$(incdirs_ext-y) ifneq ($$(libname),) incdirs-lib$$(libname)-$$(sm) := $$(incdirs-lib$$(libname)-$$(sm)) $$(addprefix $1/,$$(incdirs-lib-y)) cflags-lib$$(libname)-$$(sm) := $$(cflags-lib$$(libname)-$$(sm)) $$(cflags-lib-y) cxxflags-lib$$(libname)-$$(sm) := $$(cxxflags-lib$$(libname)-$$(sm)) $$(cxxflags-lib-y) cppflags-lib$$(libname)-$$(sm) := $$(cppflags-lib$$(libname)-$$(sm)) $$(cppflags-lib-y) endif # Process files in current directory $$(foreach g, $$(gensrcs-y), $$(eval $$(call process-subdir-gensrcs-y,$$(g)))) $$(foreach s, $$(srcs-y), $$(eval $$(call process-subdir-srcs-y,$$(s)))) $$(foreach a, $$(asm-defines-y), $$(eval $$(call process-subdir-asm-defines-y,$$(a)))) # Clear flags used when processing current directory srcs-y := cflags-y := cflags-lib-y := cxxflags-y := cxxflags-lib-y := cppflags-y := cppflags-lib-y := aflags-y := cflags-remove-y := cxxflags-remove-y := aflags-remove-y := subdirs-y := subdirs_ext-y := global-incdirs-y := incdirs-lib-y := incdirs-y := incdirs_ext-y := gensrcs-y := this-out-dir := asm-defines-y := # Process subdirectories in current directory $$(foreach sd, $$(call uniq,$$(sub-subdirs)), $$(eval $$(call process-subdir,$$(sd)))) endef #process-subdir # Top subdirectories $(foreach sd, $(call uniq,$(subdirs)), $(eval $(call process-subdir,$(sd)))) optee_os-4.3.0/scripts/000077500000000000000000000000001464416617300150365ustar00rootroot00000000000000optee_os-4.3.0/scripts/arm32_sysreg.py000077500000000000000000000157301464416617300177410ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018, Linaro Limited # import argparse import sys import re def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) def my_err(line_number, msg): eprint('Error: line:' + repr(line_number) + ' ' + msg) sys.exit(1) def gen_read64_macro(reg_name, opc1, crm, descr): print('') if len(descr): print('\t# ' + descr) print('\t.macro read_' + reg_name.lower() + ' reg0, reg1') print('\tmrrc\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm) print('\t.endm') def gen_write64_macro(reg_name, opc1, crm, descr): print('') if len(descr): print('\t# ' + descr) print('\t.macro write_' + reg_name.lower() + ' reg0, reg1') print('\tmcrr\tp15, ' + opc1 + ', \\reg0, \\reg1, ' + crm) print('\t.endm') def gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr): print('') if len(descr): print('\t# ' + descr) print('\t.macro read_' + reg_name.lower() + ' reg') print('\tmrc p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2) print('\t.endm') def gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr): print('') if len(descr): print('\t# ' + descr) print('\t.macro write_' + reg_name.lower() + ' reg') print('\tmcr p15, ' + opc1 + ', \\reg, ' + crn + ', ' + crm + ', ' + opc2) print('\t.endm') def gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, descr): print('') if len(descr): print('\t# ' + descr) print('\t.macro write_' + reg_name.lower()) print('\t# Register ignored') print('\tmcr p15, ' + opc1 + ', r0, ' + crn + ', ' + crm + ', ' + opc2) print('\t.endm') def gen_read64_func(reg_name, opc1, crm, descr): print('') if len(descr): print('/* ' + descr + ' */') print('static inline __noprof uint64_t read_' + reg_name.lower() + '(void)') print('{') print('\tuint64_t v;') print('') print('\tasm volatile ("mrrc p15, ' + opc1 + ', %Q0, %R0, ' + crm + '"' + ' : "=r" (v));') print('') print('\treturn v;') print('}') def gen_write64_func(reg_name, opc1, crm, descr): print('') if len(descr): print('/* ' + descr + ' */') print('static inline __noprof void write_' + reg_name.lower() + '(uint64_t v)') print('{') print('\tasm volatile ("mcrr p15, ' + opc1 + ', %Q0, %R0, ' + crm + '"' + ' : : "r" (v));') print('}') def gen_read32_func(reg_name, crn, opc1, crm, opc2, descr): print('') if len(descr): print('/* ' + descr + ' */') print('static inline __noprof uint32_t read_' + reg_name.lower() + '(void)') print('{') print('\tuint32_t v;') print('') print('\tasm volatile ("mrc p15, ' + opc1 + ', %0, ' + crn + ', ' + crm + ', ' + opc2 + '"' + ' : "=r" (v));') print('') print('\treturn v;') print('}') def gen_write32_func(reg_name, crn, opc1, crm, opc2, descr): print('') if len(descr): print('/* ' + descr + ' */') print('static inline __noprof void write_' + reg_name.lower() + '(uint32_t v)') print('{') print('\tasm volatile ("mcr p15, ' + opc1 + ', %0, ' + crn + ', ' + crm + ', ' + opc2 + '"' + ' : : "r" (v));') print('}') def gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, descr): print('') if len(descr): print('/* ' + descr + ' */') print('static inline __noprof void write_' + reg_name.lower() + '(void)') print('{') print('\t/* Register ignored */') print('\tasm volatile ("mcr p15, ' + opc1 + ', r0, ' + crn + ', ' + crm + ', ' + opc2 + '");') print('}') def gen_file(line, line_number, s_file): words = line.split() if len(words) == 0: return if len(re.findall('^ *#', line)): return if len(re.findall('^ *@', line)): comment = re.sub('^ *@', '', line) comment = re.sub('^ *', '', comment) comment = re.sub('[ \n]*$', '', comment) if len(comment) == 0: print('') return if s_file: print('# ' + comment) else: print('/* ' + comment + ' */') return reg_name = words[0] crn = words[1] opc1 = words[2] crm = words[3] opc2 = words[4] access_type = words[5] descr = " ".join(words[6:]) read_access = access_type == 'RO' or access_type == 'RW' write_access = (access_type == 'WO' or access_type == 'RW' or access_type == 'WOD') dummy_access = access_type == 'WOD' if not read_access and not write_access: my_err(line_number, 'bad Access Type "' + access_type + '"') if crn == '-': if opc2 != '-': my_err(line_number, 'bad opc2, expected -') if read_access: if s_file: gen_read64_macro(reg_name, opc1, crm, descr) else: gen_read64_func(reg_name, opc1, crm, descr) if s_file: gen_write64_macro(reg_name, opc1, crm, descr) else: gen_write64_func(reg_name, opc1, crm, descr) else: if read_access: if s_file: gen_read32_macro(reg_name, crn, opc1, crm, opc2, descr) else: gen_read32_func(reg_name, crn, opc1, crm, opc2, descr) if write_access: if dummy_access: if s_file: gen_write32_dummy_macro(reg_name, crn, opc1, crm, opc2, descr) else: gen_write32_dummy_func(reg_name, crn, opc1, crm, opc2, descr) else: if s_file: gen_write32_macro(reg_name, crn, opc1, crm, opc2, descr) else: gen_write32_func(reg_name, crn, opc1, crm, opc2, descr) def get_args(): parser = argparse.ArgumentParser(description='Generates instructions to ' 'access ARM32 system registers.') parser.add_argument('--s_file', action='store_true', help='Generate an Assembly instead of a C file') parser.add_argument('--guard', help='Provide #ifdef in C file') return parser.parse_args() def main(): args = get_args() cmnt = 'Automatically generated, do not edit' if args.s_file: print('# ' + cmnt) else: print('/* ' + cmnt + ' */') if args.guard is not None: print('#ifndef ' + args.guard.upper().replace('.', '_')) print('#define ' + args.guard.upper().replace('.', '_')) print('#include ') line_number = 0 for line in sys.stdin: line_number = line_number + 1 gen_file(line, line_number, args.s_file) if not args.s_file and args.guard is not None: print('#endif /*' + args.guard.upper().replace('.', '_') + '*/') if __name__ == '__main__': main() optee_os-4.3.0/scripts/bin_to_c.py000077500000000000000000000040031464416617300171640ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2018, Linaro Limited # import argparse import array import os import re import sys def get_args(): parser = argparse.ArgumentParser(description='Converts a binary file ' 'into C source file defining binary ' 'data as a constant byte array.') parser.add_argument('--bin', required=True, help='Path to the input binary file') parser.add_argument('--vname', required=True, help='Variable name for the generated table in ' 'the output C source file.') parser.add_argument('--out', required=True, help='Path for the generated C file') parser.add_argument('--text', required=False, action='store_true', help='Treat input as a text file') return parser.parse_args() def main(): args = get_args() with open(args.bin, 'rb') as indata: bytes = indata.read() if args.text: bytes += b'\0' size = len(bytes) f = open(args.out, 'w') f.write('/* Generated from ' + args.bin + ' by ' + os.path.basename(__file__) + ' */\n\n') f.write('#include \n') f.write('#include \n') if args.text: f.write('__extension__ const char ' + args.vname + '[] = {\n') else: f.write('__extension__ const uint8_t ' + args.vname + '[] ' + ' __aligned(__alignof__(uint64_t)) = {\n') i = 0 while i < size: if i % 8 == 0: f.write('\t\t') if args.text and i != size - 1 and bytes[i] == b'\0': print('Error: null byte encountered in text file') sys.exit(1) f.write(hex(bytes[i]) + ',') i = i + 1 if i % 8 == 0 or i == size: f.write('\n') else: f.write(' ') f.write('};\n') f.close() if __name__ == "__main__": main() optee_os-4.3.0/scripts/checkpatch.sh000077500000000000000000000072631464416617300175020ustar00rootroot00000000000000#!/bin/bash DIR="${BASH_SOURCE%/*}" # if no CHECKPATCH is explicitly given by the environment, try to # locate checkpatch.pl: first take the one from the path, then check # for a local copy of the linux headers, finally try sources downloaded # with OP-TEE (for QEMU) if [ -z "$CHECKPATCH" ]; then CHECKPATCH=$(command -v checkpatch.pl) fi if [ -z "$CHECKPATCH" ]; then CHECKPATCH=$(find /usr/src/linux-headers* -name checkpatch.pl -print -quit) fi if [ -z "$CHECKPATCH" ]; then CHECKPATCH=$(find "$PWD/../linux" -name checkpatch.pl -print -quit) fi source "$DIR/checkpatch_inc.sh" hash $CHECKPATCH 2>/dev/null || { echo >&2 "Could not find checkpatch.pl, aborting"; exit 1; } help() { cat <<-EOF Usage: checkpatch.sh [--working] checkpatch.sh ... checkpatch.sh ... checkpatch.sh --diff checkpatch.sh --cached checkpatch.sh --help Args: Any commit or any number of commits. Any number of Git Revision Selections. (requires git v2.19) https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection Options: --working Check the working area [Default]. --cached Check the staging area. --diff Check the diff between commit1 and commit2. --help Print this help message. Examples: checkpatch.sh commit1 commit2 commit3 Check commit1, commit2, and commit3. checkpatch.sh HEAD~5 Check the commit 5 revisions before the current HEAD. checkpatch.sh commit1..^commit2 Check each commit from commit1 to commit2 inclusively. (requires git v2.19) checkpatch.sh HEAD~5..HEAD~1 Check each commit from HEAD~5 to HEAD~1 exclusively, aka not including HEAD~1. (requires git v2.19) checkpatch.sh commit1...tags/tag1 Check each commit that exists exclusively within the history of only one of each given revision. (requires git v2.19) checkpatch.sh HEAD~10-5 Check 5 commits moving forward in history starting from HEAD~10. (requires git v2.19) checkpatch.sh branch1 tags/tag1 Check the HEAD of branch1 and the HEAD of tag1. (requires git v2.19) EOF exit 1 } op=${1:---working} case "$op" in --cached) echo "Checking staging area: " checkstaging ;; --diff) echo "Checking diff (diff $1...$2)" checkdiff "$2" "$3" ;; --working) echo "Checking working area: " checkworking ;; --help|-h) help ;; *) echo "Checking commit(s):" read -r MAJOR MINOR < <(git --version | awk -F '[. ]' '{print $3, $4}') if (( MAJOR < 2 )) || (( MAJOR == 2 && MINOR < 19 )); then for c in "$@"; do checkpatch "$c"; done else for arg in "$@"; do # parse the argument into a git object or list of git objects object="$(git rev-parse "${arg}")" || continue # run checkpatch if the parsed argument represents a single commit hash if git cat-file -e "${object}" 2>/dev/null; then checkpatch "${object}" else # expand the object list and run checkpatch on each commit id commits="$(echo "${object}" | git rev-list --stdin)" for c in ${commits}; do checkpatch "$c"; done fi done fi ;; esac optee_os-4.3.0/scripts/checkpatch_inc.sh000066400000000000000000000030371464416617300203230ustar00rootroot00000000000000#!/bin/bash CHECKPATCH="${CHECKPATCH:-checkpatch.pl}" CHECKPATCH_OPT="${CHECKPATCH_OPT:-}" # checkpatch.pl will ignore the following paths CHECKPATCH_IGNORE=$(echo \ core/include/gen-asm-defines.h \ core/lib/lib{fdt,tomcrypt} core/lib/zlib \ lib/libutils lib/libmbedtls \ lib/libutee/include/elf.h \ lib/libutee/include/elf_common.h \ core/arch/arm/include/arm{32,64}.h \ core/arch/arm/plat-ti/api_monitor_index_a{9,15}.h \ core/arch/arm/dts \ ta/pkcs11/scripts/verify-helpers.sh \ core/arch/riscv/include/encoding.h ) _CP_EXCL=$(for p in $CHECKPATCH_IGNORE; do echo ":(exclude)$p" ; done) function _checkpatch() { # Use --typedefsfile if supported by the checkpatch tool typedefs_opt="--typedefsfile typedefs.checkpatch" $CHECKPATCH --help 2>&1 | grep -q -- --typedefsfile || \ typedefs_opt=""; # Ignore NOT_UNIFIED_DIFF in case patch has no diff # (e.g., all paths filtered out) eval "$CHECKPATCH $CHECKPATCH_OPT $typedefs_opt -" } function checkpatch() { git show --oneline --no-patch $1 # The first git 'format-patch' shows the commit message # The second one produces the diff (might be empty if _CP_EXCL # filters out all diffs) (git format-patch $1^..$1 --stdout | sed -n '/^diff --git/q;p'; \ git format-patch $1^..$1 --stdout -- $_CP_EXCL . | \ sed -n '/^diff --git/,$p') | _checkpatch } function checkstaging() { git diff --cached -- . $_CP_EXCL | _checkpatch } function checkworking() { git diff -- . $_CP_EXCL | _checkpatch } function checkdiff() { git diff $1...$2 -- . $_CP_EXCL | _checkpatch } optee_os-4.3.0/scripts/derive_rpmb_key.py000077500000000000000000000110531464416617300205610ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2023, Linaro Limited # import sys def hex_parse(str): try: h = bytes.fromhex(str) except ValueError as e: try: # Try to pad with a '0' nibble in front h = bytes.fromhex('0' + str) print('Odd number of nibbles in hexadecimal string', file=sys.stderr) raise e except ValueError: raise e return h def get_args(): import argparse import textwrap parser = argparse.ArgumentParser( allow_abbrev=False, description='''Derive an RPMB key from the Hardware Unique Key used by OP-TEE and the CID of the RPMB.''', epilog='''Note that the derived key matches what the __huk_subkey_derive() would produce. If huk_subkey_derive() is overridden to call another function, please don't use this script''') parser.add_argument('--quiet', action='store_true', default=False, help='''Gives only the hexstring of the RPMB key as output, intended for scripting''') parser.add_argument('--testkey', action='store_true', default=False, help='''Outputs the hardcoded test key''') parser.add_argument('--huk', type=hex_parse, help='''Hardware Unique Key (16 bytes), as returned by the platform specific function tee_otp_get_hw_unique_key() in OP-TEE''') parser.add_argument('--cid', type=hex_parse, help='CID (16 bytes)') parser.add_argument('--compat', action='store_true', default=False, help='''Generates a backwards compatible key, only to be used if OP-TEE is build with CFG_CORE_HUK_SUBKEY_COMPAT=y''') return parser.parse_args() def derive_key(huk, cid, compat): import struct from cryptography.hazmat.primitives import hashes, hmac # Prepare the CID and Clear the PRV (Product revision) and CRC (CRC7 # checksum) fields as OP-TEE does. data = bytearray(cid) data[9] = 0 data[15] = 0 # This is how __huk_subkey_derive() is implemented, if huk_subkey_derive() # is overridden the key derived here may not match what OP-TEE is using # # HUK is as tee_otp_get_hw_unique_key() in OP-TEE returns it h = hmac.HMAC(huk, hashes.SHA256()) if not compat: usage_word = struct.pack(' FTRACE\x00\x01 ... # # is an array of 64-bit integers. # - When the topmost byte is 0, the entry indicates a function return and the # remaining bytes are a duration in nanoseconds. # - A non-zero value is a stack depth, indicating a function entry, and the # remaining bytes are the function's address. import sys line = "" curr_depth = 0 def usage(): print(f"Usage: {sys.argv[0]} ftrace.out") print("Converts a ftrace file to text. Output is written to stdout.") sys.exit(0) def format_time(ns): if ns < 1000000: us = ns / 1000 return f"{us:7.3f} us" elif ns < 1000000000: ms = ns / 1000000 return f"{ms:7.3f} ms" else: s = ns / 1000000000 return f"{s:7.3f} s " def display(depth, val): global line, curr_depth if depth != 0: curr_depth = depth if line != "": line = line.replace("TIME", " " * 10) + " {" print(line) line = "" line = f" TIME | {depth:3} | " + " " * depth + f"0x{val:016x}()" else: if line != "": line = line.replace("TIME", format_time(val)) print(line) line = "" else: if curr_depth != 0: curr_depth = curr_depth - 1 print(" " + format_time(val) + f" | {curr_depth:3} | " + " " * curr_depth + "}") def main(): if len(sys.argv) < 2: usage() with open(sys.argv[1], 'rb') as f: s = f.read() magic = s.find(b'FTRACE\x00\x01') if magic == -1: print("Magic not found", file=sys.stderr) sys.exit(1) print(s[:magic].rstrip(b'\x00').decode()) s = s[magic + 8:] for i in range(0, len(s), 8): elem = int.from_bytes(s[i:i + 8], byteorder="little", signed=False) depth = elem >> 56 val = elem & 0xFFFFFFFFFFFFFF display(depth, val) if __name__ == "__main__": main() optee_os-4.3.0/scripts/gen_compile_commands.py000077500000000000000000000201421464416617300215540ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 # # Copyright (C) Google LLC, 2018 # # Author: Tom Roeder # Ported and modified for U-Boot by Joao Marcos Costa # Briefly documented at doc/build/gen_compile_commands.rst # # Ported and modified for OP-TEE by Joakim Bech """A tool for generating compile_commands.json in OP-TEE.""" import argparse import json import logging import os import re import subprocess import sys _DEFAULT_OUTPUT = 'compile_commands.json' _DEFAULT_LOG_LEVEL = 'WARNING' _FILENAME_PATTERN = r'^\..*\.cmd$' _LINE_PATTERN = r'^old-cmd[^ ]* := (?:/usr/bin/ccache )?(.*) -c (\S+)' _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] # The tools/ directory adopts a different build system, and produces .cmd # files in a different format. Do not support it. _EXCLUDE_DIRS = ['.git', 'Documentation', 'include', 'tools'] def parse_arguments(): """Sets up and parses command-line arguments. Returns: log_level: A logging level to filter log output. directory: The work directory where the objects were built. ar: Command used for parsing .a archives. output: Where to write the compile-commands JSON file. paths: The list of files/directories to handle to find .cmd files. """ usage = 'Creates a compile_commands.json database from OP-TEE .cmd files' parser = argparse.ArgumentParser(description=usage) directory_help = ('specify the output directory used for the OP-TEE build ' '(defaults to the working directory)') parser.add_argument('-d', '--directory', type=str, default='.', help=directory_help) output_help = ('path to the output command database (defaults to ' + _DEFAULT_OUTPUT + ')') parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT, help=output_help) log_level_help = ('the level of log messages to produce (defaults to ' + _DEFAULT_LOG_LEVEL + ')') parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, default=_DEFAULT_LOG_LEVEL, help=log_level_help) ar_help = 'command used for parsing .a archives' parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help) paths_help = ('directories to search or files to parse ' '(files should be *.o, *.a, or modules.order). ' 'If nothing is specified, the current directory is searched') parser.add_argument('paths', type=str, nargs='*', help=paths_help) args = parser.parse_args() return (args.log_level, os.path.abspath(args.directory), args.output, args.ar, args.paths if len(args.paths) > 0 else [args.directory]) def cmdfiles_in_dir(directory): """Generate the iterator of .cmd files found under the directory. Walk under the given directory, and yield every .cmd file found. Args: directory: The directory to search for .cmd files. Yields: The path to a .cmd file. """ filename_matcher = re.compile(_FILENAME_PATTERN) exclude_dirs = [os.path.join(directory, d) for d in _EXCLUDE_DIRS] for dirpath, dirnames, filenames in os.walk(directory, topdown=True): # Prune unwanted directories. if dirpath in exclude_dirs: dirnames[:] = [] continue for filename in filenames: if filename_matcher.match(filename): yield os.path.join(dirpath, filename) def to_cmdfile(path): """Return the path of .cmd file used for the given build artifact Args: Path: file path Returns: The path to .cmd file """ dir, base = os.path.split(path) return os.path.join(dir, '.' + base + '.cmd') def cmdfiles_for_a(archive, ar): """Generate the iterator of .cmd files associated with the archive. Parse the given archive, and yield every .cmd file used to build it. Args: archive: The archive to parse Yields: The path to every .cmd file found """ for obj in subprocess.check_output([ar, '-t', archive]).decode().split(): yield to_cmdfile(obj) def cmdfiles_for_modorder(modorder): """Generate the iterator of .cmd files associated with the modules.order. Parse the given modules.order, and yield every .cmd file used to build the contained modules. Args: modorder: The modules.order file to parse Yields: The path to every .cmd file found """ with open(modorder) as f: for line in f: obj = line.rstrip() base, ext = os.path.splitext(obj) if ext != '.o': sys.exit('{}: module path must end with .o'.format(obj)) mod = base + '.mod' # Read from *.mod, to get a list of objects that compose the # module. with open(mod) as m: for mod_line in m: yield to_cmdfile(mod_line.rstrip()) def process_line(root_directory, command_prefix, file_path): """Extracts information from a .cmd line and creates an entry from it. Args: root_directory: The directory that was searched for .cmd files. Usually used directly in the "directory" entry in compile_commands.json. command_prefix: The extracted command line, up to the last element. file_path: The .c file from the end of the extracted command. Usually relative to root_directory, but sometimes absolute. Returns: An entry to append to compile_commands. Raises: ValueError: Could not find the extracted file based on file_path and root_directory or file_directory. """ # The .cmd files are intended to be included directly by Make, so they # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the # kernel version). The compile_commands.json file is not interpreted # by Make, so this code replaces the escaped version with '#'. prefix = command_prefix.replace(r'\#', '#').replace('$(pound)', '#') # Use os.path.abspath() to normalize the path resolving '.' and '..' . abs_path = os.path.abspath(os.path.join(root_directory, file_path)) if not os.path.exists(abs_path): raise ValueError('File %s not found' % abs_path) return { 'directory': root_directory, 'file': abs_path, 'command': prefix + file_path, } def main(): """Walks through the directory and finds and parses .cmd files.""" log_level, directory, output, ar, paths = parse_arguments() level = getattr(logging, log_level) logging.basicConfig(format='%(levelname)s: %(message)s', level=level) line_matcher = re.compile(_LINE_PATTERN) compile_commands = [] for path in paths: # If 'path' is a directory, handle all .cmd files under it. # Otherwise, handle .cmd files associated with the file. # built-in objects are linked via vmlinux.a # Modules are listed in modules.order. if os.path.isdir(path): cmdfiles = cmdfiles_in_dir(path) elif path.endswith('.a'): cmdfiles = cmdfiles_for_a(path, ar) elif path.endswith('modules.order'): cmdfiles = cmdfiles_for_modorder(path) else: sys.exit('{}: unknown file type'.format(path)) for cmdfile in cmdfiles: with open(cmdfile, 'rt') as f: try: result = line_matcher.match(f.readline()) if result: entry = process_line(directory, result.group(1), result.group(2)) compile_commands.append(entry) except ValueError as err: logging.info('Could not add line from %s: %s', cmdfile, err) except AttributeError as err: continue with open(output, 'wt') as f: json.dump(compile_commands, f, indent=2, sort_keys=True) if __name__ == '__main__': main() optee_os-4.3.0/scripts/gen_ld_sects.py000077500000000000000000000023741464416617300200520ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2017, Linaro Limited # import sys import re def usage(): print("Usage: {0}
[...]".format( sys.argv[0])) sys.exit(1) def main(): if len(sys.argv) < 2: usage() in_shdr = False section_headers = re.compile("Section Headers:") key_to_flags = re.compile("Key to Flags:") match_rule = re.compile(sys.argv[1]) skip_sections = sys.argv[2:] for line in sys.stdin: if section_headers.match(line): in_shdr = True continue if key_to_flags.match(line): in_shdr = False continue if not in_shdr: continue words = line.split() if len(words) < 3: continue if words[0] == "[": name_offs = 2 else: name_offs = 1 sect_name = words[name_offs] sect_type = words[name_offs + 1] if sect_type != "PROGBITS": continue if not match_rule.match(sect_name): continue if sect_name in skip_sections: continue print('\t*({0})'.format(sect_name)) if __name__ == "__main__": main() optee_os-4.3.0/scripts/gen_ldelf_hex.py000077500000000000000000000110441464416617300201760ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019, Linaro Limited # from __future__ import print_function from __future__ import division import argparse import sys try: from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection from elftools.elf.constants import P_FLAGS except ImportError: print(""" *** Can't find elftools module. Probably it is not installed on your system. You can install this module with $ apt install python3-pyelftools if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in your package manager if you are using some other distribution. *** """) raise def round_up(n, m): if n == 0: return 0 else: return (((n - 1) // m) + 1) * m def emit_load_segments(elffile, outf): load_size = 0 code_size = 0 data_size = 0 load_segments = [s for s in elffile.iter_segments() if s['p_type'] == 'PT_LOAD'] prev_segment = None pad = 0 pad_size = [] w_found = False n = 0 # Check that load segments ordered by VA have the expected layout: # read only first, then read-write. Compute padding at end of each segment, # 0 if none is required. for segment in load_segments: if prev_segment: pad = segment['p_vaddr'] - (prev_segment['p_vaddr'] + prev_segment['p_filesz']) else: if segment['p_flags'] & P_FLAGS.PF_W: print('Expected RO load segment(s) first') sys.exit(1) if segment['p_flags'] & P_FLAGS.PF_W: if not w_found: # End of RO segments, discard padding for the last one (it # would just take up space in the generated C file) pad = 0 w_found = True else: if w_found: print('RO load segment found after RW one(s) (m={})'.format(n)) sys.exit(1) if prev_segment: if pad > 31: # We expect segments to be tightly packed together for memory # efficiency. 31 is an arbitrary, "sounds reasonable" value # which might need to be adjusted -- who knows what the # compiler/linker can do. print('Warning: suspiciously large padding ({}) after load ' 'segment {}, please check'.format(pad, n-1)) pad_size.append(pad) prev_segment = segment n = n + 1 pad_size.append(0) n = 0 # Compute code_size, data_size and load_size for segment in load_segments: sz = segment['p_filesz'] + pad_size[n] if segment['p_flags'] & P_FLAGS.PF_W: data_size += sz else: code_size += sz load_size += sz n = n + 1 n = 0 i = 0 # Output data to C file outf.write(b'const uint8_t ldelf_data[%d]' % round_up(load_size, 4096)) outf.write(b' __aligned(4096) = {\n') for segment in load_segments: data = segment.data() if pad_size[n]: # Pad with zeros if needed data += bytearray(pad_size[n]) for j in range(len(data)): if i % 8 == 0: outf.write(b'\t') outf.write(b'0x' + '{:02x}'.format(data[j]).encode('utf-8') + b',') i = i + 1 if i % 8 == 0 or i == load_size: outf.write(b'\n') else: outf.write(b' ') n = n + 1 outf.write(b'};\n') outf.write(b'const unsigned int ldelf_code_size = %d;\n' % code_size) outf.write(b'const unsigned int ldelf_data_size = %d;\n' % data_size) def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--input', required=True, type=argparse.FileType('rb'), help='The input ldelf.elf') parser.add_argument('--output', required=True, type=argparse.FileType('wb'), help='The output ldelf_hex.c') return parser.parse_args() def main(): args = get_args() inf = args.input outf = args.output elffile = ELFFile(inf) outf.write(b'/* Automatically generated, do no edit */\n') outf.write(b'#include \n') outf.write(b'#include \n') emit_load_segments(elffile, outf) outf.write(b'const unsigned long ldelf_entry = %lu;\n' % elffile.header['e_entry']) inf.close() outf.close() if __name__ == "__main__": main() optee_os-4.3.0/scripts/gen_stmm_hex.py000077500000000000000000000026301464416617300200710ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019, Linaro Limited # import argparse import sys import zlib def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--input', required=True, type=argparse.FileType('rb'), help='The input StMM binary (BL32_AP_MM.fd)') parser.add_argument('--output', required=True, type=argparse.FileType('w'), help='The output stmm_hex.c') return parser.parse_args() def main(): args = get_args() inf = args.input outf = args.output bytes = inf.read() uncompressed_size = len(bytes) bytes = zlib.compress(bytes) size = len(bytes) outf.write('/* Automatically generated, do no edit */\n') outf.write('const unsigned char stmm_image[] = {\n') i = 0 while i < size: if i % 8 == 0: outf.write('\t') outf.write('0x{:02x},'.format(bytes[i])) i = i + 1 if i % 8 == 0 or i == size: outf.write('\n') else: outf.write(' ') outf.write('};\n') outf.write('const unsigned int stmm_image_size = sizeof(stmm_image);\n') outf.write('const unsigned int stmm_image_uncompressed_size = ' '{:d};\n'.format(uncompressed_size)) inf.close() outf.close() if __name__ == "__main__": main() optee_os-4.3.0/scripts/gen_tee_bin.py000077500000000000000000000325561464416617300176640ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019, Linaro Limited # from __future__ import print_function from __future__ import division import argparse import sys import struct import re import hashlib try: from elftools.elf.elffile import ELFFile from elftools.elf.constants import SH_FLAGS from elftools.elf.enums import ENUM_RELOC_TYPE_ARM from elftools.elf.enums import ENUM_RELOC_TYPE_AARCH64 from elftools.elf.sections import SymbolTableSection from elftools.elf.relocation import RelocationSection except ImportError: print(""" *** Can't find elftools module. Probably it is not installed on your system. You can install this module with $ apt install python3-pyelftools if you are using Ubuntu. Or try to search for "pyelftools" or "elftools" in your package manager if you are using some other distribution. *** """) raise small_page_size = 4 * 1024 elffile_symbols = None tee_pageable_bin = None tee_pager_bin = None tee_embdata_bin = None def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) def round_up(n, m): if n == 0: return 0 else: return (((n - 1) // m) + 1) * m def get_arch_id(elffile): e_machine = elffile.header['e_machine'] if e_machine == 'EM_ARM': return 0 if e_machine == 'EM_AARCH64': return 1 eprint('Unknown e_machine "%s"' % e_machine) sys.exit(1) def get_name(obj): # Symbol or section .name might be a byte array or a string, we want a # string try: name = obj.name.decode() except (UnicodeDecodeError, AttributeError): name = obj.name return name def get_symbol(elffile, name): global elffile_symbols global lsyms_def if elffile_symbols is None: elffile_symbols = dict() lsyms_def = dict() symbol_tables = [s for s in elffile.iter_sections() if isinstance(s, SymbolTableSection)] for section in symbol_tables: for symbol in section.iter_symbols(): symbol_name = get_name(symbol) if symbol['st_info']['bind'] == 'STB_GLOBAL': elffile_symbols[symbol_name] = symbol elif symbol['st_info']['bind'] == 'STB_LOCAL': if symbol_name not in elffile_symbols.keys(): elffile_symbols[symbol_name] = symbol if symbol_name not in lsyms_def.keys(): lsyms_def[symbol_name] = 1 else: lsyms_def[symbol_name] += 1 if name in lsyms_def.keys() and lsyms_def[name] > 1: eprint("Multiple definitions of local symbol %s" % name) sys.exit(1) if name not in elffile_symbols.keys(): eprint("Cannot find symbol %s" % name) sys.exit(1) return elffile_symbols[name] def get_sections(elffile, pad_to, dump_names): last_end = 0 bin_data = bytearray() for section in elffile.iter_sections(): section_name = get_name(section) if (section['sh_type'] == 'SHT_NOBITS' or not (section['sh_flags'] & SH_FLAGS.SHF_ALLOC) or not dump_names.match(section_name)): continue if last_end == 0: bin_data = section.data() else: if section['sh_addr'] > last_end: bin_data += bytearray(section['sh_addr'] - last_end) bin_data += section.data() last_end = section['sh_addr'] + section['sh_size'] if pad_to > last_end: bin_data += bytearray(pad_to - last_end) last_end = pad_to return bin_data def get_pageable_bin(elffile): global tee_pageable_bin if tee_pageable_bin is None: pad_to = 0 dump_names = re.compile(r'^\..*_(pageable|init)$') tee_pageable_bin = get_sections(elffile, pad_to, dump_names) return tee_pageable_bin def get_pager_bin(elffile): global tee_pager_bin if tee_pager_bin is None: pad_to = get_symbol(elffile, '__data_end')['st_value'] dump_names = re.compile(r'^\.(text|nex_data|rodata|ctors|got|data|' r'data\.rel\.ro|ARM\.exidx|ARM\.extab)$') tee_pager_bin = get_sections(elffile, pad_to, dump_names) return tee_pager_bin def get_reloc_bin(elffile): if get_arch_id(elffile) == 0: exp_rel_type = ENUM_RELOC_TYPE_ARM['R_ARM_RELATIVE'] else: exp_rel_type = ENUM_RELOC_TYPE_AARCH64['R_AARCH64_RELATIVE'] link_address = get_symbol(elffile, '__text_start')['st_value'] addrs = [] for section in elffile.iter_sections(): if not isinstance(section, RelocationSection): continue for rel in section.iter_relocations(): if rel['r_info_type'] == 0: continue if rel['r_info_type'] != exp_rel_type: eprint("Unexpected relocation type 0x%x" % rel['r_info_type']) sys.exit(1) addrs.append(rel['r_offset'] - link_address) addrs.sort() data = bytearray() for a in addrs: data += struct.pack('> 32 init_load_addr_lo = init_load_addr & 0xffffffff return init_load_addr_hi, init_load_addr_lo def output_raw_bin(elffile, outf): pager_bin = get_pager_bin(elffile) pageable_bin = get_pageable_bin(elffile) embdata_bin = get_embdata_bin(elffile) init_bin_size = get_symbol(elffile, '__init_size')['st_value'] outf.write(pager_bin) outf.write(pageable_bin[:init_bin_size]) outf.write(embdata_bin) outf.write(pageable_bin[init_bin_size:]) def output_header_v1(elffile, outf): arch_id = get_arch_id(elffile) pager_bin = get_pager_bin(elffile) pageable_bin = get_pageable_bin(elffile) embdata_bin = get_embdata_bin(elffile) init_load_addr = get_init_load_addr(elffile) init_bin_size = get_symbol(elffile, '__init_size')['st_value'] pager_bin_size = len(pager_bin) paged_area_size = len(pageable_bin) init_mem_usage = (get_symbol(elffile, '__get_tee_init_end')['st_value'] - get_symbol(elffile, '__text_start')['st_value'] + len(embdata_bin)) init_size = (pager_bin_size + min(init_bin_size, paged_area_size) + len(embdata_bin)) paged_size = paged_area_size - min(init_bin_size, paged_area_size) magic = 0x4554504f # 'OPTE' version = 1 flags = 0 outf.write(struct.pack('.*) ') REVIEWED_RE = re.compile(r'^Reviewed-by: (?P.*>)') ACKED_RE = re.compile(r'^Acked-by: (?P.*>)') PATCH_START = re.compile(r'^From [0-9a-f]{40}') def get_args(): parser = argparse.ArgumentParser(description='Print the maintainers for ' 'the given source files or directories; ' 'or for the files modified by a patch or ' 'a pull request. ' '(With -m) Check if a patch or pull ' 'request is properly Acked/Reviewed for ' 'merging.') parser.add_argument('-m', '--merge-check', action='store_true', help='use Reviewed-by: and Acked-by: tags found in ' 'patches to prevent display of information for all ' 'the approved paths.') parser.add_argument('-p', '--show-paths', action='store_true', help='show all paths that are not approved.') parser.add_argument('-s', '--strict', action='store_true', help='stricter conditions for patch approval check: ' 'subsystem "THE REST" is ignored for paths that ' 'match some other subsystem.') parser.add_argument('arg', nargs='*', help='file or patch') parser.add_argument('-f', '--file', action='append', help='treat following argument as a file path, not ' 'a patch.') parser.add_argument('-g', '--github-pr', action='append', type=int, help='Github pull request ID. The script will ' 'download the patchset from Github to a temporary ' 'file and process it.') parser.add_argument('-r', '--release-to', action='store_true', help='show all the recipients to be used in release ' 'announcement emails (i.e., maintainers, reviewers ' 'and OP-TEE mailing list(s)) and exit.') return parser.parse_args() def check_cwd(): cwd = os.getcwd() parent = os.path.dirname(os.path.realpath(__file__)) + "/../" if (os.path.realpath(cwd) != os.path.realpath(parent)): print("Error: this script must be run from the top-level of the " "optee_os tree") exit(1) # Parse MAINTAINERS and return a dictionary of subsystems such as: # {'Subsystem name': {'R': ['foo', 'bar'], 'S': ['Maintained'], # 'F': [ 'path1', 'path2' ]}, ...} def parse_maintainers(): subsystems = {} check_cwd() with open("MAINTAINERS", "r") as f: start_found = False ss = {} name = '' for line in f: line = line.strip() if not line: continue if not start_found: if line.startswith("----------"): start_found = True continue if line[1] == ':': letter = line[0] if (not ss.get(letter)): ss[letter] = [] ss[letter].append(line[3:]) else: if name: subsystems[name] = ss name = line ss = {} if name: subsystems[name] = ss return subsystems # If @patchset is a patchset files and contains 2 patches or more, write # individual patches to temporary files and return the paths. # Otherwise return []. def split_patchset(patchset): psname = os.path.basename(patchset).replace('.', '_') patchnum = 0 of = None ret = [] f = None try: f = open(patchset, "r") except OSError: return [] for line in f: match = re.search(PATCH_START, line) if match: # New patch found: create new file patchnum += 1 prefix = "{}_{}_".format(patchnum, psname) of = tempfile.NamedTemporaryFile(mode="w", prefix=prefix, suffix=".patch", delete=False) ret.append(of.name) if of: of.write(line) if len(ret) >= 2: return ret if len(ret) == 1: os.remove(ret[0]) return [] # If @path is a patch file, returns the paths touched by the patch as well # as the content of the review/ack tags def get_paths_from_patch(patch): paths = [] approvers = [] try: with open(patch, "r") as f: for line in f: match = re.search(DIFF_GIT_RE, line) if match: p = match.group('path') if p not in paths: paths.append(p) continue match = re.search(REVIEWED_RE, line) if match: a = match.group('approver') if a not in approvers: approvers.append(a) continue match = re.search(ACKED_RE, line) if match: a = match.group('approver') if a not in approvers: approvers.append(a) continue except Exception: pass return (paths, approvers) # Does @path match @pattern? # @pattern has the syntax defined in the Linux MAINTAINERS file -- mostly a # shell glob pattern, except that a trailing slash means a directory and # everything below. Matching can easily be done by converting to a regexp. def match_pattern(path, pattern): # Append a trailing slash if path is an existing directory, so that it # matches F: entries such as 'foo/bar/' if not path.endswith('/') and os.path.isdir(path): path += '/' rep = "^" + pattern rep = rep.replace('*', '[^/]+') rep = rep.replace('?', '[^/]') if rep.endswith('/'): rep += '.*' rep += '$' return not not re.match(rep, path) def get_subsystems_for_path(subsystems, path, strict): found = {} for key in subsystems: def inner(): excluded = subsystems[key].get('X') if excluded: for pattern in excluded: if match_pattern(path, pattern): return # next key included = subsystems[key].get('F') if not included: return # next key for pattern in included: if match_pattern(path, pattern): found[key] = subsystems[key] inner() if strict and len(found) > 1: found.pop('THE REST', None) return found def get_ss_maintainers(subsys): return subsys.get('M') or [] def get_ss_reviewers(subsys): return subsys.get('R') or [] def get_ss_approvers(ss): return get_ss_maintainers(ss) + get_ss_reviewers(ss) def get_ss_lists(subsys): return subsys.get('L') or [] def approvers_have_approved(approved_by, approvers): for n in approvers: # Ignore anything after the email (Github ID...) n = n.split('>', 1)[0] for m in approved_by: m = m.split('>', 1)[0] if n == m: return True return False def download(pr): url = "https://github.com/OP-TEE/optee_os/pull/{}.patch".format(pr) f = tempfile.NamedTemporaryFile(mode="wb", prefix="pr{}_".format(pr), suffix=".patch", delete=False) print("Downloading {}...".format(url), end='', flush=True) f.write(urlopen(url).read()) print(" Done.") return f.name def show_release_to(subsystems): check_cwd() with open("MAINTAINERS", "r") as f: emails = sorted(set(re.findall(r'[RM]:\t(.*[\w]*<[\w\.-]+@[\w\.-]+>)', f.read()))) emails += get_ss_lists(subsystems["THE REST"]) print(*emails, sep=', ') def main(): global args args = get_args() all_subsystems = parse_maintainers() if args.release_to: show_release_to(all_subsystems) return paths = [] arglist = [] downloads = [] split_patches = [] for pr in args.github_pr or []: downloads += [download(pr)] for arg in args.arg + downloads: if os.path.exists(arg): patches = split_patchset(arg) if patches: split_patches += patches continue arglist.append(arg) for arg in arglist + split_patches: patch_paths = [] approved_by = [] if os.path.exists(arg): # Try to parse as a patch (patch_paths, approved_by) = get_paths_from_patch(arg) if not patch_paths: # Not a patch, consider the path itself # as_posix() cleans the path a little bit (suppress leading ./ and # duplicate slashes...) patch_paths = [PurePath(arg).as_posix()] for path in patch_paths: approved = False if args.merge_check: ss_for_path = get_subsystems_for_path(all_subsystems, path, args.strict) for key in ss_for_path: ss_approvers = get_ss_approvers(ss_for_path[key]) if approvers_have_approved(approved_by, ss_approvers): approved = True if not approved: paths += [path] for f in downloads + split_patches: os.remove(f) if args.file: paths += args.file if (args.show_paths): print(paths) ss = {} for path in paths: ss.update(get_subsystems_for_path(all_subsystems, path, args.strict)) for key in ss: ss_name = key[:50] + (key[50:] and '...') for name in ss[key].get('M') or []: print("{} (maintainer:{})".format(name, ss_name)) for name in ss[key].get('R') or []: print("{} (reviewer:{})".format(name, ss_name)) if __name__ == "__main__": main() optee_os-4.3.0/scripts/mem_usage.py000077500000000000000000000137711464416617300173660ustar00rootroot00000000000000#!/usr/bin/env python3 # # Copyright (c) 2014-2017, Linaro Limited # # SPDX-License-Identifier: BSD-3-Clause import argparse import os import subprocess import sys def get_args(): parser = argparse.ArgumentParser(description='Shows the memory usage ' 'of an OP-TEE based on ELF sections') parser.add_argument('tee_elf', help='the OP-TEE ELF file (tee.elf)') parser.add_argument('-a', '--all', action='store_true', help=' same as -i -p -u -U') parser.add_argument('-n', '--no-map', action='store_true', help=' do not show the detailed section mappings and ' 'RAM usage') parser.add_argument('-i', '--init', action='store_true', help='report the total size of the .*_init sections') parser.add_argument('-p', '--paged', action='store_true', help='report the total size of the .*_pageable ' 'sections') parser.add_argument('-u', '--unpaged', action='store_true', help='report the total size of the unpaged sections, ' 'that is, all sections but the ones in --init or ' '--paged') parser.add_argument('-U', '--unpaged-no-heap', action='store_true', help='report the size of all unpaged sections ' 'excluding heap space. Reflects the size of unpaged ' 'code and data (.text, .rodata, .data, .bss, .nozi ' 'and possibly unwind tables)') parser.add_argument('-r', '--raw', action='store_true', help='when processing -i, -p, -u, or -U, show only ' 'the size (in decimal) and no other text') return parser.parse_args() def printf(format, *args): sys.stdout.write(format % args) def print_sect(name, addr, size, round_up=False, print_num_pages=False): if args.no_map: return if size == 0: size_kib = 0 num_pages = 0 else: if round_up: size_kib = (size - 1) / 1024 + 1 else: size_kib = size / 1024 num_pages = (size - 1) / 4096 + 1 printf('%-16s %.8X - %.8X size %.8X %3d KiB', name, addr, addr + size, size, size_kib) if print_num_pages: printf(' %d pages', num_pages) printf('\n') def print_pager_stat(name, size): size_kib = size / 1024 if args.raw: printf('%d ', size) else: printf('%-36s size %.8X %3d KiB\n', name, size, size_kib) def readelf_cmd(): return os.getenv('CROSS_COMPILE', '') + 'readelf' def main(): global args in_shdr = False sects = [] init_size = 0 paged_size = 0 unpaged_size = 0 unpaged_no_heap_size = 0 args = get_args() env = os.environ.copy() env['LC_ALL'] = 'C' readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-s', args.tee_elf], stdout=subprocess.PIPE, env=env, universal_newlines=True) for line in iter(readelf.stdout.readline, ''): words = line.split() if len(words) == 8 and words[7] == '_end_of_ram': end_of_ram = int(words[1], 16) break readelf.terminate() readelf = subprocess.Popen(str.split(readelf_cmd()) + ['-S', '-W', args.tee_elf], stdout=subprocess.PIPE, env=env, universal_newlines=True) for line in iter(readelf.stdout.readline, ''): if 'Section Headers:' in line: in_shdr = True continue if 'Key to Flags:' in line: in_shdr = False continue if in_shdr: words = line.split() if words[0] == '[': words.pop(0) try: (_, name, _, addr, offs, size, _, flags) = words[:8] except BaseException: continue if ('A' in flags): sects.append({'name': name, 'addr': addr, 'offs': offs, 'size': size}) first_addr = None for sect in sects: if sect['addr'] != 0: addr = sect['addr'] if not first_addr: first_addr = addr if int(addr, 16) >= end_of_ram: break last_addr = addr last_size = sect['size'] ram_usage = int(last_addr, 16) + int(last_size, 16) - int(first_addr, 16) print_sect('RAM Usage', int(first_addr, 16), ram_usage, True, True) last_addr = 0 last_size = 0 for sect in sects: name = sect['name'] addr = int(sect['addr'], 16) size = int(sect['size'], 16) if addr >= end_of_ram: break if last_addr != 0 and addr != last_addr + last_size: print_sect('*hole*', last_addr + last_size, addr - (last_addr + last_size)) print_sect(name, addr, size) if name.endswith('_init'): init_size += size elif name.endswith('_pageable'): paged_size += size else: if not name.startswith('.heap'): unpaged_no_heap_size += size unpaged_size += size last_addr = addr last_size = size if args.all or args.init: print_pager_stat('Init sections (.*_init)', init_size) if args.all or args.paged: print_pager_stat('Paged sections (.*_pageable)', paged_size) if args.all or args.unpaged: print_pager_stat('Unpaged sections ', unpaged_size) if args.all or args.unpaged_no_heap: print_pager_stat('Unpaged sections (heap excluded)', unpaged_no_heap_size) if (args.raw and (args.all or args.init or args.paged or args.unpaged or args.unpaged_no_heap)): printf('\n') if __name__ == "__main__": main() optee_os-4.3.0/scripts/pem_to_pub_c.py000077500000000000000000000046441464416617300200560ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2015, Linaro Limited def get_args(): import argparse parser = argparse.ArgumentParser() parser.add_argument( '--prefix', required=True, help='Prefix for the public key exponent and modulus in c file') parser.add_argument( '--out', required=True, help='Name of c file for the public key') parser.add_argument('--key', required=True, help='Name of key file') return parser.parse_args() def main(): import array from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa args = get_args() with open(args.key, 'rb') as f: data = f.read() try: key = serialization.load_pem_private_key(data, password=None, backend=default_backend()) key = key.public_key() except ValueError: key = serialization.load_pem_public_key(data, backend=default_backend()) # Refuse public exponent with more than 32 bits. Otherwise the C # compiler may simply truncate the value and proceed. # This will lead to TAs seemingly having invalid signatures with a # possible security issue for any e = k*2^32 + 1 (for any integer k). if key.public_numbers().e > 0xffffffff: raise ValueError( 'Unsupported large public exponent detected. ' + 'OP-TEE handles only public exponents up to 2^32 - 1.') with open(args.out, 'w') as f: f.write("#include \n") f.write("#include \n\n") f.write("const uint32_t " + args.prefix + "_exponent = " + str(key.public_numbers().e) + ";\n\n") f.write("const uint8_t " + args.prefix + "_modulus[] = {\n") i = 0 nbuf = key.public_numbers().n.to_bytes(key.key_size >> 3, 'big') for x in array.array("B", nbuf): f.write("0x" + '{0:02x}'.format(x) + ",") i = i + 1 if i % 8 == 0: f.write("\n") else: f.write(" ") f.write("};\n") f.write("const size_t " + args.prefix + "_modulus_size = sizeof(" + args.prefix + "_modulus);\n") if __name__ == "__main__": main() optee_os-4.3.0/scripts/print_tee_hash.py000077500000000000000000000044701464416617300204140ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2021, Huawei Technologies Co., Ltd # from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection import codecs import sys verbose = False def dump(buf): print(codecs.encode(buf, 'hex').decode('utf-8')) def resolve_symbol(elf, name): for section in elf.iter_sections(): if isinstance(section, SymbolTableSection): for symbol in section.iter_symbols(): if symbol.name == name: return symbol.entry['st_value'] raise RuntimeError(f'Symbol {name} not found') def hash_range(h, elf, start, end): global verbose start_addr = resolve_symbol(elf, start) end_addr = resolve_symbol(elf, end) size = end_addr - start_addr if verbose: print(f'[{start}(0x{start_addr:x}), {end}(0x{end_addr:x})]: ' f'{size} bytes') for segment in elf.iter_segments(): if (segment['p_type'] == 'PT_LOAD' and segment['p_vaddr'] <= start_addr and end_addr <= segment['p_vaddr'] + segment['p_filesz']): begin_offs = start_addr - segment['p_vaddr'] h.update(segment.data()[begin_offs:begin_offs + size]) def hash_section(h, elf, name): global verbose s = elf.get_section_by_name(name) if s is None: return d = s.data() if verbose: print(f'{name}: {len(d)} bytes') h.update(d) def main(): global verbose argc = len(sys.argv) if argc != 2 and argc != 3: print('Usage:', sys.argv[0], '') return 1 if argc == 3 and sys.argv[1] == '-v': verbose = True with open(sys.argv[argc - 1], 'rb') as f: elf = ELFFile(f) h = hashes.Hash(hashes.SHA256(), default_backend()) hash_range(h, elf, '__text_start', '__text_data_start') hash_range(h, elf, '__text_data_end', '__text_end') hash_section(h, elf, '.text_init') hash_section(h, elf, '.text_pageable') hash_section(h, elf, '.rodata') hash_section(h, elf, '.rodata_init') hash_section(h, elf, '.rodata_pageable') dump(h.finalize()) if __name__ == "__main__": main() optee_os-4.3.0/scripts/sign_encrypt.py000077500000000000000000001100741464416617300201220ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2015, 2017, 2019, Linaro Limited # import sys import math sig_tee_alg = {'TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256': 0x70414930, 'TEE_ALG_RSASSA_PKCS1_V1_5_SHA256': 0x70004830} enc_tee_alg = {'TEE_ALG_AES_GCM': 0x40000810} enc_key_type = {'SHDR_ENC_KEY_DEV_SPECIFIC': 0x0, 'SHDR_ENC_KEY_CLASS_WIDE': 0x1} TEE_ATTR_RSA_MODULUS = 0xD0000130 TEE_ATTR_RSA_PUBLIC_EXPONENT = 0xD0000230 SHDR_BOOTSTRAP_TA = 1 SHDR_ENCRYPTED_TA = 2 SHDR_SUBKEY = 3 SHDR_MAGIC = 0x4f545348 SHDR_SIZE = 20 SK_HDR_SIZE = 20 EHDR_SIZE = 12 UUID_SIZE = 16 # Use 12 bytes for nonce per recommendation NONCE_SIZE = 12 TAG_SIZE = 16 def value_to_key(db, val): for k, v in db.items(): if v == val: return k def uuid_v5_sha512(namespace_bytes, name): from cryptography.hazmat.primitives import hashes from uuid import UUID h = hashes.Hash(hashes.SHA512()) h.update(namespace_bytes + bytes(name, 'utf-8')) digest = h.finalize() return UUID(bytes=digest[:16], version=5) def name_img_to_str(name_img): return name_img.decode().split('\x00', 1)[0] def uuid_parse(s): from uuid import UUID return UUID(s) def int_parse(str): return int(str, 0) def get_args(): import argparse import textwrap class OnlyOne(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): a = self.dest + '_assigned' if getattr(namespace, a, False): raise argparse.ArgumentError(self, 'Can only be given once') setattr(namespace, a, True) setattr(namespace, self.dest, values) def arg_add_uuid(parser): parser.add_argument( '--uuid', required=True, type=uuid_parse, help='String UUID of the TA') def arg_add_key(parser): parser.add_argument( '--key', required=True, help=''' Name of signing and verification key file (PEM format) or an Amazon Resource Name (arn:) of an AWS KMS asymmetric key. At least public key for the commands digest, stitch, and verify, else a private key''') def arg_add_enc_key(parser): parser.add_argument( '--enc-key', required=False, help='Encryption key string') def arg_add_enc_key_type(parser): parser.add_argument( '--enc-key-type', required=False, default='SHDR_ENC_KEY_DEV_SPECIFIC', choices=list(enc_key_type.keys()), help=''' Encryption key type, Defaults to SHDR_ENC_KEY_DEV_SPECIFIC.''') def arg_add_ta_version(parser): parser.add_argument( '--ta-version', required=False, type=int_parse, default=0, help=''' TA version stored as a 32-bit unsigned integer and used for rollback protection of TA install in the secure database. Defaults to 0.''') def arg_add_sig(parser): parser.add_argument( '--sig', required=True, dest='sigf', help='Name of signature input file, defaults to .sig') def arg_add_dig(parser): parser.add_argument( '--dig', required=True, dest='digf', help='Name of digest output file, defaults to .dig') def arg_add_in(parser): parser.add_argument( '--in', required=False, dest='inf', help=''' Name of application input file, defaults to .stripped.elf''') def arg_add_out(parser): parser.add_argument( '--out', required=True, dest='outf', help='Name of application output file, defaults to .ta') def arg_add_algo(parser): parser.add_argument( '--algo', required=False, choices=list(sig_tee_alg.keys()), default='TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256', help=''' The hash and signature algorithm. Defaults to TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256.''') def arg_add_subkey(parser): parser.add_argument( '--subkey', action=OnlyOne, help='Name of subkey input file') def arg_add_name(parser): parser.add_argument('--name', help='Input name for subspace of a subkey') def arg_add_subkey_uuid_in(parser): parser.add_argument( '--in', required=True, dest='inf', help='Name of subkey input file') def arg_add_max_depth(parser): parser.add_argument( '--max-depth', required=False, type=int_parse, help=''' Max depth of subkeys below this subkey''') def arg_add_name_size(parser): parser.add_argument( '--name-size', required=True, type=int_parse, help=''' Size of (unsigned) input name for subspace of a subkey. Set to 0 to create an identity subkey (a subkey having the same UUID as the next subkey or TA)''') def arg_add_subkey_version(parser): parser.add_argument( '--subkey-version', required=False, type=int_parse, default=0, help='Subkey version used for rollback protection') def arg_add_subkey_in(parser): parser.add_argument( '--in', required=True, dest='inf', help=''' Name of PEM file with the public key of the new subkey''') def arg_add_subkey_out(parser): parser.add_argument( '--out', required=True, dest='outf', help='Name of subkey output file') def get_outf_default(parsed): return str(parsed.uuid) + '.ta' def get_inf_default(parsed): return str(parsed.uuid) + '.stripped.elf' def get_sigf_default(parsed): return str(parsed.uuid) + '.sig' def get_digf_default(parsed): return str(parsed.uuid) + '.dig' def assign_default_value(parsed, attr, func): if hasattr(parsed, attr) and getattr(parsed, attr) is None: setattr(parsed, attr, func(parsed)) parser = argparse.ArgumentParser( description='Sign and encrypt (optional) a Trusted Application ' + ' for OP-TEE.', usage='%(prog)s ...', epilog=' -h for detailed help') subparsers = parser.add_subparsers( title='valid commands, with possible aliases in ()', dest='command', metavar='') parser_sign_enc = subparsers.add_parser( 'sign-enc', prog=parser.prog + ' sign-enc', help='Generate signed and optionally encrypted loadable TA image file') parser_sign_enc.set_defaults(func=command_sign_enc) arg_add_uuid(parser_sign_enc) arg_add_ta_version(parser_sign_enc) arg_add_in(parser_sign_enc) arg_add_out(parser_sign_enc) arg_add_key(parser_sign_enc) arg_add_subkey(parser_sign_enc) arg_add_name(parser_sign_enc) arg_add_enc_key(parser_sign_enc) arg_add_enc_key_type(parser_sign_enc) arg_add_algo(parser_sign_enc) parser_digest = subparsers.add_parser( 'digest', aliases=['generate-digest'], prog=parser.prog + ' digest', formatter_class=argparse.RawDescriptionHelpFormatter, help='Generate loadable TA binary image digest for offline signing', epilog=textwrap.dedent('''\ example offline signing command using OpenSSL for algorithm TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: base64 -d .dig | \\ openssl pkeyutl -sign -inkey .pem \\ -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss \\ -pkeyopt rsa_pss_saltlen:digest \\ -pkeyopt rsa_mgf1_md:sha256 | \\ base64 > .sig example offline signing command using OpenSSL for algorithm TEE_ALG_RSASSA_PKCS1_V1_5_SHA256: base64 -d .dig | \\ openssl pkeyutl -sign -inkey .pem \\ -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pkcs1 | \\ base64 > .sig ''')) parser_digest.set_defaults(func=command_digest) arg_add_uuid(parser_digest) arg_add_ta_version(parser_digest) arg_add_in(parser_digest) arg_add_key(parser_digest) arg_add_enc_key(parser_digest) arg_add_enc_key_type(parser_digest) arg_add_algo(parser_digest) arg_add_dig(parser_digest) parser_stitch = subparsers.add_parser( 'stitch', aliases=['stitch-ta'], prog=parser.prog + ' stich', help='Generate loadable signed and encrypted TA binary image file' + ' from TA raw image and its signature') parser_stitch.set_defaults(func=command_stitch) arg_add_uuid(parser_stitch) arg_add_ta_version(parser_stitch) arg_add_in(parser_stitch) arg_add_key(parser_stitch) arg_add_out(parser_stitch) arg_add_enc_key(parser_stitch) arg_add_enc_key_type(parser_stitch) arg_add_algo(parser_stitch) arg_add_sig(parser_stitch) parser_verify = subparsers.add_parser( 'verify', prog=parser.prog + ' verify', help='Verify signed TA binary') parser_verify.set_defaults(func=command_verify) arg_add_uuid(parser_verify) arg_add_in(parser_verify) arg_add_key(parser_verify) parser_display = subparsers.add_parser( 'display', prog=parser.prog + ' display', help='Parses and displays a signed TA binary') parser_display.set_defaults(func=command_display) arg_add_in(parser_display) parser_subkey_uuid = subparsers.add_parser( 'subkey-uuid', prog=parser.prog + ' subkey-uuid', help='calculate the UUID of next TA or subkey') parser_subkey_uuid.set_defaults(func=command_subkey_uuid) arg_add_subkey_uuid_in(parser_subkey_uuid) arg_add_name(parser_subkey_uuid) parser_sign_subkey = subparsers.add_parser( 'sign-subkey', prog=parser.prog + ' sign-subkey', help='Sign a subkey') parser_sign_subkey.set_defaults(func=command_sign_subkey) arg_add_name(parser_sign_subkey) arg_add_subkey_in(parser_sign_subkey) arg_add_uuid(parser_sign_subkey) arg_add_key(parser_sign_subkey) arg_add_subkey_out(parser_sign_subkey) arg_add_max_depth(parser_sign_subkey) arg_add_name_size(parser_sign_subkey) arg_add_subkey(parser_sign_subkey) arg_add_subkey_version(parser_sign_subkey) arg_add_algo(parser_sign_subkey) argv = sys.argv[1:] if (len(argv) > 0 and argv[0][0] == '-' and argv[0] != '-h' and argv[0] != '--help'): # The default sub-command is 'sign-enc' so add it to the parser # if one is missing argv = ['sign-enc'] + argv parsed = parser.parse_args(argv) if parsed.command is None: parser.print_help() sys.exit(1) # Set a few defaults if defined for the current command assign_default_value(parsed, 'inf', get_inf_default) assign_default_value(parsed, 'outf', get_outf_default) assign_default_value(parsed, 'sigf', get_sigf_default) assign_default_value(parsed, 'digf', get_digf_default) return parsed def load_asymmetric_key_img(data): from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import ( load_pem_private_key, load_pem_public_key) try: return load_pem_private_key(data, password=None, backend=default_backend()) except ValueError: return load_pem_public_key(data, backend=default_backend()) def load_asymmetric_key(arg_key): if arg_key.startswith('arn:'): from sign_helper_kms import _RSAPrivateKeyInKMS return _RSAPrivateKeyInKMS(arg_key) else: with open(arg_key, 'rb') as f: return load_asymmetric_key_img(f.read()) class BinaryImage: def __init__(self, arg_inf, arg_key): from cryptography.hazmat.primitives import hashes # Exactly what inf is holding isn't determined a this stage if isinstance(arg_inf, str): with open(arg_inf, 'rb') as f: self.inf = f.read() else: self.inf = arg_inf if arg_key is None: self.key = None else: if isinstance(arg_key, str): self.key = load_asymmetric_key(arg_key) else: self.key = arg_key self.sig_size = math.ceil(self.key.key_size / 8) self.chosen_hash = hashes.SHA256() self.hash_size = self.chosen_hash.digest_size def __pack_img(self, img_type, sign_algo): import struct self.sig_algo = sign_algo self.img_type = img_type self.shdr = struct.pack('= getattr(self, 'previous_max_depth')): logger.error('Max depth of previous subkey is {} ' .format(self.previous_max_depth) + 'and the next value must be smaller') sys.exit(1) def int_to_bytes(x: int) -> bytes: return x.to_bytes((x.bit_length() + 8) // 8, 'big') n_bytes = int_to_bytes(subkey_pkey.public_numbers().n) e_bytes = int_to_bytes(subkey_pkey.public_numbers().e) attrs_end_offs = 16 + 5 * 4 + 2 * 3 * 4 shdr_subkey = struct.pack(' 0: # name_size is the previous subkey header name_img = self.inf[offs:offs + name_size] print(' next name: "{}"'.format(name_img_to_str(name_img))) offs += name_size print('Next header at offset: {} (0x{:x})' .format(offs, offs)) shdr = self.inf[offs:offs + SHDR_SIZE] [magic, img_type, img_size, algo_value, hash_size, sig_size] = struct.unpack(' 0: sk_image = BinaryImage(sk_image.next_inf, None) sk_image.parse() if name is None: name = '' self.previous_max_depth = sk_image.max_depth self.name_img = str.encode(name).ljust(sk_image.name_size, b'\0') def write(self, outf): with open(outf, 'wb') as f: if hasattr(self, 'subkey_img'): f.write(self.subkey_img) f.write(self.name_img) f.write(self.shdr) f.write(self.img_digest) f.write(self.sig) if hasattr(self, 'ta_uuid'): f.write(self.ta_uuid) f.write(self.ta_version) if hasattr(self, 'ehdr'): f.write(self.ehdr) f.write(self.nonce) f.write(self.tag) f.write(self.ciphertext) else: f.write(self.img) def load_ta_image(args): ta_image = BinaryImage(args.inf, args.key) if args.enc_key: ta_image.encrypt_ta(args.enc_key, args.enc_key_type, args.algo, args.uuid, args.ta_version) else: ta_image.set_bootstrap_ta(args.algo, args.uuid, args.ta_version) return ta_image def command_sign_enc(args): ta_image = load_ta_image(args) if args.subkey: ta_image.add_subkey(args.subkey, args.name) ta_image.sign() ta_image.write(args.outf) logger.info('Successfully signed application.') def command_sign_subkey(args): image = BinaryImage(args.inf, args.key) if args.subkey: image.add_subkey(args.subkey, args.name) image.set_subkey(args.algo, args.name, args.uuid, args.subkey_version, args.max_depth, args.name_size) image.sign() image.write(args.outf) logger.info('Successfully signed subkey.') def command_digest(args): import base64 ta_image = load_ta_image(args) with open(args.digf, 'wb+') as digfile: digfile.write(base64.b64encode(ta_image.img_digest)) def command_stitch(args): ta_image = load_ta_image(args) ta_image.add_signature(args.sigf) ta_image.verify_signature() ta_image.write(args.outf) logger.info('Successfully applied signature.') def command_verify(args): import uuid image = BinaryImage(args.inf, args.key) next_uuid = None max_depth = -1 while True: image.parse() if hasattr(image, 'subkey_hdr'): # Subkey print('Subkey UUID: {}'.format(uuid.UUID(bytes=image.uuid))) image.verify_signature() image.verify_digest() if next_uuid: if uuid.UUID(bytes=image.uuid) != next_uuid: raise Exception('UUID {} does not match {}' .format(uuid.UUID(bytes=image.uuid), next_uuid)) if max_depth >= 0: if image.max_depth < 0 or image.max_depth >= max_depth: raise Exception('Invalid max_depth {} not less than {}' .format(image.max_depth, max_depth)) max_depth = image.max_depth if len(image.next_inf) == 0: logger.info('Subkey is correctly verified.') return if image.name_size > 0: next_uuid = uuid_v5_sha512(image.uuid, name_img_to_str(image.name_img)) else: next_uuid = image.uuid image = BinaryImage(image.next_inf, image.subkey_key) else: # TA print('TA UUID: {}'.format(uuid.UUID(bytes=image.ta_uuid))) if next_uuid: if uuid.UUID(bytes=image.ta_uuid) != next_uuid: raise Exception('UUID {} does not match {}' .format(uuid.UUID(bytes=image.ta_uuid), next_uuid)) if hasattr(image, 'ciphertext'): if args.enc_key is None: logger.error('--enc_key needed to decrypt TA') sys.exit(1) image.decrypt_ta(args.enc_key) image.verify_signature() image.verify_digest() image.verify_uuid(args.uuid) logger.info('Trusted application is correctly verified.') return def command_display(args): ta_image = BinaryImage(args.inf, None) ta_image.display() def command_subkey_uuid(args): import uuid sk_image = BinaryImage(args.inf, None) sk_image.parse() if not hasattr(sk_image, 'next_inf'): logger.error('Invalid subkey file') sys.exit(1) print('Subkey UUID: {}'.format(uuid.UUID(bytes=sk_image.uuid))) while len(sk_image.next_inf) > 0: sk_image = BinaryImage(sk_image.next_inf, None) sk_image.parse() print('Subkey UUID: {}'.format(uuid.UUID(bytes=sk_image.uuid))) if args.name: if len(args.name) > sk_image.name_size: logger.error('Length of name ({}) '.format(len(args.name)) + 'is larger than max name size ({})' .format(sk_image.name_size)) sys.exit(1) print('Next subkey UUID: {}' .format(uuid_v5_sha512(sk_image.uuid, args.name))) else: print('Next subkey UUID unchanged: {}' .format(uuid.UUID(bytes=sk_image.uuid))) def main(): import logging import os global logger logging.basicConfig() logger = logging.getLogger(os.path.basename(__file__)) args = get_args() args.func(args) if __name__ == "__main__": main() optee_os-4.3.0/scripts/sign_helper_kms.py000077500000000000000000000057471464416617300206010ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright Amazon.com Inc. or its affiliates # import typing import boto3 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( AsymmetricSignatureContext, utils as asym_utils, ) from cryptography.hazmat.primitives.asymmetric.padding import ( AsymmetricPadding, PKCS1v15, PSS, ) from cryptography.hazmat.primitives.asymmetric.rsa import ( RSAPrivateKey, RSAPrivateNumbers, RSAPublicKey, ) class _RSAPrivateKeyInKMS(RSAPrivateKey): def __init__(self, arn): self.arn = arn self.client = boto3.client('kms') response = self.client.get_public_key(KeyId=self.arn) # Parse public key self.public_key = serialization.load_der_public_key( response['PublicKey']) @property def key_size(self): return self.public_key.key_size def public_key(self) -> RSAPublicKey: return self.public_key def sign(self, data: bytes, padding: AsymmetricPadding, algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm] ) -> bytes: if isinstance(algorithm, asym_utils.Prehashed): message_type = 'DIGEST' else: message_type = 'RAW' if isinstance(padding, PSS): signing_alg = 'RSASSA_PSS_' elif isinstance(padding, PKCS1v15): signing_alg = 'RSASSA_PKCS1_V1_5_' else: raise TypeError("Unsupported padding") if (isinstance(algorithm._algorithm, hashes.SHA256) or isinstance(algorithm, hashes.SHA256)): signing_alg += 'SHA_256' elif (isinstance(algorithm._algorithm, hashes.SHA384) or isinstance(algorithm, hashes.SHA384)): signing_alg += 'SHA_384' elif (isinstance(algorithm._algorithm, hashes.SHA512) or isinstance(algorithm, hashes.SHA512)): signing_alg += 'SHA_512' else: raise TypeError("Unsupported hashing algorithm") response = self.client.sign( KeyId=self.arn, Message=data, MessageType=message_type, SigningAlgorithm=signing_alg) return response['Signature'] # No need to implement these functions so we raise an exception def signer( self, padding: AsymmetricPadding, algorithm: hashes.HashAlgorithm ) -> AsymmetricSignatureContext: raise NotImplementedError def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: raise NotImplementedError def private_numbers(self) -> RSAPrivateNumbers: raise NotImplementedError def private_bytes( self, encoding: serialization.Encoding, format: serialization.PrivateFormat, encryption_algorithm: serialization.KeySerializationEncryption ) -> bytes: raise NotImplementedError optee_os-4.3.0/scripts/sign_rproc_fw.py000077500000000000000000000372541464416617300202670ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (C) 2023, STMicroelectronics # try: from elftools.elf.elffile import ELFFile from elftools.elf.sections import SymbolTableSection from elftools.elf.enums import ENUM_P_TYPE_ARM from elftools.elf.enums import * except ImportError: print(""" *** ERROR: "pyelftools" python module is not installed or version < 0.25. *** """) raise try: from Cryptodome.Hash import SHA256 from Cryptodome.Signature import pkcs1_15 from Cryptodome.PublicKey import RSA from Cryptodome.Signature import DSS from Cryptodome.PublicKey import ECC except ImportError: print(""" *** ERROR: "pycryptodomex" python module should be installed. *** """) raise import os import sys import struct import logging import binascii # Generated file structure: # # -----+-------------+ # / | Magic | 32-bit word, magic value equal to # / +-------------+ 0x3543A468 # / +-------------+ # / | version | 32-bit word, version of the format # / +-------------+ # +-----------+ +-------------+ # | Header | | TLV size | 32-bit word, size of the TLV # +-----------+ +-------------+ (aligned on 64-bit), in bytes. # \ +-------------+ # \ | sign size | 32-bit word, size of the signature # \ +-------------+ (aligned on 64-bit), in bytes. # \ +-------------+ # \ | images size | 32-bit word, size of the images to # -----+-------------+ load (aligned on 64-bit), in bytes. # # +-------------+ Information used to authenticate the # | TLV | images and boot the remote processor, # | | stored in Type-Length-Value format. # +-------------+ 'Type' and 'Length' are 32-bit words. # # +-------------+ # | Signature | Signature of the header and the TLV. # +-------------+ # # +-------------+ # | Firmware | # | image 1 | # +-------------+ # ... # +-------------+ # | Firmware | # | image n | # +-------------+ # Generic type definitions TLV_TYPES = { 'SIGNTYPE': 0x00000001, # algorithm used for signature 'HASHTYPE': 0x00000002, # algorithm used for computing segment's hash 'NUM_IMG': 0x00000003, # number of images to load 'IMGTYPE': 0x00000004, # array of type of images to load 'IMGSIZE': 0x00000005, # array of the size of the images to load 'HASHTABLE': 0x000000010, # segment hash table for authentication 'PKEYINFO': 0x0000000011, # information to retrieve signature key } GENERIC_TLV_TYPE_RANGE = range(0x00000000, 0x00010000) PLATFORM_TLV_TYPE_RANGE = range(0x00010000, 0x00020000) HEADER_MAGIC = 0x3543A468 logging.basicConfig(stream=sys.stderr, level=logging.INFO) ENUM_HASH_TYPE = dict( SHA256=1, ) ENUM_SIGNATURE_TYPE = dict( RSA=1, ECC=2, ) ENUM_BINARY_TYPE = dict( ELF=1, ) def dump_buffer(buf, step=16, name="", logger=logging.debug, indent=""): logger("%s%s:" % (indent, name)) for i in range(0, len(buf), step): logger("%s " % (indent) + " ". join(["%02X" % c for c in buf[i:i+step]])) logger("\n") class TLV(): def __init__(self): self.buf = bytearray() self.tlvs = {} def add(self, kind, payload): """ Add a TLV record. Argument type is either the type scalar ID or a matching string defined in TLV_TYPES. """ if isinstance(kind, int): buf = struct.pack('II', kind, len(payload)) else: buf = struct.pack('II', TLV_TYPES[kind], len(payload)) # Ensure that each TLV is 64-bit aligned align_64b = (len(payload) + len(buf)) % 8 self.buf += buf self.buf += payload if align_64b: self.buf += bytearray(8 - align_64b) def add_plat_tlv(self, cust_tlv): # Get list of custom protected TLVs from the command-line for tlv in cust_tlv: type_id = int(tlv[0], 0) if type_id not in PLATFORM_TLV_TYPE_RANGE: raise Exception('TLV %s not in range' % hex(type_id)) value = tlv[1] if value.startswith('0x'): int_val = int(value[2:], 16) self.tlvs[type_id] = int_val.to_bytes(4, 'little') else: self.tlvs[type_id] = value.encode('utf-8') if self.tlvs is not None: for type_id, value in self.tlvs.items(): self.add(type_id, value) def get(self): """ Get a byte-array that concatenates all the TLV added. """ if len(self.buf) == 0: return bytes() return bytes(self.buf) class RSA_Signature(object): def __init__(self, key): self._hasher = SHA256.new() self.signer = pkcs1_15.new(key) def hash_compute(self, segment): self._hasher.update(segment) def sign(self): return self.signer.sign(self._hasher) class ECC_Signature(object): def __init__(self, key): self._hasher = SHA256.new() self.signer = DSS.new(key, 'fips-186-3') def hash_compute(self, segment): self._hasher.update(segment) def sign(self): return self.signer.sign(self._hasher) Signature = { 1: RSA_Signature, 2: ECC_Signature, } class SegmentHashStruct: pass class SegmentHash(object): ''' Hash table based on Elf program segments ''' def __init__(self, img): self._num_segments = img.num_segments() self._pack_fmt = '<%dL' % 8 self.img = img self.hashProgTable = bytes() self._offset = 0 def get_table(self): ''' Create a segment hash table containing for each segment: - the segments header - a hash of the segment ''' h = SHA256.new() seg = SegmentHashStruct() self.size = (h.digest_size + 32) * self._num_segments logging.debug("hash section size %d" % self.size) del h self.buf = bytearray(self.size) self._bufview_ = memoryview(self.buf) for i in range(self._num_segments): h = SHA256.new() segment = self.img.get_segment(i) seg.header = self.img.get_segment(i).header logging.debug("compute hash for segment offset %s" % seg.header) h.update(segment.data()) seg.hash = h.digest() logging.debug("hash computed: %s" % seg.hash) del h struct.pack_into('0x[0-9a-f]+)') # This gets the address from lines looking like this: # E/TC:0 0x001044a8 STACK_ADDR_RE = re.compile( r'[UEIDFM]/(TC|LD):([0-9]+ )?(\?*|[0-9]*) [0-9]* +(?P0x[0-9a-f]+)') ABORT_ADDR_RE = re.compile(r'-abort at address (?P0x[0-9a-f]+)') TA_PANIC_RE = re.compile(r'TA panicked with code (?P0x[0-9a-f]+)') REGION_RE = re.compile(r'region +[0-9]+: va (?P0x[0-9a-f]+) ' r'pa 0x[0-9a-f]+ size (?P0x[0-9a-f]+)' r'( flags .{4} (\[(?P[0-9]+)\])?)?') ELF_LIST_RE = re.compile(r'\[(?P[0-9]+)\] (?P[0-9a-f\-]+)' r' @ (?P0x[0-9a-f\-]+)') FUNC_GRAPH_RE = re.compile(r'Function graph') GRAPH_ADDR_RE = re.compile(r'(?P0x[0-9a-f]+)') GRAPH_RE = re.compile(r'}') epilog = ''' This scripts reads an OP-TEE abort or panic message from stdin and adds debug information to the output, such as ' at :' next to each address in the call stack. Any message generated by OP-TEE and containing a call stack can in principle be processed by this script. This currently includes aborts and panics from the TEE core as well as from any TA. The paths provided on the command line are used to locate the appropriate ELF binary (tee.elf or Trusted Application). The GNU binutils (addr2line, objdump, nm) are used to extract the debug info. If the CROSS_COMPILE environment variable is set, it is used as a prefix to the binutils tools. That is, the script will invoke $(CROSS_COMPILE)addr2line etc. If it is not set however, the prefix will be determined automatically for each ELF file based on its architecture. The resulting command is then expected to be found in the user's PATH. OP-TEE abort and panic messages are sent to the secure console. They look like the following: E/TC:0 User TA data-abort at address 0xffffdecd (alignment fault) ... E/TC:0 Call stack: E/TC:0 0x4000549e E/TC:0 0x40001f4b E/TC:0 0x4000273f E/TC:0 0x40005da7 Inspired by a script of the same name by the Chromium project. Sample usage: $ scripts/symbolize.py -d out/arm-plat-hikey/core -d ../optee_test/out/ta/* ^D Also, this script reads function graph generated for OP-TEE user TA from /tmp/ftrace-.out file and resolves function addresses to corresponding symbols. Sample usage: $ cat /tmp/ftrace-.out | scripts/symbolize.py -d .elf ^D ''' tee_result_names = { '0xf0100001': 'TEE_ERROR_CORRUPT_OBJECT', '0xf0100002': 'TEE_ERROR_CORRUPT_OBJECT_2', '0xf0100003': 'TEE_ERROR_STORAGE_NOT_AVAILABLE', '0xf0100004': 'TEE_ERROR_STORAGE_NOT_AVAILABLE_2', '0xf0100006': 'TEE_ERROR_CIPHERTEXT_INVALID ', '0xffff0000': 'TEE_ERROR_GENERIC', '0xffff0001': 'TEE_ERROR_ACCESS_DENIED', '0xffff0002': 'TEE_ERROR_CANCEL', '0xffff0003': 'TEE_ERROR_ACCESS_CONFLICT', '0xffff0004': 'TEE_ERROR_EXCESS_DATA', '0xffff0005': 'TEE_ERROR_BAD_FORMAT', '0xffff0006': 'TEE_ERROR_BAD_PARAMETERS', '0xffff0007': 'TEE_ERROR_BAD_STATE', '0xffff0008': 'TEE_ERROR_ITEM_NOT_FOUND', '0xffff0009': 'TEE_ERROR_NOT_IMPLEMENTED', '0xffff000a': 'TEE_ERROR_NOT_SUPPORTED', '0xffff000b': 'TEE_ERROR_NO_DATA', '0xffff000c': 'TEE_ERROR_OUT_OF_MEMORY', '0xffff000d': 'TEE_ERROR_BUSY', '0xffff000e': 'TEE_ERROR_COMMUNICATION', '0xffff000f': 'TEE_ERROR_SECURITY', '0xffff0010': 'TEE_ERROR_SHORT_BUFFER', '0xffff0011': 'TEE_ERROR_EXTERNAL_CANCEL', '0xffff300f': 'TEE_ERROR_OVERFLOW', '0xffff3024': 'TEE_ERROR_TARGET_DEAD', '0xffff3041': 'TEE_ERROR_STORAGE_NO_SPACE', '0xffff3071': 'TEE_ERROR_MAC_INVALID', '0xffff3072': 'TEE_ERROR_SIGNATURE_INVALID', '0xffff5000': 'TEE_ERROR_TIME_NOT_SET', '0xffff5001': 'TEE_ERROR_TIME_NEEDS_RESET', } def get_args(): parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description='Symbolizes OP-TEE abort dumps or function graphs', epilog=epilog) parser.add_argument('-d', '--dir', action='append', nargs='+', help='Search for ELF file in DIR. tee.elf is needed ' 'to decode a TEE Core or pseudo-TA abort, while ' '.elf is required if a user-mode TA has ' 'crashed. For convenience, ELF files may also be ' 'given.') parser.add_argument('-s', '--strip_path', nargs='?', help='Strip STRIP_PATH from file paths (default: ' 'current directory, use -s with no argument to show ' 'full paths)', default=os.getcwd()) return parser.parse_args() class Symbolizer(object): def __init__(self, out, dirs, strip_path): self._out = out self._dirs = dirs self._strip_path = strip_path self._addr2line = None self.reset() def my_Popen(self, cmd): try: return subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True, bufsize=1) except OSError as e: if e.errno == errno.ENOENT: print("*** Error:{}: command not found".format(cmd[0]), file=sys.stderr) sys.exit(1) def get_elf(self, elf_or_uuid): if not elf_or_uuid.endswith('.elf'): elf_or_uuid += '.elf' for d in self._dirs: if d.endswith(elf_or_uuid) and os.path.isfile(d): return d elf = glob.glob(d + '/' + elf_or_uuid) if elf: return elf[0] def set_arch(self, elf): self._arch = os.getenv('CROSS_COMPILE') if self._arch: return p = subprocess.Popen(['file', '-L', elf], stdout=subprocess.PIPE) output = p.stdout.readlines() p.terminate() if b'ARM aarch64,' in output[0]: self._arch = 'aarch64-linux-gnu-' elif b'ARM,' in output[0]: self._arch = 'arm-linux-gnueabihf-' elif b'RISC-V,' in output[0]: if b'32-bit' in output[0]: self._arch = 'riscv32-unknown-linux-gnu-' elif b'64-bit' in output[0]: self._arch = 'riscv64-unknown-linux-gnu-' def arch_prefix(self, cmd, elf): self.set_arch(elf) if self._arch is None: return '' return self._arch + cmd def spawn_addr2line(self, elf_name): if elf_name is None: return if self._addr2line_elf_name is elf_name: return if self._addr2line: self._addr2line.terminate self._addr2line = None elf = self.get_elf(elf_name) if not elf: return cmd = self.arch_prefix('addr2line', elf) if not cmd: return self._addr2line = self.my_Popen([cmd, '-f', '-p', '-e', elf]) self._addr2line_elf_name = elf_name # If addr falls into a region that maps a TA ELF file, return the load # address of that file. def elf_load_addr(self, addr): if self._regions: for r in self._regions: r_addr = int(r[0], 16) r_size = int(r[1], 16) i_addr = int(addr, 16) if (i_addr >= r_addr and i_addr < (r_addr + r_size)): # Found region elf_idx = r[2] if elf_idx is not None: return self._elfs[int(elf_idx)][1] # In case address is not found in TA ELF file, fallback to tee.elf # especially to symbolize mixed (user-space and kernel) addresses # which is true when syscall ftrace is enabled along with TA # ftrace. return self._tee_load_addr else: # tee.elf return self._tee_load_addr def elf_for_addr(self, addr): l_addr = self.elf_load_addr(addr) if l_addr == self._tee_load_addr: return 'tee.elf' for k in self._elfs: e = self._elfs[k] if int(e[1], 16) == int(l_addr, 16): return e[0] return None def subtract_load_addr(self, addr): l_addr = self.elf_load_addr(addr) if l_addr is None: return None if int(l_addr, 16) > int(addr, 16): return '' return '0x{:x}'.format(int(addr, 16) - int(l_addr, 16)) def resolve(self, addr): reladdr = self.subtract_load_addr(addr) self.spawn_addr2line(self.elf_for_addr(addr)) if not reladdr or not self._addr2line: return '???' if self.elf_for_addr(addr) == 'tee.elf': reladdr = '0x{:x}'.format(int(reladdr, 16) + int(self.first_vma('tee.elf'), 16)) try: print(reladdr, file=self._addr2line.stdin) ret = self._addr2line.stdout.readline().rstrip('\n') except IOError: ret = '!!!' return ret def symbol_plus_offset(self, addr): ret = '' prevsize = 0 reladdr = self.subtract_load_addr(addr) elf_name = self.elf_for_addr(addr) if elf_name is None: return '' elf = self.get_elf(elf_name) if elf is None: return '' cmd = self.arch_prefix('nm', elf) if not reladdr or not elf or not cmd: return '' ireladdr = int(reladdr, 16) nm = self.my_Popen([cmd, '--numeric-sort', '--print-size', elf]) for line in iter(nm.stdout.readline, ''): try: addr, size, _, name = line.split() except ValueError: # Size is missing try: addr, _, name = line.split() size = '0' except ValueError: # E.g., undefined (external) symbols (line = "U symbol") continue iaddr = int(addr, 16) isize = int(size, 16) if iaddr == ireladdr: ret = name break if iaddr < ireladdr and iaddr + isize >= ireladdr: offs = ireladdr - iaddr ret = name + '+' + str(offs) break if iaddr > ireladdr and prevsize == 0: offs = iaddr + ireladdr ret = prevname + '+' + str(offs) break prevsize = size prevname = name nm.terminate() return ret def section_plus_offset(self, addr): ret = '' reladdr = self.subtract_load_addr(addr) elf_name = self.elf_for_addr(addr) if elf_name is None: return '' elf = self.get_elf(elf_name) if elf is None: return '' cmd = self.arch_prefix('objdump', elf) if not reladdr or not elf or not cmd: return '' iaddr = int(reladdr, 16) objdump = self.my_Popen([cmd, '--section-headers', elf]) for line in iter(objdump.stdout.readline, ''): try: idx, name, size, vma, lma, offs, algn = line.split() except ValueError: continue ivma = int(vma, 16) isize = int(size, 16) if ivma == iaddr: ret = name break if ivma < iaddr and ivma + isize >= iaddr: offs = iaddr - ivma ret = name + '+' + str(offs) break objdump.terminate() return ret def process_abort(self, line): ret = '' match = re.search(ABORT_ADDR_RE, line) addr = match.group('addr') pre = match.start('addr') post = match.end('addr') sym = self.symbol_plus_offset(addr) sec = self.section_plus_offset(addr) if sym or sec: ret += line[:pre] ret += addr if sym: ret += ' ' + sym if sec: ret += ' ' + sec ret += line[post:] return ret # Return all ELF sections with the ALLOC flag def read_sections(self, elf_name): if elf_name is None: return if elf_name in self._sections: return elf = self.get_elf(elf_name) if not elf: return cmd = self.arch_prefix('objdump', elf) if not elf or not cmd: return self._sections[elf_name] = [] objdump = self.my_Popen([cmd, '--section-headers', elf]) for line in iter(objdump.stdout.readline, ''): try: _, name, size, vma, _, _, _ = line.split() except ValueError: if 'ALLOC' in line: self._sections[elf_name].append([name, int(vma, 16), int(size, 16)]) def first_vma(self, elf_name): self.read_sections(elf_name) return '0x{:x}'.format(self._sections[elf_name][0][1]) def overlaps(self, section, addr, size): sec_addr = section[1] sec_size = section[2] if not size or not sec_size: return False return ((addr <= (sec_addr + sec_size - 1)) and ((addr + size - 1) >= sec_addr)) def sections_in_region(self, addr, size, elf_idx): ret = '' addr = self.subtract_load_addr(addr) if not addr: return '' iaddr = int(addr, 16) isize = int(size, 16) elf = self._elfs[int(elf_idx)][0] if elf is None: return '' self.read_sections(elf) if elf not in self._sections: return '' for s in self._sections[elf]: if self.overlaps(s, iaddr, isize): ret += ' ' + s[0] return ret def reset(self): self._call_stack_found = False if self._addr2line: self._addr2line.terminate() self._addr2line = None self._addr2line_elf_name = None self._arch = None self._saved_abort_line = '' self._sections = {} # {elf_name: [[name, addr, size], ...], ...} self._regions = [] # [[addr, size, elf_idx, saved line], ...] self._elfs = {0: ["tee.elf", 0]} # {idx: [uuid, load_addr], ...} self._tee_load_addr = '0x0' self._func_graph_found = False self._func_graph_skip_line = True def pretty_print_path(self, path): if self._strip_path: return re.sub(re.escape(self._strip_path) + '/*', '', path) return path def write(self, line): if self._call_stack_found: match = re.search(STACK_ADDR_RE, line) if match: addr = match.group('addr') pre = match.start('addr') post = match.end('addr') self._out.write(line[:pre]) self._out.write(addr) # The call stack contains return addresses (LR/ELR values). # Heuristic: subtract 2 to obtain the call site of the function # or the location of the exception. This value works for A64, # A32 as well as Thumb. pc = 0 lr = int(addr, 16) if lr: pc = lr - 2 res = self.resolve('0x{:x}'.format(pc)) res = self.pretty_print_path(res) self._out.write(' ' + res) self._out.write(line[post:]) return else: self.reset() if self._func_graph_found: match = re.search(GRAPH_ADDR_RE, line) match_re = re.search(GRAPH_RE, line) if match: addr = match.group('addr') pre = match.start('addr') post = match.end('addr') self._out.write(line[:pre]) res = self.resolve(addr) res_arr = re.split(' ', res) self._out.write(res_arr[0]) self._out.write(line[post:]) self._func_graph_skip_line = False return elif match_re: self._out.write(line) return elif self._func_graph_skip_line: return else: self.reset() match = re.search(REGION_RE, line) if match: # Region table: save info for later processing once # we know which UUID corresponds to which ELF index addr = match.group('addr') size = match.group('size') elf_idx = match.group('elf_idx') self._regions.append([addr, size, elf_idx, line]) return match = re.search(ELF_LIST_RE, line) if match: # ELF list: save info for later. Region table and ELF list # will be displayed when the call stack is reached i = int(match.group('idx')) self._elfs[i] = [match.group('uuid'), match.group('load_addr'), line] return match = re.search(TA_PANIC_RE, line) if match: code = match.group('code') if code in tee_result_names: line = line.strip() + ' (' + tee_result_names[code] + ')\n' self._out.write(line) return match = re.search(TEE_LOAD_ADDR_RE, line) if match: self._tee_load_addr = match.group('load_addr') match = re.search(CALL_STACK_RE, line) if match: self._call_stack_found = True if self._regions: for r in self._regions: r_addr = r[0] r_size = r[1] elf_idx = r[2] saved_line = r[3] if elf_idx is None: self._out.write(saved_line) else: self._out.write(saved_line.strip() + self.sections_in_region(r_addr, r_size, elf_idx) + '\n') if self._elfs: for k in self._elfs: e = self._elfs[k] if (len(e) >= 3): # TA executable or library self._out.write(e[2].strip()) elf = self.get_elf(e[0]) if elf: rpath = os.path.realpath(elf) path = self.pretty_print_path(rpath) self._out.write(' (' + path + ')') self._out.write('\n') # Here is a good place to resolve the abort address because we # have all the information we need if self._saved_abort_line: self._out.write(self.process_abort(self._saved_abort_line)) match = re.search(FUNC_GRAPH_RE, line) if match: self._func_graph_found = True match = re.search(ABORT_ADDR_RE, line) if match: self.reset() # At this point the arch and TA load address are unknown. # Save the line so We can translate the abort address later. self._saved_abort_line = line self._out.write(line) def flush(self): self._out.flush() def main(): args = get_args() if args.dir: # Flatten list in case -d is used several times *and* with multiple # arguments args.dirs = [item for sublist in args.dir for item in sublist] else: args.dirs = [] symbolizer = Symbolizer(sys.stdout, args.dirs, args.strip_path) fd = sys.stdin.fileno() isatty = os.isatty(fd) if isatty: old = termios.tcgetattr(fd) new = termios.tcgetattr(fd) new[3] = new[3] & ~termios.ECHO # lflags try: if isatty: termios.tcsetattr(fd, termios.TCSADRAIN, new) for line in sys.stdin: symbolizer.write(line) finally: symbolizer.flush() if isatty: termios.tcsetattr(fd, termios.TCSADRAIN, old) if __name__ == "__main__": main() optee_os-4.3.0/scripts/tee_bin_parser.py000077500000000000000000000032021464416617300203710ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2016, Linaro Limited import struct import argparse def get_args(): parser = argparse.ArgumentParser() parser.add_argument('--input', required=False, dest='inf', default='../out/arm/core/tee.bin', help='The input tee.bin') return parser.parse_args() def main(): args = get_args() with open(args.inf, "rb") as f: data = f.read(4) magic = struct.unpack('\n\n') f.write('#include \n\n') f.write('const uint8_t ts_bin_' + ts_uuid.hex + '[] = {\n') ts_size, ts_uncompressed_size = dump_bin(f, ts, args.compress) f.write('};\n') if is_sp: f.write('#include \n\n') f.write('const uint8_t fdt_bin_' + ts_uuid.hex + '[] = {\n') dump_bin(f, args.manifest, False) f.write('};\n') f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(sp_images, struct \ sp_image) = {\n') f.write('\t.fdt = fdt_bin_' + ts_uuid.hex + ',\n') f.write('. image = {') f.write('\t.flags = 0x{:04x},\n'.format(sp_get_flags(ts))) else: f.write('SCATTERED_ARRAY_DEFINE_PG_ITEM(early_tas, struct \ embedded_ts) = {\n') f.write('\t.flags = 0x{:04x},\n'.format(ta_get_flags(ts))) f.write('\t.uuid = {\n') f.write('\t\t.timeLow = 0x{:08x},\n'.format(ts_uuid.time_low)) f.write('\t\t.timeMid = 0x{:04x},\n'.format(ts_uuid.time_mid)) f.write('\t\t.timeHiAndVersion = ' + '0x{:04x},\n'.format(ts_uuid.time_hi_version)) f.write('\t\t.clockSeqAndNode = {\n') csn = '{0:02x}{1:02x}{2:012x}'.format(ts_uuid.clock_seq_hi_variant, ts_uuid.clock_seq_low, ts_uuid.node) f.write('\t\t\t') f.write(', '.join('0x' + csn[i:i + 2] for i in range(0, len(csn), 2))) f.write('\n\t\t},\n\t},\n') f.write('\t.size = sizeof(ts_bin_' + ts_uuid.hex + '), /* {:d} */\n'.format(ts_size)) f.write('\t.ts = ts_bin_' + ts_uuid.hex + ',\n') if args.compress: f.write('\t.uncompressed_size = ' '{:d},\n'.format(ts_uncompressed_size)) if is_sp: f.write('}\n') f.write('};\n') f.close() if __name__ == "__main__": main() optee_os-4.3.0/scripts/update_changelog.py000077500000000000000000000065121464416617300207100ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: BSD-2-Clause # # Copyright (c) 2019, Linaro Limited # from subprocess import Popen, PIPE import argparse def get_args(): parser = argparse.ArgumentParser(description='Helper script that updates ' 'the CHANGELOG.md file.\n' 'Usage example:\n' ' ./update_changelog.py ' ' --changelog-file CHANGELOG.md' ' --release-version 3.7.0' ' --previous-release-version 3.6.0' ' --release-date 2019-10-11') parser.add_argument('--changelog-file', action='store', required=False, default='CHANGELOG.md', help='Changelog file to be updated.') parser.add_argument('--release-date', action='store', required=True, help='The release date (yyyy-mm-dd).') parser.add_argument('--release-version', action='store', required=True, help='Release version (MAJOR.MINOR.PATCH).') parser.add_argument('--previous-release-version', action='store', required=True, help='Previous release version (MAJOR.MINOR.PATCH).') return parser.parse_args() def prepend_write(filename, text): with open(filename, 'r+') as f: current_content = f.read() f.seek(0, 0) f.write(text + '\n' + current_content) f.flush() def get_previous_release_date(tag): cmd = "git log -1 --date=format:%Y-%m-%d --format=format:%cd " \ "{}".format(tag) process = Popen(cmd.split(), stdout=PIPE) (output, err) = process.communicate() return output.decode("utf-8") def main(): global args args = get_args() gits = ["OP-TEE/optee_os", "OP-TEE/optee_client", "OP-TEE/optee_test", "OP-TEE/build", "linaro-swg/optee_examples"] # Shorten name clf = args.changelog_file rv = args.release_version prv = args.previous_release_version rd = args.release_date prd = get_previous_release_date(prv) # In some cases we need underscore in string rvu = rv.replace('.', '_') text = "# OP-TEE - version {} ({})\n".format(rv, rd) text += "\n" text += "- Links to the release pages, commits and pull requests merged " \ "into this release for:\n" for g in gits: gu = g.replace('/', '_') gu = gu.replace('-', '_') text += " - {}: [release page][{}_release_{}], " \ "[commits][{}_commits_{}] and [pull requests]" \ "[{}_pr_{}]\n".format(g, gu, rvu, gu, rvu, gu, rvu) text += "\n" for g in gits: gu = g.replace('/', '_') gu = gu.replace('-', '_') text += "\n[{}_release_{}]: https://github.com/{}/releases/tag/" \ "{}\n".format(gu, rvu, g, rv) text += "[{}_commits_{}]: https://github.com/{}/compare/" \ "{}...{}\n".format(gu, rvu, g, prv, rv) text += "[{}_pr_{}]: https://github.com/{}/pulls?q=is%3Apr+is%3A" \ "merged+base%3Amaster+merged%3A{}..{}\n".format( gu, rvu, g, prd, rd) prepend_write(args.changelog_file, text) if __name__ == "__main__": main() optee_os-4.3.0/ta/000077500000000000000000000000001464416617300137535ustar00rootroot00000000000000optee_os-4.3.0/ta/arch/000077500000000000000000000000001464416617300146705ustar00rootroot00000000000000optee_os-4.3.0/ta/arch/arm/000077500000000000000000000000001464416617300154475ustar00rootroot00000000000000optee_os-4.3.0/ta/arch/arm/ta.ld.S000066400000000000000000000056431464416617300166050ustar00rootroot00000000000000#ifdef ARM32 OUTPUT_FORMAT("elf32-littlearm") OUTPUT_ARCH(arm) #define MCOUNT_SYM __gnu_mcount_nc #endif #ifdef ARM64 OUTPUT_FORMAT("elf64-littleaarch64") OUTPUT_ARCH(aarch64) #define MCOUNT_SYM _mcount #endif #ifndef CFG_FTRACE_BUF_SIZE #define CFG_FTRACE_BUF_SIZE 2048 #endif SECTIONS { .text : { __text_start = .; *(.text .text.*) *(.stub) *(.glue_7) *(.glue_7t) *(.gnu.linkonce.t.*) /* Workaround for an erratum in ARM's VFP11 coprocessor */ *(.vfp11_veneer) __text_end = .; } .note.gnu.property : { *(.note.gnu.property) } .plt : { *(.plt) } .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } .eh_frame : { KEEP(*(.eh_frame)) *(.eh_frame.*) } .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } .rodata : { *(.gnu.linkonce.r.*) *(.rodata .rodata.*) } .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } /* .ARM.exidx is sorted, so has to go in its own output section. */ PROVIDE_HIDDEN(__exidx_start = .); .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } PROVIDE_HIDDEN(__exidx_end = .); .ctors : { *(.ctors) } .dtors : { *(.dtors) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .hash : { *(.hash) } /* Page align to allow dropping execute bit for RW data */ . = ALIGN(4096); .dynamic : { *(.dynamic) } .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .got : { *(.got.plt) *(.got) } .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } .rel.dyn : { *(.rel.dyn) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.ctors : { *(.rel.ctors) } .rela.ctors : { *(.rela.ctors) } .rel.dtors : { *(.rel.dtors) } .rela.dtors : { *(.rela.dtors) } .rel.init : { *(.rel.init) } .rela.init : { *(.rela.init) } .rel.fini : { *(.rel.fini) } .rela.fini : { *(.rela.fini) } .rel.bss : { *(.rel.bss) } .rela.bss : { *(.rela.bss) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .data : { *(.data .data.* .gnu.linkonce.d.*) } .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) /* * TA tracing using ftrace * Reserve some space for the ftrace buffer, only if the * TA is instrumented (i.e., some files were built with -pg). */ . = ALIGN(8); __ftrace_buf_start = .; . += DEFINED(MCOUNT_SYM) ? CFG_FTRACE_BUF_SIZE : 0; __ftrace_buf_end = .; } /DISCARD/ : { *(.interp) } } optee_os-4.3.0/ta/arch/arm/ta_entry_a32.S000066400000000000000000000011221464416617300200610ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2019, Linaro Limited */ #include .section .note.GNU-stack,"",%progbits /* * This function is the bottom of the user call stack. Mark it as such so that * the unwinding code won't try to go further down. * We need an assembly wrapper because Clang does not accept asm(".cantunwind") * in a C function: * * user_ta_header.c:44:6: error: .fnstart must precede .cantunwind directive * asm(".cantunwind"); * ^ */ FUNC __ta_entry, : UNWIND( .cantunwind) bl __ta_entry_c END_FUNC __ta_entry optee_os-4.3.0/ta/arch/riscv/000077500000000000000000000000001464416617300160165ustar00rootroot00000000000000optee_os-4.3.0/ta/arch/riscv/ta.ld.S000066400000000000000000000051321464416617300171450ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ #ifdef RV32 OUTPUT_FORMAT("elf32-littleriscv") OUTPUT_ARCH(riscv) #endif #ifdef RV64 OUTPUT_FORMAT("elf64-littleriscv") OUTPUT_ARCH(riscv) #endif #define MCOUNT_SYM _mcount #ifndef CFG_FTRACE_BUF_SIZE #define CFG_FTRACE_BUF_SIZE 2048 #endif SECTIONS { .ta_head : {*(.ta_head)} .text : { __text_start = .; *(.text .text.*) *(.stub) *(.gnu.linkonce.t.*) __text_end = .; } .note.gnu.property : { *(.note.gnu.property) } .plt : { *(.plt) } .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } .eh_frame : { KEEP(*(.eh_frame)) *(.eh_frame.*) } .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } .rodata : { *(.gnu.linkonce.r.*) *(.rodata .rodata.*) } .ctors : { *(.ctors) } .dtors : { *(.dtors) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .hash : { *(.hash) } /* Page align to allow dropping execute bit for RW data */ . = ALIGN(4096); .dynamic : { *(.dynamic) } .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .got : { *(.got.plt) *(.got) } .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } .rel.dyn : { *(.rel.dyn) } .rel.got : { *(.rel.got) } .rela.got : { *(.rela.got) } .rel.ctors : { *(.rel.ctors) } .rela.ctors : { *(.rela.ctors) } .rel.dtors : { *(.rel.dtors) } .rela.dtors : { *(.rela.dtors) } .rel.init : { *(.rel.init) } .rela.init : { *(.rela.init) } .rel.fini : { *(.rel.fini) } .rela.fini : { *(.rela.fini) } .rel.bss : { *(.rel.bss) } .rela.bss : { *(.rela.bss) } .rel.plt : { *(.rel.plt) } .rela.plt : { *(.rela.plt) } .data : { *(.data .data.* .gnu.linkonce.d.*) } .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) /* * TA tracing using ftrace * Reserve some space for the ftrace buffer, only if the * TA is instrumented (i.e., some files were built with -pg). */ . = ALIGN(8); __ftrace_buf_start = .; . += DEFINED(MCOUNT_SYM) ? CFG_FTRACE_BUF_SIZE : 0; __ftrace_buf_end = .; } /DISCARD/ : { *(.interp) } } optee_os-4.3.0/ta/avb/000077500000000000000000000000001464416617300145235ustar00rootroot00000000000000optee_os-4.3.0/ta/avb/Makefile000066400000000000000000000007621464416617300161700ustar00rootroot00000000000000# The UUID for the Trusted Application BINARY=023f8f1a-292a-432b-8fc4-de8471358067 ifdef TA_CROSS_COMPILE CROSS_COMPILE ?= $(TA_CROSS_COMPILE) endif export CROSS_COMPILE CFG_TEE_TA_LOG_LEVEL ?= 2 CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) -include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), ) clean: @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA' @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)' endif optee_os-4.3.0/ta/avb/entry.c000066400000000000000000000225151464416617300160350ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* Copyright (c) 2018, Linaro Limited */ #include #include #include #include #define DEFAULT_LOCK_STATE 0 static const uint32_t storageid = TEE_STORAGE_PRIVATE_RPMB; static const char rb_obj_name[] = "rb_state"; static const char *named_value_prefix = "named_value_"; static TEE_Result get_slot_offset(size_t slot, size_t *offset) { if (slot >= TA_AVB_MAX_ROLLBACK_LOCATIONS) return TEE_ERROR_BAD_PARAMETERS; *offset = sizeof(uint32_t) /* lock_state */ + slot * sizeof(uint64_t); return TEE_SUCCESS; } static TEE_Result create_rb_state(uint32_t lock_state, TEE_ObjectHandle *h) { const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_OVERWRITE; return TEE_CreatePersistentObject(storageid, rb_obj_name, sizeof(rb_obj_name), flags, NULL, &lock_state, sizeof(lock_state), h); } static TEE_Result open_rb_state(uint32_t default_lock_state, TEE_ObjectHandle *h) { uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE; TEE_Result res; res = TEE_OpenPersistentObject(storageid, rb_obj_name, sizeof(rb_obj_name), flags, h); if (!res) return TEE_SUCCESS; return create_rb_state(default_lock_state, h); } static TEE_Result get_named_object_name(char *name_orig, uint32_t name_orig_size, char *name, uint32_t *name_size) { size_t pref_len = strlen(named_value_prefix); if (name_orig_size + pref_len > TEE_OBJECT_ID_MAX_LEN) return TEE_ERROR_BAD_PARAMETERS; /* Start with prefix */ TEE_MemMove(name, named_value_prefix, pref_len); /* Concatenate provided object name */ TEE_MemMove(name + pref_len, name_orig, name_orig_size); *name_size = name_orig_size + pref_len; return TEE_SUCCESS; } static TEE_Result read_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); size_t slot_offset; uint64_t idx; size_t count; TEE_Result res; TEE_ObjectHandle h; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; res = get_slot_offset(params[0].value.a, &slot_offset); if (res) return res; res = open_rb_state(DEFAULT_LOCK_STATE, &h); if (res) return res; res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); if (res) goto out; res = TEE_ReadObjectData(h, &idx, sizeof(idx), &count); if (res) goto out; if (count != sizeof(idx)) { idx = 0; /* Not yet written slots are reported as 0 */ if (count) { /* * Somehow the file didn't even hold a complete * slot index entry. Write it as 0. */ res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); if (res) goto out; res = TEE_WriteObjectData(h, &idx, sizeof(idx)); if (res) goto out; } } params[1].value.a = idx >> 32; params[1].value.b = idx; out: TEE_CloseObject(h); return res; } static TEE_Result write_rb_idx(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); size_t slot_offset; uint64_t widx; uint64_t idx; size_t count; TEE_Result res; TEE_ObjectHandle h; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; res = get_slot_offset(params[0].value.a, &slot_offset); if (res) return res; widx = ((uint64_t)params[1].value.a << 32) | params[1].value.b; res = open_rb_state(DEFAULT_LOCK_STATE, &h); if (res) return res; res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); if (res) goto out; res = TEE_ReadObjectData(h, &idx, sizeof(idx), &count); if (res) goto out; if (count != sizeof(idx)) idx = 0; /* Not yet written slots are reported as 0 */ if (widx < idx) { res = TEE_ERROR_SECURITY; goto out; } res = TEE_SeekObjectData(h, slot_offset, TEE_DATA_SEEK_SET); if (res) goto out; res = TEE_WriteObjectData(h, &widx, sizeof(widx)); out: TEE_CloseObject(h); return res; } static TEE_Result read_lock_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t lock_state; size_t count; TEE_Result res; TEE_ObjectHandle h; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; res = open_rb_state(DEFAULT_LOCK_STATE, &h); if (res) return res; res = TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count); if (res) goto out; if (count != sizeof(lock_state)) { /* * Client need write the lock state to recover, this can * normally not happen. */ res = TEE_ERROR_CORRUPT_OBJECT; goto out; } params[0].value.a = lock_state; out: TEE_CloseObject(h); return res; } static TEE_Result write_lock_state(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t wlock_state; uint32_t lock_state; size_t count; TEE_Result res; TEE_ObjectHandle h; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; wlock_state = params[0].value.a; res = open_rb_state(wlock_state, &h); if (res) return res; res = TEE_ReadObjectData(h, &lock_state, sizeof(lock_state), &count); if (res) goto out; if (count == sizeof(lock_state) && lock_state == wlock_state) goto out; res = TEE_SeekObjectData(h, 0, TEE_DATA_SEEK_SET); if (res) goto out; res = TEE_WriteObjectData(h, &wlock_state, sizeof(wlock_state)); out: TEE_CloseObject(h); return res; } static TEE_Result write_persist_value(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); const uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_OVERWRITE; char name_full[TEE_OBJECT_ID_MAX_LEN] = { }; TEE_ObjectHandle h = TEE_HANDLE_NULL; TEE_Result res = TEE_SUCCESS; uint32_t name_full_sz = 0; uint32_t name_buf_sz = 0; uint32_t value_sz = 0; char *name_buf = NULL; char *value = NULL; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; name_buf = params[0].memref.buffer; name_buf_sz = params[0].memref.size; value_sz = params[1].memref.size; value = TEE_Malloc(value_sz, 0); if (!value) return TEE_ERROR_OUT_OF_MEMORY; TEE_MemMove(value, params[1].memref.buffer, value_sz); res = get_named_object_name(name_buf, name_buf_sz, name_full, &name_full_sz); if (res) goto out; res = TEE_CreatePersistentObject(storageid, name_full, name_full_sz, flags, NULL, value, value_sz, &h); if (res) EMSG("Can't create named object value, res = 0x%x", res); TEE_CloseObject(h); out: TEE_Free(value); return res; } static TEE_Result read_persist_value(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); uint32_t flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE; TEE_Result res = TEE_SUCCESS; TEE_ObjectHandle h = TEE_HANDLE_NULL; char name_full[TEE_OBJECT_ID_MAX_LEN]; uint32_t name_full_sz = 0; uint32_t name_buf_sz = 0; char *name_buf = NULL; uint32_t value_sz = 0; char *value = NULL; size_t count = 0; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; name_buf = params[0].memref.buffer; name_buf_sz = params[0].memref.size; value_sz = params[1].memref.size; value = TEE_Malloc(value_sz, 0); if (!value) return TEE_ERROR_OUT_OF_MEMORY; res = get_named_object_name(name_buf, name_buf_sz, name_full, &name_full_sz); if (res) goto out_free; res = TEE_OpenPersistentObject(storageid, name_full, name_full_sz, flags, &h); if (res) { EMSG("Can't open named object value, res = 0x%x", res); goto out_free; } res = TEE_ReadObjectData(h, value, value_sz, &count); if (res) { EMSG("Can't read named object value, res = 0x%x", res); goto out; } TEE_MemMove(params[1].memref.buffer, value, value_sz); params[1].memref.size = count; out: TEE_CloseObject(h); out_free: TEE_Free(value); return res; } TEE_Result TA_CreateEntryPoint(void) { return TEE_SUCCESS; } void TA_DestroyEntryPoint(void) { } TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, TEE_Param params[4] __unused, void **session __unused) { return TEE_SUCCESS; } void TA_CloseSessionEntryPoint(void *sess __unused) { } TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd) { case TA_AVB_CMD_READ_ROLLBACK_INDEX: return read_rb_idx(pt, params); case TA_AVB_CMD_WRITE_ROLLBACK_INDEX: return write_rb_idx(pt, params); case TA_AVB_CMD_READ_LOCK_STATE: return read_lock_state(pt, params); case TA_AVB_CMD_WRITE_LOCK_STATE: return write_lock_state(pt, params); case TA_AVB_CMD_READ_PERSIST_VALUE: return read_persist_value(pt, params); case TA_AVB_CMD_WRITE_PERSIST_VALUE: return write_persist_value(pt, params); default: EMSG("Command ID 0x%x is not supported", cmd); return TEE_ERROR_NOT_SUPPORTED; } } optee_os-4.3.0/ta/avb/include/000077500000000000000000000000001464416617300161465ustar00rootroot00000000000000optee_os-4.3.0/ta/avb/include/ta_avb.h000066400000000000000000000032251464416617300175550ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ #ifndef __TA_AVB_H #define __TA_AVB_H #define TA_AVB_UUID { 0x023f8f1a, 0x292a, 0x432b, \ { 0x8f, 0xc4, 0xde, 0x84, 0x71, 0x35, 0x80, 0x67 } } #define TA_AVB_MAX_ROLLBACK_LOCATIONS 256 /* * Gets the rollback index corresponding to the given rollback index slot. * * in params[0].value.a: rollback index slot * out params[1].value.a: upper 32 bits of rollback index * out params[1].value.b: lower 32 bits of rollback index */ #define TA_AVB_CMD_READ_ROLLBACK_INDEX 0 /* * Updates the rollback index corresponding to the given rollback index slot. * * Will refuse to update a slot with a lower value. * * in params[0].value.a: rollback index slot * in params[1].value.a: upper 32 bits of rollback index * in params[1].value.b: lower 32 bits of rollback index */ #define TA_AVB_CMD_WRITE_ROLLBACK_INDEX 1 /* * Gets the lock state of the device. * * out params[0].value.a: lock state */ #define TA_AVB_CMD_READ_LOCK_STATE 2 /* * Sets the lock state of the device. * * If the lock state is changed all rollback slots will be reset to 0 * * in params[0].value.a: lock state */ #define TA_AVB_CMD_WRITE_LOCK_STATE 3 /* * Reads a persistent value corresponding to the given name. * * in params[0].memref: persistent value name * out params[1].memref: read persistent value buffer */ #define TA_AVB_CMD_READ_PERSIST_VALUE 4 /* * Writes a persistent value corresponding to the given name. * * in params[0].memref: persistent value name * in params[1].memref: persistent value buffer to write */ #define TA_AVB_CMD_WRITE_PERSIST_VALUE 5 #endif /*__TA_AVB_H*/ optee_os-4.3.0/ta/avb/sub.mk000066400000000000000000000001041464416617300156400ustar00rootroot00000000000000global-incdirs-y += include global-incdirs-y += . srcs-y += entry.c optee_os-4.3.0/ta/avb/user_ta.mk000066400000000000000000000001121464416617300165100ustar00rootroot00000000000000user-ta-uuid := 023f8f1a-292a-432b-8fc4-de8471358067 user-ta-version := 0 optee_os-4.3.0/ta/avb/user_ta_header_defines.h000066400000000000000000000006161464416617300213460ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* Copyright (c) 2018, Linaro Limited */ #ifndef __USER_TA_HEADER_DEFINES_H #define __USER_TA_HEADER_DEFINES_H #include #define TA_UUID TA_AVB_UUID #define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ TA_FLAG_MULTI_SESSION) #define TA_STACK_SIZE (16 * 1024) #define TA_DATA_SIZE (16 * 1024) #endif /*__USER_TA_HEADER_DEFINES_H*/ optee_os-4.3.0/ta/link.mk000066400000000000000000000106121464416617300152410ustar00rootroot00000000000000link-script$(sm) = $(ta-dev-kit-dir$(sm))/src/ta.ld.S link-script-pp$(sm) = $(link-out-dir$(sm))/ta.lds link-script-dep$(sm) = $(link-out-dir$(sm))/.ta.ld.d SIGN_ENC ?= $(PYTHON3) $(ta-dev-kit-dir$(sm))/scripts/sign_encrypt.py TA_SIGN_KEY ?= $(ta-dev-kit-dir$(sm))/keys/default_ta.pem ifeq ($(CFG_ENCRYPT_TA),y) # Default TA encryption key is a dummy key derived from default # hardware unique key (an array of 16 zero bytes) to demonstrate # usage of REE-FS TAs encryption feature. # # Note that a user of this TA encryption feature needs to provide # encryption key and its handling corresponding to their security # requirements. TA_ENC_KEY ?= 'b64d239b1f3c7d3b06506229cd8ff7c8af2bb4db2168621ac62c84948468c4f4' endif all: $(link-out-dir$(sm))/$(user-ta-uuid).dmp \ $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf \ $(link-out-dir$(sm))/$(user-ta-uuid).ta cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).elf cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).dmp cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).map cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf cleanfiles += $(link-out-dir$(sm))/$(user-ta-uuid).ta cleanfiles += $(link-script-pp$(sm)) $(link-script-dep$(sm)) link-ldflags = -e__ta_entry -pie link-ldflags += -T $(link-script-pp$(sm)) link-ldflags += -Map=$(link-out-dir$(sm))/$(user-ta-uuid).map link-ldflags += --sort-section=alignment link-ldflags += -z max-page-size=4096 # OP-TEE always uses 4K alignment ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y) link-ldflags += $(call ld-option,-z force-bti) --fatal-warnings endif link-ldflags += --as-needed # Do not add dependency on unused shlib link-ldflags += $(link-ldflags$(sm)) $(link-out-dir$(sm))/dyn_list: FORCE @$(cmd-echo-silent) ' GEN $@' $(q)mkdir -p $(dir $@) $(q)echo "{" >$@.tmp $(q)echo "__elf_phdr_info;" >>$@.tmp ifeq ($(CFG_FTRACE_SUPPORT),y) $(q)echo "__ftrace_info;" >>$@.tmp endif $(q)echo "trace_ext_prefix;" >>$@.tmp $(q)echo "trace_level;" >>$@.tmp $(q)echo "ta_head;" >>$@.tmp $(q)echo "};" >>$@.tmp $(q)$(call mv-if-changed,$@.tmp,$@) link-ldflags += --dynamic-list $(link-out-dir$(sm))/dyn_list dynlistdep = $(link-out-dir$(sm))/dyn_list cleanfiles += $(link-out-dir$(sm))/dyn_list link-ldadd = $(user-ta-ldadd) $(addprefix -L,$(libdirs)) link-ldadd += --start-group link-ldadd += $(addprefix -l,$(libnames)) ifneq (,$(filter %.cpp,$(srcs))) link-ldflags += --eh-frame-hdr link-ldadd += $(libstdc++$(sm)) $(libgcc_eh$(sm)) endif link-ldadd += --end-group link-ldadd-after-libgcc += $(addprefix -l,$(libnames-after-libgcc)) ldargs-$(user-ta-uuid).elf := $(link-ldflags) $(objs) $(link-ldadd) \ $(libgcc$(sm)) $(link-ldadd-after-libgcc) link-script-cppflags-$(sm) := \ $(filter-out $(CPPFLAGS_REMOVE) $(cppflags-remove), \ $(nostdinc$(sm)) $(CPPFLAGS) \ $(addprefix -I,$(incdirs$(sm)) $(link-out-dir$(sm))) \ $(cppflags$(sm))) -include $(link-script-dep$(sm)) link-script-pp-makefiles$(sm) = $(filter-out %.d %.cmd,$(MAKEFILE_LIST)) define gen-link-t $(link-script-pp$(sm)): $(link-script$(sm)) $(conf-file) $(link-script-pp-makefiles$(sm)) @$(cmd-echo-silent) ' CPP $$@' $(q)mkdir -p $$(dir $$@) $(q)$(CPP$(sm)) -P -MT $$@ -MD -MF $(link-script-dep$(sm)) \ $(link-script-cppflags-$(sm)) $$< -o $$@ $(link-out-dir$(sm))/$(user-ta-uuid).elf: $(objs) $(libdeps) \ $(libdeps-after-libgcc) \ $(link-script-pp$(sm)) \ $(dynlistdep) \ $(additional-link-deps) @$(cmd-echo-silent) ' LD $$@' $(q)$(LD$(sm)) $(ldargs-$(user-ta-uuid).elf) -o $$@ $(link-out-dir$(sm))/$(user-ta-uuid).dmp: \ $(link-out-dir$(sm))/$(user-ta-uuid).elf @$(cmd-echo-silent) ' OBJDUMP $$@' $(q)$(OBJDUMP$(sm)) -l -x -d $$< > $$@ $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf: \ $(link-out-dir$(sm))/$(user-ta-uuid).elf @$(cmd-echo-silent) ' OBJCOPY $$@' $(q)$(OBJCOPY$(sm)) --strip-unneeded $$< $$@ cmd-echo$(user-ta-uuid) := SIGN # ifeq ($(CFG_ENCRYPT_TA),y) crypt-args$(user-ta-uuid) := --enc-key $(TA_ENC_KEY) cmd-echo$(user-ta-uuid) := SIGNENC endif $(link-out-dir$(sm))/$(user-ta-uuid).ta: \ $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf \ $(TA_SIGN_KEY) $(TA_SUBKEY_DEPS) \ $(lastword $(SIGN_ENC)) @$(cmd-echo-silent) ' $$(cmd-echo$(user-ta-uuid)) $$@' $(q)$(SIGN_ENC) --key $(TA_SIGN_KEY) $(TA_SUBKEY_ARGS) \ $$(crypt-args$(user-ta-uuid)) \ --uuid $(user-ta-uuid) --ta-version $(user-ta-version) \ --in $$< --out $$@ endef $(eval $(call gen-link-t)) additional-link-deps := optee_os-4.3.0/ta/link_shlib.mk000066400000000000000000000037101464416617300164230ustar00rootroot00000000000000ifeq (,$(shlibuuid)) $(error SHLIBUUID not set) endif link-out-dir = $(out-dir) SIGN ?= $(TA_DEV_KIT_DIR)/scripts/sign_encrypt.py TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem all: $(link-out-dir)/$(shlibname).so $(link-out-dir)/$(shlibname).dmp \ $(link-out-dir)/$(shlibname).stripped.so \ $(link-out-dir)/$(shlibuuid).elf \ $(link-out-dir)/$(shlibuuid).ta cleanfiles += $(link-out-dir)/$(shlibname).so cleanfiles += $(link-out-dir)/$(shlibname).dmp cleanfiles += $(link-out-dir)/$(shlibname).stripped.so cleanfiles += $(link-out-dir)/$(shlibuuid).elf cleanfiles += $(link-out-dir)/$(shlibuuid).ta shlink-ldflags = $(LDFLAGS) shlink-ldflags += -shared -z max-page-size=4096 shlink-ldflags += $(call ld-option,-z separate-loadable-segments) ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y) shlink-ldflags += $(call ld-option,-z force-bti) --fatal-warnings endif shlink-ldflags += --as-needed # Do not add dependency on unused shlib shlink-ldadd = $(LDADD) shlink-ldadd += $(addprefix -L,$(libdirs)) shlink-ldadd += --start-group $(addprefix -l,$(libnames)) --end-group ldargs-$(shlibname).so := $(shlink-ldflags) $(objs) $(shlink-ldadd) $(libgcc$(sm)) $(link-out-dir)/$(shlibname).so: $(objs) $(libdeps) @$(cmd-echo-silent) ' LD $@' $(q)$(LD$(sm)) $(ldargs-$(shlibname).so) --soname=$(shlibuuid) -o $@ $(link-out-dir)/$(shlibname).dmp: $(link-out-dir)/$(shlibname).so @$(cmd-echo-silent) ' OBJDUMP $@' $(q)$(OBJDUMP$(sm)) -l -x -d $< > $@ $(link-out-dir)/$(shlibname).stripped.so: $(link-out-dir)/$(shlibname).so @$(cmd-echo-silent) ' OBJCOPY $@' $(q)$(OBJCOPY$(sm)) --strip-unneeded $< $@ $(link-out-dir)/$(shlibuuid).elf: $(link-out-dir)/$(shlibname).so @$(cmd-echo-silent) ' LN $@' $(q)ln -sf $( #include #define PKCS11_TA_UUID { 0xfd02c9da, 0x306c, 0x48c7, \ { 0xa4, 0x9c, 0xbb, 0xd8, 0x27, 0xae, 0x86, 0xee } } /* PKCS11 trusted application version information */ #define PKCS11_TA_VERSION_MAJOR 0 #define PKCS11_TA_VERSION_MINOR 1 #define PKCS11_TA_VERSION_PATCH 0 /* Attribute specific values */ #define PKCS11_CK_UNAVAILABLE_INFORMATION UINT32_C(0xFFFFFFFF) #define PKCS11_UNDEFINED_ID UINT32_C(0xFFFFFFFF) #define PKCS11_FALSE false #define PKCS11_TRUE true /* * Note on PKCS#11 TA commands ABI * * For evolution of the TA API and to not mess with the GPD TEE 4 parameters * constraint, all the PKCS11 TA invocation commands use a subset of available * the GPD TEE invocation parameter types. * * Param#0 is used for the so-called control arguments of the invoked command * and for providing a PKCS#11 compliant status code for the request command. * Param#0 is an in/out memory reference (aka memref[0]). The input buffer * stores serialized arguments for the command. The output buffer store the * 32bit TA return code for the command. As a consequence, param#0 shall * always be an input/output memory reference of at least 32bit, more if * the command expects more input arguments. * * When the TA returns with TEE_SUCCESS result, client shall always get the * 32bit value stored in param#0 output buffer and use the value as TA * return code for the invoked command. * * Param#1 can be used for input data arguments of the invoked command. * It is unused or is an input memory reference, aka memref[1]. * Evolution of the API may use memref[1] for output data as well. * * Param#2 is mostly used for output data arguments of the invoked command * and for output handles generated from invoked commands. * Few commands uses it for a secondary input data buffer argument. * It is unused or is an input/output/in-out memory reference, aka memref[2]. * * Param#3 is currently unused and reserved for evolution of the API. */ enum pkcs11_ta_cmd { /* * PKCS11_CMD_PING Ack TA presence and return version info * * [in] memref[0] = 32bit, unused, must be 0 * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = [ * 32bit version major value, * 32bit version minor value * 32bit version patch value * ] */ PKCS11_CMD_PING = 0, /* * PKCS11_CMD_SLOT_LIST - Get the table of the valid slot IDs * * [in] memref[0] = 32bit, unused, must be 0 * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit array slot_ids[slot counts] * * The TA instance may represent several PKCS#11 slots and * associated tokens. This commadn reports the IDs of embedded tokens. * This command relates the PKCS#11 API function C_GetSlotList(). */ PKCS11_CMD_SLOT_LIST = 1, /* * PKCS11_CMD_SLOT_INFO - Get cryptoki structured slot information * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_slot_info)info * * The TA instance may represent several PKCS#11 slots/tokens. * This command relates the PKCS#11 API function C_GetSlotInfo(). */ PKCS11_CMD_SLOT_INFO = 2, /* * PKCS11_CMD_TOKEN_INFO - Get cryptoki structured token information * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_token_info)info * * The TA instance may represent several PKCS#11 slots/tokens. * This command relates the PKCS#11 API function C_GetTokenInfo(). */ PKCS11_CMD_TOKEN_INFO = 3, /* * PKCS11_CMD_MECHANISM_IDS - Get list of the supported mechanisms * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit array mechanism IDs * * This command relates to the PKCS#11 API function * C_GetMechanismList(). */ PKCS11_CMD_MECHANISM_IDS = 4, /* * PKCS11_CMD_MECHANISM_INFO - Get information on a specific mechanism * * [in] memref[0] = [ * 32bit slot ID, * 32bit mechanism ID (PKCS11_CKM_*) * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_mechanism_info)info * * This command relates to the PKCS#11 API function * C_GetMechanismInfo(). */ PKCS11_CMD_MECHANISM_INFO = 5, /* * PKCS11_CMD_OPEN_SESSION - Open a session * * [in] memref[0] = [ * 32bit slot ID, * 32bit session flags, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit session handle * * This command relates to the PKCS#11 API function C_OpenSession(). */ PKCS11_CMD_OPEN_SESSION = 6, /* * PKCS11_CMD_CLOSE_SESSION - Close an opened session * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_CloseSession(). */ PKCS11_CMD_CLOSE_SESSION = 7, /* * PKCS11_CMD_CLOSE_ALL_SESSIONS - Close all client sessions on token * * [in] memref[0] = 32bit slot ID * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function * C_CloseAllSessions(). */ PKCS11_CMD_CLOSE_ALL_SESSIONS = 8, /* * PKCS11_CMD_SESSION_INFO - Get Cryptoki information on a session * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_session_info)info * * This command relates to the PKCS#11 API function C_GetSessionInfo(). */ PKCS11_CMD_SESSION_INFO = 9, /* * PKCS11_CMD_INIT_TOKEN - Initialize PKCS#11 token * * [in] memref[0] = [ * 32bit slot ID, * 32bit PIN length, * byte array label[32] * byte array PIN[PIN length], * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_InitToken(). */ PKCS11_CMD_INIT_TOKEN = 10, /* * PKCS11_CMD_INIT_PIN - Initialize user PIN * * [in] memref[0] = [ * 32bit session handle, * 32bit PIN byte size, * byte array: PIN data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_InitPIN(). */ PKCS11_CMD_INIT_PIN = 11, /* * PKCS11_CMD_SET_PIN - Change user PIN * * [in] memref[0] = [ * 32bit session handle, * 32bit old PIN byte size, * 32bit new PIN byte size, * byte array: PIN data, * byte array: new PIN data, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_SetPIN(). */ PKCS11_CMD_SET_PIN = 12, /* * PKCS11_CMD_LOGIN - Initialize user PIN * * [in] memref[0] = [ * 32bit session handle, * 32bit user identifier, enum pkcs11_user_type * 32bit PIN byte size, * byte array: PIN data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_Login(). */ PKCS11_CMD_LOGIN = 13, /* * PKCS11_CMD_LOGOUT - Log out from token * * [in] memref[0] = [ * 32bit session handle, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_Logout(). */ PKCS11_CMD_LOGOUT = 14, /* * PKCS11_CMD_CREATE_OBJECT - Create a raw client assembled object in * the session or token * * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_CreateObject(). */ PKCS11_CMD_CREATE_OBJECT = 15, /* * PKCS11_CMD_DESTROY_OBJECT - Destroy an object * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_DestroyObject(). */ PKCS11_CMD_DESTROY_OBJECT = 16, /* * PKCS11_CMD_ENCRYPT_INIT - Initialize encryption processing * PKCS11_CMD_DECRYPT_INIT - Initialize decryption processing * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle of the key, * (struct pkcs11_attribute_head)mechanism + mecha params * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * These commands relate to the PKCS#11 API functions * C_EncryptInit() and C_DecryptInit(). */ PKCS11_CMD_ENCRYPT_INIT = 17, PKCS11_CMD_DECRYPT_INIT = 18, /* * PKCS11_CMD_ENCRYPT_UPDATE - Update encryption processing * PKCS11_CMD_DECRYPT_UPDATE - Update decryption processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = output processed data * * These commands relate to the PKCS#11 API functions * C_EncryptUpdate() and C_DecryptUpdate(). */ PKCS11_CMD_ENCRYPT_UPDATE = 19, PKCS11_CMD_DECRYPT_UPDATE = 20, /* * PKCS11_CMD_ENCRYPT_FINAL - Finalize encryption processing * PKCS11_CMD_DECRYPT_FINAL - Finalize decryption processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = output processed data * * These commands relate to the PKCS#11 API functions * C_EncryptFinal() and C_DecryptFinal(). */ PKCS11_CMD_ENCRYPT_FINAL = 21, PKCS11_CMD_DECRYPT_FINAL = 22, /* * PKCS11_CMD_ENCRYPT_ONESHOT - Update and finalize encryption * processing * PKCS11_CMD_DECRYPT_ONESHOT - Update and finalize decryption * processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = output processed data * * These commands relate to the PKCS#11 API functions C_Encrypt and * C_Decrypt. */ PKCS11_CMD_ENCRYPT_ONESHOT = 23, PKCS11_CMD_DECRYPT_ONESHOT = 24, /* * PKCS11_CMD_SIGN_INIT - Initialize a signature computation * processing * PKCS11_CMD_VERIFY_INIT - Initialize a signature verification * processing * * [in] memref[0] = [ * 32bit session handle, * 32bit key handle, * (struct pkcs11_attribute_head)mechanism + * mechanism params, * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * These commands relate to the PKCS#11 API functions C_SignInit() and * C_VerifyInit(). */ PKCS11_CMD_SIGN_INIT = 25, PKCS11_CMD_VERIFY_INIT = 26, /* * PKCS11_CMD_SIGN_UPDATE - Update a signature computation processing * PKCS11_CMD_VERIFY_UPDATE - Update a signature verification processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * * These commands relate to the PKCS#11 API functions C_SignUpdate() and * C_VerifyUpdate(). */ PKCS11_CMD_SIGN_UPDATE = 27, PKCS11_CMD_VERIFY_UPDATE = 28, /* * PKCS11_CMD_SIGN_FINAL - Finalize a signature computation processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = output signature * * This command relates to the PKCS#11 API functions C_SignFinal(). */ PKCS11_CMD_SIGN_FINAL = 29, /* * PKCS11_CMD_VERIFY_FINAL - Finalize a signature verification * processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[2] = input signature to be processed * * This command relates to the PKCS#11 API functions C_VerifyFinal(). */ PKCS11_CMD_VERIFY_FINAL = 30, /* * PKCS11_CMD_SIGN_ONESHOT - Compute a signature * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = byte array: generated signature * * This command relates to the PKCS#11 API function C_Sign(). */ PKCS11_CMD_SIGN_ONESHOT = 31, /* * PKCS11_CMD_VERIFY_ONESHOT - Compute and compare a signature * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [in] memref[2] = input signature to be processed * * This command relates to the PKCS#11 API function C_Verify(). */ PKCS11_CMD_VERIFY_ONESHOT = 32, /* * PKCS11_CMD_GENERATE_KEY - Generate a symmetric key or domain * parameters * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_GenerateKey(). */ PKCS11_CMD_GENERATE_KEY = 33, /* * PKCS11_CMD_FIND_OBJECTS_INIT - Initialize an object search * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_FindOjectsInit(). */ PKCS11_CMD_FIND_OBJECTS_INIT = 34, /* * PKCS11_CMD_FIND_OBJECTS - Get handles of matching objects * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit array object_handle_array[N] * * This command relates to the PKCS#11 API function C_FindOjects(). * The size of object_handle_array depends on the size of the output * buffer provided by the client. */ PKCS11_CMD_FIND_OBJECTS = 35, /* * PKCS11_CMD_FIND_OBJECTS_FINAL - Finalize current objects search * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_FindOjectsFinal(). */ PKCS11_CMD_FIND_OBJECTS_FINAL = 36, /* * PKCS11_CMD_GET_OBJECT_SIZE - Get byte size used by object in the TEE * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object_byte_size * * This command relates to the PKCS#11 API function C_GetObjectSize(). */ PKCS11_CMD_GET_OBJECT_SIZE = 37, /* * PKCS11_CMD_GET_ATTRIBUTE_VALUE - Get the value of object attribute(s) * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = (struct pkcs11_object_head)attribs + attributes * data * * This command relates to the PKCS#11 API function C_GetAttributeValue. * Caller provides an attribute template as 3rd argument in memref[0] * (referred here as attribs + attributes data). Upon successful * completion, the TA returns the provided template filled with expected * data through output argument memref[2] (referred here again as * attribs + attributes data). */ PKCS11_CMD_GET_ATTRIBUTE_VALUE = 38, /* * PKCS11_CMD_SET_ATTRIBUTE_VALUE - Set the value of object attribute(s) * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_SetAttributeValue. * Caller provides an attribute template as 3rd argument in memref[0] * (referred here as attribs + attributes data). */ PKCS11_CMD_SET_ATTRIBUTE_VALUE = 39, /* * PKCS11_CMD_COPY_OBJECT - Copies an object, creating a new object for * the copy. * * [in] memref[0] = [ * 32bit session handle, * 32bit object handle, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_CopyObject(). * Caller provides an attribute template as 3rd argument in memref[0] * (referred here as attribs + attributes data). */ PKCS11_CMD_COPY_OBJECT = 40, /* * PKCS11_CMD_SEED_RANDOM - Seed random data generator * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = byte array: seed material to feed into the RNG * * This command relates to the PKCS#11 API function C_SeedRandom(). */ PKCS11_CMD_SEED_RANDOM = 41, /* * PKCS11_CMD_GENERATE_RANDOM - Generate random data * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = byte array: generated random * * This command relates to the PKCS#11 API function C_GenerateRandom(). */ PKCS11_CMD_GENERATE_RANDOM = 42, /* * PKCS11_CMD_DERIVE_KEY - Derive a key from a parent key. * * [in] memref[0] = [ * 32bit session handle, * 32bit parent key handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_DeriveKey(). */ PKCS11_CMD_DERIVE_KEY = 43, /* * PKCS11_CMD_RELEASE_ACTIVE_PROCESSING - Release active processing * * [in] memref[0] = [ * 32bit session handle, * 32bit enum pkcs11_ta_cmd * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command is used to release active processing in case of * Cryptoki API invocation error is detected in user space processing. * Function derived from pkcs11_ta_cmd is used to verify that active * processing matches. */ PKCS11_CMD_RELEASE_ACTIVE_PROCESSING = 44, /* * PKCS11_CMD_DIGEST_INIT - Initialize a digest computation processing * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_attribute_head)mechanism + mecha params * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_DigestInit(). */ PKCS11_CMD_DIGEST_INIT = 45, /* * PKCS11_CMD_DIGEST_KEY - Update digest with a key * * [in] memref[0] = [ * 32bit session handle, * 32bit key handle * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * * This command relates to the PKCS#11 API function C_DigestKey(). */ PKCS11_CMD_DIGEST_KEY = 46, /* * PKCS11_CMD_DIGEST_UPDATE - Update digest with data * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * * This command relates to the PKCS#11 API function C_DigestUpdate(). */ PKCS11_CMD_DIGEST_UPDATE = 47, /* * PKCS11_CMD_DIGEST_FINAL - Finalize a digest computation processing * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = output digest * * This command relates to the PKCS#11 API function C_DigestFinal(). */ PKCS11_CMD_DIGEST_FINAL = 48, /* * PKCS11_CMD_DIGEST_ONESHOT - Compute a digest * * [in] memref[0] = 32bit session handle * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = input data to be processed * [out] memref[2] = byte array: generated digest * * This command relates to the PKCS#11 API function C_Digest(). */ PKCS11_CMD_DIGEST_ONESHOT = 49, /* * PKCS11_CMD_GENERATE_KEY_PAIR - Generate an asymmetric key pair * * [in] memref[0] = [ * 32bit session handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)public key attribs + * attributes data, * (struct pkcs11_object_head)private key attribs + * attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = [ * 32bit public key object handle, * 32bit private key object handle * ] * * This command relates to the PKCS#11 API function * C_GenerateKeyPair(). */ PKCS11_CMD_GENERATE_KEY_PAIR = 50, /* * PKCS11_CMD_WRAP_KEY - Wraps a private or secret key. * * [in] memref[0] = [ * 32bit session handle, * 32bit wrapping key handle, * 32bit key handle, * (struct pkcs11_attribute_head)mechanism + mecha params * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [out] memref[2] = wrapped key * * This command relates to the PKCS#11 API function C_WrapKey(). */ PKCS11_CMD_WRAP_KEY = 51, /* * PKCS11_CMD_UNWRAP_KEY - Unwraps a wrapped key, creating a new * private or secret key object. * * [in] memref[0] = [ * 32bit session handle, * 32bit unwrapping key handle, * (struct pkcs11_attribute_head)mechanism + mecha params, * (struct pkcs11_object_head)attribs + attributes data * ] * [out] memref[0] = 32bit return code, enum pkcs11_rc * [in] memref[1] = wrapped key * [out] memref[2] = 32bit object handle * * This command relates to the PKCS#11 API function C_UnwrapKey(). */ PKCS11_CMD_UNWRAP_KEY = 52, }; /* * Command return codes * PKCS11_ relates CryptoKi client API CKR_ */ enum pkcs11_rc { PKCS11_CKR_OK = 0, PKCS11_CKR_CANCEL = 0x0001, PKCS11_CKR_SLOT_ID_INVALID = 0x0003, PKCS11_CKR_GENERAL_ERROR = 0x0005, PKCS11_CKR_FUNCTION_FAILED = 0x0006, PKCS11_CKR_ARGUMENTS_BAD = 0x0007, PKCS11_CKR_ATTRIBUTE_READ_ONLY = 0x0010, PKCS11_CKR_ATTRIBUTE_SENSITIVE = 0x0011, PKCS11_CKR_ATTRIBUTE_TYPE_INVALID = 0x0012, PKCS11_CKR_ATTRIBUTE_VALUE_INVALID = 0x0013, PKCS11_CKR_ACTION_PROHIBITED = 0x001b, PKCS11_CKR_DATA_INVALID = 0x0020, PKCS11_CKR_DATA_LEN_RANGE = 0x0021, PKCS11_CKR_DEVICE_ERROR = 0x0030, PKCS11_CKR_DEVICE_MEMORY = 0x0031, PKCS11_CKR_DEVICE_REMOVED = 0x0032, PKCS11_CKR_ENCRYPTED_DATA_INVALID = 0x0040, PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE = 0x0041, PKCS11_CKR_KEY_HANDLE_INVALID = 0x0060, PKCS11_CKR_KEY_SIZE_RANGE = 0x0062, PKCS11_CKR_KEY_TYPE_INCONSISTENT = 0x0063, PKCS11_CKR_KEY_INDIGESTIBLE = 0x0067, PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED = 0x0068, PKCS11_CKR_KEY_NOT_WRAPPABLE = 0x0069, PKCS11_CKR_KEY_UNEXTRACTABLE = 0x006a, PKCS11_CKR_MECHANISM_INVALID = 0x0070, PKCS11_CKR_MECHANISM_PARAM_INVALID = 0x0071, PKCS11_CKR_OBJECT_HANDLE_INVALID = 0x0082, PKCS11_CKR_OPERATION_ACTIVE = 0x0090, PKCS11_CKR_OPERATION_NOT_INITIALIZED = 0x0091, PKCS11_CKR_PIN_INCORRECT = 0x00a0, PKCS11_CKR_PIN_INVALID = 0x00a1, PKCS11_CKR_PIN_LEN_RANGE = 0x00a2, PKCS11_CKR_PIN_EXPIRED = 0x00a3, PKCS11_CKR_PIN_LOCKED = 0x00a4, PKCS11_CKR_SESSION_CLOSED = 0x00b0, PKCS11_CKR_SESSION_COUNT = 0x00b1, PKCS11_CKR_SESSION_HANDLE_INVALID = 0x00b3, PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x00b4, PKCS11_CKR_SESSION_READ_ONLY = 0x00b5, PKCS11_CKR_SESSION_EXISTS = 0x00b6, PKCS11_CKR_SESSION_READ_ONLY_EXISTS = 0x00b7, PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS = 0x00b8, PKCS11_CKR_SIGNATURE_INVALID = 0x00c0, PKCS11_CKR_SIGNATURE_LEN_RANGE = 0x00c1, PKCS11_CKR_TEMPLATE_INCOMPLETE = 0x00d0, PKCS11_CKR_TEMPLATE_INCONSISTENT = 0x00d1, PKCS11_CKR_TOKEN_NOT_PRESENT = 0x00e0, PKCS11_CKR_TOKEN_NOT_RECOGNIZED = 0x00e1, PKCS11_CKR_TOKEN_WRITE_PROTECTED = 0x00e2, PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x00f0, PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x00f1, PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x00f2, PKCS11_CKR_USER_ALREADY_LOGGED_IN = 0x0100, PKCS11_CKR_USER_NOT_LOGGED_IN = 0x0101, PKCS11_CKR_USER_PIN_NOT_INITIALIZED = 0x0102, PKCS11_CKR_USER_TYPE_INVALID = 0x0103, PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x0104, PKCS11_CKR_USER_TOO_MANY_TYPES = 0x0105, PKCS11_CKR_WRAPPED_KEY_INVALID = 0x0110, PKCS11_CKR_WRAPPED_KEY_LEN_RANGE = 0x0112, PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID = 0x0113, PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE = 0x0114, PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x0115, PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED = 0x0120, PKCS11_CKR_RANDOM_NO_RNG = 0x0121, PKCS11_CKR_DOMAIN_PARAMS_INVALID = 0x0130, PKCS11_CKR_CURVE_NOT_SUPPORTED = 0x0140, PKCS11_CKR_BUFFER_TOO_SMALL = 0x0150, PKCS11_CKR_SAVED_STATE_INVALID = 0x0160, PKCS11_CKR_INFORMATION_SENSITIVE = 0x0170, PKCS11_CKR_STATE_UNSAVEABLE = 0x0180, PKCS11_CKR_PIN_TOO_WEAK = 0x01b8, PKCS11_CKR_PUBLIC_KEY_INVALID = 0x01b9, PKCS11_CKR_FUNCTION_REJECTED = 0x0200, /* Vendor specific IDs not returned to client */ PKCS11_RV_NOT_FOUND = 0x80000000, PKCS11_RV_NOT_IMPLEMENTED = 0x80000001, }; /* * Arguments for PKCS11_CMD_SLOT_INFO */ #define PKCS11_SLOT_DESC_SIZE 64 #define PKCS11_SLOT_MANUFACTURER_SIZE 32 #define PKCS11_SLOT_VERSION_SIZE 2 struct pkcs11_slot_info { uint8_t slot_description[PKCS11_SLOT_DESC_SIZE]; uint8_t manufacturer_id[PKCS11_SLOT_MANUFACTURER_SIZE]; uint32_t flags; uint8_t hardware_version[PKCS11_SLOT_VERSION_SIZE]; uint8_t firmware_version[PKCS11_SLOT_VERSION_SIZE]; }; /* * Values for pkcs11_slot_info::flags. * PKCS11_CKFS_ reflects CryptoKi client API slot flags CKF_. */ #define PKCS11_CKFS_TOKEN_PRESENT (1U << 0) #define PKCS11_CKFS_REMOVABLE_DEVICE (1U << 1) #define PKCS11_CKFS_HW_SLOT (1U << 2) /* * Arguments for PKCS11_CMD_TOKEN_INFO */ #define PKCS11_TOKEN_LABEL_SIZE 32 #define PKCS11_TOKEN_MANUFACTURER_SIZE 32 #define PKCS11_TOKEN_MODEL_SIZE 16 #define PKCS11_TOKEN_SERIALNUM_SIZE 16 struct pkcs11_token_info { uint8_t label[PKCS11_TOKEN_LABEL_SIZE]; uint8_t manufacturer_id[PKCS11_TOKEN_MANUFACTURER_SIZE]; uint8_t model[PKCS11_TOKEN_MODEL_SIZE]; uint8_t serial_number[PKCS11_TOKEN_SERIALNUM_SIZE]; uint32_t flags; uint32_t max_session_count; uint32_t session_count; uint32_t max_rw_session_count; uint32_t rw_session_count; uint32_t max_pin_len; uint32_t min_pin_len; uint32_t total_public_memory; uint32_t free_public_memory; uint32_t total_private_memory; uint32_t free_private_memory; uint8_t hardware_version[2]; uint8_t firmware_version[2]; uint8_t utc_time[16]; }; /* * Values for pkcs11_token_info::flags. * PKCS11_CKFT_ reflects CryptoKi client API token flags CKF_. */ #define PKCS11_CKFT_RNG (1U << 0) #define PKCS11_CKFT_WRITE_PROTECTED (1U << 1) #define PKCS11_CKFT_LOGIN_REQUIRED (1U << 2) #define PKCS11_CKFT_USER_PIN_INITIALIZED (1U << 3) #define PKCS11_CKFT_RESTORE_KEY_NOT_NEEDED (1U << 5) #define PKCS11_CKFT_CLOCK_ON_TOKEN (1U << 6) #define PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH (1U << 8) #define PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS (1U << 9) #define PKCS11_CKFT_TOKEN_INITIALIZED (1U << 10) #define PKCS11_CKFT_SECONDARY_AUTHENTICATION (1U << 11) #define PKCS11_CKFT_USER_PIN_COUNT_LOW (1U << 16) #define PKCS11_CKFT_USER_PIN_FINAL_TRY (1U << 17) #define PKCS11_CKFT_USER_PIN_LOCKED (1U << 18) #define PKCS11_CKFT_USER_PIN_TO_BE_CHANGED (1U << 19) #define PKCS11_CKFT_SO_PIN_COUNT_LOW (1U << 20) #define PKCS11_CKFT_SO_PIN_FINAL_TRY (1U << 21) #define PKCS11_CKFT_SO_PIN_LOCKED (1U << 22) #define PKCS11_CKFT_SO_PIN_TO_BE_CHANGED (1U << 23) #define PKCS11_CKFT_ERROR_STATE (1U << 24) /* Values for user identity */ enum pkcs11_user_type { PKCS11_CKU_SO = 0x000, PKCS11_CKU_USER = 0x001, PKCS11_CKU_CONTEXT_SPECIFIC = 0x002, }; /* * TEE Identity based authentication for tokens * * When configuration CFG_PKCS11_TA_AUTH_TEE_IDENTITY is enabled TEE Identity * based authentication scheme is enabled. * * Feature enablement per token basis is controlled by token flag: * pkcs11_token_info->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH * * When calling C_InitToken() mode is determined based on SO PIN value. * - If the PIN is empty (or NULL_PTR) then active client TEE Identity will be * used as SO TEE Identity * - If the PIN is given then normal PIN behavior is used * * Once TEE Identity based authentication is activated following operational * changes happen: * - PIN failure counters are disabled to prevent token authentication lockups * - When C_Login() or so is performed actual PIN value is ignored and active * client TEE Identity will be used * * After a successful call to C_InitToken(), one can switch authentication * mode as user credentials have been cleared. After user credentials has been * set authentication mode switching is protected. * * To switch the authentication mode from PIN to TEE Identity: * - Make sure active TEE Identity is set for the TA connection * - Login as SO so that PIN change affects SO * - Call C_SetPIN() with empty PIN to capture current TEE Identity as SO * credential * - Optional: Successive call to C_SetPIN() can be used for change to other * TEE Identity vs. current TA connection * * To switch the authentication mode from TEE Identity to PIN: * - Make sure SO's TEE Identity is set for the TA connection * - Login as SO so that PIN change affects SO * - Call C_SetPIN() with any PIN that does not match TEE Identity PIN syntax * - Optional: Successive call to C_SetPIN() can be used to change SO * credential to any valid PIN if there was collision with TEE Identity PIN * syntax * * Different types of TEE Identity authentication methods can be configured: * - Configured with C_InitToken(), C_InitPIN() or by C_SetPIN() * - PIN value follows below PIN syntax * * TEE Identity based authenticate PIN syntax: * - PIN value: NULL_PTR or empty * - Use active client TEE Identity * - PIN value: public * - TEE public login * - PIN value: user: * - TEE user login with client UUID matching user credentials * - PIN value: group: * - TEE group login with client UUID matching group credentials */ /* Keywords for protected authenticated path PIN parser */ #define PKCS11_AUTH_TEE_IDENTITY_PUBLIC "public" #define PKCS11_AUTH_TEE_IDENTITY_USER "user:" #define PKCS11_AUTH_TEE_IDENTITY_GROUP "group:" /* * Values for 32bit session flags argument to PKCS11_CMD_OPEN_SESSION * and pkcs11_session_info::flags. * PKCS11_CKFSS_ reflects CryptoKi client API session flags CKF_. */ #define PKCS11_CKFSS_RW_SESSION (1U << 1) #define PKCS11_CKFSS_SERIAL_SESSION (1U << 2) /* * Arguments for PKCS11_CMD_SESSION_INFO */ struct pkcs11_session_info { uint32_t slot_id; uint32_t state; uint32_t flags; uint32_t device_error; }; /* Valid values for pkcs11_session_info::state */ enum pkcs11_session_state { PKCS11_CKS_RO_PUBLIC_SESSION = 0, PKCS11_CKS_RO_USER_FUNCTIONS = 1, PKCS11_CKS_RW_PUBLIC_SESSION = 2, PKCS11_CKS_RW_USER_FUNCTIONS = 3, PKCS11_CKS_RW_SO_FUNCTIONS = 4, }; /* * Arguments for PKCS11_CMD_MECHANISM_INFO */ struct pkcs11_mechanism_info { uint32_t min_key_size; uint32_t max_key_size; uint32_t flags; }; /* * Values for pkcs11_mechanism_info::flags. * PKCS11_CKFM_ reflects CryptoKi client API mechanism flags CKF_. */ #define PKCS11_CKFM_HW (1U << 0) #define PKCS11_CKFM_ENCRYPT (1U << 8) #define PKCS11_CKFM_DECRYPT (1U << 9) #define PKCS11_CKFM_DIGEST (1U << 10) #define PKCS11_CKFM_SIGN (1U << 11) #define PKCS11_CKFM_SIGN_RECOVER (1U << 12) #define PKCS11_CKFM_VERIFY (1U << 13) #define PKCS11_CKFM_VERIFY_RECOVER (1U << 14) #define PKCS11_CKFM_GENERATE (1U << 15) #define PKCS11_CKFM_GENERATE_KEY_PAIR (1U << 16) #define PKCS11_CKFM_WRAP (1U << 17) #define PKCS11_CKFM_UNWRAP (1U << 18) #define PKCS11_CKFM_DERIVE (1U << 19) #define PKCS11_CKFM_EC_F_P (1U << 20) #define PKCS11_CKFM_EC_F_2M (1U << 21) #define PKCS11_CKFM_EC_ECPARAMETERS (1U << 22) #define PKCS11_CKFM_EC_NAMEDCURVE (1U << 23) #define PKCS11_CKFM_EC_UNCOMPRESS (1U << 24) #define PKCS11_CKFM_EC_COMPRESS (1U << 25) /* * pkcs11_object_head - Header of object whose data are serialized in memory * * An object is made of several attributes. Attributes are stored one next to * the other with byte alignment as a serialized byte array. The byte array * of serialized attributes is prepended with the size of the attrs[] array * in bytes and the number of attributes in the array, yielding the struct * pkcs11_object_head. * * @attrs_size - byte size of whole byte array attrs[] * @attrs_count - number of attribute items stored in attrs[] * @attrs - then starts the attributes data */ struct pkcs11_object_head { uint32_t attrs_size; uint32_t attrs_count; uint8_t attrs[]; }; /* * Attribute reference in the TA ABI. Each attribute starts with a header * structure followed by the attribute value. The attribute byte size is * defined in the attribute header. * * @id - the 32bit identifier of the attribute, see PKCS11_CKA_ * @size - the 32bit value attribute byte size * @data - then starts the attribute value */ struct pkcs11_attribute_head { uint32_t id; uint32_t size; uint8_t data[]; }; #define PKCS11_CKA_VENDOR_DEFINED 0x80000000UL /** * The PKCS11_CKF_ARRAY_ATTRIBUTE flag identifies an attribute which * consists of an array of values. */ #define PKCS11_CKF_ARRAY_ATTRIBUTE 0x40000000UL /* * OP-TEE's vendor specific PKCS#11 attribute allocation * * bit 31 - PKCS11_CKA_VENDOR_DEFINED * bit 30 - PKCS11_CKF_ARRAY_ATTRIBUTE - works like in normal attributes * bit 24-29 - reserved in case PKCS#11 standard starts to use them * bit 16-23 - allocated for OP-TEE attribute flags * bit 0-15 - allocated for attribute identifier */ /* OP-TEE attribute flags */ /** * Flags mask for checking if OP-TEE attribute flags are set. */ #define PKCS11_CKA_OPTEE_FLAGS_MASK (PKCS11_CKA_VENDOR_DEFINED | \ 0x00FF0000UL) /** * PKCS11_CKA_OPTEE_FLAGS_HIDDEN defines attribute that will not be exported * from PKCS11 TA to its client. From client application point of view the * attribute does not exist. */ #define PKCS11_CKA_OPTEE_FLAGS_HIDDEN (PKCS11_CKA_VENDOR_DEFINED | \ 0x00010000UL) /* * Attribute identification IDs as of v2.40 excluding deprecated IDs. * Valid values for struct pkcs11_attribute_head::id * PKCS11_CKA_ reflects CryptoKi client API attribute IDs CKA_. */ enum pkcs11_attr_id { PKCS11_CKA_CLASS = 0x0000, PKCS11_CKA_TOKEN = 0x0001, PKCS11_CKA_PRIVATE = 0x0002, PKCS11_CKA_LABEL = 0x0003, PKCS11_CKA_APPLICATION = 0x0010, PKCS11_CKA_VALUE = 0x0011, PKCS11_CKA_OBJECT_ID = 0x0012, PKCS11_CKA_CERTIFICATE_TYPE = 0x0080, PKCS11_CKA_ISSUER = 0x0081, PKCS11_CKA_SERIAL_NUMBER = 0x0082, PKCS11_CKA_AC_ISSUER = 0x0083, PKCS11_CKA_OWNER = 0x0084, PKCS11_CKA_ATTR_TYPES = 0x0085, PKCS11_CKA_TRUSTED = 0x0086, PKCS11_CKA_CERTIFICATE_CATEGORY = 0x0087, PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x0088, PKCS11_CKA_URL = 0x0089, PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x008a, PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x008b, PKCS11_CKA_NAME_HASH_ALGORITHM = 0x008c, PKCS11_CKA_CHECK_VALUE = 0x0090, PKCS11_CKA_KEY_TYPE = 0x0100, PKCS11_CKA_SUBJECT = 0x0101, PKCS11_CKA_ID = 0x0102, PKCS11_CKA_SENSITIVE = 0x0103, PKCS11_CKA_ENCRYPT = 0x0104, PKCS11_CKA_DECRYPT = 0x0105, PKCS11_CKA_WRAP = 0x0106, PKCS11_CKA_UNWRAP = 0x0107, PKCS11_CKA_SIGN = 0x0108, PKCS11_CKA_SIGN_RECOVER = 0x0109, PKCS11_CKA_VERIFY = 0x010a, PKCS11_CKA_VERIFY_RECOVER = 0x010b, PKCS11_CKA_DERIVE = 0x010c, PKCS11_CKA_START_DATE = 0x0110, PKCS11_CKA_END_DATE = 0x0111, PKCS11_CKA_MODULUS = 0x0120, PKCS11_CKA_MODULUS_BITS = 0x0121, PKCS11_CKA_PUBLIC_EXPONENT = 0x0122, PKCS11_CKA_PRIVATE_EXPONENT = 0x0123, PKCS11_CKA_PRIME_1 = 0x0124, PKCS11_CKA_PRIME_2 = 0x0125, PKCS11_CKA_EXPONENT_1 = 0x0126, PKCS11_CKA_EXPONENT_2 = 0x0127, PKCS11_CKA_COEFFICIENT = 0x0128, PKCS11_CKA_PUBLIC_KEY_INFO = 0x0129, PKCS11_CKA_PRIME = 0x0130, PKCS11_CKA_SUBPRIME = 0x0131, PKCS11_CKA_BASE = 0x0132, PKCS11_CKA_PRIME_BITS = 0x0133, PKCS11_CKA_SUBPRIME_BITS = 0x0134, PKCS11_CKA_VALUE_BITS = 0x0160, PKCS11_CKA_VALUE_LEN = 0x0161, PKCS11_CKA_EXTRACTABLE = 0x0162, PKCS11_CKA_LOCAL = 0x0163, PKCS11_CKA_NEVER_EXTRACTABLE = 0x0164, PKCS11_CKA_ALWAYS_SENSITIVE = 0x0165, PKCS11_CKA_KEY_GEN_MECHANISM = 0x0166, PKCS11_CKA_MODIFIABLE = 0x0170, PKCS11_CKA_COPYABLE = 0x0171, PKCS11_CKA_DESTROYABLE = 0x0172, PKCS11_CKA_EC_PARAMS = 0x0180, PKCS11_CKA_EC_POINT = 0x0181, PKCS11_CKA_ALWAYS_AUTHENTICATE = 0x0202, PKCS11_CKA_WRAP_WITH_TRUSTED = 0x0210, PKCS11_CKA_WRAP_TEMPLATE = PKCS11_CKF_ARRAY_ATTRIBUTE | 0x0211, PKCS11_CKA_UNWRAP_TEMPLATE = PKCS11_CKF_ARRAY_ATTRIBUTE | 0x0212, PKCS11_CKA_DERIVE_TEMPLATE = PKCS11_CKF_ARRAY_ATTRIBUTE | 0x0213, PKCS11_CKA_OTP_FORMAT = 0x0220, PKCS11_CKA_OTP_LENGTH = 0x0221, PKCS11_CKA_OTP_TIME_INTERVAL = 0x0222, PKCS11_CKA_OTP_USER_FRIENDLY_MODE = 0x0223, PKCS11_CKA_OTP_CHALLENGE_REQUIREMENT = 0x0224, PKCS11_CKA_OTP_TIME_REQUIREMENT = 0x0225, PKCS11_CKA_OTP_COUNTER_REQUIREMENT = 0x0226, PKCS11_CKA_OTP_PIN_REQUIREMENT = 0x0227, PKCS11_CKA_OTP_COUNTER = 0x022e, PKCS11_CKA_OTP_TIME = 0x022f, PKCS11_CKA_OTP_USER_IDENTIFIER = 0x022a, PKCS11_CKA_OTP_SERVICE_IDENTIFIER = 0x022b, PKCS11_CKA_OTP_SERVICE_LOGO = 0x022c, PKCS11_CKA_OTP_SERVICE_LOGO_TYPE = 0x022d, PKCS11_CKA_GOSTR3410_PARAMS = 0x0250, PKCS11_CKA_GOSTR3411_PARAMS = 0x0251, PKCS11_CKA_GOST28147_PARAMS = 0x0252, PKCS11_CKA_HW_FEATURE_TYPE = 0x0300, PKCS11_CKA_RESET_ON_INIT = 0x0301, PKCS11_CKA_HAS_RESET = 0x0302, PKCS11_CKA_PIXEL_X = 0x0400, PKCS11_CKA_PIXEL_Y = 0x0401, PKCS11_CKA_RESOLUTION = 0x0402, PKCS11_CKA_CHAR_ROWS = 0x0403, PKCS11_CKA_CHAR_COLUMNS = 0x0404, PKCS11_CKA_COLOR = 0x0405, PKCS11_CKA_BITS_PER_PIXEL = 0x0406, PKCS11_CKA_CHAR_SETS = 0x0480, PKCS11_CKA_ENCODING_METHODS = 0x0481, PKCS11_CKA_MIME_TYPES = 0x0482, PKCS11_CKA_MECHANISM_TYPE = 0x0500, PKCS11_CKA_REQUIRED_CMS_ATTRIBUTES = 0x0501, PKCS11_CKA_DEFAULT_CMS_ATTRIBUTES = 0x0502, PKCS11_CKA_SUPPORTED_CMS_ATTRIBUTES = 0x0503, PKCS11_CKA_ALLOWED_MECHANISMS = PKCS11_CKF_ARRAY_ATTRIBUTE | 0x0600, /* Vendor specific attributes */ /** * TEE Internal API requires to have EC public key information * available for private key operations. As EC private key object * should not include CKA_EC_POINT include hidden one so that it does * not need to be calculated on each operation. */ PKCS11_CKA_OPTEE_HIDDEN_EC_POINT = PKCS11_CKA_VENDOR_DEFINED | PKCS11_CKA_OPTEE_FLAGS_HIDDEN | 0x0000, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKA_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_CLASS * PKCS11_CKO_ reflects CryptoKi client API object class IDs CKO_. */ enum pkcs11_class_id { PKCS11_CKO_DATA = 0x000, PKCS11_CKO_CERTIFICATE = 0x001, PKCS11_CKO_PUBLIC_KEY = 0x002, PKCS11_CKO_PRIVATE_KEY = 0x003, PKCS11_CKO_SECRET_KEY = 0x004, PKCS11_CKO_HW_FEATURE = 0x005, PKCS11_CKO_DOMAIN_PARAMETERS = 0x006, PKCS11_CKO_MECHANISM = 0x007, PKCS11_CKO_OTP_KEY = 0x008, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKO_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_KEY_TYPE * PKCS11_CKK_ reflects CryptoKi client API key type IDs CKK_. * Note that this is only a subset of the PKCS#11 specification. */ enum pkcs11_key_type { PKCS11_CKK_RSA = 0x000, PKCS11_CKK_DSA = 0x001, PKCS11_CKK_DH = 0x002, PKCS11_CKK_EC = 0x003, PKCS11_CKK_EDDSA = 0x004, PKCS11_CKK_GENERIC_SECRET = 0x010, PKCS11_CKK_AES = 0x01f, PKCS11_CKK_MD5_HMAC = 0x027, PKCS11_CKK_SHA_1_HMAC = 0x028, PKCS11_CKK_SHA256_HMAC = 0x02b, PKCS11_CKK_SHA384_HMAC = 0x02c, PKCS11_CKK_SHA512_HMAC = 0x02d, PKCS11_CKK_SHA224_HMAC = 0x02e, PKCS11_CKK_EC_EDWARDS = 0x040, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKK_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_CERTIFICATE_TYPE */ enum pkcs11_certificate_type { PKCS11_CKC_X_509 = 0x00000000UL, PKCS11_CKC_X_509_ATTR_CERT = 0x00000001UL, PKCS11_CKC_WTLS = 0x00000002UL, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKC_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for attribute PKCS11_CKA_CERTIFICATE_CATEGORY */ enum pkcs11_certificate_category { PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0UL, PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER = 1UL, PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY = 2UL, PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 3UL, }; /* * Valid values for mechanism IDs * PKCS11_CKM_ reflects CryptoKi client API mechanism IDs CKM_. * Note that this will be extended as needed. */ enum pkcs11_mechanism_id { PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000, PKCS11_CKM_RSA_PKCS = 0x00001, PKCS11_CKM_MD5_RSA_PKCS = 0x00005, PKCS11_CKM_SHA1_RSA_PKCS = 0x00006, PKCS11_CKM_RSA_PKCS_OAEP = 0x00009, PKCS11_CKM_RSA_PKCS_PSS = 0x0000d, PKCS11_CKM_SHA1_RSA_PKCS_PSS = 0x0000e, PKCS11_CKM_SHA256_RSA_PKCS = 0x00040, PKCS11_CKM_SHA384_RSA_PKCS = 0x00041, PKCS11_CKM_SHA512_RSA_PKCS = 0x00042, PKCS11_CKM_SHA256_RSA_PKCS_PSS = 0x00043, PKCS11_CKM_SHA384_RSA_PKCS_PSS = 0x00044, PKCS11_CKM_SHA512_RSA_PKCS_PSS = 0x00045, PKCS11_CKM_SHA224_RSA_PKCS = 0x00046, PKCS11_CKM_SHA224_RSA_PKCS_PSS = 0x00047, PKCS11_CKM_MD5 = 0x00210, PKCS11_CKM_MD5_HMAC = 0x00211, PKCS11_CKM_MD5_HMAC_GENERAL = 0x00212, PKCS11_CKM_SHA_1 = 0x00220, PKCS11_CKM_SHA_1_HMAC = 0x00221, PKCS11_CKM_SHA_1_HMAC_GENERAL = 0x00222, PKCS11_CKM_SHA256 = 0x00250, PKCS11_CKM_SHA256_HMAC = 0x00251, PKCS11_CKM_SHA256_HMAC_GENERAL = 0x00252, PKCS11_CKM_SHA224 = 0x00255, PKCS11_CKM_SHA224_HMAC = 0x00256, PKCS11_CKM_SHA224_HMAC_GENERAL = 0x00257, PKCS11_CKM_SHA384 = 0x00260, PKCS11_CKM_SHA384_HMAC = 0x00261, PKCS11_CKM_SHA384_HMAC_GENERAL = 0x00262, PKCS11_CKM_SHA512 = 0x00270, PKCS11_CKM_SHA512_HMAC = 0x00271, PKCS11_CKM_SHA512_HMAC_GENERAL = 0x00272, PKCS11_CKM_GENERIC_SECRET_KEY_GEN = 0x00350, PKCS11_CKM_EC_KEY_PAIR_GEN = 0x01040, PKCS11_CKM_ECDSA = 0x01041, PKCS11_CKM_ECDSA_SHA1 = 0x01042, PKCS11_CKM_ECDSA_SHA224 = 0x01043, PKCS11_CKM_ECDSA_SHA256 = 0x01044, PKCS11_CKM_ECDSA_SHA384 = 0x01045, PKCS11_CKM_ECDSA_SHA512 = 0x01046, PKCS11_CKM_ECDH1_DERIVE = 0x01050, PKCS11_CKM_RSA_AES_KEY_WRAP = 0x01054, PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN = 0x01055, PKCS11_CKM_EDDSA = 0x01057, PKCS11_CKM_AES_KEY_GEN = 0x01080, PKCS11_CKM_AES_ECB = 0x01081, PKCS11_CKM_AES_CBC = 0x01082, PKCS11_CKM_AES_CBC_PAD = 0x01085, PKCS11_CKM_AES_CTR = 0x01086, PKCS11_CKM_AES_GCM = 0x01087, PKCS11_CKM_AES_CTS = 0x01089, PKCS11_CKM_AES_CMAC = 0x0108a, PKCS11_CKM_AES_CMAC_GENERAL = 0x0108b, PKCS11_CKM_AES_ECB_ENCRYPT_DATA = 0x01104, PKCS11_CKM_AES_CBC_ENCRYPT_DATA = 0x01105, /* * Vendor extensions below. * PKCS11 added IDs for operation not related to a CK mechanism ID */ PKCS11_PROCESSING_IMPORT = 0x80000000, PKCS11_CKM_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * PKCS11_CKD_ reflects CryptoKi client API key diff function IDs CKD_. */ enum pkcs11_keydiff_id { PKCS11_CKD_NULL = 0x0001, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKD_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values MG function identifiers * PKCS11_CKG_ reflects CryptoKi client API MG function IDs CKG_. */ enum pkcs11_mgf_id { PKCS11_CKG_MGF1_SHA1 = 0x0001, PKCS11_CKG_MGF1_SHA224 = 0x0005, PKCS11_CKG_MGF1_SHA256 = 0x0002, PKCS11_CKG_MGF1_SHA384 = 0x0003, PKCS11_CKG_MGF1_SHA512 = 0x0004, /* Vendor extension: reserved for undefined ID (~0U) */ PKCS11_CKG_UNDEFINED_ID = PKCS11_UNDEFINED_ID, }; /* * Valid values for RSA PKCS/OAEP source type identifier * PKCS11_CKZ_ reflects CryptoKi client API source type IDs CKZ_. */ #define PKCS11_CKZ_DATA_SPECIFIED 0x0001 #endif /*PKCS11_TA_H*/ optee_os-4.3.0/ta/pkcs11/scripts/000077500000000000000000000000001464416617300165445ustar00rootroot00000000000000optee_os-4.3.0/ta/pkcs11/scripts/dump_ec_curve_params.sh000077500000000000000000000015421464416617300232700ustar00rootroot00000000000000#!/bin/bash # SPDX-License-Identifier: BSD-2-Clause EC_CURVES="prime192v1 secp224r1 prime256v1 secp384r1 secp521r1" echo "/*" echo " * DER encoded EC parameters generated with script:" echo " * ta/pkcs11/scripts/dump_ec_params.sh" echo " */" echo "" for EC_CURVE in ${EC_CURVES} ; do echo "static const uint8_t ${EC_CURVE}_name_der[] = {" openssl ecparam -name ${EC_CURVE} -param_enc named_curve | \ openssl asn1parse -noout -out /dev/stdout | \ hexdump -v -e '/8 "\t"' -e '/1 "0x%02x, " ' -e '/8 "\n"' | \ sed 's/0x ,//g' echo "};" echo "" done for EC_CURVE in ${EC_CURVES} ; do echo "static const uint8_t ${EC_CURVE}_oid_der[] = {" openssl ecparam -name ${EC_CURVE} -param_enc explicit | \ openssl asn1parse -noout -out /dev/stdout | \ hexdump -v -e '/8 "\t"' -e '/1 "0x%02x, " ' -e '/8 "\n"' | \ sed 's/0x ,//g' echo "};" echo "" done optee_os-4.3.0/ta/pkcs11/scripts/verify-helpers.sh000077500000000000000000000052001464416617300220440ustar00rootroot00000000000000#!/bin/bash # SPDX-License-Identifier: BSD-2-Clause SHOW_DETAILS=1 ERRORS="" basepath="$(dirname $(dirname $(readlink -f "$0")))" details () [[ ${SHOW_DETAILS} -ne 0 ]] verify_enum () { PREFIX=$1 SYMBOL_LIST="$(grep PKCS11\_$PREFIX\_ ${basepath}/include/pkcs11_ta.h | cut -f2 | cut '-d ' -f1)" details && echo -e "\e[4m${PREFIX}\e[0m" details && echo "" details && echo -e "symbol\tuses\tstatus" for symbol in $SYMBOL_LIST ; do details && echo -n "$symbol" COUNT="$(grep ${symbol} ${basepath}/src/* | wc -l)" details && echo -n -e "\t${COUNT}\t" PRESENT="$(grep PKCS11_ID.*\($symbol.*\) ${basepath}/src/pkcs11_helpers.c | wc -l)" if [ ${PRESENT} -ne 0 ] ; then details && echo -e "\e[32mOK\e[0m" elif [ $COUNT -eq 0 ] ; then details && echo -e "\e[33mmissing but unused\e[0m" else details && echo -e "\e[31mMISSING!\e[0m" ERRORS+=" ${symbol}" fi done details && echo "" } verify_define () { PREFIX=$1 SYMBOL_LIST="$(grep PKCS11\_$PREFIX\_ ${basepath}/include/pkcs11_ta.h | grep ^#define | cut '-d ' -f2 | cut -f1)" details && echo -e "\e[4m${PREFIX}\e[0m" details && echo "" details && echo -e "symbol\tuses\tstatus" for symbol in $SYMBOL_LIST ; do details && echo -n "$symbol" COUNT="$(grep ${symbol} ${basepath}/src/* | wc -l)" details && echo -n -e "\t${COUNT}\t" PRESENT="$(grep PKCS11_ID.*\($symbol.*\) ${basepath}/src/pkcs11_helpers.c | wc -l)" if [ ${PRESENT} -ne 0 ] ; then details && echo -e "\e[32mOK\e[0m" elif [ $COUNT -eq 0 ] ; then details && echo -e "\e[33mmissing but unused\e[0m" else details && echo -e "\e[31mMISSING!\e[0m" ERRORS+=" ${symbol}" fi done details && echo "" } usage() { SCR=$(basename "$0") echo "Usage: $SCR Verify that helpers are up to date" echo " $SCR --quiet Only print errors" echo " $SCR --help This help" echo "" echo "Verification checks that all PKCS11_* enums or defines from \ include/pkcs11_ta.h are either present in src/pkcs11_helpers.c or not used at \ all." exit 1 } while [[ $# -gt 0 ]]; do arg="$1" shift case $arg in -q|--quiet) SHOW_DETAILS=0 ;; -h|--help) usage ;; *) echo "error: invalid argument: ${arg}" 1>&2 exit 1 esac done # check that symbols exists verify_enum CKA verify_define CKFS verify_define CKFT verify_define CKFSS verify_enum CKS verify_enum CKR verify_enum CKO verify_enum CKK if [ -n "${ERRORS}" ] ; then SCR=$(basename "$0") for symbol in $ERRORS ; do echo "${SCR}: error: missing symbol ${symbol} in ${basepath}/src/pkcs11_helpers.c" 1>&2 done exit 1 fi exit 0 optee_os-4.3.0/ta/pkcs11/src/000077500000000000000000000000001464416617300156445ustar00rootroot00000000000000optee_os-4.3.0/ta/pkcs11/src/attributes.c000066400000000000000000000261121464416617300202000ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include "attributes.h" #include "pkcs11_helpers.h" #include "serializer.h" enum pkcs11_rc init_attributes_head(struct obj_attrs **head) { *head = TEE_Malloc(sizeof(**head), TEE_MALLOC_FILL_ZERO); if (!*head) return PKCS11_CKR_DEVICE_MEMORY; return PKCS11_CKR_OK; } enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute, void *data, size_t size) { size_t buf_len = sizeof(struct obj_attrs) + (*head)->attrs_size; char **bstart = (void *)head; enum pkcs11_rc rc = PKCS11_CKR_OK; uint32_t data32 = 0; data32 = attribute; rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); if (rc) return rc; data32 = size; rc = serialize(bstart, &buf_len, &data32, sizeof(uint32_t)); if (rc) return rc; rc = serialize(bstart, &buf_len, data, size); if (rc) return rc; /* Alloced buffer is always well aligned */ head = (void *)bstart; (*head)->attrs_size += 2 * sizeof(uint32_t) + size; (*head)->attrs_count++; return rc; } static enum pkcs11_rc _remove_attribute(struct obj_attrs **head, uint32_t attribute, bool empty) { struct obj_attrs *h = *head; char *cur = NULL; char *end = NULL; size_t next_off = 0; /* Let's find the target attribute */ cur = (char *)h + sizeof(struct obj_attrs); end = cur + h->attrs_size; for (; cur < end; cur += next_off) { struct pkcs11_attribute_head pkcs11_ref = { }; TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; if (pkcs11_ref.id != attribute) continue; if (empty && pkcs11_ref.size) return PKCS11_CKR_FUNCTION_FAILED; TEE_MemMove(cur, cur + next_off, end - (cur + next_off)); h->attrs_count--; h->attrs_size -= next_off; end -= next_off; next_off = 0; return PKCS11_CKR_OK; } DMSG("Attribute %s (%#x) not found", id2str_attr(attribute), attribute); return PKCS11_RV_NOT_FOUND; } enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head, uint32_t attribute) { return _remove_attribute(head, attribute, true /* empty */); } void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute, void **attr, uint32_t *attr_size, size_t *count) { char *cur = (char *)head + sizeof(struct obj_attrs); char *end = cur + head->attrs_size; size_t next_off = 0; size_t max_found = *count; size_t found = 0; void **attr_ptr = attr; uint32_t *attr_size_ptr = attr_size; for (; cur < end; cur += next_off) { /* Structure aligned copy of the pkcs11_ref in the object */ struct pkcs11_attribute_head pkcs11_ref = { }; TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; if (pkcs11_ref.id != attribute) continue; found++; if (!max_found) continue; /* only count matching attributes */ if (attr) { if (pkcs11_ref.size) *attr_ptr++ = cur + sizeof(pkcs11_ref); else *attr_ptr++ = NULL; } if (attr_size) *attr_size_ptr++ = pkcs11_ref.size; if (found == max_found) break; } /* Sanity */ if (cur > end) { DMSG("Exceeding serial object length"); TEE_Panic(0); } *count = found; } enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute, void **attr_ptr, uint32_t *attr_size) { size_t count = 1; get_attribute_ptrs(head, attribute, attr_ptr, attr_size, &count); if (!count) return PKCS11_RV_NOT_FOUND; if (count != 1) return PKCS11_CKR_GENERAL_ERROR; return PKCS11_CKR_OK; } enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute, void *attr, uint32_t *attr_size) { enum pkcs11_rc rc = PKCS11_CKR_OK; void *attr_ptr = NULL; uint32_t size = 0; rc = get_attribute_ptr(head, attribute, &attr_ptr, &size); if (rc) return rc; if (attr_size && *attr_size < size) { *attr_size = size; /* This reuses buffer-to-small for any bad size matching */ return PKCS11_CKR_BUFFER_TOO_SMALL; } if (attr) TEE_MemMove(attr, attr_ptr, size); if (attr_size) *attr_size = size; return PKCS11_CKR_OK; } enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute, void *data, size_t size) { enum pkcs11_rc rc = PKCS11_CKR_OK; rc = _remove_attribute(head, attribute, false); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) return rc; return add_attribute(head, attribute, data, size); } enum pkcs11_rc modify_attributes_list(struct obj_attrs **dst, struct obj_attrs *head) { char *cur = (char *)head + sizeof(struct obj_attrs); char *end = cur + head->attrs_size; size_t len = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; for (; cur < end; cur += len) { struct pkcs11_attribute_head *cli_ref = (void *)cur; /* Structure aligned copy of the pkcs11_ref in the object */ struct pkcs11_attribute_head cli_head = { }; TEE_MemMove(&cli_head, cur, sizeof(cli_head)); len = sizeof(cli_head) + cli_head.size; rc = set_attribute(dst, cli_head.id, cli_head.size ? cli_ref->data : NULL, cli_head.size); if (rc) return rc; } return PKCS11_CKR_OK; } bool get_bool(struct obj_attrs *head, uint32_t attribute) { enum pkcs11_rc rc = PKCS11_CKR_OK; uint8_t bbool = 0; uint32_t size = sizeof(bbool); rc = get_attribute(head, attribute, &bbool, &size); if (rc == PKCS11_RV_NOT_FOUND) return false; assert(rc == PKCS11_CKR_OK); return bbool; } bool attributes_match_reference(struct obj_attrs *candidate, struct obj_attrs *ref) { size_t count = ref->attrs_count; unsigned char *ref_attr = ref->attrs; uint32_t rc = PKCS11_CKR_GENERAL_ERROR; if (!ref->attrs_count) { DMSG("Empty reference match all"); return true; } for (count = 0; count < ref->attrs_count; count++) { struct pkcs11_attribute_head pkcs11_ref = { }; void *value = NULL; uint32_t size = 0; TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref)); /* Hidden attributes cannot be matched */ if (attribute_is_hidden(&pkcs11_ref)) return false; rc = get_attribute_ptr(candidate, pkcs11_ref.id, &value, &size); if (rc || !value || size != pkcs11_ref.size || TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value, size)) return false; ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size; } return true; } enum pkcs11_rc attributes_match_add_reference(struct obj_attrs **head, struct obj_attrs *ref) { size_t count = ref->attrs_count; unsigned char *ref_attr = ref->attrs; enum pkcs11_rc rc = PKCS11_CKR_OK; if (!ref->attrs_count) return PKCS11_CKR_OK; for (count = 0; count < ref->attrs_count; count++) { struct pkcs11_attribute_head pkcs11_ref = { }; void *value = NULL; uint32_t size = 0; TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref)); rc = get_attribute_ptr(*head, pkcs11_ref.id, &value, &size); if (rc == PKCS11_RV_NOT_FOUND) { rc = add_attribute(head, pkcs11_ref.id, ref_attr + sizeof(pkcs11_ref), pkcs11_ref.size); if (rc) return rc; } else { if (rc || !value || size != pkcs11_ref.size || TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value, size)) return PKCS11_CKR_TEMPLATE_INCONSISTENT; } ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size; } return PKCS11_CKR_OK; } #if CFG_TEE_TA_LOG_LEVEL > 0 /* * Debug: dump CK attribute array to output trace */ #define ATTR_TRACE_FMT "%s attr %s / %s\t(0x%04"PRIx32" %"PRIu32"-byte" #define ATTR_FMT_0BYTE ATTR_TRACE_FMT ")" #define ATTR_FMT_1BYTE ATTR_TRACE_FMT ": %02x)" #define ATTR_FMT_2BYTE ATTR_TRACE_FMT ": %02x %02x)" #define ATTR_FMT_3BYTE ATTR_TRACE_FMT ": %02x %02x %02x)" #define ATTR_FMT_4BYTE ATTR_TRACE_FMT ": %02x %02x %02x %02x)" #define ATTR_FMT_ARRAY ATTR_TRACE_FMT ": %02x %02x %02x %02x ...)" static void __trace_attributes(char *prefix, void *src, void *end) { size_t next_off = 0; char *prefix2 = NULL; size_t prefix_len = strlen(prefix); char *cur = src; /* append 4 spaces to the prefix plus terminal '\0' */ prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); if (!prefix2) return; TEE_MemMove(prefix2, prefix, prefix_len + 1); TEE_MemFill(prefix2 + prefix_len, ' ', 4); *(prefix2 + prefix_len + 4) = '\0'; for (; cur < (char *)end; cur += next_off) { struct pkcs11_attribute_head pkcs11_ref = { }; uint8_t data[4] = { 0 }; TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), MIN(pkcs11_ref.size, sizeof(data))); next_off = sizeof(pkcs11_ref) + pkcs11_ref.size; switch (pkcs11_ref.size) { case 0: IMSG_RAW(ATTR_FMT_0BYTE, prefix, id2str_attr(pkcs11_ref.id), "*", pkcs11_ref.id, pkcs11_ref.size); break; case 1: IMSG_RAW(ATTR_FMT_1BYTE, prefix, id2str_attr(pkcs11_ref.id), id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, cur + sizeof(pkcs11_ref)), pkcs11_ref.id, pkcs11_ref.size, data[0]); break; case 2: IMSG_RAW(ATTR_FMT_2BYTE, prefix, id2str_attr(pkcs11_ref.id), id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, cur + sizeof(pkcs11_ref)), pkcs11_ref.id, pkcs11_ref.size, data[0], data[1]); break; case 3: IMSG_RAW(ATTR_FMT_3BYTE, prefix, id2str_attr(pkcs11_ref.id), id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, cur + sizeof(pkcs11_ref)), pkcs11_ref.id, pkcs11_ref.size, data[0], data[1], data[2]); break; case 4: IMSG_RAW(ATTR_FMT_4BYTE, prefix, id2str_attr(pkcs11_ref.id), id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, cur + sizeof(pkcs11_ref)), pkcs11_ref.id, pkcs11_ref.size, data[0], data[1], data[2], data[3]); break; default: IMSG_RAW(ATTR_FMT_ARRAY, prefix, id2str_attr(pkcs11_ref.id), id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, cur + sizeof(pkcs11_ref)), pkcs11_ref.id, pkcs11_ref.size, data[0], data[1], data[2], data[3]); break; } switch (pkcs11_ref.id) { case PKCS11_CKA_WRAP_TEMPLATE: case PKCS11_CKA_UNWRAP_TEMPLATE: case PKCS11_CKA_DERIVE_TEMPLATE: if (pkcs11_ref.size) trace_attributes(prefix2, cur + sizeof(pkcs11_ref)); break; default: break; } } /* Sanity */ if (cur != end) EMSG("Warning: unexpected alignment in object attributes"); TEE_Free(prefix2); } void trace_attributes(const char *prefix, void *ref) { struct obj_attrs head = { }; char *pre = NULL; TEE_MemMove(&head, ref, sizeof(head)); if (!head.attrs_count) return; pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); if (!pre) { EMSG("%s: out of memory", prefix); return; } if (prefix) TEE_MemMove(pre, prefix, strlen(prefix)); IMSG_RAW("%s,--- (serial object) Attributes list --------", pre); IMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", pre, head.attrs_count, head.attrs_size); pre[prefix ? strlen(prefix) : 0] = '|'; __trace_attributes(pre, (char *)ref + sizeof(head), (char *)ref + sizeof(head) + head.attrs_size); IMSG_RAW("%s`-----------------------", prefix ? prefix : ""); TEE_Free(pre); } #endif /*CFG_TEE_TA_LOG_LEVEL*/ optee_os-4.3.0/ta/pkcs11/src/attributes.h000066400000000000000000000230051464416617300202030ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_ATTRIBUTES_H #define PKCS11_TA_ATTRIBUTES_H #include #include #include #include #include "pkcs11_helpers.h" /* * Boolean property attributes (BPA): bit position in a 64 bit mask * for boolean properties object can mandate as attribute, depending * on the object. These attributes are often accessed and it is * quicker to get them from a 64 bit field in the object instance * rather than searching into the object attributes. */ #define PKCS11_BOOLPROPS_BASE 0 #define PKCS11_BOOLPROPS_MAX_COUNT 64 enum boolprop_attr { BPA_TOKEN = 0, BPA_PRIVATE, BPA_TRUSTED, BPA_SENSITIVE, BPA_ENCRYPT, BPA_DECRYPT, BPA_WRAP, BPA_UNWRAP, BPA_SIGN, BPA_SIGN_RECOVER, BPA_VERIFY, BPA_VERIFY_RECOVER, BPA_DERIVE, BPA_EXTRACTABLE, BPA_LOCAL, BPA_NEVER_EXTRACTABLE, BPA_ALWAYS_SENSITIVE, BPA_MODIFIABLE, BPA_COPYABLE, BPA_DESTROYABLE, BPA_ALWAYS_AUTHENTICATE, BPA_WRAP_WITH_TRUSTED, }; /* * Header of a serialized memory object inside PKCS11 TA. * * @attrs_size: byte size of the serialized data * @attrs_count: number of items in the blob * @attrs: then starts the blob binary data */ struct obj_attrs { uint32_t attrs_size; uint32_t attrs_count; uint8_t attrs[]; }; /* * init_attributes_head() - Allocate a reference for serialized attributes * @head: *@head holds the retrieved pointer * * Retrieved pointer can be freed from a simple TEE_Free(reference). * * Return PKCS11_CKR_OK on success or a PKCS11 return code. */ enum pkcs11_rc init_attributes_head(struct obj_attrs **head); /* * add_attribute() - Update serialized attributes to add an entry. * * @head: *@head points to serialized attributes, * can be reallocated as attributes are added * @attribute: Attribute ID to add * @data: Opaque data of attribute * @size: Size of data * * Return PKCS11_CKR_OK on success or a PKCS11 return code. */ enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute, void *data, size_t size); /* * Update serialized attributes to remove an empty entry. Can relocate the * attribute list buffer. Only 1 instance of the entry is expected. * * Return PKCS11_CKR_OK on success or a PKCS11 return code. */ enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head, uint32_t attrib); /* * get_attribute_ptrs() - Get pointers to attributes with a given ID * @head: Pointer to serialized attributes * @attribute: Attribute ID to look for * @attr: Array of pointers to the data inside @head * @attr_size: Array of uint32_t holding the sizes of each value pointed to * by @attr * @count: Number of elements in the arrays above * * If *count == 0, count and return in *count the number of attributes matching * the input attribute ID. * * If *count != 0, return the address and size of the attributes found, up to * the occurrence number *count. attr and attr_size are expected large * enough. attr is the output array of the values found. attr_size is the * output array of the size of each value found. * * If attr_size != NULL, return in *attr_size attribute value size. * If attr != NULL return in *attr the address of the attribute value. */ void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute, void **attr, uint32_t *attr_size, size_t *count); /* * get_attribute_ptrs() - Get pointer to the attribute of a given ID * @head: Pointer to serialized attributes * @attribute: Attribute ID * @attr: *@attr holds the retrieved pointer to the attribute value * @attr_size: Size of the attribute value * * If no matching attributes is found return PKCS11_RV_NOT_FOUND. * If attr_size != NULL, return in *attr_size attribute value size. * If attr != NULL, return in *attr the address of the attribute value. * * Return PKCS11_CKR_OK or PKCS11_RV_NOT_FOUND on success, or a PKCS11 return * code. */ enum pkcs11_rc get_attribute_ptr(struct obj_attrs *head, uint32_t attribute, void **attr_ptr, uint32_t *attr_size); /* * get_attribute() - Copy out the attribute of a given ID * @head: Pointer to serialized attributes * @attribute: Attribute ID to look for * @attr: holds the retrieved attribute value * @attr_size: Size of the attribute value * * If attribute is not found, return PKCS11_RV_NOT_FOUND. * * If attr_size != NULL, check that attr has enough room for value (compare * against *attr_size), copy attribute value to attr and finally return actual * value size in *attr_size. * * If there is not enough room return PKCS11_CKR_BUFFER_TOO_SMALL with expected * size in *attr_size. * * If attr is NULL and attr_size != NULL return expected buffer size in * *attr_size. * * Return PKCS11_CKR_OK or PKCS11_RV_NOT_FOUND on success, or a PKCS11 return * code. */ enum pkcs11_rc get_attribute(struct obj_attrs *head, uint32_t attribute, void *attr, uint32_t *attr_size); /* * set_attribute() - Set the attribute of a given ID with value * @head: Pointer to serialized attributes where attribute is to be set, * can be relocated as attributes are modified/added * @attribute: Attribute ID to look for * @data: Holds the attribute value to be set * @size: Size of the attribute value * * Return PKCS11_CKR_OK on success or a PKCS11 return code. */ enum pkcs11_rc set_attribute(struct obj_attrs **head, uint32_t attribute, void *data, size_t size); /* * modify_attributes_list() - Modify the value of attributes in destination * attribute list (serialized attributes) based on the value of attributes in * the source attribute list * @dst: Pointer to serialized attrbutes where attributes are to be * modified, can be relocated as attributes are modified * @head: Serialized attributes containing attributes which need to be * modified in the destination attribute list * * Return PKCS11_CKR_OK on success */ enum pkcs11_rc modify_attributes_list(struct obj_attrs **dst, struct obj_attrs *head); /* * get_u32_attribute() - Copy out the 32-bit attribute value of a given ID * @head: Pointer to serialized attributes * @attribute: Attribute ID * @attr: holds the retrieved 32-bit attribute value * * If attribute is not found, return PKCS11_RV_NOT_FOUND. * If the retreived attribute doesn't have a 4 byte sized value * PKCS11_CKR_GENERAL_ERROR is returned. * * Return PKCS11_CKR_OK or PKCS11_RV_NOT_FOUND on success, or a PKCS11 return * code. */ static inline enum pkcs11_rc get_u32_attribute(struct obj_attrs *head, uint32_t attribute, uint32_t *attr) { uint32_t size = sizeof(uint32_t); enum pkcs11_rc rc = get_attribute(head, attribute, attr, &size); if (!rc && size != sizeof(uint32_t)) return PKCS11_CKR_GENERAL_ERROR; return rc; } /* * Return true if all attributes from the reference are found and match value * in the candidate attribute list. */ bool attributes_match_reference(struct obj_attrs *ref, struct obj_attrs *candidate); /* * Check attributes from @ref are all found or added in @head * * Return PKCS11_CKR_OK on success, or a PKCS11 return code. */ enum pkcs11_rc attributes_match_add_reference(struct obj_attrs **head, struct obj_attrs *ref); /* * get_class() - Get class ID of an object * @head: Pointer to serialized attributes * * Returns the class ID of an object on succes or returns * PKCS11_CKO_UNDEFINED_ID on error. */ static inline enum pkcs11_class_id get_class(struct obj_attrs *head) { uint32_t class = 0; uint32_t size = sizeof(class); if (get_attribute(head, PKCS11_CKA_CLASS, &class, &size)) return PKCS11_CKO_UNDEFINED_ID; return class; } /* * get_key_type() - Get the key type of an object * @head: Pointer to serialized attributes * * Returns the key type of an object on success or returns * PKCS11_CKK_UNDEFINED_ID on error. */ static inline enum pkcs11_key_type get_key_type(struct obj_attrs *head) { uint32_t type = 0; uint32_t size = sizeof(type); if (get_attribute(head, PKCS11_CKA_KEY_TYPE, &type, &size)) return PKCS11_CKK_UNDEFINED_ID; return type; } /* * get_certificate_type() - Get the certificate type of an object * @head: Pointer to serialized attributes * * Returns the certificate type of an object on success or returns * PKCS11_CKC_UNDEFINED_ID on error. */ static inline enum pkcs11_certificate_type get_certificate_type(struct obj_attrs *head) { uint32_t type = 0; if (get_u32_attribute(head, PKCS11_CKA_CERTIFICATE_TYPE, &type)) return PKCS11_CKC_UNDEFINED_ID; return type; } /* * get_mechanism_type() - Get the mechanism type of an object * @head: Pointer to serialized attributes * * Returns the mechanism type of an object on success or returns * PKCS11_CKM_UNDEFINED_ID on error. */ static inline enum pkcs11_mechanism_id get_mechanism_type(struct obj_attrs *head) { uint32_t type = 0; uint32_t size = sizeof(type); if (get_attribute(head, PKCS11_CKA_MECHANISM_TYPE, &type, &size)) return PKCS11_CKM_UNDEFINED_ID; return type; } /* * get_bool() - Get the bool value of an attribute * @head: Pointer to serialized attributes * @attribute: Attribute ID to look for * * May assert if attribute ID isn't of the boolean type. * * Returns the bool value of the supplied attribute ID on success if found * else false. */ bool get_bool(struct obj_attrs *head, uint32_t attribute); #if CFG_TEE_TA_LOG_LEVEL > 0 /* Debug: dump object attributes to IMSG() trace console */ void trace_attributes(const char *prefix, void *ref); #else static inline void trace_attributes(const char *prefix __unused, void *ref __unused) { } #endif /*CFG_TEE_TA_LOG_LEVEL*/ #endif /*PKCS11_TA_ATTRIBUTES_H*/ optee_os-4.3.0/ta/pkcs11/src/entry.c000066400000000000000000000250131464416617300171520ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2020, Linaro Limited */ #include #include #include #include #include #include #include "object.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" TEE_Result TA_CreateEntryPoint(void) { return pkcs11_init(); } void TA_DestroyEntryPoint(void) { pkcs11_deinit(); } TEE_Result TA_OpenSessionEntryPoint(uint32_t __unused param_types, TEE_Param __unused params[4], void **tee_session) { struct pkcs11_client *client = register_client(); if (!client) return TEE_ERROR_OUT_OF_MEMORY; *tee_session = client; return TEE_SUCCESS; } void TA_CloseSessionEntryPoint(void *tee_session) { struct pkcs11_client *client = tee_session2client(tee_session); unregister_client(client); } /* * Entry point for invocation command PKCS11_CMD_PING * * Return a PKCS11_CKR_* value which is also loaded into the output param#0 */ static enum pkcs11_rc entry_ping(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *out = params + 2; const uint32_t ver[] = { PKCS11_TA_VERSION_MAJOR, PKCS11_TA_VERSION_MINOR, PKCS11_TA_VERSION_PATCH, }; if (ptypes != exp_pt || params[0].memref.size != TEE_PARAM0_SIZE_MIN || out->memref.size != sizeof(ver)) return PKCS11_CKR_ARGUMENTS_BAD; TEE_MemMove(out->memref.buffer, ver, sizeof(ver)); return PKCS11_CKR_OK; } static bool __maybe_unused param_is_none(uint32_t ptypes, unsigned int index) { return TEE_PARAM_TYPE_GET(ptypes, index) == TEE_PARAM_TYPE_NONE; } static bool __maybe_unused param_is_memref(uint32_t ptypes, unsigned int index) { switch (TEE_PARAM_TYPE_GET(ptypes, index)) { case TEE_PARAM_TYPE_MEMREF_INPUT: case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: return true; default: return false; } } static bool __maybe_unused param_is_input(uint32_t ptypes, unsigned int index) { return TEE_PARAM_TYPE_GET(ptypes, index) == TEE_PARAM_TYPE_MEMREF_INPUT; } static bool __maybe_unused param_is_output(uint32_t ptypes, unsigned int index) { return TEE_PARAM_TYPE_GET(ptypes, index) == TEE_PARAM_TYPE_MEMREF_OUTPUT; } /* * Entry point for PKCS11 TA commands * * Param#0 (ctrl) is an output or an in/out buffer. Input data are serialized * arguments for the invoked command while the output data is used to send * back to the client a PKCS11 finer status ID than the GPD TEE result codes * Client shall check the status ID from the parameter #0 output buffer together * with the GPD TEE result code. */ TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd, uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS]) { struct pkcs11_client *client = tee_session2client(tee_session); enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; if (!client) return TEE_ERROR_SECURITY; /* All command handlers will check only against 4 parameters */ COMPILE_TIME_ASSERT(TEE_NUM_PARAMS == 4); /* * Param#0 must be either an output or an inout memref as used to * store the output return value for the invoked command. */ switch (TEE_PARAM_TYPE_GET(ptypes, 0)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: if (params[0].memref.size < sizeof(rc)) return TEE_ERROR_BAD_PARAMETERS; break; default: return TEE_ERROR_BAD_PARAMETERS; } DMSG("%s p#0 %zu@%p, p#1 %s %zu@%p, p#2 %s %zu@%p", id2str_ta_cmd(cmd), params[0].memref.size, params[0].memref.buffer, param_is_input(ptypes, 1) ? "in" : param_is_output(ptypes, 1) ? "out" : "---", param_is_memref(ptypes, 1) ? params[1].memref.size : 0, param_is_memref(ptypes, 1) ? params[1].memref.buffer : NULL, param_is_input(ptypes, 2) ? "in" : param_is_output(ptypes, 2) ? "out" : "---", param_is_memref(ptypes, 2) ? params[2].memref.size : 0, param_is_memref(ptypes, 2) ? params[2].memref.buffer : NULL); switch (cmd) { case PKCS11_CMD_PING: rc = entry_ping(ptypes, params); break; case PKCS11_CMD_SLOT_LIST: rc = entry_ck_slot_list(ptypes, params); break; case PKCS11_CMD_SLOT_INFO: rc = entry_ck_slot_info(ptypes, params); break; case PKCS11_CMD_TOKEN_INFO: rc = entry_ck_token_info(ptypes, params); break; case PKCS11_CMD_MECHANISM_IDS: rc = entry_ck_token_mecha_ids(ptypes, params); break; case PKCS11_CMD_MECHANISM_INFO: rc = entry_ck_token_mecha_info(ptypes, params); break; case PKCS11_CMD_OPEN_SESSION: rc = entry_ck_open_session(client, ptypes, params); break; case PKCS11_CMD_CLOSE_SESSION: rc = entry_ck_close_session(client, ptypes, params); break; case PKCS11_CMD_CLOSE_ALL_SESSIONS: rc = entry_ck_close_all_sessions(client, ptypes, params); break; case PKCS11_CMD_SESSION_INFO: rc = entry_ck_session_info(client, ptypes, params); break; case PKCS11_CMD_INIT_TOKEN: rc = entry_ck_token_initialize(ptypes, params); break; case PKCS11_CMD_INIT_PIN: rc = entry_ck_init_pin(client, ptypes, params); break; case PKCS11_CMD_SET_PIN: rc = entry_ck_set_pin(client, ptypes, params); break; case PKCS11_CMD_LOGIN: rc = entry_ck_login(client, ptypes, params); break; case PKCS11_CMD_LOGOUT: rc = entry_ck_logout(client, ptypes, params); break; case PKCS11_CMD_CREATE_OBJECT: rc = entry_create_object(client, ptypes, params); break; case PKCS11_CMD_DESTROY_OBJECT: rc = entry_destroy_object(client, ptypes, params); break; case PKCS11_CMD_ENCRYPT_INIT: rc = entry_processing_init(client, ptypes, params, PKCS11_FUNCTION_ENCRYPT); break; case PKCS11_CMD_DECRYPT_INIT: rc = entry_processing_init(client, ptypes, params, PKCS11_FUNCTION_DECRYPT); break; case PKCS11_CMD_ENCRYPT_UPDATE: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_ENCRYPT, PKCS11_FUNC_STEP_UPDATE); break; case PKCS11_CMD_DECRYPT_UPDATE: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DECRYPT, PKCS11_FUNC_STEP_UPDATE); break; case PKCS11_CMD_ENCRYPT_ONESHOT: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_ENCRYPT, PKCS11_FUNC_STEP_ONESHOT); break; case PKCS11_CMD_DECRYPT_ONESHOT: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DECRYPT, PKCS11_FUNC_STEP_ONESHOT); break; case PKCS11_CMD_ENCRYPT_FINAL: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_ENCRYPT, PKCS11_FUNC_STEP_FINAL); break; case PKCS11_CMD_DECRYPT_FINAL: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DECRYPT, PKCS11_FUNC_STEP_FINAL); break; case PKCS11_CMD_SIGN_INIT: rc = entry_processing_init(client, ptypes, params, PKCS11_FUNCTION_SIGN); break; case PKCS11_CMD_VERIFY_INIT: rc = entry_processing_init(client, ptypes, params, PKCS11_FUNCTION_VERIFY); break; case PKCS11_CMD_SIGN_ONESHOT: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_SIGN, PKCS11_FUNC_STEP_ONESHOT); break; case PKCS11_CMD_VERIFY_ONESHOT: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_VERIFY, PKCS11_FUNC_STEP_ONESHOT); break; case PKCS11_CMD_SIGN_UPDATE: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_SIGN, PKCS11_FUNC_STEP_UPDATE); break; case PKCS11_CMD_VERIFY_UPDATE: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_VERIFY, PKCS11_FUNC_STEP_UPDATE); break; case PKCS11_CMD_SIGN_FINAL: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_SIGN, PKCS11_FUNC_STEP_FINAL); break; case PKCS11_CMD_VERIFY_FINAL: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_VERIFY, PKCS11_FUNC_STEP_FINAL); break; case PKCS11_CMD_GENERATE_KEY: rc = entry_generate_secret(client, ptypes, params); break; case PKCS11_CMD_FIND_OBJECTS_INIT: rc = entry_find_objects_init(client, ptypes, params); break; case PKCS11_CMD_FIND_OBJECTS: rc = entry_find_objects(client, ptypes, params); break; case PKCS11_CMD_FIND_OBJECTS_FINAL: rc = entry_find_objects_final(client, ptypes, params); break; case PKCS11_CMD_GET_ATTRIBUTE_VALUE: rc = entry_get_attribute_value(client, ptypes, params); break; case PKCS11_CMD_GET_OBJECT_SIZE: rc = entry_get_object_size(client, ptypes, params); break; case PKCS11_CMD_SET_ATTRIBUTE_VALUE: rc = entry_set_attribute_value(client, ptypes, params); break; case PKCS11_CMD_COPY_OBJECT: rc = entry_copy_object(client, ptypes, params); break; case PKCS11_CMD_SEED_RANDOM: rc = entry_ck_seed_random(client, ptypes, params); break; case PKCS11_CMD_GENERATE_RANDOM: rc = entry_ck_generate_random(client, ptypes, params); break; case PKCS11_CMD_DERIVE_KEY: rc = entry_processing_key(client, ptypes, params, PKCS11_FUNCTION_DERIVE); break; case PKCS11_CMD_RELEASE_ACTIVE_PROCESSING: rc = entry_release_active_processing(client, ptypes, params); break; case PKCS11_CMD_DIGEST_INIT: rc = entry_processing_init(client, ptypes, params, PKCS11_FUNCTION_DIGEST); break; case PKCS11_CMD_DIGEST_UPDATE: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DIGEST, PKCS11_FUNC_STEP_UPDATE); break; case PKCS11_CMD_DIGEST_KEY: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DIGEST, PKCS11_FUNC_STEP_UPDATE_KEY); break; case PKCS11_CMD_DIGEST_ONESHOT: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DIGEST, PKCS11_FUNC_STEP_ONESHOT); break; case PKCS11_CMD_DIGEST_FINAL: rc = entry_processing_step(client, ptypes, params, PKCS11_FUNCTION_DIGEST, PKCS11_FUNC_STEP_FINAL); break; case PKCS11_CMD_GENERATE_KEY_PAIR: rc = entry_generate_key_pair(client, ptypes, params); break; case PKCS11_CMD_WRAP_KEY: rc = entry_wrap_key(client, ptypes, params); break; case PKCS11_CMD_UNWRAP_KEY: rc = entry_processing_key(client, ptypes, params, PKCS11_FUNCTION_UNWRAP); break; default: EMSG("Command %#"PRIx32" is not supported", cmd); return TEE_ERROR_NOT_SUPPORTED; } DMSG("%s rc %#"PRIx32"/%s", id2str_ta_cmd(cmd), rc, id2str_rc(rc)); TEE_MemMove(params[0].memref.buffer, &rc, sizeof(rc)); params[0].memref.size = sizeof(rc); if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) return TEE_ERROR_SHORT_BUFFER; else return TEE_SUCCESS; } optee_os-4.3.0/ta/pkcs11/src/handle.c000066400000000000000000000047651464416617300172570ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014-2020, Linaro Limited */ #include #include #include "handle.h" /* * Define the initial capacity of the database. It should be a low number * multiple of 2 since some databases a likely to only use a few handles. * Since the algorithm is to doubles up when growing it shouldn't cause a * noticeable overhead on large databases. */ #define HANDLE_DB_INITIAL_MAX_PTRS 4 /* Specific pointer ~0 denotes a still allocated but invalid handle */ #define INVALID_HANDLE_PTR ((void *)~0) void handle_db_init(struct handle_db *db) { TEE_MemFill(db, 0, sizeof(*db)); } void handle_db_destroy(struct handle_db *db) { if (db) { TEE_Free(db->ptrs); db->ptrs = NULL; db->max_ptrs = 0; } } uint32_t handle_get(struct handle_db *db, void *ptr) { uint32_t n = 0; void *p = NULL; uint32_t new_max_ptrs = 0; if (!db || !ptr || ptr == INVALID_HANDLE_PTR) return 0; /* Try to find an empty location (index 0 is reserved as invalid) */ for (n = 1; n < db->max_ptrs; n++) { if (!db->ptrs[n]) { db->ptrs[n] = ptr; return n; } } /* No location available, grow the ptrs array */ if (db->max_ptrs) new_max_ptrs = db->max_ptrs * 2; else new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *)); if (!p) return 0; db->ptrs = p; TEE_MemFill(db->ptrs + db->max_ptrs, 0, (new_max_ptrs - db->max_ptrs) * sizeof(void *)); db->max_ptrs = new_max_ptrs; /* Since n stopped at db->max_ptrs there is an empty location there */ db->ptrs[n] = ptr; return n; } static bool handle_is_valid(struct handle_db *db, uint32_t handle) { return db && handle && handle < db->max_ptrs; } void *handle_put(struct handle_db *db, uint32_t handle) { void *p = NULL; if (!handle_is_valid(db, handle)) return NULL; p = db->ptrs[handle]; db->ptrs[handle] = NULL; return p; } void *handle_lookup(struct handle_db *db, uint32_t handle) { if (!handle_is_valid(db, handle) || db->ptrs[handle] == INVALID_HANDLE_PTR) return NULL; return db->ptrs[handle]; } void handle_invalidate(struct handle_db *db, uint32_t handle) { if (handle_is_valid(db, handle)) { if (!db->ptrs[handle]) TEE_Panic(TEE_ERROR_GENERIC); db->ptrs[handle] = INVALID_HANDLE_PTR; } } uint32_t handle_lookup_handle(struct handle_db *db, void *ptr) { uint32_t n = 0; if (ptr && ptr != INVALID_HANDLE_PTR) { for (n = 1; n < db->max_ptrs; n++) if (db->ptrs[n] == ptr) return n; } return 0; } optee_os-4.3.0/ta/pkcs11/src/handle.h000066400000000000000000000025471464416617300172600ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2014-2020, Linaro Limited */ #ifndef PKCS11_TA_HANDLE_H #define PKCS11_TA_HANDLE_H #include struct handle_db { void **ptrs; uint32_t max_ptrs; }; /* * Initialize the handle database */ void handle_db_init(struct handle_db *db); /* * Free all internal data structures of the database, but does not free * the db pointer. The database is safe to reuse after it's destroyed, it * just be empty again. */ void handle_db_destroy(struct handle_db *db); /* * Allocate a new handle ID and assigns the supplied pointer to it, * The function returns > 0 on success and 0 on failure. */ uint32_t handle_get(struct handle_db *db, void *ptr); /* * Deallocate a handle. Returns the associated pointer of the handle * if the handle was valid or NULL if it's invalid. */ void *handle_put(struct handle_db *db, uint32_t handle); /* * Return the associated pointer of the handle if the handle is a valid * handle. * Returns NULL on failure. */ void *handle_lookup(struct handle_db *db, uint32_t handle); /* Return the handle associated to a pointer if found, else return 0 */ uint32_t handle_lookup_handle(struct handle_db *db, void *ptr); /* Invalidate the reference referred by an allocated handle */ void handle_invalidate(struct handle_db *db, uint32_t handle); #endif /*PKCS11_TA_HANDLE_H*/ optee_os-4.3.0/ta/pkcs11/src/object.c000066400000000000000000001036421464416617300172640ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include "attributes.h" #include "handle.h" #include "object.h" #include "pkcs11_attributes.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "sanitize_object.h" #include "serializer.h" /* * Temporary list used to register allocated struct pkcs11_object instances * so that destroy_object() can unconditionally remove the object from its * list, being from an object destruction request or because object creation * failed before being completed. Objects are moved to their target list at * creation completion. */ LIST_HEAD(temp_obj_list, pkcs11_object) temporary_object_list = LIST_HEAD_INITIALIZER(temp_obj_list); static struct ck_token *get_session_token(void *session); struct pkcs11_object *pkcs11_handle2object(uint32_t handle, struct pkcs11_session *session) { struct pkcs11_object *object = NULL; object = handle_lookup(get_object_handle_db(session), handle); if (!object) return NULL; /* * If object is session only then no extra checks are needed as session * objects has flat access control space */ if (!object->token) return object; /* * Only allow access to token object if session is associated with * the token */ if (object->token != get_session_token(session)) return NULL; return object; } uint32_t pkcs11_object2handle(struct pkcs11_object *obj, struct pkcs11_session *session) { return handle_lookup_handle(get_object_handle_db(session), obj); } /* Currently handle pkcs11 sessions and tokens */ static struct object_list *get_session_objects(void *session) { /* Currently supporting only pkcs11 session */ struct pkcs11_session *ck_session = session; return pkcs11_get_session_objects(ck_session); } static struct ck_token *get_session_token(void *session) { struct pkcs11_session *ck_session = session; return pkcs11_session2token(ck_session); } /* Release resources of a non-persistent object */ static void cleanup_volatile_obj_ref(struct pkcs11_object *obj) { if (!obj) return; LIST_REMOVE(obj, link); if (obj->key_handle != TEE_HANDLE_NULL) TEE_FreeTransientObject(obj->key_handle); if (obj->attribs_hdl != TEE_HANDLE_NULL) TEE_CloseObject(obj->attribs_hdl); TEE_Free(obj->attributes); TEE_Free(obj->uuid); TEE_Free(obj); } /* Release resources of a persistent object including volatile resources */ void cleanup_persistent_object(struct pkcs11_object *obj, struct ck_token *token) { TEE_Result res = TEE_SUCCESS; if (!obj) return; /* Open handle with write properties to destroy the object */ if (obj->attribs_hdl != TEE_HANDLE_NULL) TEE_CloseObject(obj->attribs_hdl); res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, obj->uuid, sizeof(TEE_UUID), TEE_DATA_FLAG_ACCESS_WRITE_META, &obj->attribs_hdl); if (!res) TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl); obj->attribs_hdl = TEE_HANDLE_NULL; destroy_object_uuid(token, obj); cleanup_volatile_obj_ref(obj); } /* * destroy_object - destroy an PKCS11 TA object * * @session - session requesting object destruction * @obj - reference to the PKCS11 TA object * @session_only - true if only session object shall be destroyed */ void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj, bool session_only) { #ifdef DEBUG trace_attributes("[destroy]", obj->attributes); if (obj->uuid) MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid); #endif if (session_only) { /* Destroy object due to session closure */ handle_put(get_object_handle_db(session), pkcs11_object2handle(obj, session)); cleanup_volatile_obj_ref(obj); return; } /* Destroy target object (persistent or not) */ if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { assert(obj->uuid); /* Try twice otherwise panic! */ if (unregister_persistent_object(session->token, obj->uuid) && unregister_persistent_object(session->token, obj->uuid)) TEE_Panic(0); handle_put(get_object_handle_db(session), pkcs11_object2handle(obj, session)); cleanup_persistent_object(obj, session->token); token_invalidate_object_handles(obj); } else { handle_put(get_object_handle_db(session), pkcs11_object2handle(obj, session)); cleanup_volatile_obj_ref(obj); } } static struct pkcs11_object *create_obj_instance(struct obj_attrs *head, struct ck_token *token) { struct pkcs11_object *obj = NULL; obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO); if (!obj) return NULL; obj->key_handle = TEE_HANDLE_NULL; obj->attribs_hdl = TEE_HANDLE_NULL; obj->attributes = head; obj->token = token; return obj; } struct pkcs11_object *create_token_object(struct obj_attrs *head, TEE_UUID *uuid, struct ck_token *token) { struct pkcs11_object *obj = create_obj_instance(head, token); if (obj) obj->uuid = uuid; return obj; } /* * create_object - create an PKCS11 TA object from its attributes and value * * @sess - session requesting object creation * @head - reference to serialized attributes * @out_handle - generated handle for the created object */ enum pkcs11_rc create_object(void *sess, struct obj_attrs *head, uint32_t *out_handle) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct pkcs11_object *obj = NULL; struct pkcs11_session *session = (struct pkcs11_session *)sess; uint32_t obj_handle = 0; #ifdef DEBUG trace_attributes("[create]", head); #endif /* * We do not check the key attributes. At this point, key attributes * are expected consistent and reliable. */ obj = create_obj_instance(head, NULL); if (!obj) return PKCS11_CKR_DEVICE_MEMORY; LIST_INSERT_HEAD(&temporary_object_list, obj, link); /* Create a handle for the object in the session database */ obj_handle = handle_get(get_object_handle_db(session), obj); if (!obj_handle) { rc = PKCS11_CKR_DEVICE_MEMORY; goto err; } if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { TEE_Result res = TEE_SUCCESS; /* * Get an ID for the persistent object * Create the file * Register the object in the persistent database * (move the full sequence to persisent_db.c?) */ size_t size = sizeof(struct obj_attrs) + obj->attributes->attrs_size; uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META; rc = create_object_uuid(get_session_token(session), obj); if (rc) goto err; res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, obj->uuid, sizeof(TEE_UUID), tee_obj_flags, TEE_HANDLE_NULL, obj->attributes, size, &obj->attribs_hdl); if (res) { rc = tee2pkcs_error(res); goto err; } rc = register_persistent_object(get_session_token(session), obj->uuid); if (rc) goto err; TEE_CloseObject(obj->attribs_hdl); obj->attribs_hdl = TEE_HANDLE_NULL; /* Move object from temporary list to target token list */ LIST_REMOVE(obj, link); LIST_INSERT_HEAD(&session->token->object_list, obj, link); } else { /* Move object from temporary list to target session list */ LIST_REMOVE(obj, link); LIST_INSERT_HEAD(get_session_objects(session), obj, link); } *out_handle = obj_handle; return PKCS11_CKR_OK; err: /* make sure that supplied "head" isn't freed */ obj->attributes = NULL; handle_put(get_object_handle_db(session), obj_handle); if (get_bool(head, PKCS11_CKA_TOKEN)) cleanup_persistent_object(obj, session->token); else cleanup_volatile_obj_ref(obj); return rc; } enum pkcs11_rc entry_create_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); enum pkcs11_rc rc = PKCS11_CKR_OK; TEE_Param *ctrl = params; TEE_Param *out = params + 2; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct obj_attrs *head = NULL; struct pkcs11_object_head *template = NULL; size_t template_size = 0; uint32_t obj_handle = 0; /* * Collect the arguments of the request */ if (!client || ptypes != exp_pt || out->memref.size != sizeof(obj_handle)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } template_size = sizeof(*template) + template->attrs_size; /* * Prepare a clean initial state for the requested object attributes. * Free temporary template once done. */ rc = create_attributes_from_template(&head, template, template_size, NULL, PKCS11_FUNCTION_IMPORT, PKCS11_PROCESSING_IMPORT, PKCS11_CKO_UNDEFINED_ID); TEE_Free(template); template = NULL; if (rc) goto out; /* Set key check value attribute */ rc = set_check_value_attr(&head); if (rc) goto out; /* * Check target object attributes match target processing * Check target object attributes match token state */ rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT, head); if (rc) goto out; rc = check_created_attrs_against_token(session, head); if (rc) goto out; rc = check_access_attrs_against_token(session, head); if (rc) goto out; /* * At this stage the object is almost created: all its attributes are * referenced in @head, including the key value and are assumed * reliable. Now need to register it and get a handle for it. */ rc = create_object(session, head, &obj_handle); if (rc) goto out; /* * Now obj_handle (through the related struct pkcs11_object * instance) owns the serialized buffer that holds the object * attributes. We clear reference in head to NULL as the serializer * object is now referred from obj_handle. This allows smooth pass * through free at function exit. */ head = NULL; TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); out->memref.size = sizeof(obj_handle); DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32, session->handle, obj_handle); out: TEE_Free(template); TEE_Free(head); return rc; } enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); enum pkcs11_rc rc = PKCS11_CKR_OK; TEE_Param *ctrl = params; struct serialargs ctrlargs = { }; uint32_t object_handle = 0; struct pkcs11_session *session = NULL; struct pkcs11_object *object = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get_u32(&ctrlargs, &object_handle); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; object = pkcs11_handle2object(object_handle, session); if (!object) return PKCS11_CKR_OBJECT_HANDLE_INVALID; /* Only session objects can be destroyed during a read-only session */ if (get_bool(object->attributes, PKCS11_CKA_TOKEN) && !pkcs11_session_is_read_write(session)) { DMSG("Can't destroy persistent object"); return PKCS11_CKR_SESSION_READ_ONLY; } /* * Only public objects can be destroyed unless normal user is logged in */ rc = check_access_attrs_against_token(session, object->attributes); if (rc) return PKCS11_CKR_USER_NOT_LOGGED_IN; /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */ if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE)) return PKCS11_CKR_ACTION_PROHIBITED; destroy_object(session, object, false); DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32, session->handle, object_handle); return rc; } static void release_find_obj_context(struct pkcs11_find_objects *find_ctx) { if (!find_ctx) return; TEE_Free(find_ctx->attributes); TEE_Free(find_ctx->handles); TEE_Free(find_ctx); } static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx, uint32_t handle) { uint32_t *hdls = TEE_Realloc(find_ctx->handles, (find_ctx->count + 1) * sizeof(*hdls)); if (!hdls) return PKCS11_CKR_DEVICE_MEMORY; find_ctx->handles = hdls; *(find_ctx->handles + find_ctx->count) = handle; find_ctx->count++; return PKCS11_CKR_OK; } enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_session *sess = NULL; struct pkcs11_object_head *template = NULL; struct obj_attrs *req_attrs = NULL; struct pkcs11_object *obj = NULL; struct pkcs11_find_objects *find_ctx = NULL; struct handle_db *object_db = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } /* Search objects only if no operation is on-going */ if (session_is_active(session)) { rc = PKCS11_CKR_OPERATION_ACTIVE; goto out; } if (session->find_ctx) { EMSG("Active object search already in progress"); rc = PKCS11_CKR_FUNCTION_FAILED; goto out; } rc = sanitize_client_object(&req_attrs, template, sizeof(*template) + template->attrs_size, PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID); if (rc) goto out; /* Must zero init the structure */ find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO); if (!find_ctx) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } TEE_Free(template); template = NULL; switch (get_class(req_attrs)) { case PKCS11_CKO_UNDEFINED_ID: /* Unspecified class searches among data objects */ case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: case PKCS11_CKO_DATA: case PKCS11_CKO_CERTIFICATE: break; default: EMSG("Find object of class %s (%"PRIu32") is not supported", id2str_class(get_class(req_attrs)), get_class(req_attrs)); rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } /* * Scan all objects (sessions and persistent ones) and set a list of * candidates that match caller attributes. */ /* Scan all session objects first */ TAILQ_FOREACH(sess, get_session_list(session), link) { LIST_FOREACH(obj, &sess->object_list, link) { /* * Skip all token objects as they could be from * different token which the session does not have * access */ if (obj->token) continue; if (!attributes_match_reference(obj->attributes, req_attrs)) continue; rc = find_ctx_add(find_ctx, pkcs11_object2handle(obj, session)); if (rc) goto out; } } object_db = get_object_handle_db(session); /* Scan token objects */ LIST_FOREACH(obj, &session->token->object_list, link) { uint32_t handle = 0; bool new_load = false; if (!obj->attributes) { rc = load_persistent_object_attributes(obj); if (rc) { rc = PKCS11_CKR_GENERAL_ERROR; goto out; } new_load = true; } if (!obj->attributes || check_access_attrs_against_token(session, obj->attributes) || !attributes_match_reference(obj->attributes, req_attrs)) { if (new_load) release_persistent_object_attributes(obj); continue; } /* Resolve object handle for object */ handle = pkcs11_object2handle(obj, session); if (!handle) { handle = handle_get(object_db, obj); if (!handle) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } } rc = find_ctx_add(find_ctx, handle); if (rc) goto out; } find_ctx->attributes = req_attrs; req_attrs = NULL; session->find_ctx = find_ctx; find_ctx = NULL; rc = PKCS11_CKR_OK; out: TEE_Free(req_attrs); TEE_Free(template); release_find_obj_context(find_ctx); return rc; } enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_find_objects *ctx = NULL; uint8_t *out_handles = NULL; size_t out_count = 0; size_t count = 0; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; out_count = out->memref.size / sizeof(uint32_t); out_handles = out->memref.buffer; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; ctx = session->find_ctx; if (!ctx) return PKCS11_CKR_OPERATION_NOT_INITIALIZED; for (count = 0; ctx->next < ctx->count && count < out_count; ctx->next++, count++) TEE_MemMove(out_handles + count * sizeof(uint32_t), ctx->handles + ctx->next, sizeof(uint32_t)); /* Update output buffer according the number of handles provided */ out->memref.size = count * sizeof(uint32_t); DMSG("PKCS11 session %"PRIu32": finding objects", session->handle); return PKCS11_CKR_OK; } void release_session_find_obj_context(struct pkcs11_session *session) { release_find_obj_context(session->find_ctx); session->find_ctx = NULL; } enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (!session->find_ctx) return PKCS11_CKR_OPERATION_NOT_INITIALIZED; release_session_find_obj_context(session); return PKCS11_CKR_OK; } enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_object_head *template = NULL; struct pkcs11_object *obj = NULL; uint32_t object_handle = 0; char *cur = NULL; size_t len = 0; char *end = NULL; bool attr_sensitive = 0; bool attr_type_invalid = 0; bool buffer_too_small = 0; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } obj = pkcs11_handle2object(object_handle, session); if (!obj) { rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; goto out; } rc = check_access_attrs_against_token(session, obj->attributes); if (rc) { rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; goto out; } /* Iterate over attributes and set their values */ /* * 1. If the specified attribute (i.e., the attribute specified by the * type field) for the object cannot be revealed because the object is * sensitive or unextractable, then the ulValueLen field in that triple * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION. * * 2. Otherwise, if the specified value for the object is invalid (the * object does not possess such an attribute), then the ulValueLen field * in that triple is modified to hold the value * PKCS11_CK_UNAVAILABLE_INFORMATION. * * 3. Otherwise, if the pValue field has the value NULL_PTR, then the * ulValueLen field is modified to hold the exact length of the * specified attribute for the object. * * 4. Otherwise, if the length specified in ulValueLen is large enough * to hold the value of the specified attribute for the object, then * that attribute is copied into the buffer located at pValue, and the * ulValueLen field is modified to hold the exact length of the * attribute. * * 5. Otherwise, the ulValueLen field is modified to hold the value * PKCS11_CK_UNAVAILABLE_INFORMATION. */ cur = (char *)template + sizeof(struct pkcs11_object_head); end = cur + template->attrs_size; for (; cur < end; cur += len) { struct pkcs11_attribute_head *cli_ref = (void *)cur; struct pkcs11_attribute_head cli_head = { }; void *data_ptr = NULL; /* Make copy of header so that is aligned properly. */ TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head)); len = sizeof(*cli_ref) + cli_head.size; /* Treat hidden attributes as missing attributes */ if (attribute_is_hidden(&cli_head)) { cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; TEE_MemMove(&cli_ref->size, &cli_head.size, sizeof(cli_head.size)); attr_type_invalid = 1; continue; } /* We don't support getting value of indirect templates */ if (pkcs11_attr_has_indirect_attributes(cli_head.id)) { attr_type_invalid = 1; continue; } /* Check 1. */ if (!attribute_is_exportable(&cli_head, obj)) { cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; TEE_MemMove(&cli_ref->size, &cli_head.size, sizeof(cli_head.size)); attr_sensitive = 1; continue; } /* Get real data pointer from template data */ data_ptr = cli_head.size ? cli_ref->data : NULL; /* * We assume that if size is 0, pValue was NULL, so we return * the size of the required buffer for it (3., 4.) */ rc = get_attribute(obj->attributes, cli_head.id, data_ptr, &cli_head.size); /* Check 2. */ switch (rc) { case PKCS11_CKR_OK: break; case PKCS11_RV_NOT_FOUND: cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; attr_type_invalid = 1; break; case PKCS11_CKR_BUFFER_TOO_SMALL: if (data_ptr) buffer_too_small = 1; break; default: rc = PKCS11_CKR_GENERAL_ERROR; goto out; } TEE_MemMove(&cli_ref->size, &cli_head.size, sizeof(cli_head.size)); } /* * If case 1 applies to any of the requested attributes, then the call * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to * any of the requested attributes, then the call should return the * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the * requested attributes, then the call should return the value * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes * is applicable, Cryptoki may return any of them. Only if none of them * applies to any of the requested attributes will CKR_OK be returned. */ rc = PKCS11_CKR_OK; if (attr_sensitive) rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE; if (attr_type_invalid) rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; if (buffer_too_small) rc = PKCS11_CKR_BUFFER_TOO_SMALL; /* Move updated template to out buffer */ TEE_MemMove(out->memref.buffer, template, out->memref.size); DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32, session->handle, object_handle); out: TEE_Free(template); return rc; } enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; uint32_t object_handle = 0; struct pkcs11_object *obj = NULL; uint32_t obj_size = 0; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; obj = pkcs11_handle2object(object_handle, session); if (!obj) return PKCS11_CKR_OBJECT_HANDLE_INVALID; rc = check_access_attrs_against_token(session, obj->attributes); if (rc) return PKCS11_CKR_OBJECT_HANDLE_INVALID; if (out->memref.size != sizeof(uint32_t)) return PKCS11_CKR_ARGUMENTS_BAD; obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size + sizeof(struct obj_attrs); TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size)); return PKCS11_CKR_OK; } enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_object_head *template = NULL; size_t template_size = 0; struct pkcs11_object *obj = NULL; struct obj_attrs *head = NULL; struct obj_attrs *head_new = NULL; struct obj_attrs *head_old = NULL; uint32_t object_handle = 0; enum processing_func function = PKCS11_FUNCTION_MODIFY; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } obj = pkcs11_handle2object(object_handle, session); if (!obj) { rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; goto out; } /* Only session objects can be modified during a read-only session */ if (object_is_token(obj->attributes) && !pkcs11_session_is_read_write(session)) { DMSG("Can't modify persistent object in a RO session"); rc = PKCS11_CKR_SESSION_READ_ONLY; goto out; } /* * Only public objects can be modified unless normal user is logged in */ rc = check_access_attrs_against_token(session, obj->attributes); if (rc) { rc = PKCS11_CKR_USER_NOT_LOGGED_IN; goto out; } /* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */ if (!object_is_modifiable(obj->attributes)) { rc = PKCS11_CKR_ACTION_PROHIBITED; goto out; } template_size = sizeof(*template) + template->attrs_size; /* * Prepare a clean initial state (@head) for the template. Helps in * removing any duplicates or inconsistent values from the * template. */ rc = create_attributes_from_template(&head, template, template_size, NULL, function, PKCS11_CKM_UNDEFINED_ID, PKCS11_CKO_UNDEFINED_ID); if (rc) goto out; /* Check the attributes in @head to see if they are modifiable */ rc = check_attrs_against_modification(session, head, obj, function); if (rc) goto out; /* Create new object attributes to modify */ template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size; head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO); if (!head_new) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } TEE_MemMove(head_new, obj->attributes, template_size); /* * All checks complete. The attributes in @head have been checked and * can now be used to set/modify the object attributes. */ rc = modify_attributes_list(&head_new, head); if (rc) goto out; /* Set key check value attribute */ rc = set_check_value_attr(&head_new); if (rc) goto out; /* Update the object */ head_old = obj->attributes; obj->attributes = head_new; head_new = NULL; if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { rc = update_persistent_object_attributes(obj); if (rc) { obj->attributes = head_old; goto out; } } TEE_Free(head_old); DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32, session->handle, object_handle); out: TEE_Free(head); TEE_Free(head_new); TEE_Free(template); return rc; } enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_object_head *template = NULL; struct obj_attrs *head = NULL; struct obj_attrs *head_new = NULL; size_t template_size = 0; struct pkcs11_object *obj = NULL; uint32_t object_handle = 0; uint32_t obj_handle = 0; enum processing_func function = PKCS11_FUNCTION_COPY; enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; if (!client || ptypes != exp_pt || out->memref.size != sizeof(obj_handle)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } obj = pkcs11_handle2object(object_handle, session); if (!obj) { rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; goto out; } /* Only session objects can be modified during a read-only session */ if (object_is_token(obj->attributes) && !pkcs11_session_is_read_write(session)) { DMSG("Can't modify persistent object in a RO session"); rc = PKCS11_CKR_SESSION_READ_ONLY; goto out; } /* * Only public objects can be modified unless normal user is logged in */ rc = check_access_attrs_against_token(session, obj->attributes); if (rc) { rc = PKCS11_CKR_USER_NOT_LOGGED_IN; goto out; } /* Objects with PKCS11_CKA_COPYABLE as false can't be copied */ if (!object_is_copyable(obj->attributes)) { rc = PKCS11_CKR_ACTION_PROHIBITED; goto out; } template_size = sizeof(*template) + template->attrs_size; /* * Prepare a clean initial state (@head) for the template. Helps in * removing any duplicates or inconsistent values from the * template. */ rc = create_attributes_from_template(&head, template, template_size, NULL, function, PKCS11_CKM_UNDEFINED_ID, PKCS11_CKO_UNDEFINED_ID); if (rc) goto out; /* Check the attributes in @head to see if they are modifiable */ rc = check_attrs_against_modification(session, head, obj, function); if (rc) goto out; class = get_class(obj->attributes); if (class == PKCS11_CKO_SECRET_KEY || class == PKCS11_CKO_PRIVATE_KEY) { /* * If CKA_EXTRACTABLE attribute in passed template (@head) is * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also * change to CKA_FALSE in copied obj. So, add it to the * passed template. */ uint8_t bbool = 0; uint32_t size = sizeof(bbool); rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size); if (!rc && !bbool) { rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE, &bbool, sizeof(uint8_t)); if (rc) goto out; } rc = PKCS11_CKR_OK; } /* * All checks have passed. Create a copy of the serialized buffer which * holds the object attributes in @head_new for the new object */ template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size; head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO); if (!head_new) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } TEE_MemMove(head_new, obj->attributes, template_size); /* * Modify the copied attribute @head_new based on the template @head * given by the callee */ rc = modify_attributes_list(&head_new, head); if (rc) goto out; /* Set key check value attribute */ rc = set_check_value_attr(&head_new); if (rc) goto out; /* * At this stage the object is almost created: all its attributes are * referenced in @head_new, including the key value and are assumed * reliable. Now need to register it and get a handle for it. */ rc = create_object(session, head_new, &obj_handle); if (rc) goto out; /* * Now obj_handle (through the related struct pkcs11_object * instance) owns the serialized buffer that holds the object * attributes. We clear reference in head to NULL as the serializer * object is now referred from obj_handle. This allows smooth pass * through free at function exit. */ head_new = NULL; TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); out->memref.size = sizeof(obj_handle); DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32, session->handle, obj_handle); out: TEE_Free(head_new); TEE_Free(head); TEE_Free(template); return rc; } optee_os-4.3.0/ta/pkcs11/src/object.h000066400000000000000000000053731464416617300172730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_OBJECT_H #define PKCS11_TA_OBJECT_H #include #include #include struct ck_token; struct obj_attrs; struct pkcs11_client; struct pkcs11_session; /* * link: objects are referenced in a double-linked list * attributes: pointer to the serialized object attributes * key_handle: GPD TEE object handle if used in an operation * key_type: GPD TEE key type (shortcut used for processing) * token: associated token for the object * uuid: object UUID in the persistent database if a persistent object, or NULL * attribs_hdl: GPD TEE attributes handles if persistent object */ struct pkcs11_object { LIST_ENTRY(pkcs11_object) link; struct obj_attrs *attributes; TEE_ObjectHandle key_handle; uint32_t key_type; struct ck_token *token; TEE_UUID *uuid; TEE_ObjectHandle attribs_hdl; }; LIST_HEAD(object_list, pkcs11_object); struct pkcs11_object *pkcs11_handle2object(uint32_t client_handle, struct pkcs11_session *session); uint32_t pkcs11_object2handle(struct pkcs11_object *obj, struct pkcs11_session *session); struct pkcs11_object *create_token_object(struct obj_attrs *head, TEE_UUID *uuid, struct ck_token *token); enum pkcs11_rc create_object(void *session, struct obj_attrs *attributes, uint32_t *handle); void cleanup_persistent_object(struct pkcs11_object *obj, struct ck_token *token); void destroy_object(struct pkcs11_session *session, struct pkcs11_object *object, bool session_object_only); /* * Entry function called from the PKCS11 command parser */ enum pkcs11_rc entry_create_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); void release_session_find_obj_context(struct pkcs11_session *session); #endif /*PKCS11_TA_OBJECT_H*/ optee_os-4.3.0/ta/pkcs11/src/persistent_token.c000066400000000000000000000420411464416617300214110ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2020, Linaro Limited */ #include #include #include #include #include #include #include "attributes.h" #include "pkcs11_token.h" #include "pkcs11_helpers.h" #define PERSISTENT_OBJECT_ID_LEN 32 /* * Token persistent objects * * The persistent objects are each identified by a UUID. * The persistent object database stores the list of the UUIDs registered. For * each it is expected that a file of ID "UUID" is stored in the TA secure * storage. */ static TEE_Result get_db_file_name(struct ck_token *token, char *name, size_t size) { int n = snprintf(name, size, "token.db.%u", get_token_id(token)); if (n < 0 || (size_t)n >= size) return TEE_ERROR_SECURITY; else return TEE_SUCCESS; } static TEE_Result open_db_file(struct ck_token *token, TEE_ObjectHandle *out_hdl) { char file[PERSISTENT_OBJECT_ID_LEN] = { }; TEE_Result res = TEE_ERROR_GENERIC; res = get_db_file_name(token, file, sizeof(file)); if (res) return res; return TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file), TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE, out_hdl); } void update_persistent_db(struct ck_token *token) { TEE_Result res = TEE_ERROR_GENERIC; TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; res = open_db_file(token, &db_hdl); if (res) { EMSG("Failed to open token persistent db: %#"PRIx32, res); TEE_Panic(0); } res = TEE_WriteObjectData(db_hdl, token->db_main, sizeof(*token->db_main)); if (res) { EMSG("Failed to write to token persistent db: %#"PRIx32, res); TEE_Panic(0); } TEE_CloseObject(db_hdl); } static enum pkcs11_rc do_hash(uint32_t user, const uint8_t *pin, size_t pin_size, uint32_t salt, uint8_t hash[TEE_MAX_HASH_SIZE]) { TEE_Result res = TEE_SUCCESS; TEE_OperationHandle oh = TEE_HANDLE_NULL; size_t sz = TEE_MAX_HASH_SIZE; res = TEE_AllocateOperation(&oh, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); if (res) return tee2pkcs_error(res); TEE_DigestUpdate(oh, &user, sizeof(user)); TEE_DigestUpdate(oh, &salt, sizeof(salt)); res = TEE_DigestDoFinal(oh, pin, pin_size, hash, &sz); TEE_FreeOperation(oh); if (res) return PKCS11_CKR_GENERAL_ERROR; memset(hash + sz, 0, TEE_MAX_HASH_SIZE - sz); return PKCS11_CKR_OK; } enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, size_t pin_size, uint32_t *salt, uint8_t hash[TEE_MAX_HASH_SIZE]) { enum pkcs11_rc rc = PKCS11_CKR_OK; uint32_t s = 0; TEE_GenerateRandom(&s, sizeof(s)); if (!s) s++; rc = do_hash(user, pin, pin_size, s, hash); if (!rc) *salt = s; return rc; } enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, size_t pin_size, uint32_t salt, const uint8_t hash[TEE_MAX_HASH_SIZE]) { uint8_t tmp_hash[TEE_MAX_HASH_SIZE] = { 0 }; enum pkcs11_rc rc = PKCS11_CKR_OK; rc = do_hash(user, pin, pin_size, salt, tmp_hash); if (rc) return rc; if (buf_compare_ct(tmp_hash, hash, TEE_MAX_HASH_SIZE)) rc = PKCS11_CKR_PIN_INCORRECT; return rc; } #if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token) { TEE_Identity identity = { }; TEE_Result res = TEE_SUCCESS; res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, "gpd.client.identity", &identity); if (res != TEE_SUCCESS) { EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); return PKCS11_CKR_PIN_INVALID; } TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity)); token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; token->db_main->so_pin_salt = 0; return PKCS11_CKR_OK; } enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, enum pkcs11_user_type user_type, const uint8_t *pin, size_t pin_size) { TEE_Identity identity = { }; TEE_Result res = TEE_SUCCESS; uint32_t flags_clear = 0; uint32_t flags_set = 0; char *acl_string = NULL; char *uuid_str = NULL; assert(token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); if (!pin) { /* Use client identity */ res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, "gpd.client.identity", &identity); if (res != TEE_SUCCESS) { EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); return PKCS11_CKR_PIN_INVALID; } } else { /* Parse PIN ACL string: : */ acl_string = TEE_Malloc(pin_size + 1, TEE_MALLOC_FILL_ZERO); if (!acl_string) return PKCS11_CKR_DEVICE_MEMORY; TEE_MemMove(acl_string, pin, pin_size); uuid_str = strstr(acl_string, ":"); if (uuid_str) uuid_str++; if (strcmp(PKCS11_AUTH_TEE_IDENTITY_PUBLIC, acl_string) == 0) { identity.login = TEE_LOGIN_PUBLIC; } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_USER) == acl_string) { identity.login = TEE_LOGIN_USER; } else if (strstr(acl_string, PKCS11_AUTH_TEE_IDENTITY_GROUP) == acl_string) { identity.login = TEE_LOGIN_GROUP; } else { EMSG("Invalid PIN ACL string - login"); TEE_Free(acl_string); return PKCS11_CKR_PIN_INVALID; } if (identity.login != TEE_LOGIN_PUBLIC) { if (!uuid_str) { EMSG("Invalid PIN ACL string - colon"); TEE_Free(acl_string); return PKCS11_CKR_PIN_INVALID; } res = tee_uuid_from_str(&identity.uuid, uuid_str); if (res) { EMSG("Invalid PIN ACL string - client id"); TEE_Free(acl_string); return PKCS11_CKR_PIN_INVALID; } } TEE_Free(acl_string); } switch (user_type) { case PKCS11_CKU_SO: token->db_main->so_pin_count = 0; token->db_main->so_pin_salt = 0; flags_clear = PKCS11_CKFT_SO_PIN_COUNT_LOW | PKCS11_CKFT_SO_PIN_FINAL_TRY | PKCS11_CKFT_SO_PIN_LOCKED | PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; TEE_MemMove(&token->db_main->so_identity, &identity, sizeof(identity)); break; case PKCS11_CKU_USER: token->db_main->user_pin_count = 0; token->db_main->user_pin_salt = 0; flags_clear = PKCS11_CKFT_USER_PIN_COUNT_LOW | PKCS11_CKFT_USER_PIN_FINAL_TRY | PKCS11_CKFT_USER_PIN_LOCKED | PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; flags_set = PKCS11_CKFT_USER_PIN_INITIALIZED; TEE_MemMove(&token->db_main->user_identity, &identity, sizeof(identity)); break; default: return PKCS11_CKR_FUNCTION_FAILED; } token->db_main->flags &= ~flags_clear; token->db_main->flags |= flags_set; return PKCS11_CKR_OK; } enum pkcs11_rc verify_identity_auth(struct ck_token *token, enum pkcs11_user_type user_type) { TEE_Identity identity = { }; TEE_Result res = TEE_SUCCESS; assert(token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH); res = TEE_GetPropertyAsIdentity(TEE_PROPSET_CURRENT_CLIENT, "gpd.client.identity", &identity); if (res != TEE_SUCCESS) { EMSG("TEE_GetPropertyAsIdentity: returned %#"PRIx32, res); return PKCS11_CKR_PIN_INVALID; } if (user_type == PKCS11_CKU_SO) { if (TEE_MemCompare(&token->db_main->so_identity, &identity, sizeof(identity))) return PKCS11_CKR_PIN_INCORRECT; } else if (user_type == PKCS11_CKU_USER) { if (TEE_MemCompare(&token->db_main->user_identity, &identity, sizeof(identity))) return PKCS11_CKR_PIN_INCORRECT; } else { return PKCS11_CKR_PIN_INCORRECT; } return PKCS11_CKR_OK; } #endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ /* * Release resources relate to persistent database */ void close_persistent_db(struct ck_token *token __unused) { } static int get_persistent_obj_idx(struct ck_token *token, TEE_UUID *uuid) { size_t i = 0; if (!uuid) return -1; for (i = 0; i < token->db_objs->count; i++) if (!TEE_MemCompare(token->db_objs->uuids + i, uuid, sizeof(TEE_UUID))) return i; return -1; } /* UUID for persistent object */ enum pkcs11_rc create_object_uuid(struct ck_token *token, struct pkcs11_object *obj) { assert(!obj->uuid); obj->uuid = TEE_Malloc(sizeof(TEE_UUID), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!obj->uuid) return PKCS11_CKR_DEVICE_MEMORY; obj->token = token; do { TEE_GenerateRandom(obj->uuid, sizeof(TEE_UUID)); } while (get_persistent_obj_idx(token, obj->uuid) >= 0); return PKCS11_CKR_OK; } void destroy_object_uuid(struct ck_token *token __maybe_unused, struct pkcs11_object *obj) { assert(get_persistent_obj_idx(token, obj->uuid) < 0); TEE_Free(obj->uuid); obj->uuid = NULL; } enum pkcs11_rc get_persistent_objects_list(struct ck_token *token, TEE_UUID *array, size_t *size) { size_t out_size = *size; *size = token->db_objs->count * sizeof(TEE_UUID); if (out_size < *size) return PKCS11_CKR_BUFFER_TOO_SMALL; if (array) TEE_MemMove(array, token->db_objs->uuids, *size); return PKCS11_CKR_OK; } enum pkcs11_rc unregister_persistent_object(struct ck_token *token, TEE_UUID *uuid) { TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; struct token_persistent_objs *ptr = NULL; TEE_Result res = TEE_ERROR_GENERIC; int count = 0; int idx = 0; if (!uuid) return PKCS11_CKR_OK; idx = get_persistent_obj_idx(token, uuid); if (idx < 0) { DMSG("Cannot unregister an invalid persistent object"); return PKCS11_RV_NOT_FOUND; } ptr = TEE_Malloc(sizeof(struct token_persistent_objs) + ((token->db_objs->count - 1) * sizeof(TEE_UUID)), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!ptr) return PKCS11_CKR_DEVICE_MEMORY; res = open_db_file(token, &db_hdl); if (res) goto out; res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), TEE_DATA_SEEK_SET); if (res) { DMSG("Failed to read database"); goto out; } TEE_MemMove(ptr, token->db_objs, sizeof(struct token_persistent_objs) + idx * sizeof(TEE_UUID)); ptr->count--; count = ptr->count - idx; TEE_MemMove(&ptr->uuids[idx], &token->db_objs->uuids[idx + 1], count * sizeof(TEE_UUID)); res = TEE_WriteObjectData(db_hdl, ptr, sizeof(struct token_persistent_objs) + ptr->count * sizeof(TEE_UUID)); if (res) DMSG("Failed to update database"); TEE_Free(token->db_objs); token->db_objs = ptr; ptr = NULL; out: TEE_CloseObject(db_hdl); TEE_Free(ptr); return tee2pkcs_error(res); } enum pkcs11_rc register_persistent_object(struct ck_token *token, TEE_UUID *uuid) { TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; TEE_Result res = TEE_ERROR_GENERIC; void *ptr = NULL; size_t size = 0; int count = 0; if (get_persistent_obj_idx(token, uuid) >= 0) TEE_Panic(0); count = token->db_objs->count; ptr = TEE_Realloc(token->db_objs, sizeof(struct token_persistent_objs) + ((count + 1) * sizeof(TEE_UUID))); if (!ptr) return PKCS11_CKR_DEVICE_MEMORY; token->db_objs = ptr; TEE_MemMove(token->db_objs->uuids + count, uuid, sizeof(TEE_UUID)); size = sizeof(struct token_persistent_main) + sizeof(struct token_persistent_objs) + count * sizeof(TEE_UUID); res = open_db_file(token, &db_hdl); if (res) goto out; res = TEE_TruncateObjectData(db_hdl, size + sizeof(TEE_UUID)); if (res) goto out; res = TEE_SeekObjectData(db_hdl, sizeof(struct token_persistent_main), TEE_DATA_SEEK_SET); if (res) goto out; token->db_objs->count++; res = TEE_WriteObjectData(db_hdl, token->db_objs, sizeof(struct token_persistent_objs) + token->db_objs->count * sizeof(TEE_UUID)); if (res) token->db_objs->count--; out: TEE_CloseObject(db_hdl); return tee2pkcs_error(res); } enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; TEE_ObjectHandle hdl = obj->attribs_hdl; TEE_ObjectInfo info = { }; struct obj_attrs *attr = NULL; size_t read_bytes = 0; if (obj->attributes) return PKCS11_CKR_OK; if (hdl == TEE_HANDLE_NULL) { res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, obj->uuid, sizeof(*obj->uuid), TEE_DATA_FLAG_ACCESS_READ, &hdl); if (res) { EMSG("OpenPersistent failed %#"PRIx32, res); return tee2pkcs_error(res); } } TEE_MemFill(&info, 0, sizeof(info)); res = TEE_GetObjectInfo1(hdl, &info); if (res) { EMSG("GetObjectInfo failed %#"PRIx32, res); rc = tee2pkcs_error(res); goto out; } attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO); if (!attr) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes); if (!res) { res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET); if (res) EMSG("Seek to 0 failed %#"PRIx32, res); } if (res) { rc = tee2pkcs_error(res); EMSG("Read %zu bytes, failed %#"PRIx32, read_bytes, res); goto out; } if (read_bytes != info.dataSize) { EMSG("Read %zu bytes, expected %zu", read_bytes, info.dataSize); rc = PKCS11_CKR_GENERAL_ERROR; goto out; } obj->attributes = attr; attr = NULL; rc = PKCS11_CKR_OK; out: TEE_Free(attr); /* Close object only if it was open from this function */ if (obj->attribs_hdl == TEE_HANDLE_NULL) TEE_CloseObject(hdl); return rc; } void release_persistent_object_attributes(struct pkcs11_object *obj) { TEE_Free(obj->attributes); obj->attributes = NULL; } enum pkcs11_rc update_persistent_object_attributes(struct pkcs11_object *obj) { TEE_Result res = TEE_ERROR_GENERIC; TEE_ObjectHandle hdl = TEE_HANDLE_NULL; uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_WRITE; size_t size = 0; assert(obj && obj->attributes); res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, obj->uuid, sizeof(*obj->uuid), tee_obj_flags, &hdl); if (res) { EMSG("OpenPersistent failed %#"PRIx32, res); return tee2pkcs_error(res); } size = sizeof(struct obj_attrs) + obj->attributes->attrs_size; res = TEE_WriteObjectData(hdl, obj->attributes, size); if (res) goto out; res = TEE_TruncateObjectData(hdl, size); out: TEE_CloseObject(hdl); return tee2pkcs_error(res); } /* * Return the token instance, either initialized from reset or initialized * from the token persistent state if found. */ struct ck_token *init_persistent_db(unsigned int token_id) { struct ck_token *token = get_token(token_id); TEE_Result res = TEE_ERROR_GENERIC; TEE_ObjectHandle db_hdl = TEE_HANDLE_NULL; /* Copy persistent database: main db and object db */ struct token_persistent_main *db_main = NULL; struct token_persistent_objs *db_objs = NULL; void *ptr = NULL; if (!token) return NULL; LIST_INIT(&token->object_list); db_main = TEE_Malloc(sizeof(*db_main), TEE_MALLOC_FILL_ZERO); db_objs = TEE_Malloc(sizeof(*db_objs), TEE_MALLOC_FILL_ZERO); if (!db_main || !db_objs) goto error; res = open_db_file(token, &db_hdl); if (res == TEE_SUCCESS) { size_t size = 0; size_t idx = 0; IMSG("PKCS11 token %u: load db", token_id); size = sizeof(*db_main); res = TEE_ReadObjectData(db_hdl, db_main, size, &size); if (res || size != sizeof(*db_main)) TEE_Panic(0); size = sizeof(*db_objs); res = TEE_ReadObjectData(db_hdl, db_objs, size, &size); if (res || size != sizeof(*db_objs)) TEE_Panic(0); if (db_objs->count > 0) { size += db_objs->count * sizeof(TEE_UUID); ptr = TEE_Realloc(db_objs, size); if (!ptr) goto error; db_objs = ptr; size -= sizeof(*db_objs); res = TEE_ReadObjectData(db_hdl, db_objs->uuids, size, &size); if (res || size != (db_objs->count * sizeof(TEE_UUID))) TEE_Panic(0); } for (idx = 0; idx < db_objs->count; idx++) { /* Create an empty object instance */ struct pkcs11_object *obj = NULL; TEE_UUID *uuid = NULL; uuid = TEE_Malloc(sizeof(TEE_UUID), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!uuid) goto error; TEE_MemMove(uuid, &db_objs->uuids[idx], sizeof(*uuid)); obj = create_token_object(NULL, uuid, token); if (!obj) TEE_Panic(0); LIST_INSERT_HEAD(&token->object_list, obj, link); } } else if (res == TEE_ERROR_ITEM_NOT_FOUND) { char file[PERSISTENT_OBJECT_ID_LEN] = { }; IMSG("PKCS11 token %u: init db", token_id); TEE_MemFill(db_main, 0, sizeof(*db_main)); TEE_MemFill(db_main->label, '*', sizeof(db_main->label)); db_main->flags = PKCS11_CKFT_SO_PIN_TO_BE_CHANGED | PKCS11_CKFT_USER_PIN_TO_BE_CHANGED | PKCS11_CKFT_RNG | PKCS11_CKFT_LOGIN_REQUIRED; res = get_db_file_name(token, file, sizeof(file)); if (res) TEE_Panic(0); /* * Object stores persistent state + persistent object * references. */ res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, file, sizeof(file), TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE, TEE_HANDLE_NULL, db_main, sizeof(*db_main), &db_hdl); if (res) { EMSG("Failed to create db: %#"PRIx32, res); goto error; } res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) + sizeof(*db_objs)); if (res) TEE_Panic(0); res = TEE_SeekObjectData(db_hdl, sizeof(*db_main), TEE_DATA_SEEK_SET); if (res) TEE_Panic(0); db_objs->count = 0; res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs)); if (res) TEE_Panic(0); } else { goto error; } token->db_main = db_main; token->db_objs = db_objs; TEE_CloseObject(db_hdl); return token; error: TEE_Free(db_main); TEE_Free(db_objs); if (db_hdl != TEE_HANDLE_NULL) TEE_CloseObject(db_hdl); return NULL; } optee_os-4.3.0/ta/pkcs11/src/pkcs11_attributes.c000066400000000000000000002326221464416617300213670ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include "attributes.h" #include "handle.h" #include "pkcs11_attributes.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "sanitize_object.h" #include "serializer.h" #include "token_capabilities.h" static uint32_t pkcs11_func2ckfm(enum processing_func function) { switch (function) { case PKCS11_FUNCTION_DIGEST: return PKCS11_CKFM_DIGEST; case PKCS11_FUNCTION_GENERATE: return PKCS11_CKFM_GENERATE; case PKCS11_FUNCTION_GENERATE_PAIR: return PKCS11_CKFM_GENERATE_KEY_PAIR; case PKCS11_FUNCTION_DERIVE: return PKCS11_CKFM_DERIVE; case PKCS11_FUNCTION_WRAP: return PKCS11_CKFM_WRAP; case PKCS11_FUNCTION_UNWRAP: return PKCS11_CKFM_UNWRAP; case PKCS11_FUNCTION_ENCRYPT: return PKCS11_CKFM_ENCRYPT; case PKCS11_FUNCTION_DECRYPT: return PKCS11_CKFM_DECRYPT; case PKCS11_FUNCTION_SIGN: return PKCS11_CKFM_SIGN; case PKCS11_FUNCTION_VERIFY: return PKCS11_CKFM_VERIFY; case PKCS11_FUNCTION_SIGN_RECOVER: return PKCS11_CKFM_SIGN_RECOVER; case PKCS11_FUNCTION_VERIFY_RECOVER: return PKCS11_CKFM_VERIFY_RECOVER; default: return 0; } } enum pkcs11_rc check_mechanism_against_processing(struct pkcs11_session *session, enum pkcs11_mechanism_id mechanism_type, enum processing_func function, enum processing_step step) { bool allowed = false; switch (step) { case PKCS11_FUNC_STEP_INIT: switch (function) { case PKCS11_FUNCTION_IMPORT: case PKCS11_FUNCTION_COPY: case PKCS11_FUNCTION_MODIFY: case PKCS11_FUNCTION_DESTROY: return PKCS11_CKR_OK; default: break; } /* * Check that the returned PKCS11_CKFM_* flag from * pkcs11_func2ckfm() is among the ones from * mechanism_supported_flags(). */ allowed = mechanism_supported_flags(mechanism_type) & pkcs11_func2ckfm(function); break; case PKCS11_FUNC_STEP_ONESHOT: if (session->processing->always_authen && !session->processing->relogged) return PKCS11_CKR_USER_NOT_LOGGED_IN; if (session->processing->step == PKCS11_FUNC_STEP_UPDATE || session->processing->step == PKCS11_FUNC_STEP_FINAL) { EMSG("Cannot perform one-shot on active processing"); return PKCS11_CKR_OPERATION_ACTIVE; } allowed = true; break; case PKCS11_FUNC_STEP_UPDATE: if (session->processing->always_authen && !session->processing->relogged) return PKCS11_CKR_USER_NOT_LOGGED_IN; if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT || session->processing->step == PKCS11_FUNC_STEP_FINAL) { EMSG("Cannot perform update on finalized processing"); return PKCS11_CKR_OPERATION_ACTIVE; } allowed = !mechanism_is_one_shot_only(mechanism_type); break; case PKCS11_FUNC_STEP_UPDATE_KEY: assert(function == PKCS11_FUNCTION_DIGEST); if (session->processing->always_authen && !session->processing->relogged) return PKCS11_CKR_USER_NOT_LOGGED_IN; allowed = true; break; case PKCS11_FUNC_STEP_FINAL: if (session->processing->always_authen && !session->processing->relogged) return PKCS11_CKR_USER_NOT_LOGGED_IN; if (session->processing->step == PKCS11_FUNC_STEP_ONESHOT) { EMSG("Cannot perform final on oneshot processing"); return PKCS11_CKR_OPERATION_ACTIVE; } return PKCS11_CKR_OK; default: TEE_Panic(step); break; } if (!allowed) { EMSG("Processing %#x/%s not permitted (%u/%u)", (unsigned int)mechanism_type, id2str_proc(mechanism_type), function, step); return PKCS11_CKR_MECHANISM_INVALID; } return PKCS11_CKR_OK; } /* * Object default boolean attributes as per PKCS#11 */ static uint8_t *pkcs11_object_default_boolprop(uint32_t attribute) { static const uint8_t bool_true = 1; static const uint8_t bool_false; switch (attribute) { /* As per PKCS#11 default value */ case PKCS11_CKA_MODIFIABLE: case PKCS11_CKA_COPYABLE: case PKCS11_CKA_DESTROYABLE: return (uint8_t *)&bool_true; case PKCS11_CKA_TOKEN: case PKCS11_CKA_PRIVATE: case PKCS11_CKA_WRAP_WITH_TRUSTED: case PKCS11_CKA_ALWAYS_AUTHENTICATE: case PKCS11_CKA_SENSITIVE: return (uint8_t *)&bool_false; /* Token specific default value */ case PKCS11_CKA_SIGN: case PKCS11_CKA_VERIFY: case PKCS11_CKA_DERIVE: case PKCS11_CKA_ENCRYPT: case PKCS11_CKA_DECRYPT: case PKCS11_CKA_SIGN_RECOVER: case PKCS11_CKA_VERIFY_RECOVER: case PKCS11_CKA_WRAP: case PKCS11_CKA_UNWRAP: case PKCS11_CKA_EXTRACTABLE: case PKCS11_CKA_TRUSTED: return (uint8_t *)&bool_false; default: DMSG("No default for boolprop attribute %#"PRIx32, attribute); return NULL; } } /* * Object expects several boolean attributes to be set to a default value * or to a validate client configuration value. This function append the input * attribute (id/size/value) in the serialized object. */ static enum pkcs11_rc pkcs11_import_object_boolprop(struct obj_attrs **out, struct obj_attrs *templ, uint32_t attribute) { enum pkcs11_rc rc = PKCS11_CKR_OK; uint8_t bbool = 0; uint32_t size = sizeof(uint8_t); void *attr = NULL; rc = get_attribute(templ, attribute, &bbool, &size); if (rc) { if (rc != PKCS11_RV_NOT_FOUND) return rc; attr = pkcs11_object_default_boolprop(attribute); if (!attr) return PKCS11_CKR_TEMPLATE_INCOMPLETE; } else { attr = &bbool; } /* Boolean attributes are 1byte in the ABI, no alignment issue */ return add_attribute(out, attribute, attr, sizeof(uint8_t)); } static enum pkcs11_rc set_mandatory_boolprops(struct obj_attrs **out, struct obj_attrs *temp, uint32_t const *bp, size_t bp_count) { enum pkcs11_rc rc = PKCS11_CKR_OK; size_t n = 0; for (n = 0; n < bp_count; n++) { rc = pkcs11_import_object_boolprop(out, temp, bp[n]); if (rc) return rc; } return rc; } static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out, struct obj_attrs *temp, uint32_t const *attrs, size_t attrs_count) { enum pkcs11_rc rc = PKCS11_CKR_OK; size_t n = 0; for (n = 0; n < attrs_count; n++) { uint32_t size = 0; void *value = NULL; if (get_attribute_ptr(temp, attrs[n], &value, &size)) return PKCS11_CKR_TEMPLATE_INCOMPLETE; rc = add_attribute(out, attrs[n], value, size); if (rc) return rc; } return rc; } static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id __maybe_unused, void **value, uint32_t *size) { /* should have been taken care of already */ assert(!pkcs11_attr_is_boolean(id)); /* All other attributes have an empty default value */ *value = NULL; *size = 0; return PKCS11_CKR_OK; } static enum pkcs11_rc set_optional_attributes_with_def(struct obj_attrs **out, struct obj_attrs *temp, uint32_t const *attrs, size_t attrs_count, bool default_to_null) { enum pkcs11_rc rc = PKCS11_CKR_OK; size_t n = 0; for (n = 0; n < attrs_count; n++) { uint32_t size = 0; void *value = NULL; rc = get_attribute_ptr(temp, attrs[n], &value, &size); if (rc == PKCS11_RV_NOT_FOUND) { if (default_to_null) { rc = get_default_value(attrs[n], &value, &size); } else { rc = PKCS11_CKR_OK; continue; } } if (rc) return rc; rc = add_attribute(out, attrs[n], value, size); if (rc) return rc; } return rc; } static enum pkcs11_rc set_attributes_opt_or_null(struct obj_attrs **out, struct obj_attrs *temp, uint32_t const *attrs, size_t attrs_count) { return set_optional_attributes_with_def(out, temp, attrs, attrs_count, true /* defaults to empty */); } static enum pkcs11_rc set_optional_attributes(struct obj_attrs **out, struct obj_attrs *temp, uint32_t const *attrs, size_t attrs_count) { return set_optional_attributes_with_def(out, temp, attrs, attrs_count, false /* no default value */); } /* * Below are listed the mandated or optional expected attributes for * PKCS#11 storage objects. * * Note: boolprops (mandated boolean attributes) PKCS11_CKA_ALWAYS_SENSITIVE, * and PKCS11_CKA_NEVER_EXTRACTABLE are set by the token, not provided * in the client template. */ /* PKCS#11 specification for any object (session/token) of the storage */ static const uint32_t any_object_boolprops[] = { PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE, PKCS11_CKA_MODIFIABLE, PKCS11_CKA_COPYABLE, PKCS11_CKA_DESTROYABLE, }; static const uint32_t any_object_opt_or_null[] = { PKCS11_CKA_LABEL, }; /* PKCS#11 specification for raw data object (+any_object_xxx) */ const uint32_t raw_data_opt_or_null[] = { PKCS11_CKA_OBJECT_ID, PKCS11_CKA_APPLICATION, PKCS11_CKA_VALUE, }; /* PKCS#11 specification for certificate object (+pkcs11_any_object_xxx) */ static const uint32_t pkcs11_certificate_mandated[] = { PKCS11_CKA_CERTIFICATE_TYPE, }; static const uint32_t pkcs11_certificate_boolprops[] = { PKCS11_CKA_TRUSTED, }; static const uint32_t pkcs11_certificate_optional[] = { PKCS11_CKA_CERTIFICATE_CATEGORY, PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, PKCS11_CKA_PUBLIC_KEY_INFO, #ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE /* Consider KCV attribute only when supported */ PKCS11_CKA_CHECK_VALUE, #endif }; /* * PKCS#11 specification for X.509 certificate object (+pkcs11_certificate_xxx) */ static const uint32_t pkcs11_x509_certificate_mandated[] = { PKCS11_CKA_SUBJECT, }; static const uint32_t pkcs11_x509_certificate_optional[] = { PKCS11_CKA_ID, PKCS11_CKA_ISSUER, PKCS11_CKA_SERIAL_NUMBER, PKCS11_CKA_VALUE, PKCS11_CKA_URL, PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY, PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY, PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, PKCS11_CKA_NAME_HASH_ALGORITHM, }; /* PKCS#11 specification for any key object (+any_object_xxx) */ static const uint32_t any_key_boolprops[] = { PKCS11_CKA_DERIVE, }; static const uint32_t any_key_opt_or_null[] = { PKCS11_CKA_ID, PKCS11_CKA_START_DATE, PKCS11_CKA_END_DATE, }; static const uint32_t any_key_optional[] = { PKCS11_CKA_ALLOWED_MECHANISMS, }; /* PKCS#11 specification for any symmetric key (+any_key_xxx) */ static const uint32_t symm_key_boolprops[] = { PKCS11_CKA_ENCRYPT, PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_VERIFY, PKCS11_CKA_WRAP, PKCS11_CKA_UNWRAP, PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE, PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_TRUSTED, }; static const uint32_t symm_key_opt_or_null[] = { PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_UNWRAP_TEMPLATE, PKCS11_CKA_DERIVE_TEMPLATE, PKCS11_CKA_VALUE, }; static const uint32_t symm_key_optional[] = { PKCS11_CKA_VALUE_LEN, #ifdef CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE /* Consider KCV attribute only when supported */ PKCS11_CKA_CHECK_VALUE, #endif }; /* PKCS#11 specification for any asymmetric public key (+any_key_xxx) */ static const uint32_t public_key_boolprops[] = { PKCS11_CKA_ENCRYPT, PKCS11_CKA_VERIFY, PKCS11_CKA_VERIFY_RECOVER, PKCS11_CKA_WRAP, PKCS11_CKA_TRUSTED, }; static const uint32_t public_key_mandated[] = { }; static const uint32_t public_key_opt_or_null[] = { PKCS11_CKA_SUBJECT, PKCS11_CKA_WRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO, }; /* PKCS#11 specification for any asymmetric private key (+any_key_xxx) */ static const uint32_t private_key_boolprops[] = { PKCS11_CKA_DECRYPT, PKCS11_CKA_SIGN, PKCS11_CKA_SIGN_RECOVER, PKCS11_CKA_UNWRAP, PKCS11_CKA_SENSITIVE, PKCS11_CKA_EXTRACTABLE, PKCS11_CKA_WRAP_WITH_TRUSTED, PKCS11_CKA_ALWAYS_AUTHENTICATE, }; static const uint32_t private_key_mandated[] = { }; static const uint32_t private_key_opt_or_null[] = { PKCS11_CKA_SUBJECT, PKCS11_CKA_UNWRAP_TEMPLATE, PKCS11_CKA_PUBLIC_KEY_INFO, }; /* PKCS#11 specification for any RSA key (+public/private_key_xxx) */ static const uint32_t rsa_pub_key_gen_mand[] = { PKCS11_CKA_MODULUS_BITS, }; static const uint32_t rsa_pub_key_create_mand[] = { PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT, }; static const uint32_t rsa_pub_key_gen_opt_or_null[] = { PKCS11_CKA_PUBLIC_EXPONENT, }; static const uint32_t rsa_priv_key_opt_or_null[] = { PKCS11_CKA_MODULUS, PKCS11_CKA_PUBLIC_EXPONENT, PKCS11_CKA_PRIVATE_EXPONENT, PKCS11_CKA_PRIME_1, PKCS11_CKA_PRIME_2, PKCS11_CKA_EXPONENT_1, PKCS11_CKA_EXPONENT_2, PKCS11_CKA_COEFFICIENT, }; /* PKCS#11 specification for any EC key (+public/private_key_xxx) */ static const uint32_t ec_public_key_mandated[] = { PKCS11_CKA_EC_PARAMS, }; static const uint32_t ec_public_key_opt_or_null[] = { PKCS11_CKA_EC_POINT, }; static const uint32_t ec_private_key_mandated[] = { }; static const uint32_t ec_private_key_opt_or_null[] = { PKCS11_CKA_EC_PARAMS, PKCS11_CKA_VALUE, }; static const uint32_t eddsa_private_key_opt_or_null[] = { PKCS11_CKA_EC_PARAMS, PKCS11_CKA_VALUE, PKCS11_CKA_EC_POINT, }; static enum pkcs11_rc create_storage_attributes(struct obj_attrs **out, struct obj_attrs *temp) { enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; enum pkcs11_rc rc = PKCS11_CKR_OK; rc = init_attributes_head(out); if (rc) return rc; /* Object class is mandatory */ class = get_class(temp); if (class == PKCS11_CKO_UNDEFINED_ID) { EMSG("Class attribute not found"); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = add_attribute(out, PKCS11_CKA_CLASS, &class, sizeof(uint32_t)); if (rc) return rc; rc = set_mandatory_boolprops(out, temp, any_object_boolprops, ARRAY_SIZE(any_object_boolprops)); if (rc) return rc; return set_attributes_opt_or_null(out, temp, any_object_opt_or_null, ARRAY_SIZE(any_object_opt_or_null)); } static enum pkcs11_rc create_genkey_attributes(struct obj_attrs **out, struct obj_attrs *temp) { uint32_t type = PKCS11_CKO_UNDEFINED_ID; enum pkcs11_rc rc = PKCS11_CKR_OK; rc = create_storage_attributes(out, temp); if (rc) return rc; type = get_key_type(temp); if (type == PKCS11_CKK_UNDEFINED_ID) { EMSG("Key type attribute not found"); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = add_attribute(out, PKCS11_CKA_KEY_TYPE, &type, sizeof(uint32_t)); if (rc) return rc; rc = set_mandatory_boolprops(out, temp, any_key_boolprops, ARRAY_SIZE(any_key_boolprops)); if (rc) return rc; rc = set_attributes_opt_or_null(out, temp, any_key_opt_or_null, ARRAY_SIZE(any_key_opt_or_null)); if (rc) return rc; return set_optional_attributes(out, temp, any_key_optional, ARRAY_SIZE(any_key_optional)); } static enum pkcs11_rc create_symm_key_attributes(struct obj_attrs **out, struct obj_attrs *temp) { enum pkcs11_rc rc = PKCS11_CKR_OK; assert(get_class(temp) == PKCS11_CKO_SECRET_KEY); rc = create_genkey_attributes(out, temp); if (rc) return rc; assert(get_class(*out) == PKCS11_CKO_SECRET_KEY); switch (get_key_type(*out)) { case PKCS11_CKK_GENERIC_SECRET: case PKCS11_CKK_AES: case PKCS11_CKK_MD5_HMAC: case PKCS11_CKK_SHA_1_HMAC: case PKCS11_CKK_SHA256_HMAC: case PKCS11_CKK_SHA384_HMAC: case PKCS11_CKK_SHA512_HMAC: case PKCS11_CKK_SHA224_HMAC: break; default: EMSG("Invalid key type %#"PRIx32"/%s", get_key_type(*out), id2str_key_type(get_key_type(*out))); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = set_mandatory_boolprops(out, temp, symm_key_boolprops, ARRAY_SIZE(symm_key_boolprops)); if (rc) return rc; rc = set_attributes_opt_or_null(out, temp, symm_key_opt_or_null, ARRAY_SIZE(symm_key_opt_or_null)); if (rc) return rc; return set_optional_attributes(out, temp, symm_key_optional, ARRAY_SIZE(symm_key_optional)); } static enum pkcs11_rc create_data_attributes(struct obj_attrs **out, struct obj_attrs *temp) { enum pkcs11_rc rc = PKCS11_CKR_OK; assert(get_class(temp) == PKCS11_CKO_DATA); rc = create_storage_attributes(out, temp); if (rc) return rc; assert(get_class(*out) == PKCS11_CKO_DATA); return set_attributes_opt_or_null(out, temp, raw_data_opt_or_null, ARRAY_SIZE(raw_data_opt_or_null)); } static enum pkcs11_rc create_certificate_attributes(struct obj_attrs **out, struct obj_attrs *temp) { uint32_t const *mandated = NULL; uint32_t const *optional = NULL; size_t mandated_count = 0; size_t optional_count = 0; void *attr_value = NULL; uint32_t attr_size = 0; uint32_t default_cert_category = PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED; uint32_t default_name_hash_alg = PKCS11_CKM_SHA_1; uint32_t cert_category = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; assert(get_class(temp) == PKCS11_CKO_CERTIFICATE); rc = create_storage_attributes(out, temp); if (rc) return rc; assert(get_class(*out) == PKCS11_CKO_CERTIFICATE); rc = set_mandatory_boolprops(out, temp, pkcs11_certificate_boolprops, ARRAY_SIZE(pkcs11_certificate_boolprops)); if (rc) return rc; rc = set_mandatory_attributes(out, temp, pkcs11_certificate_mandated, ARRAY_SIZE(pkcs11_certificate_mandated)); if (rc) return rc; rc = set_optional_attributes(out, temp, pkcs11_certificate_optional, ARRAY_SIZE(pkcs11_certificate_optional)); if (rc) return rc; switch (get_certificate_type(*out)) { case PKCS11_CKC_X_509: mandated = pkcs11_x509_certificate_mandated; optional = pkcs11_x509_certificate_optional; mandated_count = ARRAY_SIZE(pkcs11_x509_certificate_mandated); optional_count = ARRAY_SIZE(pkcs11_x509_certificate_optional); break; default: EMSG("Invalid certificate type %#"PRIx32"/%s", get_certificate_type(*out), id2str_certificate_type(get_certificate_type(*out))); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = set_mandatory_attributes(out, temp, mandated, mandated_count); if (rc) return rc; rc = set_optional_attributes(out, temp, optional, optional_count); if (rc) return rc; attr_size = 0; rc = get_attribute_ptr(*out, PKCS11_CKA_CERTIFICATE_CATEGORY, &attr_value, &attr_size); if (rc == PKCS11_CKR_OK && attr_size == sizeof(cert_category)) { /* Sanitize certificate category */ TEE_MemMove(&cert_category, attr_value, sizeof(cert_category)); switch (cert_category) { case PKCS11_CK_CERTIFICATE_CATEGORY_UNSPECIFIED: case PKCS11_CK_CERTIFICATE_CATEGORY_TOKEN_USER: case PKCS11_CK_CERTIFICATE_CATEGORY_AUTHORITY: case PKCS11_CK_CERTIFICATE_CATEGORY_OTHER_ENTITY: break; default: EMSG("Invalid certificate category %#"PRIx32, cert_category); return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; } } else if (rc == PKCS11_RV_NOT_FOUND) { /* Set default category when missing */ rc = set_attribute(out, PKCS11_CKA_CERTIFICATE_CATEGORY, &default_cert_category, sizeof(default_cert_category)); if (rc) return rc; } else { /* All other cases are errors */ EMSG("Invalid certificate category"); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } attr_size = 0; rc = get_attribute_ptr(*out, PKCS11_CKA_NAME_HASH_ALGORITHM, NULL, &attr_size); if (rc == PKCS11_CKR_OK && attr_size == sizeof(uint32_t)) { /* We accept any algorithm what caller wanted to specify */ } else if (rc == PKCS11_RV_NOT_FOUND) { /* Set default hash algorithm when missing */ rc = set_attribute(out, PKCS11_CKA_NAME_HASH_ALGORITHM, &default_name_hash_alg, sizeof(default_name_hash_alg)); if (rc) return rc; } else { /* All other cases are errors */ EMSG("Invalid name hash algorithm"); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } return rc; } static enum pkcs11_rc create_pub_key_attributes(struct obj_attrs **out, struct obj_attrs *temp, enum processing_func function) { uint32_t const *mandated = NULL; uint32_t const *oon = NULL; size_t mandated_count = 0; size_t oon_count = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; assert(get_class(temp) == PKCS11_CKO_PUBLIC_KEY); rc = create_genkey_attributes(out, temp); if (rc) return rc; assert(get_class(*out) == PKCS11_CKO_PUBLIC_KEY); rc = set_mandatory_boolprops(out, temp, public_key_boolprops, ARRAY_SIZE(public_key_boolprops)); if (rc) return rc; rc = set_mandatory_attributes(out, temp, public_key_mandated, ARRAY_SIZE(public_key_mandated)); if (rc) return rc; rc = set_attributes_opt_or_null(out, temp, public_key_opt_or_null, ARRAY_SIZE(public_key_opt_or_null)); if (rc) return rc; switch (get_key_type(*out)) { case PKCS11_CKK_RSA: switch (function) { case PKCS11_FUNCTION_GENERATE_PAIR: mandated = rsa_pub_key_gen_mand; oon = rsa_pub_key_gen_opt_or_null; mandated_count = ARRAY_SIZE(rsa_pub_key_gen_mand); oon_count = ARRAY_SIZE(rsa_pub_key_gen_opt_or_null); break; case PKCS11_FUNCTION_IMPORT: mandated = rsa_pub_key_create_mand; mandated_count = ARRAY_SIZE(rsa_pub_key_create_mand); break; default: EMSG("Unsupported function %#"PRIx32"/%s", function, id2str_function(function)); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } break; case PKCS11_CKK_EC: case PKCS11_CKK_EC_EDWARDS: mandated = ec_public_key_mandated; oon = ec_public_key_opt_or_null; mandated_count = ARRAY_SIZE(ec_public_key_mandated); oon_count = ARRAY_SIZE(ec_public_key_opt_or_null); break; default: EMSG("Invalid key type %#"PRIx32"/%s", get_key_type(*out), id2str_key_type(get_key_type(*out))); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = set_mandatory_attributes(out, temp, mandated, mandated_count); if (rc) return rc; return set_attributes_opt_or_null(out, temp, oon, oon_count); } static enum pkcs11_rc create_pub_key_rsa_generated_attributes(struct obj_attrs **out, struct obj_attrs *temp, enum processing_func function) { uint32_t key_bits = 0; void *a_ptr = NULL; uint32_t a_size = 0; if (function != PKCS11_FUNCTION_IMPORT) return PKCS11_CKR_OK; /* Calculate CKA_MODULUS_BITS */ if (get_attribute_ptr(temp, PKCS11_CKA_MODULUS, &a_ptr, &a_size) || !a_ptr) { EMSG("No CKA_MODULUS attribute found in public key"); return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; } key_bits = a_size * 8; return add_attribute(out, PKCS11_CKA_MODULUS_BITS, &key_bits, sizeof(key_bits)); } static enum pkcs11_rc create_pub_key_generated_attributes(struct obj_attrs **out, struct obj_attrs *temp, enum processing_func function) { enum pkcs11_rc rc = PKCS11_CKR_OK; switch (get_key_type(*out)) { case PKCS11_CKK_RSA: rc = create_pub_key_rsa_generated_attributes(out, temp, function); break; default: /* no-op */ break; } return rc; } static enum pkcs11_rc create_priv_key_attributes(struct obj_attrs **out, struct obj_attrs *temp) { uint32_t const *mandated = NULL; uint32_t const *oon = NULL; size_t mandated_count = 0; size_t oon_count = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; assert(get_class(temp) == PKCS11_CKO_PRIVATE_KEY); rc = create_genkey_attributes(out, temp); if (rc) return rc; assert(get_class(*out) == PKCS11_CKO_PRIVATE_KEY); rc = set_mandatory_boolprops(out, temp, private_key_boolprops, ARRAY_SIZE(private_key_boolprops)); if (rc) return rc; rc = set_mandatory_attributes(out, temp, private_key_mandated, ARRAY_SIZE(private_key_mandated)); if (rc) return rc; rc = set_attributes_opt_or_null(out, temp, private_key_opt_or_null, ARRAY_SIZE(private_key_opt_or_null)); if (rc) return rc; switch (get_key_type(*out)) { case PKCS11_CKK_RSA: oon = rsa_priv_key_opt_or_null; oon_count = ARRAY_SIZE(rsa_priv_key_opt_or_null); break; case PKCS11_CKK_EC: mandated = ec_private_key_mandated; oon = ec_private_key_opt_or_null; mandated_count = ARRAY_SIZE(ec_private_key_mandated); oon_count = ARRAY_SIZE(ec_private_key_opt_or_null); break; case PKCS11_CKK_EC_EDWARDS: mandated = ec_private_key_mandated; oon = eddsa_private_key_opt_or_null; mandated_count = ARRAY_SIZE(ec_private_key_mandated); oon_count = ARRAY_SIZE(eddsa_private_key_opt_or_null); break; default: EMSG("Invalid key type %#"PRIx32"/%s", get_key_type(*out), id2str_key_type(get_key_type(*out))); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = set_mandatory_attributes(out, temp, mandated, mandated_count); if (rc) return rc; return set_attributes_opt_or_null(out, temp, oon, oon_count); } static int mbd_rand(void *rng_state __unused, unsigned char *output, size_t len) { TEE_GenerateRandom(output, len); return 0; } static enum pkcs11_rc create_ec_priv_key_hidden_attributes(struct obj_attrs **out, struct obj_attrs *temp, enum processing_func function) { struct mbedtls_ecp_keypair key_pair = { }; mbedtls_ecp_group_id ec_curve = MBEDTLS_ECP_DP_NONE; mbedtls_ecp_group key_pair_grp = { }; mbedtls_ecp_point key_pair_Q = { }; mbedtls_mpi key_pair_d = { }; size_t buflen = 0; uint8_t *buf = NULL; size_t asnbuflen = 0; uint8_t *asnbuf = NULL; uint8_t *ptr = NULL; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; int tee_size = 0; int tee_curve = 0; void *a_ptr = NULL; uint32_t a_size = 0; int ret = 0; if (function != PKCS11_FUNCTION_IMPORT) return PKCS11_CKR_OK; /* * TEE internal API requires that for private key operations there * needs to be also public key available. * * Generate hidden EC point from private key. */ if (get_attribute_ptr(temp, PKCS11_CKA_EC_PARAMS, &a_ptr, &a_size) || !a_ptr) { EMSG("No EC_PARAMS attribute found in private key"); return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; } /* Just valdiate that curve is found */ tee_size = ec_params2tee_keysize(a_ptr, a_size); if (!tee_size) { EMSG("Unsupported EC_PARAMS curve"); return PKCS11_CKR_CURVE_NOT_SUPPORTED; } tee_curve = ec_params2tee_curve(a_ptr, a_size); switch (tee_curve) { case TEE_ECC_CURVE_NIST_P192: ec_curve = MBEDTLS_ECP_DP_SECP192R1; break; case TEE_ECC_CURVE_NIST_P224: ec_curve = MBEDTLS_ECP_DP_SECP224R1; break; case TEE_ECC_CURVE_NIST_P256: ec_curve = MBEDTLS_ECP_DP_SECP256R1; break; case TEE_ECC_CURVE_NIST_P384: ec_curve = MBEDTLS_ECP_DP_SECP384R1; break; case TEE_ECC_CURVE_NIST_P521: ec_curve = MBEDTLS_ECP_DP_SECP521R1; break; default: EMSG("Failed to map EC_PARAMS to supported curve"); return PKCS11_CKR_CURVE_NOT_SUPPORTED; } if (get_attribute_ptr(temp, PKCS11_CKA_VALUE, &a_ptr, &a_size) || !a_ptr) { EMSG("No VALUE attribute found in private key"); return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; } mbedtls_ecp_keypair_init(&key_pair); mbedtls_ecp_group_init(&key_pair_grp); mbedtls_mpi_init(&key_pair_d); mbedtls_ecp_point_init(&key_pair_Q); ret = mbedtls_ecp_read_key(ec_curve, &key_pair, a_ptr, a_size); if (ret) { EMSG("Failed to parse CKA_VALUE"); rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; goto out; } ret = mbedtls_ecp_export(&key_pair, &key_pair_grp, &key_pair_d, &key_pair_Q); if (ret) { EMSG("Failed to export key"); goto out; } ret = mbedtls_ecp_mul(&key_pair_grp, &key_pair_Q, &key_pair_d, &key_pair_grp.G, mbd_rand, NULL); if (ret) { EMSG("Failed to create public key"); goto out; } ret = mbedtls_ecp_check_privkey(&key_pair_grp, &key_pair_d); if (ret) { EMSG("Failed to verify private key"); goto out; } ret = mbedtls_ecp_check_pubkey(&key_pair_grp, &key_pair_Q); if (ret) { EMSG("Failed to verify public key"); goto out; } ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &buflen, NULL, 0); if (ret != MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) { EMSG("Failed to determine size of binary public key"); goto out; } buf = TEE_Malloc(buflen, TEE_MALLOC_FILL_ZERO); if (!buf) { EMSG("Failed to allocate memory for public key"); rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } asnbuflen = 1 /* octet string */ + 5 /* length */ + buflen; asnbuf = TEE_Malloc(asnbuflen, TEE_MALLOC_FILL_ZERO); if (!asnbuf) { EMSG("Failed to allocate memory for public key"); rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } ret = mbedtls_ecp_point_write_binary(&key_pair_grp, &key_pair_Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &buflen, buf, buflen); if (ret) { EMSG("Failed to write binary public key"); goto out; } /* Note: ASN.1 writing works backwards */ ptr = asnbuf + asnbuflen; ret = mbedtls_asn1_write_octet_string(&ptr, asnbuf, buf, buflen); if (ret < 0) { EMSG("Failed to write asn1 public key"); goto out; } rc = add_attribute(out, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ptr, (size_t)ret); out: TEE_Free(asnbuf); TEE_Free(buf); mbedtls_ecp_keypair_free(&key_pair); mbedtls_ecp_group_free(&key_pair_grp); mbedtls_mpi_free(&key_pair_d); mbedtls_ecp_point_free(&key_pair_Q); return rc; } static enum pkcs11_rc create_priv_key_hidden_attributes(struct obj_attrs **out, struct obj_attrs *temp, enum processing_func function) { enum pkcs11_rc rc = PKCS11_CKR_OK; switch (get_key_type(*out)) { case PKCS11_CKK_EC: rc = create_ec_priv_key_hidden_attributes(out, temp, function); break; default: /* no-op */ break; } return rc; } static enum pkcs11_rc sanitize_symm_key_attributes(struct obj_attrs **temp, enum processing_func function) { enum pkcs11_rc rc = PKCS11_CKR_OK; uint32_t a_size = 0; assert(get_class(*temp) == PKCS11_CKO_SECRET_KEY); rc = get_attribute_ptr(*temp, PKCS11_CKA_VALUE, NULL, &a_size); switch (get_key_type(*temp)) { case PKCS11_CKK_GENERIC_SECRET: case PKCS11_CKK_AES: case PKCS11_CKK_MD5_HMAC: case PKCS11_CKK_SHA_1_HMAC: case PKCS11_CKK_SHA256_HMAC: case PKCS11_CKK_SHA384_HMAC: case PKCS11_CKK_SHA512_HMAC: case PKCS11_CKK_SHA224_HMAC: switch (function) { case PKCS11_FUNCTION_IMPORT: /* CKA_VALUE is a mandatory with C_CreateObject */ if (rc || a_size == 0) return PKCS11_CKR_TEMPLATE_INCONSISTENT; if (get_attribute_ptr(*temp, PKCS11_CKA_VALUE_LEN, NULL, NULL) != PKCS11_RV_NOT_FOUND) return PKCS11_CKR_TEMPLATE_INCONSISTENT; return add_attribute(temp, PKCS11_CKA_VALUE_LEN, &a_size, sizeof(uint32_t)); case PKCS11_FUNCTION_GENERATE: if (rc != PKCS11_RV_NOT_FOUND) return PKCS11_CKR_TEMPLATE_INCONSISTENT; break; default: break; } break; default: EMSG("Invalid key type %#"PRIx32"/%s", get_key_type(*temp), id2str_key_type(get_key_type(*temp))); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } return PKCS11_CKR_OK; } /* * Create an attribute list for a new object from a template and a parent * object (optional) for an object generation function (generate, copy, * derive...). * * PKCS#11 directives on the supplied template and expected return value: * - template has an invalid attribute ID: ATTRIBUTE_TYPE_INVALID * - template has an invalid value for an attribute: ATTRIBUTE_VALID_INVALID * - template has value for a read-only attribute: ATTRIBUTE_READ_ONLY * - template+default+parent => still miss an attribute: TEMPLATE_INCONSISTENT * * INFO on PKCS11_CMD_COPY_OBJECT: * - parent PKCS11_CKA_COPYIABLE=false => return ACTION_PROHIBITED. * - template can specify PKCS11_CKA_TOKEN, PKCS11_CKA_PRIVATE, * PKCS11_CKA_MODIFIABLE, PKCS11_CKA_DESTROYABLE. * - SENSITIVE can change from false to true, not from true to false. * - LOCAL is the parent LOCAL */ enum pkcs11_rc create_attributes_from_template(struct obj_attrs **out, void *template, size_t template_size, struct obj_attrs *parent, enum processing_func function, enum pkcs11_mechanism_id mecha, enum pkcs11_class_id template_class) { struct obj_attrs *temp = NULL; struct obj_attrs *attrs = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; uint8_t local = 0; uint8_t always_sensitive = 0; uint8_t never_extract = 0; uint8_t extractable = 0; uint32_t class = PKCS11_UNDEFINED_ID; uint32_t type = PKCS11_UNDEFINED_ID; uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID; struct obj_attrs *req_attrs = NULL; uint32_t size = 0; uint32_t indirect_template = PKCS11_CKA_UNDEFINED_ID; #ifdef DEBUG /* Sanity: check function argument */ trace_attributes_from_api_head("template", template, template_size); switch (function) { case PKCS11_FUNCTION_GENERATE: case PKCS11_FUNCTION_GENERATE_PAIR: case PKCS11_FUNCTION_IMPORT: case PKCS11_FUNCTION_MODIFY: case PKCS11_FUNCTION_DERIVE: case PKCS11_FUNCTION_UNWRAP: case PKCS11_FUNCTION_COPY: break; default: TEE_Panic(TEE_ERROR_NOT_SUPPORTED); } #endif /* * For PKCS11_FUNCTION_GENERATE, find the class and type * based on the mechanism. These will be passed as hint * sanitize_client_object() and added in temp if not * already present */ if (function == PKCS11_FUNCTION_GENERATE) { switch (mecha) { case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: class = PKCS11_CKO_SECRET_KEY; type = PKCS11_CKK_GENERIC_SECRET; break; case PKCS11_CKM_AES_KEY_GEN: class = PKCS11_CKO_SECRET_KEY; type = PKCS11_CKK_AES; break; default: TEE_Panic(TEE_ERROR_NOT_SUPPORTED); } } /* * For PKCS11_FUNCTION_GENERATE_PAIR, find the class and type * based on the mechanism. These will be passed as hint * sanitize_client_object() and added in temp if not * already present */ if (function == PKCS11_FUNCTION_GENERATE_PAIR) { switch (mecha) { case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: class = template_class; type = PKCS11_CKK_EDDSA; break; case PKCS11_CKM_EC_KEY_PAIR_GEN: class = template_class; type = PKCS11_CKK_EC; break; case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: class = template_class; type = PKCS11_CKK_RSA; break; default: TEE_Panic(TEE_ERROR_NOT_SUPPORTED); } } /* * Check and remove duplicates if any and create a new temporary * template */ rc = sanitize_client_object(&temp, template, template_size, class, type); if (rc) goto out; /* * For function type modify and copy return the created template * from here. Rest of the code below is for creating objects * or generating keys. */ switch (function) { case PKCS11_FUNCTION_MODIFY: case PKCS11_FUNCTION_COPY: *out = temp; return rc; case PKCS11_FUNCTION_DERIVE: case PKCS11_FUNCTION_UNWRAP: if (function == PKCS11_FUNCTION_UNWRAP) indirect_template = PKCS11_CKA_UNWRAP_TEMPLATE; else indirect_template = PKCS11_CKA_DERIVE_TEMPLATE; rc = get_attribute_ptr(parent, indirect_template, (void *)&req_attrs, &size); if (rc == PKCS11_CKR_OK && size != 0) { rc = attributes_match_add_reference(&temp, req_attrs); if (rc) goto out; } break; default: break; } /* * Check if class and type in temp are consistent with the mechanism */ switch (mecha) { case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: if (get_class(temp) != PKCS11_CKO_SECRET_KEY || get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } break; case PKCS11_CKM_AES_KEY_GEN: if (get_class(temp) != PKCS11_CKO_SECRET_KEY || get_key_type(temp) != PKCS11_CKK_AES) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } break; case PKCS11_CKM_EC_KEY_PAIR_GEN: if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY && get_class(temp) != PKCS11_CKO_PRIVATE_KEY) || get_key_type(temp) != PKCS11_CKK_EC) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } break; case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY && get_class(temp) != PKCS11_CKO_PRIVATE_KEY) || get_key_type(temp) != PKCS11_CKK_EC_EDWARDS) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } break; case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: if ((get_class(temp) != PKCS11_CKO_PUBLIC_KEY && get_class(temp) != PKCS11_CKO_PRIVATE_KEY) || get_key_type(temp) != PKCS11_CKK_RSA) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } break; default: break; } if (!sanitize_consistent_class_and_type(temp)) { EMSG("Inconsistent class/type"); rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } /* * TBD - Add a check to see if temp contains any attribute which * is not consistent with the object class or type and return error. * In current implementation such attributes are ignored and not * added to final object while PKCS#11 specification expects a * failure and an error code be returned. */ switch (get_class(temp)) { case PKCS11_CKO_DATA: rc = create_data_attributes(&attrs, temp); break; case PKCS11_CKO_CERTIFICATE: rc = create_certificate_attributes(&attrs, temp); break; case PKCS11_CKO_SECRET_KEY: rc = sanitize_symm_key_attributes(&temp, function); if (rc) goto out; rc = create_symm_key_attributes(&attrs, temp); break; case PKCS11_CKO_PUBLIC_KEY: rc = create_pub_key_attributes(&attrs, temp, function); if (rc) goto out; rc = create_pub_key_generated_attributes(&attrs, temp, function); break; case PKCS11_CKO_PRIVATE_KEY: rc = create_priv_key_attributes(&attrs, temp); if (rc) goto out; rc = create_priv_key_hidden_attributes(&attrs, temp, function); break; default: DMSG("Invalid object class %#"PRIx32"/%s", get_class(temp), id2str_class(get_class(temp))); rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; break; } if (rc) goto out; if (get_attribute_ptr(temp, PKCS11_CKA_LOCAL, NULL, NULL) != PKCS11_RV_NOT_FOUND) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } if (get_attribute_ptr(temp, PKCS11_CKA_KEY_GEN_MECHANISM, NULL, NULL) != PKCS11_RV_NOT_FOUND) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } switch (function) { case PKCS11_FUNCTION_GENERATE: case PKCS11_FUNCTION_GENERATE_PAIR: local = PKCS11_TRUE; break; case PKCS11_FUNCTION_IMPORT: case PKCS11_FUNCTION_DERIVE: case PKCS11_FUNCTION_UNWRAP: default: local = PKCS11_FALSE; break; } rc = add_attribute(&attrs, PKCS11_CKA_LOCAL, &local, sizeof(local)); if (rc) goto out; switch (get_class(attrs)) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PRIVATE_KEY: case PKCS11_CKO_PUBLIC_KEY: always_sensitive = PKCS11_FALSE; never_extract = PKCS11_FALSE; switch (function) { case PKCS11_FUNCTION_DERIVE: always_sensitive = get_bool(parent, PKCS11_CKA_ALWAYS_SENSITIVE) && get_bool(attrs, PKCS11_CKA_SENSITIVE); never_extract = get_bool(parent, PKCS11_CKA_NEVER_EXTRACTABLE) && !get_bool(attrs, PKCS11_CKA_EXTRACTABLE); break; case PKCS11_FUNCTION_UNWRAP: always_sensitive = PKCS11_FALSE; never_extract = PKCS11_FALSE; extractable = PKCS11_TRUE; /* * Check if template passed by user has CKA_EXTRACTABLE. * If not, by default value of CKA_EXTRACTABLE is set as * TRUE. */ if (get_attribute_ptr(temp, PKCS11_CKA_EXTRACTABLE, NULL, NULL) == PKCS11_RV_NOT_FOUND) { rc = set_attribute(&attrs, PKCS11_CKA_EXTRACTABLE, &extractable, sizeof(extractable)); if (rc) goto out; } break; case PKCS11_FUNCTION_GENERATE: case PKCS11_FUNCTION_GENERATE_PAIR: always_sensitive = get_bool(attrs, PKCS11_CKA_SENSITIVE); never_extract = !get_bool(attrs, PKCS11_CKA_EXTRACTABLE); break; default: break; } rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE, &always_sensitive, sizeof(always_sensitive)); if (rc) goto out; rc = add_attribute(&attrs, PKCS11_CKA_NEVER_EXTRACTABLE, &never_extract, sizeof(never_extract)); if (rc) goto out; /* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */ if (local) mechanism_id = mecha; else mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION; rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM, &mechanism_id, sizeof(mechanism_id)); if (rc) goto out; break; default: break; } *out = attrs; #ifdef DEBUG trace_attributes("object", attrs); #endif out: TEE_Free(temp); if (rc) TEE_Free(attrs); return rc; } static enum pkcs11_rc check_attrs_misc_integrity(struct obj_attrs *head) { if (get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE) && get_bool(head, PKCS11_CKA_EXTRACTABLE)) { DMSG("Never/Extractable attributes mismatch %d/%d", get_bool(head, PKCS11_CKA_NEVER_EXTRACTABLE), get_bool(head, PKCS11_CKA_EXTRACTABLE)); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } if (get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE) && !get_bool(head, PKCS11_CKA_SENSITIVE)) { DMSG("Sensitive/always attributes mismatch %d/%d", get_bool(head, PKCS11_CKA_SENSITIVE), get_bool(head, PKCS11_CKA_ALWAYS_SENSITIVE)); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } return PKCS11_CKR_OK; } bool object_is_private(struct obj_attrs *head) { return get_bool(head, PKCS11_CKA_PRIVATE); } bool object_is_token(struct obj_attrs *head) { return get_bool(head, PKCS11_CKA_TOKEN); } bool object_is_modifiable(struct obj_attrs *head) { return get_bool(head, PKCS11_CKA_MODIFIABLE); } bool object_is_copyable(struct obj_attrs *head) { return get_bool(head, PKCS11_CKA_COPYABLE); } /* * Check access to object against authentication to token */ enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session, struct obj_attrs *head) { bool private = true; switch (get_class(head)) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PRIVATE_KEY: case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_DATA: case PKCS11_CKO_CERTIFICATE: private = object_is_private(head); break; default: return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } if (private && (pkcs11_session_is_public(session) || pkcs11_session_is_so(session))) { DMSG("Private object access from a public or SO session"); return PKCS11_CKR_USER_NOT_LOGGED_IN; } return PKCS11_CKR_OK; } /* * Check the attributes of a to-be-created object matches the token state */ enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session, struct obj_attrs *head) { enum pkcs11_rc rc = PKCS11_CKR_OK; rc = check_attrs_misc_integrity(head); if (rc) return rc; if (get_bool(head, PKCS11_CKA_TRUSTED) && !pkcs11_session_is_so(session)) { DMSG("Can't create trusted object"); return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } if (get_bool(head, PKCS11_CKA_TOKEN) && !pkcs11_session_is_read_write(session)) { DMSG("Can't create persistent object"); return PKCS11_CKR_SESSION_READ_ONLY; } return PKCS11_CKR_OK; } #define DMSG_BAD_BBOOL(attr, proc, head) \ do { \ uint32_t __maybe_unused _attr = (attr); \ uint8_t __maybe_unused _bvalue = 0; \ enum pkcs11_rc __maybe_unused _rc = PKCS11_CKR_OK; \ \ _rc = get_attribute((head), _attr, &_bvalue, NULL); \ DMSG("%s issue for %s: %sfound, value %"PRIu8, \ id2str_attr(_attr), id2str_proc((proc)), \ _rc ? "not " : "", _bvalue); \ } while (0) static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused, struct obj_attrs *head, uint32_t attribute, bool val) { uint8_t bbool = 0; uint32_t sz = sizeof(bbool); if (!get_attribute(head, attribute, &bbool, &sz) && !!bbool == val) return true; DMSG_BAD_BBOOL(attribute, proc_id, head); return false; } /* * Check the attributes of a new secret match the processing/mechanism * used to create it. * * @proc_id - PKCS11_CKM_xxx * @head - head of the attributes of the to-be-created object. */ enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id, struct obj_attrs *head __maybe_unused) { /* * Processings that do not create secrets are not expected to call * this function which would panic. */ switch (proc_id) { case PKCS11_PROCESSING_IMPORT: case PKCS11_CKM_ECDH1_DERIVE: case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: case PKCS11_CKM_RSA_AES_KEY_WRAP: assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false)); break; case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: case PKCS11_CKM_AES_KEY_GEN: case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: case PKCS11_CKM_EC_KEY_PAIR_GEN: case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true)); break; default: TEE_Panic(proc_id); break; } switch (proc_id) { case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: assert(get_key_type(head) == PKCS11_CKK_GENERIC_SECRET); break; case PKCS11_CKM_AES_KEY_GEN: assert(get_key_type(head) == PKCS11_CKK_AES); break; case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: assert(get_key_type(head) == PKCS11_CKK_EC_EDWARDS); break; case PKCS11_CKM_EC_KEY_PAIR_GEN: assert(get_key_type(head) == PKCS11_CKK_EC); break; case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: assert(get_key_type(head) == PKCS11_CKK_RSA); break; case PKCS11_PROCESSING_IMPORT: case PKCS11_CKM_ECDH1_DERIVE: default: break; } return PKCS11_CKR_OK; } /* Return min and max key size supported for a key_type in bytes */ static void get_key_min_max_sizes(enum pkcs11_key_type key_type, uint32_t *min_key_size, uint32_t *max_key_size) { enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID; switch (key_type) { case PKCS11_CKK_GENERIC_SECRET: mechanism = PKCS11_CKM_GENERIC_SECRET_KEY_GEN; break; case PKCS11_CKK_AES: mechanism = PKCS11_CKM_AES_KEY_GEN; break; case PKCS11_CKK_MD5_HMAC: mechanism = PKCS11_CKM_MD5_HMAC; break; case PKCS11_CKK_SHA_1_HMAC: mechanism = PKCS11_CKM_SHA_1_HMAC; break; case PKCS11_CKK_SHA224_HMAC: mechanism = PKCS11_CKM_SHA224_HMAC; break; case PKCS11_CKK_SHA256_HMAC: mechanism = PKCS11_CKM_SHA256_HMAC; break; case PKCS11_CKK_SHA384_HMAC: mechanism = PKCS11_CKM_SHA384_HMAC; break; case PKCS11_CKK_SHA512_HMAC: mechanism = PKCS11_CKM_SHA512_HMAC; break; case PKCS11_CKK_EC: mechanism = PKCS11_CKM_EC_KEY_PAIR_GEN; break; case PKCS11_CKK_EDDSA: mechanism = PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN; break; case PKCS11_CKK_RSA: mechanism = PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN; break; default: TEE_Panic(key_type); break; } mechanism_supported_key_sizes_bytes(mechanism, min_key_size, max_key_size); } enum pkcs11_rc check_created_attrs(struct obj_attrs *key1, struct obj_attrs *key2) { enum pkcs11_rc rc = PKCS11_CKR_OK; struct obj_attrs *secret = NULL; struct obj_attrs *private = NULL; struct obj_attrs *public = NULL; uint32_t max_key_size = 0; uint32_t min_key_size = 0; uint32_t key_length = 0; switch (get_class(key1)) { case PKCS11_CKO_SECRET_KEY: secret = key1; break; case PKCS11_CKO_PUBLIC_KEY: public = key1; break; case PKCS11_CKO_PRIVATE_KEY: private = key1; break; default: return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; } if (key2) { switch (get_class(key2)) { case PKCS11_CKO_PUBLIC_KEY: public = key2; if (private == key1) break; return PKCS11_CKR_TEMPLATE_INCONSISTENT; case PKCS11_CKO_PRIVATE_KEY: private = key2; if (public == key1) break; return PKCS11_CKR_TEMPLATE_INCONSISTENT; default: return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; } if (get_key_type(private) != get_key_type(public)) return PKCS11_CKR_TEMPLATE_INCONSISTENT; } if (secret) { switch (get_key_type(secret)) { case PKCS11_CKK_AES: case PKCS11_CKK_GENERIC_SECRET: case PKCS11_CKK_MD5_HMAC: case PKCS11_CKK_SHA_1_HMAC: case PKCS11_CKK_SHA224_HMAC: case PKCS11_CKK_SHA256_HMAC: case PKCS11_CKK_SHA384_HMAC: case PKCS11_CKK_SHA512_HMAC: break; default: return PKCS11_CKR_TEMPLATE_INCONSISTENT; } /* Get key size */ rc = get_u32_attribute(secret, PKCS11_CKA_VALUE_LEN, &key_length); if (rc) return PKCS11_CKR_TEMPLATE_INCOMPLETE; } if (public) { switch (get_key_type(public)) { case PKCS11_CKK_RSA: /* Get key size */ rc = get_u32_attribute(public, PKCS11_CKA_MODULUS_BITS, &key_length); if (rc) return PKCS11_CKR_TEMPLATE_INCONSISTENT; key_length = ROUNDUP(key_length, 8) / 8; break; case PKCS11_CKK_EC: case PKCS11_CKK_EC_EDWARDS: break; default: return PKCS11_CKR_TEMPLATE_INCONSISTENT; } } if (private) { switch (get_key_type(private)) { case PKCS11_CKK_RSA: case PKCS11_CKK_EC: case PKCS11_CKK_EC_EDWARDS: break; default: return PKCS11_CKR_TEMPLATE_INCONSISTENT; } } /* * Check key size for symmetric keys and RSA keys * EC is bound to domains, no need to check here. */ switch (get_key_type(key1)) { case PKCS11_CKK_EC: case PKCS11_CKK_EC_EDWARDS: return PKCS11_CKR_OK; default: break; } get_key_min_max_sizes(get_key_type(key1), &min_key_size, &max_key_size); if (key_length < min_key_size || key_length > max_key_size) { EMSG("Length %"PRIu32" vs range [%"PRIu32" %"PRIu32"]", key_length, min_key_size, max_key_size); return PKCS11_CKR_KEY_SIZE_RANGE; } if (secret && get_key_type(secret) == PKCS11_CKK_AES) { if (key_length != 16 && key_length != 24 && key_length != 32) return PKCS11_CKR_KEY_SIZE_RANGE; } return PKCS11_CKR_OK; } /* Check processing ID against attribute ALLOWED_MECHANISMS if any */ static bool parent_key_complies_allowed_processings(uint32_t proc_id, struct obj_attrs *head) { char *attr = NULL; uint32_t size = 0; uint32_t proc = 0; size_t count = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; rc = get_attribute_ptr(head, PKCS11_CKA_ALLOWED_MECHANISMS, (void *)&attr, &size); if (rc == PKCS11_RV_NOT_FOUND) return true; if (rc) { EMSG("unexpected attributes state"); TEE_Panic(TEE_ERROR_BAD_STATE); } for (count = size / sizeof(uint32_t); count; count--) { TEE_MemMove(&proc, attr, sizeof(uint32_t)); attr += sizeof(uint32_t); if (proc == proc_id) return true; } DMSG("can't find %s in allowed list", id2str_proc(proc_id)); return false; } static enum pkcs11_attr_id func_to_attr(enum processing_func func) { switch (func) { case PKCS11_FUNCTION_ENCRYPT: return PKCS11_CKA_ENCRYPT; case PKCS11_FUNCTION_DECRYPT: return PKCS11_CKA_DECRYPT; case PKCS11_FUNCTION_SIGN: return PKCS11_CKA_SIGN; case PKCS11_FUNCTION_VERIFY: return PKCS11_CKA_VERIFY; case PKCS11_FUNCTION_WRAP: return PKCS11_CKA_WRAP; case PKCS11_FUNCTION_UNWRAP: return PKCS11_CKA_UNWRAP; case PKCS11_FUNCTION_DERIVE: return PKCS11_CKA_DERIVE; default: return PKCS11_CKA_UNDEFINED_ID; } } enum pkcs11_rc check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id, enum processing_func function, struct obj_attrs *head) { enum pkcs11_class_id key_class = get_class(head); enum pkcs11_key_type key_type = get_key_type(head); enum pkcs11_attr_id attr = func_to_attr(function); if (!get_bool(head, attr)) { DMSG("%s not permitted", id2str_attr(attr)); return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } /* Check processing complies with parent key family */ switch (proc_id) { case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_CTS: case PKCS11_CKM_AES_CTR: case PKCS11_CKM_AES_GCM: case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_AES_CMAC_GENERAL: if (key_class == PKCS11_CKO_SECRET_KEY && key_type == PKCS11_CKK_AES) break; DMSG("%s invalid key %s/%s", id2str_proc(proc_id), id2str_class(key_class), id2str_key_type(key_type)); if (function == PKCS11_FUNCTION_WRAP) return PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT; else if (function == PKCS11_FUNCTION_UNWRAP) return PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; else return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: if (key_class != PKCS11_CKO_SECRET_KEY && key_type != PKCS11_CKK_AES) return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; if (get_bool(head, PKCS11_CKA_ENCRYPT)) { /* * Intentionally refuse to proceed despite * PKCS#11 specifications v2.40 and v3.0 not expecting * this behavior to avoid potential security issue * where keys derived by these mechanisms can be * revealed by doing data encryption using parent key. */ return PKCS11_CKR_FUNCTION_FAILED; } break; case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: if (key_class != PKCS11_CKO_SECRET_KEY) return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; if (key_type == PKCS11_CKK_GENERIC_SECRET) break; switch (proc_id) { case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_MD5_HMAC_GENERAL: if (key_type == PKCS11_CKK_MD5_HMAC) break; return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA_1_HMAC_GENERAL: if (key_type == PKCS11_CKK_SHA_1_HMAC) break; return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA224_HMAC_GENERAL: if (key_type == PKCS11_CKK_SHA224_HMAC) break; return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA256_HMAC_GENERAL: if (key_type == PKCS11_CKK_SHA256_HMAC) break; return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA384_HMAC_GENERAL: if (key_type == PKCS11_CKK_SHA384_HMAC) break; return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_SHA512_HMAC_GENERAL: if (key_type == PKCS11_CKK_SHA512_HMAC) break; return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; default: return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } break; case PKCS11_CKM_EDDSA: if (key_type != PKCS11_CKK_EC_EDWARDS) { EMSG("Invalid key %s for mechanism %s", id2str_type(key_type, key_class), id2str_proc(proc_id)); return PKCS11_CKR_KEY_TYPE_INCONSISTENT; } if (key_class != PKCS11_CKO_PUBLIC_KEY && key_class != PKCS11_CKO_PRIVATE_KEY) { EMSG("Invalid key class for mechanism %s", id2str_proc(proc_id)); return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } break; case PKCS11_CKM_ECDSA: case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: case PKCS11_CKM_ECDH1_DERIVE: if (key_type != PKCS11_CKK_EC) { EMSG("Invalid key %s for mechanism %s", id2str_type(key_type, key_class), id2str_proc(proc_id)); return PKCS11_CKR_KEY_TYPE_INCONSISTENT; } if (key_class != PKCS11_CKO_PUBLIC_KEY && key_class != PKCS11_CKO_PRIVATE_KEY) { EMSG("Invalid key class for mechanism %s", id2str_proc(proc_id)); return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } break; case PKCS11_CKM_RSA_PKCS: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_RSA_AES_KEY_WRAP: case PKCS11_CKM_RSA_PKCS_OAEP: case PKCS11_CKM_RSA_PKCS_PSS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: if (key_type != PKCS11_CKK_RSA) { EMSG("Invalid key %s for mechanism %s", id2str_type(key_type, key_class), id2str_proc(proc_id)); return PKCS11_CKR_KEY_TYPE_INCONSISTENT; } if (key_class != PKCS11_CKO_PUBLIC_KEY && key_class != PKCS11_CKO_PRIVATE_KEY) { EMSG("Invalid key class for mechanism %s", id2str_proc(proc_id)); return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } break; default: DMSG("Invalid processing %#"PRIx32"/%s", proc_id, id2str_proc(proc_id)); return PKCS11_CKR_MECHANISM_INVALID; } if (!parent_key_complies_allowed_processings(proc_id, head)) { DMSG("Allowed mechanism failed"); return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED; } return PKCS11_CKR_OK; } bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr, struct pkcs11_object *obj) { uint8_t boolval = 0; uint32_t boolsize = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; enum pkcs11_class_id key_class = get_class(obj->attributes); if (attribute_is_hidden(req_attr)) return false; if (key_class != PKCS11_CKO_SECRET_KEY && key_class != PKCS11_CKO_PRIVATE_KEY) return true; switch (req_attr->id) { case PKCS11_CKA_PRIVATE_EXPONENT: case PKCS11_CKA_PRIME_1: case PKCS11_CKA_PRIME_2: case PKCS11_CKA_EXPONENT_1: case PKCS11_CKA_EXPONENT_2: case PKCS11_CKA_COEFFICIENT: case PKCS11_CKA_VALUE: boolsize = sizeof(boolval); rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE, &boolval, &boolsize); if (rc || boolval == PKCS11_FALSE) return false; boolsize = sizeof(boolval); rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE, &boolval, &boolsize); if (rc || boolval == PKCS11_TRUE) return false; break; default: break; } return true; } static bool attr_is_modifiable_any_key(struct pkcs11_attribute_head *attr) { switch (attr->id) { case PKCS11_CKA_ID: case PKCS11_CKA_START_DATE: case PKCS11_CKA_END_DATE: case PKCS11_CKA_DERIVE: return true; default: return false; } } static bool attr_is_modifiable_secret_key(struct pkcs11_attribute_head *attr, struct pkcs11_session *session, struct pkcs11_object *obj) { switch (attr->id) { case PKCS11_CKA_ENCRYPT: case PKCS11_CKA_DECRYPT: case PKCS11_CKA_SIGN: case PKCS11_CKA_VERIFY: case PKCS11_CKA_WRAP: case PKCS11_CKA_UNWRAP: case PKCS11_CKA_CHECK_VALUE: return true; /* Can't be modified once set to CK_FALSE - 12 in Table 10 */ case PKCS11_CKA_EXTRACTABLE: return get_bool(obj->attributes, attr->id); /* Can't be modified once set to CK_TRUE - 11 in Table 10 */ case PKCS11_CKA_SENSITIVE: case PKCS11_CKA_WRAP_WITH_TRUSTED: return !get_bool(obj->attributes, attr->id); /* Change in CKA_TRUSTED can only be done by SO */ case PKCS11_CKA_TRUSTED: return pkcs11_session_is_so(session); case PKCS11_CKA_NEVER_EXTRACTABLE: case PKCS11_CKA_ALWAYS_SENSITIVE: return false; default: return false; } } static bool attr_is_modifiable_public_key(struct pkcs11_attribute_head *attr, struct pkcs11_session *session, struct pkcs11_object *obj __unused) { switch (attr->id) { case PKCS11_CKA_SUBJECT: case PKCS11_CKA_ENCRYPT: case PKCS11_CKA_VERIFY: case PKCS11_CKA_VERIFY_RECOVER: case PKCS11_CKA_WRAP: return true; case PKCS11_CKA_TRUSTED: /* Change in CKA_TRUSTED can only be done by SO */ return pkcs11_session_is_so(session); default: return false; } } static bool attr_is_modifiable_private_key(struct pkcs11_attribute_head *attr, struct pkcs11_session *sess __unused, struct pkcs11_object *obj) { switch (attr->id) { case PKCS11_CKA_SUBJECT: case PKCS11_CKA_DECRYPT: case PKCS11_CKA_SIGN: case PKCS11_CKA_SIGN_RECOVER: case PKCS11_CKA_UNWRAP: /* * TBD: Revisit if we don't support PKCS11_CKA_PUBLIC_KEY_INFO * Specification mentions that if this attribute is * supplied as part of a template for C_CreateObject, C_CopyObject or * C_SetAttributeValue for a private key, the token MUST verify * correspondence between the private key data and the public key data * as supplied in CKA_PUBLIC_KEY_INFO. This needs to be * taken care of when this object type will be implemented */ case PKCS11_CKA_PUBLIC_KEY_INFO: return true; /* Can't be modified once set to CK_FALSE - 12 in Table 10 */ case PKCS11_CKA_EXTRACTABLE: return get_bool(obj->attributes, attr->id); /* Can't be modified once set to CK_TRUE - 11 in Table 10 */ case PKCS11_CKA_SENSITIVE: case PKCS11_CKA_WRAP_WITH_TRUSTED: return !get_bool(obj->attributes, attr->id); case PKCS11_CKA_NEVER_EXTRACTABLE: case PKCS11_CKA_ALWAYS_SENSITIVE: return false; default: return false; } } static bool attr_is_modifiable_certificate(struct pkcs11_attribute_head *attr, struct pkcs11_session *session, struct pkcs11_object *obj) { uint8_t boolval = 0; uint32_t boolsize = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; /* Trusted certificates cannot be modified. */ rc = get_attribute(obj->attributes, PKCS11_CKA_TRUSTED, &boolval, &boolsize); if (rc || boolval == PKCS11_TRUE) return false; /* Common certificate attributes */ switch (attr->id) { case PKCS11_CKA_TRUSTED: /* * The CKA_TRUSTED attribute cannot be set to CK_TRUE by an * application. It MUST be set by a token initialization * application or by the token’s SO. */ return pkcs11_session_is_so(session); case PKCS11_CKA_CERTIFICATE_TYPE: case PKCS11_CKA_CERTIFICATE_CATEGORY: return false; default: break; } /* Certificate type specific attributes */ switch (get_certificate_type(obj->attributes)) { case PKCS11_CKC_X_509: /* * Only the CKA_ID, CKA_ISSUER, and CKA_SERIAL_NUMBER * attributes may be modified after the object is created. */ switch (attr->id) { case PKCS11_CKA_ID: case PKCS11_CKA_ISSUER: case PKCS11_CKA_SERIAL_NUMBER: return true; default: break; } break; default: /* Unsupported certificate type */ break; } return false; } static bool attribute_is_modifiable(struct pkcs11_session *session, struct pkcs11_attribute_head *req_attr, struct pkcs11_object *obj, enum pkcs11_class_id class, enum processing_func function) { /* Check modifiable attributes common to any object */ switch (req_attr->id) { case PKCS11_CKA_LABEL: return true; case PKCS11_CKA_TOKEN: case PKCS11_CKA_MODIFIABLE: case PKCS11_CKA_DESTROYABLE: case PKCS11_CKA_PRIVATE: return function == PKCS11_FUNCTION_COPY; case PKCS11_CKA_COPYABLE: /* * Specification mentions that if the attribute value is false * it can't be set to true. Reading this we assume that it * should be possible to modify this attribute even though this * is not marked as modifiable in Table 10 if done in right * direction i.e from TRUE -> FALSE. */ return get_bool(obj->attributes, req_attr->id); default: break; } /* Attribute checking based on class type */ switch (class) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: if (attr_is_modifiable_any_key(req_attr)) return true; if (class == PKCS11_CKO_SECRET_KEY && attr_is_modifiable_secret_key(req_attr, session, obj)) return true; if (class == PKCS11_CKO_PUBLIC_KEY && attr_is_modifiable_public_key(req_attr, session, obj)) return true; if (class == PKCS11_CKO_PRIVATE_KEY && attr_is_modifiable_private_key(req_attr, session, obj)) return true; break; case PKCS11_CKO_DATA: /* None of the data object attributes are modifiable */ return false; case PKCS11_CKO_CERTIFICATE: return attr_is_modifiable_certificate(req_attr, session, obj); default: break; } return false; } enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session, struct obj_attrs *head, struct pkcs11_object *obj, enum processing_func function) { enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; char *cur = NULL; char *end = NULL; size_t len = 0; class = get_class(obj->attributes); cur = (char *)head + sizeof(struct obj_attrs); end = cur + head->attrs_size; for (; cur < end; cur += len) { /* Structure aligned copy of the pkcs11_ref in the object */ struct pkcs11_attribute_head cli_ref = { }; TEE_MemMove(&cli_ref, cur, sizeof(cli_ref)); len = sizeof(cli_ref) + cli_ref.size; /* Protect hidden attributes */ if (attribute_is_hidden(&cli_ref)) return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; /* * Check 1 - Check if attribute belongs to the object * The obj->attributes has all the attributes in * it which are allowed for an object. */ if (get_attribute_ptr(obj->attributes, cli_ref.id, NULL, NULL) == PKCS11_RV_NOT_FOUND) return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; /* Check 2 - Is attribute modifiable */ if (!attribute_is_modifiable(session, &cli_ref, obj, class, function)) return PKCS11_CKR_ATTRIBUTE_READ_ONLY; /* * Checks for modification in PKCS11_CKA_TOKEN and * PKCS11_CKA_PRIVATE are required for PKCS11_FUNCTION_COPY * only, so skip them for PKCS11_FUNCTION_MODIFY. */ if (function == PKCS11_FUNCTION_MODIFY) continue; /* * An attempt to copy an object to a token will fail for * RO session */ if (cli_ref.id == PKCS11_CKA_TOKEN && get_bool(head, PKCS11_CKA_TOKEN)) { if (!pkcs11_session_is_read_write(session)) { DMSG("Can't copy to token in a RO session"); return PKCS11_CKR_SESSION_READ_ONLY; } } if (cli_ref.id == PKCS11_CKA_PRIVATE) { bool parent_priv = get_bool(obj->attributes, cli_ref.id); bool obj_priv = get_bool(head, cli_ref.id); /* * If PKCS11_CKA_PRIVATE is being set to TRUE from * FALSE, user has to be logged in */ if (!parent_priv && obj_priv) { if ((pkcs11_session_is_public(session) || pkcs11_session_is_so(session))) return PKCS11_CKR_USER_NOT_LOGGED_IN; } /* * Restriction added - Even for Copy, do not allow * modification of CKA_PRIVATE from TRUE to FALSE */ if (parent_priv && !obj_priv) return PKCS11_CKR_TEMPLATE_INCONSISTENT; } } return PKCS11_CKR_OK; } static enum pkcs11_rc set_secret_key_data(struct obj_attrs **head, void *data, size_t key_size) { uint32_t size = sizeof(uint32_t); uint32_t key_length = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; /* Get key size if present in template */ rc = get_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_length, &size); if (rc && rc != PKCS11_RV_NOT_FOUND) return rc; if (key_length) { if (key_size < key_length) return PKCS11_CKR_DATA_LEN_RANGE; } else { key_length = key_size; rc = set_attribute(head, PKCS11_CKA_VALUE_LEN, &key_length, sizeof(uint32_t)); if (rc) return rc; } /* Now we can check the VALUE_LEN field */ rc = check_created_attrs(*head, NULL); if (rc) return rc; /* Remove the default empty value attribute if found */ rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) return PKCS11_CKR_GENERAL_ERROR; rc = add_attribute(head, PKCS11_CKA_VALUE, data, key_length); if (rc) return rc; return set_check_value_attr(head); } static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head, void *data, size_t key_size) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; int mbedtls_rc = 0; uint32_t key_bits = 0; uint32_t size = 0; uint32_t buffer_size = 0; void *buffer = NULL; mbedtls_pk_context pk = { }; mbedtls_rsa_context *rsa = NULL; mbedtls_mpi n = { }; mbedtls_mpi e = { }; mbedtls_mpi d = { }; mbedtls_mpi p = { }; mbedtls_mpi q = { }; rc = get_u32_attribute(*head, PKCS11_CKA_MODULUS_BITS, &key_bits); if (rc && rc != PKCS11_RV_NOT_FOUND) return rc; if (remove_empty_attribute(head, PKCS11_CKA_MODULUS) || remove_empty_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT) || remove_empty_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT) || remove_empty_attribute(head, PKCS11_CKA_PRIME_1) || remove_empty_attribute(head, PKCS11_CKA_PRIME_2)) return PKCS11_CKR_GENERAL_ERROR; mbedtls_pk_init(&pk); mbedtls_mpi_init(&n); mbedtls_mpi_init(&e); mbedtls_mpi_init(&d); mbedtls_mpi_init(&p); mbedtls_mpi_init(&q); mbedtls_rc = mbedtls_pk_parse_key(&pk, data, key_size, NULL, 0, mbd_rand, NULL); if (mbedtls_rc) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } rsa = mbedtls_pk_rsa(pk); if (!rsa) { rc = PKCS11_CKR_GENERAL_ERROR; goto out; } mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e); if (mbedtls_rc) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } if (key_bits && mbedtls_mpi_bitlen(&n) != key_bits) { rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; goto out; } size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&n), 8); buffer_size = size; buffer = TEE_Malloc(buffer_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!buffer) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } mbedtls_rc = mbedtls_mpi_write_binary(&n, buffer, size); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } rc = add_attribute(head, PKCS11_CKA_MODULUS, buffer, size); if (rc) goto out; size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&e), 8); if (buffer_size < size) { rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; goto out; } mbedtls_rc = mbedtls_mpi_write_binary(&e, buffer, size); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } rc = add_attribute(head, PKCS11_CKA_PUBLIC_EXPONENT, buffer, size); if (rc) goto out; size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&d), 8); if (buffer_size < size) { rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; goto out; } mbedtls_rc = mbedtls_mpi_write_binary(&d, buffer, size); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } rc = add_attribute(head, PKCS11_CKA_PRIVATE_EXPONENT, buffer, size); if (rc) goto out; size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&p), 8); if (buffer_size < size) { rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; goto out; } mbedtls_rc = mbedtls_mpi_write_binary(&p, buffer, size); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } rc = add_attribute(head, PKCS11_CKA_PRIME_1, buffer, size); if (rc) goto out; size = ROUNDUP_DIV(mbedtls_mpi_bitlen(&q), 8); if (buffer_size < size) { rc = PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; goto out; } mbedtls_rc = mbedtls_mpi_write_binary(&q, buffer, size); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } rc = add_attribute(head, PKCS11_CKA_PRIME_2, buffer, size); out: mbedtls_pk_free(&pk); mbedtls_mpi_free(&n); mbedtls_mpi_free(&e); mbedtls_mpi_free(&d); mbedtls_mpi_free(&p); mbedtls_mpi_free(&q); TEE_Free(buffer); return rc; } enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data, size_t key_size) { switch (get_class(*head)) { case PKCS11_CKO_SECRET_KEY: return set_secret_key_data(head, data, key_size); case PKCS11_CKO_PRIVATE_KEY: if (get_key_type(*head) == PKCS11_CKK_RSA) return set_private_key_data_rsa(head, data, key_size); break; default: return PKCS11_CKR_GENERAL_ERROR; } return PKCS11_CKR_GENERAL_ERROR; } static enum pkcs11_rc alloc_copy_attribute_value(struct obj_attrs *head, void **data, uint32_t *sz) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *buffer = NULL; void *value = NULL; rc = get_attribute_ptr(head, PKCS11_CKA_VALUE, &value, sz); if (rc) return PKCS11_CKR_ARGUMENTS_BAD; buffer = TEE_Malloc(*sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!buffer) return PKCS11_CKR_DEVICE_MEMORY; TEE_MemMove(buffer, value, *sz); *data = buffer; return PKCS11_CKR_OK; } static enum pkcs11_rc encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; int i = 0; int mbedtls_rc = 0; int start = 0; int der_size = 0; void *n = NULL; void *p = NULL; void *q = NULL; void *d = NULL; void *e = NULL; uint32_t n_len = 0; uint32_t p_len = 0; uint32_t q_len = 0; uint32_t d_len = 0; uint32_t e_len = 0; uint8_t *buffer = NULL; mbedtls_pk_context pk = { }; mbedtls_rsa_context *rsa = NULL; const mbedtls_pk_info_t *pk_info = NULL; mbedtls_pk_init(&pk); pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); if (mbedtls_pk_setup(&pk, pk_info)) { rc = PKCS11_CKR_GENERAL_ERROR; goto out; } rc = get_attribute_ptr(head, PKCS11_CKA_MODULUS, &n, &n_len); if (rc) goto out; rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_1, &p, &p_len); if (rc) goto out; rc = get_attribute_ptr(head, PKCS11_CKA_PRIME_2, &q, &q_len); if (rc) goto out; rc = get_attribute_ptr(head, PKCS11_CKA_PRIVATE_EXPONENT, &d, &d_len); if (rc) goto out; rc = get_attribute_ptr(head, PKCS11_CKA_PUBLIC_EXPONENT, &e, &e_len); if (rc) goto out; rsa = mbedtls_pk_rsa(pk); if (!rsa) { rc = PKCS11_CKR_GENERAL_ERROR; goto out; } mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len, q, q_len, d, d_len, e, e_len); if (mbedtls_rc) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } if (mbedtls_rsa_complete(rsa)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } if (mbedtls_rsa_check_privkey(rsa)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } der_size = n_len * 8; buffer = TEE_Malloc(der_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!buffer) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } mbedtls_rc = mbedtls_pk_write_key_der(&pk, buffer, der_size); if (mbedtls_rc < 0) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } start = der_size - mbedtls_rc; for (i = 0; i < mbedtls_rc; i++) { buffer[i] = buffer[i + start]; buffer[i + start] = 0; } *data = buffer; *sz = mbedtls_rc; out: mbedtls_pk_free(&pk); if (rc) TEE_Free(buffer); return rc; } enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data, uint32_t *sz) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; switch (get_class(head)) { case PKCS11_CKO_SECRET_KEY: rc = alloc_copy_attribute_value(head, data, sz); break; case PKCS11_CKO_PRIVATE_KEY: if (get_key_type(head) == PKCS11_CKK_RSA) rc = encode_rsa_private_key_der(head, data, sz); break; default: break; } return rc; } enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head, struct obj_attrs **priv_head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *id1 = NULL; uint32_t id1_size = 0; void *id2 = NULL; uint32_t id2_size = 0; assert(pub_head); assert(priv_head); rc = get_attribute_ptr(*pub_head, PKCS11_CKA_ID, &id1, &id1_size); if (rc) { if (rc != PKCS11_RV_NOT_FOUND) return rc; id1 = NULL; } else if (!id1_size) { id1 = NULL; } rc = get_attribute_ptr(*priv_head, PKCS11_CKA_ID, &id2, &id2_size); if (rc) { if (rc != PKCS11_RV_NOT_FOUND) return rc; id2 = NULL; } else if (!id2_size) { id2 = NULL; } /* Both have value -- let them be what caller has specified them */ if (id1 && id2) return PKCS11_CKR_OK; /* Both are empty -- leave empty values */ if (!id1 && !id2) return PKCS11_CKR_OK; /* Cross copy CKA_ID value */ if (id1) return set_attribute(priv_head, PKCS11_CKA_ID, id1, id1_size); else return set_attribute(pub_head, PKCS11_CKA_ID, id2, id2_size); } /* * The key check value is derived from the object by taking the first * three bytes of the SHA-1 hash of the object's CKA_VALUE attribute. */ static enum pkcs11_rc compute_check_value_with_sha1(void *key, uint32_t key_size, void *kcv) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; TEE_OperationHandle op = TEE_HANDLE_NULL; size_t buf_size = TEE_MAX_HASH_SIZE; uint8_t *buf = NULL; assert(key && kcv); res = TEE_AllocateOperation(&op, TEE_ALG_SHA1, TEE_MODE_DIGEST, 0); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; buf = TEE_Malloc(buf_size, TEE_MALLOC_FILL_ZERO); if (!buf) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } res = TEE_DigestDoFinal(op, key, key_size, buf, &buf_size); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE); out: TEE_Free(buf); TEE_FreeOperation(op); return rc; } /* * The key check value that is calculated as follows: * 1) Take a buffer of the cipher block size of binary zeros (0x00). * 2) Encrypt this block in ECB mode. * 3) Take the first three bytes of cipher text as the check value. */ static enum pkcs11_rc compute_check_value_with_ecb(void *key, uint32_t key_size, void *kcv) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; TEE_OperationHandle op = TEE_HANDLE_NULL; TEE_ObjectHandle hkey = TEE_HANDLE_NULL; TEE_Attribute attr = { }; uint8_t buf[TEE_AES_BLOCK_SIZE] = { }; size_t buf_size = sizeof(buf); assert(key && kcv); res = TEE_AllocateOperation(&op, TEE_ALG_AES_ECB_NOPAD, TEE_MODE_ENCRYPT, key_size * 8); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; res = TEE_AllocateTransientObject(TEE_TYPE_AES, key_size * 8, &hkey); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; TEE_InitRefAttribute(&attr, TEE_ATTR_SECRET_VALUE, key, key_size); res = TEE_PopulateTransientObject(hkey, &attr, 1); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; res = TEE_SetOperationKey(op, hkey); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; TEE_CipherInit(op, NULL, 0); res = TEE_CipherDoFinal(op, buf, buf_size, buf, &buf_size); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; TEE_MemMove(kcv, buf, PKCS11_CKA_CHECK_VALUE_SIZE); out: TEE_FreeTransientObject(hkey); TEE_FreeOperation(op); return rc; } enum pkcs11_rc set_check_value_attr(struct obj_attrs **head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t val_len = 0; uint32_t kcv2_len = 0; void *val = NULL; uint8_t kcv[PKCS11_CKA_CHECK_VALUE_SIZE] = { }; void *kcv2 = NULL; assert(head && *head); if (!IS_ENABLED(CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE)) return PKCS11_CKR_OK; switch (get_class(*head)) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_CERTIFICATE: break; default: /* Nothing to do */ return PKCS11_CKR_OK; } /* Check whether CKA_CHECK_VALUE has been provided in the template */ rc = get_attribute_ptr(*head, PKCS11_CKA_CHECK_VALUE, &kcv2, &kcv2_len); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) return PKCS11_CKR_GENERAL_ERROR; /* * The generation of the KCV may be prevented by the application * supplying the attribute in the template as a no-value (0 length) * entry. */ if (rc == PKCS11_CKR_OK && !kcv2_len) return PKCS11_CKR_OK; if (rc == PKCS11_CKR_OK && kcv2_len != PKCS11_CKA_CHECK_VALUE_SIZE) return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; /* Get key CKA_VALUE */ rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE, &val, &val_len); if (rc) return rc; if (get_class(*head) == PKCS11_CKO_SECRET_KEY) { switch (get_key_type(*head)) { case PKCS11_CKK_AES: rc = compute_check_value_with_ecb(val, val_len, kcv); break; case PKCS11_CKK_GENERIC_SECRET: case PKCS11_CKK_MD5_HMAC: case PKCS11_CKK_SHA_1_HMAC: case PKCS11_CKK_SHA256_HMAC: case PKCS11_CKK_SHA384_HMAC: case PKCS11_CKK_SHA512_HMAC: case PKCS11_CKK_SHA224_HMAC: rc = compute_check_value_with_sha1(val, val_len, kcv); break; default: rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; break; } } else { rc = compute_check_value_with_sha1(val, val_len, kcv); } if (rc) return rc; /* * If the computed KCV does not match the provided one * then return CKR_ATTRIBUTE_VALUE_INVALID */ if (kcv2_len) { /* Provided KCV value shall match the computed one */ if (TEE_MemCompare(kcv2, kcv, PKCS11_CKA_CHECK_VALUE_SIZE)) rc = PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; } else { rc = add_attribute(head, PKCS11_CKA_CHECK_VALUE, kcv, PKCS11_CKA_CHECK_VALUE_SIZE); } return rc; } optee_os-4.3.0/ta/pkcs11/src/pkcs11_attributes.h000066400000000000000000000175211464416617300213730ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_PKCS11_ATTRIBUTES_H #define PKCS11_TA_PKCS11_ATTRIBUTES_H #include #include #include "serializer.h" /* The key check value (KCV) attribute for objects is 3 bytes */ #define PKCS11_CKA_CHECK_VALUE_SIZE U(3) struct obj_attrs; struct pkcs11_object; struct pkcs11_session; /* * PKCS#11 directives on object attributes. * Those with a '*' are optional, other must be defined, either by caller * or by some known default value. * * [all] objects: class * * [stored] objects: persistent, need_authen, modifiable, copyable, * destroyable, label*. * * [data] objects: [all], [stored], application_id*, object_id*, value. * * [key] objects: [all], [stored], type, id*, start_date/end_date*, * derive, local, allowed_mechanisms*. * * [symm-key]: [key], sensitive, encrypt, decrypt, sign, verify, wrap, * unwrap, extractable, wrap_with_trusted, trusted, * wrap_template, unwrap_template, derive_template. */ /* * Utils to check compliance of attributes at various processing steps. * Any processing operation is exclusively one of the following. * * Case 1: Create a secret from some local random value (C_CreateKey & friends) * - client provides an attributes list template, PKCS11 TA completes with * default attribute values. Object is created if attributes are * consistent and comply token/session state. * - PKCS11 sequence: * - check/set token/session state * - create an attribute list from client template and default values. * - check new secret attributes complies requested mechanism. * - check new secret attributes complies token/session state. * - Generate the value for the secret. * - Set some runtime attributes in the new secret. * - Register the new secret and return a handle for it. * * Case 2: Create a secret from a client clear data (C_CreateObject) * - client provides an attributes list template, PKCS11 TA completes with * default attribute values. Object is created if attributes are * consistent and comply token/session state. * - check/set token/session state * - create an attribute list from client template and default values. * - check new secret attributes complies requested mechanism (raw-import). * - check new secret attributes complies token/session state. * - Set some runtime attributes in the new secret. * - Register the new secret and return a handle for it. * Case 3: Use a secret for data processing * - client provides a mechanism ID and the secret handle. * - PKCS11 checks mechanism and secret comply, if mechanism and token/session * state comply and last if secret and token/session state comply. * - check/set token/session state * - check secret's parent attributes complies requested processing. * - check secret's parent attributes complies token/session state. * - check new secret attributes complies secret's parent attributes. * - check new secret attributes complies requested mechanism. * - check new secret attributes complies token/session state. * * Case 4: Create a secret from a client template and a secret's parent * (i.e derive a symmetric key) * - client args: new-key template, mechanism ID, parent-key handle. * - PKCS11 create a new-key attribute list based on template + default values + * inheritance from the parent key attributes. * - PKCS11 checks: * - token/session state * - parent-key vs mechanism * - parent-key vs token/session state * - parent-key vs new-key * - new-key vs mechanism * - new-key vs token/session state * - then do processing * - then finalize object creation */ enum processing_func { PKCS11_FUNCTION_DIGEST, PKCS11_FUNCTION_GENERATE, PKCS11_FUNCTION_GENERATE_PAIR, PKCS11_FUNCTION_DERIVE, PKCS11_FUNCTION_WRAP, PKCS11_FUNCTION_UNWRAP, PKCS11_FUNCTION_ENCRYPT, PKCS11_FUNCTION_DECRYPT, PKCS11_FUNCTION_SIGN, PKCS11_FUNCTION_VERIFY, PKCS11_FUNCTION_SIGN_RECOVER, PKCS11_FUNCTION_VERIFY_RECOVER, PKCS11_FUNCTION_IMPORT, PKCS11_FUNCTION_COPY, PKCS11_FUNCTION_MODIFY, PKCS11_FUNCTION_DESTROY, PKCS11_FUNCTION_UNKNOWN, }; enum processing_step { PKCS11_FUNC_STEP_INIT, PKCS11_FUNC_STEP_ONESHOT, PKCS11_FUNC_STEP_UPDATE, PKCS11_FUNC_STEP_UPDATE_KEY, PKCS11_FUNC_STEP_FINAL, }; /* Create an attribute list for a new object */ enum pkcs11_rc create_attributes_from_template(struct obj_attrs **out, void *template, size_t template_size, struct obj_attrs *parent, enum processing_func func, enum pkcs11_mechanism_id proc_mecha, enum pkcs11_class_id template_class); /* * The various checks to be performed before a processing: * - create a new object in the current token state * - use a parent object in the processing * - use a mechanism with provided configuration */ enum pkcs11_rc check_created_attrs_against_token(struct pkcs11_session *session, struct obj_attrs *head); enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id, struct obj_attrs *head); enum pkcs11_rc check_created_attrs(struct obj_attrs *key1, struct obj_attrs *key2); /* * Check the attributes of the parent secret (key) used in the processing * do match the target processing. * * @proc_id - PKCS11_CKM_xxx * @func - identifier of the processing function operated with @proc_id. * @head - head of the attributes of parent object. */ enum pkcs11_rc check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id, enum processing_func func, struct obj_attrs *head); enum pkcs11_rc check_access_attrs_against_token(struct pkcs11_session *session, struct obj_attrs *head); enum pkcs11_rc check_mechanism_against_processing(struct pkcs11_session *session, enum pkcs11_mechanism_id mechanism_type, enum processing_func function, enum processing_step step); static inline bool attribute_is_hidden(struct pkcs11_attribute_head *req_attr) { return (req_attr->id & PKCS11_CKA_OPTEE_FLAGS_HIDDEN) == PKCS11_CKA_OPTEE_FLAGS_HIDDEN; } bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr, struct pkcs11_object *obj); bool object_is_private(struct obj_attrs *head); bool object_is_token(struct obj_attrs *head); bool object_is_modifiable(struct obj_attrs *head); bool object_is_copyable(struct obj_attrs *head); /* * Check the attributes passed in template against the attributes which can be * modified. These are the attributes marked with * 8,10,11 or 12 in Table 10 * in PKCS #11 Cryptographic Token InterfaceBase Specification Version 2.40. * Few attributes not with this marking but explicitly specified as modifiable * in footnote of their tables are also considered to be modifiable */ enum pkcs11_rc check_attrs_against_modification(struct pkcs11_session *session, struct obj_attrs *head, struct pkcs11_object *obj, enum processing_func function); enum pkcs11_rc set_key_data(struct obj_attrs **head, void *data, size_t key_size); /* * Get an allocated copy of key data to be wrapped from @head * @head: Object attribute where to find key data to be wrapped * @data: Output allocated and filled buffer upon success * @sz: Key output data size in bytes upon success * Return a pkcs11_rv compliant value */ enum pkcs11_rc alloc_key_data_to_wrap(struct obj_attrs *head, void **data, uint32_t *sz); /* * Adds CKA_ID attribute from paired object if missing. * * @pub_head - Public key object attributes * @priv_head - Private key object attributes * Return a PKCS11 return code */ enum pkcs11_rc add_missing_attribute_id(struct obj_attrs **pub_head, struct obj_attrs **priv_head); /* * Check an object's check value (Checksum) * @head: Object attribute where to find KCV to be checked * Return a pkcs11_rv compliant value */ enum pkcs11_rc set_check_value_attr(struct obj_attrs **head); #endif /*PKCS11_TA_PKCS11_ATTRIBUTES_H*/ optee_os-4.3.0/ta/pkcs11/src/pkcs11_helpers.c000066400000000000000000000561071464416617300206450ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2020, Linaro Limited */ #include #include #include #include #include "attributes.h" #include "object.h" #include "pkcs11_attributes.h" #include "pkcs11_helpers.h" #include "processing.h" static const char __maybe_unused unknown[] = ""; struct attr_size { uint32_t id; uint32_t size; #if CFG_TEE_TA_LOG_LEVEL > 0 const char *string; #endif }; #if CFG_TEE_TA_LOG_LEVEL > 0 #define PKCS11_ID_SZ(_id, _sz) \ { .id = (uint32_t)(_id), .size = (_sz), .string = #_id } #else #define PKCS11_ID_SZ(_id, _sz) \ { .id = (uint32_t)(_id), .size = (_sz) } #endif static const struct attr_size attr_ids[] = { PKCS11_ID_SZ(PKCS11_CKA_CLASS, 4), PKCS11_ID_SZ(PKCS11_CKA_KEY_TYPE, 4), PKCS11_ID_SZ(PKCS11_CKA_VALUE, 0), PKCS11_ID_SZ(PKCS11_CKA_VALUE_LEN, 4), PKCS11_ID_SZ(PKCS11_CKA_KEY_GEN_MECHANISM, 4), PKCS11_ID_SZ(PKCS11_CKA_LABEL, 0), PKCS11_ID_SZ(PKCS11_CKA_CERTIFICATE_TYPE, 4), PKCS11_ID_SZ(PKCS11_CKA_ISSUER, 0), PKCS11_ID_SZ(PKCS11_CKA_SERIAL_NUMBER, 0), PKCS11_ID_SZ(PKCS11_CKA_CERTIFICATE_CATEGORY, 4), PKCS11_ID_SZ(PKCS11_CKA_URL, 0), PKCS11_ID_SZ(PKCS11_CKA_HASH_OF_SUBJECT_PUBLIC_KEY, 0), PKCS11_ID_SZ(PKCS11_CKA_HASH_OF_ISSUER_PUBLIC_KEY, 0), PKCS11_ID_SZ(PKCS11_CKA_JAVA_MIDP_SECURITY_DOMAIN, 4), PKCS11_ID_SZ(PKCS11_CKA_NAME_HASH_ALGORITHM, 4), PKCS11_ID_SZ(PKCS11_CKA_CHECK_VALUE, 0), PKCS11_ID_SZ(PKCS11_CKA_WRAP_TEMPLATE, 0), PKCS11_ID_SZ(PKCS11_CKA_UNWRAP_TEMPLATE, 0), PKCS11_ID_SZ(PKCS11_CKA_DERIVE_TEMPLATE, 0), PKCS11_ID_SZ(PKCS11_CKA_START_DATE, 4), PKCS11_ID_SZ(PKCS11_CKA_END_DATE, 4), PKCS11_ID_SZ(PKCS11_CKA_OBJECT_ID, 0), PKCS11_ID_SZ(PKCS11_CKA_APPLICATION, 0), PKCS11_ID_SZ(PKCS11_CKA_MECHANISM_TYPE, 4), PKCS11_ID_SZ(PKCS11_CKA_ID, 0), PKCS11_ID_SZ(PKCS11_CKA_ALLOWED_MECHANISMS, 0), PKCS11_ID_SZ(PKCS11_CKA_EC_POINT, 0), PKCS11_ID_SZ(PKCS11_CKA_EC_PARAMS, 0), PKCS11_ID_SZ(PKCS11_CKA_MODULUS, 0), PKCS11_ID_SZ(PKCS11_CKA_MODULUS_BITS, 4), PKCS11_ID_SZ(PKCS11_CKA_PUBLIC_EXPONENT, 0), PKCS11_ID_SZ(PKCS11_CKA_PRIVATE_EXPONENT, 0), PKCS11_ID_SZ(PKCS11_CKA_PRIME_1, 0), PKCS11_ID_SZ(PKCS11_CKA_PRIME_2, 0), PKCS11_ID_SZ(PKCS11_CKA_EXPONENT_1, 0), PKCS11_ID_SZ(PKCS11_CKA_EXPONENT_2, 0), PKCS11_ID_SZ(PKCS11_CKA_COEFFICIENT, 0), PKCS11_ID_SZ(PKCS11_CKA_SUBJECT, 0), PKCS11_ID_SZ(PKCS11_CKA_PUBLIC_KEY_INFO, 0), PKCS11_ID_SZ(PKCS11_CKA_KEY_GEN_MECHANISM, 4), /* Below are boolean attributes */ PKCS11_ID_SZ(PKCS11_CKA_TOKEN, 1), PKCS11_ID_SZ(PKCS11_CKA_PRIVATE, 1), PKCS11_ID_SZ(PKCS11_CKA_TRUSTED, 1), PKCS11_ID_SZ(PKCS11_CKA_SENSITIVE, 1), PKCS11_ID_SZ(PKCS11_CKA_ENCRYPT, 1), PKCS11_ID_SZ(PKCS11_CKA_DECRYPT, 1), PKCS11_ID_SZ(PKCS11_CKA_WRAP, 1), PKCS11_ID_SZ(PKCS11_CKA_UNWRAP, 1), PKCS11_ID_SZ(PKCS11_CKA_SIGN, 1), PKCS11_ID_SZ(PKCS11_CKA_SIGN_RECOVER, 1), PKCS11_ID_SZ(PKCS11_CKA_VERIFY, 1), PKCS11_ID_SZ(PKCS11_CKA_VERIFY_RECOVER, 1), PKCS11_ID_SZ(PKCS11_CKA_DERIVE, 1), PKCS11_ID_SZ(PKCS11_CKA_EXTRACTABLE, 1), PKCS11_ID_SZ(PKCS11_CKA_LOCAL, 1), PKCS11_ID_SZ(PKCS11_CKA_NEVER_EXTRACTABLE, 1), PKCS11_ID_SZ(PKCS11_CKA_ALWAYS_SENSITIVE, 1), PKCS11_ID_SZ(PKCS11_CKA_MODIFIABLE, 1), PKCS11_ID_SZ(PKCS11_CKA_COPYABLE, 1), PKCS11_ID_SZ(PKCS11_CKA_DESTROYABLE, 1), PKCS11_ID_SZ(PKCS11_CKA_ALWAYS_AUTHENTICATE, 1), PKCS11_ID_SZ(PKCS11_CKA_WRAP_WITH_TRUSTED, 1), /* Specific PKCS11 TA internal attribute ID */ PKCS11_ID_SZ(PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, 0), PKCS11_ID_SZ(PKCS11_CKA_UNDEFINED_ID, 0), }; struct any_id { uint32_t id; #if CFG_TEE_TA_LOG_LEVEL > 0 const char *string; #endif }; /* * Macro PKCS11_ID() can be used to define cells in ID list arrays * or ID/string conversion arrays. */ #if CFG_TEE_TA_LOG_LEVEL > 0 #define PKCS11_ID(_id) { .id = _id, .string = #_id } #else #define PKCS11_ID(_id) { .id = _id } #endif #define ID2STR(id, table, prefix) \ id2str(id, table, ARRAY_SIZE(table), prefix) #if CFG_TEE_TA_LOG_LEVEL > 0 /* Convert a PKCS11 ID into its label string */ static const char *id2str(uint32_t id, const struct any_id *table, size_t count, const char *prefix) { size_t n = 0; const char *str = NULL; for (n = 0; n < count; n++) { if (id != table[n].id) continue; str = table[n].string; /* Skip prefix provided matches found */ if (prefix && !TEE_MemCompare(str, prefix, strlen(prefix))) str += strlen(prefix); return str; } return unknown; } #endif /* CFG_TEE_TA_LOG_LEVEL > 0 */ /* * TA command IDs: used only as ID/string conversion for debug trace support */ static const struct any_id __maybe_unused string_ta_cmd[] = { PKCS11_ID(PKCS11_CMD_PING), PKCS11_ID(PKCS11_CMD_SLOT_LIST), PKCS11_ID(PKCS11_CMD_SLOT_INFO), PKCS11_ID(PKCS11_CMD_TOKEN_INFO), PKCS11_ID(PKCS11_CMD_MECHANISM_IDS), PKCS11_ID(PKCS11_CMD_MECHANISM_INFO), PKCS11_ID(PKCS11_CMD_OPEN_SESSION), PKCS11_ID(PKCS11_CMD_SESSION_INFO), PKCS11_ID(PKCS11_CMD_CLOSE_SESSION), PKCS11_ID(PKCS11_CMD_CLOSE_ALL_SESSIONS), PKCS11_ID(PKCS11_CMD_INIT_TOKEN), PKCS11_ID(PKCS11_CMD_INIT_PIN), PKCS11_ID(PKCS11_CMD_SET_PIN), PKCS11_ID(PKCS11_CMD_LOGIN), PKCS11_ID(PKCS11_CMD_LOGOUT), PKCS11_ID(PKCS11_CMD_CREATE_OBJECT), PKCS11_ID(PKCS11_CMD_DESTROY_OBJECT), PKCS11_ID(PKCS11_CMD_ENCRYPT_INIT), PKCS11_ID(PKCS11_CMD_DECRYPT_INIT), PKCS11_ID(PKCS11_CMD_ENCRYPT_UPDATE), PKCS11_ID(PKCS11_CMD_DECRYPT_UPDATE), PKCS11_ID(PKCS11_CMD_ENCRYPT_FINAL), PKCS11_ID(PKCS11_CMD_DECRYPT_FINAL), PKCS11_ID(PKCS11_CMD_ENCRYPT_ONESHOT), PKCS11_ID(PKCS11_CMD_DECRYPT_ONESHOT), PKCS11_ID(PKCS11_CMD_SIGN_INIT), PKCS11_ID(PKCS11_CMD_VERIFY_INIT), PKCS11_ID(PKCS11_CMD_SIGN_UPDATE), PKCS11_ID(PKCS11_CMD_VERIFY_UPDATE), PKCS11_ID(PKCS11_CMD_SIGN_FINAL), PKCS11_ID(PKCS11_CMD_VERIFY_FINAL), PKCS11_ID(PKCS11_CMD_SIGN_ONESHOT), PKCS11_ID(PKCS11_CMD_VERIFY_ONESHOT), PKCS11_ID(PKCS11_CMD_GENERATE_KEY), PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_INIT), PKCS11_ID(PKCS11_CMD_FIND_OBJECTS), PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_FINAL), PKCS11_ID(PKCS11_CMD_GET_OBJECT_SIZE), PKCS11_ID(PKCS11_CMD_GET_ATTRIBUTE_VALUE), PKCS11_ID(PKCS11_CMD_SET_ATTRIBUTE_VALUE), PKCS11_ID(PKCS11_CMD_COPY_OBJECT), PKCS11_ID(PKCS11_CMD_SEED_RANDOM), PKCS11_ID(PKCS11_CMD_GENERATE_RANDOM), PKCS11_ID(PKCS11_CMD_DERIVE_KEY), PKCS11_ID(PKCS11_CMD_RELEASE_ACTIVE_PROCESSING), PKCS11_ID(PKCS11_CMD_DIGEST_INIT), PKCS11_ID(PKCS11_CMD_DIGEST_UPDATE), PKCS11_ID(PKCS11_CMD_DIGEST_KEY), PKCS11_ID(PKCS11_CMD_DIGEST_ONESHOT), PKCS11_ID(PKCS11_CMD_DIGEST_FINAL), PKCS11_ID(PKCS11_CMD_GENERATE_KEY_PAIR), PKCS11_ID(PKCS11_CMD_WRAP_KEY), PKCS11_ID(PKCS11_CMD_UNWRAP_KEY), }; static const struct any_id __maybe_unused string_slot_flags[] = { PKCS11_ID(PKCS11_CKFS_TOKEN_PRESENT), PKCS11_ID(PKCS11_CKFS_REMOVABLE_DEVICE), PKCS11_ID(PKCS11_CKFS_HW_SLOT), }; static const struct any_id __maybe_unused string_token_flags[] = { PKCS11_ID(PKCS11_CKFT_RNG), PKCS11_ID(PKCS11_CKFT_WRITE_PROTECTED), PKCS11_ID(PKCS11_CKFT_LOGIN_REQUIRED), PKCS11_ID(PKCS11_CKFT_USER_PIN_INITIALIZED), PKCS11_ID(PKCS11_CKFT_RESTORE_KEY_NOT_NEEDED), PKCS11_ID(PKCS11_CKFT_CLOCK_ON_TOKEN), PKCS11_ID(PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH), PKCS11_ID(PKCS11_CKFT_DUAL_CRYPTO_OPERATIONS), PKCS11_ID(PKCS11_CKFT_TOKEN_INITIALIZED), PKCS11_ID(PKCS11_CKFT_USER_PIN_COUNT_LOW), PKCS11_ID(PKCS11_CKFT_USER_PIN_FINAL_TRY), PKCS11_ID(PKCS11_CKFT_USER_PIN_LOCKED), PKCS11_ID(PKCS11_CKFT_USER_PIN_TO_BE_CHANGED), PKCS11_ID(PKCS11_CKFT_SO_PIN_COUNT_LOW), PKCS11_ID(PKCS11_CKFT_SO_PIN_FINAL_TRY), PKCS11_ID(PKCS11_CKFT_SO_PIN_LOCKED), PKCS11_ID(PKCS11_CKFT_SO_PIN_TO_BE_CHANGED), PKCS11_ID(PKCS11_CKFT_ERROR_STATE), }; static const struct any_id __maybe_unused string_session_flags[] = { PKCS11_ID(PKCS11_CKFSS_RW_SESSION), PKCS11_ID(PKCS11_CKFSS_SERIAL_SESSION), }; static const struct any_id __maybe_unused string_session_state[] = { PKCS11_ID(PKCS11_CKS_RO_PUBLIC_SESSION), PKCS11_ID(PKCS11_CKS_RO_USER_FUNCTIONS), PKCS11_ID(PKCS11_CKS_RW_PUBLIC_SESSION), PKCS11_ID(PKCS11_CKS_RW_USER_FUNCTIONS), PKCS11_ID(PKCS11_CKS_RW_SO_FUNCTIONS), }; static const struct any_id __maybe_unused string_rc[] = { PKCS11_ID(PKCS11_CKR_OK), PKCS11_ID(PKCS11_CKR_SLOT_ID_INVALID), PKCS11_ID(PKCS11_CKR_GENERAL_ERROR), PKCS11_ID(PKCS11_CKR_FUNCTION_FAILED), PKCS11_ID(PKCS11_CKR_ARGUMENTS_BAD), PKCS11_ID(PKCS11_CKR_ATTRIBUTE_READ_ONLY), PKCS11_ID(PKCS11_CKR_ATTRIBUTE_SENSITIVE), PKCS11_ID(PKCS11_CKR_ATTRIBUTE_TYPE_INVALID), PKCS11_ID(PKCS11_CKR_ATTRIBUTE_VALUE_INVALID), PKCS11_ID(PKCS11_CKR_ACTION_PROHIBITED), PKCS11_ID(PKCS11_CKR_DATA_LEN_RANGE), PKCS11_ID(PKCS11_CKR_DEVICE_MEMORY), PKCS11_ID(PKCS11_CKR_ENCRYPTED_DATA_INVALID), PKCS11_ID(PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE), PKCS11_ID(PKCS11_CKR_KEY_HANDLE_INVALID), PKCS11_ID(PKCS11_CKR_KEY_SIZE_RANGE), PKCS11_ID(PKCS11_CKR_KEY_TYPE_INCONSISTENT), PKCS11_ID(PKCS11_CKR_KEY_INDIGESTIBLE), PKCS11_ID(PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED), PKCS11_ID(PKCS11_CKR_KEY_NOT_WRAPPABLE), PKCS11_ID(PKCS11_CKR_KEY_UNEXTRACTABLE), PKCS11_ID(PKCS11_CKR_MECHANISM_INVALID), PKCS11_ID(PKCS11_CKR_MECHANISM_PARAM_INVALID), PKCS11_ID(PKCS11_CKR_OBJECT_HANDLE_INVALID), PKCS11_ID(PKCS11_CKR_OPERATION_ACTIVE), PKCS11_ID(PKCS11_CKR_OPERATION_NOT_INITIALIZED), PKCS11_ID(PKCS11_CKR_PIN_INCORRECT), PKCS11_ID(PKCS11_CKR_PIN_INVALID), PKCS11_ID(PKCS11_CKR_PIN_LEN_RANGE), PKCS11_ID(PKCS11_CKR_PIN_EXPIRED), PKCS11_ID(PKCS11_CKR_PIN_LOCKED), PKCS11_ID(PKCS11_CKR_SESSION_HANDLE_INVALID), PKCS11_ID(PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED), PKCS11_ID(PKCS11_CKR_SESSION_READ_ONLY), PKCS11_ID(PKCS11_CKR_SESSION_EXISTS), PKCS11_ID(PKCS11_CKR_SESSION_READ_ONLY_EXISTS), PKCS11_ID(PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS), PKCS11_ID(PKCS11_CKR_SIGNATURE_INVALID), PKCS11_ID(PKCS11_CKR_SIGNATURE_LEN_RANGE), PKCS11_ID(PKCS11_CKR_TEMPLATE_INCOMPLETE), PKCS11_ID(PKCS11_CKR_TEMPLATE_INCONSISTENT), PKCS11_ID(PKCS11_CKR_TOKEN_NOT_PRESENT), PKCS11_ID(PKCS11_CKR_TOKEN_NOT_RECOGNIZED), PKCS11_ID(PKCS11_CKR_TOKEN_WRITE_PROTECTED), PKCS11_ID(PKCS11_CKR_UNWRAPPING_KEY_HANDLE_INVALID), PKCS11_ID(PKCS11_CKR_UNWRAPPING_KEY_SIZE_RANGE), PKCS11_ID(PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT), PKCS11_ID(PKCS11_CKR_USER_ALREADY_LOGGED_IN), PKCS11_ID(PKCS11_CKR_USER_NOT_LOGGED_IN), PKCS11_ID(PKCS11_CKR_USER_PIN_NOT_INITIALIZED), PKCS11_ID(PKCS11_CKR_USER_TYPE_INVALID), PKCS11_ID(PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN), PKCS11_ID(PKCS11_CKR_USER_TOO_MANY_TYPES), PKCS11_ID(PKCS11_CKR_WRAPPED_KEY_INVALID), PKCS11_ID(PKCS11_CKR_WRAPPED_KEY_LEN_RANGE), PKCS11_ID(PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID), PKCS11_ID(PKCS11_CKR_WRAPPING_KEY_SIZE_RANGE), PKCS11_ID(PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT), PKCS11_ID(PKCS11_CKR_RANDOM_SEED_NOT_SUPPORTED), PKCS11_ID(PKCS11_CKR_RANDOM_NO_RNG), PKCS11_ID(PKCS11_CKR_DOMAIN_PARAMS_INVALID), PKCS11_ID(PKCS11_CKR_CURVE_NOT_SUPPORTED), PKCS11_ID(PKCS11_CKR_BUFFER_TOO_SMALL), PKCS11_ID(PKCS11_CKR_PIN_TOO_WEAK), PKCS11_ID(PKCS11_RV_NOT_FOUND), PKCS11_ID(PKCS11_RV_NOT_IMPLEMENTED), }; static const struct any_id __maybe_unused string_class[] = { PKCS11_ID(PKCS11_CKO_SECRET_KEY), PKCS11_ID(PKCS11_CKO_PUBLIC_KEY), PKCS11_ID(PKCS11_CKO_PRIVATE_KEY), PKCS11_ID(PKCS11_CKO_OTP_KEY), PKCS11_ID(PKCS11_CKO_CERTIFICATE), PKCS11_ID(PKCS11_CKO_DATA), PKCS11_ID(PKCS11_CKO_DOMAIN_PARAMETERS), PKCS11_ID(PKCS11_CKO_HW_FEATURE), PKCS11_ID(PKCS11_CKO_MECHANISM), PKCS11_ID(PKCS11_CKO_UNDEFINED_ID) }; static const struct any_id __maybe_unused string_key_type[] = { PKCS11_ID(PKCS11_CKK_AES), PKCS11_ID(PKCS11_CKK_GENERIC_SECRET), PKCS11_ID(PKCS11_CKK_MD5_HMAC), PKCS11_ID(PKCS11_CKK_SHA_1_HMAC), PKCS11_ID(PKCS11_CKK_SHA224_HMAC), PKCS11_ID(PKCS11_CKK_SHA256_HMAC), PKCS11_ID(PKCS11_CKK_SHA384_HMAC), PKCS11_ID(PKCS11_CKK_SHA512_HMAC), PKCS11_ID(PKCS11_CKK_EC), PKCS11_ID(PKCS11_CKK_EC_EDWARDS), PKCS11_ID(PKCS11_CKK_EDDSA), PKCS11_ID(PKCS11_CKK_RSA), PKCS11_ID(PKCS11_CKK_UNDEFINED_ID) }; static const struct any_id __maybe_unused string_certificate_type[] = { PKCS11_ID(PKCS11_CKC_X_509), PKCS11_ID(PKCS11_CKC_X_509_ATTR_CERT), PKCS11_ID(PKCS11_CKC_WTLS), PKCS11_ID(PKCS11_CKC_UNDEFINED_ID) }; /* * Processing IDs not exported in the TA API. * PKCS11_CKM_* mechanism IDs are looked up from mechanism_string_id(). */ static const struct any_id __maybe_unused string_internal_processing[] = { PKCS11_ID(PKCS11_PROCESSING_IMPORT), }; static const struct any_id __maybe_unused string_functions[] = { PKCS11_ID(PKCS11_FUNCTION_DIGEST), PKCS11_ID(PKCS11_FUNCTION_IMPORT), PKCS11_ID(PKCS11_FUNCTION_ENCRYPT), PKCS11_ID(PKCS11_FUNCTION_DECRYPT), PKCS11_ID(PKCS11_FUNCTION_SIGN), PKCS11_ID(PKCS11_FUNCTION_VERIFY), PKCS11_ID(PKCS11_FUNCTION_DERIVE), PKCS11_ID(PKCS11_FUNCTION_WRAP), PKCS11_ID(PKCS11_FUNCTION_UNWRAP), }; /* * Conversion between PKCS11 TA and GPD TEE return codes */ enum pkcs11_rc tee2pkcs_error(TEE_Result res) { switch (res) { case TEE_SUCCESS: return PKCS11_CKR_OK; case TEE_ERROR_BAD_PARAMETERS: return PKCS11_CKR_ARGUMENTS_BAD; case TEE_ERROR_CIPHERTEXT_INVALID: return PKCS11_CKR_ENCRYPTED_DATA_INVALID; case TEE_ERROR_OUT_OF_MEMORY: return PKCS11_CKR_DEVICE_MEMORY; case TEE_ERROR_SHORT_BUFFER: return PKCS11_CKR_BUFFER_TOO_SMALL; case TEE_ERROR_MAC_INVALID: case TEE_ERROR_SIGNATURE_INVALID: return PKCS11_CKR_SIGNATURE_INVALID; default: return PKCS11_CKR_GENERAL_ERROR; } } /* * Helper functions to analyse PKCS11 identifiers */ /* Check attribute ID is known and size matches if fixed */ bool valid_pkcs11_attribute_id(uint32_t id, uint32_t size) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(attr_ids); n++) if (id == attr_ids[n].id) return !attr_ids[n].size || size == attr_ids[n].size; return false; } size_t pkcs11_attr_is_type(uint32_t attribute_id) { enum pkcs11_attr_id id = attribute_id; switch (id) { case PKCS11_CKA_KEY_TYPE: case PKCS11_CKA_MECHANISM_TYPE: case PKCS11_CKA_KEY_GEN_MECHANISM: return sizeof(uint32_t); default: return 0; } } bool pkcs11_attr_has_indirect_attributes(uint32_t attribute_id) { switch (attribute_id) { case PKCS11_CKA_WRAP_TEMPLATE: case PKCS11_CKA_UNWRAP_TEMPLATE: case PKCS11_CKA_DERIVE_TEMPLATE: return true; default: return false; } } bool pkcs11_class_has_type(uint32_t class) { enum pkcs11_class_id class_id = class; switch (class_id) { case PKCS11_CKO_CERTIFICATE: case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_MECHANISM: case PKCS11_CKO_HW_FEATURE: return true; default: return false; } } bool pkcs11_attr_class_is_key(uint32_t class) { enum pkcs11_class_id class_id = class; switch (class_id) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: return true; default: return false; } } bool key_type_is_symm_key(uint32_t id) { enum pkcs11_key_type key_type = id; switch (key_type) { case PKCS11_CKK_AES: case PKCS11_CKK_GENERIC_SECRET: case PKCS11_CKK_MD5_HMAC: case PKCS11_CKK_SHA_1_HMAC: case PKCS11_CKK_SHA224_HMAC: case PKCS11_CKK_SHA256_HMAC: case PKCS11_CKK_SHA384_HMAC: case PKCS11_CKK_SHA512_HMAC: return true; default: return false; } } bool key_type_is_asymm_key(uint32_t id) { enum pkcs11_key_type key_type = id; switch (key_type) { case PKCS11_CKK_EC: case PKCS11_CKK_EC_EDWARDS: case PKCS11_CKK_RSA: return true; default: return false; } } /* * Returns shift position or -1 on error. * Mainly used when PKCS11_SHEAD_WITH_BOOLPROPS is enabled */ int pkcs11_attr2boolprop_shift(uint32_t attr) { static const uint32_t bpa[] = { [BPA_TOKEN] = PKCS11_CKA_TOKEN, [BPA_PRIVATE] = PKCS11_CKA_PRIVATE, [BPA_TRUSTED] = PKCS11_CKA_TRUSTED, [BPA_SENSITIVE] = PKCS11_CKA_SENSITIVE, [BPA_ENCRYPT] = PKCS11_CKA_ENCRYPT, [BPA_DECRYPT] = PKCS11_CKA_DECRYPT, [BPA_WRAP] = PKCS11_CKA_WRAP, [BPA_UNWRAP] = PKCS11_CKA_UNWRAP, [BPA_SIGN] = PKCS11_CKA_SIGN, [BPA_SIGN_RECOVER] = PKCS11_CKA_SIGN_RECOVER, [BPA_VERIFY] = PKCS11_CKA_VERIFY, [BPA_VERIFY_RECOVER] = PKCS11_CKA_VERIFY_RECOVER, [BPA_DERIVE] = PKCS11_CKA_DERIVE, [BPA_EXTRACTABLE] = PKCS11_CKA_EXTRACTABLE, [BPA_LOCAL] = PKCS11_CKA_LOCAL, [BPA_NEVER_EXTRACTABLE] = PKCS11_CKA_NEVER_EXTRACTABLE, [BPA_ALWAYS_SENSITIVE] = PKCS11_CKA_ALWAYS_SENSITIVE, [BPA_MODIFIABLE] = PKCS11_CKA_MODIFIABLE, [BPA_COPYABLE] = PKCS11_CKA_COPYABLE, [BPA_DESTROYABLE] = PKCS11_CKA_DESTROYABLE, [BPA_ALWAYS_AUTHENTICATE] = PKCS11_CKA_ALWAYS_AUTHENTICATE, [BPA_WRAP_WITH_TRUSTED] = PKCS11_CKA_WRAP_WITH_TRUSTED, }; size_t pos = 0; for (pos = 0; pos < ARRAY_SIZE(bpa); pos++) if (bpa[pos] == attr) return (int)pos; return -1; } /* Initialize a TEE attribute for a target PKCS11 TA attribute in an object */ bool pkcs2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id, struct pkcs11_object *obj, enum pkcs11_attr_id pkcs11_id) { void *a_ptr = NULL; uint8_t *der_ptr = NULL; uint32_t a_size = 0; uint32_t data32 = 0; size_t hsize = 0; size_t qsize = 0; switch (tee_id) { case TEE_ATTR_ECC_PUBLIC_VALUE_X: case TEE_ATTR_ECC_PUBLIC_VALUE_Y: case TEE_ATTR_ECC_CURVE: if (get_attribute_ptr(obj->attributes, PKCS11_CKA_EC_PARAMS, &a_ptr, &a_size) || !a_ptr) { EMSG("Missing EC_PARAMS attribute"); return false; } if (tee_id == TEE_ATTR_ECC_CURVE) { data32 = ec_params2tee_curve(a_ptr, a_size); TEE_InitValueAttribute(tee_ref, TEE_ATTR_ECC_CURVE, data32, 0); return true; } data32 = (ec_params2tee_keysize(a_ptr, a_size) + 7) / 8; /* * For private keys we need EC public key for TEE operations so * first try to get hidden EC POINT and as backwards * compatibility also check for CKA_EC_POINT. * * For public keys we only have CKA_EC_POINT but there is no * harm to check for hidden one too. */ if (get_attribute_ptr(obj->attributes, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, &a_ptr, &a_size)) { if (get_attribute_ptr(obj->attributes, PKCS11_CKA_EC_POINT, &a_ptr, &a_size)) { /* * Without EC public key we cannot proceed. */ EMSG("Missing EC_POINT attribute"); return false; } } der_ptr = (uint8_t *)a_ptr; if (der_ptr[0] != 0x04) { EMSG("Unsupported DER type"); return false; } if ((der_ptr[1] & 0x80) == 0) { /* DER short definitive form up to 127 bytes */ qsize = der_ptr[1] & 0x7F; hsize = 2 /* der */ + 1 /* point compression */; } else if (der_ptr[1] == 0x81) { /* DER long definitive form up to 255 bytes */ qsize = der_ptr[2]; hsize = 3 /* der */ + 1 /* point compression */; } else { EMSG("Unsupported DER long form"); return false; } if (der_ptr[hsize - 1] != 0x04) { EMSG("Unsupported EC_POINT compression"); return false; } if (a_size != (hsize - 1) + qsize) { EMSG("Invalid EC_POINT attribute"); return false; } if (a_size != hsize + 2 * data32) { EMSG("Invalid EC_POINT attribute"); return false; } if (tee_id == TEE_ATTR_ECC_PUBLIC_VALUE_X) TEE_InitRefAttribute(tee_ref, tee_id, der_ptr + hsize, data32); else TEE_InitRefAttribute(tee_ref, tee_id, der_ptr + hsize + data32, data32); return true; default: break; } if (get_attribute_ptr(obj->attributes, pkcs11_id, &a_ptr, &a_size)) return false; TEE_InitRefAttribute(tee_ref, tee_id, a_ptr, a_size); return true; } /* * Initialize a TEE attribute with hash of a target PKCS11 TA attribute * in an object. */ enum pkcs11_rc pkcs2tee_load_hashed_attr(TEE_Attribute *tee_ref, uint32_t tee_id, struct pkcs11_object *obj, enum pkcs11_attr_id pkcs11_id, uint32_t tee_algo, void *hash_ptr, uint32_t *hash_size) { TEE_OperationHandle handle = TEE_HANDLE_NULL; void *a_ptr = NULL; uint32_t a_size = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; TEE_Result res = TEE_ERROR_GENERIC; size_t tmp_sz = 0; rc = get_attribute_ptr(obj->attributes, pkcs11_id, &a_ptr, &a_size); if (rc) return rc; res = TEE_AllocateOperation(&handle, tee_algo, TEE_MODE_DIGEST, 0); if (res) { EMSG("TEE_AllocateOperation() failed %#"PRIx32, tee_algo); return tee2pkcs_error(res); } tmp_sz = *hash_size; res = TEE_DigestDoFinal(handle, a_ptr, a_size, hash_ptr, &tmp_sz); *hash_size = tmp_sz; TEE_FreeOperation(handle); if (res) { EMSG("TEE_DigestDoFinal() failed %#"PRIx32, tee_algo); return PKCS11_CKR_FUNCTION_FAILED; } TEE_InitRefAttribute(tee_ref, tee_id, hash_ptr, *hash_size); return PKCS11_CKR_OK; } /* Easy conversion between PKCS11 TA function of TEE crypto mode */ void pkcs2tee_mode(uint32_t *tee_id, enum processing_func function) { switch (function) { case PKCS11_FUNCTION_ENCRYPT: *tee_id = TEE_MODE_ENCRYPT; break; case PKCS11_FUNCTION_DECRYPT: *tee_id = TEE_MODE_DECRYPT; break; case PKCS11_FUNCTION_SIGN: *tee_id = TEE_MODE_SIGN; break; case PKCS11_FUNCTION_VERIFY: *tee_id = TEE_MODE_VERIFY; break; case PKCS11_FUNCTION_DERIVE: *tee_id = TEE_MODE_DERIVE; break; case PKCS11_FUNCTION_DIGEST: *tee_id = TEE_MODE_DIGEST; break; default: TEE_Panic(function); } } #if CFG_TEE_TA_LOG_LEVEL > 0 const char *id2str_rc(uint32_t id) { return ID2STR(id, string_rc, "PKCS11_CKR_"); } const char *id2str_ta_cmd(uint32_t id) { return ID2STR(id, string_ta_cmd, NULL); } const char *id2str_slot_flag(uint32_t id) { return ID2STR(id, string_slot_flags, "PKCS11_CKFS_"); } const char *id2str_token_flag(uint32_t id) { return ID2STR(id, string_token_flags, "PKCS11_CKFT_"); } const char *id2str_session_flag(uint32_t id) { return ID2STR(id, string_session_flags, "PKCS11_CKFSS_"); } const char *id2str_session_state(uint32_t id) { return ID2STR(id, string_session_state, "PKCS11_CKS_"); } const char *id2str_attr(uint32_t id) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(attr_ids); n++) { if (id == attr_ids[n].id) { /* Skip PKCS11_CKA_ prefix */ return attr_ids[n].string + strlen("PKCS11_CKA_"); } } return unknown; } const char *id2str_class(uint32_t id) { return ID2STR(id, string_class, "PKCS11_CKO_"); } const char *id2str_type(uint32_t id, uint32_t class) { enum pkcs11_class_id class_id = class; enum pkcs11_key_type key_type = id; switch (class_id) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: return id2str_key_type(key_type); default: return unknown; } } const char *id2str_key_type(uint32_t id) { return ID2STR(id, string_key_type, "PKCS11_CKK_"); } const char *id2str_certificate_type(uint32_t id) { return ID2STR(id, string_certificate_type, "PKCS11_CKC_"); } const char *id2str_attr_value(uint32_t id, size_t size, void *value) { static const char str_true[] = "TRUE"; static const char str_false[] = "FALSE"; static const char str_unknown[] = "*"; uint32_t type = 0; if (pkcs11_attr2boolprop_shift(id) >= 0) return *(uint8_t *)value ? str_true : str_false; if (size < sizeof(uint32_t)) return str_unknown; TEE_MemMove(&type, value, sizeof(uint32_t)); switch (id) { case PKCS11_CKA_CLASS: return id2str_class(type); case PKCS11_CKA_KEY_TYPE: return id2str_key_type(type); case PKCS11_CKA_MECHANISM_TYPE: return id2str_mechanism(type); default: return str_unknown; } } const char *id2str_proc(uint32_t id) { const char *str = ID2STR(id, string_internal_processing, "PKCS11_PROCESSING_"); if (str != unknown) return str; return id2str_mechanism(id); } const char *id2str_function(uint32_t id) { return ID2STR(id, string_functions, "PKCS11_FUNCTION_"); } #endif /*CFG_TEE_TA_LOG_LEVEL*/ optee_os-4.3.0/ta/pkcs11/src/pkcs11_helpers.h000066400000000000000000000066521464416617300206520ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2020, Linaro Limited */ #ifndef PKCS11_HELPERS_H #define PKCS11_HELPERS_H #include #include #include #include #include #include struct pkcs11_object; /* * TEE invocation parameter#0 is an in/out buffer of at least 32bit * to store the TA PKCS#11 compliant return value. */ #define TEE_PARAM0_SIZE_MIN sizeof(uint32_t) /* GPD TEE to PKCS11 status conversion */ enum pkcs11_rc tee2pkcs_error(TEE_Result res); /* * Return true if and only if attribute ID with companion attribute value * size do match a valid attribute identifier. * * @attribute_id - Target PKCS11 attribute ID * @size - Byte size of the attribute value, 0 if non-constant size */ bool valid_pkcs11_attribute_id(uint32_t attribute_id, uint32_t size); /* * Return type attribute byte size if @attribute_id is the ID of a type * attribute or 0 if not. */ size_t pkcs11_attr_is_type(uint32_t attribute_id); /* Return true if the attribute has indirect attributes */ bool pkcs11_attr_has_indirect_attributes(uint32_t attribute_id); /* Return true if the object class is related to a type-in-class */ bool pkcs11_class_has_type(uint32_t class_id); /* Return true if the object class relates to a key */ bool pkcs11_attr_class_is_key(uint32_t class_id); /* Return true if the key type @key_type_id relates to a symmetric key */ bool key_type_is_symm_key(uint32_t key_type_id); /* Return true if the key type @key_type_id relates to an asymmetric key */ bool key_type_is_asymm_key(uint32_t key_type_id); /* Boolprop flag shift position if @attribute_id is boolean, else -1 */ int pkcs11_attr2boolprop_shift(uint32_t attribute_id); /* Convert PKCS11 TA function ID into a TEE crypto operation mode */ void pkcs2tee_mode(uint32_t *tee_id, enum processing_func function); /* Load TEE operation attributes from a PKCS11 object, return false on error */ bool pkcs2tee_load_attr(TEE_Attribute *tee_ref, uint32_t tee_id, struct pkcs11_object *obj, enum pkcs11_attr_id pkcs11_id); /* Hash and load TEE operation attributes from a PKCS11 object */ enum pkcs11_rc pkcs2tee_load_hashed_attr(TEE_Attribute *tee_ref, uint32_t tee_id, struct pkcs11_object *obj, enum pkcs11_attr_id pkcs11_id, uint32_t tee_algo, void *hash_ptr, uint32_t *hash_size); /* Return true if attribute is a boolean, false otherwise */ static inline bool pkcs11_attr_is_boolean(enum pkcs11_attr_id id) { return pkcs11_attr2boolprop_shift(id) >= 0; } #if CFG_TEE_TA_LOG_LEVEL > 0 /* Id-to-string conversions only for trace support */ const char *id2str_ta_cmd(uint32_t id); const char *id2str_rc(uint32_t id); const char *id2str_slot_flag(uint32_t id); const char *id2str_token_flag(uint32_t id); const char *id2str_session_flag(uint32_t id); const char *id2str_session_state(uint32_t id); const char *id2str_attr(uint32_t id); const char *id2str_class(uint32_t id); const char *id2str_type(uint32_t id, uint32_t class); const char *id2str_key_type(uint32_t id); const char *id2str_certificate_type(uint32_t id); const char *id2str_attr_value(uint32_t id, size_t size, void *value); const char *id2str_proc(uint32_t id); const char *id2str_function(uint32_t id); static inline const char *id2str_mechanism(enum pkcs11_mechanism_id id) { return mechanism_string_id(id); } #endif /* CFG_TEE_TA_LOG_LEVEL > 0 */ #endif /*PKCS11_HELPERS_H*/ optee_os-4.3.0/ta/pkcs11/src/pkcs11_token.c000066400000000000000000001274711464416617300203260ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include #include #include #include #include "attributes.h" #include "handle.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "serializer.h" #include "token_capabilities.h" /* Number of tokens implemented by the TA. Token ID is the token index */ #define TOKEN_COUNT CFG_PKCS11_TA_TOKEN_COUNT /* RNG chunk size used to split RNG generation to smaller sizes */ #define RNG_CHUNK_SIZE 512U /* * Structure tracking client applications * * @link - chained list of registered client applications * @sessions - list of the PKCS11 sessions opened by the client application * @object_handle_db - Database for object handles in name space of client */ struct pkcs11_client { TAILQ_ENTRY(pkcs11_client) link; struct session_list session_list; struct handle_db session_handle_db; struct handle_db object_handle_db; }; /* Static allocation of tokens runtime instances (reset to 0 at load) */ struct ck_token ck_token[TOKEN_COUNT]; static struct client_list pkcs11_client_list = TAILQ_HEAD_INITIALIZER(pkcs11_client_list); static void close_ck_session(struct pkcs11_session *session); struct ck_token *get_token(unsigned int token_id) { if (token_id < TOKEN_COUNT) return &ck_token[confine_array_index(token_id, TOKEN_COUNT)]; return NULL; } unsigned int get_token_id(struct ck_token *token) { ptrdiff_t id = token - ck_token; assert(id >= 0 && id < TOKEN_COUNT); return id; } struct handle_db *get_object_handle_db(struct pkcs11_session *session) { return &session->client->object_handle_db; } struct session_list *get_session_list(struct pkcs11_session *session) { return &session->client->session_list; } struct pkcs11_client *tee_session2client(void *tee_session) { struct pkcs11_client *client = NULL; TAILQ_FOREACH(client, &pkcs11_client_list, link) if (client == tee_session) break; return client; } struct pkcs11_session *pkcs11_handle2session(uint32_t handle, struct pkcs11_client *client) { return handle_lookup(&client->session_handle_db, handle); } void token_invalidate_object_handles(struct pkcs11_object *obj) { struct pkcs11_client *client = NULL; uint32_t handle = 0; TAILQ_FOREACH(client, &pkcs11_client_list, link) { handle = handle_lookup_handle(&client->object_handle_db, obj); if (handle) handle_invalidate(&client->object_handle_db, handle); } } struct pkcs11_client *register_client(void) { struct pkcs11_client *client = NULL; client = TEE_Malloc(sizeof(*client), TEE_MALLOC_FILL_ZERO); if (!client) return NULL; TAILQ_INSERT_HEAD(&pkcs11_client_list, client, link); TAILQ_INIT(&client->session_list); handle_db_init(&client->session_handle_db); handle_db_init(&client->object_handle_db); return client; } void unregister_client(struct pkcs11_client *client) { struct pkcs11_session *session = NULL; struct pkcs11_session *next = NULL; if (!client) { EMSG("Invalid TEE session handle"); return; } TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) close_ck_session(session); TAILQ_REMOVE(&pkcs11_client_list, client, link); handle_db_destroy(&client->object_handle_db); handle_db_destroy(&client->session_handle_db); TEE_Free(client); } static TEE_Result pkcs11_token_init(unsigned int id) { struct ck_token *token = init_persistent_db(id); if (!token) return TEE_ERROR_SECURITY; if (token->state == PKCS11_TOKEN_RESET) { /* As per PKCS#11 spec, token resets to read/write state */ token->state = PKCS11_TOKEN_READ_WRITE; token->session_count = 0; token->rw_session_count = 0; } return TEE_SUCCESS; } TEE_Result pkcs11_init(void) { unsigned int id = 0; TEE_Result ret = TEE_ERROR_GENERIC; for (id = 0; id < TOKEN_COUNT; id++) { ret = pkcs11_token_init(id); if (ret) break; } return ret; } void pkcs11_deinit(void) { unsigned int id = 0; for (id = 0; id < TOKEN_COUNT; id++) close_persistent_db(get_token(id)); } /* * Currently no support for dual operations. */ enum pkcs11_rc set_processing_state(struct pkcs11_session *session, enum processing_func function, struct pkcs11_object *obj1, struct pkcs11_object *obj2) { enum pkcs11_proc_state state = PKCS11_SESSION_READY; struct active_processing *proc = NULL; if (session->processing) return PKCS11_CKR_OPERATION_ACTIVE; switch (function) { case PKCS11_FUNCTION_ENCRYPT: state = PKCS11_SESSION_ENCRYPTING; break; case PKCS11_FUNCTION_DECRYPT: state = PKCS11_SESSION_DECRYPTING; break; case PKCS11_FUNCTION_SIGN: state = PKCS11_SESSION_SIGNING; break; case PKCS11_FUNCTION_VERIFY: state = PKCS11_SESSION_VERIFYING; break; case PKCS11_FUNCTION_DIGEST: state = PKCS11_SESSION_DIGESTING; break; case PKCS11_FUNCTION_DERIVE: case PKCS11_FUNCTION_WRAP: case PKCS11_FUNCTION_UNWRAP: state = PKCS11_SESSION_BUSY; break; default: TEE_Panic(function); return -1; } proc = TEE_Malloc(sizeof(*proc), TEE_MALLOC_FILL_ZERO); if (!proc) return PKCS11_CKR_DEVICE_MEMORY; /* Boolean are default to false and pointers to NULL */ proc->state = state; proc->step = PKCS11_FUNC_STEP_INIT; proc->tee_op_handle = TEE_HANDLE_NULL; proc->tee_hash_algo = 0; proc->tee_op_handle2 = TEE_HANDLE_NULL; if (obj1 && get_bool(obj1->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) proc->always_authen = true; if (obj2 && get_bool(obj2->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE)) proc->always_authen = true; session->processing = proc; return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *out = params + 2; uint32_t token_id = 0; const size_t out_size = sizeof(token_id) * TOKEN_COUNT; uint8_t *id = NULL; if (ptypes != exp_pt || params[0].memref.size != TEE_PARAM0_SIZE_MIN) return PKCS11_CKR_ARGUMENTS_BAD; if (out->memref.size < out_size) { out->memref.size = out_size; if (out->memref.buffer) return PKCS11_CKR_BUFFER_TOO_SMALL; else return PKCS11_CKR_OK; } for (token_id = 0, id = out->memref.buffer; token_id < TOKEN_COUNT; token_id++, id += sizeof(token_id)) TEE_MemMove(id, &token_id, sizeof(token_id)); out->memref.size = out_size; return PKCS11_CKR_OK; } static void pad_str(uint8_t *str, size_t size) { int n = strnlen((char *)str, size); TEE_MemFill(str + n, ' ', size - n); } static void set_token_description(struct pkcs11_slot_info *info) { char desc[sizeof(info->slot_description) + 1] = { 0 }; TEE_UUID dev_id = { }; TEE_Result res = TEE_ERROR_GENERIC; int n = 0; res = TEE_GetPropertyAsUUID(TEE_PROPSET_TEE_IMPLEMENTATION, "gpd.tee.deviceID", &dev_id); if (res == TEE_SUCCESS) { n = snprintk(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION " - TEE UUID %pUl", (void *)&dev_id); } else { n = snprintf(desc, sizeof(desc), PKCS11_SLOT_DESCRIPTION " - No TEE UUID"); } if (n < 0 || n >= (int)sizeof(desc)) TEE_Panic(0); TEE_MemMove(info->slot_description, desc, n); pad_str(info->slot_description, sizeof(info->slot_description)); } enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t token_id = 0; struct pkcs11_slot_info info = { .slot_description = PKCS11_SLOT_DESCRIPTION, .manufacturer_id = PKCS11_SLOT_MANUFACTURER, .flags = PKCS11_CKFS_TOKEN_PRESENT, .hardware_version = PKCS11_SLOT_HW_VERSION, .firmware_version = PKCS11_SLOT_FW_VERSION, }; COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_DESCRIPTION) <= sizeof(info.slot_description)); COMPILE_TIME_ASSERT(sizeof(PKCS11_SLOT_MANUFACTURER) <= sizeof(info.manufacturer_id)); if (ptypes != exp_pt || out->memref.size != sizeof(info)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (!get_token(token_id)) return PKCS11_CKR_SLOT_ID_INVALID; set_token_description(&info); pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); out->memref.size = sizeof(info); TEE_MemMove(out->memref.buffer, &info, out->memref.size); return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t token_id = 0; struct ck_token *token = NULL; struct pkcs11_token_info info = { .manufacturer_id = PKCS11_TOKEN_MANUFACTURER, .model = PKCS11_TOKEN_MODEL, .max_session_count = UINT32_MAX, .max_rw_session_count = UINT32_MAX, .max_pin_len = PKCS11_TOKEN_PIN_SIZE_MAX, .min_pin_len = PKCS11_TOKEN_PIN_SIZE_MIN, .total_public_memory = UINT32_MAX, .free_public_memory = UINT32_MAX, .total_private_memory = UINT32_MAX, .free_private_memory = UINT32_MAX, .hardware_version = PKCS11_TOKEN_HW_VERSION, .firmware_version = PKCS11_TOKEN_FW_VERSION, }; char sn[sizeof(info.serial_number) + 1] = { 0 }; int n = 0; if (ptypes != exp_pt || out->memref.size != sizeof(info)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; token = get_token(token_id); if (!token) return PKCS11_CKR_SLOT_ID_INVALID; pad_str(info.manufacturer_id, sizeof(info.manufacturer_id)); pad_str(info.model, sizeof(info.model)); n = snprintf(sn, sizeof(sn), "%0*"PRIu32, (int)sizeof(info.serial_number), token_id); if (n != (int)sizeof(info.serial_number)) TEE_Panic(0); TEE_MemMove(info.serial_number, sn, sizeof(info.serial_number)); pad_str(info.serial_number, sizeof(info.serial_number)); TEE_MemMove(info.label, token->db_main->label, sizeof(info.label)); info.flags = token->db_main->flags; info.session_count = token->session_count; info.rw_session_count = token->rw_session_count; TEE_MemMove(out->memref.buffer, &info, sizeof(info)); return PKCS11_CKR_OK; } static void dmsg_print_supported_mechanism(unsigned int token_id __maybe_unused, uint32_t *array __maybe_unused, size_t count __maybe_unused) { size_t __maybe_unused n = 0; if (TRACE_LEVEL < TRACE_DEBUG) return; for (n = 0; n < count; n++) DMSG("PKCS11 token %"PRIu32": mechanism 0x%04"PRIx32": %s", token_id, array[n], id2str_mechanism(array[n])); } enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t token_id = 0; struct ck_token __maybe_unused *token = NULL; size_t count = 0; uint32_t *array = NULL; if (ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; token = get_token(token_id); if (!token) return PKCS11_CKR_SLOT_ID_INVALID; count = out->memref.size / sizeof(*array); array = tee_malloc_mechanism_list(&count); if (out->memref.size < count * sizeof(*array)) { assert(!array); out->memref.size = count * sizeof(*array); if (out->memref.buffer) return PKCS11_CKR_BUFFER_TOO_SMALL; else return PKCS11_CKR_OK; } if (!array) return PKCS11_CKR_DEVICE_MEMORY; dmsg_print_supported_mechanism(token_id, array, count); out->memref.size = count * sizeof(*array); TEE_MemMove(out->memref.buffer, array, out->memref.size); TEE_Free(array); return rc; } enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t token_id = 0; uint32_t type = 0; struct ck_token *token = NULL; struct pkcs11_mechanism_info info = { }; if (ptypes != exp_pt || out->memref.size != sizeof(info)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &type, sizeof(uint32_t)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; token = get_token(token_id); if (!token) return PKCS11_CKR_SLOT_ID_INVALID; if (!mechanism_is_valid(type)) return PKCS11_CKR_MECHANISM_INVALID; info.flags = mechanism_supported_flags(type); pkcs11_mechanism_supported_key_sizes(type, &info.min_key_size, &info.max_key_size); TEE_MemMove(out->memref.buffer, &info, sizeof(info)); DMSG("PKCS11 token %"PRIu32": mechanism 0x%"PRIx32" info", token_id, type); return PKCS11_CKR_OK; } /* Select the ReadOnly or ReadWrite state for session login state */ static void set_session_state(struct pkcs11_client *client, struct pkcs11_session *session, bool readonly) { struct pkcs11_session *sess = NULL; enum pkcs11_session_state state = PKCS11_CKS_RO_PUBLIC_SESSION; /* Default to public session if no session already registered */ if (readonly) state = PKCS11_CKS_RO_PUBLIC_SESSION; else state = PKCS11_CKS_RW_PUBLIC_SESSION; /* * No need to check all client sessions, the first found in * target token gives client login configuration. */ TAILQ_FOREACH(sess, &client->session_list, link) { assert(sess != session); if (sess->token == session->token) { switch (sess->state) { case PKCS11_CKS_RW_PUBLIC_SESSION: case PKCS11_CKS_RO_PUBLIC_SESSION: if (readonly) state = PKCS11_CKS_RO_PUBLIC_SESSION; else state = PKCS11_CKS_RW_PUBLIC_SESSION; break; case PKCS11_CKS_RO_USER_FUNCTIONS: case PKCS11_CKS_RW_USER_FUNCTIONS: if (readonly) state = PKCS11_CKS_RO_USER_FUNCTIONS; else state = PKCS11_CKS_RW_USER_FUNCTIONS; break; case PKCS11_CKS_RW_SO_FUNCTIONS: if (readonly) TEE_Panic(0); else state = PKCS11_CKS_RW_SO_FUNCTIONS; break; default: TEE_Panic(0); } break; } } session->state = state; } enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t token_id = 0; uint32_t flags = 0; struct ck_token *token = NULL; struct pkcs11_session *session = NULL; bool readonly = false; if (!client || ptypes != exp_pt || out->memref.size != sizeof(session->handle)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(token_id)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &flags, sizeof(flags)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; token = get_token(token_id); if (!token) return PKCS11_CKR_SLOT_ID_INVALID; /* Sanitize session flags */ if (!(flags & PKCS11_CKFSS_SERIAL_SESSION)) return PKCS11_CKR_SESSION_PARALLEL_NOT_SUPPORTED; if (flags & ~(PKCS11_CKFSS_RW_SESSION | PKCS11_CKFSS_SERIAL_SESSION)) return PKCS11_CKR_ARGUMENTS_BAD; readonly = !(flags & PKCS11_CKFSS_RW_SESSION); if (!readonly && token->state == PKCS11_TOKEN_READ_ONLY) return PKCS11_CKR_TOKEN_WRITE_PROTECTED; if (readonly) { /* Specifically reject read-only session under SO login */ TAILQ_FOREACH(session, &client->session_list, link) if (pkcs11_session_is_so(session)) return PKCS11_CKR_SESSION_READ_WRITE_SO_EXISTS; } session = TEE_Malloc(sizeof(*session), TEE_MALLOC_FILL_ZERO); if (!session) return PKCS11_CKR_DEVICE_MEMORY; session->handle = handle_get(&client->session_handle_db, session); if (!session->handle) { TEE_Free(session); return PKCS11_CKR_DEVICE_MEMORY; } session->token = token; session->client = client; LIST_INIT(&session->object_list); set_session_state(client, session, readonly); TAILQ_INSERT_HEAD(&client->session_list, session, link); session->token->session_count++; if (!readonly) session->token->rw_session_count++; TEE_MemMove(out->memref.buffer, &session->handle, sizeof(session->handle)); DMSG("Open PKCS11 session %"PRIu32, session->handle); return PKCS11_CKR_OK; } static void close_ck_session(struct pkcs11_session *session) { release_active_processing(session); release_session_find_obj_context(session); /* Release all session objects */ while (!LIST_EMPTY(&session->object_list)) destroy_object(session, LIST_FIRST(&session->object_list), true); TAILQ_REMOVE(&session->client->session_list, session, link); handle_put(&session->client->session_handle_db, session->handle); session->token->session_count--; if (pkcs11_session_is_read_write(session)) session->token->rw_session_count--; DMSG("Close PKCS11 session %"PRIu32, session->handle); TEE_Free(session); } enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; close_ck_session(session); return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t token_id = 0; struct ck_token *token = NULL; struct pkcs11_session *session = NULL; struct pkcs11_session *next = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; token = get_token(token_id); if (!token) return PKCS11_CKR_SLOT_ID_INVALID; DMSG("Close all sessions for PKCS11 token %"PRIu32, token_id); TAILQ_FOREACH_SAFE(session, &client->session_list, link, next) if (session->token == token) close_ck_session(session); return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_session_info info = { .flags = PKCS11_CKFSS_SERIAL_SESSION, }; if (!client || ptypes != exp_pt || out->memref.size != sizeof(info)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; info.slot_id = get_token_id(session->token); info.state = session->state; if (pkcs11_session_is_read_write(session)) info.flags |= PKCS11_CKFSS_RW_SESSION; TEE_MemMove(out->memref.buffer, &info, sizeof(info)); DMSG("Get find on PKCS11 session %"PRIu32, session->handle); return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); char label[PKCS11_TOKEN_LABEL_SIZE] = { 0 }; struct pkcs11_client *client = NULL; struct pkcs11_session *sess = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct ck_token *token = NULL; TEE_Param *ctrl = params; uint32_t token_id = 0; uint32_t pin_size = 0; void *pin = NULL; struct pkcs11_object *obj = NULL; if (ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get(&ctrlargs, &token_id, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &label, PKCS11_TOKEN_LABEL_SIZE); if (rc) return rc; rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; token = get_token(token_id); if (!token) return PKCS11_CKR_SLOT_ID_INVALID; if (token->db_main->flags & PKCS11_CKFT_SO_PIN_LOCKED) { IMSG("Token %"PRIu32": SO PIN locked", token_id); return PKCS11_CKR_PIN_LOCKED; } /* Check there's no open session on this token */ TAILQ_FOREACH(client, &pkcs11_client_list, link) TAILQ_FOREACH(sess, &client->session_list, link) if (sess->token == token) return PKCS11_CKR_SESSION_EXISTS; /* Verify authentication if token is already initialized */ if (token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED) { unsigned int pin_count = 0; if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && (token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)) { /* Check TEE Identity based authentication if enabled */ rc = verify_identity_auth(token, PKCS11_CKU_SO); if (rc) return rc; goto inited; } /* Check PIN based authentication */ rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, token->db_main->so_pin_salt, token->db_main->so_pin_hash); if (!rc) goto inited; if (rc != PKCS11_CKR_PIN_INCORRECT) return rc; token->db_main->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; token->db_main->so_pin_count++; pin_count = token->db_main->so_pin_count; if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) token->db_main->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; if (pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) token->db_main->flags |= PKCS11_CKFT_SO_PIN_LOCKED; update_persistent_db(token); return PKCS11_CKR_PIN_INCORRECT; } /* Initialize SO's authentication */ if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && !pin) { rc = setup_so_identity_auth_from_client(token); if (rc) return rc; } else { /* * The spec doesn't permit returning * PKCS11_CKR_PIN_LEN_RANGE for this function, take another * error code. */ if (pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) return PKCS11_CKR_ARGUMENTS_BAD; rc = hash_pin(PKCS11_CKU_SO, pin, pin_size, &token->db_main->so_pin_salt, token->db_main->so_pin_hash); if (rc) return rc; } inited: /* Make sure SO PIN counters are zeroed */ token->db_main->flags &= ~(PKCS11_CKFT_SO_PIN_COUNT_LOW | PKCS11_CKFT_SO_PIN_FINAL_TRY | PKCS11_CKFT_SO_PIN_LOCKED | PKCS11_CKFT_SO_PIN_TO_BE_CHANGED); token->db_main->so_pin_count = 0; TEE_MemMove(token->db_main->label, label, PKCS11_TOKEN_LABEL_SIZE); token->db_main->flags |= PKCS11_CKFT_TOKEN_INITIALIZED; /* Reset user PIN */ token->db_main->user_pin_salt = 0; token->db_main->flags &= ~(PKCS11_CKFT_USER_PIN_INITIALIZED | PKCS11_CKFT_USER_PIN_COUNT_LOW | PKCS11_CKFT_USER_PIN_FINAL_TRY | PKCS11_CKFT_USER_PIN_LOCKED | PKCS11_CKFT_USER_PIN_TO_BE_CHANGED); update_persistent_db(token); /* Remove all persistent objects */ while (!LIST_EMPTY(&token->object_list)) { obj = LIST_FIRST(&token->object_list); /* Try twice otherwise panic! */ if (unregister_persistent_object(token, obj->uuid) && unregister_persistent_object(token, obj->uuid)) TEE_Panic(0); cleanup_persistent_object(obj, token); } IMSG("PKCS11 token %"PRIu32": initialized", token_id); return PKCS11_CKR_OK; } static enum pkcs11_rc set_pin(struct pkcs11_session *session, uint8_t *new_pin, size_t new_pin_size, enum pkcs11_user_type user_type) { struct ck_token *token = session->token; enum pkcs11_rc rc = PKCS11_CKR_OK; uint32_t flags_clear = 0; uint32_t flags_set = 0; if (token->db_main->flags & PKCS11_CKFT_WRITE_PROTECTED) return PKCS11_CKR_TOKEN_WRITE_PROTECTED; if (!pkcs11_session_is_read_write(session)) return PKCS11_CKR_SESSION_READ_ONLY; if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && (token->db_main->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH)) { rc = setup_identity_auth_from_pin(token, user_type, new_pin, new_pin_size); if (rc == PKCS11_CKR_OK) { goto update_db; } else if (rc == PKCS11_CKR_PIN_INVALID && !(token->db_main->flags & PKCS11_CKFT_USER_PIN_INITIALIZED)) { /* * PIN was not compatible with TEE Identity * Authentication syntax so let's assume it might be a * new SO PIN to switch the authentication mode. */ /* Update mode flag if all PIN checks pass */ flags_clear |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; } else { return rc; } } else if ((user_type == PKCS11_CKU_SO) && !new_pin && IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && !(token->db_main->flags & PKCS11_CKFT_USER_PIN_INITIALIZED)) { /* * Allow changing of token authentication mode before user pin * has been initialized. */ /* * Set protected authentication path temporary until * finalized. */ token->db_main->flags |= PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; /* * Setup authentication from currently active TEE Client * Identity. */ rc = setup_identity_auth_from_pin(token, PKCS11_CKU_SO, NULL, 0); if (rc) { /* * Failed to setup protected authentication path so * clear the temporary flag. */ token->db_main->flags &= ~PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH; return rc; } goto update_db; } if (new_pin_size < PKCS11_TOKEN_PIN_SIZE_MIN || new_pin_size > PKCS11_TOKEN_PIN_SIZE_MAX) return PKCS11_CKR_PIN_LEN_RANGE; switch (user_type) { case PKCS11_CKU_SO: rc = hash_pin(user_type, new_pin, new_pin_size, &token->db_main->so_pin_salt, token->db_main->so_pin_hash); if (rc) return rc; token->db_main->so_pin_count = 0; flags_clear |= PKCS11_CKFT_SO_PIN_COUNT_LOW | PKCS11_CKFT_SO_PIN_FINAL_TRY | PKCS11_CKFT_SO_PIN_LOCKED | PKCS11_CKFT_SO_PIN_TO_BE_CHANGED; break; case PKCS11_CKU_USER: rc = hash_pin(user_type, new_pin, new_pin_size, &token->db_main->user_pin_salt, token->db_main->user_pin_hash); if (rc) return rc; token->db_main->user_pin_count = 0; flags_clear |= PKCS11_CKFT_USER_PIN_COUNT_LOW | PKCS11_CKFT_USER_PIN_FINAL_TRY | PKCS11_CKFT_USER_PIN_LOCKED | PKCS11_CKFT_USER_PIN_TO_BE_CHANGED; flags_set |= PKCS11_CKFT_USER_PIN_INITIALIZED; break; default: return PKCS11_CKR_FUNCTION_FAILED; } update_db: token->db_main->flags &= ~flags_clear; token->db_main->flags |= flags_set; update_persistent_db(token); return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct pkcs11_session *session = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; TEE_Param *ctrl = params; uint32_t pin_size = 0; void *pin = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (!pkcs11_session_is_so(session)) return PKCS11_CKR_USER_NOT_LOGGED_IN; assert(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED); IMSG("PKCS11 session %"PRIu32": init PIN", session->handle); return set_pin(session, pin, pin_size, PKCS11_CKU_USER); } static enum pkcs11_rc check_so_pin(struct pkcs11_session *session, uint8_t *pin, size_t pin_size) { struct ck_token *token = session->token; struct token_persistent_main *db = token->db_main; enum pkcs11_rc rc = PKCS11_CKR_OK; assert(db->flags & PKCS11_CKFT_TOKEN_INITIALIZED); if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) return verify_identity_auth(token, PKCS11_CKU_SO); if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; /* * Preset the counter and flags conservatively in the database so that * the tentative is saved whatever happens next. */ db->flags |= PKCS11_CKFT_SO_PIN_COUNT_LOW; db->so_pin_count++; if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) db->flags |= PKCS11_CKFT_SO_PIN_FINAL_TRY; else if (db->so_pin_count == PKCS11_TOKEN_SO_PIN_COUNT_MAX) db->flags |= PKCS11_CKFT_SO_PIN_LOCKED; update_persistent_db(token); rc = verify_pin(PKCS11_CKU_SO, pin, pin_size, db->so_pin_salt, db->so_pin_hash); if (rc == PKCS11_CKR_PIN_INCORRECT) { if (db->flags & PKCS11_CKFT_SO_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; return PKCS11_CKR_PIN_INCORRECT; } if (rc) db->so_pin_count--; else db->so_pin_count = 0; db->flags &= ~PKCS11_CKFT_SO_PIN_LOCKED; if (db->so_pin_count < PKCS11_TOKEN_SO_PIN_COUNT_MAX - 1) { db->flags &= ~PKCS11_CKFT_SO_PIN_FINAL_TRY; if (!db->so_pin_count) db->flags &= ~PKCS11_CKFT_SO_PIN_COUNT_LOW; } update_persistent_db(token); return rc; } static enum pkcs11_rc check_user_pin(struct pkcs11_session *session, uint8_t *pin, size_t pin_size) { struct ck_token *token = session->token; struct token_persistent_main *db = token->db_main; enum pkcs11_rc rc = PKCS11_CKR_OK; if (!(db->flags & PKCS11_CKFT_USER_PIN_INITIALIZED)) return PKCS11_CKR_USER_PIN_NOT_INITIALIZED; if (IS_ENABLED(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) && db->flags & PKCS11_CKFT_PROTECTED_AUTHENTICATION_PATH) return verify_identity_auth(token, PKCS11_CKU_USER); assert(db->user_pin_salt); if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; /* * Preset the counter and flags conservatively in the database so that * the tentative is saved whatever happens next. */ db->flags |= PKCS11_CKFT_USER_PIN_COUNT_LOW; db->user_pin_count++; if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) db->flags |= PKCS11_CKFT_USER_PIN_FINAL_TRY; else if (db->user_pin_count == PKCS11_TOKEN_USER_PIN_COUNT_MAX) db->flags |= PKCS11_CKFT_USER_PIN_LOCKED; update_persistent_db(token); rc = verify_pin(PKCS11_CKU_USER, pin, pin_size, db->user_pin_salt, db->user_pin_hash); if (rc == PKCS11_CKR_PIN_INCORRECT) { if (db->flags & PKCS11_CKFT_USER_PIN_LOCKED) return PKCS11_CKR_PIN_LOCKED; return PKCS11_CKR_PIN_INCORRECT; } if (rc) db->user_pin_count--; else db->user_pin_count = 0; db->flags &= ~PKCS11_CKFT_USER_PIN_LOCKED; if (db->user_pin_count < PKCS11_TOKEN_USER_PIN_COUNT_MAX - 1) { db->flags &= ~PKCS11_CKFT_USER_PIN_FINAL_TRY; if (!db->user_pin_count) db->flags &= ~PKCS11_CKFT_USER_PIN_COUNT_LOW; } update_persistent_db(token); return rc; } enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct pkcs11_session *session = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; uint32_t old_pin_size = 0; TEE_Param *ctrl = params; uint32_t pin_size = 0; void *old_pin = NULL; void *pin = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &old_pin_size, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get_ptr(&ctrlargs, &old_pin, old_pin_size); if (rc) return rc; rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (!pkcs11_session_is_read_write(session)) return PKCS11_CKR_SESSION_READ_ONLY; if (pkcs11_session_is_so(session)) { if (!(session->token->db_main->flags & PKCS11_CKFT_TOKEN_INITIALIZED)) return PKCS11_CKR_GENERAL_ERROR; rc = check_so_pin(session, old_pin, old_pin_size); if (rc) return rc; IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); return set_pin(session, pin, pin_size, PKCS11_CKU_SO); } if (!(session->token->db_main->flags & PKCS11_CKFT_USER_PIN_INITIALIZED)) return PKCS11_CKR_GENERAL_ERROR; rc = check_user_pin(session, old_pin, old_pin_size); if (rc) return rc; IMSG("PKCS11 session %"PRIu32": set PIN", session->handle); return set_pin(session, pin, pin_size, PKCS11_CKU_USER); } static void session_login_user(struct pkcs11_session *session) { struct pkcs11_client *client = session->client; struct pkcs11_session *sess = NULL; TAILQ_FOREACH(sess, &client->session_list, link) { if (sess->token != session->token) continue; if (pkcs11_session_is_read_write(sess)) sess->state = PKCS11_CKS_RW_USER_FUNCTIONS; else sess->state = PKCS11_CKS_RO_USER_FUNCTIONS; } } static void session_login_so(struct pkcs11_session *session) { struct pkcs11_client *client = session->client; struct pkcs11_session *sess = NULL; TAILQ_FOREACH(sess, &client->session_list, link) { if (sess->token != session->token) continue; if (pkcs11_session_is_read_write(sess)) sess->state = PKCS11_CKS_RW_SO_FUNCTIONS; else TEE_Panic(0); } } static void session_logout(struct pkcs11_session *session) { struct pkcs11_client *client = session->client; struct pkcs11_session *sess = NULL; TAILQ_FOREACH(sess, &client->session_list, link) { struct pkcs11_object *obj = NULL; struct pkcs11_object *tobj = NULL; uint32_t handle = 0; if (sess->token != session->token) continue; release_active_processing(session); /* Destroy private session objects */ LIST_FOREACH_SAFE(obj, &sess->object_list, link, tobj) { if (object_is_private(obj->attributes)) destroy_object(sess, obj, true); } /* * Remove handle of token private objects from * sessions object_handle_db */ LIST_FOREACH(obj, &session->token->object_list, link) { handle = pkcs11_object2handle(obj, session); if (handle && object_is_private(obj->attributes)) handle_put(get_object_handle_db(sess), handle); } release_session_find_obj_context(session); if (pkcs11_session_is_read_write(sess)) sess->state = PKCS11_CKS_RW_PUBLIC_SESSION; else sess->state = PKCS11_CKS_RO_PUBLIC_SESSION; } } enum pkcs11_rc entry_ck_login(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct pkcs11_session *session = NULL; struct pkcs11_session *sess = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; TEE_Param *ctrl = params; uint32_t user_type = 0; uint32_t pin_size = 0; void *pin = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &user_type, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &pin_size, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get_ptr(&ctrlargs, &pin, pin_size); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; switch (user_type) { case PKCS11_CKU_SO: if (pkcs11_session_is_so(session)) return PKCS11_CKR_USER_ALREADY_LOGGED_IN; if (pkcs11_session_is_user(session)) return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; TAILQ_FOREACH(sess, &client->session_list, link) if (sess->token == session->token && !pkcs11_session_is_read_write(sess)) return PKCS11_CKR_SESSION_READ_ONLY_EXISTS; /* * This is the point where we could check if another client * has another user or SO logged in. * * The spec says: * CKR_USER_TOO_MANY_TYPES: An attempt was made to have * more distinct users simultaneously logged into the token * than the token and/or library permits. For example, if * some application has an open SO session, and another * application attempts to log the normal user into a * session, the attempt may return this error. It is not * required to, however. Only if the simultaneous distinct * users cannot be supported does C_Login have to return * this value. Note that this error code generalizes to * true multi-user tokens. * * So it's permitted to have another user or SO logged in * from another client. */ rc = check_so_pin(session, pin, pin_size); if (!rc) session_login_so(session); break; case PKCS11_CKU_USER: if (pkcs11_session_is_so(session)) return PKCS11_CKR_USER_ANOTHER_ALREADY_LOGGED_IN; if (pkcs11_session_is_user(session)) return PKCS11_CKR_USER_ALREADY_LOGGED_IN; /* * This is the point where we could check if another client * has another user or SO logged in. * See comment on CKR_USER_TOO_MANY_TYPES above. */ rc = check_user_pin(session, pin, pin_size); if (!rc) session_login_user(session); break; case PKCS11_CKU_CONTEXT_SPECIFIC: return PKCS11_CKR_OPERATION_NOT_INITIALIZED; default: return PKCS11_CKR_USER_TYPE_INVALID; } if (!rc) IMSG("PKCS11 session %"PRIu32": login", session->handle); return rc; } enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct pkcs11_session *session = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; TEE_Param *ctrl = params; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (pkcs11_session_is_public(session)) return PKCS11_CKR_USER_NOT_LOGGED_IN; session_logout(session); IMSG("PKCS11 session %"PRIu32": logout", session->handle); return PKCS11_CKR_OK; } static TEE_Result seed_rng_pool(void *seed, size_t length) { static const TEE_UUID system_uuid = PTA_SYSTEM_UUID; uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param params[TEE_NUM_PARAMS] = { }; TEE_TASessionHandle sess = TEE_HANDLE_NULL; TEE_Result res = TEE_ERROR_GENERIC; uint32_t ret_orig = 0; params[0].memref.buffer = seed; params[0].memref.size = (uint32_t)length; res = TEE_OpenTASession(&system_uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, &ret_orig); if (res != TEE_SUCCESS) { EMSG("Can't open session to system PTA"); return res; } res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, PTA_SYSTEM_ADD_RNG_ENTROPY, param_types, params, &ret_orig); if (res != TEE_SUCCESS) EMSG("Can't invoke system PTA"); TEE_CloseTASession(sess); return res; } enum pkcs11_rc entry_ck_seed_random(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *in = params + 1; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; TEE_Result res = TEE_SUCCESS; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (in->memref.size && !in->memref.buffer) return PKCS11_CKR_ARGUMENTS_BAD; if (!in->memref.size) return PKCS11_CKR_OK; res = seed_rng_pool(in->memref.buffer, in->memref.size); if (res != TEE_SUCCESS) return PKCS11_CKR_FUNCTION_FAILED; DMSG("PKCS11 session %"PRIu32": seed random", session->handle); return PKCS11_CKR_OK; } enum pkcs11_rc entry_ck_generate_random(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; void *buffer = NULL; size_t buffer_size = 0; uint8_t *data = NULL; size_t left = 0; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; if (out->memref.size && !out->memref.buffer) return PKCS11_CKR_ARGUMENTS_BAD; if (!out->memref.size) return PKCS11_CKR_OK; buffer_size = MIN(out->memref.size, RNG_CHUNK_SIZE); buffer = TEE_Malloc(buffer_size, TEE_MALLOC_FILL_ZERO); if (!buffer) return PKCS11_CKR_DEVICE_MEMORY; data = out->memref.buffer; left = out->memref.size; while (left) { size_t count = MIN(left, buffer_size); TEE_GenerateRandom(buffer, count); TEE_MemMove(data, buffer, count); data += count; left -= count; } DMSG("PKCS11 session %"PRIu32": generate random", session->handle); TEE_Free(buffer); return PKCS11_CKR_OK; } optee_os-4.3.0/ta/pkcs11/src/pkcs11_token.h000066400000000000000000000276371464416617300203360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_PKCS11_TOKEN_H #define PKCS11_TA_PKCS11_TOKEN_H #include #include #include #include #include "handle.h" #include "object.h" #include "pkcs11_attributes.h" /* Hard coded description */ #define PKCS11_SLOT_DESCRIPTION "OP-TEE PKCS11 TA" #define PKCS11_SLOT_MANUFACTURER "Linaro" #define PKCS11_SLOT_HW_VERSION { 0, 0 } #define PKCS11_SLOT_FW_VERSION { PKCS11_TA_VERSION_MAJOR, \ PKCS11_TA_VERSION_MINOR } #define PKCS11_TOKEN_LABEL "OP-TEE PKCS#11 TA token" #define PKCS11_TOKEN_MANUFACTURER PKCS11_SLOT_MANUFACTURER #define PKCS11_TOKEN_MODEL "OP-TEE TA" #define PKCS11_TOKEN_HW_VERSION PKCS11_SLOT_HW_VERSION #define PKCS11_TOKEN_FW_VERSION PKCS11_SLOT_FW_VERSION enum pkcs11_token_state { PKCS11_TOKEN_RESET = 0, PKCS11_TOKEN_READ_WRITE, PKCS11_TOKEN_READ_ONLY, }; TAILQ_HEAD(client_list, pkcs11_client); TAILQ_HEAD(session_list, pkcs11_session); struct pkcs11_client; #define PKCS11_MAX_USERS 2 #define PKCS11_TOKEN_PIN_SIZE_MAX 128 #define PKCS11_TOKEN_PIN_SIZE_MIN 4 #define PKCS11_TOKEN_SO_PIN_COUNT_MAX 7 #define PKCS11_TOKEN_USER_PIN_COUNT_MAX 7 /* * Persistent state of the token * * @version - currently unused... * @label - pkcs11 formatted token label, set by client * @flags - pkcs11 token flags * @so_pin_count - counter on security officer login failure * @so_pin_salt - stores salt in hash of SO PIN, 0 if not set * @so_pin_hash - stores hash of SO PIN * @user_pin_count - counter on user login failure * @user_pin_salt - stores salt in hash of user PIN, 0 if not set * @user_pin_hash - stores hash of user PIN */ struct token_persistent_main { uint32_t version; uint8_t label[PKCS11_TOKEN_LABEL_SIZE]; uint32_t flags; uint32_t so_pin_count; uint32_t so_pin_salt; union { uint8_t so_pin_hash[TEE_MAX_HASH_SIZE]; TEE_Identity so_identity; }; uint32_t user_pin_count; uint32_t user_pin_salt; union { uint8_t user_pin_hash[TEE_MAX_HASH_SIZE]; TEE_Identity user_identity; }; }; /* * Persistent objects in the token * * @count - number of objects stored in the token * @uuids - array of object references/UUIDs (@count items) */ struct token_persistent_objs { uint32_t count; TEE_UUID uuids[]; }; /* * Runtime state of the token, complies with pkcs11 * * @state - Pkcs11 login is public, user, SO or custom * @session_count - Counter for opened Pkcs11 sessions * @rw_session_count - Count for opened Pkcs11 read/write sessions * @object_list - List of the objects owned by the token * @db_main - Volatile copy of the persistent main database * @db_objs - Volatile copy of the persistent object database */ struct ck_token { enum pkcs11_token_state state; uint32_t session_count; uint32_t rw_session_count; struct object_list object_list; /* Copy in RAM of the persistent database */ struct token_persistent_main *db_main; struct token_persistent_objs *db_objs; }; /* * A session can enter a processing state (encrypt, decrypt, digest, ...) * only from the initialized state. A session must return the initialized * state (from a processing finalization request) before entering another * processing state. */ enum pkcs11_proc_state { PKCS11_SESSION_READY = 0, /* No active processing */ PKCS11_SESSION_ENCRYPTING, PKCS11_SESSION_DECRYPTING, PKCS11_SESSION_DIGESTING, PKCS11_SESSION_DIGESTING_ENCRYPTING, /* case C_DigestEncryptUpdate */ PKCS11_SESSION_DECRYPTING_DIGESTING, /* case C_DecryptDigestUpdate */ PKCS11_SESSION_SIGNING, PKCS11_SESSION_SIGNING_ENCRYPTING, /* case C_SignEncryptUpdate */ PKCS11_SESSION_VERIFYING, PKCS11_SESSION_DECRYPTING_VERIFYING, /* case C_DecryptVerifyUpdate */ PKCS11_SESSION_SIGNING_RECOVER, PKCS11_SESSION_VERIFYING_RECOVER, PKCS11_SESSION_BUSY, }; /* * Context of the active processing in the session * * @state - ongoing active processing function or ready state * @mecha_type - mechanism type of the active processing * @always_authen - true if user need to login before each use * @relogged - true once client logged since last operation update * @op_step - last active operation step - update, final or one-shot * @tee_op_handle - handle on active crypto operation or TEE_HANDLE_NULL * @tee_op_handle2 - second handle for specific operations or TEE_HANDLE_NULL * @tee_hash_algo - hash algorithm identifier. * @extra_ctx - context for the active processing */ struct active_processing { enum pkcs11_proc_state state; uint32_t mecha_type; enum processing_step step; bool always_authen; bool relogged; TEE_OperationHandle tee_op_handle; TEE_OperationHandle tee_op_handle2; uint32_t tee_hash_algo; void *extra_ctx; }; /* * Pkcs11 objects search context * * @attributes - matching attributes list searched (null if no search) * @count - number of matching handle found * @handles - array of handle of matching objects * @next - index of the next object handle to return to C_FindObject */ struct pkcs11_find_objects { void *attributes; size_t count; uint32_t *handles; size_t next; }; /* * Structure tracking the PKCS#11 sessions * * @link - List of the session belonging to a client * @client - Client the session belongs to * @token - Token this session belongs to * @handle - Identifier of the session published to the client * @object_list - Entry of the session objects list * @state - R/W SO, R/W user, RO user, R/W public, RO public. * @processing - Reference to initialized processing context if any * @find_ctx - Reference to active search context (null if no active search) */ struct pkcs11_session { TAILQ_ENTRY(pkcs11_session) link; struct pkcs11_client *client; struct ck_token *token; enum pkcs11_mechanism_id handle; struct object_list object_list; enum pkcs11_session_state state; struct active_processing *processing; struct pkcs11_find_objects *find_ctx; }; /* Initialize static token instance(s) from default/persistent database */ TEE_Result pkcs11_init(void); void pkcs11_deinit(void); /* Speculation safe lookup of token instance from token identifier */ struct ck_token *get_token(unsigned int token_id); /* Return token identified from token instance address */ unsigned int get_token_id(struct ck_token *token); /* Return client's (shared) object handle database associated with session */ struct handle_db *get_object_handle_db(struct pkcs11_session *session); /* Access to persistent database */ struct ck_token *init_persistent_db(unsigned int token_id); void update_persistent_db(struct ck_token *token); void close_persistent_db(struct ck_token *token); /* Load and release persistent object attributes in memory */ enum pkcs11_rc load_persistent_object_attributes(struct pkcs11_object *obj); void release_persistent_object_attributes(struct pkcs11_object *obj); enum pkcs11_rc update_persistent_object_attributes(struct pkcs11_object *obj); enum pkcs11_rc hash_pin(enum pkcs11_user_type user, const uint8_t *pin, size_t pin_size, uint32_t *salt, uint8_t hash[TEE_MAX_HASH_SIZE]); enum pkcs11_rc verify_pin(enum pkcs11_user_type user, const uint8_t *pin, size_t pin_size, uint32_t salt, const uint8_t hash[TEE_MAX_HASH_SIZE]); #if defined(CFG_PKCS11_TA_AUTH_TEE_IDENTITY) enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token); enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token, enum pkcs11_user_type user_type, const uint8_t *pin, size_t pin_size); enum pkcs11_rc verify_identity_auth(struct ck_token *token, enum pkcs11_user_type user_type); #else static inline enum pkcs11_rc setup_so_identity_auth_from_client(struct ck_token *token __unused) { return PKCS11_CKR_PIN_INVALID; } static inline enum pkcs11_rc setup_identity_auth_from_pin(struct ck_token *token __unused, enum pkcs11_user_type user_type __unused, const uint8_t *pin __unused, size_t pin_size __unused) { return PKCS11_CKR_PIN_INVALID; } static inline enum pkcs11_rc verify_identity_auth(struct ck_token *token __unused, enum pkcs11_user_type user_type __unused) { return PKCS11_CKR_PIN_INCORRECT; } #endif /* CFG_PKCS11_TA_AUTH_TEE_IDENTITY */ /* Token persistent objects */ enum pkcs11_rc create_object_uuid(struct ck_token *token, struct pkcs11_object *obj); void destroy_object_uuid(struct ck_token *token, struct pkcs11_object *obj); enum pkcs11_rc unregister_persistent_object(struct ck_token *token, TEE_UUID *uuid); enum pkcs11_rc register_persistent_object(struct ck_token *token, TEE_UUID *uuid); enum pkcs11_rc get_persistent_objects_list(struct ck_token *token, TEE_UUID *array, size_t *size); /* * Pkcs11 session support */ struct session_list *get_session_list(struct pkcs11_session *session); struct pkcs11_client *tee_session2client(void *tee_session); struct pkcs11_client *register_client(void); void unregister_client(struct pkcs11_client *client); struct pkcs11_session *pkcs11_handle2session(uint32_t handle, struct pkcs11_client *client); static inline bool session_is_active(struct pkcs11_session *session) { return session->processing; } enum pkcs11_rc set_processing_state(struct pkcs11_session *session, enum processing_func function, struct pkcs11_object *obj1, struct pkcs11_object *obj2); static inline bool pkcs11_session_is_read_write(struct pkcs11_session *session) { return session->state == PKCS11_CKS_RW_PUBLIC_SESSION || session->state == PKCS11_CKS_RW_USER_FUNCTIONS || session->state == PKCS11_CKS_RW_SO_FUNCTIONS; } static inline bool pkcs11_session_is_public(struct pkcs11_session *session) { return session->state == PKCS11_CKS_RO_PUBLIC_SESSION || session->state == PKCS11_CKS_RW_PUBLIC_SESSION; } static inline bool pkcs11_session_is_user(struct pkcs11_session *session) { return session->state == PKCS11_CKS_RO_USER_FUNCTIONS || session->state == PKCS11_CKS_RW_USER_FUNCTIONS; } static inline bool pkcs11_session_is_so(struct pkcs11_session *session) { return session->state == PKCS11_CKS_RW_SO_FUNCTIONS; } static inline struct object_list *pkcs11_get_session_objects(struct pkcs11_session *session) { return &session->object_list; } static inline struct ck_token *pkcs11_session2token(struct pkcs11_session *session) { return session->token; } /* Invalidate any handle referring the object since the object no more exists */ void token_invalidate_object_handles(struct pkcs11_object *obj); /* Entry point for the TA commands */ enum pkcs11_rc entry_ck_slot_list(uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_slot_info(uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_token_info(uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_token_mecha_ids(uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_token_mecha_info(uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_open_session(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_close_session(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_close_all_sessions(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_session_info(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_token_initialize(uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_init_pin(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_set_pin(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_login(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_logout(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_seed_random(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_ck_generate_random(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); #endif /*PKCS11_TA_PKCS11_TOKEN_H*/ optee_os-4.3.0/ta/pkcs11/src/processing.c000066400000000000000000001020301464416617300201600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include "attributes.h" #include "object.h" #include "pkcs11_attributes.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "serializer.h" static enum pkcs11_rc get_ready_session(struct pkcs11_session *session) { if (session_is_active(session)) return PKCS11_CKR_OPERATION_ACTIVE; return PKCS11_CKR_OK; } static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd) { switch (cmd) { case PKCS11_CMD_ENCRYPT_UPDATE: case PKCS11_CMD_ENCRYPT_ONESHOT: case PKCS11_CMD_ENCRYPT_FINAL: return PKCS11_FUNCTION_ENCRYPT; case PKCS11_CMD_DECRYPT_UPDATE: case PKCS11_CMD_DECRYPT_ONESHOT: case PKCS11_CMD_DECRYPT_FINAL: return PKCS11_FUNCTION_DECRYPT; case PKCS11_CMD_SIGN_ONESHOT: case PKCS11_CMD_SIGN_UPDATE: case PKCS11_CMD_SIGN_FINAL: return PKCS11_FUNCTION_SIGN; case PKCS11_CMD_VERIFY_ONESHOT: case PKCS11_CMD_VERIFY_UPDATE: case PKCS11_CMD_VERIFY_FINAL: return PKCS11_FUNCTION_VERIFY; case PKCS11_CMD_DIGEST_UPDATE: case PKCS11_CMD_DIGEST_KEY: case PKCS11_CMD_DIGEST_ONESHOT: case PKCS11_CMD_DIGEST_FINAL: return PKCS11_FUNCTION_DIGEST; default: return PKCS11_FUNCTION_UNKNOWN; } } static bool func_matches_state(enum processing_func function, enum pkcs11_proc_state state) { switch (function) { case PKCS11_FUNCTION_ENCRYPT: return state == PKCS11_SESSION_ENCRYPTING || state == PKCS11_SESSION_DIGESTING_ENCRYPTING || state == PKCS11_SESSION_SIGNING_ENCRYPTING; case PKCS11_FUNCTION_DECRYPT: return state == PKCS11_SESSION_DECRYPTING || state == PKCS11_SESSION_DECRYPTING_DIGESTING || state == PKCS11_SESSION_DECRYPTING_VERIFYING; case PKCS11_FUNCTION_DIGEST: return state == PKCS11_SESSION_DIGESTING || state == PKCS11_SESSION_DIGESTING_ENCRYPTING; case PKCS11_FUNCTION_SIGN: return state == PKCS11_SESSION_SIGNING || state == PKCS11_SESSION_SIGNING_ENCRYPTING; case PKCS11_FUNCTION_VERIFY: return state == PKCS11_SESSION_VERIFYING || state == PKCS11_SESSION_DECRYPTING_VERIFYING; case PKCS11_FUNCTION_SIGN_RECOVER: return state == PKCS11_SESSION_SIGNING_RECOVER; case PKCS11_FUNCTION_VERIFY_RECOVER: return state == PKCS11_SESSION_SIGNING_RECOVER; default: TEE_Panic(function); return false; } } static enum pkcs11_rc get_active_session(struct pkcs11_session *session, enum processing_func function) { enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; if (session->processing && func_matches_state(function, session->processing->state)) rc = PKCS11_CKR_OK; return rc; } void release_active_processing(struct pkcs11_session *session) { if (!session->processing) return; switch (session->processing->mecha_type) { case PKCS11_CKM_AES_GCM: tee_release_gcm_operation(session); break; default: break; } if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { TEE_FreeOperation(session->processing->tee_op_handle); session->processing->tee_op_handle = TEE_HANDLE_NULL; } if (session->processing->tee_op_handle2 != TEE_HANDLE_NULL) { TEE_FreeOperation(session->processing->tee_op_handle2); session->processing->tee_op_handle2 = TEE_HANDLE_NULL; } TEE_Free(session->processing->extra_ctx); TEE_Free(session->processing); session->processing = NULL; } size_t get_object_key_bit_size(struct pkcs11_object *obj) { void *a_ptr = NULL; uint32_t a_size = 0; struct obj_attrs *attrs = obj->attributes; switch (get_key_type(attrs)) { case PKCS11_CKK_AES: case PKCS11_CKK_GENERIC_SECRET: case PKCS11_CKK_MD5_HMAC: case PKCS11_CKK_SHA_1_HMAC: case PKCS11_CKK_SHA224_HMAC: case PKCS11_CKK_SHA256_HMAC: case PKCS11_CKK_SHA384_HMAC: case PKCS11_CKK_SHA512_HMAC: if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) return 0; return a_size * 8; case PKCS11_CKK_RSA: if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size)) return 0; return a_size * 8; case PKCS11_CKK_EC: if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS, &a_ptr, &a_size) || !a_ptr) return 0; return ec_params2tee_keysize(a_ptr, a_size); case PKCS11_CKK_EC_EDWARDS: if (get_attribute_ptr(attrs, PKCS11_CKA_EC_POINT, NULL, &a_size)) return 0; return a_size * 8; default: TEE_Panic(0); return 0; } } static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t data_size = 0; uint32_t value_len = 0; void *value = NULL; void *data = NULL; if (!*head) return PKCS11_CKR_TEMPLATE_INCONSISTENT; rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); if (rc || data_size != sizeof(uint32_t)) { DMSG("%s", rc ? "No attribute value_len found" : "Invalid size for attribute VALUE_LEN"); return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; } TEE_MemMove(&value_len, data, data_size); /* Remove the default empty value attribute if found */ rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) return PKCS11_CKR_GENERAL_ERROR; value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!value) return PKCS11_CKR_DEVICE_MEMORY; TEE_GenerateRandom(value, value_len); rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); if (rc == PKCS11_CKR_OK) rc = set_check_value_attr(head); TEE_Free(value); return rc; } enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_attribute_head *proc_params = NULL; struct obj_attrs *head = NULL; struct pkcs11_object_head *template = NULL; size_t template_size = 0; uint32_t obj_handle = 0; if (!client || ptypes != exp_pt || out->memref.size != sizeof(obj_handle)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); if (rc) goto out; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) goto out; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } rc = get_ready_session(session); if (rc) goto out; template_size = sizeof(*template) + template->attrs_size; rc = check_mechanism_against_processing(session, proc_params->id, PKCS11_FUNCTION_GENERATE, PKCS11_FUNC_STEP_INIT); if (rc) { DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); goto out; } /* * Prepare a clean initial state for the requested object attributes. * Free temporary template once done. */ rc = create_attributes_from_template(&head, template, template_size, NULL, PKCS11_FUNCTION_GENERATE, proc_params->id, PKCS11_CKO_UNDEFINED_ID); if (rc) goto out; TEE_Free(template); template = NULL; rc = check_created_attrs(head, NULL); if (rc) goto out; rc = check_created_attrs_against_processing(proc_params->id, head); if (rc) goto out; rc = check_created_attrs_against_token(session, head); if (rc) goto out; /* * Execute target processing and add value as attribute * PKCS11_CKA_VALUE. Symm key generation: depends on target * processing to be used. */ switch (proc_params->id) { case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: case PKCS11_CKM_AES_KEY_GEN: /* Generate random of size specified by attribute VALUE_LEN */ rc = generate_random_key_value(&head); if (rc) goto out; break; default: rc = PKCS11_CKR_MECHANISM_INVALID; goto out; } TEE_Free(proc_params); proc_params = NULL; /* * Object is ready, register it and return a handle. */ rc = create_object(session, head, &obj_handle); if (rc) goto out; /* * Now obj_handle (through the related struct pkcs11_object instance) * owns the serialized buffer that holds the object attributes. * We reset head to NULL as it is no more the buffer owner and would * be freed at function out. */ head = NULL; TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); out->memref.size = sizeof(obj_handle); DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, session->handle, obj_handle); out: TEE_Free(proc_params); TEE_Free(template); TEE_Free(head); return rc; } enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, uint32_t attribute, void **data, size_t *size) { TEE_Result res = TEE_ERROR_GENERIC; void *ptr = NULL; size_t sz = 0; res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz); if (res != TEE_ERROR_SHORT_BUFFER) return PKCS11_CKR_FUNCTION_FAILED; ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!ptr) return PKCS11_CKR_DEVICE_MEMORY; res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz); if (res) { TEE_Free(ptr); } else { *data = ptr; *size = sz; } return tee2pkcs_error(res); } enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, uint32_t pkcs11_id, TEE_ObjectHandle tee_obj, uint32_t tee_id) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *a_ptr = NULL; size_t a_size = 0; rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size); if (rc) goto out; rc = add_attribute(head, pkcs11_id, a_ptr, a_size); TEE_Free(a_ptr); out: if (rc) EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s", tee_id, pkcs11_id, id2str_attr(pkcs11_id)); return rc; } enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_attribute_head *proc_params = NULL; struct obj_attrs *pub_head = NULL; struct obj_attrs *priv_head = NULL; struct pkcs11_object_head *pub_template = NULL; struct pkcs11_object_head *priv_template = NULL; struct pkcs11_object *object = NULL; size_t pub_template_size = 0; size_t priv_template_size = 0; uint32_t pubkey_handle = 0; uint32_t privkey_handle = 0; uint32_t *hdl_ptr = NULL; size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle); if (!client || ptypes != exp_pt || out->memref.size != out_ref_size) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); if (rc) goto out; rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template); if (rc) goto out; rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template); if (rc) goto out; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } rc = get_ready_session(session); if (rc) goto out; rc = check_mechanism_against_processing(session, proc_params->id, PKCS11_FUNCTION_GENERATE_PAIR, PKCS11_FUNC_STEP_INIT); if (rc) goto out; pub_template_size = sizeof(*pub_template) + pub_template->attrs_size; rc = create_attributes_from_template(&pub_head, pub_template, pub_template_size, NULL, PKCS11_FUNCTION_GENERATE_PAIR, proc_params->id, PKCS11_CKO_PUBLIC_KEY); if (rc) goto out; TEE_Free(pub_template); pub_template = NULL; priv_template_size = sizeof(*priv_template) + priv_template->attrs_size; rc = create_attributes_from_template(&priv_head, priv_template, priv_template_size, NULL, PKCS11_FUNCTION_GENERATE_PAIR, proc_params->id, PKCS11_CKO_PRIVATE_KEY); if (rc) goto out; TEE_Free(priv_template); priv_template = NULL; /* Generate CKA_ID for keys if not specified by the templates */ rc = add_missing_attribute_id(&pub_head, &priv_head); if (rc) goto out; /* Check created object against processing and token state */ rc = check_created_attrs(pub_head, priv_head); if (rc) goto out; rc = check_created_attrs_against_processing(proc_params->id, pub_head); if (rc) goto out; rc = check_created_attrs_against_processing(proc_params->id, priv_head); if (rc) goto out; rc = check_created_attrs_against_token(session, pub_head); if (rc) goto out; rc = check_access_attrs_against_token(session, pub_head); if (rc) goto out; rc = check_created_attrs_against_token(session, priv_head); if (rc) goto out; rc = check_access_attrs_against_token(session, priv_head); if (rc) goto out; /* Generate key pair */ switch (proc_params->id) { case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: rc = generate_eddsa_keys(proc_params, &pub_head, &priv_head); break; case PKCS11_CKM_EC_KEY_PAIR_GEN: rc = generate_ec_keys(proc_params, &pub_head, &priv_head); break; case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: rc = generate_rsa_keys(proc_params, &pub_head, &priv_head); break; default: rc = PKCS11_CKR_MECHANISM_INVALID; break; } if (rc) goto out; TEE_Free(proc_params); proc_params = NULL; /* * Object is ready, register it and return a handle. */ rc = create_object(session, pub_head, &pubkey_handle); if (rc) goto out; /* * Now obj_handle (through the related struct pkcs11_object instance) * owns the serialized buffer that holds the object attributes. * We reset local pub_head to NULL to mark that ownership has been * transferred. */ pub_head = NULL; rc = create_object(session, priv_head, &privkey_handle); if (rc) goto out; /* Ownership has been transferred so mark it with NULL */ priv_head = NULL; hdl_ptr = (uint32_t *)out->memref.buffer; TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle)); TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle)); DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32, session->handle, privkey_handle, pubkey_handle); pubkey_handle = 0; privkey_handle = 0; out: if (pubkey_handle) { object = pkcs11_handle2object(pubkey_handle, session); if (!object) TEE_Panic(0); destroy_object(session, object, false); } TEE_Free(priv_head); TEE_Free(pub_head); TEE_Free(priv_template); TEE_Free(pub_template); TEE_Free(proc_params); return rc; } /* * entry_processing_init - Generic entry for initializing a processing * * @client = client reference * @ptype = Invocation parameter types * @params = Invocation parameters reference * @function - encrypt, decrypt, sign, verify, digest, ... */ enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params, enum processing_func function) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_attribute_head *proc_params = NULL; uint32_t key_handle = 0; struct pkcs11_object *obj = NULL; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (function != PKCS11_FUNCTION_DIGEST) { rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); if (rc) return rc; } rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out_free; } rc = get_ready_session(session); if (rc) goto out_free; if (function != PKCS11_FUNCTION_DIGEST) { obj = pkcs11_handle2object(key_handle, session); if (!obj) { rc = PKCS11_CKR_KEY_HANDLE_INVALID; goto out_free; } } rc = set_processing_state(session, function, obj, NULL); if (rc) goto out; rc = check_mechanism_against_processing(session, proc_params->id, function, PKCS11_FUNC_STEP_INIT); if (rc) goto out; if (obj) { rc = check_parent_attrs_against_processing(proc_params->id, function, obj->attributes); if (rc) goto out; rc = check_access_attrs_against_token(session, obj->attributes); if (rc) goto out; } if (processing_is_tee_symm(proc_params->id)) rc = init_symm_operation(session, function, proc_params, obj); else if (processing_is_tee_asymm(proc_params->id)) rc = init_asymm_operation(session, function, proc_params, obj); else if (processing_is_tee_digest(proc_params->id)) rc = init_digest_operation(session, proc_params); else rc = PKCS11_CKR_MECHANISM_INVALID; if (rc == PKCS11_CKR_OK) { DMSG("PKCS11 session %"PRIu32": init processing %s %s", session->handle, id2str_proc(proc_params->id), id2str_function(function)); } out: if (rc) release_active_processing(session); out_free: TEE_Free(proc_params); return rc; } /* * entry_processing_step - Generic entry on active processing * * @client = client reference * @ptype = Invocation parameter types * @params = Invocation parameters reference * @function - encrypt, decrypt, sign, verify, digest, ... * @step - update, oneshot, final */ enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params, enum processing_func function, enum processing_step step) { TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; uint32_t key_handle = 0; struct pkcs11_object *obj = NULL; if (!client || TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { assert(function == PKCS11_FUNCTION_DIGEST); rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); if (rc) return rc; } if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; rc = get_active_session(session, function); if (rc) return rc; if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { assert(function == PKCS11_FUNCTION_DIGEST); obj = pkcs11_handle2object(key_handle, session); if (!obj) { rc = PKCS11_CKR_KEY_HANDLE_INVALID; goto out; } rc = check_access_attrs_against_token(session, obj->attributes); if (rc) { rc = PKCS11_CKR_KEY_HANDLE_INVALID; goto out; } } mecha_type = session->processing->mecha_type; rc = check_mechanism_against_processing(session, mecha_type, function, step); if (rc) goto out; if (processing_is_tee_symm(mecha_type)) rc = step_symm_operation(session, function, step, ptypes, params); else if (processing_is_tee_asymm(mecha_type)) rc = step_asymm_operation(session, function, step, ptypes, params); else if (processing_is_tee_digest(mecha_type)) rc = step_digest_operation(session, step, obj, ptypes, params); else rc = PKCS11_CKR_MECHANISM_INVALID; if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE || step == PKCS11_FUNC_STEP_UPDATE_KEY)) { session->processing->step = PKCS11_FUNC_STEP_UPDATE; DMSG("PKCS11 session%"PRIu32": processing %s %s", session->handle, id2str_proc(mecha_type), id2str_function(function)); } if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_ONESHOT) session->processing->step = PKCS11_FUNC_STEP_ONESHOT; if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL) session->processing->step = PKCS11_FUNC_STEP_FINAL; out: switch (step) { case PKCS11_FUNC_STEP_UPDATE: case PKCS11_FUNC_STEP_UPDATE_KEY: if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) release_active_processing(session); break; default: /* ONESHOT and FINAL terminates processing on success */ if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) release_active_processing(session); break; } return rc; } enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params, enum processing_func function) { TEE_Param *ctrl = params; TEE_Param *out = params + 2; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_attribute_head *proc_params = NULL; struct pkcs11_object_head *template = NULL; uint32_t parent_handle = 0; uint32_t obj_handle = 0; struct pkcs11_object *parent = NULL; struct obj_attrs *head = NULL; size_t template_size = 0; void *in_buf = NULL; uint32_t in_size = 0; void *out_buf = NULL; uint32_t out_size = 0; enum processing_func operation = PKCS11_FUNCTION_UNKNOWN; if (!client || TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT || TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT || out->memref.size != sizeof(obj_handle) || TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) return PKCS11_CKR_ARGUMENTS_BAD; switch (function) { case PKCS11_FUNCTION_UNWRAP: if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_MEMREF_INPUT) return PKCS11_CKR_ARGUMENTS_BAD; in_buf = params[1].memref.buffer; in_size = params[1].memref.size; if (in_size && !in_buf) return PKCS11_CKR_ARGUMENTS_BAD; /* * Some unwrap mechanisms require encryption to be * performed on the data passed in proc_params by parent * key. Hence set operation as PKCS11_FUNCTION_DECRYPT * to be used with init_symm_operation() */ operation = PKCS11_FUNCTION_DECRYPT; break; case PKCS11_FUNCTION_DERIVE: if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE) return PKCS11_CKR_ARGUMENTS_BAD; /* * Some derivation mechanism require encryption to be * performed on the data passed in proc_params by parent * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT * to be used with init_symm_operation() */ operation = PKCS11_FUNCTION_ENCRYPT; break; default: return PKCS11_CKR_ARGUMENTS_BAD; } serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); if (rc) return rc; rc = serialargs_alloc_get_attributes(&ctrlargs, &template); if (rc) goto out_free; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out_free; } /* Return error if processing already active */ rc = get_ready_session(session); if (rc) goto out_free; /* Check parent handle */ parent = pkcs11_handle2object(parent_handle, session); if (!parent) { rc = PKCS11_CKR_KEY_HANDLE_INVALID; goto out_free; } /* Check if mechanism can be used for derivation function */ rc = check_mechanism_against_processing(session, proc_params->id, function, PKCS11_FUNC_STEP_INIT); if (rc) goto out_free; /* Set the processing state to active */ rc = set_processing_state(session, function, parent, NULL); if (rc) goto out_free; /* * Check if base/parent key has CKA_DERIVE set and its key type is * compatible with the mechanism passed */ rc = check_parent_attrs_against_processing(proc_params->id, function, parent->attributes); if (rc) { /* * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors * specified with C_Derive/Unwrap() in the specification. So * return the next most appropriate error. */ if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) { if (function == PKCS11_FUNCTION_UNWRAP) rc = PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; else rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; } goto out; } /* Check access of base/parent key */ rc = check_access_attrs_against_token(session, parent->attributes); if (rc) goto out; template_size = sizeof(*template) + template->attrs_size; /* * Prepare a clean initial state for the requested object attributes * using base/parent key attributes. Free temporary template once done. */ rc = create_attributes_from_template(&head, template, template_size, parent->attributes, function, proc_params->id, PKCS11_CKO_UNDEFINED_ID); if (rc) goto out; TEE_Free(template); template = NULL; /* check_created_attrs() is called later once key size is known */ rc = check_created_attrs_against_processing(proc_params->id, head); if (rc) goto out; rc = check_created_attrs_against_token(session, head); if (rc) goto out; rc = check_access_attrs_against_token(session, head); if (rc) goto out; if (processing_is_tee_symm(proc_params->id)) { rc = init_symm_operation(session, operation, proc_params, parent); if (rc) goto out; switch (function) { case PKCS11_FUNCTION_DERIVE: rc = derive_key_by_symm_enc(session, &out_buf, &out_size); break; case PKCS11_FUNCTION_UNWRAP: rc = unwrap_key_by_symm(session, in_buf, in_size, &out_buf, &out_size); break; default: TEE_Panic(function); } if (rc) goto out; } else if (processing_is_tee_asymm(proc_params->id)) { switch (function) { case PKCS11_FUNCTION_DERIVE: rc = init_asymm_operation(session, function, proc_params, parent); if (rc) goto out; rc = do_asymm_derivation(session, proc_params, &head); if (!rc) goto done; break; case PKCS11_FUNCTION_UNWRAP: rc = init_asymm_operation(session, operation, proc_params, parent); if (rc) goto out; rc = unwrap_key_by_asymm(session, in_buf, in_size, &out_buf, &out_size); break; default: TEE_Panic(function); } if (rc) goto out; } else { rc = PKCS11_CKR_MECHANISM_INVALID; goto out; } rc = set_key_data(&head, out_buf, out_size); if (rc) goto out; done: TEE_Free(out_buf); out_buf = NULL; TEE_Free(proc_params); proc_params = NULL; /* * Object is ready, register it and return a handle. */ rc = create_object(session, head, &obj_handle); if (rc) goto out; /* * Now obj_handle (through the related struct pkcs11_object instance) * owns the serialized buffer that holds the object attributes. * We reset head to NULL as it is no more the buffer owner and would * be freed at function out. */ head = NULL; TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); out->memref.size = sizeof(obj_handle); DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, session->handle, obj_handle); out: release_active_processing(session); out_free: TEE_Free(proc_params); TEE_Free(template); TEE_Free(head); TEE_Free(out_buf); return rc; } enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; enum processing_func function = PKCS11_FUNCTION_UNKNOWN; uint32_t cmd = 0; if (!client || ptypes != exp_pt) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get_u32(&ctrlargs, &cmd); if (serialargs_remaining_bytes(&ctrlargs)) return PKCS11_CKR_ARGUMENTS_BAD; function = func_for_cmd(cmd); if (function == PKCS11_FUNCTION_UNKNOWN) return PKCS11_CKR_ARGUMENTS_BAD; rc = get_active_session(session, function); if (rc) return rc; release_active_processing(session); DMSG("PKCS11 session %"PRIu32": release processing", session->handle); return PKCS11_CKR_OK; } enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param *ctrl = params; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs ctrlargs = { }; struct pkcs11_session *session = NULL; struct pkcs11_attribute_head *proc_params = NULL; struct pkcs11_object *wrapping_key = NULL; struct pkcs11_object *key = NULL; void *req_attrs = NULL; uint32_t wrapping_key_handle = 0; uint32_t key_handle = 0; uint32_t size = 0; void *key_data = NULL; uint32_t key_sz = 0; void *out_buf = params[2].memref.buffer; uint32_t out_size = params[2].memref.size; const enum processing_func function = PKCS11_FUNCTION_WRAP; if (!client || ptypes != exp_pt || (out_size && !out_buf)) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); if (rc) return rc; rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); if (rc) return rc; if (serialargs_remaining_bytes(&ctrlargs)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out_free; } rc = get_ready_session(session); if (rc) goto out_free; wrapping_key = pkcs11_handle2object(wrapping_key_handle, session); if (!wrapping_key) { rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID; goto out_free; } key = pkcs11_handle2object(key_handle, session); if (!key) { rc = PKCS11_CKR_KEY_HANDLE_INVALID; goto out_free; } /* * The wrapping key and key to be wrapped shouldn't be same. * PKCS#11 spec doesn't explicitly state that but logically this isn't * a use case and also acts as an attack vector, so explicitly * disallow this. */ if (key == wrapping_key) { rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID; goto out_free; } rc = set_processing_state(session, function, wrapping_key, NULL); if (rc) goto out_free; /* Check if mechanism can be used for wrapping function */ rc = check_mechanism_against_processing(session, proc_params->id, function, PKCS11_FUNC_STEP_INIT); if (rc) goto out; /* * Check if wrapping key has CKA_WRAP set and its key type is * compatible with the mechanism passed */ rc = check_parent_attrs_against_processing(proc_params->id, function, wrapping_key->attributes); if (rc) { /* * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors * specified with C_Wrap() in the specification. So * return the next most appropriate error. */ if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT; goto out; } /* Check access of wrapping key */ rc = check_access_attrs_against_token(session, wrapping_key->attributes); if (rc) goto out; switch (get_class(key->attributes)) { case PKCS11_CKO_SECRET_KEY: case PKCS11_CKO_PRIVATE_KEY: break; default: rc = PKCS11_CKR_KEY_NOT_WRAPPABLE; goto out; } /* Check if key to be wrapped is extractable */ if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) { DMSG("Extractable property is false"); rc = PKCS11_CKR_KEY_UNEXTRACTABLE; goto out; } if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) && !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) { DMSG("Wrap with trusted not satisfied"); rc = PKCS11_CKR_KEY_NOT_WRAPPABLE; goto out; } rc = check_access_attrs_against_token(session, key->attributes); if (rc) goto out; rc = get_attribute_ptr(wrapping_key->attributes, PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size); if (rc == PKCS11_CKR_OK && size != 0) { if (!attributes_match_reference(key->attributes, req_attrs)) { rc = PKCS11_CKR_KEY_HANDLE_INVALID; goto out; } } rc = alloc_key_data_to_wrap(key->attributes, &key_data, &key_sz); if (rc) goto out; if (processing_is_tee_symm(proc_params->id)) { rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, proc_params, wrapping_key); if (rc) goto out; rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf, &out_size); } else { rc = init_asymm_operation(session, PKCS11_FUNCTION_ENCRYPT, proc_params, wrapping_key); if (rc) goto out; rc = wrap_data_by_asymm_enc(session, key_data, key_sz, out_buf, &out_size); } if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL) params[2].memref.size = out_size; out: release_active_processing(session); out_free: TEE_Free(key_data); TEE_Free(proc_params); return rc; } optee_os-4.3.0/ta/pkcs11/src/processing.h000066400000000000000000000210421464416617300201700ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_PROCESSING_H #define PKCS11_TA_PROCESSING_H #include #include #include struct pkcs11_client; struct pkcs11_session; struct pkcs11_object; struct active_processing; /** * RSA PSS processing context * * @hash_alg: Hash algorithm mechanism * @mgf_type: Mask generator function * @salt_len: Length of the salt in bytes */ struct rsa_pss_processing_ctx { enum pkcs11_mechanism_id hash_alg; enum pkcs11_mgf_id mgf_type; uint32_t salt_len; }; /** * RSA OAEP processing context * * @hash_alg: Hash algorithm mechanism * @mgf_type: Mask generator function * @source_type: Type of source. * @source_data_len: Length of the source data. * @source_data: Source data. */ struct rsa_oaep_processing_ctx { enum pkcs11_mechanism_id hash_alg; enum pkcs11_mgf_id mgf_type; uint32_t source_type; uint32_t source_data_len; uint8_t source_data[]; }; /** * RSA AES key wrap processing context * * @hash_alg: Hash algorithm mechanism * @mgf_type: Mask generator function * @aes_key_bits: Length of AES key in bits * @source_type: Type of source. * @source_data_len: Length of the source data. * @source_data: Source data. */ struct rsa_aes_key_wrap_processing_ctx { enum pkcs11_mechanism_id hash_alg; enum pkcs11_mgf_id mgf_type; uint32_t aes_key_bits; uint32_t source_type; uint32_t source_data_len; uint8_t source_data[]; }; /** * EDDSA processing context * * @flag: Prehash flag * @ctx_len: Length of the context data * @ctx: Context data */ struct eddsa_processing_ctx { uint32_t flag; uint32_t ctx_len; uint8_t ctx[]; }; /* * Entry points from PKCS11 TA invocation commands */ enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params, enum processing_func function); enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params, enum processing_func function, enum processing_step step); enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params, enum processing_func function); enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); /* * Util */ size_t get_object_key_bit_size(struct pkcs11_object *obj); void release_active_processing(struct pkcs11_session *session); enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, uint32_t attribute, void **data, size_t *size); enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, uint32_t pkcs11_id, TEE_ObjectHandle tee_obj, uint32_t tee_id); /* Asymmetric key operations util */ bool processing_is_tee_asymm(uint32_t proc_id); enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session, enum processing_func function, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj); enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session, enum processing_func function, enum processing_step step, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session, void *data, uint32_t data_sz, void *out_buf, uint32_t *out_sz); enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session, void *data, uint32_t data_sz, void **out_buf, uint32_t *out_sz); /* * Symmetric crypto algorithm specific functions */ bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id); enum pkcs11_rc init_symm_operation(struct pkcs11_session *session, enum processing_func function, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *key); enum pkcs11_rc step_symm_operation(struct pkcs11_session *session, enum processing_func function, enum processing_step step, uint32_t ptypes, TEE_Param *params); enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing, void *proc_params, size_t params_size); enum pkcs11_rc derive_key_by_symm_enc(struct pkcs11_session *session, void **out_buf, uint32_t *out_sz); enum pkcs11_rc wrap_data_by_symm_enc(struct pkcs11_session *session, void *data, uint32_t data_sz, void *out_buf, uint32_t *out_sz); enum pkcs11_rc unwrap_key_by_symm(struct pkcs11_session *session, void *data, uint32_t data_sz, void **out_buf, uint32_t *out_sz); enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session, void *in, size_t in_size); enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session, void *out, size_t *out_size); enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session, void *out, size_t *out_size); void tee_release_gcm_operation(struct pkcs11_session *session); enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session, void *proc_params, size_t params_size); enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session); /* Digest specific functions */ bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id); enum pkcs11_rc init_digest_operation(struct pkcs11_session *session, struct pkcs11_attribute_head *proc_params); enum pkcs11_rc step_digest_operation(struct pkcs11_session *session, enum processing_step step, struct pkcs11_object *obj, uint32_t ptypes, TEE_Param *params); /* * Elliptic curve crypto algorithm specific functions */ enum pkcs11_rc load_tee_ec_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count, struct pkcs11_object *obj); enum pkcs11_rc load_tee_eddsa_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count, struct pkcs11_object *obj); size_t ec_params2tee_keysize(void *attr, size_t size); uint32_t ec_params2tee_curve(void *attr, size_t size); enum pkcs11_rc pkcs2tee_algo_ecdsa(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj); enum pkcs11_rc generate_ec_keys(struct pkcs11_attribute_head *proc_params, struct obj_attrs **pub_head, struct obj_attrs **priv_head); enum pkcs11_rc generate_eddsa_keys(struct pkcs11_attribute_head *proc_params, struct obj_attrs **pub_head, struct obj_attrs **priv_head); size_t ecdsa_get_input_max_byte_size(TEE_OperationHandle op); /* * RSA crypto algorithm specific functions */ enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count, struct pkcs11_object *obj); enum pkcs11_rc pkcs2tee_proc_params_rsa_pss(struct active_processing *proc, struct pkcs11_attribute_head *proc_params); enum pkcs11_rc pkcs2tee_validate_rsa_pss(struct active_processing *proc, struct pkcs11_object *obj); enum pkcs11_rc pkcs2tee_algo_rsa_pss(uint32_t *tee_id, struct pkcs11_attribute_head *params); enum pkcs11_rc pkcs2tee_proc_params_rsa_oaep(struct active_processing *proc, struct pkcs11_attribute_head *proc_params); enum pkcs11_rc pkcs2tee_proc_params_rsa_aes_wrap(struct active_processing *proc, struct pkcs11_attribute_head *proc_params); enum pkcs11_rc pkcs2tee_proc_params_eddsa(struct active_processing *proc, struct pkcs11_attribute_head *proc_params); enum pkcs11_rc pkcs2tee_algo_rsa_oaep(uint32_t *tee_id, uint32_t *tee_hash_id, struct pkcs11_attribute_head *params); enum pkcs11_rc pkcs2tee_algo_rsa_aes_wrap(uint32_t *tee_id, uint32_t *tee_hash_id, struct pkcs11_attribute_head *params); enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params, struct obj_attrs **pub_head, struct obj_attrs **priv_head); size_t rsa_get_input_max_byte_size(TEE_OperationHandle op); enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session, struct pkcs11_attribute_head *proc_params, struct obj_attrs **head); enum pkcs11_rc pkcs2tee_param_ecdh(struct pkcs11_attribute_head *proc_params, void **pub_data, size_t *pub_size); enum pkcs11_rc pkcs2tee_algo_ecdh(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj); #endif /*PKCS11_TA_PROCESSING_H*/ optee_os-4.3.0/ta/pkcs11/src/processing_aes.c000066400000000000000000000340141464416617300210160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2020, Linaro Limited */ #include #include #include #include #include #include #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "serializer.h" /* * Authenticated ciphering: (AES GCM) * * As per PKCS#11, GCM decryption shall not reveal the data until the * decryption is completed and the MAC verified. The pkcs11 TA retains the * ciphered data until the operation is completed. Therefore every chunk of * decrypted data is saved in a allocated buffer during AE update processing * and only copied into the client's output buffer at AE finalization when * tag is authenticated. * * As per PKCS#11, GCM decryption expect the tag data to be provided * inside the input data for C_DecryptUpdate() and friends, appended to the * input encyprted data hence we do not know which is the last call to * C_DecryptUpdate() where last bytes are not ciphered data but the requested * tag bytes for message autehntication. To handle this, the TA saves * the last input data bytes (length is defined by the tag byte size) in the * AE context and waits the C_DecryptFinal() to either treat these as data * bytes or tag/MAC bytes. Refer to pending_tag and pending_size in struct * ae_aes_context. */ /* * struct out_data_ref - AE decyrption output data chunks * @size - byte size of the allocated buffer * @data - pointer to allocated data */ struct out_data_ref { size_t size; void *data; }; /* * struct ae_aes_context - Extra context data got AE operations * @tag_byte_len - Tag size in byte * @pending_tag - Input data that could be the appended tag * @pending_size - Size of pending input data that could be the tag * @out_data - Pointer to an array of output data references. * @out_count - Number of buffer references in out_data */ struct ae_aes_context { size_t tag_byte_len; char *pending_tag; size_t pending_size; struct out_data_ref *out_data; size_t out_count; }; static enum pkcs11_rc init_ae_aes_context(struct ae_aes_context *ctx) { struct out_data_ref *out_data = NULL; char *pending_tag = NULL; assert(!ctx->out_data && !ctx->out_count && !ctx->pending_tag && !ctx->pending_size); out_data = TEE_Malloc(sizeof(*out_data), TEE_MALLOC_FILL_ZERO); pending_tag = TEE_Malloc(ctx->tag_byte_len, TEE_MALLOC_FILL_ZERO); if (!out_data || !pending_tag) { TEE_Free(out_data); TEE_Free(pending_tag); return PKCS11_CKR_DEVICE_MEMORY; } ctx->pending_tag = pending_tag; ctx->out_data = out_data; return PKCS11_CKR_OK; } static void release_ae_aes_context(struct ae_aes_context *ctx) { size_t n = 0; for (n = 0; n < ctx->out_count; n++) TEE_Free(ctx->out_data[n].data); TEE_Free(ctx->out_data); ctx->out_data = NULL; ctx->out_count = 0; TEE_Free(ctx->pending_tag); ctx->pending_tag = NULL; ctx->pending_size = 0; } /* * This function feeds the AE decryption processing with client * input data. There are 2 constraints to consider. * * Firstly we don't know yet which are the ciphered data and which are * the tag data. GP TEE Internal API function requires we split data and * tag when TEE_AEDecryptFinal() will be called. * * Secondly any generated data must be kept in the TA and only revealed * once tag if succefully processed. */ enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session, void *in, size_t in_size) { struct ae_aes_context *ctx = session->processing->extra_ctx; TEE_Result res = TEE_ERROR_GENERIC; enum pkcs11_rc rc = PKCS11_CKR_OK; size_t data_len = 0; size_t ct_size = 0; void *ptr = NULL; char *ct = NULL; if (!in_size) return PKCS11_CKR_OK; if (!in) return PKCS11_CKR_ARGUMENTS_BAD; /* * Save the last input bytes in case they are the tag * bytes and not ciphered data bytes to be decrypted. */ if (ctx->pending_size + in_size <= ctx->tag_byte_len) { /* * Data bytes are all potential tag bytes. * We only need to update the pending_tag buffer, * and cannot treat any byte as data byte. */ TEE_MemMove(ctx->pending_tag + ctx->pending_size, in, in_size); ctx->pending_size += in_size; return PKCS11_CKR_OK; } /* Size of data that are not potential tag in pending and input data */ data_len = in_size + ctx->pending_size - ctx->tag_byte_len; /* Process pending bytes that are effective data byte */ if (ctx->pending_size && (ctx->pending_size + in_size) >= ctx->tag_byte_len) { uint32_t len = MIN(data_len, ctx->pending_size); res = TEE_AEUpdate(session->processing->tee_op_handle, ctx->pending_tag, len, NULL, &ct_size); if (res && res != TEE_ERROR_SHORT_BUFFER) { rc = tee2pkcs_error(res); goto out; } assert(res == TEE_ERROR_SHORT_BUFFER || !ct_size); /* * If output data to store (not revealed yet), redo with * an allocated temporary reference. */ if (ct_size) { ct = TEE_Malloc(ct_size, TEE_MALLOC_FILL_ZERO); if (!ct) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } res = TEE_AEUpdate(session->processing->tee_op_handle, ctx->pending_tag, len, ct, &ct_size); if (res) { rc = tee2pkcs_error(res); goto out; } assert(ct_size); } /* Save potential tag bytes for later */ TEE_MemMove(ctx->pending_tag, ctx->pending_tag + len, ctx->pending_size - len); ctx->pending_size -= len; data_len -= len; } /* Process input data that are not potential tag bytes */ if (data_len) { size_t size = 0; res = TEE_AEUpdate(session->processing->tee_op_handle, in, data_len, NULL, &size); if (res != TEE_ERROR_SHORT_BUFFER && (res != TEE_SUCCESS || size)) { /* This is not expected */ rc = PKCS11_CKR_GENERAL_ERROR; goto out; } if (size) { ptr = TEE_Realloc(ct, ct_size + size); if (!ptr) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } ct = ptr; res = TEE_AEUpdate(session->processing->tee_op_handle, in, data_len, ct + ct_size, &size); if (res) { rc = tee2pkcs_error(res); goto out; } ct_size += size; } } /* Update pending tag in context if any */ data_len = in_size - data_len; if (data_len > (ctx->tag_byte_len - ctx->pending_size)) { /* This is not expected */ rc = PKCS11_CKR_GENERAL_ERROR; goto out; } if (data_len) { TEE_MemMove(ctx->pending_tag + ctx->pending_size, (char *)in + in_size - data_len, data_len); ctx->pending_size += data_len; } /* Save output data reference in the context */ if (ct_size) { ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) * sizeof(struct out_data_ref)); if (!ptr) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } ctx->out_data = ptr; ctx->out_data[ctx->out_count].size = ct_size; ctx->out_data[ctx->out_count].data = ct; ctx->out_count++; } rc = PKCS11_CKR_OK; out: if (rc) TEE_Free(ct); return rc; } static enum pkcs11_rc reveal_ae_data(struct ae_aes_context *ctx, void *out, size_t *out_size) { uint32_t req_size = 0; char *out_ptr = out; size_t n = 0; for (req_size = 0, n = 0; n < ctx->out_count; n++) req_size += ctx->out_data[n].size; if (*out_size < req_size) { *out_size = req_size; return PKCS11_CKR_BUFFER_TOO_SMALL; } if (!out_ptr) return PKCS11_CKR_ARGUMENTS_BAD; for (n = 0; n < ctx->out_count; n++) { TEE_MemMove(out_ptr, ctx->out_data[n].data, ctx->out_data[n].size); out_ptr += ctx->out_data[n].size; } release_ae_aes_context(ctx); *out_size = req_size; return PKCS11_CKR_OK; } enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session, void *out, size_t *out_size) { struct ae_aes_context *ctx = session->processing->extra_ctx; TEE_Result res = TEE_ERROR_GENERIC; enum pkcs11_rc rc = 0; void *data_ptr = NULL; size_t data_size = 0; if (!out_size) { DMSG("Expect at least a buffer for the output data"); return PKCS11_CKR_ARGUMENTS_BAD; } /* Final is already completed, only need to output the data */ if (!ctx->pending_tag) return reveal_ae_data(ctx, out, out_size); if (ctx->pending_size != ctx->tag_byte_len) { DMSG("Not enough samples: %zu/%zu", ctx->pending_size, ctx->tag_byte_len); return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; } /* Query tag size if any */ data_size = 0; res = TEE_AEDecryptFinal(session->processing->tee_op_handle, NULL, 0, NULL, &data_size, ctx->pending_tag, ctx->tag_byte_len); if (res == TEE_ERROR_SHORT_BUFFER) { data_ptr = TEE_Malloc(data_size, TEE_MALLOC_FILL_ZERO); if (!data_ptr) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } res = TEE_AEDecryptFinal(session->processing->tee_op_handle, NULL, 0, data_ptr, &data_size, ctx->pending_tag, ctx->tag_byte_len); assert(res || data_size); } /* AE decryption is completed */ TEE_Free(ctx->pending_tag); ctx->pending_tag = NULL; rc = tee2pkcs_error(res); if (rc) goto out; if (data_ptr) { void *tmp_ptr = NULL; tmp_ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) * sizeof(struct out_data_ref)); if (!tmp_ptr) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } ctx->out_data = tmp_ptr; ctx->out_data[ctx->out_count].size = data_size; ctx->out_data[ctx->out_count].data = data_ptr; ctx->out_count++; data_ptr = NULL; } rc = reveal_ae_data(ctx, out, out_size); out: TEE_Free(data_ptr); return rc; } enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session, void *out, size_t *out_size) { struct ae_aes_context *ctx = session->processing->extra_ctx; TEE_Result res = TEE_ERROR_GENERIC; uint8_t *tag = NULL; size_t tag_len = 0; size_t size = 0; if (!out || !out_size) return PKCS11_CKR_ARGUMENTS_BAD; /* Check the required sizes (warning: 2 output len: data + tag) */ res = TEE_AEEncryptFinal(session->processing->tee_op_handle, NULL, 0, NULL, &size, &tag, &tag_len); if (tag_len != ctx->tag_byte_len || (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)) { EMSG("Unexpected tag length %zu/%zu or rc 0x%" PRIx32, tag_len, ctx->tag_byte_len, res); return PKCS11_CKR_GENERAL_ERROR; } if (*out_size < size + tag_len) { *out_size = size + tag_len; return PKCS11_CKR_BUFFER_TOO_SMALL; } /* Process data and tag input the client output buffer */ tag = (uint8_t *)out + size; res = TEE_AEEncryptFinal(session->processing->tee_op_handle, NULL, 0, out, &size, tag, &tag_len); if (tag_len != ctx->tag_byte_len) { EMSG("Unexpected tag length"); return PKCS11_CKR_GENERAL_ERROR; } if (!res) *out_size = size + tag_len; return tee2pkcs_error(res); } enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing, void *proc_params, size_t params_size) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_OK; /* CTR parameters */ uint32_t incr_counter = 0; void *counter_bits = NULL; if (!proc_params) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&args, proc_params, params_size); rc = serialargs_get(&args, &incr_counter, sizeof(uint32_t)); if (rc) return rc; rc = serialargs_get_ptr(&args, &counter_bits, 16); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; if (incr_counter != 1) { DMSG("Supports only 1 bit increment counter: %"PRIu32, incr_counter); return PKCS11_CKR_MECHANISM_PARAM_INVALID; } TEE_CipherInit(processing->tee_op_handle, counter_bits, 16); return PKCS11_CKR_OK; } enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session, void *proc_params, size_t params_size) { struct ae_aes_context *params = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; struct serialargs args = { }; /* GCM parameters */ uint32_t tag_bitlen = 0; uint32_t tag_len = 0; uint32_t iv_len = 0; void *iv = NULL; uint32_t aad_len = 0; void *aad = NULL; TEE_MemFill(&args, 0, sizeof(args)); if (!proc_params) return PKCS11_CKR_ARGUMENTS_BAD; serialargs_init(&args, proc_params, params_size); rc = serialargs_get(&args, &iv_len, sizeof(uint32_t)); if (rc) goto out; rc = serialargs_get_ptr(&args, &iv, iv_len); if (rc) goto out; rc = serialargs_get(&args, &aad_len, sizeof(uint32_t)); if (rc) goto out; rc = serialargs_get_ptr(&args, &aad, aad_len); if (rc) goto out; rc = serialargs_get(&args, &tag_bitlen, sizeof(uint32_t)); if (rc) goto out; tag_len = ROUNDUP(tag_bitlen, 8) / 8; /* As per pkcs#11 mechanism specification */ if (tag_bitlen > 128 || !iv_len || iv_len > 256) { DMSG("Invalid parameters: tag_bit_len %"PRIu32 ", iv_len %"PRIu32, tag_bitlen, iv_len); rc = PKCS11_CKR_MECHANISM_PARAM_INVALID; goto out; } params = TEE_Malloc(sizeof(*params), TEE_MALLOC_FILL_ZERO); if (!params) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } /* Store the byte round up byte length for the tag */ params->tag_byte_len = tag_len; rc = init_ae_aes_context(params); if (rc) goto out; /* Session processing owns the active processing params */ assert(!session->processing->extra_ctx); session->processing->extra_ctx = params; TEE_AEInit(session->processing->tee_op_handle, iv, iv_len, tag_bitlen, 0, 0); if (aad_len) TEE_AEUpdateAAD(session->processing->tee_op_handle, aad, aad_len); /* * Save initialized operation state to reset to this state * on one-shot AE request that queries its output buffer size. */ TEE_CopyOperation(session->processing->tee_op_handle2, session->processing->tee_op_handle); rc = PKCS11_CKR_OK; out: if (rc && params) { release_ae_aes_context(params); TEE_Free(params); } return rc; } /* Release extra resources related to the GCM processing*/ void tee_release_gcm_operation(struct pkcs11_session *session) { struct ae_aes_context *ctx = session->processing->extra_ctx; release_ae_aes_context(ctx); TEE_Free(session->processing->extra_ctx); session->processing->extra_ctx = NULL; } /* Reset processing state to the state it was after initialization */ enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session) { struct ae_aes_context *ctx = session->processing->extra_ctx; TEE_CopyOperation(session->processing->tee_op_handle, session->processing->tee_op_handle2); release_ae_aes_context(ctx); return init_ae_aes_context(ctx); } optee_os-4.3.0/ta/pkcs11/src/processing_asymm.c000066400000000000000000000721101464416617300213730ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2020, Linaro Limited */ #include #include #include #include #include #include #include "attributes.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "serializer.h" bool processing_is_tee_asymm(uint32_t proc_id) { switch (proc_id) { /* RSA flavors */ case PKCS11_CKM_RSA_AES_KEY_WRAP: case PKCS11_CKM_RSA_PKCS: case PKCS11_CKM_RSA_PKCS_OAEP: case PKCS11_CKM_RSA_PKCS_PSS: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: /* EC flavors */ case PKCS11_CKM_EDDSA: case PKCS11_CKM_ECDSA: case PKCS11_CKM_ECDH1_DERIVE: case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: return true; default: return false; } } static enum pkcs11_rc pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id, enum processing_func function __unused, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj) { static const struct { enum pkcs11_mechanism_id mech_id; uint32_t tee_id; uint32_t tee_hash_id; } pkcs2tee_algo[] = { /* RSA flavors */ { PKCS11_CKM_RSA_AES_KEY_WRAP, 1, 0 }, { PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 }, { PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 }, { PKCS11_CKM_RSA_PKCS_PSS, 1, 0 }, { PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5, TEE_ALG_MD5 }, { PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1, TEE_ALG_SHA1 }, { PKCS11_CKM_SHA224_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA224, TEE_ALG_SHA224 }, { PKCS11_CKM_SHA256_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, TEE_ALG_SHA256 }, { PKCS11_CKM_SHA384_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA384, TEE_ALG_SHA384 }, { PKCS11_CKM_SHA512_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA512, TEE_ALG_SHA512 }, { PKCS11_CKM_SHA1_RSA_PKCS_PSS, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1, TEE_ALG_SHA1 }, { PKCS11_CKM_SHA224_RSA_PKCS_PSS, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224, TEE_ALG_SHA224 }, { PKCS11_CKM_SHA256_RSA_PKCS_PSS, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256, TEE_ALG_SHA256 }, { PKCS11_CKM_SHA384_RSA_PKCS_PSS, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384, TEE_ALG_SHA384 }, { PKCS11_CKM_SHA512_RSA_PKCS_PSS, TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512, TEE_ALG_SHA512 }, /* EC flavors (Must find key size from the object) */ { PKCS11_CKM_ECDSA, 1, 0 }, { PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 }, { PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 }, { PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 }, { PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 }, { PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 }, { PKCS11_CKM_ECDH1_DERIVE, 1, 0 }, { PKCS11_CKM_EDDSA, TEE_ALG_ED25519, 0 }, }; size_t n = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { if (pkcs2tee_algo[n].mech_id == proc_params->id) { *tee_id = pkcs2tee_algo[n].tee_id; *tee_hash_id = pkcs2tee_algo[n].tee_hash_id; break; } } if (n == ARRAY_SIZE(pkcs2tee_algo)) return PKCS11_RV_NOT_IMPLEMENTED; switch (proc_params->id) { case PKCS11_CKM_RSA_PKCS_PSS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: rc = pkcs2tee_algo_rsa_pss(tee_id, proc_params); break; case PKCS11_CKM_RSA_PKCS_OAEP: rc = pkcs2tee_algo_rsa_oaep(tee_id, tee_hash_id, proc_params); break; case PKCS11_CKM_RSA_AES_KEY_WRAP: rc = pkcs2tee_algo_rsa_aes_wrap(tee_id, tee_hash_id, proc_params); break; case PKCS11_CKM_ECDSA: case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj); break; case PKCS11_CKM_ECDH1_DERIVE: rc = pkcs2tee_algo_ecdh(tee_id, proc_params, obj); break; default: rc = PKCS11_CKR_OK; break; } /* * PKCS#11 uses single mechanism CKM_RSA_PKCS for both ciphering and * authentication whereas GPD TEE expects TEE_ALG_RSAES_PKCS1_V1_5 for * ciphering and TEE_ALG_RSASSA_PKCS1_V1_5 for authentication. */ if (*tee_id == TEE_ALG_RSAES_PKCS1_V1_5 && (function == PKCS11_FUNCTION_SIGN || function == PKCS11_FUNCTION_VERIFY)) *tee_id = TEE_ALG_RSASSA_PKCS1_V1_5; return rc; } static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type, struct pkcs11_object *obj, enum processing_func function) { enum pkcs11_class_id class = get_class(obj->attributes); enum pkcs11_key_type type = get_key_type(obj->attributes); switch (class) { case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: break; default: TEE_Panic(class); break; } switch (type) { case PKCS11_CKK_EC: if (class == PKCS11_CKO_PRIVATE_KEY) { if (function == PKCS11_FUNCTION_DERIVE) *tee_type = TEE_TYPE_ECDH_KEYPAIR; else *tee_type = TEE_TYPE_ECDSA_KEYPAIR; } else { if (function == PKCS11_FUNCTION_DERIVE) *tee_type = TEE_TYPE_ECDH_PUBLIC_KEY; else *tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY; } break; case PKCS11_CKK_RSA: if (class == PKCS11_CKO_PRIVATE_KEY) *tee_type = TEE_TYPE_RSA_KEYPAIR; else *tee_type = TEE_TYPE_RSA_PUBLIC_KEY; break; case PKCS11_CKK_EC_EDWARDS: if (class == PKCS11_CKO_PRIVATE_KEY) *tee_type = TEE_TYPE_ED25519_KEYPAIR; else *tee_type = TEE_TYPE_ED25519_PUBLIC_KEY; break; default: TEE_Panic(type); break; } return PKCS11_CKR_OK; } static enum pkcs11_rc allocate_tee_operation(struct pkcs11_session *session, enum processing_func function, struct pkcs11_attribute_head *params, struct pkcs11_object *obj) { uint32_t size = (uint32_t)get_object_key_bit_size(obj); uint32_t algo = 0; uint32_t hash_algo = 0; uint32_t mode = 0; uint32_t hash_mode = 0; TEE_Result res = TEE_ERROR_GENERIC; struct active_processing *processing = session->processing; assert(processing->tee_op_handle == TEE_HANDLE_NULL); assert(processing->tee_op_handle2 == TEE_HANDLE_NULL); if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj)) return PKCS11_CKR_FUNCTION_FAILED; pkcs2tee_mode(&mode, function); if (hash_algo) { pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST); res = TEE_AllocateOperation(&processing->tee_op_handle2, hash_algo, hash_mode, 0); if (res) { EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32, hash_algo, hash_mode); if (res == TEE_ERROR_NOT_SUPPORTED) return PKCS11_CKR_MECHANISM_INVALID; return tee2pkcs_error(res); } processing->tee_hash_algo = hash_algo; } res = TEE_AllocateOperation(&processing->tee_op_handle, algo, mode, size); if (res) EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32, algo, mode, size); if (res == TEE_ERROR_NOT_SUPPORTED) return PKCS11_CKR_MECHANISM_INVALID; if (res != TEE_SUCCESS && processing->tee_op_handle2 != TEE_HANDLE_NULL) { TEE_FreeOperation(session->processing->tee_op_handle2); processing->tee_op_handle2 = TEE_HANDLE_NULL; processing->tee_hash_algo = 0; } return tee2pkcs_error(res); } static enum pkcs11_rc load_tee_key(struct pkcs11_session *session, struct pkcs11_object *obj, enum processing_func function) { TEE_Attribute *tee_attrs = NULL; size_t tee_attrs_count = 0; size_t object_size = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes); enum pkcs11_key_type type = get_key_type(obj->attributes); assert(class == PKCS11_CKO_PUBLIC_KEY || class == PKCS11_CKO_PRIVATE_KEY); if (obj->key_handle != TEE_HANDLE_NULL) { switch (type) { case PKCS11_CKK_RSA: /* RSA loaded keys can be reused */ assert((obj->key_type == TEE_TYPE_RSA_PUBLIC_KEY && class == PKCS11_CKO_PUBLIC_KEY) || (obj->key_type == TEE_TYPE_RSA_KEYPAIR && class == PKCS11_CKO_PRIVATE_KEY)); goto key_ready; case PKCS11_CKK_EC: /* Reuse EC TEE key only if already DSA or DH */ switch (obj->key_type) { case TEE_TYPE_ECDSA_PUBLIC_KEY: case TEE_TYPE_ECDSA_KEYPAIR: if (function != PKCS11_FUNCTION_DERIVE) goto key_ready; break; case TEE_TYPE_ECDH_PUBLIC_KEY: case TEE_TYPE_ECDH_KEYPAIR: if (function == PKCS11_FUNCTION_DERIVE) goto key_ready; break; default: assert(0); break; } break; default: assert(0); break; } TEE_CloseObject(obj->key_handle); obj->key_handle = TEE_HANDLE_NULL; } rc = pkcs2tee_key_type(&obj->key_type, obj, function); if (rc) return rc; object_size = get_object_key_bit_size(obj); if (!object_size) return PKCS11_CKR_GENERAL_ERROR; switch (type) { case PKCS11_CKK_RSA: rc = load_tee_rsa_key_attrs(&tee_attrs, &tee_attrs_count, obj); break; case PKCS11_CKK_EC: rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj); break; case PKCS11_CKK_EC_EDWARDS: rc = load_tee_eddsa_key_attrs(&tee_attrs, &tee_attrs_count, obj); break; default: break; } if (rc) return rc; res = TEE_AllocateTransientObject(obj->key_type, object_size, &obj->key_handle); if (res) { DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); return tee2pkcs_error(res); } res = TEE_PopulateTransientObject(obj->key_handle, tee_attrs, tee_attrs_count); TEE_Free(tee_attrs); if (res) { DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res); goto error; } key_ready: res = TEE_SetOperationKey(session->processing->tee_op_handle, obj->key_handle); if (res) { DMSG("TEE_SetOperationKey failed, %#"PRIx32, res); goto error; } return PKCS11_CKR_OK; error: TEE_FreeTransientObject(obj->key_handle); obj->key_handle = TEE_HANDLE_NULL; return tee2pkcs_error(res); } static enum pkcs11_rc init_tee_operation(struct pkcs11_session *session, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj) { enum pkcs11_rc rc = PKCS11_CKR_OK; struct active_processing *proc = session->processing; switch (proc_params->id) { case PKCS11_CKM_RSA_PKCS_PSS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: rc = pkcs2tee_proc_params_rsa_pss(proc, proc_params); if (rc) break; rc = pkcs2tee_validate_rsa_pss(proc, obj); break; case PKCS11_CKM_RSA_PKCS_OAEP: rc = pkcs2tee_proc_params_rsa_oaep(proc, proc_params); break; case PKCS11_CKM_EDDSA: rc = pkcs2tee_proc_params_eddsa(proc, proc_params); break; case PKCS11_CKM_RSA_AES_KEY_WRAP: rc = pkcs2tee_proc_params_rsa_aes_wrap(proc, proc_params); break; default: break; } return rc; } enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session, enum processing_func function, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; assert(processing_is_tee_asymm(proc_params->id)); rc = allocate_tee_operation(session, function, proc_params, obj); if (rc) return rc; rc = load_tee_key(session, obj, function); if (rc) return rc; rc = init_tee_operation(session, proc_params, obj); if (!rc) session->processing->mecha_type = proc_params->id; return rc; } /* * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation * * @session - current session * @function - processing function (encrypt, decrypt, sign, ...) * @step - step ID in the processing (oneshot, update, final) * @ptypes - invocation parameter types * @params - invocation parameter references */ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session, enum processing_func function, enum processing_step step, uint32_t ptypes, TEE_Param *params) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; void *in_buf = NULL; void *in2_buf = NULL; void *out_buf = NULL; void *hash_buf = NULL; uint32_t in_size = 0; uint32_t in2_size = 0; size_t out_size = 0; size_t hash_size = 0; TEE_Attribute *tee_attrs = NULL; size_t tee_attrs_count = 0; bool output_data = false; struct active_processing *proc = session->processing; struct rsa_aes_key_wrap_processing_ctx *rsa_aes_ctx = NULL; struct rsa_oaep_processing_ctx *rsa_oaep_ctx = NULL; struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL; struct eddsa_processing_ctx *eddsa_ctx = NULL; size_t sz = 0; if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { in_buf = params[1].memref.buffer; in_size = params[1].memref.size; if (in_size && !in_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) { in2_buf = params[2].memref.buffer; in2_size = params[2].memref.size; if (in2_size && !in2_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { out_buf = params[2].memref.buffer; out_size = params[2].memref.size; if (out_size && !out_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) return PKCS11_CKR_ARGUMENTS_BAD; switch (step) { case PKCS11_FUNC_STEP_ONESHOT: case PKCS11_FUNC_STEP_UPDATE: case PKCS11_FUNC_STEP_FINAL: break; default: return PKCS11_CKR_GENERAL_ERROR; } /* TEE attribute(s) required by the operation */ switch (proc->mecha_type) { case PKCS11_CKM_RSA_PKCS_PSS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: tee_attrs = TEE_Malloc(sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!tee_attrs) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } rsa_pss_ctx = proc->extra_ctx; TEE_InitValueAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_RSA_PSS_SALT_LENGTH, rsa_pss_ctx->salt_len, 0); tee_attrs_count++; break; case PKCS11_CKM_EDDSA: eddsa_ctx = proc->extra_ctx; tee_attrs = TEE_Malloc(2 * sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!tee_attrs) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } if (eddsa_ctx->flag) { TEE_InitValueAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_EDDSA_PREHASH, 0, 0); tee_attrs_count++; } if (eddsa_ctx->ctx_len > 0) { TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_EDDSA_CTX, eddsa_ctx->ctx, eddsa_ctx->ctx_len); tee_attrs_count++; } break; case PKCS11_CKM_RSA_PKCS_OAEP: rsa_oaep_ctx = proc->extra_ctx; if (!rsa_oaep_ctx->source_data_len) break; tee_attrs = TEE_Malloc(sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!tee_attrs) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_RSA_OAEP_LABEL, rsa_oaep_ctx->source_data, rsa_oaep_ctx->source_data_len); tee_attrs_count++; break; case PKCS11_CKM_RSA_AES_KEY_WRAP: rsa_aes_ctx = proc->extra_ctx; if (!rsa_aes_ctx->source_data_len) break; tee_attrs = TEE_Malloc(sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!tee_attrs) { rc = PKCS11_CKR_DEVICE_MEMORY; goto out; } TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_RSA_OAEP_LABEL, rsa_aes_ctx->source_data, rsa_aes_ctx->source_data_len); tee_attrs_count++; break; default: break; } /* * Handle multi stage update step for mechas needing hash * calculation */ if (step == PKCS11_FUNC_STEP_UPDATE) { switch (proc->mecha_type) { case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: assert(proc->tee_op_handle2 != TEE_HANDLE_NULL); TEE_DigestUpdate(proc->tee_op_handle2, in_buf, in_size); rc = PKCS11_CKR_OK; break; default: /* * Other mechanism do not expect multi stage * operation */ rc = PKCS11_CKR_GENERAL_ERROR; break; } goto out; } /* * Handle multi stage one shot and final steps for mechas needing hash * calculation */ switch (proc->mecha_type) { case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: assert(proc->tee_op_handle2 != TEE_HANDLE_NULL); hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo); hash_buf = TEE_Malloc(hash_size, 0); if (!hash_buf) return PKCS11_CKR_DEVICE_MEMORY; res = TEE_DigestDoFinal(proc->tee_op_handle2, in_buf, in_size, hash_buf, &hash_size); rc = tee2pkcs_error(res); if (rc != PKCS11_CKR_OK) goto out; break; default: break; } /* * Finalize either provided hash or calculated hash with signing * operation */ /* First determine amount of bytes for signing operation */ switch (proc->mecha_type) { case PKCS11_CKM_ECDSA: sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle); if (!in_size || !sz) { rc = PKCS11_CKR_FUNCTION_FAILED; goto out; } /* * Note 3) Input the entire raw digest. Internally, this will * be truncated to the appropriate number of bits. */ if (in_size > sz) in_size = sz; if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) { rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; goto out; } break; case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: /* Get key size in bytes */ sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle); if (!sz) { rc = PKCS11_CKR_FUNCTION_FAILED; goto out; } if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) { rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; goto out; } break; case PKCS11_CKM_RSA_PKCS: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_RSA_PKCS_PSS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: /* Get key size in bytes */ sz = rsa_get_input_max_byte_size(proc->tee_op_handle); if (!sz) { rc = PKCS11_CKR_FUNCTION_FAILED; goto out; } if (function == PKCS11_FUNCTION_VERIFY && in2_size != sz) { rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; goto out; } break; default: break; } /* Next perform actual signing operation */ switch (proc->mecha_type) { case PKCS11_CKM_ECDSA: case PKCS11_CKM_EDDSA: case PKCS11_CKM_RSA_PKCS: case PKCS11_CKM_RSA_PKCS_OAEP: case PKCS11_CKM_RSA_PKCS_PSS: /* For operations using provided input data */ switch (function) { case PKCS11_FUNCTION_ENCRYPT: res = TEE_AsymmetricEncrypt(proc->tee_op_handle, tee_attrs, tee_attrs_count, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); if (rc == PKCS11_CKR_ARGUMENTS_BAD) rc = PKCS11_CKR_DATA_LEN_RANGE; break; case PKCS11_FUNCTION_DECRYPT: res = TEE_AsymmetricDecrypt(proc->tee_op_handle, tee_attrs, tee_attrs_count, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); if (rc == PKCS11_CKR_ARGUMENTS_BAD) rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; break; case PKCS11_FUNCTION_SIGN: res = TEE_AsymmetricSignDigest(proc->tee_op_handle, tee_attrs, tee_attrs_count, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); break; case PKCS11_FUNCTION_VERIFY: res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle, tee_attrs, tee_attrs_count, in_buf, in_size, in2_buf, in2_size); rc = tee2pkcs_error(res); break; default: TEE_Panic(function); break; } break; case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: /* For operations having hash operation use calculated hash */ switch (function) { case PKCS11_FUNCTION_SIGN: res = TEE_AsymmetricSignDigest(proc->tee_op_handle, tee_attrs, tee_attrs_count, hash_buf, hash_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); break; case PKCS11_FUNCTION_VERIFY: res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle, tee_attrs, tee_attrs_count, hash_buf, hash_size, in2_buf, in2_size); rc = tee2pkcs_error(res); break; default: TEE_Panic(function); break; } break; default: TEE_Panic(proc->mecha_type); break; } out: if (output_data && (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) { switch (TEE_PARAM_TYPE_GET(ptypes, 2)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: params[2].memref.size = out_size; break; default: rc = PKCS11_CKR_GENERAL_ERROR; break; } } TEE_Free(hash_buf); TEE_Free(tee_attrs); return rc; } enum pkcs11_rc do_asymm_derivation(struct pkcs11_session *session, struct pkcs11_attribute_head *proc_params, struct obj_attrs **head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_ObjectHandle out_handle = TEE_HANDLE_NULL; TEE_Result res = TEE_ERROR_GENERIC; TEE_Attribute tee_attrs[2] = { }; size_t tee_attrs_count = 0; uint32_t key_byte_size = 0; uint32_t key_bit_size = 0; void *a_ptr = NULL; size_t a_size = 0; /* Remove default attribute set at template sanitization */ if (remove_empty_attribute(head, PKCS11_CKA_VALUE)) return PKCS11_CKR_FUNCTION_FAILED; rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &key_bit_size); if (rc) return rc; key_bit_size *= 8; key_byte_size = (key_bit_size + 7) / 8; res = TEE_AllocateTransientObject(TEE_TYPE_GENERIC_SECRET, key_byte_size * 8, &out_handle); if (res) { DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); return tee2pkcs_error(res); } switch (proc_params->id) { case PKCS11_CKM_ECDH1_DERIVE: rc = pkcs2tee_param_ecdh(proc_params, &a_ptr, &a_size); if (rc) goto out; TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_ECC_PUBLIC_VALUE_X, a_ptr, a_size / 2); tee_attrs_count++; TEE_InitRefAttribute(&tee_attrs[tee_attrs_count], TEE_ATTR_ECC_PUBLIC_VALUE_Y, (char *)a_ptr + a_size / 2, a_size / 2); tee_attrs_count++; break; default: TEE_Panic(proc_params->id); break; } TEE_DeriveKey(session->processing->tee_op_handle, &tee_attrs[0], tee_attrs_count, out_handle); rc = alloc_get_tee_attribute_data(out_handle, TEE_ATTR_SECRET_VALUE, &a_ptr, &a_size); if (rc) goto out; if (a_size * 8 < key_bit_size) rc = PKCS11_CKR_KEY_SIZE_RANGE; else rc = add_attribute(head, PKCS11_CKA_VALUE, a_ptr, key_byte_size); TEE_Free(a_ptr); out: release_active_processing(session); TEE_FreeTransientObject(out_handle); return rc; } static enum pkcs11_rc wrap_rsa_aes_key(struct active_processing *proc, void *data, uint32_t data_sz, void *out_buf, uint32_t *out_sz) { enum pkcs11_rc rc = PKCS11_CKR_OK; TEE_Result res = TEE_ERROR_GENERIC; int mbedtls_rc = 0; struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx; mbedtls_nist_kw_context kw_ctx = { }; uint8_t aes_key_value[32] = { }; uint32_t aes_key_size = ctx->aes_key_bits / 8; size_t aes_wrapped_size = *out_sz; uint32_t expected_size = 0; size_t target_key_size = 0; const size_t kw_semiblock_len = 8; if (ctx->aes_key_bits != 128 && ctx->aes_key_bits != 192 && ctx->aes_key_bits != 256) return PKCS11_CKR_ARGUMENTS_BAD; mbedtls_nist_kw_init(&kw_ctx); TEE_GenerateRandom(aes_key_value, aes_key_size); res = TEE_AsymmetricEncrypt(proc->tee_op_handle, NULL, 0, aes_key_value, aes_key_size, out_buf, &aes_wrapped_size); expected_size = aes_wrapped_size + data_sz + kw_semiblock_len; if (res) { if (res == TEE_ERROR_SHORT_BUFFER) *out_sz = expected_size; rc = tee2pkcs_error(res); goto out; } if (*out_sz < expected_size) { rc = PKCS11_CKR_BUFFER_TOO_SMALL; *out_sz = expected_size; goto out; } mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES, aes_key_value, ctx->aes_key_bits, true); if (mbedtls_rc) { if (mbedtls_rc == MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) rc = PKCS11_CKR_KEY_SIZE_RANGE; else rc = PKCS11_CKR_FUNCTION_FAILED; goto out; } mbedtls_rc = mbedtls_nist_kw_wrap(&kw_ctx, MBEDTLS_KW_MODE_KWP, data, data_sz, (uint8_t *)out_buf + aes_wrapped_size, &target_key_size, *out_sz - aes_wrapped_size); if (mbedtls_rc) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto out; } assert(*out_sz >= target_key_size + aes_wrapped_size); *out_sz = target_key_size + aes_wrapped_size; out: mbedtls_nist_kw_free(&kw_ctx); TEE_MemFill(aes_key_value, 0, aes_key_size); return rc; } static enum pkcs11_rc unwrap_rsa_aes_key(struct active_processing *proc, void *data, uint32_t data_sz, void **out_buf, uint32_t *out_sz) { enum pkcs11_rc rc = PKCS11_CKR_OK; int mbedtls_rc = 0; TEE_Result res = TEE_ERROR_GENERIC; TEE_OperationInfo info = { }; struct rsa_aes_key_wrap_processing_ctx *ctx = proc->extra_ctx; mbedtls_nist_kw_context kw_ctx = { }; uint8_t aes_key_value[32] = { }; size_t aes_key_size = ctx->aes_key_bits / 8; uint32_t wrapped_key_size = 0; uint32_t rsa_key_size = 0; size_t target_key_size = 0; if (ctx->aes_key_bits != 128 && ctx->aes_key_bits != 192 && ctx->aes_key_bits != 256) return PKCS11_CKR_ARGUMENTS_BAD; TEE_GetOperationInfo(proc->tee_op_handle, &info); rsa_key_size = info.keySize / 8; wrapped_key_size = data_sz - rsa_key_size; target_key_size = wrapped_key_size - 8; *out_buf = TEE_Malloc(target_key_size, TEE_MALLOC_FILL_ZERO); if (!*out_buf) return PKCS11_CKR_DEVICE_MEMORY; mbedtls_nist_kw_init(&kw_ctx); res = TEE_AsymmetricDecrypt(proc->tee_op_handle, NULL, 0, data, rsa_key_size, aes_key_value, &aes_key_size); if (res) { rc = tee2pkcs_error(res); goto out; } mbedtls_rc = mbedtls_nist_kw_setkey(&kw_ctx, MBEDTLS_CIPHER_ID_AES, aes_key_value, ctx->aes_key_bits, false); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } mbedtls_rc = mbedtls_nist_kw_unwrap(&kw_ctx, MBEDTLS_KW_MODE_KWP, (uint8_t *)data + rsa_key_size, wrapped_key_size, *out_buf, &target_key_size, target_key_size); if (mbedtls_rc) { rc = PKCS11_CKR_WRAPPED_KEY_INVALID; goto out; } *out_sz = target_key_size; out: TEE_MemFill(aes_key_value, 0, aes_key_size); mbedtls_nist_kw_free(&kw_ctx); return rc; } enum pkcs11_rc wrap_data_by_asymm_enc(struct pkcs11_session *session, void *data, uint32_t data_sz, void *out_buf, uint32_t *out_sz) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct active_processing *proc = session->processing; switch (proc->mecha_type) { case PKCS11_CKM_RSA_AES_KEY_WRAP: rc = wrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz); break; default: return PKCS11_CKR_MECHANISM_INVALID; } return rc; } enum pkcs11_rc unwrap_key_by_asymm(struct pkcs11_session *session, void *data, uint32_t data_sz, void **out_buf, uint32_t *out_sz) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct active_processing *proc = session->processing; switch (proc->mecha_type) { case PKCS11_CKM_RSA_AES_KEY_WRAP: rc = unwrap_rsa_aes_key(proc, data, data_sz, out_buf, out_sz); break; default: return PKCS11_CKR_MECHANISM_INVALID; } return rc; } optee_os-4.3.0/ta/pkcs11/src/processing_digest.c000066400000000000000000000125001464416617300215210ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, Vaisala Oyj */ #include #include #include #include #include #include #include #include #include #include "attributes.h" #include "object.h" #include "pkcs11_attributes.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "serializer.h" bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id) { switch (mecha_id) { case PKCS11_CKM_MD5: case PKCS11_CKM_SHA_1: case PKCS11_CKM_SHA224: case PKCS11_CKM_SHA256: case PKCS11_CKM_SHA384: case PKCS11_CKM_SHA512: return true; default: return false; } } static enum pkcs11_rc pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params) { static const struct { enum pkcs11_mechanism_id mech_id; uint32_t tee_id; } pkcs2tee_algo[] = { { PKCS11_CKM_MD5, TEE_ALG_MD5 }, { PKCS11_CKM_SHA_1, TEE_ALG_SHA1 }, { PKCS11_CKM_SHA224, TEE_ALG_SHA224 }, { PKCS11_CKM_SHA256, TEE_ALG_SHA256 }, { PKCS11_CKM_SHA384, TEE_ALG_SHA384 }, { PKCS11_CKM_SHA512, TEE_ALG_SHA512 }, }; size_t n = 0; for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { if (proc_params->id == pkcs2tee_algo[n].mech_id) { *tee_id = pkcs2tee_algo[n].tee_id; return PKCS11_CKR_OK; } } return PKCS11_RV_NOT_IMPLEMENTED; } static enum pkcs11_rc allocate_tee_operation(struct pkcs11_session *session, struct pkcs11_attribute_head *params) { uint32_t algo = 0; TEE_Result res = TEE_ERROR_GENERIC; assert(session->processing->tee_op_handle == TEE_HANDLE_NULL); if (pkcs2tee_algorithm(&algo, params)) return PKCS11_CKR_FUNCTION_FAILED; res = TEE_AllocateOperation(&session->processing->tee_op_handle, algo, TEE_MODE_DIGEST, 0); if (res) EMSG("TEE_AllocateOp. failed %#"PRIx32, algo); if (res == TEE_ERROR_NOT_SUPPORTED) return PKCS11_CKR_MECHANISM_INVALID; return tee2pkcs_error(res); } enum pkcs11_rc init_digest_operation(struct pkcs11_session *session, struct pkcs11_attribute_head *proc_params) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; assert(processing_is_tee_digest(proc_params->id)); rc = allocate_tee_operation(session, proc_params); if (!rc) session->processing->mecha_type = proc_params->id; return rc; } /* * step_digest_operation - processing digest operation step * * @session - current session * @step - step ID in the processing (oneshot, update, final) * @obj - PKCS#11 object for key based operations * @ptype - invocation parameter types * @params - invocation parameter references */ enum pkcs11_rc step_digest_operation(struct pkcs11_session *session, enum processing_step step, struct pkcs11_object *obj, uint32_t ptypes, TEE_Param *params) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; void *in_buf = NULL; size_t in_size = 0; void *out_buf = NULL; size_t out_size = 0; void *secret_value = NULL; uint32_t secret_value_size = 0; enum pkcs11_key_type key_type = PKCS11_CKK_UNDEFINED_ID; struct active_processing *proc = session->processing; if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { in_buf = params[1].memref.buffer; in_size = params[1].memref.size; if (in_size && !in_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { out_buf = params[2].memref.buffer; out_size = params[2].memref.size; if (out_size && !out_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) return PKCS11_CKR_ARGUMENTS_BAD; switch (step) { case PKCS11_FUNC_STEP_ONESHOT: case PKCS11_FUNC_STEP_UPDATE: case PKCS11_FUNC_STEP_UPDATE_KEY: case PKCS11_FUNC_STEP_FINAL: break; default: TEE_Panic(step); break; } assert(proc->tee_op_handle != TEE_HANDLE_NULL); assert(processing_is_tee_digest(proc->mecha_type)); /* * Feed active operation with data */ switch (step) { case PKCS11_FUNC_STEP_UPDATE_KEY: assert(obj); if (!IS_ENABLED(CFG_PKCS11_TA_ALLOW_DIGEST_KEY)) return PKCS11_CKR_KEY_INDIGESTIBLE; if (get_class(obj->attributes) != PKCS11_CKO_SECRET_KEY) return PKCS11_CKR_KEY_INDIGESTIBLE; key_type = get_key_type(obj->attributes); if (key_type != PKCS11_CKK_GENERIC_SECRET && key_type != PKCS11_CKK_AES) return PKCS11_CKR_KEY_INDIGESTIBLE; rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_VALUE, &secret_value, &secret_value_size); assert(!rc && secret_value && secret_value_size); TEE_DigestUpdate(proc->tee_op_handle, secret_value, secret_value_size); return PKCS11_CKR_OK; case PKCS11_FUNC_STEP_UPDATE: if (!in_buf || !in_size) return PKCS11_CKR_OK; TEE_DigestUpdate(proc->tee_op_handle, in_buf, in_size); return PKCS11_CKR_OK; case PKCS11_FUNC_STEP_ONESHOT: if (!out_buf) return PKCS11_CKR_ARGUMENTS_BAD; goto do_final; case PKCS11_FUNC_STEP_FINAL: if (in_buf || !out_buf) return PKCS11_CKR_ARGUMENTS_BAD; goto do_final; default: TEE_Panic(step); break; } do_final: res = TEE_DigestDoFinal(proc->tee_op_handle, in_buf, in_size, out_buf, &out_size); rc = tee2pkcs_error(res); if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL) params[2].memref.size = out_size; return rc; } optee_os-4.3.0/ta/pkcs11/src/processing_ec.c000066400000000000000000000661531464416617300206460ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include "attributes.h" #include "object.h" #include "pkcs11_token.h" #include "processing.h" /* * DER encoded EC parameters generated with script: * ta/pkcs11/scripts/dump_ec_curve_params.sh */ static const uint8_t prime192v1_name_der[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x01, }; static const uint8_t secp224r1_name_der[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x21, }; static const uint8_t prime256v1_name_der[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, }; static const uint8_t secp384r1_name_der[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, }; static const uint8_t secp521r1_name_der[] = { 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, }; static const uint8_t prime192v1_oid_der[] = { 0x30, 0x81, 0xc7, 0x02, 0x01, 0x01, 0x30, 0x24, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x4b, 0x04, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x18, 0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, 0x80, 0xe7, 0x0f, 0xa7, 0xe9, 0xab, 0x72, 0x24, 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec, 0xc1, 0x46, 0xb9, 0xb1, 0x03, 0x15, 0x00, 0x30, 0x45, 0xae, 0x6f, 0xc8, 0x42, 0x2f, 0x64, 0xed, 0x57, 0x95, 0x28, 0xd3, 0x81, 0x20, 0xea, 0xe1, 0x21, 0x96, 0xd5, 0x04, 0x31, 0x04, 0x18, 0x8d, 0xa8, 0x0e, 0xb0, 0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00, 0xf4, 0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12, 0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x99, 0xde, 0xf8, 0x36, 0x14, 0x6b, 0xc9, 0xb1, 0xb4, 0xd2, 0x28, 0x31, 0x02, 0x01, 0x01, }; static const uint8_t secp224r1_oid_der[] = { 0x30, 0x81, 0xdf, 0x02, 0x01, 0x01, 0x30, 0x28, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x1d, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30, 0x53, 0x04, 0x1c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x04, 0x1c, 0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, 0xd7, 0xbf, 0xd8, 0xba, 0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4, 0x03, 0x15, 0x00, 0xbd, 0x71, 0x34, 0x47, 0x99, 0xd5, 0xc7, 0xfc, 0xdc, 0x45, 0xb5, 0x9f, 0xa3, 0xb9, 0xab, 0x8f, 0x6a, 0x94, 0x8b, 0xc5, 0x04, 0x39, 0x04, 0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6, 0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34, 0x02, 0x1d, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, 0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45, 0x5c, 0x5c, 0x2a, 0x3d, 0x02, 0x01, 0x01, }; static const uint8_t prime256v1_oid_der[] = { 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 0x02, 0x01, 0x01, }; static const uint8_t secp384r1_oid_der[] = { 0x30, 0x82, 0x01, 0x57, 0x02, 0x01, 0x01, 0x30, 0x3c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x31, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x30, 0x7b, 0x04, 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x30, 0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e, 0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e, 0xfe, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13, 0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d, 0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef, 0x03, 0x15, 0x00, 0xa3, 0x35, 0x92, 0x6a, 0xa3, 0x19, 0xa2, 0x7a, 0x1d, 0x00, 0x89, 0x6a, 0x67, 0x73, 0xa4, 0x82, 0x7a, 0xcd, 0xac, 0x73, 0x04, 0x61, 0x04, 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7, 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f, 0x02, 0x31, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73, 0x02, 0x01, 0x01, }; static const uint8_t secp521r1_oid_der[] = { 0x30, 0x82, 0x01, 0xc3, 0x02, 0x01, 0x01, 0x30, 0x4d, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x81, 0x9f, 0x04, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x42, 0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1, 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e, 0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, 0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00, 0x03, 0x15, 0x00, 0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc, 0x67, 0x17, 0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba, 0x04, 0x81, 0x85, 0x04, 0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7, 0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50, 0x02, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09, 0x02, 0x01, 0x01, }; /* * Edwards curves may be specified in two flavours: * - as a PrintableString 'edwards25519' or 'edwards448' * - as an OID, DER encoded ASN.1 Object */ static const uint8_t ed25519_name_der[] = { 0x13, 0x0c, 'e', 'd', 'w', 'a', 'r', 'd', 's', '2', '5', '5', '1', '9', }; static const uint8_t ed25519_oid_der[] = { 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01, }; struct supported_ecc_curve { const uint8_t *oid_der; size_t oid_size; const uint8_t *name_der; size_t name_size; size_t key_size; uint32_t tee_id; const char *label; size_t label_size; }; #define ECC_CURVE(_tee_id, _key_size, _label) \ { \ .tee_id = (_tee_id), \ .key_size = (_key_size), \ .oid_der = _label ## _oid_der, \ .oid_size = sizeof(_label ## _oid_der), \ .name_der = _label ## _name_der, \ .name_size = sizeof(_label ## _name_der), \ .label = #_label, \ .label_size = sizeof(#_label) - 1, \ } static const struct supported_ecc_curve ec_curve_param[] = { ECC_CURVE(TEE_ECC_CURVE_NIST_P192, 192, prime192v1), ECC_CURVE(TEE_ECC_CURVE_NIST_P224, 224, secp224r1), ECC_CURVE(TEE_ECC_CURVE_NIST_P256, 256, prime256v1), ECC_CURVE(TEE_ECC_CURVE_NIST_P384, 384, secp384r1), ECC_CURVE(TEE_ECC_CURVE_NIST_P521, 521, secp521r1), ECC_CURVE(TEE_ECC_CURVE_25519, 256, ed25519), }; static const struct supported_ecc_curve *get_curve(void *attr, size_t size) { size_t idx = 0; /* Weak: not a real DER parser: try by params then by named curve */ for (idx = 0; idx < ARRAY_SIZE(ec_curve_param); idx++) { const struct supported_ecc_curve *curve = ec_curve_param + idx; if (size == curve->oid_size && !TEE_MemCompare(attr, curve->oid_der, curve->oid_size)) return curve; if (size == curve->name_size && !TEE_MemCompare(attr, curve->name_der, curve->name_size)) return curve; } return NULL; } size_t ec_params2tee_keysize(void *ec_params, size_t size) { const struct supported_ecc_curve *curve = get_curve(ec_params, size); if (!curve) return 0; return curve->key_size; } /* * This function intentionally panics if the curve is not found. * Use ec_params2tee_keysize() to check the curve is supported by * the internal core API. */ uint32_t ec_params2tee_curve(void *ec_params, size_t size) { const struct supported_ecc_curve *curve = get_curve(ec_params, size); assert(curve); return curve->tee_id; } enum pkcs11_rc load_tee_ec_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count, struct pkcs11_object *obj) { TEE_Attribute *attrs = NULL; size_t count = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; assert(get_key_type(obj->attributes) == PKCS11_CKK_EC); switch (get_class(obj->attributes)) { case PKCS11_CKO_PUBLIC_KEY: attrs = TEE_Malloc(3 * sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!attrs) return PKCS11_CKR_DEVICE_MEMORY; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_CURVE, obj, PKCS11_CKA_EC_PARAMS)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PUBLIC_VALUE_X, obj, PKCS11_CKA_EC_POINT)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PUBLIC_VALUE_Y, obj, PKCS11_CKA_EC_POINT)) count++; if (count == 3) rc = PKCS11_CKR_OK; break; case PKCS11_CKO_PRIVATE_KEY: attrs = TEE_Malloc(4 * sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!attrs) return PKCS11_CKR_DEVICE_MEMORY; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_CURVE, obj, PKCS11_CKA_EC_PARAMS)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PRIVATE_VALUE, obj, PKCS11_CKA_VALUE)) count++; /* * Standard does not have CKA_EC_POINT for EC private keys * but that is required by TEE internal API. First try to get * hidden EC POINT and for backwards compatibility then try to * get CKA_EC_POINT value. */ if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PUBLIC_VALUE_X, obj, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT)) count++; else if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PUBLIC_VALUE_X, obj, PKCS11_CKA_EC_POINT)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PUBLIC_VALUE_Y, obj, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT)) count++; else if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ECC_PUBLIC_VALUE_Y, obj, PKCS11_CKA_EC_POINT)) count++; if (count == 4) rc = PKCS11_CKR_OK; break; default: assert(0); break; } if (rc == PKCS11_CKR_OK) { *tee_attrs = attrs; *tee_count = count; } else { TEE_Free(attrs); } return rc; } enum pkcs11_rc pkcs2tee_algo_ecdsa(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj) { switch (proc_params->id) { case PKCS11_CKM_ECDSA: case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: break; default: return PKCS11_CKR_GENERAL_ERROR; } /* * TODO: Fixing this in a way to support also other EC curves would * require OP-TEE to be updated for newer version of GlobalPlatform API */ switch (get_object_key_bit_size(obj)) { case 192: *tee_id = TEE_ALG_ECDSA_P192; break; case 224: *tee_id = TEE_ALG_ECDSA_P224; break; case 256: *tee_id = TEE_ALG_ECDSA_P256; break; case 384: *tee_id = TEE_ALG_ECDSA_P384; break; case 521: *tee_id = TEE_ALG_ECDSA_P521; break; default: TEE_Panic(0); break; } return PKCS11_CKR_OK; } static enum pkcs11_rc tee2pkcs_ec_attributes(struct obj_attrs **pub_head, struct obj_attrs **priv_head, TEE_ObjectHandle tee_obj, size_t tee_size) { void *x_ptr = NULL; void *y_ptr = NULL; uint8_t *ecpoint = NULL; size_t x_size = 0; size_t y_size = 0; size_t psize = 0; size_t qsize = 0; size_t dersize = 0; size_t poffset = 0; size_t hsize = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_VALUE, tee_obj, TEE_ATTR_ECC_PRIVATE_VALUE); if (rc) goto out; rc = alloc_get_tee_attribute_data(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_X, &x_ptr, &x_size); if (rc) goto out; rc = alloc_get_tee_attribute_data(tee_obj, TEE_ATTR_ECC_PUBLIC_VALUE_Y, &y_ptr, &y_size); if (rc) goto x_cleanup; psize = (tee_size + 7) / 8; if (x_size > psize || y_size > psize) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto y_cleanup; } qsize = 1 + 2 * psize; if (qsize < 0x80) { /* DER short definitive form up to 127 bytes */ dersize = qsize + 2; hsize = 2 /* der */ + 1 /* point compression */; } else if (qsize < 0x100) { /* DER long definitive form up to 255 bytes */ dersize = qsize + 3; hsize = 3 /* der */ + 1 /* point compression */; } else { EMSG("Too long DER value"); rc = PKCS11_CKR_MECHANISM_PARAM_INVALID; goto y_cleanup; } ecpoint = TEE_Malloc(dersize, TEE_MALLOC_FILL_ZERO); if (!ecpoint) { rc = PKCS11_CKR_DEVICE_MEMORY; goto y_cleanup; } if (qsize < 0x80) { /* DER encoding */ ecpoint[0] = 0x04; ecpoint[1] = qsize & 0x7f; /* Only UNCOMPRESSED ECPOINT is currently supported */ ecpoint[2] = 0x04; } else if (qsize < 0x100) { /* DER encoding */ ecpoint[0] = 0x04; ecpoint[1] = 0x80 | 0x01; /* long form, one size octet */ ecpoint[2] = qsize & 0xFF; /* Only UNCOMPRESSED ECPOINT is currently supported */ ecpoint[3] = 0x04; } poffset = 0; if (x_size < psize) poffset = psize - x_size; TEE_MemMove(ecpoint + hsize + poffset, x_ptr, x_size); poffset = 0; if (y_size < psize) poffset = psize - y_size; TEE_MemMove(ecpoint + hsize + psize + poffset, y_ptr, y_size); /* * Add PKCS11_CKA_OPTEE_HIDDEN_EC_POINT to private key object and * standard PKCS11_CKA_EC_POINT to public key objects as * TEE_PopulateTransientObject requires public x/y values * for TEE_TYPE_ECDSA_KEYPAIR. */ rc = add_attribute(priv_head, PKCS11_CKA_OPTEE_HIDDEN_EC_POINT, ecpoint, dersize); if (rc) goto ecpoint_cleanup; rc = add_attribute(pub_head, PKCS11_CKA_EC_POINT, ecpoint, dersize); ecpoint_cleanup: TEE_Free(ecpoint); y_cleanup: TEE_Free(y_ptr); x_cleanup: TEE_Free(x_ptr); out: return rc; } enum pkcs11_rc generate_ec_keys(struct pkcs11_attribute_head *proc_params, struct obj_attrs **pub_head, struct obj_attrs **priv_head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *a_ptr = NULL; uint32_t a_size = 0; uint32_t tee_size = 0; uint32_t tee_curve = 0; TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL; TEE_Attribute tee_key_attr[1] = { }; TEE_Result res = TEE_ERROR_GENERIC; if (!proc_params || !*pub_head || !*priv_head) return PKCS11_CKR_TEMPLATE_INCONSISTENT; if (remove_empty_attribute(pub_head, PKCS11_CKA_EC_POINT) || remove_empty_attribute(priv_head, PKCS11_CKA_VALUE) || remove_empty_attribute(priv_head, PKCS11_CKA_EC_PARAMS)) { EMSG("Unexpected attribute(s) found"); trace_attributes("public-key", *pub_head); trace_attributes("private-key", *priv_head); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } if (get_attribute_ptr(*pub_head, PKCS11_CKA_EC_PARAMS, &a_ptr, &a_size) || !a_ptr) { EMSG("No EC_PARAMS attribute found in public key"); return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; } tee_size = ec_params2tee_keysize(a_ptr, a_size); if (!tee_size) return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; tee_curve = ec_params2tee_curve(a_ptr, a_size); TEE_InitValueAttribute(tee_key_attr, TEE_ATTR_ECC_CURVE, tee_curve, 0); /* Create an ECDSA TEE key: will match PKCS11 ECDSA and ECDH */ res = TEE_AllocateTransientObject(TEE_TYPE_ECDSA_KEYPAIR, tee_size, &tee_obj); if (res) { EMSG("Transient alloc failed with %#"PRIx32, res); return tee2pkcs_error(res); } res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE); if (res) { rc = tee2pkcs_error(res); goto out; } res = TEE_GenerateKey(tee_obj, tee_size, tee_key_attr, 1); if (res) { rc = tee2pkcs_error(res); goto out; } /* Private key needs the same EC_PARAMS as used by the public key */ rc = add_attribute(priv_head, PKCS11_CKA_EC_PARAMS, a_ptr, a_size); if (rc) goto out; rc = tee2pkcs_ec_attributes(pub_head, priv_head, tee_obj, tee_size); out: if (tee_obj != TEE_HANDLE_NULL) TEE_CloseObject(tee_obj); return rc; } enum pkcs11_rc load_tee_eddsa_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count, struct pkcs11_object *obj) { TEE_Attribute *attrs = NULL; size_t count = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; assert(get_key_type(obj->attributes) == PKCS11_CKK_EC_EDWARDS); switch (get_class(obj->attributes)) { case PKCS11_CKO_PUBLIC_KEY: attrs = TEE_Malloc(sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!attrs) return PKCS11_CKR_DEVICE_MEMORY; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ED25519_PUBLIC_VALUE, obj, PKCS11_CKA_EC_POINT)) count++; if (count == 1) rc = PKCS11_CKR_OK; break; case PKCS11_CKO_PRIVATE_KEY: attrs = TEE_Malloc(2 * sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!attrs) return PKCS11_CKR_DEVICE_MEMORY; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ED25519_PRIVATE_VALUE, obj, PKCS11_CKA_VALUE)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_ED25519_PUBLIC_VALUE, obj, PKCS11_CKA_EC_POINT)) count++; if (count == 2) rc = PKCS11_CKR_OK; break; default: assert(0); break; } if (rc == PKCS11_CKR_OK) { *tee_attrs = attrs; *tee_count = count; } else { TEE_Free(attrs); } return rc; } enum pkcs11_rc generate_eddsa_keys(struct pkcs11_attribute_head *proc_params, struct obj_attrs **pub_head, struct obj_attrs **priv_head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *a_ptr = NULL; uint32_t a_size = 0; uint32_t tee_size = 0; TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL; TEE_Result res = TEE_ERROR_GENERIC; if (!proc_params || !*pub_head || !*priv_head) return PKCS11_CKR_TEMPLATE_INCONSISTENT; if (remove_empty_attribute(pub_head, PKCS11_CKA_EC_POINT) || remove_empty_attribute(priv_head, PKCS11_CKA_VALUE) || remove_empty_attribute(priv_head, PKCS11_CKA_EC_POINT) || remove_empty_attribute(priv_head, PKCS11_CKA_EC_PARAMS)) { EMSG("Unexpected attribute(s) found"); trace_attributes("public-key", *pub_head); trace_attributes("private-key", *priv_head); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } if (get_attribute_ptr(*pub_head, PKCS11_CKA_EC_PARAMS, &a_ptr, &a_size) || !a_ptr) { EMSG("No EC_PARAMS attribute found in public key"); return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; } tee_size = ec_params2tee_keysize(a_ptr, a_size); if (!tee_size) return PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; res = TEE_AllocateTransientObject(TEE_TYPE_ED25519_KEYPAIR, tee_size, &tee_obj); if (res) { EMSG("Transient alloc failed with %#"PRIx32, res); return tee2pkcs_error(res); } res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE); if (res) { rc = tee2pkcs_error(res); goto out; } res = TEE_GenerateKey(tee_obj, tee_size, NULL, 0); if (res) { rc = tee2pkcs_error(res); goto out; } /* Private key needs the same EC_PARAMS as used by the public key */ rc = add_attribute(priv_head, PKCS11_CKA_EC_PARAMS, a_ptr, a_size); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_VALUE, tee_obj, TEE_ATTR_ED25519_PRIVATE_VALUE); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EC_POINT, tee_obj, TEE_ATTR_ED25519_PUBLIC_VALUE); if (rc) goto out; rc = tee2pkcs_add_attribute(pub_head, PKCS11_CKA_EC_POINT, tee_obj, TEE_ATTR_ED25519_PUBLIC_VALUE); out: if (tee_obj != TEE_HANDLE_NULL) TEE_CloseObject(tee_obj); return rc; } enum pkcs11_rc pkcs2tee_proc_params_eddsa(struct active_processing *proc, struct pkcs11_attribute_head *proc_params) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t ctx_len = 0; uint32_t flag = 0; void *ctx_data = NULL; struct serialargs args = { }; struct eddsa_processing_ctx *ctx = NULL; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &flag); if (rc) return rc; rc = serialargs_get_u32(&args, &ctx_len); if (rc) return rc; rc = serialargs_get_ptr(&args, &ctx_data, ctx_len); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; proc->extra_ctx = TEE_Malloc(sizeof(*ctx) + ctx_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!proc->extra_ctx) return PKCS11_CKR_DEVICE_MEMORY; ctx = proc->extra_ctx; ctx->ctx_len = ctx_len; ctx->flag = flag; TEE_MemMove(ctx->ctx, ctx_data, ctx_len); return PKCS11_CKR_OK; } size_t ecdsa_get_input_max_byte_size(TEE_OperationHandle op) { TEE_OperationInfo info = { }; TEE_GetOperationInfo(op, &info); switch (info.algorithm) { case TEE_ALG_ECDSA_P192: return 24; case TEE_ALG_ECDSA_P224: return 28; case TEE_ALG_ECDSA_P256: return 32; case TEE_ALG_ECDSA_P384: return 48; case TEE_ALG_ECDSA_P521: return 66; default: DMSG("Unexpected ECDSA algorithm %#"PRIx32, info.algorithm); return 0; } } enum pkcs11_rc pkcs2tee_param_ecdh(struct pkcs11_attribute_head *proc_params, void **pub_data, size_t *pub_size) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs args = { }; uint32_t word = 0; uint8_t byte = 0; serialargs_init(&args, proc_params->data, proc_params->size); /* Skip KDF */ rc = serialargs_get_u32(&args, &word); if (rc) return rc; /* Shared data size, shall be 0 */ rc = serialargs_get_u32(&args, &word); if (rc || word) return rc; /* Public data size and content */ rc = serialargs_get_u32(&args, &word); if (rc || !word) return rc; *pub_size = word; rc = serialargs_get(&args, &byte, sizeof(uint8_t)); if (rc) return rc; if (byte != 0x02 && byte != 0x03 && byte != 0x04) return PKCS11_CKR_ARGUMENTS_BAD; if (byte != 0x04) { EMSG("DER compressed public key format not yet supported"); return PKCS11_CKR_ARGUMENTS_BAD; } *pub_size -= sizeof(uint8_t); if (*pub_size >= 0x80) { EMSG("DER long definitive form not yet supported"); return PKCS11_CKR_ARGUMENTS_BAD; } rc = serialargs_get_ptr(&args, pub_data, *pub_size); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; return PKCS11_CKR_OK; } enum pkcs11_rc pkcs2tee_algo_ecdh(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct serialargs args = { }; uint32_t kdf = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &kdf); if (rc) return rc; /* Remaining arguments are extracted by pkcs2tee_param_ecdh */ if (kdf != PKCS11_CKD_NULL) { DMSG("Only support CKD_NULL key derivation for ECDH"); return PKCS11_CKR_MECHANISM_PARAM_INVALID; } switch (get_object_key_bit_size(obj)) { case 192: *tee_id = TEE_ALG_ECDH_P192; break; case 224: *tee_id = TEE_ALG_ECDH_P224; break; case 256: *tee_id = TEE_ALG_ECDH_P256; break; case 384: *tee_id = TEE_ALG_ECDH_P384; break; case 521: *tee_id = TEE_ALG_ECDH_P521; break; default: TEE_Panic(0); break; } return PKCS11_CKR_OK; } optee_os-4.3.0/ta/pkcs11/src/processing_rsa.c000066400000000000000000000466201464416617300210410ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2018-2021, Linaro Limited */ #include #include #include #include #include #include "attributes.h" #include "object.h" #include "pkcs11_token.h" #include "processing.h" enum pkcs11_rc pkcs2tee_proc_params_rsa_pss(struct active_processing *proc, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct rsa_pss_processing_ctx *ctx = NULL; uint32_t hash = 0; uint32_t mgf = 0; uint32_t salt_len = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &hash); if (rc) return rc; rc = serialargs_get_u32(&args, &mgf); if (rc) return rc; rc = serialargs_get_u32(&args, &salt_len); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; proc->extra_ctx = TEE_Malloc(sizeof(struct rsa_pss_processing_ctx), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!proc->extra_ctx) return PKCS11_CKR_DEVICE_MEMORY; ctx = proc->extra_ctx; ctx->hash_alg = hash; ctx->mgf_type = mgf; ctx->salt_len = salt_len; return PKCS11_CKR_OK; } enum pkcs11_rc pkcs2tee_validate_rsa_pss(struct active_processing *proc, struct pkcs11_object *obj) { struct rsa_pss_processing_ctx *rsa_pss_ctx = NULL; size_t modulus_size = 0; size_t hash_size = 0; uint32_t k = 0; rsa_pss_ctx = proc->extra_ctx; assert(rsa_pss_ctx); switch (rsa_pss_ctx->hash_alg) { case PKCS11_CKM_SHA_1: hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA1); break; case PKCS11_CKM_SHA224: hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA224); break; case PKCS11_CKM_SHA256: hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA256); break; case PKCS11_CKM_SHA384: hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA384); break; case PKCS11_CKM_SHA512: hash_size = TEE_ALG_GET_DIGEST_SIZE(TEE_ALG_SHA512); break; default: assert(0); break; } modulus_size = get_object_key_bit_size(obj); /** * The sLen field must be less than or equal to k*-2-hLen where * hLen is the length in bytes of the hash value. k* is the * length in bytes of the RSA modulus, except if the length in * bits of the RSA modulus is one more than a multiple of 8, in * which case k* is one less than the length in bytes of the * RSA modulus. */ if ((modulus_size % 8) == 1) k = modulus_size / 8; else k = ROUNDUP(modulus_size, 8) / 8; if (rsa_pss_ctx->salt_len > (k - 2 - hash_size)) return PKCS11_CKR_KEY_SIZE_RANGE; return PKCS11_CKR_OK; } /* * Check or set TEE algorithm identifier upon PKCS11 mechanism parameters * @tee_id: Input and/or output TEE algorithm identifier * @proc_params: PKCS11 processing parameters */ enum pkcs11_rc pkcs2tee_algo_rsa_pss(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t hash = 0; uint32_t mgf = 0; uint32_t salt_len = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &hash); if (rc) return rc; rc = serialargs_get_u32(&args, &mgf); if (rc) return rc; rc = serialargs_get_u32(&args, &salt_len); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; if (proc_params->id == PKCS11_CKM_RSA_PKCS_PSS) { if (hash == PKCS11_CKM_SHA_1 && mgf == PKCS11_CKG_MGF1_SHA1) { *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1; return PKCS11_CKR_OK; } if (hash == PKCS11_CKM_SHA224 && mgf == PKCS11_CKG_MGF1_SHA224) { *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224; return PKCS11_CKR_OK; } if (hash == PKCS11_CKM_SHA256 && mgf == PKCS11_CKG_MGF1_SHA256) { *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256; return PKCS11_CKR_OK; } if (hash == PKCS11_CKM_SHA384 && mgf == PKCS11_CKG_MGF1_SHA384) { *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384; return PKCS11_CKR_OK; } if (hash == PKCS11_CKM_SHA512 && mgf == PKCS11_CKG_MGF1_SHA512) { *tee_id = TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512; return PKCS11_CKR_OK; } return PKCS11_CKR_MECHANISM_PARAM_INVALID; } switch (*tee_id) { case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1: if (hash != PKCS11_CKM_SHA_1 || mgf != PKCS11_CKG_MGF1_SHA1) return PKCS11_CKR_MECHANISM_PARAM_INVALID; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224: if (hash != PKCS11_CKM_SHA224 || mgf != PKCS11_CKG_MGF1_SHA224) return PKCS11_CKR_MECHANISM_PARAM_INVALID; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256: if (hash != PKCS11_CKM_SHA256 || mgf != PKCS11_CKG_MGF1_SHA256) return PKCS11_CKR_MECHANISM_PARAM_INVALID; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384: if (hash != PKCS11_CKM_SHA384 || mgf != PKCS11_CKG_MGF1_SHA384) return PKCS11_CKR_MECHANISM_PARAM_INVALID; break; case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512: if (hash != PKCS11_CKM_SHA512 || mgf != PKCS11_CKG_MGF1_SHA512) return PKCS11_CKR_MECHANISM_PARAM_INVALID; break; default: return PKCS11_CKR_GENERAL_ERROR; } return PKCS11_CKR_OK; } enum pkcs11_rc pkcs2tee_proc_params_rsa_oaep(struct active_processing *proc, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct rsa_oaep_processing_ctx *ctx = NULL; uint32_t hash = 0; uint32_t mgf = 0; uint32_t source_type = 0; void *source_data = NULL; uint32_t source_size = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &hash); if (rc) return rc; rc = serialargs_get_u32(&args, &mgf); if (rc) return rc; rc = serialargs_get_u32(&args, &source_type); if (rc) return rc; rc = serialargs_get_u32(&args, &source_size); if (rc) return rc; rc = serialargs_get_ptr(&args, &source_data, source_size); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; proc->extra_ctx = TEE_Malloc(sizeof(struct rsa_oaep_processing_ctx) + source_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!proc->extra_ctx) return PKCS11_CKR_DEVICE_MEMORY; ctx = proc->extra_ctx; ctx->hash_alg = hash; ctx->mgf_type = mgf; ctx->source_type = source_type; ctx->source_data_len = source_size; TEE_MemMove(ctx->source_data, source_data, source_size); return PKCS11_CKR_OK; } enum pkcs11_rc pkcs2tee_proc_params_rsa_aes_wrap(struct active_processing *proc, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; struct rsa_aes_key_wrap_processing_ctx *ctx = NULL; uint32_t aes_key_bits = 0; uint32_t hash = 0; uint32_t mgf = 0; uint32_t source_type = 0; void *source_data = NULL; uint32_t source_size = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &aes_key_bits); if (rc) return rc; rc = serialargs_get_u32(&args, &hash); if (rc) return rc; rc = serialargs_get_u32(&args, &mgf); if (rc) return rc; rc = serialargs_get_u32(&args, &source_type); if (rc) return rc; rc = serialargs_get_u32(&args, &source_size); if (rc) return rc; rc = serialargs_get_ptr(&args, &source_data, source_size); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; proc->extra_ctx = TEE_Malloc(sizeof(struct rsa_aes_key_wrap_processing_ctx) + source_size, TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!proc->extra_ctx) return PKCS11_CKR_DEVICE_MEMORY; ctx = proc->extra_ctx; ctx->aes_key_bits = aes_key_bits; ctx->hash_alg = hash; ctx->mgf_type = mgf; ctx->source_type = source_type; ctx->source_data_len = source_size; TEE_MemMove(ctx->source_data, source_data, source_size); return PKCS11_CKR_OK; } /* * Set TEE RSA OAEP algorithm identifier upon PKCS11 mechanism parameters * @tee_id: output TEE RSA OAEP algorithm identifier * @tee_hash_id: output TEE hash algorithm identifier * @proc_params: PKCS11 processing parameters */ enum pkcs11_rc pkcs2tee_algo_rsa_oaep(uint32_t *tee_id, uint32_t *tee_hash_id, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t hash = 0; uint32_t mgf = 0; uint32_t source_type = 0; void *source_data = NULL; uint32_t source_size = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &hash); if (rc) return rc; rc = serialargs_get_u32(&args, &mgf); if (rc) return rc; rc = serialargs_get_u32(&args, &source_type); if (rc) return rc; rc = serialargs_get_u32(&args, &source_size); if (rc) return rc; rc = serialargs_get_ptr(&args, &source_data, source_size); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; if (source_type != PKCS11_CKZ_DATA_SPECIFIED) return PKCS11_CKR_MECHANISM_PARAM_INVALID; switch (proc_params->id) { case PKCS11_CKM_RSA_PKCS_OAEP: switch (hash) { case PKCS11_CKM_SHA_1: if (mgf != PKCS11_CKG_MGF1_SHA1) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1; *tee_hash_id = TEE_ALG_SHA1; break; case PKCS11_CKM_SHA224: if (mgf != PKCS11_CKG_MGF1_SHA224) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224; *tee_hash_id = TEE_ALG_SHA224; break; case PKCS11_CKM_SHA256: if (mgf != PKCS11_CKG_MGF1_SHA256) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256; *tee_hash_id = TEE_ALG_SHA256; break; case PKCS11_CKM_SHA384: if (mgf != PKCS11_CKG_MGF1_SHA384) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384; *tee_hash_id = TEE_ALG_SHA384; break; case PKCS11_CKM_SHA512: if (mgf != PKCS11_CKG_MGF1_SHA512) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512; *tee_hash_id = TEE_ALG_SHA512; break; default: EMSG("Unexpected %#"PRIx32"/%s", hash, id2str_proc(hash)); return PKCS11_CKR_GENERAL_ERROR; } break; default: EMSG("Unexpected mechanism %#"PRIx32"/%s", proc_params->id, id2str_proc(proc_params->id)); return PKCS11_CKR_GENERAL_ERROR; } return PKCS11_CKR_OK; } enum pkcs11_rc pkcs2tee_algo_rsa_aes_wrap(uint32_t *tee_id, uint32_t *tee_hash_id, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t aes_key_bits = 0; uint32_t hash = 0; uint32_t mgf = 0; uint32_t source_type = 0; void *source_data = NULL; uint32_t source_size = 0; serialargs_init(&args, proc_params->data, proc_params->size); rc = serialargs_get_u32(&args, &aes_key_bits); if (rc) return rc; rc = serialargs_get_u32(&args, &hash); if (rc) return rc; rc = serialargs_get_u32(&args, &mgf); if (rc) return rc; rc = serialargs_get_u32(&args, &source_type); if (rc) return rc; rc = serialargs_get_u32(&args, &source_size); if (rc) return rc; rc = serialargs_get_ptr(&args, &source_data, source_size); if (rc) return rc; if (serialargs_remaining_bytes(&args)) return PKCS11_CKR_ARGUMENTS_BAD; if (source_type != PKCS11_CKZ_DATA_SPECIFIED) return PKCS11_CKR_MECHANISM_PARAM_INVALID; switch (proc_params->id) { case PKCS11_CKM_RSA_AES_KEY_WRAP: switch (hash) { case PKCS11_CKM_SHA_1: if (mgf != PKCS11_CKG_MGF1_SHA1) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1; *tee_hash_id = TEE_ALG_SHA1; break; case PKCS11_CKM_SHA224: if (mgf != PKCS11_CKG_MGF1_SHA224) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224; *tee_hash_id = TEE_ALG_SHA224; break; case PKCS11_CKM_SHA256: if (mgf != PKCS11_CKG_MGF1_SHA256) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256; *tee_hash_id = TEE_ALG_SHA256; break; case PKCS11_CKM_SHA384: if (mgf != PKCS11_CKG_MGF1_SHA384) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384; *tee_hash_id = TEE_ALG_SHA384; break; case PKCS11_CKM_SHA512: if (mgf != PKCS11_CKG_MGF1_SHA512) return PKCS11_CKR_MECHANISM_PARAM_INVALID; *tee_id = TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512; *tee_hash_id = TEE_ALG_SHA512; break; default: EMSG("Unexpected %#"PRIx32"/%s", hash, id2str_proc(hash)); return PKCS11_CKR_GENERAL_ERROR; } break; default: EMSG("Unexpected mechanism %#"PRIx32"/%s", proc_params->id, id2str_proc(proc_params->id)); return PKCS11_CKR_GENERAL_ERROR; } return PKCS11_CKR_OK; } enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs, size_t *tee_count, struct pkcs11_object *obj) { TEE_Attribute *attrs = NULL; size_t count = 0; enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *a_ptr = NULL; assert(get_key_type(obj->attributes) == PKCS11_CKK_RSA); switch (get_class(obj->attributes)) { case PKCS11_CKO_PUBLIC_KEY: attrs = TEE_Malloc(2 * sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!attrs) return PKCS11_CKR_DEVICE_MEMORY; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS, obj, PKCS11_CKA_MODULUS)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PUBLIC_EXPONENT, obj, PKCS11_CKA_PUBLIC_EXPONENT)) count++; if (count == 2) rc = PKCS11_CKR_OK; break; case PKCS11_CKO_PRIVATE_KEY: attrs = TEE_Malloc(8 * sizeof(TEE_Attribute), TEE_USER_MEM_HINT_NO_FILL_ZERO); if (!attrs) return PKCS11_CKR_DEVICE_MEMORY; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_MODULUS, obj, PKCS11_CKA_MODULUS)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PUBLIC_EXPONENT, obj, PKCS11_CKA_PUBLIC_EXPONENT)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIVATE_EXPONENT, obj, PKCS11_CKA_PRIVATE_EXPONENT)) count++; if (count != 3) break; /* If pre-computed values are present load those */ rc = get_attribute_ptr(obj->attributes, PKCS11_CKA_PRIME_1, &a_ptr, NULL); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) break; if (rc == PKCS11_RV_NOT_FOUND || !a_ptr) { rc = PKCS11_CKR_OK; break; } if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME1, obj, PKCS11_CKA_PRIME_1)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME2, obj, PKCS11_CKA_PRIME_2)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_EXPONENT1, obj, PKCS11_CKA_EXPONENT_1)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_EXPONENT2, obj, PKCS11_CKA_EXPONENT_2)) count++; if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_COEFFICIENT, obj, PKCS11_CKA_COEFFICIENT)) count++; if (count == 8) rc = PKCS11_CKR_OK; break; default: assert(0); break; } if (rc == PKCS11_CKR_OK) { *tee_attrs = attrs; *tee_count = count; } else { TEE_Free(attrs); } return rc; } static enum pkcs11_rc tee2pkcs_rsa_attributes(struct obj_attrs **pub_head, struct obj_attrs **priv_head, TEE_ObjectHandle tee_obj) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *a_ptr = NULL; rc = tee2pkcs_add_attribute(pub_head, PKCS11_CKA_MODULUS, tee_obj, TEE_ATTR_RSA_MODULUS); if (rc) goto out; rc = get_attribute_ptr(*pub_head, PKCS11_CKA_PUBLIC_EXPONENT, &a_ptr, NULL); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) goto out; if (rc == PKCS11_CKR_OK && !a_ptr) { rc = remove_empty_attribute(pub_head, PKCS11_CKA_PUBLIC_EXPONENT); if (rc) goto out; rc = PKCS11_RV_NOT_FOUND; } if (rc == PKCS11_RV_NOT_FOUND) { rc = tee2pkcs_add_attribute(pub_head, PKCS11_CKA_PUBLIC_EXPONENT, tee_obj, TEE_ATTR_RSA_PUBLIC_EXPONENT); if (rc) goto out; } rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_MODULUS, tee_obj, TEE_ATTR_RSA_MODULUS); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PUBLIC_EXPONENT, tee_obj, TEE_ATTR_RSA_PUBLIC_EXPONENT); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIVATE_EXPONENT, tee_obj, TEE_ATTR_RSA_PRIVATE_EXPONENT); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIME_1, tee_obj, TEE_ATTR_RSA_PRIME1); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_PRIME_2, tee_obj, TEE_ATTR_RSA_PRIME2); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EXPONENT_1, tee_obj, TEE_ATTR_RSA_EXPONENT1); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_EXPONENT_2, tee_obj, TEE_ATTR_RSA_EXPONENT2); if (rc) goto out; rc = tee2pkcs_add_attribute(priv_head, PKCS11_CKA_COEFFICIENT, tee_obj, TEE_ATTR_RSA_COEFFICIENT); out: return rc; } enum pkcs11_rc generate_rsa_keys(struct pkcs11_attribute_head *proc_params, struct obj_attrs **pub_head, struct obj_attrs **priv_head) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; void *a_ptr = NULL; uint32_t a_size = 0; TEE_ObjectHandle tee_obj = TEE_HANDLE_NULL; TEE_Result res = TEE_ERROR_GENERIC; uint32_t modulus_bits = 0; TEE_Attribute tee_attrs[1] = { }; uint32_t tee_count = 0; if (!proc_params || !*pub_head || !*priv_head) return PKCS11_CKR_TEMPLATE_INCONSISTENT; rc = get_attribute_ptr(*pub_head, PKCS11_CKA_MODULUS_BITS, &a_ptr, &a_size); if (rc != PKCS11_CKR_OK || a_size != sizeof(uint32_t)) return PKCS11_CKR_TEMPLATE_INCONSISTENT; TEE_MemMove(&modulus_bits, a_ptr, sizeof(uint32_t)); rc = get_attribute_ptr(*pub_head, PKCS11_CKA_PUBLIC_EXPONENT, &a_ptr, &a_size); if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) return rc; if (rc == PKCS11_CKR_OK && a_ptr) { TEE_InitRefAttribute(&tee_attrs[tee_count], TEE_ATTR_RSA_PUBLIC_EXPONENT, a_ptr, a_size); tee_count++; } if (remove_empty_attribute(priv_head, PKCS11_CKA_MODULUS) || remove_empty_attribute(priv_head, PKCS11_CKA_PUBLIC_EXPONENT) || remove_empty_attribute(priv_head, PKCS11_CKA_PRIVATE_EXPONENT) || remove_empty_attribute(priv_head, PKCS11_CKA_PRIME_1) || remove_empty_attribute(priv_head, PKCS11_CKA_PRIME_2) || remove_empty_attribute(priv_head, PKCS11_CKA_EXPONENT_1) || remove_empty_attribute(priv_head, PKCS11_CKA_EXPONENT_2) || remove_empty_attribute(priv_head, PKCS11_CKA_COEFFICIENT)) { EMSG("Unexpected attribute(s) found"); rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto out; } /* Create an RSA TEE key */ res = TEE_AllocateTransientObject(TEE_TYPE_RSA_KEYPAIR, modulus_bits, &tee_obj); if (res) { DMSG("TEE_AllocateTransientObject failed %#"PRIx32, res); rc = tee2pkcs_error(res); goto out; } res = TEE_RestrictObjectUsage1(tee_obj, TEE_USAGE_EXTRACTABLE); if (res) { DMSG("TEE_RestrictObjectUsage1 failed %#"PRIx32, res); rc = tee2pkcs_error(res); goto out; } res = TEE_GenerateKey(tee_obj, modulus_bits, tee_attrs, tee_count); if (res) { DMSG("TEE_GenerateKey failed %#"PRIx32, res); rc = tee2pkcs_error(res); goto out; } rc = tee2pkcs_rsa_attributes(pub_head, priv_head, tee_obj); out: if (tee_obj != TEE_HANDLE_NULL) TEE_CloseObject(tee_obj); return rc; } size_t rsa_get_input_max_byte_size(TEE_OperationHandle op) { TEE_OperationInfo info = { }; TEE_GetOperationInfo(op, &info); return info.maxKeySize / 8; } optee_os-4.3.0/ta/pkcs11/src/processing_symm.c000066400000000000000000000766561464416617300212550ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include "attributes.h" #include "object.h" #include "pkcs11_attributes.h" #include "pkcs11_helpers.h" #include "pkcs11_token.h" #include "processing.h" #include "serializer.h" struct input_data_ref { size_t size; void *data; }; bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id) { switch (proc_id) { /* Authentication */ case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_AES_CMAC_GENERAL: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: /* Ciphering */ case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_CTS: case PKCS11_CKM_AES_CTR: case PKCS11_CKM_AES_GCM: case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: return true; default: return false; } } static enum pkcs11_rc pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params) { static const struct { enum pkcs11_mechanism_id mech_id; uint32_t tee_id; } pkcs2tee_algo[] = { /* AES flavors */ { PKCS11_CKM_AES_ECB, TEE_ALG_AES_ECB_NOPAD }, { PKCS11_CKM_AES_CBC, TEE_ALG_AES_CBC_NOPAD }, { PKCS11_CKM_AES_ECB_ENCRYPT_DATA, TEE_ALG_AES_ECB_NOPAD }, { PKCS11_CKM_AES_CBC_ENCRYPT_DATA, TEE_ALG_AES_CBC_NOPAD }, { PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR }, { PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS }, { PKCS11_CKM_AES_GCM, TEE_ALG_AES_GCM }, { PKCS11_CKM_AES_CMAC, TEE_ALG_AES_CMAC }, { PKCS11_CKM_AES_CMAC_GENERAL, TEE_ALG_AES_CMAC }, /* HMAC flavors */ { PKCS11_CKM_MD5_HMAC, TEE_ALG_HMAC_MD5 }, { PKCS11_CKM_SHA_1_HMAC, TEE_ALG_HMAC_SHA1 }, { PKCS11_CKM_SHA224_HMAC, TEE_ALG_HMAC_SHA224 }, { PKCS11_CKM_SHA256_HMAC, TEE_ALG_HMAC_SHA256 }, { PKCS11_CKM_SHA384_HMAC, TEE_ALG_HMAC_SHA384 }, { PKCS11_CKM_SHA512_HMAC, TEE_ALG_HMAC_SHA512 }, { PKCS11_CKM_MD5_HMAC_GENERAL, TEE_ALG_HMAC_MD5 }, { PKCS11_CKM_SHA_1_HMAC_GENERAL, TEE_ALG_HMAC_SHA1 }, { PKCS11_CKM_SHA224_HMAC_GENERAL, TEE_ALG_HMAC_SHA224 }, { PKCS11_CKM_SHA256_HMAC_GENERAL, TEE_ALG_HMAC_SHA256 }, { PKCS11_CKM_SHA384_HMAC_GENERAL, TEE_ALG_HMAC_SHA384 }, { PKCS11_CKM_SHA512_HMAC_GENERAL, TEE_ALG_HMAC_SHA512 }, }; size_t n = 0; for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { if (proc_params->id == pkcs2tee_algo[n].mech_id) { *tee_id = pkcs2tee_algo[n].tee_id; return PKCS11_CKR_OK; } } return PKCS11_RV_NOT_IMPLEMENTED; } static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type, struct pkcs11_object *obj) { static const struct { enum pkcs11_key_type key_type; uint32_t tee_id; } pkcs2tee_key_type[] = { { PKCS11_CKK_AES, TEE_TYPE_AES }, { PKCS11_CKK_GENERIC_SECRET, TEE_TYPE_GENERIC_SECRET }, { PKCS11_CKK_MD5_HMAC, TEE_TYPE_HMAC_MD5 }, { PKCS11_CKK_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 }, { PKCS11_CKK_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 }, { PKCS11_CKK_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 }, { PKCS11_CKK_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 }, { PKCS11_CKK_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 }, }; size_t n = 0; enum pkcs11_key_type key_type = get_key_type(obj->attributes); assert(get_class(obj->attributes) == PKCS11_CKO_SECRET_KEY); for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) { if (pkcs2tee_key_type[n].key_type == key_type) { *tee_type = pkcs2tee_key_type[n].tee_id; return PKCS11_CKR_OK; } } return PKCS11_RV_NOT_FOUND; } static enum pkcs11_rc pkcsmech2tee_key_type(uint32_t *tee_type, enum pkcs11_mechanism_id mech_id) { static const struct { enum pkcs11_mechanism_id mech; uint32_t tee_id; } pkcs2tee_key_type[] = { { PKCS11_CKM_MD5_HMAC, TEE_TYPE_HMAC_MD5 }, { PKCS11_CKM_SHA_1_HMAC, TEE_TYPE_HMAC_SHA1 }, { PKCS11_CKM_SHA224_HMAC, TEE_TYPE_HMAC_SHA224 }, { PKCS11_CKM_SHA256_HMAC, TEE_TYPE_HMAC_SHA256 }, { PKCS11_CKM_SHA384_HMAC, TEE_TYPE_HMAC_SHA384 }, { PKCS11_CKM_SHA512_HMAC, TEE_TYPE_HMAC_SHA512 }, { PKCS11_CKM_MD5_HMAC_GENERAL, TEE_TYPE_HMAC_MD5 }, { PKCS11_CKM_SHA_1_HMAC_GENERAL, TEE_TYPE_HMAC_SHA1 }, { PKCS11_CKM_SHA224_HMAC_GENERAL, TEE_TYPE_HMAC_SHA224 }, { PKCS11_CKM_SHA256_HMAC_GENERAL, TEE_TYPE_HMAC_SHA256 }, { PKCS11_CKM_SHA384_HMAC_GENERAL, TEE_TYPE_HMAC_SHA384 }, { PKCS11_CKM_SHA512_HMAC_GENERAL, TEE_TYPE_HMAC_SHA512 }, }; size_t n = 0; for (n = 0; n < ARRAY_SIZE(pkcs2tee_key_type); n++) { if (pkcs2tee_key_type[n].mech == mech_id) { *tee_type = pkcs2tee_key_type[n].tee_id; return PKCS11_CKR_OK; } } return PKCS11_RV_NOT_FOUND; } static enum pkcs11_rc hmac_to_tee_hash(uint32_t *algo, enum pkcs11_mechanism_id mech_id) { static const struct { enum pkcs11_mechanism_id mech; uint32_t tee_id; } hmac_hash[] = { { PKCS11_CKM_MD5_HMAC, TEE_ALG_MD5 }, { PKCS11_CKM_SHA_1_HMAC, TEE_ALG_SHA1 }, { PKCS11_CKM_SHA224_HMAC, TEE_ALG_SHA224 }, { PKCS11_CKM_SHA256_HMAC, TEE_ALG_SHA256 }, { PKCS11_CKM_SHA384_HMAC, TEE_ALG_SHA384 }, { PKCS11_CKM_SHA512_HMAC, TEE_ALG_SHA512 }, { PKCS11_CKM_MD5_HMAC_GENERAL, TEE_ALG_MD5 }, { PKCS11_CKM_SHA_1_HMAC_GENERAL, TEE_ALG_SHA1 }, { PKCS11_CKM_SHA224_HMAC_GENERAL, TEE_ALG_SHA224 }, { PKCS11_CKM_SHA256_HMAC_GENERAL, TEE_ALG_SHA256 }, { PKCS11_CKM_SHA384_HMAC_GENERAL, TEE_ALG_SHA384 }, { PKCS11_CKM_SHA512_HMAC_GENERAL, TEE_ALG_SHA512 }, }; size_t n = 0; for (n = 0; n < ARRAY_SIZE(hmac_hash); n++) { if (hmac_hash[n].mech == mech_id) { *algo = hmac_hash[n].tee_id; return PKCS11_CKR_OK; } } return PKCS11_RV_NOT_FOUND; } static enum pkcs11_rc allocate_tee_operation(struct pkcs11_session *session, enum processing_func function, struct pkcs11_attribute_head *params, struct pkcs11_object *obj) { uint32_t size = (uint32_t)get_object_key_bit_size(obj); uint32_t key_size = size / 8; uint32_t algo = 0; uint32_t mode = 0; uint32_t max_key_size = 0; uint32_t min_key_size = 0; TEE_Result res = TEE_ERROR_GENERIC; assert(session->processing->tee_op_handle == TEE_HANDLE_NULL && session->processing->tee_op_handle2 == TEE_HANDLE_NULL); if (pkcs2tee_algorithm(&algo, params)) return PKCS11_CKR_FUNCTION_FAILED; /* Sign/Verify with AES or generic key relate to TEE MAC operation */ switch (params->id) { case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: mechanism_supported_key_sizes_bytes(params->id, &min_key_size, &max_key_size); if (key_size < min_key_size) return PKCS11_CKR_KEY_SIZE_RANGE; /* * If size of generic key is greater than the size * supported by TEE API, this is not considered an * error. When loading TEE key, we will hash the key * to generate the appropriate key for HMAC operation. * This key size will not be greater than the * max_key_size. So we can use max_key_size for * TEE_AllocateOperation(). */ if (key_size > max_key_size) size = max_key_size * 8; mode = TEE_MODE_MAC; break; case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_AES_CMAC_GENERAL: mode = TEE_MODE_MAC; break; default: pkcs2tee_mode(&mode, function); break; } res = TEE_AllocateOperation(&session->processing->tee_op_handle, algo, mode, size); if (res) EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32, algo, mode, size); if (res == TEE_ERROR_NOT_SUPPORTED) return PKCS11_CKR_MECHANISM_INVALID; if (res == TEE_SUCCESS || params->id == PKCS11_CKM_AES_GCM) { /* * Allocate a 2nd operation handler to save the operation state * on AES GCM one-shot processing that queries the output * buffer size. This is needed as we will need to reset and * re-init the TEE operation once we report the expected output * buffer size to client that we call again the AE processing * function. */ TEE_OperationHandle *hdl = &session->processing->tee_op_handle2; res = TEE_AllocateOperation(hdl, algo, mode, size); } return tee2pkcs_error(res); } static enum pkcs11_rc hash_secret_helper(enum pkcs11_mechanism_id mech_id, struct pkcs11_object *obj, TEE_Attribute *tee_attr, void **ctx, size_t *object_size_bits) { uint32_t algo = 0; void *hash_ptr = NULL; uint32_t hash_size = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; rc = hmac_to_tee_hash(&algo, mech_id); if (rc) return rc; hash_size = TEE_ALG_GET_DIGEST_SIZE(algo); hash_ptr = TEE_Malloc(hash_size, 0); if (!hash_ptr) return PKCS11_CKR_DEVICE_MEMORY; rc = pkcs2tee_load_hashed_attr(tee_attr, TEE_ATTR_SECRET_VALUE, obj, PKCS11_CKA_VALUE, algo, hash_ptr, &hash_size); if (rc) { EMSG("No secret/hash error"); TEE_Free(hash_ptr); return rc; } *ctx = hash_ptr; *object_size_bits = hash_size * 8; return PKCS11_CKR_OK; } static enum pkcs11_rc load_tee_key(struct pkcs11_session *session, struct pkcs11_object *obj, struct pkcs11_attribute_head *proc_params) { TEE_Attribute tee_attr = { }; size_t object_size = 0; uint32_t tee_key_type = 0; enum pkcs11_key_type key_type = 0; enum pkcs11_rc rc = PKCS11_CKR_OK; TEE_Result res = TEE_ERROR_GENERIC; uint32_t max_key_size = 0; uint32_t min_key_size = 0; if (obj->key_handle != TEE_HANDLE_NULL) { /* Key was already loaded and fits current need */ goto key_ready; } object_size = get_object_key_bit_size(obj); if (!object_size) return PKCS11_CKR_GENERAL_ERROR; switch (proc_params->id) { case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: key_type = get_key_type(obj->attributes); /* * If Object Key type is PKCS11_CKK_GENERIC_SECRET, * determine the tee_key_type using the * mechanism instead of object key_type. */ if (key_type == PKCS11_CKK_GENERIC_SECRET) rc = pkcsmech2tee_key_type(&tee_key_type, proc_params->id); else rc = pkcs2tee_key_type(&tee_key_type, obj); if (rc) return rc; mechanism_supported_key_sizes_bytes(proc_params->id, &min_key_size, &max_key_size); if ((object_size / 8) > max_key_size) { rc = hash_secret_helper(proc_params->id, obj, &tee_attr, &session->processing->extra_ctx, &object_size); if (rc) return rc; } else { if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE, obj, PKCS11_CKA_VALUE)) { EMSG("No secret found"); return PKCS11_CKR_FUNCTION_FAILED; } } break; default: rc = pkcs2tee_key_type(&tee_key_type, obj); if (rc) return rc; if (!pkcs2tee_load_attr(&tee_attr, TEE_ATTR_SECRET_VALUE, obj, PKCS11_CKA_VALUE)) { EMSG("No secret found"); return PKCS11_CKR_FUNCTION_FAILED; } break; } res = TEE_AllocateTransientObject(tee_key_type, object_size, &obj->key_handle); if (res) { DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); return tee2pkcs_error(res); } res = TEE_PopulateTransientObject(obj->key_handle, &tee_attr, 1); if (res) { DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res); goto error; } key_ready: res = TEE_SetOperationKey(session->processing->tee_op_handle, obj->key_handle); if (res) { DMSG("TEE_SetOperationKey failed, %#"PRIx32, res); goto error; } return PKCS11_CKR_OK; error: TEE_FreeTransientObject(obj->key_handle); obj->key_handle = TEE_HANDLE_NULL; return tee2pkcs_error(res); } static enum pkcs11_rc tee_init_derive_symm(struct active_processing *processing, struct pkcs11_attribute_head *proc_params) { struct serialargs args = { }; enum pkcs11_rc rc = PKCS11_CKR_OK; struct input_data_ref *param = NULL; void *iv = NULL; if (!proc_params) return PKCS11_CKR_ARGUMENTS_BAD; param = TEE_Malloc(sizeof(struct input_data_ref), TEE_MALLOC_FILL_ZERO); if (!param) return PKCS11_CKR_DEVICE_MEMORY; serialargs_init(&args, proc_params->data, proc_params->size); switch (proc_params->id) { case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: rc = serialargs_get_ptr(&args, &iv, 16); if (rc) goto err; break; default: break; } rc = serialargs_get(&args, ¶m->size, sizeof(uint32_t)); if (rc) goto err; rc = serialargs_get_ptr(&args, ¶m->data, param->size); if (rc) goto err; if (serialargs_remaining_bytes(&args)) { rc = PKCS11_CKR_ARGUMENTS_BAD; goto err; } processing->extra_ctx = param; switch (proc_params->id) { case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: if (param->size % TEE_AES_BLOCK_SIZE) { rc = PKCS11_CKR_DATA_LEN_RANGE; goto err; } TEE_CipherInit(processing->tee_op_handle, NULL, 0); break; case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: if (param->size % TEE_AES_BLOCK_SIZE) { rc = PKCS11_CKR_DATA_LEN_RANGE; goto err; } TEE_CipherInit(processing->tee_op_handle, iv, 16); break; default: TEE_Panic(proc_params->id); break; } return PKCS11_CKR_OK; err: processing->extra_ctx = NULL; TEE_Free(param); return rc; } static enum pkcs11_rc input_hmac_len_is_valid(struct pkcs11_attribute_head *proc_params, uint32_t hmac_len) { uint32_t sign_sz = 0; switch (proc_params->id) { case PKCS11_CKM_MD5_HMAC_GENERAL: sign_sz = TEE_MD5_HASH_SIZE; break; case PKCS11_CKM_SHA_1_HMAC_GENERAL: sign_sz = TEE_SHA1_HASH_SIZE; break; case PKCS11_CKM_SHA224_HMAC_GENERAL: sign_sz = TEE_SHA224_HASH_SIZE; break; case PKCS11_CKM_SHA256_HMAC_GENERAL: sign_sz = TEE_SHA256_HASH_SIZE; break; case PKCS11_CKM_SHA384_HMAC_GENERAL: sign_sz = TEE_SHA384_HASH_SIZE; break; case PKCS11_CKM_SHA512_HMAC_GENERAL: sign_sz = TEE_SHA512_HASH_SIZE; break; case PKCS11_CKM_AES_CMAC_GENERAL: sign_sz = TEE_AES_BLOCK_SIZE; break; default: return PKCS11_CKR_MECHANISM_INVALID; } if (!hmac_len || hmac_len > sign_sz) return PKCS11_CKR_SIGNATURE_LEN_RANGE; return PKCS11_CKR_OK; } static enum pkcs11_rc init_tee_operation(struct pkcs11_session *session, struct pkcs11_attribute_head *proc_params) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; uint32_t *pkcs11_data = NULL; switch (proc_params->id) { case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: if (proc_params->size) return PKCS11_CKR_MECHANISM_PARAM_INVALID; TEE_MACInit(session->processing->tee_op_handle, NULL, 0); rc = PKCS11_CKR_OK; break; case PKCS11_CKM_AES_CMAC_GENERAL: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: if (proc_params->size != sizeof(uint32_t)) return PKCS11_CKR_MECHANISM_PARAM_INVALID; pkcs11_data = TEE_Malloc(sizeof(uint32_t), TEE_MALLOC_FILL_ZERO); if (!pkcs11_data) return PKCS11_CKR_DEVICE_MEMORY; TEE_MemMove(pkcs11_data, proc_params->data, sizeof(uint32_t)); rc = input_hmac_len_is_valid(proc_params, *pkcs11_data); if (rc) { TEE_Free(pkcs11_data); return rc; } session->processing->extra_ctx = (void *)pkcs11_data; TEE_MACInit(session->processing->tee_op_handle, NULL, 0); rc = PKCS11_CKR_OK; break; case PKCS11_CKM_AES_ECB: if (proc_params->size) return PKCS11_CKR_MECHANISM_PARAM_INVALID; TEE_CipherInit(session->processing->tee_op_handle, NULL, 0); rc = PKCS11_CKR_OK; break; case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_CTS: if (proc_params->size != 16) return PKCS11_CKR_MECHANISM_PARAM_INVALID; TEE_CipherInit(session->processing->tee_op_handle, proc_params->data, 16); rc = PKCS11_CKR_OK; break; case PKCS11_CKM_AES_CTR: rc = tee_init_ctr_operation(session->processing, proc_params->data, proc_params->size); break; case PKCS11_CKM_AES_GCM: rc = tee_init_gcm_operation(session, proc_params->data, proc_params->size); break; case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: rc = tee_init_derive_symm(session->processing, proc_params); break; default: TEE_Panic(proc_params->id); break; } return rc; } enum pkcs11_rc init_symm_operation(struct pkcs11_session *session, enum processing_func function, struct pkcs11_attribute_head *proc_params, struct pkcs11_object *obj) { enum pkcs11_rc rc = PKCS11_CKR_OK; assert(processing_is_tee_symm(proc_params->id)); rc = allocate_tee_operation(session, function, proc_params, obj); if (rc) return rc; rc = load_tee_key(session, obj, proc_params); if (rc) return rc; rc = init_tee_operation(session, proc_params); if (!rc) session->processing->mecha_type = proc_params->id; return rc; } /* Validate input buffer size as per PKCS#11 constraints */ static enum pkcs11_rc input_data_size_is_valid(struct active_processing *proc, enum processing_func function, size_t in_size) { switch (proc->mecha_type) { case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: if (function == PKCS11_FUNCTION_ENCRYPT && in_size % TEE_AES_BLOCK_SIZE) return PKCS11_CKR_DATA_LEN_RANGE; if (function == PKCS11_FUNCTION_DECRYPT && in_size % TEE_AES_BLOCK_SIZE) return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; break; case PKCS11_CKM_AES_CTS: if (function == PKCS11_FUNCTION_ENCRYPT && in_size < TEE_AES_BLOCK_SIZE) return PKCS11_CKR_DATA_LEN_RANGE; if (function == PKCS11_FUNCTION_DECRYPT && in_size < TEE_AES_BLOCK_SIZE) return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; break; default: break; } return PKCS11_CKR_OK; } /* Validate input buffer size as per PKCS#11 constraints */ static enum pkcs11_rc input_sign_size_is_valid(struct active_processing *proc, size_t in_size) { size_t sign_sz = 0; switch (proc->mecha_type) { case PKCS11_CKM_MD5_HMAC: sign_sz = TEE_MD5_HASH_SIZE; break; case PKCS11_CKM_SHA_1_HMAC: sign_sz = TEE_SHA1_HASH_SIZE; break; case PKCS11_CKM_SHA224_HMAC: sign_sz = TEE_SHA224_HASH_SIZE; break; case PKCS11_CKM_SHA256_HMAC: sign_sz = TEE_SHA256_HASH_SIZE; break; case PKCS11_CKM_SHA384_HMAC: sign_sz = TEE_SHA384_HASH_SIZE; break; case PKCS11_CKM_SHA512_HMAC: sign_sz = TEE_SHA512_HASH_SIZE; break; case PKCS11_CKM_AES_CMAC: sign_sz = TEE_AES_BLOCK_SIZE; break; default: return PKCS11_CKR_GENERAL_ERROR; } if (in_size != sign_sz) return PKCS11_CKR_SIGNATURE_LEN_RANGE; return PKCS11_CKR_OK; } /* * step_sym_cipher - processing symmetric (and related) cipher operation step * * @session - current session * @function - processing function (encrypt, decrypt, sign, ...) * @step - step ID in the processing (oneshot, update, final) * @ptype - invocation parameter types * @params - invocation parameter references */ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session, enum processing_func function, enum processing_step step, uint32_t ptypes, TEE_Param *params) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; void *in_buf = NULL; size_t in_size = 0; void *out_buf = NULL; size_t out_size = 0; void *in2_buf = NULL; uint32_t in2_size = 0; bool output_data = false; struct active_processing *proc = session->processing; uint32_t hmac_len = 0; uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 }; size_t computed_mac_size = TEE_MAX_HASH_SIZE; size_t ae_out_size = 0; if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { in_buf = params[1].memref.buffer; in_size = params[1].memref.size; if (in_size && !in_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) { in2_buf = params[2].memref.buffer; in2_size = params[2].memref.size; if (in2_size && !in2_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { out_buf = params[2].memref.buffer; out_size = params[2].memref.size; ae_out_size = out_size; if (out_size && !out_buf) return PKCS11_CKR_ARGUMENTS_BAD; } if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) return PKCS11_CKR_ARGUMENTS_BAD; switch (step) { case PKCS11_FUNC_STEP_ONESHOT: case PKCS11_FUNC_STEP_UPDATE: case PKCS11_FUNC_STEP_FINAL: break; default: return PKCS11_CKR_GENERAL_ERROR; } if (step != PKCS11_FUNC_STEP_FINAL) { rc = input_data_size_is_valid(proc, function, in_size); if (rc) return rc; } /* * Feed active operation with data */ switch (proc->mecha_type) { case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_AES_CMAC_GENERAL: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: if (step == PKCS11_FUNC_STEP_FINAL || step == PKCS11_FUNC_STEP_ONESHOT) break; if (!in_buf) { DMSG("No input data"); return PKCS11_CKR_ARGUMENTS_BAD; } switch (function) { case PKCS11_FUNCTION_SIGN: case PKCS11_FUNCTION_VERIFY: TEE_MACUpdate(proc->tee_op_handle, in_buf, in_size); rc = PKCS11_CKR_OK; break; default: TEE_Panic(function); break; } break; case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_CTS: case PKCS11_CKM_AES_CTR: if (step == PKCS11_FUNC_STEP_FINAL || step == PKCS11_FUNC_STEP_ONESHOT) break; if (!in_buf) { EMSG("No input data"); return PKCS11_CKR_ARGUMENTS_BAD; } switch (function) { case PKCS11_FUNCTION_ENCRYPT: case PKCS11_FUNCTION_DECRYPT: res = TEE_CipherUpdate(proc->tee_op_handle, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); break; default: TEE_Panic(function); break; } break; case PKCS11_CKM_AES_GCM: if (step == PKCS11_FUNC_STEP_FINAL) break; switch (function) { case PKCS11_FUNCTION_ENCRYPT: res = TEE_AEUpdate(proc->tee_op_handle, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); if (rc && rc != PKCS11_CKR_BUFFER_TOO_SMALL) return rc; if (step == PKCS11_FUNC_STEP_ONESHOT) { if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) { /* Return output data size incl. tag*/ out_size += 16; goto out; } out_buf = (char *)out_buf + out_size; /* Remaining space for the tag data */ ae_out_size -= out_size; } break; case PKCS11_FUNCTION_DECRYPT: rc = tee_ae_decrypt_update(session, in_buf, in_size); assert(rc != PKCS11_CKR_BUFFER_TOO_SMALL); if (rc) return rc; /* Do not output decrypted data until tag is verified */ out_size = 0; output_data = true; break; default: TEE_Panic(function); break; } break; default: TEE_Panic(proc->mecha_type); break; } if (step == PKCS11_FUNC_STEP_UPDATE) goto out; /* * Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation */ switch (proc->mecha_type) { case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA512_HMAC: switch (function) { case PKCS11_FUNCTION_SIGN: res = TEE_MACComputeFinal(proc->tee_op_handle, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); break; case PKCS11_FUNCTION_VERIFY: rc = input_sign_size_is_valid(proc, in2_size); if (rc) return rc; res = TEE_MACCompareFinal(proc->tee_op_handle, in_buf, in_size, in2_buf, in2_size); rc = tee2pkcs_error(res); break; default: TEE_Panic(function); break; } break; case PKCS11_CKM_AES_CMAC_GENERAL: case PKCS11_CKM_MD5_HMAC_GENERAL: case PKCS11_CKM_SHA_1_HMAC_GENERAL: case PKCS11_CKM_SHA224_HMAC_GENERAL: case PKCS11_CKM_SHA256_HMAC_GENERAL: case PKCS11_CKM_SHA384_HMAC_GENERAL: case PKCS11_CKM_SHA512_HMAC_GENERAL: assert(proc->extra_ctx); hmac_len = *(uint32_t *)proc->extra_ctx; switch (function) { case PKCS11_FUNCTION_SIGN: if (out_size < hmac_len) { /* inform client of required size */ out_size = hmac_len; output_data = true; rc = PKCS11_CKR_BUFFER_TOO_SMALL; goto out; } res = TEE_MACComputeFinal(proc->tee_op_handle, in_buf, in_size, computed_mac, &computed_mac_size); if (res == TEE_SUCCESS) { /* truncate to hmac_len */ TEE_MemMove(out_buf, computed_mac, hmac_len); output_data = true; } /* inform client of required size */ out_size = hmac_len; rc = tee2pkcs_error(res); break; case PKCS11_FUNCTION_VERIFY: /* must compute full MAC before comparing partial */ res = TEE_MACComputeFinal(proc->tee_op_handle, in_buf, in_size, computed_mac, &computed_mac_size); if (!in2_size || in2_size > computed_mac_size) { EMSG("Invalid signature size: %"PRIu32, in2_size); return PKCS11_CKR_SIGNATURE_LEN_RANGE; } if (res == TEE_SUCCESS) { /* * Only the first in2_size bytes of the * signature to be verified is passed in from * caller */ if (TEE_MemCompare(in2_buf, computed_mac, in2_size)) { res = TEE_ERROR_MAC_INVALID; } } rc = tee2pkcs_error(res); break; default: TEE_Panic(function); break; } break; case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_CTS: case PKCS11_CKM_AES_CTR: if (step == PKCS11_FUNC_STEP_ONESHOT && !in_buf) { EMSG("No input data"); return PKCS11_CKR_ARGUMENTS_BAD; } switch (function) { case PKCS11_FUNCTION_ENCRYPT: case PKCS11_FUNCTION_DECRYPT: res = TEE_CipherDoFinal(proc->tee_op_handle, in_buf, in_size, out_buf, &out_size); output_data = true; rc = tee2pkcs_error(res); break; default: TEE_Panic(function); break; } break; case PKCS11_CKM_AES_GCM: switch (function) { case PKCS11_FUNCTION_ENCRYPT: rc = tee_ae_encrypt_final(session, out_buf, &ae_out_size); output_data = true; if (step == PKCS11_FUNC_STEP_ONESHOT) out_size += ae_out_size; else out_size = ae_out_size; break; case PKCS11_FUNCTION_DECRYPT: /* Now we're ready to reveal data */ out_size = ae_out_size; rc = tee_ae_decrypt_final(session, out_buf, &out_size); output_data = true; break; default: TEE_Panic(function); break; } if (step == PKCS11_FUNC_STEP_ONESHOT && rc == PKCS11_CKR_BUFFER_TOO_SMALL) { enum pkcs11_rc rc2 = PKCS11_CKR_OK; /* * Change operation state to its initial state * as client will likely request again the * one-shot processing but possibly with * different input data. */ rc2 = tee_ae_reinit_gcm_operation(session); if (rc2) return rc2; } break; default: TEE_Panic(proc->mecha_type); break; } out: if (output_data && (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) { switch (TEE_PARAM_TYPE_GET(ptypes, 2)) { case TEE_PARAM_TYPE_MEMREF_OUTPUT: case TEE_PARAM_TYPE_MEMREF_INOUT: params[2].memref.size = out_size; break; default: rc = PKCS11_CKR_ARGUMENTS_BAD; break; } } return rc; } enum pkcs11_rc derive_key_by_symm_enc(struct pkcs11_session *session, void **out_buf, uint32_t *out_size) { enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; TEE_Result res = TEE_ERROR_GENERIC; struct active_processing *proc = session->processing; struct input_data_ref *input = proc->extra_ctx; void *in_buf = NULL; void *dest_buf = NULL; uint32_t in_size = 0; size_t tmp_sz = 0; switch (proc->mecha_type) { case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: if (!proc->extra_ctx) return PKCS11_CKR_ARGUMENTS_BAD; in_buf = input->data; in_size = input->size; *out_size = in_size; dest_buf = TEE_Malloc(*out_size, 0); if (!dest_buf) return PKCS11_CKR_DEVICE_MEMORY; tmp_sz = *out_size; res = TEE_CipherDoFinal(proc->tee_op_handle, in_buf, in_size, dest_buf, &tmp_sz); *out_size = tmp_sz; rc = tee2pkcs_error(res); if (rc) { TEE_Free(dest_buf); return rc; } *out_buf = dest_buf; break; default: return PKCS11_CKR_MECHANISM_INVALID; } return rc; } enum pkcs11_rc wrap_data_by_symm_enc(struct pkcs11_session *session, void *data, uint32_t data_sz, void *out_buf, uint32_t *out_sz) { TEE_Result res = TEE_ERROR_GENERIC; struct active_processing *proc = session->processing; void *in_buf = NULL; uint32_t align = 0; uint32_t in_sz = data_sz; size_t tmp_sz = *out_sz; uint8_t *tmp_buf = out_buf; switch (proc->mecha_type) { case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: align = data_sz % TEE_AES_BLOCK_SIZE; if (align) in_sz = data_sz + (TEE_AES_BLOCK_SIZE - align); if (*out_sz < in_sz) { *out_sz = in_sz; return PKCS11_CKR_BUFFER_TOO_SMALL; } if (align) { if (data_sz > TEE_AES_BLOCK_SIZE) { in_sz = data_sz - align; res = TEE_CipherUpdate(proc->tee_op_handle, data, in_sz, tmp_buf, &tmp_sz); if (res) { assert(res != TEE_ERROR_SHORT_BUFFER); return tee2pkcs_error(res); } tmp_buf += tmp_sz; tmp_sz = *out_sz - tmp_sz; } else { in_sz = 0; } in_buf = TEE_Malloc(TEE_AES_BLOCK_SIZE, TEE_MALLOC_FILL_ZERO); if (!in_buf) return PKCS11_CKR_DEVICE_MEMORY; TEE_MemMove(in_buf, (uint8_t *)data + in_sz, align); in_sz = TEE_AES_BLOCK_SIZE; } else { in_buf = data; in_sz = data_sz; } res = TEE_CipherDoFinal(proc->tee_op_handle, in_buf, in_sz, tmp_buf, &tmp_sz); if (res == TEE_SUCCESS || res == TEE_ERROR_SHORT_BUFFER) { *out_sz = tmp_sz; if (align) *out_sz += tmp_buf - (uint8_t *)out_buf; } if (align) TEE_Free(in_buf); return tee2pkcs_error(res); default: return PKCS11_CKR_MECHANISM_INVALID; } return PKCS11_CKR_GENERAL_ERROR; } enum pkcs11_rc unwrap_key_by_symm(struct pkcs11_session *session, void *data, uint32_t data_sz, void **out_buf, uint32_t *out_sz) { TEE_Result res = TEE_ERROR_GENERIC; struct active_processing *proc = session->processing; size_t tmp_sz = 0; if (input_data_size_is_valid(proc, PKCS11_FUNCTION_DECRYPT, data_sz)) return PKCS11_CKR_WRAPPED_KEY_LEN_RANGE; switch (proc->mecha_type) { case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: *out_sz = 0; res = TEE_CipherDoFinal(proc->tee_op_handle, data, data_sz, NULL, &tmp_sz); *out_sz = tmp_sz; if (res != TEE_ERROR_SHORT_BUFFER) { DMSG("TEE_CipherDoFinal() issue: %#"PRIx32, res); return PKCS11_CKR_GENERAL_ERROR; } *out_buf = TEE_Malloc(*out_sz, TEE_MALLOC_FILL_ZERO); if (!*out_buf) return PKCS11_CKR_DEVICE_MEMORY; res = TEE_CipherDoFinal(proc->tee_op_handle, data, data_sz, *out_buf, &tmp_sz); *out_sz = tmp_sz; if (tee2pkcs_error(res)) { TEE_Free(*out_buf); *out_buf = NULL; return PKCS11_CKR_WRAPPED_KEY_INVALID; } break; default: return PKCS11_CKR_MECHANISM_INVALID; } return PKCS11_CKR_OK; } optee_os-4.3.0/ta/pkcs11/src/sanitize_object.c000066400000000000000000000245541464416617300211760ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #include "attributes.h" #include "pkcs11_helpers.h" #include "sanitize_object.h" #include "serializer.h" #include "token_capabilities.h" /* * Functions to generate a serialized object. * References are pointers to struct serializer. */ bool sanitize_consistent_class_and_type(struct obj_attrs *attrs) { switch (get_class(attrs)) { case PKCS11_CKO_DATA: case PKCS11_CKO_CERTIFICATE: return true; case PKCS11_CKO_SECRET_KEY: return key_type_is_symm_key(get_key_type(attrs)); case PKCS11_CKO_MECHANISM: return mechanism_is_valid(get_mechanism_type(attrs)); case PKCS11_CKO_PUBLIC_KEY: case PKCS11_CKO_PRIVATE_KEY: return key_type_is_asymm_key(get_key_type(attrs)); case PKCS11_CKO_OTP_KEY: case PKCS11_CKO_DOMAIN_PARAMETERS: case PKCS11_CKO_HW_FEATURE: default: return false; } return false; } static enum pkcs11_rc read_attr_advance(void *buf, size_t blen, size_t *pos, struct pkcs11_attribute_head *attr, void **data) { uint8_t *b = buf; size_t data_pos = 0; size_t next_pos = 0; if (ADD_OVERFLOW(*pos, sizeof(*attr), &data_pos) || data_pos > blen) return PKCS11_CKR_FUNCTION_FAILED; TEE_MemMove(attr, b + *pos, sizeof(*attr)); if (ADD_OVERFLOW(data_pos, attr->size, &next_pos) || next_pos > blen) return PKCS11_CKR_FUNCTION_FAILED; *data = b + data_pos; *pos = next_pos; return PKCS11_CKR_OK; } /* Sanitize class/type in a client attribute list */ static enum pkcs11_rc sanitize_class_and_type(struct obj_attrs **dst, void *src, size_t src_size, uint32_t class_hint, uint32_t type_hint) { uint32_t class_found = PKCS11_CKO_UNDEFINED_ID; size_t pos = sizeof(struct pkcs11_object_head); struct pkcs11_attribute_head cli_ref = { }; uint32_t type_found = PKCS11_UNDEFINED_ID; enum pkcs11_rc rc = PKCS11_CKR_OK; void *data = NULL; while (pos != src_size) { rc = read_attr_advance(src, src_size, &pos, &cli_ref, &data); if (rc) goto err; if (cli_ref.id == PKCS11_CKA_CLASS) { uint32_t class = 0; if (cli_ref.size != sizeof(class)) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto err; } TEE_MemMove(&class, data, sizeof(class)); if (class_found != PKCS11_CKO_UNDEFINED_ID && class_found != class) { EMSG("Conflicting class value"); rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto err; } class_found = class; continue; } /* The attribute is a type-in-class */ if (pkcs11_attr_is_type(cli_ref.id)) { uint32_t type = 0; if (cli_ref.size != sizeof(type)) { rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto err; } TEE_MemMove(&type, data, sizeof(type)); if (type_found != PKCS11_CKK_UNDEFINED_ID && type_found != type) { EMSG("Conflicting type-in-class value"); rc = PKCS11_CKR_TEMPLATE_INCONSISTENT; goto err; } type_found = type; } } if (class_found != PKCS11_CKO_UNDEFINED_ID) { rc = add_attribute(dst, PKCS11_CKA_CLASS, &class_found, sizeof(class_found)); if (rc) return rc; } else { if (class_hint != PKCS11_CKO_UNDEFINED_ID) { rc = add_attribute(dst, PKCS11_CKA_CLASS, &class_hint, sizeof(class_hint)); if (rc) return rc; } } if (type_found != PKCS11_UNDEFINED_ID) { rc = add_attribute(dst, PKCS11_CKA_KEY_TYPE, &type_found, sizeof(type_found)); if (rc) return rc; } else { if (type_hint != PKCS11_UNDEFINED_ID) { rc = add_attribute(dst, PKCS11_CKA_KEY_TYPE, &type_hint, sizeof(type_hint)); if (rc) return rc; } } return PKCS11_CKR_OK; err: trace_attributes_from_api_head("bad-template", src, src_size); return rc; } static enum pkcs11_rc sanitize_boolprops(struct obj_attrs **dst, void *src, size_t src_size) { bitstr_t bit_decl(seen_attrs, PKCS11_BOOLPROPS_MAX_COUNT) = { 0 }; bitstr_t bit_decl(boolprops, PKCS11_BOOLPROPS_MAX_COUNT) = { 0 }; size_t pos = sizeof(struct pkcs11_object_head); struct pkcs11_attribute_head cli_ref = { }; enum pkcs11_rc rc = PKCS11_CKR_OK; bool value = false; void *data = NULL; int idx = 0; /* * We're keeping track of seen boolean attributes in the bitstring * seen_attrs. The bitstring boolprops holds the recorded value * once seen_attrs has been updated. */ while (pos != src_size) { rc = read_attr_advance(src, src_size, &pos, &cli_ref, &data); if (rc) return rc; idx = pkcs11_attr2boolprop_shift(cli_ref.id); if (idx < 0) continue; /* skipping non-boolean attributes */ if (idx >= PKCS11_BOOLPROPS_MAX_COUNT || cli_ref.size != sizeof(uint8_t)) return PKCS11_CKR_FUNCTION_FAILED; value = *(uint8_t *)data; /* * If this attribute has already been seen, check that it * still holds the same value as last time. */ if (bit_test(seen_attrs, idx) && value != (bool)bit_test(boolprops, idx)) return PKCS11_CKR_TEMPLATE_INCONSISTENT; if (value) bit_set(boolprops, idx); if (!bit_test(seen_attrs, idx)) { uint8_t pkcs11_bool = value; rc = add_attribute(dst, cli_ref.id, &pkcs11_bool, sizeof(pkcs11_bool)); if (rc) return rc; } bit_set(seen_attrs, idx); } return PKCS11_CKR_OK; } static uint32_t sanitize_indirect_attr(struct obj_attrs **dst, struct pkcs11_attribute_head *cli_ref, char *data) { struct obj_attrs *obj2 = NULL; enum pkcs11_rc rc = PKCS11_CKR_OK; assert(pkcs11_attr_has_indirect_attributes(cli_ref->id)); /* Build a new serial object while sanitizing the attributes list */ rc = sanitize_client_object(&obj2, data, cli_ref->size, PKCS11_CKO_UNDEFINED_ID, PKCS11_UNDEFINED_ID); if (rc) goto out; rc = add_attribute(dst, cli_ref->id, obj2, sizeof(*obj2) + obj2->attrs_size); out: TEE_Free(obj2); return rc; } enum pkcs11_rc sanitize_client_object(struct obj_attrs **dst, void *src, size_t size, uint32_t class_hint, uint32_t type_hint) { struct pkcs11_attribute_head cli_ref = { }; struct pkcs11_object_head head = { }; enum pkcs11_rc rc = PKCS11_CKR_OK; size_t pos = sizeof(head); size_t sz_from_hdr = 0; void *data = NULL; if (size < sizeof(head)) return PKCS11_CKR_ARGUMENTS_BAD; TEE_MemMove(&head, src, sizeof(head)); if (ADD_OVERFLOW(sizeof(head), head.attrs_size, &sz_from_hdr) || size < sz_from_hdr) return PKCS11_CKR_ARGUMENTS_BAD; rc = init_attributes_head(dst); if (rc) return rc; rc = sanitize_class_and_type(dst, src, sz_from_hdr, class_hint, type_hint); if (rc) return rc; rc = sanitize_boolprops(dst, src, sz_from_hdr); if (rc) return rc; while (pos != sz_from_hdr) { rc = read_attr_advance(src, sz_from_hdr, &pos, &cli_ref, &data); if (rc) return rc; if (cli_ref.id == PKCS11_CKA_CLASS || pkcs11_attr_is_type(cli_ref.id) || pkcs11_attr_is_boolean(cli_ref.id)) continue; if (pkcs11_attr_has_indirect_attributes(cli_ref.id)) { rc = sanitize_indirect_attr(dst, &cli_ref, data); if (rc) return rc; continue; } if (!valid_pkcs11_attribute_id(cli_ref.id, cli_ref.size)) { EMSG("Invalid attribute id %#"PRIx32, cli_ref.id); return PKCS11_CKR_TEMPLATE_INCONSISTENT; } rc = add_attribute(dst, cli_ref.id, data, cli_ref.size); if (rc) return rc; } return rc; } /* * Debug: dump object attribute array to output trace */ static void __trace_attributes(char *prefix, void *src, void *end) { size_t next = 0; char *prefix2 = NULL; size_t prefix_len = strlen(prefix); char *cur = src; /* append 4 spaces to the prefix plus terminal '\0' */ prefix2 = TEE_Malloc(prefix_len + 1 + 4, TEE_MALLOC_FILL_ZERO); if (!prefix2) return; TEE_MemMove(prefix2, prefix, prefix_len + 1); TEE_MemFill(prefix2 + prefix_len, ' ', 4); *(prefix2 + prefix_len + 4) = '\0'; for (; cur < (char *)end; cur += next) { struct pkcs11_attribute_head pkcs11_ref; uint8_t data[4] = { 0 }; uint32_t data_u32 = 0; char *start = NULL; TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref)); TEE_MemMove(&data[0], cur + sizeof(pkcs11_ref), MIN(pkcs11_ref.size, sizeof(data))); TEE_MemMove(&data_u32, cur + sizeof(pkcs11_ref), sizeof(data_u32)); next = sizeof(pkcs11_ref) + pkcs11_ref.size; DMSG_RAW("%s Attr %s / %s (%#04"PRIx32" %"PRIu32"-byte)", prefix, id2str_attr(pkcs11_ref.id), id2str_attr_value(pkcs11_ref.id, pkcs11_ref.size, cur + sizeof(pkcs11_ref)), pkcs11_ref.id, pkcs11_ref.size); switch (pkcs11_ref.size) { case 0: break; case 1: DMSG_RAW("%s Attr byte value: %02x", prefix, data[0]); break; case 2: DMSG_RAW("%s Attr byte value: %02x %02x", prefix, data[0], data[1]); break; case 3: DMSG_RAW("%s Attr byte value: %02x %02x %02x", prefix, data[0], data[1], data[2]); break; case 4: DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x", prefix, data[0], data[1], data[2], data[3]); break; default: DMSG_RAW("%s Attr byte value: %02x %02x %02x %02x ...", prefix, data[0], data[1], data[2], data[3]); break; } switch (pkcs11_ref.id) { case PKCS11_CKA_WRAP_TEMPLATE: case PKCS11_CKA_UNWRAP_TEMPLATE: case PKCS11_CKA_DERIVE_TEMPLATE: start = cur + sizeof(pkcs11_ref); trace_attributes_from_api_head(prefix2, start, (char *)end - start); break; default: break; } } /* Sanity */ if (cur != (char *)end) EMSG("Warning: unexpected alignment issue"); TEE_Free(prefix2); } void trace_attributes_from_api_head(const char *prefix, void *ref, size_t size) { struct pkcs11_object_head head = { }; char *pre = NULL; size_t offset = 0; TEE_MemMove(&head, ref, sizeof(head)); if (size > sizeof(head) + head.attrs_size) { EMSG("template overflows client buffer (%zu/%zu)", size, sizeof(head) + head.attrs_size); return; } pre = TEE_Malloc(prefix ? strlen(prefix) + 2 : 2, TEE_MALLOC_FILL_ZERO); if (!pre) { EMSG("%s: out of memory", prefix); return; } if (prefix) TEE_MemMove(pre, prefix, strlen(prefix)); DMSG_RAW("%s,--- (serial object) Attributes list --------", pre); DMSG_RAW("%s| %"PRIu32" item(s) - %"PRIu32" bytes", pre, head.attrs_count, head.attrs_size); offset = sizeof(head); pre[prefix ? strlen(prefix) : 0] = '|'; __trace_attributes(pre, (char *)ref + offset, (char *)ref + offset + head.attrs_size); DMSG_RAW("%s`-----------------------", prefix ? prefix : ""); TEE_Free(pre); } optee_os-4.3.0/ta/pkcs11/src/sanitize_object.h000066400000000000000000000032261464416617300211740ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_SANITIZE_OBJECT_H #define PKCS11_TA_SANITIZE_OBJECT_H #include "serializer.h" /* * sanitize_consistent_class_and_type - Check object type matches object class * * @attrs - object attributes * Return true if class/type matches, else return false */ bool sanitize_consistent_class_and_type(struct obj_attrs *attrs); /** * sanitize_client_object - Setup a serializer from a serialized object * * @dst - output structure tracking the generated serial object * @head - pointer to the formatted serialized object (its head) * @size - byte size of the serialized binary blob * @class_hint - Hint for class to be added to template if not presnet * in serialized object. * @type_hint - Hint for type to be added to template if not presnet * in serialized object. * * This function copies an attribute list from a client API attribute head * into a PKCS11 TA internal attribute structure. It generates a serialized * attribute list with a consistent format and identified attribute IDs. * * @head points to a blob starting with a pkcs11 attribute header. * @head may point to an unaligned address. * This function allocates, fills and returns a serialized attribute list * into a serializer container. */ enum pkcs11_rc sanitize_client_object(struct obj_attrs **dst, void *head, size_t size, uint32_t class_hint, uint32_t type_hint); /* Debug: dump attribute content as debug traces */ void trace_attributes_from_api_head(const char *prefix, void *ref, size_t size); #endif /*PKCS11_TA_SANITIZE_OBJECT_H*/ optee_os-4.3.0/ta/pkcs11/src/serializer.c000066400000000000000000000077701464416617300201740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include #include "pkcs11_token.h" #include "serializer.h" /* * Util routines for serializes unformatted arguments in a client memref */ void serialargs_init(struct serialargs *args, void *in, size_t size) { args->start = in; args->next = in; args->size = size; } enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t size) { enum pkcs11_rc rc = PKCS11_CKR_OK; void *src = NULL; rc = serialargs_get_ptr(args, &src, size); if (!rc) TEE_MemMove(out, src, size); return rc; } static enum pkcs11_rc alloc_and_get(struct serialargs *args, char *orig_next, const void *buf0, size_t buf0_sz, void **out, size_t size) { enum pkcs11_rc rc = PKCS11_CKR_OK; uint8_t *ptr = NULL; void *src = NULL; size_t sz = 0; if (ADD_OVERFLOW(buf0_sz, size, &sz)) return PKCS11_CKR_ARGUMENTS_BAD; if (!sz) { *out = NULL; return PKCS11_CKR_OK; } rc = serialargs_get_ptr(args, &src, size); if (rc) return rc; ptr = TEE_Malloc(sz, TEE_MALLOC_FILL_ZERO); if (!ptr) { args->next = orig_next; return PKCS11_CKR_DEVICE_MEMORY; } TEE_MemMove(ptr, buf0, buf0_sz); TEE_MemMove(ptr + buf0_sz, src, size); *out = ptr; return PKCS11_CKR_OK; } enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args, void **out, size_t size) { return alloc_and_get(args, args->next, NULL, 0, out, size); } enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out, size_t size) { void *ptr = args->next; vaddr_t next_end = 0; if (ADD_OVERFLOW((vaddr_t)args->next, size, &next_end)) return PKCS11_CKR_ARGUMENTS_BAD; if (!size) { *out = NULL; return PKCS11_CKR_OK; } if ((char *)next_end > args->start + args->size) { EMSG("arg too short: full %zd, remain %zd, expect %zd", args->size, args->size - (args->next - args->start), size); return PKCS11_CKR_ARGUMENTS_BAD; } args->next += size; *out = ptr; return PKCS11_CKR_OK; } enum pkcs11_rc serialargs_alloc_get_one_attribute(struct serialargs *args, struct pkcs11_attribute_head **out) { struct pkcs11_attribute_head head = { }; enum pkcs11_rc rc = PKCS11_CKR_OK; char *orig_next = args->next; void *p = NULL; rc = serialargs_get(args, &head, sizeof(head)); if (rc) return rc; rc = alloc_and_get(args, orig_next, &head, sizeof(head), &p, head.size); if (rc) return rc; *out = p; return PKCS11_CKR_OK; } enum pkcs11_rc serialargs_alloc_get_attributes(struct serialargs *args, struct pkcs11_object_head **out) { struct pkcs11_object_head attr = { }; enum pkcs11_rc rc = PKCS11_CKR_OK; char *orig_next = args->next; void *p = NULL; rc = serialargs_get(args, &attr, sizeof(attr)); if (rc) return rc; rc = alloc_and_get(args, orig_next, &attr, sizeof(attr), &p, attr.attrs_size); if (rc) return rc; *out = p; return PKCS11_CKR_OK; } bool serialargs_remaining_bytes(struct serialargs *args) { return args->next < args->start + args->size; } enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args, struct pkcs11_client *client, struct pkcs11_session **sess) { uint32_t rv = PKCS11_CKR_GENERAL_ERROR; uint32_t session_handle = 0; struct pkcs11_session *session = NULL; rv = serialargs_get(args, &session_handle, sizeof(uint32_t)); if (rv) return rv; session = pkcs11_handle2session(session_handle, client); if (!session) return PKCS11_CKR_SESSION_HANDLE_INVALID; *sess = session; return PKCS11_CKR_OK; } enum pkcs11_rc serialize(char **bstart, size_t *blen, void *data, size_t len) { char *buf = NULL; size_t nlen = 0; if (ADD_OVERFLOW(*blen, len, &nlen)) return PKCS11_CKR_ARGUMENTS_BAD; buf = TEE_Realloc(*bstart, nlen); if (!buf) return PKCS11_CKR_DEVICE_MEMORY; TEE_MemMove(buf + *blen, data, len); *blen = nlen; *bstart = buf; return PKCS11_CKR_OK; } optee_os-4.3.0/ta/pkcs11/src/serializer.h000066400000000000000000000077241464416617300202000ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef PKCS11_TA_SERIALIZER_H #define PKCS11_TA_SERIALIZER_H #include #include #include struct pkcs11_client; struct pkcs11_session; /* * Util routines for serializes unformated arguments in a client memref */ struct serialargs { char *start; char *next; size_t size; }; struct pkcs11_client; struct pkcs11_session; /* * serialargs_init() - Initialize with a new input buffer * @args: serializing state * @in: input buffer * @size: size of the input buffer */ void serialargs_init(struct serialargs *args, void *in, size_t size); /* * serialargs_get() - copy out a chunk of data and advance * @args: serializing state * @out: output buffer * @sz: number of bytes to copy to output buffer * * Returns PKCS11_CKR_OK on success or PKCS11_CKR_ARGUMENTS_BAD on failure. */ enum pkcs11_rc serialargs_get(struct serialargs *args, void *out, size_t sz); /* * serialargs_get_u32() - copy out a uint32_t and advance * @args: serializing state * @out: output buffer * * Returns PKCS11_CKR_OK on success or PKCS11_CKR_ARGUMENTS_BAD on failure. */ static inline enum pkcs11_rc serialargs_get_u32(struct serialargs *args, uint32_t *out) { return serialargs_get(args, out, sizeof(*out)); } /* * serialargs_get_ptr() - get a pointer to a chunk of data and advance * @args: serializing state * @out: Pointer to the data retrieved in *@out * @size: Number of bytes to advance * * Returns PKCS11_CKR_OK on success or PKCS11_CKR_ARGUMENTS_BAD on failure. */ enum pkcs11_rc serialargs_get_ptr(struct serialargs *args, void **out, size_t size); /* * serialargs_alloc_get_one_attribute() - allocate and extract one attribute * @args: serializing state * @out: Pointer to the allocated and extracted attribute in *@out * * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on * failure. */ enum pkcs11_rc serialargs_alloc_get_one_attribute(struct serialargs *args, struct pkcs11_attribute_head **out); /* * serialargs_alloc_get_attributes() - allocate and extract an object * @args: serializing state * @out: Pointer to the allocated and extracted object in *@out * * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on * failure. */ enum pkcs11_rc serialargs_alloc_get_attributes(struct serialargs *args, struct pkcs11_object_head **out); /* * serialargs_alloc_and_get() - allocate and extract data * @args: serializing state * @out: Pointer to the allocated and extracted data in *@out * @size: Number of bytes to extract * * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on * failure. */ enum pkcs11_rc serialargs_alloc_and_get(struct serialargs *args, void **out, size_t size); /* * serialargs_remaining_bytes() - check for remaining bytes * @args: serializing state * * Returns true if there are remaining bytes in @args or false if all bytes * are consumed. */ bool serialargs_remaining_bytes(struct serialargs *args); /* * serialargs_get_session_from_handle() - extract and verify session * @args: serializing state * @client: client state * @sess: The retrieved session handle is available in *@sess * * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on * failure. */ enum pkcs11_rc serialargs_get_session_from_handle(struct serialargs *args, struct pkcs11_client *client, struct pkcs11_session **sess); /* * serialize() - append data into a serialized buffer * @bstart: points to start of a buffer or NULL, *@bstart is updated * with the new buffer if changed * @blen: size of the *@bstart buffer, updated when data is added * @data: data to appen to the buffer * @len: size of the @data buffer * * Returns PKCS11_CKR_OK on success or an error code from enum pkcs11_rc on * failure. */ enum pkcs11_rc serialize(char **bstart, size_t *blen, void *data, size_t len); #endif /*PKCS11_TA_SERIALIZER_H*/ optee_os-4.3.0/ta/pkcs11/src/sub.mk000066400000000000000000000007161464416617300167720ustar00rootroot00000000000000srcs-y += attributes.c srcs-y += entry.c srcs-y += handle.c srcs-y += object.c srcs-y += persistent_token.c srcs-y += pkcs11_attributes.c srcs-y += pkcs11_helpers.c srcs-y += pkcs11_token.c srcs-y += processing.c srcs-y += processing_aes.c srcs-y += processing_asymm.c srcs-y += processing_digest.c srcs-y += processing_ec.c srcs-y += processing_rsa.c srcs-y += processing_symm.c srcs-y += sanitize_object.c srcs-y += serializer.c srcs-y += token_capabilities.c optee_os-4.3.0/ta/pkcs11/src/token_capabilities.c000066400000000000000000000372171464416617300216530ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2017-2020, Linaro Limited */ #include #include #include #include #include #include #include "pkcs11_helpers.h" #include "token_capabilities.h" #define ALLOWED_PKCS11_CKFM \ (PKCS11_CKFM_ENCRYPT | PKCS11_CKFM_DECRYPT | \ PKCS11_CKFM_DERIVE | PKCS11_CKFM_DIGEST | \ PKCS11_CKFM_SIGN | PKCS11_CKFM_SIGN_RECOVER | \ PKCS11_CKFM_VERIFY | PKCS11_CKFM_VERIFY_RECOVER | \ PKCS11_CKFM_GENERATE | PKCS11_CKFM_GENERATE_KEY_PAIR | \ PKCS11_CKFM_WRAP | PKCS11_CKFM_UNWRAP) /* * Definition of supported processings for a PKCS#11 mechanisms * @id: Mechanism ID * @flags: Valid PKCS11_CKFM_* for a mechanism as per PKCS#11 * @one_shot: true of mechanism can be used for a one-short processing * @string: Helper string of the mechanism ID for debug purpose */ struct pkcs11_mechachism_modes { uint32_t id; uint32_t flags; bool one_shot; #if CFG_TEE_TA_LOG_LEVEL > 0 const char *string; #endif }; #if CFG_TEE_TA_LOG_LEVEL > 0 #define MECHANISM(_label, _flags, _single_part) \ { \ .id = _label, \ .one_shot = (_single_part), \ .flags = (_flags), \ .string = #_label, \ } #else #define MECHANISM(_label, _flags, _single_part) \ { \ .id = _label, \ .one_shot = (_single_part), \ .flags = (_flags), \ } #endif #define SINGLE_PART_ONLY true #define ANY_PART false #define CKFM_CIPHER (PKCS11_CKFM_ENCRYPT | PKCS11_CKFM_DECRYPT) #define CKFM_WRAP_UNWRAP (PKCS11_CKFM_WRAP | PKCS11_CKFM_UNWRAP) #define CKFM_CIPHER_WRAP (CKFM_CIPHER | CKFM_WRAP_UNWRAP) #define CKFM_CIPHER_WRAP_DERIVE (CKFM_CIPHER_WRAP | PKCS11_CKFM_DERIVE) #define CKFM_AUTH_NO_RECOVER (PKCS11_CKFM_SIGN | PKCS11_CKFM_VERIFY) #define CKFM_AUTH_WITH_RECOVER (PKCS11_CKFM_SIGN_RECOVER | \ PKCS11_CKFM_VERIFY_RECOVER) /* PKCS#11 specificies permitted operation for each mechanism */ static const struct pkcs11_mechachism_modes pkcs11_modes[] = { /* AES */ MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER_WRAP, ANY_PART), MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER_WRAP, ANY_PART), MECHANISM(PKCS11_CKM_AES_CBC_PAD, CKFM_CIPHER_WRAP, ANY_PART), MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER_WRAP, ANY_PART), MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER_WRAP, ANY_PART), MECHANISM(PKCS11_CKM_AES_GCM, CKFM_CIPHER_WRAP, ANY_PART), MECHANISM(PKCS11_CKM_AES_CMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_AES_CMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE, ANY_PART), MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE, ANY_PART), MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE, ANY_PART), MECHANISM(PKCS11_CKM_GENERIC_SECRET_KEY_GEN, PKCS11_CKFM_GENERATE, ANY_PART), /* Digest */ MECHANISM(PKCS11_CKM_MD5, PKCS11_CKFM_DIGEST, ANY_PART), MECHANISM(PKCS11_CKM_SHA_1, PKCS11_CKFM_DIGEST, ANY_PART), MECHANISM(PKCS11_CKM_SHA224, PKCS11_CKFM_DIGEST, ANY_PART), MECHANISM(PKCS11_CKM_SHA256, PKCS11_CKFM_DIGEST, ANY_PART), MECHANISM(PKCS11_CKM_SHA384, PKCS11_CKFM_DIGEST, ANY_PART), MECHANISM(PKCS11_CKM_SHA512, PKCS11_CKFM_DIGEST, ANY_PART), /* HMAC */ MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA256_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA384_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA512_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_MD5_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA_1_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA224_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA256_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA384_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA512_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART), /* EC */ MECHANISM(PKCS11_CKM_EC_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR, ANY_PART), MECHANISM(PKCS11_CKM_ECDH1_DERIVE, PKCS11_CKFM_DERIVE, ANY_PART), MECHANISM(PKCS11_CKM_ECDSA, CKFM_AUTH_NO_RECOVER, SINGLE_PART_ONLY), MECHANISM(PKCS11_CKM_ECDSA_SHA1, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_ECDSA_SHA224, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_ECDSA_SHA256, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_ECDSA_SHA384, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_ECDSA_SHA512, CKFM_AUTH_NO_RECOVER, ANY_PART), /* EDDSA */ MECHANISM(PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR, ANY_PART), MECHANISM(PKCS11_CKM_EDDSA, CKFM_AUTH_NO_RECOVER, ANY_PART), /* RSA */ MECHANISM(PKCS11_CKM_RSA_AES_KEY_WRAP, CKFM_CIPHER_WRAP, SINGLE_PART_ONLY), MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR, ANY_PART), MECHANISM(PKCS11_CKM_RSA_PKCS, CKFM_CIPHER_WRAP | CKFM_AUTH_NO_RECOVER | CKFM_AUTH_WITH_RECOVER, SINGLE_PART_ONLY), MECHANISM(PKCS11_CKM_RSA_PKCS_OAEP, CKFM_CIPHER_WRAP, SINGLE_PART_ONLY), MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, SINGLE_PART_ONLY), MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART), MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER, ANY_PART), }; #if CFG_TEE_TA_LOG_LEVEL > 0 const char *mechanism_string_id(enum pkcs11_mechanism_id id) { const size_t offset = sizeof("PKCS11_CKM_") - 1; size_t n = 0; for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) if (pkcs11_modes[n].id == id) return pkcs11_modes[n].string + offset; return "Unknown ID"; } #endif /*CFG_TEE_TA_LOG_LEVEL*/ /* * Return true if @id is a valid mechanism ID */ bool mechanism_is_valid(enum pkcs11_mechanism_id id) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) if (id == pkcs11_modes[n].id) return true; return false; } /* * Return true if mechanism ID is valid and flags matches PKCS#11 compliancy */ bool __maybe_unused mechanism_flags_complies_pkcs11(uint32_t mechanism_type, uint32_t flags) { size_t n = 0; assert((flags & ~ALLOWED_PKCS11_CKFM) == 0); for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) { if (pkcs11_modes[n].id == mechanism_type) { if (flags & ~pkcs11_modes[n].flags) EMSG("%s flags: 0x%"PRIx32" vs 0x%"PRIx32, id2str_mechanism(mechanism_type), flags, pkcs11_modes[n].flags); return (flags & ~pkcs11_modes[n].flags) == 0; } } /* Mechanism ID unexpectedly not found */ return false; } bool mechanism_is_one_shot_only(uint32_t mechanism_type) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(pkcs11_modes); n++) if (pkcs11_modes[n].id == mechanism_type) return pkcs11_modes[n].one_shot; /* Mechanism ID unexpectedly not found */ TEE_Panic(PKCS11_RV_NOT_FOUND); /* Dummy return to keep compiler happy */ return false; } /* * Field single_part_only is unused from array token_mechanism[], hence * simply use ANY_PART for all mechanism there. */ #define TA_MECHANISM(_label, _flags) MECHANISM((_label), (_flags), ANY_PART) /* * Arrays that centralizes the IDs and processing flags for mechanisms * supported by each embedded token. */ const struct pkcs11_mechachism_modes token_mechanism[] = { TA_MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER_WRAP), TA_MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER_WRAP), TA_MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER), TA_MECHANISM(PKCS11_CKM_AES_GCM, CKFM_CIPHER), TA_MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER), TA_MECHANISM(PKCS11_CKM_AES_CMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_AES_CMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE), TA_MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE), TA_MECHANISM(PKCS11_CKM_ECDH1_DERIVE, PKCS11_CKFM_DERIVE), TA_MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE), TA_MECHANISM(PKCS11_CKM_GENERIC_SECRET_KEY_GEN, PKCS11_CKFM_GENERATE), TA_MECHANISM(PKCS11_CKM_MD5, PKCS11_CKFM_DIGEST), TA_MECHANISM(PKCS11_CKM_SHA_1, PKCS11_CKFM_DIGEST), TA_MECHANISM(PKCS11_CKM_SHA224, PKCS11_CKFM_DIGEST), TA_MECHANISM(PKCS11_CKM_SHA256, PKCS11_CKFM_DIGEST), TA_MECHANISM(PKCS11_CKM_SHA384, PKCS11_CKFM_DIGEST), TA_MECHANISM(PKCS11_CKM_SHA512, PKCS11_CKFM_DIGEST), TA_MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA256_HMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA384_HMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA512_HMAC, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_MD5_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA_1_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA224_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA256_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA384_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA512_HMAC_GENERAL, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_EC_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR), TA_MECHANISM(PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR), TA_MECHANISM(PKCS11_CKM_ECDSA, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_ECDSA_SHA1, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_ECDSA_SHA224, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_ECDSA_SHA256, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_ECDSA_SHA384, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_ECDSA_SHA512, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_EDDSA, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_RSA_AES_KEY_WRAP, CKFM_CIPHER_WRAP), TA_MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN, PKCS11_CKFM_GENERATE_KEY_PAIR), TA_MECHANISM(PKCS11_CKM_RSA_PKCS, CKFM_CIPHER | CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_RSA_PKCS_OAEP, CKFM_CIPHER), TA_MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA256_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA384_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA512_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS, CKFM_AUTH_NO_RECOVER), TA_MECHANISM(PKCS11_CKM_SHA224_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER), }; /* * tee_malloc_mechanism_array - Allocate and fill array of supported mechanisms * @count: [in] [out] Pointer to number of mechanism IDs in client resource * Return allocated array of the supported mechanism IDs * * Allocates array with 32bit cells mechanism IDs for the supported ones only * if *@count covers number mechanism IDs exposed. */ uint32_t *tee_malloc_mechanism_list(size_t *out_count) { size_t n = 0; size_t count = 0; uint32_t *array = NULL; for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) if (token_mechanism[n].flags) count++; if (*out_count >= count) array = TEE_Malloc(count * sizeof(*array), TEE_USER_MEM_HINT_NO_FILL_ZERO); *out_count = count; if (!array) return NULL; for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) { if (token_mechanism[n].flags) { count--; array[count] = token_mechanism[n].id; } } assert(!count); return array; } uint32_t mechanism_supported_flags(enum pkcs11_mechanism_id id) { size_t n = 0; for (n = 0; n < ARRAY_SIZE(token_mechanism); n++) { if (id == token_mechanism[n].id) { uint32_t flags = token_mechanism[n].flags; assert(mechanism_flags_complies_pkcs11(id, flags)); return flags; } } return 0; } void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id, uint32_t *min_key_size, uint32_t *max_key_size) { switch (proc_id) { case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: /* This mechanism expects the keysize to be returned in bits */ *min_key_size = 1; /* in bits */ *max_key_size = 4096; /* in bits */ break; case PKCS11_CKM_MD5_HMAC: case PKCS11_CKM_MD5_HMAC_GENERAL: *min_key_size = 8; *max_key_size = 64; break; case PKCS11_CKM_SHA_1_HMAC: case PKCS11_CKM_SHA_1_HMAC_GENERAL: *min_key_size = 10; *max_key_size = 64; break; case PKCS11_CKM_SHA224_HMAC: case PKCS11_CKM_SHA224_HMAC_GENERAL: *min_key_size = 14; *max_key_size = 64; break; case PKCS11_CKM_SHA256_HMAC: case PKCS11_CKM_SHA256_HMAC_GENERAL: *min_key_size = 24; *max_key_size = 128; break; case PKCS11_CKM_SHA384_HMAC: case PKCS11_CKM_SHA384_HMAC_GENERAL: *min_key_size = 32; *max_key_size = 128; break; case PKCS11_CKM_SHA512_HMAC: case PKCS11_CKM_SHA512_HMAC_GENERAL: *min_key_size = 32; *max_key_size = 128; break; case PKCS11_CKM_AES_KEY_GEN: case PKCS11_CKM_AES_ECB: case PKCS11_CKM_AES_CBC: case PKCS11_CKM_AES_CBC_PAD: case PKCS11_CKM_AES_CTR: case PKCS11_CKM_AES_GCM: case PKCS11_CKM_AES_CTS: case PKCS11_CKM_AES_CMAC: case PKCS11_CKM_AES_CMAC_GENERAL: *min_key_size = 16; *max_key_size = 32; break; case PKCS11_CKM_EC_KEY_PAIR_GEN: case PKCS11_CKM_ECDSA: case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: case PKCS11_CKM_ECDH1_DERIVE: *min_key_size = 160; /* in bits */ *max_key_size = 521; /* in bits */ break; case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: case PKCS11_CKM_EDDSA: *min_key_size = 256; /* in bits */ *max_key_size = 448; /* in bits */ break; case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: case PKCS11_CKM_RSA_PKCS: case PKCS11_CKM_MD5_RSA_PKCS: case PKCS11_CKM_SHA1_RSA_PKCS: case PKCS11_CKM_RSA_PKCS_OAEP: case PKCS11_CKM_SHA1_RSA_PKCS_PSS: case PKCS11_CKM_SHA256_RSA_PKCS: case PKCS11_CKM_SHA384_RSA_PKCS: case PKCS11_CKM_SHA512_RSA_PKCS: case PKCS11_CKM_SHA256_RSA_PKCS_PSS: case PKCS11_CKM_SHA384_RSA_PKCS_PSS: case PKCS11_CKM_SHA512_RSA_PKCS_PSS: case PKCS11_CKM_SHA224_RSA_PKCS: case PKCS11_CKM_SHA224_RSA_PKCS_PSS: *min_key_size = 256; /* in bits */ *max_key_size = 4096; /* in bits */ break; default: *min_key_size = 0; *max_key_size = 0; break; } } void mechanism_supported_key_sizes_bytes(uint32_t proc_id, uint32_t *min_key_size, uint32_t *max_key_size) { pkcs11_mechanism_supported_key_sizes(proc_id, min_key_size, max_key_size); switch (proc_id) { case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: case PKCS11_CKM_EC_KEY_PAIR_GEN: case PKCS11_CKM_ECDSA: case PKCS11_CKM_EDDSA: case PKCS11_CKM_ECDSA_SHA1: case PKCS11_CKM_ECDSA_SHA224: case PKCS11_CKM_ECDSA_SHA256: case PKCS11_CKM_ECDSA_SHA384: case PKCS11_CKM_ECDSA_SHA512: case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: /* Size is in bits -> convert to bytes and ceil */ *min_key_size = ROUNDUP(*min_key_size, 8) / 8; *max_key_size = ROUNDUP(*max_key_size, 8) / 8; break; default: /* Size is already in bytes */ break; } } optee_os-4.3.0/ta/pkcs11/src/token_capabilities.h000066400000000000000000000020101464416617300216370ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2017-2020, Linaro Limited */ #ifndef TOKEN_CAPABILITIES_H #define TOKEN_CAPABILITIES_H #include #include #include bool mechanism_flags_complies_pkcs11(uint32_t mechanism_type, uint32_t flags); bool mechanism_is_one_shot_only(uint32_t mechanism_type); bool mechanism_is_valid(enum pkcs11_mechanism_id id); #if CFG_TEE_TA_LOG_LEVEL > 0 const char *mechanism_string_id(enum pkcs11_mechanism_id id); #endif uint32_t *tee_malloc_mechanism_list(size_t *out_count); uint32_t mechanism_supported_flags(enum pkcs11_mechanism_id id); void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id, uint32_t *min_key_size, uint32_t *max_key_size); void mechanism_supported_key_sizes_bytes(uint32_t proc_id, uint32_t *min_key_size, uint32_t *max_key_size); static inline bool mechanism_is_supported(enum pkcs11_mechanism_id id) { return mechanism_supported_flags(id) != 0; } #endif /*TOKEN_CAPABILITIES_H*/ optee_os-4.3.0/ta/pkcs11/src/user_ta_header_defines.h000066400000000000000000000012141464416617300224620ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2018-2019, Linaro Limited */ #ifndef USER_TA_HEADER_DEFINES_H #define USER_TA_HEADER_DEFINES_H #include #define TA_UUID PKCS11_TA_UUID #define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ TA_FLAG_MULTI_SESSION | \ TA_FLAG_INSTANCE_KEEP_ALIVE) #define TA_STACK_SIZE (4 * 1024) #define TA_DATA_SIZE CFG_PKCS11_TA_HEAP_SIZE #define TA_DESCRIPTION "PKCS#11 trusted application" #define TA_VERSION TO_STR(PKCS11_TA_VERSION_MAJOR) "." \ TO_STR(PKCS11_TA_VERSION_MINOR) "." \ TO_STR(PKCS11_TA_VERSION_PATCH) #endif /*USER_TA_HEADER_DEFINES_H*/ optee_os-4.3.0/ta/pkcs11/sub.mk000066400000000000000000000010611464416617300161750ustar00rootroot00000000000000# Enable PKCS#11 TA's C_DigestKey support CFG_PKCS11_TA_ALLOW_DIGEST_KEY ?= y # Enable PKCS#11 TA's TEE Identity based authentication support CFG_PKCS11_TA_AUTH_TEE_IDENTITY ?= y # PKCS#11 TA heap size can be customized if 32kB is not enough CFG_PKCS11_TA_HEAP_SIZE ?= (32 * 1024) # Defines the number of PKCS11 token implemented by the PKCS11 TA CFG_PKCS11_TA_TOKEN_COUNT ?= 3 # When enabled, embed support for object checksum value computation CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE ?= y global-incdirs-y += include global-incdirs-y += src subdirs-y += src optee_os-4.3.0/ta/pkcs11/user_ta.mk000066400000000000000000000003451464416617300170520ustar00rootroot00000000000000user-ta-uuid := fd02c9da-306c-48c7-a49c-bbd827ae86ee all: pkcs11-ta-verify-helpers .PHONY: pkcs11-ta-verify-helpers pkcs11-ta-verify-helpers: @$(cmd-echo-silent) ' CHK ' $@ ${q}ta/pkcs11/scripts/verify-helpers.sh --quiet optee_os-4.3.0/ta/remoteproc/000077500000000000000000000000001464416617300161325ustar00rootroot00000000000000optee_os-4.3.0/ta/remoteproc/Makefile000066400000000000000000000007621464416617300175770ustar00rootroot00000000000000# The UUID for the Trusted Application BINARY=80a4c275-0a47-4905-8285-1486a9771a08 ifdef TA_CROSS_COMPILE CROSS_COMPILE ?= $(TA_CROSS_COMPILE) endif export CROSS_COMPILE CFG_TEE_TA_LOG_LEVEL ?= 2 CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) -include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), ) clean: @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA' @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)' endif optee_os-4.3.0/ta/remoteproc/include/000077500000000000000000000000001464416617300175555ustar00rootroot00000000000000optee_os-4.3.0/ta/remoteproc/include/ta_remoteproc.h000066400000000000000000000037401464416617300225750ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, STMicroelectronics */ #ifndef TA_REMOTEPROC_H #define TA_REMOTEPROC_H /* * This UUID is generated with uuidgen * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html */ #define TA_REMOTEPROC_UUID { 0x80a4c275, 0x0a47, 0x4905, \ { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } /* The command IDs implemented in this TA */ /* * Authentication of the firmware and load in the remote processor memory. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [in] params[1].memref: buffer containing the image of the firmware */ #define TA_RPROC_CMD_LOAD_FW 1 /* * Start the remote processor. * * [in] params[0].value.a: Unique 32bit remote processor identifier */ #define TA_RPROC_CMD_START_FW 2 /* * Stop the remote processor. * * [in] params[0].value.a: Unique 32bit remote processor identifier */ #define TA_RPROC_CMD_STOP_FW 3 /* * Return the physical address of the resource table, or 0 if not found * No check is done to verify that the address returned is accessible by the * non-secure world. If the resource table is loaded in a protected memory, * then accesses from non-secure world will likely fail. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [out] params[1].value.a: 32bit LSB resource table memory address * [out] params[1].value.b: 32bit MSB resource table memory address * [out] params[2].value.a: 32bit LSB resource table memory size * [out] params[2].value.b: 32bit MSB resource table memory size */ #define TA_RPROC_CMD_GET_RSC_TABLE 4 /* * Get remote processor firmware core dump. If found, return either * TEE_SUCCESS on successful completion or TEE_ERROR_SHORT_BUFFER if output * buffer is too short to store the core dump. * * [in] params[0].value.a: Unique 32bit remote processor identifier * [out] params[1].memref: Core dump, if found */ #define TA_RPROC_CMD_GET_COREDUMP 5 #endif /*TA_REMOTEPROC_H*/ optee_os-4.3.0/ta/remoteproc/src/000077500000000000000000000000001464416617300167215ustar00rootroot00000000000000optee_os-4.3.0/ta/remoteproc/src/elf_parser.c000066400000000000000000000105311464416617300212070ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2023, STMicroelectronics */ #include #include #include #include #include #include static bool va_in_fwm_image_range(void *va, uint8_t *fw, size_t fw_size) { uint8_t *vaddr = va; return vaddr >= fw && vaddr < fw + fw_size; } TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; if (!fw || !IS_ALIGNED_WITH_TYPE(fw, uint32_t)) { EMSG("Invalid firmware address"); return TEE_ERROR_BAD_PARAMETERS; } if (size < sizeof(Elf32_Ehdr) || size < (ehdr->e_shoff + sizeof(Elf32_Shdr))) return TEE_ERROR_BAD_FORMAT; if (!IS_ELF(*ehdr) || ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_phentsize != sizeof(Elf32_Phdr) || ehdr->e_shentsize != sizeof(Elf32_Shdr)) { EMSG("Invalid header"); return TEE_ERROR_BAD_FORMAT; } if (ehdr->e_phnum == 0) { EMSG("No loadable segment found"); return TEE_ERROR_BAD_FORMAT; } return TEE_SUCCESS; } TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, TEE_Result (*load_seg)(uint8_t *src, uint32_t size, uint32_t da, uint32_t mem_size, void *priv), void *priv_data) { Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; Elf32_Phdr *phdr = (void *)((int8_t *)ehdr + ehdr->e_phoff); TEE_Result res = TEE_SUCCESS; unsigned int i = 0; if (!load_seg || fw + fw_size <= fw) return TEE_ERROR_BAD_PARAMETERS; if (!IS_ALIGNED_WITH_TYPE(phdr, uint32_t) || !va_in_fwm_image_range(phdr, fw, fw_size)) return TEE_ERROR_BAD_FORMAT; for (i = 0; i < ehdr->e_phnum; i++, phdr++) { uint32_t dst = phdr->p_paddr; uint8_t *src = NULL; if (phdr->p_type != PT_LOAD) continue; if (!va_in_fwm_image_range((void *)((vaddr_t)(phdr + 1) - 1), fw, fw_size)) return TEE_ERROR_BAD_FORMAT; src = (uint8_t *)fw + phdr->p_offset; if (!va_in_fwm_image_range(src, fw, fw_size) || !va_in_fwm_image_range(src + phdr->p_filesz, fw, fw_size)) return TEE_ERROR_BAD_FORMAT; res = load_seg(src, phdr->p_filesz, dst, phdr->p_memsz, priv_data); if (res) return res; } return TEE_SUCCESS; } TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, Elf32_Addr *rsc_addr, Elf32_Word *rsc_size) { Elf32_Shdr *shdr = NULL; unsigned int i = 0; char *name_table = NULL; struct resource_table *table = NULL; Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; uint8_t *elf_data = fw; if (fw + fw_size <= fw || fw + ehdr->e_shoff < fw) return TEE_ERROR_BAD_PARAMETERS; shdr = (void *)(fw + ehdr->e_shoff); if (!IS_ALIGNED_WITH_TYPE(shdr, uint32_t) || !va_in_fwm_image_range(shdr, fw, fw_size)) return TEE_ERROR_BAD_FORMAT; name_table = (char *)elf_data + shdr[ehdr->e_shstrndx].sh_offset; if (!va_in_fwm_image_range(name_table, fw, fw_size)) return TEE_ERROR_BAD_FORMAT; for (i = 0; i < ehdr->e_shnum; i++, shdr++) { size_t size = shdr->sh_size; size_t offset = shdr->sh_offset; size_t s = 0; if (!va_in_fwm_image_range(shdr, fw, fw_size)) return TEE_ERROR_BAD_FORMAT; if (strcmp(name_table + shdr->sh_name, ".resource_table")) continue; if (!shdr->sh_size) return TEE_ERROR_NO_DATA; if (offset + size > fw_size || offset + size < size) { EMSG("Resource table truncated"); return TEE_ERROR_BAD_FORMAT; } if (sizeof(struct resource_table) > size) { EMSG("No header found in resource table"); return TEE_ERROR_BAD_FORMAT; } table = (struct resource_table *)(void *)(elf_data + offset); if (!IS_ALIGNED_WITH_TYPE(table, uint32_t)) return TEE_ERROR_CORRUPT_OBJECT; if (table->ver != 1) { EMSG("Unsupported firmware version %"PRId32, table->ver); return TEE_ERROR_BAD_FORMAT; } if (table->reserved[0] || table->reserved[1]) { EMSG("Non zero reserved bytes"); return TEE_ERROR_BAD_FORMAT; } if (MUL_OVERFLOW(table->num, sizeof(*table->offset), &s) || ADD_OVERFLOW(s, sizeof(struct resource_table), &s) || s > size) { EMSG("Resource table incomplete"); return TEE_ERROR_BAD_FORMAT; } DMSG("Resource table address %#"PRIx32", size %"PRIu32, shdr->sh_addr, shdr->sh_size); *rsc_addr = shdr->sh_addr; *rsc_size = shdr->sh_size; return TEE_SUCCESS; } return TEE_ERROR_NO_DATA; } optee_os-4.3.0/ta/remoteproc/src/elf_parser.h000066400000000000000000000052151464416617300212170ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023, STMicroelectronics */ #ifndef ELF_PARSER_H #define ELF_PARSER_H #include #include #include /** * struct resource_table - firmware resource table header * @ver: version number * @num: number of resource entries * @reserved: reserved (must be zero) * @offset: array of offsets pointing at the various resource entries * * A resource table is essentially a list of system resources required * by the remote processor. It may also include configuration entries. * If needed, the remote processor firmware should contain this table * as a dedicated ".resource_table" ELF section. * * This structure shall be consistent with the Linux kernel structure * definition from include/linux/remoteproc.h. * * The resource_table structure does not need to be packed in OP-TEE. The ELF * parser does not access the system resources structures that follow this * structure in shared memory (no memory alignment constraint on structures). */ struct resource_table { uint32_t ver; uint32_t num; uint32_t reserved[2]; uint32_t offset[]; }; struct fw_elf32 { uintptr_t e_entry; uintptr_t e_phoff; uintptr_t e_shoff; uint32_t e_phnum; uint32_t e_shnum; uint32_t e_phentsize; uint32_t e_shentsize; Elf32_Phdr *phdr; Elf32_Shdr *shdr; }; /* * e32_parse_ehdr() - Check and parse the ELF header * * @fw: Firmware ELF file image * @size: Byte size of firmware ELF file image * Return TEE_SUCCESS or appropriate error. */ TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size); /* * e32_parser_load_elf_image() - simple ELF loader * @fw: Firmware ELF file image * @fw_size: Firmware ELF file image byte size * @load_seg: Callback for loading a firmware image segment into device memory * @priv_data: Private data passed to @load_seg callback. * Return TEE_SUCCESS or appropriate error. */ TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, TEE_Result (*load_seg)(uint8_t *src, uint32_t size, uint32_t da, uint32_t mem_size, void *priv), void *priv_data); /* * e32_parser_find_rsc_table() - find resource table in an ELF image * @fw: Firmware ELF file image * @fw_size: Firmware ELF file image byte size * @rsc_addr: Output resource table address from the remote proc perspective * @rsc_size: Output resource table size * Return TEE_SUCCESS if found, * TEE_ERROR_NO_DATA if not found, * or appropriate error. */ TEE_Result e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, Elf32_Addr *rsc_addr, Elf32_Word *rsc_size); #endif /*ELF_PARSER_H*/ optee_os-4.3.0/ta/remoteproc/src/remoteproc_core.c000066400000000000000000000720051464416617300222600ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2023, STMicroelectronics */ #include #include #include #include #include #include #include #include #include #include /* * The remoteproc Trusted Application is in charge of authenticating and loading * images signed by the scripts/sign_rproc_fw.py. The TA is also in charge of * starting and stopping the remote processor. * The structure of the signed image is: * * -----+-------------+ * / | Magic | 32-bit word, magic value equal to * / +-------------+ 0x3543A468 * / +-------------+ * / | version | 32-bit word, version of the format * / +-------------+ * +-----------+ +-------------+ * | Header | | TLV size | 32-bit word, size of the TLV * +-----------+ +-------------+ (aligned on 64-bit), in bytes. * \ +-------------+ * \ | sign size | 32-bit word, size of the signature * \ +-------------+ (aligned on 64-bit), in bytes. * \ +-------------+ * \ | images size | 32-bit word, size of the images to * -----+-------------+ load (aligned on 64-bit), in bytes. * * +-------------+ Information used to authenticate the * | TLV | images and boot the remote processor, * | | stored in Type-Length-Value format. * +-------------+ 'Type' and 'Length' are 32-bit words. * * +-------------+ * | Signature | Signature of the header and the TLV. * +-------------+ * * +-------------+ * | Firmware | * | image 1 | * +-------------+ * ... * +-------------+ * | Firmware | * | image n | * +-------------+ */ /* Firmware state */ enum remoteproc_state { REMOTEPROC_OFF = 0, REMOTEPROC_LOADED, REMOTEPROC_STARTED, }; #define RPROC_HDR_MAGIC 0x3543A468 #define HEADER_VERSION 1 /* Supported signature algorithm */ enum remoteproc_sign_type { RPROC_RSASSA_PKCS1_v1_5_SHA256 = 1, RPROC_ECDSA_SHA256 = 2, }; enum remoteproc_img_type { REMOTEPROC_ELF_TYPE = 1, REMOTEPROC_INVALID_TYPE = 0xFF }; /* remoteproc_tlv structure offsets */ #define RPROC_TLV_LENGTH_OF U(0x04) #define RPROC_TLV_VALUE_OF U(0x08) /* TLV types */ #define RPROC_TLV_SIGNTYPE U(0x00000001) #define RPROC_TLV_HASHTYPE U(0x00000002) #define RPROC_TLV_NUM_IMG U(0x00000003) #define RPROC_TLV_IMGTYPE U(0x00000004) #define RPROC_TLV_IMGSIZE U(0x00000005) #define RPROC_TLV_HASHTABLE U(0x00000010) #define RPROC_TLV_PKEYINFO U(0x00000011) #define RPROC_PLAT_TLV_TYPE_MIN U(0x00010000) #define RPROC_PLAT_TLV_TYPE_MAX U(0x00020000) #define RPROC_TLV_SIGNTYPE_LGTH U(1) #define ROUNDUP_64(x) ROUNDUP((x), sizeof(uint64_t)) /* * struct remoteproc_tlv - Type-Length-Value structure * @type: type of data * @length: size of the data. * @value: pointer to the data. */ struct remoteproc_tlv { uint32_t type; uint32_t length; uint8_t value[]; }; /* * struct remoteproc_segment - program header with hash structure * @phdr: program header * @hash: hash associated to the program segment. */ struct remoteproc_segment { Elf32_Phdr phdr; uint8_t hash[TEE_SHA256_HASH_SIZE]; }; /* * struct remoteproc_fw_hdr - firmware header * @magic: Magic number, must be equal to RPROC_HDR_MAGIC * @version: Version of the header (must be 1) * @tlv_len: Generic meta data chunk (TLV format) * @sign_len: Signature chunk byte length * @img_len: Firmware image chunk byte length */ struct remoteproc_fw_hdr { uint32_t magic; uint32_t version; uint32_t tlv_len; uint32_t sign_len; uint32_t img_len; }; #define FW_TLV_PTR(img, hdr) ((img) + sizeof(*(hdr))) #define FW_SIGN_PTR(img, hdr) ({ \ struct remoteproc_fw_hdr *__hdr = (hdr); \ \ FW_TLV_PTR((img), __hdr) + ROUNDUP_64(__hdr->tlv_len); \ }) #define FW_IMG_PTR(img, hdr) ({ \ struct remoteproc_fw_hdr *___hdr = (hdr); \ \ FW_SIGN_PTR((img), ___hdr) + ROUNDUP_64(___hdr->sign_len); \ }) /* * struct remoteproc_sig_algo - signature algorithm information * @sign_type: Header signature type * @id: Signature algorithm identifier TEE_ALG_* * @hash_len: Signature hash length */ struct remoteproc_sig_algo { enum remoteproc_sign_type sign_type; uint32_t id; size_t hash_len; }; /* * struct remoteproc_context - firmware context * @rproc_id: Unique Id of the processor * @sec_cpy: Location of a secure copy of the header, TLVs and signature * @tlvs: Location of a secure copy of the firmware TLVs * @tlvs_sz: Byte size of the firmware TLVs blob. * @fw_img: Firmware image * @fw_img_sz: Byte size of the firmware image * @hash_table: Location of a copy of the segment's hash table * @nb_segment: number of segment to load * @rsc_pa: Physical address of the firmware resource table * @rsc_size: Byte size of the firmware resource table * @state: Remote-processor state * @hw_fmt: Image format capabilities of the remoteproc PTA * @hw_img_prot: Image protection capabilities of the remoteproc PTA * @link: Linked list element */ struct remoteproc_context { uint32_t rproc_id; uint8_t *sec_cpy; uint8_t *tlvs; size_t tlvs_sz; uint8_t *fw_img; size_t fw_img_sz; struct remoteproc_segment *hash_table; uint32_t nb_segment; paddr_t rsc_pa; size_t rsc_size; enum remoteproc_state state; uint32_t hw_fmt; uint32_t hw_img_prot; TAILQ_ENTRY(remoteproc_context) link; }; TAILQ_HEAD(remoteproc_firmware_head, remoteproc_context); static struct remoteproc_firmware_head firmware_head = TAILQ_HEAD_INITIALIZER(firmware_head); static const struct remoteproc_sig_algo rproc_ta_sign_algo[] = { { .sign_type = RPROC_RSASSA_PKCS1_v1_5_SHA256, .id = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, .hash_len = TEE_SHA256_HASH_SIZE, }, { .sign_type = RPROC_ECDSA_SHA256, .id = TEE_ALG_ECDSA_P256, .hash_len = TEE_SHA256_HASH_SIZE, }, }; static size_t session_refcount; static TEE_TASessionHandle pta_session; static void remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused *hdr) { DMSG("magic :\t%#"PRIx32, hdr->magic); DMSG("version :\t%#"PRIx32, hdr->version); DMSG("tlv_len :\t%#"PRIx32, hdr->tlv_len); DMSG("sign_len :\t%#"PRIx32, hdr->sign_len); DMSG("img_len :\t%#"PRIx32, hdr->img_len); } static TEE_Result remoteproc_get_tlv(void *tlv_chunk, size_t tlv_size, uint16_t type, uint8_t **value, size_t *length) { uint8_t *p_tlv = (uint8_t *)tlv_chunk; uint8_t *p_end_tlv = p_tlv + tlv_size; uint32_t tlv_type = 0; uint32_t tlv_length = 0; uint32_t tlv_v = 0; *value = NULL; *length = 0; /* Parse the TLV area */ while (p_tlv < p_end_tlv) { memcpy(&tlv_v, p_tlv, sizeof(tlv_v)); tlv_type = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); memcpy(&tlv_v, p_tlv + RPROC_TLV_LENGTH_OF, sizeof(tlv_v)); tlv_length = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); if (tlv_type == type) { /* The specified TLV has been found */ DMSG("TLV type %#"PRIx32" found, size %#"PRIx32, type, tlv_length); *value = &p_tlv[RPROC_TLV_VALUE_OF]; *length = tlv_length; if (tlv_length) return TEE_SUCCESS; else return TEE_ERROR_NO_DATA; } p_tlv += ROUNDUP_64(sizeof(struct remoteproc_tlv) + tlv_length); } return TEE_ERROR_NO_DATA; } static struct remoteproc_context *remoteproc_find_firmware(uint32_t rproc_id) { struct remoteproc_context *ctx = NULL; TAILQ_FOREACH(ctx, &firmware_head, link) if (ctx->rproc_id == rproc_id) return ctx; return NULL; } static struct remoteproc_context *remoteproc_add_firmware(uint32_t rproc_id) { struct remoteproc_context *ctx = NULL; ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO); if (!ctx) return NULL; ctx->rproc_id = rproc_id; TAILQ_INSERT_TAIL(&firmware_head, ctx, link); return ctx; } static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type) { unsigned int i = 0; for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++) if (sign_type == rproc_ta_sign_algo[i].sign_type) return &rproc_ta_sign_algo[i]; return NULL; } static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx, const struct remoteproc_sig_algo *algo, uint8_t *hash, uint32_t hash_len) { TEE_Result res = TEE_ERROR_GENERIC; struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; struct rproc_pta_key_info *keyinfo = NULL; uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT); TEE_Param params[TEE_NUM_PARAMS] = { }; size_t length = 0; uint8_t *tlv_keyinfo = NULL; uint8_t *sign = NULL; res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_PKEYINFO, &tlv_keyinfo, &length); if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA) return res; keyinfo = TEE_Malloc(sizeof(*keyinfo) + length, TEE_MALLOC_FILL_ZERO); if (!keyinfo) return TEE_ERROR_OUT_OF_MEMORY; keyinfo->algo = algo->id; keyinfo->info_size = length; memcpy(keyinfo->info, tlv_keyinfo, length); sign = FW_SIGN_PTR(ctx->sec_cpy, hdr); params[0].value.a = ctx->rproc_id; params[1].memref.buffer = keyinfo; params[1].memref.size = rproc_pta_keyinfo_size(keyinfo); params[2].memref.buffer = hash; params[2].memref.size = hash_len; params[3].memref.buffer = sign; params[3].memref.size = hdr->sign_len; res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_VERIFY_DIGEST, param_types, params, NULL); if (res != TEE_SUCCESS) EMSG("Failed to verify signature, res = %#"PRIx32, res); TEE_Free(keyinfo); return res; } static TEE_Result remoteproc_save_fw_header_and_tlvs(struct remoteproc_context *ctx, void *fw_orig, uint32_t fw_orig_size) { struct remoteproc_fw_hdr *hdr = fw_orig; uint32_t length = 0; if (!IS_ALIGNED_WITH_TYPE(fw_orig, struct remoteproc_fw_hdr)) return TEE_ERROR_BAD_PARAMETERS; if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->tlv_len), &length) || ADD_OVERFLOW(length, ROUNDUP_64(hdr->sign_len), &length)) return TEE_ERROR_BAD_PARAMETERS; if (fw_orig_size <= length || !hdr->sign_len || !hdr->tlv_len) return TEE_ERROR_BAD_PARAMETERS; remoteproc_header_dump(hdr); /* Copy the header, the TLVs and the signature in secure memory */ ctx->sec_cpy = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO); if (!ctx->sec_cpy) return TEE_ERROR_OUT_OF_MEMORY; memcpy(ctx->sec_cpy, fw_orig, length); return TEE_SUCCESS; } static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx) { TEE_OperationHandle op = TEE_HANDLE_NULL; struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; const struct remoteproc_sig_algo *algo = NULL; TEE_Result res = TEE_ERROR_GENERIC; uint8_t *tlv_sign_algo = NULL; size_t length = 0; uint8_t *hash = NULL; size_t hash_len = 0; /* Get the algo type from TLV data */ res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_SIGNTYPE, &tlv_sign_algo, &length); if (res != TEE_SUCCESS || length != RPROC_TLV_SIGNTYPE_LGTH) return TEE_ERROR_BAD_PARAMETERS; algo = remoteproc_get_algo(*tlv_sign_algo); if (!algo) { EMSG("Unsupported signature type %"PRId8, *tlv_sign_algo); return TEE_ERROR_NOT_SUPPORTED; } /* Compute the header and TLVs hashes */ hash_len = algo->hash_len; hash = TEE_Malloc(hash_len, TEE_MALLOC_FILL_ZERO); if (!hash) return TEE_ERROR_OUT_OF_MEMORY; res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); if (res != TEE_SUCCESS) goto free_hash; TEE_DigestUpdate(op, hdr, sizeof(*hdr)); res = TEE_DigestDoFinal(op, ctx->tlvs, ROUNDUP_64(hdr->tlv_len), hash, &hash_len); if (res != TEE_SUCCESS) goto out; /* * This implementation could be enhanced by providing alternative to * verify the signature in the TA. This could be done for instance by * getting the key object from secure storage. */ /* By default ask the remoteproc PTA to verify the signature. */ res = remoteproc_pta_verify(ctx, algo, hash, hash_len); out: TEE_FreeOperation(op); free_hash: TEE_Free(hash); return res; } static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx, uint32_t fw_orig_size) { struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy; uint32_t size = 0; if (hdr->magic != RPROC_HDR_MAGIC) return TEE_ERROR_BAD_PARAMETERS; if (hdr->version != HEADER_VERSION) return TEE_ERROR_BAD_PARAMETERS; /* * The offsets are aligned to 64 bits format. While the length of each * chunks are the effective length, excluding the alignment padding * bytes. */ if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->sign_len), &size) || ADD_OVERFLOW(size, ROUNDUP_64(hdr->img_len), &size) || ADD_OVERFLOW(size, ROUNDUP_64(hdr->tlv_len), &size) || fw_orig_size != size) return TEE_ERROR_BAD_PARAMETERS; return TEE_SUCCESS; } static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx) { uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); TEE_Param params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_ERROR_GENERIC; params[0].value.a = ctx->rproc_id; res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_HW_CAPABILITIES, param_types, params, NULL); if (res) return res; ctx->hw_fmt = params[1].value.a; ctx->hw_img_prot = params[2].value.a; return TEE_SUCCESS; } static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx, uint8_t *fw_orig, uint32_t fw_orig_size) { struct remoteproc_fw_hdr *hdr = NULL; TEE_Result res = TEE_ERROR_GENERIC; res = get_rproc_pta_capabilities(ctx); if (res) return res; /* Secure the firmware image depending on strategy */ if (!(ctx->hw_img_prot & PTA_RPROC_HWCAP_PROT_HASH_TABLE) || ctx->hw_fmt != PTA_RPROC_HWCAP_FMT_ELF) { /* * Only hash table for ELF format support implemented * in a first step. */ return TEE_ERROR_NOT_IMPLEMENTED; } res = remoteproc_save_fw_header_and_tlvs(ctx, fw_orig, fw_orig_size); if (res) return res; res = remoteproc_verify_header(ctx, fw_orig_size); if (res) goto free_sec_cpy; hdr = (void *)ctx->sec_cpy; ctx->tlvs_sz = hdr->tlv_len; ctx->tlvs = FW_TLV_PTR(ctx->sec_cpy, hdr); res = remoteproc_verify_signature(ctx); if (res) goto free_sec_cpy; /* Store location of the loadable binary in non-secure memory */ ctx->fw_img_sz = hdr->img_len; ctx->fw_img = FW_IMG_PTR(fw_orig, hdr); DMSG("Firmware images addr: %p size: %zu", ctx->fw_img, ctx->fw_img_sz); return TEE_SUCCESS; free_sec_cpy: TEE_Free(ctx->sec_cpy); ctx->sec_cpy = NULL; return res; } static paddr_t remoteproc_da_to_pa(uint32_t da, size_t size, struct remoteproc_context *ctx) { uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT); TEE_Param params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_ERROR_GENERIC; paddr_t pa = 0; /* * The ELF file contains remote processor device addresses, that refer * to the remote processor memory space. * A translation is needed to get the corresponding physical address. */ params[0].value.a = ctx->rproc_id; params[1].value.a = da; params[2].value.a = size; res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_FIRMWARE_DA_TO_PA, param_types, params, NULL); if (res != TEE_SUCCESS) { EMSG("Failed to translate device address %#"PRIx32, da); return 0; } pa = (paddr_t)reg_pair_to_64(params[3].value.b, params[3].value.a); /* Assert that the pa address is not 0 */ assert(pa); return pa; } static TEE_Result remoteproc_parse_rsc_table(struct remoteproc_context *ctx, uint8_t *fw_img, size_t fw_img_sz, paddr_t *rsc_pa, size_t *rsc_size) { uint32_t da = 0; TEE_Result res = TEE_ERROR_GENERIC; Elf32_Word size = 0; res = e32_parser_find_rsc_table(fw_img, fw_img_sz, &da, &size); if (res) return res; DMSG("Resource table device address %#"PRIx32" size %#"PRIx32, da, size); *rsc_pa = remoteproc_da_to_pa(da, size, ctx); if (!*rsc_pa) return TEE_ERROR_ACCESS_DENIED; *rsc_size = size; return TEE_SUCCESS; } static TEE_Result get_hash_table(struct remoteproc_context *ctx) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *tlv_hash = NULL; struct remoteproc_segment *hash_table = NULL; size_t length = 0; /* Get the segment's hash table from TLV data */ res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_HASHTABLE, &tlv_hash, &length); if (res) return res; if (length % sizeof(struct remoteproc_segment)) return TEE_ERROR_BAD_PARAMETERS; /* We can not ensure that tlv_hash is memory aligned so make a copy */ hash_table = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO); if (!hash_table) return TEE_ERROR_OUT_OF_MEMORY; memcpy(hash_table, tlv_hash, length); ctx->hash_table = hash_table; ctx->nb_segment = length / sizeof(struct remoteproc_segment); return TEE_SUCCESS; } static TEE_Result get_tlv_images_type(struct remoteproc_context *ctx, uint8_t num_img, uint8_t idx, uint8_t *img_type) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *tlv_value = NULL; size_t length = 0; /* Get the type of the image to load, from TLV data */ res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGTYPE, &tlv_value, &length); if (res) return res; if (length != (sizeof(*img_type) * num_img)) return TEE_ERROR_BAD_PARAMETERS; *img_type = tlv_value[idx]; return TEE_SUCCESS; } static TEE_Result get_tlv_images_size(struct remoteproc_context *ctx, uint8_t num_img, uint8_t idx, uint32_t *img_size) { TEE_Result res = TEE_ERROR_GENERIC; uint8_t *tlv_value = NULL; uint32_t tlv_v = 0; size_t length = 0; /* Get the size of the image to load, from TLV data */ res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGSIZE, &tlv_value, &length); if (res) return res; if (length != (sizeof(*img_size) * num_img)) return TEE_ERROR_BAD_PARAMETERS; memcpy(&tlv_v, &tlv_value[sizeof(*img_size) * idx], sizeof(tlv_v)); *img_size = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v); return TEE_SUCCESS; } static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src, uint32_t size, uint32_t da, uint32_t mem_size, uint8_t **hash) { struct remoteproc_segment *peh = NULL; unsigned int i = 0; unsigned int nb_entry = ctx->nb_segment; peh = (void *)(ctx->hash_table); for (i = 0; i < nb_entry; peh++, i++) { if (peh->phdr.p_paddr != da) continue; /* * Segment metadata are read from a non-secure memory. * Validate them using hash table data stored in secure memory. */ if (peh->phdr.p_type != PT_LOAD) return TEE_ERROR_BAD_PARAMETERS; if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size) return TEE_ERROR_BAD_PARAMETERS; if (src < ctx->fw_img || src > (ctx->fw_img + ctx->fw_img_sz) || (src + peh->phdr.p_filesz) > (ctx->fw_img + ctx->fw_img_sz)) return TEE_ERROR_BAD_PARAMETERS; *hash = peh->hash; return TEE_SUCCESS; } return TEE_ERROR_NO_DATA; } static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size, uint32_t da, uint32_t mem_size, void *priv) { struct remoteproc_context *ctx = priv; uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT); TEE_Param params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_ERROR_GENERIC; uint8_t *hash = NULL; /* * Invoke platform remoteproc PTA to load the segment in remote * processor memory which is not mapped in the TA space. */ DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size, mem_size); res = get_segment_hash(ctx, src, size, da, mem_size, &hash); if (res) return res; params[0].value.a = ctx->rproc_id; params[1].memref.buffer = src; params[1].memref.size = size; params[2].value.a = da; params[3].memref.buffer = hash; params[3].memref.size = TEE_SHA256_HASH_SIZE; if (size) { res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_LOAD_SEGMENT_SHA256, param_types, params, NULL); if (res != TEE_SUCCESS) { EMSG("Fails to load segment, res = 0x%#"PRIx32, res); return res; } } /* Fill the rest of the memory with 0 */ if (size < mem_size) { param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT); params[1].value.a = da + size; params[2].value.a = mem_size - size; params[3].value.a = 0; res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_SET_MEMORY, param_types, params, NULL); if (res != TEE_SUCCESS) EMSG("Fails to clear segment, res = %#"PRIx32, res); } return res; } static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx) { TEE_Result res = TEE_ERROR_GENERIC; unsigned int num_img = 0; unsigned int i = 0; uint8_t img_type = REMOTEPROC_INVALID_TYPE; uint32_t img_size = 0; uint8_t *tlv = NULL; int32_t offset = 0; size_t length = 0; paddr_t rsc_pa = 0; size_t rsc_size = 0; res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_sz); if (res) { EMSG("Failed to parse firmware, res = %#"PRIx32, res); return res; } res = get_hash_table(ctx); if (res) return res; /* Get the number of firmware images to load */ res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_NUM_IMG, &tlv, &length); if (res) goto out; if (length != sizeof(uint8_t)) { res = TEE_ERROR_BAD_FORMAT; goto out; } num_img = *tlv; if (!num_img) { res = TEE_ERROR_NO_DATA; goto out; } /* * Initialize resource table with zero. These values will be returned if * no optional resource table is found in images. */ ctx->rsc_pa = 0; ctx->rsc_size = 0; for (i = 0; i < num_img; i++) { res = get_tlv_images_type(ctx, num_img, i, &img_type); if (res) goto out; if (img_type != REMOTEPROC_ELF_TYPE) { res = TEE_ERROR_BAD_FORMAT; goto out; } res = get_tlv_images_size(ctx, num_img, i, &img_size); if (res) goto out; res = e32_parser_load_elf_image(ctx->fw_img + offset, img_size, remoteproc_load_segment, ctx); if (res) goto out; /* Take opportunity to get the resource table address */ res = remoteproc_parse_rsc_table(ctx, ctx->fw_img + offset, img_size, &rsc_pa, &rsc_size); if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA) goto out; if (res == TEE_SUCCESS) { /* * Only one resource table is supported, check that no * other one has been declared in a previously loaded * firmware. */ if (ctx->rsc_pa || ctx->rsc_size) { EMSG("More than one resource table found"); res = TEE_ERROR_BAD_FORMAT; goto out; } ctx->rsc_pa = rsc_pa; ctx->rsc_size = rsc_size; } else { /* * No resource table found. Force to TEE_SUCCESS as the * resource table is optional. */ res = TEE_SUCCESS; } offset += img_size; } out: /* Should we clean-up the memories in case of fail ? */ TEE_Free(ctx->hash_table); ctx->hash_table = NULL; return res; } static TEE_Result remoteproc_load_fw(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct remoteproc_context *ctx = NULL; uint32_t rproc_id = params[0].value.a; TEE_Result res = TEE_ERROR_GENERIC; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; ctx = remoteproc_find_firmware(rproc_id); if (!ctx) ctx = remoteproc_add_firmware(rproc_id); if (!ctx) return TEE_ERROR_OUT_OF_MEMORY; /* The firmware is already loaded, do nothing */ if (ctx->state == REMOTEPROC_LOADED) return TEE_SUCCESS; if (ctx->state != REMOTEPROC_OFF) return TEE_ERROR_BAD_STATE; if (!params[1].memref.buffer || !params[1].memref.size) return TEE_ERROR_BAD_PARAMETERS; DMSG("Got base addr: %p size %#zx", params[1].memref.buffer, params[1].memref.size); res = remoteproc_verify_firmware(ctx, params[1].memref.buffer, params[1].memref.size); if (res) { EMSG("Can't Authenticate the firmware (res = %#"PRIx32")", res); goto out; } res = remoteproc_load_elf(ctx); if (res) goto out; ctx->state = REMOTEPROC_LOADED; out: /* Clear reference to firmware image from shared memory */ ctx->fw_img = NULL; ctx->fw_img_sz = 0; ctx->nb_segment = 0; /* Free allocated memories */ TEE_Free(ctx->sec_cpy); ctx->sec_cpy = NULL; return res; } static TEE_Result remoteproc_start_fw(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct remoteproc_context *ctx = NULL; uint32_t rproc_id = params[0].value.a; TEE_Result res = TEE_ERROR_GENERIC; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; ctx = remoteproc_find_firmware(rproc_id); if (!ctx) return TEE_ERROR_BAD_PARAMETERS; switch (ctx->state) { case REMOTEPROC_OFF: res = TEE_ERROR_BAD_STATE; break; case REMOTEPROC_STARTED: res = TEE_SUCCESS; break; case REMOTEPROC_LOADED: res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_FIRMWARE_START, pt, params, NULL); if (res == TEE_SUCCESS) ctx->state = REMOTEPROC_STARTED; break; default: res = TEE_ERROR_BAD_STATE; } return res; } static TEE_Result remoteproc_stop_fw(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); struct remoteproc_context *ctx = NULL; uint32_t rproc_id = params[0].value.a; TEE_Result res = TEE_ERROR_GENERIC; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; ctx = remoteproc_find_firmware(rproc_id); if (!ctx) return TEE_ERROR_BAD_PARAMETERS; switch (ctx->state) { case REMOTEPROC_LOADED: res = TEE_ERROR_BAD_STATE; break; case REMOTEPROC_OFF: res = TEE_SUCCESS; break; case REMOTEPROC_STARTED: res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, PTA_RPROC_FIRMWARE_STOP, pt, params, NULL); if (res == TEE_SUCCESS) ctx->state = REMOTEPROC_OFF; break; default: res = TEE_ERROR_BAD_STATE; } return res; } static TEE_Result remoteproc_get_rsc_table(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE); struct remoteproc_context *ctx = NULL; if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; ctx = remoteproc_find_firmware(params[0].value.a); if (!ctx) return TEE_ERROR_BAD_PARAMETERS; if (ctx->state == REMOTEPROC_OFF) return TEE_ERROR_BAD_STATE; reg_pair_from_64((uint64_t)ctx->rsc_pa, ¶ms[1].value.b, ¶ms[1].value.a); reg_pair_from_64((uint64_t)ctx->rsc_size, ¶ms[2].value.b, ¶ms[2].value.a); return TEE_SUCCESS; } TEE_Result TA_CreateEntryPoint(void) { return TEE_SUCCESS; } void TA_DestroyEntryPoint(void) { } /* * TA_OpenSessionEntryPoint: open a TA session associated to a remote processor * to manage. * * [in] params[0].value.a: Unique 32bit remote processor identifier */ TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], void **sess __unused) { static const TEE_UUID uuid = PTA_RPROC_UUID; TEE_Result res = TEE_ERROR_GENERIC; const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); if (pt != exp_pt) return TEE_ERROR_BAD_PARAMETERS; if (!session_refcount) { res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, pt, params, &pta_session, NULL); if (res) return res; } session_refcount++; return TEE_SUCCESS; } void TA_CloseSessionEntryPoint(void *sess __unused) { session_refcount--; if (!session_refcount) TEE_CloseTASession(pta_session); } TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd_id) { case TA_RPROC_CMD_LOAD_FW: return remoteproc_load_fw(pt, params); case TA_RPROC_CMD_START_FW: return remoteproc_start_fw(pt, params); case TA_RPROC_CMD_STOP_FW: return remoteproc_stop_fw(pt, params); case TA_RPROC_CMD_GET_RSC_TABLE: return remoteproc_get_rsc_table(pt, params); case TA_RPROC_CMD_GET_COREDUMP: return TEE_ERROR_NOT_IMPLEMENTED; default: return TEE_ERROR_BAD_PARAMETERS; } } optee_os-4.3.0/ta/remoteproc/src/sub.mk000066400000000000000000000000631464416617300200420ustar00rootroot00000000000000srcs-y += remoteproc_core.c srcs-y += elf_parser.c optee_os-4.3.0/ta/remoteproc/src/user_ta_header_defines.h000066400000000000000000000013121464416617300235360ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2023 STMicroelectronics */ #ifndef USER_TA_HEADER_DEFINES_H #define USER_TA_HEADER_DEFINES_H #include #define TA_UUID TA_REMOTEPROC_UUID #define TA_FLAGS (TA_FLAG_DEVICE_ENUM | \ TA_FLAG_SINGLE_INSTANCE | \ TA_FLAG_INSTANCE_KEEP_ALIVE) /* Provisioned stack size */ #define TA_STACK_SIZE (4 * 1024) /* Provisioned heap size for TEE_Malloc() and friends */ #define TA_DATA_SIZE CFG_REMOTEPROC_TA_HEAP_SIZE /* The gpd.ta.version property */ #define TA_VERSION "1.0" /* The gpd.ta.description property */ #define TA_DESCRIPTION "remote processor firmware management" #endif /* USER_TA_HEADER_DEFINES_H */ optee_os-4.3.0/ta/remoteproc/sub.mk000066400000000000000000000001051464416617300172500ustar00rootroot00000000000000global-incdirs-y += include global-incdirs-y += src subdirs-y += src optee_os-4.3.0/ta/remoteproc/user_ta.mk000066400000000000000000000002411464416617300201220ustar00rootroot00000000000000user-ta-uuid := 80a4c275-0a47-4905-8285-1486a9771a08 # REMOTEPROC TA heap size can be customized if 4kB is not enough CFG_REMOTEPROC_TA_HEAP_SIZE ?= (4 * 1024) optee_os-4.3.0/ta/ta.mk000066400000000000000000000161451464416617300147170ustar00rootroot00000000000000include mk/cleanvars.mk # Set current submodule (used for module specific flags compile result etc) sm := $(ta-target) sm-$(sm) := y # Setup compiler for this sub module COMPILER_$(sm) ?= $(COMPILER) include mk/$(COMPILER_$(sm)).mk # # Config flags from mk/config.mk # ta-stackp-cflags-$(CFG_TA_STACK_PROTECTOR) := -fstack-protector ta-stackp-cflags-$(CFG_TA_STACK_PROTECTOR_STRONG) := -fstack-protector-strong ta-stackp-cflags-$(CFG_TA_STACK_PROTECTOR_ALL) := -fstack-protector-all $(sm)-platform-cflags += $(ta-stackp-cflags-y) ifeq ($(CFG_TA_MBEDTLS_SELF_TEST),y) $(sm)-platform-cppflags += -DMBEDTLS_SELF_TEST endif ifeq ($(CFG_TEE_TA_MALLOC_DEBUG),y) # Build malloc debug code into libutils: (mdbg_malloc(), mdbg_free(), # mdbg_check(), etc.). $(sm)-platform-cppflags += -DENABLE_MDBG=1 endif # Config variables to be explicitly exported to the dev kit conf.mk ta-mk-file-export-vars-$(sm) += CFG_TA_FLOAT_SUPPORT ta-mk-file-export-vars-$(sm) += CFG_CACHE_API ta-mk-file-export-vars-$(sm) += CFG_SECURE_DATA_PATH ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS_SELF_TEST ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS_MPI ta-mk-file-export-vars-$(sm) += CFG_SYSTEM_PTA ta-mk-file-export-vars-$(sm) += CFG_FTRACE_SUPPORT ta-mk-file-export-vars-$(sm) += CFG_UNWIND ta-mk-file-export-vars-$(sm) += CFG_TA_MCOUNT ta-mk-file-export-vars-$(sm) += CFG_TA_BTI ta-mk-file-export-vars-$(sm) += CFG_TA_PAUTH ta-mk-file-export-vars-$(sm) += CFG_CORE_TPM_EVENT_LOG ta-mk-file-export-add-$(sm) += CFG_TEE_TA_LOG_LEVEL ?= $(CFG_TEE_TA_LOG_LEVEL)_nl_ ta-mk-file-export-vars-$(sm) += CFG_TA_BGET_TEST ta-mk-file-export-vars-$(sm) += CFG_ATTESTATION_PTA ta-mk-file-export-vars-$(sm) += CFG_MEMTAG # Expand platform flags here as $(sm) will change if we have several TA # targets. Platform flags should not change after inclusion of ta/ta.mk. cppflags$(sm) := $(platform-cppflags) $($(sm)-platform-cppflags) cflags$(sm) := $(platform-cflags) $($(sm)-platform-cflags) aflags$(sm) := $(platform-aflags) $($(sm)-platform-aflags) # Changes to cppflags$(sm) will only affect how TA dev kit libraries are # compiled, these flags are not propagated to the TA cppflags$(sm) += -include $(conf-file) cppflags$(sm) += -DTRACE_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) ifeq ($(ta-target),ta_arm32) arm32-user-sysreg-txt = lib/libutee/arch/arm/arm32_user_sysreg.txt arm32-user-sysregs-$(arm32-user-sysreg-txt)-h := arm32_user_sysreg.h arm32-user-sysregs += $(arm32-user-sysreg-txt) arm32-user-sysregs-out := $(out-dir)/include/generated define process-arm32-user-sysreg FORCE-GENSRC$(sm): $$(arm32-user-sysregs-out)/$$(arm32-user-sysregs-$(1)-h) cleanfiles := $$(cleanfiles) \ $$(arm32-user-sysregs-out)/$$(arm32-user-sysregs-$(1)-h) $$(arm32-user-sysregs-out)/$$(arm32-user-sysregs-$(1)-h): \ $(1) scripts/arm32_sysreg.py @$(cmd-echo-silent) ' GEN $$@' $(q)mkdir -p $$(dir $$@) $(q)$(PYTHON3) scripts/arm32_sysreg.py --guard __$$(arm32-user-sysregs-$(1)-h) \ < $$< > $$@ endef #process-arm32-user-sysreg $(foreach sr, $(arm32-user-sysregs), \ $(eval $(call process-arm32-user-sysreg,$(sr)))) cppflags$(sm) += -I$(arm32-user-sysregs-out) endif base-prefix := $(sm)- libname = utils libdir = lib/libutils libuuid = 71855bba-6055-4293-a63f-b0963a737360 include mk/lib.mk libname = mbedtls libdir = lib/libmbedtls libuuid = 87bb6ae8-4b1d-49fe-9986-2b966132c309 libl = utils include mk/lib.mk ta-mk-file-export-vars-$(sm) += CFG_TA_MBEDTLS libname = utee libdir = lib/libutee libuuid = 4b3d937e-d57e-418b-8673-1c04f2420226 libl = mbedtls utils include mk/lib.mk libname = dl libdir = lib/libdl libuuid = be807bbd-81e1-4dc4-bd99-3d363f240ece libl = utee utils include mk/lib.mk base-prefix := incdirs-host := $(filter-out lib/libutils%, $(incdirs$(sm))) incfiles-extra-host := lib/libutils/ext/include/compiler.h incfiles-extra-host += lib/libutils/ext/include/util.h incfiles-extra-host += lib/libutils/ext/include/types_ext.h incfiles-extra-host += $(conf-file) incfiles-extra-host += $(conf-mk-file) incfiles-extra-host += $(conf-cmake-file) incfiles-extra-host += core/include/tee/tee_fs_key_manager.h incfiles-extra-host += core/include/tee/fs_htree.h incfiles-extra-host += core/include/signed_hdr.h ifeq ($(ta-target),ta_arm32) incfiles-extra-host += $(out-dir)/include/generated/arm32_user_sysreg.h endif # # Copy lib files and exported headers from each lib # define copy-file $2/$$(notdir $1): $1 @set -e; \ mkdir -p $$(dir $$@) ; \ $(cmd-echo-silent) ' INSTALL $$@' ; \ cp -P $$< $$@ cleanfiles += $2/$$(notdir $1) ta_dev_kit: $2/$$(notdir $1) ta_dev_kit-files += $2/$$(notdir $1) ta_dev_kit-files-$3 += $2/$$(notdir $1) endef # Copy the .a files $(foreach f, $(libfiles), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/lib,lib))) # Copy .mk files ta-mkfiles = mk/compile.mk mk/subdir.mk mk/gcc.mk mk/clang.mk mk/cleandirs.mk \ mk/cc-option.mk mk/macros.mk \ ta/link.mk ta/link_shlib.mk \ ta/mk/ta_dev_kit.mk $(foreach f, $(ta-mkfiles), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/mk))) # Copy the .h files for TAs define copy-incdir sf := $(subst $1/, , $(shell find $1 -name "*.[hS]")) $$(foreach h, $$(sf), $$(eval $$(call copy-file, $1/$$(h), \ $$(patsubst %/,%,$$(subst /./,/,$2/$$(dir $$(h)))),$3))) endef $(foreach d, $(incdirs$(sm)), \ $(eval $(call copy-incdir,$(d),$(out-dir)/export-$(sm)/include,include))) # Copy the .h files needed by host $(foreach d, $(incdirs-host), \ $(eval $(call copy-incdir, $(d), $(out-dir)/export-$(sm)/host_include))) $(foreach f, $(incfiles-extra-host), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/host_include))) # Copy the src files ta-srcfiles = ta/user_ta_header.c ta/arch/$(ARCH)/ta.ld.S ifeq ($(ta-target),ta_arm32) ta-srcfiles += ta/arch/$(ARCH)/ta_entry_a32.S endif $(foreach f, $(ta-srcfiles), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/src))) # Copy keys ta-keys := $(TA_SIGN_KEY) # default_ta.pem is a symlink to default.pem, for backwards compatibility. # If default_ta.pem is used, copy both files. ifeq ($(TA_SIGN_KEY),keys/default_ta.pem) ta-keys += keys/default.pem endif $(foreach f, $(ta-keys), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/keys))) # Copy the scripts ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py \ scripts/sign_rproc_fw.py scripts/ftrace_format.py $(foreach f, $(ta-scripts), \ $(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/scripts))) # Create config file conf-mk-file-export := $(out-dir)/export-$(sm)/mk/conf.mk sm-$(conf-mk-file-export) := $(sm) define mk-file-export .PHONY: $(conf-mk-file-export) $(conf-mk-file-export): @$$(cmd-echo-silent) ' CHK ' $$@ $(q)mkdir -p $$(dir $$@) $(q)echo sm := $$(sm-$(conf-mk-file-export)) > $$@.tmp $(q)echo sm-$$(sm-$(conf-mk-file-export)) := y >> $$@.tmp $(q)($$(foreach v, $$(ta-mk-file-export-vars-$$(sm-$(conf-mk-file-export))), \ $$(if $$($$(v)),echo $$(v) := $$($$(v));,))) >> $$@.tmp $(q)echo '$$(ta-mk-file-export-add-$$(sm-$(conf-mk-file-export)))' | sed 's/_nl_ */\n/g' >> $$@.tmp $(q)$(call mv-if-changed,$$@.tmp,$$@) endef $(eval $(mk-file-export)) cleanfiles := $(cleanfiles) $(conf-mk-file-export) ta_dev_kit: $(conf-mk-file-export) all: ta_dev_kit optee_os-4.3.0/ta/trusted_keys/000077500000000000000000000000001464416617300165005ustar00rootroot00000000000000optee_os-4.3.0/ta/trusted_keys/entry.c000066400000000000000000000205751464416617300200160ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (C) 2019-2020, Linaro Limited */ #include #include #include #include #include #include #include #include #define IV_SIZE 16 #define TAG_SIZE 16 #define MAX_BUF_SIZE 512 /* * Acronym: * * TK - Trusted Key */ struct tk_blob_hdr { uint8_t reserved; uint8_t iv[IV_SIZE]; uint8_t tag[TAG_SIZE]; uint8_t enc_key[]; }; static TEE_Result get_random(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { uint8_t *rng_buf = NULL; DMSG("Invoked TA_CMD_GET_RANDOM"); if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; if (!params[0].memref.buffer || !params[0].memref.size) return TEE_ERROR_BAD_PARAMETERS; rng_buf = TEE_Malloc(params[0].memref.size, TEE_MALLOC_FILL_ZERO); if (!rng_buf) return TEE_ERROR_OUT_OF_MEMORY; TEE_GenerateRandom(rng_buf, params[0].memref.size); memcpy(params[0].memref.buffer, rng_buf, params[0].memref.size); memzero_explicit(rng_buf, params[0].memref.size); TEE_Free(rng_buf); return TEE_SUCCESS; } static TEE_Result derive_unique_key(uint8_t *key, uint16_t key_size, uint8_t *extra, uint16_t extra_size) { TEE_TASessionHandle sess = TEE_HANDLE_NULL; TEE_Param params[TEE_NUM_PARAMS] = { }; TEE_Result res = TEE_ERROR_GENERIC; uint32_t ret_orig = 0; uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); res = TEE_OpenTASession(&(const TEE_UUID)PTA_SYSTEM_UUID, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, &ret_orig); if (res) return res; if (extra && extra_size) { params[0].memref.buffer = extra; params[0].memref.size = extra_size; } params[1].memref.buffer = key; params[1].memref.size = key_size; res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, PTA_SYSTEM_DERIVE_TA_UNIQUE_KEY, param_types, params, &ret_orig); TEE_CloseTASession(sess); return res; } static TEE_Result huk_ae_encrypt(TEE_OperationHandle crypto_op, uint8_t *in, size_t in_sz, uint8_t *out, size_t *out_sz) { TEE_Result res = TEE_ERROR_GENERIC; struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)out; uint8_t iv[IV_SIZE] = { 0 }; size_t enc_key_len = in_sz; size_t tag_len = TAG_SIZE; hdr->reserved = 0; TEE_GenerateRandom(iv, IV_SIZE); memcpy(hdr->iv, iv, IV_SIZE); res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0); if (res) return res; res = TEE_AEEncryptFinal(crypto_op, in, in_sz, hdr->enc_key, &enc_key_len, hdr->tag, &tag_len); if (res || tag_len != TAG_SIZE) return TEE_ERROR_SECURITY; if (ADD_OVERFLOW(enc_key_len, sizeof(*hdr), out_sz)) return TEE_ERROR_SECURITY; return res; } static TEE_Result huk_ae_decrypt(TEE_OperationHandle crypto_op, uint8_t *in, size_t in_sz, uint8_t *out, size_t *out_sz) { TEE_Result res = TEE_ERROR_GENERIC; struct tk_blob_hdr *hdr = (struct tk_blob_hdr *)in; uint8_t tag[TAG_SIZE] = { 0 }; size_t enc_key_len = 0; if (SUB_OVERFLOW(in_sz, sizeof(*hdr), &enc_key_len)) return TEE_ERROR_SECURITY; res = TEE_AEInit(crypto_op, hdr->iv, IV_SIZE, TAG_SIZE * 8, 0, 0); if (res) return res; memcpy(tag, hdr->tag, TAG_SIZE); res = TEE_AEDecryptFinal(crypto_op, hdr->enc_key, enc_key_len, out, out_sz, tag, TAG_SIZE); if (res) res = TEE_ERROR_SECURITY; return res; } static TEE_Result huk_crypt(TEE_OperationMode mode, uint8_t *in, size_t in_sz, uint8_t *out, size_t *out_sz) { TEE_Result res = TEE_ERROR_GENERIC; TEE_OperationHandle crypto_op = TEE_HANDLE_NULL; TEE_ObjectHandle hkey = TEE_HANDLE_NULL; uint8_t huk_key[TA_DERIVED_KEY_MAX_SIZE] = { }; TEE_Attribute attr = { }; res = TEE_AllocateOperation(&crypto_op, TEE_ALG_AES_GCM, mode, sizeof(huk_key) * 8); if (res) return res; res = derive_unique_key(huk_key, sizeof(huk_key), NULL, 0); if (res) { EMSG("derive_unique_key failed: returned %#"PRIx32, res); goto out_op; } res = TEE_AllocateTransientObject(TEE_TYPE_AES, sizeof(huk_key) * 8, &hkey); if (res) goto out_op; attr.attributeID = TEE_ATTR_SECRET_VALUE; attr.content.ref.buffer = huk_key; attr.content.ref.length = sizeof(huk_key); res = TEE_PopulateTransientObject(hkey, &attr, 1); if (res) goto out_key; res = TEE_SetOperationKey(crypto_op, hkey); if (res) goto out_key; if (mode == TEE_MODE_ENCRYPT) { res = huk_ae_encrypt(crypto_op, in, in_sz, out, out_sz); if (res) EMSG("huk_AE_encrypt failed: returned %#"PRIx32, res); } else if (mode == TEE_MODE_DECRYPT) { res = huk_ae_decrypt(crypto_op, in, in_sz, out, out_sz); if (res) EMSG("huk_AE_decrypt failed: returned %#"PRIx32, res); } else { TEE_Panic(0); } out_key: TEE_FreeTransientObject(hkey); out_op: TEE_FreeOperation(crypto_op); memzero_explicit(huk_key, sizeof(huk_key)); return res; } static TEE_Result seal_trusted_key(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; uint8_t *in = NULL; size_t in_sz = 0; uint8_t *out = NULL; size_t out_sz = 0; DMSG("Invoked TA_CMD_SEAL"); if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; in = params[0].memref.buffer; in_sz = params[0].memref.size; out = params[1].memref.buffer; out_sz = params[1].memref.size; if (!in || !in_sz || in_sz > MAX_BUF_SIZE) return TEE_ERROR_BAD_PARAMETERS; if ((!out && out_sz) || (out && !IS_ALIGNED_WITH_TYPE(out, struct tk_blob_hdr)) || out_sz > MAX_BUF_SIZE) return TEE_ERROR_BAD_PARAMETERS; if ((in_sz + sizeof(struct tk_blob_hdr)) > out_sz) { params[1].memref.size = in_sz + sizeof(struct tk_blob_hdr); return TEE_ERROR_SHORT_BUFFER; } res = huk_crypt(TEE_MODE_ENCRYPT, in, in_sz, out, &out_sz); if (res == TEE_SUCCESS) { assert(out_sz == in_sz + sizeof(struct tk_blob_hdr)); params[1].memref.size = out_sz; } return res; } static TEE_Result unseal_trusted_key(uint32_t types, TEE_Param params[TEE_NUM_PARAMS]) { TEE_Result res = TEE_SUCCESS; uint8_t *in = NULL; size_t in_sz = 0; uint8_t *out = NULL; size_t out_sz = 0; DMSG("Invoked TA_CMD_UNSEAL"); if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE)) return TEE_ERROR_BAD_PARAMETERS; in = params[0].memref.buffer; in_sz = params[0].memref.size; out = params[1].memref.buffer; out_sz = params[1].memref.size; if (!in || !IS_ALIGNED_WITH_TYPE(in, struct tk_blob_hdr) || in_sz <= sizeof(struct tk_blob_hdr) || in_sz > MAX_BUF_SIZE) return TEE_ERROR_BAD_PARAMETERS; if ((!out && out_sz) || out_sz > MAX_BUF_SIZE) return TEE_ERROR_BAD_PARAMETERS; if (in_sz > (out_sz + sizeof(struct tk_blob_hdr))) { params[1].memref.size = in_sz - sizeof(struct tk_blob_hdr); return TEE_ERROR_SHORT_BUFFER; } res = huk_crypt(TEE_MODE_DECRYPT, in, in_sz, out, &out_sz); if (res == TEE_SUCCESS) { assert(out_sz == in_sz - sizeof(struct tk_blob_hdr)); params[1].memref.size = out_sz; } return res; } TEE_Result TA_CreateEntryPoint(void) { return TEE_SUCCESS; } void TA_DestroyEntryPoint(void) { } TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, TEE_Param params[TEE_NUM_PARAMS] __unused, void **session __unused) { TEE_Result res = TEE_ERROR_GENERIC; TEE_PropSetHandle h = TEE_HANDLE_NULL; TEE_Identity id = { }; res = TEE_AllocatePropertyEnumerator(&h); if (res) goto out; TEE_StartPropertyEnumerator(h, TEE_PROPSET_CURRENT_CLIENT); res = TEE_GetPropertyAsIdentity(h, NULL, &id); if (res) goto out; if (id.login != TEE_LOGIN_REE_KERNEL) res = TEE_ERROR_ACCESS_DENIED; out: if (h) TEE_FreePropertyEnumerator(h); return res; } void TA_CloseSessionEntryPoint(void *sess __unused) { } TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { switch (cmd) { case TA_CMD_GET_RANDOM: return get_random(pt, params); case TA_CMD_SEAL: return seal_trusted_key(pt, params); case TA_CMD_UNSEAL: return unseal_trusted_key(pt, params); default: EMSG("Command ID %#"PRIx32" is not supported", cmd); return TEE_ERROR_NOT_SUPPORTED; } } optee_os-4.3.0/ta/trusted_keys/include/000077500000000000000000000000001464416617300201235ustar00rootroot00000000000000optee_os-4.3.0/ta/trusted_keys/include/trusted_keys.h000066400000000000000000000013601464416617300230210ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (C) 2019-2020, Linaro Limited */ #ifndef TRUSTED_KEYS_H #define TRUSTED_KEYS_H #define TRUSTED_KEYS_UUID { 0xf04a0fe7, 0x1f5d, 0x4b9b, \ { 0xab, 0xf7, 0x61, 0x9b, 0x85, 0xb4, 0xce, 0x8c } } /* * Get random data for symmetric key * * [out] memref[0] Random data */ #define TA_CMD_GET_RANDOM 0x0 /* * Seal trusted key using hardware unique key * * [in] memref[0] Plain key * [out] memref[1] Sealed key datablob */ #define TA_CMD_SEAL 0x1 /* * Unseal trusted key using hardware unique key * * [in] memref[0] Sealed key datablob * [out] memref[1] Plain key */ #define TA_CMD_UNSEAL 0x2 #endif /* TRUSTED_KEYS_H */ optee_os-4.3.0/ta/trusted_keys/sub.mk000066400000000000000000000001041464416617300176150ustar00rootroot00000000000000global-incdirs-y += include global-incdirs-y += . srcs-y += entry.c optee_os-4.3.0/ta/trusted_keys/user_ta.mk000066400000000000000000000000651464416617300204740ustar00rootroot00000000000000user-ta-uuid := f04a0fe7-1f5d-4b9b-abf7-619b85b4ce8c optee_os-4.3.0/ta/trusted_keys/user_ta_header_defines.h000066400000000000000000000006651464416617300233270ustar00rootroot00000000000000/* SPDX-License-Identifier: BSD-2-Clause */ /* * Copyright (c) 2020, Linaro Limited */ #ifndef USER_TA_HEADER_DEFINES_H #define USER_TA_HEADER_DEFINES_H #include #define TA_UUID TRUSTED_KEYS_UUID #define TA_FLAGS (TA_FLAG_SINGLE_INSTANCE | \ TA_FLAG_MULTI_SESSION | \ TA_FLAG_DEVICE_ENUM) #define TA_STACK_SIZE (4 * 1024) #define TA_DATA_SIZE (16 * 1024) #endif /*USER_TA_HEADER_DEFINES_H*/ optee_os-4.3.0/ta/user_ta_header.c000066400000000000000000000134141464416617300170740ustar00rootroot00000000000000// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include #include #include #include extern void *__stack_chk_guard; int trace_level = TRACE_LEVEL; const char trace_ext_prefix[] = "TA"; #ifndef TA_VERSION #define TA_VERSION "Undefined version" #endif #ifndef TA_DESCRIPTION #define TA_DESCRIPTION "Undefined description" #endif /* exprted to user_ta_header.c, built within TA */ struct utee_params; #ifdef ARM32 #define _C_FUNCTION(name) name##_c #else #define _C_FUNCTION(name) name #endif /* ARM32 */ /* From libutee */ TEE_Result __utee_entry(unsigned long func, unsigned long session_id, struct utee_params *up, unsigned long cmd_id); void __noreturn _C_FUNCTION(__ta_entry)(unsigned long func, unsigned long session_id, struct utee_params *up, unsigned long cmd_id); void __noreturn _C_FUNCTION(__ta_entry)(unsigned long func, unsigned long session_id, struct utee_params *up, unsigned long cmd_id) { static bool stack_canary_inited; TEE_Result res = TEE_ERROR_GENERIC; if (IS_ENABLED(_CFG_TA_STACK_PROTECTOR) && !stack_canary_inited) { uintptr_t canary = 0; res = _utee_cryp_random_number_generate(&canary, sizeof(canary)); if (res != TEE_SUCCESS) _utee_return(res); /* Leave null byte in canary to prevent string base exploit */ canary &= ~0xffUL; __stack_chk_guard = (void *)canary; stack_canary_inited = true; } res = __utee_entry(func, session_id, up, cmd_id); #if defined(CFG_FTRACE_SUPPORT) /* * __ta_entry is the first TA API called from TEE core. As it being * __noreturn API, we need to call ftrace_return in this API just * before _utee_return syscall to get proper ftrace call graph. */ ftrace_return(); #endif _utee_return(res); } /* * According to GP Internal API, TA_STACK_SIZE corresponds to the stack * size used by the TA code itself and does not include stack space * possibly used by the Trusted Core Framework. * Hence, stack_size which is the size of the stack to use, * must be enlarged * It has been set to 2048 to include trace framework and invoke commands */ #define TA_FRAMEWORK_STACK_SIZE 2048 const struct ta_head ta_head __section(".ta_head") = { /* UUID, unique to each TA */ .uuid = TA_UUID, /* * According to GP Internal API, TA_FRAMEWORK_STACK_SIZE corresponds to * the stack size used by the TA code itself and does not include stack * space possibly used by the Trusted Core Framework. * Hence, stack_size which is the size of the stack to use, * must be enlarged */ .stack_size = TA_STACK_SIZE + TA_FRAMEWORK_STACK_SIZE, .flags = TA_FLAGS, /* * The TA entry doesn't go via this field any longer, to be able to * reliably check that an old TA isn't loaded set this field to a * fixed value. */ .depr_entry = UINT64_MAX, }; /* Keeping the heap in bss */ #if TA_DATA_SIZE < MALLOC_INITIAL_POOL_MIN_SIZE #error TA_DATA_SIZE too small #endif uint8_t ta_heap[TA_DATA_SIZE]; const size_t ta_heap_size = sizeof(ta_heap); #ifndef TA_NO_SHARE_DATA_SIZE #define TA_NO_SHARE_DATA_SIZE 0 #endif #if TA_NO_SHARE_DATA_SIZE && \ TA_NO_SHARE_DATA_SIZE < MALLOC_INITIAL_POOL_MIN_SIZE #error TA_NO_SHARE_DATA_SIZE too small #endif uint8_t __ta_no_share_heap[TA_NO_SHARE_DATA_SIZE]; const size_t __ta_no_share_heap_size = sizeof(__ta_no_share_heap); const struct user_ta_property ta_props[] = { {TA_PROP_STR_SINGLE_INSTANCE, USER_TA_PROP_TYPE_BOOL, &(const bool){(TA_FLAGS & TA_FLAG_SINGLE_INSTANCE) != 0}}, {TA_PROP_STR_MULTI_SESSION, USER_TA_PROP_TYPE_BOOL, &(const bool){(TA_FLAGS & TA_FLAG_MULTI_SESSION) != 0}}, {TA_PROP_STR_KEEP_ALIVE, USER_TA_PROP_TYPE_BOOL, &(const bool){(TA_FLAGS & TA_FLAG_INSTANCE_KEEP_ALIVE) != 0}}, {TA_PROP_STR_DATA_SIZE, USER_TA_PROP_TYPE_U32, &(const uint32_t){TA_DATA_SIZE}}, {TA_PROP_STR_STACK_SIZE, USER_TA_PROP_TYPE_U32, &(const uint32_t){TA_STACK_SIZE}}, {TA_PROP_STR_VERSION, USER_TA_PROP_TYPE_STRING, TA_VERSION}, {TA_PROP_STR_DESCRIPTION, USER_TA_PROP_TYPE_STRING, TA_DESCRIPTION}, /* Only little-endian supported */ {TA_PROP_STR_ENDIAN, USER_TA_PROP_TYPE_U32, &(const uint32_t){0}}, {TA_PROP_STR_DOES_NOT_CLOSE_HANDLE_ON_CORRUPT_OBJECT, USER_TA_PROP_TYPE_BOOL, &(const bool){TA_FLAGS & TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT}}, /* * Extended propietary properties, name of properties must not begin with * "gpd." */ #ifdef TA_CURRENT_TA_EXT_PROPERTIES TA_CURRENT_TA_EXT_PROPERTIES #endif }; const size_t ta_num_props = sizeof(ta_props) / sizeof(ta_props[0]); #ifdef CFG_FTRACE_SUPPORT struct __ftrace_info __ftrace_info = { #ifdef __ILP32__ .buf_start.ptr32 = { .lo = (uint32_t)&__ftrace_buf_start }, .buf_end.ptr32 = { .lo = (uint32_t)__ftrace_buf_end }, .ret_ptr.ptr32 = { .lo = (uint32_t)&__ftrace_return }, #else .buf_start.ptr64 = (uint64_t)&__ftrace_buf_start, .buf_end.ptr64 = (uint64_t)__ftrace_buf_end, .ret_ptr.ptr64 = (uint64_t)&__ftrace_return, #endif }; #endif int tahead_get_trace_level(void) { /* * Store trace level in TA head structure, as ta_head.prop_tracelevel */ return TRACE_LEVEL; } #if __OPTEE_CORE_API_COMPAT_1_1 #undef TA_OpenSessionEntryPoint #undef TA_InvokeCommandEntryPoint #undef TEE_Param TEE_Result TA_OpenSessionEntryPoint(uint32_t pt, TEE_Param params[TEE_NUM_PARAMS], void **sess_ctx) { return __ta_open_sess(pt, params, sess_ctx, __GP11_TA_OpenSessionEntryPoint); } TEE_Result TA_InvokeCommandEntryPoint(void *sess_ctx, uint32_t cmd_id, uint32_t pt, TEE_Param params[TEE_NUM_PARAMS]) { return __ta_invoke_cmd(sess_ctx, cmd_id, pt, params, __GP11_TA_InvokeCommandEntryPoint); } #endif optee_os-4.3.0/typedefs.checkpatch000066400000000000000000000013101464416617300172040ustar00rootroot00000000000000# Note: please keep the entries in this file sorted in reverse alphabetical # order (sort -r) TEE_Whence TEE_UUID TEE_Time TEE_TASessionHandle TEE_Session TEE_SESessionHandle TEE_SEServiceHandle TEE_SEReaderProperties TEE_SEReaderHandle TEE_SEChannelHandle TEE_SEAID TEE_Result TEE_PropSetHandle TEE_Param TEE_OperationMode TEE_OperationInfoMultiple TEE_OperationInfoKey TEE_OperationInfo TEE_OperationHandle TEE_ObjectType TEE_ObjectInfo TEE_ObjectHandle TEE_ObjectEnumHandle TEE_Identity TEE_ErrorOrigin TEE_BigIntFMMContext TEE_BigIntFMM TEE_BigInt TEE_Attribute TAILQ_ENTRY\(.*\) STAILQ_HEAD\(.*\) STAILQ_ENTRY\(.*\) SLIST_HEAD\(.*\) SLIST_ENTRY\(.*\) mbedtls_mpi_uint mbedtls_mpi Elf_Phdr Elf_Half Elf_Addr